update code
diff --git a/AMCL.pdf b/AMCL.pdf
deleted file mode 100644
index 9d9ab9a..0000000
--- a/AMCL.pdf
+++ /dev/null
Binary files differ
diff --git a/CMakeLists.txt b/CMakeLists.txt
deleted file mode 100644
index a6fd195..0000000
--- a/CMakeLists.txt
+++ /dev/null
@@ -1,184 +0,0 @@
-cmake_minimum_required (VERSION 2.8)
-project (AMCL)
-enable_testing()
-
-set(AMCL_VERSION_MAJOR "1")
-set(AMCL_VERSION_MINOR "1")
-set(AMCL_VERSION_PATCH "0")
-set(PROJECT_VERSION "${AMCL_VERSION_MAJOR}.${AMCL_VERSION_MINOR}.${AMCL_VERSION_PATCH}")
-message(STATUS "PROJECT_VERSION='${PROJECT_VERSION}'")
-message(STATUS "Generator - ${CMAKE_GENERATOR}")
-
-# Add options for build
-option (BUILD_SHARED_LIBS "Build Shared Libraries" ON)
-option (BUILD_PYTHON "Build Python" ON) 
-option (BUILD_MPIN "Build MPIN" ON) 
-option (BUILD_WCC "Build WCC" OFF) 
-option (BUILD_DOXYGEN "Build Doxygen" ON) 
-option (USE_PATENTS "Use alleged patents" ON)
-option (USE_ANONYMOUS "Anonymous authenticaion for M-Pin Full" OFF)
-
-# Allow the developer to select if Dynamic or Static libraries are built
-# Set the default LIB_TYPE variable to STATIC
-SET (LIB_TYPE STATIC)
-IF (BUILD_SHARED_LIBS)
-  # User wants to build Dynamic Libraries, so change the LIB_TYPE variable to CMake keyword 'SHARED'
-  SET (LIB_TYPE SHARED)
-ENDIF (BUILD_SHARED_LIBS)
-
-if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
-   # Mac OS X specific code
-   set(OS "Mac OS X")
-   # MACOSX_RPATH
-   cmake_policy(SET CMP0042 NEW)
-   set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99")
-endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
-
-if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
-   # Linux specific code
-   set(OS "Linux")
-   set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99")
-endif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
-
-if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
-   # Windows specific code
-   set(OS "Windows")
-endif(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
-
-# Select word length
-set(WORD_LENGTH "32" CACHE STRING "Word length. See amcl.h.in for explanation")
-set(Word_Length_Values "16;32;64")
-set_property(CACHE WORD_LENGTH PROPERTY STRINGS ${Word_Length_Values})
-message(STATUS "WORD_LENGTH='${WORD_LENGTH}'")
-
-# Select Field
-set(FIELD_CHOICE "BNCX" CACHE STRING "Choice of Field. See amcl.h.in for explanation")
-set(Field_Values "BN;BNCX;BNT;BNT2;NIST;C25519;BRAINPOOL;ANSSI;MF254;MS255;MF256;MS256")
-set_property(CACHE FIELD_CHOICE PROPERTY STRINGS ${Field_Values})
-message(STATUS "FIELD_CHOICE='${FIELD_CHOICE}'")
-
-# Select Curve type
-set(CURVE_TYPE "WEIERSTRASS" CACHE STRING "Choice of Curve. See amcl.h.in for explanation")
-set(Curve_Values "WEIERSTRASS;EDWARDS;MONTGOMERY")
-set_property(CACHE CURVE_TYPE PROPERTY STRINGS ${Curve_Values})
-message(STATUS "CURVE_TYPE='${CURVE_TYPE}'")
-
-# configure amcl header file to pass CMake settings
-# to the source code
-configure_file (
-  "${PROJECT_SOURCE_DIR}/c/amcl.h.in"
-  "${PROJECT_BINARY_DIR}/c/amcl.h"
-  )
-
-if(NOT(FIELD_CHOICE MATCHES "BN"))
-  message(STATUS "Field choice prevents MPIN being built")
-  set(BUILD_MPIN OFF)
-  set(BUILD_WSS OFF)
-endif(NOT(FIELD_CHOICE MATCHES "BN"))
-
-# test configuration
-if(BUILD_MPIN OR BUILD_WCC)
-  set(MPIN_TIME_PERMIT_TESTS 10 CACHE STRING "Number of days in the future to test M-PIN time permits")
-  set(MPIN_RANDOM_TESTS 10 CACHE STRING "Number of random M-PIN tests")
-  message(STATUS "MPIN_TIME_PERMIT_TESTS=${MPIN_TIME_PERMIT_TESTS}")
-  message(STATUS "MPIN_RANDOM_TESTS=${MPIN_RANDOM_TESTS}")
-  # Configure test variables
-  configure_file (
-    "${PROJECT_SOURCE_DIR}/c/tests/config.h.in"
-    "${PROJECT_BINARY_DIR}/c/tests/config.h"
-  )
-endif(BUILD_MPIN OR BUILD_WCC)
-
-# Set a default build type if none was specified
-if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
-  message(STATUS "Setting build type to 'Release' as none was specified.")
-  set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE)
-  # Set the possible values of build type for cmake-gui
-  set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
-endif()
-
-# Add subdirectories
-add_subdirectory (c)
-
-# Only build Python for shared libs
-if (NOT BUILD_SHARED_LIBS)
-  set(BUILD_PYTHON OFF)
-endif (NOT BUILD_SHARED_LIBS)
-
-if (BUILD_PYTHON)
-  message(STATUS "Build Python CFFI")
-  execute_process (COMMAND python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()" OUTPUT_VARIABLE PYTHON_SITE_PACKAGES OUTPUT_STRIP_TRAILING_WHITESPACE)
-  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 OUTPUT_STRIP_TRAILING_WHITESPACE)
-
-  if((FIELD_CHOICE STREQUAL "BNCX") AND BUILD_MPIN)
-    file(COPY "${PROJECT_SOURCE_DIR}/testVectors/mpin/BNCX.json" DESTINATION "${PROJECT_BINARY_DIR}/pythonCFFI")
-    file(RENAME "${PROJECT_BINARY_DIR}/pythonCFFI/BNCX.json" "${PROJECT_BINARY_DIR}/pythonCFFI/MPINTestVectors.json")
-  endif((FIELD_CHOICE STREQUAL "BNCX") AND BUILD_MPIN)
-  add_subdirectory (pythonCFFI)
-endif (BUILD_PYTHON)
-
-# Build Documentation
-if (BUILD_DOXYGEN)
-  find_package(Doxygen QUIET)
-  if(DOXYGEN_FOUND)
-    add_subdirectory (docs)
-  else(DOXYGEN_FOUND)
-    message(STATUS "Doxygen not found. Documentation will not be built.")
-  endif(DOXYGEN_FOUND)
-endif (BUILD_DOXYGEN)
-
-message(STATUS "Install ${CMAKE_INSTALL_PREFIX}")
-
-# uninstall target
-configure_file(
-    "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
-    "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
-    IMMEDIATE @ONLY)
-
-add_custom_target(uninstall
-    COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
-
-# Build a CPack driven installer package
-include (InstallRequiredSystemLibraries)
-set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
-set(CPACK_PACKAGE_VERSION "${AMCL_VERSION_MAJOR}.${AMCL_VERSION_MINOR}.${AMCL_VERSION_PATCH}")
-set(CPACK_PACKAGE_NAME "AMCL")
-set(CPACK_PACKAGE_RELEASE 1)
-set(CPACK_PACKAGE_CONTACT "support@miracl.com")
-set(CPACK_PACKAGE_VENDOR "MIRACL")
-if (BUILD_PYTHON)
-  set(CPACK_RPM_PACKAGE_REQUIRES "python >= 2.7.0")
-endif (BUILD_PYTHON)
-set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${CPACK_PACKAGE_RELEASE}.${CMAKE_SYSTEM_PROCESSOR}")
-
-if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
-  # Linux specific code
-  set(CPACK_PACKAGING_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX})
-  # Prevents CPack from generating file conflicts
-  set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "${CPACK_PACKAGING_INSTALL_PREFIX}")
-  list(APPEND CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "${CPACK_PACKAGING_INSTALL_PREFIX}/bin")
-  list(APPEND CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "${CPACK_PACKAGING_INSTALL_PREFIX}/include")
-  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}")
-  set(CPACK_GENERATOR "RPM")
-endif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
-
-if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
-  # Windows specific code
-  set(CPACK_PACKAGE_INSTALL_DIRECTORY "AMCL")
-  set(CPACK_NSIS_MODIFY_PATH ON)
-  set(CPACK_PACKAGE_ICON "${CMAKE_SOURCE_DIR}/data\\\\icon.bmp")
-  set(CPACK_NSIS_MUI_ICON "${CMAKE_SOURCE_DIR}/data\\\\icon.ico")
-  set(CPACK_NSIS_MUI_UNIICON "${CMAKE_SOURCE_DIR}/data\\\\icon.ico")
-  set(CPACK_NSIS_HELP_LINK "http:\\\\\\\\www.miracl.com")
-  set(CPACK_NSIS_URL_INFO_ABOUT "http:\\\\\\\\www.miracl.com")
-  set(CPACK_NSIS_CONTACT "support@miracl.com")
-endif(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
-
-if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
-  # Mac OS X specific code
-endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
-
-include (CPack)
-
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index 19efef5..0000000
--- a/LICENSE
+++ /dev/null
@@ -1,202 +0,0 @@
-
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
-   APPENDIX: How to apply the Apache License to your work.
-
-      To apply the Apache License to your work, attach the following
-      boilerplate notice, with the fields enclosed by brackets "[]"
-      replaced with your own identifying information. (Don't include
-      the brackets!)  The text should be enclosed in the appropriate
-      comment syntax for the file format. We also recommend that a
-      file or class name and description of purpose be included on the
-      same "printed page" as the copyright notice for easier
-      identification within third-party archives.
-
-   Copyright 2016 MIRACL UK Ltd
-
-   Licensed 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.
diff --git a/LICENSE-2.0.TXT b/LICENSE-2.0.TXT
new file mode 100644
index 0000000..9b5e401
--- /dev/null
+++ b/LICENSE-2.0.TXT
@@ -0,0 +1,202 @@
+

+                                 Apache License

+                           Version 2.0, January 2004

+                        http://www.apache.org/licenses/

+

+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

+

+   1. Definitions.

+

+      "License" shall mean the terms and conditions for use, reproduction,

+      and distribution as defined by Sections 1 through 9 of this document.

+

+      "Licensor" shall mean the copyright owner or entity authorized by

+      the copyright owner that is granting the License.

+

+      "Legal Entity" shall mean the union of the acting entity and all

+      other entities that control, are controlled by, or are under common

+      control with that entity. For the purposes of this definition,

+      "control" means (i) the power, direct or indirect, to cause the

+      direction or management of such entity, whether by contract or

+      otherwise, or (ii) ownership of fifty percent (50%) or more of the

+      outstanding shares, or (iii) beneficial ownership of such entity.

+

+      "You" (or "Your") shall mean an individual or Legal Entity

+      exercising permissions granted by this License.

+

+      "Source" form shall mean the preferred form for making modifications,

+      including but not limited to software source code, documentation

+      source, and configuration files.

+

+      "Object" form shall mean any form resulting from mechanical

+      transformation or translation of a Source form, including but

+      not limited to compiled object code, generated documentation,

+      and conversions to other media types.

+

+      "Work" shall mean the work of authorship, whether in Source or

+      Object form, made available under the License, as indicated by a

+      copyright notice that is included in or attached to the work

+      (an example is provided in the Appendix below).

+

+      "Derivative Works" shall mean any work, whether in Source or Object

+      form, that is based on (or derived from) the Work and for which the

+      editorial revisions, annotations, elaborations, or other modifications

+      represent, as a whole, an original work of authorship. For the purposes

+      of this License, Derivative Works shall not include works that remain

+      separable from, or merely link (or bind by name) to the interfaces of,

+      the Work and Derivative Works thereof.

+

+      "Contribution" shall mean any work of authorship, including

+      the original version of the Work and any modifications or additions

+      to that Work or Derivative Works thereof, that is intentionally

+      submitted to Licensor for inclusion in the Work by the copyright owner

+      or by an individual or Legal Entity authorized to submit on behalf of

+      the copyright owner. For the purposes of this definition, "submitted"

+      means any form of electronic, verbal, or written communication sent

+      to the Licensor or its representatives, including but not limited to

+      communication on electronic mailing lists, source code control systems,

+      and issue tracking systems that are managed by, or on behalf of, the

+      Licensor for the purpose of discussing and improving the Work, but

+      excluding communication that is conspicuously marked or otherwise

+      designated in writing by the copyright owner as "Not a Contribution."

+

+      "Contributor" shall mean Licensor and any individual or Legal Entity

+      on behalf of whom a Contribution has been received by Licensor and

+      subsequently incorporated within the Work.

+

+   2. Grant of Copyright License. Subject to the terms and conditions of

+      this License, each Contributor hereby grants to You a perpetual,

+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable

+      copyright license to reproduce, prepare Derivative Works of,

+      publicly display, publicly perform, sublicense, and distribute the

+      Work and such Derivative Works in Source or Object form.

+

+   3. Grant of Patent License. Subject to the terms and conditions of

+      this License, each Contributor hereby grants to You a perpetual,

+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable

+      (except as stated in this section) patent license to make, have made,

+      use, offer to sell, sell, import, and otherwise transfer the Work,

+      where such license applies only to those patent claims licensable

+      by such Contributor that are necessarily infringed by their

+      Contribution(s) alone or by combination of their Contribution(s)

+      with the Work to which such Contribution(s) was submitted. If You

+      institute patent litigation against any entity (including a

+      cross-claim or counterclaim in a lawsuit) alleging that the Work

+      or a Contribution incorporated within the Work constitutes direct

+      or contributory patent infringement, then any patent licenses

+      granted to You under this License for that Work shall terminate

+      as of the date such litigation is filed.

+

+   4. Redistribution. You may reproduce and distribute copies of the

+      Work or Derivative Works thereof in any medium, with or without

+      modifications, and in Source or Object form, provided that You

+      meet the following conditions:

+

+      (a) You must give any other recipients of the Work or

+          Derivative Works a copy of this License; and

+

+      (b) You must cause any modified files to carry prominent notices

+          stating that You changed the files; and

+

+      (c) You must retain, in the Source form of any Derivative Works

+          that You distribute, all copyright, patent, trademark, and

+          attribution notices from the Source form of the Work,

+          excluding those notices that do not pertain to any part of

+          the Derivative Works; and

+

+      (d) If the Work includes a "NOTICE" text file as part of its

+          distribution, then any Derivative Works that You distribute must

+          include a readable copy of the attribution notices contained

+          within such NOTICE file, excluding those notices that do not

+          pertain to any part of the Derivative Works, in at least one

+          of the following places: within a NOTICE text file distributed

+          as part of the Derivative Works; within the Source form or

+          documentation, if provided along with the Derivative Works; or,

+          within a display generated by the Derivative Works, if and

+          wherever such third-party notices normally appear. The contents

+          of the NOTICE file are for informational purposes only and

+          do not modify the License. You may add Your own attribution

+          notices within Derivative Works that You distribute, alongside

+          or as an addendum to the NOTICE text from the Work, provided

+          that such additional attribution notices cannot be construed

+          as modifying the License.

+

+      You may add Your own copyright statement to Your modifications and

+      may provide additional or different license terms and conditions

+      for use, reproduction, or distribution of Your modifications, or

+      for any such Derivative Works as a whole, provided Your use,

+      reproduction, and distribution of the Work otherwise complies with

+      the conditions stated in this License.

+

+   5. Submission of Contributions. Unless You explicitly state otherwise,

+      any Contribution intentionally submitted for inclusion in the Work

+      by You to the Licensor shall be under the terms and conditions of

+      this License, without any additional terms or conditions.

+      Notwithstanding the above, nothing herein shall supersede or modify

+      the terms of any separate license agreement you may have executed

+      with Licensor regarding such Contributions.

+

+   6. Trademarks. This License does not grant permission to use the trade

+      names, trademarks, service marks, or product names of the Licensor,

+      except as required for reasonable and customary use in describing the

+      origin of the Work and reproducing the content of the NOTICE file.

+

+   7. Disclaimer of Warranty. Unless required by applicable law or

+      agreed to in writing, Licensor provides the Work (and each

+      Contributor provides its Contributions) on an "AS IS" BASIS,

+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or

+      implied, including, without limitation, any warranties or conditions

+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A

+      PARTICULAR PURPOSE. You are solely responsible for determining the

+      appropriateness of using or redistributing the Work and assume any

+      risks associated with Your exercise of permissions under this License.

+

+   8. Limitation of Liability. In no event and under no legal theory,

+      whether in tort (including negligence), contract, or otherwise,

+      unless required by applicable law (such as deliberate and grossly

+      negligent acts) or agreed to in writing, shall any Contributor be

+      liable to You for damages, including any direct, indirect, special,

+      incidental, or consequential damages of any character arising as a

+      result of this License or out of the use or inability to use the

+      Work (including but not limited to damages for loss of goodwill,

+      work stoppage, computer failure or malfunction, or any and all

+      other commercial damages or losses), even if such Contributor

+      has been advised of the possibility of such damages.

+

+   9. Accepting Warranty or Additional Liability. While redistributing

+      the Work or Derivative Works thereof, You may choose to offer,

+      and charge a fee for, acceptance of support, warranty, indemnity,

+      or other liability obligations and/or rights consistent with this

+      License. However, in accepting such obligations, You may act only

+      on Your own behalf and on Your sole responsibility, not on behalf

+      of any other Contributor, and only if You agree to indemnify,

+      defend, and hold each Contributor harmless for any liability

+      incurred by, or claims asserted against, such Contributor by reason

+      of your accepting any such warranty or additional liability.

+

+   END OF TERMS AND CONDITIONS

+

+   APPENDIX: How to apply the Apache License to your work.

+

+      To apply the Apache License to your work, attach the following

+      boilerplate notice, with the fields enclosed by brackets "[]"

+      replaced with your own identifying information. (Don't include

+      the brackets!)  The text should be enclosed in the appropriate

+      comment syntax for the file format. We also recommend that a

+      file or class name and description of purpose be included on the

+      same "printed page" as the copyright notice for easier

+      identification within third-party archives.

+

+   Copyright [yyyy] [name of copyright owner]

+

+   Licensed 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.
\ No newline at end of file
diff --git a/NOTICE b/NOTICE
deleted file mode 100644
index 434d2bb..0000000
--- a/NOTICE
+++ /dev/null
@@ -1,5 +0,0 @@
-Apache Milagro Crypto Libraries
-Copyright 2016 The Apache Software Foundation
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
diff --git a/NOTICE.txt b/NOTICE.txt
new file mode 100644
index 0000000..2e6c028
--- /dev/null
+++ b/NOTICE.txt
@@ -0,0 +1,5 @@
+Apache Milagro Crypto Libraries

+Copyright 2016 The Apache Software Foundation

+

+This product includes software developed at

+The Apache Software Foundation (http://www.apache.org/).

diff --git a/README.md b/README.md
deleted file mode 100644
index 7282e43..0000000
--- a/README.md
+++ /dev/null
@@ -1,42 +0,0 @@
-<h2>AMCL</h2>
-
-<p>This directory contains the source code for the AMCL Library.</p>
-
-<p>The directory structure is as follows</p>
-
-<dl>
-  <dt>./c</dt>
-  <dd>- C Source code</dd>
-  <dt>./js</dt>
-  <dd>- JavaScript code</dd>
-  <dt>./java</dt>
-  <dd>- JAVA code</dd>
-  <dt>./java64</dt>
-  <dd>- JAVA code optimal for a 64-bit Virtual Machine</dd>
-  <dt>./go</dt>
-  <dd>- GO code</dd>
-  <dt>./swift</dt>
-  <dd>- swift code</dd>
-  <dt>./cs</dt>
-  <dd>- C# code</dd>
-  <dt>./pythonCFFI</dt>
-  <dd>- Python code that accesses the C library via the CFFI module</dd>
-  <dt>./testVectors</dt>
-  <dd>- Test Vectors</dd>
-  <dt>./docs</dt>
-  <dd>- Documentation</dd>
-</dl>
-
-<h2>Build Instructions</h2>
-
-<p>AMCL is a standards compliant C library with no external dependencies. It
-can be built using the <a href="http://www.cmake.org">CMake</a> build system.
-In order to use the  Python wrappers <a href="https://cffi.readthedocs.org/en/release-0.8/">CFFI</a> is also
-required. There are instructions provided for both Linux and Windows based systems.</p>
-
-<p>Instructions for the Linux build are in ./linux.md</p>
-
-<p>Instructions for the Mac OS build are in ./mac.md</p>
-
-<p>Instructions for the Windows build are in ./windows.md</p>
-
diff --git a/bigtobig.cpp b/bigtobig.cpp
deleted file mode 100755
index 730b790..0000000
--- a/bigtobig.cpp
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
-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.
-*/
-
-//
-// Program to convert from Big to AMCL BIG format
-// cl /O2 bigtobig.cpp big.cpp miracl.lib
-// gcc -O2 bigtobig.cpp big.cpp miracl.a -o bigtobig
-//
-//
-
-#include <iostream>
-#include "zzn.h"
-
-using namespace std;
-
-Miracl precision=100;
-
-// Code to parse formula in command line
-// This code isn't mine, but its public domain
-// Shamefully I forget the source
-//
-// NOTE: It may be necessary on some platforms to change the operators * and #
-//
-
-#if defined(unix)
-#define TIMES '.'
-#define RAISE '^'
-#else
-#define TIMES '*'
-#define RAISE '#'
-#endif
-
-Big tt;
-static char *ss;
-
-void eval_power (Big& oldn,Big& n,char op)
-{
-        if (op) n=pow(oldn,toint(n));    // power(oldn,size(n),n,n);
-}
-
-void eval_product (Big& oldn,Big& n,char op)
-{
-        switch (op)
-        {
-        case TIMES:
-                n*=oldn;
-                break;
-        case '/':
-                n=oldn/n;
-                break;
-        case '%':
-                n=oldn%n;
-        }
-}
-
-void eval_sum (Big& oldn,Big& n,char op)
-{
-        switch (op)
-        {
-        case '+':
-                n+=oldn;
-                break;
-        case '-':
-                n=oldn-n;
-        }
-}
-
-void eval (void)
-{
-        Big oldn[3];
-        Big n;
-        int i;
-        char oldop[3];
-        char op;
-        char minus;
-        for (i=0;i<3;i++)
-        {
-            oldop[i]=0;
-        }
-LOOP:
-        while (*ss==' ')
-        ss++;
-        if (*ss=='-')    /* Unary minus */
-        {
-        ss++;
-        minus=1;
-        }
-        else
-        minus=0;
-        while (*ss==' ')
-        ss++;
-        if (*ss=='(' || *ss=='[' || *ss=='{')    /* Number is subexpression */
-        {
-        ss++;
-        eval ();
-        n=tt;
-        }
-        else            /* Number is decimal value */
-        {
-        for (i=0;ss[i]>='0' && ss[i]<='9';i++)
-                ;
-        if (!i)         /* No digits found */
-        {
-                cout <<  "Error - invalid number" << endl;
-                exit (20);
-        }
-        op=ss[i];
-        ss[i]=0;
-        n=atoi(ss);
-        ss+=i;
-        *ss=op;
-        }
-        if (minus) n=-n;
-        do
-        op=*ss++;
-        while (op==' ');
-        if (op==0 || op==')' || op==']' || op=='}')
-        {
-        eval_power (oldn[2],n,oldop[2]);
-        eval_product (oldn[1],n,oldop[1]);
-        eval_sum (oldn[0],n,oldop[0]);
-        tt=n;
-        return;
-        }
-        else
-        {
-        if (op==RAISE)
-        {
-                eval_power (oldn[2],n,oldop[2]);
-                oldn[2]=n;
-                oldop[2]=RAISE;
-        }
-        else
-        {
-                if (op==TIMES || op=='/' || op=='%')
-                {
-                eval_power (oldn[2],n,oldop[2]);
-                oldop[2]=0;
-                eval_product (oldn[1],n,oldop[1]);
-                oldn[1]=n;
-                oldop[1]=op;
-                }
-                else
-                {
-                if (op=='+' || op=='-')
-                {
-                        eval_power (oldn[2],n,oldop[2]);
-                        oldop[2]=0;
-                        eval_product (oldn[1],n,oldop[1]);
-                        oldop[1]=0;
-                        eval_sum (oldn[0],n,oldop[0]);
-                        oldn[0]=n;
-                        oldop[0]=op;
-                }
-                else    /* Error - invalid operator */
-                {
-                        cout <<  "Error - invalid operator" << endl;
-                        exit (20);
-                }
-                }
-        }
-        }
-        goto LOOP;
-}
-
-void output(int w,Big t,Big m)
-{
-	Big y=t;
-
-	for (int i=0;i<w;i++)
-	{
-		cout << "0x" << y%m ;
-		if (i<w-1) cout << ",";
-		y/=m;
-	}
-	cout << endl;
-}
-
-int main(int argc, char **argv)
-{
-    int i,ip,chunk,basebits;
-    Big n,m;
-    BOOL gotP,gotA,gotB;
-    int Base;
-    miracl *mip=&precision;
-    argv++; argc--;
-    if (argc<1)
-    {
-        cout << "Program converts from Big to BIG" << endl;
-        cout << "bigtobig <big number> <chunk>> <basebits>" << endl;
-        cout << "OR" << endl;
-        cout << "bigtobig <formula for big number> <chunk>> <basebits>" << endl;
-#if defined(unix)
-        cout << "e.g. bigtobig -f 2^255-19 32 29" << endl;
-#else
-        cout << "e.g. bigtobig -f 2#255-19 32 29" << endl;
-#endif
-        cout << "To input Big number in Hex, precede with -h" << endl;
-        return 0;
-    }
-
-    ip=0;
-    gprime(1000);
-    gotP=gotA=gotB=FALSE;
-    n=0;
-    Base=10;
-    while (ip<argc)
-    {
-        if (!gotP && strcmp(argv[ip],"-f")==0)
-        {
-            ip++;
-            if (!gotP && ip<argc)
-            {
-
-                ss=argv[ip++];
-                tt=0;
-                eval();
-                n=tt;
-                gotP=TRUE;
-                continue;
-            }
-            else
-            {
-                cout << "Error in command line" << endl;
-                return 0;
-            }
-        }
-
-
-        if (strcmp(argv[ip],"-h")==0)
-        {
-            ip++;
-            Base=16;
-            continue;
-        }
-
-        if (!gotP)
-        {
-            mip->IOBASE=Base;
-            n=argv[ip++];
-            mip->IOBASE=10;
-            gotP=TRUE;
-            continue;
-        }
-        if (!gotA)
-        {
-            mip->IOBASE=Base;
-            chunk=atoi(argv[ip++]);
-            gotA=TRUE;
-            continue;
-        }
-        if (!gotB)
-        {
-            mip->IOBASE=Base;
-            basebits=atoi(argv[ip++]);
-            gotB=TRUE;
-            continue;
-        }
-        cout << "Error in command line" << endl;
-        return 0;
-    }
-    if (!gotP || !gotA || !gotB)
-    {
-        cout << "Error in command line" << endl;
-        return 0;
-    }
-
-	mip->IOBASE=16;
-
-	m=pow((Big)2,basebits);
-
-	output(1+bits(n)/basebits,n,m);
-
-    return 0;
-}
-
diff --git a/bngen.cpp b/bngen.cpp
deleted file mode 100755
index f59d6f8..0000000
--- a/bngen.cpp
+++ /dev/null
@@ -1,511 +0,0 @@
-/*
-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.
-*/
-
-/* BNGEN - Helper MIRACL program to generate constants for BN curve
-
-(MINGW build)
-
-g++ -O3 bngen.cpp big.cpp zzn.cpp zzn2.cpp ecn2.cpp miracl.a -o bngen.exe
-
-This ONLY works for D-type curves of the form y^2=x^3+2, with a negative x parameter, and x=3 mod 4
-
-*/
-
-#include <iostream>
-#include "big.h"
-#include "zzn2.h"
-#include "ecn2.h"
-
-using namespace std;
-
-Miracl precision(20,0);
-
-
-/* set d=0 for c, d=1 to include leading zeros, d=2 for JS-type square brackets, d=3 for L (for long) appended */
-void output(int d,int w,Big t,Big m)
-{
-	Big y=t;
-
-	if (d!=2) cout << "{";
-	else cout << "[";
-	for (int i=0;i<w;i++)
-	{
-		cout << "0x" << y%m;
-		y/=m;
-		if ((y==0 && (d==0 || d==2)) || i==w-1) break;
-		if (d==3) cout << "L,";
-		else cout << ",";
-	}
-	if (d!=2)
-	{
-		if (d==3) cout << "L}";
-		else cout << "}";
-	}
-	else cout << "]";
-}
-
-
-void q_power_frobenius(ECn2 &A,ZZn2 &F)
-{
-// Fast multiplication of A by q (for Trace-Zero group members only)
-    ZZn2 x,y,z,w,r;
-
-    A.get(x,y);
-
-	w=F*F;
-	r=F;
-
-	if (get_mip()->TWIST==MR_SEXTIC_M) r=inverse(F);  // could be precalculated
-	if (get_mip()->TWIST==MR_SEXTIC_D) r=F;
-
-	w=r*r;
-	x=w*conj(x);
-	y=r*w*conj(y);
-
-    A.set(x,y);
-}
-
-//
-// Faster Hashing to G2 - Fuentes-Castaneda, Knapp and Rodriguez-Henriquez
-//
-
-void cofactor(ECn2& S,ZZn2 &F,Big& x)
-{
-	ECn2 T,K;
-	T=S;
-	T*=-x;
-	T.norm();
-	K=(T+T)+T;
-	K.norm();
-	q_power_frobenius(K,F);
-	q_power_frobenius(S,F); q_power_frobenius(S,F); q_power_frobenius(S,F);
-	S+=T; S+=K;
-	q_power_frobenius(T,F); q_power_frobenius(T,F);
-	S+=T;
-	S.norm();
-}
-
-
-void set_frobenius_constant(ZZn2 &X)
-{
-    Big p=get_modulus();
-    switch (get_mip()->pmod8)
-    {
-    case 5:
-         X.set((Big)0,(Big)1); // = (sqrt(-2)^(p-1)/2
-         break;
-    case 3:                    // = (1+sqrt(-1))^(p-1)/2
-         X.set((Big)1,(Big)1);
-         break;
-   case 7:
-         X.set((Big)2,(Big)1); // = (2+sqrt(-1))^(p-1)/2
-    default: break;
-    }
-    X=pow(X,(p-1)/6);
-}
-
-int main()
-{
-	miracl *mip=&precision;
-	Big p,q,R,cru;
-	Big m,x,y,w,t,c,n,r,a,b,gx,gy,D,xa,xb,ya,yb;
-	ZZn2 X;
-	ECn2 Q;
-	ZZn2 Xa,Ya;
-	int i;
-	int CHUNK[4]={16,32,64,32};
-	int WORDS[4]={20,9,5,11};//{20,9,5};
-	int BITS[4]={13,29,56,24};//{13,29,56};
-
-	mip->IOBASE=16;
-
-/* Set BN value x which determines curve - note that x is assumed to be negative */
-
-//  x=(char *)"6000000000101041";    // for full 256-bit GT_STRONG parameter
-//	x=(char *)"4080000000000001";    // Fast but not not GT_STRONG parameter
-
-	x=(char *)"4000020100608205"; // G2 and GT-Strong parameter
-	x=(char *)"4000000003C012B1";    // MIRACL's GT_STRONG parameter
-	x=(char *)"4080000000000001";    // Nogami's fast parameter
-	x=(char *)"4000806000004081";    // Best GT_STRONG parameter
-
-	p=36*pow(x,4)-36*pow(x,3)+24*x*x-6*x+1;
-    ecurve((Big)0,(Big)2,p,MR_AFFINE);
-    mip->TWIST=MR_SEXTIC_D;
-
-	cout << "/* AMCL - ROM  C file for BN curve - Weierstrass Only */" << endl << endl;
-
-	cout << "#define MBITS " << bits(p) << endl;
-	cout << "#define MOD8 " << p%8 << endl;
-	cout << endl;
-	cout << "const int CURVE_A=0;" << endl;
-	for (i=0;i<3;i++)
-	{
-		cout << "#if CHUNK==" << CHUNK[i] << endl << endl;
-		m=pow((Big)2,BITS[i]);
-
-
-		cout << "const chunk MConst=0x" << inverse(m-p%m,m) << ";" << endl;
-
-		cout << "const BIG Modulus="; output(0,WORDS[i],p,m); cout << ";" << endl;
-		t=6*x*x+1;
-		q=p+1-t;
-		cout << "const BIG CURVE_Order="; output(0,WORDS[i],q,m); cout << ";" << endl;
-		cout << "const BIG CURVE_B={0x2};" << endl;
-
-		R=pow((Big)2,WORDS[i]*BITS[i]);
-	//	cout << "const BIG Monty=";output(0,WORDS[i],inverse(R,p),m); cout << ";" << endl;
-
-		cout << "const BIG CURVE_Bnx="; output(0,WORDS[i],x,m); cout << ";" << endl;
-
-		cru=(18*pow(x,3)-18*x*x+9*x-2);
-		cout << "const BIG CURVE_Cru="; output(0,WORDS[i],cru,m); cout << ";" << endl;
-
-		set_frobenius_constant(X);
-
-		X.get(a,b);
-		cout << "const BIG CURVE_Fra="; output(0,WORDS[i],a,m); cout << ";" << endl;
-		cout << "const BIG CURVE_Frb="; output(0,WORDS[i],b,m); cout << ";" << endl;
-
-		Xa.set((ZZn)0,(ZZn)-1);
-		Ya.set((ZZn)1,ZZn(0));
-		Q.set(Xa,Ya);
-
-		cofactor(Q,X,x);
-
-		Q.get(Xa,Ya);
-		Xa.get(a,b);
-		cout << "const BIG CURVE_Pxa="; output(0,WORDS[i],a,m); cout << ";" << endl;
-		cout << "const BIG CURVE_Pxb="; output(0,WORDS[i],b,m); cout << ";" << endl;
-		Ya.get(a,b);
-		cout << "const BIG CURVE_Pya="; output(0,WORDS[i],a,m); cout << ";" << endl;
-		cout << "const BIG CURVE_Pyb="; output(0,WORDS[i],b,m); cout << ";" << endl;
-
-//		Q*=q;
-//		cout << "Q= " << Q << endl;
-
-		cout << "const BIG CURVE_Gx="; output(0,WORDS[i],p-1,m); cout << ";" << endl;
-		cout << "const BIG CURVE_Gy="; output(0,WORDS[i],(Big)1,m); cout << ";" << endl;
-
-		cout << "const BIG CURVE_W[2]={"; output(0,WORDS[i],6*x*x-4*x+1,m);cout << ","; output(0,WORDS[i],(2*x-1),m); cout << "};" << endl;
-		cout << "const BIG CURVE_SB[2][2]={"; cout << "{"; output(0,WORDS[i],6*x*x-2*x,m); cout << ","; output(0,WORDS[i],(2*x-1),m); cout << "}";cout << ","; cout << "{"; output(0,WORDS[i],(2*x-1),m); cout << ","; output(0,WORDS[i],q-(6*x*x-4*x+1),m); cout << "}"; cout << "};" << endl;
-
-		cout << "const BIG CURVE_WB[4]={"; output(0,WORDS[i],2*x*x-3*x+1,m); cout << ","; output(0,WORDS[i],12*x*x*x-8*x*x+x,m);
-		cout << ","; output(0,WORDS[i],6*x*x*x-4*x*x+x,m); cout << ","; output(0,WORDS[i],2*x*x-x,m); cout << "};" << endl;
-
-		cout << "const BIG CURVE_BB[4][4]={";
-		cout << "{";
-		output(0,WORDS[i],q-x+1,m);
-		cout << ","; output(0,WORDS[i],q-x,m);
-		cout << ","; output(0,WORDS[i],q-x,m);
-		cout << ","; output(0,WORDS[i],2*x,m);
-		cout << "}";
-
-		cout << ","; cout << "{";output(0,WORDS[i],2*x-1,m);
-		cout << ","; output(0,WORDS[i],q-x,m);
-		cout << ","; output(0,WORDS[i],q-x+1,m);
-		cout << ","; output(0,WORDS[i],q-x,m);
-		cout << "}";
-		cout << ","; cout << "{"; output(0,WORDS[i],2*x,m);
-		cout << ","; output(0,WORDS[i],2*x-1,m);
-		cout << ","; output(0,WORDS[i],2*x-1,m);
-		cout << ","; output(0,WORDS[i],2*x-1,m);
-		cout << "}";
-
-		cout << ","; cout << "{"; output(0,WORDS[i],x+1,m);
-		cout << ","; output(0,WORDS[i],4*x-2,m);
-		cout << ","; output(0,WORDS[i],q-2*x-1,m);
-		cout << ","; output(0,WORDS[i],x+1,m);
-		cout << "}";
-		cout << "};" << endl;
-
-		cout << "#endif" << endl << endl;
-
-	}
-
-	cout << endl;
-	cout << "Cut here -----------------------------------------------------------" << endl;
-	cout << "/* AMCL - ROM  Java file for 32-bit VM and BN curve - Weierstrass Only */" << endl << endl;
-
-	cout << "public static final int MODBITS= " << bits(p) << ";" << endl;
-	cout << "public static final int MOD8= " << p%8 << ";" << endl;
-	cout << endl;
-	cout << "public static final int MODTYPE=NOT_SPECIAL;" << endl;
-	m=pow((Big)2,BITS[1]);
-
-
-	cout << "public static final int[] Modulus= "; output(1,WORDS[1],p,m); cout << ";" << endl;
-	R=pow((Big)2,WORDS[1]*BITS[1]);
-//	cout << "public static final int[] Monty=";output(1,WORDS[1],inverse(R,p),m); cout << ";" << endl;
-	cout << "public static final int MConst=0x" << inverse(m-p%m,m) << ";" <<  endl;
-	cout << endl;
-	cout << "public static final int CURVETYPE=WEIERSTRASS;" << endl;
-
-
-	cout << "public static final int CURVE_A = 0;" << endl;
-	cout << "public static final int[] CURVE_B = {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};" << endl;
-	t=6*x*x+1;
-	q=p+1-t;
-	cout << "public static final int[] CURVE_Order="; output(1,WORDS[1],q,m); cout << ";" << endl;
-
-
-	cout << "public static final int[] CURVE_Bnx="; output(1,WORDS[1],x,m); cout << ";" << endl;
-
-	cru=(18*pow(x,3)-18*x*x+9*x-2);
-	cout << "public static final int[] CURVE_Cru="; output(1,WORDS[1],cru,m); cout << ";" << endl;
-
-	set_frobenius_constant(X);
-
-	X.get(a,b);
-	cout << "public static final int[] CURVE_Fra="; output(1,WORDS[1],a,m); cout << ";" << endl;
-	cout << "public static final int[] CURVE_Frb="; output(1,WORDS[1],b,m); cout << ";" << endl;
-
-	Xa.set((ZZn)0,(ZZn)-1);
-	Ya.set((ZZn)1,ZZn(0));
-	Q.set(Xa,Ya);
-
-	cofactor(Q,X,x);
-
-	Q.get(Xa,Ya);
-	Xa.get(a,b);
-	cout << "public static final int[] CURVE_Pxa="; output(1,WORDS[1],a,m); cout << ";" << endl;
-	cout << "public static final int[] CURVE_Pxb="; output(1,WORDS[1],b,m); cout << ";" << endl;
-	Ya.get(a,b);
-	cout << "public static final int[] CURVE_Pya="; output(1,WORDS[1],a,m); cout << ";" << endl;
-	cout << "public static final int[] CURVE_Pyb="; output(1,WORDS[1],b,m); cout << ";" << endl;
-
-//		Q*=q;
-//		cout << "Q= " << Q << endl;
-
-	cout << "public static final int[] CURVE_Gx ="; output(1,WORDS[1],p-1,m); cout << ";" << endl;
-	cout << "public static final int[] CURVE_Gy ="; output(1,WORDS[1],(Big)1,m); cout << ";" << endl;
-
-	cout << "public static final int[][] CURVE_W={"; output(1,WORDS[1],6*x*x-4*x+1,m);cout << ","; output(1,WORDS[1],(2*x-1),m); cout << "};" << endl;
-	cout << "public static final int[][][] CURVE_SB={"; cout << "{"; output(1,WORDS[1],6*x*x-2*x,m); cout << ","; output(1,WORDS[1],(2*x-1),m); cout << "}";cout << ","; cout << "{"; output(1,WORDS[1],(2*x-1),m); cout << ","; output(1,WORDS[1],q-(6*x*x-4*x+1),m); cout << "}"; cout << "};" << endl;
-
-	cout << "public static final int[][] CURVE_WB={"; output(1,WORDS[1],2*x*x-3*x+1,m); cout << ","; output(1,WORDS[1],12*x*x*x-8*x*x+x,m);
-	cout << ","; output(1,WORDS[1],6*x*x*x-4*x*x+x,m); cout << ","; output(1,WORDS[1],2*x*x-x,m); cout << "};" << endl;
-
-	cout << "public static final int[][][] CURVE_BB={";
-	cout << "{";
-	output(1,WORDS[1],q-x+1,m);
-	cout << ","; output(1,WORDS[1],q-x,m);
-	cout << ","; output(1,WORDS[1],q-x,m);
-	cout << ","; output(1,WORDS[1],2*x,m);
-	cout << "}";
-
-	cout << ","; cout << "{";output(1,WORDS[1],2*x-1,m);
-	cout << ","; output(1,WORDS[1],q-x,m);
-	cout << ","; output(1,WORDS[1],q-x+1,m);
-	cout << ","; output(1,WORDS[1],q-x,m);
-	cout << "}";
-	cout << ","; cout << "{"; output(1,WORDS[1],2*x,m);
-	cout << ","; output(1,WORDS[1],2*x-1,m);
-	cout << ","; output(1,WORDS[1],2*x-1,m);
-	cout << ","; output(1,WORDS[1],2*x-1,m);
-	cout << "}";
-
-	cout << ","; cout << "{"; output(1,WORDS[1],x+1,m);
-	cout << ","; output(1,WORDS[1],4*x-2,m);
-	cout << ","; output(1,WORDS[1],q-2*x-1,m);
-	cout << ","; output(1,WORDS[1],x+1,m);
-	cout << "}";
-	cout << "};" << endl;
-
-
-	cout << endl;
-	cout << "Cut here -----------------------------------------------------------" << endl;
-	cout << "/* AMCL - ROM  Java file for 64-bit VM and BN curve - Weierstrass Only */" << endl << endl;
-
-	cout << "public static final int MODBITS= " << bits(p) << ";" << endl;
-	cout << "public static final int MOD8= " << p%8 << ";" << endl;
-	cout << endl;
-	cout << "public static final int MODTYPE=NOT_SPECIAL;" << endl;
-	m=pow((Big)2,BITS[2]);
-
-
-	cout << "public static final long[] Modulus= "; output(3,WORDS[2],p,m); cout << ";" << endl;
-	R=pow((Big)2,WORDS[2]*BITS[2]);
-//	cout << "public static final long[] Monty=";output(3,WORDS[2],inverse(R,p),m); cout << ";" << endl;
-	cout << "public static final long MConst=0x" << inverse(m-p%m,m) << "L;" <<  endl;
-	cout << endl;
-	cout << "public static final int CURVETYPE=WEIERSTRASS;" << endl;
-
-
-	cout << "public static final int CURVE_A = 0;" << endl;
-	cout << "public static final long[] CURVE_B = {0x2L,0x0L,0x0L,0x0L,0x0L};" << endl;
-	t=6*x*x+1;
-	q=p+1-t;
-	cout << "public static final long[] CURVE_Order="; output(3,WORDS[2],q,m); cout << ";" << endl;
-
-
-	cout << "public static final long[] CURVE_Bnx="; output(3,WORDS[2],x,m); cout << ";" << endl;
-
-	cru=(18*pow(x,3)-18*x*x+9*x-2);
-	cout << "public static final long[] CURVE_Cru="; output(3,WORDS[2],cru,m); cout << ";" << endl;
-
-	set_frobenius_constant(X);
-
-	X.get(a,b);
-	cout << "public static final long[] CURVE_Fra="; output(3,WORDS[2],a,m); cout << ";" << endl;
-	cout << "public static final long[] CURVE_Frb="; output(3,WORDS[2],b,m); cout << ";" << endl;
-
-	Xa.set((ZZn)0,(ZZn)-1);
-	Ya.set((ZZn)1,ZZn(0));
-	Q.set(Xa,Ya);
-
-	cofactor(Q,X,x);
-
-	Q.get(Xa,Ya);
-	Xa.get(a,b);
-	cout << "public static final long[] CURVE_Pxa="; output(3,WORDS[2],a,m); cout << ";" << endl;
-	cout << "public static final long[] CURVE_Pxb="; output(3,WORDS[2],b,m); cout << ";" << endl;
-	Ya.get(a,b);
-	cout << "public static final long[] CURVE_Pya="; output(3,WORDS[2],a,m); cout << ";" << endl;
-	cout << "public static final long[] CURVE_Pyb="; output(3,WORDS[2],b,m); cout << ";" << endl;
-
-//		Q*=q;
-//		cout << "Q= " << Q << endl;
-
-	cout << "public static final long[] CURVE_Gx ="; output(3,WORDS[2],p-1,m); cout << ";" << endl;
-	cout << "public static final long[] CURVE_Gy ="; output(3,WORDS[2],(Big)1,m); cout << ";" << endl;
-
-	cout << "public static final long[][] CURVE_W={"; output(3,WORDS[2],6*x*x-4*x+1,m);cout << ","; output(3,WORDS[2],(2*x-1),m); cout << "};" << endl;
-	cout << "public static final long[][][] CURVE_SB={"; cout << "{"; output(3,WORDS[2],6*x*x-2*x,m); cout << ","; output(3,WORDS[2],(2*x-1),m); cout << "}";cout << ","; cout << "{"; output(3,WORDS[2],(2*x-1),m); cout << ","; output(3,WORDS[2],q-(6*x*x-4*x+1),m); cout << "}"; cout << "};" << endl;
-
-	cout << "public static final long[][] CURVE_WB={"; output(3,WORDS[2],2*x*x-3*x+1,m); cout << ","; output(3,WORDS[2],12*x*x*x-8*x*x+x,m);
-	cout << ","; output(3,WORDS[2],6*x*x*x-4*x*x+x,m); cout << ","; output(3,WORDS[2],2*x*x-x,m); cout << "};" << endl;
-
-	cout << "public static final long[][][] CURVE_BB={";
-	cout << "{";
-	output(3,WORDS[2],q-x+1,m);
-	cout << ","; output(3,WORDS[2],q-x,m);
-	cout << ","; output(3,WORDS[2],q-x,m);
-	cout << ","; output(3,WORDS[2],2*x,m);
-	cout << "}";
-
-	cout << ","; cout << "{";output(3,WORDS[2],2*x-1,m);
-	cout << ","; output(3,WORDS[2],q-x,m);
-	cout << ","; output(3,WORDS[2],q-x+1,m);
-	cout << ","; output(3,WORDS[2],q-x,m);
-	cout << "}";
-	cout << ","; cout << "{"; output(3,WORDS[2],2*x,m);
-	cout << ","; output(3,WORDS[2],2*x-1,m);
-	cout << ","; output(3,WORDS[2],2*x-1,m);
-	cout << ","; output(3,WORDS[2],2*x-1,m);
-	cout << "}";
-
-	cout << ","; cout << "{"; output(3,WORDS[2],x+1,m);
-	cout << ","; output(3,WORDS[2],4*x-2,m);
-	cout << ","; output(3,WORDS[2],q-2*x-1,m);
-	cout << ","; output(3,WORDS[2],x+1,m);
-	cout << "}";
-	cout << "};" << endl;
-
-
-
-	cout << endl;
-	cout << "Cut here -----------------------------------------------------------" << endl;
-	cout << "/* AMCL - ROM  Javascript file for BN curve - Weierstrass Only */" << endl << endl;
-
-	cout << "MODBITS: " << bits(p) << "," << endl;
-	cout << "MOD8: " << p%8 << "," << endl;
-	cout << endl;
-	cout << "MODTYPE:0," << endl;
-	m=pow((Big)2,BITS[3]);
-
-
-	cout << "Modulus: "; output(2,WORDS[3],p,m); cout << "," << endl;
-	R=pow((Big)2,WORDS[3]*BITS[3]);
-//	cout << "Monty:";output(2,WORDS[3],inverse(R,p),m); cout << "," << endl;
-	cout << "MConst:0x" << inverse(m-p%m,m) << "," <<  endl;
-	cout << endl;
-	cout << "CURVETYPE:0," << endl;
-
-
-	cout << "CURVE_A : 0," << endl;
-	cout << "CURVE_B : [0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]," << endl;
-	t=6*x*x+1;
-	q=p+1-t;
-	cout << "CURVE_Order:"; output(2,WORDS[3],q,m); cout << "," << endl;
-
-
-	cout << "CURVE_Bnx:"; output(2,WORDS[3],x,m); cout << "," << endl;
-
-	cru=(18*pow(x,3)-18*x*x+9*x-2);
-	cout << "CURVE_Cru:"; output(2,WORDS[3],cru,m); cout << "," << endl;
-
-	set_frobenius_constant(X);
-
-	X.get(a,b);
-	cout << "CURVE_Fra:"; output(2,WORDS[3],a,m); cout << "," << endl;
-	cout << "CURVE_Frb:"; output(2,WORDS[3],b,m); cout << "," << endl;
-
-	Xa.set((ZZn)0,(ZZn)-1);
-	Ya.set((ZZn)1,ZZn(0));
-	Q.set(Xa,Ya);
-
-	cofactor(Q,X,x);
-
-	Q.get(Xa,Ya);
-	Xa.get(a,b);
-	cout << "CURVE_Pxa:"; output(2,WORDS[3],a,m); cout << "," << endl;
-	cout << "CURVE_Pxb:"; output(2,WORDS[3],b,m); cout << "," << endl;
-	Ya.get(a,b);
-	cout << "CURVE_Pya:"; output(2,WORDS[3],a,m); cout << "," << endl;
-	cout << "CURVE_Pyb:"; output(2,WORDS[3],b,m); cout << "," << endl;
-
-//		Q*=q;
-//		cout << "Q= " << Q << endl;
-
-	cout << "CURVE_Gx :"; output(2,WORDS[3],p-1,m); cout << "," << endl;
-	cout << "CURVE_Gy :"; output(2,WORDS[3],(Big)1,m); cout << "," << endl;
-
-	cout << "CURVE_W:["; output(2,WORDS[3],6*x*x-4*x+1,m);cout << ","; output(2,WORDS[3],(2*x-1),m); cout << "]," << endl;
-	cout << "CURVE_SB:["; cout << "["; output(2,WORDS[3],6*x*x-2*x,m); cout << ","; output(2,WORDS[3],(2*x-1),m); cout << "]";cout << ","; cout << "["; output(2,WORDS[3],(2*x-1),m); cout << ","; output(2,WORDS[3],q-(6*x*x-4*x+1),m); cout << "]"; cout << "]," << endl;
-
-	cout << "CURVE_WB:["; output(2,WORDS[3],2*x*x-3*x+1,m); cout << ","; output(2,WORDS[3],12*x*x*x-8*x*x+x,m);
-	cout << ","; output(2,WORDS[3],6*x*x*x-4*x*x+x,m); cout << ","; output(2,WORDS[3],2*x*x-x,m); cout << "]," << endl;
-
-	cout << "CURVE_BB:[";
-	cout << "[";
-	output(2,WORDS[3],q-x+1,m);
-	cout << ","; output(2,WORDS[3],q-x,m);
-	cout << ","; output(2,WORDS[3],q-x,m);
-	cout << ","; output(2,WORDS[3],2*x,m);
-	cout << "]";
-
-	cout << ","; cout << "[";output(2,WORDS[3],2*x-1,m);
-	cout << ","; output(2,WORDS[3],q-x,m);
-	cout << ","; output(2,WORDS[3],q-x+1,m);
-	cout << ","; output(2,WORDS[3],q-x,m);
-	cout << "]";
-	cout << ","; cout << "["; output(2,WORDS[3],2*x,m);
-	cout << ","; output(2,WORDS[3],2*x-1,m);
-	cout << ","; output(2,WORDS[3],2*x-1,m);
-	cout << ","; output(2,WORDS[3],2*x-1,m);
-	cout << "]";
-
-	cout << ","; cout << "["; output(2,WORDS[3],x+1,m);
-	cout << ","; output(2,WORDS[3],4*x-2,m);
-	cout << ","; output(2,WORDS[3],q-2*x-1,m);
-	cout << ","; output(2,WORDS[3],x+1,m);
-	cout << "]";
-	cout << "]," << endl;
-}
diff --git a/bower.json b/bower.json
deleted file mode 100644
index 9a388dc..0000000
--- a/bower.json
+++ /dev/null
@@ -1,47 +0,0 @@
-{
-	"name": "clint",
-	"description": "AMCL cryptography js library",
-	"authors": [
-		"MIRACL Crypto Labs."
-	],
-	"main": [
-		"js/DBIG.js",
-		"js/BIG.js",
-		"js/FP.js",
-		"js/ROM.js",
-		"js/HASH.js",
-		"js/RAND.js",
-		"js/AES.js",
-		"js/GPM.js",
-		"js/ECP.js",
-		"js/FP2.js",
-		"js/ECP2.js",
-		"js/FP4.js",
-		"js/FP12.js",
-		"js/PAIR.js",
-		"js/MPIN.js",
-		"js/MPINAuth.js"
-	],
-	"ignore": [
-		"**/.*",
-		"c",
-		"data",
-		"docs",
-		"java",
-		"java64",
-		"pythonCFFI",
-		"swift",
-		"testVectors",
-		"*.*",
-		"!*.json",
-		"js/tests",
-		"js/*.html",
-		"js/*.txt"
-	],
-	"keywords": [
-		"JS",
-		"front-end",
-		"AMCL"
-	],
-	"homepage": "http://miracl.com"
-}
diff --git a/c/CMakeLists.txt b/c/CMakeLists.txt
deleted file mode 100644
index 663adbd..0000000
--- a/c/CMakeLists.txt
+++ /dev/null
@@ -1,291 +0,0 @@
-# Create AMCL library and examples
-
-# add the binary tree directory to the search path for include files and linking
-include_directories( ${CMAKE_CURRENT_BINARY_DIR} )
-link_directories( ${CMAKE_CURRENT_BINARY_DIR} )
-
-# post build: mv amcl_.h amcl.h
-if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/amcl.h")
-  file(RENAME amcl.h amcl_.h)
-endif()
-file(COPY DLLDefines.h DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
-
-set(SOURCES_AMCL
-big.c
-fp.c
-ecp.c
-hash.c
-rand.c
-aes.c
-gcm.c
-oct.c
-rom.c
-fp2.c
-ecp2.c
-fp4.c
-fp12.c
-ff.c)
-
-# Build AMCL
-add_library(amcl ${LIB_TYPE} ${SOURCES_AMCL} version.c)
-
-if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
-  if(BUILD_SHARED_LIBS)
-    message(STATUS "Build shared libs")
-    target_link_libraries (amcl libm.so) 
-  else()
-    message(STATUS "Build static libs")
-    target_link_libraries (amcl libm.a) 
-  endif(BUILD_SHARED_LIBS)
-endif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
-
-# Build libmpin
-if(BUILD_MPIN)
-  add_library(mpin ${LIB_TYPE} pair.c mpin.c utils.c)
-  target_link_libraries (mpin amcl) 
-  add_executable (testmpin testmpin.c)
-  target_link_libraries (testmpin mpin) 
-endif(BUILD_MPIN)
-
-# Build libwcc
-if(BUILD_WCC)
-  message(STATUS "Build WCC")
-  add_library(wcc ${LIB_TYPE} pair.c wcc.c utils.c)
-  target_link_libraries (wcc amcl) 
-  add_executable (testwcc testwcc.c)
-  add_executable (testwcc_tp testwcc_tp.c)
-  add_executable (testwcc_dta testwcc_dta.c)
-  target_link_libraries (testwcc wcc) 
-  target_link_libraries (testwcc_tp wcc) 
-  target_link_libraries (testwcc_dta wcc) 
-endif(BUILD_WCC)
-
-# Copy built libs to c/tests which allows testing without
-# having to install the libs.
-if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
-    message(STATUS "Copy libamcl.dll to c/tests for testing")
-    add_custom_command(
-                TARGET amcl
-                POST_BUILD
-                COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/libamcl.dll" "${PROJECT_BINARY_DIR}/c/tests/")
-
-    if(BUILD_MPIN)
-      message(STATUS "Copy libmpin.dll to c/tests for testing")
-      add_custom_command(
-                  TARGET mpin
-                  POST_BUILD
-                  COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/libmpin.dll" "${PROJECT_BINARY_DIR}/c/tests/")
-    endif(BUILD_MPIN)
-
-    if(BUILD_WCC)
-      message(STATUS "Copy libwcc.dll to c/tests for testing")
-      add_custom_command(
-                  TARGET wcc
-                  POST_BUILD
-                  COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/libwcc.dll" "${PROJECT_BINARY_DIR}/c/tests/")
-    endif(BUILD_WCC)
-
-endif(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
-
-# Copy built libs to pythonCFFI which allows testing without
-# having to install the libs.
-if (BUILD_PYTHON AND BUILD_SHARED_LIBS)
-
-  if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
-
-    if(BUILD_MPIN)
-      message(STATUS "Copy libmpin.so to pythonCFFI for testing")
-      add_custom_command(
-                  TARGET mpin
-                  POST_BUILD
-                  COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/libmpin.so" "${PROJECT_BINARY_DIR}/pythonCFFI/")
-    endif(BUILD_MPIN)
-
-    if(BUILD_WCC)
-      message(STATUS "Copy libwcc.so to pythonCFFI for testing")
-      add_custom_command(
-                  TARGET wcc
-                  POST_BUILD
-                  COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/libwcc.so" "${PROJECT_BINARY_DIR}/pythonCFFI/")
-    endif(BUILD_WCC)  
-
-  endif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
-
-  if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
-    message(STATUS "Copy libamcl.dll to pythonCFFI for testing")
-    add_custom_command(
-                TARGET amcl
-                POST_BUILD
-                COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/libamcl.dll" "${PROJECT_BINARY_DIR}/pythonCFFI/")
-
-    if(BUILD_MPIN)
-      message(STATUS "Copy libmpin.dll to pythonCFFI for testing")
-      add_custom_command(
-                  TARGET mpin
-                  POST_BUILD
-                  COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/libmpin.dll" "${PROJECT_BINARY_DIR}/pythonCFFI/")
-    endif(BUILD_MPIN)
-
-    if(BUILD_WCC)
-      message(STATUS "Copy libwcc.dll to pythonCFFI for testing")
-      add_custom_command(
-                  TARGET wcc
-                  POST_BUILD
-                  COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/libwcc.dll" "${PROJECT_BINARY_DIR}/pythonCFFI/")
-    endif(BUILD_WCC)
-
-  endif(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
-
-  if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
-
-    message(STATUS "Copy libamcl.dylib to pythonCFFI for testing")
-    add_custom_command(
-                TARGET amcl
-                POST_BUILD
-                COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/libamcl.dylib" "${PROJECT_BINARY_DIR}/pythonCFFI/")
-
-    if(BUILD_MPIN)
-      message(STATUS "Copy libmpin.dylib to pythonCFFI for testing")
-      add_custom_command(
-                  TARGET mpin
-                  POST_BUILD
-                  COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/libmpin.dylib" "${PROJECT_BINARY_DIR}/pythonCFFI/")
-    endif(BUILD_MPIN)
-
-    if(BUILD_WCC)
-      message(STATUS "Copy libwcc.dylib to pythonCFFI for testing")
-      add_custom_command(
-                  TARGET wcc
-                  POST_BUILD
-                  COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/libwcc.dylib" "${PROJECT_BINARY_DIR}/pythonCFFI/")
-    endif(BUILD_WCC)  
-
-
-  endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
-
-
-endif (BUILD_PYTHON AND BUILD_SHARED_LIBS)
-
-# Example programs
-add_executable (testecm testecm.c ecdh.c)
-add_executable (testecdh testecdh.c ecdh.c)
-add_executable (testrsa testrsa.c rsa.c)
-target_link_libraries (testecm amcl) 
-target_link_libraries (testecdh amcl) 
-target_link_libraries (testrsa amcl) 
-
-add_subdirectory (tests)
-
-# Install libs and headers
-if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
-  install(DIRECTORY DESTINATION include DIRECTORY_PERMISSIONS
-          OWNER_WRITE OWNER_READ OWNER_EXECUTE
-          GROUP_WRITE GROUP_READ
-          WORLD_WRITE WORLD_READ WORLD_EXECUTE)
-  install (TARGETS amcl DESTINATION lib PERMISSIONS
-          OWNER_WRITE OWNER_READ OWNER_EXECUTE
-          GROUP_READ GROUP_EXECUTE
-          WORLD_READ WORLD_EXECUTE)
-  install (FILES ${CMAKE_CURRENT_BINARY_DIR}/amcl.h DESTINATION include PERMISSIONS
-          OWNER_WRITE OWNER_READ OWNER_EXECUTE
-          GROUP_READ GROUP_EXECUTE
-          WORLD_READ WORLD_EXECUTE)
-  install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/utils.h DESTINATION include PERMISSIONS
-          OWNER_WRITE OWNER_READ OWNER_EXECUTE
-          GROUP_READ GROUP_EXECUTE
-          WORLD_READ WORLD_EXECUTE)
-  install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/DLLDefines.h DESTINATION include PERMISSIONS
-          OWNER_WRITE OWNER_READ OWNER_EXECUTE
-          GROUP_READ GROUP_EXECUTE
-          WORLD_READ WORLD_EXECUTE)
-
-  if(BUILD_MPIN)
-    install (TARGETS mpin DESTINATION lib PERMISSIONS
-            OWNER_WRITE OWNER_READ OWNER_EXECUTE
-            GROUP_READ GROUP_EXECUTE
-            WORLD_READ WORLD_EXECUTE)
-    install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/mpin.h DESTINATION include PERMISSIONS
-            OWNER_WRITE OWNER_READ OWNER_EXECUTE
-            GROUP_READ GROUP_EXECUTE
-            WORLD_READ WORLD_EXECUTE)
-  endif(BUILD_MPIN)
-  
-  if(BUILD_WCC)
-    install (TARGETS wcc DESTINATION lib PERMISSIONS
-            OWNER_WRITE OWNER_READ OWNER_EXECUTE
-            GROUP_READ GROUP_EXECUTE
-            WORLD_READ WORLD_EXECUTE)
-    install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/wcc.h DESTINATION include PERMISSIONS
-            OWNER_WRITE OWNER_READ OWNER_EXECUTE
-            GROUP_READ GROUP_EXECUTE
-            WORLD_READ WORLD_EXECUTE)
-  endif(BUILD_WCC)
-
-endif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
-
-if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
-  # Windows specific code
-  install (TARGETS amcl DESTINATION lib)
-  install (FILES ${CMAKE_CURRENT_BINARY_DIR}/amcl.h DESTINATION lib)
-  install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/utils.h DESTINATION lib)
-  install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/DLLDefines.h DESTINATION lib)
-  
-  if(BUILD_MPIN)
-    install (TARGETS mpin DESTINATION lib)
-    install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/mpin.h DESTINATION lib)
-  endif(BUILD_MPIN)
-  
-  if(BUILD_WCC)
-    install (TARGETS wcc DESTINATION lib)
-    install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/wcc.h DESTINATION lib)
-  endif(BUILD_WCC)
-
-endif(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
-
-if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
-  # Mac OS X specific code
-  install(DIRECTORY DESTINATION include DIRECTORY_PERMISSIONS
-          OWNER_WRITE OWNER_READ OWNER_EXECUTE
-          GROUP_WRITE GROUP_READ
-          WORLD_WRITE WORLD_READ WORLD_EXECUTE)
-  install (TARGETS amcl DESTINATION lib PERMISSIONS
-          OWNER_WRITE OWNER_READ OWNER_EXECUTE
-          GROUP_READ GROUP_EXECUTE
-          WORLD_READ WORLD_EXECUTE)
-  install (FILES ${CMAKE_CURRENT_BINARY_DIR}/amcl.h DESTINATION include PERMISSIONS
-          OWNER_WRITE OWNER_READ OWNER_EXECUTE
-          GROUP_READ GROUP_EXECUTE
-          WORLD_READ WORLD_EXECUTE)
-  install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/utils.h DESTINATION include PERMISSIONS
-          OWNER_WRITE OWNER_READ OWNER_EXECUTE
-          GROUP_READ GROUP_EXECUTE
-          WORLD_READ WORLD_EXECUTE)
-  install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/DLLDefines.h DESTINATION include PERMISSIONS
-          OWNER_WRITE OWNER_READ OWNER_EXECUTE
-          GROUP_READ GROUP_EXECUTE
-          WORLD_READ WORLD_EXECUTE)
-
-  if(BUILD_MPIN)
-    install (TARGETS mpin DESTINATION lib PERMISSIONS
-            OWNER_WRITE OWNER_READ OWNER_EXECUTE
-            GROUP_READ GROUP_EXECUTE
-            WORLD_READ WORLD_EXECUTE)
-    install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/mpin.h DESTINATION include PERMISSIONS
-            OWNER_WRITE OWNER_READ OWNER_EXECUTE
-            GROUP_READ GROUP_EXECUTE
-            WORLD_READ WORLD_EXECUTE)
-  endif(BUILD_MPIN)
-
-  if(BUILD_WCC)
-    install (TARGETS wcc DESTINATION lib PERMISSIONS
-            OWNER_WRITE OWNER_READ OWNER_EXECUTE
-            GROUP_READ GROUP_EXECUTE
-            WORLD_READ WORLD_EXECUTE)
-    install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/wcc.h DESTINATION include PERMISSIONS
-            OWNER_WRITE OWNER_READ OWNER_EXECUTE
-            GROUP_READ GROUP_EXECUTE
-            WORLD_READ WORLD_EXECUTE)
-  endif(BUILD_WCC)
-
-
-endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
diff --git a/c/DLLDefines.h b/c/DLLDefines.h
deleted file mode 100755
index 57655f3..0000000
--- a/c/DLLDefines.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one
-or more contributor license agreements.  See the NOTICE file
-distributed with this work for additional information
-regarding copyright ownership.  The ASF licenses this file
-to you under the Apache License, Version 2.0 (the
-"License"); you may not use this file except in compliance
-with the License.  You may obtain a copy of the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing,
-software distributed under the License is distributed on an
-"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-KIND, either express or implied.  See the License for the
-specific language governing permissions and limitations
-under the License.
-*/
-
-/* Use with Visual Studio Compiler for building Shared libraries */
-#ifndef _DLLDEFINES_H_
-#define _DLLDEFINES_H_
-
-/* Cmake will define sok_EXPORTS and mpin_EXPORTS on Windows when it
-configures to build a shared library. If you are going to use
-another build system on windows or create the visual studio
-projects by hand you need to define sok_EXPORTS and mpin_EXPORTS when
-building a DLL on windows. */
-/* #define sok_EXPORTS */
-/* #define mpin_EXPORTS */
-
-
-#if defined (_MSC_VER)
-
- #define DLL_EXPORT extern
-/* This code does not work with cl */
-/*  #if defined(sok_EXPORTS) || defined(mpin_EXPORTS) */
-/*    #define  DLL_EXPORT __declspec(dllexport) */
-/*  #else */
-/*    #define  DLL_EXPORT __declspec(dllimport) */
-/*  #endif /\* sok_EXPORTS || mpin_EXPORTS *\/ */
-
-#else /* defined (_WIN32) */
-
- #define DLL_EXPORT extern
-
-#endif
-
-#endif /* _DLLDEFINES_H_ */
diff --git a/c/aes.c b/c/aes.c
deleted file mode 100755
index d9360e9..0000000
--- a/c/aes.c
+++ /dev/null
@@ -1,620 +0,0 @@
-/*
-/*
-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.
-*/
-
-
-/*
- * Implementation of the NIST Advanced Ecryption Standard
- *
- * SU=m, SU is Stack Usage
- */
-
-#include <stdlib.h>
-#include "amcl.h"
-
-/* this is fixed */
-#define NB 4
-#define ROUNDS 10
-
-/* Rotates 32-bit word left by 1, 2 or 3 byte  */
-
-#define ROTL8(x) (((x)<<8)|((x)>>24))
-#define ROTL16(x) (((x)<<16)|((x)>>16))
-#define ROTL24(x) (((x)<<24)|((x)>>8))
-
-static const uchar InCo[4]={0xB,0xD,0x9,0xE};  /* Inverse Coefficients */
-
-static const uchar ptab[]=
-{1,3,5,15,17,51,85,255,26,46,114,150,161,248,19,53,
-95,225,56,72,216,115,149,164,247,2,6,10,30,34,102,170,
-229,52,92,228,55,89,235,38,106,190,217,112,144,171,230,49,
-83,245,4,12,20,60,68,204,79,209,104,184,211,110,178,205,
-76,212,103,169,224,59,77,215,98,166,241,8,24,40,120,136,
-131,158,185,208,107,189,220,127,129,152,179,206,73,219,118,154,
-181,196,87,249,16,48,80,240,11,29,39,105,187,214,97,163,
-254,25,43,125,135,146,173,236,47,113,147,174,233,32,96,160,
-251,22,58,78,210,109,183,194,93,231,50,86,250,21,63,65,
-195,94,226,61,71,201,64,192,91,237,44,116,156,191,218,117,
-159,186,213,100,172,239,42,126,130,157,188,223,122,142,137,128,
-155,182,193,88,232,35,101,175,234,37,111,177,200,67,197,84,
-252,31,33,99,165,244,7,9,27,45,119,153,176,203,70,202,
-69,207,74,222,121,139,134,145,168,227,62,66,198,81,243,14,
-18,54,90,238,41,123,141,140,143,138,133,148,167,242,13,23,
-57,75,221,124,132,151,162,253,28,36,108,180,199,82,246,1};
-
-static const uchar ltab[]=
-{0,255,25,1,50,2,26,198,75,199,27,104,51,238,223,3,
-100,4,224,14,52,141,129,239,76,113,8,200,248,105,28,193,
-125,194,29,181,249,185,39,106,77,228,166,114,154,201,9,120,
-101,47,138,5,33,15,225,36,18,240,130,69,53,147,218,142,
-150,143,219,189,54,208,206,148,19,92,210,241,64,70,131,56,
-102,221,253,48,191,6,139,98,179,37,226,152,34,136,145,16,
-126,110,72,195,163,182,30,66,58,107,40,84,250,133,61,186,
-43,121,10,21,155,159,94,202,78,212,172,229,243,115,167,87,
-175,88,168,80,244,234,214,116,79,174,233,213,231,230,173,232,
-44,215,117,122,235,22,11,245,89,203,95,176,156,169,81,160,
-127,12,246,111,23,196,73,236,216,67,31,45,164,118,123,183,
-204,187,62,90,251,96,177,134,59,82,161,108,170,85,41,157,
-151,178,135,144,97,190,220,252,188,149,207,205,55,63,91,209,
-83,57,132,60,65,162,109,71,20,42,158,93,86,242,211,171,
-68,17,146,217,35,32,46,137,180,124,184,38,119,153,227,165,
-103,74,237,222,197,49,254,24,13,99,140,128,192,247,112,7};
-
-static const uchar fbsub[]=
-{99,124,119,123,242,107,111,197,48,1,103,43,254,215,171,118,
-202,130,201,125,250,89,71,240,173,212,162,175,156,164,114,192,
-183,253,147,38,54,63,247,204,52,165,229,241,113,216,49,21,
-4,199,35,195,24,150,5,154,7,18,128,226,235,39,178,117,
-9,131,44,26,27,110,90,160,82,59,214,179,41,227,47,132,
-83,209,0,237,32,252,177,91,106,203,190,57,74,76,88,207,
-208,239,170,251,67,77,51,133,69,249,2,127,80,60,159,168,
-81,163,64,143,146,157,56,245,188,182,218,33,16,255,243,210,
-205,12,19,236,95,151,68,23,196,167,126,61,100,93,25,115,
-96,129,79,220,34,42,144,136,70,238,184,20,222,94,11,219,
-224,50,58,10,73,6,36,92,194,211,172,98,145,149,228,121,
-231,200,55,109,141,213,78,169,108,86,244,234,101,122,174,8,
-186,120,37,46,28,166,180,198,232,221,116,31,75,189,139,138,
-112,62,181,102,72,3,246,14,97,53,87,185,134,193,29,158,
-225,248,152,17,105,217,142,148,155,30,135,233,206,85,40,223,
-140,161,137,13,191,230,66,104,65,153,45,15,176,84,187,22};
-
-static const uchar rbsub[]=
-{82,9,106,213,48,54,165,56,191,64,163,158,129,243,215,251,
-124,227,57,130,155,47,255,135,52,142,67,68,196,222,233,203,
-84,123,148,50,166,194,35,61,238,76,149,11,66,250,195,78,
-8,46,161,102,40,217,36,178,118,91,162,73,109,139,209,37,
-114,248,246,100,134,104,152,22,212,164,92,204,93,101,182,146,
-108,112,72,80,253,237,185,218,94,21,70,87,167,141,157,132,
-144,216,171,0,140,188,211,10,247,228,88,5,184,179,69,6,
-208,44,30,143,202,63,15,2,193,175,189,3,1,19,138,107,
-58,145,17,65,79,103,220,234,151,242,207,206,240,180,230,115,
-150,172,116,34,231,173,53,133,226,249,55,232,28,117,223,110,
-71,241,26,113,29,41,197,137,111,183,98,14,170,24,190,27,
-252,86,62,75,198,210,121,32,154,219,192,254,120,205,90,244,
-31,221,168,51,136,7,199,49,177,18,16,89,39,128,236,95,
-96,81,127,169,25,181,74,13,45,229,122,159,147,201,156,239,
-160,224,59,77,174,42,245,176,200,235,187,60,131,83,153,97,
-23,43,4,126,186,119,214,38,225,105,20,99,85,33,12,125};
-
-static const unsign32 rco[]=
-{1,2,4,8,16,32,64,128,27,54,108,216,171,77,154,47};
-
-static const unsign32 ftable[]=
-{0xa56363c6,0x847c7cf8,0x997777ee,0x8d7b7bf6,0xdf2f2ff,0xbd6b6bd6,
-0xb16f6fde,0x54c5c591,0x50303060,0x3010102,0xa96767ce,0x7d2b2b56,
-0x19fefee7,0x62d7d7b5,0xe6abab4d,0x9a7676ec,0x45caca8f,0x9d82821f,
-0x40c9c989,0x877d7dfa,0x15fafaef,0xeb5959b2,0xc947478e,0xbf0f0fb,
-0xecadad41,0x67d4d4b3,0xfda2a25f,0xeaafaf45,0xbf9c9c23,0xf7a4a453,
-0x967272e4,0x5bc0c09b,0xc2b7b775,0x1cfdfde1,0xae93933d,0x6a26264c,
-0x5a36366c,0x413f3f7e,0x2f7f7f5,0x4fcccc83,0x5c343468,0xf4a5a551,
-0x34e5e5d1,0x8f1f1f9,0x937171e2,0x73d8d8ab,0x53313162,0x3f15152a,
-0xc040408,0x52c7c795,0x65232346,0x5ec3c39d,0x28181830,0xa1969637,
-0xf05050a,0xb59a9a2f,0x907070e,0x36121224,0x9b80801b,0x3de2e2df,
-0x26ebebcd,0x6927274e,0xcdb2b27f,0x9f7575ea,0x1b090912,0x9e83831d,
-0x742c2c58,0x2e1a1a34,0x2d1b1b36,0xb26e6edc,0xee5a5ab4,0xfba0a05b,
-0xf65252a4,0x4d3b3b76,0x61d6d6b7,0xceb3b37d,0x7b292952,0x3ee3e3dd,
-0x712f2f5e,0x97848413,0xf55353a6,0x68d1d1b9,0x0,0x2cededc1,
-0x60202040,0x1ffcfce3,0xc8b1b179,0xed5b5bb6,0xbe6a6ad4,0x46cbcb8d,
-0xd9bebe67,0x4b393972,0xde4a4a94,0xd44c4c98,0xe85858b0,0x4acfcf85,
-0x6bd0d0bb,0x2aefefc5,0xe5aaaa4f,0x16fbfbed,0xc5434386,0xd74d4d9a,
-0x55333366,0x94858511,0xcf45458a,0x10f9f9e9,0x6020204,0x817f7ffe,
-0xf05050a0,0x443c3c78,0xba9f9f25,0xe3a8a84b,0xf35151a2,0xfea3a35d,
-0xc0404080,0x8a8f8f05,0xad92923f,0xbc9d9d21,0x48383870,0x4f5f5f1,
-0xdfbcbc63,0xc1b6b677,0x75dadaaf,0x63212142,0x30101020,0x1affffe5,
-0xef3f3fd,0x6dd2d2bf,0x4ccdcd81,0x140c0c18,0x35131326,0x2fececc3,
-0xe15f5fbe,0xa2979735,0xcc444488,0x3917172e,0x57c4c493,0xf2a7a755,
-0x827e7efc,0x473d3d7a,0xac6464c8,0xe75d5dba,0x2b191932,0x957373e6,
-0xa06060c0,0x98818119,0xd14f4f9e,0x7fdcdca3,0x66222244,0x7e2a2a54,
-0xab90903b,0x8388880b,0xca46468c,0x29eeeec7,0xd3b8b86b,0x3c141428,
-0x79dedea7,0xe25e5ebc,0x1d0b0b16,0x76dbdbad,0x3be0e0db,0x56323264,
-0x4e3a3a74,0x1e0a0a14,0xdb494992,0xa06060c,0x6c242448,0xe45c5cb8,
-0x5dc2c29f,0x6ed3d3bd,0xefacac43,0xa66262c4,0xa8919139,0xa4959531,
-0x37e4e4d3,0x8b7979f2,0x32e7e7d5,0x43c8c88b,0x5937376e,0xb76d6dda,
-0x8c8d8d01,0x64d5d5b1,0xd24e4e9c,0xe0a9a949,0xb46c6cd8,0xfa5656ac,
-0x7f4f4f3,0x25eaeacf,0xaf6565ca,0x8e7a7af4,0xe9aeae47,0x18080810,
-0xd5baba6f,0x887878f0,0x6f25254a,0x722e2e5c,0x241c1c38,0xf1a6a657,
-0xc7b4b473,0x51c6c697,0x23e8e8cb,0x7cdddda1,0x9c7474e8,0x211f1f3e,
-0xdd4b4b96,0xdcbdbd61,0x868b8b0d,0x858a8a0f,0x907070e0,0x423e3e7c,
-0xc4b5b571,0xaa6666cc,0xd8484890,0x5030306,0x1f6f6f7,0x120e0e1c,
-0xa36161c2,0x5f35356a,0xf95757ae,0xd0b9b969,0x91868617,0x58c1c199,
-0x271d1d3a,0xb99e9e27,0x38e1e1d9,0x13f8f8eb,0xb398982b,0x33111122,
-0xbb6969d2,0x70d9d9a9,0x898e8e07,0xa7949433,0xb69b9b2d,0x221e1e3c,
-0x92878715,0x20e9e9c9,0x49cece87,0xff5555aa,0x78282850,0x7adfdfa5,
-0x8f8c8c03,0xf8a1a159,0x80898909,0x170d0d1a,0xdabfbf65,0x31e6e6d7,
-0xc6424284,0xb86868d0,0xc3414182,0xb0999929,0x772d2d5a,0x110f0f1e,
-0xcbb0b07b,0xfc5454a8,0xd6bbbb6d,0x3a16162c};
-
-static const unsign32 rtable[]=
-{0x50a7f451,0x5365417e,0xc3a4171a,0x965e273a,0xcb6bab3b,0xf1459d1f,
-0xab58faac,0x9303e34b,0x55fa3020,0xf66d76ad,0x9176cc88,0x254c02f5,
-0xfcd7e54f,0xd7cb2ac5,0x80443526,0x8fa362b5,0x495ab1de,0x671bba25,
-0x980eea45,0xe1c0fe5d,0x2752fc3,0x12f04c81,0xa397468d,0xc6f9d36b,
-0xe75f8f03,0x959c9215,0xeb7a6dbf,0xda595295,0x2d83bed4,0xd3217458,
-0x2969e049,0x44c8c98e,0x6a89c275,0x78798ef4,0x6b3e5899,0xdd71b927,
-0xb64fe1be,0x17ad88f0,0x66ac20c9,0xb43ace7d,0x184adf63,0x82311ae5,
-0x60335197,0x457f5362,0xe07764b1,0x84ae6bbb,0x1ca081fe,0x942b08f9,
-0x58684870,0x19fd458f,0x876cde94,0xb7f87b52,0x23d373ab,0xe2024b72,
-0x578f1fe3,0x2aab5566,0x728ebb2,0x3c2b52f,0x9a7bc586,0xa50837d3,
-0xf2872830,0xb2a5bf23,0xba6a0302,0x5c8216ed,0x2b1ccf8a,0x92b479a7,
-0xf0f207f3,0xa1e2694e,0xcdf4da65,0xd5be0506,0x1f6234d1,0x8afea6c4,
-0x9d532e34,0xa055f3a2,0x32e18a05,0x75ebf6a4,0x39ec830b,0xaaef6040,
-0x69f715e,0x51106ebd,0xf98a213e,0x3d06dd96,0xae053edd,0x46bde64d,
-0xb58d5491,0x55dc471,0x6fd40604,0xff155060,0x24fb9819,0x97e9bdd6,
-0xcc434089,0x779ed967,0xbd42e8b0,0x888b8907,0x385b19e7,0xdbeec879,
-0x470a7ca1,0xe90f427c,0xc91e84f8,0x0,0x83868009,0x48ed2b32,
-0xac70111e,0x4e725a6c,0xfbff0efd,0x5638850f,0x1ed5ae3d,0x27392d36,
-0x64d90f0a,0x21a65c68,0xd1545b9b,0x3a2e3624,0xb1670a0c,0xfe75793,
-0xd296eeb4,0x9e919b1b,0x4fc5c080,0xa220dc61,0x694b775a,0x161a121c,
-0xaba93e2,0xe52aa0c0,0x43e0223c,0x1d171b12,0xb0d090e,0xadc78bf2,
-0xb9a8b62d,0xc8a91e14,0x8519f157,0x4c0775af,0xbbdd99ee,0xfd607fa3,
-0x9f2601f7,0xbcf5725c,0xc53b6644,0x347efb5b,0x7629438b,0xdcc623cb,
-0x68fcedb6,0x63f1e4b8,0xcadc31d7,0x10856342,0x40229713,0x2011c684,
-0x7d244a85,0xf83dbbd2,0x1132f9ae,0x6da129c7,0x4b2f9e1d,0xf330b2dc,
-0xec52860d,0xd0e3c177,0x6c16b32b,0x99b970a9,0xfa489411,0x2264e947,
-0xc48cfca8,0x1a3ff0a0,0xd82c7d56,0xef903322,0xc74e4987,0xc1d138d9,
-0xfea2ca8c,0x360bd498,0xcf81f5a6,0x28de7aa5,0x268eb7da,0xa4bfad3f,
-0xe49d3a2c,0xd927850,0x9bcc5f6a,0x62467e54,0xc2138df6,0xe8b8d890,
-0x5ef7392e,0xf5afc382,0xbe805d9f,0x7c93d069,0xa92dd56f,0xb31225cf,
-0x3b99acc8,0xa77d1810,0x6e639ce8,0x7bbb3bdb,0x97826cd,0xf418596e,
-0x1b79aec,0xa89a4f83,0x656e95e6,0x7ee6ffaa,0x8cfbc21,0xe6e815ef,
-0xd99be7ba,0xce366f4a,0xd4099fea,0xd67cb029,0xafb2a431,0x31233f2a,
-0x3094a5c6,0xc066a235,0x37bc4e74,0xa6ca82fc,0xb0d090e0,0x15d8a733,
-0x4a9804f1,0xf7daec41,0xe50cd7f,0x2ff69117,0x8dd64d76,0x4db0ef43,
-0x544daacc,0xdf0496e4,0xe3b5d19e,0x1b886a4c,0xb81f2cc1,0x7f516546,
-0x4ea5e9d,0x5d358c01,0x737487fa,0x2e410bfb,0x5a1d67b3,0x52d2db92,
-0x335610e9,0x1347d66d,0x8c61d79a,0x7a0ca137,0x8e14f859,0x893c13eb,
-0xee27a9ce,0x35c961b7,0xede51ce1,0x3cb1477a,0x59dfd29c,0x3f73f255,
-0x79ce1418,0xbf37c773,0xeacdf753,0x5baafd5f,0x146f3ddf,0x86db4478,
-0x81f3afca,0x3ec468b9,0x2c342438,0x5f40a3c2,0x72c31d16,0xc25e2bc,
-0x8b493c28,0x41950dff,0x7101a839,0xdeb30c08,0x9ce4b4d8,0x90c15664,
-0x6184cb7b,0x70b632d5,0x745c6c48,0x4257b8d0};
-
-#define MR_TOBYTE(x) ((uchar)((x)))
-
-static unsign32 pack(const uchar *b)
-{ /* pack bytes into a 32-bit Word */
-    return ((unsign32)b[3]<<24)|((unsign32)b[2]<<16)|((unsign32)b[1]<<8)|(unsign32)b[0];
-}
-
-static void unpack(unsign32 a,uchar *b)
-{ /* unpack bytes from a word */
-    b[0]=MR_TOBYTE(a);
-    b[1]=MR_TOBYTE(a>>8);
-    b[2]=MR_TOBYTE(a>>16);
-    b[3]=MR_TOBYTE(a>>24);
-}
-
-/* SU= 8 */
-static uchar bmul(uchar x,uchar y)
-{ /* x.y= AntiLog(Log(x) + Log(y)) */
-    if (x && y) return ptab[(ltab[x]+ltab[y])%255];
-    else return 0;
-}
-
-static unsign32 SubByte(unsign32 a)
-{
-    uchar b[4];
-    unpack(a,b);
-    b[0]=fbsub[b[0]];
-    b[1]=fbsub[b[1]];
-    b[2]=fbsub[b[2]];
-    b[3]=fbsub[b[3]];
-    return pack(b);
-}
-
-/* SU= 16 */
-static uchar product(unsign32 x,unsign32 y)
-{ /* dot product of two 4-byte arrays */
-    uchar xb[4],yb[4];
-    unpack(x,xb);
-    unpack(y,yb);
-    return bmul(xb[0],yb[0])^bmul(xb[1],yb[1])^bmul(xb[2],yb[2])^bmul(xb[3],yb[3]);
-}
-
-static unsign32 InvMixCol(unsign32 x)
-{ /* matrix Multiplication */
-    unsign32 y,m;
-    uchar b[4];
-
-    m=pack(InCo);
-    b[3]=product(m,x);
-    m=ROTL24(m);
-    b[2]=product(m,x);
-    m=ROTL24(m);
-    b[1]=product(m,x);
-    m=ROTL24(m);
-    b[0]=product(m,x);
-    y=pack(b);
-    return y;
-}
-
-/* SU= 8 */
-/* reset cipher */
-void AES_reset(aes *a,int mode,char *iv)
-{ /* reset mode, or reset iv */
-    int i;
-    a->mode=mode;
-    for (i=0;i<4*NB;i++)
-        a->f[i]=0;
-    if (mode!=ECB && iv!=NULL)
-    {
-        for (i=0;i<4*NB;i++)
-            a->f[i]=iv[i];
-    }
-}
-
-void AES_getreg(aes *a,char *ir)
-{
-    int i;
-    for (i=0;i<4*NB;i++) ir[i]=a->f[i];
-}
-
-/* SU= 72 */
-/* Initialise cipher */
-void AES_init(aes* a,int mode,char *key,char *iv)
-{ /* Key=16 bytes */
-  /* Key Scheduler. Create expanded encryption key */
-    int i,j,k,N,nk;
-    unsign32 CipherKey[4];
-
-    nk=4;
-
-    AES_reset(a,mode,iv);
-
-    N=NB*(ROUNDS+1);
-
-    for (i=j=0;i<nk;i++,j+=4)
-    {
-        CipherKey[i]=pack((uchar *)&key[j]);
-    }
-    for (i=0;i<nk;i++) a->fkey[i]=CipherKey[i];
-    for (j=nk,k=0;j<N;j+=nk,k++)
-    {
-        a->fkey[j]=a->fkey[j-nk]^SubByte(ROTL24(a->fkey[j-1]))^rco[k];
-
-        for (i=1;i<nk && (i+j)<N;i++)
-            a->fkey[i+j]=a->fkey[i+j-nk]^a->fkey[i+j-1];
-
-	}
- /* now for the expanded decrypt key in reverse order */
-
-    for (j=0;j<NB;j++) a->rkey[j+N-NB]=a->fkey[j];
-    for (i=NB;i<N-NB;i+=NB)
-    {
-        k=N-NB-i;
-        for (j=0;j<NB;j++) a->rkey[k+j]=InvMixCol(a->fkey[i+j]);
-    }
-    for (j=N-NB;j<N;j++) a->rkey[j-N+NB]=a->fkey[j];
-
-}
-
-/* SU= 80 */
-/* Encrypt a single block */
-void AES_ecb_encrypt(aes *a,uchar *buff)
-{
-    int i,j,k;
-    unsign32 p[4],q[4],*x,*y,*t;
-
-    for (i=j=0;i<NB;i++,j+=4)
-    {
-        p[i]=pack((uchar *)&buff[j]);
-        p[i]^=a->fkey[i];
-    }
-
-    k=NB;
-    x=p; y=q;
-
-/* State alternates between x and y */
-    for (i=1;i<ROUNDS;i++)
-    {
-
-        y[0]=a->fkey[k]^ftable[MR_TOBYTE(x[0])]^
-             ROTL8(ftable[MR_TOBYTE(x[1]>>8)])^
-             ROTL16(ftable[MR_TOBYTE(x[2]>>16)])^
-             ROTL24(ftable[x[3]>>24]);
-        y[1]=a->fkey[k+1]^ftable[MR_TOBYTE(x[1])]^
-             ROTL8(ftable[MR_TOBYTE(x[2]>>8)])^
-             ROTL16(ftable[MR_TOBYTE(x[3]>>16)])^
-             ROTL24(ftable[x[0]>>24]);
-        y[2]=a->fkey[k+2]^ftable[MR_TOBYTE(x[2])]^
-             ROTL8(ftable[MR_TOBYTE(x[3]>>8)])^
-             ROTL16(ftable[MR_TOBYTE(x[0]>>16)])^
-             ROTL24(ftable[x[1]>>24]);
-        y[3]=a->fkey[k+3]^ftable[MR_TOBYTE(x[3])]^
-             ROTL8(ftable[MR_TOBYTE(x[0]>>8)])^
-             ROTL16(ftable[MR_TOBYTE(x[1]>>16)])^
-             ROTL24(ftable[x[2]>>24]);
-
-        k+=4;
-        t=x; x=y; y=t;      /* swap pointers */
-    }
-
-/* Last Round */
-
-    y[0]=a->fkey[k]^(unsign32)fbsub[MR_TOBYTE(x[0])]^
-         ROTL8((unsign32)fbsub[MR_TOBYTE(x[1]>>8)])^
-         ROTL16((unsign32)fbsub[MR_TOBYTE(x[2]>>16)])^
-         ROTL24((unsign32)fbsub[x[3]>>24]);
-    y[1]=a->fkey[k+1]^(unsign32)fbsub[MR_TOBYTE(x[1])]^
-         ROTL8((unsign32)fbsub[MR_TOBYTE(x[2]>>8)])^
-         ROTL16((unsign32)fbsub[MR_TOBYTE(x[3]>>16)])^
-         ROTL24((unsign32)fbsub[x[0]>>24]);
-    y[2]=a->fkey[k+2]^(unsign32)fbsub[MR_TOBYTE(x[2])]^
-         ROTL8((unsign32)fbsub[MR_TOBYTE(x[3]>>8)])^
-         ROTL16((unsign32)fbsub[MR_TOBYTE(x[0]>>16)])^
-         ROTL24((unsign32)fbsub[x[1]>>24]);
-    y[3]=a->fkey[k+3]^(unsign32)fbsub[MR_TOBYTE(x[3])]^
-         ROTL8((unsign32)fbsub[MR_TOBYTE(x[0]>>8)])^
-         ROTL16((unsign32)fbsub[MR_TOBYTE(x[1]>>16)])^
-         ROTL24((unsign32)fbsub[x[2]>>24]);
-
-    for (i=j=0;i<NB;i++,j+=4)
-    {
-        unpack(y[i],(uchar *)&buff[j]);
-        x[i]=y[i]=0;   /* clean up stack */
-    }
-}
-
-/* SU= 80 */
-/* Decrypt a single block */
-void AES_ecb_decrypt(aes *a,uchar *buff)
-{
-    int i,j,k;
-    unsign32 p[4],q[4],*x,*y,*t;
-
-    for (i=j=0;i<NB;i++,j+=4)
-    {
-        p[i]=pack((uchar *)&buff[j]);
-        p[i]^=a->rkey[i];
-    }
-
-    k=NB;
-    x=p; y=q;
-
-/* State alternates between x and y */
-    for (i=1;i<ROUNDS;i++)
-    { /* Nr is number of rounds. May be odd. */
-
-        y[0]=a->rkey[k]^rtable[MR_TOBYTE(x[0])]^
-             ROTL8(rtable[MR_TOBYTE(x[3]>>8)])^
-             ROTL16(rtable[MR_TOBYTE(x[2]>>16)])^
-             ROTL24(rtable[x[1]>>24]);
-        y[1]=a->rkey[k+1]^rtable[MR_TOBYTE(x[1])]^
-             ROTL8(rtable[MR_TOBYTE(x[0]>>8)])^
-             ROTL16(rtable[MR_TOBYTE(x[3]>>16)])^
-             ROTL24(rtable[x[2]>>24]);
-        y[2]=a->rkey[k+2]^rtable[MR_TOBYTE(x[2])]^
-             ROTL8(rtable[MR_TOBYTE(x[1]>>8)])^
-             ROTL16(rtable[MR_TOBYTE(x[0]>>16)])^
-             ROTL24(rtable[x[3]>>24]);
-        y[3]=a->rkey[k+3]^rtable[MR_TOBYTE(x[3])]^
-             ROTL8(rtable[MR_TOBYTE(x[2]>>8)])^
-             ROTL16(rtable[MR_TOBYTE(x[1]>>16)])^
-             ROTL24(rtable[x[0]>>24]);
-
-        k+=4;
-        t=x; x=y; y=t;      /* swap pointers */
-    }
-
-
-/* Last Round */
-    y[0]=a->rkey[k]^(unsign32)rbsub[MR_TOBYTE(x[0])]^
-         ROTL8((unsign32)rbsub[MR_TOBYTE(x[3]>>8)])^
-         ROTL16((unsign32)rbsub[MR_TOBYTE(x[2]>>16)])^
-         ROTL24((unsign32)rbsub[x[1]>>24]);
-    y[1]=a->rkey[k+1]^(unsign32)rbsub[MR_TOBYTE(x[1])]^
-         ROTL8((unsign32)rbsub[MR_TOBYTE(x[0]>>8)])^
-         ROTL16((unsign32)rbsub[MR_TOBYTE(x[3]>>16)])^
-         ROTL24((unsign32)rbsub[x[2]>>24]);
-    y[2]=a->rkey[k+2]^(unsign32)rbsub[MR_TOBYTE(x[2])]^
-         ROTL8((unsign32)rbsub[MR_TOBYTE(x[1]>>8)])^
-         ROTL16((unsign32)rbsub[MR_TOBYTE(x[0]>>16)])^
-         ROTL24((unsign32)rbsub[x[3]>>24]);
-    y[3]=a->rkey[k+3]^(unsign32)rbsub[MR_TOBYTE(x[3])]^
-         ROTL8((unsign32)rbsub[MR_TOBYTE(x[2]>>8)])^
-         ROTL16((unsign32)rbsub[MR_TOBYTE(x[1]>>16)])^
-         ROTL24((unsign32)rbsub[x[0]>>24]);
-
-    for (i=j=0;i<NB;i++,j+=4)
-    {
-        unpack(y[i],(uchar *)&buff[j]);
-        x[i]=y[i]=0;   /* clean up stack */
-    }
-
-}
-
-/* SU= 40 */
-/* Encrypt using selected mode of operation */
-unsign32 AES_encrypt(aes* a,char *buff)
-{
-    int j,bytes;
-    char st[16];
-    unsign32 fell_off;
-
-/* Supported Modes of Operation */
-
-    fell_off=0;
-    switch (a->mode)
-    {
-    case ECB:
-        AES_ecb_encrypt(a,(uchar *)buff);
-        return 0;
-    case CBC:
-        for (j=0;j<4*NB;j++) buff[j]^=a->f[j];
-        AES_ecb_encrypt(a,(uchar *)buff);
-        for (j=0;j<4*NB;j++) a->f[j]=buff[j];
-        return 0;
-
-    case CFB1:
-    case CFB2:
-    case CFB4:
-        bytes=a->mode-CFB1+1;
-        for (j=0;j<bytes;j++) fell_off=(fell_off<<8)|a->f[j];
-        for (j=0;j<4*NB;j++) st[j]=a->f[j];
-        for (j=bytes;j<4*NB;j++) a->f[j-bytes]=a->f[j];
-        AES_ecb_encrypt(a,(uchar *)st);
-        for (j=0;j<bytes;j++)
-        {
-            buff[j]^=st[j];
-            a->f[16-bytes+j]=buff[j];
-        }
-        return fell_off;
-
-    case OFB1:
-    case OFB2:
-    case OFB4:
-    case OFB8:
-    case OFB16:
-
-        bytes=a->mode-OFB1+1;
-        AES_ecb_encrypt(a,(uchar *)(a->f));
-        for (j=0;j<bytes;j++) buff[j]^=a->f[j];
-        return 0;
-
-    default:
-        return 0;
-    }
-}
-
-/* SU= 40 */
-/* Decrypt using selected mode of operation */
-unsign32 AES_decrypt(aes *a,char *buff)
-{
-    int j,bytes;
-    char st[16];
-    unsign32 fell_off;
-
-   /* Supported modes of operation */
-    fell_off=0;
-    switch (a->mode)
-    {
-    case ECB:
-        AES_ecb_decrypt(a,(uchar *)buff);
-        return 0;
-    case CBC:
-        for (j=0;j<4*NB;j++)
-        {
-            st[j]=a->f[j];
-            a->f[j]=buff[j];
-        }
-        AES_ecb_decrypt(a,(uchar *)buff);
-        for (j=0;j<4*NB;j++)
-        {
-            buff[j]^=st[j];
-            st[j]=0;
-        }
-        return 0;
-    case CFB1:
-    case CFB2:
-    case CFB4:
-        bytes=a->mode-CFB1+1;
-        for (j=0;j<bytes;j++) fell_off=(fell_off<<8)|a->f[j];
-        for (j=0;j<4*NB;j++) st[j]=a->f[j];
-        for (j=bytes;j<4*NB;j++) a->f[j-bytes]=a->f[j];
-        AES_ecb_encrypt(a,(uchar *)st);
-        for (j=0;j<bytes;j++)
-        {
-            a->f[16-bytes+j]=buff[j];
-            buff[j]^=st[j];
-        }
-        return fell_off;
-    case OFB1:
-    case OFB2:
-    case OFB4:
-    case OFB8:
-    case OFB16:
-        bytes=a->mode-OFB1+1;
-        AES_ecb_encrypt(a,(uchar *)(a->f));
-        for (j=0;j<bytes;j++) buff[j]^=a->f[j];
-        return 0;
-
-
-    default:
-        return 0;
-    }
-}
-
-/* Clean up and delete left-overs */
-void AES_end(aes *a)
-{ /* clean up */
-    int i;
-    for (i=0;i<NB*(ROUNDS+1);i++)
-        a->fkey[i]=a->rkey[i]=0;
-    for (i=0;i<4*NB;i++)
-        a->f[i]=0;
-}
-
-/*
-int main()
-{
-    int i;
-    aes a;
-	unsign32 t;
-	uchar x,y;
-
-    char key[16];
-    char block[16];
-    char iv[16];
-    for (i=0;i<16;i++) key[i]=0;
-    key[0]=1;
-    for (i=0;i<16;i++) iv[i]=i;
-    for (i=0;i<16;i++) block[i]=i;
-
-    AES_init(&a,CBC,key,iv);
-
-    printf("Plain=   ");
-    for (i=0;i<16;i++) printf("%02x",block[i]);
-    printf("\n");
-    AES_encrypt(&a,block);
-    printf("Encrypt= ");
-    for (i=0;i<16;i++) printf("%02x",(uchar)block[i]);
-    printf("\n");
-    AES_reset(&a,CBC,iv);
-    AES_decrypt(&a,block);
-    printf("Decrypt= ");
-    for (i=0;i<16;i++) printf("%02x",(uchar)block[i]);
-    printf("\n");
-
-    AES_end(&a);
-
-    return 0;
-}
-
-*/
-
diff --git a/c/amcl.h.in b/c/amcl.h.in
deleted file mode 100755
index 3bbec0e..0000000
--- a/c/amcl.h.in
+++ /dev/null
@@ -1,2511 +0,0 @@
-/*
-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.
-*/
-
-/* AMCL header file */
-/* Designed for AES-128 security, 254-256 bit elliptic curves and BN curves for pairings */
-/* Each "limb" of a big number occupies at most (n-3) bits of an n-bit computer word. The most significant word must have at least 4 extra unused bits */
-/* For n=64, use 5 words, use 56 bits per limb, leaving at least 24 unused MSBs 5*56-256  */
-/* For n=32, use 9 words, use 29 bits per limb, leaving at least 5 unused MSBs  9*29-256  */
-/* For n=16, use 20 words, use 13 bits per limb, leaving at least 4 unused MSBs 20*13-256 */
-
-/**
- * @file amcl.h.in
- * @author Mike Scott and kealan McCusker
- * @date 19th May 2015
- * @brief Main Header File
- *
- * Allows some user configuration
- * defines structures
- * declares functions
- *
- */
-
-
-/* NOTE: There is only one user configurable section in this header - see below */
-
-#ifndef AMCL_H
-#define AMCL_H
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "DLLDefines.h"
-
-#define AMCL_VERSION_MAJOR @AMCL_VERSION_MAJOR@
-#define AMCL_VERSION_MINOR @AMCL_VERSION_MINOR@
-#define AMCL_VERSION_PATCH @AMCL_VERSION_PATCH@
-#define OS "@OS@"
-#cmakedefine USE_PATENTS
-#cmakedefine USE_ANONYMOUS
-
-/* Support for C99?  Note for GCC need to explicitly include -std=c99 in command line */
-
-#if __STDC_VERSION__ >= 199901L
-/* C99 code */
-#define C99
-#else
-/* Not C99 code */
-#endif
-
-#ifndef C99  /* You are on your own! These are for Microsoft C */
-#define sign32 __int32			/**< 32-bit signed integer */
-#define sign8 signed char		/**< 8-bit signed integer */
-#define unsign32 unsigned __int32 /**< 32-bit unsigned integer */
-#else
-#include <stdint.h>
-#define sign8 int8_t			/**< 8-bit signed integer */
-#define sign32 int32_t			/**< 32-bit signed integer */
-#define unsign32 uint32_t		/**< 32-bit unsigned integer */
-#endif
-
-/* modulus types */
-
-#define NOT_SPECIAL 0			/**< Modulus of no exploitable form */
-#define PSEUDO_MERSENNE 1		/**< Pseudo-mersenne modulus of form $2^n-c$  */
-#define MONTGOMERY_FRIENDLY 3	/**< Montgomery Friendly modulus of form $2^a(2^b-c)-1$  */
-
-/* curve types */
-
-#define WEIERSTRASS 0			/**< Short Weierstrass form curve  */
-#define EDWARDS 1				/**< Edwards or Twisted Edwards curve  */
-#define MONTGOMERY 2			/**< Montgomery form curve  */
-
-/* Elliptic curves are defined over prime fields */
-/* Here are some popular EC prime fields for which I have prepared curves. Feel free to specify your own. */
-
-#define NIST 0 /**< For the NIST 256-bit standard curve		- WEIERSTRASS only */
-#define C25519 1  /**< Bernstein's Modulus 2^255-19			- EDWARDS or MONTGOMERY only */
-#define BRAINPOOL 2 /**< For Brainpool 256-bit curve			- WEIERSTRASS only */
-#define ANSSI 3 /**< For French 256-bit standard curve		- WEIERSTRASS only */
-#define MF254 4 /**< For NUMS curves from Bos et al - 254-bit Montgomery friendly modulus		- WEIERSTRASS or EDWARDS or MONTGOMERY */
-#define MS255 5 /**< For NUMS curve - 255-bit pseudo-mersenne modulus							- WEIERSTRASS or EDWARDS or MONTGOMERY */
-#define MF256 6 /**< For NUMS curve - 256-bit Montgomery friendly modulus						- WEIERSTRASS or EDWARDS or MONTGOMERY */
-#define MS256 7 /**< For NUMS curve - 256-bit pseudo-merseene modulus							- WEIERSTRASS or EDWARDS or MONTGOMERY */
-
-#define BN 100    /**< Standard Nogami BN curve - fastest. Modulus built from  t=-0x4080000000000001	- WEIERSTRASS only */
-#define BNCX 101  /**< Our MIRACL BN curve. Modulus built from t=-0x4000000003C012B1					- WEIERSTRASS only */
-#define BNT 102   /**< GT_Strong BN curve. Modulus built from t=-0x4000806000004081  					- WEIERSTRASS only */
-#define BNT2 103  /**< G2 and GT-Strong BN curve.  Modulus built from t=-0x4000020100608205 			- WEIERSTRASS only */
-
-
-/*** START OF USER CONFIGURABLE SECTION - set architecture and choose modulus and curve  ***/
-
-#define CHUNK @WORD_LENGTH@ 	/**< size of chunk in bits = wordlength of computer = 16, 32 or 64. Note not all curve options are supported on 16-bit processors - see rom.c */
-#define CHOICE  @FIELD_CHOICE@	/**< Current choice of Field */
-#define FIELD_CHOICE "@FIELD_CHOICE@"
-/* For some moduli only WEIERSTRASS curves are supported. For others there is a choice of WEIERSTRASS, EDWARDS or MONTGOMERY curves. See above. */
-#define CURVETYPE @CURVE_TYPE@	/**< Note that not all curve types are supported - see above */
-
-/* Actual curve parameters associated with these choices can be found in rom.c */
-#define CURVE_TYPE "@CURVE_TYPE@"
-
-/* These next options only apply for pairings */
-#ifdef USE_PATENTS
-  #define USE_GLV		/**< Note this method is patented (GLV), so maybe you want to comment this out */
-  #define USE_GS_G2	/**< Well we didn't patent it :) But may be covered by GLV patent :( */
-#endif
-#define USE_GS_GT   /**< Not patented, so probably always use this */
-
-/* Finite field support - for RSA, DH etc. */
-#define FF_BITS 2048 /**< Finite Field Size in bits - must be 256.2^n */
-
-/* For debugging Only.
-#define DEBUG_REDUCE
-#define DEBUG_NORM
-#define GET_STATS
-*/
-
-/*** END OF USER CONFIGURABLE SECTION ***/
-
-
-#if CHOICE>=BN     /* Its a BN curve */
-#define MBITS 254	/**< Number of bits in Modulus */
-#define MOD8 3		/**< Modulus mod 8  */
-#define MODTYPE  NOT_SPECIAL /**< Modulus type */
-#endif
-
-#if CHOICE>BN
-#define GT_STRONG   /**< Using a GT-Strong BN curve */
-#endif
-
-#if CHOICE==NIST
-#define MBITS 256	/**< Number of bits in Modulus */
-#define MOD8 7		/**< Modulus mod 8  */
-#define MODTYPE  NOT_SPECIAL /**< Modulus type */
-#endif
-
-#if CHOICE==C25519
-#define MBITS 255	/**< Number of bits in Modulus */
-#define MOD8 5		/**< Modulus mod 8  */
-#define MODTYPE PSEUDO_MERSENNE /**< Modulus type */
-#endif
-
-#if CHOICE==BRAINPOOL
-#define MBITS 256 /**< Number of bits in Modulus */
-#define MOD8 7 /**< Modulus mod 8  */
-#define MODTYPE  NOT_SPECIAL /**< Modulus type */
-#endif
-
-#if CHOICE==ANSSI
-#define MBITS 256		/**< Number of bits in Modulus */
-#define MOD8 3			/**< Modulus mod 8  */
-#define MODTYPE  NOT_SPECIAL /**< Modulus type */
-#endif
-
-/**< NUMS curve from Bos et al. paper */
-
-#if CHOICE==MF254
-#define MBITS 254   /**< Number of bits in Modulus */
-#define MOD8 7      /**< Modulus mod 8  */
-#define MODTYPE MONTGOMERY_FRIENDLY  /**< Modulus type */
-#endif
-
-#if CHOICE==MF256
-#define MBITS 256   /**< Number of bits in Modulus */
-#define MOD8 7      /**< Modulus mod 8  */
-#define MODTYPE MONTGOMERY_FRIENDLY  /**< Modulus type */
-#endif
-
-#if CHOICE==MS255
-#define MBITS 255	/**< Number of bits in Modulus */
-#define MOD8 3		/**< Modulus mod 8  */
-#define MODTYPE PSEUDO_MERSENNE /**< Modulus type */
-#endif
-
-#if CHOICE==MS256
-#define MBITS 256	/**< Number of bits in Modulus */
-#define MOD8 3		/**< Modulus mod 8  */
-#define MODTYPE PSEUDO_MERSENNE /**< Modulus type */
-#endif
-
-
-#define FFLEN (FF_BITS/256)  /**< RSA public key bytes */
-#define HFLEN (FFLEN/2)		/**< Useful for half-size RSA private key operations */
-
-/* This next is probably OK, but may need changing for non-C99-standard environments */
-
-#if CHUNK==16
-#define NLEN 20				/**< Number of words in BIG. */
-#define BASEBITS 13			/**< Numbers represented to base 2*BASEBITS */
-#ifndef C99
-#define chunk __int16		/**< C type corresponding to word length */
-#define dchunk __int32		/**< Always define double length chunk type if available */
-#else
-#define chunk int16_t		/**< C type corresponding to word length */
-#define dchunk int32_t		/**< Always define double length chunk type if available */
-#endif
-#endif
-
-#if CHUNK == 32
-#define NLEN 9				/**< Number of words in BIG. */
-#define BASEBITS 29			/**< Numbers represented to base 2*BASEBITS */
-#ifndef C99
-#define chunk __int32		/**< C type corresponding to word length */
-#define dchunk __int64		/**< Always define double length chunk type if available */
-#else
-#define chunk int32_t		/**< C type corresponding to word length */
-#define dchunk int64_t		/**< Always define double length chunk type if available */
-#endif
-#endif
-
-#if CHUNK == 64
-#define NLEN 5				/**< Number of words in BIG. */
-#define BASEBITS 56			/**< Numbers represented to base 2*BASEBITS */
-#ifndef C99
-#define chunk __int64		/**< C type corresponding to word length */
-							/**< Note - no 128-bit type available    */
-#else
-#define chunk int64_t		/**< C type corresponding to word length */
-#ifdef __GNUC__
-#define dchunk __int128		/**< Always define double length chunk type if available - GCC supports 128 bit type  ??? */
-#endif
-#endif
-#endif
-
-/* Don't mess with anything below this line */
-
-#ifdef GET_STATS
-extern int tsqr,rsqr,tmul,rmul;
-extern int tadd,radd,tneg,rneg;
-extern int tdadd,rdadd,tdneg,rdneg;
-#endif
-
-#define DCHUNK 2*CHUNK	/**< Number of bits in double-length type */
-#define DNLEN 2*NLEN	/**< double length required for products of BIGs */
-
-#ifdef dchunk
-#define COMBA      /**< Use COMBA method for faster BN muls, sqrs and reductions */
-#endif
-
-#define CHUNK_BITS 8*sizeof(chunk) /**< Number of bits in a chunk */
-
-#ifdef DEBUG_NORM    /* Add an extra location to track chunk extension */
-typedef chunk BIG[NLEN+1]; /**< Define type BIG as array of chunks */
-typedef chunk DBIG[DNLEN+1]; /**< Define type DBIG as array of chunks */
-#else
-typedef chunk BIG[NLEN];  /**< Define type BIG as array of chunks */
-typedef chunk DBIG[DNLEN]; /**< Define type DBIG as array of chunks */
-#endif
-
-#define HBITS (BASEBITS/2)  /**< Number of bits in number base divided by 2 */
-#define HBITS1 ((BASEBITS+1)/2) /**< Number of bits in number base plus 1 divided by 2 */
-#define HDIFF (HBITS1-HBITS)  /**< Will be either 0 or 1, depending if number of bits in number base is even or odd */
-
-#define MASK (((chunk)1<<BASEBITS)-1) /**< Mask = 2^BASEBITS-1 */
-#define HMASK (((chunk)1<<HBITS)-1)   /**< Mask = 2^HBITS-1 */
-#define HMASK1 (((chunk)1<<HBITS1)-1) /**< Mask = 2^HBITS1-1 */
-
-#define MODBITS MBITS /**< Number of bits in Modulus for selected curve */
-#define MODBYTES 32   /**< Number of bytes in Modulus */
-#define MB (MBITS%BASEBITS) /**<  Number of bits in modulus mod number of bits in number base */
-#define TBITS (MBITS%BASEBITS) /**< Number of active bits in top word */
-#define TMASK (((chunk)1<<(MBITS%BASEBITS))-1)  /**< Mask for active bits in top word */
-#define NEXCESS (1<<(CHUNK-BASEBITS-1)) /**< 2^(CHUNK-BASEBITS-1) - digit cannot be multiplied by more than this before normalisation */
-#define FEXCESS ((chunk)1<<(BASEBITS*NLEN-MBITS)) /**< 2^(BASEBITS*NLEN-MODBITS) - normalised BIG can be multiplied by more than this before reduction */
-#define OMASK ((chunk)(-1)<<(MBITS%BASEBITS))     /**<  for masking out overflow bits */
-
-/* catch field excesses */
-#define EXCESS(a) ((a[NLEN-1]&OMASK)>>(MB))   /**< Field Excess */
-
-/* Field Params - see rom.c */
-extern const BIG Modulus;  /**< Actual Modulus set in rom.c */
-extern const chunk MConst; /**< Montgomery only - 1/p mod 2^BASEBITS */
-
-/* Curve Params - see rom.c */
-extern const int CURVE_A; /**< Elliptic curve A parameter */
-extern const BIG CURVE_B; /**< Elliptic curve B parameter */
-extern const BIG CURVE_Order; /**< Elliptic curve group order */
-
-/* Generator point on G1 */
-extern const BIG CURVE_Gx; /**< x-coordinate of generator point in group G1  */
-extern const BIG CURVE_Gy; /**< y-coordinate of generator point in group G1  */
-
-/* For Pairings only */
-
-/* Generator point on G2 */
-extern const BIG CURVE_Pxa; /**< real part of x-coordinate of generator point in group G2 */
-extern const BIG CURVE_Pxb; /**< imaginary part of x-coordinate of generator point in group G2 */
-extern const BIG CURVE_Pya; /**< real part of y-coordinate of generator point in group G2 */
-extern const BIG CURVE_Pyb; /**< imaginary part of y-coordinate of generator point in group G2 */
-
-extern const BIG CURVE_Bnx; /**< BN curve x parameter */
-
-extern const BIG CURVE_Cru; /**< BN curve Cube Root of Unity */
-
-extern const BIG CURVE_Fra; /**< real part of BN curve Frobenius Constant */
-extern const BIG CURVE_Frb; /**< imaginary part of BN curve Frobenius Constant */
-
-
-extern const BIG CURVE_W[2];		/**< BN curve constant for GLV decomposition */
-extern const BIG CURVE_SB[2][2];	/**< BN curve constant for GLV decomposition */
-extern const BIG CURVE_WB[4];		/**< BN curve constant for GS decomposition */
-extern const BIG CURVE_BB[4][4];	/**< BN curve constant for GS decomposition */
-
-/* Structures */
-
-/**
-	@brief ECP structure - Elliptic Curve Point over base field
-*/
-
-typedef struct {
-#if CURVETYPE!=EDWARDS
-int inf; /**< Infinity Flag - not needed for Edwards representation */
-#endif
-BIG x;   /**< x-coordinate of point */
-#if CURVETYPE!=MONTGOMERY
-BIG y;  /**< y-coordinate of point. Not needed for Montgomery representation */
-#endif
-BIG z; /**< z-coordinate of point */
-} ECP;
-
-/**
-	@brief FP2 Structure - quadratic extension field
-*/
-
-typedef struct {
-BIG a; /**< real part of FP2 */
-BIG b; /**< imaginary part of FP2 */
-} FP2;
-
-/**
-	@brief FP4 Structure - towered over two FP2
-*/
-
-typedef struct {
-FP2 a; /**< real part of FP4 */
-FP2 b; /**< imaginary part of FP4 */
-} FP4;
-
-/**
-	@brief FP12 Structure - towered over three FP4
-*/
-
-typedef struct {
-FP4 a; /**< first part of FP12 */
-FP4 b; /**< second part of FP12 */
-FP4 c; /**< third part of FP12 */
-} FP12;
-
-/**
-	@brief ECP2 Structure - Elliptic Curve Point over quadratic extension field
-*/
-
-typedef struct {
-int inf; /**< Infinity Flag */
-FP2 x;  /**< x-coordinate of point */
-FP2 y;  /**< y-coordinate of point */
-FP2 z;  /**< z-coordinate of point */
-} ECP2;
-
-/**
-	@brief SHA256 hash function instance
-*/
-
-typedef struct {
-unsign32 length[2];  /**< 64-bit input length */
-unsign32 h[8];       /**< Internal state */
-unsign32 w[64];		/**< Internal state */
-} hash;
-
-/* Symmetric Encryption AES structure */
-
-#define ECB   0  /**< Electronic Code Book */
-#define CBC   1  /**< Cipher Block Chaining */
-#define CFB1  2  /**< Cipher Feedback - 1 byte */
-#define CFB2  3  /**< Cipher Feedback - 2 bytes */
-#define CFB4  5  /**< Cipher Feedback - 4 bytes */
-#define OFB1  14 /**< Output Feedback - 1 byte */
-#define OFB2  15 /**< Output Feedback - 2 bytes */
-#define OFB4  17 /**< Output Feedback - 4 bytes */
-#define OFB8  21 /**< Output Feedback - 8 bytes */
-#define OFB16 29 /**< Output Feedback - 16 bytes */
-
-#define uchar unsigned char  /**<  Unsigned char */
-
-/**
-	@brief AES instance
-*/
-
-
-typedef struct {
-int mode;          /**< AES mode of operation */
-unsign32 fkey[44]; /**< subkeys for encrypton */
-unsign32 rkey[44]; /**< subkeys for decrypton */
-char f[16];        /**< buffer for chaining vector */
-} aes;
-
-/* AES-GCM suppport.  */
-
-#define GCM_ACCEPTING_HEADER 0 /**< GCM status */
-#define GCM_ACCEPTING_CIPHER 1 /**< GCM status */
-#define GCM_NOT_ACCEPTING_MORE 2 /**< GCM status */
-#define GCM_FINISHED 3 /**< GCM status */
-#define GCM_ENCRYPTING 0 /**< GCM mode */
-#define GCM_DECRYPTING 1 /**< GCM mode */
-
-
-/**
-	@brief GCM mode instance, using AES internally
-*/
-
-typedef struct {
-unsign32 table[128][4]; /**< 2k byte table */
-uchar stateX[16];	/**< GCM Internal State */
-uchar Y_0[16];		/**< GCM Internal State */
-unsign32 lenA[2];	/**< GCM 64-bit length of header */
-unsign32 lenC[2];	/**< GCM 64-bit length of ciphertext */
-int status;		/**< GCM Status */
-aes a;			/**< Internal Instance of AES cipher */
-} gcm;
-
-/* Marsaglia & Zaman Random number generator constants */
-
-#define NK   21 /**< PRNG constant */
-#define NJ   6 /**< PRNG constant */
-#define NV   8 /**< PRNG constant */
-
-
-/**
-	@brief Cryptographically secure pseudo-random number generator instance
-*/
-
-typedef struct {
-unsign32 ira[NK];  /**< random number array   */
-int      rndptr;   /**< pointer into array */
-unsign32 borrow;   /**<  borrow as a result of subtraction */
-int pool_ptr;		/**< pointer into random pool */
-char pool[32];		/**< random pool */
-} csprng;
-
-
-/**
-	@brief Portable representation of a big positive number
-*/
-
-typedef struct
-{
-    int len; /**< length in bytes  */
-    int max; /**< max length allowed - enforce truncation  */
-    char *val; /**< byte array  */
-} octet;
-
-/**
-	@brief Integer Factorisation Public Key
-*/
-
-typedef struct
-{
-    sign32 e;     /**< RSA exponent (typically 65537) */
-    BIG n[FFLEN]; /**< An array of BIGs to store public key */
-} rsa_public_key;
-
-/**
-	@brief Integer Factorisation Private Key
-*/
-
-typedef struct
-{
-    BIG p[FFLEN/2]; /**< secret prime p  */
-    BIG q[FFLEN/2]; /**< secret prime q  */
-    BIG dp[FFLEN/2]; /**< decrypting exponent mod (p-1)  */
-    BIG dq[FFLEN/2]; /**< decrypting exponent mod (q-1)  */
-    BIG c[FFLEN/2];  /**< 1/p mod q */
-} rsa_private_key;
-
-/*
-
-Note that a normalised BIG consists of digits mod 2^BASEBITS
-However BIG digits may be "extended" up to 2^(WORDLENGTH-1).
-
-BIGs in extended form may need to be normalised before certain
-operations.
-
-A BIG may be "reduced" to be less that the Modulus, or it
-may be "unreduced" and allowed to grow greater than the
-Modulus.
-
-Normalisation is quite fast. Reduction involves conditional branches,
-which can be regarded as significant "speed bumps". We try to
-delay reductions as much as possible. Reductions may also involve
-side channel leakage, so delaying and batching them
-hopefully disguises internal operations.
-
-*/
-
-/* BIG number prototypes */
-
-/**	@brief Calculates a*b+c+*d
- *
-	Calculate partial product of a.b, add in carry c, and add total to d
-	@param a multiplier
-	@param b multiplicand
-	@param c carry
-	@param d pointer to accumulated bottom half of result
-	@return top half of result
- */
-extern chunk muladd(chunk a,chunk b,chunk c,chunk *d);
-/**	@brief Tests for BIG equal to zero
- *
-	@param x a BIG number
-	@return 1 if zero, else returns 0
- */
-extern int BIG_iszilch(BIG x);
-/**	@brief Tests for DBIG equal to zero
- *
-	@param x a DBIG number
-	@return 1 if zero, else returns 0
- */
-extern int BIG_diszilch(DBIG x);
-/**	@brief Outputs a BIG number to the console
- *
-	@param x a BIG number
- */
-extern void BIG_output(BIG x);
-/**	@brief Outputs a BIG number to the console in raw form (for debugging)
- *
-	@param x a BIG number
- */
-extern void BIG_rawoutput(BIG x);
-/**	@brief Conditional constant time swap of two BIG numbers
- *
-	Conditionally swaps parameters in constant time (without branching)
-	@param x a BIG number
-	@param y another BIG number
-	@param s swap takes place if not equal to 0
- */
-extern void BIG_cswap(BIG x,BIG y,int s);
-/**	@brief Conditional copy of BIG number
- *
-	Conditionally copies second parameter to the first (without branching)
-	@param x a BIG number
-	@param y another BIG number
-	@param s copy takes place if not equal to 0
- */
-extern void BIG_cmove(BIG x,BIG y,int s);
-/**	@brief Convert from BIG number to byte array
- *
-	@param a byte array
-	@param x BIG number
- */
-extern void BIG_toBytes(char *a,BIG x);
-/**	@brief Convert to BIG number from byte array
- *
-	@param x BIG number
-	@param a byte array
- */
-extern void BIG_fromBytes(BIG x,char *a);
-/**	@brief Outputs a DBIG number to the console
- *
-	@param x a DBIG number
- */
-extern void BIG_doutput(DBIG x);
-/**	@brief Copy BIG from Read-Only Memory to a BIG
- *
-	@param x BIG number
-	@param y BIG number in ROM
- */
-extern void BIG_rcopy(BIG x,const BIG y);
-/**	@brief Copy BIG to another BIG
- *
-	@param x BIG number
-	@param y BIG number to be copied
- */
-extern void BIG_copy(BIG x,BIG y);
-/**	@brief Copy DBIG to another DBIG
- *
-	@param x DBIG number
-	@param y DBIG number to be copied
- */
-extern void BIG_dcopy(DBIG x,DBIG y);
-/**	@brief Copy BIG to upper half of DBIG
- *
-	@param x DBIG number
-	@param y BIG number to be copied
- */
-extern void BIG_dsucopy(DBIG x,BIG y);
-/**	@brief Copy BIG to lower half of DBIG
- *
-	@param x DBIG number
-	@param y BIG number to be copied
- */
-extern void BIG_dscopy(DBIG x,BIG y);
-/**	@brief Copy lower half of DBIG to a BIG
- *
-	@param x BIG number
-	@param y DBIG number to be copied
- */
-extern void BIG_sdcopy(BIG x,DBIG y);
-/**	@brief Copy upper half of DBIG to a BIG
- *
-	@param x BIG number
-	@param y DBIG number to be copied
- */
-extern void BIG_sducopy(BIG x,DBIG y);
-/**	@brief Set BIG to zero
- *
-	@param x BIG number to be set to zero
- */
-extern void BIG_zero(BIG x);
-/**	@brief Set DBIG to zero
- *
-	@param x DBIG number to be set to zero
- */
-extern void BIG_dzero(DBIG x);
-/**	@brief Set BIG to one (unity)
- *
-	@param x BIG number to be set to one.
- */
-extern void BIG_one(BIG x);
-/**	@brief Set BIG to inverse mod 2^256
- *
-	@param x BIG number to be inverted
- */
-extern void BIG_invmod2m(BIG x);
-/**	@brief Set BIG to sum of two BIGs - output not normalised
- *
-	@param x BIG number, sum of other two
-	@param y BIG number
-	@param z BIG number
- */
-extern void BIG_add(BIG x,BIG y,BIG z);
-/**	@brief Increment BIG by a small integer - output not normalised
- *
-	@param x BIG number to be incremented
-	@param i integer
- */
-extern void BIG_inc(BIG x,int i);
-/**	@brief Set BIG to difference of two BIGs
- *
-	@param x BIG number, difference of other two - output not normalised
-	@param y BIG number
-	@param z BIG number
- */
-extern void BIG_sub(BIG x,BIG y,BIG z);
-/**	@brief Decrement BIG by a small integer - output not normalised
- *
-	@param x BIG number to be decremented
-	@param i integer
- */
-extern void BIG_dec(BIG x,int i);
-/**	@brief Set DBIG to difference of two DBIGs
- *
-	@param x DBIG number, difference of other two - output not normalised
-	@param y DBIG number
-	@param z DBIG number
- */
-extern void BIG_dsub(DBIG x,DBIG y,DBIG z);
-/**	@brief Multiply BIG by a small integer - output not normalised
- *
-	@param x BIG number, product of other two
-	@param y BIG number
-	@param i small integer
- */
-extern void BIG_imul(BIG x,BIG y,int i);
-/**	@brief Multiply BIG by not-so-small small integer - output normalised
- *
-	@param x BIG number, product of other two
-	@param y BIG number
-	@param i small integer
-	@return Overflowing bits
- */
-extern chunk BIG_pmul(BIG x,BIG y,int i);
-/**	@brief Divide BIG by 3 - output normalised
- *
-	@param x BIG number
-	@return Remainder
- */
-extern int BIG_div3(BIG x);
-/**	@brief Multiply BIG by even bigger small integer resulting in a DBIG - output normalised
- *
-	@param x DBIG number, product of other two
-	@param y BIG number
-	@param i small integer
- */
-extern void BIG_pxmul(DBIG x,BIG y,int i);
-/**	@brief Multiply BIG by another BIG resulting in DBIG - inputs normalised and output normalised
- *
-	@param x DBIG number, product of other two
-	@param y BIG number
-	@param z BIG number
- */
-extern void BIG_mul(DBIG x,BIG y,BIG z);
-/**	@brief Multiply BIG by another BIG resulting in another BIG - inputs normalised and output normalised
- *
-	Note that the product must fit into a BIG, and x must be distinct from y and z
-	@param x BIG number, product of other two
-	@param y BIG number
-	@param z BIG number
- */
-extern void BIG_smul(BIG x,BIG y,BIG z);
-/**	@brief Square BIG resulting in a DBIG - input normalised and output normalised
- *
-	@param x DBIG number, square of a BIG
-	@param y BIG number to be squared
- */
-extern void BIG_sqr(DBIG x,BIG y);
-/**	@brief Shifts a BIG left by any number of bits - input must be normalised, output normalised
- *
-	@param x BIG number to be shifted
-	@param s Number of bits to shift
- */
-extern void BIG_shl(BIG x,int s);
-/**	@brief Fast shifts a BIG left by a small number of bits - input must be normalised, output will be normalised
- *
-	The number of bits to be shifted must be less than BASEBITS
-	@param x BIG number to be shifted
-	@param s Number of bits to shift
-	@return Overflow bits
- */
-extern chunk BIG_fshl(BIG x,int s);
-/**	@brief Shifts a DBIG left by any number of bits - input must be normalised, output normalised
- *
-	@param x DBIG number to be shifted
-	@param s Number of bits to shift
- */
-extern void BIG_dshl(DBIG x,int s);
-/**	@brief Shifts a BIG right by any number of bits - input must be normalised, output normalised
- *
-	@param x BIG number to be shifted
-	@param s Number of bits to shift
- */
-extern void BIG_shr(BIG x,int s);
-/**	@brief Fast shifts a BIG right by a small number of bits - input must be normalised, output will be normalised
- *
-	The number of bits to be shifted must be less than BASEBITS
-	@param x BIG number to be shifted
-	@param s Number of bits to shift
-	@return Shifted out bits
- */
-extern chunk BIG_fshr(BIG x,int s);
-/**	@brief Shifts a DBIG right by any number of bits - input must be normalised, output normalised
- *
-	@param x DBIG number to be shifted
-	@param s Number of bits to shift
- */
-extern void BIG_dshr(DBIG x,int s);
-/**	@brief Splits a DBIG into two BIGs - input must be normalised, outputs normalised
- *
-	Internal function. The value of s must be approximately in the middle of the DBIG.
-	Typically used to extract z mod 2^MODBITS and z/2^MODBITS
-	@param x BIG number, top half of z
-	@param y BIG number, bottom half of z
-	@param z DBIG number to be split in two.
-	@param s Bit position at which to split
- */
-extern void BIG_split(BIG x,BIG y,DBIG z,int s);
-/**	@brief Normalizes a BIG number - output normalised
- *
-	All digits of the input BIG are reduced mod 2^BASEBITS
-	@param x BIG number to be normalised
- */
-extern chunk BIG_norm(BIG x);
-/**	@brief Normalizes a DBIG number - output normalised
- *
-	All digits of the input DBIG are reduced mod 2^BASEBITS
-	@param x DBIG number to be normalised
- */
-extern void BIG_dnorm(DBIG x);
-/**	@brief Compares two BIG numbers. Inputs must be normalised externally
- *
-	@param x first BIG number to be compared
-	@param y second BIG number to be compared
-	@return -1 is x<y, 0 if x=y, 1 if x>y
- */
-extern int BIG_comp(BIG x,BIG y);
-/**	@brief Compares two DBIG numbers. Inputs must be normalised externally
- *
-	@param x first DBIG number to be compared
-	@param y second DBIG number to be compared
-	@return -1 is x<y, 0 if x=y, 1 if x>y
- */
-extern int BIG_dcomp(DBIG x,DBIG y);
-/**	@brief Calculate number of bits in a BIG - output normalised
- *
-	@param x BIG number
-	@return Number of bits in x
- */
-extern int BIG_nbits(BIG x);
-/**	@brief Calculate number of bits in a DBIG - output normalised
- *
-	@param x DBIG number
-	@return Number of bits in x
- */
-extern int BIG_dnbits(DBIG x);
-/**	@brief Reduce x mod n - input and output normalised
- *
-	Slow but rarely used
-	@param x BIG number to be reduced mod n
-	@param n The modulus
- */
-extern void BIG_mod(BIG x,BIG n);
-/**	@brief Divide x by n - output normalised
- *
-	Slow but rarely used
-	@param x BIG number to be divided by n
-	@param n The Divisor
- */
-extern void BIG_sdiv(BIG x,BIG n);
-/**	@brief  x=y mod n - output normalised
- *
-	Slow but rarely used. y is destroyed.
-	@param x BIG number, on exit = y mod n
-	@param y DBIG number
-	@param n Modulus
- */
-extern void BIG_dmod(BIG x,DBIG y,BIG n);
-/**	@brief  x=y/n - output normalised
- *
-	Slow but rarely used. y is destroyed.
-	@param x BIG number, on exit = y/n
-	@param y DBIG number
-	@param n Modulus
- */
-extern void BIG_ddiv(BIG x,DBIG y,BIG n);
-/**	@brief  return parity of BIG, that is the least significant bit
- *
-	@param x BIG number
-	@return 0 or 1
- */
-extern int BIG_parity(BIG x);
-/**	@brief  return i-th of BIG
- *
-	@param x BIG number
-	@param i the bit of x to be returned
-	@return 0 or 1
- */
-extern int BIG_bit(BIG x,int i);
-/**	@brief  return least significant bits of a BIG
- *
-	@param x BIG number
-	@param n number of bits to return. Assumed to be less than BASEBITS.
-	@return least significant n bits as an integer
- */
-extern int BIG_lastbits(BIG x,int n);
-/**	@brief  Create a random BIG from a random number generator
- *
-	Assumes that the random number generator has been suitably initialised
-	@param x BIG number, on exit a random number
-	@param r A pointer to a Cryptographically Secure Random Number Generator
- */
-extern void BIG_random(BIG x,csprng *r);
-/**	@brief  Create an unbiased random BIG from a random number generator, reduced with respect to a modulus
- *
-	Assumes that the random number generator has been suitably initialised
-	@param x BIG number, on exit a random number
-	@param n The modulus
-	@param r A pointer to a Cryptographically Secure Random Number Generator
- */
-extern void BIG_randomnum(BIG x,BIG n,csprng *r);
-/**	@brief  return NAF (Non-Adjacent-Form) value as +/- 1, 3 or 5, inputs must be normalised
- *
-	Given x and 3*x extracts NAF value from given bit position, and returns number of bits processed, and number of trailing zeros detected if any
-	@param x BIG number
-	@param x3 BIG number, three times x
-	@param i bit position
-	@param nbs pointer to integer returning number of bits processed
-	@param nzs pointer to integer returning number of trailing 0s
-	@return + or - 1, 3 or 5
- */
-extern int BIG_nafbits(BIG x,BIG x3,int i,int *nbs,int *nzs);
-/**	@brief  Calculate x=y*z mod n
- *
-	Slow method for modular multiplication
-	@param x BIG number, on exit = y*z mod n
-	@param y BIG number
-	@param z BIG number
-	@param n The BIG Modulus
- */
-extern void BIG_modmul(BIG x,BIG y,BIG z,BIG n);
-/**	@brief  Calculate x=y/z mod n
- *
-	Slow method for modular division
-	@param x BIG number, on exit = y/z mod n
-	@param y BIG number
-	@param z BIG number
-	@param n The BIG Modulus
- */
-extern void BIG_moddiv(BIG x,BIG y,BIG z,BIG n);
-/**	@brief  Calculate x=y^2 mod n
- *
-	Slow method for modular squaring
-	@param x BIG number, on exit = y^2 mod n
-	@param y BIG number
-	@param n The BIG Modulus
- */
-extern void BIG_modsqr(BIG x,BIG y,BIG n);
-/**	@brief  Calculate x=-y mod n
- *
-	Modular negation
-	@param x BIG number, on exit = -y mod n
-	@param y BIG number
-	@param n The BIG Modulus
- */
-extern void BIG_modneg(BIG x,BIG y,BIG n);
-/**	@brief  Calculate jacobi Symbol (x/y)
- *
-	@param x BIG number
-	@param y BIG number
-	@return Jacobi symbol, -1,0 or 1
- */
-extern int BIG_jacobi(BIG x,BIG y);
-/**	@brief  Calculate x=1/y mod n
- *
-	Modular Inversion - This is slow. Uses binary method.
-	@param x BIG number, on exit = 1/y mod n
-	@param y BIG number
-	@param n The BIG Modulus
- */
-extern void BIG_invmodp(BIG x,BIG y,BIG n);
-
-
-
-/* FP prototypes */
-
-/**	@brief Tests for BIG equal to zero mod Modulus
- *
-	@param x BIG number to be tested
-	@return 1 if zero, else returns 0
- */
-extern int FP_iszilch(BIG x);
-/**	@brief Converts from BIG integer to n-residue form mod Modulus
- *
-	@param x BIG number to be converted
- */
-extern void FP_nres(BIG x);
-/**	@brief Converts from n-residue form back to BIG integer form
- *
-	@param x BIG number to be converted
- */
-extern void FP_redc(BIG x);
-/**	@brief Sets BIG to representation of unity in n-residue form
- *
-	@param x BIG number to be set equal to unity.
- */
-extern void FP_one(BIG x);
-/**	@brief Reduces DBIG to BIG exploiting special form of the modulus
- *
-	This function comes in different flavours depending on the form of Modulus that is currently in use.
-	@param x BIG number, on exit = y mod Modulus
-	@param y DBIG number to be reduced
- */
-extern void FP_mod(BIG x,DBIG y);
-/**	@brief Fast Modular multiplication of two BIGs in n-residue form, mod Modulus
- *
-	Uses appropriate fast modular reduction method
-	@param x BIG number, on exit the modular product = y*z mod Modulus
-	@param y BIG number, the multiplicand
-	@param z BIG number, the multiplier
- */
-extern void FP_mul(BIG x,BIG y,BIG z);
-/**	@brief Fast Modular multiplication of a BIG in n-residue form, by a small integer, mod Modulus
- *
-	@param x BIG number, on exit the modular product = y*i mod Modulus
-	@param y BIG number, the multiplicand
-	@param i a small number, the multiplier
- */
-extern void FP_imul(BIG x,BIG y,int i);
-/**	@brief Fast Modular squaring of a BIG in n-residue form, mod Modulus
- *
-	Uses appropriate fast modular reduction method
-	@param x BIG number, on exit the modular product = y^2 mod Modulus
-	@param y BIG number, the number to be squared
-
- */
-extern void FP_sqr(BIG x,BIG y);
-/**	@brief Modular addition of two BIGs in n-residue form, mod Modulus
- *
-	@param x BIG number, on exit the modular sum = y+z mod Modulus
-	@param y BIG number
-	@param z BIG number
- */
-extern void FP_add(BIG x,BIG y,BIG z);
-/**	@brief Modular subtraction of two BIGs in n-residue form, mod Modulus
- *
-	@param x BIG number, on exit the modular difference = y-z mod Modulus
-	@param y BIG number
-	@param z BIG number
- */
-extern void FP_sub(BIG x,BIG y,BIG z);
-/**	@brief Modular division by 2 of a BIG in n-residue form, mod Modulus
- *
-	@param x BIG number, on exit =y/2 mod Modulus
-	@param y BIG number
- */
-extern void FP_div2(BIG x,BIG y);
-/**	@brief Fast Modular exponentiation of a BIG in n-residue form, to the power of a BIG, mod Modulus
- *
-	@param x BIG number, on exit  = y^z mod Modulus
-	@param y BIG number
-	@param z Big number exponent
- */
-extern void FP_pow(BIG x,BIG y,BIG z);
-/**	@brief Fast Modular square root of a BIG in n-residue form, mod Modulus
- *
-	@param x BIG number, on exit  = sqrt(y) mod Modulus
-	@param y BIG number, the number whose square root is calculated
-
- */
-extern void FP_sqrt(BIG x,BIG y);
-/**	@brief Modular negation of a BIG in n-residue form, mod Modulus
- *
-	@param x BIG number, on exit = -y mod Modulus
-	@param y BIG number
- */
-extern void FP_neg(BIG x,BIG y);
-/**	@brief Outputs a BIG number that is in n-residue form to the console
- *
-	Converts from n-residue form before output
-	@param x a BIG number
- */
-extern void FP_output(BIG x);
-/**	@brief Outputs a BIG number that is in n-residue form to the console, in raw form
- *
-	Converts from n-residue form before output
-	@param x a BIG number
- */
-extern void FP_rawoutput(BIG x);
-/**	@brief Reduces possibly unreduced BIG mod Modulus
- *
-	@param x BIG number, on exit reduced mod Modulus
- */
-extern void FP_reduce(BIG x);
-/**	@brief Tests for BIG a quadratic residue mod Modulus
- *
-	@param x BIG number to be tested
-	@return 1 if quadratic residue, else returns 0 if quadratic non-residue
- */
-extern int FP_qr(BIG x);
-/**	@brief Modular inverse of a BIG in n-residue form, mod Modulus
- *
-	@param x BIG number, on exit = 1/y mod Modulus
-	@param y BIG number
- */
-extern void FP_inv(BIG x,BIG y);
-
-
-/* FP2 prototypes */
-
-/**	@brief Tests for FP2 equal to zero
- *
-	@param x FP2 number to be tested
-	@return 1 if zero, else returns 0
- */
-extern int FP2_iszilch(FP2 *x);
-/**	@brief Conditional copy of FP2 number
- *
-	Conditionally copies second parameter to the first (without branching)
-	@param x FP2 instance, set to y if s!=0
-	@param y another FP2 instance
-	@param s copy only takes place if not equal to 0
- */
-extern void FP2_cmove(FP2 *x,FP2 *y,int s);
-/**	@brief Tests for FP2 equal to one
- *
-	@param x FP2 instance to be tested
-	@return 1 if x=1, else returns 0
- */
-extern int FP2_isunity(FP2 *x);
-/**	@brief Tests for equality of two FP2s
- *
-	@param x FP2 instance to be compared
-	@param y FP2 instance to be compared
-	@return 1 if x=y, else returns 0
- */
-extern int FP2_equals(FP2 *x,FP2 *y);
-/**	@brief Initialise FP2 from two BIGs in n-residue form
- *
-	@param x FP2 instance to be initialised
-	@param a BIG to form real part of FP2
-	@param b BIG to form imaginary part of FP2
- */
-extern void FP2_from_FPs(FP2 *x,BIG a,BIG b);
-/**	@brief Initialise FP2 from two BIG integers
- *
-	@param x FP2 instance to be initialised
-	@param a BIG to form real part of FP2
-	@param b BIG to form imaginary part of FP2
- */
-extern void FP2_from_BIGs(FP2 *x,BIG a,BIG b);
-/**	@brief Initialise FP2 from single BIG in n-residue form
- *
-	Imaginary part is set to zero
-	@param x FP2 instance to be initialised
-	@param a BIG to form real part of FP2
- */
-extern void FP2_from_FP(FP2 *x,BIG a);
-/**	@brief Initialise FP2 from single BIG
- *
-	Imaginary part is set to zero
-	@param x FP2 instance to be initialised
-	@param a BIG to form real part of FP2
- */
-extern void FP2_from_BIG(FP2 *x,BIG a);
-/**	@brief Copy FP2 to another FP2
- *
-	@param x FP2 instance, on exit = y
-	@param y FP2 instance to be copied
- */
-extern void FP2_copy(FP2 *x,FP2 *y);
-/**	@brief Set FP2 to zero
- *
-	@param x FP2 instance to be set to zero
- */
-extern void FP2_zero(FP2 *x);
-/**	@brief Set FP2 to unity
- *
-	@param x FP2 instance to be set to one
- */
-extern void FP2_one(FP2 *x);
-/**	@brief Negation of FP2
- *
-	@param x FP2 instance, on exit = -y
-	@param y FP2 instance
- */
-extern void FP2_neg(FP2 *x,FP2 *y);
-/**	@brief Conjugation of FP2
- *
-	If y=(a,b) on exit x=(a,-b)
-	@param x FP2 instance, on exit = conj(y)
-	@param y FP2 instance
- */
-extern void FP2_conj(FP2 *x,FP2 *y);
-/**	@brief addition of two FP2s
- *
-	@param x FP2 instance, on exit = y+z
-	@param y FP2 instance
-	@param z FP2 instance
- */
-extern void FP2_add(FP2 *x,FP2 *y,FP2 *z);
-/**	@brief subtraction of two FP2s
- *
-	@param x FP2 instance, on exit = y-z
-	@param y FP2 instance
-	@param z FP2 instance
- */
-extern void FP2_sub(FP2 *x,FP2 *y,FP2 *z);
-/**	@brief Multiplication of an FP2 by an n-residue
- *
-	@param x FP2 instance, on exit = y*b
-	@param y FP2 instance
-	@param b BIG n-residue
- */
-extern void FP2_pmul(FP2 *x,FP2 *y,BIG b);
-/**	@brief Multiplication of an FP2 by a small integer
- *
-	@param x FP2 instance, on exit = y*i
-	@param y FP2 instance
-	@param i an integer
- */
-extern void FP2_imul(FP2 *x,FP2 *y,int i);
-/**	@brief Squaring an FP2
- *
-	@param x FP2 instance, on exit = y^2
-	@param y FP2 instance
- */
-extern void FP2_sqr(FP2 *x,FP2 *y);
-/**	@brief Multiplication of two FP2s
- *
-	@param x FP2 instance, on exit = y*z
-	@param y FP2 instance
-	@param z FP2 instance
- */
-extern void FP2_mul(FP2 *x,FP2 *y,FP2 *z);
-/**	@brief Formats and outputs an FP2 to the console
- *
-	@param x FP2 instance
- */
-extern void FP2_output(FP2 *x);
-/**	@brief Formats and outputs an FP2 to the console in raw form (for debugging)
- *
-	@param x FP2 instance
- */
-extern void FP2_rawoutput(FP2 *x);
-/**	@brief Inverting an FP2
- *
-	@param x FP2 instance, on exit = 1/y
-	@param y FP2 instance
- */
-extern void FP2_inv(FP2 *x,FP2 *y);
-/**	@brief Divide an FP2 by 2
- *
-	@param x FP2 instance, on exit = y/2
-	@param y FP2 instance
- */
-extern void FP2_div2(FP2 *x,FP2 *y);
-/**	@brief Multiply an FP2 by (1+sqrt(-1))
- *
-	Note that (1+sqrt(-1)) is irreducible for FP4
-	@param x FP2 instance, on exit = x*(1+sqrt(-1))
- */
-extern void FP2_mul_ip(FP2 *x);
-/**	@brief Divide an FP2 by (1+sqrt(-1))
- *
-	Note that (1+sqrt(-1)) is irreducible for FP4
-	@param x FP2 instance, on exit = x/(1+sqrt(-1))
- */
-extern void FP2_div_ip(FP2 *x);
-/**	@brief Normalises the components of an FP2
- *
-	@param x FP2 instance to be normalised
- */
-extern void FP2_norm(FP2 *x);
-/**	@brief Reduces all components of possibly unreduced FP2 mod Modulus
- *
-	@param x FP2 instance, on exit reduced mod Modulus
- */
-extern void FP2_reduce(FP2 *x);
-/**	@brief Raises an FP2 to the power of a BIG
- *
-	@param x FP2 instance, on exit = y^b
-	@param y FP2 instance
-	@param b BIG number
- */
-extern void FP2_pow(FP2 *x,FP2 *y,BIG b);
-/**	@brief Square root of an FP2
- *
-	@param x FP2 instance, on exit = sqrt(y)
-	@param y FP2 instance
- */
-extern int FP2_sqrt(FP2 *x,FP2 *y);
-
-
-
-/* ECP E(Fp) prototypes */
-/**	@brief Tests for ECP point equal to infinity
- *
-	@param P ECP point to be tested
-	@return 1 if infinity, else returns 0
- */
-extern int ECP_isinf(ECP *P);
-/**	@brief Tests for equality of two ECPs
- *
-	@param P ECP instance to be compared
-	@param Q ECP instance to be compared
-	@return 1 if P=Q, else returns 0
- */
-extern int ECP_equals(ECP *P,ECP *Q);
-/**	@brief Copy ECP point to another ECP point
- *
-	@param P ECP instance, on exit = Q
-	@param Q ECP instance to be copied
- */
-extern void ECP_copy(ECP *P,ECP *Q);
-/**	@brief Negation of an ECP point
- *
-	@param P ECP instance, on exit = -P
- */
-extern void ECP_neg(ECP *P);
-/**	@brief Set ECP to point-at-infinity
- *
-	@param P ECP instance to be set to infinity
- */
-extern void ECP_inf(ECP *P);
-/**	@brief Calculate Right Hand Side of curve equation y^2=f(x)
- *
-	Function f(x) depends on form of elliptic curve, Weierstrass, Edwards or Montgomery.
-	Used internally.
-	@param r BIG n-residue value of f(x)
-	@param x BIG n-residue x
- */
-extern void ECP_rhs(BIG r,BIG x);
-/**	@brief Set ECP to point(x,y) given just x and sign of y
- *
-	Point P set to infinity if no such point on the curve. If x is on the curve then y is calculated from the curve equation.
-	The correct y value (plus or minus) is selected given its sign s.
-	@param P ECP instance to be set (x,[y])
-	@param x BIG x coordinate of point
-	@param s an integer representing the "sign" of y, in fact its least significant bit.
- */
-extern int ECP_setx(ECP *P,BIG x,int s);
-
-#if CURVETYPE==MONTGOMERY
-/**	@brief Set ECP to point(x,[y]) given x
- *
-	Point P set to infinity if no such point on the curve. Note that y coordinate is not needed.
-	@param P ECP instance to be set (x,[y])
-	@param x BIG x coordinate of point
-	@return 1 if point exists, else 0
- */
-extern int ECP_set(ECP *P,BIG x);
-/**	@brief Extract x coordinate of an ECP point P
- *
-	@param x BIG on exit = x coordinate of point
-	@param P ECP instance (x,[y])
-	@return -1 if P is point-at-infinity, else 0
- */
-extern int ECP_get(BIG x,ECP *P);
-/**	@brief Adds ECP instance Q to ECP instance P, given difference D=P-Q
- *
-	Differential addition of points on a Montgomery curve
-	@param P ECP instance, on exit =P+Q
-	@param Q ECP instance to be added to P
-	@param D Difference between P and Q
- */
-extern void ECP_add(ECP *P,ECP *Q,ECP *D);
-#else
-/**	@brief Set ECP to point(x,y) given x and y
- *
-	Point P set to infinity if no such point on the curve.
-	@param P ECP instance to be set (x,y)
-	@param x BIG x coordinate of point
-	@param y BIG y coordinate of point
-	@return 1 if point exists, else 0
- */
-extern int ECP_set(ECP *P,BIG x,BIG y);
-/**	@brief Extract x and y coordinates of an ECP point P
- *
-	If x=y, returns only x
-	@param x BIG on exit = x coordinate of point
-	@param y BIG on exit = y coordinate of point (unless x=y)
-	@param P ECP instance (x,y)
-	@return sign of y, or -1 if P is point-at-infinity
- */
-extern int ECP_get(BIG x,BIG y,ECP *P);
-/**	@brief Adds ECP instance Q to ECP instance P
- *
-	@param P ECP instance, on exit =P+Q
-	@param Q ECP instance to be added to P
- */
-extern void ECP_add(ECP *P,ECP *Q);
-/**	@brief Subtracts ECP instance Q from ECP instance P
- *
-	@param P ECP instance, on exit =P-Q
-	@param Q ECP instance to be subtracted from P
- */
-extern void ECP_sub(ECP *P,ECP *Q);
-#endif
-/**	@brief Converts an ECP point from Projective (x,y,z) coordinates to affine (x,y) coordinates
- *
-	@param P ECP instance to be converted to affine form
- */
-extern void ECP_affine(ECP *P);
-/**	@brief Formats and outputs an ECP point to the console, in projective coordinates
- *
-	@param P ECP instance to be printed
- */
-extern void ECP_outputxyz(ECP *P);
-/**	@brief Formats and outputs an ECP point to the console, converted to affine coordinates
- *
-	@param P ECP instance to be printed
- */
-extern void ECP_output(ECP * P);
-/**	@brief Formats and outputs an ECP point to an octet string
- *
-	The octet string is created in the standard form 04|x|y, except for Montgomery curve in which case it is 06|x
-	Here x (and y) are the x and y coordinates in big-endian base 256 form.
-	@param S output octet string
-	@param P ECP instance to be converted to an octet string
- */
-extern void ECP_toOctet(octet *S,ECP *P);
-/**	@brief Creates an ECP point from an octet string
- *
-	The octet string is in the standard form 0x04|x|y, except for Montgomery curve in which case it is 0x06|x
-	Here x (and y) are the x and y coordinates in left justified big-endian base 256 form.
-	@param P ECP instance to be created from the octet string
-	@param S input octet string
-	return 1 if octet string corresponds to a point on the curve, else 0
- */
-extern int ECP_fromOctet(ECP *P,octet *S);
-/**	@brief Doubles an ECP instance P
- *
-	@param P ECP instance, on exit =2*P
- */
-extern void ECP_dbl(ECP *P);
-/**	@brief Multiplies an ECP instance P by a small integer, side-channel resistant
- *
-	@param P ECP instance, on exit =i*P
-	@param i small integer multiplier
-	@param b maximum number of bits in multiplier
- */
-extern void ECP_pinmul(ECP *P,int i,int b);
-/**	@brief Multiplies an ECP instance P by a BIG, side-channel resistant
- *
-	Uses Montgomery ladder for Montgomery curves, otherwise fixed sized windows.
-	@param P ECP instance, on exit =b*P
-	@param b BIG number multiplier
-
- */
-extern void ECP_mul(ECP *P,BIG b);
-/**	@brief Calculates double multiplication P=e*P+f*Q, side-channel resistant
- *
-	@param P ECP instance, on exit =e*P+f*Q
-	@param Q ECP instance
-	@param e BIG number multiplier
-	@param f BIG number multiplier
- */
-extern void ECP_mul2(ECP *P,ECP *Q,BIG e,BIG f);
-
-
-
-/* ECP2 E(Fp2) prototypes */
-/**	@brief Tests for ECP2 point equal to infinity
- *
-	@param P ECP2 point to be tested
-	@return 1 if infinity, else returns 0
- */
-extern int ECP2_isinf(ECP2 *P);
-/**	@brief Copy ECP2 point to another ECP2 point
- *
-	@param P ECP2 instance, on exit = Q
-	@param Q ECP2 instance to be copied
- */
-extern void ECP2_copy(ECP2 *P,ECP2 *Q);
-/**	@brief Set ECP2 to point-at-infinity
- *
-	@param P ECP2 instance to be set to infinity
- */
-extern void ECP2_inf(ECP2 *P);
-/**	@brief Tests for equality of two ECP2s
- *
-	@param P ECP2 instance to be compared
-	@param Q ECP2 instance to be compared
-	@return 1 if P=Q, else returns 0
- */
-extern int ECP2_equals(ECP2 *P,ECP2 *Q);
-/**	@brief Converts an ECP2 point from Projective (x,y,z) coordinates to affine (x,y) coordinates
- *
-	@param P ECP2 instance to be converted to affine form
- */
-extern void ECP2_affine(ECP2 *P);
-/**	@brief Extract x and y coordinates of an ECP2 point P
- *
-	If x=y, returns only x
-	@param x FP2 on exit = x coordinate of point
-	@param y FP2 on exit = y coordinate of point (unless x=y)
-	@param P ECP2 instance (x,y)
-	@return -1 if P is point-at-infinity, else 0
- */
-extern int ECP2_get(FP2 *x,FP2 *y,ECP2 *P);
-/**	@brief Formats and outputs an ECP2 point to the console, converted to affine coordinates
- *
-	@param P ECP2 instance to be printed
- */
-extern void ECP2_output(ECP2 *P);
-/**	@brief Formats and outputs an ECP2 point to the console, in projective coordinates
- *
-	@param P ECP2 instance to be printed
- */
-extern void ECP2_outputxyz(ECP2 *P);
-/**	@brief Formats and outputs an ECP2 point to an octet string
- *
-	The octet string is created in the form x|y.
-	Convert the real and imaginary parts of the x and y coordinates to big-endian base 256 form.
-	@param S output octet string
-	@param P ECP2 instance to be converted to an octet string
- */
-extern void ECP2_toOctet(octet *S,ECP2 *P);
-/**	@brief Creates an ECP2 point from an octet string
- *
-	The octet string is in the form x|y
-	The real and imaginary parts of the x and y coordinates are in big-endian base 256 form.
-	@param P ECP2 instance to be created from the octet string
-	@param S input octet string
-	return 1 if octet string corresponds to a point on the curve, else 0
- */
-extern int ECP2_fromOctet(ECP2 *P,octet *S);
-/**	@brief Calculate Right Hand Side of curve equation y^2=f(x)
- *
-	Function f(x)=x^3+Ax+B
-	Used internally.
-	@param r FP2 value of f(x)
-	@param x FP2 instance
- */
-extern void ECP2_rhs(FP2 *r,FP2 *x);
-/**	@brief Set ECP2 to point(x,y) given x and y
- *
-	Point P set to infinity if no such point on the curve.
-	@param P ECP2 instance to be set (x,y)
-	@param x FP2 x coordinate of point
-	@param y FP2 y coordinate of point
-	@return 1 if point exists, else 0
- */
-extern int ECP2_set(ECP2 *P,FP2 *x,FP2 *y);
-/**	@brief Set ECP to point(x,[y]) given x
- *
-	Point P set to infinity if no such point on the curve. Otherwise y coordinate is calculated from x.
-	@param P ECP instance to be set (x,[y])
-	@param x BIG x coordinate of point
-	@return 1 if point exists, else 0
- */
-extern int ECP2_setx(ECP2 *P,FP2 *x);
-/**	@brief Negation of an ECP2 point
- *
-	@param P ECP2 instance, on exit = -P
- */
-extern void ECP2_neg(ECP2 *P);
-/**	@brief Doubles an ECP2 instance P
- *
-	@param P ECP2 instance, on exit =2*P
- */
-extern int ECP2_dbl(ECP2 *P);
-/**	@brief Adds ECP2 instance Q to ECP2 instance P
- *
-	@param P ECP2 instance, on exit =P+Q
-	@param Q ECP2 instance to be added to P
- */
-extern int ECP2_add(ECP2 *P,ECP2 *Q);
-/**	@brief Subtracts ECP instance Q from ECP2 instance P
- *
-	@param P ECP2 instance, on exit =P-Q
-	@param Q ECP2 instance to be subtracted from P
- */
-extern void ECP2_sub(ECP2 *P,ECP2 *Q);
-/**	@brief Multiplies an ECP2 instance P by a BIG, side-channel resistant
- *
-	Uses fixed sized windows.
-	@param P ECP2 instance, on exit =b*P
-	@param b BIG number multiplier
-
- */
-extern void ECP2_mul(ECP2 *P,BIG b);
-/**	@brief Multiplies an ECP2 instance P by the internal modulus p, using precalculated Frobenius constant f
- *
-	Fast point multiplication using Frobenius
-	@param P ECP2 instance, on exit = p*P
-	@param f FP2 precalculated Frobenius constant
-
- */
-extern void ECP2_frob(ECP2 *P,FP2 *f);
-/**	@brief Calculates P=b[0]*Q[0]+b[1]*Q[1]+b[2]*Q[2]+b[3]*Q[3]
- *
-	@param P ECP2 instance, on exit = b[0]*Q[0]+b[1]*Q[1]+b[2]*Q[2]+b[3]*Q[3]
-	@param Q ECP2 array of 4 points
-	@param b BIG array of 4 multipliers
- */
-extern void ECP2_mul4(ECP2 *P,ECP2 *Q,BIG *b);
-
-
-
-/* FP4 prototypes */
-/**	@brief Tests for FP4 equal to zero
- *
-	@param x FP4 number to be tested
-	@return 1 if zero, else returns 0
- */
-extern int FP4_iszilch(FP4 *x);
-/**	@brief Tests for FP4 equal to unity
- *
-	@param x FP4 number to be tested
-	@return 1 if unity, else returns 0
- */
-extern int FP4_isunity(FP4 *x);
-/**	@brief Tests for equality of two FP4s
- *
-	@param x FP4 instance to be compared
-	@param y FP4 instance to be compared
-	@return 1 if x=y, else returns 0
- */
-extern int FP4_equals(FP4 *x,FP4 *y);
-/**	@brief Tests for FP4 having only a real part and no imaginary part
- *
-	@param x FP4 number to be tested
-	@return 1 if real, else returns 0
- */
-extern int FP4_isreal(FP4 *x);
-/**	@brief Initialise FP4 from two FP2s
- *
-	@param x FP4 instance to be initialised
-	@param a FP2 to form real part of FP4
-	@param b FP2 to form imaginary part of FP4
- */
-extern void FP4_from_FP2s(FP4 *x,FP2 *a,FP2 *b);
-/**	@brief Initialise FP4 from single FP2
- *
-	Imaginary part is set to zero
-	@param x FP4 instance to be initialised
-	@param a FP2 to form real part of FP4
- */
-extern void FP4_from_FP2(FP4 *x,FP2 *a);
-/**	@brief Copy FP4 to another FP4
- *
-	@param x FP4 instance, on exit = y
-	@param y FP4 instance to be copied
- */
-extern void FP4_copy(FP4 *x,FP4 *y);
-/**	@brief Set FP4 to zero
- *
-	@param x FP4 instance to be set to zero
- */
-extern void FP4_zero(FP4 *x);
-/**	@brief Set FP4 to unity
- *
-	@param x FP4 instance to be set to one
- */
-extern void FP4_one(FP4 *x);
-/**	@brief Negation of FP4
- *
-	@param x FP4 instance, on exit = -y
-	@param y FP4 instance
- */
-extern void FP4_neg(FP4 *x,FP4 *y);
-/**	@brief Conjugation of FP4
- *
-	If y=(a,b) on exit x=(a,-b)
-	@param x FP4 instance, on exit = conj(y)
-	@param y FP4 instance
- */
-extern void FP4_conj(FP4 *x,FP4 *y);
-/**	@brief Negative conjugation of FP4
- *
-	If y=(a,b) on exit x=(-a,b)
-	@param x FP4 instance, on exit = -conj(y)
-	@param y FP4 instance
- */
-extern void FP4_nconj(FP4 *x,FP4 *y);
-/**	@brief addition of two FP4s
- *
-	@param x FP4 instance, on exit = y+z
-	@param y FP4 instance
-	@param z FP4 instance
- */
-extern void FP4_add(FP4 *x,FP4 *y,FP4 *z);
-/**	@brief subtraction of two FP4s
- *
-	@param x FP4 instance, on exit = y-z
-	@param y FP4 instance
-	@param z FP4 instance
- */
-extern void FP4_sub(FP4 *x,FP4 *y,FP4 *z);
-/**	@brief Multiplication of an FP4 by an FP2
- *
-	@param x FP4 instance, on exit = y*a
-	@param y FP4 instance
-	@param a FP2 multiplier
- */
-extern void FP4_pmul(FP4 *x,FP4 *y,FP2 *a);
-/**	@brief Multiplication of an FP4 by a small integer
- *
-	@param x FP4 instance, on exit = y*i
-	@param y FP4 instance
-	@param i an integer
- */
-extern void FP4_imul(FP4 *x,FP4 *y,int i);
-/**	@brief Squaring an FP4
- *
-	@param x FP4 instance, on exit = y^2
-	@param y FP4 instance
- */
-extern void FP4_sqr(FP4 *x,FP4 *y);
-/**	@brief Multiplication of two FP4s
- *
-	@param x FP4 instance, on exit = y*z
-	@param y FP4 instance
-	@param z FP4 instance
- */
-extern void FP4_mul(FP4 *x,FP4 *y,FP4 *z);
-/**	@brief Inverting an FP4
- *
-	@param x FP4 instance, on exit = 1/y
-	@param y FP4 instance
- */
-extern void FP4_inv(FP4 *x,FP4 *y);
-/**	@brief Formats and outputs an FP4 to the console
- *
-	@param x FP4 instance to be printed
- */
-extern void FP4_output(FP4 *x);
-/**	@brief Formats and outputs an FP4 to the console in raw form (for debugging)
- *
-	@param x FP4 instance to be printed
- */
-extern void FP4_rawoutput(FP4 *x);
-/**	@brief multiplies an FP4 instance by irreducible polynomial sqrt(1+sqrt(-1))
- *
-	@param x FP4 instance, on exit = sqrt(1+sqrt(-1)*x
- */
-extern void FP4_times_i(FP4 *x);
-/**	@brief Normalises the components of an FP4
- *
-	@param x FP4 instance to be normalised
- */
-extern void FP4_norm(FP4 *x);
-/**	@brief Reduces all components of possibly unreduced FP4 mod Modulus
- *
-	@param x FP4 instance, on exit reduced mod Modulus
- */
-extern void FP4_reduce(FP4 *x);
-/**	@brief Raises an FP4 to the power of a BIG
- *
-	@param x FP4 instance, on exit = y^b
-	@param y FP4 instance
-	@param b BIG number
- */
-extern void FP4_pow(FP4 *x,FP4 *y,BIG b);
-/**	@brief Raises an FP4 to the power of the internal modulus p, using the Frobenius
- *
-	@param x FP4 instance, on exit = x^p
-	@param f FP2 precalculated Frobenius constant
- */
-extern void FP4_frob(FP4 *x,FP2 *f);
-/**	@brief Calculates the XTR addition function r=w*x-conj(x)*y+z
- *
-	@param r FP4 instance, on exit = w*x-conj(x)*y+z
-	@param w FP4 instance
-	@param x FP4 instance
-	@param y FP4 instance
-	@param z FP4 instance
- */
-extern void FP4_xtr_A(FP4 *r,FP4 *w,FP4 *x,FP4 *y,FP4 *z);
-/**	@brief Calculates the XTR doubling function r=x^2-2*conj(x)
- *
-	@param r FP4 instance, on exit = x^2-2*conj(x)
-	@param x FP4 instance
- */
-extern void FP4_xtr_D(FP4 *r,FP4 *x);
-/**	@brief Calculates FP4 trace of an FP12 raised to the power of a BIG number
- *
-	XTR single exponentiation
-	@param r FP4 instance, on exit = trace(w^b)
-	@param x FP4 instance, trace of an FP12 w
-	@param b BIG number
- */
-extern void FP4_xtr_pow(FP4 *r,FP4 *x,BIG b);
-/**	@brief Calculates FP4 trace of c^a.d^b, where c and d are derived from FP4 traces of FP12s
- *
-	XTR double exponentiation
-	Assumes c=tr(x^m), d=tr(x^n), e=tr(x^(m-n)), f=tr(x^(m-2n))
-	@param r FP4 instance, on exit = trace(c^a.d^b)
-	@param c FP4 instance, trace of an FP12
-	@param d FP4 instance, trace of an FP12
-	@param e FP4 instance, trace of an FP12
-	@param f FP4 instance, trace of an FP12
-	@param a BIG number
-	@param b BIG number
- */
-extern void FP4_xtr_pow2(FP4 *r,FP4 *c,FP4 *d,FP4 *e,FP4 *f,BIG a,BIG b);
-
-
-
-/* FP12 prototypes */
-/**	@brief Tests for FP12 equal to zero
- *
-	@param x FP12 number to be tested
-	@return 1 if zero, else returns 0
- */
-extern int FP12_iszilch(FP12 *x);
-/**	@brief Tests for FP12 equal to unity
- *
-	@param x FP12 number to be tested
-	@return 1 if unity, else returns 0
- */
-extern int FP12_isunity(FP12 *x);
-/**	@brief Copy FP12 to another FP12
- *
-	@param x FP12 instance, on exit = y
-	@param y FP12 instance to be copied
- */
-extern void FP12_copy(FP12 *x,FP12 *y);
-/**	@brief Set FP12 to unity
- *
-	@param x FP12 instance to be set to one
- */
-extern void FP12_one(FP12 *x);
-/**	@brief Tests for equality of two FP12s
- *
-	@param x FP12 instance to be compared
-	@param y FP12 instance to be compared
-	@return 1 if x=y, else returns 0
- */
-extern int FP12_equals(FP12 *x,FP12 *y);
-/**	@brief Conjugation of FP12
- *
-	If y=(a,b,c) (where a,b,c are its three FP4 components) on exit x=(conj(a),-conj(b),conj(c))
-	@param x FP12 instance, on exit = conj(y)
-	@param y FP12 instance
- */
-extern void FP12_conj(FP12 *x,FP12 *y);
-/**	@brief Initialise FP12 from single FP4
- *
-	Sets first FP4 component of an FP12, other components set to zero
-	@param x FP12 instance to be initialised
-	@param a FP4 to form first part of FP4
- */
-extern void FP12_from_FP4(FP12 *x,FP4 *a);
-/**	@brief Initialise FP12 from three FP4s
- *
-	@param x FP12 instance to be initialised
-	@param a FP4 to form first part of FP12
-	@param b FP4 to form second part of FP12
-	@param c FP4 to form third part of FP12
- */
-extern void FP12_from_FP4s(FP12 *x,FP4 *a,FP4* b,FP4 *c);
-/**	@brief Fast Squaring of an FP12 in "unitary" form
- *
-	@param x FP12 instance, on exit = y^2
-	@param y FP4 instance, must be unitary
- */
-extern void FP12_usqr(FP12 *x,FP12 *y);
-/**	@brief Squaring an FP12
- *
-	@param x FP12 instance, on exit = y^2
-	@param y FP12 instance
- */
-extern void FP12_sqr(FP12 *x,FP12 *y);
-/**	@brief Fast multiplication of an FP12 by an FP12 that arises from an ATE pairing line function
- *
-	Here the multiplier has a special form that can be exploited
-	@param x FP12 instance, on exit = x*y
-	@param y FP12 instance, of special form
- */
-extern void FP12_smul(FP12 *x,FP12 *y);
-/**	@brief Multiplication of two FP12s
- *
-	@param x FP12 instance, on exit = x*y
-	@param y FP12 instance, the multiplier
- */
-extern void FP12_mul(FP12 *x,FP12 *y);
-/**	@brief Inverting an FP12
- *
-	@param x FP12 instance, on exit = 1/y
-	@param y FP12 instance
- */
-extern void FP12_inv(FP12 *x,FP12 *y);
-/**	@brief Raises an FP12 to the power of a BIG
- *
-	@param r FP12 instance, on exit = y^b
-	@param x FP12 instance
-	@param b BIG number
- */
-extern void FP12_pow(FP12 *r,FP12 *x,BIG b);
-/**	@brief Raises an FP12 instance x to a small integer power, side-channel resistant
- *
-	@param x ECP instance, on exit = x^i
-	@param i small integer exponent
-	@param b maximum number of bits in exponent
- */
-extern void FP12_pinpow(FP12 *x,int i,int b);
-/**	@brief Calculate x[0]^b[0].x[1]^b[1].x[2]^b[2].x[3]^b[3], side-channel resistant
- *
-	@param r ECP instance, on exit = x[0]^b[0].x[1]^b[1].x[2]^b[2].x[3]^b[3]
-	@param x FP12 array with 4 FP12s
-	@param b BIG array of 4 exponents
- */
-extern void FP12_pow4(FP12 *r,FP12 *x,BIG *b);
-/**	@brief Raises an FP12 to the power of the internal modulus p, using the Frobenius
- *
-	@param x FP12 instance, on exit = x^p
-	@param f FP2 precalculated Frobenius constant
- */
-extern void FP12_frob(FP12 *x,FP2 *f);
-/**	@brief Reduces all components of possibly unreduced FP12 mod Modulus
- *
-	@param x FP12 instance, on exit reduced mod Modulus
- */
-extern void FP12_reduce(FP12 *x);
-/**	@brief Normalises the components of an FP12
- *
-	@param x FP12 instance to be normalised
- */
-extern void FP12_norm(FP12 *x);
-/**	@brief Formats and outputs an FP12 to the console
- *
-	@param x FP12 instance to be printed
- */
-extern void FP12_output(FP12 *x);
-/**	@brief Formats and outputs an FP12 instance to an octet string
- *
-	Serializes the components of an FP12 to big-endian base 256 form.
-	@param S output octet string
-	@param x FP12 instance to be converted to an octet string
- */
-extern void FP12_toOctet(octet *S,FP12 *x);
-/**	@brief Creates an FP12 instance from an octet string
- *
-	De-serializes the components of an FP12 to create an FP12 from big-endian base 256 components.
-	@param x FP12 instance to be created from an octet string
-	@param S input octet string
-
- */
-extern void FP12_fromOctet(FP12 *x,octet *S);
-/**	@brief Calculate the trace of an FP12
- *
-	@param t FP4 trace of x, on exit = tr(x)
-	@param x FP12 instance
-
- */
-extern void FP12_trace(FP4 *t,FP12 *x);
-
-
-
-/* Pairing function prototypes */
-/**	@brief Calculate Miller loop for Optimal ATE pairing e(P,Q)
- *
-	@param r FP12 result of the pairing calculation e(P,Q)
-	@param P ECP2 instance, an element of G2
-	@param Q ECP instance, an element of G1
-
- */
-extern void PAIR_ate(FP12 *r,ECP2 *P,ECP *Q);
-/**	@brief Calculate Miller loop for Optimal ATE double-pairing e(P,Q).e(R,S)
- *
-	Faster than calculating two separate pairings
-	@param r FP12 result of the pairing calculation e(P,Q).e(R,S), an element of GT
-	@param P ECP2 instance, an element of G2
-	@param Q ECP instance, an element of G1
-	@param R ECP2 instance, an element of G2
-	@param S ECP instance, an element of G1
- */
-extern void PAIR_double_ate(FP12 *r,ECP2 *P,ECP *Q,ECP2 *R,ECP *S);
-/**	@brief Final exponentiation of pairing, converts output of Miller loop to element in GT
- *
-	Here p is the internal modulus, and r is the group order
-	@param x FP12, on exit = x^((p^12-1)/r)
- */
-extern void PAIR_fexp(FP12 *x);
-/**	@brief Fast point multiplication of a member of the group G1 by a BIG number
- *
-	May exploit endomorphism for speed.
-	@param Q ECP member of G1.
-	@param b BIG multiplier
-
- */
-extern void PAIR_G1mul(ECP *Q,BIG b);
-/**	@brief Fast point multiplication of a member of the group G2 by a BIG number
- *
-	May exploit endomorphism for speed.
-	@param P ECP2 member of G1.
-	@param b BIG multiplier
-
- */
-extern void PAIR_G2mul(ECP2 *P,BIG b);
-/**	@brief Fast raising of a member of GT to a BIG power
- *
-	May exploit endomorphism for speed.
-	@param x FP12 member of GT.
-	@param b BIG exponent
-
- */
-extern void PAIR_GTpow(FP12 *x,BIG b);
-/**	@brief Tests FP12 for membership of GT
- *
-	@param x FP12 instance
-	@return 1 if x is in GT, else return 0
-
- */
-extern int PAIR_GTmember(FP12 *x);
-
-
-
-/* Finite Field Prototypes */
-/**	@brief Copy one FF element of given length to another
- *
-	@param x FF instance to be copied to, on exit = y
-	@param y FF instance to be copied from
-	@param n size of FF in BIGs
-
- */
-extern void FF_copy(BIG *x,BIG *y,int n);
-/**	@brief Initialize an FF element of given length from a 32-bit integer m
- *
-	@param x FF instance to be copied to, on exit = m
-	@param m integer
-	@param n size of FF in BIGs
- */
-extern void FF_init(BIG *x,sign32 m,int n);
-/**	@brief Set FF element of given size to zero
- *
-	@param x FF instance to be set to zero
-	@param n size of FF in BIGs
- */
-extern void FF_zero(BIG *x,int n);
-/**	@brief Tests for FF element equal to zero
- *
-	@param x FF number to be tested
-	@param n size of FF in BIGs
-	@return 1 if zero, else returns 0
- */
-extern int FF_iszilch(BIG *x,int n);
-/**	@brief  return parity of an FF, that is the least significant bit
- *
-	@param x FF number
-	@return 0 or 1
- */
-extern int FF_parity(BIG *x);
-/**	@brief  return least significant m bits of an FF
- *
-	@param x FF number
-	@param m number of bits to return. Assumed to be less than BASEBITS.
-	@return least significant n bits as an integer
- */
-extern int FF_lastbits(BIG *x,int m);
-/**	@brief Set FF element of given size to unity
- *
-	@param x FF instance to be set to unity
-	@param n size of FF in BIGs
- */
-extern void FF_one(BIG *x,int n);
-/**	@brief Compares two FF numbers. Inputs must be normalised externally
- *
-	@param x first FF number to be compared
-	@param y second FF number to be compared
-	@param n size of FF in BIGs
-	@return -1 is x<y, 0 if x=y, 1 if x>y
- */
-extern int FF_comp(BIG *x,BIG *y,int n);
-/**	@brief addition of two FFs
- *
-	@param x FF instance, on exit = y+z
-	@param y FF instance
-	@param z FF instance
-	@param n size of FF in BIGs
- */
-extern void FF_add(BIG *x,BIG *y,BIG *z,int n);
-/**	@brief subtraction of two FFs
- *
-	@param x FF instance, on exit = y-z
-	@param y FF instance
-	@param z FF instance
-	@param n size of FF in BIGs
- */
-extern void FF_sub(BIG *x,BIG *y,BIG *z,int n);
-/**	@brief increment an FF by an integer,and normalise
- *
-	@param x FF instance, on exit = x+m
-	@param m an integer to be added to x
-	@param n size of FF in BIGs
- */
-extern void FF_inc(BIG *x,int m,int n);
-/**	@brief Decrement an FF by an integer,and normalise
- *
-	@param x FF instance, on exit = x-m
-	@param m an integer to be subtracted from x
-	@param n size of FF in BIGs
- */
-extern void FF_dec(BIG *x,int m,int n);
-/**	@brief Normalises the components of an FF
- *
-	@param x FF instance to be normalised
-	@param n size of FF in BIGs
- */
-extern void FF_norm(BIG *x,int n);
-/**	@brief Shift left an FF by 1 bit
- *
-	@param x FF instance to be shifted left
-	@param n size of FF in BIGs
- */
-extern void FF_shl(BIG *x,int n);
-/**	@brief Shift right an FF by 1 bit
- *
-	@param x FF instance to be shifted right
-	@param n size of FF in BIGs
- */
-extern void FF_shr(BIG *x,int n);
-/**	@brief Formats and outputs an FF to the console
- *
-	@param x FF instance to be printed
-	@param n size of FF in BIGs
- */
-extern void FF_output(BIG *x,int n);
-/**	@brief Formats and outputs an FF instance to an octet string
- *
-	Converts an FF to big-endian base 256 form.
-	@param S output octet string
-	@param x FF instance to be converted to an octet string
-	@param n size of FF in BIGs
- */
-extern void FF_toOctet(octet *S,BIG *x,int n);
-/**	@brief Populates an FF instance from an octet string
- *
-	Creates FF from big-endian base 256 form.
-	@param x FF instance to be created from an octet string
-	@param S input octet string
-	@param n size of FF in BIGs
- */
-extern void FF_fromOctet(BIG *x,octet *S,int n);
-/**	@brief Multiplication of two FFs
- *
-	Uses Karatsuba method internally
-	@param x FF instance, on exit = y*z
-	@param y FF instance
-	@param z FF instance
-	@param n size of FF in BIGs
- */
-extern void FF_mul(BIG *x,BIG *y,BIG *z,int n);
-/**	@brief Reduce FF mod a modulus
- *
-	This is slow
-	@param x FF instance to be reduced mod m - on exit = x mod m
-	@param m FF modulus
-	@param n size of FF in BIGs
- */
-extern void FF_mod(BIG *x,BIG *m,int n);
-/**	@brief Square an FF
- *
-	Uses Karatsuba method internally
-	@param x FF instance, on exit = y^2
-	@param y FF instance to be squared
-	@param n size of FF in BIGs
- */
-extern void FF_sqr(BIG *x,BIG *y,int n);
-/**	@brief Reduces a double-length FF with respect to a given modulus
- *
-	This is slow
-	@param x FF instance, on exit = y mod z
-	@param y FF instance, of double length 2*n
-	@param z FF modulus
-	@param n size of FF in BIGs
- */
-extern void FF_dmod(BIG *x,BIG *y,BIG *z,int n);
-/**	@brief Invert an FF mod a prime modulus
- *
-	@param x FF instance, on exit = 1/y mod z
-	@param y FF instance
-	@param z FF prime modulus
-	@param n size of FF in BIGs
- */
-extern void FF_invmodp(BIG *x,BIG *y,BIG *z,int n);
-/**	@brief Create an FF from a random number generator
- *
-	@param x FF instance, on exit x is a random number of length n BIGs with most significant bit a 1
-	@param R an instance of a Cryptographically Secure Random Number Generator
-	@param n size of FF in BIGs
- */
-extern void FF_random(BIG *x,csprng *R,int n);
-/**	@brief Create a random FF less than a given modulus from a random number generator
- *
-	@param x FF instance, on exit x is a random number < y
-	@param y FF instance, the modulus
-	@param R an instance of a Cryptographically Secure Random Number Generator
-	@param n size of FF in BIGs
- */
-extern void FF_randomnum(BIG *x,BIG *y,csprng *R,int n);
-/**	@brief Calculate r=x^e mod m, side channel resistant
- *
-	@param r FF instance, on exit = x^e mod p
-	@param x FF instance
-	@param e FF exponent
-	@param m FF modulus
-	@param n size of FF in BIGs
- */
-extern void FF_skpow(BIG *r,BIG *x,BIG * e,BIG *m,int n);
-/**	@brief Calculate r=x^e mod m, side channel resistant
- *
-	For short BIG exponent
-	@param r FF instance, on exit = x^e mod p
-	@param x FF instance
-	@param e BIG exponent
-	@param m FF modulus
-	@param n size of FF in BIGs
- */
-extern void FF_skspow(BIG *r,BIG *x,BIG e,BIG *m,int n);
-/**	@brief Calculate r=x^e mod m
- *
-	For very short integer exponent
-	@param r FF instance, on exit = x^e mod p
-	@param x FF instance
-	@param e integer exponent
-	@param m FF modulus
-	@param n size of FF in BIGs
- */
-extern void FF_power(BIG *r,BIG *x,int e,BIG *m,int n);
-/**	@brief Calculate r=x^e mod m
- *
-	@param r FF instance, on exit = x^e mod p
-	@param x FF instance
-	@param e FF exponent
-	@param m FF modulus
-	@param n size of FF in BIGs
- */
-extern void FF_pow(BIG *r,BIG *x,BIG *e,BIG *m,int n);
-/**	@brief Test if an FF has factor in common with integer s
- *
-	@param x FF instance to be tested
-	@param s the supplied integer
-	@param n size of FF in BIGs
-	@return 1 if gcd(x,s)!=1, else return 0
- */
-extern int FF_cfactor(BIG *x,sign32 s,int n);
-/**	@brief Test if an FF is prime
- *
-	Uses Miller-Rabin Method
-	@param x FF instance to be tested
-	@param R an instance of a Cryptographically Secure Random Number Generator
-	@param n size of FF in BIGs
-	@return 1 if x is (almost certainly) prime, else return 0
- */
-extern int FF_prime(BIG *x,csprng *R,int n);
-/**	@brief Calculate r=x^e.y^f mod m
- *
-	@param r FF instance, on exit = x^e.y^f mod p
-	@param x FF instance
-	@param e BIG exponent
-	@param y FF instance
-	@param f BIG exponent
-	@param m FF modulus
-	@param n size of FF in BIGs
- */
-extern void FF_pow2(BIG *r,BIG *x,BIG e,BIG *y,BIG f,BIG *m,int n);
-
-
-/* Octet string handlers */
-/**	@brief Formats and outputs an octet to the console in hex
- *
-	@param O Octet to be output
- */
-extern void OCT_output(octet *O);
-/**	@brief Formats and outputs an octet to the console as a character string
- *
-	@param O Octet to be output
- */
-extern void OCT_output_string(octet *O);
-/**	@brief Wipe clean an octet
- *
-	@param O Octet to be cleaned
- */
-extern void OCT_clear(octet *O);
-/**	@brief Compare two octets
- *
-	@param O first Octet to be compared
-	@param P second Octet to be compared
-	@return 1 if equal, else 0
- */
-extern int  OCT_comp(octet *O,octet *P);
-/**	@brief Compare first n bytes of two octets
- *
-	@param O first Octet to be compared
-	@param P second Octet to be compared
-	@param n number of bytes to compare
-	@return 1 if equal, else 0
- */
-extern int  OCT_ncomp(octet *O,octet *P,int n);
-/**	@brief Join from a C string to end of an octet
- *
-	Truncates if there is no room
-	@param O Octet to be written to
-	@param s zero terminated string to be joined to octet
- */
-extern void OCT_jstring(octet *O,char *s);
-/**	@brief Join bytes to end of an octet
- *
-	Truncates if there is no room
-	@param O Octet to be written to
-	@param s bytes to be joined to end of octet
-	@param n number of bytes to join
- */
-extern void OCT_jbytes(octet *O,char *s,int n);
-/**	@brief Join single byte to end of an octet, repeated n times
- *
-	Truncates if there is no room
-	@param O Octet to be written to
-	@param b byte to be joined to end of octet
-	@param n number of times b is to be joined
- */
-extern void OCT_jbyte(octet *O,int b,int n);
-/**	@brief Join one octet to the end of another
- *
-	Truncates if there is no room
-	@param O Octet to be written to
-	@param P Octet to be joined to the end of O
- */
-extern void OCT_joctet(octet *O,octet *P);
-/**	@brief XOR common bytes of a pair of Octets
- *
-	@param O Octet - on exit = O xor P
-	@param P Octet to be xored into O
- */
-extern void OCT_xor(octet *O,octet *P);
-/**	@brief reset Octet to zero length
- *
-	@param O Octet to be emptied
- */
-extern void OCT_empty(octet *O);
-/**	@brief Pad out an Octet to the given length
- *
-	Padding is done by inserting leading zeros, so abcd becomes 00abcd
-	@param O Octet to be padded
-	@param n new length of Octet
- */
-extern int OCT_pad(octet *O,int n);
-/**	@brief Convert an Octet to printable base64 number
- *
-	@param b zero terminated byte array to take base64 conversion
-	@param O Octet to be converted
- */
-extern void OCT_tobase64(char *b,octet *O);
-/**	@brief Populate an Octet from base64 number
- *
- 	@param O Octet to be populated
-	@param b zero terminated base64 string
-
- */
-extern void OCT_frombase64(octet *O,char *b);
-/**	@brief Copy one Octet into another
- *
- 	@param O Octet to be copied to
-	@param P Octet to be copied from
-
- */
-extern void OCT_copy(octet *O,octet *P);
-/**	@brief XOR every byte of an octet with input m
- *
- 	@param O Octet
-	@param m byte to be XORed with every byte of O
-
- */
-extern void OCT_xorbyte(octet *O,int m);
-/**	@brief Chops Octet into two, leaving first n bytes in O, moving the rest to P
- *
- 	@param O Octet to be chopped
-	@param P new Octet to be created
-	@param n number of bytes to chop off O
-
- */
-extern void OCT_chop(octet *O,octet *P,int n);
-/**	@brief Join n bytes of integer m to end of Octet O (big endian)
- *
-	Typically n is 4 for a 32-bit integer
- 	@param O Octet to be appended to
-	@param m integer to be appended to O
-	@param n number of bytes in m
-
- */
-extern void OCT_jint(octet *O,int m,int n);
-/**	@brief Create an Octet from bytes taken from a random number generator
- *
-	Truncates if there is no room
- 	@param O Octet to be populated
-	@param R an instance of a Cryptographically Secure Random Number Generator
-	@param n number of bytes to extracted from R
-
- */
-extern void OCT_rand(octet *O,csprng *R,int n);
-/**	@brief Shifts Octet left by n bytes
- *
-	Leftmost bytes disappear
- 	@param O Octet to be shifted
-	@param n number of bytes to shift
-
- */
-extern void OCT_shl(octet *O,int n);
-/**	@brief Convert an Octet to printable hex number
- *
-	@param dst hex value
-	@param src Octet to be converted
- */
-extern void OCT_toHex(octet *src,char *dst);
-/**	@brief Convert an Octet to string
- *
-	@param dst string value
-	@param src Octet to be converted
- */
-extern void OCT_toStr(octet *src,char *dst);
-
-
-/* Hash function */
-/**	@brief Initialise an instance of SHA256
- *
-	@param H an instance SHA256
- */
-extern void HASH_init(hash *H);
-/**	@brief Add a byte to the hash
- *
-	@param H an instance SHA256
-	@param b byte to be included in hash
- */
-extern void HASH_process(hash *H,int b);
-/**	@brief Generate 32-byte hash
- *
-	@param H an instance SHA256
-	@param h is the output 32-byte hash
- */
-extern void HASH_hash(hash *H,char *h);
-
-
-
-/* AES functions */
-/**	@brief Reset AES mode or IV
- *
-	@param A an instance of the AES
-	@param m is the new active mode of operation (ECB, CBC, OFB, CFB etc)
-	@param iv the new Initialisation Vector
- */
-extern void AES_reset(aes *A,int m,char *iv);
-/**	@brief Extract chaining vector from AES instance
- *
-	@param A an instance of the AES
-	@param f the extracted chaining vector
- */
-extern void AES_getreg(aes *A,char * f);
-/**	@brief Initialise an instance of AES and its mode of operation
- *
-	@param A an instance AES
-	@param m is the active mode of operation (ECB, CBC, OFB, CFB etc)
-	@param k the AES key as an array of 16 bytes
-	@param iv the Initialisation Vector
- */
-extern void AES_init(aes *A,int m,char *k,char *iv);
-/**	@brief Encrypt a single 16 byte block in ECB mode
- *
-	@param A an instance of the AES
-	@param b is an array of 16 plaintext bytes, on exit becomes ciphertext
- */
-extern void AES_ecb_encrypt(aes *A,uchar * b);
-/**	@brief Decrypt a single 16 byte block in ECB mode
- *
-	@param A an instance of the AES
-	@param b is an array of 16 cipherext bytes, on exit becomes plaintext
- */
-extern void AES_ecb_decrypt(aes *A,uchar * b);
-/**	@brief Encrypt a single 16 byte block in active mode
- *
-	@param A an instance of the AES
-	@param b is an array of 16 plaintext bytes, on exit becomes ciphertext
-	@return 0, or overflow bytes from CFB mode
- */
-extern unsign32 AES_encrypt(aes *A,char *b );
-/**	@brief Decrypt a single 16 byte block in active mode
- *
-	@param A an instance of the AES
-	@param b is an array of 16 ciphertext bytes, on exit becomes plaintext
-	@return 0, or overflow bytes from CFB mode
- */
-extern unsign32 AES_decrypt(aes *A,char *b);
-/**	@brief Clean up after application of AES
- *
-	@param A an instance of the AES
- */
-extern void AES_end(aes *A);
-
-
-/* AES-GCM functions */
-/**	@brief Initialise an instance of AES-GCM mode
- *
-	@param G an instance AES-GCM
-	@param k the AES key as an array of 16 bytes
-	@param n the number of bytes in the Initialisation Vector (IV)
-	@param iv the IV
- */
-extern void GCM_init(gcm *G,char *k,int n,char *iv);
-/**	@brief Add header (material to be authenticated but not encrypted)
- *
-	Note that this function can be called any number of times with n a multiple of 16, and then one last time with any value for n
-	@param G an instance AES-GCM
-	@param b is the header material to be added
-	@param n the number of bytes in the header
- */
-extern int GCM_add_header(gcm *G,char *b,int n);
-/**	@brief Add plaintext and extract ciphertext
- *
-	Note that this function can be called any number of times with n a multiple of 16, and then one last time with any value for n
-	@param G an instance AES-GCM
-	@param c is the ciphertext generated
-	@param p is the plaintext material to be added
-	@param n the number of bytes in the plaintext
- */
-extern int GCM_add_plain(gcm *G,char *c,char *p,int n);
-/**	@brief Add ciphertext and extract plaintext
- *
-	Note that this function can be called any number of times with n a multiple of 16, and then one last time with any value for n
-	@param G an instance AES-GCM
-	@param p is the plaintext generated
-	@param c is the ciphertext material to be added
-	@param n the number of bytes in the ciphertext
- */
-extern int GCM_add_cipher(gcm *G,char *p,char *c,int n);
-/**	@brief Finish off and extract authentication tag (HMAC)
- *
-	@param G is an active instance AES-GCM
-	@param t is the output 16 byte authentication tag
- */
-extern void GCM_finish(gcm *G,char *t);
-
-
-
-/* random numbers */
-/**	@brief Seed a random number generator from an array of bytes
- *
-	The provided seed should be truly random
-	@param R an instance of a Cryptographically Secure Random Number Generator
-	@param n the number of seed bytes provided
-	@param b an array of seed bytes
-
- */
-extern void RAND_seed(csprng *R,int n,char *b);
-/**	@brief Delete all internal state of a random number generator
- *
-	@param R an instance of a Cryptographically Secure Random Number Generator
- */
-extern void RAND_clean(csprng *R);
-/**	@brief Return a random byte from a random number generator
- *
-	@param R an instance of a Cryptographically Secure Random Number Generator
-	@return a random byte
- */
-extern int RAND_byte(csprng *R);
-
-#endif
diff --git a/c/amcl_.h b/c/amcl_.h
deleted file mode 100755
index cb9cd58..0000000
--- a/c/amcl_.h
+++ /dev/null
@@ -1,2501 +0,0 @@
-/*
-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.
-*/
-
-/* AMCL header file */
-/* Designed for AES-128 security, 254-256 bit elliptic curves and BN curves for pairings */
-/* Each "limb" of a big number occupies at most (n-3) bits of an n-bit computer word. The most significant word must have at least 4 extra unused bits */
-/* For n=64, use 5 words, use 56 bits per limb, leaving at least 24 unused MSBs 5*56-256  */
-/* For n=32, use 9 words, use 29 bits per limb, leaving at least 5 unused MSBs  9*29-256  */
-/* For n=16, use 20 words, use 13 bits per limb, leaving at least 4 unused MSBs 20*13-256 */
-
-/**
- * @file amcl_.h
- * @author Mike Scott and Kealan McCusker
- * @date 19th May 2015
- * @brief Main Header File
- *
- * Allows some user configuration
- * defines structures
- * declares functions
- *
- */
-
-
-/* NOTE: There is only one user configurable section in this header - see below */
-
-#ifndef AMCL_H
-#define AMCL_H
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "DLLDefines.h"
-
-/* Support for C99?  Note for GCC need to explicitly include -std=c99 in command line */
-
-#if __STDC_VERSION__ >= 199901L
-/* C99 code */
-#define C99
-#else
-/* Not C99 code */
-#endif
-
-#ifndef C99  /* You are on your own! These are for Microsoft C */
-#define sign32 __int32			/**< 32-bit signed integer */
-#define sign8 signed char		/**< 8-bit signed integer */
-#define unsign32 unsigned __int32 /**< 32-bit unsigned integer */
-#else
-#include <stdint.h>
-#define sign8 int8_t			/**< 8-bit signed integer */
-#define sign32 int32_t			/**< 32-bit signed integer */
-#define unsign32 uint32_t		/**< 32-bit unsigned integer */
-#endif
-
-/* modulus types */
-
-#define NOT_SPECIAL 0			/**< Modulus of no exploitable form */
-#define PSEUDO_MERSENNE 1		/**< Pseudo-mersenne modulus of form $2^n-c$  */
-#define MONTGOMERY_FRIENDLY 3	/**< Montgomery Friendly modulus of form $2^a(2^b-c)-1$  */
-
-/* curve types */
-
-#define WEIERSTRASS 0			/**< Short Weierstrass form curve  */
-#define EDWARDS 1				/**< Edwards or Twisted Edwards curve  */
-#define MONTGOMERY 2			/**< Montgomery form curve  */
-
-/* Elliptic curves are defined over prime fields */
-/* Here are some popular EC prime fields for which I have prepared curves. Feel free to specify your own. */
-
-#define NIST 0 /**< For the NIST 256-bit standard curve		- WEIERSTRASS only */
-#define C25519 1  /**< Bernstein's Modulus 2^255-19			- EDWARDS or MONTGOMERY only */
-#define BRAINPOOL 2 /**< For Brainpool 256-bit curve			- WEIERSTRASS only */
-#define ANSSI 3 /**< For French 256-bit standard curve		- WEIERSTRASS only */
-#define MF254 4 /**< For NUMS curves from Bos et al - 254-bit Montgomery friendly modulus		- WEIERSTRASS or EDWARDS or MONTGOMERY */
-#define MS255 5 /**< For NUMS curve - 255-bit pseudo-mersenne modulus							- WEIERSTRASS or EDWARDS or MONTGOMERY */
-#define MF256 6 /**< For NUMS curve - 256-bit Montgomery friendly modulus						- WEIERSTRASS or EDWARDS or MONTGOMERY */
-#define MS256 7 /**< For NUMS curve - 256-bit pseudo-merseene modulus							- WEIERSTRASS or EDWARDS or MONTGOMERY */
-
-#define BN 100    /**< Standard Nogami BN curve - fastest. Modulus built from  t=-0x4080000000000001	- WEIERSTRASS only */
-#define BNCX 101  /**< Our MIRACL BN curve. Modulus built from t=-0x4000000003C012B1					- WEIERSTRASS only */
-#define BNT 102   /**< GT_Strong BN curve. Modulus built from t=-0x4000806000004081  					- WEIERSTRASS only */
-#define BNT2 103  /**< G2 and GT-Strong BN curve.  Modulus built from t=-0x4000020100608205 			- WEIERSTRASS only */
-
-
-/*** START OF USER CONFIGURABLE SECTION - set architecture and choose modulus and curve  ***/
-
-#define CHUNK 32		/**< size of chunk in bits = wordlength of computer = 16, 32 or 64. Note not all curve options are supported on 16-bit processors - see rom.c */
-#define CHOICE  BNCX	/**< Current choice of Field */
-/* For some moduli only WEIERSTRASS curves are supported. For others there is a choice of WEIERSTRASS, EDWARDS or MONTGOMERY curves. See above. */
-#define CURVETYPE WEIERSTRASS	/**< Note that not all curve types are supported - see above */
-
-/* Actual curve parameters associated with these choices can be found in rom.c */
-
-/* These next options only apply for pairings */
-#define USE_GLV		/**< Note this method is patented (GLV), so maybe you want to comment this out */
-#define USE_GS_G2	/**< Well we didn't patent it :) But may be covered by GLV patent :( */
-#define USE_GS_GT   /**< Not patented, so probably always use this */
-
-/* Finite field support - for RSA, DH etc. */
-#define FF_BITS 2048 /**< Finite Field Size in bits - must be 256.2^n */
-
-/* For debugging Only.
-#define DEBUG_REDUCE
-#define DEBUG_NORM
-#define GET_STATS
-*/
-
-/*** END OF USER CONFIGURABLE SECTION ***/
-
-
-#if CHOICE>=BN     /* Its a BN curve */
-#define MBITS 254	/**< Number of bits in Modulus */
-#define MOD8 3		/**< Modulus mod 8  */
-#define MODTYPE  NOT_SPECIAL /**< Modulus type */
-#endif
-
-#if CHOICE>BN
-#define GT_STRONG   /**< Using a GT-Strong BN curve */
-#endif
-
-#if CHOICE==NIST
-#define MBITS 256	/**< Number of bits in Modulus */
-#define MOD8 7		/**< Modulus mod 8  */
-#define MODTYPE  NOT_SPECIAL /**< Modulus type */
-#endif
-
-#if CHOICE==C25519
-#define MBITS 255	/**< Number of bits in Modulus */
-#define MOD8 5		/**< Modulus mod 8  */
-#define MODTYPE PSEUDO_MERSENNE /**< Modulus type */
-#endif
-
-#if CHOICE==BRAINPOOL
-#define MBITS 256 /**< Number of bits in Modulus */
-#define MOD8 7 /**< Modulus mod 8  */
-#define MODTYPE  NOT_SPECIAL /**< Modulus type */
-#endif
-
-#if CHOICE==ANSSI
-#define MBITS 256		/**< Number of bits in Modulus */
-#define MOD8 3			/**< Modulus mod 8  */
-#define MODTYPE  NOT_SPECIAL /**< Modulus type */
-#endif
-
-/**< NUMS curve from Bos et al. paper */
-
-#if CHOICE==MF254
-#define MBITS 254   /**< Number of bits in Modulus */
-#define MOD8 7      /**< Modulus mod 8  */
-#define MODTYPE MONTGOMERY_FRIENDLY  /**< Modulus type */
-#endif
-
-#if CHOICE==MF256
-#define MBITS 256   /**< Number of bits in Modulus */
-#define MOD8 7      /**< Modulus mod 8  */
-#define MODTYPE MONTGOMERY_FRIENDLY  /**< Modulus type */
-#endif
-
-#if CHOICE==MS255
-#define MBITS 255	/**< Number of bits in Modulus */
-#define MOD8 3		/**< Modulus mod 8  */
-#define MODTYPE PSEUDO_MERSENNE /**< Modulus type */
-#endif
-
-#if CHOICE==MS256
-#define MBITS 256	/**< Number of bits in Modulus */
-#define MOD8 3		/**< Modulus mod 8  */
-#define MODTYPE PSEUDO_MERSENNE /**< Modulus type */
-#endif
-
-
-#define FFLEN (FF_BITS/256)  /**< RSA public key bytes */
-#define HFLEN (FFLEN/2)		/**< Useful for half-size RSA private key operations */
-
-/* This next is probably OK, but may need changing for non-C99-standard environments */
-
-#if CHUNK==16
-#define NLEN 20				/**< Number of words in BIG. */
-#define BASEBITS 13			/**< Numbers represented to base 2*BASEBITS */
-#ifndef C99
-#define chunk __int16		/**< C type corresponding to word length */
-#define dchunk __int32		/**< Always define double length chunk type if available */
-#else
-#define chunk int16_t		/**< C type corresponding to word length */
-#define dchunk int32_t		/**< Always define double length chunk type if available */
-#endif
-#endif
-
-#if CHUNK == 32
-#define NLEN 9				/**< Number of words in BIG. */
-#define BASEBITS 29			/**< Numbers represented to base 2*BASEBITS */
-#ifndef C99
-#define chunk __int32		/**< C type corresponding to word length */
-#define dchunk __int64		/**< Always define double length chunk type if available */
-#else
-#define chunk int32_t		/**< C type corresponding to word length */
-#define dchunk int64_t		/**< Always define double length chunk type if available */
-#endif
-#endif
-
-#if CHUNK == 64
-#define NLEN 5				/**< Number of words in BIG. */
-#define BASEBITS 56			/**< Numbers represented to base 2*BASEBITS */
-#ifndef C99
-#define chunk __int64		/**< C type corresponding to word length */
-							/**< Note - no 128-bit type available    */
-#else
-#define chunk int64_t		/**< C type corresponding to word length */
-#ifdef __GNUC__
-#define dchunk __int128		/**< Always define double length chunk type if available - GCC supports 128 bit type  ??? */
-#endif
-#endif
-#endif
-
-/* Don't mess with anything below this line */
-
-#ifdef GET_STATS
-extern int tsqr,rsqr,tmul,rmul;
-extern int tadd,radd,tneg,rneg;
-extern int tdadd,rdadd,tdneg,rdneg;
-#endif
-
-#define DCHUNK 2*CHUNK	/**< Number of bits in double-length type */
-#define DNLEN 2*NLEN	/**< double length required for products of BIGs */
-
-#ifdef dchunk
-#define COMBA      /**< Use COMBA method for faster BN muls, sqrs and reductions */
-#endif
-
-#define CHUNK_BITS 8*sizeof(chunk) /**< Number of bits in a chunk */
-
-#ifdef DEBUG_NORM    /* Add an extra location to track chunk extension */
-typedef chunk BIG[NLEN+1]; /**< Define type BIG as array of chunks */
-typedef chunk DBIG[DNLEN+1]; /**< Define type DBIG as array of chunks */
-#else
-typedef chunk BIG[NLEN];  /**< Define type BIG as array of chunks */
-typedef chunk DBIG[DNLEN]; /**< Define type DBIG as array of chunks */
-#endif
-
-#define HBITS (BASEBITS/2)  /**< Number of bits in number base divided by 2 */
-#define HBITS1 ((BASEBITS+1)/2) /**< Number of bits in number base plus 1 divided by 2 */
-#define HDIFF (HBITS1-HBITS)  /**< Will be either 0 or 1, depending if number of bits in number base is even or odd */
-
-#define MASK (((chunk)1<<BASEBITS)-1) /**< Mask = 2^BASEBITS-1 */
-#define HMASK (((chunk)1<<HBITS)-1)   /**< Mask = 2^HBITS-1 */
-#define HMASK1 (((chunk)1<<HBITS1)-1) /**< Mask = 2^HBITS1-1 */
-
-#define MODBITS MBITS /**< Number of bits in Modulus for selected curve */
-#define MODBYTES 32   /**< Number of bytes in Modulus */
-#define MB (MBITS%BASEBITS) /**<  Number of bits in modulus mod number of bits in number base */
-#define TBITS (MBITS%BASEBITS) /**< Number of active bits in top word */
-#define TMASK (((chunk)1<<(MBITS%BASEBITS))-1)  /**< Mask for active bits in top word */
-#define NEXCESS (1<<(CHUNK-BASEBITS-1)) /**< 2^(CHUNK-BASEBITS-1) - digit cannot be multiplied by more than this before normalisation */
-#define FEXCESS ((chunk)1<<(BASEBITS*NLEN-MBITS)) /**< 2^(BASEBITS*NLEN-MODBITS) - normalised BIG can be multiplied by more than this before reduction */
-#define OMASK ((chunk)(-1)<<(MBITS%BASEBITS))     /**<  for masking out overflow bits */
-
-/* catch field excesses */
-#define EXCESS(a) ((a[NLEN-1]&OMASK)>>(MB))   /**< Field Excess */
-
-/* Field Params - see rom.c */
-extern const BIG Modulus;  /**< Actual Modulus set in rom.c */
-extern const chunk MConst; /**< Montgomery only - 1/p mod 2^BASEBITS */
-
-/* Curve Params - see rom.c */
-extern const int CURVE_A; /**< Elliptic curve A parameter */
-extern const BIG CURVE_B; /**< Elliptic curve B parameter */
-extern const BIG CURVE_Order; /**< Elliptic curve group order */
-
-/* Generator point on G1 */
-extern const BIG CURVE_Gx; /**< x-coordinate of generator point in group G1  */
-extern const BIG CURVE_Gy; /**< y-coordinate of generator point in group G1  */
-
-/* For Pairings only */
-
-/* Generator point on G2 */
-extern const BIG CURVE_Pxa; /**< real part of x-coordinate of generator point in group G2 */
-extern const BIG CURVE_Pxb; /**< imaginary part of x-coordinate of generator point in group G2 */
-extern const BIG CURVE_Pya; /**< real part of y-coordinate of generator point in group G2 */
-extern const BIG CURVE_Pyb; /**< imaginary part of y-coordinate of generator point in group G2 */
-
-extern const BIG CURVE_Bnx; /**< BN curve x parameter */
-
-extern const BIG CURVE_Cru; /**< BN curve Cube Root of Unity */
-
-extern const BIG CURVE_Fra; /**< real part of BN curve Frobenius Constant */
-extern const BIG CURVE_Frb; /**< imaginary part of BN curve Frobenius Constant */
-
-
-extern const BIG CURVE_W[2];		/**< BN curve constant for GLV decomposition */
-extern const BIG CURVE_SB[2][2];	/**< BN curve constant for GLV decomposition */
-extern const BIG CURVE_WB[4];		/**< BN curve constant for GS decomposition */
-extern const BIG CURVE_BB[4][4];	/**< BN curve constant for GS decomposition */
-
-/* Structures */
-
-/**
-	@brief ECP structure - Elliptic Curve Point over base field
-*/
-
-typedef struct {
-#if CURVETYPE!=EDWARDS
-int inf; /**< Infinity Flag - not needed for Edwards representation */
-#endif
-BIG x;   /**< x-coordinate of point */
-#if CURVETYPE!=MONTGOMERY
-BIG y;  /**< y-coordinate of point. Not needed for Montgomery representation */
-#endif
-BIG z; /**< z-coordinate of point */
-} ECP;
-
-/**
-	@brief FP2 Structure - quadratic extension field
-*/
-
-typedef struct {
-BIG a; /**< real part of FP2 */
-BIG b; /**< imaginary part of FP2 */
-} FP2;
-
-/**
-	@brief FP4 Structure - towered over two FP2
-*/
-
-typedef struct {
-FP2 a; /**< real part of FP4 */
-FP2 b; /**< imaginary part of FP4 */
-} FP4;
-
-/**
-	@brief FP12 Structure - towered over three FP4
-*/
-
-typedef struct {
-FP4 a; /**< first part of FP12 */
-FP4 b; /**< second part of FP12 */
-FP4 c; /**< third part of FP12 */
-} FP12;
-
-/**
-	@brief ECP2 Structure - Elliptic Curve Point over quadratic extension field
-*/
-
-typedef struct {
-int inf; /**< Infinity Flag */
-FP2 x;  /**< x-coordinate of point */
-FP2 y;  /**< y-coordinate of point */
-FP2 z;  /**< z-coordinate of point */
-} ECP2;
-
-/**
-	@brief SHA256 hash function instance
-*/
-
-typedef struct {
-unsign32 length[2];  /**< 64-bit input length */
-unsign32 h[8];       /**< Internal state */
-unsign32 w[64];		/**< Internal state */
-} hash;
-
-/* Symmetric Encryption AES structure */
-
-#define ECB   0  /**< Electronic Code Book */
-#define CBC   1  /**< Cipher Block Chaining */
-#define CFB1  2  /**< Cipher Feedback - 1 byte */
-#define CFB2  3  /**< Cipher Feedback - 2 bytes */
-#define CFB4  5  /**< Cipher Feedback - 4 bytes */
-#define OFB1  14 /**< Output Feedback - 1 byte */
-#define OFB2  15 /**< Output Feedback - 2 bytes */
-#define OFB4  17 /**< Output Feedback - 4 bytes */
-#define OFB8  21 /**< Output Feedback - 8 bytes */
-#define OFB16 29 /**< Output Feedback - 16 bytes */
-
-#define uchar unsigned char  /**<  Unsigned char */
-
-/**
-	@brief AES instance
-*/
-
-
-typedef struct {
-int mode;          /**< AES mode of operation */
-unsign32 fkey[44]; /**< subkeys for encrypton */
-unsign32 rkey[44]; /**< subkeys for decrypton */
-char f[16];        /**< buffer for chaining vector */
-} aes;
-
-/* AES-GCM suppport.  */
-
-#define GCM_ACCEPTING_HEADER 0 /**< GCM status */
-#define GCM_ACCEPTING_CIPHER 1 /**< GCM status */
-#define GCM_NOT_ACCEPTING_MORE 2 /**< GCM status */
-#define GCM_FINISHED 3 /**< GCM status */
-#define GCM_ENCRYPTING 0 /**< GCM mode */
-#define GCM_DECRYPTING 1 /**< GCM mode */
-
-
-/**
-	@brief GCM mode instance, using AES internally
-*/
-
-typedef struct {
-unsign32 table[128][4]; /**< 2k byte table */
-uchar stateX[16];	/**< GCM Internal State */
-uchar Y_0[16];		/**< GCM Internal State */
-unsign32 lenA[2];	/**< GCM 64-bit length of header */
-unsign32 lenC[2];	/**< GCM 64-bit length of ciphertext */
-int status;		/**< GCM Status */
-aes a;			/**< Internal Instance of AES cipher */
-} gcm;
-
-/* Marsaglia & Zaman Random number generator constants */
-
-#define NK   21 /**< PRNG constant */
-#define NJ   6 /**< PRNG constant */
-#define NV   8 /**< PRNG constant */
-
-
-/**
-	@brief Cryptographically secure pseudo-random number generator instance
-*/
-
-typedef struct {
-unsign32 ira[NK];  /**< random number array   */
-int      rndptr;   /**< pointer into array */
-unsign32 borrow;   /**<  borrow as a result of subtraction */
-int pool_ptr;		/**< pointer into random pool */
-char pool[32];		/**< random pool */
-} csprng;
-
-
-/**
-	@brief Portable representation of a big positive number
-*/
-
-typedef struct
-{
-    int len; /**< length in bytes  */
-    int max; /**< max length allowed - enforce truncation  */
-    char *val; /**< byte array  */
-} octet;
-
-/**
-	@brief Integer Factorisation Public Key
-*/
-
-typedef struct
-{
-    sign32 e;     /**< RSA exponent (typically 65537) */
-    BIG n[FFLEN]; /**< An array of BIGs to store public key */
-} rsa_public_key;
-
-/**
-	@brief Integer Factorisation Private Key
-*/
-
-typedef struct
-{
-    BIG p[FFLEN/2]; /**< secret prime p  */
-    BIG q[FFLEN/2]; /**< secret prime q  */
-    BIG dp[FFLEN/2]; /**< decrypting exponent mod (p-1)  */
-    BIG dq[FFLEN/2]; /**< decrypting exponent mod (q-1)  */
-    BIG c[FFLEN/2];  /**< 1/p mod q */
-} rsa_private_key;
-
-/*
-
-Note that a normalised BIG consists of digits mod 2^BASEBITS
-However BIG digits may be "extended" up to 2^(WORDLENGTH-1).
-
-BIGs in extended form may need to be normalised before certain
-operations.
-
-A BIG may be "reduced" to be less that the Modulus, or it
-may be "unreduced" and allowed to grow greater than the
-Modulus.
-
-Normalisation is quite fast. Reduction involves conditional branches,
-which can be regarded as significant "speed bumps". We try to
-delay reductions as much as possible. Reductions may also involve
-side channel leakage, so delaying and batching them
-hopefully disguises internal operations.
-
-*/
-
-/* BIG number prototypes */
-
-/**	@brief Calculates a*b+c+*d
- *
-	Calculate partial product of a.b, add in carry c, and add total to d
-	@param a multiplier
-	@param b multiplicand
-	@param c carry
-	@param d pointer to accumulated bottom half of result
-	@return top half of result
- */
-extern chunk muladd(chunk a,chunk b,chunk c,chunk *d);
-/**	@brief Tests for BIG equal to zero
- *
-	@param x a BIG number
-	@return 1 if zero, else returns 0
- */
-extern int BIG_iszilch(BIG x);
-/**	@brief Tests for DBIG equal to zero
- *
-	@param x a DBIG number
-	@return 1 if zero, else returns 0
- */
-extern int BIG_diszilch(DBIG x);
-/**	@brief Outputs a BIG number to the console
- *
-	@param x a BIG number
- */
-extern void BIG_output(BIG x);
-/**	@brief Outputs a BIG number to the console in raw form (for debugging)
- *
-	@param x a BIG number
- */
-extern void BIG_rawoutput(BIG x);
-/**	@brief Conditional constant time swap of two BIG numbers
- *
-	Conditionally swaps parameters in constant time (without branching)
-	@param x a BIG number
-	@param y another BIG number
-	@param s swap takes place if not equal to 0
- */
-extern void BIG_cswap(BIG x,BIG y,int s);
-/**	@brief Conditional copy of BIG number
- *
-	Conditionally copies second parameter to the first (without branching)
-	@param x a BIG number
-	@param y another BIG number
-	@param s copy takes place if not equal to 0
- */
-extern void BIG_cmove(BIG x,BIG y,int s);
-/**	@brief Convert from BIG number to byte array
- *
-	@param a byte array
-	@param x BIG number
- */
-extern void BIG_toBytes(char *a,BIG x);
-/**	@brief Convert to BIG number from byte array
- *
-	@param x BIG number
-	@param a byte array
- */
-extern void BIG_fromBytes(BIG x,char *a);
-/**	@brief Outputs a DBIG number to the console
- *
-	@param x a DBIG number
- */
-extern void BIG_doutput(DBIG x);
-/**	@brief Copy BIG from Read-Only Memory to a BIG
- *
-	@param x BIG number
-	@param y BIG number in ROM
- */
-extern void BIG_rcopy(BIG x,const BIG y);
-/**	@brief Copy BIG to another BIG
- *
-	@param x BIG number
-	@param y BIG number to be copied
- */
-extern void BIG_copy(BIG x,BIG y);
-/**	@brief Copy DBIG to another DBIG
- *
-	@param x DBIG number
-	@param y DBIG number to be copied
- */
-extern void BIG_dcopy(DBIG x,DBIG y);
-/**	@brief Copy BIG to upper half of DBIG
- *
-	@param x DBIG number
-	@param y BIG number to be copied
- */
-extern void BIG_dsucopy(DBIG x,BIG y);
-/**	@brief Copy BIG to lower half of DBIG
- *
-	@param x DBIG number
-	@param y BIG number to be copied
- */
-extern void BIG_dscopy(DBIG x,BIG y);
-/**	@brief Copy lower half of DBIG to a BIG
- *
-	@param x BIG number
-	@param y DBIG number to be copied
- */
-extern void BIG_sdcopy(BIG x,DBIG y);
-/**	@brief Copy upper half of DBIG to a BIG
- *
-	@param x BIG number
-	@param y DBIG number to be copied
- */
-extern void BIG_sducopy(BIG x,DBIG y);
-/**	@brief Set BIG to zero
- *
-	@param x BIG number to be set to zero
- */
-extern void BIG_zero(BIG x);
-/**	@brief Set DBIG to zero
- *
-	@param x DBIG number to be set to zero
- */
-extern void BIG_dzero(DBIG x);
-/**	@brief Set BIG to one (unity)
- *
-	@param x BIG number to be set to one.
- */
-extern void BIG_one(BIG x);
-/**	@brief Set BIG to inverse mod 2^256
- *
-	@param x BIG number to be inverted
- */
-extern void BIG_invmod2m(BIG x);
-/**	@brief Set BIG to sum of two BIGs - output not normalised
- *
-	@param x BIG number, sum of other two
-	@param y BIG number
-	@param z BIG number
- */
-extern void BIG_add(BIG x,BIG y,BIG z);
-/**	@brief Increment BIG by a small integer - output not normalised
- *
-	@param x BIG number to be incremented
-	@param i integer
- */
-extern void BIG_inc(BIG x,int i);
-/**	@brief Set BIG to difference of two BIGs
- *
-	@param x BIG number, difference of other two - output not normalised
-	@param y BIG number
-	@param z BIG number
- */
-extern void BIG_sub(BIG x,BIG y,BIG z);
-/**	@brief Decrement BIG by a small integer - output not normalised
- *
-	@param x BIG number to be decremented
-	@param i integer
- */
-extern void BIG_dec(BIG x,int i);
-/**	@brief Set DBIG to difference of two DBIGs
- *
-	@param x DBIG number, difference of other two - output not normalised
-	@param y DBIG number
-	@param z DBIG number
- */
-extern void BIG_dsub(DBIG x,DBIG y,DBIG z);
-/**	@brief Multiply BIG by a small integer - output not normalised
- *
-	@param x BIG number, product of other two
-	@param y BIG number
-	@param i small integer
- */
-extern void BIG_imul(BIG x,BIG y,int i);
-/**	@brief Multiply BIG by not-so-small small integer - output normalised
- *
-	@param x BIG number, product of other two
-	@param y BIG number
-	@param i small integer
-	@return Overflowing bits
- */
-extern chunk BIG_pmul(BIG x,BIG y,int i);
-/**	@brief Divide BIG by 3 - output normalised
- *
-	@param x BIG number
-	@return Remainder
- */
-extern int BIG_div3(BIG x);
-/**	@brief Multiply BIG by even bigger small integer resulting in a DBIG - output normalised
- *
-	@param x DBIG number, product of other two
-	@param y BIG number
-	@param i small integer
- */
-extern void BIG_pxmul(DBIG x,BIG y,int i);
-/**	@brief Multiply BIG by another BIG resulting in DBIG - inputs normalised and output normalised
- *
-	@param x DBIG number, product of other two
-	@param y BIG number
-	@param z BIG number
- */
-extern void BIG_mul(DBIG x,BIG y,BIG z);
-/**	@brief Multiply BIG by another BIG resulting in another BIG - inputs normalised and output normalised
- *
-	Note that the product must fit into a BIG, and x must be distinct from y and z
-	@param x BIG number, product of other two
-	@param y BIG number
-	@param z BIG number
- */
-extern void BIG_smul(BIG x,BIG y,BIG z);
-/**	@brief Square BIG resulting in a DBIG - input normalised and output normalised
- *
-	@param x DBIG number, square of a BIG
-	@param y BIG number to be squared
- */
-extern void BIG_sqr(DBIG x,BIG y);
-/**	@brief Shifts a BIG left by any number of bits - input must be normalised, output normalised
- *
-	@param x BIG number to be shifted
-	@param s Number of bits to shift
- */
-extern void BIG_shl(BIG x,int s);
-/**	@brief Fast shifts a BIG left by a small number of bits - input must be normalised, output will be normalised
- *
-	The number of bits to be shifted must be less than BASEBITS
-	@param x BIG number to be shifted
-	@param s Number of bits to shift
-	@return Overflow bits
- */
-extern chunk BIG_fshl(BIG x,int s);
-/**	@brief Shifts a DBIG left by any number of bits - input must be normalised, output normalised
- *
-	@param x DBIG number to be shifted
-	@param s Number of bits to shift
- */
-extern void BIG_dshl(DBIG x,int s);
-/**	@brief Shifts a BIG right by any number of bits - input must be normalised, output normalised
- *
-	@param x BIG number to be shifted
-	@param s Number of bits to shift
- */
-extern void BIG_shr(BIG x,int s);
-/**	@brief Fast shifts a BIG right by a small number of bits - input must be normalised, output will be normalised
- *
-	The number of bits to be shifted must be less than BASEBITS
-	@param x BIG number to be shifted
-	@param s Number of bits to shift
-	@return Shifted out bits
- */
-extern chunk BIG_fshr(BIG x,int s);
-/**	@brief Shifts a DBIG right by any number of bits - input must be normalised, output normalised
- *
-	@param x DBIG number to be shifted
-	@param s Number of bits to shift
- */
-extern void BIG_dshr(DBIG x,int s);
-/**	@brief Splits a DBIG into two BIGs - input must be normalised, outputs normalised
- *
-	Internal function. The value of s must be approximately in the middle of the DBIG.
-	Typically used to extract z mod 2^MODBITS and z/2^MODBITS
-	@param x BIG number, top half of z
-	@param y BIG number, bottom half of z
-	@param z DBIG number to be split in two.
-	@param s Bit position at which to split
- */
-extern void BIG_split(BIG x,BIG y,DBIG z,int s);
-/**	@brief Normalizes a BIG number - output normalised
- *
-	All digits of the input BIG are reduced mod 2^BASEBITS
-	@param x BIG number to be normalised
- */
-extern chunk BIG_norm(BIG x);
-/**	@brief Normalizes a DBIG number - output normalised
- *
-	All digits of the input DBIG are reduced mod 2^BASEBITS
-	@param x DBIG number to be normalised
- */
-extern void BIG_dnorm(DBIG x);
-/**	@brief Compares two BIG numbers. Inputs must be normalised externally
- *
-	@param x first BIG number to be compared
-	@param y second BIG number to be compared
-	@return -1 is x<y, 0 if x=y, 1 if x>y
- */
-extern int BIG_comp(BIG x,BIG y);
-/**	@brief Compares two DBIG numbers. Inputs must be normalised externally
- *
-	@param x first DBIG number to be compared
-	@param y second DBIG number to be compared
-	@return -1 is x<y, 0 if x=y, 1 if x>y
- */
-extern int BIG_dcomp(DBIG x,DBIG y);
-/**	@brief Calculate number of bits in a BIG - output normalised
- *
-	@param x BIG number
-	@return Number of bits in x
- */
-extern int BIG_nbits(BIG x);
-/**	@brief Calculate number of bits in a DBIG - output normalised
- *
-	@param x DBIG number
-	@return Number of bits in x
- */
-extern int BIG_dnbits(DBIG x);
-/**	@brief Reduce x mod n - input and output normalised
- *
-	Slow but rarely used
-	@param x BIG number to be reduced mod n
-	@param n The modulus
- */
-extern void BIG_mod(BIG x,BIG n);
-/**	@brief Divide x by n - output normalised
- *
-	Slow but rarely used
-	@param x BIG number to be divided by n
-	@param n The Divisor
- */
-extern void BIG_sdiv(BIG x,BIG n);
-/**	@brief  x=y mod n - output normalised
- *
-	Slow but rarely used. y is destroyed.
-	@param x BIG number, on exit = y mod n
-	@param y DBIG number
-	@param n Modulus
- */
-extern void BIG_dmod(BIG x,DBIG y,BIG n);
-/**	@brief  x=y/n - output normalised
- *
-	Slow but rarely used. y is destroyed.
-	@param x BIG number, on exit = y/n
-	@param y DBIG number
-	@param n Modulus
- */
-extern void BIG_ddiv(BIG x,DBIG y,BIG n);
-/**	@brief  return parity of BIG, that is the least significant bit
- *
-	@param x BIG number
-	@return 0 or 1
- */
-extern int BIG_parity(BIG x);
-/**	@brief  return i-th of BIG
- *
-	@param x BIG number
-	@param i the bit of x to be returned
-	@return 0 or 1
- */
-extern int BIG_bit(BIG x,int i);
-/**	@brief  return least significant bits of a BIG
- *
-	@param x BIG number
-	@param n number of bits to return. Assumed to be less than BASEBITS.
-	@return least significant n bits as an integer
- */
-extern int BIG_lastbits(BIG x,int n);
-/**	@brief  Create a random BIG from a random number generator
- *
-	Assumes that the random number generator has been suitably initialised
-	@param x BIG number, on exit a random number
-	@param r A pointer to a Cryptographically Secure Random Number Generator
- */
-extern void BIG_random(BIG x,csprng *r);
-/**	@brief  Create an unbiased random BIG from a random number generator, reduced with respect to a modulus
- *
-	Assumes that the random number generator has been suitably initialised
-	@param x BIG number, on exit a random number
-	@param n The modulus
-	@param r A pointer to a Cryptographically Secure Random Number Generator
- */
-extern void BIG_randomnum(BIG x,BIG n,csprng *r);
-/**	@brief  return NAF (Non-Adjacent-Form) value as +/- 1, 3 or 5, inputs must be normalised
- *
-	Given x and 3*x extracts NAF value from given bit position, and returns number of bits processed, and number of trailing zeros detected if any
-	@param x BIG number
-	@param x3 BIG number, three times x
-	@param i bit position
-	@param nbs pointer to integer returning number of bits processed
-	@param nzs pointer to integer returning number of trailing 0s
-	@return + or - 1, 3 or 5
- */
-extern int BIG_nafbits(BIG x,BIG x3,int i,int *nbs,int *nzs);
-/**	@brief  Calculate x=y*z mod n
- *
-	Slow method for modular multiplication
-	@param x BIG number, on exit = y*z mod n
-	@param y BIG number
-	@param z BIG number
-	@param n The BIG Modulus
- */
-extern void BIG_modmul(BIG x,BIG y,BIG z,BIG n);
-/**	@brief  Calculate x=y/z mod n
- *
-	Slow method for modular division
-	@param x BIG number, on exit = y/z mod n
-	@param y BIG number
-	@param z BIG number
-	@param n The BIG Modulus
- */
-extern void BIG_moddiv(BIG x,BIG y,BIG z,BIG n);
-/**	@brief  Calculate x=y^2 mod n
- *
-	Slow method for modular squaring
-	@param x BIG number, on exit = y^2 mod n
-	@param y BIG number
-	@param n The BIG Modulus
- */
-extern void BIG_modsqr(BIG x,BIG y,BIG n);
-/**	@brief  Calculate x=-y mod n
- *
-	Modular negation
-	@param x BIG number, on exit = -y mod n
-	@param y BIG number
-	@param n The BIG Modulus
- */
-extern void BIG_modneg(BIG x,BIG y,BIG n);
-/**	@brief  Calculate jacobi Symbol (x/y)
- *
-	@param x BIG number
-	@param y BIG number
-	@return Jacobi symbol, -1,0 or 1
- */
-extern int BIG_jacobi(BIG x,BIG y);
-/**	@brief  Calculate x=1/y mod n
- *
-	Modular Inversion - This is slow. Uses binary method.
-	@param x BIG number, on exit = 1/y mod n
-	@param y BIG number
-	@param n The BIG Modulus
- */
-extern void BIG_invmodp(BIG x,BIG y,BIG n);
-
-
-
-/* FP prototypes */
-
-/**	@brief Tests for BIG equal to zero mod Modulus
- *
-	@param x BIG number to be tested
-	@return 1 if zero, else returns 0
- */
-extern int FP_iszilch(BIG x);
-/**	@brief Converts from BIG integer to n-residue form mod Modulus
- *
-	@param x BIG number to be converted
- */
-extern void FP_nres(BIG x);
-/**	@brief Converts from n-residue form back to BIG integer form
- *
-	@param x BIG number to be converted
- */
-extern void FP_redc(BIG x);
-/**	@brief Sets BIG to representation of unity in n-residue form
- *
-	@param x BIG number to be set equal to unity.
- */
-extern void FP_one(BIG x);
-/**	@brief Reduces DBIG to BIG exploiting special form of the modulus
- *
-	This function comes in different flavours depending on the form of Modulus that is currently in use.
-	@param x BIG number, on exit = y mod Modulus
-	@param y DBIG number to be reduced
- */
-extern void FP_mod(BIG x,DBIG y);
-/**	@brief Fast Modular multiplication of two BIGs in n-residue form, mod Modulus
- *
-	Uses appropriate fast modular reduction method
-	@param x BIG number, on exit the modular product = y*z mod Modulus
-	@param y BIG number, the multiplicand
-	@param z BIG number, the multiplier
- */
-extern void FP_mul(BIG x,BIG y,BIG z);
-/**	@brief Fast Modular multiplication of a BIG in n-residue form, by a small integer, mod Modulus
- *
-	@param x BIG number, on exit the modular product = y*i mod Modulus
-	@param y BIG number, the multiplicand
-	@param i a small number, the multiplier
- */
-extern void FP_imul(BIG x,BIG y,int i);
-/**	@brief Fast Modular squaring of a BIG in n-residue form, mod Modulus
- *
-	Uses appropriate fast modular reduction method
-	@param x BIG number, on exit the modular product = y^2 mod Modulus
-	@param y BIG number, the number to be squared
-
- */
-extern void FP_sqr(BIG x,BIG y);
-/**	@brief Modular addition of two BIGs in n-residue form, mod Modulus
- *
-	@param x BIG number, on exit the modular sum = y+z mod Modulus
-	@param y BIG number
-	@param z BIG number
- */
-extern void FP_add(BIG x,BIG y,BIG z);
-/**	@brief Modular subtraction of two BIGs in n-residue form, mod Modulus
- *
-	@param x BIG number, on exit the modular difference = y-z mod Modulus
-	@param y BIG number
-	@param z BIG number
- */
-extern void FP_sub(BIG x,BIG y,BIG z);
-/**	@brief Modular division by 2 of a BIG in n-residue form, mod Modulus
- *
-	@param x BIG number, on exit =y/2 mod Modulus
-	@param y BIG number
- */
-extern void FP_div2(BIG x,BIG y);
-/**	@brief Fast Modular exponentiation of a BIG in n-residue form, to the power of a BIG, mod Modulus
- *
-	@param x BIG number, on exit  = y^z mod Modulus
-	@param y BIG number
-	@param z Big number exponent
- */
-extern void FP_pow(BIG x,BIG y,BIG z);
-/**	@brief Fast Modular square root of a BIG in n-residue form, mod Modulus
- *
-	@param x BIG number, on exit  = sqrt(y) mod Modulus
-	@param y BIG number, the number whose square root is calculated
-
- */
-extern void FP_sqrt(BIG x,BIG y);
-/**	@brief Modular negation of a BIG in n-residue form, mod Modulus
- *
-	@param x BIG number, on exit = -y mod Modulus
-	@param y BIG number
- */
-extern void FP_neg(BIG x,BIG y);
-/**	@brief Outputs a BIG number that is in n-residue form to the console
- *
-	Converts from n-residue form before output
-	@param x a BIG number
- */
-extern void FP_output(BIG x);
-/**	@brief Outputs a BIG number that is in n-residue form to the console, in raw form
- *
-	Converts from n-residue form before output
-	@param x a BIG number
- */
-extern void FP_rawoutput(BIG x);
-/**	@brief Reduces possibly unreduced BIG mod Modulus
- *
-	@param x BIG number, on exit reduced mod Modulus
- */
-extern void FP_reduce(BIG x);
-/**	@brief Tests for BIG a quadratic residue mod Modulus
- *
-	@param x BIG number to be tested
-	@return 1 if quadratic residue, else returns 0 if quadratic non-residue
- */
-extern int FP_qr(BIG x);
-/**	@brief Modular inverse of a BIG in n-residue form, mod Modulus
- *
-	@param x BIG number, on exit = 1/y mod Modulus
-	@param y BIG number
- */
-extern void FP_inv(BIG x,BIG y);
-
-
-/* FP2 prototypes */
-
-/**	@brief Tests for FP2 equal to zero
- *
-	@param x FP2 number to be tested
-	@return 1 if zero, else returns 0
- */
-extern int FP2_iszilch(FP2 *x);
-/**	@brief Conditional copy of FP2 number
- *
-	Conditionally copies second parameter to the first (without branching)
-	@param x FP2 instance, set to y if s!=0
-	@param y another FP2 instance
-	@param s copy only takes place if not equal to 0
- */
-extern void FP2_cmove(FP2 *x,FP2 *y,int s);
-/**	@brief Tests for FP2 equal to one
- *
-	@param x FP2 instance to be tested
-	@return 1 if x=1, else returns 0
- */
-extern int FP2_isunity(FP2 *x);
-/**	@brief Tests for equality of two FP2s
- *
-	@param x FP2 instance to be compared
-	@param y FP2 instance to be compared
-	@return 1 if x=y, else returns 0
- */
-extern int FP2_equals(FP2 *x,FP2 *y);
-/**	@brief Initialise FP2 from two BIGs in n-residue form
- *
-	@param x FP2 instance to be initialised
-	@param a BIG to form real part of FP2
-	@param b BIG to form imaginary part of FP2
- */
-extern void FP2_from_FPs(FP2 *x,BIG a,BIG b);
-/**	@brief Initialise FP2 from two BIG integers
- *
-	@param x FP2 instance to be initialised
-	@param a BIG to form real part of FP2
-	@param b BIG to form imaginary part of FP2
- */
-extern void FP2_from_BIGs(FP2 *x,BIG a,BIG b);
-/**	@brief Initialise FP2 from single BIG in n-residue form
- *
-	Imaginary part is set to zero
-	@param x FP2 instance to be initialised
-	@param a BIG to form real part of FP2
- */
-extern void FP2_from_FP(FP2 *x,BIG a);
-/**	@brief Initialise FP2 from single BIG
- *
-	Imaginary part is set to zero
-	@param x FP2 instance to be initialised
-	@param a BIG to form real part of FP2
- */
-extern void FP2_from_BIG(FP2 *x,BIG a);
-/**	@brief Copy FP2 to another FP2
- *
-	@param x FP2 instance, on exit = y
-	@param y FP2 instance to be copied
- */
-extern void FP2_copy(FP2 *x,FP2 *y);
-/**	@brief Set FP2 to zero
- *
-	@param x FP2 instance to be set to zero
- */
-extern void FP2_zero(FP2 *x);
-/**	@brief Set FP2 to unity
- *
-	@param x FP2 instance to be set to one
- */
-extern void FP2_one(FP2 *x);
-/**	@brief Negation of FP2
- *
-	@param x FP2 instance, on exit = -y
-	@param y FP2 instance
- */
-extern void FP2_neg(FP2 *x,FP2 *y);
-/**	@brief Conjugation of FP2
- *
-	If y=(a,b) on exit x=(a,-b)
-	@param x FP2 instance, on exit = conj(y)
-	@param y FP2 instance
- */
-extern void FP2_conj(FP2 *x,FP2 *y);
-/**	@brief addition of two FP2s
- *
-	@param x FP2 instance, on exit = y+z
-	@param y FP2 instance
-	@param z FP2 instance
- */
-extern void FP2_add(FP2 *x,FP2 *y,FP2 *z);
-/**	@brief subtraction of two FP2s
- *
-	@param x FP2 instance, on exit = y-z
-	@param y FP2 instance
-	@param z FP2 instance
- */
-extern void FP2_sub(FP2 *x,FP2 *y,FP2 *z);
-/**	@brief Multiplication of an FP2 by an n-residue
- *
-	@param x FP2 instance, on exit = y*b
-	@param y FP2 instance
-	@param b BIG n-residue
- */
-extern void FP2_pmul(FP2 *x,FP2 *y,BIG b);
-/**	@brief Multiplication of an FP2 by a small integer
- *
-	@param x FP2 instance, on exit = y*i
-	@param y FP2 instance
-	@param i an integer
- */
-extern void FP2_imul(FP2 *x,FP2 *y,int i);
-/**	@brief Squaring an FP2
- *
-	@param x FP2 instance, on exit = y^2
-	@param y FP2 instance
- */
-extern void FP2_sqr(FP2 *x,FP2 *y);
-/**	@brief Multiplication of two FP2s
- *
-	@param x FP2 instance, on exit = y*z
-	@param y FP2 instance
-	@param z FP2 instance
- */
-extern void FP2_mul(FP2 *x,FP2 *y,FP2 *z);
-/**	@brief Formats and outputs an FP2 to the console
- *
-	@param x FP2 instance
- */
-extern void FP2_output(FP2 *x);
-/**	@brief Formats and outputs an FP2 to the console in raw form (for debugging)
- *
-	@param x FP2 instance
- */
-extern void FP2_rawoutput(FP2 *x);
-/**	@brief Inverting an FP2
- *
-	@param x FP2 instance, on exit = 1/y
-	@param y FP2 instance
- */
-extern void FP2_inv(FP2 *x,FP2 *y);
-/**	@brief Divide an FP2 by 2
- *
-	@param x FP2 instance, on exit = y/2
-	@param y FP2 instance
- */
-extern void FP2_div2(FP2 *x,FP2 *y);
-/**	@brief Multiply an FP2 by (1+sqrt(-1))
- *
-	Note that (1+sqrt(-1)) is irreducible for FP4
-	@param x FP2 instance, on exit = x*(1+sqrt(-1))
- */
-extern void FP2_mul_ip(FP2 *x);
-/**	@brief Divide an FP2 by (1+sqrt(-1))
- *
-	Note that (1+sqrt(-1)) is irreducible for FP4
-	@param x FP2 instance, on exit = x/(1+sqrt(-1))
- */
-extern void FP2_div_ip(FP2 *x);
-/**	@brief Normalises the components of an FP2
- *
-	@param x FP2 instance to be normalised
- */
-extern void FP2_norm(FP2 *x);
-/**	@brief Reduces all components of possibly unreduced FP2 mod Modulus
- *
-	@param x FP2 instance, on exit reduced mod Modulus
- */
-extern void FP2_reduce(FP2 *x);
-/**	@brief Raises an FP2 to the power of a BIG
- *
-	@param x FP2 instance, on exit = y^b
-	@param y FP2 instance
-	@param b BIG number
- */
-extern void FP2_pow(FP2 *x,FP2 *y,BIG b);
-/**	@brief Square root of an FP2
- *
-	@param x FP2 instance, on exit = sqrt(y)
-	@param y FP2 instance
- */
-extern int FP2_sqrt(FP2 *x,FP2 *y);
-
-
-
-/* ECP E(Fp) prototypes */
-/**	@brief Tests for ECP point equal to infinity
- *
-	@param P ECP point to be tested
-	@return 1 if infinity, else returns 0
- */
-extern int ECP_isinf(ECP *P);
-/**	@brief Tests for equality of two ECPs
- *
-	@param P ECP instance to be compared
-	@param Q ECP instance to be compared
-	@return 1 if P=Q, else returns 0
- */
-extern int ECP_equals(ECP *P,ECP *Q);
-/**	@brief Copy ECP point to another ECP point
- *
-	@param P ECP instance, on exit = Q
-	@param Q ECP instance to be copied
- */
-extern void ECP_copy(ECP *P,ECP *Q);
-/**	@brief Negation of an ECP point
- *
-	@param P ECP instance, on exit = -P
- */
-extern void ECP_neg(ECP *P);
-/**	@brief Set ECP to point-at-infinity
- *
-	@param P ECP instance to be set to infinity
- */
-extern void ECP_inf(ECP *P);
-/**	@brief Calculate Right Hand Side of curve equation y^2=f(x)
- *
-	Function f(x) depends on form of elliptic curve, Weierstrass, Edwards or Montgomery.
-	Used internally.
-	@param r BIG n-residue value of f(x)
-	@param x BIG n-residue x
- */
-extern void ECP_rhs(BIG r,BIG x);
-/**	@brief Set ECP to point(x,y) given just x and sign of y
- *
-	Point P set to infinity if no such point on the curve. If x is on the curve then y is calculated from the curve equation.
-	The correct y value (plus or minus) is selected given its sign s.
-	@param P ECP instance to be set (x,[y])
-	@param x BIG x coordinate of point
-	@param s an integer representing the "sign" of y, in fact its least significant bit.
- */
-extern int ECP_setx(ECP *P,BIG x,int s);
-
-#if CURVETYPE==MONTGOMERY
-/**	@brief Set ECP to point(x,[y]) given x
- *
-	Point P set to infinity if no such point on the curve. Note that y coordinate is not needed.
-	@param P ECP instance to be set (x,[y])
-	@param x BIG x coordinate of point
-	@return 1 if point exists, else 0
- */
-extern int ECP_set(ECP *P,BIG x);
-/**	@brief Extract x coordinate of an ECP point P
- *
-	@param x BIG on exit = x coordinate of point
-	@param P ECP instance (x,[y])
-	@return -1 if P is point-at-infinity, else 0
- */
-extern int ECP_get(BIG x,ECP *P);
-/**	@brief Adds ECP instance Q to ECP instance P, given difference D=P-Q
- *
-	Differential addition of points on a Montgomery curve
-	@param P ECP instance, on exit =P+Q
-	@param Q ECP instance to be added to P
-	@param D Difference between P and Q
- */
-extern void ECP_add(ECP *P,ECP *Q,ECP *D);
-#else
-/**	@brief Set ECP to point(x,y) given x and y
- *
-	Point P set to infinity if no such point on the curve.
-	@param P ECP instance to be set (x,y)
-	@param x BIG x coordinate of point
-	@param y BIG y coordinate of point
-	@return 1 if point exists, else 0
- */
-extern int ECP_set(ECP *P,BIG x,BIG y);
-/**	@brief Extract x and y coordinates of an ECP point P
- *
-	If x=y, returns only x
-	@param x BIG on exit = x coordinate of point
-	@param y BIG on exit = y coordinate of point (unless x=y)
-	@param P ECP instance (x,y)
-	@return sign of y, or -1 if P is point-at-infinity
- */
-extern int ECP_get(BIG x,BIG y,ECP *P);
-/**	@brief Adds ECP instance Q to ECP instance P
- *
-	@param P ECP instance, on exit =P+Q
-	@param Q ECP instance to be added to P
- */
-extern void ECP_add(ECP *P,ECP *Q);
-/**	@brief Subtracts ECP instance Q from ECP instance P
- *
-	@param P ECP instance, on exit =P-Q
-	@param Q ECP instance to be subtracted from P
- */
-extern void ECP_sub(ECP *P,ECP *Q);
-#endif
-/**	@brief Converts an ECP point from Projective (x,y,z) coordinates to affine (x,y) coordinates
- *
-	@param P ECP instance to be converted to affine form
- */
-extern void ECP_affine(ECP *P);
-/**	@brief Formats and outputs an ECP point to the console, in projective coordinates
- *
-	@param P ECP instance to be printed
- */
-extern void ECP_outputxyz(ECP *P);
-/**	@brief Formats and outputs an ECP point to the console, converted to affine coordinates
- *
-	@param P ECP instance to be printed
- */
-extern void ECP_output(ECP * P);
-/**	@brief Formats and outputs an ECP point to an octet string
- *
-	The octet string is created in the standard form 04|x|y, except for Montgomery curve in which case it is 06|x
-	Here x (and y) are the x and y coordinates in big-endian base 256 form.
-	@param S output octet string
-	@param P ECP instance to be converted to an octet string
- */
-extern void ECP_toOctet(octet *S,ECP *P);
-/**	@brief Creates an ECP point from an octet string
- *
-	The octet string is in the standard form 0x04|x|y, except for Montgomery curve in which case it is 0x06|x
-	Here x (and y) are the x and y coordinates in left justified big-endian base 256 form.
-	@param P ECP instance to be created from the octet string
-	@param S input octet string
-	return 1 if octet string corresponds to a point on the curve, else 0
- */
-extern int ECP_fromOctet(ECP *P,octet *S);
-/**	@brief Doubles an ECP instance P
- *
-	@param P ECP instance, on exit =2*P
- */
-extern void ECP_dbl(ECP *P);
-/**	@brief Multiplies an ECP instance P by a small integer, side-channel resistant
- *
-	@param P ECP instance, on exit =i*P
-	@param i small integer multiplier
-	@param b maximum number of bits in multiplier
- */
-extern void ECP_pinmul(ECP *P,int i,int b);
-/**	@brief Multiplies an ECP instance P by a BIG, side-channel resistant
- *
-	Uses Montgomery ladder for Montgomery curves, otherwise fixed sized windows.
-	@param P ECP instance, on exit =b*P
-	@param b BIG number multiplier
-
- */
-extern void ECP_mul(ECP *P,BIG b);
-/**	@brief Calculates double multiplication P=e*P+f*Q, side-channel resistant
- *
-	@param P ECP instance, on exit =e*P+f*Q
-	@param Q ECP instance
-	@param e BIG number multiplier
-	@param f BIG number multiplier
- */
-extern void ECP_mul2(ECP *P,ECP *Q,BIG e,BIG f);
-
-
-
-/* ECP2 E(Fp2) prototypes */
-/**	@brief Tests for ECP2 point equal to infinity
- *
-	@param P ECP2 point to be tested
-	@return 1 if infinity, else returns 0
- */
-extern int ECP2_isinf(ECP2 *P);
-/**	@brief Copy ECP2 point to another ECP2 point
- *
-	@param P ECP2 instance, on exit = Q
-	@param Q ECP2 instance to be copied
- */
-extern void ECP2_copy(ECP2 *P,ECP2 *Q);
-/**	@brief Set ECP2 to point-at-infinity
- *
-	@param P ECP2 instance to be set to infinity
- */
-extern void ECP2_inf(ECP2 *P);
-/**	@brief Tests for equality of two ECP2s
- *
-	@param P ECP2 instance to be compared
-	@param Q ECP2 instance to be compared
-	@return 1 if P=Q, else returns 0
- */
-extern int ECP2_equals(ECP2 *P,ECP2 *Q);
-/**	@brief Converts an ECP2 point from Projective (x,y,z) coordinates to affine (x,y) coordinates
- *
-	@param P ECP2 instance to be converted to affine form
- */
-extern void ECP2_affine(ECP2 *P);
-/**	@brief Extract x and y coordinates of an ECP2 point P
- *
-	If x=y, returns only x
-	@param x FP2 on exit = x coordinate of point
-	@param y FP2 on exit = y coordinate of point (unless x=y)
-	@param P ECP2 instance (x,y)
-	@return -1 if P is point-at-infinity, else 0
- */
-extern int ECP2_get(FP2 *x,FP2 *y,ECP2 *P);
-/**	@brief Formats and outputs an ECP2 point to the console, converted to affine coordinates
- *
-	@param P ECP2 instance to be printed
- */
-extern void ECP2_output(ECP2 *P);
-/**	@brief Formats and outputs an ECP2 point to the console, in projective coordinates
- *
-	@param P ECP2 instance to be printed
- */
-extern void ECP2_outputxyz(ECP2 *P);
-/**	@brief Formats and outputs an ECP2 point to an octet string
- *
-	The octet string is created in the form x|y.
-	Convert the real and imaginary parts of the x and y coordinates to big-endian base 256 form.
-	@param S output octet string
-	@param P ECP2 instance to be converted to an octet string
- */
-extern void ECP2_toOctet(octet *S,ECP2 *P);
-/**	@brief Creates an ECP2 point from an octet string
- *
-	The octet string is in the form x|y
-	The real and imaginary parts of the x and y coordinates are in big-endian base 256 form.
-	@param P ECP2 instance to be created from the octet string
-	@param S input octet string
-	return 1 if octet string corresponds to a point on the curve, else 0
- */
-extern int ECP2_fromOctet(ECP2 *P,octet *S);
-/**	@brief Calculate Right Hand Side of curve equation y^2=f(x)
- *
-	Function f(x)=x^3+Ax+B
-	Used internally.
-	@param r FP2 value of f(x)
-	@param x FP2 instance
- */
-extern void ECP2_rhs(FP2 *r,FP2 *x);
-/**	@brief Set ECP2 to point(x,y) given x and y
- *
-	Point P set to infinity if no such point on the curve.
-	@param P ECP2 instance to be set (x,y)
-	@param x FP2 x coordinate of point
-	@param y FP2 y coordinate of point
-	@return 1 if point exists, else 0
- */
-extern int ECP2_set(ECP2 *P,FP2 *x,FP2 *y);
-/**	@brief Set ECP to point(x,[y]) given x
- *
-	Point P set to infinity if no such point on the curve. Otherwise y coordinate is calculated from x.
-	@param P ECP instance to be set (x,[y])
-	@param x BIG x coordinate of point
-	@return 1 if point exists, else 0
- */
-extern int ECP2_setx(ECP2 *P,FP2 *x);
-/**	@brief Negation of an ECP2 point
- *
-	@param P ECP2 instance, on exit = -P
- */
-extern void ECP2_neg(ECP2 *P);
-/**	@brief Doubles an ECP2 instance P
- *
-	@param P ECP2 instance, on exit =2*P
- */
-extern int ECP2_dbl(ECP2 *P);
-/**	@brief Adds ECP2 instance Q to ECP2 instance P
- *
-	@param P ECP2 instance, on exit =P+Q
-	@param Q ECP2 instance to be added to P
- */
-extern int ECP2_add(ECP2 *P,ECP2 *Q);
-/**	@brief Subtracts ECP instance Q from ECP2 instance P
- *
-	@param P ECP2 instance, on exit =P-Q
-	@param Q ECP2 instance to be subtracted from P
- */
-extern void ECP2_sub(ECP2 *P,ECP2 *Q);
-/**	@brief Multiplies an ECP2 instance P by a BIG, side-channel resistant
- *
-	Uses fixed sized windows.
-	@param P ECP2 instance, on exit =b*P
-	@param b BIG number multiplier
-
- */
-extern void ECP2_mul(ECP2 *P,BIG b);
-/**	@brief Multiplies an ECP2 instance P by the internal modulus p, using precalculated Frobenius constant f
- *
-	Fast point multiplication using Frobenius
-	@param P ECP2 instance, on exit = p*P
-	@param f FP2 precalculated Frobenius constant
-
- */
-extern void ECP2_frob(ECP2 *P,FP2 *f);
-/**	@brief Calculates P=b[0]*Q[0]+b[1]*Q[1]+b[2]*Q[2]+b[3]*Q[3]
- *
-	@param P ECP2 instance, on exit = b[0]*Q[0]+b[1]*Q[1]+b[2]*Q[2]+b[3]*Q[3]
-	@param Q ECP2 array of 4 points
-	@param b BIG array of 4 multipliers
- */
-extern void ECP2_mul4(ECP2 *P,ECP2 *Q,BIG *b);
-
-
-
-/* FP4 prototypes */
-/**	@brief Tests for FP4 equal to zero
- *
-	@param x FP4 number to be tested
-	@return 1 if zero, else returns 0
- */
-extern int FP4_iszilch(FP4 *x);
-/**	@brief Tests for FP4 equal to unity
- *
-	@param x FP4 number to be tested
-	@return 1 if unity, else returns 0
- */
-extern int FP4_isunity(FP4 *x);
-/**	@brief Tests for equality of two FP4s
- *
-	@param x FP4 instance to be compared
-	@param y FP4 instance to be compared
-	@return 1 if x=y, else returns 0
- */
-extern int FP4_equals(FP4 *x,FP4 *y);
-/**	@brief Tests for FP4 having only a real part and no imaginary part
- *
-	@param x FP4 number to be tested
-	@return 1 if real, else returns 0
- */
-extern int FP4_isreal(FP4 *x);
-/**	@brief Initialise FP4 from two FP2s
- *
-	@param x FP4 instance to be initialised
-	@param a FP2 to form real part of FP4
-	@param b FP2 to form imaginary part of FP4
- */
-extern void FP4_from_FP2s(FP4 *x,FP2 *a,FP2 *b);
-/**	@brief Initialise FP4 from single FP2
- *
-	Imaginary part is set to zero
-	@param x FP4 instance to be initialised
-	@param a FP2 to form real part of FP4
- */
-extern void FP4_from_FP2(FP4 *x,FP2 *a);
-/**	@brief Copy FP4 to another FP4
- *
-	@param x FP4 instance, on exit = y
-	@param y FP4 instance to be copied
- */
-extern void FP4_copy(FP4 *x,FP4 *y);
-/**	@brief Set FP4 to zero
- *
-	@param x FP4 instance to be set to zero
- */
-extern void FP4_zero(FP4 *x);
-/**	@brief Set FP4 to unity
- *
-	@param x FP4 instance to be set to one
- */
-extern void FP4_one(FP4 *x);
-/**	@brief Negation of FP4
- *
-	@param x FP4 instance, on exit = -y
-	@param y FP4 instance
- */
-extern void FP4_neg(FP4 *x,FP4 *y);
-/**	@brief Conjugation of FP4
- *
-	If y=(a,b) on exit x=(a,-b)
-	@param x FP4 instance, on exit = conj(y)
-	@param y FP4 instance
- */
-extern void FP4_conj(FP4 *x,FP4 *y);
-/**	@brief Negative conjugation of FP4
- *
-	If y=(a,b) on exit x=(-a,b)
-	@param x FP4 instance, on exit = -conj(y)
-	@param y FP4 instance
- */
-extern void FP4_nconj(FP4 *x,FP4 *y);
-/**	@brief addition of two FP4s
- *
-	@param x FP4 instance, on exit = y+z
-	@param y FP4 instance
-	@param z FP4 instance
- */
-extern void FP4_add(FP4 *x,FP4 *y,FP4 *z);
-/**	@brief subtraction of two FP4s
- *
-	@param x FP4 instance, on exit = y-z
-	@param y FP4 instance
-	@param z FP4 instance
- */
-extern void FP4_sub(FP4 *x,FP4 *y,FP4 *z);
-/**	@brief Multiplication of an FP4 by an FP2
- *
-	@param x FP4 instance, on exit = y*a
-	@param y FP4 instance
-	@param a FP2 multiplier
- */
-extern void FP4_pmul(FP4 *x,FP4 *y,FP2 *a);
-/**	@brief Multiplication of an FP4 by a small integer
- *
-	@param x FP4 instance, on exit = y*i
-	@param y FP4 instance
-	@param i an integer
- */
-extern void FP4_imul(FP4 *x,FP4 *y,int i);
-/**	@brief Squaring an FP4
- *
-	@param x FP4 instance, on exit = y^2
-	@param y FP4 instance
- */
-extern void FP4_sqr(FP4 *x,FP4 *y);
-/**	@brief Multiplication of two FP4s
- *
-	@param x FP4 instance, on exit = y*z
-	@param y FP4 instance
-	@param z FP4 instance
- */
-extern void FP4_mul(FP4 *x,FP4 *y,FP4 *z);
-/**	@brief Inverting an FP4
- *
-	@param x FP4 instance, on exit = 1/y
-	@param y FP4 instance
- */
-extern void FP4_inv(FP4 *x,FP4 *y);
-/**	@brief Formats and outputs an FP4 to the console
- *
-	@param x FP4 instance to be printed
- */
-extern void FP4_output(FP4 *x);
-/**	@brief Formats and outputs an FP4 to the console in raw form (for debugging)
- *
-	@param x FP4 instance to be printed
- */
-extern void FP4_rawoutput(FP4 *x);
-/**	@brief multiplies an FP4 instance by irreducible polynomial sqrt(1+sqrt(-1))
- *
-	@param x FP4 instance, on exit = sqrt(1+sqrt(-1)*x
- */
-extern void FP4_times_i(FP4 *x);
-/**	@brief Normalises the components of an FP4
- *
-	@param x FP4 instance to be normalised
- */
-extern void FP4_norm(FP4 *x);
-/**	@brief Reduces all components of possibly unreduced FP4 mod Modulus
- *
-	@param x FP4 instance, on exit reduced mod Modulus
- */
-extern void FP4_reduce(FP4 *x);
-/**	@brief Raises an FP4 to the power of a BIG
- *
-	@param x FP4 instance, on exit = y^b
-	@param y FP4 instance
-	@param b BIG number
- */
-extern void FP4_pow(FP4 *x,FP4 *y,BIG b);
-/**	@brief Raises an FP4 to the power of the internal modulus p, using the Frobenius
- *
-	@param x FP4 instance, on exit = x^p
-	@param f FP2 precalculated Frobenius constant
- */
-extern void FP4_frob(FP4 *x,FP2 *f);
-/**	@brief Calculates the XTR addition function r=w*x-conj(x)*y+z
- *
-	@param r FP4 instance, on exit = w*x-conj(x)*y+z
-	@param w FP4 instance
-	@param x FP4 instance
-	@param y FP4 instance
-	@param z FP4 instance
- */
-extern void FP4_xtr_A(FP4 *r,FP4 *w,FP4 *x,FP4 *y,FP4 *z);
-/**	@brief Calculates the XTR doubling function r=x^2-2*conj(x)
- *
-	@param r FP4 instance, on exit = x^2-2*conj(x)
-	@param x FP4 instance
- */
-extern void FP4_xtr_D(FP4 *r,FP4 *x);
-/**	@brief Calculates FP4 trace of an FP12 raised to the power of a BIG number
- *
-	XTR single exponentiation
-	@param r FP4 instance, on exit = trace(w^b)
-	@param x FP4 instance, trace of an FP12 w
-	@param b BIG number
- */
-extern void FP4_xtr_pow(FP4 *r,FP4 *x,BIG b);
-/**	@brief Calculates FP4 trace of c^a.d^b, where c and d are derived from FP4 traces of FP12s
- *
-	XTR double exponentiation
-	Assumes c=tr(x^m), d=tr(x^n), e=tr(x^(m-n)), f=tr(x^(m-2n))
-	@param r FP4 instance, on exit = trace(c^a.d^b)
-	@param c FP4 instance, trace of an FP12
-	@param d FP4 instance, trace of an FP12
-	@param e FP4 instance, trace of an FP12
-	@param f FP4 instance, trace of an FP12
-	@param a BIG number
-	@param b BIG number
- */
-extern void FP4_xtr_pow2(FP4 *r,FP4 *c,FP4 *d,FP4 *e,FP4 *f,BIG a,BIG b);
-
-
-
-/* FP12 prototypes */
-/**	@brief Tests for FP12 equal to zero
- *
-	@param x FP12 number to be tested
-	@return 1 if zero, else returns 0
- */
-extern int FP12_iszilch(FP12 *x);
-/**	@brief Tests for FP12 equal to unity
- *
-	@param x FP12 number to be tested
-	@return 1 if unity, else returns 0
- */
-extern int FP12_isunity(FP12 *x);
-/**	@brief Copy FP12 to another FP12
- *
-	@param x FP12 instance, on exit = y
-	@param y FP12 instance to be copied
- */
-extern void FP12_copy(FP12 *x,FP12 *y);
-/**	@brief Set FP12 to unity
- *
-	@param x FP12 instance to be set to one
- */
-extern void FP12_one(FP12 *x);
-/**	@brief Tests for equality of two FP12s
- *
-	@param x FP12 instance to be compared
-	@param y FP12 instance to be compared
-	@return 1 if x=y, else returns 0
- */
-extern int FP12_equals(FP12 *x,FP12 *y);
-/**	@brief Conjugation of FP12
- *
-	If y=(a,b,c) (where a,b,c are its three FP4 components) on exit x=(conj(a),-conj(b),conj(c))
-	@param x FP12 instance, on exit = conj(y)
-	@param y FP12 instance
- */
-extern void FP12_conj(FP12 *x,FP12 *y);
-/**	@brief Initialise FP12 from single FP4
- *
-	Sets first FP4 component of an FP12, other components set to zero
-	@param x FP12 instance to be initialised
-	@param a FP4 to form first part of FP4
- */
-extern void FP12_from_FP4(FP12 *x,FP4 *a);
-/**	@brief Initialise FP12 from three FP4s
- *
-	@param x FP12 instance to be initialised
-	@param a FP4 to form first part of FP12
-	@param b FP4 to form second part of FP12
-	@param c FP4 to form third part of FP12
- */
-extern void FP12_from_FP4s(FP12 *x,FP4 *a,FP4* b,FP4 *c);
-/**	@brief Fast Squaring of an FP12 in "unitary" form
- *
-	@param x FP12 instance, on exit = y^2
-	@param y FP4 instance, must be unitary
- */
-extern void FP12_usqr(FP12 *x,FP12 *y);
-/**	@brief Squaring an FP12
- *
-	@param x FP12 instance, on exit = y^2
-	@param y FP12 instance
- */
-extern void FP12_sqr(FP12 *x,FP12 *y);
-/**	@brief Fast multiplication of an FP12 by an FP12 that arises from an ATE pairing line function
- *
-	Here the multiplier has a special form that can be exploited
-	@param x FP12 instance, on exit = x*y
-	@param y FP12 instance, of special form
- */
-extern void FP12_smul(FP12 *x,FP12 *y);
-/**	@brief Multiplication of two FP12s
- *
-	@param x FP12 instance, on exit = x*y
-	@param y FP12 instance, the multiplier
- */
-extern void FP12_mul(FP12 *x,FP12 *y);
-/**	@brief Inverting an FP12
- *
-	@param x FP12 instance, on exit = 1/y
-	@param y FP12 instance
- */
-extern void FP12_inv(FP12 *x,FP12 *y);
-/**	@brief Raises an FP12 to the power of a BIG
- *
-	@param r FP12 instance, on exit = y^b
-	@param x FP12 instance
-	@param b BIG number
- */
-extern void FP12_pow(FP12 *r,FP12 *x,BIG b);
-/**	@brief Raises an FP12 instance x to a small integer power, side-channel resistant
- *
-	@param x ECP instance, on exit = x^i
-	@param i small integer exponent
-	@param b maximum number of bits in exponent
- */
-extern void FP12_pinpow(FP12 *x,int i,int b);
-/**	@brief Calculate x[0]^b[0].x[1]^b[1].x[2]^b[2].x[3]^b[3], side-channel resistant
- *
-	@param r ECP instance, on exit = x[0]^b[0].x[1]^b[1].x[2]^b[2].x[3]^b[3]
-	@param x FP12 array with 4 FP12s
-	@param b BIG array of 4 exponents
- */
-extern void FP12_pow4(FP12 *r,FP12 *x,BIG *b);
-/**	@brief Raises an FP12 to the power of the internal modulus p, using the Frobenius
- *
-	@param x FP12 instance, on exit = x^p
-	@param f FP2 precalculated Frobenius constant
- */
-extern void FP12_frob(FP12 *x,FP2 *f);
-/**	@brief Reduces all components of possibly unreduced FP12 mod Modulus
- *
-	@param x FP12 instance, on exit reduced mod Modulus
- */
-extern void FP12_reduce(FP12 *x);
-/**	@brief Normalises the components of an FP12
- *
-	@param x FP12 instance to be normalised
- */
-extern void FP12_norm(FP12 *x);
-/**	@brief Formats and outputs an FP12 to the console
- *
-	@param x FP12 instance to be printed
- */
-extern void FP12_output(FP12 *x);
-/**	@brief Formats and outputs an FP12 instance to an octet string
- *
-	Serializes the components of an FP12 to big-endian base 256 form.
-	@param S output octet string
-	@param x FP12 instance to be converted to an octet string
- */
-extern void FP12_toOctet(octet *S,FP12 *x);
-/**	@brief Creates an FP12 instance from an octet string
- *
-	De-serializes the components of an FP12 to create an FP12 from big-endian base 256 components.
-	@param x FP12 instance to be created from an octet string
-	@param S input octet string
-
- */
-extern void FP12_fromOctet(FP12 *x,octet *S);
-/**	@brief Calculate the trace of an FP12
- *
-	@param t FP4 trace of x, on exit = tr(x)
-	@param x FP12 instance
-
- */
-extern void FP12_trace(FP4 *t,FP12 *x);
-
-
-
-/* Pairing function prototypes */
-/**	@brief Calculate Miller loop for Optimal ATE pairing e(P,Q)
- *
-	@param r FP12 result of the pairing calculation e(P,Q)
-	@param P ECP2 instance, an element of G2
-	@param Q ECP instance, an element of G1
-
- */
-extern void PAIR_ate(FP12 *r,ECP2 *P,ECP *Q);
-/**	@brief Calculate Miller loop for Optimal ATE double-pairing e(P,Q).e(R,S)
- *
-	Faster than calculating two separate pairings
-	@param r FP12 result of the pairing calculation e(P,Q).e(R,S), an element of GT
-	@param P ECP2 instance, an element of G2
-	@param Q ECP instance, an element of G1
-	@param R ECP2 instance, an element of G2
-	@param S ECP instance, an element of G1
- */
-extern void PAIR_double_ate(FP12 *r,ECP2 *P,ECP *Q,ECP2 *R,ECP *S);
-/**	@brief Final exponentiation of pairing, converts output of Miller loop to element in GT
- *
-	Here p is the internal modulus, and r is the group order
-	@param x FP12, on exit = x^((p^12-1)/r)
- */
-extern void PAIR_fexp(FP12 *x);
-/**	@brief Fast point multiplication of a member of the group G1 by a BIG number
- *
-	May exploit endomorphism for speed.
-	@param Q ECP member of G1.
-	@param b BIG multiplier
-
- */
-extern void PAIR_G1mul(ECP *Q,BIG b);
-/**	@brief Fast point multiplication of a member of the group G2 by a BIG number
- *
-	May exploit endomorphism for speed.
-	@param P ECP2 member of G1.
-	@param b BIG multiplier
-
- */
-extern void PAIR_G2mul(ECP2 *P,BIG b);
-/**	@brief Fast raising of a member of GT to a BIG power
- *
-	May exploit endomorphism for speed.
-	@param x FP12 member of GT.
-	@param b BIG exponent
-
- */
-extern void PAIR_GTpow(FP12 *x,BIG b);
-/**	@brief Tests FP12 for membership of GT
- *
-	@param x FP12 instance
-	@return 1 if x is in GT, else return 0
-
- */
-extern int PAIR_GTmember(FP12 *x);
-
-
-
-/* Finite Field Prototypes */
-/**	@brief Copy one FF element of given length to another
- *
-	@param x FF instance to be copied to, on exit = y
-	@param y FF instance to be copied from
-	@param n size of FF in BIGs
-
- */
-extern void FF_copy(BIG *x,BIG *y,int n);
-/**	@brief Initialize an FF element of given length from a 32-bit integer m
- *
-	@param x FF instance to be copied to, on exit = m
-	@param m integer
-	@param n size of FF in BIGs
- */
-extern void FF_init(BIG *x,sign32 m,int n);
-/**	@brief Set FF element of given size to zero
- *
-	@param x FF instance to be set to zero
-	@param n size of FF in BIGs
- */
-extern void FF_zero(BIG *x,int n);
-/**	@brief Tests for FF element equal to zero
- *
-	@param x FF number to be tested
-	@param n size of FF in BIGs
-	@return 1 if zero, else returns 0
- */
-extern int FF_iszilch(BIG *x,int n);
-/**	@brief  return parity of an FF, that is the least significant bit
- *
-	@param x FF number
-	@return 0 or 1
- */
-extern int FF_parity(BIG *x);
-/**	@brief  return least significant m bits of an FF
- *
-	@param x FF number
-	@param m number of bits to return. Assumed to be less than BASEBITS.
-	@return least significant n bits as an integer
- */
-extern int FF_lastbits(BIG *x,int m);
-/**	@brief Set FF element of given size to unity
- *
-	@param x FF instance to be set to unity
-	@param n size of FF in BIGs
- */
-extern void FF_one(BIG *x,int n);
-/**	@brief Compares two FF numbers. Inputs must be normalised externally
- *
-	@param x first FF number to be compared
-	@param y second FF number to be compared
-	@param n size of FF in BIGs
-	@return -1 is x<y, 0 if x=y, 1 if x>y
- */
-extern int FF_comp(BIG *x,BIG *y,int n);
-/**	@brief addition of two FFs
- *
-	@param x FF instance, on exit = y+z
-	@param y FF instance
-	@param z FF instance
-	@param n size of FF in BIGs
- */
-extern void FF_add(BIG *x,BIG *y,BIG *z,int n);
-/**	@brief subtraction of two FFs
- *
-	@param x FF instance, on exit = y-z
-	@param y FF instance
-	@param z FF instance
-	@param n size of FF in BIGs
- */
-extern void FF_sub(BIG *x,BIG *y,BIG *z,int n);
-/**	@brief increment an FF by an integer,and normalise
- *
-	@param x FF instance, on exit = x+m
-	@param m an integer to be added to x
-	@param n size of FF in BIGs
- */
-extern void FF_inc(BIG *x,int m,int n);
-/**	@brief Decrement an FF by an integer,and normalise
- *
-	@param x FF instance, on exit = x-m
-	@param m an integer to be subtracted from x
-	@param n size of FF in BIGs
- */
-extern void FF_dec(BIG *x,int m,int n);
-/**	@brief Normalises the components of an FF
- *
-	@param x FF instance to be normalised
-	@param n size of FF in BIGs
- */
-extern void FF_norm(BIG *x,int n);
-/**	@brief Shift left an FF by 1 bit
- *
-	@param x FF instance to be shifted left
-	@param n size of FF in BIGs
- */
-extern void FF_shl(BIG *x,int n);
-/**	@brief Shift right an FF by 1 bit
- *
-	@param x FF instance to be shifted right
-	@param n size of FF in BIGs
- */
-extern void FF_shr(BIG *x,int n);
-/**	@brief Formats and outputs an FF to the console
- *
-	@param x FF instance to be printed
-	@param n size of FF in BIGs
- */
-extern void FF_output(BIG *x,int n);
-/**	@brief Formats and outputs an FF instance to an octet string
- *
-	Converts an FF to big-endian base 256 form.
-	@param S output octet string
-	@param x FF instance to be converted to an octet string
-	@param n size of FF in BIGs
- */
-extern void FF_toOctet(octet *S,BIG *x,int n);
-/**	@brief Populates an FF instance from an octet string
- *
-	Creates FF from big-endian base 256 form.
-	@param x FF instance to be created from an octet string
-	@param S input octet string
-	@param n size of FF in BIGs
- */
-extern void FF_fromOctet(BIG *x,octet *S,int n);
-/**	@brief Multiplication of two FFs
- *
-	Uses Karatsuba method internally
-	@param x FF instance, on exit = y*z
-	@param y FF instance
-	@param z FF instance
-	@param n size of FF in BIGs
- */
-extern void FF_mul(BIG *x,BIG *y,BIG *z,int n);
-/**	@brief Reduce FF mod a modulus
- *
-	This is slow
-	@param x FF instance to be reduced mod m - on exit = x mod m
-	@param m FF modulus
-	@param n size of FF in BIGs
- */
-extern void FF_mod(BIG *x,BIG *m,int n);
-/**	@brief Square an FF
- *
-	Uses Karatsuba method internally
-	@param x FF instance, on exit = y^2
-	@param y FF instance to be squared
-	@param n size of FF in BIGs
- */
-extern void FF_sqr(BIG *x,BIG *y,int n);
-/**	@brief Reduces a double-length FF with respect to a given modulus
- *
-	This is slow
-	@param x FF instance, on exit = y mod z
-	@param y FF instance, of double length 2*n
-	@param z FF modulus
-	@param n size of FF in BIGs
- */
-extern void FF_dmod(BIG *x,BIG *y,BIG *z,int n);
-/**	@brief Invert an FF mod a prime modulus
- *
-	@param x FF instance, on exit = 1/y mod z
-	@param y FF instance
-	@param z FF prime modulus
-	@param n size of FF in BIGs
- */
-extern void FF_invmodp(BIG *x,BIG *y,BIG *z,int n);
-/**	@brief Create an FF from a random number generator
- *
-	@param x FF instance, on exit x is a random number of length n BIGs with most significant bit a 1
-	@param R an instance of a Cryptographically Secure Random Number Generator
-	@param n size of FF in BIGs
- */
-extern void FF_random(BIG *x,csprng *R,int n);
-/**	@brief Create a random FF less than a given modulus from a random number generator
- *
-	@param x FF instance, on exit x is a random number < y
-	@param y FF instance, the modulus
-	@param R an instance of a Cryptographically Secure Random Number Generator
-	@param n size of FF in BIGs
- */
-extern void FF_randomnum(BIG *x,BIG *y,csprng *R,int n);
-/**	@brief Calculate r=x^e mod m, side channel resistant
- *
-	@param r FF instance, on exit = x^e mod p
-	@param x FF instance
-	@param e FF exponent
-	@param m FF modulus
-	@param n size of FF in BIGs
- */
-extern void FF_skpow(BIG *r,BIG *x,BIG * e,BIG *m,int n);
-/**	@brief Calculate r=x^e mod m, side channel resistant
- *
-	For short BIG exponent
-	@param r FF instance, on exit = x^e mod p
-	@param x FF instance
-	@param e BIG exponent
-	@param m FF modulus
-	@param n size of FF in BIGs
- */
-extern void FF_skspow(BIG *r,BIG *x,BIG e,BIG *m,int n);
-/**	@brief Calculate r=x^e mod m
- *
-	For very short integer exponent
-	@param r FF instance, on exit = x^e mod p
-	@param x FF instance
-	@param e integer exponent
-	@param m FF modulus
-	@param n size of FF in BIGs
- */
-extern void FF_power(BIG *r,BIG *x,int e,BIG *m,int n);
-/**	@brief Calculate r=x^e mod m
- *
-	@param r FF instance, on exit = x^e mod p
-	@param x FF instance
-	@param e FF exponent
-	@param m FF modulus
-	@param n size of FF in BIGs
- */
-extern void FF_pow(BIG *r,BIG *x,BIG *e,BIG *m,int n);
-/**	@brief Test if an FF has factor in common with integer s
- *
-	@param x FF instance to be tested
-	@param s the supplied integer
-	@param n size of FF in BIGs
-	@return 1 if gcd(x,s)!=1, else return 0
- */
-extern int FF_cfactor(BIG *x,sign32 s,int n);
-/**	@brief Test if an FF is prime
- *
-	Uses Miller-Rabin Method
-	@param x FF instance to be tested
-	@param R an instance of a Cryptographically Secure Random Number Generator
-	@param n size of FF in BIGs
-	@return 1 if x is (almost certainly) prime, else return 0
- */
-extern int FF_prime(BIG *x,csprng *R,int n);
-/**	@brief Calculate r=x^e.y^f mod m
- *
-	@param r FF instance, on exit = x^e.y^f mod p
-	@param x FF instance
-	@param e BIG exponent
-	@param y FF instance
-	@param f BIG exponent
-	@param m FF modulus
-	@param n size of FF in BIGs
- */
-extern void FF_pow2(BIG *r,BIG *x,BIG e,BIG *y,BIG f,BIG *m,int n);
-
-
-/* Octet string handlers */
-/**	@brief Formats and outputs an octet to the console in hex
- *
-	@param O Octet to be output
- */
-extern void OCT_output(octet *O);
-/**	@brief Formats and outputs an octet to the console as a character string
- *
-	@param O Octet to be output
- */
-extern void OCT_output_string(octet *O);
-/**	@brief Wipe clean an octet
- *
-	@param O Octet to be cleaned
- */
-extern void OCT_clear(octet *O);
-/**	@brief Compare two octets
- *
-	@param O first Octet to be compared
-	@param P second Octet to be compared
-	@return 1 if equal, else 0
- */
-extern int  OCT_comp(octet *O,octet *P);
-/**	@brief Compare first n bytes of two octets
- *
-	@param O first Octet to be compared
-	@param P second Octet to be compared
-	@param n number of bytes to compare
-	@return 1 if equal, else 0
- */
-extern int  OCT_ncomp(octet *O,octet *P,int n);
-/**	@brief Join from a C string to end of an octet
- *
-	Truncates if there is no room
-	@param O Octet to be written to
-	@param s zero terminated string to be joined to octet
- */
-extern void OCT_jstring(octet *O,char *s);
-/**	@brief Join bytes to end of an octet
- *
-	Truncates if there is no room
-	@param O Octet to be written to
-	@param s bytes to be joined to end of octet
-	@param n number of bytes to join
- */
-extern void OCT_jbytes(octet *O,char *s,int n);
-/**	@brief Join single byte to end of an octet, repeated n times
- *
-	Truncates if there is no room
-	@param O Octet to be written to
-	@param b byte to be joined to end of octet
-	@param n number of times b is to be joined
- */
-extern void OCT_jbyte(octet *O,int b,int n);
-/**	@brief Join one octet to the end of another
- *
-	Truncates if there is no room
-	@param O Octet to be written to
-	@param P Octet to be joined to the end of O
- */
-extern void OCT_joctet(octet *O,octet *P);
-/**	@brief XOR common bytes of a pair of Octets
- *
-	@param O Octet - on exit = O xor P
-	@param P Octet to be xored into O
- */
-extern void OCT_xor(octet *O,octet *P);
-/**	@brief reset Octet to zero length
- *
-	@param O Octet to be emptied
- */
-extern void OCT_empty(octet *O);
-/**	@brief Pad out an Octet to the given length
- *
-	Padding is done by inserting leading zeros, so abcd becomes 00abcd
-	@param O Octet to be padded
-	@param n new length of Octet
- */
-extern int OCT_pad(octet *O,int n);
-/**	@brief Convert an Octet to printable base64 number
- *
-	@param b zero terminated byte array to take base64 conversion
-	@param O Octet to be converted
- */
-extern void OCT_tobase64(char *b,octet *O);
-/**	@brief Populate an Octet from base64 number
- *
- 	@param O Octet to be populated
-	@param b zero terminated base64 string
-
- */
-extern void OCT_frombase64(octet *O,char *b);
-/**	@brief Copy one Octet into another
- *
- 	@param O Octet to be copied to
-	@param P Octet to be copied from
-
- */
-extern void OCT_copy(octet *O,octet *P);
-/**	@brief XOR every byte of an octet with input m
- *
- 	@param O Octet
-	@param m byte to be XORed with every byte of O
-
- */
-extern void OCT_xorbyte(octet *O,int m);
-/**	@brief Chops Octet into two, leaving first n bytes in O, moving the rest to P
- *
- 	@param O Octet to be chopped
-	@param P new Octet to be created
-	@param n number of bytes to chop off O
-
- */
-extern void OCT_chop(octet *O,octet *P,int n);
-/**	@brief Join n bytes of integer m to end of Octet O (big endian)
- *
-	Typically n is 4 for a 32-bit integer
- 	@param O Octet to be appended to
-	@param m integer to be appended to O
-	@param n number of bytes in m
-
- */
-extern void OCT_jint(octet *O,int m,int n);
-/**	@brief Create an Octet from bytes taken from a random number generator
- *
-	Truncates if there is no room
- 	@param O Octet to be populated
-	@param R an instance of a Cryptographically Secure Random Number Generator
-	@param n number of bytes to extracted from R
-
- */
-extern void OCT_rand(octet *O,csprng *R,int n);
-/**	@brief Shifts Octet left by n bytes
- *
-	Leftmost bytes disappear
- 	@param O Octet to be shifted
-	@param n number of bytes to shift
-
- */
-extern void OCT_shl(octet *O,int n);
-/**	@brief Convert an Octet to printable hex number
- *
-	@param dst hex value
-	@param src Octet to be converted
- */
-extern void OCT_toHex(octet *src,char *dst);
-/**	@brief Convert an Octet to string
- *
-	@param dst string value
-	@param src Octet to be converted
- */
-extern void OCT_toStr(octet *src,char *dst);
-
-
-
-/* Hash function */
-/**	@brief Initialise an instance of SHA256
- *
-	@param H an instance SHA256
- */
-extern void HASH_init(hash *H);
-/**	@brief Add a byte to the hash
- *
-	@param H an instance SHA256
-	@param b byte to be included in hash
- */
-extern void HASH_process(hash *H,int b);
-/**	@brief Generate 32-byte hash
- *
-	@param H an instance SHA256
-	@param h is the output 32-byte hash
- */
-extern void HASH_hash(hash *H,char *h);
-
-
-
-/* AES functions */
-/**	@brief Reset AES mode or IV
- *
-	@param A an instance of the AES
-	@param m is the new active mode of operation (ECB, CBC, OFB, CFB etc)
-	@param iv the new Initialisation Vector
- */
-extern void AES_reset(aes *A,int m,char *iv);
-/**	@brief Extract chaining vector from AES instance
- *
-	@param A an instance of the AES
-	@param f the extracted chaining vector
- */
-extern void AES_getreg(aes *A,char * f);
-/**	@brief Initialise an instance of AES and its mode of operation
- *
-	@param A an instance AES
-	@param m is the active mode of operation (ECB, CBC, OFB, CFB etc)
-	@param k the AES key as an array of 16 bytes
-	@param iv the Initialisation Vector
- */
-extern void AES_init(aes *A,int m,char *k,char *iv);
-/**	@brief Encrypt a single 16 byte block in ECB mode
- *
-	@param A an instance of the AES
-	@param b is an array of 16 plaintext bytes, on exit becomes ciphertext
- */
-extern void AES_ecb_encrypt(aes *A,uchar * b);
-/**	@brief Decrypt a single 16 byte block in ECB mode
- *
-	@param A an instance of the AES
-	@param b is an array of 16 cipherext bytes, on exit becomes plaintext
- */
-extern void AES_ecb_decrypt(aes *A,uchar * b);
-/**	@brief Encrypt a single 16 byte block in active mode
- *
-	@param A an instance of the AES
-	@param b is an array of 16 plaintext bytes, on exit becomes ciphertext
-	@return 0, or overflow bytes from CFB mode
- */
-extern unsign32 AES_encrypt(aes *A,char *b );
-/**	@brief Decrypt a single 16 byte block in active mode
- *
-	@param A an instance of the AES
-	@param b is an array of 16 ciphertext bytes, on exit becomes plaintext
-	@return 0, or overflow bytes from CFB mode
- */
-extern unsign32 AES_decrypt(aes *A,char *b);
-/**	@brief Clean up after application of AES
- *
-	@param A an instance of the AES
- */
-extern void AES_end(aes *A);
-
-
-/* AES-GCM functions */
-/**	@brief Initialise an instance of AES-GCM mode
- *
-	@param G an instance AES-GCM
-	@param k the AES key as an array of 16 bytes
-	@param n the number of bytes in the Initialisation Vector (IV)
-	@param iv the IV
- */
-extern void GCM_init(gcm *G,char *k,int n,char *iv);
-/**	@brief Add header (material to be authenticated but not encrypted)
- *
-	Note that this function can be called any number of times with n a multiple of 16, and then one last time with any value for n
-	@param G an instance AES-GCM
-	@param b is the header material to be added
-	@param n the number of bytes in the header
- */
-extern int GCM_add_header(gcm *G,char *b,int n);
-/**	@brief Add plaintext and extract ciphertext
- *
-	Note that this function can be called any number of times with n a multiple of 16, and then one last time with any value for n
-	@param G an instance AES-GCM
-	@param c is the ciphertext generated
-	@param p is the plaintext material to be added
-	@param n the number of bytes in the plaintext
- */
-extern int GCM_add_plain(gcm *G,char *c,char *p,int n);
-/**	@brief Add ciphertext and extract plaintext
- *
-	Note that this function can be called any number of times with n a multiple of 16, and then one last time with any value for n
-	@param G an instance AES-GCM
-	@param p is the plaintext generated
-	@param c is the ciphertext material to be added
-	@param n the number of bytes in the ciphertext
- */
-extern int GCM_add_cipher(gcm *G,char *p,char *c,int n);
-/**	@brief Finish off and extract authentication tag (HMAC)
- *
-	@param G is an active instance AES-GCM
-	@param t is the output 16 byte authentication tag
- */
-extern void GCM_finish(gcm *G,char *t);
-
-
-
-/* random numbers */
-/**	@brief Seed a random number generator from an array of bytes
- *
-	The provided seed should be truly random
-	@param R an instance of a Cryptographically Secure Random Number Generator
-	@param n the number of seed bytes provided
-	@param b an array of seed bytes
-
- */
-extern void RAND_seed(csprng *R,int n,char *b);
-/**	@brief Delete all internal state of a random number generator
- *
-	@param R an instance of a Cryptographically Secure Random Number Generator
- */
-extern void RAND_clean(csprng *R);
-/**	@brief Return a random byte from a random number generator
- *
-	@param R an instance of a Cryptographically Secure Random Number Generator
-	@return a random byte
- */
-extern int RAND_byte(csprng *R);
-
-#endif
diff --git a/c/big.c b/c/big.c
deleted file mode 100755
index b26abc2..0000000
--- a/c/big.c
+++ /dev/null
@@ -1,1210 +0,0 @@
-/*
-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.
-*/
-
-/* AMCL basic functions for BIG type */
-/* SU=m, SU is Stack Usage */
-
-#include "amcl.h"
-
-/* Calculates x*y+c+*r */
-
-#ifdef dchunk
-
-/* Method required to calculate x*y+c+r, bottom half in r, top half returned */
-chunk muladd(chunk x,chunk y,chunk c,chunk *r)
-{
-	dchunk prod=(dchunk)x*y+c+*r;
-	*r=(chunk)prod&MASK;
-	return (chunk)(prod>>BASEBITS);
-}
-
-#else
-
-/* No integer type available that can store double the wordlength */
-/* accumulate partial products */
-
-chunk muladd(chunk x,chunk y,chunk c,chunk *r)
-{
-	chunk x0,x1,y0,y1;
-	chunk bot,top,mid,carry;
-	x0=x&HMASK;
-	x1=(x>>HBITS);
-	y0=y&HMASK;
-	y1=(y>>HBITS);
-	bot=x0*y0;
-	top=x1*y1;
-	mid=x0*y1+x1*y0;
-	x0=mid&HMASK1;
-	x1=(mid>>HBITS1);
-	bot+=x0<<HBITS; bot+=*r; bot+=c;
-
-#if HDIFF==1
-	bot+=(top&HDIFF)<<(BASEBITS-1);
-	top>>=HDIFF;
-#endif
-
-	top+=x1;
-	carry=bot>>BASEBITS;
-	bot&=MASK;
-	top+=carry;
-
-	*r=bot;
-	return top;
-}
-
-#endif
-
-/* test a=0? */
-int BIG_iszilch(BIG a)
-{
-	int i;
-	for (i=0;i<NLEN;i++)
-		if (a[i]!=0) return 0;
-	return 1;
-}
-
-/* test a=0? */
-int BIG_diszilch(DBIG a)
-{
-	int i;
-	for (i=0;i<DNLEN;i++)
-		if (a[i]!=0) return 0;
-	return 1;
-}
-
-/* SU= 56 */
-/* output a */
-void BIG_output(BIG a)
-{
-	BIG b;
-	int i,len;
-	len=BIG_nbits(a);
-	if (len%4==0) len/=4;
-	else {len/=4; len++;}
-	if (len<MODBYTES*2) len=MODBYTES*2;
-
-	for (i=len-1;i>=0;i--)
-	{
-		BIG_copy(b,a);
-		BIG_shr(b,i*4);
-		printf("%01x",(unsigned int) b[0]&15);
-	}
-}
-
-/* SU= 16 */
-void BIG_rawoutput(BIG a)
-{
-	int i;
-	printf("(");
-	for (i=0;i<NLEN-1;i++)
-	  printf("%llx,",(long long unsigned int) a[i]);
-	printf("%llx)",(long long unsigned int) a[NLEN-1]);
-}
-
-/* Swap a and b if d=1 */
-void BIG_cswap(BIG a,BIG b,int d)
-{
-	int i;
-	chunk t,c=d;
-	c=~(c-1);
-#ifdef DEBUG_NORM
-	for (i=0;i<=NLEN;i++)
-#else
-	for (i=0;i<NLEN;i++)
-#endif
-	{
-		t=c&(a[i]^b[i]);
-		a[i]^=t;
-		b[i]^=t;
-	}
-}
-
-/* Move b to a if d=1 */
-void BIG_cmove(BIG f,BIG g,int d)
-{
-	int i;
-	chunk b=(chunk)-d;
-#ifdef DEBUG_NORM
-	for (i=0;i<=NLEN;i++)
-#else
-	for (i=0;i<NLEN;i++)
-#endif
-	{
-		f[i]^=(f[i]^g[i])&b;
-	}
-}
-
-/* convert BIG to/from bytes */
-/* SU= 64 */
-void BIG_toBytes(char *b,BIG a)
-{
-	int i;
-	BIG c;
-	BIG_norm(a);
-	BIG_copy(c,a);
-	for (i=MODBYTES-1;i>=0;i--)
-	{
-		b[i]=c[0]&0xff;
-		BIG_fshr(c,8);
-	}
-}
-
-/* SU= 16 */
-void BIG_fromBytes(BIG a,char *b)
-{
-	int i;
-	BIG_zero(a);
-	for (i=0;i<MODBYTES;i++)
-	{
-		BIG_fshl(a,8); a[0]+=(int)(unsigned char)b[i];
-		//BIG_inc(a,(int)(unsigned char)b[i]); BIG_norm(a);
-	}
-#ifdef DEBUG_NORM
-	a[NLEN]=0;
-#endif
-}
-
-/* SU= 88 */
-void BIG_doutput(DBIG a)
-{
-	DBIG b;
-	int i,len;
-	BIG_dnorm(a);
-	len=BIG_dnbits(a);
-	if (len%4==0) len/=4;
-	else {len/=4; len++;}
-
-	for (i=len-1;i>=0;i--)
-	{
-		BIG_dcopy(b,a);
-		BIG_dshr(b,i*4);
-		printf("%01x",(unsigned int) b[0]&15);
-	}
-}
-
-/* Copy b=a */
-void BIG_copy(BIG b,BIG a)
-{
-	int i;
-	for (i=0;i<NLEN;i++)
-		b[i]=a[i];
-#ifdef DEBUG_NORM
-	b[NLEN]=a[NLEN];
-#endif
-}
-
-/* Copy from ROM b=a */
-void BIG_rcopy(BIG b,const BIG a)
-{
-	int i;
-	for (i=0;i<NLEN;i++)
-		b[i]=a[i];
-#ifdef DEBUG_NORM
-	b[NLEN]=0;
-#endif
-}
-
-/* double length DBIG copy b=a */
-void BIG_dcopy(DBIG b,DBIG a)
-{
-	int i;
-	for (i=0;i<DNLEN;i++)
-		b[i]=a[i];
-#ifdef DEBUG_NORM
-	b[DNLEN]=a[DNLEN];
-#endif
-}
-
-/* Copy BIG to bottom half of DBIG */
-void BIG_dscopy(DBIG b,BIG a)
-{
-	int i;
-	for (i=0;i<NLEN-1;i++)
-		b[i]=a[i];
-
-	b[NLEN-1]=a[NLEN-1]&MASK; /* top word normalized */
-	b[NLEN]=a[NLEN-1]>>BASEBITS;
-
-	for (i=NLEN+1;i<DNLEN;i++) b[i]=0;
-#ifdef DEBUG_NORM
-	b[DNLEN]=a[NLEN];
-#endif
-}
-
-/* Copy BIG to top half of DBIG */
-void BIG_dsucopy(DBIG b,BIG a)
-{
-	int i;
-	for (i=0;i<NLEN;i++)
-		b[i]=0;
-	for (i=NLEN;i<DNLEN;i++)
-		b[i]=a[i-NLEN];
-#ifdef DEBUG_NORM
-	b[DNLEN]=a[NLEN];
-#endif
-}
-
-/* Copy bottom half of DBIG to BIG */
-void BIG_sdcopy(BIG b,DBIG a)
-{
-	int i;
-	for (i=0;i<NLEN;i++)
-		b[i]=a[i];
-#ifdef DEBUG_NORM
-	b[NLEN]=a[DNLEN];
-#endif
-}
-
-/* Copy top half of DBIG to BIG */
-void BIG_sducopy(BIG b,DBIG a)
-{
-	int i;
-	for (i=0;i<NLEN;i++)
-		b[i]=a[i+NLEN];
-#ifdef DEBUG_NORM
-	b[NLEN]=a[DNLEN];
-#endif
-}
-
-/* Set a=0 */
-void BIG_zero(BIG a)
-{
-	int i;
-	for (i=0;i<NLEN;i++)
-		a[i]=0;
-#ifdef DEBUG_NORM
-	a[NLEN]=0;
-#endif
-}
-
-void BIG_dzero(DBIG a)
-{
-	int i;
-	for (i=0;i<DNLEN;i++)
-		a[i]=0;
-#ifdef DEBUG_NORM
-	a[DNLEN]=0;
-#endif
-}
-
-/* set a=1 */
-void BIG_one(BIG a)
-{
-	int i;
-	a[0]=1;
-	for (i=1;i<NLEN;i++)
-		a[i]=0;
-#ifdef DEBUG_NORM
-	a[NLEN]=0;
-#endif
-}
-
-
-
-/* Set c=a+b */
-/* SU= 8 */
-void BIG_add(BIG c,BIG a,BIG b)
-{
-	int i;
-	for (i=0;i<NLEN;i++)
-		c[i]=a[i]+b[i];
-#ifdef DEBUG_NORM
-	c[NLEN]=a[NLEN]+b[NLEN]+1;
-	if (c[NLEN]>=NEXCESS) printf("add problem - digit overflow %d\n",c[NLEN]);
-#endif
-}
-
-/* Set c=c+d */
-void BIG_inc(BIG c,int d)
-{
-	BIG_norm(c);
-	c[0]+=(chunk)d;
-#ifdef DEBUG_NORM
-	c[NLEN]=1;
-#endif
-}
-
-/* Set c=a-b */
-/* SU= 8 */
-void BIG_sub(BIG c,BIG a,BIG b)
-{
-	int i;
-	for (i=0;i<NLEN;i++)
-		c[i]=a[i]-b[i];
-#ifdef DEBUG_NORM
-	c[NLEN]=a[NLEN]+b[NLEN]+1;
-	if (c[NLEN]>=NEXCESS) printf("sub problem - digit overflow %d\n",c[NLEN]);
-#endif
-}
-
-/* SU= 8 */
-
-void BIG_dsub(DBIG c,DBIG a,DBIG b)
-{
-	int i;
-	for (i=0;i<DNLEN;i++)
-		c[i]=a[i]-b[i];
-#ifdef DEBUG_NORM
-	c[DNLEN]=a[DNLEN]+b[DNLEN]+1;
-	if (c[DNLEN]>=NEXCESS) printf("sub problem - digit overflow %d\n",c[DNLEN]);
-#endif
-}
-
-
-/* Set c=c-1 */
-void BIG_dec(BIG c,int d)
-{
-	BIG_norm(c);
-	c[0]-=(chunk)d;
-#ifdef DEBUG_NORM
-	c[NLEN]=1;
-#endif
-}
-
-/* multiplication r=a*c by c<=NEXCESS */
-void BIG_imul(BIG r,BIG a,int c)
-{
-	int i;
-	for (i=0;i<NLEN;i++) r[i]=a[i]*c;
-#ifdef DEBUG_NORM
-	r[NLEN]=(a[NLEN]+1)*c-1;
-	if (r[NLEN]>=NEXCESS) printf("int mul problem - digit overflow %d\n",r[NLEN]);
-#endif
-}
-
-/* multiplication r=a*c by larger integer - c<=FEXCESS */
-/* SU= 24 */
-chunk BIG_pmul(BIG r,BIG a,int c)
-{
-	int i;
-	chunk ak,carry=0;
-	BIG_norm(a);
-	for (i=0;i<NLEN;i++)
-	{
-		ak=a[i];
-		r[i]=0;
-		carry=muladd(ak,(chunk)c,carry,&r[i]);
-	}
-#ifdef DEBUG_NORM
-	r[NLEN]=0;
-#endif
-	return carry;
-}
-
-/* r/=3 */
-/* SU= 16 */
-int BIG_div3(BIG r)
-{
-	int i;
-	chunk ak,base,carry=0;
-	BIG_norm(r);
-	base=((chunk)1<<BASEBITS);
-	for (i=NLEN-1;i>=0;i--)
-	{
-		ak=(carry*base+r[i]);
-		r[i]=ak/3;
-		carry=ak%3;
-	}
-	return (int)carry;
-}
-
-/* multiplication c=a*b by even larger integer b>FEXCESS, resulting in DBIG */
-/* SU= 24 */
-void BIG_pxmul(DBIG c,BIG a,int b)
-{
-	int j;
-	chunk carry;
-	BIG_dzero(c);
-	carry=0;
-	for (j=0;j<NLEN;j++)
-		carry=muladd(a[j],(chunk)b,carry,&c[j]);
-	c[NLEN]=carry;
-#ifdef DEBUG_NORM
-	c[DNLEN]=0;
-#endif
-}
-
-/* Set c=a*b */
-/* SU= 72 */
-void BIG_mul(DBIG c,BIG a,BIG b)
-{
-	int i,j;
-	chunk carry;
-#ifdef dchunk
-	dchunk t,co;
-#endif
-
-	BIG_norm(a);  /* needed here to prevent overflow from addition of partial products */
-	BIG_norm(b);
-
-/* Faster to Combafy it.. Let the compiler unroll the loops! */
-
-#ifdef COMBA
-
-	t=(dchunk)a[0]*b[0];
-	c[0]=(chunk)t&MASK; co=t>>BASEBITS;
-	t=(dchunk)a[1]*b[0]+(dchunk)a[0]*b[1]+co;
-	c[1]=(chunk)t&MASK; co=t>>BASEBITS;
-
-	for (j=2;j<NLEN;j++)
-	{
-		t=co; for (i=0;i<=j;i++) t+=(dchunk)a[j-i]*b[i];
-		c[j]=(chunk)t&MASK; co=t>>BASEBITS;
-	}
-
-	for (j=NLEN;j<DNLEN-2;j++)
-	{
-		t=co; for (i=j-NLEN+1;i<NLEN;i++) t+=(dchunk)a[j-i]*b[i];
-		c[j]=(chunk)t&MASK; co=t>>BASEBITS;
-	}
-
-	t=(dchunk)a[NLEN-1]*b[NLEN-1]+co;
-	c[DNLEN-2]=(chunk)t&MASK; co=t>>BASEBITS;
-	c[DNLEN-1]=(chunk)co;
-#else
-	BIG_dzero(c);
-	for (i=0;i<NLEN;i++)
-	{
-		carry=0;
-		for (j=0;j<NLEN;j++)
-			carry=muladd(a[i],b[j],carry,&c[i+j]);
-        c[NLEN+i]=carry;
-	}
-#endif
-
-#ifdef DEBUG_NORM
-	c[DNLEN]=0;
-#endif
-}
-
-/* .. if you know the result will fit in a BIG, c must be distinct from a and b */
-/* SU= 40 */
-void BIG_smul(BIG c,BIG a,BIG b)
-{
-	int i,j;
-	chunk carry;
-	BIG_norm(a);
-	BIG_norm(b);
-
-	BIG_zero(c);
-	for (i=0;i<NLEN;i++)
-	{
-		carry=0;
-		for (j=0;j<NLEN;j++)
-			if (i+j<NLEN) carry=muladd(a[i],b[j],carry,&c[i+j]);
-	}
-#ifdef DEBUG_NORM
-	c[NLEN]=0;
-#endif
-
-}
-
-/* Set c=a*a */
-/* SU= 80 */
-void BIG_sqr(DBIG c,BIG a)
-{
-	int i,j;
-	chunk carry;
-#ifdef dchunk
-	dchunk t,co;
-#endif
-
-	BIG_norm(a);
-
-/* Note 2*a[i] in loop below and extra addition */
-
-#ifdef COMBA
-
-	t=(dchunk)a[0]*a[0];
-	c[0]=(chunk)t&MASK; co=t>>BASEBITS;
-	t=(dchunk)a[1]*a[0]; t+=t; t+=co;
-	c[1]=(chunk)t&MASK; co=t>>BASEBITS;
-
-#if NLEN%2==1
-	for (j=2;j<NLEN-1;j+=2)
-	{
-		t=(dchunk)a[j]*a[0]; for (i=1;i<(j+1)/2;i++) t+=(dchunk)a[j-i]*a[i]; t+=t; t+=co;  t+=(dchunk)a[j/2]*a[j/2];
-		c[j]=(chunk)t&MASK; co=t>>BASEBITS;
-		t=(dchunk)a[j+1]*a[0]; for (i=1;i<(j+2)/2;i++) t+=(dchunk)a[j+1-i]*a[i]; t+=t; t+=co;
-		c[j+1]=(chunk)t&MASK; co=t>>BASEBITS;
-	}
-	j=NLEN-1;
-	t=(dchunk)a[j]*a[0]; for (i=1;i<(j+1)/2;i++) t+=(dchunk)a[j-i]*a[i]; t+=t; t+=co;  t+=(dchunk)a[j/2]*a[j/2];
-	c[j]=(chunk)t&MASK; co=t>>BASEBITS;
-
-#else
-	for (j=2;j<NLEN;j+=2)
-	{
-		t=(dchunk)a[j]*a[0]; for (i=1;i<(j+1)/2;i++) t+=(dchunk)a[j-i]*a[i]; t+=t; t+=co;  t+=(dchunk)a[j/2]*a[j/2];
-		c[j]=(chunk)t&MASK; co=t>>BASEBITS;
-		t=(dchunk)a[j+1]*a[0]; for (i=1;i<(j+2)/2;i++) t+=(dchunk)a[j+1-i]*a[i]; t+=t; t+=co;
-		c[j+1]=(chunk)t&MASK; co=t>>BASEBITS;
-	}
-
-#endif
-
-#if NLEN%2==1
-	j=NLEN;
-	t=(dchunk)a[NLEN-1]*a[j-NLEN+1]; for (i=j-NLEN+2;i<(j+1)/2;i++) t+=(dchunk)a[j-i]*a[i]; t+=t; t+=co;
-	c[j]=(chunk)t&MASK; co=t>>BASEBITS;
-	for (j=NLEN+1;j<DNLEN-2;j+=2)
-	{
-		t=(dchunk)a[NLEN-1]*a[j-NLEN+1]; for (i=j-NLEN+2;i<(j+1)/2;i++) t+=(dchunk)a[j-i]*a[i]; t+=t; t+=co; t+=(dchunk)a[j/2]*a[j/2];
-		c[j]=(chunk)t&MASK; co=t>>BASEBITS;
-		t=(dchunk)a[NLEN-1]*a[j-NLEN+2]; for (i=j-NLEN+3;i<(j+2)/2;i++) t+=(dchunk)a[j+1-i]*a[i]; t+=t; t+=co;
-		c[j+1]=(chunk)t&MASK; co=t>>BASEBITS;
-	}
-#else
-	for (j=NLEN;j<DNLEN-2;j+=2)
-	{
-		t=(dchunk)a[NLEN-1]*a[j-NLEN+1]; for (i=j-NLEN+2;i<(j+1)/2;i++) t+=(dchunk)a[j-i]*a[i]; t+=t; t+=co; t+=(dchunk)a[j/2]*a[j/2];
-		c[j]=(chunk)t&MASK; co=t>>BASEBITS;
-		t=(dchunk)a[NLEN-1]*a[j-NLEN+2]; for (i=j-NLEN+3;i<(j+2)/2;i++) t+=(dchunk)a[j+1-i]*a[i]; t+=t; t+=co;
-		c[j+1]=(chunk)t&MASK; co=t>>BASEBITS;
-	}
-
-#endif
-
-	t=(dchunk)a[NLEN-1]*a[NLEN-1]+co;
-	c[DNLEN-2]=(chunk)t&MASK; co=t>>BASEBITS;
-	c[DNLEN-1]=(chunk)co;
-
-#else
-	BIG_dzero(c);
-	for (i=0;i<NLEN;i++)
-	{
-		carry=0;
-		for (j=i+1;j<NLEN;j++)
-			carry=muladd(a[i],a[j],carry,&c[i+j]);
-        c[NLEN+i]=carry;
-	}
-
-	for (i=0;i<DNLEN;i++) c[i]*=2;
-
-	for (i=0;i<NLEN;i++)
-		c[2*i+1]+=muladd(a[i],a[i],0,&c[2*i]);
-
-	BIG_dnorm(c);
-#endif
-
-
-#ifdef DEBUG_NORM
-	c[DNLEN]=0;
-#endif
-
-}
-
-/* General shift left of a by n bits */
-/* a MUST be normalised */
-/* SU= 32 */
-void BIG_shl(BIG a,int k)
-{
-	int i;
-	int n=k%BASEBITS;
-	int m=k/BASEBITS;
-
-	a[NLEN-1]=((a[NLEN-1-m]<<n))|(a[NLEN-m-2]>>(BASEBITS-n));
-
-	for (i=NLEN-2;i>m;i--)
-		a[i]=((a[i-m]<<n)&MASK)|(a[i-m-1]>>(BASEBITS-n));
-	a[m]=(a[0]<<n)&MASK;
-	for (i=0;i<m;i++) a[i]=0;
-
-}
-
-/* Fast shift left of a by n bits, where n less than a word, Return excess (but store it as well) */
-/* a MUST be normalised */
-/* SU= 16 */
-chunk BIG_fshl(BIG a,int n)
-{
-	int i;
-
-	a[NLEN-1]=((a[NLEN-1]<<n))|(a[NLEN-2]>>(BASEBITS-n)); /* top word not masked */
-	for (i=NLEN-2;i>0;i--)
-		a[i]=((a[i]<<n)&MASK)|(a[i-1]>>(BASEBITS-n));
-	a[0]=(a[0]<<n)&MASK;
-
-	return (a[NLEN-1]>>((8*MODBYTES)%BASEBITS)); /* return excess - only used in ff.c */
-}
-
-/* double length left shift of a by k bits - k can be > BASEBITS , a MUST be normalised */
-/* SU= 32 */
-void BIG_dshl(DBIG a,int k)
-{
-	int i;
-	int n=k%BASEBITS;
-	int m=k/BASEBITS;
-
-	a[DNLEN-1]=((a[DNLEN-1-m]<<n))|(a[DNLEN-m-2]>>(BASEBITS-n));
-
-	for (i=DNLEN-2;i>m;i--)
-		a[i]=((a[i-m]<<n)&MASK)|(a[i-m-1]>>(BASEBITS-n));
-	a[m]=(a[0]<<n)&MASK;
-	for (i=0;i<m;i++) a[i]=0;
-
-}
-
-/* General shift rightof a by k bits */
-/* a MUST be normalised */
-/* SU= 32 */
-void BIG_shr(BIG a,int k)
-{
-	int i;
-	int n=k%BASEBITS;
-	int m=k/BASEBITS;
-	for (i=0;i<NLEN-m-1;i++)
-		a[i]=(a[m+i]>>n)|((a[m+i+1]<<(BASEBITS-n))&MASK);
-	a[NLEN-m-1]=a[NLEN-1]>>n;
-	for (i=NLEN-m;i<NLEN;i++) a[i]=0;
-
-}
-
-/* Faster shift right of a by k bits. Return shifted out part */
-/* a MUST be normalised */
-/* SU= 16 */
-chunk BIG_fshr(BIG a,int k)
-{
-	int i;
-	chunk r=a[0]&(((chunk)1<<k)-1); /* shifted out part */
-	for (i=0;i<NLEN-1;i++)
-		a[i]=(a[i]>>k)|((a[i+1]<<(BASEBITS-k))&MASK);
-	a[NLEN-1]=a[NLEN-1]>>k;
-	return r;
-}
-
-/* double length right shift of a by k bits - can be > BASEBITS */
-/* SU= 32 */
-void BIG_dshr(DBIG a,int k)
-{
-	int i;
-	int n=k%BASEBITS;
-	int m=k/BASEBITS;
-	for (i=0;i<DNLEN-m-1;i++)
-		a[i]=(a[m+i]>>n)|((a[m+i+1]<<(BASEBITS-n))&MASK);
-	a[DNLEN-m-1]=a[DNLEN-1]>>n;
-	for (i=DNLEN-m;i<DNLEN;i++ ) a[i]=0;
-}
-
-/* Split DBIG d into two BIGs t|b. Split happens at n bits, where n falls into NLEN word */
-/* d MUST be normalised */
-/* SU= 24 */
-void BIG_split(BIG t,BIG b,DBIG d,int n)
-{
-	int i;
-	chunk nw,carry;
-	int m=n%BASEBITS;
-//	BIG_dnorm(d);
-
-	for (i=0;i<NLEN-1;i++) b[i]=d[i];
-
-	b[NLEN-1]=d[NLEN-1]&(((chunk)1<<m)-1);
-
-	if (t!=b)
-	{
-		carry=(d[DNLEN-1]<<(BASEBITS-m));
-		for (i=DNLEN-2;i>=NLEN-1;i--)
-		{
-			nw=(d[i]>>m)|carry;
-			carry=(d[i]<<(BASEBITS-m))&MASK;
-			t[i-NLEN+1]=nw;
-		}
-	}
-#ifdef DEBUG_NORM
-		t[NLEN]=0;
-		b[NLEN]=0;
-#endif
-
-}
-
-/* you gotta keep the sign of carry! Look - no branching! */
-/* Note that sign bit is needed to disambiguate between +ve and -ve values */
-/* normalise BIG - force all digits < 2^BASEBITS */
-chunk BIG_norm(BIG a)
-{
-	int i;
-	chunk d,carry=0;
-	for (i=0;i<NLEN-1;i++)
-	{
-		d=a[i]+carry;
-		a[i]=d&MASK;
-		carry=d>>BASEBITS;
-	}
-	a[NLEN-1]=(a[NLEN-1]+carry);
-
-#ifdef DEBUG_NORM
-	a[NLEN]=0;
-#endif
-	return (a[NLEN-1]>>((8*MODBYTES)%BASEBITS));  /* only used in ff.c */
-}
-
-void BIG_dnorm(DBIG a)
-{
-	int i;
-	chunk d,carry=0;;
-	for (i=0;i<DNLEN-1;i++)
-	{
-		d=a[i]+carry;
-		a[i]=d&MASK;
-		carry=d>>BASEBITS;
-	}
-	a[DNLEN-1]=(a[DNLEN-1]+carry);
-#ifdef DEBUG_NORM
-	a[DNLEN]=0;
-#endif
-}
-
-/* Compare a and b. Return 1 for a>b, -1 for a<b, 0 for a==b */
-/* a and b MUST be normalised before call */
-int BIG_comp(BIG a,BIG b)
-{
-	int i;
-	for (i=NLEN-1;i>=0;i--)
-	{
-		if (a[i]==b[i]) continue;
-		if (a[i]>b[i]) return 1;
-		else  return -1;
-	}
-	return 0;
-}
-
-int BIG_dcomp(DBIG a,DBIG b)
-{
-	int i;
-	for (i=DNLEN-1;i>=0;i--)
-	{
-		if (a[i]==b[i]) continue;
-		if (a[i]>b[i]) return 1;
-		else  return -1;
-	}
-	return 0;
-}
-
-/* return number of bits in a */
-/* SU= 8 */
-int BIG_nbits(BIG a)
-{
-	int bts,k=NLEN-1;
-	chunk c;
-	BIG_norm(a);
-	while (k>=0 && a[k]==0) k--;
-	if (k<0) return 0;
-    bts=BASEBITS*k;
-	c=a[k];
-	while (c!=0) {c/=2; bts++;}
-	return bts;
-}
-
-/* SU= 8 */
-int BIG_dnbits(BIG a)
-{
-	int bts,k=DNLEN-1;
-	chunk c;
-	BIG_dnorm(a);
-	while (a[k]==0 && k>=0) k--;
-	if (k<0) return 0;
-    bts=BASEBITS*k;
-	c=a[k];
-	while (c!=0) {c/=2; bts++;}
-	return bts;
-}
-
-
-/* Set b=b mod c */
-/* SU= 16 */
-void BIG_mod(BIG b,BIG c)
-{
-	int k=0;
-
-	BIG_norm(b);
-	if (BIG_comp(b,c)<0)
-		return;
-	do
-	{
-		BIG_fshl(c,1);
-		k++;
-	} while (BIG_comp(b,c)>=0);
-
-	while (k>0)
-	{
-		BIG_fshr(c,1);
-		if (BIG_comp(b,c)>=0)
-		{
-			BIG_sub(b,b,c);
-			BIG_norm(b);
-		}
-		k--;
-	}
-}
-
-/* Set a=b mod c, b is destroyed. Slow but rarely used. */
-/* SU= 96 */
-void BIG_dmod(BIG a,DBIG b,BIG c)
-{
-	int k=0;
-	DBIG m;
-	BIG_dnorm(b);
-	BIG_dscopy(m,c);
-
-	if (BIG_dcomp(b,m)<0)
-	{
-		BIG_sdcopy(a,b);
-		return;
-	}
-
-	do
-	{
-		BIG_dshl(m,1);
-		k++;
-	} while (BIG_dcomp(b,m)>=0);
-
-	while (k>0)
-	{
-		BIG_dshr(m,1);
-		if (BIG_dcomp(b,m)>=0)
-		{
-			BIG_dsub(b,b,m);
-			BIG_dnorm(b);
-		}
-		k--;
-	}
-	BIG_sdcopy(a,b);
-}
-
-/* Set a=b/c,  b is destroyed. Slow but rarely used. */
-/* SU= 136 */
-void BIG_ddiv(BIG a,DBIG b,BIG c)
-{
-	int k=0;
-	DBIG m;
-	BIG e;
-	BIG_dnorm(b);
-	BIG_dscopy(m,c);
-
-	BIG_zero(a);
-	BIG_zero(e); BIG_inc(e,1);
-
-	while (BIG_dcomp(b,m)>=0)
-	{
-		BIG_fshl(e,1);
-		BIG_dshl(m,1);
-		k++;
-	}
-
-	while (k>0)
-	{
-		BIG_dshr(m,1);
-		BIG_fshr(e,1);
-		if (BIG_dcomp(b,m)>=0)
-		{
-			BIG_add(a,a,e);
-			BIG_norm(a);
-			BIG_dsub(b,b,m);
-			BIG_dnorm(b);
-		}
-		k--;
-	}
-}
-
-/* SU= 136 */
-
-void BIG_sdiv(BIG a,BIG c)
-{
-	int k=0;
-	BIG m,e,b;
-	BIG_norm(a);
-	BIG_copy(b,a);
-	BIG_copy(m,c);
-
-	BIG_zero(a);
-	BIG_zero(e); BIG_inc(e,1);
-
-	while (BIG_comp(b,m)>=0)
-	{
-		BIG_fshl(e,1);
-		BIG_fshl(m,1);
-		k++;
-	}
-
-	while (k>0)
-	{
-		BIG_fshr(m,1);
-		BIG_fshr(e,1);
-		if (BIG_comp(b,m)>=0)
-		{
-			BIG_add(a,a,e);
-			BIG_norm(a);
-			BIG_sub(b,b,m);
-			BIG_norm(b);
-		}
-		k--;
-	}
-}
-
-/* return LSB of a */
-int BIG_parity(BIG a)
-{
-	return a[0]%2;
-}
-
-/* return n-th bit of a */
-/* SU= 16 */
-int BIG_bit(BIG a,int n)
-{
-	if (a[n/BASEBITS]&((chunk)1<<(n%BASEBITS))) return 1;
-	else return 0;
-}
-
-/* return NAF value as +/- 1, 3 or 5. x and x3 should be normed.
-nbs is number of bits processed, and nzs is number of trailing 0s detected */
-/* SU= 32 */
-int BIG_nafbits(BIG x,BIG x3,int i,int *nbs,int *nzs)
-{
-	int j,r,nb;
-
-	nb=BIG_bit(x3,i)-BIG_bit(x,i);
-	*nbs=1;
-	*nzs=0;
-	if (nb==0) return 0;
-	if (i==0) return nb;
-
-    if (nb>0) r=1;
-    else      r=(-1);
-
-    for (j=i-1;j>0;j--)
-    {
-        (*nbs)++;
-        r*=2;
-        nb=BIG_bit(x3,j)-BIG_bit(x,j);
-        if (nb>0) r+=1;
-        if (nb<0) r-=1;
-        if (abs(r)>5) break;
-    }
-
-	if (r%2!=0 && j!=0)
-    { /* backtrack */
-        if (nb>0) r=(r-1)/2;
-        if (nb<0) r=(r+1)/2;
-        (*nbs)--;
-    }
-
-    while (r%2==0)
-    { /* remove trailing zeros */
-        r/=2;
-        (*nzs)++;
-        (*nbs)--;
-    }
-    return r;
-}
-
-/* return last n bits of a, where n is small < BASEBITS */
-/* SU= 16 */
-int BIG_lastbits(BIG a,int n)
-{
-	int msk=(1<<n)-1;
-	BIG_norm(a);
-	return ((int)a[0])&msk;
-}
-
-/* get 8*MODBYTES size random number */
-void BIG_random(BIG m,csprng *rng)
-{
-	int i,b,j=0,r=0;
-
-	BIG_zero(m);
-/* generate random BIG */
-	for (i=0;i<8*MODBYTES;i++)
-	{
-		if (j==0) r=RAND_byte(rng);
-		else r>>=1;
-		b=r&1;
-		BIG_shl(m,1); m[0]+=b;
-		j++; j&=7;
-	}
-
-#ifdef DEBUG_NORM
-	m[NLEN]=0;
-#endif
-}
-
-/* get random BIG from rng, modulo q. Done one bit at a time, so its portable */
-
-void BIG_randomnum(BIG m,BIG q,csprng *rng)
-{
-	int i,b,j=0,r=0;
-	DBIG d;
-	BIG_dzero(d);
-/* generate random DBIG */
-	for (i=0;i<2*MODBITS;i++)
-	{
-		if (j==0) r=RAND_byte(rng);
-		else r>>=1;
-		b=r&1;
-		BIG_dshl(d,1); d[0]+=b;
-		j++; j&=7;
-	}
-/* reduce modulo a BIG. Removes bias */
-	BIG_dmod(m,d,q);
-#ifdef DEBUG_NORM
-	m[NLEN]=0;
-#endif
-}
-
-/* Set r=a*b mod m */
-/* SU= 96 */
-void BIG_modmul(BIG r,BIG a,BIG b,BIG m)
-{
-	DBIG d;
-	BIG_mod(a,m);
-	BIG_mod(b,m);
-	BIG_mul(d,a,b);
-	BIG_dmod(r,d,m);
-}
-
-/* Set a=a*a mod m */
-/* SU= 88 */
-void BIG_modsqr(BIG r,BIG a,BIG m)
-{
-	DBIG d;
-	BIG_mod(a,m);
-	BIG_sqr(d,a);
-	BIG_dmod(r,d,m);
-}
-
-/* Set r=-a mod m */
-/* SU= 16 */
-void BIG_modneg(BIG r,BIG a,BIG m)
-{
-	BIG_mod(a,m);
-	BIG_sub(r,m,a);
-}
-
-/* Set a=a/b mod m */
-/* SU= 136 */
-void BIG_moddiv(BIG r,BIG a,BIG b,BIG m)
-{
-	DBIG d;
-	BIG z;
-	BIG_mod(a,m);
-	BIG_invmodp(z,b,m);
-	BIG_mul(d,a,z);
-	BIG_dmod(r,d,m);
-}
-
-/* Get jacobi Symbol (a/p). Returns 0, 1 or -1 */
-/* SU= 216 */
-int BIG_jacobi(BIG a,BIG p)
-{
-	int n8,k,m=0;
-	BIG t,x,n,zilch,one;
-	BIG_one(one);
-	BIG_zero(zilch);
-	if (BIG_parity(p)==0 || BIG_comp(a,zilch)==0 || BIG_comp(p,one)<=0) return 0;
-	BIG_norm(a);
-	BIG_copy(x,a);
-	BIG_copy(n,p);
-	BIG_mod(x,p);
-
-	while (BIG_comp(n,one)>0)
-	{
-		if (BIG_comp(x,zilch)==0) return 0;
-		n8=BIG_lastbits(n,3);
-		k=0;
-		while (BIG_parity(x)==0)
-		{
-			k++;
-			BIG_shr(x,1);
-		}
-		if (k%2==1) m+=(n8*n8-1)/8;
-		m+=(n8-1)*(BIG_lastbits(x,2)-1)/4;
-		BIG_copy(t,n);
-
-		BIG_mod(t,x);
-		BIG_copy(n,x);
-		BIG_copy(x,t);
-		m%=2;
-
-	}
-	if (m==0) return 1;
-	else return -1;
-}
-
-/* Set r=1/a mod p. Binary method */
-/* SU= 240 */
-void BIG_invmodp(BIG r,BIG a,BIG p)
-{
-	BIG u,v,x1,x2,t,one;
-	BIG_mod(a,p);
-	BIG_copy(u,a);
-	BIG_copy(v,p);
-	BIG_one(one);
-	BIG_copy(x1,one);
-	BIG_zero(x2);
-
-	while (BIG_comp(u,one)!=0 && BIG_comp(v,one)!=0)
-	{
-		while (BIG_parity(u)==0)
-		{
-			BIG_shr(u,1);
-			if (BIG_parity(x1)!=0)
-			{
-				BIG_add(x1,p,x1);
-				BIG_norm(x1);
-			}
-			BIG_shr(x1,1);
-		}
-		while (BIG_parity(v)==0)
-		{
-			BIG_shr(v,1);
-			if (BIG_parity(x2)!=0)
-			{
-				BIG_add(x2,p,x2);
-				BIG_norm(x2);
-			}
-			BIG_shr(x2,1);
-		}
-		if (BIG_comp(u,v)>=0)
-		{
-			BIG_sub(u,u,v);
-			BIG_norm(u);
-			if (BIG_comp(x1,x2)>=0) BIG_sub(x1,x1,x2);
-			else
-			{
-				BIG_sub(t,p,x2);
-				BIG_add(x1,x1,t);
-			}
-			BIG_norm(x1);
-		}
-		else
-		{
-			BIG_sub(v,v,u);
-			BIG_norm(v);
-			if (BIG_comp(x2,x1)>=0) BIG_sub(x2,x2,x1);
-			else
-			{
-				BIG_sub(t,p,x1);
-				BIG_add(x2,x2,t);
-			}
-			BIG_norm(x2);
-		}
-	}
-	if (BIG_comp(u,one)==0)
-		BIG_copy(r,x1);
-	else
-		BIG_copy(r,x2);
-}
diff --git a/c/build_ec b/c/build_ec
deleted file mode 100644
index 5b364d0..0000000
--- a/c/build_ec
+++ /dev/null
@@ -1,24 +0,0 @@
-cp amcl_.h amcl.h
-
-gcc -std=c99 -c -O3 big.c
-gcc -std=c99 -c -O3 fp.c
-gcc -std=c99 -c -O3 ecp.c
-gcc -std=c99 -c -O3 hash.c
-gcc -std=c99 -c -O3 rand.c
-gcc -std=c99 -c -O3 aes.c
-gcc -std=c99 -c -O3 gcm.c
-gcc -std=c99 -c -O3 oct.c
-gcc -std=c99 -c -O3 rom.c
-
-gcc -std=c99 -c -O3 ff.c
-
-rm amcl.a
-ar rc amcl.a big.o fp.o ecp.o hash.o ff.o
-ar r amcl.a rand.o aes.o gcm.o oct.o rom.o
-
-gcc -std=c99 -O3 testecm.c ecdh.c amcl.a -o testecm
-gcc -std=c99 -O3 testecdh.c ecdh.c amcl.a -o testecdh
-gcc -std=c99 -O3 testrsa.c rsa.c amcl.a -o testrsa
-
-rm amcl.h
-rm *.o
diff --git a/c/build_ec.bat b/c/build_ec.bat
deleted file mode 100644
index c302beb..0000000
--- a/c/build_ec.bat
+++ /dev/null
@@ -1,24 +0,0 @@
-copy amcl_.h amcl.h
-
-gcc -std=c99 -c -O3 big.c
-gcc -std=c99 -c -O3 fp.c
-gcc -std=c99 -c -O3 ecp.c
-gcc -std=c99 -c -O3 hash.c
-gcc -std=c99 -c -O3 rand.c
-gcc -std=c99 -c -O3 aes.c
-gcc -std=c99 -c -O3 gcm.c
-gcc -std=c99 -c -O3 oct.c
-gcc -std=c99 -c -O3 rom.c
-
-gcc -std=c99 -c -O3 ff.c
-
-del amcl.a
-ar rc amcl.a big.o fp.o ecp.o hash.o ff.o
-ar r amcl.a rand.o aes.o gcm.o oct.o rom.o
-
-gcc -std=c99 -O3 testecm.c ecdh.c amcl.a -o testecm.exe
-gcc -std=c99 -O3 testecdh.c ecdh.c amcl.a -o testecdh.exe
-gcc -std=c99 -O3 testrsa.c rsa.c amcl.a -o testrsa.exe
-
-del amcl.h
-del *.o
diff --git a/c/build_pair b/c/build_pair
deleted file mode 100644
index 7232c27..0000000
--- a/c/build_pair
+++ /dev/null
@@ -1,28 +0,0 @@
-cp amcl_.h amcl.h
-
-gcc -std=c99 -c -O3 big.c
-gcc -std=c99 -c -O3 fp.c
-gcc -std=c99 -c -O3 ecp.c
-gcc -std=c99 -c -O3 hash.c
-gcc -std=c99 -c -O3 rand.c
-gcc -std=c99 -c -O3 aes.c
-gcc -std=c99 -c -O3 gcm.c
-gcc -std=c99 -c -O3 oct.c
-gcc -std=c99 -c -O3 rom.c
-
-gcc -std=c99 -c -O3 fp2.c
-gcc -std=c99 -c -O3 ecp2.c
-gcc -std=c99 -c -O3 fp4.c
-gcc -std=c99 -c -O3 fp12.c
-gcc -std=c99 -c -O3 pair.c
-
-rm amcl.a
-ar rc amcl.a big.o fp.o ecp.o hash.o
-ar r amcl.a rand.o aes.o gcm.o oct.o rom.o
-
-ar r amcl.a pair.o fp2.o ecp2.o fp4.o fp12.o
-
-gcc -std=c99 -O3 testmpin.c mpin.c amcl.a -o testmpin
-
-rm amcl.h
-rm *.o
diff --git a/c/build_pair.bat b/c/build_pair.bat
deleted file mode 100644
index 05d1c24..0000000
--- a/c/build_pair.bat
+++ /dev/null
@@ -1,28 +0,0 @@
-copy amcl_.h amcl.h
-
-gcc -std=c99 -c -O3 big.c
-gcc -std=c99 -c -O3 fp.c
-gcc -std=c99 -c -O3 ecp.c
-gcc -std=c99 -c -O3 hash.c
-gcc -std=c99 -c -O3 rand.c
-gcc -std=c99 -c -O3 aes.c
-gcc -std=c99 -c -O3 gcm.c
-gcc -std=c99 -c -O3 oct.c
-gcc -std=c99 -c -O3 rom.c
-
-gcc -std=c99 -c -O3 fp2.c
-gcc -std=c99 -c -O3 ecp2.c
-gcc -std=c99 -c -O3 fp4.c
-gcc -std=c99 -c -O3 fp12.c
-gcc -std=c99 -c -O3 pair.c
-
-del amcl.a
-ar rc amcl.a big.o fp.o ecp.o hash.o
-ar r amcl.a rand.o aes.o gcm.o oct.o rom.o
-
-ar r amcl.a pair.o fp2.o ecp2.o fp4.o fp12.o
-
-gcc -std=c99 -O3 testmpin.c mpin.c amcl.a -o testmpin.exe
-
-del amcl.h
-del *.o
diff --git a/c/build_pair_ms.bat b/c/build_pair_ms.bat
deleted file mode 100644
index 96b6234..0000000
--- a/c/build_pair_ms.bat
+++ /dev/null
@@ -1,28 +0,0 @@
-copy amcl_.h amcl.h
-
-cl /c /O2 big.c
-cl /c /O2 fp.c
-cl /c /O2 ecp.c
-cl /c /O2 hash.c
-cl /c /O2 rand.c
-cl /c /O2 aes.c
-cl /c /O2 gcm.c
-cl /c /O2 oct.c
-cl /c /O2 rom.c
-cl /c /O2 fp.c
-cl /c /O2 fp2.c
-cl /c /O2 ecp2.c
-cl /c /O2 fp4.c
-cl /c /O2 fp12.c
-cl /c /O2 pair.c
-
-del amcl.lib
-lib /OUT:amcl.lib big.obj fp.obj ecp.obj hash.obj
-lib /OUT:amcl.lib amcl.lib rand.obj aes.obj gcm.obj oct.obj rom.obj
-
-lib /OUT:amcl.lib amcl.lib pair.obj fp2.obj ecp2.obj fp4.obj fp12.obj
-
-cl /O2 testmpin.c mpin.c amcl.lib
-
-del amcl.h
-del *.obj
diff --git a/c/ecdh.c b/c/ecdh.c
deleted file mode 100755
index 56152da..0000000
--- a/c/ecdh.c
+++ /dev/null
@@ -1,576 +0,0 @@
-/*
-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.
-*/
-
-/* ECDH/ECIES/ECDSA Functions - see main program below */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <time.h>
-
-#include "ecdh.h"
-
-#define ROUNDUP(a,b) ((a)-1)/(b)+1
-
-/* general purpose hash function w=hash(p|n|x|y) */
-static void hashit(octet *p,int n,octet *x,octet *y,octet *w)
-{
-    int i,c[4];
-    hash sha;
-    char hh[32];
-
-    HASH_init(&sha);
-    if (p!=NULL)
-        for (i=0;i<p->len;i++) HASH_process(&sha,p->val[i]);
-	if (n>0)
-    {
-        c[0]=(n>>24)&0xff;
-        c[1]=(n>>16)&0xff;
-        c[2]=(n>>8)&0xff;
-        c[3]=(n)&0xff;
-		for (i=0;i<4;i++) HASH_process(&sha,c[i]);
-    }
-    if (x!=NULL)
-        for (i=0;i<x->len;i++) HASH_process(&sha,x->val[i]);
-    if (y!=NULL)
-        for (i=0;i<y->len;i++) HASH_process(&sha,y->val[i]);
-
-
-    HASH_hash(&sha,hh);
-
-    OCT_empty(w);
-    OCT_jbytes(w,hh,32);
-    for (i=0;i<32;i++) hh[i]=0;
-}
-
-/* Hash octet p to octet w */
-void ECP_HASH(octet *p,octet *w)
-{
-	hashit(p,-1,NULL,NULL,w);
-}
-
-/* Initialise a Cryptographically Strong Random Number Generator from
-   an octet of raw random data */
-void ECP_CREATE_CSPRNG(csprng *RNG,octet *RAW)
-{
-    RAND_seed(RNG,RAW->len,RAW->val);
-}
-
-void ECP_KILL_CSPRNG(csprng *RNG)
-{
-    RAND_clean(RNG);
-}
-
-/* Calculate HMAC of m using key k. HMAC is tag of length olen */
-int ECP_HMAC(octet *m,octet *k,int olen,octet *tag)
-{
-/* Input is from an octet m        *
- * olen is requested output length in bytes. k is the key  *
- * The output is the calculated tag */
-    int hlen,b;
-	char h[32],k0[64];
-    octet H={0,sizeof(h),h};
-	octet K0={0,sizeof(k0),k0};
-
-    hlen=32; b=64;
-    if (olen<4 || olen>hlen) return 0;
-
-    if (k->len > b) hashit(k,-1,NULL,NULL,&K0);
-    else            OCT_copy(&K0,k);
-
-    OCT_jbyte(&K0,0,b-K0.len);
-
-    OCT_xorbyte(&K0,0x36);
-
-    hashit(&K0,-1,m,NULL,&H);
-
-    OCT_xorbyte(&K0,0x6a);   /* 0x6a = 0x36 ^ 0x5c */
-    hashit(&K0,-1,&H,NULL,&H);
-
-    OCT_empty(tag);
-    OCT_jbytes(tag,H.val,olen);
-
-    return 1;
-}
-
-/* Key Derivation Functions */
-/* Input octet z */
-/* Output key of length olen */
-/*
-void KDF1(octet *z,int olen,octet *key)
-{
-    char h[32];
-	octet H={0,sizeof(h),h};
-    int counter,cthreshold;
-    int hlen=32;
-
-    OCT_empty(key);
-
-    cthreshold=ROUNDUP(olen,hlen);
-
-    for (counter=0;counter<cthreshold;counter++)
-    {
-        hashit(z,counter,NULL,NULL,&H);
-        if (key->len+hlen>olen) OCT_jbytes(key,H.val,olen%hlen);
-        else                    OCT_joctet(key,&H);
-    }
-}
-*/
-void ECP_KDF2(octet *z,octet *p,int olen,octet *key)
-{
-/* NOTE: the parameter olen is the length of the output k in bytes */
-    char h[32];
-	octet H={0,sizeof(h),h};
-    int counter,cthreshold;
-    int hlen=32;
-
-    OCT_empty(key);
-
-    cthreshold=ROUNDUP(olen,hlen);
-
-    for (counter=1;counter<=cthreshold;counter++)
-    {
-        hashit(z,counter,p,NULL,&H);
-        if (key->len+hlen>olen)  OCT_jbytes(key,H.val,olen%hlen);
-        else                     OCT_joctet(key,&H);
-    }
-}
-
-/* Password based Key Derivation Function */
-/* Input password p, salt s, and repeat count */
-/* Output key of length olen */
-void ECP_PBKDF2(octet *p,octet *s,int rep,int olen,octet *key)
-{
-	int i,j,len,d=ROUNDUP(olen,32);
-	char f[EFS],u[EFS];
-	octet F={0,sizeof(f),f};
-	octet U={0,sizeof(u),u};
-	OCT_empty(key);
-
-	for (i=1;i<=d;i++)
-	{
-		len=s->len;
-		OCT_jint(s,i,4);
-		ECP_HMAC(s,p,EFS,&F);
-		s->len=len;
-		OCT_copy(&U,&F);
-		for (j=2;j<=rep;j++)
-		{
-			ECP_HMAC(&U,p,EFS,&U);
-			OCT_xor(&F,&U);
-		}
-
-		OCT_joctet(key,&F);
-	}
-	OCT_chop(key,NULL,olen);
-}
-
-/* AES encryption/decryption. Encrypt byte array M using key K and returns ciphertext */
-void ECP_AES_CBC_IV0_ENCRYPT(octet *k,octet *m,octet *c)
-{ /* AES CBC encryption, with Null IV and key k */
-  /* Input is from an octet string m, output is to an octet string c */
-  /* Input is padded as necessary to make up a full final block */
-    aes a;
-	int fin;
-    int i,j,ipt,opt;
-    char buff[16];
-    int padlen;
-
-	OCT_clear(c);
-	if (m->len==0) return;
-    AES_init(&a,CBC,k->val,NULL);
-
-    ipt=opt=0;
-    fin=0;
-    for(;;)
-    {
-        for (i=0;i<16;i++)
-        {
-            if (ipt<m->len) buff[i]=m->val[ipt++];
-            else {fin=1; break;}
-        }
-        if (fin) break;
-        AES_encrypt(&a,buff);
-        for (i=0;i<16;i++)
-            if (opt<c->max) c->val[opt++]=buff[i];
-    }
-
-/* last block, filled up to i-th index */
-
-    padlen=16-i;
-    for (j=i;j<16;j++) buff[j]=padlen;
-    AES_encrypt(&a,buff);
-    for (i=0;i<16;i++)
-        if (opt<c->max) c->val[opt++]=buff[i];
-    AES_end(&a);
-    c->len=opt;
-}
-
-/* decrypts and returns TRUE if all consistent, else returns FALSE */
-int ECP_AES_CBC_IV0_DECRYPT(octet *k,octet *c,octet *m)
-{ /* padding is removed */
-    aes a;
-    int i,ipt,opt,ch;
-    char buff[16];
-    int fin,bad;
-    int padlen;
-    ipt=opt=0;
-
-    OCT_clear(m);
-    if (c->len==0) return 1;
-    ch=c->val[ipt++];
-
-    AES_init(&a,CBC,k->val,NULL);
-    fin=0;
-
-    for(;;)
-    {
-        for (i=0;i<16;i++)
-        {
-            buff[i]=ch;
-            if (ipt>=c->len) {fin=1; break;}
-            else ch=c->val[ipt++];
-        }
-        AES_decrypt(&a,buff);
-        if (fin) break;
-        for (i=0;i<16;i++)
-            if (opt<m->max) m->val[opt++]=buff[i];
-    }
-    AES_end(&a);
-    bad=0;
-    padlen=buff[15];
-    if (i!=15 || padlen<1 || padlen>16) bad=1;
-    if (padlen>=2 && padlen<=16)
-        for (i=16-padlen;i<16;i++) if (buff[i]!=padlen) bad=1;
-
-    if (!bad) for (i=0;i<16-padlen;i++)
-        if (opt<m->max) m->val[opt++]=buff[i];
-
-    m->len=opt;
-    if (bad) return 0;
-    return 1;
-}
-
-/* Calculate a public/private EC GF(p) key pair. W=S.G mod EC(p),
- * where S is the secret key and W is the public key
- * and G is fixed generator.
- * If RNG is NULL then the private key is provided externally in S
- * otherwise it is generated randomly internally */
-int ECP_KEY_PAIR_GENERATE(csprng *RNG,octet* S,octet *W)
-{
-    BIG r,gx,gy,s;
-    ECP G;
-    int res=0;
-	BIG_rcopy(gx,CURVE_Gx);
-
-#if CURVETYPE!=MONTGOMERY
-	BIG_rcopy(gy,CURVE_Gy);
-    ECP_set(&G,gx,gy);
-#else
-    ECP_set(&G,gx);
-#endif
-
-	BIG_rcopy(r,CURVE_Order);
-    if (RNG!=NULL)
-		BIG_randomnum(s,r,RNG);
-    else
-	{
-		BIG_fromBytes(s,S->val);
-		BIG_mod(s,r);
-	}
-
-    ECP_mul(&G,s);
-#if CURVETYPE!=MONTGOMERY
-    ECP_get(gx,gy,&G);
-#else
-    ECP_get(gx,&G);
-#endif
-    if (RNG!=NULL)
-	{
-		S->len=EGS;
-		BIG_toBytes(S->val,s);
-	}
-#if CURVETYPE!=MONTGOMERY
-	W->len=2*EFS+1;	W->val[0]=4;
-	BIG_toBytes(&(W->val[1]),gx);
-	BIG_toBytes(&(W->val[EFS+1]),gy);
-#else
-	W->len=EFS+1;	W->val[0]=2;
-	BIG_toBytes(&(W->val[1]),gx);
-#endif
-
-    return res;
-}
-
-/* validate public key. Set full=true for fuller check */
-int ECP_PUBLIC_KEY_VALIDATE(int full,octet *W)
-{
-    BIG q,r,wx,wy;
-    ECP WP;
-    int valid;
-    int res=0;
-
-	BIG_rcopy(q,Modulus);
-	BIG_rcopy(r,CURVE_Order);
-
-	BIG_fromBytes(wx,&(W->val[1]));
-    if (BIG_comp(wx,q)>=0) res=ECDH_INVALID_PUBLIC_KEY;
-#if CURVETYPE!=MONTGOMERY
-	BIG_fromBytes(wy,&(W->val[EFS+1]));
-	if (BIG_comp(wy,q)>=0) res=ECDH_INVALID_PUBLIC_KEY;
-#endif
-    if (res==0)
-    {
-#if CURVETYPE!=MONTGOMERY
-        valid=ECP_set(&WP,wx,wy);
-#else
-	    valid=ECP_set(&WP,wx);
-#endif
-        if (!valid || ECP_isinf(&WP)) res=ECDH_INVALID_PUBLIC_KEY;
-        if (res==0 && full)
-        {
-            ECP_mul(&WP,r);
-            if (!ECP_isinf(&WP)) res=ECDH_INVALID_PUBLIC_KEY;
-        }
-    }
-
-    return res;
-}
-
-/* IEEE-1363 Diffie-Hellman online calculation Z=S.WD */
-int ECP_SVDP_DH(octet *S,octet *WD,octet *Z)
-{
-    BIG r,s,wx,wy;
-    int valid;
-    ECP W;
-    int res=0;
-
-	BIG_fromBytes(s,S->val);
-
-	BIG_fromBytes(wx,&(WD->val[1]));
-#if CURVETYPE!=MONTGOMERY
-	BIG_fromBytes(wy,&(WD->val[EFS+1]));
-	valid=ECP_set(&W,wx,wy);
-#else
-	valid=ECP_set(&W,wx);
-#endif
-	if (!valid) res=ECDH_ERROR;
-	if (res==0)
-	{
-		BIG_rcopy(r,CURVE_Order);
-		BIG_mod(s,r);
-
-	    ECP_mul(&W,s);
-        if (ECP_isinf(&W)) res=ECDH_ERROR;
-        else
-        {
-#if CURVETYPE!=MONTGOMERY
-            ECP_get(wx,wx,&W);
-#else
-	        ECP_get(wx,&W);
-#endif
-			Z->len=32;
-			BIG_toBytes(Z->val,wx);
-        }
-    }
-    return res;
-}
-
-#if CURVETYPE!=MONTGOMERY
-
-/* IEEE ECDSA Signature, C and D are signature on F using private key S */
-int ECP_SP_DSA(csprng *RNG,octet *S,octet *F,octet *C,octet *D)
-{
-	char h[32];
-	octet H={0,sizeof(h),h};
-
-    BIG gx,gy,r,s,f,c,d,u,vx;
-    ECP G,V;
-
-	hashit(F,-1,NULL,NULL,&H);
-
-	BIG_rcopy(gx,CURVE_Gx);
-	BIG_rcopy(gy,CURVE_Gy);
-	BIG_rcopy(r,CURVE_Order);
-
-	BIG_fromBytes(s,S->val);
-	BIG_fromBytes(f,H.val);
-
-    ECP_set(&G,gx,gy);
-
-    do {
-		BIG_randomnum(u,r,RNG);
-        ECP_copy(&V,&G);
-        ECP_mul(&V,u);
-
-        ECP_get(vx,vx,&V);
-
-		BIG_copy(c,vx);
-		BIG_mod(c,r);
-		if (BIG_iszilch(c)) continue;
-
-		BIG_invmodp(u,u,r);
-		BIG_modmul(d,s,c,r);
-
-		BIG_add(d,f,d);
-
-		BIG_modmul(d,u,d,r);
-
-	} while (BIG_iszilch(d));
-
-	C->len=D->len=EGS;
-
-	BIG_toBytes(C->val,c);
-	BIG_toBytes(D->val,d);
-
-    return 0;
-}
-
-/* IEEE1363 ECDSA Signature Verification. Signature C and D on F is verified using public key W */
-int ECP_VP_DSA(octet *W,octet *F, octet *C,octet *D)
-{
-	char h[32];
-	octet H={0,sizeof(h),h};
-
-    BIG r,gx,gy,wx,wy,f,c,d,h2;
-    int res=0;
-    ECP G,WP;
-    int valid;
-
- 	hashit(F,-1,NULL,NULL,&H);
-
-	BIG_rcopy(gx,CURVE_Gx);
-	BIG_rcopy(gy,CURVE_Gy);
-	BIG_rcopy(r,CURVE_Order);
-
-	BIG_fromBytes(c,C->val);
-	BIG_fromBytes(d,D->val);
-	BIG_fromBytes(f,H.val);
-
-    if (BIG_iszilch(c) || BIG_comp(c,r)>=0 || BIG_iszilch(d) || BIG_comp(d,r)>=0)
-		res=ECDH_INVALID;
-
-    if (res==0)
-    {
-		BIG_invmodp(d,d,r);
-		BIG_modmul(f,f,d,r);
-		BIG_modmul(h2,c,d,r);
-
-		ECP_set(&G,gx,gy);
-
-		BIG_fromBytes(wx,&(W->val[1]));
-		BIG_fromBytes(wy,&(W->val[EFS+1]));
-
-		valid=ECP_set(&WP,wx,wy);
-
-        if (!valid) res=ECDH_ERROR;
-        else
-        {
-			ECP_mul2(&WP,&G,h2,f);
-
-            if (ECP_isinf(&WP)) res=ECDH_INVALID;
-            else
-            {
-                ECP_get(d,d,&WP);
-				BIG_mod(d,r);
-                if (BIG_comp(d,c)!=0) res=ECDH_INVALID;
-            }
-        }
-    }
-
-    return res;
-}
-
-/* IEEE1363 ECIES encryption. Encryption of plaintext M uses public key W and produces ciphertext V,C,T */
-void ECP_ECIES_ENCRYPT(octet *P1,octet *P2,csprng *RNG,octet *W,octet *M,int tlen,octet *V,octet *C,octet *T)
-{
-
-	int i,len;
-	char z[EFS],vz[3*EFS+2],k[32],k1[16],k2[16],l2[8],u[EFS];
-	octet Z={0,sizeof(z),z};
-	octet VZ={0,sizeof(vz),vz};
-	octet K={0,sizeof(k),k};
-	octet K1={0,sizeof(k1),k1};
-	octet K2={0,sizeof(k2),k2};
-	octet L2={0,sizeof(l2),l2};
-	octet U={0,sizeof(u),u};
-
-    if (ECP_KEY_PAIR_GENERATE(RNG,&U,V)!=0) return;
-    if (ECP_SVDP_DH(&U,W,&Z)!=0) return;
-
-    OCT_copy(&VZ,V);
-    OCT_joctet(&VZ,&Z);
-
-    ECP_KDF2(&VZ,P1,EFS,&K);
-
-    K1.len=K2.len=16;
-    for (i=0;i<16;i++) {K1.val[i]=K.val[i]; K2.val[i]=K.val[16+i];}
-
-    ECP_AES_CBC_IV0_ENCRYPT(&K1,M,C);
-
-    OCT_jint(&L2,P2->len,8);
-
-    len=C->len;
-    OCT_joctet(C,P2);
-    OCT_joctet(C,&L2);
-    ECP_HMAC(C,&K2,tlen,T);
-    C->len=len;
-}
-
-/* IEEE1363 ECIES decryption. Decryption of ciphertext V,C,T using private key U outputs plaintext M */
-int ECP_ECIES_DECRYPT(octet *P1,octet *P2,octet *V,octet *C,octet *T,octet *U,octet *M)
-{
-
-	int i,len;
-	char z[EFS],vz[3*EFS+2],k[32],k1[16],k2[16],l2[8],tag[32];
-	octet Z={0,sizeof(z),z};
-	octet VZ={0,sizeof(vz),vz};
-	octet K={0,sizeof(k),k};
-	octet K1={0,sizeof(k1),k1};
-	octet K2={0,sizeof(k2),k2};
-	octet L2={0,sizeof(l2),l2};
-	octet TAG={0,sizeof(tag),tag};
-
-	if (ECP_SVDP_DH(U,V,&Z)!=0) return 0;
-
-    OCT_copy(&VZ,V);
-    OCT_joctet(&VZ,&Z);
-
-	ECP_KDF2(&VZ,P1,EFS,&K);
-
-	K1.len=K2.len=16;
-    for (i=0;i<16;i++) {K1.val[i]=K.val[i]; K2.val[i]=K.val[16+i];}
-
-	if (!ECP_AES_CBC_IV0_DECRYPT(&K1,C,M)) return 0;
-
-	OCT_jint(&L2,P2->len,8);
-
-	len=C->len;
-	OCT_joctet(C,P2);
-    OCT_joctet(C,&L2);
-	ECP_HMAC(C,&K2,T->len,&TAG);
-	C->len=len;
-
-	if (!OCT_comp(T,&TAG)) return 0;
-
-	return 1;
-
-}
-
-#endif
diff --git a/c/ecdh.h b/c/ecdh.h
deleted file mode 100755
index 0dae41a..0000000
--- a/c/ecdh.h
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
-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.
-*/
-
-/**
- * @file ecdh.h
- * @author Mike Scott and Kealan McCusker
- * @date 2nd June 2015
- * @brief ECDH Header file for implementation of standard EC protocols
- *
- * declares functions
- *
- */
-
-#ifndef ECDH_H
-#define ECDH_H
-
-#include "amcl.h"
-
-#define EAS 16 /**< Symmetric Key size - 128 bits */
-#define EGS 32 /**< ECC Group Size */
-#define EFS 32 /**< ECC Field Size */
-
-#define ECDH_OK                     0     /**< Function completed without error */
-/*#define ECDH_DOMAIN_ERROR          -1*/
-#define ECDH_INVALID_PUBLIC_KEY    -2	/**< Public Key is Invalid */
-#define ECDH_ERROR                 -3	/**< ECDH Internal Error */
-#define ECDH_INVALID               -4	/**< ECDH Internal Error */
-/*#define ECDH_DOMAIN_NOT_FOUND      -5
-#define ECDH_OUT_OF_MEMORY         -6
-#define ECDH_DIV_BY_ZERO           -7
-#define ECDH_BAD_ASSUMPTION        -8*/
-
-/* ECDH Auxiliary Functions */
-
-/**	@brief Initialise a random number generator
- *
-	@param R is a pointer to a cryptographically secure random number generator
-	@param S is an input truly random seed value
- */
-extern void ECP_CREATE_CSPRNG(csprng *R,octet *S);
-/**	@brief Kill a random number generator
- *
-	Deletes all internal state
-	@param R is a pointer to a cryptographically secure random number generator
- */
-extern void ECP_KILL_CSPRNG(csprng *R);
-/**	@brief hash an octet into another octet
- *
-	@param I input octet
-	@param O output octet - H(I)
- */
-extern void ECP_HASH(octet *I,octet *O);
-/**	@brief HMAC of message M using key K to create tag of length len in octet tag
- *
-	IEEE-1363 MAC1 function. Uses SHA256 internally.
-	@param M input message octet
-	@param K input encryption key
-	@param len is output desired length of HMAC tag
-	@param tag is the output HMAC
-	@return 0 for bad parameters, else 1
- */
-extern int ECP_HMAC(octet *M,octet *K,int len,octet *tag);
-
-/*extern void KDF1(octet *,int,octet *);*/
-
-/**	@brief Key Derivation Function - generates key K from inputs Z and P
- *
-	IEEE-1363 KDF2 Key Derivation Function. Uses SHA256 internally.
-	@param Z input octet
-	@param P input key derivation parameters - can be NULL
-	@param len is output desired length of key
-	@param K is the derived key
- */
-extern void ECP_KDF2(octet *Z,octet *P,int len,octet *K);
-/**	@brief Password Based Key Derivation Function - generates key K from password, salt and repeat counter
- *
-	PBKDF2 Password Based Key Derivation Function. Uses SHA256 internally.
-	@param P input password
-	@param S input salt
-	@param rep Number of times to be iterated.
-	@param len is output desired length of key
-	@param K is the derived key
- */
-extern void ECP_PBKDF2(octet *P,octet *S,int rep,int len,octet *K);
-/**	@brief AES encrypts a plaintext to a ciphtertext
- *
-	IEEE-1363 AES_CBC_IV0_ENCRYPT function. Encrypts in CBC mode with a zero IV, padding as necessary to create a full final block.
-	@param K AES key
-	@param P input plaintext octet
-	@param C output ciphertext octet
- */
-extern void ECP_AES_CBC_IV0_ENCRYPT(octet *K,octet *P,octet *C);
-/**	@brief AES encrypts a plaintext to a ciphtertext
- *
-	IEEE-1363 AES_CBC_IV0_DECRYPT function. Decrypts in CBC mode with a zero IV.
-	@param K AES key
-	@param C input ciphertext octet
-	@param P output plaintext octet
-	@return 0 if bad input, else 1
- */
-extern int ECP_AES_CBC_IV0_DECRYPT(octet *K,octet *C,octet *P);
-
-/* ECDH primitives - support functions */
-/**	@brief Generate an ECC public/private key pair
- *
-	@param R is a pointer to a cryptographically secure random number generator
-	@param s the private key, an output internally randomly generated if R!=NULL, otherwise must be provided as an input
-	@param W the output public key, which is s.G, where G is a fixed generator
-	@return 0 or an error code
- */
-extern int  ECP_KEY_PAIR_GENERATE(csprng *R,octet *s,octet *W);
-/**	@brief Validate an ECC public key
- *
-	@param f if = 0 just does some simple checks, else tests that W is of the correct order
-	@param W the input public key to be validated
-	@return 0 if public key is OK, or an error code
- */
-extern int  ECP_PUBLIC_KEY_VALIDATE(int f,octet *W);
-
-/* ECDH primitives */
-
-/**	@brief Generate Diffie-Hellman shared key
- *
-	IEEE-1363 Diffie-Hellman shared secret calculation
-	@param s is the input private key,
-	@param W the input public key of the other party
-	@param K the output shared key, in fact the x-coordinate of s.W
-	@return 0 or an error code
- */
-extern int ECP_SVDP_DH(octet *s,octet *W,octet *K);
-/*extern int ECPSVDP_DHC(octet *,octet *,int,octet *);*/
-
-/*#if CURVETYPE!=MONTGOMERY */
-/* ECIES functions */
-/**	@brief ECIES Encryption
- *
-	IEEE-1363 ECIES Encryption
-	@param P1 input Key Derivation parameters
-	@param P2 input Encoding parameters
-	@param R is a pointer to a cryptographically secure random number generator
-	@param W the input public key of the recieving party
-	@param M is the plaintext message to be encrypted
-	@param len the length of the HMAC tag
-	@param V component of the output ciphertext
-	@param C the output ciphertext
-	@param T the output HMAC tag, part of the ciphertext
- */
-extern void ECP_ECIES_ENCRYPT(octet *P1,octet *P2,csprng *R,octet *W,octet *M,int len,octet *V,octet *C,octet *T);
-/**	@brief ECIES Decryption
- *
-	IEEE-1363 ECIES Decryption
-	@param P1 input Key Derivation parameters
-	@param P2 input Encoding parameters
-	@param V component of the input ciphertext
-	@param C the input ciphertext
-	@param T the input HMAC tag, part of the ciphertext
-	@param U the input private key for decryption
-	@param M the output plaintext message
-	@return 1 if successful, else 0
- */
-extern int ECP_ECIES_DECRYPT(octet *P1,octet *P2,octet *V,octet *C,octet *T,octet *U,octet *M);
-
-/* ECDSA functions */
-/**	@brief ECDSA Signature
- *
-	IEEE-1363 ECDSA Signature
-	@param R is a pointer to a cryptographically secure random number generator
-	@param s the input private signing key
-	@param M the input message to be signed
-	@param c component of the output signature
-	@param d component of the output signature
-
- */
-extern int ECP_SP_DSA(csprng *R,octet *s,octet *M,octet *c,octet *d);
-/**	@brief ECDSA Signature Verification
- *
-	IEEE-1363 ECDSA Signature Verification
-	@param W the input public key
-	@param M the input message
-	@param c component of the input signature
-	@param d component of the input signature
-	@return 0 or an error code
- */
-extern int ECP_VP_DSA(octet *W,octet *M,octet *c,octet *d);
-/*#endif*/
-
-#endif
-
diff --git a/c/ecp.c b/c/ecp.c
deleted file mode 100755
index b7fdd10..0000000
--- a/c/ecp.c
+++ /dev/null
@@ -1,1091 +0,0 @@
-/*
-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.
-*/
-
-/* AMCL Elliptic Curve Functions */
-/* SU=m, SU is Stack Usage (Weierstrass Curves) */
-
-//#define HAS_MAIN
-
-#include "amcl.h"
-
-/* test for P=O point-at-infinity */
-int ECP_isinf(ECP *P)
-{
-#if CURVETYPE==EDWARDS
-	FP_reduce(P->x);
-	FP_reduce(P->y);
-	FP_reduce(P->z);
-	return (BIG_iszilch(P->x) && BIG_comp(P->y,P->z)==0);
-#else
-	return P->inf;
-#endif
-}
-
-/* Conditional swap of P and Q dependant on d */
-static void ECP_cswap(ECP *P,ECP *Q,int d)
-{
-	BIG_cswap(P->x,Q->x,d);
-#if CURVETYPE!=MONTGOMERY
-	BIG_cswap(P->y,Q->y,d);
-#endif
-	BIG_cswap(P->z,Q->z,d);
-#if CURVETYPE!=EDWARDS
-	d=~(d-1);
-	d=d&(P->inf^Q->inf);
-	P->inf^=d;
-	Q->inf^=d;
-#endif
-}
-
-/* Conditional move Q to P dependant on d */
-static void ECP_cmove(ECP *P,ECP *Q,int d)
-{
-	BIG_cmove(P->x,Q->x,d);
-#if CURVETYPE!=MONTGOMERY
-	BIG_cmove(P->y,Q->y,d);
-#endif
-	BIG_cmove(P->z,Q->z,d);
-#if CURVETYPE!=EDWARDS
-	d=~(d-1);
-	P->inf^=(P->inf^Q->inf)&d;
-#endif
-}
-
-/* return 1 if b==c, no branching */
-static int teq(sign32 b,sign32 c)
-{
-	sign32 x=b^c;
-	x-=1;  // if x=0, x now -1
-	return (int)((x>>31)&1);
-}
-
-/* Constant time select from pre-computed table */
-static void ECP_select(ECP *P,ECP W[],sign32 b)
-{
-  ECP MP;
-  sign32 m=b>>31;
-  sign32 babs=(b^m)-m;
-
-  babs=(babs-1)/2;
-
-  ECP_cmove(P,&W[0],teq(babs,0));  // conditional move
-  ECP_cmove(P,&W[1],teq(babs,1));
-  ECP_cmove(P,&W[2],teq(babs,2));
-  ECP_cmove(P,&W[3],teq(babs,3));
-  ECP_cmove(P,&W[4],teq(babs,4));
-  ECP_cmove(P,&W[5],teq(babs,5));
-  ECP_cmove(P,&W[6],teq(babs,6));
-  ECP_cmove(P,&W[7],teq(babs,7));
-
-  ECP_copy(&MP,P);
-  ECP_neg(&MP);  // minus P
-  ECP_cmove(P,&MP,(int)(m&1));
-}
-
-/* Test P == Q */
-/* SU=168 */
-int ECP_equals(ECP *P,ECP *Q)
-{
-#if CURVETYPE==WEIERSTRASS
-	BIG pz2,qz2,a,b;
-	if (ECP_isinf(P) && ECP_isinf(Q)) return 1;
-	if (ECP_isinf(P) || ECP_isinf(Q)) return 0;
-
-	FP_sqr(pz2,P->z); FP_sqr(qz2,Q->z);
-
-	FP_mul(a,P->x,qz2);
-	FP_mul(b,Q->x,pz2);
-	FP_reduce(a);
-	FP_reduce(b);
-	if (BIG_comp(a,b)!=0) return 0;
-
-	FP_mul(a,P->y,qz2);
-	FP_mul(a,a,Q->z);
-	FP_mul(b,Q->y,pz2);
-	FP_mul(b,b,P->z);
-	FP_reduce(a);
-	FP_reduce(b);
-	if (BIG_comp(a,b)!=0) return 0;
-	return 1;
-#else
-	BIG a,b;
-	if (ECP_isinf(P) && ECP_isinf(Q)) return 1;
-	if (ECP_isinf(P) || ECP_isinf(Q)) return 0;
-
-	FP_mul(a,P->x,Q->z);
-	FP_mul(b,Q->x,P->z);
-	FP_reduce(a);
-	FP_reduce(b);
-	if (BIG_comp(a,b)!=0) return 0;
-
-#if CURVETYPE==EDWARDS
-	FP_mul(a,P->y,Q->z);
-	FP_mul(b,Q->y,P->z);
-	FP_reduce(a);
-	FP_reduce(b);
-	if (BIG_comp(a,b)!=0) return 0;
-#endif
-
-	return 1;
-#endif
-}
-
-/* Set P=Q */
-/* SU=16 */
-void ECP_copy(ECP *P,ECP *Q)
-{
-#if CURVETYPE!=EDWARDS
-	P->inf=Q->inf;
-#endif
-	BIG_copy(P->x,Q->x);
-#if CURVETYPE!=MONTGOMERY
-	BIG_copy(P->y,Q->y);
-#endif
-	BIG_copy(P->z,Q->z);
-}
-
-/* Set P=-Q */
-#if CURVETYPE!=MONTGOMERY
-/* SU=8 */
-void ECP_neg(ECP *P)
-{
-	if (ECP_isinf(P)) return;
-#if CURVETYPE==WEIERSTRASS
-	FP_neg(P->y,P->y);
-	BIG_norm(P->y);
-#else
-	FP_neg(P->x,P->x);
-	BIG_norm(P->x);
-#endif
-
-}
-#endif
-
-/* Set P=O */
-void ECP_inf(ECP *P)
-{
-#if CURVETYPE==EDWARDS
-	BIG_zero(P->x); FP_one(P->y); FP_one(P->z);
-#else
-	P->inf=1;
-#endif
-}
-
-/* Calculate right Hand Side of curve equation y^2=RHS */
-/* SU=56 */
-void ECP_rhs(BIG v,BIG x)
-{
-#if CURVETYPE==WEIERSTRASS
-/* x^3+Ax+B */
-	BIG t;
-	FP_sqr(t,x);
-	FP_mul(t,t,x);
-
-	if (CURVE_A==-3)
-	{
-		FP_neg(v,x);
-		BIG_norm(v);
-		BIG_imul(v,v,-CURVE_A);
-		BIG_norm(v);
-		FP_add(v,t,v);
-	}
-	else BIG_copy(v,t);
-
-	BIG_rcopy(t,CURVE_B);
-	FP_nres(t);
-	FP_add(v,t,v);
-	FP_reduce(v);
-#endif
-
-#if CURVETYPE==EDWARDS
-/* (Ax^2-1)/(Bx^2-1) */
-	BIG t,m,one;
-	BIG_rcopy(m,Modulus);
-	FP_sqr(v,x);
-	FP_one(one);
-	BIG_rcopy(t,CURVE_B); FP_nres(t);
-	FP_mul(t,v,t); FP_sub(t,t,one);
-	if (CURVE_A==1) FP_sub(v,v,one);
-
-	if (CURVE_A==-1)
-	{
-		FP_add(v,v,one);
-		FP_neg(v,v);
-	}
-	FP_redc(v); FP_redc(t);
-	BIG_moddiv(v,v,t,m);
-	FP_nres(v);
-#endif
-
-#if CURVETYPE==MONTGOMERY
-/* x^3+Ax^2+x */
-	BIG x2,x3;
-	FP_sqr(x2,x);
-	FP_mul(x3,x2,x);
-	BIG_copy(v,x);
-	FP_imul(x2,x2,CURVE_A);
-	FP_add(v,v,x2);
-	FP_add(v,v,x3);
-	FP_reduce(v);
-#endif
-}
-
-/* Set P=(x,y) */
-
-#if CURVETYPE==MONTGOMERY
-
-/* Set P=(x,{y}) */
-
-int ECP_set(ECP *P,BIG x)
-{
-	BIG m,rhs;
-	BIG_rcopy(m,Modulus);
-	BIG_copy(rhs,x);
-	FP_nres(rhs);
-	ECP_rhs(rhs,rhs);
-	FP_redc(rhs);
-
-	if (BIG_jacobi(rhs,m)!=1)
-	{
-		ECP_inf(P);
-		return 0;
-	}
-	P->inf=0;
-	BIG_copy(P->x,x); FP_nres(P->x);
-	FP_one(P->z);
-	return 1;
-}
-
-/* Extract x coordinate as BIG */
-int ECP_get(BIG x,ECP *P)
-{
-	if (ECP_isinf(P)) return -1;
-	ECP_affine(P);
-	BIG_copy(x,P->x);
-	FP_redc(x);
-	return 0;
-}
-
-
-#else
-/* Extract (x,y) and return sign of y. If x and y are the same return only x */
-/* SU=16 */
-int ECP_get(BIG x,BIG y,ECP *P)
-{
-	int s;
-#if CURVETYPE!=EDWARDS
-	if (ECP_isinf(P)) return -1;
-#endif
-	ECP_affine(P);
-
-	BIG_copy(y,P->y);
-	FP_redc(y);
-
-	s=BIG_parity(y);
-
-	BIG_copy(x,P->x);
-	FP_redc(x);
-
-	return s;
-}
-
-/* Set P=(x,{y}) */
-/* SU=96 */
-int ECP_set(ECP *P,BIG x,BIG y)
-{
-	BIG rhs,y2;
-	BIG_copy(y2,y);
-
-	FP_nres(y2);
-
-	FP_sqr(y2,y2);
-	FP_reduce(y2);
-
-	BIG_copy(rhs,x);
-	FP_nres(rhs);
-
-	ECP_rhs(rhs,rhs);
-
-	if (BIG_comp(y2,rhs)!=0)
-	{
-		ECP_inf(P);
-		return 0;
-	}
-#if CURVETYPE==WEIERSTRASS
-	P->inf=0;
-#endif
-	BIG_copy(P->x,x); FP_nres(P->x);
-	BIG_copy(P->y,y); FP_nres(P->y);
-	FP_one(P->z);
-	return 1;
-}
-
-/* Set P=(x,y), where y is calculated from x with sign s */
-/* SU=136 */
-int ECP_setx(ECP *P,BIG x,int s)
-{
-	BIG t,rhs,m;
-	BIG_rcopy(m,Modulus);
-
-	BIG_copy(rhs,x);
-	FP_nres(rhs);
-	ECP_rhs(rhs,rhs);
-	BIG_copy(t,rhs);
-	FP_redc(t);
-	if (BIG_jacobi(t,m)!=1)
-	{
-		ECP_inf(P);
-		return 0;
-	}
-#if CURVETYPE==WEIERSTRASS
-	P->inf=0;
-#endif
-	BIG_copy(P->x,x); FP_nres(P->x);
-
-	FP_sqrt(P->y,rhs);
-	BIG_copy(rhs,P->y);
-	FP_redc(rhs);
-	if (BIG_parity(rhs)!=s)
-		FP_neg(P->y,P->y);
-	FP_reduce(P->y);
-	FP_one(P->z);
-	return 1;
-}
-
-#endif
-
-/* Convert P to Affine, from (x,y,z) to (x,y) */
-/* SU=160 */
-void ECP_affine(ECP *P)
-{
-	BIG one,iz,m;
-#if CURVETYPE==WEIERSTRASS
-	BIG izn;
-	if (ECP_isinf(P)) return;
-	FP_one(one);
-	if (BIG_comp(P->z,one)==0) return;
-	BIG_rcopy(m,Modulus);
-	FP_redc(P->z);
-
-	BIG_invmodp(iz,P->z,m);
-	FP_nres(iz);
-
-	FP_sqr(izn,iz);
-	FP_mul(P->x,P->x,izn);
-	FP_mul(izn,izn,iz);
-	FP_mul(P->y,P->y,izn);
-	FP_reduce(P->y);
-
-#endif
-#if CURVETYPE==EDWARDS
-	FP_one(one);
-	if (BIG_comp(P->z,one)==0) return;
-	BIG_rcopy(m,Modulus);
-	FP_redc(P->z);
-
-	BIG_invmodp(iz,P->z,m);
-	FP_nres(iz);
-
-	FP_mul(P->x,P->x,iz);
-	FP_mul(P->y,P->y,iz);
-	FP_reduce(P->y);
-
-#endif
-#if CURVETYPE==MONTGOMERY
-	if (ECP_isinf(P)) return;
-	FP_one(one);
-	if (BIG_comp(P->z,one)==0) return;
-
-	BIG_rcopy(m,Modulus);
-	FP_redc(P->z);
-	BIG_invmodp(iz,P->z,m);
-	FP_nres(iz);
-
-	FP_mul(P->x,P->x,iz);
-
-#endif
-	FP_reduce(P->x);
-	BIG_copy(P->z,one);
-}
-
-/* SU=120 */
-void ECP_outputxyz(ECP *P)
-{
-	BIG x,y,z;
-	if (ECP_isinf(P))
-	{
-		printf("Infinity\n");
-		return;
-	}
-	BIG_copy(x,P->x); FP_reduce(x); FP_redc(x);
-	BIG_copy(z,P->z); FP_reduce(z); FP_redc(z);
-
-#if CURVETYPE!=MONTGOMERY
-	BIG_copy(y,P->y); FP_reduce(y); FP_redc(y);
-	printf("(");BIG_output(x);printf(",");BIG_output(y);printf(",");BIG_output(z);printf(")\n");
-
-#else
-	printf("(");BIG_output(x);printf(",");BIG_output(z);printf(")\n");
-#endif
-}
-
-/* SU=16 */
-/* Output point P */
-void ECP_output(ECP *P)
-{
-	if (ECP_isinf(P))
-	{
-		printf("Infinity\n");
-		return;
-	}
-	ECP_affine(P);
-#if CURVETYPE!=MONTGOMERY
-	FP_redc(P->x); FP_redc(P->y);
-	printf("(");BIG_output(P->x);printf(",");BIG_output(P->y);printf(")\n");
-	FP_nres(P->x); FP_nres(P->y);
-#else
-	FP_redc(P->x);
-	printf("(");BIG_output(P->x);printf(")\n");
-	FP_nres(P->x);
-#endif
-}
-
-
-/* SU=88 */
-/* Convert P to octet string */
-void ECP_toOctet(octet *W,ECP *P)
-{
-#if CURVETYPE==MONTGOMERY
-	BIG x;
-	ECP_get(x,P);
-	W->len=MODBYTES+1; W->val[0]=6;
-	BIG_toBytes(&(W->val[1]),x);
-#else
-	BIG x,y;
-	ECP_get(x,y,P);
-	W->len=2*MODBYTES+1; W->val[0]=4;
-	BIG_toBytes(&(W->val[1]),x);
-	BIG_toBytes(&(W->val[MODBYTES+1]),y);
-#endif
-}
-
-/* SU=88 */
-/* Restore P from octet string */
-int ECP_fromOctet(ECP *P,octet *W)
-{
-#if CURVETYPE==MONTGOMERY
-	BIG x;
-	BIG_fromBytes(x,&(W->val[1]));
-    if (ECP_set(P,x)) return 1;
-	return 0;
-#else
-	BIG x,y;
-	BIG_fromBytes(x,&(W->val[1]));
-	BIG_fromBytes(y,&(W->val[MODBYTES+1]));
-    if (ECP_set(P,x,y)) return 1;
-	return 0;
-#endif
-}
-
-
-/* Set P=2P */
-/* SU=272 */
-void ECP_dbl(ECP *P)
-{
-#if CURVETYPE==WEIERSTRASS
-	int i;
-	BIG one,s1,s2;
-	BIG w1,w7,w8,w2,w3,w6;
-	if (ECP_isinf(P)) return;
-
-	if (BIG_iszilch(P->y))
-	{
-		P->inf=1;
-		return;
-	}
-	FP_one(one);
-	BIG_zero(w6);
-
-	if (CURVE_A==-3)
-	{
-		if (BIG_comp(P->z,one)==0) BIG_copy(w6,one);
-		else FP_sqr(w6,P->z);
-		FP_neg(w1,w6);
-		FP_add(w3,P->x,w1);
-		FP_add(w8,P->x,w6);
-		FP_mul(w3,w3,w8);
-		BIG_imul(w8,w3,3);
-	}
-	else
-	{
-/* assuming A=0 */
-		FP_sqr(w1,P->x);
-		BIG_imul(w8,w1,3);
-	}
-
-	FP_sqr(w2,P->y);
-	FP_mul(w3,P->x,w2);
-
-	BIG_imul(w3,w3,4);
-	FP_neg(w1,w3);
-#if CHUNK<64
-	BIG_norm(w1);
-#endif
-	FP_sqr(P->x,w8);
-	FP_add(P->x,P->x,w1);
-	FP_add(P->x,P->x,w1);
-
-	BIG_norm(P->x);
-
-	if (BIG_comp(P->z,one)==0) BIG_copy(P->z,P->y);
-	else FP_mul(P->z,P->z,P->y);
-	FP_add(P->z,P->z,P->z);
-
-
-	FP_add(w7,w2,w2);
-	FP_sqr(w2,w7);
-
-	FP_add(w2,w2,w2);
-	FP_sub(w3,w3,P->x);
-	FP_mul(P->y,w8,w3);
-//#if CHUNK<64
-//	BIG_norm(w2);
-//#endif
-	FP_sub(P->y,P->y,w2);
-
-	BIG_norm(P->y);
-	BIG_norm(P->z);
-
-#endif
-
-#if CURVETYPE==EDWARDS
-/* Not using square for multiplication swap, as (1) it needs more adds, and (2) it triggers more reductions */
-	BIG B,C,D,E,F,H,J;
-
-	FP_mul(B,P->x,P->y); FP_add(B,B,B);
-	FP_sqr(C,P->x);
-	FP_sqr(D,P->y);
-	if (CURVE_A==1) BIG_copy(E,C);
-	if (CURVE_A==-1) FP_neg(E,C);
-	FP_add(F,E,D);
-#if CHUNK<64
-	BIG_norm(F);
-#endif
-	FP_sqr(H,P->z);
-	FP_add(H,H,H); FP_sub(J,F,H);
-	FP_mul(P->x,B,J);
-	FP_sub(E,E,D);
-	FP_mul(P->y,F,E);
-	FP_mul(P->z,F,J);
-
-	BIG_norm(P->x);
-	BIG_norm(P->y);
-	BIG_norm(P->z);
-
-#endif
-
-#if CURVETYPE==MONTGOMERY
-	BIG t,A,B,AA,BB,C;
-	if (ECP_isinf(P)) return;
-
-	FP_add(A,P->x,P->z);
-	FP_sqr(AA,A);
-	FP_sub(B,P->x,P->z);
-	FP_sqr(BB,B);
-	FP_sub(C,AA,BB);
-//#if CHUNK<64
-//	BIG_norm(C);
-//#endif
-
-	FP_mul(P->x,AA,BB);
-	FP_imul(A,C,(CURVE_A+2)/4);
-	FP_add(BB,BB,A);
-	FP_mul(P->z,BB,C);
-
-	BIG_norm(P->x);
-	BIG_norm(P->z);
-#endif
-}
-
-#if CURVETYPE==MONTGOMERY
-
-/* Set P+=Q. W is difference between P and Q and is affine */
-void ECP_add(ECP *P,ECP *Q,ECP *W)
-{
-	BIG A,B,C,D,DA,CB;
-
-	FP_add(A,P->x,P->z);
-	FP_sub(B,P->x,P->z);
-
-	FP_add(C,Q->x,Q->z);
-	FP_sub(D,Q->x,Q->z);
-
-	FP_mul(DA,D,A);
-	FP_mul(CB,C,B);
-
-	FP_add(A,DA,CB); FP_sqr(A,A);
-	FP_sub(B,DA,CB); FP_sqr(B,B);
-
-	BIG_copy(P->x,A);
-	FP_mul(P->z,W->x,B);
-
-	FP_reduce(P->z);
-	if (BIG_iszilch(P->z)) P->inf=1;
-	else P->inf=0;
-
-	BIG_norm(P->x);
-}
-
-
-#else
-
-/* Set P+=Q */
-/* SU=248 */
-void ECP_add(ECP *P,ECP *Q)
-{
-#if CURVETYPE==WEIERSTRASS
-	int aff;
-	BIG one,B,D,E,C,A;
-	if (ECP_isinf(Q)) return;
-	if (ECP_isinf(P))
-	{
-		ECP_copy(P,Q);
-		return;
-	}
-
-	FP_one(one);
-	aff=1;
-	if (BIG_comp(Q->z,one)!=0) aff=0;
-
-	if (!aff)
-	{
-		FP_sqr(A,Q->z);
-		FP_mul(C,A,Q->z);
-
-		FP_sqr(B,P->z);
-		FP_mul(D,B,P->z);
-
-		FP_mul(A,P->x,A);
-		FP_mul(C,P->y,C);
-	}
-	else
-	{
-		BIG_copy(A,P->x);
-		BIG_copy(C,P->y);
-
-		FP_sqr(B,P->z);
-		FP_mul(D,B,P->z);
-	}
-
-	FP_mul(B,Q->x,B); FP_sub(B,B,A); /* B=Qx.z^2-x.Qz^2 */
-	FP_mul(D,Q->y,D); FP_sub(D,D,C); /* D=Qy.z^3-y.Qz^3 */
-
-	FP_reduce(B);
-	if (BIG_iszilch(B))
-	{
-		FP_reduce(D);
-		if (BIG_iszilch(D))
-		{
-			ECP_dbl(P);
-			return;
-		}
-		else
-		{
-			ECP_inf(P);
-			return;
-		}
-	}
-	if (!aff) FP_mul(P->z,P->z,Q->z);
-	FP_mul(P->z,P->z,B);
-
-	FP_sqr(E,B);
-	FP_mul(B,B,E);
-	FP_mul(A,A,E);
-
-	FP_add(E,A,A);
-	FP_add(E,E,B);
-
-	FP_sqr(P->x,D);
-	FP_sub(P->x,P->x,E);
-
-	FP_sub(A,A,P->x);
-	FP_mul(P->y,A,D);
-	FP_mul(C,C,B);
-	FP_sub(P->y,P->y,C);
-
-	BIG_norm(P->x);
-	BIG_norm(P->y);
-	BIG_norm(P->z);
-
-#else
-	BIG b,A,B,C,D,E,F,G,H,I;
-
-	BIG_rcopy(b,CURVE_B); FP_nres(b);
-	FP_mul(A,P->z,Q->z);
-
-	FP_sqr(B,A);
-	FP_mul(C,P->x,Q->x);
-	FP_mul(D,P->y,Q->y);
-	FP_mul(E,C,D); FP_mul(E,E,b);
-
-	FP_sub(F,B,E);
-	FP_add(G,B,E);
-
-	FP_add(C,C,D);
-
-	if (CURVE_A==1) FP_sub(E,D,C);
-
-	FP_add(B,P->x,P->y);
-	FP_add(D,Q->x,Q->y);
-	FP_mul(B,B,D);
-	FP_sub(B,B,C);
-	FP_mul(B,B,F);
-	FP_mul(P->x,A,B);
-
-
-	if (CURVE_A==1) FP_mul(C,E,G);
-	if (CURVE_A==-1)FP_mul(C,C,G);
-
-	FP_mul(P->y,A,C);
-	FP_mul(P->z,F,G);
-
-	BIG_norm(P->x);
-	BIG_norm(P->y);
-	BIG_norm(P->z);
-
-#endif
-}
-
-/* Set P-=Q */
-/* SU=16 */
-void  ECP_sub(ECP *P,ECP *Q)
-{
-	ECP_neg(Q);
-	ECP_add(P,Q);
-	ECP_neg(Q);
-}
-
-#endif
-
-
-#if CURVETYPE==WEIERSTRASS
-/* normalises array of points. Assumes P[0] is normalised already */
-
-static void ECP_multiaffine(int m,ECP P[],BIG work[])
-{
-	int i;
-	BIG t1,t2;
-
-	FP_one(work[0]);
-	BIG_copy(work[1],P[0].z);
-	for (i=2;i<m;i++)
-		FP_mul(work[i],work[i-1],P[i-1].z);
-
-	FP_mul(t1,work[m-1],P[m-1].z);
-	FP_inv(t1,t1);
-
-	BIG_copy(t2,P[m-1].z);
-	FP_mul(work[m-1],work[m-1],t1);
-
-	for (i=m-2;;i--)
-    {
-		if (i==0)
-		{
-			FP_mul(work[0],t1,t2);
-			break;
-		}
-		FP_mul(work[i],work[i],t2);
-		FP_mul(work[i],work[i],t1);
-		FP_mul(t2,P[i].z,t2);
-    }
-/* now work[] contains inverses of all Z coordinates */
-
-	for (i=0;i<m;i++)
-	{
-		FP_one(P[i].z);
-		FP_sqr(t1,work[i]);
-		FP_mul(P[i].x,P[i].x,t1);
-		FP_mul(t1,work[i],t1);
-		FP_mul(P[i].y,P[i].y,t1);
-    }
-}
-
-#endif
-
-#if CURVETYPE!=MONTGOMERY
-/* constant time multiply by small integer of length bts - use ladder */
-void ECP_pinmul(ECP *P,int e,int bts)
-{
-	int nb,i,b;
-	ECP R0,R1;
-
-	ECP_affine(P);
-	ECP_inf(&R0);
-	ECP_copy(&R1,P);
-
-    for (i=bts-1;i>=0;i--)
-	{
-		b=(e>>i)&1;
-		ECP_copy(P,&R1);
-		ECP_add(P,&R0);
-		ECP_cswap(&R0,&R1,b);
-		ECP_copy(&R1,P);
-		ECP_dbl(&R0);
-		ECP_cswap(&R0,&R1,b);
-	}
-	ECP_copy(P,&R0);
-	ECP_affine(P);
-}
-#endif
-
-/* Set P=r*P */
-/* SU=424 */
-void ECP_mul(ECP *P,BIG e)
-{
-#if CURVETYPE==MONTGOMERY
-/* Montgomery ladder */
-	int nb,i,b;
-	ECP R0,R1,D;
-	if (ECP_isinf(P)) return;
-	if (BIG_iszilch(e))
-	{
-		ECP_inf(P);
-		return;
-	}
-	ECP_affine(P);
-
-	ECP_copy(&R0,P);
-	ECP_copy(&R1,P);
-	ECP_dbl(&R1);
-	ECP_copy(&D,P);
-
-	nb=BIG_nbits(e);
-    for (i=nb-2;i>=0;i--)
-    {
-		b=BIG_bit(e,i);
-		ECP_copy(P,&R1);
-		ECP_add(P,&R0,&D);
-		ECP_cswap(&R0,&R1,b);
-		ECP_copy(&R1,P);
-		ECP_dbl(&R0);
-		ECP_cswap(&R0,&R1,b);
-	}
-	ECP_copy(P,&R0);
-
-#else
-/* fixed size windows */
-	int i,b,nb,m,s,ns;
-	BIG mt,t;
-	ECP Q,W[8],C;
-	sign8 w[1+(NLEN*BASEBITS+3)/4];
-#if CURVETYPE==WEIERSTRASS
-	BIG work[8];
-#endif
-	if (ECP_isinf(P)) return;
-	if (BIG_iszilch(e))
-	{
-		ECP_inf(P);
-		return;
-	}
-
-	ECP_affine(P);
-
-/* precompute table */
-
-	ECP_copy(&Q,P);
-	ECP_dbl(&Q);
-	ECP_copy(&W[0],P);
-
-	for (i=1;i<8;i++)
-	{
-		ECP_copy(&W[i],&W[i-1]);
-		ECP_add(&W[i],&Q);
-	}
-
-/* convert the table to affine */
-#if CURVETYPE==WEIERSTRASS
-	ECP_multiaffine(8,W,work);
-#endif
-
-/* make exponent odd - add 2P if even, P if odd */
-	BIG_copy(t,e);
-	s=BIG_parity(t);
-	BIG_inc(t,1); BIG_norm(t); ns=BIG_parity(t); BIG_copy(mt,t); BIG_inc(mt,1); BIG_norm(mt);
-	BIG_cmove(t,mt,s);
-	ECP_cmove(&Q,P,ns);
-	ECP_copy(&C,&Q);
-
-	nb=1+(BIG_nbits(t)+3)/4;
-
-/* convert exponent to signed 4-bit window */
-	for (i=0;i<nb;i++)
-	{
-		w[i]=BIG_lastbits(t,5)-16;
-		BIG_dec(t,w[i]); BIG_norm(t);
-		BIG_fshr(t,4);
-	}
-	w[nb]=BIG_lastbits(t,5);
-
-	ECP_copy(P,&W[(w[nb]-1)/2]);
-	for (i=nb-1;i>=0;i--)
-	{
-		ECP_select(&Q,W,w[i]);
-		ECP_dbl(P);
-		ECP_dbl(P);
-		ECP_dbl(P);
-		ECP_dbl(P);
-		ECP_add(P,&Q);
-	}
-	ECP_sub(P,&C); /* apply correction */
-#endif
-	ECP_affine(P);
-}
-
-#if CURVETYPE!=MONTGOMERY
-/* Set P=eP+fQ double multiplication */
-/* constant time - as useful for GLV method in pairings */
-/* SU=456 */
-
-void ECP_mul2(ECP *P,ECP *Q,BIG e,BIG f)
-{
-	BIG te,tf,mt;
-	ECP S,T,W[8],C;
-	sign8 w[1+(NLEN*BASEBITS+1)/2];
-	int i,a,b,s,ns,nb;
-#if CURVETYPE==WEIERSTRASS
-	BIG work[8];
-#endif
-
-	ECP_affine(P);
-	ECP_affine(Q);
-
-	BIG_copy(te,e);
-	BIG_copy(tf,f);
-
-/* precompute table */
-	ECP_copy(&W[1],P); ECP_sub(&W[1],Q);  /* P+Q */
-	ECP_copy(&W[2],P); ECP_add(&W[2],Q);  /* P-Q */
-	ECP_copy(&S,Q); ECP_dbl(&S);  /* S=2Q */
-	ECP_copy(&W[0],&W[1]); ECP_sub(&W[0],&S);
-	ECP_copy(&W[3],&W[2]); ECP_add(&W[3],&S);
-	ECP_copy(&T,P); ECP_dbl(&T); /* T=2P */
-	ECP_copy(&W[5],&W[1]); ECP_add(&W[5],&T);
-	ECP_copy(&W[6],&W[2]); ECP_add(&W[6],&T);
-	ECP_copy(&W[4],&W[5]); ECP_sub(&W[4],&S);
-	ECP_copy(&W[7],&W[6]); ECP_add(&W[7],&S);
-
-#if CURVETYPE==WEIERSTRASS
-	ECP_multiaffine(8,W,work);
-#endif
-
-/* if multiplier is odd, add 2, else add 1 to multiplier, and add 2P or P to correction */
-
-	s=BIG_parity(te);
-	BIG_inc(te,1); BIG_norm(te); ns=BIG_parity(te); BIG_copy(mt,te); BIG_inc(mt,1); BIG_norm(mt);
-	BIG_cmove(te,mt,s);
-	ECP_cmove(&T,P,ns);
-	ECP_copy(&C,&T);
-
-	s=BIG_parity(tf);
-	BIG_inc(tf,1); BIG_norm(tf); ns=BIG_parity(tf); BIG_copy(mt,tf); BIG_inc(mt,1); BIG_norm(mt);
-	BIG_cmove(tf,mt,s);
-	ECP_cmove(&S,Q,ns);
-	ECP_add(&C,&S);
-
-	BIG_add(mt,te,tf); BIG_norm(mt);
-	nb=1+(BIG_nbits(mt)+1)/2;
-
-/* convert exponent to signed 2-bit window */
-	for (i=0;i<nb;i++)
-	{
-		a=BIG_lastbits(te,3)-4;
-		BIG_dec(te,a); BIG_norm(te);
-		BIG_fshr(te,2);
-		b=BIG_lastbits(tf,3)-4;
-		BIG_dec(tf,b); BIG_norm(tf);
-		BIG_fshr(tf,2);
-		w[i]=4*a+b;
-	}
-	w[nb]=(4*BIG_lastbits(te,3)+BIG_lastbits(tf,3));
-
-	ECP_copy(P,&W[(w[nb]-1)/2]);
-	for (i=nb-1;i>=0;i--)
-	{
-		ECP_select(&T,W,w[i]);
-		ECP_dbl(P);
-		ECP_dbl(P);
-		ECP_add(P,&T);
-	}
-	ECP_sub(P,&C); /* apply correction */
-	ECP_affine(P);
-}
-
-#endif
-
-#ifdef HAS_MAIN
-
-int main()
-{
-	int i;
-	ECP G,P;
-	csprng RNG;
-	BIG r,s,x,y,b,m,w,q;
-	BIG_rcopy(x,CURVE_Gx);
-#if CURVETYPE!=MONTGOMERY
-	BIG_rcopy(y,CURVE_Gy);
-#endif
-	BIG_rcopy(m,Modulus);
-
-	printf("x= ");BIG_output(x); printf("\n");
-#if CURVETYPE!=MONTGOMERY
-	printf("y= ");BIG_output(y); printf("\n");
-#endif
-	RNG_seed(&RNG,3,"abc");
-
-#if CURVETYPE!=MONTGOMERY
-	ECP_set(&G,x,y);
-#else
-	ECP_set(&G,x);
-#endif
-	if (ECP_isinf(&G)) printf("Failed to set - point not on curve\n");
-	else printf("set success\n");
-
-	ECP_output(&G);
-
-	BIG_rcopy(r,CURVE_Order); //BIG_dec(r,7);
-	printf("r= ");BIG_output(r); printf("\n");
-
-	ECP_copy(&P,&G);
-
-	ECP_mul(&P,r);
-
-	ECP_output(&P);
-//exit(0);
-	BIG_randomnum(w,&RNG);
-	BIG_mod(w,r);
-
-	ECP_copy(&P,&G);
-	ECP_mul(&P,w);
-
-	ECP_output(&P);
-
-	return 0;
-}
-
-#endif
diff --git a/c/ecp2.c b/c/ecp2.c
deleted file mode 100755
index 5ebc588..0000000
--- a/c/ecp2.c
+++ /dev/null
@@ -1,666 +0,0 @@
-/*
-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.
-*/
-
-/* AMCL Weierstrass elliptic curve functions over FP2 */
-/* SU=m, m is Stack Usage */
-
-#include "amcl.h"
-
-int ECP2_isinf(ECP2 *P)
-{
-    return P->inf;
-}
-
-/* Set P=Q */
-/* SU= 16 */
-void ECP2_copy(ECP2 *P,ECP2 *Q)
-{
-	P->inf=Q->inf;
-	FP2_copy(&(P->x),&(Q->x));
-	FP2_copy(&(P->y),&(Q->y));
-	FP2_copy(&(P->z),&(Q->z));
-}
-
-/* set P to Infinity */
-/* SU= 8 */
-void ECP2_inf(ECP2 *P)
-{
-	P->inf=1;
-	FP2_zero(&(P->x)); FP2_zero(&(P->y)); FP2_zero(&(P->z));
-}
-
-/* Conditional move Q to P dependant on d */
-static void ECP2_cmove(ECP2 *P,ECP2 *Q,int d)
-{
-	FP2_cmove(&(P->x),&(Q->x),d);
-	FP2_cmove(&(P->y),&(Q->y),d);
-	FP2_cmove(&(P->z),&(Q->z),d);
-	d=~(d-1);
-	P->inf^=(P->inf^Q->inf)&d;
-}
-
-/* return 1 if b==c, no branching */
-static int teq(sign32 b,sign32 c)
-{
-	sign32 x=b^c;
-	x-=1;  // if x=0, x now -1
-	return (int)((x>>31)&1);
-}
-
-/* Constant time select from pre-computed table */
-static void ECP2_select(ECP2 *P,ECP2 W[],sign32 b)
-{
-  ECP2 MP;
-  sign32 m=b>>31;
-  sign32 babs=(b^m)-m;
-
-  babs=(babs-1)/2;
-
-  ECP2_cmove(P,&W[0],teq(babs,0));  // conditional move
-  ECP2_cmove(P,&W[1],teq(babs,1));
-  ECP2_cmove(P,&W[2],teq(babs,2));
-  ECP2_cmove(P,&W[3],teq(babs,3));
-  ECP2_cmove(P,&W[4],teq(babs,4));
-  ECP2_cmove(P,&W[5],teq(babs,5));
-  ECP2_cmove(P,&W[6],teq(babs,6));
-  ECP2_cmove(P,&W[7],teq(babs,7));
-
-  ECP2_copy(&MP,P);
-  ECP2_neg(&MP);  // minus P
-  ECP2_cmove(P,&MP,(int)(m&1));
-}
-
-/* return 1 if P==Q, else 0 */
-/* SU= 312 */
-int ECP2_equals(ECP2 *P,ECP2 *Q)
-{
-	FP2 pz2,qz2,a,b;
-	if (P->inf && Q->inf) return 1;
-	if (P->inf || Q->inf) return 0;
-
-	FP2_sqr(&pz2,&(P->z)); FP2_sqr(&qz2,&(Q->z));
-
-	FP2_mul(&a,&(P->x),&qz2);
-	FP2_mul(&b,&(Q->x),&pz2);
-	if (!FP2_equals(&a,&b)) return 0;
-
-	FP2_mul(&a,&(P->y),&qz2);
-	FP2_mul(&a,&a,&(Q->z));
-	FP2_mul(&b,&(Q->y),&pz2);
-	FP2_mul(&b,&b,&(P->z));
-	if (!FP2_equals(&a,&b)) return 0;
-	return 1;
-}
-
-/* Make P affine (so z=1) */
-/* SU= 232 */
-void ECP2_affine(ECP2 *P)
-{
-	FP2 one,iz,izn;
-	if (P->inf) return;
-
-	FP2_one(&one);
-	if (FP2_isunity(&(P->z)))
-	{
-		FP2_reduce(&(P->x));
-		FP2_reduce(&(P->y));
-		return;
-	}
-
-	FP2_inv(&iz,&(P->z));
-	FP2_sqr(&izn,&iz);
-	FP2_mul(&(P->x),&(P->x),&izn);
-	FP2_mul(&izn,&izn,&iz);
-	FP2_mul(&(P->y),&(P->y),&izn);
-
-	FP2_reduce(&(P->x));
-	FP2_reduce(&(P->y));
-	FP2_copy(&(P->z),&one);
-}
-
-/* extract x, y from point P */
-/* SU= 16 */
-int ECP2_get(FP2 *x,FP2 *y,ECP2 *P)
-{
-	if (P->inf) return -1;
-	ECP2_affine(P);
-	FP2_copy(y,&(P->y));
-	FP2_copy(x,&(P->x));
-	return 0;
-}
-
-/* SU= 152 */
-/* Output point P */
-void ECP2_output(ECP2 *P)
-{
-	FP2 x,y;
-	if (P->inf)
-	{
-		printf("Infinity\n");
-		return;
-	}
-	ECP2_get(&x,&y,P);
-	printf("(");FP2_output(&x);printf(",");FP2_output(&y);printf(")\n");
-}
-
-/* SU= 232 */
-void ECP2_outputxyz(ECP2 *P)
-{
-	FP2 x,y,z;
-	ECP2 Q;
-	if (P->inf)
-	{
-		printf("Infinity\n");
-		return;
-	}
-	ECP2_copy(&Q,P);
-	printf("(");FP2_output(&(Q.x));printf(",");FP2_output(&(Q.y));printf(",");FP2_output(&(Q.z)); printf(")\n");
-}
-
-/* SU= 168 */
-/* Convert Q to octet string */
-void ECP2_toOctet(octet *W,ECP2 *Q)
-{
-	FP2 qx,qy;
-	ECP2_get(&qx,&qy,Q);
-	FP_redc(qx.a); FP_redc(qx.b); FP_redc(qy.a); FP_redc(qy.b);
-	W->len=4*MODBYTES;
-
-	BIG_toBytes(&(W->val[0]),qx.a);
-	BIG_toBytes(&(W->val[MODBYTES]),qx.b);
-	BIG_toBytes(&(W->val[2*MODBYTES]),qy.a);
-	BIG_toBytes(&(W->val[3*MODBYTES]),qy.b);
-}
-
-/* SU= 176 */
-/* restore Q from octet string */
-int ECP2_fromOctet(ECP2 *Q,octet *W)
-{
-	FP2 qx,qy;
-    BIG_fromBytes(qx.a,&(W->val[0]));
-    BIG_fromBytes(qx.b,&(W->val[MODBYTES]));
-    BIG_fromBytes(qy.a,&(W->val[2*MODBYTES]));
-    BIG_fromBytes(qy.b,&(W->val[3*MODBYTES]));
-	FP_nres(qx.a); FP_nres(qx.b); FP_nres(qy.a); FP_nres(qy.b);
-
-	if (ECP2_set(Q,&qx,&qy)) return 1;
-	return 0;
-}
-
-/* SU= 128 */
-/* Calculate RHS of twisted curve equation x^3+B/i */
-void ECP2_rhs(FP2 *rhs,FP2 *x)
-{ /* calculate RHS of elliptic curve equation */
-	FP2 t;
-	BIG b;
-	FP2_sqr(&t,x);
-
-	FP2_mul(rhs,&t,x);
-
-/* Assuming CURVE_A=0 */
-
-	BIG_rcopy(b,CURVE_B);
-
-	FP2_from_BIG(&t,b);
-
-	FP2_div_ip(&t);   /* IMPORTANT - here we use the SEXTIC twist of the curve */
-
-	FP2_add(rhs,&t,rhs);
-	FP2_reduce(rhs);
-}
-
-
-/* Set P=(x,y). Return 1 if (x,y) is on the curve, else return 0*/
-/* SU= 232 */
-int ECP2_set(ECP2 *P,FP2 *x,FP2 *y)
-{
-	FP2 one,rhs,y2;
-	FP2_copy(&y2,y);
-
-	FP2_sqr(&y2,&y2);
-	ECP2_rhs(&rhs,x);
-
-	if (!FP2_equals(&y2,&rhs))
-	{
-
-		P->inf=1;
-		return 0;
-	}
-
-	P->inf=0;
-	FP2_copy(&(P->x),x);
-	FP2_copy(&(P->y),y);
-
-	FP2_one(&one);
-	FP2_copy(&(P->z),&one);
-	return 1;
-}
-
-/* Set P=(x,y). Return 1 if (x,.) is on the curve, else return 0 */
-/* SU= 232 */
-int ECP2_setx(ECP2 *P,FP2 *x)
-{
-	FP2 y;
-	ECP2_rhs(&y,x);
-
-	if (!FP2_sqrt(&y,&y))
-	{
-		P->inf=1;
-		return 0;
-	}
-
-	P->inf=0;
-	FP2_copy(&(P->x),x);
-	FP2_copy(&(P->y),&y);
-	FP2_one(&(P->z));
-	return 1;
-}
-
-/* Set P=-P */
-/* SU= 8 */
-void ECP2_neg(ECP2 *P)
-{
-	FP2_neg(&(P->y),&(P->y));
-	FP2_norm(&(P->y));
-}
-
-/* R+=R */
-/* return -1 for Infinity, 0 for addition, 1 for doubling */
-/* SU= 448 */
-int ECP2_dbl(ECP2 *P)
-{
-	FP2 w1,w7,w8,w2,w3;
-	if (P->inf) return -1;
-
-	if (FP2_iszilch(&(P->y)))
-	{
-		P->inf=1;
-		return -1;
-	}
-
-/* Assuming A=0 */
-	FP2_sqr(&w1,&(P->x));
-	FP2_imul(&w8,&w1,3);
-
-	FP2_sqr(&w2,&(P->y));
-	FP2_mul(&w3,&(P->x),&w2);
-	FP2_imul(&w3,&w3,4);
-
-	FP2_neg(&w1,&w3);
-#if CHUNK<64
-	FP2_norm(&w1);
-#endif
-	FP2_sqr(&(P->x),&w8);
-	FP2_add(&(P->x),&(P->x),&w1);
-	FP2_add(&(P->x),&(P->x),&w1);
-
-	FP2_norm(&(P->x));
-
-	if (FP2_isunity(&(P->z))) FP2_copy(&(P->z),&(P->y));
-	else FP2_mul(&(P->z),&(P->z),&(P->y));
-	FP2_add(&(P->z),&(P->z),&(P->z));
-
-	FP2_add(&w7,&w2,&w2);
-	FP2_sqr(&w2,&w7);
-
-	FP2_add(&w2,&w2,&w2);
-	FP2_sub(&w3,&w3,&(P->x));
-
-	FP2_mul(&(P->y),&w8,&w3);
-//#if CHUNK<64
-//	FP2_norm(&w2);
-//#endif
-	FP2_sub(&(P->y),&(P->y),&w2);
-
-
-	FP2_norm(&(P->y));
-	FP2_norm(&(P->z));
-
-	return 1;
-}
-
-/* Set P+=Q */
-/* SU= 400 */
-int ECP2_add(ECP2 *P,ECP2 *Q)
-{
-	int aff;
-	FP2 B,D,E,C,A;
-	if (Q->inf) return 0;
-	if (P->inf)
-	{
-		ECP2_copy(P,Q);
-		return 0;
-	}
-
-	aff=1;
-	if (!FP2_isunity(&(Q->z))) aff=0;
-
-	if (!aff)
-	{
-		FP2_sqr(&A,&(Q->z));
-		FP2_mul(&C,&A,&(Q->z));
-
-		FP2_sqr(&B,&(P->z));
-		FP2_mul(&D,&B,&(P->z));
-
-		FP2_mul(&A,&(P->x),&A);
-		FP2_mul(&C,&(P->y),&C);
-	}
-	else
-	{
-		FP2_copy(&A,&(P->x));
-		FP2_copy(&C,&(P->y));
-
-		FP2_sqr(&B,&(P->z));
-		FP2_mul(&D,&B,&(P->z));
-	}
-
-	FP2_mul(&B,&(Q->x),&B); FP2_sub(&B,&B,&A); /* B=Qx.z^2-x.Qz^2 */
-	FP2_mul(&D,&(Q->y),&D); FP2_sub(&D,&D,&C); /* D=Qy.z^3-y.Qz^3 */
-
-	if (FP2_iszilch(&B))
-	{
-		if (FP2_iszilch(&D))
-		{
-			ECP2_dbl(P);
-			return 1;
-		}
-		else
-		{
-			ECP2_inf(P);
-			return -1;
-		}
-	}
-	if (!aff) FP2_mul(&(P->z),&(P->z),&(Q->z));
-	FP2_mul(&(P->z),&(P->z),&B);
-
-	FP2_sqr(&E,&B);
-	FP2_mul(&B,&B,&E);
-	FP2_mul(&A,&A,&E);
-
-	FP2_add(&E,&A,&A);
-	FP2_add(&E,&E,&B);
-
-	FP2_sqr(&(P->x),&D);
-	FP2_sub(&(P->x),&(P->x),&E);
-
-	FP2_sub(&A,&A,&(P->x));
-	FP2_mul(&(P->y),&A,&D);
-	FP2_mul(&C,&C,&B);
-	FP2_sub(&(P->y),&(P->y),&C);
-
-	FP2_norm(&(P->x));
-	FP2_norm(&(P->y));
-	FP2_norm(&(P->z));
-
-	return 0;
-}
-
-/* Set P-=Q */
-/* SU= 16 */
-void ECP2_sub(ECP2 *P,ECP2 *Q)
-{
-	ECP2_neg(Q);
-	ECP2_add(P,Q);
-	ECP2_neg(Q);
-}
-
-/* normalises m-array of ECP2 points. Requires work vector of m FP2s */
-/* SU= 200 */
-static void ECP2_multiaffine(int m,ECP2 *P,FP2 *work)
-{
-	int i;
-	FP2 t1,t2;
-
-	FP2_one(&work[0]);
-	FP2_copy(&work[1],&(P[0].z));
-	for (i=2;i<m;i++)
-		FP2_mul(&work[i],&work[i-1],&(P[i-1].z));
-	FP2_mul(&t1,&work[m-1],&(P[m-1].z));
-
-	FP2_inv(&t1,&t1);
-
-	FP2_copy(&t2,&(P[m-1].z));
-	FP2_mul(&work[m-1],&work[m-1],&t1);
-
-	for (i=m-2;;i--)
-    {
-		if (i==0)
-		{
-			FP2_mul(&work[0],&t1,&t2);
-			break;
-		}
-		FP2_mul(&work[i],&work[i],&t2);
-		FP2_mul(&work[i],&work[i],&t1);
-		FP2_mul(&t2,&(P[i].z),&t2);
-    }
-/* now work[] contains inverses of all Z coordinates */
-
-	for (i=0;i<m;i++)
-	{
-		FP2_one(&(P[i].z));
-		FP2_sqr(&t1,&work[i]);
-		FP2_mul(&(P[i].x),&(P[i].x),&t1);
-		FP2_mul(&t1,&work[i],&t1);
-		FP2_mul(&(P[i].y),&(P[i].y),&t1);
-    }
-}
-
-/* P*=e */
-/* SU= 280 */
-void ECP2_mul(ECP2 *P,BIG e)
-{
-/* fixed size windows */
-	int i,b,nb,m,s,ns;
-	BIG mt,t,r;
-	ECP2 Q,W[8],C;
-	sign8 w[1+(NLEN*BASEBITS+3)/4];
-	FP2 work[8];
-
-	if (ECP2_isinf(P)) return;
-	ECP2_affine(P);
-
-
-/* precompute table */
-
-	ECP2_copy(&Q,P);
-	ECP2_dbl(&Q);
-	ECP2_copy(&W[0],P);
-
-	for (i=1;i<8;i++)
-	{
-		ECP2_copy(&W[i],&W[i-1]);
-		ECP2_add(&W[i],&Q);
-	}
-
-/* convert the table to affine */
-
-	ECP2_multiaffine(8,W,work);
-
-/* make exponent odd - add 2P if even, P if odd */
-	BIG_copy(t,e);
-	s=BIG_parity(t);
-	BIG_inc(t,1); BIG_norm(t); ns=BIG_parity(t); BIG_copy(mt,t); BIG_inc(mt,1); BIG_norm(mt);
-	BIG_cmove(t,mt,s);
-	ECP2_cmove(&Q,P,ns);
-	ECP2_copy(&C,&Q);
-
-	nb=1+(BIG_nbits(t)+3)/4;
-
-/* convert exponent to signed 4-bit window */
-	for (i=0;i<nb;i++)
-	{
-		w[i]=BIG_lastbits(t,5)-16;
-		BIG_dec(t,w[i]); BIG_norm(t);
-		BIG_fshr(t,4);
-	}
-	w[nb]=BIG_lastbits(t,5);
-
-	ECP2_copy(P,&W[(w[nb]-1)/2]);
-	for (i=nb-1;i>=0;i--)
-	{
-		ECP2_select(&Q,W,w[i]);
-		ECP2_dbl(P);
-		ECP2_dbl(P);
-		ECP2_dbl(P);
-		ECP2_dbl(P);
-		ECP2_add(P,&Q);
-	}
-	ECP2_sub(P,&C); /* apply correction */
-	ECP2_affine(P);
-}
-
-/* Calculates q.P using Frobenius constant X */
-/* SU= 96 */
-void ECP2_frob(ECP2 *P,FP2 *X)
-{
-	FP2 X2;
-	if (P->inf) return;
-	FP2_sqr(&X2,X);
-	FP2_conj(&(P->x),&(P->x));
-	FP2_conj(&(P->y),&(P->y));
-	FP2_conj(&(P->z),&(P->z));
-	FP2_reduce(&(P->z));
-
-	FP2_mul(&(P->x),&X2,&(P->x));
-	FP2_mul(&(P->y),&X2,&(P->y));
-	FP2_mul(&(P->y),X,&(P->y));
-}
-
-void ECP2_mul4(ECP2 *P,ECP2 Q[4],BIG u[4])
-{
-	int i,j,a[4],nb;
-	ECP2 W[8],T,C;
-	BIG mt,t[4];
-	FP2 work[8];
-	sign8 w[NLEN*BASEBITS+1];
-
-	for (i=0;i<4;i++)
-	{
-		BIG_copy(t[i],u[i]);
-		ECP2_affine(&Q[i]);
-	}
-
-/* precompute table */
-
-	ECP2_copy(&W[0],&Q[0]); ECP2_sub(&W[0],&Q[1]);  /* P-Q */
-	ECP2_copy(&W[1],&W[0]);
-	ECP2_copy(&W[2],&W[0]);
-	ECP2_copy(&W[3],&W[0]);
-	ECP2_copy(&W[4],&Q[0]); ECP2_add(&W[4],&Q[1]);  /* P+Q */
-	ECP2_copy(&W[5],&W[4]);
-	ECP2_copy(&W[6],&W[4]);
-	ECP2_copy(&W[7],&W[4]);
-
-	ECP2_copy(&T,&Q[2]); ECP2_sub(&T,&Q[3]);       /* R-S */
-	ECP2_sub(&W[1],&T);
-	ECP2_add(&W[2],&T);
-	ECP2_sub(&W[5],&T);
-	ECP2_add(&W[6],&T);
-	ECP2_copy(&T,&Q[2]); ECP2_add(&T,&Q[3]);      /* R+S */
-	ECP2_sub(&W[0],&T);
-	ECP2_add(&W[3],&T);
-	ECP2_sub(&W[4],&T);
-	ECP2_add(&W[7],&T);
-
-	ECP2_multiaffine(8,W,work);
-
-/* if multiplier is even add 1 to multiplier, and add P to correction */
-	ECP2_inf(&C);
-
-	BIG_zero(mt);
-	for (i=0;i<4;i++)
-	{
-		if (BIG_parity(t[i])==0)
-		{
-			BIG_inc(t[i],1); BIG_norm(t[i]);
-			ECP2_add(&C,&Q[i]);
-		}
-		BIG_add(mt,mt,t[i]); BIG_norm(mt);
-	}
-
-	nb=1+BIG_nbits(mt);
-
-/* convert exponent to signed 1-bit window */
-	for (j=0;j<nb;j++)
-	{
-		for (i=0;i<4;i++)
-		{
-			a[i]=BIG_lastbits(t[i],2)-2;
-			BIG_dec(t[i],a[i]); BIG_norm(t[i]);
-			BIG_fshr(t[i],1);
-		}
-		w[j]=8*a[0]+4*a[1]+2*a[2]+a[3];
-	}
-	w[nb]=8*BIG_lastbits(t[0],2)+4*BIG_lastbits(t[1],2)+2*BIG_lastbits(t[2],2)+BIG_lastbits(t[3],2);
-
-	ECP2_copy(P,&W[(w[nb]-1)/2]);
-	for (i=nb-1;i>=0;i--)
-	{
-		ECP2_select(&T,W,w[i]);
-		ECP2_dbl(P);
-		ECP2_add(P,&T);
-	}
-	ECP2_sub(P,&C); /* apply correction */
-
-	ECP2_affine(P);
-}
-
-/*
-
-int main()
-{
-	int i;
-	ECP2 G,P;
-	ECP2 *W;
-	FP2 x,y,w,z,f;
-	BIG r,xa,xb,ya,yb;
-
-	BIG_rcopy(xa,CURVE_Pxa);
-	BIG_rcopy(xb,CURVE_Pxb);
-	BIG_rcopy(ya,CURVE_Pya);
-	BIG_rcopy(yb,CURVE_Pyb);
-
-	FP2_from_BIGs(&x,xa,xb);
-	FP2_from_BIGs(&y,ya,yb);
-	ECP2_set(&G,&x,&y);
-	if (G.inf) printf("Failed to set - point not on curve\n");
-	else printf("set success\n");
-
-	ECP2_output(&G);
-
-//	BIG_copy(r,CURVE_Order);
-	BIG_rcopy(r,Modulus);
-
-	ECP2_copy(&P,&G);
-
-	ECP2_mul(&P,r);
-
-	ECP2_output(&P);
-
-	FP2_gfc(&f,12);
-
-	ECP2_frob(&G,&f);
-
-	ECP2_output(&G);
-
-	return 0;
-}
-
-*/
diff --git a/c/ff.c b/c/ff.c
deleted file mode 100755
index 684a8f3..0000000
--- a/c/ff.c
+++ /dev/null
@@ -1,1050 +0,0 @@
-/*
-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.
-*/
-
-/* AMCL basic functions for Large Finite Field support */
-
-#include "amcl.h"
-
-#define P_MBITS MODBYTES*8
-#define P_MB (P_MBITS%BASEBITS)
-#define P_OMASK ((chunk)(-1)<<(P_MBITS%BASEBITS))
-#define P_EXCESS(a) ((a[NLEN-1]&P_OMASK)>>(P_MB))
-#define P_FEXCESS ((chunk)1<<(BASEBITS*NLEN-P_MBITS))
-#define P_TBITS (P_MBITS%BASEBITS)
-
-/* set x = x mod 2^m */
-static void BIG_mod2m(BIG x,int m)
-{
-	int i,wd,bt;
-	chunk msk;
-//	if (m>=MODBITS) return;
-	wd=m/BASEBITS;
-	bt=m%BASEBITS;
-	msk=((chunk)1<<bt)-1;
-	x[wd]&=msk;
-	for (i=wd+1;i<NLEN;i++) x[i]=0;
-}
-
-/* Arazi and Qi inversion mod 256 */
-static int invmod256(int a)
-{
-	int i,m,U,t1,t2,b,c;
-	t1=0;
-	c=(a>>1)&1;
-	t1+=c;
-	t1&=1;
-	t1=2-t1;
-	t1<<=1;
-	U=t1+1;
-
-// i=2
-	b=a&3;
-	t1=U*b; t1>>=2;
-	c=(a>>2)&3;
-	t2=(U*c)&3;
-	t1+=t2;
-	t1*=U; t1&=3;
-	t1=4-t1;
-	t1<<=2;
-	U+=t1;
-
-// i=4
-	b=a&15;
-	t1=U*b; t1>>=4;
-	c=(a>>4)&15;
-	t2=(U*c)&15;
-	t1+=t2;
-	t1*=U; t1&=15;
-	t1=16-t1;
-	t1<<=4;
-	U+=t1;
-
-	return U;
-}
-
-/* a=1/a mod 2^256. This is very fast! */
-void BIG_invmod2m(BIG a)
-{
-	int i;
-	BIG U,t1,b,c;
-	BIG_zero(U);
-	BIG_inc(U,invmod256(BIG_lastbits(a,8)));
-
-	for (i=8;i<256;i<<=1)
-	{
-		BIG_copy(b,a); BIG_mod2m(b,i);   // bottom i bits of a
-		BIG_smul(t1,U,b); BIG_shr(t1,i); // top i bits of U*b
-		BIG_copy(c,a); BIG_shr(c,i); BIG_mod2m(c,i); // top i bits of a
-		BIG_smul(b,U,c); BIG_mod2m(b,i);  // bottom i bits of U*c
-		BIG_add(t1,t1,b);
-		BIG_smul(b,t1,U); BIG_copy(t1,b);  // (t1+b)*U
-
-		BIG_mod2m(t1,i);				// bottom i bits of (t1+b)*U
-
-		BIG_one(b); BIG_shl(b,i); BIG_sub(t1,b,t1); BIG_norm(t1);
-		BIG_shl(t1,i);
-		BIG_add(U,U,t1);
-	}
-	BIG_copy(a,U);
-}
-
-/*
-void FF_rcopy(BIG x[],const BIG y[],int n)
-{
-	int i;
-	for (i=0;i<n;i++)
-		BIG_rcopy(x[i],y[i]);
-}
-*/
-
-/* x=y */
-void FF_copy(BIG x[],BIG y[],int n)
-{
-	int i;
-	for (i=0;i<n;i++)
-		BIG_copy(x[i],y[i]);
-}
-
-/* x=y<<n */
-static void FF_dsucopy(BIG x[],BIG y[],int n)
-{
-	int i;
-	for (i=0;i<n;i++)
-	{
-		BIG_copy(x[n+i],y[i]);
-		BIG_zero(x[i]);
-	}
-}
-
-/* x=y */
-static void FF_dscopy(BIG x[],BIG y[],int n)
-{
-	int i;
-	for (i=0;i<n;i++)
-	{
-		BIG_copy(x[i],y[i]);
-		BIG_zero(x[n+i]);
-	}
-}
-
-/* x=y>>n */
-static void FF_sducopy(BIG x[],BIG y[],int n)
-{
-	int i;
-	for (i=0;i<n;i++)
-		BIG_copy(x[i],y[n+i]);
-}
-
-/* set to zero */
-void FF_zero(BIG x[],int n)
-{
-	int i;
-	for (i=0;i<n;i++)
-		BIG_zero(x[i]);
-}
-
-/* test equals 0 */
-int FF_iszilch(BIG x[],int n)
-{
-	int i;
-	for (i=0;i<n;i++)
-		if (!BIG_iszilch(x[i])) return 0;
-	return 1;
-}
-
-/* shift right by 256-bit words */
-static void FF_shrw(BIG a[],int n)
-{
-	int i;
-	for (i=0;i<n;i++) {BIG_copy(a[i],a[i+n]);BIG_zero(a[i+n]);}
-}
-
-/* shift left by 256-bit words */
-static void FF_shlw(BIG a[],int n)
-{
-	int i;
-	for (i=0;i<n;i++) {BIG_copy(a[i+n],a[i]); BIG_zero(a[i]);}
-}
-
-/* extract last bit */
-int FF_parity(BIG x[])
-{
-	return BIG_parity(x[0]);
-}
-
-/* extract last m bits */
-int FF_lastbits(BIG x[],int m)
-{
-	return BIG_lastbits(x[0],m);
-}
-
-/* x=1 */
-void FF_one(BIG x[],int n)
-{
-	int i;
-	BIG_one(x[0]);
-	for (i=1;i<n;i++)
-		BIG_zero(x[i]);
-}
-
-/* x=m, where m is 32-bit int */
-void FF_init(BIG x[],sign32 m,int n)
-{
-	int i;
-	BIG_zero(x[0]);
-#if CHUNK<64
-	x[0][0]=(chunk)(m&MASK);
-	x[0][1]=(chunk)(m>>BASEBITS);
-#else
-	x[0][0]=(chunk)m;
-#endif
-	for (i=1;i<n;i++)
-		BIG_zero(x[i]);
-}
-
-/* compare x and y - must be normalised */
-int FF_comp(BIG x[],BIG y[],int n)
-{
-	int i,j;
-	for (i=n-1;i>=0;i--)
-	{
-		j=BIG_comp(x[i],y[i]);
-		if (j!=0) return j;
-	}
-	return 0;
-}
-
-/* recursive add */
-static void FF_radd(BIG z[],int zp,BIG x[],int xp,BIG y[],int yp,int n)
-{
-	int i;
-	for (i=0;i<n;i++)
-		BIG_add(z[zp+i],x[xp+i],y[yp+i]);
-}
-
-/* recursive inc */
-static void FF_rinc(BIG z[],int zp,BIG y[],int yp,int n)
-{
-	int i;
-	for (i=0;i<n;i++)
-		BIG_add(z[zp+i],z[zp+i],y[yp+i]);
-}
-
-/* recursive sub */
-static void FF_rsub(BIG z[],int zp,BIG x[],int xp,BIG y[],int yp,int n)
-{
-	int i;
-	for (i=0;i<n;i++)
-		BIG_sub(z[zp+i],x[xp+i],y[yp+i]);
-}
-
-/* recursive dec */
-static void FF_rdec(BIG z[],int zp,BIG y[],int yp,int n)
-{
-	int i;
-	for (i=0;i<n;i++)
-		BIG_sub(z[zp+i],z[zp+i],y[yp+i]);
-}
-
-/* simple add */
-void FF_add(BIG z[],BIG x[],BIG y[],int n)
-{
-	int i;
-	for (i=0;i<n;i++)
-		BIG_add(z[i],x[i],y[i]);
-}
-
-/* simple sub */
-void FF_sub(BIG z[],BIG x[],BIG y[],int n)
-{
-	int i;
-	for (i=0;i<n;i++)
-		BIG_sub(z[i],x[i],y[i]);
-}
-
-/* increment/decrement by a small integer */
-void FF_inc(BIG x[],int m,int n)
-{
-	BIG_inc(x[0],m);
-	FF_norm(x,n);
-}
-
-void FF_dec(BIG x[],int m,int n)
-{
-	BIG_dec(x[0],m);
-	FF_norm(x,n);
-}
-
-/* normalise - but hold any overflow in top part unless n<0 */
-static void FF_rnorm(BIG z[],int zp,int n)
-{
-	int i,trunc=0;
-	chunk carry;
-	if (n<0)
-	{ /* -v n signals to do truncation */
-		n=-n;
-		trunc=1;
-	}
-	for (i=0;i<n-1;i++)
-	{
-		carry=BIG_norm(z[zp+i]);
-		z[zp+i][NLEN-1]^=carry<<P_TBITS; /* remove it */
-		z[zp+i+1][0]+=carry;
-	}
-	carry=BIG_norm(z[zp+n-1]);
-	if (trunc) z[zp+n-1][NLEN-1]^=carry<<P_TBITS;
-}
-
-void FF_norm(BIG z[],int n)
-{
-	FF_rnorm(z,0,n);
-}
-
-/* shift left by one bit */
-void FF_shl(BIG x[],int n)
-{
-	int i;
-	chunk carry,delay_carry=0;
-	for (i=0;i<n-1;i++)
-	{
-		carry=BIG_fshl(x[i],1);
-		x[i][0]|=delay_carry;
-		x[i][NLEN-1]^=carry<<P_TBITS;
-		delay_carry=carry;
-	}
-	BIG_fshl(x[n-1],1);
-	x[n-1][0]|=delay_carry;
-}
-
-/* shift right by one bit */
-void FF_shr(BIG x[],int n)
-{
-	int i;
-	chunk carry;
-	for (i=n-1;i>0;i--)
-	{
-		carry=BIG_fshr(x[i],1);
-		x[i-1][NLEN-1]|=carry<<P_TBITS;
-	}
-	BIG_fshr(x[0],1);
-}
-
-void FF_output(BIG x[],int n)
-{
-	int i;
-	FF_norm(x,n);
-	for (i=n-1;i>=0;i--)
-	{
-		BIG_output(x[i]);// printf(" ");
-	}
-}
-
-/* Convert FFs to/from octet strings */
-void FF_toOctet(octet *w,BIG x[],int n)
-{
-	int i;
-	w->len=n*MODBYTES;
-	for (i=0;i<n;i++)
-	{
-		BIG_toBytes(&(w->val[(n-i-1)*MODBYTES]),x[i]);
-	}
-}
-
-void FF_fromOctet(BIG x[],octet *w,int n)
-{
-	int i;
-	for (i=0;i<n;i++)
-	{
-		BIG_fromBytes(x[i],&(w->val[(n-i-1)*MODBYTES]));
-	}
-}
-
-/* in-place swapping using xor - side channel resistant */
-static void FF_cswap(BIG a[],BIG b[],int d,int n)
-{
-	int i;
-	for (i=0;i<n;i++)
-		BIG_cswap(a[i],b[i],d);
-	return;
-}
-
-/* z=x*y, t is workspace */
-static void FF_karmul(BIG z[],int zp,BIG x[],int xp,BIG y[],int yp,BIG t[],int tp,int n)
-{
-    int nd2;
-	if (n==1)
-	{
-		BIG_mul(t[tp],x[xp],y[yp]);
-		BIG_split(z[zp+1],z[zp],t[tp],256);
-		return;
-	}
-
-	nd2=n/2;
-	FF_radd(z,zp,x,xp,x,xp+nd2,nd2);
-#if CHUNK<64
-	FF_rnorm(z,zp,nd2);  /* needs this if recursion level too deep */
-#endif
-	FF_radd(z,zp+nd2,y,yp,y,yp+nd2,nd2);
-#if CHUNK<64
-	FF_rnorm(z,zp+nd2,nd2);
-#endif
-	FF_karmul(t,tp,z,zp,z,zp+nd2,t,tp+n,nd2);
-	FF_karmul(z,zp,x,xp,y,yp,t,tp+n,nd2);
-	FF_karmul(z,zp+n,x,xp+nd2,y,yp+nd2,t,tp+n,nd2);
-	FF_rdec(t,tp,z,zp,n);
-	FF_rdec(t,tp,z,zp+n,n);
-	FF_rinc(z,zp+nd2,t,tp,n);
-	FF_rnorm(z,zp,2*n);
-}
-
-static void FF_karsqr(BIG z[],int zp,BIG x[],int xp,BIG t[],int tp,int n)
-{
-	int nd2;
-	if (n==1)
-	{
-		BIG_sqr(t[tp],x[xp]);
-		BIG_split(z[zp+1],z[zp],t[tp],256);
-		return;
-	}
-	nd2=n/2;
-	FF_karsqr(z,zp,x,xp,t,tp+n,nd2);
-	FF_karsqr(z,zp+n,x,xp+nd2,t,tp+n,nd2);
-	FF_karmul(t,tp,x,xp,x,xp+nd2,t,tp+n,nd2);
-	FF_rinc(z,zp+nd2,t,tp,n);
-	FF_rinc(z,zp+nd2,t,tp,n);
-
-	FF_rnorm(z,zp+nd2,n);  /* was FF_rnorm(z,zp,2*n)  */
-}
-
-static void FF_karmul_lower(BIG z[],int zp,BIG x[],int xp,BIG y[],int yp,BIG t[],int tp,int n)
-{ /* Calculates Least Significant bottom half of x*y */
-    int nd2;
-    if (n==1)
-    { /* only calculate bottom half of product */
-	//	BIG_mul(d,x[xp],y[yp]);
-	//	BIG_split(z[zp],z[zp],d,256);
-		BIG_smul(z[zp],x[xp],y[yp]);
-        return;
-    }
-    nd2=n/2;
-
-	FF_karmul(z,zp,x,xp,y,yp,t,tp+n,nd2);
-	FF_karmul_lower(t,tp,x,xp+nd2,y,yp,t,tp+n,nd2);
-	FF_rinc(z,zp+nd2,t,tp,nd2);
-	FF_karmul_lower(t,tp,x,xp,y,yp+nd2,t,tp+n,nd2);
-	FF_rinc(z,zp+nd2,t,tp,nd2);
-	FF_rnorm(z,zp+nd2,-nd2);  /* truncate it */
-}
-
-static void FF_karmul_upper(BIG z[],BIG x[],BIG y[],BIG t[],int n)
-{ /* Calculates Most Significant upper half of x*y, given lower part */
-    int i,nd2;
-
-    nd2=n/2;
-	FF_radd(z,n,x,0,x,nd2,nd2);
-	FF_radd(z,n+nd2,y,0,y,nd2,nd2);
-
-	FF_karmul(t,0,z,n+nd2,z,n,t,n,nd2);  /* t = (a0+a1)(b0+b1) */
-	FF_karmul(z,n,x,nd2,y,nd2,t,n,nd2); /* z[n]= a1*b1 */
-									/* z[0-nd2]=l(a0b0) z[nd2-n]= h(a0b0)+l(t)-l(a0b0)-l(a1b1) */
-	FF_rdec(t,0,z,n,n);              /* t=t-a1b1  */
-	FF_rinc(z,nd2,z,0,nd2);   /* z[nd2-n]+=l(a0b0) = h(a0b0)+l(t)-l(a1b1)  */
-	FF_rdec(z,nd2,t,0,nd2);   /* z[nd2-n]=h(a0b0)+l(t)-l(a1b1)-l(t-a1b1)=h(a0b0) */
-	FF_rnorm(z,0,-n);					/* a0b0 now in z - truncate it */
-	FF_rdec(t,0,z,0,n);         /* (a0+a1)(b0+b1) - a0b0 */
-	FF_rinc(z,nd2,t,0,n);
-
-	FF_rnorm(z,nd2,n);
-}
-
-/* z=x*y */
-void FF_mul(BIG z[],BIG x[],BIG y[],int n)
-{
-#ifndef C99
-	BIG t[2*FFLEN];
-#else
-	BIG t[2*n];
-#endif
-	FF_karmul(z,0,x,0,y,0,t,0,n);
-}
-
-/* return low part of product */
-static void FF_lmul(BIG z[],BIG x[],BIG y[],int n)
-{
-#ifndef C99
-	BIG t[2*FFLEN];
-#else
-	BIG t[2*n];
-#endif
-	FF_karmul_lower(z,0,x,0,y,0,t,0,n);
-}
-
-/* Set b=b mod c */
-void FF_mod(BIG b[],BIG c[],int n)
-{
-	int k=0;
-
-	FF_norm(b,n);
-	if (FF_comp(b,c,n)<0)
-		return;
-	do
-	{
-		FF_shl(c,n);
-		k++;
-	} while (FF_comp(b,c,n)>=0);
-
-	while (k>0)
-	{
-		FF_shr(c,n);
-		if (FF_comp(b,c,n)>=0)
-		{
-			FF_sub(b,b,c,n);
-			FF_norm(b,n);
-		}
-		k--;
-	}
-}
-
-/* z=x^2 */
-void FF_sqr(BIG z[],BIG x[],int n)
-{
-#ifndef C99
-	BIG t[2*FFLEN];
-#else
-	BIG t[2*n];
-#endif
-	FF_karsqr(z,0,x,0,t,0,n);
-}
-
-/* r=t mod modulus, N is modulus, ND is Montgomery Constant */
-static void FF_reduce(BIG r[],BIG T[],BIG N[],BIG ND[],int n)
-{ /* fast karatsuba Montgomery reduction */
-#ifndef C99
-	BIG t[2*FFLEN];
-	BIG m[FFLEN];
-#else
-	BIG t[2*n];
-	BIG m[n];
-#endif
-	FF_sducopy(r,T,n);  /* keep top half of T */
-	FF_karmul_lower(m,0,T,0,ND,0,t,0,n);  /* m=T.(1/N) mod R */
-
-	FF_karmul_upper(T,N,m,t,n);  /* T=mN */
-	FF_sducopy(m,T,n);
-
-	FF_add(r,r,N,n);
-	FF_sub(r,r,m,n);
-	FF_norm(r,n);
-}
-
-
-/* Set r=a mod b */
-/* a is of length - 2*n */
-/* r,b is of length - n */
-void FF_dmod(BIG r[],BIG a[],BIG b[],int n)
-{
-	int len,k;
-#ifndef C99
-	BIG m[2*FFLEN];
-	BIG x[2*FFLEN];
-#else
-	BIG m[2*n];
-	BIG x[2*n];
-#endif
-	FF_copy(x,a,2*n);
-	FF_norm(x,2*n);
-	FF_dsucopy(m,b,n); k=256*n;
-
-	while (k>0)
-	{
-	//	len=2*n-((256*n-k)/256);  // reduce length as numbers get smaller?
-		FF_shr(m,2*n);
-
-		if (FF_comp(x,m,2*n)>=0)
-		{
-			FF_sub(x,x,m,2*n);
-			FF_norm(x,2*n);
-		}
-
-		k--;
-	}
-	FF_copy(r,x,n);
-	FF_mod(r,b,n);
-}
-
-/* Set r=1/a mod p. Binary method - a<p on entry */
-
-void FF_invmodp(BIG r[],BIG a[],BIG p[],int n)
-{
-#ifndef C99
-	BIG u[FFLEN],v[FFLEN],x1[FFLEN],x2[FFLEN],t[FFLEN],one[FFLEN];
-#else
-	BIG u[n],v[n],x1[n],x2[n],t[n],one[n];
-#endif
-	FF_copy(u,a,n);
-	FF_copy(v,p,n);
-	FF_one(one,n);
-	FF_copy(x1,one,n);
-	FF_zero(x2,n);
-
-// reduce n in here as well!
-	while (FF_comp(u,one,n)!=0 && FF_comp(v,one,n)!=0)
-	{
-		while (FF_parity(u)==0)
-		{
-			FF_shr(u,n);
-			if (FF_parity(x1)!=0)
-			{
-				FF_add(x1,p,x1,n);
-				FF_norm(x1,n);
-			}
-			FF_shr(x1,n);
-		}
-		while (FF_parity(v)==0)
-		{
-			FF_shr(v,n);
-			if (FF_parity(x2)!=0)
-			{
-				FF_add(x2,p,x2,n);
-				FF_norm(x2,n);
-			}
-			FF_shr(x2,n);
-		}
-		if (FF_comp(u,v,n)>=0)
-		{
-
-			FF_sub(u,u,v,n);
-			FF_norm(u,n);
-			if (FF_comp(x1,x2,n)>=0) FF_sub(x1,x1,x2,n);
-			else
-			{
-				FF_sub(t,p,x2,n);
-				FF_add(x1,x1,t,n);
-			}
-			FF_norm(x1,n);
-		}
-		else
-		{
-			FF_sub(v,v,u,n);
-			FF_norm(v,n);
-			if (FF_comp(x2,x1,n)>=0) FF_sub(x2,x2,x1,n);
-			else
-			{
-				FF_sub(t,p,x1,n);
-				FF_add(x2,x2,t,n);
-			}
-			FF_norm(x2,n);
-		}
-	}
-	if (FF_comp(u,one,n)==0)
-		FF_copy(r,x1,n);
-	else
-		FF_copy(r,x2,n);
-}
-
-/* nesidue mod m */
-static void FF_nres(BIG a[],BIG m[],int n)
-{
-#ifndef C99
-	BIG d[2*FFLEN];
-#else
-	BIG d[2*n];
-#endif
-
-	FF_dsucopy(d,a,n);
-	FF_dmod(a,d,m,n);
-}
-
-static void FF_redc(BIG a[],BIG m[],BIG ND[],int n)
-{
-#ifndef C99
-	BIG d[2*FFLEN];
-#else
-	BIG d[2*n];
-#endif
-	FF_mod(a,m,n);
-	FF_dscopy(d,a,n);
-	FF_reduce(a,d,m,ND,n);
-	FF_mod(a,m,n);
-}
-
-/* U=1/a mod 2^m - Arazi & Qi */
-static void FF_invmod2m(BIG U[],BIG a[],int n)
-{
-	int i;
-#ifndef C99
-	BIG t1[FFLEN],b[FFLEN],c[FFLEN];
-#else
-	BIG t1[n],b[n],c[n];
-#endif
-	FF_zero(U,n);
-	BIG_copy(U[0],a[0]);
-	BIG_invmod2m(U[0]);
-
-	for (i=1;i<n;i<<=1)
-	{
-		FF_copy(b,a,i);
-		FF_mul(t1,U,b,i); FF_shrw(t1,i); // top half to bottom half, top half=0
-
-		FF_copy(c,a,2*i); FF_shrw(c,i); // top half of c
-		FF_lmul(b,U,c,i); // should set top half of b=0
-		FF_add(t1,t1,b,i);  FF_norm(t1,2*i);
-		FF_lmul(b,t1,U,i); FF_copy(t1,b,i);
-		FF_one(b,i); FF_shlw(b,i);
-		FF_sub(t1,b,t1,2*i); FF_norm(t1,2*i);
-		FF_shlw(t1,i);
-		FF_add(U,U,t1,2*i);
-	}
-	FF_norm(U,n);
-}
-
-void FF_random(BIG x[],csprng *rng,int n)
-{
-	int i;
-	for (i=0;i<n;i++)
-	{
-		BIG_random(x[i],rng);
-	}
-/* make sure top bit is 1 */
-	while (BIG_nbits(x[n-1])<MODBYTES*8) BIG_random(x[n-1],rng);
-}
-
-/* generate random x mod p */
-void FF_randomnum(BIG x[],BIG p[],csprng *rng,int n)
-{
-	int i;
-#ifndef C99
-	BIG d[2*FFLEN];
-#else
-	BIG d[2*n];
-#endif
-	for (i=0;i<2*n;i++)
-	{
-		BIG_random(d[i],rng);
-	}
-	FF_dmod(x,d,p,n);
-}
-
-static void FF_modmul(BIG z[],BIG x[],BIG y[],BIG p[],BIG ND[],int n)
-{
-#ifndef C99
-	BIG d[2*FFLEN];
-#else
-	BIG d[2*n];
-#endif
-	chunk ex=P_EXCESS(x[n-1]);
-	chunk ey=P_EXCESS(y[n-1]);
-	if ((ex+1)*(ey+1)+1>=P_FEXCESS)
-	{
-#ifdef DEBUG_REDUCE
-		printf("Product too large - reducing it %d %d\n",ex,ey);
-#endif
-		FF_mod(x,p,n);
-	}
-	FF_mul(d,x,y,n);
-	FF_reduce(z,d,p,ND,n);
-}
-
-static void FF_modsqr(BIG z[],BIG x[],BIG p[],BIG ND[],int n)
-{
-#ifndef C99
-	BIG d[2*FFLEN];
-#else
-	BIG d[2*n];
-#endif
-	chunk ex=P_EXCESS(x[n-1]);
-	if ((ex+1)*(ex+1)+1>=P_FEXCESS)
-	{
-#ifdef DEBUG_REDUCE
-		printf("Product too large - reducing it %d\n",ex);
-#endif
-		FF_mod(x,p,n);
-	}
-	FF_sqr(d,x,n);
-	FF_reduce(z,d,p,ND,n);
-}
-
-/* r=x^e mod p using side-channel resistant Montgomery Ladder, for large e */
-void FF_skpow(BIG r[],BIG x[],BIG e[],BIG p[],int n)
-{
-	int i,b;
-#ifndef C99
-	BIG R0[FFLEN],R1[FFLEN],ND[FFLEN];
-#else
-	BIG R0[n],R1[n],ND[n];
-#endif
-	FF_invmod2m(ND,p,n);
-
-	FF_one(R0,n);
-	FF_copy(R1,x,n);
-	FF_nres(R0,p,n);
-	FF_nres(R1,p,n);
-
-	for (i=8*MODBYTES*n-1;i>=0;i--)
-	{
-		b=BIG_bit(e[i/256],i%256);
-		FF_modmul(r,R0,R1,p,ND,n);
-
-		FF_cswap(R0,R1,b,n);
-		FF_modsqr(R0,R0,p,ND,n);
-
-		FF_copy(R1,r,n);
-		FF_cswap(R0,R1,b,n);
-	}
-	FF_copy(r,R0,n);
-	FF_redc(r,p,ND,n);
-}
-
-/* r=x^e mod p using side-channel resistant Montgomery Ladder, for short e */
-void FF_skspow(BIG r[],BIG x[],BIG e,BIG p[],int n)
-{
-	int i,b;
-#ifndef C99
-	BIG R0[FFLEN],R1[FFLEN],ND[FFLEN];
-#else
-	BIG R0[n],R1[n],ND[n];
-#endif
-	FF_invmod2m(ND,p,n);
-	FF_one(R0,n);
-	FF_copy(R1,x,n);
-	FF_nres(R0,p,n);
-	FF_nres(R1,p,n);
-	for (i=8*MODBYTES-1;i>=0;i--)
-	{
-		b=BIG_bit(e,i);
-		FF_modmul(r,R0,R1,p,ND,n);
-		FF_cswap(R0,R1,b,n);
-		FF_modsqr(R0,R0,p,ND,n);
-		FF_copy(R1,r,n);
-		FF_cswap(R0,R1,b,n);
-	}
-	FF_copy(r,R0,n);
-	FF_redc(r,p,ND,n);
-}
-
-/* raise to an integer power - right-to-left method */
-void FF_power(BIG r[],BIG x[],int e,BIG p[],int n)
-{
-	int i,b,f=1;
-#ifndef C99
-	BIG w[FFLEN],ND[FFLEN];
-#else
-	BIG w[n],ND[n];
-#endif
-	FF_invmod2m(ND,p,n);
-
-	FF_copy(w,x,n);
-	FF_nres(w,p,n);
-
-	if (e==2)
-	{
-		FF_modsqr(r,w,p,ND,n);
-	}
-	else for (;;)
-	{
-		if (e%2==1)
-		{
-			if (f) FF_copy(r,w,n);
-			else FF_modmul(r,r,w,p,ND,n);
-			f=0;
-		}
-		e>>=1;
-		if (e==0) break;
-		FF_modsqr(w,w,p,ND,n);
-	}
-
-	FF_redc(r,p,ND,n);
-}
-
-/* r=x^e mod p, faster but not side channel resistant */
-void FF_pow(BIG r[],BIG x[],BIG e[],BIG p[],int n)
-{
-	int i,b;
-#ifndef C99
-	BIG w[FFLEN],ND[FFLEN];
-#else
-	BIG w[n],ND[n];
-#endif
-	FF_invmod2m(ND,p,n);
-	FF_copy(w,x,n);
-	FF_one(r,n);
-	FF_nres(r,p,n);
-	FF_nres(w,p,n);
-	for (i=8*MODBYTES*n-1;i>=0;i--)
-	{
-		FF_modsqr(r,r,p,ND,n);
-		b=BIG_bit(e[i/256],i%256);
-		if (b==1) FF_modmul(r,r,w,p,ND,n);
-	}
-	FF_redc(r,p,ND,n);
-}
-
-/* double exponentiation r=x^e.y^f mod p */
-void FF_pow2(BIG r[],BIG x[],BIG e,BIG y[],BIG f,BIG p[],int n)
-{
-	int i,eb,fb;
-#ifndef C99
-	BIG xn[FFLEN],yn[FFLEN],xy[FFLEN],ND[FFLEN];
-#else
-	BIG xn[n],yn[n],xy[n],ND[n];
-#endif
-	FF_invmod2m(ND,p,n);
-	FF_copy(xn,x,n);
-	FF_copy(yn,y,n);
-	FF_nres(xn,p,n);
-	FF_nres(yn,p,n);
-	FF_modmul(xy,xn,yn,p,ND,n);
-	FF_one(r,n);
-	FF_nres(r,p,n);
-
-	for (i=8*MODBYTES-1;i>=0;i--)
-	{
-		eb=BIG_bit(e,i);
-		fb=BIG_bit(f,i);
-		FF_modsqr(r,r,p,ND,n);
-		if (eb==1)
-		{
-			if (fb==1) FF_modmul(r,r,xy,p,ND,n);
-			else FF_modmul(r,r,xn,p,ND,n);
-		}
-		else
-		{
-			if (fb==1) FF_modmul(r,r,yn,p,ND,n);
-		}
-	}
-	FF_redc(r,p,ND,n);
-}
-
-static sign32 igcd(sign32 x,sign32 y)
-{ /* integer GCD, returns GCD of x and y */
-    sign32 r;
-    if (y==0) return x;
-    while ((r=x%y)!=0)
-        x=y,y=r;
-    return y;
-}
-
-/* quick and dirty check for common factor with s */
-int FF_cfactor(BIG w[],sign32 s,int n)
-{
-	int r;
-	sign32 g;
-#ifndef C99
-	BIG x[FFLEN],y[FFLEN];
-#else
-	BIG x[n],y[n];
-#endif
-	FF_init(y,s,n);
-	FF_copy(x,w,n);
-	FF_norm(x,n);
-
-//	if (FF_parity(x)==0) return 1;
-	do
-	{
-		FF_sub(x,x,y,n);
-		FF_norm(x,n);
-		while (!FF_iszilch(x,n) && FF_parity(x)==0) FF_shr(x,n);
-	}
-	while (FF_comp(x,y,n)>0);
-#if CHUNK<32
-	g=x[0][0]+((sign32)(x[0][1])<<BASEBITS);
-#else
-	g=(sign32)x[0][0];
-#endif
-	r=igcd(s,g);
-//printf("r= %d\n",r);
-	if (r>1) return 1;
-	return 0;
-}
-
-/* Miller-Rabin test for primality. Slow. */
-int FF_prime(BIG p[],csprng *rng,int n)
-{
-	int i,j,loop,s=0;
-#ifndef C99
-	BIG d[FFLEN],x[FFLEN],unity[FFLEN],nm1[FFLEN];
-#else
-	BIG d[n],x[n],unity[n],nm1[n];
-#endif
-	sign32 sf=4849845;/* 3*5*.. *19 */
-
-	FF_norm(p,n);
-	if (FF_cfactor(p,sf,n)) return 0;
-
-	FF_one(unity,n);
-	FF_sub(nm1,p,unity,n);
-	FF_norm(nm1,n);
-	FF_copy(d,nm1,n);
-
-	while (FF_parity(d)==0)
-	{
-		FF_shr(d,n);
-		s++;
-	}
-	if (s==0) return 0;
-
-	for (i=0;i<10;i++)
-	{
-		FF_randomnum(x,p,rng,n);
-		FF_pow(x,x,d,p,n);
-		if (FF_comp(x,unity,n)==0 || FF_comp(x,nm1,n)==0) continue;
-		loop=0;
-		for (j=1;j<s;j++)
-		{
-			FF_power(x,x,2,p,n);
-			if (FF_comp(x,unity,n)==0) return 0;
-			if (FF_comp(x,nm1,n)==0 ) {loop=1; break;}
-		}
-		if (loop) continue;
-		return 0;
-	}
-	return 1;
-}
-
-/*
-BIG P[4]= {{0x1670957,0x1568CD3C,0x2595E5,0xEED4F38,0x1FC9A971,0x14EF7E62,0xA503883,0x9E1E05E,0xBF59E3},{0x1844C908,0x1B44A798,0x3A0B1E7,0xD1B5B4E,0x1836046F,0x87E94F9,0x1D34C537,0xF7183B0,0x46D07},{0x17813331,0x19E28A90,0x1473A4D6,0x1CACD01F,0x1EEA8838,0xAF2AE29,0x1F85292A,0x1632585E,0xD945E5},{0x919F5EF,0x1567B39F,0x19F6AD11,0x16CE47CF,0x9B36EB1,0x35B7D3,0x483B28C,0xCBEFA27,0xB5FC21}};
-
-int main()
-{
-	int i;
-	BIG p[4],e[4],x[4],r[4];
-	csprng rng;
-	char raw[100];
-	for (i=0;i<100;i++) raw[i]=i;
-    RAND_seed(&rng,100,raw);
-
-
-	FF_init(x,3,4);
-
-	FF_copy(p,P,4);
-	FF_copy(e,p,4);
-	FF_dec(e,1,4);
-	FF_norm(e,4);
-
-
-
-	printf("p= ");FF_output(p,4); printf("\n");
-	if (FF_prime(p,&rng,4)) printf("p is a prime\n");
-	printf("e= ");FF_output(e,4); printf("\n");
-
-	FF_skpow(r,x,e,p,4);
-	printf("r= ");FF_output(r,4); printf("\n");
-}
-
-*/
diff --git a/c/fp.c b/c/fp.c
deleted file mode 100755
index aa858cc..0000000
--- a/c/fp.c
+++ /dev/null
@@ -1,559 +0,0 @@
-/*
-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.
-*/
-
-/* AMCL mod p functions */
-/* Small Finite Field arithmetic */
-/* SU=m, SU is Stack Usage (NOT_SPECIAL Modulus) */
-
-#include "amcl.h"
-
-/* Fast Modular Reduction Methods */
-
-/* r=d mod m */
-/* d MUST be normalised */
-/* Products must be less than pR in all cases !!! */
-/* So when multiplying two numbers, their product *must* be less than MODBITS+BASEBITS*NLEN */
-/* Results *may* be one bit bigger than MODBITS */
-
-#if MODTYPE == PSEUDO_MERSENNE
-/* r=d mod m */
-
-void FP_nres(BIG a) {}
-
-void FP_redc(BIG a) {}
-
-/* reduce a DBIG to a BIG exploiting the special form of the modulus */
-void FP_mod(BIG r,DBIG d)
-{
-	BIG t,b,m;
-	chunk v,tw;
-	BIG_split(t,b,d,MODBITS);
-
-/* Note that all of the excess gets pushed into t. So if squaring a value with a 4-bit excess, this results in
-   t getting all 8 bits of the excess product! So products must be less than pR which is Montgomery compatible */
-
-	if (MConst < NEXCESS)
-	{
-		BIG_imul(t,t,MConst);
-
-		BIG_norm(t);
-		tw=t[NLEN-1];
-		t[NLEN-1]&=TMASK;
-		t[0]+=MConst*((tw>>TBITS));
-	}
-	else
-	{
-		v=BIG_pmul(t,t,MConst);
-		tw=t[NLEN-1];
-		t[NLEN-1]&=TMASK;
-#if CHUNK == 16
-		t[1]+=muladd(MConst,((tw>>TBITS)+(v<<(BASEBITS-TBITS))),0,&t[0]);
-#else
-		t[0]+=MConst*((tw>>TBITS)+(v<<(BASEBITS-TBITS)));
-#endif
-	}
-	BIG_add(r,t,b);
-	BIG_norm(r);
-}
-#endif
-
-#if MODTYPE == MONTGOMERY_FRIENDLY
-
-/* convert to Montgomery n-residue form */
-void FP_nres(BIG a)
-{
-	DBIG d;
-	BIG m;
-	BIG_rcopy(m,Modulus);
-	BIG_dscopy(d,a);
-	BIG_dshl(d,NLEN*BASEBITS);
-	BIG_dmod(a,d,m);
-}
-
-/* convert back to regular form */
-void FP_redc(BIG a)
-{
-	DBIG d;
-	BIG_dzero(d);
-	BIG_dscopy(d,a);
-	FP_mod(a,d);
-}
-
-/* fast modular reduction from DBIG to BIG exploiting special form of the modulus */
-void FP_mod(BIG a,DBIG d)
-{
-	int i;
-	chunk k;
-
-	for (i=0;i<NLEN;i++)
-		d[NLEN+i]+=muladd(d[i],MConst-1,d[i],&d[NLEN+i-1]);
-
-	BIG_sducopy(a,d);
-	BIG_norm(a);
-}
-
-#endif
-
-#if MODTYPE == NOT_SPECIAL
-
-/* convert BIG a to Montgomery n-residue form */
-/* SU= 120 */
-void FP_nres(BIG a)
-{
-	DBIG d;
-	BIG m;
-	BIG_rcopy(m,Modulus);
-	BIG_dscopy(d,a);
-	BIG_dshl(d,NLEN*BASEBITS);
-	BIG_dmod(a,d,m);
-}
-
-/* SU= 80 */
-/* convert back to regular form */
-void FP_redc(BIG a)
-{
-	DBIG d;
-	BIG_dzero(d);
-	BIG_dscopy(d,a);
-	FP_mod(a,d);
-}
-
-/* reduce a DBIG to a BIG using Montgomery's no trial division method */
-/* d is expected to be dnormed before entry */
-/* SU= 112 */
-void FP_mod(BIG a,DBIG d)
-{
-	int i,j;
-	chunk m,carry;
-	BIG md;
-
-#ifdef dchunk
-	dchunk sum;
-	chunk sp;
-#endif
-
-	BIG_rcopy(md,Modulus);
-
-#ifdef COMBA
-
-/* Faster to Combafy it.. Let the compiler unroll the loops! */
-
-	sum=d[0];
-	for (j=0;j<NLEN;j++)
-	{
-		for (i=0;i<j;i++) sum+=(dchunk)d[i]*md[j-i];
-		if (MConst==-1) sp=(-(chunk)sum)&MASK;
-		else
-		{
-			if (MConst==1) sp=((chunk)sum)&MASK;
-			else sp=((chunk)sum*MConst)&MASK;
-		}
-		d[j]=sp; sum+=(dchunk)sp*md[0];  /* no need for &MASK here! */
-		sum=d[j+1]+(sum>>BASEBITS);
-	}
-
-	for (j=NLEN;j<DNLEN-2;j++)
-	{
-		for (i=j-NLEN+1;i<NLEN;i++) sum+=(dchunk)d[i]*md[j-i];
-		d[j]=(chunk)sum&MASK;
-		sum=d[j+1]+(sum>>BASEBITS);
-	}
-
-	sum+=(dchunk)d[NLEN-1]*md[NLEN-1];
-	d[DNLEN-2]=(chunk)sum&MASK;
-	sum=d[DNLEN-1]+(sum>>BASEBITS);
-	d[DNLEN-1]=(chunk)sum&MASK;
-
-	BIG_sducopy(a,d);
-	BIG_norm(a);
-
-#else
-	for (i=0;i<NLEN;i++)
-	{
-		if (MConst==-1) m=(-d[i])&MASK;
-		else
-		{
-			if (MConst==1) m=d[i];
-			else m=(MConst*d[i])&MASK;
-		}
-		carry=0;
-		for (j=0;j<NLEN;j++)
-			carry=muladd(m,md[j],carry,&d[i+j]);
-		d[NLEN+i]+=carry;
-	}
-	BIG_sducopy(a,d);
-	BIG_norm(a);
-
-#endif
-}
-
-#endif
-
-/* test x==0 ? */
-/* SU= 48 */
-int FP_iszilch(BIG x)
-{
-	BIG m;
-	BIG_rcopy(m,Modulus);
-	BIG_mod(x,m);
-	return BIG_iszilch(x);
-}
-
-/* output FP */
-/* SU= 48 */
-void FP_output(BIG r)
-{
-	BIG c;
-	BIG_copy(c,r);
-	FP_redc(c);
-	BIG_output(c);
-}
-
-void FP_rawoutput(BIG r)
-{
-	BIG_rawoutput(r);
-}
-
-#ifdef GET_STATS
-int tsqr=0,rsqr=0,tmul=0,rmul=0;
-int tadd=0,radd=0,tneg=0,rneg=0;
-int tdadd=0,rdadd=0,tdneg=0,rdneg=0;
-#endif
-
-/* r=a*b mod Modulus */
-/* product must be less that p.R - and we need to know this in advance! */
-/* SU= 88 */
-void FP_mul(BIG r,BIG a,BIG b)
-{
-	DBIG d;
-	chunk ea=EXCESS(a);
-	chunk eb=EXCESS(b);
-	if ((ea+1)*(eb+1)+1>=FEXCESS)
-	{
-#ifdef DEBUG_REDUCE
-		printf("Product too large - reducing it %d %d\n",ea,eb);
-#endif
-		FP_reduce(a);  /* it is sufficient to fully reduce just one of them < p */
-#ifdef GET_STATS
-		rmul++;
-	}
-	tmul++;
-#else
-	}
-#endif
-
-	BIG_mul(d,a,b);
-	FP_mod(r,d);
-}
-
-/* multiplication by an integer, r=a*c */
-/* SU= 136 */
-void FP_imul(BIG r,BIG a,int c)
-{
-	DBIG d;
-	BIG m;
-	int s=0;
-	chunk afx;
-	BIG_norm(a);
-	if (c<0)
-	{
-		c=-c;
-		s=1;
-	}
-	afx=(EXCESS(a)+1)*(c+1)+1;
-	if (c<NEXCESS && afx<FEXCESS)
-		BIG_imul(r,a,c);
-	else
-	{
-		if (afx<FEXCESS)
-		{
-			BIG_pmul(r,a,c);
-		}
-		else
-		{
-			BIG_rcopy(m,Modulus);
-			BIG_pxmul(d,a,c);
-			BIG_dmod(r,d,m);
-		}
-	}
-	if (s) FP_neg(r,r);
-	BIG_norm(r);
-}
-
-/* Set r=a^2 mod m */
-/* SU= 88 */
-void FP_sqr(BIG r,BIG a)
-{
-	DBIG d;
-	chunk ea=EXCESS(a);
-	if ((ea+1)*(ea+1)+1>=FEXCESS)
-	{
-#ifdef DEBUG_REDUCE
-		printf("Product too large - reducing it %d\n",ea);
-#endif
-		FP_reduce(a);
-#ifdef GET_STATS
-		rsqr++;
-	}
-	tsqr++;
-#else
-	}
-#endif
-	BIG_sqr(d,a);
-	FP_mod(r,d);
-}
-
-/* SU= 16 */
-/* Set r=a+b */
-void FP_add(BIG r,BIG a,BIG b)
-{
-	BIG_add(r,a,b);
-	if (EXCESS(r)+2>=FEXCESS)  /* +2 because a and b not normalised */
-	{
-#ifdef DEBUG_REDUCE
-		printf("Sum too large - reducing it %d\n",EXCESS(r));
-#endif
-		FP_reduce(r);
-#ifdef GET_STATS
-		radd++;
-	}
-	tadd++;
-#else
-	}
-#endif
-}
-
-/* Set r=a-b mod m */
-/* SU= 56 */
-void FP_sub(BIG r,BIG a,BIG b)
-{
-	BIG n;
-	FP_neg(n,b);
-	FP_add(r,a,n);
-}
-
-/* SU= 48 */
-/* Fully reduce a mod Modulus */
-void FP_reduce(BIG a)
-{
-	BIG m;
-	BIG_rcopy(m,Modulus);
-	BIG_mod(a,m);
-}
-
-/* Set r=-a mod Modulus */
-/* SU= 64 */
-void FP_neg(BIG r,BIG a)
-{
-	int sb;
-	chunk ov;
-	BIG m,t;
-
-	BIG_rcopy(m,Modulus);
-	BIG_norm(a);
-
-	ov=EXCESS(a);
-	sb=1; while(ov!=0) {sb++;ov>>=1;}  /* only unpredictable branch */
-
-	BIG_fshl(m,sb);
-	BIG_sub(r,m,a);
-
-	if (EXCESS(r)>=FEXCESS)
-	{
-#ifdef DEBUG_REDUCE
-		printf("Negation too large -  reducing it %d\n",EXCESS(r));
-#endif
-		FP_reduce(r);
-#ifdef GET_STATS
-		rneg++;
-	}
-	tneg++;
-#else
-	}
-#endif
-
-}
-
-/* Set r=a/2. */
-/* SU= 56 */
-void FP_div2(BIG r,BIG a)
-{
-	BIG m;
-	BIG_rcopy(m,Modulus);
-	BIG_norm(a);
-	if (BIG_parity(a)==0)
-	{
-		BIG_copy(r,a);
-		BIG_fshr(r,1);
-	}
-	else
-	{
-		BIG_add(r,a,m);
-		BIG_norm(r);
-		BIG_fshr(r,1);
-	}
-}
-
-/* set w=1/x */
-void FP_inv(BIG w,BIG x)
-{
-	BIG m;
-	BIG_rcopy(m,Modulus);
-	BIG_copy(w,x);
-	FP_redc(w);
-
-	BIG_invmodp(w,w,m);
-	FP_nres(w);
-}
-
-/* SU=8 */
-/* set n=1 */
-void FP_one(BIG n)
-{
-	BIG_one(n); FP_nres(n);
-}
-
-/* Set r=a^b mod Modulus */
-/* SU= 136 */
-void FP_pow(BIG r,BIG a,BIG b)
-{
-	BIG w,z,zilch;
-	int bt;
-	BIG_zero(zilch);
-
-	BIG_norm(b);
-	BIG_copy(z,b);
-	BIG_copy(w,a);
-	FP_one(r);
-	while(1)
-	{
-		bt=BIG_parity(z);
-		BIG_fshr(z,1);
-		if (bt) FP_mul(r,r,w);
-		if (BIG_comp(z,zilch)==0) break;
-		FP_sqr(w,w);
-	}
-	FP_reduce(r);
-}
-
-/* is r a QR? */
-int FP_qr(BIG r)
-{
-	int j;
-	BIG m;
-	BIG_rcopy(m,Modulus);
-	FP_redc(r);
-	j=BIG_jacobi(r,m);
-	FP_nres(r);
-	if (j==1) return 1;
-	return 0;
-
-}
-
-/* Set a=sqrt(b) mod Modulus */
-/* SU= 160 */
-void FP_sqrt(BIG r,BIG a)
-{
-	BIG v,i,b;
-	BIG m;
-	BIG_rcopy(m,Modulus);
-	BIG_mod(a,m);
-	BIG_copy(b,m);
-	if (MOD8==5)
-	{
-		BIG_dec(b,5); BIG_norm(b); BIG_fshr(b,3); /* (p-5)/8 */
-		BIG_copy(i,a); BIG_fshl(i,1);
-		FP_pow(v,i,b);
-		FP_mul(i,i,v); FP_mul(i,i,v);
-		BIG_dec(i,1);
-		FP_mul(r,a,v); FP_mul(r,r,i);
-		BIG_mod(r,m);
-	}
-	if (MOD8==3 || MOD8==7)
-	{
-		BIG_inc(b,1); BIG_norm(b); BIG_fshr(b,2); /* (p+1)/4 */
-		FP_pow(r,a,b);
-	}
-}
-
-/*
-int main()
-{
-
-	BIG r;
-
-	FP_one(r);
-	FP_sqr(r,r);
-
-	BIG_output(r);
-
-	int i,carry;
-	DBIG c={0,0,0,0,0,0,0,0};
-	BIG a={1,2,3,4};
-	BIG b={3,4,5,6};
-	BIG r={11,12,13,14};
-	BIG s={23,24,25,15};
-	BIG w;
-
-//	printf("NEXCESS= %d\n",NEXCESS);
-//	printf("MConst= %d\n",MConst);
-
-	BIG_copy(b,Modulus);
-	BIG_dec(b,1);
-	BIG_norm(b);
-
-	BIG_randomnum(r); BIG_norm(r); BIG_mod(r,Modulus);
-//	BIG_randomnum(s); norm(s); BIG_mod(s,Modulus);
-
-//	BIG_output(r);
-//	BIG_output(s);
-
-	BIG_output(r);
-	FP_nres(r);
-	BIG_output(r);
-	BIG_copy(a,r);
-	FP_redc(r);
-	BIG_output(r);
-	BIG_dscopy(c,a);
-	FP_mod(r,c);
-	BIG_output(r);
-
-
-//	exit(0);
-
-//	copy(r,a);
-	printf("r=   "); BIG_output(r);
-	BIG_modsqr(r,r,Modulus);
-	printf("r^2= "); BIG_output(r);
-
-	FP_nres(r);
-	FP_sqrt(r,r);
-	FP_redc(r);
-	printf("r=   "); BIG_output(r);
-	BIG_modsqr(r,r,Modulus);
-	printf("r^2= "); BIG_output(r);
-
-
-//	for (i=0;i<100000;i++) FP_sqr(r,r);
-//	for (i=0;i<100000;i++)
-		FP_sqrt(r,r);
-
-	BIG_output(r);
-}
-*/
diff --git a/c/fp12.c b/c/fp12.c
deleted file mode 100755
index 51f41cc..0000000
--- a/c/fp12.c
+++ /dev/null
@@ -1,688 +0,0 @@
-/*
-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.
-*/
-
-/* AMCL Fp^12 functions */
-/* SU=m, m is Stack Usage (no lazy )*/
-/* FP12 elements are of the form a+i.b+i^2.c */
-
-#include "amcl.h"
-
-/* test x==0 ? */
-/* SU= 8 */
-int FP12_iszilch(FP12 *x)
-{
-	if (FP4_iszilch(&(x->a)) && FP4_iszilch(&(x->b)) && FP4_iszilch(&(x->c))) return 1;
-	return 0;
-}
-
-/* test x==1 ? */
-/* SU= 8 */
-int FP12_isunity(FP12 *x)
-{
-	if (FP4_isunity(&(x->a)) && FP4_iszilch(&(x->b)) && FP4_iszilch(&(x->c))) return 1;
-	return 0;
-}
-
-/* FP12 copy w=x */
-/* SU= 16 */
-void FP12_copy(FP12 *w,FP12 *x)
-{
-	if (x==w) return;
-	FP4_copy(&(w->a),&(x->a));
-	FP4_copy(&(w->b),&(x->b));
-	FP4_copy(&(w->c),&(x->c));
-}
-
-/* FP12 w=1 */
-/* SU= 8 */
-void FP12_one(FP12 *w)
-{
-	FP4_one(&(w->a));
-	FP4_zero(&(w->b));
-	FP4_zero(&(w->c));
-}
-
-/* return 1 if x==y, else 0 */
-/* SU= 16 */
-int FP12_equals(FP12 *x,FP12 *y)
-{
-	if (FP4_equals(&(x->a),&(y->a)) && FP4_equals(&(x->b),&(y->b)) && FP4_equals(&(x->b),&(y->b)))
-		return 1;
-	return 0;
-}
-
-/* Set w=conj(x) */
-/* SU= 8 */
-void FP12_conj(FP12 *w,FP12 *x)
-{
-	FP12_copy(w,x);
-	FP4_conj(&(w->a),&(w->a));
-	FP4_nconj(&(w->b),&(w->b));
-	FP4_conj(&(w->c),&(w->c));
-}
-
-/* Create FP12 from FP4 */
-/* SU= 8 */
-void FP12_from_FP4(FP12 *w,FP4 *a)
-{
-	FP4_copy(&(w->a),a);
-	FP4_zero(&(w->b));
-	FP4_zero(&(w->c));
-}
-
-/* Create FP12 from 3 FP4's */
-/* SU= 16 */
-void FP12_from_FP4s(FP12 *w,FP4 *a,FP4 *b,FP4 *c)
-{
-	FP4_copy(&(w->a),a);
-	FP4_copy(&(w->b),b);
-	FP4_copy(&(w->c),c);
-}
-
-/* Granger-Scott Unitary Squaring. This does not benefit from lazy reduction */
-/* SU= 600 */
-void FP12_usqr(FP12 *w,FP12 *x)
-{
-	FP4 A,B,C,D;
-
-	FP4_copy(&A,&(x->a));
-
-	FP4_sqr(&(w->a),&(x->a));
-	FP4_add(&D,&(w->a),&(w->a));
-	FP4_add(&(w->a),&D,&(w->a));
-
-#if CHUNK<64
-	FP4_norm(&(w->a));
-#endif
-
-	FP4_nconj(&A,&A);
-
-	FP4_add(&A,&A,&A);
-	FP4_add(&(w->a),&(w->a),&A);
-	FP4_sqr(&B,&(x->c));
-	FP4_times_i(&B);
-
-	FP4_add(&D,&B,&B);
-	FP4_add(&B,&B,&D);
-#if CHUNK<64
-	FP4_norm(&B);
-#endif
-	FP4_sqr(&C,&(x->b));
-
-	FP4_add(&D,&C,&C);
-	FP4_add(&C,&C,&D);
-
-#if CHUNK<64
-	FP4_norm(&C);
-#endif
-	FP4_conj(&(w->b),&(x->b));
-	FP4_add(&(w->b),&(w->b),&(w->b));
-	FP4_nconj(&(w->c),&(x->c));
-
-	FP4_add(&(w->c),&(w->c),&(w->c));
-	FP4_add(&(w->b),&B,&(w->b));
-	FP4_add(&(w->c),&C,&(w->c));
-	FP12_reduce(w);	    /* reduce here as in pow function repeated squarings would trigger multiple reductions */
-
-}
-
-/* FP12 squaring w=x^2 */
-/* SU= 600 */
-void FP12_sqr(FP12 *w,FP12 *x)
-{
-/* Use Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
-
-	FP4 A,B,C,D;
-
-	FP4_sqr(&A,&(x->a));
-	FP4_mul(&B,&(x->b),&(x->c));
-	FP4_add(&B,&B,&B);
-	FP4_sqr(&C,&(x->c));
-	FP4_mul(&D,&(x->a),&(x->b));
-	FP4_add(&D,&D,&D);
-	FP4_add(&(w->c),&(x->a),&(x->c));
-	FP4_add(&(w->c),&(x->b),&(w->c));
-
-	FP4_sqr(&(w->c),&(w->c));
-
-	FP4_copy(&(w->a),&A);
-
-	FP4_add(&A,&A,&B);
-#if CHUNK<64
-	FP4_norm(&A);
-#endif
-	FP4_add(&A,&A,&C);
-	FP4_add(&A,&A,&D);
-#if CHUNK<64
-	FP4_norm(&A);
-#endif
-	FP4_neg(&A,&A);
-	FP4_times_i(&B);
-	FP4_times_i(&C);
-
-	FP4_add(&(w->a),&(w->a),&B);
-	FP4_add(&(w->b),&C,&D);
-	FP4_add(&(w->c),&(w->c),&A);
-
-	FP12_norm(w);
-}
-
-/* FP12 full multiplication w=w*y */
-
-
-/* SU= 896 */
-/* FP12 full multiplication w=w*y */
-void FP12_mul(FP12 *w,FP12 *y)
-{
-	FP4 z0,z1,z2,z3,t0,t1;
-
-	FP4_mul(&z0,&(w->a),&(y->a));
-	FP4_mul(&z2,&(w->b),&(y->b));  //
-
-	FP4_add(&t0,&(w->a),&(w->b));
-	FP4_add(&t1,&(y->a),&(y->b));  //
-	FP4_mul(&z1,&t0,&t1);
-	FP4_add(&t0,&(w->b),&(w->c));
-
-	FP4_add(&t1,&(y->b),&(y->c));  //
-	FP4_mul(&z3,&t0,&t1);
-
-	FP4_neg(&t0,&z0);
-	FP4_neg(&t1,&z2);
-
-	FP4_add(&z1,&z1,&t0);   // z1=z1-z0
-#if CHUNK<64
-	FP4_norm(&z1);
-#endif
-	FP4_add(&(w->b),&z1,&t1);
-// z1=z1-z2
-	FP4_add(&z3,&z3,&t1);        // z3=z3-z2
-	FP4_add(&z2,&z2,&t0);        // z2=z2-z0
-
-	FP4_add(&t0,&(w->a),&(w->c));
-
-	FP4_add(&t1,&(y->a),&(y->c));
-	FP4_mul(&t0,&t1,&t0);
-	FP4_add(&z2,&z2,&t0);
-
-	FP4_mul(&t0,&(w->c),&(y->c));
-	FP4_neg(&t1,&t0);
-#if CHUNK<64
-	FP4_norm(&z2);
-	FP4_norm(&z3);
-	FP4_norm(&(w->b));
-#endif
-	FP4_add(&(w->c),&z2,&t1);
-	FP4_add(&z3,&z3,&t1);
-	FP4_times_i(&t0);
-	FP4_add(&(w->b),&(w->b),&t0);
-
-	FP4_times_i(&z3);
-	FP4_add(&(w->a),&z0,&z3);
-
-	FP12_norm(w);
-}
-
-/* FP12 multiplication w=w*y */
-/* SU= 744 */
-/* catering for special case that arises from special form of ATE pairing line function */
-void FP12_smul(FP12 *w,FP12 *y)
-{
-	FP4 z0,z2,z3,t0,t1;
-
-	FP4_copy(&z3,&(w->b));
-	FP4_mul(&z0,&(w->a),&(y->a));
-	FP4_pmul(&z2,&(w->b),&(y->b).a);
-	FP4_add(&(w->b),&(w->a),&(w->b));
-	FP4_copy(&t1,&(y->a));
-	FP2_add(&t1.a,&t1.a,&(y->b).a);
-
-	FP4_mul(&(w->b),&(w->b),&t1);
-	FP4_add(&z3,&z3,&(w->c));
-	FP4_pmul(&z3,&z3,&(y->b).a);
-	FP4_neg(&t0,&z0);
-	FP4_neg(&t1,&z2);
-
-	FP4_add(&(w->b),&(w->b),&t0);   // z1=z1-z0
-#if CHUNK<64
-	FP4_norm(&(w->b));
-#endif
-	FP4_add(&(w->b),&(w->b),&t1);   // z1=z1-z2
-
-	FP4_add(&z3,&z3,&t1);        // z3=z3-z2
-	FP4_add(&z2,&z2,&t0);        // z2=z2-z0
-
-	FP4_add(&t0,&(w->a),&(w->c));
-
-	FP4_mul(&t0,&(y->a),&t0);
-	FP4_add(&(w->c),&z2,&t0);
-
-	FP4_times_i(&z3);
-	FP4_add(&(w->a),&z0,&z3);
-
-	FP12_norm(w);
-}
-
-/* Set w=1/x */
-/* SU= 600 */
-void FP12_inv(FP12 *w,FP12 *x)
-{
-	FP4 f0,f1,f2,f3;
-	FP12_norm(x);
-
-	FP4_sqr(&f0,&(x->a));
-	FP4_mul(&f1,&(x->b),&(x->c));
-	FP4_times_i(&f1);
-	FP4_sub(&f0,&f0,&f1);  /* y.a */
-
-	FP4_sqr(&f1,&(x->c));
-	FP4_times_i(&f1);
-	FP4_mul(&f2,&(x->a),&(x->b));
-	FP4_sub(&f1,&f1,&f2);  /* y.b */
-
-	FP4_sqr(&f2,&(x->b));
-	FP4_mul(&f3,&(x->a),&(x->c));
-	FP4_sub(&f2,&f2,&f3);  /* y.c */
-
-	FP4_mul(&f3,&(x->b),&f2);
-	FP4_times_i(&f3);
-	FP4_mul(&(w->a),&f0,&(x->a));
-	FP4_add(&f3,&(w->a),&f3);
-	FP4_mul(&(w->c),&f1,&(x->c));
-	FP4_times_i(&(w->c));
-
-	FP4_add(&f3,&(w->c),&f3);
-	FP4_inv(&f3,&f3);
-
-	FP4_mul(&(w->a),&f0,&f3);
-	FP4_mul(&(w->b),&f1,&f3);
-	FP4_mul(&(w->c),&f2,&f3);
-
-}
-
-/* constant time powering by small integer of max length bts */
-
-void FP12_pinpow(FP12 *r,int e,int bts)
-{
-	int i,b;
-	FP12 R[2];
-
-	FP12_one(&R[0]);
-	FP12_copy(&R[1],r);
-
-    for (i=bts-1;i>=0;i--)
-	{
-		b=(e>>i)&1;
-		FP12_mul(&R[1-b],&R[b]);
-		FP12_usqr(&R[b],&R[b]);
-	}
-	FP12_copy(r,&R[0]);
-}
-
-/* SU= 528 */
-/* set r=a^b */
-/* Note this is simple square and multiply, so not side-channel safe */
-
-void FP12_pow(FP12 *r,FP12 *a,BIG b)
-{
-	FP12 w;
-	BIG z,zilch;
-	int bt;
-	BIG_zero(zilch);
-	BIG_norm(b);
-	BIG_copy(z,b);
-	FP12_copy(&w,a);
-	FP12_one(r);
-
-	while(1)
-	{
-		bt=BIG_parity(z);
-		BIG_shr(z,1);
-		if (bt)
-			FP12_mul(r,&w);
-		if (BIG_comp(z,zilch)==0) break;
-		FP12_usqr(&w,&w);
-	}
-
-	FP12_reduce(r);
-}
-
-/* p=q0^u0.q1^u1.q2^u2.q3^u3 */
-/* Timing attack secure, but not cache attack secure */
-
-void FP12_pow4(FP12 *p,FP12 *q,BIG u[4])
-{
-	int i,j,a[4],nb,m;
-	FP12 g[8],c,s[2];
-	BIG t[4],mt;
-	sign8 w[NLEN*BASEBITS+1];
-
-	for (i=0;i<4;i++)
-		BIG_copy(t[i],u[i]);
-
-	FP12_copy(&g[0],&q[0]); FP12_conj(&s[0],&q[1]); FP12_mul(&g[0],&s[0]);  /* P/Q */
-	FP12_copy(&g[1],&g[0]);
-	FP12_copy(&g[2],&g[0]);
-	FP12_copy(&g[3],&g[0]);
-	FP12_copy(&g[4],&q[0]); FP12_mul(&g[4],&q[1]);  /* P*Q */
-	FP12_copy(&g[5],&g[4]);
-	FP12_copy(&g[6],&g[4]);
-	FP12_copy(&g[7],&g[4]);
-
-	FP12_copy(&s[1],&q[2]); FP12_conj(&s[0],&q[3]); FP12_mul(&s[1],&s[0]);       /* R/S */
-	FP12_conj(&s[0],&s[1]); FP12_mul(&g[1],&s[0]);
-	FP12_mul(&g[2],&s[1]);
-	FP12_mul(&g[5],&s[0]);
-	FP12_mul(&g[6],&s[1]);
-	FP12_copy(&s[1],&q[2]); FP12_mul(&s[1],&q[3]);      /* R*S */
-	FP12_conj(&s[0],&s[1]); FP12_mul(&g[0],&s[0]);
-	FP12_mul(&g[3],&s[1]);
-	FP12_mul(&g[4],&s[0]);
-	FP12_mul(&g[7],&s[1]);
-
-/* if power is even add 1 to power, and add q to correction */
-	FP12_one(&c);
-
-	BIG_zero(mt);
-	for (i=0;i<4;i++)
-	{
-		if (BIG_parity(t[i])==0)
-		{
-			BIG_inc(t[i],1); BIG_norm(t[i]);
-			FP12_mul(&c,&q[i]);
-		}
-		BIG_add(mt,mt,t[i]); BIG_norm(mt);
-	}
-
-	FP12_conj(&c,&c);
-	nb=1+BIG_nbits(mt);
-
-/* convert exponent to signed 1-bit window */
-	for (j=0;j<nb;j++)
-	{
-		for (i=0;i<4;i++)
-		{
-			a[i]=BIG_lastbits(t[i],2)-2;
-			BIG_dec(t[i],a[i]); BIG_norm(t[i]);
-			BIG_fshr(t[i],1);
-		}
-		w[j]=8*a[0]+4*a[1]+2*a[2]+a[3];
-	}
-	w[nb]=8*BIG_lastbits(t[0],2)+4*BIG_lastbits(t[1],2)+2*BIG_lastbits(t[2],2)+BIG_lastbits(t[3],2);
-	FP12_copy(p,&g[(w[nb]-1)/2]);
-
-	for (i=nb-1;i>=0;i--)
-	{
-		m=w[i]>>7;
-		j=(w[i]^m)-m;  /* j=abs(w[i]) */
-		j=(j-1)/2;
-		FP12_copy(&s[0],&g[j]);
-		FP12_conj(&s[1],&g[j]);
-		FP12_usqr(p,p);
-		FP12_mul(p,&s[m&1]);
-	}
-	FP12_mul(p,&c); /* apply correction */
-	FP12_reduce(p);
-}
-
-/* Set w=w^p using Frobenius */
-/* SU= 160 */
-void FP12_frob(FP12 *w,FP2 *f)
-{
-	FP2 f2,f3;
-	FP2_sqr(&f2,f);     /* f2=f^2 */
-	FP2_mul(&f3,&f2,f); /* f3=f^3 */
-
-	FP4_frob(&(w->a),&f3);
-	FP4_frob(&(w->b),&f3);
-	FP4_frob(&(w->c),&f3);
-
-	FP4_pmul(&(w->b),&(w->b),f);
-	FP4_pmul(&(w->c),&(w->c),&f2);
-}
-
-/* SU= 8 */
-/* normalise all components of w */
-void FP12_norm(FP12 *w)
-{
-	 FP4_norm(&(w->a));
-	 FP4_norm(&(w->b));
-	 FP4_norm(&(w->c));
-}
-
-/* SU= 8 */
-/* reduce all components of w */
-void FP12_reduce(FP12 *w)
-{
-	 FP4_reduce(&(w->a));
-	 FP4_reduce(&(w->b));
-	 FP4_reduce(&(w->c));
-}
-
-/* trace function w=trace(x) */
-/* SU= 8 */
-void FP12_trace(FP4 *w,FP12 *x)
-{
-	FP4_imul(w,&(x->a),3);
-	FP4_reduce(w);
-}
-
-/* SU= 8 */
-/* Output w in hex */
-void FP12_output(FP12 *w)
-{
-	printf("[");
-	FP4_output(&(w->a));
-	printf(",");
-	FP4_output(&(w->b));
-	printf(",");
-	FP4_output(&(w->c));
-	printf("]");
-}
-
-/* SU= 64 */
-/* Convert g to octet string w */
-void FP12_toOctet(octet *W,FP12 *g)
-{
-	BIG a;
-	W->len=12*MODBYTES;
-
-	BIG_copy(a,(*g).a.a.a); FP_redc(a); BIG_toBytes(&(W->val[0]),a);
-	BIG_copy(a,(*g).a.a.b); FP_redc(a); BIG_toBytes(&(W->val[MODBYTES]),a);
-	BIG_copy(a,(*g).a.b.a); FP_redc(a); BIG_toBytes(&(W->val[2*MODBYTES]),a);
-	BIG_copy(a,(*g).a.b.b); FP_redc(a); BIG_toBytes(&(W->val[3*MODBYTES]),a);
-
-	BIG_copy(a,(*g).b.a.a); FP_redc(a); BIG_toBytes(&(W->val[4*MODBYTES]),a);
-	BIG_copy(a,(*g).b.a.b); FP_redc(a); BIG_toBytes(&(W->val[5*MODBYTES]),a);
-	BIG_copy(a,(*g).b.b.a); FP_redc(a); BIG_toBytes(&(W->val[6*MODBYTES]),a);
-	BIG_copy(a,(*g).b.b.b); FP_redc(a); BIG_toBytes(&(W->val[7*MODBYTES]),a);
-
-	BIG_copy(a,(*g).c.a.a); FP_redc(a); BIG_toBytes(&(W->val[8*MODBYTES]),a);
-	BIG_copy(a,(*g).c.a.b); FP_redc(a); BIG_toBytes(&(W->val[9*MODBYTES]),a);
-	BIG_copy(a,(*g).c.b.a); FP_redc(a); BIG_toBytes(&(W->val[10*MODBYTES]),a);
-	BIG_copy(a,(*g).c.b.b); FP_redc(a); BIG_toBytes(&(W->val[11*MODBYTES]),a);
-}
-
-/* SU= 24 */
-/* Restore g from octet string w */
-void FP12_fromOctet(FP12 *g,octet *W)
-{
-	BIG_fromBytes((*g).a.a.a,&W->val[0]);			FP_nres((*g).a.a.a);
-	BIG_fromBytes((*g).a.a.b,&W->val[MODBYTES]);		FP_nres((*g).a.a.b);
-	BIG_fromBytes((*g).a.b.a,&W->val[2*MODBYTES]);	FP_nres((*g).a.b.a);
-	BIG_fromBytes((*g).a.b.b,&W->val[3*MODBYTES]);	FP_nres((*g).a.b.b);
-	BIG_fromBytes((*g).b.a.a,&W->val[4*MODBYTES]);	FP_nres((*g).b.a.a);
-	BIG_fromBytes((*g).b.a.b,&W->val[5*MODBYTES]);	FP_nres((*g).b.a.b);
-	BIG_fromBytes((*g).b.b.a,&W->val[6*MODBYTES]);	FP_nres((*g).b.b.a);
-	BIG_fromBytes((*g).b.b.b,&W->val[7*MODBYTES]);	FP_nres((*g).b.b.b);
-	BIG_fromBytes((*g).c.a.a,&W->val[8*MODBYTES]);	FP_nres((*g).c.a.a);
-	BIG_fromBytes((*g).c.a.b,&W->val[9*MODBYTES]);	FP_nres((*g).c.a.b);
-	BIG_fromBytes((*g).c.b.a,&W->val[10*MODBYTES]);	FP_nres((*g).c.b.a);
-	BIG_fromBytes((*g).c.b.b,&W->val[11*MODBYTES]);	FP_nres((*g).c.b.b);
-}
-
-/*
-int main(){
-		FP2 f,w0,w1;
-		FP4 t0,t1,t2;
-		FP12 w,t,lv;
-		BIG a,b;
-		BIG p;
-
-		//Test w^(P^4) = w mod p^2
-//		BIG_randomnum(a);
-//		BIG_randomnum(b);
-//		BIG_mod(a,Modulus); BIG_mod(b,Modulus);
-	BIG_zero(a); BIG_zero(b); BIG_inc(a,1); BIG_inc(b,2); FP_nres(a); FP_nres(b);
-		FP2_from_zps(&w0,a,b);
-
-//		BIG_randomnum(a); BIG_randomnum(b);
-//		BIG_mod(a,Modulus); BIG_mod(b,Modulus);
-	BIG_zero(a); BIG_zero(b); BIG_inc(a,3); BIG_inc(b,4); FP_nres(a); FP_nres(b);
-		FP2_from_zps(&w1,a,b);
-
-		FP4_from_FP2s(&t0,&w0,&w1);
-		FP4_reduce(&t0);
-
-//		BIG_randomnum(a);
-//		BIG_randomnum(b);
-//		BIG_mod(a,Modulus); BIG_mod(b,Modulus);
-		BIG_zero(a); BIG_zero(b); BIG_inc(a,5); BIG_inc(b,6); FP_nres(a); FP_nres(b);
-		FP2_from_zps(&w0,a,b);
-
-//		BIG_randomnum(a); BIG_randomnum(b);
-//		BIG_mod(a,Modulus); BIG_mod(b,Modulus);
-
-		BIG_zero(a); BIG_zero(b); BIG_inc(a,7); BIG_inc(b,8); FP_nres(a); FP_nres(b);
-		FP2_from_zps(&w1,a,b);
-
-		FP4_from_FP2s(&t1,&w0,&w1);
-		FP4_reduce(&t1);
-
-//		BIG_randomnum(a);
-//		BIG_randomnum(b);
-//		BIG_mod(a,Modulus); BIG_mod(b,Modulus);
-		BIG_zero(a); BIG_zero(b); BIG_inc(a,9); BIG_inc(b,10); FP_nres(a); FP_nres(b);
-		FP2_from_zps(&w0,a,b);
-
-//		BIG_randomnum(a); BIG_randomnum(b);
-//		BIG_mod(a,Modulus); BIG_mod(b,Modulus);
-		BIG_zero(a); BIG_zero(b); BIG_inc(a,11); BIG_inc(b,12); FP_nres(a); FP_nres(b);
-		FP2_from_zps(&w1,a,b);
-
-		FP4_from_FP2s(&t2,&w0,&w1);
-		FP4_reduce(&t2);
-
-		FP12_from_FP4s(&w,&t0,&t1,&t2);
-
-		FP12_copy(&t,&w);
-
-		printf("w= ");
-		FP12_output(&w);
-		printf("\n");
-
-		BIG_rcopy(p,Modulus);
-		//BIG_zero(p); BIG_inc(p,7);
-
-		FP12_pow(&w,&w,p);
-
-		printf("w^p= ");
-		FP12_output(&w);
-		printf("\n");
-
-		FP2_gfc(&f,12);
-		FP12_frob(&t,&f);
-		printf("w^p= ");
-		FP12_output(&t);
-		printf("\n");
-
-//exit(0);
-
-		FP12_pow(&w,&w,p);
-		//printf("w^p^2= ");
-		//FP12_output(&w);
-		//printf("\n");
-		FP12_pow(&w,&w,p);
-		//printf("w^p^3= ");
-		//FP12_output(&w);
-		//printf("\n");
-		FP12_pow(&w,&w,p);
-		FP12_pow(&w,&w,p);
-		FP12_pow(&w,&w,p);
-		printf("w^p^6= ");
-		FP12_output(&w);
-		printf("\n");
-		FP12_pow(&w,&w,p);
-		FP12_pow(&w,&w,p);
-		printf("w^p^8= ");
-		FP12_output(&w);
-		printf("\n");
-		FP12_pow(&w,&w,p);
-		FP12_pow(&w,&w,p);
-		FP12_pow(&w,&w,p);
-		printf("w^p^11= ");
-		FP12_output(&w);
-		printf("\n");
-
-	//	BIG_zero(p); BIG_inc(p,7); BIG_norm(p);
-		FP12_pow(&w,&w,p);
-
-		printf("w^p12= ");
-		FP12_output(&w);
-		printf("\n");
-//exit(0);
-
-		FP12_inv(&t,&w);
-		printf("1/w mod p^4 = ");
-		FP12_output(&t);
-		printf("\n");
-
-		FP12_inv(&w,&t);
-		printf("1/(1/w) mod p^4 = ");
-		FP12_output(&w);
-		printf("\n");
-
-
-
-	FP12_inv(&lv,&w);
-//printf("w= "); FP12_output(&w); printf("\n");
-	FP12_conj(&w,&w);
-//printf("w= "); FP12_output(&w); printf("\n");
-//exit(0);
-	FP12_mul(&w,&w,&lv);
-//printf("w= "); FP12_output(&w); printf("\n");
-	FP12_copy(&lv,&w);
-	FP12_frob(&w,&f);
-	FP12_frob(&w,&f);
-	FP12_mul(&w,&w,&lv);
-
-//printf("w= "); FP12_output(&w); printf("\n");
-//exit(0);
-
-w.unitary=0;
-FP12_conj(&lv,&w);
-	printf("rx= "); FP12_output(&lv); printf("\n");
-FP12_inv(&lv,&w);
-	printf("ry= "); FP12_output(&lv); printf("\n");
-
-
-		return 0;
-}
-
-*/
diff --git a/c/fp2.c b/c/fp2.c
deleted file mode 100755
index 618815b..0000000
--- a/c/fp2.c
+++ /dev/null
@@ -1,421 +0,0 @@
-/*
-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.
-*/
-
-/* AMCL Fp^2 functions */
-/* SU=m, m is Stack Usage (no lazy )*/
-
-/* FP2 elements are of the form a+ib, where i is sqrt(-1) */
-#include "amcl.h"
-
-/* test x==0 ? */
-/* SU= 8 */
-int FP2_iszilch(FP2 *x)
-{
-	BIG m;
-	FP2_reduce(x);
-    if (BIG_iszilch(x->a) && BIG_iszilch(x->b)) return 1;
-    return 0;
-}
-
-/* Move b to a if d=1 */
-void FP2_cmove(FP2 *f,FP2 *g,int d)
-{
-	BIG_cmove(f->a,g->a,d);
-	BIG_cmove(f->b,g->b,d);
-}
-
-/* test x==1 ? */
-/* SU= 48 */
-int FP2_isunity(FP2 *x)
-{
-	BIG one;
-	FP_one(one);
-	FP2_reduce(x);
-	if (BIG_comp(x->a,one)==0 && BIG_iszilch(x->b)) return 1;
-    return 0;
-}
-
-/* SU= 8 */
-/* Fully reduce a and b mod Modulus */
-void FP2_reduce(FP2 *w)
-{
-	FP_reduce(w->a);
-	FP_reduce(w->b);
-}
-
-/* return 1 if x==y, else 0 */
-/* SU= 16 */
-int FP2_equals(FP2 *x,FP2 *y)
-{
-	FP2_reduce(x); FP2_reduce(y);
-	if (BIG_comp(x->a,y->a)==0 && BIG_comp(x->b,y->b)==0)
-		return 1;
-	return 0;
-}
-
-/* Create FP2 from two FPs */
-/* SU= 16 */
-void FP2_from_FPs(FP2 *w,BIG x,BIG y)
-{
-	BIG_copy(w->a,x);
-	BIG_copy(w->b,y);
-}
-
-/* Create FP2 from two BIGS */
-/* SU= 16 */
-void FP2_from_BIGs(FP2 *w,BIG x,BIG y)
-{
-	BIG_copy(w->a,x);
-	BIG_copy(w->b,y);
-	FP_nres(w->a); FP_nres(w->b);
-}
-
-/* Create FP2 from FP */
-/* SU= 8 */
-void FP2_from_FP(FP2 *w,BIG x)
-{
-	BIG_copy(w->a,x);
-	BIG_zero(w->b);
-}
-
-/* Create FP2 from BIG */
-/* SU= 8 */
-void FP2_from_BIG(FP2 *w,BIG x)
-{
-	BIG_copy(w->a,x); FP_nres(w->a);
-	BIG_zero(w->b);
-}
-
-/* FP2 copy w=x */
-/* SU= 16 */
-void FP2_copy(FP2 *w,FP2 *x)
-{
-	if (w==x) return;
-	BIG_copy(w->a,x->a);
-	BIG_copy(w->b,x->b);
-}
-
-/* FP2 set w=0 */
-/* SU= 8 */
-void FP2_zero(FP2 *w)
-{
-	BIG_zero(w->a);
-	BIG_zero(w->b);
-}
-
-/* FP2 set w=1 */
-/* SU= 48 */
-void FP2_one(FP2 *w)
-{
-	BIG one;
-	FP_one(one);
-	FP2_from_FP(w,one);
-}
-
-/* Set w=-x */
-/* SU= 88 */
-void FP2_neg(FP2 *w,FP2 *x)
-{ /* Just one neg! */
-	BIG m,t;
-	FP2_norm(x);
-	FP_add(m,x->a,x->b);
-	FP_neg(m,m);
-	BIG_norm(m);
-	FP_add(t,m,x->b);
-	FP_add(w->b,m,x->a);
-	BIG_copy(w->a,t);
-}
-
-/* Set w=conj(x) */
-/* SU= 16 */
-void FP2_conj(FP2 *w,FP2 *x)
-{
-	BIG_copy(w->a,x->a);
-	FP_neg(w->b,x->b);
-}
-
-/* Set w=x+y */
-/* SU= 16 */
-void FP2_add(FP2 *w,FP2 *x,FP2 *y)
-{
-	FP_add(w->a,x->a,y->a);
-	FP_add(w->b,x->b,y->b);
-}
-
-/* Set w=x-y */
-/* SU= 16 */
-void FP2_sub(FP2 *w,FP2 *x,FP2 *y)
-{
-	FP2 m;
-	FP2_neg(&m,y);
-	FP2_add(w,x,&m);
-}
-
-/* Set w=s*x, where s is FP */
-/* SU= 16 */
-void FP2_pmul(FP2 *w,FP2 *x,BIG s)
-{
-	FP_mul(w->a,x->a,s);
-	FP_mul(w->b,x->b,s);
-}
-
-/* SU= 16 */
-/* Set w=s*x, where s is int */
-void FP2_imul(FP2 *w,FP2 *x,int s)
-{
-	FP_imul(w->a,x->a,s);
-	FP_imul(w->b,x->b,s);
-}
-
-/* Set w=x^2 */
-/* SU= 128 */
-void FP2_sqr(FP2 *w,FP2 *x)
-{
-	BIG w1,w3,mb;
-
-	FP_mul(w3,x->a,x->b); /* norms x */
-	FP_add(w1,x->a,x->b); /* w1#2 w1=2 */
-	FP_neg(mb,x->b);      /* mb#2 mb=1 */
-	FP_add(w->a,x->a,mb);   /* w2#3 w2=3 */
-	FP_mul(w->a,w1,w->a);     /* w->a#2 w->a=1 w1&w2=6 w1*w2=2 */
-
-	FP_add(w->b,w3,w3); /* w->b#4 w->b=2 */
-
-	FP2_norm(w);
-
-}
-
-
-/* Set w=x*y */
-/* SU= 168 */
-void FP2_mul(FP2 *w,FP2 *x,FP2 *y)
-{
-	BIG w1,w2,w5,mw;
-
-	FP_mul(w1,x->a,y->a);  /* norms x  */
-	FP_mul(w2,x->b,y->b);  /* and y */
-
-	FP_add(w5,x->a,x->b);
-
-	FP_add(w->b,y->a,y->b);
-
-	FP_mul(w->b,w->b,w5);
-	FP_add(mw,w1,w2);
-	FP_neg(mw,mw);
-
-	FP_add(w->b,w->b,mw);
-	FP_add(mw,w1,mw);
-	FP_add(w->a,w1,mw);
-
-	FP2_norm(w);
-
-}
-
-/* output FP2 in hex format [a,b] */
-/* SU= 16 */
-void FP2_output(FP2 *w)
-{
-	FP2_reduce(w);
-	FP_redc(w->a); FP_redc(w->b);
-	printf("[");BIG_output(w->a);printf(",");BIG_output(w->b);printf("]");
-	FP_nres(w->a); FP_nres(w->b);
-}
-
-/* SU= 8 */
-void FP2_rawoutput(FP2 *w)
-{
-	printf("[");BIG_rawoutput(w->a);printf(",");BIG_rawoutput(w->b);printf("]");
-}
-
-
-/* Set w=1/x */
-/* SU= 128 */
-void FP2_inv(FP2 *w,FP2 *x)
-{
-	BIG m,w1,w2;
-	BIG_rcopy(m,Modulus);
-	FP2_norm(x);
-	FP_sqr(w1,x->a);
-	FP_sqr(w2,x->b);
-	FP_add(w1,w1,w2);
-
-	FP_redc(w1);
-	BIG_invmodp(w1,w1,m);
-	FP_nres(w1);
-	FP_mul(w->a,x->a,w1);
-	FP_neg(w1,w1);
-	FP_mul(w->b,x->b,w1);
-//	FP2_norm(w);
-}
-
-
-/* Set w=x/2 */
-/* SU= 16 */
-void FP2_div2(FP2 *w,FP2 *x)
-{
-	FP_div2(w->a,x->a);
-	FP_div2(w->b,x->b);
-}
-
-/* Set w*=(1+sqrt(-1)) */
-/* where X^2-(1+sqrt(-1)) is irreducible for FP4, assumes p=3 mod 8 */
-
-/* SU= 128 */
-void FP2_mul_ip(FP2 *w)
-{
-	FP2 t;
-	BIG z;
-
-	FP2_norm(w);
-	FP2_copy(&t,w);
-
-	BIG_copy(z,w->a);
-	FP_neg(w->a,w->b);
-	BIG_copy(w->b,z);
-
-	FP2_add(w,&t,w);
-	FP2_norm(w);
-}
-
-/* Set w/=(1+sqrt(-1)) */
-/* SU= 88 */
-void FP2_div_ip(FP2 *w)
-{
-	FP2 t;
-	FP2_norm(w);
-	FP_add(t.a,w->a,w->b);
-	FP_sub(t.b,w->b,w->a);
-	FP2_div2(w,&t);
-}
-
-/* SU= 8 */
-/* normalise a and b components of w */
-void FP2_norm(FP2 *w)
-{
-	BIG_norm(w->a);
-	BIG_norm(w->b);
-}
-
-/* Set w=a^b mod m */
-/* SU= 208 */
-void FP2_pow(FP2 *r,FP2* a,BIG b)
-{
-	FP2 w;
-	BIG z,one,zilch;
-	int bt;
-
-	BIG_norm(b);
-	BIG_copy(z,b);
-	FP2_copy(&w,a);
-	FP_one(one);
-	BIG_zero(zilch);
-	FP2_from_FP(r,one);
-	while(1)
-	{
-		bt=BIG_parity(z);
-		BIG_shr(z,1);
-		if (bt) FP2_mul(r,r,&w);
-		if (BIG_comp(z,zilch)==0) break;
-		FP2_sqr(&w,&w);
-	}
-	FP2_reduce(r);
-}
-
-/* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */
-/* returns true if u is QR */
-
-int FP2_sqrt(FP2 *w,FP2 *u)
-{
-	BIG w1,w2,q;
-	FP2_copy(w,u);
-	if (FP2_iszilch(w)) return 1;
-
-	BIG_rcopy(q,Modulus);
-	FP_sqr(w1,w->b);
-	FP_sqr(w2,w->a);
-	FP_add(w1,w1,w2);
-	if (!FP_qr(w1))
-	{
-		FP2_zero(w);
-		return 0;
-	}
-	FP_sqrt(w1,w1);
-	FP_add(w2,w->a,w1);
-	FP_div2(w2,w2);
-	if (!FP_qr(w2))
-	{
-		FP_sub(w2,w->a,w1);
-		FP_div2(w2,w2);
-		if (!FP_qr(w2))
-		{
-			FP2_zero(w);
-			return 0;
-		}
-	}
-	FP_sqrt(w2,w2);
-	BIG_copy(w->a,w2);
-	FP_add(w2,w2,w2);
-	FP_redc(w2);
-	BIG_invmodp(w2,w2,q);
-	FP_nres(w2);
-	FP_mul(w->b,w->b,w2);
-	return 1;
-}
-
-/*
-int main()
-{
-	int i;
-	FP2 w,z;
-	BIG a,b,e;
-	BIG pp1,pm1;
-	BIG_unity(a); BIG_unity(b);
-	FP2_from_BIGs(&w,a,b);
-//	for (i=0;i<100;i++)
-//	{
-//		BIG_randomnum(a); BIG_randomnum(b);
-//		BIG_mod(a,Modulus); BIG_mod(b,Modulus);
-//		FP2_from_FPs(&w,a,b);
-//		FP2_output(&w);
-//		FP2_inv(&z,&w);
-//				FP2_output(&z);
-//		FP2_inv(&z,&z);
-//				FP2_output(&z);
-//				FP2_output(&w);
-//		if (FP2_comp(&w,&z)!=1) printf("error \n");
-//		else printf("OK \n");
-//	}
-//exit(0);
-	printf("w= "); FP2_output(&w); printf("\n");
-	BIG_zero(e); BIG_inc(e,27);
-	FP2_pow(&w,&w,e);
-	FP2_output(&w);
-exit(0);
-	BIG_rcopy(pp1,Modulus);
-	BIG_rcopy(pm1,Modulus);
-	BIG_inc(pp1,1);
-	BIG_dec(pm1,1);
-	BIG_norm(pp1);
-	BIG_norm(pm1);
-	FP2_pow(&w,&w,pp1);
-	FP2_pow(&w,&w,pm1);
-	FP2_output(&w);
-}
-
-*/
diff --git a/c/fp4.c b/c/fp4.c
deleted file mode 100755
index 0dafe0d..0000000
--- a/c/fp4.c
+++ /dev/null
@@ -1,636 +0,0 @@
-/*
-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.
-*/
-
-/* AMCL Fp^4 functions */
-/* SU=m, m is Stack Usage (no lazy )*/
-
-/* FP4 elements are of the form a+ib, where i is sqrt(-1+sqrt(-1)) */
-
-#include "amcl.h"
-
-/* test x==0 ? */
-/* SU= 8 */
-int FP4_iszilch(FP4 *x)
-{
-	if (FP2_iszilch(&(x->a)) && FP2_iszilch(&(x->b))) return 1;
-	return 0;
-}
-
-/* test x==1 ? */
-/* SU= 8 */
-int FP4_isunity(FP4 *x)
-{
-	if (FP2_isunity(&(x->a)) && FP2_iszilch(&(x->b))) return 1;
-	return 0;
-}
-
-/* test is w real? That is in a+ib test b is zero */
-int FP4_isreal(FP4 *w)
-{
-	return FP2_iszilch(&(w->b));
-}
-
-/* return 1 if x==y, else 0 */
-/* SU= 16 */
-int FP4_equals(FP4 *x,FP4 *y)
-{
-	if (FP2_equals(&(x->a),&(y->a)) && FP2_equals(&(x->b),&(y->b)))
-			return 1;
-	return 0;
-}
-
-/* set FP4 from two FP2s */
-/* SU= 16 */
-void FP4_from_FP2s(FP4 *w,FP2 * x,FP2* y)
-{
-		FP2_copy(&(w->a), x);
-		FP2_copy(&(w->b), y);
-}
-
-/* set FP4 from FP2 */
-/* SU= 8 */
-void FP4_from_FP2(FP4 *w,FP2 *x)
-{
-	FP2_copy(&(w->a), x);
-	FP2_zero(&(w->b));
-}
-
-/* FP4 copy w=x */
-/* SU= 16 */
-void FP4_copy(FP4 *w,FP4 *x)
-{
-	if (w==x) return;
-	FP2_copy(&(w->a), &(x->a));
-	FP2_copy(&(w->b), &(x->b));
-}
-
-/* FP4 w=0 */
-/* SU= 8 */
-void FP4_zero(FP4 *w)
-{
-	FP2_zero(&(w->a));
-	FP2_zero(&(w->b));
-}
-
-/* FP4 w=1 */
-/* SU= 8 */
-void FP4_one(FP4 *w)
-{
-	FP2_one(&(w->a));
-	FP2_zero(&(w->b));
-}
-
-/* Set w=-x */
-/* SU= 160 */
-void FP4_neg(FP4 *w,FP4 *x)
-{ /* Just one field neg */
-	FP2 m,t;
-	FP2_add(&m,&(x->a),&(x->b));
-	FP2_neg(&m,&m);
-	FP2_norm(&m);
-	FP2_add(&t,&m,&(x->b));
-	FP2_add(&(w->b),&m,&(x->a));
-	FP2_copy(&(w->a),&t);
-}
-
-/* Set w=conj(x) */
-/* SU= 16 */
-void FP4_conj(FP4 *w,FP4 *x)
-{
-	FP2_copy(&(w->a), &(x->a));
-	FP2_neg(&(w->b), &(x->b));
-	FP2_norm(&(w->b));
-}
-
-/* Set w=-conj(x) */
-/* SU= 16 */
-void FP4_nconj(FP4 *w,FP4 *x)
-{
-	FP2_copy(&(w->b),&(x->b));
-	FP2_neg(&(w->a), &(x->a));
-	FP2_norm(&(w->a));
-}
-
-/* Set w=x+y */
-/* SU= 16 */
-void FP4_add(FP4 *w,FP4 *x,FP4 *y)
-{
-	FP2_add(&(w->a), &(x->a), &(y->a));
-	FP2_add(&(w->b), &(x->b), &(y->b));
-}
-
-/* Set w=x-y */
-/* SU= 160 */
-void FP4_sub(FP4 *w,FP4 *x,FP4 *y)
-{
-	FP4 my;
-	FP4_neg(&my, y);
-	FP4_add(w, x, &my);
-
-}
-/* SU= 8 */
-/* reduce all components of w mod Modulus */
-void FP4_reduce(FP4 *w)
-{
-	 FP2_reduce(&(w->a));
-	 FP2_reduce(&(w->b));
-}
-
-/* SU= 8 */
-/* normalise all elements of w */
-void FP4_norm(FP4 *w)
-{
-	 FP2_norm(&(w->a));
-	 FP2_norm(&(w->b));
-}
-
-/* Set w=s*x, where s is FP2 */
-/* SU= 16 */
-void FP4_pmul(FP4 *w,FP4 *x,FP2 *s)
-{
-	FP2_mul(&(w->a),&(x->a),s);
-	FP2_mul(&(w->b),&(x->b),s);
-}
-
-/* SU= 16 */
-/* Set w=s*x, where s is int */
-void FP4_imul(FP4 *w,FP4 *x,int s)
-{
-	FP2_imul(&(w->a),&(x->a),s);
-	FP2_imul(&(w->b),&(x->b),s);
-}
-
-/* Set w=x^2 */
-/* SU= 232 */
-void FP4_sqr(FP4 *w,FP4 *x)
-{
-	FP2 t1,t2,t3;
-
-	FP2_mul(&t3,&(x->a),&(x->b)); /* norms x */
-	FP2_copy(&t2,&(x->b));
-	FP2_add(&t1,&(x->a),&(x->b));
-	FP2_mul_ip(&t2);
-
-	FP2_add(&t2,&(x->a),&t2);
-
-	FP2_mul(&(w->a),&t1,&t2);
-
-	FP2_copy(&t2,&t3);
-	FP2_mul_ip(&t2);
-
-	FP2_add(&t2,&t2,&t3);
-
-	FP2_neg(&t2,&t2);
-	FP2_add(&(w->a),&(w->a),&t2);  /* a=(a+b)(a+i^2.b)-i^2.ab-ab = a*a+ib*ib */
-	FP2_add(&(w->b),&t3,&t3);  /* b=2ab */
-
-	FP4_norm(w);
-}
-
-/* Set w=x*y */
-/* SU= 312 */
-void FP4_mul(FP4 *w,FP4 *x,FP4 *y)
-{
-
-	FP2 t1,t2,t3,t4;
-	FP2_mul(&t1,&(x->a),&(y->a)); /* norms x */
-	FP2_mul(&t2,&(x->b),&(y->b)); /* and y */
-	FP2_add(&t3,&(y->b),&(y->a));
-	FP2_add(&t4,&(x->b),&(x->a));
-
-
-	FP2_mul(&t4,&t4,&t3); /* (xa+xb)(ya+yb) */
-	FP2_sub(&t4,&t4,&t1);
-#if CHUNK<64
-	FP2_norm(&t4);
-#endif
-	FP2_sub(&(w->b),&t4,&t2);
-	FP2_mul_ip(&t2);
-	FP2_add(&(w->a),&t2,&t1);
-
-	FP4_norm(w);
-}
-
-/* output FP4 in format [a,b] */
-/* SU= 8 */
-void FP4_output(FP4 *w)
-{
-	printf("[");
-	FP2_output(&(w->a));
-	printf(",");
-	FP2_output(&(w->b));
-	printf("]");
-}
-
-/* SU= 8 */
-void FP4_rawoutput(FP4 *w)
-{
-	printf("[");
-	FP2_rawoutput(&(w->a));
-	printf(",");
-	FP2_rawoutput(&(w->b));
-	printf("]");
-}
-
-/* Set w=1/x */
-/* SU= 160 */
-void FP4_inv(FP4 *w,FP4 *x)
-{
-	FP2 t1,t2;
-	FP2_sqr(&t1,&(x->a));
-	FP2_sqr(&t2,&(x->b));
-	FP2_mul_ip(&t2);
-	FP2_sub(&t1,&t1,&t2);
-	FP2_inv(&t1,&t1);
-	FP2_mul(&(w->a),&t1,&(x->a));
-	FP2_neg(&t1,&t1);
-	FP2_mul(&(w->b),&t1,&(x->b));
-}
-
-/* w*=i where i = sqrt(-1+sqrt(-1)) */
-/* SU= 200 */
-void FP4_times_i(FP4 *w)
-{
-	BIG z;
-	FP2 s,t;
-#if CHUNK<64
-	FP4_norm(w);
-#endif
-	FP2_copy(&t,&(w->b));
-
-	FP2_copy(&s,&t);
-
-	BIG_copy(z,s.a);
-	FP_neg(s.a,s.b);
-	BIG_copy(s.b,z);
-
-	FP2_add(&t,&t,&s);
-#if CHUNK<64
-	FP2_norm(&t);
-#endif
-	FP2_copy(&(w->b),&(w->a));
-	FP2_copy(&(w->a),&t);
-}
-
-/* Set w=w^p using Frobenius */
-/* SU= 16 */
-void FP4_frob(FP4 *w,FP2 *f)
-{
-	FP2_conj(&(w->a),&(w->a));
-	FP2_conj(&(w->b),&(w->b));
-	FP2_mul( &(w->b),f,&(w->b));
-}
-
-/* Set r=a^b mod m */
-/* SU= 240 */
-void FP4_pow(FP4 *r,FP4* a,BIG b)
-{
-	FP4 w;
-	BIG z,zilch;
-	int bt;
-
-	BIG_zero(zilch);
-	BIG_norm(b);
-	BIG_copy(z,b);
-	FP4_copy(&w,a);
-	FP4_one(r);
-
-	while(1)
-	{
-		bt=BIG_parity(z);
-		BIG_shr(z,1);
-		if (bt) FP4_mul(r,r,&w);
-		if (BIG_comp(z,zilch)==0) break;
-		FP4_sqr(&w,&w);
-	}
-	FP4_reduce(r);
-}
-
-/* SU= 304 */
-/* XTR xtr_a function */
-void FP4_xtr_A(FP4 *r,FP4 *w,FP4 *x,FP4 *y,FP4 *z)
-{
-	FP4 t1,t2;
-
-	FP4_copy(r,x);
-
-	FP4_sub(&t1,w,y);
-
-	FP4_pmul(&t1,&t1,&(r->a));
-	FP4_add(&t2,w,y);
-	FP4_pmul(&t2,&t2,&(r->b));
-	FP4_times_i(&t2);
-
-	FP4_add(r,&t1,&t2);
-	FP4_add(r,r,z);
-
-	FP4_norm(r);
-}
-
-/* SU= 152 */
-/* XTR xtr_d function */
-void FP4_xtr_D(FP4 *r,FP4 *x)
-{
-	FP4 w;
-	FP4_copy(r,x);
-	FP4_conj(&w,r);
-	FP4_add(&w,&w,&w);
-	FP4_sqr(r,r);
-	FP4_sub(r,r,&w);
-	FP4_reduce(r);    /* reduce here as multiple calls trigger automatic reductions */
-}
-
-/* SU= 728 */
-/* r=x^n using XTR method on traces of FP12s */
-void FP4_xtr_pow(FP4 *r,FP4 *x,BIG n)
-{
-	int i,par,nb;
-	BIG v;
-	FP2 w;
-	FP4 t,a,b,c;
-
-	BIG_zero(v); BIG_inc(v,3);
-	FP2_from_BIG(&w,v);
-	FP4_from_FP2(&a,&w);
-	FP4_copy(&b,x);
-	FP4_xtr_D(&c,x);
-
-	BIG_norm(n); par=BIG_parity(n); BIG_copy(v,n); BIG_shr(v,1);
-	if (par==0) {BIG_dec(v,1); BIG_norm(v);}
-
-	nb=BIG_nbits(v);
-
-	for (i=nb-1;i>=0;i--)
-	{
-		if (!BIG_bit(v,i))
-		{
-			FP4_copy(&t,&b);
-			FP4_conj(x,x);
-			FP4_conj(&c,&c);
-			FP4_xtr_A(&b,&a,&b,x,&c);
-			FP4_conj(x,x);
-			FP4_xtr_D(&c,&t);
-			FP4_xtr_D(&a,&a);
-		}
-		else
-		{
-			FP4_conj(&t,&a);
-			FP4_xtr_D(&a,&b);
-			FP4_xtr_A(&b,&c,&b,x,&t);
-			FP4_xtr_D(&c,&c);
-		}
-	}
-	if (par==0) FP4_copy(r,&c);
-	else FP4_copy(r,&b);
-	FP4_reduce(r);
-}
-
-/* SU= 872 */
-/* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */
-void FP4_xtr_pow2(FP4 *r,FP4 *ck,FP4 *cl,FP4 *ckml,FP4 *ckm2l,BIG a,BIG b)
-{
-	int i,f2,nb;
-	BIG d,e,w;
-	FP4 t,cu,cv,cumv,cum2v;
-
-	BIG_norm(a);
-	BIG_norm(b);
-	BIG_copy(e,a);
-	BIG_copy(d,b);
-	FP4_copy(&cu,ck);
-	FP4_copy(&cv,cl);
-	FP4_copy(&cumv,ckml);
-	FP4_copy(&cum2v,ckm2l);
-
-	f2=0;
-	while (BIG_parity(d)==0 && BIG_parity(e)==0)
-	{
-		BIG_shr(d,1);
-		BIG_shr(e,1);
-		f2++;
-	}
-	while (BIG_comp(d,e)!=0)
-	{
-		if (BIG_comp(d,e)>0)
-		{
-			BIG_imul(w,e,4); BIG_norm(w);
-			if (BIG_comp(d,w)<=0)
-			{
-				BIG_copy(w,d);
-				BIG_copy(d,e);
-				BIG_sub(e,w,e); BIG_norm(e);
-				FP4_xtr_A(&t,&cu,&cv,&cumv,&cum2v);
-				FP4_conj(&cum2v,&cumv);
-				FP4_copy(&cumv,&cv);
-				FP4_copy(&cv,&cu);
-				FP4_copy(&cu,&t);
-			}
-			else if (BIG_parity(d)==0)
-			{
-				BIG_shr(d,1);
-				FP4_conj(r,&cum2v);
-				FP4_xtr_A(&t,&cu,&cumv,&cv,r);
-				FP4_xtr_D(&cum2v,&cumv);
-				FP4_copy(&cumv,&t);
-				FP4_xtr_D(&cu,&cu);
-			}
-			else if (BIG_parity(e)==1)
-			{
-				BIG_sub(d,d,e); BIG_norm(d);
-				BIG_shr(d,1);
-				FP4_xtr_A(&t,&cu,&cv,&cumv,&cum2v);
-				FP4_xtr_D(&cu,&cu);
-				FP4_xtr_D(&cum2v,&cv);
-				FP4_conj(&cum2v,&cum2v);
-				FP4_copy(&cv,&t);
-			}
-			else
-			{
-				BIG_copy(w,d);
-				BIG_copy(d,e); BIG_shr(d,1);
-				BIG_copy(e,w);
-				FP4_xtr_D(&t,&cumv);
-				FP4_conj(&cumv,&cum2v);
-				FP4_conj(&cum2v,&t);
-				FP4_xtr_D(&t,&cv);
-				FP4_copy(&cv,&cu);
-				FP4_copy(&cu,&t);
-			}
-		}
-		if (BIG_comp(d,e)<0)
-		{
-			BIG_imul(w,d,4); BIG_norm(w);
-			if (BIG_comp(e,w)<=0)
-			{
-				BIG_sub(e,e,d); BIG_norm(e);
-				FP4_xtr_A(&t,&cu,&cv,&cumv,&cum2v);
-				FP4_copy(&cum2v,&cumv);
-				FP4_copy(&cumv,&cu);
-				FP4_copy(&cu,&t);
-			}
-			else if (BIG_parity(e)==0)
-			{
-				BIG_copy(w,d);
-				BIG_copy(d,e); BIG_shr(d,1);
-				BIG_copy(e,w);
-				FP4_xtr_D(&t,&cumv);
-				FP4_conj(&cumv,&cum2v);
-				FP4_conj(&cum2v,&t);
-				FP4_xtr_D(&t,&cv);
-				FP4_copy(&cv,&cu);
-				FP4_copy(&cu,&t);
-			}
-			else if (BIG_parity(d)==1)
-			{
-				BIG_copy(w,e);
-				BIG_copy(e,d);
-				BIG_sub(w,w,d); BIG_norm(w);
-				BIG_copy(d,w); BIG_shr(d,1);
-				FP4_xtr_A(&t,&cu,&cv,&cumv,&cum2v);
-				FP4_conj(&cumv,&cumv);
-				FP4_xtr_D(&cum2v,&cu);
-				FP4_conj(&cum2v,&cum2v);
-				FP4_xtr_D(&cu,&cv);
-				FP4_copy(&cv,&t);
-			}
-			else
-			{
-				BIG_shr(d,1);
-				FP4_conj(r,&cum2v);
-				FP4_xtr_A(&t,&cu,&cumv,&cv,r);
-				FP4_xtr_D(&cum2v,&cumv);
-				FP4_copy(&cumv,&t);
-				FP4_xtr_D(&cu,&cu);
-			}
-		}
-	}
-	FP4_xtr_A(r,&cu,&cv,&cumv,&cum2v);
-	for (i=0;i<f2;i++)	FP4_xtr_D(r,r);
-	FP4_xtr_pow(r,r,d);
-}
-/*
-int main(){
-		FP2 w0,w1,f;
-		FP4 w,t;
-		FP4 c1,c2,c3,c4,cr;
-		BIG a,b;
-		BIG e,e1,e2;
-		BIG p,md;
-
-
-		BIG_rcopy(md,Modulus);
-		//Test w^(P^4) = w mod p^2
-		BIG_zero(a); BIG_inc(a,27);
-		BIG_zero(b); BIG_inc(b,45);
-		FP2_from_BIGs(&w0,a,b);
-
-		BIG_zero(a); BIG_inc(a,33);
-		BIG_zero(b); BIG_inc(b,54);
-		FP2_from_BIGs(&w1,a,b);
-
-		FP4_from_FP2s(&w,&w0,&w1);
-		FP4_reduce(&w);
-
-		printf("w= ");
-		FP4_output(&w);
-		printf("\n");
-
-
-		FP4_copy(&t,&w);
-
-
-		BIG_copy(p,md);
-		FP4_pow(&w,&w,p);
-
-		printf("w^p= ");
-		FP4_output(&w);
-		printf("\n");
-//exit(0);
-
-		BIG_rcopy(a,CURVE_Fra);
-		BIG_rcopy(b,CURVE_Frb);
-		FP2_from_BIGs(&f,a,b);
-
-		FP4_frob(&t,&f);
-		printf("w^p= ");
-		FP4_output(&t);
-		printf("\n");
-
-		FP4_pow(&w,&w,p);
-		FP4_pow(&w,&w,p);
-		FP4_pow(&w,&w,p);
-		printf("w^p4= ");
-		FP4_output(&w);
-		printf("\n");
-
-// Test 1/(1/x) = x mod p^4
-		FP4_from_FP2s(&w,&w0,&w1);
-		printf("Test Inversion \nw= ");
-		FP4_output(&w);
-		printf("\n");
-
-		FP4_inv(&w,&w);
-		printf("1/w mod p^4 = ");
-		FP4_output(&w);
-		printf("\n");
-
-		FP4_inv(&w,&w);
-		printf("1/(1/w) mod p^4 = ");
-		FP4_output(&w);
-		printf("\n");
-
-		BIG_zero(e); BIG_inc(e,12);
-
-
-
-	//	FP4_xtr_A(&w,&t,&w,&t,&t);
-		FP4_xtr_pow(&w,&w,e);
-
-		printf("w^e= ");
-		FP4_output(&w);
-		printf("\n");
-
-
-		BIG_zero(a); BIG_inc(a,37);
-		BIG_zero(b); BIG_inc(b,17);
-		FP2_from_BIGs(&w0,a,b);
-
-		BIG_zero(a); BIG_inc(a,49);
-		BIG_zero(b); BIG_inc(b,31);
-		FP2_from_BIGs(&w1,a,b);
-
-		FP4_from_FP2s(&c1,&w0,&w1);
-		FP4_from_FP2s(&c2,&w0,&w1);
-		FP4_from_FP2s(&c3,&w0,&w1);
-		FP4_from_FP2s(&c4,&w0,&w1);
-
-		BIG_zero(e1); BIG_inc(e1,3331);
-		BIG_zero(e2); BIG_inc(e2,3372);
-
-		FP4_xtr_pow2(&w,&c1,&w,&c2,&c3,e1,e2);
-
-		printf("c^e= ");
-		FP4_output(&w);
-		printf("\n");
-
-
-		return 0;
-}
-*/
-
diff --git a/c/gcm.c b/c/gcm.c
deleted file mode 100755
index c36b3fb..0000000
--- a/c/gcm.c
+++ /dev/null
@@ -1,368 +0,0 @@
-/*
-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.
-*/
-
-
-
-/*
- * Implementation of the AES-GCM Encryption/Authentication
- *
- * Some restrictions..
- * 1. Only for use with AES
- * 2. Returned tag is always 128-bits. Truncate at your own risk.
- * 3. The order of function calls must follow some rules
- *
- * Typical sequence of calls..
- * 1. call GCM_init
- * 2. call GCM_add_header any number of times, as long as length of header is multiple of 16 bytes (block size)
- * 3. call GCM_add_header one last time with any length of header
- * 4. call GCM_add_cipher any number of times, as long as length of cipher/plaintext is multiple of 16 bytes
- * 5. call GCM_add_cipher one last time with any length of cipher/plaintext
- * 6. call GCM_finish to extract the tag.
- *
- * See http://www.mindspring.com/~dmcgrew/gcm-nist-6.pdf
- */
-/* SU=m, m is Stack Usage */
-
-#include <stdlib.h>
-#include <string.h>
-#include "amcl.h"
-
-#define NB 4
-#define MR_TOBYTE(x) ((uchar)((x)))
-
-static unsign32 pack(const uchar *b)
-{ /* pack bytes into a 32-bit Word */
-    return ((unsign32)b[0]<<24)|((unsign32)b[1]<<16)|((unsign32)b[2]<<8)|(unsign32)b[3];
-}
-
-static void unpack(unsign32 a,uchar *b)
-{ /* unpack bytes from a word */
-    b[3]=MR_TOBYTE(a);
-    b[2]=MR_TOBYTE(a>>8);
-    b[1]=MR_TOBYTE(a>>16);
-    b[0]=MR_TOBYTE(a>>24);
-}
-
-static void precompute(gcm *g,uchar *H)
-{ /* precompute small 2k bytes gf2m table of x^n.H */
-	int i,j;
-	unsign32 *last,*next,b;
-
-	for (i=j=0;i<NB;i++,j+=4) g->table[0][i]=pack((uchar *)&H[j]);
-
-	for (i=1;i<128;i++)
-	{
-		next=g->table[i]; last=g->table[i-1]; b=0;
-		for (j=0;j<NB;j++) {next[j]=b|(last[j])>>1; b=last[j]<<31;}
-		if (b) next[0]^=0xE1000000; /* irreducible polynomial */
-	}
-}
-
-/* SU= 32 */
-static void gf2mul(gcm *g)
-{ /* gf2m mul - Z=H*X mod 2^128 */
-	int i,j,m,k;
-	unsign32 P[4];
-	uchar b;
-
-	P[0]=P[1]=P[2]=P[3]=0;
-	j=8; m=0;
-	for (i=0;i<128;i++)
-	{
-		b=(g->stateX[m]>>(--j))&1;
-		if (b) for (k=0;k<NB;k++) P[k]^=g->table[i][k];
-		if (j==0)
-		{
-			j=8; m++;
-			if (m==16) break;
-		}
-	}
-	for (i=j=0;i<NB;i++,j+=4) unpack(P[i],(uchar *)&g->stateX[j]);
-}
-
-/* SU= 32 */
-static void GCM_wrap(gcm *g)
-{ /* Finish off GHASH */
-	int i,j;
-	unsign32 F[4];
-	uchar L[16];
-
-/* convert lengths from bytes to bits */
-	F[0]=(g->lenA[0]<<3)|(g->lenA[1]&0xE0000000)>>29;
-	F[1]=g->lenA[1]<<3;
-	F[2]=(g->lenC[0]<<3)|(g->lenC[1]&0xE0000000)>>29;
-	F[3]=g->lenC[1]<<3;
-	for (i=j=0;i<NB;i++,j+=4) unpack(F[i],(uchar *)&L[j]);
-
-	for (i=0;i<16;i++) g->stateX[i]^=L[i];
-	gf2mul(g);
-}
-
-static int GCM_ghash(gcm *g,char *plain,int len)
-{
-	int i,j=0;
-	unsign32 counter;
-	uchar B[16];
-	if (g->status==GCM_ACCEPTING_HEADER) g->status=GCM_ACCEPTING_CIPHER;
-	if (g->status!=GCM_ACCEPTING_CIPHER) return 0;
-
-	while (j<len)
-	{
-		for (i=0;i<16 && j<len;i++)
-		{
-			g->stateX[i]^=plain[j++];
-			g->lenC[1]++; if (g->lenC[1]==0) g->lenC[0]++;
-		}
-		gf2mul(g);
-	}
-	if (len%16!=0) g->status=GCM_NOT_ACCEPTING_MORE;
-	return 1;
-}
-
-/* SU= 48 */
-/* Initialize GCM mode */
-void GCM_init(gcm* g,char *key,int niv,char *iv)
-{ /* iv size niv is usually 12 bytes (96 bits). AES key is 16 bytes */
-	int i;
-	uchar H[16];
-	for (i=0;i<16;i++) {H[i]=0; g->stateX[i]=0;}
-
-	AES_init(&(g->a),ECB,key,iv);
-	AES_ecb_encrypt(&(g->a),H);     /* E(K,0) */
-	precompute(g,H);
-
-	g->lenA[0]=g->lenC[0]=g->lenA[1]=g->lenC[1]=0;
-	if (niv==12)
-	{
-		for (i=0;i<12;i++) g->a.f[i]=iv[i];
-		unpack((unsign32)1,(uchar *)&(g->a.f[12]));  /* initialise IV */
-		for (i=0;i<16;i++) g->Y_0[i]=g->a.f[i];
-	}
-	else
-	{
-		g->status=GCM_ACCEPTING_CIPHER;
-		GCM_ghash(g,iv,niv); /* GHASH(H,0,IV) */
-		GCM_wrap(g);
-		for (i=0;i<16;i++) {g->a.f[i]=g->stateX[i];g->Y_0[i]=g->a.f[i];g->stateX[i]=0;}
-		g->lenA[0]=g->lenC[0]=g->lenA[1]=g->lenC[1]=0;
-	}
-	g->status=GCM_ACCEPTING_HEADER;
-}
-
-/* SU= 24 */
-/* Add Header data - included but not encrypted */
-int GCM_add_header(gcm* g,char *header,int len)
-{ /* Add some header. Won't be encrypted, but will be authenticated. len is length of header */
-	int i,j=0;
-	if (g->status!=GCM_ACCEPTING_HEADER) return 0;
-
-	while (j<len)
-	{
-		for (i=0;i<16 && j<len;i++)
-		{
-			g->stateX[i]^=header[j++];
-			g->lenA[1]++; if (g->lenA[1]==0) g->lenA[0]++;
-		}
-		gf2mul(g);
-	}
-	if (len%16!=0) g->status=GCM_ACCEPTING_CIPHER;
-	return 1;
-}
-
-/* SU= 48 */
-/* Add Plaintext - included and encrypted */
-int GCM_add_plain(gcm *g,char *cipher,char *plain,int len)
-{ /* Add plaintext to extract ciphertext, len is length of plaintext.  */
-	int i,j=0;
-	unsign32 counter;
-	uchar B[16];
-	if (g->status==GCM_ACCEPTING_HEADER) g->status=GCM_ACCEPTING_CIPHER;
-	if (g->status!=GCM_ACCEPTING_CIPHER) return 0;
-
-	while (j<len)
-	{
-		counter=pack((uchar *)&(g->a.f[12]));
-		counter++;
-		unpack(counter,(uchar *)&(g->a.f[12]));  /* increment counter */
-		for (i=0;i<16;i++) B[i]=g->a.f[i];
-		AES_ecb_encrypt(&(g->a),B);        /* encrypt it  */
-
-		for (i=0;i<16 && j<len;i++)
-		{
-			cipher[j]=plain[j]^B[i];
-			g->stateX[i]^=cipher[j++];
-			g->lenC[1]++; if (g->lenC[1]==0) g->lenC[0]++;
-		}
-		gf2mul(g);
-	}
-	if (len%16!=0) g->status=GCM_NOT_ACCEPTING_MORE;
-	return 1;
-}
-
-/* SU= 48 */
-/* Add Ciphertext - decrypts to plaintext */
-int GCM_add_cipher(gcm *g,char *plain,char *cipher,int len)
-{ /* Add ciphertext to extract plaintext, len is length of ciphertext. */
-	int i,j=0;
-	unsign32 counter;
-	uchar B[16];
-	if (g->status==GCM_ACCEPTING_HEADER) g->status=GCM_ACCEPTING_CIPHER;
-	if (g->status!=GCM_ACCEPTING_CIPHER) return 0;
-
-	while (j<len)
-	{
-		counter=pack((uchar *)&(g->a.f[12]));
-		counter++;
-		unpack(counter,(uchar *)&(g->a.f[12]));  /* increment counter */
-		for (i=0;i<16;i++) B[i]=g->a.f[i];
-		AES_ecb_encrypt(&(g->a),B);        /* encrypt it  */
-		for (i=0;i<16 && j<len;i++)
-		{
-			plain[j]=cipher[j]^B[i];
-			g->stateX[i]^=cipher[j++];
-			g->lenC[1]++; if (g->lenC[1]==0) g->lenC[0]++;
-		}
-		gf2mul(g);
-	}
-	if (len%16!=0) g->status=GCM_NOT_ACCEPTING_MORE;
-	return 1;
-}
-
-/* SU= 16 */
-/* Finish and extract Tag */
-void GCM_finish(gcm *g,char *tag)
-{ /* Finish off GHASH and extract tag (MAC) */
-	int i;
-
-	GCM_wrap(g);
-
-/* extract tag */
-	if (tag!=NULL)
-	{
-		AES_ecb_encrypt(&(g->a),g->Y_0);        /* E(K,Y0) */
-		for (i=0;i<16;i++) g->Y_0[i]^=g->stateX[i];
-		for (i=0;i<16;i++) {tag[i]=g->Y_0[i];g->Y_0[i]=g->stateX[i]=0;}
-	}
-	g->status=GCM_FINISHED;
-	AES_end(&(g->a));
-}
-
-
-// Compile with
-// gcc -O2 amcl_gcm.c amcl_aes.c -o amcl_gcm.exe
-/* SU= 16
-*/
-/*
-static void hex2bytes(char *hex,char *bin)
-{
-	int i;
-	char v;
-	int len=strlen(hex);
-	for (i = 0; i < len/2; i++) {
-        char c = hex[2*i];
-        if (c >= '0' && c <= '9') {
-            v = c - '0';
-        } else if (c >= 'A' && c <= 'F') {
-            v = c - 'A' + 10;
-        } else if (c >= 'a' && c <= 'f') {
-            v = c - 'a' + 10;
-        } else {
-            v = 0;
-        }
-        v <<= 4;
-        c = hex[2*i + 1];
-        if (c >= '0' && c <= '9') {
-            v += c - '0';
-        } else if (c >= 'A' && c <= 'F') {
-            v += c - 'A' + 10;
-        } else if (c >= 'a' && c <= 'f') {
-            v += c - 'a' + 10;
-        } else {
-            v = 0;
-        }
-        bin[i] = v;
-    }
-}
-*/
-/*
-int main()
-{
-	int i;
-
-	char* KT="feffe9928665731c6d6a8f9467308308";
-	char* MT="d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39";
-	char* HT="feedfacedeadbeeffeedfacedeadbeefabaddad2";
-//	char* NT="cafebabefacedbaddecaf888";
-// Tag should be 5bc94fbc3221a5db94fae95ae7121a47
-	char* NT="9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b";
-// Tag should be 619cc5aefffe0bfa462af43c1699d050
-
-
-	int len=strlen(MT)/2;
-	int lenH=strlen(HT)/2;
-	int lenK=strlen(KT)/2;
-	int lenIV=strlen(NT)/2;
-
-	char T[16];   // Tag
-	char K[16];   // AES Key
-	char H[64];   // Header - to be included in Authentication, but not encrypted
-	char N[100];   // IV - Initialisation vector
-	char M[100];  // Plaintext to be encrypted/authenticated
-	char C[100];  // Ciphertext
-	char P[100];  // Recovered Plaintext
-
-	gcm g;
-
-    hex2bytes(MT, M);
-    hex2bytes(HT, H);
-    hex2bytes(NT, N);
-	hex2bytes(KT, K);
-
- 	printf("Plaintext=\n");
-	for (i=0;i<len;i++) printf("%02x",(unsigned char)M[i]);
-	printf("\n");
-
-	GCM_init(&g,K,lenIV,N);
-	GCM_add_header(&g,H,lenH);
-	GCM_add_plain(&g,C,M,len);
-	GCM_finish(&g,T);
-
-	printf("Ciphertext=\n");
-	for (i=0;i<len;i++) printf("%02x",(unsigned char)C[i]);
-	printf("\n");
-
-	printf("Tag=\n");
-	for (i=0;i<16;i++) printf("%02x",(unsigned char)T[i]);
-	printf("\n");
-
-	GCM_init(&g,K,lenIV,N);
-	GCM_add_header(&g,H,lenH);
-	GCM_add_cipher(&g,P,C,len);
-	GCM_finish(&g,T);
-
- 	printf("Plaintext=\n");
-	for (i=0;i<len;i++) printf("%02x",(unsigned char)P[i]);
-	printf("\n");
-
-	printf("Tag=\n");
-	for (i=0;i<16;i++) printf("%02x",(unsigned char)T[i]);
-	printf("\n");
-}
-
-*/
diff --git a/c/hash.c b/c/hash.c
deleted file mode 100755
index 2d11437..0000000
--- a/c/hash.c
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
-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.
-*/
-
-/*
- * Implementation of the Secure Hashing Algorithm (SHA-256)
- *
- * Generates a 256 bit message digest. It should be impossible to come
- * come up with two messages that hash to the same value ("collision free").
- *
- * For use with byte-oriented messages only. Could/Should be speeded
- * up by unwinding loops in HASH_transform(), and assembly patches.
- */
-/* SU=m, m is Stack Usage */
-
-#include "amcl.h"
-
-#define H0 0x6A09E667L
-#define H1 0xBB67AE85L
-#define H2 0x3C6EF372L
-#define H3 0xA54FF53AL
-#define H4 0x510E527FL
-#define H5 0x9B05688CL
-#define H6 0x1F83D9ABL
-#define H7 0x5BE0CD19L
-
-static const unsign32 K[64]={
-0x428a2f98L,0x71374491L,0xb5c0fbcfL,0xe9b5dba5L,0x3956c25bL,0x59f111f1L,0x923f82a4L,0xab1c5ed5L,
-0xd807aa98L,0x12835b01L,0x243185beL,0x550c7dc3L,0x72be5d74L,0x80deb1feL,0x9bdc06a7L,0xc19bf174L,
-0xe49b69c1L,0xefbe4786L,0x0fc19dc6L,0x240ca1ccL,0x2de92c6fL,0x4a7484aaL,0x5cb0a9dcL,0x76f988daL,
-0x983e5152L,0xa831c66dL,0xb00327c8L,0xbf597fc7L,0xc6e00bf3L,0xd5a79147L,0x06ca6351L,0x14292967L,
-0x27b70a85L,0x2e1b2138L,0x4d2c6dfcL,0x53380d13L,0x650a7354L,0x766a0abbL,0x81c2c92eL,0x92722c85L,
-0xa2bfe8a1L,0xa81a664bL,0xc24b8b70L,0xc76c51a3L,0xd192e819L,0xd6990624L,0xf40e3585L,0x106aa070L,
-0x19a4c116L,0x1e376c08L,0x2748774cL,0x34b0bcb5L,0x391c0cb3L,0x4ed8aa4aL,0x5b9cca4fL,0x682e6ff3L,
-0x748f82eeL,0x78a5636fL,0x84c87814L,0x8cc70208L,0x90befffaL,0xa4506cebL,0xbef9a3f7L,0xc67178f2L};
-
-#define PAD  0x80
-#define ZERO 0
-
-/* functions */
-
-#define S(n,x) (((x)>>n) | ((x)<<(32-n)))
-#define R(n,x) ((x)>>n)
-
-#define Ch(x,y,z)  ((x&y)^(~(x)&z))
-#define Maj(x,y,z) ((x&y)^(x&z)^(y&z))
-#define Sig0(x)    (S(2,x)^S(13,x)^S(22,x))
-#define Sig1(x)    (S(6,x)^S(11,x)^S(25,x))
-#define theta0(x)  (S(7,x)^S(18,x)^R(3,x))
-#define theta1(x)  (S(17,x)^S(19,x)^R(10,x))
-
-/* SU= 72 */
-static void HASH_transform(hash *sh)
-{ /* basic transformation step */
-    unsign32 a,b,c,d,e,f,g,h,t1,t2;
-    int j;
-    for (j=16;j<64;j++)
-        sh->w[j]=theta1(sh->w[j-2])+sh->w[j-7]+theta0(sh->w[j-15])+sh->w[j-16];
-
-    a=sh->h[0]; b=sh->h[1]; c=sh->h[2]; d=sh->h[3];
-    e=sh->h[4]; f=sh->h[5]; g=sh->h[6]; h=sh->h[7];
-
-    for (j=0;j<64;j++)
-    { /* 64 times - mush it up */
-        t1=h+Sig1(e)+Ch(e,f,g)+K[j]+sh->w[j];
-        t2=Sig0(a)+Maj(a,b,c);
-        h=g; g=f; f=e;
-        e=d+t1;
-        d=c;
-        c=b;
-        b=a;
-        a=t1+t2;
-    }
-
-    sh->h[0]+=a; sh->h[1]+=b; sh->h[2]+=c; sh->h[3]+=d;
-    sh->h[4]+=e; sh->h[5]+=f; sh->h[6]+=g; sh->h[7]+=h;
-}
-
-/* Initialise Hash function */
-void HASH_init(hash *sh)
-{ /* re-initialise */
-    int i;
-    for (i=0;i<64;i++) sh->w[i]=0L;
-    sh->length[0]=sh->length[1]=0L;
-    sh->h[0]=H0;
-    sh->h[1]=H1;
-    sh->h[2]=H2;
-    sh->h[3]=H3;
-    sh->h[4]=H4;
-    sh->h[5]=H5;
-    sh->h[6]=H6;
-    sh->h[7]=H7;
-}
-
-/* process a single byte */
-void HASH_process(hash *sh,int byte)
-{ /* process the next message byte */
-    int cnt;
-//printf("byt= %x\n",byte);
-    cnt=(int)((sh->length[0]/32)%16);
-
-    sh->w[cnt]<<=8;
-    sh->w[cnt]|=(unsign32)(byte&0xFF);
-
-    sh->length[0]+=8;
-    if (sh->length[0]==0L) { sh->length[1]++; sh->length[0]=0L; }
-    if ((sh->length[0]%512)==0) HASH_transform(sh);
-}
-
-/* SU= 24 */
-/* Generate 32-byte Hash */
-void HASH_hash(hash *sh,char digest[32])
-{ /* pad message and finish - supply digest */
-    int i;
-    unsign32 len0,len1;
-    len0=sh->length[0];
-    len1=sh->length[1];
-    HASH_process(sh,PAD);
-    while ((sh->length[0]%512)!=448) HASH_process(sh,ZERO);
-    sh->w[14]=len1;
-    sh->w[15]=len0;
-    HASH_transform(sh);
-    for (i=0;i<32;i++)
-    { /* convert to bytes */
-        digest[i]=(char)((sh->h[i/4]>>(8*(3-i%4))) & 0xffL);
-    }
-    HASH_init(sh);
-}
-
-/* test program: should produce digest  */
-
-//248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1
-
-/*
-#include <stdio.h>
-#include "amcl.h"
-
-char test[]="abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
-
-int main()
-{
-    char digest[32];
-    int i;
-    hash sh;
-    HASH_init(&sh);
-    for (i=0;test[i]!=0;i++)
-		HASH_process(&sh,test[i]);
-
-    HASH_hash(&sh,digest);
-    for (i=0;i<32;i++) printf("%02x",(unsigned char)digest[i]);
-    printf("\n");
-    return 0;
-}
-
-*/
-
diff --git a/c/maxstack.c b/c/maxstack.c
deleted file mode 100755
index 3eb436f..0000000
--- a/c/maxstack.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
-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.
-*/
-
-/*
-	How to determine maximum stack usage
-	1. Compile this file *with no optimization*, for example gcc -c maxstack.c
-	2. Rename your main() function to mymain()
-	3. Compile with normal level of optimization, linking to maxstack.o for example gcc maxstack.o -O3 myprogram.c -o myprogam
-	4. Execute myprogram
-	5. Program runs, at end prints out maximum stack usage
-
-	Caveat Code!
-	Mike Scott October 2014
-*/
-
-#include <stdio.h>
-
-#define MAXSTACK 65536  /* greater than likely stack requirement */
-
-extern void mymain();
-
-void start()
-{
-	char stack[MAXSTACK];
-	int i;
-	for (i=0;i<MAXSTACK;i++) stack[i]=0x55;
-}
-
-void finish()
-{
-	char stack[MAXSTACK];
-	int i;
-	for (i=0;i<MAXSTACK;i++)
-		if (stack[i]!=0x55) break;
-	printf("Max Stack usage = %d\n",MAXSTACK-i);
-}
-
-int main()
-{
- start();
-
- mymain();
-
- finish();
- return 0;
-}
diff --git a/c/mpin.c b/c/mpin.c
deleted file mode 100755
index b494833..0000000
--- a/c/mpin.c
+++ /dev/null
@@ -1,1153 +0,0 @@
-/*
-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.
-*/
-
-/* MPIN Functions */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include "mpin.h"
-
-#define ROUNDUP(a,b) ((a)-1)/(b)+1
-
-/* general purpose hashing functions */
-static void start_hash(hash *sha)
-{
-	HASH_init(sha);
-}
-
-static void add_to_hash(hash *sha,octet *x)
-{
-	int i;
-	for (i=0;i<x->len;i++) {/*printf("%d,",(unsigned char)x->val[i]);*/ HASH_process(sha,x->val[i]);  }
-}
-
-static void finish_hash(hash *sha,octet *w)
-{
-	int i;
-	char hh[32];
-    HASH_hash(sha,hh);
-
-    OCT_empty(w);
-    OCT_jbytes(w,hh,32);
-    for (i=0;i<32;i++) hh[i]=0;
-}
-
-/* these next two functions help to implement elligator squared - http://eprint.iacr.org/2014/043 */
-/* maps a random u to a point on the curve */
-static void map(ECP *P,BIG u,int cb)
-{
-	BIG x,q;
-
-	BIG_rcopy(q,Modulus);
-	BIG_copy(x,u);
-	BIG_mod(x,q);
-
-	while (!ECP_setx(P,x,cb))
-		BIG_inc(x,1);
-}
-
-/* returns u derived from P. Random value in range 1 to return value should then be added to u */
-static int unmap(BIG u,int *cb,ECP *P)
-{
-	int s,r=0;
-	BIG x;
-
-	s=ECP_get(x,x,P);
-	BIG_copy(u,x);
-	do
-	{
-		BIG_dec(u,1);
-		r++;
-	}
-	while (!ECP_setx(P,u,s));
-	ECP_setx(P,x,s);
-
-	*cb=s;
-
-	return r;
-}
-
-/* map octet string to point on curve */
-static void mapit(octet *h,ECP *P)
-{
-	BIG q,px;
-	BIG_fromBytes(px,h->val);
-	BIG_rcopy(q,Modulus);
-	BIG_mod(px,q);
-
-	while (!ECP_setx(P,px,0))
-		BIG_inc(px,1);
-}
-
-/* needed for SOK */
-static void mapit2(octet *h,ECP2 *Q)
-{
-	BIG q,one,Fx,Fy,x,hv;
-	FP2 X;
-	ECP2 T,K;
-	BIG_fromBytes(hv,h->val);
-	BIG_rcopy(q,Modulus);
-	BIG_one(one);
-	BIG_mod(hv,q);
-
-	for (;;)
-	{
-		FP2_from_BIGs(&X,one,hv);
-		if (ECP2_setx(Q,&X)) break;
-		BIG_inc(hv,1);
-	}
-
-/* Fast Hashing to G2 - Fuentes-Castaneda, Knapp and Rodriguez-Henriquez */
-	BIG_rcopy(Fx,CURVE_Fra);
-	BIG_rcopy(Fy,CURVE_Frb);
-	FP2_from_BIGs(&X,Fx,Fy);
-	BIG_rcopy(x,CURVE_Bnx);
-
-	ECP2_copy(&T,Q);
-	ECP2_mul(&T,x);
-	ECP2_neg(&T);  /* our x is negative */
-	ECP2_copy(&K,&T);
-	ECP2_dbl(&K);
-	ECP2_add(&K,&T);
-	ECP2_affine(&K);
-
-	ECP2_frob(&K,&X);
-	ECP2_frob(Q,&X); ECP2_frob(Q,&X); ECP2_frob(Q,&X);
-	ECP2_add(Q,&T);
-	ECP2_add(Q,&K);
-	ECP2_frob(&T,&X); ECP2_frob(&T,&X);
-	ECP2_add(Q,&T);
-	ECP2_affine(Q);
-}
-
-/* Hash number (optional) and octet to octet */
-static void hashit(int n,octet *x,octet *h)
-{
-    int i,c[4];
-    hash sha;
-    char hh[HASH_BYTES];
-	BIG px;
-
-    HASH_init(&sha);
-	if (n>0)
-    {
-        c[0]=(n>>24)&0xff;
-        c[1]=(n>>16)&0xff;
-        c[2]=(n>>8)&0xff;
-        c[3]=(n)&0xff;
-		for (i=0;i<4;i++) HASH_process(&sha,c[i]);
-    }
-    for (i=0;i<x->len;i++) HASH_process(&sha,x->val[i]);
-    HASH_hash(&sha,hh);
-    OCT_empty(h);
-    OCT_jbytes(h,hh,HASH_BYTES);
-    for (i=0;i<32;i++) hh[i]=0;
-}
-
-unsign32 MPIN_today(void)
-{ /* return time in slots since epoch */
-	unsign32 ti=(unsign32)time(NULL);
-	return (long)(ti/(60*TIME_SLOT_MINUTES));
-}
-
-/* Initialise a Cryptographically Strong Random Number Generator from
-   an octet of raw random data */
-
-void MPIN_CREATE_CSPRNG(csprng *RNG,octet *RAW)
-{
-    RAND_seed(RNG,RAW->len,RAW->val);
-}
-
-void MPIN_KILL_CSPRNG(csprng *RNG)
-{
-    RAND_clean(RNG);
-}
-
-void MPIN_HASH_ID(octet *ID,octet *HID)
-{
-	hashit(0,ID,HID);
-}
-
-/* these next two functions implement elligator squared - http://eprint.iacr.org/2014/043 */
-/* Elliptic curve point E in format (0x04,x,y} is converted to form {0x0-,u,v} */
-/* Note that u and v are indistinguisible from random strings */
-int MPIN_ENCODING(csprng *RNG,octet *E)
-{
-	int rn,m,su,sv,res=0;
-
-    BIG q,u,v;
-    ECP P,W;
-
-	if (!ECP_fromOctet(&P,E)) res=MPIN_INVALID_POINT;
-
-	if (res==0)
-	{
-		BIG_rcopy(q,Modulus);
-
-		BIG_randomnum(u,q,RNG);
-
-		su=RAND_byte(RNG); if (su<0) su=-su; su%=2;
-		map(&W,u,su);
-		ECP_sub(&P,&W);
-
-		rn=unmap(v,&sv,&P);
-		m=RAND_byte(RNG); if (m<0) m=-m; m%=rn;
-		BIG_inc(v,m+1);
-		E->val[0]=su+2*sv;
-		BIG_toBytes(&(E->val[1]),u);
-		BIG_toBytes(&(E->val[PFS+1]),v);
-	}
-
-    return res;
-}
-
-int MPIN_DECODING(octet *D)
-{
-	int su,sv;
-    BIG u,v;
-    ECP P,W;
-    int res=0;
-
-	if ((D->val[0]&0x04)!=0) res=MPIN_INVALID_POINT;
-	if (res==0)
-	{
-
-		BIG_fromBytes(u,&(D->val[1]));
-		BIG_fromBytes(v,&(D->val[PFS+1]));
-
-		su=D->val[0]&1;
-		sv=(D->val[0]>>1)&1;
-
-		map(&W,u,su);
-		map(&P,v,sv);
-
-		ECP_add(&P,&W);
-		ECP_toOctet(D,&P);
-	}
-    return res;
-}
-
-/* R=R1+R2 in group G1 */
-int MPIN_RECOMBINE_G1(octet *R1,octet *R2,octet *R)
-{
-    ECP P,T;
-    int res=0;
-    if (res==0)
-    {
-		if (!ECP_fromOctet(&P,R1)) res=MPIN_INVALID_POINT;
-		if (!ECP_fromOctet(&T,R2)) res=MPIN_INVALID_POINT;
-	}
-    if (res==0)
-    {
-		ECP_add(&P,&T);
-		ECP_toOctet(R,&P);
-	}
-    return res;
-}
-
-/* W=W1+W2 in group G2 */
-int MPIN_RECOMBINE_G2(octet *W1,octet *W2,octet *W)
-{
-    ECP2 Q,T;
-    int res=0;
-	if (!ECP2_fromOctet(&Q,W1)) res=MPIN_INVALID_POINT;
-	if (!ECP2_fromOctet(&T,W2)) res=MPIN_INVALID_POINT;
-    if (res==0)
-    {
-		ECP2_add(&Q,&T);
-		ECP2_toOctet(W,&Q);
-	}
-    return res;
-}
-
-/* create random secret S */
-int MPIN_RANDOM_GENERATE(csprng *RNG,octet* S)
-{
-    BIG r,s;
-	BIG_rcopy(r,CURVE_Order);
-	BIG_randomnum(s,r,RNG);
-	BIG_toBytes(S->val,s);
-	S->len=32;
-    return 0;
-}
-
-/* Extract PIN from TOKEN for identity CID */
-int MPIN_EXTRACT_PIN(octet *CID,int pin,octet *TOKEN)
-{
-    ECP P,R;
-    int plen,res=0;
-	char h[HASH_BYTES];
-	octet H={0,sizeof(h),h};
-
-	if (!ECP_fromOctet(&P,TOKEN))  res=MPIN_INVALID_POINT;
-	if (res==0)
-	{
-		hashit(-1,CID,&H);
-		mapit(&H,&R);
-
-		pin%=MAXPIN;
-
-		ECP_pinmul(&R,pin,PBLEN);
-		ECP_sub(&P,&R);
-
-		ECP_toOctet(TOKEN,&P);
-	}
-    return res;
-}
-
-/* Implement step 2 on client side of MPin protocol - SEC=-(x+y)*SEC */
-int MPIN_CLIENT_2(octet *X,octet *Y,octet *SEC)
-{
-    BIG px,py,r;
-    ECP P;
-    int res=0;
-	BIG_rcopy(r,CURVE_Order);
-	if (!ECP_fromOctet(&P,SEC)) res=MPIN_INVALID_POINT;
-	if (res==0)
-	{
-		BIG_fromBytes(px,X->val);
-		BIG_fromBytes(py,Y->val);
-		BIG_add(px,px,py);
-		BIG_mod(px,r);
-		BIG_sub(px,r,px);
-		PAIR_G1mul(&P,px);
-		ECP_toOctet(SEC,&P);
-	}
-    return res;
-}
-
-/*
- W=x*H(G);
- if RNG == NULL then X is passed in
- if RNG != NULL the X is passed out
- if type=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve
-*/
-
-int MPIN_GET_G1_MULTIPLE(csprng *RNG,int type,octet *X,octet *G,octet *W)
-{
-	ECP P;
-	BIG r,x;
-	int res=0;
-	if (RNG!=NULL)
-	{
-		BIG_rcopy(r,CURVE_Order);
-		BIG_randomnum(x,r,RNG);
-		X->len=32;
-		BIG_toBytes(X->val,x);
-	}
-	else
-		BIG_fromBytes(x,X->val);
-
-	if (type==0)
-	{
-		if (!ECP_fromOctet(&P,G)) res=MPIN_INVALID_POINT;
-	}
-	else mapit(G,&P);
-
-	if (res==0)
-	{
-		PAIR_G1mul(&P,x);
-		ECP_toOctet(W,&P);
-	}
-	return res;
-}
-
-
-/* Client secret CST=s*H(CID) where CID is client ID and s is master secret */
-/* CID is hashed externally */
-int MPIN_GET_CLIENT_SECRET(octet *S,octet *CID,octet *CST)
-{
-	return MPIN_GET_G1_MULTIPLE(NULL,1,S,CID,CST);
-}
-
-/* Implement step 1 on client side of MPin protocol */
-int MPIN_CLIENT_1(int date,octet *CLIENT_ID,csprng *RNG,octet *X,int pin,octet *TOKEN,octet *SEC,octet *xID,octet *xCID,octet *PERMIT)
-{
-    BIG r,x;
-    ECP P,T,W;
-    int plen,res=0;
-	char h[HASH_BYTES];
-	octet H={0,sizeof(h),h};
-
-	BIG_rcopy(r,CURVE_Order);
-	if (RNG!=NULL)
-	{
-		BIG_randomnum(x,r,RNG);
-		X->len=32;
-		BIG_toBytes(X->val,x);
-	}
-	else
-		BIG_fromBytes(x,X->val);
-
-	hashit(-1,CLIENT_ID,&H);
-	mapit(&H,&P);
-
-	if (!ECP_fromOctet(&T,TOKEN)) res=MPIN_INVALID_POINT;
-
-	if (res==0)
-	{
-		pin%=MAXPIN;
-
-		ECP_copy(&W,&P);				// W=H(ID)
-		ECP_pinmul(&W,pin,PBLEN);			// W=alpha.H(ID)
-		ECP_add(&T,&W);					// T=Token+alpha.H(ID) = s.H(ID)
-
-		if (date)
-		{
-			if (!ECP_fromOctet(&W,PERMIT)) res=MPIN_INVALID_POINT;
-			ECP_add(&T,&W);					// SEC=s.H(ID)+s.H(T|ID)
-			hashit(date,&H,&H);
-			mapit(&H,&W);
-			if (xID!=NULL)
-			{
-				PAIR_G1mul(&P,x);				// P=x.H(ID)
-				ECP_toOctet(xID,&P);  // xID
-				PAIR_G1mul(&W,x);               // W=x.H(T|ID)
-				ECP_add(&P,&W);
-			}
-			else
-			{
-				ECP_add(&P,&W);
-				PAIR_G1mul(&P,x);
-			}
-			if (xCID!=NULL) ECP_toOctet(xCID,&P);  // U
-		}
-		else
-		{
-			if (xID!=NULL)
-			{
-				PAIR_G1mul(&P,x);				// P=x.H(ID)
-				ECP_toOctet(xID,&P);  // xID
-			}
-		}
-	}
-
-	if (res==0)
-		ECP_toOctet(SEC,&T);  // V
-
-    return res;
-}
-
-/* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */
-int MPIN_GET_SERVER_SECRET(octet *S,octet *SST)
-{
-    BIG r,s;
-	FP2 qx,qy;
-    ECP2 Q;
-    int res=0;
-
-	BIG_rcopy(r,CURVE_Order);
-    BIG_rcopy(qx.a,CURVE_Pxa); FP_nres(qx.a);
-    BIG_rcopy(qx.b,CURVE_Pxb); FP_nres(qx.b);
-    BIG_rcopy(qy.a,CURVE_Pya); FP_nres(qy.a);
-    BIG_rcopy(qy.b,CURVE_Pyb); FP_nres(qy.b);
-	ECP2_set(&Q,&qx,&qy);
-
-	if (res==0)
-	{
-		BIG_fromBytes(s,S->val);
-		PAIR_G2mul(&Q,s);
-		ECP2_toOctet(SST,&Q);
-    }
-
-    return res;
-}
-
-
-/* Time Permit CTT=s*H(date|H(CID)) where s is master secret */
-int MPIN_GET_CLIENT_PERMIT(int date,octet *S,octet *CID,octet *CTT)
-{
-    BIG s;
-    ECP P;
-	char h[HASH_BYTES];
-	octet H={0,sizeof(h),h};
-
-	hashit(date,CID,&H);
-
-	mapit(&H,&P);
-	BIG_fromBytes(s,S->val);
-	PAIR_G1mul(&P,s);
-
-	ECP_toOctet(CTT,&P);
-    return 0;
-}
-
-// if date=0 only use HID, set HCID=NULL
-// if date and !PE, use set HID=NULL and use HCID only
-// if date and PE, use HID and HCID
-
-/* Outputs H(CID) and H(CID)+H(T|H(CID)) for time permits. If no time permits set HTID=NULL */
-void MPIN_SERVER_1(int date,octet *CID,octet *HID,octet *HTID)
-{
-  char h[HASH_BYTES];
-  octet H={0,sizeof(h),h};
-  ECP P,R;
-
-#ifdef USE_ANONYMOUS
-  mapit(CID,&P);
-#else 
-  hashit(-1,CID,&H);
-  mapit(&H,&P);
-#endif
-
-  if (date) {
-    if (HID!=NULL) {
-      ECP_toOctet(HID,&P);
-    }
-#ifdef USE_ANONYMOUS
-    hashit(date,CID,&H);
-#else
-    hashit(date,&H,&H);
-#endif
-    mapit(&H,&R);
-    ECP_add(&P,&R);
-    ECP_toOctet(HTID,&P);
-  } else {
-    ECP_toOctet(HID,&P);
-  }
-
-}
-
-/* Implement M-Pin on server side */
-int MPIN_SERVER_2(int date,octet *HID,octet *HTID,octet *Y,octet *SST,octet *xID,octet *xCID,octet *mSEC,octet *E,octet *F)
-{
-    BIG a,px,py,y;
-	FP2 qx,qy;
-	FP12 g;
-    ECP2 Q,sQ;
-	ECP P,R;
-    int res=0;
-
-    BIG_rcopy(qx.a,CURVE_Pxa); FP_nres(qx.a);
-    BIG_rcopy(qx.b,CURVE_Pxb); FP_nres(qx.b);
-    BIG_rcopy(qy.a,CURVE_Pya); FP_nres(qy.a);
-    BIG_rcopy(qy.b,CURVE_Pyb); FP_nres(qy.b);
-
-	if (!ECP2_set(&Q,&qx,&qy)) res=MPIN_INVALID_POINT;
-
-	if (res==0)
-	{
-		if (!ECP2_fromOctet(&sQ,SST)) res=MPIN_INVALID_POINT;
-	}
-
-	if (res==0)
-	{
-		if (date)
-		{
-			BIG_fromBytes(px,&(xCID->val[1]));
-			BIG_fromBytes(py,&(xCID->val[PFS+1]));
-		}
-		else
-		{
-			BIG_fromBytes(px,&(xID->val[1]));
-			BIG_fromBytes(py,&(xID->val[PFS+1]));
-		}
-		if (!ECP_set(&R,px,py)) res=MPIN_INVALID_POINT; // x(A+AT)
-	}
-	if (res==0)
-	{
-		BIG_fromBytes(y,Y->val);
-		if (date)
-		{
-			if (!ECP_fromOctet(&P,HTID))  res=MPIN_INVALID_POINT;
-		}
-		else
-		{
-			if (!ECP_fromOctet(&P,HID))  res=MPIN_INVALID_POINT;
-		}
-	}
-	if (res==0)
-	{
-		PAIR_G1mul(&P,y);  // y(A+AT)
-		ECP_add(&P,&R); // x(A+AT)+y(A+T)
-		if (!ECP_fromOctet(&R,mSEC))  res=MPIN_INVALID_POINT; // V
-	}
-	if (res==0)
-	{
-		PAIR_double_ate(&g,&Q,&R,&sQ,&P);
-		PAIR_fexp(&g);
-
-		if (!FP12_isunity(&g))
-		{
-			if (HID!=NULL && xID!=NULL && E!=NULL && F !=NULL)
-			{ /* xID is set to NULL if there is no way to calculate PIN error */
-				FP12_toOctet(E,&g);
-
-/* Note error is in the PIN, not in the time permit! Hence the need to exclude Time Permit from this check */
-
-				if (date)
-				{
-					if (!ECP_fromOctet(&P,HID)) res=MPIN_INVALID_POINT;
-					if (!ECP_fromOctet(&R,xID)) res=MPIN_INVALID_POINT; // U
-
-					if (res==0)
-					{
-						PAIR_G1mul(&P,y);  // yA
-						ECP_add(&P,&R); // yA+xA
-					}
-				}
-				if (res==0)
-				{
-					PAIR_ate(&g,&Q,&P);
-					PAIR_fexp(&g);
-					FP12_toOctet(F,&g);
-				}
-			}
-			res=MPIN_BAD_PIN;
-		}
-	}
-
-    return res;
-}
-
-#if MAXPIN==10000
-#define MR_TS 10  /* 2^10/10 approx = sqrt(MAXPIN) */
-#define TRAP 200  /* 2*sqrt(MAXPIN) */
-#endif
-
-#if MAXPIN==1000000
-#define MR_TS 14
-#define TRAP 2000
-#endif
-
-/* Pollards kangaroos used to return PIN error */
-int MPIN_KANGAROO(octet *E,octet *F)
-{
-	int i,j,m,s,dn,dm,steps;
-	int distance[MR_TS];
-	FP12 ge,gf,t,table[MR_TS];
-    int res=0;
-
-	FP12_fromOctet(&ge,E);
-	FP12_fromOctet(&gf,F);
-
-	FP12_copy(&t,&gf);
-
-	for (s=1,m=0;m<MR_TS;m++)
-	{
-		distance[m]=s;
-		FP12_copy(&table[m],&t);
-		s*=2;
-		FP12_usqr(&t,&t);
-		FP12_reduce(&t);
-	}
-
-	FP12_one(&t);
-
-	for (dn=0,j=0;j<TRAP;j++)
-	{
-		i=t.a.a.a[0]%MR_TS;
-		FP12_mul(&t,&table[i]);
-		FP12_reduce(&t);
-		dn+=distance[i];
-	}
-
-	FP12_conj(&gf,&t);
-	steps=0; dm=0;
-	while (dm-dn<MAXPIN)
-	{
-		steps++;
-		if (steps>4*TRAP) break;
-		i=ge.a.a.a[0]%MR_TS;
-		FP12_mul(&ge,&table[i]);
-		FP12_reduce(&ge);
-		dm+=distance[i];
-		if (FP12_equals(&ge,&t))
-		{
-			res=dm-dn;
-			break;
-		}
-		if (FP12_equals(&ge,&gf))
-		{
-			res=dn-dm;
-			break;
-		}
-	}
-	if (steps>4*TRAP || dm-dn>=MAXPIN) {res=0; }    /* Trap Failed  - probable invalid token */
-
-    return res;
-}
-
-/* Functions to support M-Pin Full */
-
-int MPIN_PRECOMPUTE(octet *TOKEN,octet *CID,octet *G1,octet *G2)
-{
-	ECP P,T;
-	ECP2 Q;
-	FP2 qx,qy;
-	FP12 g;
-	int res=0;
-
-	if (!ECP_fromOctet(&T,TOKEN)) res=MPIN_INVALID_POINT;
-
-	if (res==0)
-	{
-		mapit(CID,&P);
-
-		BIG_rcopy(qx.a,CURVE_Pxa); FP_nres(qx.a);
-		BIG_rcopy(qx.b,CURVE_Pxb); FP_nres(qx.b);
-		BIG_rcopy(qy.a,CURVE_Pya); FP_nres(qy.a);
-		BIG_rcopy(qy.b,CURVE_Pyb); FP_nres(qy.b);
-
-		if (!ECP2_set(&Q,&qx,&qy)) res=MPIN_INVALID_POINT;
-	}
-	if (res==0)
-	{
-		PAIR_ate(&g,&Q,&T);
-		PAIR_fexp(&g);
-		FP12_toOctet(G1,&g);
-		PAIR_ate(&g,&Q,&P);
-		PAIR_fexp(&g);
-		FP12_toOctet(G2,&g);
-	}
-	return res;
-}
-
-/* calculate common key on client side */
-/* wCID = w.(A+AT) */
-int MPIN_CLIENT_KEY(octet *G1,octet *G2,int pin,octet *R,octet *X,octet *H,octet *wCID,octet *CK)
-{
-	FP12 g1,g2;
-	FP4 c,cp,cpm1,cpm2;
-	FP2 f;
-	ECP W;
-        int res=0;
-	BIG r,z,x,q,m,a,b,h;
-	hash sha;
-	char ht[HASH_BYTES];
-	octet HT={0,sizeof(ht),ht};
-
-	FP12_fromOctet(&g1,G1);
-	FP12_fromOctet(&g2,G2);
-	BIG_fromBytes(z,R->val);
-	BIG_fromBytes(x,X->val);
-	BIG_fromBytes(h,H->val);
-
-	if (!ECP_fromOctet(&W,wCID)) res=MPIN_INVALID_POINT;
-
-	if (res==0)
-	{
-		BIG_rcopy(r,CURVE_Order);
-		BIG_add(z,z,h);    // new
-		BIG_mod(z,r);
-
-		PAIR_G1mul(&W,x);
-
-		BIG_rcopy(a,CURVE_Fra);
-		BIG_rcopy(b,CURVE_Frb);
-		FP2_from_BIGs(&f,a,b);
-
-		BIG_rcopy(q,Modulus);
-		BIG_copy(m,q);
-		BIG_mod(m,r);
-
-		BIG_copy(a,z);
-		BIG_mod(a,m);
-
-		BIG_copy(b,z);
-		BIG_sdiv(b,m);
-
-		FP12_pinpow(&g2,pin,PBLEN);
-		FP12_mul(&g1,&g2);
-
-		FP12_trace(&c,&g1);
-
-		FP12_copy(&g2,&g1);
-		FP12_frob(&g2,&f);
-		FP12_trace(&cp,&g2);
-
-		FP12_conj(&g1,&g1);
-		FP12_mul(&g2,&g1);
-		FP12_trace(&cpm1,&g2);
-		FP12_mul(&g2,&g1);
-		FP12_trace(&cpm2,&g2);
-
-		FP4_xtr_pow2(&c,&cp,&c,&cpm1,&cpm2,a,b);
-
-		HT.len=PFS;
-		start_hash(&sha);
-		BIG_copy(m,c.a.a); FP_redc(m); BIG_toBytes(&(HT.val[0]),m);
-		add_to_hash(&sha,&HT);
-		BIG_copy(m,c.a.b); FP_redc(m); BIG_toBytes(&(HT.val[0]),m);
-		add_to_hash(&sha,&HT);
-		BIG_copy(m,c.b.a); FP_redc(m); BIG_toBytes(&(HT.val[0]),m);
-		add_to_hash(&sha,&HT);
-		BIG_copy(m,c.b.b); FP_redc(m); BIG_toBytes(&(HT.val[0]),m);
-		add_to_hash(&sha,&HT);
-
-		ECP_get(a,b,&W);
-
-		BIG_toBytes(&(HT.val[0]),a);
-		add_to_hash(&sha,&HT);
-		BIG_toBytes(&(HT.val[0]),b);
-		add_to_hash(&sha,&HT);
-
-		finish_hash(&sha,&HT);
-		OCT_empty(CK);
-		OCT_jbytes(CK,HT.val,PAS);
-	}
-	return res;
-}
-
-/* calculate common key on server side */
-/* Z=r.A - no time permits involved */
-
-int MPIN_SERVER_KEY(octet *Z,octet *SST,octet *W,octet *H,octet *HID,octet *xID,octet *xCID,octet *SK)
-{
-	int res=0;
-	FP12 g;
-	FP4 c;
-	FP2 qx,qy;
-	ECP R,U,A;
-	ECP2 sQ;
-	BIG w,x,y,h;
-	hash sha;
-	char ht[HASH_BYTES];
-	octet HT={0,sizeof(ht),ht};
-
-	if (!ECP2_fromOctet(&sQ,SST)) res=MPIN_INVALID_POINT;
-	if (!ECP_fromOctet(&R,Z)) res=MPIN_INVALID_POINT;
-
-
-	if (!ECP_fromOctet(&A,HID)) res=MPIN_INVALID_POINT;
-
-	// new
-	if (xCID!=NULL)
-	{
-		if (!ECP_fromOctet(&U,xCID)) res=MPIN_INVALID_POINT;
-	}
-	else
-	{
-		if (!ECP_fromOctet(&U,xID)) res=MPIN_INVALID_POINT;
-	}
-	BIG_fromBytes(w,W->val);
-	BIG_fromBytes(h,H->val);
-
-	if (res==0)
-	{
-		PAIR_G1mul(&A,h);
-		ECP_add(&R,&A);  // new
-
-		PAIR_ate(&g,&sQ,&R);
-		PAIR_fexp(&g);
-		PAIR_G1mul(&U,w);
-		FP12_trace(&c,&g);
-		HT.len=PFS;
-		start_hash(&sha);
-		BIG_copy(w,c.a.a); FP_redc(w); BIG_toBytes(&(HT.val[0]),w);
-		add_to_hash(&sha,&HT);
-		BIG_copy(w,c.a.b); FP_redc(w); BIG_toBytes(&(HT.val[0]),w);
-		add_to_hash(&sha,&HT);
-		BIG_copy(w,c.b.a); FP_redc(w); BIG_toBytes(&(HT.val[0]),w);
-		add_to_hash(&sha,&HT);
-		BIG_copy(w,c.b.b); FP_redc(w); BIG_toBytes(&(HT.val[0]),w);
-		add_to_hash(&sha,&HT);
-
-		ECP_get(x,y,&U);
-		BIG_toBytes(&(HT.val[0]),x);
-		add_to_hash(&sha,&HT);
-		BIG_toBytes(&(HT.val[0]),y);
-		add_to_hash(&sha,&HT);
-
-		finish_hash(&sha,&HT);
-		OCT_empty(SK);
-		OCT_jbytes(SK,HT.val,PAS);
-	}
-	return res;
-}
-
-unsign32 MPIN_GET_TIME(void)
-{
-  return (unsign32)time(NULL);
-}
-
-/* Generate Y = H(epoch, xCID/xID) */
-void MPIN_GET_Y(int TimeValue,octet *xCID,octet *Y)
-{
-  BIG q,y;
-  char h[HASH_BYTES];
-  octet H={0,sizeof(h),h};
-
-  hashit(TimeValue,xCID,&H);
-  BIG_fromBytes(y,H.val);
-  BIG_rcopy(q,CURVE_Order);
-  BIG_mod(y,q);
-  BIG_toBytes(Y->val,y);
-  Y->len=PGS;
-}
-
-/* One pass MPIN Client */
-int MPIN_CLIENT(int date,octet *ID,csprng *RNG,octet *X,int pin,octet *TOKEN,octet *V,octet *U,octet *UT,octet *TP,octet *MESSAGE,int TimeValue,octet *Y)
-{
-  int rtn=0;
-  char m[256];
-  octet M={0,sizeof(m),m};
-
-  octet *pID;
-  if (date == 0)
-    pID = U;
-  else
-    pID = UT;
-
-  rtn = MPIN_CLIENT_1(date,ID,RNG,X,pin,TOKEN,V,U,UT,TP);
-  if (rtn != 0)
-    return rtn;
-
-  OCT_joctet(&M,pID);
-  if (MESSAGE!=NULL) {
-    OCT_joctet(&M,MESSAGE);
-  }
-
-  MPIN_GET_Y(TimeValue,&M,Y);
-
-  rtn = MPIN_CLIENT_2(X,Y,V);
-  if (rtn != 0)
-    return rtn;
-
-  return 0;
-}
-
-/* One pass MPIN Server */
-int MPIN_SERVER(int date,octet *HID,octet *HTID,octet *Y,octet *SST,octet *U,octet *UT,octet *V,octet *E,octet *F,octet *ID,octet *MESSAGE,int TimeValue)
-{
-  int rtn=0;
-  char m[256];
-  octet M={0,sizeof(m),m};
-
-  octet *pID;
-  if (date == 0)
-    pID = U;
-  else
-    pID = UT;
-
-  MPIN_SERVER_1(date,ID,HID,HTID);
-
-  OCT_joctet(&M,pID);
-  if (MESSAGE!=NULL) {
-    OCT_joctet(&M,MESSAGE);
-  }
-
-  MPIN_GET_Y(TimeValue,&M,Y);
-
-  rtn = MPIN_SERVER_2(date,HID,HTID,Y,SST,U,UT,V,E,F);
-  if (rtn != 0)
-    return rtn;
-
-  return 0;
-}
-
-/* AES-GCM Encryption of octets, K is key, H is header,
-   P is plaintext, C is ciphertext, T is authentication tag */
-void MPIN_AES_GCM_ENCRYPT(octet *K,octet *IV,octet *H,octet *P,octet *C,octet *T)
-{
-  gcm g;
-  GCM_init(&g,K->val,IV->len,IV->val);
-  GCM_add_header(&g,H->val,H->len);
-  GCM_add_plain(&g,C->val,P->val,P->len);
-  C->len=P->len;
-  GCM_finish(&g,T->val);
-  T->len=16;
-}
-
-/* AES-GCM Decryption of octets, K is key, H is header,
-   P is plaintext, C is ciphertext, T is authentication tag */
-void MPIN_AES_GCM_DECRYPT(octet *K,octet *IV,octet *H,octet *C,octet *P,octet *T)
-{
-  gcm g;
-  GCM_init(&g,K->val,IV->len,IV->val);
-  GCM_add_header(&g,H->val,H->len);
-  GCM_add_cipher(&g,P->val,C->val,C->len);
-  P->len=C->len;
-  GCM_finish(&g,T->val);
-  T->len=16;
-}
-
-/* general purpose hash function w=hash(p|n|x|y) */
-static void hashitGen(octet *p,int n,octet *x,octet *y,octet *w)
-{
-    int i,c[4];
-    hash sha;
-    char hh[32];
-
-    HASH_init(&sha);
-    if (p!=NULL)
-        for (i=0;i<p->len;i++) HASH_process(&sha,p->val[i]);
-	if (n>0)
-    {
-        c[0]=(n>>24)&0xff;
-        c[1]=(n>>16)&0xff;
-        c[2]=(n>>8)&0xff;
-        c[3]=(n)&0xff;
-		for (i=0;i<4;i++) HASH_process(&sha,c[i]);
-    }
-    if (x!=NULL)
-        for (i=0;i<x->len;i++) HASH_process(&sha,x->val[i]);
-    if (y!=NULL)
-        for (i=0;i<y->len;i++) HASH_process(&sha,y->val[i]);
-
-
-    HASH_hash(&sha,hh);
-
-    OCT_empty(w);
-    OCT_jbytes(w,hh,32);
-    for (i=0;i<32;i++) hh[i]=0;
-}
-
-/* Calculate HMAC of m using key k. HMAC is tag of length olen */
-int MPIN_HMAC(octet *m,octet *k,int olen,octet *tag)
-{
-/* Input is from an octet m        *
- * olen is requested output length in bytes. k is the key  *
- * The output is the calculated tag */
-    int hlen,b;
-	char h[32],k0[64];
-    octet H={0,sizeof(h),h};
-	octet K0={0,sizeof(k0),k0};
-
-    hlen=32; b=64;
-    if (olen<4 || olen>hlen) return 0;
-
-    if (k->len > b) hashitGen(k,-1,NULL,NULL,&K0);
-    else            OCT_copy(&K0,k);
-
-    OCT_jbyte(&K0,0,b-K0.len);
-
-    OCT_xorbyte(&K0,0x36);
-
-    hashitGen(&K0,-1,m,NULL,&H);
-
-    OCT_xorbyte(&K0,0x6a);   /* 0x6a = 0x36 ^ 0x5c */
-    hashitGen(&K0,-1,&H,NULL,&H);
-
-    OCT_empty(tag);
-    OCT_jbytes(tag,H.val,olen);
-
-    return 1;
-}
-
-/* Password based Key Derivation Function */
-/* Input password p, salt s, and repeat count */
-/* Output key of length olen */
-void MPIN_PBKDF2(octet *p,octet *s,int rep,int olen,octet *key)
-{
-	int i,j,len,d=ROUNDUP(olen,32);
-	char f[PFS],u[PFS];
-	octet F={0,sizeof(f),f};
-	octet U={0,sizeof(u),u};
-	OCT_empty(key);
-
-	for (i=1;i<=d;i++)
-	{
-		len=s->len;
-		OCT_jint(s,i,4);
-		MPIN_HMAC(s,p,PFS,&F);
-		s->len=len;
-		OCT_copy(&U,&F);
-		for (j=2;j<=rep;j++)
-		{
-			MPIN_HMAC(&U,p,PFS,&U);
-			OCT_xor(&F,&U);
-		}
-
-		OCT_joctet(key,&F);
-	}
-	OCT_chop(key,NULL,olen);
-}
-
-/* Hash the M-Pin transcript - new */
-void MPIN_HASH_ALL(octet *HID,octet *xID,octet *xCID,octet *SEC,octet *Y,octet *R,octet *W,octet *H)
-{
-	char t[10*PFS+4];
-	octet T={0,sizeof(t),t};
-
-	OCT_joctet(&T,HID);
-	if (xCID!=NULL) OCT_joctet(&T,xCID);
-	else OCT_joctet(&T,xID);
-	OCT_joctet(&T,SEC);
-	OCT_joctet(&T,Y);
-	OCT_joctet(&T,R);
-	OCT_joctet(&T,W);
-
-	hashit(0,&T,H);
-}
-
-/*
-int MPIN_TEST_PAIRING(octet *CID,octet *R)
-{
-    BIG b,px;
-	FP2 qx,qy;
-	FP12 g;
-    ECP2 Q;
-	ECP P;
-    int res=0;
-
-	hashit(-1,CID,&P);
-	BIG_rcopy(qx.a,CURVE_Pxa); FP_nres(qx.a);
-	BIG_rcopy(qx.b,CURVE_Pxb); FP_nres(qx.b);
-	BIG_rcopy(qy.a,CURVE_Pya); FP_nres(qy.a);
-	BIG_rcopy(qy.b,CURVE_Pyb); FP_nres(qy.b);
-
-	if (!ECP2_set(&Q,&qx,&qy))  res=MPIN_INVALID_POINT;
-
-	if (res==0)
-	{
-		PAIR_ate(&g,&Q,&P);
-        PAIR_fexp(&g);
-		FP12_trace(&(g.a),&g);
-
-		BIG_copy(b,g.a.a.a); FP_redc(b); printf("trace pairing= "); BIG_output(b); printf("\n");
-		BIG_copy(b,g.a.a.b); FP_redc(b); printf("trace pairing= "); BIG_output(b); printf("\n");
-		BIG_copy(b,g.a.b.a); FP_redc(b); printf("trace pairing= "); BIG_output(b); printf("\n");
-		BIG_copy(b,g.a.b.b); FP_redc(b); printf("trace pairing= "); BIG_output(b); printf("\n");
-
-	}
-
-    return res;
-}
-*/
-
-/*
-int main()
-{
-	ECP2 X;
-	FP2 x,y,rhs;
-	BIG r;
-	char hcid[HASH_BYTES],client_id[100];
-	octet HCID={0,sizeof(hcid),hcid};
-	octet CLIENT_ID={0,sizeof(client_id),client_id};
-
-	OCT_jstring(&CLIENT_ID,"testUser@miracl.com");
-	MPIN_HASH_ID(&CLIENT_ID,&HCID);
-
-	printf("Client ID= "); OCT_output_string(&CLIENT_ID); printf("\n");
-
-	mapit2(&HCID,&X);
-
-	ECP2_output(&X);
-
-	BIG_rcopy(r,CURVE_Order);
-
-	ECP2_mul(&X,r);
-
-	ECP2_output(&X);
-
-}
-*/
diff --git a/c/mpin.h b/c/mpin.h
deleted file mode 100755
index dd49d75..0000000
--- a/c/mpin.h
+++ /dev/null
@@ -1,379 +0,0 @@
-/*
-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.
-*/
-
-/**
- * @file mpin.h
- * @author Mike Scott and Kealan McCusker
- * @date 2nd June 2015
- * @brief M-Pin Header file
- *
- * Allows some user configuration
- * defines structures
- * declares functions
- *
- */
-
-#ifndef MPIN_H
-#define MPIN_H
-
-#include "amcl.h"
-
-/* Field size is assumed to be greater than or equal to group size */
-
-#define PGS 32  /**< MPIN Group Size */
-#define PFS 32  /**< MPIN Field Size */
-#define PAS 16  /**< MPIN Symmetric Key Size */
-
-#define MPIN_OK                     0  /**< Function completed without error */
-/*#define MPIN_DOMAIN_ERROR          -11
-#define MPIN_INVALID_PUBLIC_KEY    -12
-#define MPIN_ERROR                 -13*/
-#define MPIN_INVALID_POINT         -14	/**< Point is NOT on the curve */
-/*#define MPIN_DOMAIN_NOT_FOUND      -15
-#define MPIN_OUT_OF_MEMORY         -16
-#define MPIN_DIV_BY_ZERO           -17
-#define MPIN_WRONG_ORDER           -18*/
-#define MPIN_BAD_PIN               -19  /**< Bad PIN number entered */
-
-
-/* Configure your PIN here */
-
-#define MAXPIN 10000 /**< max PIN */
-#define PBLEN 14   /**< max length of PIN in bits */
-
-#define TIME_SLOT_MINUTES 1440 /**< Time Slot = 1 day */
-#define HASH_BYTES 32 /**< Number of bytes output by Hash function */
-
-/* MPIN support functions */
-
-/* MPIN primitives */
-
-/**	@brief Hash an M-Pin Identity to an octet string
- *
-	@param ID an octet containing the identity
-	@param HID an octet containing the hashed identity
- */
-DLL_EXPORT void MPIN_HASH_ID(octet *ID,octet *HID);
-/**	@brief Get epoch time as unsigned integer
- *
-	@return current epoch time in seconds
- */
-DLL_EXPORT unsign32 MPIN_GET_TIME(void);
-/**	@brief Generate Y=H(t,O), where t is epoch time, O is an octet, and H(.) is a hash function
- *
-	@param t is epoch time in seconds
-	@param O is an input octet
-	@param Y is the output octet
- */
-DLL_EXPORT void MPIN_GET_Y(int t,octet *O,octet *Y);
-/**	@brief Extract a PIN number from a client secret
- *
-	@param ID is the input client identity
-	@param pin is an input PIN number
-	@param CS is the client secret from which the PIN is to be extracted
-	@return 0 or an error code
- */
-DLL_EXPORT int MPIN_EXTRACT_PIN(octet *ID,int pin,octet *CS);
-/**	@brief Perform client side of the one-pass version of the M-Pin protocol
- *
-	If Time Permits are disabled, set d = 0, and UT is not generated and can be set to NULL.
-	If Time Permits are enabled, and PIN error detection is OFF, U is not generated and can be set to NULL.
-	If Time Permits are enabled, and PIN error detection is ON, U and UT are both generated.
-	@param d is input date, in days since the epoch. Set to 0 if Time permits disabled
-	@param ID is the input client identity
-	@param R is a pointer to a cryptographically secure random number generator
-	@param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input
-	@param pin is the input PIN number
-	@param T is the input M-Pin token (the client secret with PIN portion removed)
-	@param V is output = -(x+y)(CS+TP), where CS is the reconstructed client secret, and TP is the time permit
-	@param U is output = x.H(ID)
-	@param UT is output = x.(H(ID)+H(d|H(ID)))
-	@param TP is the input time permit
-	@param MESSAGE is the message to be signed
-	@param t is input epoch time in seconds - a timestamp
-	@param y is output H(t|U) or H(t|UT) if Time Permits enabled
-	@return 0 or an error code
- */
-DLL_EXPORT int MPIN_CLIENT(int d,octet *ID,csprng *R,octet *x,int pin,octet *T,octet *V,octet *U,octet *UT,octet *TP, octet* MESSAGE, int t, octet *y);
-/**	@brief Perform first pass of the client side of the 3-pass version of the M-Pin protocol
- *
-	If Time Permits are disabled, set d = 0, and UT is not generated and can be set to NULL.
-	If Time Permits are enabled, and PIN error detection is OFF, U is not generated and can be set to NULL.
-	If Time Permits are enabled, and PIN error detection is ON, U and UT are both generated.
-	@param d is input date, in days since the epoch. Set to 0 if Time permits disabled
-	@param ID is the input client identity
-	@param R is a pointer to a cryptographically secure random number generator
-	@param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input
-	@param pin is the input PIN number
-	@param T is the input M-Pin token (the client secret with PIN portion removed)
-	@param S is output = CS+TP, where CS=is the reconstructed client secret, and TP is the time permit
-	@param U is output = x.H(ID)
-	@param UT is output = x.(H(ID)+H(d|H(ID)))
-	@param TP is the input time permit
-	@return 0 or an error code
- */
-DLL_EXPORT int MPIN_CLIENT_1(int d,octet *ID,csprng *R,octet *x,int pin,octet *T,octet *S,octet *U,octet *UT,octet *TP);
-/**	@brief Generate a random group element
- *
-	@param R is a pointer to a cryptographically secure random number generator
-	@param S is the output random octet
-	@return 0 or an error code
- */
-DLL_EXPORT int MPIN_RANDOM_GENERATE(csprng *R,octet *S);
-/**	@brief Perform second pass of the client side of the 3-pass version of the M-Pin protocol
- *
-	@param x an input, a locally generated random number
-	@param y an input random challenge from the server
-	@param V on output = -(x+y).V
-	@return 0 or an error code
- */
-DLL_EXPORT int MPIN_CLIENT_2(octet *x,octet *y,octet *V);
-/**	@brief Perform server side of the one-pass version of the M-Pin protocol
- *
-	If Time Permits are disabled, set d = 0, and UT and HTID are not generated and can be set to NULL.
-	If Time Permits are enabled, and PIN error detection is OFF, U and HID are not needed and can be set to NULL.
-	If Time Permits are enabled, and PIN error detection is ON, U, UT, HID and HTID are all required.
-	@param d is input date, in days since the epoch. Set to 0 if Time permits disabled
-	@param HID is output H(ID), a hash of the client ID
-	@param HTID is output H(ID)+H(d|H(ID))
-	@param y is output H(t|U) or H(t|UT) if Time Permits enabled
-	@param SS is the input server secret
-	@param U is input from the client = x.H(ID)
-	@param UT is input from the client= x.(H(ID)+H(d|H(ID)))
-	@param V is an input from the client
-	@param E is an output to help the Kangaroos to find the PIN error, or NULL if not required
-	@param F is an output to help the Kangaroos to find the PIN error, or NULL if not required
-	@param ID is the input claimed client identity
-	@param MESSAGE is the message to be signed
-	@param t is input epoch time in seconds - a timestamp
-	@return 0 or an error code
- */
-DLL_EXPORT int MPIN_SERVER(int d,octet *HID,octet *HTID,octet *y,octet *SS,octet *U,octet *UT,octet *V,octet *E,octet *F,octet *ID,octet *MESSAGE, int t);
-/**	@brief Perform first pass of the server side of the 3-pass version of the M-Pin protocol
- *
-	@param d is input date, in days since the epoch. Set to 0 if Time permits disabled
-	@param ID is the input claimed client identity
-	@param HID is output H(ID), a hash of the client ID
-	@param HTID is output H(ID)+H(d|H(ID))
-	@return 0 or an error code
- */
-DLL_EXPORT void	MPIN_SERVER_1(int d,octet *ID,octet *HID,octet *HTID);
-/**	@brief Perform third pass on the server side of the 3-pass version of the M-Pin protocol
- *
-	If Time Permits are disabled, set d = 0, and UT and HTID are not needed and can be set to NULL.
-	If Time Permits are enabled, and PIN error detection is OFF, U and HID are not needed and can be set to NULL.
-	If Time Permits are enabled, and PIN error detection is ON, U, UT, HID and HTID are all required.
-	@param d is input date, in days since the epoch. Set to 0 if Time permits disabled
-	@param HID is input H(ID), a hash of the client ID
-	@param HTID is input H(ID)+H(d|H(ID))
-	@param y is the input server's randomly generated challenge
-	@param SS is the input server secret
-	@param U is input from the client = x.H(ID)
-	@param UT is input from the client= x.(H(ID)+H(d|H(ID)))
-	@param V is an input from the client
-	@param E is an output to help the Kangaroos to find the PIN error, or NULL if not required
-	@param F is an output to help the Kangaroos to find the PIN error, or NULL if not required
-	@return 0 or an error code
- */
-DLL_EXPORT int MPIN_SERVER_2(int d,octet *HID,octet *HTID,octet *y,octet *SS,octet *U,octet *UT,octet *V,octet *E,octet *F);
-/**	@brief Add two members from the group G1
- *
-	@param Q1 an input member of G1
-	@param Q2 an input member of G1
-	@param Q an output member of G1 = Q1+Q2
-	@return 0 or an error code
- */
-DLL_EXPORT int MPIN_RECOMBINE_G1(octet *Q1,octet *Q2,octet *Q);
-/**	@brief Add two members from the group G2
- *
-	@param P1 an input member of G2
-	@param P2 an input member of G2
-	@param P an output member of G2 = P1+P2
-	@return 0 or an error code
- */
-DLL_EXPORT int MPIN_RECOMBINE_G2(octet *P1,octet *P2,octet *P);
-/**	@brief Use Kangaroos to find PIN error
- *
-	@param E a member of the group GT
-	@param F a member of the group GT =  E^e
-	@return 0 if Kangaroos failed, or the PIN error e
- */
-DLL_EXPORT int MPIN_KANGAROO(octet *E,octet *F);
-/**	@brief Encoding of a Time Permit to make it indistinguishable from a random string
- *
-	@param R is a pointer to a cryptographically secure random number generator
-	@param TP is the input time permit, obfuscated on output
-	@return 0 or an error code
- */
-DLL_EXPORT int MPIN_ENCODING(csprng *R,octet *TP);
-/**	@brief Encoding of an obfuscated Time Permit
- *
-	@param TP is the input obfuscated time permit, restored on output
-	@return 0 or an error code
- */
-DLL_EXPORT int MPIN_DECODING(octet *TP);
-/**	@brief Supply today's date as days from the epoch
- *
-	@return today's date, as number of days elapsed since the epoch
- */
-DLL_EXPORT unsign32 MPIN_today(void);
-/**	@brief Initialise a random number generator
- *
-	@param R is a pointer to a cryptographically secure random number generator
-	@param S is an input truly random seed value
- */
-DLL_EXPORT void MPIN_CREATE_CSPRNG(csprng *R,octet *S);
-/**	@brief Kill a random number generator
- *
-	Deletes all internal state
-	@param R is a pointer to a cryptographically secure random number generator
- */
-DLL_EXPORT void MPIN_KILL_CSPRNG(csprng *R);
-/**	@brief Find a random multiple of a point in G1
- *
-	@param R is a pointer to a cryptographically secure random number generator
-	@param type determines type of action to be taken
-	@param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input
-	@param G if type=0 a point in G1, else an octet to be mapped to G1
-	@param W the output =x.G or x.M(G), where M(.) is a mapping
-	@return 0 or an error code
- */
-DLL_EXPORT int MPIN_GET_G1_MULTIPLE(csprng *R,int type,octet *x,octet *G,octet *W);
-/**	@brief Create a client secret in G1 from a master secret and the client ID
- *
-	@param S is an input master secret
-	@param ID is the input client identity
-	@param CS is the full client secret = s.H(ID)
-	@return 0 or an error code
- */
-DLL_EXPORT int MPIN_GET_CLIENT_SECRET(octet *S,octet *ID,octet *CS);
-/**	@brief Create a Time Permit in G1 from a master secret and the client ID
- *
-	@param d is input date, in days since the epoch.
-	@param S is an input master secret
-	@param ID is the input client identity
-	@param TP is a Time Permit for the given date = s.H(d|H(ID))
-	@return 0 or an error code
- */
-DLL_EXPORT int MPIN_GET_CLIENT_PERMIT(int d,octet *S,octet *ID,octet *TP);
-/**	@brief Create a server secret in G2 from a master secret
- *
-	@param S is an input master secret
-	@param SS is the server secret = s.Q where Q is a fixed generator of G2
-	@return 0 or an error code
- */
-DLL_EXPORT int MPIN_GET_SERVER_SECRET(octet *S,octet *SS);
-/* DLL_EXPORT int MPIN_TEST_PAIRING(octet *,octet *); */
-
-/* For M-Pin Full */
-/**	@brief Precompute values for use by the client side of M-Pin Full
- *
-	@param T is the input M-Pin token (the client secret with PIN portion removed)
-	@param ID is the input client identity
-	@param g1 precomputed output
-	@param g2 precomputed output
-	@return 0 or an error code
- */
-DLL_EXPORT int MPIN_PRECOMPUTE(octet *T,octet *ID,octet *g1,octet *g2);
-/**	@brief Calculate Key on Server side for M-Pin Full
- *
-	Uses UT internally for the key calculation, unless not available in which case U is used
-	@param Z is the input Client-side Diffie-Hellman component
-	@param SS is the input server secret
-	@param w is an input random number generated by the server
-	@param p is an input, hash of the protocol transcript
-	@param I is the hashed input client ID = H(ID)
-	@param U is input from the client = x.H(ID)
-	@param UT is input from the client= x.(H(ID)+H(d|H(ID)))
-	@param K is the output calculated shared key
-	@return 0 or an error code
- */
-DLL_EXPORT int MPIN_SERVER_KEY(octet *Z,octet *SS,octet *w,octet *p,octet *I,octet *U,octet *UT,octet *K);
-/**	@brief Calculate Key on Client side for M-Pin Full
- *
-	@param g1 precomputed input
-	@param g2 precomputed input
-	@param pin is the input PIN number
-	@param r is an input, a locally generated random number
-	@param x is an input, a locally generated random number
-	@param p is an input, hash of the protocol transcript
-	@param T is the input Server-side Diffie-Hellman component
-	@param K is the output calculated shared key
-	@return 0 or an error code
- */
-DLL_EXPORT int MPIN_CLIENT_KEY(octet *g1,octet *g2,int pin,octet *r,octet *x,octet *p,octet *T,octet *K);
-
-/**	@brief AES-GCM Encryption
- *
-	@param K  AES key
-	@param IV Initialization vector
-	@param H Header
-	@param P Plaintext
-	@param C Ciphertext
-	@param T Checksum
- */
-DLL_EXPORT void MPIN_AES_GCM_ENCRYPT(octet *K,octet *IV,octet *H,octet *P,octet *C,octet *T);
-
-/**	@brief AES-GCM Decryption
- *
-	@param K  AES key
-	@param IV Initialization vector
-	@param H Header
-	@param P Plaintext
-	@param C Ciphertext
-	@param T Checksum
- */
-DLL_EXPORT void MPIN_AES_GCM_DECRYPT(octet *K,octet *IV,octet *H,octet *C,octet *P,octet *T);
-
-/**	@brief HMAC of message M using key K to create tag of length len in octet tag
- *
-	IEEE-1363 MAC1 function. Uses SHA256 internally.
-	@param M input message octet
-	@param K input encryption key
-	@param len is output desired length of HMAC tag
-	@param tag is the output HMAC
-	@return 0 for bad parameters, else 1
- */
-DLL_EXPORT int MPIN_HMAC(octet *M,octet *K,int len,octet *tag);
-
-/**	@brief Password Based Key Derivation Function - generates key K from password, salt and repeat counter
- *
-	PBKDF2 Password Based Key Derivation Function. Uses SHA256 internally.
-	@param P input password
-	@param S input salt
-	@param rep Number of times to be iterated.
-	@param len is output desired length of key
-	@param K is the derived key
- */
-DLL_EXPORT void MPIN_PBKDF2(octet *P,octet *S,int rep,int len,octet *K);
-
-/** @brief Hash the session transcript 
-	@param I is the hashed input client ID = H(ID)
-	@param U is the client output = x.H(ID)
-	@param CU is the client output = x.(H(ID)+H(T|H(ID)))
-	@param Y is the server challenge
-	@param V is the client part response
-	@param R is the client part response
-	@param W is the server part response
-	@param H the output is the hash of all of the above that apply
-*/
-DLL_EXPORT void MPIN_HASH_ALL(octet *I,octet *U,octet *CU,octet *V,octet *Y,octet *R,octet *W,octet *H);
-
-#endif
-
diff --git a/c/oct.c b/c/oct.c
deleted file mode 100755
index 52455ae..0000000
--- a/c/oct.c
+++ /dev/null
@@ -1,388 +0,0 @@
-/*
-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.
-*/
-
-
-/*** Basic Octet string maintainance routines  ***/
-/* SU=m, m is Stack Usage */
-
-#include <string.h>
-#include "amcl.h"
-
-/* Output an octet string (Debug Only) */
-
-/* SU= 16 */
-/* output octet */
-void OCT_output(octet *w)
-{
-    int i;
-    unsigned char ch;
-    for (i=0;i<w->len;i++)
-    {
-        ch=w->val[i];
-        printf("%02x",ch);
-    }
-    printf("\n");
-}
-
-/* SU= 16 */
-void OCT_output_string(octet *w)
-{
-    int i;
-    unsigned char ch;
-    for (i=0;i<w->len;i++)
-    {
-        ch=w->val[i];
-        printf("%c",ch);
-    }
-  /*  printf("\n"); */
-}
-
-/* Convert C string to octet format - truncates if no room  */
-void OCT_jstring(octet *y,char *s)
-{
-    int i,j;
-    i=y->len;
-    j=0;
-    while (s[j]!=0 && i<y->max)
-    {
-        y->val[i]=s[j];
-        y->len++;
-        i++;  j++;
-    }
-}
-
-/* compare 2 octet strings.
- * If x==y return TRUE, else return FALSE */
-/* SU= 8 */
-int OCT_comp(octet *x,octet *y)
-{
-    int i;
-    if (x->len>y->len) return 0;
-    if (x->len<y->len) return 0;
-    for (i=0;i<x->len;i++)
-    {
-        if (x->val[i]!=y->val[i]) return 0;
-    }
-    return 1;
-}
-
-/* check are first n bytes the same */
-
-int OCT_ncomp(octet *x,octet *y,int n)
-{
-    int i;
-    if (n>y->len || n>x->len) return 0;
-    for (i=0;i<n;i++)
-    {
-        if (x->val[i]!=y->val[i]) return 0;
-    }
-    return 1;
-}
-
-/* Shift octet to the left by n bytes. Leftmost bytes disappear  */
-void OCT_shl(octet *x,int n)
-{
-    int i;
-    if (n>=x->len)
-    {
-        x->len=0;
-        return;
-    }
-    x->len-=n;
-    for (i=0;i<x->len;i++)
-        x->val[i]=x->val[i+n];
-}
-
-/* Append binary string to octet - truncates if no room */
-/* SU= 12 */
-void OCT_jbytes(octet *y,char *b,int len)
-{
-    int i,j;
-    i=y->len;
-    for (j=0;j<len && i<y->max;j++)
-    {
-        y->val[i]=b[j];
-        y->len++;
-        i++;
-    }
-}
-
-/* Concatenates two octet strings */
-/* SU= 8 */
-void OCT_joctet(octet *y,octet *x)
-{ /* y=y || x */
-    int i,j;
-    if (x==NULL) return;
-
-    for (i=0;i<x->len;i++)
-    {
-        j=y->len+i;
-        if (j>=y->max)
-        {
-            y->len=y->max;
-            return;
-        }
-        y->val[j]=x->val[i];
-    }
-    y->len+=x->len;
-}
-
-/* Append byte to octet rep times */
-/* SU= 8 */
-void OCT_jbyte(octet *y,int ch,int rep)
-{
-    int i,j;
-    i=y->len;
-    for (j=0;j<rep && i<y->max;j++)
-    {
-        y->val[i]=ch;
-        y->len++;
-        i++;
-    }
-}
-
-/* XOR common bytes of x with y */
-/* SU= 8 */
-void OCT_xor(octet *y,octet *x)
-{ /* xor first x->len bytes of y */
-
-    int i;
-    for (i=0;i<x->len && i<y->len;i++)
-    {
-        y->val[i]^=x->val[i];
-    }
-}
-
-/* clear an octet */
-void OCT_empty(octet *w)
-{
-    w->len=0;
-}
-
-/* Kill an octet string - Zeroise it for security */
-void OCT_clear(octet *w)
-{
-    int i;
-    for (i=0;i<w->max;i++) w->val[i]=0;
-    w->len=0;
-}
-
-/* appends int x of length len bytes to OCTET string */
-/* SU= 8 */
-void OCT_jint(octet *y,int x,int len)
-{
-    int i,n;
-    n=y->len+len;
-    if (n>y->max || len<=0) return;
-    for (i=y->len;i<n;i++) y->val[i]=0;
-    y->len=n;
-
-    i=y->len;
-    while (x>0 && i>0)
-    {
-        i--;
-        y->val[i]=x%256;
-        x/=256;
-    }
-}
-
-/* Pad an octet to a given length */
-/* SU= 8 */
-int OCT_pad(octet *w,int n)
-{
-	int i,d;
-	if (w->len>n || n>w->max) return 0;
-	if (n==w->len) return 1;
-	d=n-w->len;
-	for (i=n-1;i>=d;i--)
-		w->val[i]=w->val[i-d];
-	for (i=d-1;i>=0;i--)
-		w->val[i]=0;
-	w->len=n;
-	return 1;
-}
-
-
-/* Convert an octet string to base64 string */
-/* SU= 56 */
-void OCT_tobase64(char *b,octet *w)
-{
-	int i,j,k,rem,last;
-	int c,ch[4];
-	unsigned char ptr[3];
-	rem=w->len%3; j=k=0; last=4;
-	while (j<w->len)
-	{
-		for (i=0;i<3;i++)
-		{
-			if (j<w->len) ptr[i]=w->val[j++];
-			else {ptr[i]=0; last--;}
-		}
-		ch[0]=(ptr[0]>>2)&0x3f;
-		ch[1]=((ptr[0]<<4)|(ptr[1]>>4))&0x3f;
-		ch[2]=((ptr[1]<<2)|(ptr[2]>>6))&0x3f;
-		ch[3]=ptr[2]&0x3f;
-		for (i=0;i<last;i++)
-		{
-			c=ch[i];
-			if (c<26) c+=65;
-            if (c>=26 && c<52) c+=71;
-            if (c>=52 && c<62) c-=4;
-            if (c==62) c='+';
-            if (c==63) c='/';
-			b[k++]=c;
-		}
-	}
-	if (rem>0) for (i=rem;i<3;i++) b[k++]='=';
-	b[k]='\0';  /* dangerous! */
-}
-
-/* SU= 56 */
-void OCT_frombase64(octet *w,char *b)
-{
-	int i,j,k,pads,len=(int)strlen(b);
-	int c,ch[4],ptr[3];
-	int lead=1;
-	j=k=0;
-	while (j<len && k<w->max)
-	{
-		pads=0;
-		for (i=0;i<4;i++)
-		{
-			c=80+b[j++];
-			if (c<=112) continue; /* ignore white space */
-            if (c>144 && c<171) c-=145;
-            if (c>176 && c<203) c-=151;
-            if (c>127 && c<138) c-=76;
-            if (c==123) c=62;
-            if (c==127) c=63;
-            if (c==141) {pads++; continue;} /* ignore pads '=' */
-			ch[i]=c;
-		}
-		ptr[0]=(ch[0]<<2)|(ch[1]>>4);
-		ptr[1]=(ch[1]<<4)|(ch[2]>>2);
-		ptr[2]=(ch[2]<<6)|ch[3];
-		for (i=0;i<3-pads && k<w->max;i++)
-		{ /* don't put in leading zeros */
-			/* if (lead && ptr[i]==0) continue; */
-			w->val[k++]=ptr[i];
-			lead=0;
-		}
-
-	}
-	w->len=k;
-}
-
-/* copy an octet string - truncates if no room */
-/* SU= 16 */
-void OCT_copy(octet *y,octet *x)
-{
-    int i;
-    OCT_clear(y);
-    y->len=x->len;
-    if (y->len>y->max) y->len=y->max;
-
-    for (i=0;i<y->len;i++)
-        y->val[i]=x->val[i];
-}
-
-/* XOR m with all of x */
-void OCT_xorbyte(octet *x,int m)
-{
-    int i;
-    for (i=0;i<x->len;i++) x->val[i]^=m;
-}
-
-/* truncates x to n bytes and places the rest in y (if y is not NULL) */
-/* SU= 8 */
-void OCT_chop(octet *x,octet *y,int n)
-{
-    int i;
-    if (n>=x->len)
-    {
-        if (y!=NULL) y->len=0;
-        return;
-    }
-    if (y!=NULL) y->len=x->len-n;
-    x->len=n;
-
-    if (y!=NULL)
-    {
-        for (i=0;i<y->len && i<y->max;i++) y->val[i]=x->val[i+n];
-    }
-}
-
-/* set x to len random bytes */
-void OCT_rand(octet *x,csprng *RNG,int len)
-{
-    int i;
-    if (len>x->max) len=x->max;
-    x->len=len;
-
-    for (i=0;i<len;i++) x->val[i]=RAND_byte(RNG);
-}
-
-/* Convert an octet to a hex string */
-void OCT_toHex(octet *src,char *dst)
-{
-    int i;
-    unsigned char ch;
-    for (i=0;i<src->len;i++)
-    {
-        ch=src->val[i];
-        sprintf(&dst[i*2],"%02x", ch);
-    }
-}
-
-/* Convert an octet to a string */
-void OCT_toStr(octet *src,char *dst)
-{
-    int i;
-    unsigned char ch;
-    for (i=0;i<src->len;i++)
-    {
-        ch=src->val[i];
-        sprintf(&dst[i],"%c", ch);
-    }
-}
-
-/* Test program
-#include <stdio.h>
-#include "amcl.h"
-
-char test[]="abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
-
-int main()
-{
-	char gm[100],gn[100],t[100];
-    octet m={0,sizeof(gm),gm};
-    octet n={0,sizeof(gn),gn};
-
-	OCT_jbytes(&m,test,strlen(test));
-	OCT_output(&m);
-
-	OCT_tobase64(t,&m);
-	printf(t); printf("\n");
-
-	OCT_frombase64(&n,t);
-	OCT_output(&n);
-
-    return 0;
-}
-*/
diff --git a/c/pair.c b/c/pair.c
deleted file mode 100755
index c5bbc6f..0000000
--- a/c/pair.c
+++ /dev/null
@@ -1,652 +0,0 @@
-/*
-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.
-*/
-
-/* AMCL BN Curve pairing functions */
-
-//#define HAS_MAIN
-
-#include "amcl.h"
-
-/* Line function */
-static void PAIR_line(FP12 *v,ECP2 *A,ECP2 *B,BIG Qx,BIG Qy)
-{
-	ECP2 P;
-	FP2 Z3,X,Y,ZZ,T,NY;
-	FP4 a,b,c;
-	int D;
-	ECP2_copy(&P,A);
-	if (A==B)
-		D=ECP2_dbl(A);  // check these return numbers...
-	else
-		D=ECP2_add(A,B);
-	if (D<0)
-	{ /* Infinity */
-		FP12_one(v);
-		return;
-	}
-
-	FP2_copy(&Z3,&(A->z));
-	FP4_zero(&c);
-	FP2_sqr(&ZZ,&(P.z));    /* ZZ=Z^2 */
-	if (D==0)
-	{ /* addition */
-		ECP2_get(&X,&Y,B);
-		FP2_mul(&T,&(P.z),&Y);  /* T=Z*Y2 */
-
-		FP2_mul(&ZZ,&ZZ,&T);
-
-		FP2_neg(&NY,&(P.y));
-		FP2_add(&ZZ,&ZZ,&NY); /* ZZ=Z^3*Y2-Y (slope numerator) */
-		FP2_pmul(&Z3,&Z3,Qy);    /* Z3*Qy */
-		FP2_mul(&T,&T,&(P.x));
-		FP2_mul(&X,&X,&NY);
-		FP2_add(&T,&T,&X);       /* Z*Y2*X-X2*Y */
-		FP4_from_FP2s(&a,&Z3,&T); /* a=[Z3*Qy,Z*Y2*X-X2*Y] */
-		FP2_neg(&ZZ,&ZZ);
-		FP2_pmul(&ZZ,&ZZ,Qx);
-		FP4_from_FP2(&b,&ZZ);    /* b=-slope*Qx */
-	}
-	else
-	{ /* doubling */
-		FP2_sqr(&T,&(P.x));
-		FP2_imul(&T,&T,3);   /* T=3X^2 (slope numerator) */
-		FP2_sqr(&Y,&(P.y));
-
-		FP2_add(&Y,&Y,&Y);   /* Y=2Y^2 */
-		FP2_mul(&Z3,&Z3,&ZZ);   /* Z3=Z3*ZZ */
-		FP2_pmul(&Z3,&Z3,Qy);   /* Z3=Z3*ZZ*Qy */
-
-		FP2_mul(&X,&(P.x),&T);
-		FP2_sub(&X,&X,&Y);      /* X=X*slope-2Y^2 */
-		FP4_from_FP2s(&a,&Z3,&X); /* a=[Z3*ZZ*Qy , X*slope-2Y^2] */
-		FP2_neg(&T,&T);
-		FP2_mul(&ZZ,&ZZ,&T);
-		FP2_pmul(&ZZ,&ZZ,Qx);
-		FP4_from_FP2(&b,&ZZ);    /* b=-slope*ZZ*Qx */
-	}
-
-	FP12_from_FP4s(v,&a,&b,&c);
-}
-
-/* Optimal R-ate pairing r=e(P,Q) */
-void PAIR_ate(FP12 *r,ECP2 *P,ECP *Q)
-{
-	FP2 X;
-	BIG x,n,Qx,Qy;
-	int i,nb;
-	ECP2 A,KA;
-	FP12 lv;
-
-	BIG_rcopy(Qx,CURVE_Fra);
-	BIG_rcopy(Qy,CURVE_Frb);
-	FP2_from_BIGs(&X,Qx,Qy);
-
-	BIG_rcopy(x,CURVE_Bnx);
-	BIG_pmul(n,x,6);
-
-	BIG_dec(n,2);
-	BIG_norm(n);
-
-	ECP2_affine(P);
-	ECP_affine(Q);
-
-	BIG_copy(Qx,Q->x);
-	BIG_copy(Qy,Q->y);
-
-	ECP2_copy(&A,P);
-	FP12_one(r);
-	nb=BIG_nbits(n);
-
-/* Main Miller Loop */
-    for (i=nb-2;i>=1;i--)
-    {
-		PAIR_line(&lv,&A,&A,Qx,Qy);
-		FP12_smul(r,&lv);
-		if (BIG_bit(n,i))
-		{
-
-			PAIR_line(&lv,&A,P,Qx,Qy);
-			FP12_smul(r,&lv);
-		}
-		FP12_sqr(r,r);
-    }
-
-	PAIR_line(&lv,&A,&A,Qx,Qy);
-	FP12_smul(r,&lv);
-
-/* R-ate fixup */
-
-	ECP2_copy(&KA,P);
-	ECP2_frob(&KA,&X);
-
-	ECP2_neg(&A);
-	FP12_conj(r,r);
-
-	PAIR_line(&lv,&A,&KA,Qx,Qy);
-	FP12_smul(r,&lv);
-	ECP2_frob(&KA,&X);
-	ECP2_neg(&KA);
-	PAIR_line(&lv,&A,&KA,Qx,Qy);
-	FP12_smul(r,&lv);
-
-}
-
-/* Optimal R-ate double pairing e(P,Q).e(R,S) */
-void PAIR_double_ate(FP12 *r,ECP2 *P,ECP *Q,ECP2 *R,ECP *S)
-{
-	FP2 X;
-	BIG x,n,Qx,Qy,Sx,Sy;
-	int i,nb;
-	ECP2 A,B,K;
-	FP12 lv;
-
-	BIG_rcopy(Qx,CURVE_Fra);
-	BIG_rcopy(Qy,CURVE_Frb);
-	FP2_from_BIGs(&X,Qx,Qy);
-
-	BIG_rcopy(x,CURVE_Bnx);
-
-	BIG_pmul(n,x,6);
-	BIG_dec(n,2);
-	BIG_norm(n);
-
-	ECP2_affine(P);
-	ECP_affine(Q);
-
-	ECP2_affine(R);
-	ECP_affine(S);
-
-	BIG_copy(Qx,Q->x);
-	BIG_copy(Qy,Q->y);
-
-	BIG_copy(Sx,S->x);
-	BIG_copy(Sy,S->y);
-
-	ECP2_copy(&A,P);
-	ECP2_copy(&B,R);
-	FP12_one(r);
-	nb=BIG_nbits(n);
-
-/* Main Miller Loop */
-    for (i=nb-2;i>=1;i--)
-    {
-		PAIR_line(&lv,&A,&A,Qx,Qy);
-		FP12_smul(r,&lv);
-		PAIR_line(&lv,&B,&B,Sx,Sy);
-		FP12_smul(r,&lv);
-
-		if (BIG_bit(n,i))
-		{
-			PAIR_line(&lv,&A,P,Qx,Qy);
-			FP12_smul(r,&lv);
-
-			PAIR_line(&lv,&B,R,Sx,Sy);
-			FP12_smul(r,&lv);
-		}
-		FP12_sqr(r,r);
-    }
-
-	PAIR_line(&lv,&A,&A,Qx,Qy);
-	FP12_smul(r,&lv);
-
-	PAIR_line(&lv,&B,&B,Sx,Sy);
-	FP12_smul(r,&lv);
-
-/* R-ate fixup */
-
-	FP12_conj(r,r);
-
-	ECP2_copy(&K,P);
-	ECP2_frob(&K,&X);
-	ECP2_neg(&A);
-	PAIR_line(&lv,&A,&K,Qx,Qy);
-	FP12_smul(r,&lv);
-	ECP2_frob(&K,&X);
-	ECP2_neg(&K);
-	PAIR_line(&lv,&A,&K,Qx,Qy);
-	FP12_smul(r,&lv);
-
-	ECP2_copy(&K,R);
-	ECP2_frob(&K,&X);
-	ECP2_neg(&B);
-	PAIR_line(&lv,&B,&K,Sx,Sy);
-	FP12_smul(r,&lv);
-	ECP2_frob(&K,&X);
-	ECP2_neg(&K);
-	PAIR_line(&lv,&B,&K,Sx,Sy);
-	FP12_smul(r,&lv);
-}
-
-/* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */
-void PAIR_fexp(FP12 *r)
-{
-	FP2 X;
-	BIG x,a,b;
-	FP12 t0,y0,y1,y2,y3;
-
-	BIG_rcopy(x,CURVE_Bnx);
-	BIG_rcopy(a,CURVE_Fra);
-	BIG_rcopy(b,CURVE_Frb);
-	FP2_from_BIGs(&X,a,b);
-
-/* Easy part of final exp */
-
-	FP12_inv(&t0,r);
-	FP12_conj(r,r);
-
-	FP12_mul(r,&t0);
-	FP12_copy(&t0,r);
-
-	FP12_frob(r,&X);
-	FP12_frob(r,&X);
-	FP12_mul(r,&t0);
-
-/* Hard part of final exp - see Duquesne & Ghamman eprint 2015/192.pdf */
-
-	FP12_pow(&t0,r,x); // t0=f^-u
-	FP12_usqr(&y3,&t0); // y3=t0^2
-	FP12_copy(&y0,&t0); FP12_mul(&y0,&y3); // y0=t0*y3
-	FP12_copy(&y2,&y3); FP12_frob(&y2,&X); // y2=y3^p
-	FP12_mul(&y2,&y3); //y2=y2*y3
-	FP12_usqr(&y2,&y2); //y2=y2^2
-	FP12_mul(&y2,&y3); // y2=y2*y3
-
-	FP12_pow(&t0,&y0,x);  //t0=y0^-u
-	FP12_conj(&y0,r);     //y0=~r
-	FP12_copy(&y1,&t0); FP12_frob(&y1,&X); FP12_frob(&y1,&X); //y1=t0^p^2
-	FP12_mul(&y1,&y0); // y1=y0*y1
-	FP12_conj(&t0,&t0); // t0=~t0
-	FP12_copy(&y3,&t0); FP12_frob(&y3,&X); //y3=t0^p
-	FP12_mul(&y3,&t0); // y3=t0*y3
-	FP12_usqr(&t0,&t0); // t0=t0^2
-	FP12_mul(&y1,&t0); // y1=t0*y1
-
-	FP12_pow(&t0,&y3,x); // t0=y3^-u
-	FP12_usqr(&t0,&t0); //t0=t0^2
-	FP12_conj(&t0,&t0); //t0=~t0
-	FP12_mul(&y3,&t0); // y3=t0*y3
-
-	FP12_frob(r,&X); FP12_copy(&y0,r);
-	FP12_frob(r,&X); FP12_mul(&y0,r);
-	FP12_frob(r,&X); FP12_mul(&y0,r);
-
-	FP12_usqr(r,&y3);  //r=y3^2
-	FP12_mul(r,&y2);   //r=y2*r
-	FP12_copy(&y3,r); FP12_mul(&y3,&y0); // y3=r*y0
-	FP12_mul(r,&y1); // r=r*y1
-	FP12_usqr(r,r); // r=r^2
-	FP12_mul(r,&y3); // r=r*y3
-	FP12_reduce(r);
-
-
-/* our way */
-/*
-//	FP12 lv,x0,x1,x2,x3,x4,x5;
-
-	FP12_copy(&lv,r);
-	FP12_frob(&lv,&X);
-	FP12_copy(&x0,&lv);
-	FP12_frob(&x0,&X);
-	FP12_mul(&lv,r);
-	FP12_mul(&x0,&lv);
-	FP12_frob(&x0,&X);
-
-	FP12_conj(&x1,r);
-	FP12_pow(&x4,r,x);
-	FP12_copy(&x3,&x4);
-	FP12_frob(&x3,&X);
-
-	FP12_pow(&x2,&x4,x);
-	FP12_conj(&x5,&x2);
-	FP12_pow(&lv,&x2,x);
-	FP12_frob(&x2,&X);
-	FP12_conj(r,&x2);
-
-	FP12_mul(&x4,r);
-	FP12_frob(&x2,&X);
-
-	FP12_copy(r,&lv);
-	FP12_frob(r,&X);
-	FP12_mul(&lv,r);
-
-	FP12_usqr(&lv,&lv);
-	FP12_mul(&lv,&x4);
-	FP12_mul(&lv,&x5);
-	FP12_copy(r,&x3);
-	FP12_mul(r,&x5);
-	FP12_mul(r,&lv);
-	FP12_mul(&lv,&x2);
-	FP12_usqr(r,r);
-	FP12_mul(r,&lv);
-	FP12_usqr(r,r);
-	FP12_copy(&lv,r);
-	FP12_mul(&lv,&x1);
-	FP12_mul(r,&x0);
-	FP12_usqr(&lv,&lv);
-	FP12_mul(r,&lv);
-	FP12_reduce(r); */
-}
-
-/* GLV method */
-static void glv(BIG u[2],BIG e)
-{
-	int i,j;
-	BIG v[2],t,q;
-	DBIG d;
-	BIG_rcopy(q,CURVE_Order);
-	for (i=0;i<2;i++)
-	{
-		BIG_rcopy(t,CURVE_W[i]);
-		BIG_mul(d,t,e);
-		BIG_ddiv(v[i],d,q);
-		BIG_zero(u[i]);
-	}
-	BIG_copy(u[0],e);
-	for (i=0;i<2;i++)
-		for (j=0;j<2;j++)
-		{
-			BIG_rcopy(t,CURVE_SB[j][i]);
-			BIG_modmul(t,v[j],t,q);
-			BIG_add(u[i],u[i],q);
-			BIG_sub(u[i],u[i],t);
-			BIG_mod(u[i],q);
-		}
-	return;
-}
-
-/* Galbraith & Scott Method */
-static void gs(BIG u[4],BIG e)
-{
-	int i,j;
-	BIG v[4],t,q;
-	DBIG d;
-	BIG_rcopy(q,CURVE_Order);
-	for (i=0;i<4;i++)
-	{
-		BIG_rcopy(t,CURVE_WB[i]);
-		BIG_mul(d,t,e);
-		BIG_ddiv(v[i],d,q);
-		BIG_zero(u[i]);
-	}
-
-	BIG_copy(u[0],e);
-	for (i=0;i<4;i++)
-		for (j=0;j<4;j++)
-		{
-			BIG_rcopy(t,CURVE_BB[j][i]);
-			BIG_modmul(t,v[j],t,q);
-			BIG_add(u[i],u[i],q);
-			BIG_sub(u[i],u[i],t);
-			BIG_mod(u[i],q);
-		}
-	return;
-}
-
-/* Multiply P by e in group G1 */
-void PAIR_G1mul(ECP *P,BIG e)
-{
-#ifdef USE_GLV   /* Note this method is patented */
-	int i,np,nn;
-	ECP Q;
-	BIG cru,t,q;
-	BIG u[2];
-
-	BIG_rcopy(q,CURVE_Order);
-	glv(u,e);
-
-	ECP_affine(P);
-	ECP_copy(&Q,P);
-	BIG_rcopy(cru,CURVE_Cru);
-	FP_nres(cru);
-	FP_mul(Q.x,Q.x,cru);
-
-/* note that -a.B = a.(-B). Use a or -a depending on which is smaller */
-
-	np=BIG_nbits(u[0]);
-	BIG_modneg(t,u[0],q);
-	nn=BIG_nbits(t);
-	if (nn<np)
-	{
-		BIG_copy(u[0],t);
-		ECP_neg(P);
-	}
-
-	np=BIG_nbits(u[1]);
-	BIG_modneg(t,u[1],q);
-	nn=BIG_nbits(t);
-	if (nn<np)
-	{
-		BIG_copy(u[1],t);
-		ECP_neg(&Q);
-	}
-
-
-	ECP_mul2(P,&Q,u[0],u[1]);
-
-#else
-	ECP_mul(P,e);
-#endif
-}
-
-/* Multiply P by e in group G2 */
-void PAIR_G2mul(ECP2 *P,BIG e)
-{
-#ifdef USE_GS_G2   /* Well I didn't patent it :) */
-	int i,np,nn;
-	ECP2 Q[4];
-	FP2 X;
-	BIG x,y;
-	BIG u[4];
-
-	BIG_rcopy(x,CURVE_Fra);
-	BIG_rcopy(y,CURVE_Frb);
-	FP2_from_BIGs(&X,x,y);
-
-	BIG_rcopy(y,CURVE_Order);
-	gs(u,e);
-
-
-	ECP2_affine(P);
-
-	ECP2_copy(&Q[0],P);
-	for (i=1;i<4;i++)
-	{
-		ECP2_copy(&Q[i],&Q[i-1]);
-		ECP2_frob(&Q[i],&X);
-	}
-
-	for (i=0;i<4;i++)
-	{
-		np=BIG_nbits(u[i]);
-		BIG_modneg(x,u[i],y);
-		nn=BIG_nbits(x);
-		if (nn<np)
-		{
-			BIG_copy(u[i],x);
-			ECP2_neg(&Q[i]);
-		}
-	}
-
-	ECP2_mul4(P,Q,u);
-
-#else
-	ECP2_mul(P,e);
-#endif
-}
-
-/* f=f^e */
-void PAIR_GTpow(FP12 *f,BIG e)
-{
-#ifdef USE_GS_GT   /* Note that this option requires a lot of RAM! Maybe better to use compressed XTR method, see amcl_fp4.c */
-	int i,np,nn;
-	FP12 g[4];
-	FP2 X;
-	BIG t,q,x,y;
-	BIG u[4];
-
-	BIG_rcopy(x,CURVE_Fra);
-	BIG_rcopy(y,CURVE_Frb);
-	FP2_from_BIGs(&X,x,y);
-
-	BIG_rcopy(q,CURVE_Order);
-	gs(u,e);
-
-	FP12_copy(&g[0],f);
-	for (i=1;i<4;i++)
-	{
-		FP12_copy(&g[i],&g[i-1]);
-		FP12_frob(&g[i],&X);
-	}
-
-	for (i=0;i<4;i++)
-	{
-		np=BIG_nbits(u[i]);
-		BIG_modneg(t,u[i],q);
-		nn=BIG_nbits(t);
-		if (nn<np)
-		{
-			BIG_copy(u[i],t);
-			FP12_conj(&g[i],&g[i]);
-		}
-	}
-	FP12_pow4(f,g,u);
-
-#else
-	FP12_pow(f,f,e);
-#endif
-}
-
-/* test group membership */
-/* with GT-Strong curve, now only check that m!=1, conj(m)*m==1, and m.m^{p^4}=m^{p^2} */
-int PAIR_GTmember(FP12 *m)
-{
-	BIG a,b;
-	FP2 X;
-	FP12 r,w;
-	if (FP12_isunity(m)) return 0;
-	FP12_conj(&r,m);
-	FP12_mul(&r,m);
-	if (!FP12_isunity(&r)) return 0;
-
-	BIG_rcopy(a,CURVE_Fra);
-	BIG_rcopy(b,CURVE_Frb);
-	FP2_from_BIGs(&X,a,b);
-
-
-	FP12_copy(&r,m); FP12_frob(&r,&X); FP12_frob(&r,&X);
-	FP12_copy(&w,&r); FP12_frob(&w,&X); FP12_frob(&w,&X);
-	FP12_mul(&w,m);
-
-
-#ifndef GT_STRONG
-	if (!FP12_equals(&w,&r)) return 0;
-
-	BIG_rcopy(a,CURVE_Bnx);
-
-	FP12_copy(&r,m); FP12_pow(&w,&r,a); FP12_pow(&w,&w,a);
-	FP12_sqr(&r,&w); FP12_mul(&r,&w); FP12_sqr(&r,&r);
-
-	FP12_copy(&w,m); FP12_frob(&w,&X);
- #endif
-
-	return FP12_equals(&w,&r);
-}
-
-#ifdef HAS_MAIN
-
-#if CHOICE==BNT
-
-const BIG TEST_Gx={0x18AFF11A,0xF2EF406,0xAF68220,0x171F2E27,0x6BA0959,0x124C50E0,0x450BE27,0x7003EA8,0x8A914};
-const BIG TEST_Gy={0x6E010F4,0xA71D07E,0x7ECADA8,0x8260E8E,0x1F79C328,0x17A09412,0xBFAE690,0x1C57CBD1,0x17DF54};
-
-const BIG TEST_Pxa={0x1047D566,0xD83CD71,0x10322E9D,0x991FA93,0xA282C48,0x18AEBEC8,0xCB05850,0x13B4F669,0x21794A};
-const BIG TEST_Pxb={0x1E305936,0x16885BF1,0x327060,0xE26F794,0x1547D870,0x1963E5B2,0x1BEBB96C,0x988A33C,0x1A9B47};
-const BIG TEST_Pya={0x20FF876,0x4427E67,0x18732211,0xE88E45E,0x174D1A7E,0x17D877ED,0x343AB37,0x97EB453,0xB00D5};
-const BIG TEST_Pyb={0x1D746B7B,0x732F4C2,0x122A49B0,0x16267985,0x235DF56,0x10B1E4D,0x14D8F210,0x17A05C3E,0x5ECF8};
-
-#endif
-
-#if CHOICE==BNT2
-
-const BIG TEST_Gx={0x15488765,0x46790D7,0xD9900A,0x1DFB43F,0x9F2D307,0xC4724E8,0x5678E51,0x15C3E3A7,0x1BEC8E};
-const BIG TEST_Gy={0x3D3273C,0x1AFA5FF,0x1880A139,0xACD34DF,0x17493067,0x10FA4103,0x1D4C9766,0x1A73F3DB,0x2D148};
-
-const BIG TEST_Pxa={0xF8DC275,0xAC27FA,0x11815151,0x152691C8,0x5CDEBF1,0x7D5A965,0x1BF70CE3,0x679A1C8,0xD62CF};
-const BIG TEST_Pxb={0x1D17D7A8,0x6B28DF4,0x174A0389,0xFE67E5F,0x1FA97A3C,0x7F5F473,0xFFB5146,0x4BC19A5,0x227010};
-const BIG TEST_Pya={0x16CC1F90,0x5284627,0x171B91AB,0x11F843B9,0x1D468755,0x67E279C,0x19FE0EF8,0x1A0CAA6B,0x1CC6CB};
-const BIG TEST_Pyb={0x1FF0CF2A,0xBC83255,0x6DD6EE8,0xB8B752F,0x13E484EC,0x1809BE81,0x1A648AA1,0x8CEF3F3,0x86EE};
-
-
-#endif
-
-int main()
-{
-	int i;
-	char byt[32];
-	csprng rng;
-	BIG xa,xb,ya,yb,w,a,b,t1,q,u[2],v[4],m,r;
-	ECP2 P,G;
-	ECP Q,R;
-	FP12 g,gp;
-	FP4 t,c,cp,cpm1,cpm2;
-	FP2 x,y,X;
-
-
-	BIG_rcopy(a,CURVE_Fra);
-	BIG_rcopy(b,CURVE_Frb);
-	FP2_from_BIGs(&X,a,b);
-
-	BIG_rcopy(xa,TEST_Gx);
-	BIG_rcopy(ya,TEST_Gy);
-
-	ECP_set(&Q,xa,ya);
-	if (Q.inf) printf("Failed to set - point not on curve\n");
-	else printf("G1 set success\n");
-
-	printf("Q= "); ECP_output(&Q); printf("\n");
-
-//	BIG_rcopy(r,CURVE_Order); BIG_dec(r,7); BIG_norm(r);
-	BIG_rcopy(xa,TEST_Pxa);
-	BIG_rcopy(xb,TEST_Pxb);
-	BIG_rcopy(ya,TEST_Pya);
-	BIG_rcopy(yb,TEST_Pyb);
-
-	FP2_from_BIGs(&x,xa,xb);
-	FP2_from_BIGs(&y,ya,yb);
-
-	ECP2_set(&P,&x,&y);
-	if (P.inf) printf("Failed to set - point not on curve\n");
-	else printf("G2 set success\n");
-
-	printf("P= "); ECP2_output(&P); printf("\n");
-
-//for (i=0;i<1000;i++ )
-//{
-
-	PAIR_ate(&g,&P,&Q);
-	PAIR_fexp(&g);
-
-//	PAIR_GTpow(&g,xa);
-
-//}
-	printf("g3= ");FP12_output(&g); printf("\n");
-
-}
-
-#endif
diff --git a/c/rand.c b/c/rand.c
deleted file mode 100755
index 4075de1..0000000
--- a/c/rand.c
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
-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.
-*/
-
-/*
- *   Cryptographic strong random number generator
- *
- *   Unguessable seed -> SHA -> PRNG internal state -> SHA -> random numbers
- *   Slow - but secure
- *
- *   See ftp://ftp.rsasecurity.com/pub/pdfs/bull-1.pdf for a justification
- */
-/* SU=m, m is Stack Usage */
-
-#include "amcl.h"
-
-/* SU= 20 */
-static unsign32 sbrand(csprng *rng)
-{ /* Marsaglia & Zaman random number generator */
-    int i,k;
-    unsign32 pdiff,t;
-    rng->rndptr++;
-    if (rng->rndptr<NK) return rng->ira[rng->rndptr];
-    rng->rndptr=0;
-    for (i=0,k=NK-NJ;i<NK;i++,k++)
-    { /* calculate next NK values */
-        if (k==NK) k=0;
-        t=rng->ira[k];
-        pdiff=t - rng->ira[i] - rng->borrow;
-
-        if (pdiff<t) rng->borrow=0;
-        if (pdiff>t) rng->borrow=1;
-        rng->ira[i]=pdiff;
-    }
-    return rng->ira[0];
-}
-
-/* SU= 20 */
-static void sirand(csprng* rng,unsign32 seed)
-{ /* initialise random number system */
-  /* modified so that a subsequent call "stirs" in another seed value */
-  /* in this way as many seed bits as desired may be used */
-    int i,in;
-    unsign32 t,m=1;
-    rng->borrow=0L;
-    rng->rndptr=0;
-    rng->ira[0]^=seed;
-    for (i=1;i<NK;i++)
-    { /* fill initialisation vector */
-        in=(NV*i)%NK;
-        rng->ira[in]^=m;      /* note XOR */
-        t=m;
-        m=seed-m;
-        seed=t;
-    }
-    for (i=0;i<10000;i++) sbrand(rng ); /* "warm-up" & stir the generator */
-}
-
-/* SU= 312 */
-static void fill_pool(csprng *rng)
-{ /* hash down output of RNG to re-fill the pool */
-    int i;
-    hash sh;
-    HASH_init(&sh);
-    for (i=0;i<128;i++) HASH_process(&sh,sbrand(rng));
-    HASH_hash(&sh,rng->pool);
-    rng->pool_ptr=0;
-}
-
-static unsign32 pack(const uchar *b)
-{ /* pack bytes into a 32-bit Word */
-    return ((unsign32)b[3]<<24)|((unsign32)b[2]<<16)|((unsign32)b[1]<<8)|(unsign32)b[0];
-}
-
-/* SU= 360 */
-/* Initialize RNG with some real entropy from some external source */
-void RAND_seed(csprng *rng,int rawlen,char *raw)
-{ /* initialise from at least 128 byte string of raw  *
-   * random (keyboard?) input, and 32-bit time-of-day */
-    int i;
-    char digest[32];
-    uchar b[4];
-    hash sh;
-    rng->pool_ptr=0;
-    for (i=0;i<NK;i++) rng->ira[i]=0;
-    if (rawlen>0)
-    {
-        HASH_init(&sh);
-        for (i=0;i<rawlen;i++)
-            HASH_process(&sh,raw[i]);
-        HASH_hash(&sh,digest);
-
-/* initialise PRNG from distilled randomness */
-
-        for (i=0;i<8;i++)
-		{
-			b[0]=digest[4*i]; b[1]=digest[4*i+1]; b[2]=digest[4*i+2]; b[3]=digest[4*i+3];
-		//	printf("%08x\n",pack(b));
-			sirand(rng,pack(b));
-		}
-    }
-    fill_pool(rng);
-}
-
-/* Terminate and clean up */
-void RAND_clean(csprng *rng)
-{ /* kill internal state */
-    int i;
-    rng->pool_ptr=rng->rndptr=0;
-    for (i=0;i<32;i++) rng->pool[i]=0;
-    for (i=0;i<NK;i++) rng->ira[i]=0;
-    rng->borrow=0;
-}
-
-/* get random byte */
-/* SU= 8 */
-int RAND_byte(csprng *rng)
-{
-    int r;
-    r=rng->pool[rng->pool_ptr++];
-    if (rng->pool_ptr>=32) fill_pool(rng);
-    return (r&0xff);
-}
-
-/* test main program */
-/*
-#include <stdio.h>
-#include <string.h>
-
-void main()
-{
-    int i;
-    char raw[256];
-    csprng rng;
-
-	RAND_clean(&rng);
-
-
-	for (i=0;i<256;i++) raw[i]=(char)i;
-    RAND_seed(&rng,256,raw);
-
-	for (i=0;i<1000;i++)
-		printf("%02x ",(unsigned char)RAND_byte(&rng));
-}
-
-*/
diff --git a/c/readme.txt b/c/readme.txt
deleted file mode 100644
index 5c19b62..0000000
--- a/c/readme.txt
+++ /dev/null
@@ -1,62 +0,0 @@
-AMCL is very simple to build.
-
-The examples here are for GCC under Linux and Windows (using MINGW).
-
-First - decide what you want to do. Edit amcl_.h - note there is only
-one area where USER CONFIGURABLE input is requested.
-
-Here set the wordlength of your computer, and choose your curve.
-
-Once this is done, build the library, and compile and link your program 
-with an API file and the ROM file rom.c that contains curve constants.
-
-Three example API files are provided, mpin.c which supports our M-Pin 
-(tm) protocol, ecdh.c which supports standard elliptic 
-curve key exchange, digital signature and public key crypto, and rsa.c 
-which supports the RSA method. The first 
-can be tested using the testmpin.c driver programs, the second can 
-be tested using testecm/testecdh.c, and the third can be tested using
-testrsa.c
-
-In the ROM file you must provide the curve constants. Several examples
-are provided there, and if you are willing to use one of these, simply
-select your curve of CHOICE in amcl_.h
-
-Example (1), in amcl_.h choose
-
-#define CHOICE BN
-
-Under windows run the batch file build_pair.bat to build the amcl.a library
-and the testmpin.exe applications.
-
-For linux execute "bash build_pair"
-
-Example (2), in amcl_.h choose
-
-#define CHOICE C25519
-
-to select the Edwards curve ed25519.
-
-Under Windows run the batch file build_ec.bat to build the amcl.a library and
-the testecdh.exe application.
-
-For Linux execute "bash build_ec"
-
-
-To help generate the ROM constants for your own curve some MIRACL helper 
-programs are included. The program bngen.cpp generates a ROM file for a 
-BN curve, and the program ecgen.cpp generates the ROM for EC curves. 
-
-The program bigtobig.cpp converts a big number to the AMCL 
-BIG format.
-
-
-For quick jumpstart:-
-
-(Linux)
-bash build_pair
-./testmpin
-
-(Windows + MingW)
-build_pair
-testmpin
diff --git a/c/rom.c b/c/rom.c
deleted file mode 100755
index 2b61c17..0000000
--- a/c/rom.c
+++ /dev/null
@@ -1,852 +0,0 @@
-/*
-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.
-*/
-
-/* AMCL - ROM file */
-
-#include "amcl.h"
-
-/* Field and Curve Details */
-
-#if CHOICE==BN
-
-/* Nogami's fast curve */
-
-const int CURVE_A=0;
-#if CHUNK==16
-
-const chunk MConst=0x15E5;
-const BIG Modulus={0x13,0x0,0x0,0x0,0x1A70,0x9,0x0,0x0,0x100,0x309,0x2,0x0,0x1800,0x1A26,0x6E8,0x0,0x0,0x412,0x8D9,0x4A};
-const BIG CURVE_Order={0xD,0x0,0x0,0x0,0xA10,0x8,0x0,0x0,0x1F80,0x1FFC,0x1,0x0,0x1800,0x1A26,0x6E8,0x0,0x0,0x412,0x8D9,0x4A};
-const BIG CURVE_B={0x2};
-const BIG CURVE_Bnx={0x1,0x0,0x0,0x0,0x408};
-const BIG CURVE_Cru={0x7,0x0,0x0,0x0,0xCD8,0x3,0x0,0x0,0x900,0x1248,0x0,0x0,0x400,0x19B1,0x126};
-const BIG CURVE_Fra={0xDE9,0x1953,0x101B,0x1BCD,0xE17,0x1BE1,0x14FD,0x1249,0x974,0x1C28,0x54F,0x108D,0x150A,0x4CD,0x12D9,0xF91,0x12E,0x10C9,0xDDD,0x36};
-const BIG CURVE_Frb={0x122A,0x6AC,0xFE4,0x432,0xC58,0x428,0xB02,0xDB6,0x178B,0x6E0,0x1AB2,0xF72,0x2F5,0x1559,0x140F,0x106E,0x1ED1,0x1348,0x1AFB,0x13};
-const BIG CURVE_Pxa={0xCB4,0xFE8,0x1E4D,0x1658,0x2BA,0x2BE,0x13F3,0x33C,0x5E3,0x182D,0x1D8E,0xDBE,0x124F,0xFDB,0x8CD,0x14FD,0x155E,0x6A7,0x16C1,0x12};
-const BIG CURVE_Pxb={0x455,0x4B1,0x1E4,0xFA,0x38A,0x152F,0x149E,0x17C7,0xD86,0x1CEB,0x11FC,0xAE,0x189E,0x15F,0x1275,0x8F6,0x83,0x53E,0x1536,0xB};
-const BIG CURVE_Pya={0x46C,0x1045,0x1A1E,0x1B9C,0x1F9A,0xC8,0x629,0x61D,0x82B,0xB48,0xC7C,0xF09,0x4C3,0x168E,0x1E85,0x627,0x5E5,0x15F9,0xFCA,0x15};
-const BIG CURVE_Pyb={0x6EC,0xF98,0x1501,0x1F11,0xE6D,0x9D0,0xB74,0xED,0x482,0x12E0,0x75A,0xF03,0x11E4,0x313,0x16CE,0x1B57,0x679,0x143F,0x1DA6,0x30};
-const BIG CURVE_Gx={0x12,0x0,0x0,0x0,0x1A70,0x9,0x0,0x0,0x100,0x309,0x2,0x0,0x1800,0x1A26,0x6E8,0x0,0x0,0x412,0x8D9,0x4A};
-const BIG CURVE_Gy={0x1};
-const BIG CURVE_W[2]={{0x3,0x0,0x0,0x0,0x40,0x1,0x0,0x0,0x180,0x30C},{0x1,0x0,0x0,0x0,0x810}};
-const BIG CURVE_SB[2][2]={{{0x4,0x0,0x0,0x0,0x850,0x1,0x0,0x0,0x180,0x30C},{0x1,0x0,0x0,0x0,0x810}},{{0x1,0x0,0x0,0x0,0x810},{0xA,0x0,0x0,0x0,0x9D0,0x7,0x0,0x0,0x1E00,0x1CF0,0x1,0x0,0x1800,0x1A26,0x6E8,0x0,0x0,0x412,0x8D9,0x4A}}};
-const BIG CURVE_WB[4]={{0x0,0x0,0x0,0x0,0x408,0x0,0x0,0x0,0x80,0x104},{0x5,0x0,0x0,0x0,0x14A8,0x2,0x0,0x0,0x700,0xE38,0x0,0x0,0x1800,0x1120,0xC4},{0x3,0x0,0x0,0x0,0xC58,0x1,0x0,0x0,0x380,0x71C,0x0,0x0,0xC00,0x890,0x62},{0x1,0x0,0x0,0x0,0xC18,0x0,0x0,0x0,0x80,0x104}};
-const BIG CURVE_BB[4][4]={{{0xD,0x0,0x0,0x0,0x608,0x8,0x0,0x0,0x1F80,0x1FFC,0x1,0x0,0x1800,0x1A26,0x6E8,0x0,0x0,0x412,0x8D9,0x4A},{0xC,0x0,0x0,0x0,0x608,0x8,0x0,0x0,0x1F80,0x1FFC,0x1,0x0,0x1800,0x1A26,0x6E8,0x0,0x0,0x412,0x8D9,0x4A},{0xC,0x0,0x0,0x0,0x608,0x8,0x0,0x0,0x1F80,0x1FFC,0x1,0x0,0x1800,0x1A26,0x6E8,0x0,0x0,0x412,0x8D9,0x4A},{0x2,0x0,0x0,0x0,0x810}},{{0x1,0x0,0x0,0x0,0x810},{0xC,0x0,0x0,0x0,0x608,0x8,0x0,0x0,0x1F80,0x1FFC,0x1,0x0,0x1800,0x1A26,0x6E8,0x0,0x0,0x412,0x8D9,0x4A},{0xD,0x0,0x0,0x0,0x608,0x8,0x0,0x0,0x1F80,0x1FFC,0x1,0x0,0x1800,0x1A26,0x6E8,0x0,0x0,0x412,0x8D9,0x4A},{0xC,0x0,0x0,0x0,0x608,0x8,0x0,0x0,0x1F80,0x1FFC,0x1,0x0,0x1800,0x1A26,0x6E8,0x0,0x0,0x412,0x8D9,0x4A}},{{0x2,0x0,0x0,0x0,0x810},{0x1,0x0,0x0,0x0,0x810},{0x1,0x0,0x0,0x0,0x810},{0x1,0x0,0x0,0x0,0x810}},{{0x2,0x0,0x0,0x0,0x408},{0x2,0x0,0x0,0x0,0x1020},{0xA,0x0,0x0,0x0,0x200,0x8,0x0,0x0,0x1F80,0x1FFC,0x1,0x0,0x1800,0x1A26,0x6E8,0x0,0x0,0x412,0x8D9,0x4A},{0x2,0x0,0x0,0x0,0x408}}};
-#endif
-
-#if CHUNK==32
-
-const chunk MConst=0x179435E5;
-const BIG Modulus={0x13,0x18000000,0x4E9,0x2000000,0x8612,0x6C00000,0x6E8D1,0x10480000,0x252364};
-const BIG CURVE_Order={0xD,0x8000000,0x428,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364};
-const BIG CURVE_B={0x2};
-const BIG CURVE_Bnx={0x1,0x4000000,0x10};
-const BIG CURVE_Cru={0x7,0xC000000,0x1B3,0x12000000,0x2490,0x11200000,0x126CD};
-const BIG CURVE_Fra={0xF2A6DE9,0xBEF3603,0xFDDF0B8,0x12E9249A,0x953F850,0xDA85423,0x1232D926,0x32425CF,0x1B3776};
-const BIG CURVE_Frb={0x10D5922A,0xC10C9FC,0x10221431,0xF16DB65,0x16AC8DC1,0x1917ABDC,0xDD40FAA,0xD23DA30,0x9EBEE};
-const BIG CURVE_Pxa={0x15FD0CB4,0x1D5963C9,0x1F315F0A,0xBC633C9,0x1763B05A,0x1B927B6F,0x1FA8CD7E,0x1A9EABD4,0x95B04};
-const BIG CURVE_Pxb={0x10962455,0x503E83C,0x9EA978E,0x1B0D7C7A,0x147F39D6,0x1FC4F02B,0x1ED2750A,0x14F81068,0x5D4D8};
-const BIG CURVE_Pya={0x1A08A46C,0xD6E7343,0x290647E,0x105661D3,0xB1F1690,0xE261BC2,0x4FE85B4,0x17E4BCA6,0xABF2A};
-const BIG CURVE_Pyb={0x5F306EC,0x16FC46A0,0x1744E839,0x9040ED5,0x19D6A5C0,0x138F23C0,0xAF6CE18,0x10FCCF3B,0x18769A};
-const BIG CURVE_Gx={0x12,0x18000000,0x4E9,0x2000000,0x8612,0x6C00000,0x6E8D1,0x10480000,0x252364};
-const BIG CURVE_Gy={0x1};
-const BIG CURVE_W[2]={{0x3,0x0,0x81,0x3000000,0x618},{0x1,0x8000000,0x20}};
-const BIG CURVE_SB[2][2]={{{0x4,0x8000000,0xA1,0x3000000,0x618},{0x1,0x8000000,0x20}},{{0x1,0x8000000,0x20},{0xA,0x8000000,0x3A7,0x1C000000,0x79E1,0x6C00000,0x6E8D1,0x10480000,0x252364}}};
-const BIG CURVE_WB[4]={{0x0,0x4000000,0x10,0x1000000,0x208},{0x5,0x14000000,0x152,0xE000000,0x1C70,0xC00000,0xC489},{0x3,0xC000000,0xB1,0x7000000,0xE38,0x10600000,0x6244},{0x1,0xC000000,0x30,0x1000000,0x208}};
-const BIG CURVE_BB[4][4]={{{0xD,0x4000000,0x418,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364},{0xC,0x4000000,0x418,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364},{0xC,0x4000000,0x418,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364},{0x2,0x8000000,0x20}},{{0x1,0x8000000,0x20},{0xC,0x4000000,0x418,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364},{0xD,0x4000000,0x418,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364},{0xC,0x4000000,0x418,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364}},{{0x2,0x8000000,0x20},{0x1,0x8000000,0x20},{0x1,0x8000000,0x20},{0x1,0x8000000,0x20}},{{0x2,0x4000000,0x10},{0x2,0x10000000,0x40},{0xA,0x0,0x408,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364},{0x2,0x4000000,0x10}}};
-#endif
-
-#if CHUNK==64
-
-const chunk MConst=0x435E50D79435E5;
-const BIG Modulus={0x13,0x13A7,0x80000000086121,0x40000001BA344D,0x25236482};
-const BIG CURVE_Order={0xD,0x800000000010A1,0x8000000007FF9F,0x40000001BA344D,0x25236482};
-const BIG CURVE_B={0x2};
-const BIG CURVE_Bnx={0x80000000000001,0x40};
-const BIG CURVE_Cru={0x80000000000007,0x6CD,0x40000000024909,0x49B362};
-const BIG CURVE_Fra={0x7DE6C06F2A6DE9,0x74924D3F77C2E1,0x50A846953F8509,0x212E7C8CB6499B,0x1B377619};
-const BIG CURVE_Frb={0x82193F90D5922A,0x8B6DB2C08850C5,0x2F57B96AC8DC17,0x1ED1837503EAB2,0x9EBEE69};
-const BIG CURVE_Pxa={0xAB2C7935FD0CB4,0xE319E4FCC57C2B,0x24F6DF763B05A5,0xF55EA7EA335FB7,0x95B04D4};
-const BIG CURVE_Pxb={0xA07D0790962455,0x86BE3D27AA5E38,0x89E05747F39D6D,0xC08347B49D42BF,0x5D4D8A7};
-const BIG CURVE_Pya={0xADCE687A08A46C,0x2B30E98A4191F9,0x4C3784B1F16908,0x25E5313FA16D1C,0xABF2ABF};
-const BIG CURVE_Pyb={0xDF88D405F306EC,0x82076ADD13A0E6,0x1E47819D6A5C04,0xE679DABDB38627,0x18769A87};
-const BIG CURVE_Gx={0x12,0x13A7,0x80000000086121,0x40000001BA344D,0x25236482};
-const BIG CURVE_Gy={0x1};
-const BIG CURVE_W[2]={{0x3,0x80000000000204,0x6181},{0x1,0x81}};
-const BIG CURVE_SB[2][2]={{{0x4,0x80000000000285,0x6181},{0x1,0x81}},{{0x1,0x81},{0xA,0xE9D,0x80000000079E1E,0x40000001BA344D,0x25236482}}};
-const BIG CURVE_WB[4]={{0x80000000000000,0x80000000000040,0x2080},{0x80000000000005,0x54A,0x8000000001C707,0x312241},{0x80000000000003,0x800000000002C5,0xC000000000E383,0x189120},{0x80000000000001,0x800000000000C1,0x2080}};
-const BIG CURVE_BB[4][4]={{{0x8000000000000D,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482},{0x8000000000000C,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482},{0x8000000000000C,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482},{0x2,0x81}},{{0x1,0x81},{0x8000000000000C,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482},{0x8000000000000D,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482},{0x8000000000000C,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482}},{{0x2,0x81},{0x1,0x81},{0x1,0x81},{0x1,0x81}},{{0x80000000000002,0x40},{0x2,0x102},{0xA,0x80000000001020,0x8000000007FF9F,0x40000001BA344D,0x25236482},{0x80000000000002,0x40}}};
-#endif
-
-#endif
-
-#if CHOICE==BNT
-
-/* GT-Strong BN curve */
-
-const int CURVE_A=0;
-#if CHUNK==16
-
-const chunk MConst=0x4E5;
-const BIG Modulus={0x713,0x15A5,0x1FBB,0x1B77,0xBE9,0x125D,0x13D1,0xAC2,0xA55,0x374,0x157C,0xDF1,0x1369,0x5D5,0x1BE8,0x29,0x517,0x6DB,0x48,0x48};
-const BIG CURVE_Order={0x10D,0x981,0x1FA3,0xAEE,0x3A7,0x59B,0xACB,0x692,0x8D4,0x74,0x157C,0xDF1,0x1369,0x5D5,0x1BE8,0x29,0x517,0x6DB,0x48,0x48};
-const BIG CURVE_B={0x2};
-const BIG CURVE_Bnx={0x81,0x2,0x1800,0x100,0x400};
-const BIG CURVE_Cru={0xD87,0x1A7E,0x156A,0x16A7,0x1ADE,0x188F,0xAEA,0x14BE,0xC82,0xBB2,0x132,0xA2A,0x1476,0xD8,0x120};
-const BIG CURVE_Fra={0x22,0xE40,0x13AB,0xBA2,0x159F,0x671,0x1BEB,0x9A,0xC49,0xDF3,0xC84,0x142,0x1F19,0x1284,0x53D,0x1887,0x9BB,0x1496,0xA28,0x26};
-const BIG CURVE_Frb={0x6F1,0x765,0xC10,0xFD5,0x164A,0xBEB,0x17E6,0xA27,0x1E0C,0x1580,0x8F7,0xCAF,0x1450,0x1350,0x16AA,0x7A2,0x1B5B,0x1244,0x161F,0x21};
-const BIG CURVE_Pxa={0x5BB,0x473,0x188A,0x130F,0x1BE8,0x1189,0x12A9,0x15A3,0xC00,0x1BE6,0x1522,0x82,0x1325,0x2A,0x1AF3,0x673,0x4C1,0x1E68,0x120F,0x28};
-const BIG CURVE_Pxb={0x2C0,0x6DF,0x202,0xF11,0x13A6,0x1A42,0x78,0x1C3F,0x157F,0xBDC,0x146D,0x634,0x10A6,0x1FE2,0xB68,0x1860,0x184E,0x1599,0x1FD1,0x10};
-const BIG CURVE_Pya={0xA1D,0x106,0x11F8,0x58,0x16C2,0xCF9,0x1A0E,0x2CF,0xCB4,0x164A,0x7DC,0xA87,0x1C6E,0x1634,0x1D28,0x17A,0x102B,0x14E0,0x1A30,0x29};
-const BIG CURVE_Pyb={0x8F2,0xB31,0x1F1C,0x1086,0x6BD,0x1BEE,0x1EF2,0x1C2C,0xA27,0xE8,0x1C9A,0x18EA,0xA82,0x160C,0x7B7,0x97A,0x245,0x1523,0xBF8,0x2F};
-const BIG CURVE_Gx={0x712,0x15A5,0x1FBB,0x1B77,0xBE9,0x125D,0x13D1,0xAC2,0xA55,0x374,0x157C,0xDF1,0x1369,0x5D5,0x1BE8,0x29,0x517,0x6DB,0x48,0x48};
-const BIG CURVE_Gy={0x1};
-const BIG CURVE_W[2]={{0x403,0xC1C,0x18,0xC86,0x1842,0xCC1,0x906,0x430,0x181,0x300},{0x101,0x4,0x1000,0x201,0x800}};
-const BIG CURVE_SB[2][2]={{{0x504,0xC20,0x1018,0xE87,0x42,0xCC2,0x906,0x430,0x181,0x300},{0x101,0x4,0x1000,0x201,0x800}},{{0x101,0x4,0x1000,0x201,0x800},{0x1D0A,0x1D64,0x1F8A,0x1E68,0xB64,0x18D9,0x1C4,0x262,0x753,0x1D74,0x157B,0xDF1,0x1369,0x5D5,0x1BE8,0x29,0x517,0x6DB,0x48,0x48}}};
-const BIG CURVE_WB[4]={{0x80,0x406,0x1808,0x280,0xC16,0x440,0x302,0xC10,0x80,0x100},{0xA85,0x462,0x102,0xA72,0x36B,0xE36,0xD4B,0x5F4,0x1EAD,0x1476,0x1621,0x6C6,0xDA4,0x90,0xC0},{0x583,0x232,0xC81,0x15B9,0x3B5,0x171B,0x6A5,0x12FA,0xF56,0x1A3B,0xB10,0x363,0x6D2,0x48,0x60},{0x181,0x40A,0x808,0x482,0x1416,0x440,0x302,0xC10,0x80,0x100}};
-const BIG CURVE_BB[4][4]={{{0x8D,0x97F,0x7A3,0x9EE,0x1FA7,0x59A,0xACB,0x692,0x8D4,0x74,0x157C,0xDF1,0x1369,0x5D5,0x1BE8,0x29,0x517,0x6DB,0x48,0x48},{0x8C,0x97F,0x7A3,0x9EE,0x1FA7,0x59A,0xACB,0x692,0x8D4,0x74,0x157C,0xDF1,0x1369,0x5D5,0x1BE8,0x29,0x517,0x6DB,0x48,0x48},{0x8C,0x97F,0x7A3,0x9EE,0x1FA7,0x59A,0xACB,0x692,0x8D4,0x74,0x157C,0xDF1,0x1369,0x5D5,0x1BE8,0x29,0x517,0x6DB,0x48,0x48},{0x102,0x4,0x1000,0x201,0x800}},{{0x101,0x4,0x1000,0x201,0x800},{0x8C,0x97F,0x7A3,0x9EE,0x1FA7,0x59A,0xACB,0x692,0x8D4,0x74,0x157C,0xDF1,0x1369,0x5D5,0x1BE8,0x29,0x517,0x6DB,0x48,0x48},{0x8D,0x97F,0x7A3,0x9EE,0x1FA7,0x59A,0xACB,0x692,0x8D4,0x74,0x157C,0xDF1,0x1369,0x5D5,0x1BE8,0x29,0x517,0x6DB,0x48,0x48},{0x8C,0x97F,0x7A3,0x9EE,0x1FA7,0x59A,0xACB,0x692,0x8D4,0x74,0x157C,0xDF1,0x1369,0x5D5,0x1BE8,0x29,0x517,0x6DB,0x48,0x48}},{{0x102,0x4,0x1000,0x201,0x800},{0x101,0x4,0x1000,0x201,0x800},{0x101,0x4,0x1000,0x201,0x800},{0x101,0x4,0x1000,0x201,0x800}},{{0x82,0x2,0x1800,0x100,0x400},{0x202,0x8,0x0,0x403,0x1000},{0xA,0x97D,0xFA3,0x8ED,0x1BA7,0x59A,0xACB,0x692,0x8D4,0x74,0x157C,0xDF1,0x1369,0x5D5,0x1BE8,0x29,0x517,0x6DB,0x48,0x48},{0x82,0x2,0x1800,0x100,0x400}}};
-#endif
-
-#if CHUNK==32
-
-const chunk MConst=0x1914C4E5;
-const BIG Modulus={0xEB4A713,0x14EDDFF7,0x1D192EAF,0x14AAAC29,0xD5F06E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120};
-const BIG CURVE_Order={0xD30210D,0x13ABBBF4,0xCB2CD8E,0x11A86925,0xD5F00E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120};
-const BIG CURVE_B={0x2};
-const BIG CURVE_Bnx={0x4081,0x40300,0x10};
-const BIG CURVE_Cru={0xB4FCD87,0xF5A9EAD,0xEAC47EB,0x19054BE5,0x104C9764,0x18A3B28A,0x12006};
-const BIG CURVE_Fra={0xDC80022,0xFAE8A75,0x1EB338D6,0x189209AD,0x13211BE6,0x4F8C850,0x10E53D94,0x12593778,0x1328A2};
-const BIG CURVE_Frb={0xECA6F1,0x53F5582,0x1E65F5D9,0x1C18A27B,0x1A3DEB01,0x10A2832B,0x1456AA9A,0x9136B67,0x10D87E};
-const BIG CURVE_Pxa={0x88E65BB,0x144C3F11,0xA98C4EF,0x18015A39,0x1548B7CC,0xA992820,0xE7AF301,0x19A09826,0x14483F};
-const BIG CURVE_Pxb={0x8DBE2C0,0x133C4440,0x78D214E,0xAFFC3F0,0x51B57B9,0x285318D,0xC0B68FF,0x166709D8,0x87F46};
-const BIG CURVE_Pya={0x20CA1D,0x101623F,0xE67CDB,0x19682CFD,0x19F72C94,0x14E372A1,0xF5D28B1,0x13820561,0x14E8C2};
-const BIG CURVE_Pyb={0x116628F2,0x1EC21BE3,0xF2DF71A,0x144FC2CF,0x172681D0,0xC54163A,0xF47B7B0,0x148C48A9,0x17AFE2};
-const BIG CURVE_Gx={0xEB4A712,0x14EDDFF7,0x1D192EAF,0x14AAAC29,0xD5F06E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120};
-const BIG CURVE_Gy={0x1};
-const BIG CURVE_W[2]={{0x1838403,0x1321803,0x106660E1,0x3024304,0x600},{0x8101,0x80600,0x20}};
-const BIG CURVE_SB[2][2]={{{0x1840504,0x13A1E03,0x10666101,0x3024304,0x600},{0x8101,0x80600,0x20}},{{0x8101,0x80600,0x20},{0xBAC9D0A,0x1279A3F1,0x1C4C6CAD,0xEA62620,0xD5EFAE8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120}}};
-const BIG CURVE_WB[4]={{0x80C080,0xB0A0301,0x10222030,0x100C101,0x200},{0x88C4A85,0x15A9C820,0x14B71B0D,0x1D5A5F46,0x158868ED,0x106D21B1,0xC004},{0x4464583,0x1AD6E590,0xA5B8D8E,0x1EAD2FA3,0x1AC43476,0x83690D8,0x6002},{0x814181,0xB120901,0x10222050,0x100C101,0x200}};
-const BIG CURVE_BB[4][4]={{{0xD2FE08D,0x13A7B8F4,0xCB2CD7E,0x11A86925,0xD5F00E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120},{0xD2FE08C,0x13A7B8F4,0xCB2CD7E,0x11A86925,0xD5F00E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120},{0xD2FE08C,0x13A7B8F4,0xCB2CD7E,0x11A86925,0xD5F00E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120},{0x8102,0x80600,0x20}},{{0x8101,0x80600,0x20},{0xD2FE08C,0x13A7B8F4,0xCB2CD7E,0x11A86925,0xD5F00E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120},{0xD2FE08D,0x13A7B8F4,0xCB2CD7E,0x11A86925,0xD5F00E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120},{0xD2FE08C,0x13A7B8F4,0xCB2CD7E,0x11A86925,0xD5F00E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120}},{{0x8102,0x80600,0x20},{0x8101,0x80600,0x20},{0x8101,0x80600,0x20},{0x8101,0x80600,0x20}},{{0x4082,0x40300,0x10},{0x10202,0x100C00,0x40},{0xD2FA00A,0x13A3B5F4,0xCB2CD6E,0x11A86925,0xD5F00E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120},{0x4082,0x40300,0x10}}};
-#endif
-
-#if CHUNK==64
-
-const chunk MConst=0xC5A872D914C4E5;
-const BIG Modulus={0x9DBBFEEEB4A713,0x555614F464BABE,0x3696F8D5F06E8A,0x6517014EFA0BAB,0x240120DB};
-const BIG CURVE_Order={0x75777E8D30210D,0xD43492B2CB363A,0x3696F8D5F00E88,0x6517014EFA0BAB,0x240120DB};
-const BIG CURVE_B={0x2};
-const BIG CURVE_Bnx={0x806000004081,0x40};
-const BIG CURVE_Cru={0xEB53D5AB4FCD87,0x82A5F2BAB11FAD,0x47651504C9764C,0x4801B1};
-const BIG CURVE_Fra={0xF5D14EADC80022,0x4904D6FACCE359,0xF190A13211BE6C,0xC9BBC4394F6509,0x1328A292};
-const BIG CURVE_Frb={0xA7EAB040ECA6F1,0xC513DF997D764,0x450657A3DEB01E,0x9B5B3D15AAA6A1,0x10D87E48};
-const BIG CURVE_Pxa={0x8987E2288E65BB,0xAD1CAA6313BE,0x325041548B7CCC,0x4C1339EBCC055,0x14483FCD};
-const BIG CURVE_Pxb={0x67888808DBE2C0,0x7FE1F81E34853A,0xA631A51B57B95,0x384EC302DA3FC5,0x87F46B3};
-const BIG CURVE_Pya={0x202C47E020CA1D,0xB4167E8399F36C,0xC6E5439F72C94C,0x102B0BD74A2C69,0x14E8C29C};
-const BIG CURVE_Pyb={0xD8437C716628F2,0x27E167BCB7DC6B,0xA82C7572681D0A,0x62454BD1EDEC18,0x17AFE2A4};
-const BIG CURVE_Gx={0x9DBBFEEEB4A712,0x555614F464BABE,0x3696F8D5F06E8A,0x6517014EFA0BAB,0x240120DB};
-const BIG CURVE_Gy={0x1};
-const BIG CURVE_W[2]={{0x26430061838403,0x81218241998384,0x6001},{0x100C000008101,0x80}};
-const BIG CURVE_SB[2][2]={{{0x2743C061840504,0x81218241998404,0x6001},{0x100C000008101,0x80}},{{0x100C000008101,0x80},{0x4F347E2BAC9D0A,0x5313107131B2B6,0x3696F8D5EFAE87,0x6517014EFA0BAB,0x240120DB}}};
-const BIG CURVE_WB[4]={{0x6140602080C080,0x806080C08880C1,0x2000},{0xB53904088C4A85,0xAD2FA352DC6C36,0xDA436358868EDE,0x300120},{0x5ADCB204464583,0x5697D1A96E363B,0x6D21B1AC43476F,0x180090},{0x62412020814181,0x806080C0888141,0x2000}};
-const BIG CURVE_BB[4][4]={{{0x74F71E8D2FE08D,0xD43492B2CB35FA,0x3696F8D5F00E88,0x6517014EFA0BAB,0x240120DB},{0x74F71E8D2FE08C,0xD43492B2CB35FA,0x3696F8D5F00E88,0x6517014EFA0BAB,0x240120DB},{0x74F71E8D2FE08C,0xD43492B2CB35FA,0x3696F8D5F00E88,0x6517014EFA0BAB,0x240120DB},{0x100C000008102,0x80}},{{0x100C000008101,0x80},{0x74F71E8D2FE08C,0xD43492B2CB35FA,0x3696F8D5F00E88,0x6517014EFA0BAB,0x240120DB},{0x74F71E8D2FE08D,0xD43492B2CB35FA,0x3696F8D5F00E88,0x6517014EFA0BAB,0x240120DB},{0x74F71E8D2FE08C,0xD43492B2CB35FA,0x3696F8D5F00E88,0x6517014EFA0BAB,0x240120DB}},{{0x100C000008102,0x80},{0x100C000008101,0x80},{0x100C000008101,0x80},{0x100C000008101,0x80}},{{0x806000004082,0x40},{0x2018000010202,0x100},{0x7476BE8D2FA00A,0xD43492B2CB35BA,0x3696F8D5F00E88,0x6517014EFA0BAB,0x240120DB},{0x806000004082,0x40}}};
-#endif
-
-#endif
-
-#if CHOICE==BNT2
-
-const int CURVE_A=0;
-#if CHUNK==16
-
-const chunk MConst=0x1CDD;
-const BIG Modulus={0x48B,0x305,0xAED,0x5B8,0x1E8B,0xB28,0x3C3,0x1C85,0xF93,0x40E,0x1400,0x1713,0xF3,0x710,0x16DD,0xB55,0x10F,0x412,0x1,0x48};
-const BIG CURVE_Order={0xBF5,0xD51,0x944,0x16E3,0x1D7F,0x1C19,0x1EDC,0x1C24,0xF8D,0x10E,0x1400,0x1713,0xF3,0x710,0x16DD,0xB55,0x10F,0x412,0x1,0x48};
-const BIG CURVE_B={0x2};
-const BIG CURVE_Bnx={0x205,0x304,0x40,0x4,0x400};
-const BIG CURVE_Cru={0x1D33,0x335,0x1112,0x4E,0xFB5,0x387,0x59,0xEE6,0x155B,0x11B3,0x1B3C,0x2F7,0xC36,0x3,0x120};
-const BIG CURVE_Fra={0x1062,0x1D77,0x125C,0x4D1,0x92B,0x1E72,0xF0E,0x1366,0x1CC6,0xADD,0x1FC6,0x1F46,0x1F67,0x520,0x1AF4,0x1956,0x9E8,0x1C69,0x1382,0x24};
-const BIG CURVE_Frb={0x1429,0x58D,0x1890,0xE6,0x1560,0xCB6,0x14B4,0x91E,0x12CD,0x1930,0x1439,0x17CC,0x18B,0x1EF,0x1BE9,0x11FE,0x1726,0x7A8,0xC7E,0x23};
-const BIG CURVE_Pxa={0x3C8,0x1A05,0xE67,0x1924,0x4AC,0x8BC,0x598,0x149D,0x15CD,0x359,0x185C,0xAD2,0x17B0,0x1CEB,0x609,0x18C6,0x1693,0x1E7C,0x1F05,0x2D};
-const BIG CURVE_Pxb={0x1540,0x2A4,0x2B6,0xAF5,0x105,0x883,0x1BD9,0xF7C,0x1B6F,0x8BE,0xA57,0x120F,0x565,0xC4,0x272,0xEB2,0x1D59,0x805,0xD6D,0x3D};
-const BIG CURVE_Pya={0x513,0x110,0x1145,0x17D9,0x1147,0x19BD,0x1839,0xF10,0x44A,0x934,0xD7C,0x1072,0x51B,0x6FD,0xA75,0x455,0x1614,0x4C3,0x3B9,0x3D};
-const BIG CURVE_Pyb={0x78E,0x1BE7,0x3D5,0x1265,0x1FB,0x12BC,0x9BE,0x8DC,0x1EB7,0x713,0x7EE,0x1B78,0xA93,0xEBB,0xE8A,0x77B,0x1AE3,0x66D,0x13BD,0x47};
-const BIG CURVE_Gx={0x48A,0x305,0xAED,0x5B8,0x1E8B,0xB28,0x3C3,0x1C85,0xF93,0x40E,0x1400,0x1713,0xF3,0x710,0x16DD,0xB55,0x10F,0x412,0x1,0x48};
-const BIG CURVE_Gy={0x1};
-const BIG CURVE_W[2]={{0x1083,0x9A3,0xA8,0xEC5,0x110B,0xF0E,0x4E6,0x60,0x6,0x300},{0x409,0x608,0x80,0x8,0x800}};
-const BIG CURVE_SB[2][2]={{{0x148C,0xFAB,0x128,0xECD,0x190B,0xF0E,0x4E6,0x60,0x6,0x300},{0x409,0x608,0x80,0x8,0x800}},{{0x409,0x608,0x80,0x8,0x800},{0x1B72,0x3AD,0x89C,0x81E,0xC74,0xD0B,0x19F6,0x1BC4,0xF87,0x1E0E,0x13FF,0x1713,0xF3,0x710,0x16DD,0xB55,0x10F,0x412,0x1,0x48}}};
-const BIG CURVE_WB[4]={{0x224,0x1385,0x1522,0x4E5,0x1459,0x504,0x1A2,0x20,0x2,0x100},{0xF19,0x187,0xB3C,0x14AE,0x1D5,0x1B9,0x18D5,0xA2E,0x396,0xDCD,0x1228,0x1FA,0x824,0x2,0xC0},{0x188F,0x245,0x5BE,0x1A59,0x12EA,0x10DC,0xC6A,0x517,0x11CB,0x6E6,0x914,0xFD,0x412,0x1,0x60},{0x62D,0x198D,0x15A2,0x4ED,0x1C59,0x504,0x1A2,0x20,0x2,0x100}};
-const BIG CURVE_BB[4][4]={{{0x9F1,0xA4D,0x904,0x16DF,0x197F,0x1C19,0x1EDC,0x1C24,0xF8D,0x10E,0x1400,0x1713,0xF3,0x710,0x16DD,0xB55,0x10F,0x412,0x1,0x48},{0x9F0,0xA4D,0x904,0x16DF,0x197F,0x1C19,0x1EDC,0x1C24,0xF8D,0x10E,0x1400,0x1713,0xF3,0x710,0x16DD,0xB55,0x10F,0x412,0x1,0x48},{0x9F0,0xA4D,0x904,0x16DF,0x197F,0x1C19,0x1EDC,0x1C24,0xF8D,0x10E,0x1400,0x1713,0xF3,0x710,0x16DD,0xB55,0x10F,0x412,0x1,0x48},{0x40A,0x608,0x80,0x8,0x800}},{{0x409,0x608,0x80,0x8,0x800},{0x9F0,0xA4D,0x904,0x16DF,0x197F,0x1C19,0x1EDC,0x1C24,0xF8D,0x10E,0x1400,0x1713,0xF3,0x710,0x16DD,0xB55,0x10F,0x412,0x1,0x48},{0x9F1,0xA4D,0x904,0x16DF,0x197F,0x1C19,0x1EDC,0x1C24,0xF8D,0x10E,0x1400,0x1713,0xF3,0x710,0x16DD,0xB55,0x10F,0x412,0x1,0x48},{0x9F0,0xA4D,0x904,0x16DF,0x197F,0x1C19,0x1EDC,0x1C24,0xF8D,0x10E,0x1400,0x1713,0xF3,0x710,0x16DD,0xB55,0x10F,0x412,0x1,0x48}},{{0x40A,0x608,0x80,0x8,0x800},{0x409,0x608,0x80,0x8,0x800},{0x409,0x608,0x80,0x8,0x800},{0x409,0x608,0x80,0x8,0x800}},{{0x206,0x304,0x40,0x4,0x400},{0x812,0xC10,0x100,0x10,0x1000},{0x7EA,0x749,0x8C4,0x16DB,0x157F,0x1C19,0x1EDC,0x1C24,0xF8D,0x10E,0x1400,0x1713,0xF3,0x710,0x16DD,0xB55,0x10F,0x412,0x1,0x48},{0x206,0x304,0x40,0x4,0x400}}};
-#endif
-
-#if CHUNK==32
-
-const chunk MConst=0x6505CDD;
-const BIG Modulus={0x1460A48B,0x596E15D,0x1C35947A,0x1F27C851,0x1D00081C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004};
-const BIG CURVE_Order={0x11AA2BF5,0x1FDB8D28,0xDCE0CF5,0x1F1BC24F,0x1D00021C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004};
-const BIG CURVE_B={0x2};
-const BIG CURVE_Bnx={0x608205,0x1008,0x10};
-const BIG CURVE_Cru={0x866BD33,0x1A813A22,0x591C3BE,0xAB6EE60,0x1ECF2367,0x361B0BD,0x12000};
-const BIG CURVE_Fra={0x13AEF062,0x1593464B,0x10EF3924,0x198D3667,0x17F195BB,0xFB3FD1,0xADAF429,0x11A53D19,0x124E0B};
-const BIG CURVE_Frb={0xB1B429,0x10039B12,0xB465B55,0x59A91EA,0x50E7261,0xF0C5DF3,0x1FDBE90F,0x1EA2E4D1,0x11B1F8};
-const BIG CURVE_Pxa={0x1F40A3C8,0x166491CC,0x19845E12,0xB9B49D2,0x161706B3,0xBBD82B4,0x18C609E7,0x19F2D278,0x16FC17};
-const BIG CURVE_Pxb={0x18549540,0x2ABD456,0x1D944184,0x16DEF7CD,0x1A95D17D,0x42B2C83,0x16427206,0x17AB2E,0x1EB5B5};
-const BIG CURVE_Pya={0x14220513,0x3DF6628,0x39CDEC5,0x894F10C,0x135F1268,0x1D28DC1C,0xAAA7537,0x130EC284,0x1E8EE4};
-const BIG CURVE_Pyb={0x177CE78E,0x1DC9947A,0x1BE95E07,0x1D6E8DC4,0x1FB8E27,0x1B549EDE,0xF6E8A75,0x19B75C67,0x23CEF4};
-const BIG CURVE_Gx={0x1460A48A,0x596E15D,0x1C35947A,0x1F27C851,0x1D00081C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004};
-const BIG CURVE_Gy={0x1};
-const BIG CURVE_W[2]={{0x1347083,0x5BB1415,0xE678744,0xC0602,0x600},{0xC10409,0x2010,0x20}};
-const BIG CURVE_SB[2][2]={{{0x1F5748C,0x5BB3425,0xE678764,0xC0602,0x600},{0xC10409,0x2010,0x20}},{{0xC10409,0x2010,0x20},{0x1075BB72,0x1A207913,0x1F6685B1,0x1F0FBC4C,0x1CFFFC1C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004}}};
-const BIG CURVE_WB[4]={{0xA70A224,0xC9396A4,0x1A228251,0x40200,0x200},{0x1030EF19,0xAD2B967,0xD50DC87,0x72CA2EC,0x148A1B9A,0x241207E,0xC000},{0x1848B88F,0x156964B7,0x6A86E4B,0x3965176,0xA450DCD,0x120903F,0x6000},{0xB31A62D,0xC93B6B4,0x1A228271,0x40200,0x200}};
-const BIG CURVE_BB[4][4]={{{0x1149A9F1,0x1FDB7D20,0xDCE0CE5,0x1F1BC24F,0x1D00021C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004},{0x1149A9F0,0x1FDB7D20,0xDCE0CE5,0x1F1BC24F,0x1D00021C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004},{0x1149A9F0,0x1FDB7D20,0xDCE0CE5,0x1F1BC24F,0x1D00021C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004},{0xC1040A,0x2010,0x20}},{{0xC10409,0x2010,0x20},{0x1149A9F0,0x1FDB7D20,0xDCE0CE5,0x1F1BC24F,0x1D00021C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004},{0x1149A9F1,0x1FDB7D20,0xDCE0CE5,0x1F1BC24F,0x1D00021C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004},{0x1149A9F0,0x1FDB7D20,0xDCE0CE5,0x1F1BC24F,0x1D00021C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004}},{{0xC1040A,0x2010,0x20},{0xC10409,0x2010,0x20},{0xC10409,0x2010,0x20},{0xC10409,0x2010,0x20}},{{0x608206,0x1008,0x10},{0x1820812,0x4020,0x40},{0x10E927EA,0x1FDB6D18,0xDCE0CD5,0x1F1BC24F,0x1D00021C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004},{0x608206,0x1008,0x10}}};
-#endif
-
-#if CHUNK==64
-
-const chunk MConst=0xFE6A47A6505CDD;
-const BIG Modulus={0xB2DC2BB460A48B,0x93E428F0D651E8,0xF3B89D00081CF,0x410F5AADB74E20,0x24000482};
-const BIG CURVE_Order={0xFB71A511AA2BF5,0x8DE127B73833D7,0xF3B89D00021CF,0x410F5AADB74E20,0x24000482};
-const BIG CURVE_B={0x2};
-const BIG CURVE_Bnx={0x20100608205,0x40};
-const BIG CURVE_Cru={0x5027444866BD33,0x5B773016470EFB,0xC3617BECF23675,0x480006};
-const BIG CURVE_Fra={0xB268C973AEF062,0xC69B33C3BCE492,0xF67FA37F195BBC,0x29E8CAB6BD0A41,0x124E0B8D};
-const BIG CURVE_Frb={0x736240B1B429,0xCD48F52D196D56,0x18BBE650E72612,0x17268FF6FA43DE,0x11B1F8F5};
-const BIG CURVE_Pxa={0xCC92399F40A3C8,0xCDA4E96611784A,0x7B056961706B35,0x9693C6318279D7,0x16FC17CF};
-const BIG CURVE_Pxb={0x557A8AD8549540,0x6F7BE6F6510610,0x565907A95D17DB,0xBD5975909C8188,0x1EB5B500};
-const BIG CURVE_Pya={0x7BECC514220513,0x4A78860E737B14,0x51B83935F12684,0x761422AA9D4DFA,0x1E8EE498};
-const BIG CURVE_Pyb={0xB9328F577CE78E,0xB746E26FA5781F,0xA93DBC1FB8E27E,0xBAE33BDBA29D76,0x23CEF4CD};
-const BIG CURVE_Gx={0xB2DC2BB460A48A,0x93E428F0D651E8,0xF3B89D00081CF,0x410F5AADB74E20,0x24000482};
-const BIG CURVE_Gy={0x1};
-const BIG CURVE_W[2]={{0xB76282A1347083,0x60301399E1D10,0x6000},{0x40200C10409,0x80}};
-const BIG CURVE_SB[2][2]={{{0xB76684A1F5748C,0x60301399E1D90,0x6000},{0x40200C10409,0x80}},{{0x40200C10409,0x80},{0x440F227075BB72,0x87DE267D9A16C7,0xF3B89CFFFC1CF,0x410F5AADB74E20,0x24000482}}};
-const BIG CURVE_WB[4]={{0x9272D48A70A224,0x20100688A0945,0x2000},{0x5A572CF030EF19,0x9651763543721D,0x8240FD48A1B9A3,0x300004},{0xAD2C96F848B88F,0xCB28BB1AA1B92E,0x41207EA450DCD1,0x180002},{0x9276D68B31A62D,0x20100688A09C5,0x2000}};
-const BIG CURVE_BB[4][4]={{{0xFB6FA41149A9F1,0x8DE127B7383397,0xF3B89D00021CF,0x410F5AADB74E20,0x24000482},{0xFB6FA41149A9F0,0x8DE127B7383397,0xF3B89D00021CF,0x410F5AADB74E20,0x24000482},{0xFB6FA41149A9F0,0x8DE127B7383397,0xF3B89D00021CF,0x410F5AADB74E20,0x24000482},{0x40200C1040A,0x80}},{{0x40200C10409,0x80},{0xFB6FA41149A9F0,0x8DE127B7383397,0xF3B89D00021CF,0x410F5AADB74E20,0x24000482},{0xFB6FA41149A9F1,0x8DE127B7383397,0xF3B89D00021CF,0x410F5AADB74E20,0x24000482},{0xFB6FA41149A9F0,0x8DE127B7383397,0xF3B89D00021CF,0x410F5AADB74E20,0x24000482}},{{0x40200C1040A,0x80},{0x40200C10409,0x80},{0x40200C10409,0x80},{0x40200C10409,0x80}},{{0x20100608206,0x40},{0x80401820812,0x100},{0xFB6DA310E927EA,0x8DE127B7383357,0xF3B89D00021CF,0x410F5AADB74E20,0x24000482},{0x20100608206,0x40}}};
-#endif
-
-
-#endif
-
-#if CHOICE==BNCX
-
-/* MIRACL BN Curve */
-
-const int CURVE_A=0;
-#if CHUNK==16
-
-const chunk MConst=0x1E85;
-const BIG Modulus={0x15B3,0xDA,0x1BD7,0xC47,0x1BE6,0x1F70,0x24,0x1DC3,0x1FD6,0x1921,0x19B4,0x14C6,0x1647,0x1EEF,0x16C2,0x541,0x870,0x0,0x0,0x48};
-const BIG CURVE_Order={0x1F6D,0x1758,0x98D,0x381,0xBE1,0x367,0x1324,0x1DC1,0x1FD6,0x1621,0x19B4,0x14C6,0x1647,0x1EEF,0x16C2,0x541,0x870,0x0,0x0,0x48};
-const BIG CURVE_B={0x2};
-const BIG CURVE_Bnx={0x12B1,0x1E00,0x0,0x0,0x400};
-const BIG CURVE_Cru={0x1C97,0x11A,0x5E5,0x126,0x31E,0x3AB,0x7BE,0xC8E,0x1DDF,0x205,0xFC5,0x1950,0x0,0x0,0x120};
-const BIG CURVE_Fra={0xEA3,0xE40,0xCD5,0x1210,0x15BD,0x1C10,0x5CF,0x4DE,0x773,0x343,0x626,0x194E,0x18AA,0x10C5,0x12BF,0x2C,0x63A,0x17D,0x1642,0x26};
-const BIG CURVE_Frb={0x710,0x129A,0xF01,0x1A37,0x628,0x360,0x1A55,0x18E4,0x1863,0x15DE,0x138E,0x1B78,0x1D9C,0xE29,0x403,0x515,0x236,0x1E83,0x9BD,0x21};
-const BIG CURVE_Pxa={0xC74,0x697,0x1BB9,0xA39,0xC08,0x1393,0xF8,0x17F4,0x1C85,0x1C83,0x12EE,0xB86,0x100F,0x592,0x18D6,0x164A,0x1053,0x963,0x1A0B,0x32};
-const BIG CURVE_Pxb={0xFE1,0x114E,0x2CB,0xB1D,0x147A,0x187,0x827,0x1618,0x1B97,0x1FC0,0x5D0,0x11D3,0x137A,0x8E4,0xA80,0x1EC9,0x1E19,0xF61,0x19AE,0x28};
-const BIG CURVE_Pya={0x9F,0x185F,0x1AF3,0x17F9,0x10CF,0xD9,0x11FB,0x7B0,0x1B3,0xB1B,0x1882,0x1B5D,0x157,0xF11,0x1760,0x571,0x1233,0xECB,0x1E7B,0x14};
-const BIG CURVE_Pyb={0xE9D,0x4C7,0x8A2,0x96,0x1ED9,0x16F5,0x74B,0x14AD,0x64E,0xE14,0xD18,0x1B1A,0x512,0x372,0xD7,0x1812,0xCC4,0x1CF,0x583,0xC};
-const BIG CURVE_Gx={0x15B2,0xDA,0x1BD7,0xC47,0x1BE6,0x1F70,0x24,0x1DC3,0x1FD6,0x1921,0x19B4,0x14C6,0x1647,0x1EEF,0x16C2,0x541,0x870,0x0,0x0,0x48};
-const BIG CURVE_Gy={0x1};
-const BIG CURVE_W[2]={{0xB83,0x117F,0x1245,0x8C6,0x5,0x1C09,0xD00,0x1,0x0,0x300},{0x561,0x1C01,0x1,0x0,0x800}};
-const BIG CURVE_SB[2][2]={{{0x10E4,0xD80,0x1247,0x8C6,0x805,0x1C09,0xD00,0x1,0x0,0x300},{0x561,0x1C01,0x1,0x0,0x800}},{{0x561,0x1C01,0x1,0x0,0x800},{0x13EA,0x5D9,0x1748,0x1ABA,0xBDB,0x75E,0x623,0x1DC0,0x1FD6,0x1321,0x19B4,0x14C6,0x1647,0x1EEF,0x16C2,0x541,0x870,0x0,0x0,0x48}}};
-const BIG CURVE_WB[4]={{0x4B0,0x13D4,0x615,0x1842,0x401,0x958,0xF00,0x0,0x0,0x100},{0x475,0x1110,0x56F,0x1BF3,0x36C,0x1FCD,0x329,0x1DB5,0x1E94,0xE03,0xA83,0x10E0,0x0,0x0,0xC0},{0xB93,0x788,0x12B8,0xDF9,0x13B6,0x1FE6,0x1194,0xEDA,0x1F4A,0x1701,0x541,0x870,0x0,0x0,0x60},{0xA11,0xFD5,0x617,0x1842,0xC01,0x958,0xF00,0x0,0x0,0x100}};
-const BIG CURVE_BB[4][4]={{{0xCBD,0x1958,0x98C,0x381,0x7E1,0x367,0x1324,0x1DC1,0x1FD6,0x1621,0x19B4,0x14C6,0x1647,0x1EEF,0x16C2,0x541,0x870,0x0,0x0,0x48},{0xCBC,0x1958,0x98C,0x381,0x7E1,0x367,0x1324,0x1DC1,0x1FD6,0x1621,0x19B4,0x14C6,0x1647,0x1EEF,0x16C2,0x541,0x870,0x0,0x0,0x48},{0xCBC,0x1958,0x98C,0x381,0x7E1,0x367,0x1324,0x1DC1,0x1FD6,0x1621,0x19B4,0x14C6,0x1647,0x1EEF,0x16C2,0x541,0x870,0x0,0x0,0x48},{0x562,0x1C01,0x1,0x0,0x800}},{{0x561,0x1C01,0x1,0x0,0x800},{0xCBC,0x1958,0x98C,0x381,0x7E1,0x367,0x1324,0x1DC1,0x1FD6,0x1621,0x19B4,0x14C6,0x1647,0x1EEF,0x16C2,0x541,0x870,0x0,0x0,0x48},{0xCBD,0x1958,0x98C,0x381,0x7E1,0x367,0x1324,0x1DC1,0x1FD6,0x1621,0x19B4,0x14C6,0x1647,0x1EEF,0x16C2,0x541,0x870,0x0,0x0,0x48},{0xCBC,0x1958,0x98C,0x381,0x7E1,0x367,0x1324,0x1DC1,0x1FD6,0x1621,0x19B4,0x14C6,0x1647,0x1EEF,0x16C2,0x541,0x870,0x0,0x0,0x48}},{{0x562,0x1C01,0x1,0x0,0x800},{0x561,0x1C01,0x1,0x0,0x800},{0x561,0x1C01,0x1,0x0,0x800},{0x561,0x1C01,0x1,0x0,0x800}},{{0x12B2,0x1E00,0x0,0x0,0x400},{0xAC2,0x1802,0x3,0x0,0x1000},{0x1A0A,0x1B57,0x98B,0x381,0x3E1,0x367,0x1324,0x1DC1,0x1FD6,0x1621,0x19B4,0x14C6,0x1647,0x1EEF,0x16C2,0x541,0x870,0x0,0x0,0x48},{0x12B2,0x1E00,0x0,0x0,0x400}}};
-#endif
-
-#if CHUNK==32
-
-const chunk MConst=0x19789E85;
-const BIG Modulus={0x1C1B55B3,0x13311F7A,0x24FB86F,0x1FADDC30,0x166D3243,0xFB23D31,0x836C2F7,0x10E05,0x240000};
-const BIG CURVE_Order={0x16EB1F6D,0x108E0531,0x1241B3AF,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000};
-const BIG CURVE_B={0x2};
-const BIG CURVE_Bnx={0x3C012B1,0x0,0x10};
-const BIG CURVE_Cru={0x14235C97,0xF0498BC,0x1BE1D58C,0x1BBEC8E3,0x3F1440B,0x654,0x12000};
-const BIG CURVE_Fra={0x15C80EA3,0x1EC8419A,0x1CFE0856,0xEE64DE2,0x11898686,0x5C55653,0x592BF86,0x5F4C740,0x135908};
-const BIG CURVE_Frb={0x6534710,0x1468DDE0,0x551B018,0x10C78E4D,0x4E3ABBD,0x9ECE6DE,0x2A40371,0x1A0C46C5,0x10A6F7};
-const BIG CURVE_Pxa={0x4D2EC74,0x428E777,0xF89C9B0,0x190B7F40,0x14BBB907,0x12807AE1,0x958D62C,0x58E0A76,0x19682D};
-const BIG CURVE_Pxb={0xE29CFE1,0x1D2C7459,0x270C3D1,0x172F6184,0x19743F81,0x49BD474,0x192A8047,0x1D87C33E,0x1466B9};
-const BIG CURVE_Pya={0xF0BE09F,0x7DFE75E,0x1FB06CC3,0x3667B08,0xE209636,0x110ABED7,0xE376078,0x1B2E4665,0xA79ED};
-const BIG CURVE_Pyb={0x898EE9D,0xC825914,0x14BB7AFB,0xC9D4AD3,0x13461C28,0x122896C6,0x240D71B,0x73D9898,0x6160C};
-const BIG CURVE_Gx={0x1C1B55B2,0x13311F7A,0x24FB86F,0x1FADDC30,0x166D3243,0xFB23D31,0x836C2F7,0x10E05,0x240000};
-const BIG CURVE_Gy={0x1};
-const BIG CURVE_W[2]={{0x162FEB83,0x2A31A48,0x100E0480,0x16,0x600},{0x7802561,0x0,0x20}};
-const BIG CURVE_SB[2][2]={{{0x1DB010E4,0x2A31A48,0x100E04A0,0x16,0x600},{0x7802561,0x0,0x20}},{{0x7802561,0x0,0x20},{0xBB33EA,0xDEAEAE9,0x233AF2F,0x1FADDC03,0x166D2643,0xFB23D31,0x836C2F7,0x10E05,0x240000}}};
-const BIG CURVE_WB[4]={{0x167A84B0,0xE108C2,0x1004AC10,0x7,0x200},{0x1E220475,0x166FCCAD,0x129FE68D,0x1D29DB51,0x2A0DC07,0x438,0xC000},{0xF10B93,0x1B37E657,0x194FF34E,0x1E94EDA8,0x1506E03,0x21C,0x6000},{0x1DFAAA11,0xE108C2,0x1004AC30,0x7,0x200}};
-const BIG CURVE_BB[4][4]={{{0x132B0CBD,0x108E0531,0x1241B39F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000},{0x132B0CBC,0x108E0531,0x1241B39F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000},{0x132B0CBC,0x108E0531,0x1241B39F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000},{0x7802562,0x0,0x20}},{{0x7802561,0x0,0x20},{0x132B0CBC,0x108E0531,0x1241B39F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000},{0x132B0CBD,0x108E0531,0x1241B39F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000},{0x132B0CBC,0x108E0531,0x1241B39F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000}},{{0x7802562,0x0,0x20},{0x7802561,0x0,0x20},{0x7802561,0x0,0x20},{0x7802561,0x0,0x20}},{{0x3C012B2,0x0,0x10},{0xF004AC2,0x0,0x40},{0xF6AFA0A,0x108E0531,0x1241B38F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000},{0x3C012B2,0x0,0x10}}};
-#endif
-
-#if CHUNK==64
-
-const chunk MConst=0x4E205BF9789E85;
-const BIG Modulus={0x6623EF5C1B55B3,0xD6EE18093EE1BE,0x647A6366D3243F,0x8702A0DB0BDDF,0x24000000};
-const BIG CURVE_Order={0x11C0A636EB1F6D,0xD6EE0CC906CEBE,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000};
-const BIG CURVE_B={0x2};
-const BIG CURVE_Bnx={0x3C012B1,0x40};
-const BIG CURVE_Cru={0xE0931794235C97,0xDF6471EF875631,0xCA83F1440BD,0x480000};
-const BIG CURVE_Fra={0xD9083355C80EA3,0x7326F173F8215B,0x8AACA718986867,0xA63A0164AFE18B,0x1359082F};
-const BIG CURVE_Frb={0x8D1BBC06534710,0x63C7269546C062,0xD9CDBC4E3ABBD8,0x623628A900DC53,0x10A6F7D0};
-const BIG CURVE_Pxa={0x851CEEE4D2EC74,0x85BFA03E2726C0,0xF5C34BBB907C,0x7053B256358B25,0x19682D2C};
-const BIG CURVE_Pxb={0xA58E8B2E29CFE1,0x97B0C209C30F47,0x37A8E99743F81B,0x3E19F64AA011C9,0x1466B9EC};
-const BIG CURVE_Pya={0xFBFCEBCF0BE09F,0xB33D847EC1B30C,0x157DAEE2096361,0x72332B8DD81E22,0xA79EDD9};
-const BIG CURVE_Pyb={0x904B228898EE9D,0x4EA569D2EDEBED,0x512D8D3461C286,0xECC4C09035C6E4,0x6160C39};
-const BIG CURVE_Gx={0x6623EF5C1B55B2,0xD6EE18093EE1BE,0x647A6366D3243F,0x8702A0DB0BDDF,0x24000000};
-const BIG CURVE_Gy={0x1};
-const BIG CURVE_W[2]={{0x546349162FEB83,0xB40381200,0x6000},{0x7802561,0x80}};
-const BIG CURVE_SB[2][2]={{{0x5463491DB010E4,0xB40381280,0x6000},{0x7802561,0x80}},{{0x7802561,0x80},{0xBD5D5D20BB33EA,0xD6EE0188CEBCBD,0x647A6366D2643F,0x8702A0DB0BDDF,0x24000000}}};
-const BIG CURVE_WB[4]={{0x1C2118567A84B0,0x3C012B040,0x2000},{0xCDF995BE220475,0x94EDA8CA7F9A36,0x8702A0DC07E,0x300000},{0x66FCCAE0F10B93,0x4A76D4653FCD3B,0x4381506E03F,0x180000},{0x1C21185DFAAA11,0x3C012B0C0,0x2000}};
-const BIG CURVE_BB[4][4]={{{0x11C0A6332B0CBD,0xD6EE0CC906CE7E,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000},{0x11C0A6332B0CBC,0xD6EE0CC906CE7E,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000},{0x11C0A6332B0CBC,0xD6EE0CC906CE7E,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000},{0x7802562,0x80}},{{0x7802561,0x80},{0x11C0A6332B0CBC,0xD6EE0CC906CE7E,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000},{0x11C0A6332B0CBD,0xD6EE0CC906CE7E,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000},{0x11C0A6332B0CBC,0xD6EE0CC906CE7E,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000}},{{0x7802562,0x80},{0x7802561,0x80},{0x7802561,0x80},{0x7802561,0x80}},{{0x3C012B2,0x40},{0xF004AC2,0x100},{0x11C0A62F6AFA0A,0xD6EE0CC906CE3E,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000},{0x3C012B2,0x40}}};
-#endif
-
-#endif
-
-#if CHOICE==NIST
-
-/* Standard NIST-256 Curve */
-
-const int CURVE_A= -3;
-const chunk MConst=1;
-
-#if CHUNK==16
-
-const BIG Modulus={0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1F,0x0,0x0,0x0,0x0,0x0,0x0,0x400,0x0,0x0,0x1FF8,0x1FFF,0x1FF};
-const BIG CURVE_B={0x4B,0x1E93,0xF89,0x1C78,0x3BC,0x187B,0x114E,0x1619,0x1D06,0x328,0x1AF,0xD31,0x1557,0x15DE,0x1ECF,0x127C,0xA3A,0xEC5,0x118D,0xB5};
-const BIG CURVE_Order={0x551,0x319,0x10BF,0x1395,0xF3B,0xF42,0x1C5E,0x15B4,0x6FA,0x1DE7,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x3FF,0x0,0x0,0x1FF8,0x1FFF,0x1FF};
-const BIG CURVE_Gx={0x296,0x4C6,0x1176,0x272,0xF4A,0x19D0,0x17AC,0x1025,0x37D,0x13B8,0x103C,0x748,0xE56,0x1E73,0x1FE2,0x848,0x12C,0xF97,0x5F4,0xD6};
-const BIG CURVE_Gy={0x11F5,0x1DFA,0x1A0D,0xC80,0xCBB,0xF67,0xCC5,0xAED,0xE33,0x115E,0x785,0x181F,0x14A7,0x13F5,0xE3B,0xFF3,0x1E1A,0x1717,0x18D0,0x9F};
-
-#endif
-
-#if CHUNK==32
-
-const BIG Modulus={0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FF,0x0,0x0,0x40000,0x1FE00000,0xFFFFFF};
-const BIG CURVE_B={0x7D2604B,0x1E71E1F1,0x14EC3D8E,0x1A0D6198,0x86BC651,0x1EAABB4C,0xF9ECFAE,0x1B154752,0x5AC635};
-const BIG CURVE_Order={0x1C632551,0x1DCE5617,0x5E7A13C,0xDF55B4E,0x1FFFFBCE,0x1FFFFFFF,0x3FFFF,0x1FE00000,0xFFFFFF};
-const BIG CURVE_Gx={0x1898C296,0x509CA2E,0x1ACCE83D,0x6FB025B,0x40F2770,0x1372B1D2,0x91FE2F3,0x1E5C2588,0x6B17D1};
-const BIG CURVE_Gy={0x17BF51F5,0x1DB20341,0xC57B3B2,0x1C66AED6,0x19E162BC,0x15A53E07,0x1E6E3B9F,0x1C5FC34F,0x4FE342};
-
-#endif
-
-#if CHUNK==64
-
-const BIG Modulus={0xFFFFFFFFFFFFFF,0xFFFFFFFFFF,0x0,0x1000000,0xFFFFFFFF};
-const BIG CURVE_B={0xCE3C3E27D2604B,0x6B0CC53B0F63B,0x55769886BC651D,0xAA3A93E7B3EBBD,0x5AC635D8};
-const BIG CURVE_Order={0xB9CAC2FC632551,0xFAADA7179E84F3,0xFFFFFFFFFFBCE6,0xFFFFFF,0xFFFFFFFF};
-const BIG CURVE_Gx={0xA13945D898C296,0x7D812DEB33A0F4,0xE563A440F27703,0xE12C4247F8BCE6,0x6B17D1F2};
-const BIG CURVE_Gy={0xB6406837BF51F5,0x33576B315ECECB,0x4A7C0F9E162BCE,0xFE1A7F9B8EE7EB,0x4FE342E2};
-
-#endif
-
-#endif
-
-#if CHOICE==MF254
-
-/* Montgomery-Friendly NUMS curves http://eprint.iacr.org/2014/130 */
-
-/* p=k.2^n-1 where n is multiple of BASEBITS - but k can be adjusted. */
-/* Here p=2^240(2^14-127)-1 = 2^232(2^22-256.127)-1 where 8*29=232 and (2^22-256.127)=0x3F8100 */
-/* or = 2^224(2^30-65536.127)-1 where 4*56=224 and (2^30-65536.127) = 0x3F810000 */
-
-#if CHUNK==32
-
-const BIG Modulus={0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3F80FF};
-const chunk MConst=0x3F8100;
-
-#if CURVETYPE==WEIERSTRASS
-const int CURVE_A= -3;
-const BIG CURVE_Order={0xF8DF83F,0x1D20CE25,0x8DD701B,0x317D41B,0x1FFFFEB8,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3F80FF};
-const BIG CURVE_B={0x1FFFD08D,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3F80FF};
-const BIG CURVE_Gx={0x2};
-const BIG CURVE_Gy={0x190D4EBC,0xB2EF9BF,0x14464C6B,0xE71C7F0,0x18AEBDFB,0xD3ADEBB,0x18052B85,0x1A6765CA,0x140E3F};
-#endif
-
-#if CURVETYPE==EDWARDS
-const int CURVE_A= -1;
-const BIG CURVE_Order={0x46E98C7,0x179E9FF6,0x158BEC3A,0xA60D917,0x1FFFFEB9,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFE03F};
-const BIG CURVE_B={0x367B};
-const BIG CURVE_Gx={0x1};
-const BIG CURVE_Gy={0xF2701E5,0x29687ED,0xC84861F,0x535081C,0x3F4E363,0x6A811B,0xCD65474,0x121AD498,0x19F0E6};
-#endif
-
-#if CURVETYPE==MONTGOMERY
-
-const int CURVE_A=-55790;
-const BIG CURVE_Order={0x46E98C7,0x179E9FF6,0x158BEC3A,0xA60D917,0x1FFFFEB9,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFE03F};
-const BIG CURVE_Gx={0x3};
-
-#endif
-
-#endif
-
-#if CHUNK==64
-
-const BIG Modulus={0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0x3F80FFFF};
-const chunk MConst=0x3F810000;
-
-
-#if CURVETYPE==WEIERSTRASS
-const int CURVE_A= -3;
-const BIG CURVE_Order={0xA419C4AF8DF83F,0x8BEA0DA375C06F,0xFFFFFFFFFFEB81,0xFFFFFFFFFFFFFF,0x3F80FFFF};
-const BIG CURVE_B={0xFFFFFFFFFFD08D,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0x3F80FFFF};
-const BIG CURVE_Gx={0x2};
-const BIG CURVE_Gy={0x65DF37F90D4EBC,0x38E3F8511931AD,0x75BD778AEBDFB7,0x3B2E56014AE15A,0x140E3FD3};
-#endif
-
-#if CURVETYPE==EDWARDS
-const int CURVE_A= -1;
-const BIG CURVE_Order={0xF3D3FEC46E98C7,0x306C8BD62FB0EA,0xFFFFFFFFFFEB95,0xFFFFFFFFFFFFFF,0xFE03FFF};
-const BIG CURVE_B={0x367B};
-const BIG CURVE_Gx={0x1};
-const BIG CURVE_Gy={0x52D0FDAF2701E5,0x9A840E3212187C,0xD502363F4E3632,0xD6A4C335951D00,0x19F0E690};
-#endif
-
-#if CURVETYPE==MONTGOMERY
-const int CURVE_A=-55790;
-const BIG CURVE_Order={0xF3D3FEC46E98C7,0x306C8BD62FB0EA,0xFFFFFFFFFFEB95,0xFFFFFFFFFFFFFF,0xFE03FFF};
-const BIG CURVE_Gx={0x3};
-#endif
-
-#endif
-
-#endif
-
-
-
-
-#if CHOICE==MF256
-
-/* Montgomery-Friendly NUMS curves http://eprint.iacr.org/2014/130 */
-
-#if CHUNK==32
-
-const BIG Modulus={0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFFA7FF};
-const chunk MConst=0xFFA800;
-
-#if CURVETYPE==WEIERSTRASS
-const int CURVE_A= -3;
-const BIG CURVE_Order={0x79857EB,0x8862F0D,0x1941D2E7,0x2EA27CD,0x1FFFFFC5,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFFA7FF};
-const BIG CURVE_B={0x14E6A};
-const BIG CURVE_Gx={0x1};
-const BIG CURVE_Gy={0xB724D2A,0x3CAA61,0x5371984,0x128FD71B,0x1AE28956,0x1D13091E,0x339EEAE,0x10F7C301,0x20887C};
-#endif
-
-#if CURVETYPE==EDWARDS
-const int CURVE_A= -1;
-const BIG CURVE_Order={0x18EC7BAB,0x16C976F6,0x19CCF259,0x9775F70,0x1FFFFB15,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3FE9FF};
-const BIG CURVE_B={0x350A};
-const BIG CURVE_Gx={0x1};
-const BIG CURVE_Gy={0x12F3C908,0xF553917,0x1FA9A35F,0xBCC91B,0x1AACA0C,0x1779ED96,0x156BABAF,0x1F1F1989,0xDAD8D4};
-#endif
-
-#if CURVETYPE==MONTGOMERY
-
-const int CURVE_A=-54314;
-const BIG CURVE_Order={0x18EC7BAB,0x16C976F6,0x19CCF259,0x9775F70,0x1FFFFB15,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3FE9FF};
-const BIG CURVE_Gx={0x8};
-
-#endif
-
-#endif
-
-#if CHUNK==64
-
-const BIG Modulus={0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFA7FFFF};
-const chunk MConst=0xFFA80000;
-
-
-#if CURVETYPE==WEIERSTRASS
-const int CURVE_A= -3;
-const BIG CURVE_Order={0x10C5E1A79857EB,0x7513E6E5074B9D,0xFFFFFFFFFFFC51,0xFFFFFFFFFFFFFF,0xFFA7FFFF};
-const BIG CURVE_B={0x14E6A};
-const BIG CURVE_Gx={0x1};
-const BIG CURVE_Gy={0x7954C2B724D2A,0x47EB8D94DC6610,0x26123DAE289569,0xBE1808CE7BABBA,0x20887C87};
-#endif
-
-#if CURVETYPE==EDWARDS
-const int CURVE_A= -1;
-const BIG CURVE_Order={0xD92EDED8EC7BAB,0xBBAFB86733C966,0xFFFFFFFFFFB154,0xFFFFFFFFFFFFFF,0x3FE9FFFF};
-const BIG CURVE_B={0x350A};
-const BIG CURVE_Gx={0x1};
-const BIG CURVE_Gy={0xEAA722F2F3C908,0x5E648DFEA68D7D,0xF3DB2C1AACA0C0,0xF8CC4D5AEAEBEE,0xDAD8D4F8};
-#endif
-
-#if CURVETYPE==MONTGOMERY
-const int CURVE_A=-54314;
-const BIG CURVE_Order={0xD92EDED8EC7BAB,0xBBAFB86733C966,0xFFFFFFFFFFB154,0xFFFFFFFFFFFFFF,0x3FE9FFFF};
-const BIG CURVE_Gx={0x8};
-#endif
-
-#endif
-
-#endif
-
-
-
-
-#if CHOICE==MS255
-/* Pseudo-Mersenne NUMS curves http://eprint.iacr.org/2014/130 */
-
-#if CHUNK==16
-const BIG Modulus={0x1D03,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0xFF};
-const chunk MConst=0x2FD;
-
-#if CURVETYPE==WEIERSTRASS
-const int CURVE_A=-3;
-const BIG CURVE_Order={0xAEB,0x2CA,0x60F,0x1F59,0x1AB8,0x19EF,0xB4A,0x507,0xA38,0x1C32,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0xFF};
-const BIG CURVE_B={0xB46,0x1FFD,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0xFF};
-const BIG CURVE_Gx={0x1};
-const BIG CURVE_Gy={0x4BA,0xE5A,0x19DA,0x7FE,0x1173,0x1306,0x17F6,0x119B,0x16C7,0x1BED,0x1F45,0x5FE,0x1F9B,0xF5F,0xE48,0xF06,0xDBA,0x1607,0x1E9A,0xDE};
-#endif
-
-#if CURVETYPE==EDWARDS
-const int CURVE_A=-1;
-const BIG CURVE_Order={0xB75,0x1B7,0x1B41,0x13A3,0xAC4,0x197,0x169A,0x10BD,0x11A7,0x1EE7,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x3F};
-const BIG CURVE_B={0xA97,0x7};
-const BIG CURVE_Gx={0x4};
-const BIG CURVE_Gy={0x16A0,0x439,0x16F4,0x144A,0x1BA2,0xD22,0x1511,0x115D,0x114B,0xA94,0x11F9,0x1C18,0xDD8,0x12A6,0x17B0,0x16A8,0xA7B,0x29A,0x12DE,0x4D};
-#endif
-
-#endif
-
-#if CHUNK==32
-const BIG Modulus={0x1FFFFD03,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFFF};
-const chunk MConst=0x2FD;
-
-#if CURVETYPE==WEIERSTRASS
-const int CURVE_A=-3;
-const BIG CURVE_Order={0x1C594AEB,0x1C7D64C1,0x14ACF7EA,0x14705075,0x1FFFF864,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFFF};
-const BIG CURVE_B={0x1FFFAB46,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFFF};
-const BIG CURVE_Gx={0x1};
-const BIG CURVE_Gy={0x9CB44BA,0x199FFB3B,0x1F698345,0xD8F19BB,0x17D177DB,0x1FFCD97F,0xCE487A,0x181DB74F,0x6F7A6A};
-#endif
-
-#if CURVETYPE==EDWARDS
-const int CURVE_A=-1;
-const BIG CURVE_Order={0x436EB75,0x24E8F68,0x9A0CBAB,0x34F0BDB,0x1FFFFDCF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFF};
-const BIG CURVE_B={0xEA97};
-const BIG CURVE_Gx={0x4};
-const BIG CURVE_Gy={0x108736A0,0x11512ADE,0x1116916E,0x29715DA,0x47E5529,0x66EC706,0x1517B095,0xA694F76,0x26CB78};
-#endif
-
-#if CURVETYPE==MONTGOMERY
-const int CURVE_A=-240222;
-const BIG CURVE_Order={0x436EB75,0x24E8F68,0x9A0CBAB,0x34F0BDB,0x1FFFFDCF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFF};
-const BIG CURVE_Gx={0x4};
-#endif
-
-
-#endif
-
-#if CHUNK==64
-const BIG Modulus={0xFFFFFFFFFFFD03,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0x7FFFFFFF};
-const chunk MConst=0x2FD;
-
-#if CURVETYPE==WEIERSTRASS
-const int CURVE_A=-3;
-const BIG CURVE_Order={0x8FAC983C594AEB,0x38283AD2B3DFAB,0xFFFFFFFFFF864A,0xFFFFFFFFFFFFFF,0x7FFFFFFF};
-const BIG CURVE_B={0xFFFFFFFFFFAB46,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0x7FFFFFFF};
-const BIG CURVE_Gx={0x1};
-const BIG CURVE_Gy={0x33FF6769CB44BA,0xC78CDDFDA60D17,0xF9B2FF7D177DB6,0xEDBA7833921EBF,0x6F7A6AC0};
-#endif
-
-#if CURVETYPE==EDWARDS
-const int CURVE_A=-1;
-const BIG CURVE_Order={0x49D1ED0436EB75,0xA785EDA6832EAC,0xFFFFFFFFFFDCF1,0xFFFFFFFFFFFFFF,0x1FFFFFFF};
-const BIG CURVE_B={0xEA97};
-const BIG CURVE_Gx={0x4};
-const BIG CURVE_Gy={0x2A255BD08736A0,0x4B8AED445A45BA,0xDD8E0C47E55291,0x4A7BB545EC254C,0x26CB7853};
-#endif
-
-#if CURVETYPE==MONTGOMERY
-const int CURVE_A=-240222;
-const BIG CURVE_Order={0x49D1ED0436EB75,0xA785EDA6832EAC,0xFFFFFFFFFFDCF1,0xFFFFFFFFFFFFFF,0x1FFFFFFF};
-const BIG CURVE_Gx={0x4};
-#endif
-
-#endif
-
-#endif
-
-
-
-#if CHOICE==MS256
-/* Pseudo-Mersenne NUMS curves http://eprint.iacr.org/2014/130 */
-
-#if CHUNK==16
-const BIG Modulus={0x1F43,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FF};
-const chunk MConst=0xBD;
-
-#if CURVETYPE==WEIERSTRASS
-const int CURVE_A=-3;
-const BIG CURVE_Order={0x825,0x1A8D,0xA51,0x1640,0x20A,0xE30,0x899,0xEBD,0x1C82,0x1F21,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FF};
-const BIG CURVE_B={0x1581,0x12};
-const BIG CURVE_Gx={0x1};
-const BIG CURVE_Gy={0xC77,0x15AB,0x1B0,0x8C6,0x10BF,0x760,0x1625,0x126E,0xC2F,0x1E81,0x175A,0x1DDD,0x16CC,0x164,0x1FF2,0xCDA,0x1E4,0x29E,0x1BC6,0xD2};
-#endif
-
-#if CURVETYPE==EDWARDS
-const int CURVE_A=-1;
-const BIG CURVE_Order={0x14AD,0x915,0x1BC4,0x109C,0xE5B,0x1E32,0x29A,0xB5A,0xAA5,0x1DF3,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x7F};
-const BIG CURVE_B={0x1BEE,0x1};
-const BIG CURVE_Gx={0xd};
-const BIG CURVE_Gy={0xDBA,0x18E5,0xD4C,0x1EDF,0x1707,0x181F,0x934,0xC70,0xA6D,0x1DF1,0x11AF,0x1F40,0xB39,0x998,0xE8F,0xEDB,0xA12,0xF1,0x2AD,0xFA};
-#endif
-
-#endif
-
-#if CHUNK==32
-const BIG Modulus={0x1FFFFF43,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFFFFFF};
-const chunk MConst=0xBD;
-
-#if CURVETYPE==WEIERSTRASS
-const int CURVE_A=-3;
-const BIG CURVE_Order={0x751A825,0x559014A,0x9971808,0x1904EBD4,0x1FFFFE43,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFFFFFF};
-const BIG CURVE_B={0x25581};
-const BIG CURVE_Gx={0x1};
-const BIG CURVE_Gy={0x2B56C77,0x1FA31836,0x253B042,0x185F26EB,0xDD6BD02,0x4B66777,0x1B5FF20B,0xA783C8C,0x696F18};
-#endif
-
-#if CURVETYPE==EDWARDS
-const int CURVE_A=-1;
-const BIG CURVE_Order={0x1122B4AD,0xDC27378,0x9AF1939,0x154AB5A1,0x1FFFFBE6,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3FFFFF};
-const BIG CURVE_B={0x3BEE};
-const BIG CURVE_Gx={0xd};
-const BIG CURVE_Gy={0x131CADBA,0x3FB7DA9,0x134C0FDC,0x14DAC704,0x46BFBE2,0x1859CFD0,0x1B6E8F4C,0x3C5424E,0x7D0AB4};
-#endif
-
-#if CURVETYPE==MONTGOMERY
-const int CURVE_A=-61370;
-const BIG CURVE_Order={0x1122B4AD,0xDC27378,0x9AF1939,0x154AB5A1,0x1FFFFBE6,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3FFFFF};
-const BIG CURVE_Gx={0xb};
-#endif
-
-
-#endif
-
-#if CHUNK==64
-const BIG Modulus={0xFFFFFFFFFFFF43,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFF};
-const chunk MConst=0xBD;
-
-#if CURVETYPE==WEIERSTRASS
-const int CURVE_A=-3;
-const BIG CURVE_Order={0xAB20294751A825,0x8275EA265C6020,0xFFFFFFFFFFE43C,0xFFFFFFFFFFFFFF,0xFFFFFFFF};
-const BIG CURVE_B={0x25581};
-const BIG CURVE_Gx={0x1};
-const BIG CURVE_Gy={0xF46306C2B56C77,0x2F9375894EC10B,0x6CCEEEDD6BD02C,0xC1E466D7FC82C9,0x696F1853};
-#endif
-
-#if CURVETYPE==EDWARDS
-const int CURVE_A=-1;
-const BIG CURVE_Order={0xB84E6F1122B4AD,0xA55AD0A6BC64E5,0xFFFFFFFFFFBE6A,0xFFFFFFFFFFFFFF,0x3FFFFFFF};
-const BIG CURVE_B={0x3BEE};
-const BIG CURVE_Gx={0xd};
-const BIG CURVE_Gy={0x7F6FB5331CADBA,0x6D63824D303F70,0xB39FA046BFBE2A,0x2A1276DBA3D330,0x7D0AB41E};
-#endif
-
-#if CURVETYPE==MONTGOMERY
-const int CURVE_A=-61370;
-const BIG CURVE_Order={0xB84E6F1122B4AD,0xA55AD0A6BC64E5,0xFFFFFFFFFFBE6A,0xFFFFFFFFFFFFFF,0x3FFFFFFF};
-const BIG CURVE_Gx={0xb};
-#endif
-
-#endif
-
-#endif
-
-
-
-
-#if CHOICE==C25519
-
-/* Modulus p = 2^MODBITS-MConst*/
-/* Three Curves for the price of one..*/
-
-#if CHUNK==16
-
-const chunk MConst=19;
-const BIG Modulus={0x1FED,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0xFF};
-
-#if CURVETYPE==WEIERSTRASS
-/* Curve I generated myself */
-const int CURVE_A=-3;
-const BIG CURVE_B={0x28};
-const BIG CURVE_Order={0xCA1,0x1945,0x1865,0x19C8,0x16D1,0x11B9,0xD0E,0x1C96,0x1E0F,0x2EA,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x100};
-const BIG CURVE_Gx={0x61F,0x6C1,0x1DD,0xEA7,0x4C4,0x124C,0x1BE3,0x1560,0x74E,0x7CD,0x6F4,0x14B,0x13DE,0x133A,0xFB4,0x106,0x15F,0x909,0x18FD,0xCF};
-const BIG CURVE_Gy={0xF38,0xEF7,0x11F8,0xC65,0x1574,0x10E3,0x4,0x12E7,0xB2B,0xA6,0x17A8,0x1C8B,0x1CD4,0xFA,0x1D79,0xBB2,0x1E68,0x1640,0x1A15,0x6};
-
-#endif
-
-#if CURVETYPE==EDWARDS
-/* Ed25519 Curve */
-const int CURVE_A=-1;
-const BIG CURVE_B={0x18A3,0x1ACB,0x1284,0x169B,0x175E,0xC55,0x507,0x9A8,0x100A,0x3,0x1A26,0xEF3,0x797,0x3A0,0xE33,0x1FCE,0xB6F,0x771,0xDB,0xA4};
-const BIG CURVE_Order={0x13ED,0x7AE,0x697,0x4C6,0x581,0xE6B,0xBDE,0x1BD4,0x1EF9,0xA6,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20};
-const BIG CURVE_Gx={0x151A,0x192E,0x1823,0xC5A,0xC95,0x13D9,0x1496,0xC12,0xCC7,0x349,0x1717,0x1BAD,0x31F,0x1271,0x1B02,0xA7F,0xD6E,0x169E,0x1A4D,0x42};
-const BIG CURVE_Gy={0x658,0x1333,0x1999,0xCCC,0x666,0x1333,0x1999,0xCCC,0x666,0x1333,0x1999,0xCCC,0x666,0x1333,0x1999,0xCCC,0x666,0x1333,0x1999,0xCC};
-
-#endif
-
-/*
-#if CURVETYPE==MONTGOMERY
-const int CURVE_A=486662;  // Not Working as A too big for 16-bit int
-const BIG CURVE_Order={0x13ED,0x7AE,0x697,0x4C6,0x581,0xE6B,0xBDE,0x1BD4,0x1EF9,0xA6,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20};
-const BIG CURVE_Gx={0x9};
-#endif
-*/
-
-#endif
-
-
-#if CHUNK==32
-
-const chunk MConst=19;
-const BIG Modulus={0x1FFFFFED,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFFF};
-
-#if CURVETYPE==WEIERSTRASS
-const int CURVE_A=-3;
-const BIG CURVE_B={0x28};
-const BIG CURVE_Order={0x1728ACA1,0x8E7230C,0x10E8DCDB,0x1C1FC966,0x5D5,0x0,0x0,0x0,0x800000};
-const BIG CURVE_Gx={0x14D8261F,0x23A9C3B,0x1E392613,0xE9D560D,0x19BD0F9A,0x1A9EF052,0xCFB499,0x4242BE1,0x67E3F5};
-const BIG CURVE_Gy={0x1DEEF38,0x1A31963F,0x4871D5,0x16572E70,0x1DEA014C,0x1AE6A722,0x165D7907,0x1903CD0B,0x36856};
-
-#endif
-
-#if CURVETYPE==EDWARDS
-const int CURVE_A=-1;
-const BIG CURVE_B={0x135978A3,0xF5A6E50,0x10762ADD,0x149A82,0x1E898007,0x3CBBBC,0x19CE331D,0x1DC56DFF,0x52036C};
-const BIG CURVE_Order={0x1CF5D3ED,0x9318D2,0x1DE73596,0x1DF3BD45,0x14D,0x0,0x0,0x0,0x100000};
-const BIG CURVE_Gx={0xF25D51A,0xAB16B04,0x969ECB2,0x198EC12A,0xDC5C692,0x1118FEEB,0xFFB0293,0x1A79ADCA,0x216936};
-const BIG CURVE_Gy={0x6666658,0x13333333,0x19999999,0xCCCCCCC,0x6666666,0x13333333,0x19999999,0xCCCCCCC,0x666666};
-
-#endif
-
-#if CURVETYPE==MONTGOMERY
-
-const int CURVE_A=486662;
-const BIG CURVE_Order={0x1CF5D3ED,0x9318D2,0x1DE73596,0x1DF3BD45,0x14D,0x0,0x0,0x0,0x100000};
-const BIG CURVE_Gx={0x9};
-
-#endif
-
-#endif
-
-#if CHUNK==64
-
-const chunk MConst=19;
-const BIG Modulus={0xFFFFFFFFFFFFED,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0x7FFFFFFF};
-
-#if CURVETYPE==WEIERSTRASS
-const int CURVE_A=-3;
-const BIG CURVE_B={0x28};
-const BIG CURVE_Order={0x1CE4619728ACA1,0xFE4B343A3736D,0x5D5E,0x0,0x80000000};
-const BIG CURVE_Gx={0x47538774D8261F,0x4EAB06F8E4984C,0x3DE0A59BD0F9A7,0x215F0833ED2675,0x67E3F521};
-const BIG CURVE_Gy={0x4632C7E1DEEF38,0x2B97380121C757,0xCD4E45DEA014CB,0x1E685D975E41F5,0x36856C8};
-
-#endif
-
-#if CURVETYPE==EDWARDS
-const int CURVE_A=-1;
-const BIG CURVE_B={0xEB4DCA135978A3,0xA4D4141D8AB75,0x797779E8980070,0x2B6FFE738CC740,0x52036CEE};
-const BIG CURVE_Order={0x12631A5CF5D3ED,0xF9DEA2F79CD658,0x14DE,0x0,0x10000000};
-const BIG CURVE_Gx={0x562D608F25D51A,0xC7609525A7B2C9,0x31FDD6DC5C692C,0xCD6E53FEC0A4E2,0x216936D3};
-const BIG CURVE_Gy={0x66666666666658,0x66666666666666,0x66666666666666,0x66666666666666,0x66666666};
-
-#endif
-
-#if CURVETYPE==MONTGOMERY
-
-const int CURVE_A=486662;
-const BIG CURVE_Order={0x12631A5CF5D3ED,0xF9DEA2F79CD658,0x14DE,0x0,0x10000000};
-const BIG CURVE_Gx={0x9};
-
-#endif
-
-#endif
-
-#endif
-
-
-#if CHOICE==BRAINPOOL
-
-const int CURVE_A=-3;
-#if CHUNK==16
-
-const BIG Modulus={0x1377,0x1B72,0x747,0x690,0x201,0x1014,0x1498,0x47A,0x1BF6,0x1371,0x35C,0x1B07,0x909,0x1305,0x10F9,0x1537,0x1EE,0x1EDD,0x1ED5,0x153};
-const chunk MConst=0x9B9;
-const BIG CURVE_Order={0x16A7,0x1A42,0xA5,0x1C1D,0x1901,0x137B,0x1586,0x1476,0x197A,0xC61,0x35C,0x1B07,0x909,0x1305,0x10F9,0x1537,0x1EE,0x1EDD,0x1ED5,0x153};
-const BIG CURVE_B={0xB04,0x1749,0x7F,0xB02,0x16AE,0x492,0x1CBD,0x1895,0x13EB,0x1DFC,0x1DAD,0x1A16,0x1733,0x1353,0x13F9,0x9D4,0x10D8,0xE21,0xB18,0xCC};
-const BIG CURVE_Gx={0x5F4,0x1098,0x158B,0x322,0x179A,0x1E15,0xABE,0x188F,0x142,0xD7D,0x1852,0x14CA,0x1B23,0x1109,0x1DCC,0x1CF6,0x1CF,0x19E6,0x1A3A,0x147};
-const BIG CURVE_Gy={0x9BE,0x192E,0x1CD6,0x17D1,0x1DA,0x1380,0x740,0x1BC7,0x1CB6,0x134D,0x105F,0xC88,0xE14,0x1D91,0x15FD,0x18AD,0x1439,0x411,0x65B,0x5B};
-#endif
-
-#if CHUNK==32
-
-const BIG Modulus={0x1F6E5377,0x9A40E8,0x9880A08,0x17EC47AA,0x18D726E3,0x5484EC1,0x6F0F998,0x1B743DD5,0xA9FB57};
-const chunk MConst=0xEFD89B9;
-const BIG CURVE_Order={0x174856A7,0xF07414,0x1869BDE4,0x12F5476A,0x18D718C3,0x5484EC1,0x6F0F998,0x1B743DD5,0xA9FB57};
-const BIG CURVE_B={0x1EE92B04,0x172C080F,0xBD2495A,0x7D7895E,0x176B7BF9,0x13B99E85,0x1A93F99A,0x18861B09,0x662C61};
-const BIG CURVE_Gx={0xE1305F4,0xD0C8AB1,0xBEF0ADE,0x28588F5,0x16149AFA,0x9D91D32,0x1EDDCC88,0x79839FC,0xA3E8EB};
-const BIG CURVE_Gy={0x1B25C9BE,0xD5F479A,0x1409C007,0x196DBC73,0x417E69B,0x1170A322,0x15B5FDEC,0x10468738,0x2D996C};
-#endif
-
-#if CHUNK==64
-
-const BIG Modulus={0x13481D1F6E5377,0xF623D526202820,0x909D838D726E3B,0xA1EEA9BC3E660A,0xA9FB57DB};
-const chunk MConst=0xA75590CEFD89B9;
-const BIG CURVE_Order={0x1E0E82974856A7,0x7AA3B561A6F790,0x909D838D718C39,0xA1EEA9BC3E660A,0xA9FB57DB};
-const BIG CURVE_B={0xE58101FEE92B04,0xEBC4AF2F49256A,0x733D0B76B7BF93,0x30D84EA4FE66A7,0x662C61C4};
-const BIG CURVE_Gx={0xA191562E1305F4,0x42C47AAFBC2B79,0xB23A656149AFA1,0xC1CFE7B7732213,0xA3E8EB3C};
-const BIG CURVE_Gy={0xABE8F35B25C9BE,0xB6DE39D027001D,0xE14644417E69BC,0x3439C56D7F7B22,0x2D996C82};
-#endif
-
-#endif
-
-
-#if CHOICE==ANSSI
-
-const int CURVE_A=-3;
-#if CHUNK==16
-
-const BIG Modulus={0x1C03,0x374,0x14F6,0x19E6,0x1E8F,0x536,0xF23,0x1795,0x1AD,0x19CB,0x10D6,0x1C84,0x1E8C,0x936,0x1C40,0x1AB1,0xB3A,0x1C60,0x1F45,0x1E3};
-const chunk MConst=0x1155;
-const BIG CURVE_Order={0x15E1,0x16B2,0x1671,0x1BA8,0x1FF,0x1FCA,0x34A,0x1C28,0x1C67,0x1A9E,0x10D6,0x1C84,0x1E8C,0x936,0x1C40,0x1AB1,0xB3A,0x1C60,0x1F45,0x1E3};
-const BIG CURVE_B={0x173F,0x1BDD,0x59E,0xBDB,0x307,0x10C0,0x12C6,0x135C,0xC0C,0x1EFF,0x1003,0x1489,0x754,0x55D,0x35,0x1526,0x1428,0x1E52,0xD4F,0x1DC};
-const BIG CURVE_Gx={0x1CFF,0xC7A,0xB76,0x12F4,0x164C,0x1B80,0x1E62,0x1B95,0x7D2,0xC61,0x8E5,0x13A8,0x1474,0xC1E,0xCC4,0x73D,0x16C1,0x61A,0xCF5,0x16D};
-const BIG CURVE_Gy={0xCFB,0x31,0x555,0x2B4,0x1831,0x4F0,0x393,0xFD,0x1C3,0x138,0x1BE3,0x7D9,0x1F0F,0x938,0x47E,0x92,0x8B2,0x7BE,0x10B8,0xC2};
-#endif
-
-#if CHUNK==32
-
-const BIG Modulus={0x186E9C03,0x7E79A9E,0x12329B7A,0x35B7957,0x435B396,0x16F46721,0x163C4049,0x1181675A,0xF1FD17};
-const chunk MConst=0x164E1155;
-const BIG CURVE_Order={0x6D655E1,0x1FEEA2CE,0x14AFE507,0x18CFC281,0x435B53D,0x16F46721,0x163C4049,0x1181675A,0xF1FD17};
-const BIG CURVE_B={0x1B7BB73F,0x3AF6CB3,0xC68600C,0x181935C9,0xC00FDFE,0x1D3AA522,0x4C0352A,0x194A8515,0xEE353F};
-const BIG CURVE_Gx={0x198F5CFF,0x64BD16E,0x62DC059,0xFA5B95F,0x23958C2,0x1EA3A4EA,0x7ACC460,0x186AD827,0xB6B3D4};
-const BIG CURVE_Gy={0x14062CFB,0x188AD0AA,0x19327860,0x3860FD1,0xEF8C270,0x18F879F6,0x12447E49,0x1EF91640,0x6142E0};
-#endif
-
-#if CHUNK==64
-
-const BIG Modulus={0xFCF353D86E9C03,0xADBCABC8CA6DE8,0xE8CE42435B3961,0xB3AD58F10126D,0xF1FD178C};
-const chunk MConst=0x97483A164E1155;
-const BIG CURVE_Order={0xFDD459C6D655E1,0x67E140D2BF941F,0xE8CE42435B53DC,0xB3AD58F10126D,0xF1FD178C};
-const BIG CURVE_B={0x75ED967B7BB73F,0xC9AE4B1A18030,0x754A44C00FDFEC,0x5428A9300D4ABA,0xEE353FCA};
-const BIG CURVE_Gx={0xC97A2DD98F5CFF,0xD2DCAF98B70164,0x4749D423958C27,0x56C139EB31183D,0xB6B3D4C3};
-const BIG CURVE_Gy={0x115A1554062CFB,0xC307E8E4C9E183,0xF0F3ECEF8C2701,0xC8B204911F9271,0x6142E0F7};
-#endif
-
-#endif
diff --git a/c/rsa.c b/c/rsa.c
deleted file mode 100755
index d74ff97..0000000
--- a/c/rsa.c
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
-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.
-*/
-
-
-/* RSA Functions - see main program below */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <time.h>
-
-#include "rsa.h"
-
-#define ROUNDUP(a,b) ((a)-1)/(b)+1
-
-/* general purpose hash function w=hash(p|n|x|y) */
-static void hashit(octet *p,int n,octet *w)
-{
-    int i,c[4];
-    hash sha;
-    char hh[32];
-
-    HASH_init(&sha);
-    if (p!=NULL)
-        for (i=0;i<p->len;i++) HASH_process(&sha,p->val[i]);
-	if (n>=0)
-    {
-        c[0]=(n>>24)&0xff;
-        c[1]=(n>>16)&0xff;
-        c[2]=(n>>8)&0xff;
-        c[3]=(n)&0xff;
-		for (i=0;i<4;i++) HASH_process(&sha,c[i]);
-    }
-
-    HASH_hash(&sha,hh);
-
-    OCT_empty(w);
-    OCT_jbytes(w,hh,32);
-    for (i=0;i<32;i++) hh[i]=0;
-}
-
-/* Initialise a Cryptographically Strong Random Number Generator from
-   an octet of raw random data */
-void RSA_CREATE_CSPRNG(csprng *RNG,octet *RAW)
-{
-    RAND_seed(RNG,RAW->len,RAW->val);
-}
-
-void RSA_KILL_CSPRNG(csprng *RNG)
-{
-    RAND_clean(RNG);
-}
-
-/* generate an RSA key pair */
-
-void RSA_KEY_PAIR(csprng *RNG,sign32 e,rsa_private_key *PRIV,rsa_public_key *PUB)
-{ /* IEEE1363 A16.11/A16.12 more or less */
-
-    int hE,m,r,bytes,hbytes,words,err,res=0;
-    BIG t[HFLEN],p1[HFLEN],q1[HFLEN];
-
-	for (;;)
-	{
-
-		FF_random(PRIV->p,RNG,HFLEN);
-		while (FF_lastbits(PRIV->p,2)!=3) FF_inc(PRIV->p,1,HFLEN);
-		while (!FF_prime(PRIV->p,RNG,HFLEN))
-			FF_inc(PRIV->p,4,HFLEN);
-
-		FF_copy(p1,PRIV->p,HFLEN);
-		FF_dec(p1,1,HFLEN);
-
-		if (FF_cfactor(p1,e,HFLEN)) continue;
-		break;
-	}
-
-	for (;;)
-	{
-		FF_random(PRIV->q,RNG,HFLEN);
-		while (FF_lastbits(PRIV->q,2)!=3) FF_inc(PRIV->q,1,HFLEN);
-		while (!FF_prime(PRIV->q,RNG,HFLEN))
-			FF_inc(PRIV->q,4,HFLEN);
-
-		FF_copy(q1,PRIV->q,HFLEN);
-		FF_dec(q1,1,HFLEN);
-		if (FF_cfactor(q1,e,HFLEN)) continue;
-
-		break;
-	}
-
-	FF_mul(PUB->n,PRIV->p,PRIV->q,HFLEN);
-	PUB->e=e;
-
-	FF_copy(t,p1,HFLEN);
-	FF_shr(t,HFLEN);
-	FF_init(PRIV->dp,e,HFLEN);
-	FF_invmodp(PRIV->dp,PRIV->dp,t,HFLEN);
-	if (FF_parity(PRIV->dp)==0) FF_add(PRIV->dp,PRIV->dp,t,HFLEN);
-	FF_norm(PRIV->dp,HFLEN);
-
-	FF_copy(t,q1,HFLEN);
-	FF_shr(t,HFLEN);
-	FF_init(PRIV->dq,e,HFLEN);
-	FF_invmodp(PRIV->dq,PRIV->dq,t,HFLEN);
-	if (FF_parity(PRIV->dq)==0) FF_add(PRIV->dq,PRIV->dq,t,HFLEN);
-	FF_norm(PRIV->dq,HFLEN);
-
-	FF_invmodp(PRIV->c,PRIV->p,PRIV->q,HFLEN);
-
-	return;
-}
-
-/* Mask Generation Function */
-
-void MGF1(octet *z,int olen,octet *mask)
-{
-	char h[32];
-    octet H={0,sizeof(h),h};
-	int hlen=32;
-    int counter,cthreshold;
-
-    OCT_empty(mask);
-
-    cthreshold=ROUNDUP(olen,hlen);
-
-    for (counter=0;counter<cthreshold;counter++)
-    {
-        hashit(z,counter,&H);
-        if (mask->len+hlen>olen) OCT_jbytes(mask,H.val,olen%hlen);
-        else                     OCT_joctet(mask,&H);
-    }
-    OCT_clear(&H);
-}
-
-/* OAEP Message Encoding for Encryption */
-
-int RSA_OAEP_ENCODE(octet *m,csprng *RNG,octet *p,octet *f)
-{
-    int i,slen,olen=RFS-1;
-    int mlen=m->len;
-    int hlen,seedlen;
-    char dbmask[RFS],seed[32];
-	octet DBMASK={0,sizeof(dbmask),dbmask};
-	octet SEED={0,sizeof(seed),seed};
-
-    hlen=seedlen=32;
-    if (mlen>olen-hlen-seedlen-1) return 0;
-    if (m==f) return 0;  /* must be distinct octets */
-
-    hashit(p,-1,f);
-
-    slen=olen-mlen-hlen-seedlen-1;
-
-    OCT_jbyte(f,0,slen);
-    OCT_jbyte(f,0x1,1);
-    OCT_joctet(f,m);
-
-    OCT_rand(&SEED,RNG,seedlen);
-
-    MGF1(&SEED,olen-seedlen,&DBMASK);
-
-    OCT_xor(&DBMASK,f);
-    MGF1(&DBMASK,seedlen,f);
-
-    OCT_xor(f,&SEED);
-
-    OCT_joctet(f,&DBMASK);
-
-	OCT_pad(f,RFS);
-    OCT_clear(&SEED);
-    OCT_clear(&DBMASK);
-
-    return 1;
-}
-
-/* OAEP Message Decoding for Decryption */
-
-int RSA_OAEP_DECODE(octet *p,octet *f)
-{
-    int comp,x,t;
-    int i,k,olen=RFS-1;
-    int hlen,seedlen;
-    char dbmask[RFS],seed[32],chash[32];;
-	octet DBMASK={0,sizeof(dbmask),dbmask};
-	octet SEED={0,sizeof(seed),seed};
-	octet CHASH={0,sizeof(chash),chash};
-
-    seedlen=hlen=32;;
-    if (olen<seedlen+hlen+1) return 0;
-    if (!OCT_pad(f,olen+1)) return 0;
-    hashit(p,-1,&CHASH);
-
-    x=f->val[0];
-    for (i=seedlen;i<olen;i++)
-        DBMASK.val[i-seedlen]=f->val[i+1];
-    DBMASK.len=olen-seedlen;
-
-    MGF1(&DBMASK,seedlen,&SEED);
-    for (i=0;i<seedlen;i++) SEED.val[i]^=f->val[i+1];
-    MGF1(&SEED,olen-seedlen,f);
-    OCT_xor(&DBMASK,f);
-
-    comp=OCT_ncomp(&CHASH,&DBMASK,hlen);
-
-    OCT_shl(&DBMASK,hlen);
-
-    OCT_clear(&SEED);
-    OCT_clear(&CHASH);
-
-    for (k=0;;k++)
-    {
-        if (k>=DBMASK.len)
-        {
-            OCT_clear(&DBMASK);
-            return 0;
-        }
-        if (DBMASK.val[k]!=0) break;
-    }
-
-    t=DBMASK.val[k];
-    if (!comp || x!=0 || t!=0x01)
-    {
-        OCT_clear(&DBMASK);
-        return 0;
-    }
-
-    OCT_shl(&DBMASK,k+1);
-    OCT_copy(f,&DBMASK);
-    OCT_clear(&DBMASK);
-
-    return 1;
-}
-
-/* destroy the Private Key structure */
-void RSA_PRIVATE_KEY_KILL(rsa_private_key *PRIV)
-{
-    FF_zero(PRIV->p,HFLEN);
-	FF_zero(PRIV->q,HFLEN);
-	FF_zero(PRIV->dp,HFLEN);
-	FF_zero(PRIV->dq,HFLEN);
-	FF_zero(PRIV->c,HFLEN);
-}
-
-/* RSA encryption with the public key */
-void RSA_ENCRYPT(rsa_public_key *PUB,octet *F,octet *G)
-{
-	BIG f[FFLEN];
-	FF_fromOctet(f,F,FFLEN);
-
-    FF_power(f,f,PUB->e,PUB->n,FFLEN);
-
-	FF_toOctet(G,f,FFLEN);
-}
-
-/* RSA decryption with the private key */
-void RSA_DECRYPT(rsa_private_key *PRIV,octet *G,octet *F)
-{
-	BIG g[FFLEN],t[FFLEN],jp[HFLEN],jq[HFLEN];
-
-	FF_fromOctet(g,G,FFLEN);
-
-	FF_dmod(jp,g,PRIV->p,HFLEN);
-	FF_dmod(jq,g,PRIV->q,HFLEN);
-
-	FF_skpow(jp,jp,PRIV->dp,PRIV->p,HFLEN);
-	FF_skpow(jq,jq,PRIV->dq,PRIV->q,HFLEN);
-
-
-	FF_zero(g,FFLEN);
-	FF_copy(g,jp,HFLEN);
-	FF_mod(jp,PRIV->q,HFLEN);
-	if (FF_comp(jp,jq,HFLEN)>0)
-		FF_add(jq,jq,PRIV->q,HFLEN);
-	FF_sub(jq,jq,jp,HFLEN);
-	FF_norm(jq,HFLEN);
-
-	FF_mul(t,PRIV->c,jq,HFLEN);
-	FF_dmod(jq,t,PRIV->q,HFLEN);
-
-	FF_mul(t,jq,PRIV->p,HFLEN);
-	FF_add(g,t,g,FFLEN);
-	FF_norm(g,FFLEN);
-
-	FF_toOctet(F,g,FFLEN);
-
-	return;
-}
-
diff --git a/c/rsa.h b/c/rsa.h
deleted file mode 100755
index df1a151..0000000
--- a/c/rsa.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
-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.
-*/
-
-/**
- * @file rsa.h
- * @author Mike Scott and Kealan McCusker
- * @date 2nd June 2015
- * @brief RSA Header file for implementation of RSA protocol
- *
- * declares functions
- *
- */
-
-#ifndef RSA_H
-#define RSA_H
-
-#include "amcl.h"
-
-#define RFS MODBYTES*FFLEN /**< RSA Public Key Size in bytes */
-
-/* RSA Auxiliary Functions */
-/**	@brief Initialise a random number generator
- *
-	@param R is a pointer to a cryptographically secure random number generator
-	@param S is an input truly random seed value
- */
-extern void RSA_CREATE_CSPRNG(csprng *R,octet *S);
-/**	@brief Kill a random number generator
- *
-	Deletes all internal state
-	@param R is a pointer to a cryptographically secure random number generator
- */
-extern void RSA_KILL_CSPRNG(csprng *R);
-/**	@brief RSA Key Pair Generator
- *
-	@param R is a pointer to a cryptographically secure random number generator
-	@param e the encryption exponent
-	@param PRIV the output RSA private key
-	@param PUB the output RSA public key
- */
-extern void RSA_KEY_PAIR(csprng *R,sign32 e,rsa_private_key* PRIV,rsa_public_key* PUB);
-/**	@brief OAEP padding of a message prior to RSA encryption
- *
-	@param M is the input message
-	@param R is a pointer to a cryptographically secure random number generator
-	@param P are input encoding parameter string (could be NULL)
-	@param F is the output encoding, ready for RSA encryption
-	@return 1 if OK, else 0
- */
-extern int RSA_OAEP_ENCODE(octet *M,csprng *R,octet *P,octet *F);
-/**	@brief OAEP unpadding of a message after RSA decryption
- *
-	Unpadding is done in-place
-	@param P are input encoding parameter string (could be NULL)
-	@param F is input padded message, unpadded on output
-	@return 1 if OK, else 0
- */
-extern int RSA_OAEP_DECODE(octet *P,octet *F);
-/**	@brief RSA encryption of suitably padded plaintext
- *
-	@param PUB the input RSA public key
-	@param F is input padded message
-	@param G is the output ciphertext
- */
-extern void RSA_ENCRYPT(rsa_public_key* PUB,octet *F,octet *G);
-/**	@brief RSA decryption of ciphertext
- *
-	@param PRIV the input RSA private key
-	@param G is the input ciphertext
-	@param F is output plaintext (requires unpadding)
-
- */
-extern void RSA_DECRYPT(rsa_private_key* PRIV,octet *G,octet *F);
-/**	@brief Destroy an RSA private Key
- *
-	@param PRIV the input RSA private key. Destroyed on output.
- */
-extern void RSA_PRIVATE_KEY_KILL(rsa_private_key *PRIV);
-
-#endif
diff --git a/c/testecdh.c b/c/testecdh.c
deleted file mode 100755
index 26621a7..0000000
--- a/c/testecdh.c
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
-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.
-*/
-
-/* test driver and function exerciser for ECDH/ECIES/ECDSA API Functions */
-/* gcc -std=c99 -O3 testecdh.c ecdh.c amcl.a -o testecdh.exe */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include "ecdh.h"
-
-int main()
-{
-    int i,j=0,res;
-    int result;
-	unsigned long ran;
-	char *pp="M0ng00se";
-/* These octets are automatically protected against buffer overflow attacks */
-/* Note salt must be big enough to include an appended word */
-/* Note ECIES ciphertext C must be big enough to include at least 1 appended block */
-/* Recall EFS is field size in bytes. So EFS=32 for 256-bit curve */
-	char s0[EGS],s1[EGS],w0[2*EFS+1],w1[2*EFS+1],z0[EFS],z1[EFS],raw[100],key[EAS],salt[32],pw[20],p1[30],p2[30],v[2*EFS+1],m[32],c[64],t[32],cs[EGS],ds[EGS];
-	octet S0={0,sizeof(s0),s0};
-	octet S1={0,sizeof(s1),s1};
-	octet W0={0,sizeof(w0),w0};
-	octet W1={0,sizeof(w1),w1};
-	octet Z0={0,sizeof(z0),z0};
-	octet Z1={0,sizeof(z1),z1};
-	octet RAW={0,sizeof(raw),raw};
-	octet KEY={0,sizeof(key),key};
-	octet SALT={0,sizeof(salt),salt};
-	octet PW={0,sizeof(pw),pw};
-	octet P1={0,sizeof(p1),p1};
-	octet P2={0,sizeof(p2),p2};
-	octet V={0,sizeof(v),v};
-	octet M={0,sizeof(m),m};
-	octet C={0,sizeof(c),c};
-	octet T={0,sizeof(t),t};
-	octet CS={0,sizeof(cs),cs};
-	octet DS={0,sizeof(ds),ds};
-
-    csprng RNG;                /* Crypto Strong RNG */
-
-	time((time_t *)&ran);
-
-    RAW.len=100;				/* fake random seed source */
-    RAW.val[0]=ran;
-    RAW.val[1]=ran>>8;
-    RAW.val[2]=ran>>16;
-    RAW.val[3]=ran>>24;
-    for (i=0;i<100;i++) RAW.val[i]=i;
-
-    ECP_CREATE_CSPRNG(&RNG,&RAW);   /* initialise strong RNG */
-
-//for (j=0;j<100;j++)
-//{
-    SALT.len=8;
-    for (i=0;i<8;i++) SALT.val[i]=i+1;  // set Salt
-
-	printf("Alice's Passphrase= %s\n",pp);
-
-	OCT_empty(&PW);
-	OCT_jstring(&PW,pp);   // set Password from string
-
-/* private key S0 of size EGS bytes derived from Password and Salt */
-
-	ECP_PBKDF2(&PW,&SALT,1000,EGS,&S0);
-	printf("Alices private key= 0x"); OCT_output(&S0);
-
-/* Generate Key pair S/W */
-
-    ECP_KEY_PAIR_GENERATE(NULL,&S0,&W0);
-
-    res=ECP_PUBLIC_KEY_VALIDATE(1,&W0);
-    if (res!=0)
-    {
-        printf("ECP Public Key is invalid!\n");
-        return 0;
-    }
-
-	printf("Alice's public key= 0x");  OCT_output(&W0);
-
-/* Random private key for other party */
-    ECP_KEY_PAIR_GENERATE(&RNG,&S1,&W1);
-    res=ECP_PUBLIC_KEY_VALIDATE(1,&W1);
-    if (res!=0)
-    {
-        printf("ECP Public Key is invalid!\n");
-        return 0;
-    }
-	printf("Servers private key= 0x");  OCT_output(&S1);
-	printf("Servers public key= 0x");   OCT_output(&W1);
-
-/* Calculate common key using DH - IEEE 1363 method */
-
-    ECP_SVDP_DH(&S0,&W1,&Z0);
-    ECP_SVDP_DH(&S1,&W0,&Z1);
-
-	if (!OCT_comp(&Z0,&Z1))
-    {
-        printf("*** ECPSVDP-DH Failed\n");
-        return 0;
-    }
-
-	ECP_KDF2(&Z0,NULL,EAS,&KEY);
-
-	printf("Alice's DH Key=  0x"); OCT_output(&KEY);
-	printf("Servers DH Key=  0x"); OCT_output(&KEY);
-
-	printf("Testing ECIES\n");
-
-	P1.len=3; P1.val[0]=0x0; P1.val[1]=0x1; P1.val[2]=0x2;
-	P2.len=4; P2.val[0]=0x0; P2.val[1]=0x1; P2.val[2]=0x2; P2.val[3]=0x3;
-
-    M.len=17;
-    for (i=0;i<=16;i++) M.val[i]=i;
-
-	ECP_ECIES_ENCRYPT(&P1,&P2,&RNG,&W1,&M,12,&V,&C,&T);
-
-	printf("Ciphertext= \n");
-	printf("V= 0x"); OCT_output(&V);
-	printf("C= 0x"); OCT_output(&C);
-	printf("T= 0x"); OCT_output(&T);
-
-	if (!ECP_ECIES_DECRYPT(&P1,&P2,&V,&C,&T,&S1,&M))
-	{
-		printf("*** ECIES Decryption Failed\n");
-		return 0;
-	}
-	else printf("Decryption succeeded\n");
-
-	printf("Message is 0x"); OCT_output(&M);
-
-
-	printf("Testing ECDSA\n");
-
-	if (ECP_SP_DSA(&RNG,&S0,&M,&CS,&DS)!=0)
-	{
-		printf("***ECDSA Signature Failed\n");
-		return 0;
-	}
-
-	printf("Signature C = 0x"); OCT_output(&CS);
-	printf("Signature D = 0x"); OCT_output(&DS);
-
-	if (ECP_VP_DSA(&W0,&M,&CS,&DS)!=0)
-	{
-		printf("***ECDSA Verification Failed\n");
-		return 0;
-	}
-	else printf("ECDSA Signature/Verification succeeded %d\n",j);
-//}
-//printf("Test Completed Successfully\n");
-	ECP_KILL_CSPRNG(&RNG);
-
-    return 0;
-}
-
diff --git a/c/testecm.c b/c/testecm.c
deleted file mode 100755
index 94c996d..0000000
--- a/c/testecm.c
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
-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.
-*/
-
-/* test driver and function exerciser for ECDH API Functions only - suitable for testing Montgomery curves */
-/* gcc -std=c99 -O3 testecm.c ecdh.c amcl.a -o testecm.exe */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include "ecdh.h"
-
-int main()
-{
-    int i,j=0,res;
-    int result;
-	unsigned long ran;
-	char *pp="M0ng00se";
-/* These octets are automatically protected against buffer overflow attacks */
-/* Note salt must be big enough to include an appended word */
-/* Note ECIES ciphertext C must be big enough to include at least 1 appended block */
-/* Recall EFS is field size in bytes. So EFS=32 for 256-bit curve */
-	char s0[EGS],s1[EGS],w0[2*EFS+1],w1[2*EFS+1],z0[EFS],z1[EFS],raw[100],key[EAS],salt[32],pw[20];
-	octet S0={0,sizeof(s0),s0};
-	octet S1={0,sizeof(s1),s1};
-	octet W0={0,sizeof(w0),w0};
-	octet W1={0,sizeof(w1),w1};
-	octet Z0={0,sizeof(z0),z0};
-	octet Z1={0,sizeof(z1),z1};
-	octet RAW={0,sizeof(raw),raw};
-	octet KEY={0,sizeof(key),key};
-	octet SALT={0,sizeof(salt),salt};
-	octet PW={0,sizeof(pw),pw};
-
-    csprng RNG;                /* Crypto Strong RNG */
-
-	time((time_t *)&ran);
-
-    RAW.len=100;				/* fake random seed source */
-    RAW.val[0]=ran;
-    RAW.val[1]=ran>>8;
-    RAW.val[2]=ran>>16;
-    RAW.val[3]=ran>>24;
-    for (i=4;i<100;i++) RAW.val[i]=i;
-
-    ECP_CREATE_CSPRNG(&RNG,&RAW);   /* initialise strong RNG */
-
-//for (j=0;j<1000;j++)
-//{
-    SALT.len=8;
-    for (i=0;i<8;i++) SALT.val[i]=i+1;  // set Salt
-
-	printf("Alice's Passphrase= %s\n",pp);
-
-	OCT_clear(&PW);
-	OCT_jstring(&PW,pp);   // set Password from string
-
-/* private key S0 of size EGS bytes derived from Password and Salt */
-
-	ECP_PBKDF2(&PW,&SALT,1000,EGS,&S0);
-	printf("Alices private key= 0x"); OCT_output(&S0);
-
-/* Generate Key pair S/W */
-
-    ECP_KEY_PAIR_GENERATE(NULL,&S0,&W0);
-
-    res=ECP_PUBLIC_KEY_VALIDATE(1,&W0);
-    if (res!=0)
-    {
-        printf("Alice's ECP Public Key is invalid!\n");
-        return 0;
-    }
-
-	printf("Alice's public key= 0x");  OCT_output(&W0);
-
-/* Random private key for other party */
-    ECP_KEY_PAIR_GENERATE(&RNG,&S1,&W1);
-	printf("Servers private key= 0x");  OCT_output(&S1);
-	printf("Servers public key= 0x");   OCT_output(&W1);
-
-    res=ECP_PUBLIC_KEY_VALIDATE(1,&W1);
-    if (res!=0)
-    {
-        printf("Server's ECP Public Key is invalid!\n");
-        return 0;
-    }
-
-/* Calculate common key using DH - IEEE 1363 method */
-
-    ECP_SVDP_DH(&S0,&W1,&Z0);
-    ECP_SVDP_DH(&S1,&W0,&Z1);
-
-	if (!OCT_comp(&Z0,&Z1))
-    {
-        printf("*** ECP_SVDP-DH Failed\n");
-        return 0;
-    }
-
-	ECP_KDF2(&Z0,NULL,EAS,&KEY);
-
-	printf("Alice's DH Key=  0x"); OCT_output(&KEY);
-	printf("Servers DH Key=  0x"); OCT_output(&KEY);
-//}
-//printf("Test Completed Successfully\n");
-
-    return 0;
-}
-
diff --git a/c/testmpin.c b/c/testmpin.c
deleted file mode 100755
index 6dedf7c..0000000
--- a/c/testmpin.c
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
-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.
-*/
-
-/* test driver and function exerciser for MPIN Functions */
-/* Version 3.0 - supports Time Permits */
-
-
-/* Build executible after installation:
-
-  gcc -std=c99 -g ./testmpin.c -I/opt/amcl/include -L/opt/amcl/lib -lamcl -lmpin -o testmpin
-
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include "mpin.h"
-
-#define PERMITS  /* for time permits ON or OFF */
-#define PINERROR /* For PIN ERROR detection ON or OFF */
-#define FULL     /* for M-Pin Full or M-Pin regular */
-#define SINGLE_PASS /* SINGLE PASS M-Pin */
-
-int main()
-{
-  int i,pin,rtn,err,timeValue;
-#ifdef PERMITS
-  int date=MPIN_today();
-#else
-  int date=0;
-#endif
-  unsigned long ran;
-  char x[PGS],s[PGS],y[PGS],client_id[100],raw[100],sst[4*PFS],token[2*PFS+1],sec[2*PFS+1],permit[2*PFS+1],xcid[2*PFS+1],xid[2*PFS+1],e[12*PFS],f[12*PFS];
-  char hcid[HASH_BYTES],hsid[HASH_BYTES],hid[2*PFS+1],htid[2*PFS+1],h[PGS];
-#ifdef FULL
-  char r[PGS],z[2*PFS+1],w[PGS],t[2*PFS+1];
-  char g1[12*PFS],g2[12*PFS];
-  char ck[PAS],sk[PAS];
-#endif
-  octet S={0,sizeof(s),s};
-  octet X={0,sizeof(x),x};
-  octet Y={0,sizeof(y),y};
-  octet H={0,sizeof(h),h};
-  octet RAW={0,sizeof(raw),raw};
-  octet CLIENT_ID={0,sizeof(client_id),client_id};
-  octet SST={0,sizeof(sst),sst};
-  octet TOKEN={0,sizeof(token),token};
-  octet SEC={0,sizeof(sec),sec};
-  octet PERMIT={0,sizeof(permit),permit};
-  octet xCID={0,sizeof(xcid),xcid};
-  octet xID={0,sizeof(xid),xid};
-  octet HCID={0,sizeof(hcid),hcid};
-  octet HSID={0,sizeof(hsid),hsid};
-  octet HID={0,sizeof(hid),hid};
-  octet HTID={0,sizeof(htid),htid};
-  octet E={0,sizeof(e),e};
-  octet F={0,sizeof(f),f};
-#ifdef FULL
-  octet R={0,sizeof(r),r};
-  octet Z={0,sizeof(z),z};
-  octet W={0,sizeof(w),w};
-  octet T={0,sizeof(t),t};
-  octet G1={0,sizeof(g1),g1};
-  octet G2={0,sizeof(g2),g2};
-  octet SK={0,sizeof(sk),sk};
-  octet CK={0,sizeof(ck),ck};
-#endif
-  octet *pxID,*pxCID,*pHID,*pHTID,*pE,*pF,*pPERMIT,*prHID;
-
-  /* Crypto Strong RNG */
-  csprng RNG;
-  /* fake random seed source */
-  time((time_t *)&ran);
-  RAW.len=100;
-  RAW.val[0]=ran;
-  RAW.val[1]=ran>>8;
-  RAW.val[2]=ran>>16;
-  RAW.val[3]=ran>>24;
-  for (i=4;i<100;i++) RAW.val[i]=i+1;
-
-  /* initialise strong RNG */
-  MPIN_CREATE_CSPRNG(&RNG,&RAW);
-
-  /* Trusted Authority set-up */
-  MPIN_RANDOM_GENERATE(&RNG,&S);
-  printf("Master Secret= "); OCT_output(&S);
-
-  /* Create Client Identity */
-  OCT_jstring(&CLIENT_ID,"testUser@miracl.com");
-  MPIN_HASH_ID(&CLIENT_ID,&HCID);  /* Either Client or TA calculates Hash(ID) - you decide! */
-  printf("Client ID= "); OCT_output_string(&CLIENT_ID); printf("\n");
-
-  /* When set only send hashed IDs to server */
-  octet *pID;
-#ifdef USE_ANONYMOUS
-  pID = &HCID;
-#else
-  pID = &CLIENT_ID;
-#endif
-
-  /* Client and Server are issued secrets by DTA */
-  MPIN_GET_SERVER_SECRET(&S,&SST);
-  printf("Server Secret= "); OCT_output(&SST);
-
-  MPIN_GET_CLIENT_SECRET(&S,&HCID,&TOKEN);
-  printf("Client Secret= "); OCT_output(&TOKEN);
-
-  /* Client extracts PIN from secret to create Token */
-  pin=1234;
-  printf("Client extracts PIN= %d\n",pin);
-  MPIN_EXTRACT_PIN(&CLIENT_ID,pin,&TOKEN);
-  printf("Client Token= "); OCT_output(&TOKEN);
-
-#ifdef FULL
-  MPIN_PRECOMPUTE(&TOKEN,&HCID,&G1,&G2);
-#endif
-
-#ifdef PERMITS
-  /* Client gets "Time Permit" from DTA */
-  printf("Client gets Time Permit\n");
-
-  MPIN_GET_CLIENT_PERMIT(date,&S,&HCID,&PERMIT);
-  printf("Time Permit= "); OCT_output(&PERMIT);
-
-  /* This encoding makes Time permit look random */
-  if (MPIN_ENCODING(&RNG,&PERMIT)!=0) printf("Encoding error\n");
-  /* printf("Encoded Time Permit= "); OCT_output(&PERMIT); */
-  if (MPIN_DECODING(&PERMIT)!=0) printf("Decoding error\n");
-  /* printf("Decoded Time Permit= "); OCT_output(&PERMIT); */
-#endif
-
-  /* MPin Protocol */
-
-  /* Client enters PIN */
-  printf("\nPIN= ");
-  if(scanf("%d",&pin)){};
-  /* to avoid silly compile error */
-  getchar();
-
-  /* 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
-
-  HSID - hashed client ID as calculated by the server
-  HCID - hashed client ID as calculated by the client
-
-  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.
-
-  */
-
-  pxID=&xID;
-  pxCID=&xCID;
-  pHID=&HID;
-  pHTID=&HTID;
-  pE=&E;
-  pF=&F;
-  pPERMIT=&PERMIT;
-
-#ifdef PERMITS
-  prHID=pHTID;
-#ifndef PINERROR
-   pxID=NULL;
-   // pHID=NULL;
-#endif
-#else
-   prHID=pHID;
-   pPERMIT=NULL;
-   pxCID=NULL;
-   pHTID=NULL;
-#endif
-#ifndef PINERROR
-   pE=NULL;
-   pF=NULL;
-#endif
-
-#ifdef SINGLE_PASS
-  printf("MPIN Single Pass\n");
-  timeValue = MPIN_GET_TIME();
-  rtn=MPIN_CLIENT(date,&CLIENT_ID,&RNG,&X,pin,&TOKEN,&SEC,pxID,pxCID,pPERMIT,NULL,timeValue,&Y);
-  if (rtn != 0)
-  {
-    printf("MPIN_CLIENT ERROR %d\n", rtn);
-    return 1;
-  }
-
-#ifdef FULL
-  MPIN_GET_G1_MULTIPLE(&RNG,1,&R,&HCID,&Z);  /* Also Send Z=r.ID to Server, remember random r */
-#endif
-
-  rtn=MPIN_SERVER(date,pHID,pHTID,&Y,&SST,pxID,pxCID,&SEC,pE,pF,&CLIENT_ID,NULL,timeValue);
-  if (rtn != 0)
-  {
-    printf("MPIN_SERVER ERROR %d\n", rtn);
-  }
-
-#ifdef FULL
-  MPIN_GET_G1_MULTIPLE(&RNG,0,&W,prHID,&T);  /* Also send T=w.ID to client, remember random w  */
-#endif
-
-#else // SINGLE_PASS
-  printf("MPIN Multi Pass\n");
-
-  if (MPIN_CLIENT_1(date,&CLIENT_ID,&RNG,&X,pin,&TOKEN,&SEC,pxID,pxCID,pPERMIT)!=0)
-  {
-    printf("Error from Client side - First Pass\n");
-    return 0;
-  }
-
-  /* Send U=x.ID to server, and recreate secret from token and pin */
-
-#ifdef FULL
-  MPIN_GET_G1_MULTIPLE(&RNG,1,&R,&HCID,&Z);  /* Also Send Z=r.ID to Server, remember random r */
-#endif
-
-  /* Server calculates H(ID) and H(ID)+H(T|H(ID)) (if time permits enabled), and maps them to points on the curve HID and HTID resp. */
-  MPIN_SERVER_1(date,pID,pHID,pHTID);
-
-  /* Server generates Random number Y and sends it to Client */
-  MPIN_RANDOM_GENERATE(&RNG,&Y);
-
-#ifdef FULL
-  MPIN_GET_G1_MULTIPLE(&RNG,0,&W,prHID,&T);  /* Also send T=w.ID to client, remember random w  */
-#endif
-
-  /* Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC */
-  if (MPIN_CLIENT_2(&X,&Y,&SEC)!=0)
-  {
-    printf("Error from Client side - Second Pass\n");
-    return 1;
-  }
-
-  /* Server Second phase. 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=MPIN_SERVER_2(date,pHID,pHTID,&Y,&SST,pxID,pxCID,&SEC,pE,pF);
-#endif // SINGLE_PASS
-
-  if (rtn!=0)
-    {
-      printf("Server says - Bad Pin. \n");
-#ifdef PINERROR
-
-      err=MPIN_KANGAROO(&E,&F);
-      if (err) printf("(Client PIN is out by %d)\n",err);
-
-#endif
-      return 1;
-    }
-  else
-    {
-      printf("Server says - PIN is good! ID: "); 
-      OCT_output_string(&CLIENT_ID); 
-      printf(".\n");
-    }
-
-#ifdef FULL
-  MPIN_HASH_ALL(&HCID,pxID,pxCID,&SEC,&Y,&Z,&T,&H);  
-  MPIN_CLIENT_KEY(&G1,&G2,pin,&R,&X,&H,&T,&CK);      
-  printf("Client Key = "); OCT_output(&CK); 
-
-  /* Server will use the hashed ID if anonymous connection required.
-     MPIN_HASH_ID(&CLIENT_ID,&HSID);
-     MPIN_HASH_ALL(&HSID,pxID,pxCID,&SEC,&Y,&Z,&T,&H);
-  */
-  MPIN_SERVER_KEY(&Z,&SST,&W,&H,pHID,pxID,pxCID,&SK);
-  printf("Server Key = "); OCT_output(&SK); 
-#endif
-  return 0;
-}
diff --git a/c/testrsa.c b/c/testrsa.c
deleted file mode 100755
index 81b5887..0000000
--- a/c/testrsa.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
-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.
-*/
-
-/* test driver and function exerciser for RSA API Functions */
-/* gcc -std=c99 -O3 testrsa.c rsa.c amcl.a -o testrsa.exe */
-
-
-#include <stdio.h>
-#include <time.h>
-#include "rsa.h"
-
-int main()
-{
-    int i,bytes,res;
-	unsigned long ran;
- 	char m[RFS],ml[RFS],c[RFS],e[RFS],raw[100];
-    rsa_public_key pub;
-    rsa_private_key priv;
-    csprng RNG;
-	octet M={0,sizeof(m),m};
-	octet ML={0,sizeof(ml),ml};
-	octet C={0,sizeof(c),c};
-	octet E={0,sizeof(e),e};
-	octet RAW={0,sizeof(raw),raw};
-
-	time((time_t *)&ran);
-
-    RAW.len=100;				/* fake random seed source */
-    RAW.val[0]=ran;
-    RAW.val[1]=ran>>8;
-    RAW.val[2]=ran>>16;
-    RAW.val[3]=ran>>24;
-    for (i=4;i<100;i++) RAW.val[i]=i;
-
-    RSA_CREATE_CSPRNG(&RNG,&RAW);   /* initialise strong RNG */
-//for (i=0;i<10;i++)
-//{
-
-	printf("Generating public/private key pair\n");
-    RSA_KEY_PAIR(&RNG,65537,&priv,&pub);
-
-	printf("Encrypting test string\n");
-	OCT_jstring(&M,(char *)"Hello World\n");
-	RSA_OAEP_ENCODE(&M,&RNG,NULL,&E); /* OAEP encode message m to e  */
-
-	RSA_ENCRYPT(&pub,&E,&C);     /* encrypt encoded message */
-	printf("Ciphertext= "); OCT_output(&C);
-
-	printf("Decrypting test string\n");
-    RSA_DECRYPT(&priv,&C,&ML);   /* ... and then decrypt it */
-
-    RSA_OAEP_DECODE(NULL,&ML);    /* decode it */
-	OCT_output_string(&ML);
-
-    OCT_clear(&M); OCT_clear(&ML);   /* clean up afterwards */
-    OCT_clear(&C); OCT_clear(&RAW); OCT_clear(&E);
-//}
-	RSA_KILL_CSPRNG(&RNG);
-
-	RSA_PRIVATE_KEY_KILL(&priv);
-
-	return 0;
-}
diff --git a/c/tests/CMakeLists.txt b/c/tests/CMakeLists.txt
deleted file mode 100644
index bdafec1..0000000
--- a/c/tests/CMakeLists.txt
+++ /dev/null
@@ -1,84 +0,0 @@
-# Create tests
-
-# add the binary tree directory to the search path for include files and linking
-include_directories (${CMAKE_CURRENT_BINARY_DIR} ${PROJECT_SOURCE_DIR}/c ${PROJECT_BINARY_DIR}/c )
-link_directories (${PROJECT_BINARY_DIR}/c)
-
-# enable testing
-enable_testing ()
-
-#define a macro to simplify adding tests
-macro (do_test arg result)
-  add_test (${arg} ${arg})
-  set_tests_properties (${arg}
-    PROPERTIES PASS_REGULAR_EXPRESSION ${result}
-    )
-endmacro ()
-
-if(BUILD_MPIN)
-  add_executable (test_mpin test_mpin.c)
-  add_executable (test_mpin_sign test_mpin_sign.c)
-  add_executable (test_mpin_good test_mpin_good.c)
-  add_executable (test_mpin_bad_pin test_mpin_bad_pin.c)
-  add_executable (test_mpin_bad_token test_mpin_bad_token.c)
-  add_executable (test_mpin_expired_tp test_mpin_expired_tp.c)
-  add_executable (test_mpin_tp test_mpin_tp.c config.h)
-  add_executable (test_mpin_random test_mpin_random.c config.h)
-  add_executable (test_mpinfull test_mpinfull.c)
-  add_executable (test_mpinfullSingle test_mpinfullSingle.c)
-  add_executable (test_mpinfull_random test_mpinfull_random.c config.h)
-  # Link the executable to the libraries
-  target_link_libraries (test_mpin mpin) 
-  target_link_libraries (test_mpin_sign mpin) 
-  target_link_libraries (test_mpin_good mpin) 
-  target_link_libraries (test_mpin_bad_pin mpin) 
-  target_link_libraries (test_mpin_bad_token mpin) 
-  target_link_libraries (test_mpin_expired_tp mpin) 
-  target_link_libraries (test_mpin_tp mpin) 
-  target_link_libraries (test_mpin_random mpin) 
-  target_link_libraries (test_mpinfull mpin) 
-  target_link_libraries (test_mpinfullSingle mpin) 
-  target_link_libraries (test_mpinfull_random mpin) 
-  # tests
-  do_test (test_mpin "SUCCESS Error Code 0")
-  do_test (test_mpin_sign "TEST PASSED")
-  do_test (test_mpin_good "SUCCESS Error Code 0")
-  do_test (test_mpin_bad_pin "FAILURE")
-  do_test (test_mpin_bad_token "FAILURE Invalid Token Error Code -19")
-  do_test (test_mpin_expired_tp "FAILURE Invalid Token Error Code -19")
-  do_test (test_mpin_tp "Iteration ${MPIN_TIME_PERMIT_TESTS} SUCCESS Error Code 0")
-  do_test (test_mpin_random "Iteration ${MPIN_RANDOM_TESTS} SUCCESS Error Code 0")
-  do_test (test_mpinfull "SUCCESS")
-  do_test (test_mpinfullSingle "SUCCESS")
-  do_test (test_mpinfull_random "Iteration ${MPIN_RANDOM_TESTS} SUCCESS")
-endif(BUILD_MPIN)
-
-if(BUILD_WCC)
-  add_executable (test_wcc_gcm test_wcc_gcm.c)
-  add_executable (test_wcc test_wcc.c)
-  add_executable (test_wcc_random test_wcc_random.c)
-  # Link the executable to the libraries
-  target_link_libraries (test_wcc_gcm wcc) 
-  target_link_libraries (test_wcc wcc) 
-  target_link_libraries (test_wcc_random wcc) 
-  # tests  
-  do_test (test_wcc_gcm "SUCCESS")
-  do_test (test_wcc "SUCCESS")
-  do_test (test_wcc_random "SUCCESS")
-endif(BUILD_WCC)  
-
-# General tests
-add_executable (test_rsa ${PROJECT_SOURCE_DIR}/c/rsa.c test_rsa.c)
-add_executable (test_ecm ${PROJECT_SOURCE_DIR}/c/ecdh.c test_ecm.c)
-add_executable (test_ecdh ${PROJECT_SOURCE_DIR}/c/ecdh.c test_ecdh.c)
-add_executable (test_version test_version.c)
-# Link the executable to the libraries
-target_link_libraries (test_rsa amcl) 
-target_link_libraries (test_ecm amcl) 
-target_link_libraries (test_ecdh amcl) 
-target_link_libraries (test_version amcl) 
-# tests  
-do_test (test_rsa "SUCCESS")
-do_test (test_ecm "SUCCESS")
-do_test (test_ecdh "SUCCESS")
-do_test (test_version "Version: ${AMCL_VERSION_MAJOR}.${AMCL_VERSION_MINOR}.${AMCL_VERSION_PATCH} OS: ${OS} FIELD CHOICE: ${FIELD_CHOICE} CURVE TYPE: ${CURVE_TYPE} WORD_LENGTH: ${WORD_LENGTH}")
diff --git a/c/tests/config.h.in b/c/tests/config.h.in
deleted file mode 100644
index 7240997..0000000
--- a/c/tests/config.h.in
+++ /dev/null
@@ -1,2 +0,0 @@
-const int nTimePermitTests = @MPIN_TIME_PERMIT_TESTS@;
-const int nRandomTests = @MPIN_RANDOM_TESTS@;
diff --git a/c/tests/test_ecdh.c b/c/tests/test_ecdh.c
deleted file mode 100755
index 8bb9e8c..0000000
--- a/c/tests/test_ecdh.c
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
-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.
-*/
-
-/* test driver and function exerciser for ECDH/ECIES/ECDSA API Functions */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include "ecdh.h"
-
-int main()
-{
-  int i,j=0,res;
-  int result;
-  unsigned long ran;
-  char *pp="M0ng00se";
-  /* These octets are automatically protected against buffer overflow attacks */
-  /* Note salt must be big enough to include an appended word */
-  /* Note ECIES ciphertext C must be big enough to include at least 1 appended block */
-  /* Recall EFS is field size in bytes. So EFS=32 for 256-bit curve */
-  char s0[EGS],s1[EGS],w0[2*EFS+1],w1[2*EFS+1],z0[EFS],z1[EFS],raw[100],key[EAS],salt[32],pw[20],p1[30],p2[30],v[2*EFS+1],m[32],c[64],t[32],cs[EGS],ds[EGS];
-  octet S0={0,sizeof(s0),s0};
-  octet S1={0,sizeof(s1),s1};
-  octet W0={0,sizeof(w0),w0};
-  octet W1={0,sizeof(w1),w1};
-  octet Z0={0,sizeof(z0),z0};
-  octet Z1={0,sizeof(z1),z1};
-  octet RAW={0,sizeof(raw),raw};
-  octet KEY={0,sizeof(key),key};
-  octet SALT={0,sizeof(salt),salt};
-  octet PW={0,sizeof(pw),pw};
-  octet P1={0,sizeof(p1),p1};
-  octet P2={0,sizeof(p2),p2};
-  octet V={0,sizeof(v),v};
-  octet M={0,sizeof(m),m};
-  octet C={0,sizeof(c),c};
-  octet T={0,sizeof(t),t};
-  octet CS={0,sizeof(cs),cs};
-  octet DS={0,sizeof(ds),ds};
-
-  /* Crypto Strong RNG */
-  csprng RNG;
-  time((time_t *)&ran);
-  /* fake random seed source */
-  RAW.len=100;
-  RAW.val[0]=ran;
-  RAW.val[1]=ran>>8;
-  RAW.val[2]=ran>>16;
-  RAW.val[3]=ran>>24;
-  for (i=0;i<100;i++) RAW.val[i]=i;
-  /* initialise strong RNG */
-  ECP_CREATE_CSPRNG(&RNG,&RAW);
-
-  SALT.len=8;
-  for (i=0;i<8;i++) SALT.val[i]=i+1;  // set Salt
-
-  printf("Alice's Passphrase= %s\n",pp);
-
-  OCT_empty(&PW);
-  OCT_jstring(&PW,pp);   // set Password from string
-
-  /* private key S0 of size EGS bytes derived from Password and Salt */
-  ECP_PBKDF2(&PW,&SALT,1000,EGS,&S0);
-  printf("Alices private key= 0x"); OCT_output(&S0);
-
-  /* Generate Key pair S/W */
-  ECP_KEY_PAIR_GENERATE(NULL,&S0,&W0);
-
-  res=ECP_PUBLIC_KEY_VALIDATE(1,&W0);
-  if (res!=0)
-  {
-    printf("ECP Public Key is invalid!\n");
-    return 1;
-  }
-
-  printf("Alice's public key= 0x");  OCT_output(&W0);
-
-  /* Random private key for other party */
-  ECP_KEY_PAIR_GENERATE(&RNG,&S1,&W1);
-  res=ECP_PUBLIC_KEY_VALIDATE(1,&W1);
-  if (res!=0)
-  {
-    printf("ECP Public Key is invalid!\n");
-    return 1;
-  }
-  printf("Servers private key= 0x");  OCT_output(&S1);
-  printf("Servers public key= 0x");   OCT_output(&W1);
-
-  /* Calculate common key using DH - IEEE 1363 method */
-  ECP_SVDP_DH(&S0,&W1,&Z0);
-  ECP_SVDP_DH(&S1,&W0,&Z1);
-
-  if (!OCT_comp(&Z0,&Z1))
-  {
-    printf("*** ECPSVDP-DH Failed\n");
-    return 0;
-  }
-
-  ECP_KDF2(&Z0,NULL,EAS,&KEY);
-
-  printf("Alice's DH Key=  0x"); OCT_output(&KEY);
-  printf("Servers DH Key=  0x"); OCT_output(&KEY);
-
-  printf("Testing ECIES\n");
-
-  P1.len=3; P1.val[0]=0x0; P1.val[1]=0x1; P1.val[2]=0x2;
-  P2.len=4; P2.val[0]=0x0; P2.val[1]=0x1; P2.val[2]=0x2; P2.val[3]=0x3;
-
-  M.len=17;
-  for (i=0;i<=16;i++) M.val[i]=i;
-
-  ECP_ECIES_ENCRYPT(&P1,&P2,&RNG,&W1,&M,12,&V,&C,&T);
-
-  printf("Ciphertext= \n");
-  printf("V= 0x"); OCT_output(&V);
-  printf("C= 0x"); OCT_output(&C);
-  printf("T= 0x"); OCT_output(&T);
-
-  if (!ECP_ECIES_DECRYPT(&P1,&P2,&V,&C,&T,&S1,&M))
-  {
-    printf("*** ECIES Decryption Failed\n");
-    return 1;
-  }
-  else printf("Decryption succeeded\n");
-
-  printf("Message is 0x"); OCT_output(&M);
-
-  printf("Testing ECDSA\n");
-
-  if (ECP_SP_DSA(&RNG,&S0,&M,&CS,&DS)!=0)
-  {
-    printf("***ECDSA Signature Failed\n");
-    return 1;
-  }
-
-  printf("Signature C = 0x"); OCT_output(&CS);
-  printf("Signature D = 0x"); OCT_output(&DS);
-
-  if (ECP_VP_DSA(&W0,&M,&CS,&DS)!=0)
-  {
-    printf("***ECDSA Verification Failed\n");
-    return 1;
-  }
-  else printf("ECDSA Signature/Verification succeeded %d\n",j);
-
-  ECP_KILL_CSPRNG(&RNG);
-
-  printf("SUCCESS\n");
-  return 0;
-}
-
diff --git a/c/tests/test_ecm.c b/c/tests/test_ecm.c
deleted file mode 100755
index c96e4ab..0000000
--- a/c/tests/test_ecm.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
-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.
-*/
-
-/* test driver and function exerciser for ECDH API Functions only - suitable for testing Montgomery curves */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include "ecdh.h"
-
-int main()
-{
-  int i,j=0,res;
-  int result;
-  unsigned long ran;
-  char *pp="M0ng00se";
-  /* These octets are automatically protected against buffer overflow attacks */
-  /* Note salt must be big enough to include an appended word */
-  /* Note ECIES ciphertext C must be big enough to include at least 1 appended block */
-  /* Recall EFS is field size in bytes. So EFS=32 for 256-bit curve */
-  char s0[EGS],s1[EGS],w0[2*EFS+1],w1[2*EFS+1],z0[EFS],z1[EFS],raw[100],key[EAS],salt[32],pw[20];
-  octet S0={0,sizeof(s0),s0};
-  octet S1={0,sizeof(s1),s1};
-  octet W0={0,sizeof(w0),w0};
-  octet W1={0,sizeof(w1),w1};
-  octet Z0={0,sizeof(z0),z0};
-  octet Z1={0,sizeof(z1),z1};
-  octet RAW={0,sizeof(raw),raw};
-  octet KEY={0,sizeof(key),key};
-  octet SALT={0,sizeof(salt),salt};
-  octet PW={0,sizeof(pw),pw};
-
-  /* Crypto Strong RNG */
-  csprng RNG;
-  time((time_t *)&ran);
-  /* fake random seed source */
-  RAW.len=100;
-  RAW.val[0]=ran;
-  RAW.val[1]=ran>>8;
-  RAW.val[2]=ran>>16;
-  RAW.val[3]=ran>>24;
-  for (i=4;i<100;i++) RAW.val[i]=i;
-
-  ECP_CREATE_CSPRNG(&RNG,&RAW);   /* initialise strong RNG */
-
-  SALT.len=8;
-  for (i=0;i<8;i++) SALT.val[i]=i+1;  // set Salt
-
-  printf("Alice's Passphrase= %s\n",pp);
-
-  OCT_clear(&PW);
-  OCT_jstring(&PW,pp);   // set Password from string
-
-  /* private key S0 of size EGS bytes derived from Password and Salt */
-  ECP_PBKDF2(&PW,&SALT,1000,EGS,&S0);
-  printf("Alices private key= 0x"); OCT_output(&S0);
-
-  /* Generate Key pair S/W */
-  ECP_KEY_PAIR_GENERATE(NULL,&S0,&W0);
-
-  res=ECP_PUBLIC_KEY_VALIDATE(1,&W0);
-  if (res!=0)
-  {
-    printf("Alice's ECP Public Key is invalid!\n");
-    return 1;
-  }
-
-  printf("Alice's public key= 0x");  OCT_output(&W0);
-
-  /* Random private key for other party */
-  ECP_KEY_PAIR_GENERATE(&RNG,&S1,&W1);
-  printf("Servers private key= 0x");  OCT_output(&S1);
-  printf("Servers public key= 0x");   OCT_output(&W1);
-
-  res=ECP_PUBLIC_KEY_VALIDATE(1,&W1);
-  if (res!=0)
-  {
-    printf("Server's ECP Public Key is invalid!\n");
-    return 1;
-  }
-
-  /* Calculate common key using DH - IEEE 1363 method */
-
-  ECP_SVDP_DH(&S0,&W1,&Z0);
-  ECP_SVDP_DH(&S1,&W0,&Z1);
-
-  if (!OCT_comp(&Z0,&Z1))
-  {
-    printf("*** ECPSVDP-DH Failed\n");
-    return 1;
-  }
-
-  ECP_KDF2(&Z0,NULL,EAS,&KEY);
-
-  printf("Alice's DH Key=  0x"); OCT_output(&KEY);
-  printf("Servers DH Key=  0x"); OCT_output(&KEY);
-
-  printf("SUCCESS\n");
-  return 0;
-}
-
diff --git a/c/tests/test_mpin.c b/c/tests/test_mpin.c
deleted file mode 100755
index b747fc9..0000000
--- a/c/tests/test_mpin.c
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
-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.
-*/
-
-/* Test good token and correct PIN with D-TA. Single pass */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include "mpin.h"
-
-int main()
-{
-  int i,PIN1,PIN2,rtn,err;
-
-  char id[256];
-  octet ID = {0,sizeof(id),id};
-
-  char x[PGS],y1[PGS],y2[PGS];
-  octet X={sizeof(x), sizeof(x),x};
-  octet Y1={sizeof(y1),sizeof(y1),y1};
-  octet Y2={sizeof(y2),sizeof(y2),y2};
-
-  /* Master secret shares */
-  char ms1[PGS], ms2[PGS];
-  octet MS1={sizeof(ms1),sizeof(ms1),ms1};
-  octet MS2={sizeof(ms2),sizeof(ms2),ms2};
-
-  /* Hash values of Client ID */
-  char hcid[32];
-  octet HCID={sizeof(hcid),sizeof(hcid), hcid};
-
-  /* Client secret and shares */
-  char cs1[2*PFS+1], cs2[2*PFS+1], sec[2*PFS+1];
-  octet SEC={sizeof(sec),sizeof(sec),sec};
-  octet CS1={sizeof(cs1),sizeof(cs1), cs1};
-  octet CS2={sizeof(cs2),sizeof(cs2), cs2};
-
-  /* Server secret and shares */
-  char ss1[4*PFS], ss2[4*PFS], serverSecret[4*PFS];
-  octet ServerSecret={sizeof(serverSecret),sizeof(serverSecret),serverSecret};
-  octet SS1={sizeof(ss1),sizeof(ss1),ss1};
-  octet SS2={sizeof(ss2),sizeof(ss2),ss2};
-
-  /* Time Permit and shares */
-  char tp1[2*PFS+1], tp2[2*PFS+1], tp[2*PFS+1];
-  octet TP={sizeof(tp),sizeof(tp),tp};
-  octet TP1={sizeof(tp1),sizeof(tp1),tp1};
-  octet TP2={sizeof(tp2),sizeof(tp2),tp2};
-
-  /* Token stored on computer */
-  char token[2*PFS+1];
-  octet TOKEN={sizeof(token),sizeof(token),token};
-
-  char ut[2*PFS+1],u[2*PFS+1];
-  octet UT={sizeof(ut),sizeof(ut),ut};
-  octet U={sizeof(u),sizeof(u),u};
-
-  char hid[2*PFS+1],htid[2*PFS+1];
-  octet HID={0,sizeof(hid),hid};
-  octet HTID={0,sizeof(htid),htid};
-
-  char e[12*PFS], f[12*PFS];
-  octet E={sizeof(e),sizeof(e),e};
-  octet F={sizeof(f),sizeof(f),f};
-
-  int TimeValue = 0;
-
-  PIN1 = 1234;
-  PIN2 = 1234;
-
-  /* Assign the End-User an ID */
-  char* user = "testuser@miracl.com";
-  OCT_jstring(&ID,user);
-  printf("CLIENT: ID %s\n", user);
-
-  int date = 0;
-  char seed[100] = {0};
-  octet SEED = {0,sizeof(seed),seed};
-  csprng RNG;
-
-  /* unrandom seed value! */
-  SEED.len=100;
-  for (i=0;i<100;i++) SEED.val[i]=i+1;
-
-  /* initialise random number generator */
-  MPIN_CREATE_CSPRNG(&RNG,&SEED);
-
-  /* Hash ID */
-  MPIN_HASH_ID(&ID,&HCID);
-  OCT_output(&HCID);
-
-  /* When set only send hashed IDs to server */
-  octet *pID;
-#ifdef USE_ANONYMOUS
-  pID = &HCID;
-#else
-  pID = &ID;
-#endif
-
-  /* Generate Client master secret for MIRACL and Customer */
-  rtn = MPIN_RANDOM_GENERATE(&RNG,&MS1);
-  if (rtn != 0) {
-      printf("MPIN_RANDOM_GENERATE(&RNG,&MS1) Error %d\n", rtn);
-      return 1;
-  }
-  rtn = MPIN_RANDOM_GENERATE(&RNG,&MS2);
-  if (rtn != 0) {
-      printf("MPIN_RANDOM_GENERATE(&RNG,&MS2) Error %d\n", rtn);
-      return 1;
-  }
-  printf("MASTER SECRET MIRACL:= 0x");
-  OCT_output(&MS1);
-  printf("MASTER SECRET CUSTOMER:= 0x");
-  OCT_output(&MS2);
-
-  /* Generate server secret shares */
-  rtn = MPIN_GET_SERVER_SECRET(&MS1,&SS1);
-  if (rtn != 0) {
-      printf("MPIN_GET_SERVER_SECRET(&MS1,&SS1) Error %d\n", rtn);
-      return 1;
-  }
-  rtn = MPIN_GET_SERVER_SECRET(&MS2,&SS2);
-  if (rtn != 0) {
-      printf("MPIN_GET_SERVER_SECRET(&MS2,&SS2) Error %d\n", rtn);
-      return 1;
-  }
-  printf("SS1 = 0x");
-  OCT_output(&SS1);
-  printf("SS2 = 0x");
-  OCT_output(&SS2);
-
-  /* Combine server secret share */
-  rtn = MPIN_RECOMBINE_G2(&SS1, &SS2, &ServerSecret);
-  if (rtn != 0) {
-      printf("MPIN_RECOMBINE_G2(&SS1, &SS2, &ServerSecret) Error %d\n", rtn);
-      return 1;
-  }
-  printf("ServerSecret = 0x");
-  OCT_output(&ServerSecret);
-
-  /* Generate client secret shares */
-  rtn = MPIN_GET_CLIENT_SECRET(&MS1,&HCID,&CS1);
-  if (rtn != 0) {
-      printf("MPIN_GET_CLIENT_SECRET(&MS1,&HCID,&CS1) Error %d\n", rtn);
-      return 1;
-  }
-  rtn = MPIN_GET_CLIENT_SECRET(&MS2,&HCID,&CS2);
-  if (rtn != 0) {
-      printf("MPIN_GET_CLIENT_SECRET(&MS2,&HCID,&CS2) Error %d\n", rtn);
-      return 1;
-  }
-  printf("CS1 = 0x");
-  OCT_output(&CS1);
-  printf("CS2 = 0x");
-  OCT_output(&CS2);
-
-  /* Combine client secret shares : TOKEN is the full client secret */
-  rtn = MPIN_RECOMBINE_G1(&CS1, &CS2, &TOKEN);
-  if (rtn != 0) {
-      printf("MPIN_RECOMBINE_G1(&CS1, &CS2, &TOKEN) Error %d\n", rtn);
-      return 1;
-  }
-  printf("Client Secret = 0x");
-  OCT_output(&TOKEN);
-
-  /* Generate Time Permit shares */
-  date = MPIN_today();
-  printf("Date %d \n", date);
-  rtn = MPIN_GET_CLIENT_PERMIT(date,&MS1,&HCID,&TP1);
-  if (rtn != 0) {
-      printf("MPIN_GET_CLIENT_PERMIT(date,&MS1,&HCID,&TP1) Error %d\n", rtn);
-      return 1;
-  }
-  rtn = MPIN_GET_CLIENT_PERMIT(date,&MS2,&HCID,&TP2);
-  if (rtn != 0) {
-      printf("MPIN_GET_CLIENT_PERMIT(date,&MS2,&HCID,&TP2) Error %d\n", rtn);
-      return 1;
-  }
-  printf("TP1 = 0x");
-  OCT_output(&TP1);
-  printf("TP2 = 0x");
-  OCT_output(&TP2);
-
-  /* Combine Time Permit shares */
-  rtn = MPIN_RECOMBINE_G1(&TP1, &TP2, &TP);
-  if (rtn != 0) {
-      printf("MPIN_RECOMBINE_G1(&TP1, &TP2, &TP) Error %d\n", rtn);
-      return 1;
-  }
-  printf("Time Permit = 0x");
-  OCT_output(&TP);
-
-  /* Client extracts PIN1 from secret to create Token */
-  rtn = MPIN_EXTRACT_PIN(&ID, PIN1, &TOKEN);
-  if (rtn != 0) {
-      printf("MPIN_EXTRACT_PIN( &ID, PIN, &TOKEN) Error %d\n", rtn);
-      return 1;
-  }
-  printf("Token = 0x");
-  OCT_output(&TOKEN);
-
-  /* Single pass MPIN protocol */
-  /* Client  */
-  TimeValue = MPIN_GET_TIME();
-  printf("TimeValue %d \n", TimeValue);
-  rtn = MPIN_CLIENT(date,&ID,&RNG,&X,PIN2,&TOKEN,&SEC,NULL,&UT,&TP,NULL,TimeValue,&Y1);
-  if (rtn != 0) {
-      printf("MPIN_CLIENT ERROR %d\n", rtn);
-      return 1;
-  }
-  printf("Y1 = 0x");
-  OCT_output(&Y1);
-  printf("V = 0x");
-  OCT_output(&SEC);
-
-  /* Server  */
-  rtn = MPIN_SERVER(date,NULL,&HTID,&Y2,&ServerSecret,NULL,&UT,&SEC,&E,&F,pID,NULL,TimeValue);
-  printf("Y2 = 0x");
-  OCT_output(&Y2);
-  if (rtn != 0) {
-    printf("FAILURE Invalid Token Error Code %d\n", rtn);
-  } else {
-    printf("SUCCESS Error Code %d\n", rtn);
-  }
-  return 0;
-}
diff --git a/c/tests/test_mpin_bad_pin.c b/c/tests/test_mpin_bad_pin.c
deleted file mode 100755
index 454cbfc..0000000
--- a/c/tests/test_mpin_bad_pin.c
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
-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.
-*/
-
-/* Test good token and incorrect PIN with D-TA */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include "mpin.h"
-
-int main()
-{
-  int i,PIN1,PIN2,rtn,err;
-
-  char id[256];
-  octet ID = {0,sizeof(id),id};
-
-  char x[PGS],y[PGS];
-  octet X={sizeof(x), sizeof(x),x};
-  octet Y={sizeof(y),sizeof(y),y};
-
-  /* Master secret shares */
-  char ms1[PGS], ms2[PGS];
-  octet MS1={sizeof(ms1),sizeof(ms1),ms1};
-  octet MS2={sizeof(ms2),sizeof(ms2),ms2};
-
-  /* Hash values of ID */
-  char hcid[32];
-  octet HCID={sizeof(hcid),sizeof(hcid), hcid};
-
-  /* Client secret and shares */
-  char cs1[2*PFS+1], cs2[2*PFS+1], sec[2*PFS+1];
-  octet SEC={sizeof(sec),sizeof(sec),sec};
-  octet CS1={sizeof(cs1),sizeof(cs1), cs1};
-  octet CS2={sizeof(cs2),sizeof(cs2), cs2};
-
-  /* Server secret and shares */
-  char ss1[4*PFS], ss2[4*PFS], serverSecret[4*PFS];
-  octet ServerSecret={sizeof(serverSecret),sizeof(serverSecret),serverSecret};
-  octet SS1={sizeof(ss1),sizeof(ss1),ss1};
-  octet SS2={sizeof(ss2),sizeof(ss2),ss2};
-
-  /* Time Permit and shares */
-  char tp1[2*PFS+1], tp2[2*PFS+1], tp[2*PFS+1];
-  octet TP={sizeof(tp),sizeof(tp),tp};
-  octet TP1={sizeof(tp1),sizeof(tp1),tp1};
-  octet TP2={sizeof(tp2),sizeof(tp2),tp2};
-
-  /* Token stored on computer */
-  char token[2*PFS+1];
-  octet TOKEN={sizeof(token),sizeof(token),token};
-
-  char ut[2*PFS+1],u[2*PFS+1];
-  octet UT={sizeof(ut),sizeof(ut),ut};
-  octet U={sizeof(u),sizeof(u),u};
-
-  char hid[2*PFS+1],htid[2*PFS+1];
-  octet HID={0,sizeof(hid),hid};
-  octet HTID={0,sizeof(htid),htid};
-
-  char e[12*PFS], f[12*PFS];
-  octet E={sizeof(e),sizeof(e),e};
-  octet F={sizeof(f),sizeof(f),f};
-
-  PIN1 = 1234;
-  PIN2 = 1237;
-
-  /* Assign the End-User an ID */
-  char* user = "testuser@miracl.com";
-  OCT_jstring(&ID,user);
-  printf("CLIENT: ID %s\n", user);
-
-  int date = 16512;
-  char seed[100] = {0};
-  octet SEED = {0,sizeof(seed),seed};
-  csprng RNG;
-
-  /* unrandom seed value! */
-  SEED.len=100;
-  for (i=0;i<100;i++) SEED.val[i]=i+1;
-
-  /* initialise random number generator */
-  MPIN_CREATE_CSPRNG(&RNG,&SEED);
-
-  /* Hash ID */
-  MPIN_HASH_ID(&ID,&HCID);
-  OCT_output(&HCID);
-
-  /* When set only send hashed IDs to server */
-  octet *pID;
-#ifdef USE_ANONYMOUS
-  pID = &HCID;
-#else
-  pID = &ID;
-#endif
-
-  /* Generate Client master secret for MIRACL and Customer */
-  rtn = MPIN_RANDOM_GENERATE(&RNG,&MS1);
-  if (rtn != 0) {
-      printf("MPIN_RANDOM_GENERATE(&RNG,&MS1) Error %d\n", rtn);
-      return 1;
-  }
-  rtn = MPIN_RANDOM_GENERATE(&RNG,&MS2);
-  if (rtn != 0) {
-      printf("MPIN_RANDOM_GENERATE(&RNG,&MS2) Error %d\n", rtn);
-      return 1;
-  }
-  printf("MASTER SECRET MIRACL:= 0x");
-  OCT_output(&MS1);
-  printf("MASTER SECRET CUSTOMER:= 0x");
-  OCT_output(&MS2);
-
-  /* Generate server secret shares */
-  rtn = MPIN_GET_SERVER_SECRET(&MS1,&SS1);
-  if (rtn != 0) {
-      printf("MPIN_GET_SERVER_SECRET(&MS1,&SS1) Error %d\n", rtn);
-      return 1;
-  }
-  rtn = MPIN_GET_SERVER_SECRET(&MS2,&SS2);
-  if (rtn != 0) {
-      printf("MPIN_GET_SERVER_SECRET(&MS2,&SS2) Error %d\n", rtn);
-      return 1;
-  }
-  printf("SS1 = 0x");
-  OCT_output(&SS1);
-  printf("SS2 = 0x");
-  OCT_output(&SS2);
-
-  /* Combine server secret share */
-  rtn = MPIN_RECOMBINE_G2(&SS1, &SS2, &ServerSecret);
-  if (rtn != 0) {
-      printf("MPIN_RECOMBINE_G2(&SS1, &SS2, &ServerSecret) Error %d\n", rtn);
-      return 1;
-  }
-  printf("ServerSecret = 0x");
-  OCT_output(&ServerSecret);
-
-  /* Generate client secret shares */
-  rtn = MPIN_GET_CLIENT_SECRET(&MS1,&HCID,&CS1);
-  if (rtn != 0) {
-      printf("MPIN_GET_CLIENT_SECRET(&MS1,&HCID,&CS1) Error %d\n", rtn);
-      return 1;
-  }
-  rtn = MPIN_GET_CLIENT_SECRET(&MS2,&HCID,&CS2);
-  if (rtn != 0) {
-      printf("MPIN_GET_CLIENT_SECRET(&MS2,&HCID,&CS2) Error %d\n", rtn);
-      return 1;
-  }
-  printf("CS1 = 0x");
-  OCT_output(&CS1);
-  printf("CS2 = 0x");
-  OCT_output(&CS2);
-
-  /* Combine client secret shares : TOKEN is the full client secret */
-  rtn = MPIN_RECOMBINE_G1(&CS1, &CS2, &TOKEN);
-  if (rtn != 0) {
-      printf("MPIN_RECOMBINE_G1(&CS1, &CS2, &TOKEN) Error %d\n", rtn);
-      return 1;
-  }
-  printf("Client Secret = 0x");
-  OCT_output(&TOKEN);
-
-  /* Generate Time Permit shares */
-  printf("Date %d \n", date);
-  rtn = MPIN_GET_CLIENT_PERMIT(date,&MS1,&HCID,&TP1);
-  if (rtn != 0) {
-      printf("MPIN_GET_CLIENT_PERMIT(date,&MS1,&HCID,&TP1) Error %d\n", rtn);
-      return 1;
-  }
-  rtn = MPIN_GET_CLIENT_PERMIT(date,&MS2,&HCID,&TP2);
-  if (rtn != 0) {
-      printf("MPIN_GET_CLIENT_PERMIT(date,&MS2,&HCID,&TP2) Error %d\n", rtn);
-      return 1;
-  }
-  printf("TP1 = 0x");
-  OCT_output(&TP1);
-  printf("TP2 = 0x");
-  OCT_output(&TP2);
-
-  /* Combine Time Permit shares */
-  rtn = MPIN_RECOMBINE_G1(&TP1, &TP2, &TP);
-  if (rtn != 0) {
-      printf("MPIN_RECOMBINE_G1(&TP1, &TP2, &TP) Error %d\n", rtn);
-      return 1;
-  }
-  printf("Time Permit = 0x");
-  OCT_output(&TP);
-
-  /* Client extracts PIN1 from secret to create Token */
-  rtn = MPIN_EXTRACT_PIN(&ID, PIN1, &TOKEN);
-  if (rtn != 0) {
-      printf("MPIN_EXTRACT_PIN(&ID, PIN, &TOKEN) Error %d\n", rtn);
-      return 1;
-  }
-  printf("Token = 0x");
-  OCT_output(&TOKEN);
-
-  /* Client first pass */
-  rtn = MPIN_CLIENT_1(date,&ID,&RNG,&X,PIN2,&TOKEN,&SEC,&U,&UT,&TP);
-  if (rtn != 0) {
-      printf("MPIN_CLIENT_1 ERROR %d\n", rtn);
-      return 1;
-  }
-
-  /* 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. */
-  MPIN_SERVER_1(date,pID,&HID,&HTID);
-
-  /* Server generates Random number Y and sends it to Client */
-  rtn = MPIN_RANDOM_GENERATE(&RNG,&Y);
-  if (rtn != 0) {
-      printf("MPIN_RANDOM_GENERATE(&RNG,&Y) Error %d\n", rtn);
-      return 1;
-  }
-  printf("Y = 0x");
-  OCT_output(&Y);
-
-  /* Client second pass */
-  rtn = MPIN_CLIENT_2(&X,&Y,&SEC);
-  if (rtn != 0) {
-    printf("MPIN_CLIENT_2(&X,&Y,&SEC) Error %d\n", rtn);
-  }
-  printf("V = 0x");
-  OCT_output(&SEC);
-
-  /* Server second pass */
-  rtn = MPIN_SERVER_2(date,&HID,&HTID,&Y,&ServerSecret,&U,&UT,&SEC,&E,&F);
-  if (rtn != 0) {
-      err=MPIN_KANGAROO(&E,&F);
-      if (err)
-        printf("FAILURE PIN Error %d, Error Code %d\n",err, rtn);
-      else
-        printf("FAILURE Invalid Token Error Code %d\n", rtn);
-  } else {
-      printf("SUCCESS Error Code %d\n", rtn); 
-      OCT_output_string(&ID); 
-      printf("\n");
-  }
-  return 0;
-}
diff --git a/c/tests/test_mpin_bad_token.c b/c/tests/test_mpin_bad_token.c
deleted file mode 100755
index 61e4838..0000000
--- a/c/tests/test_mpin_bad_token.c
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
-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.
-*/
-
-/* Test bad token and correct PIN with D-TA */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include "mpin.h"
-
-int main()
-{
-  int i,PIN1,PIN2,rtn,err;
-
-  char id[256];
-  octet ID = {0,sizeof(id),id};
-
-  char x[PGS],y[PGS];
-  octet X={sizeof(x), sizeof(x),x};
-  octet Y={sizeof(y),sizeof(y),y};
-
-  /* Master secret shares */
-  char ms1[PGS], ms2[PGS];
-  octet MS1={sizeof(ms1),sizeof(ms1),ms1};
-  octet MS2={sizeof(ms2),sizeof(ms2),ms2};
-
-  /* Hash values of ID */
-  char hcid[32];
-  octet HCID={sizeof(hcid),sizeof(hcid), hcid};
-
-  /* Client secret and shares */
-  char cs1[2*PFS+1], cs2[2*PFS+1], sec[2*PFS+1];
-  octet SEC={sizeof(sec),sizeof(sec),sec};
-  octet CS1={sizeof(cs1),sizeof(cs1), cs1};
-  octet CS2={sizeof(cs2),sizeof(cs2), cs2};
-
-  /* Server secret and shares */
-  char ss1[4*PFS], ss2[4*PFS], serverSecret[4*PFS];
-  octet ServerSecret={sizeof(serverSecret),sizeof(serverSecret),serverSecret};
-  octet SS1={sizeof(ss1),sizeof(ss1),ss1};
-  octet SS2={sizeof(ss2),sizeof(ss2),ss2};
-
-  /* Time Permit and shares */
-  char tp1[2*PFS+1], tp2[2*PFS+1], tp[2*PFS+1];
-  octet TP={sizeof(tp),sizeof(tp),tp};
-  octet TP1={sizeof(tp1),sizeof(tp1),tp1};
-  octet TP2={sizeof(tp2),sizeof(tp2),tp2};
-
-  /* Token stored on computer */
-  char token[2*PFS+1];
-  octet TOKEN={sizeof(token),sizeof(token),token};
-
-  char ut[2*PFS+1],u[2*PFS+1];
-  octet UT={sizeof(ut),sizeof(ut),ut};
-  octet U={sizeof(u),sizeof(u),u};
-
-  char hid[2*PFS+1],htid[2*PFS+1];
-  octet HID={0,sizeof(hid),hid};
-  octet HTID={0,sizeof(htid),htid};
-
-  char e[12*PFS], f[12*PFS];
-  octet E={sizeof(e),sizeof(e),e};
-  octet F={sizeof(f),sizeof(f),f};
-
-  PIN1 = 1234;
-  PIN2 = 1234;
-
-  /* Assign the End-User an ID */
-  char* user = "testuser@miracl.com";
-  OCT_jstring(&ID,user);
-  printf("CLIENT: ID %s\n", user);
-
-  int date = 0;
-  char seed[100] = {0};
-  octet SEED = {0,sizeof(seed),seed};
-  csprng RNG;
-
-  /* unrandom seed value! */
-  SEED.len=100;
-  for (i=0;i<100;i++) SEED.val[i]=i+1;
-
-  /* initialise random number generator */
-  MPIN_CREATE_CSPRNG(&RNG,&SEED);
-
-  /* Hash ID */
-  MPIN_HASH_ID(&ID,&HCID);
-  OCT_output(&HCID);
-
-  /* When set only send hashed IDs to server */
-  octet *pID;
-#ifdef USE_ANONYMOUS
-  pID = &HCID;
-#else
-  pID = &ID;
-#endif
-
-  /* Generate Client master secret for MIRACL and Customer */
-  rtn = MPIN_RANDOM_GENERATE(&RNG,&MS1);
-  if (rtn != 0) {
-      printf("MPIN_RANDOM_GENERATE(&RNG,&MS1) Error %d\n", rtn);
-      return 1;
-  }
-  rtn = MPIN_RANDOM_GENERATE(&RNG,&MS2);
-  if (rtn != 0) {
-      printf("MPIN_RANDOM_GENERATE(&RNG,&MS2) Error %d\n", rtn);
-      return 1;
-  }
-  printf("MASTER SECRET MIRACL:= 0x");
-  OCT_output(&MS1);
-  printf("MASTER SECRET CUSTOMER:= 0x");
-  OCT_output(&MS2);
-
-  /* Generate server secret shares */
-  rtn = MPIN_GET_SERVER_SECRET(&MS1,&SS1);
-  if (rtn != 0) {
-      printf("MPIN_GET_SERVER_SECRET(&MS1,&SS1) Error %d\n", rtn);
-      return 1;
-  }
-  rtn = MPIN_GET_SERVER_SECRET(&MS2,&SS2);
-  if (rtn != 0) {
-      printf("MPIN_GET_SERVER_SECRET(&MS2,&SS2) Error %d\n", rtn);
-      return 1;
-  }
-  printf("SS1 = 0x");
-  OCT_output(&SS1);
-  printf("SS2 = 0x");
-  OCT_output(&SS2);
-
-  /* Combine server secret share */
-  rtn = MPIN_RECOMBINE_G2(&SS1, &SS2, &ServerSecret);
-  if (rtn != 0) {
-      printf("MPIN_RECOMBINE_G2(&SS1, &SS2, &ServerSecret) Error %d\n", rtn);
-      return 1;
-  }
-  printf("ServerSecret = 0x");
-  OCT_output(&ServerSecret);
-
-  /* Generate client secret shares */
-  rtn = MPIN_GET_CLIENT_SECRET(&MS1,&HCID,&CS1);
-  if (rtn != 0) {
-      printf("MPIN_GET_CLIENT_SECRET(&MS1,&HCID,&CS1) Error %d\n", rtn);
-      return 1;
-  }
-  rtn = MPIN_GET_CLIENT_SECRET(&MS2,&HCID,&CS2);
-  if (rtn != 0) {
-      printf("MPIN_GET_CLIENT_SECRET(&MS2,&HCID,&CS2) Error %d\n", rtn);
-      return 1;
-  }
-  printf("CS1 = 0x");
-  OCT_output(&CS1);
-  printf("CS2 = 0x");
-  OCT_output(&CS2);
-
-  /* Combine client secret shares : TOKEN is the full client secret */
-  rtn = MPIN_RECOMBINE_G1(&CS1, &CS2, &TOKEN);
-  if (rtn != 0) {
-      printf("MPIN_RECOMBINE_G1(&CS1, &CS2, &TOKEN) Error %d\n", rtn);
-      return 1;
-  }
-  printf("Client Secret = 0x");
-  OCT_output(&TOKEN);
-
-  /* Generate Time Permit shares */
-  date = MPIN_today();
-  printf("Date %d \n", date);
-  rtn = MPIN_GET_CLIENT_PERMIT(date,&MS1,&HCID,&TP1);
-  if (rtn != 0) {
-      printf("MPIN_GET_CLIENT_PERMIT(date,&MS1,&HCID,&TP1) Error %d\n", rtn);
-      return 1;
-  }
-  rtn = MPIN_GET_CLIENT_PERMIT(date,&MS2,&HCID,&TP2);
-  if (rtn != 0) {
-      printf("MPIN_GET_CLIENT_PERMIT(date,&MS2,&HCID,&TP2) Error %d\n", rtn);
-      return 1;
-  }
-  printf("TP1 = 0x");
-  OCT_output(&TP1);
-  printf("TP2 = 0x");
-  OCT_output(&TP2);
-
-  /* Combine Time Permit shares */
-  rtn = MPIN_RECOMBINE_G1(&TP1, &TP2, &TP);
-  if (rtn != 0) {
-      printf("MPIN_RECOMBINE_G1(&TP1, &TP2, &TP) Error %d\n", rtn);
-      return 1;
-  }
-  printf("Time Permit = 0x");
-  OCT_output(&TP);
-
-  /* Client extracts PIN1 from secret to create Token */
-  rtn = MPIN_EXTRACT_PIN(&ID, PIN1, &TOKEN);
-  if (rtn != 0) {
-      printf("MPIN_EXTRACT_PIN(&ID, PIN, &TOKEN) Error %d\n", rtn);
-      return 1;
-  }
-  printf("Token = 0x");
-  OCT_output(&TOKEN);
-
-  /* Client first pass */
-  rtn = MPIN_CLIENT_1(date,&ID,&RNG,&X,PIN2,&TOKEN,&SEC,&U,&UT,&TP);
-  if (rtn != 0) {
-      printf("MPIN_CLIENT_1 ERROR %d\n", rtn);
-      return 1;
-  }
-
-  /* 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. */
-  MPIN_SERVER_1(date,pID,&HID,&HTID);
-
-  /* Server generates Random number Y and sends it to Client */
-  rtn = MPIN_RANDOM_GENERATE(&RNG,&Y);
-  if (rtn != 0) {
-      printf("MPIN_RANDOM_GENERATE(&RNG,&Y) Error %d\n", rtn);
-      return 1;
-  }
-  printf("Y = 0x");
-  OCT_output(&Y);
-
-  /* Client second pass */
-  rtn = MPIN_CLIENT_2(&X,&Y,&SEC);
-  if (rtn != 0) {
-    printf("MPIN_CLIENT_2(&X,&Y,&SEC) Error %d\n", rtn);
-  }
-  printf("V = 0x");
-  OCT_output(&SEC);
-
-  /* Server second pass */
-  /* Set SEC to UT to simulate a bad token */
-  rtn = MPIN_SERVER_2(date,&HID,&HTID,&Y,&ServerSecret,&U,&UT,&UT,&E,&F);
-  if (rtn != 0) {
-      err=MPIN_KANGAROO(&E,&F);
-      if (err==0) printf("FAILURE Invalid Token Error Code %d\n", rtn);
-      else printf("FAILURE PIN Error %d, Error Code %d\n",err, rtn);
-  } else {
-      printf("SUCCESS Error Code %d\n", rtn); 
-      OCT_output_string(&ID); printf("\n");
-  }
-  return 0;
-}
diff --git a/c/tests/test_mpin_expired_tp.c b/c/tests/test_mpin_expired_tp.c
deleted file mode 100755
index cb7f23e..0000000
--- a/c/tests/test_mpin_expired_tp.c
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
-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.
-*/
-
-/* Test good token and correct PIN with D-TA and expired time permit */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include "mpin.h"
-
-int main()
-{
-  int i,PIN1,PIN2,rtn,err;
-
-  char id[256];
-  octet ID = {0,sizeof(id),id};
-
-  char x[PGS],y[PGS];
-  octet X={sizeof(x), sizeof(x),x};
-  octet Y={sizeof(y),sizeof(y),y};
-
-  /* Master secret shares */
-  char ms1[PGS], ms2[PGS];
-  octet MS1={sizeof(ms1),sizeof(ms1),ms1};
-  octet MS2={sizeof(ms2),sizeof(ms2),ms2};
-
-  /* Hash values of ID */
-  char hcid[32];
-  octet HCID={sizeof(hcid),sizeof(hcid), hcid};
-
-  /* Client secret and shares */
-  char cs1[2*PFS+1], cs2[2*PFS+1], sec[2*PFS+1];
-  octet SEC={sizeof(sec),sizeof(sec),sec};
-  octet CS1={sizeof(cs1),sizeof(cs1), cs1};
-  octet CS2={sizeof(cs2),sizeof(cs2), cs2};
-
-  /* Server secret and shares */
-  char ss1[4*PFS], ss2[4*PFS], serverSecret[4*PFS];
-  octet ServerSecret={sizeof(serverSecret),sizeof(serverSecret),serverSecret};
-  octet SS1={sizeof(ss1),sizeof(ss1),ss1};
-  octet SS2={sizeof(ss2),sizeof(ss2),ss2};
-
-  /* Time Permit and shares */
-  char tp1[2*PFS+1], tp2[2*PFS+1], tp[2*PFS+1];
-  octet TP={sizeof(tp),sizeof(tp),tp};
-  octet TP1={sizeof(tp1),sizeof(tp1),tp1};
-  octet TP2={sizeof(tp2),sizeof(tp2),tp2};
-
-  /* Token stored on computer */
-  char token[2*PFS+1];
-  octet TOKEN={sizeof(token),sizeof(token),token};
-
-  char ut[2*PFS+1],u[2*PFS+1];
-  octet UT={sizeof(ut),sizeof(ut),ut};
-  octet U={sizeof(u),sizeof(u),u};
-
-  char hid[2*PFS+1],htid[2*PFS+1];
-  octet HID={0,sizeof(hid),hid};
-  octet HTID={0,sizeof(htid),htid};
-
-  char e[12*PFS], f[12*PFS];
-  octet E={sizeof(e),sizeof(e),e};
-  octet F={sizeof(f),sizeof(f),f};
-
-  PIN1 = 1234;
-  PIN2 = 1234;
-
-  /* Assign the End-User an ID */
-  char* user = "testuser@miracl.com";
-  OCT_jstring(&ID,user);
-  printf("CLIENT: ID %s\n", user);
-
-  int date = 0;
-  char seed[100] = {0};
-  octet SEED = {0,sizeof(seed),seed};
-  csprng RNG;
-
-  /* unrandom seed value! */
-  SEED.len = 100;
-  for (i=0;i<100;i++) SEED.val[i]=i+1;
-
-  /* initialise random number generator */
-  MPIN_CREATE_CSPRNG(&RNG,&SEED);
-
-  /* Hash ID */
-  MPIN_HASH_ID(&ID,&HCID);
-  OCT_output(&HCID);
-
-  /* When set only send hashed IDs to server */
-  octet *pID;
-#ifdef USE_ANONYMOUS
-  pID = &HCID;
-#else
-  pID = &ID;
-#endif
-
-  /* Generate Client master secret for MIRACL and Customer */
-  rtn = MPIN_RANDOM_GENERATE(&RNG,&MS1);
-  if (rtn != 0) {
-      printf("MPIN_RANDOM_GENERATE(&RNG,&MS1) Error %d\n", rtn);
-      return 1;
-  }
-  rtn = MPIN_RANDOM_GENERATE(&RNG,&MS2);
-  if (rtn != 0) {
-      printf("MPIN_RANDOM_GENERATE(&RNG,&MS2) Error %d\n", rtn);
-      return 1;
-  }
-  printf("MASTER SECRET MIRACL:= 0x");
-  OCT_output(&MS1);
-  printf("MASTER SECRET CUSTOMER:= 0x");
-  OCT_output(&MS2);
-
-  /* Generate server secret shares */
-  rtn = MPIN_GET_SERVER_SECRET(&MS1,&SS1);
-  if (rtn != 0) {
-      printf("MPIN_GET_SERVER_SECRET(&MS1,&SS1) Error %d\n", rtn);
-      return 1;
-  }
-  rtn = MPIN_GET_SERVER_SECRET(&MS2,&SS2);
-  if (rtn != 0) {
-      printf("MPIN_GET_SERVER_SECRET(&MS2,&SS2) Error %d\n", rtn);
-      return 1;
-  }
-  printf("SS1 = 0x");
-  OCT_output(&SS1);
-  printf("SS2 = 0x");
-  OCT_output(&SS2);
-
-  /* Combine server secret share */
-  rtn = MPIN_RECOMBINE_G2(&SS1, &SS2, &ServerSecret);
-  if (rtn != 0) {
-      printf("MPIN_RECOMBINE_G2(&SS1, &SS2, &ServerSecret) Error %d\n", rtn);
-      return 1;
-  }
-  printf("ServerSecret = 0x");
-  OCT_output(&ServerSecret);
-
-  /* Generate client secret shares */
-  rtn = MPIN_GET_CLIENT_SECRET(&MS1,&HCID,&CS1);
-  if (rtn != 0) {
-      printf("MPIN_GET_CLIENT_SECRET(&MS1,&HCID,&CS1) Error %d\n", rtn);
-      return 1;
-  }
-  rtn = MPIN_GET_CLIENT_SECRET(&MS2,&HCID,&CS2);
-  if (rtn != 0) {
-      printf("MPIN_GET_CLIENT_SECRET(&MS2,&HCID,&CS2) Error %d\n", rtn);
-      return 1;
-  }
-  printf("CS1 = 0x");
-  OCT_output(&CS1);
-  printf("CS2 = 0x");
-  OCT_output(&CS2);
-
-  /* Combine client secret shares : TOKEN is the full client secret */
-  rtn = MPIN_RECOMBINE_G1(&CS1, &CS2, &TOKEN);
-  if (rtn != 0) {
-      printf("MPIN_RECOMBINE_G1(&CS1, &CS2, &TOKEN) Error %d\n", rtn);
-      return 1;
-  }
-  printf("Client Secret = 0x");
-  OCT_output(&TOKEN);
-
-  /* Generate Time Permit shares */
-  date = MPIN_today();
-  printf("Date %d \n", date);
-  int yesterday = date -1;
-  rtn = MPIN_GET_CLIENT_PERMIT(yesterday,&MS1,&HCID,&TP1);
-  if (rtn != 0) {
-      printf("MPIN_GET_CLIENT_PERMIT(yesterday,&MS1,&HCID,&TP1) Error %d\n", rtn);
-      return 1;
-  }
-  rtn = MPIN_GET_CLIENT_PERMIT(yesterday,&MS2,&HCID,&TP2);
-  if (rtn != 0) {
-      printf("MPIN_GET_CLIENT_PERMIT(yesterday,&MS2,&HCID,&TP2) Error %d\n", rtn);
-      return 1;
-  }
-  printf("TP1 = 0x");
-  OCT_output(&TP1);
-  printf("TP2 = 0x");
-  OCT_output(&TP2);
-
-  /* Combine Time Permit shares */
-  rtn = MPIN_RECOMBINE_G1(&TP1, &TP2, &TP);
-  if (rtn != 0) {
-      printf("MPIN_RECOMBINE_G1(&TP1, &TP2, &TP) Error %d\n", rtn);
-      return 1;
-  }
-  printf("Time Permit = 0x");
-  OCT_output(&TP);
-
-  /* Client extracts PIN1 from secret to create Token */
-  rtn = MPIN_EXTRACT_PIN(&ID, PIN1, &TOKEN);
-  if (rtn != 0) {
-      printf("MPIN_EXTRACT_PIN(&ID, PIN, &TOKEN) Error %d\n", rtn);
-      return 1;
-  }
-  printf("Token = 0x");
-  OCT_output(&TOKEN);
-
-  /* Client first pass */
-  rtn = MPIN_CLIENT_1(date,&ID,&RNG,&X,PIN2,&TOKEN,&SEC,&U,&UT,&TP);
-  if (rtn != 0) {
-      printf("MPIN_CLIENT_1 ERROR %d\n", rtn);
-      return 1;
-  }
-
-  /* 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. */
-  MPIN_SERVER_1(date,pID,&HID,&HTID);
-
-  /* Server generates Random number Y and sends it to Client */
-  rtn = MPIN_RANDOM_GENERATE(&RNG,&Y);
-  if (rtn != 0) {
-      printf("MPIN_RANDOM_GENERATE(&RNG,&Y) Error %d\n", rtn);
-      return 1;
-  }
-  printf("Y = 0x");
-  OCT_output(&Y);
-
-  /* Client second pass */
-  rtn = MPIN_CLIENT_2(&X,&Y,&SEC);
-  if (rtn != 0) {
-    printf("MPIN_CLIENT_2(&X,&Y,&SEC) Error %d\n", rtn);
-  }
-  printf("V = 0x");
-  OCT_output(&SEC);
-
-  /* Server second pass */
-  rtn = MPIN_SERVER_2(date,&HID,&HTID,&Y,&ServerSecret,&U,&UT,&SEC,&E,&F);
-  if (rtn != 0) {
-      err=MPIN_KANGAROO(&E,&F);
-      if (err==0) printf("FAILURE Invalid Token Error Code %d\n", rtn);
-      else printf("FAILURE PIN Error %d, Error Code %d\n",err, rtn);
-  } else {
-      printf("SUCCESS Error Code %d\n", rtn); 
-      OCT_output_string(&ID); printf("\n");
-  }
-  return 0;
-}
diff --git a/c/tests/test_mpin_good.c b/c/tests/test_mpin_good.c
deleted file mode 100755
index d43de5e..0000000
--- a/c/tests/test_mpin_good.c
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
-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.
-*/
-
-/* Test good token and correct PIN with D-TA */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include "mpin.h"
-
-int main()
-{
-  int i,PIN1,PIN2,rtn,err;
-
-  char id[256];
-  octet ID = {0,sizeof(id),id};
-
-  char x[PGS],y[PGS];
-  octet X={sizeof(x), sizeof(x),x};
-  octet Y={sizeof(y),sizeof(y),y};
-
-  /* Master secret shares */
-  char ms1[PGS], ms2[PGS];
-  octet MS1={sizeof(ms1),sizeof(ms1),ms1};
-  octet MS2={sizeof(ms2),sizeof(ms2),ms2};
-
-  /* Hash values of Client ID */
-  char hcid[32];
-  octet HCID={sizeof(hcid),sizeof(hcid), hcid};
-
-  /* Client secret and shares */
-  char cs1[2*PFS+1], cs2[2*PFS+1], sec[2*PFS+1];
-  octet SEC={sizeof(sec),sizeof(sec),sec};
-  octet CS1={sizeof(cs1),sizeof(cs1), cs1};
-  octet CS2={sizeof(cs2),sizeof(cs2), cs2};
-
-  /* Server secret and shares */
-  char ss1[4*PFS], ss2[4*PFS], serverSecret[4*PFS];
-  octet ServerSecret={sizeof(serverSecret),sizeof(serverSecret),serverSecret};
-  octet SS1={sizeof(ss1),sizeof(ss1),ss1};
-  octet SS2={sizeof(ss2),sizeof(ss2),ss2};
-
-  /* Time Permit and shares */
-  char tp1[2*PFS+1], tp2[2*PFS+1], tp[2*PFS+1];
-  octet TP={sizeof(tp),sizeof(tp),tp};
-  octet TP1={sizeof(tp1),sizeof(tp1),tp1};
-  octet TP2={sizeof(tp2),sizeof(tp2),tp2};
-
-  /* Token stored on computer */
-  char token[2*PFS+1];
-  octet TOKEN={sizeof(token),sizeof(token),token};
-
-  char ut[2*PFS+1],u[2*PFS+1];
-  octet UT={sizeof(ut),sizeof(ut),ut};
-  octet U={sizeof(u),sizeof(u),u};
-
-  char hid[2*PFS+1],htid[2*PFS+1];
-  octet HID={0,sizeof(hid),hid};
-  octet HTID={0,sizeof(htid),htid};
-
-  char e[12*PFS], f[12*PFS];
-  octet E={sizeof(e),sizeof(e),e};
-  octet F={sizeof(f),sizeof(f),f};
-
-  PIN1 = 1234;
-  PIN2 = 1234;
-
-  /* Assign the End-User an ID */
-  char* user = "testuser@miracl.com";
-  OCT_jstring(&ID,user);
-  printf("CLIENT: ID %s\n", user);
-
-  int date = 0;
-  char seed[100] = {0};
-  octet SEED = {0,sizeof(seed),seed};
-  csprng RNG;
-
-  /* unrandom seed value! */
-  SEED.len=100;
-  for (i=0;i<100;i++) SEED.val[i]=i+1;
-
-  /* initialise random number generator */
-  MPIN_CREATE_CSPRNG(&RNG,&SEED);
-
-  /* Hash ID */
-  MPIN_HASH_ID(&ID,&HCID);
-  OCT_output(&HCID);
-
-  /* When set only send hashed IDs to server */
-  octet *pID;
-#ifdef USE_ANONYMOUS
-  pID = &HCID;
-#else
-  pID = &ID;
-#endif
-
-  /* Generate Client master secret for MIRACL and Customer */
-  rtn = MPIN_RANDOM_GENERATE(&RNG,&MS1);
-  if (rtn != 0) {
-      printf("MPIN_RANDOM_GENERATE(&RNG,&MS1) Error %d\n", rtn);
-      return 1;
-  }
-  rtn = MPIN_RANDOM_GENERATE(&RNG,&MS2);
-  if (rtn != 0) {
-      printf("MPIN_RANDOM_GENERATE(&RNG,&MS2) Error %d\n", rtn);
-      return 1;
-  }
-  printf("MASTER SECRET MIRACL:= 0x");
-  OCT_output(&MS1);
-  printf("MASTER SECRET CUSTOMER:= 0x");
-  OCT_output(&MS2);
-
-  /* Generate server secret shares */
-  rtn = MPIN_GET_SERVER_SECRET(&MS1,&SS1);
-  if (rtn != 0) {
-      printf("MPIN_GET_SERVER_SECRET(&MS1,&SS1) Error %d\n", rtn);
-      return 1;
-  }
-  rtn = MPIN_GET_SERVER_SECRET(&MS2,&SS2);
-  if (rtn != 0) {
-      printf("MPIN_GET_SERVER_SECRET(&MS2,&SS2) Error %d\n", rtn);
-      return 1;
-  }
-  printf("SS1 = 0x");
-  OCT_output(&SS1);
-  printf("SS2 = 0x");
-  OCT_output(&SS2);
-
-  /* Combine server secret share */
-  rtn = MPIN_RECOMBINE_G2(&SS1, &SS2, &ServerSecret);
-  if (rtn != 0) {
-      printf("MPIN_RECOMBINE_G2(&SS1, &SS2, &ServerSecret) Error %d\n", rtn);
-      return 1;
-  }
-  printf("ServerSecret = 0x");
-  OCT_output(&ServerSecret);
-
-  /* Generate client secret shares */
-  rtn = MPIN_GET_CLIENT_SECRET(&MS1,&HCID,&CS1);
-  if (rtn != 0) {
-      printf("MPIN_GET_CLIENT_SECRET(&MS1,&HCID,&CS1) Error %d\n", rtn);
-      return 1;
-  }
-  rtn = MPIN_GET_CLIENT_SECRET(&MS2,&HCID,&CS2);
-  if (rtn != 0) {
-      printf("MPIN_GET_CLIENT_SECRET(&MS2,&HCID,&CS2) Error %d\n", rtn);
-      return 1;
-  }
-  printf("CS1 = 0x");
-  OCT_output(&CS1);
-  printf("CS2 = 0x");
-  OCT_output(&CS2);
-
-  /* Combine client secret shares : TOKEN is the full client secret */
-  rtn = MPIN_RECOMBINE_G1(&CS1, &CS2, &TOKEN);
-  if (rtn != 0)
-    {
-      printf("MPIN_RECOMBINE_G1(&CS1, &CS2, &TOKEN) Error %d\n", rtn);
-      return 1;
-    }
-  printf("Client Secret = 0x");
-  OCT_output(&TOKEN);
-
-  /* Generate Time Permit shares */
-  date = MPIN_today();
-  printf("Date %d \n", date);
-  rtn = MPIN_GET_CLIENT_PERMIT(date,&MS1,&HCID,&TP1);
-  if (rtn != 0) {
-      printf("MPIN_GET_CLIENT_PERMIT(date,&MS1,&HCID,&TP1) Error %d\n", rtn);
-      return 1;
-  }
-  rtn = MPIN_GET_CLIENT_PERMIT(date,&MS2,&HCID,&TP2);
-  if (rtn != 0) {
-      printf("MPIN_GET_CLIENT_PERMIT(date,&MS2,&HCID,&TP2) Error %d\n", rtn);
-      return 1;
-  }
-  printf("TP1 = 0x");
-  OCT_output(&TP1);
-  printf("TP2 = 0x");
-  OCT_output(&TP2);
-
-  /* Combine Time Permit shares */
-  rtn = MPIN_RECOMBINE_G1(&TP1, &TP2, &TP);
-  if (rtn != 0) {
-      printf("MPIN_RECOMBINE_G1(&TP1, &TP2, &TP) Error %d\n", rtn);
-      return 1;
-  }
-  printf("Time Permit = 0x");
-  OCT_output(&TP);
-
-  /* Client extracts PIN1 from secret to create Token */
-  rtn = MPIN_EXTRACT_PIN(&ID, PIN1, &TOKEN);
-  if (rtn != 0) {
-      printf("MPIN_EXTRACT_PIN( &ID, PIN, &TOKEN) Error %d\n", rtn);
-      return 1;
-  }
-  printf("Token = 0x");
-  OCT_output(&TOKEN);
-
-  /* Client first pass */
-  rtn = MPIN_CLIENT_1(date,&ID,&RNG,&X,PIN2,&TOKEN,&SEC,&U,&UT,&TP);
-  if (rtn != 0) {
-      printf("MPIN_CLIENT_1 ERROR %d\n", rtn);
-      return 1;
-  }
-
-  /* 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. */
-  MPIN_SERVER_1(date,pID,&HID,&HTID);
-
-  /* Server generates Random number Y and sends it to Client */
-  rtn = MPIN_RANDOM_GENERATE(&RNG,&Y);
-  if (rtn != 0) {
-      printf("MPIN_RANDOM_GENERATE(&RNG,&Y) Error %d\n", rtn);
-      return 1;
-  }
-
-  printf("Y = 0x");
-  OCT_output(&Y);
-
-  /* Client second pass */
-  rtn = MPIN_CLIENT_2(&X,&Y,&SEC);
-  if (rtn != 0) {
-      printf("MPIN_CLIENT_2(&X,&Y,&SEC) Error %d\n", rtn);
-      return 1;
-  }
-  printf("V = 0x");
-  OCT_output(&SEC);
-
-  /* Server second pass */
-  rtn = MPIN_SERVER_2(date,&HID,&HTID,&Y,&ServerSecret,&U,&UT,&SEC,&E,&F);
-  if (rtn != 0) {
-      err=MPIN_KANGAROO(&E,&F);
-      if (err==0) {
-          printf("FAILURE Invalid Token Error Code %d\n", rtn);
-      } else {
-          printf("FAILURE PIN Error %d, Error> Code %d\n",err, rtn);
-      }
-  } else {
-      printf("SUCCESS Error Code %d\n", rtn);
-  }
-  return 0;
-}
diff --git a/c/tests/test_mpin_random.c b/c/tests/test_mpin_random.c
deleted file mode 100755
index 645cb19..0000000
--- a/c/tests/test_mpin_random.c
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
-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.
-*/
-
-/* Test good token and correct PIN with D-TA */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include "config.h"
-#include "mpin.h"
-
-// Define PIN range:
-#define MAX_RANGE 10000
-
-void rand_str(char *dest, size_t length,csprng *RNG) {
-  BIG r;
-  char charset[] = "0123456789@.*"
-                   "abcdefghijklmnopqrstuvwxyz"
-                   "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
-  while (length-- > 0) {
-    BIG_random(r,RNG);
-    size_t index = r[0] % (sizeof charset);
-    *dest++ = charset[index];
-  }
-  *dest = '\0';
-}
-
-int main()
-{
-  int i,PIN1,PIN2,rtn,err,iter;
-
-  char x[PGS],y[PGS];
-  octet X={sizeof(x), sizeof(x),x};
-  octet Y={sizeof(y),sizeof(y),y};
-
-  /* Master secret shares */
-  char ms1[PGS], ms2[PGS];
-  octet MS1={sizeof(ms1),sizeof(ms1),ms1};
-  octet MS2={sizeof(ms2),sizeof(ms2),ms2};
-
-  /* Hash values of ID */
-  char hcid[32];
-  octet HCID={sizeof(hcid),sizeof(hcid), hcid};
-
-  /* Client secret and shares */
-  char cs1[2*PFS+1], cs2[2*PFS+1], sec[2*PFS+1];
-  octet SEC={sizeof(sec),sizeof(sec),sec};
-  octet CS1={sizeof(cs1),sizeof(cs1), cs1};
-  octet CS2={sizeof(cs2),sizeof(cs2), cs2};
-
-  /* Server secret and shares */
-  char ss1[4*PFS], ss2[4*PFS], serverSecret[4*PFS];
-  octet ServerSecret={sizeof(serverSecret),sizeof(serverSecret),serverSecret};
-  octet SS1={sizeof(ss1),sizeof(ss1),ss1};
-  octet SS2={sizeof(ss2),sizeof(ss2),ss2};
-
-  /* Time Permit and shares */
-  char tp1[2*PFS+1], tp2[2*PFS+1], tp[2*PFS+1];
-  octet TP={sizeof(tp),sizeof(tp),tp};
-  octet TP1={sizeof(tp1),sizeof(tp1),tp1};
-  octet TP2={sizeof(tp2),sizeof(tp2),tp2};
-
-  /* Token stored on computer */
-  char token[2*PFS+1];
-  octet TOKEN={sizeof(token),sizeof(token),token};
-
-  char ut[2*PFS+1],u[2*PFS+1];
-  octet UT={sizeof(ut),sizeof(ut),ut};
-  octet U={sizeof(u),sizeof(u),u};
-
-  char hid[2*PFS+1],htid[2*PFS+1];
-  octet HID={0,sizeof(hid),hid};
-  octet HTID={0,sizeof(htid),htid};
-
-  char e[12*PFS], f[12*PFS];
-  octet E={sizeof(e),sizeof(e),e};
-  octet F={sizeof(f),sizeof(f),f};
-
-  octet *pID;
-
-  int date = 0;
-
-  unsigned long ran;
-  int byte_count = 32;
-  FILE *fp;
-  char seed[32] = {0};
-  octet SEED = {sizeof(seed),sizeof(seed),seed};
-  csprng RNG;
-
-#ifdef __linux__
-  size_t readSize;
-  fp = fopen("/dev/urandom", "r");
-  readSize = fread(&seed, 1, byte_count, fp);
-  fclose(fp);
-#else
-  /* non random seed value! */
-  time((time_t *)&ran);
-  SEED.val[0]=ran;
-  SEED.val[1]=ran>>8;
-  SEED.val[2]=ran>>16;
-  SEED.val[3]=ran>>24;
-  for (i=4;i<byte_count;i++) SEED.val[i]=i+1;
-#endif
-  printf("SEED 0x");
-  OCT_output(&SEED);
-
-  /* initialise random number generator */
-  MPIN_CREATE_CSPRNG(&RNG,&SEED);
-
-  for(iter=1; iter<nRandomTests+1; iter++)
-    {
-      /* Generate Client master secret for MIRACL and Customer */
-      rtn = MPIN_RANDOM_GENERATE(&RNG,&MS1);
-      if (rtn != 0) {
-          printf("MPIN_RANDOM_GENERATE(&RNG,&MS1) Error %d\n", rtn);
-          return 1;
-      }
-      rtn = MPIN_RANDOM_GENERATE(&RNG,&MS2);
-      if (rtn != 0) {
-          printf("MPIN_RANDOM_GENERATE(&RNG,&MS2) Error %d\n", rtn);
-          return 1;
-      }
-      printf("MASTER SECRET MIRACL:= 0x");
-      OCT_output(&MS1);
-      printf("MASTER SECRET CUSTOMER:= 0x");
-      OCT_output(&MS2);
-
-      /* Generate server secret shares */
-      rtn = MPIN_GET_SERVER_SECRET(&MS1,&SS1);
-      if (rtn != 0) {
-          printf("MPIN_GET_SERVER_SECRET(&MS1,&SS1) Error %d\n", rtn);
-          return 1;
-      }
-      rtn = MPIN_GET_SERVER_SECRET(&MS2,&SS2);
-      if (rtn != 0) {
-          printf("MPIN_GET_SERVER_SECRET(&MS2,&SS2) Error %d\n", rtn);
-          return 1;
-      }
-      printf("SS1 = 0x");
-      OCT_output(&SS1);
-      printf("SS2 = 0x");
-      OCT_output(&SS2);
-
-      /* Combine server secret share */
-      rtn = MPIN_RECOMBINE_G2(&SS1, &SS2, &ServerSecret);
-      if (rtn != 0) {
-          printf("MPIN_RECOMBINE_G2(&SS1, &SS2, &ServerSecret) Error %d\n", rtn);
-          return 1;
-      }
-      printf("ServerSecret = 0x");
-      OCT_output(&ServerSecret);
-
-      /* Assign the End-User an ID */
-      char id[256];
-      octet ID = {0,sizeof(id),id};
-      rand_str(id,256,&RNG);
-      OCT_jstring(&ID,id);
-      printf("CLIENT: ID %s\n", id);
-
-      /* Hash ID */
-      MPIN_HASH_ID(&ID,&HCID);
-      OCT_output(&HCID);
-
-#ifdef USE_ANONYMOUS
-      pID = &HCID;
-#else
-      pID = &ID;
-#endif
-
-      srand ( time (NULL) );
-      PIN1 = rand()%MAX_RANGE; // Get random between 0 and MAX_RANGE
-      PIN2 = PIN1;
-      printf("PIN1 %d PIN2 %d\n", PIN1, PIN2);
-
-      /* Generate client secret shares */
-      rtn = MPIN_GET_CLIENT_SECRET(&MS1,&HCID,&CS1);
-      if (rtn != 0) {
-          printf("MPIN_GET_CLIENT_SECRET(&MS1,&HCID,&CS1) Error %d\n", rtn);
-          return 1;
-      }
-      rtn = MPIN_GET_CLIENT_SECRET(&MS2,&HCID,&CS2);
-      if (rtn != 0) {
-          printf("MPIN_GET_CLIENT_SECRET(&MS2,&HCID,&CS2) Error %d\n", rtn);
-          return 1;
-      }
-      printf("CS1 = 0x");
-      OCT_output(&CS1);
-      printf("CS2 = 0x");
-      OCT_output(&CS2);
-
-      /* Combine client secret shares : TOKEN is the full client secret */
-      rtn = MPIN_RECOMBINE_G1(&CS1, &CS2, &TOKEN);
-      if (rtn != 0) {
-          printf("MPIN_RECOMBINE_G1(&CS1, &CS2, &TOKEN) Error %d\n", rtn);
-          return 1;
-      }
-      printf("Client Secret = 0x");
-      OCT_output(&TOKEN);
-
-      /* Client extracts PIN1 from secret to create Token */
-      rtn = MPIN_EXTRACT_PIN(&ID, PIN1, &TOKEN);
-      if (rtn != 0) {
-          printf("MPIN_EXTRACT_PIN( &ID, PIN, &TOKEN) Error %d\n", rtn);
-          return 1;
-      }
-      printf("Token = 0x");
-      OCT_output(&TOKEN);
-
-      /* Generate Time Permit shares */
-      date = MPIN_today();
-
-      printf("Date %d \n", date);
-      rtn = MPIN_GET_CLIENT_PERMIT(date,&MS1,&HCID,&TP1);
-      if (rtn != 0) {
-          printf("MPIN_GET_CLIENT_PERMIT(date,&MS1,&HCID,&TP1) Error %d\n", rtn);
-          return 1;
-      }
-      rtn = MPIN_GET_CLIENT_PERMIT(date,&MS2,&HCID,&TP2);
-      if (rtn != 0) {
-          printf("MPIN_GET_CLIENT_PERMIT(date,&MS2,&HCID,&TP2) Error %d\n", rtn);
-          return 1;
-      }
-      printf("TP1 = 0x");
-      OCT_output(&TP1);
-      printf("TP2 = 0x");
-      OCT_output(&TP2);
-
-      /* Combine Time Permit shares */
-      rtn = MPIN_RECOMBINE_G1(&TP1, &TP2, &TP);
-      if (rtn != 0) {
-          printf("MPIN_RECOMBINE_G1(&TP1, &TP2, &TP) Error %d\n", rtn);
-          return 1;
-      }
-      printf("Time Permit = 0x");
-      OCT_output(&TP);
-
-      /* Client first pass */
-      rtn = MPIN_CLIENT_1(date,&ID,&RNG,&X,PIN2,&TOKEN,&SEC,&U,&UT,&TP);
-      if (rtn != 0) {
-          printf("MPIN_CLIENT_1 ERROR %d\n", rtn);
-          return 1;
-      }
-
-      /* 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. */
-      MPIN_SERVER_1(date,pID,&HID,&HTID);
-
-      /* Server generates Random number Y and sends it to Client */
-      rtn = MPIN_RANDOM_GENERATE(&RNG,&Y);
-      if (rtn != 0) {
-          printf("MPIN_RANDOM_GENERATE(&RNG,&Y) Error %d\n", rtn);
-          return 1;
-      }
-      printf("Y = 0x");
-      OCT_output(&Y);
-
-      /* Client second pass */
-      rtn = MPIN_CLIENT_2(&X,&Y,&SEC);
-      if (rtn != 0) {
-          printf("MPIN_CLIENT_2(&X,&Y,&SEC) Error %d\n", rtn);
-          return 1;
-      }
-      printf("V = 0x");
-      OCT_output(&SEC);
-
-      /* Server second pass */
-      rtn = MPIN_SERVER_2(date,&HID,&HTID,&Y,&ServerSecret,&U,&UT,&SEC,&E,&F);
-      if (rtn != 0) {
-          err=MPIN_KANGAROO(&E,&F);
-          if (err==0) {
-              printf("Iteration %d FAILURE Invalid Token Error Code %d\n", iter, rtn);
-              return 1;
-	  } else {
-              printf("Iteration %d FAILURE PIN Error %d, Error Code %d\n", iter, err, rtn);
-              return 1;
-	  }
-      } else {
-          printf("Iteration %d SUCCESS Error Code %d\n\n", iter, rtn);
-      }
-    }
-  return 0;
-}
diff --git a/c/tests/test_mpin_sign.c b/c/tests/test_mpin_sign.c
deleted file mode 100755
index 7743e66..0000000
--- a/c/tests/test_mpin_sign.c
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
-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.
-*/
-
-/* Test M-Pin Signature */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include "mpin.h"
-
-int main()
-{
-  int i,PIN1,PIN2,rtn,err;
-
-  int failure = 0;
-
-  char id[256];
-  octet ID = {0,sizeof(id),id};
-
-  // Message to sign
-  char m[256];
-  octet M={0,sizeof(m),m};
-
-  char x[PGS],y1[PGS],y2[PGS];
-  octet X={sizeof(x), sizeof(x),x};
-  octet Y1={sizeof(y1),sizeof(y1),y1};
-  octet Y2={sizeof(y2),sizeof(y2),y2};
-
-  /* Master secret shares */
-  char ms1[PGS], ms2[PGS];
-  octet MS1={sizeof(ms1),sizeof(ms1),ms1};
-  octet MS2={sizeof(ms2),sizeof(ms2),ms2};
-
-  /* Hash values of Client ID */
-  char hcid[32];
-  octet HCID={sizeof(hcid),sizeof(hcid), hcid};
-
-  /* Client secret and shares */
-  char cs1[2*PFS+1], cs2[2*PFS+1], sec[2*PFS+1];
-  octet SEC={sizeof(sec),sizeof(sec),sec};
-  octet CS1={sizeof(cs1),sizeof(cs1), cs1};
-  octet CS2={sizeof(cs2),sizeof(cs2), cs2};
-
-  /* Server secret and shares */
-  char ss1[4*PFS], ss2[4*PFS], serverSecret[4*PFS];
-  octet ServerSecret={sizeof(serverSecret),sizeof(serverSecret),serverSecret};
-  octet SS1={sizeof(ss1),sizeof(ss1),ss1};
-  octet SS2={sizeof(ss2),sizeof(ss2),ss2};
-
-  /* Time Permit and shares */
-  char tp1[2*PFS+1], tp2[2*PFS+1], tp[2*PFS+1];
-  octet TP={sizeof(tp),sizeof(tp),tp};
-  octet TP1={sizeof(tp1),sizeof(tp1),tp1};
-  octet TP2={sizeof(tp2),sizeof(tp2),tp2};
-
-  /* Token stored on computer */
-  char token[2*PFS+1];
-  octet TOKEN={sizeof(token),sizeof(token),token};
-
-  char ut[2*PFS+1],u[2*PFS+1];
-  octet UT={sizeof(ut),sizeof(ut),ut};
-  octet U={sizeof(u),sizeof(u),u};
-
-  char hid[2*PFS+1],htid[2*PFS+1];
-  octet HID={0,sizeof(hid),hid};
-  octet HTID={0,sizeof(htid),htid};
-
-  char e[12*PFS], f[12*PFS];
-  octet E={sizeof(e),sizeof(e),e};
-  octet F={sizeof(f),sizeof(f),f};
-
-
-
-  int TimeValue = 0;
-
-  PIN1 = 1234;
-  PIN2 = 1234;
-
-  /* Assign the End-User an ID */
-  char* user = "testuser@miracl.com";
-  OCT_jstring(&ID,user);
-  printf("CLIENT: ID %s\n", user);
-
-  int date = 0;
-  char seed[100] = {0};
-  octet SEED = {0,sizeof(seed),seed};
-  csprng RNG;
-
-  /* unrandom seed value! */
-  SEED.len=100;
-  for (i=0;i<100;i++) SEED.val[i]=i+1;
-
-  /* initialise random number generator */
-  MPIN_CREATE_CSPRNG(&RNG,&SEED);
-
-  /* Hash ID */
-  MPIN_HASH_ID(&ID,&HCID);
-  OCT_output(&HCID);
-
-  /* When set only send hashed IDs to server */
-  octet *pID;
-#ifdef USE_ANONYMOUS
-  pID = &HCID;
-#else
-  pID = &ID;
-#endif
-
-  /* Generate Client master secret for MIRACL and Customer */
-  rtn = MPIN_RANDOM_GENERATE(&RNG,&MS1);
-  if (rtn != 0) {
-      printf("MPIN_RANDOM_GENERATE(&RNG,&MS1) Error %d\n", rtn);
-      return 1;
-  }
-  rtn = MPIN_RANDOM_GENERATE(&RNG,&MS2);
-  if (rtn != 0) {
-      printf("MPIN_RANDOM_GENERATE(&RNG,&MS2) Error %d\n", rtn);
-      return 1;
-  }
-  printf("MASTER SECRET MIRACL:= 0x");
-  OCT_output(&MS1);
-  printf("MASTER SECRET CUSTOMER:= 0x");
-  OCT_output(&MS2);
-
-  /* Generate server secret shares */
-  rtn = MPIN_GET_SERVER_SECRET(&MS1,&SS1);
-  if (rtn != 0) {
-      printf("MPIN_GET_SERVER_SECRET(&MS1,&SS1) Error %d\n", rtn);
-      return 1;
-  }
-  rtn = MPIN_GET_SERVER_SECRET(&MS2,&SS2);
-  if (rtn != 0) {
-      printf("MPIN_GET_SERVER_SECRET(&MS2,&SS2) Error %d\n", rtn);
-      return 1;
-  }
-  printf("SS1 = 0x");
-  OCT_output(&SS1);
-  printf("SS2 = 0x");
-  OCT_output(&SS2);
-
-  /* Combine server secret share */
-  rtn = MPIN_RECOMBINE_G2(&SS1, &SS2, &ServerSecret);
-  if (rtn != 0) {
-      printf("MPIN_RECOMBINE_G2(&SS1, &SS2, &ServerSecret) Error %d\n", rtn);
-      return 1;
-  }
-  printf("ServerSecret = 0x");
-  OCT_output(&ServerSecret);
-
-  /* Generate client secret shares */
-  rtn = MPIN_GET_CLIENT_SECRET(&MS1,&HCID,&CS1);
-  if (rtn != 0) {
-      printf("MPIN_GET_CLIENT_SECRET(&MS1,&HCID,&CS1) Error %d\n", rtn);
-      return 1;
-  }
-  rtn = MPIN_GET_CLIENT_SECRET(&MS2,&HCID,&CS2);
-  if (rtn != 0) {
-      printf("MPIN_GET_CLIENT_SECRET(&MS2,&HCID,&CS2) Error %d\n", rtn);
-      return 1;
-  }
-  printf("CS1 = 0x");
-  OCT_output(&CS1);
-  printf("CS2 = 0x");
-  OCT_output(&CS2);
-
-  /* Combine client secret shares : TOKEN is the full client secret */
-  rtn = MPIN_RECOMBINE_G1(&CS1, &CS2, &TOKEN);
-  if (rtn != 0) {
-      printf("MPIN_RECOMBINE_G1(&CS1, &CS2, &TOKEN) Error %d\n", rtn);
-      return 1;
-  }
-  printf("Client Secret = 0x");
-  OCT_output(&TOKEN);
-
-  /* Generate Time Permit shares */
-  date = MPIN_today();
-  printf("Date %d \n", date);
-  rtn = MPIN_GET_CLIENT_PERMIT(date,&MS1,&HCID,&TP1);
-  if (rtn != 0) {
-      printf("MPIN_GET_CLIENT_PERMIT(date,&MS1,&HCID,&TP1) Error %d\n", rtn);
-      return 1;
-  }
-  rtn = MPIN_GET_CLIENT_PERMIT(date,&MS2,&HCID,&TP2);
-  if (rtn != 0) {
-      printf("MPIN_GET_CLIENT_PERMIT(date,&MS2,&HCID,&TP2) Error %d\n", rtn);
-      return 1;
-  }
-  printf("TP1 = 0x");
-  OCT_output(&TP1);
-  printf("TP2 = 0x");
-  OCT_output(&TP2);
-
-  /* Combine Time Permit shares */
-  rtn = MPIN_RECOMBINE_G1(&TP1, &TP2, &TP);
-  if (rtn != 0) {
-      printf("MPIN_RECOMBINE_G1(&TP1, &TP2, &TP) Error %d\n", rtn);
-      return 1;
-  }
-  printf("Time Permit = 0x");
-  OCT_output(&TP);
-
-  /* Client extracts PIN1 from secret to create Token */
-  rtn = MPIN_EXTRACT_PIN(&ID, PIN1, &TOKEN);
-  if (rtn != 0) {
-      printf("MPIN_EXTRACT_PIN( &ID, PIN, &TOKEN) Error %d\n", rtn);
-      return 1;
-  }
-  printf("Token = 0x");
-  OCT_output(&TOKEN);
-
-  /* Good signature */
-
-  /* Client  */
-  char* message = "sign this message";
-  OCT_jstring(&M,message);
-  TimeValue = MPIN_GET_TIME();
-  printf("TimeValue %d \n", TimeValue);
-  rtn = MPIN_CLIENT(date,&ID,&RNG,&X,PIN2,&TOKEN,&SEC,NULL,&UT,&TP,&M,TimeValue,&Y1);
-  if (rtn != 0) {
-      printf("MPIN_CLIENT ERROR %d\n", rtn);
-      return 1;
-  }
-  printf("Y1 = 0x");
-  OCT_output(&Y1);
-  printf("V = 0x");
-  OCT_output(&SEC);
-
-  /* Server  */
-  rtn = MPIN_SERVER(date,NULL,&HTID,&Y2,&ServerSecret,NULL,&UT,&SEC,&E,&F,pID,&M,TimeValue);
-  printf("Y2 = 0x");
-  OCT_output(&Y2);
-  if (rtn != 0) {
-      failure = 1;
-      printf("FAILURE valid signature not detected %d\n", rtn);
-  } else {
-      printf("SUCCESS Error Code %d\n", rtn);
-  }
-
-  /* Time stamp expired */
-
-  /* Client  */
-  OCT_clear(&M);
-  message = "sign this message";
-  OCT_jstring(&M,message);
-  TimeValue = MPIN_GET_TIME();
-  printf("TimeValue %d \n", TimeValue);
-  rtn = MPIN_CLIENT(date,&ID,&RNG,&X,PIN2,&TOKEN,&SEC,NULL,&UT,&TP,&M,TimeValue,&Y1);
-  if (rtn != 0) {
-      printf("MPIN_CLIENT ERROR %d\n", rtn);
-      return 1;
-  }
-  printf("Y1 = 0x");
-  OCT_output(&Y1);
-  printf("V = 0x");
-  OCT_output(&SEC);
-
-  /* Server  */
-  TimeValue += 10;
-  rtn = MPIN_SERVER(date,NULL,&HTID,&Y2,&ServerSecret,NULL,&UT,&SEC,&E,&F,pID,&M,TimeValue);
-  printf("Y2 = 0x");
-  OCT_output(&Y2);
-  if (rtn != -19) {
-      failure = 1;
-      printf("FAILURE Invalid signature not detected %d\n", rtn);
-  } else {
-      printf("SUCCESS Error Code %d\n", rtn);
-  }
-
-  /* Invalid data */
-
-  /* Client  */
-  OCT_clear(&M);
-  message = "sign this message";
-  OCT_jstring(&M,message);
-  TimeValue = MPIN_GET_TIME();
-  printf("TimeValue %d \n", TimeValue);
-  rtn = MPIN_CLIENT(date,&ID,&RNG,&X,PIN2,&TOKEN,&SEC,NULL,&UT,&TP,&M,TimeValue,&Y1);
-  if (rtn != 0) {
-      printf("MPIN_CLIENT ERROR %d\n", rtn);
-      return 1;
-  }
-  printf("Y1 = 0x");
-  OCT_output(&Y1);
-  printf("V = 0x");
-  OCT_output(&SEC);
-
-  /* Server  */
-  OCT_clear(&M);
-  message = "bad message";
-  OCT_jstring(&M,message);
-  rtn = MPIN_SERVER(date,NULL,&HTID,&Y2,&ServerSecret,NULL,&UT,&SEC,&E,&F,pID,&M,TimeValue);
-  printf("Y2 = 0x");
-  OCT_output(&Y2);
-  if (rtn != -19) {
-      failure = 1;
-      printf("FAILURE Invalid signature not detected %d\n", rtn);
-  } else {
-      printf("SUCCESS Error Code %d\n", rtn);
-  }
-
-  if (failure != 0) {
-      printf("TEST FAILED\n");
-      return 1;
-  }
-
-  printf("TEST PASSED\n");
-  return 0;
-}
diff --git a/c/tests/test_mpin_tp.c b/c/tests/test_mpin_tp.c
deleted file mode 100755
index 05562b9..0000000
--- a/c/tests/test_mpin_tp.c
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
-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.
-*/
-
-/* Test good token and correct PIN with D-TA for
-   nTimePermitTests days in the future */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include "config.h"
-#include "mpin.h"
-
-int main()
-{
-  int i,PIN1,PIN2,rtn,err,iter;
-
-  char id[256];
-  octet ID = {0,sizeof(id),id};
-
-  char x[PGS],y[PGS];
-  octet X={sizeof(x), sizeof(x),x};
-  octet Y={sizeof(y),sizeof(y),y};
-
-  /* Master secret shares */
-  char ms1[PGS], ms2[PGS];
-  octet MS1={sizeof(ms1),sizeof(ms1),ms1};
-  octet MS2={sizeof(ms2),sizeof(ms2),ms2};
-
-  /* Hash values of ID */
-  char hcid[32];
-  octet HCID={sizeof(hcid),sizeof(hcid), hcid};
-
-  /* Client secret and shares */
-  char cs1[2*PFS+1], cs2[2*PFS+1], sec[2*PFS+1];
-  octet SEC={sizeof(sec),sizeof(sec),sec};
-  octet CS1={sizeof(cs1),sizeof(cs1), cs1};
-  octet CS2={sizeof(cs2),sizeof(cs2), cs2};
-
-  /* Server secret and shares */
-  char ss1[4*PFS], ss2[4*PFS], serverSecret[4*PFS];
-  octet ServerSecret={sizeof(serverSecret),sizeof(serverSecret),serverSecret};
-  octet SS1={sizeof(ss1),sizeof(ss1),ss1};
-  octet SS2={sizeof(ss2),sizeof(ss2),ss2};
-
-  /* Time Permit and shares */
-  char tp1[2*PFS+1], tp2[2*PFS+1], tp[2*PFS+1];
-  octet TP={sizeof(tp),sizeof(tp),tp};
-  octet TP1={sizeof(tp1),sizeof(tp1),tp1};
-  octet TP2={sizeof(tp2),sizeof(tp2),tp2};
-
-  /* Token stored on computer */
-  char token[2*PFS+1];
-  octet TOKEN={sizeof(token),sizeof(token),token};
-
-  char ut[2*PFS+1],u[2*PFS+1];
-  octet UT={sizeof(ut),sizeof(ut),ut};
-  octet U={sizeof(u),sizeof(u),u};
-
-  char hid[2*PFS+1],htid[2*PFS+1];
-  octet HID={0,sizeof(hid),hid};
-  octet HTID={0,sizeof(htid),htid};
-
-  char e[12*PFS], f[12*PFS];
-  octet E={sizeof(e),sizeof(e),e};
-  octet F={sizeof(f),sizeof(f),f};
-
-  octet *pID;
-
-  PIN1 = 1234;
-  PIN2 = 1234;
-
-  /* Assign the End-User an ID */
-  char* user = "testuser@miracl.com";
-  OCT_jstring(&ID,user);
-  printf("CLIENT: ID %s\n", user);
-
-  int date = 0;
-  char seed[100] = {0};
-  octet SEED = {0,sizeof(seed),seed};
-  csprng RNG;
-
-  /* unrandom seed value! */
-  SEED.len=100;
-  for (i=0;i<100;i++) SEED.val[i]=i+1;
-
-  /* initialise random number generator */
-  MPIN_CREATE_CSPRNG(&RNG,&SEED);
-
-  /* Hash ID */
-  MPIN_HASH_ID(&ID,&HCID);
-  OCT_output(&HCID);
-
-  /* When set only send hashed IDs to server */
-#ifdef USE_ANONYMOUS
-  pID = &HCID;
-#else
-  pID = &ID;
-#endif
-
-  /* Generate Client master secret for MIRACL and Customer */
-  rtn = MPIN_RANDOM_GENERATE(&RNG,&MS1);
-  if (rtn != 0) {
-      printf("MPIN_RANDOM_GENERATE(&RNG,&MS1) Error %d\n", rtn);
-      return 1;
-  }
-  rtn = MPIN_RANDOM_GENERATE(&RNG,&MS2);
-  if (rtn != 0) {
-      printf("MPIN_RANDOM_GENERATE(&RNG,&MS2) Error %d\n", rtn);
-      return 1;
-  }
-  printf("MASTER SECRET MIRACL:= 0x");
-  OCT_output(&MS1);
-  printf("MASTER SECRET CUSTOMER:= 0x");
-  OCT_output(&MS2);
-
-  /* Generate server secret shares */
-  rtn = MPIN_GET_SERVER_SECRET(&MS1,&SS1);
-  if (rtn != 0) {
-      printf("MPIN_GET_SERVER_SECRET(&MS1,&SS1) Error %d\n", rtn);
-      return 1;
-  }
-  rtn = MPIN_GET_SERVER_SECRET(&MS2,&SS2);
-  if (rtn != 0) {
-      printf("MPIN_GET_SERVER_SECRET(&MS2,&SS2) Error %d\n", rtn);
-      return 1;
-  }
-  printf("SS1 = 0x");
-  OCT_output(&SS1);
-  printf("SS2 = 0x");
-  OCT_output(&SS2);
-
-  /* Combine server secret share */
-  rtn = MPIN_RECOMBINE_G2(&SS1, &SS2, &ServerSecret);
-  if (rtn != 0) {
-      printf("MPIN_RECOMBINE_G2(&SS1, &SS2, &ServerSecret) Error %d\n", rtn);
-      return 1;
-  }
-  printf("ServerSecret = 0x");
-  OCT_output(&ServerSecret);
-
-  /* Generate client secret shares */
-  rtn = MPIN_GET_CLIENT_SECRET(&MS1,&HCID,&CS1);
-  if (rtn != 0) {
-      printf("MPIN_GET_CLIENT_SECRET(&MS1,&HCID,&CS1) Error %d\n", rtn);
-      return 1;
-  }
-  rtn = MPIN_GET_CLIENT_SECRET(&MS2,&HCID,&CS2);
-  if (rtn != 0) {
-      printf("MPIN_GET_CLIENT_SECRET(&MS2,&HCID,&CS2) Error %d\n", rtn);
-      return 1;
-  }
-  printf("CS1 = 0x");
-  OCT_output(&CS1);
-  printf("CS2 = 0x");
-  OCT_output(&CS2);
-
-  /* Combine client secret shares : TOKEN is the full client secret */
-  rtn = MPIN_RECOMBINE_G1(&CS1, &CS2, &TOKEN);
-  if (rtn != 0) {
-      printf("MPIN_RECOMBINE_G1(&CS1, &CS2, &TOKEN) Error %d\n", rtn);
-      return 1;
-  }
-  printf("Client Secret = 0x");
-  OCT_output(&TOKEN);
-
-  /* Client extracts PIN1 from secret to create Token */
-  rtn = MPIN_EXTRACT_PIN(&ID, PIN1, &TOKEN);
-  if (rtn != 0) {
-      printf("MPIN_EXTRACT_PIN( &ID, PIN, &TOKEN) Error %d\n", rtn);
-      return 1;
-  }
-  printf("Token = 0x");
-  OCT_output(&TOKEN);
-
-  /* Generate Time Permit shares */
-  date = MPIN_today();
-  for(iter=1; iter<nTimePermitTests+1; iter++)
-    {
-      printf("Date %d \n", date);
-      rtn = MPIN_GET_CLIENT_PERMIT(date,&MS1,&HCID,&TP1);
-      if (rtn != 0) {
-          printf("MPIN_GET_CLIENT_PERMIT(date,&MS1,&HCID,&TP1) Error %d\n", rtn);
-          return 1;
-      }
-      rtn = MPIN_GET_CLIENT_PERMIT(date,&MS2,&HCID,&TP2);
-      if (rtn != 0) {
-          printf("MPIN_GET_CLIENT_PERMIT(date,&MS2,&HCID,&TP2) Error %d\n", rtn);
-          return 1;
-      }
-      printf("TP1 = 0x");
-      OCT_output(&TP1);
-      printf("TP2 = 0x");
-      OCT_output(&TP2);
-
-      /* Combine Time Permit shares */
-      rtn = MPIN_RECOMBINE_G1(&TP1, &TP2, &TP);
-      if (rtn != 0) {
-          printf("MPIN_RECOMBINE_G1(&TP1, &TP2, &TP) Error %d\n", rtn);
-          return 1;
-      }
-      printf("Time Permit = 0x");
-      OCT_output(&TP);
-
-      /* Client first pass */
-      rtn = MPIN_CLIENT_1(date,&ID,&RNG,&X,PIN2,&TOKEN,&SEC,&U,&UT,&TP);
-      if (rtn != 0) {
-          printf("MPIN_CLIENT_1 ERROR %d\n", rtn);
-          return 1;
-      }
-
-      /* 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. */
-      MPIN_SERVER_1(date,pID,&HID,&HTID);
-
-      /* Server generates Random number Y and sends it to Client */
-      rtn = MPIN_RANDOM_GENERATE(&RNG,&Y);
-      if (rtn != 0) {
-          printf("MPIN_RANDOM_GENERATE(&RNG,&Y) Error %d\n", rtn);
-          return 1;
-      }
-      printf("Y = 0x");
-      OCT_output(&Y);
-
-      /* Client second pass */
-      rtn = MPIN_CLIENT_2(&X,&Y,&SEC);
-      if (rtn != 0) {
-          printf("MPIN_CLIENT_2(&X,&Y,&SEC) Error %d\n", rtn);
-          return 1;
-      }
-      printf("V = 0x");
-      OCT_output(&SEC);
-
-      /* Server second pass */
-      rtn = MPIN_SERVER_2(date,&HID,&HTID,&Y,&ServerSecret,&U,&UT,&SEC,&E,&F);
-      if (rtn != 0) {
-          err=MPIN_KANGAROO(&E,&F);
-          if (err==0) {
-              printf("Iteration %d FAILURE Invalid Token Error Code %d\n", iter, rtn);
-              break;
-	  } else {
-              printf("Iteration %d FAILURE PIN Error %d, Error Code %d\n", iter, err, rtn);
-              break;
-	   }
-      } else {
-          printf("Iteration %d SUCCESS Error Code %d\n", iter, rtn);
-      }
-      date++;
-    }
-  return 0;
-}
diff --git a/c/tests/test_mpinfull.c b/c/tests/test_mpinfull.c
deleted file mode 100755
index 10cc857..0000000
--- a/c/tests/test_mpinfull.c
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
-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.
-*/
-
-/* Test M-Pin Full */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include "mpin.h"
-
-int main()
-{
-  int i,PIN1,PIN2,rtn,err;
-
-  char id[256];
-  octet ID = {0,sizeof(id),id};
-
-  char x[PGS],y[PGS];
-  octet X={sizeof(x), sizeof(x),x};
-  octet Y={sizeof(y),sizeof(y),y};
-
-  /* Master secret shares */
-  char ms1[PGS], ms2[PGS];
-  octet MS1={sizeof(ms1),sizeof(ms1),ms1};
-  octet MS2={sizeof(ms2),sizeof(ms2),ms2};
-
-  /* Hash values of client ID */
-  char hcid[HASH_BYTES];
-  octet HCID={sizeof(hcid),sizeof(hcid), hcid};
-  char hsid[HASH_BYTES];
-  octet HSID={sizeof(hsid),sizeof(hsid), hsid};
-
-  /* Hash values of messages */
-  char hm[HASH_BYTES];
-  octet HM={sizeof(hm),sizeof(hm), hm};
-
-  /* Client secret and shares */
-  char cs1[2*PFS+1], cs2[2*PFS+1], sec[2*PFS+1];
-  octet SEC={sizeof(sec),sizeof(sec),sec};
-  octet CS1={sizeof(cs1),sizeof(cs1), cs1};
-  octet CS2={sizeof(cs2),sizeof(cs2), cs2};
-
-  /* Server secret and shares */
-  char ss1[4*PFS], ss2[4*PFS], serverSecret[4*PFS];
-  octet ServerSecret={sizeof(serverSecret),sizeof(serverSecret),serverSecret};
-  octet SS1={sizeof(ss1),sizeof(ss1),ss1};
-  octet SS2={sizeof(ss2),sizeof(ss2),ss2};
-
-  /* Time Permit and shares */
-  char tp1[2*PFS+1], tp2[2*PFS+1], tp[2*PFS+1];
-  octet TP={sizeof(tp),sizeof(tp),tp};
-  octet TP1={sizeof(tp1),sizeof(tp1),tp1};
-  octet TP2={sizeof(tp2),sizeof(tp2),tp2};
-
-  /* Token stored on device */
-  char token[2*PFS+1];
-  octet TOKEN={sizeof(token),sizeof(token),token};
-
-  /* Precomputed values stored on device */
-  char g1[12*PFS],g2[12*PFS];
-  octet G1={0,sizeof(g1),g1};
-  octet G2={0,sizeof(g2),g2};
-
-  char ut[2*PFS+1],u[2*PFS+1];
-  octet UT={sizeof(ut),sizeof(ut),ut};
-  octet U={sizeof(u),sizeof(u),u};
-
-  char hid[2*PFS+1],htid[2*PFS+1];
-  octet HID={0,sizeof(hid),hid};
-  octet HTID={0,sizeof(htid),htid};
-
-  char e[12*PFS], f[12*PFS];
-  octet E={sizeof(e),sizeof(e),e};
-  octet F={sizeof(f),sizeof(f),f};
-
-  char r[PGS],z[2*PFS+1],w[PGS],t[2*PFS+1];
-
-  char ck[PAS],sk[PAS];
-  octet R={0,sizeof(r),r};
-  octet Z={0,sizeof(z),z};
-  octet W={0,sizeof(w),w};
-  octet T={0,sizeof(t),t};
-  octet SK={0,sizeof(sk),sk};
-  octet CK={0,sizeof(ck),ck};
-
-  PIN1 = 1234;
-  PIN2 = 1234;
-
-  /* Assign the End-User an ID */
-  char* user = "testuser@miracl.com";
-  OCT_jstring(&ID,user);
-  printf("CLIENT: ID %s\n", user);
-
-  int date = 0;
-  char seed[100] = {0};
-  octet SEED = {0,sizeof(seed),seed};
-  csprng RNG;
-
-  /* unrandom seed value! */
-  SEED.len=100;
-  for (i=0;i<100;i++) SEED.val[i]=i+1;
-
-  /* initialise random number generator */
-  MPIN_CREATE_CSPRNG(&RNG,&SEED);
-
-  /* Hash ID */
-  MPIN_HASH_ID(&ID,&HCID);
-  OCT_output(&HCID);
-
-  /* When set only send hashed IDs to server */
-  octet *pID;
-#ifdef USE_ANONYMOUS
-  pID = &HCID;
-#else
-  pID = &ID;
-#endif
-
-  /* Generate Client master secret for MIRACL and Customer */
-  rtn = MPIN_RANDOM_GENERATE(&RNG,&MS1);
-  if (rtn != 0) {
-      printf("MPIN_RANDOM_GENERATE(&RNG,&MS1) Error %d\n", rtn);
-      return 1;
-  }
-  rtn = MPIN_RANDOM_GENERATE(&RNG,&MS2);
-  if (rtn != 0) {
-      printf("MPIN_RANDOM_GENERATE(&RNG,&MS2) Error %d\n", rtn);
-      return 1;
-  }
-  printf("MASTER SECRET MIRACL:= 0x");
-  OCT_output(&MS1);
-  printf("MASTER SECRET CUSTOMER:= 0x");
-  OCT_output(&MS2);
-
-  /* Generate server secret shares */
-  rtn = MPIN_GET_SERVER_SECRET(&MS1,&SS1);
-  if (rtn != 0) {
-      printf("MPIN_GET_SERVER_SECRET(&MS1,&SS1) Error %d\n", rtn);
-      return 1;
-  }
-  rtn = MPIN_GET_SERVER_SECRET(&MS2,&SS2);
-  if (rtn != 0) {
-      printf("MPIN_GET_SERVER_SECRET(&MS2,&SS2) Error %d\n", rtn);
-      return 1;
-  }
-  printf("SS1 = 0x");
-  OCT_output(&SS1);
-  printf("SS2 = 0x");
-  OCT_output(&SS2);
-
-  /* Combine server secret share */
-  rtn = MPIN_RECOMBINE_G2(&SS1, &SS2, &ServerSecret);
-  if (rtn != 0) {
-      printf("MPIN_RECOMBINE_G2(&SS1, &SS2, &ServerSecret) Error %d\n", rtn);
-      return 1;
-  }
-  printf("ServerSecret = 0x");
-  OCT_output(&ServerSecret);
-
-  /* Generate client secret shares */
-  rtn = MPIN_GET_CLIENT_SECRET(&MS1,&HCID,&CS1);
-  if (rtn != 0) {
-      printf("MPIN_GET_CLIENT_SECRET(&MS1,&HCID,&CS1) Error %d\n", rtn);
-      return 1;
-  }
-  rtn = MPIN_GET_CLIENT_SECRET(&MS2,&HCID,&CS2);
-  if (rtn != 0) {
-      printf("MPIN_GET_CLIENT_SECRET(&MS2,&HCID,&CS2) Error %d\n", rtn);
-      return 1;
-  }
-  printf("CS1 = 0x");
-  OCT_output(&CS1);
-  printf("CS2 = 0x");
-  OCT_output(&CS2);
-
-  /* Combine client secret shares : TOKEN is the full client secret */
-  rtn = MPIN_RECOMBINE_G1(&CS1, &CS2, &TOKEN);
-  if (rtn != 0) {
-      printf("MPIN_RECOMBINE_G1(&CS1, &CS2, &TOKEN) Error %d\n", rtn);
-      return 1;
-  }
-  printf("Client Secret = 0x");
-  OCT_output(&TOKEN);
-
-  /* Generate Time Permit shares */
-  date = MPIN_today();
-  printf("Date %d \n", date);
-  rtn = MPIN_GET_CLIENT_PERMIT(date,&MS1,&HCID,&TP1);
-  if (rtn != 0) {
-      printf("MPIN_GET_CLIENT_PERMIT(date,&MS1,&HCID,&TP1) Error %d\n", rtn);
-      return 1;
-  }
-  rtn = MPIN_GET_CLIENT_PERMIT(date,&MS2,&HCID,&TP2);
-  if (rtn != 0) {
-      printf("MPIN_GET_CLIENT_PERMIT(date,&MS2,&HCID,&TP2) Error %d\n", rtn);
-      return 1;
-  }
-  printf("TP1 = 0x");
-  OCT_output(&TP1);
-  printf("TP2 = 0x");
-  OCT_output(&TP2);
-
-  /* Combine Time Permit shares */
-  rtn = MPIN_RECOMBINE_G1(&TP1, &TP2, &TP);
-  if (rtn != 0) {
-      printf("MPIN_RECOMBINE_G1(&TP1, &TP2, &TP) Error %d\n", rtn);
-      return 1;
-  }
-  printf("Time Permit = 0x");
-  OCT_output(&TP);
-
-  /* This encoding makes Time permit look random */
-  if (MPIN_ENCODING(&RNG,&TP)!=0) printf("Encoding error\n");
-  printf("Encoded Time Permit= "); OCT_output(&TP);
-  if (MPIN_DECODING(&TP)!=0) printf("Decoding error\n");
-  printf("Decoded Time Permit= "); OCT_output(&TP);
-
-  /* Client extracts PIN1 from secret to create Token */
-  rtn = MPIN_EXTRACT_PIN(&ID, PIN1, &TOKEN);
-  if (rtn != 0) {
-      printf("MPIN_EXTRACT_PIN( &ID, PIN, &TOKEN) Error %d\n", rtn);
-      return 1;
-  }
-  printf("Token = 0x");
-  OCT_output(&TOKEN);
-
-  /* Client precomputation */
-  MPIN_PRECOMPUTE(&TOKEN,&HCID,&G1,&G2);
-
-  /* Client first pass */
-  rtn = MPIN_CLIENT_1(date,&ID,&RNG,&X,PIN2,&TOKEN,&SEC,&U,&UT,&TP);
-  if (rtn != 0) {
-      printf("MPIN_CLIENT_1 ERROR %d\n", rtn);
-      return 1;
-  }
-
-  /* Client sends Z=r.ID to Server */
-  MPIN_GET_G1_MULTIPLE(&RNG,1,&R,&HCID,&Z);
-
-  /* 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. */
-  MPIN_SERVER_1(date,pID,&HID,&HTID);
-
-  /* Server generates Random number Y and sends it to Client */
-  rtn = MPIN_RANDOM_GENERATE(&RNG,&Y);
-  if (rtn != 0) {
-      printf("MPIN_RANDOM_GENERATE(&RNG,&Y) Error %d\n", rtn);
-      return 1;
-  }
-  printf("Y = 0x");
-  OCT_output(&Y);
-
-  /* Server sends T=w.ID to client */
-  MPIN_GET_G1_MULTIPLE(&RNG,0,&W,&HTID,&T);
-  printf("T = 0x");
-  OCT_output(&T);
-
-  /* Client second pass */
-  rtn = MPIN_CLIENT_2(&X,&Y,&SEC);
-  if (rtn != 0) {
-    printf("MPIN_CLIENT_2(&X,&Y,&SEC) Error %d\n", rtn);
-  }
-  printf("V = 0x");
-  OCT_output(&SEC);
-
-  /* Server second pass */
-  rtn = MPIN_SERVER_2(date,NULL,&HTID,&Y,&ServerSecret,NULL,&UT,&SEC,&E,&F);
-  if (rtn != 0) {
-      printf("FAILURE Invalid Token Error Code %d\n", rtn);
-  }
-
-  MPIN_HASH_ALL(&HCID,NULL,&UT,&SEC,&Y,&Z,&T,&HM);  
-  MPIN_CLIENT_KEY(&G1,&G2,PIN2,&R,&X,&HM,&T,&CK);      
-  printf("Client Key = "); 
-  OCT_output(&CK);
-
-  /* Server will use the hashed ID if anonymous connection required.
-  MPIN_HASH_ID(&ID,&HSID);
-  MPIN_HASH_ALL(&HSID,NULL,&UT,&SEC,&Y,&Z,&T,&HM);
-  */
-  MPIN_SERVER_KEY(&Z,&ServerSecret,&W,&HM,&HID,NULL,&UT,&SK);
-  printf("Server Key = "); 
-  OCT_output(&SK);
-
-  if (!OCT_comp(&CK,&SK)) {
-      printf("FAILURE Keys are different\n");
-      return 1;
-  }
-
-  printf("SUCCESS\n");
-  return 0;
-}
diff --git a/c/tests/test_mpinfullSingle.c b/c/tests/test_mpinfullSingle.c
deleted file mode 100755
index c2a657d..0000000
--- a/c/tests/test_mpinfullSingle.c
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
-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.
-*/
-
-/* Test M-Pin Full Single pass */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include "mpin.h"
-
-int main()
-{
-  int i,PIN1,PIN2,rtn,err;
-
-  char id[256];
-  octet ID = {0,sizeof(id),id};
-
-  char x[PGS],y1[PGS],y2[PGS];
-  octet X={sizeof(x), sizeof(x),x};
-  octet Y1={sizeof(y1),sizeof(y1),y1};
-  octet Y2={sizeof(y2),sizeof(y2),y2};
-
-  /* Master secret shares */
-  char ms1[PGS], ms2[PGS];
-  octet MS1={sizeof(ms1),sizeof(ms1),ms1};
-  octet MS2={sizeof(ms2),sizeof(ms2),ms2};
-
-  /* Hash values of client ID */
-  char hcid[32];
-  octet HCID={sizeof(hcid),sizeof(hcid), hcid};
-
-  /* Hash values of messages */
-  char hm[HASH_BYTES];
-  octet HM={sizeof(hm),sizeof(hm), hm};
-
-  /* Client secret and shares */
-  char cs1[2*PFS+1], cs2[2*PFS+1], sec[2*PFS+1];
-  octet SEC={sizeof(sec),sizeof(sec),sec};
-  octet CS1={sizeof(cs1),sizeof(cs1), cs1};
-  octet CS2={sizeof(cs2),sizeof(cs2), cs2};
-
-  /* Server secret and shares */
-  char ss1[4*PFS], ss2[4*PFS], serverSecret[4*PFS];
-  octet ServerSecret={sizeof(serverSecret),sizeof(serverSecret),serverSecret};
-  octet SS1={sizeof(ss1),sizeof(ss1),ss1};
-  octet SS2={sizeof(ss2),sizeof(ss2),ss2};
-
-  /* Time Permit and shares */
-  char tp1[2*PFS+1], tp2[2*PFS+1], tp[2*PFS+1];
-  octet TP={sizeof(tp),sizeof(tp),tp};
-  octet TP1={sizeof(tp1),sizeof(tp1),tp1};
-  octet TP2={sizeof(tp2),sizeof(tp2),tp2};
-
-  /* Token stored on device */
-  char token[2*PFS+1];
-  octet TOKEN={sizeof(token),sizeof(token),token};
-
-  /* Precomputed values stored on device */
-  char g1[12*PFS],g2[12*PFS];
-  octet G1={0,sizeof(g1),g1};
-  octet G2={0,sizeof(g2),g2};
-
-  char ut[2*PFS+1],u[2*PFS+1];
-  octet UT={sizeof(ut),sizeof(ut),ut};
-  octet U={sizeof(u),sizeof(u),u};
-
-  char hid[2*PFS+1],htid[2*PFS+1];
-  octet HID={0,sizeof(hid),hid};
-  octet HTID={0,sizeof(htid),htid};
-
-  char e[12*PFS], f[12*PFS];
-  octet E={sizeof(e),sizeof(e),e};
-  octet F={sizeof(f),sizeof(f),f};
-
-  char r[PGS],z[2*PFS+1],w[PGS],t[2*PFS+1];
-  char ck[PAS],sk[PAS];
-  octet R={0,sizeof(r),r};
-  octet Z={0,sizeof(z),z};
-  octet W={0,sizeof(w),w};
-  octet T={0,sizeof(t),t};
-  octet SK={0,sizeof(sk),sk};
-  octet CK={0,sizeof(ck),ck};
-
-  int TimeValue = 0;
-
-  PIN1 = 1234;
-  PIN2 = 1234;
-
-  /* Assign the End-User an ID */
-  char* user = "testuser@miracl.com";
-  OCT_jstring(&ID,user);
-  printf("CLIENT: ID %s\n", user);
-
-  int date = 0;
-  char seed[100] = {0};
-  octet SEED = {0,sizeof(seed),seed};
-  csprng RNG;
-
-  /* unrandom seed value! */
-  SEED.len=100;
-  for (i=0;i<100;i++) SEED.val[i]=i+1;
-
-  /* initialise random number generator */
-  MPIN_CREATE_CSPRNG(&RNG,&SEED);
-
-  /* Hash ID */
-  MPIN_HASH_ID(&ID,&HCID);
-  OCT_output(&HCID);
-
-  /* When set only send hashed IDs to server */
-  octet *pID;
-#ifdef USE_ANONYMOUS
-  pID = &HCID;
-#else
-  pID = &ID;
-#endif
-
-  /* Generate Client master secret for MIRACL and Customer */
-  rtn = MPIN_RANDOM_GENERATE(&RNG,&MS1);
-  if (rtn != 0) {
-      printf("MPIN_RANDOM_GENERATE(&RNG,&MS1) Error %d\n", rtn);
-      return 1;
-  }
-  rtn = MPIN_RANDOM_GENERATE(&RNG,&MS2);
-  if (rtn != 0) {
-      printf("MPIN_RANDOM_GENERATE(&RNG,&MS2) Error %d\n", rtn);
-      return 1;
-  }
-  printf("MASTER SECRET MIRACL:= 0x");
-  OCT_output(&MS1);
-  printf("MASTER SECRET CUSTOMER:= 0x");
-  OCT_output(&MS2);
-
-  /* Generate server secret shares */
-  rtn = MPIN_GET_SERVER_SECRET(&MS1,&SS1);
-  if (rtn != 0) {
-      printf("MPIN_GET_SERVER_SECRET(&MS1,&SS1) Error %d\n", rtn);
-      return 1;
-  }
-  rtn = MPIN_GET_SERVER_SECRET(&MS2,&SS2);
-  if (rtn != 0) {
-      printf("MPIN_GET_SERVER_SECRET(&MS2,&SS2) Error %d\n", rtn);
-      return 1;
-  }
-  printf("SS1 = 0x");
-  OCT_output(&SS1);
-  printf("SS2 = 0x");
-  OCT_output(&SS2);
-
-  /* Combine server secret share */
-  rtn = MPIN_RECOMBINE_G2(&SS1, &SS2, &ServerSecret);
-  if (rtn != 0) {
-      printf("MPIN_RECOMBINE_G2(&SS1, &SS2, &ServerSecret) Error %d\n", rtn);
-      return 1;
-  }
-  printf("ServerSecret = 0x");
-  OCT_output(&ServerSecret);
-
-  /* Generate client secret shares */
-  rtn = MPIN_GET_CLIENT_SECRET(&MS1,&HCID,&CS1);
-  if (rtn != 0) {
-      printf("MPIN_GET_CLIENT_SECRET(&MS1,&HCID,&CS1) Error %d\n", rtn);
-      return 1;
-  }
-  rtn = MPIN_GET_CLIENT_SECRET(&MS2,&HCID,&CS2);
-  if (rtn != 0) {
-      printf("MPIN_GET_CLIENT_SECRET(&MS2,&HCID,&CS2) Error %d\n", rtn);
-      return 1;
-  }
-  printf("CS1 = 0x");
-  OCT_output(&CS1);
-  printf("CS2 = 0x");
-  OCT_output(&CS2);
-
-  /* Combine client secret shares : TOKEN is the full client secret */
-  rtn = MPIN_RECOMBINE_G1(&CS1, &CS2, &TOKEN);
-  if (rtn != 0) {
-      printf("MPIN_RECOMBINE_G1(&CS1, &CS2, &TOKEN) Error %d\n", rtn);
-      return 1;
-  }
-  printf("Client Secret = 0x");
-  OCT_output(&TOKEN);
-
-  /* Generate Time Permit shares */
-  date = MPIN_today();
-  printf("Date %d \n", date);
-  rtn = MPIN_GET_CLIENT_PERMIT(date,&MS1,&HCID,&TP1);
-  if (rtn != 0) {
-      printf("MPIN_GET_CLIENT_PERMIT(date,&MS1,&HCID,&TP1) Error %d\n", rtn);
-      return 1;
-  }
-  rtn = MPIN_GET_CLIENT_PERMIT(date,&MS2,&HCID,&TP2);
-  if (rtn != 0) {
-      printf("MPIN_GET_CLIENT_PERMIT(date,&MS2,&HCID,&TP2) Error %d\n", rtn);
-      return 1;
-  }
-  printf("TP1 = 0x");
-  OCT_output(&TP1);
-  printf("TP2 = 0x");
-  OCT_output(&TP2);
-
-  /* Combine Time Permit shares */
-  rtn = MPIN_RECOMBINE_G1(&TP1, &TP2, &TP);
-  if (rtn != 0) {
-      printf("MPIN_RECOMBINE_G1(&TP1, &TP2, &TP) Error %d\n", rtn);
-      return 1;
-  }
-  printf("Time Permit = 0x");
-  OCT_output(&TP);
-
-  /* This encoding makes Time permit look random */
-  if (MPIN_ENCODING(&RNG,&TP)!=0) printf("Encoding error\n");
-  printf("Encoded Time Permit= "); OCT_output(&TP);
-  if (MPIN_DECODING(&TP)!=0) printf("Decoding error\n");
-  printf("Decoded Time Permit= "); OCT_output(&TP);
-
-  /* Client extracts PIN1 from secret to create Token */
-  rtn = MPIN_EXTRACT_PIN(&ID, PIN1, &TOKEN);
-  if (rtn != 0) {
-      printf("MPIN_EXTRACT_PIN( &ID, PIN, &TOKEN) Error %d\n", rtn);
-      return 1;
-  }
-  printf("Token = 0x");
-  OCT_output(&TOKEN);
-
-  /* Client precomputation */
-  MPIN_PRECOMPUTE(&TOKEN,&HCID,&G1,&G2);
-
-  /* Client  */
-  TimeValue = MPIN_GET_TIME();
-  printf("TimeValue %d \n", TimeValue);
-  rtn = MPIN_CLIENT(date,&ID,&RNG,&X,PIN2,&TOKEN,&SEC,NULL,&UT,&TP,NULL,TimeValue,&Y1);
-  if (rtn != 0) {
-      printf("MPIN_CLIENT ERROR %d\n", rtn);
-      return 1;
-  }
-  printf("Y1 = 0x");
-  OCT_output(&Y1);
-  printf("V = 0x");
-  OCT_output(&SEC);
-
-  /* Client sends Z=r.ID to Server */
-  MPIN_GET_G1_MULTIPLE(&RNG,1,&R,&HCID,&Z);
-
-  /* Server  */
-  rtn = MPIN_SERVER(date,&HID,&HTID,&Y2,&ServerSecret,NULL,&UT,&SEC,&E,&F,pID,NULL,TimeValue);
-
-  printf("Y2 = 0x");
-  OCT_output(&Y2);
-  if (rtn != 0) {
-      printf("FAILURE Invalid Token Error Code %d\n", rtn);
-      return 1;
-  } else {
-      printf("SUCCESS Error Code %d\n", rtn);
-  }
-
-  /* Server sends T=w.ID to client */
-  MPIN_GET_G1_MULTIPLE(&RNG,0,&W,&HTID,&T);
-  printf("T = 0x");
-  OCT_output(&T);
-
-  MPIN_HASH_ALL(&HCID,NULL,&UT,&SEC,&Y1,&Z,&T,&HM);  
-  MPIN_CLIENT_KEY(&G1,&G2,PIN2,&R,&X,&HM,&T,&CK);      
-  printf("Client Key = "); 
-  OCT_output(&CK);
-
-  MPIN_HASH_ALL(&HCID,NULL,&UT,&SEC,&Y2,&Z,&T,&HM);
-  MPIN_SERVER_KEY(&Z,&ServerSecret,&W,&HM,&HID,NULL,&UT,&SK);
-  printf("Server Key = "); 
-  OCT_output(&SK);
-
-  if (!OCT_comp(&CK,&SK)) {
-      printf("FAILURE Keys are different\n");
-      return 1;
-  }
-
-  printf("SUCCESS\n");
-  return 0;
-}
diff --git a/c/tests/test_mpinfull_random.c b/c/tests/test_mpinfull_random.c
deleted file mode 100755
index 1638464..0000000
--- a/c/tests/test_mpinfull_random.c
+++ /dev/null
@@ -1,349 +0,0 @@
-/*
-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.
-*/
-
-/* Test good token and correct PIN with D-TA */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include "config.h"
-#include "mpin.h"
-
-// Define PIN range:
-#define MAX_RANGE 10000
-
-void rand_str(char *dest, size_t length,csprng *RNG) {
-  BIG r;
-  char charset[] = "0123456789@.*"
-                   "abcdefghijklmnopqrstuvwxyz"
-                   "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
-  while (length-- > 0) {
-    BIG_random(r,RNG);
-    size_t index = r[0] % (sizeof charset);
-    *dest++ = charset[index];
-  }
-  *dest = '\0';
-}
-
-int main()
-{
-  int i,PIN1,PIN2,rtn,err,iter;
-
-  char id[256];
-  octet ID = {0,sizeof(id),id};
-
-  char x[PGS],y[PGS];
-  octet X={sizeof(x), sizeof(x),x};
-  octet Y={sizeof(y),sizeof(y),y};
-
-  /* Master secret shares */
-  char ms1[PGS], ms2[PGS];
-  octet MS1={sizeof(ms1),sizeof(ms1),ms1};
-  octet MS2={sizeof(ms2),sizeof(ms2),ms2};
-
-  /* Hash values of client ID */
-  char hcid[HASH_BYTES];
-  octet HCID={sizeof(hcid),sizeof(hcid), hcid};
-  char hsid[HASH_BYTES];
-  octet HSID={sizeof(hsid),sizeof(hsid), hsid};
-
-  /* Hash values of messages */
-  char hm[HASH_BYTES];
-  octet HM={sizeof(hm),sizeof(hm), hm};
-
-  /* Client secret and shares */
-  char cs1[2*PFS+1], cs2[2*PFS+1], sec[2*PFS+1];
-  octet SEC={sizeof(sec),sizeof(sec),sec};
-  octet CS1={sizeof(cs1),sizeof(cs1), cs1};
-  octet CS2={sizeof(cs2),sizeof(cs2), cs2};
-
-  /* Server secret and shares */
-  char ss1[4*PFS], ss2[4*PFS], serverSecret[4*PFS];
-  octet ServerSecret={sizeof(serverSecret),sizeof(serverSecret),serverSecret};
-  octet SS1={sizeof(ss1),sizeof(ss1),ss1};
-  octet SS2={sizeof(ss2),sizeof(ss2),ss2};
-
-  /* Time Permit and shares */
-  char tp1[2*PFS+1], tp2[2*PFS+1], tp[2*PFS+1];
-  octet TP={sizeof(tp),sizeof(tp),tp};
-  octet TP1={sizeof(tp1),sizeof(tp1),tp1};
-  octet TP2={sizeof(tp2),sizeof(tp2),tp2};
-
-  /* Token stored on computer */
-  char token[2*PFS+1];
-  octet TOKEN={sizeof(token),sizeof(token),token};
-
-  /* Precomputed values stored on device */
-  char g1[12*PFS],g2[12*PFS];
-  octet G1={0,sizeof(g1),g1};
-  octet G2={0,sizeof(g2),g2};
-
-  char ut[2*PFS+1],u[2*PFS+1];
-  octet UT={sizeof(ut),sizeof(ut),ut};
-  octet U={sizeof(u),sizeof(u),u};
-
-  char hid[2*PFS+1],htid[2*PFS+1];
-  octet HID={0,sizeof(hid),hid};
-  octet HTID={0,sizeof(htid),htid};
-
-  char e[12*PFS], f[12*PFS];
-  octet E={sizeof(e),sizeof(e),e};
-  octet F={sizeof(f),sizeof(f),f};
-
-  char r[PGS],z[2*PFS+1],w[PGS],t[2*PFS+1];
-  char ck[PAS],sk[PAS];
-  octet R={0,sizeof(r),r};
-  octet Z={0,sizeof(z),z};
-  octet W={0,sizeof(w),w};
-  octet T={0,sizeof(t),t};
-  octet SK={0,sizeof(sk),sk};
-  octet CK={0,sizeof(ck),ck};
-
-  octet *pID;
-
-  int date = 0;
-
-  unsigned long ran;
-  int byte_count = 32;
-  FILE *fp;
-  char seed[32] = {0};
-  octet SEED = {sizeof(seed),sizeof(seed),seed};
-  csprng RNG;
-#ifdef __linux__
-  fp = fopen("/dev/urandom", "r");
-  fread(&seed, 1, byte_count, fp);
-  fclose(fp);
-#else
-  /* non random seed value! */
-  time((time_t *)&ran);
-  SEED.val[0]=ran;
-  SEED.val[1]=ran>>8;
-  SEED.val[2]=ran>>16;
-  SEED.val[3]=ran>>24;
-  for (i=4;i<byte_count;i++) SEED.val[i]=i+1;
-#endif
-  printf("SEED 0x");
-  OCT_output(&SEED);
-
-  /* initialise random number generator */
-  MPIN_CREATE_CSPRNG(&RNG,&SEED);
-
-  for(iter=1; iter<nRandomTests+1; iter++)
-    {
-      /* Generate Client master secret for MIRACL and Customer */
-      rtn = MPIN_RANDOM_GENERATE(&RNG,&MS1);
-      if (rtn != 0) {
-          printf("MPIN_RANDOM_GENERATE(&RNG,&MS1) Error %d\n", rtn);
-          return 1;
-      }
-      rtn = MPIN_RANDOM_GENERATE(&RNG,&MS2);
-      if (rtn != 0) {
-          printf("MPIN_RANDOM_GENERATE(&RNG,&MS2) Error %d\n", rtn);
-          return 1;
-      }
-      printf("MASTER SECRET MIRACL:= 0x");
-      OCT_output(&MS1);
-      printf("MASTER SECRET CUSTOMER:= 0x");
-      OCT_output(&MS2);
-
-      /* Generate server secret shares */
-      rtn = MPIN_GET_SERVER_SECRET(&MS1,&SS1);
-      if (rtn != 0) {
-          printf("MPIN_GET_SERVER_SECRET(&MS1,&SS1) Error %d\n", rtn);
-          return 1;
-      }
-      rtn = MPIN_GET_SERVER_SECRET(&MS2,&SS2);
-      if (rtn != 0) {
-          printf("MPIN_GET_SERVER_SECRET(&MS2,&SS2) Error %d\n", rtn);
-          return 1;
-      }
-      printf("SS1 = 0x");
-      OCT_output(&SS1);
-      printf("SS2 = 0x");
-      OCT_output(&SS2);
-
-      /* Combine server secret share */
-      rtn = MPIN_RECOMBINE_G2(&SS1, &SS2, &ServerSecret);
-      if (rtn != 0) {
-          printf("MPIN_RECOMBINE_G2(&SS1, &SS2, &ServerSecret) Error %d\n", rtn);
-          return 1;
-      }
-      printf("ServerSecret = 0x");
-      OCT_output(&ServerSecret);
-
-      /* Assign the End-User an ID */
-      rand_str(id,256,&RNG);
-      OCT_jstring(&ID,id);
-      printf("CLIENT: ID %s\n", id);
-
-      srand(time(NULL));
-      PIN1 = rand()%MAX_RANGE; // Get random between 0 and MAX_RANGE
-      PIN2 = PIN1;
-      printf("PIN1 %d PIN2 %d\n", PIN1, PIN2);
-
-      /* Hash ID */
-      MPIN_HASH_ID(&ID,&HCID);
-      OCT_output(&HCID);
-
-      /* When set only send hashed IDs to server */
-#ifdef USE_ANONYMOUS
-      pID = &HCID;
-#else
-      pID = &ID;
-#endif
-
-      /* Generate client secret shares */
-      rtn = MPIN_GET_CLIENT_SECRET(&MS1,&HCID,&CS1);
-      if (rtn != 0) {
-          printf("MPIN_GET_CLIENT_SECRET(&MS1,&HCID,&CS1) Error %d\n", rtn);
-          return 1;
-      }
-      rtn = MPIN_GET_CLIENT_SECRET(&MS2,&HCID,&CS2);
-      if (rtn != 0) {
-          printf("MPIN_GET_CLIENT_SECRET(&MS2,&HCID,&CS2) Error %d\n", rtn);
-          return 1;
-      }
-      printf("CS1 = 0x");
-      OCT_output(&CS1);
-      printf("CS2 = 0x");
-      OCT_output(&CS2);
-
-      /* Combine client secret shares : TOKEN is the full client secret */
-      rtn = MPIN_RECOMBINE_G1(&CS1, &CS2, &TOKEN);
-      if (rtn != 0) {
-          printf("MPIN_RECOMBINE_G1(&CS1, &CS2, &TOKEN) Error %d\n", rtn);
-          return 1;
-      }
-      printf("Client Secret = 0x");
-      OCT_output(&TOKEN);
-
-      /* Generate Time Permit shares */
-      date = MPIN_today();
-      printf("Date %d \n", date);
-      rtn = MPIN_GET_CLIENT_PERMIT(date,&MS1,&HCID,&TP1);
-      if (rtn != 0) {
-          printf("MPIN_GET_CLIENT_PERMIT(date,&MS1,&HCID,&TP1) Error %d\n", rtn);
-          return 1;
-      }
-      rtn = MPIN_GET_CLIENT_PERMIT(date,&MS2,&HCID,&TP2);
-      if (rtn != 0) {
-          printf("MPIN_GET_CLIENT_PERMIT(date,&MS2,&HCID,&TP2) Error %d\n", rtn);
-          return 1;
-      }
-      printf("TP1 = 0x");
-      OCT_output(&TP1);
-      printf("TP2 = 0x");
-      OCT_output(&TP2);
-
-      /* Combine Time Permit shares */
-      rtn = MPIN_RECOMBINE_G1(&TP1, &TP2, &TP);
-      if (rtn != 0) {
-          printf("MPIN_RECOMBINE_G1(&TP1, &TP2, &TP) Error %d\n", rtn);
-          return 1;
-      }
-      printf("Time Permit = 0x");
-      OCT_output(&TP);
-
-      /* This encoding makes Time permit look random */
-      if (MPIN_ENCODING(&RNG,&TP)!=0) printf("Encoding error\n");
-      printf("Encoded Time Permit= "); OCT_output(&TP);
-      if (MPIN_DECODING(&TP)!=0) printf("Decoding error\n");
-      printf("Decoded Time Permit= "); OCT_output(&TP);
-
-      /* Client extracts PIN1 from secret to create Token */
-      rtn = MPIN_EXTRACT_PIN(&ID, PIN1, &TOKEN);
-      if (rtn != 0) {
-          printf("MPIN_EXTRACT_PIN( &ID, PIN, &TOKEN) Error %d\n", rtn);
-          return 1;
-      }
-      printf("Token = 0x");
-      OCT_output(&TOKEN);
-
-      /* Client precomputation */
-      MPIN_PRECOMPUTE(&TOKEN,&HCID,&G1,&G2);
-
-      /* Client first pass */
-      rtn = MPIN_CLIENT_1(date,&ID,&RNG,&X,PIN2,&TOKEN,&SEC,&U,&UT,&TP);
-      if (rtn != 0) {
-          printf("MPIN_CLIENT_1 ERROR %d\n", rtn);
-          return 1;
-      }
-
-      /* Client sends Z=r.ID to Server */
-      MPIN_GET_G1_MULTIPLE(&RNG,1,&R,&HCID,&Z);
-
-      /* 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. */
-      MPIN_SERVER_1(date,pID,&HID,&HTID);
-
-      /* Server generates Random number Y and sends it to Client */
-      rtn = MPIN_RANDOM_GENERATE(&RNG,&Y);
-      if (rtn != 0) {
-          printf("MPIN_RANDOM_GENERATE(&RNG,&Y) Error %d\n", rtn);
-          return 1;
-      }
-      printf("Y = 0x");
-      OCT_output(&Y);
-
-      /* Server sends T=w.ID to client */
-      MPIN_GET_G1_MULTIPLE(&RNG,0,&W,&HTID,&T);
-      printf("T = 0x");
-      OCT_output(&T);
-
-      /* Client second pass */
-      rtn = MPIN_CLIENT_2(&X,&Y,&SEC);
-      if (rtn != 0) {
-        printf("MPIN_CLIENT_2(&X,&Y,&SEC) Error %d\n", rtn);
-      }
-      printf("V = 0x");
-      OCT_output(&SEC);
-
-      /* Server second pass */
-      rtn = MPIN_SERVER_2(date,&HID,&HTID,&Y,&ServerSecret,&U,&UT,&SEC,&E,&F);
-      if (rtn != 0) {
-        err=MPIN_KANGAROO(&E,&F);
-        if (err==0) {
-          printf("FAILURE Invalid Token Error Code %d\n", rtn);
-        } else {
-          printf("FAILURE PIN Error %d, Error Code %d\n",err, rtn);
-        }
-      }
-
-      MPIN_HASH_ALL(&HCID,&U,&UT,&SEC,&Y,&Z,&T,&HM);  
-      MPIN_CLIENT_KEY(&G1,&G2,PIN2,&R,&X,&HM,&T,&CK);      
-      printf("Client Key = "); 
-      OCT_output(&CK);
-
-      /* Server will use the hashed ID if anonymous connection required.
-      MPIN_HASH_ID(&ID,&HSID);
-      MPIN_HASH_ALL(&HSID,NULL,&UT,&SEC,&Y,&Z,&T,&HM);
-      */
-      MPIN_SERVER_KEY(&Z,&ServerSecret,&W,&HM,&HID,NULL,&UT,&SK);
-      printf("Server Key = "); 
-      OCT_output(&SK);
-
-      if (!OCT_comp(&CK,&SK)) {
-          printf("Iteration %d FAILURE keys are different\n", iter);
-          return 1;
-      } else {
-          printf("Iteration %d SUCCESS\n\n", iter);
-      }
-    }
-  return 0;
-}
diff --git a/c/tests/test_rsa.c b/c/tests/test_rsa.c
deleted file mode 100755
index d2aa8a3..0000000
--- a/c/tests/test_rsa.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
-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.
-*/
-
-/* test driver and function exerciser for RSA API Functions */
-
-#include <stdio.h>
-#include <time.h>
-#include "rsa.h"
-
-int main()
-{
-  int i,bytes,res;
-  unsigned long ran;
-  char m[RFS],ml[RFS],c[RFS],e[RFS],raw[100];
-  rsa_public_key pub;
-  rsa_private_key priv;
-  csprng RNG;
-  octet M={0,sizeof(m),m};
-  octet ML={0,sizeof(ml),ml};
-  octet C={0,sizeof(c),c};
-  octet E={0,sizeof(e),e};
-  octet RAW={0,sizeof(raw),raw};
-
-  time((time_t *)&ran);
-
-  RAW.len=100;				/* fake random seed source */
-  RAW.val[0]=ran;
-  RAW.val[1]=ran>>8;
-  RAW.val[2]=ran>>16;
-  RAW.val[3]=ran>>24;
-  for (i=4;i<100;i++) RAW.val[i]=i;
-
-  RSA_CREATE_CSPRNG(&RNG,&RAW);   /* initialise strong RNG */
-
-  printf("Generating public/private key pair\n");
-  RSA_KEY_PAIR(&RNG,65537,&priv,&pub);
-
-  printf("Encrypting test string\n");
-  OCT_jstring(&M,(char *)"Hello World\n");
-  RSA_OAEP_ENCODE(&M,&RNG,NULL,&E); /* OAEP encode message m to e  */
-
-  RSA_ENCRYPT(&pub,&E,&C);     /* encrypt encoded message */
-  printf("Ciphertext= "); OCT_output(&C);
-
-  printf("Decrypting test string\n");
-  RSA_DECRYPT(&priv,&C,&ML);   /* ... and then decrypt it */
-
-  RSA_OAEP_DECODE(NULL,&ML);    /* decode it */
-  OCT_output_string(&ML);
-
-  if (!OCT_comp(&M,&ML))
-    {
-      printf("FAILURE RSA Encryption failed");
-      return 1;
-    }
-
-  OCT_clear(&M); OCT_clear(&ML);   /* clean up afterwards */
-  OCT_clear(&C); OCT_clear(&RAW); OCT_clear(&E);
-
-  RSA_KILL_CSPRNG(&RNG);
-
-  RSA_PRIVATE_KEY_KILL(&priv);
-
-  printf("SUCCESS\n");
-  return 0;
-}
diff --git a/c/tests/test_version.c b/c/tests/test_version.c
deleted file mode 100755
index a3f726c..0000000
--- a/c/tests/test_version.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
-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.
-*/
-
-/* Test version function */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "amcl.h"
-#include "config.h"
-#include "version.h"
-
-int main()
-{
-  char info[200] = {0};
-  version(info);
-  printf("%s\n", info);
-  return 0;
-}
diff --git a/c/tests/test_wcc.c b/c/tests/test_wcc.c
deleted file mode 100755
index d5204fa..0000000
--- a/c/tests/test_wcc.c
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
-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.
-*/
-
-/* Test WCC with and without time permits */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include "wcc.h"
-#include "utils.h"
-
-int main()
-{
-  int i,rtn;
-
-  /* Master secret */
-  char ms[PGS];
-  octet MS={sizeof(ms),sizeof(ms),ms};
-
-  // sender key
-  char akeyG1[2*PFS+1];
-  octet AKeyG1={0,sizeof(akeyG1), akeyG1};
-
-  // receiver key
-  char bkeyG2[4*PFS];
-  octet BKeyG2={0,sizeof(bkeyG2), bkeyG2};
-
-  char hv[HASH_BYTES],alice_id[256],bob_id[256];
-  octet HV={0,sizeof(hv),hv};
-
-  octet IdA={0,sizeof(alice_id),alice_id};
-  octet IdB={0,sizeof(bob_id),bob_id};
-
-  char x[PGS];
-  octet X={sizeof(x),sizeof(x),x};
-  char y[PGS];
-  octet Y={sizeof(y),sizeof(y),y};
-  char w[PGS];
-  octet W={sizeof(w),sizeof(w),w};
-  char pia[PGS];
-  octet PIA={sizeof(pia),sizeof(pia),pia};
-  char pib[PGS];
-  octet PIB={sizeof(pib),sizeof(pib),pib};
-
-  char pgg1[2*PFS+1];
-  octet PgG1={0,sizeof(pgg1), pgg1};
-
-  char pag1[2*PFS+1];
-  octet PaG1={0,sizeof(pag1), pag1};
-
-  char pbg2[4*PFS];
-  octet PbG2={0,sizeof(pbg2), pbg2};
-
-  char seed[32] = {0};
-  octet SEED = {0,sizeof(seed),seed};
-  csprng RNG;
-
-  char message1[256];
-  octet MESSAGE1 = {0, sizeof(message1), message1};
-  OCT_jstring(&MESSAGE1,"Hello Bob");
-
-  char t1[16];  // Tag
-  char t2[16];  // Tag
-  char k1[16];  // AES Key
-  char k2[16];  // AES Key
-  char iv[12]; // IV - Initialisation vector
-  char c[100];  // Ciphertext
-  char p[100];  // Recovered Plaintext
-  octet T1={sizeof(t1),sizeof(t1),t1};
-  octet T2={sizeof(t2),sizeof(t2),t2};
-  octet K1={0,sizeof(k1),k1};
-  octet K2={0,sizeof(k2),k2};
-  octet IV={0,sizeof(iv),iv};
-  octet C={0,sizeof(c),c};
-  octet P={0,sizeof(p),p};
-
-  int date;
-
-  int hashDoneOn = 1;
-  int hashDoneOff = 0;
-
-  date = 0;
-
-  /* unrandom seed value! */
-  SEED.len=32;
-  for (i=0;i<32;i++) SEED.val[i]=i+1;
-
-  /* initialise random number generator */
-  WCC_CREATE_CSPRNG(&RNG,&SEED);
-
-  /* TA: Generate master secret  */
-  rtn = WCC_RANDOM_GENERATE(&RNG,&MS);
-  if (rtn != 0) {
-      printf("TA WCC_RANDOM_GENERATE(&RNG,&MS) Error %d\n", rtn);
-      return 1;
-  }
-
-  // Alice's ID
-  OCT_jstring(&IdA,"alice@miracl.com");
-
-  // TA: Generate Alices's sender key
-  WCC_HASH_ID(&IdA,&HV);
-  rtn = WCC_GET_G1_MULTIPLE(hashDoneOn,&MS,&HV,&AKeyG1);
-  if (rtn != 0) {
-      printf("TA WCC_GET_G1_MULTIPLE() Error %d\n", rtn);
-      return 1;
-  }
-
-  // Bob's ID
-  OCT_jstring(&IdB,"bob@miracl.com");
-
-  // TA: Generate Bob's receiver key
-  WCC_HASH_ID(&IdB,&HV);
-  rtn = WCC_GET_G2_MULTIPLE(hashDoneOn,&MS,&HV,&BKeyG2);
-  if (rtn != 0) {
-      printf("TA WCC_GET_G2_MULTIPLE() Error %d\n", rtn);
-      return 1;
-  }
-
-  rtn = WCC_RANDOM_GENERATE(&RNG,&X);
-  if (rtn != 0) {
-      printf("Alice WCC_RANDOM_GENERATE(&RNG,&X) Error %d\n", rtn);
-      return 1;
-  }
-
-  rtn = WCC_GET_G1_MULTIPLE(hashDoneOff,&X,&IdA,&PaG1);
-  if (rtn != 0) {
-      printf("Alice WCC_GET_G1_MULTIPLE() Error %d\n", rtn);
-      return 1;
-  }
-
-  rtn = WCC_RANDOM_GENERATE(&RNG,&W);
-  if (rtn != 0) {
-      printf("Bob WCC_RANDOM_GENERATE(&RNG,&W) Error %d\n", rtn);
-      return 1;
-  }
-  rtn = WCC_GET_G1_MULTIPLE(hashDoneOff,&W,&IdA,&PgG1);
-  if (rtn != 0) {
-      printf("Bob WCC_GET_G1_MULTIPLE() Error %d\n", rtn);
-      return 1;
-  }
-
-  rtn = WCC_RANDOM_GENERATE(&RNG,&Y);
-  if (rtn != 0) {
-      printf("Bob WCC_RANDOM_GENERATE(&RNG,&Y) Error %d\n", rtn);
-      return 1;
-  }
-
-  rtn = WCC_GET_G2_MULTIPLE(hashDoneOff,&Y,&IdB,&PbG2);
-  if (rtn != 0) {
-      printf("Bob WCC_GET_G1_MULTIPLE() Error %d\n", rtn);
-      return 1;
-  }
-
-  // pia = Hq(PaG1,PbG2,PgG1,IdB)
-  WCC_Hq(&PaG1,&PbG2,&PgG1,&IdB,&PIA);
-
-  // pib = Hq(PbG2,PaG1,PgG1,IdA)
-  WCC_Hq(&PbG2,&PaG1,&PgG1,&IdA,&PIB);
-
-  // Bob calculates AES Key
-  WCC_RECEIVER_KEY(date, &Y, &W,  &PIA, &PIB,  &PaG1, &PgG1, &BKeyG2, NULL, &IdA, &K2);
-  if (rtn != 0) {
-      printf("Bob WCC_RECEIVER_KEY() Error %d\n", rtn);
-      return 1;
-  }
-
-  // pia = Hq(PaG1,PbG2,PgG1,IdB)
-  WCC_Hq(&PaG1,&PbG2,&PgG1,&IdB,&PIA);
-
-  // pib = Hq(PbG2,PaG1,PgG1,IdA)
-  WCC_Hq(&PbG2,&PaG1,&PgG1,&IdA,&PIB);
-
-  // Alice calculates AES Key
-  rtn = WCC_SENDER_KEY(date, &X, &PIA, &PIB, &PbG2, &PgG1, &AKeyG1, NULL, &IdB, &K1);
-  if (rtn != 0) {
-      printf("Alice WCC_SENDER_KEY() Error %d\n", rtn);
-      return 1;
-  }
-
-  if (!OCT_comp(&K1,&K2))
-    {
-      printf("FAILURE No Time Permit Test. OCT_comp(&K1,&K2)\n");
-      return 1;
-    }
-
-  WCC_KILL_CSPRNG(&RNG);
-
-  printf("SUCCESS\n");
-  return 0;
-}
diff --git a/c/tests/test_wcc_gcm.c b/c/tests/test_wcc_gcm.c
deleted file mode 100755
index 5cef3a9..0000000
--- a/c/tests/test_wcc_gcm.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
-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.
-*/
-
-#include <stdlib.h>
-#include <string.h>
-#include "amcl.h"
-#include "wcc.h"
-#include "utils.h"
-
-
-int main()
-{
-  char* KT="feffe9928665731c6d6a8f9467308308";
-  char* MT="d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39";
-  char* HT="feedfacedeadbeeffeedfacedeadbeefabaddad2";
-  char* NT="9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b";
-  // Tag should be 619cc5aefffe0bfa462af43c1699d050
-
-  int lenM=strlen(MT)/2;
-  int lenH=strlen(HT)/2;
-  int lenK=strlen(KT)/2;
-  int lenIV=strlen(NT)/2;
-
-  char t1[16];  // Tag
-  char t2[16];  // Tag
-  char k[16];   // AES Key
-  char h[64];   // Header - to be included in Authentication, but not encrypted
-  char iv[100]; // IV - Initialisation vector
-  char m[100];  // Plaintext to be encrypted/authenticated
-  char c[100];  // Ciphertext
-  char p[100];  // Recovered Plaintext
-  octet T1={sizeof(t1),sizeof(t1),t1};
-  octet T2={sizeof(t2),sizeof(t2),t2};
-  octet K={0,sizeof(k),k};
-  octet H={0,sizeof(h),h};
-  octet IV={0,sizeof(iv),iv};
-  octet M={0,sizeof(m),m};
-  octet C={0,sizeof(c),c};
-  octet P={0,sizeof(p),p};
-  M.len=lenM;
-  K.len=lenK;
-  H.len=lenH;
-  IV.len=lenIV;
-
-  hex2bytes(MT, m);
-  hex2bytes(HT, h);
-  hex2bytes(NT, iv);
-  hex2bytes(KT, k);
-
-  printf("Plaintext: ");
-  OCT_output(&M);
-  printf("\n");
-
-  WCC_AES_GCM_ENCRYPT(&K, &IV, &H, &M, &C, &T1);
-
-  printf("Ciphertext: ");
-  OCT_output(&C);
-  printf("\n");
-
-  printf("Encryption Tag: ");
-  OCT_output(&T1);
-  printf("\n");
-
-  WCC_AES_GCM_DECRYPT(&K, &IV, &H, &C, &P, &T2);
-
-  printf("Plaintext: ");
-  OCT_output(&P);
-  printf("\n");
-
-  printf("Decryption Tag: ");
-  OCT_output(&T2);
-  printf("\n");
-
-  if (!OCT_comp(&M,&P))
-    {
-      printf("FAILURE Decryption\n");
-      return 1;
-    }
-
-  if (!OCT_comp(&T1,&T2))
-    {
-      printf("FAILURE TAG mismatch\n");
-      return 1;
-    }
-
-  printf("SUCCESS\n");
-  return 0;
-}
-
diff --git a/c/tests/test_wcc_random.c b/c/tests/test_wcc_random.c
deleted file mode 100755
index 5749adf..0000000
--- a/c/tests/test_wcc_random.c
+++ /dev/null
@@ -1,469 +0,0 @@
-/*
-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.
-*/
-
-
-/* Test WCC with two TAs and time permits for random values */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include "config.h"
-#include "wcc.h"
-
-#define DEBUG
-
-void rand_str(char *dest, size_t length,csprng *RNG) {
-  BIG r;
-  char charset[] = "0123456789@.*"
-                   "abcdefghijklmnopqrstuvwxyz"
-                   "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
-  while (length-- > 0) {
-    BIG_random(r,RNG);
-    size_t index = r[0] % (sizeof charset);
-    *dest++ = charset[index];
-  }
-  *dest = '\0';
-}
-
-int main()
-{
-  int i,rtn,iter;
-
-  /* Master secret shares */
-  char ms1[PGS], ms2[PGS];
-  octet MS1={sizeof(ms1),sizeof(ms1),ms1};
-  octet MS2={sizeof(ms2),sizeof(ms2),ms2};
-
-  // Sender keys
-  char a1keyG1[2*PFS+1], a2keyG1[2*PFS+1];
-  octet A1KeyG1={0,sizeof(a1keyG1), a1keyG1};
-  octet A2KeyG1={0,sizeof(a2keyG1), a2keyG1};
-  char akeyG1[2*PFS+1];
-  octet AKeyG1={0,sizeof(akeyG1), akeyG1};
-
-  // Sender time permits
-  char a1TPG1[2*PFS+1], a2TPG1[2*PFS+1];
-  octet A1TPG1={sizeof(a1TPG1),sizeof(a1TPG1), a1TPG1};
-  octet A2TPG1={sizeof(a2TPG1),sizeof(a2TPG1), a2TPG1};
-  char aTPG1[2*PFS+1];
-  octet ATPG1={0,sizeof(aTPG1), aTPG1};
-
-  // Receiver keys
-  char b1keyG2[4*PFS], b2keyG2[4*PFS];
-  octet B1KeyG2={0,sizeof(b1keyG2), b1keyG2};
-  octet B2KeyG2={0,sizeof(b2keyG2), b2keyG2};
-  char bkeyG2[4*PFS];
-  octet BKeyG2={0,sizeof(bkeyG2), bkeyG2};
-
-  // Receiver time permits
-  char b1TPG2[4*PFS], b2TPG2[4*PFS];
-  octet B1TPG2={sizeof(b1TPG2),sizeof(b1TPG2), b1TPG2};
-  octet B2TPG2={sizeof(b2TPG2),sizeof(b2TPG2), b2TPG2};
-  char bTPG2[4*PFS];
-  octet BTPG2={0,sizeof(bTPG2), bTPG2};
-
-  char ahv[HASH_BYTES],alice_id[256],bhv[HASH_BYTES],bob_id[256];
-  octet AHV={0,sizeof(ahv),ahv};
-  octet BHV={0,sizeof(bhv),bhv};
-
-  octet IdA={0,sizeof(alice_id),alice_id};
-  octet IdB={0,sizeof(bob_id),bob_id};
-
-  char x[PGS];
-  octet X={sizeof(x),sizeof(x),x};
-  char y[PGS];
-  octet Y={sizeof(y),sizeof(y),y};
-  char w[PGS];
-  octet W={sizeof(w),sizeof(w),w};
-  char pia[PGS];
-  octet PIA={sizeof(pia),sizeof(pia),pia};
-  char pib[PGS];
-  octet PIB={sizeof(pib),sizeof(pib),pib};
-
-  char pgg1[2*PFS+1];
-  octet PgG1={0,sizeof(pgg1), pgg1};
-
-  char pag1[2*PFS+1];
-  octet PaG1={0,sizeof(pag1), pag1};
-
-  char pbg2[4*PFS];
-  octet PbG2={0,sizeof(pbg2), pbg2};
-
-  char message1[256];
-  char message2[256];
-  octet MESSAGE1 = {0, sizeof(message1), message1};
-  octet MESSAGE2 = {0, sizeof(message2), message2};
-
-  char t1[16];  // Tag
-  char t2[16];  // Tag
-  char k1[16];  // AES Key
-  char k2[16];  // AES Key
-  char iv[12]; // IV - Initialisation vector
-  char c[100];  // Ciphertext
-  char p[100];  // Recovered Plaintext
-  octet T1={sizeof(t1),sizeof(t1),t1};
-  octet T2={sizeof(t2),sizeof(t2),t2};
-  octet K1={0,sizeof(k1),k1};
-  octet K2={0,sizeof(k2),k2};
-  octet IV={0,sizeof(iv),iv};
-  octet C={0,sizeof(c),c};
-  octet P={0,sizeof(p),p};
-
-  int date;
-  date = WCC_today();
-  printf("Date %d \n", date);
-
-  int hashDoneOn = 1;
-  int hashDoneOff = 0;
-
-  OCT_jstring(&MESSAGE1,"Hello Bob");
-  OCT_jstring(&MESSAGE2,"Hello Alice");
-
-  unsigned long ran;
-  int byte_count = 32;
-  FILE *fp;
-  char seed[32] = {0};
-  octet SEED = {sizeof(seed),sizeof(seed),seed};
-  csprng RNG;
-
-#ifdef __linux__
-  size_t readSize;
-  fp = fopen("/dev/urandom", "r");
-  readSize = fread(&seed, 1, byte_count, fp);
-  fclose(fp);
-#else
-  /* non random seed value! */
-  time((time_t *)&ran);
-  SEED.val[0]=ran;
-  SEED.val[1]=ran>>8;
-  SEED.val[2]=ran>>16;
-  SEED.val[3]=ran>>24;
-  for (i=4;i<byte_count;i++) SEED.val[i]=i+1;
-#endif
-  printf("SEED 0x");
-  OCT_output(&SEED);
-
-  /* initialise random number generator */
-  WCC_CREATE_CSPRNG(&RNG,&SEED);
-
-  for(iter=1; iter<nRandomTests+1; iter++) {
-
-    /* Generate Client master secret for MIRACL and Customer */
-    rtn = WCC_RANDOM_GENERATE(&RNG,&MS1);
-    if (rtn != 0) {
-        printf("TA WCC_RANDOM_GENERATE(&RNG,&MS1) Error %d\n", rtn);
-        return 1;
-    }
-    rtn = WCC_RANDOM_GENERATE(&RNG,&MS2);
-    if (rtn != 0) {
-        printf("TA WCC_RANDOM_GENERATE(&RNG,&MS2) Error %d\n", rtn);
-        return 1;
-    }
-    printf("TA MASTER SECRET MIRACL: ");
-    OCT_output(&MS1);
-    printf("TA MASTER SECRET CUSTOMER: ");
-    OCT_output(&MS2);
-  
-    // Alice's ID
-    rand_str(alice_id,256,&RNG);
-    OCT_jstring(&IdA,alice_id);
-    printf("ALICE ID: %s\n", alice_id);
-
-     // TA: Generate Alice's sender key
-    WCC_HASH_ID(&IdA,&AHV);
-    rtn = WCC_GET_G1_MULTIPLE(hashDoneOn,&MS1,&AHV,&A1KeyG1);
-    if (rtn != 0) {
-        printf("TA WCC_GET_G1_MULTIPLE(hashDoneOn,&MS1,&AHV,&A1KeyG1) Error %d\n", rtn);
-        return 1;
-    }
-    rtn = WCC_GET_G1_MULTIPLE(hashDoneOn,&MS2,&AHV,&A2KeyG1);
-    if (rtn != 0) {
-        printf("TA WCC_GET_G1_MULTIPLE(hashDoneOn,&MS2,&AHV,&A2KeyG1) Error %d\n", rtn);
-        return 1;
-    }
-    printf("TA A1KeyG1: ");
-    OCT_output(&A1KeyG1);
-    printf("TA A2KeyG1: ");
-    OCT_output(&A2KeyG1);
-  
-    rtn = WCC_RECOMBINE_G1(&A1KeyG1, &A2KeyG1, &AKeyG1);
-    if (rtn != 0) {
-        printf("TA WCC_RECOMBINE_G1(&A1KeyG1, &A2KeyG1, &AKeyG1) Error %d\n", rtn);
-        return 1;
-    }
-    printf("TA Alice's sender key: ");
-    OCT_output(&AKeyG1);
-  
-    // TA: Generate Alice's G1 time permit
-    rtn = WCC_GET_G1_PERMIT(date,&MS1,&AHV,&A1TPG1);
-    if (rtn != 0) {
-        printf("TA WCC_GET_G1_PERMIT(date,&MS1,&AHV,&A1TPG1) Error %d\n", rtn);
-        return 1;
-    }
-    rtn = WCC_GET_G1_PERMIT(date,&MS2,&AHV,&A2TPG1);
-    if (rtn != 0) {
-        printf("TA WCC_GET_G1_PERMIT(date,&MS2,&AHV,&A2TPG1) Error %d\n", rtn);
-        return 1;
-    }
-    printf("TA A1TPG1: ");
-    OCT_output(&A1TPG1);
-    printf("TA A2TPG1: ");
-    OCT_output(&A2TPG1);
-  
-    rtn = WCC_RECOMBINE_G1(&A1TPG1, &A2TPG1, &ATPG1);
-    if (rtn != 0) {
-        printf("Alice WCC_RECOMBINE_G1(&A1TPG1, &A2TPG1, &ATPG1) Error %d\n", rtn);
-        return 1;
-    }
-    printf("TA Alice's sender time permit: ");
-    OCT_output(&ATPG1);
-  
-    // Bob's ID
-    rand_str(bob_id,256,&RNG);
-    OCT_jstring(&IdB,bob_id);
-    printf("BOB ID: %s\n", bob_id);
-  
-    // TA: Generate Bob's receiver key
-    WCC_HASH_ID(&IdB,&BHV);
-    rtn = WCC_GET_G2_MULTIPLE(hashDoneOn,&MS1,&BHV,&B1KeyG2);
-    if (rtn != 0) {
-        printf("TA WCC_GET_G2_MULTIPLE(hashDoneOn,&MS1,&BHV,&B1KeyG2) Error %d\n", rtn);
-        return 1;
-    }
-    rtn = WCC_GET_G2_MULTIPLE(hashDoneOn,&MS2,&BHV,&B2KeyG2);
-    if (rtn != 0) {
-        printf("Bob WCC_GET_G2_MULTIPLE(hashDoneOn,&MS2,&BHV,&B2KeyG2) Error %d\n", rtn);
-        return 1;
-    }
-    printf("TA B1KeyG2: ");
-    OCT_output(&B1KeyG2);
-    printf("TA B2KeyG2: ");
-    OCT_output(&B2KeyG2);
-  
-    rtn = WCC_RECOMBINE_G2(&B1KeyG2, &B2KeyG2, &BKeyG2);
-    if (rtn != 0) {
-        printf("Bob WCC_RECOMBINE_G2(&B1KeyG1, &B2KeyG1, &BKeyG2) Error %d\n", rtn);
-        return 1;
-    }
-    printf("TA Bob's receiver key: ");
-    OCT_output(&BKeyG2);
-  
-    // TA: Generate Bob's receiver time permit
-    rtn = WCC_GET_G2_PERMIT(date,&MS1,&BHV,&B1TPG2);
-    if (rtn != 0) {
-        printf("TA WCC_GET_G2_PERMIT(date,&MS1,&BHV,&B1TPG2) Error %d\n", rtn);
-        return 1;
-    }
-    rtn = WCC_GET_G2_PERMIT(date,&MS2,&BHV,&B2TPG2);
-    if (rtn != 0) {
-        printf("TA WCC_GET_G2_PERMIT(date,&MS2,&BHV,&B2TPG2) Error %d\n", rtn);
-        return 1;
-    }
-    printf("TA B1TPG2: ");
-    OCT_output(&B1TPG2);
-    printf("TA B2TPG2: ");
-    OCT_output(&B2TPG2);
-  
-    rtn = WCC_RECOMBINE_G2(&B1TPG2, &B2TPG2, &BTPG2);
-    if (rtn != 0) {
-        printf("Bob WCC_RECOMBINE_G2(&B1TPG2, &B2TPG2, &BTPG2) Error %d\n", rtn);
-        return 1;
-    }
-    printf("TA Bob's receiver time permit: ");
-    OCT_output(&BTPG2);
-    printf("\n");
-  
-    printf("Alice\n");
-  
-    rtn = WCC_RANDOM_GENERATE(&RNG,&X);
-    if (rtn != 0) {
-        printf("Alice WCC_RANDOM_GENERATE(&RNG,&X) Error %d\n", rtn);
-        return 1;
-    }
-  #ifdef DEBUG
-    printf("Alice X: ");
-    OCT_output(&X);
-    printf("\n");
-  #endif
-  
-    rtn = WCC_GET_G1_TPMULT(date,&X,&IdA,&PaG1);
-    if (rtn != 0) {
-        printf("Alice WCC_GET_G1_TPMULT(date,&X,&IdA,&PaG1) Error %d\n", rtn);
-        return 1;
-    }
-  
-    printf("Alice sends IdA and PaG1 to Bob\n\n");
-    printf("Alice IdA: "); 
-    OCT_output_string(&IdA); 
-    printf("\n");
-    printf("Alice PaG1: ");
-    OCT_output(&PaG1);
-    printf("\n");
-  
-    printf("Bob\n");
-  
-    rtn = WCC_RANDOM_GENERATE(&RNG,&W);
-    if (rtn != 0) {
-        printf("Bob WCC_RANDOM_GENERATE(&RNG,&W) Error %d\n", rtn);
-        return 1;
-    }
-  #ifdef DEBUG
-    printf("Bob W: ");
-    OCT_output(&W);
-    printf("\n");
-  #endif
-    rtn = WCC_GET_G1_TPMULT(date,&W,&IdA,&PgG1);
-    if (rtn != 0) {
-        printf("Bob WCC_GET_G1_TPMULT(date,&W,&IdA,&PgG1) Error %d\n", rtn);
-        return 1;
-    }
-  #ifdef DEBUG
-    printf("PgG1: ");
-    OCT_output(&PgG1);
-    printf("\n");
-  #endif
-  
-    rtn = WCC_RANDOM_GENERATE(&RNG,&Y);
-    if (rtn != 0) {
-        printf("Bob WCC_RANDOM_GENERATE(&RNG,&Y) Error %d\n", rtn);
-        return 1;
-    }
-  #ifdef DEBUG
-    printf("Bob Y: ");
-    OCT_output(&Y);
-    printf("\n");
-  #endif
-    rtn = WCC_GET_G2_TPMULT(date,&Y,&IdB,&PbG2);
-    if (rtn != 0) {
-        printf("Bob WCC_GET_G1_TPMULT(date,&Y,&IdB,&PbG2) Error %d\n", rtn);
-        return 1;
-    }
-  #ifdef DEBUG
-    printf("Bob PbG2: ");
-    OCT_output(&PbG2);
-    printf("\n");
-  #endif
-  
-    // pia = Hq(PaG1,PbG2,PgG1,IdB)
-    WCC_Hq(&PaG1,&PbG2,&PgG1,&IdB,&PIA);
-
-    // pib = Hq(PbG2,PaG1,PgG1,IdA)
-    WCC_Hq(&PbG2,&PaG1,&PgG1,&IdA,&PIB);
-  
-  #ifdef DEBUG
-    printf("Bob PIA: ");
-    OCT_output(&PIA);
-    printf("\n");
-    printf("Bob PIB: ");
-    OCT_output(&PIB);
-    printf("\n");
-  #endif
-  
-    // Bob calculates AES Key
-    WCC_RECEIVER_KEY(date, &Y, &W,  &PIA, &PIB,  &PaG1, &PgG1, &BKeyG2, &BTPG2, &IdA, &K2);
-    if (rtn != 0) {
-        printf("Bob WCC_RECEIVER_KEY() Error %d\n", rtn);
-        return 1;
-    }
-    printf("Bob AES Key: ");
-    OCT_output(&K2);
-  
-    printf("Bob sends IdB, PbG2 and PgG1 to Alice\n\n");
-    printf("Bob IdB: "); 
-    OCT_output_string(&IdB); 
-    printf("\n");
-    printf("Bob PbG2: ");
-    OCT_output(&PbG2);
-    printf("\n");
-    printf("Bob PgG1: ");
-    OCT_output(&PgG1);
-    printf("\n");
-  
-    printf("Alice\n");
-  
-    // pia = Hq(PaG1,PbG2,PgG1,IdB)
-    WCC_Hq(&PaG1,&PbG2,&PgG1,&IdB,&PIA);
-
-    // pib = Hq(PbG2,PaG1,PgG1,IdA)
-    WCC_Hq(&PbG2,&PaG1,&PgG1,&IdA,&PIB);
-  
-  #ifdef DEBUG
-    printf("Alice PIA: ");
-    OCT_output(&PIA);
-    printf("\n");
-    printf("Alice PIB: ");
-    OCT_output(&PIB);
-    printf("\n");
-  #endif
-  
-    // Alice calculates AES Key
-    rtn = WCC_SENDER_KEY(date, &X, &PIA, &PIB, &PbG2, &PgG1, &AKeyG1, &ATPG1, &IdB, &K1);
-    if (rtn != 0) {
-        printf("Alice WCC_SENDER_KEY() Error %d\n", rtn);
-        return 1;
-    }
-    printf("Alice AES Key: ");
-    OCT_output(&K1);
-  
-    // Send message
-    IV.len=12;
-    for (i=0;i<IV.len;i++)
-      IV.val[i]=i+1;
-    printf("Alice: IV ");
-    OCT_output(&IV);
-  
-    printf("Alice: Message to encrypt for Bob: ");
-    OCT_output_string(&MESSAGE1);
-    printf("\n");
-  
-    WCC_AES_GCM_ENCRYPT(&K1, &IV, &IdA, &MESSAGE1, &C, &T1);
-  
-    printf("Alice: Ciphertext: ");
-    OCT_output(&C);
-  
-    printf("Alice: Encryption Tag: ");
-    OCT_output(&T1);
-    printf("\n");
-  
-    WCC_AES_GCM_DECRYPT(&K2, &IV, &IdA, &C, &P, &T2);
-  
-    printf("Bob: Decrypted message received from Alice: ");
-    OCT_output_string(&P);
-    printf("\n");
-  
-    printf("Bob: Decryption Tag: ");
-    OCT_output(&T2);
-    printf("\n");
-  
-    if (!OCT_comp(&MESSAGE1,&P)) {
-        printf("FAILURE Decryption\n");
-        return 1;
-    }
-  
-    if (!OCT_comp(&T1,&T2)) {
-        printf("FAILURE TAG mismatch\n");
-        return 1;
-    }
-    printf("Iteration %d SUCCESS \n\n", iter);
-  }
-
-  WCC_KILL_CSPRNG(&RNG);
-  return 0;
-}
diff --git a/c/testwcc.c b/c/testwcc.c
deleted file mode 100755
index f01300d..0000000
--- a/c/testwcc.c
+++ /dev/null
@@ -1,340 +0,0 @@
-/*
-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.
-*/
-
-
-/* Demonstrate WCC with one TA and no time permits */
-
-/* Build executible after installation:
-   gcc -std=c99 -g testwcc.c -I/opt/amcl/include -L/opt/amcl/lib -lamcl -lwcc -o testwcc */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include "wcc.h"
-
-#define DEBUG
-
-int main()
-{
-  int i,rtn;
-
-  /* Master secret */
-  char ms[PGS];
-  octet MS={sizeof(ms),sizeof(ms),ms};
-
-  // sender keys
-  char akeyG1[2*PFS+1];
-  octet AKeyG1={0,sizeof(akeyG1), akeyG1};
-
-  // receiver keys
-  char bkeyG2[4*PFS];
-  octet BKeyG2={0,sizeof(bkeyG2), bkeyG2};
-
-  char hv[HASH_BYTES],alice_id[256],bob_id[256];
-  octet HV={0,sizeof(hv),hv};
-
-  octet IdA={0,sizeof(alice_id),alice_id};
-  octet IdB={0,sizeof(bob_id),bob_id};
-
-  char x[PGS];
-  octet X={sizeof(x),sizeof(x),x};
-  char y[PGS];
-  octet Y={sizeof(y),sizeof(y),y};
-  char w[PGS];
-  octet W={sizeof(w),sizeof(w),w};
-  char pia[PGS];
-  octet PIA={sizeof(pia),sizeof(pia),pia};
-  char pib[PGS];
-  octet PIB={sizeof(pib),sizeof(pib),pib};
-
-  char pgg1[2*PFS+1];
-  octet PgG1={0,sizeof(pgg1), pgg1};
-
-  char pag1[2*PFS+1];
-  octet PaG1={0,sizeof(pag1), pag1};
-
-  char pbg2[4*PFS];
-  octet PbG2={0,sizeof(pbg2), pbg2};
-
-  char seed[32] = {0};
-  octet SEED = {0,sizeof(seed),seed};
-  csprng RNG;
-
-  char message1[256];
-  octet MESSAGE1 = {0, sizeof(message1), message1};
-  OCT_jstring(&MESSAGE1,"Hello Bob");
-
-  char t1[16];  // Tag
-  char t2[16];  // Tag
-  char k1[16];  // AES Key
-  char k2[16];  // AES Key
-  char iv[12]; // IV - Initialisation vector
-  char c[100];  // Ciphertext
-  char p[100];  // Recovered Plaintext
-  octet T1={sizeof(t1),sizeof(t1),t1};
-  octet T2={sizeof(t2),sizeof(t2),t2};
-  octet K1={0,sizeof(k1),k1};
-  octet K2={0,sizeof(k2),k2};
-  octet IV={0,sizeof(iv),iv};
-  octet C={0,sizeof(c),c};
-  octet P={0,sizeof(p),p};
-
-  int date;
-
-  int hashDoneOn = 1;
-  int hashDoneOff = 0;
-
-  date = 0;
-#ifdef DEBUG
-  printf("Date %d \n", date);
-#endif
-
-  /* unrandom seed value! */
-  SEED.len=32;
-  for (i=0;i<32;i++) SEED.val[i]=i+1;
-#ifdef DEBUG
-  printf("SEED: ");
-  OCT_output(&SEED);
-  printf("\n");
-#endif
-
-  /* initialise random number generator */
-  WCC_CREATE_CSPRNG(&RNG,&SEED);
-
-  /* TA: Generate master secret  */
-  rtn = WCC_RANDOM_GENERATE(&RNG,&MS);
-  if (rtn != 0) {
-      printf("TA WCC_RANDOM_GENERATE(&RNG,&MS) Error %d\n", rtn);
-      return 1;
-  }
-#ifdef DEBUG
-  printf("TA MASTER SECRET: ");
-  OCT_output(&MS);
-  printf("\n");
-#endif
-
-  // Alice's ID
-  OCT_jstring(&IdA,"alice@miracl.com");
-
-  // TA: Generate Alices's sender key
-  WCC_HASH_ID(&IdA,&HV);
-  rtn = WCC_GET_G1_MULTIPLE(hashDoneOn,&MS,&HV,&AKeyG1);
-  if (rtn != 0) {
-      printf("TA WCC_GET_G1_MULTIPLE() Error %d\n", rtn);
-      return 1;
-  }
-#ifdef DEBUG
-  printf("TA Alice's sender key: ");
-  OCT_output(&AKeyG1);
-#endif
-
-  // Bob's ID
-  OCT_jstring(&IdB,"bob@miracl.com");
-
-  // TA: Generate Bob's receiver key
-  WCC_HASH_ID(&IdB,&HV);
-  rtn = WCC_GET_G2_MULTIPLE(hashDoneOn,&MS,&HV,&BKeyG2);
-  if (rtn != 0) {
-      printf("TA WCC_GET_G2_MULTIPLE() Error %d\n", rtn);
-      return 1;
-  }
-#ifdef DEBUG
-  printf("TA Bob's receiver key: ");
-  OCT_output(&BKeyG2);
-  printf("\n");
-#endif
-
-  printf("Alice\n");
-
-  rtn = WCC_RANDOM_GENERATE(&RNG,&X);
-  if (rtn != 0) {
-      printf("Alice WCC_RANDOM_GENERATE(&RNG,&X) Error %d\n", rtn);
-      return 1;
-  }
-#ifdef DEBUG
-  printf("Alice X: ");
-  OCT_output(&X);
-  printf("\n");
-#endif
-
-  rtn = WCC_GET_G1_MULTIPLE(hashDoneOff,&X,&IdA,&PaG1);
-  if (rtn != 0) {
-      printf("Alice WCC_GET_G1_MULTIPLE() Error %d\n", rtn);
-      return 1;
-  }
-
-  printf("Alice sends IdA and PaG1 to Bob\n\n");
-  printf("Alice IdA: "); 
-  OCT_output_string(&IdA); 
-  printf("\n");
-  printf("Alice PaG1: ");
-  OCT_output(&PaG1);
-  printf("\n");
-
-  printf("Bob\n");
-
-  rtn = WCC_RANDOM_GENERATE(&RNG,&W);
-  if (rtn != 0) {
-      printf("Bob WCC_RANDOM_GENERATE(&RNG,&W) Error %d\n", rtn);
-      return 1;
-  }
-#ifdef DEBUG
-  printf("Bob W: ");
-  OCT_output(&W);
-  printf("\n");
-#endif
-  rtn = WCC_GET_G1_MULTIPLE(hashDoneOff,&W,&IdA,&PgG1);
-  if (rtn != 0) {
-      printf("Bob WCC_GET_G1_MULTIPLE() Error %d\n", rtn);
-      return 1;
-  }
-#ifdef DEBUG
-  printf("PgG1: ");
-  OCT_output(&PgG1);
-  printf("\n");
-#endif
-
-  rtn = WCC_RANDOM_GENERATE(&RNG,&Y);
-  if (rtn != 0) {
-      printf("Bob WCC_RANDOM_GENERATE(&RNG,&Y) Error %d\n", rtn);
-      return 1;
-  }
-#ifdef DEBUG
-  printf("Bob Y: ");
-  OCT_output(&Y);
-  printf("\n");
-#endif
-  rtn = WCC_GET_G2_MULTIPLE(hashDoneOff,&Y,&IdB,&PbG2);
-  if (rtn != 0) {
-      printf("Bob WCC_GET_G1_MULTIPLE() Error %d\n", rtn);
-      return 1;
-  }
-#ifdef DEBUG
-  printf("Bob PbG2: ");
-  OCT_output(&PbG2);
-  printf("\n");
-#endif
-
-  // pia = Hq(PaG1,PbG2,PgG1,IdB)
-  WCC_Hq(&PaG1,&PbG2,&PgG1,&IdB,&PIA);
-
-  // pib = Hq(PbG2,PaG1,PgG1,IdA)
-  WCC_Hq(&PbG2,&PaG1,&PgG1,&IdA,&PIB);
-
-#ifdef DEBUG
-  printf("Bob PIA: ");
-  OCT_output(&PIA);
-  printf("\n");
-  printf("Bob PIB: ");
-  OCT_output(&PIB);
-  printf("\n");
-#endif
-
-  // Bob calculates AES Key
-  WCC_RECEIVER_KEY(date, &Y, &W,  &PIA, &PIB,  &PaG1, &PgG1, &BKeyG2, NULL, &IdA, &K2);
-  if (rtn != 0) {
-      printf("Bob WCC_RECEIVER_KEY() Error %d\n", rtn);
-      return 1;
-  }
-  printf("Bob AES Key: ");
-  OCT_output(&K2);
-
-  printf("Bob sends IdB, PbG2 and PgG1 to Alice\n\n");
-  printf("Bob IdB: "); 
-  OCT_output_string(&IdB); 
-  printf("\n");
-  printf("Bob PbG2: ");
-  OCT_output(&PbG2);
-  printf("\n");
-  printf("Bob PgG1: ");
-  OCT_output(&PgG1);
-  printf("\n");
-
-  printf("Alice\n");
-
-  // pia = Hq(PaG1,PbG2,PgG1,IdB)
-  WCC_Hq(&PaG1,&PbG2,&PgG1,&IdB,&PIA);
-
-  // pib = Hq(PbG2,PaG1,PgG1,IdA)
-  WCC_Hq(&PbG2,&PaG1,&PgG1,&IdA,&PIB);
-
-#ifdef DEBUG
-  printf("Alice PIA: ");
-  OCT_output(&PIA);
-  printf("\n");
-  printf("Alice PIB: ");
-  OCT_output(&PIB);
-  printf("\n");
-#endif
-
-  // Alice calculates AES Key
-  rtn = WCC_SENDER_KEY(date, &X, &PIA, &PIB, &PbG2, &PgG1, &AKeyG1, NULL, &IdB, &K1);
-  if (rtn != 0) {
-      printf("Alice WCC_SENDER_KEY() Error %d\n", rtn);
-      return 1;
-  }
-  printf("Alice AES Key: ");
-  OCT_output(&K1);
-
-
-  // Send message
-  IV.len=12;
-  for (i=0;i<IV.len;i++)
-    IV.val[i]=i+1;
-  printf("Alice: IV ");
-  OCT_output(&IV);
-
-  printf("Alice: Message to encrypt for Bob: ");
-  OCT_output_string(&MESSAGE1);
-  printf("\n");
-
-  WCC_AES_GCM_ENCRYPT(&K1, &IV, &IdA, &MESSAGE1, &C, &T1);
-
-  printf("Alice: Ciphertext: ");
-  OCT_output(&C);
-
-  printf("Alice: Encryption Tag: ");
-  OCT_output(&T1);
-  printf("\n");
-
-  WCC_AES_GCM_DECRYPT(&K2, &IV, &IdA, &C, &P, &T2);
-
-  printf("Bob: Decrypted message received from Alice: ");
-  OCT_output_string(&P);
-  printf("\n");
-
-  printf("Bob: Decryption Tag: ");
-  OCT_output(&T2);
-  printf("\n");
-
-  if (!OCT_comp(&MESSAGE1,&P)) {
-      printf("FAILURE Decryption\n");
-      return 1;
-  }
-
-  if (!OCT_comp(&T1,&T2)) {
-      printf("FAILURE TAG mismatch\n");
-      return 1;
-  }
-
-  WCC_KILL_CSPRNG(&RNG);
-
-  return 0;
-}
diff --git a/c/testwcc_dta.c b/c/testwcc_dta.c
deleted file mode 100755
index d05d70f..0000000
--- a/c/testwcc_dta.c
+++ /dev/null
@@ -1,438 +0,0 @@
-/*
-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.
-*/
-
-
-/* Demonstrate WCC with two TAs and time permits */
-
-/* Build executible after installation:
-   gcc -std=c99 -g testwcc_dta.c  -I/opt/amcl/include -L/opt/amcl/lib -lamcl -lwcc -o testwcc_dta */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include "mpin.h"
-#include "wcc.h"
-
-#define DEBUG
-
-int main()
-{
-  int i,rtn;
-
-  /* Master secret shares */
-  char ms1[PGS], ms2[PGS];
-  octet MS1={sizeof(ms1),sizeof(ms1),ms1};
-  octet MS2={sizeof(ms2),sizeof(ms2),ms2};
-
-  // Sender keys
-  char a1keyG1[2*PFS+1], a2keyG1[2*PFS+1];
-  octet A1KeyG1={0,sizeof(a1keyG1), a1keyG1};
-  octet A2KeyG1={0,sizeof(a2keyG1), a2keyG1};
-  char akeyG1[2*PFS+1];
-  octet AKeyG1={0,sizeof(akeyG1), akeyG1};
-
-  // Sender time permits
-  char a1TPG1[2*PFS+1], a2TPG1[2*PFS+1];
-  octet A1TPG1={sizeof(a1TPG1),sizeof(a1TPG1), a1TPG1};
-  octet A2TPG1={sizeof(a2TPG1),sizeof(a2TPG1), a2TPG1};
-  char aTPG1[2*PFS+1];
-  octet ATPG1={0,sizeof(aTPG1), aTPG1};
-
-  // Receiver keys
-  char b1keyG2[4*PFS], b2keyG2[4*PFS];
-  octet B1KeyG2={0,sizeof(b1keyG2), b1keyG2};
-  octet B2KeyG2={0,sizeof(b2keyG2), b2keyG2};
-  char bkeyG2[4*PFS];
-  octet BKeyG2={0,sizeof(bkeyG2), bkeyG2};
-
-  // Receiver time permits
-  char b1TPG2[4*PFS], b2TPG2[4*PFS];
-  octet B1TPG2={sizeof(b1TPG2),sizeof(b1TPG2), b1TPG2};
-  octet B2TPG2={sizeof(b2TPG2),sizeof(b2TPG2), b2TPG2};
-  char bTPG2[4*PFS];
-  octet BTPG2={0,sizeof(bTPG2), bTPG2};
-
-  char ahv[HASH_BYTES],alice_id[256],bhv[HASH_BYTES],bob_id[256];
-  octet AHV={0,sizeof(ahv),ahv};
-  octet BHV={0,sizeof(bhv),bhv};
-
-  octet IdA={0,sizeof(alice_id),alice_id};
-  octet IdB={0,sizeof(bob_id),bob_id};
-
-  char x[PGS];
-  octet X={sizeof(x),sizeof(x),x};
-  char y[PGS];
-  octet Y={sizeof(y),sizeof(y),y};
-  char w[PGS];
-  octet W={sizeof(w),sizeof(w),w};
-  char pia[PGS];
-  octet PIA={sizeof(pia),sizeof(pia),pia};
-  char pib[PGS];
-  octet PIB={sizeof(pib),sizeof(pib),pib};
-
-  char pgg1[2*PFS+1];
-  octet PgG1={0,sizeof(pgg1), pgg1};
-
-  char pag1[2*PFS+1];
-  octet PaG1={0,sizeof(pag1), pag1};
-
-  char pbg2[4*PFS];
-  octet PbG2={0,sizeof(pbg2), pbg2};
-
-  char seed[32] = {0};
-  octet SEED = {0,sizeof(seed),seed};
-  csprng RNG;
-
-  char message1[256];
-  char message2[256];
-  octet MESSAGE1 = {0, sizeof(message1), message1};
-  octet MESSAGE2 = {0, sizeof(message2), message2};
-
-  char t1[16];  // Tag
-  char t2[16];  // Tag
-  char k1[16];  // AES Key
-  char k2[16];  // AES Key
-  char iv[12]; // IV - Initialisation vector
-  char c[100];  // Ciphertext
-  char p[100];  // Recovered Plaintext
-  octet T1={sizeof(t1),sizeof(t1),t1};
-  octet T2={sizeof(t2),sizeof(t2),t2};
-  octet K1={0,sizeof(k1),k1};
-  octet K2={0,sizeof(k2),k2};
-  octet IV={0,sizeof(iv),iv};
-  octet C={0,sizeof(c),c};
-  octet P={0,sizeof(p),p};
-
-  int date;
-  date = WCC_today();
-  printf("Date %d \n", date);
-
-  int hashDoneOn = 1;
-  int hashDoneOff = 0;
-
-  OCT_jstring(&MESSAGE1,"Hello Bob");
-  OCT_jstring(&MESSAGE2,"Hello Alice");
-
-  /* unrandom seed value! */
-  SEED.len=32;
-  for (i=0;i<32;i++) SEED.val[i]=i+1;
-
-  /* initialise random number generator */
-  WCC_CREATE_CSPRNG(&RNG,&SEED);
-
-  /* Generate Client master secret for MIRACL and Customer */
-  rtn = WCC_RANDOM_GENERATE(&RNG,&MS1);
-  if (rtn != 0) {
-      printf("TA WCC_RANDOM_GENERATE(&RNG,&MS1) Error %d\n", rtn);
-      return 1;
-  }
-  rtn = WCC_RANDOM_GENERATE(&RNG,&MS2);
-  if (rtn != 0)
-    {
-      printf("TA WCC_RANDOM_GENERATE(&RNG,&MS2) Error %d\n", rtn);
-      return 1;
-    }
-  printf("TA MASTER SECRET MIRACL: ");
-  OCT_output(&MS1);
-  printf("TA MASTER SECRET CUSTOMER: ");
-  OCT_output(&MS2);
-
-  // Alice's ID
-  OCT_jstring(&IdA,"alice@miracl.com");
-
-  // TA: Generate Alice's sender key
-  WCC_HASH_ID(&IdA,&AHV);
-  rtn = WCC_GET_G1_MULTIPLE(hashDoneOn,&MS1,&AHV,&A1KeyG1);
-  if (rtn != 0) {
-      printf("TA WCC_GET_G1_MULTIPLE(hashDoneOn,&MS1,&AHV,&A1KeyG1) Error %d\n", rtn);
-      return 1;
-  }
-  rtn = WCC_GET_G1_MULTIPLE(hashDoneOn,&MS2,&AHV,&A2KeyG1);
-  if (rtn != 0) {
-      printf("TA WCC_GET_G1_MULTIPLE(hashDoneOn,&MS2,&AHV,&A2KeyG1) Error %d\n", rtn);
-      return 1;
-  }
-  printf("TA A1KeyG1: ");
-  OCT_output(&A1KeyG1);
-  printf("TA A2KeyG1: ");
-  OCT_output(&A2KeyG1);
-
-  rtn = WCC_RECOMBINE_G1(&A1KeyG1, &A2KeyG1, &AKeyG1);
-  if (rtn != 0) {
-      printf("TA WCC_RECOMBINE_G1(&A1KeyG1, &A2KeyG1, &AKeyG1) Error %d\n", rtn);
-      return 1;
-  }
-  printf("TA Alice's sender key: ");
-  OCT_output(&AKeyG1);
-
-  // TA: Generate Alice's G1 time permit
-  rtn = WCC_GET_G1_PERMIT(date,&MS1,&AHV,&A1TPG1);
-  if (rtn != 0) {
-      printf("TA WCC_GET_G1_PERMIT(date,&MS1,&AHV,&A1TPG1) Error %d\n", rtn);
-      return 1;
-  }
-  rtn = WCC_GET_G1_PERMIT(date,&MS2,&AHV,&A2TPG1);
-  if (rtn != 0) {
-      printf("TA WCC_GET_G1_PERMIT(date,&MS2,&AHV,&A2TPG1) Error %d\n", rtn);
-      return 1;
-  }
-  printf("TA A1TPG1: ");
-  OCT_output(&A1TPG1);
-  printf("TA A2TPG1: ");
-  OCT_output(&A2TPG1);
-
-  rtn = WCC_RECOMBINE_G1(&A1TPG1, &A2TPG1, &ATPG1);
-  if (rtn != 0) {
-      printf("Alice WCC_RECOMBINE_G1(&A1TPG1, &A2TPG1, &ATPG1) Error %d\n", rtn);
-      return 1;
-  }
-  printf("TA Alice's sender time permit: ");
-  OCT_output(&ATPG1);
-
-  // Bob's ID
-  OCT_jstring(&IdB,"bob@miracl.com");
-
-  // TA: Generate Bob's receiver key
-  WCC_HASH_ID(&IdB,&BHV);
-  rtn = WCC_GET_G2_MULTIPLE(hashDoneOn,&MS1,&BHV,&B1KeyG2);
-  if (rtn != 0) {
-      printf("TA WCC_GET_G2_MULTIPLE(hashDoneOn,&MS1,&BHV,&B1KeyG2) Error %d\n", rtn);
-      return 1;
-  }
-  rtn = WCC_GET_G2_MULTIPLE(hashDoneOn,&MS2,&BHV,&B2KeyG2);
-  if (rtn != 0) {
-      printf("Bob WCC_GET_G2_MULTIPLE(hashDoneOn,&MS2,&BHV,&B2KeyG2) Error %d\n", rtn);
-      return 1;
-  }
-  printf("TA B1KeyG2: ");
-  OCT_output(&B1KeyG2);
-  printf("TA B2KeyG2: ");
-  OCT_output(&B2KeyG2);
-
-  rtn = WCC_RECOMBINE_G2(&B1KeyG2, &B2KeyG2, &BKeyG2);
-  if (rtn != 0) {
-      printf("Bob WCC_RECOMBINE_G2(&B1KeyG1, &B2KeyG1, &BKeyG2) Error %d\n", rtn);
-      return 1;
-  }
-  printf("TA Bob's receiver key: ");
-  OCT_output(&BKeyG2);
-
-  // TA: Generate Bob's receiver time permit
-  rtn = WCC_GET_G2_PERMIT(date,&MS1,&BHV,&B1TPG2);
-  if (rtn != 0)
-    {
-      printf("TA WCC_GET_G2_PERMIT(date,&MS1,&BHV,&B1TPG2) Error %d\n", rtn);
-      return 1;
-    }
-  rtn = WCC_GET_G2_PERMIT(date,&MS2,&BHV,&B2TPG2);
-  if (rtn != 0) {
-      printf("TA WCC_GET_G2_PERMIT(date,&MS2,&BHV,&B2TPG2) Error %d\n", rtn);
-      return 1;
-  }
-  printf("TA B1TPG2: ");
-  OCT_output(&B1TPG2);
-  printf("TA B2TPG2: ");
-  OCT_output(&B2TPG2);
-
-  rtn = WCC_RECOMBINE_G2(&B1TPG2, &B2TPG2, &BTPG2);
-  if (rtn != 0) {
-      printf("Bob WCC_RECOMBINE_G2(&B1TPG2, &B2TPG2, &BTPG2) Error %d\n", rtn);
-      return 1;
-  }
-  printf("TA Bob's receiver time permit: ");
-  OCT_output(&BTPG2);
-  printf("\n");
-
-  printf("Alice\n");
-
-  rtn = WCC_RANDOM_GENERATE(&RNG,&X);
-  if (rtn != 0) {
-      printf("Alice WCC_RANDOM_GENERATE(&RNG,&X) Error %d\n", rtn);
-      return 1;
-  }
-#ifdef DEBUG
-  printf("Alice X: ");
-  OCT_output(&X);
-  printf("\n");
-#endif
-
-  rtn = WCC_GET_G1_TPMULT(date,&X,&IdA,&PaG1);
-  if (rtn != 0) {
-      printf("Alice WCC_GET_G1_TPMULT(date,&X,&IdA,&PaG1) Error %d\n", rtn);
-      return 1;
-  }
-
-  printf("Alice sends IdA and PaG1 to Bob\n\n");
-  printf("Alice IdA: "); 
-  OCT_output_string(&IdA); 
-  printf("\n");
-  printf("Alice PaG1: ");
-  OCT_output(&PaG1);
-  printf("\n");
-
-  printf("Bob\n");
-
-  rtn = WCC_RANDOM_GENERATE(&RNG,&W);
-  if (rtn != 0) {
-      printf("Bob WCC_RANDOM_GENERATE(&RNG,&W) Error %d\n", rtn);
-      return 1;
-  }
-#ifdef DEBUG
-  printf("Bob W: ");
-  OCT_output(&W);
-  printf("\n");
-#endif
-  rtn = WCC_GET_G1_TPMULT(date,&W,&IdA,&PgG1);
-  if (rtn != 0) {
-      printf("Bob WCC_GET_G1_TPMULT(date,&W,&IdA,&PgG1) Error %d\n", rtn);
-      return 1;
-  }
-#ifdef DEBUG
-  printf("PgG1: ");
-  OCT_output(&PgG1);
-  printf("\n");
-#endif
-
-  rtn = WCC_RANDOM_GENERATE(&RNG,&Y);
-  if (rtn != 0) {
-      printf("Bob WCC_RANDOM_GENERATE(&RNG,&Y) Error %d\n", rtn);
-      return 1;
-  }
-#ifdef DEBUG
-  printf("Bob Y: ");
-  OCT_output(&Y);
-  printf("\n");
-#endif
-  rtn = WCC_GET_G2_TPMULT(date,&Y,&IdB,&PbG2);
-  if (rtn != 0) {
-      printf("Bob WCC_GET_G1_TPMULT(date,&Y,&IdB,&PbG2) Error %d\n", rtn);
-      return 1;
-  }
-#ifdef DEBUG
-  printf("Bob PbG2: ");
-  OCT_output(&PbG2);
-  printf("\n");
-#endif
-
-  // pia = Hq(PaG1,PbG2,PgG1,IdB)
-  WCC_Hq(&PaG1,&PbG2,&PgG1,&IdB,&PIA);
-
-  // pib = Hq(PbG2,PaG1,PgG1,IdA)
-  WCC_Hq(&PbG2,&PaG1,&PgG1,&IdA,&PIB);
-
-#ifdef DEBUG
-  printf("Bob PIA: ");
-  OCT_output(&PIA);
-  printf("\n");
-  printf("Bob PIB: ");
-  OCT_output(&PIB);
-  printf("\n");
-#endif
-
-  // Bob calculates AES Key
-  WCC_RECEIVER_KEY(date, &Y, &W,  &PIA, &PIB,  &PaG1, &PgG1, &BKeyG2, &BTPG2, &IdA, &K2);
-  if (rtn != 0) {
-      printf("Bob WCC_RECEIVER_KEY() Error %d\n", rtn);
-      return 1;
-  }
-  printf("Bob AES Key: ");
-  OCT_output(&K2);
-
-  printf("Bob sends IdB, PbG2 and PgG1 to Alice\n\n");
-  printf("Bob IdB: "); 
-  OCT_output_string(&IdB); 
-  printf("\n");
-  printf("Bob PbG2: ");
-  OCT_output(&PbG2);
-  printf("\n");
-  printf("Bob PgG1: ");
-  OCT_output(&PgG1);
-  printf("\n");
-
-  printf("Alice\n");
-
-  // pia = Hq(PaG1,PbG2,PgG1,IdB)
-  WCC_Hq(&PaG1,&PbG2,&PgG1,&IdB,&PIA);
-
-  // pib = Hq(PbG2,PaG1,PgG1,IdA)
-  WCC_Hq(&PbG2,&PaG1,&PgG1,&IdA,&PIB);
-
-#ifdef DEBUG
-  printf("Alice PIA: ");
-  OCT_output(&PIA);
-  printf("\n");
-  printf("Alice PIB: ");
-  OCT_output(&PIB);
-  printf("\n");
-#endif
-
-  // Alice calculates AES Key
-  rtn = WCC_SENDER_KEY(date, &X, &PIA, &PIB, &PbG2, &PgG1, &AKeyG1, &ATPG1, &IdB, &K1);
-  if (rtn != 0) {
-      printf("Alice WCC_SENDER_KEY() Error %d\n", rtn);
-      return 1;
-  }
-  printf("Alice AES Key: ");
-  OCT_output(&K1);
-
-  // Send message
-  IV.len=12;
-  for (i=0;i<IV.len;i++)
-    IV.val[i]=i+1;
-  printf("Alice: IV ");
-  OCT_output(&IV);
-
-  printf("Alice: Message to encrypt for Bob: ");
-  OCT_output_string(&MESSAGE1);
-  printf("\n");
-
-  WCC_AES_GCM_ENCRYPT(&K1, &IV, &IdA, &MESSAGE1, &C, &T1);
-
-  printf("Alice: Ciphertext: ");
-  OCT_output(&C);
-
-  printf("Alice: Encryption Tag: ");
-  OCT_output(&T1);
-  printf("\n");
-
-  WCC_AES_GCM_DECRYPT(&K2, &IV, &IdA, &C, &P, &T2);
-
-  printf("Bob: Decrypted message received from Alice: ");
-  OCT_output_string(&P);
-  printf("\n");
-
-  printf("Bob: Decryption Tag: ");
-  OCT_output(&T2);
-  printf("\n");
-
-  if (!OCT_comp(&MESSAGE1,&P)) {
-      printf("FAILURE Decryption\n");
-      return 1;
-  }
-
-  if (!OCT_comp(&T1,&T2)) {
-      printf("FAILURE TAG mismatch\n");
-      return 1;
-  }
-
-  WCC_KILL_CSPRNG(&RNG);
-
-  return 0;
-}
diff --git a/c/testwcc_tp.c b/c/testwcc_tp.c
deleted file mode 100755
index 280fa85..0000000
--- a/c/testwcc_tp.c
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
-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.
-*/
-
-
-/* Demonstrate WCC with time permits */
-
-/* Build executible after installation:
-   gcc -std=c99 -g testwcc_dta.c  -I/opt/amcl/include -L/opt/amcl/lib -lamcl -lwcc -o testwcc_dta */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include "mpin.h"
-#include "wcc.h"
-
-#define DEBUG
-
-int main()
-{
-  int i,rtn;
-
-  /* Master secret shares */
-  char ms[PGS];
-  octet MS={sizeof(ms),sizeof(ms),ms};
-
-  // Sender key
-  char akeyG1[2*PFS+1];
-  octet AKeyG1={0,sizeof(akeyG1), akeyG1};
-
-  // Sender time permits
-  char aTPG1[2*PFS+1];
-  octet ATPG1={sizeof(aTPG1),sizeof(aTPG1), aTPG1};
-
-  // Receiver keys
-  char bkeyG2[4*PFS];
-  octet BKeyG2={0,sizeof(bkeyG2), bkeyG2};
-
-  // Receiver time permits
-  char bTPG2[4*PFS];
-  octet BTPG2={sizeof(bTPG2),sizeof(bTPG2), bTPG2};
-
-  char ahv[HASH_BYTES],alice_id[256],bhv[HASH_BYTES],bob_id[256];
-  octet AHV={0,sizeof(ahv),ahv};
-  octet BHV={0,sizeof(bhv),bhv};
-
-  octet IdA={0,sizeof(alice_id),alice_id};
-  octet IdB={0,sizeof(bob_id),bob_id};
-
-  char x[PGS];
-  octet X={sizeof(x),sizeof(x),x};
-  char y[PGS];
-  octet Y={sizeof(y),sizeof(y),y};
-  char w[PGS];
-  octet W={sizeof(w),sizeof(w),w};
-  char pia[PGS];
-  octet PIA={sizeof(pia),sizeof(pia),pia};
-  char pib[PGS];
-  octet PIB={sizeof(pib),sizeof(pib),pib};
-
-  char pgg1[2*PFS+1];
-  octet PgG1={0,sizeof(pgg1), pgg1};
-
-  char pag1[2*PFS+1];
-  octet PaG1={0,sizeof(pag1), pag1};
-
-  char pbg2[4*PFS];
-  octet PbG2={0,sizeof(pbg2), pbg2};
-
-  char seed[32] = {0};
-  octet SEED = {0,sizeof(seed),seed};
-  csprng RNG;
-
-  char message1[256];
-  char message2[256];
-  octet MESSAGE1 = {0, sizeof(message1), message1};
-  octet MESSAGE2 = {0, sizeof(message2), message2};
-
-  char t1[16];  // Tag
-  char t2[16];  // Tag
-  char k1[16];  // AES Key
-  char k2[16];  // AES Key
-  char iv[12]; // IV - Initialisation vector
-  char c[100];  // Ciphertext
-  char p[100];  // Recovered Plaintext
-  octet T1={sizeof(t1),sizeof(t1),t1};
-  octet T2={sizeof(t2),sizeof(t2),t2};
-  octet K1={0,sizeof(k1),k1};
-  octet K2={0,sizeof(k2),k2};
-  octet IV={0,sizeof(iv),iv};
-  octet C={0,sizeof(c),c};
-  octet P={0,sizeof(p),p};
-
-  int date;
-  date = WCC_today();
-  printf("Date %d \n", date);
-
-  int hashDoneOn = 1;
-  int hashDoneOff = 0;
-
-  OCT_jstring(&MESSAGE1,"Hello Bob");
-  OCT_jstring(&MESSAGE2,"Hello Alice");
-
-  /* unrandom seed value! */
-  SEED.len=32;
-  for (i=0;i<32;i++) SEED.val[i]=i+1;
-
-  /* initialise random number generator */
-  WCC_CREATE_CSPRNG(&RNG,&SEED);
-
-  /* Generate Client master secret for MIRACL and Customer */
-  rtn = WCC_RANDOM_GENERATE(&RNG,&MS);
-  if (rtn != 0) {
-      printf("TA WCC_RANDOM_GENERATE(&RNG,&MS) Error %d\n", rtn);
-      return 1;
-  }
-  printf("TA MASTER SECRET: ");
-  OCT_output(&MS);
-
-  // Alice's ID
-  OCT_jstring(&IdA,"alice@miracl.com");
-
-  // TA: Generate Alice's sender key
-  WCC_HASH_ID(&IdA,&AHV);
-  rtn = WCC_GET_G1_MULTIPLE(hashDoneOn,&MS,&AHV,&AKeyG1);
-  if (rtn != 0) {
-      printf("TA WCC_GET_G1_MULTIPLE(hashDoneOn,&MS,&AHV,&AKeyG1) Error %d\n", rtn);
-      return 1;
-  }
-  printf("TA Alice's sender key: ");
-  OCT_output(&AKeyG1);
-
-  // TA: Generate Alice's G1 time permit
-  rtn = WCC_GET_G1_PERMIT(date,&MS,&AHV,&ATPG1);
-  if (rtn != 0) {
-      printf("TA WCC_GET_G1_PERMIT(date,&MS,&AHV,&ATPG1) Error %d\n", rtn);
-      return 1;
-  }
-  printf("TA Alice's sender time permit: ");
-  OCT_output(&ATPG1);
-
-  // Bob's ID
-  OCT_jstring(&IdB,"bob@miracl.com");
-
-  // TA: Generate Bob's receiver key
-  WCC_HASH_ID(&IdB,&BHV);
-  rtn = WCC_GET_G2_MULTIPLE(hashDoneOn,&MS,&BHV,&BKeyG2);
-  if (rtn != 0) {
-      printf("TA WCC_GET_G2_MULTIPLE(hashDoneOn,&MS,&BHV,&BKeyG2) Error %d\n", rtn);
-      return 1;
-  }
-  printf("TA Bob's receiver key: ");
-  OCT_output(&BKeyG2);
-
-  // TA: Generate Bob's receiver time permit
-  rtn = WCC_GET_G2_PERMIT(date,&MS,&BHV,&BTPG2);
-  if (rtn != 0)
-    {
-      printf("TA WCC_GET_G2_PERMIT(date,&MS,&BHV,&BTPG2) Error %d\n", rtn);
-      return 1;
-    }
-  printf("TA Bob's receiver time permit: ");
-  OCT_output(&BTPG2);
-  printf("\n");
-
-  printf("Alice\n");
-
-  rtn = WCC_RANDOM_GENERATE(&RNG,&X);
-  if (rtn != 0) {
-      printf("Alice WCC_RANDOM_GENERATE(&RNG,&X) Error %d\n", rtn);
-      return 1;
-  }
-#ifdef DEBUG
-  printf("Alice X: ");
-  OCT_output(&X);
-  printf("\n");
-#endif
-
-  rtn = WCC_GET_G1_TPMULT(date,&X,&IdA,&PaG1);
-  if (rtn != 0) {
-      printf("Alice WCC_GET_G1_TPMULT(date,&X,&IdA,&PaG1) Error %d\n", rtn);
-      return 1;
-  }
-
-  printf("Alice sends IdA and PaG1 to Bob\n\n");
-  printf("Alice IdA: "); 
-  OCT_output_string(&IdA); 
-  printf("\n");
-  printf("Alice PaG1: ");
-  OCT_output(&PaG1);
-  printf("\n");
-
-  printf("Bob\n");
-
-  rtn = WCC_RANDOM_GENERATE(&RNG,&W);
-  if (rtn != 0) {
-      printf("Bob WCC_RANDOM_GENERATE(&RNG,&W) Error %d\n", rtn);
-      return 1;
-  }
-#ifdef DEBUG
-  printf("Bob W: ");
-  OCT_output(&W);
-  printf("\n");
-#endif
-  rtn = WCC_GET_G1_TPMULT(date,&W,&IdA,&PgG1);
-  if (rtn != 0) {
-      printf("Bob WCC_GET_G1_TPMULT(date,&W,&IdA,&PgG1) Error %d\n", rtn);
-      return 1;
-  }
-#ifdef DEBUG
-  printf("PgG1: ");
-  OCT_output(&PgG1);
-  printf("\n");
-#endif
-
-  rtn = WCC_RANDOM_GENERATE(&RNG,&Y);
-  if (rtn != 0) {
-      printf("Bob WCC_RANDOM_GENERATE(&RNG,&Y) Error %d\n", rtn);
-      return 1;
-  }
-#ifdef DEBUG
-  printf("Bob Y: ");
-  OCT_output(&Y);
-  printf("\n");
-#endif
-  rtn = WCC_GET_G2_TPMULT(date,&Y,&IdB,&PbG2);
-  if (rtn != 0) {
-      printf("Bob WCC_GET_G1_TPMULT(date,&Y,&IdB,&PbG2) Error %d\n", rtn);
-      return 1;
-  }
-#ifdef DEBUG
-  printf("Bob PbG2: ");
-  OCT_output(&PbG2);
-  printf("\n");
-#endif
-
-  // pia = Hq(PaG1,PbG2,PgG1,IdB)
-  WCC_Hq(&PaG1,&PbG2,&PgG1,&IdB,&PIA);
-
-  // pib = Hq(PbG2,PaG1,PgG1,IdA)
-  WCC_Hq(&PbG2,&PaG1,&PgG1,&IdA,&PIB);
-
-#ifdef DEBUG
-  printf("Bob PIA: ");
-  OCT_output(&PIA);
-  printf("\n");
-  printf("Bob PIB: ");
-  OCT_output(&PIB);
-  printf("\n");
-#endif
-
-  // Bob calculates AES Key
-  WCC_RECEIVER_KEY(date, &Y, &W,  &PIA, &PIB,  &PaG1, &PgG1, &BKeyG2, &BTPG2, &IdA, &K2);
-  if (rtn != 0) {
-      printf("Bob WCC_RECEIVER_KEY() Error %d\n", rtn);
-      return 1;
-  }
-  printf("Bob AES Key: ");
-  OCT_output(&K2);
-
-  printf("Bob sends IdB, PbG2 and PgG1 to Alice\n\n");
-  printf("Bob IdB: "); 
-  OCT_output_string(&IdB); 
-  printf("\n");
-  printf("Bob PbG2: ");
-  OCT_output(&PbG2);
-  printf("\n");
-  printf("Bob PgG1: ");
-  OCT_output(&PgG1);
-  printf("\n");
-
-  printf("Alice\n");
-
-  // pia = Hq(PaG1,PbG2,PgG1,IdB)
-  WCC_Hq(&PaG1,&PbG2,&PgG1,&IdB,&PIA);
-
-  // pib = Hq(PbG2,PaG1,PgG1,IdA)
-  WCC_Hq(&PbG2,&PaG1,&PgG1,&IdA,&PIB);
-
-#ifdef DEBUG
-  printf("Alice PIA: ");
-  OCT_output(&PIA);
-  printf("\n");
-  printf("Alice PIB: ");
-  OCT_output(&PIB);
-  printf("\n");
-#endif
-
-  // Alice calculates AES Key
-  rtn = WCC_SENDER_KEY(date, &X, &PIA, &PIB, &PbG2, &PgG1, &AKeyG1, &ATPG1, &IdB, &K1);
-  if (rtn != 0) {
-      printf("Alice WCC_SENDER_KEY() Error %d\n", rtn);
-      return 1;
-  }
-  printf("Alice AES Key: ");
-  OCT_output(&K1);
-
-  // Send message
-  IV.len=12;
-  for (i=0;i<IV.len;i++)
-    IV.val[i]=i+1;
-  printf("Alice: IV ");
-  OCT_output(&IV);
-
-  printf("Alice: Message to encrypt for Bob: ");
-  OCT_output_string(&MESSAGE1);
-  printf("\n");
-
-  WCC_AES_GCM_ENCRYPT(&K1, &IV, &IdA, &MESSAGE1, &C, &T1);
-
-  printf("Alice: Ciphertext: ");
-  OCT_output(&C);
-
-  printf("Alice: Encryption Tag: ");
-  OCT_output(&T1);
-  printf("\n");
-
-  WCC_AES_GCM_DECRYPT(&K2, &IV, &IdA, &C, &P, &T2);
-
-  printf("Bob: Decrypted message received from Alice: ");
-  OCT_output_string(&P);
-  printf("\n");
-
-  printf("Bob: Decryption Tag: ");
-  OCT_output(&T2);
-  printf("\n");
-
-  if (!OCT_comp(&MESSAGE1,&P)) {
-      printf("FAILURE Decryption\n");
-      return 1;
-  }
-
-  if (!OCT_comp(&T1,&T2)) {
-      printf("FAILURE TAG mismatch\n");
-      return 1;
-  }
-
-  WCC_KILL_CSPRNG(&RNG);
-
-  return 0;
-}
diff --git a/c/utils.c b/c/utils.c
deleted file mode 100755
index 592780e..0000000
--- a/c/utils.c
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
-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.
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "amcl.h"
-#include "utils.h"
-
-void hex2bytes(char *hex, char *bin)
-{
-  int i;
-  char v;
-  int len=strlen(hex);
-  for (i = 0; i < len/2; i++) {
-    char c = hex[2*i];
-    if (c >= '0' && c <= '9') {
-        v = c - '0';
-    } else if (c >= 'A' && c <= 'F') {
-        v = c - 'A' + 10;
-    } else if (c >= 'a' && c <= 'f') {
-        v = c - 'a' + 10;
-    } else {
-        v = 0;
-    }
-    v <<= 4;
-    c = hex[2*i + 1];
-    if (c >= '0' && c <= '9') {
-        v += c - '0';
-    } else if (c >= 'A' && c <= 'F') {
-        v += c - 'A' + 10;
-    } else if (c >= 'a' && c <= 'f') {
-        v += c - 'a' + 10;
-    } else {
-        v = 0;
-    }
-    bin[i] = v;
-  }
-}
-
-/*! \brief Generate a random six digit one time password
- *
- *  Generates a random six digit one time password
- *
- *  @param  RNG             random number generator
- *  @return OTP             One Time Password
- */
-int generateOTP(csprng* RNG)
-{
-  int OTP=0;
-
-  int i = 0;
-  int val = 0;
-  char byte[6] = {0};
-
-  /* Generate random 6 digit random value */
-  for (i=0;i<6;i++)
-    {
-       byte[i]=RAND_byte(RNG);
-       val = byte[i];
-       OTP = ((abs(val) % 10) * pow(10.0,i)) + OTP;
-    }
-
-  return OTP;
-}
-
-/*! \brief Generate a random Octet
- *
- *  Generate a random Octet
- *
- *  @param  RNG             random number generator
- *  @return randomValue     random Octet
- */
-void generateRandom(csprng *RNG,octet *randomValue)
-{
-  int i;
-  for (i=0;i<randomValue->len;i++)
-    randomValue->val[i]=RAND_byte(RNG);
-}
-
-
diff --git a/c/utils.h b/c/utils.h
deleted file mode 100755
index d1cbae0..0000000
--- a/c/utils.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
-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.
-*/
-
-#ifndef UTILS_H
-#define UTILS_H
-
-#include "amcl.h"
-#include <math.h>
-
-DLL_EXPORT void hex2bytes(char *hex, char *bin);
-DLL_EXPORT void generateRandom(csprng*, octet*);
-DLL_EXPORT int generateOTP(csprng*);
-
-#endif
diff --git a/c/version.c b/c/version.c
deleted file mode 100755
index 8c2d899..0000000
--- a/c/version.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
-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.
-*/
-
-#include "version.h"
-
-
-/*! \brief Print version number and information about the build
- *
- *  Print version number and information about the build
- *
- */
-void version(char* info)
-{
-  sprintf(info,"Version: %d.%d.%d OS: %s FIELD CHOICE: %s CURVE TYPE: %s WORD_LENGTH: %d", AMCL_VERSION_MAJOR, AMCL_VERSION_MINOR, AMCL_VERSION_PATCH, OS, FIELD_CHOICE, CURVE_TYPE, CHUNK);
-}
-
diff --git a/c/version.h b/c/version.h
deleted file mode 100755
index 18a899f..0000000
--- a/c/version.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
-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.
-*/
-
-#ifndef VERSION_H
-#define VERSION_H
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "amcl.h"
-
-DLL_EXPORT void version(char* info);
-
-#endif
diff --git a/c/wcc.c b/c/wcc.c
deleted file mode 100755
index c1c8a75..0000000
--- a/c/wcc.c
+++ /dev/null
@@ -1,823 +0,0 @@
-/*
-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.
-*/
-
-/**
- * @file wcc.c
- * @author Mike Scott and Kealan McCusker
- * @date 28th April 2016
- * @brief Wang / Chow Choo (WCC) definitions
- *
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include "wcc.h"
-
-// #define DEBUG
-
-/* general purpose hashing functions */
-static void start_hash(hash *sha)
-{
-  HASH_init(sha);
-}
-
-static void add_to_hash(hash *sha,octet *x)
-{
-  int i;
-  for (i=0;i<x->len;i++)
-  {
-    /*printf("%d,",(unsigned char)x->val[i]);*/
-    HASH_process(sha,x->val[i]);
-  }
-}
-
-static void finish_hash(hash *sha,octet *w)
-{
-  int i;
-  char hh[HASH_BYTES];
-  HASH_hash(sha,hh);
-
-  OCT_empty(w);
-  OCT_jbytes(w,hh,HASH_BYTES);
-  for (i=0;i<HASH_BYTES;i++) hh[i]=0;
-}
-
-/* map octet string to point on curve */
-static void mapit(octet *h,ECP *P)
-{
-  BIG q,px;
-  BIG_fromBytes(px,h->val);
-  BIG_rcopy(q,Modulus);
-  BIG_mod(px,q);
-
-  while (!ECP_setx(P,px,0))
-    BIG_inc(px,1);
-}
-
-/* maps to hash value to point on G2 */
-static void mapit2(octet *h,ECP2 *Q)
-{
-  BIG q,one,Fx,Fy,x,hv;
-  FP2 X;
-  ECP2 T,K;
-  BIG_fromBytes(hv,h->val);
-  BIG_rcopy(q,Modulus);
-  BIG_one(one);
-  BIG_mod(hv,q);
-
-  for (;;)
-  {
-    FP2_from_BIGs(&X,one,hv);
-    if (ECP2_setx(Q,&X)) break;
-    BIG_inc(hv,1);
-  }
-
-  /* Fast Hashing to G2 - Fuentes-Castaneda, Knapp and Rodriguez-Henriquez */
-  BIG_rcopy(Fx,CURVE_Fra);
-  BIG_rcopy(Fy,CURVE_Frb);
-  FP2_from_BIGs(&X,Fx,Fy);
-  BIG_rcopy(x,CURVE_Bnx);
-
-  ECP2_copy(&T,Q);
-  ECP2_mul(&T,x);
-  ECP2_neg(&T);  /* our x is negative */
-  ECP2_copy(&K,&T);
-  ECP2_dbl(&K);
-  ECP2_add(&K,&T);
-  ECP2_affine(&K);
-
-  ECP2_frob(&K,&X);
-  ECP2_frob(Q,&X); ECP2_frob(Q,&X); ECP2_frob(Q,&X);
-  ECP2_add(Q,&T);
-  ECP2_add(Q,&K);
-  ECP2_frob(&T,&X); ECP2_frob(&T,&X);
-  ECP2_add(Q,&T);
-  ECP2_affine(Q);
-}
-
-/* Hash number (optional) and octet to octet */
-static void hashit(int n,octet *x,octet *h)
-{
-  int i,c[4];
-  hash sha;
-  char hh[HASH_BYTES];
-  BIG px;
-
-  HASH_init(&sha);
-  if (n>0)
-  {
-    c[0]=(n>>24)&0xff;
-    c[1]=(n>>16)&0xff;
-    c[2]=(n>>8)&0xff;
-    c[3]=(n)&0xff;
-    for (i=0;i<4;i++) HASH_process(&sha,c[i]);
-  }
-  for (i=0;i<x->len;i++) HASH_process(&sha,x->val[i]);
-  HASH_hash(&sha,hh);
-  OCT_empty(h);
-  OCT_jbytes(h,hh,HASH_BYTES);
-  for (i=0;i<HASH_BYTES;i++) hh[i]=0;
-}
-
-
-/*! \brief Hash EC Points and Id to an integer 
- *
- *  Perform sha256 of EC Points and Id. Map to an integer modulus the 
- *  curve order
- * 
- *  <ol>
- *  <li> x = toInteger(sha256(A,B,C,D))
- *  <li> h = x % q where q is the curve order
- *  </ol>
- *
- *  @param  A        EC Point
- *  @param  B        EC Point
- *  @param  C        EC Point
- *  @param  D        Identity
- *  @return h        Integer
- */
-void WCC_Hq(octet *A,octet *B,octet *C,octet *D,octet *h)
-{
-  int i;
-  hash sha;
-  char hh[HASH_BYTES];
-  BIG q,hs;
-
-  BIG_rcopy(q,CURVE_Order);
-
-#ifdef DEBUG
-  printf("WCC_Hq: A: ");
-  OCT_output(A);
-  printf("\n");
-  printf("WCC_Hq: B: ");
-  OCT_output(B);
-  printf("\n");
-  printf("WCC_Hq: C: ");
-  OCT_output(C);
-  printf("\n");
-  printf("WCC_Hq: D: ");
-  OCT_output(D);
-  printf("\n");
-#endif
-
-  HASH_init(&sha);
-  for (i=0;i<A->len;i++) {
-    HASH_process(&sha,A->val[i]);
-  }
-
-  for (i=0;i<B->len;i++) {
-    HASH_process(&sha,B->val[i]);
-  }
-
-  for (i=0;i<C->len;i++) {
-    HASH_process(&sha,C->val[i]);
-  }
-
-  for (i=0;i<D->len;i++) {
-    HASH_process(&sha,D->val[i]);
-  }
-
-  HASH_hash(&sha,hh);
-
-  BIG_fromBytes(hs,hh);
-  BIG_mod(hs,q);
-  for (i=0;i<HASH_BYTES;i++) {
-    hh[i]=0;
-  }
-  BIG_toBytes(h->val,hs);
-  h->len=PGS;
-}
-
-/*! \brief Calculate value in G1 multiplied by an integer
- *
- *  Calculate a value in G1. VG1 = s*H1(ID) where ID is the identity.
- * 
- *  <ol>
- *  <li> VG1 = s*H1(ID)
- *  </ol>
- *
- *  @param  hashDone    ID value is already hashed if set to 1
- *  @param  S           integer modulus curve order
- *  @param  ID          ID value or sha256(ID)
- *  @param  VG1         EC point VG1 = s*H1(ID)
- *  @return rtn         Returns 0 if successful or else an error code  
- */
-int WCC_GET_G1_MULTIPLE(int hashDone, octet *S,octet *ID,octet *VG1)
-{
-  BIG s;
-  ECP P;
-  char h[HASH_BYTES];
-  octet H={0,sizeof(h),h};
-
-  if (hashDone) {
-    mapit(ID,&P);
-  } else {
-    hashit(0,ID,&H);
-    mapit(&H,&P);
-  }
-
-  BIG_fromBytes(s,S->val);
-  PAIR_G1mul(&P,s);
-
-  ECP_toOctet(VG1,&P);
-  return 0;
-}
-
-/*! \brief Calculate a value in G1 used for when time permits are enabled
- *
- *  Calculate a value in G1 used for when time permits are enabled
- * 
- *  <ol>
- *  <li> VG1 = s*H1(ID) + s*H1(date|sha256(ID))
- *  </ol>
- *
- *  @param  date        Epoch days
- *  @param  S           integer modulus curve order
- *  @param  ID          ID value or sha256(ID)
- *  @param  VG1         EC point in G1
- *  @return rtn         Returns 0 if successful or else an error code  
- */
-int WCC_GET_G1_TPMULT(int date, octet *S,octet *ID,octet *VG1)
-{
-  BIG s;
-  ECP P,Q;
-  char h1[HASH_BYTES];
-  octet H1={0,sizeof(h1),h1};
-  char h2[HASH_BYTES];
-  octet H2={0,sizeof(h2),h2};
-
-  // H1(ID)
-  hashit(0,ID,&H1);
-  mapit(&H1,&P);
-
-  // H1(date|sha256(ID))
-  hashit(date,&H1,&H2);
-  mapit(&H2,&Q);
-
-  // P = P + Q
-  ECP_add(&P,&Q);
-
-  // P = s(P+Q)
-  BIG_fromBytes(s,S->val);
-  PAIR_G1mul(&P,s);
-
-  ECP_toOctet(VG1,&P);
-  return 0;
-}
-
-/*! \brief Calculate a value in G2 used for when time permits are enabled
- *
- *  Calculate a value in G2 used for when time permits are enabled
- * 
- *  <ol>
- *  <li> VG2 = s*H1(ID) + s*H1(date|sha256(ID))
- *  </ol>
- *
- *  @param  date        Epoch days
- *  @param  S           integer modulus curve order
- *  @param  ID          ID value or sha256(ID)
- *  @param  VG2         EC point in G2
- *  @return rtn         Returns 0 if successful or else an error code  
- */
-int WCC_GET_G2_TPMULT(int date, octet *S,octet *ID,octet *VG2)
-{
-  BIG s;
-  ECP2 P,Q;
-  char h1[HASH_BYTES];
-  octet H1={0,sizeof(h1),h1};
-  char h2[HASH_BYTES];
-  octet H2={0,sizeof(h2),h2};
-
-  // H1(ID)
-  hashit(0,ID,&H1);
-  mapit2(&H1,&P);
-
-  // H1(date|sha256(ID))
-  hashit(date,&H1,&H2);
-  mapit2(&H2,&Q);
-
-  // P = P + Q
-  ECP2_add(&P,&Q);
-
-  // P = s(P+Q)
-  BIG_fromBytes(s,S->val);
-  PAIR_G2mul(&P,s);
-
-  ECP2_toOctet(VG2,&P);
-  return 0;
-}
-
-/*! \brief Calculate value in G2 multiplied by an integer
- *
- *  Calculate a value in G2. VG2 = s*H2(ID) where ID is the identity.
- * 
- *  <ol>
- *  <li> VG2 = s*H2(ID)
- *  </ol>
- *
- *  @param  hashDone  ID is value is already hashed if set to 1
- *  @param  S         integer modulus curve order
- *  @param  ID        ID Value or sha256(ID)
- *  @param  VG2       EC Point VG2 = s*H2(ID)
- *  @return rtn       Returns 0 if successful or else an error code  
- */
-int WCC_GET_G2_MULTIPLE(int hashDone, octet *S,octet *ID,octet *VG2)
-{
-  BIG s;
-  ECP2 P;
-  char h[HASH_BYTES];
-  octet H={0,sizeof(h),h};
-
-  if (hashDone) {
-    mapit2(ID,&P);
-  } else {
-    hashit(0,ID,&H);
-    mapit2(&H,&P);
-  }
-
-  BIG_fromBytes(s,S->val);
-  PAIR_G2mul(&P,s);
-
-  ECP2_toOctet(VG2,&P);
-  return 0;
-}
-
-/*! \brief Calculate time permit in G2 
- *
- *  Calculate time permit in G2. 
- * 
- *  <ol>
- *  <li> TPG2=s*H2(date|sha256(ID))
- *  </ol>
- *
- *  @param  date      Epoch days
- *  @param  S         Master secret
- *  @param  HID       sha256(ID)
- *  @param  TPG2      Time Permit in G2
- *  @return rtn       Returns 0 if successful or else an error code  
- */
-int WCC_GET_G2_PERMIT(int date,octet *S,octet *HID,octet *TPG2)
-{
-  BIG s;
-  ECP2 P;
-  char h[HASH_BYTES];
-  octet H={0,sizeof(h),h};
-
-  hashit(date,HID,&H);
-  mapit2(&H,&P);
-  BIG_fromBytes(s,S->val);
-  PAIR_G2mul(&P,s);
-
-  ECP2_toOctet(TPG2,&P);
-  return 0;
-}
-
-/*! \brief Calculate the sender AES key
- *
- *  Calculate the sender AES Key
- * 
- *  <ol>
- *  <li> j=e((x+pia).AKeyG1,pib.BG2+PbG2)
- *  <li> K=H(j,x.PgG1)
- *  </ol>
- *
- *  @param  date        Epoch days
- *  @param  xOct        Random x < q where q is the curve order
- *  @param  piaOct      Hq(PaG1,PbG2,PgG1)
- *  @param  pibOct      Hq(PbG2,PaG1,PgG1)
- *  @param  PbG2Oct     y.BG2 where y < q
- *  @param  PgG1Oct     w.AG1 where w < q
- *  @param  AKeyG1Oct   Sender key 
- *  @param  ATPG1Oct    Sender time permit 
- *  @param  IdBOct      Receiver identity
- *  @return AESKeyOct   AES key
- *  @return rtn         Returns 0 if successful or else an error code  
- */
-int WCC_SENDER_KEY(int date, octet *xOct, octet *piaOct, octet *pibOct, octet *PbG2Oct, octet *PgG1Oct, octet *AKeyG1Oct, octet *ATPG1Oct, octet *IdBOct, octet *AESKeyOct)
-{
-  ECP sAG1,ATPG1,PgG1;
-  ECP2 BG2,dateBG2,PbG2;
-  char hv1[HASH_BYTES],hv2[HASH_BYTES];
-  octet HV1={0,sizeof(hv1),hv1};
-  octet HV2={0,sizeof(hv2),hv2};
-
-  // Pairing outputs
-  FP12 g;
-  char pair[12*PFS];
-  octet PAIR={0,sizeof(pair),pair};
-
-  FP4 c;
-  BIG t,x,z,pia,pib;
-  char ht[HASH_BYTES];
-  octet HT={0,sizeof(ht),ht};
-  hash sha;
-  char xpgg1[2*PFS+1];
-  octet xPgG1Oct={0,sizeof(xpgg1), xpgg1};
-
-  BIG_fromBytes(x,xOct->val);
-  BIG_fromBytes(pia,piaOct->val);
-  BIG_fromBytes(pib,pibOct->val);
-
-  if (!ECP2_fromOctet(&PbG2,PbG2Oct)) {
-#ifdef DEBUG
-    printf("PbG2Oct Invalid Point: ");
-    OCT_output(PbG2Oct);
-    printf("\n");
-#endif
-    return WCC_INVALID_POINT;
-  }
-
-  if (!ECP_fromOctet(&PgG1,PgG1Oct)) {
-#ifdef DEBUG
-    printf("PgG1Oct Invalid Point: ");
-    OCT_output(PgG1Oct);
-    printf("\n");
-#endif
-    return WCC_INVALID_POINT;
-  }
-
-  hashit(0,IdBOct,&HV1);
-  mapit2(&HV1,&BG2);
-
-  if (!ECP_fromOctet(&sAG1,AKeyG1Oct)) {
-#ifdef DEBUG
-    printf("AKeyG1Oct Invalid Point: ");
-    OCT_output(AKeyG1Oct);
-    printf("\n");
-#endif
-    return WCC_INVALID_POINT;
-  }
-
-  // Use time permits
-  if (date)
-    {
-      // calculate e( (s*A+s*H(date|H(AID))) , (B+H(date|H(BID))) )
-      if (!ECP_fromOctet(&ATPG1,ATPG1Oct)) {
-#ifdef DEBUG
-        printf("ATPG1Oct Invalid Point: ");
-        OCT_output(ATPG1Oct);
-        printf("\n");
-        return WCC_INVALID_POINT;
-#endif
-      }
-
-      // H2(date|sha256(IdB))
-      hashit(date,&HV1,&HV2);
-      mapit2(&HV2,&dateBG2);
-
-      // sAG1 = sAG1 + ATPG1
-      ECP_add(&sAG1, &ATPG1);
-      // BG2 = BG2 + H(date|H(IdB))
-      ECP2_add(&BG2, &dateBG2);
-    }
-  // z =  x + pia
-  BIG_add(z,x,pia);
-
-  // (x+pia).AKeyG1
-  PAIR_G1mul(&sAG1,z);
-
-  // pib.BG2
-  PAIR_G2mul(&BG2,pib);
-
-  // pib.BG2+PbG2
-  ECP2_add(&BG2, &PbG2);
-
-  PAIR_ate(&g,&BG2,&sAG1);
-  PAIR_fexp(&g);
-  // printf("WCC_SENDER_KEY e(sAG1,BG2) = ");FP12_output(&g); printf("\n");
-
-  // x.PgG1
-  PAIR_G1mul(&PgG1,x);
-  ECP_toOctet(&xPgG1Oct,&PgG1);
-
-  // Generate AES Key : K=H(k,x.PgG1)
-  FP12_trace(&c,&g);
-  HT.len=HASH_BYTES;
-  start_hash(&sha);
-  BIG_copy(t,c.a.a); FP_redc(t); BIG_toBytes(&(HT.val[0]),t);
-  add_to_hash(&sha,&HT);
-  BIG_copy(t,c.a.b); FP_redc(t); BIG_toBytes(&(HT.val[0]),t);
-  add_to_hash(&sha,&HT);
-  BIG_copy(t,c.b.a); FP_redc(t); BIG_toBytes(&(HT.val[0]),t);
-  add_to_hash(&sha,&HT);
-  BIG_copy(t,c.b.b); FP_redc(t); BIG_toBytes(&(HT.val[0]),t);
-  add_to_hash(&sha,&HT);
-  add_to_hash(&sha,&xPgG1Oct);
-  finish_hash(&sha,&HT);
-  OCT_empty(AESKeyOct);
-  OCT_jbytes(AESKeyOct,HT.val,PAS);
-
-  return 0;
-}
-
-/*! \brief Calculate the receiver AES key
- *
- *  Calculate time permit in G2. 
- * 
- *  <ol>
- *  <li> j=e(pia.AG1+PaG1,(y+pib).BKeyG2)
- *  <li> K=H(j,w.PaG1)
- *  </ol>
- *
- *  @param  date        Epoch days
- *  @param  yOct        Random y < q where q is the curve order
- *  @param  wOct        Random w < q where q is the curve order
- *  @param  piaOct      Hq(PaG1,PbG2,PgG1)
- *  @param  pibOct      Hq(PbG2,PaG1,PgG1)
- *  @param  PaG1Oct     x.AG1 where x < q
- *  @param  PgG1Oct     w.AG1 where w < q
- *  @param  BKeyG2Oct   Receiver key 
- *  @param  BTPG2Oct    Receiver time permit 
- *  @param  IdAOct      Sender identity
- *  @return AESKeyOct   AES key
- *  @return rtn         Returns 0 if successful or else an error code  
- */
-int WCC_RECEIVER_KEY(int date, octet *yOct, octet *wOct,  octet *piaOct, octet *pibOct,  octet *PaG1Oct, octet *PgG1Oct, octet *BKeyG2Oct,octet *BTPG2Oct,  octet *IdAOct, octet *AESKeyOct)
-{
-  ECP AG1,dateAG1,PgG1,PaG1;
-  ECP2 sBG2,BTPG2;
-  char hv1[HASH_BYTES],hv2[HASH_BYTES];
-  octet HV1={0,sizeof(hv1),hv1};
-  octet HV2={0,sizeof(hv2),hv2};
-
-  // Pairing outputs
-  FP12 g;
-  char pair[12*PFS];
-  octet PAIR={0,sizeof(pair),pair};
-
-  FP4 c;
-  BIG t,w,y,pia,pib;;
-  char ht[HASH_BYTES];
-  octet HT={0,sizeof(ht),ht};
-  hash sha;
-  char wpag1[2*PFS+1];
-  octet wPaG1Oct={0,sizeof(wpag1), wpag1};
-  BIG_fromBytes(y,yOct->val);
-  BIG_fromBytes(w,wOct->val);
-  BIG_fromBytes(pia,piaOct->val);
-  BIG_fromBytes(pib,pibOct->val);
-
-  if (!ECP_fromOctet(&PaG1,PaG1Oct))
-    return WCC_INVALID_POINT;
-
-  if (!ECP_fromOctet(&PgG1,PgG1Oct))
-    return WCC_INVALID_POINT;
-
-  hashit(0,IdAOct,&HV1);
-  mapit(&HV1,&AG1);
-
-  if (!ECP2_fromOctet(&sBG2,BKeyG2Oct))
-    return WCC_INVALID_POINT;
-
-  if (date) {       
-    // Calculate e( (A+H(date|H(AID))) , (s*B+s*H(date|H(IdB))) )
-    if (!ECP2_fromOctet(&BTPG2,BTPG2Oct))   
-      return WCC_INVALID_POINT;
-
-    // H1(date|sha256(AID))
-    hashit(date,&HV1,&HV2);
-    mapit(&HV2,&dateAG1);
-
-    // sBG2 = sBG2 + TPG2
-    ECP2_add(&sBG2, &BTPG2);
-    // AG1 = AG1 + H(date|H(AID))
-    ECP_add(&AG1, &dateAG1);
-  }
-  // y =  y + pib
-  BIG_add(y,y,pib);
-
-  // (y+pib).BKeyG2
-  PAIR_G2mul(&sBG2,y);
-
-  // pia.AG1
-  PAIR_G1mul(&AG1,pia);
-
-  // pia.AG1+PaG1
-  ECP_add(&AG1, &PaG1);
-
-  PAIR_ate(&g,&sBG2,&AG1);
-  PAIR_fexp(&g);
-  // printf("WCC_RECEIVER_KEY e(AG1,sBG2) = ");FP12_output(&g); printf("\n");
-
-  // w.PaG1
-  PAIR_G1mul(&PaG1,w);
-  ECP_toOctet(&wPaG1Oct,&PaG1);
-
-  // Generate AES Key: K=H(k,w.PaG1)
-  FP12_trace(&c,&g);
-  HT.len=HASH_BYTES;
-  start_hash(&sha);
-  BIG_copy(t,c.a.a); FP_redc(t); BIG_toBytes(&(HT.val[0]),t);
-  add_to_hash(&sha,&HT);
-  BIG_copy(t,c.a.b); FP_redc(t); BIG_toBytes(&(HT.val[0]),t);
-  add_to_hash(&sha,&HT);
-  BIG_copy(t,c.b.a); FP_redc(t); BIG_toBytes(&(HT.val[0]),t);
-  add_to_hash(&sha,&HT);
-  BIG_copy(t,c.b.b); FP_redc(t); BIG_toBytes(&(HT.val[0]),t);
-  add_to_hash(&sha,&HT);
-  add_to_hash(&sha,&wPaG1Oct);
-  finish_hash(&sha,&HT);
-  OCT_empty(AESKeyOct);
-  OCT_jbytes(AESKeyOct,HT.val,PAS);
-
-  return 0;
-
-}
-
-/*! \brief Encrypt data using AES GCM
- *
- *  AES is run as a block cypher in the GCM  mode of operation. The key size is 128 bits.
- *  This function will encrypt any data length.
- *
- *  @param  K             128 bit secret key
- *  @param  IV            96 bit initialization vector
- *  @param  H             Additional authenticated data (AAD). This data is authenticated, but not encrypted.
- *  @param  P             Plaintext
- *  @return C             Ciphertext. It is the same length as the plaintext.
- *  @return T             128 bit authentication tag.
- */
-void WCC_AES_GCM_ENCRYPT(octet *K,octet *IV,octet *H,octet *P,octet *C,octet *T)
-{
-  gcm g;
-  GCM_init(&g,K->val,IV->len,IV->val);
-  GCM_add_header(&g,H->val,H->len);
-  GCM_add_plain(&g,C->val,P->val,P->len);
-  C->len=P->len;
-  GCM_finish(&g,T->val);
-  T->len=16;
-}
-
-/*! \brief Decrypt data using AES GCM
- *
- *  AES is run as a block cypher in the GCM  mode of operation. The key size is 128 bits.
- *  This function will decrypt any data length.
- *
- *  @param  K             128 bit secret key
- *  @param  IV            96 bit initialization vector
- *  @param  H             Additional authenticated data (AAD). This data is authenticated, but not encrypted.
- *  @param  C             Ciphertext.
- *  @return P             Decrypted data. It is the same length as the ciphertext.Plaintext
- *  @return T             128 bit authentication tag.
- */
-void WCC_AES_GCM_DECRYPT(octet *K,octet *IV,octet *H,octet *C,octet *P,octet *T)
-{
-  gcm g;
-  GCM_init(&g,K->val,IV->len,IV->val);
-  GCM_add_header(&g,H->val,H->len);
-  GCM_add_cipher(&g,P->val,C->val,C->len);
-  P->len=C->len;
-  GCM_finish(&g,T->val);
-  T->len=16;
-}
-
-/*!  \brief Get today's date as days from the epoch
- *
- *   @return today's date, as number of days elapsed since the epoch
- */
-unsign32 WCC_today(void)
-{
-  unsign32 ti=(unsign32)time(NULL);
-  return (long)(ti/(60*TIME_SLOT_MINUTES));
-}
-
-/*!  \brief Initialise a random number generator
- *
- *   @param RNG     cryptographically secure random number generator
- *   @param SEED    random seed value
- */
-void WCC_CREATE_CSPRNG(csprng *RNG,octet *SEED)
-{
-  RAND_seed(RNG,SEED->len,SEED->val);
-}
-
-/*!  \brief Kill a random number generator
- *   
- *   Deletes all internal state
- * 
- *   @param RNG    cryptographically secure random number generator
- */
-void WCC_KILL_CSPRNG(csprng *RNG)
-{
-  RAND_clean(RNG);
-}
-
-/*!  \brief Perform sha256
- *   
- *   Hash ID
- * 
- *   @param  ID     Value to hash
- *   @return HID    sha256 hashed value
- */
-void WCC_HASH_ID(octet *ID,octet *HID)
-{
-  hashit(0,ID,HID);
-}
-
-/*!  \brief Generate a random integer
- *   
- *   Generate a random number modulus the group order
- * 
- *   @param  RNG    cryptographically secure random number generator
- *   @return S      Random integer modulus the group order
- */
-int WCC_RANDOM_GENERATE(csprng *RNG,octet* S)
-{
-  BIG r,s;
-  BIG_rcopy(r,CURVE_Order);
-  BIG_randomnum(s,r,RNG);
-  BIG_toBytes(S->val,s);
-  S->len=PGS;
-  return 0;
-}
-
-
-/*! \brief Calculate time permit in G2 
- *
- *  Calculate time permit in G2. 
- * 
- *  <ol>
- *  <li> TPG1=s*H1(date|sha256(ID))
- *  </ol>
- *
- *  @param  date      Epoch days
- *  @param  S         Master secret
- *  @param  HID       sha256(ID)
- *  @param  TPG1      Time Permit in G1
- *  @return rtn       Returns 0 if successful or else an error code  
- */
-int WCC_GET_G1_PERMIT(int date,octet *S,octet *HID,octet *TPG1)
-{
-  BIG s;
-  ECP P;
-  char h[HASH_BYTES];
-  octet H={0,sizeof(h),h};
-
-  hashit(date,HID,&H);
-  mapit(&H,&P);
-  BIG_fromBytes(s,S->val);
-  PAIR_G1mul(&P,s);
-
-  ECP_toOctet(TPG1,&P);
-  return 0;
-}
-
-/*! \brief Add two members from the group G1
- *
- *   @param  R1      member of G1 
- *   @param  R2      member of G1 
- *   @return R       member of G1 = R1+R2
- *   @return         Returns 0 if successful or else an error code
- */
-int WCC_RECOMBINE_G1(octet *R1,octet *R2,octet *R)
-{
-  ECP P,T;
-  int res=0;
-  if (!ECP_fromOctet(&P,R1)) res=WCC_INVALID_POINT;
-  if (!ECP_fromOctet(&T,R2)) res=WCC_INVALID_POINT;
-  if (res==0)
-  {
-    ECP_add(&P,&T);
-    ECP_toOctet(R,&P);
-  }
-  return res;
-}
-
-/*! \brief Add two members from the group G2
- *
- *   @param  W1      member of G2 
- *   @param  W2      member of G2 
- *   @return W       member of G2 = W1+W2
- *   @return         Weturns 0 if successful or else an error code
- */
-int WCC_RECOMBINE_G2(octet *W1,octet *W2,octet *W)
-{
-  ECP2 Q,T;
-  int res=0;
-  if (!ECP2_fromOctet(&Q,W1)) res=WCC_INVALID_POINT;
-  if (!ECP2_fromOctet(&T,W2)) res=WCC_INVALID_POINT;
-  if (res==0)
-  {
-    ECP2_add(&Q,&T);
-    ECP2_toOctet(W,&Q);
-  }
-  return res;
-}
diff --git a/c/wcc.h b/c/wcc.h
deleted file mode 100755
index 893fe5d..0000000
--- a/c/wcc.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
-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.
-*/
-
-/**
- * @file wcc.h
- * @author Mike Scott and Kealan McCusker
- * @date 28th April 2016
- * @brief Wang / Chow Choo (WCC)  header file
- *
- * defines structures
- * declares functions
- *
- */
-
-#ifndef WCC_H
-#define WCC_H
-
-#include "amcl.h"
-
-/* Field size is assumed to be greater than or equal to group size */
-
-#define PGS 32  /* WCC Group Size */
-#define PFS 32  /* WCC Field Size */
-#define PAS 16  /* AES Symmetric Key Size */
-
-#define WCC_OK                     0
-#define WCC_INVALID_POINT         -51
-
-
-
-#define TIME_SLOT_MINUTES 1440 /* Time Slot = 1 day */
-#define HASH_BYTES 32
-
-/*! \brief Generate a random integer */
-DLL_EXPORT int WCC_RANDOM_GENERATE(csprng *RNG,octet* S);
-
-/*! \brief Hash EC Points and Id to an integer */
-DLL_EXPORT void WCC_Hq(octet *A,octet *B,octet *C,octet *D,octet *h);
-
-/*! \brief Calculate value in G2 multiplied by an integer */
-DLL_EXPORT int WCC_GET_G2_MULTIPLE(int hashDone,octet *S,octet *ID,octet *VG2);
-
-/*! \brief Calculate value in G1 multiplied by an integer */
-DLL_EXPORT int WCC_GET_G1_MULTIPLE(int hashDone,octet *S,octet *ID,octet *VG1);
-
-/*! \brief Calculate a value in G1 used for when time permits are enabled */
-DLL_EXPORT int WCC_GET_G1_TPMULT(int date, octet *S,octet *ID,octet *VG1);
-
-/*! \brief Calculate a value in G2 used for when time permits are enabled */
-DLL_EXPORT int WCC_GET_G2_TPMULT(int date, octet *S,octet *ID,octet *VG2);
-
-/*! \brief Calculate time permit in G2 */
-DLL_EXPORT int WCC_GET_G1_PERMIT(int date,octet *S,octet *HID,octet *G1TP);
-
-/*! \brief Calculate time permit in G2 */
-DLL_EXPORT int WCC_GET_G2_PERMIT(int date,octet *S,octet *HID,octet *G2TP);
-
-/*! \brief Calculate the sender AES key */
-DLL_EXPORT int WCC_SENDER_KEY(int date, octet *xOct, octet *piaOct, octet *pibOct, octet *PbG2Oct, octet *PgG1Oct, octet *AKeyG1Oct, octet *ATPG1Oct, octet *IdBOct, octet *AESKeyOct);
-
-/*! \brief Calculate the receiver AES key */
-DLL_EXPORT int WCC_RECEIVER_KEY(int date, octet *yOct, octet *wOct,  octet *piaOct, octet *pibOct,  octet *PaG1Oct, octet *PgG1Oct, octet *BKeyG2Oct,octet *BTPG2Oct,  octet *IdAOct, octet *AESKeyOct);
-
-/*! \brief Encrypt data using AES GCM */
-DLL_EXPORT void WCC_AES_GCM_ENCRYPT(octet *K,octet *IV,octet *H,octet *P,octet *C,octet *T);
-
-/*! \brief Decrypt data using AES GCM */
-DLL_EXPORT void WCC_AES_GCM_DECRYPT(octet *K,octet *IV,octet *H,octet *C,octet *P,octet *T);
-
-/*!  \brief Perform sha256 */
-DLL_EXPORT void WCC_HASH_ID(octet *,octet *);
-
-/*! \brief Add two members from the group G1 */
-DLL_EXPORT int WCC_RECOMBINE_G1(octet *,octet *,octet *);
-
-/*! \brief Add two members from the group G2 */
-DLL_EXPORT int WCC_RECOMBINE_G2(octet *,octet *,octet *);
-
-/*! \brief Get today's date as days from the epoch */
-DLL_EXPORT unsign32 WCC_today(void);
-
-/*! \brief Initialise a random number generator */
-DLL_EXPORT void WCC_CREATE_CSPRNG(csprng *,octet *);
-
-/*! \brief Kill a random number generator */
-DLL_EXPORT void WCC_KILL_CSPRNG(csprng *RNG);
-
-
-#endif
diff --git a/cmake_uninstall.cmake.in b/cmake_uninstall.cmake.in
deleted file mode 100644
index f633ef3..0000000
--- a/cmake_uninstall.cmake.in
+++ /dev/null
@@ -1,23 +0,0 @@
-cmake_policy(SET CMP0007 OLD)
-if (NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
-    message(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"")
-endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
-
-file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
-string(REGEX REPLACE "\n" ";" files "${files}")
-list(REVERSE files)
-foreach (file ${files})
-    message(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"")
-    if (EXISTS "$ENV{DESTDIR}${file}")
-        execute_process(
-            COMMAND @CMAKE_COMMAND@ -E remove "$ENV{DESTDIR}${file}"
-            OUTPUT_VARIABLE rm_out
-            RESULT_VARIABLE rm_retval
-        )
-        if(NOT ${rm_retval} EQUAL 0)
-            message(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"")
-        endif (NOT ${rm_retval} EQUAL 0)
-    else (EXISTS "$ENV{DESTDIR}${file}")
-        message(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.")
-    endif (EXISTS "$ENV{DESTDIR}${file}")
-endforeach(file)
diff --git a/cs/AES.cs b/cs/AES.cs
deleted file mode 100644
index 1b0d595..0000000
--- a/cs/AES.cs
+++ /dev/null
@@ -1,531 +0,0 @@
-/*
-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.
-*/
-
-/* AES Encryption */
-
-
-public class AES
-{
-	internal int mode;
-	private int[] fkey = new int[44];
-	private int[] rkey = new int[44];
-	public sbyte[] f = new sbyte[16];
-
-
-	public const int ECB = 0;
-	public const int CBC = 1;
-	public const int CFB1 = 2;
-	public const int CFB2 = 3;
-	public const int CFB4 = 5;
-	public const int OFB1 = 14;
-	public const int OFB2 = 15;
-	public const int OFB4 = 17;
-	public const int OFB8 = 21;
-	public const int OFB16 = 29;
-
-	private static readonly sbyte[] InCo = new sbyte[] {(sbyte)0xB,(sbyte)0xD,(sbyte)0x9,(sbyte)0xE}; // Inverse Coefficients
-
-	public const int KS = 16; // Key Size in bytes
-	public const int BS = 16; // Block Size
-
-	private static readonly sbyte[] ptab = new sbyte[] {(sbyte)1,(sbyte)3,(sbyte)5,(sbyte)15,(sbyte)17,(sbyte)51,(sbyte)85,unchecked((sbyte)255),(sbyte)26,(sbyte)46,(sbyte)114,unchecked((sbyte)150),unchecked((sbyte)161),unchecked((sbyte)248),(sbyte)19,(sbyte)53, (sbyte)95,unchecked((sbyte)225),(sbyte)56,(sbyte)72,unchecked((sbyte)216),(sbyte)115,unchecked((sbyte)149),unchecked((sbyte)164),unchecked((sbyte)247),(sbyte)2,(sbyte)6,(sbyte)10,(sbyte)30,(sbyte)34,(sbyte)102,unchecked((sbyte)170), unchecked((sbyte)229),(sbyte)52,(sbyte)92,unchecked((sbyte)228),(sbyte)55,(sbyte)89,unchecked((sbyte)235),(sbyte)38,(sbyte)106,unchecked((sbyte)190),unchecked((sbyte)217),(sbyte)112,unchecked((sbyte)144),unchecked((sbyte)171),unchecked((sbyte)230),(sbyte)49, (sbyte)83,unchecked((sbyte)245),(sbyte)4,(sbyte)12,(sbyte)20,(sbyte)60,(sbyte)68,unchecked((sbyte)204),(sbyte)79,unchecked((sbyte)209),(sbyte)104,unchecked((sbyte)184),unchecked((sbyte)211),(sbyte)110,unchecked((sbyte)178),unchecked((sbyte)205), (sbyte)76,unchecked((sbyte)212),(sbyte)103,unchecked((sbyte)169),unchecked((sbyte)224),(sbyte)59,(sbyte)77,unchecked((sbyte)215),(sbyte)98,unchecked((sbyte)166),unchecked((sbyte)241),(sbyte)8,(sbyte)24,(sbyte)40,(sbyte)120,unchecked((sbyte)136), unchecked((sbyte)131),unchecked((sbyte)158),unchecked((sbyte)185),unchecked((sbyte)208),(sbyte)107,unchecked((sbyte)189),unchecked((sbyte)220),(sbyte)127,unchecked((sbyte)129),unchecked((sbyte)152),unchecked((sbyte)179),unchecked((sbyte)206),(sbyte)73,unchecked((sbyte)219),(sbyte)118,unchecked((sbyte)154), unchecked((sbyte)181),unchecked((sbyte)196),(sbyte)87,unchecked((sbyte)249),(sbyte)16,(sbyte)48,(sbyte)80,unchecked((sbyte)240),(sbyte)11,(sbyte)29,(sbyte)39,(sbyte)105,unchecked((sbyte)187),unchecked((sbyte)214),(sbyte)97,unchecked((sbyte)163), unchecked((sbyte)254),(sbyte)25,(sbyte)43,(sbyte)125,unchecked((sbyte)135),unchecked((sbyte)146),unchecked((sbyte)173),unchecked((sbyte)236),(sbyte)47,(sbyte)113,unchecked((sbyte)147),unchecked((sbyte)174),unchecked((sbyte)233),(sbyte)32,(sbyte)96,unchecked((sbyte)160), unchecked((sbyte)251),(sbyte)22,(sbyte)58,(sbyte)78,unchecked((sbyte)210),(sbyte)109,unchecked((sbyte)183),unchecked((sbyte)194),(sbyte)93,unchecked((sbyte)231),(sbyte)50,(sbyte)86,unchecked((sbyte)250),(sbyte)21,(sbyte)63,(sbyte)65, unchecked((sbyte)195),(sbyte)94,unchecked((sbyte)226),(sbyte)61,(sbyte)71,unchecked((sbyte)201),(sbyte)64,unchecked((sbyte)192),(sbyte)91,unchecked((sbyte)237),(sbyte)44,(sbyte)116,unchecked((sbyte)156),unchecked((sbyte)191),unchecked((sbyte)218),(sbyte)117, unchecked((sbyte)159),unchecked((sbyte)186),unchecked((sbyte)213),(sbyte)100,unchecked((sbyte)172),unchecked((sbyte)239),(sbyte)42,(sbyte)126,unchecked((sbyte)130),unchecked((sbyte)157),unchecked((sbyte)188),unchecked((sbyte)223),(sbyte)122,unchecked((sbyte)142),unchecked((sbyte)137),unchecked((sbyte)128), unchecked((sbyte)155),unchecked((sbyte)182),unchecked((sbyte)193),(sbyte)88,unchecked((sbyte)232),(sbyte)35,(sbyte)101,unchecked((sbyte)175),unchecked((sbyte)234),(sbyte)37,(sbyte)111,unchecked((sbyte)177),unchecked((sbyte)200),(sbyte)67,unchecked((sbyte)197),(sbyte)84, unchecked((sbyte)252),(sbyte)31,(sbyte)33,(sbyte)99,unchecked((sbyte)165),unchecked((sbyte)244),(sbyte)7,(sbyte)9,(sbyte)27,(sbyte)45,(sbyte)119,unchecked((sbyte)153),unchecked((sbyte)176),unchecked((sbyte)203),(sbyte)70,unchecked((sbyte)202), (sbyte)69,unchecked((sbyte)207),(sbyte)74,unchecked((sbyte)222),(sbyte)121,unchecked((sbyte)139),unchecked((sbyte)134),unchecked((sbyte)145),unchecked((sbyte)168),unchecked((sbyte)227),(sbyte)62,(sbyte)66,unchecked((sbyte)198),(sbyte)81,unchecked((sbyte)243),(sbyte)14, (sbyte)18,(sbyte)54,(sbyte)90,unchecked((sbyte)238),(sbyte)41,(sbyte)123,unchecked((sbyte)141),unchecked((sbyte)140),unchecked((sbyte)143),unchecked((sbyte)138),unchecked((sbyte)133),unchecked((sbyte)148),unchecked((sbyte)167),unchecked((sbyte)242),(sbyte)13,(sbyte)23, (sbyte)57,(sbyte)75,unchecked((sbyte)221),(sbyte)124,unchecked((sbyte)132),unchecked((sbyte)151),unchecked((sbyte)162),unchecked((sbyte)253),(sbyte)28,(sbyte)36,(sbyte)108,unchecked((sbyte)180),unchecked((sbyte)199),(sbyte)82,unchecked((sbyte)246),(sbyte)1};
-
-	private static readonly sbyte[] ltab = new sbyte[] {(sbyte)0,unchecked((sbyte)255),(sbyte)25,(sbyte)1,(sbyte)50,(sbyte)2,(sbyte)26,unchecked((sbyte)198),(sbyte)75,unchecked((sbyte)199),(sbyte)27,(sbyte)104,(sbyte)51,unchecked((sbyte)238),unchecked((sbyte)223),(sbyte)3, (sbyte)100,(sbyte)4,unchecked((sbyte)224),(sbyte)14,(sbyte)52,unchecked((sbyte)141),unchecked((sbyte)129),unchecked((sbyte)239),(sbyte)76,(sbyte)113,(sbyte)8,unchecked((sbyte)200),unchecked((sbyte)248),(sbyte)105,(sbyte)28,unchecked((sbyte)193), (sbyte)125,unchecked((sbyte)194),(sbyte)29,unchecked((sbyte)181),unchecked((sbyte)249),unchecked((sbyte)185),(sbyte)39,(sbyte)106,(sbyte)77,unchecked((sbyte)228),unchecked((sbyte)166),(sbyte)114,unchecked((sbyte)154),unchecked((sbyte)201),(sbyte)9,(sbyte)120, (sbyte)101,(sbyte)47,unchecked((sbyte)138),(sbyte)5,(sbyte)33,(sbyte)15,unchecked((sbyte)225),(sbyte)36,(sbyte)18,unchecked((sbyte)240),unchecked((sbyte)130),(sbyte)69,(sbyte)53,unchecked((sbyte)147),unchecked((sbyte)218),unchecked((sbyte)142), unchecked((sbyte)150),unchecked((sbyte)143),unchecked((sbyte)219),unchecked((sbyte)189),(sbyte)54,unchecked((sbyte)208),unchecked((sbyte)206),unchecked((sbyte)148),(sbyte)19,(sbyte)92,unchecked((sbyte)210),unchecked((sbyte)241),(sbyte)64,(sbyte)70,unchecked((sbyte)131),(sbyte)56, (sbyte)102,unchecked((sbyte)221),unchecked((sbyte)253),(sbyte)48,unchecked((sbyte)191),(sbyte)6,unchecked((sbyte)139),(sbyte)98,unchecked((sbyte)179),(sbyte)37,unchecked((sbyte)226),unchecked((sbyte)152),(sbyte)34,unchecked((sbyte)136),unchecked((sbyte)145),(sbyte)16, (sbyte)126,(sbyte)110,(sbyte)72,unchecked((sbyte)195),unchecked((sbyte)163),unchecked((sbyte)182),(sbyte)30,(sbyte)66,(sbyte)58,(sbyte)107,(sbyte)40,(sbyte)84,unchecked((sbyte)250),unchecked((sbyte)133),(sbyte)61,unchecked((sbyte)186), (sbyte)43,(sbyte)121,(sbyte)10,(sbyte)21,unchecked((sbyte)155),unchecked((sbyte)159),(sbyte)94,unchecked((sbyte)202),(sbyte)78,unchecked((sbyte)212),unchecked((sbyte)172),unchecked((sbyte)229),unchecked((sbyte)243),(sbyte)115,unchecked((sbyte)167),(sbyte)87, unchecked((sbyte)175),(sbyte)88,unchecked((sbyte)168),(sbyte)80,unchecked((sbyte)244),unchecked((sbyte)234),unchecked((sbyte)214),(sbyte)116,(sbyte)79,unchecked((sbyte)174),unchecked((sbyte)233),unchecked((sbyte)213),unchecked((sbyte)231),unchecked((sbyte)230),unchecked((sbyte)173),unchecked((sbyte)232), (sbyte)44,unchecked((sbyte)215),(sbyte)117,(sbyte)122,unchecked((sbyte)235),(sbyte)22,(sbyte)11,unchecked((sbyte)245),(sbyte)89,unchecked((sbyte)203),(sbyte)95,unchecked((sbyte)176),unchecked((sbyte)156),unchecked((sbyte)169),(sbyte)81,unchecked((sbyte)160), (sbyte)127,(sbyte)12,unchecked((sbyte)246),(sbyte)111,(sbyte)23,unchecked((sbyte)196),(sbyte)73,unchecked((sbyte)236),unchecked((sbyte)216),(sbyte)67,(sbyte)31,(sbyte)45,unchecked((sbyte)164),(sbyte)118,(sbyte)123,unchecked((sbyte)183), unchecked((sbyte)204),unchecked((sbyte)187),(sbyte)62,(sbyte)90,unchecked((sbyte)251),(sbyte)96,unchecked((sbyte)177),unchecked((sbyte)134),(sbyte)59,(sbyte)82,unchecked((sbyte)161),(sbyte)108,unchecked((sbyte)170),(sbyte)85,(sbyte)41,unchecked((sbyte)157), unchecked((sbyte)151),unchecked((sbyte)178),unchecked((sbyte)135),unchecked((sbyte)144),(sbyte)97,unchecked((sbyte)190),unchecked((sbyte)220),unchecked((sbyte)252),unchecked((sbyte)188),unchecked((sbyte)149),unchecked((sbyte)207),unchecked((sbyte)205),(sbyte)55,(sbyte)63,(sbyte)91,unchecked((sbyte)209), (sbyte)83,(sbyte)57,unchecked((sbyte)132),(sbyte)60,(sbyte)65,unchecked((sbyte)162),(sbyte)109,(sbyte)71,(sbyte)20,(sbyte)42,unchecked((sbyte)158),(sbyte)93,(sbyte)86,unchecked((sbyte)242),unchecked((sbyte)211),unchecked((sbyte)171), (sbyte)68,(sbyte)17,unchecked((sbyte)146),unchecked((sbyte)217),(sbyte)35,(sbyte)32,(sbyte)46,unchecked((sbyte)137),unchecked((sbyte)180),(sbyte)124,unchecked((sbyte)184),(sbyte)38,(sbyte)119,unchecked((sbyte)153),unchecked((sbyte)227),unchecked((sbyte)165), (sbyte)103,(sbyte)74,unchecked((sbyte)237),unchecked((sbyte)222),unchecked((sbyte)197),(sbyte)49,unchecked((sbyte)254),(sbyte)24,(sbyte)13,(sbyte)99,unchecked((sbyte)140),unchecked((sbyte)128),unchecked((sbyte)192),unchecked((sbyte)247),(sbyte)112,(sbyte)7};
-
-	private static readonly sbyte[] fbsub = new sbyte[] {(sbyte)99,(sbyte)124,(sbyte)119,(sbyte)123,unchecked((sbyte)242),(sbyte)107,(sbyte)111,unchecked((sbyte)197),(sbyte)48,(sbyte)1,(sbyte)103,(sbyte)43,unchecked((sbyte)254),unchecked((sbyte)215),unchecked((sbyte)171),(sbyte)118, unchecked((sbyte)202),unchecked((sbyte)130),unchecked((sbyte)201),(sbyte)125,unchecked((sbyte)250),(sbyte)89,(sbyte)71,unchecked((sbyte)240),unchecked((sbyte)173),unchecked((sbyte)212),unchecked((sbyte)162),unchecked((sbyte)175),unchecked((sbyte)156),unchecked((sbyte)164),(sbyte)114,unchecked((sbyte)192), unchecked((sbyte)183),unchecked((sbyte)253),unchecked((sbyte)147),(sbyte)38,(sbyte)54,(sbyte)63,unchecked((sbyte)247),unchecked((sbyte)204),(sbyte)52,unchecked((sbyte)165),unchecked((sbyte)229),unchecked((sbyte)241),(sbyte)113,unchecked((sbyte)216),(sbyte)49,(sbyte)21, (sbyte)4,unchecked((sbyte)199),(sbyte)35,unchecked((sbyte)195),(sbyte)24,unchecked((sbyte)150),(sbyte)5,unchecked((sbyte)154),(sbyte)7,(sbyte)18,unchecked((sbyte)128),unchecked((sbyte)226),unchecked((sbyte)235),(sbyte)39,unchecked((sbyte)178),(sbyte)117, (sbyte)9,unchecked((sbyte)131),(sbyte)44,(sbyte)26,(sbyte)27,(sbyte)110,(sbyte)90,unchecked((sbyte)160),(sbyte)82,(sbyte)59,unchecked((sbyte)214),unchecked((sbyte)179),(sbyte)41,unchecked((sbyte)227),(sbyte)47,unchecked((sbyte)132), (sbyte)83,unchecked((sbyte)209),(sbyte)0,unchecked((sbyte)237),(sbyte)32,unchecked((sbyte)252),unchecked((sbyte)177),(sbyte)91,(sbyte)106,unchecked((sbyte)203),unchecked((sbyte)190),(sbyte)57,(sbyte)74,(sbyte)76,(sbyte)88,unchecked((sbyte)207), unchecked((sbyte)208),unchecked((sbyte)239),unchecked((sbyte)170),unchecked((sbyte)251),(sbyte)67,(sbyte)77,(sbyte)51,unchecked((sbyte)133),(sbyte)69,unchecked((sbyte)249),(sbyte)2,(sbyte)127,(sbyte)80,(sbyte)60,unchecked((sbyte)159),unchecked((sbyte)168), (sbyte)81,unchecked((sbyte)163),(sbyte)64,unchecked((sbyte)143),unchecked((sbyte)146),unchecked((sbyte)157),(sbyte)56,unchecked((sbyte)245),unchecked((sbyte)188),unchecked((sbyte)182),unchecked((sbyte)218),(sbyte)33,(sbyte)16,unchecked((sbyte)255),unchecked((sbyte)243),unchecked((sbyte)210), unchecked((sbyte)205),(sbyte)12,(sbyte)19,unchecked((sbyte)236),(sbyte)95,unchecked((sbyte)151),(sbyte)68,(sbyte)23,unchecked((sbyte)196),unchecked((sbyte)167),(sbyte)126,(sbyte)61,(sbyte)100,(sbyte)93,(sbyte)25,(sbyte)115, (sbyte)96,unchecked((sbyte)129),(sbyte)79,unchecked((sbyte)220),(sbyte)34,(sbyte)42,unchecked((sbyte)144),unchecked((sbyte)136),(sbyte)70,unchecked((sbyte)238),unchecked((sbyte)184),(sbyte)20,unchecked((sbyte)222),(sbyte)94,(sbyte)11,unchecked((sbyte)219), unchecked((sbyte)224),(sbyte)50,(sbyte)58,(sbyte)10,(sbyte)73,(sbyte)6,(sbyte)36,(sbyte)92,unchecked((sbyte)194),unchecked((sbyte)211),unchecked((sbyte)172),(sbyte)98,unchecked((sbyte)145),unchecked((sbyte)149),unchecked((sbyte)228),(sbyte)121, unchecked((sbyte)231),unchecked((sbyte)200),(sbyte)55,(sbyte)109,unchecked((sbyte)141),unchecked((sbyte)213),(sbyte)78,unchecked((sbyte)169),(sbyte)108,(sbyte)86,unchecked((sbyte)244),unchecked((sbyte)234),(sbyte)101,(sbyte)122,unchecked((sbyte)174),(sbyte)8, unchecked((sbyte)186),(sbyte)120,(sbyte)37,(sbyte)46,(sbyte)28,unchecked((sbyte)166),unchecked((sbyte)180),unchecked((sbyte)198),unchecked((sbyte)232),unchecked((sbyte)221),(sbyte)116,(sbyte)31,(sbyte)75,unchecked((sbyte)189),unchecked((sbyte)139),unchecked((sbyte)138), (sbyte)112,(sbyte)62,unchecked((sbyte)181),(sbyte)102,(sbyte)72,(sbyte)3,unchecked((sbyte)246),(sbyte)14,(sbyte)97,(sbyte)53,(sbyte)87,unchecked((sbyte)185),unchecked((sbyte)134),unchecked((sbyte)193),(sbyte)29,unchecked((sbyte)158), unchecked((sbyte)225),unchecked((sbyte)248),unchecked((sbyte)152),(sbyte)17,(sbyte)105,unchecked((sbyte)217),unchecked((sbyte)142),unchecked((sbyte)148),unchecked((sbyte)155),(sbyte)30,unchecked((sbyte)135),unchecked((sbyte)233),unchecked((sbyte)206),(sbyte)85,(sbyte)40,unchecked((sbyte)223), unchecked((sbyte)140),unchecked((sbyte)161),unchecked((sbyte)137),(sbyte)13,unchecked((sbyte)191),unchecked((sbyte)230),(sbyte)66,(sbyte)104,(sbyte)65,unchecked((sbyte)153),(sbyte)45,(sbyte)15,unchecked((sbyte)176),(sbyte)84,unchecked((sbyte)187),(sbyte)22};
-
-	private static readonly sbyte[] rbsub = new sbyte[] {(sbyte)82,(sbyte)9,(sbyte)106,unchecked((sbyte)213),(sbyte)48,(sbyte)54,unchecked((sbyte)165),(sbyte)56,unchecked((sbyte)191),(sbyte)64,unchecked((sbyte)163),unchecked((sbyte)158),unchecked((sbyte)129),unchecked((sbyte)243),unchecked((sbyte)215),unchecked((sbyte)251), (sbyte)124,unchecked((sbyte)227),(sbyte)57,unchecked((sbyte)130),unchecked((sbyte)155),(sbyte)47,unchecked((sbyte)255),unchecked((sbyte)135),(sbyte)52,unchecked((sbyte)142),(sbyte)67,(sbyte)68,unchecked((sbyte)196),unchecked((sbyte)222),unchecked((sbyte)233),unchecked((sbyte)203), (sbyte)84,(sbyte)123,unchecked((sbyte)148),(sbyte)50,unchecked((sbyte)166),unchecked((sbyte)194),(sbyte)35,(sbyte)61,unchecked((sbyte)238),(sbyte)76,unchecked((sbyte)149),(sbyte)11,(sbyte)66,unchecked((sbyte)250),unchecked((sbyte)195),(sbyte)78, (sbyte)8,(sbyte)46,unchecked((sbyte)161),(sbyte)102,(sbyte)40,unchecked((sbyte)217),(sbyte)36,unchecked((sbyte)178),(sbyte)118,(sbyte)91,unchecked((sbyte)162),(sbyte)73,(sbyte)109,unchecked((sbyte)139),unchecked((sbyte)209),(sbyte)37, (sbyte)114,unchecked((sbyte)248),unchecked((sbyte)246),(sbyte)100,unchecked((sbyte)134),(sbyte)104,unchecked((sbyte)152),(sbyte)22,unchecked((sbyte)212),unchecked((sbyte)164),(sbyte)92,unchecked((sbyte)204),(sbyte)93,(sbyte)101,unchecked((sbyte)182),unchecked((sbyte)146), (sbyte)108,(sbyte)112,(sbyte)72,(sbyte)80,unchecked((sbyte)253),unchecked((sbyte)237),unchecked((sbyte)185),unchecked((sbyte)218),(sbyte)94,(sbyte)21,(sbyte)70,(sbyte)87,unchecked((sbyte)167),unchecked((sbyte)141),unchecked((sbyte)157),unchecked((sbyte)132), unchecked((sbyte)144),unchecked((sbyte)216),unchecked((sbyte)171),(sbyte)0,unchecked((sbyte)140),unchecked((sbyte)188),unchecked((sbyte)211),(sbyte)10,unchecked((sbyte)247),unchecked((sbyte)228),(sbyte)88,(sbyte)5,unchecked((sbyte)184),unchecked((sbyte)179),(sbyte)69,(sbyte)6, unchecked((sbyte)208),(sbyte)44,(sbyte)30,unchecked((sbyte)143),unchecked((sbyte)202),(sbyte)63,(sbyte)15,(sbyte)2,unchecked((sbyte)193),unchecked((sbyte)175),unchecked((sbyte)189),(sbyte)3,(sbyte)1,(sbyte)19,unchecked((sbyte)138),(sbyte)107, (sbyte)58,unchecked((sbyte)145),(sbyte)17,(sbyte)65,(sbyte)79,(sbyte)103,unchecked((sbyte)220),unchecked((sbyte)234),unchecked((sbyte)151),unchecked((sbyte)242),unchecked((sbyte)207),unchecked((sbyte)206),unchecked((sbyte)240),unchecked((sbyte)180),unchecked((sbyte)230),(sbyte)115, unchecked((sbyte)150),unchecked((sbyte)172),(sbyte)116,(sbyte)34,unchecked((sbyte)231),unchecked((sbyte)173),(sbyte)53,unchecked((sbyte)133),unchecked((sbyte)226),unchecked((sbyte)249),(sbyte)55,unchecked((sbyte)232),(sbyte)28,(sbyte)117,unchecked((sbyte)223),(sbyte)110, (sbyte)71,unchecked((sbyte)241),(sbyte)26,(sbyte)113,(sbyte)29,(sbyte)41,unchecked((sbyte)197),unchecked((sbyte)137),(sbyte)111,unchecked((sbyte)183),(sbyte)98,(sbyte)14,unchecked((sbyte)170),(sbyte)24,unchecked((sbyte)190),(sbyte)27, unchecked((sbyte)252),(sbyte)86,(sbyte)62,(sbyte)75,unchecked((sbyte)198),unchecked((sbyte)210),(sbyte)121,(sbyte)32,unchecked((sbyte)154),unchecked((sbyte)219),unchecked((sbyte)192),unchecked((sbyte)254),(sbyte)120,unchecked((sbyte)205),(sbyte)90,unchecked((sbyte)244), (sbyte)31,unchecked((sbyte)221),unchecked((sbyte)168),(sbyte)51,unchecked((sbyte)136),(sbyte)7,unchecked((sbyte)199),(sbyte)49,unchecked((sbyte)177),(sbyte)18,(sbyte)16,(sbyte)89,(sbyte)39,unchecked((sbyte)128),unchecked((sbyte)236),(sbyte)95, (sbyte)96,(sbyte)81,(sbyte)127,unchecked((sbyte)169),(sbyte)25,unchecked((sbyte)181),(sbyte)74,(sbyte)13,(sbyte)45,unchecked((sbyte)229),(sbyte)122,unchecked((sbyte)159),unchecked((sbyte)147),unchecked((sbyte)201),unchecked((sbyte)156),unchecked((sbyte)239), unchecked((sbyte)160),unchecked((sbyte)224),(sbyte)59,(sbyte)77,unchecked((sbyte)174),(sbyte)42,unchecked((sbyte)245),unchecked((sbyte)176),unchecked((sbyte)200),unchecked((sbyte)235),unchecked((sbyte)187),(sbyte)60,unchecked((sbyte)131),(sbyte)83,unchecked((sbyte)153),(sbyte)97, (sbyte)23,(sbyte)43,(sbyte)4,(sbyte)126,unchecked((sbyte)186),(sbyte)119,unchecked((sbyte)214),(sbyte)38,unchecked((sbyte)225),(sbyte)105,(sbyte)20,(sbyte)99,(sbyte)85,(sbyte)33,(sbyte)12,(sbyte)125};
-
-	private static readonly sbyte[] rco = new sbyte[] {(sbyte)1,(sbyte)2,(sbyte)4,(sbyte)8,(sbyte)16,(sbyte)32,(sbyte)64,unchecked((sbyte)128),(sbyte)27,(sbyte)54,(sbyte)108,unchecked((sbyte)216),unchecked((sbyte)171),(sbyte)77,unchecked((sbyte)154),(sbyte)47};
-
-	private static readonly int[] ftable = new int[] {unchecked((int)0xa56363c6), unchecked((int)0x847c7cf8), unchecked((int)0x997777ee), unchecked((int)0x8d7b7bf6), 0xdf2f2ff, unchecked((int)0xbd6b6bd6), unchecked((int)0xb16f6fde), 0x54c5c591, 0x50303060, 0x3010102, unchecked((int)0xa96767ce), 0x7d2b2b56, 0x19fefee7, 0x62d7d7b5, unchecked((int)0xe6abab4d), unchecked((int)0x9a7676ec), 0x45caca8f, unchecked((int)0x9d82821f), 0x40c9c989, unchecked((int)0x877d7dfa), 0x15fafaef, unchecked((int)0xeb5959b2), unchecked((int)0xc947478e), 0xbf0f0fb, unchecked((int)0xecadad41), 0x67d4d4b3, unchecked((int)0xfda2a25f), unchecked((int)0xeaafaf45), unchecked((int)0xbf9c9c23), unchecked((int)0xf7a4a453), unchecked((int)0x967272e4), 0x5bc0c09b, unchecked((int)0xc2b7b775), 0x1cfdfde1, unchecked((int)0xae93933d), 0x6a26264c, 0x5a36366c, 0x413f3f7e, 0x2f7f7f5, 0x4fcccc83, 0x5c343468, unchecked((int)0xf4a5a551), 0x34e5e5d1, 0x8f1f1f9, unchecked((int)0x937171e2), 0x73d8d8ab, 0x53313162, 0x3f15152a, 0xc040408, 0x52c7c795, 0x65232346, 0x5ec3c39d, 0x28181830, unchecked((int)0xa1969637), 0xf05050a, unchecked((int)0xb59a9a2f), 0x907070e, 0x36121224, unchecked((int)0x9b80801b), 0x3de2e2df, 0x26ebebcd, 0x6927274e, unchecked((int)0xcdb2b27f), unchecked((int)0x9f7575ea), 0x1b090912, unchecked((int)0x9e83831d), 0x742c2c58, 0x2e1a1a34, 0x2d1b1b36, unchecked((int)0xb26e6edc), unchecked((int)0xee5a5ab4), unchecked((int)0xfba0a05b), unchecked((int)0xf65252a4), 0x4d3b3b76, 0x61d6d6b7, unchecked((int)0xceb3b37d), 0x7b292952, 0x3ee3e3dd, 0x712f2f5e, unchecked((int)0x97848413), unchecked((int)0xf55353a6), 0x68d1d1b9, 0x0, 0x2cededc1, 0x60202040, 0x1ffcfce3, unchecked((int)0xc8b1b179), unchecked((int)0xed5b5bb6), unchecked((int)0xbe6a6ad4), 0x46cbcb8d, unchecked((int)0xd9bebe67), 0x4b393972, unchecked((int)0xde4a4a94), unchecked((int)0xd44c4c98), unchecked((int)0xe85858b0), 0x4acfcf85, 0x6bd0d0bb, 0x2aefefc5, unchecked((int)0xe5aaaa4f), 0x16fbfbed, unchecked((int)0xc5434386), unchecked((int)0xd74d4d9a), 0x55333366, unchecked((int)0x94858511), unchecked((int)0xcf45458a), 0x10f9f9e9, 0x6020204, unchecked((int)0x817f7ffe), unchecked((int)0xf05050a0), 0x443c3c78, unchecked((int)0xba9f9f25), unchecked((int)0xe3a8a84b), unchecked((int)0xf35151a2), unchecked((int)0xfea3a35d), unchecked((int)0xc0404080), unchecked((int)0x8a8f8f05), unchecked((int)0xad92923f), unchecked((int)0xbc9d9d21), 0x48383870, 0x4f5f5f1, unchecked((int)0xdfbcbc63), unchecked((int)0xc1b6b677), 0x75dadaaf, 0x63212142, 0x30101020, 0x1affffe5, 0xef3f3fd, 0x6dd2d2bf, 0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3, unchecked((int)0xe15f5fbe), unchecked((int)0xa2979735), unchecked((int)0xcc444488), 0x3917172e, 0x57c4c493, unchecked((int)0xf2a7a755), unchecked((int)0x827e7efc), 0x473d3d7a, unchecked((int)0xac6464c8), unchecked((int)0xe75d5dba), 0x2b191932, unchecked((int)0x957373e6), unchecked((int)0xa06060c0), unchecked((int)0x98818119), unchecked((int)0xd14f4f9e), 0x7fdcdca3, 0x66222244, 0x7e2a2a54, unchecked((int)0xab90903b), unchecked((int)0x8388880b), unchecked((int)0xca46468c), 0x29eeeec7, unchecked((int)0xd3b8b86b), 0x3c141428, 0x79dedea7, unchecked((int)0xe25e5ebc), 0x1d0b0b16, 0x76dbdbad, 0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14, unchecked((int)0xdb494992), 0xa06060c, 0x6c242448, unchecked((int)0xe45c5cb8), 0x5dc2c29f, 0x6ed3d3bd, unchecked((int)0xefacac43), unchecked((int)0xa66262c4), unchecked((int)0xa8919139), unchecked((int)0xa4959531), 0x37e4e4d3, unchecked((int)0x8b7979f2), 0x32e7e7d5, 0x43c8c88b, 0x5937376e, unchecked((int)0xb76d6dda), unchecked((int)0x8c8d8d01), 0x64d5d5b1, unchecked((int)0xd24e4e9c), unchecked((int)0xe0a9a949), unchecked((int)0xb46c6cd8), unchecked((int)0xfa5656ac), 0x7f4f4f3, 0x25eaeacf, unchecked((int)0xaf6565ca), unchecked((int)0x8e7a7af4), unchecked((int)0xe9aeae47), 0x18080810, unchecked((int)0xd5baba6f), unchecked((int)0x887878f0), 0x6f25254a, 0x722e2e5c, 0x241c1c38, unchecked((int)0xf1a6a657), unchecked((int)0xc7b4b473), 0x51c6c697, 0x23e8e8cb, 0x7cdddda1, unchecked((int)0x9c7474e8), 0x211f1f3e, unchecked((int)0xdd4b4b96), unchecked((int)0xdcbdbd61), unchecked((int)0x868b8b0d), unchecked((int)0x858a8a0f), unchecked((int)0x907070e0), 0x423e3e7c, unchecked((int)0xc4b5b571), unchecked((int)0xaa6666cc), unchecked((int)0xd8484890), 0x5030306, 0x1f6f6f7, 0x120e0e1c, unchecked((int)0xa36161c2), 0x5f35356a, unchecked((int)0xf95757ae), unchecked((int)0xd0b9b969), unchecked((int)0x91868617), 0x58c1c199, 0x271d1d3a, unchecked((int)0xb99e9e27), 0x38e1e1d9, 0x13f8f8eb, unchecked((int)0xb398982b), 0x33111122, unchecked((int)0xbb6969d2), 0x70d9d9a9, unchecked((int)0x898e8e07), unchecked((int)0xa7949433), unchecked((int)0xb69b9b2d), 0x221e1e3c, unchecked((int)0x92878715), 0x20e9e9c9, 0x49cece87, unchecked((int)0xff5555aa), 0x78282850, 0x7adfdfa5, unchecked((int)0x8f8c8c03), unchecked((int)0xf8a1a159), unchecked((int)0x80898909), 0x170d0d1a, unchecked((int)0xdabfbf65), 0x31e6e6d7, unchecked((int)0xc6424284), unchecked((int)0xb86868d0), unchecked((int)0xc3414182), unchecked((int)0xb0999929), 0x772d2d5a, 0x110f0f1e, unchecked((int)0xcbb0b07b), unchecked((int)0xfc5454a8), unchecked((int)0xd6bbbb6d), 0x3a16162c};
-
-	private static readonly int[] rtable = new int[] {0x50a7f451, 0x5365417e, unchecked((int)0xc3a4171a), unchecked((int)0x965e273a), unchecked((int)0xcb6bab3b), unchecked((int)0xf1459d1f), unchecked((int)0xab58faac), unchecked((int)0x9303e34b), 0x55fa3020, unchecked((int)0xf66d76ad), unchecked((int)0x9176cc88), 0x254c02f5, unchecked((int)0xfcd7e54f), unchecked((int)0xd7cb2ac5), unchecked((int)0x80443526), unchecked((int)0x8fa362b5), 0x495ab1de, 0x671bba25, unchecked((int)0x980eea45), unchecked((int)0xe1c0fe5d), 0x2752fc3, 0x12f04c81, unchecked((int)0xa397468d), unchecked((int)0xc6f9d36b), unchecked((int)0xe75f8f03), unchecked((int)0x959c9215), unchecked((int)0xeb7a6dbf), unchecked((int)0xda595295), 0x2d83bed4, unchecked((int)0xd3217458), 0x2969e049, 0x44c8c98e, 0x6a89c275, 0x78798ef4, 0x6b3e5899, unchecked((int)0xdd71b927), unchecked((int)0xb64fe1be), 0x17ad88f0, 0x66ac20c9, unchecked((int)0xb43ace7d), 0x184adf63, unchecked((int)0x82311ae5), 0x60335197, 0x457f5362, unchecked((int)0xe07764b1), unchecked((int)0x84ae6bbb), 0x1ca081fe, unchecked((int)0x942b08f9), 0x58684870, 0x19fd458f, unchecked((int)0x876cde94), unchecked((int)0xb7f87b52), 0x23d373ab, unchecked((int)0xe2024b72), 0x578f1fe3, 0x2aab5566, 0x728ebb2, 0x3c2b52f, unchecked((int)0x9a7bc586), unchecked((int)0xa50837d3), unchecked((int)0xf2872830), unchecked((int)0xb2a5bf23), unchecked((int)0xba6a0302), 0x5c8216ed, 0x2b1ccf8a, unchecked((int)0x92b479a7), unchecked((int)0xf0f207f3), unchecked((int)0xa1e2694e), unchecked((int)0xcdf4da65), unchecked((int)0xd5be0506), 0x1f6234d1, unchecked((int)0x8afea6c4), unchecked((int)0x9d532e34), unchecked((int)0xa055f3a2), 0x32e18a05, 0x75ebf6a4, 0x39ec830b, unchecked((int)0xaaef6040), 0x69f715e, 0x51106ebd, unchecked((int)0xf98a213e), 0x3d06dd96, unchecked((int)0xae053edd), 0x46bde64d, unchecked((int)0xb58d5491), 0x55dc471, 0x6fd40604, unchecked((int)0xff155060), 0x24fb9819, unchecked((int)0x97e9bdd6), unchecked((int)0xcc434089), 0x779ed967, unchecked((int)0xbd42e8b0), unchecked((int)0x888b8907), 0x385b19e7, unchecked((int)0xdbeec879), 0x470a7ca1, unchecked((int)0xe90f427c), unchecked((int)0xc91e84f8), 0x0, unchecked((int)0x83868009), 0x48ed2b32, unchecked((int)0xac70111e), 0x4e725a6c, unchecked((int)0xfbff0efd), 0x5638850f, 0x1ed5ae3d, 0x27392d36, 0x64d90f0a, 0x21a65c68, unchecked((int)0xd1545b9b), 0x3a2e3624, unchecked((int)0xb1670a0c), 0xfe75793, unchecked((int)0xd296eeb4), unchecked((int)0x9e919b1b), 0x4fc5c080, unchecked((int)0xa220dc61), 0x694b775a, 0x161a121c, 0xaba93e2, unchecked((int)0xe52aa0c0), 0x43e0223c, 0x1d171b12, 0xb0d090e, unchecked((int)0xadc78bf2), unchecked((int)0xb9a8b62d), unchecked((int)0xc8a91e14), unchecked((int)0x8519f157), 0x4c0775af, unchecked((int)0xbbdd99ee), unchecked((int)0xfd607fa3), unchecked((int)0x9f2601f7), unchecked((int)0xbcf5725c), unchecked((int)0xc53b6644), 0x347efb5b, 0x7629438b, unchecked((int)0xdcc623cb), 0x68fcedb6, 0x63f1e4b8, unchecked((int)0xcadc31d7), 0x10856342, 0x40229713, 0x2011c684, 0x7d244a85, unchecked((int)0xf83dbbd2), 0x1132f9ae, 0x6da129c7, 0x4b2f9e1d, unchecked((int)0xf330b2dc), unchecked((int)0xec52860d), unchecked((int)0xd0e3c177), 0x6c16b32b, unchecked((int)0x99b970a9), unchecked((int)0xfa489411), 0x2264e947, unchecked((int)0xc48cfca8), 0x1a3ff0a0, unchecked((int)0xd82c7d56), unchecked((int)0xef903322), unchecked((int)0xc74e4987), unchecked((int)0xc1d138d9), unchecked((int)0xfea2ca8c), 0x360bd498, unchecked((int)0xcf81f5a6), 0x28de7aa5, 0x268eb7da, unchecked((int)0xa4bfad3f), unchecked((int)0xe49d3a2c), 0xd927850, unchecked((int)0x9bcc5f6a), 0x62467e54, unchecked((int)0xc2138df6), unchecked((int)0xe8b8d890), 0x5ef7392e, unchecked((int)0xf5afc382), unchecked((int)0xbe805d9f), 0x7c93d069, unchecked((int)0xa92dd56f), unchecked((int)0xb31225cf), 0x3b99acc8, unchecked((int)0xa77d1810), 0x6e639ce8, 0x7bbb3bdb, 0x97826cd, unchecked((int)0xf418596e), 0x1b79aec, unchecked((int)0xa89a4f83), 0x656e95e6, 0x7ee6ffaa, 0x8cfbc21, unchecked((int)0xe6e815ef), unchecked((int)0xd99be7ba), unchecked((int)0xce366f4a), unchecked((int)0xd4099fea), unchecked((int)0xd67cb029), unchecked((int)0xafb2a431), 0x31233f2a, 0x3094a5c6, unchecked((int)0xc066a235), 0x37bc4e74, unchecked((int)0xa6ca82fc), unchecked((int)0xb0d090e0), 0x15d8a733, 0x4a9804f1, unchecked((int)0xf7daec41), 0xe50cd7f, 0x2ff69117, unchecked((int)0x8dd64d76), 0x4db0ef43, 0x544daacc, unchecked((int)0xdf0496e4), unchecked((int)0xe3b5d19e), 0x1b886a4c, unchecked((int)0xb81f2cc1), 0x7f516546, 0x4ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb, 0x5a1d67b3, 0x52d2db92, 0x335610e9, 0x1347d66d, unchecked((int)0x8c61d79a), 0x7a0ca137, unchecked((int)0x8e14f859), unchecked((int)0x893c13eb), unchecked((int)0xee27a9ce), 0x35c961b7, unchecked((int)0xede51ce1), 0x3cb1477a, 0x59dfd29c, 0x3f73f255, 0x79ce1418, unchecked((int)0xbf37c773), unchecked((int)0xeacdf753), 0x5baafd5f, 0x146f3ddf, unchecked((int)0x86db4478), unchecked((int)0x81f3afca), 0x3ec468b9, 0x2c342438, 0x5f40a3c2, 0x72c31d16, 0xc25e2bc, unchecked((int)0x8b493c28), 0x41950dff, 0x7101a839, unchecked((int)0xdeb30c08), unchecked((int)0x9ce4b4d8), unchecked((int)0x90c15664), 0x6184cb7b, 0x70b632d5, 0x745c6c48, 0x4257b8d0};
-
-
-/* Rotates 32-bit word left by 1, 2 or 3 byte  */
-
-	private static int ROTL8(int x)
-	{
-		return (((x) << 8) | ((int)((uint)(x)>>24)));
-	}
-
-	private static int ROTL16(int x)
-	{
-		return (((x) << 16) | ((int)((uint)(x)>>16)));
-	}
-
-	private static int ROTL24(int x)
-	{
-		return (((x) << 24) | ((int)((uint)(x)>>8)));
-	}
-
-	private static int pack(sbyte[] b)
-	{ // pack bytes into a 32-bit Word
-		return ((((int)b[3]) & 0xff) << 24) | (((int)b[2] & 0xff) << 16) | (((int)b[1] & 0xff) << 8) | ((int)b[0] & 0xff);
-	}
-
-	private static sbyte[] unpack(int a)
-	{ // unpack bytes from a word
-		sbyte[] b = new sbyte[4];
-		b[0] = (sbyte)(a);
-		b[1] = (sbyte)((int)((uint)a >> 8));
-		b[2] = (sbyte)((int)((uint)a >> 16));
-		b[3] = (sbyte)((int)((uint)a >> 24));
-		return b;
-	}
-
-	private static sbyte bmul(sbyte x, sbyte y)
-	{ // x.y= AntiLog(Log(x) + Log(y))
-
-		int ix = ((int)x) & 0xff;
-		int iy = ((int)y) & 0xff;
-		int lx = ((int)ltab[ix]) & 0xff;
-		int ly = ((int)ltab[iy]) & 0xff;
-		if (x != 0 && y != 0)
-		{
-			return ptab[(lx + ly) % 255];
-		}
-		else
-		{
-			return (sbyte)0;
-		}
-	}
-
-  //  if (x && y)
-
-	private static int SubByte(int a)
-	{
-		sbyte[] b = unpack(a);
-		b[0] = fbsub[(int)b[0] & 0xff];
-		b[1] = fbsub[(int)b[1] & 0xff];
-		b[2] = fbsub[(int)b[2] & 0xff];
-		b[3] = fbsub[(int)b[3] & 0xff];
-		return pack(b);
-	}
-
-	private static sbyte product(int x, int y)
-	{ // dot product of two 4-byte arrays
-		sbyte[] xb; //=new byte[4];
-		sbyte[] yb; //=new byte[4];
-		xb = unpack(x);
-		yb = unpack(y);
-
-		return (sbyte)(bmul(xb[0],yb[0]) ^ bmul(xb[1],yb[1]) ^ bmul(xb[2],yb[2]) ^ bmul(xb[3],yb[3]));
-	}
-
-	private static int InvMixCol(int x)
-	{ // matrix Multiplication
-		int y, m;
-		sbyte[] b = new sbyte[4];
-
-		m = pack(InCo);
-		b[3] = product(m,x);
-		m = ROTL24(m);
-		b[2] = product(m,x);
-		m = ROTL24(m);
-		b[1] = product(m,x);
-		m = ROTL24(m);
-		b[0] = product(m,x);
-		y = pack(b);
-		return y;
-	}
-
-/* reset cipher */
-	public virtual void reset(int m, sbyte[] iv)
-	{ // reset mode, or reset iv
-		mode = m;
-		for (int i = 0;i < 16;i++)
-		{
-			f[i] = 0;
-		}
-		if (mode != ECB && iv != null)
-		{
-			for (int i = 0;i < 16;i++)
-			{
-				f[i] = iv[i];
-			}
-		}
-	}
-
-	public virtual sbyte[] getreg()
-	{
-		sbyte[] ir = new sbyte[16];
-		for (int i = 0;i < 16;i++)
-		{
-			ir[i] = f[i];
-		}
-		return ir;
-	}
-
-/* Initialise cipher */
-	public virtual void init(int m, sbyte[] key, sbyte[] iv)
-	{ // Key=16 bytes
-		/* Key Scheduler. Create expanded encryption key */
-		int i, j, k, N, nk;
-		int[] CipherKey = new int[4];
-		sbyte[] b = new sbyte[4];
-		nk = 4;
-		reset(m,iv);
-		N = 44;
-
-		for (i = j = 0;i < nk;i++,j += 4)
-		{
-			for (k = 0;k < 4;k++)
-			{
-				b[k] = key[j + k];
-			}
-			CipherKey[i] = pack(b);
-		}
-		for (i = 0;i < nk;i++)
-		{
-			fkey[i] = CipherKey[i];
-		}
-		for (j = nk,k = 0;j < N;j += nk,k++)
-		{
-			fkey[j] = fkey[j - nk] ^ SubByte(ROTL24(fkey[j - 1])) ^ ((int)rco[k]) & 0xff;
-			for (i = 1;i < nk && (i + j) < N;i++)
-			{
-				fkey[i + j] = fkey[i + j - nk] ^ fkey[i + j - 1];
-			}
-		}
-
- /* now for the expanded decrypt key in reverse order */
-
-		for (j = 0;j < 4;j++)
-		{
-			rkey[j + N - 4] = fkey[j];
-		}
-		for (i = 4;i < N - 4;i += 4)
-		{
-			k = N - 4 - i;
-			for (j = 0;j < 4;j++)
-			{
-				rkey[k + j] = InvMixCol(fkey[i + j]);
-			}
-		}
-		for (j = N - 4;j < N;j++)
-		{
-			rkey[j - N + 4] = fkey[j];
-		}
-	}
-
-/* Encrypt a single block */
-	public virtual void ecb_encrypt(sbyte[] buff)
-	{
-		int i, j, k;
-		int t;
-		sbyte[] b = new sbyte[4];
-		int[] p = new int[4];
-		int[] q = new int[4];
-
-		for (i = j = 0;i < 4;i++,j += 4)
-		{
-			for (k = 0;k < 4;k++)
-			{
-				b[k] = buff[j + k];
-			}
-			p[i] = pack(b);
-			p[i] ^= fkey[i];
-		}
-
-		k = 4;
-
-/* State alternates between p and q */
-		for (i = 1;i < 10;i++)
-		{
-			q[0] = fkey[k] ^ ftable[p[0] & 0xff] ^ ROTL8(ftable[((int)((uint)p[1] >> 8)) & 0xff]) ^ ROTL16(ftable[((int)((uint)p[2] >> 16)) & 0xff]) ^ ROTL24(ftable[((int)((uint)p[3] >> 24)) & 0xff]);
-			q[1] = fkey[k + 1] ^ ftable[p[1] & 0xff] ^ ROTL8(ftable[((int)((uint)p[2] >> 8)) & 0xff]) ^ ROTL16(ftable[((int)((uint)p[3] >> 16)) & 0xff]) ^ ROTL24(ftable[((int)((uint)p[0] >> 24)) & 0xff]);
-			q[2] = fkey[k + 2] ^ ftable[p[2] & 0xff] ^ ROTL8(ftable[((int)((uint)p[3] >> 8)) & 0xff]) ^ ROTL16(ftable[((int)((uint)p[0] >> 16)) & 0xff]) ^ ROTL24(ftable[((int)((uint)p[1] >> 24)) & 0xff]);
-			q[3] = fkey[k + 3] ^ ftable[p[3] & 0xff] ^ ROTL8(ftable[((int)((uint)p[0] >> 8)) & 0xff]) ^ ROTL16(ftable[((int)((uint)p[1] >> 16)) & 0xff]) ^ ROTL24(ftable[((int)((uint)p[2] >> 24)) & 0xff]);
-
-			k += 4;
-			for (j = 0;j < 4;j++)
-			{
-				t = p[j];
-				p[j] = q[j];
-				q[j] = t;
-			}
-		}
-
-/* Last Round */
-
-		q[0] = fkey[k] ^ ((int)fbsub[p[0] & 0xff] & 0xff) ^ ROTL8((int)fbsub[((int)((uint)p[1] >> 8)) & 0xff] & 0xff) ^ ROTL16((int)fbsub[((int)((uint)p[2] >> 16)) & 0xff] & 0xff) ^ ROTL24((int)fbsub[((int)((uint)p[3] >> 24)) & 0xff] & 0xff);
-
-		q[1] = fkey[k + 1] ^ ((int)fbsub[p[1] & 0xff] & 0xff) ^ ROTL8((int)fbsub[((int)((uint)p[2] >> 8)) & 0xff] & 0xff) ^ ROTL16((int)fbsub[((int)((uint)p[3] >> 16)) & 0xff] & 0xff) ^ ROTL24((int)fbsub[((int)((uint)p[0] >> 24)) & 0xff] & 0xff);
-
-		q[2] = fkey[k + 2] ^ ((int)fbsub[p[2] & 0xff] & 0xff) ^ ROTL8((int)fbsub[((int)((uint)p[3] >> 8)) & 0xff] & 0xff) ^ ROTL16((int)fbsub[((int)((uint)p[0] >> 16)) & 0xff] & 0xff) ^ ROTL24((int)fbsub[((int)((uint)p[1] >> 24)) & 0xff] & 0xff);
-
-		q[3] = fkey[k + 3] ^ ((int)fbsub[(p[3]) & 0xff] & 0xff) ^ ROTL8((int)fbsub[((int)((uint)p[0] >> 8)) & 0xff] & 0xff) ^ ROTL16((int)fbsub[((int)((uint)p[1] >> 16)) & 0xff] & 0xff) ^ ROTL24((int)fbsub[((int)((uint)p[2] >> 24)) & 0xff] & 0xff);
-
-		for (i = j = 0;i < 4;i++,j += 4)
-		{
-			b = unpack(q[i]);
-			for (k = 0;k < 4;k++)
-			{
-				buff[j + k] = b[k];
-			}
-		}
-	}
-
-/* Decrypt a single block */
-	public virtual void ecb_decrypt(sbyte[] buff)
-	{
-		int i, j, k;
-		int t;
-		sbyte[] b = new sbyte[4];
-		int[] p = new int[4];
-		int[] q = new int[4];
-
-		for (i = j = 0;i < 4;i++,j += 4)
-		{
-			for (k = 0;k < 4;k++)
-			{
-				b[k] = buff[j + k];
-			}
-			p[i] = pack(b);
-			p[i] ^= rkey[i];
-		}
-
-		k = 4;
-
-/* State alternates between p and q */
-		for (i = 1;i < 10;i++)
-		{
-			q[0] = rkey[k] ^ rtable[p[0] & 0xff] ^ ROTL8(rtable[((int)((uint)p[3] >> 8)) & 0xff]) ^ ROTL16(rtable[((int)((uint)p[2] >> 16)) & 0xff]) ^ ROTL24(rtable[((int)((uint)p[1] >> 24)) & 0xff]);
-			q[1] = rkey[k + 1] ^ rtable[p[1] & 0xff] ^ ROTL8(rtable[((int)((uint)p[0] >> 8)) & 0xff]) ^ ROTL16(rtable[((int)((uint)p[3] >> 16)) & 0xff]) ^ ROTL24(rtable[((int)((uint)p[2] >> 24)) & 0xff]);
-			q[2] = rkey[k + 2] ^ rtable[p[2] & 0xff] ^ ROTL8(rtable[((int)((uint)p[1] >> 8)) & 0xff]) ^ ROTL16(rtable[((int)((uint)p[0] >> 16)) & 0xff]) ^ ROTL24(rtable[((int)((uint)p[3] >> 24)) & 0xff]);
-			q[3] = rkey[k + 3] ^ rtable[p[3] & 0xff] ^ ROTL8(rtable[((int)((uint)p[2] >> 8)) & 0xff]) ^ ROTL16(rtable[((int)((uint)p[1] >> 16)) & 0xff]) ^ ROTL24(rtable[((int)((uint)p[0] >> 24)) & 0xff]);
-
-			k += 4;
-			for (j = 0;j < 4;j++)
-			{
-				t = p[j];
-				p[j] = q[j];
-				q[j] = t;
-			}
-		}
-
-/* Last Round */
-
-		q[0] = rkey[k] ^ ((int)rbsub[p[0] & 0xff] & 0xff) ^ ROTL8((int)rbsub[((int)((uint)p[3] >> 8)) & 0xff] & 0xff) ^ ROTL16((int)rbsub[((int)((uint)p[2] >> 16)) & 0xff] & 0xff) ^ ROTL24((int)rbsub[((int)((uint)p[1] >> 24)) & 0xff] & 0xff);
-		q[1] = rkey[k + 1] ^ ((int)rbsub[p[1] & 0xff] & 0xff) ^ ROTL8((int)rbsub[((int)((uint)p[0] >> 8)) & 0xff] & 0xff) ^ ROTL16((int)rbsub[((int)((uint)p[3] >> 16)) & 0xff] & 0xff) ^ ROTL24((int)rbsub[((int)((uint)p[2] >> 24)) & 0xff] & 0xff);
-		q[2] = rkey[k + 2] ^ ((int)rbsub[p[2] & 0xff] & 0xff) ^ ROTL8((int)rbsub[((int)((uint)p[1] >> 8)) & 0xff] & 0xff) ^ ROTL16((int)rbsub[((int)((uint)p[0] >> 16)) & 0xff] & 0xff) ^ ROTL24((int)rbsub[((int)((uint)p[3] >> 24)) & 0xff] & 0xff);
-		q[3] = rkey[k + 3] ^ ((int)rbsub[p[3] & 0xff] & 0xff) ^ ROTL8((int)rbsub[((int)((uint)p[2] >> 8)) & 0xff] & 0xff) ^ ROTL16((int)rbsub[((int)((uint)p[1] >> 16)) & 0xff] & 0xff) ^ ROTL24((int)rbsub[((int)((uint)p[0] >> 24)) & 0xff] & 0xff);
-
-		for (i = j = 0;i < 4;i++,j += 4)
-		{
-			b = unpack(q[i]);
-			for (k = 0;k < 4;k++)
-			{
-				buff[j + k] = b[k];
-			}
-		}
-
-	}
-
-/* Encrypt using selected mode of operation */
-	public virtual int encrypt(sbyte[] buff)
-	{
-		int j, bytes;
-		sbyte[] st = new sbyte[16];
-		int fell_off;
-
-// Supported Modes of Operation
-
-		fell_off = 0;
-		switch (mode)
-		{
-		case ECB:
-			ecb_encrypt(buff);
-			return 0;
-		case CBC:
-			for (j = 0;j < 16;j++)
-			{
-				buff[j] ^= f[j];
-			}
-			ecb_encrypt(buff);
-			for (j = 0;j < 16;j++)
-			{
-				f[j] = buff[j];
-			}
-			return 0;
-
-		case CFB1:
-		case CFB2:
-		case CFB4:
-			bytes = mode - CFB1 + 1;
-			for (j = 0;j < bytes;j++)
-			{
-				fell_off = (fell_off << 8) | f[j];
-			}
-			for (j = 0;j < 16;j++)
-			{
-				st[j] = f[j];
-			}
-			for (j = bytes;j < 16;j++)
-			{
-				f[j - bytes] = f[j];
-			}
-			ecb_encrypt(st);
-			for (j = 0;j < bytes;j++)
-			{
-				buff[j] ^= st[j];
-				f[16 - bytes + j] = buff[j];
-			}
-			return fell_off;
-
-		case OFB1:
-		case OFB2:
-		case OFB4:
-		case OFB8:
-		case OFB16:
-
-			bytes = mode - OFB1 + 1;
-			ecb_encrypt(f);
-			for (j = 0;j < bytes;j++)
-			{
-				buff[j] ^= f[j];
-			}
-			return 0;
-
-	default:
-			return 0;
-		}
-	}
-
-/* Decrypt using selected mode of operation */
-	public virtual int decrypt(sbyte[] buff)
-	{
-		int j, bytes;
-		sbyte[] st = new sbyte[16];
-		int fell_off;
-
-   // Supported modes of operation
-		fell_off = 0;
-		switch (mode)
-		{
-		case ECB:
-			ecb_decrypt(buff);
-			return 0;
-		case CBC:
-			for (j = 0;j < 16;j++)
-			{
-				st[j] = f[j];
-				f[j] = buff[j];
-			}
-			ecb_decrypt(buff);
-			for (j = 0;j < 16;j++)
-			{
-				buff[j] ^= st[j];
-				st[j] = 0;
-			}
-			return 0;
-		case CFB1:
-		case CFB2:
-		case CFB4:
-			bytes = mode - CFB1 + 1;
-			for (j = 0;j < bytes;j++)
-			{
-				fell_off = (fell_off << 8) | f[j];
-			}
-			for (j = 0;j < 16;j++)
-			{
-				st[j] = f[j];
-			}
-			for (j = bytes;j < 16;j++)
-			{
-				f[j - bytes] = f[j];
-			}
-			ecb_encrypt(st);
-			for (j = 0;j < bytes;j++)
-			{
-				f[16 - bytes + j] = buff[j];
-				buff[j] ^= st[j];
-			}
-			return fell_off;
-		case OFB1:
-		case OFB2:
-		case OFB4:
-		case OFB8:
-		case OFB16:
-			bytes = mode - OFB1 + 1;
-			ecb_encrypt(f);
-			for (j = 0;j < bytes;j++)
-			{
-				buff[j] ^= f[j];
-			}
-			return 0;
-
-
-		default:
-			return 0;
-		}
-	}
-
-/* Clean up and delete left-overs */
-	public virtual void end()
-	{ // clean up
-		int i;
-		for (i = 0;i < 44;i++)
-		{
-			fkey[i] = rkey[i] = 0;
-		}
-		for (i = 0;i < 16;i++)
-		{
-			f[i] = 0;
-		}
-	}
-/*
-	public static void main(String[] args) {
-		int i;
-
-		byte[] key=new byte[16];
-		byte[] block=new byte[16];
-		byte[] iv=new byte[16];
-
-		for (i=0;i<16;i++) key[i]=0;
-		key[0]=1;
-		for (i=0;i<16;i++) iv[i]=(byte)i;
-		for (i=0;i<16;i++) block[i]=(byte)i;
-
-		AES a=new AES();
-
-		a.init(CBC,key,iv);
-		System.out.println("Plain= ");
-		for (i=0;i<16;i++)  System.out.format("%02X ", block[i]&0xff);
-		System.out.println("");
-
-		a.encrypt(block);
-
-		System.out.println("Encrypt= ");
-		for (i=0;i<16;i++)  System.out.format("%02X ", block[i]&0xff);
-		System.out.println("");
-
-		a.reset(CBC,iv);
-		a.decrypt(block);
-
-		System.out.println("Decrypt= ");
-		for (i=0;i<16;i++)  System.out.format("%02X ", block[i]&0xff);
-		System.out.println("");
-
-		a.end();
-
-	} */
-}
diff --git a/cs/BIG.cs b/cs/BIG.cs
deleted file mode 100644
index 40e2e6a..0000000
--- a/cs/BIG.cs
+++ /dev/null
@@ -1,1145 +0,0 @@
-/*
-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.
-*/
-
-/* AMCL BIG number class */
-
-public class BIG
-{
-	private long[] w = new long[ROM.NLEN];
-/* Constructors */
-	public BIG()
-	{
-		for (int i = 0;i < ROM.NLEN;i++)
-		{
-			w[i] = 0;
-		}
-	}
-
-	public BIG(int x)
-	{
-		w[0] = x;
-		for (int i = 1;i < ROM.NLEN;i++)
-		{
-			w[i] = 0;
-		}
-	}
-
-	public BIG(BIG x)
-	{
-		for (int i = 0;i < ROM.NLEN;i++)
-		{
-			w[i] = x.w[i];
-		}
-	}
-
-	public BIG(DBIG x)
-	{
-		for (int i = 0;i < ROM.NLEN;i++)
-		{
-			w[i] = x.w[i];
-		}
-	}
-
-	public BIG(long[] x)
-	{
-		for (int i = 0;i < ROM.NLEN;i++)
-		{
-			w[i] = x[i];
-		}
-	}
-
-	public virtual long get(int i)
-	{
-		return w[i];
-	}
-
-	public virtual void set(int i, long x)
-	{
-		w[i] = x;
-	}
-
-	public virtual void xortop(long x)
-	{
-		w[ROM.NLEN - 1] ^= x;
-	}
-
-	public virtual void ortop(long x)
-	{
-		w[ROM.NLEN - 1] |= x;
-	}
-
-/* calculate Field Excess */
-	public static long EXCESS(BIG a)
-	{
-		return ((a.w[ROM.NLEN - 1] & ROM.OMASK) >> (ROM.MODBITS % ROM.BASEBITS));
-	}
-
-/* test for zero */
-	public virtual bool iszilch()
-	{
-		for (int i = 0;i < ROM.NLEN;i++)
-		{
-			if (w[i] != 0)
-			{
-				return false;
-			}
-		}
-		return true;
-	}
-
-/* set to zero */
-	public virtual void zero()
-	{
-		for (int i = 0;i < ROM.NLEN;i++)
-		{
-			w[i] = 0;
-		}
-	}
-
-/* set to one */
-	public virtual void one()
-	{
-		w[0] = 1;
-		for (int i = 1;i < ROM.NLEN;i++)
-		{
-			w[i] = 0;
-		}
-	}
-
-/* Test for equal to one */
-	public virtual bool isunity()
-	{
-		for (int i = 1;i < ROM.NLEN;i++)
-		{
-			if (w[i] != 0)
-			{
-				return false;
-			}
-		}
-		if (w[0] != 1)
-		{
-			return false;
-		}
-		return true;
-	}
-
-/* Copy from another BIG */
-	public virtual void copy(BIG x)
-	{
-		for (int i = 0;i < ROM.NLEN;i++)
-		{
-			w[i] = x.w[i];
-		}
-	}
-
-	public virtual void copy(DBIG x)
-	{
-		for (int i = 0;i < ROM.NLEN;i++)
-		{
-			w[i] = x.w[i];
-		}
-	}
-
-/* Conditional swap of two bigs depending on d using XOR - no branches */
-	public virtual void cswap(BIG b, int d)
-	{
-		int i;
-		long t , c = (long)d;
-		c = ~(c - 1);
-
-		for (i = 0;i < ROM.NLEN;i++)
-		{
-			t = c & (w[i] ^ b.w[i]);
-			w[i] ^= t;
-			b.w[i] ^= t;
-		}
-	}
-
-	public virtual void cmove(BIG g, int d)
-	{
-		int i;
-		long  b = -d;
-
-		for (i = 0;i < ROM.NLEN;i++)
-		{
-			w[i] ^= (w[i] ^ g.w[i]) & b;
-		}
-	}
-
-
-/* normalise BIG - force all digits < 2^BASEBITS */
-	public virtual long norm()
-	{
-		long d , carry = 0;
-		for (int i = 0;i < ROM.NLEN - 1;i++)
-		{
-			d = w[i] + carry;
-			w[i] = d & ROM.MASK;
-			carry = d >> ROM.BASEBITS;
-		}
-		w[ROM.NLEN - 1] = (w[ROM.NLEN - 1] + carry);
-		return (w[ROM.NLEN - 1] >> ((8 * ROM.MODBYTES) % ROM.BASEBITS));
-	}
-
-/* Shift right by less than a word */
-	public virtual long fshr(int k)
-	{
-		long r = w[0] & (((long)1 << k) - 1); // shifted out part
-		for (int i = 0;i < ROM.NLEN - 1;i++)
-		{
-			w[i] = (w[i] >> k) | ((w[i + 1] << (ROM.BASEBITS - k)) & ROM.MASK);
-		}
-		w[ROM.NLEN - 1] = w[ROM.NLEN - 1] >> k;
-		return r;
-	}
-
-/* general shift right */
-	public virtual void shr(int k)
-	{
-		int n = k % ROM.BASEBITS;
-		int m = k / ROM.BASEBITS;
-		for (int i = 0;i < ROM.NLEN - m - 1;i++)
-		{
-			w[i] = (w[m + i] >> n) | ((w[m + i + 1] << (ROM.BASEBITS - n)) & ROM.MASK);
-		}
-		w[ROM.NLEN - m - 1] = w[ROM.NLEN - 1] >> n;
-		for (int i = ROM.NLEN - m;i < ROM.NLEN;i++)
-		{
-			w[i] = 0;
-		}
-	}
-
-/* Shift right by less than a word */
-	public virtual long fshl(int k)
-	{
-		w[ROM.NLEN - 1] = ((w[ROM.NLEN - 1] << k)) | (w[ROM.NLEN - 2]>>(ROM.BASEBITS - k));
-		for (int i = ROM.NLEN - 2;i > 0;i--)
-		{
-			w[i] = ((w[i] << k) & ROM.MASK) | (w[i - 1]>>(ROM.BASEBITS - k));
-		}
-		w[0] = (w[0] << k) & ROM.MASK;
-		return (w[ROM.NLEN - 1] >> ((8 * ROM.MODBYTES) % ROM.BASEBITS)); // return excess - only used in ff.c
-	}
-
-/* general shift left */
-	public virtual void shl(int k)
-	{
-		int n = k % ROM.BASEBITS;
-		int m = k / ROM.BASEBITS;
-
-		w[ROM.NLEN - 1] = ((w[ROM.NLEN - 1 - m] << n)) | (w[ROM.NLEN - m - 2]>>(ROM.BASEBITS - n));
-		for (int i = ROM.NLEN - 2;i > m;i--)
-		{
-			w[i] = ((w[i - m] << n) & ROM.MASK) | (w[i - m - 1]>>(ROM.BASEBITS - n));
-		}
-		w[m] = (w[0] << n) & ROM.MASK;
-		for (int i = 0;i < m;i++)
-		{
-			w[i] = 0;
-		}
-	}
-
-/* return number of bits */
-	public virtual int nbits()
-	{
-		int bts , k = ROM.NLEN - 1;
-		long c;
-		norm();
-		while (k >= 0 && w[k] == 0)
-		{
-			k--;
-		}
-		if (k < 0)
-		{
-			return 0;
-		}
-		bts = ROM.BASEBITS * k;
-		c = w[k];
-		while (c != 0)
-		{
-			c /= 2;
-			bts++;
-		}
-		return bts;
-	}
-
-	public virtual string toRawString()
-	{
-		BIG b = new BIG(this);
-		string s = "(";
-		for (int i = 0;i < ROM.NLEN - 1;i++)
-		{
-			s += b.w[i].ToString("x");
-			s += ",";
-		}
-		s += b.w[ROM.NLEN - 1].ToString("x");
-		s += ")";
-		return s;
-	}
-
-/* Convert to Hex String */
-	public override string ToString()
-	{
-		BIG b;
-		string s = "";
-		int len = nbits();
-
-		if (len % 4 == 0)
-		{
-			len /= 4;
-		}
-		else
-		{
-			len /= 4;
-			len++;
-		}
-		if (len < ROM.MODBYTES * 2)
-		{
-			len = ROM.MODBYTES * 2;
-		}
-
-		for (int i = len - 1;i >= 0;i--)
-		{
-			b = new BIG(this);
-			b.shr(i * 4);
-			s += (b.w[0] & 15).ToString("x");
-		}
-		return s;
-	}
-
-/* return this+x */
-	public virtual BIG plus(BIG x)
-	{
-		BIG s = new BIG(0);
-		for (int i = 0;i < ROM.NLEN;i++)
-		{
-			s.w[i] = w[i] + x.w[i];
-		}
-		return s;
-	}
-
-/* this+=x */
-	public virtual void add(BIG x)
-	{
-		for (int i = 0;i < ROM.NLEN;i++)
-		{
-			w[i] += x.w[i];
-		}
-	}
-
-/* this+=x, where x is int */
-	public virtual void inc(int x)
-	{
-		norm();
-		w[0] += x;
-	}
-
-/* return this.x */
-	public virtual BIG minus(BIG x)
-	{
-		BIG d = new BIG(0);
-		for (int i = 0;i < ROM.NLEN;i++)
-		{
-			d.w[i] = w[i] - x.w[i];
-		}
-		return d;
-	}
-
-/* this-=x */
-	public virtual void sub(BIG x)
-	{
-		for (int i = 0;i < ROM.NLEN;i++)
-		{
-			w[i] -= x.w[i];
-		}
-	}
-
-/* reverse subtract this=x-this */
-	public virtual void rsub(BIG x)
-	{
-		for (int i = 0;i < ROM.NLEN;i++)
-		{
-			w[i] = x.w[i] - w[i];
-		}
-	}
-
-/* this-=x where x is int */
-	public virtual void dec(int x)
-	{
-		norm();
-		w[0] -= (long)x;
-	}
-
-/* this*=x, where x is small int<NEXCESS */
-	public virtual void imul(int c)
-	{
-		for (int i = 0;i < ROM.NLEN;i++)
-		{
-			w[i] *= c;
-		}
-	}
-
-/* convert this BIG to byte array */
-	public virtual void tobytearray(sbyte[] b, int n)
-	{
-		norm();
-		BIG c = new BIG(this);
-
-		for (int i = ROM.MODBYTES - 1;i >= 0;i--)
-		{
-			b[i + n] = (sbyte)c.w[0];
-			c.fshr(8);
-		}
-	}
-
-/* convert from byte array to BIG */
-	public static BIG frombytearray(sbyte[] b, int n)
-	{
-		BIG m = new BIG(0);
-
-		for (int i = 0;i < ROM.MODBYTES;i++)
-		{
-			m.fshl(8);
-			m.w[0] += (int)b[i + n] & 0xff;
-			//m.inc((int)b[i]&0xff);
-		}
-		return m;
-	}
-
-	public virtual void toBytes(sbyte[] b)
-	{
-		tobytearray(b,0);
-	}
-
-	public static BIG fromBytes(sbyte[] b)
-	{
-		return frombytearray(b,0);
-	}
-
-
-/* set this[i]+=x*y+c, and return high part */
-
-	public virtual long muladd(long a, long b, long c, int i)
-	{
-		long x0, x1, y0, y1;
-		x0 = a & ROM.HMASK;
-		x1 = (a >> ROM.HBITS);
-		y0 = b & ROM.HMASK;
-		y1 = (b >> ROM.HBITS);
-		long bot = x0 * y0;
-		long top = x1 * y1;
-		long mid = x0 * y1 + x1 * y0;
-		x0 = mid & ROM.HMASK;
-		x1 = (mid >> ROM.HBITS);
-		bot += x0 << ROM.HBITS;
-		bot += c;
-		bot += w[i];
-		top += x1;
-		long carry = bot >> ROM.BASEBITS;
-		bot &= ROM.MASK;
-		top += carry;
-		w[i] = bot;
-		return top;
-	}
-
-/* this*=x, where x is >NEXCESS */
-	public virtual long pmul(int c)
-	{
-		long ak , carry = 0;
-		norm();
-		for (int i = 0;i < ROM.NLEN;i++)
-		{
-			ak = w[i];
-			w[i] = 0;
-			carry = muladd(ak,(long)c,carry,i);
-		}
-		return carry;
-	}
-
-/* this*=c and catch overflow in DBIG */
-	public virtual DBIG pxmul(int c)
-	{
-		DBIG m = new DBIG(0);
-		long carry = 0;
-		for (int j = 0;j < ROM.NLEN;j++)
-		{
-			carry = m.muladd(w[j],(long)c,carry,j);
-		}
-		m.w[ROM.NLEN] = carry;
-		return m;
-	}
-
-/* divide by 3 */
-	public virtual int div3()
-	{
-		long ak , @base , carry = 0;
-		norm();
-		@base = ((long)1 << ROM.BASEBITS);
-		for (int i = ROM.NLEN - 1;i >= 0;i--)
-		{
-			ak = (carry * @base + w[i]);
-			w[i] = ak / 3;
-			carry = ak % 3;
-		}
-		return (int)carry;
-	}
-
-/* return a*b where result fits in a BIG */
-	public static BIG smul(BIG a, BIG b)
-	{
-		long carry;
-		BIG c = new BIG(0);
-		for (int i = 0;i < ROM.NLEN;i++)
-		{
-			carry = 0;
-			for (int j = 0;j < ROM.NLEN;j++)
-			{
-				if (i + j < ROM.NLEN)
-				{
-					carry = c.muladd(a.w[i],b.w[j],carry,i + j);
-				}
-			}
-		}
-		return c;
-	}
-
-/* Compare a and b, return 0 if a==b, -1 if a<b, +1 if a>b. Inputs must be normalised */
-	public static int comp(BIG a, BIG b)
-	{
-		for (int i = ROM.NLEN - 1;i >= 0;i--)
-		{
-			if (a.w[i] == b.w[i])
-			{
-				continue;
-			}
-			if (a.w[i] > b.w[i])
-			{
-				return 1;
-			}
-			else
-			{
-				return -1;
-			}
-		}
-		return 0;
-	}
-
-/* set x = x mod 2^m */
-	public virtual void mod2m(int m)
-	{
-		int i, wd, bt;
-		long msk;
-
-		wd = m / ROM.BASEBITS;
-		bt = m % ROM.BASEBITS;
-		msk = ((long)1 << bt) - 1;
-		w[wd] &= msk;
-		for (i = wd + 1;i < ROM.NLEN;i++)
-		{
-			w[i] = 0;
-		}
-	}
-
-/* Arazi and Qi inversion mod 256 */
-	public static int invmod256(int a)
-	{
-		int U, t1, t2, b, c;
-		t1 = 0;
-		c = (a >> 1) & 1;
-		t1 += c;
-		t1 &= 1;
-		t1 = 2 - t1;
-		t1 <<= 1;
-		U = t1 + 1;
-
-// i=2
-		b = a & 3;
-		t1 = U * b;
-		t1 >>= 2;
-		c = (a >> 2) & 3;
-		t2 = (U * c) & 3;
-		t1 += t2;
-		t1 *= U;
-		t1 &= 3;
-		t1 = 4 - t1;
-		t1 <<= 2;
-		U += t1;
-
-// i=4
-		b = a & 15;
-		t1 = U * b;
-		t1 >>= 4;
-		c = (a >> 4) & 15;
-		t2 = (U * c) & 15;
-		t1 += t2;
-		t1 *= U;
-		t1 &= 15;
-		t1 = 16 - t1;
-		t1 <<= 4;
-		U += t1;
-
-		return U;
-	}
-
-/* a=1/a mod 2^256. This is very fast! */
-	public virtual void invmod2m()
-	{
-		int i;
-		BIG U = new BIG(0);
-		BIG b = new BIG(0);
-		BIG c = new BIG(0);
-
-		U.inc(invmod256(lastbits(8)));
-
-		for (i = 8;i < 256;i <<= 1)
-		{
-			b.copy(this);
-			b.mod2m(i);
-			BIG t1 = BIG.smul(U,b);
-			t1.shr(i);
-			c.copy(this);
-			c.shr(i);
-			c.mod2m(i);
-
-			BIG t2 = BIG.smul(U,c);
-			t2.mod2m(i);
-			t1.add(t2);
-			b = BIG.smul(t1,U);
-			t1.copy(b);
-			t1.mod2m(i);
-
-			t2.one();
-			t2.shl(i);
-			t1.rsub(t2);
-			t1.norm();
-			t1.shl(i);
-			U.add(t1);
-		}
-		this.copy(U);
-	}
-
-/* reduce this mod m */
-	public virtual void mod(BIG m)
-	{
-		int k = 0;
-
-		norm();
-		if (comp(this,m) < 0)
-		{
-			return;
-		}
-		do
-		{
-			m.fshl(1);
-			k++;
-		} while (comp(this,m) >= 0);
-
-		while (k > 0)
-		{
-			m.fshr(1);
-			if (comp(this,m) >= 0)
-			{
-				sub(m);
-				norm();
-			}
-			k--;
-		}
-	}
-
-/* divide this by m */
-	public virtual void div(BIG m)
-	{
-		int k = 0;
-		norm();
-		BIG e = new BIG(1);
-		BIG b = new BIG(this);
-		zero();
-
-		while (comp(b,m) >= 0)
-		{
-			e.fshl(1);
-			m.fshl(1);
-			k++;
-		}
-
-		while (k > 0)
-		{
-			m.fshr(1);
-			e.fshr(1);
-			if (comp(b,m) >= 0)
-			{
-				add(e);
-				norm();
-				b.sub(m);
-				b.norm();
-			}
-			k--;
-		}
-	}
-
-/* return parity */
-	public virtual int parity()
-	{
-		return (int)(w[0] % 2);
-	}
-
-/* return n-th bit */
-	public virtual int bit(int n)
-	{
-		if ((w[n / ROM.BASEBITS] & ((long)1 << (n % ROM.BASEBITS)))>0)
-		{
-			return 1;
-		}
-		else
-		{
-			return 0;
-		}
-	}
-
-/* return n last bits */
-	public virtual int lastbits(int n)
-	{
-		int msk = (1 << n) - 1;
-		norm();
-		return ((int)w[0]) & msk;
-	}
-
-/* get 8*MODBYTES size random number */
-	public static BIG random(RAND rng)
-	{
-		BIG m = new BIG(0);
-		int i , b , j = 0, r = 0;
-
-/* generate random BIG */
-		for (i = 0;i < 8 * ROM.MODBYTES;i++)
-		{
-			if (j == 0)
-			{
-				r = rng.Byte;
-			}
-			else
-			{
-				r >>= 1;
-			}
-
-			b = r & 1;
-			m.shl(1);
-			m.w[0] += b; // m.inc(b);
-			j++;
-			j &= 7;
-		}
-		return m;
-	}
-
-/* Create random BIG in portable way, one bit at a time */
-	public static BIG randomnum(BIG q, RAND rng)
-	{
-		DBIG d = new DBIG(0);
-		int i , b , j = 0, r = 0;
-		for (i = 0;i < 2 * ROM.MODBITS;i++)
-		{
-			if (j == 0)
-			{
-				r = rng.Byte;
-			}
-			else
-			{
-				r >>= 1;
-			}
-
-			b = r & 1;
-			d.shl(1);
-			d.w[0] += b; // m.inc(b);
-			j++;
-			j &= 7;
-		}
-		BIG m = d.mod(q);
-		return m;
-	}
-
-/* return NAF value as +/- 1, 3 or 5. x and x3 should be normed.
-nbs is number of bits processed, and nzs is number of trailing 0s detected */
-	public static int[] nafbits(BIG x, BIG x3, int i)
-	{
-		int[] n = new int[3];
-		int nb = x3.bit(i) - x.bit(i);
-		int j;
-		n[1] = 1;
-		n[0] = 0;
-		if (nb == 0)
-		{
-			n[0] = 0;
-			return n;
-		}
-		if (i == 0)
-		{
-			n[0] = nb;
-			return n;
-		}
-		if (nb > 0)
-		{
-			n[0] = 1;
-		}
-		else
-		{
-			n[0] = (-1);
-		}
-
-		for (j = i - 1;j > 0;j--)
-		{
-			n[1]++;
-			n[0] *= 2;
-			nb = x3.bit(j) - x.bit(j);
-			if (nb > 0)
-			{
-				n[0] += 1;
-			}
-			if (nb < 0)
-			{
-				n[0] -= 1;
-			}
-			if (n[0] > 5 || n[0] < -5)
-			{
-				break;
-			}
-		}
-
-		if (n[0] % 2 != 0 && j != 0)
-		{ // backtrack
-			if (nb > 0)
-			{
-				n[0] = (n[0] - 1) / 2;
-			}
-			if (nb < 0)
-			{
-				n[0] = (n[0] + 1) / 2;
-			}
-			n[1]--;
-		}
-		while (n[0] % 2 == 0)
-		{ // remove trailing zeros
-			n[0] /= 2;
-			n[2]++;
-			n[1]--;
-		}
-		return n;
-	}
-
-/* return a*b as DBIG */
-	public static DBIG mul(BIG a, BIG b)
-	{
-		DBIG c = new DBIG(0);
-		long carry;
-		a.norm();
-		b.norm();
-
-		for (int i = 0;i < ROM.NLEN;i++)
-		{
-			carry = 0;
-			for (int j = 0;j < ROM.NLEN;j++)
-			{
-				carry = c.muladd(a.w[i],b.w[j],carry,i + j);
-			}
-			c.w[ROM.NLEN + i] = carry;
-		}
-
-		return c;
-	}
-
-/* return a^2 as DBIG */
-	public static DBIG sqr(BIG a)
-	{
-		DBIG c = new DBIG(0);
-		long carry;
-		a.norm();
-		for (int i = 0;i < ROM.NLEN;i++)
-		{
-			carry = 0;
-			for (int j = i + 1;j < ROM.NLEN;j++)
-			{
-				carry = c.muladd(2 * a.w[i],a.w[j],carry,i + j);
-			}
-			c.w[ROM.NLEN + i] = carry;
-		}
-
-		for (int i = 0;i < ROM.NLEN;i++)
-		{
-			c.w[2 * i + 1] += c.muladd(a.w[i],a.w[i],0,2 * i);
-		}
-
-		c.norm();
-		return c;
-	}
-
-/* reduce a DBIG to a BIG using the appropriate form of the modulus */
-	public static BIG mod(DBIG d)
-	{
-		BIG b;
-		if (ROM.MODTYPE == ROM.PSEUDO_MERSENNE)
-		{
-			long v, tw;
-			BIG t = d.Split(ROM.MODBITS);
-			b = new BIG(d);
-			unchecked
-			{
-				v = t.pmul((int)ROM.MConst);
-			}
-			tw = t.w[ROM.NLEN - 1];
-			t.w[ROM.NLEN - 1] &= ROM.TMASK;
-			t.w[0] += (ROM.MConst * ((tw >> ROM.TBITS) + (v << (ROM.BASEBITS - ROM.TBITS))));
-
-			b.add(t);
-			b.norm();
-		}
-		if (ROM.MODTYPE == ROM.MONTGOMERY_FRIENDLY)
-		{
-			for (int i = 0;i < ROM.NLEN;i++)
-			{
-				d.w[ROM.NLEN + i] += d.muladd(d.w[i],ROM.MConst - 1,d.w[i],ROM.NLEN + i - 1);
-			}
-
-			b = new BIG(0);
-
-			for (int i = 0;i < ROM.NLEN;i++)
-			{
-				b.w[i] = d.w[ROM.NLEN + i];
-			}
-			b.norm();
-		}
-
-		if (ROM.MODTYPE == ROM.NOT_SPECIAL)
-		{
-			BIG md = new BIG(ROM.Modulus);
-			long m, carry;
-			for (int i = 0;i < ROM.NLEN;i++)
-			{
-				if (ROM.MConst == -1)
-				{
-					m = (-d.w[i]) & ROM.MASK;
-				}
-				else
-				{
-					if (ROM.MConst == 1)
-					{
-						m = d.w[i];
-					}
-					else
-					{
-						m = (ROM.MConst * d.w[i]) & ROM.MASK;
-					}
-				}
-
-				carry = 0;
-				for (int j = 0;j < ROM.NLEN;j++)
-				{
-					carry = d.muladd(m,md.w[j],carry,i + j);
-				}
-				d.w[ROM.NLEN + i] += carry;
-			}
-
-			b = new BIG(0);
-			for (int i = 0;i < ROM.NLEN;i++)
-			{
-				b.w[i] = d.w[ROM.NLEN + i];
-			}
-			b.norm();
-		}
-
-		return b;
-	}
-
-/* return a*b mod m */
-	public static BIG modmul(BIG a, BIG b, BIG m)
-	{
-		a.mod(m);
-		b.mod(m);
-		DBIG d = mul(a,b);
-		return d.mod(m);
-	}
-
-/* return a^2 mod m */
-	public static BIG modsqr(BIG a, BIG m)
-	{
-		a.mod(m);
-		DBIG d = sqr(a);
-		return d.mod(m);
-	}
-
-/* return -a mod m */
-	public static BIG modneg(BIG a, BIG m)
-	{
-		a.mod(m);
-		return m.minus(a);
-	}
-
-/* return this^e mod m */
-	public virtual BIG powmod(BIG e, BIG m)
-	{
-		int bt;
-		norm();
-		e.norm();
-		BIG a = new BIG(1);
-		BIG z = new BIG(e);
-		BIG s = new BIG(this);
-		while (true)
-		{
-			bt = z.parity();
-			z.fshr(1);
-			if (bt == 1)
-			{
-				a = modmul(a,s,m);
-			}
-			if (z.iszilch())
-			{
-				break;
-			}
-			s = modsqr(s,m);
-		}
-		return a;
-	}
-
-/* Jacobi Symbol (this/p). Returns 0, 1 or -1 */
-	public virtual int jacobi(BIG p)
-	{
-		int n8 , k , m = 0;
-		BIG t = new BIG(0);
-		BIG x = new BIG(0);
-		BIG n = new BIG(0);
-		BIG zilch = new BIG(0);
-		BIG one = new BIG(1);
-		if (p.parity() == 0 || comp(this,zilch) == 0 || comp(p,one) <= 0)
-		{
-			return 0;
-		}
-		norm();
-		x.copy(this);
-		n.copy(p);
-		x.mod(p);
-
-		while (comp(n,one) > 0)
-		{
-			if (comp(x,zilch) == 0)
-			{
-				return 0;
-			}
-			n8 = n.lastbits(3);
-			k = 0;
-			while (x.parity() == 0)
-			{
-				k++;
-				x.shr(1);
-			}
-			if (k % 2 == 1)
-			{
-				m += (n8 * n8 - 1) / 8;
-			}
-			m += (n8 - 1) * (x.lastbits(2) - 1) / 4;
-			t.copy(n);
-			t.mod(x);
-			n.copy(x);
-			x.copy(t);
-			m %= 2;
-
-		}
-		if (m == 0)
-		{
-			return 1;
-		}
-		else
-		{
-			return -1;
-		}
-	}
-
-/* this=1/this mod p. Binary method */
-	public virtual void invmodp(BIG p)
-	{
-		mod(p);
-		BIG u = new BIG(this);
-
-		BIG v = new BIG(p);
-		BIG x1 = new BIG(1);
-		BIG x2 = new BIG(0);
-		BIG t = new BIG(0);
-		BIG one = new BIG(1);
-		while (comp(u,one) != 0 && comp(v,one) != 0)
-		{
-			while (u.parity() == 0)
-			{
-				u.shr(1);
-				if (x1.parity() != 0)
-				{
-					x1.add(p);
-					x1.norm();
-				}
-				x1.shr(1);
-			}
-			while (v.parity() == 0)
-			{
-				v.shr(1);
-				if (x2.parity() != 0)
-				{
-					x2.add(p);
-					x2.norm();
-				}
-				x2.shr(1);
-			}
-			if (comp(u,v) >= 0)
-			{
-				u.sub(v);
-				u.norm();
-				if (comp(x1,x2) >= 0)
-				{
-					x1.sub(x2);
-				}
-				else
-				{
-					t.copy(p);
-					t.sub(x2);
-					x1.add(t);
-				}
-				x1.norm();
-			}
-			else
-			{
-				v.sub(u);
-				v.norm();
-				if (comp(x2,x1) >= 0)
-				{
-					x2.sub(x1);
-				}
-				else
-				{
-					t.copy(p);
-					t.sub(x1);
-					x2.add(t);
-				}
-				x2.norm();
-			}
-		}
-		if (comp(u,one) == 0)
-		{
-			copy(x1);
-		}
-		else
-		{
-			copy(x2);
-		}
-	}
-}
diff --git a/cs/DBIG.cs b/cs/DBIG.cs
deleted file mode 100644
index 935fc52..0000000
--- a/cs/DBIG.cs
+++ /dev/null
@@ -1,374 +0,0 @@
-/*
-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.
-*/
-
-/* AMCL double length DBIG number class */
-
-public class DBIG
-{
-	protected internal long[] w = new long[ROM.DNLEN];
-
-/* Constructors */
-	public DBIG(int x)
-	{
-		w[0] = x;
-		for (int i = 1;i < ROM.DNLEN;i++)
-		{
-			w[i] = 0;
-		}
-	}
-
-	public DBIG(DBIG x)
-	{
-		for (int i = 0;i < ROM.DNLEN;i++)
-		{
-			w[i] = x.w[i];
-		}
-	}
-
-	public DBIG(BIG x)
-	{
-		for (int i = 0;i < ROM.NLEN - 1;i++)
-		{
-			w[i] = x.get(i);
-		}
-
-		w[ROM.NLEN - 1] = x.get(ROM.NLEN - 1) & ROM.MASK; // top word normalized
-		w[ROM.NLEN] = x.get(ROM.NLEN - 1) >> ROM.BASEBITS;
-
-		for (int i = ROM.NLEN + 1;i < ROM.DNLEN;i++)
-		{
-			w[i] = 0;
-		}
-	}
-
-/* get and set digits of this */
-	public virtual long get(int i)
-	{
-		return w[i];
-	}
-
-	public virtual void set(int i, long x)
-	{
-		w[i] = x;
-	}
-
-	public virtual void inc(int i, long x)
-	{
-		w[i] += x;
-	}
-
-/* test this=0? */
-	public virtual bool iszilch()
-	{
-		for (int i = 0;i < ROM.DNLEN;i++)
-		{
-			if (w[i] != 0)
-			{
-				return false;
-			}
-		}
-		return true;
-	}
-
-/* normalise this */
-	public virtual void norm()
-	{
-		long d , carry = 0;
-		for (int i = 0;i < ROM.DNLEN - 1;i++)
-		{
-			d = w[i] + carry;
-			w[i] = d & ROM.MASK;
-			carry = d >> ROM.BASEBITS;
-		}
-		w[ROM.DNLEN - 1] = (w[ROM.DNLEN - 1] + carry);
-	}
-
-/* shift this right by k bits */
-	public virtual void shr(int k)
-	{
-		int n = k % ROM.BASEBITS;
-		int m = k / ROM.BASEBITS;
-		for (int i = 0;i < ROM.DNLEN - m - 1;i++)
-		{
-			w[i] = (w[m + i] >> n) | ((w[m + i + 1] << (ROM.BASEBITS - n)) & ROM.MASK);
-		}
-		w[ROM.DNLEN - m - 1] = w[ROM.DNLEN - 1] >> n;
-		for (int i = ROM.DNLEN - m;i < ROM.DNLEN;i++)
-		{
-			w[i] = 0;
-		}
-	}
-
-/* shift this left by k bits */
-	public virtual void shl(int k)
-	{
-		int n = k % ROM.BASEBITS;
-		int m = k / ROM.BASEBITS;
-
-		w[ROM.DNLEN - 1] = ((w[ROM.DNLEN - 1 - m] << n)) | (w[ROM.DNLEN - m - 2]>>(ROM.BASEBITS - n));
-		for (int i = ROM.DNLEN - 2;i > m;i--)
-		{
-			w[i] = ((w[i - m] << n) & ROM.MASK) | (w[i - m - 1]>>(ROM.BASEBITS - n));
-		}
-		w[m] = (w[0] << n) & ROM.MASK;
-		for (int i = 0;i < m;i++)
-		{
-			w[i] = 0;
-		}
-	}
-
-/* return number of bits in this */
-	public virtual int nbits()
-	{
-		int bts , k = ROM.DNLEN - 1;
-		long c;
-		norm();
-		while (w[k] == 0 && k >= 0)
-		{
-			k--;
-		}
-		if (k < 0)
-		{
-			return 0;
-		}
-		bts = ROM.BASEBITS * k;
-		c = w[k];
-		while (c != 0)
-		{
-			c /= 2;
-			bts++;
-		}
-		return bts;
-	}
-
-/* convert this to string */
-	public override string ToString()
-	{
-		DBIG b;
-		string s = "";
-		int len = nbits();
-		if (len % 4 == 0)
-		{
-			len >>= 2; //len/=4;
-		}
-		else
-		{
-			len >>= 2;
-			len++;
-		}
-
-		for (int i = len - 1;i >= 0;i--)
-		{
-			b = new DBIG(this);
-			b.shr(i * 4);
-			s += (b.w[0] & 15).ToString("x");
-		}
-		return s;
-	}
-
-/* return this+x */
-/*
-	public DBIG plus(DBIG x) {
-		DBIG s=new DBIG(0);
-		for (int i=0;i<ROM.DNLEN;i++)
-			s.w[i]=w[i]+x.w[i];
-		return s;
-	}
-*/
-/* return this-x */
-/*
-	public DBIG minus(DBIG x) {
-		DBIG d=new DBIG(0);
-		for (int i=0;i<ROM.DNLEN;i++)
-			d.w[i]=w[i]-x.w[i];
-		return d;
-	}
-*/
-/* this+=x */
-	public virtual void add(DBIG x)
-	{
-		for (int i = 0;i < ROM.DNLEN;i++)
-		{
-			w[i] += x.w[i];
-		}
-	}
-
-/* this-=x */
-	public virtual void sub(DBIG x)
-	{
-		for (int i = 0;i < ROM.DNLEN;i++)
-		{
-			w[i] -= x.w[i];
-		}
-	}
-
-/* set this[i]+=x*y+c, and return high part */
-/* This is time critical */
-/* What if you knew the bottom half in advance ?? */
-	public virtual long muladd(long a, long b, long c, int i)
-	{
-		long x0, x1, y0, y1;
-		x0 = a & ROM.HMASK;
-		x1 = (a >> ROM.HBITS);
-		y0 = b & ROM.HMASK;
-		y1 = (b >> ROM.HBITS);
-		long bot = x0 * y0;
-		long top = x1 * y1;
-		long mid = x0 * y1 + x1 * y0;
-		x0 = mid & ROM.HMASK;
-		x1 = (mid >> ROM.HBITS);
-		bot += x0 << ROM.HBITS;
-		bot += c;
-		bot += w[i];
-		top += x1;
-		long carry = bot >> ROM.BASEBITS;
-		bot &= ROM.MASK;
-		top += carry;
-		w[i] = bot;
-		return top;
-	}
-
-/* Compare a and b, return 0 if a==b, -1 if a<b, +1 if a>b. Inputs must be normalised */
-	public static int comp(DBIG a, DBIG b)
-	{
-		for (int i = ROM.DNLEN - 1;i >= 0;i--)
-		{
-			if (a.w[i] == b.w[i])
-			{
-				continue;
-			}
-			if (a.w[i] > b.w[i])
-			{
-				return 1;
-			}
-			else
-			{
-				return -1;
-			}
-		}
-		return 0;
-	}
-
-/* reduces this DBIG mod a BIG, and returns the BIG */
-	public virtual BIG mod(BIG c)
-	{
-		int k = 0;
-		norm();
-		DBIG m = new DBIG(c);
-
-		if (comp(this,m) < 0)
-		{
-			return new BIG(this);
-		}
-
-		do
-		{
-			m.shl(1);
-			k++;
-		} while (comp(this,m) >= 0);
-
-		while (k > 0)
-		{
-			m.shr(1);
-			if (comp(this,m) >= 0)
-			{
-				sub(m);
-				norm();
-			}
-			k--;
-		}
-		return new BIG(this);
-	}
-
-/* reduces this DBIG mod a DBIG in place */
-/*	public void mod(DBIG m)
-	{
-		int k=0;
-		if (comp(this,m)<0) return;
-
-		do
-		{
-			m.shl(1);
-			k++;
-		}
-		while (comp(this,m)>=0);
-
-		while (k>0)
-		{
-			m.shr(1);
-			if (comp(this,m)>=0)
-			{
-				sub(m);
-				norm();
-			}
-			k--;
-		}
-		return;
-
-	}*/
-
-/* return this/c */
-	public virtual BIG div(BIG c)
-	{
-		int k = 0;
-		DBIG m = new DBIG(c);
-		BIG a = new BIG(0);
-		BIG e = new BIG(1);
-		norm();
-
-		while (comp(this,m) >= 0)
-		{
-			e.fshl(1);
-			m.shl(1);
-			k++;
-		}
-
-		while (k > 0)
-		{
-			m.shr(1);
-			e.shr(1);
-			if (comp(this,m) > 0)
-			{
-				a.add(e);
-				a.norm();
-				sub(m);
-				norm();
-			}
-			k--;
-		}
-		return a;
-	}
-
-/* split DBIG at position n, return higher half, keep lower half */
-	public virtual BIG Split(int n)
-	{
-		BIG t = new BIG(0);
-		int m = n % ROM.BASEBITS;
-		long nw , carry = w[ROM.DNLEN - 1] << (ROM.BASEBITS - m);
-
-		for (int i = ROM.DNLEN - 2;i >= ROM.NLEN - 1;i--)
-		{
-			nw = (w[i] >> m) | carry;
-			carry = (w[i] << (ROM.BASEBITS - m)) & ROM.MASK;
-			t.set(i - ROM.NLEN + 1,nw);
-		}
-		w[ROM.NLEN - 1] &= (((long)1 << m) - 1);
-		return t;
-	}
-}
diff --git a/cs/ECDH.cs b/cs/ECDH.cs
deleted file mode 100644
index f63dff1..0000000
--- a/cs/ECDH.cs
+++ /dev/null
@@ -1,778 +0,0 @@
-/*
-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.
-*/
-
-/* Elliptic Curve API high-level functions  */
-
-public sealed class ECDH
-{
-	public const int INVALID_PUBLIC_KEY = -2;
-	public const int ERROR = -3;
-	public const int INVALID = -4;
-	public static readonly int EFS = ROM.MODBYTES;
-	public static readonly int EGS = ROM.MODBYTES;
-	public static readonly int EAS = AES.KS;
-	public static readonly int EBS = AES.BS;
-
-/* Convert Integer to n-byte array */
-	private static sbyte[] inttoBytes(int n, int len)
-	{
-		int i;
-		sbyte[] b = new sbyte[len];
-
-		for (i = 0;i < len;i++)
-		{
-			b[i] = 0;
-		}
-		i = len;
-		while (n > 0 && i > 0)
-		{
-			i--;
-			b[i] = unchecked((sbyte)(n & 0xff));
-			n /= 256;
-		}
-		return b;
-	}
-
-/* Key Derivation Functions */
-/* Input octet Z */
-/* Output key of length olen */
-	public static sbyte[] KDF1(sbyte[] Z, int olen)
-	{
-/* NOTE: the parameter olen is the length of the output K in bytes */
-		HASH H = new HASH();
-		int hlen = HASH.len;
-		sbyte[] K = new sbyte[olen];
-
-		sbyte[] B;
-		int counter , cthreshold , k = 0;
-
-		for (int i = 0;i < K.Length;i++)
-		{
-			K[i] = 0;
-		}
-
-		cthreshold = olen / hlen;
-		if (olen % hlen != 0)
-		{
-			cthreshold++;
-		}
-
-		for (counter = 0;counter < cthreshold;counter++)
-		{
-			H.process_array(Z);
-			if (counter > 0)
-			{
-				H.process_num(counter);
-			}
-			B = H.hash();
-			if (k + hlen > olen)
-			{
-				for (int i = 0;i < olen % hlen;i++)
-				{
-					K[k++] = B[i];
-				}
-			}
-			else
-			{
-				for (int i = 0;i < hlen;i++)
-				{
-					K[k++] = B[i];
-				}
-			}
-		}
-		return K;
-	}
-
-	public static sbyte[] KDF2(sbyte[] Z, sbyte[] P, int olen)
-	{
-/* NOTE: the parameter olen is the length of the output k in bytes */
-		HASH H = new HASH();
-		int hlen = HASH.len;
-		sbyte[] K = new sbyte[olen];
-
-		sbyte[] B = new sbyte[hlen];
-		int counter , cthreshold , k = 0;
-
-		for (int i = 0;i < K.Length;i++)
-		{
-			K[i] = 0;
-		}
-
-		cthreshold = olen / hlen;
-		if (olen % hlen != 0)
-		{
-			cthreshold++;
-		}
-
-		for (counter = 1;counter <= cthreshold;counter++)
-		{
-			H.process_array(Z);
-			H.process_num(counter);
-			H.process_array(P);
-			B = H.hash();
-			if (k + hlen > olen)
-			{
-				for (int i = 0;i < olen % hlen;i++)
-				{
-					K[k++] = B[i];
-				}
-			}
-			else
-			{
-				for (int i = 0;i < hlen;i++)
-				{
-					K[k++] = B[i];
-				}
-			}
-		}
-		return K;
-	}
-
-/* Password based Key Derivation Function */
-/* Input password p, salt s, and repeat count */
-/* Output key of length olen */
-	public static sbyte[] PBKDF2(sbyte[] Pass, sbyte[] Salt, int rep, int olen)
-	{
-		int i, j, k, d, opt;
-		d = olen / 32;
-		if (olen % 32 != 0)
-		{
-			d++;
-		}
-		sbyte[] F = new sbyte[EFS];
-		sbyte[] U = new sbyte[EFS];
-		sbyte[] S = new sbyte[Salt.Length + 4];
-
-		sbyte[] K = new sbyte[d * EFS];
-		opt = 0;
-
-		for (i = 1;i <= d;i++)
-		{
-			for (j = 0;j < Salt.Length;j++)
-			{
-				S[j] = Salt[j];
-			}
-			sbyte[] N = inttoBytes(i,4);
-			for (j = 0;j < 4;j++)
-			{
-				S[Salt.Length + j] = N[j];
-			}
-
-			HMAC(S,Pass,F);
-
-			for (j = 0;j < EFS;j++)
-			{
-				U[j] = F[j];
-			}
-			for (j = 2;j <= rep;j++)
-			{
-				HMAC(U,Pass,U);
-				for (k = 0;k < EFS;k++)
-				{
-					F[k] ^= U[k];
-				}
-			}
-			for (j = 0;j < EFS;j++)
-			{
-				K[opt++] = F[j];
-			}
-		}
-		sbyte[] key = new sbyte[olen];
-		for (i = 0;i < olen;i++)
-		{
-			key[i] = K[i];
-		}
-		return key;
-	}
-
-/* Calculate HMAC of m using key k. HMAC is tag of length olen */
-	public static int HMAC(sbyte[] M, sbyte[] K, sbyte[] tag)
-	{
-	/* Input is from an octet m        *
-	* olen is requested output length in bytes. k is the key  *
-	* The output is the calculated tag */
-		int b;
-		sbyte[] B;
-		sbyte[] K0 = new sbyte[64];
-		int olen = tag.Length;
-
-		b = K0.Length;
-		if (olen < 4 || olen> HASH.len)
-		{
-			return 0;
-		}
-
-		for (int i = 0;i < b;i++)
-		{
-			K0[i] = 0;
-		}
-
-		HASH H = new HASH();
-
-		if (K.Length > b)
-		{
-			H.process_array(K);
-			B = H.hash();
-			for (int i = 0;i < 32;i++)
-			{
-				K0[i] = B[i];
-			}
-		}
-		else
-		{
-			for (int i = 0;i < K.Length;i++)
-			{
-				K0[i] = K[i];
-			}
-		}
-
-		for (int i = 0;i < b;i++)
-		{
-			K0[i] ^= 0x36;
-		}
-		H.process_array(K0);
-		H.process_array(M);
-		B = H.hash();
-
-		for (int i = 0;i < b;i++)
-		{
-			K0[i] ^= 0x6a;
-		}
-		H.process_array(K0);
-		H.process_array(B);
-		B = H.hash();
-
-		for (int i = 0;i < olen;i++)
-		{
-			tag[i] = B[i];
-		}
-
-		return 1;
-	}
-
-/* AES encryption/decryption. Encrypt byte array M using key K and returns ciphertext */
-	public static sbyte[] AES_CBC_IV0_ENCRYPT(sbyte[] K, sbyte[] M)
-	{ // AES CBC encryption, with Null IV and key K
-	/* Input is from an octet string M, output is to an octet string C */
-	/* Input is padded as necessary to make up a full final block */
-		AES a = new AES();
-		bool fin;
-		int i, j, ipt, opt;
-		sbyte[] buff = new sbyte[16];
-		int clen = 16 + (M.Length / 16) * 16;
-
-		sbyte[] C = new sbyte[clen];
-		int padlen;
-
-		a.init(AES.CBC,K,null);
-
-		ipt = opt = 0;
-		fin = false;
-		for (;;)
-		{
-			for (i = 0;i < 16;i++)
-			{
-				if (ipt < M.Length)
-				{
-					buff[i] = M[ipt++];
-				}
-				else
-				{
-					fin = true;
-					break;
-				}
-			}
-			if (fin)
-			{
-				break;
-			}
-			a.encrypt(buff);
-			for (i = 0;i < 16;i++)
-			{
-				C[opt++] = buff[i];
-			}
-		}
-
-/* last block, filled up to i-th index */
-
-		padlen = 16 - i;
-		for (j = i;j < 16;j++)
-		{
-			buff[j] = (sbyte)padlen;
-		}
-
-		a.encrypt(buff);
-
-		for (i = 0;i < 16;i++)
-		{
-			C[opt++] = buff[i];
-		}
-		a.end();
-		return C;
-	}
-
-/* returns plaintext if all consistent, else returns null string */
-	public static sbyte[] AES_CBC_IV0_DECRYPT(sbyte[] K, sbyte[] C)
-	{ // padding is removed
-		AES a = new AES();
-		int i, ipt, opt, ch;
-		sbyte[] buff = new sbyte[16];
-		sbyte[] MM = new sbyte[C.Length];
-		bool fin, bad;
-		int padlen;
-		ipt = opt = 0;
-
-		a.init(AES.CBC,K,null);
-
-		if (C.Length == 0)
-		{
-			return new sbyte[0];
-		}
-		ch = C[ipt++];
-
-		fin = false;
-
-		for (;;)
-		{
-			for (i = 0;i < 16;i++)
-			{
-				buff[i] = (sbyte)ch;
-				if (ipt >= C.Length)
-				{
-					fin = true;
-					break;
-				}
-				else
-				{
-					ch = C[ipt++];
-				}
-			}
-			a.decrypt(buff);
-			if (fin)
-			{
-				break;
-			}
-			for (i = 0;i < 16;i++)
-			{
-				MM[opt++] = buff[i];
-			}
-		}
-
-		a.end();
-		bad = false;
-		padlen = buff[15];
-		if (i != 15 || padlen < 1 || padlen>16)
-		{
-			bad = true;
-		}
-		if (padlen >= 2 && padlen <= 16)
-		{
-			for (i = 16 - padlen;i < 16;i++)
-			{
-				if (buff[i] != padlen)
-				{
-					bad = true;
-				}
-			}
-		}
-
-		if (!bad)
-		{
-			for (i = 0;i < 16 - padlen;i++)
-			{
-					MM[opt++] = buff[i];
-			}
-		}
-
-		if (bad)
-		{
-			return new sbyte[0];
-		}
-
-		sbyte[] M = new sbyte[opt];
-		for (i = 0;i < opt;i++)
-		{
-			M[i] = MM[i];
-		}
-
-		return M;
-	}
-
-/* Calculate a public/private EC GF(p) key pair W,S where W=S.G mod EC(p),
- * where S is the secret key and W is the public key
- * and G is fixed generator.
- * If RNG is NULL then the private key is provided externally in S
- * otherwise it is generated randomly internally */
-	public static int KEY_PAIR_GENERATE(RAND RNG, sbyte[] S, sbyte[] W)
-	{
-		BIG r, gx, gy, s;
-		ECP G, WP;
-		int res = 0;
-		sbyte[] T = new sbyte[EFS];
-
-		gx = new BIG(ROM.CURVE_Gx);
-		if (ROM.CURVETYPE != ROM.MONTGOMERY)
-		{
-			gy = new BIG(ROM.CURVE_Gy);
-			G = new ECP(gx,gy);
-		}
-		else
-		{
-			G = new ECP(gx);
-		}
-
-		r = new BIG(ROM.CURVE_Order);
-
-		if (RNG == null)
-		{
-			s = BIG.fromBytes(S);
-		}
-		else
-		{
-			s = BIG.randomnum(r,RNG);
-
-			s.toBytes(T);
-			for (int i = 0;i < EGS;i++)
-			{
-				S[i] = T[i];
-			}
-		}
-
-		WP = G.mul(s);
-		WP.toBytes(W);
-
-		return res;
-	}
-
-/* validate public key. Set full=true for fuller check */
-	public static int PUBLIC_KEY_VALIDATE(bool full, sbyte[] W)
-	{
-		BIG r;
-		ECP WP = ECP.fromBytes(W);
-		int res = 0;
-
-		r = new BIG(ROM.CURVE_Order);
-
-		if (WP.is_infinity())
-		{
-			res = INVALID_PUBLIC_KEY;
-		}
-		if (res == 0 && full)
-		{
-			WP = WP.mul(r);
-			if (!WP.is_infinity())
-			{
-				res = INVALID_PUBLIC_KEY;
-			}
-		}
-		return res;
-	}
-
-/* IEEE-1363 Diffie-Hellman online calculation Z=S.WD */
-	public static int ECPSVDP_DH(sbyte[] S, sbyte[] WD, sbyte[] Z)
-	{
-		BIG r, s;
-		ECP W;
-		int res = 0;
-		sbyte[] T = new sbyte[EFS];
-
-		s = BIG.fromBytes(S);
-
-		W = ECP.fromBytes(WD);
-		if (W.is_infinity())
-		{
-			res = ERROR;
-		}
-
-		if (res == 0)
-		{
-			r = new BIG(ROM.CURVE_Order);
-			s.mod(r);
-			W = W.mul(s);
-			if (W.is_infinity())
-			{
-				res = ERROR;
-			}
-			else
-			{
-				W.X.toBytes(T);
-				for (int i = 0;i < EFS;i++)
-				{
-					Z[i] = T[i];
-				}
-			}
-		}
-		return res;
-	}
-
-/* IEEE ECDSA Signature, C and D are signature on F using private key S */
-	public static int ECPSP_DSA(RAND RNG, sbyte[] S, sbyte[] F, sbyte[] C, sbyte[] D)
-	{
-		sbyte[] T = new sbyte[EFS];
-		BIG gx, gy, r, s, f, c, d, u, vx;
-		ECP G, V;
-
-		HASH H = new HASH();
-		H.process_array(F);
-		sbyte[] B = H.hash();
-
-		gx = new BIG(ROM.CURVE_Gx);
-		gy = new BIG(ROM.CURVE_Gy);
-
-		G = new ECP(gx,gy);
-		r = new BIG(ROM.CURVE_Order);
-
-		s = BIG.fromBytes(S);
-		f = BIG.fromBytes(B);
-
-		c = new BIG(0);
-		d = new BIG(0);
-		V = new ECP();
-
-		do
-		{
-			u = BIG.randomnum(r,RNG);
-
-			V.copy(G);
-			V = V.mul(u);
-			vx = V.X;
-			c.copy(vx);
-			c.mod(r);
-			if (c.iszilch())
-			{
-				continue;
-			}
-			u.invmodp(r);
-			d.copy(BIG.modmul(s,c,r));
-			d.add(f);
-			d.copy(BIG.modmul(u,d,r));
-		} while (d.iszilch());
-
-		c.toBytes(T);
-		for (int i = 0;i < EFS;i++)
-		{
-			C[i] = T[i];
-		}
-		d.toBytes(T);
-		for (int i = 0;i < EFS;i++)
-		{
-			D[i] = T[i];
-		}
-		return 0;
-	}
-
-/* IEEE1363 ECDSA Signature Verification. Signature C and D on F is verified using public key W */
-	public static int ECPVP_DSA(sbyte[] W, sbyte[] F, sbyte[] C, sbyte[] D)
-	{
-		BIG r, gx, gy, f, c, d, h2;
-		int res = 0;
-		ECP G, WP, P;
-
-		HASH H = new HASH();
-		H.process_array(F);
-		sbyte[] B = H.hash();
-
-		gx = new BIG(ROM.CURVE_Gx);
-		gy = new BIG(ROM.CURVE_Gy);
-
-		G = new ECP(gx,gy);
-		r = new BIG(ROM.CURVE_Order);
-
-		c = BIG.fromBytes(C);
-		d = BIG.fromBytes(D);
-		f = BIG.fromBytes(B);
-
-		if (c.iszilch() || BIG.comp(c,r) >= 0 || d.iszilch() || BIG.comp(d,r) >= 0)
-		{
-			res = INVALID;
-		}
-
-		if (res == 0)
-		{
-			d.invmodp(r);
-			f.copy(BIG.modmul(f,d,r));
-			h2 = BIG.modmul(c,d,r);
-
-			WP = ECP.fromBytes(W);
-			if (WP.is_infinity())
-			{
-				res = ERROR;
-			}
-			else
-			{
-				P = new ECP();
-				P.copy(WP);
-				P = P.mul2(h2,G,f);
-				if (P.is_infinity())
-				{
-					res = INVALID;
-				}
-				else
-				{
-					d = P.X;
-					d.mod(r);
-					if (BIG.comp(d,c) != 0)
-					{
-						res = INVALID;
-					}
-				}
-			}
-		}
-
-		return res;
-	}
-
-/* IEEE1363 ECIES encryption. Encryption of plaintext M uses public key W and produces ciphertext V,C,T */
-	public static sbyte[] ECIES_ENCRYPT(sbyte[] P1, sbyte[] P2, RAND RNG, sbyte[] W, sbyte[] M, sbyte[] V, sbyte[] T)
-	{
-		int i;
-
-		sbyte[] Z = new sbyte[EFS];
-		sbyte[] VZ = new sbyte[3 * EFS + 1];
-		sbyte[] K1 = new sbyte[EAS];
-		sbyte[] K2 = new sbyte[EAS];
-		sbyte[] U = new sbyte[EGS];
-
-		if (KEY_PAIR_GENERATE(RNG,U,V) != 0)
-		{
-			return new sbyte[0];
-		}
-		if (ECPSVDP_DH(U,W,Z) != 0)
-		{
-			return new sbyte[0];
-		}
-
-		for (i = 0;i < 2 * EFS + 1;i++)
-		{
-			VZ[i] = V[i];
-		}
-		for (i = 0;i < EFS;i++)
-		{
-			VZ[2 * EFS + 1 + i] = Z[i];
-		}
-
-
-		sbyte[] K = KDF2(VZ,P1,EFS);
-
-		for (i = 0;i < EAS;i++)
-		{
-			K1[i] = K[i];
-			K2[i] = K[EAS + i];
-		}
-
-		sbyte[] C = AES_CBC_IV0_ENCRYPT(K1,M);
-
-		sbyte[] L2 = inttoBytes(P2.Length,8);
-
-		sbyte[] AC = new sbyte[C.Length + P2.Length + 8];
-		for (i = 0;i < C.Length;i++)
-		{
-			AC[i] = C[i];
-		}
-		for (i = 0;i < P2.Length;i++)
-		{
-			AC[C.Length + i] = P2[i];
-		}
-		for (i = 0;i < 8;i++)
-		{
-			AC[C.Length + P2.Length + i] = L2[i];
-		}
-
-		HMAC(AC,K2,T);
-
-		return C;
-	}
-
-/* IEEE1363 ECIES decryption. Decryption of ciphertext V,C,T using private key U outputs plaintext M */
-	public static sbyte[] ECIES_DECRYPT(sbyte[] P1, sbyte[] P2, sbyte[] V, sbyte[] C, sbyte[] T, sbyte[] U)
-	{
-
-		int i;
-
-		sbyte[] Z = new sbyte[EFS];
-		sbyte[] VZ = new sbyte[3 * EFS + 1];
-		sbyte[] K1 = new sbyte[EAS];
-		sbyte[] K2 = new sbyte[EAS];
-		sbyte[] TAG = new sbyte[T.Length];
-
-		if (ECPSVDP_DH(U,V,Z) != 0)
-		{
-			return new sbyte[0];
-		}
-
-		for (i = 0;i < 2 * EFS + 1;i++)
-		{
-			VZ[i] = V[i];
-		}
-		for (i = 0;i < EFS;i++)
-		{
-			VZ[2 * EFS + 1 + i] = Z[i];
-		}
-
-		sbyte[] K = KDF2(VZ,P1,EFS);
-
-		for (i = 0;i < EAS;i++)
-		{
-			K1[i] = K[i];
-			K2[i] = K[EAS + i];
-		}
-
-		sbyte[] M = AES_CBC_IV0_DECRYPT(K1,C);
-
-		if (M.Length == 0)
-		{
-			return M;
-		}
-
-		sbyte[] L2 = inttoBytes(P2.Length,8);
-
-		sbyte[] AC = new sbyte[C.Length + P2.Length + 8];
-
-		for (i = 0;i < C.Length;i++)
-		{
-			AC[i] = C[i];
-		}
-		for (i = 0;i < P2.Length;i++)
-		{
-			AC[C.Length + i] = P2[i];
-		}
-		for (i = 0;i < 8;i++)
-		{
-			AC[C.Length + P2.Length + i] = L2[i];
-		}
-
-		HMAC(AC,K2,TAG);
-
-		bool same = true;
-		for (i = 0;i < T.Length;i++)
-		{
-			if (T[i] != TAG[i])
-			{
-				same = false;
-			}
-		}
-		if (!same)
-		{
-			return new sbyte[0];
-		}
-
-		return M;
-
-	}
-}
diff --git a/cs/ECP.cs b/cs/ECP.cs
deleted file mode 100644
index 4ad1a5c..0000000
--- a/cs/ECP.cs
+++ /dev/null
@@ -1,1216 +0,0 @@
-/*
-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.
-*/
-
-/* Elliptic Curve Point class */
-
-public sealed class ECP
-{
-	private FP x;
-	private FP y;
-	private FP z;
-	private bool INF;
-
-/* Constructor - set to O */
-	public ECP()
-	{
-		INF = true;
-		x = new FP(0);
-		y = new FP(1);
-		z = new FP(1);
-	}
-/* test for O point-at-infinity */
-	public bool is_infinity()
-	{
-		if (ROM.CURVETYPE == ROM.EDWARDS)
-		{
-			x.reduce();
-			y.reduce();
-			z.reduce();
-			return (x.iszilch() && y.Equals(z));
-		}
-		else
-		{
-			return INF;
-		}
-	}
-/* Conditional swap of P and Q dependant on d */
-	private void cswap(ECP Q, int d)
-	{
-		x.cswap(Q.x,d);
-		if (ROM.CURVETYPE != ROM.MONTGOMERY)
-		{
-			y.cswap(Q.y,d);
-		}
-		z.cswap(Q.z,d);
-		if (ROM.CURVETYPE != ROM.EDWARDS)
-		{
-			bool bd;
-			if (d == 0)
-			{
-				bd = false;
-			}
-			else
-			{
-				bd = true;
-			}
-			bd = bd & (INF ^ Q.INF);
-			INF ^= bd;
-			Q.INF ^= bd;
-		}
-	}
-
-/* Conditional move of Q to P dependant on d */
-	private void cmove(ECP Q, int d)
-	{
-		x.cmove(Q.x,d);
-		if (ROM.CURVETYPE != ROM.MONTGOMERY)
-		{
-			y.cmove(Q.y,d);
-		}
-		z.cmove(Q.z,d);
-		if (ROM.CURVETYPE != ROM.EDWARDS)
-		{
-			bool bd;
-			if (d == 0)
-			{
-				bd = false;
-			}
-			else
-			{
-				bd = true;
-			}
-			INF ^= (INF ^ Q.INF) & bd;
-		}
-	}
-
-/* return 1 if b==c, no branching */
-	private static int teq(int b, int c)
-	{
-		int x = b ^ c;
-		x -= 1; // if x=0, x now -1
-		return ((x >> 31) & 1);
-	}
-
-/* Constant time select from pre-computed table */
-	private void select(ECP[] W, int b)
-	{
-		ECP MP = new ECP();
-		int m = b >> 31;
-		int babs = (b ^ m) - m;
-
-		babs = (babs - 1) / 2;
-
-		cmove(W[0],teq(babs,0)); // conditional move
-		cmove(W[1],teq(babs,1));
-		cmove(W[2],teq(babs,2));
-		cmove(W[3],teq(babs,3));
-		cmove(W[4],teq(babs,4));
-		cmove(W[5],teq(babs,5));
-		cmove(W[6],teq(babs,6));
-		cmove(W[7],teq(babs,7));
-
-		MP.copy(this);
-		MP.neg();
-		cmove(MP,(int)(m & 1));
-	}
-
-
-/* Test P == Q */
-	public bool Equals(ECP Q)
-	{
-		if (is_infinity() && Q.is_infinity())
-		{
-			return true;
-		}
-		if (is_infinity() || Q.is_infinity())
-		{
-			return false;
-		}
-		if (ROM.CURVETYPE == ROM.WEIERSTRASS)
-		{
-			FP zs2 = new FP(z);
-			zs2.sqr();
-			FP zo2 = new FP(Q.z);
-			zo2.sqr();
-			FP zs3 = new FP(zs2);
-			zs3.mul(z);
-			FP zo3 = new FP(zo2);
-			zo3.mul(Q.z);
-			zs2.mul(Q.x);
-			zo2.mul(x);
-			if (!zs2.Equals(zo2))
-			{
-				return false;
-			}
-			zs3.mul(Q.y);
-			zo3.mul(y);
-			if (!zs3.Equals(zo3))
-			{
-				return false;
-			}
-		}
-		else
-		{
-			FP a = new FP(0);
-			FP b = new FP(0);
-			a.copy(x);
-			a.mul(Q.z);
-			a.reduce();
-			b.copy(Q.x);
-			b.mul(z);
-			b.reduce();
-			if (!a.Equals(b))
-			{
-				return false;
-			}
-			if (ROM.CURVETYPE == ROM.EDWARDS)
-			{
-				a.copy(y);
-				a.mul(Q.z);
-				a.reduce();
-				b.copy(Q.y);
-				b.mul(z);
-				b.reduce();
-				if (!a.Equals(b))
-				{
-					return false;
-				}
-			}
-		}
-		return true;
-	}
-
-/* this=P */
-	public void copy(ECP P)
-	{
-		x.copy(P.x);
-		if (ROM.CURVETYPE != ROM.MONTGOMERY)
-		{
-			y.copy(P.y);
-		}
-		z.copy(P.z);
-		INF = P.INF;
-	}
-/* this=-this */
-	public void neg()
-	{
-		if (is_infinity())
-		{
-			return;
-		}
-		if (ROM.CURVETYPE == ROM.WEIERSTRASS)
-		{
-			y.neg();
-			y.reduce();
-		}
-		if (ROM.CURVETYPE == ROM.EDWARDS)
-		{
-			x.neg();
-			x.reduce();
-		}
-		return;
-	}
-/* set this=O */
-	public void inf()
-	{
-		INF = true;
-		x.zero();
-		y.one();
-		z.one();
-	//	y=new FP(1);
-	//	z=new FP(1);
-	}
-
-/* Calculate RHS of curve equation */
-	public static FP RHS(FP x)
-	{
-		x.norm();
-		FP r = new FP(x);
-		r.sqr();
-
-		if (ROM.CURVETYPE == ROM.WEIERSTRASS)
-		{ // x^3+Ax+B
-			FP b = new FP(new BIG(ROM.CURVE_B));
-			r.mul(x);
-			if (ROM.CURVE_A == -3)
-			{
-				FP cx = new FP(x);
-				cx.imul(3);
-				cx.neg();
-				cx.norm();
-				r.add(cx);
-			}
-			r.add(b);
-		}
-		if (ROM.CURVETYPE == ROM.EDWARDS)
-		{ // (Ax^2-1)/(Bx^2-1)
-			FP b = new FP(new BIG(ROM.CURVE_B));
-
-			FP one = new FP(1);
-			b.mul(r);
-			b.sub(one);
-			if (ROM.CURVE_A == -1)
-			{
-				r.neg();
-			}
-			r.sub(one);
-
-			b.inverse();
-
-			r.mul(b);
-		}
-		if (ROM.CURVETYPE == ROM.MONTGOMERY)
-		{ // x^3+Ax^2+x
-			FP x3 = new FP(0);
-			x3.copy(r);
-			x3.mul(x);
-			r.imul(ROM.CURVE_A);
-			r.add(x3);
-			r.add(x);
-		}
-		r.reduce();
-		return r;
-	}
-
-/* set (x,y) from two BIGs */
-	public ECP(BIG ix, BIG iy)
-	{
-		x = new FP(ix);
-		y = new FP(iy);
-		z = new FP(1);
-		FP rhs = RHS(x);
-
-		if (ROM.CURVETYPE == ROM.MONTGOMERY)
-		{
-			if (rhs.jacobi() == 1)
-			{
-				INF = false;
-			}
-			else
-			{
-				inf();
-			}
-		}
-		else
-		{
-			FP y2 = new FP(y);
-			y2.sqr();
-			if (y2.Equals(rhs))
-			{
-				INF = false;
-			}
-			else
-			{
-				inf();
-			}
-		}
-	}
-/* set (x,y) from BIG and a bit */
-	public ECP(BIG ix, int s)
-	{
-		x = new FP(ix);
-		FP rhs = RHS(x);
-		y = new FP(0);
-		z = new FP(1);
-		if (rhs.jacobi() == 1)
-		{
-			FP ny = rhs.sqrt();
-			if (ny.redc().parity() != s)
-			{
-				ny.neg();
-			}
-			y.copy(ny);
-			INF = false;
-		}
-		else
-		{
-			inf();
-		}
-	}
-
-/* set from x - calculate y from curve equation */
-	public ECP(BIG ix)
-	{
-		x = new FP(ix);
-		FP rhs = RHS(x);
-		y = new FP(0);
-		z = new FP(1);
-		if (rhs.jacobi() == 1)
-		{
-			if (ROM.CURVETYPE != ROM.MONTGOMERY)
-			{
-				y.copy(rhs.sqrt());
-			}
-			INF = false;
-		}
-		else
-		{
-			INF = true;
-		}
-	}
-
-/* set to affine - from (x,y,z) to (x,y) */
-	public void affine()
-	{
-		if (is_infinity())
-		{
-			return;
-		}
-		FP one = new FP(1);
-		if (z.Equals(one))
-		{
-			return;
-		}
-		z.inverse();
-		if (ROM.CURVETYPE == ROM.WEIERSTRASS)
-		{
-			FP z2 = new FP(z);
-			z2.sqr();
-			x.mul(z2);
-			x.reduce();
-			y.mul(z2);
-			y.mul(z);
-			y.reduce();
-		}
-		if (ROM.CURVETYPE == ROM.EDWARDS)
-		{
-			x.mul(z);
-			x.reduce();
-			y.mul(z);
-			y.reduce();
-		}
-		if (ROM.CURVETYPE == ROM.MONTGOMERY)
-		{
-			x.mul(z);
-			x.reduce();
-		}
-		z.copy(one);
-	}
-/* extract x as a BIG */
-	public BIG X
-	{
-		get
-		{
-			affine();
-			return x.redc();
-		}
-	}
-/* extract y as a BIG */
-	public BIG Y
-	{
-		get
-		{
-			affine();
-			return y.redc();
-		}
-	}
-
-/* get sign of Y */
-	public int S
-	{
-		get
-		{
-			affine();
-			BIG y = Y;
-			return y.parity();
-		}
-	}
-/* extract x as an FP */
-	public FP getx()
-	{
-		return x;
-	}
-/* extract y as an FP */
-	public FP gety()
-	{
-		return y;
-	}
-/* extract z as an FP */
-	public FP getz()
-	{
-		return z;
-	}
-/* convert to byte array */
-	public void toBytes(sbyte[] b)
-	{
-		sbyte[] t = new sbyte[ROM.MODBYTES];
-		if (ROM.CURVETYPE != ROM.MONTGOMERY)
-		{
-			b[0] = 0x04;
-		}
-		else
-		{
-			b[0] = 0x02;
-		}
-
-		affine();
-		x.redc().toBytes(t);
-		for (int i = 0;i < ROM.MODBYTES;i++)
-		{
-			b[i + 1] = t[i];
-		}
-		if (ROM.CURVETYPE != ROM.MONTGOMERY)
-		{
-			y.redc().toBytes(t);
-			for (int i = 0;i < ROM.MODBYTES;i++)
-			{
-				b[i + ROM.MODBYTES + 1] = t[i];
-			}
-		}
-	}
-/* convert from byte array to point */
-	public static ECP fromBytes(sbyte[] b)
-	{
-		sbyte[] t = new sbyte[ROM.MODBYTES];
-		BIG p = new BIG(ROM.Modulus);
-
-		for (int i = 0;i < ROM.MODBYTES;i++)
-		{
-			t[i] = b[i + 1];
-		}
-		BIG px = BIG.fromBytes(t);
-		if (BIG.comp(px,p) >= 0)
-		{
-			return new ECP();
-		}
-
-		if (b[0] == 0x04)
-		{
-			for (int i = 0;i < ROM.MODBYTES;i++)
-			{
-				t[i] = b[i + ROM.MODBYTES + 1];
-			}
-			BIG py = BIG.fromBytes(t);
-			if (BIG.comp(py,p) >= 0)
-			{
-				return new ECP();
-			}
-			return new ECP(px,py);
-		}
-		else
-		{
-			return new ECP(px);
-		}
-	}
-/* convert to hex string */
-	public override string ToString()
-	{
-		if (is_infinity())
-		{
-			return "infinity";
-		}
-		affine();
-		if (ROM.CURVETYPE == ROM.MONTGOMERY)
-		{
-			return "(" + x.redc().ToString() + ")";
-		}
-		else
-		{
-			return "(" + x.redc().ToString() + "," + y.redc().ToString() + ")";
-		}
-	}
-/* this*=2 */
-	public void dbl()
-	{
-		if (ROM.CURVETYPE == ROM.WEIERSTRASS)
-		{
-			if (INF)
-			{
-				return;
-			}
-			if (y.iszilch())
-			{
-				inf();
-				return;
-			}
-
-			FP w1 = new FP(x);
-			FP w6 = new FP(z);
-			FP w2 = new FP(0);
-			FP w3 = new FP(x);
-			FP w8 = new FP(x);
-
-			if (ROM.CURVE_A == -3)
-			{
-				w6.sqr();
-				w1.copy(w6);
-				w1.neg();
-				w3.add(w1);
-				w8.add(w6);
-				w3.mul(w8);
-				w8.copy(w3);
-				w8.imul(3);
-			}
-			else
-			{
-				w1.sqr();
-				w8.copy(w1);
-				w8.imul(3);
-			}
-
-			w2.copy(y);
-			w2.sqr();
-			w3.copy(x);
-			w3.mul(w2);
-			w3.imul(4);
-			w1.copy(w3);
-			w1.neg();
-	//		w1.norm();
-
-			x.copy(w8);
-			x.sqr();
-			x.add(w1);
-			x.add(w1);
-	//		x.reduce();
-			x.norm();
-
-			z.mul(y);
-			z.add(z);
-
-			w2.add(w2);
-			w2.sqr();
-			w2.add(w2);
-			w3.sub(x);
-			y.copy(w8);
-			y.mul(w3);
-	//		w2.norm();
-			y.sub(w2);
-	//		y.reduce();
-	//		z.reduce();
-			y.norm();
-			z.norm();
-		}
-		if (ROM.CURVETYPE == ROM.EDWARDS)
-		{
-			FP C = new FP(x);
-			FP D = new FP(y);
-			FP H = new FP(z);
-			FP J = new FP(0);
-
-			x.mul(y);
-			x.add(x);
-			C.sqr();
-			D.sqr();
-			if (ROM.CURVE_A == -1)
-			{
-				C.neg();
-			}
-			y.copy(C);
-			y.add(D);
-	//		y.norm();
-			H.sqr();
-			H.add(H);
-			z.copy(y);
-			J.copy(y);
-			J.sub(H);
-			x.mul(J);
-			C.sub(D);
-			y.mul(C);
-			z.mul(J);
-
-			x.norm();
-			y.norm();
-			z.norm();
-		}
-		if (ROM.CURVETYPE == ROM.MONTGOMERY)
-		{
-			FP A = new FP(x);
-			FP B = new FP(x);
-			FP AA = new FP(0);
-			FP BB = new FP(0);
-			FP C = new FP(0);
-
-			if (INF)
-			{
-				return;
-			}
-
-			A.add(z);
-			AA.copy(A);
-			AA.sqr();
-			B.sub(z);
-			BB.copy(B);
-			BB.sqr();
-			C.copy(AA);
-			C.sub(BB);
-	//		C.norm();
-
-			x.copy(AA);
-			x.mul(BB);
-
-			A.copy(C);
-			A.imul((ROM.CURVE_A + 2) / 4);
-
-			BB.add(A);
-			z.copy(BB);
-			z.mul(C);
-	//		x.reduce();
-	//		z.reduce();
-			x.norm();
-			z.norm();
-		}
-		return;
-	}
-
-/* this+=Q */
-	public void add(ECP Q)
-	{
-		if (ROM.CURVETYPE == ROM.WEIERSTRASS)
-		{
-			if (INF)
-			{
-				copy(Q);
-				return;
-			}
-			if (Q.INF)
-			{
-				return;
-			}
-
-			bool aff = false;
-
-			FP one = new FP(1);
-			if (Q.z.Equals(one))
-			{
-				aff = true;
-			}
-
-			FP A, C;
-			FP B = new FP(z);
-			FP D = new FP(z);
-			if (!aff)
-			{
-				A = new FP(Q.z);
-				C = new FP(Q.z);
-
-				A.sqr();
-				B.sqr();
-				C.mul(A);
-				D.mul(B);
-
-				A.mul(x);
-				C.mul(y);
-			}
-			else
-			{
-				A = new FP(x);
-				C = new FP(y);
-
-				B.sqr();
-				D.mul(B);
-			}
-
-			B.mul(Q.x);
-			B.sub(A);
-			D.mul(Q.y);
-			D.sub(C);
-
-			if (B.iszilch())
-			{
-				if (D.iszilch())
-				{
-					dbl();
-					return;
-				}
-				else
-				{
-					INF = true;
-					return;
-				}
-			}
-
-			if (!aff)
-			{
-				z.mul(Q.z);
-			}
-			z.mul(B);
-
-			FP e = new FP(B);
-			e.sqr();
-			B.mul(e);
-			A.mul(e);
-
-			e.copy(A);
-			e.add(A);
-			e.add(B);
-			x.copy(D);
-			x.sqr();
-			x.sub(e);
-
-			A.sub(x);
-			y.copy(A);
-			y.mul(D);
-			C.mul(B);
-			y.sub(C);
-
-		//	x.reduce();
-		//	y.reduce();
-		//	z.reduce();
-			x.norm();
-			y.norm();
-			z.norm();
-		}
-		if (ROM.CURVETYPE == ROM.EDWARDS)
-		{
-			FP b = new FP(new BIG(ROM.CURVE_B));
-			FP A = new FP(z);
-			FP B = new FP(0);
-			FP C = new FP(x);
-			FP D = new FP(y);
-			FP E = new FP(0);
-			FP F = new FP(0);
-			FP G = new FP(0);
-		//	FP H=new FP(0);
-		//	FP I=new FP(0);
-
-			A.mul(Q.z);
-			B.copy(A);
-			B.sqr();
-			C.mul(Q.x);
-			D.mul(Q.y);
-
-			E.copy(C);
-			E.mul(D);
-			E.mul(b);
-			F.copy(B);
-			F.sub(E);
-			G.copy(B);
-			G.add(E);
-			C.add(D);
-
-			if (ROM.CURVE_A == 1)
-			{
-				E.copy(D);
-				D.sub(C);
-			}
-
-			B.copy(x);
-			B.add(y);
-			D.copy(Q.x);
-			D.add(Q.y);
-			B.mul(D);
-			B.sub(C);
-			B.mul(F);
-			x.copy(A);
-			x.mul(B);
-
-			if (ROM.CURVE_A == 1)
-			{
-				C.copy(E);
-				C.mul(G);
-			}
-			if (ROM.CURVE_A == -1)
-			{
-				C.mul(G);
-			}
-			y.copy(A);
-			y.mul(C);
-			z.copy(F);
-			z.mul(G);
-		//	x.reduce(); y.reduce(); z.reduce();
-			x.norm();
-			y.norm();
-			z.norm();
-		}
-		return;
-	}
-
-/* Differential Add for Montgomery curves. this+=Q where W is this-Q and is affine. */
-	public void dadd(ECP Q, ECP W)
-	{
-			FP A = new FP(x);
-			FP B = new FP(x);
-			FP C = new FP(Q.x);
-			FP D = new FP(Q.x);
-			FP DA = new FP(0);
-			FP CB = new FP(0);
-
-			A.add(z);
-			B.sub(z);
-
-			C.add(Q.z);
-			D.sub(Q.z);
-
-			DA.copy(D);
-			DA.mul(A);
-			CB.copy(C);
-			CB.mul(B);
-
-			A.copy(DA);
-			A.add(CB);
-			A.sqr();
-			B.copy(DA);
-			B.sub(CB);
-			B.sqr();
-
-			x.copy(A);
-			z.copy(W.x);
-			z.mul(B);
-
-			if (z.iszilch())
-			{
-				inf();
-			}
-			else
-			{
-				INF = false;
-			}
-
-	//		x.reduce();
-			x.norm();
-	}
-/* this-=Q */
-	public void sub(ECP Q)
-	{
-		Q.neg();
-		add(Q);
-		Q.neg();
-	}
-
-	public static void multiaffine(int m, ECP[] P)
-	{
-		int i;
-		FP t1 = new FP(0);
-		FP t2 = new FP(0);
-
-		FP[] work = new FP[m];
-
-		for (i = 0;i < m;i++)
-		{
-			work[i] = new FP(0);
-		}
-
-		work[0].one();
-		work[1].copy(P[0].z);
-
-		for (i = 2;i < m;i++)
-		{
-			work[i].copy(work[i - 1]);
-			work[i].mul(P[i - 1].z);
-		}
-
-		t1.copy(work[m - 1]);
-		t1.mul(P[m - 1].z);
-		t1.inverse();
-		t2.copy(P[m - 1].z);
-		work[m - 1].mul(t1);
-
-		for (i = m - 2;;i--)
-		{
-			if (i == 0)
-			{
-				work[0].copy(t1);
-				work[0].mul(t2);
-				break;
-			}
-			work[i].mul(t2);
-			work[i].mul(t1);
-			t2.mul(P[i].z);
-		}
-/* now work[] contains inverses of all Z coordinates */
-
-		for (i = 0;i < m;i++)
-		{
-			P[i].z.one();
-			t1.copy(work[i]);
-			t1.sqr();
-			P[i].x.mul(t1);
-			t1.mul(work[i]);
-			P[i].y.mul(t1);
-		}
-	}
-
-/* constant time multiply by small integer of length bts - use ladder */
-	public ECP pinmul(int e, int bts)
-	{
-		if (ROM.CURVETYPE == ROM.MONTGOMERY)
-		{
-			return this.mul(new BIG(e));
-		}
-		else
-		{
-			int nb, i, b;
-			ECP P = new ECP();
-			ECP R0 = new ECP();
-			ECP R1 = new ECP();
-			R1.copy(this);
-
-			for (i = bts - 1;i >= 0;i--)
-			{
-				b = (e >> i) & 1;
-				P.copy(R1);
-				P.add(R0);
-				R0.cswap(R1,b);
-				R1.copy(P);
-				R0.dbl();
-				R0.cswap(R1,b);
-			}
-			P.copy(R0);
-			P.affine();
-			return P;
-		}
-	}
-
-/* return e.this */
-
-	public ECP mul(BIG e)
-	{
-		if (e.iszilch() || is_infinity())
-		{
-			return new ECP();
-		}
-		ECP P = new ECP();
-		if (ROM.CURVETYPE == ROM.MONTGOMERY)
-		{
-/* use Ladder */
-			int nb, i, b;
-			ECP D = new ECP();
-			ECP R0 = new ECP();
-			R0.copy(this);
-			ECP R1 = new ECP();
-			R1.copy(this);
-			R1.dbl();
-			D.copy(this);
-			D.affine();
-			nb = e.nbits();
-			for (i = nb - 2;i >= 0;i--)
-			{
-				b = e.bit(i);
-				P.copy(R1);
-				P.dadd(R0,D);
-				R0.cswap(R1,b);
-				R1.copy(P);
-				R0.dbl();
-				R0.cswap(R1,b);
-			}
-			P.copy(R0);
-		}
-		else
-		{
-// fixed size windows
-			int i, b, nb, m, s, ns;
-			BIG mt = new BIG();
-			BIG t = new BIG();
-			ECP Q = new ECP();
-			ECP C = new ECP();
-			ECP[] W = new ECP[8];
-			sbyte[] w = new sbyte[1 + (ROM.NLEN * ROM.BASEBITS + 3) / 4];
-
-			affine();
-
-// precompute table
-			Q.copy(this);
-			Q.dbl();
-			W[0] = new ECP();
-			W[0].copy(this);
-
-			for (i = 1;i < 8;i++)
-			{
-				W[i] = new ECP();
-				W[i].copy(W[i - 1]);
-				W[i].add(Q);
-			}
-
-// convert the table to affine
-			if (ROM.CURVETYPE == ROM.WEIERSTRASS)
-			{
-				multiaffine(8,W);
-			}
-
-// make exponent odd - add 2P if even, P if odd
-			t.copy(e);
-			s = t.parity();
-			t.inc(1);
-			t.norm();
-			ns = t.parity();
-			mt.copy(t);
-			mt.inc(1);
-			mt.norm();
-			t.cmove(mt,s);
-			Q.cmove(this,ns);
-			C.copy(Q);
-
-			nb = 1 + (t.nbits() + 3) / 4;
-
-// convert exponent to signed 4-bit window
-			for (i = 0;i < nb;i++)
-			{
-				w[i] = (sbyte)(t.lastbits(5) - 16);
-				t.dec(w[i]);
-				t.norm();
-				t.fshr(4);
-			}
-			w[nb] = (sbyte)t.lastbits(5);
-
-			P.copy(W[(w[nb] - 1) / 2]);
-			for (i = nb - 1;i >= 0;i--)
-			{
-				Q.select(W,w[i]);
-				P.dbl();
-				P.dbl();
-				P.dbl();
-				P.dbl();
-				P.add(Q);
-			}
-			P.sub(C); // apply correction
-		}
-		P.affine();
-		return P;
-	}
-/* Return e.this+f.Q */
-
-	public ECP mul2(BIG e, ECP Q, BIG f)
-	{
-		BIG te = new BIG();
-		BIG tf = new BIG();
-		BIG mt = new BIG();
-		ECP S = new ECP();
-		ECP T = new ECP();
-		ECP C = new ECP();
-		ECP[] W = new ECP[8];
-		sbyte[] w = new sbyte[1 + (ROM.NLEN * ROM.BASEBITS + 1) / 2];
-		int i, s, ns, nb;
-		sbyte a, b;
-
-		affine();
-		Q.affine();
-
-		te.copy(e);
-		tf.copy(f);
-
-// precompute table
-		W[1] = new ECP();
-		W[1].copy(this);
-		W[1].sub(Q);
-		W[2] = new ECP();
-		W[2].copy(this);
-		W[2].add(Q);
-		S.copy(Q);
-		S.dbl();
-		W[0] = new ECP();
-		W[0].copy(W[1]);
-		W[0].sub(S);
-		W[3] = new ECP();
-		W[3].copy(W[2]);
-		W[3].add(S);
-		T.copy(this);
-		T.dbl();
-		W[5] = new ECP();
-		W[5].copy(W[1]);
-		W[5].add(T);
-		W[6] = new ECP();
-		W[6].copy(W[2]);
-		W[6].add(T);
-		W[4] = new ECP();
-		W[4].copy(W[5]);
-		W[4].sub(S);
-		W[7] = new ECP();
-		W[7].copy(W[6]);
-		W[7].add(S);
-
-// convert the table to affine
-		if (ROM.CURVETYPE == ROM.WEIERSTRASS)
-		{
-			multiaffine(8,W);
-		}
-
-// if multiplier is odd, add 2, else add 1 to multiplier, and add 2P or P to correction
-
-		s = te.parity();
-		te.inc(1);
-		te.norm();
-		ns = te.parity();
-		mt.copy(te);
-		mt.inc(1);
-		mt.norm();
-		te.cmove(mt,s);
-		T.cmove(this,ns);
-		C.copy(T);
-
-		s = tf.parity();
-		tf.inc(1);
-		tf.norm();
-		ns = tf.parity();
-		mt.copy(tf);
-		mt.inc(1);
-		mt.norm();
-		tf.cmove(mt,s);
-		S.cmove(Q,ns);
-		C.add(S);
-
-		mt.copy(te);
-		mt.add(tf);
-		mt.norm();
-		nb = 1 + (mt.nbits() + 1) / 2;
-
-// convert exponent to signed 2-bit window
-		for (i = 0;i < nb;i++)
-		{
-			a = (sbyte)(te.lastbits(3) - 4);
-			te.dec(a);
-			te.norm();
-			te.fshr(2);
-			b = (sbyte)(tf.lastbits(3) - 4);
-			tf.dec(b);
-			tf.norm();
-			tf.fshr(2);
-			w[i] = (sbyte)(4 * a + b);
-		}
-		w[nb] = (sbyte)(4 * te.lastbits(3) + tf.lastbits(3));
-		S.copy(W[(w[nb] - 1) / 2]);
-
-		for (i = nb - 1;i >= 0;i--)
-		{
-			T.select(W,w[i]);
-			S.dbl();
-			S.dbl();
-			S.add(T);
-		}
-		S.sub(C); // apply correction
-		S.affine();
-		return S;
-	}
-
-/*
-	public static void main(String[] args) {
-
-		BIG Gx=new BIG(ROM.CURVE_Gx);
-		BIG Gy;
-		ECP P;
-		if (ROM.CURVETYPE!=ROM.MONTGOMERY) Gy=new BIG(ROM.CURVE_Gy);
-		BIG r=new BIG(ROM.CURVE_Order);
-
-		//r.dec(7);
-
-		System.out.println("Gx= "+Gx.toString());
-		if (ROM.CURVETYPE!=ROM.MONTGOMERY) System.out.println("Gy= "+Gy.toString());
-
-		if (ROM.CURVETYPE!=ROM.MONTGOMERY) P=new ECP(Gx,Gy);
-		else  P=new ECP(Gx);
-
-		System.out.println("P= "+P.toString());
-
-		ECP R=P.mul(r);
-		//for (int i=0;i<10000;i++)
-		//	R=P.mul(r);
-
-		System.out.println("R= "+R.toString());
-    } */
-}
-
diff --git a/cs/ECP2.cs b/cs/ECP2.cs
deleted file mode 100644
index 28f9295..0000000
--- a/cs/ECP2.cs
+++ /dev/null
@@ -1,771 +0,0 @@
-/*
-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.
-*/
-
-/* AMCL Weierstrass elliptic curve functions over FP2 */
-
-public sealed class ECP2
-{
-	private FP2 x;
-	private FP2 y;
-	private FP2 z;
-	private bool INF;
-
-/* Constructor - set this=O */
-	public ECP2()
-	{
-		INF = true;
-		x = new FP2(0);
-		y = new FP2(1);
-		z = new FP2(1);
-	}
-
-/* Test this=O? */
-	public bool is_infinity()
-	{
-		return INF;
-	}
-/* copy this=P */
-	public void copy(ECP2 P)
-	{
-		x.copy(P.x);
-		y.copy(P.y);
-		z.copy(P.z);
-		INF = P.INF;
-	}
-/* set this=O */
-	public void inf()
-	{
-		INF = true;
-		x.zero();
-		y.zero();
-		z.zero();
-	}
-
-/* Conditional move of Q to P dependant on d */
-	public void cmove(ECP2 Q, int d)
-	{
-		x.cmove(Q.x,d);
-		y.cmove(Q.y,d);
-		z.cmove(Q.z,d);
-
-		bool bd;
-		if (d == 0)
-		{
-			bd = false;
-		}
-		else
-		{
-			bd = true;
-		}
-		INF ^= (INF ^ Q.INF) & bd;
-	}
-
-/* return 1 if b==c, no branching */
-	public static int teq(int b, int c)
-	{
-		int x = b ^ c;
-		x -= 1; // if x=0, x now -1
-		return ((x >> 31) & 1);
-	}
-
-/* Constant time select from pre-computed table */
-	public void select(ECP2[] W, int b)
-	{
-		ECP2 MP = new ECP2();
-		int m = b >> 31;
-		int babs = (b ^ m) - m;
-
-		babs = (babs - 1) / 2;
-
-		cmove(W[0],teq(babs,0)); // conditional move
-		cmove(W[1],teq(babs,1));
-		cmove(W[2],teq(babs,2));
-		cmove(W[3],teq(babs,3));
-		cmove(W[4],teq(babs,4));
-		cmove(W[5],teq(babs,5));
-		cmove(W[6],teq(babs,6));
-		cmove(W[7],teq(babs,7));
-
-		MP.copy(this);
-		MP.neg();
-		cmove(MP,(int)(m & 1));
-	}
-
-
-/* Test if P == Q */
-	public bool Equals(ECP2 Q)
-	{
-		if (is_infinity() && Q.is_infinity())
-		{
-			return true;
-		}
-		if (is_infinity() || Q.is_infinity())
-		{
-			return false;
-		}
-
-		FP2 zs2 = new FP2(z);
-		zs2.sqr();
-		FP2 zo2 = new FP2(Q.z);
-		zo2.sqr();
-		FP2 zs3 = new FP2(zs2);
-		zs3.mul(z);
-		FP2 zo3 = new FP2(zo2);
-		zo3.mul(Q.z);
-		zs2.mul(Q.x);
-		zo2.mul(x);
-		if (!zs2.Equals(zo2))
-		{
-			return false;
-		}
-		zs3.mul(Q.y);
-		zo3.mul(y);
-		if (!zs3.Equals(zo3))
-		{
-			return false;
-		}
-
-		return true;
-	}
-/* set this=-this */
-	public void neg()
-	{
-		if (is_infinity())
-		{
-			return;
-		}
-		y.neg();
-		y.reduce();
-		return;
-	}
-/* set to Affine - (x,y,z) to (x,y) */
-	public void affine()
-	{
-		if (is_infinity())
-		{
-			return;
-		}
-		FP2 one = new FP2(1);
-		if (z.Equals(one))
-		{
-			return;
-		}
-		z.inverse();
-
-		FP2 z2 = new FP2(z);
-		z2.sqr();
-		x.mul(z2);
-		x.reduce();
-		y.mul(z2);
-		y.mul(z);
-		y.reduce();
-		z.copy(one);
-	}
-/* extract affine x as FP2 */
-	public FP2 X
-	{
-		get
-		{
-			affine();
-			return x;
-		}
-	}
-/* extract affine y as FP2 */
-	public FP2 Y
-	{
-		get
-		{
-			affine();
-			return y;
-		}
-	}
-/* extract projective x */
-	public FP2 getx()
-	{
-		return x;
-	}
-/* extract projective y */
-	public FP2 gety()
-	{
-		return y;
-	}
-/* extract projective z */
-	public FP2 getz()
-	{
-		return z;
-	}
-/* convert to byte array */
-	public void toBytes(sbyte[] b)
-	{
-		sbyte[] t = new sbyte[ROM.MODBYTES];
-		affine();
-		x.A.toBytes(t);
-		for (int i = 0;i < ROM.MODBYTES;i++)
-		{
-			b[i] = t[i];
-		}
-		x.B.toBytes(t);
-		for (int i = 0;i < ROM.MODBYTES;i++)
-		{
-			b[i + ROM.MODBYTES] = t[i];
-		}
-
-		y.A.toBytes(t);
-		for (int i = 0;i < ROM.MODBYTES;i++)
-		{
-			b[i + 2 * ROM.MODBYTES] = t[i];
-		}
-		y.B.toBytes(t);
-		for (int i = 0;i < ROM.MODBYTES;i++)
-		{
-			b[i + 3 * ROM.MODBYTES] = t[i];
-		}
-	}
-/* convert from byte array to point */
-	public static ECP2 fromBytes(sbyte[] b)
-	{
-		sbyte[] t = new sbyte[ROM.MODBYTES];
-		BIG ra;
-		BIG rb;
-
-		for (int i = 0;i < ROM.MODBYTES;i++)
-		{
-			t[i] = b[i];
-		}
-		ra = BIG.fromBytes(t);
-		for (int i = 0;i < ROM.MODBYTES;i++)
-		{
-			t[i] = b[i + ROM.MODBYTES];
-		}
-		rb = BIG.fromBytes(t);
-		FP2 rx = new FP2(ra,rb);
-
-		for (int i = 0;i < ROM.MODBYTES;i++)
-		{
-			t[i] = b[i + 2 * ROM.MODBYTES];
-		}
-		ra = BIG.fromBytes(t);
-		for (int i = 0;i < ROM.MODBYTES;i++)
-		{
-			t[i] = b[i + 3 * ROM.MODBYTES];
-		}
-		rb = BIG.fromBytes(t);
-		FP2 ry = new FP2(ra,rb);
-
-		return new ECP2(rx,ry);
-	}
-/* convert this to hex string */
-	public override string ToString()
-	{
-		if (is_infinity())
-		{
-			return "infinity";
-		}
-		affine();
-		return "(" + x.ToString() + "," + y.ToString() + ")";
-	}
-
-/* Calculate RHS of twisted curve equation x^3+B/i */
-	public static FP2 RHS(FP2 x)
-	{
-		x.norm();
-		FP2 r = new FP2(x);
-		r.sqr();
-		FP2 b = new FP2(new BIG(ROM.CURVE_B));
-		b.div_ip();
-		r.mul(x);
-		r.add(b);
-
-		r.reduce();
-		return r;
-	}
-/* construct this from (x,y) - but set to O if not on curve */
-	public ECP2(FP2 ix, FP2 iy)
-	{
-		x = new FP2(ix);
-		y = new FP2(iy);
-		z = new FP2(1);
-		FP2 rhs = RHS(x);
-		FP2 y2 = new FP2(y);
-		y2.sqr();
-		if (y2.Equals(rhs))
-		{
-			INF = false;
-		}
-		else
-		{
-			x.zero();
-			INF = true;
-		}
-	}
-
-/* construct this from x - but set to O if not on curve */
-	public ECP2(FP2 ix)
-	{
-		x = new FP2(ix);
-		y = new FP2(1);
-		z = new FP2(1);
-		FP2 rhs = RHS(x);
-		if (rhs.sqrt())
-		{
-			y.copy(rhs);
-			INF = false;
-		}
-		else
-		{
-			x.zero();
-			INF = true;
-		}
-	}
-
-/* this+=this */
-	public int dbl()
-	{
-		if (INF)
-		{
-			return -1;
-		}
-		if (y.iszilch())
-		{
-			inf();
-			return -1;
-		}
-
-		FP2 w1 = new FP2(x);
-		FP2 w2 = new FP2(0);
-		FP2 w3 = new FP2(x);
-		FP2 w8 = new FP2(x);
-
-		w1.sqr();
-		w8.copy(w1);
-		w8.imul(3);
-
-		w2.copy(y);
-		w2.sqr();
-		w3.copy(x);
-		w3.mul(w2);
-		w3.imul(4);
-		w1.copy(w3);
-		w1.neg();
-	//	w1.norm();
-
-		x.copy(w8);
-		x.sqr();
-		x.add(w1);
-		x.add(w1);
-		x.norm();
-
-		z.mul(y);
-		z.add(z);
-
-		w2.add(w2);
-		w2.sqr();
-		w2.add(w2);
-		w3.sub(x);
-		y.copy(w8);
-		y.mul(w3);
-	//	w2.norm();
-		y.sub(w2);
-
-		y.norm();
-		z.norm();
-
-		return 1;
-	}
-/* this+=Q - return 0 for add, 1 for double, -1 for O */
-	public int add(ECP2 Q)
-	{
-		if (INF)
-		{
-			copy(Q);
-			return -1;
-		}
-		if (Q.INF)
-		{
-			return -1;
-		}
-
-		bool aff = false;
-
-		if (Q.z.isunity())
-		{
-			aff = true;
-		}
-
-		FP2 A, C;
-		FP2 B = new FP2(z);
-		FP2 D = new FP2(z);
-		if (!aff)
-		{
-			A = new FP2(Q.z);
-			C = new FP2(Q.z);
-
-			A.sqr();
-			B.sqr();
-			C.mul(A);
-			D.mul(B);
-
-			A.mul(x);
-			C.mul(y);
-		}
-		else
-		{
-			A = new FP2(x);
-			C = new FP2(y);
-
-			B.sqr();
-			D.mul(B);
-		}
-
-		B.mul(Q.x);
-		B.sub(A);
-		D.mul(Q.y);
-		D.sub(C);
-
-		if (B.iszilch())
-		{
-			if (D.iszilch())
-			{
-				dbl();
-				return 1;
-			}
-			else
-			{
-				INF = true;
-				return -1;
-			}
-		}
-
-		if (!aff)
-		{
-			z.mul(Q.z);
-		}
-		z.mul(B);
-
-		FP2 e = new FP2(B);
-		e.sqr();
-		B.mul(e);
-		A.mul(e);
-
-		e.copy(A);
-		e.add(A);
-		e.add(B);
-		x.copy(D);
-		x.sqr();
-		x.sub(e);
-
-		A.sub(x);
-		y.copy(A);
-		y.mul(D);
-		C.mul(B);
-		y.sub(C);
-
-		x.norm();
-		y.norm();
-		z.norm();
-
-		return 0;
-	}
-
-/* set this-=Q */
-	public int sub(ECP2 Q)
-	{
-		Q.neg();
-		int D = add(Q);
-		Q.neg();
-		return D;
-	}
-/* set this*=q, where q is Modulus, using Frobenius */
-	public void frob(FP2 X)
-	{
-		if (INF)
-		{
-			return;
-		}
-		FP2 X2 = new FP2(X);
-		X2.sqr();
-		x.conj();
-		y.conj();
-		z.conj();
-		z.reduce();
-		x.mul(X2);
-		y.mul(X2);
-		y.mul(X);
-	}
-
-/* normalises m-array of ECP2 points. Requires work vector of m FP2s */
-
-	public static void multiaffine(int m, ECP2[] P)
-	{
-		int i;
-		FP2 t1 = new FP2(0);
-		FP2 t2 = new FP2(0);
-
-		FP2[] work = new FP2[m];
-		work[0] = new FP2(1);
-		work[1] = new FP2(P[0].z);
-		for (i = 2;i < m;i++)
-		{
-			work[i] = new FP2(work[i - 1]);
-			work[i].mul(P[i - 1].z);
-		}
-
-		t1.copy(work[m - 1]);
-		t1.mul(P[m - 1].z);
-
-		t1.inverse();
-
-		t2.copy(P[m - 1].z);
-		work[m - 1].mul(t1);
-
-		for (i = m - 2;;i--)
-		{
-			if (i == 0)
-			{
-				work[0].copy(t1);
-				work[0].mul(t2);
-				break;
-			}
-			work[i].mul(t2);
-			work[i].mul(t1);
-			t2.mul(P[i].z);
-		}
-/* now work[] contains inverses of all Z coordinates */
-
-		for (i = 0;i < m;i++)
-		{
-			P[i].z.one();
-			t1.copy(work[i]);
-			t1.sqr();
-			P[i].x.mul(t1);
-			t1.mul(work[i]);
-			P[i].y.mul(t1);
-		}
-	}
-
-/* P*=e */
-	public ECP2 mul(BIG e)
-	{
-/* fixed size windows */
-		int i, b, nb, m, s, ns;
-		BIG mt = new BIG();
-		BIG t = new BIG();
-		ECP2 P = new ECP2();
-		ECP2 Q = new ECP2();
-		ECP2 C = new ECP2();
-		ECP2[] W = new ECP2[8];
-		sbyte[] w = new sbyte[1 + (ROM.NLEN * ROM.BASEBITS + 3) / 4];
-
-		if (is_infinity())
-		{
-			return new ECP2();
-		}
-
-		affine();
-
-/* precompute table */
-		Q.copy(this);
-		Q.dbl();
-		W[0] = new ECP2();
-		W[0].copy(this);
-
-		for (i = 1;i < 8;i++)
-		{
-			W[i] = new ECP2();
-			W[i].copy(W[i - 1]);
-			W[i].add(Q);
-		}
-
-/* convert the table to affine */
-
-		multiaffine(8,W);
-
-/* make exponent odd - add 2P if even, P if odd */
-		t.copy(e);
-		s = t.parity();
-		t.inc(1);
-		t.norm();
-		ns = t.parity();
-		mt.copy(t);
-		mt.inc(1);
-		mt.norm();
-		t.cmove(mt,s);
-		Q.cmove(this,ns);
-		C.copy(Q);
-
-		nb = 1 + (t.nbits() + 3) / 4;
-/* convert exponent to signed 4-bit window */
-		for (i = 0;i < nb;i++)
-		{
-			w[i] = (sbyte)(t.lastbits(5) - 16);
-			t.dec(w[i]);
-			t.norm();
-			t.fshr(4);
-		}
-		w[nb] = (sbyte)t.lastbits(5);
-
-		P.copy(W[(w[nb] - 1) / 2]);
-		for (i = nb - 1;i >= 0;i--)
-		{
-			Q.select(W,w[i]);
-			P.dbl();
-			P.dbl();
-			P.dbl();
-			P.dbl();
-			P.add(Q);
-		}
-		P.sub(C);
-		P.affine();
-		return P;
-	}
-
-/* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3 */
-	public static ECP2 mul4(ECP2[] Q, BIG[] u)
-	{
-		int i, j, nb;
-		int[] a = new int[4];
-		ECP2 T = new ECP2();
-		ECP2 C = new ECP2();
-		ECP2 P = new ECP2();
-		ECP2[] W = new ECP2[8];
-
-		BIG mt = new BIG();
-		BIG[] t = new BIG[4];
-
-		sbyte[] w = new sbyte[ROM.NLEN * ROM.BASEBITS + 1];
-
-		for (i = 0;i < 4;i++)
-		{
-			t[i] = new BIG(u[i]);
-			Q[i].affine();
-		}
-
-/* precompute table */
-
-		W[0] = new ECP2();
-		W[0].copy(Q[0]);
-		W[0].sub(Q[1]);
-		W[1] = new ECP2();
-		W[1].copy(W[0]);
-		W[2] = new ECP2();
-		W[2].copy(W[0]);
-		W[3] = new ECP2();
-		W[3].copy(W[0]);
-		W[4] = new ECP2();
-		W[4].copy(Q[0]);
-		W[4].add(Q[1]);
-		W[5] = new ECP2();
-		W[5].copy(W[4]);
-		W[6] = new ECP2();
-		W[6].copy(W[4]);
-		W[7] = new ECP2();
-		W[7].copy(W[4]);
-		T.copy(Q[2]);
-		T.sub(Q[3]);
-		W[1].sub(T);
-		W[2].add(T);
-		W[5].sub(T);
-		W[6].add(T);
-		T.copy(Q[2]);
-		T.add(Q[3]);
-		W[0].sub(T);
-		W[3].add(T);
-		W[4].sub(T);
-		W[7].add(T);
-
-		multiaffine(8,W);
-
-/* if multiplier is even add 1 to multiplier, and add P to correction */
-		mt.zero();
-		C.inf();
-		for (i = 0;i < 4;i++)
-		{
-			if (t[i].parity() == 0)
-			{
-				t[i].inc(1);
-				t[i].norm();
-				C.add(Q[i]);
-			}
-			mt.add(t[i]);
-			mt.norm();
-		}
-
-		nb = 1 + mt.nbits();
-
-/* convert exponent to signed 1-bit window */
-		for (j = 0;j < nb;j++)
-		{
-			for (i = 0;i < 4;i++)
-			{
-				a[i] = (sbyte)(t[i].lastbits(2) - 2);
-				t[i].dec(a[i]);
-				t[i].norm();
-				t[i].fshr(1);
-			}
-			w[j] = (sbyte)(8 * a[0] + 4 * a[1] + 2 * a[2] + a[3]);
-		}
-		w[nb] = (sbyte)(8 * t[0].lastbits(2) + 4 * t[1].lastbits(2) + 2 * t[2].lastbits(2) + t[3].lastbits(2));
-
-		P.copy(W[(w[nb] - 1) / 2]);
-		for (i = nb - 1;i >= 0;i--)
-		{
-			T.select(W,w[i]);
-			P.dbl();
-			P.add(T);
-		}
-		P.sub(C); // apply correction
-
-		P.affine();
-		return P;
-	}
-
-
-/*
-	public static void main(String[] args) {
-		BIG r=new BIG(ROM.Modulus);
-
-		BIG Pxa=new BIG(ROM.CURVE_Pxa);
-		BIG Pxb=new BIG(ROM.CURVE_Pxb);
-		BIG Pya=new BIG(ROM.CURVE_Pya);
-		BIG Pyb=new BIG(ROM.CURVE_Pyb);
-
-		BIG Fra=new BIG(ROM.CURVE_Fra);
-		BIG Frb=new BIG(ROM.CURVE_Frb);
-
-		FP2 f=new FP2(Fra,Frb);
-
-		FP2 Px=new FP2(Pxa,Pxb);
-		FP2 Py=new FP2(Pya,Pyb);
-
-		ECP2 P=new ECP2(Px,Py);
-
-		System.out.println("P= "+P.toString());
-
-		P=P.mul(r);
-		System.out.println("P= "+P.toString());
-
-		ECP2 Q=new ECP2(Px,Py);
-		Q.frob(f);
-		System.out.println("Q= "+Q.toString());
-
-
-	} */
-
-
-}
diff --git a/cs/FF.cs b/cs/FF.cs
deleted file mode 100644
index ed27844..0000000
--- a/cs/FF.cs
+++ /dev/null
@@ -1,1084 +0,0 @@
-/*
-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.
-*/
-
-/* Large Finite Field arithmetic */
-/* AMCL mod p functions */
-
-public sealed class FF
-{
-	private readonly BIG[] v;
-	private readonly int length;
-
-	private static readonly int P_MBITS = ROM.MODBYTES * 8;
-	private static readonly int P_MB = (P_MBITS % ROM.BASEBITS);
-	private static readonly long P_OMASK = ((long)(-1) << (P_MBITS % ROM.BASEBITS));
-	private static readonly long P_FEXCESS = ((long)1 << (ROM.BASEBITS * ROM.NLEN - P_MBITS));
-	private static readonly int P_TBITS = (P_MBITS % ROM.BASEBITS);
-
-	public long P_EXCESS()
-	{
-		return ((v[length - 1].get(ROM.NLEN - 1) & P_OMASK) >> (P_MB));
-	}
-
-/* Constructors */
-	public FF(int n)
-	{
-		v = new BIG[n];
-		for (int i = 0;i < n;i++)
-		{
-			v[i] = new BIG(0);
-		}
-		length = n;
-	}
-
-	public FF(long[][] x, int n)
-	{
-		v = new BIG[n];
-		for (int i = 0;i < n;i++)
-		{
-			v[i] = new BIG(x[i]);
-		}
-		length = n;
-	}
-
-	public int getlen()
-	{
-		return length;
-	}
-
-/* set to integer */
-	public void set(int m)
-	{
-		zero();
-		v[0].set(0,(long)m);
-	}
-
-/* copy from FF b */
-	public void copy(FF b)
-	{
-		for (int i = 0;i < length;i++)
-		{
-			v[i].copy(b.v[i]);
-		}
-	}
-
-/* x=y<<n */
-	public void dsucopy(FF b)
-	{
-		for (int i = 0;i < b.length;i++)
-		{
-			v[b.length + i].copy(b.v[i]);
-			v[i].zero();
-		}
-	}
-
-/* x=y */
-	public void dscopy(FF b)
-	{
-		for (int i = 0;i < b.length;i++)
-		{
-			v[i].copy(b.v[i]);
-			v[b.length + i].zero();
-		}
-	}
-
-/* x=y>>n */
-	public void sducopy(FF b)
-	{
-		for (int i = 0;i < length;i++)
-		{
-			v[i].copy(b.v[length + i]);
-		}
-	}
-
-/* set to zero */
-	public void zero()
-	{
-		for (int i = 0;i < length;i++)
-		{
-			v[i].zero();
-		}
-	}
-
-	public void one()
-	{
-		v[0].one();
-		for (int i = 1;i < length;i++)
-		{
-			v[i].zero();
-		}
-	}
-
-/* test equals 0 */
-	public bool iszilch()
-	{
-		for (int i = 0;i < length;i++)
-		{
-			if (!v[i].iszilch())
-			{
-				return false;
-			}
-		}
-		return true;
-	}
-
-/* shift right by 256-bit words */
-	public void shrw(int n)
-	{
-		for (int i = 0;i < n;i++)
-		{
-			v[i].copy(v[i + n]);
-			v[i + n].zero();
-		}
-	}
-
-/* shift left by 256-bit words */
-	public void shlw(int n)
-	{
-		for (int i = 0;i < n;i++)
-		{
-			v[n + i].copy(v[i]);
-			v[i].zero();
-		}
-	}
-
-/* extract last bit */
-	public int parity()
-	{
-		return v[0].parity();
-	}
-
-	public int lastbits(int m)
-	{
-		return v[0].lastbits(m);
-	}
-
-/* compare x and y - must be normalised, and of same length */
-	public static int comp(FF a, FF b)
-	{
-		int i, j;
-		for (i = a.length - 1;i >= 0;i--)
-		{
-			j = BIG.comp(a.v[i],b.v[i]);
-			if (j != 0)
-			{
-				return j;
-			}
-		}
-		return 0;
-	}
-
-/* recursive add */
-	public void radd(int vp, FF x, int xp, FF y, int yp, int n)
-	{
-		for (int i = 0;i < n;i++)
-		{
-			v[vp + i].copy(x.v[xp + i]);
-			v[vp + i].add(y.v[yp + i]);
-		}
-	}
-
-/* recursive inc */
-	public void rinc(int vp, FF y, int yp, int n)
-	{
-		for (int i = 0;i < n;i++)
-		{
-			v[vp + i].add(y.v[yp + i]);
-		}
-	}
-
-/* recursive sub */
-	public void rsub(int vp, FF x, int xp, FF y, int yp, int n)
-	{
-		for (int i = 0;i < n;i++)
-		{
-			v[vp + i].copy(x.v[xp + i]);
-			v[vp + i].sub(y.v[yp + i]);
-		}
-	}
-
-/* recursive dec */
-	public void rdec(int vp, FF y, int yp, int n)
-	{
-		for (int i = 0;i < n;i++)
-		{
-			v[vp + i].sub(y.v[yp + i]);
-		}
-	}
-
-/* simple add */
-	public void add(FF b)
-	{
-		for (int i = 0;i < length;i++)
-		{
-			v[i].add(b.v[i]);
-		}
-	}
-
-/* simple sub */
-	public void sub(FF b)
-	{
-		for (int i = 0;i < length;i++)
-		{
-			v[i].sub(b.v[i]);
-		}
-	}
-
-/* reverse sub */
-	public void revsub(FF b)
-	{
-		for (int i = 0;i < length;i++)
-		{
-			v[i].rsub(b.v[i]);
-		}
-	}
-
-/* increment/decrement by a small integer */
-	public void inc(int m)
-	{
-		v[0].inc(m);
-		norm();
-	}
-
-	public void dec(int m)
-	{
-		v[0].dec(m);
-		norm();
-	}
-
-	/* normalise - but hold any overflow in top part unless n<0 */
-	private void rnorm(int vp, int n)
-	{
-		bool trunc = false;
-		int i;
-		long carry;
-		if (n < 0)
-		{ // -v n signals to do truncation
-			n = -n;
-			trunc = true;
-		}
-		for (i = 0;i < n - 1;i++)
-		{
-			carry = v[vp + i].norm();
-			v[vp + i].xortop(carry << P_TBITS);
-			v[vp + i + 1].inc((int)carry);
-		}
-		carry = v[vp + n - 1].norm();
-		if (trunc)
-		{
-			v[vp + n - 1].xortop(carry << P_TBITS);
-		}
-
-	}
-
-	public void norm()
-	{
-		rnorm(0,length);
-	}
-
-/* shift left by one bit */
-	public void shl()
-	{
-		int i , delay_carry = 0;
-		long carry;
-		for (i = 0;i < length - 1;i++)
-		{
-			carry = v[i].fshl(1);
-			v[i].inc(delay_carry);
-			v[i].xortop(carry << P_TBITS);
-			delay_carry = (int)carry;
-		}
-		v[length - 1].fshl(1);
-		v[length - 1].inc(delay_carry);
-	}
-
-/* shift right by one bit */
-
-	public void shr()
-	{
-		int i;
-		long carry;
-		for (i = length - 1;i > 0;i--)
-		{
-			carry = v[i].fshr(1);
-			v[i - 1].ortop(carry << P_TBITS);
-		}
-		v[0].fshr(1);
-	}
-
-/* Convert to Hex String */
-	public override string ToString()
-	{
-		norm();
-		string s = "";
-		for (int i = length - 1;i >= 0;i--)
-		{
-			s += v[i].ToString();
-		}
-		return s;
-	}
-
-/* Convert FFs to/from byte arrays */
-	public void toBytes(sbyte[] b)
-	{
-		for (int i = 0;i < length;i++)
-		{
-			v[i].tobytearray(b,(length - i - 1) * ROM.MODBYTES);
-		}
-	}
-
-	public static void fromBytes(FF x, sbyte[] b)
-	{
-		for (int i = 0;i < x.length;i++)
-		{
-			x.v[i] = BIG.frombytearray(b,(x.length - i - 1) * ROM.MODBYTES);
-		}
-	}
-
-/* in-place swapping using xor - side channel resistant - lengths must be the same */
-	private static void cswap(FF a, FF b, int d)
-	{
-		for (int i = 0;i < a.length;i++)
-		{
-		//	BIG.cswap(a.v[i],b.v[i],d);
-			a.v[i].cswap(b.v[i],d);
-		}
-	}
-
-/* z=x*y, t is workspace */
-	private void karmul(int vp, FF x, int xp, FF y, int yp, FF t, int tp, int n)
-	{
-		int nd2;
-		if (n == 1)
-		{
-			DBIG d = BIG.mul(x.v[xp],y.v[yp]);
-			v[vp + 1] = d.Split(8 * ROM.MODBYTES);
-			v[vp].copy(d);
-			return;
-		}
-		nd2 = n / 2;
-		radd(vp,x,xp,x,xp + nd2,nd2);
-		//rnorm(vp,nd2);
-		radd(vp + nd2,y,yp,y,yp + nd2,nd2);
-		//rnorm(vp+nd2,nd2);
-		t.karmul(tp,this,vp,this,vp + nd2,t,tp + n,nd2);
-		karmul(vp,x,xp,y,yp,t,tp + n,nd2);
-		karmul(vp + n,x,xp + nd2,y,yp + nd2,t,tp + n,nd2);
-		t.rdec(tp,this,vp,n);
-		t.rdec(tp,this,vp + n,n);
-		rinc(vp + nd2,t,tp,n);
-		rnorm(vp,2 * n);
-	}
-
-	private void karsqr(int vp, FF x, int xp, FF t, int tp, int n)
-	{
-		int nd2;
-		if (n == 1)
-		{
-			DBIG d = BIG.sqr(x.v[xp]);
-			v[vp + 1].copy(d.Split(8 * ROM.MODBYTES));
-			v[vp].copy(d);
-			return;
-		}
-
-		nd2 = n / 2;
-		karsqr(vp,x,xp,t,tp + n,nd2);
-		karsqr(vp + n,x,xp + nd2,t,tp + n,nd2);
-		t.karmul(tp,x,xp,x,xp + nd2,t,tp + n,nd2);
-		rinc(vp + nd2,t,tp,n);
-		rinc(vp + nd2,t,tp,n);
-		rnorm(vp + nd2,n);
-	}
-
-
-	private void karmul_lower(int vp, FF x, int xp, FF y, int yp, FF t, int tp, int n)
-	{ // Calculates Least Significant bottom half of x*y
-		int nd2;
-		if (n == 1)
-		{ // only calculate bottom half of product
-			v[vp].copy(BIG.smul(x.v[xp],y.v[yp]));
-			return;
-		}
-		nd2 = n / 2;
-
-		karmul(vp,x,xp,y,yp,t,tp + n,nd2);
-		t.karmul_lower(tp,x,xp + nd2,y,yp,t,tp + n,nd2);
-		rinc(vp + nd2,t,tp,nd2);
-		t.karmul_lower(tp,x,xp,y,yp + nd2,t,tp + n,nd2);
-		rinc(vp + nd2,t,tp,nd2);
-		rnorm(vp + nd2,-nd2); // truncate it
-	}
-
-	private void karmul_upper(FF x, FF y, FF t, int n)
-	{ // Calculates Most Significant upper half of x*y, given lower part
-		int nd2;
-
-		nd2 = n / 2;
-		radd(n,x,0,x,nd2,nd2);
-		radd(n + nd2,y,0,y,nd2,nd2);
-
-		t.karmul(0,this,n + nd2,this,n,t,n,nd2); // t = (a0+a1)(b0+b1)
-		karmul(n,x,nd2,y,nd2,t,n,nd2); // z[n]= a1*b1
-									/* z[0-nd2]=l(a0b0) z[nd2-n]= h(a0b0)+l(t)-l(a0b0)-l(a1b1) */
-		t.rdec(0,this,n,n); // t=t-a1b1
-		rinc(nd2,this,0,nd2); // z[nd2-n]+=l(a0b0) = h(a0b0)+l(t)-l(a1b1)
-		rdec(nd2,t,0,nd2); // z[nd2-n]=h(a0b0)+l(t)-l(a1b1)-l(t-a1b1)=h(a0b0)
-		rnorm(0,-n); // a0b0 now in z - truncate it
-		t.rdec(0,this,0,n); // (a0+a1)(b0+b1) - a0b0
-		rinc(nd2,t,0,n);
-
-		rnorm(nd2,n);
-	}
-
-	/* z=x*y. Assumes x and y are of same length. */
-	public static FF mul(FF x, FF y)
-	{
-		int n = x.length;
-		FF z = new FF(2 * n);
-		FF t = new FF(2 * n);
-		z.karmul(0,x,0,y,0,t,0,n);
-		return z;
-	}
-
-/* return low part of product this*y */
-	public void lmul(FF y)
-	{
-		int n = length;
-		FF t = new FF(2 * n);
-		FF x = new FF(n);
-		x.copy(this);
-		karmul_lower(0,x,0,y,0,t,0,n);
-	}
-
-/* Set b=b mod c */
-	public void mod(FF c)
-	{
-		int k = 0;
-
-		norm();
-		if (comp(this,c) < 0)
-		{
-			return;
-		}
-		do
-		{
-			c.shl();
-			k++;
-		} while (comp(this,c) >= 0);
-
-		while (k > 0)
-		{
-			c.shr();
-			if (comp(this,c) >= 0)
-			{
-				sub(c);
-				norm();
-			}
-			k--;
-		}
-	}
-
-	/* z=x^2 */
-	public static FF sqr(FF x)
-	{
-		int n = x.length;
-		FF z = new FF(2 * n);
-		FF t = new FF(2 * n);
-		z.karsqr(0,x,0,t,0,n);
-		return z;
-	}
-
-/* return This mod modulus, N is modulus, ND is Montgomery Constant */
-	public FF reduce(FF N, FF ND)
-	{ // fast karatsuba Montgomery reduction
-		int n = N.length;
-		FF t = new FF(2 * n);
-		FF r = new FF(n);
-		FF m = new FF(n);
-
-		r.sducopy(this);
-		m.karmul_lower(0,this,0,ND,0,t,0,n);
-		karmul_upper(N,m,t,n);
-		m.sducopy(this);
-
-		r.add(N);
-		r.sub(m);
-		r.norm();
-
-		return r;
-
-	}
-
-/* Set r=this mod b */
-/* this is of length - 2*n */
-/* r,b is of length - n */
-	public FF dmod(FF b)
-	{
-		int k , n = b.length;
-		FF m = new FF(2 * n);
-		FF x = new FF(2 * n);
-		FF r = new FF(n);
-
-		x.copy(this);
-		x.norm();
-		m.dsucopy(b);
-		k = 256 * n;
-
-		while (k > 0)
-		{
-			m.shr();
-
-			if (comp(x,m) >= 0)
-			{
-				x.sub(m);
-				x.norm();
-			}
-			k--;
-		}
-
-		r.copy(x);
-		r.mod(b);
-		return r;
-	}
-
-/* Set return=1/this mod p. Binary method - a<p on entry */
-
-	public void invmodp(FF p)
-	{
-		int n = p.length;
-
-		FF u = new FF(n);
-		FF v = new FF(n);
-		FF x1 = new FF(n);
-		FF x2 = new FF(n);
-		FF t = new FF(n);
-		FF one = new FF(n);
-
-		one.one();
-		u.copy(this);
-		v.copy(p);
-		x1.copy(one);
-		x2.zero();
-
-	// reduce n in here as well!
-		while (comp(u,one) != 0 && comp(v,one) != 0)
-		{
-			while (u.parity() == 0)
-			{
-				u.shr();
-				if (x1.parity() != 0)
-				{
-					x1.add(p);
-					x1.norm();
-				}
-				x1.shr();
-			}
-			while (v.parity() == 0)
-			{
-				v.shr();
-				if (x2.parity() != 0)
-				{
-					x2.add(p);
-					x2.norm();
-				}
-				x2.shr();
-			}
-			if (comp(u,v) >= 0)
-			{
-
-				u.sub(v);
-				u.norm();
-				if (comp(x1,x2) >= 0)
-				{
-					x1.sub(x2);
-				}
-				else
-				{
-					t.copy(p);
-					t.sub(x2);
-					x1.add(t);
-				}
-				x1.norm();
-			}
-			else
-			{
-				v.sub(u);
-				v.norm();
-				if (comp(x2,x1) >= 0)
-				{
-					x2.sub(x1);
-				}
-				else
-				{
-					t.copy(p);
-					t.sub(x1);
-					x2.add(t);
-				}
-				x2.norm();
-			}
-		}
-		if (comp(u,one) == 0)
-		{
-			copy(x1);
-		}
-		else
-		{
-			copy(x2);
-		}
-	}
-
-/* nresidue mod m */
-	public void nres(FF m)
-	{
-		int n = m.length;
-		FF d = new FF(2 * n);
-		d.dsucopy(this);
-		copy(d.dmod(m));
-	}
-
-	public void redc(FF m, FF ND)
-	{
-		int n = m.length;
-		FF d = new FF(2 * n);
-		mod(m);
-		d.dscopy(this);
-		copy(d.reduce(m,ND));
-		mod(m);
-	}
-
-	private void mod2m(int m)
-	{
-		for (int i = m;i < length;i++)
-		{
-			v[i].zero();
-		}
-	}
-
-	/* U=1/a mod 2^m - Arazi & Qi */
-	private FF invmod2m()
-	{
-		int i , n = length;
-
-		FF b = new FF(n);
-		FF c = new FF(n);
-		FF U = new FF(n);
-
-		FF t;
-
-		U.zero();
-		U.v[0].copy(v[0]);
-		U.v[0].invmod2m();
-
-		for (i = 1;i < n;i <<= 1)
-		{
-			b.copy(this);
-			b.mod2m(i);
-			t = mul(U,b);
-			t.shrw(i);
-			b.copy(t);
-			c.copy(this);
-			c.shrw(i);
-			c.mod2m(i);
-			c.lmul(U);
-			c.mod2m(i);
-
-			b.add(c);
-			b.norm();
-			b.lmul(U);
-			b.mod2m(i);
-
-			c.one();
-			c.shlw(i);
-			b.revsub(c);
-			b.norm();
-			b.shlw(i);
-			U.add(b);
-		}
-		U.norm();
-		return U;
-	}
-
-	public void random(RAND rng)
-	{
-		int n = length;
-		for (int i = 0;i < n;i++)
-		{
-			v[i].copy(BIG.random(rng));
-		}
-	/* make sure top bit is 1 */
-		while (v[n - 1].nbits() < ROM.MODBYTES * 8)
-		{
-			v[n - 1].copy(BIG.random(rng));
-		}
-	}
-
-	/* generate random x */
-	public void randomnum(FF p, RAND rng)
-	{
-		int n = length;
-		FF d = new FF(2 * n);
-
-		for (int i = 0;i < 2 * n;i++)
-		{
-			d.v[i].copy(BIG.random(rng));
-		}
-		copy(d.dmod(p));
-	}
-
-	/* this*=y mod p */
-	public void modmul(FF y, FF p, FF nd)
-	{
-		//FF d=new FF(2*p.length);
-		long ex = P_EXCESS();
-		long ey = y.P_EXCESS();
-		if ((ex + 1) * (ey + 1) + 1 >= P_FEXCESS)
-		{
-			mod(p);
-		}
-		FF d = mul(this,y);
-		copy(d.reduce(p,nd));
-	}
-
-	/* this*=y mod p */
-	public void modsqr(FF p, FF nd)
-	{
-		//FF d=new FF(2*p.length);
-		long ex = P_EXCESS();
-		if ((ex + 1) * (ex + 1) + 1 >= P_FEXCESS)
-		{
-			mod(p);
-		}
-		FF d = sqr(this);
-		copy(d.reduce(p,nd));
-	}
-
-	/* this=this^e mod p using side-channel resistant Montgomery Ladder, for large e */
-	public void skpow(FF e, FF p)
-	{
-		int i , b , n = p.length;
-		FF R0 = new FF(n);
-		FF R1 = new FF(n);
-		FF ND = p.invmod2m();
-
-		mod(p);
-		R0.one();
-		R1.copy(this);
-		R0.nres(p);
-		R1.nres(p);
-
-		for (i = 8 * ROM.MODBYTES * n - 1;i >= 0;i--)
-		{
-			b = e.v[i / 256].bit(i % 256);
-			copy(R0);
-			modmul(R1,p,ND);
-
-			cswap(R0,R1,b);
-			R0.modsqr(p,ND);
-
-			R1.copy(this);
-			cswap(R0,R1,b);
-		}
-		copy(R0);
-		redc(p,ND);
-	}
-
-	/* this =this^e mod p using side-channel resistant Montgomery Ladder, for short e */
-	public void skpow(BIG e, FF p)
-	{
-		int i , b , n = p.length;
-		FF R0 = new FF(n);
-		FF R1 = new FF(n);
-		FF ND = p.invmod2m();
-
-		mod(p);
-		R0.one();
-		R1.copy(this);
-		R0.nres(p);
-		R1.nres(p);
-
-		for (i = 8 * ROM.MODBYTES - 1;i >= 0;i--)
-		{
-			b = e.bit(i);
-			copy(R0);
-			modmul(R1,p,ND);
-
-			cswap(R0,R1,b);
-			R0.modsqr(p,ND);
-
-			R1.copy(this);
-			cswap(R0,R1,b);
-		}
-		copy(R0);
-		redc(p,ND);
-	}
-
-	/* raise to an integer power - right-to-left method */
-	public void power(int e, FF p)
-	{
-		int n = p.length;
-		FF w = new FF(n);
-		FF ND = p.invmod2m();
-		bool f = true;
-
-		w.copy(this);
-		w.nres(p);
-
-		if (e == 2)
-		{
-			copy(w);
-			modsqr(p,ND);
-		}
-		else
-		{
-			for (; ;)
-			{
-			if (e % 2 == 1)
-			{
-				if (f)
-				{
-					copy(w);
-				}
-				else
-				{
-					modmul(w,p,ND);
-				}
-				f = false;
-			}
-			e >>= 1;
-			if (e == 0)
-			{
-				break;
-			}
-			w.modsqr(p,ND);
-			}
-		}
-		redc(p,ND);
-	}
-
-	/* this=this^e mod p, faster but not side channel resistant */
-	public void pow(FF e, FF p)
-	{
-		int i , b , n = p.length;
-		FF w = new FF(n);
-		FF ND = p.invmod2m();
-
-		w.copy(this);
-		one();
-		nres(p);
-		w.nres(p);
-		for (i = 8 * ROM.MODBYTES * n - 1;i >= 0;i--)
-		{
-			modsqr(p,ND);
-			b = e.v[i / 256].bit(i % 256);
-			if (b == 1)
-			{
-				modmul(w,p,ND);
-			}
-		}
-		redc(p,ND);
-	}
-
-	/* double exponentiation r=x^e.y^f mod p */
-	public void pow2(BIG e, FF y, BIG f, FF p)
-	{
-		int i , eb , fb , n = p.length;
-		FF xn = new FF(n);
-		FF yn = new FF(n);
-		FF xy = new FF(n);
-		FF ND = p.invmod2m();
-
-		xn.copy(this);
-		yn.copy(y);
-		xn.nres(p);
-		yn.nres(p);
-		xy.copy(xn);
-		xy.modmul(yn,p,ND);
-		one();
-		nres(p);
-
-		for (i = 8 * ROM.MODBYTES - 1;i >= 0;i--)
-		{
-			eb = e.bit(i);
-			fb = f.bit(i);
-			modsqr(p,ND);
-			if (eb == 1)
-			{
-				if (fb == 1)
-				{
-					modmul(xy,p,ND);
-				}
-				else
-				{
-					modmul(xn,p,ND);
-				}
-			}
-			else
-			{
-				if (fb == 1)
-				{
-					modmul(yn,p,ND);
-				}
-			}
-		}
-		redc(p,ND);
-	}
-
-	private static int igcd(int x, int y)
-	{ // integer GCD, returns GCD of x and y
-		int r;
-		if (y == 0)
-		{
-			return x;
-		}
-		while ((r = x % y) != 0)
-		{
-				x = y;
-				y = r;
-		}
-		return y;
-	}
-
-	/* quick and dirty check for common factor with n */
-	public bool cfactor(int s)
-	{
-		int r , n = length;
-		int g;
-
-		FF x = new FF(n);
-		FF y = new FF(n);
-
-		y.set(s);
-		x.copy(this);
-		x.norm();
-
-		do
-		{
-			x.sub(y);
-			x.norm();
-			while (!x.iszilch() && x.parity() == 0)
-			{
-				x.shr();
-			}
-		} while (comp(x,y) > 0);
-
-		g = (int)x.v[0].get(0);
-		r = igcd(s,g);
-		if (r > 1)
-		{
-			return true;
-		}
-		return false;
-	}
-
-	/* Miller-Rabin test for primality. Slow. */
-	public static bool prime(FF p, RAND rng)
-	{
-		int i , j , s = 0, n = p.length;
-		bool loop;
-		FF d = new FF(n);
-		FF x = new FF(n);
-		FF unity = new FF(n);
-		FF nm1 = new FF(n);
-
-		int sf = 4849845; // 3*5*.. *19
-		p.norm();
-
-		if (p.cfactor(sf))
-		{
-			return false;
-		}
-		unity.one();
-		nm1.copy(p);
-		nm1.sub(unity);
-		nm1.norm();
-		d.copy(nm1);
-
-		while (d.parity() == 0)
-		{
-			d.shr();
-			s++;
-		}
-		if (s == 0)
-		{
-			return false;
-		}
-		for (i = 0;i < 10;i++)
-		{
-			x.randomnum(p,rng);
-			x.pow(d,p);
-			if (comp(x,unity) == 0 || comp(x,nm1) == 0)
-			{
-				continue;
-			}
-			loop = false;
-			for (j = 1;j < s;j++)
-			{
-				x.power(2,p);
-				if (comp(x,unity) == 0)
-				{
-					return false;
-				}
-				if (comp(x,nm1) == 0)
-				{
-					loop = true;
-					break;
-				}
-			}
-			if (loop)
-			{
-				continue;
-			}
-			return false;
-		}
-		return true;
-	}
-
-/*
-	public static final long[][] P ={{0xAD19A781670957L,0x76A79C00965796L,0xDEFCC5FC9A9717L,0xF02F2940E20E9L,0xBF59E34FL},{0x6894F31844C908L,0x8DADA70E82C79FL,0xFD29F3836046F6L,0x8C1D874D314DD0L,0x46D077BL},{0x3C515217813331L,0x56680FD1CE935BL,0xE55C53EEA8838EL,0x92C2F7E14A4A95L,0xD945E5B1L},{0xACF673E919F5EFL,0x6723E7E7DAB446L,0x6B6FA69B36EB1BL,0xF7D13920ECA300L,0xB5FC2165L}};
-
-	public static void main(String[] args) {
-		byte[] raw=new byte[100];
-		RAND rng=new RAND();
-
-		rng.clean();
-		for (int i=0;i<100;i++) raw[i]=(byte)i;
-
-		rng.seed(100,raw);
-
-		int n=4;
-
-		FF x=new FF(n);
-		x.set(3);
-
-		FF p=new FF(P,n);
-
-		if (prime(p,rng)) System.out.println("p is a prime");
-
-		FF e=new FF(n);
-		e.copy(p);
-		e.dec(1); e.norm();
-
-		System.out.println("e= "+e.toString());
-
-		x.skpow(e,p);
-		System.out.println("x= "+x.toString());
-
-    } */
-
-}
diff --git a/cs/FP.cs b/cs/FP.cs
deleted file mode 100644
index 4e7b74e..0000000
--- a/cs/FP.cs
+++ /dev/null
@@ -1,368 +0,0 @@
-/*
-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.
-*/
-
-/* Finite Field arithmetic */
-/* AMCL mod p functions */
-
-public sealed class FP
-{
-	private readonly BIG x;
-	private static BIG p = new BIG(ROM.Modulus);
-
-/* Constructors */
-	public FP(int a)
-	{
-		x = new BIG(a);
-		nres();
-	}
-
-	public FP(BIG a)
-	{
-		x = new BIG(a);
-		nres();
-	}
-
-	public FP(FP a)
-	{
-		x = new BIG(a.x);
-	}
-
-/* convert to string */
-	public override string ToString()
-	{
-		string s = redc().ToString();
-		return s;
-	}
-
-	public string toRawString()
-	{
-		string s = x.toRawString();
-		return s;
-	}
-
-/* convert to Montgomery n-residue form */
-	public void nres()
-	{
-		if (ROM.MODTYPE != ROM.PSEUDO_MERSENNE)
-		{
-			DBIG d = new DBIG(x);
-			d.shl(ROM.NLEN * ROM.BASEBITS);
-			x.copy(d.mod(p));
-		}
-	}
-
-/* convert back to regular form */
-	public BIG redc()
-	{
-		if (ROM.MODTYPE != ROM.PSEUDO_MERSENNE)
-		{
-			DBIG d = new DBIG(x);
-			return BIG.mod(d);
-		}
-		else
-		{
-			BIG r = new BIG(x);
-			return r;
-		}
-	}
-
-/* test this=0? */
-	public bool iszilch()
-	{
-		reduce();
-		return x.iszilch();
-	}
-
-/* copy from FP b */
-	public void copy(FP b)
-	{
-		x.copy(b.x);
-	}
-
-/* set this=0 */
-	public void zero()
-	{
-		x.zero();
-	}
-
-/* set this=1 */
-	public void one()
-	{
-		x.one();
-		nres();
-	}
-
-/* normalise this */
-	public void norm()
-	{
-		x.norm();
-	}
-
-/* swap FPs depending on d */
-	public void cswap(FP b, int d)
-	{
-		x.cswap(b.x,d);
-	}
-
-/* copy FPs depending on d */
-	public void cmove(FP b, int d)
-	{
-		x.cmove(b.x,d);
-	}
-
-/* this*=b mod Modulus */
-	public void mul(FP b)
-	{
-		long ea = BIG.EXCESS(x);
-		long eb = BIG.EXCESS(b.x);
-
-		if ((ea + 1) * (eb + 1) + 1 >= ROM.FEXCESS)
-		{
-			reduce();
-		}
-
-		DBIG d = BIG.mul(x,b.x);
-		x.copy(BIG.mod(d));
-	}
-
-/* this*=c mod Modulus, where c is a small int */
-	public void imul(int c)
-	{
-		norm();
-		bool s = false;
-		if (c < 0)
-		{
-			c = -c;
-			s = true;
-		}
-		long afx = (BIG.EXCESS(x) + 1) * (c + 1) + 1;
-		if (c < ROM.NEXCESS && afx < ROM.FEXCESS)
-		{
-			x.imul(c);
-		}
-		else
-		{
-			if (afx < ROM.FEXCESS)
-			{
-				x.pmul(c);
-			}
-			else
-			{
-				DBIG d = x.pxmul(c);
-				x.copy(d.mod(p));
-			}
-		}
-		if (s)
-		{
-			neg();
-		}
-		norm();
-	}
-
-
-/* this*=this mod Modulus */
-	public void sqr()
-	{
-		DBIG d;
-		long ea = BIG.EXCESS(x);
-		if ((ea + 1) * (ea + 1) + 1 >= ROM.FEXCESS)
-		{
-			reduce();
-		}
-
-		d = BIG.sqr(x);
-		x.copy(BIG.mod(d));
-	}
-
-/* this+=b */
-	public void add(FP b)
-	{
-		x.add(b.x);
-		if (BIG.EXCESS(x) + 2 >= ROM.FEXCESS)
-		{
-			reduce();
-		}
-	}
-
-/* this = -this mod Modulus */
-	public void neg()
-	{
-		int sb;
-		long ov;
-		BIG m = new BIG(p);
-
-		norm();
-
-		ov = BIG.EXCESS(x);
-		sb = 1;
-		while (ov != 0)
-		{
-			sb++;
-			ov >>= 1;
-		}
-
-		m.fshl(sb);
-		x.rsub(m);
-
-		if (BIG.EXCESS(x) >= ROM.FEXCESS)
-		{
-			reduce();
-		}
-	}
-
-/* this-=b */
-	public void sub(FP b)
-	{
-		FP n = new FP(b);
-		n.neg();
-		this.add(n);
-	}
-
-/* this/=2 mod Modulus */
-	public void div2()
-	{
-		x.norm();
-		if (x.parity() == 0)
-		{
-			x.fshr(1);
-		}
-		else
-		{
-			x.add(p);
-			x.norm();
-			x.fshr(1);
-		}
-	}
-
-/* this=1/this mod Modulus */
-	public void inverse()
-	{
-		BIG r = redc();
-		r.invmodp(p);
-		x.copy(r);
-		nres();
-	}
-
-/* return TRUE if this==a */
-	public bool Equals(FP a)
-	{
-		a.reduce();
-		reduce();
-		if (BIG.comp(a.x,x) == 0)
-		{
-			return true;
-		}
-		return false;
-	}
-
-/* reduce this mod Modulus */
-	public void reduce()
-	{
-		x.mod(p);
-	}
-
-/* return this^e mod Modulus */
-	public FP pow(BIG e)
-	{
-		int bt;
-		FP r = new FP(1);
-		e.norm();
-		x.norm();
-		FP m = new FP(this);
-		while (true)
-		{
-			bt = e.parity();
-			e.fshr(1);
-			if (bt == 1)
-			{
-				r.mul(m);
-			}
-			if (e.iszilch())
-			{
-				break;
-			}
-			m.sqr();
-		}
-		r.x.mod(p);
-		return r;
-	}
-
-/* return sqrt(this) mod Modulus */
-	public FP sqrt()
-	{
-		reduce();
-		BIG b = new BIG(p);
-		if (ROM.MOD8 == 5)
-		{
-			b.dec(5);
-			b.norm();
-			b.shr(3);
-			FP i = new FP(this);
-			i.x.shl(1);
-			FP v = i.pow(b);
-			i.mul(v);
-			i.mul(v);
-			i.x.dec(1);
-			FP r = new FP(this);
-			r.mul(v);
-			r.mul(i);
-			r.reduce();
-			return r;
-		}
-		else
-		{
-			b.inc(1);
-			b.norm();
-			b.shr(2);
-			return pow(b);
-		}
-	}
-
-/* return jacobi symbol (this/Modulus) */
-	public int jacobi()
-	{
-		BIG w = redc();
-		return w.jacobi(p);
-	}
-/*
-	public static void main(String[] args) {
-		BIG m=new BIG(ROM.Modulus);
-		BIG x=new BIG(3);
-		BIG e=new BIG(m);
-		e.dec(1);
-
-		System.out.println("m= "+m.nbits());
-
-
-		BIG r=x.powmod(e,m);
-
-		System.out.println("m= "+m.toString());
-		System.out.println("r= "+r.toString());
-
-		BIG.cswap(m,r,0);
-
-		System.out.println("m= "+m.toString());
-		System.out.println("r= "+r.toString());
-
-//		FP y=new FP(3);
-//		FP s=y.pow(e);
-//		System.out.println("s= "+s.toString());
-
-	} */
-}
diff --git a/cs/FP12.cs b/cs/FP12.cs
deleted file mode 100644
index 2574aa8..0000000
--- a/cs/FP12.cs
+++ /dev/null
@@ -1,769 +0,0 @@
-/*
-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.
-*/
-
-/* AMCL Fp^12 functions */
-/* FP12 elements are of the form a+i.b+i^2.c */
-
-public sealed class FP12
-{
-	private readonly FP4 a;
-	private readonly FP4 b;
-	private readonly FP4 c;
-/* reduce all components of this mod Modulus */
-	public void reduce()
-	{
-		a.reduce();
-		b.reduce();
-		c.reduce();
-	}
-/* normalise all components of this */
-	public void norm()
-	{
-		a.norm();
-		b.norm();
-		c.norm();
-	}
-/* test x==0 ? */
-	public bool iszilch()
-	{
-		reduce();
-		return (a.iszilch() && b.iszilch() && c.iszilch());
-	}
-/* test x==1 ? */
-	public bool isunity()
-	{
-		FP4 one = new FP4(1);
-		return (a.Equals(one) && b.iszilch() && c.iszilch());
-	}
-/* return 1 if x==y, else 0 */
-	public bool Equals(FP12 x)
-	{
-		return (a.Equals(x.a) && b.Equals(x.b) && c.Equals(x.c));
-	}
-/* extract a from this */
-	public FP4 geta()
-	{
-		return a;
-	}
-/* extract b */
-	public FP4 getb()
-	{
-		return b;
-	}
-/* extract c */
-	public FP4 getc()
-	{
-		return c;
-	}
-/* copy this=x */
-	public void copy(FP12 x)
-	{
-		a.copy(x.a);
-		b.copy(x.b);
-		c.copy(x.c);
-	}
-/* set this=1 */
-	public void one()
-	{
-		a.one();
-		b.zero();
-		c.zero();
-	}
-/* this=conj(this) */
-	public void conj()
-	{
-		a.conj();
-		b.nconj();
-		c.conj();
-	}
-/* Constructors */
-	public FP12(FP4 d)
-	{
-		a = new FP4(d);
-		b = new FP4(0);
-		c = new FP4(0);
-	}
-
-	public FP12(int d)
-	{
-		a = new FP4(d);
-		b = new FP4(0);
-		c = new FP4(0);
-	}
-
-	public FP12(FP4 d, FP4 e, FP4 f)
-	{
-		a = new FP4(d);
-		b = new FP4(e);
-		c = new FP4(f);
-	}
-
-	public FP12(FP12 x)
-	{
-		a = new FP4(x.a);
-		b = new FP4(x.b);
-		c = new FP4(x.c);
-	}
-
-/* Granger-Scott Unitary Squaring */
-	public void usqr()
-	{
-		FP4 A = new FP4(a);
-		FP4 B = new FP4(c);
-		FP4 C = new FP4(b);
-		FP4 D = new FP4(0);
-
-		a.sqr();
-		D.copy(a);
-		D.add(a);
-		a.add(D);
-
-//		a.norm();
-		A.nconj();
-
-		A.add(A);
-		a.add(A);
-		B.sqr();
-		B.times_i();
-
-		D.copy(B);
-		D.add(B);
-		B.add(D);
-//		B.norm();
-
-		C.sqr();
-		D.copy(C);
-		D.add(C);
-		C.add(D);
-//		C.norm();
-
-		b.conj();
-		b.add(b);
-		c.nconj();
-
-		c.add(c);
-		b.add(B);
-		c.add(C);
-		reduce();
-
-	}
-
-/* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
-	public void sqr()
-	{
-		FP4 A = new FP4(a);
-		FP4 B = new FP4(b);
-		FP4 C = new FP4(c);
-		FP4 D = new FP4(a);
-
-		A.sqr();
-		B.mul(c);
-		B.add(B);
-		C.sqr();
-		D.mul(b);
-		D.add(D);
-
-		c.add(a);
-		c.add(b);
-		c.sqr();
-
-		a.copy(A);
-
-		A.add(B);
-//		A.norm();
-		A.add(C);
-		A.add(D);
-//		A.norm();
-
-		A.neg();
-		B.times_i();
-		C.times_i();
-
-		a.add(B);
-
-		b.copy(C);
-		b.add(D);
-		c.add(A);
-		norm();
-	}
-
-/* FP12 full multiplication this=this*y */
-	public void mul(FP12 y)
-	{
-		FP4 z0 = new FP4(a);
-		FP4 z1 = new FP4(0);
-		FP4 z2 = new FP4(b);
-		FP4 z3 = new FP4(0);
-		FP4 t0 = new FP4(a);
-		FP4 t1 = new FP4(y.a);
-
-		z0.mul(y.a);
-		z2.mul(y.b);
-
-		t0.add(b);
-		t1.add(y.b);
-
-		z1.copy(t0);
-		z1.mul(t1);
-		t0.copy(b);
-		t0.add(c);
-
-		t1.copy(y.b);
-		t1.add(y.c);
-		z3.copy(t0);
-		z3.mul(t1);
-
-		t0.copy(z0);
-		t0.neg();
-		t1.copy(z2);
-		t1.neg();
-
-		z1.add(t0);
-//		z1.norm();
-		b.copy(z1);
-		b.add(t1);
-
-		z3.add(t1);
-		z2.add(t0);
-
-		t0.copy(a);
-		t0.add(c);
-		t1.copy(y.a);
-		t1.add(y.c);
-		t0.mul(t1);
-		z2.add(t0);
-
-		t0.copy(c);
-		t0.mul(y.c);
-		t1.copy(t0);
-		t1.neg();
-
-//		z2.norm();
-//		z3.norm();
-//		b.norm();
-
-		c.copy(z2);
-		c.add(t1);
-		z3.add(t1);
-		t0.times_i();
-		b.add(t0);
-
-		z3.times_i();
-		a.copy(z0);
-		a.add(z3);
-		norm();
-	}
-
-/* Special case of multiplication arises from special form of ATE pairing line function */
-	public void smul(FP12 y)
-	{
-		FP4 z0 = new FP4(a);
-		FP4 z2 = new FP4(b);
-		FP4 z3 = new FP4(b);
-		FP4 t0 = new FP4(0);
-		FP4 t1 = new FP4(y.a);
-
-		z0.mul(y.a);
-		z2.pmul(y.b.real());
-		b.add(a);
-		t1.real().add(y.b.real());
-
-		b.mul(t1);
-		z3.add(c);
-		z3.pmul(y.b.real());
-
-		t0.copy(z0);
-		t0.neg();
-		t1.copy(z2);
-		t1.neg();
-
-		b.add(t0);
-//		b.norm();
-
-		b.add(t1);
-		z3.add(t1);
-		z2.add(t0);
-
-		t0.copy(a);
-		t0.add(c);
-		t0.mul(y.a);
-		c.copy(z2);
-		c.add(t0);
-
-		z3.times_i();
-		a.copy(z0);
-		a.add(z3);
-
-		norm();
-	}
-
-/* this=1/this */
-	public void inverse()
-	{
-		FP4 f0 = new FP4(a);
-		FP4 f1 = new FP4(b);
-		FP4 f2 = new FP4(a);
-		FP4 f3 = new FP4(0);
-
-		norm();
-		f0.sqr();
-		f1.mul(c);
-		f1.times_i();
-		f0.sub(f1);
-
-		f1.copy(c);
-		f1.sqr();
-		f1.times_i();
-		f2.mul(b);
-		f1.sub(f2);
-
-		f2.copy(b);
-		f2.sqr();
-		f3.copy(a);
-		f3.mul(c);
-		f2.sub(f3);
-
-		f3.copy(b);
-		f3.mul(f2);
-		f3.times_i();
-		a.mul(f0);
-		f3.add(a);
-		c.mul(f1);
-		c.times_i();
-
-		f3.add(c);
-		f3.inverse();
-		a.copy(f0);
-		a.mul(f3);
-		b.copy(f1);
-		b.mul(f3);
-		c.copy(f2);
-		c.mul(f3);
-	}
-
-/* this=this^p using Frobenius */
-	public void frob(FP2 f)
-	{
-		FP2 f2 = new FP2(f);
-		FP2 f3 = new FP2(f);
-
-		f2.sqr();
-		f3.mul(f2);
-
-		a.frob(f3);
-		b.frob(f3);
-		c.frob(f3);
-
-		b.pmul(f);
-		c.pmul(f2);
-	}
-
-/* trace function */
-	public FP4 trace()
-	{
-		FP4 t = new FP4(0);
-		t.copy(a);
-		t.imul(3);
-		t.reduce();
-		return t;
-	}
-
-/* convert from byte array to FP12 */
-	public static FP12 fromBytes(sbyte[] w)
-	{
-		BIG a, b;
-		FP2 c, d;
-		FP4 e, f, g;
-		sbyte[] t = new sbyte[ROM.MODBYTES];
-
-		for (int i = 0;i < ROM.MODBYTES;i++)
-		{
-			t[i] = w[i];
-		}
-		a = BIG.fromBytes(t);
-		for (int i = 0;i < ROM.MODBYTES;i++)
-		{
-			t[i] = w[i + ROM.MODBYTES];
-		}
-		b = BIG.fromBytes(t);
-		c = new FP2(a,b);
-
-		for (int i = 0;i < ROM.MODBYTES;i++)
-		{
-			t[i] = w[i + 2 * ROM.MODBYTES];
-		}
-		a = BIG.fromBytes(t);
-		for (int i = 0;i < ROM.MODBYTES;i++)
-		{
-			t[i] = w[i + 3 * ROM.MODBYTES];
-		}
-		b = BIG.fromBytes(t);
-		d = new FP2(a,b);
-
-		e = new FP4(c,d);
-
-
-		for (int i = 0;i < ROM.MODBYTES;i++)
-		{
-			t[i] = w[i + 4 * ROM.MODBYTES];
-		}
-		a = BIG.fromBytes(t);
-		for (int i = 0;i < ROM.MODBYTES;i++)
-		{
-			t[i] = w[i + 5 * ROM.MODBYTES];
-		}
-		b = BIG.fromBytes(t);
-		c = new FP2(a,b);
-
-		for (int i = 0;i < ROM.MODBYTES;i++)
-		{
-			t[i] = w[i + 6 * ROM.MODBYTES];
-		}
-		a = BIG.fromBytes(t);
-		for (int i = 0;i < ROM.MODBYTES;i++)
-		{
-			t[i] = w[i + 7 * ROM.MODBYTES];
-		}
-		b = BIG.fromBytes(t);
-		d = new FP2(a,b);
-
-		f = new FP4(c,d);
-
-
-		for (int i = 0;i < ROM.MODBYTES;i++)
-		{
-			t[i] = w[i + 8 * ROM.MODBYTES];
-		}
-		a = BIG.fromBytes(t);
-		for (int i = 0;i < ROM.MODBYTES;i++)
-		{
-			t[i] = w[i + 9 * ROM.MODBYTES];
-		}
-		b = BIG.fromBytes(t);
-		c = new FP2(a,b);
-
-		for (int i = 0;i < ROM.MODBYTES;i++)
-		{
-			t[i] = w[i + 10 * ROM.MODBYTES];
-		}
-		a = BIG.fromBytes(t);
-		for (int i = 0;i < ROM.MODBYTES;i++)
-		{
-			t[i] = w[i + 11 * ROM.MODBYTES];
-		}
-		b = BIG.fromBytes(t);
-		d = new FP2(a,b);
-
-		g = new FP4(c,d);
-
-		return new FP12(e,f,g);
-	}
-
-/* convert this to byte array */
-	public void toBytes(sbyte[] w)
-	{
-		sbyte[] t = new sbyte[ROM.MODBYTES];
-		a.geta().A.toBytes(t);
-		for (int i = 0;i < ROM.MODBYTES;i++)
-		{
-			w[i] = t[i];
-		}
-		a.geta().B.toBytes(t);
-		for (int i = 0;i < ROM.MODBYTES;i++)
-		{
-			w[i + ROM.MODBYTES] = t[i];
-		}
-		a.getb().A.toBytes(t);
-		for (int i = 0;i < ROM.MODBYTES;i++)
-		{
-			w[i + 2 * ROM.MODBYTES] = t[i];
-		}
-		a.getb().B.toBytes(t);
-		for (int i = 0;i < ROM.MODBYTES;i++)
-		{
-			w[i + 3 * ROM.MODBYTES] = t[i];
-		}
-
-		b.geta().A.toBytes(t);
-		for (int i = 0;i < ROM.MODBYTES;i++)
-		{
-			w[i + 4 * ROM.MODBYTES] = t[i];
-		}
-		b.geta().B.toBytes(t);
-		for (int i = 0;i < ROM.MODBYTES;i++)
-		{
-			w[i + 5 * ROM.MODBYTES] = t[i];
-		}
-		b.getb().A.toBytes(t);
-		for (int i = 0;i < ROM.MODBYTES;i++)
-		{
-			w[i + 6 * ROM.MODBYTES] = t[i];
-		}
-		b.getb().B.toBytes(t);
-		for (int i = 0;i < ROM.MODBYTES;i++)
-		{
-			w[i + 7 * ROM.MODBYTES] = t[i];
-		}
-
-		c.geta().A.toBytes(t);
-		for (int i = 0;i < ROM.MODBYTES;i++)
-		{
-			w[i + 8 * ROM.MODBYTES] = t[i];
-		}
-		c.geta().B.toBytes(t);
-		for (int i = 0;i < ROM.MODBYTES;i++)
-		{
-			w[i + 9 * ROM.MODBYTES] = t[i];
-		}
-		c.getb().A.toBytes(t);
-		for (int i = 0;i < ROM.MODBYTES;i++)
-		{
-			w[i + 10 * ROM.MODBYTES] = t[i];
-		}
-		c.getb().B.toBytes(t);
-		for (int i = 0;i < ROM.MODBYTES;i++)
-		{
-			w[i + 11 * ROM.MODBYTES] = t[i];
-		}
-	}
-
-/* convert to hex string */
-	public override string ToString()
-	{
-		return ("[" + a.ToString() + "," + b.ToString() + "," + c.ToString() + "]");
-	}
-
-/* this=this^e */
-	public FP12 pow(BIG e)
-	{
-		norm();
-		e.norm();
-		FP12 w = new FP12(this);
-		BIG z = new BIG(e);
-		FP12 r = new FP12(1);
-
-		while (true)
-		{
-			int bt = z.parity();
-			z.fshr(1);
-			if (bt == 1)
-			{
-				r.mul(w);
-			}
-			if (z.iszilch())
-			{
-				break;
-			}
-			w.usqr();
-		}
-		r.reduce();
-		return r;
-	}
-
-/* constant time powering by small integer of max length bts */
-	public void pinpow(int e, int bts)
-	{
-		int i, b;
-		FP12[] R = new FP12[2];
-		R[0] = new FP12(1);
-		R[1] = new FP12(this);
-		for (i = bts - 1;i >= 0;i--)
-		{
-			b = (e >> i) & 1;
-			R[1 - b].mul(R[b]);
-			R[b].usqr();
-		}
-		this.copy(R[0]);
-	}
-
-/* p=q0^u0.q1^u1.q2^u2.q3^u3 */
-/* Timing attack secure, but not cache attack secure */
-
-	public static FP12 pow4(FP12[] q, BIG[] u)
-	{
-		int i, j, nb, m;
-		int[] a = new int[4];
-		FP12[] g = new FP12[8];
-		FP12[] s = new FP12[2];
-		FP12 c = new FP12(1);
-		FP12 p = new FP12(0);
-		BIG[] t = new BIG[4];
-		BIG mt = new BIG(0);
-		sbyte[] w = new sbyte[ROM.NLEN * ROM.BASEBITS + 1];
-
-		for (i = 0;i < 4;i++)
-		{
-			t[i] = new BIG(u[i]);
-		}
-
-		s[0] = new FP12(0);
-		s[1] = new FP12(0);
-
-		g[0] = new FP12(q[0]);
-		s[0].copy(q[1]);
-		s[0].conj();
-		g[0].mul(s[0]);
-		g[1] = new FP12(g[0]);
-		g[2] = new FP12(g[0]);
-		g[3] = new FP12(g[0]);
-		g[4] = new FP12(q[0]);
-		g[4].mul(q[1]);
-		g[5] = new FP12(g[4]);
-		g[6] = new FP12(g[4]);
-		g[7] = new FP12(g[4]);
-
-		s[1].copy(q[2]);
-		s[0].copy(q[3]);
-		s[0].conj();
-		s[1].mul(s[0]);
-		s[0].copy(s[1]);
-		s[0].conj();
-		g[1].mul(s[0]);
-		g[2].mul(s[1]);
-		g[5].mul(s[0]);
-		g[6].mul(s[1]);
-		s[1].copy(q[2]);
-		s[1].mul(q[3]);
-		s[0].copy(s[1]);
-		s[0].conj();
-		g[0].mul(s[0]);
-		g[3].mul(s[1]);
-		g[4].mul(s[0]);
-		g[7].mul(s[1]);
-
-/* if power is even add 1 to power, and add q to correction */
-
-		for (i = 0;i < 4;i++)
-		{
-			if (t[i].parity() == 0)
-			{
-				t[i].inc(1);
-				t[i].norm();
-				c.mul(q[i]);
-			}
-			mt.add(t[i]);
-			mt.norm();
-		}
-		c.conj();
-		nb = 1 + mt.nbits();
-
-/* convert exponent to signed 1-bit window */
-		for (j = 0;j < nb;j++)
-		{
-			for (i = 0;i < 4;i++)
-			{
-				a[i] = (t[i].lastbits(2) - 2);
-				t[i].dec(a[i]);
-				t[i].norm();
-				t[i].fshr(1);
-			}
-			w[j] = (sbyte)(8 * a[0] + 4 * a[1] + 2 * a[2] + a[3]);
-		}
-		w[nb] = (sbyte)(8 * t[0].lastbits(2) + 4 * t[1].lastbits(2) + 2 * t[2].lastbits(2) + t[3].lastbits(2));
-		p.copy(g[(w[nb] - 1) / 2]);
-
-		for (i = nb - 1;i >= 0;i--)
-		{
-			m = w[i] >> 7;
-			j = (w[i] ^ m) - m; // j=abs(w[i])
-			j = (j - 1) / 2;
-			s[0].copy(g[j]);
-			s[1].copy(g[j]);
-			s[1].conj();
-			p.usqr();
-			p.mul(s[m & 1]);
-		}
-		p.mul(c); // apply correction
-		p.reduce();
-		return p;
-	}
-
-/*
-	public static void main(String[] args) {
-		BIG p=new BIG(ROM.Modulus);
-		FP2 w0,w1;
-		BIG a=new BIG(0);
-		BIG b=new BIG(0);
-
-		a.zero(); b.zero(); a.inc(1); b.inc(2);
-		w0=new FP2(a,b);
-		a.zero(); b.zero(); a.inc(3); b.inc(4);
-		w1=new FP2(a,b);
-		FP4 t0=new FP4(w0,w1);
-
-		a.zero(); b.zero(); a.inc(5); b.inc(6);
-		w0=new FP2(a,b);
-		a.zero(); b.zero(); a.inc(7); b.inc(8);
-		w1=new FP2(a,b);
-		FP4 t1=new FP4(w0,w1);
-
-		a.zero(); b.zero(); a.inc(9); b.inc(10);
-		w0=new FP2(a,b);
-		a.zero(); b.zero(); a.inc(11); b.inc(12);
-		w1=new FP2(a,b);
-		FP4 t2=new FP4(w0,w1);
-
-		FP12 w=new FP12(t0,t1,t2);
-		FP12 t=new FP12(w);
-
-		System.out.println("w= "+w.toString());
-
-		a=new BIG(ROM.CURVE_Fra);
-		b=new BIG(ROM.CURVE_Frb);
-
-		FP2 f=new FP2(a,b);
-
-		w.frob(f);
-		System.out.println("w= "+w.toString());
-
-		w=t.pow(p);
-
-		System.out.println("w= "+w.toString());
-
-		w.inverse();
-
-		System.out.println("1/w= "+w.toString());
-
-		w.inverse();
-
-		System.out.println("w= "+w.toString());
-
-		t.copy(w);
-		w.conj();
-		t.inverse();
-		w.mul(t);
-
-		System.out.println("w^(p^6-1)= "+w.toString());
-
-		t.copy(w);
-		w.frob(f);
-		w.frob(f);
-		w.mul(t);
-
-		System.out.println("w^(p^6-1)(p^2+1)= "+w.toString());
-
-		t.copy(w);
-
-		t.inverse();
-		w.conj();
-
-		System.out.println("w= "+w.toString());
-		System.out.println("t= "+t.toString());
-	} */
-}
diff --git a/cs/FP2.cs b/cs/FP2.cs
deleted file mode 100644
index f5c8d16..0000000
--- a/cs/FP2.cs
+++ /dev/null
@@ -1,428 +0,0 @@
-/*
-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.
-*/
-
-/* Finite Field arithmetic  Fp^2 functions */
-
-/* FP2 elements are of the form a+ib, where i is sqrt(-1) */
-
-public sealed class FP2
-{
-	private readonly FP a;
-	private readonly FP b;
-
-/* reduce components mod Modulus */
-	public void reduce()
-	{
-		a.reduce();
-		b.reduce();
-	}
-
-/* normalise components of w */
-	public void norm()
-	{
-		a.norm();
-		b.norm();
-	}
-
-/* test this=0 ? */
-	public bool iszilch()
-	{
-		reduce();
-		return (a.iszilch() && b.iszilch());
-	}
-
-	public void cmove(FP2 g, int d)
-	{
-		a.cmove(g.a,d);
-		b.cmove(g.b,d);
-	}
-
-/* test this=1 ? */
-	public bool isunity()
-	{
-		FP one = new FP(1);
-		return (a.Equals(one) && b.iszilch());
-	}
-
-/* test this=x */
-	public bool Equals(FP2 x)
-	{
-		return (a.Equals(x.a) && b.Equals(x.b));
-	}
-
-/* Constructors */
-	public FP2(int c)
-	{
-		a = new FP(c);
-		b = new FP(0);
-	}
-
-	public FP2(FP2 x)
-	{
-		a = new FP(x.a);
-		b = new FP(x.b);
-	}
-
-	public FP2(FP c, FP d)
-	{
-		a = new FP(c);
-		b = new FP(d);
-	}
-
-	public FP2(BIG c, BIG d)
-	{
-		a = new FP(c);
-		b = new FP(d);
-	}
-
-	public FP2(FP c)
-	{
-		a = new FP(c);
-		b = new FP(0);
-	}
-
-	public FP2(BIG c)
-	{
-		a = new FP(c);
-		b = new FP(0);
-	}
-
-/* extract a */
-	public BIG A
-	{
-		get
-		{
-			return a.redc();
-		}
-	}
-
-/* extract b */
-	public BIG B
-	{
-		get
-		{
-			return b.redc();
-		}
-	}
-
-/* copy this=x */
-	public void copy(FP2 x)
-	{
-		a.copy(x.a);
-		b.copy(x.b);
-	}
-
-/* set this=0 */
-	public void zero()
-	{
-		a.zero();
-		b.zero();
-	}
-
-/* set this=1 */
-	public void one()
-	{
-		a.one();
-		b.zero();
-	}
-
-/* negate this mod Modulus */
-	public void neg()
-	{
-		norm();
-		FP m = new FP(a);
-		FP t = new FP(0);
-
-		m.add(b);
-		m.neg();
-		m.norm();
-		t.copy(m);
-		t.add(b);
-		b.copy(m);
-		b.add(a);
-		a.copy(t);
-	}
-
-/* set to a-ib */
-	public void conj()
-	{
-		b.neg();
-	}
-
-/* this+=a */
-	public void add(FP2 x)
-	{
-		a.add(x.a);
-		b.add(x.b);
-	}
-
-/* this-=a */
-	public void sub(FP2 x)
-	{
-		FP2 m = new FP2(x);
-		m.neg();
-		add(m);
-	}
-
-/* this*=s, where s is an FP */
-	public void pmul(FP s)
-	{
-		a.mul(s);
-		b.mul(s);
-	}
-
-/* this*=i, where i is an int */
-	public void imul(int c)
-	{
-		a.imul(c);
-		b.imul(c);
-	}
-
-/* this*=this */
-	public void sqr()
-	{
-		norm();
-		FP w1 = new FP(a);
-		FP w3 = new FP(a);
-		FP mb = new FP(b);
-
-		w3.mul(b);
-		w1.add(b);
-		mb.neg();
-		a.add(mb);
-		a.mul(w1);
-		b.copy(w3);
-		b.add(w3);
-//		reduce();
-		norm();
-	}
-
-/* this*=y */
-	public void mul(FP2 y)
-	{
-		norm(); // This is needed here as {a,b} is not normed before additions
-
-		FP w1 = new FP(a);
-		FP w2 = new FP(b);
-		FP w5 = new FP(a);
-		FP mw = new FP(0);
-
-		w1.mul(y.a); // w1=a*y.a  - this norms w1 and y.a, NOT a
-		w2.mul(y.b); // w2=b*y.b  - this norms w2 and y.b, NOT b
-		w5.add(b); // w5=a+b
-		b.copy(y.a);
-		b.add(y.b); // b=y.a+y.b
-
-		b.mul(w5);
-		mw.copy(w1);
-		mw.add(w2);
-		mw.neg();
-
-		b.add(mw);
-		mw.add(w1);
-		a.copy(w1);
-		a.add(mw);
-
-//		reduce();
-		norm();
-	}
-
-
-/* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */
-/* returns true if this is QR */
-	public bool sqrt()
-	{
-		if (iszilch())
-		{
-			return true;
-		}
-		FP w1 = new FP(b);
-		FP w2 = new FP(a);
-		w1.sqr();
-		w2.sqr();
-		w1.add(w2);
-		if (w1.jacobi() != 1)
-		{
-			zero();
-			return false;
-		}
-		w1 = w1.sqrt();
-		w2.copy(a);
-		w2.add(w1);
-		w2.div2();
-		if (w2.jacobi() != 1)
-		{
-			w2.copy(a);
-			w2.sub(w1);
-			w2.div2();
-			if (w2.jacobi() != 1)
-			{
-				zero();
-				return false;
-			}
-		}
-		w2 = w2.sqrt();
-		a.copy(w2);
-		w2.add(w2);
-		w2.inverse();
-		b.mul(w2);
-		return true;
-	}
-
-/* output to hex string */
-	public override string ToString()
-	{
-		return ("[" + a.ToString() + "," + b.ToString() + "]");
-	}
-
-	public string toRawString()
-	{
-		return ("[" + a.toRawString() + "," + b.toRawString() + "]");
-	}
-
-/* this=1/this */
-	public void inverse()
-	{
-		norm();
-		FP w1 = new FP(a);
-		FP w2 = new FP(b);
-
-		w1.sqr();
-		w2.sqr();
-		w1.add(w2);
-		w1.inverse();
-		a.mul(w1);
-		w1.neg();
-		b.mul(w1);
-	}
-
-/* this/=2 */
-	public void div2()
-	{
-		a.div2();
-		b.div2();
-	}
-
-/* this*=sqrt(-1) */
-	public void times_i()
-	{
-	//	a.norm();
-		FP z = new FP(a);
-		a.copy(b);
-		a.neg();
-		b.copy(z);
-	}
-
-/* w*=(1+sqrt(-1)) */
-/* where X*2-(1+sqrt(-1)) is irreducible for FP4, assumes p=3 mod 8 */
-	public void mul_ip()
-	{
-		norm();
-		FP2 t = new FP2(this);
-		FP z = new FP(a);
-		a.copy(b);
-		a.neg();
-		b.copy(z);
-		add(t);
-		norm();
-	}
-
-/* w/=(1+sqrt(-1)) */
-	public void div_ip()
-	{
-		FP2 t = new FP2(0);
-		norm();
-		t.a.copy(a);
-		t.a.add(b);
-		t.b.copy(b);
-		t.b.sub(a);
-		copy(t);
-		div2();
-	}
-/*
-	public FP2 pow(BIG e)
-	{
-		int bt;
-		FP2 r=new FP2(1);
-		e.norm();
-		norm();
-		while (true)
-		{
-			bt=e.parity();
-			e.fshr(1);
-			if (bt==1) r.mul(this);
-			if (e.iszilch()) break;
-			sqr();
-		}
-
-		r.reduce();
-		return r;
-	}
-
-	public static void main(String[] args) {
-		BIG m=new BIG(ROM.Modulus);
-		BIG x=new BIG(3);
-		BIG e=new BIG(27);
-		BIG pp1=new BIG(m);
-		BIG pm1=new BIG(m);
-		BIG a=new BIG(1);
-		BIG b=new BIG(1);
-		FP2 w=new FP2(a,b);
-		FP2 z=new FP2(w);
-
-		byte[] RAW=new byte[100];
-
-		RAND rng=new RAND();
-		for (int i=0;i<100;i++) RAW[i]=(byte)(i);
-
-		rng.seed(100,RAW);
-
-	//	for (int i=0;i<100;i++)
-	//	{
-			a.randomnum(rng);
-			b.randomnum(rng);
-
-			w=new FP2(a,b);
-			System.out.println("w="+w.toString());
-
-			z=new FP2(w);
-			z.inverse();
-			System.out.println("z="+z.toString());
-
-			z.inverse();
-			if (!z.equals(w)) System.out.println("Error");
-	//	}
-
-//		System.out.println("m="+m.toString());
-//		w.sqr();
-//		w.mul(z);
-
-		System.out.println("w="+w.toString());
-
-
-		pp1.inc(1); pp1.norm();
-		pm1.dec(1); pm1.norm();
-		System.out.println("p+1="+pp1.toString());
-		System.out.println("p-1="+pm1.toString());
-		w=w.pow(pp1);
-		w=w.pow(pm1);
-		System.out.println("w="+w.toString());
-	}
-*/
-}
diff --git a/cs/FP4.cs b/cs/FP4.cs
deleted file mode 100644
index 317a07c..0000000
--- a/cs/FP4.cs
+++ /dev/null
@@ -1,633 +0,0 @@
-/*
-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.
-*/
-
-/* Finite Field arithmetic  Fp^4 functions */
-
-/* FP4 elements are of the form a+ib, where i is sqrt(-1+sqrt(-1))  */
-
-public sealed class FP4
-{
-	private readonly FP2 a;
-	private readonly FP2 b;
-/* reduce all components of this mod Modulus */
-	public void reduce()
-	{
-		a.reduce();
-		b.reduce();
-	}
-/* normalise all components of this mod Modulus */
-	public void norm()
-	{
-		a.norm();
-		b.norm();
-	}
-/* test this==0 ? */
-	public bool iszilch()
-	{
-		reduce();
-		return (a.iszilch() && b.iszilch());
-	}
-/* test this==1 ? */
-	public bool isunity()
-	{
-		FP2 one = new FP2(1);
-		return (a.Equals(one) && b.iszilch());
-	}
-
-/* test is w real? That is in a+ib test b is zero */
-	public bool isreal()
-	{
-		return b.iszilch();
-	}
-/* extract real part a */
-	public FP2 real()
-	{
-		return a;
-	}
-
-	public FP2 geta()
-	{
-		return a;
-	}
-/* extract imaginary part b */
-	public FP2 getb()
-	{
-		return b;
-	}
-/* test this=x? */
-	public bool Equals(FP4 x)
-	{
-		return (a.Equals(x.a) && b.Equals(x.b));
-	}
-/* constructors */
-	public FP4(int c)
-	{
-		a = new FP2(c);
-		b = new FP2(0);
-	}
-
-	public FP4(FP4 x)
-	{
-		a = new FP2(x.a);
-		b = new FP2(x.b);
-	}
-
-	public FP4(FP2 c, FP2 d)
-	{
-		a = new FP2(c);
-		b = new FP2(d);
-	}
-
-	public FP4(FP2 c)
-	{
-		a = new FP2(c);
-		b = new FP2(0);
-	}
-/* copy this=x */
-	public void copy(FP4 x)
-	{
-		a.copy(x.a);
-		b.copy(x.b);
-	}
-/* set this=0 */
-	public void zero()
-	{
-		a.zero();
-		b.zero();
-	}
-/* set this=1 */
-	public void one()
-	{
-		a.one();
-		b.zero();
-	}
-/* set this=-this */
-	public void neg()
-	{
-		FP2 m = new FP2(a);
-		FP2 t = new FP2(0);
-		m.add(b);
-		m.neg();
-		m.norm();
-		t.copy(m);
-		t.add(b);
-		b.copy(m);
-		b.add(a);
-		a.copy(t);
-	}
-/* this=conjugate(this) */
-	public void conj()
-	{
-		b.neg();
-		b.norm();
-	}
-/* this=-conjugate(this) */
-	public void nconj()
-	{
-		a.neg();
-		a.norm();
-	}
-/* this+=x */
-	public void add(FP4 x)
-	{
-		a.add(x.a);
-		b.add(x.b);
-	}
-/* this-=x */
-	public void sub(FP4 x)
-	{
-		FP4 m = new FP4(x);
-		m.neg();
-		add(m);
-	}
-
-/* this*=s where s is FP2 */
-	public void pmul(FP2 s)
-	{
-		a.mul(s);
-		b.mul(s);
-	}
-/* this*=c where c is int */
-	public void imul(int c)
-	{
-		a.imul(c);
-		b.imul(c);
-	}
-/* this*=this */
-	public void sqr()
-	{
-		norm();
-
-		FP2 t1 = new FP2(a);
-		FP2 t2 = new FP2(b);
-		FP2 t3 = new FP2(a);
-
-		t3.mul(b);
-		t1.add(b);
-		t2.mul_ip();
-
-		t2.add(a);
-		a.copy(t1);
-
-		a.mul(t2);
-
-		t2.copy(t3);
-		t2.mul_ip();
-		t2.add(t3);
-		t2.neg();
-		a.add(t2);
-
-		b.copy(t3);
-		b.add(t3);
-
-		norm();
-	}
-/* this*=y */
-	public void mul(FP4 y)
-	{
-		norm();
-
-		FP2 t1 = new FP2(a);
-		FP2 t2 = new FP2(b);
-		FP2 t3 = new FP2(0);
-		FP2 t4 = new FP2(b);
-
-		t1.mul(y.a);
-		t2.mul(y.b);
-		t3.copy(y.b);
-		t3.add(y.a);
-		t4.add(a);
-
-		t4.mul(t3);
-		t4.sub(t1);
-//		t4.norm();
-
-		b.copy(t4);
-		b.sub(t2);
-		t2.mul_ip();
-		a.copy(t2);
-		a.add(t1);
-
-		norm();
-	}
-/* convert this to hex string */
-	public override string ToString()
-	{
-		return ("[" + a.ToString() + "," + b.ToString() + "]");
-	}
-
-	public string toRawString()
-	{
-		return ("[" + a.toRawString() + "," + b.toRawString() + "]");
-	}
-
-/* this=1/this */
-	public void inverse()
-	{
-		norm();
-
-		FP2 t1 = new FP2(a);
-		FP2 t2 = new FP2(b);
-
-		t1.sqr();
-		t2.sqr();
-		t2.mul_ip();
-		t1.sub(t2);
-		t1.inverse();
-		a.mul(t1);
-		t1.neg();
-		b.mul(t1);
-	}
-
-
-/* this*=i where i = sqrt(-1+sqrt(-1)) */
-	public void times_i()
-	{
-		norm();
-		FP2 s = new FP2(b);
-		FP2 t = new FP2(b);
-		s.times_i();
-		t.add(s);
-//		t.norm();
-		b.copy(a);
-		a.copy(t);
-	}
-
-/* this=this^p using Frobenius */
-	public void frob(FP2 f)
-	{
-		a.conj();
-		b.conj();
-		b.mul(f);
-	}
-
-/* this=this^e */
-	public FP4 pow(BIG e)
-	{
-		norm();
-		e.norm();
-		FP4 w = new FP4(this);
-		BIG z = new BIG(e);
-		FP4 r = new FP4(1);
-		while (true)
-		{
-			int bt = z.parity();
-			z.fshr(1);
-			if (bt == 1)
-			{
-				r.mul(w);
-			}
-			if (z.iszilch())
-			{
-				break;
-			}
-			w.sqr();
-		}
-		r.reduce();
-		return r;
-	}
-/* XTR xtr_a function */
-	public void xtr_A(FP4 w, FP4 y, FP4 z)
-	{
-		FP4 r = new FP4(w);
-		FP4 t = new FP4(w);
-		r.sub(y);
-		r.pmul(a);
-		t.add(y);
-		t.pmul(b);
-		t.times_i();
-
-		copy(r);
-		add(t);
-		add(z);
-
-		norm();
-	}
-
-/* XTR xtr_d function */
-	public void xtr_D()
-	{
-		FP4 w = new FP4(this);
-		sqr();
-		w.conj();
-		w.add(w);
-		sub(w);
-		reduce();
-	}
-
-/* r=x^n using XTR method on traces of FP12s */
-	public FP4 xtr_pow(BIG n)
-	{
-		FP4 a = new FP4(3);
-		FP4 b = new FP4(this);
-		FP4 c = new FP4(b);
-		c.xtr_D();
-		FP4 t = new FP4(0);
-		FP4 r = new FP4(0);
-
-		n.norm();
-		int par = n.parity();
-		BIG v = new BIG(n);
-		v.fshr(1);
-		if (par == 0)
-		{
-			v.dec(1);
-			v.norm();
-		}
-
-		int nb = v.nbits();
-		for (int i = nb - 1;i >= 0;i--)
-		{
-			if (v.bit(i) != 1)
-			{
-				t.copy(b);
-				conj();
-				c.conj();
-				b.xtr_A(a,this,c);
-				conj();
-				c.copy(t);
-				c.xtr_D();
-				a.xtr_D();
-			}
-			else
-			{
-				t.copy(a);
-				t.conj();
-				a.copy(b);
-				a.xtr_D();
-				b.xtr_A(c,this,t);
-				c.xtr_D();
-			}
-		}
-		if (par == 0)
-		{
-			r.copy(c);
-		}
-		else
-		{
-			r.copy(b);
-		}
-		r.reduce();
-		return r;
-	}
-
-/* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */
-	public FP4 xtr_pow2(FP4 ck, FP4 ckml, FP4 ckm2l, BIG a, BIG b)
-	{
-		a.norm();
-		b.norm();
-		BIG e = new BIG(a);
-		BIG d = new BIG(b);
-		BIG w = new BIG(0);
-
-		FP4 cu = new FP4(ck); // can probably be passed in w/o copying
-		FP4 cv = new FP4(this);
-		FP4 cumv = new FP4(ckml);
-		FP4 cum2v = new FP4(ckm2l);
-		FP4 r = new FP4(0);
-		FP4 t = new FP4(0);
-
-		int f2 = 0;
-		while (d.parity() == 0 && e.parity() == 0)
-		{
-			d.fshr(1);
-			e.fshr(1);
-			f2++;
-		}
-
-		while (BIG.comp(d,e) != 0)
-		{
-			if (BIG.comp(d,e) > 0)
-			{
-				w.copy(e);
-				w.imul(4);
-				w.norm();
-				if (BIG.comp(d,w) <= 0)
-				{
-					w.copy(d);
-					d.copy(e);
-					e.rsub(w);
-					e.norm();
-
-					t.copy(cv);
-					t.xtr_A(cu,cumv,cum2v);
-					cum2v.copy(cumv);
-					cum2v.conj();
-					cumv.copy(cv);
-					cv.copy(cu);
-					cu.copy(t);
-
-				}
-				else if (d.parity() == 0)
-				{
-					d.fshr(1);
-					r.copy(cum2v);
-					r.conj();
-					t.copy(cumv);
-					t.xtr_A(cu,cv,r);
-					cum2v.copy(cumv);
-					cum2v.xtr_D();
-					cumv.copy(t);
-					cu.xtr_D();
-				}
-				else if (e.parity() == 1)
-				{
-					d.sub(e);
-					d.norm();
-					d.fshr(1);
-					t.copy(cv);
-					t.xtr_A(cu,cumv,cum2v);
-					cu.xtr_D();
-					cum2v.copy(cv);
-					cum2v.xtr_D();
-					cum2v.conj();
-					cv.copy(t);
-				}
-				else
-				{
-					w.copy(d);
-					d.copy(e);
-					d.fshr(1);
-					e.copy(w);
-					t.copy(cumv);
-					t.xtr_D();
-					cumv.copy(cum2v);
-					cumv.conj();
-					cum2v.copy(t);
-					cum2v.conj();
-					t.copy(cv);
-					t.xtr_D();
-					cv.copy(cu);
-					cu.copy(t);
-				}
-			}
-			if (BIG.comp(d,e) < 0)
-			{
-				w.copy(d);
-				w.imul(4);
-				w.norm();
-				if (BIG.comp(e,w) <= 0)
-				{
-					e.sub(d);
-					e.norm();
-					t.copy(cv);
-					t.xtr_A(cu,cumv,cum2v);
-					cum2v.copy(cumv);
-					cumv.copy(cu);
-					cu.copy(t);
-				}
-				else if (e.parity() == 0)
-				{
-					w.copy(d);
-					d.copy(e);
-					d.fshr(1);
-					e.copy(w);
-					t.copy(cumv);
-					t.xtr_D();
-					cumv.copy(cum2v);
-					cumv.conj();
-					cum2v.copy(t);
-					cum2v.conj();
-					t.copy(cv);
-					t.xtr_D();
-					cv.copy(cu);
-					cu.copy(t);
-				}
-				else if (d.parity() == 1)
-				{
-					w.copy(e);
-					e.copy(d);
-					w.sub(d);
-					w.norm();
-					d.copy(w);
-					d.fshr(1);
-					t.copy(cv);
-					t.xtr_A(cu,cumv,cum2v);
-					cumv.conj();
-					cum2v.copy(cu);
-					cum2v.xtr_D();
-					cum2v.conj();
-					cu.copy(cv);
-					cu.xtr_D();
-					cv.copy(t);
-				}
-				else
-				{
-					d.fshr(1);
-					r.copy(cum2v);
-					r.conj();
-					t.copy(cumv);
-					t.xtr_A(cu,cv,r);
-					cum2v.copy(cumv);
-					cum2v.xtr_D();
-					cumv.copy(t);
-					cu.xtr_D();
-				}
-			}
-		}
-		r.copy(cv);
-		r.xtr_A(cu,cumv,cum2v);
-		for (int i = 0;i < f2;i++)
-		{
-			r.xtr_D();
-		}
-		r = r.xtr_pow(d);
-		return r;
-	}
-
-/*
-
-	public static void main(String[] args) {
-		BIG m=new BIG(ROM.Modulus);
-		BIG e=new BIG(12);
-		BIG a=new BIG(0);
-		BIG b=new BIG(0);
-
-		a.inc(27); b.inc(45);
-
-		FP2 w0=new FP2(a,b);
-
-		a.zero(); b.zero();
-		a.inc(33); b.inc(54);
-
-		FP2 w1=new FP2(a,b);
-
-
-		FP4 w=new FP4(w0,w1);
-		FP4 t=new FP4(w);
-
-		a=new BIG(ROM.CURVE_Fra);
-		b=new BIG(ROM.CURVE_Frb);
-
-		FP2 f=new FP2(a,b);
-
-		System.out.println("w= "+w.toString());
-
-		w=w.pow(m);
-
-		System.out.println("w^p= "+w.toString());
-
-		t.frob(f);
-
-
-		System.out.println("w^p= "+t.toString());
-
-		w=w.pow(m);
-		w=w.pow(m);
-		w=w.pow(m);
-		System.out.println("w^p4= "+w.toString());
-
-
-	System.out.println("Test Inversion");
-
-		w=new FP4(w0,w1);
-
-		w.inverse();
-
-		System.out.println("1/w mod p^4 = "+w.toString());
-
-		w.inverse();
-
-		System.out.println("1/(1/w) mod p^4 = "+w.toString());
-
-		FP4 ww=new FP4(w);
-
-		w=w.xtr_pow(e);
-		System.out.println("w^e= "+w.toString());
-
-
-		a.zero(); b.zero();
-		a.inc(37); b.inc(17);
-		w0=new FP2(a,b);
-		a.zero(); b.zero();
-		a.inc(49); b.inc(31);
-		w1=new FP2(a,b);
-
-		FP4 c1=new FP4(w0,w1);
-		FP4 c2=new FP4(w0,w1);
-		FP4 c3=new FP4(w0,w1);
-
-		BIG e1=new BIG(3331);
-		BIG e2=new BIG(3372);
-
-		FP4 cr=w.xtr_pow2(c1,c2,c3,e1,e2);
-
-		System.out.println("c^e= "+cr.toString());
-	} */
-}
diff --git a/cs/GCM.cs b/cs/GCM.cs
deleted file mode 100644
index 5ddd706..0000000
--- a/cs/GCM.cs
+++ /dev/null
@@ -1,500 +0,0 @@
-/*
-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.
-*/
-
-
-
-/*
- * Implementation of the AES-GCM Encryption/Authentication
- *
- * Some restrictions..
- * 1. Only for use with AES
- * 2. Returned tag is always 128-bits. Truncate at your own risk.
- * 3. The order of function calls must follow some rules
- *
- * Typical sequence of calls..
- * 1. call GCM_init
- * 2. call GCM_add_header any number of times, as long as length of header is multiple of 16 bytes (block size)
- * 3. call GCM_add_header one last time with any length of header
- * 4. call GCM_add_cipher any number of times, as long as length of cipher/plaintext is multiple of 16 bytes
- * 5. call GCM_add_cipher one last time with any length of cipher/plaintext
- * 6. call GCM_finish to extract the tag.
- *
- * See http://www.mindspring.com/~dmcgrew/gcm-nist-6.pdf
- */
-
-public class GCM
-{
-	public const int NB = 4;
-	public const int GCM_ACCEPTING_HEADER = 0;
-	public const int GCM_ACCEPTING_CIPHER = 1;
-	public const int GCM_NOT_ACCEPTING_MORE = 2;
-	public const int GCM_FINISHED = 3;
-	public const int GCM_ENCRYPTING = 0;
-	public const int GCM_DECRYPTING = 1;
-
-//JAVA TO C# CONVERTER NOTE: The following call to the 'RectangularArrays' helper class reproduces the rectangular array initialization that is automatic in Java:
-//ORIGINAL LINE: private int[][] table = new int[128][4]; // 2k bytes
-	private int[][] table = RectangularArrays.ReturnRectangularIntArray(128, 4); // 2k bytes
-	private sbyte[] stateX = new sbyte[16];
-	private sbyte[] Y_0 = new sbyte[16];
-	private int counter;
-	private int[] lenA = new int[2];
-	private int[] lenC = new int[2];
-	private int status;
-	private AES a = new AES();
-
-	private static int pack(sbyte[] b)
-	{ // pack bytes into a 32-bit Word
-		return ((((int)b[0]) & 0xff) << 24) | (((int)b[1] & 0xff) << 16) | (((int)b[2] & 0xff) << 8) | ((int)b[3] & 0xff);
-	}
-
-	private static sbyte[] unpack(int a)
-	{ // unpack bytes from a word
-		sbyte[] b = new sbyte[4];
-		b[3] = (sbyte)(a);
-		b[2] = (sbyte)((int)((uint)a >> 8));
-		b[1] = (sbyte)((int)((uint)a >> 16));
-		b[0] = (sbyte)((int)((uint)a >> 24));
-		return b;
-	}
-
-	private void precompute(sbyte[] H)
-	{
-		int i, j, c;
-		sbyte[] b = new sbyte[4];
-
-		for (i = j = 0;i < NB;i++,j += 4)
-		{
-			b[0] = H[j];
-			b[1] = H[j + 1];
-			b[2] = H[j + 2];
-			b[3] = H[j + 3];
-			table[0][i] = pack(b);
-		}
-		for (i = 1;i < 128;i++)
-		{
-			c = 0;
-			for (j = 0;j < NB;j++)
-			{
-				table[i][j] = c | (int)((uint)(table[i - 1][j]) >> 1);
-				c = table[i - 1][j] << 31;
-			}
-			if (c != 0)
-			{
-				table[i][0] ^= unchecked((int)0xE1000000); // irreducible polynomial
-			}
-		}
-	}
-
-	private void gf2mul()
-	{ // gf2m mul - Z=H*X mod 2^128
-		int i, j, m, k;
-		int[] P = new int[4];
-		int c;
-		sbyte[] b; //=new byte[4];
-
-		P[0] = P[1] = P[2] = P[3] = 0;
-		j = 8;
-		m = 0;
-		for (i = 0;i < 128;i++)
-		{
-			c = ((int)((uint)stateX[m] >> (--j))) & 1;
-			if (c != 0)
-			{
-				for (k = 0;k < NB;k++)
-				{
-					P[k] ^= table[i][k];
-				}
-			}
-			if (j == 0)
-			{
-				j = 8;
-				m++;
-				if (m == 16)
-				{
-					break;
-				}
-			}
-		}
-		for (i = j = 0;i < NB;i++,j += 4)
-		{
-			b = unpack(P[i]);
-			stateX[j] = b[0];
-			stateX[j + 1] = b[1];
-			stateX[j + 2] = b[2];
-			stateX[j + 3] = b[3];
-		}
-	}
-
-	private void wrap()
-	{ // Finish off GHASH
-		int i, j;
-		int[] F = new int[4];
-		sbyte[] L = new sbyte[16];
-		sbyte[] b; //=new byte[4];
-
-/* convert lengths from bytes to bits */
-		F[0] = (lenA[0] << 3) | (int)((uint)(lenA[1] & 0xE0000000)>>29);
-		F[1] = lenA[1] << 3;
-		F[2] = (lenC[0] << 3) | (int)((uint)(lenC[1] & 0xE0000000)>>29);
-		F[3] = lenC[1] << 3;
-		for (i = j = 0;i < NB;i++,j += 4)
-		{
-			b = unpack(F[i]);
-			L[j] = b[0];
-			L[j + 1] = b[1];
-			L[j + 2] = b[2];
-			L[j + 3] = b[3];
-		}
-		for (i = 0;i < 16;i++)
-		{
-			stateX[i] ^= L[i];
-		}
-		gf2mul();
-	}
-
-/* Initialize GCM mode */
-	public virtual void init(sbyte[] key, int niv, sbyte[] iv)
-	{ // iv size niv is usually 12 bytes (96 bits). AES key size nk can be 16,24 or 32 bytes
-		int i;
-		sbyte[] H = new sbyte[16];
-		sbyte[] b; //=new byte[4];
-
-		for (i = 0;i < 16;i++)
-		{
-			H[i] = 0;
-			stateX[i] = 0;
-		}
-
-		a.init(AES.ECB,key,iv);
-		a.ecb_encrypt(H); // E(K,0)
-		precompute(H);
-
-		lenA[0] = lenC[0] = lenA[1] = lenC[1] = 0;
-		if (niv == 12)
-		{
-			for (i = 0;i < 12;i++)
-			{
-				a.f[i] = iv[i];
-			}
-			b = unpack((int)1);
-			a.f[12] = b[0];
-			a.f[13] = b[1];
-			a.f[14] = b[2];
-			a.f[15] = b[3]; // initialise IV
-			for (i = 0;i < 16;i++)
-			{
-				Y_0[i] = a.f[i];
-			}
-		}
-		else
-		{
-			status = GCM_ACCEPTING_CIPHER;
-			ghash(iv,niv); // GHASH(H,0,IV)
-			wrap();
-			for (i = 0;i < 16;i++)
-			{
-				a.f[i] = stateX[i];
-				Y_0[i] = a.f[i];
-				stateX[i] = 0;
-			}
-			lenA[0] = lenC[0] = lenA[1] = lenC[1] = 0;
-		}
-		status = GCM_ACCEPTING_HEADER;
-	}
-
-/* Add Header data - included but not encrypted */
-	public virtual bool add_header(sbyte[] header, int len)
-	{ // Add some header. Won't be encrypted, but will be authenticated. len is length of header
-		int i , j = 0;
-		if (status != GCM_ACCEPTING_HEADER)
-		{
-			return false;
-		}
-
-		while (j < len)
-		{
-			for (i = 0;i < 16 && j < len;i++)
-			{
-				stateX[i] ^= header[j++];
-				lenA[1]++;
-				if (lenA[1] == 0)
-				{
-					lenA[0]++;
-				}
-			}
-			gf2mul();
-		}
-		if (len % 16 != 0)
-		{
-			status = GCM_ACCEPTING_CIPHER;
-		}
-		return true;
-	}
-
-	private bool ghash(sbyte[] plain, int len)
-	{
-		int i , j = 0;
-		int counter;
-	//	byte[] B=new byte[16];
-	//	byte[] b=new byte[4];
-
-		if (status == GCM_ACCEPTING_HEADER)
-		{
-			status = GCM_ACCEPTING_CIPHER;
-		}
-		if (status != GCM_ACCEPTING_CIPHER)
-		{
-			return false;
-		}
-
-		while (j < len)
-		{
-			for (i = 0;i < 16 && j < len;i++)
-			{
-				stateX[i] ^= plain[j++];
-				lenC[1]++;
-				if (lenC[1] == 0)
-				{
-					lenC[0]++;
-				}
-			}
-			gf2mul();
-		}
-		if (len % 16 != 0)
-		{
-			status = GCM_NOT_ACCEPTING_MORE;
-		}
-		return true;
-	}
-
-/* Add Plaintext - included and encrypted */
-	public virtual sbyte[] add_plain(sbyte[] plain, int len)
-	{
-		int i , j = 0;
-		int counter;
-		sbyte[] B = new sbyte[16];
-		sbyte[] b = new sbyte[4];
-		sbyte[] cipher = new sbyte[len];
-
-		if (status == GCM_ACCEPTING_HEADER)
-		{
-			status = GCM_ACCEPTING_CIPHER;
-		}
-		if (status != GCM_ACCEPTING_CIPHER)
-		{
-			return new sbyte[0];
-		}
-
-		while (j < len)
-		{
-
-			b[0] = a.f[12];
-			b[1] = a.f[13];
-			b[2] = a.f[14];
-			b[3] = a.f[15];
-			counter = pack(b);
-			counter++;
-			b = unpack(counter);
-			a.f[12] = b[0];
-			a.f[13] = b[1];
-			a.f[14] = b[2];
-			a.f[15] = b[3]; // increment counter
-			for (i = 0;i < 16;i++)
-			{
-				B[i] = a.f[i];
-			}
-			a.ecb_encrypt(B); // encrypt it
-
-			for (i = 0;i < 16 && j < len;i++)
-			{
-				cipher[j] = (sbyte)(plain[j] ^ B[i]);
-				stateX[i] ^= cipher[j++];
-				lenC[1]++;
-				if (lenC[1] == 0)
-				{
-					lenC[0]++;
-				}
-			}
-			gf2mul();
-		}
-		if (len % 16 != 0)
-		{
-			status = GCM_NOT_ACCEPTING_MORE;
-		}
-		return cipher;
-	}
-
-/* Add Ciphertext - decrypts to plaintext */
-	public virtual sbyte[] add_cipher(sbyte[] cipher, int len)
-	{
-		int i , j = 0;
-		int counter;
-		sbyte[] B = new sbyte[16];
-		sbyte[] b = new sbyte[4];
-		sbyte[] plain = new sbyte[len];
-
-		if (status == GCM_ACCEPTING_HEADER)
-		{
-			status = GCM_ACCEPTING_CIPHER;
-		}
-		if (status != GCM_ACCEPTING_CIPHER)
-		{
-			return new sbyte[0];
-		}
-
-		while (j < len)
-		{
-
-			b[0] = a.f[12];
-			b[1] = a.f[13];
-			b[2] = a.f[14];
-			b[3] = a.f[15];
-			counter = pack(b);
-			counter++;
-			b = unpack(counter);
-			a.f[12] = b[0];
-			a.f[13] = b[1];
-			a.f[14] = b[2];
-			a.f[15] = b[3]; // increment counter
-			for (i = 0;i < 16;i++)
-			{
-				B[i] = a.f[i];
-			}
-			a.ecb_encrypt(B); // encrypt it
-			for (i = 0;i < 16 && j < len;i++)
-			{
-				plain[j] = (sbyte)(cipher[j] ^ B[i]);
-				stateX[i] ^= cipher[j++];
-				lenC[1]++;
-				if (lenC[1] == 0)
-				{
-					lenC[0]++;
-				}
-			}
-			gf2mul();
-		}
-		if (len % 16 != 0)
-		{
-			status = GCM_NOT_ACCEPTING_MORE;
-		}
-		return plain;
-	}
-
-/* Finish and extract Tag */
-	public virtual sbyte[] finish(bool extract)
-	{ // Finish off GHASH and extract tag (MAC)
-		int i;
-		sbyte[] tag = new sbyte[16];
-
-		wrap();
-/* extract tag */
-		if (extract)
-		{
-			a.ecb_encrypt(Y_0); // E(K,Y0)
-			for (i = 0;i < 16;i++)
-			{
-				Y_0[i] ^= stateX[i];
-			}
-			for (i = 0;i < 16;i++)
-			{
-				tag[i] = Y_0[i];
-				Y_0[i] = stateX[i] = 0;
-			}
-		}
-		status = GCM_FINISHED;
-		a.end();
-		return tag;
-	}
-
-	public static sbyte[] hex2bytes(string s)
-	{
-		int len = s.Length;
-		sbyte[] data = new sbyte[len / 2];
-		for (int i = 0; i < len; i += 2)
-		{
-			data[i / 2] = (sbyte)((char.digit(s[i], 16) << 4) + char.digit(s[i + 1], 16));
-		}
-		return data;
-	}
-
-/*
-	public static void main(String[] args) {
-		int i;
-
-		String KT="feffe9928665731c6d6a8f9467308308";
-		String MT="d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39";
-		String HT="feedfacedeadbeeffeedfacedeadbeefabaddad2";
-//	char* NT="cafebabefacedbaddecaf888";
-// Tag should be 5bc94fbc3221a5db94fae95ae7121a47
-		String NT="9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b";
-// Tag should be 619cc5aefffe0bfa462af43c1699d050
-
-
-		byte[] T=new byte[16];   // Tag
-		byte[] K=new byte[16];   // AES Key
-		byte[] H=new byte[64];   // Header - to be included in Authentication, but not encrypted
-		byte[] N=new byte[100];   // IV - Initialisation vector
-		byte[] M=new byte[100];  // Plaintext to be encrypted/authenticated
-		byte[] C=new byte[100];  // Ciphertext
-		byte[] P=new byte[100];  // Recovered Plaintext
-
-		GCM g=new GCM();
-
-		M=hex2bytes(MT);
-		H=hex2bytes(HT);
-		N=hex2bytes(NT);
-		K=hex2bytes(KT);
-
-		int len=M.length;
-		int lenH=H.length;
-		int lenK=K.length;
-		int lenIV=N.length;
-
- 		System.out.format("Plaintext=\n");
-		for (i=0;i<len;i++) System.out.format("%02x",M[i]);
-		System.out.format("\n");
-
-		g.init(K,lenIV,N);
-		g.add_header(H,lenH);
-		C=g.add_plain(M,len);
-		T=g.finish(true);
-
-		System.out.format("Ciphertext=\n");
-		for (i=0;i<len;i++) System.out.format("%02x",C[i]);
-		System.out.format("\n");
-
-		System.out.format("Tag=\n");
-		for (i=0;i<16;i++) System.out.format("%02x",T[i]);
-		System.out.format("\n");
-
-		g.init(K,lenIV,N);
-		g.add_header(H,lenH);
-		P=g.add_cipher(C,len);
-		T=g.finish(true);
-
- 		System.out.format("Plaintext=\n");
-		for (i=0;i<len;i++) System.out.format("%02x",P[i]);
-		System.out.format("\n");
-
-		System.out.format("Tag=\n");
-		for (i=0;i<16;i++) System.out.format("%02x",T[i]);
-		System.out.format("\n");
-	} */
-}
diff --git a/cs/HASH.cs b/cs/HASH.cs
deleted file mode 100644
index 50d4427..0000000
--- a/cs/HASH.cs
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
-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.
-*/
-
-/*
- * Implementation of the Secure Hashing Algorithm (SHA-256)
- *
- * Generates a 256 bit message digest. It should be impossible to come
- * come up with two messages that hash to the same value ("collision free").
- *
- * For use with byte-oriented messages only.
- */
-
-public class HASH
-{
-	private int[] length = new int[2];
-	private int[] h = new int[8];
-	private int[] w = new int[64];
-
-	public const int H0 = 0x6A09E667;
-	public const int H1 = unchecked((int)0xBB67AE85);
-	public const int H2 = 0x3C6EF372;
-	public const int H3 = unchecked((int)0xA54FF53A);
-	public const int H4 = 0x510E527F;
-	public const int H5 = unchecked((int)0x9B05688C);
-	public const int H6 = 0x1F83D9AB;
-	public const int H7 = 0x5BE0CD19;
-
-	public const int len = 32;
-
-	public static readonly int[] K = new int[] {0x428a2f98, 0x71374491, unchecked((int)0xb5c0fbcf), unchecked((int)0xe9b5dba5), 0x3956c25b, 0x59f111f1, unchecked((int)0x923f82a4), unchecked((int)0xab1c5ed5), unchecked((int)0xd807aa98), 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, unchecked((int)0x80deb1fe), unchecked((int)0x9bdc06a7), unchecked((int)0xc19bf174), unchecked((int)0xe49b69c1), unchecked((int)0xefbe4786), 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, unchecked((int)0x983e5152), unchecked((int)0xa831c66d), unchecked((int)0xb00327c8), unchecked((int)0xbf597fc7), unchecked((int)0xc6e00bf3), unchecked((int)0xd5a79147), 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, unchecked((int)0x81c2c92e), unchecked((int)0x92722c85), unchecked((int)0xa2bfe8a1), unchecked((int)0xa81a664b), unchecked((int)0xc24b8b70), unchecked((int)0xc76c51a3), unchecked((int)0xd192e819), unchecked((int)0xd6990624), unchecked((int)0xf40e3585), 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, unchecked((int)0x84c87814), unchecked((int)0x8cc70208), unchecked((int)0x90befffa), unchecked((int)0xa4506ceb), unchecked((int)0xbef9a3f7), unchecked((int)0xc67178f2)};
-
-
-/* functions */
-	private static int S(int n, int x)
-	{
-		return (((int)((uint)(x) >> n)) | ((x) << (32 - n)));
-	}
-
-	private static int R(int n, int x)
-	{
-		return ((int)((uint)(x) >> n));
-	}
-
-	private static int Ch(int x, int y, int z)
-	{
-		return ((x & y) ^ (~(x) & z));
-	}
-
-	private static int Maj(int x, int y, int z)
-	{
-		return ((x & y) ^ (x & z) ^ (y & z));
-	}
-
-	private static int Sig0(int x)
-	{
-		return (S(2,x) ^ S(13,x) ^ S(22,x));
-	}
-
-	private static int Sig1(int x)
-	{
-		return (S(6,x) ^ S(11,x) ^ S(25,x));
-	}
-
-	private static int theta0(int x)
-	{
-		return (S(7,x) ^ S(18,x) ^ R(3,x));
-	}
-
-	private static int theta1(int x)
-	{
-		return (S(17,x) ^ S(19,x) ^ R(10,x));
-	}
-
-
-	private void transform()
-	{ // basic transformation step
-		int a, b, c, d, e, f, g, hh, t1, t2;
-		int j;
-		for (j = 16;j < 64;j++)
-		{
-			w[j] = theta1(w[j - 2]) + w[j - 7] + theta0(w[j - 15]) + w[j - 16];
-		}
-		a = h[0];
-		b = h[1];
-		c = h[2];
-		d = h[3];
-		e = h[4];
-		f = h[5];
-		g = h[6];
-		hh = h[7];
-
-		for (j = 0;j < 64;j++)
-		{ // 64 times - mush it up
-			t1 = hh + Sig1(e) + Ch(e,f,g) + K[j] + w[j];
-			t2 = Sig0(a) + Maj(a,b,c);
-			hh = g;
-			g = f;
-			f = e;
-			e = d + t1;
-			d = c;
-			c = b;
-			b = a;
-			a = t1 + t2;
-
-		}
-		h[0] += a;
-		h[1] += b;
-		h[2] += c;
-		h[3] += d;
-		h[4] += e;
-		h[5] += f;
-		h[6] += g;
-		h[7] += hh;
-	}
-
-/* Initialise Hash function */
-	public virtual void init()
-	{ // initialise
-		int i;
-		for (i = 0;i < 64;i++)
-		{
-			w[i] = 0;
-		}
-		length[0] = length[1] = 0;
-		h[0] = H0;
-		h[1] = H1;
-		h[2] = H2;
-		h[3] = H3;
-		h[4] = H4;
-		h[5] = H5;
-		h[6] = H6;
-		h[7] = H7;
-	}
-
-/* Constructor */
-	public HASH()
-	{
-		init();
-	}
-
-/* process a single byte */
-	public virtual void process(int byt)
-	{ // process the next message byte
-		int cnt;
-		cnt = (length[0] / 32) % 16;
-
-		w[cnt] <<= 8;
-		w[cnt] |= (byt & 0xFF);
-		length[0] += 8;
-		if (length[0] == 0)
-		{
-			length[1]++;
-			length[0] = 0;
-		}
-		if ((length[0] % 512) == 0)
-		{
-			transform();
-		}
-	}
-
-/* process an array of bytes */
-	public virtual void process_array(sbyte[] b)
-	{
-		for (int i = 0;i < b.Length;i++)
-		{
-			process((int)b[i]);
-		}
-	}
-
-/* process a 32-bit integer */
-	public virtual void process_num(int n)
-	{
-		process((n >> 24) & 0xff);
-		process((n >> 16) & 0xff);
-		process((n >> 8) & 0xff);
-		process(n & 0xff);
-	}
-
-/* Generate 32-byte Hash */
-	public virtual sbyte[] hash()
-	{ // pad message and finish - supply digest
-		int i;
-		sbyte[] digest = new sbyte[32];
-		int len0, len1;
-		len0 = length[0];
-		len1 = length[1];
-		process(0x80);
-		while ((length[0] % 512) != 448)
-		{
-			process(0);
-		}
-		w[14] = len1;
-		w[15] = len0;
-		transform();
-		for (i = 0;i < len;i++)
-		{ // convert to bytes
-			digest[i] = unchecked((sbyte)((h[i / 4] >> (8 * (3 - i % 4))) & 0xff));
-		}
-		init();
-		return digest;
-	}
-
-/* test program: should produce digest */
-
-//248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1
-/*
-	public static void main(String[] args) {
-		byte[] test="abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq".getBytes();
-		byte[] digest;
-		int i;
-		HASH sh=new HASH();
-
-		for (i=0;i<test.length;i++)
-			sh.process(test[i]);
-
-		digest=sh.hash();
-		for (i=0;i<32;i++) System.out.format("%02x",digest[i]);
-
-	//	for (i=0;i<32;i++) System.out.format("%d ",digest[i]);
-
-		System.out.println("");
-	} */
-}
-
diff --git a/cs/MPIN.cs b/cs/MPIN.cs
deleted file mode 100644
index f8ae051..0000000
--- a/cs/MPIN.cs
+++ /dev/null
@@ -1,916 +0,0 @@
-using System;
-
-/*
-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.
-*/
-
-/* MPIN API Functions */
-
-public class MPIN
-{
-	public static readonly int EFS = ROM.MODBYTES;
-	public static readonly int EGS = ROM.MODBYTES;
-	public const int PAS = 16;
-	public const int BAD_PARAMS = -11;
-	public const int INVALID_POINT = -14;
-	public const int WRONG_ORDER = -18;
-	public const int BAD_PIN = -19;
-
-/* Configure your PIN here */
-
-	public const int MAXPIN = 10000; // PIN less than this
-	public const int PBLEN = 14; // Number of bits in PIN
-	public const int TS = 10; // 10 for 4 digit PIN, 14 for 6-digit PIN - 2^TS/TS approx = sqrt(MAXPIN)
-	public const int TRAP = 200; // 200 for 4 digit PIN, 2000 for 6-digit PIN  - approx 2*sqrt(MAXPIN)
-
-/* Hash number (optional) and string to point on curve */
-
-	public static sbyte[] hashit(int n, sbyte[] ID)
-	{
-		HASH H = new HASH();
-		if (n != 0)
-		{
-			H.process_num(n);
-		}
-		H.process_array(ID);
-		sbyte[] h = H.hash();
-		return h;
-	}
-
-	public static ECP mapit(sbyte[] h)
-	{
-		BIG q = new BIG(ROM.Modulus);
-		BIG x = BIG.fromBytes(h);
-		x.mod(q);
-		ECP P;
-		while (true)
-		{
-			P = new ECP(x,0);
-			if (!P.is_infinity())
-			{
-				break;
-			}
-			x.inc(1);
-			x.norm();
-		}
-		return P;
-	}
-
-/* needed for SOK */
-	public static ECP2 mapit2(sbyte[] h)
-	{
-		BIG q = new BIG(ROM.Modulus);
-		BIG x = BIG.fromBytes(h);
-		BIG one = new BIG(1);
-		FP2 X;
-		ECP2 Q, T, K;
-		x.mod(q);
-		while (true)
-		{
-			X = new FP2(one,x);
-			Q = new ECP2(X);
-			if (!Q.is_infinity())
-			{
-				break;
-			}
-			x.inc(1);
-			x.norm();
-		}
-/* Fast Hashing to G2 - Fuentes-Castaneda, Knapp and Rodriguez-Henriquez */
-		BIG Fra = new BIG(ROM.CURVE_Fra);
-		BIG Frb = new BIG(ROM.CURVE_Frb);
-		X = new FP2(Fra,Frb);
-		x = new BIG(ROM.CURVE_Bnx);
-
-		T = new ECP2();
-		T.copy(Q);
-		T.mul(x);
-		T.neg();
-		K = new ECP2();
-		K.copy(T);
-		K.dbl();
-		K.add(T);
-		K.affine();
-
-		K.frob(X);
-		Q.frob(X);
-		Q.frob(X);
-		Q.frob(X);
-		Q.add(T);
-		Q.add(K);
-		T.frob(X);
-		T.frob(X);
-		Q.add(T);
-		Q.affine();
-		return Q;
-	}
-
-/* return time in slots since epoch */
-	public static int today()
-	{
-		TimeSpan t = DateTime.Now- new DateTime(1970,1,1);
-		return (int)(t.TotalSeconds / (60 * 1440));
-	}
-
-/* these next two functions help to implement elligator squared - http://eprint.iacr.org/2014/043 */
-/* maps a random u to a point on the curve */
-	public static ECP map(BIG u, int cb)
-	{
-		ECP P;
-		BIG x = new BIG(u);
-		BIG p = new BIG(ROM.Modulus);
-		x.mod(p);
-		while (true)
-		{
-			P = new ECP(x,cb);
-			if (!P.is_infinity())
-			{
-				break;
-			}
-			x.inc(1);
-			x.norm();
-		}
-		return P;
-	}
-
-/* returns u derived from P. Random value in range 1 to return value should then be added to u */
-	public static int unmap(BIG u, ECP P)
-	{
-		int s = P.S;
-		ECP R;
-		int r = 0;
-		BIG x = P.X;
-		u.copy(x);
-		while (true)
-		{
-			u.dec(1);
-			u.norm();
-			r++;
-			R = new ECP(u,s);
-			if (!R.is_infinity())
-			{
-				break;
-			}
-		}
-		return r;
-	}
-
-	public static sbyte[] HASH_ID(sbyte[] ID)
-	{
-		return hashit(0,ID);
-	}
-
-
-/* these next two functions implement elligator squared - http://eprint.iacr.org/2014/043 */
-/* Elliptic curve point E in format (0x04,x,y} is converted to form {0x0-,u,v} */
-/* Note that u and v are indistinguisible from random strings */
-	public static int ENCODING(RAND rng, sbyte[] E)
-	{
-		int rn, m, su, sv;
-		sbyte[] T = new sbyte[EFS];
-
-		for (int i = 0;i < EFS;i++)
-		{
-			T[i] = E[i + 1];
-		}
-		BIG u = BIG.fromBytes(T);
-		for (int i = 0;i < EFS;i++)
-		{
-			T[i] = E[i + EFS + 1];
-		}
-		BIG v = BIG.fromBytes(T);
-
-		ECP P = new ECP(u,v);
-		if (P.is_infinity())
-		{
-			return INVALID_POINT;
-		}
-
-		BIG p = new BIG(ROM.Modulus);
-		u = BIG.randomnum(p,rng);
-
-		su = rng.Byte; //if (su<0) su=-su;
- su %= 2;
-
-		ECP W = map(u,su);
-		P.sub(W);
-		sv = P.S;
-		rn = unmap(v,P);
-		m = rng.Byte; //if (m<0) m=-m;
- m %= rn;
-		v.inc(m + 1);
-		E[0] = (sbyte)(su + 2 * sv);
-		u.toBytes(T);
-		for (int i = 0;i < EFS;i++)
-		{
-			E[i + 1] = T[i];
-		}
-		v.toBytes(T);
-		for (int i = 0;i < EFS;i++)
-		{
-			E[i + EFS + 1] = T[i];
-		}
-
-		return 0;
-	}
-
-	public static int DECODING(sbyte[] D)
-	{
-		int su, sv;
-		sbyte[] T = new sbyte[EFS];
-
-		if ((D[0] & 0x04) != 0)
-		{
-			return INVALID_POINT;
-		}
-
-		for (int i = 0;i < EFS;i++)
-		{
-			T[i] = D[i + 1];
-		}
-		BIG u = BIG.fromBytes(T);
-		for (int i = 0;i < EFS;i++)
-		{
-			T[i] = D[i + EFS + 1];
-		}
-		BIG v = BIG.fromBytes(T);
-
-		su = D[0] & 1;
-		sv = (D[0] >> 1) & 1;
-		ECP W = map(u,su);
-		ECP P = map(v,sv);
-		P.add(W);
-		u = P.X;
-		v = P.Y;
-		D[0] = 0x04;
-		u.toBytes(T);
-		for (int i = 0;i < EFS;i++)
-		{
-			D[i + 1] = T[i];
-		}
-		v.toBytes(T);
-		for (int i = 0;i < EFS;i++)
-		{
-			D[i + EFS + 1] = T[i];
-		}
-
-		return 0;
-	}
-
-/* R=R1+R2 in group G1 */
-	public static int RECOMBINE_G1(sbyte[] R1, sbyte[] R2, sbyte[] R)
-	{
-		ECP P = ECP.fromBytes(R1);
-		ECP Q = ECP.fromBytes(R2);
-
-		if (P.is_infinity() || Q.is_infinity())
-		{
-			return INVALID_POINT;
-		}
-
-		P.add(Q);
-
-		P.toBytes(R);
-		return 0;
-	}
-
-/* W=W1+W2 in group G2 */
-	public static int RECOMBINE_G2(sbyte[] W1, sbyte[] W2, sbyte[] W)
-	{
-		ECP2 P = ECP2.fromBytes(W1);
-		ECP2 Q = ECP2.fromBytes(W2);
-
-		if (P.is_infinity() || Q.is_infinity())
-		{
-			return INVALID_POINT;
-		}
-
-		P.add(Q);
-
-		P.toBytes(W);
-		return 0;
-	}
-
-/* create random secret S */
-	public static int RANDOM_GENERATE(RAND rng, sbyte[] S)
-	{
-		BIG s;
-		BIG r = new BIG(ROM.CURVE_Order);
-		s = BIG.randomnum(r,rng);
-
-		s.toBytes(S);
-		return 0;
-	}
-
-/* Extract PIN from TOKEN for identity CID */
-	public static int EXTRACT_PIN(sbyte[] CID, int pin, sbyte[] TOKEN)
-	{
-		ECP P = ECP.fromBytes(TOKEN);
-		if (P.is_infinity())
-		{
-			return INVALID_POINT;
-		}
-		sbyte[] h = hashit(0,CID);
-		ECP R = mapit(h);
-
-
-		pin %= MAXPIN;
-
-		R = R.pinmul(pin,PBLEN);
-		P.sub(R);
-
-		P.toBytes(TOKEN);
-
-		return 0;
-	}
-
-/* Implement step 2 on client side of MPin protocol */
-	public static int CLIENT_2(sbyte[] X, sbyte[] Y, sbyte[] SEC)
-	{
-		BIG r = new BIG(ROM.CURVE_Order);
-		ECP P = ECP.fromBytes(SEC);
-		if (P.is_infinity())
-		{
-			return INVALID_POINT;
-		}
-
-		BIG px = BIG.fromBytes(X);
-		BIG py = BIG.fromBytes(Y);
-		px.add(py);
-		px.mod(r);
-		px.rsub(r);
-
-		PAIR.G1mul(P,px).toBytes(SEC);
-		return 0;
-	}
-
-/* Implement step 1 on client side of MPin protocol */
-	public static int CLIENT_1(int date, sbyte[] CLIENT_ID, RAND rng, sbyte[] X, int pin, sbyte[] TOKEN, sbyte[] SEC, sbyte[] xID, sbyte[] xCID, sbyte[] PERMIT)
-	{
-		BIG r = new BIG(ROM.CURVE_Order);
-//		BIG q=new BIG(ROM.Modulus);
-		BIG x;
-//		BIG m=new BIG(0);
-		if (rng != null)
-		{
-			x = BIG.randomnum(r,rng);
-			x.toBytes(X);
-		}
-		else
-		{
-			x = BIG.fromBytes(X);
-		}
-		ECP P, T, W;
-		BIG px;
-//		byte[] t=new byte[EFS];
-
-		sbyte[] h = hashit(0,CLIENT_ID);
-		P = mapit(h);
-
-		T = ECP.fromBytes(TOKEN);
-		if (T.is_infinity())
-		{
-			return INVALID_POINT;
-		}
-
-		pin %= MAXPIN;
-		W = P.pinmul(pin,PBLEN);
-		T.add(W);
-		if (date != 0)
-		{
-			W = ECP.fromBytes(PERMIT);
-			if (W.is_infinity())
-			{
-				return INVALID_POINT;
-			}
-			T.add(W);
-			h = hashit(date,h);
-			W = mapit(h);
-			if (xID != null)
-			{
-				P = PAIR.G1mul(P,x);
-				P.toBytes(xID);
-				W = PAIR.G1mul(W,x);
-				P.add(W);
-			}
-			else
-			{
-				P.add(W);
-				P = PAIR.G1mul(P,x);
-			}
-			if (xCID != null)
-			{
-				P.toBytes(xCID);
-			}
-		}
-		else
-		{
-			if (xID != null)
-			{
-				P = PAIR.G1mul(P,x);
-				P.toBytes(xID);
-			}
-		}
-
-
-		T.toBytes(SEC);
-		return 0;
-	}
-
-/* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */
-	public static int GET_SERVER_SECRET(sbyte[] S, sbyte[] SST)
-	{
-		ECP2 Q = new ECP2(new FP2(new BIG(ROM.CURVE_Pxa),new BIG(ROM.CURVE_Pxb)),new FP2(new BIG(ROM.CURVE_Pya),new BIG(ROM.CURVE_Pyb)));
-
-		BIG s = BIG.fromBytes(S);
-		Q = PAIR.G2mul(Q,s);
-		Q.toBytes(SST);
-		return 0;
-	}
-
-/*
- W=x*H(G);
- if RNG == NULL then X is passed in
- if RNG != NULL the X is passed out
- if type=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve
-*/
-	public static int GET_G1_MULTIPLE(RAND rng, int type, sbyte[] X, sbyte[] G, sbyte[] W)
-	{
-		BIG x;
-		BIG r = new BIG(ROM.CURVE_Order);
-		if (rng != null)
-		{
-			x = BIG.randomnum(r,rng);
-			x.toBytes(X);
-		}
-		else
-		{
-			x = BIG.fromBytes(X);
-		}
-		ECP P;
-		if (type == 0)
-		{
-			P = ECP.fromBytes(G);
-			if (P.is_infinity())
-			{
-				return INVALID_POINT;
-			}
-		}
-		else
-		{
-			P = mapit(G);
-		}
-
-		PAIR.G1mul(P,x).toBytes(W);
-		return 0;
-	}
-
-/* Client secret CST=S*H(CID) where CID is client ID and S is master secret */
-/* CID is hashed externally */
-	public static int GET_CLIENT_SECRET(sbyte[] S, sbyte[] CID, sbyte[] CST)
-	{
-		return GET_G1_MULTIPLE(null,1,S,CID,CST);
-	}
-
-/* Time Permit CTT=S*(date|H(CID)) where S is master secret */
-	public static int GET_CLIENT_PERMIT(int date, sbyte[] S, sbyte[] CID, sbyte[] CTT)
-	{
-		sbyte[] h = hashit(date,CID);
-		ECP P = mapit(h);
-
-		BIG s = BIG.fromBytes(S);
-		PAIR.G1mul(P,s).toBytes(CTT);
-		return 0;
-	}
-
-/* Outputs H(CID) and H(T|H(CID)) for time permits. If no time permits set HID=HTID */
-	public static void SERVER_1(int date, sbyte[] CID, sbyte[] HID, sbyte[] HTID)
-	{
-		sbyte[] h = hashit(0,CID);
-		ECP R , P = mapit(h);
-
-		if (date != 0)
-		{
-			if (HID != null)
-			{
-				P.toBytes(HID);
-			}
-			h = hashit(date,h);
-			R = mapit(h);
-			P.add(R);
-			P.toBytes(HTID);
-		}
-		else
-		{
-			P.toBytes(HID);
-		}
-	}
-
-/* Implement step 2 of MPin protocol on server side */
-	public static int SERVER_2(int date, sbyte[] HID, sbyte[] HTID, sbyte[] Y, sbyte[] SST, sbyte[] xID, sbyte[] xCID, sbyte[] mSEC, sbyte[] E, sbyte[] F)
-	{
-		BIG q = new BIG(ROM.Modulus);
-		ECP2 Q = new ECP2(new FP2(new BIG(ROM.CURVE_Pxa),new BIG(ROM.CURVE_Pxb)),new FP2(new BIG(ROM.CURVE_Pya),new BIG(ROM.CURVE_Pyb)));
-		ECP2 sQ = ECP2.fromBytes(SST);
-		if (sQ.is_infinity())
-		{
-			return INVALID_POINT;
-		}
-
-		ECP R;
-		if (date != 0)
-		{
-			R = ECP.fromBytes(xCID);
-		}
-		else
-		{
-			if (xID == null)
-			{
-				return BAD_PARAMS;
-			}
-			R = ECP.fromBytes(xID);
-		}
-		if (R.is_infinity())
-		{
-			return INVALID_POINT;
-		}
-
-		BIG y = BIG.fromBytes(Y);
-		ECP P;
-		if (date != 0)
-		{
-			P = ECP.fromBytes(HTID);
-		}
-		else
-		{
-			if (HID == null)
-			{
-				return BAD_PARAMS;
-			}
-			P = ECP.fromBytes(HID);
-		}
-
-		if (P.is_infinity())
-		{
-			return INVALID_POINT;
-		}
-
-		P = PAIR.G1mul(P,y);
-		P.add(R);
-		R = ECP.fromBytes(mSEC);
-		if (R.is_infinity())
-		{
-			return INVALID_POINT;
-		}
-
-		FP12 g;
-//		FP12 g1=new FP12(0);
-
-		g = PAIR.ate2(Q,R,sQ,P);
-		g = PAIR.fexp(g);
-
-		if (!g.isunity())
-		{
-			if (HID != null && xID != null && E != null && F != null)
-			{
-				g.toBytes(E);
-				if (date != 0)
-				{
-					P = ECP.fromBytes(HID);
-					if (P.is_infinity())
-					{
-						return INVALID_POINT;
-					}
-					R = ECP.fromBytes(xID);
-					if (R.is_infinity())
-					{
-						return INVALID_POINT;
-					}
-
-					P = PAIR.G1mul(P,y);
-					P.add(R);
-				}
-				g = PAIR.ate(Q,P);
-				g = PAIR.fexp(g);
-				g.toBytes(F);
-			}
-			return BAD_PIN;
-		}
-
-		return 0;
-	}
-
-/* Pollards kangaroos used to return PIN error */
-	public static int KANGAROO(sbyte[] E, sbyte[] F)
-	{
-		FP12 ge = FP12.fromBytes(E);
-		FP12 gf = FP12.fromBytes(F);
-		int[] distance = new int[TS];
-		FP12 t = new FP12(gf);
-		FP12[] table = new FP12[TS];
-		int i, j, m, s, dn, dm, res, steps;
-
-		s = 1;
-		for (m = 0;m < TS;m++)
-		{
-			distance[m] = s;
-			table[m] = new FP12(t);
-			s *= 2;
-			t.usqr();
-		}
-		t.one();
-		dn = 0;
-		for (j = 0;j < TRAP;j++)
-		{
-			i = t.geta().geta().A.lastbits(8) % TS;
-			t.mul(table[i]);
-			dn += distance[i];
-		}
-		gf.copy(t);
-		gf.conj();
-		steps = 0;
-		dm = 0;
-		res = 0;
-		while (dm - dn < MAXPIN)
-		{
-			steps++;
-			if (steps > 4 * TRAP)
-			{
-				break;
-			}
-			i = ge.geta().geta().A.lastbits(8) % TS;
-			ge.mul(table[i]);
-			dm += distance[i];
-			if (ge.Equals(t))
-			{
-				res = dm - dn;
-				break;
-			}
-			if (ge.Equals(gf))
-			{
-				res = dn - dm;
-				break;
-			}
-
-		}
-		if (steps > 4 * TRAP || dm - dn >= MAXPIN)
-		{
-			res = 0;
-		} // Trap Failed  - probable invalid token
-		return res;
-	}
-
-/* Functions to support M-Pin Full */
-
-	public static int PRECOMPUTE(sbyte[] TOKEN, sbyte[] CID, sbyte[] G1, sbyte[] G2)
-	{
-		ECP P, T;
-		FP12 g;
-
-		T = ECP.fromBytes(TOKEN);
-		if (T.is_infinity())
-		{
-			return INVALID_POINT;
-		}
-
-		P = mapit(CID);
-
-		ECP2 Q = new ECP2(new FP2(new BIG(ROM.CURVE_Pxa),new BIG(ROM.CURVE_Pxb)),new FP2(new BIG(ROM.CURVE_Pya),new BIG(ROM.CURVE_Pyb)));
-
-		g = PAIR.ate(Q,T);
-		g = PAIR.fexp(g);
-		g.toBytes(G1);
-
-		g = PAIR.ate(Q,P);
-		g = PAIR.fexp(g);
-		g.toBytes(G2);
-
-		return 0;
-	}
-
-/* calculate common key on client side */
-/* wCID = w.(A+AT) */
-	public static int CLIENT_KEY(sbyte[] G1, sbyte[] G2, int pin, sbyte[] R, sbyte[] X, sbyte[] wCID, sbyte[] CK)
-	{
-		HASH H = new HASH();
-		sbyte[] t = new sbyte[EFS];
-
-		FP12 g1 = FP12.fromBytes(G1);
-		FP12 g2 = FP12.fromBytes(G2);
-		BIG z = BIG.fromBytes(R);
-		BIG x = BIG.fromBytes(X);
-
-		ECP W = ECP.fromBytes(wCID);
-		if (W.is_infinity())
-		{
-			return INVALID_POINT;
-		}
-
-		W = PAIR.G1mul(W,x);
-
-		FP2 f = new FP2(new BIG(ROM.CURVE_Fra),new BIG(ROM.CURVE_Frb));
-		BIG r = new BIG(ROM.CURVE_Order);
-		BIG q = new BIG(ROM.Modulus);
-
-		BIG m = new BIG(q);
-		m.mod(r);
-
-		BIG a = new BIG(z);
-		a.mod(m);
-
-		BIG b = new BIG(z);
-		b.div(m);
-
-		g2.pinpow(pin,PBLEN);
-		g1.mul(g2);
-
-		FP4 c = g1.trace();
-		g2.copy(g1);
-		g2.frob(f);
-		FP4 cp = g2.trace();
-		g1.conj();
-		g2.mul(g1);
-		FP4 cpm1 = g2.trace();
-		g2.mul(g1);
-		FP4 cpm2 = g2.trace();
-
-		c = c.xtr_pow2(cp,cpm1,cpm2,a,b);
-
-		c.geta().A.toBytes(t);
-		H.process_array(t);
-		c.geta().B.toBytes(t);
-		H.process_array(t);
-		c.getb().A.toBytes(t);
-		H.process_array(t);
-		c.getb().B.toBytes(t);
-		H.process_array(t);
-
-		W.X.toBytes(t);
-		H.process_array(t);
-		W.Y.toBytes(t);
-		H.process_array(t);
-
-		t = H.hash();
-		for (int i = 0;i < PAS;i++)
-		{
-			CK[i] = t[i];
-		}
-
-		return 0;
-	}
-
-/* calculate common key on server side */
-/* Z=r.A - no time permits involved */
-
-	public static int SERVER_KEY(sbyte[] Z, sbyte[] SST, sbyte[] W, sbyte[] xID, sbyte[] xCID, sbyte[] SK)
-	{
-		HASH H = new HASH();
-		sbyte[] t = new sbyte[EFS];
-
-		ECP2 sQ = ECP2.fromBytes(SST);
-		if (sQ.is_infinity())
-		{
-			return INVALID_POINT;
-		}
-		ECP R = ECP.fromBytes(Z);
-		if (R.is_infinity())
-		{
-			return INVALID_POINT;
-		}
-
-		ECP U;
-		if (xCID != null)
-		{
-			U = ECP.fromBytes(xCID);
-		}
-		else
-		{
-			U = ECP.fromBytes(xID);
-		}
-		if (U.is_infinity())
-		{
-			return INVALID_POINT;
-		}
-
-		BIG w = BIG.fromBytes(W);
-		U = PAIR.G1mul(U,w);
-		FP12 g = PAIR.ate(sQ,R);
-		g = PAIR.fexp(g);
-
-		FP4 c = g.trace();
-		c.geta().A.toBytes(t);
-		H.process_array(t);
-		c.geta().B.toBytes(t);
-		H.process_array(t);
-		c.getb().A.toBytes(t);
-		H.process_array(t);
-		c.getb().B.toBytes(t);
-		H.process_array(t);
-
-		U.X.toBytes(t);
-		H.process_array(t);
-		U.Y.toBytes(t);
-		H.process_array(t);
-
-		t = H.hash();
-		for (int i = 0;i < PAS;i++)
-		{
-			SK[i] = t[i];
-		}
-
-		return 0;
-	}
-
-/* return time since epoch */
-	public static int GET_TIME()
-	{
-		DateTime date = DateTime.Now;
-		return (int)(date.Ticks / 1000);
-	}
-
-/* Generate Y = H(epoch, xCID/xID) */
-		public static void GET_Y(int TimeValue, sbyte[] xCID, sbyte[] Y)
-		{
-		  sbyte[] h = hashit(TimeValue,xCID);
-		  BIG y = BIG.fromBytes(h);
-		  BIG q = new BIG(ROM.CURVE_Order);
-		  y.mod(q);
-		  y.toBytes(Y);
-		}
-
-/* One pass MPIN Client */
-		public static int CLIENT(int date, sbyte[] CLIENT_ID, RAND RNG, sbyte[] X, int pin, sbyte[] TOKEN, sbyte[] SEC, sbyte[] xID, sbyte[] xCID, sbyte[] PERMIT, int TimeValue, sbyte[] Y)
-		{
-		  int rtn = 0;
-
-		  sbyte[] pID;
-		  if (date == 0)
-		  {
-			pID = xID;
-		  }
-		  else
-		  {
-			pID = xCID;
-		  }
-
-		  rtn = CLIENT_1(date,CLIENT_ID,RNG,X,pin,TOKEN,SEC,xID,xCID,PERMIT);
-		  if (rtn != 0)
-		  {
-			return rtn;
-		  }
-
-		  GET_Y(TimeValue,pID,Y);
-
-		  rtn = CLIENT_2(X,Y,SEC);
-		  if (rtn != 0)
-		  {
-			return rtn;
-		  }
-
-		  return 0;
-		}
-
-/* One pass MPIN Server */
-		public static int SERVER(int date, sbyte[] HID, sbyte[] HTID, sbyte[] Y, sbyte[] SST, sbyte[] xID, sbyte[] xCID, sbyte[] SEC, sbyte[] E, sbyte[] F, sbyte[] CID, int TimeValue)
-		{
-		  int rtn = 0;
-
-		  sbyte[] pID;
-		  if (date == 0)
-		  {
-			pID = xID;
-		  }
-		  else
-		  {
-			pID = xCID;
-		  }
-
-		  SERVER_1(date,CID,HID,HTID);
-
-		  GET_Y(TimeValue,pID,Y);
-
-		  rtn = SERVER_2(date,HID,HTID,Y,SST,xID,xCID,SEC,E,F);
-		  if (rtn != 0)
-		  {
-			return rtn;
-		  }
-
-		  return 0;
-		}
-
-}
diff --git a/cs/PAIR.cs b/cs/PAIR.cs
deleted file mode 100644
index 14bd6db..0000000
--- a/cs/PAIR.cs
+++ /dev/null
@@ -1,586 +0,0 @@
-using System;
-
-/*
-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.
-*/
-
-/* AMCL BN Curve Pairing functions */
-
-public sealed class PAIR
-{
-
-/* Line function */
-	public static FP12 line(ECP2 A, ECP2 B, FP Qx, FP Qy)
-	{
-		ECP2 P = new ECP2();
-
-		FP4 a, b, c;
-		P.copy(A);
-		FP2 ZZ = new FP2(P.getz());
-		ZZ.sqr();
-		int D;
-		if (A == B)
-		{
-			D = A.dbl(); // Check this return value in amcl_ec2.c
-		}
-		else
-		{
-			D = A.add(B);
-		}
-		if (D < 0)
-		{
-			return new FP12(1);
-		}
-		FP2 Z3 = new FP2(A.getz());
-		c = new FP4(0);
-		if (D == 0)
-		{ // Addition
-			FP2 X = new FP2(B.getx());
-			FP2 Y = new FP2(B.gety());
-			FP2 T = new FP2(P.getz());
-			T.mul(Y);
-			ZZ.mul(T);
-
-			FP2 NY = new FP2(P.gety());
-			NY.neg();
-			ZZ.add(NY);
-			Z3.pmul(Qy);
-			T.mul(P.getx());
-			X.mul(NY);
-			T.add(X);
-			a = new FP4(Z3,T);
-			ZZ.neg();
-			ZZ.pmul(Qx);
-			b = new FP4(ZZ);
-		}
-		else
-		{ // Doubling
-			FP2 X = new FP2(P.getx());
-			FP2 Y = new FP2(P.gety());
-			FP2 T = new FP2(P.getx());
-			T.sqr();
-			T.imul(3);
-
-			Y.sqr();
-			Y.add(Y);
-			Z3.mul(ZZ);
-			Z3.pmul(Qy);
-
-			X.mul(T);
-			X.sub(Y);
-			a = new FP4(Z3,X);
-			T.neg();
-			ZZ.mul(T);
-			ZZ.pmul(Qx);
-			b = new FP4(ZZ);
-		}
-		return new FP12(a,b,c);
-	}
-
-/* Optimal R-ate pairing */
-	public static FP12 ate(ECP2 P, ECP Q)
-	{
-		FP2 f = new FP2(new BIG(ROM.CURVE_Fra),new BIG(ROM.CURVE_Frb));
-		BIG x = new BIG(ROM.CURVE_Bnx);
-		BIG n = new BIG(x);
-		ECP2 K = new ECP2();
-		FP12 lv;
-		n.pmul(6);
-		n.dec(2);
-		n.norm();
-		P.affine();
-		Q.affine();
-		FP Qx = new FP(Q.getx());
-		FP Qy = new FP(Q.gety());
-
-		ECP2 A = new ECP2();
-		FP12 r = new FP12(1);
-
-		A.copy(P);
-		int nb = n.nbits();
-
-		for (int i = nb - 2;i >= 1;i--)
-		{
-			lv = line(A,A,Qx,Qy);
-			r.smul(lv);
-
-			if (n.bit(i) == 1)
-			{
-				lv = line(A,P,Qx,Qy);
-
-				r.smul(lv);
-			}
-			r.sqr();
-		}
-
-		lv = line(A,A,Qx,Qy);
-		r.smul(lv);
-
-/* R-ate fixup */
-
-		r.conj();
-
-		K.copy(P);
-		K.frob(f);
-		A.neg();
-		lv = line(A,K,Qx,Qy);
-		r.smul(lv);
-		K.frob(f);
-		K.neg();
-		lv = line(A,K,Qx,Qy);
-		r.smul(lv);
-
-		return r;
-	}
-
-/* Optimal R-ate double pairing e(P,Q).e(R,S) */
-	public static FP12 ate2(ECP2 P, ECP Q, ECP2 R, ECP S)
-	{
-		FP2 f = new FP2(new BIG(ROM.CURVE_Fra),new BIG(ROM.CURVE_Frb));
-		BIG x = new BIG(ROM.CURVE_Bnx);
-		BIG n = new BIG(x);
-		ECP2 K = new ECP2();
-		FP12 lv;
-		n.pmul(6);
-		n.dec(2);
-		n.norm();
-		P.affine();
-		Q.affine();
-		R.affine();
-		S.affine();
-
-		FP Qx = new FP(Q.getx());
-		FP Qy = new FP(Q.gety());
-		FP Sx = new FP(S.getx());
-		FP Sy = new FP(S.gety());
-
-		ECP2 A = new ECP2();
-		ECP2 B = new ECP2();
-		FP12 r = new FP12(1);
-
-		A.copy(P);
-		B.copy(R);
-		int nb = n.nbits();
-
-		for (int i = nb - 2;i >= 1;i--)
-		{
-			lv = line(A,A,Qx,Qy);
-			r.smul(lv);
-			lv = line(B,B,Sx,Sy);
-			r.smul(lv);
-
-			if (n.bit(i) == 1)
-			{
-				lv = line(A,P,Qx,Qy);
-				r.smul(lv);
-				lv = line(B,R,Sx,Sy);
-				r.smul(lv);
-			}
-			r.sqr();
-		}
-
-		lv = line(A,A,Qx,Qy);
-		r.smul(lv);
-
-		lv = line(B,B,Sx,Sy);
-		r.smul(lv);
-
-/* R-ate fixup */
-		r.conj();
-
-		K.copy(P);
-		K.frob(f);
-		A.neg();
-		lv = line(A,K,Qx,Qy);
-		r.smul(lv);
-		K.frob(f);
-		K.neg();
-		lv = line(A,K,Qx,Qy);
-		r.smul(lv);
-
-		K.copy(R);
-		K.frob(f);
-		B.neg();
-		lv = line(B,K,Sx,Sy);
-		r.smul(lv);
-		K.frob(f);
-		K.neg();
-		lv = line(B,K,Sx,Sy);
-		r.smul(lv);
-
-		return r;
-	}
-
-/* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */
-	public static FP12 fexp(FP12 m)
-	{
-		FP2 f = new FP2(new BIG(ROM.CURVE_Fra),new BIG(ROM.CURVE_Frb));
-		BIG x = new BIG(ROM.CURVE_Bnx);
-		FP12 r = new FP12(m);
-		FP12 x0, x1, x2, x3, x4, x5;
-
-/* Easy part of final exp */
-		FP12 lv = new FP12(r);
-		lv.inverse();
-		r.conj();
-
-		r.mul(lv);
-		lv.copy(r);
-		r.frob(f);
-		r.frob(f);
-		r.mul(lv);
-/* Hard part of final exp */
-		lv.copy(r);
-		lv.frob(f);
-		x0 = new FP12(lv);
-		x0.frob(f);
-		lv.mul(r);
-		x0.mul(lv);
-		x0.frob(f);
-		x1 = new FP12(r);
-		x1.conj();
-		x4 = r.pow(x);
-
-		x3 = new FP12(x4);
-		x3.frob(f);
-
-		x2 = x4.pow(x);
-
-		x5 = new FP12(x2);
-		x5.conj();
-		lv = x2.pow(x);
-
-		x2.frob(f);
-		r.copy(x2);
-		r.conj();
-
-		x4.mul(r);
-		x2.frob(f);
-
-		r.copy(lv);
-		r.frob(f);
-		lv.mul(r);
-
-		lv.usqr();
-		lv.mul(x4);
-		lv.mul(x5);
-		r.copy(x3);
-		r.mul(x5);
-		r.mul(lv);
-		lv.mul(x2);
-		r.usqr();
-		r.mul(lv);
-		r.usqr();
-		lv.copy(r);
-		lv.mul(x1);
-		r.mul(x0);
-		lv.usqr();
-		r.mul(lv);
-		r.reduce();
-		return r;
-	}
-
-/* GLV method */
-	public static BIG[] glv(BIG e)
-	{
-		int i, j;
-		BIG t = new BIG(0);
-		BIG q = new BIG(ROM.CURVE_Order);
-		BIG[] u = new BIG[2];
-		BIG[] v = new BIG[2];
-		for (i = 0;i < 2;i++)
-		{
-			t.copy(new BIG(ROM.CURVE_W[i])); // why not just t=new BIG(ROM.CURVE_W[i]);
-			DBIG d = BIG.mul(t,e);
-			v[i] = new BIG(d.div(q));
-			u[i] = new BIG(0);
-		}
-		u[0].copy(e);
-		for (i = 0;i < 2;i++)
-		{
-			for (j = 0;j < 2;j++)
-			{
-				t.copy(new BIG(ROM.CURVE_SB[j][i]));
-				t.copy(BIG.modmul(v[j],t,q));
-				u[i].add(q);
-				u[i].sub(t);
-				u[i].mod(q);
-			}
-		}
-		return u;
-	}
-
-/* Galbraith & Scott Method */
-	public static BIG[] gs(BIG e)
-	{
-		int i, j;
-		BIG t = new BIG(0);
-		BIG q = new BIG(ROM.CURVE_Order);
-		BIG[] u = new BIG[4];
-		BIG[] v = new BIG[4];
-		for (i = 0;i < 4;i++)
-		{
-			t.copy(new BIG(ROM.CURVE_WB[i]));
-			DBIG d = BIG.mul(t,e);
-			v[i] = new BIG(d.div(q));
-			u[i] = new BIG(0);
-		}
-		u[0].copy(e);
-		for (i = 0;i < 4;i++)
-		{
-			for (j = 0;j < 4;j++)
-			{
-				t.copy(new BIG(ROM.CURVE_BB[j][i]));
-				t.copy(BIG.modmul(v[j],t,q));
-				u[i].add(q);
-				u[i].sub(t);
-				u[i].mod(q);
-			}
-		}
-		return u;
-	}
-
-/* Multiply P by e in group G1 */
-	public static ECP G1mul(ECP P, BIG e)
-	{
-		ECP R;
-		if (ROM.USE_GLV)
-		{
-			P.affine();
-			R = new ECP();
-			R.copy(P);
-			int i, np, nn;
-			ECP Q = new ECP();
-			Q.copy(P);
-			BIG q = new BIG(ROM.CURVE_Order);
-			FP cru = new FP(new BIG(ROM.CURVE_Cru));
-			BIG t = new BIG(0);
-			BIG[] u = glv(e);
-			Q.getx().mul(cru);
-
-			np = u[0].nbits();
-			t.copy(BIG.modneg(u[0],q));
-			nn = t.nbits();
-			if (nn < np)
-			{
-				u[0].copy(t);
-				R.neg();
-			}
-
-			np = u[1].nbits();
-			t.copy(BIG.modneg(u[1],q));
-			nn = t.nbits();
-			if (nn < np)
-			{
-				u[1].copy(t);
-				Q.neg();
-			}
-
-			R = R.mul2(u[0],Q,u[1]);
-
-		}
-		else
-		{
-			R = P.mul(e);
-		}
-		return R;
-	}
-
-/* Multiply P by e in group G2 */
-	public static ECP2 G2mul(ECP2 P, BIG e)
-	{
-		ECP2 R;
-		if (ROM.USE_GS_G2)
-		{
-			ECP2[] Q = new ECP2[4];
-			FP2 f = new FP2(new BIG(ROM.CURVE_Fra),new BIG(ROM.CURVE_Frb));
-			BIG q = new BIG(ROM.CURVE_Order);
-			BIG[] u = gs(e);
-
-			BIG t = new BIG(0);
-			int i, np, nn;
-			P.affine();
-			Q[0] = new ECP2();
-			Q[0].copy(P);
-			for (i = 1;i < 4;i++)
-			{
-				Q[i] = new ECP2();
-				Q[i].copy(Q[i - 1]);
-				Q[i].frob(f);
-			}
-			for (i = 0;i < 4;i++)
-			{
-				np = u[i].nbits();
-				t.copy(BIG.modneg(u[i],q));
-				nn = t.nbits();
-				if (nn < np)
-				{
-					u[i].copy(t);
-					Q[i].neg();
-				}
-			}
-			R = ECP2.mul4(Q,u);
-
-		}
-		else
-		{
-			R = P.mul(e);
-		}
-		return R;
-	}
-
-/* f=f^e */
-/* Note that this method requires a lot of RAM! Better to use compressed XTR method, see FP4.java */
-	public static FP12 GTpow(FP12 d, BIG e)
-	{
-		FP12 r;
-		if (ROM.USE_GS_GT)
-		{
-			FP12[] g = new FP12[4];
-			FP2 f = new FP2(new BIG(ROM.CURVE_Fra),new BIG(ROM.CURVE_Frb));
-			BIG q = new BIG(ROM.CURVE_Order);
-			BIG t = new BIG(0);
-			int i, np, nn;
-			BIG[] u = gs(e);
-
-			g[0] = new FP12(d);
-			for (i = 1;i < 4;i++)
-			{
-				g[i] = new FP12(0);
-				g[i].copy(g[i - 1]);
-				g[i].frob(f);
-			}
-			for (i = 0;i < 4;i++)
-			{
-				np = u[i].nbits();
-				t.copy(BIG.modneg(u[i],q));
-				nn = t.nbits();
-				if (nn < np)
-				{
-					u[i].copy(t);
-					g[i].conj();
-				}
-			}
-			r = FP12.pow4(g,u);
-		}
-		else
-		{
-			r = d.pow(e);
-		}
-		return r;
-	}
-
-/* test group membership */
-/* with GT-Strong curve, now only check that m!=1, conj(m)*m==1, and m.m^{p^4}=m^{p^2} */
-	public static bool GTmember(FP12 m)
-	{
-		if (m.isunity())
-		{
-			return false;
-		}
-		FP12 r = new FP12(m);
-		r.conj();
-		r.mul(m);
-		if (!r.isunity())
-		{
-			return false;
-		}
-
-		FP2 f = new FP2(new BIG(ROM.CURVE_Fra),new BIG(ROM.CURVE_Frb));
-
-		r.copy(m);
-		r.frob(f);
-		r.frob(f);
-		FP12 w = new FP12(r);
-		w.frob(f);
-		w.frob(f);
-		w.mul(m);
-		if (!ROM.GT_STRONG)
-		{
-			if (!w.Equals(r))
-			{
-				return false;
-			}
-			BIG x = new BIG(ROM.CURVE_Bnx);
-			r.copy(m);
-			w = r.pow(x);
-			w = w.pow(x);
-			r.copy(w);
-			r.sqr();
-			r.mul(w);
-			r.sqr();
-			w.copy(m);
-			w.frob(f);
-		}
-		return w.Equals(r);
-	}
-}
-/*
-	public static void Main(string[] args)
-	{
-		ECP Q = new ECP(new BIG(ROM.CURVE_Gx),new BIG(ROM.CURVE_Gy));
-		ECP2 P = new ECP2(new FP2(new BIG(ROM.CURVE_Pxa),new BIG(ROM.CURVE_Pxb)),new FP2(new BIG(ROM.CURVE_Pya),new BIG(ROM.CURVE_Pyb)));
-
-		BIG r = new BIG(ROM.CURVE_Order);
-		BIG xa = new BIG(ROM.CURVE_Pxa);
-
-		Console.WriteLine("P= " + P.ToString());
-		Console.WriteLine("Q= " + Q.ToString());
-
-		BIG m = new BIG(17);
-
-		FP12 e = ate(P,Q);
-		Console.WriteLine("\ne= " + e.ToString());
-
-		e = fexp(e);
-	//	e=GTpow(e,m);
-
-		Console.WriteLine("\ne= " + e.ToString());
-
-		BIG[] GLV = glv(r);
-
-		Console.WriteLine("GLV[0]= " + GLV[0].ToString());
-		Console.WriteLine("GLV[0]= " + GLV[1].ToString());
-
-		ECP G = new ECP();
-		G.copy(Q);
-		ECP2 R = new ECP2();
-		R.copy(P);
-
-
-		e = ate(R,Q);
-		e = fexp(e);
-
-		e = GTpow(e,xa);
-		Console.WriteLine("\ne= " + e.ToString());
-
-
-		R = G2mul(R,xa);
-		e = ate(R,G);
-		e = fexp(e);
-
-		Console.WriteLine("\ne= " + e.ToString());
-
-		G = G1mul(G,xa);
-		e = ate(P,G);
-		e = fexp(e);
-		Console.WriteLine("\ne= " + e.ToString());
-	}
-}
-
-*/
diff --git a/cs/RAND.cs b/cs/RAND.cs
deleted file mode 100644
index 0c74885..0000000
--- a/cs/RAND.cs
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
-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.
-*/
-
-/*
- *   Cryptographic strong random number generator
- *
- *   Unguessable seed -> SHA -> PRNG internal state -> SHA -> random numbers
- *   Slow - but secure
- *
- *   See ftp://ftp.rsasecurity.com/pub/pdfs/bull-1.pdf for a justification
- */
-
-/* Marsaglia & Zaman Random number generator constants */
-
-
-public class RAND
-{
-/* Cryptographically strong pseudo-random number generator */
-
-	private const int NK = 21;
-	private const int NJ = 6;
-	private const int NV = 8;
-	private int[] ira = new int[NK]; // random number...
-	private int rndptr; // ...array & pointer
-	private int borrow;
-	private int pool_ptr;
-	private sbyte[] pool = new sbyte[32]; // random pool
-
-	public RAND()
-	{
-		clean();
-	}
-
-	private int sbrand()
-	{ // Marsaglia & Zaman random number generator
-		int i, k;
-		long pdiff, t;
-
-		rndptr++;
-		if (rndptr < NK)
-		{
-			return ira[rndptr];
-		}
-		rndptr = 0;
-		for (i = 0,k = NK - NJ;i < NK;i++,k++)
-		{ // calculate next NK values
-			if (k == NK)
-			{
-				k = 0;
-			}
-			t = ((long)ira[k]) & 0xffffffffL;
-			pdiff = (t - (((long)ira[i]) & 0xffffffffL) - (long)borrow) & 0xffffffffL;
-			if (pdiff < t)
-			{
-				borrow = 0;
-			}
-			if (pdiff > t)
-			{
-				borrow = 1;
-			}
-			ira[i] = unchecked((int)(pdiff & 0xffffffffL));
-		}
-
-		return ira[0];
-	}
-
-	public virtual void sirand(int seed)
-	{
-		int i, @in;
-		int t , m = 1;
-		borrow = 0;
-		rndptr = 0;
-		ira[0] ^= seed;
-		for (i = 1;i < NK;i++)
-		{ // fill initialisation vector
-			@in = (NV * i) % NK;
-			ira[@in] ^= m; // note XOR
-			t = m;
-			m = seed - m;
-			seed = t;
-		}
-		for (i = 0;i < 10000;i++)
-		{
-			sbrand(); // "warm-up" & stir the generator
-		}
-	}
-
-	private void fill_pool()
-	{
-		HASH sh = new HASH();
-		for (int i = 0;i < 128;i++)
-		{
-			sh.process(sbrand());
-		}
-		pool = sh.hash();
-		pool_ptr = 0;
-	}
-
-	private static int pack(sbyte[] b)
-	{ // pack 4 bytes into a 32-bit Word
-		return ((((int)b[3]) & 0xff) << 24) | (((int)b[2] & 0xff) << 16) | (((int)b[1] & 0xff) << 8) | ((int)b[0] & 0xff);
-	}
-
-/* Initialize RNG with some real entropy from some external source */
-	public virtual void seed(int rawlen, sbyte[] raw)
-	{ // initialise from at least 128 byte string of raw random entropy
-		int i;
-		sbyte[] digest;
-		sbyte[] b = new sbyte[4];
-		HASH sh = new HASH();
-		pool_ptr = 0;
-		for (i = 0;i < NK;i++)
-		{
-			ira[i] = 0;
-		}
-		if (rawlen > 0)
-		{
-			for (i = 0;i < rawlen;i++)
-			{
-				sh.process(raw[i]);
-			}
-			digest = sh.hash();
-
-/* initialise PRNG from distilled randomness */
-
-			for (i = 0;i < 8;i++)
-			{
-				b[0] = digest[4 * i];
-				b[1] = digest[4 * i + 1];
-				b[2] = digest[4 * i + 2];
-				b[3] = digest[4 * i + 3];
-				sirand(pack(b));
-			}
-		}
-		fill_pool();
-	}
-
-/* Terminate and clean up */
-	public virtual void clean()
-	{ // kill internal state
-		int i;
-		pool_ptr = rndptr = 0;
-		for (i = 0;i < 32;i++)
-		{
-			pool[i] = 0;
-		}
-		for (i = 0;i < NK;i++)
-		{
-			ira[i] = 0;
-		}
-		borrow = 0;
-	}
-
-/* get random byte */
-	public virtual int Byte
-	{
-		get
-		{
-			int r;
-			r = pool[pool_ptr++];
-			if (pool_ptr >= 32)
-			{
-				fill_pool();
-			}
-			return (r & 0xff);
-		}
-	}
-
-/* test main program */
-/*
-	public static void main(String[] args) {
-		int i;
-		byte[] raw=new byte[100];
-		RAND rng=new RAND();
-
-		rng.clean();
-		for (i=0;i<100;i++) raw[i]=(byte)i;
-
-		rng.seed(100,raw);
-
-		for (i=0;i<1000;i++)
-			System.out.format("%03d ",rng.getByte());
-	} */
-}
diff --git a/cs/ROM.cs b/cs/ROM.cs
deleted file mode 100644
index 2daf906..0000000
--- a/cs/ROM.cs
+++ /dev/null
@@ -1,434 +0,0 @@
-/*
-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.
-*/
-
-/* Fixed Data in ROM - Field and Curve parameters */
-
-public class ROM
-{
-/* Don't Modify from here... */
-	public const int NOT_SPECIAL = 0;
-	public const int PSEUDO_MERSENNE = 1;
-	public const int MONTGOMERY_FRIENDLY = 2;
-	public const int WEIERSTRASS = 0;
-	public const int EDWARDS = 1;
-	public const int MONTGOMERY = 2;
-/* ...to here */
-
-/// <summary>
-///* Enter Some Field details here  ** </summary>
-// BN Curve
-	public const int MODBITS = 254; // Number of bits in Modulus
-	public const int MOD8 = 3; // Modulus mod 8
-// Curve 25519
-//	public static final int MODBITS=255;
-//	public static final int MOD8=5;
-// NIST256 or Brainpool
-//	public static final int MODBITS=256;
-//	public static final int MOD8=7;
-// MF254
-//	public static final int MODBITS=254;
-//	public static final int MOD8=7;
-// MS255
-//public static final int MODBITS= 255;
-//public static final int MOD8= 3;
-// MF256
-//	public static final int MODBITS=256;
-//	public static final int MOD8=7;
-// MS256
-//public static final int MODBITS= 256;
-//public static final int MOD8= 3;
-// ANSSI
-//  public static final int MODBITS= 256;
-//  public static final int MOD8= 3;
-
-/* Don't Modify from here... */
-	public const int NLEN = 5;
-	public const int CHUNK = 64;
-	public static readonly int DNLEN = 2 * NLEN;
-	public const int BASEBITS = 56;
-	public static readonly long MASK = (((long)1 << BASEBITS) - 1);
-	public static readonly int HBITS = BASEBITS / 2;
-	public static readonly long HMASK = (((long)1 << HBITS) - 1);
-	public const int MODBYTES = 32;
-	public static readonly int NEXCESS = ((int)1 << (CHUNK - BASEBITS - 1));
-	public static readonly long FEXCESS = ((long)1 << (BASEBITS * NLEN - MODBITS));
-	public static readonly long OMASK = (long)(-1) << (MODBITS % BASEBITS);
-	public static readonly int TBITS = MODBITS % BASEBITS; // Number of active bits in top word
-	public static readonly long TMASK = ((long)1 << TBITS) - 1;
-/* ...to here */
-
-/* Finite field support - for RSA, DH etc. */
-	public const int FF_BITS = 2048; // Finite Field Size in bits - must be 256.2^n
-	public static readonly int FFLEN = (FF_BITS / 256);
-	public static readonly int HFLEN = (FFLEN / 2); // Useful for half-size RSA private key operations
-
-
-// START SPECIFY FIELD DETAILS HERE
-//*********************************************************************************
-// Curve25519 Modulus
-//	public static final int MODTYPE=PSEUDO_MERSENNE;
-//	public static final long[] Modulus= {0xFFFFFFFFFFFFEDL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0x7FFFFFFFL};
-//	public static final long MConst=0x13L;
-
-
-// NIST-256 Curve
-//	public static final int MODTYPE=NOT_SPECIAL;
-//	public static final long[] Modulus= {0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFL,0x0L,0x1000000L,0xFFFFFFFFL};
-//	public static final long MConst=0x1L;
-
-// MF254 Modulus
-//	public static final int MODTYPE=MONTGOMERY_FRIENDLY;
-//	public static final long[] Modulus= {0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0x3F80FFFFL};
-//	public static final long MConst=0x3F810000L;
-
-// MS255 Modulus
-//public static final int MODTYPE= 1;
-//public static final long[] Modulus= {0xFFFFFFFFFFFD03L,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0x7FFFFFFFL};
-//public static final long MConst=0x2FDL;
-
-// MS256 Modulus
-//public static final int MODTYPE= 1;
-//public static final long[] Modulus= {0xFFFFFFFFFFFF43L,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFL};
-//public static final long MConst=0xBDL;
-
-// MF256 Modulus
-//public static final int MODTYPE= 2;
-//public static final long[] Modulus= {0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFA7FFFFL};
-//public static final long MConst=0xFFA80000L;
-
-// Brainpool
-//	public static final int MODTYPE= NOT_SPECIAL;
-//	public static final long[] Modulus= {0x13481D1F6E5377L,0xF623D526202820L,0x909D838D726E3BL,0xA1EEA9BC3E660AL,0xA9FB57DBL};
-//	public static final long MConst=0xA75590CEFD89B9L;
-
-// ANSSI
-//  public static final int MODTYPE= 0;
-//  public static final long[] Modulus= {0xFCF353D86E9C03L,0xADBCABC8CA6DE8L,0xE8CE42435B3961L,0xB3AD58F10126DL,0xF1FD178CL};
-//  public static final long MConst=0x97483A164E1155L;
-
-// BNCX Curve Modulus
-public const int MODTYPE = NOT_SPECIAL;
-public static readonly long[] Modulus = new long[] {0x6623EF5C1B55B3L,0xD6EE18093EE1BEL,0x647A6366D3243FL,0x8702A0DB0BDDFL,0x24000000L};
-public const long MConst = 0x4E205BF9789E85L;
-
-// BN Curve
-//public static final int MODTYPE=NOT_SPECIAL;
-//public static final long[] Modulus= {0x13L,0x13A7L,0x80000000086121L,0x40000001BA344DL,0x25236482L};
-//public static final long MConst=0x435E50D79435E5L;
-
-// BNT Curve
-//public static final int MODTYPE=NOT_SPECIAL;
-//public static final long[] Modulus= {0x9DBBFEEEB4A713L,0x555614F464BABEL,0x3696F8D5F06E8AL,0x6517014EFA0BABL,0x240120DBL};
-//public static final long MConst=0xC5A872D914C4E5L;
-
-// BNT2 Curve
-//public static final int MODTYPE=NOT_SPECIAL;
-//public static final long[] Modulus= {0xB2DC2BB460A48BL,0x93E428F0D651E8L,0xF3B89D00081CFL,0x410F5AADB74E20L,0x24000482L};
-//public static final long MConst=0xFE6A47A6505CDDL;
-
-// START SPECIFY CURVE DETAILS HERE
-//*********************************************************************************
-
-// Ed25519 Curve
-//	public static final int CURVETYPE=EDWARDS;
-//	public static final int CURVE_A = -1;
-//	public static final long[] CURVE_B = {0xEB4DCA135978A3L,0xA4D4141D8AB75L,0x797779E8980070L,0x2B6FFE738CC740L,0x52036CEEL};
-//	public static final long[] CURVE_Order={0x12631A5CF5D3EDL,0xF9DEA2F79CD658L,0x14DEL,0x0L,0x10000000L};
-//	public static final long[] CURVE_Gx ={0x562D608F25D51AL,0xC7609525A7B2C9L,0x31FDD6DC5C692CL,0xCD6E53FEC0A4E2L,0x216936D3L};
-//	public static final long[] CURVE_Gy ={0x66666666666658L,0x66666666666666L,0x66666666666666L,0x66666666666666L,0x66666666L};
-
-// Original Curve25519
-//	public static final int CURVETYPE=MONTGOMERY;
-//	public static final int CURVE_A =486662;
-//	public static final long[] CURVE_B = {0x0L,0x0L,0x0L,0x0L,0x0L}; // not used
-//	public static final long[] CURVE_Order={0x12631A5CF5D3EDL,0xF9DEA2F79CD658L,0x14DEL,0x0L,0x10000000L};
-//	public static final long[] CURVE_Gx ={0x9L,0x0L,0x0L,0x0L,0x0L};
-//	public static final long[] CURVE_Gy ={0x0L,0x0L,0x0L,0x0L,0x0L}; // not used
-
-// NIST-256 Curve
-//	public static final int CURVETYPE=WEIERSTRASS;
-//	public static final int CURVE_A = -3;
-//	public static final long[] CURVE_B = {0xCE3C3E27D2604BL,0x6B0CC53B0F63BL,0x55769886BC651DL,0xAA3A93E7B3EBBDL,0x5AC635D8L};
-//	public static final long[] CURVE_Order={0xB9CAC2FC632551L,0xFAADA7179E84F3L,0xFFFFFFFFFFBCE6L,0xFFFFFFL,0xFFFFFFFFL};
-//	public static final long[] CURVE_Gx ={0xA13945D898C296L,0x7D812DEB33A0F4L,0xE563A440F27703L,0xE12C4247F8BCE6L,0x6B17D1F2L};
-//	public static final long[] CURVE_Gy ={0xB6406837BF51F5L,0x33576B315ECECBL,0x4A7C0F9E162BCEL,0xFE1A7F9B8EE7EBL,0x4FE342E2L};
-
-// MF254 Modulus, Weierstrass Curve w-254-mont
-//public static final int CURVETYPE= 0;
-//public static final int CURVE_A = -3;
-//public static final long[] CURVE_B = {0xFFFFFFFFFFD08DL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0x3F80FFFFL};
-//public static final long[] CURVE_Order={0xA419C4AF8DF83FL,0x8BEA0DA375C06FL,0xFFFFFFFFFFEB81L,0xFFFFFFFFFFFFFFL,0x3F80FFFFL};
-//public static final long[] CURVE_Gx ={0x2L,0x0L,0x0L,0x0L,0x0L};
-//public static final long[] CURVE_Gy ={0x65DF37F90D4EBCL,0x38E3F8511931ADL,0x75BD778AEBDFB7L,0x3B2E56014AE15AL,0x140E3FD3L};
-
-// MF254 Modulus, Edwards Curve ed-254-mont
-//public static final int CURVETYPE= 1;
-//public static final int CURVE_A = -1;
-//public static final long[] CURVE_B = {0x367BL,0x0L,0x0L,0x0L,0x0L};
-//public static final long[] CURVE_Order={0xF3D3FEC46E98C7L,0x306C8BD62FB0EAL,0xFFFFFFFFFFEB95L,0xFFFFFFFFFFFFFFL,0xFE03FFFL};
-//public static final long[] CURVE_Gx ={0x1L,0x0L,0x0L,0x0L,0x0L};
-//public static final long[] CURVE_Gy ={0x52D0FDAF2701E5L,0x9A840E3212187CL,0xD502363F4E3632L,0xD6A4C335951D00L,0x19F0E690L};
-
-// MF254 Modulus, Montgomery Curve
-//	public static final int CURVETYPE=MONTGOMERY;
-//	public static final int CURVE_A =-55790;
-//	public static final long[] CURVE_B = {0x0L,0x0L,0x0L,0x0L,0x0L}; // not used
-//	public static final long[] CURVE_Order={0xF3D3FEC46E98C7L,0x306C8BD62FB0EAL,0xFFFFFFFFFFEB95L,0xFFFFFFFFFFFFFFL,0xFE03FFFL};
-//	public static final long[] CURVE_Gx ={0x3L,0x0L,0x0L,0x0L,0x0L};
-//	public static final long[] CURVE_Gy ={0x0L,0x0L,0x0L,0x0L,0x0L}; // not used
-
-// MS255 Modulus, Weierstrass Curve
-//public static final int CURVETYPE= 0;
-//public static final int CURVE_A = -3;
-//public static final long[] CURVE_B = {0xFFFFFFFFFFAB46L,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0x7FFFFFFFL};
-//public static final long[] CURVE_Order={0x8FAC983C594AEBL,0x38283AD2B3DFABL,0xFFFFFFFFFF864AL,0xFFFFFFFFFFFFFFL,0x7FFFFFFFL};
-//public static final long[] CURVE_Gx ={0x1L,0x0L,0x0L,0x0L,0x0L};
-//public static final long[] CURVE_Gy ={0x33FF6769CB44BAL,0xC78CDDFDA60D17L,0xF9B2FF7D177DB6L,0xEDBA7833921EBFL,0x6F7A6AC0L};
-
-// MS255 Modulus, Edwards Curve
-//public static final int CURVETYPE= 1;
-//public static final int CURVE_A = -1;
-//public static final long[] CURVE_B = {0xEA97L,0x0L,0x0L,0x0L,0x0L};
-//public static final long[] CURVE_Order={0x49D1ED0436EB75L,0xA785EDA6832EACL,0xFFFFFFFFFFDCF1L,0xFFFFFFFFFFFFFFL,0x1FFFFFFFL};
-//public static final long[] CURVE_Gx ={0x4L,0x0L,0x0L,0x0L,0x0L};
-//public static final long[] CURVE_Gy ={0x2A255BD08736A0L,0x4B8AED445A45BAL,0xDD8E0C47E55291L,0x4A7BB545EC254CL,0x26CB7853L};
-
-// MS255 Modulus, Montgomery Curve
-//	public static final int CURVETYPE=MONTGOMERY;
-//	public static final int CURVE_A =-240222;
-//	public static final long[] CURVE_B = {0x0L,0x0L,0x0L,0x0L,0x0L}; // not used
-//	public static final long[] CURVE_Order={0x49D1ED0436EB75L,0xA785EDA6832EACL,0xFFFFFFFFFFDCF1L,0xFFFFFFFFFFFFFFL,0x1FFFFFFFL};
-//	public static final long[] CURVE_Gx ={0x4L,0x0L,0x0L,0x0L,0x0L};
-//	public static final long[] CURVE_Gy ={0x0L,0x0L,0x0L,0x0L,0x0L}; // not used
-
-// MS256, Weierstrass Curve
-//public static final int CURVETYPE= 0;
-//public static final int CURVE_A = -3;
-//public static final long[] CURVE_B = {0x25581L,0x0L,0x0L,0x0L,0x0L};
-//public static final long[] CURVE_Order={0xAB20294751A825L,0x8275EA265C6020L,0xFFFFFFFFFFE43CL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFL};
-//public static final long[] CURVE_Gx ={0x1L,0x0L,0x0L,0x0L,0x0L};
-//public static final long[] CURVE_Gy ={0xF46306C2B56C77L,0x2F9375894EC10BL,0x6CCEEEDD6BD02CL,0xC1E466D7FC82C9L,0x696F1853L};
-
-// MS256, Edwards Curve
-//public static final int CURVETYPE= 1;
-//public static final int CURVE_A = -1;
-//public static final long[] CURVE_B = {0x3BEEL,0x0L,0x0L,0x0L,0x0L};
-//public static final long[] CURVE_Order={0xB84E6F1122B4ADL,0xA55AD0A6BC64E5L,0xFFFFFFFFFFBE6AL,0xFFFFFFFFFFFFFFL,0x3FFFFFFFL};
-//public static final long[] CURVE_Gx ={0xDL,0x0L,0x0L,0x0L,0x0L};
-//public static final long[] CURVE_Gy ={0x7F6FB5331CADBAL,0x6D63824D303F70L,0xB39FA046BFBE2AL,0x2A1276DBA3D330L,0x7D0AB41EL};
-
-// MS256 Modulus, Montgomery Curve
-//	public static final int CURVETYPE=MONTGOMERY;
-//	public static final int CURVE_A =-61370;
-//	public static final long[] CURVE_B = {0x0L,0x0L,0x0L,0x0L,0x0L}; // not used
-//  public static final long[] CURVE_Order={0xB84E6F1122B4ADL,0xA55AD0A6BC64E5L,0xFFFFFFFFFFBE6AL,0xFFFFFFFFFFFFFFL,0x3FFFFFFFL};
-//	public static final long[] CURVE_Gx ={0xbL,0x0L,0x0L,0x0L,0x0L};
-//	public static final long[] CURVE_Gy ={0x0L,0x0L,0x0L,0x0L,0x0L}; // not used
-
-// MF256 Modulus, Weierstrass Curve
-//public static final int CURVETYPE= 0;
-//public static final int CURVE_A = -3;
-//public static final long[] CURVE_B = {0x14E6AL,0x0L,0x0L,0x0L,0x0L};
-//public static final long[] CURVE_Order={0x10C5E1A79857EBL,0x7513E6E5074B9DL,0xFFFFFFFFFFFC51L,0xFFFFFFFFFFFFFFL,0xFFA7FFFFL};
-//public static final long[] CURVE_Gx ={0x1L,0x0L,0x0L,0x0L,0x0L};
-//public static final long[] CURVE_Gy ={0x7954C2B724D2AL,0x47EB8D94DC6610L,0x26123DAE289569L,0xBE1808CE7BABBAL,0x20887C87L};
-
-// MF256, Edwards Curve
-//public static final int CURVETYPE= 1;
-//public static final int CURVE_A = -1;
-//public static final long[] CURVE_B = {0x350AL,0x0L,0x0L,0x0L,0x0L};
-//public static final long[] CURVE_Order={0xD92EDED8EC7BABL,0xBBAFB86733C966L,0xFFFFFFFFFFB154L,0xFFFFFFFFFFFFFFL,0x3FE9FFFFL};
-//public static final long[] CURVE_Gx ={0x1L,0x0L,0x0L,0x0L,0x0L};
-//public static final long[] CURVE_Gy ={0xEAA722F2F3C908L,0x5E648DFEA68D7DL,0xF3DB2C1AACA0C0L,0xF8CC4D5AEAEBEEL,0xDAD8D4F8L};
-
-// MF256 Modulus, Montgomery Curve
-//	public static final int CURVETYPE=MONTGOMERY;
-//	public static final int CURVE_A =-54314;
-//	public static final long[] CURVE_B = {0x0L,0x0L,0x0L,0x0L,0x0L}; // not used
-//  public static final long[] CURVE_Order={0xD92EDED8EC7BABL,0xBBAFB86733C966L,0xFFFFFFFFFFB154L,0xFFFFFFFFFFFFFFL,0x3FE9FFFFL};
-//	public static final long[] CURVE_Gx ={0x8L,0x0L,0x0L,0x0L,0x0L};
-//	public static final long[] CURVE_Gy ={0x0L,0x0L,0x0L,0x0L,0x0L}; // not used
-
-
-
-// Brainpool
-//	public static final int CURVETYPE= 0;
-//	public static final int CURVE_A = -3;
-//	public static final long[] CURVE_B = {0xE58101FEE92B04L,0xEBC4AF2F49256AL,0x733D0B76B7BF93L,0x30D84EA4FE66A7L,0x662C61C4L};
-//	public static final long[] CURVE_Order={0x1E0E82974856A7L,0x7AA3B561A6F790L,0x909D838D718C39L,0xA1EEA9BC3E660AL,0xA9FB57DBL};
-//	public static final long[] CURVE_Gx ={0xA191562E1305F4L,0x42C47AAFBC2B79L,0xB23A656149AFA1L,0xC1CFE7B7732213L,0xA3E8EB3CL};
-//	public static final long[] CURVE_Gy ={0xABE8F35B25C9BEL,0xB6DE39D027001DL,0xE14644417E69BCL,0x3439C56D7F7B22L,0x2D996C82L};
-
-// ANSSI
-//  public static final int CURVETYPE= 0;
-//  public static final int CURVE_A = -3;
-//  public static final long[] CURVE_B = {0x75ED967B7BB73FL,0xC9AE4B1A18030L,0x754A44C00FDFECL,0x5428A9300D4ABAL,0xEE353FCAL};
-//  public static final long[] CURVE_Order={0xFDD459C6D655E1L,0x67E140D2BF941FL,0xE8CE42435B53DCL,0xB3AD58F10126DL,0xF1FD178CL};
-//  public static final long[] CURVE_Gx ={0xC97A2DD98F5CFFL,0xD2DCAF98B70164L,0x4749D423958C27L,0x56C139EB31183DL,0xB6B3D4C3L};
-//  public static final long[] CURVE_Gy ={0x115A1554062CFBL,0xC307E8E4C9E183L,0xF0F3ECEF8C2701L,0xC8B204911F9271L,0x6142E0F7L};
-
-// BNCX Curve
-
-	public const int CURVETYPE = WEIERSTRASS;
-	public const int CURVE_A = 0;
-	public static readonly long[] CURVE_B = new long[] {0x2L,0x0L,0x0L,0x0L,0x0L};
-	public static readonly long[] CURVE_Order = new long[] {0x11C0A636EB1F6DL,0xD6EE0CC906CEBEL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L};
-	public static readonly long[] CURVE_Bnx = new long[] {0x3C012B1L,0x40L,0x0L,0x0L,0x0L};
-	public static readonly long[] CURVE_Cru = new long[] {0xE0931794235C97L,0xDF6471EF875631L,0xCA83F1440BDL,0x480000L,0x0L};
-	public static readonly long[] CURVE_Fra = new long[] {0xD9083355C80EA3L,0x7326F173F8215BL,0x8AACA718986867L,0xA63A0164AFE18BL,0x1359082FL};
-	public static readonly long[] CURVE_Frb = new long[] {0x8D1BBC06534710L,0x63C7269546C062L,0xD9CDBC4E3ABBD8L,0x623628A900DC53L,0x10A6F7D0L};
-	public static readonly long[] CURVE_Pxa = new long[] {0x851CEEE4D2EC74L,0x85BFA03E2726C0L,0xF5C34BBB907CL,0x7053B256358B25L,0x19682D2CL};
-	public static readonly long[] CURVE_Pxb = new long[] {0xA58E8B2E29CFE1L,0x97B0C209C30F47L,0x37A8E99743F81BL,0x3E19F64AA011C9L,0x1466B9ECL};
-	public static readonly long[] CURVE_Pya = new long[] {0xFBFCEBCF0BE09FL,0xB33D847EC1B30CL,0x157DAEE2096361L,0x72332B8DD81E22L,0xA79EDD9L};
-	public static readonly long[] CURVE_Pyb = new long[] {0x904B228898EE9DL,0x4EA569D2EDEBEDL,0x512D8D3461C286L,0xECC4C09035C6E4L,0x6160C39L};
-	public static readonly long[] CURVE_Gx = new long[] {0x6623EF5C1B55B2L,0xD6EE18093EE1BEL,0x647A6366D3243FL,0x8702A0DB0BDDFL,0x24000000L};
-	public static readonly long[] CURVE_Gy = new long[] {0x1L,0x0L,0x0L,0x0L,0x0L};
-	public static readonly long[][] CURVE_W = new long[][]
-	{
-		new long[] {0x546349162FEB83L,0xB40381200L,0x6000L,0x0L,0x0L},
-		new long[] {0x7802561L,0x80L,0x0L,0x0L,0x0L}
-	};
-	public static readonly long[][][] CURVE_SB = new long[][][]
-	{
-		new long[][]
-		{
-			new long[] {0x5463491DB010E4L,0xB40381280L,0x6000L,0x0L,0x0L},
-			new long[] {0x7802561L,0x80L,0x0L,0x0L,0x0L}
-		},
-		new long[][]
-		{
-			new long[] {0x7802561L,0x80L,0x0L,0x0L,0x0L},
-			new long[] {0xBD5D5D20BB33EAL,0xD6EE0188CEBCBDL,0x647A6366D2643FL,0x8702A0DB0BDDFL,0x24000000L}
-		}
-	};
-	public static readonly long[][] CURVE_WB = new long[][]
-	{
-		new long[] {0x1C2118567A84B0L,0x3C012B040L,0x2000L,0x0L,0x0L},
-		new long[] {0xCDF995BE220475L,0x94EDA8CA7F9A36L,0x8702A0DC07EL,0x300000L,0x0L},
-		new long[] {0x66FCCAE0F10B93L,0x4A76D4653FCD3BL,0x4381506E03FL,0x180000L,0x0L},
-		new long[] {0x1C21185DFAAA11L,0x3C012B0C0L,0x2000L,0x0L,0x0L}
-	};
-	public static readonly long[][][] CURVE_BB = new long[][][]
-	{
-		new long[][]
-		{
-			new long[] {0x11C0A6332B0CBDL,0xD6EE0CC906CE7EL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L},
-			new long[] {0x11C0A6332B0CBCL,0xD6EE0CC906CE7EL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L},
-			new long[] {0x11C0A6332B0CBCL,0xD6EE0CC906CE7EL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L},
-			new long[] {0x7802562L,0x80L,0x0L,0x0L,0x0L}
-		},
-		new long[][]
-		{
-			new long[] {0x7802561L,0x80L,0x0L,0x0L,0x0L},
-			new long[] {0x11C0A6332B0CBCL,0xD6EE0CC906CE7EL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L},
-			new long[] {0x11C0A6332B0CBDL,0xD6EE0CC906CE7EL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L},
-			new long[] {0x11C0A6332B0CBCL,0xD6EE0CC906CE7EL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L}
-		},
-		new long[][]
-		{
-			new long[] {0x7802562L,0x80L,0x0L,0x0L,0x0L},
-			new long[] {0x7802561L,0x80L,0x0L,0x0L,0x0L},
-			new long[] {0x7802561L,0x80L,0x0L,0x0L,0x0L},
-			new long[] {0x7802561L,0x80L,0x0L,0x0L,0x0L}
-		},
-		new long[][]
-		{
-			new long[] {0x3C012B2L,0x40L,0x0L,0x0L,0x0L},
-			new long[] {0xF004AC2L,0x100L,0x0L,0x0L,0x0L},
-			new long[] {0x11C0A62F6AFA0AL,0xD6EE0CC906CE3EL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L},
-			new long[] {0x3C012B2L,0x40L,0x0L,0x0L,0x0L}
-		}
-	};
-
-	public const bool USE_GLV = true;
-	public const bool USE_GS_G2 = true;
-	public const bool USE_GS_GT = true;
-	public const bool GT_STRONG = true;
-
-// BNT Curve
-/*
-public static final int CURVETYPE=WEIERSTRASS;
-public static final int CURVE_A = 0;
-public static final long[] CURVE_B = {0x2L,0x0L,0x0L,0x0L,0x0L};
-public static final long[] CURVE_Order={0x75777E8D30210DL,0xD43492B2CB363AL,0x3696F8D5F00E88L,0x6517014EFA0BABL,0x240120DBL};
-public static final long[] CURVE_Bnx={0x806000004081L,0x40L,0x0L,0x0L,0x0L};
-public static final long[] CURVE_Cru={0xEB53D5AB4FCD87L,0x82A5F2BAB11FADL,0x47651504C9764CL,0x4801B1L,0x0L};
-public static final long[] CURVE_Fra={0xF5D14EADC80022L,0x4904D6FACCE359L,0xF190A13211BE6CL,0xC9BBC4394F6509L,0x1328A292L};
-public static final long[] CURVE_Frb={0xA7EAB040ECA6F1L,0xC513DF997D764L,0x450657A3DEB01EL,0x9B5B3D15AAA6A1L,0x10D87E48L};
-public static final long[] CURVE_Pxa={0x8987E2288E65BBL,0xAD1CAA6313BEL,0x325041548B7CCCL,0x4C1339EBCC055L,0x14483FCDL};
-public static final long[] CURVE_Pxb={0x67888808DBE2C0L,0x7FE1F81E34853AL,0xA631A51B57B95L,0x384EC302DA3FC5L,0x87F46B3L};
-public static final long[] CURVE_Pya={0x202C47E020CA1DL,0xB4167E8399F36CL,0xC6E5439F72C94CL,0x102B0BD74A2C69L,0x14E8C29CL};
-public static final long[] CURVE_Pyb={0xD8437C716628F2L,0x27E167BCB7DC6BL,0xA82C7572681D0AL,0x62454BD1EDEC18L,0x17AFE2A4L};
-public static final long[] CURVE_Gx ={0x9DBBFEEEB4A712L,0x555614F464BABEL,0x3696F8D5F06E8AL,0x6517014EFA0BABL,0x240120DBL};
-public static final long[] CURVE_Gy ={0x1L,0x0L,0x0L,0x0L,0x0L};
-public static final long[][] CURVE_W={{0x26430061838403L,0x81218241998384L,0x6001L,0x0L,0x0L},{0x100C000008101L,0x80L,0x0L,0x0L,0x0L}};
-public static final long[][][] CURVE_SB={{{0x2743C061840504L,0x81218241998404L,0x6001L,0x0L,0x0L},{0x100C000008101L,0x80L,0x0L,0x0L,0x0L}},{{0x100C000008101L,0x80L,0x0L,0x0L,0x0L},{0x4F347E2BAC9D0AL,0x5313107131B2B6L,0x3696F8D5EFAE87L,0x6517014EFA0BABL,0x240120DBL}}};
-public static final long[][] CURVE_WB={{0x6140602080C080L,0x806080C08880C1L,0x2000L,0x0L,0x0L},{0xB53904088C4A85L,0xAD2FA352DC6C36L,0xDA436358868EDEL,0x300120L,0x0L},{0x5ADCB204464583L,0x5697D1A96E363BL,0x6D21B1AC43476FL,0x180090L,0x0L},{0x62412020814181L,0x806080C0888141L,0x2000L,0x0L,0x0L}};
-public static final long[][][] CURVE_BB={{{0x74F71E8D2FE08DL,0xD43492B2CB35FAL,0x3696F8D5F00E88L,0x6517014EFA0BABL,0x240120DBL},{0x74F71E8D2FE08CL,0xD43492B2CB35FAL,0x3696F8D5F00E88L,0x6517014EFA0BABL,0x240120DBL},{0x74F71E8D2FE08CL,0xD43492B2CB35FAL,0x3696F8D5F00E88L,0x6517014EFA0BABL,0x240120DBL},{0x100C000008102L,0x80L,0x0L,0x0L,0x0L}},{{0x100C000008101L,0x80L,0x0L,0x0L,0x0L},{0x74F71E8D2FE08CL,0xD43492B2CB35FAL,0x3696F8D5F00E88L,0x6517014EFA0BABL,0x240120DBL},{0x74F71E8D2FE08DL,0xD43492B2CB35FAL,0x3696F8D5F00E88L,0x6517014EFA0BABL,0x240120DBL},{0x74F71E8D2FE08CL,0xD43492B2CB35FAL,0x3696F8D5F00E88L,0x6517014EFA0BABL,0x240120DBL}},{{0x100C000008102L,0x80L,0x0L,0x0L,0x0L},{0x100C000008101L,0x80L,0x0L,0x0L,0x0L},{0x100C000008101L,0x80L,0x0L,0x0L,0x0L},{0x100C000008101L,0x80L,0x0L,0x0L,0x0L}},{{0x806000004082L,0x40L,0x0L,0x0L,0x0L},{0x2018000010202L,0x100L,0x0L,0x0L,0x0L},{0x7476BE8D2FA00AL,0xD43492B2CB35BAL,0x3696F8D5F00E88L,0x6517014EFA0BABL,0x240120DBL},{0x806000004082L,0x40L,0x0L,0x0L,0x0L}}};
-
-*/
-
-// BNT2 Curve
-/*
-	public static final int CURVETYPE=WEIERSTRASS;
-	public static final int CURVE_A = 0;
-	public static final long[] CURVE_B = {0x2L,0x0L,0x0L,0x0L,0x0L};
-	public static final long[] CURVE_Order={0xFB71A511AA2BF5L,0x8DE127B73833D7L,0xF3B89D00021CFL,0x410F5AADB74E20L,0x24000482L};
-	public static final long[] CURVE_Bnx={0x20100608205L,0x40L,0x0L,0x0L,0x0L};
-	public static final long[] CURVE_Cru={0x5027444866BD33L,0x5B773016470EFBL,0xC3617BECF23675L,0x480006L,0x0L};
-	public static final long[] CURVE_Fra={0xB268C973AEF062L,0xC69B33C3BCE492L,0xF67FA37F195BBCL,0x29E8CAB6BD0A41L,0x124E0B8DL};
-	public static final long[] CURVE_Frb={0x736240B1B429L,0xCD48F52D196D56L,0x18BBE650E72612L,0x17268FF6FA43DEL,0x11B1F8F5L};
-	public static final long[] CURVE_Pxa={0xCC92399F40A3C8L,0xCDA4E96611784AL,0x7B056961706B35L,0x9693C6318279D7L,0x16FC17CFL};
-	public static final long[] CURVE_Pxb={0x557A8AD8549540L,0x6F7BE6F6510610L,0x565907A95D17DBL,0xBD5975909C8188L,0x1EB5B500L};
-	public static final long[] CURVE_Pya={0x7BECC514220513L,0x4A78860E737B14L,0x51B83935F12684L,0x761422AA9D4DFAL,0x1E8EE498L};
-	public static final long[] CURVE_Pyb={0xB9328F577CE78EL,0xB746E26FA5781FL,0xA93DBC1FB8E27EL,0xBAE33BDBA29D76L,0x23CEF4CDL};
-	public static final long[] CURVE_Gx ={0xB2DC2BB460A48AL,0x93E428F0D651E8L,0xF3B89D00081CFL,0x410F5AADB74E20L,0x24000482L};
-	public static final long[] CURVE_Gy ={0x1L,0x0L,0x0L,0x0L,0x0L};
-	public static final long[][] CURVE_W={{0xB76282A1347083L,0x60301399E1D10L,0x6000L,0x0L,0x0L},{0x40200C10409L,0x80L,0x0L,0x0L,0x0L}};
-	public static final long[][][] CURVE_SB={{{0xB76684A1F5748CL,0x60301399E1D90L,0x6000L,0x0L,0x0L},{0x40200C10409L,0x80L,0x0L,0x0L,0x0L}},{{0x40200C10409L,0x80L,0x0L,0x0L,0x0L},{0x440F227075BB72L,0x87DE267D9A16C7L,0xF3B89CFFFC1CFL,0x410F5AADB74E20L,0x24000482L}}};
-	public static final long[][] CURVE_WB={{0x9272D48A70A224L,0x20100688A0945L,0x2000L,0x0L,0x0L},{0x5A572CF030EF19L,0x9651763543721DL,0x8240FD48A1B9A3L,0x300004L,0x0L},{0xAD2C96F848B88FL,0xCB28BB1AA1B92EL,0x41207EA450DCD1L,0x180002L,0x0L},{0x9276D68B31A62DL,0x20100688A09C5L,0x2000L,0x0L,0x0L}};
-	public static final long[][][] CURVE_BB={{{0xFB6FA41149A9F1L,0x8DE127B7383397L,0xF3B89D00021CFL,0x410F5AADB74E20L,0x24000482L},{0xFB6FA41149A9F0L,0x8DE127B7383397L,0xF3B89D00021CFL,0x410F5AADB74E20L,0x24000482L},{0xFB6FA41149A9F0L,0x8DE127B7383397L,0xF3B89D00021CFL,0x410F5AADB74E20L,0x24000482L},{0x40200C1040AL,0x80L,0x0L,0x0L,0x0L}},{{0x40200C10409L,0x80L,0x0L,0x0L,0x0L},{0xFB6FA41149A9F0L,0x8DE127B7383397L,0xF3B89D00021CFL,0x410F5AADB74E20L,0x24000482L},{0xFB6FA41149A9F1L,0x8DE127B7383397L,0xF3B89D00021CFL,0x410F5AADB74E20L,0x24000482L},{0xFB6FA41149A9F0L,0x8DE127B7383397L,0xF3B89D00021CFL,0x410F5AADB74E20L,0x24000482L}},{{0x40200C1040AL,0x80L,0x0L,0x0L,0x0L},{0x40200C10409L,0x80L,0x0L,0x0L,0x0L},{0x40200C10409L,0x80L,0x0L,0x0L,0x0L},{0x40200C10409L,0x80L,0x0L,0x0L,0x0L}},{{0x20100608206L,0x40L,0x0L,0x0L,0x0L},{0x80401820812L,0x100L,0x0L,0x0L,0x0L},{0xFB6DA310E927EAL,0x8DE127B7383357L,0xF3B89D00021CFL,0x410F5AADB74E20L,0x24000482L},{0x20100608206L,0x40L,0x0L,0x0L,0x0L}}};
-*/
-
-// BN Curve
-/*
-public static final int CURVETYPE=WEIERSTRASS;
-public static final int CURVE_A = 0;
-public static final long[] CURVE_B = {0x2L,0x0L,0x0L,0x0L,0x0L};
-public static final long[] CURVE_Order={0xDL,0x800000000010A1L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L};
-public static final long[] CURVE_Bnx={0x80000000000001L,0x40L,0x0L,0x0L,0x0L};
-public static final long[] CURVE_Cru={0x80000000000007L,0x6CDL,0x40000000024909L,0x49B362L,0x0L};
-public static final long[] CURVE_Fra={0x7DE6C06F2A6DE9L,0x74924D3F77C2E1L,0x50A846953F8509L,0x212E7C8CB6499BL,0x1B377619L};
-public static final long[] CURVE_Frb={0x82193F90D5922AL,0x8B6DB2C08850C5L,0x2F57B96AC8DC17L,0x1ED1837503EAB2L,0x9EBEE69L};
-public static final long[] CURVE_Pxa={0xAB2C7935FD0CB4L,0xE319E4FCC57C2BL,0x24F6DF763B05A5L,0xF55EA7EA335FB7L,0x95B04D4L};
-public static final long[] CURVE_Pxb={0xA07D0790962455L,0x86BE3D27AA5E38L,0x89E05747F39D6DL,0xC08347B49D42BFL,0x5D4D8A7L};
-public static final long[] CURVE_Pya={0xADCE687A08A46CL,0x2B30E98A4191F9L,0x4C3784B1F16908L,0x25E5313FA16D1CL,0xABF2ABFL};
-public static final long[] CURVE_Pyb={0xDF88D405F306ECL,0x82076ADD13A0E6L,0x1E47819D6A5C04L,0xE679DABDB38627L,0x18769A87L};
-public static final long[] CURVE_Gx ={0x12L,0x13A7L,0x80000000086121L,0x40000001BA344DL,0x25236482L};
-public static final long[] CURVE_Gy ={0x1L,0x0L,0x0L,0x0L,0x0L};
-public static final long[][] CURVE_W={{0x3L,0x80000000000204L,0x6181L,0x0L,0x0L},{0x1L,0x81L,0x0L,0x0L,0x0L}};
-public static final long[][][] CURVE_SB={{{0x4L,0x80000000000285L,0x6181L,0x0L,0x0L},{0x1L,0x81L,0x0L,0x0L,0x0L}},{{0x1L,0x81L,0x0L,0x0L,0x0L},{0xAL,0xE9DL,0x80000000079E1EL,0x40000001BA344DL,0x25236482L}}};
-public static final long[][] CURVE_WB={{0x80000000000000L,0x80000000000040L,0x2080L,0x0L,0x0L},{0x80000000000005L,0x54AL,0x8000000001C707L,0x312241L,0x0L},{0x80000000000003L,0x800000000002C5L,0xC000000000E383L,0x189120L,0x0L},{0x80000000000001L,0x800000000000C1L,0x2080L,0x0L,0x0L}};
-public static final long[][][] CURVE_BB={{{0x8000000000000DL,0x80000000001060L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L},{0x8000000000000CL,0x80000000001060L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L},{0x8000000000000CL,0x80000000001060L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L},{0x2L,0x81L,0x0L,0x0L,0x0L}},{{0x1L,0x81L,0x0L,0x0L,0x0L},{0x8000000000000CL,0x80000000001060L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L},{0x8000000000000DL,0x80000000001060L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L},{0x8000000000000CL,0x80000000001060L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L}},{{0x2L,0x81L,0x0L,0x0L,0x0L},{0x1L,0x81L,0x0L,0x0L,0x0L},{0x1L,0x81L,0x0L,0x0L,0x0L},{0x1L,0x81L,0x0L,0x0L,0x0L}},{{0x80000000000002L,0x40L,0x0L,0x0L,0x0L},{0x2L,0x102L,0x0L,0x0L,0x0L},{0xAL,0x80000000001020L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L},{0x80000000000002L,0x40L,0x0L,0x0L,0x0L}}};
-
-*/
-
-//	public static boolean debug=false;
-
-}
diff --git a/cs/RSA.cs b/cs/RSA.cs
deleted file mode 100644
index 20c7dcf..0000000
--- a/cs/RSA.cs
+++ /dev/null
@@ -1,443 +0,0 @@
-using System;
-
-/*
-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.
-*/
-
-/* RSA API high-level functions  */
-
-public sealed class rsa_private_key
-{
-	public FF p, q, dp, dq, c;
-
-	public rsa_private_key(int n)
-	{
-		p = new FF(n);
-		q = new FF(n);
-		dp = new FF(n);
-		dq = new FF(n);
-		c = new FF(n);
-	}
-}
-
-public sealed class rsa_public_key
-{
-	public int e;
-	public FF n;
-
-	public rsa_public_key(int m)
-	{
-		e = 0;
-		n = new FF(m);
-	}
-}
-
-public sealed class RSA
-{
-
-	public static readonly int RFS = ROM.MODBYTES * ROM.FFLEN;
-
-/* generate an RSA key pair */
-
-	public static void KEY_PAIR(RAND rng, int e, rsa_private_key PRIV, rsa_public_key PUB)
-	{ // IEEE1363 A16.11/A16.12 more or less
-		int n = PUB.n.getlen() / 2;
-		FF t = new FF(n);
-		FF p1 = new FF(n);
-		FF q1 = new FF(n);
-
-		for (;;)
-		{
-
-			PRIV.p.random(rng);
-			while (PRIV.p.lastbits(2) != 3)
-			{
-				PRIV.p.inc(1);
-			}
-			while (!FF.prime(PRIV.p,rng))
-			{
-				PRIV.p.inc(4);
-			}
-
-			p1.copy(PRIV.p);
-			p1.dec(1);
-
-			if (p1.cfactor(e))
-			{
-				continue;
-			}
-			break;
-		}
-
-		for (;;)
-		{
-			PRIV.q.random(rng);
-			while (PRIV.q.lastbits(2) != 3)
-			{
-				PRIV.q.inc(1);
-			}
-			while (!FF.prime(PRIV.q,rng))
-			{
-				PRIV.q.inc(4);
-			}
-
-			q1.copy(PRIV.q);
-			q1.dec(1);
-
-			if (q1.cfactor(e))
-			{
-				continue;
-			}
-
-			break;
-		}
-
-		PUB.n = FF.mul(PRIV.p,PRIV.q);
-		PUB.e = e;
-
-		t.copy(p1);
-		t.shr();
-		PRIV.dp.set(e);
-		PRIV.dp.invmodp(t);
-		if (PRIV.dp.parity() == 0)
-		{
-			PRIV.dp.add(t);
-		}
-		PRIV.dp.norm();
-
-		t.copy(q1);
-		t.shr();
-		PRIV.dq.set(e);
-		PRIV.dq.invmodp(t);
-		if (PRIV.dq.parity() == 0)
-		{
-			PRIV.dq.add(t);
-		}
-		PRIV.dq.norm();
-
-		PRIV.c.copy(PRIV.p);
-		PRIV.c.invmodp(PRIV.q);
-
-		return;
-	}
-
-/* Mask Generation Function */
-
-	public static void MGF1(sbyte[] Z, int olen, sbyte[] K)
-	{
-		HASH H = new HASH();
-		int hlen = HASH.len;
-		sbyte[] B = new sbyte[hlen];
-
-		int counter , cthreshold , k = 0;
-		for (int i = 0;i < K.Length;i++)
-		{
-			K[i] = 0;
-		}
-
-		cthreshold = olen / hlen;
-		if (olen % hlen != 0)
-		{
-			cthreshold++;
-		}
-		for (counter = 0;counter < cthreshold;counter++)
-		{
-			H.process_array(Z);
-			H.process_num(counter);
-			B = H.hash();
-
-			if (k + hlen > olen)
-			{
-				for (int i = 0;i < olen % hlen;i++)
-				{
-					K[k++] = B[i];
-				}
-			}
-			else
-			{
-				for (int i = 0;i < hlen;i++)
-				{
-					K[k++] = B[i];
-				}
-			}
-		}
-	}
-
-	public static void printBinary(sbyte[] array)
-	{
-		int i;
-		for (i = 0;i < array.Length;i++)
-		{
-			Console.Write("{0:x2}", array[i]);
-		}
-		Console.WriteLine();
-	}
-
-	/* OAEP Message Encoding for Encryption */
-	public static sbyte[] OAEP_ENCODE(sbyte[] m, RAND rng, sbyte[] p)
-	{
-		int i , slen , olen = RFS - 1;
-		int mlen = m.Length;
-		int hlen, seedlen;
-		sbyte[] f = new sbyte[RFS];
-
-		HASH H = new HASH();
-		hlen = HASH.len;
-		sbyte[] SEED = new sbyte[hlen];
-		seedlen = hlen;
-		if (mlen > olen - hlen - seedlen - 1)
-		{
-			return new sbyte[0];
-		}
-
-		sbyte[] DBMASK = new sbyte[olen - seedlen];
-
-		if (p != null)
-		{
-			H.process_array(p);
-		}
-		sbyte[] h = H.hash();
-		for (i = 0;i < hlen;i++)
-		{
-			f[i] = h[i];
-		}
-
-		slen = olen - mlen - hlen - seedlen - 1;
-
-		for (i = 0;i < slen;i++)
-		{
-			f[hlen + i] = 0;
-		}
-		f[hlen + slen] = 1;
-		for (i = 0;i < mlen;i++)
-		{
-			f[hlen + slen + 1 + i] = m[i];
-		}
-
-		for (i = 0;i < seedlen;i++)
-		{
-			SEED[i] = (sbyte)rng.Byte;
-		}
-		MGF1(SEED,olen - seedlen,DBMASK);
-
-		for (i = 0;i < olen - seedlen;i++)
-		{
-			DBMASK[i] ^= f[i];
-		}
-		MGF1(DBMASK,seedlen,f);
-
-		for (i = 0;i < seedlen;i++)
-		{
-			f[i] ^= SEED[i];
-		}
-
-		for (i = 0;i < olen - seedlen;i++)
-		{
-			f[i + seedlen] = DBMASK[i];
-		}
-
-		/* pad to length RFS */
-		int d = 1;
-		for (i = RFS - 1;i >= d;i--)
-		{
-			f[i] = f[i - d];
-		}
-		for (i = d - 1;i >= 0;i--)
-		{
-			f[i] = 0;
-		}
-
-		return f;
-	}
-
-	/* OAEP Message Decoding for Decryption */
-	public static sbyte[] OAEP_DECODE(sbyte[] p, sbyte[] f)
-	{
-		int x, t;
-		bool comp;
-		int i , k , olen = RFS - 1;
-		int hlen, seedlen;
-
-		HASH H = new HASH();
-		hlen = HASH.len;
-		sbyte[] SEED = new sbyte[hlen];
-		seedlen = hlen;
-		sbyte[] CHASH = new sbyte[hlen];
-
-		if (olen < seedlen + hlen + 1)
-		{
-			return new sbyte[0];
-		}
-		sbyte[] DBMASK = new sbyte[olen - seedlen];
-		for (i = 0;i < olen - seedlen;i++)
-		{
-			DBMASK[i] = 0;
-		}
-
-		if (f.Length < RFS)
-		{
-			int d = RFS - f.Length;
-			for (i = RFS - 1;i >= d;i--)
-			{
-				f[i] = f[i - d];
-			}
-			for (i = d - 1;i >= 0;i--)
-			{
-				f[i] = 0;
-			}
-
-		}
-
-		if (p != null)
-		{
-			H.process_array(p);
-		}
-		sbyte[] h = H.hash();
-		for (i = 0;i < hlen;i++)
-		{
-			CHASH[i] = h[i];
-		}
-
-		x = f[0];
-
-		for (i = seedlen;i < olen;i++)
-		{
-			DBMASK[i - seedlen] = f[i + 1];
-		}
-
-		MGF1(DBMASK,seedlen,SEED);
-		for (i = 0;i < seedlen;i++)
-		{
-			SEED[i] ^= f[i + 1];
-		}
-		MGF1(SEED,olen - seedlen,f);
-		for (i = 0;i < olen - seedlen;i++)
-		{
-			DBMASK[i] ^= f[i];
-		}
-
-		comp = true;
-		for (i = 0;i < hlen;i++)
-		{
-			if (CHASH[i] != DBMASK[i])
-			{
-				comp = false;
-			}
-		}
-
-		for (i = 0;i < olen - seedlen - hlen;i++)
-		{
-			DBMASK[i] = DBMASK[i + hlen];
-		}
-
-		for (i = 0;i < hlen;i++)
-		{
-			SEED[i] = CHASH[i] = 0;
-		}
-
-		for (k = 0;;k++)
-		{
-			if (k >= olen - seedlen - hlen)
-			{
-				return new sbyte[0];
-			}
-			if (DBMASK[k] != 0)
-			{
-				break;
-			}
-		}
-
-		t = DBMASK[k];
-		if (!comp || x != 0 || t != 0x01)
-		{
-			for (i = 0;i < olen - seedlen;i++)
-			{
-				DBMASK[i] = 0;
-			}
-			return new sbyte[0];
-		}
-
-		sbyte[] r = new sbyte[olen - seedlen - hlen - k - 1];
-
-		for (i = 0;i < olen - seedlen - hlen - k - 1;i++)
-		{
-			r[i] = DBMASK[i + k + 1];
-		}
-
-		for (i = 0;i < olen - seedlen;i++)
-		{
-			DBMASK[i] = 0;
-		}
-
-		return r;
-	}
-
-	/* destroy the Private Key structure */
-	public static void PRIVATE_KEY_KILL(rsa_private_key PRIV)
-	{
-		PRIV.p.zero();
-		PRIV.q.zero();
-		PRIV.dp.zero();
-		PRIV.dq.zero();
-		PRIV.c.zero();
-	}
-
-	/* RSA encryption with the public key */
-	public static void ENCRYPT(rsa_public_key PUB, sbyte[] F, sbyte[] G)
-	{
-		int n = PUB.n.getlen();
-		FF f = new FF(n);
-
-		FF.fromBytes(f,F);
-		f.power(PUB.e,PUB.n);
-		f.toBytes(G);
-	}
-
-	/* RSA decryption with the private key */
-	public static void DECRYPT(rsa_private_key PRIV, sbyte[] G, sbyte[] F)
-	{
-		int n = PRIV.p.getlen();
-		FF g = new FF(2 * n);
-
-		FF.fromBytes(g,G);
-		FF jp = g.dmod(PRIV.p);
-		FF jq = g.dmod(PRIV.q);
-
-		jp.skpow(PRIV.dp,PRIV.p);
-		jq.skpow(PRIV.dq,PRIV.q);
-
-		g.zero();
-		g.dscopy(jp);
-		jp.mod(PRIV.q);
-		if (FF.comp(jp,jq) > 0)
-		{
-			jq.add(PRIV.q);
-		}
-		jq.sub(jp);
-		jq.norm();
-
-		FF t = FF.mul(PRIV.c,jq);
-		jq = t.dmod(PRIV.q);
-
-		t = FF.mul(jq,PRIV.p);
-		g.add(t);
-		g.norm();
-
-		g.toBytes(F);
-	}
-}
diff --git a/cs/RectangularArrays.cs b/cs/RectangularArrays.cs
deleted file mode 100644
index 976a070..0000000
--- a/cs/RectangularArrays.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-//----------------------------------------------------------------------------------------
-//	Copyright © 2007 - 2015 Tangible Software Solutions Inc.
-//	This class can be used by anyone provided that the copyright notice remains intact.
-//
-//	This class provides the logic to simulate Java rectangular arrays, which are jagged
-//	arrays with inner arrays of the same length. A size of -1 indicates unknown length.
-//----------------------------------------------------------------------------------------
-internal static partial class RectangularArrays
-{
-    internal static int[][] ReturnRectangularIntArray(int size1, int size2)
-    {
-        int[][] newArray;
-        if (size1 > -1)
-        {
-            newArray = new int[size1][];
-            if (size2 > -1)
-            {
-                for (int array1 = 0; array1 < size1; array1++)
-                {
-                    newArray[array1] = new int[size2];
-                }
-            }
-        }
-        else
-            newArray = null;
-
-        return newArray;
-    }
-}
\ No newline at end of file
diff --git a/cs/StringHelperClass.cs b/cs/StringHelperClass.cs
deleted file mode 100644
index 3bcece0..0000000
--- a/cs/StringHelperClass.cs
+++ /dev/null
@@ -1,90 +0,0 @@
-//-------------------------------------------------------------------------------------------
-//	Copyright © 2007 - 2015 Tangible Software Solutions Inc.
-//	This class can be used by anyone provided that the copyright notice remains intact.
-//
-//	This class is used to convert some aspects of the Java String class.
-//-------------------------------------------------------------------------------------------
-internal static class StringHelperClass
-{
-	//----------------------------------------------------------------------------------
-	//	This method replaces the Java String.substring method when 'start' is a
-	//	method call or calculated value to ensure that 'start' is obtained just once.
-	//----------------------------------------------------------------------------------
-	internal static string SubstringSpecial(this string self, int start, int end)
-	{
-		return self.Substring(start, end - start);
-	}
-
-	//------------------------------------------------------------------------------------
-	//	This method is used to replace calls to the 2-arg Java String.startsWith method.
-	//------------------------------------------------------------------------------------
-	internal static bool StartsWith(this string self, string prefix, int toffset)
-	{
-		return self.IndexOf(prefix, toffset, System.StringComparison.Ordinal) == toffset;
-	}
-
-	//------------------------------------------------------------------------------
-	//	This method is used to replace most calls to the Java String.split method.
-	//------------------------------------------------------------------------------
-	internal static string[] Split(this string self, string regexDelimiter, bool trimTrailingEmptyStrings)
-	{
-		string[] splitArray = System.Text.RegularExpressions.Regex.Split(self, regexDelimiter);
-
-		if (trimTrailingEmptyStrings)
-		{
-			if (splitArray.Length > 1)
-			{
-				for (int i = splitArray.Length; i > 0; i--)
-				{
-					if (splitArray[i - 1].Length > 0)
-					{
-						if (i < splitArray.Length)
-							System.Array.Resize(ref splitArray, i);
-
-						break;
-					}
-				}
-			}
-		}
-
-		return splitArray;
-	}
-
-	//-----------------------------------------------------------------------------
-	//	These methods are used to replace calls to some Java String constructors.
-	//-----------------------------------------------------------------------------
-	internal static string NewString(sbyte[] bytes)
-	{
-		return NewString(bytes, 0, bytes.Length);
-	}
-	internal static string NewString(sbyte[] bytes, int index, int count)
-	{
-		return System.Text.Encoding.UTF8.GetString((byte[])(object)bytes, index, count);
-	}
-	internal static string NewString(sbyte[] bytes, string encoding)
-	{
-		return NewString(bytes, 0, bytes.Length, encoding);
-	}
-	internal static string NewString(sbyte[] bytes, int index, int count, string encoding)
-	{
-		return System.Text.Encoding.GetEncoding(encoding).GetString((byte[])(object)bytes, index, count);
-	}
-
-	//--------------------------------------------------------------------------------
-	//	These methods are used to replace calls to the Java String.getBytes methods.
-	//--------------------------------------------------------------------------------
-	internal static sbyte[] GetBytes(this string self)
-	{
-		return GetSBytesForEncoding(System.Text.Encoding.UTF8, self);
-	}
-	internal static sbyte[] GetBytes(this string self, string encoding)
-	{
-		return GetSBytesForEncoding(System.Text.Encoding.GetEncoding(encoding), self);
-	}
-	private static sbyte[] GetSBytesForEncoding(System.Text.Encoding encoding, string s)
-	{
-		sbyte[] sbytes = new sbyte[encoding.GetByteCount(s)];
-		encoding.GetBytes(s, 0, s.Length, (byte[])(object)sbytes, 0);
-		return sbytes;
-	}
-}
\ No newline at end of file
diff --git a/cs/TestECDH.cs b/cs/TestECDH.cs
deleted file mode 100644
index 216414d..0000000
--- a/cs/TestECDH.cs
+++ /dev/null
@@ -1,210 +0,0 @@
-using System;
-
-/*
-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.
-*/
-
-/* test driver and function exerciser for ECDH/ECIES/ECDSA API Functions */
-
-public class TestECDH
-{
-	public static void printBinary(sbyte[] array)
-	{
-		int i;
-		for (i = 0;i < array.Length;i++)
-		{
-			Console.Write("{0:x2}", array[i]);
-		}
-		Console.WriteLine();
-	}
-
-	public static void Main(string[] args)
-	{
-		int i , j = 0, res ;
-		int result;
-		string pp = "M0ng00se";
-
-		int EGS = ECDH.EGS;
-		int EFS = ECDH.EFS;
-		int EAS = AES.KS;
-
-		sbyte[] S1 = new sbyte[EGS];
-		sbyte[] W0 = new sbyte[2 * EFS + 1];
-		sbyte[] W1 = new sbyte[2 * EFS + 1];
-		sbyte[] Z0 = new sbyte[EFS];
-		sbyte[] Z1 = new sbyte[EFS];
-		sbyte[] RAW = new sbyte[100];
-		sbyte[] SALT = new sbyte[8];
-		sbyte[] P1 = new sbyte[3];
-		sbyte[] P2 = new sbyte[4];
-		sbyte[] V = new sbyte[2 * EFS + 1];
-		sbyte[] M = new sbyte[17];
-		sbyte[] T = new sbyte[12];
-		sbyte[] CS = new sbyte[EGS];
-		sbyte[] DS = new sbyte[EGS];
-
-		RAND rng = new RAND();
-
-		rng.clean();
-		for (i = 0;i < 100;i++)
-		{
-			RAW[i] = (sbyte)(i);
-		}
-
-		rng.seed(100,RAW);
-
-//for (j=0;j<100;j++)
-//{
-
-		for (i = 0;i < 8;i++)
-		{
-			SALT[i] = (sbyte)(i + 1); // set Salt
-		}
-
-		Console.WriteLine("Alice's Passphrase= " + pp);
-		sbyte[] PW = pp.GetBytes();
-
-/* private key S0 of size EGS bytes derived from Password and Salt */
-
-		sbyte[] S0 = ECDH.PBKDF2(PW,SALT,1000,EGS);
-
-		Console.Write("Alice's private key= 0x");
-		printBinary(S0);
-
-/* Generate Key pair S/W */
-		ECDH.KEY_PAIR_GENERATE(null,S0,W0);
-
-		Console.Write("Alice's public key= 0x");
-		printBinary(W0);
-
-		res = ECDH.PUBLIC_KEY_VALIDATE(true,W0);
-		if (res != 0)
-		{
-			Console.WriteLine("ECP Public Key is invalid!\n");
-			return;
-		}
-/* Random private key for other party */
-		ECDH.KEY_PAIR_GENERATE(rng,S1,W1);
-
-		Console.Write("Servers private key= 0x");
-		printBinary(S1);
-
-		Console.Write("Servers public key= 0x");
-		printBinary(W1);
-
-
-		res = ECDH.PUBLIC_KEY_VALIDATE(true,W1);
-		if (res != 0)
-		{
-			Console.Write("ECP Public Key is invalid!\n");
-			return;
-		}
-
-/* Calculate common key using DH - IEEE 1363 method */
-
-		ECDH.ECPSVDP_DH(S0,W1,Z0);
-		ECDH.ECPSVDP_DH(S1,W0,Z1);
-
-		bool same = true;
-		for (i = 0;i < EFS;i++)
-		{
-			if (Z0[i] != Z1[i])
-			{
-				same = false;
-			}
-		}
-
-		if (!same)
-		{
-			Console.WriteLine("*** ECPSVDP-DH Failed");
-			return;
-		}
-
-		sbyte[] KEY = ECDH.KDF1(Z0,EAS);
-
-		Console.Write("Alice's DH Key=  0x");
-		printBinary(KEY);
-		Console.Write("Servers DH Key=  0x");
-		printBinary(KEY);
-
-		Console.WriteLine("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 = 0;i <= 16;i++)
-		{
-			M[i] = (sbyte)i;
-		}
-
-		sbyte[] C = ECDH.ECIES_ENCRYPT(P1,P2,rng,W1,M,V,T);
-
-		Console.WriteLine("Ciphertext= ");
-		Console.Write("V= 0x");
-		printBinary(V);
-		Console.Write("C= 0x");
-		printBinary(C);
-		Console.Write("T= 0x");
-		printBinary(T);
-
-
-		M = ECDH.ECIES_DECRYPT(P1,P2,V,C,T,S1);
-		if (M.Length == 0)
-		{
-			Console.WriteLine("*** ECIES Decryption Failed\n");
-			return;
-		}
-		else
-		{
-			Console.WriteLine("Decryption succeeded");
-		}
-
-		Console.Write("Message is 0x");
-		printBinary(M);
-
-		Console.WriteLine("Testing ECDSA");
-
-		if (ECDH.ECPSP_DSA(rng,S0,M,CS,DS) != 0)
-		{
-			Console.WriteLine("***ECDSA Signature Failed");
-			return;
-		}
-		Console.WriteLine("Signature= ");
-		Console.Write("C= 0x");
-		printBinary(CS);
-		Console.Write("D= 0x");
-		printBinary(DS);
-
-		if (ECDH.ECPVP_DSA(W0,M,CS,DS) != 0)
-		{
-			Console.WriteLine("***ECDSA Verification Failed");
-			return;
-		}
-		else
-		{
-			Console.WriteLine("ECDSA Signature/Verification succeeded " + j);
-		}
-//}
-//System.out.println("Test Completed Successfully");
-	}
-}
diff --git a/cs/TestECM.cs b/cs/TestECM.cs
deleted file mode 100644
index d9c1eeb..0000000
--- a/cs/TestECM.cs
+++ /dev/null
@@ -1,141 +0,0 @@
-using System;
-
-/*
-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.
-*/
-
-/* test driver and function exerciser for ECDH API Function only - for use with Montgomery curves */
-
-public class TestECM
-{
-	public static void printBinary(sbyte[] array)
-	{
-		int i;
-		for (i = 0;i < array.Length;i++)
-		{
-			Console.Write("{0:x2}", array[i]);
-		}
-		Console.WriteLine();
-	}
-
-	public static void Main(string[] args)
-	{
-		int i , j = 0, res ;
-		int result;
-		string pp = "M0ng00se";
-
-		int EGS = ECDH.EGS;
-		int EFS = ECDH.EFS;
-		int EAS = AES.KS;
-
-		sbyte[] S1 = new sbyte[EGS];
-		sbyte[] W0 = new sbyte[2 * EFS + 1];
-		sbyte[] W1 = new sbyte[2 * EFS + 1];
-		sbyte[] Z0 = new sbyte[EFS];
-		sbyte[] Z1 = new sbyte[EFS];
-		sbyte[] RAW = new sbyte[100];
-		sbyte[] SALT = new sbyte[8];
-
-		RAND rng = new RAND();
-
-		rng.clean();
-		for (i = 0;i < 100;i++)
-		{
-			RAW[i] = (sbyte)(i);
-		}
-
-		rng.seed(100,RAW);
-
-//for (j=0;j<100;j++)
-//{
-
-		for (i = 0;i < 8;i++)
-		{
-			SALT[i] = (sbyte)(i + 1); // set Salt
-		}
-
-		Console.WriteLine("Alice's Passphrase= " + pp);
-		sbyte[] PW = pp.GetBytes();
-
-/* private key S0 of size EGS bytes derived from Password and Salt */
-
-		sbyte[] S0 = ECDH.PBKDF2(PW,SALT,1000,EGS);
-
-		Console.Write("Alice's private key= 0x");
-		printBinary(S0);
-
-/* Generate Key pair S/W */
-		ECDH.KEY_PAIR_GENERATE(null,S0,W0);
-
-		Console.Write("Alice's public key= 0x");
-		printBinary(W0);
-
-		res = ECDH.PUBLIC_KEY_VALIDATE(true,W0);
-		if (res != 0)
-		{
-			Console.WriteLine("Alice's public Key is invalid!\n");
-			return;
-		}
-/* Random private key for other party */
-		ECDH.KEY_PAIR_GENERATE(rng,S1,W1);
-
-		Console.Write("Servers private key= 0x");
-		printBinary(S1);
-
-		Console.Write("Servers public key= 0x");
-		printBinary(W1);
-
-
-		res = ECDH.PUBLIC_KEY_VALIDATE(true,W1);
-		if (res != 0)
-		{
-			Console.Write("Server's public Key is invalid!\n");
-			return;
-		}
-
-/* Calculate common key using DH - IEEE 1363 method */
-
-		ECDH.ECPSVDP_DH(S0,W1,Z0);
-		ECDH.ECPSVDP_DH(S1,W0,Z1);
-
-		bool same = true;
-		for (i = 0;i < EFS;i++)
-		{
-			if (Z0[i] != Z1[i])
-			{
-				same = false;
-			}
-		}
-
-		if (!same)
-		{
-			Console.WriteLine("*** ECPSVDP-DH Failed");
-			return;
-		}
-
-		sbyte[] KEY = ECDH.KDF1(Z0,EAS);
-
-		Console.Write("Alice's DH Key=  0x");
-		printBinary(KEY);
-		Console.Write("Servers DH Key=  0x");
-		printBinary(KEY);
-
-//}
-//System.out.println("Test Completed Successfully");
-	}
-}
diff --git a/cs/TestMPIN.cs b/cs/TestMPIN.cs
deleted file mode 100644
index e3eeb83..0000000
--- a/cs/TestMPIN.cs
+++ /dev/null
@@ -1,298 +0,0 @@
-using System;
-
-/*
-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.
-*/
-
-/* test driver and function exerciser for MPIN API Functions */
-
-
-public class TestMPIN
-{
-	internal static bool PERMITS = true;
-	internal static bool PINERROR = true;
-	internal static bool FULL = true;
-	internal static bool SINGLE_PASS = false;
-
-	internal static void printBinary(sbyte[] array)
-	{
-		int i;
-		for (i = 0;i < array.Length;i++)
-		{
-			Console.Write("{0:x2}", array[i]);
-		}
-		Console.WriteLine();
-	}
-
-	public static void Main(string[] args)
-	{
-		RAND rng = new RAND();
-		sbyte[] raw = new sbyte[100];
-		for (int i = 0;i < 100;i++)
-		{
-			raw[i] = (sbyte)(i + 1);
-		}
-		rng.seed(100,raw);
-
-		int EGS = MPIN.EGS;
-		int EFS = MPIN.EFS;
-		int G1S = 2 * EFS + 1; // Group 1 Size
-		int G2S = 4 * EFS; // Group 2 Size
-		int EAS = 16;
-
-		sbyte[] S = new sbyte[EGS];
-		sbyte[] SST = new sbyte[G2S];
-		sbyte[] TOKEN = new sbyte[G1S];
-		sbyte[] PERMIT = new sbyte[G1S];
-		sbyte[] SEC = new sbyte[G1S];
-		sbyte[] xID = new sbyte[G1S];
-		sbyte[] xCID = new sbyte[G1S];
-		sbyte[] X = new sbyte[EGS];
-		sbyte[] Y = new sbyte[EGS];
-		sbyte[] E = new sbyte[12 * EFS];
-		sbyte[] F = new sbyte[12 * EFS];
-		sbyte[] HID = new sbyte[G1S];
-		sbyte[] HTID = new sbyte[G1S];
-
-		sbyte[] G1 = new sbyte[12 * EFS];
-		sbyte[] G2 = new sbyte[12 * EFS];
-		sbyte[] R = new sbyte[EGS];
-		sbyte[] Z = new sbyte[G1S];
-		sbyte[] W = new sbyte[EGS];
-		sbyte[] T = new sbyte[G1S];
-		sbyte[] CK = new sbyte[EAS];
-		sbyte[] SK = new sbyte[EAS];
-
-/* Trusted Authority set-up */
-
-		MPIN.RANDOM_GENERATE(rng,S);
-		Console.Write("Master Secret s: 0x");
-		printBinary(S);
-
- /* Create Client Identity */
-		 string IDstr = "testUser@miracl.com";
-		sbyte[] CLIENT_ID = IDstr.GetBytes();
-
-		sbyte[] HCID = MPIN.HASH_ID(CLIENT_ID); // Either Client or TA calculates Hash(ID) - you decide!
-
-		Console.Write("Client ID= ");
-		printBinary(CLIENT_ID);
-
-/* Client and Server are issued secrets by DTA */
-		MPIN.GET_SERVER_SECRET(S,SST);
-		Console.Write("Server Secret SS: 0x");
-		printBinary(SST);
-
-		MPIN.GET_CLIENT_SECRET(S,HCID,TOKEN);
-		Console.Write("Client Secret CS: 0x");
-		printBinary(TOKEN);
-
-/* Client extracts PIN from secret to create Token */
-		int pin = 1234;
-		Console.WriteLine("Client extracts PIN= " + pin);
-		int rtn = MPIN.EXTRACT_PIN(CLIENT_ID,pin,TOKEN);
-		if (rtn != 0)
-		{
-			Console.WriteLine("FAILURE: EXTRACT_PIN rtn: " + rtn);
-		}
-
-		Console.Write("Client Token TK: 0x");
-		printBinary(TOKEN);
-
-		if (FULL)
-		{
-			MPIN.PRECOMPUTE(TOKEN,HCID,G1,G2);
-		}
-		int date;
-		if (PERMITS)
-		{
-			date = MPIN.today();
-			Console.WriteLine("Date= "+date);
-/* Client gets "Time Token" permit from DTA */
-			MPIN.GET_CLIENT_PERMIT(date,S,HCID,PERMIT);
-			Console.Write("Time Permit TP: 0x");
-			printBinary(PERMIT);
-
-/* This encoding makes Time permit look random - Elligator squared */
-			MPIN.ENCODING(rng,PERMIT);
-			Console.Write("Encoded Time Permit TP: 0x");
-			printBinary(PERMIT);
-			MPIN.DECODING(PERMIT);
-			Console.Write("Decoded Time Permit TP: 0x");
-			printBinary(PERMIT);
-		}
-		else
-		{
-			date = 0;
-		}
-
-		Console.Write("\nPIN= ");
-//		Scanner scan = new Scanner(System.in);
-//		pin = scan.Next();
-
-		pin=int.Parse(Console.ReadLine());
-
-/* 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.
-
-
-*/
-
-		sbyte[] pxID = xID;
-		sbyte[] pxCID = xCID;
-		sbyte[] pHID = HID;
-		sbyte[] pHTID = HTID;
-		sbyte[] pE = E;
-		sbyte[] pF = F;
-		sbyte[] pPERMIT = PERMIT;
-		sbyte[] prHID;
-
-		if (date != 0)
-		{
-
-			prHID = pHTID;
-			if (!PINERROR)
-			{
-				pxID = null;
-				pHID = null;
-			}
-		}
-		else
-		{
-			prHID = pHID;
-			pPERMIT = null;
-			pxCID = null;
-			pHTID = null;
-		}
-		if (!PINERROR)
-		{
-			pE = null;
-			pF = null;
-		}
-
-				if (SINGLE_PASS)
-				{
-			Console.WriteLine("MPIN Single Pass");
-				  int timeValue = MPIN.GET_TIME();
-				  rtn = MPIN.CLIENT(date,CLIENT_ID,rng,X,pin,TOKEN,SEC,pxID,pxCID,pPERMIT,timeValue,Y);
-			if (rtn != 0)
-			{
-			  Console.WriteLine("FAILURE: CLIENT rtn: " + rtn);
-			}
-
-				  if (FULL)
-				  {
-					HCID = MPIN.HASH_ID(CLIENT_ID);
-					MPIN.GET_G1_MULTIPLE(rng,1,R,HCID,Z); // Also Send Z=r.ID to Server, remember random r
-				  }
-
-				  rtn = MPIN.SERVER(date,pHID,pHTID,Y,SST,pxID,pxCID,SEC,pE,pF,CLIENT_ID,timeValue);
-				  if (rtn != 0)
-				  {
-			  Console.WriteLine("FAILURE: SERVER rtn: " + rtn);
-				  }
-
-				  if (FULL)
-				  {
-					MPIN.GET_G1_MULTIPLE(rng,0,W,prHID,T); // Also send T=w.ID to client, remember random w
-				  }
-				}
-				else
-				{
-			Console.WriteLine("MPIN Multi Pass");
-				  /* Send U=x.ID to server, and recreate secret from token and pin */
-			rtn = MPIN.CLIENT_1(date,CLIENT_ID,rng,X,pin,TOKEN,SEC,pxID,pxCID,pPERMIT);
-			if (rtn != 0)
-			{
-			  Console.WriteLine("FAILURE: CLIENT_1 rtn: " + rtn);
-			}
-
-			if (FULL)
-			{
-			  HCID = MPIN.HASH_ID(CLIENT_ID);
-			  MPIN.GET_G1_MULTIPLE(rng,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. */
-			MPIN.SERVER_1(date,CLIENT_ID,pHID,pHTID);
-
-				  /* Server generates Random number Y and sends it to Client */
-			MPIN.RANDOM_GENERATE(rng,Y);
-
-				  if (FULL)
-				  {
-			  MPIN.GET_G1_MULTIPLE(rng,0,W,prHID,T); // Also send T=w.ID to client, remember random w
-				  }
-
-				  /* Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC */
-			rtn = MPIN.CLIENT_2(X,Y,SEC);
-			if (rtn != 0)
-			{
-			  Console.WriteLine("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 = MPIN.SERVER_2(date,pHID,pHTID,Y,SST,pxID,pxCID,SEC,pE,pF);
-
-			if (rtn != 0)
-			{
-			  Console.WriteLine("FAILURE: SERVER_1 rtn: " + rtn);
-			}
-				}
-
-		if (rtn == MPIN.BAD_PIN)
-		{
-		  Console.WriteLine("Server says - Bad Pin. I don't know you. Feck off.\n");
-		  if (PINERROR)
-		  {
-			int err = MPIN.KANGAROO(E,F);
-			if (err != 0)
-			{
-				Console.Write("(Client PIN is out by {0:D})\n",err);
-			}
-		  }
-		  return;
-		}
-		else
-		{
-			Console.WriteLine("Server says - PIN is good! You really are " + IDstr);
-		}
-
-
-		if (FULL)
-		{
-			MPIN.CLIENT_KEY(G1,G2,pin,R,X,T,CK);
-			Console.Write("Client Key =  0x");
-			printBinary(CK);
-
-			MPIN.SERVER_KEY(Z,SST,W,pxID,pxCID,SK);
-			Console.Write("Server Key =  0x");
-			printBinary(SK);
-		}
-	}
-}
diff --git a/cs/TestRSA.cs b/cs/TestRSA.cs
deleted file mode 100644
index 07cd6f9..0000000
--- a/cs/TestRSA.cs
+++ /dev/null
@@ -1,72 +0,0 @@
-using System;
-
-/*
-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.
-*/
-
-/* test driver and function exerciser for RSA API Functions */
-
-public class TestRSA
-{
-
-	public static void Main(string[] args)
-	{
-		int i;
-		int RFS = RSA.RFS;
-
-		string message = "Hello World\n";
-
-		rsa_public_key pub = new rsa_public_key(ROM.FFLEN);
-		rsa_private_key priv = new rsa_private_key(ROM.HFLEN);
-
-		sbyte[] ML = new sbyte[RFS];
-		sbyte[] C = new sbyte[RFS];
-		sbyte[] RAW = new sbyte[100];
-
-		RAND rng = new RAND();
-
-		rng.clean();
-		for (i = 0;i < 100;i++)
-		{
-			RAW[i] = (sbyte)(i);
-		}
-
-		rng.seed(100,RAW);
-//for (i=0;i<10;i++)
-//{
-		Console.WriteLine("Generating public/private key pair");
-		RSA.KEY_PAIR(rng,65537,priv,pub);
-
-		sbyte[] M = message.GetBytes();
-		Console.Write("Encrypting test string\n");
-		sbyte[] E = RSA.OAEP_ENCODE(M,rng,null); // OAEP encode message M to E
-
-		RSA.ENCRYPT(pub,E,C); // encrypt encoded message
-		Console.Write("Ciphertext= 0x");
-		RSA.printBinary(C);
-
-		Console.Write("Decrypting test string\n");
-		RSA.DECRYPT(priv,C,ML);
-		sbyte[] MS = RSA.OAEP_DECODE(null,ML); // OAEP decode message
-
-		message = StringHelperClass.NewString(MS);
-		Console.Write(message);
-//}
-		RSA.PRIVATE_KEY_KILL(priv);
-	}
-}
diff --git a/cs/readme.txt b/cs/readme.txt
deleted file mode 100644
index 14b81d0..0000000
--- a/cs/readme.txt
+++ /dev/null
@@ -1,30 +0,0 @@
-AMCL is very simple to build for C#.
-
-NOTE: The C# code was automatically generated from the Java64 code using 
-the Java to C# Converter from Tangible Software Solutions. A few minor
-fix-ups were required.
-
-First - decide the modulus and curve type you want to use. Edit ROM.cs 
-where indicated. You will probably want to use one of the curves whose 
-details are already in there.
-
-Three example API files are provided, MPIN.cs which 
-supports our M-Pin (tm) protocol, ECDH.cs which supports elliptic 
-curve key exchange, digital signature and public key crypto, and RSA.cs
-which supports the RSA method.
-
-In the ROM.cs file you must provide the curve constants. Several examples
-are provided there, if you are willing to use one of these.
-
-For a quick jumpstart:-
-
-csc TestMPIN.cs MPIN.cs FP.cs BIG.cs DBIG.cs AES.cs HASH.cs RAND.cs ROM.cs StringHelperClass.cs ECP.cs FP2.cs ECP2.cs FP4.cs FP12.cs PAIR.cs RectangularArrays.cs
-
-or 
-
-csc TestECDH.cs ECDH.cs FP.cs BIG.cs DBIG.cs AES.cs HASH.cs RAND.cs ROM.cs StringHelperClass.cs ECP.cs
-
-or
-
-csc TestRSA.cs RSA.cs FF.cs BIG.cs DBIG.cs HASH.cs RAND.cs ROM.cs StringHelperClass.cs
-
diff --git a/data/icon.bmp b/data/icon.bmp
deleted file mode 100644
index 3e53971..0000000
--- a/data/icon.bmp
+++ /dev/null
Binary files differ
diff --git a/data/icon.ico b/data/icon.ico
deleted file mode 100644
index 89dfae6..0000000
--- a/data/icon.ico
+++ /dev/null
Binary files differ
diff --git a/docs/AMCL.dox b/docs/AMCL.dox
deleted file mode 100755
index 68f1fa8..0000000
--- a/docs/AMCL.dox
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
-  This file contains NO source code, just some documentation for doxygen to
-  parse.
-*/
-
-/*!
-  \mainpage Apache Milagro Crypto Library (AMCL)
-
- Read <a href="AMCL.pdf">AMCL.pdf</a> for an introduction to AMCL
-
- AMCL is provided in these languages;
-
-<ul type="disc">
- <li> C
- <li> JAVA
- <li> JavaScript 
- <li> C#
- <li> Swift
- <li> GO
-</ul>
-
- There is also a Python wrapper provided that requires <a href="https://cffi.readthedocs.org/en/release-0.8/">CFFI</a>
-
-  \section homepage Project page
-  The official project page is hosted at 
-	<a href="http://www.miracl.com/index">MIRACL Products</a>
-
-  \section license License
-
-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.
-
-  \section platforms Platforms
-
-  The software can be compiled and installed for these operating systems;
-
-<ul type="disc">
-  <li>Linux</li>
-  <li>Windows</li>
-  <li>Mac OS</li>
-</ul>
-
-
-
-  \section downloads Downloads
-
-  The source code is available from the GIT repository:
-
-  git clone https://github.com/miracl/milagro-crypto
-
-  \section installonmainpage Installation
- 
-  There are instructions for building for \ref linux, \ref mac and \ref windows.
-
-*/
-
-
-/*!
-  \page linux Linux 
-
-<h2>Software dependencies</h2>
-
-CMake is required to build the library and can usually be installed from
-the operating system package manager.
-
-<ul type="disc">
-  <li>sudo apt-get install cmake</li>
-</ul>
-
-If not, then you can download it from www.cmake.org
-
-The C Foreign Function Interface for Python <a href="https://cffi.readthedocs.org/en/latest/">CFFI</a> module
-is also required if you wish to use the Python module.
-
-<ul type="disc">
-  <li>sudo pip install cffi</li>
-</ul>
-
-In order to build the documentation <a href="http://www.stack.nl/~dimitri/doxygen/">doxygen</a> is required.
-
-<h2>Build Instructions</h2>
-
-<p>The default build is for 32 bit machines</p>
-
-<ol type="disc">
-  <li>mkdir Release</li>
-  <li>cd Release</li>
-  <li>cmake ..</li>
-  <li>make</li>
-  <li>make test</li>
-  <li>make doc</li>
-  <li>sudo make install</li>
-</ol>
-
-<p>The build can be configured using by setting flags on the command line i.e.</p>
-
-<ol type="disc">
-  <li>cmake  -D CMAKE_INSTALL_PREFIX=/opt/amcl -D WORD_LENGTH=64 ..</li>
-</ol>
-
-<h2>Uninstall software</h2>
-
-<ul type="disc">
-  <li>sudo make uninstall</li>
-</ul>
-
-<h2>Building an installer</h2>
-
-<p>After having built the libraries you can build a binary installer and a source distribution by running this command</p>
-
-<ul type="disc">
-  <li>make package</li>
-</ul>
-
-*/
-
-
-
-
-/*!
-  \page mac Mac OS 
-
-<h2>Software dependencies</h2>
-
-Install <a href="http://brew.sh/">Homebrew</a>
-
-<ul type="disc">
-  <li>ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"</li>
-</ul>
-
-Install  <a href="http://www.cmake.org/download/">cmake</a>
-
-<ul type="disc">
-  <li>brew install cmake</li>
-</ul>
-
-The C Foreign Function Interface for Python <a href="https://cffi.readthedocs.org/en/latest/">CFFI</a> module
-is also required if you wish to use the Python module.
-
-<ul type="disc">
-  <li>brew install pkg-config libffi</li>
-  <li>sudo pip install cffi</li>
-</ul>
-
-In order to build the documentation <a href="http://www.stack.nl/~dimitri/doxygen/">doxygen</a> is required.
-
-<ul type="disc">
-  <li>brew install doxygen</li>
-</ul>
-
-<h2>Build Instructions</h2>
-
-<p>The default build is for 32 bit machines</p>
-
-<ol type="disc">
-  <li>mkdir Release</li>
-  <li>cd Release</li>
-  <li>cmake ..</li>
-  <li>make</li>
-  <li>make test</li>
-  <li>make doc</li>
-  <li>sudo make install</li>
-</ol>
-
-<p>The build can be configured using by setting flags on the command line i.e.</p>
-
-<ol type="disc">
-  <li>cmake -DWORD_LENGTH=64 ..</li>
-</ol>
-
-<h2>Uninstall software</h2>
-
-<ul type="disc">
-  <li>sudo make uninstall</li>
-</ul>
-
-*/
-
-/*!
-  \page windows Windows
-
-<h2>Software dependencies</h2>
-
-<p>Minimalist GNU for Windows <a href="http://www.mingw.org/">MinGW</a> provides the 
-tool set used to build the library and should be installed. When the MinGW installer
-starts select the mingw32-base and mingw32-gcc-g++ components. From the menu select
-"Installation" -> "Apply Changes", then click "Apply". Finally add C:\\MinGW\\bin
-to the PATH variable.</p>
-
-<p>CMake is required to build the library and can be downloaded from www.cmake.org</p>
-
-<p>The C Foreign Function Interface for Python <a href="https://cffi.readthedocs.org/en/latest/">CFFI</a> module
-is also required, if you wish to use the Python module.</p>
-
-<ul type="disc">
-  <li>pip install cffi</li>
-</ul>
-
-In order to build the documentation <a href="http://www.stack.nl/~dimitri/doxygen/">doxygen</a> is required.
-
-<h2>Build Instructions</h2>
-
-<p>Start a command prompt as an administrator</p>
-
-<p>The default build is for 32 bit machines</p>
-
-<ol type="disc">
-  <li>mkdir Release</li>
-  <li>cd Release</li>
-  <li>cmake -G "MinGW Makefiles" ..</li>
-  <li>mingw32-make</li>
-  <li>mingw32-make test</li>
-  <li>mingw32-make doc</li>
-  <li>mingw32-make install</li>
-</ol>
-
-<p>
-
-Post install append the PATH system variable to point to the install ./lib.
-
-My Computer -> Properties -> Advanced > Environment Variables
-
-</p>
-
-
-<p>The build can be configured using by setting flags on the command line i.e.</p>
-
-<ol type="disc">
-  <li>cmake -G "MinGW Makefiles" -DWORD_LENGTH=64 ..</li>
-</ol>
-
-<h2>Uninstall software</h2>
-
-<ul type="disc">
-  <li>mingw32-make uninstall</li>
-</ul>
-
-<h2>Building an installer</h2>
-
-<p>After having built the libraries you can build a Windows installer using this command</p>
-
-<ul type="disc">
-  <li>sudo mingw32-make package</li>
-</ul>
-
-<p>In order for this to work <a href="http://nsis.sourceforge.net/Download">NSSI</a> has
-to have been installed</p>
-
-*/
-
-
-
diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt
deleted file mode 100644
index 55efd99..0000000
--- a/docs/CMakeLists.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY)
-
-add_custom_target(doc
-${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
-WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
-COMMENT "Generating documentation with Doxygen" VERBATIM)
-
-file(COPY ${PROJECT_SOURCE_DIR}/AMCL.pdf  DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/html/")
-
-
-
diff --git a/docs/Doxyfile.in b/docs/Doxyfile.in
deleted file mode 100644
index 0150171..0000000
--- a/docs/Doxyfile.in
+++ /dev/null
@@ -1,1796 +0,0 @@
-# Doxyfile 1.8.1.1
-
-# This file describes the settings to be used by the documentation system
-# doxygen (www.doxygen.org) for a project.
-#
-# All text after a hash (#) is considered a comment and will be ignored.
-# The format is:
-#       TAG = value [value, ...]
-# For lists items can also be appended using:
-#       TAG += value [value, ...]
-# Values that contain spaces should be placed between quotes (" ").
-
-#---------------------------------------------------------------------------
-# Project related configuration options
-#---------------------------------------------------------------------------
-
-# This tag specifies the encoding used for all characters in the config file
-# that follow. The default is UTF-8 which is also the encoding used for all
-# text before the first occurrence of this tag. Doxygen uses libiconv (or the
-# iconv built into libc) for the transcoding. See
-# http://www.gnu.org/software/libiconv for the list of possible encodings.
-
-DOXYFILE_ENCODING      = UTF-8
-
-# The PROJECT_NAME tag is a single word (or sequence of words) that should
-# identify the project. Note that if you do not use Doxywizard you need
-# to put quotes around the project name if it contains spaces.
-
-PROJECT_NAME           = "AMCL"
-
-# The PROJECT_NUMBER tag can be used to enter a project or revision number.
-# This could be handy for archiving the generated documentation or
-# if some version control system is used.
-
-PROJECT_NUMBER         =
-
-# Using the PROJECT_BRIEF tag one can provide an optional one line description
-# for a project that appears at the top of each page and should give viewer
-# a quick idea about the purpose of the project. Keep the description short.
-
-PROJECT_BRIEF          =
-
-# With the PROJECT_LOGO tag one can specify an logo or icon that is
-# included in the documentation. The maximum height of the logo should not
-# exceed 55 pixels and the maximum width should not exceed 200 pixels.
-# Doxygen will copy the logo to the output directory.
-
-PROJECT_LOGO           =
-
-# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
-# base path where the generated documentation will be put.
-# If a relative path is entered, it will be relative to the location
-# where doxygen was started. If left blank the current directory will be used.
-
-OUTPUT_DIRECTORY       =
-
-# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
-# 4096 sub-directories (in 2 levels) under the output directory of each output
-# format and will distribute the generated files over these directories.
-# Enabling this option can be useful when feeding doxygen a huge amount of
-# source files, where putting all generated files in the same directory would
-# otherwise cause performance problems for the file system.
-
-CREATE_SUBDIRS         = NO
-
-# The OUTPUT_LANGUAGE tag is used to specify the language in which all
-# documentation generated by doxygen is written. Doxygen will use this
-# information to generate all constant output in the proper language.
-# The default language is English, other supported languages are:
-# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
-# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
-# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
-# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
-# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak,
-# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
-
-OUTPUT_LANGUAGE        = English
-
-# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
-# include brief member descriptions after the members that are listed in
-# the file and class documentation (similar to JavaDoc).
-# Set to NO to disable this.
-
-BRIEF_MEMBER_DESC      = YES
-
-# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
-# the brief description of a member or function before the detailed description.
-# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
-# brief descriptions will be completely suppressed.
-
-REPEAT_BRIEF           = NO
-
-# This tag implements a quasi-intelligent brief description abbreviator
-# that is used to form the text in various listings. Each string
-# in this list, if found as the leading text of the brief description, will be
-# stripped from the text and the result after processing the whole list, is
-# used as the annotated text. Otherwise, the brief description is used as-is.
-# If left blank, the following values are used ("$name" is automatically
-# replaced with the name of the entity): "The $name class" "The $name widget"
-# "The $name file" "is" "provides" "specifies" "contains"
-# "represents" "a" "an" "the"
-
-ABBREVIATE_BRIEF       =
-
-# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
-# Doxygen will generate a detailed section even if there is only a brief
-# description.
-
-ALWAYS_DETAILED_SEC    = NO
-
-# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
-# inherited members of a class in the documentation of that class as if those
-# members were ordinary class members. Constructors, destructors and assignment
-# operators of the base classes will not be shown.
-
-INLINE_INHERITED_MEMB  = NO
-
-# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
-# path before files name in the file list and in the header files. If set
-# to NO the shortest path that makes the file name unique will be used.
-
-FULL_PATH_NAMES        = NO
-
-# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
-# can be used to strip a user-defined part of the path. Stripping is
-# only done if one of the specified strings matches the left-hand part of
-# the path. The tag can be used to show relative paths in the file list.
-# If left blank the directory from which doxygen is run is used as the
-# path to strip.
-
-STRIP_FROM_PATH        = 
-
-# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
-# the path mentioned in the documentation of a class, which tells
-# the reader which header file to include in order to use a class.
-# If left blank only the name of the header file containing the class
-# definition is used. Otherwise one should specify the include paths that
-# are normally passed to the compiler using the -I flag.
-
-STRIP_FROM_INC_PATH    =
-
-# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
-# (but less readable) file names. This can be useful if your file system
-# doesn't support long names like on DOS, Mac, or CD-ROM.
-
-SHORT_NAMES            = NO
-
-# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
-# will interpret the first line (until the first dot) of a JavaDoc-style
-# comment as the brief description. If set to NO, the JavaDoc
-# comments will behave just like regular Qt-style comments
-# (thus requiring an explicit @brief command for a brief description.)
-
-JAVADOC_AUTOBRIEF      = NO
-
-# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
-# interpret the first line (until the first dot) of a Qt-style
-# comment as the brief description. If set to NO, the comments
-# will behave just like regular Qt-style comments (thus requiring
-# an explicit \brief command for a brief description.)
-
-QT_AUTOBRIEF           = NO
-
-# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
-# treat a multi-line C++ special comment block (i.e. a block of //! or ///
-# comments) as a brief description. This used to be the default behaviour.
-# The new default is to treat a multi-line C++ comment block as a detailed
-# description. Set this tag to YES if you prefer the old behaviour instead.
-
-MULTILINE_CPP_IS_BRIEF = NO
-
-# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
-# member inherits the documentation from any documented member that it
-# re-implements.
-
-INHERIT_DOCS           = YES
-
-# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
-# a new page for each member. If set to NO, the documentation of a member will
-# be part of the file/class/namespace that contains it.
-
-SEPARATE_MEMBER_PAGES  = NO
-
-# The TAB_SIZE tag can be used to set the number of spaces in a tab.
-# Doxygen uses this value to replace tabs by spaces in code fragments.
-
-TAB_SIZE               = 8
-
-# This tag can be used to specify a number of aliases that acts
-# as commands in the documentation. An alias has the form "name=value".
-# For example adding "sideeffect=\par Side Effects:\n" will allow you to
-# put the command \sideeffect (or @sideeffect) in the documentation, which
-# will result in a user-defined paragraph with heading "Side Effects:".
-# You can put \n's in the value part of an alias to insert newlines.
-
-ALIASES                =
-
-# This tag can be used to specify a number of word-keyword mappings (TCL only).
-# A mapping has the form "name=value". For example adding
-# "class=itcl::class" will allow you to use the command class in the
-# itcl::class meaning.
-
-TCL_SUBST              =
-
-# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
-# sources only. Doxygen will then generate output that is more tailored for C.
-# For instance, some of the names that are used will be different. The list
-# of all members will be omitted, etc.
-
-OPTIMIZE_OUTPUT_FOR_C  = YES
-
-# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
-# sources only. Doxygen will then generate output that is more tailored for
-# Java. For instance, namespaces will be presented as packages, qualified
-# scopes will look different, etc.
-
-OPTIMIZE_OUTPUT_JAVA   = NO
-
-# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
-# sources only. Doxygen will then generate output that is more tailored for
-# Fortran.
-
-OPTIMIZE_FOR_FORTRAN   = NO
-
-# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
-# sources. Doxygen will then generate output that is tailored for
-# VHDL.
-
-OPTIMIZE_OUTPUT_VHDL   = NO
-
-# Doxygen selects the parser to use depending on the extension of the files it
-# parses. With this tag you can assign which parser to use for a given extension.
-# Doxygen has a built-in mapping, but you can override or extend it using this
-# tag. The format is ext=language, where ext is a file extension, and language
-# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C,
-# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make
-# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
-# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions
-# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen.
-
-EXTENSION_MAPPING      =
-
-# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all
-# comments according to the Markdown format, which allows for more readable
-# documentation. See http://daringfireball.net/projects/markdown/ for details.
-# The output of markdown processing is further processed by doxygen, so you
-# can mix doxygen, HTML, and XML commands with Markdown formatting.
-# Disable only in case of backward compatibilities issues.
-
-MARKDOWN_SUPPORT       = YES
-
-# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
-# to include (a tag file for) the STL sources as input, then you should
-# set this tag to YES in order to let doxygen match functions declarations and
-# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
-# func(std::string) {}). This also makes the inheritance and collaboration
-# diagrams that involve STL classes more complete and accurate.
-
-BUILTIN_STL_SUPPORT    = NO
-
-# If you use Microsoft's C++/CLI language, you should set this option to YES to
-# enable parsing support.
-
-CPP_CLI_SUPPORT        = NO
-
-# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
-# Doxygen will parse them like normal C++ but will assume all classes use public
-# instead of private inheritance when no explicit protection keyword is present.
-
-SIP_SUPPORT            = NO
-
-# For Microsoft's IDL there are propget and propput attributes to indicate getter
-# and setter methods for a property. Setting this option to YES (the default)
-# will make doxygen replace the get and set methods by a property in the
-# documentation. This will only work if the methods are indeed getting or
-# setting a simple type. If this is not the case, or you want to show the
-# methods anyway, you should set this option to NO.
-
-IDL_PROPERTY_SUPPORT   = YES
-
-# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
-# tag is set to YES, then doxygen will reuse the documentation of the first
-# member in the group (if any) for the other members of the group. By default
-# all members of a group must be documented explicitly.
-
-DISTRIBUTE_GROUP_DOC   = NO
-
-# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
-# the same type (for instance a group of public functions) to be put as a
-# subgroup of that type (e.g. under the Public Functions section). Set it to
-# NO to prevent subgrouping. Alternatively, this can be done per class using
-# the \nosubgrouping command.
-
-SUBGROUPING            = YES
-
-# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and
-# unions are shown inside the group in which they are included (e.g. using
-# @ingroup) instead of on a separate page (for HTML and Man pages) or
-# section (for LaTeX and RTF).
-
-INLINE_GROUPED_CLASSES = NO
-
-# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and
-# unions with only public data fields will be shown inline in the documentation
-# of the scope in which they are defined (i.e. file, namespace, or group
-# documentation), provided this scope is documented. If set to NO (the default),
-# structs, classes, and unions are shown on a separate page (for HTML and Man
-# pages) or section (for LaTeX and RTF).
-
-INLINE_SIMPLE_STRUCTS  = NO
-
-# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
-# is documented as struct, union, or enum with the name of the typedef. So
-# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
-# with name TypeT. When disabled the typedef will appear as a member of a file,
-# namespace, or class. And the struct will be named TypeS. This can typically
-# be useful for C code in case the coding convention dictates that all compound
-# types are typedef'ed and only the typedef is referenced, never the tag name.
-
-TYPEDEF_HIDES_STRUCT   = NO
-
-# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
-# determine which symbols to keep in memory and which to flush to disk.
-# When the cache is full, less often used symbols will be written to disk.
-# For small to medium size projects (<1000 input files) the default value is
-# probably good enough. For larger projects a too small cache size can cause
-# doxygen to be busy swapping symbols to and from disk most of the time
-# causing a significant performance penalty.
-# If the system has enough physical memory increasing the cache will improve the
-# performance by keeping more symbols in memory. Note that the value works on
-# a logarithmic scale so increasing the size by one will roughly double the
-# memory usage. The cache size is given by this formula:
-# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
-# corresponding to a cache size of 2^16 = 65536 symbols.
-
-# SYMBOL_CACHE_SIZE      = 0
-
-# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be
-# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given
-# their name and scope. Since this can be an expensive process and often the
-# same symbol appear multiple times in the code, doxygen keeps a cache of
-# pre-resolved symbols. If the cache is too small doxygen will become slower.
-# If the cache is too large, memory is wasted. The cache size is given by this
-# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0,
-# corresponding to a cache size of 2^16 = 65536 symbols.
-
-LOOKUP_CACHE_SIZE      = 0
-
-#---------------------------------------------------------------------------
-# Build related configuration options
-#---------------------------------------------------------------------------
-
-# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
-# documentation are documented, even if no documentation was available.
-# Private class members and static file members will be hidden unless
-# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
-
-EXTRACT_ALL            = NO
-
-# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
-# will be included in the documentation.
-
-EXTRACT_PRIVATE        = NO
-
-# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal scope will be included in the documentation.
-
-EXTRACT_PACKAGE        = NO
-
-# If the EXTRACT_STATIC tag is set to YES all static members of a file
-# will be included in the documentation.
-
-EXTRACT_STATIC         = NO
-
-# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
-# defined locally in source files will be included in the documentation.
-# If set to NO only classes defined in header files are included.
-
-EXTRACT_LOCAL_CLASSES  = YES
-
-# This flag is only useful for Objective-C code. When set to YES local
-# methods, which are defined in the implementation section but not in
-# the interface are included in the documentation.
-# If set to NO (the default) only methods in the interface are included.
-
-EXTRACT_LOCAL_METHODS  = NO
-
-# If this flag is set to YES, the members of anonymous namespaces will be
-# extracted and appear in the documentation as a namespace called
-# 'anonymous_namespace{file}', where file will be replaced with the base
-# name of the file that contains the anonymous namespace. By default
-# anonymous namespaces are hidden.
-
-EXTRACT_ANON_NSPACES   = NO
-
-# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
-# undocumented members of documented classes, files or namespaces.
-# If set to NO (the default) these members will be included in the
-# various overviews, but no documentation section is generated.
-# This option has no effect if EXTRACT_ALL is enabled.
-
-HIDE_UNDOC_MEMBERS     = NO
-
-# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
-# undocumented classes that are normally visible in the class hierarchy.
-# If set to NO (the default) these classes will be included in the various
-# overviews. This option has no effect if EXTRACT_ALL is enabled.
-
-HIDE_UNDOC_CLASSES     = NO
-
-# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
-# friend (class|struct|union) declarations.
-# If set to NO (the default) these declarations will be included in the
-# documentation.
-
-HIDE_FRIEND_COMPOUNDS  = NO
-
-# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
-# documentation blocks found inside the body of a function.
-# If set to NO (the default) these blocks will be appended to the
-# function's detailed documentation block.
-
-HIDE_IN_BODY_DOCS      = NO
-
-# The INTERNAL_DOCS tag determines if documentation
-# that is typed after a \internal command is included. If the tag is set
-# to NO (the default) then the documentation will be excluded.
-# Set it to YES to include the internal documentation.
-
-INTERNAL_DOCS          = NO
-
-# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
-# file names in lower-case letters. If set to YES upper-case letters are also
-# allowed. This is useful if you have classes or files whose names only differ
-# in case and if your file system supports case sensitive file names. Windows
-# and Mac users are advised to set this option to NO.
-
-CASE_SENSE_NAMES       = YES
-
-# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
-# will show members with their full class and namespace scopes in the
-# documentation. If set to YES the scope will be hidden.
-
-HIDE_SCOPE_NAMES       = NO
-
-# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
-# will put a list of the files that are included by a file in the documentation
-# of that file.
-
-SHOW_INCLUDE_FILES     = YES
-
-# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
-# will list include files with double quotes in the documentation
-# rather than with sharp brackets.
-
-FORCE_LOCAL_INCLUDES   = NO
-
-# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
-# is inserted in the documentation for inline members.
-
-INLINE_INFO            = YES
-
-# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
-# will sort the (detailed) documentation of file and class members
-# alphabetically by member name. If set to NO the members will appear in
-# declaration order.
-
-SORT_MEMBER_DOCS       = YES
-
-# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
-# brief documentation of file, namespace and class members alphabetically
-# by member name. If set to NO (the default) the members will appear in
-# declaration order.
-
-SORT_BRIEF_DOCS        = NO
-
-# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
-# will sort the (brief and detailed) documentation of class members so that
-# constructors and destructors are listed first. If set to NO (the default)
-# the constructors will appear in the respective orders defined by
-# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
-# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
-# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
-
-SORT_MEMBERS_CTORS_1ST = NO
-
-# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
-# hierarchy of group names into alphabetical order. If set to NO (the default)
-# the group names will appear in their defined order.
-
-SORT_GROUP_NAMES       = NO
-
-# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
-# sorted by fully-qualified names, including namespaces. If set to
-# NO (the default), the class list will be sorted only by class name,
-# not including the namespace part.
-# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
-# Note: This option applies only to the class list, not to the
-# alphabetical list.
-
-SORT_BY_SCOPE_NAME     = NO
-
-# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to
-# do proper type resolution of all parameters of a function it will reject a
-# match between the prototype and the implementation of a member function even
-# if there is only one candidate or it is obvious which candidate to choose
-# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen
-# will still accept a match between prototype and implementation in such cases.
-
-STRICT_PROTO_MATCHING  = NO
-
-# The GENERATE_TODOLIST tag can be used to enable (YES) or
-# disable (NO) the todo list. This list is created by putting \todo
-# commands in the documentation.
-
-GENERATE_TODOLIST      = YES
-
-# The GENERATE_TESTLIST tag can be used to enable (YES) or
-# disable (NO) the test list. This list is created by putting \test
-# commands in the documentation.
-
-GENERATE_TESTLIST      = YES
-
-# The GENERATE_BUGLIST tag can be used to enable (YES) or
-# disable (NO) the bug list. This list is created by putting \bug
-# commands in the documentation.
-
-GENERATE_BUGLIST       = YES
-
-# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
-# disable (NO) the deprecated list. This list is created by putting
-# \deprecated commands in the documentation.
-
-GENERATE_DEPRECATEDLIST= YES
-
-# The ENABLED_SECTIONS tag can be used to enable conditional
-# documentation sections, marked by \if sectionname ... \endif.
-
-ENABLED_SECTIONS       =
-
-# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
-# the initial value of a variable or macro consists of for it to appear in
-# the documentation. If the initializer consists of more lines than specified
-# here it will be hidden. Use a value of 0 to hide initializers completely.
-# The appearance of the initializer of individual variables and macros in the
-# documentation can be controlled using \showinitializer or \hideinitializer
-# command in the documentation regardless of this setting.
-
-MAX_INITIALIZER_LINES  = 30
-
-# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
-# at the bottom of the documentation of classes and structs. If set to YES the
-# list will mention the files that were used to generate the documentation.
-
-SHOW_USED_FILES        = YES
-
-# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
-# This will remove the Files entry from the Quick Index and from the
-# Folder Tree View (if specified). The default is YES.
-
-SHOW_FILES             = YES
-
-# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
-# Namespaces page.
-# This will remove the Namespaces entry from the Quick Index
-# and from the Folder Tree View (if specified). The default is YES.
-
-SHOW_NAMESPACES        = YES
-
-# The FILE_VERSION_FILTER tag can be used to specify a program or script that
-# doxygen should invoke to get the current version for each file (typically from
-# the version control system). Doxygen will invoke the program by executing (via
-# popen()) the command <command> <input-file>, where <command> is the value of
-# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
-# provided by doxygen. Whatever the program writes to standard output
-# is used as the file version. See the manual for examples.
-
-FILE_VERSION_FILTER    =
-
-# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
-# by doxygen. The layout file controls the global structure of the generated
-# output files in an output format independent way. To create the layout file
-# that represents doxygen's defaults, run doxygen with the -l option.
-# You can optionally specify a file name after the option, if omitted
-# DoxygenLayout.xml will be used as the name of the layout file.
-
-LAYOUT_FILE            =
-
-# The CITE_BIB_FILES tag can be used to specify one or more bib files
-# containing the references data. This must be a list of .bib files. The
-# .bib extension is automatically appended if omitted. Using this command
-# requires the bibtex tool to be installed. See also
-# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style
-# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this
-# feature you need bibtex and perl available in the search path.
-
-CITE_BIB_FILES         =
-
-#---------------------------------------------------------------------------
-# configuration options related to warning and progress messages
-#---------------------------------------------------------------------------
-
-# The QUIET tag can be used to turn on/off the messages that are generated
-# by doxygen. Possible values are YES and NO. If left blank NO is used.
-
-QUIET                  = NO
-
-# The WARNINGS tag can be used to turn on/off the warning messages that are
-# generated by doxygen. Possible values are YES and NO. If left blank
-# NO is used.
-
-WARNINGS               = YES
-
-# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
-# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
-# automatically be disabled.
-
-WARN_IF_UNDOCUMENTED   = YES
-
-# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
-# potential errors in the documentation, such as not documenting some
-# parameters in a documented function, or documenting parameters that
-# don't exist or using markup commands wrongly.
-
-WARN_IF_DOC_ERROR      = YES
-
-# The WARN_NO_PARAMDOC option can be enabled to get warnings for
-# functions that are documented, but have no documentation for their parameters
-# or return value. If set to NO (the default) doxygen will only warn about
-# wrong or incomplete parameter documentation, but not about the absence of
-# documentation.
-
-WARN_NO_PARAMDOC       = NO
-
-# The WARN_FORMAT tag determines the format of the warning messages that
-# doxygen can produce. The string should contain the $file, $line, and $text
-# tags, which will be replaced by the file and line number from which the
-# warning originated and the warning text. Optionally the format may contain
-# $version, which will be replaced by the version of the file (if it could
-# be obtained via FILE_VERSION_FILTER)
-
-WARN_FORMAT            = "$file:$line: $text"
-
-# The WARN_LOGFILE tag can be used to specify a file to which warning
-# and error messages should be written. If left blank the output is written
-# to stderr.
-
-WARN_LOGFILE           =
-
-#---------------------------------------------------------------------------
-# configuration options related to the input files
-#---------------------------------------------------------------------------
-
-# The INPUT tag can be used to specify the files and/or directories that contain
-# documented source files. You may enter file names like "myfile.cpp" or
-# directories like "/usr/src/myproject". Separate the files or directories
-# with spaces.
-
-INPUT                  =  @CMAKE_CURRENT_SOURCE_DIR@/../c/ecdh.h \
-                          @CMAKE_CURRENT_SOURCE_DIR@/../c/mpin.h \
-                          @CMAKE_CURRENT_SOURCE_DIR@/../c/wcc.c \
-                          @CMAKE_CURRENT_SOURCE_DIR@/../c/rsa.h \
-                          @CMAKE_CURRENT_SOURCE_DIR@/AMCL.dox
-
-# This tag can be used to specify the character encoding of the source files
-# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
-# also the default input encoding. Doxygen uses libiconv (or the iconv built
-# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
-# the list of possible encodings.
-
-INPUT_ENCODING         = UTF-8
-
-# If the value of the INPUT tag contains directories, you can use the
-# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
-# and *.h) to filter out the source-files in the directories. If left
-# blank the following patterns are tested:
-# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh
-# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py
-# *.f90 *.f *.for *.vhd *.vhdl
-
-FILE_PATTERNS          =
-
-# The RECURSIVE tag can be used to turn specify whether or not subdirectories
-# should be searched for input files as well. Possible values are YES and NO.
-# If left blank NO is used.
-
-RECURSIVE              = NO
-
-# The EXCLUDE tag can be used to specify files and/or directories that should be
-# excluded from the INPUT source files. This way you can easily exclude a
-# subdirectory from a directory tree whose root is specified with the INPUT tag.
-# Note that relative paths are relative to the directory from which doxygen is
-# run.
-
-EXCLUDE                = 
-
-# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
-# directories that are symbolic links (a Unix file system feature) are excluded
-# from the input.
-
-EXCLUDE_SYMLINKS       = NO
-
-# If the value of the INPUT tag contains directories, you can use the
-# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
-# certain files from those directories. Note that the wildcards are matched
-# against the file with absolute path, so to exclude all test directories
-# for example use the pattern */test/*
-
-EXCLUDE_PATTERNS       =
-
-# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
-# (namespaces, classes, functions, etc.) that should be excluded from the
-# output. The symbol name can be a fully qualified name, a word, or if the
-# wildcard * is used, a substring. Examples: ANamespace, AClass,
-# AClass::ANamespace, ANamespace::*Test
-
-EXCLUDE_SYMBOLS        =
-
-# The EXAMPLE_PATH tag can be used to specify one or more files or
-# directories that contain example code fragments that are included (see
-# the \include command).
-
-EXAMPLE_PATH           =
-
-# If the value of the EXAMPLE_PATH tag contains directories, you can use the
-# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
-# and *.h) to filter out the source-files in the directories. If left
-# blank all files are included.
-
-EXAMPLE_PATTERNS       =
-
-# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
-# searched for input files to be used with the \include or \dontinclude
-# commands irrespective of the value of the RECURSIVE tag.
-# Possible values are YES and NO. If left blank NO is used.
-
-EXAMPLE_RECURSIVE      = NO
-
-# The IMAGE_PATH tag can be used to specify one or more files or
-# directories that contain image that are included in the documentation (see
-# the \image command).
-
-IMAGE_PATH             = @CMAKE_CURRENT_BINARY_DIR@/
-
-# The INPUT_FILTER tag can be used to specify a program that doxygen should
-# invoke to filter for each input file. Doxygen will invoke the filter program
-# by executing (via popen()) the command <filter> <input-file>, where <filter>
-# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
-# input file. Doxygen will then use the output that the filter program writes
-# to standard output.
-# If FILTER_PATTERNS is specified, this tag will be
-# ignored.
-
-INPUT_FILTER           =
-
-# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
-# basis.
-# Doxygen will compare the file name with each pattern and apply the
-# filter if there is a match.
-# The filters are a list of the form:
-# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
-# info on how filters are used. If FILTER_PATTERNS is empty or if
-# non of the patterns match the file name, INPUT_FILTER is applied.
-
-FILTER_PATTERNS        =
-
-# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
-# INPUT_FILTER) will be used to filter the input files when producing source
-# files to browse (i.e. when SOURCE_BROWSER is set to YES).
-
-FILTER_SOURCE_FILES    = NO
-
-# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
-# pattern. A pattern will override the setting for FILTER_PATTERN (if any)
-# and it is also possible to disable source filtering for a specific pattern
-# using *.ext= (so without naming a filter). This option only has effect when
-# FILTER_SOURCE_FILES is enabled.
-
-FILTER_SOURCE_PATTERNS =
-
-#---------------------------------------------------------------------------
-# configuration options related to source browsing
-#---------------------------------------------------------------------------
-
-# If the SOURCE_BROWSER tag is set to YES then a list of source files will
-# be generated. Documented entities will be cross-referenced with these sources.
-# Note: To get rid of all source code in the generated output, make sure also
-# VERBATIM_HEADERS is set to NO.
-
-SOURCE_BROWSER         = NO
-
-# Setting the INLINE_SOURCES tag to YES will include the body
-# of functions and classes directly in the documentation.
-
-INLINE_SOURCES         = NO
-
-# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
-# doxygen to hide any special comment blocks from generated source code
-# fragments. Normal C, C++ and Fortran comments will always remain visible.
-
-STRIP_CODE_COMMENTS    = YES
-
-# If the REFERENCED_BY_RELATION tag is set to YES
-# then for each documented function all documented
-# functions referencing it will be listed.
-
-REFERENCED_BY_RELATION = NO
-
-# If the REFERENCES_RELATION tag is set to YES
-# then for each documented function all documented entities
-# called/used by that function will be listed.
-
-REFERENCES_RELATION    = NO
-
-# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
-# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
-# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
-# link to the source code.
-# Otherwise they will link to the documentation.
-
-REFERENCES_LINK_SOURCE = YES
-
-# If the USE_HTAGS tag is set to YES then the references to source code
-# will point to the HTML generated by the htags(1) tool instead of doxygen
-# built-in source browser. The htags tool is part of GNU's global source
-# tagging system (see http://www.gnu.org/software/global/global.html). You
-# will need version 4.8.6 or higher.
-
-USE_HTAGS              = NO
-
-# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
-# will generate a verbatim copy of the header file for each class for
-# which an include is specified. Set to NO to disable this.
-
-VERBATIM_HEADERS       = YES
-
-#---------------------------------------------------------------------------
-# configuration options related to the alphabetical class index
-#---------------------------------------------------------------------------
-
-# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
-# of all compounds will be generated. Enable this if the project
-# contains a lot of classes, structs, unions or interfaces.
-
-ALPHABETICAL_INDEX     = YES
-
-# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
-# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
-# in which this list will be split (can be a number in the range [1..20])
-
-COLS_IN_ALPHA_INDEX    = 5
-
-# In case all classes in a project start with a common prefix, all
-# classes will be put under the same header in the alphabetical index.
-# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
-# should be ignored while generating the index headers.
-
-IGNORE_PREFIX          =
-
-#---------------------------------------------------------------------------
-# configuration options related to the HTML output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
-# generate HTML output.
-
-GENERATE_HTML          = YES
-
-# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `html' will be used as the default path.
-
-HTML_OUTPUT            = html
-
-# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
-# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
-# doxygen will generate files with .html extension.
-
-HTML_FILE_EXTENSION    = .html
-
-# The HTML_HEADER tag can be used to specify a personal HTML header for
-# each generated HTML page. If it is left blank doxygen will generate a
-# standard header. Note that when using a custom header you are responsible
-#  for the proper inclusion of any scripts and style sheets that doxygen
-# needs, which is dependent on the configuration options used.
-# It is advised to generate a default header using "doxygen -w html
-# header.html footer.html stylesheet.css YourConfigFile" and then modify
-# that header. Note that the header is subject to change so you typically
-# have to redo this when upgrading to a newer version of doxygen or when
-# changing the value of configuration settings such as GENERATE_TREEVIEW!
-
-HTML_HEADER            =
-
-# The HTML_FOOTER tag can be used to specify a personal HTML footer for
-# each generated HTML page. If it is left blank doxygen will generate a
-# standard footer.
-
-HTML_FOOTER            =
-
-# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
-# style sheet that is used by each HTML page. It can be used to
-# fine-tune the look of the HTML output. If the tag is left blank doxygen
-# will generate a default style sheet. Note that doxygen will try to copy
-# the style sheet file to the HTML output directory, so don't put your own
-# style sheet in the HTML output directory as well, or it will be erased!
-
-HTML_STYLESHEET        =
-
-# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
-# other source files which should be copied to the HTML output directory. Note
-# that these files will be copied to the base HTML output directory. Use the
-# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
-# files. In the HTML_STYLESHEET file, use the file name only. Also note that
-# the files will be copied as-is; there are no commands or markers available.
-
-HTML_EXTRA_FILES       =
-
-# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
-# Doxygen will adjust the colors in the style sheet and background images
-# according to this color. Hue is specified as an angle on a colorwheel,
-# see http://en.wikipedia.org/wiki/Hue for more information.
-# For instance the value 0 represents red, 60 is yellow, 120 is green,
-# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
-# The allowed range is 0 to 359.
-
-HTML_COLORSTYLE_HUE    = 220
-
-# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
-# the colors in the HTML output. For a value of 0 the output will use
-# grayscales only. A value of 255 will produce the most vivid colors.
-
-HTML_COLORSTYLE_SAT    = 100
-
-# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
-# the luminance component of the colors in the HTML output. Values below
-# 100 gradually make the output lighter, whereas values above 100 make
-# the output darker. The value divided by 100 is the actual gamma applied,
-# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
-# and 100 does not change the gamma.
-
-HTML_COLORSTYLE_GAMMA  = 80
-
-# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
-# page will contain the date and time when the page was generated. Setting
-# this to NO can help when comparing the output of multiple runs.
-
-HTML_TIMESTAMP         = NO
-
-# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
-# documentation will contain sections that can be hidden and shown after the
-# page has loaded.
-
-HTML_DYNAMIC_SECTIONS  = NO
-
-# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of
-# entries shown in the various tree structured indices initially; the user
-# can expand and collapse entries dynamically later on. Doxygen will expand
-# the tree to such a level that at most the specified number of entries are
-# visible (unless a fully collapsed tree already exceeds this amount).
-# So setting the number of entries 1 will produce a full collapsed tree by
-# default. 0 is a special value representing an infinite number of entries
-# and will result in a full expanded tree by default.
-
-HTML_INDEX_NUM_ENTRIES = 100
-
-# If the GENERATE_DOCSET tag is set to YES, additional index files
-# will be generated that can be used as input for Apple's Xcode 3
-# integrated development environment, introduced with OSX 10.5 (Leopard).
-# To create a documentation set, doxygen will generate a Makefile in the
-# HTML output directory. Running make will produce the docset in that
-# directory and running "make install" will install the docset in
-# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
-# it at startup.
-# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
-# for more information.
-
-GENERATE_DOCSET        = NO
-
-# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
-# feed. A documentation feed provides an umbrella under which multiple
-# documentation sets from a single provider (such as a company or product suite)
-# can be grouped.
-
-DOCSET_FEEDNAME        = "Doxygen generated docs"
-
-# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
-# should uniquely identify the documentation set bundle. This should be a
-# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
-# will append .docset to the name.
-
-DOCSET_BUNDLE_ID       = org.doxygen.Project
-
-# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify
-# the documentation publisher. This should be a reverse domain-name style
-# string, e.g. com.mycompany.MyDocSet.documentation.
-
-DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
-
-# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
-
-DOCSET_PUBLISHER_NAME  = Publisher
-
-# If the GENERATE_HTMLHELP tag is set to YES, additional index files
-# will be generated that can be used as input for tools like the
-# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
-# of the generated HTML documentation.
-
-GENERATE_HTMLHELP      = NO
-
-# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
-# be used to specify the file name of the resulting .chm file. You
-# can add a path in front of the file if the result should not be
-# written to the html output directory.
-
-CHM_FILE               =
-
-# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
-# be used to specify the location (absolute path including file name) of
-# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
-# the HTML help compiler on the generated index.hhp.
-
-HHC_LOCATION           =
-
-# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
-# controls if a separate .chi index file is generated (YES) or that
-# it should be included in the master .chm file (NO).
-
-GENERATE_CHI           = NO
-
-# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
-# is used to encode HtmlHelp index (hhk), content (hhc) and project file
-# content.
-
-CHM_INDEX_ENCODING     =
-
-# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
-# controls whether a binary table of contents is generated (YES) or a
-# normal table of contents (NO) in the .chm file.
-
-BINARY_TOC             = NO
-
-# The TOC_EXPAND flag can be set to YES to add extra items for group members
-# to the contents of the HTML help documentation and to the tree view.
-
-TOC_EXPAND             = NO
-
-# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
-# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated
-# that can be used as input for Qt's qhelpgenerator to generate a
-# Qt Compressed Help (.qch) of the generated HTML documentation.
-
-GENERATE_QHP           = NO
-
-# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
-# be used to specify the file name of the resulting .qch file.
-# The path specified is relative to the HTML output folder.
-
-QCH_FILE               =
-
-# The QHP_NAMESPACE tag specifies the namespace to use when generating
-# Qt Help Project output. For more information please see
-# http://doc.trolltech.com/qthelpproject.html#namespace
-
-QHP_NAMESPACE          = org.doxygen.Project
-
-# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
-# Qt Help Project output. For more information please see
-# http://doc.trolltech.com/qthelpproject.html#virtual-folders
-
-QHP_VIRTUAL_FOLDER     = doc
-
-# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to
-# add. For more information please see
-# http://doc.trolltech.com/qthelpproject.html#custom-filters
-
-QHP_CUST_FILTER_NAME   =
-
-# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the
-# custom filter to add. For more information please see
-# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">
-# Qt Help Project / Custom Filters</a>.
-
-QHP_CUST_FILTER_ATTRS  =
-
-# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
-# project's
-# filter section matches.
-# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">
-# Qt Help Project / Filter Attributes</a>.
-
-QHP_SECT_FILTER_ATTRS  =
-
-# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
-# be used to specify the location of Qt's qhelpgenerator.
-# If non-empty doxygen will try to run qhelpgenerator on the generated
-# .qhp file.
-
-QHG_LOCATION           =
-
-# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
-#  will be generated, which together with the HTML files, form an Eclipse help
-# plugin. To install this plugin and make it available under the help contents
-# menu in Eclipse, the contents of the directory containing the HTML and XML
-# files needs to be copied into the plugins directory of eclipse. The name of
-# the directory within the plugins directory should be the same as
-# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before
-# the help appears.
-
-GENERATE_ECLIPSEHELP   = NO
-
-# A unique identifier for the eclipse help plugin. When installing the plugin
-# the directory name containing the HTML and XML files should also have
-# this name.
-
-ECLIPSE_DOC_ID         = org.doxygen.Project
-
-# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs)
-# at top of each HTML page. The value NO (the default) enables the index and
-# the value YES disables it. Since the tabs have the same information as the
-# navigation tree you can set this option to NO if you already set
-# GENERATE_TREEVIEW to YES.
-
-DISABLE_INDEX          = NO
-
-# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
-# structure should be generated to display hierarchical information.
-# If the tag value is set to YES, a side panel will be generated
-# containing a tree-like index structure (just like the one that
-# is generated for HTML Help). For this to work a browser that supports
-# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
-# Windows users are probably better off using the HTML help feature.
-# Since the tree basically has the same information as the tab index you
-# could consider to set DISABLE_INDEX to NO when enabling this option.
-
-GENERATE_TREEVIEW      = NO
-
-# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values
-# (range [0,1..20]) that doxygen will group on one line in the generated HTML
-# documentation. Note that a value of 0 will completely suppress the enum
-# values from appearing in the overview section.
-
-ENUM_VALUES_PER_LINE   = 4
-
-# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
-# used to set the initial width (in pixels) of the frame in which the tree
-# is shown.
-
-TREEVIEW_WIDTH         = 250
-
-# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open
-# links to external symbols imported via tag files in a separate window.
-
-EXT_LINKS_IN_WINDOW    = NO
-
-# Use this tag to change the font size of Latex formulas included
-# as images in the HTML documentation. The default is 10. Note that
-# when you change the font size after a successful doxygen run you need
-# to manually remove any form_*.png images from the HTML output directory
-# to force them to be regenerated.
-
-FORMULA_FONTSIZE       = 10
-
-# Use the FORMULA_TRANPARENT tag to determine whether or not the images
-# generated for formulas are transparent PNGs. Transparent PNGs are
-# not supported properly for IE 6.0, but are supported on all modern browsers.
-# Note that when changing this option you need to delete any form_*.png files
-# in the HTML output before the changes have effect.
-
-FORMULA_TRANSPARENT    = YES
-
-# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax
-# (see http://www.mathjax.org) which uses client side Javascript for the
-# rendering instead of using prerendered bitmaps. Use this if you do not
-# have LaTeX installed or if you want to formulas look prettier in the HTML
-# output. When enabled you may also need to install MathJax separately and
-# configure the path to it using the MATHJAX_RELPATH option.
-
-USE_MATHJAX            = NO
-
-# When MathJax is enabled you need to specify the location relative to the
-# HTML output directory using the MATHJAX_RELPATH option. The destination
-# directory should contain the MathJax.js script. For instance, if the mathjax
-# directory is located at the same level as the HTML output directory, then
-# MATHJAX_RELPATH should be ../mathjax. The default value points to
-# the MathJax Content Delivery Network so you can quickly see the result without
-# installing MathJax.
-# However, it is strongly recommended to install a local
-# copy of MathJax from http://www.mathjax.org before deployment.
-
-MATHJAX_RELPATH        = http://cdn.mathjax.org/mathjax/latest
-
-# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension
-# names that should be enabled during MathJax rendering.
-
-MATHJAX_EXTENSIONS     =
-
-# When the SEARCHENGINE tag is enabled doxygen will generate a search box
-# for the HTML output. The underlying search engine uses javascript
-# and DHTML and should work on any modern browser. Note that when using
-# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets
-# (GENERATE_DOCSET) there is already a search function so this one should
-# typically be disabled. For large projects the javascript based search engine
-# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
-
-SEARCHENGINE           = YES
-
-# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
-# implemented using a PHP enabled web server instead of at the web client
-# using Javascript. Doxygen will generate the search PHP script and index
-# file to put on the web server. The advantage of the server
-# based approach is that it scales better to large projects and allows
-# full text search. The disadvantages are that it is more difficult to setup
-# and does not have live searching capabilities.
-
-SERVER_BASED_SEARCH    = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to the LaTeX output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
-# generate Latex output.
-
-GENERATE_LATEX         = YES
-
-# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `latex' will be used as the default path.
-
-LATEX_OUTPUT           = latex
-
-# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
-# invoked. If left blank `latex' will be used as the default command name.
-# Note that when enabling USE_PDFLATEX this option is only used for
-# generating bitmaps for formulas in the HTML output, but not in the
-# Makefile that is written to the output directory.
-
-LATEX_CMD_NAME         = latex
-
-# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
-# generate index for LaTeX. If left blank `makeindex' will be used as the
-# default command name.
-
-MAKEINDEX_CMD_NAME     = makeindex
-
-# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
-# LaTeX documents. This may be useful for small projects and may help to
-# save some trees in general.
-
-COMPACT_LATEX          = NO
-
-# The PAPER_TYPE tag can be used to set the paper type that is used
-# by the printer. Possible values are: a4, letter, legal and
-# executive. If left blank a4wide will be used.
-
-PAPER_TYPE             = a4
-
-# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
-# packages that should be included in the LaTeX output.
-
-EXTRA_PACKAGES         =
-
-# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
-# the generated latex document. The header should contain everything until
-# the first chapter. If it is left blank doxygen will generate a
-# standard header. Notice: only use this tag if you know what you are doing!
-
-LATEX_HEADER           =
-
-# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for
-# the generated latex document. The footer should contain everything after
-# the last chapter. If it is left blank doxygen will generate a
-# standard footer. Notice: only use this tag if you know what you are doing!
-
-LATEX_FOOTER           =
-
-# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
-# is prepared for conversion to pdf (using ps2pdf). The pdf file will
-# contain links (just like the HTML output) instead of page references
-# This makes the output suitable for online browsing using a pdf viewer.
-
-PDF_HYPERLINKS         = YES
-
-# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
-# plain latex in the generated Makefile. Set this option to YES to get a
-# higher quality PDF documentation.
-
-USE_PDFLATEX           = YES
-
-# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
-# command to the generated LaTeX files. This will instruct LaTeX to keep
-# running if errors occur, instead of asking the user for help.
-# This option is also used when generating formulas in HTML.
-
-LATEX_BATCHMODE        = NO
-
-# If LATEX_HIDE_INDICES is set to YES then doxygen will not
-# include the index chapters (such as File Index, Compound Index, etc.)
-# in the output.
-
-LATEX_HIDE_INDICES     = NO
-
-# If LATEX_SOURCE_CODE is set to YES then doxygen will include
-# source code with syntax highlighting in the LaTeX output.
-# Note that which sources are shown also depends on other settings
-# such as SOURCE_BROWSER.
-
-LATEX_SOURCE_CODE      = NO
-
-# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
-# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See
-# http://en.wikipedia.org/wiki/BibTeX for more info.
-
-LATEX_BIB_STYLE        = plain
-
-#---------------------------------------------------------------------------
-# configuration options related to the RTF output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
-# The RTF output is optimized for Word 97 and may not look very pretty with
-# other RTF readers or editors.
-
-GENERATE_RTF           = NO
-
-# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `rtf' will be used as the default path.
-
-RTF_OUTPUT             = rtf
-
-# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
-# RTF documents. This may be useful for small projects and may help to
-# save some trees in general.
-
-COMPACT_RTF            = NO
-
-# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
-# will contain hyperlink fields. The RTF file will
-# contain links (just like the HTML output) instead of page references.
-# This makes the output suitable for online browsing using WORD or other
-# programs which support those fields.
-# Note: wordpad (write) and others do not support links.
-
-RTF_HYPERLINKS         = NO
-
-# Load style sheet definitions from file. Syntax is similar to doxygen's
-# config file, i.e. a series of assignments. You only have to provide
-# replacements, missing definitions are set to their default value.
-
-RTF_STYLESHEET_FILE    =
-
-# Set optional variables used in the generation of an rtf document.
-# Syntax is similar to doxygen's config file.
-
-RTF_EXTENSIONS_FILE    =
-
-#---------------------------------------------------------------------------
-# configuration options related to the man page output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
-# generate man pages
-
-GENERATE_MAN           = NO
-
-# The MAN_OUTPUT tag is used to specify where the man pages will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `man' will be used as the default path.
-
-MAN_OUTPUT             = man
-
-# The MAN_EXTENSION tag determines the extension that is added to
-# the generated man pages (default is the subroutine's section .3)
-
-MAN_EXTENSION          = .3
-
-# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
-# then it will generate one additional man file for each entity
-# documented in the real man page(s). These additional files
-# only source the real man page, but without them the man command
-# would be unable to find the correct page. The default is NO.
-
-MAN_LINKS              = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to the XML output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_XML tag is set to YES Doxygen will
-# generate an XML file that captures the structure of
-# the code including all documentation.
-
-GENERATE_XML           = NO
-
-# The XML_OUTPUT tag is used to specify where the XML pages will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `xml' will be used as the default path.
-
-XML_OUTPUT             = xml
-
-# The XML_SCHEMA tag can be used to specify an XML schema,
-# which can be used by a validating XML parser to check the
-# syntax of the XML files.
-
-XML_SCHEMA             =
-
-# The XML_DTD tag can be used to specify an XML DTD,
-# which can be used by a validating XML parser to check the
-# syntax of the XML files.
-
-XML_DTD                =
-
-# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
-# dump the program listings (including syntax highlighting
-# and cross-referencing information) to the XML output. Note that
-# enabling this will significantly increase the size of the XML output.
-
-XML_PROGRAMLISTING     = YES
-
-#---------------------------------------------------------------------------
-# configuration options for the AutoGen Definitions output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
-# generate an AutoGen Definitions (see autogen.sf.net) file
-# that captures the structure of the code including all
-# documentation. Note that this feature is still experimental
-# and incomplete at the moment.
-
-GENERATE_AUTOGEN_DEF   = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to the Perl module output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_PERLMOD tag is set to YES Doxygen will
-# generate a Perl module file that captures the structure of
-# the code including all documentation. Note that this
-# feature is still experimental and incomplete at the
-# moment.
-
-GENERATE_PERLMOD       = NO
-
-# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
-# the necessary Makefile rules, Perl scripts and LaTeX code to be able
-# to generate PDF and DVI output from the Perl module output.
-
-PERLMOD_LATEX          = NO
-
-# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
-# nicely formatted so it can be parsed by a human reader.
-# This is useful
-# if you want to understand what is going on.
-# On the other hand, if this
-# tag is set to NO the size of the Perl module output will be much smaller
-# and Perl will parse it just the same.
-
-PERLMOD_PRETTY         = YES
-
-# The names of the make variables in the generated doxyrules.make file
-# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
-# This is useful so different doxyrules.make files included by the same
-# Makefile don't overwrite each other's variables.
-
-PERLMOD_MAKEVAR_PREFIX =
-
-#---------------------------------------------------------------------------
-# Configuration options related to the preprocessor
-#---------------------------------------------------------------------------
-
-# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
-# evaluate all C-preprocessor directives found in the sources and include
-# files.
-
-ENABLE_PREPROCESSING   = YES
-
-# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
-# names in the source code. If set to NO (the default) only conditional
-# compilation will be performed. Macro expansion can be done in a controlled
-# way by setting EXPAND_ONLY_PREDEF to YES.
-
-MACRO_EXPANSION        = NO
-
-# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
-# then the macro expansion is limited to the macros specified with the
-# PREDEFINED and EXPAND_AS_DEFINED tags.
-
-EXPAND_ONLY_PREDEF     = NO
-
-# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
-# pointed to by INCLUDE_PATH will be searched when a #include is found.
-
-SEARCH_INCLUDES        = YES
-
-# The INCLUDE_PATH tag can be used to specify one or more directories that
-# contain include files that are not input files but should be processed by
-# the preprocessor.
-
-INCLUDE_PATH           =
-
-# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
-# patterns (like *.h and *.hpp) to filter out the header-files in the
-# directories. If left blank, the patterns specified with FILE_PATTERNS will
-# be used.
-
-INCLUDE_FILE_PATTERNS  =
-
-# The PREDEFINED tag can be used to specify one or more macro names that
-# are defined before the preprocessor is started (similar to the -D option of
-# gcc). The argument of the tag is a list of macros of the form: name
-# or name=definition (no spaces). If the definition and the = are
-# omitted =1 is assumed. To prevent a macro definition from being
-# undefined via #undef or recursively expanded use the := operator
-# instead of the = operator.
-
-PREDEFINED             =
-
-# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
-# this tag can be used to specify a list of macro names that should be expanded.
-# The macro definition that is found in the sources will be used.
-# Use the PREDEFINED tag if you want to use a different macro definition that
-# overrules the definition found in the source code.
-
-EXPAND_AS_DEFINED      =
-
-# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
-# doxygen's preprocessor will remove all references to function-like macros
-# that are alone on a line, have an all uppercase name, and do not end with a
-# semicolon, because these will confuse the parser if not removed.
-
-SKIP_FUNCTION_MACROS   = YES
-
-#---------------------------------------------------------------------------
-# Configuration::additions related to external references
-#---------------------------------------------------------------------------
-
-# The TAGFILES option can be used to specify one or more tagfiles. For each
-# tag file the location of the external documentation should be added. The
-# format of a tag file without this location is as follows:
-#
-# TAGFILES = file1 file2 ...
-# Adding location for the tag files is done as follows:
-#
-# TAGFILES = file1=loc1 "file2 = loc2" ...
-# where "loc1" and "loc2" can be relative or absolute paths
-# or URLs. Note that each tag file must have a unique name (where the name does
-# NOT include the path). If a tag file is not located in the directory in which
-# doxygen is run, you must also specify the path to the tagfile here.
-
-TAGFILES               =
-
-# When a file name is specified after GENERATE_TAGFILE, doxygen will create
-# a tag file that is based on the input files it reads.
-
-GENERATE_TAGFILE       =
-
-# If the ALLEXTERNALS tag is set to YES all external classes will be listed
-# in the class index. If set to NO only the inherited external classes
-# will be listed.
-
-ALLEXTERNALS           = NO
-
-# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
-# in the modules index. If set to NO, only the current project's groups will
-# be listed.
-
-EXTERNAL_GROUPS        = YES
-
-# The PERL_PATH should be the absolute path and name of the perl script
-# interpreter (i.e. the result of `which perl').
-
-PERL_PATH              = /usr/bin/perl
-
-#---------------------------------------------------------------------------
-# Configuration options related to the dot tool
-#---------------------------------------------------------------------------
-
-# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
-# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
-# or super classes. Setting the tag to NO turns the diagrams off. Note that
-# this option also works with HAVE_DOT disabled, but it is recommended to
-# install and use dot, since it yields more powerful graphs.
-
-CLASS_DIAGRAMS         = YES
-
-# You can define message sequence charts within doxygen comments using the \msc
-# command. Doxygen will then run the mscgen tool (see
-# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
-# documentation. The MSCGEN_PATH tag allows you to specify the directory where
-# the mscgen tool resides. If left empty the tool is assumed to be found in the
-# default search path.
-
-MSCGEN_PATH            =
-
-# If set to YES, the inheritance and collaboration graphs will hide
-# inheritance and usage relations if the target is undocumented
-# or is not a class.
-
-HIDE_UNDOC_RELATIONS   = YES
-
-# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
-# available from the path. This tool is part of Graphviz, a graph visualization
-# toolkit from AT&T and Lucent Bell Labs. The other options in this section
-# have no effect if this option is set to NO (the default)
-
-HAVE_DOT               = NO
-
-# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
-# allowed to run in parallel. When set to 0 (the default) doxygen will
-# base this on the number of processors available in the system. You can set it
-# explicitly to a value larger than 0 to get control over the balance
-# between CPU load and processing speed.
-
-DOT_NUM_THREADS        = 0
-
-# By default doxygen will use the Helvetica font for all dot files that
-# doxygen generates. When you want a differently looking font you can specify
-# the font name using DOT_FONTNAME. You need to make sure dot is able to find
-# the font, which can be done by putting it in a standard location or by setting
-# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
-# directory containing the font.
-
-DOT_FONTNAME           = Helvetica
-
-# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
-# The default size is 10pt.
-
-DOT_FONTSIZE           = 10
-
-# By default doxygen will tell dot to use the Helvetica font.
-# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to
-# set the path where dot can find it.
-
-DOT_FONTPATH           =
-
-# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
-# will generate a graph for each documented class showing the direct and
-# indirect inheritance relations. Setting this tag to YES will force the
-# CLASS_DIAGRAMS tag to NO.
-
-CLASS_GRAPH            = YES
-
-# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
-# will generate a graph for each documented class showing the direct and
-# indirect implementation dependencies (inheritance, containment, and
-# class references variables) of the class with other documented classes.
-
-COLLABORATION_GRAPH    = YES
-
-# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
-# will generate a graph for groups, showing the direct groups dependencies
-
-GROUP_GRAPHS           = YES
-
-# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
-# collaboration diagrams in a style similar to the OMG's Unified Modeling
-# Language.
-
-UML_LOOK               = NO
-
-# If the UML_LOOK tag is enabled, the fields and methods are shown inside
-# the class node. If there are many fields or methods and many nodes the
-# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS
-# threshold limits the number of items for each type to make the size more
-# managable. Set this to 0 for no limit. Note that the threshold may be
-# exceeded by 50% before the limit is enforced.
-
-UML_LIMIT_NUM_FIELDS   = 10
-
-# If set to YES, the inheritance and collaboration graphs will show the
-# relations between templates and their instances.
-
-TEMPLATE_RELATIONS     = NO
-
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
-# tags are set to YES then doxygen will generate a graph for each documented
-# file showing the direct and indirect include dependencies of the file with
-# other documented files.
-
-INCLUDE_GRAPH          = NO
-
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
-# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
-# documented header file showing the documented files that directly or
-# indirectly include this file.
-
-INCLUDED_BY_GRAPH      = YES
-
-# If the CALL_GRAPH and HAVE_DOT options are set to YES then
-# doxygen will generate a call dependency graph for every global function
-# or class method. Note that enabling this option will significantly increase
-# the time of a run. So in most cases it will be better to enable call graphs
-# for selected functions only using the \callgraph command.
-
-CALL_GRAPH             = YES
-
-# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
-# doxygen will generate a caller dependency graph for every global function
-# or class method. Note that enabling this option will significantly increase
-# the time of a run. So in most cases it will be better to enable caller
-# graphs for selected functions only using the \callergraph command.
-
-CALLER_GRAPH           = YES
-
-# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
-# will generate a graphical hierarchy of all classes instead of a textual one.
-
-GRAPHICAL_HIERARCHY    = YES
-
-# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES
-# then doxygen will show the dependencies a directory has on other directories
-# in a graphical way. The dependency relations are determined by the #include
-# relations between the files in the directories.
-
-DIRECTORY_GRAPH        = NO
-
-# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
-# generated by dot. Possible values are svg, png, jpg, or gif.
-# If left blank png will be used. If you choose svg you need to set
-# HTML_FILE_EXTENSION to xhtml in order to make the SVG files
-# visible in IE 9+ (other browsers do not have this requirement).
-
-DOT_IMAGE_FORMAT       = png
-
-# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
-# enable generation of interactive SVG images that allow zooming and panning.
-# Note that this requires a modern browser other than Internet Explorer.
-# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you
-# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files
-# visible. Older versions of IE do not have SVG support.
-
-INTERACTIVE_SVG        = NO
-
-# The tag DOT_PATH can be used to specify the path where the dot tool can be
-# found. If left blank, it is assumed the dot tool can be found in the path.
-
-DOT_PATH               =
-
-# The DOTFILE_DIRS tag can be used to specify one or more directories that
-# contain dot files that are included in the documentation (see the
-# \dotfile command).
-
-DOTFILE_DIRS           =
-
-# The MSCFILE_DIRS tag can be used to specify one or more directories that
-# contain msc files that are included in the documentation (see the
-# \mscfile command).
-
-MSCFILE_DIRS           =
-
-# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
-# nodes that will be shown in the graph. If the number of nodes in a graph
-# becomes larger than this value, doxygen will truncate the graph, which is
-# visualized by representing a node as a red box. Note that doxygen if the
-# number of direct children of the root node in a graph is already larger than
-# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
-# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
-
-DOT_GRAPH_MAX_NODES    = 50
-
-# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
-# graphs generated by dot. A depth value of 3 means that only nodes reachable
-# from the root by following a path via at most 3 edges will be shown. Nodes
-# that lay further from the root node will be omitted. Note that setting this
-# option to 1 or 2 may greatly reduce the computation time needed for large
-# code bases. Also note that the size of a graph can be further restricted by
-# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
-
-MAX_DOT_GRAPH_DEPTH    = 0
-
-# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
-# background. This is disabled by default, because dot on Windows does not
-# seem to support this out of the box. Warning: Depending on the platform used,
-# enabling this option may lead to badly anti-aliased labels on the edges of
-# a graph (i.e. they become hard to read).
-
-DOT_TRANSPARENT        = NO
-
-# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
-# files in one run (i.e. multiple -o and -T options on the command line). This
-# makes dot run faster, but since only newer versions of dot (>1.8.10)
-# support this, this feature is disabled by default.
-
-DOT_MULTI_TARGETS      = NO
-
-# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
-# generate a legend page explaining the meaning of the various boxes and
-# arrows in the dot generated graphs.
-
-GENERATE_LEGEND        = YES
-
-# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
-# remove the intermediate dot files that are used to generate
-# the various graphs.
-
-DOT_CLEANUP            = YES
diff --git a/docs/README.txt b/docs/README.txt
deleted file mode 100755
index 17fd90d..0000000
--- a/docs/README.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-./Doxyfile.in         This file describes the settings to be used by the 
-                      documentation system
-
-./AMCL.dox            Main page of the documentation.
-
-To generate the documentation type: make doc
-
-This will generate the directories
-
-./html    This can be read by typing:
-          firefox ./html/index.html
-
-./latex   These are the latex source files. The pdf can be generated by
-          typing: make. The output is refman.pdf.
-
-
diff --git a/docs/latex/README.txt b/docs/latex/README.txt
deleted file mode 100644
index ad1c410..0000000
--- a/docs/latex/README.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-latex amcl.tex
-dvips -Ppdf -G0 amcl.dvi
-ps2pdf  amcl.ps
diff --git a/docs/latex/amcl.bib b/docs/latex/amcl.bib
deleted file mode 100644
index 3d6d22e..0000000
--- a/docs/latex/amcl.bib
+++ /dev/null
@@ -1,156 +0,0 @@
-@misc{aranha-karabina-longa-gebotys-lopez,

-	author = "D.~F.~Aranha and K.~Karabina and P.~Longa and C.~H.~ Gebotys and J.~Lopez",

-	title = "Faster Explicit Formulae for Computing Pairings over Ordinary Curves",

-	year = "2010",

-	howpublished = "Cryptology ePrint Archive, Report 2010/526",

-	note = {\url{http://eprint.iacr.org/2010/526}},

-}

-

-@misc{bernstein-chuengsatiansup-lange,

-    author = {Daniel J. Bernstein and Chitchanok Chuengsatiansup and Tanja Lange},

-    title = {Curve41417: Karatsuba revisited},

-    howpublished = {Cryptology ePrint Archive, Report 2014/526},

-    year = {2014},

-    note = {\url{http://eprint.iacr.org/2014/526}},

-}

-

-@article{montgomery,

-	author={Peter L. Montgomery},

-	title={Modular Multiplication Without Trial Division},

-	journal={Mathematics of Computation},

-	volume="44",

-	number="170",

-	pages="519–-521",

-	year="1985"

-}

-

-@misc{bos-costello-longa-naehrig,

-    author = {Joppe W. Bos and Craig Costello and Patrick Longa and Michael Naehrig},

-    title = {Selecting Elliptic Curves for Cryptography: An Efficiency and Security Analysis},

-    howpublished = {Cryptology ePrint Archive, Report 2014/130},

-    year = {2014},

-    note = {\url{http://eprint.iacr.org/2014/130}},

-}

-

-@misc{bernstein-duif-lange-schwabe-yang,

-    author = {Daniel J. Bernstein and Niels Duif and Tanja Lange and Peter Schwabe and Bo-Yin Yang},

-    title = {High-speed high-security signatures},

-    howpublished = {Cryptology ePrint Archive, Report 2011/368},

-    year = {2011},

-    note = {\url{http://eprint.iacr.org/2011/368}},

-}

-

-@misc{tss,

-	author="Tangible Software Solutions",

-	note={\url{http://www.tangiblesoftwaresolutions.com/}},

-}

-

-@misc{ml,

-	author="A.~ Miele and A.~K.~Lenstra",

-	title = "Efficient ephemeral elliptic curve cryptographic keys",

-	year="2015",

-	note={\url{http://csrc.nist.gov/groups/ST/ecc-workshop-2015/papers/session1-miele-paper.pdf}},

-}

-

-@misc{gol,

-	author="Google j2objc",

-	note={\url{https://github.com/google/j2objc}},

-}

-

-@Inproceedings{bernstein,

-	author={Daniel J. Bernstein},

-	title={Curve25519: new {D}iffie-{H}ellman speed records},

-	booktitle="PKC 2006", 

-	pages="207--228", 

-	publisher="Springer-Verlag",

-	series = "Lecture Notes in Computer Science",

-	volume="3958",

-	year="2006"

-}

-

-@misc{nist,

-	author="National Institute for Standards and Technology",

-	title="Federal Information Processing Standards Publication 186-2",

-	year="2000",

-	note = {\url{http://csrc.nist.gov/publications/fips/archive/fips186-2/fips186-2.pdf}},

-}

-

-@misc{mpin,

-	author="M. ~Scott",

-	title= "M-{P}in: A Multi-Factor Zero Knowledge Authentication Protocol",

-	year="2014",

-	note={\url{http://www.miracl.com/crypto-labs}},

-}

-

-@Inproceedings{barreto-naehrig,

-	author="P.S.L.M.~Barreto and M.~Naehrig",

-	title="Pairing-Friendly elliptic curves of prime order", 

-	booktitle="Selected Areas in Cryptology -- {SAC} 2005", 

-	pages="319--331", 

-	publisher="Springer-Verlag",

-	series = "Lecture Notes in Computer Science",

-	volume= "3897", 

-	year="2006",

-}

-

-@book{knuth,

- author = {Knuth, Donald E.},

- title = {The Art of Computer Programming, Volume 2 (3rd Ed.): Seminumerical Algorithms},

- year = {1997},

- isbn = {0-201-89684-2},

- publisher = {Addison-Wesley Longman Publishing Co., Inc.},

-} 

-

-

-

-@Inproceedings{scott,

-	author="M.~ Scott",

-	title= "Implementing Cryptographic Pairings",

-	booktitle="Pairing 2007",

-	pages="177--196",

-	year="2007",

-	series = "Lecture Notes in Computer Science",

-	volume= "4575"

-}

-

-@article{montgomery2,

-	author={Peter L. Montgomery},

-	title="Speeding the {P}ollard and Elliptic Curve Methods of Factorisation",

-	journal={Mathematics of Computation},

-	volume="48",

-	number="177",

-	pages="243–-264",

-	year="1987"

-}

-

-@misc{bernstein-lange,

-    author = {Daniel J. Bernstein and Tanja Lange},

-    title = {Inverted {E}dwards coordinates},

-    howpublished = {Cryptology ePrint Archive, Report 2007/410},

-    year = {2007},

-    note = {\url{http://eprint.iacr.org/2007/410}},

-}

-

-@misc{brainpool,

-	author="Brainpool",

-	title="{ECC} Brainpool standard curves and curve generation.",

-	year={2005},

-	note={\url{http://www.ecc-brainpool.org/download/Domain-parameters.pdf}},

-}

-

-@misc{ANSSI,

-	author="{ANSSI}",

-	title="Publication d'un paramétrage de courbe elliptique visant des applications de passeport électronique et de l'administration électronique française.",

-	year={2011},

-	note={\url{http://www.legifrance.gouv.fr/affichTexte.do?cidTexte=JORFTEXT000024668816}},

-}

-

-@misc{certicom,

-	author="Certicom",

-	title="SEC 2: Recommended Elliptic Curve Domain Parameters, Version 2.0",

-	year={2010},

-	note={\url{ http://www.secg.org/download/aid-784/sec2-v2.pdf }},

-}

-

-

-

diff --git a/docs/latex/amcl.tex b/docs/latex/amcl.tex
deleted file mode 100644
index 2f897a2..0000000
--- a/docs/latex/amcl.tex
+++ /dev/null
@@ -1,416 +0,0 @@
-\documentclass{llncs}

-\usepackage{amsmath,amssymb,url}

-\usepackage{algorithm}

-\usepackage{algpseudocode}

-\usepackage{graphicx}

-\usepackage{mathcomp}

-

-\newcommand{\Cyc}{\mathrm{\Phi}}

-\newcommand{\Frob}{\mathrm{\Phi}}

-\newcommand{\twist}{\mathrm{\Psi}}

-\newcommand{\F}{\mathbb{F}}

-\newcommand{\half}[1]{{\lfloor#1/2\rfloor}}

-\newcommand{\ord}{\qopname\relax{no}{ord}}

-\newcommand{\sign}{\qopname\relax{no}{sign}}

-\newcommand{\tr}{\qopname\relax{no}{tr}}

-\newcommand{\Z}{\mathbb{Z}}

-\newcommand{\Cpp}{C\kern-0.05em\texttt{+\kern-0.03em+}}

-\newcommand{\pp}{\,\kern-0.05em\texttt{+\kern-0.031em+}}

-\newcommand\T{\rule{0pt}{2.6ex}}

-

-\newcommand{\Input}{\item[\textsc{Input:}]}

-\newcommand{\Output}{\item[\textsc{Output:}]}

-

-\sloppy

-

-\begin{document}

-

-\pagestyle{plain}

-

-\title{The Apache Milagro Crypto Library}

-

-\author{

-Michael Scott 

-}

-

-\institute{}

-

-\institute{

-%Chief Cryptographer \\

-MIRACL Labs\\%

-%\bf{For Internal Distribution Only} \\

-\email{mike.scott@miracl.com} \\

-}

-

-\maketitle

-

-\begin{abstract}

-

-We introduce a new multi-lingual crypto library, specifically designed to support the Internet of Things.

-

-\end{abstract} 

-

-\section{Introduction}\label{sec:intro}

-

-%One of the major mysteries in the real-world of crypto is resistance to the exploitation of new research ideas. Its not that cryptographic research has failed to throw up new ideas that have

-%the potential for commercial exploitation -- far from it. But in the real-world 1970's crypto rules supreme, and very little happens that isn't PKI/RSA based. The reasons for this are many and varied.

-%However one part of the puzzle might be the non-availability of easy-to-use open source cryptographic tools, that do not require in depth cryptographic expertise to deploy.

-

-%In particular 

-There are many crypto libraries out there. Many offer a bewildering variety of cryptographic primitives, at different levels of security. Many use extensive assembly language 

-in order to be as fast as possible. Many are very big, even bloated. Some rely on other external libraries. Many were designed by academics for academics, and so are not really suitable for 

-commercial use. Many are otherwise excellent, but not written in our favourite language.

-

-The Apache Milagro Crypto Library (AMCL) \footnote{\url{https://github.com/MIRACL/amcl.git}} is different. AMCL is completely self-contained (except for the requirement for an external entropy source for random number generation). AMCL is for use in 

-the pre-quantum era -- that is in the here and now. With 

-the advent of a workable quantum computer, AMCL will become history. But we are not expecting that to happen any time soon.

-

-AMCL is portable -- there is no assembly language. The original version is written in C, Java, Javascript, Go and Swift using only generic programming constructs, but AMCL is truly 

-multi-lingual, as compatible 

-versions will be available in many other languages (see below). These versions will be identical in that for the same inputs they will not only produce the same outputs, but all internal calculations will also be the same. 

-AMCL is fast, but does not attempt to set speed records (a particular academic obsession). There are of course contexts where speed is of the essence -- for example for a server farm which must handle 

-multiple SSL connections, and where a 10\% speed increase implies the need for 10\% less servers, with a a 10\% saving on electricity. But in the Internet of Things we would suggest that this is less 

-important. In general the speed

-is expected to be ``good enough''. However AMCL is small. Some libraries boast of having hundreds of thousands of lines of code - AMCL has less than 10,000. AMCL takes up the minimum of 

-ROM/RAM resources in order to fit into the smallest possible embedded footprint, consistent with other design constraints. It is expected that this will be vital for implementations that 

-support security in the Internet of Things. AMCL (the C version) only uses stack memory, and is thus natively multi-threaded.

-

-Only one level of security is supported, equivalent to 128-bit AES. This is the current standard level for cryptography that is expected to be unbreakable. As a justification we could not 

-improve on that given by Miele and Lenstra \cite{ml} -- ``With 128-bit security more than sufficient for the foreseeable future, it is not 

-clear either what purpose is served by higher security levels, other than catering 

-to “TOP SECRET” 192-bit security ..... In this context it is interesting to 

-note that 256-bit AES, also prescribed ...... for “TOP SECRET”, was introduced 

-only to still have a 128-bit secure symmetric cipher in the post-quantum world 

-......, and that 192-bit security was merely a side-effect that resulted from 

-the calculation (128+256)/2 ....... In that world ECC is obsolete anyhow.''

-

-

-AMCL makes most 

-of the choices for you as to which primitives to use, based on the best available current advice. Specifically it uses AES-128 for symmetric encryption, SHA256 for hashing, 256-bit prime field elliptic

-curves for public key protocols, and 256-bit BN curves to support pairing-based protocols. However three different parameterizations of Elliptic curve are supported - Weierstrass, Edwards and 

-Montgomery, as each is appropriate within its own niche. In each case only the standard projective coordinates are used. But you do get to 

-choose the actual elliptic curve, with support for three different 

-forms of the modulus. For pairings we assume a modulus congruent to $3 \bmod 8$ with a D-type twist, parameterized by a negative $x$ value \cite{barreto-naehrig}.

-Standard modes of AES are supported, plus GCM mode for authenticated encryption.

-

-The C version of AMCL is configured at compile time for 16, 32 or 64 bit processors, and for a specific elliptic curve. The Java and Javascript versions are (obviously) processor agnostic, 

-but the same choices of elliptic curve are available.

-

-AMCL is written with an awareness of the abilities of modern pipelined processors. In particular there was an awareness that the unpredictable program branch should be avoided at all costs, not 

-only as it slows down the processor, but as it may open the door to side-channel attacks. The innocuous looking {\tt if} statement -- unless its outcome can be accurately predicted -- is the enemy 

-of quality crypto software.

-

-In the sequel we refer to the C version of AMCL, unless otherwise specified. We emphasis that all AMCL versions are completely self-contained. No external 

-libraries or packages are required to implement all of the supported cryptographic functionality (other than for an external entropy source).

-

-\section{Context}

-

-A crypto library does not function is isolation. The AMCL was originally designed to support the MIRACL IoT solution. The MIRACL IoT solution is based on a cloud-based infrastructure designed by MIRACL 

-to support the M-Pin protocol \cite{mpin}, but which has wider application to novel protocols of particular relevance to the IoT. This document describes the AMCL library which was originally designed for internal use, 

-but which has now reached a level of maturity where we are pleased to make it available as a service to the wider community as an open source product, under a standard Apache 2.0 license.

-

-\section{Library Structure}

-

-The modules that make up AMCL are shown below, with some indication of how they interact. Several example APIs will be provided to implement common protocols. Note that all

-interaction with the API is via machine-independent endian-indifferent arrays of bytes (a.k.a. octet strings). 

-Therefore the underlying workings of the library are invisible to the consumer of its services.

-

-\begin{figure}[!htb]

-  \begin{center}

-    \includegraphics[width=120mm ]{clint.eps}

-  \end{center}

-  \caption{\small The AMCL library.}

-  \label{clint}

-\end{figure}

-

-The symmetric encryption and hashing code, along with the random number generation, is uninteresting, and since we make no claims for it, we will not refer to it again. It was mostly

-borrowed from our well-known MIRACL library.

-

-\section{Handling 256-bit Numbers}

-

-\subsection{Representation}

-

-One of the major design decisions is how to represent the 256-bit field elements required for the elliptic curve and pairing-based cryptography. Here there are two different approaches. 

-One is to pack the bits as tightly as possible into computer words. For example on a 64-bit computer 256-bit numbers can be stored in just 4 words. However to manipulate numbers in this 

-form, even for simple addition, requires handling of carry bits if overflow is to be avoided, 

-and a high-level language does not have direct access to carry flags. It is possible to emulate the flags, but this would be inefficient. In fact this approach is only really suitable 

-for an assembly language implementation.

-

-The alternative idea is to use extra words for the representation, and then try to offset the additional cost by taking full advantage of the ``spare'' bits in every word. 

-This idea follows a ``corner of the literature'' \cite{bernstein-chuengsatiansup-lange} which has been promoted by Bernstein and his collaborators in several publications.

-Refer to figure \ref{words}, where each digit of the representation is stored as a signed integer which is the size of the processor word-length. 

-

-

-Note that almost all arithmetic takes place modulo a 256-bit prime number, the modulus representing the field over which the elliptic curve is defined, here denoted as $p$.

-

-On 64-bit processors, AMCL represents numbers to the base $2^{56}$ in a 5 element array, the Word Excess is 7 bits, and for a 256-bit modulus the Field Excess is 24 bits

-

-On 32-bit processors, AMCL represents numbers to the base $2^{29}$ in a 9 element array, the Word Excess is 2 bits, and for a 256-bit modulus the Field Excess is 5 bits

-

-On 16-bit processors, AMCL represents numbers to the base $2^{13}$ in a 20 element array, the Word Excess is 2 bits, and for a 256-bit modulus the Field Excess is 4 bits

-

-Such a representation of a 256-bit number is referred to as a {BIG}. Addition or subtraction of a pair of {BIG}s, results in another {BIG}.

-

-The Java version uses exactly the same 32-bit representation as above. For Javascript (where all numbers are stored as 64-bit floating point with a 52-bit mantissa, but mostly 

-manipulated as 32-bit integers), numbers

-are represented to the base $2^{24}$ in an 11 element array, the Word Excess is 7 bits, and the Field Excess for a 256-bit modulus is 8 bits. 

-

-\subsection{Addition and Subtraction}

-

-The existance of a word excess means for example that multiple field elements can be added together digit by digit, without processing of carries, before overflow can occur. 

-Only occasionally will there be a requirement to {\it normalise} these {\it extended} values,  that is to force them back into the original format. Note that this is independent of the modulus.

-

-The existance of a field excess means that, independent of the word excess, multiple field elements can be added together before it is required to reduce the sum with respect to the modulus. In the 

-literature this is referred to as lazy, or delayed, reduction. In fact we allow the modulus to be as small as 254 bits, which obviously increases the field excess.

-

-Note that these two mechanisms associated with the word excess and the field excess (often confused in the literature) operate largely independently of each other.

-

-AMCL has no support for negative numbers. Therefore subtraction will be implemented as field negation followed by addition. Negation is performed using the method described as 

-Option 1 in \cite{aranha-karabina-longa-gebotys-lopez}. Basically the 

-number of the active bits in the field excess of the number to be negated is determined, the modulus is shifted left by this amount plus one, and the value to be negated is subtracted from this value.

-Note that because of the ``plus 1'', this will always produce a positive result at the cost of eating a bit into the field excess.

-

-\begin{figure}[!htb]

-  \begin{center}

-    \includegraphics[width=120mm ]{words.eps}

-  \end{center}

-  \caption{\small 256-bit number representation}

-  \label{words}

-\end{figure}

-

-Normalisation of extended numbers requires the word excess of each digit to be shifted right by the number of base bits, and added to the next digit, working right to left. Note that when numbers 

-are subtracted digit-by-digit individual digits may become negative. However

-since we are avoiding using the sign bit, due to the magic of 2's complement arithmetic, this all works fine without any conditional branches.

-

-Reduction of unreduced BIG numbers is carried out using a simple shift-compare-and-subtract of the modulus, with one subtraction needed on average half of the time for every active bit in the field excess. 

-Hopefully such reductions will rarely be required, as they are slow and involve unpredictable program branches.

-

-Since the length of field elements is fixed at compile time, it is expected that the compiler will unroll most of the time-critical loops. In any case the conditional branch required at the foot of a 

-fixed-size loop can be accurately predicted by modern hardware.

-

-The problem now is to decide when to normalise and when to reduce numbers to avoid the possibility of overflow. There are two ways of doing this. One is to monitor the excesses at run-time and act when the 

-threat of overflow arises. The second is to do a careful analysis of the code and insert normalisation and reduction code at points where the possibility of overflow may arise, based on a static worst-case 

-analysis. 

-

-The field excess $E_n$ of a number $n$ is easily captured by a simple masking and shifting of the top word. If two normalised numbers $a$ and $b$ are to be added then the excess of their sum will be at worst 

-$E_a + E_b +1$. As long as this is less than $2^{FE}$ where $FE$ is the field excess, then we are fine. Otherwise both numbers should be reduced prior to the addition. In AMCL these checks are 

-performed at run-time. However, as we shall see, in practise these reductions are very rarely required. So the {\tt if} statement used to control them is highly predictable. Observe that even

-in the worst case, for a 16-bit implementation, the excess is a generous $FE=4$, and so many elements can be added or subtracted before reduction is required.

-

-The worst case word excess for the result of a calculation is harder to calculate at run time, as it would require inspection of every digit of every {BIG}. This would slow computation down to an unacceptable extent. 

-Therefore in this case

-we use static analysis and insert normalisation code where we know it might be needed. This process was supported by special debugging code that warned of places where overflow was possible, based on a simple

-worst-case analysis.

-

-\subsection{Multiplication and Reduction}

-

-To support multiplication of {BIG}s, we will require a double-length {DBIG} type. Also the partial products that arise in the process of long multiplication will require a double-length data type. Fortunately many 

-popular C compilers, like Gnu {GCC}, always support an integer type that is double the native word-length. For Java the ``int'' type is 32-bits and there is a double-length ``long'' type which is 64-bit.

-Of course for Javascript a double length type is not possible, and so the partial products must be accomodated within the 52-bit mantissa.

-

-It is generally accepted that the fastest way to do multi-precision multiplication is to accumulate the double-length partial products that contribute to each column in the classic school-boy long multiplication

-algorithm, also known as the Comba method. Then at the foot of the column the total is split into the sum for that column, and the carry to the next column, working right-to-left. If the numbers are normalised 

-prior to the multiplication, then 

-with the word excesses that we have chosen, this will not result in overflow. The {DBIG} product will be automatically normalised as a result of this process. Squaring can be done in a 

-similar fashion, but only requires just over half of the number of partial products, and so it may be somewhat faster.

-

-The {DBIG} value that results from a multiplication or squaring may be immediately reduced with respect to the modulus to bring it back to a {BIG}. However again we may choose to delay this 

-reduction, and therefore we need the ability to safely add and subtract DBIG numbers while again avoiding overflow.

-

-The method used for full reduction of a DBIG back to a BIG depends on the form of the modulus. We choose to support three distinct types of modulus, (a) pseudo Mersenne of the form $2^n-c$ where 

-$c$ is small and $n$ is the size of the modulus in bits, 

-(b) Montgomery-friendly of the form $k.2^n-1$, and (c) moduli of no special form. For cases (b) and (c) we convert all 

-field elements to Montgomery's {\it n}-residue form, and use Montgomery's fast method for modular reduction \cite{montgomery}. In all cases the DBIG number to be reduced $y$ must be in the 

-range $0<y<pR$ (a requirement of Montgomery's method), and the result $x$ is guaranteed to 

-be in the range $0<x<2p$, where $R=2^{256+FE}$ for a 256-bit modulus. Note that the BIG result will be (nearly) fully reduced. The fact than we allow $x$ to be larger than $p$ means that we can avoid

-the notorious Montgomery ``final subtraction'' \cite{montgomery}.

-

-Observe how unreduced numbers involved in complex calculations tend to be (nearly fully) reduced if they are involved in a modular multiplication. So for example if field element $x$ has a large field excess,

-and if we calculate $x=x.y$, then as long as the unreduced product is less than $pR$, the result will be a nearly fully reduced $x$. So in many cases there is a natural tendency for field excesses 

-not to grow without limit, and not to overflow, without requiring explicit action on our part.

-

-Consider now a sequence of code that adds, subtracts and multiplies field elements, as might arise in elliptic curve additions and doublings. Assume that the code has been analysed and that normalisation 

-code has been inserted where needed. Assume that the reduction code that 

-activates if there is a possibility of an element overflowing its field excess, while present, never in fact is triggered (due to the behaviour described above). Then we assert that there is only one 

-possible place in which an unpredicted branch may occur. This will be in the negation code associated with a subtraction, where the number of bits in the field excess must be counted. However we would 

-point out that some architectures do now support machine code instructions that count the number of active bits in a computer register -- although unfortunately this capability is not supported by the 

-typical high-level language syntax.

-

-\section{Extension Field arithmetic}

-

-To support cryptographic pairings we will need support for extension fields. We use a towering of extensions, from $\F_p$ to $\F_{p^2}$ to $\F_{p^4}$ to $\F_{p^{12}}$ as required for 

-BN curves \cite{barreto-naehrig}. An element 

-of the quadratic extension field will be represented as $f=a+ib$, where $i$ is the square root of the quadratic non-residue -1.

-To add, subtract and multiply them we use the obvious methods. However for negation we can construct $-f=-a-ib$ as $b-(a+b)+i.(a-(a+b)$ which requires only one base field negation. A similar idea 

-can be used recursively for higher order extensions, so that only one base field negation is ever required.

-

-

-\section{Elliptic Curves}

-

-Three types of Elliptic curve are supported for the implementation of Elliptic Curve Cryptography (ECC), but curves are limited to popular families that support faster implementation. Weierstrass 

-curves are supported using the Short Weierstrass representation:-

-

-$$ y^2=x^3+Ax+B $$

-

-where $A=0$ or $A=-3$. Edwards curves are supported using both regular and twisted Edwards format:-

-

-$$ Ax^2+y^2=1+Bx^2y^2 $$

-

-where $A=1$ or $A=-1$. Montgomery curves are represented as:-

-

-$$ y^2=x^3+Ax^2+x $$

-

-where $A$ must be small.

-

-In the particular case of elliptic curve point multiplication, there are potentially a myriad of very dangerous side-channel attacks that arise from using the classic double-and-add algorithm

-and its variants. Vulnerabilities arise if branches are taken that depend on secret bits, or if data is even accessed using secret values as indices.

-Many types of counter-measures have been suggested. The simplest solution is to use a constant-time algorithm like the Montgomery ladder, which has a very simple structure, uses very little 

-memory and has no key-bit-dependent branches. 

-If using a Montgomery representation of the elliptic curve the Montgomery ladder \cite{montgomery2} is in fact the optimal algorithm for point multiplication. For other representations we use a 

-fixed-sized signed window method, as described in \cite{bos-costello-longa-naehrig}. 

-

-AMCL has built-in support for most standardised elliptic curves, along with many curves that have been proposed for standardisation at our chosen level of security. 

-Specifically it supports the NIST curve \cite{certicom}, \cite{nist}, the well known Curve25519 \cite{bernstein}, the 256-bit Brainpool curve \cite{brainpool}, the ANSSI curve \cite{ANSSI}, and four

-NUMS (Nothing-Up-My-Sleeve) curves proposed by Bos et al. \cite{bos-costello-longa-naehrig}. Some of these proposals support only a Weierstrass representation, but many also allow an Edwards and Montgomery 

-form. Tools are provided to allow easy integration of more curves.

-

-

-\section{Support for classic Finite Field Methods}

-

-Before Elliptic Curves, cryptography depended on methods based on simple finite fields. The most famous of these would be the well known RSA method. These methods have the advantage of

-being effectively parameterless, and therefore the issue of trust in parameters that arises for elliptic curves, is not an issue. However these methods are subject to index calculus based

-methods of cryptanalysis, and so fields and keys are typically much larger. So how to support for example a 2048-bit implementation of RSA based on a library designed for optimized 256-bit operations? The idea is simple --

-use AMCL as a virtual 256-bit machine, and build 2048-bit arithmetic on top of that. And to claw back some decent performance use the Karatsuba method \cite{knuth} so that for example 2048-bit multiplication

-recurses efficiently right down to 256-bit operations. Of course the downside of the Karatsuba method is that while it saves on multiplications, the number of additions and subtractions is greatly increased.

-However the existance of generous word excesses in our representation makes this less of a problem, as most additions can be carried out without normalisation. 

-

-Secret key operations like RSA decryption use the Montgomery ladder to achieve side-channel-attack resistance.

-

-The implementation can currently support $1024.2^n$ bit fields, so for example 2048-bit RSA can be used to get reasonably close to the AES-128-bit level of security, and if desired 4096 bit RSA can be used to

-comfortably exceed it. 

-

-Note that this code is supported independently of the elliptic curve code. So for example RSA and ECC can be run together within a single application. 

-

-However we regard these methods as ``legacy'' as in our view ECC based methods are a much better fit for the IoT. 

-

-\section{Multi-Lingual support}

-

-It is a big ask to develop and maintain multiple versions of a crypto library written in radically different languages such as C, Java, Javascript, Go and Swift. This has discouraged the use of

-language specific methods (which are in any case of little relevance here), and strongly encouraged the use of simple, generic computer language constructs. 

-

-This approach brings a surprising bonus: AMCL can be automatically converted to many other languages using available translator tools. For example Tangible Software Solutions \cite{tss}

-market a Java to C\# converter. This generated an efficient fully functional C\# version of AMCL within minutes. The same company market a Java to Visual Basic converter. 

-Google have a Java to Objective C

-converter \cite{gol} specifically designed to convert Android apps developed in Java, to iOS apps written in Objective C.

-

-Of course not all languages can be supported in this way, so support for some will be developed manually. In particular a Rust version is currently under development.

-

-

-\section{Discussion}

-

-We found in our code that, with few exceptions, reductions due to possible overflow of the field excess of a BIG were very rare, especially for the 64-bit version of the library. Similarly 

-normalisation was 

-rarely needed for the 64-bit code. This is due to the much greater excesses that apply in the 64-bit representation. In some experiments we calculated thousands of random pairings, 

-and reduction due to field excess overflow detection never happened.

-

-In general in developing AMCL we tried to use optimal methods, without going to what we (very subjectively) regarded as extremes in order to maximise performance. 

-Algorithms that require less memory were generally preferred if the impact on performance was not large. Some optimizations, while perfectly valid, are hard to 

-implement without having a significant impact on program readability and maintainability. Deciding which optimizations to use and which to reject (on the grounds of code size and negative impact on code 

-readability and maintainability) is admittedly rather arbitrary!

-

-One notable omission from AMCL is the use of precomputation on fixed parameters in order to speed up certain calculations. We try to justify this, rather unconvincingly, by pointing out 

-that precomputation must of necessity increase code size. Furthermore such methods are more sensitive to side-channel attacks and much of their speed advantage will be lost if they are to be 

-fully side-channel protected. Also precomputation on secret values clearly increases the amount of secret data that needs to be protected.

-However our view might change in later versions depending on our in-the-field experiences of using AMCL.

-

-%\newpage

-\bibliographystyle{plain}

-\bibliography{amcl}

-

-%\newpage

-\appendix

-

-\section*{Benchmarks}

-

-Since AMCL is intended for the Internet of Things, we think it appropriate to give some timings based on an implementation on the Raspberry Pi (version 2) computer, which is

-based on a 32-bit ARM7 chip. We do not overclock the 900MHz processor. 

-

-We developed three API programs, one which tests standard methods of elliptic curve key exchange, public key cryptography and digital signature. Another implements all components of our M-Pin protocol,

-a pairing-based protocol of medium complexity \cite{mpin}.  The former uses the ed25519 Edwards curve \cite{bernstein-duif-lange-schwabe-yang} with its pseudo-mersenne modulus, and the latter a BN curve.

-Finally we implement all the steps of the RSA public key encryption protocol using 2048-bit keys, that is key generation, encryption and decryption.

-

-These might be regarded as representative of what might be expected for an implementation of a typical elliptic curve (ECC) protocol, a typical pairing-based (PBC) protocol, and a typical classic 

-public key protocol based on RSA.

-The results in the first table indicate the code and stack requirements when these programs were compiled using version 4.8 of the GCC compiler, using the standard  -O3 (optimize for best performance) and -Os

-(optimize for minimum size) flags, and a flag to indicate the specific ARM architecture (Cortex-A7).

-

-

-\begin{table}

-\centering

-\begin{tabular}{|l|c|c|}

-\hline

-&~~Code Size~~&~Maximum Stack Usage~\\

-\hline

-~ECC  -O3 & 68085 & 4140  \\  %

-~ECC  -Os & 31115 & 3752 \\   %

-~PBC  -O3 & 84031 & 8140 \\   %

-~PBC  -Os & 46044 & 7904 \\   %

-~RSA  -O3 & 61461 & 5332 \\   %

-~RSA  -Os & 23449 & 5228 \\   %

-\hline

-\end{tabular}

-~\\

-\caption{Typical Memory Footprint}

-\label{footprint}

-\end{table}

-

-

-Next we give some timings for a single SPA-protected ECC point multiplication on an Edwards curve, for the calculation of a single PBC pairing on the BN curve, and for a SPA-protected 2048-bit RSA decryption.

-

-\begin{table}

-\centering

-\begin{tabular}{|l|c|}

-\hline

-&~Time in milliseconds~\\

-\hline

-~ECC point multiplication -O3 & 3.9  \\ % 

-~ECC point multiplication -Os & 5.9 \\ % 

-~PBC pairing -O3 & 47.4 \\ % 

-~PBC pairing -Os & 77.3 \\ % 

-~RSA decryption -O3 & 155 \\  %  

-~RSA decryption -Os & 233 \\  % 

-\hline

-\end{tabular}

-~\\

-\caption{C Benchmarks}

-\label{cspeed}

-\end{table}

-

-Observe that we do not compare these timings with any other -- because that is not the point.

-The point is -- are they ``good enough'' for whatever application you have in mind? And we suspect that, in the great majority of cases, they are.

-

-Clearly for Java and Javascript we are completely at the mercy of the efficiency (or otherwise) of the virtual machine. As can be seen from these Javascript timings, these

-can vary significantly.

-

-

-\begin{table}

-\centering

-\begin{tabular}{|l|l|l|c|}

-\hline

- & ~Device~ & ~Browser~ &~Time in seconds~\\

-\hline

-~ECC point multiplication~  & ~Raspberry Pi~ & ~Epiphany~ & 0.65  \\

-  & ~Apple iPad 2~ & ~Safari~ & 0.096  \\

-  & ~Samsung Galaxy Note 4~ & ~Chrome~ & 0.018  \\

-~PBC pairing~  &  ~Raspberry Pi~ & ~Epiphany~ & 11.0\\

- &  ~Apple iPad 2~ & ~Safari~ & 1.6\\

- &  ~Samsung Galaxy Note 4~ & ~Chrome~ & 0.30\\

-\hline

-\end{tabular}

-~\\

-\caption{JavaScript Benchmarks}

-\label{jsspeed}

-\end{table}

-

-

-\end{document}

diff --git a/docs/latex/clint.eps b/docs/latex/clint.eps
deleted file mode 100644
index ac8d8d0..0000000
--- a/docs/latex/clint.eps
+++ /dev/null
@@ -1,682 +0,0 @@
-%!PS-Adobe-2.0 EPSF-2.0

-%%Title: C:\Users\Shamus\Pictures\ngcl.dia

-%%Creator: Dia v0.97.2

-%%CreationDate: Thu Dec 04 10:27:13 2014

-%%For: Shamus

-%%Orientation: Portrait

-%%Magnification: 1.0000

-%%BoundingBox: 0 0 1109 740

-%%BeginSetup

-%%EndSetup

-%%EndComments

-%%BeginProlog

-[ /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef

-/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef

-/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef

-/.notdef /.notdef /space /exclam /quotedbl /numbersign /dollar /percent /ampersand /quoteright

-/parenleft /parenright /asterisk /plus /comma /hyphen /period /slash /zero /one

-/two /three /four /five /six /seven /eight /nine /colon /semicolon

-/less /equal /greater /question /at /A /B /C /D /E

-/F /G /H /I /J /K /L /M /N /O

-/P /Q /R /S /T /U /V /W /X /Y

-/Z /bracketleft /backslash /bracketright /asciicircum /underscore /quoteleft /a /b /c

-/d /e /f /g /h /i /j /k /l /m

-/n /o /p /q /r /s /t /u /v /w

-/x /y /z /braceleft /bar /braceright /asciitilde /.notdef /.notdef /.notdef

-/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef

-/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef

-/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef

-/space /exclamdown /cent /sterling /currency /yen /brokenbar /section /dieresis /copyright

-/ordfeminine /guillemotleft /logicalnot /hyphen /registered /macron /degree /plusminus /twosuperior /threesuperior

-/acute /mu /paragraph /periodcentered /cedilla /onesuperior /ordmasculine /guillemotright /onequarter /onehalf

-/threequarters /questiondown /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla

-/Egrave /Eacute /Ecircumflex /Edieresis /Igrave /Iacute /Icircumflex /Idieresis /Eth /Ntilde

-/Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply /Oslash /Ugrave /Uacute /Ucircumflex

-/Udieresis /Yacute /Thorn /germandbls /agrave /aacute /acircumflex /atilde /adieresis /aring

-/ae /ccedilla /egrave /eacute /ecircumflex /edieresis /igrave /iacute /icircumflex /idieresis

-/eth /ntilde /ograve /oacute /ocircumflex /otilde /odieresis /divide /oslash /ugrave

-/uacute /ucircumflex /udieresis /yacute /thorn /ydieresis] /isolatin1encoding exch def

-/cp {closepath} bind def

-/c {curveto} bind def

-/f {fill} bind def

-/a {arc} bind def

-/ef {eofill} bind def

-/ex {exch} bind def

-/gr {grestore} bind def

-/gs {gsave} bind def

-/sa {save} bind def

-/rs {restore} bind def

-/l {lineto} bind def

-/m {moveto} bind def

-/rm {rmoveto} bind def

-/n {newpath} bind def

-/s {stroke} bind def

-/sh {show} bind def

-/slc {setlinecap} bind def

-/slj {setlinejoin} bind def

-/slw {setlinewidth} bind def

-/srgb {setrgbcolor} bind def

-/rot {rotate} bind def

-/sc {scale} bind def

-/sd {setdash} bind def

-/ff {findfont} bind def

-/sf {setfont} bind def

-/scf {scalefont} bind def

-/sw {stringwidth pop} bind def

-/tr {translate} bind def

-

-/ellipsedict 8 dict def

-ellipsedict /mtrx matrix put

-/ellipse

-{ ellipsedict begin

-   /endangle exch def

-   /startangle exch def

-   /yrad exch def

-   /xrad exch def

-   /y exch def

-   /x exch def   /savematrix mtrx currentmatrix def

-   x y tr xrad yrad sc

-   0 0 1 startangle endangle arc

-   savematrix setmatrix

-   end

-} def

-

-/mergeprocs {

-dup length

-3 -1 roll

-dup

-length

-dup

-5 1 roll

-3 -1 roll

-add

-array cvx

-dup

-3 -1 roll

-0 exch

-putinterval

-dup

-4 2 roll

-putinterval

-} bind def

-/Times-Roman-latin1

-    /Times-Roman findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Times-Italic-latin1

-    /Times-Italic findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Times-Bold-latin1

-    /Times-Bold findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Times-BoldItalic-latin1

-    /Times-BoldItalic findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/AvantGarde-Gothic-latin1

-    /AvantGarde-Gothic findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/AvantGarde-BookOblique-latin1

-    /AvantGarde-BookOblique findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/AvantGarde-Demi-latin1

-    /AvantGarde-Demi findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/AvantGarde-DemiOblique-latin1

-    /AvantGarde-DemiOblique findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Bookman-Light-latin1

-    /Bookman-Light findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Bookman-LightItalic-latin1

-    /Bookman-LightItalic findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Bookman-Demi-latin1

-    /Bookman-Demi findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Bookman-DemiItalic-latin1

-    /Bookman-DemiItalic findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Courier-latin1

-    /Courier findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Courier-Oblique-latin1

-    /Courier-Oblique findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Courier-Bold-latin1

-    /Courier-Bold findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Courier-BoldOblique-latin1

-    /Courier-BoldOblique findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Helvetica-latin1

-    /Helvetica findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Helvetica-Oblique-latin1

-    /Helvetica-Oblique findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Helvetica-Bold-latin1

-    /Helvetica-Bold findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Helvetica-BoldOblique-latin1

-    /Helvetica-BoldOblique findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Helvetica-Narrow-latin1

-    /Helvetica-Narrow findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Helvetica-Narrow-Oblique-latin1

-    /Helvetica-Narrow-Oblique findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Helvetica-Narrow-Bold-latin1

-    /Helvetica-Narrow-Bold findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Helvetica-Narrow-BoldOblique-latin1

-    /Helvetica-Narrow-BoldOblique findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/NewCenturySchlbk-Roman-latin1

-    /NewCenturySchlbk-Roman findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/NewCenturySchlbk-Italic-latin1

-    /NewCenturySchlbk-Italic findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/NewCenturySchlbk-Bold-latin1

-    /NewCenturySchlbk-Bold findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/NewCenturySchlbk-BoldItalic-latin1

-    /NewCenturySchlbk-BoldItalic findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Palatino-Roman-latin1

-    /Palatino-Roman findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Palatino-Italic-latin1

-    /Palatino-Italic findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Palatino-Bold-latin1

-    /Palatino-Bold findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Palatino-BoldItalic-latin1

-    /Palatino-BoldItalic findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Symbol-latin1

-    /Symbol findfont

-definefont pop

-/ZapfChancery-MediumItalic-latin1

-    /ZapfChancery-MediumItalic findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/ZapfDingbats-latin1

-    /ZapfDingbats findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-28.346000 -28.346000 scale

--0.950000 -18.050000 translate

-%%EndProlog

-

-

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slj

-1.000000 1.000000 1.000000 srgb

-n 14.000000 15.000000 m 14.000000 18.000000 l 26.000000 18.000000 l 26.000000 15.000000 l f

-0.000000 0.000000 0.000000 srgb

-n 14.000000 15.000000 m 14.000000 18.000000 l 26.000000 18.000000 l 26.000000 15.000000 l cp s

-/Helvetica-latin1 ff 0.560000 scf sf

-(BIG - Big Number support) 15.000000 16.880000 m

- gs 1 -1 sc sh gr

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slj

-1.000000 1.000000 1.000000 srgb

-n 14.000000 11.000000 m 14.000000 14.000000 l 26.000000 14.000000 l 26.000000 11.000000 l f

-0.000000 0.000000 0.000000 srgb

-n 14.000000 11.000000 m 14.000000 14.000000 l 26.000000 14.000000 l 26.000000 11.000000 l cp s

-/Helvetica-latin1 ff 0.560000 scf sf

-(FP - Finite Field Functions) 15.000000 12.880000 m

- gs 1 -1 sc sh gr

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slj

-1.000000 1.000000 1.000000 srgb

-n 28.000000 11.000000 m 28.000000 14.000000 l 40.000000 14.000000 l 40.000000 11.000000 l f

-0.000000 0.000000 0.000000 srgb

-n 28.000000 11.000000 m 28.000000 14.000000 l 40.000000 14.000000 l 40.000000 11.000000 l cp s

-/Helvetica-latin1 ff 0.560000 scf sf

-(ECP - Elliptic Curves over Fp) 29.000000 12.880000 m

- gs 1 -1 sc sh gr

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slc

-n 26.000000 12.500000 m 27.513197 12.500000 l s

-[] 0 sd

-0 slj

-0 slc

-n 27.888197 12.500000 m 27.388197 12.750000 l 27.513197 12.500000 l 27.388197 12.250000 l ef

-n 27.888197 12.500000 m 27.388197 12.750000 l 27.513197 12.500000 l 27.388197 12.250000 l cp s

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slj

-1.000000 1.000000 1.000000 srgb

-n 14.000000 7.000000 m 14.000000 10.000000 l 26.000000 10.000000 l 26.000000 7.000000 l f

-0.000000 0.000000 0.000000 srgb

-n 14.000000 7.000000 m 14.000000 10.000000 l 26.000000 10.000000 l 26.000000 7.000000 l cp s

-/Helvetica-latin1 ff 0.560000 scf sf

-(FP2 - Extension Field Fp2) 15.000000 8.880000 m

- gs 1 -1 sc sh gr

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slj

-1.000000 1.000000 1.000000 srgb

-n 14.000000 3.000000 m 14.000000 6.000000 l 26.000000 6.000000 l 26.000000 3.000000 l f

-0.000000 0.000000 0.000000 srgb

-n 14.000000 3.000000 m 14.000000 6.000000 l 26.000000 6.000000 l 26.000000 3.000000 l cp s

-/Helvetica-latin1 ff 0.560000 scf sf

-(FP4 - Extension Field Fp4) 16.000000 4.880000 m

- gs 1 -1 sc sh gr

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slj

-1.000000 1.000000 1.000000 srgb

-n 14.000000 -1.000000 m 14.000000 2.000000 l 26.000000 2.000000 l 26.000000 -1.000000 l f

-0.000000 0.000000 0.000000 srgb

-n 14.000000 -1.000000 m 14.000000 2.000000 l 26.000000 2.000000 l 26.000000 -1.000000 l cp s

-/Helvetica-latin1 ff 0.560000 scf sf

-(FP12 - Extension Field Fp12) 16.000000 0.880000 m

- gs 1 -1 sc sh gr

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slj

-1.000000 1.000000 1.000000 srgb

-n 28.000000 7.000000 m 28.000000 10.000000 l 40.000000 10.000000 l 40.000000 7.000000 l f

-0.000000 0.000000 0.000000 srgb

-n 28.000000 7.000000 m 28.000000 10.000000 l 40.000000 10.000000 l 40.000000 7.000000 l cp s

-/Helvetica-latin1 ff 0.560000 scf sf

-(ECP2 - Elliptic Curves over Fp2) 29.000000 8.880000 m

- gs 1 -1 sc sh gr

-/Helvetica-latin1 ff 0.560000 scf sf

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slc

-n 34.000000 10.950928 m 34.000000 10.486803 l s

-[] 0 sd

-0 slj

-0 slc

-n 34.000000 10.111803 m 34.250000 10.611803 l 34.000000 10.486803 l 33.750000 10.611803 l ef

-n 34.000000 10.111803 m 34.250000 10.611803 l 34.000000 10.486803 l 33.750000 10.611803 l cp s

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slc

-n 20.000000 11.000000 m 20.000000 10.486803 l s

-[] 0 sd

-0 slj

-0 slc

-n 20.000000 10.111803 m 20.250000 10.611803 l 20.000000 10.486803 l 19.750000 10.611803 l ef

-n 20.000000 10.111803 m 20.250000 10.611803 l 20.000000 10.486803 l 19.750000 10.611803 l cp s

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slc

-n 20.000000 7.000000 m 20.000000 6.486803 l s

-[] 0 sd

-0 slj

-0 slc

-n 20.000000 6.111803 m 20.250000 6.611803 l 20.000000 6.486803 l 19.750000 6.611803 l ef

-n 20.000000 6.111803 m 20.250000 6.611803 l 20.000000 6.486803 l 19.750000 6.611803 l cp s

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slc

-n 20.000000 3.000000 m 20.000000 2.486803 l s

-[] 0 sd

-0 slj

-0 slc

-n 20.000000 2.111803 m 20.250000 2.611803 l 20.000000 2.486803 l 19.750000 2.611803 l ef

-n 20.000000 2.111803 m 20.250000 2.611803 l 20.000000 2.486803 l 19.750000 2.611803 l cp s

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slj

-1.000000 1.000000 1.000000 srgb

-n 28.000000 3.000000 m 28.000000 6.000000 l 40.000000 6.000000 l 40.000000 3.000000 l f

-0.000000 0.000000 0.000000 srgb

-n 28.000000 3.000000 m 28.000000 6.000000 l 40.000000 6.000000 l 40.000000 3.000000 l cp s

-/Helvetica-latin1 ff 0.560000 scf sf

-(PAIR - Pairings on BN curves) 29.000000 4.880000 m

- gs 1 -1 sc sh gr

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slc

-n 34.000000 6.950928 m 34.000000 6.486803 l s

-[] 0 sd

-0 slj

-0 slc

-n 34.000000 6.111803 m 34.250000 6.611803 l 34.000000 6.486803 l 33.750000 6.611803 l ef

-n 34.000000 6.111803 m 34.250000 6.611803 l 34.000000 6.486803 l 33.750000 6.611803 l cp s

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slc

-n 26.000000 0.500000 m 27.695896 2.619870 l s

-[] 0 sd

-0 slj

-0 slc

-n 27.930157 2.912696 m 27.422592 2.678436 l 27.695896 2.619870 l 27.813027 2.366088 l ef

-n 27.930157 2.912696 m 27.422592 2.678436 l 27.695896 2.619870 l 27.813027 2.366088 l cp s

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slj

-1.000000 1.000000 1.000000 srgb

-n 1.000000 3.000000 m 1.000000 6.000000 l 12.000000 6.000000 l 12.000000 3.000000 l f

-0.000000 0.000000 0.000000 srgb

-n 1.000000 3.000000 m 1.000000 6.000000 l 12.000000 6.000000 l 12.000000 3.000000 l cp s

-/Helvetica-latin1 ff 0.560000 scf sf

-(AES - Symmetric Encryption) 2.000000 4.880000 m

- gs 1 -1 sc sh gr

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slj

-1.000000 1.000000 1.000000 srgb

-n 1.000000 11.000000 m 1.000000 14.000000 l 12.000000 14.000000 l 12.000000 11.000000 l f

-0.000000 0.000000 0.000000 srgb

-n 1.000000 11.000000 m 1.000000 14.000000 l 12.000000 14.000000 l 12.000000 11.000000 l cp s

-/Helvetica-latin1 ff 0.560000 scf sf

-(RAND - Random Numbers) 2.000000 12.880000 m

- gs 1 -1 sc sh gr

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slc

-n 12.000000 12.500000 m 13.695896 14.619870 l s

-[] 0 sd

-0 slj

-0 slc

-n 13.930157 14.912696 m 13.422592 14.678436 l 13.695896 14.619870 l 13.813027 14.366088 l ef

-n 13.930157 14.912696 m 13.422592 14.678436 l 13.695896 14.619870 l 13.813027 14.366088 l cp s

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slj

-1.000000 1.000000 1.000000 srgb

-n 1.000000 15.000000 m 1.000000 18.000000 l 12.000000 18.000000 l 12.000000 15.000000 l f

-0.000000 0.000000 0.000000 srgb

-n 1.000000 15.000000 m 1.000000 18.000000 l 12.000000 18.000000 l 12.000000 15.000000 l cp s

-/Helvetica-latin1 ff 0.560000 scf sf

-(HASH - Hashing) 2.000000 8.880000 m

- gs 1 -1 sc sh gr

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slc

-n 6.500000 14.535876 m 6.500000 15.000000 l s

-[] 0 sd

-0 slj

-0 slc

-n 6.500000 14.160876 m 6.750000 14.660876 l 6.500000 14.535876 l 6.250000 14.660876 l ef

-n 6.500000 14.160876 m 6.750000 14.660876 l 6.500000 14.535876 l 6.250000 14.660876 l cp s

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slj

-n 1.000000 7.000000 m 1.000000 10.000000 l 12.000000 10.000000 l 12.000000 7.000000 l cp s

-/Helvetica-latin1 ff 0.560000 scf sf

-(External Entropy Source) 3.000000 16.880000 m

- gs 1 -1 sc sh gr

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slc

-n 6.500000 10.000000 m 6.500000 10.513197 l s

-[] 0 sd

-0 slj

-0 slc

-n 6.500000 10.888197 m 6.250000 10.388197 l 6.500000 10.513197 l 6.750000 10.388197 l ef

-n 6.500000 10.888197 m 6.250000 10.388197 l 6.500000 10.513197 l 6.750000 10.388197 l cp s

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slj

-1.000000 1.000000 1.000000 srgb

-n 28.000000 -1.000000 m 28.000000 2.000000 l 40.000000 2.000000 l 40.000000 -1.000000 l f

-0.000000 0.000000 0.000000 srgb

-n 28.000000 -1.000000 m 28.000000 2.000000 l 40.000000 2.000000 l 40.000000 -1.000000 l cp s

-/Helvetica-latin1 ff 0.560000 scf sf

-(OCT - Octet Input/Output ) 29.000000 0.880000 m

- gs 1 -1 sc sh gr

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slj

-1.000000 1.000000 1.000000 srgb

-n 28.000000 15.000000 m 28.000000 18.000000 l 40.000000 18.000000 l 40.000000 15.000000 l f

-0.000000 0.000000 0.000000 srgb

-n 28.000000 15.000000 m 28.000000 18.000000 l 40.000000 18.000000 l 40.000000 15.000000 l cp s

-/Helvetica-latin1 ff 0.560000 scf sf

-(ROM - Field/Curve Constants) 29.000000 16.880000 m

- gs 1 -1 sc sh gr

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slj

-1.000000 1.000000 1.000000 srgb

-n 4.000000 -8.000000 m 4.000000 -4.000000 l 36.000000 -4.000000 l 36.000000 -8.000000 l f

-0.000000 0.000000 0.000000 srgb

-n 4.000000 -8.000000 m 4.000000 -4.000000 l 36.000000 -4.000000 l 36.000000 -8.000000 l cp s

-/Helvetica-latin1 ff 0.560000 scf sf

-(Your API) 20.000000 -6.120000 m

- gs 1 -1 sc sh gr

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slc

-n 30.662354 -1.049622 m 24.850715 -3.747882 l s

-[] 0 sd

-0 slj

-0 slc

-n 24.510586 -3.905799 m 25.069369 -3.921996 l 24.850715 -3.747882 l 24.858813 -3.468491 l ef

-n 24.510586 -3.905799 m 25.069369 -3.921996 l 24.850715 -3.747882 l 24.858813 -3.468491 l cp s

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slj

-1.000000 1.000000 1.000000 srgb

-n 1.000000 -1.000000 m 1.000000 2.000000 l 12.000000 2.000000 l 12.000000 -1.000000 l f

-0.000000 0.000000 0.000000 srgb

-n 1.000000 -1.000000 m 1.000000 2.000000 l 12.000000 2.000000 l 12.000000 -1.000000 l cp s

-/Helvetica-latin1 ff 0.560000 scf sf

-(GCM - authenticated encryption ) 2.000000 0.880000 m

- gs 1 -1 sc sh gr

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slc

-n 26.000000 8.500000 m 27.513197 8.500000 l s

-[] 0 sd

-0 slj

-0 slc

-n 27.888197 8.500000 m 27.388197 8.750000 l 27.513197 8.500000 l 27.388197 8.250000 l ef

-n 27.888197 8.500000 m 27.388197 8.750000 l 27.513197 8.500000 l 27.388197 8.250000 l cp s

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slc

-n 6.500000 2.950928 m 6.500000 2.486803 l s

-[] 0 sd

-0 slj

-0 slc

-n 6.500000 2.111803 m 6.750000 2.611803 l 6.500000 2.486803 l 6.250000 2.611803 l ef

-n 6.500000 2.111803 m 6.750000 2.611803 l 6.500000 2.486803 l 6.250000 2.611803 l cp s

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slc

-n 20.000000 15.000000 m 20.000000 14.486803 l s

-[] 0 sd

-0 slj

-0 slc

-n 20.000000 14.111803 m 20.250000 14.611803 l 20.000000 14.486803 l 19.750000 14.611803 l ef

-n 20.000000 14.111803 m 20.250000 14.611803 l 20.000000 14.486803 l 19.750000 14.611803 l cp s

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slc

-n 34.000000 15.000000 m 34.000000 14.486803 l s

-[] 0 sd

-0 slj

-0 slc

-n 34.000000 14.111803 m 34.250000 14.611803 l 34.000000 14.486803 l 33.750000 14.611803 l ef

-n 34.000000 14.111803 m 34.250000 14.611803 l 34.000000 14.486803 l 33.750000 14.611803 l cp s

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slc

-n 28.000000 16.500000 m 26.304104 14.380130 l s

-[] 0 sd

-0 slj

-0 slc

-n 26.069843 14.087304 m 26.577408 14.321564 l 26.304104 14.380130 l 26.186973 14.633912 l ef

-n 26.069843 14.087304 m 26.577408 14.321564 l 26.304104 14.380130 l 26.186973 14.633912 l cp s

-showpage

diff --git a/docs/latex/llncs.cls b/docs/latex/llncs.cls
deleted file mode 100644
index 23fd1c6..0000000
--- a/docs/latex/llncs.cls
+++ /dev/null
@@ -1,1190 +0,0 @@
-% LLNCS DOCUMENT CLASS -- version 2.14 (17-Aug-2004)

-% Springer Verlag LaTeX2e support for Lecture Notes in Computer Science

-%

-%%

-%% \CharacterTable

-%%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z

-%%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z

-%%   Digits        \0\1\2\3\4\5\6\7\8\9

-%%   Exclamation   \!     Double quote  \"     Hash (number) \#

-%%   Dollar        \$     Percent       \%     Ampersand     \&

-%%   Acute accent  \'     Left paren    \(     Right paren   \)

-%%   Asterisk      \*     Plus          \+     Comma         \,

-%%   Minus         \-     Point         \.     Solidus       \/

-%%   Colon         \:     Semicolon     \;     Less than     \<

-%%   Equals        \=     Greater than  \>     Question mark \?

-%%   Commercial at \@     Left bracket  \[     Backslash     \\

-%%   Right bracket \]     Circumflex    \^     Underscore    \_

-%%   Grave accent  \`     Left brace    \{     Vertical bar  \|

-%%   Right brace   \}     Tilde         \~}

-%%

-\NeedsTeXFormat{LaTeX2e}[1995/12/01]

-\ProvidesClass{llncs}[2004/08/17 v2.14

-^^J LaTeX document class for Lecture Notes in Computer Science]

-% Options

-\let\if@envcntreset\iffalse

-\DeclareOption{envcountreset}{\let\if@envcntreset\iftrue}

-\DeclareOption{citeauthoryear}{\let\citeauthoryear=Y}

-\DeclareOption{oribibl}{\let\oribibl=Y}

-\let\if@custvec\iftrue

-\DeclareOption{orivec}{\let\if@custvec\iffalse}

-\let\if@envcntsame\iffalse

-\DeclareOption{envcountsame}{\let\if@envcntsame\iftrue}

-\let\if@envcntsect\iffalse

-\DeclareOption{envcountsect}{\let\if@envcntsect\iftrue}

-\let\if@runhead\iffalse

-\DeclareOption{runningheads}{\let\if@runhead\iftrue}

-

-\let\if@openbib\iffalse

-\DeclareOption{openbib}{\let\if@openbib\iftrue}

-

-% languages

-\let\switcht@@therlang\relax

-\def\ds@deutsch{\def\switcht@@therlang{\switcht@deutsch}}

-\def\ds@francais{\def\switcht@@therlang{\switcht@francais}}

-

-\DeclareOption*{\PassOptionsToClass{\CurrentOption}{article}}

-

-\ProcessOptions

-

-\LoadClass[twoside]{article}

-\RequirePackage{multicol} % needed for the list of participants, index

-

-\setlength{\textwidth}{12.2cm}

-\setlength{\textheight}{19.3cm}

-\renewcommand\@pnumwidth{2em}

-\renewcommand\@tocrmarg{3.5em}

-%

-\def\@dottedtocline#1#2#3#4#5{%

-  \ifnum #1>\c@tocdepth \else

-    \vskip \z@ \@plus.2\p@

-    {\leftskip #2\relax \rightskip \@tocrmarg \advance\rightskip by 0pt plus 2cm

-               \parfillskip -\rightskip \pretolerance=10000

-     \parindent #2\relax\@afterindenttrue

-     \interlinepenalty\@M

-     \leavevmode

-     \@tempdima #3\relax

-     \advance\leftskip \@tempdima \null\nobreak\hskip -\leftskip

-     {#4}\nobreak

-     \leaders\hbox{$\m@th

-        \mkern \@dotsep mu\hbox{.}\mkern \@dotsep

-        mu$}\hfill

-     \nobreak

-     \hb@xt@\@pnumwidth{\hfil\normalfont \normalcolor #5}%

-     \par}%

-  \fi}

-%

-\def\switcht@albion{%

-\def\abstractname{Abstract.}

-\def\ackname{Acknowledgement.}

-\def\andname{and}

-\def\lastandname{\unskip, and}

-\def\appendixname{Appendix}

-\def\chaptername{Chapter}

-\def\claimname{Claim}

-\def\conjecturename{Conjecture}

-\def\contentsname{Table of Contents}

-\def\corollaryname{Corollary}

-\def\definitionname{Definition}

-\def\examplename{Example}

-\def\exercisename{Exercise}

-\def\figurename{Fig.}

-\def\keywordname{{\bf Key words:}}

-\def\indexname{Index}

-\def\lemmaname{Lemma}

-\def\contriblistname{List of Contributors}

-\def\listfigurename{List of Figures}

-\def\listtablename{List of Tables}

-\def\mailname{{\it Correspondence to\/}:}

-\def\noteaddname{Note added in proof}

-\def\notename{Note}

-\def\partname{Part}

-\def\problemname{Problem}

-\def\proofname{Proof}

-\def\propertyname{Property}

-\def\propositionname{Proposition}

-\def\questionname{Question}

-\def\remarkname{Remark}

-\def\seename{see}

-\def\solutionname{Solution}

-\def\subclassname{{\it Subject Classifications\/}:}

-\def\tablename{Table}

-\def\theoremname{Theorem}}

-\switcht@albion

-% Names of theorem like environments are already defined

-% but must be translated if another language is chosen

-%

-% French section

-\def\switcht@francais{%\typeout{On parle francais.}%

- \def\abstractname{R\'esum\'e.}%

- \def\ackname{Remerciements.}%

- \def\andname{et}%

- \def\lastandname{ et}%

- \def\appendixname{Appendice}

- \def\chaptername{Chapitre}%

- \def\claimname{Pr\'etention}%

- \def\conjecturename{Hypoth\`ese}%

- \def\contentsname{Table des mati\`eres}%

- \def\corollaryname{Corollaire}%

- \def\definitionname{D\'efinition}%

- \def\examplename{Exemple}%

- \def\exercisename{Exercice}%

- \def\figurename{Fig.}%

- \def\keywordname{{\bf Mots-cl\'e:}}

- \def\indexname{Index}

- \def\lemmaname{Lemme}%

- \def\contriblistname{Liste des contributeurs}

- \def\listfigurename{Liste des figures}%

- \def\listtablename{Liste des tables}%

- \def\mailname{{\it Correspondence to\/}:}

- \def\noteaddname{Note ajout\'ee \`a l'\'epreuve}%

- \def\notename{Remarque}%

- \def\partname{Partie}%

- \def\problemname{Probl\`eme}%

- \def\proofname{Preuve}%

- \def\propertyname{Caract\'eristique}%

-%\def\propositionname{Proposition}%

- \def\questionname{Question}%

- \def\remarkname{Remarque}%

- \def\seename{voir}

- \def\solutionname{Solution}%

- \def\subclassname{{\it Subject Classifications\/}:}

- \def\tablename{Tableau}%

- \def\theoremname{Th\'eor\`eme}%

-}

-%

-% German section

-\def\switcht@deutsch{%\typeout{Man spricht deutsch.}%

- \def\abstractname{Zusammenfassung.}%

- \def\ackname{Danksagung.}%

- \def\andname{und}%

- \def\lastandname{ und}%

- \def\appendixname{Anhang}%

- \def\chaptername{Kapitel}%

- \def\claimname{Behauptung}%

- \def\conjecturename{Hypothese}%

- \def\contentsname{Inhaltsverzeichnis}%

- \def\corollaryname{Korollar}%

-%\def\definitionname{Definition}%

- \def\examplename{Beispiel}%

- \def\exercisename{\"Ubung}%

- \def\figurename{Abb.}%

- \def\keywordname{{\bf Schl\"usselw\"orter:}}

- \def\indexname{Index}

-%\def\lemmaname{Lemma}%

- \def\contriblistname{Mitarbeiter}

- \def\listfigurename{Abbildungsverzeichnis}%

- \def\listtablename{Tabellenverzeichnis}%

- \def\mailname{{\it Correspondence to\/}:}

- \def\noteaddname{Nachtrag}%

- \def\notename{Anmerkung}%

- \def\partname{Teil}%

-%\def\problemname{Problem}%

- \def\proofname{Beweis}%

- \def\propertyname{Eigenschaft}%

-%\def\propositionname{Proposition}%

- \def\questionname{Frage}%

- \def\remarkname{Anmerkung}%

- \def\seename{siehe}

- \def\solutionname{L\"osung}%

- \def\subclassname{{\it Subject Classifications\/}:}

- \def\tablename{Tabelle}%

-%\def\theoremname{Theorem}%

-}

-

-% Ragged bottom for the actual page

-\def\thisbottomragged{\def\@textbottom{\vskip\z@ plus.0001fil

-\global\let\@textbottom\relax}}

-

-\renewcommand\small{%

-   \@setfontsize\small\@ixpt{11}%

-   \abovedisplayskip 8.5\p@ \@plus3\p@ \@minus4\p@

-   \abovedisplayshortskip \z@ \@plus2\p@

-   \belowdisplayshortskip 4\p@ \@plus2\p@ \@minus2\p@

-   \def\@listi{\leftmargin\leftmargini

-               \parsep 0\p@ \@plus1\p@ \@minus\p@

-               \topsep 8\p@ \@plus2\p@ \@minus4\p@

-               \itemsep0\p@}%

-   \belowdisplayskip \abovedisplayskip

-}

-

-\frenchspacing

-\widowpenalty=10000

-\clubpenalty=10000

-

-\setlength\oddsidemargin   {63\p@}

-\setlength\evensidemargin  {63\p@}

-\setlength\marginparwidth  {90\p@}

-

-\setlength\headsep   {16\p@}

-

-\setlength\footnotesep{7.7\p@}

-\setlength\textfloatsep{8mm\@plus 2\p@ \@minus 4\p@}

-\setlength\intextsep   {8mm\@plus 2\p@ \@minus 2\p@}

-

-\setcounter{secnumdepth}{2}

-

-\newcounter {chapter}

-\renewcommand\thechapter      {\@arabic\c@chapter}

-

-\newif\if@mainmatter \@mainmattertrue

-\newcommand\frontmatter{\cleardoublepage

-            \@mainmatterfalse\pagenumbering{Roman}}

-\newcommand\mainmatter{\cleardoublepage

-       \@mainmattertrue\pagenumbering{arabic}}

-\newcommand\backmatter{\if@openright\cleardoublepage\else\clearpage\fi

-      \@mainmatterfalse}

-

-\renewcommand\part{\cleardoublepage

-                 \thispagestyle{empty}%

-                 \if@twocolumn

-                     \onecolumn

-                     \@tempswatrue

-                   \else

-                     \@tempswafalse

-                 \fi

-                 \null\vfil

-                 \secdef\@part\@spart}

-

-\def\@part[#1]#2{%

-    \ifnum \c@secnumdepth >-2\relax

-      \refstepcounter{part}%

-      \addcontentsline{toc}{part}{\thepart\hspace{1em}#1}%

-    \else

-      \addcontentsline{toc}{part}{#1}%

-    \fi

-    \markboth{}{}%

-    {\centering

-     \interlinepenalty \@M

-     \normalfont

-     \ifnum \c@secnumdepth >-2\relax

-       \huge\bfseries \partname~\thepart

-       \par

-       \vskip 20\p@

-     \fi

-     \Huge \bfseries #2\par}%

-    \@endpart}

-\def\@spart#1{%

-    {\centering

-     \interlinepenalty \@M

-     \normalfont

-     \Huge \bfseries #1\par}%

-    \@endpart}

-\def\@endpart{\vfil\newpage

-              \if@twoside

-                \null

-                \thispagestyle{empty}%

-                \newpage

-              \fi

-              \if@tempswa

-                \twocolumn

-              \fi}

-

-\newcommand\chapter{\clearpage

-                    \thispagestyle{empty}%

-                    \global\@topnum\z@

-                    \@afterindentfalse

-                    \secdef\@chapter\@schapter}

-\def\@chapter[#1]#2{\ifnum \c@secnumdepth >\m@ne

-                       \if@mainmatter

-                         \refstepcounter{chapter}%

-                         \typeout{\@chapapp\space\thechapter.}%

-                         \addcontentsline{toc}{chapter}%

-                                  {\protect\numberline{\thechapter}#1}%

-                       \else

-                         \addcontentsline{toc}{chapter}{#1}%

-                       \fi

-                    \else

-                      \addcontentsline{toc}{chapter}{#1}%

-                    \fi

-                    \chaptermark{#1}%

-                    \addtocontents{lof}{\protect\addvspace{10\p@}}%

-                    \addtocontents{lot}{\protect\addvspace{10\p@}}%

-                    \if@twocolumn

-                      \@topnewpage[\@makechapterhead{#2}]%

-                    \else

-                      \@makechapterhead{#2}%

-                      \@afterheading

-                    \fi}

-\def\@makechapterhead#1{%

-% \vspace*{50\p@}%

-  {\centering

-    \ifnum \c@secnumdepth >\m@ne

-      \if@mainmatter

-        \large\bfseries \@chapapp{} \thechapter

-        \par\nobreak

-        \vskip 20\p@

-      \fi

-    \fi

-    \interlinepenalty\@M

-    \Large \bfseries #1\par\nobreak

-    \vskip 40\p@

-  }}

-\def\@schapter#1{\if@twocolumn

-                   \@topnewpage[\@makeschapterhead{#1}]%

-                 \else

-                   \@makeschapterhead{#1}%

-                   \@afterheading

-                 \fi}

-\def\@makeschapterhead#1{%

-% \vspace*{50\p@}%

-  {\centering

-    \normalfont

-    \interlinepenalty\@M

-    \Large \bfseries  #1\par\nobreak

-    \vskip 40\p@

-  }}

-

-\renewcommand\section{\@startsection{section}{1}{\z@}%

-                       {-18\p@ \@plus -4\p@ \@minus -4\p@}%

-                       {12\p@ \@plus 4\p@ \@minus 4\p@}%

-                       {\normalfont\large\bfseries\boldmath

-                        \rightskip=\z@ \@plus 8em\pretolerance=10000 }}

-\renewcommand\subsection{\@startsection{subsection}{2}{\z@}%

-                       {-18\p@ \@plus -4\p@ \@minus -4\p@}%

-                       {8\p@ \@plus 4\p@ \@minus 4\p@}%

-                       {\normalfont\normalsize\bfseries\boldmath

-                        \rightskip=\z@ \@plus 8em\pretolerance=10000 }}

-\renewcommand\subsubsection{\@startsection{subsubsection}{3}{\z@}%

-                       {-18\p@ \@plus -4\p@ \@minus -4\p@}%

-                       {-0.5em \@plus -0.22em \@minus -0.1em}%

-                       {\normalfont\normalsize\bfseries\boldmath}}

-\renewcommand\paragraph{\@startsection{paragraph}{4}{\z@}%

-                       {-12\p@ \@plus -4\p@ \@minus -4\p@}%

-                       {-0.5em \@plus -0.22em \@minus -0.1em}%

-                       {\normalfont\normalsize\itshape}}

-\renewcommand\subparagraph[1]{\typeout{LLNCS warning: You should not use

-                  \string\subparagraph\space with this class}\vskip0.5cm

-You should not use \verb|\subparagraph| with this class.\vskip0.5cm}

-

-\DeclareMathSymbol{\Gamma}{\mathalpha}{letters}{"00}

-\DeclareMathSymbol{\Delta}{\mathalpha}{letters}{"01}

-\DeclareMathSymbol{\Theta}{\mathalpha}{letters}{"02}

-\DeclareMathSymbol{\Lambda}{\mathalpha}{letters}{"03}

-\DeclareMathSymbol{\Xi}{\mathalpha}{letters}{"04}

-\DeclareMathSymbol{\Pi}{\mathalpha}{letters}{"05}

-\DeclareMathSymbol{\Sigma}{\mathalpha}{letters}{"06}

-\DeclareMathSymbol{\Upsilon}{\mathalpha}{letters}{"07}

-\DeclareMathSymbol{\Phi}{\mathalpha}{letters}{"08}

-\DeclareMathSymbol{\Psi}{\mathalpha}{letters}{"09}

-\DeclareMathSymbol{\Omega}{\mathalpha}{letters}{"0A}

-

-\let\footnotesize\small

-

-\if@custvec

-\def\vec#1{\mathchoice{\mbox{\boldmath$\displaystyle#1$}}

-{\mbox{\boldmath$\textstyle#1$}}

-{\mbox{\boldmath$\scriptstyle#1$}}

-{\mbox{\boldmath$\scriptscriptstyle#1$}}}

-\fi

-

-\def\squareforqed{\hbox{\rlap{$\sqcap$}$\sqcup$}}

-\def\qed{\ifmmode\squareforqed\else{\unskip\nobreak\hfil

-\penalty50\hskip1em\null\nobreak\hfil\squareforqed

-\parfillskip=0pt\finalhyphendemerits=0\endgraf}\fi}

-

-\def\getsto{\mathrel{\mathchoice {\vcenter{\offinterlineskip

-\halign{\hfil

-$\displaystyle##$\hfil\cr\gets\cr\to\cr}}}

-{\vcenter{\offinterlineskip\halign{\hfil$\textstyle##$\hfil\cr\gets

-\cr\to\cr}}}

-{\vcenter{\offinterlineskip\halign{\hfil$\scriptstyle##$\hfil\cr\gets

-\cr\to\cr}}}

-{\vcenter{\offinterlineskip\halign{\hfil$\scriptscriptstyle##$\hfil\cr

-\gets\cr\to\cr}}}}}

-\def\lid{\mathrel{\mathchoice {\vcenter{\offinterlineskip\halign{\hfil

-$\displaystyle##$\hfil\cr<\cr\noalign{\vskip1.2pt}=\cr}}}

-{\vcenter{\offinterlineskip\halign{\hfil$\textstyle##$\hfil\cr<\cr

-\noalign{\vskip1.2pt}=\cr}}}

-{\vcenter{\offinterlineskip\halign{\hfil$\scriptstyle##$\hfil\cr<\cr

-\noalign{\vskip1pt}=\cr}}}

-{\vcenter{\offinterlineskip\halign{\hfil$\scriptscriptstyle##$\hfil\cr

-<\cr

-\noalign{\vskip0.9pt}=\cr}}}}}

-\def\gid{\mathrel{\mathchoice {\vcenter{\offinterlineskip\halign{\hfil

-$\displaystyle##$\hfil\cr>\cr\noalign{\vskip1.2pt}=\cr}}}

-{\vcenter{\offinterlineskip\halign{\hfil$\textstyle##$\hfil\cr>\cr

-\noalign{\vskip1.2pt}=\cr}}}

-{\vcenter{\offinterlineskip\halign{\hfil$\scriptstyle##$\hfil\cr>\cr

-\noalign{\vskip1pt}=\cr}}}

-{\vcenter{\offinterlineskip\halign{\hfil$\scriptscriptstyle##$\hfil\cr

->\cr

-\noalign{\vskip0.9pt}=\cr}}}}}

-\def\grole{\mathrel{\mathchoice {\vcenter{\offinterlineskip

-\halign{\hfil

-$\displaystyle##$\hfil\cr>\cr\noalign{\vskip-1pt}<\cr}}}

-{\vcenter{\offinterlineskip\halign{\hfil$\textstyle##$\hfil\cr

->\cr\noalign{\vskip-1pt}<\cr}}}

-{\vcenter{\offinterlineskip\halign{\hfil$\scriptstyle##$\hfil\cr

->\cr\noalign{\vskip-0.8pt}<\cr}}}

-{\vcenter{\offinterlineskip\halign{\hfil$\scriptscriptstyle##$\hfil\cr

->\cr\noalign{\vskip-0.3pt}<\cr}}}}}

-\def\bbbr{{\rm I\!R}} %reelle Zahlen

-\def\bbbm{{\rm I\!M}}

-\def\bbbn{{\rm I\!N}} %natuerliche Zahlen

-\def\bbbf{{\rm I\!F}}

-\def\bbbh{{\rm I\!H}}

-\def\bbbk{{\rm I\!K}}

-\def\bbbp{{\rm I\!P}}

-\def\bbbone{{\mathchoice {\rm 1\mskip-4mu l} {\rm 1\mskip-4mu l}

-{\rm 1\mskip-4.5mu l} {\rm 1\mskip-5mu l}}}

-\def\bbbc{{\mathchoice {\setbox0=\hbox{$\displaystyle\rm C$}\hbox{\hbox

-to0pt{\kern0.4\wd0\vrule height0.9\ht0\hss}\box0}}

-{\setbox0=\hbox{$\textstyle\rm C$}\hbox{\hbox

-to0pt{\kern0.4\wd0\vrule height0.9\ht0\hss}\box0}}

-{\setbox0=\hbox{$\scriptstyle\rm C$}\hbox{\hbox

-to0pt{\kern0.4\wd0\vrule height0.9\ht0\hss}\box0}}

-{\setbox0=\hbox{$\scriptscriptstyle\rm C$}\hbox{\hbox

-to0pt{\kern0.4\wd0\vrule height0.9\ht0\hss}\box0}}}}

-\def\bbbq{{\mathchoice {\setbox0=\hbox{$\displaystyle\rm

-Q$}\hbox{\raise

-0.15\ht0\hbox to0pt{\kern0.4\wd0\vrule height0.8\ht0\hss}\box0}}

-{\setbox0=\hbox{$\textstyle\rm Q$}\hbox{\raise

-0.15\ht0\hbox to0pt{\kern0.4\wd0\vrule height0.8\ht0\hss}\box0}}

-{\setbox0=\hbox{$\scriptstyle\rm Q$}\hbox{\raise

-0.15\ht0\hbox to0pt{\kern0.4\wd0\vrule height0.7\ht0\hss}\box0}}

-{\setbox0=\hbox{$\scriptscriptstyle\rm Q$}\hbox{\raise

-0.15\ht0\hbox to0pt{\kern0.4\wd0\vrule height0.7\ht0\hss}\box0}}}}

-\def\bbbt{{\mathchoice {\setbox0=\hbox{$\displaystyle\rm

-T$}\hbox{\hbox to0pt{\kern0.3\wd0\vrule height0.9\ht0\hss}\box0}}

-{\setbox0=\hbox{$\textstyle\rm T$}\hbox{\hbox

-to0pt{\kern0.3\wd0\vrule height0.9\ht0\hss}\box0}}

-{\setbox0=\hbox{$\scriptstyle\rm T$}\hbox{\hbox

-to0pt{\kern0.3\wd0\vrule height0.9\ht0\hss}\box0}}

-{\setbox0=\hbox{$\scriptscriptstyle\rm T$}\hbox{\hbox

-to0pt{\kern0.3\wd0\vrule height0.9\ht0\hss}\box0}}}}

-\def\bbbs{{\mathchoice

-{\setbox0=\hbox{$\displaystyle     \rm S$}\hbox{\raise0.5\ht0\hbox

-to0pt{\kern0.35\wd0\vrule height0.45\ht0\hss}\hbox

-to0pt{\kern0.55\wd0\vrule height0.5\ht0\hss}\box0}}

-{\setbox0=\hbox{$\textstyle        \rm S$}\hbox{\raise0.5\ht0\hbox

-to0pt{\kern0.35\wd0\vrule height0.45\ht0\hss}\hbox

-to0pt{\kern0.55\wd0\vrule height0.5\ht0\hss}\box0}}

-{\setbox0=\hbox{$\scriptstyle      \rm S$}\hbox{\raise0.5\ht0\hbox

-to0pt{\kern0.35\wd0\vrule height0.45\ht0\hss}\raise0.05\ht0\hbox

-to0pt{\kern0.5\wd0\vrule height0.45\ht0\hss}\box0}}

-{\setbox0=\hbox{$\scriptscriptstyle\rm S$}\hbox{\raise0.5\ht0\hbox

-to0pt{\kern0.4\wd0\vrule height0.45\ht0\hss}\raise0.05\ht0\hbox

-to0pt{\kern0.55\wd0\vrule height0.45\ht0\hss}\box0}}}}

-\def\bbbz{{\mathchoice {\hbox{$\mathsf\textstyle Z\kern-0.4em Z$}}

-{\hbox{$\mathsf\textstyle Z\kern-0.4em Z$}}

-{\hbox{$\mathsf\scriptstyle Z\kern-0.3em Z$}}

-{\hbox{$\mathsf\scriptscriptstyle Z\kern-0.2em Z$}}}}

-

-\let\ts\,

-

-\setlength\leftmargini  {17\p@}

-\setlength\leftmargin    {\leftmargini}

-\setlength\leftmarginii  {\leftmargini}

-\setlength\leftmarginiii {\leftmargini}

-\setlength\leftmarginiv  {\leftmargini}

-\setlength  \labelsep  {.5em}

-\setlength  \labelwidth{\leftmargini}

-\addtolength\labelwidth{-\labelsep}

-

-\def\@listI{\leftmargin\leftmargini

-            \parsep 0\p@ \@plus1\p@ \@minus\p@

-            \topsep 8\p@ \@plus2\p@ \@minus4\p@

-            \itemsep0\p@}

-\let\@listi\@listI

-\@listi

-\def\@listii {\leftmargin\leftmarginii

-              \labelwidth\leftmarginii

-              \advance\labelwidth-\labelsep

-              \topsep    0\p@ \@plus2\p@ \@minus\p@}

-\def\@listiii{\leftmargin\leftmarginiii

-              \labelwidth\leftmarginiii

-              \advance\labelwidth-\labelsep

-              \topsep    0\p@ \@plus\p@\@minus\p@

-              \parsep    \z@

-              \partopsep \p@ \@plus\z@ \@minus\p@}

-

-\renewcommand\labelitemi{\normalfont\bfseries --}

-\renewcommand\labelitemii{$\m@th\bullet$}

-

-\setlength\arraycolsep{1.4\p@}

-\setlength\tabcolsep{1.4\p@}

-

-\def\tableofcontents{\chapter*{\contentsname\@mkboth{{\contentsname}}%

-                                                    {{\contentsname}}}

- \def\authcount##1{\setcounter{auco}{##1}\setcounter{@auth}{1}}

- \def\lastand{\ifnum\value{auco}=2\relax

-                 \unskip{} \andname\

-              \else

-                 \unskip \lastandname\

-              \fi}%

- \def\and{\stepcounter{@auth}\relax

-          \ifnum\value{@auth}=\value{auco}%

-             \lastand

-          \else

-             \unskip,

-          \fi}%

- \@starttoc{toc}\if@restonecol\twocolumn\fi}

-

-\def\l@part#1#2{\addpenalty{\@secpenalty}%

-   \addvspace{2em plus\p@}%  % space above part line

-   \begingroup

-     \parindent \z@

-     \rightskip \z@ plus 5em

-     \hrule\vskip5pt

-     \large               % same size as for a contribution heading

-     \bfseries\boldmath   % set line in boldface

-     \leavevmode          % TeX command to enter horizontal mode.

-     #1\par

-     \vskip5pt

-     \hrule

-     \vskip1pt

-     \nobreak             % Never break after part entry

-   \endgroup}

-

-\def\@dotsep{2}

-

-\def\hyperhrefextend{\ifx\hyper@anchor\@undefined\else

-{chapter.\thechapter}\fi}

-

-\def\addnumcontentsmark#1#2#3{%

-\addtocontents{#1}{\protect\contentsline{#2}{\protect\numberline

-                     {\thechapter}#3}{\thepage}\hyperhrefextend}}

-\def\addcontentsmark#1#2#3{%

-\addtocontents{#1}{\protect\contentsline{#2}{#3}{\thepage}\hyperhrefextend}}

-\def\addcontentsmarkwop#1#2#3{%

-\addtocontents{#1}{\protect\contentsline{#2}{#3}{0}\hyperhrefextend}}

-

-\def\@adcmk[#1]{\ifcase #1 \or

-\def\@gtempa{\addnumcontentsmark}%

-  \or    \def\@gtempa{\addcontentsmark}%

-  \or    \def\@gtempa{\addcontentsmarkwop}%

-  \fi\@gtempa{toc}{chapter}}

-\def\addtocmark{\@ifnextchar[{\@adcmk}{\@adcmk[3]}}

-

-\def\l@chapter#1#2{\addpenalty{-\@highpenalty}

- \vskip 1.0em plus 1pt \@tempdima 1.5em \begingroup

- \parindent \z@ \rightskip \@tocrmarg

- \advance\rightskip by 0pt plus 2cm

- \parfillskip -\rightskip \pretolerance=10000

- \leavevmode \advance\leftskip\@tempdima \hskip -\leftskip

- {\large\bfseries\boldmath#1}\ifx0#2\hfil\null

- \else

-      \nobreak

-      \leaders\hbox{$\m@th \mkern \@dotsep mu.\mkern

-      \@dotsep mu$}\hfill

-      \nobreak\hbox to\@pnumwidth{\hss #2}%

- \fi\par

- \penalty\@highpenalty \endgroup}

-

-\def\l@title#1#2{\addpenalty{-\@highpenalty}

- \addvspace{8pt plus 1pt}

- \@tempdima \z@

- \begingroup

- \parindent \z@ \rightskip \@tocrmarg

- \advance\rightskip by 0pt plus 2cm

- \parfillskip -\rightskip \pretolerance=10000

- \leavevmode \advance\leftskip\@tempdima \hskip -\leftskip

- #1\nobreak

- \leaders\hbox{$\m@th \mkern \@dotsep mu.\mkern

- \@dotsep mu$}\hfill

- \nobreak\hbox to\@pnumwidth{\hss #2}\par

- \penalty\@highpenalty \endgroup}

-

-\def\l@author#1#2{\addpenalty{\@highpenalty}

- \@tempdima=15\p@ %\z@

- \begingroup

- \parindent \z@ \rightskip \@tocrmarg

- \advance\rightskip by 0pt plus 2cm

- \pretolerance=10000

- \leavevmode \advance\leftskip\@tempdima %\hskip -\leftskip

- \textit{#1}\par

- \penalty\@highpenalty \endgroup}

-

-\setcounter{tocdepth}{0}

-\newdimen\tocchpnum

-\newdimen\tocsecnum

-\newdimen\tocsectotal

-\newdimen\tocsubsecnum

-\newdimen\tocsubsectotal

-\newdimen\tocsubsubsecnum

-\newdimen\tocsubsubsectotal

-\newdimen\tocparanum

-\newdimen\tocparatotal

-\newdimen\tocsubparanum

-\tocchpnum=\z@            % no chapter numbers

-\tocsecnum=15\p@          % section 88. plus 2.222pt

-\tocsubsecnum=23\p@       % subsection 88.8 plus 2.222pt

-\tocsubsubsecnum=27\p@    % subsubsection 88.8.8 plus 1.444pt

-\tocparanum=35\p@         % paragraph 88.8.8.8 plus 1.666pt

-\tocsubparanum=43\p@      % subparagraph 88.8.8.8.8 plus 1.888pt

-\def\calctocindent{%

-\tocsectotal=\tocchpnum

-\advance\tocsectotal by\tocsecnum

-\tocsubsectotal=\tocsectotal

-\advance\tocsubsectotal by\tocsubsecnum

-\tocsubsubsectotal=\tocsubsectotal

-\advance\tocsubsubsectotal by\tocsubsubsecnum

-\tocparatotal=\tocsubsubsectotal

-\advance\tocparatotal by\tocparanum}

-\calctocindent

-

-\def\l@section{\@dottedtocline{1}{\tocchpnum}{\tocsecnum}}

-\def\l@subsection{\@dottedtocline{2}{\tocsectotal}{\tocsubsecnum}}

-\def\l@subsubsection{\@dottedtocline{3}{\tocsubsectotal}{\tocsubsubsecnum}}

-\def\l@paragraph{\@dottedtocline{4}{\tocsubsubsectotal}{\tocparanum}}

-\def\l@subparagraph{\@dottedtocline{5}{\tocparatotal}{\tocsubparanum}}

-

-\def\listoffigures{\@restonecolfalse\if@twocolumn\@restonecoltrue\onecolumn

- \fi\section*{\listfigurename\@mkboth{{\listfigurename}}{{\listfigurename}}}

- \@starttoc{lof}\if@restonecol\twocolumn\fi}

-\def\l@figure{\@dottedtocline{1}{0em}{1.5em}}

-

-\def\listoftables{\@restonecolfalse\if@twocolumn\@restonecoltrue\onecolumn

- \fi\section*{\listtablename\@mkboth{{\listtablename}}{{\listtablename}}}

- \@starttoc{lot}\if@restonecol\twocolumn\fi}

-\let\l@table\l@figure

-

-\renewcommand\listoffigures{%

-    \section*{\listfigurename

-      \@mkboth{\listfigurename}{\listfigurename}}%

-    \@starttoc{lof}%

-    }

-

-\renewcommand\listoftables{%

-    \section*{\listtablename

-      \@mkboth{\listtablename}{\listtablename}}%

-    \@starttoc{lot}%

-    }

-

-\ifx\oribibl\undefined

-\ifx\citeauthoryear\undefined

-\renewenvironment{thebibliography}[1]

-     {\section*{\refname}

-      \def\@biblabel##1{##1.}

-      \small

-      \list{\@biblabel{\@arabic\c@enumiv}}%

-           {\settowidth\labelwidth{\@biblabel{#1}}%

-            \leftmargin\labelwidth

-            \advance\leftmargin\labelsep

-            \if@openbib

-              \advance\leftmargin\bibindent

-              \itemindent -\bibindent

-              \listparindent \itemindent

-              \parsep \z@

-            \fi

-            \usecounter{enumiv}%

-            \let\p@enumiv\@empty

-            \renewcommand\theenumiv{\@arabic\c@enumiv}}%

-      \if@openbib

-        \renewcommand\newblock{\par}%

-      \else

-        \renewcommand\newblock{\hskip .11em \@plus.33em \@minus.07em}%

-      \fi

-      \sloppy\clubpenalty4000\widowpenalty4000%

-      \sfcode`\.=\@m}

-     {\def\@noitemerr

-       {\@latex@warning{Empty `thebibliography' environment}}%

-      \endlist}

-\def\@lbibitem[#1]#2{\item[{[#1]}\hfill]\if@filesw

-     {\let\protect\noexpand\immediate

-     \write\@auxout{\string\bibcite{#2}{#1}}}\fi\ignorespaces}

-\newcount\@tempcntc

-\def\@citex[#1]#2{\if@filesw\immediate\write\@auxout{\string\citation{#2}}\fi

-  \@tempcnta\z@\@tempcntb\m@ne\def\@citea{}\@cite{\@for\@citeb:=#2\do

-    {\@ifundefined

-       {b@\@citeb}{\@citeo\@tempcntb\m@ne\@citea\def\@citea{,}{\bfseries

-        ?}\@warning

-       {Citation `\@citeb' on page \thepage \space undefined}}%

-    {\setbox\z@\hbox{\global\@tempcntc0\csname b@\@citeb\endcsname\relax}%

-     \ifnum\@tempcntc=\z@ \@citeo\@tempcntb\m@ne

-       \@citea\def\@citea{,}\hbox{\csname b@\@citeb\endcsname}%

-     \else

-      \advance\@tempcntb\@ne

-      \ifnum\@tempcntb=\@tempcntc

-      \else\advance\@tempcntb\m@ne\@citeo

-      \@tempcnta\@tempcntc\@tempcntb\@tempcntc\fi\fi}}\@citeo}{#1}}

-\def\@citeo{\ifnum\@tempcnta>\@tempcntb\else

-               \@citea\def\@citea{,\,\hskip\z@skip}%

-               \ifnum\@tempcnta=\@tempcntb\the\@tempcnta\else

-               {\advance\@tempcnta\@ne\ifnum\@tempcnta=\@tempcntb \else

-                \def\@citea{--}\fi

-      \advance\@tempcnta\m@ne\the\@tempcnta\@citea\the\@tempcntb}\fi\fi}

-\else

-\renewenvironment{thebibliography}[1]

-     {\section*{\refname}

-      \small

-      \list{}%

-           {\settowidth\labelwidth{}%

-            \leftmargin\parindent

-            \itemindent=-\parindent

-            \labelsep=\z@

-            \if@openbib

-              \advance\leftmargin\bibindent

-              \itemindent -\bibindent

-              \listparindent \itemindent

-              \parsep \z@

-            \fi

-            \usecounter{enumiv}%

-            \let\p@enumiv\@empty

-            \renewcommand\theenumiv{}}%

-      \if@openbib

-        \renewcommand\newblock{\par}%

-      \else

-        \renewcommand\newblock{\hskip .11em \@plus.33em \@minus.07em}%

-      \fi

-      \sloppy\clubpenalty4000\widowpenalty4000%

-      \sfcode`\.=\@m}

-     {\def\@noitemerr

-       {\@latex@warning{Empty `thebibliography' environment}}%

-      \endlist}

-      \def\@cite#1{#1}%

-      \def\@lbibitem[#1]#2{\item[]\if@filesw

-        {\def\protect##1{\string ##1\space}\immediate

-      \write\@auxout{\string\bibcite{#2}{#1}}}\fi\ignorespaces}

-   \fi

-\else

-\@cons\@openbib@code{\noexpand\small}

-\fi

-

-\def\idxquad{\hskip 10\p@}% space that divides entry from number

-

-\def\@idxitem{\par\hangindent 10\p@}

-

-\def\subitem{\par\setbox0=\hbox{--\enspace}% second order

-                \noindent\hangindent\wd0\box0}% index entry

-

-\def\subsubitem{\par\setbox0=\hbox{--\,--\enspace}% third

-                \noindent\hangindent\wd0\box0}% order index entry

-

-\def\indexspace{\par \vskip 10\p@ plus5\p@ minus3\p@\relax}

-

-\renewenvironment{theindex}

-               {\@mkboth{\indexname}{\indexname}%

-                \thispagestyle{empty}\parindent\z@

-                \parskip\z@ \@plus .3\p@\relax

-                \let\item\par

-                \def\,{\relax\ifmmode\mskip\thinmuskip

-                             \else\hskip0.2em\ignorespaces\fi}%

-                \normalfont\small

-                \begin{multicols}{2}[\@makeschapterhead{\indexname}]%

-                }

-                {\end{multicols}}

-

-\renewcommand\footnoterule{%

-  \kern-3\p@

-  \hrule\@width 2truecm

-  \kern2.6\p@}

-  \newdimen\fnindent

-  \fnindent1em

-\long\def\@makefntext#1{%

-    \parindent \fnindent%

-    \leftskip \fnindent%

-    \noindent

-    \llap{\hb@xt@1em{\hss\@makefnmark\ }}\ignorespaces#1}

-

-\long\def\@makecaption#1#2{%

-  \vskip\abovecaptionskip

-  \sbox\@tempboxa{{\bfseries #1.} #2}%

-  \ifdim \wd\@tempboxa >\hsize

-    {\bfseries #1.} #2\par

-  \else

-    \global \@minipagefalse

-    \hb@xt@\hsize{\hfil\box\@tempboxa\hfil}%

-  \fi

-  \vskip\belowcaptionskip}

-

-\def\fps@figure{htbp}

-\def\fnum@figure{\figurename\thinspace\thefigure}

-\def \@floatboxreset {%

-        \reset@font

-        \small

-        \@setnobreak

-        \@setminipage

-}

-\def\fps@table{htbp}

-\def\fnum@table{\tablename~\thetable}

-\renewenvironment{table}

-               {\setlength\abovecaptionskip{0\p@}%

-                \setlength\belowcaptionskip{10\p@}%

-                \@float{table}}

-               {\end@float}

-\renewenvironment{table*}

-               {\setlength\abovecaptionskip{0\p@}%

-                \setlength\belowcaptionskip{10\p@}%

-                \@dblfloat{table}}

-               {\end@dblfloat}

-

-\long\def\@caption#1[#2]#3{\par\addcontentsline{\csname

-  ext@#1\endcsname}{#1}{\protect\numberline{\csname

-  the#1\endcsname}{\ignorespaces #2}}\begingroup

-    \@parboxrestore

-    \@makecaption{\csname fnum@#1\endcsname}{\ignorespaces #3}\par

-  \endgroup}

-

-% LaTeX does not provide a command to enter the authors institute

-% addresses. The \institute command is defined here.

-

-\newcounter{@inst}

-\newcounter{@auth}

-\newcounter{auco}

-\newdimen\instindent

-\newbox\authrun

-\newtoks\authorrunning

-\newtoks\tocauthor

-\newbox\titrun

-\newtoks\titlerunning

-\newtoks\toctitle

-

-\def\clearheadinfo{\gdef\@author{No Author Given}%

-                   \gdef\@title{No Title Given}%

-                   \gdef\@subtitle{}%

-                   \gdef\@institute{No Institute Given}%

-                   \gdef\@thanks{}%

-                   \global\titlerunning={}\global\authorrunning={}%

-                   \global\toctitle={}\global\tocauthor={}}

-

-\def\institute#1{\gdef\@institute{#1}}

-

-\def\institutename{\par

- \begingroup

- \parskip=\z@

- \parindent=\z@

- \setcounter{@inst}{1}%

- \def\and{\par\stepcounter{@inst}%

- \noindent$^{\the@inst}$\enspace\ignorespaces}%

- \setbox0=\vbox{\def\thanks##1{}\@institute}%

- \ifnum\c@@inst=1\relax

-   \gdef\fnnstart{0}%

- \else

-   \xdef\fnnstart{\c@@inst}%

-   \setcounter{@inst}{1}%

-   \noindent$^{\the@inst}$\enspace

- \fi

- \ignorespaces

- \@institute\par

- \endgroup}

-

-\def\@fnsymbol#1{\ensuremath{\ifcase#1\or\star\or{\star\star}\or

-   {\star\star\star}\or \dagger\or \ddagger\or

-   \mathchar "278\or \mathchar "27B\or \|\or **\or \dagger\dagger

-   \or \ddagger\ddagger \else\@ctrerr\fi}}

-

-\def\inst#1{\unskip$^{#1}$}

-\def\fnmsep{\unskip$^,$}

-\def\email#1{{\tt#1}}

-\AtBeginDocument{\@ifundefined{url}{\def\url#1{#1}}{}%

-\@ifpackageloaded{babel}{%

-\@ifundefined{extrasenglish}{}{\addto\extrasenglish{\switcht@albion}}%

-\@ifundefined{extrasfrenchb}{}{\addto\extrasfrenchb{\switcht@francais}}%

-\@ifundefined{extrasgerman}{}{\addto\extrasgerman{\switcht@deutsch}}%

-}{\switcht@@therlang}%

-}

-\def\homedir{\~{ }}

-

-\def\subtitle#1{\gdef\@subtitle{#1}}

-\clearheadinfo

-%

-\renewcommand\maketitle{\newpage

-  \refstepcounter{chapter}%

-  \stepcounter{section}%

-  \setcounter{section}{0}%

-  \setcounter{subsection}{0}%

-  \setcounter{figure}{0}

-  \setcounter{table}{0}

-  \setcounter{equation}{0}

-  \setcounter{footnote}{0}%

-  \begingroup

-    \parindent=\z@

-    \renewcommand\thefootnote{\@fnsymbol\c@footnote}%

-    \if@twocolumn

-      \ifnum \col@number=\@ne

-        \@maketitle

-      \else

-        \twocolumn[\@maketitle]%

-      \fi

-    \else

-      \newpage

-      \global\@topnum\z@   % Prevents figures from going at top of page.

-      \@maketitle

-    \fi

-    \thispagestyle{empty}\@thanks

-%

-    \def\\{\unskip\ \ignorespaces}\def\inst##1{\unskip{}}%

-    \def\thanks##1{\unskip{}}\def\fnmsep{\unskip}%

-    \instindent=\hsize

-    \advance\instindent by-\headlineindent

-    \if!\the\toctitle!\addcontentsline{toc}{title}{\@title}\else

-       \addcontentsline{toc}{title}{\the\toctitle}\fi

-    \if@runhead

-       \if!\the\titlerunning!\else

-         \edef\@title{\the\titlerunning}%

-       \fi

-       \global\setbox\titrun=\hbox{\small\rm\unboldmath\ignorespaces\@title}%

-       \ifdim\wd\titrun>\instindent

-          \typeout{Title too long for running head. Please supply}%

-          \typeout{a shorter form with \string\titlerunning\space prior to

-                   \string\maketitle}%

-          \global\setbox\titrun=\hbox{\small\rm

-          Title Suppressed Due to Excessive Length}%

-       \fi

-       \xdef\@title{\copy\titrun}%

-    \fi

-%

-    \if!\the\tocauthor!\relax

-      {\def\and{\noexpand\protect\noexpand\and}%

-      \protected@xdef\toc@uthor{\@author}}%

-    \else

-      \def\\{\noexpand\protect\noexpand\newline}%

-      \protected@xdef\scratch{\the\tocauthor}%

-      \protected@xdef\toc@uthor{\scratch}%

-    \fi

-    \addtocontents{toc}{\noexpand\protect\noexpand\authcount{\the\c@auco}}%

-    \addcontentsline{toc}{author}{\toc@uthor}%

-    \if@runhead

-       \if!\the\authorrunning!

-         \value{@inst}=\value{@auth}%

-         \setcounter{@auth}{1}%

-       \else

-         \edef\@author{\the\authorrunning}%

-       \fi

-       \global\setbox\authrun=\hbox{\small\unboldmath\@author\unskip}%

-       \ifdim\wd\authrun>\instindent

-          \typeout{Names of authors too long for running head. Please supply}%

-          \typeout{a shorter form with \string\authorrunning\space prior to

-                   \string\maketitle}%

-          \global\setbox\authrun=\hbox{\small\rm

-          Authors Suppressed Due to Excessive Length}%

-       \fi

-       \xdef\@author{\copy\authrun}%

-       \markboth{\@author}{\@title}%

-     \fi

-  \endgroup

-  \setcounter{footnote}{\fnnstart}%

-  \clearheadinfo}

-%

-\def\@maketitle{\newpage

- \markboth{}{}%

- \def\lastand{\ifnum\value{@inst}=2\relax

-                 \unskip{} \andname\

-              \else

-                 \unskip \lastandname\

-              \fi}%

- \def\and{\stepcounter{@auth}\relax

-          \ifnum\value{@auth}=\value{@inst}%

-             \lastand

-          \else

-             \unskip,

-          \fi}%

- \begin{center}%

- \let\newline\\

- {\Large \bfseries\boldmath

-  \pretolerance=10000

-  \@title \par}\vskip .8cm

-\if!\@subtitle!\else {\large \bfseries\boldmath

-  \vskip -.65cm

-  \pretolerance=10000

-  \@subtitle \par}\vskip .8cm\fi

- \setbox0=\vbox{\setcounter{@auth}{1}\def\and{\stepcounter{@auth}}%

- \def\thanks##1{}\@author}%

- \global\value{@inst}=\value{@auth}%

- \global\value{auco}=\value{@auth}%

- \setcounter{@auth}{1}%

-{\lineskip .5em

-\noindent\ignorespaces

-\@author\vskip.35cm}

- {\small\institutename}

- \end{center}%

- }

-

-% definition of the "\spnewtheorem" command.

-%

-% Usage:

-%

-%     \spnewtheorem{env_nam}{caption}[within]{cap_font}{body_font}

-% or  \spnewtheorem{env_nam}[numbered_like]{caption}{cap_font}{body_font}

-% or  \spnewtheorem*{env_nam}{caption}{cap_font}{body_font}

-%

-% New is "cap_font" and "body_font". It stands for

-% fontdefinition of the caption and the text itself.

-%

-% "\spnewtheorem*" gives a theorem without number.

-%

-% A defined spnewthoerem environment is used as described

-% by Lamport.

-%

-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

-

-\def\@thmcountersep{}

-\def\@thmcounterend{.}

-

-\def\spnewtheorem{\@ifstar{\@sthm}{\@Sthm}}

-

-% definition of \spnewtheorem with number

-

-\def\@spnthm#1#2{%

-  \@ifnextchar[{\@spxnthm{#1}{#2}}{\@spynthm{#1}{#2}}}

-\def\@Sthm#1{\@ifnextchar[{\@spothm{#1}}{\@spnthm{#1}}}

-

-\def\@spxnthm#1#2[#3]#4#5{\expandafter\@ifdefinable\csname #1\endcsname

-   {\@definecounter{#1}\@addtoreset{#1}{#3}%

-   \expandafter\xdef\csname the#1\endcsname{\expandafter\noexpand

-     \csname the#3\endcsname \noexpand\@thmcountersep \@thmcounter{#1}}%

-   \expandafter\xdef\csname #1name\endcsname{#2}%

-   \global\@namedef{#1}{\@spthm{#1}{\csname #1name\endcsname}{#4}{#5}}%

-                              \global\@namedef{end#1}{\@endtheorem}}}

-

-\def\@spynthm#1#2#3#4{\expandafter\@ifdefinable\csname #1\endcsname

-   {\@definecounter{#1}%

-   \expandafter\xdef\csname the#1\endcsname{\@thmcounter{#1}}%

-   \expandafter\xdef\csname #1name\endcsname{#2}%

-   \global\@namedef{#1}{\@spthm{#1}{\csname #1name\endcsname}{#3}{#4}}%

-                               \global\@namedef{end#1}{\@endtheorem}}}

-

-\def\@spothm#1[#2]#3#4#5{%

-  \@ifundefined{c@#2}{\@latexerr{No theorem environment `#2' defined}\@eha}%

-  {\expandafter\@ifdefinable\csname #1\endcsname

-  {\global\@namedef{the#1}{\@nameuse{the#2}}%

-  \expandafter\xdef\csname #1name\endcsname{#3}%

-  \global\@namedef{#1}{\@spthm{#2}{\csname #1name\endcsname}{#4}{#5}}%

-  \global\@namedef{end#1}{\@endtheorem}}}}

-

-\def\@spthm#1#2#3#4{\topsep 7\p@ \@plus2\p@ \@minus4\p@

-\refstepcounter{#1}%

-\@ifnextchar[{\@spythm{#1}{#2}{#3}{#4}}{\@spxthm{#1}{#2}{#3}{#4}}}

-

-\def\@spxthm#1#2#3#4{\@spbegintheorem{#2}{\csname the#1\endcsname}{#3}{#4}%

-                    \ignorespaces}

-

-\def\@spythm#1#2#3#4[#5]{\@spopargbegintheorem{#2}{\csname

-       the#1\endcsname}{#5}{#3}{#4}\ignorespaces}

-

-\def\@spbegintheorem#1#2#3#4{\trivlist

-                 \item[\hskip\labelsep{#3#1\ #2\@thmcounterend}]#4}

-

-\def\@spopargbegintheorem#1#2#3#4#5{\trivlist

-      \item[\hskip\labelsep{#4#1\ #2}]{#4(#3)\@thmcounterend\ }#5}

-

-% definition of \spnewtheorem* without number

-

-\def\@sthm#1#2{\@Ynthm{#1}{#2}}

-

-\def\@Ynthm#1#2#3#4{\expandafter\@ifdefinable\csname #1\endcsname

-   {\global\@namedef{#1}{\@Thm{\csname #1name\endcsname}{#3}{#4}}%

-    \expandafter\xdef\csname #1name\endcsname{#2}%

-    \global\@namedef{end#1}{\@endtheorem}}}

-

-\def\@Thm#1#2#3{\topsep 7\p@ \@plus2\p@ \@minus4\p@

-\@ifnextchar[{\@Ythm{#1}{#2}{#3}}{\@Xthm{#1}{#2}{#3}}}

-

-\def\@Xthm#1#2#3{\@Begintheorem{#1}{#2}{#3}\ignorespaces}

-

-\def\@Ythm#1#2#3[#4]{\@Opargbegintheorem{#1}

-       {#4}{#2}{#3}\ignorespaces}

-

-\def\@Begintheorem#1#2#3{#3\trivlist

-                           \item[\hskip\labelsep{#2#1\@thmcounterend}]}

-

-\def\@Opargbegintheorem#1#2#3#4{#4\trivlist

-      \item[\hskip\labelsep{#3#1}]{#3(#2)\@thmcounterend\ }}

-

-\if@envcntsect

-   \def\@thmcountersep{.}

-   \spnewtheorem{theorem}{Theorem}[section]{\bfseries}{\itshape}

-\else

-   \spnewtheorem{theorem}{Theorem}{\bfseries}{\itshape}

-   \if@envcntreset

-      \@addtoreset{theorem}{section}

-   \else

-      \@addtoreset{theorem}{chapter}

-   \fi

-\fi

-

-%definition of divers theorem environments

-\spnewtheorem*{claim}{Claim}{\itshape}{\rmfamily}

-\spnewtheorem*{proof}{Proof}{\itshape}{\rmfamily}

-\if@envcntsame % alle Umgebungen wie Theorem.

-   \def\spn@wtheorem#1#2#3#4{\@spothm{#1}[theorem]{#2}{#3}{#4}}

-\else % alle Umgebungen mit eigenem Zaehler

-   \if@envcntsect % mit section numeriert

-      \def\spn@wtheorem#1#2#3#4{\@spxnthm{#1}{#2}[section]{#3}{#4}}

-   \else % nicht mit section numeriert

-      \if@envcntreset

-         \def\spn@wtheorem#1#2#3#4{\@spynthm{#1}{#2}{#3}{#4}

-                                   \@addtoreset{#1}{section}}

-      \else

-         \def\spn@wtheorem#1#2#3#4{\@spynthm{#1}{#2}{#3}{#4}

-                                   \@addtoreset{#1}{chapter}}%

-      \fi

-   \fi

-\fi

-\spn@wtheorem{case}{Case}{\itshape}{\rmfamily}

-\spn@wtheorem{conjecture}{Conjecture}{\itshape}{\rmfamily}

-\spn@wtheorem{corollary}{Corollary}{\bfseries}{\itshape}

-\spn@wtheorem{definition}{Definition}{\bfseries}{\itshape}

-\spn@wtheorem{example}{Example}{\itshape}{\rmfamily}

-\spn@wtheorem{exercise}{Exercise}{\itshape}{\rmfamily}

-\spn@wtheorem{lemma}{Lemma}{\bfseries}{\itshape}

-\spn@wtheorem{note}{Note}{\itshape}{\rmfamily}

-\spn@wtheorem{problem}{Problem}{\itshape}{\rmfamily}

-\spn@wtheorem{property}{Property}{\itshape}{\rmfamily}

-\spn@wtheorem{proposition}{Proposition}{\bfseries}{\itshape}

-\spn@wtheorem{question}{Question}{\itshape}{\rmfamily}

-\spn@wtheorem{solution}{Solution}{\itshape}{\rmfamily}

-\spn@wtheorem{remark}{Remark}{\itshape}{\rmfamily}

-

-\def\@takefromreset#1#2{%

-    \def\@tempa{#1}%

-    \let\@tempd\@elt

-    \def\@elt##1{%

-        \def\@tempb{##1}%

-        \ifx\@tempa\@tempb\else

-            \@addtoreset{##1}{#2}%

-        \fi}%

-    \expandafter\expandafter\let\expandafter\@tempc\csname cl@#2\endcsname

-    \expandafter\def\csname cl@#2\endcsname{}%

-    \@tempc

-    \let\@elt\@tempd}

-

-\def\theopargself{\def\@spopargbegintheorem##1##2##3##4##5{\trivlist

-      \item[\hskip\labelsep{##4##1\ ##2}]{##4##3\@thmcounterend\ }##5}

-                  \def\@Opargbegintheorem##1##2##3##4{##4\trivlist

-      \item[\hskip\labelsep{##3##1}]{##3##2\@thmcounterend\ }}

-      }

-

-\renewenvironment{abstract}{%

-      \list{}{\advance\topsep by0.35cm\relax\small

-      \leftmargin=1cm

-      \labelwidth=\z@

-      \listparindent=\z@

-      \itemindent\listparindent

-      \rightmargin\leftmargin}\item[\hskip\labelsep

-                                    \bfseries\abstractname]}

-    {\endlist}

-

-\newdimen\headlineindent             % dimension for space between

-\headlineindent=1.166cm              % number and text of headings.

-

-\def\ps@headings{\let\@mkboth\@gobbletwo

-   \let\@oddfoot\@empty\let\@evenfoot\@empty

-   \def\@evenhead{\normalfont\small\rlap{\thepage}\hspace{\headlineindent}%

-                  \leftmark\hfil}

-   \def\@oddhead{\normalfont\small\hfil\rightmark\hspace{\headlineindent}%

-                 \llap{\thepage}}

-   \def\chaptermark##1{}%

-   \def\sectionmark##1{}%

-   \def\subsectionmark##1{}}

-

-\def\ps@titlepage{\let\@mkboth\@gobbletwo

-   \let\@oddfoot\@empty\let\@evenfoot\@empty

-   \def\@evenhead{\normalfont\small\rlap{\thepage}\hspace{\headlineindent}%

-                  \hfil}

-   \def\@oddhead{\normalfont\small\hfil\hspace{\headlineindent}%

-                 \llap{\thepage}}

-   \def\chaptermark##1{}%

-   \def\sectionmark##1{}%

-   \def\subsectionmark##1{}}

-

-\if@runhead\ps@headings\else

-\ps@empty\fi

-

-\setlength\arraycolsep{1.4\p@}

-\setlength\tabcolsep{1.4\p@}

-

-\endinput

-%end of file llncs.cls

diff --git a/docs/latex/words.eps b/docs/latex/words.eps
deleted file mode 100644
index 6651c4b..0000000
--- a/docs/latex/words.eps
+++ /dev/null
@@ -1,469 +0,0 @@
-%!PS-Adobe-2.0 EPSF-2.0

-%%Title: C:\Users\Shamus\Pictures\words.dia

-%%Creator: Dia v0.97.2

-%%CreationDate: Tue Jul 29 11:17:31 2014

-%%For: Shamus

-%%Orientation: Portrait

-%%Magnification: 1.0000

-%%BoundingBox: 0 0 966 249

-%%BeginSetup

-%%EndSetup

-%%EndComments

-%%BeginProlog

-[ /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef

-/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef

-/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef

-/.notdef /.notdef /space /exclam /quotedbl /numbersign /dollar /percent /ampersand /quoteright

-/parenleft /parenright /asterisk /plus /comma /hyphen /period /slash /zero /one

-/two /three /four /five /six /seven /eight /nine /colon /semicolon

-/less /equal /greater /question /at /A /B /C /D /E

-/F /G /H /I /J /K /L /M /N /O

-/P /Q /R /S /T /U /V /W /X /Y

-/Z /bracketleft /backslash /bracketright /asciicircum /underscore /quoteleft /a /b /c

-/d /e /f /g /h /i /j /k /l /m

-/n /o /p /q /r /s /t /u /v /w

-/x /y /z /braceleft /bar /braceright /asciitilde /.notdef /.notdef /.notdef

-/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef

-/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef

-/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef

-/space /exclamdown /cent /sterling /currency /yen /brokenbar /section /dieresis /copyright

-/ordfeminine /guillemotleft /logicalnot /hyphen /registered /macron /degree /plusminus /twosuperior /threesuperior

-/acute /mu /paragraph /periodcentered /cedilla /onesuperior /ordmasculine /guillemotright /onequarter /onehalf

-/threequarters /questiondown /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla

-/Egrave /Eacute /Ecircumflex /Edieresis /Igrave /Iacute /Icircumflex /Idieresis /Eth /Ntilde

-/Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply /Oslash /Ugrave /Uacute /Ucircumflex

-/Udieresis /Yacute /Thorn /germandbls /agrave /aacute /acircumflex /atilde /adieresis /aring

-/ae /ccedilla /egrave /eacute /ecircumflex /edieresis /igrave /iacute /icircumflex /idieresis

-/eth /ntilde /ograve /oacute /ocircumflex /otilde /odieresis /divide /oslash /ugrave

-/uacute /ucircumflex /udieresis /yacute /thorn /ydieresis] /isolatin1encoding exch def

-/cp {closepath} bind def

-/c {curveto} bind def

-/f {fill} bind def

-/a {arc} bind def

-/ef {eofill} bind def

-/ex {exch} bind def

-/gr {grestore} bind def

-/gs {gsave} bind def

-/sa {save} bind def

-/rs {restore} bind def

-/l {lineto} bind def

-/m {moveto} bind def

-/rm {rmoveto} bind def

-/n {newpath} bind def

-/s {stroke} bind def

-/sh {show} bind def

-/slc {setlinecap} bind def

-/slj {setlinejoin} bind def

-/slw {setlinewidth} bind def

-/srgb {setrgbcolor} bind def

-/rot {rotate} bind def

-/sc {scale} bind def

-/sd {setdash} bind def

-/ff {findfont} bind def

-/sf {setfont} bind def

-/scf {scalefont} bind def

-/sw {stringwidth pop} bind def

-/tr {translate} bind def

-

-/ellipsedict 8 dict def

-ellipsedict /mtrx matrix put

-/ellipse

-{ ellipsedict begin

-   /endangle exch def

-   /startangle exch def

-   /yrad exch def

-   /xrad exch def

-   /y exch def

-   /x exch def   /savematrix mtrx currentmatrix def

-   x y tr xrad yrad sc

-   0 0 1 startangle endangle arc

-   savematrix setmatrix

-   end

-} def

-

-/mergeprocs {

-dup length

-3 -1 roll

-dup

-length

-dup

-5 1 roll

-3 -1 roll

-add

-array cvx

-dup

-3 -1 roll

-0 exch

-putinterval

-dup

-4 2 roll

-putinterval

-} bind def

-/Times-Roman-latin1

-    /Times-Roman findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Times-Italic-latin1

-    /Times-Italic findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Times-Bold-latin1

-    /Times-Bold findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Times-BoldItalic-latin1

-    /Times-BoldItalic findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/AvantGarde-Gothic-latin1

-    /AvantGarde-Gothic findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/AvantGarde-BookOblique-latin1

-    /AvantGarde-BookOblique findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/AvantGarde-Demi-latin1

-    /AvantGarde-Demi findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/AvantGarde-DemiOblique-latin1

-    /AvantGarde-DemiOblique findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Bookman-Light-latin1

-    /Bookman-Light findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Bookman-LightItalic-latin1

-    /Bookman-LightItalic findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Bookman-Demi-latin1

-    /Bookman-Demi findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Bookman-DemiItalic-latin1

-    /Bookman-DemiItalic findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Courier-latin1

-    /Courier findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Courier-Oblique-latin1

-    /Courier-Oblique findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Courier-Bold-latin1

-    /Courier-Bold findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Courier-BoldOblique-latin1

-    /Courier-BoldOblique findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Helvetica-latin1

-    /Helvetica findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Helvetica-Oblique-latin1

-    /Helvetica-Oblique findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Helvetica-Bold-latin1

-    /Helvetica-Bold findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Helvetica-BoldOblique-latin1

-    /Helvetica-BoldOblique findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Helvetica-Narrow-latin1

-    /Helvetica-Narrow findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Helvetica-Narrow-Oblique-latin1

-    /Helvetica-Narrow-Oblique findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Helvetica-Narrow-Bold-latin1

-    /Helvetica-Narrow-Bold findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Helvetica-Narrow-BoldOblique-latin1

-    /Helvetica-Narrow-BoldOblique findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/NewCenturySchlbk-Roman-latin1

-    /NewCenturySchlbk-Roman findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/NewCenturySchlbk-Italic-latin1

-    /NewCenturySchlbk-Italic findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/NewCenturySchlbk-Bold-latin1

-    /NewCenturySchlbk-Bold findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/NewCenturySchlbk-BoldItalic-latin1

-    /NewCenturySchlbk-BoldItalic findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Palatino-Roman-latin1

-    /Palatino-Roman findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Palatino-Italic-latin1

-    /Palatino-Italic findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Palatino-Bold-latin1

-    /Palatino-Bold findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Palatino-BoldItalic-latin1

-    /Palatino-BoldItalic findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/Symbol-latin1

-    /Symbol findfont

-definefont pop

-/ZapfChancery-MediumItalic-latin1

-    /ZapfChancery-MediumItalic findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-/ZapfDingbats-latin1

-    /ZapfDingbats findfont

-    dup length dict begin

-	{1 index /FID ne {def} {pop pop} ifelse} forall

-	/Encoding isolatin1encoding def

-    currentdict end

-definefont pop

-28.346000 -28.346000 scale

--4.000000 2.867500 translate

-%%EndProlog

-

-

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slj

-0.000000 0.000000 0.000000 srgb

-n 5.000000 -10.000000 m 5.000000 -7.000000 l 14.000000 -7.000000 l 14.000000 -10.000000 l cp s

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slc

-n 8.000000 -10.000000 m 8.000000 -7.000000 l s

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slj

-n 15.000000 -10.000000 m 15.000000 -7.000000 l 24.000000 -7.000000 l 24.000000 -10.000000 l cp s

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slc

-n 16.000000 -10.000000 m 16.000000 -7.000000 l s

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slj

-n 29.000000 -10.000000 m 29.000000 -7.000000 l 38.000000 -7.000000 l 38.000000 -10.000000 l cp s

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slc

-n 30.000000 -10.000000 m 30.000000 -7.000000 l s

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slc

-n 11.000000 -10.000000 m 11.000000 -7.000000 l s

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slc

-n 6.000000 -10.000000 m 6.000000 -7.000000 l s

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slc

-n 18.000000 -10.000000 m 18.000000 -7.000000 l s

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slc

-n 32.000000 -10.000000 m 32.000000 -7.000000 l s

-/Helvetica-latin1 ff 0.560000 scf sf

-(Sign bit) 4.000000 -3.120000 m

- gs 1 -1 sc sh gr

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slc

-n 5.000000 -4.000000 m 5.000000 -5.513197 l s

-[] 0 sd

-0 slj

-0 slc

-n 5.000000 -5.888197 m 5.250000 -5.388197 l 5.000000 -5.513197 l 4.750000 -5.388197 l ef

-n 5.000000 -5.888197 m 5.250000 -5.388197 l 5.000000 -5.513197 l 4.750000 -5.388197 l cp s

-/Helvetica-latin1 ff 0.560000 scf sf

-(Field Excess) 8.000000 -3.120000 m

- gs 1 -1 sc sh gr

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slc

-n 9.000000 -4.000000 m 9.000000 -5.513197 l s

-[] 0 sd

-0 slj

-0 slc

-n 9.000000 -5.888197 m 9.250000 -5.388197 l 9.000000 -5.513197 l 8.750000 -5.388197 l ef

-n 9.000000 -5.888197 m 9.250000 -5.388197 l 9.000000 -5.513197 l 8.750000 -5.388197 l cp s

-/Helvetica-latin1 ff 0.560000 scf sf

-(Word Excess) 15.000000 -3.120000 m

- gs 1 -1 sc sh gr

-/Helvetica-latin1 ff 0.560000 scf sf

-(Word Excess) 29.000000 -3.120000 m

- gs 1 -1 sc sh gr

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slc

-n 17.000000 -4.000000 m 17.000000 -5.513197 l s

-[] 0 sd

-0 slj

-0 slc

-n 17.000000 -5.888197 m 17.250000 -5.388197 l 17.000000 -5.513197 l 16.750000 -5.388197 l ef

-n 17.000000 -5.888197 m 17.250000 -5.388197 l 17.000000 -5.513197 l 16.750000 -5.388197 l cp s

-0.100000 slw

-[] 0 sd

-[] 0 sd

-0 slc

-n 31.000000 -4.000000 m 31.000000 -5.513197 l s

-[] 0 sd

-0 slj

-0 slc

-n 31.000000 -5.888197 m 31.250000 -5.388197 l 31.000000 -5.513197 l 30.750000 -5.388197 l ef

-n 31.000000 -5.888197 m 31.250000 -5.388197 l 31.000000 -5.513197 l 30.750000 -5.388197 l cp s

-/Helvetica-latin1 ff 0.560000 scf sf

-(Base Bits) 20.000000 -8.120000 m

- gs 1 -1 sc sh gr

-/Helvetica-latin1 ff 0.560000 scf sf

-(Base Bits) 34.000000 -8.120000 m

- gs 1 -1 sc sh gr

-/Helvetica-latin1 ff 0.560000 scf sf

-(Top Bits) 11.000000 -8.120000 m

- gs 1 -1 sc sh gr

-/Helvetica-latin1 ff 0.560000 scf sf

-(..........) 26.000000 -7.120000 m

- gs 1 -1 sc sh gr

-/Helvetica-latin1 ff 0.560000 scf sf

-(Most Significant Word) 7.000000 -11.120000 m

- gs 1 -1 sc sh gr

-/Helvetica-latin1 ff 0.560000 scf sf

-(Least Significant Word) 30.000000 -11.120000 m

- gs 1 -1 sc sh gr

-showpage

diff --git a/ecgen.cpp b/ecgen.cpp
deleted file mode 100755
index 7a41452..0000000
--- a/ecgen.cpp
+++ /dev/null
@@ -1,340 +0,0 @@
-/*
-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.
-*/
-
-/* BNGEN - Helper MIRACL program to generate constants for EC curves
-
-(MINGW build)
-
-g++ -O3 ecgen.cpp big.cpp miracl.a -o ecgen.exe
-
-
-*/
-
-#include <iostream>
-#include "big.h"
-#include "zzn2.h"
-#include "ecn2.h"
-
-using namespace std;
-
-Miracl precision(20,0);
-
-Big output(int d,int w,Big t,Big m)
-{
-	Big last,y=t;
-
-	if (d!=2) cout << "{";
-	else cout << "[";
-	for (int i=0;i<w;i++)
-	{
-		last=y%m;
-		cout << "0x" << last;
-		y/=m;
-		if ((y==0 && d==0) || i==w-1) break;
-		if (d==3) cout << "L,";
-		else cout << ",";
-	}
-	if (d!=2)
-	{
-		if (d==3) cout << "L}";
-		else cout << "}";
-	}
-	else cout << "]";
-	return last;
-}
-
-#define NOT_SPECIAL 0
-#define PSEUDO_MERSENNE 1
-#define MONTGOMERY_FRIENDLY 3
-
-#define WEIERSTRASS 0
-#define EDWARDS 1
-#define MONTGOMERY 2
-
-/*** Set Modulus and Curve Type Here ***/
-
-#define MODTYPE  PSEUDO_MERSENNE
-#define CURVETYPE EDWARDS
-
-int main()
-{
-	miracl *mip=&precision;
-	Big p,q,R,B;
-	Big m,x,y,w,t,c,n,r,a,b,gx,gy,D,C,MC;
-	int i,A;
-	int CHUNK[4]={16,32,64,32};
-	int WORDS[4]={20,9,5,11};//{20,9,5};
-	int BITS[4]={13,29,56,24};//{13,29,56};
-
-// ***  Set prime Modulus, curve order, B parameter of curve and generator point
-/*
-// This is for ED25519
-	p=pow((Big)2,255)-19;  // or whatever
-	r=pow((Big)2,252)+"27742317777372353535851937790883648493";  // or whatever
-	B=p-moddiv((Big)121665,(Big)121666,p);  // or whatever
-	gy=moddiv((Big)4,(Big)5,p);   // Set generator point (x,y)
-	gx=moddiv((gy*gy-1)%p,(B*gy*gy+1)%p,p);
-	gx=p-sqrt(gx,p);
-	mip->IOBASE=16;
-*/
-
-// This is for NIST256 curve
-//	mip->IOBASE=10;
-//	p="115792089210356248762697446949407573530086143415290314195533631308867097853951";
-//	r="115792089210356248762697446949407573529996955224135760342422259061068512044369";
-//	mip->IOBASE=16;
-//	B="5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b";
-//	gx="6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296";
-//	gy="4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5";
-/*
-
-// This is for w-254-mont Curve
-
-	p=pow((Big)2,240)*(pow((Big)2,14)-127)-1;
-	mip->IOBASE=16;
-	r=p+1-"147E7415F25C8A3F905BE63B507207C1";
-	B=p-12146;
-	gx="2";
-	gy="140E3FD33B2E56014AE15A75BD778AEBDFB738E3F8511931AD65DF37F90D4EBC";
-
-// ed-254-mont Curve
-	p=pow((Big)2,240)*(pow((Big)2,14)-127)-1;
-	mip->IOBASE=16;
-	r=(p+1-"51AB3E4DD0A7413C5430B004EE459CE4")/4;
-	B=13947;
-	gx="1";
-	gy="19F0E690D6A4C335951D00D502363F4E36329A840E3212187C52D0FDAF2701E5";
-
-// w-255-mers Curve
-	p=pow((Big)2,255)-765;
-	mip->IOBASE=16;
-	r=p+1-"79B5C7D7C52D4C2054705367C3A6B219";
-	B=p-20925;
-	gx="1";
-	gy="6F7A6AC0EDBA7833921EBFF9B2FF7D177DB6C78CDDFDA60D1733FF6769CB44BA";
-
-// ed-255-mers Curve
-	p=pow((Big)2,255)-765;
-	mip->IOBASE=16;
-	r=(p+1-"8C3961E84965F3454ED8B84BEF244F30")/4;
-	B=60055;
-	gx="4";
-	gy="26CB78534A7BB545EC254CDD8E0C47E552914B8AED445A45BA2A255BD08736A0";
-
-// Brainpool 256-bit curve
-	mip->IOBASE=16;
-	p="A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377";
-	r="A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7";
-	B="662C61C430D84EA4FE66A7733D0B76B7BF93EBC4AF2F49256AE58101FEE92B04";
-	gx="A3E8EB3CC1CFE7B7732213B23A656149AFA142C47AAFBC2B79A191562E1305F4";
-	gy="2D996C823439C56D7F7B22E14644417E69BCB6DE39D027001DABE8F35B25C9BE";
-
-// ANSSI (French) curve
-	mip->IOBASE=16;
-	p="f1fd178c0b3ad58f10126de8ce42435b3961adbcabc8ca6de8fcf353d86e9c03";
-	r="F1FD178C0B3AD58F10126DE8CE42435B53DC67E140D2BF941FFDD459C6D655E1";
-	B="EE353FCA5428A9300D4ABA754A44C00FDFEC0C9AE4B1A1803075ED967B7BB73F";
-	gx="B6B3D4C356C139EB31183D4749D423958C27D2DCAF98B70164C97A2DD98F5CFF";
-	gy="6142E0F7C8B204911F9271F0F3ECEF8C2701C307E8E4C9E183115A1554062CFB";
-*/
-	p=pow((Big)2,255)-765;
-	mip->IOBASE=16;
-	r=(p+1-"8C3961E84965F3454ED8B84BEF244F30")/4;
-	B=60055;
-	gx="4";
-	gy="26CB78534A7BB545EC254CDD8E0C47E552914B8AED445A45BA2A255BD08736A0";
-
-
-#if MODTYPE==PSEUDO_MERSENNE
-	C=765;              // p=2^n - C, where C is very small
-#endif
-#if CURVETYPE==WEIERSTRASS
-	A=-3;   // or 0
-#endif
-#if CURVETYPE==EDWARDS
-	A=-1;  // or +1
-#endif
-#if CURVETYPE==MONTGOMERY
-	A=-55790;
-#endif
-
-	cout << "/* AMCL - ROM  C file for EC curves */" << endl << endl;
-
-	cout << "#define MBITS " << bits(p) << endl;
-	cout << "#define MOD8 " << p%8 << endl;
-	cout << endl;
-	cout << "const int CURVE_A=" << A << ";" << endl;
-	for (i=0;i<3;i++)
-	{
-		cout << "#if CHUNK==" << CHUNK[i] << endl << endl;
-		m=pow((Big)2,BITS[i]);
-
-		cout << "const BIG Modulus="; MC=output(0,WORDS[i],p,m); cout << ";" << endl;
-
-#if MODTYPE==NOT_SPECIAL
-		cout << "const chunk MConst=0x" << inverse(m-p%m,m) << ";" << endl;
-#endif
-#if MODTYPE==MONTGOMERY_FRIENDLY
-		cout << "const chunk MConst=0x" << MC+1 << ";" << endl;
-#endif
-#if MODTYPE==PSEUDO_MERSENNE
-		cout << "const chunk MConst=0x" << C << ";" << endl;
-#endif
-
-#if MODTYPE!=PSEUDO_MERSENNE
-		R=pow((Big)2,WORDS[i]*BITS[i]);
-//		cout << "const BIG Monty=";output(0,WORDS[i],inverse(R,p),m); cout << ";" << endl;
-#endif
-
-		cout << "const BIG CURVE_Order="; output(0,WORDS[i],r,m); cout << ";" << endl;
-		cout << "const BIG CURVE_B="; output(0,WORDS[i],B,m); cout << ";" <<  endl;
-
-		cout << "const BIG CURVE_Gx="; output(0,WORDS[i],gx,m); cout << ";" << endl;
-		cout << "const BIG CURVE_Gy="; output(0,WORDS[i],gy,m); cout << ";" << endl;
-
-		cout << "#endif" << endl << endl;
-
-	}
-
-	cout << endl;
-	cout << "Cut here -----------------------------------------------------------" << endl;
-	cout << "/* AMCL - ROM  Java file for 32-bit VM for EC curve */" << endl << endl;
-
-	cout << "public static final int MODBITS= " << bits(p) << ";" << endl;
-	cout << "public static final int MOD8= " << p%8 << ";" << endl;
-	cout << endl;
-	cout << "public static final int MODTYPE= " << MODTYPE << ";" << endl;
-	m=pow((Big)2,BITS[1]);
-
-
-	cout << "public static final int[] Modulus= "; MC=output(1,WORDS[1],p,m); cout << ";" << endl;
-	R=pow((Big)2,WORDS[1]*BITS[1]);
-
-
-#if MODTYPE==NOT_SPECIAL
-	cout << "public static final int MConst=0x" << inverse(m-p%m,m) << ";" <<  endl;
-#endif
-#if MODTYPE==MONTGOMERY_FRIENDLY
-	cout << "public static final int MConst=0x" << MC+1 << ";" << endl;
-#endif
-#if MODTYPE==PSEUDO_MERSENNE
-	cout << "public static final int MConst=0x" << C << ";" << endl;
-#endif
-
-#if MODTYPE!=PSEUDO_MERSENNE
-//	cout << "public static final int[] Monty=";output(1,WORDS[1],inverse(R,p),m); cout << ";" << endl;
-#endif
-
-	cout << endl;
-	cout << "public static final int CURVETYPE= " << CURVETYPE << ";" << endl;
-
-
-	cout << "public static final int CURVE_A = " << A << ";" << endl;
-	cout << "public static final int[] CURVE_B = "; output(1,WORDS[1],B,m); cout << ";" << endl;
-
-	cout << "public static final int[] CURVE_Order="; output(1,WORDS[1],r,m); cout << ";" << endl;
-
-	cout << "public static final int[] CURVE_Gx ="; output(1,WORDS[1],gx,m); cout << ";" << endl;
-	cout << "public static final int[] CURVE_Gy ="; output(1,WORDS[1],gy,m); cout << ";" << endl;
-
-
-
-	cout << endl;
-	cout << "Cut here -----------------------------------------------------------" << endl;
-	cout << "/* AMCL - ROM  Java file for 64-bit VM for EC curve */" << endl << endl;
-
-	cout << "public static final int MODBITS= " << bits(p) << ";" << endl;
-	cout << "public static final int MOD8= " << p%8 << ";" << endl;
-	cout << endl;
-	cout << "public static final int MODTYPE= " << MODTYPE << ";" << endl;
-	m=pow((Big)2,BITS[2]);
-
-
-	cout << "public static final long[] Modulus= "; MC=output(3,WORDS[2],p,m); cout << ";" << endl;
-	R=pow((Big)2,WORDS[2]*BITS[2]);
-
-
-#if MODTYPE==NOT_SPECIAL
-	cout << "public static final long MConst=0x" << inverse(m-p%m,m) << "L;" <<  endl;
-#endif
-#if MODTYPE==MONTGOMERY_FRIENDLY
-	cout << "public static final long MConst=0x" << MC+1 << "L;" << endl;
-#endif
-#if MODTYPE==PSEUDO_MERSENNE
-	cout << "public static final long MConst=0x" << C << "L;" << endl;
-#endif
-
-#if MODTYPE!=PSEUDO_MERSENNE
-//	cout << "public static final long[] Monty=";output(3,WORDS[2],inverse(R,p),m); cout << ";" << endl;
-#endif
-
-	cout << endl;
-	cout << "public static final int CURVETYPE= " << CURVETYPE << ";" << endl;
-
-
-	cout << "public static final int CURVE_A = " << A << ";" << endl;
-	cout << "public static final long[] CURVE_B = "; output(3,WORDS[2],B,m); cout << ";" << endl;
-
-	cout << "public static final long[] CURVE_Order="; output(3,WORDS[2],r,m); cout << ";" << endl;
-
-	cout << "public static final long[] CURVE_Gx ="; output(3,WORDS[2],gx,m); cout << ";" << endl;
-	cout << "public static final long[] CURVE_Gy ="; output(3,WORDS[2],gy,m); cout << ";" << endl;
-
-
-
-
-	cout << endl;
-	cout << "Cut here -----------------------------------------------------------" << endl;
-	cout << "/* AMCL - ROM  Javascript file for EC curve - Weierstrass Only */" << endl << endl;
-
-	cout << "MODBITS: " << bits(p) << "," << endl;
-	cout << "MOD8: " << p%8 << "," << endl;
-	cout << endl;
-	cout << "MODTYPE:" << MODTYPE << "," << endl;
-	m=pow((Big)2,BITS[3]);
-
-	cout << "Modulus: "; MC=output(2,WORDS[3],p,m); cout << "," << endl;
-
-#if MODTYPE==NOT_SPECIAL
-	cout << "MConst:0x" << inverse(m-p%m,m) << "," <<  endl;
-#endif
-#if MODTYPE==MONTGOMERY_FRIENDLY
-	cout << "MConst:0x" << MC+1 << "," << endl;
-#endif
-#if MODTYPE==PSEUDO_MERSENNE
-	cout << "MConst:0x" << C << "," << endl;
-#endif
-
-	R=pow((Big)2,WORDS[3]*BITS[3]);
-#if MODTYPE!=PSEUDO_MERSENNE
-//	cout << "Monty:";output(2,WORDS[3],inverse(R,p),m); cout << "," << endl;
-#endif
-
-	cout << endl;
-	cout << "CURVETYPE:" << CURVETYPE << "," << endl;
-
-	cout << "CURVE_A : " << A << "," << endl;
-	cout << "CURVE_B : "; output(2,WORDS[3],B,m); cout << "," << endl;
-
-	cout << "CURVE_Order:"; output(2,WORDS[3],r,m); cout << "," << endl;
-
-	cout << "CURVE_Gx :"; output(2,WORDS[3],gx,m); cout << "," << endl;
-	cout << "CURVE_Gy :"; output(2,WORDS[3],gy,m); cout << "," << endl;
-
-}
diff --git a/go/amcl-cgo/README.txt b/go/amcl-cgo/README.txt
deleted file mode 100644
index 79b1cee..0000000
--- a/go/amcl-cgo/README.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-When the library is built with;
-
--D USE_ANONYMOUS=on 
-
-then set
-
-const USE_ANONYMOUS = true
-
-in crypto_test.go
diff --git a/go/amcl-cgo/crypto.go b/go/amcl-cgo/crypto.go
deleted file mode 100644
index db5a6b1..0000000
--- a/go/amcl-cgo/crypto.go
+++ /dev/null
@@ -1,828 +0,0 @@
-/*
-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.
-*/
-
-package amcl
-
-/*
-#cgo CFLAGS:  -std=c99 -O3 -I/opt/amcl/include
-#cgo LDFLAGS: -L/opt/amcl/lib -lmpin  -lamcl -lm
-#include <stdio.h>
-#include <stdlib.h>
-#include "amcl.h"
-#include "mpin.h"
-#include "utils.h"
-*/
-import "C"
-import (
-	"encoding/hex"
-	"fmt"
-	"unsafe"
-
-	amcl "git.apache.org/incubator-milagro-crypto.git/go/amcl-go"
-)
-
-const EAS int = int(C.PAS)
-const EGS int = int(C.PGS)
-const EFS int = int(C.PFS)
-const HASH_BYTES int = int(C.HASH_BYTES)
-const IVS int = 12
-const G1S = 2*EFS + 1
-const G2S = 4 * EFS
-const GTS = 12 * EFS
-
-var RNG C.csprng
-
-func OCT_free(valOctet *C.octet) {
-	C.free(unsafe.Pointer(valOctet.val))
-}
-
-func GetOctetZero(lenStr int) C.octet {
-	valBytes := make([]byte, lenStr)
-	val := string(valBytes)
-	valCS := C.CString(val)
-	lenCS := C.int(lenStr)
-	octetVal := C.octet{lenCS, lenCS, valCS}
-	return octetVal
-}
-
-func GetOctet(valStr string) C.octet {
-	valCS := C.CString(valStr)
-	lenCS := C.int(len(valStr))
-	octetVal := C.octet{lenCS, lenCS, valCS}
-	return octetVal
-}
-
-func GetOctetHex(valHex string) C.octet {
-	valBytes, err := hex.DecodeString(valHex)
-	if err != nil {
-		octetVal := GetOctetZero(0)
-		return octetVal
-	}
-	valStr := string(valBytes)
-	octetVal := GetOctet(valStr)
-	return octetVal
-}
-
-func OCT_len(valOctet *C.octet) int {
-	return int(valOctet.len)
-}
-
-// Convert an octet to a string
-func OCT_toStr(valOct *C.octet) string {
-	dstLen := OCT_len(valOct)
-	dstBytes := make([]byte, dstLen)
-	dstStr := string(dstBytes)
-	dst := C.CString(dstStr)
-	C.OCT_toStr(valOct, dst)
-	dstStr = C.GoStringN(dst, valOct.len)
-	C.free(unsafe.Pointer(dst))
-	return dstStr
-}
-
-// Convert an octet to bytes
-func OCT_toBytes(valOct *C.octet) []byte {
-	dstLen := OCT_len(valOct)
-	dstBytes := make([]byte, dstLen)
-	dstStr := string(dstBytes)
-	dst := C.CString(dstStr)
-	C.OCT_toStr(valOct, dst)
-	dstStr = C.GoStringN(dst, valOct.len)
-	C.free(unsafe.Pointer(dst))
-	dstBytes = []byte(dstStr)
-	return dstBytes
-}
-
-// Convert an octet to a hex string
-func OCT_toHex(valOctet *C.octet) string {
-	dstLen := OCT_len(valOctet)
-	dstBytes := make([]byte, hex.EncodedLen(dstLen))
-	dstStr := string(dstBytes)
-	dst := C.CString(dstStr)
-	C.OCT_toHex(valOctet, dst)
-	dstStr = C.GoString(dst)
-	C.free(unsafe.Pointer(dst))
-	return dstStr
-}
-
-/* return time in slots since epoch */
-func MPIN_today() int {
-	date := C.MPIN_today()
-	return int(date)
-}
-
-/* return time since epoch */
-func MPIN_GET_TIME() int {
-	timeValue := C.MPIN_GET_TIME()
-	return int(timeValue)
-}
-
-func MPIN_CREATE_CSPRNG(RNG *C.csprng, SEED []byte) {
-	// Form Octet
-	SEEDStr := string(SEED)
-	SEEDOct := GetOctet(SEEDStr)
-	defer OCT_free(&SEEDOct)
-	C.MPIN_CREATE_CSPRNG(RNG, &SEEDOct)
-}
-
-func MPIN_HASH_ID(ID []byte) (HASHID []byte) {
-	// Form Octets
-	IDStr := string(ID)
-	IDOct := GetOctet(IDStr)
-	defer OCT_free(&IDOct)
-	HASHIDOct := GetOctetZero(HASH_BYTES)
-	defer OCT_free(&HASHIDOct)
-
-	// Hash MPIN_ID
-	C.MPIN_HASH_ID(&IDOct, &HASHIDOct)
-
-	// Convert octet to bytes
-	HASHID = OCT_toBytes(&HASHIDOct)
-
-	return
-}
-
-/* create random secret S. Use GO RNG */
-func MPIN_RANDOM_GENERATE_WRAP(RNG *amcl.RAND) (int, []byte) {
-	var S [EGS]byte
-	errorCode := amcl.MPIN_RANDOM_GENERATE(RNG, S[:])
-	return errorCode, S[:]
-}
-
-/* create random secret S. Use C RNG */
-func MPIN_RANDOM_GENERATE_C(RNG *C.csprng) (errorCode int, S []byte) {
-	// Form Octet
-	SOct := GetOctetZero(EGS)
-	defer OCT_free(&SOct)
-
-	rtn := C.MPIN_RANDOM_GENERATE(RNG, &SOct)
-	errorCode = int(rtn)
-
-	// Convert octet to bytes
-	S = OCT_toBytes(&SOct)
-
-	return
-}
-
-/* Extract Server Secret SS=S*Q where Q is fixed generator in G2 and S is master secret */
-func MPIN_GET_SERVER_SECRET_WRAP(S []byte) (errorCode int, SS []byte) {
-	// Form Octets
-	SStr := string(S)
-	SOct := GetOctet(SStr)
-	defer OCT_free(&SOct)
-	SSOct := GetOctetZero(G2S)
-	defer OCT_free(&SSOct)
-
-	rtn := C.MPIN_GET_SERVER_SECRET(&SOct, &SSOct)
-	errorCode = int(rtn)
-
-	// Convert octet to bytes
-	SS = OCT_toBytes(&SSOct)
-
-	return
-}
-
-/* R=R1+R2 in group G1 */
-func MPIN_RECOMBINE_G1_WRAP(R1 []byte, R2 []byte) (errorCode int, R []byte) {
-	// Form Octets
-	R1Str := string(R1)
-	R1Oct := GetOctet(R1Str)
-	defer OCT_free(&R1Oct)
-	R2Str := string(R2)
-	R2Oct := GetOctet(R2Str)
-	defer OCT_free(&R2Oct)
-	ROct := GetOctetZero(G1S)
-	defer OCT_free(&ROct)
-
-	rtn := C.MPIN_RECOMBINE_G1(&R1Oct, &R2Oct, &ROct)
-	errorCode = int(rtn)
-
-	// Convert octet to bytes
-	R = OCT_toBytes(&ROct)
-
-	return
-}
-
-/* W=W1+W2 in group G2 */
-func MPIN_RECOMBINE_G2_WRAP(W1 []byte, W2 []byte) (errorCode int, W []byte) {
-	// Form Octets
-	W1Str := string(W1)
-	W1Oct := GetOctet(W1Str)
-	defer OCT_free(&W1Oct)
-	W2Str := string(W2)
-	W2Oct := GetOctet(W2Str)
-	defer OCT_free(&W2Oct)
-	WOct := GetOctetZero(G2S)
-	defer OCT_free(&WOct)
-
-	rtn := C.MPIN_RECOMBINE_G2(&W1Oct, &W2Oct, &WOct)
-	errorCode = int(rtn)
-
-	// Convert octet to bytes
-	W = OCT_toBytes(&WOct)
-
-	return
-}
-
-/* Client secret CS=S*H(ID) where ID is client ID and S is master secret */
-/* CID is hashed externally */
-func MPIN_GET_CLIENT_SECRET_WRAP(S []byte, ID []byte) (errorCode int, CS []byte) {
-	// Form Octets
-	SStr := string(S)
-	SOct := GetOctet(SStr)
-	defer OCT_free(&SOct)
-	IDStr := string(ID)
-	IDOct := GetOctet(IDStr)
-	defer OCT_free(&IDOct)
-	CSOct := GetOctetZero(G1S)
-	defer OCT_free(&CSOct)
-
-	rtn := C.MPIN_GET_CLIENT_SECRET(&SOct, &IDOct, &CSOct)
-	errorCode = int(rtn)
-
-	// Convert octet to bytes
-	CS = OCT_toBytes(&CSOct)
-
-	return
-}
-
-/* Time Permit TP=S*(date|H(ID)) where S is master secret */
-func MPIN_GET_CLIENT_PERMIT_WRAP(date int, S, ID []byte) (errorCode int, TP []byte) {
-	// Form Octets
-	SStr := string(S)
-	SOct := GetOctet(SStr)
-	defer OCT_free(&SOct)
-	IDStr := string(ID)
-	IDOct := GetOctet(IDStr)
-	defer OCT_free(&IDOct)
-	TPOct := GetOctetZero(G1S)
-	defer OCT_free(&TPOct)
-
-	rtn := C.MPIN_GET_CLIENT_PERMIT(C.int(date), &SOct, &IDOct, &TPOct)
-	errorCode = int(rtn)
-
-	// Convert octet to bytes
-	TP = OCT_toBytes(&TPOct)
-
-	return
-}
-
-/* Extract PIN from CS for identity CID to form TOKEN */
-func MPIN_EXTRACT_PIN_WRAP(ID []byte, PIN int, CS []byte) (errorCode int, TOKEN []byte) {
-	// Form Octets
-	IDStr := string(ID)
-	IDOct := GetOctet(IDStr)
-	defer OCT_free(&IDOct)
-	CSStr := string(CS)
-	CSOct := GetOctet(CSStr)
-	defer OCT_free(&CSOct)
-
-	rtn := C.MPIN_EXTRACT_PIN(&IDOct, C.int(PIN), &CSOct)
-	errorCode = int(rtn)
-
-	// Convert octet to bytes
-	TOKEN = OCT_toBytes(&CSOct)
-
-	return
-}
-
-/* One pass MPIN Client. Using GO RNG */
-func MPIN_CLIENT_WRAP(date, TimeValue, PIN int, RNG *amcl.RAND, ID, X, TOKEN, TP, MESSAGE []byte) (errorCode int, XOut, Y, SEC, U, UT []byte) {
-	amcl.MPIN_RANDOM_GENERATE(RNG, X[:])
-	errorCode, XOut, Y, SEC, U, UT = MPIN_CLIENT_C(date, ID[:], nil, X[:], PIN, TOKEN[:], TP[:], MESSAGE[:], TimeValue)
-	return
-}
-
-/* One pass MPIN Client. Using C RNG */
-func MPIN_CLIENT_C(date int, ID []byte, RNG *C.csprng, X []byte, PIN int, TOKEN []byte, TP []byte, MESSAGE []byte, TimeValue int) (errorCode int, XOut, Y, SEC, U, UT []byte) {
-	// Form Octets
-	IDStr := string(ID)
-	IDOct := GetOctet(IDStr)
-	defer OCT_free(&IDOct)
-	XStr := string(X)
-	XOct := GetOctet(XStr)
-	defer OCT_free(&XOct)
-	TOKENStr := string(TOKEN)
-	TOKENOct := GetOctet(TOKENStr)
-	defer OCT_free(&TOKENOct)
-	TPStr := string(TP)
-	TPOct := GetOctet(TPStr)
-	defer OCT_free(&TPOct)
-	MESSAGEStr := string(MESSAGE)
-	MESSAGEOct := GetOctet(MESSAGEStr)
-	defer OCT_free(&MESSAGEOct)
-
-	SECOct := GetOctetZero(G1S)
-	defer OCT_free(&SECOct)
-	UOct := GetOctetZero(G1S)
-	defer OCT_free(&UOct)
-	UTOct := GetOctetZero(G1S)
-	defer OCT_free(&UTOct)
-	YOct := GetOctetZero(EGS)
-	defer OCT_free(&YOct)
-
-	rtn := C.MPIN_CLIENT(C.int(date), &IDOct, RNG, &XOct, C.int(PIN), &TOKENOct, &SECOct, &UOct, &UTOct, &TPOct, &MESSAGEOct, C.int(TimeValue), &YOct)
-	errorCode = int(rtn)
-
-	// Convert octet to bytes
-	XOut = OCT_toBytes(&XOct)
-	SEC = OCT_toBytes(&SECOct)
-	U = OCT_toBytes(&UOct)
-	UT = OCT_toBytes(&UTOct)
-	Y = OCT_toBytes(&YOct)
-
-	return
-}
-
-// Precompute values for use by the client side of M-Pin Full
-func MPIN_PRECOMPUTE_WRAP(TOKEN []byte, ID []byte) (errorCode int, GT1 []byte, GT2 []byte) {
-	// Form Octets
-	IDStr := string(ID)
-	IDOct := GetOctet(IDStr)
-	defer OCT_free(&IDOct)
-	TOKENStr := string(TOKEN)
-	TOKENOct := GetOctet(TOKENStr)
-	defer OCT_free(&TOKENOct)
-
-	GT1Oct := GetOctetZero(GTS)
-	defer OCT_free(&GT1Oct)
-	GT2Oct := GetOctetZero(GTS)
-	defer OCT_free(&GT2Oct)
-
-	rtn := C.MPIN_PRECOMPUTE(&TOKENOct, &IDOct, &GT1Oct, &GT2Oct)
-	errorCode = int(rtn)
-
-	// Convert octet to bytes
-	GT1 = OCT_toBytes(&GT1Oct)
-	GT2 = OCT_toBytes(&GT2Oct)
-
-	return
-}
-
-/*
- W=x*H(G);
- if RNG == NULL then X is passed in
- if RNG != NULL the X is passed out
- if typ=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve
- Use GO RNG
-*/
-func MPIN_GET_G1_MULTIPLE_WRAP(RNG *amcl.RAND, typ int, X, G []byte) (errorCode int, XOut, W []byte) {
-	amcl.MPIN_RANDOM_GENERATE(RNG, X[:])
-	errorCode, XOut, W = MPIN_GET_G1_MULTIPLE_C(nil, typ, X[:], G[:])
-	return
-}
-
-/*
- W=x*H(G);
- if RNG == NULL then X is passed in
- if RNG != NULL the X is passed out
- if typ=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve
- Use C RNG
-*/
-func MPIN_GET_G1_MULTIPLE_C(RNG *C.csprng, typ int, X []byte, G []byte) (errorCode int, XOut, W []byte) {
-	XStr := string(X)
-	XOct := GetOctet(XStr)
-	defer OCT_free(&XOct)
-	GStr := string(G)
-	GOct := GetOctet(GStr)
-	defer OCT_free(&GOct)
-
-	WOct := GetOctetZero(G1S)
-	defer OCT_free(&WOct)
-
-	rtn := C.MPIN_GET_G1_MULTIPLE(RNG, C.int(typ), &XOct, &GOct, &WOct)
-	errorCode = int(rtn)
-
-	// Convert octet to bytes
-	XOut = OCT_toBytes(&XOct)
-	W = OCT_toBytes(&WOct)
-
-	return
-}
-
-/* One pass MPIN Server */
-func MPIN_SERVER_WRAP(date, TimeValue int, SS, U, UT, V, ID, MESSAGE []byte) (errorCode int, HID, HTID, Y, E, F []byte) {
-	SSStr := string(SS)
-	SSOct := GetOctet(SSStr)
-	defer OCT_free(&SSOct)
-	UStr := string(U)
-	UOct := GetOctet(UStr)
-	defer OCT_free(&UOct)
-	UTStr := string(UT)
-	UTOct := GetOctet(UTStr)
-	defer OCT_free(&UTOct)
-	VStr := string(V)
-	VOct := GetOctet(VStr)
-	defer OCT_free(&VOct)
-	IDStr := string(ID)
-	IDOct := GetOctet(IDStr)
-	defer OCT_free(&IDOct)
-	MESSAGEStr := string(MESSAGE)
-	MESSAGEOct := GetOctet(MESSAGEStr)
-	defer OCT_free(&MESSAGEOct)
-
-	HIDOct := GetOctetZero(G1S)
-	defer OCT_free(&HIDOct)
-	HTIDOct := GetOctetZero(G1S)
-	defer OCT_free(&HTIDOct)
-	YOct := GetOctetZero(EGS)
-	defer OCT_free(&YOct)
-	EOct := GetOctetZero(GTS)
-	defer OCT_free(&EOct)
-	FOct := GetOctetZero(GTS)
-	defer OCT_free(&FOct)
-
-	rtn := C.MPIN_SERVER(C.int(date), &HIDOct, &HTIDOct, &YOct, &SSOct, &UOct, &UTOct, &VOct, &EOct, &FOct, &IDOct, &MESSAGEOct, C.int(TimeValue))
-	errorCode = int(rtn)
-
-	// Convert octet to bytes
-	HID = OCT_toBytes(&HIDOct)
-	HTID = OCT_toBytes(&HTIDOct)
-	Y = OCT_toBytes(&YOct)
-	E = OCT_toBytes(&EOct)
-	F = OCT_toBytes(&FOct)
-
-	return
-}
-
-/* Pollards kangaroos used to return PIN error */
-func MPIN_KANGAROO(E []byte, F []byte) (PINError int) {
-	EStr := string(E)
-	EOct := GetOctet(EStr)
-	defer OCT_free(&EOct)
-	FStr := string(F)
-	FOct := GetOctet(FStr)
-	defer OCT_free(&FOct)
-
-	rtn := C.MPIN_KANGAROO(&EOct, &FOct)
-	PINError = int(rtn)
-	return
-}
-
-/* calculate common key on server side */
-/* Z=r.A - no time permits involved */
-func MPIN_SERVER_KEY_WRAP(Z, SS, W, P, I, U, UT []byte) (errorCode int, SK []byte) {
-	ZStr := string(Z)
-	ZOct := GetOctet(ZStr)
-	defer OCT_free(&ZOct)
-	SSStr := string(SS)
-	SSOct := GetOctet(SSStr)
-	defer OCT_free(&SSOct)
-	WStr := string(W)
-	WOct := GetOctet(WStr)
-	defer OCT_free(&WOct)
-	PStr := string(P)
-	POct := GetOctet(PStr)
-	defer OCT_free(&POct)
-	IStr := string(I)
-	IOct := GetOctet(IStr)
-	defer OCT_free(&IOct)
-	UStr := string(U)
-	UOct := GetOctet(UStr)
-	defer OCT_free(&UOct)
-	UTStr := string(UT)
-	UTOct := GetOctet(UTStr)
-	defer OCT_free(&UTOct)
-
-	SKOct := GetOctetZero(EAS)
-	defer OCT_free(&SKOct)
-
-	rtn := C.MPIN_SERVER_KEY(&ZOct, &SSOct, &WOct, &POct, &IOct, &UOct, &UTOct, &SKOct)
-	errorCode = int(rtn)
-
-	// Convert octet to bytes
-	SK = OCT_toBytes(&SKOct)
-
-	return
-}
-
-/* calculate common key on client side */
-/* wCID = w.(A+AT) */
-func MPIN_CLIENT_KEY_WRAP(PIN int, GT1, GT2, R, X, P, T []byte) (errorCode int, CK []byte) {
-	GT1Str := string(GT1)
-	GT1Oct := GetOctet(GT1Str)
-	defer OCT_free(&GT1Oct)
-	GT2Str := string(GT2)
-	GT2Oct := GetOctet(GT2Str)
-	defer OCT_free(&GT2Oct)
-	RStr := string(R)
-	ROct := GetOctet(RStr)
-	defer OCT_free(&ROct)
-	XStr := string(X)
-	XOct := GetOctet(XStr)
-	defer OCT_free(&XOct)
-	PStr := string(P)
-	POct := GetOctet(PStr)
-	defer OCT_free(&POct)
-	TStr := string(T)
-	TOct := GetOctet(TStr)
-	defer OCT_free(&TOct)
-
-	CKOct := GetOctetZero(EAS)
-	defer OCT_free(&CKOct)
-
-	rtn := C.MPIN_CLIENT_KEY(&GT1Oct, &GT2Oct, C.int(PIN), &ROct, &XOct, &POct, &TOct, &CKOct)
-	errorCode = int(rtn)
-
-	// Convert octet to bytes
-	CK = OCT_toBytes(&CKOct)
-
-	return
-}
-
-// Generate a random byte array
-func GENERATE_RANDOM_C(RNG *C.csprng, randomLen int) (random []byte) {
-	randomOct := GetOctetZero(randomLen)
-	defer OCT_free(&randomOct)
-
-	C.generateRandom(RNG, &randomOct)
-
-	// Convert octet to bytes
-	random = OCT_toBytes(&randomOct)
-
-	return
-}
-
-// Generate random six digit value
-func GENERATE_OTP_C(RNG *C.csprng) int {
-	rtn := C.generateOTP(RNG)
-	return int(rtn)
-}
-
-/* AES-GCM Encryption:
-   K is key, H is header, IV is initialization vector and P is plaintext.
-   Returns cipthertext and tag (MAC) */
-func MPIN_AES_GCM_ENCRYPT(K, IV, H, P []byte) ([]byte, []byte) {
-	KStr := string(K)
-	KOct := GetOctet(KStr)
-	defer OCT_free(&KOct)
-	IVStr := string(IV)
-	IVOct := GetOctet(IVStr)
-	defer OCT_free(&IVOct)
-	HStr := string(H)
-	HOct := GetOctet(HStr)
-	defer OCT_free(&HOct)
-	PStr := string(P)
-	POct := GetOctet(PStr)
-	defer OCT_free(&POct)
-
-	TOct := GetOctetZero(16)
-	defer OCT_free(&TOct)
-	lenC := len(PStr)
-	COct := GetOctetZero(lenC)
-	defer OCT_free(&COct)
-
-	C.MPIN_AES_GCM_ENCRYPT(&KOct, &IVOct, &HOct, &POct, &COct, &TOct)
-
-	// Convert octet to bytes
-	C := OCT_toBytes(&COct)
-	T := OCT_toBytes(&TOct)
-
-	return C, T[:]
-}
-
-/* AES-GCM Deryption:
-   K is key, H is header, IV is initialization vector and P is plaintext.
-   Returns cipthertext and tag (MAC) */
-func MPIN_AES_GCM_DECRYPT(K, IV, H, C []byte) ([]byte, []byte) {
-	KStr := string(K)
-	KOct := GetOctet(KStr)
-	defer OCT_free(&KOct)
-	IVStr := string(IV)
-	IVOct := GetOctet(IVStr)
-	defer OCT_free(&IVOct)
-	HStr := string(H)
-	HOct := GetOctet(HStr)
-	defer OCT_free(&HOct)
-	CStr := string(C)
-	COct := GetOctet(CStr)
-	defer OCT_free(&COct)
-
-	TOct := GetOctetZero(16)
-	defer OCT_free(&TOct)
-	lenP := len(CStr)
-	POct := GetOctetZero(lenP)
-	defer OCT_free(&POct)
-
-	C.MPIN_AES_GCM_DECRYPT(&KOct, &IVOct, &HOct, &COct, &POct, &TOct)
-
-	// Convert octet to bytes
-	P := OCT_toBytes(&POct)
-	T := OCT_toBytes(&TOct)
-
-	return P, T[:]
-}
-
-/* Password based Key Derivation Function */
-/* Input password p, salt s, and repeat count */
-/* Output key of length olen */
-func MPIN_PBKDF2(Pass, Salt []byte, rep, olen int) (Key []byte) {
-	PassStr := string(Pass)
-	PassOct := GetOctet(PassStr)
-	defer OCT_free(&PassOct)
-	SaltStr := string(Salt)
-	SaltOct := GetOctet(SaltStr)
-	defer OCT_free(&SaltOct)
-
-	KeyOct := GetOctetZero(olen)
-	defer OCT_free(&KeyOct)
-
-	C.MPIN_PBKDF2(&PassOct, &SaltOct, C.int(rep), C.int(olen), &KeyOct)
-
-	// Convert octet to bytes
-	Key = OCT_toBytes(&KeyOct)
-
-	return
-}
-
-func MPIN_printBinary(array []byte) {
-	for i := 0; i < len(array); i++ {
-		fmt.Printf("%02x", array[i])
-	}
-	fmt.Printf("\n")
-}
-
-/* Outputs H(CID) and H(T|H(CID)) for time permits. If no time permits set HID=HTID */
-func MPIN_SERVER_1_WRAP(date int, ID []byte) (HID, HTID []byte) {
-	// Form Octets
-	IDStr := string(ID)
-	IDOct := GetOctet(IDStr)
-	defer OCT_free(&IDOct)
-
-	HIDOct := GetOctetZero(G1S)
-	defer OCT_free(&HIDOct)
-	HTIDOct := GetOctetZero(G1S)
-	defer OCT_free(&HTIDOct)
-
-	C.MPIN_SERVER_1(C.int(date), &IDOct, &HIDOct, &HTIDOct)
-
-	// Convert octet to bytes
-	HID = OCT_toBytes(&HIDOct)
-	HTID = OCT_toBytes(&HTIDOct)
-
-	return
-}
-
-/* Implement step 2 of MPin protocol on server side */
-func MPIN_SERVER_2_WRAP(date int, HID []byte, HTID []byte, Y []byte, SS []byte, U []byte, UT []byte, V []byte) (errorCode int, E, F []byte) {
-	// Form Octets
-	HIDStr := string(HID)
-	HIDOct := GetOctet(HIDStr)
-	defer OCT_free(&HIDOct)
-	HTIDStr := string(HTID)
-	HTIDOct := GetOctet(HTIDStr)
-	defer OCT_free(&HTIDOct)
-	YStr := string(Y)
-	YOct := GetOctet(YStr)
-	defer OCT_free(&YOct)
-	SSStr := string(SS)
-	SSOct := GetOctet(SSStr)
-	defer OCT_free(&SSOct)
-	UStr := string(U)
-	UOct := GetOctet(UStr)
-	defer OCT_free(&UOct)
-	UTStr := string(UT)
-	UTOct := GetOctet(UTStr)
-	defer OCT_free(&UTOct)
-	VStr := string(V)
-	VOct := GetOctet(VStr)
-	defer OCT_free(&VOct)
-
-	EOct := GetOctetZero(GTS)
-	defer OCT_free(&EOct)
-	FOct := GetOctetZero(GTS)
-	defer OCT_free(&FOct)
-	rtn := C.MPIN_SERVER_2(C.int(date), &HIDOct, &HTIDOct, &YOct, &SSOct, &UOct, &UTOct, &VOct, &EOct, &FOct)
-
-	errorCode = int(rtn)
-	E = OCT_toBytes(&EOct)
-	F = OCT_toBytes(&FOct)
-
-	return
-}
-
-/* Implement step 1 on client side of MPin protocol. Use GO code to generate random X */
-func MPIN_CLIENT_1_WRAP(date int, ID []byte, RNG *amcl.RAND, X []byte, PIN int, TOKEN []byte, TP []byte) (errorCode int, XOut, SEC, U, UT []byte) {
-	amcl.MPIN_RANDOM_GENERATE(RNG, X[:])
-	errorCode, XOut, SEC, U, UT = MPIN_CLIENT_1_C(date, ID[:], nil, X[:], PIN, TOKEN[:], TP[:])
-	return
-}
-
-/* Implement step 1 on client side of MPin protocol
-   When rng=nil the X value is externally generated
-*/
-func MPIN_CLIENT_1_C(date int, ID []byte, rng *C.csprng, X []byte, PIN int, TOKEN []byte, TP []byte) (errorCode int, XOut, SEC, U, UT []byte) {
-	// Form Octets
-	IDStr := string(ID)
-	IDOct := GetOctet(IDStr)
-	defer OCT_free(&IDOct)
-
-	XStr := string(X)
-	XOct := GetOctet(XStr)
-	defer OCT_free(&XOct)
-
-	TOKENStr := string(TOKEN)
-	TOKENOct := GetOctet(TOKENStr)
-	defer OCT_free(&TOKENOct)
-
-	TPStr := string(TP)
-	TPOct := GetOctet(TPStr)
-	defer OCT_free(&TPOct)
-
-	SECOct := GetOctetZero(G1S)
-	defer OCT_free(&SECOct)
-	UOct := GetOctetZero(G1S)
-	defer OCT_free(&UOct)
-	UTOct := GetOctetZero(G1S)
-	defer OCT_free(&UTOct)
-
-	rtn := C.MPIN_CLIENT_1(C.int(date), &IDOct, rng, &XOct, C.int(PIN), &TOKENOct, &SECOct, &UOct, &UTOct, &TPOct)
-
-	errorCode = int(rtn)
-	// Convert octet to bytes
-	XOut = OCT_toBytes(&XOct)
-	SEC = OCT_toBytes(&SECOct)
-	U = OCT_toBytes(&UOct)
-	UT = OCT_toBytes(&UTOct)
-
-	return
-}
-
-/* Implement step 2 on client side of MPin protocol */
-func MPIN_CLIENT_2_WRAP(X []byte, Y []byte, SEC []byte) (errorCode int, V []byte) {
-	// Form Octets
-	XStr := string(X)
-	XOct := GetOctet(XStr)
-	defer OCT_free(&XOct)
-	YStr := string(Y)
-	YOct := GetOctet(YStr)
-	defer OCT_free(&YOct)
-	SECStr := string(SEC)
-	SECOct := GetOctet(SECStr)
-	defer OCT_free(&SECOct)
-
-	rtn := C.MPIN_CLIENT_2(&XOct, &YOct, &SECOct)
-
-	errorCode = int(rtn)
-	// Convert octet to bytes
-	V = OCT_toBytes(&SECOct)
-
-	return
-}
-
-func MPIN_HASH_ALL_WRAP(I, U, UT, Y, V, R, W []byte) (HM []byte) {
-	// Form Octets
-	IStr := string(I)
-	IOct := GetOctet(IStr)
-	defer OCT_free(&IOct)
-
-	UStr := string(U)
-	UOct := GetOctet(UStr)
-	defer OCT_free(&UOct)
-
-	UTStr := string(UT)
-	UTOct := GetOctet(UTStr)
-	defer OCT_free(&UTOct)
-
-	YStr := string(Y)
-	YOct := GetOctet(YStr)
-	defer OCT_free(&YOct)
-
-	VStr := string(V)
-	VOct := GetOctet(VStr)
-	defer OCT_free(&VOct)
-
-	RStr := string(R)
-	ROct := GetOctet(RStr)
-	defer OCT_free(&ROct)
-
-	WStr := string(W)
-	WOct := GetOctet(WStr)
-	defer OCT_free(&WOct)
-
-	HMOct := GetOctetZero(HASH_BYTES)
-	defer OCT_free(&HMOct)
-
-	// Hash values
-	C.MPIN_HASH_ALL(&IOct, &UOct, &UTOct, &YOct, &VOct, &ROct, &WOct, &HMOct)
-
-	// Convert octet to bytes
-	HM = OCT_toBytes(&HMOct)
-
-	return
-}
diff --git a/go/amcl-cgo/crypto_test.go b/go/amcl-cgo/crypto_test.go
deleted file mode 100644
index 0fa7c78..0000000
--- a/go/amcl-cgo/crypto_test.go
+++ /dev/null
@@ -1,1175 +0,0 @@
-/*
-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.
-*/
-
-package amcl
-
-import (
-	"crypto/rand"
-	"encoding/hex"
-	"fmt"
-	mathrand "math/rand"
-	"testing"
-
-	"github.com/stretchr/testify/assert"
-
-	amclgo "git.apache.org/incubator-milagro-crypto.git/go/amcl-go"
-)
-
-const nIter int = 100
-
-// Set to true if library built with "-D USE_ANONYMOUS=on"
-const USE_ANONYMOUS = false
-
-func TestGoodPIN(t *testing.T) {
-	want := 0
-	var got int
-
-	// Assign the End-User an ID
-	IDstr := "testUser@miracl.com"
-	ID := []byte(IDstr)
-
-	// Epoch time in days
-	date := 16660
-
-	// Epoch time in seconds
-	timeValue := 1439465203
-
-	// PIN variable to create token
-	PIN1 := 1234
-	// PIN variable to authenticate
-	PIN2 := 1234
-
-	// Seed value for Random Number Generator (RNG)
-	seedHex := "9e8b4178790cd57a5761c4a6f164ba72"
-	seed, err := hex.DecodeString(seedHex)
-	if err != nil {
-		fmt.Println("Error decoding seed value")
-		return
-	}
-	rng := amclgo.NewRAND()
-	rng.Seed(len(seed), seed)
-
-	// Message to sign
-	var MESSAGE []byte
-
-	// Generate Master Secret Share 1
-	_, MS1 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Generate Master Secret Share 2
-	_, MS2 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Either Client or TA calculates Hash(ID)
-	HCID := MPIN_HASH_ID(ID)
-
-	// Generate server secret share 1
-	_, SS1 := MPIN_GET_SERVER_SECRET_WRAP(MS1[:])
-
-	// Generate server secret share 2
-	_, SS2 := MPIN_GET_SERVER_SECRET_WRAP(MS2[:])
-
-	// Combine server secret shares
-	_, SS := MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:])
-
-	// Generate client secret share 1
-	_, CS1 := MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID)
-
-	// Generate client secret share 2
-	_, CS2 := MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID)
-
-	// Combine client secret shares
-	CS := make([]byte, G1S)
-	_, CS = MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:])
-
-	// Generate time permit share 1
-	_, TP1 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID)
-
-	// Generate time permit share 2
-	_, TP2 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID)
-
-	// Combine time permit shares
-	_, TP := MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:])
-
-	// Create token
-	_, TOKEN := MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:])
-
-	// Send U, UT, V, timeValue and Message to server
-	var X [EGS]byte
-	_, _, _, V, U, UT := MPIN_CLIENT_WRAP(date, timeValue, PIN2, rng, ID[:], X[:], TOKEN[:], TP[:], MESSAGE[:])
-
-	if USE_ANONYMOUS {
-		got, _, _, _, _, _ = MPIN_SERVER_WRAP(date, timeValue, SS[:], U[:], UT[:], V[:], HCID[:], MESSAGE[:])
-	} else {
-		got, _, _, _, _, _ = MPIN_SERVER_WRAP(date, timeValue, SS[:], U[:], UT[:], V[:], ID[:], MESSAGE[:])
-	}
-	assert.Equal(t, want, got, "Should be equal")
-}
-
-func TestBadPIN(t *testing.T) {
-	want := -19
-	var got int
-
-	// Assign the End-User an ID
-	IDstr := "testUser@miracl.com"
-	ID := []byte(IDstr)
-
-	// Epoch time in days
-	date := 16660
-
-	// Epoch time in seconds
-	timeValue := 1439465203
-
-	// PIN variable to create token
-	PIN1 := 1234
-	// PIN variable to authenticate
-	PIN2 := 1235
-
-	// Seed value for Random Number Generator (RNG)
-	seedHex := "9e8b4178790cd57a5761c4a6f164ba72"
-	seed, err := hex.DecodeString(seedHex)
-	if err != nil {
-		fmt.Println("Error decoding seed value")
-		return
-	}
-	rng := amclgo.NewRAND()
-	rng.Seed(len(seed), seed)
-
-	// Message to sign
-	var MESSAGE []byte
-
-	// Generate Master Secret Share 1
-	_, MS1 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Generate Master Secret Share 2
-	_, MS2 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Either Client or TA calculates Hash(ID)
-	HCID := MPIN_HASH_ID(ID)
-
-	// Generate server secret share 1
-	_, SS1 := MPIN_GET_SERVER_SECRET_WRAP(MS1[:])
-
-	// Generate server secret share 2
-	_, SS2 := MPIN_GET_SERVER_SECRET_WRAP(MS2[:])
-
-	// Combine server secret shares
-	_, SS := MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:])
-
-	// Generate client secret share 1
-	_, CS1 := MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID)
-
-	// Generate client secret share 2
-	_, CS2 := MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID)
-
-	// Combine client secret shares
-	CS := make([]byte, G1S)
-	_, CS = MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:])
-
-	// Generate time permit share 1
-	_, TP1 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID)
-
-	// Generate time permit share 2
-	_, TP2 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID)
-
-	// Combine time permit shares
-	_, TP := MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:])
-
-	// Create token
-	_, TOKEN := MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:])
-
-	//////   Client   //////
-
-	// Send U, UT, V, timeValue and Message to server
-	var X [EGS]byte
-	_, _, _, V, U, UT := MPIN_CLIENT_WRAP(date, timeValue, PIN2, rng, ID[:], X[:], TOKEN[:], TP[:], MESSAGE[:])
-
-	//////   Server   //////
-	if USE_ANONYMOUS {
-		got, _, _, _, _, _ = MPIN_SERVER_WRAP(date, timeValue, SS[:], U[:], UT[:], V[:], HCID[:], MESSAGE[:])
-	} else {
-		got, _, _, _, _, _ = MPIN_SERVER_WRAP(date, timeValue, SS[:], U[:], UT[:], V[:], ID[:], MESSAGE[:])
-	}
-	assert.Equal(t, want, got, "Should be equal")
-}
-
-func TestBadToken(t *testing.T) {
-	want := -19
-	var got int
-
-	// Assign the End-User an ID
-	IDstr := "testUser@miracl.com"
-	ID := []byte(IDstr)
-
-	// Epoch time in days
-	date := 16660
-
-	// Epoch time in seconds
-	timeValue := 1439465203
-
-	// PIN variable to create token
-	PIN1 := 1234
-	// PIN variable to authenticate
-	PIN2 := 1234
-
-	// Seed value for Random Number Generator (RNG)
-	seedHex := "9e8b4178790cd57a5761c4a6f164ba72"
-	seed, err := hex.DecodeString(seedHex)
-	if err != nil {
-		fmt.Println("Error decoding seed value")
-		return
-	}
-	rng := amclgo.NewRAND()
-	rng.Seed(len(seed), seed)
-
-	// Message to sign
-	var MESSAGE []byte
-
-	// Generate Master Secret Share 1
-	_, MS1 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Generate Master Secret Share 2
-	_, MS2 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Either Client or TA calculates Hash(ID)
-	HCID := MPIN_HASH_ID(ID)
-
-	// Generate server secret share 1
-	_, SS1 := MPIN_GET_SERVER_SECRET_WRAP(MS1[:])
-
-	// Generate server secret share 2
-	_, SS2 := MPIN_GET_SERVER_SECRET_WRAP(MS2[:])
-
-	// Combine server secret shares
-	_, SS := MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:])
-
-	// Generate client secret share 1
-	_, CS1 := MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID)
-
-	// Generate client secret share 2
-	_, CS2 := MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID)
-
-	// Combine client secret shares
-	CS := make([]byte, G1S)
-	_, CS = MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:])
-
-	// Generate time permit share 1
-	_, TP1 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID)
-
-	// Generate time permit share 2
-	_, TP2 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID)
-
-	// Combine time permit shares
-	_, TP := MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:])
-
-	// Create token
-	_, TOKEN := MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:])
-
-	// Send U, UT, V, timeValue and Message to server
-	var X [EGS]byte
-	_, _, _, _, U, UT := MPIN_CLIENT_WRAP(date, timeValue, PIN2, rng, ID[:], X[:], TOKEN[:], TP[:], MESSAGE[:])
-
-	// Send UT as V to model bad token
-	if USE_ANONYMOUS {
-		got, _, _, _, _, _ = MPIN_SERVER_WRAP(date, timeValue, SS[:], U[:], UT[:], UT[:], HCID[:], MESSAGE[:])
-	} else {
-		got, _, _, _, _, _ = MPIN_SERVER_WRAP(date, timeValue, SS[:], U[:], UT[:], UT[:], ID[:], MESSAGE[:])
-	}
-	assert.Equal(t, want, got, "Should be equal")
-}
-
-func TestRandom(t *testing.T) {
-	want := 0
-	var got int
-
-	for i := 0; i < nIter; i++ {
-
-		// Seed value for Random Number Generator (RNG)
-		seed := make([]byte, 16)
-		rand.Read(seed)
-		rng := amclgo.NewRAND()
-		rng.Seed(len(seed), seed)
-
-		// Epoch time in days
-		date := MPIN_today()
-
-		// Epoch time in seconds
-		timeValue := MPIN_GET_TIME()
-
-		// PIN variable to create token
-		PIN1 := mathrand.Intn(10000)
-		// PIN variable to authenticate
-		PIN2 := PIN1
-
-		// Assign the End-User a random ID
-		ID := make([]byte, 16)
-		rand.Read(ID)
-
-		// Message to sign
-		var MESSAGE []byte
-
-		// Generate Master Secret Share 1
-		_, MS1 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-		// Generate Master Secret Share 2
-		_, MS2 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-		// Either Client or TA calculates Hash(ID)
-		HCID := MPIN_HASH_ID(ID)
-
-		// Generate server secret share 1
-		_, SS1 := MPIN_GET_SERVER_SECRET_WRAP(MS1[:])
-
-		// Generate server secret share 2
-		_, SS2 := MPIN_GET_SERVER_SECRET_WRAP(MS2[:])
-
-		// Combine server secret shares
-		_, SS := MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:])
-
-		// Generate client secret share 1
-		_, CS1 := MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID)
-
-		// Generate client secret share 2
-		_, CS2 := MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID)
-
-		// Combine client secret shares
-		CS := make([]byte, G1S)
-		_, CS = MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:])
-
-		// Generate time permit share 1
-		_, TP1 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID)
-
-		// Generate time permit share 2
-		_, TP2 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID)
-
-		// Combine time permit shares
-		_, TP := MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:])
-
-		// Create token
-		_, TOKEN := MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:])
-
-		// Send U, UT, V, timeValue and Message to server
-		var X [EGS]byte
-		_, _, _, V, U, UT := MPIN_CLIENT_WRAP(date, timeValue, PIN2, rng, ID[:], X[:], TOKEN[:], TP[:], MESSAGE[:])
-
-		if USE_ANONYMOUS {
-			got, _, _, _, _, _ = MPIN_SERVER_WRAP(date, timeValue, SS[:], U[:], UT[:], V[:], HCID[:], MESSAGE[:])
-		} else {
-			got, _, _, _, _, _ = MPIN_SERVER_WRAP(date, timeValue, SS[:], U[:], UT[:], V[:], ID[:], MESSAGE[:])
-		}
-		assert.Equal(t, want, got, "Should be equal")
-	}
-}
-
-func TestGoodSignature(t *testing.T) {
-	want := 0
-	var got int
-
-	// Assign the End-User an ID
-	IDstr := "testUser@miracl.com"
-	ID := []byte(IDstr)
-
-	// Message to sign
-	MESSAGE := []byte("test message to sign")
-
-	// Epoch time in days
-	date := 16660
-
-	// Epoch time in seconds
-	timeValue := 1439465203
-
-	// PIN variable to create token
-	PIN1 := 1234
-	// PIN variable to authenticate
-	PIN2 := 1234
-
-	// Seed value for Random Number Generator (RNG)
-	seedHex := "9e8b4178790cd57a5761c4a6f164ba72"
-	seed, err := hex.DecodeString(seedHex)
-	if err != nil {
-		fmt.Println("Error decoding seed value")
-		return
-	}
-	rng := amclgo.NewRAND()
-	rng.Seed(len(seed), seed)
-
-	// Generate Master Secret Share 1
-	_, MS1 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Generate Master Secret Share 2
-	_, MS2 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Either Client or TA calculates Hash(ID)
-	HCID := MPIN_HASH_ID(ID)
-
-	// Generate server secret share 1
-	_, SS1 := MPIN_GET_SERVER_SECRET_WRAP(MS1[:])
-
-	// Generate server secret share 2
-	_, SS2 := MPIN_GET_SERVER_SECRET_WRAP(MS2[:])
-
-	// Combine server secret shares
-	_, SS := MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:])
-
-	// Generate client secret share 1
-	_, CS1 := MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID)
-
-	// Generate client secret share 2
-	_, CS2 := MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID)
-
-	// Combine client secret shares
-	CS := make([]byte, G1S)
-	_, CS = MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:])
-
-	// Generate time permit share 1
-	_, TP1 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID)
-
-	// Generate time permit share 2
-	_, TP2 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID)
-
-	// Combine time permit shares
-	_, TP := MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:])
-
-	// Create token
-	_, TOKEN := MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:])
-
-	// Send U, UT, V, timeValue and Message to server
-	var X [EGS]byte
-	_, _, _, V, U, UT := MPIN_CLIENT_WRAP(date, timeValue, PIN2, rng, ID[:], X[:], TOKEN[:], TP[:], MESSAGE[:])
-
-	// Authenticate
-	if USE_ANONYMOUS {
-		got, _, _, _, _, _ = MPIN_SERVER_WRAP(date, timeValue, SS[:], U[:], UT[:], V[:], HCID[:], MESSAGE[:])
-	} else {
-		got, _, _, _, _, _ = MPIN_SERVER_WRAP(date, timeValue, SS[:], U[:], UT[:], V[:], ID[:], MESSAGE[:])
-	}
-	assert.Equal(t, want, got, "Should be equal")
-}
-
-func TestSignatureExpired(t *testing.T) {
-	want := -19
-	var got int
-
-	// Assign the End-User an ID
-	IDstr := "testUser@miracl.com"
-	ID := []byte(IDstr)
-
-	// Message to sign
-	MESSAGE := []byte("test message to sign")
-
-	// Epoch time in days
-	date := 16660
-
-	// Epoch time in seconds
-	timeValue := 1439465203
-
-	// PIN variable to create token
-	PIN1 := 1234
-	// PIN variable to authenticate
-	PIN2 := 1234
-
-	// Seed value for Random Number Generator (RNG)
-	seedHex := "9e8b4178790cd57a5761c4a6f164ba72"
-	seed, err := hex.DecodeString(seedHex)
-	if err != nil {
-		fmt.Println("Error decoding seed value")
-		return
-	}
-	rng := amclgo.NewRAND()
-	rng.Seed(len(seed), seed)
-
-	// Generate Master Secret Share 1
-	_, MS1 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Generate Master Secret Share 2
-	_, MS2 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Either Client or TA calculates Hash(ID)
-	HCID := MPIN_HASH_ID(ID)
-
-	// Generate server secret share 1
-	_, SS1 := MPIN_GET_SERVER_SECRET_WRAP(MS1[:])
-
-	// Generate server secret share 2
-	_, SS2 := MPIN_GET_SERVER_SECRET_WRAP(MS2[:])
-
-	// Combine server secret shares
-	_, SS := MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:])
-
-	// Generate client secret share 1
-	_, CS1 := MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID)
-
-	// Generate client secret share 2
-	_, CS2 := MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID)
-
-	// Combine client secret shares
-	CS := make([]byte, G1S)
-	_, CS = MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:])
-
-	// Generate time permit share 1
-	_, TP1 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID)
-
-	// Generate time permit share 2
-	_, TP2 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID)
-
-	// Combine time permit shares
-	_, TP := MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:])
-
-	// Create token
-	_, TOKEN := MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:])
-
-	// Send U, UT, V, timeValue and Message to server
-	var X [EGS]byte
-	_, _, _, V, U, UT := MPIN_CLIENT_WRAP(date, timeValue, PIN2, rng, ID[:], X[:], TOKEN[:], TP[:], MESSAGE[:])
-
-	timeValue += 10
-	// Authenticate
-	if USE_ANONYMOUS {
-		got, _, _, _, _, _ = MPIN_SERVER_WRAP(date, timeValue, SS[:], U[:], UT[:], V[:], HCID[:], MESSAGE[:])
-	} else {
-		got, _, _, _, _, _ = MPIN_SERVER_WRAP(date, timeValue, SS[:], U[:], UT[:], V[:], ID[:], MESSAGE[:])
-	}
-	assert.Equal(t, want, got, "Should be equal")
-}
-
-func TestBadSignature(t *testing.T) {
-	want := -19
-	var got int
-
-	// Assign the End-User an ID
-	IDstr := "testUser@miracl.com"
-	ID := []byte(IDstr)
-
-	// Message to sign
-	MESSAGE := []byte("test message to sign")
-
-	// Epoch time in days
-	date := 16660
-
-	// Epoch time in seconds
-	timeValue := 1439465203
-
-	// PIN variable to create token
-	PIN1 := 1234
-	// PIN variable to authenticate
-	PIN2 := 1234
-
-	// Seed value for Random Number Generator (RNG)
-	seedHex := "9e8b4178790cd57a5761c4a6f164ba72"
-	seed, err := hex.DecodeString(seedHex)
-	if err != nil {
-		fmt.Println("Error decoding seed value")
-		return
-	}
-	rng := amclgo.NewRAND()
-	rng.Seed(len(seed), seed)
-
-	// Generate Master Secret Share 1
-	_, MS1 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Generate Master Secret Share 2
-	_, MS2 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Either Client or TA calculates Hash(ID)
-	HCID := MPIN_HASH_ID(ID)
-
-	// Generate server secret share 1
-	_, SS1 := MPIN_GET_SERVER_SECRET_WRAP(MS1[:])
-
-	// Generate server secret share 2
-	_, SS2 := MPIN_GET_SERVER_SECRET_WRAP(MS2[:])
-
-	// Combine server secret shares
-	_, SS := MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:])
-
-	// Generate client secret share 1
-	_, CS1 := MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID)
-
-	// Generate client secret share 2
-	_, CS2 := MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID)
-
-	// Combine client secret shares
-	CS := make([]byte, G1S)
-	_, CS = MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:])
-
-	// Generate time permit share 1
-	_, TP1 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID)
-
-	// Generate time permit share 2
-	_, TP2 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID)
-
-	// Combine time permit shares
-	_, TP := MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:])
-
-	// Create token
-	_, TOKEN := MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:])
-
-	// Send U, UT, V, timeValue and Message to server
-	var X [EGS]byte
-	_, _, _, V, U, UT := MPIN_CLIENT_WRAP(date, timeValue, PIN2, rng, ID[:], X[:], TOKEN[:], TP[:], MESSAGE[:])
-
-	// Authenticate
-	MESSAGE[0] = 00
-	if USE_ANONYMOUS {
-		got, _, _, _, _, _ = MPIN_SERVER_WRAP(date, timeValue, SS[:], U[:], UT[:], V[:], HCID[:], MESSAGE[:])
-	} else {
-		got, _, _, _, _, _ = MPIN_SERVER_WRAP(date, timeValue, SS[:], U[:], UT[:], V[:], ID[:], MESSAGE[:])
-	}
-	assert.Equal(t, want, got, "Should be equal")
-}
-
-func TestPINError(t *testing.T) {
-	want := 1001
-	// Assign the End-User an ID
-	IDstr := "testUser@miracl.com"
-	ID := []byte(IDstr)
-
-	// Epoch time in days
-	date := 16660
-
-	// Epoch time in seconds
-	timeValue := 1439465203
-
-	// PIN variable to create token
-	PIN1 := 1234
-	// PIN variable to authenticate
-	PIN2 := 2235
-
-	// Seed value for Random Number Generator (RNG)
-	seedHex := "9e8b4178790cd57a5761c4a6f164ba72"
-	seed, err := hex.DecodeString(seedHex)
-	if err != nil {
-		fmt.Println("Error decoding seed value")
-		return
-	}
-	rng := amclgo.NewRAND()
-	rng.Seed(len(seed), seed)
-
-	// Message to sign
-	var MESSAGE []byte
-
-	// Generate Master Secret Share 1
-	_, MS1 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Generate Master Secret Share 2
-	_, MS2 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Either Client or TA calculates Hash(ID)
-	HCID := MPIN_HASH_ID(ID)
-
-	// Generate server secret share 1
-	_, SS1 := MPIN_GET_SERVER_SECRET_WRAP(MS1[:])
-
-	// Generate server secret share 2
-	_, SS2 := MPIN_GET_SERVER_SECRET_WRAP(MS2[:])
-
-	// Combine server secret shares
-	_, SS := MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:])
-
-	// Generate client secret share 1
-	_, CS1 := MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID)
-
-	// Generate client secret share 2
-	_, CS2 := MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID)
-
-	// Combine client secret shares
-	CS := make([]byte, G1S)
-	_, CS = MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:])
-
-	// Generate time permit share 1
-	_, TP1 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID)
-
-	// Generate time permit share 2
-	_, TP2 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID)
-
-	// Combine time permit shares
-	_, TP := MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:])
-
-	// Create token
-	_, TOKEN := MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:])
-
-	// Send U, UT, V, timeValue and Message to server
-	var X [EGS]byte
-	_, _, _, V, U, UT := MPIN_CLIENT_WRAP(date, timeValue, PIN2, rng, ID[:], X[:], TOKEN[:], TP[:], MESSAGE[:])
-
-	var E []byte
-	var F []byte
-	if USE_ANONYMOUS {
-		_, _, _, _, E, F = MPIN_SERVER_WRAP(date, timeValue, SS[:], U[:], UT[:], V[:], HCID[:], MESSAGE[:])
-	} else {
-		_, _, _, _, E, F = MPIN_SERVER_WRAP(date, timeValue, SS[:], U[:], UT[:], V[:], ID[:], MESSAGE[:])
-	}
-
-	got := MPIN_KANGAROO(E[:], F[:])
-	assert.Equal(t, want, got, "Should be equal")
-}
-
-func TestMPINFull(t *testing.T) {
-	want := "4e0317c9962dc2944c121ec41c800e16"
-	// Assign the End-User an ID
-	IDstr := "testUser@miracl.com"
-	ID := []byte(IDstr)
-
-	// Epoch time in days
-	date := 16660
-
-	// Epoch time in seconds
-	timeValue := 1439465203
-
-	// PIN variable to create token
-	PIN1 := 1234
-	// PIN variable to authenticate
-	PIN2 := 1234
-
-	// Seed value for Random Number Generator (RNG)
-	seedHex := "9e8b4178790cd57a5761c4a6f164ba72"
-	seed, err := hex.DecodeString(seedHex)
-	if err != nil {
-		fmt.Println("Error decoding seed value")
-		return
-	}
-	rng := amclgo.NewRAND()
-	rng.Seed(len(seed), seed)
-
-	// Message to sign
-	var MESSAGE []byte
-
-	// Generate Master Secret Share 1
-	_, MS1 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Generate Master Secret Share 2
-	_, MS2 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Either Client or TA calculates Hash(ID)
-	HCID := MPIN_HASH_ID(ID)
-
-	// Generate server secret share 1
-	_, SS1 := MPIN_GET_SERVER_SECRET_WRAP(MS1[:])
-
-	// Generate server secret share 2
-	_, SS2 := MPIN_GET_SERVER_SECRET_WRAP(MS2[:])
-
-	// Combine server secret shares
-	_, SS := MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:])
-
-	// Generate client secret share 1
-	_, CS1 := MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID)
-
-	// Generate client secret share 2
-	_, CS2 := MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID)
-
-	// Combine client secret shares
-	CS := make([]byte, G1S)
-	_, CS = MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:])
-
-	// Generate time permit share 1
-	_, TP1 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID)
-
-	// Generate time permit share 2
-	_, TP2 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID)
-
-	// Combine time permit shares
-	_, TP := MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:])
-
-	// Create token
-	_, TOKEN := MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:])
-
-	// Precomputation
-	_, G1, G2 := MPIN_PRECOMPUTE_WRAP(TOKEN[:], HCID)
-
-	// Send U, UT, V, timeValue and Message to server
-	var X [EGS]byte
-	_, XOut, _, V, U, UT := MPIN_CLIENT_WRAP(date, timeValue, PIN2, rng, ID[:], X[:], TOKEN[:], TP[:], MESSAGE[:])
-
-	// Send Z=r.ID to Server
-	var R [EGS]byte
-	_, ROut, Z := MPIN_GET_G1_MULTIPLE_WRAP(rng, 1, R[:], HCID[:])
-
-	// Authenticate
-	var HID []byte
-	var HTID []byte
-	var Y []byte
-	if USE_ANONYMOUS {
-		_, HID, HTID, Y, _, _ = MPIN_SERVER_WRAP(date, timeValue, SS[:], U[:], UT[:], V[:], HCID[:], MESSAGE[:])
-	} else {
-		_, HID, HTID, Y, _, _ = MPIN_SERVER_WRAP(date, timeValue, SS[:], U[:], UT[:], V[:], ID[:], MESSAGE[:])
-	}
-
-	// send T=w.ID to client
-	var W [EGS]byte
-	_, WOut, T := MPIN_GET_G1_MULTIPLE_WRAP(rng, 0, W[:], HTID[:])
-
-	// Hash all values
-	HM := MPIN_HASH_ALL_WRAP(HCID[:], U[:], UT[:], Y[:], V[:], Z[:], T[:])
-
-	_, AES_KEY_SERVER := MPIN_SERVER_KEY_WRAP(Z[:], SS[:], WOut[:], HM[:], HID[:], U[:], UT[:])
-	got := hex.EncodeToString(AES_KEY_SERVER[:])
-	if got != want {
-		t.Errorf("%s != %s", want, got)
-	}
-
-	_, AES_KEY_CLIENT := MPIN_CLIENT_KEY_WRAP(PIN2, G1[:], G2[:], ROut[:], XOut[:], HM[:], T[:])
-	got = hex.EncodeToString(AES_KEY_CLIENT[:])
-
-	assert.Equal(t, want, got, "Should be equal")
-}
-
-func TestTwoPassGoodPIN(t *testing.T) {
-	want := 0
-	// Assign the End-User an ID
-	IDstr := "testUser@miracl.com"
-	ID := []byte(IDstr)
-
-	// Epoch time in days
-	date := 16660
-
-	// PIN variable to create token
-	PIN1 := 1234
-	// PIN variable to authenticate
-	PIN2 := 1234
-
-	// Seed value for Random Number Generator (RNG)
-	seedHex := "9e8b4178790cd57a5761c4a6f164ba72"
-	seed, err := hex.DecodeString(seedHex)
-	if err != nil {
-		fmt.Println("Error decoding seed value")
-		return
-	}
-	rng := amclgo.NewRAND()
-	rng.Seed(len(seed), seed)
-
-	// Generate Master Secret Share 1
-	_, MS1 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Generate Master Secret Share 2
-	_, MS2 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Either Client or TA calculates Hash(ID)
-	HCID := MPIN_HASH_ID(ID)
-
-	// Generate server secret share 1
-	_, SS1 := MPIN_GET_SERVER_SECRET_WRAP(MS1[:])
-
-	// Generate server secret share 2
-	_, SS2 := MPIN_GET_SERVER_SECRET_WRAP(MS2[:])
-
-	// Combine server secret shares
-	_, SS := MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:])
-
-	// Generate client secret share 1
-	_, CS1 := MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID)
-
-	// Generate client secret share 2
-	_, CS2 := MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID)
-
-	// Combine client secret shares
-	CS := make([]byte, G1S)
-	_, CS = MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:])
-
-	// Generate time permit share 1
-	_, TP1 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID)
-
-	// Generate time permit share 2
-	_, TP2 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID)
-
-	// Combine time permit shares
-	_, TP := MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:])
-
-	// Create token
-	_, TOKEN := MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:])
-
-	// Client Pass 1
-	var X [EGS]byte
-	_, _, SEC, U, UT := MPIN_CLIENT_1_WRAP(date, ID, rng, X[:], PIN2, TOKEN[:], TP[:])
-
-	// Server Pass 1
-	var HID []byte
-	var HTID []byte
-	if USE_ANONYMOUS {
-		HID, HTID = MPIN_SERVER_1_WRAP(date, HCID)
-	} else {
-		HID, HTID = MPIN_SERVER_1_WRAP(date, ID)
-	}
-	_, Y := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Client Pass 2
-	_, V := MPIN_CLIENT_2_WRAP(X[:], Y[:], SEC[:])
-
-	// Server Pass 2
-	got, _, _ := MPIN_SERVER_2_WRAP(date, HID[:], HTID[:], Y[:], SS[:], U[:], UT[:], V[:])
-	assert.Equal(t, want, got, "Should be equal")
-}
-
-func TestTwoPassBadPIN(t *testing.T) {
-	want := -19
-	// Assign the End-User an ID
-	IDstr := "testUser@miracl.com"
-	ID := []byte(IDstr)
-
-	// Epoch time in days
-	date := 16660
-
-	// PIN variable to create token
-	PIN1 := 1234
-	// PIN variable to authenticate
-	PIN2 := 1235
-
-	// Seed value for Random Number Generator (RNG)
-	seedHex := "9e8b4178790cd57a5761c4a6f164ba72"
-	seed, err := hex.DecodeString(seedHex)
-	if err != nil {
-		fmt.Println("Error decoding seed value")
-		return
-	}
-	rng := amclgo.NewRAND()
-	rng.Seed(len(seed), seed)
-
-	// Generate Master Secret Share 1
-	_, MS1 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Generate Master Secret Share 2
-	_, MS2 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Either Client or TA calculates Hash(ID)
-	HCID := MPIN_HASH_ID(ID)
-
-	// Generate server secret share 1
-	_, SS1 := MPIN_GET_SERVER_SECRET_WRAP(MS1[:])
-
-	// Generate server secret share 2
-	_, SS2 := MPIN_GET_SERVER_SECRET_WRAP(MS2[:])
-
-	// Combine server secret shares
-	_, SS := MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:])
-
-	// Generate client secret share 1
-	_, CS1 := MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID)
-
-	// Generate client secret share 2
-	_, CS2 := MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID)
-
-	// Combine client secret shares
-	CS := make([]byte, G1S)
-	_, CS = MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:])
-
-	// Generate time permit share 1
-	_, TP1 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID)
-
-	// Generate time permit share 2
-	_, TP2 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID)
-
-	// Combine time permit shares
-	_, TP := MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:])
-
-	// Create token
-	_, TOKEN := MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:])
-
-	// Client Pass 1
-	var X [EGS]byte
-	_, _, SEC, U, UT := MPIN_CLIENT_1_WRAP(date, ID, rng, X[:], PIN2, TOKEN[:], TP[:])
-
-	// Server Pass 1
-	var HID []byte
-	var HTID []byte
-	if USE_ANONYMOUS {
-		HID, HTID = MPIN_SERVER_1_WRAP(date, HCID)
-	} else {
-		HID, HTID = MPIN_SERVER_1_WRAP(date, ID)
-	}
-	_, Y := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Client Pass 2
-	_, V := MPIN_CLIENT_2_WRAP(X[:], Y[:], SEC[:])
-
-	// Server Pass 2
-	got, _, _ := MPIN_SERVER_2_WRAP(date, HID[:], HTID[:], Y[:], SS[:], U[:], UT[:], V[:])
-	assert.Equal(t, want, got, "Should be equal")
-}
-
-func TestTwoPassBadToken(t *testing.T) {
-	want := -19
-	// Assign the End-User an ID
-	IDstr := "testUser@miracl.com"
-	ID := []byte(IDstr)
-
-	// Epoch time in days
-	date := 16660
-
-	// PIN variable to create token
-	PIN1 := 1234
-	// PIN variable to authenticate
-	PIN2 := 1234
-
-	// Seed value for Random Number Generator (RNG)
-	seedHex := "9e8b4178790cd57a5761c4a6f164ba72"
-	seed, err := hex.DecodeString(seedHex)
-	if err != nil {
-		fmt.Println("Error decoding seed value")
-		return
-	}
-	rng := amclgo.NewRAND()
-	rng.Seed(len(seed), seed)
-
-	// Generate Master Secret Share 1
-	_, MS1 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Generate Master Secret Share 2
-	_, MS2 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Either Client or TA calculates Hash(ID)
-	HCID := MPIN_HASH_ID(ID)
-
-	// Generate server secret share 1
-	_, SS1 := MPIN_GET_SERVER_SECRET_WRAP(MS1[:])
-
-	// Generate server secret share 2
-	_, SS2 := MPIN_GET_SERVER_SECRET_WRAP(MS2[:])
-
-	// Combine server secret shares
-	_, SS := MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:])
-
-	// Generate client secret share 1
-	_, CS1 := MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID)
-
-	// Generate client secret share 2
-	_, CS2 := MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID)
-
-	// Combine client secret shares
-	CS := make([]byte, G1S)
-	_, CS = MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:])
-
-	// Generate time permit share 1
-	_, TP1 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID)
-
-	// Generate time permit share 2
-	_, TP2 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID)
-
-	// Combine time permit shares
-	_, TP := MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:])
-
-	// Create token
-	_, TOKEN := MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:])
-
-	// Client Pass 1
-	var X [EGS]byte
-	_, _, SEC, U, UT := MPIN_CLIENT_1_WRAP(date, ID, rng, X[:], PIN2, TOKEN[:], TP[:])
-
-	// Server Pass 1
-	var HID []byte
-	var HTID []byte
-	if USE_ANONYMOUS {
-		HID, HTID = MPIN_SERVER_1_WRAP(date, HCID)
-	} else {
-		HID, HTID = MPIN_SERVER_1_WRAP(date, ID)
-	}
-	_, Y := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Client Pass 2
-	_, _ = MPIN_CLIENT_2_WRAP(X[:], Y[:], SEC[:])
-
-	// Server Pass 2
-	// Send UT as V to model bad token
-	got, _, _ := MPIN_SERVER_2_WRAP(date, HID[:], HTID[:], Y[:], SS[:], U[:], UT[:], UT[:])
-	assert.Equal(t, want, got, "Should be equal")
-}
-
-func TestRandomTwoPass(t *testing.T) {
-	want := 0
-
-	for i := 0; i < nIter; i++ {
-
-		// Seed value for Random Number Generator (RNG)
-		seed := make([]byte, 16)
-		rand.Read(seed)
-		rng := amclgo.NewRAND()
-		rng.Seed(len(seed), seed)
-
-		// Epoch time in days
-		date := MPIN_today()
-
-		// PIN variable to create token
-		PIN1 := mathrand.Intn(10000)
-		// PIN variable to authenticate
-		PIN2 := PIN1
-
-		// Assign the End-User a random ID
-		ID := make([]byte, 16)
-		rand.Read(ID)
-
-		// Generate Master Secret Share 1
-		_, MS1 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-		// Generate Master Secret Share 2
-		_, MS2 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-		// Either Client or TA calculates Hash(ID)
-		HCID := MPIN_HASH_ID(ID)
-
-		// Generate server secret share 1
-		_, SS1 := MPIN_GET_SERVER_SECRET_WRAP(MS1[:])
-
-		// Generate server secret share 2
-		_, SS2 := MPIN_GET_SERVER_SECRET_WRAP(MS2[:])
-
-		// Combine server secret shares
-		_, SS := MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:])
-
-		// Generate client secret share 1
-		_, CS1 := MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID)
-
-		// Generate client secret share 2
-		_, CS2 := MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID)
-
-		// Combine client secret shares
-		CS := make([]byte, G1S)
-		_, CS = MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:])
-
-		// Generate time permit share 1
-		_, TP1 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID)
-
-		// Generate time permit share 2
-		_, TP2 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID)
-
-		// Combine time permit shares
-		_, TP := MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:])
-
-		// Create token
-		_, TOKEN := MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:])
-
-		// Client Pass 1
-		var X [EGS]byte
-		_, _, SEC, U, UT := MPIN_CLIENT_1_WRAP(date, ID, rng, X[:], PIN2, TOKEN[:], TP[:])
-
-		// Server Pass 1
-		var HID []byte
-		var HTID []byte
-		if USE_ANONYMOUS {
-			HID, HTID = MPIN_SERVER_1_WRAP(date, HCID)
-		} else {
-			HID, HTID = MPIN_SERVER_1_WRAP(date, ID)
-		}
-		_, Y := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-		// Client Pass 2
-		_, V := MPIN_CLIENT_2_WRAP(X[:], Y[:], SEC[:])
-
-		// Server Pass 2
-		got, _, _ := MPIN_SERVER_2_WRAP(date, HID[:], HTID[:], Y[:], SS[:], U[:], UT[:], V[:])
-		assert.Equal(t, want, got, "Should be equal")
-
-	}
-}
diff --git a/go/amcl-go/AES.go b/go/amcl-go/AES.go
deleted file mode 100644
index 598d408..0000000
--- a/go/amcl-go/AES.go
+++ /dev/null
@@ -1,634 +0,0 @@
-/*
-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.
-*/
-
-/* AES Encryption */
-
-package amcl
-
-//import "fmt"
-
-const aes_ECB int = 0
-const aes_CBC int = 1
-const aes_CFB1 int = 2
-const aes_CFB2 int = 3
-const aes_CFB4 int = 5
-const aes_OFB1 int = 14
-const aes_OFB2 int = 15
-const aes_OFB4 int = 17
-const aes_OFB8 int = 21
-const aes_OFB16 int = 29
-
-var aes_InCo = [...]byte{0xB, 0xD, 0x9, 0xE} /* Inverse Coefficients */
-
-var aes_ptab = [...]byte{
-	1, 3, 5, 15, 17, 51, 85, 255, 26, 46, 114, 150, 161, 248, 19, 53,
-	95, 225, 56, 72, 216, 115, 149, 164, 247, 2, 6, 10, 30, 34, 102, 170,
-	229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217, 112, 144, 171, 230, 49,
-	83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104, 184, 211, 110, 178, 205,
-	76, 212, 103, 169, 224, 59, 77, 215, 98, 166, 241, 8, 24, 40, 120, 136,
-	131, 158, 185, 208, 107, 189, 220, 127, 129, 152, 179, 206, 73, 219, 118, 154,
-	181, 196, 87, 249, 16, 48, 80, 240, 11, 29, 39, 105, 187, 214, 97, 163,
-	254, 25, 43, 125, 135, 146, 173, 236, 47, 113, 147, 174, 233, 32, 96, 160,
-	251, 22, 58, 78, 210, 109, 183, 194, 93, 231, 50, 86, 250, 21, 63, 65,
-	195, 94, 226, 61, 71, 201, 64, 192, 91, 237, 44, 116, 156, 191, 218, 117,
-	159, 186, 213, 100, 172, 239, 42, 126, 130, 157, 188, 223, 122, 142, 137, 128,
-	155, 182, 193, 88, 232, 35, 101, 175, 234, 37, 111, 177, 200, 67, 197, 84,
-	252, 31, 33, 99, 165, 244, 7, 9, 27, 45, 119, 153, 176, 203, 70, 202,
-	69, 207, 74, 222, 121, 139, 134, 145, 168, 227, 62, 66, 198, 81, 243, 14,
-	18, 54, 90, 238, 41, 123, 141, 140, 143, 138, 133, 148, 167, 242, 13, 23,
-	57, 75, 221, 124, 132, 151, 162, 253, 28, 36, 108, 180, 199, 82, 246, 1}
-
-var aes_ltab = [...]byte{
-	0, 255, 25, 1, 50, 2, 26, 198, 75, 199, 27, 104, 51, 238, 223, 3,
-	100, 4, 224, 14, 52, 141, 129, 239, 76, 113, 8, 200, 248, 105, 28, 193,
-	125, 194, 29, 181, 249, 185, 39, 106, 77, 228, 166, 114, 154, 201, 9, 120,
-	101, 47, 138, 5, 33, 15, 225, 36, 18, 240, 130, 69, 53, 147, 218, 142,
-	150, 143, 219, 189, 54, 208, 206, 148, 19, 92, 210, 241, 64, 70, 131, 56,
-	102, 221, 253, 48, 191, 6, 139, 98, 179, 37, 226, 152, 34, 136, 145, 16,
-	126, 110, 72, 195, 163, 182, 30, 66, 58, 107, 40, 84, 250, 133, 61, 186,
-	43, 121, 10, 21, 155, 159, 94, 202, 78, 212, 172, 229, 243, 115, 167, 87,
-	175, 88, 168, 80, 244, 234, 214, 116, 79, 174, 233, 213, 231, 230, 173, 232,
-	44, 215, 117, 122, 235, 22, 11, 245, 89, 203, 95, 176, 156, 169, 81, 160,
-	127, 12, 246, 111, 23, 196, 73, 236, 216, 67, 31, 45, 164, 118, 123, 183,
-	204, 187, 62, 90, 251, 96, 177, 134, 59, 82, 161, 108, 170, 85, 41, 157,
-	151, 178, 135, 144, 97, 190, 220, 252, 188, 149, 207, 205, 55, 63, 91, 209,
-	83, 57, 132, 60, 65, 162, 109, 71, 20, 42, 158, 93, 86, 242, 211, 171,
-	68, 17, 146, 217, 35, 32, 46, 137, 180, 124, 184, 38, 119, 153, 227, 165,
-	103, 74, 237, 222, 197, 49, 254, 24, 13, 99, 140, 128, 192, 247, 112, 7}
-
-var aes_fbsub = [...]byte{
-	99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118,
-	202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192,
-	183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21,
-	4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117,
-	9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132,
-	83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207,
-	208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168,
-	81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210,
-	205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115,
-	96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219,
-	224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121,
-	231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8,
-	186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138,
-	112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158,
-	225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223,
-	140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22}
-
-var aes_rbsub = [...]byte{
-	82, 9, 106, 213, 48, 54, 165, 56, 191, 64, 163, 158, 129, 243, 215, 251,
-	124, 227, 57, 130, 155, 47, 255, 135, 52, 142, 67, 68, 196, 222, 233, 203,
-	84, 123, 148, 50, 166, 194, 35, 61, 238, 76, 149, 11, 66, 250, 195, 78,
-	8, 46, 161, 102, 40, 217, 36, 178, 118, 91, 162, 73, 109, 139, 209, 37,
-	114, 248, 246, 100, 134, 104, 152, 22, 212, 164, 92, 204, 93, 101, 182, 146,
-	108, 112, 72, 80, 253, 237, 185, 218, 94, 21, 70, 87, 167, 141, 157, 132,
-	144, 216, 171, 0, 140, 188, 211, 10, 247, 228, 88, 5, 184, 179, 69, 6,
-	208, 44, 30, 143, 202, 63, 15, 2, 193, 175, 189, 3, 1, 19, 138, 107,
-	58, 145, 17, 65, 79, 103, 220, 234, 151, 242, 207, 206, 240, 180, 230, 115,
-	150, 172, 116, 34, 231, 173, 53, 133, 226, 249, 55, 232, 28, 117, 223, 110,
-	71, 241, 26, 113, 29, 41, 197, 137, 111, 183, 98, 14, 170, 24, 190, 27,
-	252, 86, 62, 75, 198, 210, 121, 32, 154, 219, 192, 254, 120, 205, 90, 244,
-	31, 221, 168, 51, 136, 7, 199, 49, 177, 18, 16, 89, 39, 128, 236, 95,
-	96, 81, 127, 169, 25, 181, 74, 13, 45, 229, 122, 159, 147, 201, 156, 239,
-	160, 224, 59, 77, 174, 42, 245, 176, 200, 235, 187, 60, 131, 83, 153, 97,
-	23, 43, 4, 126, 186, 119, 214, 38, 225, 105, 20, 99, 85, 33, 12, 125}
-
-var aes_rco = [...]byte{1, 2, 4, 8, 16, 32, 64, 128, 27, 54, 108, 216, 171, 77, 154, 47}
-
-var aes_ftable = [...]uint32{
-	0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, 0xdf2f2ff, 0xbd6b6bd6,
-	0xb16f6fde, 0x54c5c591, 0x50303060, 0x3010102, 0xa96767ce, 0x7d2b2b56,
-	0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec, 0x45caca8f, 0x9d82821f,
-	0x40c9c989, 0x877d7dfa, 0x15fafaef, 0xeb5959b2, 0xc947478e, 0xbf0f0fb,
-	0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45, 0xbf9c9c23, 0xf7a4a453,
-	0x967272e4, 0x5bc0c09b, 0xc2b7b775, 0x1cfdfde1, 0xae93933d, 0x6a26264c,
-	0x5a36366c, 0x413f3f7e, 0x2f7f7f5, 0x4fcccc83, 0x5c343468, 0xf4a5a551,
-	0x34e5e5d1, 0x8f1f1f9, 0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a,
-	0xc040408, 0x52c7c795, 0x65232346, 0x5ec3c39d, 0x28181830, 0xa1969637,
-	0xf05050a, 0xb59a9a2f, 0x907070e, 0x36121224, 0x9b80801b, 0x3de2e2df,
-	0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea, 0x1b090912, 0x9e83831d,
-	0x742c2c58, 0x2e1a1a34, 0x2d1b1b36, 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b,
-	0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d, 0x7b292952, 0x3ee3e3dd,
-	0x712f2f5e, 0x97848413, 0xf55353a6, 0x68d1d1b9, 0x0, 0x2cededc1,
-	0x60202040, 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6, 0xbe6a6ad4, 0x46cbcb8d,
-	0xd9bebe67, 0x4b393972, 0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85,
-	0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed, 0xc5434386, 0xd74d4d9a,
-	0x55333366, 0x94858511, 0xcf45458a, 0x10f9f9e9, 0x6020204, 0x817f7ffe,
-	0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b, 0xf35151a2, 0xfea3a35d,
-	0xc0404080, 0x8a8f8f05, 0xad92923f, 0xbc9d9d21, 0x48383870, 0x4f5f5f1,
-	0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142, 0x30101020, 0x1affffe5,
-	0xef3f3fd, 0x6dd2d2bf, 0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3,
-	0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e, 0x57c4c493, 0xf2a7a755,
-	0x827e7efc, 0x473d3d7a, 0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6,
-	0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3, 0x66222244, 0x7e2a2a54,
-	0xab90903b, 0x8388880b, 0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428,
-	0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad, 0x3be0e0db, 0x56323264,
-	0x4e3a3a74, 0x1e0a0a14, 0xdb494992, 0xa06060c, 0x6c242448, 0xe45c5cb8,
-	0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4, 0xa8919139, 0xa4959531,
-	0x37e4e4d3, 0x8b7979f2, 0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda,
-	0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949, 0xb46c6cd8, 0xfa5656ac,
-	0x7f4f4f3, 0x25eaeacf, 0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810,
-	0xd5baba6f, 0x887878f0, 0x6f25254a, 0x722e2e5c, 0x241c1c38, 0xf1a6a657,
-	0xc7b4b473, 0x51c6c697, 0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e,
-	0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f, 0x907070e0, 0x423e3e7c,
-	0xc4b5b571, 0xaa6666cc, 0xd8484890, 0x5030306, 0x1f6f6f7, 0x120e0e1c,
-	0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969, 0x91868617, 0x58c1c199,
-	0x271d1d3a, 0xb99e9e27, 0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122,
-	0xbb6969d2, 0x70d9d9a9, 0x898e8e07, 0xa7949433, 0xb69b9b2d, 0x221e1e3c,
-	0x92878715, 0x20e9e9c9, 0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5,
-	0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a, 0xdabfbf65, 0x31e6e6d7,
-	0xc6424284, 0xb86868d0, 0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e,
-	0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c}
-
-var aes_rtable = [...]uint32{
-	0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a, 0xcb6bab3b, 0xf1459d1f,
-	0xab58faac, 0x9303e34b, 0x55fa3020, 0xf66d76ad, 0x9176cc88, 0x254c02f5,
-	0xfcd7e54f, 0xd7cb2ac5, 0x80443526, 0x8fa362b5, 0x495ab1de, 0x671bba25,
-	0x980eea45, 0xe1c0fe5d, 0x2752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b,
-	0xe75f8f03, 0x959c9215, 0xeb7a6dbf, 0xda595295, 0x2d83bed4, 0xd3217458,
-	0x2969e049, 0x44c8c98e, 0x6a89c275, 0x78798ef4, 0x6b3e5899, 0xdd71b927,
-	0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d, 0x184adf63, 0x82311ae5,
-	0x60335197, 0x457f5362, 0xe07764b1, 0x84ae6bbb, 0x1ca081fe, 0x942b08f9,
-	0x58684870, 0x19fd458f, 0x876cde94, 0xb7f87b52, 0x23d373ab, 0xe2024b72,
-	0x578f1fe3, 0x2aab5566, 0x728ebb2, 0x3c2b52f, 0x9a7bc586, 0xa50837d3,
-	0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed, 0x2b1ccf8a, 0x92b479a7,
-	0xf0f207f3, 0xa1e2694e, 0xcdf4da65, 0xd5be0506, 0x1f6234d1, 0x8afea6c4,
-	0x9d532e34, 0xa055f3a2, 0x32e18a05, 0x75ebf6a4, 0x39ec830b, 0xaaef6040,
-	0x69f715e, 0x51106ebd, 0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d,
-	0xb58d5491, 0x55dc471, 0x6fd40604, 0xff155060, 0x24fb9819, 0x97e9bdd6,
-	0xcc434089, 0x779ed967, 0xbd42e8b0, 0x888b8907, 0x385b19e7, 0xdbeec879,
-	0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x0, 0x83868009, 0x48ed2b32,
-	0xac70111e, 0x4e725a6c, 0xfbff0efd, 0x5638850f, 0x1ed5ae3d, 0x27392d36,
-	0x64d90f0a, 0x21a65c68, 0xd1545b9b, 0x3a2e3624, 0xb1670a0c, 0xfe75793,
-	0xd296eeb4, 0x9e919b1b, 0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c,
-	0xaba93e2, 0xe52aa0c0, 0x43e0223c, 0x1d171b12, 0xb0d090e, 0xadc78bf2,
-	0xb9a8b62d, 0xc8a91e14, 0x8519f157, 0x4c0775af, 0xbbdd99ee, 0xfd607fa3,
-	0x9f2601f7, 0xbcf5725c, 0xc53b6644, 0x347efb5b, 0x7629438b, 0xdcc623cb,
-	0x68fcedb6, 0x63f1e4b8, 0xcadc31d7, 0x10856342, 0x40229713, 0x2011c684,
-	0x7d244a85, 0xf83dbbd2, 0x1132f9ae, 0x6da129c7, 0x4b2f9e1d, 0xf330b2dc,
-	0xec52860d, 0xd0e3c177, 0x6c16b32b, 0x99b970a9, 0xfa489411, 0x2264e947,
-	0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, 0xef903322, 0xc74e4987, 0xc1d138d9,
-	0xfea2ca8c, 0x360bd498, 0xcf81f5a6, 0x28de7aa5, 0x268eb7da, 0xa4bfad3f,
-	0xe49d3a2c, 0xd927850, 0x9bcc5f6a, 0x62467e54, 0xc2138df6, 0xe8b8d890,
-	0x5ef7392e, 0xf5afc382, 0xbe805d9f, 0x7c93d069, 0xa92dd56f, 0xb31225cf,
-	0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb, 0x97826cd, 0xf418596e,
-	0x1b79aec, 0xa89a4f83, 0x656e95e6, 0x7ee6ffaa, 0x8cfbc21, 0xe6e815ef,
-	0xd99be7ba, 0xce366f4a, 0xd4099fea, 0xd67cb029, 0xafb2a431, 0x31233f2a,
-	0x3094a5c6, 0xc066a235, 0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733,
-	0x4a9804f1, 0xf7daec41, 0xe50cd7f, 0x2ff69117, 0x8dd64d76, 0x4db0ef43,
-	0x544daacc, 0xdf0496e4, 0xe3b5d19e, 0x1b886a4c, 0xb81f2cc1, 0x7f516546,
-	0x4ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb, 0x5a1d67b3, 0x52d2db92,
-	0x335610e9, 0x1347d66d, 0x8c61d79a, 0x7a0ca137, 0x8e14f859, 0x893c13eb,
-	0xee27a9ce, 0x35c961b7, 0xede51ce1, 0x3cb1477a, 0x59dfd29c, 0x3f73f255,
-	0x79ce1418, 0xbf37c773, 0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478,
-	0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2, 0x72c31d16, 0xc25e2bc,
-	0x8b493c28, 0x41950dff, 0x7101a839, 0xdeb30c08, 0x9ce4b4d8, 0x90c15664,
-	0x6184cb7b, 0x70b632d5, 0x745c6c48, 0x4257b8d0}
-
-type AES struct {
-	mode int
-	fkey [44]uint32
-	rkey [44]uint32
-	f    [16]byte
-}
-
-/* Rotates 32-bit word left by 1, 2 or 3 byte  */
-
-func aes_ROTL8(x uint32) uint32 {
-	return (((x) << 8) | ((x) >> 24))
-}
-
-func aes_ROTL16(x uint32) uint32 {
-	return (((x) << 16) | ((x) >> 16))
-}
-
-func aes_ROTL24(x uint32) uint32 {
-	return (((x) << 24) | ((x) >> 8))
-}
-
-func aes_pack(b [4]byte) uint32 { /* pack bytes into a 32-bit Word */
-	return ((uint32(b[3]) & 0xff) << 24) | ((uint32(b[2]) & 0xff) << 16) | ((uint32(b[1]) & 0xff) << 8) | (uint32(b[0]) & 0xff)
-}
-
-func aes_unpack(a uint32) [4]byte { /* unpack bytes from a word */
-	var b = [4]byte{byte(a & 0xff), byte((a >> 8) & 0xff), byte((a >> 16) & 0xff), byte((a >> 24) & 0xff)}
-	return b
-}
-
-func aes_bmul(x byte, y byte) byte { /* x.y= AntiLog(Log(x) + Log(y)) */
-
-	ix := int(x) & 0xff
-	iy := int(y) & 0xff
-	lx := int(aes_ltab[ix]) & 0xff
-	ly := int(aes_ltab[iy]) & 0xff
-
-	if x != 0 && y != 0 {
-		return aes_ptab[(lx+ly)%255]
-	} else {
-		return byte(0)
-	}
-}
-
-func aes_SubByte(a uint32) uint32 {
-	b := aes_unpack(a)
-	b[0] = aes_fbsub[int(b[0])]
-	b[1] = aes_fbsub[int(b[1])]
-	b[2] = aes_fbsub[int(b[2])]
-	b[3] = aes_fbsub[int(b[3])]
-	return aes_pack(b)
-}
-
-func aes_product(x uint32, y uint32) byte { /* dot product of two 4-byte arrays */
-	xb := aes_unpack(x)
-	yb := aes_unpack(y)
-
-	return (aes_bmul(xb[0], yb[0]) ^ aes_bmul(xb[1], yb[1]) ^ aes_bmul(xb[2], yb[2]) ^ aes_bmul(xb[3], yb[3]))
-}
-
-func aes_InvMixCol(x uint32) uint32 { /* matrix Multiplication */
-	var b [4]byte
-	m := aes_pack(aes_InCo)
-	b[3] = aes_product(m, x)
-	m = aes_ROTL24(m)
-	b[2] = aes_product(m, x)
-	m = aes_ROTL24(m)
-	b[1] = aes_product(m, x)
-	m = aes_ROTL24(m)
-	b[0] = aes_product(m, x)
-	var y = aes_pack(b)
-	return y
-}
-
-/* reset cipher */
-func (A *AES) Reset(m int, iv []byte) { /* reset mode, or reset iv */
-	A.mode = m
-	for i := 0; i < 16; i++ {
-		A.f[i] = 0
-	}
-	if (A.mode != aes_ECB) && (iv != nil) {
-		for i := 0; i < 16; i++ {
-			A.f[i] = iv[i]
-		}
-	}
-}
-
-func (A *AES) Init(m int, key []byte, iv []byte) { /* Key=16 bytes */
-	/* Key Scheduler. Create expanded encryption key */
-	var CipherKey [4]uint32
-	var b [4]byte
-	nk := 4
-	A.Reset(m, iv)
-	N := 44
-
-	j := 0
-	for i := 0; i < nk; i++ {
-		for k := 0; k < 4; k++ {
-			b[k] = key[j+k]
-		}
-		CipherKey[i] = aes_pack(b)
-		j += 4
-	}
-	for i := 0; i < nk; i++ {
-		A.fkey[i] = CipherKey[i]
-	}
-	j = nk
-	for k := 0; j < N; k++ {
-		A.fkey[j] = A.fkey[j-nk] ^ aes_SubByte(aes_ROTL24(A.fkey[j-1])) ^ uint32(aes_rco[k])
-		for i := 1; i < nk && (i+j) < N; i++ {
-			A.fkey[i+j] = A.fkey[i+j-nk] ^ A.fkey[i+j-1]
-		}
-		j += nk
-	}
-
-	/* now for the expanded decrypt key in reverse order */
-
-	for j := 0; j < 4; j++ {
-		A.rkey[j+N-4] = A.fkey[j]
-	}
-	for i := 4; i < N-4; i += 4 {
-		k := N - 4 - i
-		for j := 0; j < 4; j++ {
-			A.rkey[k+j] = aes_InvMixCol(A.fkey[i+j])
-		}
-	}
-	for j := N - 4; j < N; j++ {
-		A.rkey[j-N+4] = A.fkey[j]
-	}
-}
-
-func NewAES() *AES {
-	var A = new(AES)
-	return A
-}
-
-func (A *AES) Getreg() [16]byte {
-	var ir [16]byte
-	for i := 0; i < 16; i++ {
-		ir[i] = A.f[i]
-	}
-	return ir
-}
-
-/* Encrypt a single block */
-func (A *AES) ecb_encrypt(buff []byte) {
-	var b [4]byte
-	var p [4]uint32
-	var q [4]uint32
-
-	j := 0
-	for i := 0; i < 4; i++ {
-		for k := 0; k < 4; k++ {
-			b[k] = buff[j+k]
-		}
-		p[i] = aes_pack(b)
-		p[i] ^= A.fkey[i]
-		j += 4
-	}
-
-	k := 4
-
-	/* State alternates between p and q */
-	for i := 1; i < 10; i++ {
-		q[0] = A.fkey[k] ^ aes_ftable[int(p[0]&0xff)] ^ aes_ROTL8(aes_ftable[int((p[1]>>8)&0xff)]) ^ aes_ROTL16(aes_ftable[int((p[2]>>16)&0xff)]) ^ aes_ROTL24(aes_ftable[int((p[3]>>24)&0xff)])
-
-		q[1] = A.fkey[k+1] ^ aes_ftable[int(p[1]&0xff)] ^ aes_ROTL8(aes_ftable[int((p[2]>>8)&0xff)]) ^ aes_ROTL16(aes_ftable[int((p[3]>>16)&0xff)]) ^ aes_ROTL24(aes_ftable[int((p[0]>>24)&0xff)])
-
-		q[2] = A.fkey[k+2] ^ aes_ftable[int(p[2]&0xff)] ^ aes_ROTL8(aes_ftable[int((p[3]>>8)&0xff)]) ^ aes_ROTL16(aes_ftable[int((p[0]>>16)&0xff)]) ^ aes_ROTL24(aes_ftable[int((p[1]>>24)&0xff)])
-
-		q[3] = A.fkey[k+3] ^ aes_ftable[int(p[3]&0xff)] ^ aes_ROTL8(aes_ftable[int((p[0]>>8)&0xff)]) ^ aes_ROTL16(aes_ftable[int((p[1]>>16)&0xff)]) ^ aes_ROTL24(aes_ftable[int((p[2]>>24)&0xff)])
-
-		k += 4
-		for j = 0; j < 4; j++ {
-			t := p[j]
-			p[j] = q[j]
-			q[j] = t
-		}
-	}
-
-	/* Last Round */
-
-	q[0] = A.fkey[k] ^ uint32(aes_fbsub[int(p[0]&0xff)]) ^ aes_ROTL8(uint32(aes_fbsub[int((p[1]>>8)&0xff)])) ^ aes_ROTL16(uint32(aes_fbsub[int((p[2]>>16)&0xff)])) ^ aes_ROTL24(uint32(aes_fbsub[int((p[3]>>24)&0xff)]))
-
-	q[1] = A.fkey[k+1] ^ uint32(aes_fbsub[int(p[1]&0xff)]) ^ aes_ROTL8(uint32(aes_fbsub[int((p[2]>>8)&0xff)])) ^ aes_ROTL16(uint32(aes_fbsub[int((p[3]>>16)&0xff)])) ^ aes_ROTL24(uint32(aes_fbsub[int((p[0]>>24)&0xff)]))
-
-	q[2] = A.fkey[k+2] ^ uint32(aes_fbsub[int(p[2]&0xff)]) ^ aes_ROTL8(uint32(aes_fbsub[int((p[3]>>8)&0xff)])) ^ aes_ROTL16(uint32(aes_fbsub[int((p[0]>>16)&0xff)])) ^ aes_ROTL24(uint32(aes_fbsub[int((p[1]>>24)&0xff)]))
-
-	q[3] = A.fkey[k+3] ^ uint32(aes_fbsub[int(p[3]&0xff)]) ^ aes_ROTL8(uint32(aes_fbsub[int((p[0]>>8)&0xff)])) ^ aes_ROTL16(uint32(aes_fbsub[int((p[1]>>16)&0xff)])) ^ aes_ROTL24(uint32(aes_fbsub[int((p[2]>>24)&0xff)]))
-
-	j = 0
-	for i := 0; i < 4; i++ {
-		b = aes_unpack(q[i])
-		for k = 0; k < 4; k++ {
-			buff[j+k] = b[k]
-		}
-		j += 4
-	}
-}
-
-/* Decrypt a single block */
-func (A *AES) ecb_decrypt(buff []byte) {
-	var b [4]byte
-	var p [4]uint32
-	var q [4]uint32
-
-	j := 0
-	for i := 0; i < 4; i++ {
-		for k := 0; k < 4; k++ {
-			b[k] = buff[j+k]
-		}
-		p[i] = aes_pack(b)
-		p[i] ^= A.rkey[i]
-		j += 4
-	}
-
-	k := 4
-
-	/* State alternates between p and q */
-	for i := 1; i < 10; i++ {
-
-		q[0] = A.rkey[k] ^ aes_rtable[int(p[0]&0xff)] ^ aes_ROTL8(aes_rtable[int((p[3]>>8)&0xff)]) ^ aes_ROTL16(aes_rtable[int((p[2]>>16)&0xff)]) ^ aes_ROTL24(aes_rtable[int((p[1]>>24)&0xff)])
-
-		q[1] = A.rkey[k+1] ^ aes_rtable[int(p[1]&0xff)] ^ aes_ROTL8(aes_rtable[int((p[0]>>8)&0xff)]) ^ aes_ROTL16(aes_rtable[int((p[3]>>16)&0xff)]) ^ aes_ROTL24(aes_rtable[int((p[2]>>24)&0xff)])
-
-		q[2] = A.rkey[k+2] ^ aes_rtable[int(p[2]&0xff)] ^ aes_ROTL8(aes_rtable[int((p[1]>>8)&0xff)]) ^ aes_ROTL16(aes_rtable[int((p[0]>>16)&0xff)]) ^ aes_ROTL24(aes_rtable[int((p[3]>>24)&0xff)])
-
-		q[3] = A.rkey[k+3] ^ aes_rtable[int(p[3]&0xff)] ^ aes_ROTL8(aes_rtable[int((p[2]>>8)&0xff)]) ^ aes_ROTL16(aes_rtable[int((p[1]>>16)&0xff)]) ^ aes_ROTL24(aes_rtable[int((p[0]>>24)&0xff)])
-
-		k += 4
-		for j := 0; j < 4; j++ {
-			t := p[j]
-			p[j] = q[j]
-			q[j] = t
-		}
-	}
-
-	/* Last Round */
-
-	q[0] = A.rkey[k] ^ uint32(aes_rbsub[int(p[0]&0xff)]) ^ aes_ROTL8(uint32(aes_rbsub[int((p[3]>>8)&0xff)])) ^ aes_ROTL16(uint32(aes_rbsub[int((p[2]>>16)&0xff)])) ^ aes_ROTL24(uint32(aes_rbsub[int((p[1]>>24)&0xff)]))
-
-	q[1] = A.rkey[k+1] ^ uint32(aes_rbsub[int(p[1]&0xff)]) ^ aes_ROTL8(uint32(aes_rbsub[int((p[0]>>8)&0xff)])) ^ aes_ROTL16(uint32(aes_rbsub[int((p[3]>>16)&0xff)])) ^ aes_ROTL24(uint32(aes_rbsub[int((p[2]>>24)&0xff)]))
-
-	q[2] = A.rkey[k+2] ^ uint32(aes_rbsub[int(p[2]&0xff)]) ^ aes_ROTL8(uint32(aes_rbsub[int((p[1]>>8)&0xff)])) ^ aes_ROTL16(uint32(aes_rbsub[int((p[0]>>16)&0xff)])) ^ aes_ROTL24(uint32(aes_rbsub[int((p[3]>>24)&0xff)]))
-
-	q[3] = A.rkey[k+3] ^ uint32(aes_rbsub[int((p[3])&0xff)]) ^ aes_ROTL8(uint32(aes_rbsub[int((p[2]>>8)&0xff)])) ^ aes_ROTL16(uint32(aes_rbsub[int((p[1]>>16)&0xff)])) ^ aes_ROTL24(uint32(aes_rbsub[int((p[0]>>24)&0xff)]))
-
-	j = 0
-	for i := 0; i < 4; i++ {
-		b = aes_unpack(q[i])
-		for k := 0; k < 4; k++ {
-			buff[j+k] = b[k]
-		}
-		j += 4
-	}
-}
-
-/* Encrypt using selected mode of operation */
-func (A *AES) Encrypt(buff []byte) uint32 {
-	var st [16]byte
-
-	// Supported Modes of Operation
-
-	var fell_off uint32 = 0
-	switch A.mode {
-	case aes_ECB:
-		A.ecb_encrypt(buff)
-		return 0
-	case aes_CBC:
-		for j := 0; j < 16; j++ {
-			buff[j] ^= A.f[j]
-		}
-		A.ecb_encrypt(buff)
-		for j := 0; j < 16; j++ {
-			A.f[j] = buff[j]
-		}
-		return 0
-
-	case aes_CFB1:
-		fallthrough
-	case aes_CFB2:
-		fallthrough
-	case aes_CFB4:
-		bytes := A.mode - aes_CFB1 + 1
-		for j := 0; j < bytes; j++ {
-			fell_off = (fell_off << 8) | uint32(A.f[j])
-		}
-		for j := 0; j < 16; j++ {
-			st[j] = A.f[j]
-		}
-		for j := bytes; j < 16; j++ {
-			A.f[j-bytes] = A.f[j]
-		}
-		A.ecb_encrypt(st[:])
-		for j := 0; j < bytes; j++ {
-			buff[j] ^= st[j]
-			A.f[16-bytes+j] = buff[j]
-		}
-		return fell_off
-
-	case aes_OFB1:
-		fallthrough
-	case aes_OFB2:
-		fallthrough
-	case aes_OFB4:
-		fallthrough
-	case aes_OFB8:
-		fallthrough
-	case aes_OFB16:
-
-		bytes := A.mode - aes_OFB1 + 1
-		A.ecb_encrypt(A.f[:])
-		for j := 0; j < bytes; j++ {
-			buff[j] ^= A.f[j]
-		}
-		return 0
-
-	default:
-		return 0
-	}
-}
-
-/* Decrypt using selected mode of operation */
-func (A *AES) Decrypt(buff []byte) uint32 {
-
-	var st [16]byte
-
-	// Supported Modes of Operation
-
-	var fell_off uint32 = 0
-	switch A.mode {
-	case aes_ECB:
-		A.ecb_decrypt(buff)
-		return 0
-	case aes_CBC:
-		for j := 0; j < 16; j++ {
-			st[j] = A.f[j]
-			A.f[j] = buff[j]
-		}
-		A.ecb_decrypt(buff)
-		for j := 0; j < 16; j++ {
-			buff[j] ^= st[j]
-			st[j] = 0
-		}
-		return 0
-	case aes_CFB1:
-		fallthrough
-	case aes_CFB2:
-		fallthrough
-	case aes_CFB4:
-		bytes := A.mode - aes_CFB1 + 1
-		for j := 0; j < bytes; j++ {
-			fell_off = (fell_off << 8) | uint32(A.f[j])
-		}
-		for j := 0; j < 16; j++ {
-			st[j] = A.f[j]
-		}
-		for j := bytes; j < 16; j++ {
-			A.f[j-bytes] = A.f[j]
-		}
-		A.ecb_encrypt(st[:])
-		for j := 0; j < bytes; j++ {
-			A.f[16-bytes+j] = buff[j]
-			buff[j] ^= st[j]
-		}
-		return fell_off
-	case aes_OFB1:
-		fallthrough
-	case aes_OFB2:
-		fallthrough
-	case aes_OFB4:
-		fallthrough
-	case aes_OFB8:
-		fallthrough
-	case aes_OFB16:
-		bytes := A.mode - aes_OFB1 + 1
-		A.ecb_encrypt(A.f[:])
-		for j := 0; j < bytes; j++ {
-			buff[j] ^= A.f[j]
-		}
-		return 0
-
-	default:
-		return 0
-	}
-}
-
-/* Clean up and delete left-overs */
-func (A *AES) End() { // clean up
-	for i := 0; i < 44; i++ {
-		A.fkey[i] = 0
-		A.rkey[i] = 0
-	}
-	for i := 0; i < 16; i++ {
-		A.f[i] = 0
-	}
-}
-
-/*
-func main() {
-	var key [16]byte
-	var block [16]byte
-	var iv [16]byte
-
-	for i:=0;i<16;i++ {key[i]=0}
-	key[0]=1
-	for i:=0;i<16;i++ {iv[i]=byte(i)}
-	for i:=0;i<16;i++ {block[i]=byte(i)}
-
-	a:=NewAES()
-
-	a.Init(aes_CBC,key[:],iv[:])
-	fmt.Printf("Plain= \n")
-	for i:=0;i<16;i++  {fmt.Printf("%02X ", block[i]&0xff)}
-	fmt.Printf("\n")
-
-	a.Encrypt(block[:])
-
-	fmt.Printf("Encrypt= \n")
-	for i:=0;i<16;i++  {fmt.Printf("%02X ", block[i]&0xff)}
-	fmt.Printf("\n")
-
-	a.Reset(aes_CBC,iv[:])
-	a.Decrypt(block[:])
-
-	fmt.Printf("Decrypt= \n")
-	for i:=0;i<16;i++  {fmt.Printf("%02X ", block[i]&0xff)}
-	fmt.Printf("\n")
-
-	a.End();
-}
-*/
diff --git a/go/amcl-go/BIG.go b/go/amcl-go/BIG.go
deleted file mode 100644
index a1c5184..0000000
--- a/go/amcl-go/BIG.go
+++ /dev/null
@@ -1,956 +0,0 @@
-/*
-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.
-*/
-
-/* AMCL BIG number class */
-
-package amcl
-
-import "strconv"
-
-//import "fmt"
-
-type BIG struct {
-	w [NLEN]int64
-}
-
-func NewBIG() *BIG {
-	b := new(BIG)
-	for i := 0; i < NLEN; i++ {
-		b.w[i] = 0
-	}
-	return b
-}
-
-func NewBIGint(x int) *BIG {
-	b := new(BIG)
-	b.w[0] = int64(x)
-	for i := 1; i < NLEN; i++ {
-		b.w[i] = 0
-	}
-	return b
-}
-
-func NewBIGcopy(x *BIG) *BIG {
-	b := new(BIG)
-	for i := 0; i < NLEN; i++ {
-		b.w[i] = x.w[i]
-	}
-	return b
-}
-
-func NewBIGdcopy(x *DBIG) *BIG {
-	b := new(BIG)
-	for i := 0; i < NLEN; i++ {
-		b.w[i] = x.w[i]
-	}
-	return b
-}
-
-func NewBIGints(x [NLEN]int64) *BIG {
-	b := new(BIG)
-	for i := 0; i < NLEN; i++ {
-		b.w[i] = x[i]
-	}
-	return b
-}
-
-func (r *BIG) get(i int) int64 {
-	return r.w[i]
-}
-
-func (r *BIG) set(i int, x int64) {
-	r.w[i] = x
-}
-
-func (r *BIG) xortop(x int64) {
-	r.w[NLEN-1] ^= x
-}
-
-func (r *BIG) ortop(x int64) {
-	r.w[NLEN-1] |= x
-}
-
-/* test for zero */
-func (r *BIG) iszilch() bool {
-	for i := 0; i < NLEN; i++ {
-		if r.w[i] != 0 {
-			return false
-		}
-	}
-	return true
-}
-
-/* set to zero */
-func (r *BIG) zero() {
-	for i := 0; i < NLEN; i++ {
-		r.w[i] = 0
-	}
-}
-
-/* Test for equal to one */
-func (r *BIG) isunity() bool {
-	for i := 1; i < NLEN; i++ {
-		if r.w[i] != 0 {
-			return false
-		}
-	}
-	if r.w[0] != 1 {
-		return false
-	}
-	return true
-}
-
-/* set to one */
-func (r *BIG) one() {
-	r.w[0] = 1
-	for i := 1; i < NLEN; i++ {
-		r.w[i] = 0
-	}
-}
-
-/* Copy from another BIG */
-func (r *BIG) copy(x *BIG) {
-	for i := 0; i < NLEN; i++ {
-		r.w[i] = x.w[i]
-	}
-}
-
-/* Copy from another DBIG */
-func (r *BIG) dcopy(x *DBIG) {
-	for i := 0; i < NLEN; i++ {
-		r.w[i] = x.w[i]
-	}
-}
-
-/* calculate Field Excess */
-func EXCESS(a *BIG) int64 {
-	return ((a.w[NLEN-1] & OMASK) >> (MODBITS % BASEBITS))
-}
-
-/* normalise BIG - force all digits < 2^BASEBITS */
-func (r *BIG) norm() int64 {
-	var carry int64 = 0
-	for i := 0; i < NLEN-1; i++ {
-		d := r.w[i] + carry
-		r.w[i] = d & MASK
-		carry = d >> BASEBITS
-	}
-	r.w[NLEN-1] = (r.w[NLEN-1] + carry)
-
-	return (r.w[NLEN-1] >> ((8 * MODBYTES) % BASEBITS))
-}
-
-/* Conditional swap of two bigs depending on d using XOR - no branches */
-func (r *BIG) cswap(b *BIG, d int32) {
-	var c = int64(d)
-	c = ^(c - 1)
-
-	for i := 0; i < NLEN; i++ {
-		t := c & (r.w[i] ^ b.w[i])
-		r.w[i] ^= t
-		b.w[i] ^= t
-	}
-}
-
-func (r *BIG) cmove(g *BIG, d int32) {
-	var b = int64(-d)
-
-	for i := 0; i < NLEN; i++ {
-		r.w[i] ^= (r.w[i] ^ g.w[i]) & b
-	}
-}
-
-/* Shift right by less than a word */
-func (r *BIG) fshr(k uint) int64 {
-	w := r.w[0] & ((int64(1) << k) - 1) /* shifted out part */
-	for i := 0; i < NLEN-1; i++ {
-		r.w[i] = (r.w[i] >> k) | ((r.w[i+1] << (BASEBITS - k)) & MASK)
-	}
-	r.w[NLEN-1] = r.w[NLEN-1] >> k
-	return w
-}
-
-/* general shift right */
-func (r *BIG) shr(k uint) {
-	n := (k % BASEBITS)
-	m := int(k / BASEBITS)
-	for i := 0; i < NLEN-m-1; i++ {
-		r.w[i] = (r.w[m+i] >> n) | ((r.w[m+i+1] << (BASEBITS - n)) & MASK)
-	}
-	r.w[NLEN-m-1] = r.w[NLEN-1] >> n
-	for i := NLEN - m; i < NLEN; i++ {
-		r.w[i] = 0
-	}
-}
-
-/* Shift right by less than a word */
-func (r *BIG) fshl(k uint) int64 {
-	r.w[NLEN-1] = (r.w[NLEN-1] << k) | (r.w[NLEN-2] >> (BASEBITS - k))
-	for i := NLEN - 2; i > 0; i-- {
-		r.w[i] = ((r.w[i] << k) & MASK) | (r.w[i-1] >> (BASEBITS - k))
-	}
-	r.w[0] = (r.w[0] << k) & MASK
-	return (r.w[NLEN-1] >> ((8 * MODBYTES) % BASEBITS)) /* return excess - only used in ff.c */
-}
-
-/* general shift left */
-func (r *BIG) shl(k uint) {
-	n := k % BASEBITS
-	m := int(k / BASEBITS)
-
-	r.w[NLEN-1] = (r.w[NLEN-1-m] << n) | (r.w[NLEN-m-2] >> (BASEBITS - n))
-	for i := NLEN - 2; i > m; i-- {
-		r.w[i] = ((r.w[i-m] << n) & MASK) | (r.w[i-m-1] >> (BASEBITS - n))
-	}
-	r.w[m] = (r.w[0] << n) & MASK
-	for i := 0; i < m; i++ {
-		r.w[i] = 0
-	}
-}
-
-/* return number of bits */
-func (r *BIG) nbits() int {
-	k := NLEN - 1
-	r.norm()
-	for k >= 0 && r.w[k] == 0 {
-		k--
-	}
-	if k < 0 {
-		return 0
-	}
-	bts := int(BASEBITS) * k
-	c := r.w[k]
-	for c != 0 {
-		c /= 2
-		bts++
-	}
-	return bts
-}
-
-/* Convert to Hex String */
-func (r *BIG) toString() string {
-	s := ""
-	len := r.nbits()
-
-	if len%4 == 0 {
-		len /= 4
-	} else {
-		len /= 4
-		len++
-
-	}
-	MB := int(MODBYTES * 2)
-	if len < MB {
-		len = MB
-	}
-
-	for i := len - 1; i >= 0; i-- {
-		b := NewBIGcopy(r)
-
-		b.shr(uint(i * 4))
-		s += strconv.FormatInt(b.w[0]&15, 16)
-	}
-	return s
-}
-
-func (r *BIG) add(x *BIG) {
-	for i := 0; i < NLEN; i++ {
-		r.w[i] = r.w[i] + x.w[i]
-	}
-}
-
-/* return this+x */
-func (r *BIG) plus(x *BIG) *BIG {
-	s := new(BIG)
-	for i := 0; i < NLEN; i++ {
-		s.w[i] = r.w[i] + x.w[i]
-	}
-	return s
-}
-
-/* this+=x, where x is int */
-func (r *BIG) inc(x int) {
-	r.norm()
-	r.w[0] += int64(x)
-}
-
-/* return this-x */
-func (r *BIG) minus(x *BIG) *BIG {
-	d := new(BIG)
-	for i := 0; i < NLEN; i++ {
-		d.w[i] = r.w[i] - x.w[i]
-	}
-	return d
-}
-
-/* this-=x */
-func (r *BIG) sub(x *BIG) {
-	for i := 0; i < NLEN; i++ {
-		r.w[i] = r.w[i] - x.w[i]
-	}
-}
-
-/* reverse subtract this=x-this */
-func (r *BIG) rsub(x *BIG) {
-	for i := 0; i < NLEN; i++ {
-		r.w[i] = x.w[i] - r.w[i]
-	}
-}
-
-/* this-=x, where x is int */
-func (r *BIG) dec(x int) {
-	r.norm()
-	r.w[0] -= int64(x)
-}
-
-/* this*=x, where x is small int<NEXCESS */
-func (r *BIG) imul(c int) {
-	for i := 0; i < NLEN; i++ {
-		r.w[i] *= int64(c)
-	}
-}
-
-/* convert this BIG to byte array */
-func (r *BIG) tobytearray(b []byte, n int) {
-	r.norm()
-	c := NewBIGcopy(r)
-
-	for i := int(MODBYTES) - 1; i >= 0; i-- {
-		b[i+n] = byte(c.w[0])
-		c.fshr(8)
-	}
-}
-
-/* convert from byte array to BIG */
-func frombytearray(b []byte, n int) *BIG {
-	m := NewBIG()
-	for i := 0; i < int(MODBYTES); i++ {
-		m.fshl(8)
-		m.w[0] += int64(b[i+n] & 0xff)
-	}
-	return m
-}
-
-func (r *BIG) toBytes(b []byte) {
-	r.tobytearray(b, 0)
-}
-
-func fromBytes(b []byte) *BIG {
-	return frombytearray(b, 0)
-}
-
-/* set this[i]+=x*y+c, and return high part */
-
-func (r *BIG) muladd(a int64, b int64, c int64, i int) int64 {
-	x0 := a & HMASK
-	x1 := (a >> HBITS)
-	y0 := b & HMASK
-	y1 := (b >> HBITS)
-	bot := x0 * y0
-	top := x1 * y1
-	mid := x0*y1 + x1*y0
-	x0 = mid & HMASK
-	x1 = (mid >> HBITS)
-	bot += x0 << HBITS
-	bot += c
-	bot += r.w[i]
-	top += x1
-	carry := bot >> BASEBITS
-	bot &= MASK
-	top += carry
-	r.w[i] = bot
-	return top
-}
-
-/* this*=x, where x is >NEXCESS */
-func (r *BIG) pmul(c int) int64 {
-	var carry int64 = 0
-	r.norm()
-	for i := 0; i < NLEN; i++ {
-		ak := r.w[i]
-		r.w[i] = 0
-		carry = r.muladd(ak, int64(c), carry, i)
-	}
-	return carry
-}
-
-/* this*=c and catch overflow in DBIG */
-func (r *BIG) pxmul(c int) *DBIG {
-	m := NewDBIG()
-	var carry int64 = 0
-	for j := 0; j < NLEN; j++ {
-		carry = m.muladd(r.w[j], int64(c), carry, j)
-	}
-	m.w[NLEN] = carry
-	return m
-}
-
-/* divide by 3 */
-func (r *BIG) div3() int {
-	var carry int64 = 0
-	r.norm()
-	base := (int64(1) << BASEBITS)
-	for i := NLEN - 1; i >= 0; i-- {
-		ak := (carry*base + r.w[i])
-		r.w[i] = ak / 3
-		carry = ak % 3
-	}
-	return int(carry)
-}
-
-/* return a*b where result fits in a BIG */
-func smul(a *BIG, b *BIG) *BIG {
-	var carry int64
-	c := NewBIG()
-	for i := 0; i < NLEN; i++ {
-		carry = 0
-		for j := 0; j < NLEN; j++ {
-			if i+j < NLEN {
-				carry = c.muladd(a.w[i], b.w[j], carry, i+j)
-			}
-		}
-	}
-	return c
-}
-
-/* Compare a and b, return 0 if a==b, -1 if a<b, +1 if a>b. Inputs must be normalised */
-func comp(a *BIG, b *BIG) int {
-	for i := NLEN - 1; i >= 0; i-- {
-		if a.w[i] == b.w[i] {
-			continue
-		}
-		if a.w[i] > b.w[i] {
-			return 1
-		} else {
-			return -1
-		}
-	}
-	return 0
-}
-
-/* return parity */
-func (r *BIG) parity() int {
-	return int(r.w[0] % 2)
-}
-
-/* return n-th bit */
-func (r *BIG) bit(n int) int {
-	if (r.w[n/int(BASEBITS)] & (int64(1) << (uint(n) % BASEBITS))) > 0 {
-		return 1
-	}
-	return 0
-}
-
-/* return n last bits */
-func (r *BIG) lastbits(n int) int {
-	msk := (1 << uint(n)) - 1
-	r.norm()
-	return (int(r.w[0])) & msk
-}
-
-/* set x = x mod 2^m */
-func (r *BIG) mod2m(m uint) {
-	wd := int(m / BASEBITS)
-	bt := m % BASEBITS
-	msk := (int64(1) << bt) - 1
-	r.w[wd] &= msk
-	for i := wd + 1; i < NLEN; i++ {
-		r.w[i] = 0
-	}
-}
-
-/* Arazi and Qi inversion mod 256 */
-func invmod256(a int) int {
-	var t1 int = 0
-	c := (a >> 1) & 1
-	t1 += c
-	t1 &= 1
-	t1 = 2 - t1
-	t1 <<= 1
-	U := t1 + 1
-
-	// i=2
-	b := a & 3
-	t1 = U * b
-	t1 >>= 2
-	c = (a >> 2) & 3
-	t2 := (U * c) & 3
-	t1 += t2
-	t1 *= U
-	t1 &= 3
-	t1 = 4 - t1
-	t1 <<= 2
-	U += t1
-
-	// i=4
-	b = a & 15
-	t1 = U * b
-	t1 >>= 4
-	c = (a >> 4) & 15
-	t2 = (U * c) & 15
-	t1 += t2
-	t1 *= U
-	t1 &= 15
-	t1 = 16 - t1
-	t1 <<= 4
-	U += t1
-
-	return U
-}
-
-/* a=1/a mod 2^256. This is very fast! */
-func (r *BIG) invmod2m() {
-	U := NewBIG()
-	b := NewBIG()
-	c := NewBIG()
-
-	U.inc(invmod256(r.lastbits(8)))
-
-	for i := 8; i < 256; i <<= 1 {
-		ui := uint(i)
-		b.copy(r)
-		b.mod2m(ui)
-		t1 := smul(U, b)
-		t1.shr(ui)
-		c.copy(r)
-		c.shr(ui)
-		c.mod2m(ui)
-
-		t2 := smul(U, c)
-		t2.mod2m(ui)
-		t1.add(t2)
-		b = smul(t1, U)
-		t1.copy(b)
-		t1.mod2m(ui)
-
-		t2.one()
-		t2.shl(ui)
-		t1.rsub(t2)
-		t1.norm()
-		t1.shl(ui)
-		U.add(t1)
-	}
-	r.copy(U)
-}
-
-/* reduce this mod m */
-func (r *BIG) mod(m *BIG) {
-	r.norm()
-	if comp(r, m) < 0 {
-		return
-	}
-
-	m.fshl(1)
-	k := 1
-
-	for comp(r, m) >= 0 {
-		m.fshl(1)
-		k++
-	}
-
-	for k > 0 {
-		m.fshr(1)
-		if comp(r, m) >= 0 {
-			r.sub(m)
-			r.norm()
-		}
-		k--
-	}
-}
-
-/* divide this by m */
-func (r *BIG) div(m *BIG) {
-	k := 0
-	r.norm()
-	e := NewBIGint(1)
-	b := NewBIGcopy(r)
-	r.zero()
-
-	for comp(b, m) >= 0 {
-		e.fshl(1)
-		m.fshl(1)
-		k++
-	}
-
-	for k > 0 {
-		m.fshr(1)
-		e.fshr(1)
-		if comp(b, m) >= 0 {
-			r.add(e)
-			r.norm()
-			b.sub(m)
-			b.norm()
-		}
-		k--
-	}
-}
-
-/* get 8*MODBYTES size random number */
-func random(rng *RAND) *BIG {
-	m := NewBIG()
-	var j int = 0
-	var r byte = 0
-	/* generate random BIG */
-	for i := 0; i < 8*int(MODBYTES); i++ {
-		if j == 0 {
-			r = rng.GetByte()
-		} else {
-			r >>= 1
-		}
-
-		b := int64(r & 1)
-		m.shl(1)
-		m.w[0] += b // m.inc(b)
-		j++
-		j &= 7
-	}
-	return m
-}
-
-/* Create random BIG in portable way, one bit at a time */
-func randomnum(q *BIG, rng *RAND) *BIG {
-	d := NewDBIG()
-	var j int = 0
-	var r byte = 0
-	for i := 0; i < 2*int(MODBITS); i++ {
-		if j == 0 {
-			r = rng.GetByte()
-		} else {
-			r >>= 1
-		}
-
-		b := int64(r & 1)
-		d.shl(1)
-		d.w[0] += b // m.inc(b);
-		j++
-		j &= 7
-	}
-	m := d.mod(q)
-	return m
-}
-
-/* return NAF value as +/- 1, 3 or 5. x and x3 should be normed.
-nbs is number of bits processed, and nzs is number of trailing 0s detected */
-func nafbits(x *BIG, x3 *BIG, i int) [3]int {
-	var n [3]int
-	var j int
-	nb := x3.bit(i) - x.bit(i)
-
-	n[1] = 1
-	n[0] = 0
-	if nb == 0 {
-		n[0] = 0
-		return n
-	}
-	if i == 0 {
-		n[0] = nb
-		return n
-	}
-	if nb > 0 {
-		n[0] = 1
-	} else {
-		n[0] = (-1)
-	}
-
-	for j = i - 1; j > 0; j-- {
-		n[1]++
-		n[0] *= 2
-		nb = x3.bit(j) - x.bit(j)
-		if nb > 0 {
-			n[0] += 1
-		}
-		if nb < 0 {
-			n[0] -= 1
-		}
-		if n[0] > 5 || n[0] < -5 {
-			break
-		}
-	}
-
-	if n[0]%2 != 0 && j != 0 { /* backtrack */
-		if nb > 0 {
-			n[0] = (n[0] - 1) / 2
-		}
-		if nb < 0 {
-			n[0] = (n[0] + 1) / 2
-		}
-		n[1]--
-	}
-	for n[0]%2 == 0 { /* remove trailing zeros */
-		n[0] /= 2
-		n[2]++
-		n[1]--
-	}
-	return n
-}
-
-/* return a*b as DBIG */
-func mul(a *BIG, b *BIG) *DBIG {
-	c := NewDBIG()
-	var carry int64
-	a.norm()
-	b.norm()
-
-	for i := 0; i < NLEN; i++ {
-		carry = 0
-		for j := 0; j < NLEN; j++ {
-			carry = c.muladd(a.w[i], b.w[j], carry, i+j)
-		}
-		c.w[NLEN+i] = carry
-	}
-
-	return c
-}
-
-/* return a^2 as DBIG */
-func sqr(a *BIG) *DBIG {
-	c := NewDBIG()
-	var carry int64
-	a.norm()
-	for i := 0; i < NLEN; i++ {
-		carry = 0
-		for j := i + 1; j < NLEN; j++ {
-			carry = c.muladd(2*a.w[i], a.w[j], carry, i+j)
-		}
-		c.w[NLEN+i] = carry
-	}
-
-	for i := 0; i < NLEN; i++ {
-		c.w[2*i+1] += c.muladd(a.w[i], a.w[i], 0, 2*i)
-	}
-	c.norm()
-	return c
-}
-
-/* reduce a DBIG to a BIG using the appropriate form of the modulus */
-func mod(d *DBIG) *BIG {
-	var b *BIG
-	if MODTYPE == PSEUDO_MERSENNE {
-		t := d.split(MODBITS)
-		b = NewBIGdcopy(d)
-
-		v := t.pmul(int(MConst))
-		tw := t.w[NLEN-1]
-		t.w[NLEN-1] &= TMASK
-		t.w[0] += (MConst * ((tw >> TBITS) + (v << (BASEBITS - TBITS))))
-
-		b.add(t)
-	}
-	if MODTYPE == MONTGOMERY_FRIENDLY {
-		for i := 0; i < NLEN; i++ {
-			d.w[NLEN+i] += d.muladd(d.w[i], MConst-1, d.w[i], NLEN+i-1)
-		}
-		b = NewBIG()
-
-		for i := 0; i < NLEN; i++ {
-			b.w[i] = d.w[NLEN+i]
-		}
-	}
-
-	if MODTYPE == NOT_SPECIAL {
-		md := NewBIGints(Modulus)
-		var carry, m int64
-		for i := 0; i < NLEN; i++ {
-			if MConst == -1 {
-				m = (-d.w[i]) & MASK
-			} else {
-				if MConst == 1 {
-					m = d.w[i]
-				} else {
-					m = (MConst * d.w[i]) & MASK
-				}
-			}
-
-			carry = 0
-			for j := 0; j < NLEN; j++ {
-				carry = d.muladd(m, md.w[j], carry, i+j)
-			}
-			d.w[NLEN+i] += carry
-		}
-
-		b = NewBIG()
-		for i := 0; i < NLEN; i++ {
-			b.w[i] = d.w[NLEN+i]
-		}
-
-	}
-	b.norm()
-	return b
-}
-
-/* return a*b mod m */
-func modmul(a, b, m *BIG) *BIG {
-	a.mod(m)
-	b.mod(m)
-	d := mul(a, b)
-	return d.mod(m)
-}
-
-/* return a^2 mod m */
-func modsqr(a, m *BIG) *BIG {
-	a.mod(m)
-	d := sqr(a)
-	return d.mod(m)
-}
-
-/* return -a mod m */
-func modneg(a, m *BIG) *BIG {
-	a.mod(m)
-	return m.minus(a)
-}
-
-/* return this^e mod m */
-func (r *BIG) powmod(e *BIG, m *BIG) *BIG {
-	r.norm()
-	e.norm()
-	a := NewBIGint(1)
-	z := NewBIGcopy(e)
-	s := NewBIGcopy(r)
-	for true {
-		bt := z.parity()
-		z.fshr(1)
-		if bt == 1 {
-			a = modmul(a, s, m)
-		}
-		if z.iszilch() {
-			break
-		}
-		s = modsqr(s, m)
-	}
-	return a
-}
-
-/* Jacobi Symbol (this/p). Returns 0, 1 or -1 */
-func (r *BIG) jacobi(p *BIG) int {
-	m := 0
-	t := NewBIGint(0)
-	x := NewBIGint(0)
-	n := NewBIGint(0)
-	zilch := NewBIGint(0)
-	one := NewBIGint(1)
-	if p.parity() == 0 || comp(r, zilch) == 0 || comp(p, one) <= 0 {
-		return 0
-	}
-	r.norm()
-	x.copy(r)
-	n.copy(p)
-	x.mod(p)
-
-	for comp(n, one) > 0 {
-		if comp(x, zilch) == 0 {
-			return 0
-		}
-		n8 := n.lastbits(3)
-		k := 0
-		for x.parity() == 0 {
-			k++
-			x.shr(1)
-		}
-		if k%2 == 1 {
-			m += (n8*n8 - 1) / 8
-		}
-		m += (n8 - 1) * (x.lastbits(2) - 1) / 4
-		t.copy(n)
-		t.mod(x)
-		n.copy(x)
-		x.copy(t)
-		m %= 2
-
-	}
-	if m == 0 {
-		return 1
-	}
-	return -1
-}
-
-/* this=1/this mod p. Binary method */
-func (r *BIG) invmodp(p *BIG) {
-	r.mod(p)
-	u := NewBIGcopy(r)
-
-	v := NewBIGcopy(p)
-	x1 := NewBIGint(1)
-	x2 := NewBIGint(0)
-	t := NewBIGint(0)
-	one := NewBIGint(1)
-	for comp(u, one) != 0 && comp(v, one) != 0 {
-		for u.parity() == 0 {
-			u.shr(1)
-			if x1.parity() != 0 {
-				x1.add(p)
-				x1.norm()
-			}
-			x1.shr(1)
-		}
-		for v.parity() == 0 {
-			v.shr(1)
-			if x2.parity() != 0 {
-				x2.add(p)
-				x2.norm()
-			}
-			x2.shr(1)
-		}
-		if comp(u, v) >= 0 {
-			u.sub(v)
-			u.norm()
-			if comp(x1, x2) >= 0 {
-				x1.sub(x2)
-			} else {
-				t.copy(p)
-				t.sub(x2)
-				x1.add(t)
-			}
-			x1.norm()
-		} else {
-			v.sub(u)
-			v.norm()
-			if comp(x2, x1) >= 0 {
-				x2.sub(x1)
-			} else {
-				t.copy(p)
-				t.sub(x1)
-				x2.add(t)
-			}
-			x2.norm()
-		}
-	}
-	if comp(u, one) == 0 {
-		r.copy(x1)
-	} else {
-		r.copy(x2)
-	}
-}
-
-/*
-func main() {
-	a := NewBIGint(3)
-	m := NewBIGints(Modulus)
-
-	fmt.Printf("Modulus= "+m.toString())
-	fmt.Printf("\n")
-
-
-	e := NewBIGcopy(m);
-	e.dec(7); e.norm();
-	fmt.Printf("Exponent= "+e.toString())
-	fmt.Printf("\n")
-	a=a.powmod(e,m);
-	fmt.Printf("Result= "+a.toString())
-}
-*/
diff --git a/go/amcl-go/DBIG.go b/go/amcl-go/DBIG.go
deleted file mode 100644
index 98314b6..0000000
--- a/go/amcl-go/DBIG.go
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
-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.
-*/
-
-/* AMCL double length DBIG number class */
-
-package amcl
-
-import "strconv"
-
-type DBIG struct {
-	w [2 * NLEN]int64
-}
-
-func NewDBIG() *DBIG {
-	b := new(DBIG)
-	for i := 0; i < DNLEN; i++ {
-		b.w[i] = 0
-	}
-	return b
-}
-
-func NewDBIGcopy(x *DBIG) *DBIG {
-	b := new(DBIG)
-	for i := 0; i < DNLEN; i++ {
-		b.w[i] = x.w[i]
-	}
-	return b
-}
-
-func NewDBIGscopy(x *BIG) *DBIG {
-	b := new(DBIG)
-	for i := 0; i < NLEN-1; i++ {
-		b.w[i] = x.w[i]
-	}
-	b.w[NLEN-1] = x.get(NLEN-1) & MASK /* top word normalized */
-	b.w[NLEN] = x.get(NLEN-1) >> BASEBITS
-
-	for i := NLEN + 1; i < DNLEN; i++ {
-		b.w[i] = 0
-	}
-	return b
-}
-
-/* set this[i]+=x*y+c, and return high part */
-
-func (r *DBIG) muladd(a int64, b int64, c int64, i int) int64 {
-	x0 := a & HMASK
-	x1 := (a >> HBITS)
-	y0 := b & HMASK
-	y1 := (b >> HBITS)
-	bot := x0 * y0
-	top := x1 * y1
-	mid := x0*y1 + x1*y0
-	x0 = mid & HMASK
-	x1 = (mid >> HBITS)
-	bot += x0 << HBITS
-	bot += c
-	bot += r.w[i]
-	top += x1
-	carry := bot >> BASEBITS
-	bot &= MASK
-	top += carry
-	r.w[i] = bot
-	return top
-}
-
-/* normalise this */
-func (r *DBIG) norm() {
-	var carry int64 = 0
-	for i := 0; i < DNLEN-1; i++ {
-		d := r.w[i] + carry
-		r.w[i] = d & MASK
-		carry = d >> BASEBITS
-	}
-	r.w[DNLEN-1] = (r.w[DNLEN-1] + carry)
-}
-
-/* split DBIG at position n, return higher half, keep lower half */
-func (r *DBIG) split(n uint) *BIG {
-	t := NewBIG()
-	m := n % BASEBITS
-	carry := r.w[DNLEN-1] << (BASEBITS - m)
-
-	for i := DNLEN - 2; i >= NLEN-1; i-- {
-		nw := (r.w[i] >> m) | carry
-		carry = (r.w[i] << (BASEBITS - m)) & MASK
-		t.set(i-NLEN+1, nw)
-	}
-	r.w[NLEN-1] &= ((int64(1) << m) - 1)
-	return t
-}
-
-/* Compare a and b, return 0 if a==b, -1 if a<b, +1 if a>b. Inputs must be normalised */
-func dcomp(a *DBIG, b *DBIG) int {
-	for i := DNLEN - 1; i >= 0; i-- {
-		if a.w[i] == b.w[i] {
-			continue
-		}
-		if a.w[i] > b.w[i] {
-			return 1
-		} else {
-			return -1
-		}
-	}
-	return 0
-}
-
-func (r *DBIG) add(x *DBIG) {
-	for i := 0; i < DNLEN; i++ {
-		r.w[i] = r.w[i] + x.w[i]
-	}
-}
-
-/* this-=x */
-func (r *DBIG) sub(x *DBIG) {
-	for i := 0; i < DNLEN; i++ {
-		r.w[i] = r.w[i] - x.w[i]
-	}
-}
-
-/* general shift left */
-func (r *DBIG) shl(k uint) {
-	n := k % BASEBITS
-	m := int(k / BASEBITS)
-
-	r.w[DNLEN-1] = (r.w[DNLEN-1-m] << n) | (r.w[DNLEN-m-2] >> (BASEBITS - n))
-	for i := DNLEN - 2; i > m; i-- {
-		r.w[i] = ((r.w[i-m] << n) & MASK) | (r.w[i-m-1] >> (BASEBITS - n))
-	}
-	r.w[m] = (r.w[0] << n) & MASK
-	for i := 0; i < m; i++ {
-		r.w[i] = 0
-	}
-}
-
-/* general shift right */
-func (r *DBIG) shr(k uint) {
-	n := (k % BASEBITS)
-	m := int(k / BASEBITS)
-	for i := 0; i < DNLEN-m-1; i++ {
-		r.w[i] = (r.w[m+i] >> n) | ((r.w[m+i+1] << (BASEBITS - n)) & MASK)
-	}
-	r.w[DNLEN-m-1] = r.w[DNLEN-1] >> n
-	for i := DNLEN - m; i < DNLEN; i++ {
-		r.w[i] = 0
-	}
-}
-
-/* reduces this DBIG mod a BIG, and returns the BIG */
-func (r *DBIG) mod(c *BIG) *BIG {
-	r.norm()
-	m := NewDBIGscopy(c)
-
-	if dcomp(r, m) < 0 {
-		return NewBIGdcopy(r)
-	}
-
-	m.shl(1)
-	k := 1
-
-	for dcomp(r, m) >= 0 {
-		m.shl(1)
-		k++
-	}
-
-	for k > 0 {
-		m.shr(1)
-		if dcomp(r, m) >= 0 {
-			r.sub(m)
-			r.norm()
-		}
-		k--
-	}
-	return NewBIGdcopy(r)
-}
-
-/* return this/c */
-func (r *DBIG) div(c *BIG) *BIG {
-	k := 0
-	m := NewDBIGscopy(c)
-	a := NewBIGint(0)
-	e := NewBIGint(1)
-	r.norm()
-
-	for dcomp(r, m) >= 0 {
-		e.fshl(1)
-		m.shl(1)
-		k++
-	}
-
-	for k > 0 {
-		m.shr(1)
-		e.shr(1)
-		if dcomp(r, m) > 0 {
-			a.add(e)
-			a.norm()
-			r.sub(m)
-			r.norm()
-		}
-		k--
-	}
-	return a
-}
-
-/* Convert to Hex String */
-func (r *DBIG) toString() string {
-	s := ""
-	len := r.nbits()
-
-	if len%4 == 0 {
-		len /= 4
-	} else {
-		len /= 4
-		len++
-
-	}
-
-	for i := len - 1; i >= 0; i-- {
-		b := NewDBIGcopy(r)
-
-		b.shr(uint(i * 4))
-		s += strconv.FormatInt(b.w[0]&15, 16)
-	}
-	return s
-}
-
-/* return number of bits */
-func (r *DBIG) nbits() int {
-	k := DNLEN - 1
-	r.norm()
-	for k >= 0 && r.w[k] == 0 {
-		k--
-	}
-	if k < 0 {
-		return 0
-	}
-	bts := int(BASEBITS) * k
-	c := r.w[k]
-	for c != 0 {
-		c /= 2
-		bts++
-	}
-	return bts
-}
diff --git a/go/amcl-go/ECDH.go b/go/amcl-go/ECDH.go
deleted file mode 100644
index 20718eb..0000000
--- a/go/amcl-go/ECDH.go
+++ /dev/null
@@ -1,657 +0,0 @@
-/*
-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.
-*/
-
-/* Elliptic Curve API high-level functions  */
-
-package amcl
-
-import "fmt"
-
-const ECDH_INVALID_PUBLIC_KEY int = -2
-const ECDH_ERROR int = -3
-const ECDH_INVALID int = -4
-const ECDH_EFS int = int(MODBYTES)
-const ECDH_EGS int = int(MODBYTES)
-const ECDH_EAS int = 16
-const ECDH_EBS int = 16
-
-/* Convert Integer to n-byte array */
-func inttoBytes(n int, len int) []byte {
-	var b []byte
-	var i int
-	for i = 0; i < len; i++ {
-		b = append(b, 0)
-	}
-	i = len
-	for n > 0 && i > 0 {
-		i--
-		b[i] = byte(n & 0xff)
-		n /= 256
-	}
-	return b
-}
-
-/* Key Derivation Functions */
-/* Input octet Z */
-/* Output key of length olen */
-func KDF1(Z []byte, olen int) []byte {
-	/* NOTE: the parameter olen is the length of the output K in bytes */
-	H := NewHASH()
-	hlen := 32
-	var K []byte
-	k := 0
-
-	for i := 0; i < olen; i++ {
-		K = append(K, 0)
-	}
-
-	cthreshold := olen / hlen
-	if olen%hlen != 0 {
-		cthreshold++
-	}
-
-	for counter := 0; counter < cthreshold; counter++ {
-		H.Process_array(Z)
-		if counter > 0 {
-			H.Process_num(int32(counter))
-		}
-		B := H.Hash()
-		if k+hlen > olen {
-			for i := 0; i < olen%hlen; i++ {
-				K[k] = B[i]
-				k++
-			}
-		} else {
-			for i := 0; i < hlen; i++ {
-				K[k] = B[i]
-				k++
-			}
-		}
-	}
-	return K
-}
-
-func KDF2(Z []byte, P []byte, olen int) []byte {
-	/* NOTE: the parameter olen is the length of the output k in bytes */
-	H := NewHASH()
-	hlen := 32
-	var K []byte
-
-	k := 0
-
-	for i := 0; i < olen; i++ {
-		K = append(K, 0)
-	}
-
-	cthreshold := olen / hlen
-	if olen%hlen != 0 {
-		cthreshold++
-	}
-
-	for counter := 1; counter <= cthreshold; counter++ {
-		H.Process_array(Z)
-		H.Process_num(int32(counter))
-		H.Process_array(P)
-		B := H.Hash()
-		if k+hlen > olen {
-			for i := 0; i < olen%hlen; i++ {
-				K[k] = B[i]
-				k++
-			}
-		} else {
-			for i := 0; i < hlen; i++ {
-				K[k] = B[i]
-				k++
-			}
-		}
-	}
-	return K
-}
-
-/* Password based Key Derivation Function */
-/* Input password p, salt s, and repeat count */
-/* Output key of length olen */
-func PBKDF2(Pass []byte, Salt []byte, rep int, olen int) []byte {
-	d := olen / 32
-	if olen%32 != 0 {
-		d++
-	}
-	var F [ECDH_EFS]byte
-	var U [ECDH_EFS]byte
-
-	var S []byte
-
-	//byte[] S=new byte[Salt.length+4];
-
-	var K []byte
-	//byte[] K=new byte[d*EFS];
-	//opt:=0
-
-	for i := 1; i <= d; i++ {
-		for j := 0; j < len(Salt); j++ {
-			S = append(S, Salt[j])
-		}
-		N := inttoBytes(i, 4)
-		for j := 0; j < 4; j++ {
-			S = append(S, N[j])
-		}
-
-		HMAC(S, Pass, F[:])
-
-		for j := 0; j < ECDH_EFS; j++ {
-			U[j] = F[j]
-		}
-		for j := 2; j <= rep; j++ {
-			HMAC(U[:], Pass, U[:])
-			for k := 0; k < ECDH_EFS; k++ {
-				F[k] ^= U[k]
-			}
-		}
-		for j := 0; j < ECDH_EFS; j++ {
-			K = append(K, F[j])
-		}
-	}
-	var key []byte
-	for i := 0; i < olen; i++ {
-		key = append(key, K[i])
-	}
-	return key
-}
-
-/* Calculate HMAC of m using key k. HMAC is tag of length olen */
-func HMAC(M []byte, K []byte, tag []byte) int {
-	/* Input is from an octet m        *
-	* olen is requested output length in bytes. k is the key  *
-	* The output is the calculated tag */
-	var B [32]byte
-	var K0 [64]byte
-	olen := len(tag)
-
-	b := len(K0)
-	if olen < 4 || olen > 32 {
-		return 0
-	}
-
-	for i := 0; i < b; i++ {
-		K0[i] = 0
-	}
-
-	H := NewHASH()
-
-	if len(K) > b {
-		H.Process_array(K)
-		B = H.Hash()
-		for i := 0; i < 32; i++ {
-			K0[i] = B[i]
-		}
-	} else {
-		for i := 0; i < len(K); i++ {
-			K0[i] = K[i]
-		}
-	}
-
-	for i := 0; i < b; i++ {
-		K0[i] ^= 0x36
-	}
-	H.Process_array(K0[:])
-	H.Process_array(M)
-	B = H.Hash()
-
-	for i := 0; i < b; i++ {
-		K0[i] ^= 0x6a
-	}
-	H.Process_array(K0[:])
-	H.Process_array(B[:])
-	B = H.Hash()
-
-	for i := 0; i < olen; i++ {
-		tag[i] = B[i]
-	}
-
-	return 1
-}
-
-/* AES encryption/decryption. Encrypt byte array M using key K and returns ciphertext */
-func AES_CBC_IV0_ENCRYPT(K []byte, M []byte) []byte { /* AES CBC encryption, with Null IV and key K */
-	/* Input is from an octet string M, output is to an octet string C */
-	/* Input is padded as necessary to make up a full final block */
-	a := NewAES()
-	fin := false
-
-	var buff [16]byte
-	var C []byte
-
-	a.Init(aes_CBC, K, nil)
-
-	ipt := 0 //opt:=0
-	var i int
-	for true {
-		for i = 0; i < 16; i++ {
-			if ipt < len(M) {
-				buff[i] = M[ipt]
-				ipt++
-			} else {
-				fin = true
-				break
-			}
-		}
-		if fin {
-			break
-		}
-		a.Encrypt(buff[:])
-		for i = 0; i < 16; i++ {
-			C = append(C, buff[i])
-		}
-	}
-
-	/* last block, filled up to i-th index */
-
-	padlen := 16 - i
-	for j := i; j < 16; j++ {
-		buff[j] = byte(padlen)
-	}
-
-	a.Encrypt(buff[:])
-
-	for i = 0; i < 16; i++ {
-		C = append(C, buff[i])
-	}
-	a.End()
-	return C
-}
-
-/* returns plaintext if all consistent, else returns null string */
-func AES_CBC_IV0_DECRYPT(K []byte, C []byte) []byte { /* padding is removed */
-	a := NewAES()
-	var buff [16]byte
-	var MM []byte
-	var M []byte
-
-	var i int
-	ipt := 0
-	opt := 0
-
-	a.Init(aes_CBC, K, nil)
-
-	if len(C) == 0 {
-		return nil
-	}
-	ch := C[ipt]
-	ipt++
-
-	fin := false
-
-	for true {
-		for i = 0; i < 16; i++ {
-			buff[i] = ch
-			if ipt >= len(C) {
-				fin = true
-				break
-			} else {
-				ch = C[ipt]
-				ipt++
-			}
-		}
-		a.Decrypt(buff[:])
-		if fin {
-			break
-		}
-		for i = 0; i < 16; i++ {
-			MM = append(MM, buff[i])
-			opt++
-		}
-	}
-
-	a.End()
-	bad := false
-	padlen := int(buff[15])
-	if i != 15 || padlen < 1 || padlen > 16 {
-		bad = true
-	}
-	if padlen >= 2 && padlen <= 16 {
-		for i = 16 - padlen; i < 16; i++ {
-			if buff[i] != byte(padlen) {
-				bad = true
-			}
-		}
-	}
-
-	if !bad {
-		for i = 0; i < 16-padlen; i++ {
-			MM = append(MM, buff[i])
-			opt++
-		}
-	}
-
-	if bad {
-		return nil
-	}
-
-	for i = 0; i < opt; i++ {
-		M = append(M, MM[i])
-	}
-
-	return M
-}
-
-/* Calculate a public/private EC GF(p) key pair W,S where W=S.G mod EC(p),
- * where S is the secret key and W is the public key
- * and G is fixed generator.
- * If RNG is NULL then the private key is provided externally in S
- * otherwise it is generated randomly internally */
-func ECDH_KEY_PAIR_GENERATE(RNG *RAND, S []byte, W []byte) int {
-	res := 0
-	var T [ECDH_EFS]byte
-	var s *BIG
-	var G *ECP
-
-	gx := NewBIGints(CURVE_Gx)
-	if CURVETYPE != MONTGOMERY {
-		gy := NewBIGints(CURVE_Gy)
-		G = NewECPbigs(gx, gy)
-	} else {
-		G = NewECPbig(gx)
-	}
-
-	r := NewBIGints(CURVE_Order)
-
-	if RNG == nil {
-		s = fromBytes(S)
-	} else {
-		s = randomnum(r, RNG)
-
-		s.toBytes(T[:])
-		for i := 0; i < ECDH_EGS; i++ {
-			S[i] = T[i]
-		}
-	}
-
-	WP := G.mul(s)
-
-	WP.toBytes(W)
-
-	return res
-}
-
-/* validate public key. Set full=true for fuller check */
-func ECDH_PUBLIC_KEY_VALIDATE(full bool, W []byte) int {
-	WP := ECP_fromBytes(W)
-	res := 0
-
-	r := NewBIGints(CURVE_Order)
-
-	if WP.is_infinity() {
-		res = ECDH_INVALID_PUBLIC_KEY
-	}
-	if res == 0 && full {
-		WP = WP.mul(r)
-		if !WP.is_infinity() {
-			res = ECDH_INVALID_PUBLIC_KEY
-		}
-	}
-	return res
-}
-
-/* IEEE-1363 Diffie-Hellman online calculation Z=S.WD */
-func ECPSVDP_DH(S []byte, WD []byte, Z []byte) int {
-	res := 0
-	var T [ECDH_EFS]byte
-
-	s := fromBytes(S)
-
-	W := ECP_fromBytes(WD)
-	if W.is_infinity() {
-		res = ECDH_ERROR
-	}
-
-	if res == 0 {
-		r := NewBIGints(CURVE_Order)
-		s.mod(r)
-		W = W.mul(s)
-		if W.is_infinity() {
-			res = ECDH_ERROR
-		} else {
-			W.getX().toBytes(T[:])
-			for i := 0; i < ECDH_EFS; i++ {
-				Z[i] = T[i]
-			}
-		}
-	}
-	return res
-}
-
-/* IEEE ECDSA Signature, C and D are signature on F using private key S */
-func ECPSP_DSA(RNG *RAND, S []byte, F []byte, C []byte, D []byte) int {
-	var T [ECDH_EFS]byte
-
-	H := NewHASH()
-	H.Process_array(F)
-	B := H.Hash()
-
-	gx := NewBIGints(CURVE_Gx)
-	gy := NewBIGints(CURVE_Gy)
-
-	G := NewECPbigs(gx, gy)
-	r := NewBIGints(CURVE_Order)
-
-	s := fromBytes(S)
-	f := fromBytes(B[:])
-
-	c := NewBIGint(0)
-	d := NewBIGint(0)
-	V := NewECP()
-
-	for d.iszilch() {
-		u := randomnum(r, RNG)
-
-		V.copy(G)
-		V = V.mul(u)
-		vx := V.getX()
-		c.copy(vx)
-		c.mod(r)
-		if c.iszilch() {
-			continue
-		}
-		u.invmodp(r)
-		d.copy(modmul(s, c, r))
-		d.add(f)
-		d.copy(modmul(u, d, r))
-	}
-
-	c.toBytes(T[:])
-	for i := 0; i < ECDH_EFS; i++ {
-		C[i] = T[i]
-	}
-	d.toBytes(T[:])
-	for i := 0; i < ECDH_EFS; i++ {
-		D[i] = T[i]
-	}
-	return 0
-}
-
-/* IEEE1363 ECDSA Signature Verification. Signature C and D on F is verified using public key W */
-func ECPVP_DSA(W []byte, F []byte, C []byte, D []byte) int {
-	res := 0
-
-	H := NewHASH()
-	H.Process_array(F)
-	B := H.Hash()
-
-	gx := NewBIGints(CURVE_Gx)
-	gy := NewBIGints(CURVE_Gy)
-
-	G := NewECPbigs(gx, gy)
-	r := NewBIGints(CURVE_Order)
-
-	c := fromBytes(C)
-	d := fromBytes(D)
-	f := fromBytes(B[:])
-
-	if c.iszilch() || comp(c, r) >= 0 || d.iszilch() || comp(d, r) >= 0 {
-		res = ECDH_INVALID
-	}
-
-	if res == 0 {
-		d.invmodp(r)
-		f.copy(modmul(f, d, r))
-		h2 := modmul(c, d, r)
-
-		WP := ECP_fromBytes(W)
-		if WP.is_infinity() {
-			res = ECDH_ERROR
-		} else {
-			P := NewECP()
-			P.copy(WP)
-
-			P = P.mul2(h2, G, f)
-
-			if P.is_infinity() {
-				res = ECDH_INVALID
-			} else {
-				d = P.getX()
-				d.mod(r)
-
-				if comp(d, c) != 0 {
-					res = ECDH_INVALID
-				}
-			}
-		}
-	}
-
-	return res
-}
-
-/* IEEE1363 ECIES encryption. Encryption of plaintext M uses public key W and produces ciphertext V,C,T */
-func ECIES_ENCRYPT(P1 []byte, P2 []byte, RNG *RAND, W []byte, M []byte, V []byte, T []byte) []byte {
-	var Z [ECDH_EFS]byte
-	var VZ [3*ECDH_EFS + 1]byte
-	var K1 [ECDH_EAS]byte
-	var K2 [ECDH_EAS]byte
-	var U [ECDH_EGS]byte
-
-	if ECDH_KEY_PAIR_GENERATE(RNG, U[:], V) != 0 {
-		return nil
-	}
-	if ECPSVDP_DH(U[:], W, Z[:]) != 0 {
-		return nil
-	}
-
-	for i := 0; i < 2*ECDH_EFS+1; i++ {
-		VZ[i] = V[i]
-	}
-	for i := 0; i < ECDH_EFS; i++ {
-		VZ[2*ECDH_EFS+1+i] = Z[i]
-	}
-
-	K := KDF2(VZ[:], P1, ECDH_EFS)
-
-	for i := 0; i < ECDH_EAS; i++ {
-		K1[i] = K[i]
-		K2[i] = K[ECDH_EAS+i]
-	}
-
-	C := AES_CBC_IV0_ENCRYPT(K1[:], M)
-
-	L2 := inttoBytes(len(P2), 8)
-
-	var AC []byte
-
-	for i := 0; i < len(C); i++ {
-		AC = append(AC, C[i])
-	}
-	for i := 0; i < len(P2); i++ {
-		AC = append(AC, P2[i])
-	}
-	for i := 0; i < 8; i++ {
-		AC = append(AC, L2[i])
-	}
-
-	HMAC(AC, K2[:], T)
-
-	return C
-}
-
-/* IEEE1363 ECIES decryption. Decryption of ciphertext V,C,T using private key U outputs plaintext M */
-func ECIES_DECRYPT(P1 []byte, P2 []byte, V []byte, C []byte, T []byte, U []byte) []byte {
-	var Z [ECDH_EFS]byte
-	var VZ [3*ECDH_EFS + 1]byte
-	var K1 [ECDH_EAS]byte
-	var K2 [ECDH_EAS]byte
-
-	var TAG []byte = T[:]
-
-	if ECPSVDP_DH(U, V, Z[:]) != 0 {
-		return nil
-	}
-
-	for i := 0; i < 2*ECDH_EFS+1; i++ {
-		VZ[i] = V[i]
-	}
-	for i := 0; i < ECDH_EFS; i++ {
-		VZ[2*ECDH_EFS+1+i] = Z[i]
-	}
-
-	K := KDF2(VZ[:], P1, ECDH_EFS)
-
-	for i := 0; i < ECDH_EAS; i++ {
-		K1[i] = K[i]
-		K2[i] = K[ECDH_EAS+i]
-	}
-
-	M := AES_CBC_IV0_DECRYPT(K1[:], C)
-
-	if M == nil {
-		return nil
-	}
-
-	L2 := inttoBytes(len(P2), 8)
-
-	var AC []byte
-
-	for i := 0; i < len(C); i++ {
-		AC = append(AC, C[i])
-	}
-	for i := 0; i < len(P2); i++ {
-		AC = append(AC, P2[i])
-	}
-	for i := 0; i < 8; i++ {
-		AC = append(AC, L2[i])
-	}
-
-	HMAC(AC, K2[:], TAG)
-
-	same := true
-	for i := 0; i < len(T); i++ {
-		if T[i] != TAG[i] {
-			same = false
-		}
-	}
-	if !same {
-		return nil
-	}
-
-	return M
-}
-
-func ECDH_printBinary(array []byte) {
-	for i := 0; i < len(array); i++ {
-		fmt.Printf("%02x", array[i])
-	}
-	fmt.Printf("\n")
-}
diff --git a/go/amcl-go/ECP.go b/go/amcl-go/ECP.go
deleted file mode 100644
index 3ed1d04..0000000
--- a/go/amcl-go/ECP.go
+++ /dev/null
@@ -1,1076 +0,0 @@
-/*
-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.
-*/
-
-package amcl
-
-//import "fmt"
-
-/* Elliptic Curve Point Structure */
-
-type ECP struct {
-	x   *FP
-	y   *FP
-	z   *FP
-	INF bool
-}
-
-/* Constructors */
-func NewECP() *ECP {
-	E := new(ECP)
-	E.x = NewFPint(0)
-	E.y = NewFPint(0)
-	E.z = NewFPint(0)
-	E.INF = true
-	return E
-}
-
-/* set (x,y) from two BIGs */
-func NewECPbigs(ix *BIG, iy *BIG) *ECP {
-	E := new(ECP)
-	E.x = NewFPbig(ix)
-	E.y = NewFPbig(iy)
-	E.z = NewFPint(1)
-	rhs := RHS(E.x)
-
-	if CURVETYPE == MONTGOMERY {
-		if rhs.jacobi() == 1 {
-			E.INF = false
-		} else {
-			E.inf()
-		}
-	} else {
-		y2 := NewFPcopy(E.y)
-		y2.sqr()
-		if y2.equals(rhs) {
-			E.INF = false
-		} else {
-			E.inf()
-		}
-	}
-	return E
-}
-
-/* set (x,y) from BIG and a bit */
-func NewECPbigint(ix *BIG, s int) *ECP {
-	E := new(ECP)
-	E.x = NewFPbig(ix)
-	E.y = NewFPint(0)
-	rhs := RHS(E.x)
-	E.z = NewFPint(1)
-	if rhs.jacobi() == 1 {
-		ny := rhs.sqrt()
-		if ny.redc().parity() != s {
-			ny.neg()
-		}
-		E.y.copy(ny)
-		E.INF = false
-	} else {
-		E.inf()
-	}
-	return E
-}
-
-/* set from x - calculate y from curve equation */
-func NewECPbig(ix *BIG) *ECP {
-	E := new(ECP)
-	E.x = NewFPbig(ix)
-	E.y = NewFPint(0)
-	rhs := RHS(E.x)
-	E.z = NewFPint(1)
-	if rhs.jacobi() == 1 {
-		if CURVETYPE != MONTGOMERY {
-			E.y.copy(rhs.sqrt())
-		}
-		E.INF = false
-	} else {
-		E.INF = true
-	}
-	return E
-}
-
-/* test for O point-at-infinity */
-func (E *ECP) is_infinity() bool {
-	if CURVETYPE == EDWARDS {
-		E.x.reduce()
-		E.y.reduce()
-		E.z.reduce()
-		return (E.x.iszilch() && E.y.equals(E.z))
-	} else {
-		return E.INF
-	}
-}
-
-/* Conditional swap of P and Q dependant on d */
-func (E *ECP) cswap(Q *ECP, d int32) {
-	E.x.cswap(Q.x, d)
-	if CURVETYPE != MONTGOMERY {
-		E.y.cswap(Q.y, d)
-	}
-	E.z.cswap(Q.z, d)
-	if CURVETYPE != EDWARDS {
-		bd := true
-		if d == 0 {
-			bd = false
-		}
-		bd = bd && (E.INF != Q.INF)
-		E.INF = (bd != E.INF)
-		Q.INF = (bd != Q.INF)
-	}
-}
-
-/* Conditional move of Q to P dependant on d */
-func (E *ECP) cmove(Q *ECP, d int32) {
-	E.x.cmove(Q.x, d)
-	if CURVETYPE != MONTGOMERY {
-		E.y.cmove(Q.y, d)
-	}
-	E.z.cmove(Q.z, d)
-	if CURVETYPE != EDWARDS {
-		bd := true
-		if d == 0 {
-			bd = false
-		}
-		E.INF = (E.INF != ((E.INF != Q.INF) && bd))
-	}
-}
-
-/* return 1 if b==c, no branching */
-func teq(b int32, c int32) int32 {
-	x := b ^ c
-	x -= 1 // if x=0, x now -1
-	return ((x >> 31) & 1)
-}
-
-/* this=P */
-func (E *ECP) copy(P *ECP) {
-	E.x.copy(P.x)
-	if CURVETYPE != MONTGOMERY {
-		E.y.copy(P.y)
-	}
-	E.z.copy(P.z)
-	E.INF = P.INF
-}
-
-/* this=-this */
-func (E *ECP) neg() {
-	if E.is_infinity() {
-		return
-	}
-	if CURVETYPE == WEIERSTRASS {
-		E.y.neg()
-		E.y.reduce()
-	}
-	if CURVETYPE == EDWARDS {
-		E.x.neg()
-		E.x.reduce()
-	}
-	return
-}
-
-/* Constant time select from pre-computed table */
-func (E *ECP) selector(W []*ECP, b int32) {
-	MP := NewECP()
-	m := b >> 31
-	babs := (b ^ m) - m
-
-	babs = (babs - 1) / 2
-
-	E.cmove(W[0], teq(babs, 0)) // conditional move
-	E.cmove(W[1], teq(babs, 1))
-	E.cmove(W[2], teq(babs, 2))
-	E.cmove(W[3], teq(babs, 3))
-	E.cmove(W[4], teq(babs, 4))
-	E.cmove(W[5], teq(babs, 5))
-	E.cmove(W[6], teq(babs, 6))
-	E.cmove(W[7], teq(babs, 7))
-
-	MP.copy(E)
-	MP.neg()
-	E.cmove(MP, (m & 1))
-}
-
-/* set this=O */
-func (E *ECP) inf() {
-	E.INF = true
-	E.x.zero()
-	E.y.one()
-	E.z.one()
-}
-
-/* Test P == Q */
-func (E *ECP) equals(Q *ECP) bool {
-	if E.is_infinity() && Q.is_infinity() {
-		return true
-	}
-	if E.is_infinity() || Q.is_infinity() {
-		return false
-	}
-	if CURVETYPE == WEIERSTRASS {
-		zs2 := NewFPcopy(E.z)
-		zs2.sqr()
-		zo2 := NewFPcopy(Q.z)
-		zo2.sqr()
-		zs3 := NewFPcopy(zs2)
-		zs3.mul(E.z)
-		zo3 := NewFPcopy(zo2)
-		zo3.mul(Q.z)
-		zs2.mul(Q.x)
-		zo2.mul(E.x)
-		if !zs2.equals(zo2) {
-			return false
-		}
-		zs3.mul(Q.y)
-		zo3.mul(E.y)
-		if !zs3.equals(zo3) {
-			return false
-		}
-	} else {
-		a := NewFPint(0)
-		b := NewFPint(0)
-		a.copy(E.x)
-		a.mul(Q.z)
-		a.reduce()
-		b.copy(Q.x)
-		b.mul(E.z)
-		b.reduce()
-		if !a.equals(b) {
-			return false
-		}
-		if CURVETYPE == EDWARDS {
-			a.copy(E.y)
-			a.mul(Q.z)
-			a.reduce()
-			b.copy(Q.y)
-			b.mul(E.z)
-			b.reduce()
-			if !a.equals(b) {
-				return false
-			}
-		}
-	}
-	return true
-}
-
-/* Calculate RHS of curve equation */
-func RHS(x *FP) *FP {
-	x.norm()
-	r := NewFPcopy(x)
-	r.sqr()
-
-	if CURVETYPE == WEIERSTRASS { // x^3+Ax+B
-		b := NewFPbig(NewBIGints(CURVE_B))
-		r.mul(x)
-		if CURVE_A == -3 {
-			cx := NewFPcopy(x)
-			cx.imul(3)
-			cx.neg()
-			cx.norm()
-			r.add(cx)
-		}
-		r.add(b)
-	}
-	if CURVETYPE == EDWARDS { // (Ax^2-1)/(Bx^2-1)
-		b := NewFPbig(NewBIGints(CURVE_B))
-
-		one := NewFPint(1)
-		b.mul(r)
-		b.sub(one)
-		if CURVE_A == -1 {
-			r.neg()
-		}
-		r.sub(one)
-		b.inverse()
-		r.mul(b)
-	}
-	if CURVETYPE == MONTGOMERY { // x^3+Ax^2+x
-		x3 := NewFPint(0)
-		x3.copy(r)
-		x3.mul(x)
-		r.imul(CURVE_A)
-		r.add(x3)
-		r.add(x)
-	}
-	r.reduce()
-	return r
-}
-
-/* set to affine - from (x,y,z) to (x,y) */
-func (E *ECP) affine() {
-	if E.is_infinity() {
-		return
-	}
-	one := NewFPint(1)
-	if E.z.equals(one) {
-		return
-	}
-	E.z.inverse()
-	if CURVETYPE == WEIERSTRASS {
-		z2 := NewFPcopy(E.z)
-		z2.sqr()
-		E.x.mul(z2)
-		E.x.reduce()
-		E.y.mul(z2)
-		E.y.mul(E.z)
-		E.y.reduce()
-	}
-	if CURVETYPE == EDWARDS {
-		E.x.mul(E.z)
-		E.x.reduce()
-		E.y.mul(E.z)
-		E.y.reduce()
-	}
-	if CURVETYPE == MONTGOMERY {
-		E.x.mul(E.z)
-		E.x.reduce()
-	}
-	E.z.one()
-}
-
-/* extract x as a BIG */
-func (E *ECP) getX() *BIG {
-	E.affine()
-	return E.x.redc()
-}
-
-/* extract y as a BIG */
-func (E *ECP) getY() *BIG {
-	E.affine()
-	return E.y.redc()
-}
-
-/* get sign of Y */
-func (E *ECP) getS() int {
-	E.affine()
-	y := E.getY()
-	return y.parity()
-}
-
-/* extract x as an FP */
-func (E *ECP) getx() *FP {
-	return E.x
-}
-
-/* extract y as an FP */
-func (E *ECP) gety() *FP {
-	return E.y
-}
-
-/* extract z as an FP */
-func (E *ECP) getz() *FP {
-	return E.z
-}
-
-/* convert to byte array */
-func (E *ECP) toBytes(b []byte) {
-	var t [int(MODBYTES)]byte
-	MB := int(MODBYTES)
-	if CURVETYPE != MONTGOMERY {
-		b[0] = 0x04
-	} else {
-		b[0] = 0x02
-	}
-
-	E.affine()
-	E.x.redc().toBytes(t[:])
-	for i := 0; i < MB; i++ {
-		b[i+1] = t[i]
-	}
-	if CURVETYPE != MONTGOMERY {
-		E.y.redc().toBytes(t[:])
-		for i := 0; i < MB; i++ {
-			b[i+MB+1] = t[i]
-		}
-	}
-}
-
-/* convert from byte array to point */
-func ECP_fromBytes(b []byte) *ECP {
-	var t [int(MODBYTES)]byte
-	MB := int(MODBYTES)
-	p := NewBIGints(Modulus)
-
-	for i := 0; i < MB; i++ {
-		t[i] = b[i+1]
-	}
-	px := fromBytes(t[:])
-	if comp(px, p) >= 0 {
-		return NewECP()
-	}
-
-	if b[0] == 0x04 {
-		for i := 0; i < MB; i++ {
-			t[i] = b[i+MB+1]
-		}
-		py := fromBytes(t[:])
-		if comp(py, p) >= 0 {
-			return NewECP()
-		}
-		return NewECPbigs(px, py)
-	} else {
-		return NewECPbig(px)
-	}
-}
-
-/* convert to hex string */
-func (E *ECP) toString() string {
-	if E.is_infinity() {
-		return "infinity"
-	}
-	E.affine()
-	if CURVETYPE == MONTGOMERY {
-		return "(" + E.x.redc().toString() + ")"
-	} else {
-		return "(" + E.x.redc().toString() + "," + E.y.redc().toString() + ")"
-	}
-}
-
-/* this*=2 */
-func (E *ECP) dbl() {
-	if CURVETYPE == WEIERSTRASS {
-		if E.INF {
-			return
-		}
-		if E.y.iszilch() {
-			E.inf()
-			return
-		}
-
-		w1 := NewFPcopy(E.x)
-		w6 := NewFPcopy(E.z)
-		w2 := NewFPint(0)
-		w3 := NewFPcopy(E.x)
-		w8 := NewFPcopy(E.x)
-
-		if CURVE_A == -3 {
-			w6.sqr()
-			w1.copy(w6)
-			w1.neg()
-			w3.add(w1)
-
-			w8.add(w6)
-
-			w3.mul(w8)
-			w8.copy(w3)
-			w8.imul(3)
-		} else {
-			w1.sqr()
-			w8.copy(w1)
-			w8.imul(3)
-		}
-
-		w2.copy(E.y)
-		w2.sqr()
-		w3.copy(E.x)
-		w3.mul(w2)
-		w3.imul(4)
-		w1.copy(w3)
-		w1.neg()
-		//		w1.norm();
-
-		E.x.copy(w8)
-		E.x.sqr()
-		E.x.add(w1)
-		E.x.add(w1)
-		//		x.reduce();
-		E.x.norm()
-
-		E.z.mul(E.y)
-		E.z.add(E.z)
-
-		w2.add(w2)
-		w2.sqr()
-		w2.add(w2)
-		w3.sub(E.x)
-		E.y.copy(w8)
-		E.y.mul(w3)
-		//		w2.norm();
-		E.y.sub(w2)
-		//		y.reduce();
-		//		z.reduce();
-		E.y.norm()
-		E.z.norm()
-
-	}
-	if CURVETYPE == EDWARDS {
-		C := NewFPcopy(E.x)
-		D := NewFPcopy(E.y)
-		H := NewFPcopy(E.z)
-		J := NewFPint(0)
-
-		E.x.mul(E.y)
-		E.x.add(E.x)
-		C.sqr()
-		D.sqr()
-		if CURVE_A == -1 {
-			C.neg()
-		}
-		E.y.copy(C)
-		E.y.add(D)
-		//		y.norm();
-		H.sqr()
-		H.add(H)
-		E.z.copy(E.y)
-		J.copy(E.y)
-		J.sub(H)
-		E.x.mul(J)
-		C.sub(D)
-		E.y.mul(C)
-		E.z.mul(J)
-
-		E.x.norm()
-		E.y.norm()
-		E.z.norm()
-	}
-	if CURVETYPE == MONTGOMERY {
-		A := NewFPcopy(E.x)
-		B := NewFPcopy(E.x)
-		AA := NewFPint(0)
-		BB := NewFPint(0)
-		C := NewFPint(0)
-
-		if E.INF {
-			return
-		}
-
-		A.add(E.z)
-		AA.copy(A)
-		AA.sqr()
-		B.sub(E.z)
-		BB.copy(B)
-		BB.sqr()
-		C.copy(AA)
-		C.sub(BB)
-		//		C.norm();
-
-		E.x.copy(AA)
-		E.x.mul(BB)
-
-		A.copy(C)
-		A.imul((CURVE_A + 2) / 4)
-
-		BB.add(A)
-		E.z.copy(BB)
-		E.z.mul(C)
-		//		x.reduce();
-		//		z.reduce();
-		E.x.norm()
-		E.z.norm()
-	}
-	return
-}
-
-/* this+=Q */
-func (E *ECP) add(Q *ECP) {
-	if CURVETYPE == WEIERSTRASS {
-		if E.INF {
-			E.copy(Q)
-			return
-		}
-		if Q.INF {
-			return
-		}
-
-		aff := false
-
-		one := NewFPint(1)
-		if Q.z.equals(one) {
-			aff = true
-		}
-
-		var A, C *FP
-		B := NewFPcopy(E.z)
-		D := NewFPcopy(E.z)
-		if !aff {
-			A = NewFPcopy(Q.z)
-			C = NewFPcopy(Q.z)
-
-			A.sqr()
-			B.sqr()
-			C.mul(A)
-			D.mul(B)
-
-			A.mul(E.x)
-			C.mul(E.y)
-		} else {
-			A = NewFPcopy(E.x)
-			C = NewFPcopy(E.y)
-
-			B.sqr()
-			D.mul(B)
-		}
-
-		B.mul(Q.x)
-		B.sub(A)
-		D.mul(Q.y)
-		D.sub(C)
-
-		if B.iszilch() {
-			if D.iszilch() {
-				E.dbl()
-				return
-			} else {
-				E.INF = true
-				return
-			}
-		}
-
-		if !aff {
-			E.z.mul(Q.z)
-		}
-		E.z.mul(B)
-
-		e := NewFPcopy(B)
-		e.sqr()
-		B.mul(e)
-		A.mul(e)
-
-		e.copy(A)
-		e.add(A)
-		e.add(B)
-		E.x.copy(D)
-		E.x.sqr()
-		E.x.sub(e)
-
-		A.sub(E.x)
-		E.y.copy(A)
-		E.y.mul(D)
-		C.mul(B)
-		E.y.sub(C)
-
-		//	x.reduce();
-		//	y.reduce();
-		//	z.reduce();
-		E.x.norm()
-		E.y.norm()
-		E.z.norm()
-	}
-	if CURVETYPE == EDWARDS {
-		b := NewFPbig(NewBIGints(CURVE_B))
-		A := NewFPcopy(E.z)
-		B := NewFPint(0)
-		C := NewFPcopy(E.x)
-		D := NewFPcopy(E.y)
-		EE := NewFPint(0)
-		F := NewFPint(0)
-		G := NewFPint(0)
-		//H:=NewFPint(0)
-		//I:=NewFPint(0)
-
-		A.mul(Q.z)
-		B.copy(A)
-		B.sqr()
-		C.mul(Q.x)
-		D.mul(Q.y)
-
-		EE.copy(C)
-		EE.mul(D)
-		EE.mul(b)
-		F.copy(B)
-		F.sub(EE)
-		G.copy(B)
-		G.add(EE)
-		C.add(D)
-
-		if CURVE_A == 1 {
-			EE.copy(D)
-			D.sub(C)
-		}
-
-		B.copy(E.x)
-		B.add(E.y)
-		D.copy(Q.x)
-		D.add(Q.y)
-		B.mul(D)
-		B.sub(C)
-		B.mul(F)
-		E.x.copy(A)
-		E.x.mul(B)
-
-		if CURVE_A == 1 {
-			C.copy(EE)
-			C.mul(G)
-		}
-		if CURVE_A == -1 {
-			C.mul(G)
-		}
-		E.y.copy(A)
-		E.y.mul(C)
-		E.z.copy(F)
-		E.z.mul(G)
-		//	x.reduce(); y.reduce(); z.reduce();
-		E.x.norm()
-		E.y.norm()
-		E.z.norm()
-	}
-	return
-}
-
-/* Differential Add for Montgomery curves. this+=Q where W is this-Q and is affine. */
-func (E *ECP) dadd(Q *ECP, W *ECP) {
-	A := NewFPcopy(E.x)
-	B := NewFPcopy(E.x)
-	C := NewFPcopy(Q.x)
-	D := NewFPcopy(Q.x)
-	DA := NewFPint(0)
-	CB := NewFPint(0)
-
-	A.add(E.z)
-	B.sub(E.z)
-
-	C.add(Q.z)
-	D.sub(Q.z)
-
-	DA.copy(D)
-	DA.mul(A)
-	CB.copy(C)
-	CB.mul(B)
-
-	A.copy(DA)
-	A.add(CB)
-	A.sqr()
-	B.copy(DA)
-	B.sub(CB)
-	B.sqr()
-
-	E.x.copy(A)
-	E.z.copy(W.x)
-	E.z.mul(B)
-
-	if E.z.iszilch() {
-		E.inf()
-	} else {
-		E.INF = false
-	}
-
-	//	x.reduce();
-	E.x.norm()
-}
-
-/* this-=Q */
-func (E *ECP) sub(Q *ECP) {
-	Q.neg()
-	E.add(Q)
-	Q.neg()
-}
-
-func multiaffine(m int, P []*ECP) {
-	t1 := NewFPint(0)
-	t2 := NewFPint(0)
-
-	var work []*FP
-
-	for i := 0; i < m; i++ {
-		work = append(work, NewFPint(0))
-	}
-
-	work[0].one()
-	work[1].copy(P[0].z)
-
-	for i := 2; i < m; i++ {
-		work[i].copy(work[i-1])
-		work[i].mul(P[i-1].z)
-	}
-
-	t1.copy(work[m-1])
-	t1.mul(P[m-1].z)
-	t1.inverse()
-	t2.copy(P[m-1].z)
-	work[m-1].mul(t1)
-
-	for i := m - 2; ; i-- {
-		if i == 0 {
-			work[0].copy(t1)
-			work[0].mul(t2)
-			break
-		}
-		work[i].mul(t2)
-		work[i].mul(t1)
-		t2.mul(P[i].z)
-	}
-	/* now work[] contains inverses of all Z coordinates */
-
-	for i := 0; i < m; i++ {
-		P[i].z.one()
-		t1.copy(work[i])
-		t1.sqr()
-		P[i].x.mul(t1)
-		t1.mul(work[i])
-		P[i].y.mul(t1)
-	}
-}
-
-/* constant time multiply by small integer of length bts - use ladder */
-func (E *ECP) pinmul(e int32, bts int32) *ECP {
-	if CURVETYPE == MONTGOMERY {
-		return E.mul(NewBIGint(int(e)))
-	} else {
-		P := NewECP()
-		R0 := NewECP()
-		R1 := NewECP()
-		R1.copy(E)
-
-		for i := bts - 1; i >= 0; i-- {
-			b := (e >> uint32(i)) & 1
-			P.copy(R1)
-			P.add(R0)
-			R0.cswap(R1, b)
-			R1.copy(P)
-			R0.dbl()
-			R0.cswap(R1, b)
-		}
-		P.copy(R0)
-		P.affine()
-		return P
-	}
-}
-
-/* return e.this */
-
-func (E *ECP) mul(e *BIG) *ECP {
-	if e.iszilch() || E.is_infinity() {
-		return NewECP()
-	}
-	P := NewECP()
-	if CURVETYPE == MONTGOMERY {
-		/* use Ladder */
-		D := NewECP()
-		R0 := NewECP()
-		R0.copy(E)
-		R1 := NewECP()
-		R1.copy(E)
-		R1.dbl()
-		D.copy(E)
-		D.affine()
-		nb := e.nbits()
-		for i := nb - 2; i >= 0; i-- {
-			b := int32(e.bit(i))
-			P.copy(R1)
-			P.dadd(R0, D)
-			R0.cswap(R1, b)
-			R1.copy(P)
-			R0.dbl()
-			R0.cswap(R1, b)
-		}
-		P.copy(R0)
-	} else {
-		// fixed size windows
-		mt := NewBIG()
-		t := NewBIG()
-		Q := NewECP()
-		C := NewECP()
-
-		var W []*ECP
-		var w [1 + (NLEN*int(BASEBITS)+3)/4]int8
-
-		E.affine()
-
-		Q.copy(E)
-		Q.dbl()
-
-		W = append(W, NewECP())
-		W[0].copy(E)
-
-		for i := 1; i < 8; i++ {
-			W = append(W, NewECP())
-			W[i].copy(W[i-1])
-			W[i].add(Q)
-		}
-
-		// convert the table to affine
-		if CURVETYPE == WEIERSTRASS {
-			multiaffine(8, W[:])
-		}
-
-		// make exponent odd - add 2P if even, P if odd
-		t.copy(e)
-		s := int32(t.parity())
-		t.inc(1)
-		t.norm()
-		ns := int32(t.parity())
-		mt.copy(t)
-		mt.inc(1)
-		mt.norm()
-		t.cmove(mt, s)
-		Q.cmove(E, ns)
-		C.copy(Q)
-
-		nb := 1 + (t.nbits()+3)/4
-
-		// convert exponent to signed 4-bit window
-		for i := 0; i < nb; i++ {
-			w[i] = int8(t.lastbits(5) - 16)
-			t.dec(int(w[i]))
-			t.norm()
-			t.fshr(4)
-		}
-		w[nb] = int8(t.lastbits(5))
-
-		P.copy(W[(int(w[nb])-1)/2])
-		for i := nb - 1; i >= 0; i-- {
-			Q.selector(W, int32(w[i]))
-			P.dbl()
-			P.dbl()
-			P.dbl()
-			P.dbl()
-			P.add(Q)
-		}
-		P.sub(C) /* apply correction */
-	}
-	P.affine()
-	return P
-}
-
-/* Return e.this+f.Q */
-
-func (E *ECP) mul2(e *BIG, Q *ECP, f *BIG) *ECP {
-	te := NewBIG()
-	tf := NewBIG()
-	mt := NewBIG()
-	S := NewECP()
-	T := NewECP()
-	C := NewECP()
-	var W []*ECP
-	//ECP[] W=new ECP[8];
-	var w [1 + (NLEN*int(BASEBITS)+1)/2]int8
-
-	E.affine()
-	Q.affine()
-
-	te.copy(e)
-	tf.copy(f)
-
-	// precompute table
-	for i := 0; i < 8; i++ {
-		W = append(W, NewECP())
-	}
-	W[1].copy(E)
-	W[1].sub(Q)
-	W[2].copy(E)
-	W[2].add(Q)
-	S.copy(Q)
-	S.dbl()
-	W[0].copy(W[1])
-	W[0].sub(S)
-	W[3].copy(W[2])
-	W[3].add(S)
-	T.copy(E)
-	T.dbl()
-	W[5].copy(W[1])
-	W[5].add(T)
-	W[6].copy(W[2])
-	W[6].add(T)
-	W[4].copy(W[5])
-	W[4].sub(S)
-	W[7].copy(W[6])
-	W[7].add(S)
-
-	// convert the table to affine
-	if CURVETYPE == WEIERSTRASS {
-		multiaffine(8, W)
-	}
-
-	// if multiplier is odd, add 2, else add 1 to multiplier, and add 2P or P to correction
-
-	s := int32(te.parity())
-	te.inc(1)
-	te.norm()
-	ns := int32(te.parity())
-	mt.copy(te)
-	mt.inc(1)
-	mt.norm()
-	te.cmove(mt, s)
-	T.cmove(E, ns)
-	C.copy(T)
-
-	s = int32(tf.parity())
-	tf.inc(1)
-	tf.norm()
-	ns = int32(tf.parity())
-	mt.copy(tf)
-	mt.inc(1)
-	mt.norm()
-	tf.cmove(mt, s)
-	S.cmove(Q, ns)
-	C.add(S)
-
-	mt.copy(te)
-	mt.add(tf)
-	mt.norm()
-	nb := 1 + (mt.nbits()+1)/2
-
-	// convert exponent to signed 2-bit window
-	for i := 0; i < nb; i++ {
-		a := (te.lastbits(3) - 4)
-		te.dec(int(a))
-		te.norm()
-		te.fshr(2)
-		b := (tf.lastbits(3) - 4)
-		tf.dec(int(b))
-		tf.norm()
-		tf.fshr(2)
-		w[i] = int8(4*a + b)
-	}
-	w[nb] = int8(4*te.lastbits(3) + tf.lastbits(3))
-	S.copy(W[(w[nb]-1)/2])
-
-	for i := nb - 1; i >= 0; i-- {
-		T.selector(W, int32(w[i]))
-		S.dbl()
-		S.dbl()
-		S.add(T)
-	}
-	S.sub(C) /* apply correction */
-	S.affine()
-	return S
-}
-
-/*
-func main() {
-	Gx:=NewBIGints(CURVE_Gx);
-	var Gy *BIG
-	var P *ECP
-
-	if CURVETYPE!=MONTGOMERY {Gy=NewBIGints(CURVE_Gy)}
-	r:=NewBIGints(CURVE_Order)
-
-	//r.dec(7);
-
-	fmt.Printf("Gx= "+Gx.toString())
-	fmt.Printf("\n")
-
-	if CURVETYPE!=MONTGOMERY {
-		fmt.Printf("Gy= "+Gy.toString())
-		fmt.Printf("\n")
-	}
-
-	if CURVETYPE!=MONTGOMERY {
-		P=NewECPbigs(Gx,Gy)
-	} else  {P=NewECPbig(Gx)}
-
-	fmt.Printf("P= "+P.toString());
-	fmt.Printf("\n")
-
-	R:=P.mul(r);
-		//for (int i=0;i<10000;i++)
-		//	R=P.mul(r);
-
-	fmt.Printf("R= "+R.toString())
-	fmt.Printf("\n")
-}
-*/
diff --git a/go/amcl-go/ECP2.go b/go/amcl-go/ECP2.go
deleted file mode 100644
index 6770378..0000000
--- a/go/amcl-go/ECP2.go
+++ /dev/null
@@ -1,672 +0,0 @@
-/*
-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.
-*/
-
-/* AMCL Weierstrass elliptic curve functions over FP2 */
-
-package amcl
-
-//import "fmt"
-
-type ECP2 struct {
-	x   *FP2
-	y   *FP2
-	z   *FP2
-	INF bool
-}
-
-func NewECP2() *ECP2 {
-	E := new(ECP2)
-	E.x = NewFP2int(0)
-	E.y = NewFP2int(1)
-	E.z = NewFP2int(1)
-	E.INF = true
-	return E
-}
-
-/* Test this=O? */
-func (E *ECP2) is_infinity() bool {
-	return E.INF
-}
-
-/* copy this=P */
-func (E *ECP2) copy(P *ECP2) {
-	E.x.copy(P.x)
-	E.y.copy(P.y)
-	E.z.copy(P.z)
-	E.INF = P.INF
-}
-
-/* set this=O */
-func (E *ECP2) inf() {
-	E.INF = true
-	E.x.zero()
-	E.y.zero()
-	E.z.zero()
-}
-
-/* set this=-this */
-func (E *ECP2) neg() {
-	if E.is_infinity() {
-		return
-	}
-	E.y.neg()
-	E.y.reduce()
-}
-
-/* Conditional move of Q to P dependant on d */
-func (E *ECP2) cmove(Q *ECP2, d int32) {
-	E.x.cmove(Q.x, d)
-	E.y.cmove(Q.y, d)
-	E.z.cmove(Q.z, d)
-
-	var bd bool
-	if d == 0 {
-		bd = false
-	} else {
-		bd = true
-	}
-	E.INF = (E.INF != (E.INF != Q.INF) && bd)
-}
-
-/* Constant time select from pre-computed table */
-func (E *ECP2) selector(W []*ECP2, b int32) {
-	MP := NewECP2()
-	m := b >> 31
-	babs := (b ^ m) - m
-
-	babs = (babs - 1) / 2
-
-	E.cmove(W[0], teq(babs, 0)) // conditional move
-	E.cmove(W[1], teq(babs, 1))
-	E.cmove(W[2], teq(babs, 2))
-	E.cmove(W[3], teq(babs, 3))
-	E.cmove(W[4], teq(babs, 4))
-	E.cmove(W[5], teq(babs, 5))
-	E.cmove(W[6], teq(babs, 6))
-	E.cmove(W[7], teq(babs, 7))
-
-	MP.copy(E)
-	MP.neg()
-	E.cmove(MP, (m & 1))
-}
-
-/* Test if P == Q */
-func (E *ECP2) equals(Q *ECP2) bool {
-	if E.is_infinity() && Q.is_infinity() {
-		return true
-	}
-	if E.is_infinity() || Q.is_infinity() {
-		return false
-	}
-
-	zs2 := NewFP2copy(E.z)
-	zs2.sqr()
-	zo2 := NewFP2copy(Q.z)
-	zo2.sqr()
-	zs3 := NewFP2copy(zs2)
-	zs3.mul(E.z)
-	zo3 := NewFP2copy(zo2)
-	zo3.mul(Q.z)
-	zs2.mul(Q.x)
-	zo2.mul(E.x)
-	if !zs2.equals(zo2) {
-		return false
-	}
-	zs3.mul(Q.y)
-	zo3.mul(E.y)
-	if !zs3.equals(zo3) {
-		return false
-	}
-
-	return true
-}
-
-/* set to Affine - (x,y,z) to (x,y) */
-func (E *ECP2) affine() {
-	if E.is_infinity() {
-		return
-	}
-	one := NewFP2int(1)
-	if E.z.equals(one) {
-		return
-	}
-	E.z.inverse()
-
-	z2 := NewFP2copy(E.z)
-	z2.sqr()
-	E.x.mul(z2)
-	E.x.reduce()
-	E.y.mul(z2)
-	E.y.mul(E.z)
-	E.y.reduce()
-	E.z.copy(one)
-}
-
-/* extract affine x as FP2 */
-func (E *ECP2) getX() *FP2 {
-	E.affine()
-	return E.x
-}
-
-/* extract affine y as FP2 */
-func (E *ECP2) getY() *FP2 {
-	E.affine()
-	return E.y
-}
-
-/* extract projective x */
-func (E *ECP2) getx() *FP2 {
-	return E.x
-}
-
-/* extract projective y */
-func (E *ECP2) gety() *FP2 {
-	return E.y
-}
-
-/* extract projective z */
-func (E *ECP2) getz() *FP2 {
-	return E.z
-}
-
-/* convert to byte array */
-func (E *ECP2) toBytes(b []byte) {
-	var t [int(MODBYTES)]byte
-	MB := int(MODBYTES)
-
-	E.affine()
-	E.x.getA().toBytes(t[:])
-	for i := 0; i < MB; i++ {
-		b[i] = t[i]
-	}
-	E.x.getB().toBytes(t[:])
-	for i := 0; i < MB; i++ {
-		b[i+MB] = t[i]
-	}
-
-	E.y.getA().toBytes(t[:])
-	for i := 0; i < MB; i++ {
-		b[i+2*MB] = t[i]
-	}
-	E.y.getB().toBytes(t[:])
-	for i := 0; i < MB; i++ {
-		b[i+3*MB] = t[i]
-	}
-}
-
-/* convert from byte array to point */
-func ECP2_fromBytes(b []byte) *ECP2 {
-	var t [int(MODBYTES)]byte
-	MB := int(MODBYTES)
-
-	for i := 0; i < MB; i++ {
-		t[i] = b[i]
-	}
-	ra := fromBytes(t[:])
-	for i := 0; i < MB; i++ {
-		t[i] = b[i+MB]
-	}
-	rb := fromBytes(t[:])
-	rx := NewFP2bigs(ra, rb)
-
-	for i := 0; i < MB; i++ {
-		t[i] = b[i+2*MB]
-	}
-	ra = fromBytes(t[:])
-	for i := 0; i < MB; i++ {
-		t[i] = b[i+3*MB]
-	}
-	rb = fromBytes(t[:])
-	ry := NewFP2bigs(ra, rb)
-
-	return NewECP2fp2s(rx, ry)
-}
-
-/* convert this to hex string */
-func (E *ECP2) toString() string {
-	if E.is_infinity() {
-		return "infinity"
-	}
-	E.affine()
-	return "(" + E.x.toString() + "," + E.y.toString() + ")"
-}
-
-/* Calculate RHS of twisted curve equation x^3+B/i */
-func RHS2(x *FP2) *FP2 {
-	x.norm()
-	r := NewFP2copy(x)
-	r.sqr()
-	b := NewFP2big(NewBIGints(CURVE_B))
-	b.div_ip()
-	r.mul(x)
-	r.add(b)
-
-	r.reduce()
-	return r
-}
-
-/* construct this from (x,y) - but set to O if not on curve */
-func NewECP2fp2s(ix *FP2, iy *FP2) *ECP2 {
-	E := new(ECP2)
-	E.x = NewFP2copy(ix)
-	E.y = NewFP2copy(iy)
-	E.z = NewFP2int(1)
-	rhs := RHS2(E.x)
-	y2 := NewFP2copy(E.y)
-	y2.sqr()
-	if y2.equals(rhs) {
-		E.INF = false
-	} else {
-		E.x.zero()
-		E.INF = true
-	}
-	return E
-}
-
-/* construct this from x - but set to O if not on curve */
-func NewECP2fp2(ix *FP2) *ECP2 {
-	E := new(ECP2)
-	E.x = NewFP2copy(ix)
-	E.y = NewFP2int(1)
-	E.z = NewFP2int(1)
-	rhs := RHS2(E.x)
-	if rhs.sqrt() {
-		E.y.copy(rhs)
-		E.INF = false
-	} else {
-		E.x.zero()
-		E.INF = true
-	}
-	return E
-}
-
-/* this+=this */
-func (E *ECP2) dbl() int {
-	if E.INF {
-		return -1
-	}
-	if E.y.iszilch() {
-		E.inf()
-		return -1
-	}
-
-	w1 := NewFP2copy(E.x)
-	w2 := NewFP2int(0)
-	w3 := NewFP2copy(E.x)
-	w8 := NewFP2copy(E.x)
-
-	w1.sqr()
-	w8.copy(w1)
-	w8.imul(3)
-
-	w2.copy(E.y)
-	w2.sqr()
-	w3.copy(E.x)
-	w3.mul(w2)
-	w3.imul(4)
-	w1.copy(w3)
-	w1.neg()
-	//	w1.norm();
-
-	E.x.copy(w8)
-	E.x.sqr()
-	E.x.add(w1)
-	E.x.add(w1)
-	E.x.norm()
-
-	E.z.mul(E.y)
-	E.z.add(E.z)
-
-	w2.add(w2)
-	w2.sqr()
-	w2.add(w2)
-	w3.sub(E.x)
-	E.y.copy(w8)
-	E.y.mul(w3)
-	//	w2.norm();
-	E.y.sub(w2)
-
-	E.y.norm()
-	E.z.norm()
-
-	return 1
-}
-
-/* this+=Q - return 0 for add, 1 for double, -1 for O */
-func (E *ECP2) add(Q *ECP2) int {
-	if E.INF {
-		E.copy(Q)
-		return -1
-	}
-	if Q.INF {
-		return -1
-	}
-
-	aff := false
-
-	if Q.z.isunity() {
-		aff = true
-	}
-
-	var A, C *FP2
-	B := NewFP2copy(E.z)
-	D := NewFP2copy(E.z)
-	if !aff {
-		A = NewFP2copy(Q.z)
-		C = NewFP2copy(Q.z)
-
-		A.sqr()
-		B.sqr()
-		C.mul(A)
-		D.mul(B)
-
-		A.mul(E.x)
-		C.mul(E.y)
-	} else {
-		A = NewFP2copy(E.x)
-		C = NewFP2copy(E.y)
-
-		B.sqr()
-		D.mul(B)
-	}
-
-	B.mul(Q.x)
-	B.sub(A)
-	D.mul(Q.y)
-	D.sub(C)
-
-	if B.iszilch() {
-		if D.iszilch() {
-			E.dbl()
-			return 1
-		} else {
-			E.INF = true
-			return -1
-		}
-	}
-
-	if !aff {
-		E.z.mul(Q.z)
-	}
-	E.z.mul(B)
-
-	e := NewFP2copy(B)
-	e.sqr()
-	B.mul(e)
-	A.mul(e)
-
-	e.copy(A)
-	e.add(A)
-	e.add(B)
-	E.x.copy(D)
-	E.x.sqr()
-	E.x.sub(e)
-
-	A.sub(E.x)
-	E.y.copy(A)
-	E.y.mul(D)
-	C.mul(B)
-	E.y.sub(C)
-
-	E.x.norm()
-	E.y.norm()
-	E.z.norm()
-
-	return 0
-}
-
-/* set this-=Q */
-func (E *ECP2) sub(Q *ECP2) int {
-	Q.neg()
-	D := E.add(Q)
-	Q.neg()
-	return D
-}
-
-/* set this*=q, where q is Modulus, using Frobenius */
-func (E *ECP2) frob(X *FP2) {
-	if E.INF {
-		return
-	}
-	X2 := NewFP2copy(X)
-	X2.sqr()
-	E.x.conj()
-	E.y.conj()
-	E.z.conj()
-	E.z.reduce()
-	E.x.mul(X2)
-	E.y.mul(X2)
-	E.y.mul(X)
-}
-
-/* normalises m-array of ECP2 points. Requires work vector of m FP2s */
-
-func multiaffine2(m int, P []*ECP2) {
-	t1 := NewFP2int(0)
-	t2 := NewFP2int(0)
-
-	var work []*FP2
-
-	for i := 0; i < m; i++ {
-		work = append(work, NewFP2int(0))
-	}
-
-	work[0].one()
-	work[1].copy(P[0].z)
-
-	for i := 2; i < m; i++ {
-		work[i].copy(work[i-1])
-		work[i].mul(P[i-1].z)
-	}
-
-	t1.copy(work[m-1])
-	t1.mul(P[m-1].z)
-
-	t1.inverse()
-
-	t2.copy(P[m-1].z)
-	work[m-1].mul(t1)
-
-	for i := m - 2; ; i-- {
-		if i == 0 {
-			work[0].copy(t1)
-			work[0].mul(t2)
-			break
-		}
-		work[i].mul(t2)
-		work[i].mul(t1)
-		t2.mul(P[i].z)
-	}
-	/* now work[] contains inverses of all Z coordinates */
-
-	for i := 0; i < m; i++ {
-		P[i].z.one()
-		t1.copy(work[i])
-		t1.sqr()
-		P[i].x.mul(t1)
-		t1.mul(work[i])
-		P[i].y.mul(t1)
-	}
-}
-
-/* P*=e */
-func (E *ECP2) mul(e *BIG) *ECP2 {
-	/* fixed size windows */
-	mt := NewBIG()
-	t := NewBIG()
-	P := NewECP2()
-	Q := NewECP2()
-	C := NewECP2()
-
-	if E.is_infinity() {
-		return NewECP2()
-	}
-
-	var W []*ECP2
-	var w [1 + (NLEN*int(BASEBITS)+3)/4]int8
-
-	E.affine()
-
-	/* precompute table */
-	Q.copy(E)
-	Q.dbl()
-
-	W = append(W, NewECP2())
-	W[0].copy(E)
-
-	for i := 1; i < 8; i++ {
-		W = append(W, NewECP2())
-		W[i].copy(W[i-1])
-		W[i].add(Q)
-	}
-
-	/* convert the table to affine */
-
-	multiaffine2(8, W[:])
-
-	/* make exponent odd - add 2P if even, P if odd */
-	t.copy(e)
-	s := int32(t.parity())
-	t.inc(1)
-	t.norm()
-	ns := int32(t.parity())
-	mt.copy(t)
-	mt.inc(1)
-	mt.norm()
-	t.cmove(mt, s)
-	Q.cmove(E, ns)
-	C.copy(Q)
-
-	nb := 1 + (t.nbits()+3)/4
-	/* convert exponent to signed 4-bit window */
-	for i := 0; i < nb; i++ {
-		w[i] = int8(t.lastbits(5) - 16)
-		t.dec(int(w[i]))
-		t.norm()
-		t.fshr(4)
-	}
-	w[nb] = int8(t.lastbits(5))
-
-	P.copy(W[(w[nb]-1)/2])
-	for i := nb - 1; i >= 0; i-- {
-		Q.selector(W, int32(w[i]))
-		P.dbl()
-		P.dbl()
-		P.dbl()
-		P.dbl()
-		P.add(Q)
-	}
-	P.sub(C)
-	P.affine()
-	return P
-}
-
-/* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3 */
-func mul4(Q []*ECP2, u []*BIG) *ECP2 {
-	var a [4]int8
-	T := NewECP2()
-	C := NewECP2()
-	P := NewECP2()
-
-	var W []*ECP2
-
-	mt := NewBIG()
-	var t []*BIG
-
-	var w [NLEN*int(BASEBITS) + 1]int8
-
-	for i := 0; i < 4; i++ {
-		t = append(t, NewBIGcopy(u[i]))
-		Q[i].affine()
-	}
-
-	/* precompute table */
-
-	W = append(W, NewECP2())
-	W[0].copy(Q[0])
-	W[0].sub(Q[1])
-	W = append(W, NewECP2())
-	W[1].copy(W[0])
-	W = append(W, NewECP2())
-	W[2].copy(W[0])
-	W = append(W, NewECP2())
-	W[3].copy(W[0])
-	W = append(W, NewECP2())
-	W[4].copy(Q[0])
-	W[4].add(Q[1])
-	W = append(W, NewECP2())
-	W[5].copy(W[4])
-	W = append(W, NewECP2())
-	W[6].copy(W[4])
-	W = append(W, NewECP2())
-	W[7].copy(W[4])
-
-	T.copy(Q[2])
-	T.sub(Q[3])
-	W[1].sub(T)
-	W[2].add(T)
-	W[5].sub(T)
-	W[6].add(T)
-	T.copy(Q[2])
-	T.add(Q[3])
-	W[0].sub(T)
-	W[3].add(T)
-	W[4].sub(T)
-	W[7].add(T)
-
-	multiaffine2(8, W[:])
-
-	/* if multiplier is even add 1 to multiplier, and add P to correction */
-	mt.zero()
-	C.inf()
-	for i := 0; i < 4; i++ {
-		if t[i].parity() == 0 {
-			t[i].inc(1)
-			t[i].norm()
-			C.add(Q[i])
-		}
-		mt.add(t[i])
-		mt.norm()
-	}
-
-	nb := 1 + mt.nbits()
-
-	/* convert exponent to signed 1-bit window */
-	for j := 0; j < nb; j++ {
-		for i := 0; i < 4; i++ {
-			a[i] = int8(t[i].lastbits(2) - 2)
-			t[i].dec(int(a[i]))
-			t[i].norm()
-			t[i].fshr(1)
-		}
-		w[j] = (8*a[0] + 4*a[1] + 2*a[2] + a[3])
-	}
-	w[nb] = int8(8*t[0].lastbits(2) + 4*t[1].lastbits(2) + 2*t[2].lastbits(2) + t[3].lastbits(2))
-
-	P.copy(W[(w[nb]-1)/2])
-	for i := nb - 1; i >= 0; i-- {
-		T.selector(W, int32(w[i]))
-		P.dbl()
-		P.add(T)
-	}
-	P.sub(C) /* apply correction */
-
-	P.affine()
-	return P
-}
diff --git a/go/amcl-go/FF.go b/go/amcl-go/FF.go
deleted file mode 100644
index 9e6e68c..0000000
--- a/go/amcl-go/FF.go
+++ /dev/null
@@ -1,926 +0,0 @@
-/*
-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.
-*/
-
-package amcl
-
-//import "fmt"
-
-const P_MBITS uint = MODBYTES * 8
-const P_MB uint = (P_MBITS % BASEBITS)
-const P_OMASK int64 = (int64(-1) << (P_MBITS % BASEBITS))
-const P_FEXCESS int64 = (int64(1) << (BASEBITS*uint(NLEN) - P_MBITS))
-const P_TBITS uint = (P_MBITS % BASEBITS)
-
-type FF struct {
-	length int
-	v      []*BIG
-}
-
-func (F *FF) P_EXCESS() int64 {
-	return ((F.v[F.length-1].get(NLEN-1) & P_OMASK) >> (P_MB))
-}
-
-/* Constructors */
-func NewFFint(n int) *FF {
-	F := new(FF)
-	for i := 0; i < n; i++ {
-		F.v = append(F.v, NewBIG())
-	}
-	F.length = n
-	return F
-}
-
-func NewFFints(x [][5]int64, n int) *FF {
-	F := new(FF)
-	for i := 0; i < n; i++ {
-		F.v = append(F.v, NewBIGints(x[i]))
-	}
-	F.length = n
-	return F
-}
-
-/* set to zero */
-func (F *FF) zero() {
-	for i := 0; i < F.length; i++ {
-		F.v[i].zero()
-	}
-}
-
-func (F *FF) getlen() int {
-	return F.length
-}
-
-/* set to integer */
-func (F *FF) set(m int) {
-	F.zero()
-	F.v[0].set(0, int64(m))
-}
-
-/* copy from FF b */
-func (F *FF) copy(b *FF) {
-	for i := 0; i < F.length; i++ {
-		F.v[i].copy(b.v[i])
-	}
-}
-
-/* x=y<<n */
-func (F *FF) dsucopy(b *FF) {
-	for i := 0; i < b.length; i++ {
-		F.v[b.length+i].copy(b.v[i])
-		F.v[i].zero()
-	}
-}
-
-/* x=y */
-func (F *FF) dscopy(b *FF) {
-	for i := 0; i < b.length; i++ {
-		F.v[i].copy(b.v[i])
-		F.v[b.length+i].zero()
-	}
-}
-
-/* x=y>>n */
-func (F *FF) sducopy(b *FF) {
-	for i := 0; i < F.length; i++ {
-		F.v[i].copy(b.v[F.length+i])
-	}
-}
-
-func (F *FF) one() {
-	F.v[0].one()
-	for i := 1; i < F.length; i++ {
-		F.v[i].zero()
-	}
-}
-
-/* test equals 0 */
-func (F *FF) iszilch() bool {
-	for i := 0; i < F.length; i++ {
-		if !F.v[i].iszilch() {
-			return false
-		}
-	}
-	return true
-}
-
-/* shift right by 256-bit words */
-func (F *FF) shrw(n int) {
-	for i := 0; i < n; i++ {
-		F.v[i].copy(F.v[i+n])
-		F.v[i+n].zero()
-	}
-}
-
-/* shift left by 256-bit words */
-func (F *FF) shlw(n int) {
-	for i := 0; i < n; i++ {
-		F.v[n+i].copy(F.v[i])
-		F.v[i].zero()
-	}
-}
-
-/* extract last bit */
-func (F *FF) parity() int {
-	return F.v[0].parity()
-}
-
-func (F *FF) lastbits(m int) int {
-	return F.v[0].lastbits(m)
-}
-
-/* compare x and y - must be normalised, and of same length */
-func ff_comp(a *FF, b *FF) int {
-	for i := a.length - 1; i >= 0; i-- {
-		j := comp(a.v[i], b.v[i])
-		if j != 0 {
-			return j
-		}
-	}
-	return 0
-}
-
-/* recursive add */
-func (F *FF) radd(vp int, x *FF, xp int, y *FF, yp int, n int) {
-	for i := 0; i < n; i++ {
-		F.v[vp+i].copy(x.v[xp+i])
-		F.v[vp+i].add(y.v[yp+i])
-	}
-}
-
-/* recursive inc */
-func (F *FF) rinc(vp int, y *FF, yp int, n int) {
-	for i := 0; i < n; i++ {
-		F.v[vp+i].add(y.v[yp+i])
-	}
-}
-
-/* recursive sub */
-func (F *FF) rsub(vp int, x *FF, xp int, y *FF, yp int, n int) {
-	for i := 0; i < n; i++ {
-		F.v[vp+i].copy(x.v[xp+i])
-		F.v[vp+i].sub(y.v[yp+i])
-	}
-}
-
-/* recursive dec */
-func (F *FF) rdec(vp int, y *FF, yp int, n int) {
-	for i := 0; i < n; i++ {
-		F.v[vp+i].sub(y.v[yp+i])
-	}
-}
-
-/* simple add */
-func (F *FF) add(b *FF) {
-	for i := 0; i < F.length; i++ {
-		F.v[i].add(b.v[i])
-	}
-}
-
-/* simple sub */
-func (F *FF) sub(b *FF) {
-	for i := 0; i < F.length; i++ {
-		F.v[i].sub(b.v[i])
-	}
-}
-
-/* reverse sub */
-func (F *FF) revsub(b *FF) {
-	for i := 0; i < F.length; i++ {
-		F.v[i].rsub(b.v[i])
-	}
-}
-
-/* normalise - but hold any overflow in top part unless n<0 */
-func (F *FF) rnorm(vp int, n int) {
-	trunc := false
-	var carry int64
-	if n < 0 { /* -v n signals to do truncation */
-		n = -n
-		trunc = true
-	}
-	for i := 0; i < n-1; i++ {
-		carry = F.v[vp+i].norm()
-		F.v[vp+i].xortop(carry << P_TBITS)
-		F.v[vp+i+1].inc(int(carry))
-	}
-	carry = F.v[vp+n-1].norm()
-	if trunc {
-		F.v[vp+n-1].xortop(carry << P_TBITS)
-	}
-
-}
-
-func (F *FF) norm() {
-	F.rnorm(0, F.length)
-}
-
-/* increment/decrement by a small integer */
-func (F *FF) inc(m int) {
-	F.v[0].inc(m)
-	F.norm()
-}
-
-func (F *FF) dec(m int) {
-	F.v[0].dec(m)
-	F.norm()
-}
-
-/* shift left by one bit */
-func (F *FF) shl() {
-	var delay_carry int = 0
-	for i := 0; i < F.length-1; i++ {
-		carry := F.v[i].fshl(1)
-		F.v[i].inc(delay_carry)
-		F.v[i].xortop(carry << P_TBITS)
-		delay_carry = int(carry)
-	}
-	F.v[F.length-1].fshl(1)
-	F.v[F.length-1].inc(delay_carry)
-}
-
-/* shift right by one bit */
-
-func (F *FF) shr() {
-	for i := F.length - 1; i > 0; i-- {
-		carry := F.v[i].fshr(1)
-		F.v[i-1].ortop(carry << P_TBITS)
-	}
-	F.v[0].fshr(1)
-}
-
-/* Convert to Hex String */
-func (F *FF) toString() string {
-	F.norm()
-	s := ""
-	for i := F.length - 1; i >= 0; i-- {
-		s += F.v[i].toString()
-	}
-	return s
-}
-
-/* Convert FFs to/from byte arrays */
-func (F *FF) toBytes(b []byte) {
-	for i := 0; i < F.length; i++ {
-		F.v[i].tobytearray(b, (F.length-i-1)*int(MODBYTES))
-	}
-}
-
-func ff_fromBytes(x *FF, b []byte) {
-	for i := 0; i < x.length; i++ {
-		x.v[i] = frombytearray(b, (x.length-i-1)*int(MODBYTES))
-	}
-}
-
-/* in-place swapping using xor - side channel resistant - lengths must be the same */
-func ff_cswap(a *FF, b *FF, d int32) {
-	for i := 0; i < a.length; i++ {
-		a.v[i].cswap(b.v[i], d)
-	}
-}
-
-/* z=x*y, t is workspace */
-func (F *FF) karmul(vp int, x *FF, xp int, y *FF, yp int, t *FF, tp int, n int) {
-	if n == 1 {
-		d := mul(x.v[xp], y.v[yp])
-		F.v[vp+1] = d.split(8 * MODBYTES)
-		F.v[vp].dcopy(d)
-		return
-	}
-	nd2 := n / 2
-	F.radd(vp, x, xp, x, xp+nd2, nd2)
-	F.radd(vp+nd2, y, yp, y, yp+nd2, nd2)
-	t.karmul(tp, F, vp, F, vp+nd2, t, tp+n, nd2)
-	F.karmul(vp, x, xp, y, yp, t, tp+n, nd2)
-	F.karmul(vp+n, x, xp+nd2, y, yp+nd2, t, tp+n, nd2)
-	t.rdec(tp, F, vp, n)
-	t.rdec(tp, F, vp+n, n)
-	F.rinc(vp+nd2, t, tp, n)
-	F.rnorm(vp, 2*n)
-}
-
-func (F *FF) karsqr(vp int, x *FF, xp int, t *FF, tp int, n int) {
-	if n == 1 {
-		d := sqr(x.v[xp])
-		F.v[vp+1].copy(d.split(8 * MODBYTES))
-		F.v[vp].dcopy(d)
-		return
-	}
-
-	nd2 := n / 2
-	F.karsqr(vp, x, xp, t, tp+n, nd2)
-	F.karsqr(vp+n, x, xp+nd2, t, tp+n, nd2)
-	t.karmul(tp, x, xp, x, xp+nd2, t, tp+n, nd2)
-	F.rinc(vp+nd2, t, tp, n)
-	F.rinc(vp+nd2, t, tp, n)
-	F.rnorm(vp+nd2, n)
-}
-
-/* Calculates Least Significant bottom half of x*y */
-func (F *FF) karmul_lower(vp int, x *FF, xp int, y *FF, yp int, t *FF, tp int, n int) {
-	if n == 1 { /* only calculate bottom half of product */
-		F.v[vp].copy(smul(x.v[xp], y.v[yp]))
-		return
-	}
-	nd2 := n / 2
-
-	F.karmul(vp, x, xp, y, yp, t, tp+n, nd2)
-	t.karmul_lower(tp, x, xp+nd2, y, yp, t, tp+n, nd2)
-	F.rinc(vp+nd2, t, tp, nd2)
-	t.karmul_lower(tp, x, xp, y, yp+nd2, t, tp+n, nd2)
-	F.rinc(vp+nd2, t, tp, nd2)
-	F.rnorm(vp+nd2, -nd2) /* truncate it */
-}
-
-/* Calculates Most Significant upper half of x*y, given lower part */
-func (F *FF) karmul_upper(x *FF, y *FF, t *FF, n int) {
-	nd2 := n / 2
-	F.radd(n, x, 0, x, nd2, nd2)
-	F.radd(n+nd2, y, 0, y, nd2, nd2)
-
-	t.karmul(0, F, n+nd2, F, n, t, n, nd2) /* t = (a0+a1)(b0+b1) */
-	F.karmul(n, x, nd2, y, nd2, t, n, nd2) /* z[n]= a1*b1 */
-	/* z[0-nd2]=l(a0b0) z[nd2-n]= h(a0b0)+l(t)-l(a0b0)-l(a1b1) */
-	t.rdec(0, F, n, n)     /* t=t-a1b1  */
-	F.rinc(nd2, F, 0, nd2) /* z[nd2-n]+=l(a0b0) = h(a0b0)+l(t)-l(a1b1)  */
-	F.rdec(nd2, t, 0, nd2) /* z[nd2-n]=h(a0b0)+l(t)-l(a1b1)-l(t-a1b1)=h(a0b0) */
-	F.rnorm(0, -n)         /* a0b0 now in z - truncate it */
-	t.rdec(0, F, 0, n)     /* (a0+a1)(b0+b1) - a0b0 */
-	F.rinc(nd2, t, 0, n)
-
-	F.rnorm(nd2, n)
-}
-
-/* z=x*y. Assumes x and y are of same length. */
-func ff_mul(x *FF, y *FF) *FF {
-	n := x.length
-	z := NewFFint(2 * n)
-	t := NewFFint(2 * n)
-	z.karmul(0, x, 0, y, 0, t, 0, n)
-	return z
-}
-
-/* return low part of product this*y */
-func (F *FF) lmul(y *FF) {
-	n := F.length
-	t := NewFFint(2 * n)
-	x := NewFFint(n)
-	x.copy(F)
-	F.karmul_lower(0, x, 0, y, 0, t, 0, n)
-}
-
-/* Set b=b mod c */
-func (F *FF) mod(c *FF) {
-	var k int = 1
-
-	F.norm()
-	if ff_comp(F, c) < 0 {
-		return
-	}
-
-	c.shl()
-	for ff_comp(F, c) >= 0 {
-		c.shl()
-		k++
-	}
-
-	for k > 0 {
-		c.shr()
-		if ff_comp(F, c) >= 0 {
-			F.sub(c)
-			F.norm()
-		}
-		k--
-	}
-}
-
-/* z=x^2 */
-func ff_sqr(x *FF) *FF {
-	n := x.length
-	z := NewFFint(2 * n)
-	t := NewFFint(2 * n)
-	z.karsqr(0, x, 0, t, 0, n)
-	return z
-}
-
-/* return This mod modulus, N is modulus, ND is Montgomery Constant */
-func (F *FF) reduce(N *FF, ND *FF) *FF { /* fast karatsuba Montgomery reduction */
-	n := N.length
-	t := NewFFint(2 * n)
-	r := NewFFint(n)
-	m := NewFFint(n)
-
-	r.sducopy(F)
-	m.karmul_lower(0, F, 0, ND, 0, t, 0, n)
-	F.karmul_upper(N, m, t, n)
-	m.sducopy(F)
-
-	r.add(N)
-	r.sub(m)
-	r.norm()
-
-	return r
-
-}
-
-/* Set r=this mod b */
-/* this is of length - 2*n */
-/* r,b is of length - n */
-func (F *FF) dmod(b *FF) *FF {
-	n := b.length
-	m := NewFFint(2 * n)
-	x := NewFFint(2 * n)
-	r := NewFFint(n)
-
-	x.copy(F)
-	x.norm()
-	m.dsucopy(b)
-	k := 256 * n
-
-	for k > 0 {
-		m.shr()
-
-		if ff_comp(x, m) >= 0 {
-			x.sub(m)
-			x.norm()
-		}
-		k--
-	}
-
-	r.copy(x)
-	r.mod(b)
-	return r
-}
-
-/* Set return=1/this mod p. Binary method - a<p on entry */
-
-func (F *FF) invmodp(p *FF) {
-	n := p.length
-
-	u := NewFFint(n)
-	v := NewFFint(n)
-	x1 := NewFFint(n)
-	x2 := NewFFint(n)
-	t := NewFFint(n)
-	one := NewFFint(n)
-
-	one.one()
-	u.copy(F)
-	v.copy(p)
-	x1.copy(one)
-	x2.zero()
-
-	// reduce n in here as well!
-	for ff_comp(u, one) != 0 && ff_comp(v, one) != 0 {
-		for u.parity() == 0 {
-			u.shr()
-			if x1.parity() != 0 {
-				x1.add(p)
-				x1.norm()
-			}
-			x1.shr()
-		}
-		for v.parity() == 0 {
-			v.shr()
-			if x2.parity() != 0 {
-				x2.add(p)
-				x2.norm()
-			}
-			x2.shr()
-		}
-		if ff_comp(u, v) >= 0 {
-			u.sub(v)
-			u.norm()
-			if ff_comp(x1, x2) >= 0 {
-				x1.sub(x2)
-			} else {
-				t.copy(p)
-				t.sub(x2)
-				x1.add(t)
-			}
-			x1.norm()
-		} else {
-			v.sub(u)
-			v.norm()
-			if ff_comp(x2, x1) >= 0 {
-				x2.sub(x1)
-			} else {
-				t.copy(p)
-				t.sub(x1)
-				x2.add(t)
-			}
-			x2.norm()
-		}
-	}
-	if ff_comp(u, one) == 0 {
-		F.copy(x1)
-	} else {
-		F.copy(x2)
-	}
-}
-
-/* nresidue mod m */
-func (F *FF) nres(m *FF) {
-	n := m.length
-	d := NewFFint(2 * n)
-	d.dsucopy(F)
-	F.copy(d.dmod(m))
-}
-
-func (F *FF) redc(m *FF, ND *FF) {
-	n := m.length
-	d := NewFFint(2 * n)
-	F.mod(m)
-	d.dscopy(F)
-	F.copy(d.reduce(m, ND))
-	F.mod(m)
-}
-
-func (F *FF) mod2m(m int) {
-	for i := m; i < F.length; i++ {
-		F.v[i].zero()
-	}
-}
-
-/* U=1/a mod 2^m - Arazi & Qi */
-func (F *FF) invmod2m() *FF {
-	n := F.length
-
-	b := NewFFint(n)
-	c := NewFFint(n)
-	U := NewFFint(n)
-
-	U.zero()
-	U.v[0].copy(F.v[0])
-	U.v[0].invmod2m()
-
-	for i := 1; i < n; i <<= 1 {
-		b.copy(F)
-		b.mod2m(i)
-		t := ff_mul(U, b)
-		t.shrw(i)
-		b.copy(t)
-		c.copy(F)
-		c.shrw(i)
-		c.mod2m(i)
-		c.lmul(U)
-		c.mod2m(i)
-
-		b.add(c)
-		b.norm()
-		b.lmul(U)
-		b.mod2m(i)
-
-		c.one()
-		c.shlw(i)
-		b.revsub(c)
-		b.norm()
-		b.shlw(i)
-		U.add(b)
-	}
-	U.norm()
-	return U
-}
-
-func (F *FF) random(rng *RAND) {
-	n := F.length
-	for i := 0; i < n; i++ {
-		F.v[i].copy(random(rng))
-	}
-	/* make sure top bit is 1 */
-	for F.v[n-1].nbits() < int(MODBYTES*8) {
-		F.v[n-1].copy(random(rng))
-	}
-}
-
-/* generate random x less than p */
-func (F *FF) randomnum(p *FF, rng *RAND) {
-	n := F.length
-	d := NewFFint(2 * n)
-
-	for i := 0; i < 2*n; i++ {
-		d.v[i].copy(random(rng))
-	}
-	F.copy(d.dmod(p))
-}
-
-/* this*=y mod p */
-func (F *FF) modmul(y *FF, p *FF, nd *FF) {
-	ex := F.P_EXCESS()
-	ey := y.P_EXCESS()
-	if (ex+1)*(ey+1)+1 >= P_FEXCESS {
-		F.mod(p)
-	}
-	d := ff_mul(F, y)
-	F.copy(d.reduce(p, nd))
-}
-
-/* this*=y mod p */
-func (F *FF) modsqr(p *FF, nd *FF) {
-	ex := F.P_EXCESS()
-	if (ex+1)*(ex+1)+1 >= P_FEXCESS {
-		F.mod(p)
-	}
-	d := ff_sqr(F)
-	F.copy(d.reduce(p, nd))
-}
-
-/* this=this^e mod p using side-channel resistant Montgomery Ladder, for large e */
-func (F *FF) skpow(e *FF, p *FF) {
-	n := p.length
-	R0 := NewFFint(n)
-	R1 := NewFFint(n)
-	ND := p.invmod2m()
-
-	F.mod(p)
-	R0.one()
-	R1.copy(F)
-	R0.nres(p)
-	R1.nres(p)
-
-	for i := int(8*MODBYTES)*n - 1; i >= 0; i-- {
-		b := int32(e.v[i/256].bit(i % 256))
-		F.copy(R0)
-		F.modmul(R1, p, ND)
-
-		ff_cswap(R0, R1, b)
-		R0.modsqr(p, ND)
-
-		R1.copy(F)
-		ff_cswap(R0, R1, b)
-	}
-	F.copy(R0)
-	F.redc(p, ND)
-}
-
-/* this =this^e mod p using side-channel resistant Montgomery Ladder, for short e */
-func (F *FF) skpows(e *BIG, p *FF) {
-	n := p.length
-	R0 := NewFFint(n)
-	R1 := NewFFint(n)
-	ND := p.invmod2m()
-
-	F.mod(p)
-	R0.one()
-	R1.copy(F)
-	R0.nres(p)
-	R1.nres(p)
-
-	for i := int(8*MODBYTES) - 1; i >= 0; i-- {
-		b := int32(e.bit(i))
-		F.copy(R0)
-		F.modmul(R1, p, ND)
-
-		ff_cswap(R0, R1, b)
-		R0.modsqr(p, ND)
-
-		R1.copy(F)
-		ff_cswap(R0, R1, b)
-	}
-	F.copy(R0)
-	F.redc(p, ND)
-}
-
-/* raise to an integer power - right-to-left method */
-func (F *FF) power(e int, p *FF) {
-	n := p.length
-	w := NewFFint(n)
-	ND := p.invmod2m()
-	f := true
-
-	w.copy(F)
-	w.nres(p)
-
-	if e == 2 {
-		F.copy(w)
-		F.modsqr(p, ND)
-	} else {
-		for true {
-			if e%2 == 1 {
-				if f {
-					F.copy(w)
-				} else {
-					F.modmul(w, p, ND)
-				}
-				f = false
-			}
-			e >>= 1
-			if e == 0 {
-				break
-			}
-			w.modsqr(p, ND)
-		}
-	}
-	F.redc(p, ND)
-}
-
-/* this=this^e mod p, faster but not side channel resistant */
-func (F *FF) pow(e *FF, p *FF) {
-	n := p.length
-	w := NewFFint(n)
-	ND := p.invmod2m()
-
-	w.copy(F)
-	F.one()
-	F.nres(p)
-	w.nres(p)
-	for i := int(8*MODBYTES)*n - 1; i >= 0; i-- {
-		F.modsqr(p, ND)
-		b := e.v[i/256].bit(i % 256)
-		if b == 1 {
-			F.modmul(w, p, ND)
-		}
-	}
-	F.redc(p, ND)
-}
-
-/* double exponentiation r=x^e.y^f mod p */
-func (F *FF) pow2(e *BIG, y *FF, f *BIG, p *FF) {
-	n := p.length
-	xn := NewFFint(n)
-	yn := NewFFint(n)
-	xy := NewFFint(n)
-	ND := p.invmod2m()
-
-	xn.copy(F)
-	yn.copy(y)
-	xn.nres(p)
-	yn.nres(p)
-	xy.copy(xn)
-	xy.modmul(yn, p, ND)
-	F.one()
-	F.nres(p)
-
-	for i := int(8*MODBYTES) - 1; i >= 0; i-- {
-		eb := e.bit(i)
-		fb := f.bit(i)
-		F.modsqr(p, ND)
-		if eb == 1 {
-			if fb == 1 {
-				F.modmul(xy, p, ND)
-			} else {
-				F.modmul(xn, p, ND)
-			}
-		} else {
-			if fb == 1 {
-				F.modmul(yn, p, ND)
-			}
-		}
-	}
-	F.redc(p, ND)
-}
-
-func igcd(x int, y int) int { /* integer GCD, returns GCD of x and y */
-	var r int
-	if y == 0 {
-		return x
-	}
-	for true {
-		r = x % y
-		if r == 0 {
-			break
-		}
-		x = y
-		y = r
-	}
-	return y
-}
-
-/* quick and dirty check for common factor with n */
-func (F *FF) cfactor(s int) bool {
-	n := F.length
-
-	x := NewFFint(n)
-	y := NewFFint(n)
-
-	y.set(s)
-	x.copy(F)
-	x.norm()
-
-	x.sub(y)
-	x.norm()
-
-	for !x.iszilch() && x.parity() == 0 {
-		x.shr()
-	}
-
-	for ff_comp(x, y) > 0 {
-		x.sub(y)
-		x.norm()
-		for !x.iszilch() && x.parity() == 0 {
-			x.shr()
-		}
-	}
-
-	g := int(x.v[0].get(0))
-	r := igcd(s, g)
-	if r > 1 {
-		return true
-	}
-	return false
-}
-
-/* Miller-Rabin test for primality. Slow. */
-func prime(p *FF, rng *RAND) bool {
-	s := 0
-	n := p.length
-	d := NewFFint(n)
-	x := NewFFint(n)
-	unity := NewFFint(n)
-	nm1 := NewFFint(n)
-
-	sf := 4849845 /* 3*5*.. *19 */
-	p.norm()
-
-	if p.cfactor(sf) {
-		return false
-	}
-	unity.one()
-	nm1.copy(p)
-	nm1.sub(unity)
-	nm1.norm()
-	d.copy(nm1)
-
-	for d.parity() == 0 {
-		d.shr()
-		s++
-	}
-	if s == 0 {
-		return false
-	}
-	for i := 0; i < 10; i++ {
-		x.randomnum(p, rng)
-		x.pow(d, p)
-		if ff_comp(x, unity) == 0 || ff_comp(x, nm1) == 0 {
-			continue
-		}
-		loop := false
-		for j := 1; j < s; j++ {
-			x.power(2, p)
-			if ff_comp(x, unity) == 0 {
-				return false
-			}
-			if ff_comp(x, nm1) == 0 {
-				loop = true
-				break
-			}
-		}
-		if loop {
-			continue
-		}
-		return false
-	}
-	return true
-}
-
-/*
-func main() {
-
-	var P = [4][5]int64 {{0xAD19A781670957,0x76A79C00965796,0xDEFCC5FC9A9717,0xF02F2940E20E9,0xBF59E34F},{0x6894F31844C908,0x8DADA70E82C79F,0xFD29F3836046F6,0x8C1D874D314DD0,0x46D077B},{0x3C515217813331,0x56680FD1CE935B,0xE55C53EEA8838E,0x92C2F7E14A4A95,0xD945E5B1},{0xACF673E919F5EF,0x6723E7E7DAB446,0x6B6FA69B36EB1B,0xF7D13920ECA300,0xB5FC2165}}
-
-	fmt.Printf("Testing FF\n")
-	var raw [100]byte
-	rng:=NewRAND()
-
-	rng.Clean()
-	for i:=0;i<100;i++ {
-		raw[i]=byte(i)
-	}
-
-	rng.Seed(100,raw[:])
-
-	n:=4
-
-	x:=NewFFint(n)
-	x.set(3)
-
-	p:=NewFFints(P[:],n)
-
-	if prime(p,rng) {fmt.Printf("p is a prime\n"); fmt.Printf("\n")}
-
-	e:=NewFFint(n)
-	e.copy(p)
-	e.dec(1); e.norm()
-
-	fmt.Printf("e= "+e.toString())
-	fmt.Printf("\n")
-	x.skpow(e,p)
-	fmt.Printf("x= "+x.toString())
-	fmt.Printf("\n")
-}
-*/
diff --git a/go/amcl-go/FP.go b/go/amcl-go/FP.go
deleted file mode 100644
index c8a4d62..0000000
--- a/go/amcl-go/FP.go
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
-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.
-*/
-
-/* Finite Field arithmetic */
-/* CLINT mod p functions */
-
-package amcl
-
-//import "fmt"
-
-var p BIG = BIG{w: [NLEN]int64(Modulus)}
-
-type FP struct {
-	x *BIG
-}
-
-/* Constructors */
-func NewFPint(a int) *FP {
-	F := new(FP)
-	F.x = NewBIGint(a)
-	F.nres()
-	return F
-}
-
-func NewFPbig(a *BIG) *FP {
-	F := new(FP)
-	F.x = NewBIGcopy(a)
-	F.nres()
-	return F
-}
-
-func NewFPcopy(a *FP) *FP {
-	F := new(FP)
-	F.x = NewBIGcopy(a.x)
-	return F
-}
-
-func (F *FP) toString() string {
-	return F.redc().toString()
-}
-
-/* convert to Montgomery n-residue form */
-func (F *FP) nres() {
-	if MODTYPE != PSEUDO_MERSENNE {
-		d := NewDBIGscopy(F.x)
-		d.shl(uint(NLEN) * BASEBITS)
-		F.x.copy(d.mod(&p))
-	}
-}
-
-/* convert back to regular form */
-func (F *FP) redc() *BIG {
-	if MODTYPE != PSEUDO_MERSENNE {
-		d := NewDBIGscopy(F.x)
-		return mod(d)
-	} else {
-		r := NewBIGcopy(F.x)
-		return r
-	}
-}
-
-/* reduce this mod Modulus */
-func (F *FP) reduce() {
-	F.x.mod(&p)
-}
-
-/* test this=0? */
-func (F *FP) iszilch() bool {
-	F.reduce()
-	return F.x.iszilch()
-}
-
-/* copy from FP b */
-func (F *FP) copy(b *FP) {
-	F.x.copy(b.x)
-}
-
-/* set this=0 */
-func (F *FP) zero() {
-	F.x.zero()
-}
-
-/* set this=1 */
-func (F *FP) one() {
-	F.x.one()
-	F.nres()
-}
-
-/* normalise this */
-func (F *FP) norm() {
-	F.x.norm()
-}
-
-/* swap FPs depending on d */
-func (F *FP) cswap(b *FP, d int32) {
-	F.x.cswap(b.x, d)
-}
-
-/* copy FPs depending on d */
-func (F *FP) cmove(b *FP, d int32) {
-	F.x.cmove(b.x, d)
-}
-
-/* this*=b mod Modulus */
-func (F *FP) mul(b *FP) {
-	ea := EXCESS(F.x)
-	eb := EXCESS(b.x)
-
-	if (ea+1)*(eb+1)+1 >= FEXCESS {
-		F.reduce()
-	}
-
-	d := mul(F.x, b.x)
-	F.x.copy(mod(d))
-}
-
-/* this = -this mod Modulus */
-func (F *FP) neg() {
-	m := NewBIGcopy(&p)
-
-	F.norm()
-
-	ov := EXCESS(F.x)
-	sb := uint(1)
-	for ov != 0 {
-		sb++
-		ov >>= 1
-	}
-
-	m.fshl(sb)
-	F.x.rsub(m)
-
-	if EXCESS(F.x) >= FEXCESS {
-		F.reduce()
-	}
-}
-
-/* this*=c mod Modulus, where c is a small int */
-func (F *FP) imul(c int) {
-	F.norm()
-	s := false
-	if c < 0 {
-		c = -c
-		s = true
-	}
-	afx := (EXCESS(F.x)+1)*(int64(c)+1) + 1
-	if c < NEXCESS && afx < FEXCESS {
-		F.x.imul(c)
-	} else {
-		if afx < FEXCESS {
-			F.x.pmul(c)
-		} else {
-			d := F.x.pxmul(c)
-			F.x.copy(d.mod(&p))
-		}
-	}
-	if s {
-		F.neg()
-	}
-	F.norm()
-}
-
-/* this*=this mod Modulus */
-func (F *FP) sqr() {
-	ea := EXCESS(F.x)
-	if (ea+1)*(ea+1)+1 >= FEXCESS {
-		F.reduce()
-	}
-
-	d := sqr(F.x)
-
-	F.x.copy(mod(d))
-}
-
-/* this+=b */
-func (F *FP) add(b *FP) {
-	F.x.add(b.x)
-	if EXCESS(F.x)+2 >= FEXCESS {
-		F.reduce()
-	}
-}
-
-/* this-=b */
-func (F *FP) sub(b *FP) {
-	n := NewFPcopy(b)
-	n.neg()
-	F.add(n)
-}
-
-/* this/=2 mod Modulus */
-func (F *FP) div2() {
-	F.x.norm()
-	if F.x.parity() == 0 {
-		F.x.fshr(1)
-	} else {
-		F.x.add(&p)
-		F.x.norm()
-		F.x.fshr(1)
-	}
-}
-
-/* this=1/this mod Modulus */
-func (F *FP) inverse() {
-	r := F.redc()
-	r.invmodp(&p)
-	F.x.copy(r)
-	F.nres()
-}
-
-/* return TRUE if this==a */
-func (F *FP) equals(a *FP) bool {
-	a.reduce()
-	F.reduce()
-	if comp(a.x, F.x) == 0 {
-		return true
-	}
-	return false
-}
-
-/* return this^e mod Modulus */
-func (F *FP) pow(e *BIG) *FP {
-	r := NewFPint(1)
-	e.norm()
-	F.x.norm()
-	m := NewFPcopy(F)
-	for true {
-		bt := e.parity()
-		e.fshr(1)
-		if bt == 1 {
-			r.mul(m)
-		}
-		if e.iszilch() {
-			break
-		}
-		m.sqr()
-	}
-	r.x.mod(&p)
-	return r
-}
-
-/* return sqrt(this) mod Modulus */
-func (F *FP) sqrt() *FP {
-	F.reduce()
-	b := NewBIGcopy(&p)
-	if MOD8 == 5 {
-		b.dec(5)
-		b.norm()
-		b.shr(3)
-		i := NewFPcopy(F)
-		i.x.shl(1)
-		v := i.pow(b)
-		i.mul(v)
-		i.mul(v)
-		i.x.dec(1)
-		r := NewFPcopy(F)
-		r.mul(v)
-		r.mul(i)
-		r.reduce()
-		return r
-	} else {
-		b.inc(1)
-		b.norm()
-		b.shr(2)
-		return F.pow(b)
-	}
-}
-
-/* return jacobi symbol (this/Modulus) */
-func (F *FP) jacobi() int {
-	w := F.redc()
-	return w.jacobi(&p)
-}
diff --git a/go/amcl-go/FP12.go b/go/amcl-go/FP12.go
deleted file mode 100644
index 8e9cb4c..0000000
--- a/go/amcl-go/FP12.go
+++ /dev/null
@@ -1,654 +0,0 @@
-/*
-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.
-*/
-
-/* AMCL Fp^12 functions */
-/* FP12 elements are of the form a+i.b+i^2.c */
-
-package amcl
-
-//import "fmt"
-
-type FP12 struct {
-	a *FP4
-	b *FP4
-	c *FP4
-}
-
-/* Constructors */
-func NewFP12fp4(d *FP4) *FP12 {
-	F := new(FP12)
-	F.a = NewFP4copy(d)
-	F.b = NewFP4int(0)
-	F.c = NewFP4int(0)
-	return F
-}
-
-func NewFP12int(d int) *FP12 {
-	F := new(FP12)
-	F.a = NewFP4int(d)
-	F.b = NewFP4int(0)
-	F.c = NewFP4int(0)
-	return F
-}
-
-func NewFP12fp4s(d *FP4, e *FP4, f *FP4) *FP12 {
-	F := new(FP12)
-	F.a = NewFP4copy(d)
-	F.b = NewFP4copy(e)
-	F.c = NewFP4copy(f)
-	return F
-}
-
-func NewFP12copy(x *FP12) *FP12 {
-	F := new(FP12)
-	F.a = NewFP4copy(x.a)
-	F.b = NewFP4copy(x.b)
-	F.c = NewFP4copy(x.c)
-	return F
-}
-
-/* reduce all components of this mod Modulus */
-func (F *FP12) reduce() {
-	F.a.reduce()
-	F.b.reduce()
-	F.c.reduce()
-}
-
-/* normalise all components of this */
-func (F *FP12) norm() {
-	F.a.norm()
-	F.b.norm()
-	F.c.norm()
-}
-
-/* test x==0 ? */
-func (F *FP12) iszilch() bool {
-	F.reduce()
-	return (F.a.iszilch() && F.b.iszilch() && F.c.iszilch())
-}
-
-/* test x==1 ? */
-func (F *FP12) isunity() bool {
-	one := NewFP4int(1)
-	return (F.a.equals(one) && F.b.iszilch() && F.c.iszilch())
-}
-
-/* return 1 if x==y, else 0 */
-func (F *FP12) equals(x *FP12) bool {
-	return (F.a.equals(x.a) && F.b.equals(x.b) && F.c.equals(x.c))
-}
-
-/* extract a from this */
-func (F *FP12) geta() *FP4 {
-	return F.a
-}
-
-/* extract b */
-func (F *FP12) getb() *FP4 {
-	return F.b
-}
-
-/* extract c */
-func (F *FP12) getc() *FP4 {
-	return F.c
-}
-
-/* copy this=x */
-func (F *FP12) copy(x *FP12) {
-	F.a.copy(x.a)
-	F.b.copy(x.b)
-	F.c.copy(x.c)
-}
-
-/* set this=1 */
-func (F *FP12) one() {
-	F.a.one()
-	F.b.zero()
-	F.c.zero()
-}
-
-/* this=conj(this) */
-func (F *FP12) conj() {
-	F.a.conj()
-	F.b.nconj()
-	F.c.conj()
-}
-
-/* Granger-Scott Unitary Squaring */
-func (F *FP12) usqr() {
-	A := NewFP4copy(F.a)
-	B := NewFP4copy(F.c)
-	C := NewFP4copy(F.b)
-	D := NewFP4int(0)
-
-	F.a.sqr()
-	D.copy(F.a)
-	D.add(F.a)
-	F.a.add(D)
-
-	//		a.norm();
-	A.nconj()
-
-	A.add(A)
-	F.a.add(A)
-	B.sqr()
-	B.times_i()
-
-	D.copy(B)
-	D.add(B)
-	B.add(D)
-	//		B.norm();
-
-	C.sqr()
-	D.copy(C)
-	D.add(C)
-	C.add(D)
-	//		C.norm();
-
-	F.b.conj()
-	F.b.add(F.b)
-	F.c.nconj()
-
-	F.c.add(F.c)
-	F.b.add(B)
-	F.c.add(C)
-	F.reduce()
-
-}
-
-/* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
-func (F *FP12) sqr() {
-	A := NewFP4copy(F.a)
-	B := NewFP4copy(F.b)
-	C := NewFP4copy(F.c)
-	D := NewFP4copy(F.a)
-
-	A.sqr()
-	B.mul(F.c)
-	B.add(B)
-	C.sqr()
-	D.mul(F.b)
-	D.add(D)
-
-	F.c.add(F.a)
-	F.c.add(F.b)
-	F.c.sqr()
-
-	F.a.copy(A)
-
-	A.add(B)
-	//		A.norm();
-	A.add(C)
-	A.add(D)
-	//		A.norm();
-
-	A.neg()
-	B.times_i()
-	C.times_i()
-
-	F.a.add(B)
-
-	F.b.copy(C)
-	F.b.add(D)
-	F.c.add(A)
-	F.norm()
-}
-
-/* FP12 full multiplication this=this*y */
-func (F *FP12) mul(y *FP12) {
-	z0 := NewFP4copy(F.a)
-	z1 := NewFP4int(0)
-	z2 := NewFP4copy(F.b)
-	z3 := NewFP4int(0)
-	t0 := NewFP4copy(F.a)
-	t1 := NewFP4copy(y.a)
-
-	z0.mul(y.a)
-	z2.mul(y.b)
-
-	t0.add(F.b)
-	t1.add(y.b)
-
-	z1.copy(t0)
-	z1.mul(t1)
-	t0.copy(F.b)
-	t0.add(F.c)
-
-	t1.copy(y.b)
-	t1.add(y.c)
-	z3.copy(t0)
-	z3.mul(t1)
-
-	t0.copy(z0)
-	t0.neg()
-	t1.copy(z2)
-	t1.neg()
-
-	z1.add(t0)
-	//		z1.norm();
-	F.b.copy(z1)
-	F.b.add(t1)
-
-	z3.add(t1)
-	z2.add(t0)
-
-	t0.copy(F.a)
-	t0.add(F.c)
-	t1.copy(y.a)
-	t1.add(y.c)
-	t0.mul(t1)
-	z2.add(t0)
-
-	t0.copy(F.c)
-	t0.mul(y.c)
-	t1.copy(t0)
-	t1.neg()
-
-	//		z2.norm();
-	//		z3.norm();
-	//		b.norm();
-
-	F.c.copy(z2)
-	F.c.add(t1)
-	z3.add(t1)
-	t0.times_i()
-	F.b.add(t0)
-
-	z3.times_i()
-	F.a.copy(z0)
-	F.a.add(z3)
-	F.norm()
-}
-
-/* Special case of multiplication arises from special form of ATE pairing line function */
-func (F *FP12) smul(y *FP12) {
-	z0 := NewFP4copy(F.a)
-	z2 := NewFP4copy(F.b)
-	z3 := NewFP4copy(F.b)
-	t0 := NewFP4int(0)
-	t1 := NewFP4copy(y.a)
-
-	z0.mul(y.a)
-	z2.pmul(y.b.real())
-	F.b.add(F.a)
-	t1.real().add(y.b.real())
-
-	F.b.mul(t1)
-	z3.add(F.c)
-	z3.pmul(y.b.real())
-
-	t0.copy(z0)
-	t0.neg()
-	t1.copy(z2)
-	t1.neg()
-
-	F.b.add(t0)
-	//		b.norm();
-
-	F.b.add(t1)
-	z3.add(t1)
-	z2.add(t0)
-
-	t0.copy(F.a)
-	t0.add(F.c)
-	t0.mul(y.a)
-	F.c.copy(z2)
-	F.c.add(t0)
-
-	z3.times_i()
-	F.a.copy(z0)
-	F.a.add(z3)
-
-	F.norm()
-}
-
-/* this=1/this */
-func (F *FP12) inverse() {
-	f0 := NewFP4copy(F.a)
-	f1 := NewFP4copy(F.b)
-	f2 := NewFP4copy(F.a)
-	f3 := NewFP4int(0)
-
-	F.norm()
-	f0.sqr()
-	f1.mul(F.c)
-	f1.times_i()
-	f0.sub(f1)
-
-	f1.copy(F.c)
-	f1.sqr()
-	f1.times_i()
-	f2.mul(F.b)
-	f1.sub(f2)
-
-	f2.copy(F.b)
-	f2.sqr()
-	f3.copy(F.a)
-	f3.mul(F.c)
-	f2.sub(f3)
-
-	f3.copy(F.b)
-	f3.mul(f2)
-	f3.times_i()
-	F.a.mul(f0)
-	f3.add(F.a)
-	F.c.mul(f1)
-	F.c.times_i()
-
-	f3.add(F.c)
-	f3.inverse()
-	F.a.copy(f0)
-	F.a.mul(f3)
-	F.b.copy(f1)
-	F.b.mul(f3)
-	F.c.copy(f2)
-	F.c.mul(f3)
-}
-
-/* this=this^p using Frobenius */
-func (F *FP12) frob(f *FP2) {
-	f2 := NewFP2copy(f)
-	f3 := NewFP2copy(f)
-
-	f2.sqr()
-	f3.mul(f2)
-
-	F.a.frob(f3)
-	F.b.frob(f3)
-	F.c.frob(f3)
-
-	F.b.pmul(f)
-	F.c.pmul(f2)
-}
-
-/* trace function */
-func (F *FP12) trace() *FP4 {
-	t := NewFP4int(0)
-	t.copy(F.a)
-	t.imul(3)
-	t.reduce()
-	return t
-}
-
-/* convert from byte array to FP12 */
-func FP12_fromBytes(w []byte) *FP12 {
-	var t [int(MODBYTES)]byte
-	MB := int(MODBYTES)
-
-	for i := 0; i < MB; i++ {
-		t[i] = w[i]
-	}
-	a := fromBytes(t[:])
-	for i := 0; i < MB; i++ {
-		t[i] = w[i+MB]
-	}
-	b := fromBytes(t[:])
-	c := NewFP2bigs(a, b)
-
-	for i := 0; i < MB; i++ {
-		t[i] = w[i+2*MB]
-	}
-	a = fromBytes(t[:])
-	for i := 0; i < MB; i++ {
-		t[i] = w[i+3*MB]
-	}
-	b = fromBytes(t[:])
-	d := NewFP2bigs(a, b)
-
-	e := NewFP4fp2s(c, d)
-
-	for i := 0; i < MB; i++ {
-		t[i] = w[i+4*MB]
-	}
-	a = fromBytes(t[:])
-	for i := 0; i < MB; i++ {
-		t[i] = w[i+5*MB]
-	}
-	b = fromBytes(t[:])
-	c = NewFP2bigs(a, b)
-
-	for i := 0; i < MB; i++ {
-		t[i] = w[i+6*MB]
-	}
-	a = fromBytes(t[:])
-	for i := 0; i < MB; i++ {
-		t[i] = w[i+7*MB]
-	}
-	b = fromBytes(t[:])
-	d = NewFP2bigs(a, b)
-
-	f := NewFP4fp2s(c, d)
-
-	for i := 0; i < MB; i++ {
-		t[i] = w[i+8*MB]
-	}
-	a = fromBytes(t[:])
-	for i := 0; i < MB; i++ {
-		t[i] = w[i+9*MB]
-	}
-	b = fromBytes(t[:])
-
-	c = NewFP2bigs(a, b)
-
-	for i := 0; i < MB; i++ {
-		t[i] = w[i+10*MB]
-	}
-	a = fromBytes(t[:])
-	for i := 0; i < MB; i++ {
-		t[i] = w[i+11*MB]
-	}
-	b = fromBytes(t[:])
-	d = NewFP2bigs(a, b)
-
-	g := NewFP4fp2s(c, d)
-
-	return NewFP12fp4s(e, f, g)
-}
-
-/* convert this to byte array */
-func (F *FP12) toBytes(w []byte) {
-	var t [int(MODBYTES)]byte
-	MB := int(MODBYTES)
-	F.a.geta().getA().toBytes(t[:])
-	for i := 0; i < MB; i++ {
-		w[i] = t[i]
-	}
-	F.a.geta().getB().toBytes(t[:])
-	for i := 0; i < MB; i++ {
-		w[i+MB] = t[i]
-	}
-	F.a.getb().getA().toBytes(t[:])
-	for i := 0; i < MB; i++ {
-		w[i+2*MB] = t[i]
-	}
-	F.a.getb().getB().toBytes(t[:])
-	for i := 0; i < MB; i++ {
-		w[i+3*MB] = t[i]
-	}
-
-	F.b.geta().getA().toBytes(t[:])
-	for i := 0; i < MB; i++ {
-		w[i+4*MB] = t[i]
-	}
-	F.b.geta().getB().toBytes(t[:])
-	for i := 0; i < MB; i++ {
-		w[i+5*MB] = t[i]
-	}
-	F.b.getb().getA().toBytes(t[:])
-	for i := 0; i < MB; i++ {
-		w[i+6*MB] = t[i]
-	}
-	F.b.getb().getB().toBytes(t[:])
-	for i := 0; i < MB; i++ {
-		w[i+7*MB] = t[i]
-	}
-
-	F.c.geta().getA().toBytes(t[:])
-	for i := 0; i < MB; i++ {
-		w[i+8*MB] = t[i]
-	}
-	F.c.geta().getB().toBytes(t[:])
-	for i := 0; i < MB; i++ {
-		w[i+9*MB] = t[i]
-	}
-	F.c.getb().getA().toBytes(t[:])
-	for i := 0; i < MB; i++ {
-		w[i+10*MB] = t[i]
-	}
-	F.c.getb().getB().toBytes(t[:])
-	for i := 0; i < MB; i++ {
-		w[i+11*MB] = t[i]
-	}
-}
-
-/* convert to hex string */
-func (F *FP12) toString() string {
-	return ("[" + F.a.toString() + "," + F.b.toString() + "," + F.c.toString() + "]")
-}
-
-/* this=this^e */
-func (F *FP12) pow(e *BIG) *FP12 {
-	F.norm()
-	e.norm()
-	w := NewFP12copy(F)
-	z := NewBIGcopy(e)
-	r := NewFP12int(1)
-
-	for true {
-		bt := z.parity()
-		z.fshr(1)
-		if bt == 1 {
-			r.mul(w)
-		}
-		if z.iszilch() {
-			break
-		}
-		w.usqr()
-	}
-	r.reduce()
-	return r
-}
-
-/* constant time powering by small integer of max length bts */
-func (F *FP12) pinpow(e int, bts int) {
-	var R []*FP12
-	R = append(R, NewFP12int(1))
-	R = append(R, NewFP12copy(F))
-
-	for i := bts - 1; i >= 0; i-- {
-		b := (e >> uint(i)) & 1
-		R[1-b].mul(R[b])
-		R[b].usqr()
-	}
-	F.copy(R[0])
-}
-
-/* p=q0^u0.q1^u1.q2^u2.q3^u3 */
-/* Timing attack secure, but not cache attack secure */
-
-func pow4(q []*FP12, u []*BIG) *FP12 {
-	var a [4]int8
-	var g []*FP12
-	var s []*FP12
-	c := NewFP12int(1)
-	p := NewFP12int(0)
-	var w [NLEN*int(BASEBITS) + 1]int8
-	var t []*BIG
-	mt := NewBIGint(0)
-
-	for i := 0; i < 4; i++ {
-		t = append(t, NewBIGcopy(u[i]))
-	}
-
-	s = append(s, NewFP12int(0))
-	s = append(s, NewFP12int(0))
-
-	g = append(g, NewFP12copy(q[0]))
-	s[0].copy(q[1])
-	s[0].conj()
-	g[0].mul(s[0])
-	g = append(g, NewFP12copy(g[0]))
-	g = append(g, NewFP12copy(g[0]))
-	g = append(g, NewFP12copy(g[0]))
-	g = append(g, NewFP12copy(q[0]))
-	g[4].mul(q[1])
-	g = append(g, NewFP12copy(g[4]))
-	g = append(g, NewFP12copy(g[4]))
-	g = append(g, NewFP12copy(g[4]))
-
-	s[1].copy(q[2])
-	s[0].copy(q[3])
-	s[0].conj()
-	s[1].mul(s[0])
-	s[0].copy(s[1])
-	s[0].conj()
-	g[1].mul(s[0])
-	g[2].mul(s[1])
-	g[5].mul(s[0])
-	g[6].mul(s[1])
-	s[1].copy(q[2])
-	s[1].mul(q[3])
-	s[0].copy(s[1])
-	s[0].conj()
-	g[0].mul(s[0])
-	g[3].mul(s[1])
-	g[4].mul(s[0])
-	g[7].mul(s[1])
-
-	/* if power is even add 1 to power, and add q to correction */
-
-	for i := 0; i < 4; i++ {
-		if t[i].parity() == 0 {
-			t[i].inc(1)
-			t[i].norm()
-			c.mul(q[i])
-		}
-		mt.add(t[i])
-		mt.norm()
-	}
-	c.conj()
-	nb := 1 + mt.nbits()
-
-	/* convert exponent to signed 1-bit window */
-	for j := 0; j < nb; j++ {
-		for i := 0; i < 4; i++ {
-			a[i] = int8(t[i].lastbits(2) - 2)
-			t[i].dec(int(a[i]))
-			t[i].norm()
-			t[i].fshr(1)
-		}
-		w[j] = (8*a[0] + 4*a[1] + 2*a[2] + a[3])
-	}
-	w[nb] = int8(8*t[0].lastbits(2) + 4*t[1].lastbits(2) + 2*t[2].lastbits(2) + t[3].lastbits(2))
-	p.copy(g[(w[nb]-1)/2])
-
-	for i := nb - 1; i >= 0; i-- {
-		m := w[i] >> 7
-		j := (w[i] ^ m) - m /* j=abs(w[i]) */
-		j = (j - 1) / 2
-		s[0].copy(g[j])
-		s[1].copy(g[j])
-		s[1].conj()
-		p.usqr()
-		p.mul(s[m&1])
-	}
-	p.mul(c) /* apply correction */
-	p.reduce()
-	return p
-}
diff --git a/go/amcl-go/FP2.go b/go/amcl-go/FP2.go
deleted file mode 100644
index 599fbcc..0000000
--- a/go/amcl-go/FP2.go
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
-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.
-*/
-
-/* Finite Field arithmetic  Fp^2 functions */
-
-/* FP2 elements are of the form a+ib, where i is sqrt(-1) */
-
-package amcl
-
-//import "fmt"
-
-type FP2 struct {
-	a *FP
-	b *FP
-}
-
-/* Constructors */
-func NewFP2int(a int) *FP2 {
-	F := new(FP2)
-	F.a = NewFPint(a)
-	F.b = NewFPint(0)
-	return F
-}
-
-func NewFP2copy(x *FP2) *FP2 {
-	F := new(FP2)
-	F.a = NewFPcopy(x.a)
-	F.b = NewFPcopy(x.b)
-	return F
-}
-
-func NewFP2fps(c *FP, d *FP) *FP2 {
-	F := new(FP2)
-	F.a = NewFPcopy(c)
-	F.b = NewFPcopy(d)
-	return F
-}
-
-func NewFP2bigs(c *BIG, d *BIG) *FP2 {
-	F := new(FP2)
-	F.a = NewFPbig(c)
-	F.b = NewFPbig(d)
-	return F
-}
-
-func NewFP2fp(c *FP) *FP2 {
-	F := new(FP2)
-	F.a = NewFPcopy(c)
-	F.b = NewFPint(0)
-	return F
-}
-
-func NewFP2big(c *BIG) *FP2 {
-	F := new(FP2)
-	F.a = NewFPbig(c)
-	F.b = NewFPint(0)
-	return F
-}
-
-/* reduce components mod Modulus */
-func (F *FP2) reduce() {
-	F.a.reduce()
-	F.b.reduce()
-}
-
-/* normalise components of w */
-func (F *FP2) norm() {
-	F.a.norm()
-	F.b.norm()
-}
-
-/* test this=0 ? */
-func (F *FP2) iszilch() bool {
-	F.reduce()
-	return (F.a.iszilch() && F.b.iszilch())
-}
-
-func (F *FP2) cmove(g *FP2, d int32) {
-	F.a.cmove(g.a, d)
-	F.b.cmove(g.b, d)
-}
-
-/* test this=1 ? */
-func (F *FP2) isunity() bool {
-	one := NewFPint(1)
-	return (F.a.equals(one) && F.b.iszilch())
-}
-
-/* test this=x */
-func (F *FP2) equals(x *FP2) bool {
-	return (F.a.equals(x.a) && F.b.equals(x.b))
-}
-
-/* extract a */
-func (F *FP2) getA() *BIG {
-	return F.a.redc()
-}
-
-/* extract b */
-func (F *FP2) getB() *BIG {
-	return F.b.redc()
-}
-
-/* copy this=x */
-func (F *FP2) copy(x *FP2) {
-	F.a.copy(x.a)
-	F.b.copy(x.b)
-}
-
-/* set this=0 */
-func (F *FP2) zero() {
-	F.a.zero()
-	F.b.zero()
-}
-
-/* set this=1 */
-func (F *FP2) one() {
-	F.a.one()
-	F.b.zero()
-}
-
-/* negate this mod Modulus */
-func (F *FP2) neg() {
-	F.norm()
-	m := NewFPcopy(F.a)
-	t := NewFPint(0)
-
-	m.add(F.b)
-	m.neg()
-	m.norm()
-	t.copy(m)
-	t.add(F.b)
-	F.b.copy(m)
-	F.b.add(F.a)
-	F.a.copy(t)
-}
-
-/* set to a-ib */
-func (F *FP2) conj() {
-	F.b.neg()
-}
-
-/* this+=a */
-func (F *FP2) add(x *FP2) {
-	F.a.add(x.a)
-	F.b.add(x.b)
-}
-
-/* this-=a */
-func (F *FP2) sub(x *FP2) {
-	m := NewFP2copy(x)
-	m.neg()
-	F.add(m)
-}
-
-/* this*=s, where s is an FP */
-func (F *FP2) pmul(s *FP) {
-	F.a.mul(s)
-	F.b.mul(s)
-}
-
-/* this*=i, where i is an int */
-func (F *FP2) imul(c int) {
-	F.a.imul(c)
-	F.b.imul(c)
-}
-
-/* this*=this */
-func (F *FP2) sqr() {
-	F.norm()
-	w1 := NewFPcopy(F.a)
-	w3 := NewFPcopy(F.a)
-	mb := NewFPcopy(F.b)
-
-	w3.mul(F.b)
-	w1.add(F.b)
-	mb.neg()
-	F.a.add(mb)
-	F.a.mul(w1)
-	F.b.copy(w3)
-	F.b.add(w3)
-
-	F.norm()
-}
-
-/* this*=y */
-func (F *FP2) mul(y *FP2) {
-	F.norm() /* This is needed here as {a,b} is not normed before additions */
-
-	w1 := NewFPcopy(F.a)
-	w2 := NewFPcopy(F.b)
-	w5 := NewFPcopy(F.a)
-	mw := NewFPint(0)
-
-	w1.mul(y.a) // w1=a*y.a  - this norms w1 and y.a, NOT a
-	w2.mul(y.b) // w2=b*y.b  - this norms w2 and y.b, NOT b
-	w5.add(F.b) // w5=a+b
-	F.b.copy(y.a)
-	F.b.add(y.b) // b=y.a+y.b
-
-	F.b.mul(w5)
-	mw.copy(w1)
-	mw.add(w2)
-	mw.neg()
-
-	F.b.add(mw)
-	mw.add(w1)
-	F.a.copy(w1)
-	F.a.add(mw)
-
-	F.norm()
-}
-
-/* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */
-/* returns true if this is QR */
-func (F *FP2) sqrt() bool {
-	if F.iszilch() {
-		return true
-	}
-	w1 := NewFPcopy(F.b)
-	w2 := NewFPcopy(F.a)
-	w1.sqr()
-	w2.sqr()
-	w1.add(w2)
-	if w1.jacobi() != 1 {
-		F.zero()
-		return false
-	}
-	w1 = w1.sqrt()
-	w2.copy(F.a)
-	w2.add(w1)
-	w2.div2()
-	if w2.jacobi() != 1 {
-		w2.copy(F.a)
-		w2.sub(w1)
-		w2.div2()
-		if w2.jacobi() != 1 {
-			F.zero()
-			return false
-		}
-	}
-	w2 = w2.sqrt()
-	F.a.copy(w2)
-	w2.add(w2)
-	w2.inverse()
-	F.b.mul(w2)
-	return true
-}
-
-/* output to hex string */
-func (F *FP2) toString() string {
-	return ("[" + F.a.toString() + "," + F.b.toString() + "]")
-}
-
-/* this=1/this */
-func (F *FP2) inverse() {
-	F.norm()
-	w1 := NewFPcopy(F.a)
-	w2 := NewFPcopy(F.b)
-
-	w1.sqr()
-	w2.sqr()
-	w1.add(w2)
-	w1.inverse()
-	F.a.mul(w1)
-	w1.neg()
-	F.b.mul(w1)
-}
-
-/* this/=2 */
-func (F *FP2) div2() {
-	F.a.div2()
-	F.b.div2()
-}
-
-/* this*=sqrt(-1) */
-func (F *FP2) times_i() {
-	//	a.norm();
-	z := NewFPcopy(F.a)
-	F.a.copy(F.b)
-	F.a.neg()
-	F.b.copy(z)
-}
-
-/* w*=(1+sqrt(-1)) */
-/* where X*2-(1+sqrt(-1)) is irreducible for FP4, assumes p=3 mod 8 */
-func (F *FP2) mul_ip() {
-	F.norm()
-	t := NewFP2copy(F)
-	z := NewFPcopy(F.a)
-	F.a.copy(F.b)
-	F.a.neg()
-	F.b.copy(z)
-	F.add(t)
-	F.norm()
-}
-
-/* w/=(1+sqrt(-1)) */
-func (F *FP2) div_ip() {
-	t := NewFP2int(0)
-	F.norm()
-	t.a.copy(F.a)
-	t.a.add(F.b)
-	t.b.copy(F.b)
-	t.b.sub(F.a)
-	F.copy(t)
-	F.div2()
-}
diff --git a/go/amcl-go/FP4.go b/go/amcl-go/FP4.go
deleted file mode 100644
index 76e9d1e..0000000
--- a/go/amcl-go/FP4.go
+++ /dev/null
@@ -1,522 +0,0 @@
-/*
-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.
-*/
-
-/* Finite Field arithmetic  Fp^4 functions */
-
-/* FP4 elements are of the form a+ib, where i is sqrt(-1+sqrt(-1)) */
-
-package amcl
-
-//import "fmt"
-
-type FP4 struct {
-	a *FP2
-	b *FP2
-}
-
-/* Constructors */
-func NewFP4int(a int) *FP4 {
-	F := new(FP4)
-	F.a = NewFP2int(a)
-	F.b = NewFP2int(0)
-	return F
-}
-
-func NewFP4copy(x *FP4) *FP4 {
-	F := new(FP4)
-	F.a = NewFP2copy(x.a)
-	F.b = NewFP2copy(x.b)
-	return F
-}
-
-func NewFP4fp2s(c *FP2, d *FP2) *FP4 {
-	F := new(FP4)
-	F.a = NewFP2copy(c)
-	F.b = NewFP2copy(d)
-	return F
-}
-
-func NewFP4fp2(c *FP2) *FP4 {
-	F := new(FP4)
-	F.a = NewFP2copy(c)
-	F.b = NewFP2int(0)
-	return F
-}
-
-/* reduce all components of this mod Modulus */
-func (F *FP4) reduce() {
-	F.a.reduce()
-	F.b.reduce()
-}
-
-/* normalise all components of this mod Modulus */
-func (F *FP4) norm() {
-	F.a.norm()
-	F.b.norm()
-}
-
-/* test this==0 ? */
-func (F *FP4) iszilch() bool {
-	F.reduce()
-	return F.a.iszilch() && F.b.iszilch()
-}
-
-/* test this==1 ? */
-func (F *FP4) isunity() bool {
-	one := NewFP2int(1)
-	return F.a.equals(one) && F.b.iszilch()
-}
-
-/* test is w real? That is in a+ib test b is zero */
-func (F *FP4) isreal() bool {
-	return F.b.iszilch()
-}
-
-/* extract real part a */
-func (F *FP4) real() *FP2 {
-	return F.a
-}
-
-func (F *FP4) geta() *FP2 {
-	return F.a
-}
-
-/* extract imaginary part b */
-func (F *FP4) getb() *FP2 {
-	return F.b
-}
-
-/* test this=x? */
-func (F *FP4) equals(x *FP4) bool {
-	return (F.a.equals(x.a) && F.b.equals(x.b))
-}
-
-/* copy this=x */
-func (F *FP4) copy(x *FP4) {
-	F.a.copy(x.a)
-	F.b.copy(x.b)
-}
-
-/* set this=0 */
-func (F *FP4) zero() {
-	F.a.zero()
-	F.b.zero()
-}
-
-/* set this=1 */
-func (F *FP4) one() {
-	F.a.one()
-	F.b.zero()
-}
-
-/* set this=-this */
-func (F *FP4) neg() {
-	m := NewFP2copy(F.a)
-	t := NewFP2int(0)
-	m.add(F.b)
-	m.neg()
-	m.norm()
-	t.copy(m)
-	t.add(F.b)
-	F.b.copy(m)
-	F.b.add(F.a)
-	F.a.copy(t)
-}
-
-/* this=conjugate(this) */
-func (F *FP4) conj() {
-	F.b.neg()
-	F.b.norm()
-}
-
-/* this=-conjugate(this) */
-func (F *FP4) nconj() {
-	F.a.neg()
-	F.a.norm()
-}
-
-/* this+=x */
-func (F *FP4) add(x *FP4) {
-	F.a.add(x.a)
-	F.b.add(x.b)
-}
-
-/* this-=x */
-func (F *FP4) sub(x *FP4) {
-	m := NewFP4copy(x)
-	m.neg()
-	F.add(m)
-}
-
-/* this*=s where s is FP2 */
-func (F *FP4) pmul(s *FP2) {
-	F.a.mul(s)
-	F.b.mul(s)
-}
-
-/* this*=c where c is int */
-func (F *FP4) imul(c int) {
-	F.a.imul(c)
-	F.b.imul(c)
-}
-
-/* this*=this */
-func (F *FP4) sqr() {
-	F.norm()
-
-	t1 := NewFP2copy(F.a)
-	t2 := NewFP2copy(F.b)
-	t3 := NewFP2copy(F.a)
-
-	t3.mul(F.b)
-	t1.add(F.b)
-	t2.mul_ip()
-
-	t2.add(F.a)
-	F.a.copy(t1)
-
-	F.a.mul(t2)
-
-	t2.copy(t3)
-	t2.mul_ip()
-	t2.add(t3)
-	t2.neg()
-	F.a.add(t2)
-
-	F.b.copy(t3)
-	F.b.add(t3)
-
-	F.norm()
-}
-
-/* this*=y */
-func (F *FP4) mul(y *FP4) {
-	F.norm()
-
-	t1 := NewFP2copy(F.a)
-	t2 := NewFP2copy(F.b)
-	t3 := NewFP2int(0)
-	t4 := NewFP2copy(F.b)
-
-	t1.mul(y.a)
-	t2.mul(y.b)
-	t3.copy(y.b)
-	t3.add(y.a)
-	t4.add(F.a)
-
-	t4.mul(t3)
-	t4.sub(t1)
-	//		t4.norm();
-
-	F.b.copy(t4)
-	F.b.sub(t2)
-	t2.mul_ip()
-	F.a.copy(t2)
-	F.a.add(t1)
-
-	F.norm()
-}
-
-/* convert this to hex string */
-func (F *FP4) toString() string {
-	return ("[" + F.a.toString() + "," + F.b.toString() + "]")
-}
-
-/* this=1/this */
-func (F *FP4) inverse() {
-	F.norm()
-
-	t1 := NewFP2copy(F.a)
-	t2 := NewFP2copy(F.b)
-
-	t1.sqr()
-	t2.sqr()
-	t2.mul_ip()
-	t1.sub(t2)
-	t1.inverse()
-	F.a.mul(t1)
-	t1.neg()
-	F.b.mul(t1)
-}
-
-/* this*=i where i = sqrt(-1+sqrt(-1)) */
-func (F *FP4) times_i() {
-	F.norm()
-	s := NewFP2copy(F.b)
-	t := NewFP2copy(F.b)
-	s.times_i()
-	t.add(s)
-	//		t.norm();
-	F.b.copy(F.a)
-	F.a.copy(t)
-}
-
-/* this=this^p using Frobenius */
-func (F *FP4) frob(f *FP2) {
-	F.a.conj()
-	F.b.conj()
-	F.b.mul(f)
-}
-
-/* this=this^e */
-func (F *FP4) pow(e *BIG) *FP4 {
-	F.norm()
-	e.norm()
-	w := NewFP4copy(F)
-	z := NewBIGcopy(e)
-	r := NewFP4int(1)
-	for true {
-		bt := z.parity()
-		z.fshr(1)
-		if bt == 1 {
-			r.mul(w)
-		}
-		if z.iszilch() {
-			break
-		}
-		w.sqr()
-	}
-	r.reduce()
-	return r
-}
-
-/* XTR xtr_a function */
-func (F *FP4) xtr_A(w *FP4, y *FP4, z *FP4) {
-	r := NewFP4copy(w)
-	t := NewFP4copy(w)
-	r.sub(y)
-	r.pmul(F.a)
-	t.add(y)
-	t.pmul(F.b)
-	t.times_i()
-
-	F.copy(r)
-	F.add(t)
-	F.add(z)
-
-	F.norm()
-}
-
-/* XTR xtr_d function */
-func (F *FP4) xtr_D() {
-	w := NewFP4copy(F)
-	F.sqr()
-	w.conj()
-	w.add(w)
-	F.sub(w)
-	F.reduce()
-}
-
-/* r=x^n using XTR method on traces of FP12s */
-func (F *FP4) xtr_pow(n *BIG) *FP4 {
-	a := NewFP4int(3)
-	b := NewFP4copy(F)
-	c := NewFP4copy(b)
-	c.xtr_D()
-	t := NewFP4int(0)
-	r := NewFP4int(0)
-
-	n.norm()
-	par := n.parity()
-	v := NewBIGcopy(n)
-	v.fshr(1)
-	if par == 0 {
-		v.dec(1)
-		v.norm()
-	}
-
-	nb := v.nbits()
-	for i := nb - 1; i >= 0; i-- {
-		if v.bit(i) != 1 {
-			t.copy(b)
-			F.conj()
-			c.conj()
-			b.xtr_A(a, F, c)
-			F.conj()
-			c.copy(t)
-			c.xtr_D()
-			a.xtr_D()
-		} else {
-			t.copy(a)
-			t.conj()
-			a.copy(b)
-			a.xtr_D()
-			b.xtr_A(c, F, t)
-			c.xtr_D()
-		}
-	}
-	if par == 0 {
-		r.copy(c)
-	} else {
-		r.copy(b)
-	}
-	r.reduce()
-	return r
-}
-
-/* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */
-func (F *FP4) xtr_pow2(ck *FP4, ckml *FP4, ckm2l *FP4, a *BIG, b *BIG) *FP4 {
-	a.norm()
-	b.norm()
-	e := NewBIGcopy(a)
-	d := NewBIGcopy(b)
-	w := NewBIGint(0)
-
-	cu := NewFP4copy(ck) // can probably be passed in w/o copying
-	cv := NewFP4copy(F)
-	cumv := NewFP4copy(ckml)
-	cum2v := NewFP4copy(ckm2l)
-	r := NewFP4int(0)
-	t := NewFP4int(0)
-
-	f2 := 0
-	for d.parity() == 0 && e.parity() == 0 {
-		d.fshr(1)
-		e.fshr(1)
-		f2++
-	}
-
-	for comp(d, e) != 0 {
-		if comp(d, e) > 0 {
-			w.copy(e)
-			w.imul(4)
-			w.norm()
-			if comp(d, w) <= 0 {
-				w.copy(d)
-				d.copy(e)
-				e.rsub(w)
-				e.norm()
-
-				t.copy(cv)
-				t.xtr_A(cu, cumv, cum2v)
-				cum2v.copy(cumv)
-				cum2v.conj()
-				cumv.copy(cv)
-				cv.copy(cu)
-				cu.copy(t)
-			} else {
-				if d.parity() == 0 {
-					d.fshr(1)
-					r.copy(cum2v)
-					r.conj()
-					t.copy(cumv)
-					t.xtr_A(cu, cv, r)
-					cum2v.copy(cumv)
-					cum2v.xtr_D()
-					cumv.copy(t)
-					cu.xtr_D()
-				} else {
-					if e.parity() == 1 {
-						d.sub(e)
-						d.norm()
-						d.fshr(1)
-						t.copy(cv)
-						t.xtr_A(cu, cumv, cum2v)
-						cu.xtr_D()
-						cum2v.copy(cv)
-						cum2v.xtr_D()
-						cum2v.conj()
-						cv.copy(t)
-					} else {
-						w.copy(d)
-						d.copy(e)
-						d.fshr(1)
-						e.copy(w)
-						t.copy(cumv)
-						t.xtr_D()
-						cumv.copy(cum2v)
-						cumv.conj()
-						cum2v.copy(t)
-						cum2v.conj()
-						t.copy(cv)
-						t.xtr_D()
-						cv.copy(cu)
-						cu.copy(t)
-					}
-				}
-			}
-		}
-		if comp(d, e) < 0 {
-			w.copy(d)
-			w.imul(4)
-			w.norm()
-			if comp(e, w) <= 0 {
-				e.sub(d)
-				e.norm()
-				t.copy(cv)
-				t.xtr_A(cu, cumv, cum2v)
-				cum2v.copy(cumv)
-				cumv.copy(cu)
-				cu.copy(t)
-			} else {
-				if e.parity() == 0 {
-					w.copy(d)
-					d.copy(e)
-					d.fshr(1)
-					e.copy(w)
-					t.copy(cumv)
-					t.xtr_D()
-					cumv.copy(cum2v)
-					cumv.conj()
-					cum2v.copy(t)
-					cum2v.conj()
-					t.copy(cv)
-					t.xtr_D()
-					cv.copy(cu)
-					cu.copy(t)
-				} else {
-					if d.parity() == 1 {
-						w.copy(e)
-						e.copy(d)
-						w.sub(d)
-						w.norm()
-						d.copy(w)
-						d.fshr(1)
-						t.copy(cv)
-						t.xtr_A(cu, cumv, cum2v)
-						cumv.conj()
-						cum2v.copy(cu)
-						cum2v.xtr_D()
-						cum2v.conj()
-						cu.copy(cv)
-						cu.xtr_D()
-						cv.copy(t)
-					} else {
-						d.fshr(1)
-						r.copy(cum2v)
-						r.conj()
-						t.copy(cumv)
-						t.xtr_A(cu, cv, r)
-						cum2v.copy(cumv)
-						cum2v.xtr_D()
-						cumv.copy(t)
-						cu.xtr_D()
-					}
-				}
-			}
-		}
-	}
-	r.copy(cv)
-	r.xtr_A(cu, cumv, cum2v)
-	for i := 0; i < f2; i++ {
-		r.xtr_D()
-	}
-	r = r.xtr_pow(d)
-	return r
-}
diff --git a/go/amcl-go/GCM.go b/go/amcl-go/GCM.go
deleted file mode 100644
index 2fc4da3..0000000
--- a/go/amcl-go/GCM.go
+++ /dev/null
@@ -1,472 +0,0 @@
-/*
-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.
-*/
-
-/*
-* Implementation of the AES-GCM Encryption/Authentication
-*
-* Some restrictions..
-* 1. Only for use with AES
-* 2. Returned tag is always 128-bits. Truncate at your own risk.
-* 3. The order of function calls must follow some rules
-*
-* Typical sequence of calls..
-* 1. call GCM_init
-* 2. call GCM_add_header any number of times, as long as length of header is multiple of 16 bytes (block size)
-* 3. call GCM_add_header one last time with any length of header
-* 4. call GCM_add_cipher any number of times, as long as length of cipher/plaintext is multiple of 16 bytes
-* 5. call GCM_add_cipher one last time with any length of cipher/plaintext
-* 6. call GCM_finish to extract the tag.
-*
-* See http://www.mindspring.com/~dmcgrew/gcm-nist-6.pdf
- */
-
-package amcl
-
-/*
-import
-(
-	"fmt"
-	"strconv"
-)
-*/
-const gcm_NB int = 4
-const GCM_ACCEPTING_HEADER int = 0
-const GCM_ACCEPTING_CIPHER int = 1
-const GCM_NOT_ACCEPTING_MORE int = 2
-const GCM_FINISHED int = 3
-const GCM_ENCRYPTING int = 0
-const GCM_DECRYPTING int = 1
-
-type GCM struct {
-	table   [128][4]uint32 /* 2k bytes */
-	stateX  [16]byte
-	Y_0     [16]byte
-	counter int
-	lenA    [2]uint32
-	lenC    [2]uint32
-	status  int
-	a       *AES
-}
-
-func gcm_pack(b [4]byte) uint32 { /* pack bytes into a 32-bit Word */
-	return ((uint32(b[0]) & 0xff) << 24) | ((uint32(b[1]) & 0xff) << 16) | ((uint32(b[2]) & 0xff) << 8) | (uint32(b[3]) & 0xff)
-}
-
-func gcm_unpack(a uint32) [4]byte { /* unpack bytes from a word */
-	var b = [4]byte{byte((a >> 24) & 0xff), byte((a >> 16) & 0xff), byte((a >> 8) & 0xff), byte(a & 0xff)}
-	return b
-}
-
-func (G *GCM) precompute(H []byte) {
-	var b [4]byte
-	j := 0
-	for i := 0; i < gcm_NB; i++ {
-		b[0] = H[j]
-		b[1] = H[j+1]
-		b[2] = H[j+2]
-		b[3] = H[j+3]
-		G.table[0][i] = gcm_pack(b)
-		j += 4
-	}
-	for i := 1; i < 128; i++ {
-		c := uint32(0)
-		for j := 0; j < gcm_NB; j++ {
-			G.table[i][j] = c | (G.table[i-1][j])>>1
-			c = G.table[i-1][j] << 31
-		}
-		if c != 0 {
-			G.table[i][0] ^= 0xE1000000
-		} /* irreducible polynomial */
-	}
-}
-
-func (G *GCM) gf2mul() { /* gf2m mul - Z=H*X mod 2^128 */
-	var P [4]uint32
-
-	for i := 0; i < 4; i++ {
-		P[i] = 0
-	}
-	j := uint(8)
-	m := 0
-	for i := 0; i < 128; i++ {
-		j--
-		c := (G.stateX[m] >> j) & 1
-		if c != 0 {
-			for k := 0; k < gcm_NB; k++ {
-				P[k] ^= G.table[i][k]
-			}
-		}
-		if j == 0 {
-			j = 8
-			m++
-			if m == 16 {
-				break
-			}
-		}
-	}
-	j = 0
-	for i := 0; i < gcm_NB; i++ {
-		b := gcm_unpack(P[i])
-		G.stateX[j] = b[0]
-		G.stateX[j+1] = b[1]
-		G.stateX[j+2] = b[2]
-		G.stateX[j+3] = b[3]
-		j += 4
-	}
-}
-
-func (G *GCM) wrap() { /* Finish off GHASH */
-	var F [4]uint32
-	var L [16]byte
-
-	/* convert lengths from bytes to bits */
-	F[0] = (G.lenA[0] << 3) | (G.lenA[1]&0xE0000000)>>29
-	F[1] = G.lenA[1] << 3
-	F[2] = (G.lenC[0] << 3) | (G.lenC[1]&0xE0000000)>>29
-	F[3] = G.lenC[1] << 3
-	j := 0
-	for i := 0; i < gcm_NB; i++ {
-		b := gcm_unpack(F[i])
-		L[j] = b[0]
-		L[j+1] = b[1]
-		L[j+2] = b[2]
-		L[j+3] = b[3]
-		j += 4
-	}
-	for i := 0; i < 16; i++ {
-		G.stateX[i] ^= L[i]
-	}
-	G.gf2mul()
-}
-
-func (G *GCM) ghash(plain []byte, len int) bool {
-	if G.status == GCM_ACCEPTING_HEADER {
-		G.status = GCM_ACCEPTING_CIPHER
-	}
-	if G.status != GCM_ACCEPTING_CIPHER {
-		return false
-	}
-
-	j := 0
-	for j < len {
-		for i := 0; i < 16 && j < len; i++ {
-			G.stateX[i] ^= plain[j]
-			j++
-			G.lenC[1]++
-			if G.lenC[1] == 0 {
-				G.lenC[0]++
-			}
-		}
-		G.gf2mul()
-	}
-	if len%16 != 0 {
-		G.status = GCM_NOT_ACCEPTING_MORE
-	}
-	return true
-}
-
-/* Initialize GCM mode */
-func (G *GCM) Init(key []byte, niv int, iv []byte) { /* iv size niv is usually 12 bytes (96 bits). AES key size nk can be 16,24 or 32 bytes */
-	var H [16]byte
-
-	for i := 0; i < 16; i++ {
-		H[i] = 0
-		G.stateX[i] = 0
-	}
-
-	G.a = new(AES)
-
-	G.a.Init(aes_ECB, key, iv)
-	G.a.ecb_encrypt(H[:]) /* E(K,0) */
-	G.precompute(H[:])
-
-	G.lenA[0] = 0
-	G.lenC[0] = 0
-	G.lenA[1] = 0
-	G.lenC[1] = 0
-	if niv == 12 {
-		for i := 0; i < 12; i++ {
-			G.a.f[i] = iv[i]
-		}
-		b := gcm_unpack(uint32(1))
-		G.a.f[12] = b[0]
-		G.a.f[13] = b[1]
-		G.a.f[14] = b[2]
-		G.a.f[15] = b[3] /* initialise IV */
-		for i := 0; i < 16; i++ {
-			G.Y_0[i] = G.a.f[i]
-		}
-	} else {
-		G.status = GCM_ACCEPTING_CIPHER
-		G.ghash(iv, niv) /* GHASH(H,0,IV) */
-		G.wrap()
-		for i := 0; i < 16; i++ {
-			G.a.f[i] = G.stateX[i]
-			G.Y_0[i] = G.a.f[i]
-			G.stateX[i] = 0
-		}
-		G.lenA[0] = 0
-		G.lenC[0] = 0
-		G.lenA[1] = 0
-		G.lenC[1] = 0
-	}
-	G.status = GCM_ACCEPTING_HEADER
-}
-
-/* Add Header data - included but not encrypted */
-func (G *GCM) Add_header(header []byte, len int) bool { /* Add some header. Won't be encrypted, but will be authenticated. len is length of header */
-	if G.status != GCM_ACCEPTING_HEADER {
-		return false
-	}
-
-	j := 0
-	for j < len {
-		for i := 0; i < 16 && j < len; i++ {
-			G.stateX[i] ^= header[j]
-			j++
-			G.lenA[1]++
-			if G.lenA[1] == 0 {
-				G.lenA[0]++
-			}
-		}
-		G.gf2mul()
-	}
-	if len%16 != 0 {
-		G.status = GCM_ACCEPTING_CIPHER
-	}
-	return true
-}
-
-/* Add Plaintext - included and encrypted */
-func (G *GCM) Add_plain(plain []byte, len int) []byte {
-	var B [16]byte
-	var b [4]byte
-
-	cipher := make([]byte, len)
-	var counter uint32 = 0
-	if G.status == GCM_ACCEPTING_HEADER {
-		G.status = GCM_ACCEPTING_CIPHER
-	}
-	if G.status != GCM_ACCEPTING_CIPHER {
-		return nil
-	}
-
-	j := 0
-	for j < len {
-
-		b[0] = G.a.f[12]
-		b[1] = G.a.f[13]
-		b[2] = G.a.f[14]
-		b[3] = G.a.f[15]
-		counter = gcm_pack(b)
-		counter++
-		b = gcm_unpack(counter)
-		G.a.f[12] = b[0]
-		G.a.f[13] = b[1]
-		G.a.f[14] = b[2]
-		G.a.f[15] = b[3] /* increment counter */
-		for i := 0; i < 16; i++ {
-			B[i] = G.a.f[i]
-		}
-		G.a.ecb_encrypt(B[:]) /* encrypt it  */
-
-		for i := 0; i < 16 && j < len; i++ {
-			cipher[j] = (plain[j] ^ B[i])
-			G.stateX[i] ^= cipher[j]
-			j++
-			G.lenC[1]++
-			if G.lenC[1] == 0 {
-				G.lenC[0]++
-			}
-		}
-		G.gf2mul()
-	}
-	if len%16 != 0 {
-		G.status = GCM_NOT_ACCEPTING_MORE
-	}
-	return cipher
-}
-
-/* Add Ciphertext - decrypts to plaintext */
-func (G *GCM) Add_cipher(cipher []byte, len int) []byte {
-	var B [16]byte
-	var b [4]byte
-
-	plain := make([]byte, len)
-	var counter uint32 = 0
-
-	if G.status == GCM_ACCEPTING_HEADER {
-		G.status = GCM_ACCEPTING_CIPHER
-	}
-	if G.status != GCM_ACCEPTING_CIPHER {
-		return nil
-	}
-
-	j := 0
-	for j < len {
-		b[0] = G.a.f[12]
-		b[1] = G.a.f[13]
-		b[2] = G.a.f[14]
-		b[3] = G.a.f[15]
-		counter = gcm_pack(b)
-		counter++
-		b = gcm_unpack(counter)
-		G.a.f[12] = b[0]
-		G.a.f[13] = b[1]
-		G.a.f[14] = b[2]
-		G.a.f[15] = b[3] /* increment counter */
-		for i := 0; i < 16; i++ {
-			B[i] = G.a.f[i]
-		}
-		G.a.ecb_encrypt(B[:]) /* encrypt it  */
-		for i := 0; i < 16 && j < len; i++ {
-			plain[j] = (cipher[j] ^ B[i])
-			G.stateX[i] ^= cipher[j]
-			j++
-			G.lenC[1]++
-			if G.lenC[1] == 0 {
-				G.lenC[0]++
-			}
-		}
-		G.gf2mul()
-	}
-	if len%16 != 0 {
-		G.status = GCM_NOT_ACCEPTING_MORE
-	}
-	return plain
-}
-
-/* Finish and extract Tag */
-func (G *GCM) Finish(extract bool) [16]byte { /* Finish off GHASH and extract tag (MAC) */
-	var tag [16]byte
-
-	G.wrap()
-	/* extract tag */
-	if extract {
-		G.a.ecb_encrypt(G.Y_0[:]) /* E(K,Y0) */
-		for i := 0; i < 16; i++ {
-			G.Y_0[i] ^= G.stateX[i]
-		}
-		for i := 0; i < 16; i++ {
-			tag[i] = G.Y_0[i]
-			G.Y_0[i] = 0
-			G.stateX[i] = 0
-		}
-	}
-	G.status = GCM_FINISHED
-	G.a.End()
-	return tag
-}
-
-/* AES-GCM Encryption:
-   K is key, H is header, IV is initialization vector and P is plaintext.
-   Returns cipthertext and tag (MAC) */
-func AES_GCM_ENCRYPT(K, IV, H, P []byte) ([]byte, []byte) {
-	g := new(GCM)
-	lenIV := len(IV)
-	lenH := len(H)
-	lenP := len(P)
-
-	g.Init(K, lenIV, IV)
-	g.Add_header(H, lenH)
-	C := g.Add_plain(P, lenP)
-	T := g.Finish(true)
-	return C, T[:]
-}
-
-/* AES-GCM Deryption:
-   K is key, H is header, IV is initialization vector and P is plaintext.
-   Returns cipthertext and tag (MAC) */
-func AES_GCM_DECRYPT(K, IV, H, C []byte) ([]byte, []byte) {
-	g := new(GCM)
-	lenIV := len(IV)
-	lenH := len(H)
-	lenC := len(C)
-
-	g.Init(K, lenIV, IV)
-	g.Add_header(H, lenH)
-	P := g.Add_cipher(C, lenC)
-	T := g.Finish(true)
-	return P, T[:]
-}
-
-/*
-func hex2bytes(s string) []byte {
-	lgh:=len(s)
-	data:=make([]byte,lgh/2)
-
-        for i:=0;i<lgh;i+=2 {
-            a,_ := strconv.ParseInt(s[i:i+2],16,32)
-	    data[i/2]=byte(a)
-        }
-        return data
-}
-
-func main() {
-
-	KT:="feffe9928665731c6d6a8f9467308308"
-	MT:="d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39"
-	HT:="feedfacedeadbeeffeedfacedeadbeefabaddad2"
-
-	NT:="9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b";
-// Tag should be 619cc5aefffe0bfa462af43c1699d050
-
-	g:=new(GCM)
-
-	M:=hex2bytes(MT)
-	H:=hex2bytes(HT)
-	N:=hex2bytes(NT)
-	K:=hex2bytes(KT)
-
-	lenM:=len(M)
-	lenH:=len(H)
-	//lenK:=len(K)
-	lenIV:=len(N)
-
- 	fmt.Printf("Plaintext=\n");
-	for i:=0;i<lenM;i++ {fmt.Printf("%02x",M[i])}
-	fmt.Printf("\n")
-
-	g.Init(K,lenIV,N)
-	g.Add_header(H,lenH)
-	C:=g.Add_plain(M,lenM)
-	T:=g.Finish(true)
-
-	fmt.Printf("Ciphertext=\n")
-	for i:=0;i<lenM;i++ {fmt.Printf("%02x",C[i])}
-	fmt.Printf("\n")
-
-	fmt.Printf("Tag=\n")
-	for i:=0;i<16;i++ {fmt.Printf("%02x",T[i])}
-	fmt.Printf("\n")
-
-	g.Init(K,lenIV,N)
-	g.Add_header(H,lenH)
-	P:=g.Add_cipher(C,lenM)
-	T=g.Finish(true)
-
- 	fmt.Printf("Plaintext=\n");
-	for i:=0;i<lenM;i++ {fmt.Printf("%02x",P[i])}
-	fmt.Printf("\n")
-
-	fmt.Printf("Tag=\n");
-	for i:=0;i<16;i++ {fmt.Printf("%02x",T[i])}
-	fmt.Printf("\n")
-}
-*/
diff --git a/go/amcl-go/HASH.go b/go/amcl-go/HASH.go
deleted file mode 100644
index c31f51a..0000000
--- a/go/amcl-go/HASH.go
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
-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.
-*/
-
-/*
- * Implementation of the Secure Hashing Algorithm (SHA-256)
- *
- * Generates a 256 bit message digest. It should be impossible to come
- * come up with two messages that hash to the same value ("collision free").
- *
- * For use with byte-oriented messages only.
- */
-
-package amcl
-
-//import "fmt"
-
-const hash_H0 uint32 = 0x6A09E667
-const hash_H1 uint32 = 0xBB67AE85
-const hash_H2 uint32 = 0x3C6EF372
-const hash_H3 uint32 = 0xA54FF53A
-const hash_H4 uint32 = 0x510E527F
-const hash_H5 uint32 = 0x9B05688C
-const hash_H6 uint32 = 0x1F83D9AB
-const hash_H7 uint32 = 0x5BE0CD19
-
-var hash_K = [...]uint32{
-	0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
-	0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
-	0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
-	0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
-	0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
-	0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
-	0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
-	0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2}
-
-type HASH struct {
-	length [2]uint32
-	h      [8]uint32
-	w      [64]uint32
-}
-
-/* functions */
-func hash_S(n uint32, x uint32) uint32 {
-	return (((x) >> n) | ((x) << (32 - n)))
-}
-
-func hash_R(n uint32, x uint32) uint32 {
-	return ((x) >> n)
-}
-
-func hash_Ch(x, y, z uint32) uint32 {
-	return ((x & y) ^ (^(x) & z))
-}
-
-func hash_Maj(x, y, z uint32) uint32 {
-	return ((x & y) ^ (x & z) ^ (y & z))
-}
-
-func hash_Sig0(x uint32) uint32 {
-	return (hash_S(2, x) ^ hash_S(13, x) ^ hash_S(22, x))
-}
-
-func hash_Sig1(x uint32) uint32 {
-	return (hash_S(6, x) ^ hash_S(11, x) ^ hash_S(25, x))
-}
-
-func hash_theta0(x uint32) uint32 {
-	return (hash_S(7, x) ^ hash_S(18, x) ^ hash_R(3, x))
-}
-
-func hash_theta1(x uint32) uint32 {
-	return (hash_S(17, x) ^ hash_S(19, x) ^ hash_R(10, x))
-}
-
-func (H *HASH) transform() { /* basic transformation step */
-	for j := 16; j < 64; j++ {
-		H.w[j] = hash_theta1(H.w[j-2]) + H.w[j-7] + hash_theta0(H.w[j-15]) + H.w[j-16]
-	}
-	a := H.h[0]
-	b := H.h[1]
-	c := H.h[2]
-	d := H.h[3]
-	e := H.h[4]
-	f := H.h[5]
-	g := H.h[6]
-	hh := H.h[7]
-	for j := 0; j < 64; j++ { /* 64 times - mush it up */
-		t1 := hh + hash_Sig1(e) + hash_Ch(e, f, g) + hash_K[j] + H.w[j]
-		t2 := hash_Sig0(a) + hash_Maj(a, b, c)
-		hh = g
-		g = f
-		f = e
-		e = d + t1
-		d = c
-		c = b
-		b = a
-		a = t1 + t2
-	}
-	H.h[0] += a
-	H.h[1] += b
-	H.h[2] += c
-	H.h[3] += d
-	H.h[4] += e
-	H.h[5] += f
-	H.h[6] += g
-	H.h[7] += hh
-}
-
-/* Initialise Hash function */
-func (H *HASH) Init() { /* initialise */
-	for i := 0; i < 64; i++ {
-		H.w[i] = 0
-	}
-	H.length[0] = 0
-	H.length[1] = 0
-	H.h[0] = hash_H0
-	H.h[1] = hash_H1
-	H.h[2] = hash_H2
-	H.h[3] = hash_H3
-	H.h[4] = hash_H4
-	H.h[5] = hash_H5
-	H.h[6] = hash_H6
-	H.h[7] = hash_H7
-}
-
-func NewHASH() *HASH {
-	H := new(HASH)
-	H.Init()
-	return H
-}
-
-/* process a single byte */
-func (H *HASH) Process(byt byte) { /* process the next message byte */
-	cnt := (H.length[0] / 32) % 16
-
-	H.w[cnt] <<= 8
-	H.w[cnt] |= uint32(byt & 0xFF)
-	H.length[0] += 8
-	if H.length[0] == 0 {
-		H.length[1]++
-		H.length[0] = 0
-	}
-	if (H.length[0] % 512) == 0 {
-		H.transform()
-	}
-}
-
-/* process an array of bytes */
-func (H *HASH) Process_array(b []byte) {
-	for i := 0; i < len(b); i++ {
-		H.Process((b[i]))
-	}
-}
-
-/* process a 32-bit integer */
-func (H *HASH) Process_num(n int32) {
-	H.Process(byte((n >> 24) & 0xff))
-	H.Process(byte((n >> 16) & 0xff))
-	H.Process(byte((n >> 8) & 0xff))
-	H.Process(byte(n & 0xff))
-}
-
-/* Generate 32-byte Hash */
-func (H *HASH) Hash() [32]byte { /* pad message and finish - supply digest */
-	var digest [32]byte
-	len0 := H.length[0]
-	len1 := H.length[1]
-	H.Process(0x80)
-	for (H.length[0] % 512) != 448 {
-		H.Process(0)
-	}
-	H.w[14] = len1
-	H.w[15] = len0
-	H.transform()
-	for i := 0; i < 32; i++ { /* convert to bytes */
-		digest[i] = byte((H.h[i/4] >> uint(8*(3-i%4))) & 0xff)
-	}
-	H.Init()
-	return digest
-}
-
-/* test program: should produce digest */
-
-//248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1
-/*
-func main() {
-
-	test := []byte("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")
-	sh:=NewHASH()
-
-	for i:=0;i<len(test);i++ {
-		sh.Process(test[i])
-	}
-
-	digest:=sh.Hash()
-	for i:=0;i<32;i++ {fmt.Printf("%02x",digest[i])}
-
-}
-*/
diff --git a/go/amcl-go/MPIN.go b/go/amcl-go/MPIN.go
deleted file mode 100644
index 42a2443..0000000
--- a/go/amcl-go/MPIN.go
+++ /dev/null
@@ -1,807 +0,0 @@
-/*
-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.
-*/
-
-/* MPIN API Functions */
-
-package amcl
-
-import "time"
-
-import "fmt"
-
-/* Configure mode of operation */
-
-const PERMITS bool = true
-const PINERROR bool = true
-const FULL bool = true
-const SINGLE_PASS bool = false
-
-const MPIN_EFS int = int(MODBYTES)
-const MPIN_EGS int = int(MODBYTES)
-const MPIN_PAS int = 16
-const MPIN_BAD_PARAMS int = -11
-const MPIN_INVALID_POINT int = -14
-const MPIN_WRONG_ORDER int = -18
-const MPIN_BAD_PIN int = -19
-
-/* Configure your PIN here */
-
-const MPIN_MAXPIN int32 = 10000 /* PIN less than this */
-const MPIN_PBLEN int32 = 14     /* Number of bits in PIN */
-const MPIN_TS int = 10          /* 10 for 4 digit PIN, 14 for 6-digit PIN - 2^TS/TS approx = sqrt(MAXPIN) */
-const MPIN_TRAP int = 200       /* 200 for 4 digit PIN, 2000 for 6-digit PIN  - approx 2*sqrt(MAXPIN) */
-
-/* Hash number (optional) and string to point on curve */
-
-func Hashit(n int32, ID []byte) []byte {
-	H := NewHASH()
-	if n != 0 {
-		H.Process_num(n)
-	}
-	H.Process_array(ID)
-	h := H.Hash()
-	return h[:]
-}
-
-func mapit(h []byte) *ECP {
-	q := NewBIGints(Modulus)
-	x := fromBytes(h[:])
-	x.mod(q)
-	var P *ECP
-	for true {
-		P = NewECPbigint(x, 0)
-		if !P.is_infinity() {
-			break
-		}
-		x.inc(1)
-		x.norm()
-	}
-	return P
-}
-
-/* needed for SOK */
-func mapit2(h []byte) *ECP2 {
-	q := NewBIGints(Modulus)
-	x := fromBytes(h[:])
-	one := NewBIGint(1)
-	var X *FP2
-	var Q, T, K *ECP2
-	x.mod(q)
-	for true {
-		X = NewFP2bigs(one, x)
-		Q = NewECP2fp2(X)
-		if !Q.is_infinity() {
-			break
-		}
-		x.inc(1)
-		x.norm()
-	}
-	/* Fast Hashing to G2 - Fuentes-Castaneda, Knapp and Rodriguez-Henriquez */
-	Fra := NewBIGints(CURVE_Fra)
-	Frb := NewBIGints(CURVE_Frb)
-	X = NewFP2bigs(Fra, Frb)
-	x = NewBIGints(CURVE_Bnx)
-
-	T = NewECP2()
-	T.copy(Q)
-	T.mul(x)
-	T.neg()
-	K = NewECP2()
-	K.copy(T)
-	K.dbl()
-	K.add(T)
-	K.affine()
-
-	K.frob(X)
-	Q.frob(X)
-	Q.frob(X)
-	Q.frob(X)
-	Q.add(T)
-	Q.add(K)
-	T.frob(X)
-	T.frob(X)
-	Q.add(T)
-	Q.affine()
-	return Q
-}
-
-/* return time in slots since epoch */
-func MPIN_today() int {
-	now := time.Now()
-	return int(now.Unix()) / (60 * 1440)
-}
-
-/* these next two functions help to implement elligator squared - http://eprint.iacr.org/2014/043 */
-/* maps a random u to a point on the curve */
-func emap(u *BIG, cb int) *ECP {
-	var P *ECP
-	x := NewBIGcopy(u)
-	p := NewBIGints(Modulus)
-	x.mod(p)
-	for true {
-		P = NewECPbigint(x, cb)
-		if !P.is_infinity() {
-			break
-		}
-		x.inc(1)
-		x.norm()
-	}
-	return P
-}
-
-/* returns u derived from P. Random value in range 1 to return value should then be added to u */
-func unmap(u *BIG, P *ECP) int {
-	s := P.getS()
-	var R *ECP
-	r := 0
-	x := P.getX()
-	u.copy(x)
-	for true {
-		u.dec(1)
-		u.norm()
-		r++
-		R = NewECPbigint(u, s)
-		if !R.is_infinity() {
-			break
-		}
-	}
-	return r
-}
-
-func MPIN_HASH_ID(ID []byte) []byte {
-	return Hashit(0, ID)
-}
-
-/* these next two functions implement elligator squared - http://eprint.iacr.org/2014/043 */
-/* Elliptic curve point E in format (0x04,x,y} is converted to form {0x0-,u,v} */
-/* Note that u and v are indistinguisible from random strings */
-func MPIN_ENCODING(rng *RAND, E []byte) int {
-	var T [MPIN_EFS]byte
-
-	for i := 0; i < MPIN_EFS; i++ {
-		T[i] = E[i+1]
-	}
-	u := fromBytes(T[:])
-	for i := 0; i < MPIN_EFS; i++ {
-		T[i] = E[i+MPIN_EFS+1]
-	}
-	v := fromBytes(T[:])
-
-	P := NewECPbigs(u, v)
-	if P.is_infinity() {
-		return MPIN_INVALID_POINT
-	}
-
-	p := NewBIGints(Modulus)
-	u = randomnum(p, rng)
-
-	su := int(rng.GetByte())
-	su %= 2
-
-	W := emap(u, su)
-	P.sub(W)
-	sv := P.getS()
-	rn := unmap(v, P)
-	m := int(rng.GetByte())
-	m %= rn
-	v.inc(m + 1)
-	E[0] = byte(su + 2*sv)
-	u.toBytes(T[:])
-	for i := 0; i < MPIN_EFS; i++ {
-		E[i+1] = T[i]
-	}
-	v.toBytes(T[:])
-	for i := 0; i < MPIN_EFS; i++ {
-		E[i+MPIN_EFS+1] = T[i]
-	}
-
-	return 0
-}
-
-func MPIN_DECODING(D []byte) int {
-	var T [MPIN_EFS]byte
-
-	if (D[0] & 0x04) != 0 {
-		return MPIN_INVALID_POINT
-	}
-
-	for i := 0; i < MPIN_EFS; i++ {
-		T[i] = D[i+1]
-	}
-	u := fromBytes(T[:])
-	for i := 0; i < MPIN_EFS; i++ {
-		T[i] = D[i+MPIN_EFS+1]
-	}
-	v := fromBytes(T[:])
-
-	su := int(D[0] & 1)
-	sv := int((D[0] >> 1) & 1)
-	W := emap(u, su)
-	P := emap(v, sv)
-	P.add(W)
-	u = P.getX()
-	v = P.getY()
-	D[0] = 0x04
-	u.toBytes(T[:])
-	for i := 0; i < MPIN_EFS; i++ {
-		D[i+1] = T[i]
-	}
-	v.toBytes(T[:])
-	for i := 0; i < MPIN_EFS; i++ {
-		D[i+MPIN_EFS+1] = T[i]
-	}
-
-	return 0
-}
-
-/* R=R1+R2 in group G1 */
-func MPIN_RECOMBINE_G1(R1 []byte, R2 []byte, R []byte) int {
-	P := ECP_fromBytes(R1)
-	Q := ECP_fromBytes(R2)
-
-	if P.is_infinity() || Q.is_infinity() {
-		return MPIN_INVALID_POINT
-	}
-
-	P.add(Q)
-
-	P.toBytes(R[:])
-	return 0
-}
-
-/* W=W1+W2 in group G2 */
-func MPIN_RECOMBINE_G2(W1 []byte, W2 []byte, W []byte) int {
-	P := ECP2_fromBytes(W1)
-	Q := ECP2_fromBytes(W2)
-
-	if P.is_infinity() || Q.is_infinity() {
-		return MPIN_INVALID_POINT
-	}
-
-	P.add(Q)
-
-	P.toBytes(W)
-	return 0
-}
-
-/* create random secret S */
-func MPIN_RANDOM_GENERATE(rng *RAND, S []byte) int {
-	r := NewBIGints(CURVE_Order)
-	s := randomnum(r, rng)
-
-	s.toBytes(S)
-	return 0
-}
-
-/* Extract PIN from TOKEN for identity CID */
-func MPIN_EXTRACT_PIN(CID []byte, pin int, TOKEN []byte) int {
-	P := ECP_fromBytes(TOKEN)
-	if P.is_infinity() {
-		return MPIN_INVALID_POINT
-	}
-	h := Hashit(0, CID)
-	R := mapit(h)
-
-	R = R.pinmul(int32(pin)%MPIN_MAXPIN, MPIN_PBLEN)
-	P.sub(R)
-
-	P.toBytes(TOKEN)
-
-	return 0
-}
-
-/* Implement step 2 on client side of MPin protocol */
-func MPIN_CLIENT_2(X []byte, Y []byte, SEC []byte) int {
-	r := NewBIGints(CURVE_Order)
-	P := ECP_fromBytes(SEC)
-	if P.is_infinity() {
-		return MPIN_INVALID_POINT
-	}
-
-	px := fromBytes(X)
-	py := fromBytes(Y)
-	px.add(py)
-	px.mod(r)
-	px.rsub(r)
-
-	G1mul(P, px).toBytes(SEC)
-	return 0
-}
-
-/* Implement step 1 on client side of MPin protocol */
-func MPIN_CLIENT_1(date int, CLIENT_ID []byte, rng *RAND, X []byte, pin int, TOKEN []byte, SEC []byte, xID []byte, xCID []byte, PERMIT []byte) int {
-	r := NewBIGints(CURVE_Order)
-
-	var x *BIG
-	if rng != nil {
-		x = randomnum(r, rng)
-		x.toBytes(X)
-	} else {
-		x = fromBytes(X)
-	}
-
-	h := Hashit(0, CLIENT_ID)
-	P := mapit(h)
-
-	T := ECP_fromBytes(TOKEN)
-	if T.is_infinity() {
-		return MPIN_INVALID_POINT
-	}
-
-	W := P.pinmul(int32(pin)%MPIN_MAXPIN, MPIN_PBLEN)
-	T.add(W)
-	if date != 0 {
-		W = ECP_fromBytes(PERMIT)
-		if W.is_infinity() {
-			return MPIN_INVALID_POINT
-		}
-		T.add(W)
-		h = Hashit(int32(date), h)
-		W = mapit(h)
-		if xID != nil {
-			P = G1mul(P, x)
-			P.toBytes(xID)
-			W = G1mul(W, x)
-			P.add(W)
-		} else {
-			P.add(W)
-			P = G1mul(P, x)
-		}
-		if xCID != nil {
-			P.toBytes(xCID)
-		}
-	} else {
-		if xID != nil {
-			P = G1mul(P, x)
-			P.toBytes(xID)
-		}
-	}
-
-	T.toBytes(SEC)
-	return 0
-}
-
-/* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */
-func MPIN_GET_SERVER_SECRET(S []byte, SST []byte) int {
-	Q := NewECP2fp2s(NewFP2bigs(NewBIGints(CURVE_Pxa), NewBIGints(CURVE_Pxb)), NewFP2bigs(NewBIGints(CURVE_Pya), NewBIGints(CURVE_Pyb)))
-
-	s := fromBytes(S)
-	Q = G2mul(Q, s)
-	Q.toBytes(SST)
-	return 0
-}
-
-/*
- W=x*H(G);
- if RNG == NULL then X is passed in
- if RNG != NULL the X is passed out
- if type=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve
-*/
-func MPIN_GET_G1_MULTIPLE(rng *RAND, typ int, X []byte, G []byte, W []byte) int {
-	var x *BIG
-	r := NewBIGints(CURVE_Order)
-	if rng != nil {
-		x = randomnum(r, rng)
-		x.toBytes(X)
-	} else {
-		x = fromBytes(X)
-	}
-	var P *ECP
-	if typ == 0 {
-		P = ECP_fromBytes(G)
-		if P.is_infinity() {
-			return MPIN_INVALID_POINT
-		}
-	} else {
-		P = mapit(G)
-	}
-
-	G1mul(P, x).toBytes(W)
-	return 0
-}
-
-/* Client secret CST=S*H(CID) where CID is client ID and S is master secret */
-/* CID is hashed externally */
-func MPIN_GET_CLIENT_SECRET(S []byte, CID []byte, CST []byte) int {
-	return MPIN_GET_G1_MULTIPLE(nil, 1, S, CID, CST)
-}
-
-/* Time Permit CTT=S*(date|H(CID)) where S is master secret */
-func MPIN_GET_CLIENT_PERMIT(date int, S []byte, CID []byte, CTT []byte) int {
-	h := Hashit(int32(date), CID)
-	P := mapit(h)
-
-	s := fromBytes(S)
-	G1mul(P, s).toBytes(CTT)
-	return 0
-}
-
-/* Outputs H(CID) and H(T|H(CID)) for time permits. If no time permits set HID=HTID */
-func MPIN_SERVER_1(date int, CID []byte, HID []byte, HTID []byte) {
-	h := Hashit(0, CID)
-	P := mapit(h)
-
-	if date != 0 {
-		if HID != nil {
-			P.toBytes(HID)
-		}
-		h = Hashit(int32(date), h)
-		R := mapit(h)
-		P.add(R)
-		P.toBytes(HTID)
-	} else {
-		P.toBytes(HID)
-	}
-}
-
-/* Implement step 2 of MPin protocol on server side */
-func MPIN_SERVER_2(date int, HID []byte, HTID []byte, Y []byte, SST []byte, xID []byte, xCID []byte, mSEC []byte, E []byte, F []byte) int {
-	//	q:=NewBIGints(Modulus)
-	Q := NewECP2fp2s(NewFP2bigs(NewBIGints(CURVE_Pxa), NewBIGints(CURVE_Pxb)), NewFP2bigs(NewBIGints(CURVE_Pya), NewBIGints(CURVE_Pyb)))
-
-	sQ := ECP2_fromBytes(SST)
-	if sQ.is_infinity() {
-		return MPIN_INVALID_POINT
-	}
-
-	var R *ECP
-	if date != 0 {
-		R = ECP_fromBytes(xCID)
-	} else {
-		if xID == nil {
-			return MPIN_BAD_PARAMS
-		}
-		R = ECP_fromBytes(xID)
-	}
-	if R.is_infinity() {
-		return MPIN_INVALID_POINT
-	}
-
-	y := fromBytes(Y)
-	var P *ECP
-	if date != 0 {
-		P = ECP_fromBytes(HTID)
-	} else {
-		if HID == nil {
-			return MPIN_BAD_PARAMS
-		}
-		P = ECP_fromBytes(HID)
-	}
-
-	if P.is_infinity() {
-		return MPIN_INVALID_POINT
-	}
-
-	P = G1mul(P, y)
-	P.add(R)
-	R = ECP_fromBytes(mSEC)
-	if R.is_infinity() {
-		return MPIN_INVALID_POINT
-	}
-
-	var g *FP12
-	//		FP12 g1=new FP12(0);
-
-	g = ate2(Q, R, sQ, P)
-	g = fexp(g)
-
-	if !g.isunity() {
-		if HID != nil && xID != nil && E != nil && F != nil {
-			g.toBytes(E)
-			if date != 0 {
-				P = ECP_fromBytes(HID)
-				if P.is_infinity() {
-					return MPIN_INVALID_POINT
-				}
-				R = ECP_fromBytes(xID)
-				if R.is_infinity() {
-					return MPIN_INVALID_POINT
-				}
-
-				P = G1mul(P, y)
-				P.add(R)
-			}
-			g = ate(Q, P)
-			g = fexp(g)
-			g.toBytes(F)
-		}
-		return MPIN_BAD_PIN
-	}
-
-	return 0
-}
-
-/* Pollards kangaroos used to return PIN error */
-func MPIN_KANGAROO(E []byte, F []byte) int {
-	ge := FP12_fromBytes(E)
-	gf := FP12_fromBytes(F)
-	var distance [MPIN_TS]int
-	t := NewFP12copy(gf)
-
-	var table []*FP12
-	var i int
-	s := 1
-	for m := 0; m < MPIN_TS; m++ {
-		distance[m] = s
-		table = append(table, NewFP12copy(t))
-		s *= 2
-		t.usqr()
-	}
-	t.one()
-	dn := 0
-	for j := 0; j < MPIN_TRAP; j++ {
-		i = t.geta().geta().getA().lastbits(8) % MPIN_TS
-		t.mul(table[i])
-		dn += distance[i]
-	}
-	gf.copy(t)
-	gf.conj()
-	steps := 0
-	dm := 0
-	res := 0
-	for dm-dn < int(MPIN_MAXPIN) {
-		steps++
-		if steps > 4*MPIN_TRAP {
-			break
-		}
-		i = ge.geta().geta().getA().lastbits(8) % MPIN_TS
-		ge.mul(table[i])
-		dm += distance[i]
-		if ge.equals(t) {
-			res = dm - dn
-			break
-		}
-		if ge.equals(gf) {
-			res = dn - dm
-			break
-		}
-
-	}
-	if steps > 4*MPIN_TRAP || dm-dn >= int(MPIN_MAXPIN) {
-		res = 0
-	} // Trap Failed  - probable invalid token
-	return int(res)
-}
-
-/* Functions to support M-Pin Full */
-
-func MPIN_PRECOMPUTE(TOKEN []byte, CID []byte, G1 []byte, G2 []byte) int {
-	var P, T *ECP
-	var g *FP12
-
-	T = ECP_fromBytes(TOKEN)
-	if T.is_infinity() {
-		return MPIN_INVALID_POINT
-	}
-
-	P = mapit(CID)
-
-	Q := NewECP2fp2s(NewFP2bigs(NewBIGints(CURVE_Pxa), NewBIGints(CURVE_Pxb)), NewFP2bigs(NewBIGints(CURVE_Pya), NewBIGints(CURVE_Pyb)))
-
-	g = ate(Q, T)
-	g = fexp(g)
-	g.toBytes(G1)
-
-	g = ate(Q, P)
-	g = fexp(g)
-	g.toBytes(G2)
-
-	return 0
-}
-
-/* calculate common key on client side */
-/* wCID = w.(A+AT) */
-func MPIN_CLIENT_KEY(G1 []byte, G2 []byte, pin int, R []byte, X []byte, wCID []byte, CK []byte) int {
-	H := NewHASH()
-	var t [MPIN_EFS]byte
-
-	g1 := FP12_fromBytes(G1)
-	g2 := FP12_fromBytes(G2)
-	z := fromBytes(R)
-	x := fromBytes(X)
-
-	W := ECP_fromBytes(wCID)
-	if W.is_infinity() {
-		return MPIN_INVALID_POINT
-	}
-
-	W = G1mul(W, x)
-
-	f := NewFP2bigs(NewBIGints(CURVE_Fra), NewBIGints(CURVE_Frb))
-	r := NewBIGints(CURVE_Order)
-	q := NewBIGints(Modulus)
-
-	m := NewBIGcopy(q)
-	m.mod(r)
-
-	a := NewBIGcopy(z)
-	a.mod(m)
-
-	b := NewBIGcopy(z)
-	b.div(m)
-
-	g2.pinpow(pin, int(MPIN_PBLEN))
-	g1.mul(g2)
-
-	c := g1.trace()
-	g2.copy(g1)
-	g2.frob(f)
-	cp := g2.trace()
-	g1.conj()
-	g2.mul(g1)
-	cpm1 := g2.trace()
-	g2.mul(g1)
-	cpm2 := g2.trace()
-
-	c = c.xtr_pow2(cp, cpm1, cpm2, a, b)
-
-	c.geta().getA().toBytes(t[:])
-	H.Process_array(t[:])
-	c.geta().getB().toBytes(t[:])
-	H.Process_array(t[:])
-	c.getb().getA().toBytes(t[:])
-	H.Process_array(t[:])
-	c.getb().getB().toBytes(t[:])
-	H.Process_array(t[:])
-
-	W.getX().toBytes(t[:])
-	H.Process_array(t[:])
-	W.getY().toBytes(t[:])
-	H.Process_array(t[:])
-
-	t = H.Hash()
-	for i := 0; i < MPIN_PAS; i++ {
-		CK[i] = t[i]
-	}
-
-	return 0
-}
-
-/* calculate common key on server side */
-/* Z=r.A - no time permits involved */
-
-func MPIN_SERVER_KEY(Z []byte, SST []byte, W []byte, xID []byte, xCID []byte, SK []byte) int {
-	H := NewHASH()
-	var t [MPIN_EFS]byte
-
-	sQ := ECP2_fromBytes(SST)
-	if sQ.is_infinity() {
-		return MPIN_INVALID_POINT
-	}
-	R := ECP_fromBytes(Z)
-	if R.is_infinity() {
-		return MPIN_INVALID_POINT
-	}
-
-	var U *ECP
-	if xCID != nil {
-		U = ECP_fromBytes(xCID)
-	} else {
-		U = ECP_fromBytes(xID)
-	}
-	if U.is_infinity() {
-		return MPIN_INVALID_POINT
-	}
-
-	w := fromBytes(W)
-	U = G1mul(U, w)
-	g := ate(sQ, R)
-	g = fexp(g)
-
-	c := g.trace()
-	c.geta().getA().toBytes(t[:])
-	H.Process_array(t[:])
-	c.geta().getB().toBytes(t[:])
-	H.Process_array(t[:])
-	c.getb().getA().toBytes(t[:])
-	H.Process_array(t[:])
-	c.getb().getB().toBytes(t[:])
-	H.Process_array(t[:])
-
-	U.getX().toBytes(t[:])
-	H.Process_array(t[:])
-	U.getY().toBytes(t[:])
-	H.Process_array(t[:])
-
-	t = H.Hash()
-	for i := 0; i < MPIN_PAS; i++ {
-		SK[i] = t[i]
-	}
-
-	return 0
-}
-
-/* return time since epoch */
-func MPIN_GET_TIME() int {
-	now := time.Now()
-	return int(now.Unix())
-}
-
-/* Generate Y = H(epoch, xCID/xID) */
-func MPIN_GET_Y(TimeValue int, xCID []byte, Y []byte) {
-	h := Hashit(int32(TimeValue), xCID)
-	y := fromBytes(h)
-	q := NewBIGints(CURVE_Order)
-	y.mod(q)
-	y.toBytes(Y)
-}
-
-/* One pass MPIN Client */
-func MPIN_CLIENT(date int, CLIENT_ID []byte, RNG *RAND, X []byte, pin int, TOKEN []byte, SEC []byte, xID []byte, xCID []byte, PERMIT []byte, MESSAGE []byte, TimeValue int, Y []byte) int {
-	rtn := 0
-
-	var M []byte
-	if date == 0 {
-		M = xID
-	} else {
-		M = xCID
-	}
-
-	rtn = MPIN_CLIENT_1(date, CLIENT_ID, RNG, X, pin, TOKEN, SEC, xID, xCID, PERMIT)
-	if rtn != 0 {
-		return rtn
-	}
-
-	if MESSAGE != nil {
-		M = append(M, MESSAGE...)
-	}
-
-	MPIN_GET_Y(TimeValue, M, Y)
-
-	rtn = MPIN_CLIENT_2(X, Y, SEC)
-	if rtn != 0 {
-		return rtn
-	}
-
-	return 0
-}
-
-/* One pass MPIN Server */
-func MPIN_SERVER(date int, HID []byte, HTID []byte, Y []byte, SST []byte, xID []byte, xCID []byte, SEC []byte, E []byte, F []byte, CID []byte, MESSAGE []byte, TimeValue int) int {
-	rtn := 0
-
-	var M []byte
-	if date == 0 {
-		M = xID
-	} else {
-		M = xCID
-	}
-
-	MPIN_SERVER_1(date, CID, HID, HTID)
-
-	if MESSAGE != nil {
-		M = append(M, MESSAGE...)
-	}
-
-	MPIN_GET_Y(TimeValue, M, Y)
-
-	rtn = MPIN_SERVER_2(date, HID, HTID, Y, SST, xID, xCID, SEC, E, F)
-	if rtn != 0 {
-		return rtn
-	}
-
-	return 0
-}
-
-func MPIN_printBinary(array []byte) {
-	for i := 0; i < len(array); i++ {
-		fmt.Printf("%02x", array[i])
-	}
-	fmt.Printf("\n")
-}
diff --git a/go/amcl-go/MPIN_test.go b/go/amcl-go/MPIN_test.go
deleted file mode 100644
index f489bea..0000000
--- a/go/amcl-go/MPIN_test.go
+++ /dev/null
@@ -1,898 +0,0 @@
-/*
-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.
-*/
-
-package amcl
-
-import (
-	"crypto/rand"
-	"encoding/hex"
-	"fmt"
-	"testing"
-)
-
-func TestGoodPIN(t *testing.T) {
-	want := 0
-	// Assign the End-User an ID
-	IDstr := "testUser@miracl.com"
-	ID := []byte(IDstr)
-
-	// Epoch time in days
-	date := 16660
-
-	// Epoch time in seconds
-	timeValue := 1439465203
-
-	// PIN variable to create token
-	PIN1 := 1234
-	// PIN variable to authenticate
-	PIN2 := 1234
-
-	// Seed value for Random Number Generator (RNG)
-	seedHex := "9e8b4178790cd57a5761c4a6f164ba72"
-	seed, err := hex.DecodeString(seedHex)
-	if err != nil {
-		fmt.Println("Error decoding seed value")
-		return
-	}
-	rng := NewRAND()
-	rng.Seed(len(seed), seed)
-
-	// Message to sign
-	var MESSAGE []byte
-	// MESSAGE := []byte("test sign message")
-
-	const EGS = MPIN_EGS
-	const EFS = MPIN_EFS
-	const G1S = 2*EFS + 1 /* Group 1 Size */
-	const G2S = 4 * EFS   /* Group 2 Size */
-	const EAS = MPIN_PAS
-
-	var MS1 [EGS]byte
-	var SS1 [G2S]byte
-	var CS1 [G1S]byte
-	var TP1 [G1S]byte
-	var MS2 [EGS]byte
-	var SS2 [G2S]byte
-	var CS2 [G1S]byte
-	var TP2 [G1S]byte
-	var SS [G2S]byte
-	var TP [G1S]byte
-	var TOKEN [G1S]byte
-	var SEC [G1S]byte
-	var U [G1S]byte
-	var UT [G1S]byte
-	var X [EGS]byte
-	var Y [EGS]byte
-	var E [12 * EFS]byte
-	var F [12 * EFS]byte
-	var HID [G1S]byte
-	var HTID [G1S]byte
-
-	// Generate Master Secret Share 1
-	MPIN_RANDOM_GENERATE(rng, MS1[:])
-
-	// Generate Master Secret Share 2
-	MPIN_RANDOM_GENERATE(rng, MS2[:])
-
-	// Either Client or TA calculates Hash(ID)
-	HCID := MPIN_HASH_ID(ID)
-
-	// Generate server secret share 1
-	MPIN_GET_SERVER_SECRET(MS1[:], SS1[:])
-
-	// Generate server secret share 2
-	MPIN_GET_SERVER_SECRET(MS2[:], SS2[:])
-
-	// Combine server secret shares
-	MPIN_RECOMBINE_G2(SS1[:], SS2[:], SS[:])
-
-	// Generate client secret share 1
-	MPIN_GET_CLIENT_SECRET(MS1[:], HCID, CS1[:])
-
-	// Generate client secret share 2
-	MPIN_GET_CLIENT_SECRET(MS2[:], HCID, CS2[:])
-
-	// Combine client secret shares : TOKEN is the full client secret
-	MPIN_RECOMBINE_G1(CS1[:], CS2[:], TOKEN[:])
-
-	// Generate time permit share 1
-	MPIN_GET_CLIENT_PERMIT(date, MS1[:], HCID, TP1[:])
-
-	// Generate time permit share 2
-	MPIN_GET_CLIENT_PERMIT(date, MS2[:], HCID, TP2[:])
-
-	// Combine time permit shares
-	MPIN_RECOMBINE_G1(TP1[:], TP2[:], TP[:])
-
-	// Create token
-	MPIN_EXTRACT_PIN(ID, PIN1, TOKEN[:])
-
-	// Authenticate
-	MPIN_CLIENT(date, ID, rng, X[:], PIN2, TOKEN[:], SEC[:], U[:], UT[:], TP[:], MESSAGE, timeValue, Y[:])
-
-	got := MPIN_SERVER(date, HID[:], HTID[:], Y[:], SS[:], U[:], UT[:], SEC[:], E[:], F[:], ID, MESSAGE, timeValue)
-	if got != want {
-		t.Errorf("MPIN GOOD PIN %d != %d", want, got)
-	}
-}
-
-func TestBadPIN(t *testing.T) {
-	want := -19
-	// Assign the End-User an ID
-	IDstr := "testUser@miracl.com"
-	ID := []byte(IDstr)
-
-	// Epoch time in days
-	date := 16660
-
-	// Epoch time in seconds
-	timeValue := 1439465203
-
-	// PIN variable to create token
-	PIN1 := 1234
-	// PIN variable to authenticate
-	PIN2 := 1235
-
-	// Seed value for Random Number Generator (RNG)
-	seedHex := "9e8b4178790cd57a5761c4a6f164ba72"
-	seed, err := hex.DecodeString(seedHex)
-	if err != nil {
-		fmt.Println("Error decoding seed value")
-		return
-	}
-	rng := NewRAND()
-	rng.Seed(len(seed), seed)
-
-	// Message to sign
-	var MESSAGE []byte
-	// MESSAGE := []byte("test sign message")
-
-	const EGS = MPIN_EGS
-	const EFS = MPIN_EFS
-	const G1S = 2*EFS + 1 /* Group 1 Size */
-	const G2S = 4 * EFS   /* Group 2 Size */
-	const EAS = MPIN_PAS
-
-	var MS1 [EGS]byte
-	var SS1 [G2S]byte
-	var CS1 [G1S]byte
-	var TP1 [G1S]byte
-	var MS2 [EGS]byte
-	var SS2 [G2S]byte
-	var CS2 [G1S]byte
-	var TP2 [G1S]byte
-	var SS [G2S]byte
-	var TP [G1S]byte
-	var TOKEN [G1S]byte
-	var SEC [G1S]byte
-	var U [G1S]byte
-	var UT [G1S]byte
-	var X [EGS]byte
-	var Y [EGS]byte
-	var E [12 * EFS]byte
-	var F [12 * EFS]byte
-	var HID [G1S]byte
-	var HTID [G1S]byte
-
-	// Generate Master Secret Share 1
-	MPIN_RANDOM_GENERATE(rng, MS1[:])
-
-	// Generate Master Secret Share 2
-	MPIN_RANDOM_GENERATE(rng, MS2[:])
-
-	// Either Client or TA calculates Hash(ID)
-	HCID := MPIN_HASH_ID(ID)
-
-	// Generate server secret share 1
-	MPIN_GET_SERVER_SECRET(MS1[:], SS1[:])
-
-	// Generate server secret share 2
-	MPIN_GET_SERVER_SECRET(MS2[:], SS2[:])
-
-	// Combine server secret shares
-	MPIN_RECOMBINE_G2(SS1[:], SS2[:], SS[:])
-
-	// Generate client secret share 1
-	MPIN_GET_CLIENT_SECRET(MS1[:], HCID, CS1[:])
-
-	// Generate client secret share 2
-	MPIN_GET_CLIENT_SECRET(MS2[:], HCID, CS2[:])
-
-	// Combine client secret shares : TOKEN is the full client secret
-	MPIN_RECOMBINE_G1(CS1[:], CS2[:], TOKEN[:])
-
-	// Generate time permit share 1
-	MPIN_GET_CLIENT_PERMIT(date, MS1[:], HCID, TP1[:])
-
-	// Generate time permit share 2
-	MPIN_GET_CLIENT_PERMIT(date, MS2[:], HCID, TP2[:])
-
-	// Combine time permit shares
-	MPIN_RECOMBINE_G1(TP1[:], TP2[:], TP[:])
-
-	// Create token
-	MPIN_EXTRACT_PIN(ID, PIN1, TOKEN[:])
-
-	// Authenticate
-	MPIN_CLIENT(date, ID, rng, X[:], PIN2, TOKEN[:], SEC[:], U[:], UT[:], TP[:], MESSAGE, timeValue, Y[:])
-
-	got := MPIN_SERVER(date, HID[:], HTID[:], Y[:], SS[:], U[:], UT[:], SEC[:], E[:], F[:], ID, MESSAGE, timeValue)
-	if got != want {
-		t.Errorf("TestBadPIN %d != %d", want, got)
-	}
-}
-
-func TestBadToken(t *testing.T) {
-	want := -19
-	// Assign the End-User an ID
-	IDstr := "testUser@miracl.com"
-	ID := []byte(IDstr)
-
-	// Epoch time in days
-	date := 16660
-
-	// Epoch time in seconds
-	timeValue := 1439465203
-
-	// PIN variable to create token
-	PIN1 := 1234
-	// PIN variable to authenticate
-	PIN2 := 1234
-
-	// Seed value for Random Number Generator (RNG)
-	seedHex := "9e8b4178790cd57a5761c4a6f164ba72"
-	seed, err := hex.DecodeString(seedHex)
-	if err != nil {
-		fmt.Println("Error decoding seed value")
-		return
-	}
-	rng := NewRAND()
-	rng.Seed(len(seed), seed)
-
-	// Message to sign
-	var MESSAGE []byte
-	// MESSAGE := []byte("test sign message")
-
-	const EGS = MPIN_EGS
-	const EFS = MPIN_EFS
-	const G1S = 2*EFS + 1 /* Group 1 Size */
-	const G2S = 4 * EFS   /* Group 2 Size */
-	const EAS = MPIN_PAS
-
-	var MS1 [EGS]byte
-	var SS1 [G2S]byte
-	var CS1 [G1S]byte
-	var TP1 [G1S]byte
-	var MS2 [EGS]byte
-	var SS2 [G2S]byte
-	var CS2 [G1S]byte
-	var TP2 [G1S]byte
-	var SS [G2S]byte
-	var TP [G1S]byte
-	var TOKEN [G1S]byte
-	var SEC [G1S]byte
-	var U [G1S]byte
-	var UT [G1S]byte
-	var X [EGS]byte
-	var Y [EGS]byte
-	var E [12 * EFS]byte
-	var F [12 * EFS]byte
-	var HID [G1S]byte
-	var HTID [G1S]byte
-
-	// Generate Master Secret Share 1
-	MPIN_RANDOM_GENERATE(rng, MS1[:])
-
-	// Generate Master Secret Share 2
-	MPIN_RANDOM_GENERATE(rng, MS2[:])
-
-	// Either Client or TA calculates Hash(ID)
-	HCID := MPIN_HASH_ID(ID)
-
-	// Generate server secret share 1
-	MPIN_GET_SERVER_SECRET(MS1[:], SS1[:])
-
-	// Generate server secret share 2
-	MPIN_GET_SERVER_SECRET(MS2[:], SS2[:])
-
-	// Combine server secret shares
-	MPIN_RECOMBINE_G2(SS1[:], SS2[:], SS[:])
-
-	// Generate client secret share 1
-	MPIN_GET_CLIENT_SECRET(MS1[:], HCID, CS1[:])
-
-	// Generate client secret share 2
-	MPIN_GET_CLIENT_SECRET(MS2[:], HCID, CS2[:])
-
-	// Combine client secret shares : TOKEN is the full client secret
-	MPIN_RECOMBINE_G1(CS1[:], CS2[:], TOKEN[:])
-
-	// Generate time permit share 1
-	MPIN_GET_CLIENT_PERMIT(date, MS1[:], HCID, TP1[:])
-
-	// Generate time permit share 2
-	MPIN_GET_CLIENT_PERMIT(date, MS2[:], HCID, TP2[:])
-
-	// Combine time permit shares
-	MPIN_RECOMBINE_G1(TP1[:], TP2[:], TP[:])
-
-	// Create token
-	MPIN_EXTRACT_PIN(ID, PIN1, TOKEN[:])
-
-	// Authenticate
-	MPIN_CLIENT(date, ID, rng, X[:], PIN2, TOKEN[:], SEC[:], U[:], UT[:], TP[:], MESSAGE, timeValue, Y[:])
-
-	// Send UT as V to model bad token
-	got := MPIN_SERVER(date, HID[:], HTID[:], Y[:], SS[:], U[:], UT[:], UT[:], E[:], F[:], ID, MESSAGE, timeValue)
-	if got != want {
-		t.Errorf("TestBadToken %d != %d", want, got)
-	}
-}
-
-func TestRandom(t *testing.T) {
-	want := 0
-	// Assign the End-User an ID
-	IDstr := "testUser@miracl.com"
-	ID := []byte(IDstr)
-
-	// Epoch time in days
-	date := 16660
-
-	// Epoch time in seconds
-	timeValue := 1439465203
-
-	// PIN variable to create token
-	PIN1 := 1234
-	// PIN variable to authenticate
-	PIN2 := 1234
-
-	// Seed value for Random Number Generator (RNG)
-	seed := make([]byte, 16)
-	rand.Read(seed)
-	rng := NewRAND()
-	rng.Seed(len(seed), seed)
-
-	// Message to sign
-	var MESSAGE []byte
-	// MESSAGE := []byte("test sign message")
-
-	const EGS = MPIN_EGS
-	const EFS = MPIN_EFS
-	const G1S = 2*EFS + 1 /* Group 1 Size */
-	const G2S = 4 * EFS   /* Group 2 Size */
-	const EAS = MPIN_PAS
-
-	var MS1 [EGS]byte
-	var SS1 [G2S]byte
-	var CS1 [G1S]byte
-	var TP1 [G1S]byte
-	var MS2 [EGS]byte
-	var SS2 [G2S]byte
-	var CS2 [G1S]byte
-	var TP2 [G1S]byte
-	var SS [G2S]byte
-	var TP [G1S]byte
-	var TOKEN [G1S]byte
-	var SEC [G1S]byte
-	var U [G1S]byte
-	var UT [G1S]byte
-	var X [EGS]byte
-	var Y [EGS]byte
-	var E [12 * EFS]byte
-	var F [12 * EFS]byte
-	var HID [G1S]byte
-	var HTID [G1S]byte
-
-	// Generate Master Secret Share 1
-	MPIN_RANDOM_GENERATE(rng, MS1[:])
-
-	// Generate Master Secret Share 2
-	MPIN_RANDOM_GENERATE(rng, MS2[:])
-
-	// Either Client or TA calculates Hash(ID)
-	HCID := MPIN_HASH_ID(ID)
-
-	// Generate server secret share 1
-	MPIN_GET_SERVER_SECRET(MS1[:], SS1[:])
-
-	// Generate server secret share 2
-	MPIN_GET_SERVER_SECRET(MS2[:], SS2[:])
-
-	// Combine server secret shares
-	MPIN_RECOMBINE_G2(SS1[:], SS2[:], SS[:])
-
-	// Generate client secret share 1
-	MPIN_GET_CLIENT_SECRET(MS1[:], HCID, CS1[:])
-
-	// Generate client secret share 2
-	MPIN_GET_CLIENT_SECRET(MS2[:], HCID, CS2[:])
-
-	// Combine client secret shares : TOKEN is the full client secret
-	MPIN_RECOMBINE_G1(CS1[:], CS2[:], TOKEN[:])
-
-	// Generate time permit share 1
-	MPIN_GET_CLIENT_PERMIT(date, MS1[:], HCID, TP1[:])
-
-	// Generate time permit share 2
-	MPIN_GET_CLIENT_PERMIT(date, MS2[:], HCID, TP2[:])
-
-	// Combine time permit shares
-	MPIN_RECOMBINE_G1(TP1[:], TP2[:], TP[:])
-
-	// Create token
-	MPIN_EXTRACT_PIN(ID, PIN1, TOKEN[:])
-
-	// Authenticate
-	MPIN_CLIENT(date, ID, rng, X[:], PIN2, TOKEN[:], SEC[:], U[:], UT[:], TP[:], MESSAGE, timeValue, Y[:])
-
-	got := MPIN_SERVER(date, HID[:], HTID[:], Y[:], SS[:], U[:], UT[:], SEC[:], E[:], F[:], ID, MESSAGE, timeValue)
-	if got != want {
-		t.Errorf("TestRandom %d != %d", want, got)
-	}
-}
-
-func TestGoodSignature(t *testing.T) {
-	want := 0
-	// Assign the End-User an ID
-	IDstr := "testUser@miracl.com"
-	ID := []byte(IDstr)
-
-	// Message to sign
-	MESSAGE := []byte("test message to sign")
-
-	// Epoch time in days
-	date := 16660
-
-	// Epoch time in seconds
-	timeValue := 1439465203
-
-	// PIN variable to create token
-	PIN1 := 1234
-	// PIN variable to authenticate
-	PIN2 := 1234
-
-	// Seed value for Random Number Generator (RNG)
-	seedHex := "9e8b4178790cd57a5761c4a6f164ba72"
-	seed, err := hex.DecodeString(seedHex)
-	if err != nil {
-		fmt.Println("Error decoding seed value")
-		return
-	}
-	rng := NewRAND()
-	rng.Seed(len(seed), seed)
-
-	const EGS = MPIN_EGS
-	const EFS = MPIN_EFS
-	const G1S = 2*EFS + 1 /* Group 1 Size */
-	const G2S = 4 * EFS   /* Group 2 Size */
-	const EAS = MPIN_PAS
-
-	var MS1 [EGS]byte
-	var SS1 [G2S]byte
-	var CS1 [G1S]byte
-	var TP1 [G1S]byte
-	var MS2 [EGS]byte
-	var SS2 [G2S]byte
-	var CS2 [G1S]byte
-	var TP2 [G1S]byte
-	var SS [G2S]byte
-	var TP [G1S]byte
-	var TOKEN [G1S]byte
-	var SEC [G1S]byte
-	var U [G1S]byte
-	var UT [G1S]byte
-	var X [EGS]byte
-	var Y [EGS]byte
-	var E [12 * EFS]byte
-	var F [12 * EFS]byte
-	var HID [G1S]byte
-	var HTID [G1S]byte
-
-	// Generate Master Secret Share 1
-	MPIN_RANDOM_GENERATE(rng, MS1[:])
-
-	// Generate Master Secret Share 2
-	MPIN_RANDOM_GENERATE(rng, MS2[:])
-
-	// Either Client or TA calculates Hash(ID)
-	HCID := MPIN_HASH_ID(ID)
-
-	// Generate server secret share 1
-	MPIN_GET_SERVER_SECRET(MS1[:], SS1[:])
-
-	// Generate server secret share 2
-	MPIN_GET_SERVER_SECRET(MS2[:], SS2[:])
-
-	// Combine server secret shares
-	MPIN_RECOMBINE_G2(SS1[:], SS2[:], SS[:])
-
-	// Generate client secret share 1
-	MPIN_GET_CLIENT_SECRET(MS1[:], HCID, CS1[:])
-
-	// Generate client secret share 2
-	MPIN_GET_CLIENT_SECRET(MS2[:], HCID, CS2[:])
-
-	// Combine client secret shares : TOKEN is the full client secret
-	MPIN_RECOMBINE_G1(CS1[:], CS2[:], TOKEN[:])
-
-	// Generate time permit share 1
-	MPIN_GET_CLIENT_PERMIT(date, MS1[:], HCID, TP1[:])
-
-	// Generate time permit share 2
-	MPIN_GET_CLIENT_PERMIT(date, MS2[:], HCID, TP2[:])
-
-	// Combine time permit shares
-	MPIN_RECOMBINE_G1(TP1[:], TP2[:], TP[:])
-
-	// Create token
-	MPIN_EXTRACT_PIN(ID, PIN1, TOKEN[:])
-
-	// Authenticate
-	MPIN_CLIENT(date, ID, rng, X[:], PIN2, TOKEN[:], SEC[:], U[:], UT[:], TP[:], MESSAGE, timeValue, Y[:])
-
-	got := MPIN_SERVER(date, HID[:], HTID[:], Y[:], SS[:], U[:], UT[:], SEC[:], E[:], F[:], ID, MESSAGE, timeValue)
-	if got != want {
-		t.Errorf("TestGoodSignature %d != %d", want, got)
-	}
-}
-
-func TestSignatureExpired(t *testing.T) {
-	want := -19
-	// Assign the End-User an ID
-	IDstr := "testUser@miracl.com"
-	ID := []byte(IDstr)
-
-	// Epoch time in days
-	date := 16660
-
-	// Epoch time in seconds
-	timeValue := 1439465203
-
-	// PIN variable to create token
-	PIN1 := 1234
-	// PIN variable to authenticate
-	PIN2 := 1234
-
-	// Seed value for Random Number Generator (RNG)
-	seedHex := "9e8b4178790cd57a5761c4a6f164ba72"
-	seed, err := hex.DecodeString(seedHex)
-	if err != nil {
-		fmt.Println("Error decoding seed value")
-		return
-	}
-	rng := NewRAND()
-	rng.Seed(len(seed), seed)
-
-	// Message to sign
-	MESSAGE := []byte("test message to sign")
-
-	const EGS = MPIN_EGS
-	const EFS = MPIN_EFS
-	const G1S = 2*EFS + 1 /* Group 1 Size */
-	const G2S = 4 * EFS   /* Group 2 Size */
-	const EAS = MPIN_PAS
-
-	var MS1 [EGS]byte
-	var SS1 [G2S]byte
-	var CS1 [G1S]byte
-	var TP1 [G1S]byte
-	var MS2 [EGS]byte
-	var SS2 [G2S]byte
-	var CS2 [G1S]byte
-	var TP2 [G1S]byte
-	var SS [G2S]byte
-	var TP [G1S]byte
-	var TOKEN [G1S]byte
-	var SEC [G1S]byte
-	var U [G1S]byte
-	var UT [G1S]byte
-	var X [EGS]byte
-	var Y [EGS]byte
-	var E [12 * EFS]byte
-	var F [12 * EFS]byte
-	var HID [G1S]byte
-	var HTID [G1S]byte
-
-	// Generate Master Secret Share 1
-	MPIN_RANDOM_GENERATE(rng, MS1[:])
-
-	// Generate Master Secret Share 2
-	MPIN_RANDOM_GENERATE(rng, MS2[:])
-
-	// Either Client or TA calculates Hash(ID)
-	HCID := MPIN_HASH_ID(ID)
-
-	// Generate server secret share 1
-	MPIN_GET_SERVER_SECRET(MS1[:], SS1[:])
-
-	// Generate server secret share 2
-	MPIN_GET_SERVER_SECRET(MS2[:], SS2[:])
-
-	// Combine server secret shares
-	MPIN_RECOMBINE_G2(SS1[:], SS2[:], SS[:])
-
-	// Generate client secret share 1
-	MPIN_GET_CLIENT_SECRET(MS1[:], HCID, CS1[:])
-
-	// Generate client secret share 2
-	MPIN_GET_CLIENT_SECRET(MS2[:], HCID, CS2[:])
-
-	// Combine client secret shares : TOKEN is the full client secret
-	MPIN_RECOMBINE_G1(CS1[:], CS2[:], TOKEN[:])
-
-	// Generate time permit share 1
-	MPIN_GET_CLIENT_PERMIT(date, MS1[:], HCID, TP1[:])
-
-	// Generate time permit share 2
-	MPIN_GET_CLIENT_PERMIT(date, MS2[:], HCID, TP2[:])
-
-	// Combine time permit shares
-	MPIN_RECOMBINE_G1(TP1[:], TP2[:], TP[:])
-
-	// Create token
-	MPIN_EXTRACT_PIN(ID, PIN1, TOKEN[:])
-
-	// Authenticate
-	MPIN_CLIENT(date, ID, rng, X[:], PIN2, TOKEN[:], SEC[:], U[:], UT[:], TP[:], MESSAGE, timeValue, Y[:])
-
-	timeValue += 10
-	got := MPIN_SERVER(date, HID[:], HTID[:], Y[:], SS[:], U[:], UT[:], SEC[:], E[:], F[:], ID, MESSAGE, timeValue)
-	if got != want {
-		t.Errorf("TestSignatureExpired %d != %d", want, got)
-	}
-}
-
-func TestBadSignature(t *testing.T) {
-	want := -19
-	// Assign the End-User an ID
-	IDstr := "testUser@miracl.com"
-	ID := []byte(IDstr)
-
-	// Epoch time in days
-	date := 16660
-
-	// Epoch time in seconds
-	timeValue := 1439465203
-
-	// PIN variable to create token
-	PIN1 := 1234
-	// PIN variable to authenticate
-	PIN2 := 1234
-
-	// Seed value for Random Number Generator (RNG)
-	seedHex := "9e8b4178790cd57a5761c4a6f164ba72"
-	seed, err := hex.DecodeString(seedHex)
-	if err != nil {
-		fmt.Println("Error decoding seed value")
-		return
-	}
-	rng := NewRAND()
-	rng.Seed(len(seed), seed)
-
-	// Message to sign
-	MESSAGE := []byte("test message to sign")
-
-	const EGS = MPIN_EGS
-	const EFS = MPIN_EFS
-	const G1S = 2*EFS + 1 /* Group 1 Size */
-	const G2S = 4 * EFS   /* Group 2 Size */
-	const EAS = MPIN_PAS
-
-	var MS1 [EGS]byte
-	var SS1 [G2S]byte
-	var CS1 [G1S]byte
-	var TP1 [G1S]byte
-	var MS2 [EGS]byte
-	var SS2 [G2S]byte
-	var CS2 [G1S]byte
-	var TP2 [G1S]byte
-	var SS [G2S]byte
-	var TP [G1S]byte
-	var TOKEN [G1S]byte
-	var SEC [G1S]byte
-	var U [G1S]byte
-	var UT [G1S]byte
-	var X [EGS]byte
-	var Y [EGS]byte
-	var E [12 * EFS]byte
-	var F [12 * EFS]byte
-	var HID [G1S]byte
-	var HTID [G1S]byte
-
-	// Generate Master Secret Share 1
-	MPIN_RANDOM_GENERATE(rng, MS1[:])
-
-	// Generate Master Secret Share 2
-	MPIN_RANDOM_GENERATE(rng, MS2[:])
-
-	// Either Client or TA calculates Hash(ID)
-	HCID := MPIN_HASH_ID(ID)
-
-	// Generate server secret share 1
-	MPIN_GET_SERVER_SECRET(MS1[:], SS1[:])
-
-	// Generate server secret share 2
-	MPIN_GET_SERVER_SECRET(MS2[:], SS2[:])
-
-	// Combine server secret shares
-	MPIN_RECOMBINE_G2(SS1[:], SS2[:], SS[:])
-
-	// Generate client secret share 1
-	MPIN_GET_CLIENT_SECRET(MS1[:], HCID, CS1[:])
-
-	// Generate client secret share 2
-	MPIN_GET_CLIENT_SECRET(MS2[:], HCID, CS2[:])
-
-	// Combine client secret shares : TOKEN is the full client secret
-	MPIN_RECOMBINE_G1(CS1[:], CS2[:], TOKEN[:])
-
-	// Generate time permit share 1
-	MPIN_GET_CLIENT_PERMIT(date, MS1[:], HCID, TP1[:])
-
-	// Generate time permit share 2
-	MPIN_GET_CLIENT_PERMIT(date, MS2[:], HCID, TP2[:])
-
-	// Combine time permit shares
-	MPIN_RECOMBINE_G1(TP1[:], TP2[:], TP[:])
-
-	// Create token
-	MPIN_EXTRACT_PIN(ID, PIN1, TOKEN[:])
-
-	// Authenticate
-	MPIN_CLIENT(date, ID, rng, X[:], PIN2, TOKEN[:], SEC[:], U[:], UT[:], TP[:], MESSAGE, timeValue, Y[:])
-
-	MESSAGE[0] = 00
-	got := MPIN_SERVER(date, HID[:], HTID[:], Y[:], SS[:], U[:], UT[:], SEC[:], E[:], F[:], ID, MESSAGE, timeValue)
-	if got != want {
-		t.Errorf("TestBadSignature %d != %d", want, got)
-	}
-}
-
-func TestMPINFull(t *testing.T) {
-	want := "0afc948b03b2733a0663571f86411a07"
-	// Assign the End-User an ID
-	IDstr := "testUser@miracl.com"
-	ID := []byte(IDstr)
-
-	// Epoch time in days
-	date := 16660
-
-	// Epoch time in seconds
-	timeValue := 1439465203
-
-	// PIN variable to create token
-	PIN1 := 1234
-	// PIN variable to authenticate
-	PIN2 := 1234
-
-	// Seed value for Random Number Generator (RNG)
-	seedHex := "9e8b4178790cd57a5761c4a6f164ba72"
-	seed, err := hex.DecodeString(seedHex)
-	if err != nil {
-		fmt.Println("Error decoding seed value")
-		return
-	}
-	rng := NewRAND()
-	rng.Seed(len(seed), seed)
-
-	// Message to sign
-	var MESSAGE []byte
-	// MESSAGE := []byte("test sign message")
-
-	const EGS = MPIN_EGS
-	const EFS = MPIN_EFS
-	const G1S = 2*EFS + 1 /* Group 1 Size */
-	const G2S = 4 * EFS   /* Group 2 Size */
-	const EAS = MPIN_PAS
-
-	var MS1 [EGS]byte
-	var SS1 [G2S]byte
-	var CS1 [G1S]byte
-	var TP1 [G1S]byte
-	var MS2 [EGS]byte
-	var SS2 [G2S]byte
-	var CS2 [G1S]byte
-	var TP2 [G1S]byte
-	var SS [G2S]byte
-	var TP [G1S]byte
-	var TOKEN [G1S]byte
-	var SEC [G1S]byte
-	var U [G1S]byte
-	var UT [G1S]byte
-	var X [EGS]byte
-	var Y [EGS]byte
-	var E [12 * EFS]byte
-	var F [12 * EFS]byte
-	var HID [G1S]byte
-	var HTID [G1S]byte
-
-	var G1 [12 * EFS]byte
-	var G2 [12 * EFS]byte
-	var R [EGS]byte
-	var Z [G1S]byte
-	var W [EGS]byte
-	var T [G1S]byte
-	var AES_KEY_CLIENT [EAS]byte
-	var AES_KEY_SERVER [EAS]byte
-
-	// Generate Master Secret Share 1
-	MPIN_RANDOM_GENERATE(rng, MS1[:])
-
-	// Generate Master Secret Share 2
-	MPIN_RANDOM_GENERATE(rng, MS2[:])
-
-	// Either Client or TA calculates Hash(ID)
-	HCID := MPIN_HASH_ID(ID)
-
-	// Generate server secret share 1
-	MPIN_GET_SERVER_SECRET(MS1[:], SS1[:])
-
-	// Generate server secret share 2
-	MPIN_GET_SERVER_SECRET(MS2[:], SS2[:])
-
-	// Combine server secret shares
-	MPIN_RECOMBINE_G2(SS1[:], SS2[:], SS[:])
-
-	// Generate client secret share 1
-	MPIN_GET_CLIENT_SECRET(MS1[:], HCID, CS1[:])
-
-	// Generate client secret share 2
-	MPIN_GET_CLIENT_SECRET(MS2[:], HCID, CS2[:])
-
-	// Combine client secret shares : TOKEN is the full client secret
-	MPIN_RECOMBINE_G1(CS1[:], CS2[:], TOKEN[:])
-
-	// Generate time permit share 1
-	MPIN_GET_CLIENT_PERMIT(date, MS1[:], HCID, TP1[:])
-
-	// Generate time permit share 2
-	MPIN_GET_CLIENT_PERMIT(date, MS2[:], HCID, TP2[:])
-
-	// Combine time permit shares
-	MPIN_RECOMBINE_G1(TP1[:], TP2[:], TP[:])
-
-	// Create token
-	MPIN_EXTRACT_PIN(ID, PIN1, TOKEN[:])
-
-	// precomputation
-	MPIN_PRECOMPUTE(TOKEN[:], HCID, G1[:], G2[:])
-
-	// Authenticate
-	MPIN_CLIENT(date, ID, rng, X[:], PIN2, TOKEN[:], SEC[:], U[:], UT[:], TP[:], MESSAGE, timeValue, Y[:])
-
-	// Send Z=r.ID to Server
-	MPIN_GET_G1_MULTIPLE(rng, 1, R[:], HCID, Z[:])
-
-	MPIN_SERVER(date, HID[:], HTID[:], Y[:], SS[:], U[:], UT[:], SEC[:], E[:], F[:], ID, MESSAGE, timeValue)
-
-	// send T=w.ID to client
-	MPIN_GET_G1_MULTIPLE(rng, 0, W[:], HTID[:], T[:])
-
-	MPIN_SERVER_KEY(Z[:], SS[:], W[:], U[:], UT[:], AES_KEY_SERVER[:])
-	got := hex.EncodeToString(AES_KEY_SERVER[:])
-	if got != want {
-		t.Errorf("TestMPINFull %s != %s", want, got)
-	}
-
-	MPIN_CLIENT_KEY(G1[:], G2[:], PIN2, R[:], X[:], T[:], AES_KEY_CLIENT[:])
-	got = hex.EncodeToString(AES_KEY_CLIENT[:])
-	if got != want {
-		t.Errorf("TestMPINFull %s != %s", want, got)
-	}
-}
diff --git a/go/amcl-go/PAIR.go b/go/amcl-go/PAIR.go
deleted file mode 100644
index 8a7de9f..0000000
--- a/go/amcl-go/PAIR.go
+++ /dev/null
@@ -1,541 +0,0 @@
-/*
-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.
-*/
-
-/* AMCL BN Curve Pairing functions */
-
-package amcl
-
-//import "fmt"
-
-/* Line function */
-func line(A *ECP2, B *ECP2, Qx *FP, Qy *FP) *FP12 {
-	P := NewECP2()
-
-	P.copy(A)
-	ZZ := NewFP2copy(P.getz())
-	ZZ.sqr()
-	var D int
-	if A == B {
-		D = A.dbl()
-	} else {
-		D = A.add(B)
-	}
-
-	if D < 0 {
-		return NewFP12int(1)
-	}
-
-	Z3 := NewFP2copy(A.getz())
-
-	var a *FP4
-	var b *FP4
-	c := NewFP4int(0)
-
-	if D == 0 { /* Addition */
-		X := NewFP2copy(B.getx())
-		Y := NewFP2copy(B.gety())
-		T := NewFP2copy(P.getz())
-		T.mul(Y)
-		ZZ.mul(T)
-
-		NY := NewFP2copy(P.gety())
-		NY.neg()
-		ZZ.add(NY)
-		Z3.pmul(Qy)
-		T.mul(P.getx())
-		X.mul(NY)
-		T.add(X)
-		a = NewFP4fp2s(Z3, T)
-		ZZ.neg()
-		ZZ.pmul(Qx)
-		b = NewFP4fp2(ZZ)
-	} else { /* Doubling */
-		X := NewFP2copy(P.getx())
-		Y := NewFP2copy(P.gety())
-		T := NewFP2copy(P.getx())
-		T.sqr()
-		T.imul(3)
-
-		Y.sqr()
-		Y.add(Y)
-		Z3.mul(ZZ)
-		Z3.pmul(Qy)
-
-		X.mul(T)
-		X.sub(Y)
-		a = NewFP4fp2s(Z3, X)
-		T.neg()
-		ZZ.mul(T)
-		ZZ.pmul(Qx)
-		b = NewFP4fp2(ZZ)
-	}
-	return NewFP12fp4s(a, b, c)
-}
-
-/* Optimal R-ate pairing */
-func ate(P *ECP2, Q *ECP) *FP12 {
-	f := NewFP2bigs(NewBIGints(CURVE_Fra), NewBIGints(CURVE_Frb))
-	x := NewBIGints(CURVE_Bnx)
-	n := NewBIGcopy(x)
-	K := NewECP2()
-	var lv *FP12
-	n.pmul(6)
-	n.dec(2)
-	n.norm()
-	P.affine()
-	Q.affine()
-	Qx := NewFPcopy(Q.getx())
-	Qy := NewFPcopy(Q.gety())
-
-	A := NewECP2()
-	r := NewFP12int(1)
-
-	A.copy(P)
-	nb := n.nbits()
-
-	for i := nb - 2; i >= 1; i-- {
-		lv = line(A, A, Qx, Qy)
-		r.smul(lv)
-
-		if n.bit(i) == 1 {
-			lv = line(A, P, Qx, Qy)
-			r.smul(lv)
-		}
-		r.sqr()
-	}
-
-	lv = line(A, A, Qx, Qy)
-	r.smul(lv)
-
-	/* R-ate fixup */
-
-	r.conj()
-
-	K.copy(P)
-	K.frob(f)
-	A.neg()
-	lv = line(A, K, Qx, Qy)
-	r.smul(lv)
-	K.frob(f)
-	K.neg()
-	lv = line(A, K, Qx, Qy)
-	r.smul(lv)
-
-	return r
-}
-
-/* Optimal R-ate double pairing e(P,Q).e(R,S) */
-func ate2(P *ECP2, Q *ECP, R *ECP2, S *ECP) *FP12 {
-	f := NewFP2bigs(NewBIGints(CURVE_Fra), NewBIGints(CURVE_Frb))
-	x := NewBIGints(CURVE_Bnx)
-	n := NewBIGcopy(x)
-	K := NewECP2()
-	var lv *FP12
-	n.pmul(6)
-	n.dec(2)
-	n.norm()
-	P.affine()
-	Q.affine()
-	R.affine()
-	S.affine()
-
-	Qx := NewFPcopy(Q.getx())
-	Qy := NewFPcopy(Q.gety())
-	Sx := NewFPcopy(S.getx())
-	Sy := NewFPcopy(S.gety())
-
-	A := NewECP2()
-	B := NewECP2()
-	r := NewFP12int(1)
-
-	A.copy(P)
-	B.copy(R)
-	nb := n.nbits()
-
-	for i := nb - 2; i >= 1; i-- {
-		lv = line(A, A, Qx, Qy)
-		r.smul(lv)
-		lv = line(B, B, Sx, Sy)
-		r.smul(lv)
-
-		if n.bit(i) == 1 {
-			lv = line(A, P, Qx, Qy)
-			r.smul(lv)
-			lv = line(B, R, Sx, Sy)
-			r.smul(lv)
-		}
-		r.sqr()
-	}
-
-	lv = line(A, A, Qx, Qy)
-	r.smul(lv)
-
-	lv = line(B, B, Sx, Sy)
-	r.smul(lv)
-
-	/* R-ate fixup */
-	r.conj()
-
-	K.copy(P)
-	K.frob(f)
-	A.neg()
-	lv = line(A, K, Qx, Qy)
-	r.smul(lv)
-	K.frob(f)
-	K.neg()
-	lv = line(A, K, Qx, Qy)
-	r.smul(lv)
-
-	K.copy(R)
-	K.frob(f)
-	B.neg()
-	lv = line(B, K, Sx, Sy)
-	r.smul(lv)
-	K.frob(f)
-	K.neg()
-	lv = line(B, K, Sx, Sy)
-	r.smul(lv)
-
-	return r
-}
-
-/* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */
-func fexp(m *FP12) *FP12 {
-	f := NewFP2bigs(NewBIGints(CURVE_Fra), NewBIGints(CURVE_Frb))
-	x := NewBIGints(CURVE_Bnx)
-	r := NewFP12copy(m)
-
-	/* Easy part of final exp */
-	lv := NewFP12copy(r)
-	lv.inverse()
-	r.conj()
-
-	r.mul(lv)
-	lv.copy(r)
-	r.frob(f)
-	r.frob(f)
-	r.mul(lv)
-	/* Hard part of final exp */
-	lv.copy(r)
-	lv.frob(f)
-	x0 := NewFP12copy(lv)
-	x0.frob(f)
-	lv.mul(r)
-	x0.mul(lv)
-	x0.frob(f)
-	x1 := NewFP12copy(r)
-	x1.conj()
-	x4 := r.pow(x)
-
-	x3 := NewFP12copy(x4)
-	x3.frob(f)
-
-	x2 := x4.pow(x)
-
-	x5 := NewFP12copy(x2)
-	x5.conj()
-	lv = x2.pow(x)
-
-	x2.frob(f)
-	r.copy(x2)
-	r.conj()
-
-	x4.mul(r)
-	x2.frob(f)
-
-	r.copy(lv)
-	r.frob(f)
-	lv.mul(r)
-
-	lv.usqr()
-	lv.mul(x4)
-	lv.mul(x5)
-	r.copy(x3)
-	r.mul(x5)
-	r.mul(lv)
-	lv.mul(x2)
-	r.usqr()
-	r.mul(lv)
-	r.usqr()
-	lv.copy(r)
-	lv.mul(x1)
-	r.mul(x0)
-	lv.usqr()
-	r.mul(lv)
-	r.reduce()
-	return r
-}
-
-/* GLV method */
-func glv(e *BIG) []*BIG {
-	t := NewBIGint(0)
-	q := NewBIGints(CURVE_Order)
-	var u []*BIG
-	var v []*BIG
-
-	for i := 0; i < 2; i++ {
-		t.copy(NewBIGints(CURVE_W[i])) // why not just t=new BIG(ROM.CURVE_W[i]);
-		d := mul(t, e)
-		v = append(v, NewBIGcopy(d.div(q)))
-		u = append(u, NewBIGint(0))
-	}
-	u[0].copy(e)
-	for i := 0; i < 2; i++ {
-		for j := 0; j < 2; j++ {
-			t.copy(NewBIGints(CURVE_SB[j][i]))
-			t.copy(modmul(v[j], t, q))
-			u[i].add(q)
-			u[i].sub(t)
-			u[i].mod(q)
-		}
-	}
-	return u
-}
-
-/* Galbraith & Scott Method */
-func gs(e *BIG) []*BIG {
-	t := NewBIGint(0)
-	q := NewBIGints(CURVE_Order)
-	var u []*BIG
-	var v []*BIG
-	for i := 0; i < 4; i++ {
-		t.copy(NewBIGints(CURVE_WB[i]))
-		d := mul(t, e)
-		v = append(v, NewBIGcopy(d.div(q)))
-		u = append(u, NewBIGint(0))
-	}
-	u[0].copy(e)
-	for i := 0; i < 4; i++ {
-		for j := 0; j < 4; j++ {
-			t.copy(NewBIGints(CURVE_BB[j][i]))
-			t.copy(modmul(v[j], t, q))
-			u[i].add(q)
-			u[i].sub(t)
-			u[i].mod(q)
-		}
-	}
-	return u
-}
-
-/* Multiply P by e in group G1 */
-func G1mul(P *ECP, e *BIG) *ECP {
-	var R *ECP
-	if USE_GLV {
-		P.affine()
-		R = NewECP()
-		R.copy(P)
-		Q := NewECP()
-		Q.copy(P)
-		q := NewBIGints(CURVE_Order)
-		cru := NewFPbig(NewBIGints(CURVE_Cru))
-		t := NewBIGint(0)
-		u := glv(e)
-		Q.getx().mul(cru)
-
-		np := u[0].nbits()
-		t.copy(modneg(u[0], q))
-		nn := t.nbits()
-		if nn < np {
-			u[0].copy(t)
-			R.neg()
-		}
-
-		np = u[1].nbits()
-		t.copy(modneg(u[1], q))
-		nn = t.nbits()
-		if nn < np {
-			u[1].copy(t)
-			Q.neg()
-		}
-
-		R = R.mul2(u[0], Q, u[1])
-
-	} else {
-		R = P.mul(e)
-	}
-	return R
-}
-
-/* Multiply P by e in group G2 */
-func G2mul(P *ECP2, e *BIG) *ECP2 {
-	var R *ECP2
-	if USE_GS_G2 {
-		var Q []*ECP2
-		f := NewFP2bigs(NewBIGints(CURVE_Fra), NewBIGints(CURVE_Frb))
-		q := NewBIGints(CURVE_Order)
-		u := gs(e)
-
-		t := NewBIGint(0)
-		P.affine()
-		Q = append(Q, NewECP2())
-		Q[0].copy(P)
-		for i := 1; i < 4; i++ {
-			Q = append(Q, NewECP2())
-			Q[i].copy(Q[i-1])
-			Q[i].frob(f)
-		}
-		for i := 0; i < 4; i++ {
-			np := u[i].nbits()
-			t.copy(modneg(u[i], q))
-			nn := t.nbits()
-			if nn < np {
-				u[i].copy(t)
-				Q[i].neg()
-			}
-		}
-		R = mul4(Q, u)
-
-	} else {
-		R = P.mul(e)
-	}
-	return R
-}
-
-/* f=f^e */
-/* Note that this method requires a lot of RAM! Better to use compressed XTR method, see FP4.java */
-func GTpow(d *FP12, e *BIG) *FP12 {
-	var r *FP12
-	if USE_GS_GT {
-		var g []*FP12
-		f := NewFP2bigs(NewBIGints(CURVE_Fra), NewBIGints(CURVE_Frb))
-		q := NewBIGints(CURVE_Order)
-		t := NewBIGint(0)
-
-		u := gs(e)
-
-		g = append(g, NewFP12copy(d))
-		for i := 1; i < 4; i++ {
-			g = append(g, NewFP12int(0))
-			g[i].copy(g[i-1])
-			g[i].frob(f)
-		}
-		for i := 0; i < 4; i++ {
-			np := u[i].nbits()
-			t.copy(modneg(u[i], q))
-			nn := t.nbits()
-			if nn < np {
-				u[i].copy(t)
-				g[i].conj()
-			}
-		}
-		r = pow4(g, u)
-	} else {
-		r = d.pow(e)
-	}
-	return r
-}
-
-/* test group membership */
-/* with GT-Strong curve, now only check that m!=1, conj(m)*m==1, and m.m^{p^4}=m^{p^2} */
-func GTmember(m *FP12) bool {
-	if m.isunity() {
-		return false
-	}
-	r := NewFP12copy(m)
-	r.conj()
-	r.mul(m)
-	if !r.isunity() {
-		return false
-	}
-
-	f := NewFP2bigs(NewBIGints(CURVE_Fra), NewBIGints(CURVE_Frb))
-
-	r.copy(m)
-	r.frob(f)
-	r.frob(f)
-	w := NewFP12copy(r)
-	w.frob(f)
-	w.frob(f)
-	w.mul(m)
-	if !GT_STRONG {
-		if !w.equals(r) {
-			return false
-		}
-		x := NewBIGints(CURVE_Bnx)
-		r.copy(m)
-		w = r.pow(x)
-		w = w.pow(x)
-		r.copy(w)
-		r.sqr()
-		r.mul(w)
-		r.sqr()
-		w.copy(m)
-		w.frob(f)
-	}
-	return w.equals(r)
-}
-
-/*
-func main() {
-
-	Q:=NewECPbigs(NewBIGints(CURVE_Gx),NewBIGints(CURVE_Gy))
-	P:=NewECP2fp2s(NewFP2bigs(NewBIGints(CURVE_Pxa),NewBIGints(CURVE_Pxb)),NewFP2bigs(NewBIGints(CURVE_Pya),NewBIGints(CURVE_Pyb)))
-
-	r:=NewBIGints(CURVE_Order)
-	xa:=NewBIGints(CURVE_Pxa)
-
-	fmt.Printf("P= "+P.toString())
-	fmt.Printf("\n");
-	fmt.Printf("Q= "+Q.toString());
-	fmt.Printf("\n");
-
-	//m:=NewBIGint(17)
-
-	e:=ate(P,Q)
-	fmt.Printf("\ne= "+e.toString())
-	fmt.Printf("\n")
-
-	e=fexp(e)
-	//	e=GTpow(e,m);
-
-	fmt.Printf("\ne= "+e.toString())
-	fmt.Printf("\n");
-	GLV:=glv(r)
-
-	fmt.Printf("GLV[0]= "+GLV[0].toString())
-	fmt.Printf("\n")
-
-	fmt.Printf("GLV[0]= "+GLV[1].toString())
-	fmt.Printf("\n")
-
-	G:=NewECP(); G.copy(Q)
-	R:=NewECP2(); R.copy(P)
-
-
-	e=ate(R,Q)
-	e=fexp(e)
-
-	e=GTpow(e,xa)
-	fmt.Printf("\ne= "+e.toString());
-	fmt.Printf("\n")
-
-	R=G2mul(R,xa)
-	e=ate(R,G)
-	e=fexp(e)
-
-	fmt.Printf("\ne= "+e.toString())
-	fmt.Printf("\n")
-
-	G=G1mul(G,xa)
-	e=ate(P,G)
-	e=fexp(e)
-	fmt.Printf("\ne= "+e.toString())
-	fmt.Printf("\n")
-}
-*/
diff --git a/go/amcl-go/RAND.go b/go/amcl-go/RAND.go
deleted file mode 100644
index eb92107..0000000
--- a/go/amcl-go/RAND.go
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
-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.
-*/
-
-/*
- *   Cryptographic strong random number generator
- *
- *   Unguessable seed -> SHA -> PRNG internal state -> SHA -> random numbers
- *   Slow - but secure
- *
- *   See ftp://ftp.rsasecurity.com/pub/pdfs/bull-1.pdf for a justification
- */
-
-/* Marsaglia & Zaman Random number generator constants */
-
-package amcl
-
-import (
-	"sync"
-)
-
-//import "fmt"
-
-const rand_NK int = 21
-const rand_NJ int = 6
-const rand_NV int = 8
-
-type RAND struct {
-	sync.Mutex
-	ira      [rand_NK]uint32 /* random number...   */
-	rndptr   int
-	borrow   uint32
-	pool_ptr int
-	pool     [32]byte
-}
-
-/* Terminate and clean up */
-func (R *RAND) Clean() { /* kill internal state */
-	R.pool_ptr = 0
-	R.rndptr = 0
-	for i := 0; i < 32; i++ {
-		R.pool[i] = 0
-	}
-	for i := 0; i < rand_NK; i++ {
-		R.ira[i] = 0
-	}
-	R.borrow = 0
-}
-
-func NewRAND() *RAND {
-	R := new(RAND)
-	R.Clean()
-	return R
-}
-
-func (R *RAND) sbrand() uint32 { /* Marsaglia & Zaman random number generator */
-	R.rndptr++
-	if R.rndptr < rand_NK {
-		return R.ira[R.rndptr]
-	}
-	R.rndptr = 0
-	k := rand_NK - rand_NJ
-	for i := 0; i < rand_NK; i++ { /* calculate next NK values */
-		if k == rand_NK {
-			k = 0
-		}
-		t := R.ira[k]
-		pdiff := t - R.ira[i] - R.borrow
-		if pdiff < t {
-			R.borrow = 0
-		}
-		if pdiff > t {
-			R.borrow = 1
-		}
-		R.ira[i] = pdiff
-		k++
-	}
-
-	return R.ira[0]
-}
-
-func (R *RAND) sirand(seed uint32) {
-	var m uint32 = 1
-	R.borrow = 0
-	R.rndptr = 0
-	R.ira[0] ^= seed
-	for i := 1; i < rand_NK; i++ { /* fill initialisation vector */
-		in := (rand_NV * i) % rand_NK
-		R.ira[in] ^= m /* note XOR */
-		t := m
-		m = seed - m
-		seed = t
-	}
-
-	for i := 0; i < 10000; i++ {
-		R.sbrand()
-	} /* "warm-up" & stir the generator */
-}
-
-func (R *RAND) fill_pool() {
-
-	sh := NewHASH()
-	for i := 0; i < 128; i++ {
-		sh.Process(byte(R.sbrand() & 0xff))
-	}
-	R.pool = sh.Hash()
-	R.pool_ptr = 0
-}
-
-func pack(b [4]byte) uint32 { /* pack 4 bytes into a 32-bit Word */
-	return (((uint32(b[3])) & 0xff) << 24) | ((uint32(b[2]) & 0xff) << 16) | ((uint32(b[1]) & 0xff) << 8) | (uint32(b[0]) & 0xff)
-}
-
-/* Initialize RNG with some real entropy from some external source */
-func (R *RAND) Seed(rawlen int, raw []byte) { /* initialise from at least 128 byte string of raw random entropy */
-	var b [4]byte
-	sh := NewHASH()
-	R.pool_ptr = 0
-
-	for i := 0; i < rand_NK; i++ {
-		R.ira[i] = 0
-	}
-
-	if rawlen > 0 {
-		for i := 0; i < rawlen; i++ {
-			sh.Process(raw[i])
-		}
-		digest := sh.Hash()
-
-		/* initialise PRNG from distilled randomness */
-
-		for i := 0; i < 8; i++ {
-			b[0] = digest[4*i]
-			b[1] = digest[4*i+1]
-			b[2] = digest[4*i+2]
-			b[3] = digest[4*i+3]
-			R.sirand(pack(b))
-		}
-	}
-	R.fill_pool()
-}
-
-/* get random byte */
-func (R *RAND) GetByte() byte {
-	R.Lock()
-	defer R.Unlock()
-
-	r := R.pool[R.pool_ptr]
-	R.pool_ptr++
-
-	if R.pool_ptr >= 32 {
-		R.fill_pool()
-	}
-	return byte(r & 0xff)
-}
-
-/* test main program */
-/*
-func main() {
-	var raw [100]byte
-	rng:=NewRAND()
-
-	rng.Clean()
-	for i:=0;i<100;i++ {raw[i]=byte(i)}
-
-	rng.Seed(100,raw[:])
-
-	for i:=0;i<1000;i++ {
-		fmt.Printf("%03d ",rng.GetByte())
-	}
-}
-*/
diff --git a/go/amcl-go/ROM.go b/go/amcl-go/ROM.go
deleted file mode 100644
index 0a4ceb9..0000000
--- a/go/amcl-go/ROM.go
+++ /dev/null
@@ -1,353 +0,0 @@
-/*
-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.
-*/
-
-/* Fixed Data in ROM - Field and Curve parameters */
-
-package amcl
-
-const NOT_SPECIAL int = 0
-const PSEUDO_MERSENNE int = 1
-const MONTGOMERY_FRIENDLY int = 2
-const WEIERSTRASS int = 0
-const EDWARDS int = 1
-const MONTGOMERY int = 2
-
-const NLEN int = 5
-const DNLEN int = 2 * NLEN
-const CHUNK int = 64
-const MODBYTES uint = 32
-
-/*** Enter Some Field details here  ***/
-// Curve 25519
-//const MODBITS uint=255
-//const MOD8 uint=5
-// NIST256 or Brainpool
-//const MODBITS uint=256
-//const MOD8 uint=7
-// MF254
-//const MODBITS uint=254
-//const MOD8 uint=7
-// MS255
-//const MODBITS uint= 255
-//const MOD8 uint= 3
-// MF256
-//const MODBITS uint=256
-//const MOD8 uint=7
-// MS256
-//const MODBITS uint= 256
-//const MOD8 uint= 3
-// ANSSI
-//const MODBITS uint= 256
-//const MOD8 uint= 3
-// BN Curve
-const MODBITS uint = 254 /* Number of bits in Modulus */
-const MOD8 uint = 3      /* Modulus mod 8 */
-
-/* Don't Modify from here... */
-const MASK int64 = ((int64(1) << BASEBITS) - 1)
-const BASEBITS uint = 56
-const OMASK int64 = ((int64(-1)) << (MODBITS % BASEBITS))
-const HBITS uint = (BASEBITS / 2)
-const HMASK int64 = ((int64(1) << HBITS) - 1)
-const TBITS uint = MODBITS % BASEBITS // Number of active bits in top word
-const TMASK int64 = (int64(1) << TBITS) - 1
-const FF_BITS int = 2048 /* Finite Field Size in bits - must be 256.2^n */
-const FFLEN int = (FF_BITS / 256)
-const HFLEN int = (FFLEN / 2) /* Useful for half-size RSA private key operations */
-
-const NEXCESS int = (1 << (uint(CHUNK) - BASEBITS - 1))
-const FEXCESS int64 = (int64(1) << (BASEBITS*uint(NLEN) - MODBITS))
-
-// START SPECIFY FIELD DETAILS HERE
-//*********************************************************************************
-// Curve25519 Modulus
-//const MODTYPE int=PSEUDO_MERSENNE
-//var Modulus = [...]int64 {0xFFFFFFFFFFFFED,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0x7FFFFFFF}
-//const MConst int64=0x13
-// NIST-256 Curve
-//const MODTYPE int=NOT_SPECIAL
-//var Modulus = [...]int64 {0xFFFFFFFFFFFFFF,0xFFFFFFFFFF,0x0,0x1000000,0xFFFFFFFF}
-//const MConst int64=0x1
-// MF254 Modulus
-//const MODTYPE int=MONTGOMERY_FRIENDLY
-//var Modulus= [...]int64 {0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0x3F80FFFF}
-//const MConst int64=0x3F810000
-// MS255 Modulus
-//const MODTYPE int= 1
-//var Modulus= [...]int64 {0xFFFFFFFFFFFD03,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0x7FFFFFFF}
-//const MConst int64=0x2FD
-// MF256 Modulus
-//const MODTYPE int= 2
-//var Modulus= [...]int64 {0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFA7FFFF}
-//const MConst int64=0xFFA80000
-// MS256 Modulus
-//const MODTYPE int= 1
-//var Modulus= [...]int64 {0xFFFFFFFFFFFF43,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFF}
-//const MConst int64=0xBD
-// Brainpool
-//const MODTYPE int= NOT_SPECIAL
-//var Modulus= [...]int64 {0x13481D1F6E5377,0xF623D526202820,0x909D838D726E3B,0xA1EEA9BC3E660A,0xA9FB57DB}
-//const MConst int64 =0xA75590CEFD89B9
-// ANSSI
-//const MODTYPE int= 0
-//var Modulus= [...]int64{0xFCF353D86E9C03,0xADBCABC8CA6DE8,0xE8CE42435B3961,0xB3AD58F10126D,0xF1FD178C}
-//const MConst int64=0x97483A164E1155
-// BNCX Curve Modulus
-const MODTYPE int = NOT_SPECIAL
-
-var Modulus = [...]int64{0x6623EF5C1B55B3, 0xD6EE18093EE1BE, 0x647A6366D3243F, 0x8702A0DB0BDDF, 0x24000000}
-
-const MConst int64 = 0x4E205BF9789E85
-
-// BN Curve
-//const MODTYPE int=NOT_SPECIAL
-//var Modulus= [...]int64  {0x13,0x13A7,0x80000000086121,0x40000001BA344D,0x25236482}
-//const MConst int64=0x435E50D79435E5
-// BNT Curve
-//const MODTYPE int=NOT_SPECIAL
-//var Modulus= [...]int64 {0x9DBBFEEEB4A713,0x555614F464BABE,0x3696F8D5F06E8A,0x6517014EFA0BAB,0x240120DB}
-//const MConst int64=0xC5A872D914C4E5
-// BNT2 Curve
-//const MODTYPE int=NOT_SPECIAL
-//var Modulus= [...]int64 {0xB2DC2BB460A48B,0x93E428F0D651E8,0xF3B89D00081CF,0x410F5AADB74E20,0x24000482}
-//const MConst int64=0xFE6A47A6505CDD
-
-// START SPECIFY CURVE DETAILS HERE
-//*********************************************************************************
-
-// Ed25519 Curve
-//const CURVETYPE int=EDWARDS
-//const CURVE_A int = -1
-//var CURVE_B = [...]int64 {0xEB4DCA135978A3,0xA4D4141D8AB75,0x797779E8980070,0x2B6FFE738CC740,0x52036CEE}
-//var CURVE_Order = [...]int64 {0x12631A5CF5D3ED,0xF9DEA2F79CD658,0x14DE,0x0,0x10000000}
-//var CURVE_Gx = [...]int64 {0x562D608F25D51A,0xC7609525A7B2C9,0x31FDD6DC5C692C,0xCD6E53FEC0A4E2,0x216936D3}
-//var CURVE_Gy = [...]int64 {0x66666666666658,0x66666666666666,0x66666666666666,0x66666666666666,0x66666666}
-
-// NIST-256 Curve
-//const CURVETYPE int=WEIERSTRASS
-//const CURVE_A int = -3
-//var CURVE_B = [...]int64 {0xCE3C3E27D2604B,0x6B0CC53B0F63B,0x55769886BC651D,0xAA3A93E7B3EBBD,0x5AC635D8}
-//var CURVE_Order = [...]int64 {0xB9CAC2FC632551,0xFAADA7179E84F3,0xFFFFFFFFFFBCE6,0xFFFFFF,0xFFFFFFFF}
-//var CURVE_Gx =[...]int64 {0xA13945D898C296,0x7D812DEB33A0F4,0xE563A440F27703,0xE12C4247F8BCE6,0x6B17D1F2}
-//var CURVE_Gy =[...]int64 {0xB6406837BF51F5,0x33576B315ECECB,0x4A7C0F9E162BCE,0xFE1A7F9B8EE7EB,0x4FE342E2}
-
-// MF254 Modulus, Weierstrass Curve w-254-mont
-//const CURVETYPE int= 0
-//const CURVE_A int = -3
-//var CURVE_B = [...]int64 {0xFFFFFFFFFFD08D,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0x3F80FFFF}
-//var CURVE_Order=[...]int64 {0xA419C4AF8DF83F,0x8BEA0DA375C06F,0xFFFFFFFFFFEB81,0xFFFFFFFFFFFFFF,0x3F80FFFF}
-//var CURVE_Gx =[...]int64 {0x2,0x0,0x0,0x0,0x0}
-//var CURVE_Gy =[...]int64 {0x65DF37F90D4EBC,0x38E3F8511931AD,0x75BD778AEBDFB7,0x3B2E56014AE15A,0x140E3FD3}
-
-// MF254 Modulus, Edwards Curve ed-254-mont
-//const CURVETYPE int= 1
-//const CURVE_A int= -1
-//var CURVE_B = [...]int64 {0x367B,0x0,0x0,0x0,0x0}
-//var CURVE_Order=[...]int64 {0xF3D3FEC46E98C7,0x306C8BD62FB0EA,0xFFFFFFFFFFEB95,0xFFFFFFFFFFFFFF,0xFE03FFF}
-//var CURVE_Gx =[...]int64 {0x1,0x0,0x0,0x0,0x0}
-//var CURVE_Gy =[...]int64 {0x52D0FDAF2701E5,0x9A840E3212187C,0xD502363F4E3632,0xD6A4C335951D00,0x19F0E690}
-
-// MF254 Modulus, Montgomery Curve
-//const CURVETYPE int=MONTGOMERY
-//const CURVE_A int= -55790
-//var CURVE_B = [...]int64 {0x0,0x0,0x0,0x0,0x0} // not used
-//var CURVE_Order=[...]int64 {0xF3D3FEC46E98C7,0x306C8BD62FB0EA,0xFFFFFFFFFFEB95,0xFFFFFFFFFFFFFF,0xFE03FFF}
-//var CURVE_Gx =[...]int64 {0x3,0x0,0x0,0x0,0x0}
-//var CURVE_Gy =[...]int64 {0x0,0x0,0x0,0x0,0x0} // not used
-
-// MS255 Modulus, Weierstrass Curve
-//const CURVETYPE int= 0
-//const CURVE_A int= -3
-//var CURVE_B = [...]int64 {0xFFFFFFFFFFAB46,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0x7FFFFFFF}
-//var CURVE_Order=[...]int64 {0x8FAC983C594AEB,0x38283AD2B3DFAB,0xFFFFFFFFFF864A,0xFFFFFFFFFFFFFF,0x7FFFFFFF}
-//var CURVE_Gx =[...]int64 {0x1,0x0,0x0,0x0,0x0};
-//var CURVE_Gy =[...]int64 {0x33FF6769CB44BA,0xC78CDDFDA60D17,0xF9B2FF7D177DB6,0xEDBA7833921EBF,0x6F7A6AC0}
-
-// MS255 Modulus, Edwards Curve
-//const CURVETYPE int= 1
-//const CURVE_A int= -1
-//var CURVE_B = [...]int64{0xEA97,0x0,0x0,0x0,0x0}
-//var CURVE_Order=[...]int64{0x49D1ED0436EB75,0xA785EDA6832EAC,0xFFFFFFFFFFDCF1,0xFFFFFFFFFFFFFF,0x1FFFFFFF}
-//var CURVE_Gx =[...]int64{0x4,0x0,0x0,0x0,0x0}
-//var CURVE_Gy =[...]int64{0x2A255BD08736A0,0x4B8AED445A45BA,0xDD8E0C47E55291,0x4A7BB545EC254C,0x26CB7853}
-
-// MS255 Modulus, Montgomery Curve
-//const CURVETYPE int=MONTGOMERY
-//const CURVE_A int=-240222
-//var CURVE_B = [...]int64 {0x0,0x0,0x0,0x0,0x0}
-//var CURVE_Order=[...]int64 {0x49D1ED0436EB75,0xA785EDA6832EAC,0xFFFFFFFFFFDCF1,0xFFFFFFFFFFFFFF,0x1FFFFFFF}
-//var CURVE_Gx =[...]int64 {0x4,0x0,0x0,0x0,0x0}
-//var CURVE_Gy =[...]int64 {0x0,0x0,0x0,0x0,0x0};
-
-// MF256 Modulus, Weierstrass Curve
-//const CURVETYPE int= 0
-//const CURVE_A int= -3
-//var CURVE_B = [...]int64 {0x14E6A,0x0,0x0,0x0,0x0}
-//var CURVE_Order=[...]int64 {0x10C5E1A79857EB,0x7513E6E5074B9D,0xFFFFFFFFFFFC51,0xFFFFFFFFFFFFFF,0xFFA7FFFF}
-//var CURVE_Gx =[...]int64 {0x1,0x0,0x0,0x0,0x0}
-//var CURVE_Gy =[...]int64 {0x7954C2B724D2A,0x47EB8D94DC6610,0x26123DAE289569,0xBE1808CE7BABBA,0x20887C87}
-
-// MF256, Edwards Curve
-//const CURVETYPE int= 1
-//const CURVE_A int= -1
-//var CURVE_B = [...]int64 {0x350A,0x0,0x0,0x0,0x0}
-//var CURVE_Order=[...]int64 {0xD92EDED8EC7BAB,0xBBAFB86733C966,0xFFFFFFFFFFB154,0xFFFFFFFFFFFFFF,0x3FE9FFFF}
-//var CURVE_Gx =[...]int64 {0x1,0x0,0x0,0x0,0x0}
-//var CURVE_Gy =[...]int64 {0xEAA722F2F3C908,0x5E648DFEA68D7D,0xF3DB2C1AACA0C0,0xF8CC4D5AEAEBEE,0xDAD8D4F8}
-
-// MF256 Modulus, Montgomery Curve
-//const CURVETYPE int=MONTGOMERY
-//const CURVE_A int= -54314
-//var CURVE_B = [...]int64 {0x0,0x0,0x0,0x0,0x0} // not used
-//var CURVE_Order=[...]int64 {0xD92EDED8EC7BAB,0xBBAFB86733C966,0xFFFFFFFFFFB154,0xFFFFFFFFFFFFFF,0x3FE9FFFF}
-//var CURVE_Gx =[...]int64 {0x8,0x0,0x0,0x0,0x0}
-//var CURVE_Gy =[...]int64 {0x0,0x0,0x0,0x0,0x0} // not used
-
-// MS256, Weierstrass Curve
-//const CURVETYPE int= 0
-//const CURVE_A int= -3
-//var CURVE_B = [...]int64 {0x25581,0x0,0x0,0x0,0x0}
-//var CURVE_Order=[...]int64 {0xAB20294751A825,0x8275EA265C6020,0xFFFFFFFFFFE43C,0xFFFFFFFFFFFFFF,0xFFFFFFFF}
-//var CURVE_Gx =[...]int64 {0x1,0x0,0x0,0x0,0x0}
-//var CURVE_Gy =[...]int64 {0xF46306C2B56C77,0x2F9375894EC10B,0x6CCEEEDD6BD02C,0xC1E466D7FC82C9,0x696F1853}
-
-// MS256, Edwards Curve
-//const CURVETYPE int= 1
-//const CURVE_A int= -1
-//var CURVE_B = [...]int64 {0x3BEE,0x0,0x0,0x0,0x0}
-//var CURVE_Order=[...]int64 {0xB84E6F1122B4AD,0xA55AD0A6BC64E5,0xFFFFFFFFFFBE6A,0xFFFFFFFFFFFFFF,0x3FFFFFFF}
-//var CURVE_Gx =[...]int64 {0xD,0x0,0x0,0x0,0x0}
-//var CURVE_Gy =[...]int64 {0x7F6FB5331CADBA,0x6D63824D303F70,0xB39FA046BFBE2A,0x2A1276DBA3D330,0x7D0AB41E}
-
-// MS256 Modulus, Montgomery Curve
-//const CURVETYPE int=MONTGOMERY
-//const CURVE_A int=-61370
-//var CURVE_B = [...]int64  {0x0,0x0,0x0,0x0,0x0} // not used
-//var CURVE_Order= [...]int64 {0xB84E6F1122B4AD,0xA55AD0A6BC64E5,0xFFFFFFFFFFBE6A,0xFFFFFFFFFFFFFF,0x3FFFFFFF}
-//var CURVE_Gx = [...]int64 {0xb,0x0,0x0,0x0,0x0}
-//var CURVE_Gy = [...]int64 {0x0,0x0,0x0,0x0,0x0} // not used
-
-// Brainpool
-//const CURVETYPE int= 0
-//const CURVE_A int= -3
-//var CURVE_B = [...]int64  {0xE58101FEE92B04,0xEBC4AF2F49256A,0x733D0B76B7BF93,0x30D84EA4FE66A7,0x662C61C4}
-//var CURVE_Order= [...]int64 {0x1E0E82974856A7,0x7AA3B561A6F790,0x909D838D718C39,0xA1EEA9BC3E660A,0xA9FB57DB}
-//var CURVE_Gx = [...]int64 {0xA191562E1305F4,0x42C47AAFBC2B79,0xB23A656149AFA1,0xC1CFE7B7732213,0xA3E8EB3C}
-//var CURVE_Gy = [...]int64 {0xABE8F35B25C9BE,0xB6DE39D027001D,0xE14644417E69BC,0x3439C56D7F7B22,0x2D996C82}
-
-// ANSSI
-//const CURVETYPE int= 0
-//const CURVE_A int= -3
-//var CURVE_B = [...]int64  {0x75ED967B7BB73F,0xC9AE4B1A18030,0x754A44C00FDFEC,0x5428A9300D4ABA,0xEE353FCA}
-//var CURVE_Order=[...]int64  {0xFDD459C6D655E1,0x67E140D2BF941F,0xE8CE42435B53DC,0xB3AD58F10126D,0xF1FD178C}
-//var CURVE_Gx =[...]int64  {0xC97A2DD98F5CFF,0xD2DCAF98B70164,0x4749D423958C27,0x56C139EB31183D,0xB6B3D4C3}
-//var CURVE_Gy =[...]int64  {0x115A1554062CFB,0xC307E8E4C9E183,0xF0F3ECEF8C2701,0xC8B204911F9271,0x6142E0F7}
-
-// BNCX Curve
-
-const CURVETYPE int = WEIERSTRASS
-const CURVE_A int = 0
-
-var CURVE_B = [...]int64{0x2, 0x0, 0x0, 0x0, 0x0}
-var CURVE_Order = [...]int64{0x11C0A636EB1F6D, 0xD6EE0CC906CEBE, 0x647A6366D2C43F, 0x8702A0DB0BDDF, 0x24000000}
-var CURVE_Bnx = [...]int64{0x3C012B1, 0x40, 0x0, 0x0, 0x0}
-var CURVE_Cru = [...]int64{0xE0931794235C97, 0xDF6471EF875631, 0xCA83F1440BD, 0x480000, 0x0}
-var CURVE_Fra = [...]int64{0xD9083355C80EA3, 0x7326F173F8215B, 0x8AACA718986867, 0xA63A0164AFE18B, 0x1359082F}
-var CURVE_Frb = [...]int64{0x8D1BBC06534710, 0x63C7269546C062, 0xD9CDBC4E3ABBD8, 0x623628A900DC53, 0x10A6F7D0}
-var CURVE_Pxa = [...]int64{0x851CEEE4D2EC74, 0x85BFA03E2726C0, 0xF5C34BBB907C, 0x7053B256358B25, 0x19682D2C}
-var CURVE_Pxb = [...]int64{0xA58E8B2E29CFE1, 0x97B0C209C30F47, 0x37A8E99743F81B, 0x3E19F64AA011C9, 0x1466B9EC}
-var CURVE_Pya = [...]int64{0xFBFCEBCF0BE09F, 0xB33D847EC1B30C, 0x157DAEE2096361, 0x72332B8DD81E22, 0xA79EDD9}
-var CURVE_Pyb = [...]int64{0x904B228898EE9D, 0x4EA569D2EDEBED, 0x512D8D3461C286, 0xECC4C09035C6E4, 0x6160C39}
-var CURVE_Gx = [...]int64{0x6623EF5C1B55B2, 0xD6EE18093EE1BE, 0x647A6366D3243F, 0x8702A0DB0BDDF, 0x24000000}
-var CURVE_Gy = [...]int64{0x1, 0x0, 0x0, 0x0, 0x0}
-var CURVE_W = [2][5]int64{{0x546349162FEB83, 0xB40381200, 0x6000, 0x0, 0x0}, {0x7802561, 0x80, 0x0, 0x0, 0x0}}
-var CURVE_SB = [2][2][5]int64{{{0x5463491DB010E4, 0xB40381280, 0x6000, 0x0, 0x0}, {0x7802561, 0x80, 0x0, 0x0, 0x0}}, {{0x7802561, 0x80, 0x0, 0x0, 0x0}, {0xBD5D5D20BB33EA, 0xD6EE0188CEBCBD, 0x647A6366D2643F, 0x8702A0DB0BDDF, 0x24000000}}}
-var CURVE_WB = [4][5]int64{{0x1C2118567A84B0, 0x3C012B040, 0x2000, 0x0, 0x0}, {0xCDF995BE220475, 0x94EDA8CA7F9A36, 0x8702A0DC07E, 0x300000, 0x0}, {0x66FCCAE0F10B93, 0x4A76D4653FCD3B, 0x4381506E03F, 0x180000, 0x0}, {0x1C21185DFAAA11, 0x3C012B0C0, 0x2000, 0x0, 0x0}}
-var CURVE_BB = [4][4][5]int64{{{0x11C0A6332B0CBD, 0xD6EE0CC906CE7E, 0x647A6366D2C43F, 0x8702A0DB0BDDF, 0x24000000}, {0x11C0A6332B0CBC, 0xD6EE0CC906CE7E, 0x647A6366D2C43F, 0x8702A0DB0BDDF, 0x24000000}, {0x11C0A6332B0CBC, 0xD6EE0CC906CE7E, 0x647A6366D2C43F, 0x8702A0DB0BDDF, 0x24000000}, {0x7802562, 0x80, 0x0, 0x0, 0x0}}, {{0x7802561, 0x80, 0x0, 0x0, 0x0}, {0x11C0A6332B0CBC, 0xD6EE0CC906CE7E, 0x647A6366D2C43F, 0x8702A0DB0BDDF, 0x24000000}, {0x11C0A6332B0CBD, 0xD6EE0CC906CE7E, 0x647A6366D2C43F, 0x8702A0DB0BDDF, 0x24000000}, {0x11C0A6332B0CBC, 0xD6EE0CC906CE7E, 0x647A6366D2C43F, 0x8702A0DB0BDDF, 0x24000000}}, {{0x7802562, 0x80, 0x0, 0x0, 0x0}, {0x7802561, 0x80, 0x0, 0x0, 0x0}, {0x7802561, 0x80, 0x0, 0x0, 0x0}, {0x7802561, 0x80, 0x0, 0x0, 0x0}}, {{0x3C012B2, 0x40, 0x0, 0x0, 0x0}, {0xF004AC2, 0x100, 0x0, 0x0, 0x0}, {0x11C0A62F6AFA0A, 0xD6EE0CC906CE3E, 0x647A6366D2C43F, 0x8702A0DB0BDDF, 0x24000000}, {0x3C012B2, 0x40, 0x0, 0x0, 0x0}}}
-
-// BN Curve
-/*
-const CURVETYPE int=WEIERSTRASS
-const CURVE_A int= 0
-var CURVE_B = [...]int64 {0x2,0x0,0x0,0x0,0x0}
-var CURVE_Order=[...]int64 {0xD,0x800000000010A1,0x8000000007FF9F,0x40000001BA344D,0x25236482}
-var CURVE_Bnx=[...]int64 {0x80000000000001,0x40,0x0,0x0,0x0}
-var CURVE_Cru=[...]int64 {0x80000000000007,0x6CD,0x40000000024909,0x49B362,0x0}
-var CURVE_Fra=[...]int64 {0x7DE6C06F2A6DE9,0x74924D3F77C2E1,0x50A846953F8509,0x212E7C8CB6499B,0x1B377619}
-var CURVE_Frb=[...]int64 {0x82193F90D5922A,0x8B6DB2C08850C5,0x2F57B96AC8DC17,0x1ED1837503EAB2,0x9EBEE69}
-var CURVE_Pxa=[...]int64 {0xAB2C7935FD0CB4,0xE319E4FCC57C2B,0x24F6DF763B05A5,0xF55EA7EA335FB7,0x95B04D4}
-var CURVE_Pxb=[...]int64 {0xA07D0790962455,0x86BE3D27AA5E38,0x89E05747F39D6D,0xC08347B49D42BF,0x5D4D8A7}
-var CURVE_Pya=[...]int64 {0xADCE687A08A46C,0x2B30E98A4191F9,0x4C3784B1F16908,0x25E5313FA16D1C,0xABF2ABF}
-var CURVE_Pyb=[...]int64 {0xDF88D405F306EC,0x82076ADD13A0E6,0x1E47819D6A5C04,0xE679DABDB38627,0x18769A87}
-var CURVE_Gx =[...]int64 {0x12,0x13A7,0x80000000086121,0x40000001BA344D,0x25236482}
-var CURVE_Gy =[...]int64 {0x1,0x0,0x0,0x0,0x0}
-var CURVE_W=[2][5]int64{{0x3,0x80000000000204,0x6181,0x0,0x0},{0x1,0x81,0x0,0x0,0x0}}
-var CURVE_SB=[2][2][5]int64 {{{0x4,0x80000000000285,0x6181,0x0,0x0},{0x1,0x81,0x0,0x0,0x0}},{{0x1,0x81,0x0,0x0,0x0},{0xA,0xE9D,0x80000000079E1E,0x40000001BA344D,0x25236482}}}
-var CURVE_WB=[4][5]int64 {{0x80000000000000,0x80000000000040,0x2080,0x0,0x0},{0x80000000000005,0x54A,0x8000000001C707,0x312241,0x0},{0x80000000000003,0x800000000002C5,0xC000000000E383,0x189120,0x0},{0x80000000000001,0x800000000000C1,0x2080,0x0,0x0}}
-var CURVE_BB=[4][4][5]int64 {{{0x8000000000000D,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482},{0x8000000000000C,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482},{0x8000000000000C,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482},{0x2,0x81,0x0,0x0,0x0}},{{0x1,0x81,0x0,0x0,0x0},{0x8000000000000C,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482},{0x8000000000000D,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482},{0x8000000000000C,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482}},{{0x2,0x81,0x0,0x0,0x0},{0x1,0x81,0x0,0x0,0x0},{0x1,0x81,0x0,0x0,0x0},{0x1,0x81,0x0,0x0,0x0}},{{0x80000000000002,0x40,0x0,0x0,0x0},{0x2,0x102,0x0,0x0,0x0},{0xA,0x80000000001020,0x8000000007FF9F,0x40000001BA344D,0x25236482},{0x80000000000002,0x40,0x0,0x0,0x0}}}
-*/
-
-// BNT Curve
-/*
-const CURVETYPE int=WEIERSTRASS
-const CURVE_A int= 0
-var CURVE_B = [...]int64 {0x2,0x0,0x0,0x0,0x0}
-var CURVE_Order=[...]int64 {0x75777E8D30210D,0xD43492B2CB363A,0x3696F8D5F00E88,0x6517014EFA0BAB,0x240120DB}
-var CURVE_Bnx=[...]int64 {0x806000004081,0x40,0x0,0x0,0x0}
-var CURVE_Cru=[...]int64 {0xEB53D5AB4FCD87,0x82A5F2BAB11FAD,0x47651504C9764C,0x4801B1,0x0}
-var CURVE_Fra=[...]int64 {0xF5D14EADC80022,0x4904D6FACCE359,0xF190A13211BE6C,0xC9BBC4394F6509,0x1328A292}
-var CURVE_Frb=[...]int64 {0xA7EAB040ECA6F1,0xC513DF997D764,0x450657A3DEB01E,0x9B5B3D15AAA6A1,0x10D87E48}
-var CURVE_Pxa=[...]int64 {0x8987E2288E65BB,0xAD1CAA6313BE,0x325041548B7CCC,0x4C1339EBCC055,0x14483FCD}
-var CURVE_Pxb=[...]int64 {0x67888808DBE2C0,0x7FE1F81E34853A,0xA631A51B57B95,0x384EC302DA3FC5,0x87F46B3}
-var CURVE_Pya=[...]int64 {0x202C47E020CA1D,0xB4167E8399F36C,0xC6E5439F72C94C,0x102B0BD74A2C69,0x14E8C29C}
-var CURVE_Pyb=[...]int64 {0xD8437C716628F2,0x27E167BCB7DC6B,0xA82C7572681D0A,0x62454BD1EDEC18,0x17AFE2A4}
-var CURVE_Gx =[...]int64 {0x9DBBFEEEB4A712,0x555614F464BABE,0x3696F8D5F06E8A,0x6517014EFA0BAB,0x240120DB}
-var CURVE_Gy =[...]int64 {0x1,0x0,0x0,0x0,0x0}
-var CURVE_W=[2][5]int64{{0x26430061838403,0x81218241998384,0x6001,0x0,0x0},{0x100C000008101,0x80,0x0,0x0,0x0}}
-var CURVE_SB=[2][2][5]int64 {{{0x2743C061840504,0x81218241998404,0x6001,0x0,0x0},{0x100C000008101,0x80,0x0,0x0,0x0}},{{0x100C000008101,0x80,0x0,0x0,0x0},{0x4F347E2BAC9D0A,0x5313107131B2B6,0x3696F8D5EFAE87,0x6517014EFA0BAB,0x240120DB}}}
-var CURVE_WB=[4][5]int64 {{0x6140602080C080,0x806080C08880C1,0x2000,0x0,0x0},{0xB53904088C4A85,0xAD2FA352DC6C36,0xDA436358868EDE,0x300120,0x0},{0x5ADCB204464583,0x5697D1A96E363B,0x6D21B1AC43476F,0x180090,0x0},{0x62412020814181,0x806080C0888141,0x2000,0x0,0x0}}
-var CURVE_BB=[4][4][5]int64 {{{0x74F71E8D2FE08D,0xD43492B2CB35FA,0x3696F8D5F00E88,0x6517014EFA0BAB,0x240120DB},{0x74F71E8D2FE08C,0xD43492B2CB35FA,0x3696F8D5F00E88,0x6517014EFA0BAB,0x240120DB},{0x74F71E8D2FE08C,0xD43492B2CB35FA,0x3696F8D5F00E88,0x6517014EFA0BAB,0x240120DB},{0x100C000008102,0x80,0x0,0x0,0x0}},{{0x100C000008101,0x80,0x0,0x0,0x0},{0x74F71E8D2FE08C,0xD43492B2CB35FA,0x3696F8D5F00E88,0x6517014EFA0BAB,0x240120DB},{0x74F71E8D2FE08D,0xD43492B2CB35FA,0x3696F8D5F00E88,0x6517014EFA0BAB,0x240120DB},{0x74F71E8D2FE08C,0xD43492B2CB35FA,0x3696F8D5F00E88,0x6517014EFA0BAB,0x240120DB}},{{0x100C000008102,0x80,0x0,0x0,0x0},{0x100C000008101,0x80,0x0,0x0,0x0},{0x100C000008101,0x80,0x0,0x0,0x0},{0x100C000008101,0x80,0x0,0x0,0x0}},{{0x806000004082,0x40,0x0,0x0,0x0},{0x2018000010202,0x100,0x0,0x0,0x0},{0x7476BE8D2FA00A,0xD43492B2CB35BA,0x3696F8D5F00E88,0x6517014EFA0BAB,0x240120DB},{0x806000004082,0x40,0x0,0x0,0x0}}}
-*/
-
-// BNT2 Curve
-/*
-const CURVETYPE int=WEIERSTRASS
-const CURVE_A int= 0
-var CURVE_B = [...]int64 {0x2,0x0,0x0,0x0,0x0}
-var CURVE_Order=[...]int64 {0xFB71A511AA2BF5,0x8DE127B73833D7,0xF3B89D00021CF,0x410F5AADB74E20,0x24000482}
-var CURVE_Bnx=[...]int64 {0x20100608205,0x40,0x0,0x0,0x0}
-var CURVE_Cru=[...]int64 {0x5027444866BD33,0x5B773016470EFB,0xC3617BECF23675,0x480006,0x0}
-var CURVE_Fra=[...]int64 {0xB268C973AEF062,0xC69B33C3BCE492,0xF67FA37F195BBC,0x29E8CAB6BD0A41,0x124E0B8D}
-var CURVE_Frb=[...]int64 {0x736240B1B429,0xCD48F52D196D56,0x18BBE650E72612,0x17268FF6FA43DE,0x11B1F8F5}
-var CURVE_Pxa=[...]int64 {0xCC92399F40A3C8,0xCDA4E96611784A,0x7B056961706B35,0x9693C6318279D7,0x16FC17CF}
-var CURVE_Pxb=[...]int64 {0x557A8AD8549540,0x6F7BE6F6510610,0x565907A95D17DB,0xBD5975909C8188,0x1EB5B500}
-var CURVE_Pya=[...]int64 {0x7BECC514220513,0x4A78860E737B14,0x51B83935F12684,0x761422AA9D4DFA,0x1E8EE498}
-var CURVE_Pyb=[...]int64 {0xB9328F577CE78E,0xB746E26FA5781F,0xA93DBC1FB8E27E,0xBAE33BDBA29D76,0x23CEF4CD}
-var CURVE_Gx =[...]int64 {0xB2DC2BB460A48A,0x93E428F0D651E8,0xF3B89D00081CF,0x410F5AADB74E20,0x24000482}
-var CURVE_Gy =[...]int64 {0x1,0x0,0x0,0x0,0x0}
-var CURVE_W=[2][5]int64 {{0xB76282A1347083,0x60301399E1D10,0x6000,0x0,0x0},{0x40200C10409,0x80,0x0,0x0,0x0}}
-var CURVE_SB=[2][2][5]int64 {{{0xB76684A1F5748C,0x60301399E1D90,0x6000,0x0,0x0},{0x40200C10409,0x80,0x0,0x0,0x0}},{{0x40200C10409,0x80,0x0,0x0,0x0},{0x440F227075BB72,0x87DE267D9A16C7,0xF3B89CFFFC1CF,0x410F5AADB74E20,0x24000482}}}
-var CURVE_WB=[4][5]int64 {{0x9272D48A70A224,0x20100688A0945,0x2000,0x0,0x0},{0x5A572CF030EF19,0x9651763543721D,0x8240FD48A1B9A3,0x300004,0x0},{0xAD2C96F848B88F,0xCB28BB1AA1B92E,0x41207EA450DCD1,0x180002,0x0},{0x9276D68B31A62D,0x20100688A09C5,0x2000,0x0,0x0}}
-var CURVE_BB=[4][4][5]int64 {{{0xFB6FA41149A9F1,0x8DE127B7383397,0xF3B89D00021CF,0x410F5AADB74E20,0x24000482},{0xFB6FA41149A9F0,0x8DE127B7383397,0xF3B89D00021CF,0x410F5AADB74E20,0x24000482},{0xFB6FA41149A9F0,0x8DE127B7383397,0xF3B89D00021CF,0x410F5AADB74E20,0x24000482},{0x40200C1040A,0x80,0x0,0x0,0x0}},{{0x40200C10409,0x80,0x0,0x0,0x0},{0xFB6FA41149A9F0,0x8DE127B7383397,0xF3B89D00021CF,0x410F5AADB74E20,0x24000482},{0xFB6FA41149A9F1,0x8DE127B7383397,0xF3B89D00021CF,0x410F5AADB74E20,0x24000482},{0xFB6FA41149A9F0,0x8DE127B7383397,0xF3B89D00021CF,0x410F5AADB74E20,0x24000482}},{{0x40200C1040A,0x80,0x0,0x0,0x0},{0x40200C10409,0x80,0x0,0x0,0x0},{0x40200C10409,0x80,0x0,0x0,0x0},{0x40200C10409,0x80,0x0,0x0,0x0}},{{0x20100608206,0x40,0x0,0x0,0x0},{0x80401820812,0x100,0x0,0x0,0x0},{0xFB6DA310E927EA,0x8DE127B7383357,0xF3B89D00021CF,0x410F5AADB74E20,0x24000482},{0x20100608206,0x40,0x0,0x0,0x0}}}
-*/
-
-const USE_GLV bool = true
-const USE_GS_G2 bool = true
-const USE_GS_GT bool = true
-const GT_STRONG bool = true
diff --git a/go/amcl-go/RSA.go b/go/amcl-go/RSA.go
deleted file mode 100644
index 5b1cf5b..0000000
--- a/go/amcl-go/RSA.go
+++ /dev/null
@@ -1,373 +0,0 @@
-/*
-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.
-*/
-
-/* RSA API high-level functions  */
-
-package amcl
-
-import "fmt"
-
-const RSA_RFS int = int(MODBYTES) * FFLEN
-
-type rsa_private_key struct {
-	p, q, dp, dq, c *FF
-}
-
-func New_rsa_private_key(n int) *rsa_private_key {
-	SK := new(rsa_private_key)
-	SK.p = NewFFint(n)
-	SK.q = NewFFint(n)
-	SK.dp = NewFFint(n)
-	SK.dq = NewFFint(n)
-	SK.c = NewFFint(n)
-	return SK
-}
-
-type rsa_public_key struct {
-	e int
-	n *FF
-}
-
-func New_rsa_public_key(m int) *rsa_public_key {
-	PK := new(rsa_public_key)
-	PK.e = 0
-	PK.n = NewFFint(m)
-	return PK
-}
-
-func RSA_KEY_PAIR(rng *RAND, e int, PRIV *rsa_private_key, PUB *rsa_public_key) { /* IEEE1363 A16.11/A16.12 more or less */
-	n := PUB.n.getlen() / 2
-	t := NewFFint(n)
-	p1 := NewFFint(n)
-	q1 := NewFFint(n)
-
-	for true {
-		PRIV.p.random(rng)
-		for PRIV.p.lastbits(2) != 3 {
-			PRIV.p.inc(1)
-		}
-		for !prime(PRIV.p, rng) {
-			PRIV.p.inc(4)
-		}
-
-		p1.copy(PRIV.p)
-		p1.dec(1)
-
-		if p1.cfactor(e) {
-			continue
-		}
-		break
-	}
-
-	for true {
-		PRIV.q.random(rng)
-		for PRIV.q.lastbits(2) != 3 {
-			PRIV.q.inc(1)
-		}
-		for !prime(PRIV.q, rng) {
-			PRIV.q.inc(4)
-		}
-
-		q1.copy(PRIV.q)
-		q1.dec(1)
-
-		if q1.cfactor(e) {
-			continue
-		}
-
-		break
-	}
-
-	PUB.n = ff_mul(PRIV.p, PRIV.q)
-	PUB.e = e
-
-	t.copy(p1)
-	t.shr()
-	PRIV.dp.set(e)
-	PRIV.dp.invmodp(t)
-	if PRIV.dp.parity() == 0 {
-		PRIV.dp.add(t)
-	}
-	PRIV.dp.norm()
-
-	t.copy(q1)
-	t.shr()
-	PRIV.dq.set(e)
-	PRIV.dq.invmodp(t)
-	if PRIV.dq.parity() == 0 {
-		PRIV.dq.add(t)
-	}
-	PRIV.dq.norm()
-
-	PRIV.c.copy(PRIV.p)
-	PRIV.c.invmodp(PRIV.q)
-
-}
-
-/* Mask Generation Function */
-
-func RSA_MGF1(Z []byte, olen int, K []byte) {
-	H := NewHASH()
-	hlen := 32
-
-	var k int = 0
-	for i := 0; i < len(K); i++ {
-		K[i] = 0
-	}
-
-	cthreshold := olen / hlen
-	if olen%hlen != 0 {
-		cthreshold++
-	}
-	for counter := 0; counter < cthreshold; counter++ {
-		H.Process_array(Z)
-		H.Process_num(int32(counter))
-		B := H.Hash()
-
-		if k+hlen > olen {
-			for i := 0; i < olen%hlen; i++ {
-				K[k] = B[i]
-				k++
-			}
-		} else {
-			for i := 0; i < hlen; i++ {
-				K[k] = B[i]
-				k++
-			}
-		}
-	}
-}
-
-func RSA_printBinary(array []byte) {
-	for i := 0; i < len(array); i++ {
-		fmt.Printf("%02x", array[i])
-	}
-	fmt.Printf("\n")
-}
-
-/* OAEP Message Encoding for Encryption */
-func RSA_OAEP_ENCODE(m []byte, rng *RAND, p []byte) []byte {
-	olen := RSA_RFS - 1
-	mlen := len(m)
-	var f [RSA_RFS]byte
-
-	H := NewHASH()
-	hlen := 32
-	var SEED [32]byte
-	seedlen := hlen
-	if mlen > olen-hlen-seedlen-1 {
-		return nil
-	}
-
-	var DBMASK [RSA_RFS - 1 - 32]byte
-
-	if p != nil {
-		H.Process_array(p)
-	}
-	h := H.Hash()
-	for i := 0; i < hlen; i++ {
-		f[i] = h[i]
-	}
-
-	slen := olen - mlen - hlen - seedlen - 1
-
-	for i := 0; i < slen; i++ {
-		f[hlen+i] = 0
-	}
-	f[hlen+slen] = 1
-	for i := 0; i < mlen; i++ {
-		f[hlen+slen+1+i] = m[i]
-	}
-
-	for i := 0; i < seedlen; i++ {
-		SEED[i] = rng.GetByte()
-	}
-	RSA_MGF1(SEED[:], olen-seedlen, DBMASK[:])
-
-	for i := 0; i < olen-seedlen; i++ {
-		DBMASK[i] ^= f[i]
-	}
-	RSA_MGF1(DBMASK[:], seedlen, f[:])
-
-	for i := 0; i < seedlen; i++ {
-		f[i] ^= SEED[i]
-	}
-
-	for i := 0; i < olen-seedlen; i++ {
-		f[i+seedlen] = DBMASK[i]
-	}
-
-	/* pad to length RFS */
-	d := 1
-	for i := RSA_RFS - 1; i >= d; i-- {
-		f[i] = f[i-d]
-	}
-	for i := d - 1; i >= 0; i-- {
-		f[i] = 0
-	}
-	return f[:]
-}
-
-/* OAEP Message Decoding for Decryption */
-func RSA_OAEP_DECODE(p []byte, f []byte) []byte {
-	olen := RSA_RFS - 1
-
-	H := NewHASH()
-	hlen := 32
-	var SEED [32]byte
-	seedlen := hlen
-	var CHASH [32]byte
-
-	if olen < seedlen+hlen+1 {
-		return nil
-	}
-	var DBMASK [RSA_RFS - 1 - 32]byte
-	for i := 0; i < olen-seedlen; i++ {
-		DBMASK[i] = 0
-	}
-
-	if len(f) < RSA_RFS {
-		d := RSA_RFS - len(f)
-		for i := RSA_RFS - 1; i >= d; i-- {
-			f[i] = f[i-d]
-		}
-		for i := d - 1; i >= 0; i-- {
-			f[i] = 0
-		}
-	}
-
-	if p != nil {
-		H.Process_array(p)
-	}
-	h := H.Hash()
-	for i := 0; i < hlen; i++ {
-		CHASH[i] = h[i]
-	}
-
-	x := f[0]
-
-	for i := seedlen; i < olen; i++ {
-		DBMASK[i-seedlen] = f[i+1]
-	}
-
-	RSA_MGF1(DBMASK[:], seedlen, SEED[:])
-	for i := 0; i < seedlen; i++ {
-		SEED[i] ^= f[i+1]
-	}
-	RSA_MGF1(SEED[:], olen-seedlen, f)
-	for i := 0; i < olen-seedlen; i++ {
-		DBMASK[i] ^= f[i]
-	}
-
-	comp := true
-	for i := 0; i < hlen; i++ {
-		if CHASH[i] != DBMASK[i] {
-			comp = false
-		}
-	}
-
-	for i := 0; i < olen-seedlen-hlen; i++ {
-		DBMASK[i] = DBMASK[i+hlen]
-	}
-
-	for i := 0; i < hlen; i++ {
-		SEED[i] = 0
-		CHASH[i] = 0
-	}
-
-	var k int
-	for k = 0; ; k++ {
-		if k >= olen-seedlen-hlen {
-			return nil
-		}
-		if DBMASK[k] != 0 {
-			break
-		}
-	}
-
-	t := DBMASK[k]
-	if !comp || x != 0 || t != 0x01 {
-		for i := 0; i < olen-seedlen; i++ {
-			DBMASK[i] = 0
-		}
-		return nil
-	}
-
-	var r = make([]byte, olen-seedlen-hlen-k-1)
-
-	for i := 0; i < olen-seedlen-hlen-k-1; i++ {
-		r[i] = DBMASK[i+k+1]
-	}
-
-	for i := 0; i < olen-seedlen; i++ {
-		DBMASK[i] = 0
-	}
-
-	return r
-}
-
-/* destroy the Private Key structure */
-func RSA_PRIVATE_KEY_KILL(PRIV *rsa_private_key) {
-	PRIV.p.zero()
-	PRIV.q.zero()
-	PRIV.dp.zero()
-	PRIV.dq.zero()
-	PRIV.c.zero()
-}
-
-/* RSA encryption with the public key */
-func RSA_ENCRYPT(PUB *rsa_public_key, F []byte, G []byte) {
-	n := PUB.n.getlen()
-	f := NewFFint(n)
-
-	ff_fromBytes(f, F)
-	f.power(PUB.e, PUB.n)
-	f.toBytes(G)
-}
-
-/* RSA decryption with the private key */
-func RSA_DECRYPT(PRIV *rsa_private_key, G []byte, F []byte) {
-	n := PRIV.p.getlen()
-	g := NewFFint(2 * n)
-
-	ff_fromBytes(g, G)
-	jp := g.dmod(PRIV.p)
-	jq := g.dmod(PRIV.q)
-
-	jp.skpow(PRIV.dp, PRIV.p)
-	jq.skpow(PRIV.dq, PRIV.q)
-
-	g.zero()
-	g.dscopy(jp)
-	jp.mod(PRIV.q)
-	if ff_comp(jp, jq) > 0 {
-		jq.add(PRIV.q)
-	}
-	jq.sub(jp)
-	jq.norm()
-
-	t := ff_mul(PRIV.c, jq)
-	jq = t.dmod(PRIV.q)
-
-	t = ff_mul(jq, PRIV.p)
-	g.add(t)
-	g.norm()
-
-	g.toBytes(F)
-}
diff --git a/go/amcl-go/UTILS.go b/go/amcl-go/UTILS.go
deleted file mode 100644
index b9b9ecb..0000000
--- a/go/amcl-go/UTILS.go
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
-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.
-*/
-
-package amcl
-
-// Generate random six digit value
-func GENERATE_OTP(rng *RAND) int {
-	OTP := 0
-	mult := 1
-	for i := 0; i < 6; i++ {
-		val := int(rng.GetByte())
-		if val < 0 {
-			val = -val
-		}
-		val = val % 10
-		OTP = val*mult + OTP
-		mult = mult * 10
-	}
-	return OTP
-}
-
-// Generate a random byte array
-func GENERATE_RANDOM(rng *RAND, randomLen int) []byte {
-	random := make([]byte, randomLen)
-	for i := 0; i < randomLen; i++ {
-		random[i] = rng.GetByte()
-	}
-	return random
-}
diff --git a/go/amcl-go/UTILS_test.go b/go/amcl-go/UTILS_test.go
deleted file mode 100644
index 17058cc..0000000
--- a/go/amcl-go/UTILS_test.go
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
-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.
-*/
-
-package amcl
-
-import (
-	"encoding/hex"
-	"fmt"
-	"testing"
-)
-
-func TestGENERATE_OTP(t *testing.T) {
-	cases := []int{751847, 625436, 628111, 611804, 148564, 202193, 794783, 631944, 544480, 384313}
-
-	// Seed value for Random Number Generator (RNG)
-	seedHex := "9e8b4178790cd57a5761c4a6f164ba72"
-	seed, err := hex.DecodeString(seedHex)
-	if err != nil {
-		fmt.Println("Error decoding seed value")
-		return
-	}
-	rng := NewRAND()
-	rng.Seed(len(seed), seed)
-
-	// Generate the one time passwords
-	for _, want := range cases {
-		got := GENERATE_OTP(rng)
-		if got != want {
-			t.Errorf("One Time Passord %d != %d", got, want)
-		}
-	}
-}
-
-func TestGENERATE_RANDOM(t *testing.T) {
-	cases := []string{"57d662d39b1b245da469e89c", "155babf8de4204e68a656f42", "727e1980e01f996d977a0a34", "7b6c39221d89546895153f10", "32e40e9ad6f50dab3f5ec63f", "f6962a1fc5add13277900871", "93ae541acd6dc3264c19a12a", "faf196291d0820c611d3fcd4", "ba0602f0f6df1908dbcffe5b", "9e93cf35ccd5141e367cf2fd"}
-
-	// Seed value for Random Number Generator (RNG)
-	seedHex := "9e8b4178790cd57a5761c4a6f164ba72"
-	seed, err := hex.DecodeString(seedHex)
-	if err != nil {
-		fmt.Println("Error decoding seed value")
-		return
-	}
-	rng := NewRAND()
-	rng.Seed(len(seed), seed)
-
-	// Generate the one time passwords
-	for _, want := range cases {
-		val := GENERATE_RANDOM(rng, 12)
-		got := hex.EncodeToString(val)
-		if got != want {
-			t.Errorf("One Time Passord %s != %s", got, want)
-		}
-	}
-}
diff --git a/go/amcl-go/crypto.go b/go/amcl-go/crypto.go
deleted file mode 100644
index e2b8bbb..0000000
--- a/go/amcl-go/crypto.go
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
-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.
-*/
-
-package amcl
-
-const EAS int = 16
-const EGS int = int(MODBYTES)
-const EFS int = int(MODBYTES)
-const HASH_BYTES int = 32
-const IVS int = 12
-const G1S = 2*EFS + 1
-const G2S = 4 * EFS
-const GTS = 12 * EFS
-
-/* create random secret S. Use GO RNG */
-func MPIN_RANDOM_GENERATE_WRAP(RNG *RAND) (int, []byte) {
-	var S [EGS]byte
-	errorCode := MPIN_RANDOM_GENERATE(RNG, S[:])
-	return errorCode, S[:]
-}
-
-/* Extract Server Secret SS=S*Q where Q is fixed generator in G2 and S is master secret */
-func MPIN_GET_SERVER_SECRET_WRAP(S []byte) (int, []byte) {
-	var SS [G2S]byte
-	errorCode := MPIN_GET_SERVER_SECRET(S[:], SS[:])
-	return errorCode, SS[:]
-}
-
-/* R=R1+R2 in group G1 */
-func MPIN_RECOMBINE_G1_WRAP(R1 []byte, R2 []byte) (int, []byte) {
-	var R [G1S]byte
-	errorCode := MPIN_RECOMBINE_G1(R1[:], R2[:], R[:])
-	return errorCode, R[:]
-}
-
-/* W=W1+W2 in group G2 */
-func MPIN_RECOMBINE_G2_WRAP(W1 []byte, W2 []byte) (int, []byte) {
-	var W [G2S]byte
-	errorCode := MPIN_RECOMBINE_G2(W1[:], W2[:], W[:])
-	return errorCode, W[:]
-}
-
-/* Client secret CS=S*H(ID) where ID is client ID and S is master secret */
-/* CID is hashed externally */
-func MPIN_GET_CLIENT_SECRET_WRAP(S []byte, ID []byte) (int, []byte) {
-	var CS [G1S]byte
-	errorCode := MPIN_GET_CLIENT_SECRET(S[:], ID[:], CS[:])
-	return errorCode, CS[:]
-}
-
-/* Time Permit TP=S*(date|H(ID)) where S is master secret */
-func MPIN_GET_CLIENT_PERMIT_WRAP(date int, S []byte, ID []byte) (int, []byte) {
-	var TP [G1S]byte
-	errorCode := MPIN_GET_CLIENT_PERMIT(date, S[:], ID[:], TP[:])
-	return errorCode, TP[:]
-}
-
-/* Extract PIN from CS for identity CID to form TOKEN */
-func MPIN_EXTRACT_PIN_WRAP(ID []byte, PIN int, CS []byte) (int, []byte) {
-	CSIn := make([]byte, G1S)
-	copy(CSIn, CS)
-	errorCode := MPIN_EXTRACT_PIN(ID[:], PIN, CSIn[:])
-	return errorCode, CSIn[:]
-}
-
-/* One pass MPIN Client. Using GO RNG */
-func MPIN_CLIENT_WRAP(date, TimeValue, PIN int, RNG *RAND, ID, X, TOKEN, TP, MESSAGE []byte) (int, []byte, []byte, []byte, []byte, []byte) {
-	var Y [EGS]byte
-	var SEC [G1S]byte
-	var U [G1S]byte
-	var UT [G1S]byte
-	errorCode := MPIN_CLIENT(date, ID, RNG, X[:], PIN, TOKEN[:], SEC[:], U[:], UT[:], TP[:], MESSAGE, TimeValue, Y[:])
-	return errorCode, X[:], Y[:], SEC[:], U[:], UT[:]
-}
-
-// Precompute values for use by the client side of M-Pin Full
-func MPIN_PRECOMPUTE_WRAP(TOKEN []byte, ID []byte) (int, []byte, []byte) {
-	var GT1 [GTS]byte
-	var GT2 [GTS]byte
-	errorCode := MPIN_PRECOMPUTE(TOKEN[:], ID[:], GT1[:], GT2[:])
-	return errorCode, GT1[:], GT2[:]
-}
-
-/*
- W=x*H(G);
- if RNG == NULL then X is passed in
- if RNG != NULL the X is passed out
- if typ=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve
- Use GO RNG
-*/
-func MPIN_GET_G1_MULTIPLE_WRAP(RNG *RAND, typ int, X, G []byte) (int, []byte, []byte) {
-	var Z [G1S]byte
-	errorCode := MPIN_GET_G1_MULTIPLE(RNG, typ, X[:], G[:], Z[:])
-	return errorCode, X[:], Z[:]
-}
-
-/* One pass MPIN Server */
-func MPIN_SERVER_WRAP(date int, TimeValue int, SS, U, UT, V, ID, MESSAGE []byte) (int, []byte, []byte, []byte, []byte, []byte) {
-	var HID [G1S]byte
-	var HTID [G1S]byte
-	var Y [EGS]byte
-	var E [GTS]byte
-	var F [GTS]byte
-
-	errorCode := MPIN_SERVER(date, HID[:], HTID[:], Y[:], SS[:], U[:], UT[:], V[:], E[:], F[:], ID[:], MESSAGE[:], TimeValue)
-
-	return errorCode, HID[:], HTID[:], Y[:], E[:], F[:]
-}
-
-/* calculate common key on server side */
-/* Z=r.A - no time permits involved */
-func MPIN_SERVER_KEY_WRAP(Z, SS, W, U, UT []byte) (int, []byte) {
-	var SK [EAS]byte
-	errorCode := MPIN_SERVER_KEY(Z[:], SS[:], W[:], U[:], UT[:], SK[:])
-	return errorCode, SK[:]
-}
-
-/* calculate common key on client side */
-/* wCID = w.(A+AT) */
-func MPIN_CLIENT_KEY_WRAP(PIN int, GT1, GT2, R, X, T []byte) (int, []byte) {
-	var CK [EAS]byte
-	errorCode := MPIN_CLIENT_KEY(GT1[:], GT2[:], PIN, R[:], X[:], T[:], CK[:])
-	return errorCode, CK[:]
-}
-
-/* Extract big type PIN.hash(ID) from CS to form TOKEN */
-func MPIN_EXTRACT_BIG_PIN_WRAP(ID, PIN, CS []byte) (int, []byte) {
-	TOKEN := make([]byte, G1S)
-	pin := fromBytes(PIN)
-	P := ECP_fromBytes(CS)
-	if P.is_infinity() {
-		return MPIN_INVALID_POINT, TOKEN[:]
-	}
-	h := Hashit(0, ID)
-	R := mapit(h)
-
-	R = R.mul(pin)
-	P.sub(R)
-
-	P.toBytes(TOKEN)
-
-	return 0, TOKEN[:]
-}
-
-/* Add big type PIN.hash(ID) to TOKEN for identity ID to form CS */
-func MPIN_ADD_BIG_PIN_WRAP(ID, PIN, TOKEN []byte) (int, []byte) {
-	CS := make([]byte, G1S)
-	pin := fromBytes(PIN)
-	P := ECP_fromBytes(TOKEN)
-	if P.is_infinity() {
-		return MPIN_INVALID_POINT, CS[:]
-	}
-	h := Hashit(0, ID)
-	R := mapit(h)
-
-	R = R.mul(pin)
-	P.add(R)
-
-	P.toBytes(CS)
-
-	return 0, CS[:]
-}
-
-/* dst = a ^ b ^ c */
-func XORBytes(a, b, c []byte) ([]byte, int) {
-	n := len(a)
-	dst := make([]byte, n)
-	if (len(b) != n) || (len(c) != n) {
-		return dst[:], 1
-	}
-	for i := 0; i < n; i++ {
-		dst[i] = a[i] ^ b[i] ^ c[i]
-	}
-	return dst[:], 0
-}
-
-/* Outputs H(CID) and H(T|H(CID)) for time permits. If no time permits set HID=HTID */
-func MPIN_SERVER_1_WRAP(date int, ID []byte) ([]byte, []byte) {
-	var HID [G1S]byte
-	var HTID [G1S]byte
-	MPIN_SERVER_1(date, ID, HID[:], HTID[:])
-	return HID[:], HTID[:]
-}
-
-/* Implement step 2 of MPin protocol on server side */
-func MPIN_SERVER_2_WRAP(date int, HID []byte, HTID []byte, Y []byte, SS []byte, U []byte, UT []byte, V []byte) (int, []byte, []byte) {
-	var E [12 * EFS]byte
-	var F [12 * EFS]byte
-	errorCode := MPIN_SERVER_2(date, HID[:], HTID[:], Y[:], SS[:], U[:], UT[:], V[:], E[:], F[:])
-	return errorCode, E[:], F[:]
-}
-
-/* Implement step 1 on client side of MPin protocol */
-func MPIN_CLIENT_1_WRAP(date int, ID []byte, rng *RAND, X []byte, PIN int, TOKEN []byte, TP []byte) (int, []byte, []byte, []byte, []byte) {
-	var SEC [G1S]byte
-	var U [G1S]byte
-	var UT [G1S]byte
-	errorCode := MPIN_CLIENT_1(date, ID[:], rng, X[:], PIN, TOKEN[:], SEC[:], U[:], UT[:], TP[:])
-	return errorCode, X[:], SEC[:], U[:], UT[:]
-}
-
-/* Implement step 2 on client side of MPin protocol */
-func MPIN_CLIENT_2_WRAP(X []byte, Y []byte, SEC []byte) (int, []byte) {
-	errorCode := MPIN_CLIENT_2(X[:], Y[:], SEC[:])
-	return errorCode, SEC[:]
-}
diff --git a/go/amcl-go/crypto_test.go b/go/amcl-go/crypto_test.go
deleted file mode 100644
index 710204e..0000000
--- a/go/amcl-go/crypto_test.go
+++ /dev/null
@@ -1,1194 +0,0 @@
-/*
-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.
-*/
-
-package amcl
-
-import (
-	"crypto/rand"
-	"encoding/hex"
-	"fmt"
-	mathrand "math/rand"
-	"testing"
-
-	"github.com/stretchr/testify/assert"
-)
-
-const nIter int = 1000
-
-func TestCryptoGoodPIN(t *testing.T) {
-	want := 0
-	// Assign the End-User an ID
-	IDstr := "testUser@miracl.com"
-	ID := []byte(IDstr)
-
-	// Epoch time in days
-	date := 16660
-
-	// Epoch time in seconds
-	timeValue := 1439465203
-
-	// PIN variable to create token
-	PIN1 := 1234
-	// PIN variable to authenticate
-	PIN2 := 1234
-
-	// Seed value for Random Number Generator (RNG)
-	seedHex := "9e8b4178790cd57a5761c4a6f164ba72"
-	seed, err := hex.DecodeString(seedHex)
-	if err != nil {
-		fmt.Println("Error decoding seed value")
-		return
-	}
-	rng := NewRAND()
-	rng.Seed(len(seed), seed)
-
-	// Message to sign
-	var MESSAGE []byte
-
-	// Generate Master Secret Share 1
-	_, MS1 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Generate Master Secret Share 2
-	_, MS2 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Either Client or TA calculates Hash(ID)
-	HCID := MPIN_HASH_ID(ID)
-
-	// Generate server secret share 1
-	_, SS1 := MPIN_GET_SERVER_SECRET_WRAP(MS1[:])
-
-	// Generate server secret share 2
-	_, SS2 := MPIN_GET_SERVER_SECRET_WRAP(MS2[:])
-
-	// Combine server secret shares
-	_, SS := MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:])
-
-	// Generate client secret share 1
-	_, CS1 := MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID)
-
-	// Generate client secret share 2
-	_, CS2 := MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID)
-
-	// Combine client secret shares
-	CS := make([]byte, G1S)
-	_, CS = MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:])
-
-	// Generate time permit share 1
-	_, TP1 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID)
-
-	// Generate time permit share 2
-	_, TP2 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID)
-
-	// Combine time permit shares
-	_, TP := MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:])
-
-	// Create token
-	_, TOKEN := MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:])
-
-	// Send U, UT, V, timeValue and Message to server
-	var X [EGS]byte
-	_, _, _, V, U, UT := MPIN_CLIENT_WRAP(date, timeValue, PIN2, rng, ID[:], X[:], TOKEN[:], TP[:], MESSAGE[:])
-
-	got, _, _, _, _, _ := MPIN_SERVER_WRAP(date, timeValue, SS[:], U[:], UT[:], V[:], ID[:], MESSAGE[:])
-	assert.Equal(t, want, got, "Should be equal")
-}
-
-func TestCryptoBadPIN(t *testing.T) {
-	want := -19
-	// Assign the End-User an ID
-	IDstr := "testUser@miracl.com"
-	ID := []byte(IDstr)
-
-	// Epoch time in days
-	date := 16660
-
-	// Epoch time in seconds
-	timeValue := 1439465203
-
-	// PIN variable to create token
-	PIN1 := 1234
-	// PIN variable to authenticate
-	PIN2 := 1235
-
-	// Seed value for Random Number Generator (RNG)
-	seedHex := "9e8b4178790cd57a5761c4a6f164ba72"
-	seed, err := hex.DecodeString(seedHex)
-	if err != nil {
-		fmt.Println("Error decoding seed value")
-		return
-	}
-	rng := NewRAND()
-	rng.Seed(len(seed), seed)
-
-	// Message to sign
-	var MESSAGE []byte
-
-	// Generate Master Secret Share 1
-	_, MS1 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Generate Master Secret Share 2
-	_, MS2 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Either Client or TA calculates Hash(ID)
-	HCID := MPIN_HASH_ID(ID)
-
-	// Generate server secret share 1
-	_, SS1 := MPIN_GET_SERVER_SECRET_WRAP(MS1[:])
-
-	// Generate server secret share 2
-	_, SS2 := MPIN_GET_SERVER_SECRET_WRAP(MS2[:])
-
-	// Combine server secret shares
-	_, SS := MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:])
-
-	// Generate client secret share 1
-	_, CS1 := MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID)
-
-	// Generate client secret share 2
-	_, CS2 := MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID)
-
-	// Combine client secret shares
-	CS := make([]byte, G1S)
-	_, CS = MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:])
-
-	// Generate time permit share 1
-	_, TP1 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID)
-
-	// Generate time permit share 2
-	_, TP2 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID)
-
-	// Combine time permit shares
-	_, TP := MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:])
-
-	// Create token
-	_, TOKEN := MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:])
-
-	//////   Client   //////
-
-	// Send U, UT, V, timeValue and Message to server
-	var X [EGS]byte
-	_, _, _, V, U, UT := MPIN_CLIENT_WRAP(date, timeValue, PIN2, rng, ID[:], X[:], TOKEN[:], TP[:], MESSAGE[:])
-
-	//////   Server   //////
-	got, _, _, _, _, _ := MPIN_SERVER_WRAP(date, timeValue, SS[:], U[:], UT[:], V[:], ID[:], MESSAGE[:])
-	assert.Equal(t, want, got, "Should be equal")
-}
-
-func TestCryptoBadToken(t *testing.T) {
-	want := -19
-	// Assign the End-User an ID
-	IDstr := "testUser@miracl.com"
-	ID := []byte(IDstr)
-
-	// Epoch time in days
-	date := 16660
-
-	// Epoch time in seconds
-	timeValue := 1439465203
-
-	// PIN variable to create token
-	PIN1 := 1234
-	// PIN variable to authenticate
-	PIN2 := 1234
-
-	// Seed value for Random Number Generator (RNG)
-	seedHex := "9e8b4178790cd57a5761c4a6f164ba72"
-	seed, err := hex.DecodeString(seedHex)
-	if err != nil {
-		fmt.Println("Error decoding seed value")
-		return
-	}
-	rng := NewRAND()
-	rng.Seed(len(seed), seed)
-
-	// Message to sign
-	var MESSAGE []byte
-
-	// Generate Master Secret Share 1
-	_, MS1 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Generate Master Secret Share 2
-	_, MS2 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Either Client or TA calculates Hash(ID)
-	HCID := MPIN_HASH_ID(ID)
-
-	// Generate server secret share 1
-	_, SS1 := MPIN_GET_SERVER_SECRET_WRAP(MS1[:])
-
-	// Generate server secret share 2
-	_, SS2 := MPIN_GET_SERVER_SECRET_WRAP(MS2[:])
-
-	// Combine server secret shares
-	_, SS := MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:])
-
-	// Generate client secret share 1
-	_, CS1 := MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID)
-
-	// Generate client secret share 2
-	_, CS2 := MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID)
-
-	// Combine client secret shares
-	CS := make([]byte, G1S)
-	_, CS = MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:])
-
-	// Generate time permit share 1
-	_, TP1 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID)
-
-	// Generate time permit share 2
-	_, TP2 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID)
-
-	// Combine time permit shares
-	_, TP := MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:])
-
-	// Create token
-	_, TOKEN := MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:])
-
-	// Send U, UT, V, timeValue and Message to server
-	var X [EGS]byte
-	_, _, _, _, U, UT := MPIN_CLIENT_WRAP(date, timeValue, PIN2, rng, ID[:], X[:], TOKEN[:], TP[:], MESSAGE[:])
-
-	// Send UT as V to model bad token
-	got, _, _, _, _, _ := MPIN_SERVER_WRAP(date, timeValue, SS[:], U[:], UT[:], UT[:], ID[:], MESSAGE[:])
-	assert.Equal(t, want, got, "Should be equal")
-}
-
-func TestCryptoRandom(t *testing.T) {
-	want := 0
-
-	for i := 0; i < nIter; i++ {
-
-		// Seed value for Random Number Generator (RNG)
-		seed := make([]byte, 16)
-		rand.Read(seed)
-		rng := NewRAND()
-		rng.Seed(len(seed), seed)
-
-		// Epoch time in days
-		date := MPIN_today()
-
-		// Epoch time in seconds
-		timeValue := MPIN_GET_TIME()
-
-		// PIN variable to create token
-		PIN1 := mathrand.Intn(10000)
-		// PIN variable to authenticate
-		PIN2 := PIN1
-
-		// Assign the End-User a random ID
-		ID := make([]byte, 16)
-		rand.Read(ID)
-
-		// Message to sign
-		var MESSAGE []byte
-
-		// Generate Master Secret Share 1
-		_, MS1 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-		// Generate Master Secret Share 2
-		_, MS2 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-		// Either Client or TA calculates Hash(ID)
-		HCID := MPIN_HASH_ID(ID)
-
-		// Generate server secret share 1
-		_, SS1 := MPIN_GET_SERVER_SECRET_WRAP(MS1[:])
-
-		// Generate server secret share 2
-		_, SS2 := MPIN_GET_SERVER_SECRET_WRAP(MS2[:])
-
-		// Combine server secret shares
-		_, SS := MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:])
-
-		// Generate client secret share 1
-		_, CS1 := MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID)
-
-		// Generate client secret share 2
-		_, CS2 := MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID)
-
-		// Combine client secret shares
-		CS := make([]byte, G1S)
-		_, CS = MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:])
-
-		// Generate time permit share 1
-		_, TP1 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID)
-
-		// Generate time permit share 2
-		_, TP2 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID)
-
-		// Combine time permit shares
-		_, TP := MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:])
-
-		// Create token
-		_, TOKEN := MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:])
-
-		// Send U, UT, V, timeValue and Message to server
-		var X [EGS]byte
-		_, _, _, V, U, UT := MPIN_CLIENT_WRAP(date, timeValue, PIN2, rng, ID[:], X[:], TOKEN[:], TP[:], MESSAGE[:])
-
-		got, _, _, _, _, _ := MPIN_SERVER_WRAP(date, timeValue, SS[:], U[:], UT[:], V[:], ID[:], MESSAGE[:])
-		assert.Equal(t, want, got, "Should be equal")
-	}
-}
-
-func TestCryptoGoodSignature(t *testing.T) {
-	want := 0
-	// Assign the End-User an ID
-	IDstr := "testUser@miracl.com"
-	ID := []byte(IDstr)
-
-	// Message to sign
-	MESSAGE := []byte("test message to sign")
-
-	// Epoch time in days
-	date := 16660
-
-	// Epoch time in seconds
-	timeValue := 1439465203
-
-	// PIN variable to create token
-	PIN1 := 1234
-	// PIN variable to authenticate
-	PIN2 := 1234
-
-	// Seed value for Random Number Generator (RNG)
-	seedHex := "9e8b4178790cd57a5761c4a6f164ba72"
-	seed, err := hex.DecodeString(seedHex)
-	if err != nil {
-		fmt.Println("Error decoding seed value")
-		return
-	}
-	rng := NewRAND()
-	rng.Seed(len(seed), seed)
-
-	// Generate Master Secret Share 1
-	_, MS1 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Generate Master Secret Share 2
-	_, MS2 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Either Client or TA calculates Hash(ID)
-	HCID := MPIN_HASH_ID(ID)
-
-	// Generate server secret share 1
-	_, SS1 := MPIN_GET_SERVER_SECRET_WRAP(MS1[:])
-
-	// Generate server secret share 2
-	_, SS2 := MPIN_GET_SERVER_SECRET_WRAP(MS2[:])
-
-	// Combine server secret shares
-	_, SS := MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:])
-
-	// Generate client secret share 1
-	_, CS1 := MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID)
-
-	// Generate client secret share 2
-	_, CS2 := MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID)
-
-	// Combine client secret shares
-	CS := make([]byte, G1S)
-	_, CS = MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:])
-
-	// Generate time permit share 1
-	_, TP1 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID)
-
-	// Generate time permit share 2
-	_, TP2 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID)
-
-	// Combine time permit shares
-	_, TP := MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:])
-
-	// Create token
-	_, TOKEN := MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:])
-
-	// Send U, UT, V, timeValue and Message to server
-	var X [EGS]byte
-	_, _, _, V, U, UT := MPIN_CLIENT_WRAP(date, timeValue, PIN2, rng, ID[:], X[:], TOKEN[:], TP[:], MESSAGE[:])
-
-	// Authenticate
-	got, _, _, _, _, _ := MPIN_SERVER_WRAP(date, timeValue, SS[:], U[:], UT[:], V[:], ID[:], MESSAGE[:])
-	assert.Equal(t, want, got, "Should be equal")
-}
-
-func TestCryptoSignatureExpired(t *testing.T) {
-	want := -19
-	// Assign the End-User an ID
-	IDstr := "testUser@miracl.com"
-	ID := []byte(IDstr)
-
-	// Message to sign
-	MESSAGE := []byte("test message to sign")
-
-	// Epoch time in days
-	date := 16660
-
-	// Epoch time in seconds
-	timeValue := 1439465203
-
-	// PIN variable to create token
-	PIN1 := 1234
-	// PIN variable to authenticate
-	PIN2 := 1234
-
-	// Seed value for Random Number Generator (RNG)
-	seedHex := "9e8b4178790cd57a5761c4a6f164ba72"
-	seed, err := hex.DecodeString(seedHex)
-	if err != nil {
-		fmt.Println("Error decoding seed value")
-		return
-	}
-	rng := NewRAND()
-	rng.Seed(len(seed), seed)
-
-	// Generate Master Secret Share 1
-	_, MS1 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Generate Master Secret Share 2
-	_, MS2 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Either Client or TA calculates Hash(ID)
-	HCID := MPIN_HASH_ID(ID)
-
-	// Generate server secret share 1
-	_, SS1 := MPIN_GET_SERVER_SECRET_WRAP(MS1[:])
-
-	// Generate server secret share 2
-	_, SS2 := MPIN_GET_SERVER_SECRET_WRAP(MS2[:])
-
-	// Combine server secret shares
-	_, SS := MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:])
-
-	// Generate client secret share 1
-	_, CS1 := MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID)
-
-	// Generate client secret share 2
-	_, CS2 := MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID)
-
-	// Combine client secret shares
-	CS := make([]byte, G1S)
-	_, CS = MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:])
-
-	// Generate time permit share 1
-	_, TP1 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID)
-
-	// Generate time permit share 2
-	_, TP2 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID)
-
-	// Combine time permit shares
-	_, TP := MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:])
-
-	// Create token
-	_, TOKEN := MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:])
-
-	// Send U, UT, V, timeValue and Message to server
-	var X [EGS]byte
-	_, _, _, V, U, UT := MPIN_CLIENT_WRAP(date, timeValue, PIN2, rng, ID[:], X[:], TOKEN[:], TP[:], MESSAGE[:])
-
-	timeValue += 10
-	// Authenticate
-	got, _, _, _, _, _ := MPIN_SERVER_WRAP(date, timeValue, SS[:], U[:], UT[:], V[:], ID[:], MESSAGE[:])
-	assert.Equal(t, want, got, "Should be equal")
-}
-
-func TestCryptoBadSignature(t *testing.T) {
-	want := -19
-	// Assign the End-User an ID
-	IDstr := "testUser@miracl.com"
-	ID := []byte(IDstr)
-
-	// Message to sign
-	MESSAGE := []byte("test message to sign")
-
-	// Epoch time in days
-	date := 16660
-
-	// Epoch time in seconds
-	timeValue := 1439465203
-
-	// PIN variable to create token
-	PIN1 := 1234
-	// PIN variable to authenticate
-	PIN2 := 1234
-
-	// Seed value for Random Number Generator (RNG)
-	seedHex := "9e8b4178790cd57a5761c4a6f164ba72"
-	seed, err := hex.DecodeString(seedHex)
-	if err != nil {
-		fmt.Println("Error decoding seed value")
-		return
-	}
-	rng := NewRAND()
-	rng.Seed(len(seed), seed)
-
-	// Generate Master Secret Share 1
-	_, MS1 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Generate Master Secret Share 2
-	_, MS2 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Either Client or TA calculates Hash(ID)
-	HCID := MPIN_HASH_ID(ID)
-
-	// Generate server secret share 1
-	_, SS1 := MPIN_GET_SERVER_SECRET_WRAP(MS1[:])
-
-	// Generate server secret share 2
-	_, SS2 := MPIN_GET_SERVER_SECRET_WRAP(MS2[:])
-
-	// Combine server secret shares
-	_, SS := MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:])
-
-	// Generate client secret share 1
-	_, CS1 := MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID)
-
-	// Generate client secret share 2
-	_, CS2 := MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID)
-
-	// Combine client secret shares
-	CS := make([]byte, G1S)
-	_, CS = MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:])
-
-	// Generate time permit share 1
-	_, TP1 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID)
-
-	// Generate time permit share 2
-	_, TP2 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID)
-
-	// Combine time permit shares
-	_, TP := MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:])
-
-	// Create token
-	_, TOKEN := MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:])
-
-	// Send U, UT, V, timeValue and Message to server
-	var X [EGS]byte
-	_, _, _, V, U, UT := MPIN_CLIENT_WRAP(date, timeValue, PIN2, rng, ID[:], X[:], TOKEN[:], TP[:], MESSAGE[:])
-
-	// Authenticate
-	MESSAGE[0] = 00
-	got, _, _, _, _, _ := MPIN_SERVER_WRAP(date, timeValue, SS[:], U[:], UT[:], V[:], ID[:], MESSAGE[:])
-	assert.Equal(t, want, got, "Should be equal")
-}
-
-func TestCryptoPINError(t *testing.T) {
-	want := 1
-	// Assign the End-User an ID
-	IDstr := "testUser@miracl.com"
-	ID := []byte(IDstr)
-
-	// Epoch time in days
-	date := 16660
-
-	// Epoch time in seconds
-	timeValue := 1439465203
-
-	// PIN variable to create token
-	PIN1 := 1234
-	// PIN variable to authenticate
-	PIN2 := 1235
-
-	// Seed value for Random Number Generator (RNG)
-	seedHex := "9e8b4178790cd57a5761c4a6f164ba72"
-	seed, err := hex.DecodeString(seedHex)
-	if err != nil {
-		fmt.Println("Error decoding seed value")
-		return
-	}
-	rng := NewRAND()
-	rng.Seed(len(seed), seed)
-
-	// Message to sign
-	var MESSAGE []byte
-
-	// Generate Master Secret Share 1
-	_, MS1 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Generate Master Secret Share 2
-	_, MS2 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Either Client or TA calculates Hash(ID)
-	HCID := MPIN_HASH_ID(ID)
-
-	// Generate server secret share 1
-	_, SS1 := MPIN_GET_SERVER_SECRET_WRAP(MS1[:])
-
-	// Generate server secret share 2
-	_, SS2 := MPIN_GET_SERVER_SECRET_WRAP(MS2[:])
-
-	// Combine server secret shares
-	_, SS := MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:])
-
-	// Generate client secret share 1
-	_, CS1 := MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID)
-
-	// Generate client secret share 2
-	_, CS2 := MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID)
-
-	// Combine client secret shares
-	CS := make([]byte, G1S)
-	_, CS = MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:])
-
-	// Generate time permit share 1
-	_, TP1 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID)
-
-	// Generate time permit share 2
-	_, TP2 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID)
-
-	// Combine time permit shares
-	_, TP := MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:])
-
-	// Create token
-	_, TOKEN := MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:])
-
-	// Send U, UT, V, timeValue and Message to server
-	var X [EGS]byte
-	_, _, _, V, U, UT := MPIN_CLIENT_WRAP(date, timeValue, PIN2, rng, ID[:], X[:], TOKEN[:], TP[:], MESSAGE[:])
-
-	_, _, _, _, E, F := MPIN_SERVER_WRAP(date, timeValue, SS[:], U[:], UT[:], V[:], ID[:], MESSAGE[:])
-
-	got := MPIN_KANGAROO(E[:], F[:])
-	assert.Equal(t, want, got, "Should be equal")
-}
-
-func TestCryptoMPINFull(t *testing.T) {
-	want := "0afc948b03b2733a0663571f86411a07"
-	// Assign the End-User an ID
-	IDstr := "testUser@miracl.com"
-	ID := []byte(IDstr)
-
-	// Epoch time in days
-	date := 16660
-
-	// Epoch time in seconds
-	timeValue := 1439465203
-
-	// PIN variable to create token
-	PIN1 := 1234
-	// PIN variable to authenticate
-	PIN2 := 1234
-
-	// Seed value for Random Number Generator (RNG)
-	seedHex := "9e8b4178790cd57a5761c4a6f164ba72"
-	seed, err := hex.DecodeString(seedHex)
-	if err != nil {
-		fmt.Println("Error decoding seed value")
-		return
-	}
-	rng := NewRAND()
-	rng.Seed(len(seed), seed)
-
-	// Message to sign
-	var MESSAGE []byte
-
-	// Generate Master Secret Share 1
-	_, MS1 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Generate Master Secret Share 2
-	_, MS2 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Either Client or TA calculates Hash(ID)
-	HCID := MPIN_HASH_ID(ID)
-
-	// Generate server secret share 1
-	_, SS1 := MPIN_GET_SERVER_SECRET_WRAP(MS1[:])
-
-	// Generate server secret share 2
-	_, SS2 := MPIN_GET_SERVER_SECRET_WRAP(MS2[:])
-
-	// Combine server secret shares
-	_, SS := MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:])
-
-	// Generate client secret share 1
-	_, CS1 := MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID)
-
-	// Generate client secret share 2
-	_, CS2 := MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID)
-
-	// Combine client secret shares
-	CS := make([]byte, G1S)
-	_, CS = MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:])
-
-	// Generate time permit share 1
-	_, TP1 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID)
-
-	// Generate time permit share 2
-	_, TP2 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID)
-
-	// Combine time permit shares
-	_, TP := MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:])
-
-	// Create token
-	_, TOKEN := MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:])
-
-	// Precomputation
-	_, G1, G2 := MPIN_PRECOMPUTE_WRAP(TOKEN[:], HCID)
-
-	// Send U, UT, V, timeValue and Message to server
-	var X [EGS]byte
-	_, XOut, _, V, U, UT := MPIN_CLIENT_WRAP(date, timeValue, PIN2, rng, ID[:], X[:], TOKEN[:], TP[:], MESSAGE[:])
-
-	// Send Z=r.ID to Server
-	var R [EGS]byte
-	_, ROut, Z := MPIN_GET_G1_MULTIPLE_WRAP(rng, 1, R[:], HCID[:])
-
-	// Authenticate
-	_, _, HTID, _, _, _ := MPIN_SERVER_WRAP(date, timeValue, SS[:], U[:], UT[:], V[:], ID[:], MESSAGE[:])
-
-	// send T=w.ID to client
-	var W [EGS]byte
-	_, WOut, T := MPIN_GET_G1_MULTIPLE_WRAP(rng, 0, W[:], HTID[:])
-
-	_, AES_KEY_SERVER := MPIN_SERVER_KEY_WRAP(Z[:], SS[:], WOut[:], U[:], UT[:])
-	got := hex.EncodeToString(AES_KEY_SERVER[:])
-	if got != want {
-		t.Errorf("%s != %s", want, got)
-	}
-
-	_, AES_KEY_CLIENT := MPIN_CLIENT_KEY_WRAP(PIN2, G1[:], G2[:], ROut[:], XOut[:], T[:])
-	got = hex.EncodeToString(AES_KEY_CLIENT[:])
-	assert.Equal(t, want, got, "Should be equal")
-}
-
-// Subtract a 256 bit PIN
-func TestCrypoSubBigPIN(t *testing.T) {
-	want := "042182235070802ebc33633e70e6628f48fd896e86dfc40c81227caa2792367a581d461dbba6efa30896c71f427df335885142cc6fb64ba082ff9573b9276475c0"
-
-	IDHex := "7465737455736572406365727469766f782e636f6d"
-	ID, err := hex.DecodeString(IDHex)
-	assert.Equal(t, nil, err, "Should be equal")
-
-	TOKENHex := "0422a522b5c05d06cde3a65872656ab596e111c4ea7c0c349bac26f0bdaf7d5f0a1ea8a0cab99d06677cfbc3c8d667e7b0af33b9ed4df007b0ccc8c2b77353bbe6"
-	TOKEN, err := hex.DecodeString(TOKENHex)
-	assert.Equal(t, nil, err, "Should be equal")
-
-	// Seed value for Random Number Generator (RNG)
-	seedHex := "9e8b4178790cd57a5761c4a6f164ba72"
-	seed, err := hex.DecodeString(seedHex)
-	assert.Equal(t, nil, err, "Should be equal")
-	rng := NewRAND()
-	rng.Seed(len(seed), seed)
-
-	// Generate big PIN - 256 bits
-	errorCode, PIN := MPIN_RANDOM_GENERATE_WRAP(rng)
-	assert.Equal(t, 0, errorCode, "Should be equal")
-
-	// Extract big PIN
-	errorCode, TK := MPIN_EXTRACT_BIG_PIN_WRAP(ID[:], PIN[:], TOKEN[:])
-	assert.Equal(t, 0, errorCode, "Should be equal")
-	got := hex.EncodeToString(TK[:])
-	assert.Equal(t, want, got, "Should be equal")
-}
-
-// Add a 256 bit PIN
-func TestCrypoAddBigPIN(t *testing.T) {
-	want := "0422a522b5c05d06cde3a65872656ab596e111c4ea7c0c349bac26f0bdaf7d5f0a1ea8a0cab99d06677cfbc3c8d667e7b0af33b9ed4df007b0ccc8c2b77353bbe6"
-
-	IDHex := "7465737455736572406365727469766f782e636f6d"
-	ID, err := hex.DecodeString(IDHex)
-	assert.Equal(t, nil, err, "Should be equal")
-
-	TOKENHex := "042182235070802ebc33633e70e6628f48fd896e86dfc40c81227caa2792367a581d461dbba6efa30896c71f427df335885142cc6fb64ba082ff9573b9276475c0"
-	TOKEN, err := hex.DecodeString(TOKENHex)
-	assert.Equal(t, nil, err, "Should be equal")
-
-	PINHex := "1b18b8b882daf76a18bf2278fe4e15c62eed8131e708573375fd81a8415014b3"
-	PIN, err := hex.DecodeString(PINHex)
-	assert.Equal(t, nil, err, "Should be equal")
-
-	// Extract big PIN
-	errorCode, TK := MPIN_ADD_BIG_PIN_WRAP(ID[:], PIN[:], TOKEN[:])
-	assert.Equal(t, 0, errorCode, "Should be equal")
-	got := hex.EncodeToString(TK[:])
-	assert.Equal(t, want, got, "Should be equal")
-}
-
-// Split key
-func TestCryptoSplitKey(t *testing.T) {
-	want := "64b36b7a0395e61350de8839adb019d5ae2134052b8533e7c4bbab3965e0af1b"
-
-	// Seed value for Random Number Generator (RNG)
-	seedHex := "9e8b4178790cd57a5761c4a6f164ba72"
-	seed, err := hex.DecodeString(seedHex)
-	assert.Equal(t, nil, err, "Should be equal")
-	rng := NewRAND()
-	rng.Seed(len(seed), seed)
-
-	// Generate big PIN - 256 bits
-	errorCode, PIN := MPIN_RANDOM_GENERATE_WRAP(rng)
-	assert.Equal(t, 0, errorCode, "Should be equal")
-	PINHex := hex.EncodeToString(PIN[:])
-	PINGoldHex := "1b18b8b882daf76a18bf2278fe4e15c62eed8131e708573375fd81a8415014b3"
-	assert.Equal(t, PINGoldHex, PINHex, "Should be equal")
-
-	n := len(PIN)
-	// Split key by C = PIN ^ A ^ B
-	A := GENERATE_RANDOM(rng, n)
-
-	B := GENERATE_RANDOM(rng, n)
-
-	C, errorCode := XORBytes(PIN[:], A[:], B[:])
-	assert.Equal(t, 0, errorCode, "Should be equal")
-	got := hex.EncodeToString(C[:])
-	assert.Equal(t, want, got, "Should be equal")
-}
-
-// Combine key shares
-func TestCryptoCombineKey(t *testing.T) {
-	want := "1b18b8b882daf76a18bf2278fe4e15c62eed8131e708573375fd81a8415014b3"
-
-	CHex := "64b36b7a0395e61350de8839adb019d5ae2134052b8533e7c4bbab3965e0af1b"
-	C, err := hex.DecodeString(CHex)
-	assert.Equal(t, nil, err, "Should be equal")
-
-	AHex := "c5add1327790087193ae541acd6dc3264c19a12afaf196291d0820c611d3fcd4"
-	A, err := hex.DecodeString(AHex)
-	assert.Equal(t, nil, err, "Should be equal")
-
-	BHex := "ba0602f0f6df1908dbcffe5b9e93cf35ccd5141e367cf2fdac4e0a573563477c"
-	B, err := hex.DecodeString(BHex)
-	assert.Equal(t, nil, err, "Should be equal")
-
-	// Combine key shares PIN = A ^ B ^ C
-	PIN, errorCode := XORBytes(C[:], A[:], B[:])
-	assert.Equal(t, 0, errorCode, "Should be equal")
-	got := hex.EncodeToString(PIN[:])
-	assert.Equal(t, want, got, "Should be equal")
-}
-
-func TestCryptoTwoPassGoodPIN(t *testing.T) {
-	want := 0
-	// Assign the End-User an ID
-	IDstr := "testUser@miracl.com"
-	ID := []byte(IDstr)
-
-	// Epoch time in days
-	date := 16660
-
-	// PIN variable to create token
-	PIN1 := 1234
-	// PIN variable to authenticate
-	PIN2 := 1234
-
-	// Seed value for Random Number Generator (RNG)
-	seedHex := "9e8b4178790cd57a5761c4a6f164ba72"
-	seed, err := hex.DecodeString(seedHex)
-	if err != nil {
-		fmt.Println("Error decoding seed value")
-		return
-	}
-	rng := NewRAND()
-	rng.Seed(len(seed), seed)
-
-	// Generate Master Secret Share 1
-	_, MS1 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Generate Master Secret Share 2
-	_, MS2 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Either Client or TA calculates Hash(ID)
-	HCID := MPIN_HASH_ID(ID)
-
-	// Generate server secret share 1
-	_, SS1 := MPIN_GET_SERVER_SECRET_WRAP(MS1[:])
-
-	// Generate server secret share 2
-	_, SS2 := MPIN_GET_SERVER_SECRET_WRAP(MS2[:])
-
-	// Combine server secret shares
-	_, SS := MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:])
-
-	// Generate client secret share 1
-	_, CS1 := MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID)
-
-	// Generate client secret share 2
-	_, CS2 := MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID)
-
-	// Combine client secret shares
-	CS := make([]byte, G1S)
-	_, CS = MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:])
-
-	// Generate time permit share 1
-	_, TP1 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID)
-
-	// Generate time permit share 2
-	_, TP2 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID)
-
-	// Combine time permit shares
-	_, TP := MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:])
-
-	// Create token
-	_, TOKEN := MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:])
-
-	// Client Pass 1
-	var X [EGS]byte
-	_, _, SEC, U, UT := MPIN_CLIENT_1_WRAP(date, ID, rng, X[:], PIN2, TOKEN[:], TP[:])
-
-	// Server Pass 1
-	HID, HTID := MPIN_SERVER_1_WRAP(date, ID)
-	_, Y := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Client Pass 2
-	_, V := MPIN_CLIENT_2_WRAP(X[:], Y[:], SEC[:])
-
-	// Server Pass 2
-	got, _, _ := MPIN_SERVER_2_WRAP(date, HID[:], HTID[:], Y[:], SS[:], U[:], UT[:], V[:])
-	assert.Equal(t, want, got, "Should be equal")
-}
-
-func TestCryptoTwoPassBadPIN(t *testing.T) {
-	want := -19
-	// Assign the End-User an ID
-	IDstr := "testUser@miracl.com"
-	ID := []byte(IDstr)
-
-	// Epoch time in days
-	date := 16660
-
-	// PIN variable to create token
-	PIN1 := 1234
-	// PIN variable to authenticate
-	PIN2 := 1235
-
-	// Seed value for Random Number Generator (RNG)
-	seedHex := "9e8b4178790cd57a5761c4a6f164ba72"
-	seed, err := hex.DecodeString(seedHex)
-	if err != nil {
-		fmt.Println("Error decoding seed value")
-		return
-	}
-	rng := NewRAND()
-	rng.Seed(len(seed), seed)
-
-	// Generate Master Secret Share 1
-	_, MS1 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Generate Master Secret Share 2
-	_, MS2 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Either Client or TA calculates Hash(ID)
-	HCID := MPIN_HASH_ID(ID)
-
-	// Generate server secret share 1
-	_, SS1 := MPIN_GET_SERVER_SECRET_WRAP(MS1[:])
-
-	// Generate server secret share 2
-	_, SS2 := MPIN_GET_SERVER_SECRET_WRAP(MS2[:])
-
-	// Combine server secret shares
-	_, SS := MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:])
-
-	// Generate client secret share 1
-	_, CS1 := MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID)
-
-	// Generate client secret share 2
-	_, CS2 := MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID)
-
-	// Combine client secret shares
-	CS := make([]byte, G1S)
-	_, CS = MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:])
-
-	// Generate time permit share 1
-	_, TP1 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID)
-
-	// Generate time permit share 2
-	_, TP2 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID)
-
-	// Combine time permit shares
-	_, TP := MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:])
-
-	// Create token
-	_, TOKEN := MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:])
-
-	// Client Pass 1
-	var X [EGS]byte
-	_, _, SEC, U, UT := MPIN_CLIENT_1_WRAP(date, ID, rng, X[:], PIN2, TOKEN[:], TP[:])
-
-	// Server Pass 1
-	HID, HTID := MPIN_SERVER_1_WRAP(date, ID)
-	_, Y := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Client Pass 2
-	_, V := MPIN_CLIENT_2_WRAP(X[:], Y[:], SEC[:])
-
-	// Server Pass 2
-	got, _, _ := MPIN_SERVER_2_WRAP(date, HID[:], HTID[:], Y[:], SS[:], U[:], UT[:], V[:])
-	assert.Equal(t, want, got, "Should be equal")
-}
-
-func TestCryptoTwoPassBadToken(t *testing.T) {
-	want := -19
-	// Assign the End-User an ID
-	IDstr := "testUser@miracl.com"
-	ID := []byte(IDstr)
-
-	// Epoch time in days
-	date := 16660
-
-	// PIN variable to create token
-	PIN1 := 1234
-	// PIN variable to authenticate
-	PIN2 := 1234
-
-	// Seed value for Random Number Generator (RNG)
-	seedHex := "9e8b4178790cd57a5761c4a6f164ba72"
-	seed, err := hex.DecodeString(seedHex)
-	if err != nil {
-		fmt.Println("Error decoding seed value")
-		return
-	}
-	rng := NewRAND()
-	rng.Seed(len(seed), seed)
-
-	// Generate Master Secret Share 1
-	_, MS1 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Generate Master Secret Share 2
-	_, MS2 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Either Client or TA calculates Hash(ID)
-	HCID := MPIN_HASH_ID(ID)
-
-	// Generate server secret share 1
-	_, SS1 := MPIN_GET_SERVER_SECRET_WRAP(MS1[:])
-
-	// Generate server secret share 2
-	_, SS2 := MPIN_GET_SERVER_SECRET_WRAP(MS2[:])
-
-	// Combine server secret shares
-	_, SS := MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:])
-
-	// Generate client secret share 1
-	_, CS1 := MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID)
-
-	// Generate client secret share 2
-	_, CS2 := MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID)
-
-	// Combine client secret shares
-	CS := make([]byte, G1S)
-	_, CS = MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:])
-
-	// Generate time permit share 1
-	_, TP1 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID)
-
-	// Generate time permit share 2
-	_, TP2 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID)
-
-	// Combine time permit shares
-	_, TP := MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:])
-
-	// Create token
-	_, TOKEN := MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:])
-
-	// Client Pass 1
-	var X [EGS]byte
-	_, _, SEC, U, UT := MPIN_CLIENT_1_WRAP(date, ID, rng, X[:], PIN2, TOKEN[:], TP[:])
-
-	// Server Pass 1
-	HID, HTID := MPIN_SERVER_1_WRAP(date, ID)
-	_, Y := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-	// Client Pass 2
-	_, _ = MPIN_CLIENT_2_WRAP(X[:], Y[:], SEC[:])
-
-	// Server Pass 2
-	// Send UT as V to model bad token
-	got, _, _ := MPIN_SERVER_2_WRAP(date, HID[:], HTID[:], Y[:], SS[:], U[:], UT[:], UT[:])
-	assert.Equal(t, want, got, "Should be equal")
-}
-
-func TestCryptoRandomTwoPass(t *testing.T) {
-	want := 0
-
-	for i := 0; i < nIter; i++ {
-
-		// Seed value for Random Number Generator (RNG)
-		seed := make([]byte, 16)
-		rand.Read(seed)
-		rng := NewRAND()
-		rng.Seed(len(seed), seed)
-
-		// Epoch time in days
-		date := MPIN_today()
-
-		// PIN variable to create token
-		PIN1 := mathrand.Intn(10000)
-		// PIN variable to authenticate
-		PIN2 := PIN1
-
-		// Assign the End-User a random ID
-		ID := make([]byte, 16)
-		rand.Read(ID)
-
-		// Generate Master Secret Share 1
-		_, MS1 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-		// Generate Master Secret Share 2
-		_, MS2 := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-		// Either Client or TA calculates Hash(ID)
-		HCID := MPIN_HASH_ID(ID)
-
-		// Generate server secret share 1
-		_, SS1 := MPIN_GET_SERVER_SECRET_WRAP(MS1[:])
-
-		// Generate server secret share 2
-		_, SS2 := MPIN_GET_SERVER_SECRET_WRAP(MS2[:])
-
-		// Combine server secret shares
-		_, SS := MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:])
-
-		// Generate client secret share 1
-		_, CS1 := MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID)
-
-		// Generate client secret share 2
-		_, CS2 := MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID)
-
-		// Combine client secret shares
-		CS := make([]byte, G1S)
-		_, CS = MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:])
-
-		// Generate time permit share 1
-		_, TP1 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID)
-
-		// Generate time permit share 2
-		_, TP2 := MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID)
-
-		// Combine time permit shares
-		_, TP := MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:])
-
-		// Create token
-		_, TOKEN := MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:])
-
-		// Client Pass 1
-		var X [EGS]byte
-		_, _, SEC, U, UT := MPIN_CLIENT_1_WRAP(date, ID, rng, X[:], PIN2, TOKEN[:], TP[:])
-
-		// Server Pass 1
-		HID, HTID := MPIN_SERVER_1_WRAP(date, ID)
-		_, Y := MPIN_RANDOM_GENERATE_WRAP(rng)
-
-		// Client Pass 2
-		_, V := MPIN_CLIENT_2_WRAP(X[:], Y[:], SEC[:])
-
-		// Server Pass 2
-		got, _, _ := MPIN_SERVER_2_WRAP(date, HID[:], HTID[:], Y[:], SS[:], U[:], UT[:], V[:])
-		assert.Equal(t, want, got, "Should be equal")
-
-	}
-}
diff --git a/go/examples-cgo/README.txt b/go/examples-cgo/README.txt
deleted file mode 100644
index cc05766..0000000
--- a/go/examples-cgo/README.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-When the library is built with;
-
--D USE_ANONYMOUS=on 
-
-then the only example that works is mpinfullAnon.go
diff --git a/go/examples-cgo/mpin.go b/go/examples-cgo/mpin.go
deleted file mode 100644
index 35b1d03..0000000
--- a/go/examples-cgo/mpin.go
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
-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.
-*/
-
-package main
-
-import (
-	"encoding/hex"
-	"fmt"
-
-	amclcgo "git.apache.org/incubator-milagro-crypto.git/go/amcl-cgo"
-	amclgo "git.apache.org/incubator-milagro-crypto.git/go/amcl-go"
-)
-
-func main() {
-	// Assign the End-User an ID
-	IDstr := "testUser@miracl.com"
-	ID := []byte(IDstr)
-	fmt.Printf("ID: ")
-	amclcgo.MPIN_printBinary(ID)
-	fmt.Printf("\n")
-
-	// Epoch time in days
-	date := amclcgo.MPIN_today()
-
-	// Epoch time in seconds
-	timeValue := amclcgo.MPIN_GET_TIME()
-
-	// PIN variable to create token
-	PIN1 := -1
-	// PIN variable to authenticate
-	PIN2 := -1
-
-	// Seed value for Random Number Generator (RNG)
-	seedHex := "9e8b4178790cd57a5761c4a6f164ba72"
-	seed, err := hex.DecodeString(seedHex)
-	if err != nil {
-		fmt.Println("Error decoding seed value")
-		return
-	}
-	rng := amclgo.NewRAND()
-	rng.Seed(len(seed), seed)
-
-	// Message to sign
-	var MESSAGE []byte
-	// MESSAGE := []byte("test sign message")
-
-	// Generate Master Secret Share 1
-	rtn, MS1 := amclcgo.MPIN_RANDOM_GENERATE_WRAP(rng)
-	if rtn != 0 {
-		fmt.Println("MPIN_RANDOM_GENERATE Error:", rtn)
-		return
-	}
-	fmt.Printf("MS1: 0x")
-	amclcgo.MPIN_printBinary(MS1[:])
-
-	// Generate Master Secret Share 2
-	rtn, MS2 := amclcgo.MPIN_RANDOM_GENERATE_WRAP(rng)
-	if rtn != 0 {
-		fmt.Println("MPIN_RANDOM_GENERATE Error:", rtn)
-		return
-	}
-	fmt.Printf("MS2: 0x")
-	amclcgo.MPIN_printBinary(MS2[:])
-
-	// Either Client or TA calculates Hash(ID)
-	HCID := amclcgo.MPIN_HASH_ID(ID)
-
-	// Generate server secret share 1
-	rtn, SS1 := amclcgo.MPIN_GET_SERVER_SECRET_WRAP(MS1[:])
-	if rtn != 0 {
-		fmt.Println("MPIN_GET_SERVER_SECRET Error:", rtn)
-		return
-	}
-	fmt.Printf("SS1: 0x")
-	amclcgo.MPIN_printBinary(SS1[:])
-
-	// Generate server secret share 2
-	rtn, SS2 := amclcgo.MPIN_GET_SERVER_SECRET_WRAP(MS2[:])
-	if rtn != 0 {
-		fmt.Println("MPIN_GET_SERVER_SECRET Error:", rtn)
-		return
-	}
-	fmt.Printf("SS2: 0x")
-	amclcgo.MPIN_printBinary(SS2[:])
-
-	// Combine server secret shares
-	rtn, SS := amclcgo.MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:])
-	if rtn != 0 {
-		fmt.Println("MPIN_RECOMBINE_G2(SS1, SS2) Error:", rtn)
-		return
-	}
-	fmt.Printf("SS: 0x")
-	amclcgo.MPIN_printBinary(SS[:])
-
-	// Generate client secret share 1
-	rtn, CS1 := amclcgo.MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID)
-	if rtn != 0 {
-		fmt.Println("MPIN_GET_CLIENT_SECRET Error:", rtn)
-		return
-	}
-	fmt.Printf("Client Secret Share CS1: 0x")
-	amclcgo.MPIN_printBinary(CS1[:])
-
-	// Generate client secret share 2
-	rtn, CS2 := amclcgo.MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID)
-	if rtn != 0 {
-		fmt.Println("MPIN_GET_CLIENT_SECRET Error:", rtn)
-		return
-	}
-	fmt.Printf("Client Secret Share CS2: 0x")
-	amclcgo.MPIN_printBinary(CS2[:])
-
-	// Combine client secret shares
-	CS := make([]byte, amclcgo.G1S)
-	rtn, CS = amclcgo.MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:])
-	if rtn != 0 {
-		fmt.Println("MPIN_RECOMBINE_G1 Error:", rtn)
-		return
-	}
-	fmt.Printf("Client Secret CS: 0x")
-	amclcgo.MPIN_printBinary(CS[:])
-
-	// Generate time permit share 1
-	rtn, TP1 := amclcgo.MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID)
-	if rtn != 0 {
-		fmt.Println("MPIN_GET_CLIENT_PERMIT Error:", rtn)
-		return
-	}
-	fmt.Printf("TP1: 0x")
-	amclcgo.MPIN_printBinary(TP1[:])
-
-	// Generate time permit share 2
-	rtn, TP2 := amclcgo.MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID)
-	if rtn != 0 {
-		fmt.Println("MPIN_GET_CLIENT_PERMIT Error:", rtn)
-		return
-	}
-	fmt.Printf("TP2: 0x")
-	amclcgo.MPIN_printBinary(TP2[:])
-
-	// Combine time permit shares
-	rtn, TP := amclcgo.MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:])
-	if rtn != 0 {
-		fmt.Println("MPIN_RECOMBINE_G1(TP1, TP2) Error:", rtn)
-		return
-	}
-
-	// Client extracts PIN1 from secret to create Token
-	for PIN1 < 0 {
-		fmt.Printf("Please enter PIN to create token: ")
-		fmt.Scan(&PIN1)
-	}
-
-	rtn, TOKEN := amclcgo.MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:])
-	if rtn != 0 {
-		fmt.Printf("FAILURE: EXTRACT_PIN rtn: %d\n", rtn)
-		return
-	}
-	fmt.Printf("Client Token TK: 0x")
-	amclcgo.MPIN_printBinary(TOKEN[:])
-
-	//////   Client   //////
-
-	for PIN2 < 0 {
-		fmt.Printf("Please enter PIN to authenticate: ")
-		fmt.Scan(&PIN2)
-	}
-
-	// Send U, UT, V, timeValue and Message to server
-	var X [amclcgo.EGS]byte
-	fmt.Printf("X: 0x")
-	amclcgo.MPIN_printBinary(X[:])
-	rtn, XOut, Y1, SEC, U, UT := amclcgo.MPIN_CLIENT_WRAP(date, timeValue, PIN2, rng, ID[:], X[:], TOKEN[:], TP[:], MESSAGE[:])
-	if rtn != 0 {
-		fmt.Printf("FAILURE: CLIENT rtn: %d\n", rtn)
-		return
-	}
-	fmt.Printf("Y1: 0x")
-	amclcgo.MPIN_printBinary(Y1[:])
-	fmt.Printf("XOut: 0x")
-	amclcgo.MPIN_printBinary(XOut[:])
-
-	//////   Server   //////
-	rtn, HID, HTID, Y2, E, F := amclcgo.MPIN_SERVER_WRAP(date, timeValue, SS[:], U[:], UT[:], SEC[:], ID[:], MESSAGE[:])
-	if rtn != 0 {
-		fmt.Printf("FAILURE: SERVER rtn: %d\n", rtn)
-	}
-	fmt.Printf("Y2: 0x")
-	amclcgo.MPIN_printBinary(Y2[:])
-	fmt.Printf("HID: 0x")
-	amclcgo.MPIN_printBinary(HID[:])
-	fmt.Printf("HTID: 0x")
-	amclcgo.MPIN_printBinary(HTID[:])
-
-	if rtn != 0 {
-		fmt.Printf("Authentication failed Error Code %d\n", rtn)
-		err := amclcgo.MPIN_KANGAROO(E[:], F[:])
-		if err != 0 {
-			fmt.Printf("PIN Error %d\n", err)
-		}
-		return
-	} else {
-		fmt.Printf("Authenticated ID: %s \n", IDstr)
-	}
-}
diff --git a/go/examples-cgo/mpinTwoPass.go b/go/examples-cgo/mpinTwoPass.go
deleted file mode 100644
index 9e4cc62..0000000
--- a/go/examples-cgo/mpinTwoPass.go
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
-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.
-*/
-
-package main
-
-import (
-	"encoding/hex"
-	"fmt"
-
-	amclcgo "git.apache.org/incubator-milagro-crypto.git/go/amcl-cgo"
-	amclgo "git.apache.org/incubator-milagro-crypto.git/go/amcl-go"
-)
-
-func main() {
-	// Assign the End-User an ID
-	IDstr := "testUser@miracl.com"
-	ID := []byte(IDstr)
-	fmt.Printf("ID: ")
-	amclcgo.MPIN_printBinary(ID)
-	fmt.Printf("\n")
-
-	// Epoch time in days
-	date := amclcgo.MPIN_today()
-
-	// PIN variable to create token
-	PIN1 := -1
-	// PIN variable to authenticate
-	PIN2 := -1
-
-	// Seed value for Random Number Generator (RNG)
-	seedHex := "9e8b4178790cd57a5761c4a6f164ba72"
-	seed, err := hex.DecodeString(seedHex)
-	if err != nil {
-		fmt.Println("Error decoding seed value")
-		return
-	}
-	rng := amclgo.NewRAND()
-	rng.Seed(len(seed), seed)
-
-	// Generate Master Secret Share 1
-	rtn, MS1 := amclcgo.MPIN_RANDOM_GENERATE_WRAP(rng)
-	if rtn != 0 {
-		fmt.Println("MPIN_RANDOM_GENERATE Error:", rtn)
-		return
-	}
-	fmt.Printf("MS1: 0x")
-	amclcgo.MPIN_printBinary(MS1[:])
-
-	// Generate Master Secret Share 2
-	rtn, MS2 := amclcgo.MPIN_RANDOM_GENERATE_WRAP(rng)
-	if rtn != 0 {
-		fmt.Println("MPIN_RANDOM_GENERATE Error:", rtn)
-		return
-	}
-	fmt.Printf("MS2: 0x")
-	amclcgo.MPIN_printBinary(MS2[:])
-
-	// Either Client or TA calculates Hash(ID)
-	HCID := amclcgo.MPIN_HASH_ID(ID)
-
-	// Generate server secret share 1
-	rtn, SS1 := amclcgo.MPIN_GET_SERVER_SECRET_WRAP(MS1[:])
-	if rtn != 0 {
-		fmt.Println("MPIN_GET_SERVER_SECRET Error:", rtn)
-		return
-	}
-	fmt.Printf("SS1: 0x")
-	amclcgo.MPIN_printBinary(SS1[:])
-
-	// Generate server secret share 2
-	rtn, SS2 := amclcgo.MPIN_GET_SERVER_SECRET_WRAP(MS2[:])
-	if rtn != 0 {
-		fmt.Println("MPIN_GET_SERVER_SECRET Error:", rtn)
-		return
-	}
-	fmt.Printf("SS2: 0x")
-	amclcgo.MPIN_printBinary(SS2[:])
-
-	// Combine server secret shares
-	rtn, SS := amclcgo.MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:])
-	if rtn != 0 {
-		fmt.Println("MPIN_RECOMBINE_G2(SS1, SS2) Error:", rtn)
-		return
-	}
-	fmt.Printf("SS: 0x")
-	amclcgo.MPIN_printBinary(SS[:])
-
-	// Generate client secret share 1
-	rtn, CS1 := amclcgo.MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID)
-	if rtn != 0 {
-		fmt.Println("MPIN_GET_CLIENT_SECRET Error:", rtn)
-		return
-	}
-	fmt.Printf("Client Secret Share CS1: 0x")
-	amclcgo.MPIN_printBinary(CS1[:])
-
-	// Generate client secret share 2
-	rtn, CS2 := amclcgo.MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID)
-	if rtn != 0 {
-		fmt.Println("MPIN_GET_CLIENT_SECRET Error:", rtn)
-		return
-	}
-	fmt.Printf("Client Secret Share CS2: 0x")
-	amclcgo.MPIN_printBinary(CS2[:])
-
-	// Combine client secret shares
-	CS := make([]byte, amclcgo.G1S)
-	rtn, CS = amclcgo.MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:])
-	if rtn != 0 {
-		fmt.Println("MPIN_RECOMBINE_G1 Error:", rtn)
-		return
-	}
-	fmt.Printf("Client Secret CS: 0x")
-	amclcgo.MPIN_printBinary(CS[:])
-
-	// Generate time permit share 1
-	rtn, TP1 := amclcgo.MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID)
-	if rtn != 0 {
-		fmt.Println("MPIN_GET_CLIENT_PERMIT Error:", rtn)
-		return
-	}
-	fmt.Printf("TP1: 0x")
-	amclcgo.MPIN_printBinary(TP1[:])
-
-	// Generate time permit share 2
-	rtn, TP2 := amclcgo.MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID)
-	if rtn != 0 {
-		fmt.Println("MPIN_GET_CLIENT_PERMIT Error:", rtn)
-		return
-	}
-	fmt.Printf("TP2: 0x")
-	amclcgo.MPIN_printBinary(TP2[:])
-
-	// Combine time permit shares
-	rtn, TP := amclcgo.MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:])
-	if rtn != 0 {
-		fmt.Println("MPIN_RECOMBINE_G1(TP1, TP2) Error:", rtn)
-		return
-	}
-
-	// Client extracts PIN1 from secret to create Token
-	for PIN1 < 0 {
-		fmt.Printf("Please enter PIN to create token: ")
-		fmt.Scan(&PIN1)
-	}
-
-	rtn, TOKEN := amclcgo.MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:])
-	if rtn != 0 {
-		fmt.Printf("FAILURE: EXTRACT_PIN rtn: %d\n", rtn)
-		return
-	}
-	fmt.Printf("Client Token TK: 0x")
-	amclcgo.MPIN_printBinary(TOKEN[:])
-
-	//////   Client   //////
-
-	for PIN2 < 0 {
-		fmt.Printf("Please enter PIN to authenticate: ")
-		fmt.Scan(&PIN2)
-	}
-
-	////// Client Pass 1 //////
-	// Send U and UT to server
-	var X [amclcgo.EGS]byte
-	fmt.Printf("X: 0x")
-	amclcgo.MPIN_printBinary(X[:])
-	rtn, XOut, SEC, U, UT := amclcgo.MPIN_CLIENT_1_WRAP(date, ID, rng, X[:], PIN2, TOKEN[:], TP[:])
-	if rtn != 0 {
-		fmt.Printf("FAILURE: CLIENT rtn: %d\n", rtn)
-		return
-	}
-	fmt.Printf("XOut: 0x")
-	amclcgo.MPIN_printBinary(XOut[:])
-
-	//////   Server Pass 1  //////
-	/* Calculate 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 := amclcgo.MPIN_SERVER_1_WRAP(date, ID)
-
-	/* Send Y to Client */
-	rtn, Y := amclcgo.MPIN_RANDOM_GENERATE_WRAP(rng)
-	if rtn != 0 {
-		fmt.Println("MPIN_RANDOM_GENERATE Error:", rtn)
-		return
-	}
-	fmt.Printf("Y: 0x")
-	amclcgo.MPIN_printBinary(Y[:])
-
-	/* Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC */
-	rtn, V := amclcgo.MPIN_CLIENT_2_WRAP(X[:], Y[:], SEC[:])
-	if rtn != 0 {
-		fmt.Printf("FAILURE: CLIENT_2 rtn: %d\n", 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, _, _ = amclcgo.MPIN_SERVER_2_WRAP(date, HID[:], HTID[:], Y[:], SS[:], U[:], UT[:], V[:])
-	if rtn != 0 {
-		fmt.Printf("FAILURE: MPIN_SERVER_2 rtn: %d\n", rtn)
-	}
-	fmt.Printf("HID: 0x")
-	amclcgo.MPIN_printBinary(HID[:])
-	fmt.Printf("HTID: 0x")
-	amclcgo.MPIN_printBinary(HTID[:])
-
-	if rtn != 0 {
-		fmt.Printf("Authentication failed Error Code %d\n", rtn)
-		return
-	} else {
-		fmt.Printf("Authenticated ID: %s \n", IDstr)
-	}
-}
diff --git a/go/examples-cgo/mpinfull.go b/go/examples-cgo/mpinfull.go
deleted file mode 100644
index 5a6a649..0000000
--- a/go/examples-cgo/mpinfull.go
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
-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.
-*/
-
-package main
-
-import (
-	"encoding/hex"
-	"fmt"
-
-	amclcgo "git.apache.org/incubator-milagro-crypto.git/go/amcl-cgo"
-	amclgo "git.apache.org/incubator-milagro-crypto.git/go/amcl-go"
-)
-
-func main() {
-	// Assign the End-User an ID
-	IDstr := "testUser@miracl.com"
-	ID := []byte(IDstr)
-	fmt.Printf("ID: ")
-	amclcgo.MPIN_printBinary(ID)
-	fmt.Printf("\n")
-
-	// Epoch time in days
-	date := amclcgo.MPIN_today()
-
-	// Epoch time in seconds
-	timeValue := amclcgo.MPIN_GET_TIME()
-
-	// PIN variable to create token
-	PIN1 := -1
-	// PIN variable to authenticate
-	PIN2 := -1
-
-	// Seed value for Random Number Generator (RNG)
-	seedHex := "9e8b4178790cd57a5761c4a6f164ba72"
-	seed, err := hex.DecodeString(seedHex)
-	if err != nil {
-		fmt.Println("Error decoding seed value")
-		return
-	}
-	rng := amclgo.NewRAND()
-	rng.Seed(len(seed), seed)
-
-	// Message to sign
-	var MESSAGE []byte
-	// MESSAGE := []byte("test sign message")
-
-	// Generate Master Secret Share 1
-	rtn, MS1 := amclcgo.MPIN_RANDOM_GENERATE_WRAP(rng)
-	if rtn != 0 {
-		fmt.Println("MPIN_RANDOM_GENERATE Error:", rtn)
-		return
-	}
-	fmt.Printf("MS1: 0x")
-	amclcgo.MPIN_printBinary(MS1[:])
-
-	// Generate Master Secret Share 2
-	rtn, MS2 := amclcgo.MPIN_RANDOM_GENERATE_WRAP(rng)
-	if rtn != 0 {
-		fmt.Println("MPIN_RANDOM_GENERATE Error:", rtn)
-		return
-	}
-	fmt.Printf("MS2: 0x")
-	amclcgo.MPIN_printBinary(MS2[:])
-
-	// Either Client or TA calculates Hash(ID)
-	HCID := amclcgo.MPIN_HASH_ID(ID)
-
-	// Generate server secret share 1
-	rtn, SS1 := amclcgo.MPIN_GET_SERVER_SECRET_WRAP(MS1[:])
-	if rtn != 0 {
-		fmt.Println("MPIN_GET_SERVER_SECRET Error:", rtn)
-		return
-	}
-	fmt.Printf("SS1: 0x")
-	amclcgo.MPIN_printBinary(SS1[:])
-
-	// Generate server secret share 2
-	rtn, SS2 := amclcgo.MPIN_GET_SERVER_SECRET_WRAP(MS2[:])
-	if rtn != 0 {
-		fmt.Println("MPIN_GET_SERVER_SECRET Error:", rtn)
-		return
-	}
-	fmt.Printf("SS2: 0x")
-	amclcgo.MPIN_printBinary(SS2[:])
-
-	// Combine server secret shares
-	rtn, SS := amclcgo.MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:])
-	if rtn != 0 {
-		fmt.Println("MPIN_RECOMBINE_G2(SS1, SS2) Error:", rtn)
-		return
-	}
-	fmt.Printf("SS: 0x")
-	amclcgo.MPIN_printBinary(SS[:])
-
-	// Generate client secret share 1
-	rtn, CS1 := amclcgo.MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID)
-	if rtn != 0 {
-		fmt.Println("MPIN_GET_CLIENT_SECRET Error:", rtn)
-		return
-	}
-	fmt.Printf("Client Secret Share CS1: 0x")
-	amclcgo.MPIN_printBinary(CS1[:])
-
-	// Generate client secret share 2
-	rtn, CS2 := amclcgo.MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID)
-	if rtn != 0 {
-		fmt.Println("MPIN_GET_CLIENT_SECRET Error:", rtn)
-		return
-	}
-	fmt.Printf("Client Secret Share CS2: 0x")
-	amclcgo.MPIN_printBinary(CS2[:])
-
-	// Combine client secret shares
-	CS := make([]byte, amclcgo.G1S)
-	rtn, CS = amclcgo.MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:])
-	if rtn != 0 {
-		fmt.Println("MPIN_RECOMBINE_G1 Error:", rtn)
-		return
-	}
-	fmt.Printf("Client Secret CS: 0x")
-	amclcgo.MPIN_printBinary(CS[:])
-
-	// Generate time permit share 1
-	rtn, TP1 := amclcgo.MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID)
-	if rtn != 0 {
-		fmt.Println("MPIN_GET_CLIENT_PERMIT Error:", rtn)
-		return
-	}
-	fmt.Printf("TP1: 0x")
-	amclcgo.MPIN_printBinary(TP1[:])
-
-	// Generate time permit share 2
-	rtn, TP2 := amclcgo.MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID)
-	if rtn != 0 {
-		fmt.Println("MPIN_GET_CLIENT_PERMIT Error:", rtn)
-		return
-	}
-	fmt.Printf("TP2: 0x")
-	amclcgo.MPIN_printBinary(TP2[:])
-
-	// Combine time permit shares
-	rtn, TP := amclcgo.MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:])
-	if rtn != 0 {
-		fmt.Println("MPIN_RECOMBINE_G1(TP1, TP2) Error:", rtn)
-		return
-	}
-
-	// Client extracts PIN1 from secret to create Token
-	for PIN1 < 0 {
-		fmt.Printf("Please enter PIN to create token: ")
-		fmt.Scan(&PIN1)
-	}
-
-	rtn, TOKEN := amclcgo.MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:])
-	if rtn != 0 {
-		fmt.Printf("FAILURE: EXTRACT_PIN rtn: %d\n", rtn)
-		return
-	}
-	fmt.Printf("Client Token TK: 0x")
-	amclcgo.MPIN_printBinary(TOKEN[:])
-
-	//////   Client   //////
-
-	// Precomputation
-	rtn, G1, G2 := amclcgo.MPIN_PRECOMPUTE_WRAP(TOKEN[:], HCID)
-	if rtn != 0 {
-		fmt.Println("MPIN_PRECOMPUTE(TOKEN[:], HCID) Error:", rtn)
-		return
-	}
-
-	for PIN2 < 0 {
-		fmt.Printf("Please enter PIN to authenticate: ")
-		fmt.Scan(&PIN2)
-	}
-
-	// Send U, UT, V, timeValue and Message to server
-	var X [amclcgo.EGS]byte
-	fmt.Printf("X: 0x")
-	amclcgo.MPIN_printBinary(X[:])
-	rtn, XOut, Y1, V, U, UT := amclcgo.MPIN_CLIENT_WRAP(date, timeValue, PIN2, rng, ID[:], X[:], TOKEN[:], TP[:], MESSAGE[:])
-	if rtn != 0 {
-		fmt.Printf("FAILURE: CLIENT rtn: %d\n", rtn)
-		return
-	}
-	fmt.Printf("Y1: 0x")
-	amclcgo.MPIN_printBinary(Y1[:])
-	fmt.Printf("XOut: 0x")
-	amclcgo.MPIN_printBinary(XOut[:])
-
-	// Send Z=r.ID to Server
-	var R [amclcgo.EGS]byte
-	fmt.Printf("R: 0x")
-	amclcgo.MPIN_printBinary(R[:])
-	rtn, ROut, Z := amclcgo.MPIN_GET_G1_MULTIPLE_WRAP(rng, 1, R[:], HCID[:])
-	fmt.Printf("ROut: 0x")
-	amclcgo.MPIN_printBinary(ROut[:])
-
-	//////   Server   //////
-	rtn, HID, HTID, Y2, E, F := amclcgo.MPIN_SERVER_WRAP(date, timeValue, SS[:], U[:], UT[:], V[:], ID[:], MESSAGE[:])
-	if rtn != 0 {
-		fmt.Printf("FAILURE: SERVER rtn: %d\n", rtn)
-	}
-	fmt.Printf("Y2: 0x")
-	amclcgo.MPIN_printBinary(Y2[:])
-	fmt.Printf("HID: 0x")
-	amclcgo.MPIN_printBinary(HID[:])
-	fmt.Printf("HTID: 0x")
-	amclcgo.MPIN_printBinary(HTID[:])
-
-	if rtn != 0 {
-		fmt.Printf("Authentication failed Error Code %d\n", rtn)
-		err := amclcgo.MPIN_KANGAROO(E[:], F[:])
-		if err != 0 {
-			fmt.Printf("PIN Error %d\n", err)
-		}
-		return
-	} else {
-		fmt.Printf("Authenticated ID: %s \n", IDstr)
-	}
-
-	// send T=w.ID to client
-	var W [amclcgo.EGS]byte
-	fmt.Printf("W: 0x")
-	amclcgo.MPIN_printBinary(W[:])
-	rtn, WOut, T := amclcgo.MPIN_GET_G1_MULTIPLE_WRAP(rng, 0, W[:], HTID[:])
-	fmt.Printf("WOut: 0x")
-	amclcgo.MPIN_printBinary(WOut[:])
-	fmt.Printf("T: 0x")
-	amclcgo.MPIN_printBinary(T[:])
-
-        // Hash all values
-        HM := amclcgo.MPIN_HASH_ALL_WRAP(ID[:],U[:],UT[:],Y2[:],V[:],Z[:],T[:])
-
-	rtn, AES_KEY_SERVER := amclcgo.MPIN_SERVER_KEY_WRAP(Z[:], SS[:], WOut[:], HM[:],HID[:],U[:], UT[:])
-	fmt.Printf("Server Key =  0x")
-	amclcgo.MPIN_printBinary(AES_KEY_SERVER[:])
-
-	rtn, AES_KEY_CLIENT := amclcgo.MPIN_CLIENT_KEY_WRAP(PIN2, G1[:], G2[:], ROut[:], XOut[:], HM[:],T[:])
-	fmt.Printf("Client Key =  0x")
-	amclcgo.MPIN_printBinary(AES_KEY_CLIENT[:])
-
-	//////   Server   //////
-
-	// Initialization vector
-	IV := amclgo.GENERATE_RANDOM(rng, 12)
-	fmt.Printf("IV: 0x")
-	amclcgo.MPIN_printBinary(IV[:])
-
-	// header
-	HEADER := amclgo.GENERATE_RANDOM(rng, 16)
-	fmt.Printf("HEADER: 0x")
-	amclcgo.MPIN_printBinary(HEADER[:])
-
-	// Input plaintext
-	plaintextStr := "A test message"
-	PLAINTEXT1 := []byte(plaintextStr)
-	fmt.Printf("String to encrypt: %s \n", plaintextStr)
-	fmt.Printf("PLAINTEXT1: 0x")
-	amclcgo.MPIN_printBinary(PLAINTEXT1[:])
-
-	// AES-GCM Encryption
-	CIPHERTEXT, TAG1 := amclcgo.MPIN_AES_GCM_ENCRYPT(AES_KEY_SERVER[:], IV[:], HEADER[:], PLAINTEXT1[:])
-	fmt.Printf("CIPHERTEXT:  0x")
-	amclcgo.MPIN_printBinary(CIPHERTEXT[:])
-	fmt.Printf("TAG1:  0x")
-	amclcgo.MPIN_printBinary(TAG1[:])
-
-	// Send IV, HEADER, CIPHERTEXT and TAG1 to client
-
-	// AES-GCM Decryption
-	PLAINTEXT2, TAG2 := amclcgo.MPIN_AES_GCM_DECRYPT(AES_KEY_CLIENT[:], IV[:], HEADER[:], CIPHERTEXT[:])
-	fmt.Printf("PLAINTEXT2:  0x")
-	amclcgo.MPIN_printBinary(PLAINTEXT2[:])
-	fmt.Printf("TAG2:  0x")
-	amclcgo.MPIN_printBinary(TAG2[:])
-	fmt.Printf("Decrypted string: %s \n", string(PLAINTEXT2))
-}
diff --git a/go/examples-cgo/mpinfullAnon.go b/go/examples-cgo/mpinfullAnon.go
deleted file mode 100644
index 57472cb..0000000
--- a/go/examples-cgo/mpinfullAnon.go
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one
-or more contributor license agreements.  See the NOTICE file
-distributed with this work for additional information
-regarding copyright ownership.  The ASF licenses this file
-to you under the Apache License, Version 2.0 (the
-"License"); you may not use this file except in compliance
-with the License.  You may obtain a copy of the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing,
-software distributed under the License is distributed on an
-"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-KIND, either express or implied.  See the License for the
-specific language governing permissions and limitations
-under the License.
-*/
-
-// Use MPIN with only hashed IDs to the server
-
-package main
-
-import (
-	"encoding/hex"
-	"fmt"
-
-	amclcgo "git.apache.org/incubator-milagro-crypto.git/go/amcl-cgo"
-	amclgo "git.apache.org/incubator-milagro-crypto.git/go/amcl-go"
-)
-
-func main() {
-	// Assign the End-User an ID
-	IDstr := "testUser@miracl.com"
-	ID := []byte(IDstr)
-	fmt.Printf("ID: ")
-	amclcgo.MPIN_printBinary(ID)
-	fmt.Printf("\n")
-
-	// Epoch time in days
-	date := amclcgo.MPIN_today()
-
-	// Epoch time in seconds
-	timeValue := amclcgo.MPIN_GET_TIME()
-
-	// PIN variable to create token
-	PIN1 := -1
-	// PIN variable to authenticate
-	PIN2 := -1
-
-	// Seed value for Random Number Generator (RNG)
-	seedHex := "9e8b4178790cd57a5761c4a6f164ba72"
-	seed, err := hex.DecodeString(seedHex)
-	if err != nil {
-		fmt.Println("Error decoding seed value")
-		return
-	}
-	rng := amclgo.NewRAND()
-	rng.Seed(len(seed), seed)
-
-	// Message to sign
-	var MESSAGE []byte
-	// MESSAGE := []byte("test sign message")
-
-	// Generate Master Secret Share 1
-	rtn, MS1 := amclcgo.MPIN_RANDOM_GENERATE_WRAP(rng)
-	if rtn != 0 {
-		fmt.Println("MPIN_RANDOM_GENERATE Error:", rtn)
-		return
-	}
-	fmt.Printf("MS1: 0x")
-	amclcgo.MPIN_printBinary(MS1[:])
-
-	// Generate Master Secret Share 2
-	rtn, MS2 := amclcgo.MPIN_RANDOM_GENERATE_WRAP(rng)
-	if rtn != 0 {
-		fmt.Println("MPIN_RANDOM_GENERATE Error:", rtn)
-		return
-	}
-	fmt.Printf("MS2: 0x")
-	amclcgo.MPIN_printBinary(MS2[:])
-
-	// Either Client or TA calculates Hash(ID)
-	HCID := amclcgo.MPIN_HASH_ID(ID)
-
-	// Generate server secret share 1
-	rtn, SS1 := amclcgo.MPIN_GET_SERVER_SECRET_WRAP(MS1[:])
-	if rtn != 0 {
-		fmt.Println("MPIN_GET_SERVER_SECRET Error:", rtn)
-		return
-	}
-	fmt.Printf("SS1: 0x")
-	amclcgo.MPIN_printBinary(SS1[:])
-
-	// Generate server secret share 2
-	rtn, SS2 := amclcgo.MPIN_GET_SERVER_SECRET_WRAP(MS2[:])
-	if rtn != 0 {
-		fmt.Println("MPIN_GET_SERVER_SECRET Error:", rtn)
-		return
-	}
-	fmt.Printf("SS2: 0x")
-	amclcgo.MPIN_printBinary(SS2[:])
-
-	// Combine server secret shares
-	rtn, SS := amclcgo.MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:])
-	if rtn != 0 {
-		fmt.Println("MPIN_RECOMBINE_G2(SS1, SS2) Error:", rtn)
-		return
-	}
-	fmt.Printf("SS: 0x")
-	amclcgo.MPIN_printBinary(SS[:])
-
-	// Generate client secret share 1
-	rtn, CS1 := amclcgo.MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID)
-	if rtn != 0 {
-		fmt.Println("MPIN_GET_CLIENT_SECRET Error:", rtn)
-		return
-	}
-	fmt.Printf("Client Secret Share CS1: 0x")
-	amclcgo.MPIN_printBinary(CS1[:])
-
-	// Generate client secret share 2
-	rtn, CS2 := amclcgo.MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID)
-	if rtn != 0 {
-		fmt.Println("MPIN_GET_CLIENT_SECRET Error:", rtn)
-		return
-	}
-	fmt.Printf("Client Secret Share CS2: 0x")
-	amclcgo.MPIN_printBinary(CS2[:])
-
-	// Combine client secret shares
-	CS := make([]byte, amclcgo.G1S)
-	rtn, CS = amclcgo.MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:])
-	if rtn != 0 {
-		fmt.Println("MPIN_RECOMBINE_G1 Error:", rtn)
-		return
-	}
-	fmt.Printf("Client Secret CS: 0x")
-	amclcgo.MPIN_printBinary(CS[:])
-
-	// Generate time permit share 1
-	rtn, TP1 := amclcgo.MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID)
-	if rtn != 0 {
-		fmt.Println("MPIN_GET_CLIENT_PERMIT Error:", rtn)
-		return
-	}
-	fmt.Printf("TP1: 0x")
-	amclcgo.MPIN_printBinary(TP1[:])
-
-	// Generate time permit share 2
-	rtn, TP2 := amclcgo.MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID)
-	if rtn != 0 {
-		fmt.Println("MPIN_GET_CLIENT_PERMIT Error:", rtn)
-		return
-	}
-	fmt.Printf("TP2: 0x")
-	amclcgo.MPIN_printBinary(TP2[:])
-
-	// Combine time permit shares
-	rtn, TP := amclcgo.MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:])
-	if rtn != 0 {
-		fmt.Println("MPIN_RECOMBINE_G1(TP1, TP2) Error:", rtn)
-		return
-	}
-
-	// Client extracts PIN1 from secret to create Token
-	for PIN1 < 0 {
-		fmt.Printf("Please enter PIN to create token: ")
-		fmt.Scan(&PIN1)
-	}
-
-	rtn, TOKEN := amclcgo.MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:])
-	if rtn != 0 {
-		fmt.Printf("FAILURE: EXTRACT_PIN rtn: %d\n", rtn)
-		return
-	}
-	fmt.Printf("Client Token TK: 0x")
-	amclcgo.MPIN_printBinary(TOKEN[:])
-
-	//////   Client   //////
-
-	// Precomputation
-	rtn, G1, G2 := amclcgo.MPIN_PRECOMPUTE_WRAP(TOKEN[:], HCID)
-	if rtn != 0 {
-		fmt.Println("MPIN_PRECOMPUTE(TOKEN[:], HCID) Error:", rtn)
-		return
-	}
-
-	for PIN2 < 0 {
-		fmt.Printf("Please enter PIN to authenticate: ")
-		fmt.Scan(&PIN2)
-	}
-
-	// Send U, UT, V, timeValue and Message to server
-	var X [amclcgo.EGS]byte
-	fmt.Printf("X: 0x")
-	amclcgo.MPIN_printBinary(X[:])
-	rtn, XOut, Y1, V, U, UT := amclcgo.MPIN_CLIENT_WRAP(date, timeValue, PIN2, rng, ID[:], X[:], TOKEN[:], TP[:], MESSAGE[:])
-	if rtn != 0 {
-		fmt.Printf("FAILURE: CLIENT rtn: %d\n", rtn)
-		return
-	}
-	fmt.Printf("Y1: 0x")
-	amclcgo.MPIN_printBinary(Y1[:])
-	fmt.Printf("XOut: 0x")
-	amclcgo.MPIN_printBinary(XOut[:])
-
-	// Send Z=r.ID to Server
-	var R [amclcgo.EGS]byte
-	fmt.Printf("R: 0x")
-	amclcgo.MPIN_printBinary(R[:])
-	rtn, ROut, Z := amclcgo.MPIN_GET_G1_MULTIPLE_WRAP(rng, 1, R[:], HCID[:])
-	fmt.Printf("ROut: 0x")
-	amclcgo.MPIN_printBinary(ROut[:])
-
-	//////   Server   //////
-	rtn, HID, HTID, Y2, E, F := amclcgo.MPIN_SERVER_WRAP(date, timeValue, SS[:], U[:], UT[:], V[:], HCID[:], MESSAGE[:])
-	if rtn != 0 {
-		fmt.Printf("FAILURE: SERVER rtn: %d\n", rtn)
-	}
-	fmt.Printf("Y2: 0x")
-	amclcgo.MPIN_printBinary(Y2[:])
-	fmt.Printf("HID: 0x")
-	amclcgo.MPIN_printBinary(HID[:])
-	fmt.Printf("HTID: 0x")
-	amclcgo.MPIN_printBinary(HTID[:])
-
-	if rtn != 0 {
-		fmt.Printf("Authentication failed Error Code %d\n", rtn)
-		err := amclcgo.MPIN_KANGAROO(E[:], F[:])
-		if err != 0 {
-			fmt.Printf("PIN Error %d\n", err)
-		}
-		return
-	} else {
-		fmt.Printf("Authenticated ID: %s \n", IDstr)
-	}
-
-	// send T=w.ID to client
-	var W [amclcgo.EGS]byte
-	fmt.Printf("W: 0x")
-	amclcgo.MPIN_printBinary(W[:])
-	rtn, WOut, T := amclcgo.MPIN_GET_G1_MULTIPLE_WRAP(rng, 0, W[:], HTID[:])
-	fmt.Printf("WOut: 0x")
-	amclcgo.MPIN_printBinary(WOut[:])
-	fmt.Printf("T: 0x")
-	amclcgo.MPIN_printBinary(T[:])
-
-	// Hash all values
-	HM := amclcgo.MPIN_HASH_ALL_WRAP(HCID[:], U[:], UT[:], Y2[:], V[:], Z[:], T[:])
-
-	rtn, AES_KEY_SERVER := amclcgo.MPIN_SERVER_KEY_WRAP(Z[:], SS[:], WOut[:], HM[:], HID[:], U[:], UT[:])
-	fmt.Printf("Server Key =  0x")
-	amclcgo.MPIN_printBinary(AES_KEY_SERVER[:])
-
-	rtn, AES_KEY_CLIENT := amclcgo.MPIN_CLIENT_KEY_WRAP(PIN2, G1[:], G2[:], ROut[:], XOut[:], HM[:], T[:])
-	fmt.Printf("Client Key =  0x")
-	amclcgo.MPIN_printBinary(AES_KEY_CLIENT[:])
-
-	//////   Server   //////
-
-	// Initialization vector
-	IV := amclgo.GENERATE_RANDOM(rng, 12)
-	fmt.Printf("IV: 0x")
-	amclcgo.MPIN_printBinary(IV[:])
-
-	// header
-	HEADER := amclgo.GENERATE_RANDOM(rng, 16)
-	fmt.Printf("HEADER: 0x")
-	amclcgo.MPIN_printBinary(HEADER[:])
-
-	// Input plaintext
-	plaintextStr := "A test message"
-	PLAINTEXT1 := []byte(plaintextStr)
-	fmt.Printf("String to encrypt: %s \n", plaintextStr)
-	fmt.Printf("PLAINTEXT1: 0x")
-	amclcgo.MPIN_printBinary(PLAINTEXT1[:])
-
-	// AES-GCM Encryption
-	CIPHERTEXT, TAG1 := amclcgo.MPIN_AES_GCM_ENCRYPT(AES_KEY_SERVER[:], IV[:], HEADER[:], PLAINTEXT1[:])
-	fmt.Printf("CIPHERTEXT:  0x")
-	amclcgo.MPIN_printBinary(CIPHERTEXT[:])
-	fmt.Printf("TAG1:  0x")
-	amclcgo.MPIN_printBinary(TAG1[:])
-
-	// Send IV, HEADER, CIPHERTEXT and TAG1 to client
-
-	// AES-GCM Decryption
-	PLAINTEXT2, TAG2 := amclcgo.MPIN_AES_GCM_DECRYPT(AES_KEY_CLIENT[:], IV[:], HEADER[:], CIPHERTEXT[:])
-	fmt.Printf("PLAINTEXT2:  0x")
-	amclcgo.MPIN_printBinary(PLAINTEXT2[:])
-	fmt.Printf("TAG2:  0x")
-	amclcgo.MPIN_printBinary(TAG2[:])
-	fmt.Printf("Decrypted string: %s \n", string(PLAINTEXT2))
-}
diff --git a/go/examples-cgo/timempin.go b/go/examples-cgo/timempin.go
deleted file mode 100644
index d055bce..0000000
--- a/go/examples-cgo/timempin.go
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
-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.
-*/
-
-package main
-
-import (
-	"encoding/hex"
-	"flag"
-	"log"
-	"os"
-	"runtime/pprof"
-	"time"
-
-	amclcgo "git.apache.org/incubator-milagro-crypto.git/go/amcl-cgo"
-)
-
-// Number of iterations to time functions
-const nIter int = 1000
-
-var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
-
-func main() {
-	flag.Parse()
-	if *cpuprofile != "" {
-		f, err := os.Create(*cpuprofile)
-		if err != nil {
-			log.Fatal(err)
-		}
-		pprof.StartCPUProfile(f)
-		defer pprof.StopCPUProfile()
-	}
-
-	// Assign the End-User an ID
-	IDstr := "testUser@miracl.com"
-	ID := []byte(IDstr)
-
-	// Epoch time in days
-	date := 16673
-
-	// Epoch time in seconds
-	timeValue := 1440594584
-
-	SSHex := "07f8181687f42ce22ea0dee4ba9df3f2cea67ad2d79e59adc953142556d510831bbd59e9477ac479019887020579aed16af43dc7089ae8c14262e64b5d09740109917efd0618c557fbf7efaa68fb64e8d46b3766bb184dea9bef9638f23bbbeb03aedbc6e4eb9fbd658719aab26b849638690521723c0efb9c8622df2a8efa3c"
-	SS, _ := hex.DecodeString(SSHex)
-	UHex := "0403e76a28df08ea591912e0ff84ebf419e21aadf8ec5aed4b0f3cd0fc1cdea14a06f05a3be4f9f2d16530c6b4934da2e3439ea287796faac079d396f8cdb9f565"
-	U, _ := hex.DecodeString(UHex)
-	UTHex := "041012e53c991edc9514889de50fb7d893c406dc9bf4c89d46fec9ba408cc5f596226402e7c468c823a28b9003a3944c4600a1b797f10cf01060d3729729212932"
-	UT, _ := hex.DecodeString(UTHex)
-	SECHex := "04051b0d3e9dfdb2a378f0ac7056fb264a900d0867e39c334950527d8c460d76132346bf8ed8a419e2eab4ad52a8b7a51d8c09cbcfa4e80bc0487965ece72ab0ce"
-	SEC, _ := hex.DecodeString(SECHex)
-	var MESSAGE []byte
-	// MESSAGE := []byte("test sign message")
-
-	t0 := time.Now()
-	var rtn int
-	for i := 0; i < nIter; i++ {
-		rtn, _, _, _, _, _ = amclcgo.MPIN_SERVER_WRAP(date, timeValue, SS[:], U[:], UT[:], SEC[:], ID[:], MESSAGE[:])
-	}
-	t1 := time.Now()
-	log.Printf("Number Iterations: %d Time: %v\n", nIter, t1.Sub(t0))
-
-	if rtn != 0 {
-		log.Printf("Authentication failed Error Code %d\n", rtn)
-		return
-	} else {
-		log.Printf("Authenticated ID: %s \n", IDstr)
-	}
-}
diff --git a/go/examples-go/ecdh.go b/go/examples-go/ecdh.go
deleted file mode 100644
index 190ea14..0000000
--- a/go/examples-go/ecdh.go
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
-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.
-*/
-
-package main
-
-import (
-	"fmt"
-
-	amcl "git.apache.org/incubator-milagro-crypto.git/go/amcl-go"
-)
-
-func main() {
-
-	//	j:=0
-	pp := "M0ng00se"
-	res := 0
-
-	var S1 [amcl.ECDH_EGS]byte
-	var W0 [2*amcl.ECDH_EFS + 1]byte
-	var W1 [2*amcl.ECDH_EFS + 1]byte
-	var Z0 [amcl.ECDH_EFS]byte
-	var Z1 [amcl.ECDH_EFS]byte
-	var RAW [100]byte
-	var SALT [8]byte
-	var P1 [3]byte
-	var P2 [4]byte
-	var V [2*amcl.ECDH_EFS + 1]byte
-	var M [17]byte
-	var T [12]byte
-	var CS [amcl.ECDH_EGS]byte
-	var DS [amcl.ECDH_EGS]byte
-
-	rng := amcl.NewRAND()
-
-	rng.Clean()
-	for i := 0; i < 100; i++ {
-		RAW[i] = byte(i)
-	}
-
-	rng.Seed(100, RAW[:])
-
-	//for j:=0;j<100;j++ {
-
-	for i := 0; i < 8; i++ {
-		SALT[i] = byte(i + 1)
-	} // set Salt
-
-	fmt.Printf("Alice's Passphrase= " + pp)
-	fmt.Printf("\n")
-	PW := []byte(pp)
-
-	/* private key S0 of size EGS bytes derived from Password and Salt */
-
-	S0 := amcl.PBKDF2(PW, SALT[:], 1000, amcl.ECDH_EGS)
-
-	fmt.Printf("Alice's private key= 0x")
-	amcl.ECDH_printBinary(S0)
-
-	/* Generate Key pair S/W */
-	amcl.ECDH_KEY_PAIR_GENERATE(nil, S0, W0[:])
-
-	fmt.Printf("Alice's public key= 0x")
-	amcl.ECDH_printBinary(W0[:])
-
-	res = amcl.ECDH_PUBLIC_KEY_VALIDATE(true, W0[:])
-	if res != 0 {
-		fmt.Printf("ECP Public Key is invalid!\n")
-		return
-	}
-
-	/* Random private key for other party */
-	amcl.ECDH_KEY_PAIR_GENERATE(rng, S1[:], W1[:])
-
-	fmt.Printf("Servers private key= 0x")
-	amcl.ECDH_printBinary(S1[:])
-
-	fmt.Printf("Servers public key= 0x")
-	amcl.ECDH_printBinary(W1[:])
-
-	res = amcl.ECDH_PUBLIC_KEY_VALIDATE(true, W1[:])
-	if res != 0 {
-		fmt.Printf("ECP Public Key is invalid!\n")
-		return
-	}
-	/* Calculate common key using DH - IEEE 1363 method */
-
-	amcl.ECPSVDP_DH(S0, W1[:], Z0[:])
-	amcl.ECPSVDP_DH(S1[:], W0[:], Z1[:])
-
-	same := true
-	for i := 0; i < amcl.ECDH_EFS; i++ {
-		if Z0[i] != Z1[i] {
-			same = false
-		}
-	}
-
-	if !same {
-		fmt.Printf("*** ECPSVDP-DH Failed\n")
-		return
-	}
-
-	KEY := amcl.KDF1(Z0[:], amcl.ECDH_EAS)
-
-	fmt.Printf("Alice's DH Key=  0x")
-	amcl.ECDH_printBinary(KEY)
-	fmt.Printf("Servers DH Key=  0x")
-	amcl.ECDH_printBinary(KEY)
-
-	if amcl.CURVETYPE != amcl.MONTGOMERY {
-		fmt.Printf("Testing ECIES\n")
-
-		P1[0] = 0x0
-		P1[1] = 0x1
-		P1[2] = 0x2
-		P2[0] = 0x0
-		P2[1] = 0x1
-		P2[2] = 0x2
-		P2[3] = 0x3
-
-		for i := 0; i <= 16; i++ {
-			M[i] = byte(i)
-		}
-
-		C := amcl.ECIES_ENCRYPT(P1[:], P2[:], rng, W1[:], M[:], V[:], T[:])
-
-		fmt.Printf("Ciphertext= \n")
-		fmt.Printf("V= 0x")
-		amcl.ECDH_printBinary(V[:])
-		fmt.Printf("C= 0x")
-		amcl.ECDH_printBinary(C)
-		fmt.Printf("T= 0x")
-		amcl.ECDH_printBinary(T[:])
-
-		RM := amcl.ECIES_DECRYPT(P1[:], P2[:], V[:], C, T[:], S1[:])
-		if RM == nil {
-			fmt.Printf("*** ECIES Decryption Failed\n")
-			return
-		} else {
-			fmt.Printf("Decryption succeeded\n")
-		}
-
-		fmt.Printf("Message is 0x")
-		amcl.ECDH_printBinary(RM)
-
-		fmt.Printf("Testing ECDSA\n")
-
-		if amcl.ECPSP_DSA(rng, S0, M[:], CS[:], DS[:]) != 0 {
-			fmt.Printf("***ECDSA Signature Failed\n")
-			return
-		}
-		fmt.Printf("Signature= \n")
-		fmt.Printf("C= 0x")
-		amcl.ECDH_printBinary(CS[:])
-		fmt.Printf("D= 0x")
-		amcl.ECDH_printBinary(DS[:])
-
-		if amcl.ECPVP_DSA(W0[:], M[:], CS[:], DS[:]) != 0 {
-			fmt.Printf("***ECDSA Verification Failed\n")
-			return
-		} else {
-			fmt.Printf("ECDSA Signature/Verification succeeded \n")
-		}
-	}
-}
diff --git a/go/examples-go/generateRandom.go b/go/examples-go/generateRandom.go
deleted file mode 100644
index 83faf1b..0000000
--- a/go/examples-go/generateRandom.go
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
-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.
-*/
-
-/* Password Based Key Derivation Function Example */
-
-package main
-
-import (
-	"encoding/hex"
-	"fmt"
-
-	amcl "git.apache.org/incubator-milagro-crypto.git/go/amcl-go"
-)
-
-func main() {
-	// Seed value for Random Number Generator (RNG)
-	seedHex := "9e8b4178790cd57a5761c4a6f164ba72"
-	seed, err := hex.DecodeString(seedHex)
-	if err != nil {
-		fmt.Println("Error decoding seed value")
-		return
-	}
-	rng := amcl.NewRAND()
-	rng.Seed(len(seed), seed)
-
-	// Generate random byte values
-	for i := 0; i < 10; i++ {
-		val := amcl.GENERATE_RANDOM(rng, 12)
-		fmt.Printf("Random byte array %s\n", hex.EncodeToString(val))
-	}
-
-}
diff --git a/go/examples-go/mpin.go b/go/examples-go/mpin.go
deleted file mode 100644
index 4ee3ae7..0000000
--- a/go/examples-go/mpin.go
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
-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.
-*/
-
-package main
-
-import (
-	"fmt"
-
-	amcl "git.apache.org/incubator-milagro-crypto.git/go/amcl-go"
-)
-
-/* Configure mode of operation */
-
-const PERMITS bool = true
-const PINERROR bool = true
-const FULL bool = true
-const SINGLE_PASS bool = true
-
-func main() {
-	rng := amcl.NewRAND()
-	var raw [100]byte
-	for i := 0; i < 100; i++ {
-		raw[i] = byte(i + 1)
-	}
-	rng.Seed(100, raw[:])
-
-	const EGS = amcl.MPIN_EGS
-	const EFS = amcl.MPIN_EFS
-	const G1S = 2*EFS + 1 /* Group 1 Size */
-	const G2S = 4 * EFS   /* Group 2 Size */
-	const EAS int = 16
-
-	var S [EGS]byte
-	var SST [G2S]byte
-	var TOKEN [G1S]byte
-	var PERMIT [G1S]byte
-	var SEC [G1S]byte
-	var xID [G1S]byte
-	var xCID [G1S]byte
-	var X [EGS]byte
-	var Y [EGS]byte
-	var E [12 * EFS]byte
-	var F [12 * EFS]byte
-	var HID [G1S]byte
-	var HTID [G1S]byte
-
-	var G1 [12 * EFS]byte
-	var G2 [12 * EFS]byte
-	var R [EGS]byte
-	var Z [G1S]byte
-	var W [EGS]byte
-	var T [G1S]byte
-	var CK [EAS]byte
-	var SK [EAS]byte
-	var MESSAGE [256]byte
-
-	/* Trusted Authority set-up */
-
-	amcl.MPIN_RANDOM_GENERATE(rng, S[:])
-	fmt.Printf("Master Secret s: 0x")
-	amcl.MPIN_printBinary(S[:])
-
-	/* Create Client Identity */
-	IDstr := "testUser@miracl.com"
-	CLIENT_ID := []byte(IDstr)
-
-	HCID := amcl.MPIN_HASH_ID(CLIENT_ID) /* Either Client or TA calculates Hash(ID) - you decide! */
-
-	fmt.Printf("Client ID= ")
-	amcl.MPIN_printBinary(CLIENT_ID)
-	fmt.Printf("\n")
-
-	/* Client and Server are issued secrets by DTA */
-	amcl.MPIN_GET_SERVER_SECRET(S[:], SST[:])
-	fmt.Printf("Server Secret SS: 0x")
-	amcl.MPIN_printBinary(SST[:])
-
-	amcl.MPIN_GET_CLIENT_SECRET(S[:], HCID, TOKEN[:])
-	fmt.Printf("Client Secret CS: 0x")
-	amcl.MPIN_printBinary(TOKEN[:])
-
-	/* Client extracts PIN from secret to create Token */
-	pin := 1234
-	fmt.Printf("Client extracts PIN= %d", pin)
-	fmt.Printf("\n")
-	rtn := amcl.MPIN_EXTRACT_PIN(CLIENT_ID, pin, TOKEN[:])
-	if rtn != 0 {
-		fmt.Printf("FAILURE: EXTRACT_PIN rtn: %d", rtn)
-		fmt.Printf("\n")
-	}
-
-	fmt.Printf("Client Token TK: 0x")
-	amcl.MPIN_printBinary(TOKEN[:])
-
-	if FULL {
-		amcl.MPIN_PRECOMPUTE(TOKEN[:], HCID, G1[:], G2[:])
-	}
-
-	date := 0
-	if PERMITS {
-		date = amcl.MPIN_today()
-		/* Client gets "Time Token" permit from DTA */
-		amcl.MPIN_GET_CLIENT_PERMIT(date, S[:], HCID, PERMIT[:])
-		fmt.Printf("Time Permit TP: 0x")
-		amcl.MPIN_printBinary(PERMIT[:])
-
-		/* This encoding makes Time permit look random - Elligator squared */
-		amcl.MPIN_ENCODING(rng, PERMIT[:])
-		fmt.Printf("Encoded Time Permit TP: 0x")
-		amcl.MPIN_printBinary(PERMIT[:])
-		amcl.MPIN_DECODING(PERMIT[:])
-		fmt.Printf("Decoded Time Permit TP: 0x")
-		amcl.MPIN_printBinary(PERMIT[:])
-	}
-
-	pin = -1
-	for pin < 0 {
-		fmt.Printf("\nPIN= ")
-		fmt.Scanf("%d", &pin)
-	}
-
-	pxID := xID[:]
-	pxCID := xCID[:]
-	pHID := HID[:]
-	pHTID := HTID[:]
-	pE := E[:]
-	pF := F[:]
-	pPERMIT := PERMIT[:]
-	var prHID []byte
-
-	if date != 0 {
-		prHID = pHTID
-		if !PINERROR {
-			pxID = nil
-			pHID = nil
-		}
-	} else {
-		prHID = pHID
-		pPERMIT = nil
-		pxCID = nil
-		pHTID = nil
-	}
-	if !PINERROR {
-		pE = nil
-		pF = nil
-	}
-
-	if SINGLE_PASS {
-		fmt.Printf("MPIN Single Pass\n")
-		timeValue := amcl.MPIN_GET_TIME()
-		rtn = amcl.MPIN_CLIENT(date, CLIENT_ID, rng, X[:], pin, TOKEN[:], SEC[:], pxID, pxCID, pPERMIT, MESSAGE[:], timeValue, Y[:])
-		if rtn != 0 {
-			fmt.Printf("FAILURE: CLIENT rtn: %d\n", rtn)
-		}
-
-		if FULL {
-			HCID = amcl.MPIN_HASH_ID(CLIENT_ID)
-			amcl.MPIN_GET_G1_MULTIPLE(rng, 1, R[:], HCID, Z[:]) /* Also Send Z=r.ID to Server, remember random r */
-		}
-
-		rtn = amcl.MPIN_SERVER(date, pHID, pHTID, Y[:], SST[:], pxID, pxCID, SEC[:], pE, pF, CLIENT_ID, MESSAGE[:], timeValue)
-		if rtn != 0 {
-			fmt.Printf("FAILURE: SERVER rtn: %d\n", rtn)
-		}
-
-		if FULL {
-			amcl.MPIN_GET_G1_MULTIPLE(rng, 0, W[:], prHID, T[:]) /* Also send T=w.ID to client, remember random w  */
-		}
-	} else {
-		fmt.Printf("MPIN Multi Pass\n")
-		/* Send U=x.ID to server, and recreate secret from token and pin */
-		rtn = amcl.MPIN_CLIENT_1(date, CLIENT_ID, rng, X[:], pin, TOKEN[:], SEC[:], pxID, pxCID, pPERMIT)
-		if rtn != 0 {
-			fmt.Printf("FAILURE: CLIENT_1 rtn: %d\n", rtn)
-		}
-
-		if FULL {
-			HCID = amcl.MPIN_HASH_ID(CLIENT_ID)
-			amcl.MPIN_GET_G1_MULTIPLE(rng, 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. */
-		amcl.MPIN_SERVER_1(date, CLIENT_ID, pHID, pHTID)
-
-		/* Server generates Random number Y and sends it to Client */
-		amcl.MPIN_RANDOM_GENERATE(rng, Y[:])
-
-		if FULL {
-			amcl.MPIN_GET_G1_MULTIPLE(rng, 0, W[:], prHID, T[:]) /* Also send T=w.ID to client, remember random w  */
-		}
-
-		/* Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC */
-		rtn = amcl.MPIN_CLIENT_2(X[:], Y[:], SEC[:])
-		if rtn != 0 {
-			fmt.Printf("FAILURE: CLIENT_2 rtn: %d\n", 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 = amcl.MPIN_SERVER_2(date, pHID, pHTID, Y[:], SST[:], pxID, pxCID, SEC[:], pE, pF)
-	}
-
-	if rtn != 0 {
-		fmt.Printf("FAILURE: SERVER_1 rtn: %d\n", rtn)
-	}
-
-	if rtn == amcl.MPIN_BAD_PIN {
-		fmt.Printf("Server says - Bad Pin. I don't know you. Feck off.\n")
-		if PINERROR {
-			err := amcl.MPIN_KANGAROO(E[:], F[:])
-			if err != 0 {
-				fmt.Printf("(Client PIN is out by %d)\n", err)
-			}
-		}
-		return
-	} else {
-		fmt.Printf("Server says - PIN is good! You really are " + IDstr)
-		fmt.Printf("\n")
-	}
-
-	if FULL {
-		amcl.MPIN_CLIENT_KEY(G1[:], G2[:], pin, R[:], X[:], T[:], CK[:])
-		fmt.Printf("Client Key =  0x")
-		amcl.MPIN_printBinary(CK[:])
-
-		amcl.MPIN_SERVER_KEY(Z[:], SST[:], W[:], pxID, pxCID, SK[:])
-		fmt.Printf("Server Key =  0x")
-		amcl.MPIN_printBinary(SK[:])
-	}
-
-}
diff --git a/go/examples-go/mpinTwoPass.go b/go/examples-go/mpinTwoPass.go
deleted file mode 100644
index b745f10..0000000
--- a/go/examples-go/mpinTwoPass.go
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
-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.
-*/
-
-package main
-
-import (
-	"encoding/hex"
-	"fmt"
-
-	amcl "git.apache.org/incubator-milagro-crypto.git/go/amcl-go"
-)
-
-func main() {
-	// Assign the End-User an ID
-	IDstr := "testUser@miracl.com"
-	ID := []byte(IDstr)
-	fmt.Printf("ID: ")
-	amcl.MPIN_printBinary(ID)
-	fmt.Printf("\n")
-
-	// Epoch time in days
-	date := amcl.MPIN_today()
-
-	// PIN variable to create token
-	PIN1 := -1
-	// PIN variable to authenticate
-	PIN2 := -1
-
-	// Seed value for Random Number Generator (RNG)
-	seedHex := "9e8b4178790cd57a5761c4a6f164ba72"
-	seed, err := hex.DecodeString(seedHex)
-	if err != nil {
-		fmt.Println("Error decoding seed value")
-		return
-	}
-	rng := amcl.NewRAND()
-	rng.Seed(len(seed), seed)
-
-	const EGS = amcl.MPIN_EGS
-	const EFS = amcl.MPIN_EFS
-	const G1S = 2*EFS + 1 /* Group 1 Size */
-	const G2S = 4 * EFS   /* Group 2 Size */
-	const EAS = amcl.MPIN_PAS
-
-	var MS1 [EGS]byte
-	var SS1 [G2S]byte
-	var CS1 [G1S]byte
-	var TP1 [G1S]byte
-	var MS2 [EGS]byte
-	var SS2 [G2S]byte
-	var CS2 [G1S]byte
-	var TP2 [G1S]byte
-	var SS [G2S]byte
-	var TP [G1S]byte
-	var TOKEN [G1S]byte
-	var SEC [G1S]byte
-	var U [G1S]byte
-	var UT [G1S]byte
-	var X [EGS]byte
-	var Y [EGS]byte
-	var E [12 * EFS]byte
-	var F [12 * EFS]byte
-	var HID [G1S]byte
-	var HTID [G1S]byte
-
-	// Generate Master Secret Share 1
-	amcl.MPIN_RANDOM_GENERATE(rng, MS1[:])
-	fmt.Printf("MS1: 0x")
-	amcl.MPIN_printBinary(MS1[:])
-
-	// Generate Master Secret Share 2
-	amcl.MPIN_RANDOM_GENERATE(rng, MS2[:])
-	fmt.Printf("MS2: 0x")
-	amcl.MPIN_printBinary(MS2[:])
-
-	// Either Client or TA calculates Hash(ID)
-	HCID := amcl.MPIN_HASH_ID(ID)
-
-	// Generate server secret share 1
-	amcl.MPIN_GET_SERVER_SECRET(MS1[:], SS1[:])
-	fmt.Printf("SS1: 0x")
-	amcl.MPIN_printBinary(SS1[:])
-
-	// Generate server secret share 2
-	amcl.MPIN_GET_SERVER_SECRET(MS2[:], SS2[:])
-	fmt.Printf("SS2: 0x")
-	amcl.MPIN_printBinary(SS2[:])
-
-	// Combine server secret shares
-	rtn := amcl.MPIN_RECOMBINE_G2(SS1[:], SS2[:], SS[:])
-	if rtn != 0 {
-		fmt.Println("MPIN_RECOMBINE_G2(SS1, SS2, SS) Error:", rtn)
-		return
-	}
-	fmt.Printf("SS: 0x")
-	amcl.MPIN_printBinary(SS[:])
-
-	// Generate client secret share 1
-	amcl.MPIN_GET_CLIENT_SECRET(MS1[:], HCID, CS1[:])
-	fmt.Printf("Client Secret CS: 0x")
-	amcl.MPIN_printBinary(CS1[:])
-
-	// Generate client secret share 2
-	amcl.MPIN_GET_CLIENT_SECRET(MS2[:], HCID, CS2[:])
-	fmt.Printf("Client Secret CS: 0x")
-	amcl.MPIN_printBinary(CS2[:])
-
-	// Combine client secret shares : TOKEN is the full client secret
-	rtn = amcl.MPIN_RECOMBINE_G1(CS1[:], CS2[:], TOKEN[:])
-	if rtn != 0 {
-		fmt.Println("MPIN_RECOMBINE_G1(CS1, CS2, TOKEN) Error:", rtn)
-		return
-	}
-
-	// Generate time permit share 1
-	amcl.MPIN_GET_CLIENT_PERMIT(date, MS1[:], HCID, TP1[:])
-	fmt.Printf("TP1: 0x")
-	amcl.MPIN_printBinary(TP1[:])
-
-	// Generate time permit share 2
-	amcl.MPIN_GET_CLIENT_PERMIT(date, MS2[:], HCID, TP2[:])
-	fmt.Printf("TP2: 0x")
-	amcl.MPIN_printBinary(TP2[:])
-
-	// Combine time permit shares
-	rtn = amcl.MPIN_RECOMBINE_G1(TP1[:], TP2[:], TP[:])
-	if rtn != 0 {
-		fmt.Println("MPIN_RECOMBINE_G1(TP1, TP2, TP) Error:", rtn)
-		return
-	}
-
-	// Client extracts PIN1 from secret to create Token
-	for PIN1 < 0 {
-		fmt.Printf("Please enter PIN to create token: ")
-		fmt.Scan(&PIN1)
-	}
-
-	rtn = amcl.MPIN_EXTRACT_PIN(ID, PIN1, TOKEN[:])
-	if rtn != 0 {
-		fmt.Printf("FAILURE: EXTRACT_PIN rtn: %d\n", rtn)
-		return
-	}
-	fmt.Printf("Client Token TK: 0x")
-	amcl.MPIN_printBinary(TOKEN[:])
-
-	for PIN2 < 0 {
-		fmt.Printf("Please enter PIN to authenticate: ")
-		fmt.Scan(&PIN2)
-	}
-
-	/* Clients first pass. Calculate U and UT */
-	rtn = amcl.MPIN_CLIENT_1(date, ID, rng, X[:], PIN2, TOKEN[:], SEC[:], U[:], UT[:], TP[:])
-	if rtn != 0 {
-		fmt.Printf("FAILURE: CLIENT rtn: %d\n", rtn)
-		return
-	}
-
-	/* Server first pass. Calculate H(ID) and H(T|H(ID)) (if time permits enabled), and maps them to points on the curve HID and HTID resp. */
-	amcl.MPIN_SERVER_1(date, ID, HID[:], HTID[:])
-
-	/* Server generates Random number Y and sends it to Client */
-	amcl.MPIN_RANDOM_GENERATE(rng, Y[:])
-
-	/* Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC */
-	rtn = amcl.MPIN_CLIENT_2(X[:], Y[:], SEC[:])
-	if rtn != 0 {
-		fmt.Printf("FAILURE: CLIENT_2 rtn: %d\n", 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 = amcl.MPIN_SERVER_2(date, HID[:], HTID[:], Y[:], SS[:], U[:], UT[:], SEC[:], E[:], F[:])
-	if rtn != 0 {
-		fmt.Printf("FAILURE: MPIN_SERVER_2 rtn: %d\n", rtn)
-	}
-	fmt.Printf("HID: 0x")
-	amcl.MPIN_printBinary(HID[:])
-	fmt.Printf("HTID: 0x")
-	amcl.MPIN_printBinary(HTID[:])
-
-	if rtn == amcl.MPIN_BAD_PIN {
-		fmt.Printf("Authentication failed Error Code %d\n", rtn)
-		err := amcl.MPIN_KANGAROO(E[:], F[:])
-		if err != 0 {
-			fmt.Printf("PIN Error %d\n", err)
-		}
-		return
-	} else {
-		fmt.Printf("Authenticated ID: %s \n", IDstr)
-	}
-}
diff --git a/go/examples-go/mpinTwoPassWrap.go b/go/examples-go/mpinTwoPassWrap.go
deleted file mode 100644
index f3174d1..0000000
--- a/go/examples-go/mpinTwoPassWrap.go
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
-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.
-*/
-
-package main
-
-import (
-	"encoding/hex"
-	"fmt"
-
-	amcl "git.apache.org/incubator-milagro-crypto.git/go/amcl-go"
-)
-
-func main() {
-	// Assign the End-User an ID
-	IDstr := "testUser@miracl.com"
-	ID := []byte(IDstr)
-	fmt.Printf("ID: ")
-	amcl.MPIN_printBinary(ID)
-	fmt.Printf("\n")
-
-	// Epoch time in days
-	date := amcl.MPIN_today()
-
-	// PIN variable to create token
-	PIN1 := -1
-	// PIN variable to authenticate
-	PIN2 := -1
-
-	// Seed value for Random Number Generator (RNG)
-	seedHex := "9e8b4178790cd57a5761c4a6f164ba72"
-	seed, err := hex.DecodeString(seedHex)
-	if err != nil {
-		fmt.Println("Error decoding seed value")
-		return
-	}
-	rng := amcl.NewRAND()
-	rng.Seed(len(seed), seed)
-
-	const EGS = amcl.MPIN_EGS
-	const EFS = amcl.MPIN_EFS
-	const G1S = 2*EFS + 1 /* Group 1 Size */
-	const G2S = 4 * EFS   /* Group 2 Size */
-	const EAS = amcl.MPIN_PAS
-
-	var X [EGS]byte
-
-	// Generate Master Secret Share 1
-	rtn, MS1 := amcl.MPIN_RANDOM_GENERATE_WRAP(rng)
-	if rtn != 0 {
-		fmt.Println("MPIN_RANDOM_GENERATE Error:", rtn)
-		return
-	}
-	fmt.Printf("MS1: 0x")
-	amcl.MPIN_printBinary(MS1[:])
-
-	// Generate Master Secret Share 2
-	rtn, MS2 := amcl.MPIN_RANDOM_GENERATE_WRAP(rng)
-	if rtn != 0 {
-		fmt.Println("MPIN_RANDOM_GENERATE Error:", rtn)
-		return
-	}
-	fmt.Printf("MS2: 0x")
-	amcl.MPIN_printBinary(MS2[:])
-
-	// Either Client or TA calculates Hash(ID)
-	HCID := amcl.MPIN_HASH_ID(ID)
-
-	// Generate server secret share 1
-	rtn, SS1 := amcl.MPIN_GET_SERVER_SECRET_WRAP(MS1[:])
-	if rtn != 0 {
-		fmt.Println("MPIN_GET_SERVER_SECRET Error:", rtn)
-		return
-	}
-	fmt.Printf("SS1: 0x")
-	amcl.MPIN_printBinary(SS1[:])
-
-	// Generate server secret share 2
-	rtn, SS2 := amcl.MPIN_GET_SERVER_SECRET_WRAP(MS2[:])
-	if rtn != 0 {
-		fmt.Println("MPIN_GET_SERVER_SECRET Error:", rtn)
-		return
-	}
-	fmt.Printf("SS2: 0x")
-	amcl.MPIN_printBinary(SS2[:])
-
-	// Combine server secret shares
-	rtn, SS := amcl.MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:])
-	if rtn != 0 {
-		fmt.Println("MPIN_RECOMBINE_G2(SS1, SS2) Error:", rtn)
-		return
-	}
-	fmt.Printf("SS: 0x")
-	amcl.MPIN_printBinary(SS[:])
-
-	// Generate client secret share 1
-	rtn, CS1 := amcl.MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID)
-	if rtn != 0 {
-		fmt.Println("MPIN_GET_CLIENT_SECRET Error:", rtn)
-		return
-	}
-	fmt.Printf("Client Secret CS: 0x")
-	amcl.MPIN_printBinary(CS1[:])
-
-	// Generate client secret share 2
-	rtn, CS2 := amcl.MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID)
-	if rtn != 0 {
-		fmt.Println("MPIN_GET_CLIENT_SECRET Error:", rtn)
-		return
-	}
-	fmt.Printf("Client Secret CS: 0x")
-	amcl.MPIN_printBinary(CS2[:])
-
-	// Combine client secret shares
-	rtn, CS := amcl.MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:])
-	if rtn != 0 {
-		fmt.Println("MPIN_RECOMBINE_G1 Error:", rtn)
-		return
-	}
-	fmt.Printf("Client Secret CS: 0x")
-	amcl.MPIN_printBinary(CS[:])
-
-	// Generate time permit share 1
-	rtn, TP1 := amcl.MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID)
-	if rtn != 0 {
-		fmt.Println("MPIN_GET_CLIENT_PERMIT Error:", rtn)
-		return
-	}
-	fmt.Printf("TP1: 0x")
-	amcl.MPIN_printBinary(TP1[:])
-
-	// Generate time permit share 2
-	rtn, TP2 := amcl.MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID)
-	if rtn != 0 {
-		fmt.Println("MPIN_GET_CLIENT_PERMIT Error:", rtn)
-		return
-	}
-	fmt.Printf("TP2: 0x")
-	amcl.MPIN_printBinary(TP2[:])
-
-	// Combine time permit shares
-	rtn, TP := amcl.MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:])
-	if rtn != 0 {
-		fmt.Println("MPIN_RECOMBINE_G1(TP1, TP2) Error:", rtn)
-		return
-	}
-
-	// Client extracts PIN1 from secret to create Token
-	for PIN1 < 0 {
-		fmt.Printf("Please enter PIN to create token: ")
-		fmt.Scan(&PIN1)
-	}
-
-	rtn, TOKEN := amcl.MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:])
-	if rtn != 0 {
-		fmt.Printf("FAILURE: EXTRACT_PIN rtn: %d\n", rtn)
-		return
-	}
-	fmt.Printf("Client Token TK: 0x")
-	amcl.MPIN_printBinary(TOKEN[:])
-
-	for PIN2 < 0 {
-		fmt.Printf("Please enter PIN to authenticate: ")
-		fmt.Scan(&PIN2)
-	}
-
-	/* Clients first pass. Calculate U and UT */
-	fmt.Printf("X: 0x")
-	amcl.MPIN_printBinary(X[:])
-	rtn, Xout, SEC, U, UT := amcl.MPIN_CLIENT_1_WRAP(date, ID, rng, X[:], PIN2, TOKEN[:], TP[:])
-	if rtn != 0 {
-		fmt.Printf("FAILURE: CLIENT rtn: %d\n", rtn)
-		return
-	}
-	fmt.Printf("Xout: 0x")
-	amcl.MPIN_printBinary(Xout[:])
-
-	/* Server first pass. Calculate 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 := amcl.MPIN_SERVER_1_WRAP(date, ID)
-
-	/* Server generates Random number Y and sends it to Client */
-	rtn, Y := amcl.MPIN_RANDOM_GENERATE_WRAP(rng)
-	if rtn != 0 {
-		fmt.Println("MPIN_RANDOM_GENERATE Error:", rtn)
-		return
-	}
-	fmt.Printf("Y: 0x")
-	amcl.MPIN_printBinary(Y[:])
-
-	/* Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC */
-	rtn, V := amcl.MPIN_CLIENT_2_WRAP(X[:], Y[:], SEC[:])
-	if rtn != 0 {
-		fmt.Printf("FAILURE: CLIENT_2 rtn: %d\n", 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, _, _ = amcl.MPIN_SERVER_2_WRAP(date, HID[:], HTID[:], Y[:], SS[:], U[:], UT[:], V[:])
-	if rtn != 0 {
-		fmt.Printf("FAILURE: MPIN_SERVER_2 rtn: %d\n", rtn)
-	}
-	fmt.Printf("HID: 0x")
-	amcl.MPIN_printBinary(HID[:])
-	fmt.Printf("HTID: 0x")
-	amcl.MPIN_printBinary(HTID[:])
-
-	if rtn == amcl.MPIN_BAD_PIN {
-		fmt.Printf("Authentication failed Error Code %d\n", rtn)
-		return
-	} else {
-		fmt.Printf("Authenticated ID: %s \n", IDstr)
-	}
-}
diff --git a/go/examples-go/mpinfull.go b/go/examples-go/mpinfull.go
deleted file mode 100644
index 53135c4..0000000
--- a/go/examples-go/mpinfull.go
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
-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.
-*/
-
-package main
-
-import (
-	"encoding/hex"
-	"fmt"
-
-	amcl "git.apache.org/incubator-milagro-crypto.git/go/amcl-go"
-)
-
-func main() {
-	// Assign the End-User an ID
-	IDstr := "testUser@miracl.com"
-	ID := []byte(IDstr)
-	fmt.Printf("ID: ")
-	amcl.MPIN_printBinary(ID)
-	fmt.Printf("\n")
-
-	// Epoch time in days
-	date := amcl.MPIN_today()
-
-	// Epoch time in seconds
-	timeValue := amcl.MPIN_GET_TIME()
-
-	// PIN variable to create token
-	PIN1 := -1
-	// PIN variable to authenticate
-	PIN2 := -1
-
-	// Seed value for Random Number Generator (RNG)
-	seedHex := "9e8b4178790cd57a5761c4a6f164ba72"
-	seed, err := hex.DecodeString(seedHex)
-	if err != nil {
-		fmt.Println("Error decoding seed value")
-		return
-	}
-	rng := amcl.NewRAND()
-	rng.Seed(len(seed), seed)
-
-	// Message to sign
-	var MESSAGE []byte
-	// MESSAGE := []byte("test sign message")
-
-	const EGS = amcl.MPIN_EGS
-	const EFS = amcl.MPIN_EFS
-	const G1S = 2*EFS + 1 /* Group 1 Size */
-	const G2S = 4 * EFS   /* Group 2 Size */
-	const EAS = amcl.MPIN_PAS
-
-	var MS1 [EGS]byte
-	var SS1 [G2S]byte
-	var CS1 [G1S]byte
-	var TP1 [G1S]byte
-	var MS2 [EGS]byte
-	var SS2 [G2S]byte
-	var CS2 [G1S]byte
-	var TP2 [G1S]byte
-	var SS [G2S]byte
-	var TP [G1S]byte
-	var TOKEN [G1S]byte
-	var SEC [G1S]byte
-	var U [G1S]byte
-	var UT [G1S]byte
-	var X [EGS]byte
-	var Y [EGS]byte
-	var E [12 * EFS]byte
-	var F [12 * EFS]byte
-	var HID [G1S]byte
-	var HTID [G1S]byte
-
-	var G1 [12 * EFS]byte
-	var G2 [12 * EFS]byte
-	var R [EGS]byte
-	var Z [G1S]byte
-	var W [EGS]byte
-	var T [G1S]byte
-	var AES_KEY_CLIENT [EAS]byte
-	var AES_KEY_SERVER [EAS]byte
-
-	// Generate Master Secret Share 1
-	amcl.MPIN_RANDOM_GENERATE(rng, MS1[:])
-	fmt.Printf("MS1: 0x")
-	amcl.MPIN_printBinary(MS1[:])
-
-	// Generate Master Secret Share 2
-	amcl.MPIN_RANDOM_GENERATE(rng, MS2[:])
-	fmt.Printf("MS2: 0x")
-	amcl.MPIN_printBinary(MS2[:])
-
-	// Either Client or TA calculates Hash(ID)
-	HCID := amcl.MPIN_HASH_ID(ID)
-
-	// Generate server secret share 1
-	amcl.MPIN_GET_SERVER_SECRET(MS1[:], SS1[:])
-	fmt.Printf("SS1: 0x")
-	amcl.MPIN_printBinary(SS1[:])
-
-	// Generate server secret share 2
-	amcl.MPIN_GET_SERVER_SECRET(MS2[:], SS2[:])
-	fmt.Printf("SS2: 0x")
-	amcl.MPIN_printBinary(SS2[:])
-
-	// Combine server secret shares
-	rtn := amcl.MPIN_RECOMBINE_G2(SS1[:], SS2[:], SS[:])
-	if rtn != 0 {
-		fmt.Println("MPIN_RECOMBINE_G2(SS1, SS2, SS) Error:", rtn)
-		return
-	}
-	fmt.Printf("SS: 0x")
-	amcl.MPIN_printBinary(SS[:])
-
-	// Generate client secret share 1
-	amcl.MPIN_GET_CLIENT_SECRET(MS1[:], HCID, CS1[:])
-	fmt.Printf("Client Secret CS: 0x")
-	amcl.MPIN_printBinary(CS1[:])
-
-	// Generate client secret share 2
-	amcl.MPIN_GET_CLIENT_SECRET(MS2[:], HCID, CS2[:])
-	fmt.Printf("Client Secret CS: 0x")
-	amcl.MPIN_printBinary(CS2[:])
-
-	// Combine client secret shares : TOKEN is the full client secret
-	rtn = amcl.MPIN_RECOMBINE_G1(CS1[:], CS2[:], TOKEN[:])
-	if rtn != 0 {
-		fmt.Println("MPIN_RECOMBINE_G1(CS1, CS2, TOKEN) Error:", rtn)
-		return
-	}
-
-	// Generate time permit share 1
-	amcl.MPIN_GET_CLIENT_PERMIT(date, MS1[:], HCID, TP1[:])
-	fmt.Printf("TP1: 0x")
-	amcl.MPIN_printBinary(TP1[:])
-
-	// Generate time permit share 2
-	amcl.MPIN_GET_CLIENT_PERMIT(date, MS2[:], HCID, TP2[:])
-	fmt.Printf("TP2: 0x")
-	amcl.MPIN_printBinary(TP2[:])
-
-	// Combine time permit shares
-	rtn = amcl.MPIN_RECOMBINE_G1(TP1[:], TP2[:], TP[:])
-	if rtn != 0 {
-		fmt.Println("MPIN_RECOMBINE_G1(TP1, TP2, TP) Error:", rtn)
-		return
-	}
-
-	// Client extracts PIN1 from secret to create Token
-	for PIN1 < 0 {
-		fmt.Printf("Please enter PIN to create token: ")
-		fmt.Scan(&PIN1)
-	}
-
-	rtn = amcl.MPIN_EXTRACT_PIN(ID, PIN1, TOKEN[:])
-	if rtn != 0 {
-		fmt.Printf("FAILURE: EXTRACT_PIN rtn: %d\n", rtn)
-		return
-	}
-	fmt.Printf("Client Token TK: 0x")
-	amcl.MPIN_printBinary(TOKEN[:])
-
-	//////   Client   //////
-
-	// precomputation
-	amcl.MPIN_PRECOMPUTE(TOKEN[:], HCID, G1[:], G2[:])
-
-	for PIN2 < 0 {
-		fmt.Printf("Please enter PIN to authenticate: ")
-		fmt.Scan(&PIN2)
-	}
-
-	// Send U, UT, V, timeValue and Message to server
-	rtn = amcl.MPIN_CLIENT(date, ID, rng, X[:], PIN2, TOKEN[:], SEC[:], U[:], UT[:], TP[:], MESSAGE, timeValue, Y[:])
-	if rtn != 0 {
-		fmt.Printf("FAILURE: CLIENT rtn: %d\n", rtn)
-		return
-	}
-
-	// Send Z=r.ID to Server
-	amcl.MPIN_GET_G1_MULTIPLE(rng, 1, R[:], HCID, Z[:])
-
-	//////   Server   //////
-	rtn = amcl.MPIN_SERVER(date, HID[:], HTID[:], Y[:], SS[:], U[:], UT[:], SEC[:], E[:], F[:], ID, MESSAGE, timeValue)
-	if rtn != 0 {
-		fmt.Printf("FAILURE: SERVER rtn: %d\n", rtn)
-	}
-	fmt.Printf("HID: 0x")
-	amcl.MPIN_printBinary(HID[:])
-	fmt.Printf("HTID: 0x")
-	amcl.MPIN_printBinary(HTID[:])
-
-	if rtn == amcl.MPIN_BAD_PIN {
-		fmt.Printf("Authentication failed Error Code %d\n", rtn)
-		err := amcl.MPIN_KANGAROO(E[:], F[:])
-		if err != 0 {
-			fmt.Printf("PIN Error %d\n", err)
-		}
-		return
-	} else {
-		fmt.Printf("Authenticated ID: %s \n", IDstr)
-	}
-
-	// send T=w.ID to client
-	amcl.MPIN_GET_G1_MULTIPLE(rng, 0, W[:], HTID[:], T[:])
-	fmt.Printf("W: 0x")
-	amcl.MPIN_printBinary(W[:])
-	fmt.Printf("T: 0x")
-	amcl.MPIN_printBinary(T[:])
-
-	amcl.MPIN_SERVER_KEY(Z[:], SS[:], W[:], U[:], UT[:], AES_KEY_SERVER[:])
-	fmt.Printf("Server Key =  0x")
-	amcl.MPIN_printBinary(AES_KEY_SERVER[:])
-
-	amcl.MPIN_CLIENT_KEY(G1[:], G2[:], PIN2, R[:], X[:], T[:], AES_KEY_CLIENT[:])
-	fmt.Printf("Client Key =  0x")
-	amcl.MPIN_printBinary(AES_KEY_CLIENT[:])
-
-	//////   Server   //////
-
-	// Initialization vector
-	IV := amcl.GENERATE_RANDOM(rng, 12)
-	fmt.Printf("IV: 0x")
-	amcl.MPIN_printBinary(IV[:])
-
-	// header
-	HEADER := amcl.GENERATE_RANDOM(rng, 16)
-	fmt.Printf("HEADER: 0x")
-	amcl.MPIN_printBinary(HEADER[:])
-
-	// Input plaintext
-	plaintextStr := "A test message"
-	PLAINTEXT1 := []byte(plaintextStr)
-	fmt.Printf("String to encrypt: %s \n", plaintextStr)
-	fmt.Printf("PLAINTEXT1: 0x")
-	amcl.MPIN_printBinary(PLAINTEXT1[:])
-
-	// AES-GCM Encryption
-	CIPHERTEXT, TAG1 := amcl.AES_GCM_ENCRYPT(AES_KEY_SERVER[:], IV[:], HEADER[:], PLAINTEXT1[:])
-	fmt.Printf("CIPHERTEXT:  0x")
-	amcl.MPIN_printBinary(CIPHERTEXT[:])
-	fmt.Printf("TAG1:  0x")
-	amcl.MPIN_printBinary(TAG1[:])
-
-	// Send IV, HEADER, CIPHERTEXT and TAG1 to client
-
-	// AES-GCM Decryption
-	PLAINTEXT2, TAG1 := amcl.AES_GCM_DECRYPT(AES_KEY_SERVER[:], IV[:], HEADER[:], CIPHERTEXT[:])
-	fmt.Printf("PLAINTEXT2:  0x")
-	amcl.MPIN_printBinary(PLAINTEXT2[:])
-	fmt.Printf("TAG1:  0x")
-	amcl.MPIN_printBinary(TAG1[:])
-	fmt.Printf("Decrypted string: %s \n", string(PLAINTEXT2))
-}
diff --git a/go/examples-go/mpinfullWrap.go b/go/examples-go/mpinfullWrap.go
deleted file mode 100644
index 12a7240..0000000
--- a/go/examples-go/mpinfullWrap.go
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
-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.
-*/
-
-package main
-
-import (
-	"encoding/hex"
-	"fmt"
-
-	"git.apache.org/incubator-milagro-crypto.git/go/amcl-go"
-)
-
-func main() {
-	// Assign the End-User an ID
-	IDstr := "testUser@miracl.com"
-	ID := []byte(IDstr)
-	fmt.Printf("ID: ")
-	amcl.MPIN_printBinary(ID)
-	fmt.Printf("\n")
-
-	// Epoch time in days
-	date := amcl.MPIN_today()
-
-	// Epoch time in seconds
-	timeValue := amcl.MPIN_GET_TIME()
-
-	// PIN variable to create token
-	PIN1 := -1
-	// PIN variable to authenticate
-	PIN2 := -1
-
-	// Seed value for Random Number Generator (RNG)
-	seedHex := "9e8b4178790cd57a5761c4a6f164ba72"
-	seed, err := hex.DecodeString(seedHex)
-	if err != nil {
-		fmt.Println("Error decoding seed value")
-		return
-	}
-	rng := amcl.NewRAND()
-	rng.Seed(len(seed), seed)
-
-	// Message to sign
-	var MESSAGE []byte
-	// MESSAGE := []byte("test sign message")
-
-	// Generate Master Secret Share 1
-	rtn, MS1 := amcl.MPIN_RANDOM_GENERATE_WRAP(rng)
-	if rtn != 0 {
-		fmt.Println("MPIN_RANDOM_GENERATE Error:", rtn)
-		return
-	}
-	fmt.Printf("MS1: 0x")
-	amcl.MPIN_printBinary(MS1[:])
-
-	// Generate Master Secret Share 2
-	rtn, MS2 := amcl.MPIN_RANDOM_GENERATE_WRAP(rng)
-	if rtn != 0 {
-		fmt.Println("MPIN_RANDOM_GENERATE Error:", rtn)
-		return
-	}
-	fmt.Printf("MS2: 0x")
-	amcl.MPIN_printBinary(MS2[:])
-
-	// Either Client or TA calculates Hash(ID)
-	HCID := amcl.MPIN_HASH_ID(ID)
-
-	// Generate server secret share 1
-	rtn, SS1 := amcl.MPIN_GET_SERVER_SECRET_WRAP(MS1[:])
-	if rtn != 0 {
-		fmt.Println("MPIN_GET_SERVER_SECRET Error:", rtn)
-		return
-	}
-	fmt.Printf("SS1: 0x")
-	amcl.MPIN_printBinary(SS1[:])
-
-	// Generate server secret share 2
-	rtn, SS2 := amcl.MPIN_GET_SERVER_SECRET_WRAP(MS2[:])
-	if rtn != 0 {
-		fmt.Println("MPIN_GET_SERVER_SECRET Error:", rtn)
-		return
-	}
-	fmt.Printf("SS2: 0x")
-	amcl.MPIN_printBinary(SS2[:])
-
-	// Combine server secret shares
-	rtn, SS := amcl.MPIN_RECOMBINE_G2_WRAP(SS1[:], SS2[:])
-	if rtn != 0 {
-		fmt.Println("MPIN_RECOMBINE_G2(SS1, SS2) Error:", rtn)
-		return
-	}
-	fmt.Printf("SS: 0x")
-	amcl.MPIN_printBinary(SS[:])
-
-	// Generate client secret share 1
-	rtn, CS1 := amcl.MPIN_GET_CLIENT_SECRET_WRAP(MS1[:], HCID)
-	if rtn != 0 {
-		fmt.Println("MPIN_GET_CLIENT_SECRET Error:", rtn)
-		return
-	}
-	fmt.Printf("Client Secret Share CS1: 0x")
-	amcl.MPIN_printBinary(CS1[:])
-
-	// Generate client secret share 2
-	rtn, CS2 := amcl.MPIN_GET_CLIENT_SECRET_WRAP(MS2[:], HCID)
-	if rtn != 0 {
-		fmt.Println("MPIN_GET_CLIENT_SECRET Error:", rtn)
-		return
-	}
-	fmt.Printf("Client Secret Share CS2: 0x")
-	amcl.MPIN_printBinary(CS2[:])
-
-	// Combine client secret shares
-	CS := make([]byte, amcl.G1S)
-	rtn, CS = amcl.MPIN_RECOMBINE_G1_WRAP(CS1[:], CS2[:])
-	if rtn != 0 {
-		fmt.Println("MPIN_RECOMBINE_G1 Error:", rtn)
-		return
-	}
-	fmt.Printf("Client Secret CS: 0x")
-	amcl.MPIN_printBinary(CS[:])
-
-	// Generate time permit share 1
-	rtn, TP1 := amcl.MPIN_GET_CLIENT_PERMIT_WRAP(date, MS1[:], HCID)
-	if rtn != 0 {
-		fmt.Println("MPIN_GET_CLIENT_PERMIT Error:", rtn)
-		return
-	}
-	fmt.Printf("TP1: 0x")
-	amcl.MPIN_printBinary(TP1[:])
-
-	// Generate time permit share 2
-	rtn, TP2 := amcl.MPIN_GET_CLIENT_PERMIT_WRAP(date, MS2[:], HCID)
-	if rtn != 0 {
-		fmt.Println("MPIN_GET_CLIENT_PERMIT Error:", rtn)
-		return
-	}
-	fmt.Printf("TP2: 0x")
-	amcl.MPIN_printBinary(TP2[:])
-
-	// Combine time permit shares
-	rtn, TP := amcl.MPIN_RECOMBINE_G1_WRAP(TP1[:], TP2[:])
-	if rtn != 0 {
-		fmt.Println("MPIN_RECOMBINE_G1(TP1, TP2) Error:", rtn)
-		return
-	}
-
-	// Client extracts PIN1 from secret to create Token
-	for PIN1 < 0 {
-		fmt.Printf("Please enter PIN to create token: ")
-		fmt.Scan(&PIN1)
-	}
-
-	fmt.Printf("ID: 0x")
-	amcl.MPIN_printBinary(ID[:])
-	fmt.Printf("CS: 0x")
-	amcl.MPIN_printBinary(CS[:])
-	rtn, TOKEN := amcl.MPIN_EXTRACT_PIN_WRAP(ID[:], PIN1, CS[:])
-	if rtn != 0 {
-		fmt.Printf("FAILURE: EXTRACT_PIN rtn: %d\n", rtn)
-		return
-	}
-	fmt.Printf("Client Token TK: 0x")
-	amcl.MPIN_printBinary(TOKEN[:])
-
-	//////   Client   //////
-
-	// Precomputation
-	rtn, G1, G2 := amcl.MPIN_PRECOMPUTE_WRAP(TOKEN[:], HCID)
-	if rtn != 0 {
-		fmt.Println("MPIN_PRECOMPUTE(TOKEN[:], HCID) Error:", rtn)
-		return
-	}
-
-	for PIN2 < 0 {
-		fmt.Printf("Please enter PIN to authenticate: ")
-		fmt.Scan(&PIN2)
-	}
-
-	// Send U, UT, V, timeValue and Message to server
-	var X [amcl.EGS]byte
-	fmt.Printf("X: 0x")
-	amcl.MPIN_printBinary(X[:])
-	rtn, XOut, Y1, SEC, U, UT := amcl.MPIN_CLIENT_WRAP(date, timeValue, PIN2, rng,  ID[:], X[:], TOKEN[:], TP[:], MESSAGE[:])
-	if rtn != 0 {
-		fmt.Printf("FAILURE: CLIENT rtn: %d\n", rtn)
-		return
-	}
-	fmt.Printf("Y1: 0x")
-	amcl.MPIN_printBinary(Y1[:])
-	fmt.Printf("XOut: 0x")
-	amcl.MPIN_printBinary(XOut[:])
-
-	// Send Z=r.ID to Server
-	var R [amcl.EGS]byte
-	fmt.Printf("R: 0x")
-	amcl.MPIN_printBinary(R[:])
-	rtn, ROut, Z := amcl.MPIN_GET_G1_MULTIPLE_WRAP(rng, 1, R[:], HCID[:])
-	fmt.Printf("ROut: 0x")
-	amcl.MPIN_printBinary(ROut[:])
-
-	//////   Server   //////
-	rtn, HID, HTID, Y2, E, F := amcl.MPIN_SERVER_WRAP(date, timeValue, SS[:], U[:], UT[:], SEC[:], ID[:], MESSAGE[:])
-	if rtn != 0 {
-		fmt.Printf("FAILURE: SERVER rtn: %d\n", rtn)
-	}
-	fmt.Printf("Y2: 0x")
-	amcl.MPIN_printBinary(Y2[:])
-	fmt.Printf("HID: 0x")
-	amcl.MPIN_printBinary(HID[:])
-	fmt.Printf("HTID: 0x")
-	amcl.MPIN_printBinary(HTID[:])
-
-	if rtn != 0 {
-		fmt.Printf("Authentication failed Error Code %d\n", rtn)
-		err := amcl.MPIN_KANGAROO(E[:], F[:])
-		if err != 0 {
-			fmt.Printf("PIN Error %d\n", err)
-		}
-		return
-	} else {
-		fmt.Printf("Authenticated ID: %s \n", IDstr)
-	}
-
-	// send T=w.ID to client
-	var W [amcl.EGS]byte
-	fmt.Printf("W: 0x")
-	amcl.MPIN_printBinary(W[:])
-	rtn, WOut, T := amcl.MPIN_GET_G1_MULTIPLE_WRAP(rng, 0, W[:], HTID[:])
-	fmt.Printf("WOut: 0x")
-	amcl.MPIN_printBinary(WOut[:])
-	fmt.Printf("T: 0x")
-	amcl.MPIN_printBinary(T[:])
-
-	rtn, AES_KEY_SERVER := amcl.MPIN_SERVER_KEY_WRAP(Z[:], SS[:], WOut[:], U[:], UT[:])
-	fmt.Printf("Server Key =  0x")
-	amcl.MPIN_printBinary(AES_KEY_SERVER[:])
-
-	rtn, AES_KEY_CLIENT := amcl.MPIN_CLIENT_KEY_WRAP(PIN2, G1[:], G2[:], ROut[:], XOut[:], T[:])
-	fmt.Printf("Client Key =  0x")
-	amcl.MPIN_printBinary(AES_KEY_CLIENT[:])
-
-	//////   Server   //////
-
-	// Initialization vector
-	IV := amcl.GENERATE_RANDOM(rng, 12)
-	fmt.Printf("IV: 0x")
-	amcl.MPIN_printBinary(IV[:])
-
-	// header
-	HEADER := amcl.GENERATE_RANDOM(rng, 16)
-	fmt.Printf("HEADER: 0x")
-	amcl.MPIN_printBinary(HEADER[:])
-
-	// Input plaintext
-	plaintextStr := "A test message"
-	PLAINTEXT1 := []byte(plaintextStr)
-	fmt.Printf("String to encrypt: %s \n", plaintextStr)
-	fmt.Printf("PLAINTEXT1: 0x")
-	amcl.MPIN_printBinary(PLAINTEXT1[:])
-
-	// AES-GCM Encryption
-	CIPHERTEXT, TAG1 := amcl.AES_GCM_ENCRYPT(AES_KEY_SERVER[:], IV[:], HEADER[:], PLAINTEXT1[:])
-	fmt.Printf("CIPHERTEXT:  0x")
-	amcl.MPIN_printBinary(CIPHERTEXT[:])
-	fmt.Printf("TAG1:  0x")
-	amcl.MPIN_printBinary(TAG1[:])
-
-	// Send IV, HEADER, CIPHERTEXT and TAG1 to client
-
-	// AES-GCM Decryption
-	PLAINTEXT2, TAG2 := amcl.AES_GCM_DECRYPT(AES_KEY_CLIENT[:], IV[:], HEADER[:], CIPHERTEXT[:])
-	fmt.Printf("PLAINTEXT2:  0x")
-	amcl.MPIN_printBinary(PLAINTEXT2[:])
-	fmt.Printf("TAG2:  0x")
-	amcl.MPIN_printBinary(TAG2[:])
-	fmt.Printf("Decrypted string: %s \n", string(PLAINTEXT2))
-}
diff --git a/go/examples-go/otp.go b/go/examples-go/otp.go
deleted file mode 100644
index dbeef16..0000000
--- a/go/examples-go/otp.go
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
-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.
-*/
-
-/* Password Based Key Derivation Function Example */
-
-package main
-
-import (
-	"encoding/hex"
-	"fmt"
-
-	amcl "git.apache.org/incubator-milagro-crypto.git/go/amcl-go"
-)
-
-func main() {
-	// Seed value for Random Number Generator (RNG)
-	seedHex := "9e8b4178790cd57a5761c4a6f164ba72"
-	seed, err := hex.DecodeString(seedHex)
-	if err != nil {
-		fmt.Println("Error decoding seed value")
-		return
-	}
-	rng := amcl.NewRAND()
-	rng.Seed(len(seed), seed)
-
-	// Generate the one time passwords
-	for i := 0; i < 10; i++ {
-		otp := amcl.GENERATE_OTP(rng)
-		fmt.Printf("One Time Passord %d\n", otp)
-	}
-
-}
diff --git a/go/examples-go/pbkdf2.go b/go/examples-go/pbkdf2.go
deleted file mode 100644
index dbd209c..0000000
--- a/go/examples-go/pbkdf2.go
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
-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.
-*/
-
-package main
-
-import (
-	"encoding/hex"
-	"fmt"
-
-	amcl "git.apache.org/incubator-milagro-crypto.git/go/amcl-go"
-)
-
-func main() {
-	// Seed value for Random Number Generator (RNG)
-	seedHex := "9e8b4178790cd57a5761c4a6f164ba72"
-	seed, err := hex.DecodeString(seedHex)
-	if err != nil {
-		fmt.Println("Error decoding seed value")
-		return
-	}
-	rng := amcl.NewRAND()
-	rng.Seed(len(seed), seed)
-
-	// Password / Pass-phrase
-	passwordStr := "#!qwerty"
-	password := []byte(passwordStr)
-	fmt.Printf("password: %s \n", password)
-	fmt.Printf("PASSWORD: 0x")
-	amcl.MPIN_printBinary(password[:])
-
-	// Salt
-	salt := amcl.GENERATE_RANDOM(rng, 16)
-	fmt.Printf("salt: 0x")
-	amcl.MPIN_printBinary(salt[:])
-
-	// Number of repetitions
-	rep := 1000
-
-	KEY := amcl.PBKDF2(password[:], salt[:], rep, amcl.MPIN_PAS)
-
-	// Initialization vector
-	IV := amcl.GENERATE_RANDOM(rng, 12)
-	fmt.Printf("IV: 0x")
-	amcl.MPIN_printBinary(IV[:])
-
-	// header
-	HEADER := amcl.GENERATE_RANDOM(rng, 16)
-	fmt.Printf("HEADER: 0x")
-	amcl.MPIN_printBinary(HEADER[:])
-
-	// Input plaintext
-	plaintextStr := "A test message"
-	PLAINTEXT1 := []byte(plaintextStr)
-	fmt.Printf("String to encrypt: %s \n", plaintextStr)
-	fmt.Printf("PLAINTEXT1: 0x")
-	amcl.MPIN_printBinary(PLAINTEXT1[:])
-
-	// AES-GCM Encryption
-	CIPHERTEXT, TAG1 := amcl.AES_GCM_ENCRYPT(KEY[:], IV[:], HEADER[:], PLAINTEXT1[:])
-	fmt.Printf("CIPHERTEXT:  0x")
-	amcl.MPIN_printBinary(CIPHERTEXT[:])
-	fmt.Printf("TAG1:  0x")
-	amcl.MPIN_printBinary(TAG1[:])
-
-	// AES-GCM Decryption
-	PLAINTEXT2, TAG1 := amcl.AES_GCM_DECRYPT(KEY[:], IV[:], HEADER[:], CIPHERTEXT[:])
-	fmt.Printf("PLAINTEXT2:  0x")
-	amcl.MPIN_printBinary(PLAINTEXT2[:])
-	fmt.Printf("TAG1:  0x")
-	amcl.MPIN_printBinary(TAG1[:])
-	fmt.Printf("Decrypted string: %s \n", string(PLAINTEXT2))
-}
diff --git a/go/examples-go/rsa.go b/go/examples-go/rsa.go
deleted file mode 100644
index 201beeb..0000000
--- a/go/examples-go/rsa.go
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
-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.
-*/
-
-/* RSA API high-level functions  */
-
-package main
-
-import (
-	"fmt"
-
-	amcl "git.apache.org/incubator-milagro-crypto.git/go/amcl-go"
-)
-
-func main() {
-
-	message := "Hello World\n"
-
-	pub := amcl.New_rsa_public_key(amcl.FFLEN)
-	priv := amcl.New_rsa_private_key(amcl.HFLEN)
-
-	var ML [amcl.RSA_RFS]byte
-	var C [amcl.RSA_RFS]byte
-	var RAW [100]byte
-
-	rng := amcl.NewRAND()
-
-	rng.Clean()
-	for i := 0; i < 100; i++ {
-		RAW[i] = byte(i)
-	}
-
-	rng.Seed(100, RAW[:])
-	//for (i=0;i<10;i++)
-	//{
-	fmt.Printf("Generating public/private key pair\n")
-	amcl.RSA_KEY_PAIR(rng, 65537, priv, pub)
-
-	M := []byte(message)
-
-	fmt.Printf("Encrypting test string\n")
-	E := amcl.RSA_OAEP_ENCODE(M, rng, nil) /* OAEP encode message M to E  */
-
-	amcl.RSA_ENCRYPT(pub, E, C[:]) /* encrypt encoded message */
-	fmt.Printf("Ciphertext= 0x")
-	amcl.RSA_printBinary(C[:])
-
-	fmt.Printf("Decrypting test string\n")
-	amcl.RSA_DECRYPT(priv, C[:], ML[:])
-	MS := amcl.RSA_OAEP_DECODE(nil, ML[:]) /* OAEP decode message  */
-
-	message = string(MS)
-	fmt.Printf(message)
-	//}
-	amcl.RSA_PRIVATE_KEY_KILL(priv)
-}
diff --git a/go/examples-go/timempin.go b/go/examples-go/timempin.go
deleted file mode 100644
index 9906b69..0000000
--- a/go/examples-go/timempin.go
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
-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.
-*/
-
-package main
-
-import (
-	"encoding/hex"
-	"flag"
-	"log"
-	"os"
-	"runtime/pprof"
-	"time"
-
-	amcl "git.apache.org/incubator-milagro-crypto.git/go/amcl-go"
-)
-
-// Number of iterations to time functions
-const nIter int = 10
-
-var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
-
-func main() {
-	flag.Parse()
-	if *cpuprofile != "" {
-		f, err := os.Create(*cpuprofile)
-		if err != nil {
-			log.Fatal(err)
-		}
-		pprof.StartCPUProfile(f)
-		defer pprof.StopCPUProfile()
-	}
-
-	// Assign the End-User an ID
-	IDstr := "testUser@miracl.com"
-	ID := []byte(IDstr)
-
-	// Epoch time in days
-	date := 16673
-
-	// Epoch time in seconds
-	timeValue := 1440594584
-
-	SSHex := "07f8181687f42ce22ea0dee4ba9df3f2cea67ad2d79e59adc953142556d510831bbd59e9477ac479019887020579aed16af43dc7089ae8c14262e64b5d09740109917efd0618c557fbf7efaa68fb64e8d46b3766bb184dea9bef9638f23bbbeb03aedbc6e4eb9fbd658719aab26b849638690521723c0efb9c8622df2a8efa3c"
-	SS, _ := hex.DecodeString(SSHex)
-	UHex := "0403e76a28df08ea591912e0ff84ebf419e21aadf8ec5aed4b0f3cd0fc1cdea14a06f05a3be4f9f2d16530c6b4934da2e3439ea287796faac079d396f8cdb9f565"
-	U, _ := hex.DecodeString(UHex)
-	UTHex := "041012e53c991edc9514889de50fb7d893c406dc9bf4c89d46fec9ba408cc5f596226402e7c468c823a28b9003a3944c4600a1b797f10cf01060d3729729212932"
-	UT, _ := hex.DecodeString(UTHex)
-	SECHex := "04051b0d3e9dfdb2a378f0ac7056fb264a900d0867e39c334950527d8c460d76132346bf8ed8a419e2eab4ad52a8b7a51d8c09cbcfa4e80bc0487965ece72ab0ce"
-	SEC, _ := hex.DecodeString(SECHex)
-	var MESSAGE []byte
-	// MESSAGE := []byte("test sign message")
-
-	const EGS = amcl.MPIN_EGS
-	const EFS = amcl.MPIN_EFS
-	const G1S = 2*EFS + 1 /* Group 1 Size */
-	const G2S = 4 * EFS   /* Group 2 Size */
-
-	var Y [EGS]byte
-	var E [12 * EFS]byte
-	var F [12 * EFS]byte
-	var HID [G1S]byte
-	var HTID [G1S]byte
-
-	//////   Server   //////
-	t0 := time.Now()
-	rtn := 0
-	for i := 0; i < nIter; i++ {
-		rtn = amcl.MPIN_SERVER(date, HID[:], HTID[:], Y[:], SS[:], U[:], UT[:], SEC[:], E[:], F[:], ID, MESSAGE, timeValue)
-	}
-	t1 := time.Now()
-	log.Printf("Number Iterations: %d Time: %v\n", nIter, t1.Sub(t0))
-
-	if rtn == amcl.MPIN_BAD_PIN {
-		log.Printf("Authentication failed Error Code %d\n", rtn)
-		return
-	} else {
-		log.Printf("Authenticated ID: %s \n", IDstr)
-	}
-}
diff --git a/go/examples-go/timempinWrap.go b/go/examples-go/timempinWrap.go
deleted file mode 100644
index 520b1a9..0000000
--- a/go/examples-go/timempinWrap.go
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
-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.
-*/
-
-package main
-
-import (
-	"encoding/hex"
-	"flag"
-	"log"
-	"os"
-	"runtime/pprof"
-	"time"
-
-	"git.apache.org/incubator-milagro-crypto.git/go/amcl-go"
-)
-
-// Number of iterations to time functions
-const nIter int = 1000
-
-var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
-
-func main() {
-	flag.Parse()
-	if *cpuprofile != "" {
-		f, err := os.Create(*cpuprofile)
-		if err != nil {
-			log.Fatal(err)
-		}
-		pprof.StartCPUProfile(f)
-		defer pprof.StopCPUProfile()
-	}
-
-	// Assign the End-User an ID
-	IDstr := "testUser@miracl.com"
-	ID := []byte(IDstr)
-
-	// Epoch time in days
-	date := 16673
-
-	// Epoch time in seconds
-	timeValue := 1440594584
-
-	SSHex := "07f8181687f42ce22ea0dee4ba9df3f2cea67ad2d79e59adc953142556d510831bbd59e9477ac479019887020579aed16af43dc7089ae8c14262e64b5d09740109917efd0618c557fbf7efaa68fb64e8d46b3766bb184dea9bef9638f23bbbeb03aedbc6e4eb9fbd658719aab26b849638690521723c0efb9c8622df2a8efa3c"
-	SS, _ := hex.DecodeString(SSHex)
-	UHex := "0403e76a28df08ea591912e0ff84ebf419e21aadf8ec5aed4b0f3cd0fc1cdea14a06f05a3be4f9f2d16530c6b4934da2e3439ea287796faac079d396f8cdb9f565"
-	U, _ := hex.DecodeString(UHex)
-	UTHex := "041012e53c991edc9514889de50fb7d893c406dc9bf4c89d46fec9ba408cc5f596226402e7c468c823a28b9003a3944c4600a1b797f10cf01060d3729729212932"
-	UT, _ := hex.DecodeString(UTHex)
-	SECHex := "04051b0d3e9dfdb2a378f0ac7056fb264a900d0867e39c334950527d8c460d76132346bf8ed8a419e2eab4ad52a8b7a51d8c09cbcfa4e80bc0487965ece72ab0ce"
-	SEC, _ := hex.DecodeString(SECHex)
-	var MESSAGE []byte
-	// MESSAGE := []byte("test sign message")
-
-	t0 := time.Now()
-	var rtn int
-	for i := 0; i < nIter; i++ {
-		rtn, _, _, _, _, _ = amcl.MPIN_SERVER_WRAP(date, timeValue, SS[:], U[:], UT[:], SEC[:], ID[:], MESSAGE[:])
-	}
-	t1 := time.Now()
-	log.Printf("Number Iterations: %d Time: %v\n", nIter, t1.Sub(t0))
-
-	if rtn != 0 {
-		log.Printf("Authentication failed Error Code %d\n", rtn)
-		return
-	} else {
-		log.Printf("Authenticated ID: %s \n", IDstr)
-	}
-}
diff --git a/go/readme.txt b/go/readme.txt
deleted file mode 100644
index d27f74d..0000000
--- a/go/readme.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-AMCL is very simple to build for Go.
-
-First - decide the modulus and curve type you want to use. Edit ROM.go 
-where indicated. You will probably want to use one of the curves whose 
-details are already in there.
-
-Three example API files are provided, MPIN.go which 
-supports our M-Pin (tm) protocol, ECDH.go which supports elliptic 
-curve key exchange, digital signature and public key crypto, and RSA.go
-which supports the RSA method.
-
-In the ROM.go file you must provide the curve constants. Several examples
-are provided there, if you are willing to use one of these.
-
-For a quick jumpstart:-
-
-export GOPATH=$PWD
-
-go run ./examples-go/mpin.go
-
-or 
-
-go run ./examples-go/ecdh.go
-
-or
-
-go run ./examples-go/rsa.go
-
diff --git a/java/AES.java b/java/AES.java
deleted file mode 100755
index 1c9d5b6..0000000
--- a/java/AES.java
+++ /dev/null
@@ -1,648 +0,0 @@
-/*
-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.
-*/
-
-
-/* AES Encryption */
-
-
-public class AES {
-	int mode;
-	private int[] fkey=new int[44];
-	private int[] rkey=new int[44];
-	public byte[] f=new byte[16];
-
-
-	public static final int ECB=0;
-	public static final int CBC=1;
-	public static final int CFB1=2;
-	public static final int CFB2=3;
-	public static final int CFB4=5;
-	public static final int OFB1=14;
-	public static final int OFB2=15;
-	public static final int OFB4=17;
-	public static final int OFB8=21;
-	public static final int OFB16=29;
-
-	private static final byte[] InCo={(byte)0xB,(byte)0xD,(byte)0x9,(byte)0xE};  /* Inverse Coefficients */
-
-	public static final int KS=16; /* Key Size in bytes */
-	public static final int BS=16; /* Block Size */
-
-	private static final byte[] ptab=
-	{(byte)1,(byte)3,(byte)5,(byte)15,(byte)17,(byte)51,(byte)85,(byte)255,(byte)26,(byte)46,(byte)114,(byte)150,(byte)161,(byte)248,(byte)19,(byte)53,
-	(byte)95,(byte)225,(byte)56,(byte)72,(byte)216,(byte)115,(byte)149,(byte)164,(byte)247,(byte)2,(byte)6,(byte)10,(byte)30,(byte)34,(byte)102,(byte)170,
-	(byte)229,(byte)52,(byte)92,(byte)228,(byte)55,(byte)89,(byte)235,(byte)38,(byte)106,(byte)190,(byte)217,(byte)112,(byte)144,(byte)171,(byte)230,(byte)49,
-	(byte)83,(byte)245,(byte)4,(byte)12,(byte)20,(byte)60,(byte)68,(byte)204,(byte)79,(byte)209,(byte)104,(byte)184,(byte)211,(byte)110,(byte)178,(byte)205,
-	(byte)76,(byte)212,(byte)103,(byte)169,(byte)224,(byte)59,(byte)77,(byte)215,(byte)98,(byte)166,(byte)241,(byte)8,(byte)24,(byte)40,(byte)120,(byte)136,
-	(byte)131,(byte)158,(byte)185,(byte)208,(byte)107,(byte)189,(byte)220,(byte)127,(byte)129,(byte)152,(byte)179,(byte)206,(byte)73,(byte)219,(byte)118,(byte)154,
-	(byte)181,(byte)196,(byte)87,(byte)249,(byte)16,(byte)48,(byte)80,(byte)240,(byte)11,(byte)29,(byte)39,(byte)105,(byte)187,(byte)214,(byte)97,(byte)163,
-	(byte)254,(byte)25,(byte)43,(byte)125,(byte)135,(byte)146,(byte)173,(byte)236,(byte)47,(byte)113,(byte)147,(byte)174,(byte)233,(byte)32,(byte)96,(byte)160,
-	(byte)251,(byte)22,(byte)58,(byte)78,(byte)210,(byte)109,(byte)183,(byte)194,(byte)93,(byte)231,(byte)50,(byte)86,(byte)250,(byte)21,(byte)63,(byte)65,
-	(byte)195,(byte)94,(byte)226,(byte)61,(byte)71,(byte)201,(byte)64,(byte)192,(byte)91,(byte)237,(byte)44,(byte)116,(byte)156,(byte)191,(byte)218,(byte)117,
-	(byte)159,(byte)186,(byte)213,(byte)100,(byte)172,(byte)239,(byte)42,(byte)126,(byte)130,(byte)157,(byte)188,(byte)223,(byte)122,(byte)142,(byte)137,(byte)128,
-	(byte)155,(byte)182,(byte)193,(byte)88,(byte)232,(byte)35,(byte)101,(byte)175,(byte)234,(byte)37,(byte)111,(byte)177,(byte)200,(byte)67,(byte)197,(byte)84,
-	(byte)252,(byte)31,(byte)33,(byte)99,(byte)165,(byte)244,(byte)7,(byte)9,(byte)27,(byte)45,(byte)119,(byte)153,(byte)176,(byte)203,(byte)70,(byte)202,
-	(byte)69,(byte)207,(byte)74,(byte)222,(byte)121,(byte)139,(byte)134,(byte)145,(byte)168,(byte)227,(byte)62,(byte)66,(byte)198,(byte)81,(byte)243,(byte)14,
-	(byte)18,(byte)54,(byte)90,(byte)238,(byte)41,(byte)123,(byte)141,(byte)140,(byte)143,(byte)138,(byte)133,(byte)148,(byte)167,(byte)242,(byte)13,(byte)23,
-	(byte)57,(byte)75,(byte)221,(byte)124,(byte)132,(byte)151,(byte)162,(byte)253,(byte)28,(byte)36,(byte)108,(byte)180,(byte)199,(byte)82,(byte)246,(byte)1};
-
-	private static final byte[] ltab=
-	{(byte)0,(byte)255,(byte)25,(byte)1,(byte)50,(byte)2,(byte)26,(byte)198,(byte)75,(byte)199,(byte)27,(byte)104,(byte)51,(byte)238,(byte)223,(byte)3,
-	(byte)100,(byte)4,(byte)224,(byte)14,(byte)52,(byte)141,(byte)129,(byte)239,(byte)76,(byte)113,(byte)8,(byte)200,(byte)248,(byte)105,(byte)28,(byte)193,
-	(byte)125,(byte)194,(byte)29,(byte)181,(byte)249,(byte)185,(byte)39,(byte)106,(byte)77,(byte)228,(byte)166,(byte)114,(byte)154,(byte)201,(byte)9,(byte)120,
-	(byte)101,(byte)47,(byte)138,(byte)5,(byte)33,(byte)15,(byte)225,(byte)36,(byte)18,(byte)240,(byte)130,(byte)69,(byte)53,(byte)147,(byte)218,(byte)142,
-	(byte)150,(byte)143,(byte)219,(byte)189,(byte)54,(byte)208,(byte)206,(byte)148,(byte)19,(byte)92,(byte)210,(byte)241,(byte)64,(byte)70,(byte)131,(byte)56,
-	(byte)102,(byte)221,(byte)253,(byte)48,(byte)191,(byte)6,(byte)139,(byte)98,(byte)179,(byte)37,(byte)226,(byte)152,(byte)34,(byte)136,(byte)145,(byte)16,
-	(byte)126,(byte)110,(byte)72,(byte)195,(byte)163,(byte)182,(byte)30,(byte)66,(byte)58,(byte)107,(byte)40,(byte)84,(byte)250,(byte)133,(byte)61,(byte)186,
-	(byte)43,(byte)121,(byte)10,(byte)21,(byte)155,(byte)159,(byte)94,(byte)202,(byte)78,(byte)212,(byte)172,(byte)229,(byte)243,(byte)115,(byte)167,(byte)87,
-	(byte)175,(byte)88,(byte)168,(byte)80,(byte)244,(byte)234,(byte)214,(byte)116,(byte)79,(byte)174,(byte)233,(byte)213,(byte)231,(byte)230,(byte)173,(byte)232,
-	(byte)44,(byte)215,(byte)117,(byte)122,(byte)235,(byte)22,(byte)11,(byte)245,(byte)89,(byte)203,(byte)95,(byte)176,(byte)156,(byte)169,(byte)81,(byte)160,
-	(byte)127,(byte)12,(byte)246,(byte)111,(byte)23,(byte)196,(byte)73,(byte)236,(byte)216,(byte)67,(byte)31,(byte)45,(byte)164,(byte)118,(byte)123,(byte)183,
-	(byte)204,(byte)187,(byte)62,(byte)90,(byte)251,(byte)96,(byte)177,(byte)134,(byte)59,(byte)82,(byte)161,(byte)108,(byte)170,(byte)85,(byte)41,(byte)157,
-	(byte)151,(byte)178,(byte)135,(byte)144,(byte)97,(byte)190,(byte)220,(byte)252,(byte)188,(byte)149,(byte)207,(byte)205,(byte)55,(byte)63,(byte)91,(byte)209,
-	(byte)83,(byte)57,(byte)132,(byte)60,(byte)65,(byte)162,(byte)109,(byte)71,(byte)20,(byte)42,(byte)158,(byte)93,(byte)86,(byte)242,(byte)211,(byte)171,
-	(byte)68,(byte)17,(byte)146,(byte)217,(byte)35,(byte)32,(byte)46,(byte)137,(byte)180,(byte)124,(byte)184,(byte)38,(byte)119,(byte)153,(byte)227,(byte)165,
-	(byte)103,(byte)74,(byte)237,(byte)222,(byte)197,(byte)49,(byte)254,(byte)24,(byte)13,(byte)99,(byte)140,(byte)128,(byte)192,(byte)247,(byte)112,(byte)7};
-
-	private static final byte[] fbsub=
-	{(byte)99,(byte)124,(byte)119,(byte)123,(byte)242,(byte)107,(byte)111,(byte)197,(byte)48,(byte)1,(byte)103,(byte)43,(byte)254,(byte)215,(byte)171,(byte)118,
-	(byte)202,(byte)130,(byte)201,(byte)125,(byte)250,(byte)89,(byte)71,(byte)240,(byte)173,(byte)212,(byte)162,(byte)175,(byte)156,(byte)164,(byte)114,(byte)192,
-	(byte)183,(byte)253,(byte)147,(byte)38,(byte)54,(byte)63,(byte)247,(byte)204,(byte)52,(byte)165,(byte)229,(byte)241,(byte)113,(byte)216,(byte)49,(byte)21,
-	(byte)4,(byte)199,(byte)35,(byte)195,(byte)24,(byte)150,(byte)5,(byte)154,(byte)7,(byte)18,(byte)128,(byte)226,(byte)235,(byte)39,(byte)178,(byte)117,
-	(byte)9,(byte)131,(byte)44,(byte)26,(byte)27,(byte)110,(byte)90,(byte)160,(byte)82,(byte)59,(byte)214,(byte)179,(byte)41,(byte)227,(byte)47,(byte)132,
-	(byte)83,(byte)209,(byte)0,(byte)237,(byte)32,(byte)252,(byte)177,(byte)91,(byte)106,(byte)203,(byte)190,(byte)57,(byte)74,(byte)76,(byte)88,(byte)207,
-	(byte)208,(byte)239,(byte)170,(byte)251,(byte)67,(byte)77,(byte)51,(byte)133,(byte)69,(byte)249,(byte)2,(byte)127,(byte)80,(byte)60,(byte)159,(byte)168,
-	(byte)81,(byte)163,(byte)64,(byte)143,(byte)146,(byte)157,(byte)56,(byte)245,(byte)188,(byte)182,(byte)218,(byte)33,(byte)16,(byte)255,(byte)243,(byte)210,
-	(byte)205,(byte)12,(byte)19,(byte)236,(byte)95,(byte)151,(byte)68,(byte)23,(byte)196,(byte)167,(byte)126,(byte)61,(byte)100,(byte)93,(byte)25,(byte)115,
-	(byte)96,(byte)129,(byte)79,(byte)220,(byte)34,(byte)42,(byte)144,(byte)136,(byte)70,(byte)238,(byte)184,(byte)20,(byte)222,(byte)94,(byte)11,(byte)219,
-	(byte)224,(byte)50,(byte)58,(byte)10,(byte)73,(byte)6,(byte)36,(byte)92,(byte)194,(byte)211,(byte)172,(byte)98,(byte)145,(byte)149,(byte)228,(byte)121,
-	(byte)231,(byte)200,(byte)55,(byte)109,(byte)141,(byte)213,(byte)78,(byte)169,(byte)108,(byte)86,(byte)244,(byte)234,(byte)101,(byte)122,(byte)174,(byte)8,
-	(byte)186,(byte)120,(byte)37,(byte)46,(byte)28,(byte)166,(byte)180,(byte)198,(byte)232,(byte)221,(byte)116,(byte)31,(byte)75,(byte)189,(byte)139,(byte)138,
-	(byte)112,(byte)62,(byte)181,(byte)102,(byte)72,(byte)3,(byte)246,(byte)14,(byte)97,(byte)53,(byte)87,(byte)185,(byte)134,(byte)193,(byte)29,(byte)158,
-	(byte)225,(byte)248,(byte)152,(byte)17,(byte)105,(byte)217,(byte)142,(byte)148,(byte)155,(byte)30,(byte)135,(byte)233,(byte)206,(byte)85,(byte)40,(byte)223,
-	(byte)140,(byte)161,(byte)137,(byte)13,(byte)191,(byte)230,(byte)66,(byte)104,(byte)65,(byte)153,(byte)45,(byte)15,(byte)176,(byte)84,(byte)187,(byte)22};
-
-	private static final byte[] rbsub=
-	{(byte)82,(byte)9,(byte)106,(byte)213,(byte)48,(byte)54,(byte)165,(byte)56,(byte)191,(byte)64,(byte)163,(byte)158,(byte)129,(byte)243,(byte)215,(byte)251,
-	(byte)124,(byte)227,(byte)57,(byte)130,(byte)155,(byte)47,(byte)255,(byte)135,(byte)52,(byte)142,(byte)67,(byte)68,(byte)196,(byte)222,(byte)233,(byte)203,
-	(byte)84,(byte)123,(byte)148,(byte)50,(byte)166,(byte)194,(byte)35,(byte)61,(byte)238,(byte)76,(byte)149,(byte)11,(byte)66,(byte)250,(byte)195,(byte)78,
-	(byte)8,(byte)46,(byte)161,(byte)102,(byte)40,(byte)217,(byte)36,(byte)178,(byte)118,(byte)91,(byte)162,(byte)73,(byte)109,(byte)139,(byte)209,(byte)37,
-	(byte)114,(byte)248,(byte)246,(byte)100,(byte)134,(byte)104,(byte)152,(byte)22,(byte)212,(byte)164,(byte)92,(byte)204,(byte)93,(byte)101,(byte)182,(byte)146,
-	(byte)108,(byte)112,(byte)72,(byte)80,(byte)253,(byte)237,(byte)185,(byte)218,(byte)94,(byte)21,(byte)70,(byte)87,(byte)167,(byte)141,(byte)157,(byte)132,
-	(byte)144,(byte)216,(byte)171,(byte)0,(byte)140,(byte)188,(byte)211,(byte)10,(byte)247,(byte)228,(byte)88,(byte)5,(byte)184,(byte)179,(byte)69,(byte)6,
-	(byte)208,(byte)44,(byte)30,(byte)143,(byte)202,(byte)63,(byte)15,(byte)2,(byte)193,(byte)175,(byte)189,(byte)3,(byte)1,(byte)19,(byte)138,(byte)107,
-	(byte)58,(byte)145,(byte)17,(byte)65,(byte)79,(byte)103,(byte)220,(byte)234,(byte)151,(byte)242,(byte)207,(byte)206,(byte)240,(byte)180,(byte)230,(byte)115,
-	(byte)150,(byte)172,(byte)116,(byte)34,(byte)231,(byte)173,(byte)53,(byte)133,(byte)226,(byte)249,(byte)55,(byte)232,(byte)28,(byte)117,(byte)223,(byte)110,
-	(byte)71,(byte)241,(byte)26,(byte)113,(byte)29,(byte)41,(byte)197,(byte)137,(byte)111,(byte)183,(byte)98,(byte)14,(byte)170,(byte)24,(byte)190,(byte)27,
-	(byte)252,(byte)86,(byte)62,(byte)75,(byte)198,(byte)210,(byte)121,(byte)32,(byte)154,(byte)219,(byte)192,(byte)254,(byte)120,(byte)205,(byte)90,(byte)244,
-	(byte)31,(byte)221,(byte)168,(byte)51,(byte)136,(byte)7,(byte)199,(byte)49,(byte)177,(byte)18,(byte)16,(byte)89,(byte)39,(byte)128,(byte)236,(byte)95,
-	(byte)96,(byte)81,(byte)127,(byte)169,(byte)25,(byte)181,(byte)74,(byte)13,(byte)45,(byte)229,(byte)122,(byte)159,(byte)147,(byte)201,(byte)156,(byte)239,
-	(byte)160,(byte)224,(byte)59,(byte)77,(byte)174,(byte)42,(byte)245,(byte)176,(byte)200,(byte)235,(byte)187,(byte)60,(byte)131,(byte)83,(byte)153,(byte)97,
-	(byte)23,(byte)43,(byte)4,(byte)126,(byte)186,(byte)119,(byte)214,(byte)38,(byte)225,(byte)105,(byte)20,(byte)99,(byte)85,(byte)33,(byte)12,(byte)125};
-
-	private static final byte[] rco=
-	{(byte)1,(byte)2,(byte)4,(byte)8,(byte)16,(byte)32,(byte)64,(byte)128,(byte)27,(byte)54,(byte)108,(byte)216,(byte)171,(byte)77,(byte)154,(byte)47};
-
-	private static final int[] ftable=
-	{0xa56363c6,0x847c7cf8,0x997777ee,0x8d7b7bf6,0xdf2f2ff,0xbd6b6bd6,
-	0xb16f6fde,0x54c5c591,0x50303060,0x3010102,0xa96767ce,0x7d2b2b56,
-	0x19fefee7,0x62d7d7b5,0xe6abab4d,0x9a7676ec,0x45caca8f,0x9d82821f,
-	0x40c9c989,0x877d7dfa,0x15fafaef,0xeb5959b2,0xc947478e,0xbf0f0fb,
-	0xecadad41,0x67d4d4b3,0xfda2a25f,0xeaafaf45,0xbf9c9c23,0xf7a4a453,
-	0x967272e4,0x5bc0c09b,0xc2b7b775,0x1cfdfde1,0xae93933d,0x6a26264c,
-	0x5a36366c,0x413f3f7e,0x2f7f7f5,0x4fcccc83,0x5c343468,0xf4a5a551,
-	0x34e5e5d1,0x8f1f1f9,0x937171e2,0x73d8d8ab,0x53313162,0x3f15152a,
-	0xc040408,0x52c7c795,0x65232346,0x5ec3c39d,0x28181830,0xa1969637,
-	0xf05050a,0xb59a9a2f,0x907070e,0x36121224,0x9b80801b,0x3de2e2df,
-	0x26ebebcd,0x6927274e,0xcdb2b27f,0x9f7575ea,0x1b090912,0x9e83831d,
-	0x742c2c58,0x2e1a1a34,0x2d1b1b36,0xb26e6edc,0xee5a5ab4,0xfba0a05b,
-	0xf65252a4,0x4d3b3b76,0x61d6d6b7,0xceb3b37d,0x7b292952,0x3ee3e3dd,
-	0x712f2f5e,0x97848413,0xf55353a6,0x68d1d1b9,0x0,0x2cededc1,
-	0x60202040,0x1ffcfce3,0xc8b1b179,0xed5b5bb6,0xbe6a6ad4,0x46cbcb8d,
-	0xd9bebe67,0x4b393972,0xde4a4a94,0xd44c4c98,0xe85858b0,0x4acfcf85,
-	0x6bd0d0bb,0x2aefefc5,0xe5aaaa4f,0x16fbfbed,0xc5434386,0xd74d4d9a,
-	0x55333366,0x94858511,0xcf45458a,0x10f9f9e9,0x6020204,0x817f7ffe,
-	0xf05050a0,0x443c3c78,0xba9f9f25,0xe3a8a84b,0xf35151a2,0xfea3a35d,
-	0xc0404080,0x8a8f8f05,0xad92923f,0xbc9d9d21,0x48383870,0x4f5f5f1,
-	0xdfbcbc63,0xc1b6b677,0x75dadaaf,0x63212142,0x30101020,0x1affffe5,
-	0xef3f3fd,0x6dd2d2bf,0x4ccdcd81,0x140c0c18,0x35131326,0x2fececc3,
-	0xe15f5fbe,0xa2979735,0xcc444488,0x3917172e,0x57c4c493,0xf2a7a755,
-	0x827e7efc,0x473d3d7a,0xac6464c8,0xe75d5dba,0x2b191932,0x957373e6,
-	0xa06060c0,0x98818119,0xd14f4f9e,0x7fdcdca3,0x66222244,0x7e2a2a54,
-	0xab90903b,0x8388880b,0xca46468c,0x29eeeec7,0xd3b8b86b,0x3c141428,
-	0x79dedea7,0xe25e5ebc,0x1d0b0b16,0x76dbdbad,0x3be0e0db,0x56323264,
-	0x4e3a3a74,0x1e0a0a14,0xdb494992,0xa06060c,0x6c242448,0xe45c5cb8,
-	0x5dc2c29f,0x6ed3d3bd,0xefacac43,0xa66262c4,0xa8919139,0xa4959531,
-	0x37e4e4d3,0x8b7979f2,0x32e7e7d5,0x43c8c88b,0x5937376e,0xb76d6dda,
-	0x8c8d8d01,0x64d5d5b1,0xd24e4e9c,0xe0a9a949,0xb46c6cd8,0xfa5656ac,
-	0x7f4f4f3,0x25eaeacf,0xaf6565ca,0x8e7a7af4,0xe9aeae47,0x18080810,
-	0xd5baba6f,0x887878f0,0x6f25254a,0x722e2e5c,0x241c1c38,0xf1a6a657,
-	0xc7b4b473,0x51c6c697,0x23e8e8cb,0x7cdddda1,0x9c7474e8,0x211f1f3e,
-	0xdd4b4b96,0xdcbdbd61,0x868b8b0d,0x858a8a0f,0x907070e0,0x423e3e7c,
-	0xc4b5b571,0xaa6666cc,0xd8484890,0x5030306,0x1f6f6f7,0x120e0e1c,
-	0xa36161c2,0x5f35356a,0xf95757ae,0xd0b9b969,0x91868617,0x58c1c199,
-	0x271d1d3a,0xb99e9e27,0x38e1e1d9,0x13f8f8eb,0xb398982b,0x33111122,
-	0xbb6969d2,0x70d9d9a9,0x898e8e07,0xa7949433,0xb69b9b2d,0x221e1e3c,
-	0x92878715,0x20e9e9c9,0x49cece87,0xff5555aa,0x78282850,0x7adfdfa5,
-	0x8f8c8c03,0xf8a1a159,0x80898909,0x170d0d1a,0xdabfbf65,0x31e6e6d7,
-	0xc6424284,0xb86868d0,0xc3414182,0xb0999929,0x772d2d5a,0x110f0f1e,
-	0xcbb0b07b,0xfc5454a8,0xd6bbbb6d,0x3a16162c};
-
-	private static final int[] rtable=
-	{0x50a7f451,0x5365417e,0xc3a4171a,0x965e273a,0xcb6bab3b,0xf1459d1f,
-	0xab58faac,0x9303e34b,0x55fa3020,0xf66d76ad,0x9176cc88,0x254c02f5,
-	0xfcd7e54f,0xd7cb2ac5,0x80443526,0x8fa362b5,0x495ab1de,0x671bba25,
-	0x980eea45,0xe1c0fe5d,0x2752fc3,0x12f04c81,0xa397468d,0xc6f9d36b,
-	0xe75f8f03,0x959c9215,0xeb7a6dbf,0xda595295,0x2d83bed4,0xd3217458,
-	0x2969e049,0x44c8c98e,0x6a89c275,0x78798ef4,0x6b3e5899,0xdd71b927,
-	0xb64fe1be,0x17ad88f0,0x66ac20c9,0xb43ace7d,0x184adf63,0x82311ae5,
-	0x60335197,0x457f5362,0xe07764b1,0x84ae6bbb,0x1ca081fe,0x942b08f9,
-	0x58684870,0x19fd458f,0x876cde94,0xb7f87b52,0x23d373ab,0xe2024b72,
-	0x578f1fe3,0x2aab5566,0x728ebb2,0x3c2b52f,0x9a7bc586,0xa50837d3,
-	0xf2872830,0xb2a5bf23,0xba6a0302,0x5c8216ed,0x2b1ccf8a,0x92b479a7,
-	0xf0f207f3,0xa1e2694e,0xcdf4da65,0xd5be0506,0x1f6234d1,0x8afea6c4,
-	0x9d532e34,0xa055f3a2,0x32e18a05,0x75ebf6a4,0x39ec830b,0xaaef6040,
-	0x69f715e,0x51106ebd,0xf98a213e,0x3d06dd96,0xae053edd,0x46bde64d,
-	0xb58d5491,0x55dc471,0x6fd40604,0xff155060,0x24fb9819,0x97e9bdd6,
-	0xcc434089,0x779ed967,0xbd42e8b0,0x888b8907,0x385b19e7,0xdbeec879,
-	0x470a7ca1,0xe90f427c,0xc91e84f8,0x0,0x83868009,0x48ed2b32,
-	0xac70111e,0x4e725a6c,0xfbff0efd,0x5638850f,0x1ed5ae3d,0x27392d36,
-	0x64d90f0a,0x21a65c68,0xd1545b9b,0x3a2e3624,0xb1670a0c,0xfe75793,
-	0xd296eeb4,0x9e919b1b,0x4fc5c080,0xa220dc61,0x694b775a,0x161a121c,
-	0xaba93e2,0xe52aa0c0,0x43e0223c,0x1d171b12,0xb0d090e,0xadc78bf2,
-	0xb9a8b62d,0xc8a91e14,0x8519f157,0x4c0775af,0xbbdd99ee,0xfd607fa3,
-	0x9f2601f7,0xbcf5725c,0xc53b6644,0x347efb5b,0x7629438b,0xdcc623cb,
-	0x68fcedb6,0x63f1e4b8,0xcadc31d7,0x10856342,0x40229713,0x2011c684,
-	0x7d244a85,0xf83dbbd2,0x1132f9ae,0x6da129c7,0x4b2f9e1d,0xf330b2dc,
-	0xec52860d,0xd0e3c177,0x6c16b32b,0x99b970a9,0xfa489411,0x2264e947,
-	0xc48cfca8,0x1a3ff0a0,0xd82c7d56,0xef903322,0xc74e4987,0xc1d138d9,
-	0xfea2ca8c,0x360bd498,0xcf81f5a6,0x28de7aa5,0x268eb7da,0xa4bfad3f,
-	0xe49d3a2c,0xd927850,0x9bcc5f6a,0x62467e54,0xc2138df6,0xe8b8d890,
-	0x5ef7392e,0xf5afc382,0xbe805d9f,0x7c93d069,0xa92dd56f,0xb31225cf,
-	0x3b99acc8,0xa77d1810,0x6e639ce8,0x7bbb3bdb,0x97826cd,0xf418596e,
-	0x1b79aec,0xa89a4f83,0x656e95e6,0x7ee6ffaa,0x8cfbc21,0xe6e815ef,
-	0xd99be7ba,0xce366f4a,0xd4099fea,0xd67cb029,0xafb2a431,0x31233f2a,
-	0x3094a5c6,0xc066a235,0x37bc4e74,0xa6ca82fc,0xb0d090e0,0x15d8a733,
-	0x4a9804f1,0xf7daec41,0xe50cd7f,0x2ff69117,0x8dd64d76,0x4db0ef43,
-	0x544daacc,0xdf0496e4,0xe3b5d19e,0x1b886a4c,0xb81f2cc1,0x7f516546,
-	0x4ea5e9d,0x5d358c01,0x737487fa,0x2e410bfb,0x5a1d67b3,0x52d2db92,
-	0x335610e9,0x1347d66d,0x8c61d79a,0x7a0ca137,0x8e14f859,0x893c13eb,
-	0xee27a9ce,0x35c961b7,0xede51ce1,0x3cb1477a,0x59dfd29c,0x3f73f255,
-	0x79ce1418,0xbf37c773,0xeacdf753,0x5baafd5f,0x146f3ddf,0x86db4478,
-	0x81f3afca,0x3ec468b9,0x2c342438,0x5f40a3c2,0x72c31d16,0xc25e2bc,
-	0x8b493c28,0x41950dff,0x7101a839,0xdeb30c08,0x9ce4b4d8,0x90c15664,
-	0x6184cb7b,0x70b632d5,0x745c6c48,0x4257b8d0};
-
-
-/* Rotates 32-bit word left by 1, 2 or 3 byte  */
-
-	private static int ROTL8(int x)
-	{
-		return (((x)<<8)|((x)>>>24));
-	}
-
-	private static int ROTL16(int x)
-	{
-		return (((x)<<16)|((x)>>>16));
-	}
-
-	private static int ROTL24(int x)
-	{
-		return (((x)<<24)|((x)>>>8));
-	}
-
-	private static int pack(byte[] b)
-	{ /* pack bytes into a 32-bit Word */
-		return ((((int)b[3])&0xff)<<24)|(((int)b[2]&0xff)<<16)|(((int)b[1]&0xff)<<8)|((int)b[0]&0xff);
-	}
-
-	private static byte[] unpack(int a)
-	{ /* unpack bytes from a word */
-		byte [] b=new byte[4];
-		b[0]=(byte)(a);
-		b[1]=(byte)(a>>>8);
-		b[2]=(byte)(a>>>16);
-		b[3]=(byte)(a>>>24);
-		return b;
-	}
-
-	private static byte bmul(byte x,byte y)
-	{ /* x.y= AntiLog(Log(x) + Log(y)) */
-
-		int ix=((int)x)&0xff;
-		int iy=((int)y)&0xff;
-		int lx=((int)ltab[ix])&0xff;
-		int ly=((int)ltab[iy])&0xff;
-		if (x!=0 && y!=0) return ptab[(lx+ly)%255];
-		else return (byte)0;
-	}
-
-  //  if (x && y)
-
-	private static int SubByte(int a)
-	{
-		byte [] b=unpack(a);
-		b[0]=fbsub[(int)b[0]&0xff];
-		b[1]=fbsub[(int)b[1]&0xff];
-		b[2]=fbsub[(int)b[2]&0xff];
-		b[3]=fbsub[(int)b[3]&0xff];
-		return pack(b);
-	}
-
-	private static byte product(int x,int y)
-	{ /* dot product of two 4-byte arrays */
-		byte [] xb;//=new byte[4];
-		byte [] yb;//=new byte[4];
-		xb=unpack(x);
-		yb=unpack(y);
-
-		return (byte)(bmul(xb[0],yb[0])^bmul(xb[1],yb[1])^bmul(xb[2],yb[2])^bmul(xb[3],yb[3]));
-	}
-
-	private static int InvMixCol(int x)
-	{ /* matrix Multiplication */
-		int y,m;
-		byte [] b=new byte[4];
-
-		m=pack(InCo);
-		b[3]=product(m,x);
-		m=ROTL24(m);
-		b[2]=product(m,x);
-		m=ROTL24(m);
-		b[1]=product(m,x);
-		m=ROTL24(m);
-		b[0]=product(m,x);
-		y=pack(b);
-		return y;
-	}
-
-/* reset cipher */
-	public void reset(int m,byte[] iv)
-	{ /* reset mode, or reset iv */
-		mode=m;
-		for (int i=0;i<16;i++)
-			f[i]=0;
-		if (mode!=ECB && iv!=null)
-			for (int i=0;i<16;i++)
-				f[i]=iv[i];
-	}
-
-	public byte[] getreg()
-	{
-		byte [] ir=new byte[16];
-		for (int i=0;i<16;i++) ir[i]=f[i];
-		return ir;
-	}
-
-/* Initialise cipher */
-	public void init(int m,byte[] key,byte[] iv)
-	{	/* Key=16 bytes */
-		/* Key Scheduler. Create expanded encryption key */
-		int i,j,k,N,nk;
-		int [] CipherKey=new int[4];
-    	byte [] b=new byte[4];
-		nk=4;
-		reset(m,iv);
-		N=44;
-
-		for (i=j=0;i<nk;i++,j+=4)
-		{
-			for (k=0;k<4;k++) b[k]=key[j+k];
-			CipherKey[i]=pack(b);
-		}
-		for (i=0;i<nk;i++) fkey[i]=CipherKey[i];
-		for (j=nk,k=0;j<N;j+=nk,k++)
-		{
-			fkey[j]=fkey[j-nk]^SubByte(ROTL24(fkey[j-1]))^((int)rco[k])&0xff;
-			for (i=1;i<nk && (i+j)<N;i++)
-				fkey[i+j]=fkey[i+j-nk]^fkey[i+j-1];
-		}
-
- /* now for the expanded decrypt key in reverse order */
-
-		for (j=0;j<4;j++) rkey[j+N-4]=fkey[j];
-		for (i=4;i<N-4;i+=4)
-		{
-			k=N-4-i;
-			for (j=0;j<4;j++) rkey[k+j]=InvMixCol(fkey[i+j]);
-		}
-		for (j=N-4;j<N;j++) rkey[j-N+4]=fkey[j];
-	}
-
-/* Encrypt a single block */
-	public void ecb_encrypt(byte[] buff)
-	{
-		int i,j,k;
-		int t;
-    	byte [] b=new byte[4];
-    	int [] p=new int[4];
-    	int [] q=new int[4];
-
-		for (i=j=0;i<4;i++,j+=4)
-		{
-			for (k=0;k<4;k++) b[k]=buff[j+k];
-			p[i]=pack(b);
-			p[i]^=fkey[i];
-		}
-
-		k=4;
-
-/* State alternates between p and q */
-		for (i=1;i<10;i++)
-		{
-			q[0]=fkey[k]^ftable[p[0]&0xff]^
-				ROTL8(ftable[(p[1]>>>8)&0xff])^
-				ROTL16(ftable[(p[2]>>>16)&0xff])^
-				ROTL24(ftable[(p[3]>>>24)&0xff]);
-			q[1]=fkey[k+1]^ftable[p[1]&0xff]^
-				ROTL8(ftable[(p[2]>>>8)&0xff])^
-				ROTL16(ftable[(p[3]>>>16)&0xff])^
-				ROTL24(ftable[(p[0]>>>24)&0xff]);
-			q[2]=fkey[k+2]^ftable[p[2]&0xff]^
-				ROTL8(ftable[(p[3]>>>8)&0xff])^
-				ROTL16(ftable[(p[0]>>>16)&0xff])^
-				ROTL24(ftable[(p[1]>>>24)&0xff]);
-			q[3]=fkey[k+3]^ftable[p[3]&0xff]^
-				ROTL8(ftable[(p[0]>>>8)&0xff])^
-				ROTL16(ftable[(p[1]>>>16)&0xff])^
-				ROTL24(ftable[(p[2]>>>24)&0xff]);
-
-			k+=4;
-			for (j=0;j<4;j++)
-			{
-				t=p[j]; p[j]=q[j]; q[j]=t;
-			}
-		}
-
-/* Last Round */
-
-		q[0]=fkey[k]^((int)fbsub[p[0]&0xff]&0xff)^
-			ROTL8((int)fbsub[(p[1]>>>8)&0xff]&0xff)^
-			ROTL16((int)fbsub[(p[2]>>>16)&0xff]&0xff)^
-			ROTL24((int)fbsub[(p[3]>>>24)&0xff]&0xff);
-
-		q[1]=fkey[k+1]^((int)fbsub[p[1]&0xff]&0xff)^
-			ROTL8((int)fbsub[(p[2]>>>8)&0xff]&0xff)^
-			ROTL16((int)fbsub[(p[3]>>>16)&0xff]&0xff)^
-			ROTL24((int)fbsub[(p[0]>>>24)&0xff]&0xff);
-
-		q[2]=fkey[k+2]^((int)fbsub[p[2]&0xff]&0xff)^
-			ROTL8((int)fbsub[(p[3]>>>8)&0xff]&0xff)^
-			ROTL16((int)fbsub[(p[0]>>>16)&0xff]&0xff)^
-			ROTL24((int)fbsub[(p[1]>>>24)&0xff]&0xff);
-
-		q[3]=fkey[k+3]^((int)fbsub[(p[3])&0xff]&0xff)^
-			ROTL8((int)fbsub[(p[0]>>>8)&0xff]&0xff)^
-			ROTL16((int)fbsub[(p[1]>>>16)&0xff]&0xff)^
-			ROTL24((int)fbsub[(p[2]>>>24)&0xff]&0xff);
-
-		for (i=j=0;i<4;i++,j+=4)
-		{
-			b=unpack(q[i]);
-			for (k=0;k<4;k++) buff[j+k]=b[k];
-		}
-	}
-
-/* Decrypt a single block */
-	public void ecb_decrypt(byte[] buff)
-	{
-		int i,j,k;
-		int t;
-    	byte [] b=new byte[4];
-    	int [] p=new int[4];
-    	int [] q=new int[4];
-
-		for (i=j=0;i<4;i++,j+=4)
-		{
-			for (k=0;k<4;k++) b[k]=buff[j+k];
-			p[i]=pack(b);
-			p[i]^=rkey[i];
-		}
-
-		k=4;
-
-/* State alternates between p and q */
-		for (i=1;i<10;i++)
-		{
-			q[0]=rkey[k]^rtable[p[0]&0xff]^
-				ROTL8(rtable[(p[3]>>>8)&0xff])^
-				ROTL16(rtable[(p[2]>>>16)&0xff])^
-				ROTL24(rtable[(p[1]>>>24)&0xff]);
-			q[1]=rkey[k+1]^rtable[p[1]&0xff]^
-				ROTL8(rtable[(p[0]>>>8)&0xff])^
-				ROTL16(rtable[(p[3]>>>16)&0xff])^
-				ROTL24(rtable[(p[2]>>>24)&0xff]);
-			q[2]=rkey[k+2]^rtable[p[2]&0xff]^
-				ROTL8(rtable[(p[1]>>>8)&0xff])^
-				ROTL16(rtable[(p[0]>>>16)&0xff])^
-				ROTL24(rtable[(p[3]>>>24)&0xff]);
-			q[3]=rkey[k+3]^rtable[p[3]&0xff]^
-				ROTL8(rtable[(p[2]>>>8)&0xff])^
-				ROTL16(rtable[(p[1]>>>16)&0xff])^
-				ROTL24(rtable[(p[0]>>>24)&0xff]);
-
-			k+=4;
-			for (j=0;j<4;j++)
-			{
-				t=p[j]; p[j]=q[j]; q[j]=t;
-			}
-		}
-
-/* Last Round */
-
-		q[0]=rkey[k]^((int)rbsub[p[0]&0xff]&0xff)^
-			ROTL8((int)rbsub[(p[3]>>>8)&0xff]&0xff)^
-			ROTL16((int)rbsub[(p[2]>>>16)&0xff]&0xff)^
-			ROTL24((int)rbsub[(p[1]>>>24)&0xff]&0xff);
-		q[1]=rkey[k+1]^((int)rbsub[p[1]&0xff]&0xff)^
-			ROTL8((int)rbsub[(p[0]>>>8)&0xff]&0xff)^
-			ROTL16((int)rbsub[(p[3]>>>16)&0xff]&0xff)^
-			ROTL24((int)rbsub[(p[2]>>>24)&0xff]&0xff);
-		q[2]=rkey[k+2]^((int)rbsub[p[2]&0xff]&0xff)^
-			ROTL8((int)rbsub[(p[1]>>>8)&0xff]&0xff)^
-			ROTL16((int)rbsub[(p[0]>>>16)&0xff]&0xff)^
-			ROTL24((int)rbsub[(p[3]>>>24)&0xff]&0xff);
-		q[3]=rkey[k+3]^((int)rbsub[p[3]&0xff]&0xff)^
-			ROTL8((int)rbsub[(p[2]>>>8)&0xff]&0xff)^
-			ROTL16((int)rbsub[(p[1]>>>16)&0xff]&0xff)^
-			ROTL24((int)rbsub[(p[0]>>>24)&0xff]&0xff);
-
-		for (i=j=0;i<4;i++,j+=4)
-		{
-			b=unpack(q[i]);
-			for (k=0;k<4;k++) buff[j+k]=b[k];
-		}
-
-	}
-
-/* Encrypt using selected mode of operation */
-	public int encrypt(byte[] buff)
-	{
-		int j,bytes;
-		byte[] st=new byte[16];
-		int fell_off;
-
-// Supported Modes of Operation
-
-		fell_off=0;
-		switch (mode)
-		{
-		case ECB:
-			ecb_encrypt(buff);
-			return 0;
-		case CBC:
-			for (j=0;j<16;j++) buff[j]^=f[j];
-			ecb_encrypt(buff);
-			for (j=0;j<16;j++) f[j]=buff[j];
-			return 0;
-
-		case CFB1:
-		case CFB2:
-		case CFB4:
-			bytes=mode-CFB1+1;
-			for (j=0;j<bytes;j++) fell_off=(fell_off<<8)|f[j];
-			for (j=0;j<16;j++) st[j]=f[j];
-			for (j=bytes;j<16;j++) f[j-bytes]=f[j];
-			ecb_encrypt(st);
-			for (j=0;j<bytes;j++)
-			{
-				buff[j]^=st[j];
-				f[16-bytes+j]=buff[j];
-			}
-			return fell_off;
-
-		case OFB1:
-		case OFB2:
-		case OFB4:
-		case OFB8:
-		case OFB16:
-
-			bytes=mode-OFB1+1;
-			ecb_encrypt(f);
-			for (j=0;j<bytes;j++) buff[j]^=f[j];
-			return 0;
-
-    default:
-			return 0;
-		}
-	}
-
-/* Decrypt using selected mode of operation */
-	public int decrypt(byte[] buff)
-	{
-		int j,bytes;
-		byte[] st=new byte[16];
-		int fell_off;
-
-   // Supported modes of operation
-		fell_off=0;
-		switch (mode)
-		{
-		case ECB:
-			ecb_decrypt(buff);
-			return 0;
-		case CBC:
-			for (j=0;j<16;j++)
-			{
-				st[j]=f[j];
-				f[j]=buff[j];
-			}
-			ecb_decrypt(buff);
-			for (j=0;j<16;j++)
-			{
-				buff[j]^=st[j];
-				st[j]=0;
-			}
-			return 0;
-		case CFB1:
-		case CFB2:
-		case CFB4:
-			bytes=mode-CFB1+1;
-			for (j=0;j<bytes;j++) fell_off=(fell_off<<8)|f[j];
-			for (j=0;j<16;j++) st[j]=f[j];
-			for (j=bytes;j<16;j++) f[j-bytes]=f[j];
-			ecb_encrypt(st);
-			for (j=0;j<bytes;j++)
-			{
-				f[16-bytes+j]=buff[j];
-				buff[j]^=st[j];
-			}
-			return fell_off;
-		case OFB1:
-		case OFB2:
-		case OFB4:
-		case OFB8:
-		case OFB16:
-			bytes=mode-OFB1+1;
-			ecb_encrypt(f);
-			for (j=0;j<bytes;j++) buff[j]^=f[j];
-			return 0;
-
-
-		default:
-			return 0;
-		}
-	}
-
-/* Clean up and delete left-overs */
-	public void end()
-	{ // clean up
-		int i;
-		for (i=0;i<44;i++)
-			fkey[i]=rkey[i]=0;
-		for (i=0;i<16;i++)
-			f[i]=0;
-	}
-
-	public static void main(String[] args) {
-		int i;
-
-		byte[] key=new byte[16];
-		byte[] block=new byte[16];
-		byte[] iv=new byte[16];
-
-		for (i=0;i<16;i++) key[i]=0;
-		key[0]=1;
-		for (i=0;i<16;i++) iv[i]=(byte)i;
-		for (i=0;i<16;i++) block[i]=(byte)i;
-
-		AES a=new AES();
-
-		a.init(CBC,key,iv);
-		System.out.println("Plain= ");
-		for (i=0;i<16;i++)  System.out.format("%02X ", block[i]&0xff);
-		System.out.println("");
-
-		a.encrypt(block);
-
-		System.out.println("Encrypt= ");
-		for (i=0;i<16;i++)  System.out.format("%02X ", block[i]&0xff);
-		System.out.println("");
-
-		a.reset(CBC,iv);
-		a.decrypt(block);
-
-		System.out.println("Decrypt= ");
-		for (i=0;i<16;i++)  System.out.format("%02X ", block[i]&0xff);
-		System.out.println("");
-
-		a.end();
-
-	}
-}
diff --git a/java/BIG.java b/java/BIG.java
deleted file mode 100755
index 1a7c884..0000000
--- a/java/BIG.java
+++ /dev/null
@@ -1,919 +0,0 @@
-/*
-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.
-*/
-
-/* AMCL BIG number class */
-
-public class BIG {
-	private int[] w=new int[ROM.NLEN];
-/* Constructors */
-
-	public BIG()
-	{
-		for (int i=0;i<ROM.NLEN;i++)
-			w[i]=0;
-	}
-
-	public BIG(int x)
-	{
-		w[0]=x;
-		for (int i=1;i<ROM.NLEN;i++)
-			w[i]=0;
-	}
-
-	public BIG(BIG x)
-	{
-		for (int i=0;i<ROM.NLEN;i++)
-			w[i]=x.w[i];
-	}
-
-	public BIG(DBIG x)
-	{
-		for (int i=0;i<ROM.NLEN;i++)
-			w[i]=x.w[i];
-	}
-
-	public BIG(int[] x)
-	{
-		for (int i=0;i<ROM.NLEN;i++)
-			w[i]=x[i];
-	}
-
-	public int get(int i)
-	{
-		return w[i];
-	}
-
-	public void set(int i,int x)
-	{
-		w[i]=x;
-	}
-
-	public void xortop(int x)
-	{
-		w[ROM.NLEN-1]^=x;
-	}
-
-	public void ortop(int x)
-	{
-		w[ROM.NLEN-1]|=x;
-	}
-
-/* calculate Field Excess */
-	public static int EXCESS(BIG a)
-	{
-		return ((a.w[ROM.NLEN-1]&ROM.OMASK)>>(ROM.MODBITS%ROM.BASEBITS));
-	}
-
-/* test for zero */
-	public boolean iszilch() {
-		for (int i=0;i<ROM.NLEN;i++)
-			if (w[i]!=0) return false;
-		return true;
-	}
-
-/* set to zero */
-	public void zero()
-	{
-		for (int i=0;i<ROM.NLEN;i++)
-			w[i]=0;
-	}
-
-/* set to one */
-	public void one()
-	{
-		w[0]=1;
-		for (int i=1;i<ROM.NLEN;i++)
-			w[i]=0;
-	}
-
-/* Test for equal to one */
-	public boolean isunity()
-	{
-		for (int i=1;i<ROM.NLEN;i++)
-			if (w[i]!=0) return false;
-		if (w[0]!=1) return false;
-		return true;
-	}
-
-/* Copy from another BIG */
-	public void copy(BIG x)
-	{
-		for (int i=0;i<ROM.NLEN;i++)
-			w[i]=x.w[i];
-	}
-
-	public void copy(DBIG x)
-	{
-		for (int i=0;i<ROM.NLEN;i++)
-			w[i]=x.w[i];
-	}
-
-
-/* Conditional swap of two bigs depending on d using XOR - no branches */
-	public void cswap(BIG b,int d)
-	{
-		int i;
-		int t,c=d;
-		c=~(c-1);
-
-		for (i=0;i<ROM.NLEN;i++)
-		{
-			t=c&(w[i]^b.w[i]);
-			w[i]^=t;
-			b.w[i]^=t;
-		}
-	}
-
-	public void cmove(BIG g,int d)
-	{
-		int i;
-		int t,b=-d;
-
-		for (i=0;i<ROM.NLEN;i++)
-		{
-			w[i]^=(w[i]^g.w[i])&b;
-		}
-	}
-
-/* normalise BIG - force all digits < 2^BASEBITS */
-	public int norm() {
-		int d,carry=0;
-		for (int i=0;i<ROM.NLEN-1;i++)
-		{
-			d=w[i]+carry;
-			w[i]=d&ROM.MASK;
-			carry=d>>ROM.BASEBITS;
-		}
-		w[ROM.NLEN-1]=(w[ROM.NLEN-1]+carry);
-
-		return (w[ROM.NLEN-1]>>((8*ROM.MODBYTES)%ROM.BASEBITS));
-	}
-
-/* Shift right by less than a word */
-	public int fshr(int k) {
-		int r=w[0]&(((int)1<<k)-1); /* shifted out part */
-		for (int i=0;i<ROM.NLEN-1;i++)
-			w[i]=(w[i]>>k)|((w[i+1]<<(ROM.BASEBITS-k))&ROM.MASK);
-		w[ROM.NLEN-1]=w[ROM.NLEN-1]>>k;
-		return r;
-	}
-
-/* general shift right */
-	public void shr(int k) {
-		int n=k%ROM.BASEBITS;
-		int m=k/ROM.BASEBITS;
-		for (int i=0;i<ROM.NLEN-m-1;i++)
-			w[i]=(w[m+i]>>n)|((w[m+i+1]<<(ROM.BASEBITS-n))&ROM.MASK);
-		w[ROM.NLEN-m-1]=w[ROM.NLEN-1]>>n;
-		for (int i=ROM.NLEN-m;i<ROM.NLEN;i++) w[i]=0;
-	}
-
-/* Shift right by less than a word */
-	public int fshl(int k) {
-		w[ROM.NLEN-1]=((w[ROM.NLEN-1]<<k))|(w[ROM.NLEN-2]>>(ROM.BASEBITS-k));
-		for (int i=ROM.NLEN-2;i>0;i--)
-			w[i]=((w[i]<<k)&ROM.MASK)|(w[i-1]>>(ROM.BASEBITS-k));
-		w[0]=(w[0]<<k)&ROM.MASK;
-
-		return (w[ROM.NLEN-1]>>((8*ROM.MODBYTES)%ROM.BASEBITS)); /* return excess - only used in FF.java */
-	}
-
-/* general shift left */
-	public void shl(int k) {
-		int n=k%ROM.BASEBITS;
-		int m=k/ROM.BASEBITS;
-
-		w[ROM.NLEN-1]=((w[ROM.NLEN-1-m]<<n))|(w[ROM.NLEN-m-2]>>(ROM.BASEBITS-n));
-		for (int i=ROM.NLEN-2;i>m;i--)
-			w[i]=((w[i-m]<<n)&ROM.MASK)|(w[i-m-1]>>(ROM.BASEBITS-n));
-		w[m]=(w[0]<<n)&ROM.MASK;
-		for (int i=0;i<m;i++) w[i]=0;
-	}
-
-/* return number of bits */
-	public int nbits() {
-		int bts,k=ROM.NLEN-1;
-		int c;
-		norm();
-		while (k>=0 && w[k]==0) k--;
-		if (k<0) return 0;
-		bts=ROM.BASEBITS*k;
-		c=w[k];
-		while (c!=0) {c/=2; bts++;}
-		return bts;
-	}
-
-	public String toRawString()
-	{
-		BIG b=new BIG(this);
-		String s="(";
-		for (int i=0;i<ROM.NLEN-1;i++)
-		{
-			s+=Integer.toHexString(b.w[i]); s+=",";
-		}
-		s+=Integer.toHexString(b.w[ROM.NLEN-1]); s+=")";
-		return s;
-	}
-
-/* Convert to Hex String */
-	public String toString() {
-		BIG b;
-		String s="";
-		int len=nbits();
-
-		if (len%4==0) len/=4;
-		else {len/=4; len++;}
-		if (len<ROM.MODBYTES*2) len=ROM.MODBYTES*2;
-
-		for (int i=len-1;i>=0;i--)
-		{
-			b=new BIG(this);
-			b.shr(i*4);
-			s+=Integer.toHexString(b.w[0]&15);
-		}
-		return s;
-	}
-
-/* return this+x */
-	public BIG plus(BIG x) {
-		BIG s=new BIG(0);
-		for (int i=0;i<ROM.NLEN;i++)
-			s.w[i]=w[i]+x.w[i];
-		return s;
-	}
-
-/* this+=x */
-	public void add(BIG x) {
-		for (int i=0;i<ROM.NLEN;i++)
-			w[i]+=x.w[i];
-	}
-
-/* this+=x, where x is int */
-	public void inc(int x) {
-		norm();
-		w[0]+=x;
-	}
-
-/* return this.x */
-	public BIG minus(BIG x) {
-		BIG d=new BIG(0);
-		for (int i=0;i<ROM.NLEN;i++)
-			d.w[i]=w[i]-x.w[i];
-		return d;
-	}
-
-/* this-=x */
-	public void sub(BIG x) {
-		for (int i=0;i<ROM.NLEN;i++)
-			w[i]-=x.w[i];
-	}
-
-/* reverse subtract this=x-this */
-	public void rsub(BIG x) {
-		for (int i=0;i<ROM.NLEN;i++)
-			w[i]=x.w[i]-w[i];
-	}
-
-/* this-=x where x is int */
-	public void dec(int x) {
-		norm();
-		w[0]-=x;
-	}
-
-/* this*=x, where x is small int<NEXCESS */
-	public void imul(int c)
-	{
-		for (int i=0;i<ROM.NLEN;i++) w[i]*=c;
-	}
-
-/* convert this BIG to byte array */
-	public void tobytearray(byte[] b,int n)
-	{
-		norm();
-		BIG c=new BIG(this);
-
-		for (int i=ROM.MODBYTES-1;i>=0;i--)
-		{
-			b[i+n]=(byte)c.w[0];
-			c.fshr(8);
-		}
-	}
-
-/* convert from byte array to BIG */
-	public static BIG frombytearray(byte[] b,int n)
-	{
-		BIG m=new BIG(0);
-
-		for (int i=0;i<ROM.MODBYTES;i++)
-		{
-			m.fshl(8); m.w[0]+=(int)b[i+n]&0xff;
-			//m.inc((int)b[i]&0xff);
-		}
-		return m;
-	}
-
-	public void toBytes(byte[] b)
-	{
-		tobytearray(b,0);
-	}
-
-	public static BIG fromBytes(byte[] b)
-	{
-		return frombytearray(b,0);
-	}
-
-/* set this[i]+=x*y+c, and return high part */
-	public int muladd(int x,int y,int c,int i)
-	{
-		long prod=(long)x*y+c+w[i];
-		w[i]=(int)prod&ROM.MASK;
-		return (int)(prod>>ROM.BASEBITS);
-	}
-
-/* this*=x, where x is >NEXCESS */
-	public int pmul(int c)
-	{
-		int ak,carry=0;
-		norm();
-		for (int i=0;i<ROM.NLEN;i++)
-		{
-			ak=w[i];
-			w[i]=0;
-			carry=muladd(ak,c,carry,i);
-		}
-		return carry;
-	}
-
-/* this*=c and catch overflow in DBIG */
-	public DBIG pxmul(int c)
-	{
-		DBIG m=new DBIG(0);
-		int carry=0;
-		for (int j=0;j<ROM.NLEN;j++)
-			carry=m.muladd(w[j],c,carry,j);
-		m.w[ROM.NLEN]=carry;
-		return m;
-	}
-
-/* divide by 3 */
-	public int div3()
-	{
-		int ak,base,carry=0;
-		norm();
-		base=((int)1<<ROM.BASEBITS);
-		for (int i=ROM.NLEN-1;i>=0;i--)
-		{
-			ak=(carry*base+w[i]);
-			w[i]=ak/3;
-			carry=ak%3;
-		}
-		return (int)carry;
-	}
-
-/* return a*b where result fits in a BIG */
-	public static BIG smul(BIG a,BIG b)
-	{
-		int carry;
-		BIG c=new BIG(0);
-		for (int i=0;i<ROM.NLEN;i++)
-		{
-			carry=0;
-			for (int j=0;j<ROM.NLEN;j++)
-				if (i+j<ROM.NLEN) carry=c.muladd(a.w[i],b.w[j],carry,i+j);
-		}
-		return c;
-	}
-
-/* Compare a and b, return 0 if a==b, -1 if a<b, +1 if a>b. Inputs must be normalised */
-	public static int comp(BIG a,BIG b)
-	{
-		for (int i=ROM.NLEN-1;i>=0;i--)
-		{
-			if (a.w[i]==b.w[i]) continue;
-			if (a.w[i]>b.w[i]) return 1;
-			else  return -1;
-		}
-		return 0;
-	}
-
-/* set x = x mod 2^m */
-	public void mod2m(int m)
-	{
-		int i,wd,bt;
-		int msk;
-
-		wd=m/ROM.BASEBITS;
-		bt=m%ROM.BASEBITS;
-		msk=((int)1<<bt)-1;
-		w[wd]&=msk;
-		for (i=wd+1;i<ROM.NLEN;i++) w[i]=0;
-	}
-
-/* Arazi and Qi inversion mod 256 */
-	public static int invmod256(int a)
-	{
-		int U,t1,t2,b,c;
-		t1=0;
-		c=(a>>1)&1;
-		t1+=c;
-		t1&=1;
-		t1=2-t1;
-		t1<<=1;
-		U=t1+1;
-
-// i=2
-		b=a&3;
-		t1=U*b; t1>>=2;
-		c=(a>>2)&3;
-		t2=(U*c)&3;
-		t1+=t2;
-		t1*=U; t1&=3;
-		t1=4-t1;
-		t1<<=2;
-		U+=t1;
-
-// i=4
-		b=a&15;
-		t1=U*b; t1>>=4;
-		c=(a>>4)&15;
-		t2=(U*c)&15;
-		t1+=t2;
-		t1*=U; t1&=15;
-		t1=16-t1;
-		t1<<=4;
-		U+=t1;
-
-		return U;
-	}
-
-/* a=1/a mod 2^256. This is very fast! */
-	public void invmod2m()
-	{
-		int i;
-		BIG U=new BIG(0);
-		BIG b=new BIG(0);
-		BIG c=new BIG(0);
-
-		U.inc(invmod256(lastbits(8)));
-
-		for (i=8;i<256;i<<=1)
-		{
-			b.copy(this); b.mod2m(i);
-			BIG t1=BIG.smul(U,b); t1.shr(i);
-			c.copy(this); c.shr(i); c.mod2m(i);
-
-			BIG t2=BIG.smul(U,c); t2.mod2m(i);
-			t1.add(t2);
-			b=BIG.smul(t1,U); t1.copy(b);
-			t1.mod2m(i);
-
-			t2.one(); t2.shl(i); t1.rsub(t2); t1.norm();
-			t1.shl(i);
-			U.add(t1);
-		}
-		this.copy(U);
-	}
-
-/* reduce this mod m */
-	public void mod(BIG m)
-	{
-		int k=0;
-
-		norm();
-		if (comp(this,m)<0) return;
-		do
-		{
-			m.fshl(1);
-			k++;
-		} while (comp(this,m)>=0);
-
-		while (k>0)
-		{
-			m.fshr(1);
-			if (comp(this,m)>=0)
-			{
-				sub(m);
-				norm();
-			}
-			k--;
-		}
-	}
-
-/* divide this by m */
-	public void div(BIG m)
-	{
-		int k=0;
-		norm();
-		BIG e=new BIG(1);
-		BIG b=new BIG(this);
-		zero();
-
-		while (comp(b,m)>=0)
-		{
-			e.fshl(1);
-			m.fshl(1);
-			k++;
-		}
-
-		while (k>0)
-		{
-			m.fshr(1);
-			e.fshr(1);
-			if (comp(b,m)>=0)
-			{
-				add(e);
-				norm();
-				b.sub(m);
-				b.norm();
-			}
-			k--;
-		}
-	}
-
-/* return parity */
-	public int parity()
-	{
-		return w[0]%2;
-	}
-
-/* return n-th bit */
-	public int bit(int n)
-	{
-		if ((w[n/ROM.BASEBITS]&((int)1<<(n%ROM.BASEBITS)))>0) return 1;
-		else return 0;
-	}
-
-/* return n last bits */
-	public int lastbits(int n)
-	{
-		int msk=(1<<n)-1;
-		norm();
-		return ((int)w[0])&msk;
-	}
-
-/* get 8*MODBYTES size random number */
-	public static BIG random(RAND rng)
-	{
-		BIG m=new BIG(0);
-		int i,b,j=0,r=0;
-
-/* generate random BIG */
-		for (i=0;i<8*ROM.MODBYTES;i++)
-		{
-			if (j==0) r=rng.getByte();
-			else r>>=1;
-
-			b=r&1;
-			m.shl(1); m.w[0]+=b;// m.inc(b);
-			j++; j&=7;
-		}
-		return m;
-	}
-
-/* Create random BIG in portable way, one bit at a time */
-	public static BIG randomnum(BIG q,RAND rng)
-	{
-		DBIG d=new DBIG(0);
-		int i,b,j=0,r=0;
-		for (i=0;i<2*ROM.MODBITS;i++)
-		{
-			if (j==0) r=rng.getByte();
-			else r>>=1;
-
-			b=r&1;
-			d.shl(1); d.w[0]+=b;// m.inc(b);
-			j++; j&=7;
-		}
-		BIG m=d.mod(q);
-		return m;
-	}
-
-/* return NAF value as +/- 1, 3 or 5. x and x3 should be normed.
-nbs is number of bits processed, and nzs is number of trailing 0s detected */
-	public static int[] nafbits(BIG x,BIG x3,int i)
-	{
-		int[] n=new int[3];
-		int nb=x3.bit(i)-x.bit(i);
-		int j;
-		n[1]=1;
-		n[0]=0;
-		if (nb==0) {n[0]=0; return n;}
-		if (i==0) {n[0]=nb; return n;}
-	    if (nb>0) n[0]=1;
-		else      n[0]=(-1);
-
-		for (j=i-1;j>0;j--)
-		{
-			n[1]++;
-			n[0]*=2;
-			nb=x3.bit(j)-x.bit(j);
-			if (nb>0) n[0]+=1;
-			if (nb<0) n[0]-=1;
-			if (n[0]>5 || n[0]<-5) break;
-		}
-
-		if (n[0]%2!=0 && j!=0)
-		{ /* backtrack */
-			if (nb>0) n[0]=(n[0]-1)/2;
-			if (nb<0) n[0]=(n[0]+1)/2;
-			n[1]--;
-		}
-		while (n[0]%2==0)
-		{ /* remove trailing zeros */
-			n[0]/=2;
-			n[2]++;
-			n[1]--;
-		}
-		return n;
-	}
-
-/* return a*b as DBIG */
-	public static DBIG mul(BIG a,BIG b)
-	{
-		long t,co;
-		DBIG c=new DBIG(0);
-		a.norm();
-		b.norm();
-
-		t=(long)a.w[0]*b.w[0]; c.w[0]=(int)t&ROM.MASK; co=t>>ROM.BASEBITS;
-		t=(long)a.w[1]*b.w[0]+(long)a.w[0]*b.w[1]+co; c.w[1]=(int)t&ROM.MASK; co=t>>ROM.BASEBITS;
-		t=(long)a.w[2]*b.w[0]+(long)a.w[1]*b.w[1]+(long)a.w[0]*b.w[2]+co; c.w[2]=(int)t&ROM.MASK; co=t>>ROM.BASEBITS;
-		t=(long)a.w[3]*b.w[0]+(long)a.w[2]*b.w[1]+(long)a.w[1]*b.w[2]+(long)a.w[0]*b.w[3]+co; c.w[3]=(int)t&ROM.MASK; co=t>>ROM.BASEBITS;
-		t=(long)a.w[4]*b.w[0]+(long)a.w[3]*b.w[1]+(long)a.w[2]*b.w[2]+(long)a.w[1]*b.w[3]+(long)a.w[0]*b.w[4]+co; c.w[4]=(int)t&ROM.MASK; co=t>>ROM.BASEBITS;
-		t=(long)a.w[5]*b.w[0]+(long)a.w[4]*b.w[1]+(long)a.w[3]*b.w[2]+(long)a.w[2]*b.w[3]+(long)a.w[1]*b.w[4]+(long)a.w[0]*b.w[5]+co; c.w[5]=(int)t&ROM.MASK; co=t>>ROM.BASEBITS;
-		t=(long)a.w[6]*b.w[0]+(long)a.w[5]*b.w[1]+(long)a.w[4]*b.w[2]+(long)a.w[3]*b.w[3]+(long)a.w[2]*b.w[4]+(long)a.w[1]*b.w[5]+(long)a.w[0]*b.w[6]+co; c.w[6]=(int)t&ROM.MASK; co=t>>ROM.BASEBITS;
-		t=(long)a.w[7]*b.w[0]+(long)a.w[6]*b.w[1]+(long)a.w[5]*b.w[2]+(long)a.w[4]*b.w[3]+(long)a.w[3]*b.w[4]+(long)a.w[2]*b.w[5]+(long)a.w[1]*b.w[6]+(long)a.w[0]*b.w[7]+co; c.w[7]=(int)t&ROM.MASK; co=t>>ROM.BASEBITS;
-		t=(long)a.w[8]*b.w[0]+(long)a.w[7]*b.w[1]+(long)a.w[6]*b.w[2]+(long)a.w[5]*b.w[3]+(long)a.w[4]*b.w[4]+(long)a.w[3]*b.w[5]+(long)a.w[2]*b.w[6]+(long)a.w[1]*b.w[7]+(long)a.w[0]*b.w[8]+co; c.w[8]=(int)t&ROM.MASK; co=t>>ROM.BASEBITS;
-
-		t=(long)a.w[8]*b.w[1]+(long)a.w[7]*b.w[2]+(long)a.w[6]*b.w[3]+(long)a.w[5]*b.w[4]+(long)a.w[4]*b.w[5]+(long)a.w[3]*b.w[6]+(long)a.w[2]*b.w[7]+(long)a.w[1]*b.w[8]+co; c.w[9]=(int)t&ROM.MASK; co=t>>ROM.BASEBITS;
-		t=(long)a.w[8]*b.w[2]+(long)a.w[7]*b.w[3]+(long)a.w[6]*b.w[4]+(long)a.w[5]*b.w[5]+(long)a.w[4]*b.w[6]+(long)a.w[3]*b.w[7]+(long)a.w[2]*b.w[8]+co; c.w[10]=(int)t&ROM.MASK; co=t>>ROM.BASEBITS;
-		t=(long)a.w[8]*b.w[3]+(long)a.w[7]*b.w[4]+(long)a.w[6]*b.w[5]+(long)a.w[5]*b.w[6]+(long)a.w[4]*b.w[7]+(long)a.w[3]*b.w[8]+co; c.w[11]=(int)t&ROM.MASK; co=t>>ROM.BASEBITS;
-		t=(long)a.w[8]*b.w[4]+(long)a.w[7]*b.w[5]+(long)a.w[6]*b.w[6]+(long)a.w[5]*b.w[7]+(long)a.w[4]*b.w[8]+co; c.w[12]=(int)t&ROM.MASK; co=t>>ROM.BASEBITS;
-		t=(long)a.w[8]*b.w[5]+(long)a.w[7]*b.w[6]+(long)a.w[6]*b.w[7]+(long)a.w[5]*b.w[8]+co; c.w[13]=(int)t&ROM.MASK; co=t>>ROM.BASEBITS;
-		t=(long)a.w[8]*b.w[6]+(long)a.w[7]*b.w[7]+(long)a.w[6]*b.w[8]+co; c.w[14]=(int)t&ROM.MASK; co=t>>ROM.BASEBITS;
-		t=(long)a.w[8]*b.w[7]+(long)a.w[7]*b.w[8]+co; c.w[15]=(int)t&ROM.MASK; co=t>>ROM.BASEBITS;
-
-		t=(long)a.w[8]*b.w[8]+co; c.w[16]=(int)t&ROM.MASK; co=t>>ROM.BASEBITS;
-		c.w[17]=(int)co;
-
-		return c;
-	}
-
-
-/* return a^2 as DBIG */
-	public static DBIG sqr(BIG a)
-	{
-		long t,co;
-		DBIG c=new DBIG(0);
-		a.norm();
-
-		t=(long)a.w[0]*a.w[0]; c.w[0]=(int)t&ROM.MASK; co=t>>ROM.BASEBITS;
-		t=(long)a.w[1]*a.w[0]; t+=t; t+=co; c.w[1]=(int)t&ROM.MASK; co=t>>ROM.BASEBITS;
-		t=(long)a.w[2]*a.w[0]; t+=t; t+=(long)a.w[1]*a.w[1]; t+=co; c.w[2]=(int)t&ROM.MASK; co=t>>ROM.BASEBITS;
-		t=(long)a.w[3]*a.w[0]+(long)a.w[2]*a.w[1]; t+=t; t+=co; c.w[3]=(int)t&ROM.MASK; co=t>>ROM.BASEBITS;
-		t=(long)a.w[4]*a.w[0]+(long)a.w[3]*a.w[1]; t+=t; t+=(long)a.w[2]*a.w[2]; t+=co; c.w[4]=(int)t&ROM.MASK; co=t>>ROM.BASEBITS;
-		t=(long)a.w[5]*a.w[0]+(long)a.w[4]*a.w[1]+(long)a.w[3]*a.w[2]; t+=t; t+=co; c.w[5]=(int)t&ROM.MASK; co=t>>ROM.BASEBITS;
-		t=(long)a.w[6]*a.w[0]+(long)a.w[5]*a.w[1]+(long)a.w[4]*a.w[2]; t+=t; t+=(long)a.w[3]*a.w[3]; t+=co; c.w[6]=(int)t&ROM.MASK; co=t>>ROM.BASEBITS;
-		t=(long)a.w[7]*a.w[0]+(long)a.w[6]*a.w[1]+(long)a.w[5]*a.w[2]+(long)a.w[4]*a.w[3]; t+=t; t+=co; c.w[7]=(int)t&ROM.MASK; co=t>>ROM.BASEBITS;
-		t=(long)a.w[8]*a.w[0]+(long)a.w[7]*a.w[1]+(long)a.w[6]*a.w[2]+(long)a.w[5]*a.w[3]; t+=t; t+=(long)a.w[4]*a.w[4]; t+=co; c.w[8]=(int)t&ROM.MASK; co=t>>ROM.BASEBITS;
-		t=(long)a.w[8]*a.w[1]+(long)a.w[7]*a.w[2]+(long)a.w[6]*a.w[3]+(long)a.w[5]*a.w[4]; t+=t; t+=co; c.w[9]=(int)t&ROM.MASK; co=t>>ROM.BASEBITS;
-		t=(long)a.w[8]*a.w[2]+(long)a.w[7]*a.w[3]+(long)a.w[6]*a.w[4]; t+=t; t+=(long)a.w[5]*a.w[5]; t+=co; c.w[10]=(int)t&ROM.MASK; co=t>>ROM.BASEBITS;
-		t=(long)a.w[8]*a.w[3]+(long)a.w[7]*a.w[4]+(long)a.w[6]*a.w[5]; t+=t; t+=co; c.w[11]=(int)t&ROM.MASK; co=t>>ROM.BASEBITS;
-		t=(long)a.w[8]*a.w[4]+(long)a.w[7]*a.w[5]; t+=t; t+=(long)a.w[6]*a.w[6]; t+=co; c.w[12]=(int)t&ROM.MASK; co=t>>ROM.BASEBITS;
-		t=(long)a.w[8]*a.w[5]+(long)a.w[7]*a.w[6]; t+=t; t+=co; c.w[13]=(int)t&ROM.MASK; co=t>>ROM.BASEBITS;
-		t=(long)a.w[8]*a.w[6]; t+=t; t+=(long)a.w[7]*a.w[7]; t+=co; c.w[14]=(int)t&ROM.MASK; co=t>>ROM.BASEBITS;
-		t=(long)a.w[8]*a.w[7]; t+=t; t+=co; c.w[15]=(int)t&ROM.MASK; co=t>>ROM.BASEBITS;
-		t=(long)a.w[8]*a.w[8]+co; c.w[16]=(int)t&ROM.MASK; co=t>>ROM.BASEBITS;
-		c.w[17]=(int)co;
-
-		return c;
-	}
-
-/* reduce a DBIG to a BIG using the appropriate form of the modulus */
-	public static BIG mod(DBIG d)
-	{
-		BIG b;
-		if (ROM.MODTYPE==ROM.PSEUDO_MERSENNE)
-		{
-			int v,tw;
-			BIG t=d.split(ROM.MODBITS);
-			b=new BIG(d);
-
-			v=t.pmul(ROM.MConst);
-			tw=t.w[ROM.NLEN-1];
-			t.w[ROM.NLEN-1]&=ROM.TMASK;
-			t.inc(ROM.MConst*((tw>>ROM.TBITS)+(v<<(ROM.BASEBITS-ROM.TBITS))));
-
-			b.add(t);
-			b.norm();
-		}
-		if (ROM.MODTYPE==ROM.MONTGOMERY_FRIENDLY)
-		{
-			for (int i=0;i<ROM.NLEN;i++)
-				d.w[ROM.NLEN+i]+=d.muladd(d.w[i],ROM.MConst-1,d.w[i],ROM.NLEN+i-1);
-
-			b=new BIG(0);
-
-			for (int i=0;i<ROM.NLEN;i++ )
-				b.w[i]=d.w[ROM.NLEN+i];
-			b.norm();
-		}
-
-		if (ROM.MODTYPE==ROM.NOT_SPECIAL)
-		{
-			BIG md=new BIG(ROM.Modulus);
-			long sum;
-			int sp;
-			sum=d.w[0];
-			for (int j=0;j<ROM.NLEN;j++)
-			{
-				for (int i=0;i<j;i++) sum+=(long)d.w[i]*md.w[j-i];
-				sp=((int)sum*ROM.MConst)&ROM.MASK;
-				d.w[j]=sp; sum+=(long)sp*md.w[0];
-				sum=d.w[j+1]+(sum>>ROM.BASEBITS);
-			}
-
-			for (int j=ROM.NLEN;j<ROM.DNLEN-2;j++)
-			{
-				for (int i=j-ROM.NLEN+1;i<ROM.NLEN;i++) sum+=(long)d.w[i]*md.w[j-i];
-				d.w[j]=(int)sum&ROM.MASK;
-				sum=d.w[j+1]+(sum>>ROM.BASEBITS);
-			}
-
-			sum+=(long)d.w[ROM.NLEN-1]*md.w[ROM.NLEN-1];
-			d.w[ROM.DNLEN-2]=(int)sum&ROM.MASK;
-			sum=d.w[ROM.DNLEN-1]+(sum>>ROM.BASEBITS);
-			d.w[ROM.DNLEN-1]=(int)sum&ROM.MASK;
-
-			b=new BIG(0);
-
-			for (int i=0;i<ROM.NLEN;i++ )
-				b.w[i]=d.w[ROM.NLEN+i];
-			b.norm();
-		}
-
-		return b;
-	}
-
-/* return a*b mod m */
-	public static BIG modmul(BIG a,BIG b,BIG m)
-	{
-		a.mod(m);
-		b.mod(m);
-		DBIG d=mul(a,b);
-		return d.mod(m);
-	}
-
-/* return a^2 mod m */
-	public static BIG modsqr(BIG a,BIG m)
-	{
-		a.mod(m);
-		DBIG d=sqr(a);
-		return d.mod(m);
-	}
-
-/* return -a mod m */
-	public static BIG modneg(BIG a,BIG m)
-	{
-		a.mod(m);
-		return m.minus(a);
-	}
-
-/* return this^e mod m */
-	public BIG powmod(BIG e,BIG m)
-	{
-		int bt;
-		norm();
-		e.norm();
-		BIG a=new BIG(1);
-		BIG z=new BIG(e);
-		BIG s=new BIG(this);
-		while (true)
-		{
-			bt=z.parity();
-			z.fshr(1);
-			if (bt==1) a=modmul(a,s,m);
-			if (z.iszilch()) break;
-			s=modsqr(s,m);
-		}
-		return a;
-	}
-
-/* Jacobi Symbol (this/p). Returns 0, 1 or -1 */
-	public int jacobi(BIG p)
-	{
-		int n8,k,m=0;
-		BIG t=new BIG(0);
-		BIG x=new BIG(0);
-		BIG n=new BIG(0);
-		BIG zilch=new BIG(0);
-		BIG one=new BIG(1);
-		if (p.parity()==0 || comp(this,zilch)==0 || comp(p,one)<=0) return 0;
-		norm();
-		x.copy(this);
-		n.copy(p);
-		x.mod(p);
-
-		while (comp(n,one)>0)
-		{
-			if (comp(x,zilch)==0) return 0;
-			n8=n.lastbits(3);
-			k=0;
-			while (x.parity()==0)
-			{
-				k++;
-				x.shr(1);
-			}
-			if (k%2==1) m+=(n8*n8-1)/8;
-			m+=(n8-1)*(x.lastbits(2)-1)/4;
-			t.copy(n);
-			t.mod(x);
-			n.copy(x);
-			x.copy(t);
-			m%=2;
-
-		}
-		if (m==0) return 1;
-		else return -1;
-	}
-
-/* this=1/this mod p. Binary method */
-	public void invmodp(BIG p)
-	{
-		mod(p);
-		BIG u=new BIG(this);
-		BIG v=new BIG(p);
-		BIG x1=new BIG(1);
-		BIG x2=new BIG(0);
-		BIG t=new BIG(0);
-		BIG one=new BIG(1);
-
-		while (comp(u,one)!=0 && comp(v,one)!=0)
-		{
-			while (u.parity()==0)
-			{
-				u.shr(1);
-				if (x1.parity()!=0)
-				{
-					x1.add(p);
-					x1.norm();
-				}
-				x1.shr(1);
-			}
-			while (v.parity()==0)
-			{
-				v.shr(1);
-				if (x2.parity()!=0)
-				{
-					x2.add(p);
-					x2.norm();
-				}
-				x2.shr(1);
-			}
-			if (comp(u,v)>=0)
-			{
-				u.sub(v);
-				u.norm();
-				if (comp(x1,x2)>=0) x1.sub(x2);
-				else
-				{
-					t.copy(p);
-					t.sub(x2);
-					x1.add(t);
-				}
-				x1.norm();
-			}
-			else
-			{
-				v.sub(u);
-				v.norm();
-				if (comp(x2,x1)>=0) x2.sub(x1);
-				else
-				{
-					t.copy(p);
-					t.sub(x1);
-					x2.add(t);
-				}
-				x2.norm();
-			}
-		}
-		if (comp(u,one)==0) copy(x1);
-		else copy(x2);
-	}
-}
diff --git a/java/DBIG.java b/java/DBIG.java
deleted file mode 100755
index ee4c993..0000000
--- a/java/DBIG.java
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
-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.
-*/
-
-/* AMCL double length DBIG number class */
-
-public class DBIG {
-	protected int[] w=new int[ROM.DNLEN];
-
-/* Constructors */
-	public DBIG(int x)
-	{
-		w[0]=x;
-		for (int i=1;i<ROM.DNLEN;i++)
-			w[i]=0;
-	}
-
-	public DBIG(DBIG x)
-	{
-		for (int i=0;i<ROM.DNLEN;i++)
-			w[i]=x.w[i];
-	}
-
-	public DBIG(BIG x)
-	{
-		for (int i=0;i<ROM.NLEN-1;i++)
-			w[i]=x.get(i);
-
-		w[ROM.NLEN-1]=x.get(ROM.NLEN-1)&ROM.MASK; /* top word normalized */
-		w[ROM.NLEN]=x.get(ROM.NLEN-1)>>ROM.BASEBITS;
-
-		for (int i=ROM.NLEN+1;i<ROM.DNLEN;i++) w[i]=0;
-	}
-
-/* get and set digits of this */
-	public int get(int i)
-	{
-		return w[i];
-	}
-
-	public void set(int i,int x)
-	{
-		w[i]=x;
-	}
-
-/* test this=0? */
-	public boolean iszilch() {
-		for (int i=0;i<ROM.DNLEN;i++)
-			if (w[i]!=0) return false;
-		return true;
-	}
-
-/* normalise this */
-	public void norm() {
-		int d,carry=0;
-		for (int i=0;i<ROM.DNLEN-1;i++)
-		{
-			d=w[i]+carry;
-			w[i]=d&ROM.MASK;
-			carry=d>>ROM.BASEBITS;
-		}
-		w[ROM.DNLEN-1]=(w[ROM.DNLEN-1]+carry);
-	}
-
-/* shift this right by k bits */
-	public void shr(int k) {
-		int n=k%ROM.BASEBITS;
-		int m=k/ROM.BASEBITS;
-		for (int i=0;i<ROM.DNLEN-m-1;i++)
-			w[i]=(w[m+i]>>n)|((w[m+i+1]<<(ROM.BASEBITS-n))&ROM.MASK);
-		w[ROM.DNLEN-m-1]=w[ROM.DNLEN-1]>>n;
-		for (int i=ROM.DNLEN-m;i<ROM.DNLEN;i++) w[i]=0;
-	}
-
-/* shift this left by k bits */
-	public void shl(int k) {
-		int n=k%ROM.BASEBITS;
-		int m=k/ROM.BASEBITS;
-
-		w[ROM.DNLEN-1]=((w[ROM.DNLEN-1-m]<<n))|(w[ROM.DNLEN-m-2]>>(ROM.BASEBITS-n));
-		for (int i=ROM.DNLEN-2;i>m;i--)
-			w[i]=((w[i-m]<<n)&ROM.MASK)|(w[i-m-1]>>(ROM.BASEBITS-n));
-		w[m]=(w[0]<<n)&ROM.MASK;
-		for (int i=0;i<m;i++) w[i]=0;
-	}
-
-/* return number of bits in this */
-	public int nbits() {
-		int bts,k=ROM.DNLEN-1;
-		int c;
-		norm();
-		while (w[k]==0 && k>=0) k--;
-		if (k<0) return 0;
-		bts=ROM.BASEBITS*k;
-		c=w[k];
-		while (c!=0) {c/=2; bts++;}
-		return bts;
-	}
-
-/* convert this to string */
-	public String toString() {
-		DBIG b;
-		String s="";
-		int len=nbits();
-		if (len%4==0) len>>=2; //len/=4;
-		else {len>>=2; len++;}
-
-		for (int i=len-1;i>=0;i--)
-		{
-			b=new DBIG(this);
-			b.shr(i*4);
-			s+=Integer.toHexString(b.w[0]&15);
-		}
-		return s;
-	}
-
-/* return this+x */
-/*
-	public DBIG plus(DBIG x) {
-		DBIG s=new DBIG(0);
-		for (int i=0;i<ROM.DNLEN;i++)
-			s.w[i]=w[i]+x.w[i];
-		return s;
-	}
-*/
-/* return this-x */
-/*
-	public DBIG minus(DBIG x) {
-		DBIG d=new DBIG(0);
-		for (int i=0;i<ROM.DNLEN;i++)
-			d.w[i]=w[i]-x.w[i];
-		return d;
-	}
-*/
-/* this+=x */
-	public void add(DBIG x) {
-		for (int i=0;i<ROM.DNLEN;i++)
-			w[i]+=x.w[i];
-	}
-
-/* this-=x */
-	public void sub(DBIG x) {
-		for (int i=0;i<ROM.DNLEN;i++)
-			w[i]-=x.w[i];
-	}
-
-/* set this[i]+=x*y+c, and return high part */
-	public int muladd(int x,int y,int c,int i)
-	{
-		long prod=(long)x*y+c+w[i];
-		w[i]=(int)prod&ROM.MASK;
-		return (int)(prod>>ROM.BASEBITS);
-	}
-
-/* Compare a and b, return 0 if a==b, -1 if a<b, +1 if a>b. Inputs must be normalised */
-	public static int comp(DBIG a,DBIG b)
-	{
-		for (int i=ROM.DNLEN-1;i>=0;i--)
-		{
-			if (a.w[i]==b.w[i]) continue;
-			if (a.w[i]>b.w[i]) return 1;
-			else  return -1;
-		}
-		return 0;
-	}
-
-/* reduces this DBIG mod a BIG, and returns the BIG */
-	public BIG mod(BIG c)
-	{
-		int k=0;
-		norm();
-		DBIG m=new DBIG(c);
-
-		if (comp(this,m)<0) return new BIG(this);
-
-		do
-		{
-			m.shl(1);
-			k++;
-		}
-		while (comp(this,m)>=0);
-
-		while (k>0)
-		{
-			m.shr(1);
-			if (comp(this,m)>=0)
-			{
-				sub(m);
-				norm();
-			}
-			k--;
-		}
-		return new BIG(this);
-	}
-
-/* reduces this DBIG mod a DBIG in place */
-/*	public void mod(DBIG m)
-	{
-		int k=0;
-		if (comp(this,m)<0) return;
-
-		do
-		{
-			m.shl(1);
-			k++;
-		}
-		while (comp(this,m)>=0);
-
-		while (k>0)
-		{
-			m.shr(1);
-			if (comp(this,m)>=0)
-			{
-				sub(m);
-				norm();
-			}
-			k--;
-		}
-		return;
-
-	}*/
-
-/* return this/c */
-	public BIG div(BIG c)
-	{
-		int k=0;
-		DBIG m=new DBIG(c);
-		BIG a=new BIG(0);
-		BIG e=new BIG(1);
-		norm();
-
-		while (comp(this,m)>=0)
-		{
-			e.fshl(1);
-			m.shl(1);
-			k++;
-		}
-
-		while (k>0)
-		{
-			m.shr(1);
-			e.shr(1);
-			if (comp(this,m)>0)
-			{
-				a.add(e);
-				a.norm();
-				sub(m);
-				norm();
-			}
-			k--;
-		}
-		return a;
-	}
-
-/* split DBIG at position n, return higher half, keep lower half */
-	public BIG split(int n)
-	{
-		BIG t=new BIG(0);
-		int nw,m=n%ROM.BASEBITS;
-		int carry=w[ROM.DNLEN-1]<<(ROM.BASEBITS-m);
-
-		for (int i=ROM.DNLEN-2;i>=ROM.NLEN-1;i--)
-		{
-			nw=(w[i]>>m)|carry;
-			carry=(w[i]<<(ROM.BASEBITS-m))&ROM.MASK;
-			t.set(i-ROM.NLEN+1,nw);
-		}
-		w[ROM.NLEN-1]&=(((int)1<<m)-1);
-		return t;
-	}
-}
diff --git a/java/ECDH.java b/java/ECDH.java
deleted file mode 100755
index 88c48ba..0000000
--- a/java/ECDH.java
+++ /dev/null
@@ -1,531 +0,0 @@
-/*
-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.
-*/
-
-/* Elliptic Curve API high-level functions  */
-
-public final class ECDH {
-	public static final int INVALID_PUBLIC_KEY=-2;
-	public static final int ERROR=-3;
-	public static final int INVALID=-4;
-	public static final int EFS=ROM.MODBYTES;
-	public static final int EGS=ROM.MODBYTES;
-	public static final int EAS=AES.KS;
-	public static final int EBS=AES.BS;
-
-/* Convert Integer to n-byte array */
-	private static byte[] inttoBytes(int n,int len)
-	{
-		int i;
-		byte[] b=new byte[len];
-
-		for (i=0;i<len;i++) b[i]=0;
-		i=len;
-		while (n>0 && i>0)
-		{
-			i--;
-			b[i]=(byte)(n&0xff);
-			n/=256;
-		}
-		return b;
-	}
-
-/* Key Derivation Functions */
-/* Input octet Z */
-/* Output key of length olen */
-	public static byte[] KDF1(byte[] Z,int olen)
-	{
-/* NOTE: the parameter olen is the length of the output K in bytes */
-		HASH H=new HASH();
-		int hlen=HASH.len;
-		byte[] K=new byte[olen];
-
-		byte[] B;
-		int counter,cthreshold,k=0;
-
-		for (int i=0;i<K.length;i++) K[i]=0;
-
-		cthreshold=olen/hlen; if (olen%hlen!=0) cthreshold++;
-
-		for (counter=0;counter<cthreshold;counter++)
-		{
-			H.process_array(Z); if (counter>0) H.process_num(counter);
-			B=H.hash();
-			if (k+hlen>olen) for (int i=0;i<olen%hlen;i++) K[k++]=B[i];
-			else for (int i=0;i<hlen;i++) K[k++]=B[i];
-		}
-		return K;
-	}
-
-	public static byte[] KDF2(byte[] Z,byte[] P,int olen)
-	{
-/* NOTE: the parameter olen is the length of the output k in bytes */
-		HASH H=new HASH();
-		int hlen=HASH.len;
-		byte[] K=new byte[olen];
-
-		byte[] B=new byte[hlen];
-		int counter,cthreshold,k=0;
-
-		for (int i=0;i<K.length;i++) K[i]=0;
-
-		cthreshold=olen/hlen; if (olen%hlen!=0) cthreshold++;
-
-		for (counter=1;counter<=cthreshold;counter++)
-		{
-			H.process_array(Z); H.process_num(counter); H.process_array(P);
-			B=H.hash();
-			if (k+hlen>olen) for (int i=0;i<olen%hlen;i++) K[k++]=B[i];
-			else for (int i=0;i<hlen;i++) K[k++]=B[i];
-		}
-		return K;
-	}
-
-/* Password based Key Derivation Function */
-/* Input password p, salt s, and repeat count */
-/* Output key of length olen */
-	public static byte[] PBKDF2(byte[] Pass,byte[] Salt,int rep,int olen)
-	{
-		int i,j,k,len,d,opt;
-		d=olen/32; if (olen%32!=0) d++;
-		byte[] F=new byte[EFS];
-		byte[] U=new byte[EFS];
-		byte[] S=new byte[Salt.length+4];
-
-		byte[] K=new byte[d*EFS];
-		opt=0;
-
-		for (i=1;i<=d;i++)
-		{
-			for (j=0;j<Salt.length;j++) S[j]=Salt[j];
-			byte[] N=inttoBytes(i,4);
-			for (j=0;j<4;j++) S[Salt.length+j]=N[j];
-
-			HMAC(S,Pass,F);
-
-			for (j=0;j<EFS;j++) U[j]=F[j];
-			for (j=2;j<=rep;j++)
-			{
-				HMAC(U,Pass,U);
-				for (k=0;k<EFS;k++) F[k]^=U[k];
-			}
-			for (j=0;j<EFS;j++) K[opt++]=F[j];
-		}
-		byte[] key=new byte[olen];
-		for (i=0;i<olen;i++) key[i]=K[i];
-		return key;
-	}
-
-/* Calculate HMAC of m using key k. HMAC is tag of length olen */
-	public static int HMAC(byte[] M,byte[] K,byte[] tag)
-	{
-	/* Input is from an octet m        *
-	* olen is requested output length in bytes. k is the key  *
-	* The output is the calculated tag */
-		int b;
-		byte[] B;
-		byte[] K0=new byte[64];
-		int olen=tag.length;
-
-		b=K0.length;
-		if (olen<4 || olen>HASH.len) return 0;
-
-		for (int i=0;i<b;i++) K0[i]=0;
-
-		HASH H=new HASH();
-
-		if (K.length > b)
-		{
-			H.process_array(K); B=H.hash();
-			for (int i=0;i<32;i++) K0[i]=B[i];
-		}
-		else
-			for (int i=0;i<K.length;i++ ) K0[i]=K[i];
-
-		for (int i=0;i<b;i++) K0[i]^=0x36;
-		H.process_array(K0); H.process_array(M); B=H.hash();
-
-		for (int i=0;i<b;i++) K0[i]^=0x6a;
-		H.process_array(K0); H.process_array(B); B=H.hash();
-
-		for (int i=0;i<olen;i++) tag[i]=B[i];
-
-		return 1;
-	}
-
-/* AES encryption/decryption. Encrypt byte array M using key K and returns ciphertext */
-	public static byte[] AES_CBC_IV0_ENCRYPT(byte[] K,byte[] M)
-	{ /* AES CBC encryption, with Null IV and key K */
-	/* Input is from an octet string M, output is to an octet string C */
-	/* Input is padded as necessary to make up a full final block */
-		AES a=new AES();
-		boolean fin;
-		int i,j,ipt,opt;
-		byte[] buff=new byte[16];
-		int clen=16+(M.length/16)*16;
-
-		byte[] C=new byte[clen];
-		int padlen;
-
-		a.init(AES.CBC,K,null);
-
-		ipt=opt=0;
-		fin=false;
-		for(;;)
-		{
-			for (i=0;i<16;i++)
-			{
-				if (ipt<M.length) buff[i]=M[ipt++];
-				else {fin=true; break;}
-			}
-			if (fin) break;
-			a.encrypt(buff);
-			for (i=0;i<16;i++)
-				C[opt++]=buff[i];
-		}
-
-/* last block, filled up to i-th index */
-
-		padlen=16-i;
-		for (j=i;j<16;j++) buff[j]=(byte)padlen;
-
-		a.encrypt(buff);
-
-		for (i=0;i<16;i++)
-			C[opt++]=buff[i];
-		a.end();
-		return C;
-	}
-
-/* returns plaintext if all consistent, else returns null string */
-	public static byte[] AES_CBC_IV0_DECRYPT(byte[] K,byte[] C)
-	{ /* padding is removed */
-		AES a=new AES();
-		int i,ipt,opt,ch;
-		byte[] buff=new byte[16];
-		byte[] MM=new byte[C.length];
-		boolean fin,bad;
-		int padlen;
-		ipt=opt=0;
-
-		a.init(AES.CBC,K,null);
-
-		if (C.length==0) return new byte[0];
-		ch=C[ipt++];
-
-		fin=false;
-
-		for(;;)
-		{
-			for (i=0;i<16;i++)
-			{
-				buff[i]=(byte)ch;
-				if (ipt>=C.length) {fin=true; break;}
-				else ch=C[ipt++];
-			}
-			a.decrypt(buff);
-			if (fin) break;
-			for (i=0;i<16;i++)
-				MM[opt++]=buff[i];
-		}
-
-		a.end();
-		bad=false;
-		padlen=buff[15];
-		if (i!=15 || padlen<1 || padlen>16) bad=true;
-		if (padlen>=2 && padlen<=16)
-			for (i=16-padlen;i<16;i++) if (buff[i]!=padlen) bad=true;
-
-		if (!bad) for (i=0;i<16-padlen;i++)
-					MM[opt++]=buff[i];
-
-		if (bad) return new byte[0];
-
-		byte[] M=new byte[opt];
-		for (i=0;i<opt;i++) M[i]=MM[i];
-
-		return M;
-	}
-
-/* Calculate a public/private EC GF(p) key pair W,S where W=S.G mod EC(p),
- * where S is the secret key and W is the public key
- * and G is fixed generator.
- * If RNG is NULL then the private key is provided externally in S
- * otherwise it is generated randomly internally */
-	public static int KEY_PAIR_GENERATE(RAND RNG,byte[] S,byte[] W)
-	{
-		BIG r,gx,gy,s,wx,wy;
-		ECP G,WP;
-		int res=0;
-		byte[] T=new byte[EFS];
-
-		gx=new BIG(ROM.CURVE_Gx);
-
-		if (ROM.CURVETYPE!=ROM.MONTGOMERY)
-		{
-			gy=new BIG(ROM.CURVE_Gy);
-			G=new ECP(gx,gy);
-		}
-		else
-			G=new ECP(gx);
-
-		r=new BIG(ROM.CURVE_Order);
-
-		if (RNG==null)
-		{
-			s=BIG.fromBytes(S);
-		}
-		else
-		{
-			s=BIG.randomnum(r,RNG);
-
-			s.toBytes(T);
-			for (int i=0;i<EGS;i++) S[i]=T[i];
-		}
-
-		WP=G.mul(s);
-		WP.toBytes(W);
-
-		return res;
-	}
-
-/* validate public key. Set full=true for fuller check */
-	public static int PUBLIC_KEY_VALIDATE(boolean full,byte[] W)
-	{
-		BIG r;
-		ECP WP=ECP.fromBytes(W);
-		int res=0;
-
-		r=new BIG(ROM.CURVE_Order);
-
-		if (WP.is_infinity()) res=INVALID_PUBLIC_KEY;
-
-		if (res==0 && full)
-		{
-			WP=WP.mul(r);
-			if (!WP.is_infinity()) res=INVALID_PUBLIC_KEY;
-		}
-		return res;
-	}
-
-/* IEEE-1363 Diffie-Hellman online calculation Z=S.WD */
-	public static int ECPSVDP_DH(byte[] S,byte[] WD,byte[] Z)
-	{
-		BIG r,s,wx,wy,z;
-		int valid;
-		ECP W;
-		int res=0;
-		byte[] T=new byte[EFS];
-
-		s=BIG.fromBytes(S);
-
-		W=ECP.fromBytes(WD);
-		if (W.is_infinity()) res=ERROR;
-
-		if (res==0)
-		{
-			r=new BIG(ROM.CURVE_Order);
-			s.mod(r);
-
-			W=W.mul(s);
-			if (W.is_infinity()) res=ERROR;
-			else
-			{
-				W.getX().toBytes(T);
-				for (int i=0;i<EFS;i++) Z[i]=T[i];
-			}
-		}
-		return res;
-	}
-
-/* IEEE ECDSA Signature, C and D are signature on F using private key S */
-	public static int ECPSP_DSA(RAND RNG,byte[] S,byte[] F,byte[] C,byte[] D)
-	{
-		byte[] T=new byte[EFS];
-		BIG gx,gy,r,s,f,c,d,u,vx;
-		ECP G,V;
-
-		HASH H=new HASH();
-		H.process_array(F);
-		byte[] B=H.hash();
-
-		gx=new BIG(ROM.CURVE_Gx);
-		gy=new BIG(ROM.CURVE_Gy);
-
-		G=new ECP(gx,gy);
-		r=new BIG(ROM.CURVE_Order);
-
-		s=BIG.fromBytes(S);
-		f=BIG.fromBytes(B);
-
-		c=new BIG(0);
-		d=new BIG(0);
-		V=new ECP();
-
-		do {
-			u=BIG.randomnum(r,RNG);
-
-			V.copy(G);
-			V=V.mul(u);
-			vx=V.getX();
-			c.copy(vx);
-			c.mod(r);
-			if (c.iszilch()) continue;
-			u.invmodp(r);
-			d.copy(BIG.modmul(s,c,r));
-			d.add(f);
-			d.copy(BIG.modmul(u,d,r));
-		} while (d.iszilch());
-
-		c.toBytes(T);
-		for (int i=0;i<EFS;i++) C[i]=T[i];
-		d.toBytes(T);
-		for (int i=0;i<EFS;i++) D[i]=T[i];
-		return 0;
-	}
-
-/* IEEE1363 ECDSA Signature Verification. Signature C and D on F is verified using public key W */
-	public static int ECPVP_DSA(byte[] W,byte[] F, byte[] C,byte[] D)
-	{
-		BIG r,gx,gy,f,c,d,h2;
-		int res=0;
-		ECP G,WP,P;
-		int valid;
-
-		HASH H=new HASH();
-		H.process_array(F);
-		byte[] B=H.hash();
-
-		gx=new BIG(ROM.CURVE_Gx);
-		gy=new BIG(ROM.CURVE_Gy);
-
-		G=new ECP(gx,gy);
-		r=new BIG(ROM.CURVE_Order);
-
-		c=BIG.fromBytes(C);
-		d=BIG.fromBytes(D);
-		f=BIG.fromBytes(B);
-
-		if (c.iszilch() || BIG.comp(c,r)>=0 || d.iszilch() || BIG.comp(d,r)>=0)
-            res=INVALID;
-
-		if (res==0)
-		{
-			d.invmodp(r);
-			f.copy(BIG.modmul(f,d,r));
-			h2=BIG.modmul(c,d,r);
-
-			WP=ECP.fromBytes(W);
-			if (WP.is_infinity()) res=ERROR;
-			else
-			{
-				P=new ECP();
-				P.copy(WP);
-				P=P.mul2(h2,G,f);
-				if (P.is_infinity()) res=INVALID;
-				else
-				{
-					d=P.getX();
-					d.mod(r);
-					if (BIG.comp(d,c)!=0) res=INVALID;
-				}
-			}
-		}
-
-		return res;
-	}
-
-/* IEEE1363 ECIES encryption. Encryption of plaintext M uses public key W and produces ciphertext V,C,T */
-	public static byte[] ECIES_ENCRYPT(byte[] P1,byte[] P2,RAND RNG,byte[] W,byte[] M,byte[] V,byte[] T)
-	{
-		int i,len;
-
-		byte[] Z=new byte[EFS];
-		byte[] VZ=new byte[3*EFS+1];
-		byte[] K1=new byte[EAS];
-		byte[] K2=new byte[EAS];
-		byte[] U=new byte[EGS];
-
-		if (KEY_PAIR_GENERATE(RNG,U,V)!=0) return new byte[0];
-		if (ECPSVDP_DH(U,W,Z)!=0) return new byte[0];
-
-		for (i=0;i<2*EFS+1;i++) VZ[i]=V[i];
-		for (i=0;i<EFS;i++) VZ[2*EFS+1+i]=Z[i];
-
-
-		byte[] K=KDF2(VZ,P1,EFS);
-
-		for (i=0;i<EAS;i++) {K1[i]=K[i]; K2[i]=K[EAS+i];}
-
-		byte[] C=AES_CBC_IV0_ENCRYPT(K1,M);
-
-		byte[] L2=inttoBytes(P2.length,8);
-
-		byte[] AC=new byte[C.length+P2.length+8];
-		for (i=0;i<C.length;i++) AC[i]=C[i];
-		for (i=0;i<P2.length;i++) AC[C.length+i]=P2[i];
-		for (i=0;i<8;i++) AC[C.length+P2.length+i]=L2[i];
-
-		HMAC(AC,K2,T);
-
-		return C;
-	}
-
-/* IEEE1363 ECIES decryption. Decryption of ciphertext V,C,T using private key U outputs plaintext M */
-	public static byte[] ECIES_DECRYPT(byte[] P1,byte[] P2,byte[] V,byte[] C,byte[] T,byte[] U)
-	{
-
-		int i,len;
-
-		byte[] Z=new byte[EFS];
-		byte[] VZ=new byte[3*EFS+1];
-		byte[] K1=new byte[EAS];
-		byte[] K2=new byte[EAS];
-		byte[] TAG=new byte[T.length];
-
-		if (ECPSVDP_DH(U,V,Z)!=0) return new byte[0];
-
-		for (i=0;i<2*EFS+1;i++) VZ[i]=V[i];
-		for (i=0;i<EFS;i++) VZ[2*EFS+1+i]=Z[i];
-
-		byte[] K=KDF2(VZ,P1,EFS);
-
-		for (i=0;i<EAS;i++) {K1[i]=K[i]; K2[i]=K[EAS+i];}
-
-		byte[] M=AES_CBC_IV0_DECRYPT(K1,C);
-
-		if (M.length==0) return M;
-
-		byte[] L2=inttoBytes(P2.length,8);
-
-		byte[] AC=new byte[C.length+P2.length+8];
-
-		for (i=0;i<C.length;i++) AC[i]=C[i];
-		for (i=0;i<P2.length;i++) AC[C.length+i]=P2[i];
-		for (i=0;i<8;i++) AC[C.length+P2.length+i]=L2[i];
-
-		HMAC(AC,K2,TAG);
-
-		boolean same=true;
-		for (i=0;i<T.length;i++) if (T[i]!=TAG[i]) same=false;
-		if (!same) return new byte[0];
-
-		return M;
-
-	}
-}
diff --git a/java/ECP.java b/java/ECP.java
deleted file mode 100755
index af7fa76..0000000
--- a/java/ECP.java
+++ /dev/null
@@ -1,920 +0,0 @@
-/*
-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.
-*/
-
-/* Elliptic Curve Point class */
-
-public final class ECP {
-	private FP x;
-	private FP y;
-	private FP z;
-	private boolean INF;
-
-/* Constructor - set to O */
-	public ECP() {
-		INF=true;
-		x=new FP(0);
-		y=new FP(1);
-		z=new FP(1);
-	}
-/* test for O point-at-infinity */
-	public boolean is_infinity() {
-		if (ROM.CURVETYPE==ROM.EDWARDS)
-		{
-			x.reduce(); y.reduce(); z.reduce();
-			return (x.iszilch() && y.equals(z));
-		}
-		else return INF;
-	}
-/* Conditional swap of P and Q dependant on d */
-	private void cswap(ECP Q,int d)
-	{
-		x.cswap(Q.x,d);
-		if (ROM.CURVETYPE!=ROM.MONTGOMERY) y.cswap(Q.y,d);
-		z.cswap(Q.z,d);
-		if (ROM.CURVETYPE!=ROM.EDWARDS)
-		{
-			boolean bd;
-			if (d==0) bd=false;
-			else bd=true;
-			bd=bd&(INF^Q.INF);
-			INF^=bd;
-			Q.INF^=bd;
-		}
-	}
-
-/* Conditional move of Q to P dependant on d */
-	private void cmove(ECP Q,int d)
-	{
-		x.cmove(Q.x,d);
-		if (ROM.CURVETYPE!=ROM.MONTGOMERY) y.cmove(Q.y,d);
-		z.cmove(Q.z,d);
-		if (ROM.CURVETYPE!=ROM.EDWARDS)
-		{
-			boolean bd;
-			if (d==0) bd=false;
-			else bd=true;
-			INF^=(INF^Q.INF)&bd;
-		}
-	}
-
-/* return 1 if b==c, no branching */
-	private static int teq(int b,int c)
-	{
-		int x=b^c;
-		x-=1;  // if x=0, x now -1
-		return ((x>>31)&1);
-	}
-
-/* Constant time select from pre-computed table */
-	private void select(ECP W[],int b)
-	{
-		ECP MP=new ECP();
-		int m=b>>31;
-		int babs=(b^m)-m;
-
-		babs=(babs-1)/2;
-
-		cmove(W[0],teq(babs,0));  // conditional move
-		cmove(W[1],teq(babs,1));
-		cmove(W[2],teq(babs,2));
-		cmove(W[3],teq(babs,3));
-		cmove(W[4],teq(babs,4));
-		cmove(W[5],teq(babs,5));
-		cmove(W[6],teq(babs,6));
-		cmove(W[7],teq(babs,7));
-
-		MP.copy(this);
-		MP.neg();
-		cmove(MP,(int)(m&1));
-	}
-
-/* Test P == Q */
-	public boolean equals(ECP Q) {
-		if (is_infinity() && Q.is_infinity()) return true;
-		if (is_infinity() || Q.is_infinity()) return false;
-		if (ROM.CURVETYPE==ROM.WEIERSTRASS)
-		{
-			FP zs2=new FP(z); zs2.sqr();
-			FP zo2=new FP(Q.z); zo2.sqr();
-			FP zs3=new FP(zs2); zs3.mul(z);
-			FP zo3=new FP(zo2); zo3.mul(Q.z);
-			zs2.mul(Q.x);
-			zo2.mul(x);
-			if (!zs2.equals(zo2)) return false;
-			zs3.mul(Q.y);
-			zo3.mul(y);
-			if (!zs3.equals(zo3)) return false;
-		}
-		else
-		{
-			FP a=new FP(0);
-			FP b=new FP(0);
-			a.copy(x); a.mul(Q.z); a.reduce();
-			b.copy(Q.x); b.mul(z); b.reduce();
-			if (!a.equals(b)) return false;
-			if (ROM.CURVETYPE==ROM.EDWARDS)
-			{
-				a.copy(y); a.mul(Q.z); a.reduce();
-				b.copy(Q.y); b.mul(z); b.reduce();
-				if (!a.equals(b)) return false;
-			}
-		}
-		return true;
-	}
-
-/* this=P */
-	public void copy(ECP P)
-	{
-		x.copy(P.x);
-		if (ROM.CURVETYPE!=ROM.MONTGOMERY) y.copy(P.y);
-		z.copy(P.z);
-		INF=P.INF;
-	}
-/* this=-this */
-	public void neg() {
-		if (is_infinity()) return;
-		if (ROM.CURVETYPE==ROM.WEIERSTRASS)
-		{
-			y.neg(); y.norm();
-		}
-		if (ROM.CURVETYPE==ROM.EDWARDS)
-		{
-			x.neg(); x.norm();
-		}
-		return;
-	}
-/* set this=O */
-	public void inf() {
-		INF=true;
-		x.zero();
-		y.one();
-		z.one();
-	//	y=new FP(1);
-	//	z=new FP(1);
-	}
-
-/* Calculate RHS of curve equation */
-	public static FP RHS(FP x) {
-		x.norm();
-		FP r=new FP(x);
-		r.sqr();
-
-		if (ROM.CURVETYPE==ROM.WEIERSTRASS)
-		{ // x^3+Ax+B
-			FP b=new FP(new BIG(ROM.CURVE_B));
-			r.mul(x);
-			if (ROM.CURVE_A==-3)
-			{
-				FP cx=new FP(x);
-				cx.imul(3);
-				cx.neg(); cx.norm();
-				r.add(cx);
-			}
-			r.add(b);
-		}
-		if (ROM.CURVETYPE==ROM.EDWARDS)
-		{ // (Ax^2-1)/(Bx^2-1)
-			FP b=new FP(new BIG(ROM.CURVE_B));
-
-			FP one=new FP(1);
-			b.mul(r);
-			b.sub(one);
-			if (ROM.CURVE_A==-1) r.neg();
-			r.sub(one);
-
-			b.inverse();
-
-			r.mul(b);
-		}
-		if (ROM.CURVETYPE==ROM.MONTGOMERY)
-		{ // x^3+Ax^2+x
-			FP x3=new FP(0);
-			x3.copy(r);
-			x3.mul(x);
-			r.imul(ROM.CURVE_A);
-			r.add(x3);
-			r.add(x);
-		}
-		r.reduce();
-		return r;
-	}
-
-/* set (x,y) from two BIGs */
-	public ECP(BIG ix,BIG iy) {
-		x=new FP(ix);
-		y=new FP(iy);
-		z=new FP(1);
-		FP rhs=RHS(x);
-
-		if (ROM.CURVETYPE==ROM.MONTGOMERY)
-		{
-			if (rhs.jacobi()==1) INF=false;
-			else inf();
-		}
-		else
-		{
-			FP y2=new FP(y);
-			y2.sqr();
-			if (y2.equals(rhs)) INF=false;
-			else inf();
-		}
-	}
-/* set (x,y) from BIG and a bit */
-	public ECP(BIG ix,int s) {
-		x=new FP(ix);
-		FP rhs=RHS(x);
-		y=new FP(0);
-		z=new FP(1);
-		if (rhs.jacobi()==1)
-		{
-			FP ny=rhs.sqrt();
-			if (ny.redc().parity()!=s) ny.neg();
-			y.copy(ny);
-			INF=false;
-		}
-		else inf();
-	}
-
-/* set from x - calculate y from curve equation */
-	public ECP(BIG ix) {
-		x=new FP(ix);
-		FP rhs=RHS(x);
-		y=new FP(0);
-		z=new FP(1);
-		if (rhs.jacobi()==1)
-		{
-			if (ROM.CURVETYPE!=ROM.MONTGOMERY) y.copy(rhs.sqrt());
-			INF=false;
-		}
-		else INF=true;
-	}
-
-/* set to affine - from (x,y,z) to (x,y) */
-	public void affine() {
-		if (is_infinity()) return;
-		FP one=new FP(1);
-		if (z.equals(one)) return;
-		z.inverse();
-		if (ROM.CURVETYPE==ROM.WEIERSTRASS)
-		{
-			FP z2=new FP(z);
-			z2.sqr();
-			x.mul(z2); x.reduce();
-			y.mul(z2);
-			y.mul(z);  y.reduce();
-		}
-		if (ROM.CURVETYPE==ROM.EDWARDS)
-		{
-			x.mul(z); x.reduce();
-			y.mul(z); y.reduce();
-		}
-		if (ROM.CURVETYPE==ROM.MONTGOMERY)
-		{
-			x.mul(z); x.reduce();
-		}
-		z.copy(one);
-	}
-/* extract x as a BIG */
-	public BIG getX()
-	{
-		affine();
-		return x.redc();
-	}
-/* extract y as a BIG */
-	public BIG getY()
-	{
-		affine();
-		return y.redc();
-	}
-
-/* get sign of Y */
-	public int getS()
-	{
-		affine();
-		BIG y=getY();
-		return y.parity();
-	}
-/* extract x as an FP */
-	public FP getx()
-	{
-		return x;
-	}
-/* extract y as an FP */
-	public FP gety()
-	{
-		return y;
-	}
-/* extract z as an FP */
-	public FP getz()
-	{
-		return z;
-	}
-/* convert to byte array */
-	public void toBytes(byte[] b)
-	{
-		byte[] t=new byte[ROM.MODBYTES];
-		if (ROM.CURVETYPE!=ROM.MONTGOMERY) b[0]=0x04;
-		else b[0]=0x02;
-
-		affine();
-		x.redc().toBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++) b[i+1]=t[i];
-		if (ROM.CURVETYPE!=ROM.MONTGOMERY)
-		{
-			y.redc().toBytes(t);
-			for (int i=0;i<ROM.MODBYTES;i++) b[i+ROM.MODBYTES+1]=t[i];
-		}
-	}
-/* convert from byte array to point */
-	public static ECP fromBytes(byte[] b)
-	{
-		byte[] t=new byte[ROM.MODBYTES];
-		BIG p=new BIG(ROM.Modulus);
-
-		for (int i=0;i<ROM.MODBYTES;i++) t[i]=b[i+1];
-		BIG px=BIG.fromBytes(t);
-		if (BIG.comp(px,p)>=0) return new ECP();
-
-		if (b[0]==0x04)
-		{
-			for (int i=0;i<ROM.MODBYTES;i++) t[i]=b[i+ROM.MODBYTES+1];
-			BIG py=BIG.fromBytes(t);
-			if (BIG.comp(py,p)>=0) return new ECP();
-			return new ECP(px,py);
-		}
-		else return new ECP(px);
-	}
-/* convert to hex string */
-	public String toString() {
-		if (is_infinity()) return "infinity";
-		affine();
-		if (ROM.CURVETYPE==ROM.MONTGOMERY) return "("+x.redc().toString()+")";
-		else return "("+x.redc().toString()+","+y.redc().toString()+")";
-	}
-/* this*=2 */
-	public void dbl() {
-		if (ROM.CURVETYPE==ROM.WEIERSTRASS)
-		{
-			if (INF) return;
-			if (y.iszilch())
-			{
-				inf();
-				return;
-			}
-
-			FP w1=new FP(x);
-			FP w6=new FP(z);
-			FP w2=new FP(0);
-			FP w3=new FP(x);
-			FP w8=new FP(x);
-
-			if (ROM.CURVE_A==-3)
-			{
-				w6.sqr();
-				w1.copy(w6);
-				w1.neg();
-				w3.add(w1);
-				w8.add(w6);
-				w3.mul(w8);
-				w8.copy(w3);
-				w8.imul(3);
-			}
-			else
-			{
-				w1.sqr();
-				w8.copy(w1);
-				w8.imul(3);
-			}
-
-			w2.copy(y); w2.sqr();
-			w3.copy(x); w3.mul(w2);
-			w3.imul(4);
-			w1.copy(w3); w1.neg();
-			w1.norm();
-
-			x.copy(w8); x.sqr();
-			x.add(w1);
-			x.add(w1);
-			x.norm();
-
-			z.mul(y);
-			z.add(z);
-
-			w2.add(w2);
-			w2.sqr();
-			w2.add(w2);
-			w3.sub(x);
-			y.copy(w8); y.mul(w3);
-			//w2.norm();
-			y.sub(w2);
-			y.norm();
-			z.norm();
-		}
-		if (ROM.CURVETYPE==ROM.EDWARDS)
-		{
-			FP C=new FP(x);
-			FP D=new FP(y);
-			FP H=new FP(z);
-			FP J=new FP(0);
-
-			x.mul(y); x.add(x);
-			C.sqr();
-			D.sqr();
-			if (ROM.CURVE_A==-1) C.neg();
-			y.copy(C); y.add(D);
-			y.norm();
-			H.sqr(); H.add(H);
-			z.copy(y);
-			J.copy(y); J.sub(H);
-			x.mul(J);
-			C.sub(D);
-			y.mul(C);
-			z.mul(J);
-
-			x.norm();
-			y.norm();
-			z.norm();
-		}
-		if (ROM.CURVETYPE==ROM.MONTGOMERY)
-		{
-			FP A=new FP(x);
-			FP B=new FP(x);
-			FP AA=new FP(0);
-			FP BB=new FP(0);
-			FP C=new FP(0);
-
-			if (INF) return;
-
-			A.add(z);
-			AA.copy(A); AA.sqr();
-			B.sub(z);
-			BB.copy(B); BB.sqr();
-			C.copy(AA); C.sub(BB);
-			//C.norm();
-
-			x.copy(AA); x.mul(BB);
-
-			A.copy(C); A.imul((ROM.CURVE_A+2)/4);
-
-			BB.add(A);
-			z.copy(BB); z.mul(C);
-			x.norm();
-			z.norm();
-		}
-		return;
-	}
-
-/* this+=Q */
-	public void add(ECP Q) {
-		if (ROM.CURVETYPE==ROM.WEIERSTRASS)
-		{
-			if (INF)
-			{
-				copy(Q);
-				return;
-			}
-			if (Q.INF) return;
-
-			boolean aff=false;
-
-			FP one=new FP(1);
-			if (Q.z.equals(one)) aff=true;
-
-			FP A,C;
-			FP B=new FP(z);
-			FP D=new FP(z);
-			if (!aff)
-			{
-				A=new FP(Q.z);
-				C=new FP(Q.z);
-
-				A.sqr(); B.sqr();
-				C.mul(A); D.mul(B);
-
-				A.mul(x);
-				C.mul(y);
-			}
-			else
-			{
-				A=new FP(x);
-				C=new FP(y);
-
-				B.sqr();
-				D.mul(B);
-			}
-
-			B.mul(Q.x); B.sub(A);
-			D.mul(Q.y); D.sub(C);
-
-			if (B.iszilch())
-			{
-				if (D.iszilch())
-				{
-					dbl();
-					return;
-				}
-				else
-				{
-					INF=true;
-					return;
-				}
-			}
-
-			if (!aff) z.mul(Q.z);
-			z.mul(B);
-
-			FP e=new FP(B); e.sqr();
-			B.mul(e);
-			A.mul(e);
-
-			e.copy(A);
-			e.add(A); e.add(B);
-			x.copy(D); x.sqr(); x.sub(e);
-
-			A.sub(x);
-			y.copy(A); y.mul(D);
-			C.mul(B); y.sub(C);
-
-			x.norm();
-			y.norm();
-			z.norm();
-		}
-		if (ROM.CURVETYPE==ROM.EDWARDS)
-		{
-			FP b=new FP(new BIG(ROM.CURVE_B));
-			FP A=new FP(z);
-			FP B=new FP(0);
-			FP C=new FP(x);
-			FP D=new FP(y);
-			FP E=new FP(0);
-			FP F=new FP(0);
-			FP G=new FP(0);
-		//	FP H=new FP(0);
-		//	FP I=new FP(0);
-
-			A.mul(Q.z);
-			B.copy(A); B.sqr();
-			C.mul(Q.x);
-			D.mul(Q.y);
-
-			E.copy(C); E.mul(D); E.mul(b);
-			F.copy(B); F.sub(E);
-			G.copy(B); G.add(E);
-			C.add(D);
-
-			if (ROM.CURVE_A==1)
-			{
-				E.copy(D); D.sub(C);
-			}
-
-			B.copy(x); B.add(y);
-			D.copy(Q.x); D.add(Q.y);
-			B.mul(D);
-			B.sub(C);
-			B.mul(F);
-			x.copy(A); x.mul(B);
-
-			if (ROM.CURVE_A==1)
-			{
-				C.copy(E); C.mul(G);
-			}
-			if (ROM.CURVE_A==-1)
-			{
-				C.mul(G);
-			}
-			y.copy(A); y.mul(C);
-			z.copy(F); z.mul(G);
-			x.norm(); y.norm(); z.norm();
-		}
-		return;
-	}
-
-/* Differential Add for Montgomery curves. this+=Q where W is this-Q and is affine. */
-	public void dadd(ECP Q,ECP W) {
-			FP A=new FP(x);
-			FP B=new FP(x);
-			FP C=new FP(Q.x);
-			FP D=new FP(Q.x);
-			FP DA=new FP(0);
-			FP CB=new FP(0);
-
-			A.add(z);
-			B.sub(z);
-
-			C.add(Q.z);
-			D.sub(Q.z);
-
-			DA.copy(D); DA.mul(A);
-			CB.copy(C); CB.mul(B);
-
-			A.copy(DA); A.add(CB); A.sqr();
-			B.copy(DA); B.sub(CB); B.sqr();
-
-			x.copy(A);
-			z.copy(W.x); z.mul(B);
-
-			if (z.iszilch()) inf();
-			else INF=false;
-
-			x.norm();
-	}
-/* this-=Q */
-	public void sub(ECP Q) {
-		Q.neg();
-		add(Q);
-		Q.neg();
-	}
-
-	public static void multiaffine(int m,ECP[] P)
-	{
-		int i;
-		FP t1=new FP(0);
-		FP t2=new FP(0);
-
-		FP[] work=new FP[m];
-
-		for (i=0;i<m;i++)
-			work[i]=new FP(0);
-
-		work[0].one();
-		work[1].copy(P[0].z);
-
-		for (i=2;i<m;i++)
-		{
-			work[i].copy(work[i-1]);
-			work[i].mul(P[i-1].z);
-		}
-
-		t1.copy(work[m-1]);
-		t1.mul(P[m-1].z);
-		t1.inverse();
-		t2.copy(P[m-1].z);
-		work[m-1].mul(t1);
-
-		for (i=m-2;;i--)
-		{
-			if (i==0)
-			{
-				work[0].copy(t1);
-				work[0].mul(t2);
-				break;
-			}
-			work[i].mul(t2);
-			work[i].mul(t1);
-			t2.mul(P[i].z);
-		}
-/* now work[] contains inverses of all Z coordinates */
-
-		for (i=0;i<m;i++)
-		{
-			P[i].z.one();
-			t1.copy(work[i]);
-			t1.sqr();
-			P[i].x.mul(t1);
-			t1.mul(work[i]);
-			P[i].y.mul(t1);
-		}
-	}
-
-/* constant time multiply by small integer of length bts - use ladder */
-	public ECP pinmul(int e,int bts) {
-		if (ROM.CURVETYPE==ROM.MONTGOMERY)
-			return this.mul(new BIG(e));
-		else
-		{
-			int nb,i,b;
-			ECP P=new ECP();
-			ECP R0=new ECP();
-			ECP R1=new ECP(); R1.copy(this);
-
-			for (i=bts-1;i>=0;i--)
-			{
-				b=(e>>i)&1;
-				P.copy(R1);
-				P.add(R0);
-				R0.cswap(R1,b);
-				R1.copy(P);
-				R0.dbl();
-				R0.cswap(R1,b);
-			}
-			P.copy(R0);
-			P.affine();
-			return P;
-		}
-	}
-
-/* return e.this */
-
-	public ECP mul(BIG e) {
-		if (e.iszilch() || is_infinity()) return new ECP();
-
-		ECP P=new ECP();
-		if (ROM.CURVETYPE==ROM.MONTGOMERY)
-		{
-/* use Ladder */
-			int nb,i,b;
-			ECP D=new ECP();
-			ECP R0=new ECP(); R0.copy(this);
-			ECP R1=new ECP(); R1.copy(this);
-			R1.dbl();
-			D.copy(this); D.affine();
-			nb=e.nbits();
-			for (i=nb-2;i>=0;i--)
-			{
-				b=e.bit(i);
-				P.copy(R1);
-				P.dadd(R0,D);
-				R0.cswap(R1,b);
-				R1.copy(P);
-				R0.dbl();
-				R0.cswap(R1,b);
-			}
-			P.copy(R0);
-		}
-		else
-		{
-// fixed size windows
-			int i,b,nb,m,s,ns;
-			BIG mt=new BIG();
-			BIG t=new BIG();
-			ECP Q=new ECP();
-			ECP C=new ECP();
-			ECP[] W=new ECP[8];
-			byte[] w=new byte[1+(ROM.NLEN*ROM.BASEBITS+3)/4];
-
-			affine();
-
-// precompute table
-			Q.copy(this);
-			Q.dbl();
-			W[0]=new ECP();
-			W[0].copy(this);
-
-			for (i=1;i<8;i++)
-			{
-				W[i]=new ECP();
-				W[i].copy(W[i-1]);
-				W[i].add(Q);
-			}
-
-// convert the table to affine
-			if (ROM.CURVETYPE==ROM.WEIERSTRASS)
-				multiaffine(8,W);
-
-// make exponent odd - add 2P if even, P if odd
-			t.copy(e);
-			s=t.parity();
-			t.inc(1); t.norm(); ns=t.parity(); mt.copy(t); mt.inc(1); mt.norm();
-			t.cmove(mt,s);
-			Q.cmove(this,ns);
-			C.copy(Q);
-
-			nb=1+(t.nbits()+3)/4;
-
-// convert exponent to signed 4-bit window
-			for (i=0;i<nb;i++)
-			{
-				w[i]=(byte)(t.lastbits(5)-16);
-				t.dec(w[i]); t.norm();
-				t.fshr(4);
-			}
-			w[nb]=(byte)t.lastbits(5);
-
-			P.copy(W[(w[nb]-1)/2]);
-			for (i=nb-1;i>=0;i--)
-			{
-				Q.select(W,w[i]);
-				P.dbl();
-				P.dbl();
-				P.dbl();
-				P.dbl();
-				P.add(Q);
-			}
-			P.sub(C); /* apply correction */
-		}
-		P.affine();
-		return P;
-	}
-
-/* Return e.this+f.Q */
-
-	public ECP mul2(BIG e,ECP Q,BIG f) {
-		BIG te=new BIG();
-		BIG tf=new BIG();
-		BIG mt=new BIG();
-		ECP S=new ECP();
-		ECP T=new ECP();
-		ECP C=new ECP();
-		ECP[] W=new ECP[8];
-		byte[] w=new byte[1+(ROM.NLEN*ROM.BASEBITS+1)/2];
-		int i,s,ns,nb;
-		byte a,b;
-
-		affine();
-		Q.affine();
-
-		te.copy(e);
-		tf.copy(f);
-
-// precompute table
-		W[1]=new ECP(); W[1].copy(this); W[1].sub(Q);
-		W[2]=new ECP(); W[2].copy(this); W[2].add(Q);
-		S.copy(Q); S.dbl();
-		W[0]=new ECP(); W[0].copy(W[1]); W[0].sub(S);
-		W[3]=new ECP(); W[3].copy(W[2]); W[3].add(S);
-		T.copy(this); T.dbl();
-		W[5]=new ECP(); W[5].copy(W[1]); W[5].add(T);
-		W[6]=new ECP(); W[6].copy(W[2]); W[6].add(T);
-		W[4]=new ECP(); W[4].copy(W[5]); W[4].sub(S);
-		W[7]=new ECP(); W[7].copy(W[6]); W[7].add(S);
-
-// convert the table to affine
-		if (ROM.CURVETYPE==ROM.WEIERSTRASS)
-			multiaffine(8,W);
-
-// if multiplier is odd, add 2, else add 1 to multiplier, and add 2P or P to correction
-
-		s=te.parity();
-		te.inc(1); te.norm(); ns=te.parity(); mt.copy(te); mt.inc(1); mt.norm();
-		te.cmove(mt,s);
-		T.cmove(this,ns);
-		C.copy(T);
-
-		s=tf.parity();
-		tf.inc(1); tf.norm(); ns=tf.parity(); mt.copy(tf); mt.inc(1); mt.norm();
-		tf.cmove(mt,s);
-		S.cmove(Q,ns);
-		C.add(S);
-
-		mt.copy(te); mt.add(tf); mt.norm();
-		nb=1+(mt.nbits()+1)/2;
-
-// convert exponent to signed 2-bit window
-		for (i=0;i<nb;i++)
-		{
-			a=(byte)(te.lastbits(3)-4);
-			te.dec(a); te.norm();
-			te.fshr(2);
-			b=(byte)(tf.lastbits(3)-4);
-			tf.dec(b); tf.norm();
-			tf.fshr(2);
-			w[i]=(byte)(4*a+b);
-		}
-		w[nb]=(byte)(4*te.lastbits(3)+tf.lastbits(3));
-		S.copy(W[(w[nb]-1)/2]);
-
-		for (i=nb-1;i>=0;i--)
-		{
-			T.select(W,w[i]);
-			S.dbl();
-			S.dbl();
-			S.add(T);
-		}
-		S.sub(C); /* apply correction */
-		S.affine();
-		return S;
-	}
-
-/*
-	public static void main(String[] args) {
-
-		BIG Gx=new BIG(ROM.CURVE_Gx);
-		BIG Gy;
-		ECP P;
-		if (ROM.CURVETYPE!=ROM.MONTGOMERY) Gy=new BIG(ROM.CURVE_Gy);
-		BIG r=new BIG(ROM.CURVE_Order);
-
-		//r.dec(7);
-
-		System.out.println("Gx= "+Gx.toString());
-		if (ROM.CURVETYPE!=ROM.MONTGOMERY) System.out.println("Gy= "+Gy.toString());
-
-		if (ROM.CURVETYPE!=ROM.MONTGOMERY) P=new ECP(Gx,Gy);
-		else  P=new ECP(Gx);
-
-		System.out.println("P= "+P.toString());
-
-		ECP R=P.mul(r);
-		//for (int i=0;i<10000;i++)
-		//	R=P.mul(r);
-
-		System.out.println("R= "+R.toString());
-    } */
-}
-
diff --git a/java/ECP2.java b/java/ECP2.java
deleted file mode 100755
index e89237d..0000000
--- a/java/ECP2.java
+++ /dev/null
@@ -1,623 +0,0 @@
-/*
-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.
-*/
-
-/* AMCL Weierstrass elliptic curve functions over FP2 */
-
-public final class ECP2 {
-	private FP2 x;
-	private FP2 y;
-	private FP2 z;
-	private boolean INF;
-
-/* Constructor - set this=O */
-	public ECP2() {
-		INF=true;
-		x=new FP2(0);
-		y=new FP2(1);
-		z=new FP2(1);
-	}
-
-/* Test this=O? */
-	public boolean is_infinity() {
-		return INF;
-	}
-/* copy this=P */
-	public void copy(ECP2 P)
-	{
-		x.copy(P.x);
-		y.copy(P.y);
-		z.copy(P.z);
-		INF=P.INF;
-	}
-/* set this=O */
-	public void inf() {
-		INF=true;
-		x.zero();
-		y.zero();
-		z.zero();
-	}
-
-/* Conditional move of Q to P dependant on d */
-	public void cmove(ECP2 Q,int d)
-	{
-		x.cmove(Q.x,d);
-		y.cmove(Q.y,d);
-		z.cmove(Q.z,d);
-
-		boolean bd;
-		if (d==0) bd=false;
-		else bd=true;
-		INF^=(INF^Q.INF)&bd;
-	}
-
-/* return 1 if b==c, no branching */
-	public static int teq(int b,int c)
-	{
-		int x=b^c;
-		x-=1;  // if x=0, x now -1
-		return ((x>>31)&1);
-	}
-
-/* Constant time select from pre-computed table */
-	public void select(ECP2 W[],int b)
-	{
-		ECP2 MP=new ECP2();
-		int m=b>>31;
-		int babs=(b^m)-m;
-
-		babs=(babs-1)/2;
-
-		cmove(W[0],teq(babs,0));  // conditional move
-		cmove(W[1],teq(babs,1));
-		cmove(W[2],teq(babs,2));
-		cmove(W[3],teq(babs,3));
-		cmove(W[4],teq(babs,4));
-		cmove(W[5],teq(babs,5));
-		cmove(W[6],teq(babs,6));
-		cmove(W[7],teq(babs,7));
-
-		MP.copy(this);
-		MP.neg();
-		cmove(MP,(int)(m&1));
-	}
-
-/* Test if P == Q */
-	public boolean equals(ECP2 Q) {
-		if (is_infinity() && Q.is_infinity()) return true;
-		if (is_infinity() || Q.is_infinity()) return false;
-
-		FP2 zs2=new FP2(z); zs2.sqr();
-		FP2 zo2=new FP2(Q.z); zo2.sqr();
-		FP2 zs3=new FP2(zs2); zs3.mul(z);
-		FP2 zo3=new FP2(zo2); zo3.mul(Q.z);
-		zs2.mul(Q.x);
-		zo2.mul(x);
-		if (!zs2.equals(zo2)) return false;
-		zs3.mul(Q.y);
-		zo3.mul(y);
-		if (!zs3.equals(zo3)) return false;
-
-		return true;
-	}
-/* set this=-this */
-	public void neg() {
-		if (is_infinity()) return;
-		y.neg(); y.norm();
-		return;
-	}
-/* set to Affine - (x,y,z) to (x,y) */
-	public void affine() {
-		if (is_infinity()) return;
-		FP2 one=new FP2(1);
-		if (z.equals(one)) return;
-		z.inverse();
-
-		FP2 z2=new FP2(z);
-		z2.sqr();
-		x.mul(z2); x.reduce();
-		y.mul(z2);
-		y.mul(z);  y.reduce();
-		z.copy(one);
-	}
-/* extract affine x as FP2 */
-	public FP2 getX()
-	{
-		affine();
-		return x;
-	}
-/* extract affine y as FP2 */
-	public FP2 getY()
-	{
-		affine();
-		return y;
-	}
-/* extract projective x */
-	public FP2 getx()
-	{
-		return x;
-	}
-/* extract projective y */
-	public FP2 gety()
-	{
-		return y;
-	}
-/* extract projective z */
-	public FP2 getz()
-	{
-		return z;
-	}
-/* convert to byte array */
-	public void toBytes(byte[] b)
-	{
-		byte[] t=new byte[ROM.MODBYTES];
-		affine();
-		x.getA().toBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++)
-			b[i]=t[i];
-		x.getB().toBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++)
-			b[i+ROM.MODBYTES]=t[i];
-
-		y.getA().toBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++)
-			b[i+2*ROM.MODBYTES]=t[i];
-		y.getB().toBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++)
-			b[i+3*ROM.MODBYTES]=t[i];
-	}
-/* convert from byte array to point */
-	public static ECP2 fromBytes(byte[] b)
-	{
-		byte[] t=new byte[ROM.MODBYTES];
-		BIG ra;
-		BIG rb;
-
-		for (int i=0;i<ROM.MODBYTES;i++) t[i]=b[i];
-		ra=BIG.fromBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++) t[i]=b[i+ROM.MODBYTES];
-		rb=BIG.fromBytes(t);
-		FP2 rx=new FP2(ra,rb);
-
-		for (int i=0;i<ROM.MODBYTES;i++) t[i]=b[i+2*ROM.MODBYTES];
-		ra=BIG.fromBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++) t[i]=b[i+3*ROM.MODBYTES];
-		rb=BIG.fromBytes(t);
-		FP2 ry=new FP2(ra,rb);
-
-		return new ECP2(rx,ry);
-	}
-/* convert this to hex string */
-	public String toString() {
-		if (is_infinity()) return "infinity";
-		affine();
-		return "("+x.toString()+","+y.toString()+")";
-	}
-
-/* Calculate RHS of twisted curve equation x^3+B/i */
-	public static FP2 RHS(FP2 x) {
-		x.norm();
-		FP2 r=new FP2(x);
-		r.sqr();
-		FP2 b=new FP2(new BIG(ROM.CURVE_B));
-		b.div_ip();
-		r.mul(x);
-		r.add(b);
-
-		r.reduce();
-		return r;
-	}
-
-/* construct this from (x,y) - but set to O if not on curve */
-	public ECP2(FP2 ix,FP2 iy) {
-		x=new FP2(ix);
-		y=new FP2(iy);
-		z=new FP2(1);
-		FP2 rhs=RHS(x);
-		FP2 y2=new FP2(y);
-		y2.sqr();
-		if (y2.equals(rhs)) INF=false;
-		else {x.zero();INF=true;}
-	}
-
-/* construct this from x - but set to O if not on curve */
-	public ECP2(FP2 ix) {
-		x=new FP2(ix);
-		y=new FP2(1);
-		z=new FP2(1);
-		FP2 rhs=RHS(x);
-		if (rhs.sqrt())
-		{
-			y.copy(rhs);
-			INF=false;
-		}
-		else {x.zero();INF=true;}
-	}
-
-/* this+=this */
-	public int dbl() {
-		if (INF) return -1;
-		if (y.iszilch())
-		{
-			inf();
-			return -1;
-		}
-
-		FP2 w1=new FP2(x);
-		FP2 w2=new FP2(0);
-		FP2 w3=new FP2(x);
-		FP2 w8=new FP2(x);
-
-		w1.sqr();
-		w8.copy(w1);
-		w8.imul(3);
-
-		w2.copy(y); w2.sqr();
-		w3.copy(x); w3.mul(w2);
-		w3.imul(4);
-		w1.copy(w3); w1.neg();
-		w1.norm();
-
-		x.copy(w8); x.sqr();
-		x.add(w1);
-		x.add(w1);
-		x.norm();
-
-		z.mul(y);
-		z.add(z);
-
-		w2.add(w2);
-		w2.sqr();
-		w2.add(w2);
-		w3.sub(x);
-		y.copy(w8); y.mul(w3);
-		w2.norm();
-		y.sub(w2);
-		y.norm();
-		z.norm();
-
-		return 1;
-	}
-
-/* this+=Q - return 0 for add, 1 for double, -1 for O */
-	public int add(ECP2 Q) {
-		if (INF)
-		{
-			copy(Q);
-			return -1;
-		}
-		if (Q.INF) return -1;
-
-		boolean aff=false;
-
-		if (Q.z.isunity()) aff=true;
-
-		FP2 A,C;
-		FP2 B=new FP2(z);
-		FP2 D=new FP2(z);
-		if (!aff)
-		{
-			A=new FP2(Q.z);
-			C=new FP2(Q.z);
-
-			A.sqr(); B.sqr();
-			C.mul(A); D.mul(B);
-
-			A.mul(x);
-			C.mul(y);
-		}
-		else
-		{
-			A=new FP2(x);
-			C=new FP2(y);
-
-			B.sqr();
-			D.mul(B);
-		}
-
-		B.mul(Q.x); B.sub(A);
-		D.mul(Q.y); D.sub(C);
-
-		if (B.iszilch())
-		{
-			if (D.iszilch())
-			{
-				dbl();
-				return 1;
-			}
-			else
-			{
-				INF=true;
-				return -1;
-			}
-		}
-
-		if (!aff) z.mul(Q.z);
-		z.mul(B);
-
-		FP2 e=new FP2(B); e.sqr();
-		B.mul(e);
-		A.mul(e);
-
-		e.copy(A);
-		e.add(A); e.add(B);
-		x.copy(D); x.sqr(); x.sub(e);
-
-		A.sub(x);
-		y.copy(A); y.mul(D);
-		C.mul(B); y.sub(C);
-
-		x.norm();
-		y.norm();
-		z.norm();
-
-		return 0;
-	}
-
-/* set this-=Q */
-	public int sub(ECP2 Q) {
-		Q.neg();
-		int D=add(Q);
-		Q.neg();
-		return D;
-	}
-/* set this*=q, where q is Modulus, using Frobenius */
-	public void frob(FP2 X)
-	{
-		if (INF) return;
-		FP2 X2=new FP2(X);
-		X2.sqr();
-		x.conj();
-		y.conj();
-		z.conj();
-		z.reduce();
-		x.mul(X2);
-		y.mul(X2);
-		y.mul(X);
-	}
-
-/* normalises m-array of ECP2 points. Requires work vector of m FP2s */
-
-	public static void multiaffine(int m,ECP2[] P)
-	{
-		int i;
-		FP2 t1=new FP2(0);
-		FP2 t2=new FP2(0);
-
-		FP2[] work=new FP2[m];
-		work[0]=new FP2(1);
-		work[1]=new FP2(P[0].z);
-		for (i=2;i<m;i++)
-		{
-			work[i]=new FP2(work[i-1]);
-			work[i].mul(P[i-1].z);
-		}
-
-		t1.copy(work[m-1]); t1.mul(P[m-1].z);
-
-		t1.inverse();
-
-		t2.copy(P[m-1].z);
-		work[m-1].mul(t1);
-
-		for (i=m-2;;i--)
-		{
-			if (i==0)
-			{
-				work[0].copy(t1);
-				work[0].mul(t2);
-				break;
-			}
-			work[i].mul(t2);
-			work[i].mul(t1);
-			t2.mul(P[i].z);
-		}
-/* now work[] contains inverses of all Z coordinates */
-
-		for (i=0;i<m;i++)
-		{
-			P[i].z.one();
-			t1.copy(work[i]); t1.sqr();
-			P[i].x.mul(t1);
-			t1.mul(work[i]);
-			P[i].y.mul(t1);
-		}
-	}
-
-/* P*=e */
-	public ECP2 mul(BIG e)
-	{
-/* fixed size windows */
-		int i,b,nb,m,s,ns;
-		BIG mt=new BIG();
-		BIG t=new BIG();
-		ECP2 P=new ECP2();
-		ECP2 Q=new ECP2();
-		ECP2 C=new ECP2();
-		ECP2[] W=new ECP2[8];
-		byte[] w=new byte[1+(ROM.NLEN*ROM.BASEBITS+3)/4];
-
-		if (is_infinity()) return new ECP2();
-
-		affine();
-
-/* precompute table */
-		Q.copy(this);
-		Q.dbl();
-		W[0]=new ECP2();
-		W[0].copy(this);
-
-		for (i=1;i<8;i++)
-		{
-			W[i]=new ECP2();
-			W[i].copy(W[i-1]);
-			W[i].add(Q);
-		}
-
-/* convert the table to affine */
-
-		multiaffine(8,W);
-
-/* make exponent odd - add 2P if even, P if odd */
-		t.copy(e);
-		s=t.parity();
-		t.inc(1); t.norm(); ns=t.parity(); mt.copy(t); mt.inc(1); mt.norm();
-		t.cmove(mt,s);
-		Q.cmove(this,ns);
-		C.copy(Q);
-
-		nb=1+(t.nbits()+3)/4;
-/* convert exponent to signed 4-bit window */
-		for (i=0;i<nb;i++)
-		{
-			w[i]=(byte)(t.lastbits(5)-16);
-			t.dec(w[i]); t.norm();
-			t.fshr(4);
-		}
-		w[nb]=(byte)t.lastbits(5);
-
-		P.copy(W[(w[nb]-1)/2]);
-		for (i=nb-1;i>=0;i--)
-		{
-			Q.select(W,w[i]);
-			P.dbl();
-			P.dbl();
-			P.dbl();
-			P.dbl();
-			P.add(Q);
-		}
-		P.sub(C);
-		P.affine();
-		return P;
-	}
-
-/* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3 */
-	public static ECP2 mul4(ECP2[] Q,BIG[] u)
-	{
-		int i,j,nb;
-		int[] a=new int[4];
-		ECP2 T=new ECP2();
-		ECP2 C=new ECP2();
-		ECP2 P=new ECP2();
-		ECP2[] W=new ECP2[8];
-
-		BIG mt=new BIG();
-		BIG[] t=new BIG[4];
-
-		byte[] w=new byte[ROM.NLEN*ROM.BASEBITS+1];
-
-		for (i=0;i<4;i++)
-		{
-			t[i]=new BIG(u[i]);
-			Q[i].affine();
-		}
-
-/* precompute table */
-
-		W[0]=new ECP2(); W[0].copy(Q[0]); W[0].sub(Q[1]);
-		W[1]=new ECP2(); W[1].copy(W[0]);
-		W[2]=new ECP2(); W[2].copy(W[0]);
-		W[3]=new ECP2(); W[3].copy(W[0]);
-		W[4]=new ECP2(); W[4].copy(Q[0]); W[4].add(Q[1]);
-		W[5]=new ECP2(); W[5].copy(W[4]);
-		W[6]=new ECP2(); W[6].copy(W[4]);
-		W[7]=new ECP2(); W[7].copy(W[4]);
-		T.copy(Q[2]); T.sub(Q[3]);
-		W[1].sub(T);
-		W[2].add(T);
-		W[5].sub(T);
-		W[6].add(T);
-		T.copy(Q[2]); T.add(Q[3]);
-		W[0].sub(T);
-		W[3].add(T);
-		W[4].sub(T);
-		W[7].add(T);
-
-		multiaffine(8,W);
-
-/* if multiplier is even add 1 to multiplier, and add P to correction */
-		mt.zero(); C.inf();
-		for (i=0;i<4;i++)
-		{
-			if (t[i].parity()==0)
-			{
-				t[i].inc(1); t[i].norm();
-				C.add(Q[i]);
-			}
-			mt.add(t[i]); mt.norm();
-		}
-
-		nb=1+mt.nbits();
-
-/* convert exponent to signed 1-bit window */
-		for (j=0;j<nb;j++)
-		{
-			for (i=0;i<4;i++)
-			{
-				a[i]=(byte)(t[i].lastbits(2)-2);
-				t[i].dec(a[i]); t[i].norm();
-				t[i].fshr(1);
-			}
-			w[j]=(byte)(8*a[0]+4*a[1]+2*a[2]+a[3]);
-		}
-		w[nb]=(byte)(8*t[0].lastbits(2)+4*t[1].lastbits(2)+2*t[2].lastbits(2)+t[3].lastbits(2));
-
-		P.copy(W[(w[nb]-1)/2]);
-		for (i=nb-1;i>=0;i--)
-		{
-			T.select(W,w[i]);
-			P.dbl();
-			P.add(T);
-		}
-		P.sub(C); /* apply correction */
-
-		P.affine();
-		return P;
-	}
-
-/*
-	public static void main(String[] args) {
-		BIG r=new BIG(ROM.Modulus);
-
-		BIG Pxa=new BIG(ROM.CURVE_Pxa);
-		BIG Pxb=new BIG(ROM.CURVE_Pxb);
-		BIG Pya=new BIG(ROM.CURVE_Pya);
-		BIG Pyb=new BIG(ROM.CURVE_Pyb);
-
-		BIG Fra=new BIG(ROM.CURVE_Fra);
-		BIG Frb=new BIG(ROM.CURVE_Frb);
-
-		FP2 f=new FP2(Fra,Frb);
-
-		FP2 Px=new FP2(Pxa,Pxb);
-		FP2 Py=new FP2(Pya,Pyb);
-
-		ECP2 P=new ECP2(Px,Py);
-
-		System.out.println("P= "+P.toString());
-
-		P=P.mul(r);
-		System.out.println("P= "+P.toString());
-
-		ECP2 Q=new ECP2(Px,Py);
-		Q.frob(f);
-		System.out.println("Q= "+Q.toString());
-	} */
-
-
-}
diff --git a/java/FF.java b/java/FF.java
deleted file mode 100755
index e02d47b..0000000
--- a/java/FF.java
+++ /dev/null
@@ -1,974 +0,0 @@
-/*
-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.
-*/
-
-/* Java Large Finite Field arithmetic */
-/* AMCL mod p functions */
-
-public final class FF {
-	private final BIG[] v;
-	private final int length;
-
-	private static final int P_MBITS=ROM.MODBYTES*8;
-	private static final int P_MB=(P_MBITS%ROM.BASEBITS);
-	private static final int P_OMASK=((int)(-1)<<(P_MBITS%ROM.BASEBITS));
-	private static final int P_FEXCESS=((int)1<<(ROM.BASEBITS*ROM.NLEN-P_MBITS));
-	private static final int P_TBITS=(P_MBITS%ROM.BASEBITS);
-
-	public int P_EXCESS()
-	{
-		return ((v[length-1].get(ROM.NLEN-1)&P_OMASK)>>(P_MB));
-	}
-
-/* Constructors */
-	public FF(int n)
-	{
-		v=new BIG[n];
-		for (int i=0;i<n;i++)
-			v[i]=new BIG(0);
-		length=n;
-	}
-
-	public FF(int [][] x,int n)
-	{
-		v=new BIG[n];
-		for (int i=0;i<n;i++)
-			v[i]=new BIG(x[i]);
-		length=n;
-	}
-
-	public int getlen()
-	{
-		return length;
-	}
-
-/* set to integer */
-	public void set(int m)
-	{
-		zero();
-		v[0].set(0,(int)(m&ROM.MASK));
-		v[0].set(1,(int)(m>>ROM.BASEBITS));
-	}
-
-/* copy from FF b */
-	public void copy(FF b)
-	{
-		for (int i=0;i<length;i++)
-		{
-			v[i].copy(b.v[i]);
-		}
-	}
-
-/* x=y<<n */
-	public void dsucopy(FF b)
-	{
-		for (int i=0;i<b.length;i++)
-		{
-			v[b.length+i].copy(b.v[i]);
-			v[i].zero();
-		}
-	}
-
-/* x=y */
-	public void dscopy(FF b)
-	{
-		for (int i=0;i<b.length;i++)
-		{
-			v[i].copy(b.v[i]);
-			v[b.length+i].zero();
-		}
-	}
-
-/* x=y>>n */
-	public void sducopy(FF b)
-	{
-		for (int i=0;i<length;i++)
-		{
-			v[i].copy(b.v[length+i]);
-		}
-	}
-
-/* set to zero */
-	public void zero()
-	{
-		for (int i=0;i<length;i++)
-		{
-			v[i].zero();
-		}
-	}
-
-	public void one()
-	{
-		v[0].one();
-		for (int i=1;i<length;i++)
-		{
-			v[i].zero();
-		}
-	}
-
-/* test equals 0 */
-	public boolean iszilch()
-	{
-		for (int i=0;i<length;i++)
-		{
-			if (!v[i].iszilch()) return false;
-		}
-		return true;
-	}
-
-/* shift right by 256-bit words */
-	public void shrw(int n)
-	{
-		for (int i=0;i<n;i++)
-		{
-			v[i].copy(v[i+n]);
-			v[i+n].zero();
-		}
-	}
-
-/* shift left by 256-bit words */
-	public void shlw(int n)
-	{
-		for (int i=0;i<n;i++)
-		{
-			v[n+i].copy(v[i]);
-			v[i].zero();
-		}
-	}
-
-/* extract last bit */
-	public int parity()
-	{
-		return v[0].parity();
-	}
-
-	public int lastbits(int m)
-	{
-		return v[0].lastbits(m);
-	}
-
-/* compare x and y - must be normalised, and of same length */
-	public static int comp(FF a,FF b)
-	{
-		int i,j;
-		for (i=a.length-1;i>=0;i--)
-		{
-			j=BIG.comp(a.v[i],b.v[i]);
-			if (j!=0) return j;
-		}
-		return 0;
-	}
-
-/* recursive add */
-	public void radd(int vp,FF x,int xp,FF y,int yp,int n)
-	{
-		for (int i=0;i<n;i++)
-		{
-			v[vp+i].copy(x.v[xp+i]);
-			v[vp+i].add(y.v[yp+i]);
-		}
-	}
-
-/* recursive inc */
-	public void rinc(int vp,FF y,int yp,int n)
-	{
-		for (int i=0;i<n;i++)
-		{
-			v[vp+i].add(y.v[yp+i]);
-		}
-	}
-
-/* recursive sub */
-	public void rsub(int vp,FF x,int xp,FF y,int yp,int n)
-	{
-		for (int i=0;i<n;i++)
-		{
-			v[vp+i].copy(x.v[xp+i]);
-			v[vp+i].sub(y.v[yp+i]);
-		}
-	}
-
-/* recursive dec */
-	public void rdec(int vp,FF y,int yp,int n)
-	{
-		for (int i=0;i<n;i++)
-		{
-			v[vp+i].sub(y.v[yp+i]);
-		}
-	}
-
-/* simple add */
-	public void add(FF b)
-	{
-		for (int i=0;i<length;i++)
-			v[i].add(b.v[i]);
-	}
-
-/* simple sub */
-	public void sub(FF b)
-	{
-		for (int i=0;i<length;i++)
-			v[i].sub(b.v[i]);
-	}
-
-/* reverse sub */
-	public void revsub(FF b)
-	{
-		for (int i=0;i<length;i++)
-			v[i].rsub(b.v[i]);
-	}
-
-/* increment/decrement by a small integer */
-	public void inc(int m)
-	{
-		v[0].inc(m);
-		norm();
-	}
-
-	public void dec(int m)
-	{
-		v[0].dec(m);
-		norm();
-	}
-
-	/* normalise - but hold any overflow in top part unless n<0 */
-	private void rnorm(int vp,int n)
-	{
-		boolean trunc=false;
-		int i,carry;
-		if (n<0)
-		{ /* -v n signals to do truncation */
-			n=-n;
-			trunc=true;
-		}
-		for (i=0;i<n-1;i++)
-		{
-			carry=v[vp+i].norm();
-			v[vp+i].xortop(carry<<P_TBITS);
-			v[vp+i+1].inc(carry);
-		}
-		carry=v[vp+n-1].norm();
-		if (trunc)
-			v[vp+n-1].xortop(carry<<P_TBITS);
-
-	}
-
-	public void norm()
-	{
-		rnorm(0,length);
-	}
-
-/* shift left by one bit */
-	public void shl()
-	{
-		int i,carry,delay_carry=0;
-		for (i=0;i<length-1;i++)
-		{
-			carry=v[i].fshl(1);
-			v[i].inc(delay_carry);
-			v[i].xortop(carry<<P_TBITS);
-			delay_carry=carry;
-		}
-		v[length-1].fshl(1);
-		v[length-1].inc(delay_carry);
-	}
-
-/* shift right by one bit */
-
-	public void shr()
-	{
-		int i,carry;
-		for (i=length-1;i>0;i--)
-		{
-			carry=v[i].fshr(1);
-			v[i-1].ortop(carry<<P_TBITS);
-		}
-		v[0].fshr(1);
-	}
-
-/* Convert to Hex String */
-	public String toString()
-	{
-		norm();
-		String s="";
-		for (int i=length-1;i>=0;i--)
-		{
-			s+=v[i].toString();
-		}
-		return s;
-	}
-
-/* Convert FFs to/from byte arrays */
-	public void toBytes(byte[] b)
-	{
-		for (int i=0;i<length;i++)
-		{
-			v[i].tobytearray(b,(length-i-1)*ROM.MODBYTES);
-		}
-	}
-
-	public static void fromBytes(FF x,byte[] b)
-	{
-		for (int i=0;i<x.length;i++)
-		{
-			x.v[i]=BIG.frombytearray(b,(x.length-i-1)*ROM.MODBYTES);
-		}
-	}
-
-/* in-place swapping using xor - side channel resistant - lengths must be the same */
-	private static void cswap(FF a,FF b,int d)
-	{
-		for (int i=0;i<a.length;i++)
-		{
-		//	BIG.cswap(a.v[i],b.v[i],d);
-			a.v[i].cswap(b.v[i],d);
-		}
-	}
-
-/* z=x*y, t is workspace */
-	private void karmul(int vp,FF x,int xp,FF y,int yp,FF t,int tp,int n)
-	{
-		int nd2;
-		if (n==1)
-		{
-			DBIG d=BIG.mul(x.v[xp],y.v[yp]);
-			v[vp+1]=d.split(8*ROM.MODBYTES);
-			v[vp].copy(d);
-			return;
-		}
-		nd2=n/2;
-		radd(vp,x,xp,x,xp+nd2,nd2);
-		rnorm(vp,nd2);
-		radd(vp+nd2,y,yp,y,yp+nd2,nd2);
-		rnorm(vp+nd2,nd2);
-		t.karmul(tp,this,vp,this,vp+nd2,t,tp+n,nd2);
-		karmul(vp,x,xp,y,yp,t,tp+n,nd2);
-		karmul(vp+n,x,xp+nd2,y,yp+nd2,t,tp+n,nd2);
-		t.rdec(tp,this,vp,n);
-		t.rdec(tp,this,vp+n,n);
-		rinc(vp+nd2,t,tp,n);
-		rnorm(vp,2*n);
-	}
-
-	private void karsqr(int vp,FF x,int xp,FF t,int tp,int n)
-	{
-		int nd2;
-		if (n==1)
-		{
-			DBIG d=BIG.sqr(x.v[xp]);
-			v[vp+1].copy(d.split(8*ROM.MODBYTES));
-			v[vp].copy(d);
-			return;
-		}
-
-		nd2=n/2;
-		karsqr(vp,x,xp,t,tp+n,nd2);
-		karsqr(vp+n,x,xp+nd2,t,tp+n,nd2);
-		t.karmul(tp,x,xp,x,xp+nd2,t,tp+n,nd2);
-		rinc(vp+nd2,t,tp,n);
-		rinc(vp+nd2,t,tp,n);
-		rnorm(vp+nd2,n);
-	}
-
-
-	private void karmul_lower(int vp,FF x,int xp,FF y,int yp,FF t,int tp,int n)
-	{ /* Calculates Least Significant bottom half of x*y */
-		int nd2;
-		if (n==1)
-		{ /* only calculate bottom half of product */
-			v[vp].copy(BIG.smul(x.v[xp],y.v[yp]));
-			return;
-		}
-		nd2=n/2;
-
-		karmul(vp,x,xp,y,yp,t,tp+n,nd2);
-		t.karmul_lower(tp,x,xp+nd2,y,yp,t,tp+n,nd2);
-		rinc(vp+nd2,t,tp,nd2);
-		t.karmul_lower(tp,x,xp,y,yp+nd2,t,tp+n,nd2);
-		rinc(vp+nd2,t,tp,nd2);
-		rnorm(vp+nd2,-nd2);  /* truncate it */
-	}
-
-	private void karmul_upper(FF x,FF y,FF t,int n)
-	{ /* Calculates Most Significant upper half of x*y, given lower part */
-		int nd2;
-
-		nd2=n/2;
-		radd(n,x,0,x,nd2,nd2);
-		radd(n+nd2,y,0,y,nd2,nd2);
-
-		t.karmul(0,this,n+nd2,this,n,t,n,nd2);  /* t = (a0+a1)(b0+b1) */
-		karmul(n,x,nd2,y,nd2,t,n,nd2); /* z[n]= a1*b1 */
-									/* z[0-nd2]=l(a0b0) z[nd2-n]= h(a0b0)+l(t)-l(a0b0)-l(a1b1) */
-		t.rdec(0,this,n,n);              /* t=t-a1b1  */
-		rinc(nd2,this,0,nd2);   /* z[nd2-n]+=l(a0b0) = h(a0b0)+l(t)-l(a1b1)  */
-		rdec(nd2,t,0,nd2);   /* z[nd2-n]=h(a0b0)+l(t)-l(a1b1)-l(t-a1b1)=h(a0b0) */
-		rnorm(0,-n);					/* a0b0 now in z - truncate it */
-		t.rdec(0,this,0,n);         /* (a0+a1)(b0+b1) - a0b0 */
-		rinc(nd2,t,0,n);
-
-		rnorm(nd2,n);
-	}
-
-	/* z=x*y. Assumes x and y are of same length. */
-	public static FF mul(FF x,FF y)
-	{
-		int n=x.length;
-		FF z=new FF(2*n);
-		FF t=new FF(2*n);
-		z.karmul(0,x,0,y,0,t,0,n);
-		return z;
-	}
-
-	/* z=x^2 */
-	public static FF sqr(FF x)
-	{
-		int n=x.length;
-		FF z=new FF(2*n);
-		FF t=new FF(2*n);
-		z.karsqr(0,x,0,t,0,n);
-		return z;
-	}
-
-/* return low part of product this*y */
-	public void lmul(FF y)
-	{
-		int n=length;
-		FF t=new FF(2*n);
-		FF x=new FF(n); x.copy(this);
-		karmul_lower(0,x,0,y,0,t,0,n);
-	}
-
-/* Set b=b mod c */
-	public void mod(FF c)
-	{
-		int k=0;
-
-		norm();
-		if (comp(this,c)<0)
-			return;
-		do
-		{
-			c.shl();
-			k++;
-		} while (comp(this,c)>=0);
-
-		while (k>0)
-		{
-			c.shr();
-			if (comp(this,c)>=0)
-			{
-				sub(c);
-				norm();
-			}
-			k--;
-		}
-	}
-
-/* return This mod modulus, N is modulus, ND is Montgomery Constant */
-	public FF reduce(FF N,FF ND)
-	{ /* fast karatsuba Montgomery reduction */
-		int n=N.length;
-		FF t=new FF(2*n);
-		FF r=new FF(n);
-		FF m=new FF(n);
-
-		r.sducopy(this);
-		m.karmul_lower(0,this,0,ND,0,t,0,n);
-		karmul_upper(N,m,t,n);
-		m.sducopy(this);
-
-		r.add(N);
-		r.sub(m);
-		r.norm();
-
-		return r;
-
-	}
-
-/* Set r=this mod b */
-/* this is of length - 2*n */
-/* r,b is of length - n */
-	public FF dmod(FF b)
-	{
-		int k,n=b.length;
-		FF m=new FF(2*n);
-		FF x=new FF(2*n);
-		FF r=new FF(n);
-
-		x.copy(this);
-		x.norm();
-		m.dsucopy(b); k=256*n;
-
-		while (k>0)
-		{
-			m.shr();
-
-			if (comp(x,m)>=0)
-			{
-				x.sub(m);
-				x.norm();
-			}
-			k--;
-		}
-
-		r.copy(x);
-		r.mod(b);
-		return r;
-	}
-
-/* Set return=1/this mod p. Binary method - a<p on entry */
-
-	public void invmodp(FF p)
-	{
-		int n=p.length;
-
-		FF u=new FF(n);
-		FF v=new FF(n);
-		FF x1=new FF(n);
-		FF x2=new FF(n);
-		FF t=new FF(n);
-		FF one=new FF(n);
-
-		one.one();
-		u.copy(this);
-		v.copy(p);
-		x1.copy(one);
-		x2.zero();
-
-	// reduce n in here as well!
-		while (comp(u,one)!=0 && comp(v,one)!=0)
-		{
-			while (u.parity()==0)
-			{
-				u.shr();
-				if (x1.parity()!=0)
-				{
-					x1.add(p);
-					x1.norm();
-				}
-				x1.shr();
-			}
-			while (v.parity()==0)
-			{
-				v.shr();
-				if (x2.parity()!=0)
-				{
-					x2.add(p);
-					x2.norm();
-				}
-				x2.shr();
-			}
-			if (comp(u,v)>=0)
-			{
-
-				u.sub(v);
-				u.norm();
-				if (comp(x1,x2)>=0) x1.sub(x2);
-				else
-				{
-					t.copy(p);
-					t.sub(x2);
-					x1.add(t);
-				}
-				x1.norm();
-			}
-			else
-			{
-				v.sub(u);
-				v.norm();
-				if (comp(x2,x1)>=0) x2.sub(x1);
-				else
-				{
-					t.copy(p);
-					t.sub(x1);
-					x2.add(t);
-				}
-				x2.norm();
-			}
-		}
-		if (comp(u,one)==0)
-			copy(x1);
-		else
-			copy(x2);
-	}
-
-/* nresidue mod m */
-	public void nres(FF m)
-	{
-		int n=m.length;
-		FF d=new FF(2*n);
-		d.dsucopy(this);
-		copy(d.dmod(m));
-	}
-
-	public void redc(FF m,FF ND)
-	{
-		int n=m.length;
-		FF d=new FF(2*n);
-		mod(m);
-		d.dscopy(this);
-		copy(d.reduce(m,ND));
-		mod(m);
-	}
-
-	private void mod2m(int m)
-	{
-		for (int i=m;i<length;i++)
-			v[i].zero();
-	}
-
-	/* U=1/a mod 2^m - Arazi & Qi */
-	private FF invmod2m()
-	{
-		int i,n=length;
-
-		FF b=new FF(n);
-		FF c=new FF(n);
-		FF U=new FF(n);
-
-		FF t;
-
-		U.zero();
-		U.v[0].copy(v[0]);
-		U.v[0].invmod2m();
-
-		for (i=1;i<n;i<<=1)
-		{
-			b.copy(this); b.mod2m(i);
-			t=mul(U,b); t.shrw(i); b.copy(t);
-			c.copy(this); c.shrw(i); c.mod2m(i);
-			c.lmul(U); c.mod2m(i);
-
-			b.add(c); b.norm();
-			b.lmul(U); b.mod2m(i);
-
-			c.one(); c.shlw(i); b.revsub(c); b.norm();
-			b.shlw(i);
-			U.add(b);
-		}
-		U.norm();
-		return U;
-	}
-
-	public void random(RAND rng)
-	{
-		int n=length;
-		for (int i=0;i<n;i++)
-		{
-			v[i].copy(BIG.random(rng));
-		}
-	/* make sure top bit is 1 */
-		while (v[n-1].nbits()<ROM.MODBYTES*8) v[n-1].copy(BIG.random(rng));
-	}
-
-	/* generate random x */
-	public void randomnum(FF p,RAND rng)
-	{
-		int n=length;
-		FF d=new FF(2*n);
-
-		for (int i=0;i<2*n;i++)
-		{
-			d.v[i].copy(BIG.random(rng));
-		}
-		copy(d.dmod(p));
-	}
-
-	/* this*=y mod p */
-	public void modmul(FF y,FF p,FF nd)
-	{
-		int ex=P_EXCESS();
-		int ey=y.P_EXCESS();
-		if ((ex+1)*(ey+1)+1>=P_FEXCESS) mod(p);
-		FF d=mul(this,y);
-		copy(d.reduce(p,nd));
-	}
-
-	/* this*=y mod p */
-	public void modsqr(FF p,FF nd)
-	{
-		int ex=P_EXCESS();
-		if ((ex+1)*(ex+1)+1>=P_FEXCESS) mod(p);
-		FF d=sqr(this);
-		copy(d.reduce(p,nd));
-	}
-
-	/* this=this^e mod p using side-channel resistant Montgomery Ladder, for large e */
-	public void skpow(FF e,FF p)
-	{
-		int i,b,n=p.length;
-		FF R0=new FF(n);
-		FF R1=new FF(n);
-		FF ND=p.invmod2m();
-
-		mod(p);
-		R0.one();
-		R1.copy(this);
-		R0.nres(p);
-		R1.nres(p);
-
-		for (i=8*ROM.MODBYTES*n-1;i>=0;i--)
-		{
-			b=e.v[i/256].bit(i%256);
-			copy(R0);
-			modmul(R1,p,ND);
-
-			cswap(R0,R1,b);
-			R0.modsqr(p,ND);
-
-			R1.copy(this);
-			cswap(R0,R1,b);
-
-		}
-
-		copy(R0);
-		redc(p,ND);
-	}
-
-	/* this =this^e mod p using side-channel resistant Montgomery Ladder, for short e */
-	public void skpow(BIG e,FF p)
-	{
-		int i,b,n=p.length;
-		FF R0=new FF(n);
-		FF R1=new FF(n);
-		FF ND=p.invmod2m();
-
-		mod(p);
-		R0.one();
-		R1.copy(this);
-		R0.nres(p);
-		R1.nres(p);
-
-		for (i=8*ROM.MODBYTES-1;i>=0;i--)
-		{
-			b=e.bit(i);
-			copy(R0);
-			modmul(R1,p,ND);
-
-			cswap(R0,R1,b);
-			R0.modsqr(p,ND);
-
-			R1.copy(this);
-			cswap(R0,R1,b);
-		}
-		copy(R0);
-		redc(p,ND);
-	}
-
-	/* raise to an integer power - right-to-left method */
-	public void power(int e,FF p)
-	{
-		int n=p.length;
-		boolean f=true;
-		FF w=new FF(n);
-		FF ND=p.invmod2m();
-
-		w.copy(this);
-		w.nres(p);
-
-		if (e==2)
-		{
-			copy(w);
-			modsqr(p,ND);
-		}
-		else for (; ; )
-		{
-			if (e%2==1)
-			{
-				if (f) copy(w);
-				else modmul(w,p,ND);
-				f=false;
-			}
-			e>>=1;
-			if (e==0) break;
-			w.modsqr(p,ND);
-		}
-		redc(p,ND);
-	}
-
-	/* this=this^e mod p, faster but not side channel resistant */
-	public void pow(FF e,FF p)
-	{
-		int i,b,n=p.length;
-		FF w=new FF(n);
-		FF ND=p.invmod2m();
-
-		w.copy(this);
-		one();
-		nres(p);
-		w.nres(p);
-		for (i=8*ROM.MODBYTES*n-1;i>=0;i--)
-		{
-			modsqr(p,ND);
-			b=e.v[i/256].bit(i%256);
-			if (b==1) modmul(w,p,ND);
-		}
-		redc(p,ND);
-	}
-
-	/* double exponentiation r=x^e.y^f mod p */
-	public void pow2(BIG e,FF y,BIG f,FF p)
-	{
-		int i,eb,fb,n=p.length;
-		FF xn=new FF(n);
-		FF yn=new FF(n);
-		FF xy=new FF(n);
-		FF ND=p.invmod2m();
-
-		xn.copy(this);
-		yn.copy(y);
-		xn.nres(p);
-		yn.nres(p);
-		xy.copy(xn); xy.modmul(yn,p,ND);
-		one();
-		nres(p);
-
-		for (i=8*ROM.MODBYTES-1;i>=0;i--)
-		{
-			eb=e.bit(i);
-			fb=f.bit(i);
-			modsqr(p,ND);
-			if (eb==1)
-			{
-				if (fb==1) modmul(xy,p,ND);
-				else modmul(xn,p,ND);
-			}
-			else
-			{
-				if (fb==1) modmul(yn,p,ND);
-			}
-		}
-		redc(p,ND);
-	}
-
-	private static int igcd(int x,int y)
-	{ /* integer GCD, returns GCD of x and y */
-		int r;
-		if (y==0) return x;
-		while ((r=x%y)!=0)
-			{x=y;y=r;}
-		return y;
-	}
-
-	/* quick and dirty check for common factor with n */
-	public boolean cfactor(int s)
-	{
-		int r,n=length;
-		int g;
-
-		FF x=new FF(n);
-		FF y=new FF(n);
-
-		y.set(s);
-		x.copy(this);
-		x.norm();
-
-		do
-		{
-			x.sub(y);
-			x.norm();
-			while (!x.iszilch() && x.parity()==0) x.shr();
-		}
-		while (comp(x,y)>0);
-
-		g=x.v[0].get(0);
-		r=igcd(s,g);
-		if (r>1) return true;
-		return false;
-	}
-
-	/* Miller-Rabin test for primality. Slow. */
-	public static boolean prime(FF p,RAND rng)
-	{
-		int i,j,s=0,n=p.length;
-		boolean loop;
-		FF d=new FF(n);
-		FF x=new FF(n);
-		FF unity=new FF(n);
-		FF nm1=new FF(n);
-
-		int sf=4849845; /* 3*5*.. *19 */
-		p.norm();
-
-		if (p.cfactor(sf)) return false;
-		unity.one();
-		nm1.copy(p);
-		nm1.sub(unity);
-		nm1.norm();
-		d.copy(nm1);
-
-		while (d.parity()==0)
-		{
-			d.shr();
-			s++;
-		}
-		if (s==0) return false;
-		for (i=0;i<10;i++)
-		{
-			x.randomnum(p,rng);
-			x.pow(d,p);
-			if (comp(x,unity)==0 || comp(x,nm1)==0) continue;
-			loop=false;
-			for (j=1;j<s;j++)
-			{
-				x.power(2,p);
-				if (comp(x,unity)==0) return false;
-				if (comp(x,nm1)==0) {loop=true; break;}
-			}
-			if (loop) continue;
-			return false;
-		}
-		return true;
-	}
-
-
-//	public static final int[][] P ={{0x1670957,0x1568CD3C,0x2595E5,0xEED4F38,0x1FC9A971,0x14EF7E62,0xA503883,0x9E1E05E,0xBF59E3},{0x1844C908,0x1B44A798,0x3A0B1E7,0xD1B5B4E,0x1836046F,0x87E94F9,0x1D34C537,0xF7183B0,0x46D07},{0x17813331,0x19E28A90,0x1473A4D6,0x1CACD01F,0x1EEA8838,0xAF2AE29,0x1F85292A,0x1632585E,0xD945E5},{0x919F5EF,0x1567B39F,0x19F6AD11,0x16CE47CF,0x9B36EB1,0x35B7D3,0x483B28C,0xCBEFA27,0xB5FC21}};
-/*
-	public static final int[][] P= {{0x156FFDDF,0x5EC1ED,0xC6702D0,0x1C42FB6,0x1A3A50F0,0x1EE1811F,0x1AB28D94,0x1BE439E1,0x56790},{0x1D781CB3,0x1E3D731B,0x153A96F6,0x9AC443F,0x10628677,0x1F21365D,0x97B4301,0xDAD3A12,0xD6C46E},{0x833D55D,0xD44CF7B,0x4373422,0x22718D3,0x1E4CF3CA,0xB774703,0x117E2980,0x10C0F2A7,0x10D8B7},{0x1A784949,0x1483C3BF,0x7938D16,0x18E0E7B5,0x111E4EF6,0x20163B4,0x95FEBE,0x129E8526,0xF48167}};
-
-	public static void main(String[] args) {
-		byte[] raw=new byte[100];
-		RAND rng=new RAND();
-
-		rng.clean();
-		for (int i=0;i<100;i++) raw[i]=(byte)i;
-
-		rng.seed(100,raw);
-
-		int n=4;
-
-		FF x=new FF(n);
-		x.set(3);
-
-		FF p=new FF(P,n);
-
-	//	if (prime(p,rng)) System.out.println("p is a prime");
-
-		FF e=new FF(n);
-		e.copy(p);
-		e.dec(1); e.norm();
-
-		System.out.println("e= "+e.toString());
-
-		x.skpow(e,p);
-		System.out.println("x= "+x.toString());
-
-    } */
-
-}
diff --git a/java/FP.java b/java/FP.java
deleted file mode 100755
index 711a51d..0000000
--- a/java/FP.java
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
-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.
-*/
-
-/* Small Finite Field arithmetic */
-/* AMCL mod p functions */
-
-public final class FP {
-	private final BIG x;
-	private static BIG p=new BIG(ROM.Modulus);
-
-/* Constructors */
-	public FP(int a)
-	{
-		x=new BIG(a);
-		nres();
-	}
-
-	public FP()
-	{
-		x=new BIG(0);
-	}
-
-	public FP(BIG a)
-	{
-		x=new BIG(a);
-		nres();
-	}
-
-	public FP(FP a)
-	{
-		x=new BIG(a.x);
-	}
-
-/* convert to string */
-	public String toString()
-	{
-		String s=redc().toString();
-		return s;
-	}
-
-	public String toRawString()
-	{
-		String s=x.toRawString();
-		return s;
-	}
-
-/* convert to Montgomery n-residue form */
-	public void nres()
-	{
-		if (ROM.MODTYPE!=ROM.PSEUDO_MERSENNE)
-		{
-			DBIG d=new DBIG(x);
-			d.shl(ROM.NLEN*ROM.BASEBITS);
-			x.copy(d.mod(p));
-		}
-	}
-
-/* convert back to regular form */
-	public BIG redc()
-	{
-		if (ROM.MODTYPE!=ROM.PSEUDO_MERSENNE)
-		{
-			DBIG d=new DBIG(x);
-			return BIG.mod(d);
-		}
-		else
-		{
-			BIG r=new BIG(x);
-			return r;
-		}
-	}
-
-/* test this=0? */
-	public boolean iszilch() {
-		reduce();
-		return x.iszilch();
-	}
-
-/* copy from FP b */
-	public void copy(FP b)
-	{
-		x.copy(b.x);
-	}
-
-/* set this=0 */
-	public void zero()
-	{
-		x.zero();
-	}
-
-/* set this=1 */
-	public void one()
-	{
-		x.one(); nres();
-	}
-
-/* normalise this */
-	public void norm()
-	{
-		x.norm();
-	}
-
-/* swap FPs depending on d */
-	public void cswap(FP b,int d)
-	{
-		x.cswap(b.x,d);
-	}
-
-/* copy FPs depending on d */
-	public void cmove(FP b,int d)
-	{
-		x.cmove(b.x,d);
-	}
-
-/* this*=b mod Modulus */
-	public void mul(FP b)
-	{
-		int ea=BIG.EXCESS(x);
-		int eb=BIG.EXCESS(b.x);
-
-		if ((ea+1)*(eb+1)+1>=ROM.FEXCESS) reduce();
-
-		DBIG d=BIG.mul(x,b.x);
-		x.copy(BIG.mod(d));
-	}
-
-/* this*=c mod Modulus, where c is a small int */
-	public void imul(int c)
-	{
-		norm();
-		boolean s=false;
-		if (c<0)
-		{
-			c=-c;
-			s=true;
-		}
-		int afx=(BIG.EXCESS(x)+1)*(c+1)+1;
-		if (c<ROM.NEXCESS && afx<ROM.FEXCESS)
-		{
-			x.imul(c);
-		}
-		else
-		{
-			if (afx<ROM.FEXCESS) x.pmul(c);
-			else
-			{
-				DBIG d=x.pxmul(c);
-				x.copy(d.mod(p));
-			}
-		}
-		if (s) neg();
-		norm();
-	}
-
-/* this*=this mod Modulus */
-	public void sqr()
-	{
-		DBIG d;
-		int ea=BIG.EXCESS(x);
-		if ((ea+1)*(ea+1)+1>=ROM.FEXCESS)
-			reduce();
-
-		d=BIG.sqr(x);
-		x.copy(BIG.mod(d));
-	}
-
-/* this+=b */
-	public void add(FP b) {
-		x.add(b.x);
-		if (BIG.EXCESS(x)+2>=ROM.FEXCESS) reduce();
-	}
-
-/* this = -this mod Modulus */
-	public void neg()
-	{
-		int sb,ov;
-		BIG m=new BIG(p);
-
-		norm();
-
-		ov=BIG.EXCESS(x);
-		sb=1; while(ov!=0) {sb++;ov>>=1;}
-
-		m.fshl(sb);
-		x.rsub(m);
-
-		if (BIG.EXCESS(x)>=ROM.FEXCESS) reduce();
-	}
-
-/* this-=b */
-	public void sub(FP b)
-	{
-		FP n=new FP(b);
-		n.neg();
-		this.add(n);
-	}
-
-/* this/=2 mod Modulus */
-	public void div2()
-	{
-		x.norm();
-		if (x.parity()==0)
-			x.fshr(1);
-		else
-		{
-			x.add(p);
-			x.norm();
-			x.fshr(1);
-		}
-	}
-
-/* this=1/this mod Modulus */
-	public void inverse()
-	{
-		BIG r=redc();
-		r.invmodp(p);
-		x.copy(r);
-		nres();
-	}
-
-/* return TRUE if this==a */
-	public boolean equals(FP a)
-	{
-		a.reduce();
-		reduce();
-		if (BIG.comp(a.x,x)==0) return true;
-		return false;
-	}
-
-/* reduce this mod Modulus */
-	public void reduce()
-	{
-		x.mod(p);
-	}
-
-/* return this^e mod Modulus */
-	public FP pow(BIG e)
-	{
-		int bt;
-		FP r=new FP(1);
-		e.norm();
-		x.norm();
-		FP m=new FP(this);
-		while (true)
-		{
-			bt=e.parity();
-			e.fshr(1);
-			if (bt==1) r.mul(m);
-			if (e.iszilch()) break;
-			m.sqr();
-		}
-		r.x.mod(p);
-		return r;
-	}
-
-/* return sqrt(this) mod Modulus */
-	public FP sqrt()
-	{
-		reduce();
-		BIG b=new BIG(p);
-		if (ROM.MOD8==5)
-		{
-			b.dec(5); b.norm(); b.shr(3);
-			FP i=new FP(this); i.x.shl(1);
-			FP v=i.pow(b);
-			i.mul(v); i.mul(v);
-			i.x.dec(1);
-			FP r=new FP(this);
-			r.mul(v); r.mul(i);
-			r.reduce();
-			return r;
-		}
-		else
-		{
-			b.inc(1); b.norm(); b.shr(2);
-			return pow(b);
-		}
-	}
-
-/* return jacobi symbol (this/Modulus) */
-	public int jacobi()
-	{
-		BIG w=redc();
-		return w.jacobi(p);
-	}
-/*
-	public static void main(String[] args) {
-		BIG m=new BIG(ROM.Modulus);
-		BIG x=new BIG(3);
-		BIG e=new BIG(m);
-		e.dec(1);
-
-		System.out.println("m= "+m.nbits());
-
-
-		BIG r=x.powmod(e,m);
-
-		System.out.println("m= "+m.toString());
-		System.out.println("r= "+r.toString());
-
-		BIG.cswap(m,r,0);
-
-		System.out.println("m= "+m.toString());
-		System.out.println("r= "+r.toString());
-
-//		FP y=new FP(3);
-//		FP s=y.pow(e);
-//		System.out.println("s= "+s.toString());
-
-	} */
-}
diff --git a/java/FP12.java b/java/FP12.java
deleted file mode 100755
index b2f704c..0000000
--- a/java/FP12.java
+++ /dev/null
@@ -1,643 +0,0 @@
-/*
-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.
-*/
-
-/* AMCL Fp^12 functions */
-/* FP12 elements are of the form a+i.b+i^2.c */
-
-public final class FP12 {
-	private final FP4 a;
-	private final FP4 b;
-	private final FP4 c;
-/* reduce all components of this mod Modulus */
-	public void reduce()
-	{
-		a.reduce();
-		b.reduce();
-		c.reduce();
-	}
-/* normalise all components of this */
-	public void norm()
-	{
-		a.norm();
-		b.norm();
-		c.norm();
-	}
-/* test x==0 ? */
-	public boolean iszilch() {
-		reduce();
-		return (a.iszilch() && b.iszilch() && c.iszilch());
-	}
-/* test x==1 ? */
-	public boolean isunity() {
-		FP4 one=new FP4(1);
-		return (a.equals(one) && b.iszilch() && c.iszilch());
-	}
-/* return 1 if x==y, else 0 */
-	public boolean equals(FP12 x)
-	{
-		return (a.equals(x.a) && b.equals(x.b) && c.equals(x.c));
-	}
-/* extract a from this */
-	public FP4 geta()
-	{
-		return a;
-	}
-/* extract b */
-	public FP4 getb()
-	{
-		return b;
-	}
-/* extract c */
-	public FP4 getc()
-	{
-		return c;
-	}
-/* copy this=x */
-	public void copy(FP12 x)
-	{
-		a.copy(x.a);
-		b.copy(x.b);
-		c.copy(x.c);
-	}
-/* set this=1 */
-	public void one()
-	{
-		a.one();
-		b.zero();
-		c.zero();
-	}
-/* this=conj(this) */
-	public void conj()
-	{
-		a.conj();
-		b.nconj();
-		c.conj();
-	}
-/* Constructors */
-	public FP12(FP4 d)
-	{
-		a=new FP4(d);
-		b=new FP4(0);
-		c=new FP4(0);
-	}
-
-	public FP12(int d)
-	{
-		a=new FP4(d);
-		b=new FP4(0);
-		c=new FP4(0);
-	}
-
-	public FP12(FP4 d,FP4 e,FP4 f)
-	{
-		a=new FP4(d);
-		b=new FP4(e);
-		c=new FP4(f);
-	}
-
-	public FP12(FP12 x)
-	{
-		a=new FP4(x.a);
-		b=new FP4(x.b);
-		c=new FP4(x.c);
-	}
-
-/* Granger-Scott Unitary Squaring */
-	public void usqr()
-	{
-		FP4 A=new FP4(a);
-		FP4 B=new FP4(c);
-		FP4 C=new FP4(b);
-		FP4 D=new FP4(0);
-
-		a.sqr();
-		D.copy(a); D.add(a);
-		a.add(D);
-
-		a.norm();
-		A.nconj();
-
-		A.add(A);
-		a.add(A);
-		B.sqr();
-		B.times_i();
-
-		D.copy(B); D.add(B);
-		B.add(D);
-		B.norm();
-
-		C.sqr();
-		D.copy(C); D.add(C);
-		C.add(D);
-		C.norm();
-
-		b.conj();
-		b.add(b);
-		c.nconj();
-
-		c.add(c);
-		b.add(B);
-		c.add(C);
-		reduce();
-
-	}
-
-/* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
-	public void sqr()
-	{
-		FP4 A=new FP4(a);
-		FP4 B=new FP4(b);
-		FP4 C=new FP4(c);
-		FP4 D=new FP4(a);
-
-		A.sqr();
-		B.mul(c);
-		B.add(B);
-		C.sqr();
-		D.mul(b);
-		D.add(D);
-
-		c.add(a);
-		c.add(b);
-		c.sqr();
-
-		a.copy(A);
-
-		A.add(B);
-		A.norm();
-		A.add(C);
-		A.add(D);
-		A.norm();
-
-		A.neg();
-		B.times_i();
-		C.times_i();
-
-		a.add(B);
-
-		b.copy(C); b.add(D);
-		c.add(A);
-
-		norm();
-	}
-
-/* FP12 full multiplication this=this*y */
-	public void mul(FP12 y)
-	{
-		FP4 z0=new FP4(a);
-		FP4 z1=new FP4(0);
-		FP4 z2=new FP4(b);
-		FP4 z3=new FP4(0);
-		FP4 t0=new FP4(a);
-		FP4 t1=new FP4(y.a);
-
-		z0.mul(y.a);
-		z2.mul(y.b);
-
-		t0.add(b);
-		t1.add(y.b);
-
-		z1.copy(t0); z1.mul(t1);
-		t0.copy(b); t0.add(c);
-
-		t1.copy(y.b); t1.add(y.c);
-		z3.copy(t0); z3.mul(t1);
-
-		t0.copy(z0); t0.neg();
-		t1.copy(z2); t1.neg();
-
-		z1.add(t0);
-		z1.norm();
-		b.copy(z1); b.add(t1);
-
-		z3.add(t1);
-		z2.add(t0);
-
-		t0.copy(a); t0.add(c);
-		t1.copy(y.a); t1.add(y.c);
-		t0.mul(t1);
-		z2.add(t0);
-
-		t0.copy(c); t0.mul(y.c);
-		t1.copy(t0); t1.neg();
-
-		z2.norm();
-		z3.norm();
-		b.norm();
-
-		c.copy(z2); c.add(t1);
-		z3.add(t1);
-		t0.times_i();
-		b.add(t0);
-
-		z3.times_i();
-		a.copy(z0); a.add(z3);
-
-		norm();
-	}
-
-/* Special case of multiplication arises from special form of ATE pairing line function */
-	public void smul(FP12 y)
-	{
-		FP4 z0=new FP4(a);
-		FP4 z2=new FP4(b);
-		FP4 z3=new FP4(b);
-		FP4 t0=new FP4(0);
-		FP4 t1=new FP4(y.a);
-
-		z0.mul(y.a);
-		z2.pmul(y.b.real());
-		b.add(a);
-		t1.real().add(y.b.real());
-
-		b.mul(t1);
-		z3.add(c);
-		z3.pmul(y.b.real());
-
-		t0.copy(z0); t0.neg();
-		t1.copy(z2); t1.neg();
-
-		b.add(t0);
-		b.norm();
-
-		b.add(t1);
-		z3.add(t1);
-		z2.add(t0);
-
-		t0.copy(a); t0.add(c);
-		t0.mul(y.a);
-		c.copy(z2); c.add(t0);
-
-		z3.times_i();
-		a.copy(z0); a.add(z3);
-
-		norm();
-	}
-
-/* this=1/this */
-	public void inverse()
-	{
-		FP4 f0=new FP4(a);
-		FP4 f1=new FP4(b);
-		FP4 f2=new FP4(a);
-		FP4 f3=new FP4(0);
-
-		norm();
-		f0.sqr();
-		f1.mul(c);
-		f1.times_i();
-		f0.sub(f1);
-
-		f1.copy(c); f1.sqr();
-		f1.times_i();
-		f2.mul(b);
-		f1.sub(f2);
-
-		f2.copy(b); f2.sqr();
-		f3.copy(a); f3.mul(c);
-		f2.sub(f3);
-
-		f3.copy(b); f3.mul(f2);
-		f3.times_i();
-		a.mul(f0);
-		f3.add(a);
-		c.mul(f1);
-		c.times_i();
-
-		f3.add(c);
-		f3.inverse();
-		a.copy(f0); a.mul(f3);
-		b.copy(f1); b.mul(f3);
-		c.copy(f2); c.mul(f3);
-	}
-
-/* this=this^p using Frobenius */
-	public void frob(FP2 f)
-	{
-		FP2 f2=new FP2(f);
-		FP2 f3=new FP2(f);
-
-		f2.sqr();
-		f3.mul(f2);
-
-		a.frob(f3);
-		b.frob(f3);
-		c.frob(f3);
-
-		b.pmul(f);
-		c.pmul(f2);
-	}
-
-/* trace function */
-	public FP4 trace()
-	{
-		FP4 t=new FP4(0);
-		t.copy(a);
-		t.imul(3);
-		t.reduce();
-		return t;
-	}
-
-/* convert from byte array to FP12 */
-	public static FP12 fromBytes(byte[] w)
-	{
-		BIG a,b;
-		FP2 c,d;
-		FP4 e,f,g;
-		byte[] t=new byte[ROM.MODBYTES];
-
-		for (int i=0;i<ROM.MODBYTES;i++) t[i]=w[i];
-		a=BIG.fromBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++) t[i]=w[i+ROM.MODBYTES];
-		b=BIG.fromBytes(t);
-		c=new FP2(a,b);
-
-		for (int i=0;i<ROM.MODBYTES;i++) t[i]=w[i+2*ROM.MODBYTES];
-		a=BIG.fromBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++) t[i]=w[i+3*ROM.MODBYTES];
-		b=BIG.fromBytes(t);
-		d=new FP2(a,b);
-
-		e=new FP4(c,d);
-
-
-		for (int i=0;i<ROM.MODBYTES;i++) t[i]=w[i+4*ROM.MODBYTES];
-		a=BIG.fromBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++) t[i]=w[i+5*ROM.MODBYTES];
-		b=BIG.fromBytes(t);
-		c=new FP2(a,b);
-
-		for (int i=0;i<ROM.MODBYTES;i++) t[i]=w[i+6*ROM.MODBYTES];
-		a=BIG.fromBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++) t[i]=w[i+7*ROM.MODBYTES];
-		b=BIG.fromBytes(t);
-		d=new FP2(a,b);
-
-		f=new FP4(c,d);
-
-
-		for (int i=0;i<ROM.MODBYTES;i++) t[i]=w[i+8*ROM.MODBYTES];
-		a=BIG.fromBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++) t[i]=w[i+9*ROM.MODBYTES];
-		b=BIG.fromBytes(t);
-		c=new FP2(a,b);
-
-		for (int i=0;i<ROM.MODBYTES;i++) t[i]=w[i+10*ROM.MODBYTES];
-		a=BIG.fromBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++) t[i]=w[i+11*ROM.MODBYTES];
-		b=BIG.fromBytes(t);
-		d=new FP2(a,b);
-
-		g=new FP4(c,d);
-
-		return new FP12(e,f,g);
-	}
-
-/* convert this to byte array */
-	public void toBytes(byte[] w)
-	{
-		byte[] t=new byte[ROM.MODBYTES];
-		a.geta().getA().toBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++) w[i]=t[i];
-		a.geta().getB().toBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++) w[i+ROM.MODBYTES]=t[i];
-		a.getb().getA().toBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++) w[i+2*ROM.MODBYTES]=t[i];
-		a.getb().getB().toBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++) w[i+3*ROM.MODBYTES]=t[i];
-
-		b.geta().getA().toBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++) w[i+4*ROM.MODBYTES]=t[i];
-		b.geta().getB().toBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++) w[i+5*ROM.MODBYTES]=t[i];
-		b.getb().getA().toBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++) w[i+6*ROM.MODBYTES]=t[i];
-		b.getb().getB().toBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++) w[i+7*ROM.MODBYTES]=t[i];
-
-		c.geta().getA().toBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++) w[i+8*ROM.MODBYTES]=t[i];
-		c.geta().getB().toBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++) w[i+9*ROM.MODBYTES]=t[i];
-		c.getb().getA().toBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++) w[i+10*ROM.MODBYTES]=t[i];
-		c.getb().getB().toBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++) w[i+11*ROM.MODBYTES]=t[i];
-	}
-
-/* convert to hex string */
-	public String toString()
-	{
-		return ("["+a.toString()+","+b.toString()+","+c.toString()+"]");
-	}
-
-/* this=this^e */
-/* Note this is simple square and multiply, so not side-channel safe */
-	public FP12 pow(BIG e)
-	{
-		norm();
-		e.norm();
-		FP12 w=new FP12(this);
-		BIG z=new BIG(e);
-		FP12 r=new FP12(1);
-
-		while (true)
-		{
-			int bt=z.parity();
-			z.fshr(1);
-			if (bt==1) r.mul(w);
-			if (z.iszilch()) break;
-			w.usqr();
-		}
-		r.reduce();
-		return r;
-	}
-
-/* constant time powering by small integer of max length bts */
-	public void pinpow(int e,int bts)
-	{
-		int i,b;
-		FP12 [] R=new FP12[2];
-		R[0]=new FP12(1);
-		R[1]=new FP12(this);
-		for (i=bts-1;i>=0;i--)
-		{
-			b=(e>>i)&1;
-			R[1-b].mul(R[b]);
-			R[b].usqr();
-		}
-		this.copy(R[0]);
-	}
-
-/* p=q0^u0.q1^u1.q2^u2.q3^u3 */
-/* Timing attack secure, but not cache attack secure */
-
-	public static FP12 pow4(FP12[] q,BIG[] u)
-	{
-		int i,j,nb,m;
-		int[] a=new int[4];
-		FP12 [] g=new FP12[8];
-		FP12 [] s=new FP12[2];
-		FP12 c=new FP12(1);
-		FP12 p=new FP12(0);
-		BIG [] t=new BIG[4];
-		BIG mt=new BIG(0);
-		byte[] w=new byte[ROM.NLEN*ROM.BASEBITS+1];
-
-		for (i=0;i<4;i++)
-			t[i]=new BIG(u[i]);
-
-		s[0]=new FP12(0);
-		s[1]=new FP12(0);
-
-		g[0]=new FP12(q[0]); s[0].copy(q[1]); s[0].conj(); g[0].mul(s[0]);
-		g[1]=new FP12(g[0]);
-		g[2]=new FP12(g[0]);
-		g[3]=new FP12(g[0]);
-		g[4]=new FP12(q[0]); g[4].mul(q[1]);
-		g[5]=new FP12(g[4]);
-		g[6]=new FP12(g[4]);
-		g[7]=new FP12(g[4]);
-
-		s[1].copy(q[2]); s[0].copy(q[3]); s[0].conj(); s[1].mul(s[0]);
-		s[0].copy(s[1]); s[0].conj(); g[1].mul(s[0]);
-		g[2].mul(s[1]);
-		g[5].mul(s[0]);
-		g[6].mul(s[1]);
-		s[1].copy(q[2]); s[1].mul(q[3]);
-		s[0].copy(s[1]); s[0].conj(); g[0].mul(s[0]);
-		g[3].mul(s[1]);
-		g[4].mul(s[0]);
-		g[7].mul(s[1]);
-
-/* if power is even add 1 to power, and add q to correction */
-
-		for (i=0;i<4;i++)
-		{
-			if (t[i].parity()==0)
-			{
-				t[i].inc(1); t[i].norm();
-				c.mul(q[i]);
-			}
-			mt.add(t[i]); mt.norm();
-		}
-		c.conj();
-		nb=1+mt.nbits();
-
-/* convert exponent to signed 1-bit window */
-		for (j=0;j<nb;j++)
-		{
-			for (i=0;i<4;i++)
-			{
-				a[i]=(t[i].lastbits(2)-2);
-				t[i].dec(a[i]); t[i].norm();
-				t[i].fshr(1);
-			}
-			w[j]=(byte)(8*a[0]+4*a[1]+2*a[2]+a[3]);
-		}
-		w[nb]=(byte)(8*t[0].lastbits(2)+4*t[1].lastbits(2)+2*t[2].lastbits(2)+t[3].lastbits(2));
-		p.copy(g[(w[nb]-1)/2]);
-
-		for (i=nb-1;i>=0;i--)
-		{
-			m=w[i]>>7;
-			j=(w[i]^m)-m;  /* j=abs(w[i]) */
-			j=(j-1)/2;
-			s[0].copy(g[j]); s[1].copy(g[j]); s[1].conj();
-			p.usqr();
-			p.mul(s[m&1]);
-		}
-		p.mul(c);  /* apply correction */
-		p.reduce();
-		return p;
-	}
-
-/*
-	public static void main(String[] args) {
-		BIG p=new BIG(ROM.Modulus);
-		FP2 w0,w1;
-		BIG a=new BIG(0);
-		BIG b=new BIG(0);
-
-		a.zero(); b.zero(); a.inc(1); b.inc(2);
-		w0=new FP2(a,b);
-		a.zero(); b.zero(); a.inc(3); b.inc(4);
-		w1=new FP2(a,b);
-		FP4 t0=new FP4(w0,w1);
-
-		a.zero(); b.zero(); a.inc(5); b.inc(6);
-		w0=new FP2(a,b);
-		a.zero(); b.zero(); a.inc(7); b.inc(8);
-		w1=new FP2(a,b);
-		FP4 t1=new FP4(w0,w1);
-
-		a.zero(); b.zero(); a.inc(9); b.inc(10);
-		w0=new FP2(a,b);
-		a.zero(); b.zero(); a.inc(11); b.inc(12);
-		w1=new FP2(a,b);
-		FP4 t2=new FP4(w0,w1);
-
-		FP12 w=new FP12(t0,t1,t2);
-		FP12 t=new FP12(w);
-
-		System.out.println("w= "+w.toString());
-
-		a=new BIG(ROM.CURVE_Fra);
-		b=new BIG(ROM.CURVE_Frb);
-
-		FP2 f=new FP2(a,b);
-
-		w.frob(f);
-		System.out.println("w= "+w.toString());
-
-		w=t.pow(p);
-
-		System.out.println("w= "+w.toString());
-
-		w.inverse();
-
-		System.out.println("1/w= "+w.toString());
-
-		w.inverse();
-
-		System.out.println("w= "+w.toString());
-
-		t.copy(w);
-		w.conj();
-		t.inverse();
-		w.mul(t);
-
-		System.out.println("w^(p^6-1)= "+w.toString());
-
-		t.copy(w);
-		w.frob(f);
-		w.frob(f);
-		w.mul(t);
-
-		System.out.println("w^(p^6-1)(p^2+1)= "+w.toString());
-
-		t.copy(w);
-
-		t.inverse();
-		w.conj();
-
-		System.out.println("w= "+w.toString());
-		System.out.println("t= "+t.toString());
-	} */
-}
diff --git a/java/FP2.java b/java/FP2.java
deleted file mode 100755
index 185c103..0000000
--- a/java/FP2.java
+++ /dev/null
@@ -1,389 +0,0 @@
-/*
-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.
-*/
-
-/* Finite Field arithmetic  Fp^2 functions */
-
-/* FP2 elements are of the form a+ib, where i is sqrt(-1) */
-
-public final class FP2 {
-	private final FP a;
-	private final FP b;
-
-/* reduce components mod Modulus */
-	public void reduce()
-	{
-		a.reduce();
-		b.reduce();
-	}
-
-/* normalise components of w */
-	public void norm()
-	{
-		a.norm();
-		b.norm();
-	}
-
-/* test this=0 ? */
-	public boolean iszilch() {
-		reduce();
-		return (a.iszilch() && b.iszilch());
-	}
-
-	public void cmove(FP2 g,int d)
-	{
-		a.cmove(g.a,d);
-		b.cmove(g.b,d);
-	}
-
-/* test this=1 ? */
-	public boolean isunity() {
-		FP one=new FP(1);
-		return (a.equals(one) && b.iszilch());
-	}
-
-/* test this=x */
-	public boolean equals(FP2 x) {
-		return (a.equals(x.a) && b.equals(x.b));
-	}
-
-/* Constructors */
-	public FP2(int c)
-	{
-		a=new FP(c);
-		b=new FP(0);
-	}
-
-	public FP2(FP2 x)
-	{
-		a=new FP(x.a);
-		b=new FP(x.b);
-	}
-
-	public FP2(FP c,FP d)
-	{
-		a=new FP(c);
-		b=new FP(d);
-	}
-
-	public FP2(BIG c,BIG d)
-	{
-		a=new FP(c);
-		b=new FP(d);
-	}
-
-	public FP2(FP c)
-	{
-		a=new FP(c);
-		b=new FP(0);
-	}
-
-	public FP2(BIG c)
-	{
-		a=new FP(c);
-		b=new FP(0);
-	}
-
-/* extract a */
-	public BIG getA()
-	{
-		return a.redc();
-	}
-
-/* extract b */
-	public BIG getB()
-	{
-		return b.redc();
-	}
-
-/* copy this=x */
-	public void copy(FP2 x)
-	{
-		a.copy(x.a);
-		b.copy(x.b);
-	}
-
-/* set this=0 */
-	public void zero()
-	{
-		a.zero();
-		b.zero();
-	}
-
-/* set this=1 */
-	public void one()
-	{
-		a.one();
-		b.zero();
-	}
-
-/* negate this mod Modulus */
-	public void neg()
-	{
-		norm();
-		FP m=new FP(a);
-		FP t=new FP(0);
-
-		m.add(b);
-		m.neg();
-		m.norm();
-		t.copy(m); t.add(b);
-		b.copy(m);
-		b.add(a);
-		a.copy(t);
-	}
-
-/* set to a-ib */
-	public void conj()
-	{
-		b.neg();
-	}
-
-/* this+=a */
-	public void add(FP2 x)
-	{
-		a.add(x.a);
-		b.add(x.b);
-	}
-
-/* this-=a */
-	public void sub(FP2 x)
-	{
-		FP2 m=new FP2(x);
-		m.neg();
-		add(m);
-	}
-
-/* this*=s, where s is an FP */
-	public void pmul(FP s)
-	{
-		a.mul(s);
-		b.mul(s);
-	}
-
-/* this*=i, where i is an int */
-	public void imul(int c)
-	{
-		a.imul(c);
-		b.imul(c);
-	}
-
-/* this*=this */
-	public void sqr()
-	{
-		norm();
-
-		FP w1=new FP(a);
-		FP w3=new FP(a);
-		FP mb=new FP(b);
-		w3.mul(b);
-		w1.add(b);
-		mb.neg();
-		a.add(mb);
-		a.mul(w1);
-		b.copy(w3); b.add(w3);
-		norm();
-	}
-
-/* this*=y */
-	public void mul(FP2 y)
-	{
-		norm();  /* This is needed here as {a,b} is not normed before additions */
-
-		FP w1=new FP(a);
-		FP w2=new FP(b);
-		FP w5=new FP(a);
-		FP mw=new FP(0);
-
-		w1.mul(y.a);  // w1=a*y.a  - this norms w1 and y.a, NOT a
-		w2.mul(y.b);  // w2=b*y.b  - this norms w2 and y.b, NOT b
-		w5.add(b);    // w5=a+b
-		b.copy(y.a); b.add(y.b); // b=y.a+y.b
-
-		b.mul(w5);
-		mw.copy(w1); mw.add(w2); mw.neg();
-
-		b.add(mw); mw.add(w1);
-		a.copy(w1);	a.add(mw);
-
-		norm();
-
-	}
-
-/* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */
-/* returns true if this is QR */
-	public boolean sqrt()
-	{
-		if (iszilch()) return true;
-		FP w1=new FP(b);
-		FP w2=new FP(a);
-		w1.sqr(); w2.sqr(); w1.add(w2);
-		if (w1.jacobi()!=1) { zero(); return false; }
-		w1=w1.sqrt();
-		w2.copy(a); w2.add(w1); w2.div2();
-		if (w2.jacobi()!=1)
-		{
-			w2.copy(a); w2.sub(w1); w2.div2();
-			if (w2.jacobi()!=1) { zero(); return false; }
-		}
-		w2=w2.sqrt();
-		a.copy(w2);
-		w2.add(w2);
-		w2.inverse();
-		b.mul(w2);
-		return true;
-	}
-
-/* output to hex string */
-	public String toString()
-	{
-		return ("["+a.toString()+","+b.toString()+"]");
-	}
-
-	public String toRawString()
-	{
-		return ("["+a.toRawString()+","+b.toRawString()+"]");
-	}
-
-/* this=1/this */
-	public void inverse()
-	{
-		norm();
-		FP w1=new FP(a);
-		FP w2=new FP(b);
-
-		w1.sqr();
-		w2.sqr();
-		w1.add(w2);
-		w1.inverse();
-		a.mul(w1);
-		w1.neg();
-		b.mul(w1);
-	}
-
-/* this/=2 */
-	public void div2()
-	{
-		a.div2();
-		b.div2();
-	}
-
-/* this*=sqrt(-1) */
-	public void times_i()
-	{
-	//	a.norm();
-		FP z=new FP(a);
-		a.copy(b); a.neg();
-		b.copy(z);
-	}
-
-/* w*=(1+sqrt(-1)) */
-/* where X*2-(1+sqrt(-1)) is irreducible for FP4, assumes p=3 mod 8 */
-	public void mul_ip()
-	{
-		norm();
-		FP2 t=new FP2(this);
-		FP z=new FP(a);
-		a.copy(b);
-		a.neg();
-		b.copy(z);
-		add(t);
-		norm();
-	}
-
-/* w/=(1+sqrt(-1)) */
-	public void div_ip()
-	{
-		FP2 t=new FP2(0);
-		norm();
-		t.a.copy(a); t.a.add(b);
-		t.b.copy(b); t.b.sub(a);
-		copy(t);
-		div2();
-	}
-/*
-	public FP2 pow(BIG e)
-	{
-		int bt;
-		FP2 r=new FP2(1);
-		e.norm();
-		norm();
-		while (true)
-		{
-			bt=e.parity();
-			e.fshr(1);
-			if (bt==1) r.mul(this);
-			if (e.iszilch()) break;
-			sqr();
-		}
-
-		r.reduce();
-		return r;
-	}
-
-	public static void main(String[] args) {
-		BIG m=new BIG(ROM.Modulus);
-		BIG x=new BIG(3);
-		BIG e=new BIG(27);
-		BIG pp1=new BIG(m);
-		BIG pm1=new BIG(m);
-		BIG a=new BIG(1);
-		BIG b=new BIG(1);
-		FP2 w=new FP2(a,b);
-		FP2 z=new FP2(w);
-
-		byte[] RAW=new byte[100];
-
-		RAND rng=new RAND();
-		for (int i=0;i<100;i++) RAW[i]=(byte)(i);
-
-		rng.seed(100,RAW);
-
-	//	for (int i=0;i<100;i++)
-	//	{
-			a.randomnum(rng);
-			b.randomnum(rng);
-
-			w=new FP2(a,b);
-			System.out.println("w="+w.toString());
-
-			z=new FP2(w);
-			z.inverse();
-			System.out.println("z="+z.toString());
-
-			z.inverse();
-			if (!z.equals(w)) System.out.println("Error");
-	//	}
-
-//		System.out.println("m="+m.toString());
-//		w.sqr();
-//		w.mul(z);
-
-		System.out.println("w="+w.toString());
-
-
-		pp1.inc(1); pp1.norm();
-		pm1.dec(1); pm1.norm();
-		System.out.println("p+1="+pp1.toString());
-		System.out.println("p-1="+pm1.toString());
-		w=w.pow(pp1);
-		w=w.pow(pm1);
-		System.out.println("w="+w.toString());
-	}
-*/
-}
diff --git a/java/FP4.java b/java/FP4.java
deleted file mode 100755
index 5f0f42a..0000000
--- a/java/FP4.java
+++ /dev/null
@@ -1,583 +0,0 @@
-/*
-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.
-*/
-
-/* Finite Field arithmetic  Fp^4 functions */
-
-/* FP4 elements are of the form a+ib, where i is sqrt(-1+sqrt(-1))  */
-
-public final class FP4 {
-	private final FP2 a;
-	private final FP2 b;
-/* reduce all components of this mod Modulus */
-	public void reduce()
-	{
-		a.reduce();
-		b.reduce();
-	}
-/* normalise all components of this mod Modulus */
-	public void norm()
-	{
-		a.norm();
-		b.norm();
-	}
-/* test this==0 ? */
-	public boolean iszilch() {
-		reduce();
-		return (a.iszilch() && b.iszilch());
-	}
-/* test this==1 ? */
-	public boolean isunity() {
-		FP2 one=new FP2(1);
-		return (a.equals(one) && b.iszilch());
-	}
-
-/* test is w real? That is in a+ib test b is zero */
-	public boolean isreal()
-	{
-		return b.iszilch();
-	}
-/* extract real part a */
-	public FP2 real()
-	{
-		return a;
-	}
-
-	public FP2 geta()
-	{
-		return a;
-	}
-/* extract imaginary part b */
-	public FP2 getb()
-	{
-		return b;
-	}
-/* test this=x? */
-	public boolean equals(FP4 x)
-	{
-		return (a.equals(x.a) && b.equals(x.b));
-	}
-/* constructors */
-	public FP4(int c)
-	{
-		a=new FP2(c);
-		b=new FP2(0);
-	}
-
-	public FP4(FP4 x)
-	{
-		a=new FP2(x.a);
-		b=new FP2(x.b);
-	}
-
-	public FP4(FP2 c,FP2 d)
-	{
-		a=new FP2(c);
-		b=new FP2(d);
-	}
-
-	public FP4(FP2 c)
-	{
-		a=new FP2(c);
-		b=new FP2(0);
-	}
-/* copy this=x */
-	public void copy(FP4 x)
-	{
-		a.copy(x.a);
-		b.copy(x.b);
-	}
-/* set this=0 */
-	public void zero()
-	{
-		a.zero();
-		b.zero();
-	}
-/* set this=1 */
-	public void one()
-	{
-		a.one();
-		b.zero();
-	}
-/* set this=-this */
-	public void neg()
-	{
-		FP2 m=new FP2(a);
-		FP2 t=new FP2(0);
-		m.add(b);
-		m.neg();
-		m.norm();
-		t.copy(m); t.add(b);
-		b.copy(m);
-		b.add(a);
-		a.copy(t);
-	}
-/* this=conjugate(this) */
-	public void conj()
-	{
-		b.neg(); b.norm();
-	}
-/* this=-conjugate(this) */
-	public void nconj()
-	{
-		a.neg(); a.norm();
-	}
-/* this+=x */
-	public void add(FP4 x)
-	{
-		a.add(x.a);
-		b.add(x.b);
-	}
-/* this-=x */
-	public void sub(FP4 x)
-	{
-		FP4 m=new FP4(x);
-		m.neg();
-		add(m);
-	}
-
-/* this*=s where s is FP2 */
-	public void pmul(FP2 s)
-	{
-		a.mul(s);
-		b.mul(s);
-	}
-/* this*=c where c is int */
-	public void imul(int c)
-	{
-		a.imul(c);
-		b.imul(c);
-	}
-/* this*=this */
-	public void sqr()
-	{
-		norm();
-
-		FP2 t1=new FP2(a);
-		FP2 t2=new FP2(b);
-		FP2 t3=new FP2(a);
-
-		t3.mul(b);
-		t1.add(b);
-		t2.mul_ip();
-
-		t2.add(a);
-		a.copy(t1);
-
-		a.mul(t2);
-
-		t2.copy(t3);
-		t2.mul_ip();
-		t2.add(t3);
-		t2.neg();
-		a.add(t2);
-
-		b.copy(t3);
-		b.add(t3);
-
-		norm();
-	}
-/* this*=y */
-	public void mul(FP4 y)
-	{
-		norm();
-
-		FP2 t1=new FP2(a);
-		FP2 t2=new FP2(b);
-		FP2 t3=new FP2(0);
-		FP2 t4=new FP2(b);
-
-		t1.mul(y.a);
-		t2.mul(y.b);
-		t3.copy(y.b);
-		t3.add(y.a);
-		t4.add(a);
-
-		t4.mul(t3);
-		t4.sub(t1);
-		t4.norm();
-
-		b.copy(t4);
-		b.sub(t2);
-		t2.mul_ip();
-		a.copy(t2);
-		a.add(t1);
-
-		norm();
-	}
-/* convert this to hex string */
-	public String toString()
-	{
-		return ("["+a.toString()+","+b.toString()+"]");
-	}
-
-	public String toRawString()
-	{
-		return ("["+a.toRawString()+","+b.toRawString()+"]");
-	}
-
-/* this=1/this */
-	public void inverse()
-	{
-		norm();
-
-		FP2 t1=new FP2(a);
-		FP2 t2=new FP2(b);
-
-		t1.sqr();
-		t2.sqr();
-		t2.mul_ip();
-		t1.sub(t2);
-		t1.inverse();
-		a.mul(t1);
-		t1.neg();
-		b.mul(t1);
-	}
-
-
-/* this*=i where i = sqrt(-1+sqrt(-1)) */
-	public void times_i()
-	{
-		norm();
-		FP2 s=new FP2(b);
-		FP2 t=new FP2(b);
-		s.times_i();
-		t.add(s);
-		t.norm();
-		b.copy(a);
-		a.copy(t);
-	}
-
-/* this=this^p using Frobenius */
-	public void frob(FP2 f)
-	{
-		a.conj();
-		b.conj();
-		b.mul(f);
-	}
-
-/* this=this^e */
-	public FP4 pow(BIG e)
-	{
-		norm();
-		e.norm();
-		FP4 w=new FP4(this);
-		BIG z=new BIG(e);
-		FP4 r=new FP4(1);
-		while (true)
-		{
-			int bt=z.parity();
-			z.fshr(1);
-			if (bt==1) r.mul(w);
-			if (z.iszilch()) break;
-			w.sqr();
-		}
-		r.reduce();
-		return r;
-	}
-/* XTR xtr_a function */
-	public void xtr_A(FP4 w,FP4 y,FP4 z)
-	{
-		FP4 r=new FP4(w);
-		FP4 t=new FP4(w);
-		r.sub(y);
-		r.pmul(a);
-		t.add(y);
-		t.pmul(b);
-		t.times_i();
-
-		copy(r);
-		add(t);
-		add(z);
-
-		norm();
-	}
-
-/* XTR xtr_d function */
-	public void xtr_D() {
-		FP4 w=new FP4(this);
-		sqr(); w.conj();
-		w.add(w);
-		sub(w);
-		reduce();
-	}
-
-/* r=x^n using XTR method on traces of FP12s */
-	public FP4 xtr_pow(BIG n) {
-		FP4 a=new FP4(3);
-		FP4 b=new FP4(this);
-		FP4 c=new FP4(b);
-		c.xtr_D();
-		FP4 t=new FP4(0);
-		FP4 r=new FP4(0);
-
-		n.norm();
-		int par=n.parity();
-		BIG v=new BIG(n); v.fshr(1);
-		if (par==0) {v.dec(1); v.norm();}
-
-		int nb=v.nbits();
-		for (int i=nb-1;i>=0;i--)
-		{
-			if (v.bit(i)!=1)
-			{
-				t.copy(b);
-				conj();
-				c.conj();
-				b.xtr_A(a,this,c);
-				conj();
-				c.copy(t);
-				c.xtr_D();
-				a.xtr_D();
-			}
-			else
-			{
-				t.copy(a); t.conj();
-				a.copy(b);
-				a.xtr_D();
-				b.xtr_A(c,this,t);
-				c.xtr_D();
-			}
-		}
-		if (par==0) r.copy(c);
-		else r.copy(b);
-		r.reduce();
-		return r;
-	}
-
-/* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */
-	public FP4 xtr_pow2(FP4 ck,FP4 ckml,FP4 ckm2l,BIG a,BIG b)
-	{
-		a.norm(); b.norm();
-		BIG e=new BIG(a);
-		BIG d=new BIG(b);
-		BIG w=new BIG(0);
-
-		FP4 cu=new FP4(ck);  // can probably be passed in w/o copying
-		FP4 cv=new FP4(this);
-		FP4 cumv=new FP4(ckml);
-		FP4 cum2v=new FP4(ckm2l);
-		FP4 r=new FP4(0);
-		FP4 t=new FP4(0);
-
-		int f2=0;
-		while (d.parity()==0 && e.parity()==0)
-		{
-			d.fshr(1);
-			e.fshr(1);
-			f2++;
-		}
-
-		while (BIG.comp(d,e)!=0)
-		{
-			if (BIG.comp(d,e)>0)
-			{
-				w.copy(e); w.imul(4); w.norm();
-				if (BIG.comp(d,w)<=0)
-				{
-					w.copy(d); d.copy(e);
-					e.rsub(w); e.norm();
-
-					t.copy(cv);
-					t.xtr_A(cu,cumv,cum2v);
-					cum2v.copy(cumv);
-					cum2v.conj();
-					cumv.copy(cv);
-					cv.copy(cu);
-					cu.copy(t);
-
-				}
-				else if (d.parity()==0)
-				{
-					d.fshr(1);
-					r.copy(cum2v); r.conj();
-					t.copy(cumv);
-					t.xtr_A(cu,cv,r);
-					cum2v.copy(cumv);
-					cum2v.xtr_D();
-					cumv.copy(t);
-					cu.xtr_D();
-				}
-				else if (e.parity()==1)
-				{
-					d.sub(e); d.norm();
-					d.fshr(1);
-					t.copy(cv);
-					t.xtr_A(cu,cumv,cum2v);
-					cu.xtr_D();
-					cum2v.copy(cv);
-					cum2v.xtr_D();
-					cum2v.conj();
-					cv.copy(t);
-				}
-				else
-				{
-					w.copy(d);
-					d.copy(e); d.fshr(1);
-					e.copy(w);
-					t.copy(cumv);
-					t.xtr_D();
-					cumv.copy(cum2v); cumv.conj();
-					cum2v.copy(t); cum2v.conj();
-					t.copy(cv);
-					t.xtr_D();
-					cv.copy(cu);
-					cu.copy(t);
-				}
-			}
-			if (BIG.comp(d,e)<0)
-			{
-				w.copy(d); w.imul(4); w.norm();
-				if (BIG.comp(e,w)<=0)
-				{
-					e.sub(d); e.norm();
-					t.copy(cv);
-					t.xtr_A(cu,cumv,cum2v);
-					cum2v.copy(cumv);
-					cumv.copy(cu);
-					cu.copy(t);
-				}
-				else if (e.parity()==0)
-				{
-					w.copy(d);
-					d.copy(e); d.fshr(1);
-					e.copy(w);
-					t.copy(cumv);
-					t.xtr_D();
-					cumv.copy(cum2v); cumv.conj();
-					cum2v.copy(t); cum2v.conj();
-					t.copy(cv);
-					t.xtr_D();
-					cv.copy(cu);
-					cu.copy(t);
-				}
-				else if (d.parity()==1)
-				{
-					w.copy(e);
-					e.copy(d);
-					w.sub(d); w.norm();
-					d.copy(w); d.fshr(1);
-					t.copy(cv);
-					t.xtr_A(cu,cumv,cum2v);
-					cumv.conj();
-					cum2v.copy(cu);
-					cum2v.xtr_D();
-					cum2v.conj();
-					cu.copy(cv);
-					cu.xtr_D();
-					cv.copy(t);
-				}
-				else
-				{
-					d.fshr(1);
-					r.copy(cum2v); r.conj();
-					t.copy(cumv);
-					t.xtr_A(cu,cv,r);
-					cum2v.copy(cumv);
-					cum2v.xtr_D();
-					cumv.copy(t);
-					cu.xtr_D();
-				}
-			}
-		}
-		r.copy(cv);
-		r.xtr_A(cu,cumv,cum2v);
-		for (int i=0;i<f2;i++)
-			r.xtr_D();
-		r=r.xtr_pow(d);
-		return r;
-	}
-/*
-	public static void main(String[] args) {
-		BIG m=new BIG(ROM.Modulus);
-		BIG e=new BIG(12);
-		BIG a=new BIG(0);
-		BIG b=new BIG(0);
-
-		a.inc(27); b.inc(45);
-
-		FP2 w0=new FP2(a,b);
-
-		a.zero(); b.zero();
-		a.inc(33); b.inc(54);
-
-		FP2 w1=new FP2(a,b);
-
-
-		FP4 w=new FP4(w0,w1);
-		FP4 t=new FP4(w);
-
-		a=new BIG(ROM.CURVE_Fra);
-		b=new BIG(ROM.CURVE_Frb);
-
-		FP2 f=new FP2(a,b);
-
-		System.out.println("w= "+w.toString());
-
-		w=w.pow(m);
-
-		System.out.println("w^p= "+w.toString());
-
-		t.frob(f);
-
-
-		System.out.println("w^p= "+t.toString());
-
-		w=w.pow(m);
-		w=w.pow(m);
-		w=w.pow(m);
-		System.out.println("w^p4= "+w.toString());
-
-
-	System.out.println("Test Inversion");
-
-		w=new FP4(w0,w1);
-
-		w.inverse();
-
-		System.out.println("1/w mod p^4 = "+w.toString());
-
-		w.inverse();
-
-		System.out.println("1/(1/w) mod p^4 = "+w.toString());
-
-		FP4 ww=new FP4(w);
-
-		w=w.xtr_pow(e);
-		System.out.println("w^e= "+w.toString());
-
-
-		a.zero(); b.zero();
-		a.inc(37); b.inc(17);
-		w0=new FP2(a,b);
-		a.zero(); b.zero();
-		a.inc(49); b.inc(31);
-		w1=new FP2(a,b);
-
-		FP4 c1=new FP4(w0,w1);
-		FP4 c2=new FP4(w0,w1);
-		FP4 c3=new FP4(w0,w1);
-
-		BIG e1=new BIG(3331);
-		BIG e2=new BIG(3372);
-
-		FP4 cr=w.xtr_pow2(c1,c2,c3,e1,e2);
-
-		System.out.println("c^e= "+cr.toString());
-	} */
-}
diff --git a/java/GCM.java b/java/GCM.java
deleted file mode 100755
index eb9a840..0000000
--- a/java/GCM.java
+++ /dev/null
@@ -1,374 +0,0 @@
-/*
-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.
-*/
-
-
-
-/*
- * Implementation of the AES-GCM Encryption/Authentication
- *
- * Some restrictions..
- * 1. Only for use with AES
- * 2. Returned tag is always 128-bits. Truncate at your own risk.
- * 3. The order of function calls must follow some rules
- *
- * Typical sequence of calls..
- * 1. call GCM_init
- * 2. call GCM_add_header any number of times, as long as length of header is multiple of 16 bytes (block size)
- * 3. call GCM_add_header one last time with any length of header
- * 4. call GCM_add_cipher any number of times, as long as length of cipher/plaintext is multiple of 16 bytes
- * 5. call GCM_add_cipher one last time with any length of cipher/plaintext
- * 6. call GCM_finish to extract the tag.
- *
- * See http://www.mindspring.com/~dmcgrew/gcm-nist-6.pdf
- */
-
-public class GCM {
-	public static final int NB=4;
-	public static final int GCM_ACCEPTING_HEADER=0;
-	public static final int GCM_ACCEPTING_CIPHER=1;
-	public static final int GCM_NOT_ACCEPTING_MORE=2;
-	public static final int GCM_FINISHED=3;
-	public static final int GCM_ENCRYPTING=0;
-	public static final int GCM_DECRYPTING=1;
-
-	private int[][] table=new int[128][4]; /* 2k bytes */
-	private byte[] stateX=new byte[16];
-	private byte[]Y_0=new byte[16];
-	private int counter;
-	private int[] lenA=new int[2];
-	private int[] lenC=new int[2];
-	private int status;
-	private AES a=new AES();
-
-	private static int pack(byte[] b)
-	{ /* pack bytes into a 32-bit Word */
-		return ((((int)b[0])&0xff)<<24)|(((int)b[1]&0xff)<<16)|(((int)b[2]&0xff)<<8)|((int)b[3]&0xff);
-	}
-
-	private static byte[] unpack(int a)
-	{ /* unpack bytes from a word */
-		byte [] b=new byte[4];
-		b[3]=(byte)(a);
-		b[2]=(byte)(a>>>8);
-		b[1]=(byte)(a>>>16);
-		b[0]=(byte)(a>>>24);
-		return b;
-	}
-
-	private void precompute(byte[] H)
-	{
-		int i,j,c;
-		byte[] b=new byte[4];
-
-		for (i=j=0;i<NB;i++,j+=4)
-		{
-			b[0]=H[j]; b[1]=H[j+1]; b[2]=H[j+2]; b[3]=H[j+3];
-			table[0][i]=pack(b);
-		}
-		for (i=1;i<128;i++)
-		{
-			c=0;
-			for (j=0;j<NB;j++) {table[i][j]=c|(table[i-1][j])>>>1; c=table[i-1][j]<<31;}
-			if (c!=0) table[i][0]^=0xE1000000; /* irreducible polynomial */
-		}
-	}
-
-	private void gf2mul()
-	{ /* gf2m mul - Z=H*X mod 2^128 */
-		int i,j,m,k;
-		int[] P=new int[4];
-		int c;
-		byte[] b;//=new byte[4];
-
-		P[0]=P[1]=P[2]=P[3]=0;
-		j=8; m=0;
-		for (i=0;i<128;i++)
-		{
-			c=(stateX[m]>>>(--j))&1;
-			if (c!=0) for (k=0;k<NB;k++) P[k]^=table[i][k];
-			if (j==0)
-			{
-				j=8; m++;
-				if (m==16) break;
-			}
-		}
-		for (i=j=0;i<NB;i++,j+=4)
-		{
-			b=unpack(P[i]);
-			stateX[j]=b[0]; stateX[j+1]=b[1]; stateX[j+2]=b[2]; stateX[j+3]=b[3];
-		}
-	}
-
-	private void wrap()
-	{ /* Finish off GHASH */
-		int i,j;
-		int[] F=new int[4];
-		byte[] L=new byte[16];
-		byte[] b;//=new byte[4];
-
-/* convert lengths from bytes to bits */
-		F[0]=(lenA[0]<<3)|(lenA[1]&0xE0000000)>>>29;
-		F[1]=lenA[1]<<3;
-		F[2]=(lenC[0]<<3)|(lenC[1]&0xE0000000)>>>29;
-		F[3]=lenC[1]<<3;
-		for (i=j=0;i<NB;i++,j+=4)
-		{
-			b=unpack(F[i]);
-			L[j]=b[0]; L[j+1]=b[1]; L[j+2]=b[2]; L[j+3]=b[3];
-		}
-		for (i=0;i<16;i++) stateX[i]^=L[i];
-		gf2mul();
-	}
-
-/* Initialize GCM mode */
-	public void init(byte[] key,int niv,byte[] iv)
-	{ /* iv size niv is usually 12 bytes (96 bits). AES key size nk can be 16,24 or 32 bytes */
-		int i;
-		byte[] H=new byte[16];
-		byte[] b;//=new byte[4];
-
-		for (i=0;i<16;i++) {H[i]=0; stateX[i]=0;}
-
-		a.init(AES.ECB,key,iv);
-		a.ecb_encrypt(H);     /* E(K,0) */
-		precompute(H);
-
-		lenA[0]=lenC[0]=lenA[1]=lenC[1]=0;
-		if (niv==12)
-		{
-			for (i=0;i<12;i++) a.f[i]=iv[i];
-			b=unpack((int)1);
-			a.f[12]=b[0]; a.f[13]=b[1]; a.f[14]=b[2]; a.f[15]=b[3];  /* initialise IV */
-			for (i=0;i<16;i++) Y_0[i]=a.f[i];
-		}
-		else
-		{
-			status=GCM_ACCEPTING_CIPHER;
-			ghash(iv,niv); /* GHASH(H,0,IV) */
-			wrap();
-			for (i=0;i<16;i++) {a.f[i]=stateX[i];Y_0[i]=a.f[i];stateX[i]=0;}
-			lenA[0]=lenC[0]=lenA[1]=lenC[1]=0;
-		}
-		status=GCM_ACCEPTING_HEADER;
-	}
-
-/* Add Header data - included but not encrypted */
-	public boolean add_header(byte[] header,int len)
-	{ /* Add some header. Won't be encrypted, but will be authenticated. len is length of header */
-		int i,j=0;
-		if (status!=GCM_ACCEPTING_HEADER) return false;
-
-		while (j<len)
-		{
-			for (i=0;i<16 && j<len;i++)
-			{
-				stateX[i]^=header[j++];
-				lenA[1]++; if (lenA[1]==0) lenA[0]++;
-			}
-			gf2mul();
-		}
-		if (len%16!=0) status=GCM_ACCEPTING_CIPHER;
-		return true;
-	}
-
-	private boolean ghash(byte[] plain,int len)
-	{
-		int i,j=0;
-		int counter;
-	//	byte[] B=new byte[16];
-	//	byte[] b=new byte[4];
-
-		if (status==GCM_ACCEPTING_HEADER) status=GCM_ACCEPTING_CIPHER;
-		if (status!=GCM_ACCEPTING_CIPHER) return false;
-
-		while (j<len)
-		{
-			for (i=0;i<16 && j<len;i++)
-			{
-				stateX[i]^=plain[j++];
-				lenC[1]++; if (lenC[1]==0) lenC[0]++;
-			}
-			gf2mul();
-		}
-		if (len%16!=0) status=GCM_NOT_ACCEPTING_MORE;
-		return true;
-	}
-
-/* Add Plaintext - included and encrypted */
-	public byte[] add_plain(byte[] plain,int len)
-	{
-		int i,j=0;
-		int counter;
-		byte[] B=new byte[16];
-		byte[] b=new byte[4];
-		byte[] cipher=new byte[len];
-
-		if (status==GCM_ACCEPTING_HEADER) status=GCM_ACCEPTING_CIPHER;
-		if (status!=GCM_ACCEPTING_CIPHER) return new byte[0];
-
-		while (j<len)
-		{
-
-			b[0]=a.f[12]; b[1]=a.f[13]; b[2]=a.f[14]; b[3]=a.f[15];
-			counter=pack(b);
-			counter++;
-			b=unpack(counter);
-			a.f[12]=b[0]; a.f[13]=b[1]; a.f[14]=b[2]; a.f[15]=b[3]; /* increment counter */
-			for (i=0;i<16;i++) B[i]=a.f[i];
-			a.ecb_encrypt(B);        /* encrypt it  */
-
-			for (i=0;i<16 && j<len;i++)
-			{
-				cipher[j]=(byte)(plain[j]^B[i]);
-				stateX[i]^=cipher[j++];
-				lenC[1]++; if (lenC[1]==0) lenC[0]++;
-			}
-			gf2mul();
-		}
-		if (len%16!=0) status=GCM_NOT_ACCEPTING_MORE;
-		return cipher;
-	}
-
-/* Add Ciphertext - decrypts to plaintext */
-	public byte[] add_cipher(byte[] cipher,int len)
-	{
-		int i,j=0;
-		int counter;
-		byte[] B=new byte[16];
-		byte[] b=new byte[4];
-		byte[] plain=new byte[len];
-
-		if (status==GCM_ACCEPTING_HEADER) status=GCM_ACCEPTING_CIPHER;
-		if (status!=GCM_ACCEPTING_CIPHER) return new byte[0];
-
-		while (j<len)
-		{
-
-			b[0]=a.f[12]; b[1]=a.f[13]; b[2]=a.f[14]; b[3]=a.f[15];
-			counter=pack(b);
-			counter++;
-			b=unpack(counter);
-			a.f[12]=b[0]; a.f[13]=b[1]; a.f[14]=b[2]; a.f[15]=b[3]; /* increment counter */
-			for (i=0;i<16;i++) B[i]=a.f[i];
-			a.ecb_encrypt(B);        /* encrypt it  */
-			for (i=0;i<16 && j<len;i++)
-			{
-				plain[j]=(byte)(cipher[j]^B[i]);
-				stateX[i]^=cipher[j++];
-				lenC[1]++; if (lenC[1]==0) lenC[0]++;
-			}
-			gf2mul();
-		}
-		if (len%16!=0) status=GCM_NOT_ACCEPTING_MORE;
-		return plain;
-	}
-
-/* Finish and extract Tag */
-	public byte[] finish(boolean extract)
-	{ /* Finish off GHASH and extract tag (MAC) */
-		int i;
-		byte[] tag=new byte[16];
-
-		wrap();
-/* extract tag */
-		if (extract)
-		{
-			a.ecb_encrypt(Y_0);        /* E(K,Y0) */
-			for (i=0;i<16;i++) Y_0[i]^=stateX[i];
-			for (i=0;i<16;i++) {tag[i]=Y_0[i];Y_0[i]=stateX[i]=0;}
-		}
-		status=GCM_FINISHED;
-		a.end();
-		return tag;
-	}
-
-	public static byte[] hex2bytes(String s) {
-		int len = s.length();
-		byte[] data = new byte[len / 2];
-		for (int i = 0; i < len; i += 2) {
-			data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
-                             + Character.digit(s.charAt(i+1), 16));
-		}
-		return data;
-	}
-/*
-	public static void main(String[] args) {
-		int i;
-
-		String KT="feffe9928665731c6d6a8f9467308308";
-		String MT="d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39";
-		String HT="feedfacedeadbeeffeedfacedeadbeefabaddad2";
-//	char* NT="cafebabefacedbaddecaf888";
-// Tag should be 5bc94fbc3221a5db94fae95ae7121a47
-		String NT="9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b";
-// Tag should be 619cc5aefffe0bfa462af43c1699d050
-
-
-		byte[] T=new byte[16];   // Tag
-		byte[] K=new byte[16];   // AES Key
-		byte[] H=new byte[64];   // Header - to be included in Authentication, but not encrypted
-		byte[] N=new byte[100];   // IV - Initialisation vector
-		byte[] M=new byte[100];  // Plaintext to be encrypted/authenticated
-		byte[] C=new byte[100];  // Ciphertext
-		byte[] P=new byte[100];  // Recovered Plaintext
-
-		GCM g=new GCM();
-
-		M=hex2bytes(MT);
-		H=hex2bytes(HT);
-		N=hex2bytes(NT);
-		K=hex2bytes(KT);
-
-		int len=M.length;
-		int lenH=H.length;
-		int lenK=K.length;
-		int lenIV=N.length;
-
- 		System.out.format("Plaintext=\n");
-		for (i=0;i<len;i++) System.out.format("%02x",M[i]);
-		System.out.format("\n");
-
-		g.init(K,lenIV,N);
-		g.add_header(H,lenH);
-		C=g.add_plain(M,len);
-		T=g.finish(true);
-
-		System.out.format("Ciphertext=\n");
-		for (i=0;i<len;i++) System.out.format("%02x",C[i]);
-		System.out.format("\n");
-
-		System.out.format("Tag=\n");
-		for (i=0;i<16;i++) System.out.format("%02x",T[i]);
-		System.out.format("\n");
-
-		g.init(K,lenIV,N);
-		g.add_header(H,lenH);
-		P=g.add_cipher(C,len);
-		T=g.finish(true);
-
- 		System.out.format("Plaintext=\n");
-		for (i=0;i<len;i++) System.out.format("%02x",P[i]);
-		System.out.format("\n");
-
-		System.out.format("Tag=\n");
-		for (i=0;i<16;i++) System.out.format("%02x",T[i]);
-		System.out.format("\n");
-	}
-	*/
-}
diff --git a/java/HASH.java b/java/HASH.java
deleted file mode 100755
index 8a484c1..0000000
--- a/java/HASH.java
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
-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.
-*/
-
-/*
- * Implementation of the Secure Hashing Algorithm (SHA-256)
- *
- * Generates a 256 bit message digest. It should be impossible to come
- * come up with two messages that hash to the same value ("collision free").
- *
- * For use with byte-oriented messages only.
- */
-
-public class HASH {
-	private int[] length=new int[2];
-	private int[] h=new int[8];
-	private int[] w=new int[64];
-
-	public static final int H0=0x6A09E667;
-	public static final int H1=0xBB67AE85;
-	public static final int H2=0x3C6EF372;
-	public static final int H3=0xA54FF53A;
-	public static final int H4=0x510E527F;
-	public static final int H5=0x9B05688C;
-	public static final int H6=0x1F83D9AB;
-	public static final int H7=0x5BE0CD19;
-
-	public static final int len=32;
-
-	public static final int[] K={
-	0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,
-	0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,
-	0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,
-	0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,
-	0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
-	0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070,
-	0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,
-	0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2};
-
-
-/* functions */
-	private static int S(int n,int x)
-	{
-		return (((x)>>>n) | ((x)<<(32-n)));
-	}
-
-	private static int R(int n,int x)
-	{
-		return ((x)>>>n);
-	}
-
-	private static int Ch(int x,int y,int z)
-	{
-		return ((x&y)^(~(x)&z));
-	}
-
-	private static int Maj(int x,int y,int z)
-	{
-		return ((x&y)^(x&z)^(y&z));
-	}
-
-	private static int Sig0(int x)
-	{
-		return (S(2,x)^S(13,x)^S(22,x));
-	}
-
-	private static int Sig1(int x)
-	{
-		return (S(6,x)^S(11,x)^S(25,x));
-	}
-
-	private static int theta0(int x)
-	{
-		return (S(7,x)^S(18,x)^R(3,x));
-	}
-
-	private static int theta1(int x)
-	{
-		return (S(17,x)^S(19,x)^R(10,x));
-	}
-
-
-	private void transform()
-	{ /* basic transformation step */
-		int a,b,c,d,e,f,g,hh,t1,t2;
-		int j;
-		for (j=16;j<64;j++)
-			w[j]=theta1(w[j-2])+w[j-7]+theta0(w[j-15])+w[j-16];
-		a=h[0]; b=h[1]; c=h[2]; d=h[3];
-		e=h[4]; f=h[5]; g=h[6]; hh=h[7];
-
-		for (j=0;j<64;j++)
-		{ /* 64 times - mush it up */
-			t1=hh+Sig1(e)+Ch(e,f,g)+K[j]+w[j];
-			t2=Sig0(a)+Maj(a,b,c);
-			hh=g; g=f; f=e;
-			e=d+t1;
-			d=c;
-			c=b;
-			b=a;
-			a=t1+t2;
-
-		}
-		h[0]+=a; h[1]+=b; h[2]+=c; h[3]+=d;
-		h[4]+=e; h[5]+=f; h[6]+=g; h[7]+=hh;
-	}
-
-/* Initialise Hash function */
-	public void init()
-	{ /* initialise */
-		int i;
-		for (i=0;i<64;i++) w[i]=0;
-		length[0]=length[1]=0;
-		h[0]=H0;
-		h[1]=H1;
-		h[2]=H2;
-		h[3]=H3;
-		h[4]=H4;
-		h[5]=H5;
-		h[6]=H6;
-		h[7]=H7;
-	}
-
-/* Constructor */
-	public HASH()
-	{
-		init();
-	}
-
-/* process a single byte */
-	public void process(int byt)
-	{ /* process the next message byte */
-		int cnt;
-		cnt=(length[0]/32)%16;
-
-		w[cnt]<<=8;
-		w[cnt]|=(byt&0xFF);
-		length[0]+=8;
-		if (length[0]==0) { length[1]++; length[0]=0; }
-		if ((length[0]%512)==0) transform();
-	}
-
-/* process an array of bytes */
-	public void process_array(byte[] b)
-	{
-		for (int i=0;i<b.length;i++) process((int)b[i]);
-	}
-
-/* process a 32-bit integer */
-	public void process_num(int n)
-	{
-		process((n>>24)&0xff);
-		process((n>>16)&0xff);
-		process((n>>8)&0xff);
-		process(n&0xff);
-	}
-
-/* Generate 32-byte Hash */
-	public byte[] hash()
-	{ /* pad message and finish - supply digest */
-		int i;
-		byte[] digest=new byte[32];
-		int len0,len1;
-		len0=length[0];
-		len1=length[1];
-		process(0x80);
-		while ((length[0]%512)!=448) process(0);
-		w[14]=len1;
-		w[15]=len0;
-		transform();
-		for (i=0;i<len;i++)
-		{ /* convert to bytes */
-			digest[i]=(byte)((h[i/4]>>(8*(3-i%4))) & 0xff);
-		}
-		init();
-		return digest;
-	}
-
-/* test program: should produce digest */
-
-//248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1
-/*
-	public static void main(String[] args) {
-		byte[] test="abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq".getBytes();
-		byte[] digest;
-		int i;
-		HASH sh=new HASH();
-
-		for (i=0;i<test.length;i++)
-			sh.process(test[i]);
-
-		digest=sh.hash();
-		for (i=0;i<32;i++) System.out.format("%02x",digest[i]);
-
-	//	for (i=0;i<32;i++) System.out.format("%d ",digest[i]);
-
-		System.out.println("");
-	} */
-}
-
diff --git a/java/MPIN.java b/java/MPIN.java
deleted file mode 100755
index 0c517f1..0000000
--- a/java/MPIN.java
+++ /dev/null
@@ -1,746 +0,0 @@
-/*
-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.
-*/
-
-/* MPIN API Functions */
-
-import java.util.Date;
-
-public class MPIN
-{
-	public static final int EFS=ROM.MODBYTES;
-	public static final int EGS=ROM.MODBYTES;
-	public static final int PAS=16;
-	public static final int INVALID_POINT=-14;
-	public static final int BAD_PARAMS=-11;
-	public static final int WRONG_ORDER=-18;
-	public static final int BAD_PIN=-19;
-
-/* Configure your PIN here */
-
-	public static final int MAXPIN=10000;  /* PIN less than this */
-	public static final int PBLEN=14;      /* Number of bits in PIN */
-	public static final int TS=10;         /* 10 for 4 digit PIN, 14 for 6-digit PIN - 2^TS/TS approx = sqrt(MAXPIN) */
-	public static final int TRAP=200;      /* 200 for 4 digit PIN, 2000 for 6-digit PIN  - approx 2*sqrt(MAXPIN) */
-
-/* Hash number (optional) and string to point on curve */
-
-	public static byte[] hashit(int n,byte[] ID)
-	{
-		HASH H=new HASH();
-		if (n!=0) H.process_num(n);
-		H.process_array(ID);
-		byte[] h=H.hash();
-		return h;
-	}
-
-	public static ECP mapit(byte[] h)
-	{
-		BIG q=new BIG(ROM.Modulus);
-		BIG x=BIG.fromBytes(h);
-		x.mod(q);
-		ECP P;
-		while (true)
-		{
-			P=new ECP(x,0);
-			if (!P.is_infinity()) break;
-			x.inc(1); x.norm();
-		}
-		return P;
-	}
-
-/* needed for SOK */
-	public static ECP2 mapit2(byte[] h)
-	{
-		BIG q=new BIG(ROM.Modulus);
-		BIG x=BIG.fromBytes(h);
-		BIG one=new BIG(1);
-		FP2 X;
-		ECP2 Q,T,K;
-		x.mod(q);
-		while (true)
-		{
-			X=new FP2(one,x);
-			Q=new ECP2(X);
-			if (!Q.is_infinity()) break;
-			x.inc(1); x.norm();
-		}
-/* Fast Hashing to G2 - Fuentes-Castaneda, Knapp and Rodriguez-Henriquez */
-		BIG Fra=new BIG(ROM.CURVE_Fra);
-		BIG Frb=new BIG(ROM.CURVE_Frb);
-		X=new FP2(Fra,Frb);
-		x=new BIG(ROM.CURVE_Bnx);
-
-		T=new ECP2(); T.copy(Q);
-		T.mul(x); T.neg();
-		K=new ECP2(); K.copy(T);
-		K.dbl(); K.add(T); K.affine();
-
-		K.frob(X);
-		Q.frob(X); Q.frob(X); Q.frob(X);
-		Q.add(T); Q.add(K);
-		T.frob(X); T.frob(X);
-		Q.add(T);
-		Q.affine();
-		return Q;
-	}
-
-/* return time in slots since epoch */
-	public static int today() {
-		Date date=new Date();
-		return (int) (date.getTime()/(1000*60*1440));
-	}
-
-/* these next two functions help to implement elligator squared - http://eprint.iacr.org/2014/043 */
-/* maps a random u to a point on the curve */
-	public static ECP map(BIG u,int cb)
-	{
-		ECP P;
-		BIG x=new BIG(u);
-		BIG p=new BIG(ROM.Modulus);
-		x.mod(p);
-		while (true)
-		{
-			P=new ECP(x,cb);
-			if (!P.is_infinity()) break;
-			x.inc(1);  x.norm();
-		}
-		return P;
-	}
-
-/* returns u derived from P. Random value in range 1 to return value should then be added to u */
-	public static int unmap(BIG u,ECP P)
-	{
-		int s=P.getS();
-		ECP R;
-		int r=0;
-		BIG x=P.getX();
-		u.copy(x);
-		while (true)
-		{
-			u.dec(1); u.norm();
-			r++;
-			R=new ECP(u,s);
-			if (!R.is_infinity()) break;
-		}
-		return r;
-	}
-
-	public static byte[] HASH_ID(byte[] ID)
-	{
-		return hashit(0,ID);
-	}
-
-
-/* these next two functions implement elligator squared - http://eprint.iacr.org/2014/043 */
-/* Elliptic curve point E in format (0x04,x,y} is converted to form {0x0-,u,v} */
-/* Note that u and v are indistinguisible from random strings */
-	public static int ENCODING(RAND rng,byte[] E)
-	{
-		int rn,m,su,sv;
-		byte[] T=new byte[EFS];
-
-		for (int i=0;i<EFS;i++) T[i]=E[i+1];
-		BIG u=BIG.fromBytes(T);
-		for (int i=0;i<EFS;i++) T[i]=E[i+EFS+1];
-		BIG v=BIG.fromBytes(T);
-
-		ECP P=new ECP(u,v);
-		if (P.is_infinity()) return INVALID_POINT;
-
-		BIG p=new BIG(ROM.Modulus);
-		u=BIG.randomnum(p,rng);
-
-		su=rng.getByte(); /*if (su<0) su=-su;*/ su%=2;
-
-		ECP W=map(u,su);
-		P.sub(W);
-		sv=P.getS();
-		rn=unmap(v,P);
-		m=rng.getByte(); /*if (m<0) m=-m;*/ m%=rn;
-		v.inc(m+1);
-		E[0]=(byte)(su+2*sv);
-		u.toBytes(T);
-		for (int i=0;i<EFS;i++) E[i+1]=T[i];
-		v.toBytes(T);
-		for (int i=0;i<EFS;i++) E[i+EFS+1]=T[i];
-
-		return 0;
-	}
-
-	public static int DECODING(byte[] D)
-	{
-		int su,sv;
-		byte[] T=new byte[EFS];
-
-		if ((D[0]&0x04)!=0) return INVALID_POINT;
-
-		for (int i=0;i<EFS;i++) T[i]=D[i+1];
-		BIG u=BIG.fromBytes(T);
-		for (int i=0;i<EFS;i++) T[i]=D[i+EFS+1];
-		BIG v=BIG.fromBytes(T);
-
-		su=D[0]&1;
-		sv=(D[0]>>1)&1;
-		ECP W=map(u,su);
-		ECP P=map(v,sv);
-		P.add(W);
-		u=P.getX();
-		v=P.getY();
-		D[0]=0x04;
-		u.toBytes(T);
-		for (int i=0;i<EFS;i++) D[i+1]=T[i];
-		v.toBytes(T);
-		for (int i=0;i<EFS;i++) D[i+EFS+1]=T[i];
-
-		return 0;
-	}
-
-/* R=R1+R2 in group G1 */
-	public static int RECOMBINE_G1(byte[] R1,byte[] R2,byte[] R)
-	{
-		ECP P=ECP.fromBytes(R1);
-		ECP Q=ECP.fromBytes(R2);
-
-		if (P.is_infinity() || Q.is_infinity()) return INVALID_POINT;
-
-		P.add(Q);
-
-		P.toBytes(R);
-		return 0;
-	}
-
-/* W=W1+W2 in group G2 */
-	public static int RECOMBINE_G2(byte[] W1,byte[] W2,byte[] W)
-	{
-		ECP2 P=ECP2.fromBytes(W1);
-		ECP2 Q=ECP2.fromBytes(W2);
-
-		if (P.is_infinity() || Q.is_infinity()) return INVALID_POINT;
-
-		P.add(Q);
-
-		P.toBytes(W);
-		return 0;
-	}
-
-/* create random secret S */
-	public static int RANDOM_GENERATE(RAND rng,byte[] S)
-	{
-		BIG s;
-		BIG r=new BIG(ROM.CURVE_Order);
-		s=BIG.randomnum(r,rng);
-
-		s.toBytes(S);
-		return 0;
-	}
-
-/* Extract PIN from TOKEN for identity CID */
-	public static int EXTRACT_PIN(byte[] CID,int pin,byte[] TOKEN)
-	{
-		ECP P=ECP.fromBytes(TOKEN);
-		if (P.is_infinity()) return INVALID_POINT;
-		byte[] h=hashit(0,CID);
-		ECP R=mapit(h);
-
-
-		pin%=MAXPIN;
-
-		R=R.pinmul(pin,PBLEN);
-		P.sub(R);
-
-		P.toBytes(TOKEN);
-
-		return 0;
-	}
-
-/* Implement step 2 on client side of MPin protocol */
-	public static int CLIENT_2(byte[] X,byte[] Y,byte[] SEC)
-	{
-		BIG r=new BIG(ROM.CURVE_Order);
-		ECP P=ECP.fromBytes(SEC);
-		if (P.is_infinity()) return INVALID_POINT;
-
-		BIG px=BIG.fromBytes(X);
-		BIG py=BIG.fromBytes(Y);
-		px.add(py);
-		px.mod(r);
-		px.rsub(r);
-
-		PAIR.G1mul(P,px).toBytes(SEC);
-		return 0;
-	}
-
-/* Implement step 1 on client side of MPin protocol */
-	public static int CLIENT_1(int date,byte[] CLIENT_ID,RAND rng,byte[] X,int pin,byte[] TOKEN,byte[] SEC,byte[] xID,byte[] xCID,byte[] PERMIT)
-	{
-		BIG r=new BIG(ROM.CURVE_Order);
-//		BIG q=new BIG(ROM.Modulus);
-		BIG x;
-//		BIG m=new BIG(0);
-		if (rng!=null)
-		{
-			x=BIG.randomnum(r,rng);
-			x.toBytes(X);
-		}
-		else
-		{
-			x=BIG.fromBytes(X);
-		}
-		ECP P,T,W;
-		BIG px;
-//		byte[] t=new byte[EFS];
-
-		byte[] h=hashit(0,CLIENT_ID);
-		P=mapit(h);
-
-		T=ECP.fromBytes(TOKEN);
-		if (T.is_infinity()) return INVALID_POINT;
-
-		pin%=MAXPIN;
-		W=P.pinmul(pin,PBLEN);
-		T.add(W);
-		if (date!=0)
-		{
-			W=ECP.fromBytes(PERMIT);
-			if (W.is_infinity()) return INVALID_POINT;
-			T.add(W);
-			h=hashit(date,h);
-			W=mapit(h);
-			if (xID!=null)
-			{
-				P=PAIR.G1mul(P,x);
-				P.toBytes(xID);
-				W=PAIR.G1mul(W,x);
-				P.add(W);
-			}
-			else
-			{
-				P.add(W);
-				P=PAIR.G1mul(P,x);
-			}
-			if (xCID!=null) P.toBytes(xCID);
-		}
-		else
-		{
-			if (xID!=null)
-			{
-				P=PAIR.G1mul(P,x);
-				P.toBytes(xID);
-			}
-		}
-
-
-		T.toBytes(SEC);
-		return 0;
-	}
-
-/* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */
-	public static int GET_SERVER_SECRET(byte[] S,byte[] SST)
-	{
-		ECP2 Q=new ECP2(new FP2(new BIG(ROM.CURVE_Pxa),new BIG(ROM.CURVE_Pxb)),new FP2(new BIG(ROM.CURVE_Pya),new BIG(ROM.CURVE_Pyb)));
-
-		BIG s=BIG.fromBytes(S);
-		Q=PAIR.G2mul(Q,s);
-		Q.toBytes(SST);
-		return 0;
-	}
-
-/*
- W=x*H(G);
- if RNG == NULL then X is passed in
- if RNG != NULL the X is passed out
- if type=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve
-*/
-	public static int GET_G1_MULTIPLE(RAND rng, int type,byte[] X,byte[] G,byte[] W)
-	{
-		BIG x;
-		BIG r=new BIG(ROM.CURVE_Order);
-		if (rng!=null)
-		{
-			x=BIG.randomnum(r,rng);
-			x.toBytes(X);
-		}
-		else
-		{
-			x=BIG.fromBytes(X);
-		}
-		ECP P;
-		if (type==0)
-		{
-			P=ECP.fromBytes(G);
-			if (P.is_infinity()) return INVALID_POINT;
-		}
-		else
-			P=mapit(G);
-
-		PAIR.G1mul(P,x).toBytes(W);
-		return 0;
-	}
-
-/* Client secret CST=S*H(CID) where CID is client ID and S is master secret */
-/* CID is hashed externally */
-	public static int GET_CLIENT_SECRET(byte[] S,byte[] CID,byte[] CST)
-	{
-		return GET_G1_MULTIPLE(null,1,S,CID,CST);
-	}
-
-/* Time Permit CTT=S*(date|H(CID)) where S is master secret */
-	public static int GET_CLIENT_PERMIT(int date,byte[] S,byte[] CID,byte[] CTT)
-	{
-		byte[] h=hashit(date,CID);
-		ECP P=mapit(h);
-
-		BIG s=BIG.fromBytes(S);
-		PAIR.G1mul(P,s).toBytes(CTT);
-		return 0;
-	}
-
-/* Outputs H(CID) and H(T|H(CID)) for time permits. If no time permits set HID=HTID */
-	public static void SERVER_1(int date,byte[] CID,byte[] HID,byte[] HTID)
-	{
-		byte[] h=hashit(0,CID);
-		ECP R,P=mapit(h);
-
-		if (date!=0)
-		{
-			if (HID!=null) P.toBytes(HID);
-			h=hashit(date,h);
-			R=mapit(h);
-			P.add(R);
-			P.toBytes(HTID);
-		}
-		else P.toBytes(HID);
-	}
-
-/* Implement step 2 of MPin protocol on server side */
-	public static int SERVER_2(int date,byte[] HID,byte[] HTID,byte[] Y,byte[] SST,byte[] xID,byte[] xCID,byte[] mSEC,byte[] E,byte[] F)
-	{
-		BIG q=new BIG(ROM.Modulus);
-		ECP2 Q=new ECP2(new FP2(new BIG(ROM.CURVE_Pxa),new BIG(ROM.CURVE_Pxb)),new FP2(new BIG(ROM.CURVE_Pya),new BIG(ROM.CURVE_Pyb)));
-		ECP2 sQ=ECP2.fromBytes(SST);
-		if (sQ.is_infinity()) return INVALID_POINT;
-
-		ECP R;
-		if (date!=0)
-			R=ECP.fromBytes(xCID);
-		else
-		{
-			if (xID==null) return BAD_PARAMS;
-			R=ECP.fromBytes(xID);
-		}
-		if (R.is_infinity()) return INVALID_POINT;
-
-		BIG y=BIG.fromBytes(Y);
-		ECP P;
-		if (date!=0) P=ECP.fromBytes(HTID);
-		else
-		{
-			if (HID==null) return BAD_PARAMS;
-			P=ECP.fromBytes(HID);
-		}
-
-		if (P.is_infinity()) return INVALID_POINT;
-
-		P=PAIR.G1mul(P,y);
-		P.add(R);
-		R=ECP.fromBytes(mSEC);
-		if (R.is_infinity()) return INVALID_POINT;
-
-		FP12 g;
-//		FP12 g1=new FP12(0);
-
-		g=PAIR.ate2(Q,R,sQ,P);
-		g=PAIR.fexp(g);
-
-		if (!g.isunity())
-		{
-			if (HID!=null && xID!=null && E!=null && F!=null)
-			{
-				g.toBytes(E);
-				if (date!=0)
-				{
-					P=ECP.fromBytes(HID);
-					if (P.is_infinity()) return INVALID_POINT;
-					R=ECP.fromBytes(xID);
-					if (R.is_infinity()) return INVALID_POINT;
-
-					P=PAIR.G1mul(P,y);
-					P.add(R);
-				}
-				g=PAIR.ate(Q,P);
-				g=PAIR.fexp(g);
-				g.toBytes(F);
-			}
-			return BAD_PIN;
-		}
-
-		return 0;
-	}
-
-/* Pollards kangaroos used to return PIN error */
-	public static int KANGAROO(byte[] E,byte[] F)
-	{
-		FP12 ge=FP12.fromBytes(E);
-		FP12 gf=FP12.fromBytes(F);
-		int[] distance = new int[TS];
-		FP12 t=new FP12(gf);
-		FP12[] table=new FP12[TS];
-		int i,j,m,s,dn,dm,res,steps;
-
-		s=1;
-		for (m=0;m<TS;m++)
-		{
-			distance[m]=s;
-			table[m]=new FP12(t);
-			s*=2;
-			t.usqr();
-		}
-		t.one();
-		dn=0;
-		for (j=0;j<TRAP;j++)
-		{
-			i=t.geta().geta().getA().lastbits(8)%TS;
-			t.mul(table[i]);
-			dn+=distance[i];
-		}
-		gf.copy(t); gf.conj();
-		steps=0; dm=0;
-		res=0;
-		while (dm-dn<MAXPIN)
-		{
-			steps++;
-			if (steps>4*TRAP) break;
-			i=ge.geta().geta().getA().lastbits(8)%TS;
-			ge.mul(table[i]);
-			dm+=distance[i];
-			if (ge.equals(t))
-			{
-				res=dm-dn;
-				break;
-			}
-			if (ge.equals(gf))
-			{
-				res=dn-dm;
-				break;
-			}
-
-		}
-		if (steps>4*TRAP || dm-dn>=MAXPIN) {res=0; }    // Trap Failed  - probable invalid token
-		return res;
-	}
-
-/* Functions to support M-Pin Full */
-
-	public static int PRECOMPUTE(byte[] TOKEN,byte[] CID,byte[] G1,byte[] G2)
-	{
-		ECP P,T;
-		FP12 g;
-
-		T=ECP.fromBytes(TOKEN);
-		if (T.is_infinity()) return INVALID_POINT;
-
-		P=mapit(CID);
-
-		ECP2 Q=new ECP2(new FP2(new BIG(ROM.CURVE_Pxa),new BIG(ROM.CURVE_Pxb)),new FP2(new BIG(ROM.CURVE_Pya),new BIG(ROM.CURVE_Pyb)));
-
-		g=PAIR.ate(Q,T);
-		g=PAIR.fexp(g);
-		g.toBytes(G1);
-
-		g=PAIR.ate(Q,P);
-		g=PAIR.fexp(g);
-		g.toBytes(G2);
-
-		return 0;
-	}
-
-/* calculate common key on client side */
-/* wCID = w.(A+AT) */
-	public static int CLIENT_KEY(byte[] G1,byte[] G2,int pin,byte[] R,byte[] X,byte[] wCID,byte[] CK)
-	{
-		HASH H=new HASH();
-		byte[] t=new byte[EFS];
-
-		FP12 g1=FP12.fromBytes(G1);
-		FP12 g2=FP12.fromBytes(G2);
-		BIG z=BIG.fromBytes(R);
-		BIG x=BIG.fromBytes(X);
-
-		ECP W=ECP.fromBytes(wCID);
-		if (W.is_infinity()) return INVALID_POINT;
-
-		W=PAIR.G1mul(W,x);
-
-		FP2 f=new FP2(new BIG(ROM.CURVE_Fra),new BIG(ROM.CURVE_Frb));
-		BIG r=new BIG(ROM.CURVE_Order);
-		BIG q=new BIG(ROM.Modulus);
-
-		BIG m=new BIG(q);
-		m.mod(r);
-
-		BIG a=new BIG(z);
-		a.mod(m);
-
-		BIG b=new BIG(z);
-		b.div(m);
-
-		g2.pinpow(pin,PBLEN);
-		g1.mul(g2);
-
-		FP4 c=g1.trace();
-		g2.copy(g1);
-		g2.frob(f);
-		FP4 cp=g2.trace();
-		g1.conj();
-		g2.mul(g1);
-		FP4 cpm1=g2.trace();
-		g2.mul(g1);
-		FP4 cpm2=g2.trace();
-
-		c=c.xtr_pow2(cp,cpm1,cpm2,a,b);
-
-		c.geta().getA().toBytes(t);
-		H.process_array(t);
-		c.geta().getB().toBytes(t);
-		H.process_array(t);
-		c.getb().getA().toBytes(t);
-		H.process_array(t);
-		c.getb().getB().toBytes(t);
-		H.process_array(t);
-
-		W.getX().toBytes(t);
-		H.process_array(t);
-		W.getY().toBytes(t);
-		H.process_array(t);
-
-		t=H.hash();
-		for (int i=0;i<PAS;i++) CK[i]=t[i];
-
-		return 0;
-	}
-
-/* calculate common key on server side */
-/* Z=r.A - no time permits involved */
-
-	public static int SERVER_KEY(byte[] Z,byte[] SST,byte[] W,byte[] xID,byte[] xCID,byte[] SK)
-	{
-		HASH H=new HASH();
-		byte[] t=new byte[EFS];
-
-		ECP2 sQ=ECP2.fromBytes(SST);
-		if (sQ.is_infinity()) return INVALID_POINT;
-		ECP R=ECP.fromBytes(Z);
-		if (R.is_infinity()) return INVALID_POINT;
-
-		ECP U;
-		if (xCID!=null)
-			U=ECP.fromBytes(xCID);
-		else
-			U=ECP.fromBytes(xID);
-		if (U.is_infinity()) return INVALID_POINT;
-
-		BIG w=BIG.fromBytes(W);
-		U=PAIR.G1mul(U,w);
-		FP12 g=PAIR.ate(sQ,R);
-		g=PAIR.fexp(g);
-
-		FP4 c=g.trace();
-		c.geta().getA().toBytes(t);
-		H.process_array(t);
-		c.geta().getB().toBytes(t);
-		H.process_array(t);
-		c.getb().getA().toBytes(t);
-		H.process_array(t);
-		c.getb().getB().toBytes(t);
-		H.process_array(t);
-
-		U.getX().toBytes(t);
-		H.process_array(t);
-		U.getY().toBytes(t);
-		H.process_array(t);
-
-		t=H.hash();
-		for (int i=0;i<PAS;i++) SK[i]=t[i];
-
-		return 0;
-	}
-
-/* return time since epoch */
-	public static int GET_TIME() {
-		Date date=new Date();
-		return (int) (date.getTime()/1000);
-	}
-
-/* Generate Y = H(epoch, xCID/xID) */
-        public static void GET_Y(int TimeValue,byte[] xCID,byte[] Y)
-        {
-          byte[] h = hashit(TimeValue,xCID);
-          BIG y = BIG.fromBytes(h);
-          BIG q=new BIG(ROM.CURVE_Order);
-          y.mod(q);
-          y.toBytes(Y);
-        }
-
-/* One pass MPIN Client */
-        public static int CLIENT(int date,byte[] CLIENT_ID,RAND RNG,byte[] X,int pin,byte[] TOKEN,byte[] SEC,byte[] xID,byte[] xCID,byte[] PERMIT, int TimeValue, byte[] Y)
-        {
-          int rtn=0;
-
-          byte[] pID;
-          if (date == 0)
-            pID = xID;
-          else
-            pID = xCID;
-
-          rtn = CLIENT_1(date,CLIENT_ID,RNG,X,pin,TOKEN,SEC,xID,xCID,PERMIT);
-          if (rtn != 0)
-            return rtn;
-
-          GET_Y(TimeValue,pID,Y);
-
-          rtn = CLIENT_2(X,Y,SEC);
-          if (rtn != 0)
-            return rtn;
-
-          return 0;
-        }
-
-/* One pass MPIN Server */
-        public static int SERVER(int date,byte[] HID,byte[] HTID,byte[] Y,byte[] SST,byte[] xID,byte[] xCID,byte[] SEC,byte[] E,byte[] F,byte[] CID, int TimeValue)
-        {
-          int rtn=0;
-
-          byte[] pID;
-          if (date == 0)
-            pID = xID;
-          else
-            pID = xCID;
-
-          SERVER_1(date,CID,HID,HTID);
-
-          GET_Y(TimeValue,pID,Y);
-
-          rtn = SERVER_2(date,HID,HTID,Y,SST,xID,xCID,SEC,E,F);
-          if (rtn != 0)
-            return rtn;
-
-          return 0;
-        }
-
-}
diff --git a/java/PAIR.java b/java/PAIR.java
deleted file mode 100755
index ad93b61..0000000
--- a/java/PAIR.java
+++ /dev/null
@@ -1,539 +0,0 @@
-/*
-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.
-*/
-
-/* AMCL BN Curve Pairing functions */
-
-public final class PAIR {
-
-/* Line function */
-	public static FP12 line(ECP2 A,ECP2 B,FP Qx,FP Qy)
-	{
-		ECP2 P=new ECP2();
-
-		FP4 a,b,c;
-		P.copy(A);
-		FP2 ZZ=new FP2(P.getz());
-		ZZ.sqr();
-		int D;
-		if (A==B) D=A.dbl(); /* Check this return value in amcl_ec2.c */
-		else D=A.add(B);
-		if (D<0)
-			return new FP12(1);
-		FP2 Z3=new FP2(A.getz());
-		c=new FP4(0);
-		if (D==0)
-		{ /* Addition */
-			FP2 X=new FP2(B.getx());
-			FP2 Y=new FP2(B.gety());
-			FP2 T=new FP2(P.getz());
-			T.mul(Y);
-			ZZ.mul(T);
-
-			FP2 NY=new FP2(P.gety()); NY.neg();
-			ZZ.add(NY);
-			Z3.pmul(Qy);
-			T.mul(P.getx());
-			X.mul(NY);
-			T.add(X);
-			a=new FP4(Z3,T);
-			ZZ.neg();
-			ZZ.pmul(Qx);
-			b=new FP4(ZZ);
-		}
-		else
-		{ /* Doubling */
-			FP2 X=new FP2(P.getx());
-			FP2 Y=new FP2(P.gety());
-			FP2 T=new FP2(P.getx());
-			T.sqr();
-			T.imul(3);
-
-			Y.sqr();
-			Y.add(Y);
-			Z3.mul(ZZ);
-			Z3.pmul(Qy);
-
-			X.mul(T);
-			X.sub(Y);
-			a=new FP4(Z3,X);
-			T.neg();
-			ZZ.mul(T);
-			ZZ.pmul(Qx);
-			b=new FP4(ZZ);
-		}
-		return new FP12(a,b,c);
-	}
-
-/* Optimal R-ate pairing */
-	public static FP12 ate(ECP2 P,ECP Q)
-	{
-		FP2 f=new FP2(new BIG(ROM.CURVE_Fra),new BIG(ROM.CURVE_Frb));
-		BIG x=new BIG(ROM.CURVE_Bnx);
-		BIG n=new BIG(x);
-		ECP2 K=new ECP2();
-		FP12 lv;
-		n.pmul(6); n.dec(2); n.norm();
-		P.affine();
-		Q.affine();
-		FP Qx=new FP(Q.getx());
-		FP Qy=new FP(Q.gety());
-
-		ECP2 A=new ECP2();
-		FP12 r=new FP12(1);
-
-		A.copy(P);
-		int nb=n.nbits();
-
-		for (int i=nb-2;i>=1;i--)
-		{
-			lv=line(A,A,Qx,Qy);
-			r.smul(lv);
-
-			if (n.bit(i)==1)
-			{
-				lv=line(A,P,Qx,Qy);
-
-				r.smul(lv);
-			}
-			r.sqr();
-		}
-
-		lv=line(A,A,Qx,Qy);
-		r.smul(lv);
-
-/* R-ate fixup */
-
-		r.conj();
-
-		K.copy(P);
-		K.frob(f);
-		A.neg();
-		lv=line(A,K,Qx,Qy);
-		r.smul(lv);
-		K.frob(f);
-		K.neg();
-		lv=line(A,K,Qx,Qy);
-		r.smul(lv);
-
-		return r;
-	}
-
-/* Optimal R-ate double pairing e(P,Q).e(R,S) */
-	public static FP12 ate2(ECP2 P,ECP Q,ECP2 R,ECP S)
-	{
-		FP2 f=new FP2(new BIG(ROM.CURVE_Fra),new BIG(ROM.CURVE_Frb));
-		BIG x=new BIG(ROM.CURVE_Bnx);
-		BIG n=new BIG(x);
-		ECP2 K=new ECP2();
-		FP12 lv;
-		n.pmul(6); n.dec(2); n.norm();
-		P.affine();
-		Q.affine();
-		R.affine();
-		S.affine();
-
-		FP Qx=new FP(Q.getx());
-		FP Qy=new FP(Q.gety());
-		FP Sx=new FP(S.getx());
-		FP Sy=new FP(S.gety());
-
-		ECP2 A=new ECP2();
-		ECP2 B=new ECP2();
-		FP12 r=new FP12(1);
-
-		A.copy(P);
-		B.copy(R);
-		int nb=n.nbits();
-
-		for (int i=nb-2;i>=1;i--)
-		{
-			lv=line(A,A,Qx,Qy);
-			r.smul(lv);
-			lv=line(B,B,Sx,Sy);
-			r.smul(lv);
-
-			if (n.bit(i)==1)
-			{
-				lv=line(A,P,Qx,Qy);
-				r.smul(lv);
-				lv=line(B,R,Sx,Sy);
-				r.smul(lv);
-			}
-			r.sqr();
-		}
-
-		lv=line(A,A,Qx,Qy);
-		r.smul(lv);
-
-		lv=line(B,B,Sx,Sy);
-		r.smul(lv);
-
-/* R-ate fixup */
-		r.conj();
-
-		K.copy(P);
-		K.frob(f);
-		A.neg();
-		lv=line(A,K,Qx,Qy);
-		r.smul(lv);
-		K.frob(f);
-		K.neg();
-		lv=line(A,K,Qx,Qy);
-		r.smul(lv);
-
-		K.copy(R);
-		K.frob(f);
-		B.neg();
-		lv=line(B,K,Sx,Sy);
-		r.smul(lv);
-		K.frob(f);
-		K.neg();
-		lv=line(B,K,Sx,Sy);
-		r.smul(lv);
-
-		return r;
-	}
-
-/* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */
-	public static FP12 fexp(FP12 m)
-	{
-		FP2 f=new FP2(new BIG(ROM.CURVE_Fra),new BIG(ROM.CURVE_Frb));
-		BIG x=new BIG(ROM.CURVE_Bnx);
-		FP12 r=new FP12(m);
-		FP12 x0,x1,x2,x3,x4,x5;
-
-/* Easy part of final exp */
-		FP12 lv=new FP12(r);
-		lv.inverse();
-		r.conj();
-
-		r.mul(lv);
-		lv.copy(r);
-		r.frob(f);
-		r.frob(f);
-		r.mul(lv);
-/* Hard part of final exp */
-		lv.copy(r);
-		lv.frob(f);
-		x0=new FP12(lv);
-		x0.frob(f);
-		lv.mul(r);
-		x0.mul(lv);
-		x0.frob(f);
-		x1=new FP12(r);
-		x1.conj();
-		x4=r.pow(x);
-
-		x3=new FP12(x4);
-		x3.frob(f);
-
-		x2=x4.pow(x);
-
-		x5=new FP12(x2); x5.conj();
-		lv=x2.pow(x);
-
-		x2.frob(f);
-		r.copy(x2); r.conj();
-
-		x4.mul(r);
-		x2.frob(f);
-
-		r.copy(lv);
-		r.frob(f);
-		lv.mul(r);
-
-		lv.usqr();
-		lv.mul(x4);
-		lv.mul(x5);
-		r.copy(x3);
-		r.mul(x5);
-		r.mul(lv);
-		lv.mul(x2);
-		r.usqr();
-		r.mul(lv);
-		r.usqr();
-		lv.copy(r);
-		lv.mul(x1);
-		r.mul(x0);
-		lv.usqr();
-		r.mul(lv);
-		r.reduce();
-		return r;
-	}
-
-/* GLV method */
-	public static BIG[] glv(BIG e)
-	{
-		int i,j;
-		BIG t=new BIG(0);
-		BIG q=new BIG(ROM.CURVE_Order);
-		BIG[] u=new BIG[2];
-		BIG[] v=new BIG[2];
-		for (i=0;i<2;i++)
-		{
-			t.copy(new BIG(ROM.CURVE_W[i]));  // why not just t=new BIG(ROM.CURVE_W[i]);
-			DBIG d=BIG.mul(t,e);
-			v[i]=new BIG(d.div(q));
-			u[i]=new BIG(0);
-		}
-		u[0].copy(e);
-		for (i=0;i<2;i++)
-			for (j=0;j<2;j++)
-			{
-				t.copy(new BIG(ROM.CURVE_SB[j][i]));
-				t.copy(BIG.modmul(v[j],t,q));
-				u[i].add(q);
-				u[i].sub(t);
-				u[i].mod(q);
-			}
-		return u;
-	}
-
-/* Galbraith & Scott Method */
-	public static BIG[] gs(BIG e)
-	{
-		int i,j;
-		BIG t=new BIG(0);
-		BIG q=new BIG(ROM.CURVE_Order);
-		BIG[] u=new BIG[4];
-		BIG[] v=new BIG[4];
-		for (i=0;i<4;i++)
-		{
-			t.copy(new BIG(ROM.CURVE_WB[i]));
-			DBIG d=BIG.mul(t,e);
-			v[i]=new BIG(d.div(q));
-			u[i]=new BIG(0);
-		}
-		u[0].copy(e);
-		for (i=0;i<4;i++)
-			for (j=0;j<4;j++)
-			{
-				t.copy(new BIG(ROM.CURVE_BB[j][i]));
-				t.copy(BIG.modmul(v[j],t,q));
-				u[i].add(q);
-				u[i].sub(t);
-				u[i].mod(q);
-			}
-		return u;
-	}
-
-/* Multiply P by e in group G1 */
-	public static ECP G1mul(ECP P,BIG e)
-	{
-		ECP R;
-		if (ROM.USE_GLV)
-		{
-			P.affine();
-			R=new ECP();
-			R.copy(P);
-			int i,np,nn;
-			ECP Q=new ECP();
-			Q.copy(P);
-			BIG q=new BIG(ROM.CURVE_Order);
-			FP cru=new FP(new BIG(ROM.CURVE_Cru));
-			BIG t=new BIG(0);
-			BIG[] u=glv(e);
-			Q.getx().mul(cru);
-
-			np=u[0].nbits();
-			t.copy(BIG.modneg(u[0],q));
-			nn=t.nbits();
-			if (nn<np)
-			{
-				u[0].copy(t);
-				R.neg();
-			}
-
-			np=u[1].nbits();
-			t.copy(BIG.modneg(u[1],q));
-			nn=t.nbits();
-			if (nn<np)
-			{
-				u[1].copy(t);
-				Q.neg();
-			}
-
-			R=R.mul2(u[0],Q,u[1]);
-
-		}
-		else
-		{
-			R=P.mul(e);
-		}
-		return R;
-	}
-
-/* Multiply P by e in group G2 */
-	public static ECP2 G2mul(ECP2 P,BIG e)
-	{
-		ECP2 R;
-		if (ROM.USE_GS_G2)
-		{
-			ECP2[] Q=new ECP2[4];
-			FP2 f=new FP2(new BIG(ROM.CURVE_Fra),new BIG(ROM.CURVE_Frb));
-			BIG q=new BIG(ROM.CURVE_Order);
-			BIG[] u=gs(e);
-
-
-
-			BIG t=new BIG(0);
-			int i,np,nn;
-			P.affine();
-			Q[0]=new ECP2(); Q[0].copy(P);
-			for (i=1;i<4;i++)
-			{
-				Q[i]=new ECP2(); Q[i].copy(Q[i-1]);
-				Q[i].frob(f);
-			}
-			for (i=0;i<4;i++)
-			{
-				np=u[i].nbits();
-				t.copy(BIG.modneg(u[i],q));
-				nn=t.nbits();
-				if (nn<np)
-				{
-					u[i].copy(t);
-					Q[i].neg();
-				}
-			}
-
-			R=ECP2.mul4(Q,u);
-		}
-		else
-		{
-			R=P.mul(e);
-		}
-		return R;
-	}
-
-/* f=f^e */
-/* Note that this method requires a lot of RAM! Better to use compressed XTR method, see FP4.java */
-	public static FP12 GTpow(FP12 d,BIG e)
-	{
-		FP12 r;
-		if (ROM.USE_GS_GT)
-		{
-			FP12[] g=new FP12[4];
-			FP2 f=new FP2(new BIG(ROM.CURVE_Fra),new BIG(ROM.CURVE_Frb));
-			BIG q=new BIG(ROM.CURVE_Order);
-			BIG t=new BIG(0);
-			int i,np,nn;
-			BIG[] u=gs(e);
-
-			g[0]=new FP12(d);
-			for (i=1;i<4;i++)
-			{
-				g[i]=new FP12(0); g[i].copy(g[i-1]);
-				g[i].frob(f);
-			}
-			for (i=0;i<4;i++)
-			{
-				np=u[i].nbits();
-				t.copy(BIG.modneg(u[i],q));
-				nn=t.nbits();
-				if (nn<np)
-				{
-					u[i].copy(t);
-					g[i].conj();
-				}
-			}
-			r=FP12.pow4(g,u);
-		}
-		else
-		{
-			r=d.pow(e);
-		}
-		return r;
-	}
-
-/* test group membership */
-/* with GT-Strong curve, now only check that m!=1, conj(m)*m==1, and m.m^{p^4}=m^{p^2} */
-	public static boolean GTmember(FP12 m)
-	{
-		if (m.isunity()) return false;
-		FP12 r=new FP12(m);
-		r.conj();
-		r.mul(m);
-		if (!r.isunity()) return false;
-
-		FP2 f=new FP2(new BIG(ROM.CURVE_Fra),new BIG(ROM.CURVE_Frb));
-
-		r.copy(m); r.frob(f); r.frob(f);
-		FP12 w=new FP12(r); w.frob(f); w.frob(f);
-		w.mul(m);
-		if (!ROM.GT_STRONG)
-		{
-			if (!w.equals(r)) return false;
-			BIG x=new BIG(ROM.CURVE_Bnx);
-			r.copy(m); w=r.pow(x); w=w.pow(x);
-			r.copy(w); r.sqr(); r.mul(w); r.sqr();
-			w.copy(m); w.frob(f);
-		}
-		return w.equals(r);
-	}
-/*
-	public static void main(String[] args) {
-		ECP Q=new ECP(new BIG(ROM.CURVE_Gx),new BIG(ROM.CURVE_Gy));
-		ECP2 P=new ECP2(new FP2(new BIG(ROM.CURVE_Pxa),new BIG(ROM.CURVE_Pxb)),new FP2(new BIG(ROM.CURVE_Pya),new BIG(ROM.CURVE_Pyb)));
-
-		BIG r=new BIG(ROM.CURVE_Order);
-		BIG xa=new BIG(ROM.CURVE_Pxa);
-
-		System.out.println("P= "+P.toString());
-		System.out.println("Q= "+Q.toString());
-
-		BIG m=new BIG(17);
-
-		FP12 e=ate(P,Q);
-		System.out.println("\ne= "+e.toString());
-
-		e=fexp(e);
-	//	e=GTpow(e,m);
-
-		System.out.println("\ne= "+e.toString());
-
-		BIG [] GLV=glv(r);
-
-		System.out.println("GLV[0]= "+GLV[0].toString());
-		System.out.println("GLV[0]= "+GLV[1].toString());
-
-		ECP G=new ECP(); G.copy(Q);
-		ECP2 R=new ECP2(); R.copy(P);
-
-
-		e=ate(R,Q);
-		e=fexp(e);
-
-		e=GTpow(e,xa);
-		System.out.println("\ne= "+e.toString());
-
-
-		R=G2mul(R,xa);
-		e=ate(R,G);
-		e=fexp(e);
-
-		System.out.println("\ne= "+e.toString());
-
-		G=G1mul(G,xa);
-		e=ate(P,G);
-		e=fexp(e);
-		System.out.println("\ne= "+e.toString());
-	} */
-}
-
diff --git a/java/RAND.java b/java/RAND.java
deleted file mode 100755
index 1bf6be2..0000000
--- a/java/RAND.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
-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.
-*/
-
-/*
- *   Cryptographic strong random number generator
- *
- *   Unguessable seed -> SHA -> PRNG internal state -> SHA -> random numbers
- *   Slow - but secure
- *
- *   See ftp://ftp.rsasecurity.com/pub/pdfs/bull-1.pdf for a justification
- */
-
-/* Marsaglia & Zaman Random number generator constants */
-
-
-public class RAND {
-/* Cryptographically strong pseudo-random number generator */
-
-	private static final int NK=21;
-	private static final int NJ=6;
-	private static final int NV=8;
-	private int[] ira=new int[NK];  /* random number...   */
-	private int rndptr;   /* ...array & pointer */
-	private int borrow;
-	private int pool_ptr;
-	private byte[] pool=new byte[32];    /* random pool */
-
-	public RAND()
-	{
-		clean();
-	}
-
-	private int sbrand()
-	{ /* Marsaglia & Zaman random number generator */
-		int i,k;
-		long pdiff,t;
-
-		rndptr++;
-		if (rndptr<NK) return ira[rndptr];
-		rndptr=0;
-		for (i=0,k=NK-NJ;i<NK;i++,k++)
-		{ /* calculate next NK values */
-			if (k==NK) k=0;
-			t=((long)ira[k])&0xffffffffL;
-			pdiff=(t - (((long)ira[i])&0xffffffffL) - (long)borrow)&0xffffffffL;
-			if (pdiff<t) borrow=0;
-			if (pdiff>t) borrow=1;
-			ira[i]=(int)(pdiff&0xffffffffL);
-		}
-
-		return ira[0];
-	}
-
-	public void sirand(int seed)
-	{
-		int i,in;
-		int t,m=1;
-		borrow=0;
-		rndptr=0;
-		ira[0]^=seed;
-		for (i=1;i<NK;i++)
-		{ /* fill initialisation vector */
-			in=(NV*i)%NK;
-			ira[in]^=m;      /* note XOR */
-			t=m;
-			m=seed-m;
-			seed=t;
-		}
-		for (i=0;i<10000;i++) sbrand(); /* "warm-up" & stir the generator */
-	}
-
-	private void fill_pool()
-	{
-		HASH sh=new HASH();
-		for (int i=0;i<128;i++) sh.process(sbrand());
-		pool=sh.hash();
-		pool_ptr=0;
-	}
-
-	private static int pack(byte[] b)
-	{ /* pack 4 bytes into a 32-bit Word */
-		return ((((int)b[3])&0xff)<<24)|(((int)b[2]&0xff)<<16)|(((int)b[1]&0xff)<<8)|((int)b[0]&0xff);
-	}
-
-/* Initialize RNG with some real entropy from some external source */
-	public void seed(int rawlen,byte[] raw)
-	{ /* initialise from at least 128 byte string of raw random entropy */
-		int i;
-		byte [] digest;
-		byte [] b=new byte[4];
-		HASH sh=new HASH();
-		pool_ptr=0;
-		for (i=0;i<NK;i++) ira[i]=0;
-		if (rawlen>0)
-		{
-			for (i=0;i<rawlen;i++)
-				sh.process(raw[i]);
-			digest=sh.hash();
-
-/* initialise PRNG from distilled randomness */
-
-			for (i=0;i<8;i++)
-			{
-				b[0]=digest[4*i]; b[1]=digest[4*i+1]; b[2]=digest[4*i+2]; b[3]=digest[4*i+3];
-				sirand(pack(b));
-			}
-		}
-		fill_pool();
-	}
-
-/* Terminate and clean up */
-	public void clean()
-	{ /* kill internal state */
-		int i;
-		pool_ptr=rndptr=0;
-		for (i=0;i<32;i++) pool[i]=0;
-		for (i=0;i<NK;i++) ira[i]=0;
-		borrow=0;
-	}
-
-/* get random byte */
-	public int getByte()
-	{
-		int r;
-		r=pool[pool_ptr++];
-		if (pool_ptr>=32) fill_pool();
-		return (r&0xff);
-	}
-
-/* test main program */
-/*
-	public static void main(String[] args) {
-		int i;
-		byte[] raw=new byte[100];
-		RAND rng=new RAND();
-
-		rng.clean();
-		for (i=0;i<100;i++) raw[i]=(byte)i;
-
-		rng.seed(100,raw);
-
-		for (i=0;i<1000;i++)
-			System.out.format("%03d ",rng.getByte());
-	} */
-}
diff --git a/java/ROM.java b/java/ROM.java
deleted file mode 100755
index ec833d7..0000000
--- a/java/ROM.java
+++ /dev/null
@@ -1,385 +0,0 @@
-/*
-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.
-*/
-
-/* Fixed Data in ROM - Field and Curve parameters */
-
-public class ROM
-{
-/* Don't Modify from here... */
-	public static final int NOT_SPECIAL=0;
-	public static final int PSEUDO_MERSENNE=1;
-	public static final int MONTGOMERY_FRIENDLY=2;
-	public static final int WEIERSTRASS=0;
-	public static final int EDWARDS=1;
-	public static final int MONTGOMERY=2;
-/* ...to here */
-
-/*** Enter Some Field details here  ***/
-// BN Curve
-	public static final int MODBITS=254; /* Number of bits in Modulus */
-	public static final int MOD8=3;  /* Modulus mod 8 */
-// Curve 25519
-//	public static final int MODBITS=255;
-//	public static final int MOD8=5;
-// NIST256 or Brainpool
-//	public static final int MODBITS=256;
-//	public static final int MOD8=7;
-// MF254
-//	public static final int MODBITS=254;
-//	public static final int MOD8=7;
-// MS255
-//public static final int MODBITS= 255;
-//public static final int MOD8= 3;
-// MF256
-//	public static final int MODBITS=256;
-//	public static final int MOD8=7;
-// MS256
-//public static final int MODBITS= 256;
-//public static final int MOD8= 3;
-// ANSSI
-// public static final int MODBITS= 256;
-// public static final int MOD8= 3;
-
-/* Don't Modify from here... */
-	public static final int NLEN=9;
-	public static final int CHUNK=32;
-	public static final int DNLEN=2*NLEN;
-	public static final int BASEBITS=29;
-	public static final int MASK=(((int)1<<BASEBITS)-1);
-	public static final int MODBYTES=32;
-	public static final int NEXCESS =((int)1<<(CHUNK-BASEBITS-1));
-	public static final int FEXCESS =((int)1<<(BASEBITS*NLEN-MODBITS));
-	public static final int OMASK=(int)(-1)<<(MODBITS%BASEBITS);
-	public static final int TBITS=MODBITS%BASEBITS; // Number of active bits in top word
-	public static final int TMASK=((int)1<<TBITS)-1;
-/* ...to here */
-
-
-/* Finite field support - for RSA, DH etc. */
-	public static final int FF_BITS=2048; /* Finite Field Size in bits - must be 256.2^n */
-	public static final int FFLEN=(FF_BITS/256);
-	public static final int HFLEN=(FFLEN/2);  /* Useful for half-size RSA private key operations */
-
-
-// START SPECIFY FIELD DETAILS HERE
-//*********************************************************************************
-// Curve25519 Modulus
-// 	public static final int MODTYPE=PSEUDO_MERSENNE;
-//	public static final int[] Modulus={0x1FFFFFED,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFFF};
-//	public static final int MConst=19;
-
-// NIST-256 Modulus
-//	public static final int MODTYPE=NOT_SPECIAL;
-//	public static final int[] Modulus={0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FF,0x0,0x0,0x40000,0x1FE00000,0xFFFFFF};
-//	public static final int MConst=1;
-
-// MF254 Modulus
-//	public static final int MODTYPE=MONTGOMERY_FRIENDLY;
-//	public static final int[] Modulus={0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3F80FF};
-//	public static final int MConst=0x3F8100;
-
-// MS255 Modulus
-//public static final int MODTYPE= 1;
-//public static final int[] Modulus= {0x1FFFFD03,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFFF};
-//public static final int MConst=0x2FD;
-
-// MS256 Modulus
-//public static final int MODTYPE= 1;
-//public static final int[] Modulus= {0x1FFFFF43,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFFFFFF};
-//public static final int MConst=0xBD;
-
-// MF256 Modulus
-//public static final int MODTYPE= 2;
-//public static final int[] Modulus= {0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFFA7FF};
-//public static final int MConst=0xFFA800;
-
-// Brainpool Modulus
-//	public static final int MODTYPE= 0;
-//	public static final int[] Modulus= {0x1F6E5377,0x9A40E8,0x9880A08,0x17EC47AA,0x18D726E3,0x5484EC1,0x6F0F998,0x1B743DD5,0xA9FB57};
-//	public static final int MConst=0xEFD89B9;
-
-// ANSSI Modulus
-//  public static final int MODTYPE= 0;
-//  public static final int[] Modulus= {0x186E9C03,0x7E79A9E,0x12329B7A,0x35B7957,0x435B396,0x16F46721,0x163C4049,0x1181675A,0xF1FD17};
-//  public static final int MConst=0x164E1155;
-
-
-// BNCX Curve Modulus
-	public static final int MODTYPE=NOT_SPECIAL;
-	public static final int[] Modulus= {0x1C1B55B3,0x13311F7A,0x24FB86F,0x1FADDC30,0x166D3243,0xFB23D31,0x836C2F7,0x10E05,0x240000};
-	public static final int MConst=0x19789E85;
-
-// BN Curve Modulus
-//public static final int MODTYPE=NOT_SPECIAL;
-//public static final int[] Modulus= {0x13,0x18000000,0x4E9,0x2000000,0x8612,0x6C00000,0x6E8D1,0x10480000,0x252364};
-//public static final int MConst=0x179435E5;
-
-// BNT Curve Modulus
-//public static final int MODTYPE=NOT_SPECIAL;
-//public static final int[] Modulus= {0xEB4A713,0x14EDDFF7,0x1D192EAF,0x14AAAC29,0xD5F06E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120};
-//public static final int MConst=0x1914C4E5;
-
-// BNT2 Curve Modulus
-//	public static final int MODTYPE=NOT_SPECIAL;
-//	public static final int[] Modulus= {0x1460A48B,0x596E15D,0x1C35947A,0x1F27C851,0x1D00081C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004};
-//	public static final int MConst=0x6505CDD;
-
-// START SPECIFY CURVE DETAILS HERE
-//*********************************************************************************
-// Original Curve25519
-// 	public static final int CURVETYPE=MONTGOMERY;
-//	public static final int CURVE_A =486662;
-//	public static final int[] CURVE_B = {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}; // not used
-//	public static final int[] CURVE_Order={0x1CF5D3ED,0x9318D2,0x1DE73596,0x1DF3BD45,0x14D,0x0,0x0,0x0,0x100000};
-//	public static final int[] CURVE_Gx ={0x9,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
-//	public static final int[] CURVE_Gy ={0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}; // not used
-
-
-// Ed25519 Curve
-//	public static final int CURVETYPE=EDWARDS;
-//	public static final int CURVE_A = -1;
-//	public static final int[] CURVE_B = {0x135978A3,0xF5A6E50,0x10762ADD,0x149A82,0x1E898007,0x3CBBBC,0x19CE331D,0x1DC56DFF,0x52036C};
-//	public static final int[] CURVE_Order={0x1CF5D3ED,0x9318D2,0x1DE73596,0x1DF3BD45,0x14D,0x0,0x0,0x0,0x100000};
-//	public static final int[] CURVE_Gx ={0xF25D51A,0xAB16B04,0x969ECB2,0x198EC12A,0xDC5C692,0x1118FEEB,0xFFB0293,0x1A79ADCA,0x216936};
-//	public static final int[] CURVE_Gy={0x6666658,0x13333333,0x19999999,0xCCCCCCC,0x6666666,0x13333333,0x19999999,0xCCCCCCC,0x666666};
-
-// WS25519 Curve
-//	public static final int CURVETYPE=WEIERSTRASS;
-//	public static final int CURVE_A = -3;
-//	public static final int[] CURVE_B = {0x28,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
-//	public static final int[] CURVE_Order = {0x1728ACA1,0x8E7230C,0x10E8DCDB,0x1C1FC966,0x5D5,0x0,0x0,0x0,0x800000};
-//	public static final int[] CURVE_Gx={0x14D8261F,0x23A9C3B,0x1E392613,0xE9D560D,0x19BD0F9A,0x1A9EF052,0xCFB499,0x4242BE1,0x67E3F5};
-//	public static final int[] CURVE_Gy={0x1DEEF38,0x1A31963F,0x4871D5,0x16572E70,0x1DEA014C,0x1AE6A722,0x165D7907,0x1903CD0B,0x36856};
-
-// NIST-256 Curve
-//	public static final int CURVETYPE=WEIERSTRASS;
-//	public static final int CURVE_A = -3;
-//	public static final int[] CURVE_B={0x7D2604B,0x1E71E1F1,0x14EC3D8E,0x1A0D6198,0x86BC651,0x1EAABB4C,0xF9ECFAE,0x1B154752,0x5AC635};
-//	public static final int[] CURVE_Order={0x1C632551,0x1DCE5617,0x5E7A13C,0xDF55B4E,0x1FFFFBCE,0x1FFFFFFF,0x3FFFF,0x1FE00000,0xFFFFFF};
-//	public static final int[] CURVE_Gx={0x1898C296,0x509CA2E,0x1ACCE83D,0x6FB025B,0x40F2770,0x1372B1D2,0x91FE2F3,0x1E5C2588,0x6B17D1};
-//	public static final int[] CURVE_Gy={0x17BF51F5,0x1DB20341,0xC57B3B2,0x1C66AED6,0x19E162BC,0x15A53E07,0x1E6E3B9F,0x1C5FC34F,0x4FE342};
-//
-// MF254 Modulus, Weierstrass Curve w-254-mont
-//public static final int CURVETYPE= 0;
-//public static final int CURVE_A = -3;
-//public static final int[] CURVE_B = {0x1FFFD08D,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3F80FF};
-//public static final int[] CURVE_Order={0xF8DF83F,0x1D20CE25,0x8DD701B,0x317D41B,0x1FFFFEB8,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3F80FF};
-//public static final int[] CURVE_Gx ={0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
-//public static final int[] CURVE_Gy ={0x190D4EBC,0xB2EF9BF,0x14464C6B,0xE71C7F0,0x18AEBDFB,0xD3ADEBB,0x18052B85,0x1A6765CA,0x140E3F};
-
-// MF254 Modulus, Edwards Curve ed-254-mont
-//public static final int CURVETYPE= 1;
-//public static final int CURVE_A = -1;
-//public static final int[] CURVE_B = {0x367B,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
-//public static final int[] CURVE_Order={0x46E98C7,0x179E9FF6,0x158BEC3A,0xA60D917,0x1FFFFEB9,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFE03F};
-//public static final int[] CURVE_Gx ={0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
-//public static final int[] CURVE_Gy ={0xF2701E5,0x29687ED,0xC84861F,0x535081C,0x3F4E363,0x6A811B,0xCD65474,0x121AD498,0x19F0E6};
-
-// MF254 Modulus, Montgomery Curve
-// 	public static final int CURVETYPE=MONTGOMERY;
-//	public static final int CURVE_A =-55790;
-//	public static final int[] CURVE_B = {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}; // not used
-//	public static final int[] CURVE_Order={0x46E98C7,0x179E9FF6,0x158BEC3A,0xA60D917,0x1FFFFEB9,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFE03F};
-//	public static final int[] CURVE_Gx ={0x3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
-//	public static final int[] CURVE_Gy ={0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}; // not used
-
-// MS255 Modulus, Weierstrass Curve
-//public static final int CURVETYPE= 0;
-//public static final int CURVE_A = -3;
-//public static final int[] CURVE_B = {0x1FFFAB46,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFFF};
-//public static final int[] CURVE_Order={0x1C594AEB,0x1C7D64C1,0x14ACF7EA,0x14705075,0x1FFFF864,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFFF};
-//public static final int[] CURVE_Gx ={0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
-//public static final int[] CURVE_Gy ={0x9CB44BA,0x199FFB3B,0x1F698345,0xD8F19BB,0x17D177DB,0x1FFCD97F,0xCE487A,0x181DB74F,0x6F7A6A};
-
-// MS255 Modulus, Edwards Curve
-//public static final int CURVETYPE= 1;
-//public static final int CURVE_A = -1;
-//public static final int[] CURVE_B = {0xEA97,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
-//public static final int[] CURVE_Order={0x436EB75,0x24E8F68,0x9A0CBAB,0x34F0BDB,0x1FFFFDCF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFF};
-//public static final int[] CURVE_Gx ={0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
-//public static final int[] CURVE_Gy ={0x108736A0,0x11512ADE,0x1116916E,0x29715DA,0x47E5529,0x66EC706,0x1517B095,0xA694F76,0x26CB78};
-
-// MS255 Modulus, Montgomery Curve
-// 	public static final int CURVETYPE=MONTGOMERY;
-//	public static final int CURVE_A =-240222;
-//	public static final int[] CURVE_B = {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}; // not used
-//	public static final int[] CURVE_Order={0x436EB75,0x24E8F68,0x9A0CBAB,0x34F0BDB,0x1FFFFDCF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFF};
-//	public static final int[] CURVE_Gx ={0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
-//	public static final int[] CURVE_Gy ={0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}; // not used
-
-// MS256, Weierstrass Curve
-//public static final int CURVETYPE= 0;
-//public static final int CURVE_A = -3;
-//public static final int[] CURVE_B = {0x25581,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
-//public static final int[] CURVE_Order={0x751A825,0x559014A,0x9971808,0x1904EBD4,0x1FFFFE43,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFFFFFF};
-//public static final int[] CURVE_Gx ={0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
-//public static final int[] CURVE_Gy ={0x2B56C77,0x1FA31836,0x253B042,0x185F26EB,0xDD6BD02,0x4B66777,0x1B5FF20B,0xA783C8C,0x696F18};
-
-// MS256, Edwards Curve
-//public static final int CURVETYPE= 1;
-//public static final int CURVE_A = -1;
-//public static final int[] CURVE_B = {0x3BEE,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
-//public static final int[] CURVE_Order={0x1122B4AD,0xDC27378,0x9AF1939,0x154AB5A1,0x1FFFFBE6,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3FFFFF};
-//public static final int[] CURVE_Gx ={0xD,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
-//public static final int[] CURVE_Gy ={0x131CADBA,0x3FB7DA9,0x134C0FDC,0x14DAC704,0x46BFBE2,0x1859CFD0,0x1B6E8F4C,0x3C5424E,0x7D0AB4};
-
-// MS256 Modulus, Montgomery Curve
-// 	public static final int CURVETYPE=MONTGOMERY;
-//	public static final int CURVE_A =-61370;
-//	public static final int[] CURVE_B = {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}; // not used
-//  public static final int[] CURVE_Order={0x1122B4AD,0xDC27378,0x9AF1939,0x154AB5A1,0x1FFFFBE6,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3FFFFF};
-//	public static final int[] CURVE_Gx ={0xb,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
-//	public static final int[] CURVE_Gy ={0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}; // not used
-
-// MF256 Modulus, Weierstrass Curve
-//public static final int CURVETYPE= 0;
-//public static final int CURVE_A = -3;
-//public static final int[] CURVE_B = {0x14E6A,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
-//public static final int[] CURVE_Order={0x79857EB,0x8862F0D,0x1941D2E7,0x2EA27CD,0x1FFFFFC5,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFFA7FF};
-//public static final int[] CURVE_Gx ={0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
-//public static final int[] CURVE_Gy ={0xB724D2A,0x3CAA61,0x5371984,0x128FD71B,0x1AE28956,0x1D13091E,0x339EEAE,0x10F7C301,0x20887C};
-
-// MF256, Edwards Curve
-//public static final int CURVETYPE= 1;
-//public static final int CURVE_A = -1;
-//public static final int[] CURVE_B = {0x350A,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
-//public static final int[] CURVE_Order={0x18EC7BAB,0x16C976F6,0x19CCF259,0x9775F70,0x1FFFFB15,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3FE9FF};
-//public static final int[] CURVE_Gx ={0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
-//public static final int[] CURVE_Gy ={0x12F3C908,0xF553917,0x1FA9A35F,0xBCC91B,0x1AACA0C,0x1779ED96,0x156BABAF,0x1F1F1989,0xDAD8D4};
-
-// MF256 Modulus, Montgomery Curve
-// 	public static final int CURVETYPE=MONTGOMERY;
-//	public static final int CURVE_A =-54314;
-//	public static final int[] CURVE_B = {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}; // not used
-//  public static final int[] CURVE_Order={0x18EC7BAB,0x16C976F6,0x19CCF259,0x9775F70,0x1FFFFB15,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3FE9FF};
-//	public static final int[] CURVE_Gx ={0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
-//	public static final int[] CURVE_Gy ={0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}; // not used
-
-// Brainpool
-//	public static final int CURVETYPE= 0;
-//	public static final int CURVE_A = -3;
-//	public static final int[] CURVE_B = {0x1EE92B04,0x172C080F,0xBD2495A,0x7D7895E,0x176B7BF9,0x13B99E85,0x1A93F99A,0x18861B09,0x662C61};
-//	public static final int[] CURVE_Order={0x174856A7,0xF07414,0x1869BDE4,0x12F5476A,0x18D718C3,0x5484EC1,0x6F0F998,0x1B743DD5,0xA9FB57};
-//	public static final int[] CURVE_Gx ={0xE1305F4,0xD0C8AB1,0xBEF0ADE,0x28588F5,0x16149AFA,0x9D91D32,0x1EDDCC88,0x79839FC,0xA3E8EB};
-//	public static final int[] CURVE_Gy ={0x1B25C9BE,0xD5F479A,0x1409C007,0x196DBC73,0x417E69B,0x1170A322,0x15B5FDEC,0x10468738,0x2D996C};
-
-// ANSSI
-//  public static final int CURVETYPE= 0;
-//  public static final int CURVE_A = -3;
-//  public static final int[] CURVE_B = {0x1B7BB73F,0x3AF6CB3,0xC68600C,0x181935C9,0xC00FDFE,0x1D3AA522,0x4C0352A,0x194A8515,0xEE353F};
-//  public static final int[] CURVE_Order={0x6D655E1,0x1FEEA2CE,0x14AFE507,0x18CFC281,0x435B53D,0x16F46721,0x163C4049,0x1181675A,0xF1FD17};
-//  public static final int[] CURVE_Gx ={0x198F5CFF,0x64BD16E,0x62DC059,0xFA5B95F,0x23958C2,0x1EA3A4EA,0x7ACC460,0x186AD827,0xB6B3D4};
-//  public static final int[] CURVE_Gy ={0x14062CFB,0x188AD0AA,0x19327860,0x3860FD1,0xEF8C270,0x18F879F6,0x12447E49,0x1EF91640,0x6142E0};
-
-// BNCX Curve
-
-	public static final int CURVETYPE=WEIERSTRASS;
-	public static final int CURVE_A = 0;
-	public static final int[] CURVE_B = {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
-	public static final int[] CURVE_Order={0x16EB1F6D,0x108E0531,0x1241B3AF,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000};
-	public static final int[] CURVE_Bnx={0x3C012B1,0x0,0x10,0x0,0x0,0x0,0x0,0x0,0x0};
-	public static final int[] CURVE_Cru={0x14235C97,0xF0498BC,0x1BE1D58C,0x1BBEC8E3,0x3F1440B,0x654,0x12000,0x0,0x0};
-	public static final int[] CURVE_Fra={0x15C80EA3,0x1EC8419A,0x1CFE0856,0xEE64DE2,0x11898686,0x5C55653,0x592BF86,0x5F4C740,0x135908};
-	public static final int[] CURVE_Frb={0x6534710,0x1468DDE0,0x551B018,0x10C78E4D,0x4E3ABBD,0x9ECE6DE,0x2A40371,0x1A0C46C5,0x10A6F7};
-	public static final int[] CURVE_Pxa={0x4D2EC74,0x428E777,0xF89C9B0,0x190B7F40,0x14BBB907,0x12807AE1,0x958D62C,0x58E0A76,0x19682D};
-	public static final int[] CURVE_Pxb={0xE29CFE1,0x1D2C7459,0x270C3D1,0x172F6184,0x19743F81,0x49BD474,0x192A8047,0x1D87C33E,0x1466B9};
-	public static final int[] CURVE_Pya={0xF0BE09F,0x7DFE75E,0x1FB06CC3,0x3667B08,0xE209636,0x110ABED7,0xE376078,0x1B2E4665,0xA79ED};
-	public static final int[] CURVE_Pyb={0x898EE9D,0xC825914,0x14BB7AFB,0xC9D4AD3,0x13461C28,0x122896C6,0x240D71B,0x73D9898,0x6160C};
-	public static final int[] CURVE_Gx ={0x1C1B55B2,0x13311F7A,0x24FB86F,0x1FADDC30,0x166D3243,0xFB23D31,0x836C2F7,0x10E05,0x240000};
-	public static final int[] CURVE_Gy ={0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
-	public static final int[][] CURVE_W={{0x162FEB83,0x2A31A48,0x100E0480,0x16,0x600,0x0,0x0,0x0,0x0},{0x7802561,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0}};
-	public static final int[][][] CURVE_SB={{{0x1DB010E4,0x2A31A48,0x100E04A0,0x16,0x600,0x0,0x0,0x0,0x0},{0x7802561,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x7802561,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0xBB33EA,0xDEAEAE9,0x233AF2F,0x1FADDC03,0x166D2643,0xFB23D31,0x836C2F7,0x10E05,0x240000}}};
-	public static final int[][] CURVE_WB={{0x167A84B0,0xE108C2,0x1004AC10,0x7,0x200,0x0,0x0,0x0,0x0},{0x1E220475,0x166FCCAD,0x129FE68D,0x1D29DB51,0x2A0DC07,0x438,0xC000,0x0,0x0},{0xF10B93,0x1B37E657,0x194FF34E,0x1E94EDA8,0x1506E03,0x21C,0x6000,0x0,0x0},{0x1DFAAA11,0xE108C2,0x1004AC30,0x7,0x200,0x0,0x0,0x0,0x0}};
-	public static final int[][][] CURVE_BB={{{0x132B0CBD,0x108E0531,0x1241B39F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000},{0x132B0CBC,0x108E0531,0x1241B39F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000},{0x132B0CBC,0x108E0531,0x1241B39F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000},{0x7802562,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x7802561,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0x132B0CBC,0x108E0531,0x1241B39F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000},{0x132B0CBD,0x108E0531,0x1241B39F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000},{0x132B0CBC,0x108E0531,0x1241B39F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000}},{{0x7802562,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0x7802561,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0x7802561,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0x7802561,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x3C012B2,0x0,0x10,0x0,0x0,0x0,0x0,0x0,0x0},{0xF004AC2,0x0,0x40,0x0,0x0,0x0,0x0,0x0,0x0},{0xF6AFA0A,0x108E0531,0x1241B38F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000},{0x3C012B2,0x0,0x10,0x0,0x0,0x0,0x0,0x0,0x0}}};
-
-	public static final boolean USE_GLV =true;
-	public static final boolean USE_GS_G2 =true;
-	public static final boolean USE_GS_GT =true;
-	public static final boolean GT_STRONG=true;
-
-// BNT2 Curve
-/*
-	public static final int CURVETYPE=WEIERSTRASS;
-	public static final int CURVE_A = 0;
-	public static final int[] CURVE_B = {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
-	public static final int[] CURVE_Order={0x11AA2BF5,0x1FDB8D28,0xDCE0CF5,0x1F1BC24F,0x1D00021C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004};
-	public static final int[] CURVE_Bnx={0x608205,0x1008,0x10,0x0,0x0,0x0,0x0,0x0,0x0};
-	public static final int[] CURVE_Cru={0x866BD33,0x1A813A22,0x591C3BE,0xAB6EE60,0x1ECF2367,0x361B0BD,0x12000,0x0,0x0};
-	public static final int[] CURVE_Fra={0x13AEF062,0x1593464B,0x10EF3924,0x198D3667,0x17F195BB,0xFB3FD1,0xADAF429,0x11A53D19,0x124E0B};
-	public static final int[] CURVE_Frb={0xB1B429,0x10039B12,0xB465B55,0x59A91EA,0x50E7261,0xF0C5DF3,0x1FDBE90F,0x1EA2E4D1,0x11B1F8};
-	public static final int[] CURVE_Pxa={0x1F40A3C8,0x166491CC,0x19845E12,0xB9B49D2,0x161706B3,0xBBD82B4,0x18C609E7,0x19F2D278,0x16FC17};
-	public static final int[] CURVE_Pxb={0x18549540,0x2ABD456,0x1D944184,0x16DEF7CD,0x1A95D17D,0x42B2C83,0x16427206,0x17AB2E,0x1EB5B5};
-	public static final int[] CURVE_Pya={0x14220513,0x3DF6628,0x39CDEC5,0x894F10C,0x135F1268,0x1D28DC1C,0xAAA7537,0x130EC284,0x1E8EE4};
-	public static final int[] CURVE_Pyb={0x177CE78E,0x1DC9947A,0x1BE95E07,0x1D6E8DC4,0x1FB8E27,0x1B549EDE,0xF6E8A75,0x19B75C67,0x23CEF4};
-	public static final int[] CURVE_Gx ={0x1460A48A,0x596E15D,0x1C35947A,0x1F27C851,0x1D00081C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004};
-	public static final int[] CURVE_Gy ={0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
-	public static final int[][] CURVE_W={{0x1347083,0x5BB1415,0xE678744,0xC0602,0x600,0x0,0x0,0x0,0x0},{0xC10409,0x2010,0x20,0x0,0x0,0x0,0x0,0x0,0x0}};
-	public static final int[][][] CURVE_SB={{{0x1F5748C,0x5BB3425,0xE678764,0xC0602,0x600,0x0,0x0,0x0,0x0},{0xC10409,0x2010,0x20,0x0,0x0,0x0,0x0,0x0,0x0}},{{0xC10409,0x2010,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0x1075BB72,0x1A207913,0x1F6685B1,0x1F0FBC4C,0x1CFFFC1C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004}}};
-	public static final int[][] CURVE_WB={{0xA70A224,0xC9396A4,0x1A228251,0x40200,0x200,0x0,0x0,0x0,0x0},{0x1030EF19,0xAD2B967,0xD50DC87,0x72CA2EC,0x148A1B9A,0x241207E,0xC000,0x0,0x0},{0x1848B88F,0x156964B7,0x6A86E4B,0x3965176,0xA450DCD,0x120903F,0x6000,0x0,0x0},{0xB31A62D,0xC93B6B4,0x1A228271,0x40200,0x200,0x0,0x0,0x0,0x0}};
-	public static final int[][][] CURVE_BB={{{0x1149A9F1,0x1FDB7D20,0xDCE0CE5,0x1F1BC24F,0x1D00021C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004},{0x1149A9F0,0x1FDB7D20,0xDCE0CE5,0x1F1BC24F,0x1D00021C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004},{0x1149A9F0,0x1FDB7D20,0xDCE0CE5,0x1F1BC24F,0x1D00021C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004},{0xC1040A,0x2010,0x20,0x0,0x0,0x0,0x0,0x0,0x0}},{{0xC10409,0x2010,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0x1149A9F0,0x1FDB7D20,0xDCE0CE5,0x1F1BC24F,0x1D00021C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004},{0x1149A9F1,0x1FDB7D20,0xDCE0CE5,0x1F1BC24F,0x1D00021C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004},{0x1149A9F0,0x1FDB7D20,0xDCE0CE5,0x1F1BC24F,0x1D00021C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004}},{{0xC1040A,0x2010,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0xC10409,0x2010,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0xC10409,0x2010,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0xC10409,0x2010,0x20,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x608206,0x1008,0x10,0x0,0x0,0x0,0x0,0x0,0x0},{0x1820812,0x4020,0x40,0x0,0x0,0x0,0x0,0x0,0x0},{0x10E927EA,0x1FDB6D18,0xDCE0CD5,0x1F1BC24F,0x1D00021C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004},{0x608206,0x1008,0x10,0x0,0x0,0x0,0x0,0x0,0x0}}};
-*/
-
-// BN Curve
-/*
-public static final int CURVETYPE=WEIERSTRASS;
-public static final int CURVE_A = 0;
-public static final int[] CURVE_B = {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
-public static final int[] CURVE_Order={0xD,0x8000000,0x428,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364};
-public static final int[] CURVE_Bnx={0x1,0x4000000,0x10,0x0,0x0,0x0,0x0,0x0,0x0};
-public static final int[] CURVE_Cru={0x7,0xC000000,0x1B3,0x12000000,0x2490,0x11200000,0x126CD,0x0,0x0};
-public static final int[] CURVE_Fra={0xF2A6DE9,0xBEF3603,0xFDDF0B8,0x12E9249A,0x953F850,0xDA85423,0x1232D926,0x32425CF,0x1B3776};
-public static final int[] CURVE_Frb={0x10D5922A,0xC10C9FC,0x10221431,0xF16DB65,0x16AC8DC1,0x1917ABDC,0xDD40FAA,0xD23DA30,0x9EBEE};
-public static final int[] CURVE_Pxa={0x15FD0CB4,0x1D5963C9,0x1F315F0A,0xBC633C9,0x1763B05A,0x1B927B6F,0x1FA8CD7E,0x1A9EABD4,0x95B04};
-public static final int[] CURVE_Pxb={0x10962455,0x503E83C,0x9EA978E,0x1B0D7C7A,0x147F39D6,0x1FC4F02B,0x1ED2750A,0x14F81068,0x5D4D8};
-public static final int[] CURVE_Pya={0x1A08A46C,0xD6E7343,0x290647E,0x105661D3,0xB1F1690,0xE261BC2,0x4FE85B4,0x17E4BCA6,0xABF2A};
-public static final int[] CURVE_Pyb={0x5F306EC,0x16FC46A0,0x1744E839,0x9040ED5,0x19D6A5C0,0x138F23C0,0xAF6CE18,0x10FCCF3B,0x18769A};
-public static final int[] CURVE_Gx ={0x12,0x18000000,0x4E9,0x2000000,0x8612,0x6C00000,0x6E8D1,0x10480000,0x252364};
-public static final int[] CURVE_Gy ={0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
-public static final int[][] CURVE_W={{0x3,0x0,0x81,0x3000000,0x618,0x0,0x0,0x0,0x0},{0x1,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0}};
-public static final int[][][] CURVE_SB={{{0x4,0x8000000,0xA1,0x3000000,0x618,0x0,0x0,0x0,0x0},{0x1,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x1,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0xA,0x8000000,0x3A7,0x1C000000,0x79E1,0x6C00000,0x6E8D1,0x10480000,0x252364}}};
-public static final int[][] CURVE_WB={{0x0,0x4000000,0x10,0x1000000,0x208,0x0,0x0,0x0,0x0},{0x5,0x14000000,0x152,0xE000000,0x1C70,0xC00000,0xC489,0x0,0x0},{0x3,0xC000000,0xB1,0x7000000,0xE38,0x10600000,0x6244,0x0,0x0},{0x1,0xC000000,0x30,0x1000000,0x208,0x0,0x0,0x0,0x0}};
-public static final int[][][] CURVE_BB={{{0xD,0x4000000,0x418,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364},{0xC,0x4000000,0x418,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364},{0xC,0x4000000,0x418,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364},{0x2,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x1,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0xC,0x4000000,0x418,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364},{0xD,0x4000000,0x418,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364},{0xC,0x4000000,0x418,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364}},{{0x2,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x2,0x4000000,0x10,0x0,0x0,0x0,0x0,0x0,0x0},{0x2,0x10000000,0x40,0x0,0x0,0x0,0x0,0x0,0x0},{0xA,0x0,0x408,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364},{0x2,0x4000000,0x10,0x0,0x0,0x0,0x0,0x0,0x0}}};
-
-*/
-
-// BNT Curve
-/*
-public static final int CURVETYPE=WEIERSTRASS;
-public static final int CURVE_A = 0;
-public static final int[] CURVE_B = {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
-public static final int[] CURVE_Order={0xD30210D,0x13ABBBF4,0xCB2CD8E,0x11A86925,0xD5F00E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120};
-public static final int[] CURVE_Bnx={0x4081,0x40300,0x10,0x0,0x0,0x0,0x0,0x0,0x0};
-public static final int[] CURVE_Cru={0xB4FCD87,0xF5A9EAD,0xEAC47EB,0x19054BE5,0x104C9764,0x18A3B28A,0x12006,0x0,0x0};
-public static final int[] CURVE_Fra={0xDC80022,0xFAE8A75,0x1EB338D6,0x189209AD,0x13211BE6,0x4F8C850,0x10E53D94,0x12593778,0x1328A2};
-public static final int[] CURVE_Frb={0xECA6F1,0x53F5582,0x1E65F5D9,0x1C18A27B,0x1A3DEB01,0x10A2832B,0x1456AA9A,0x9136B67,0x10D87E};
-public static final int[] CURVE_Pxa={0x88E65BB,0x144C3F11,0xA98C4EF,0x18015A39,0x1548B7CC,0xA992820,0xE7AF301,0x19A09826,0x14483F};
-public static final int[] CURVE_Pxb={0x8DBE2C0,0x133C4440,0x78D214E,0xAFFC3F0,0x51B57B9,0x285318D,0xC0B68FF,0x166709D8,0x87F46};
-public static final int[] CURVE_Pya={0x20CA1D,0x101623F,0xE67CDB,0x19682CFD,0x19F72C94,0x14E372A1,0xF5D28B1,0x13820561,0x14E8C2};
-public static final int[] CURVE_Pyb={0x116628F2,0x1EC21BE3,0xF2DF71A,0x144FC2CF,0x172681D0,0xC54163A,0xF47B7B0,0x148C48A9,0x17AFE2};
-public static final int[] CURVE_Gx ={0xEB4A712,0x14EDDFF7,0x1D192EAF,0x14AAAC29,0xD5F06E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120};
-public static final int[] CURVE_Gy ={0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
-public static final int[][] CURVE_W={{0x1838403,0x1321803,0x106660E1,0x3024304,0x600,0x0,0x0,0x0,0x0},{0x8101,0x80600,0x20,0x0,0x0,0x0,0x0,0x0,0x0}};
-public static final int[][][] CURVE_SB={{{0x1840504,0x13A1E03,0x10666101,0x3024304,0x600,0x0,0x0,0x0,0x0},{0x8101,0x80600,0x20,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x8101,0x80600,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0xBAC9D0A,0x1279A3F1,0x1C4C6CAD,0xEA62620,0xD5EFAE8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120}}};
-public static final int[][] CURVE_WB={{0x80C080,0xB0A0301,0x10222030,0x100C101,0x200,0x0,0x0,0x0,0x0},{0x88C4A85,0x15A9C820,0x14B71B0D,0x1D5A5F46,0x158868ED,0x106D21B1,0xC004,0x0,0x0},{0x4464583,0x1AD6E590,0xA5B8D8E,0x1EAD2FA3,0x1AC43476,0x83690D8,0x6002,0x0,0x0},{0x814181,0xB120901,0x10222050,0x100C101,0x200,0x0,0x0,0x0,0x0}};
-public static final int[][][] CURVE_BB={{{0xD2FE08D,0x13A7B8F4,0xCB2CD7E,0x11A86925,0xD5F00E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120},{0xD2FE08C,0x13A7B8F4,0xCB2CD7E,0x11A86925,0xD5F00E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120},{0xD2FE08C,0x13A7B8F4,0xCB2CD7E,0x11A86925,0xD5F00E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120},{0x8102,0x80600,0x20,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x8101,0x80600,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0xD2FE08C,0x13A7B8F4,0xCB2CD7E,0x11A86925,0xD5F00E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120},{0xD2FE08D,0x13A7B8F4,0xCB2CD7E,0x11A86925,0xD5F00E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120},{0xD2FE08C,0x13A7B8F4,0xCB2CD7E,0x11A86925,0xD5F00E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120}},{{0x8102,0x80600,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0x8101,0x80600,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0x8101,0x80600,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0x8101,0x80600,0x20,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x4082,0x40300,0x10,0x0,0x0,0x0,0x0,0x0,0x0},{0x10202,0x100C00,0x40,0x0,0x0,0x0,0x0,0x0,0x0},{0xD2FA00A,0x13A3B5F4,0xCB2CD6E,0x11A86925,0xD5F00E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120},{0x4082,0x40300,0x10,0x0,0x0,0x0,0x0,0x0,0x0}}};
-
-*/
-	//public static boolean debug=false;
-
-}
diff --git a/java/RSA.java b/java/RSA.java
deleted file mode 100755
index 53549c5..0000000
--- a/java/RSA.java
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
-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.
-*/
-
-/* RSA API high-level functions  */
-
-final class rsa_private_key
-{
-    public FF p,q,dp,dq,c;
-
-	public rsa_private_key(int n)
-	{
-		p=new FF(n);
-		q=new FF(n);
-		dp=new FF(n);
-		dq=new FF(n);
-		c=new FF(n);
-	}
-}
-
-final class rsa_public_key
-{
-    public int e;
-    public FF n;
-
-	public rsa_public_key(int m)
-	{
-		e=0;
-		n=new FF(m);
-	}
-}
-
-public final class RSA {
-
-	public static final int RFS=ROM.MODBYTES*ROM.FFLEN;
-
-/* generate an RSA key pair */
-
-	public static void KEY_PAIR(RAND rng,int e,rsa_private_key PRIV,rsa_public_key PUB)
-	{ /* IEEE1363 A16.11/A16.12 more or less */
-
-		int n=PUB.n.getlen()/2;
-		FF t = new FF(n);
-		FF p1=new FF(n);
-		FF q1=new FF(n);
-
-		for (;;)
-		{
-
-			PRIV.p.random(rng);
-			while (PRIV.p.lastbits(2)!=3) PRIV.p.inc(1);
-			while (!FF.prime(PRIV.p,rng)) PRIV.p.inc(4);
-
-			p1.copy(PRIV.p);
-			p1.dec(1);
-
-			if (p1.cfactor(e)) continue;
-			break;
-		}
-
-		for (;;)
-		{
-			PRIV.q.random(rng);
-			while (PRIV.q.lastbits(2)!=3) PRIV.q.inc(1);
-			while (!FF.prime(PRIV.q,rng)) PRIV.q.inc(4);
-
-			q1.copy(PRIV.q);
-			q1.dec(1);
-
-			if (q1.cfactor(e)) continue;
-
-			break;
-		}
-
-		PUB.n=FF.mul(PRIV.p,PRIV.q);
-		PUB.e=e;
-
-		t.copy(p1);
-		t.shr();
-		PRIV.dp.set(e);
-		PRIV.dp.invmodp(t);
-		if (PRIV.dp.parity()==0) PRIV.dp.add(t);
-		PRIV.dp.norm();
-
-		t.copy(q1);
-		t.shr();
-		PRIV.dq.set(e);
-		PRIV.dq.invmodp(t);
-		if (PRIV.dq.parity()==0) PRIV.dq.add(t);
-		PRIV.dq.norm();
-
-		PRIV.c.copy(PRIV.p);
-		PRIV.c.invmodp(PRIV.q);
-
-		return;
-	}
-
-/* Mask Generation Function */
-
-	public static void MGF1(byte[] Z,int olen,byte[] K)
-	{
-		HASH H=new HASH();
-		int hlen=HASH.len;
-		byte[] B=new byte[hlen];
-
-		int counter,cthreshold,k=0;
-		for (int i=0;i<K.length;i++) K[i]=0;
-
-		cthreshold=olen/hlen; if (olen%hlen!=0) cthreshold++;
-		for (counter=0;counter<cthreshold;counter++)
-		{
-			H.process_array(Z); H.process_num(counter);
-			B=H.hash();
-
-			if (k+hlen>olen) for (int i=0;i<olen%hlen;i++) K[k++]=B[i];
-			else for (int i=0;i<hlen;i++) K[k++]=B[i];
-		}
-	}
-
-	public static void printBinary(byte[] array)
-	{
-		int i;
-		for (i=0;i<array.length;i++)
-		{
-			System.out.printf("%02x", array[i]);
-		}
-		System.out.println();
-	}
-
-	/* OAEP Message Encoding for Encryption */
-	public static byte[] OAEP_ENCODE(byte[] m,RAND rng,byte[] p)
-	{
-		int i,slen,olen=RFS-1;
-		int mlen=m.length;
-		int hlen,seedlen;
-		byte[] f=new byte[RFS];
-
-		HASH H=new HASH();
-		hlen=HASH.len;
-		byte[] SEED=new byte[hlen];
-		seedlen=hlen;
-		if (mlen>olen-hlen-seedlen-1) return new byte[0];
-
-		byte[] DBMASK=new byte[olen-seedlen];
-
-		if (p!=null) H.process_array(p);
-		byte[] h=H.hash();
-		for (i=0;i<hlen;i++) f[i]=h[i];
-
-		slen=olen-mlen-hlen-seedlen-1;
-
-		for (i=0;i<slen;i++) f[hlen+i]=0;
-		f[hlen+slen]=1;
-		for (i=0;i<mlen;i++) f[hlen+slen+1+i]=m[i];
-
-		for (i=0;i<seedlen;i++) SEED[i]=(byte)rng.getByte();
-		MGF1(SEED,olen-seedlen,DBMASK);
-
-		for (i=0;i<olen-seedlen;i++) DBMASK[i]^=f[i];
-		MGF1(DBMASK,seedlen,f);
-
-		for (i=0;i<seedlen;i++) f[i]^=SEED[i];
-
-		for (i=0;i<olen-seedlen;i++) f[i+seedlen]=DBMASK[i];
-
-		/* pad to length RFS */
-		int d=1;
-		for (i=RFS-1;i>=d;i--)
-			f[i]=f[i-d];
-		for (i=d-1;i>=0;i--)
-			f[i]=0;
-
-		return f;
-	}
-
-	/* OAEP Message Decoding for Decryption */
-	public static byte[] OAEP_DECODE(byte[] p,byte[] f)
-	{
-		int x,t;
-		boolean comp;
-		int i,k,olen=RFS-1;
-		int hlen,seedlen;
-
-		HASH H=new HASH();
-		hlen=HASH.len;
-		byte[] SEED=new byte[hlen];
-		seedlen=hlen;
-		byte[] CHASH=new byte[hlen];
-
-		if (olen<seedlen+hlen+1) return new byte[0];
-		byte[] DBMASK=new byte[olen-seedlen];
-		for (i=0;i<olen-seedlen;i++) DBMASK[i]=0;
-
-		if (f.length<RFS)
-		{
-			int d=RFS-f.length;
-			for (i=RFS-1;i>=d;i--)
-				f[i]=f[i-d];
-			for (i=d-1;i>=0;i--)
-				f[i]=0;
-
-		}
-
-		if (p!=null) H.process_array(p);
-		byte[] h=H.hash();
-		for (i=0;i<hlen;i++) CHASH[i]=h[i];
-
-		x=f[0];
-
-		for (i=seedlen;i<olen;i++)
-			DBMASK[i-seedlen]=f[i+1];
-
-		MGF1(DBMASK,seedlen,SEED);
-		for (i=0;i<seedlen;i++) SEED[i]^=f[i+1];
-		MGF1(SEED,olen-seedlen,f);
-		for (i=0;i<olen-seedlen;i++) DBMASK[i]^=f[i];
-
-		comp=true;
-		for (i=0;i<hlen;i++)
-		{
-			if (CHASH[i]!=DBMASK[i]) comp=false;
-		}
-
-		for (i=0;i<olen-seedlen-hlen;i++)
-			DBMASK[i]=DBMASK[i+hlen];
-
-		for (i=0;i<hlen;i++)
-			SEED[i]=CHASH[i]=0;
-
-		for (k=0;;k++)
-		{
-			if (k>=olen-seedlen-hlen) return new byte[0];
-			if (DBMASK[k]!=0) break;
-		}
-
-		t=DBMASK[k];
-		if (!comp || x!=0 || t!=0x01)
-		{
-			for (i=0;i<olen-seedlen;i++) DBMASK[i]=0;
-			return new byte[0];
-		}
-
-		byte[] r=new byte[olen-seedlen-hlen-k-1];
-
-		for (i=0;i<olen-seedlen-hlen-k-1;i++)
-			r[i]=DBMASK[i+k+1];
-
-		for (i=0;i<olen-seedlen;i++) DBMASK[i]=0;
-
-		return r;
-	}
-
-	/* destroy the Private Key structure */
-	public static void PRIVATE_KEY_KILL(rsa_private_key PRIV)
-	{
-		PRIV.p.zero();
-		PRIV.q.zero();
-		PRIV.dp.zero();
-		PRIV.dq.zero();
-		PRIV.c.zero();
-	}
-
-	/* RSA encryption with the public key */
-	public static void ENCRYPT(rsa_public_key PUB,byte[] F,byte[] G)
-	{
-		int n=PUB.n.getlen();
-		FF f=new FF(n);
-
-		FF.fromBytes(f,F);
-		f.power(PUB.e,PUB.n);
-		f.toBytes(G);
-	}
-
-	/* RSA decryption with the private key */
-	public static void DECRYPT(rsa_private_key PRIV,byte[] G,byte[] F)
-	{
-		int n=PRIV.p.getlen();
-		FF g=new FF(2*n);
-
-		FF.fromBytes(g,G);
-		FF jp=g.dmod(PRIV.p);
-		FF jq=g.dmod(PRIV.q);
-
-		jp.skpow(PRIV.dp,PRIV.p);
-		jq.skpow(PRIV.dq,PRIV.q);
-
-		g.zero();
-		g.dscopy(jp);
-		jp.mod(PRIV.q);
-		if (FF.comp(jp,jq)>0) jq.add(PRIV.q);
-		jq.sub(jp);
-		jq.norm();
-
-		FF t=FF.mul(PRIV.c,jq);
-		jq=t.dmod(PRIV.q);
-
-		t=FF.mul(jq,PRIV.p);
-		g.add(t);
-		g.norm();
-
-		g.toBytes(F);
-	}
-}
diff --git a/java/TestECDH.java b/java/TestECDH.java
deleted file mode 100755
index 3027f12..0000000
--- a/java/TestECDH.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
-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.
-*/
-
-/* test driver and function exerciser for ECDH/ECIES/ECDSA API Functions */
-
-public class TestECDH
-{
-	public static void printBinary(byte[] array)
-	{
-		int i;
-		for (i=0;i<array.length;i++)
-		{
-			System.out.printf("%02x", array[i]);
-		}
-		System.out.println();
-	}
-
-	public static void main(String[] args)
-	{
-		int i,j=0,res;
-		int result;
-		String pp=new String("M0ng00se");
-
-		int EGS=ECDH.EGS;
-		int EFS=ECDH.EFS;
-		int EAS=AES.KS;
-
-		byte[] S1=new byte[EGS];
-		byte[] W0=new byte[2*EFS+1];
-		byte[] W1=new byte[2*EFS+1];
-		byte[] Z0=new byte[EFS];
-		byte[] Z1=new byte[EFS];
-		byte[] RAW=new byte[100];
-		byte[] SALT=new byte[8];
-		byte[] P1=new byte[3];
-		byte[] P2=new byte[4];
-		byte[] V=new byte[2*EFS+1];
-		byte[] M=new byte[17];
-		byte[] T=new byte[12];
-		byte[] CS=new byte[EGS];
-		byte[] DS=new byte[EGS];
-
-		RAND rng=new RAND();
-
-		rng.clean();
-		for (i=0;i<100;i++) RAW[i]=(byte)(i);
-
-		rng.seed(100,RAW);
-
-//for (j=0;j<100;j++)
-//{
-
-		for (i=0;i<8;i++) SALT[i]=(byte)(i+1);  // set Salt
-
-		System.out.println("Alice's Passphrase= "+pp);
-		byte[] PW=pp.getBytes();
-
-/* private key S0 of size EGS bytes derived from Password and Salt */
-
-		byte[] S0=ECDH.PBKDF2(PW,SALT,1000,EGS);
-
-		System.out.print("Alice's private key= 0x");
-		printBinary(S0);
-
-/* Generate Key pair S/W */
-		ECDH.KEY_PAIR_GENERATE(null,S0,W0);
-
-		System.out.print("Alice's public key= 0x");
-		printBinary(W0);
-
-		res=ECDH.PUBLIC_KEY_VALIDATE(true,W0);
-		if (res!=0)
-		{
-			System.out.println("ECP Public Key is invalid!\n");
-			return;
-		}
-/* Random private key for other party */
-		ECDH.KEY_PAIR_GENERATE(rng,S1,W1);
-
-		System.out.print("Servers private key= 0x");
-		printBinary(S1);
-
-		System.out.print("Servers public key= 0x");
-		printBinary(W1);
-
-
-		res=ECDH.PUBLIC_KEY_VALIDATE(true,W1);
-		if (res!=0)
-		{
-			System.out.print("ECP Public Key is invalid!\n");
-			return;
-		}
-
-/* Calculate common key using DH - IEEE 1363 method */
-
-		ECDH.ECPSVDP_DH(S0,W1,Z0);
-		ECDH.ECPSVDP_DH(S1,W0,Z1);
-
-		boolean same=true;
-		for (i=0;i<EFS;i++)
-			if (Z0[i]!=Z1[i]) same=false;
-
-		if (!same)
-		{
-			System.out.println("*** ECPSVDP-DH Failed");
-			return;
-		}
-
-		byte[] KEY=ECDH.KDF1(Z0,EAS);
-
-		System.out.print("Alice's DH Key=  0x"); printBinary(KEY);
-		System.out.print("Servers DH Key=  0x"); printBinary(KEY);
-
-		System.out.println("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=0;i<=16;i++) M[i]=(byte)i;
-
-		byte[] C=ECDH.ECIES_ENCRYPT(P1,P2,rng,W1,M,V,T);
-
-		System.out.println("Ciphertext= ");
-		System.out.print("V= 0x"); printBinary(V);
-		System.out.print("C= 0x"); printBinary(C);
-		System.out.print("T= 0x"); printBinary(T);
-
-
-		M=ECDH.ECIES_DECRYPT(P1,P2,V,C,T,S1);
-		if (M.length==0)
-		{
-			System.out.println("*** ECIES Decryption Failed\n");
-			return;
-		}
-		else System.out.println("Decryption succeeded");
-
-		System.out.print("Message is 0x"); printBinary(M);
-
-		System.out.println("Testing ECDSA");
-
-		if (ECDH.ECPSP_DSA(rng,S0,M,CS,DS)!=0)
-		{
-			System.out.println("***ECDSA Signature Failed");
-			return;
-		}
-		System.out.println("Signature= ");
-		System.out.print("C= 0x"); printBinary(CS);
-		System.out.print("D= 0x"); printBinary(DS);
-
-		if (ECDH.ECPVP_DSA(W0,M,CS,DS)!=0)
-		{
-			System.out.println("***ECDSA Verification Failed");
-			return;
-		}
-		else System.out.println("ECDSA Signature/Verification succeeded "+j);
-//}
-//System.out.println("Test Completed Successfully");
-	}
-}
diff --git a/java/TestECM.java b/java/TestECM.java
deleted file mode 100755
index b0a07a1..0000000
--- a/java/TestECM.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
-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.
-*/
-
-/* test driver and function exerciser for ECDH API Function only - for use with Montgomery curves */
-
-public class TestECM
-{
-	public static void printBinary(byte[] array)
-	{
-		int i;
-		for (i=0;i<array.length;i++)
-		{
-			System.out.printf("%02x", array[i]);
-		}
-		System.out.println();
-	}
-
-	public static void main(String[] args)
-	{
-		int i,j=0,res;
-		int result;
-		String pp=new String("M0ng00se");
-
-		int EGS=ECDH.EGS;
-		int EFS=ECDH.EFS;
-		int EAS=AES.KS;
-
-		byte[] S1=new byte[EGS];
-		byte[] W0=new byte[2*EFS+1];
-		byte[] W1=new byte[2*EFS+1];
-		byte[] Z0=new byte[EFS];
-		byte[] Z1=new byte[EFS];
-		byte[] RAW=new byte[100];
-		byte[] SALT=new byte[8];
-
-		RAND rng=new RAND();
-
-		rng.clean();
-		for (i=0;i<100;i++) RAW[i]=(byte)(i);
-
-		rng.seed(100,RAW);
-
-//for (j=0;j<100;j++)
-//{
-
-		for (i=0;i<8;i++) SALT[i]=(byte)(i+1);  // set Salt
-
-		System.out.println("Alice's Passphrase= "+pp);
-		byte[] PW=pp.getBytes();
-
-/* private key S0 of size EGS bytes derived from Password and Salt */
-
-		byte[] S0=ECDH.PBKDF2(PW,SALT,1000,EGS);
-
-		System.out.print("Alice's private key= 0x");
-		printBinary(S0);
-
-/* Generate Key pair S/W */
-		ECDH.KEY_PAIR_GENERATE(null,S0,W0);
-
-		System.out.print("Alice's public key= 0x");
-		printBinary(W0);
-
-		res=ECDH.PUBLIC_KEY_VALIDATE(true,W0);
-		if (res!=0)
-		{
-			System.out.println("Alice's public Key is invalid!\n");
-			return;
-		}
-/* Random private key for other party */
-		ECDH.KEY_PAIR_GENERATE(rng,S1,W1);
-
-		System.out.print("Servers private key= 0x");
-		printBinary(S1);
-
-		System.out.print("Servers public key= 0x");
-		printBinary(W1);
-
-
-		res=ECDH.PUBLIC_KEY_VALIDATE(true,W1);
-		if (res!=0)
-		{
-			System.out.print("Server's public Key is invalid!\n");
-			return;
-		}
-
-/* Calculate common key using DH - IEEE 1363 method */
-
-		ECDH.ECPSVDP_DH(S0,W1,Z0);
-		ECDH.ECPSVDP_DH(S1,W0,Z1);
-
-		boolean same=true;
-		for (i=0;i<EFS;i++)
-			if (Z0[i]!=Z1[i]) same=false;
-
-		if (!same)
-		{
-			System.out.println("*** ECPSVDP-DH Failed");
-			return;
-		}
-
-		byte[] KEY=ECDH.KDF1(Z0,EAS);
-
-		System.out.print("Alice's DH Key=  0x"); printBinary(KEY);
-		System.out.print("Servers DH Key=  0x"); printBinary(KEY);
-
-//}
-//System.out.println("Test Completed Successfully");
-	}
-}
diff --git a/java/TestMPIN.java b/java/TestMPIN.java
deleted file mode 100755
index 4d4090c..0000000
--- a/java/TestMPIN.java
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
-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.
-*/
-
-/* test driver and function exerciser for MPIN API Functions */
-
-import java.util.Date;
-import java.util.Scanner;
-
-public class TestMPIN
-{
-	static boolean PERMITS=true;
-	static boolean PINERROR=true;
-	static boolean FULL=false;
-	static boolean SINGLE_PASS=false;
-
-	static void printBinary(byte[] array)
-	{
-		int i;
-		for (i=0;i<array.length;i++)
-		{
-			System.out.printf("%02x", array[i]);
-		}
-		System.out.println();
-	}
-
-	public static void main(String[] args) {
-		RAND rng=new RAND();
-		byte[] raw=new byte[100];
-		for (int i=0;i<100;i++) raw[i]=(byte)(i+1);
-		rng.seed(100,raw);
-
-		int EGS=MPIN.EGS;
-		int EFS=MPIN.EFS;
-		int G1S=2*EFS+1; /* Group 1 Size */
-		int G2S=4*EFS; /* Group 2 Size */
-		int EAS=16;
-
-		byte[] S=new byte[EGS];
-		byte[] SST = new byte[G2S];
-		byte[] TOKEN = new byte[G1S];
-		byte[] PERMIT = new byte[G1S];
-		byte[] SEC = new byte[G1S];
-		byte[] xID = new byte[G1S];
-		byte[] xCID = new byte[G1S];
-		byte[] X= new byte[EGS];
-		byte[] Y= new byte[EGS];
-		byte[] E=new byte[12*EFS];
-		byte[] F=new byte[12*EFS];
-		byte[] HID=new byte[G1S];
-		byte[] HTID=new byte[G1S];
-
-		byte[] G1=new byte[12*EFS];
-		byte[] G2=new byte[12*EFS];
-		byte[] R=new byte[EGS];
-		byte[] Z=new byte[G1S];
-		byte[] W=new byte[EGS];
-		byte[] T=new byte[G1S];
-		byte[] CK=new byte[EAS];
-		byte[] SK=new byte[EAS];
-
-/* Trusted Authority set-up */
-
-		MPIN.RANDOM_GENERATE(rng,S);
-		System.out.print("Master Secret s: 0x");  printBinary(S);
-
- /* Create Client Identity */
- 		String IDstr = "testUser@miracl.com";
-		byte[] CLIENT_ID = IDstr.getBytes();
-
-		byte[] HCID=MPIN.HASH_ID(CLIENT_ID);  /* Either Client or TA calculates Hash(ID) - you decide! */
-
-		System.out.print("Client ID= "); printBinary(CLIENT_ID);
-
-/* Client and Server are issued secrets by DTA */
-		MPIN.GET_SERVER_SECRET(S,SST);
-		System.out.print("Server Secret SS: 0x");  printBinary(SST);
-
-		MPIN.GET_CLIENT_SECRET(S,HCID,TOKEN);
-		System.out.print("Client Secret CS: 0x");
-		printBinary(TOKEN);
-
-/* Client extracts PIN from secret to create Token */
-		int pin=1234;
-		System.out.println("Client extracts PIN= "+pin);
-		int rtn=MPIN.EXTRACT_PIN(CLIENT_ID,pin,TOKEN);
-		if (rtn != 0)
-			System.out.println("FAILURE: EXTRACT_PIN rtn: " + rtn);
-
-		System.out.print("Client Token TK: 0x");
-		printBinary(TOKEN);
-
-		if (FULL)
-		{
-			MPIN.PRECOMPUTE(TOKEN,HCID,G1,G2);
-		}
-		int date;
-		if (PERMITS)
-		{
-			date=MPIN.today();
-/* Client gets "Time Token" permit from DTA */
-			MPIN.GET_CLIENT_PERMIT(date,S,HCID,PERMIT);
-			System.out.print("Time Permit TP: 0x");  printBinary(PERMIT);
-
-/* This encoding makes Time permit look random - Elligator squared */
-			MPIN.ENCODING(rng,PERMIT);
-			System.out.print("Encoded Time Permit TP: 0x");  printBinary(PERMIT);
-			MPIN.DECODING(PERMIT);
-			System.out.print("Decoded Time Permit TP: 0x");  printBinary(PERMIT);
-		}
-		else date=0;
-
-		System.out.print("\nPIN= ");
-		Scanner scan=new Scanner(System.in);
-		pin=scan.nextInt();
-
-/* 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.
-
-
-*/
-
-		byte[] pxID=xID;
-		byte[] pxCID=xCID;
-		byte[] pHID=HID;
-		byte[] pHTID=HTID;
-		byte[] pE=E;
-		byte[] pF=F;
-		byte[] pPERMIT=PERMIT;
-		byte[] prHID;
-
-		if (date!=0)
-		{
-
-			prHID=pHTID;
-			if (!PINERROR)
-			{
-				pxID=null;
-				pHID=null;
-			}
-		}
-		else
-		{
-			prHID=pHID;
-			pPERMIT=null;
-			pxCID=null;
-			pHTID=null;
-		}
-		if (!PINERROR)
-		{
-			pE=null;
-			pF=null;
-		}
-
-                if (SINGLE_PASS)
-		{
-  		  System.out.println("MPIN Single Pass");
-                  int timeValue = MPIN.GET_TIME();
-                  rtn=MPIN.CLIENT(date,CLIENT_ID,rng,X,pin,TOKEN,SEC,pxID,pxCID,pPERMIT,timeValue,Y);
-  		  if (rtn != 0)
-  		    System.out.println("FAILURE: CLIENT rtn: " + rtn);
-
-                  if (FULL)
-		  {
-                    HCID=MPIN.HASH_ID(CLIENT_ID);
-                    MPIN.GET_G1_MULTIPLE(rng,1,R,HCID,Z);  /* Also Send Z=r.ID to Server, remember random r */
-                  }
-
-                  rtn=MPIN.SERVER(date,pHID,pHTID,Y,SST,pxID,pxCID,SEC,pE,pF,CLIENT_ID,timeValue);
-                  if (rtn != 0)
-  		    System.out.println("FAILURE: SERVER rtn: " + rtn);
-
-                  if (FULL)
-                  {
-                    MPIN.GET_G1_MULTIPLE(rng,0,W,prHID,T);  /* Also send T=w.ID to client, remember random w  */
-                  }
-		}
-                else
-		{
-  		  System.out.println("MPIN Multi Pass");
-                  /* Send U=x.ID to server, and recreate secret from token and pin */
-  		  rtn=MPIN.CLIENT_1(date,CLIENT_ID,rng,X,pin,TOKEN,SEC,pxID,pxCID,pPERMIT);
-  		  if (rtn != 0)
-  		    System.out.println("FAILURE: CLIENT_1 rtn: " + rtn);
-
-  		  if (FULL)
-  		  {
-  		    HCID=MPIN.HASH_ID(CLIENT_ID);
-  		    MPIN.GET_G1_MULTIPLE(rng,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. */
-  		  MPIN.SERVER_1(date,CLIENT_ID,pHID,pHTID);
-
-                  /* Server generates Random number Y and sends it to Client */
-  		  MPIN.RANDOM_GENERATE(rng,Y);
-
-                  if (FULL)
-  		  {
-  		    MPIN.GET_G1_MULTIPLE(rng,0,W,prHID,T);  /* Also send T=w.ID to client, remember random w  */
-  		  }
-
-                  /* Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC */
-  		  rtn=MPIN.CLIENT_2(X,Y,SEC);
-  		  if (rtn != 0)
-  		    System.out.println("FAILURE: CLIENT_2 rtn: " + rtn);
-
-                  /* Server Second pass. Inputs hashed client id, random Y, -(x+y)*SEC, xID and xCID and Server secret SST. E and F help kangaroos to find error. */
-                  /* If PIN error not required, set E and F = null */
-
-  		  rtn=MPIN.SERVER_2(date,pHID,pHTID,Y,SST,pxID,pxCID,SEC,pE,pF);
-
-  		  if (rtn != 0)
-  		    System.out.println("FAILURE: SERVER_1 rtn: " + rtn);
-		}
-
-		if (rtn == MPIN.BAD_PIN)
-		{
-		  System.out.println("Server says - Bad Pin. I don't know you. Feck off.\n");
-		  if (PINERROR)
-		  {
-		    int err=MPIN.KANGAROO(E,F);
-		    if (err!=0) System.out.format("(Client PIN is out by %d)\n",err);
-		  }
-		  return;
-		}
-		else System.out.println("Server says - PIN is good! You really are "+IDstr);
-
-
-		if (FULL)
-		{
-			MPIN.CLIENT_KEY(G1,G2,pin,R,X,T,CK);
-			System.out.print("Client Key =  0x");  printBinary(CK);
-
-			MPIN.SERVER_KEY(Z,SST,W,pxID,pxCID,SK);
-			System.out.print("Server Key =  0x");  printBinary(SK);
-		}
-	}
-}
diff --git a/java/TestRSA.java b/java/TestRSA.java
deleted file mode 100755
index 414e596..0000000
--- a/java/TestRSA.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
-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.
-*/
-
-/* test driver and function exerciser for RSA API Functions */
-
-public class TestRSA
-{
-	public static void main(String[] args)
-	{
-		int i;
-		int RFS=RSA.RFS;
-
-		String message="Hello World\n";
-
-		rsa_public_key pub=new rsa_public_key(ROM.FFLEN);
-		rsa_private_key priv=new rsa_private_key(ROM.HFLEN);
-
-		byte[] ML=new byte[RFS];
-		byte[] C=new byte[RFS];
-		byte[] RAW=new byte[100];
-
-		RAND rng=new RAND();
-
-		rng.clean();
-		for (i=0;i<100;i++) RAW[i]=(byte)(i);
-
-		rng.seed(100,RAW);
-
-//for (i=0;i<10;i++)
-//{
-		System.out.println("Generating public/private key pair");
-		RSA.KEY_PAIR(rng,65537,priv,pub);
-
-		byte[] M=message.getBytes();
-		System.out.print("Encrypting test string\n");
-		byte[] E=RSA.OAEP_ENCODE(M,rng,null); /* OAEP encode message M to E  */
-
-		RSA.ENCRYPT(pub,E,C);     /* encrypt encoded message */
-		System.out.print("Ciphertext= 0x"); RSA.printBinary(C);
-
-		System.out.print("Decrypting test string\n");
-		RSA.DECRYPT(priv,C,ML);
-		byte[] MS=RSA.OAEP_DECODE(null,ML); /* OAEP decode message  */
-
-		message=new String(MS);
-		System.out.print(message);
-//}
-		RSA.PRIVATE_KEY_KILL(priv);
-	}
-}
diff --git a/java/readme.txt b/java/readme.txt
deleted file mode 100644
index fbe1866..0000000
--- a/java/readme.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-AMCL is very simple to build for Java. This version is optimal for a 32-bit 
-(or less) Virtual Machine.
-
-First - decide the modulus type and curve type you want to use. Edit ROM.java 
-where indicated. You might want to use one of the curves whose details are
-already in there.
-
-Three example API files are provided, MPIN.java which 
-supports our M-Pin (tm) protocol, ECDH.java which supports elliptic 
-curve key exchange, digital signature and public key crypto, and RSA.java
-which supports the RSA method. The first  can be tested using the 
-TestMPIN.java driver programs, the second can be tested using TestECDH.java 
-and TestECM.java, and the third with TestRSA.java
-
-In the ROM.java file you must provide the curve constants. Several examples
-are provided there, if you are willing to use one of these.
-
-To help generate the ROM constants for your own curve some MIRACL helper 
-programs are included. The program bngen.cpp generates the ROM details for a 
-BN curve, and the program ecgen.cpp generates the ROM for EC curves. 
-
-The program bigtobig.cpp converts a big number to the AMCL 
-BIG format.
-
-Don't forget to delete all .class files before rebuilding projects.
-
-For a quick jumpstart:-
-
-del *.class
-javac TestMPIN.java
-java TestMPIN
-
diff --git a/java64/AES.java b/java64/AES.java
deleted file mode 100755
index 08bb2fe..0000000
--- a/java64/AES.java
+++ /dev/null
@@ -1,648 +0,0 @@
-/*
-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.
-*/
-
-
-/* AES Encryption */
-
-
-public class AES {
-	int mode;
-	private int[] fkey=new int[44];
-	private int[] rkey=new int[44];
-	public byte[] f=new byte[16];
-
-
-	public static final int ECB=0;
-	public static final int CBC=1;
-	public static final int CFB1=2;
-	public static final int CFB2=3;
-	public static final int CFB4=5;
-	public static final int OFB1=14;
-	public static final int OFB2=15;
-	public static final int OFB4=17;
-	public static final int OFB8=21;
-	public static final int OFB16=29;
-
-	private static final byte[] InCo={(byte)0xB,(byte)0xD,(byte)0x9,(byte)0xE};  /* Inverse Coefficients */
-
-	public static final int KS=16; /* Key Size in bytes */
-	public static final int BS=16; /* Block Size */
-
-	private static final byte[] ptab=
-	{(byte)1,(byte)3,(byte)5,(byte)15,(byte)17,(byte)51,(byte)85,(byte)255,(byte)26,(byte)46,(byte)114,(byte)150,(byte)161,(byte)248,(byte)19,(byte)53,
-	(byte)95,(byte)225,(byte)56,(byte)72,(byte)216,(byte)115,(byte)149,(byte)164,(byte)247,(byte)2,(byte)6,(byte)10,(byte)30,(byte)34,(byte)102,(byte)170,
-	(byte)229,(byte)52,(byte)92,(byte)228,(byte)55,(byte)89,(byte)235,(byte)38,(byte)106,(byte)190,(byte)217,(byte)112,(byte)144,(byte)171,(byte)230,(byte)49,
-	(byte)83,(byte)245,(byte)4,(byte)12,(byte)20,(byte)60,(byte)68,(byte)204,(byte)79,(byte)209,(byte)104,(byte)184,(byte)211,(byte)110,(byte)178,(byte)205,
-	(byte)76,(byte)212,(byte)103,(byte)169,(byte)224,(byte)59,(byte)77,(byte)215,(byte)98,(byte)166,(byte)241,(byte)8,(byte)24,(byte)40,(byte)120,(byte)136,
-	(byte)131,(byte)158,(byte)185,(byte)208,(byte)107,(byte)189,(byte)220,(byte)127,(byte)129,(byte)152,(byte)179,(byte)206,(byte)73,(byte)219,(byte)118,(byte)154,
-	(byte)181,(byte)196,(byte)87,(byte)249,(byte)16,(byte)48,(byte)80,(byte)240,(byte)11,(byte)29,(byte)39,(byte)105,(byte)187,(byte)214,(byte)97,(byte)163,
-	(byte)254,(byte)25,(byte)43,(byte)125,(byte)135,(byte)146,(byte)173,(byte)236,(byte)47,(byte)113,(byte)147,(byte)174,(byte)233,(byte)32,(byte)96,(byte)160,
-	(byte)251,(byte)22,(byte)58,(byte)78,(byte)210,(byte)109,(byte)183,(byte)194,(byte)93,(byte)231,(byte)50,(byte)86,(byte)250,(byte)21,(byte)63,(byte)65,
-	(byte)195,(byte)94,(byte)226,(byte)61,(byte)71,(byte)201,(byte)64,(byte)192,(byte)91,(byte)237,(byte)44,(byte)116,(byte)156,(byte)191,(byte)218,(byte)117,
-	(byte)159,(byte)186,(byte)213,(byte)100,(byte)172,(byte)239,(byte)42,(byte)126,(byte)130,(byte)157,(byte)188,(byte)223,(byte)122,(byte)142,(byte)137,(byte)128,
-	(byte)155,(byte)182,(byte)193,(byte)88,(byte)232,(byte)35,(byte)101,(byte)175,(byte)234,(byte)37,(byte)111,(byte)177,(byte)200,(byte)67,(byte)197,(byte)84,
-	(byte)252,(byte)31,(byte)33,(byte)99,(byte)165,(byte)244,(byte)7,(byte)9,(byte)27,(byte)45,(byte)119,(byte)153,(byte)176,(byte)203,(byte)70,(byte)202,
-	(byte)69,(byte)207,(byte)74,(byte)222,(byte)121,(byte)139,(byte)134,(byte)145,(byte)168,(byte)227,(byte)62,(byte)66,(byte)198,(byte)81,(byte)243,(byte)14,
-	(byte)18,(byte)54,(byte)90,(byte)238,(byte)41,(byte)123,(byte)141,(byte)140,(byte)143,(byte)138,(byte)133,(byte)148,(byte)167,(byte)242,(byte)13,(byte)23,
-	(byte)57,(byte)75,(byte)221,(byte)124,(byte)132,(byte)151,(byte)162,(byte)253,(byte)28,(byte)36,(byte)108,(byte)180,(byte)199,(byte)82,(byte)246,(byte)1};
-
-	private static final byte[] ltab=
-	{(byte)0,(byte)255,(byte)25,(byte)1,(byte)50,(byte)2,(byte)26,(byte)198,(byte)75,(byte)199,(byte)27,(byte)104,(byte)51,(byte)238,(byte)223,(byte)3,
-	(byte)100,(byte)4,(byte)224,(byte)14,(byte)52,(byte)141,(byte)129,(byte)239,(byte)76,(byte)113,(byte)8,(byte)200,(byte)248,(byte)105,(byte)28,(byte)193,
-	(byte)125,(byte)194,(byte)29,(byte)181,(byte)249,(byte)185,(byte)39,(byte)106,(byte)77,(byte)228,(byte)166,(byte)114,(byte)154,(byte)201,(byte)9,(byte)120,
-	(byte)101,(byte)47,(byte)138,(byte)5,(byte)33,(byte)15,(byte)225,(byte)36,(byte)18,(byte)240,(byte)130,(byte)69,(byte)53,(byte)147,(byte)218,(byte)142,
-	(byte)150,(byte)143,(byte)219,(byte)189,(byte)54,(byte)208,(byte)206,(byte)148,(byte)19,(byte)92,(byte)210,(byte)241,(byte)64,(byte)70,(byte)131,(byte)56,
-	(byte)102,(byte)221,(byte)253,(byte)48,(byte)191,(byte)6,(byte)139,(byte)98,(byte)179,(byte)37,(byte)226,(byte)152,(byte)34,(byte)136,(byte)145,(byte)16,
-	(byte)126,(byte)110,(byte)72,(byte)195,(byte)163,(byte)182,(byte)30,(byte)66,(byte)58,(byte)107,(byte)40,(byte)84,(byte)250,(byte)133,(byte)61,(byte)186,
-	(byte)43,(byte)121,(byte)10,(byte)21,(byte)155,(byte)159,(byte)94,(byte)202,(byte)78,(byte)212,(byte)172,(byte)229,(byte)243,(byte)115,(byte)167,(byte)87,
-	(byte)175,(byte)88,(byte)168,(byte)80,(byte)244,(byte)234,(byte)214,(byte)116,(byte)79,(byte)174,(byte)233,(byte)213,(byte)231,(byte)230,(byte)173,(byte)232,
-	(byte)44,(byte)215,(byte)117,(byte)122,(byte)235,(byte)22,(byte)11,(byte)245,(byte)89,(byte)203,(byte)95,(byte)176,(byte)156,(byte)169,(byte)81,(byte)160,
-	(byte)127,(byte)12,(byte)246,(byte)111,(byte)23,(byte)196,(byte)73,(byte)236,(byte)216,(byte)67,(byte)31,(byte)45,(byte)164,(byte)118,(byte)123,(byte)183,
-	(byte)204,(byte)187,(byte)62,(byte)90,(byte)251,(byte)96,(byte)177,(byte)134,(byte)59,(byte)82,(byte)161,(byte)108,(byte)170,(byte)85,(byte)41,(byte)157,
-	(byte)151,(byte)178,(byte)135,(byte)144,(byte)97,(byte)190,(byte)220,(byte)252,(byte)188,(byte)149,(byte)207,(byte)205,(byte)55,(byte)63,(byte)91,(byte)209,
-	(byte)83,(byte)57,(byte)132,(byte)60,(byte)65,(byte)162,(byte)109,(byte)71,(byte)20,(byte)42,(byte)158,(byte)93,(byte)86,(byte)242,(byte)211,(byte)171,
-	(byte)68,(byte)17,(byte)146,(byte)217,(byte)35,(byte)32,(byte)46,(byte)137,(byte)180,(byte)124,(byte)184,(byte)38,(byte)119,(byte)153,(byte)227,(byte)165,
-	(byte)103,(byte)74,(byte)237,(byte)222,(byte)197,(byte)49,(byte)254,(byte)24,(byte)13,(byte)99,(byte)140,(byte)128,(byte)192,(byte)247,(byte)112,(byte)7};
-
-	private static final byte[] fbsub=
-	{(byte)99,(byte)124,(byte)119,(byte)123,(byte)242,(byte)107,(byte)111,(byte)197,(byte)48,(byte)1,(byte)103,(byte)43,(byte)254,(byte)215,(byte)171,(byte)118,
-	(byte)202,(byte)130,(byte)201,(byte)125,(byte)250,(byte)89,(byte)71,(byte)240,(byte)173,(byte)212,(byte)162,(byte)175,(byte)156,(byte)164,(byte)114,(byte)192,
-	(byte)183,(byte)253,(byte)147,(byte)38,(byte)54,(byte)63,(byte)247,(byte)204,(byte)52,(byte)165,(byte)229,(byte)241,(byte)113,(byte)216,(byte)49,(byte)21,
-	(byte)4,(byte)199,(byte)35,(byte)195,(byte)24,(byte)150,(byte)5,(byte)154,(byte)7,(byte)18,(byte)128,(byte)226,(byte)235,(byte)39,(byte)178,(byte)117,
-	(byte)9,(byte)131,(byte)44,(byte)26,(byte)27,(byte)110,(byte)90,(byte)160,(byte)82,(byte)59,(byte)214,(byte)179,(byte)41,(byte)227,(byte)47,(byte)132,
-	(byte)83,(byte)209,(byte)0,(byte)237,(byte)32,(byte)252,(byte)177,(byte)91,(byte)106,(byte)203,(byte)190,(byte)57,(byte)74,(byte)76,(byte)88,(byte)207,
-	(byte)208,(byte)239,(byte)170,(byte)251,(byte)67,(byte)77,(byte)51,(byte)133,(byte)69,(byte)249,(byte)2,(byte)127,(byte)80,(byte)60,(byte)159,(byte)168,
-	(byte)81,(byte)163,(byte)64,(byte)143,(byte)146,(byte)157,(byte)56,(byte)245,(byte)188,(byte)182,(byte)218,(byte)33,(byte)16,(byte)255,(byte)243,(byte)210,
-	(byte)205,(byte)12,(byte)19,(byte)236,(byte)95,(byte)151,(byte)68,(byte)23,(byte)196,(byte)167,(byte)126,(byte)61,(byte)100,(byte)93,(byte)25,(byte)115,
-	(byte)96,(byte)129,(byte)79,(byte)220,(byte)34,(byte)42,(byte)144,(byte)136,(byte)70,(byte)238,(byte)184,(byte)20,(byte)222,(byte)94,(byte)11,(byte)219,
-	(byte)224,(byte)50,(byte)58,(byte)10,(byte)73,(byte)6,(byte)36,(byte)92,(byte)194,(byte)211,(byte)172,(byte)98,(byte)145,(byte)149,(byte)228,(byte)121,
-	(byte)231,(byte)200,(byte)55,(byte)109,(byte)141,(byte)213,(byte)78,(byte)169,(byte)108,(byte)86,(byte)244,(byte)234,(byte)101,(byte)122,(byte)174,(byte)8,
-	(byte)186,(byte)120,(byte)37,(byte)46,(byte)28,(byte)166,(byte)180,(byte)198,(byte)232,(byte)221,(byte)116,(byte)31,(byte)75,(byte)189,(byte)139,(byte)138,
-	(byte)112,(byte)62,(byte)181,(byte)102,(byte)72,(byte)3,(byte)246,(byte)14,(byte)97,(byte)53,(byte)87,(byte)185,(byte)134,(byte)193,(byte)29,(byte)158,
-	(byte)225,(byte)248,(byte)152,(byte)17,(byte)105,(byte)217,(byte)142,(byte)148,(byte)155,(byte)30,(byte)135,(byte)233,(byte)206,(byte)85,(byte)40,(byte)223,
-	(byte)140,(byte)161,(byte)137,(byte)13,(byte)191,(byte)230,(byte)66,(byte)104,(byte)65,(byte)153,(byte)45,(byte)15,(byte)176,(byte)84,(byte)187,(byte)22};
-
-	private static final byte[] rbsub=
-	{(byte)82,(byte)9,(byte)106,(byte)213,(byte)48,(byte)54,(byte)165,(byte)56,(byte)191,(byte)64,(byte)163,(byte)158,(byte)129,(byte)243,(byte)215,(byte)251,
-	(byte)124,(byte)227,(byte)57,(byte)130,(byte)155,(byte)47,(byte)255,(byte)135,(byte)52,(byte)142,(byte)67,(byte)68,(byte)196,(byte)222,(byte)233,(byte)203,
-	(byte)84,(byte)123,(byte)148,(byte)50,(byte)166,(byte)194,(byte)35,(byte)61,(byte)238,(byte)76,(byte)149,(byte)11,(byte)66,(byte)250,(byte)195,(byte)78,
-	(byte)8,(byte)46,(byte)161,(byte)102,(byte)40,(byte)217,(byte)36,(byte)178,(byte)118,(byte)91,(byte)162,(byte)73,(byte)109,(byte)139,(byte)209,(byte)37,
-	(byte)114,(byte)248,(byte)246,(byte)100,(byte)134,(byte)104,(byte)152,(byte)22,(byte)212,(byte)164,(byte)92,(byte)204,(byte)93,(byte)101,(byte)182,(byte)146,
-	(byte)108,(byte)112,(byte)72,(byte)80,(byte)253,(byte)237,(byte)185,(byte)218,(byte)94,(byte)21,(byte)70,(byte)87,(byte)167,(byte)141,(byte)157,(byte)132,
-	(byte)144,(byte)216,(byte)171,(byte)0,(byte)140,(byte)188,(byte)211,(byte)10,(byte)247,(byte)228,(byte)88,(byte)5,(byte)184,(byte)179,(byte)69,(byte)6,
-	(byte)208,(byte)44,(byte)30,(byte)143,(byte)202,(byte)63,(byte)15,(byte)2,(byte)193,(byte)175,(byte)189,(byte)3,(byte)1,(byte)19,(byte)138,(byte)107,
-	(byte)58,(byte)145,(byte)17,(byte)65,(byte)79,(byte)103,(byte)220,(byte)234,(byte)151,(byte)242,(byte)207,(byte)206,(byte)240,(byte)180,(byte)230,(byte)115,
-	(byte)150,(byte)172,(byte)116,(byte)34,(byte)231,(byte)173,(byte)53,(byte)133,(byte)226,(byte)249,(byte)55,(byte)232,(byte)28,(byte)117,(byte)223,(byte)110,
-	(byte)71,(byte)241,(byte)26,(byte)113,(byte)29,(byte)41,(byte)197,(byte)137,(byte)111,(byte)183,(byte)98,(byte)14,(byte)170,(byte)24,(byte)190,(byte)27,
-	(byte)252,(byte)86,(byte)62,(byte)75,(byte)198,(byte)210,(byte)121,(byte)32,(byte)154,(byte)219,(byte)192,(byte)254,(byte)120,(byte)205,(byte)90,(byte)244,
-	(byte)31,(byte)221,(byte)168,(byte)51,(byte)136,(byte)7,(byte)199,(byte)49,(byte)177,(byte)18,(byte)16,(byte)89,(byte)39,(byte)128,(byte)236,(byte)95,
-	(byte)96,(byte)81,(byte)127,(byte)169,(byte)25,(byte)181,(byte)74,(byte)13,(byte)45,(byte)229,(byte)122,(byte)159,(byte)147,(byte)201,(byte)156,(byte)239,
-	(byte)160,(byte)224,(byte)59,(byte)77,(byte)174,(byte)42,(byte)245,(byte)176,(byte)200,(byte)235,(byte)187,(byte)60,(byte)131,(byte)83,(byte)153,(byte)97,
-	(byte)23,(byte)43,(byte)4,(byte)126,(byte)186,(byte)119,(byte)214,(byte)38,(byte)225,(byte)105,(byte)20,(byte)99,(byte)85,(byte)33,(byte)12,(byte)125};
-
-	private static final byte[] rco=
-	{(byte)1,(byte)2,(byte)4,(byte)8,(byte)16,(byte)32,(byte)64,(byte)128,(byte)27,(byte)54,(byte)108,(byte)216,(byte)171,(byte)77,(byte)154,(byte)47};
-
-	private static final int[] ftable=
-	{0xa56363c6,0x847c7cf8,0x997777ee,0x8d7b7bf6,0xdf2f2ff,0xbd6b6bd6,
-	0xb16f6fde,0x54c5c591,0x50303060,0x3010102,0xa96767ce,0x7d2b2b56,
-	0x19fefee7,0x62d7d7b5,0xe6abab4d,0x9a7676ec,0x45caca8f,0x9d82821f,
-	0x40c9c989,0x877d7dfa,0x15fafaef,0xeb5959b2,0xc947478e,0xbf0f0fb,
-	0xecadad41,0x67d4d4b3,0xfda2a25f,0xeaafaf45,0xbf9c9c23,0xf7a4a453,
-	0x967272e4,0x5bc0c09b,0xc2b7b775,0x1cfdfde1,0xae93933d,0x6a26264c,
-	0x5a36366c,0x413f3f7e,0x2f7f7f5,0x4fcccc83,0x5c343468,0xf4a5a551,
-	0x34e5e5d1,0x8f1f1f9,0x937171e2,0x73d8d8ab,0x53313162,0x3f15152a,
-	0xc040408,0x52c7c795,0x65232346,0x5ec3c39d,0x28181830,0xa1969637,
-	0xf05050a,0xb59a9a2f,0x907070e,0x36121224,0x9b80801b,0x3de2e2df,
-	0x26ebebcd,0x6927274e,0xcdb2b27f,0x9f7575ea,0x1b090912,0x9e83831d,
-	0x742c2c58,0x2e1a1a34,0x2d1b1b36,0xb26e6edc,0xee5a5ab4,0xfba0a05b,
-	0xf65252a4,0x4d3b3b76,0x61d6d6b7,0xceb3b37d,0x7b292952,0x3ee3e3dd,
-	0x712f2f5e,0x97848413,0xf55353a6,0x68d1d1b9,0x0,0x2cededc1,
-	0x60202040,0x1ffcfce3,0xc8b1b179,0xed5b5bb6,0xbe6a6ad4,0x46cbcb8d,
-	0xd9bebe67,0x4b393972,0xde4a4a94,0xd44c4c98,0xe85858b0,0x4acfcf85,
-	0x6bd0d0bb,0x2aefefc5,0xe5aaaa4f,0x16fbfbed,0xc5434386,0xd74d4d9a,
-	0x55333366,0x94858511,0xcf45458a,0x10f9f9e9,0x6020204,0x817f7ffe,
-	0xf05050a0,0x443c3c78,0xba9f9f25,0xe3a8a84b,0xf35151a2,0xfea3a35d,
-	0xc0404080,0x8a8f8f05,0xad92923f,0xbc9d9d21,0x48383870,0x4f5f5f1,
-	0xdfbcbc63,0xc1b6b677,0x75dadaaf,0x63212142,0x30101020,0x1affffe5,
-	0xef3f3fd,0x6dd2d2bf,0x4ccdcd81,0x140c0c18,0x35131326,0x2fececc3,
-	0xe15f5fbe,0xa2979735,0xcc444488,0x3917172e,0x57c4c493,0xf2a7a755,
-	0x827e7efc,0x473d3d7a,0xac6464c8,0xe75d5dba,0x2b191932,0x957373e6,
-	0xa06060c0,0x98818119,0xd14f4f9e,0x7fdcdca3,0x66222244,0x7e2a2a54,
-	0xab90903b,0x8388880b,0xca46468c,0x29eeeec7,0xd3b8b86b,0x3c141428,
-	0x79dedea7,0xe25e5ebc,0x1d0b0b16,0x76dbdbad,0x3be0e0db,0x56323264,
-	0x4e3a3a74,0x1e0a0a14,0xdb494992,0xa06060c,0x6c242448,0xe45c5cb8,
-	0x5dc2c29f,0x6ed3d3bd,0xefacac43,0xa66262c4,0xa8919139,0xa4959531,
-	0x37e4e4d3,0x8b7979f2,0x32e7e7d5,0x43c8c88b,0x5937376e,0xb76d6dda,
-	0x8c8d8d01,0x64d5d5b1,0xd24e4e9c,0xe0a9a949,0xb46c6cd8,0xfa5656ac,
-	0x7f4f4f3,0x25eaeacf,0xaf6565ca,0x8e7a7af4,0xe9aeae47,0x18080810,
-	0xd5baba6f,0x887878f0,0x6f25254a,0x722e2e5c,0x241c1c38,0xf1a6a657,
-	0xc7b4b473,0x51c6c697,0x23e8e8cb,0x7cdddda1,0x9c7474e8,0x211f1f3e,
-	0xdd4b4b96,0xdcbdbd61,0x868b8b0d,0x858a8a0f,0x907070e0,0x423e3e7c,
-	0xc4b5b571,0xaa6666cc,0xd8484890,0x5030306,0x1f6f6f7,0x120e0e1c,
-	0xa36161c2,0x5f35356a,0xf95757ae,0xd0b9b969,0x91868617,0x58c1c199,
-	0x271d1d3a,0xb99e9e27,0x38e1e1d9,0x13f8f8eb,0xb398982b,0x33111122,
-	0xbb6969d2,0x70d9d9a9,0x898e8e07,0xa7949433,0xb69b9b2d,0x221e1e3c,
-	0x92878715,0x20e9e9c9,0x49cece87,0xff5555aa,0x78282850,0x7adfdfa5,
-	0x8f8c8c03,0xf8a1a159,0x80898909,0x170d0d1a,0xdabfbf65,0x31e6e6d7,
-	0xc6424284,0xb86868d0,0xc3414182,0xb0999929,0x772d2d5a,0x110f0f1e,
-	0xcbb0b07b,0xfc5454a8,0xd6bbbb6d,0x3a16162c};
-
-	private static final int[] rtable=
-	{0x50a7f451,0x5365417e,0xc3a4171a,0x965e273a,0xcb6bab3b,0xf1459d1f,
-	0xab58faac,0x9303e34b,0x55fa3020,0xf66d76ad,0x9176cc88,0x254c02f5,
-	0xfcd7e54f,0xd7cb2ac5,0x80443526,0x8fa362b5,0x495ab1de,0x671bba25,
-	0x980eea45,0xe1c0fe5d,0x2752fc3,0x12f04c81,0xa397468d,0xc6f9d36b,
-	0xe75f8f03,0x959c9215,0xeb7a6dbf,0xda595295,0x2d83bed4,0xd3217458,
-	0x2969e049,0x44c8c98e,0x6a89c275,0x78798ef4,0x6b3e5899,0xdd71b927,
-	0xb64fe1be,0x17ad88f0,0x66ac20c9,0xb43ace7d,0x184adf63,0x82311ae5,
-	0x60335197,0x457f5362,0xe07764b1,0x84ae6bbb,0x1ca081fe,0x942b08f9,
-	0x58684870,0x19fd458f,0x876cde94,0xb7f87b52,0x23d373ab,0xe2024b72,
-	0x578f1fe3,0x2aab5566,0x728ebb2,0x3c2b52f,0x9a7bc586,0xa50837d3,
-	0xf2872830,0xb2a5bf23,0xba6a0302,0x5c8216ed,0x2b1ccf8a,0x92b479a7,
-	0xf0f207f3,0xa1e2694e,0xcdf4da65,0xd5be0506,0x1f6234d1,0x8afea6c4,
-	0x9d532e34,0xa055f3a2,0x32e18a05,0x75ebf6a4,0x39ec830b,0xaaef6040,
-	0x69f715e,0x51106ebd,0xf98a213e,0x3d06dd96,0xae053edd,0x46bde64d,
-	0xb58d5491,0x55dc471,0x6fd40604,0xff155060,0x24fb9819,0x97e9bdd6,
-	0xcc434089,0x779ed967,0xbd42e8b0,0x888b8907,0x385b19e7,0xdbeec879,
-	0x470a7ca1,0xe90f427c,0xc91e84f8,0x0,0x83868009,0x48ed2b32,
-	0xac70111e,0x4e725a6c,0xfbff0efd,0x5638850f,0x1ed5ae3d,0x27392d36,
-	0x64d90f0a,0x21a65c68,0xd1545b9b,0x3a2e3624,0xb1670a0c,0xfe75793,
-	0xd296eeb4,0x9e919b1b,0x4fc5c080,0xa220dc61,0x694b775a,0x161a121c,
-	0xaba93e2,0xe52aa0c0,0x43e0223c,0x1d171b12,0xb0d090e,0xadc78bf2,
-	0xb9a8b62d,0xc8a91e14,0x8519f157,0x4c0775af,0xbbdd99ee,0xfd607fa3,
-	0x9f2601f7,0xbcf5725c,0xc53b6644,0x347efb5b,0x7629438b,0xdcc623cb,
-	0x68fcedb6,0x63f1e4b8,0xcadc31d7,0x10856342,0x40229713,0x2011c684,
-	0x7d244a85,0xf83dbbd2,0x1132f9ae,0x6da129c7,0x4b2f9e1d,0xf330b2dc,
-	0xec52860d,0xd0e3c177,0x6c16b32b,0x99b970a9,0xfa489411,0x2264e947,
-	0xc48cfca8,0x1a3ff0a0,0xd82c7d56,0xef903322,0xc74e4987,0xc1d138d9,
-	0xfea2ca8c,0x360bd498,0xcf81f5a6,0x28de7aa5,0x268eb7da,0xa4bfad3f,
-	0xe49d3a2c,0xd927850,0x9bcc5f6a,0x62467e54,0xc2138df6,0xe8b8d890,
-	0x5ef7392e,0xf5afc382,0xbe805d9f,0x7c93d069,0xa92dd56f,0xb31225cf,
-	0x3b99acc8,0xa77d1810,0x6e639ce8,0x7bbb3bdb,0x97826cd,0xf418596e,
-	0x1b79aec,0xa89a4f83,0x656e95e6,0x7ee6ffaa,0x8cfbc21,0xe6e815ef,
-	0xd99be7ba,0xce366f4a,0xd4099fea,0xd67cb029,0xafb2a431,0x31233f2a,
-	0x3094a5c6,0xc066a235,0x37bc4e74,0xa6ca82fc,0xb0d090e0,0x15d8a733,
-	0x4a9804f1,0xf7daec41,0xe50cd7f,0x2ff69117,0x8dd64d76,0x4db0ef43,
-	0x544daacc,0xdf0496e4,0xe3b5d19e,0x1b886a4c,0xb81f2cc1,0x7f516546,
-	0x4ea5e9d,0x5d358c01,0x737487fa,0x2e410bfb,0x5a1d67b3,0x52d2db92,
-	0x335610e9,0x1347d66d,0x8c61d79a,0x7a0ca137,0x8e14f859,0x893c13eb,
-	0xee27a9ce,0x35c961b7,0xede51ce1,0x3cb1477a,0x59dfd29c,0x3f73f255,
-	0x79ce1418,0xbf37c773,0xeacdf753,0x5baafd5f,0x146f3ddf,0x86db4478,
-	0x81f3afca,0x3ec468b9,0x2c342438,0x5f40a3c2,0x72c31d16,0xc25e2bc,
-	0x8b493c28,0x41950dff,0x7101a839,0xdeb30c08,0x9ce4b4d8,0x90c15664,
-	0x6184cb7b,0x70b632d5,0x745c6c48,0x4257b8d0};
-
-
-/* Rotates 32-bit word left by 1, 2 or 3 byte  */
-
-	private static int ROTL8(int x)
-	{
-		return (((x)<<8)|((x)>>>24));
-	}
-
-	private static int ROTL16(int x)
-	{
-		return (((x)<<16)|((x)>>>16));
-	}
-
-	private static int ROTL24(int x)
-	{
-		return (((x)<<24)|((x)>>>8));
-	}
-
-	private static int pack(byte[] b)
-	{ /* pack bytes into a 32-bit Word */
-		return ((((int)b[3])&0xff)<<24)|(((int)b[2]&0xff)<<16)|(((int)b[1]&0xff)<<8)|((int)b[0]&0xff);
-	}
-
-	private static byte[] unpack(int a)
-	{ /* unpack bytes from a word */
-		byte [] b=new byte[4];
-		b[0]=(byte)(a);
-		b[1]=(byte)(a>>>8);
-		b[2]=(byte)(a>>>16);
-		b[3]=(byte)(a>>>24);
-		return b;
-	}
-
-	private static byte bmul(byte x,byte y)
-	{ /* x.y= AntiLog(Log(x) + Log(y)) */
-
-		int ix=((int)x)&0xff;
-		int iy=((int)y)&0xff;
-		int lx=((int)ltab[ix])&0xff;
-		int ly=((int)ltab[iy])&0xff;
-		if (x!=0 && y!=0) return ptab[(lx+ly)%255];
-		else return (byte)0;
-	}
-
-  //  if (x && y)
-
-	private static int SubByte(int a)
-	{
-		byte [] b=unpack(a);
-		b[0]=fbsub[(int)b[0]&0xff];
-		b[1]=fbsub[(int)b[1]&0xff];
-		b[2]=fbsub[(int)b[2]&0xff];
-		b[3]=fbsub[(int)b[3]&0xff];
-		return pack(b);
-	}
-
-	private static byte product(int x,int y)
-	{ /* dot product of two 4-byte arrays */
-		byte [] xb;//=new byte[4];
-		byte [] yb;//=new byte[4];
-		xb=unpack(x);
-		yb=unpack(y);
-
-		return (byte)(bmul(xb[0],yb[0])^bmul(xb[1],yb[1])^bmul(xb[2],yb[2])^bmul(xb[3],yb[3]));
-	}
-
-	private static int InvMixCol(int x)
-	{ /* matrix Multiplication */
-		int y,m;
-		byte [] b=new byte[4];
-
-		m=pack(InCo);
-		b[3]=product(m,x);
-		m=ROTL24(m);
-		b[2]=product(m,x);
-		m=ROTL24(m);
-		b[1]=product(m,x);
-		m=ROTL24(m);
-		b[0]=product(m,x);
-		y=pack(b);
-		return y;
-	}
-
-/* reset cipher */
-	public void reset(int m,byte[] iv)
-	{ /* reset mode, or reset iv */
-		mode=m;
-		for (int i=0;i<16;i++)
-			f[i]=0;
-		if (mode!=ECB && iv!=null)
-			for (int i=0;i<16;i++)
-				f[i]=iv[i];
-	}
-
-	public byte[] getreg()
-	{
-		byte [] ir=new byte[16];
-		for (int i=0;i<16;i++) ir[i]=f[i];
-		return ir;
-	}
-
-/* Initialise cipher */
-	public void init(int m,byte[] key,byte[] iv)
-	{	/* Key=16 bytes */
-		/* Key Scheduler. Create expanded encryption key */
-		int i,j,k,N,nk;
-		int [] CipherKey=new int[4];
-    	byte [] b=new byte[4];
-		nk=4;
-		reset(m,iv);
-		N=44;
-
-		for (i=j=0;i<nk;i++,j+=4)
-		{
-			for (k=0;k<4;k++) b[k]=key[j+k];
-			CipherKey[i]=pack(b);
-		}
-		for (i=0;i<nk;i++) fkey[i]=CipherKey[i];
-		for (j=nk,k=0;j<N;j+=nk,k++)
-		{
-			fkey[j]=fkey[j-nk]^SubByte(ROTL24(fkey[j-1]))^((int)rco[k])&0xff;
-			for (i=1;i<nk && (i+j)<N;i++)
-				fkey[i+j]=fkey[i+j-nk]^fkey[i+j-1];
-		}
-
- /* now for the expanded decrypt key in reverse order */
-
-		for (j=0;j<4;j++) rkey[j+N-4]=fkey[j];
-		for (i=4;i<N-4;i+=4)
-		{
-			k=N-4-i;
-			for (j=0;j<4;j++) rkey[k+j]=InvMixCol(fkey[i+j]);
-		}
-		for (j=N-4;j<N;j++) rkey[j-N+4]=fkey[j];
-	}
-
-/* Encrypt a single block */
-	public void ecb_encrypt(byte[] buff)
-	{
-		int i,j,k;
-		int t;
-    	byte [] b=new byte[4];
-    	int [] p=new int[4];
-    	int [] q=new int[4];
-
-		for (i=j=0;i<4;i++,j+=4)
-		{
-			for (k=0;k<4;k++) b[k]=buff[j+k];
-			p[i]=pack(b);
-			p[i]^=fkey[i];
-		}
-
-		k=4;
-
-/* State alternates between p and q */
-		for (i=1;i<10;i++)
-		{
-			q[0]=fkey[k]^ftable[p[0]&0xff]^
-				ROTL8(ftable[(p[1]>>>8)&0xff])^
-				ROTL16(ftable[(p[2]>>>16)&0xff])^
-				ROTL24(ftable[(p[3]>>>24)&0xff]);
-			q[1]=fkey[k+1]^ftable[p[1]&0xff]^
-				ROTL8(ftable[(p[2]>>>8)&0xff])^
-				ROTL16(ftable[(p[3]>>>16)&0xff])^
-				ROTL24(ftable[(p[0]>>>24)&0xff]);
-			q[2]=fkey[k+2]^ftable[p[2]&0xff]^
-				ROTL8(ftable[(p[3]>>>8)&0xff])^
-				ROTL16(ftable[(p[0]>>>16)&0xff])^
-				ROTL24(ftable[(p[1]>>>24)&0xff]);
-			q[3]=fkey[k+3]^ftable[p[3]&0xff]^
-				ROTL8(ftable[(p[0]>>>8)&0xff])^
-				ROTL16(ftable[(p[1]>>>16)&0xff])^
-				ROTL24(ftable[(p[2]>>>24)&0xff]);
-
-			k+=4;
-			for (j=0;j<4;j++)
-			{
-				t=p[j]; p[j]=q[j]; q[j]=t;
-			}
-		}
-
-/* Last Round */
-
-		q[0]=fkey[k]^((int)fbsub[p[0]&0xff]&0xff)^
-			ROTL8((int)fbsub[(p[1]>>>8)&0xff]&0xff)^
-			ROTL16((int)fbsub[(p[2]>>>16)&0xff]&0xff)^
-			ROTL24((int)fbsub[(p[3]>>>24)&0xff]&0xff);
-
-		q[1]=fkey[k+1]^((int)fbsub[p[1]&0xff]&0xff)^
-			ROTL8((int)fbsub[(p[2]>>>8)&0xff]&0xff)^
-			ROTL16((int)fbsub[(p[3]>>>16)&0xff]&0xff)^
-			ROTL24((int)fbsub[(p[0]>>>24)&0xff]&0xff);
-
-		q[2]=fkey[k+2]^((int)fbsub[p[2]&0xff]&0xff)^
-			ROTL8((int)fbsub[(p[3]>>>8)&0xff]&0xff)^
-			ROTL16((int)fbsub[(p[0]>>>16)&0xff]&0xff)^
-			ROTL24((int)fbsub[(p[1]>>>24)&0xff]&0xff);
-
-		q[3]=fkey[k+3]^((int)fbsub[(p[3])&0xff]&0xff)^
-			ROTL8((int)fbsub[(p[0]>>>8)&0xff]&0xff)^
-			ROTL16((int)fbsub[(p[1]>>>16)&0xff]&0xff)^
-			ROTL24((int)fbsub[(p[2]>>>24)&0xff]&0xff);
-
-		for (i=j=0;i<4;i++,j+=4)
-		{
-			b=unpack(q[i]);
-			for (k=0;k<4;k++) buff[j+k]=b[k];
-		}
-	}
-
-/* Decrypt a single block */
-	public void ecb_decrypt(byte[] buff)
-	{
-		int i,j,k;
-		int t;
-    	byte [] b=new byte[4];
-    	int [] p=new int[4];
-    	int [] q=new int[4];
-
-		for (i=j=0;i<4;i++,j+=4)
-		{
-			for (k=0;k<4;k++) b[k]=buff[j+k];
-			p[i]=pack(b);
-			p[i]^=rkey[i];
-		}
-
-		k=4;
-
-/* State alternates between p and q */
-		for (i=1;i<10;i++)
-		{
-			q[0]=rkey[k]^rtable[p[0]&0xff]^
-				ROTL8(rtable[(p[3]>>>8)&0xff])^
-				ROTL16(rtable[(p[2]>>>16)&0xff])^
-				ROTL24(rtable[(p[1]>>>24)&0xff]);
-			q[1]=rkey[k+1]^rtable[p[1]&0xff]^
-				ROTL8(rtable[(p[0]>>>8)&0xff])^
-				ROTL16(rtable[(p[3]>>>16)&0xff])^
-				ROTL24(rtable[(p[2]>>>24)&0xff]);
-			q[2]=rkey[k+2]^rtable[p[2]&0xff]^
-				ROTL8(rtable[(p[1]>>>8)&0xff])^
-				ROTL16(rtable[(p[0]>>>16)&0xff])^
-				ROTL24(rtable[(p[3]>>>24)&0xff]);
-			q[3]=rkey[k+3]^rtable[p[3]&0xff]^
-				ROTL8(rtable[(p[2]>>>8)&0xff])^
-				ROTL16(rtable[(p[1]>>>16)&0xff])^
-				ROTL24(rtable[(p[0]>>>24)&0xff]);
-
-			k+=4;
-			for (j=0;j<4;j++)
-			{
-				t=p[j]; p[j]=q[j]; q[j]=t;
-			}
-		}
-
-/* Last Round */
-
-		q[0]=rkey[k]^((int)rbsub[p[0]&0xff]&0xff)^
-			ROTL8((int)rbsub[(p[3]>>>8)&0xff]&0xff)^
-			ROTL16((int)rbsub[(p[2]>>>16)&0xff]&0xff)^
-			ROTL24((int)rbsub[(p[1]>>>24)&0xff]&0xff);
-		q[1]=rkey[k+1]^((int)rbsub[p[1]&0xff]&0xff)^
-			ROTL8((int)rbsub[(p[0]>>>8)&0xff]&0xff)^
-			ROTL16((int)rbsub[(p[3]>>>16)&0xff]&0xff)^
-			ROTL24((int)rbsub[(p[2]>>>24)&0xff]&0xff);
-		q[2]=rkey[k+2]^((int)rbsub[p[2]&0xff]&0xff)^
-			ROTL8((int)rbsub[(p[1]>>>8)&0xff]&0xff)^
-			ROTL16((int)rbsub[(p[0]>>>16)&0xff]&0xff)^
-			ROTL24((int)rbsub[(p[3]>>>24)&0xff]&0xff);
-		q[3]=rkey[k+3]^((int)rbsub[p[3]&0xff]&0xff)^
-			ROTL8((int)rbsub[(p[2]>>>8)&0xff]&0xff)^
-			ROTL16((int)rbsub[(p[1]>>>16)&0xff]&0xff)^
-			ROTL24((int)rbsub[(p[0]>>>24)&0xff]&0xff);
-
-		for (i=j=0;i<4;i++,j+=4)
-		{
-			b=unpack(q[i]);
-			for (k=0;k<4;k++) buff[j+k]=b[k];
-		}
-
-	}
-
-/* Encrypt using selected mode of operation */
-	public int encrypt(byte[] buff)
-	{
-		int j,bytes;
-		byte[] st=new byte[16];
-		int fell_off;
-
-// Supported Modes of Operation
-
-		fell_off=0;
-		switch (mode)
-		{
-		case ECB:
-			ecb_encrypt(buff);
-			return 0;
-		case CBC:
-			for (j=0;j<16;j++) buff[j]^=f[j];
-			ecb_encrypt(buff);
-			for (j=0;j<16;j++) f[j]=buff[j];
-			return 0;
-
-		case CFB1:
-		case CFB2:
-		case CFB4:
-			bytes=mode-CFB1+1;
-			for (j=0;j<bytes;j++) fell_off=(fell_off<<8)|f[j];
-			for (j=0;j<16;j++) st[j]=f[j];
-			for (j=bytes;j<16;j++) f[j-bytes]=f[j];
-			ecb_encrypt(st);
-			for (j=0;j<bytes;j++)
-			{
-				buff[j]^=st[j];
-				f[16-bytes+j]=buff[j];
-			}
-			return fell_off;
-
-		case OFB1:
-		case OFB2:
-		case OFB4:
-		case OFB8:
-		case OFB16:
-
-			bytes=mode-OFB1+1;
-			ecb_encrypt(f);
-			for (j=0;j<bytes;j++) buff[j]^=f[j];
-			return 0;
-
-    default:
-			return 0;
-		}
-	}
-
-/* Decrypt using selected mode of operation */
-	public int decrypt(byte[] buff)
-	{
-		int j,bytes;
-		byte[] st=new byte[16];
-		int fell_off;
-
-   // Supported modes of operation
-		fell_off=0;
-		switch (mode)
-		{
-		case ECB:
-			ecb_decrypt(buff);
-			return 0;
-		case CBC:
-			for (j=0;j<16;j++)
-			{
-				st[j]=f[j];
-				f[j]=buff[j];
-			}
-			ecb_decrypt(buff);
-			for (j=0;j<16;j++)
-			{
-				buff[j]^=st[j];
-				st[j]=0;
-			}
-			return 0;
-		case CFB1:
-		case CFB2:
-		case CFB4:
-			bytes=mode-CFB1+1;
-			for (j=0;j<bytes;j++) fell_off=(fell_off<<8)|f[j];
-			for (j=0;j<16;j++) st[j]=f[j];
-			for (j=bytes;j<16;j++) f[j-bytes]=f[j];
-			ecb_encrypt(st);
-			for (j=0;j<bytes;j++)
-			{
-				f[16-bytes+j]=buff[j];
-				buff[j]^=st[j];
-			}
-			return fell_off;
-		case OFB1:
-		case OFB2:
-		case OFB4:
-		case OFB8:
-		case OFB16:
-			bytes=mode-OFB1+1;
-			ecb_encrypt(f);
-			for (j=0;j<bytes;j++) buff[j]^=f[j];
-			return 0;
-
-
-		default:
-			return 0;
-		}
-	}
-
-/* Clean up and delete left-overs */
-	public void end()
-	{ // clean up
-		int i;
-		for (i=0;i<44;i++)
-			fkey[i]=rkey[i]=0;
-		for (i=0;i<16;i++)
-			f[i]=0;
-	}
-/*
-	public static void main(String[] args) {
-		int i;
-
-		byte[] key=new byte[16];
-		byte[] block=new byte[16];
-		byte[] iv=new byte[16];
-
-		for (i=0;i<16;i++) key[i]=0;
-		key[0]=1;
-		for (i=0;i<16;i++) iv[i]=(byte)i;
-		for (i=0;i<16;i++) block[i]=(byte)i;
-
-		AES a=new AES();
-
-		a.init(CBC,key,iv);
-		System.out.println("Plain= ");
-		for (i=0;i<16;i++)  System.out.format("%02X ", block[i]&0xff);
-		System.out.println("");
-
-		a.encrypt(block);
-
-		System.out.println("Encrypt= ");
-		for (i=0;i<16;i++)  System.out.format("%02X ", block[i]&0xff);
-		System.out.println("");
-
-		a.reset(CBC,iv);
-		a.decrypt(block);
-
-		System.out.println("Decrypt= ");
-		for (i=0;i<16;i++)  System.out.format("%02X ", block[i]&0xff);
-		System.out.println("");
-
-		a.end();
-
-	} */
-}
diff --git a/java64/BIG.java b/java64/BIG.java
deleted file mode 100755
index 737fd1a..0000000
--- a/java64/BIG.java
+++ /dev/null
@@ -1,902 +0,0 @@
-/*
-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.
-*/
-
-/* AMCL BIG number class */
-
-public class BIG {
-	private long[] w=new long[ROM.NLEN];
-/* Constructors */
-	public BIG()
-	{
-		for (int i=0;i<ROM.NLEN;i++)
-			w[i]=0;
-	}
-
-	public BIG(int x)
-	{
-		w[0]=x;
-		for (int i=1;i<ROM.NLEN;i++)
-			w[i]=0;
-	}
-
-	public BIG(BIG x)
-	{
-		for (int i=0;i<ROM.NLEN;i++)
-			w[i]=x.w[i];
-	}
-
-	public BIG(DBIG x)
-	{
-		for (int i=0;i<ROM.NLEN;i++)
-			w[i]=x.w[i];
-	}
-
-	public BIG(long[] x)
-	{
-		for (int i=0;i<ROM.NLEN;i++)
-			w[i]=x[i];
-	}
-
-	public long get(int i)
-	{
-		return w[i];
-	}
-
-	public void set(int i,long x)
-	{
-		w[i]=x;
-	}
-
-	public void xortop(long x)
-	{
-		w[ROM.NLEN-1]^=x;
-	}
-
-	public void ortop(long x)
-	{
-		w[ROM.NLEN-1]|=x;
-	}
-
-/* calculate Field Excess */
-	public static long EXCESS(BIG a)
-	{
-		return ((a.w[ROM.NLEN-1]&ROM.OMASK)>>(ROM.MODBITS%ROM.BASEBITS));
-	}
-
-/* test for zero */
-	public boolean iszilch() {
-		for (int i=0;i<ROM.NLEN;i++)
-			if (w[i]!=0) return false;
-		return true;
-	}
-
-/* set to zero */
-	public void zero()
-	{
-		for (int i=0;i<ROM.NLEN;i++)
-			w[i]=0;
-	}
-
-/* set to one */
-	public void one()
-	{
-		w[0]=1;
-		for (int i=1;i<ROM.NLEN;i++)
-			w[i]=0;
-	}
-
-/* Test for equal to one */
-	public boolean isunity()
-	{
-		for (int i=1;i<ROM.NLEN;i++)
-			if (w[i]!=0) return false;
-		if (w[0]!=1) return false;
-		return true;
-	}
-
-/* Copy from another BIG */
-	public void copy(BIG x)
-	{
-		for (int i=0;i<ROM.NLEN;i++)
-			w[i]=x.w[i];
-	}
-
-	public void copy(DBIG x)
-	{
-		for (int i=0;i<ROM.NLEN;i++)
-			w[i]=x.w[i];
-	}
-
-/* Conditional swap of two bigs depending on d using XOR - no branches */
-	public void cswap(BIG b,int d)
-	{
-		int i;
-		long t,c=(long)d;
-		c=~(c-1);
-
-		for (i=0;i<ROM.NLEN;i++)
-		{
-			t=c&(w[i]^b.w[i]);
-			w[i]^=t;
-			b.w[i]^=t;
-		}
-	}
-
-	public void cmove(BIG g,int d)
-	{
-		int i;
-		long t,b=-d;
-
-		for (i=0;i<ROM.NLEN;i++)
-		{
-			w[i]^=(w[i]^g.w[i])&b;
-		}
-	}
-
-
-/* normalise BIG - force all digits < 2^BASEBITS */
-	public long norm() {
-		long d,carry=0;
-		for (int i=0;i<ROM.NLEN-1;i++)
-		{
-			d=w[i]+carry;
-			w[i]=d&ROM.MASK;
-			carry=d>>ROM.BASEBITS;
-		}
-		w[ROM.NLEN-1]=(w[ROM.NLEN-1]+carry);
-		return (w[ROM.NLEN-1]>>((8*ROM.MODBYTES)%ROM.BASEBITS));
-	}
-
-/* Shift right by less than a word */
-	public long fshr(int k) {
-		long r=w[0]&(((long)1<<k)-1); /* shifted out part */
-		for (int i=0;i<ROM.NLEN-1;i++)
-			w[i]=(w[i]>>k)|((w[i+1]<<(ROM.BASEBITS-k))&ROM.MASK);
-		w[ROM.NLEN-1]=w[ROM.NLEN-1]>>k;
-		return r;
-	}
-
-/* general shift right */
-	public void shr(int k) {
-		int n=k%ROM.BASEBITS;
-		int m=k/ROM.BASEBITS;
-		for (int i=0;i<ROM.NLEN-m-1;i++)
-			w[i]=(w[m+i]>>n)|((w[m+i+1]<<(ROM.BASEBITS-n))&ROM.MASK);
-		w[ROM.NLEN-m-1]=w[ROM.NLEN-1]>>n;
-		for (int i=ROM.NLEN-m;i<ROM.NLEN;i++) w[i]=0;
-	}
-
-/* Shift right by less than a word */
-	public long fshl(int k) {
-		w[ROM.NLEN-1]=((w[ROM.NLEN-1]<<k))|(w[ROM.NLEN-2]>>(ROM.BASEBITS-k));
-		for (int i=ROM.NLEN-2;i>0;i--)
-			w[i]=((w[i]<<k)&ROM.MASK)|(w[i-1]>>(ROM.BASEBITS-k));
-		w[0]=(w[0]<<k)&ROM.MASK;
-		return (w[ROM.NLEN-1]>>((8*ROM.MODBYTES)%ROM.BASEBITS)); /* return excess - only used in ff.c */
-	}
-
-/* general shift left */
-	public void shl(int k) {
-		int n=k%ROM.BASEBITS;
-		int m=k/ROM.BASEBITS;
-
-		w[ROM.NLEN-1]=((w[ROM.NLEN-1-m]<<n))|(w[ROM.NLEN-m-2]>>(ROM.BASEBITS-n));
-		for (int i=ROM.NLEN-2;i>m;i--)
-			w[i]=((w[i-m]<<n)&ROM.MASK)|(w[i-m-1]>>(ROM.BASEBITS-n));
-		w[m]=(w[0]<<n)&ROM.MASK;
-		for (int i=0;i<m;i++) w[i]=0;
-	}
-
-/* return number of bits */
-	public int nbits() {
-		int bts,k=ROM.NLEN-1;
-		long c;
-		norm();
-		while (k>=0 && w[k]==0) k--;
-		if (k<0) return 0;
-		bts=ROM.BASEBITS*k;
-		c=w[k];
-		while (c!=0) {c/=2; bts++;}
-		return bts;
-	}
-
-	public String toRawString()
-	{
-		BIG b=new BIG(this);
-		String s="(";
-		for (int i=0;i<ROM.NLEN-1;i++)
-		{
-			s+=Long.toHexString(b.w[i]); s+=",";
-		}
-		s+=Long.toHexString(b.w[ROM.NLEN-1]); s+=")";
-		return s;
-	}
-
-/* Convert to Hex String */
-	public String toString() {
-		BIG b;
-		String s="";
-		int len=nbits();
-
-		if (len%4==0) len/=4;
-		else {len/=4; len++;}
-		if (len<ROM.MODBYTES*2) len=ROM.MODBYTES*2;
-
-		for (int i=len-1;i>=0;i--)
-		{
-			b=new BIG(this);
-			b.shr(i*4);
-			s+=Long.toHexString(b.w[0]&15);
-		}
-		return s;
-	}
-
-/* return this+x */
-	public BIG plus(BIG x) {
-		BIG s=new BIG(0);
-		for (int i=0;i<ROM.NLEN;i++)
-			s.w[i]=w[i]+x.w[i];
-		return s;
-	}
-
-/* this+=x */
-	public void add(BIG x) {
-		for (int i=0;i<ROM.NLEN;i++)
-			w[i]+=x.w[i];
-	}
-
-/* this+=x, where x is int */
-	public void inc(int x) {
-		norm();
-		w[0]+=x;
-	}
-
-/* return this.x */
-	public BIG minus(BIG x) {
-		BIG d=new BIG(0);
-		for (int i=0;i<ROM.NLEN;i++)
-			d.w[i]=w[i]-x.w[i];
-		return d;
-	}
-
-/* this-=x */
-	public void sub(BIG x) {
-		for (int i=0;i<ROM.NLEN;i++)
-			w[i]-=x.w[i];
-	}
-
-/* reverse subtract this=x-this */
-	public void rsub(BIG x) {
-		for (int i=0;i<ROM.NLEN;i++)
-			w[i]=x.w[i]-w[i];
-	}
-
-/* this-=x where x is int */
-	public void dec(int x) {
-		norm();
-		w[0]-=(long)x;
-	}
-
-/* this*=x, where x is small int<NEXCESS */
-	public void imul(int c)
-	{
-		for (int i=0;i<ROM.NLEN;i++) w[i]*=c;
-	}
-
-/* convert this BIG to byte array */
-	public void tobytearray(byte[] b,int n)
-	{
-		norm();
-		BIG c=new BIG(this);
-
-		for (int i=ROM.MODBYTES-1;i>=0;i--)
-		{
-			b[i+n]=(byte)c.w[0];
-			c.fshr(8);
-		}
-	}
-
-/* convert from byte array to BIG */
-	public static BIG frombytearray(byte[] b,int n)
-	{
-		BIG m=new BIG(0);
-
-		for (int i=0;i<ROM.MODBYTES;i++)
-		{
-			m.fshl(8); m.w[0]+=(int)b[i+n]&0xff;
-			//m.inc((int)b[i]&0xff);
-		}
-		return m;
-	}
-
-	public void toBytes(byte[] b)
-	{
-		tobytearray(b,0);
-	}
-
-	public static BIG fromBytes(byte[] b)
-	{
-		return frombytearray(b,0);
-	}
-
-
-/* set this[i]+=x*y+c, and return high part */
-
-	public long muladd(long a,long b,long c,int i)
-	{
-		long x0,x1,y0,y1;
-		x0=a&ROM.HMASK;
-		x1=(a>>ROM.HBITS);
-		y0=b&ROM.HMASK;
-		y1=(b>>ROM.HBITS);
-		long bot=x0*y0;
-		long top=x1*y1;
-		long mid=x0*y1+x1*y0;
-		x0=mid&ROM.HMASK;
-		x1=(mid>>ROM.HBITS);
-		bot+=x0<<ROM.HBITS; bot+=c; bot+=w[i];
-		top+=x1;
-		long carry=bot>>ROM.BASEBITS;
-		bot&=ROM.MASK;
-		top+=carry;
-		w[i]=bot;
-		return top;
-	}
-
-/* this*=x, where x is >NEXCESS */
-	public long pmul(int c)
-	{
-		long ak,carry=0;
-		norm();
-		for (int i=0;i<ROM.NLEN;i++)
-		{
-			ak=w[i];
-			w[i]=0;
-			carry=muladd(ak,(long)c,carry,i);
-		}
-		return carry;
-	}
-
-/* this*=c and catch overflow in DBIG */
-	public DBIG pxmul(int c)
-	{
-		DBIG m=new DBIG(0);
-		long carry=0;
-		for (int j=0;j<ROM.NLEN;j++)
-			carry=m.muladd(w[j],(long)c,carry,j);
-		m.w[ROM.NLEN]=carry;
-		return m;
-	}
-
-/* divide by 3 */
-	public int div3()
-	{
-		long ak,base,carry=0;
-		norm();
-		base=((long)1<<ROM.BASEBITS);
-		for (int i=ROM.NLEN-1;i>=0;i--)
-		{
-			ak=(carry*base+w[i]);
-			w[i]=ak/3;
-			carry=ak%3;
-		}
-		return (int)carry;
-	}
-
-/* return a*b where result fits in a BIG */
-	public static BIG smul(BIG a,BIG b)
-	{
-		long carry;
-		BIG c=new BIG(0);
-		for (int i=0;i<ROM.NLEN;i++)
-		{
-			carry=0;
-			for (int j=0;j<ROM.NLEN;j++)
-				if (i+j<ROM.NLEN) carry=c.muladd(a.w[i],b.w[j],carry,i+j);
-		}
-		return c;
-	}
-
-/* Compare a and b, return 0 if a==b, -1 if a<b, +1 if a>b. Inputs must be normalised */
-	public static int comp(BIG a,BIG b)
-	{
-		for (int i=ROM.NLEN-1;i>=0;i--)
-		{
-			if (a.w[i]==b.w[i]) continue;
-			if (a.w[i]>b.w[i]) return 1;
-			else  return -1;
-		}
-		return 0;
-	}
-
-/* set x = x mod 2^m */
-	public void mod2m(int m)
-	{
-		int i,wd,bt;
-		long msk;
-
-		wd=m/ROM.BASEBITS;
-		bt=m%ROM.BASEBITS;
-		msk=((long)1<<bt)-1;
-		w[wd]&=msk;
-		for (i=wd+1;i<ROM.NLEN;i++) w[i]=0;
-	}
-
-/* Arazi and Qi inversion mod 256 */
-	public static int invmod256(int a)
-	{
-		int U,t1,t2,b,c;
-		t1=0;
-		c=(a>>1)&1;
-		t1+=c;
-		t1&=1;
-		t1=2-t1;
-		t1<<=1;
-		U=t1+1;
-
-// i=2
-		b=a&3;
-		t1=U*b; t1>>=2;
-		c=(a>>2)&3;
-		t2=(U*c)&3;
-		t1+=t2;
-		t1*=U; t1&=3;
-		t1=4-t1;
-		t1<<=2;
-		U+=t1;
-
-// i=4
-		b=a&15;
-		t1=U*b; t1>>=4;
-		c=(a>>4)&15;
-		t2=(U*c)&15;
-		t1+=t2;
-		t1*=U; t1&=15;
-		t1=16-t1;
-		t1<<=4;
-		U+=t1;
-
-		return U;
-	}
-
-/* a=1/a mod 2^256. This is very fast! */
-	public void invmod2m()
-	{
-		int i;
-		BIG U=new BIG(0);
-		BIG b=new BIG(0);
-		BIG c=new BIG(0);;
-
-		U.inc(invmod256(lastbits(8)));
-
-		for (i=8;i<256;i<<=1)
-		{
-			b.copy(this); b.mod2m(i);
-			BIG t1=BIG.smul(U,b); t1.shr(i);
-			c.copy(this); c.shr(i); c.mod2m(i);
-
-			BIG t2=BIG.smul(U,c); t2.mod2m(i);
-			t1.add(t2);
-			b=BIG.smul(t1,U); t1.copy(b);
-			t1.mod2m(i);
-
-			t2.one(); t2.shl(i); t1.rsub(t2); t1.norm();
-			t1.shl(i);
-			U.add(t1);
-		}
-		this.copy(U);
-	}
-
-/* reduce this mod m */
-	public void mod(BIG m)
-	{
-		int k=0;
-
-		norm();
-		if (comp(this,m)<0) return;
-		do
-		{
-			m.fshl(1);
-			k++;
-		} while (comp(this,m)>=0);
-
-		while (k>0)
-		{
-			m.fshr(1);
-			if (comp(this,m)>=0)
-			{
-				sub(m);
-				norm();
-			}
-			k--;
-		}
-	}
-
-/* divide this by m */
-	public void div(BIG m)
-	{
-		int k=0;
-		norm();
-		BIG e=new BIG(1);
-		BIG b=new BIG(this);
-		zero();
-
-		while (comp(b,m)>=0)
-		{
-			e.fshl(1);
-			m.fshl(1);
-			k++;
-		}
-
-		while (k>0)
-		{
-			m.fshr(1);
-			e.fshr(1);
-			if (comp(b,m)>=0)
-			{
-				add(e);
-				norm();
-				b.sub(m);
-				b.norm();
-			}
-			k--;
-		}
-	}
-
-/* return parity */
-	public int parity()
-	{
-		return (int)(w[0]%2);
-	}
-
-/* return n-th bit */
-	public int bit(int n)
-	{
-		if ((w[n/ROM.BASEBITS]&((long)1<<(n%ROM.BASEBITS)))>0) return 1;
-		else return 0;
-	}
-
-/* return n last bits */
-	public int lastbits(int n)
-	{
-		int msk=(1<<n)-1;
-		norm();
-		return ((int)w[0])&msk;
-	}
-
-/* get 8*MODBYTES size random number */
-	public static BIG random(RAND rng)
-	{
-		BIG m=new BIG(0);
-		int i,b,j=0,r=0;
-
-/* generate random BIG */
-		for (i=0;i<8*ROM.MODBYTES;i++)
-		{
-			if (j==0) r=rng.getByte();
-			else r>>=1;
-
-			b=r&1;
-			m.shl(1); m.w[0]+=b;// m.inc(b);
-			j++; j&=7;
-		}
-		return m;
-	}
-
-/* Create random BIG in portable way, one bit at a time */
-	public static BIG randomnum(BIG q,RAND rng)
-	{
-		DBIG d=new DBIG(0);
-		int i,b,j=0,r=0;
-		for (i=0;i<2*ROM.MODBITS;i++)
-		{
-			if (j==0) r=rng.getByte();
-			else r>>=1;
-
-			b=r&1;
-			d.shl(1); d.w[0]+=b;// m.inc(b);
-			j++; j&=7;
-		}
-		BIG m=d.mod(q);
-		return m;
-	}
-
-/* return NAF value as +/- 1, 3 or 5. x and x3 should be normed.
-nbs is number of bits processed, and nzs is number of trailing 0s detected */
-	public static int[] nafbits(BIG x,BIG x3,int i)
-	{
-		int[] n=new int[3];
-		int nb=x3.bit(i)-x.bit(i);
-		int j;
-		n[1]=1;
-		n[0]=0;
-		if (nb==0) {n[0]=0; return n;}
-		if (i==0) {n[0]=nb; return n;}
-	    if (nb>0) n[0]=1;
-		else      n[0]=(-1);
-
-		for (j=i-1;j>0;j--)
-		{
-			n[1]++;
-			n[0]*=2;
-			nb=x3.bit(j)-x.bit(j);
-			if (nb>0) n[0]+=1;
-			if (nb<0) n[0]-=1;
-			if (n[0]>5 || n[0]<-5) break;
-		}
-
-		if (n[0]%2!=0 && j!=0)
-		{ /* backtrack */
-			if (nb>0) n[0]=(n[0]-1)/2;
-			if (nb<0) n[0]=(n[0]+1)/2;
-			n[1]--;
-		}
-		while (n[0]%2==0)
-		{ /* remove trailing zeros */
-			n[0]/=2;
-			n[2]++;
-			n[1]--;
-		}
-		return n;
-	}
-
-/* return a*b as DBIG */
-	public static DBIG mul(BIG a,BIG b)
-	{
-		DBIG c=new DBIG(0);
-		long carry;
-		a.norm();
-		b.norm();
-
-		for (int i=0;i<ROM.NLEN;i++)
-		{
-			carry=0;
-			for (int j=0;j<ROM.NLEN;j++)
-				carry=c.muladd(a.w[i],b.w[j],carry,i+j);
-			c.w[ROM.NLEN+i]=carry;
-		}
-
-		return c;
-	}
-
-/* return a^2 as DBIG */
-	public static DBIG sqr(BIG a)
-	{
-		DBIG c=new DBIG(0);
-		long carry;
-		a.norm();
-		for (int i=0;i<ROM.NLEN;i++)
-		{
-			carry=0;
-			for (int j=i+1;j<ROM.NLEN;j++)
-				carry=c.muladd(2*a.w[i],a.w[j],carry,i+j);
-			c.w[ROM.NLEN+i]=carry;
-		}
-
-		for (int i=0;i<ROM.NLEN;i++)
-			c.w[2*i+1]+=c.muladd(a.w[i],a.w[i],0,2*i);
-
-		c.norm();
-		return c;
-	}
-
-/* reduce a DBIG to a BIG using the appropriate form of the modulus */
-	public static BIG mod(DBIG d)
-	{
-		BIG b;
-		if (ROM.MODTYPE==ROM.PSEUDO_MERSENNE)
-		{
-			long v,tw;
-			BIG t=d.split(ROM.MODBITS);
-			b=new BIG(d);
-
-			v=t.pmul((int)ROM.MConst);
-			tw=t.w[ROM.NLEN-1];
-			t.w[ROM.NLEN-1]&=ROM.TMASK;
-			t.w[0]+=(ROM.MConst*((tw>>ROM.TBITS)+(v<<(ROM.BASEBITS-ROM.TBITS))));
-
-			b.add(t);
-			b.norm();
-		}
-		if (ROM.MODTYPE==ROM.MONTGOMERY_FRIENDLY)
-		{
-			for (int i=0;i<ROM.NLEN;i++)
-				d.w[ROM.NLEN+i]+=d.muladd(d.w[i],ROM.MConst-1,d.w[i],ROM.NLEN+i-1);
-
-			b=new BIG(0);
-
-			for (int i=0;i<ROM.NLEN;i++ )
-				b.w[i]=d.w[ROM.NLEN+i];
-			b.norm();
-		}
-
-		if (ROM.MODTYPE==ROM.NOT_SPECIAL)
-		{
-			BIG md=new BIG(ROM.Modulus);
-			long m,carry;
-			for (int i=0;i<ROM.NLEN;i++)
-			{
-				if (ROM.MConst==-1) m=(-d.w[i])&ROM.MASK;
-				else
-				{
-					if (ROM.MConst==1) m=d.w[i];
-					else m=(ROM.MConst*d.w[i])&ROM.MASK;
-				}
-
-				carry=0;
-				for (int j=0;j<ROM.NLEN;j++)
-					carry=d.muladd(m,md.w[j],carry,i+j);
-				d.w[ROM.NLEN+i]+=carry;
-			}
-
-			b=new BIG(0);
-			for (int i=0;i<ROM.NLEN;i++ )
-				b.w[i]=d.w[ROM.NLEN+i];
-			b.norm();
-		}
-
-		return b;
-	}
-
-/* return a*b mod m */
-	public static BIG modmul(BIG a,BIG b,BIG m)
-	{
-		a.mod(m);
-		b.mod(m);
-		DBIG d=mul(a,b);
-		return d.mod(m);
-	}
-
-/* return a^2 mod m */
-	public static BIG modsqr(BIG a,BIG m)
-	{
-		a.mod(m);
-		DBIG d=sqr(a);
-		return d.mod(m);
-	}
-
-/* return -a mod m */
-	public static BIG modneg(BIG a,BIG m)
-	{
-		a.mod(m);
-		return m.minus(a);
-	}
-
-/* return this^e mod m */
-	public BIG powmod(BIG e,BIG m)
-	{
-		int bt;
-		norm();
-		e.norm();
-		BIG a=new BIG(1);
-		BIG z=new BIG(e);
-		BIG s=new BIG(this);
-		while (true)
-		{
-			bt=z.parity();
-			z.fshr(1);
-			if (bt==1) a=modmul(a,s,m);
-			if (z.iszilch()) break;
-			s=modsqr(s,m);
-		}
-		return a;
-	}
-
-/* Jacobi Symbol (this/p). Returns 0, 1 or -1 */
-	public int jacobi(BIG p)
-	{
-		int n8,k,m=0;
-		BIG t=new BIG(0);
-		BIG x=new BIG(0);
-		BIG n=new BIG(0);
-		BIG zilch=new BIG(0);
-		BIG one=new BIG(1);
-		if (p.parity()==0 || comp(this,zilch)==0 || comp(p,one)<=0) return 0;
-		norm();
-		x.copy(this);
-		n.copy(p);
-		x.mod(p);
-
-		while (comp(n,one)>0)
-		{
-			if (comp(x,zilch)==0) return 0;
-			n8=n.lastbits(3);
-			k=0;
-			while (x.parity()==0)
-			{
-				k++;
-				x.shr(1);
-			}
-			if (k%2==1) m+=(n8*n8-1)/8;
-			m+=(n8-1)*(x.lastbits(2)-1)/4;
-			t.copy(n);
-			t.mod(x);
-			n.copy(x);
-			x.copy(t);
-			m%=2;
-
-		}
-		if (m==0) return 1;
-		else return -1;
-	}
-
-/* this=1/this mod p. Binary method */
-	public void invmodp(BIG p)
-	{
-		mod(p);
-		BIG u=new BIG(this);
-
-		BIG v=new BIG(p);
-		BIG x1=new BIG(1);
-		BIG x2=new BIG(0);
-		BIG t=new BIG(0);
-		BIG one=new BIG(1);
-		while (comp(u,one)!=0 && comp(v,one)!=0)
-		{
-			while (u.parity()==0)
-			{
-				u.shr(1);
-				if (x1.parity()!=0)
-				{
-					x1.add(p);
-					x1.norm();
-				}
-				x1.shr(1);
-			}
-			while (v.parity()==0)
-			{
-				v.shr(1);
-				if (x2.parity()!=0)
-				{
-					x2.add(p);
-					x2.norm();
-				}
-				x2.shr(1);
-			}
-			if (comp(u,v)>=0)
-			{
-				u.sub(v);
-				u.norm();
-				if (comp(x1,x2)>=0) x1.sub(x2);
-				else
-				{
-					t.copy(p);
-					t.sub(x2);
-					x1.add(t);
-				}
-				x1.norm();
-			}
-			else
-			{
-				v.sub(u);
-				v.norm();
-				if (comp(x2,x1)>=0) x2.sub(x1);
-				else
-				{
-					t.copy(p);
-					t.sub(x1);
-					x2.add(t);
-				}
-				x2.norm();
-			}
-		}
-		if (comp(u,one)==0) copy(x1);
-		else copy(x2);
-	}
-}
diff --git a/java64/DBIG.java b/java64/DBIG.java
deleted file mode 100755
index 02e64ef..0000000
--- a/java64/DBIG.java
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
-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.
-*/
-
-/* AMCL double length DBIG number class */
-
-public class DBIG {
-	protected long[] w=new long[ROM.DNLEN];
-
-/* Constructors */
-	public DBIG(int x)
-	{
-		w[0]=x;
-		for (int i=1;i<ROM.DNLEN;i++)
-			w[i]=0;
-	}
-
-	public DBIG(DBIG x)
-	{
-		for (int i=0;i<ROM.DNLEN;i++)
-			w[i]=x.w[i];
-	}
-
-	public DBIG(BIG x)
-	{
-		for (int i=0;i<ROM.NLEN-1;i++)
-			w[i]=x.get(i);
-
-		w[ROM.NLEN-1]=x.get(ROM.NLEN-1)&ROM.MASK; /* top word normalized */
-		w[ROM.NLEN]=x.get(ROM.NLEN-1)>>ROM.BASEBITS;
-
-		for (int i=ROM.NLEN+1;i<ROM.DNLEN;i++) w[i]=0;
-	}
-
-/* get and set digits of this */
-	public long get(int i)
-	{
-		return w[i];
-	}
-
-	public void set(int i,long x)
-	{
-		w[i]=x;
-	}
-
-	public void inc(int i,long x)
-	{
-		w[i]+=x;
-	}
-
-/* test this=0? */
-	public boolean iszilch() {
-		for (int i=0;i<ROM.DNLEN;i++)
-			if (w[i]!=0) return false;
-		return true;
-	}
-
-/* normalise this */
-	public void norm() {
-		long d,carry=0;
-		for (int i=0;i<ROM.DNLEN-1;i++)
-		{
-			d=w[i]+carry;
-			w[i]=d&ROM.MASK;
-			carry=d>>ROM.BASEBITS;
-		}
-		w[ROM.DNLEN-1]=(w[ROM.DNLEN-1]+carry);
-	}
-
-/* shift this right by k bits */
-	public void shr(int k) {
-		int n=k%ROM.BASEBITS;
-		int m=k/ROM.BASEBITS;
-		for (int i=0;i<ROM.DNLEN-m-1;i++)
-			w[i]=(w[m+i]>>n)|((w[m+i+1]<<(ROM.BASEBITS-n))&ROM.MASK);
-		w[ROM.DNLEN-m-1]=w[ROM.DNLEN-1]>>n;
-		for (int i=ROM.DNLEN-m;i<ROM.DNLEN;i++) w[i]=0;
-	}
-
-/* shift this left by k bits */
-	public void shl(int k) {
-		int n=k%ROM.BASEBITS;
-		int m=k/ROM.BASEBITS;
-
-		w[ROM.DNLEN-1]=((w[ROM.DNLEN-1-m]<<n))|(w[ROM.DNLEN-m-2]>>(ROM.BASEBITS-n));
-		for (int i=ROM.DNLEN-2;i>m;i--)
-			w[i]=((w[i-m]<<n)&ROM.MASK)|(w[i-m-1]>>(ROM.BASEBITS-n));
-		w[m]=(w[0]<<n)&ROM.MASK;
-		for (int i=0;i<m;i++) w[i]=0;
-	}
-
-/* return number of bits in this */
-	public int nbits() {
-		int bts,k=ROM.DNLEN-1;
-		long c;
-		norm();
-		while (w[k]==0 && k>=0) k--;
-		if (k<0) return 0;
-		bts=ROM.BASEBITS*k;
-		c=w[k];
-		while (c!=0) {c/=2; bts++;}
-		return bts;
-	}
-
-/* convert this to string */
-	public String toString() {
-		DBIG b;
-		String s="";
-		int len=nbits();
-		if (len%4==0) len>>=2; //len/=4;
-		else {len>>=2; len++;}
-
-		for (int i=len-1;i>=0;i--)
-		{
-			b=new DBIG(this);
-			b.shr(i*4);
-			s+=Long.toHexString(b.w[0]&15);
-		}
-		return s;
-	}
-
-/* return this+x */
-/*
-	public DBIG plus(DBIG x) {
-		DBIG s=new DBIG(0);
-		for (int i=0;i<ROM.DNLEN;i++)
-			s.w[i]=w[i]+x.w[i];
-		return s;
-	}
-*/
-/* return this-x */
-/*
-	public DBIG minus(DBIG x) {
-		DBIG d=new DBIG(0);
-		for (int i=0;i<ROM.DNLEN;i++)
-			d.w[i]=w[i]-x.w[i];
-		return d;
-	}
-*/
-/* this+=x */
-	public void add(DBIG x) {
-		for (int i=0;i<ROM.DNLEN;i++)
-			w[i]+=x.w[i];
-	}
-
-/* this-=x */
-	public void sub(DBIG x) {
-		for (int i=0;i<ROM.DNLEN;i++)
-			w[i]-=x.w[i];
-	}
-
-/* set this[i]+=x*y+c, and return high part */
-/* This is time critical */
-/* What if you knew the bottom half in advance ?? */
-	public long muladd(long a,long b,long c,int i)
-	{
-		long x0,x1,y0,y1;
-		x0=a&ROM.HMASK;
-		x1=(a>>ROM.HBITS);
-		y0=b&ROM.HMASK;
-		y1=(b>>ROM.HBITS);
-		long bot=x0*y0;
-		long top=x1*y1;
-		long mid=x0*y1+x1*y0;
-		x0=mid&ROM.HMASK;
-		x1=(mid>>ROM.HBITS);
-		bot+=x0<<ROM.HBITS; bot+=c; bot+=w[i];
-		top+=x1;
-		long carry=bot>>ROM.BASEBITS;
-		bot&=ROM.MASK;
-		top+=carry;
-		w[i]=bot;
-		return top;
-	}
-
-/* Compare a and b, return 0 if a==b, -1 if a<b, +1 if a>b. Inputs must be normalised */
-	public static int comp(DBIG a,DBIG b)
-	{
-		for (int i=ROM.DNLEN-1;i>=0;i--)
-		{
-			if (a.w[i]==b.w[i]) continue;
-			if (a.w[i]>b.w[i]) return 1;
-			else  return -1;
-		}
-		return 0;
-	}
-
-/* reduces this DBIG mod a BIG, and returns the BIG */
-	public BIG mod(BIG c)
-	{
-		int k=0;
-		norm();
-		DBIG m=new DBIG(c);
-
-		if (comp(this,m)<0) return new BIG(this);
-
-		do
-		{
-			m.shl(1);
-			k++;
-		}
-		while (comp(this,m)>=0);
-
-		while (k>0)
-		{
-			m.shr(1);
-			if (comp(this,m)>=0)
-			{
-				sub(m);
-				norm();
-			}
-			k--;
-		}
-		return new BIG(this);
-	}
-
-/* reduces this DBIG mod a DBIG in place */
-/*	public void mod(DBIG m)
-	{
-		int k=0;
-		if (comp(this,m)<0) return;
-
-		do
-		{
-			m.shl(1);
-			k++;
-		}
-		while (comp(this,m)>=0);
-
-		while (k>0)
-		{
-			m.shr(1);
-			if (comp(this,m)>=0)
-			{
-				sub(m);
-				norm();
-			}
-			k--;
-		}
-		return;
-
-	}*/
-
-/* return this/c */
-	public BIG div(BIG c)
-	{
-		int k=0;
-		DBIG m=new DBIG(c);
-		BIG a=new BIG(0);
-		BIG e=new BIG(1);
-		norm();
-
-		while (comp(this,m)>=0)
-		{
-			e.fshl(1);
-			m.shl(1);
-			k++;
-		}
-
-		while (k>0)
-		{
-			m.shr(1);
-			e.shr(1);
-			if (comp(this,m)>0)
-			{
-				a.add(e);
-				a.norm();
-				sub(m);
-				norm();
-			}
-			k--;
-		}
-		return a;
-	}
-
-/* split DBIG at position n, return higher half, keep lower half */
-	public BIG split(int n)
-	{
-		BIG t=new BIG(0);
-		int m=n%ROM.BASEBITS;
-		long nw,carry=w[ROM.DNLEN-1]<<(ROM.BASEBITS-m);
-
-		for (int i=ROM.DNLEN-2;i>=ROM.NLEN-1;i--)
-		{
-			nw=(w[i]>>m)|carry;
-			carry=(w[i]<<(ROM.BASEBITS-m))&ROM.MASK;
-			t.set(i-ROM.NLEN+1,nw);
-		}
-		w[ROM.NLEN-1]&=(((long)1<<m)-1);
-		return t;
-	}
-}
diff --git a/java64/ECDH.java b/java64/ECDH.java
deleted file mode 100755
index 35a9a18..0000000
--- a/java64/ECDH.java
+++ /dev/null
@@ -1,528 +0,0 @@
-/*
-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.
-*/
-
-/* Elliptic Curve API high-level functions  */
-
-public final class ECDH {
-	public static final int INVALID_PUBLIC_KEY=-2;
-	public static final int ERROR=-3;
-	public static final int INVALID=-4;
-	public static final int EFS=ROM.MODBYTES;
-	public static final int EGS=ROM.MODBYTES;
-	public static final int EAS=AES.KS;
-	public static final int EBS=AES.BS;
-
-/* Convert Integer to n-byte array */
-	private static byte[] inttoBytes(int n,int len)
-	{
-		int i;
-		byte[] b=new byte[len];
-
-		for (i=0;i<len;i++) b[i]=0;
-		i=len;
-		while (n>0 && i>0)
-		{
-			i--;
-			b[i]=(byte)(n&0xff);
-			n/=256;
-		}
-		return b;
-	}
-
-/* Key Derivation Functions */
-/* Input octet Z */
-/* Output key of length olen */
-	public static byte[] KDF1(byte[] Z,int olen)
-	{
-/* NOTE: the parameter olen is the length of the output K in bytes */
-		HASH H=new HASH();
-		int hlen=HASH.len;
-		byte[] K=new byte[olen];
-
-		byte[] B;
-		int counter,cthreshold,k=0;
-
-		for (int i=0;i<K.length;i++) K[i]=0;
-
-		cthreshold=olen/hlen; if (olen%hlen!=0) cthreshold++;
-
-		for (counter=0;counter<cthreshold;counter++)
-		{
-			H.process_array(Z); if (counter>0) H.process_num(counter);
-			B=H.hash();
-			if (k+hlen>olen) for (int i=0;i<olen%hlen;i++) K[k++]=B[i];
-			else for (int i=0;i<hlen;i++) K[k++]=B[i];
-		}
-		return K;
-	}
-
-	public static byte[] KDF2(byte[] Z,byte[] P,int olen)
-	{
-/* NOTE: the parameter olen is the length of the output k in bytes */
-		HASH H=new HASH();
-		int hlen=HASH.len;
-		byte[] K=new byte[olen];
-
-		byte[] B=new byte[hlen];
-		int counter,cthreshold,k=0;
-
-		for (int i=0;i<K.length;i++) K[i]=0;
-
-		cthreshold=olen/hlen; if (olen%hlen!=0) cthreshold++;
-
-		for (counter=1;counter<=cthreshold;counter++)
-		{
-			H.process_array(Z); H.process_num(counter); H.process_array(P);
-			B=H.hash();
-			if (k+hlen>olen) for (int i=0;i<olen%hlen;i++) K[k++]=B[i];
-			else for (int i=0;i<hlen;i++) K[k++]=B[i];
-		}
-		return K;
-	}
-
-/* Password based Key Derivation Function */
-/* Input password p, salt s, and repeat count */
-/* Output key of length olen */
-	public static byte[] PBKDF2(byte[] Pass,byte[] Salt,int rep,int olen)
-	{
-		int i,j,k,len,d,opt;
-		d=olen/32; if (olen%32!=0) d++;
-		byte[] F=new byte[EFS];
-		byte[] U=new byte[EFS];
-		byte[] S=new byte[Salt.length+4];
-
-		byte[] K=new byte[d*EFS];
-		opt=0;
-
-		for (i=1;i<=d;i++)
-		{
-			for (j=0;j<Salt.length;j++) S[j]=Salt[j];
-			byte[] N=inttoBytes(i,4);
-			for (j=0;j<4;j++) S[Salt.length+j]=N[j];
-
-			HMAC(S,Pass,F);
-
-			for (j=0;j<EFS;j++) U[j]=F[j];
-			for (j=2;j<=rep;j++)
-			{
-				HMAC(U,Pass,U);
-				for (k=0;k<EFS;k++) F[k]^=U[k];
-			}
-			for (j=0;j<EFS;j++) K[opt++]=F[j];
-		}
-		byte[] key=new byte[olen];
-		for (i=0;i<olen;i++) key[i]=K[i];
-		return key;
-	}
-
-/* Calculate HMAC of m using key k. HMAC is tag of length olen */
-	public static int HMAC(byte[] M,byte[] K,byte[] tag)
-	{
-	/* Input is from an octet m        *
-	* olen is requested output length in bytes. k is the key  *
-	* The output is the calculated tag */
-		int b;
-		byte[] B;
-		byte[] K0=new byte[64];
-		int olen=tag.length;
-
-		b=K0.length;
-		if (olen<4 || olen>HASH.len) return 0;
-
-		for (int i=0;i<b;i++) K0[i]=0;
-
-		HASH H=new HASH();
-
-		if (K.length > b)
-		{
-			H.process_array(K); B=H.hash();
-			for (int i=0;i<32;i++) K0[i]=B[i];
-		}
-		else
-			for (int i=0;i<K.length;i++ ) K0[i]=K[i];
-
-		for (int i=0;i<b;i++) K0[i]^=0x36;
-		H.process_array(K0); H.process_array(M); B=H.hash();
-
-		for (int i=0;i<b;i++) K0[i]^=0x6a;
-		H.process_array(K0); H.process_array(B); B=H.hash();
-
-		for (int i=0;i<olen;i++) tag[i]=B[i];
-
-		return 1;
-	}
-
-/* AES encryption/decryption. Encrypt byte array M using key K and returns ciphertext */
-	public static byte[] AES_CBC_IV0_ENCRYPT(byte[] K,byte[] M)
-	{ /* AES CBC encryption, with Null IV and key K */
-	/* Input is from an octet string M, output is to an octet string C */
-	/* Input is padded as necessary to make up a full final block */
-		AES a=new AES();
-		boolean fin;
-		int i,j,ipt,opt;
-		byte[] buff=new byte[16];
-		int clen=16+(M.length/16)*16;
-
-		byte[] C=new byte[clen];
-		int padlen;
-
-		a.init(AES.CBC,K,null);
-
-		ipt=opt=0;
-		fin=false;
-		for(;;)
-		{
-			for (i=0;i<16;i++)
-			{
-				if (ipt<M.length) buff[i]=M[ipt++];
-				else {fin=true; break;}
-			}
-			if (fin) break;
-			a.encrypt(buff);
-			for (i=0;i<16;i++)
-				C[opt++]=buff[i];
-		}
-
-/* last block, filled up to i-th index */
-
-		padlen=16-i;
-		for (j=i;j<16;j++) buff[j]=(byte)padlen;
-
-		a.encrypt(buff);
-
-		for (i=0;i<16;i++)
-			C[opt++]=buff[i];
-		a.end();
-		return C;
-	}
-
-/* returns plaintext if all consistent, else returns null string */
-	public static byte[] AES_CBC_IV0_DECRYPT(byte[] K,byte[] C)
-	{ /* padding is removed */
-		AES a=new AES();
-		int i,ipt,opt,ch;
-		byte[] buff=new byte[16];
-		byte[] MM=new byte[C.length];
-		boolean fin,bad;
-		int padlen;
-		ipt=opt=0;
-
-		a.init(AES.CBC,K,null);
-
-		if (C.length==0) return new byte[0];
-		ch=C[ipt++];
-
-		fin=false;
-
-		for(;;)
-		{
-			for (i=0;i<16;i++)
-			{
-				buff[i]=(byte)ch;
-				if (ipt>=C.length) {fin=true; break;}
-				else ch=C[ipt++];
-			}
-			a.decrypt(buff);
-			if (fin) break;
-			for (i=0;i<16;i++)
-				MM[opt++]=buff[i];
-		}
-
-		a.end();
-		bad=false;
-		padlen=buff[15];
-		if (i!=15 || padlen<1 || padlen>16) bad=true;
-		if (padlen>=2 && padlen<=16)
-			for (i=16-padlen;i<16;i++) if (buff[i]!=padlen) bad=true;
-
-		if (!bad) for (i=0;i<16-padlen;i++)
-					MM[opt++]=buff[i];
-
-		if (bad) return new byte[0];
-
-		byte[] M=new byte[opt];
-		for (i=0;i<opt;i++) M[i]=MM[i];
-
-		return M;
-	}
-
-/* Calculate a public/private EC GF(p) key pair W,S where W=S.G mod EC(p),
- * where S is the secret key and W is the public key
- * and G is fixed generator.
- * If RNG is NULL then the private key is provided externally in S
- * otherwise it is generated randomly internally */
-	public static int KEY_PAIR_GENERATE(RAND RNG,byte[] S,byte[] W)
-	{
-		BIG r,gx,gy,s,wx,wy;
-		ECP G,WP;
-		int res=0;
-		byte[] T=new byte[EFS];
-
-		gx=new BIG(ROM.CURVE_Gx);
-		if (ROM.CURVETYPE!=ROM.MONTGOMERY)
-		{
-			gy=new BIG(ROM.CURVE_Gy);
-			G=new ECP(gx,gy);
-		}
-		else
-			G=new ECP(gx);
-
-		r=new BIG(ROM.CURVE_Order);
-
-		if (RNG==null)
-		{
-			s=BIG.fromBytes(S);
-		}
-		else
-		{
-			s=BIG.randomnum(r,RNG);
-
-			s.toBytes(T);
-			for (int i=0;i<EGS;i++) S[i]=T[i];
-		}
-
-		WP=G.mul(s);
-		WP.toBytes(W);
-
-		return res;
-	}
-
-/* validate public key. Set full=true for fuller check */
-	public static int PUBLIC_KEY_VALIDATE(boolean full,byte[] W)
-	{
-		BIG r;
-		ECP WP=ECP.fromBytes(W);
-		int res=0;
-
-		r=new BIG(ROM.CURVE_Order);
-
-		if (WP.is_infinity()) res=INVALID_PUBLIC_KEY;
-		if (res==0 && full)
-		{
-			WP=WP.mul(r);
-			if (!WP.is_infinity()) res=INVALID_PUBLIC_KEY;
-		}
-		return res;
-	}
-
-/* IEEE-1363 Diffie-Hellman online calculation Z=S.WD */
-	public static int ECPSVDP_DH(byte[] S,byte[] WD,byte[] Z)
-	{
-		BIG r,s,wx,wy,z;
-		int valid;
-		ECP W;
-		int res=0;
-		byte[] T=new byte[EFS];
-
-		s=BIG.fromBytes(S);
-
-		W=ECP.fromBytes(WD);
-		if (W.is_infinity()) res=ERROR;
-
-		if (res==0)
-		{
-			r=new BIG(ROM.CURVE_Order);
-			s.mod(r);
-			W=W.mul(s);
-			if (W.is_infinity()) res=ERROR;
-			else
-			{
-				W.getX().toBytes(T);
-				for (int i=0;i<EFS;i++) Z[i]=T[i];
-			}
-		}
-		return res;
-	}
-
-/* IEEE ECDSA Signature, C and D are signature on F using private key S */
-	public static int ECPSP_DSA(RAND RNG,byte[] S,byte[] F,byte[] C,byte[] D)
-	{
-		byte[] T=new byte[EFS];
-		BIG gx,gy,r,s,f,c,d,u,vx;
-		ECP G,V;
-
-		HASH H=new HASH();
-		H.process_array(F);
-		byte[] B=H.hash();
-
-		gx=new BIG(ROM.CURVE_Gx);
-		gy=new BIG(ROM.CURVE_Gy);
-
-		G=new ECP(gx,gy);
-		r=new BIG(ROM.CURVE_Order);
-
-		s=BIG.fromBytes(S);
-		f=BIG.fromBytes(B);
-
-		c=new BIG(0);
-		d=new BIG(0);
-		V=new ECP();
-
-		do {
-			u=BIG.randomnum(r,RNG);
-
-			V.copy(G);
-			V=V.mul(u);
-			vx=V.getX();
-			c.copy(vx);
-			c.mod(r);
-			if (c.iszilch()) continue;
-			u.invmodp(r);
-			d.copy(BIG.modmul(s,c,r));
-			d.add(f);
-			d.copy(BIG.modmul(u,d,r));
-		} while (d.iszilch());
-
-		c.toBytes(T);
-		for (int i=0;i<EFS;i++) C[i]=T[i];
-		d.toBytes(T);
-		for (int i=0;i<EFS;i++) D[i]=T[i];
-		return 0;
-	}
-
-/* IEEE1363 ECDSA Signature Verification. Signature C and D on F is verified using public key W */
-	public static int ECPVP_DSA(byte[] W,byte[] F, byte[] C,byte[] D)
-	{
-		BIG r,gx,gy,f,c,d,h2;
-		int res=0;
-		ECP G,WP,P;
-		int valid;
-
-		HASH H=new HASH();
-		H.process_array(F);
-		byte[] B=H.hash();
-
-		gx=new BIG(ROM.CURVE_Gx);
-		gy=new BIG(ROM.CURVE_Gy);
-
-		G=new ECP(gx,gy);
-		r=new BIG(ROM.CURVE_Order);
-
-		c=BIG.fromBytes(C);
-		d=BIG.fromBytes(D);
-		f=BIG.fromBytes(B);
-
-		if (c.iszilch() || BIG.comp(c,r)>=0 || d.iszilch() || BIG.comp(d,r)>=0)
-            res=INVALID;
-
-		if (res==0)
-		{
-			d.invmodp(r);
-			f.copy(BIG.modmul(f,d,r));
-			h2=BIG.modmul(c,d,r);
-
-			WP=ECP.fromBytes(W);
-			if (WP.is_infinity()) res=ERROR;
-			else
-			{
-				P=new ECP();
-				P.copy(WP);
-				P=P.mul2(h2,G,f);
-				if (P.is_infinity()) res=INVALID;
-				else
-				{
-					d=P.getX();
-					d.mod(r);
-					if (BIG.comp(d,c)!=0) res=INVALID;
-				}
-			}
-		}
-
-		return res;
-	}
-
-/* IEEE1363 ECIES encryption. Encryption of plaintext M uses public key W and produces ciphertext V,C,T */
-	public static byte[] ECIES_ENCRYPT(byte[] P1,byte[] P2,RAND RNG,byte[] W,byte[] M,byte[] V,byte[] T)
-	{
-		int i,len;
-
-		byte[] Z=new byte[EFS];
-		byte[] VZ=new byte[3*EFS+1];
-		byte[] K1=new byte[EAS];
-		byte[] K2=new byte[EAS];
-		byte[] U=new byte[EGS];
-
-		if (KEY_PAIR_GENERATE(RNG,U,V)!=0) return new byte[0];
-		if (ECPSVDP_DH(U,W,Z)!=0) return new byte[0];
-
-		for (i=0;i<2*EFS+1;i++) VZ[i]=V[i];
-		for (i=0;i<EFS;i++) VZ[2*EFS+1+i]=Z[i];
-
-
-		byte[] K=KDF2(VZ,P1,EFS);
-
-		for (i=0;i<EAS;i++) {K1[i]=K[i]; K2[i]=K[EAS+i];}
-
-		byte[] C=AES_CBC_IV0_ENCRYPT(K1,M);
-
-		byte[] L2=inttoBytes(P2.length,8);
-
-		byte[] AC=new byte[C.length+P2.length+8];
-		for (i=0;i<C.length;i++) AC[i]=C[i];
-		for (i=0;i<P2.length;i++) AC[C.length+i]=P2[i];
-		for (i=0;i<8;i++) AC[C.length+P2.length+i]=L2[i];
-
-		HMAC(AC,K2,T);
-
-		return C;
-	}
-
-/* IEEE1363 ECIES decryption. Decryption of ciphertext V,C,T using private key U outputs plaintext M */
-	public static byte[] ECIES_DECRYPT(byte[] P1,byte[] P2,byte[] V,byte[] C,byte[] T,byte[] U)
-	{
-
-		int i,len;
-
-		byte[] Z=new byte[EFS];
-		byte[] VZ=new byte[3*EFS+1];
-		byte[] K1=new byte[EAS];
-		byte[] K2=new byte[EAS];
-		byte[] TAG=new byte[T.length];
-
-		if (ECPSVDP_DH(U,V,Z)!=0) return new byte[0];
-
-		for (i=0;i<2*EFS+1;i++) VZ[i]=V[i];
-		for (i=0;i<EFS;i++) VZ[2*EFS+1+i]=Z[i];
-
-		byte[] K=KDF2(VZ,P1,EFS);
-
-		for (i=0;i<EAS;i++) {K1[i]=K[i]; K2[i]=K[EAS+i];}
-
-		byte[] M=AES_CBC_IV0_DECRYPT(K1,C);
-
-		if (M.length==0) return M;
-
-		byte[] L2=inttoBytes(P2.length,8);
-
-		byte[] AC=new byte[C.length+P2.length+8];
-
-		for (i=0;i<C.length;i++) AC[i]=C[i];
-		for (i=0;i<P2.length;i++) AC[C.length+i]=P2[i];
-		for (i=0;i<8;i++) AC[C.length+P2.length+i]=L2[i];
-
-		HMAC(AC,K2,TAG);
-
-		boolean same=true;
-		for (i=0;i<T.length;i++) if (T[i]!=TAG[i]) same=false;
-		if (!same) return new byte[0];
-
-		return M;
-
-	}
-}
diff --git a/java64/ECP.java b/java64/ECP.java
deleted file mode 100755
index 01db5d8..0000000
--- a/java64/ECP.java
+++ /dev/null
@@ -1,929 +0,0 @@
-/*
-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.
-*/
-
-/* Elliptic Curve Point class */
-
-public final class ECP {
-	private FP x;
-	private FP y;
-	private FP z;
-	private boolean INF;
-
-/* Constructor - set to O */
-	public ECP() {
-		INF=true;
-		x=new FP(0);
-		y=new FP(1);
-		z=new FP(1);
-	}
-/* test for O point-at-infinity */
-	public boolean is_infinity() {
-		if (ROM.CURVETYPE==ROM.EDWARDS)
-		{
-			x.reduce(); y.reduce(); z.reduce();
-			return (x.iszilch() && y.equals(z));
-		}
-		else return INF;
-	}
-/* Conditional swap of P and Q dependant on d */
-	private void cswap(ECP Q,int d)
-	{
-		x.cswap(Q.x,d);
-		if (ROM.CURVETYPE!=ROM.MONTGOMERY) y.cswap(Q.y,d);
-		z.cswap(Q.z,d);
-		if (ROM.CURVETYPE!=ROM.EDWARDS)
-		{
-			boolean bd;
-			if (d==0) bd=false;
-			else bd=true;
-			bd=bd&(INF^Q.INF);
-			INF^=bd;
-			Q.INF^=bd;
-		}
-	}
-
-/* Conditional move of Q to P dependant on d */
-	private void cmove(ECP Q,int d)
-	{
-		x.cmove(Q.x,d);
-		if (ROM.CURVETYPE!=ROM.MONTGOMERY) y.cmove(Q.y,d);
-		z.cmove(Q.z,d);
-		if (ROM.CURVETYPE!=ROM.EDWARDS)
-		{
-			boolean bd;
-			if (d==0) bd=false;
-			else bd=true;
-			INF^=(INF^Q.INF)&bd;
-		}
-	}
-
-/* return 1 if b==c, no branching */
-	private static int teq(int b,int c)
-	{
-		int x=b^c;
-		x-=1;  // if x=0, x now -1
-		return ((x>>31)&1);
-	}
-
-/* Constant time select from pre-computed table */
-	private void select(ECP W[],int b)
-	{
-		ECP MP=new ECP();
-		int m=b>>31;
-		int babs=(b^m)-m;
-
-		babs=(babs-1)/2;
-
-		cmove(W[0],teq(babs,0));  // conditional move
-		cmove(W[1],teq(babs,1));
-		cmove(W[2],teq(babs,2));
-		cmove(W[3],teq(babs,3));
-		cmove(W[4],teq(babs,4));
-		cmove(W[5],teq(babs,5));
-		cmove(W[6],teq(babs,6));
-		cmove(W[7],teq(babs,7));
-
-		MP.copy(this);
-		MP.neg();
-		cmove(MP,(int)(m&1));
-	}
-
-
-/* Test P == Q */
-	public boolean equals(ECP Q) {
-		if (is_infinity() && Q.is_infinity()) return true;
-		if (is_infinity() || Q.is_infinity()) return false;
-		if (ROM.CURVETYPE==ROM.WEIERSTRASS)
-		{
-			FP zs2=new FP(z); zs2.sqr();
-			FP zo2=new FP(Q.z); zo2.sqr();
-			FP zs3=new FP(zs2); zs3.mul(z);
-			FP zo3=new FP(zo2); zo3.mul(Q.z);
-			zs2.mul(Q.x);
-			zo2.mul(x);
-			if (!zs2.equals(zo2)) return false;
-			zs3.mul(Q.y);
-			zo3.mul(y);
-			if (!zs3.equals(zo3)) return false;
-		}
-		else
-		{
-			FP a=new FP(0);
-			FP b=new FP(0);
-			a.copy(x); a.mul(Q.z); a.reduce();
-			b.copy(Q.x); b.mul(z); b.reduce();
-			if (!a.equals(b)) return false;
-			if (ROM.CURVETYPE==ROM.EDWARDS)
-			{
-				a.copy(y); a.mul(Q.z); a.reduce();
-				b.copy(Q.y); b.mul(z); b.reduce();
-				if (!a.equals(b)) return false;
-			}
-		}
-		return true;
-	}
-
-/* this=P */
-	public void copy(ECP P)
-	{
-		x.copy(P.x);
-		if (ROM.CURVETYPE!=ROM.MONTGOMERY) y.copy(P.y);
-		z.copy(P.z);
-		INF=P.INF;
-	}
-/* this=-this */
-	public void neg() {
-		if (is_infinity()) return;
-		if (ROM.CURVETYPE==ROM.WEIERSTRASS)
-		{
-			y.neg(); y.reduce();
-		}
-		if (ROM.CURVETYPE==ROM.EDWARDS)
-		{
-			x.neg(); x.reduce();
-		}
-		return;
-	}
-/* set this=O */
-	public void inf() {
-		INF=true;
-		x.zero();
-		y.one();
-		z.one();
-	//	y=new FP(1);
-	//	z=new FP(1);
-	}
-
-/* Calculate RHS of curve equation */
-	public static FP RHS(FP x) {
-		x.norm();
-		FP r=new FP(x);
-		r.sqr();
-
-		if (ROM.CURVETYPE==ROM.WEIERSTRASS)
-		{ // x^3+Ax+B
-			FP b=new FP(new BIG(ROM.CURVE_B));
-			r.mul(x);
-			if (ROM.CURVE_A==-3)
-			{
-				FP cx=new FP(x);
-				cx.imul(3);
-				cx.neg(); cx.norm();
-				r.add(cx);
-			}
-			r.add(b);
-		}
-		if (ROM.CURVETYPE==ROM.EDWARDS)
-		{ // (Ax^2-1)/(Bx^2-1)
-			FP b=new FP(new BIG(ROM.CURVE_B));
-
-			FP one=new FP(1);
-			b.mul(r);
-			b.sub(one);
-			if (ROM.CURVE_A==-1) r.neg();
-			r.sub(one);
-
-			b.inverse();
-
-			r.mul(b);
-		}
-		if (ROM.CURVETYPE==ROM.MONTGOMERY)
-		{ // x^3+Ax^2+x
-			FP x3=new FP(0);
-			x3.copy(r);
-			x3.mul(x);
-			r.imul(ROM.CURVE_A);
-			r.add(x3);
-			r.add(x);
-		}
-		r.reduce();
-		return r;
-	}
-
-/* set (x,y) from two BIGs */
-	public ECP(BIG ix,BIG iy) {
-		x=new FP(ix);
-		y=new FP(iy);
-		z=new FP(1);
-		FP rhs=RHS(x);
-
-		if (ROM.CURVETYPE==ROM.MONTGOMERY)
-		{
-			if (rhs.jacobi()==1) INF=false;
-			else inf();
-		}
-		else
-		{
-			FP y2=new FP(y);
-			y2.sqr();
-			if (y2.equals(rhs)) INF=false;
-			else inf();
-		}
-	}
-/* set (x,y) from BIG and a bit */
-	public ECP(BIG ix,int s) {
-		x=new FP(ix);
-		FP rhs=RHS(x);
-		y=new FP(0);
-		z=new FP(1);
-		if (rhs.jacobi()==1)
-		{
-			FP ny=rhs.sqrt();
-			if (ny.redc().parity()!=s) ny.neg();
-			y.copy(ny);
-			INF=false;
-		}
-		else inf();
-	}
-
-/* set from x - calculate y from curve equation */
-	public ECP(BIG ix) {
-		x=new FP(ix);
-		FP rhs=RHS(x);
-		y=new FP(0);
-		z=new FP(1);
-		if (rhs.jacobi()==1)
-		{
-			if (ROM.CURVETYPE!=ROM.MONTGOMERY) y.copy(rhs.sqrt());
-			INF=false;
-		}
-		else INF=true;
-	}
-
-/* set to affine - from (x,y,z) to (x,y) */
-	public void affine() {
-		if (is_infinity()) return;
-		FP one=new FP(1);
-		if (z.equals(one)) return;
-		z.inverse();
-		if (ROM.CURVETYPE==ROM.WEIERSTRASS)
-		{
-			FP z2=new FP(z);
-			z2.sqr();
-			x.mul(z2); x.reduce();
-			y.mul(z2);
-			y.mul(z);  y.reduce();
-		}
-		if (ROM.CURVETYPE==ROM.EDWARDS)
-		{
-			x.mul(z); x.reduce();
-			y.mul(z); y.reduce();
-		}
-		if (ROM.CURVETYPE==ROM.MONTGOMERY)
-		{
-			x.mul(z); x.reduce();
-		}
-		z.copy(one);
-	}
-/* extract x as a BIG */
-	public BIG getX()
-	{
-		affine();
-		return x.redc();
-	}
-/* extract y as a BIG */
-	public BIG getY()
-	{
-		affine();
-		return y.redc();
-	}
-
-/* get sign of Y */
-	public int getS()
-	{
-		affine();
-		BIG y=getY();
-		return y.parity();
-	}
-/* extract x as an FP */
-	public FP getx()
-	{
-		return x;
-	}
-/* extract y as an FP */
-	public FP gety()
-	{
-		return y;
-	}
-/* extract z as an FP */
-	public FP getz()
-	{
-		return z;
-	}
-/* convert to byte array */
-	public void toBytes(byte[] b)
-	{
-		byte[] t=new byte[ROM.MODBYTES];
-		if (ROM.CURVETYPE!=ROM.MONTGOMERY) b[0]=0x04;
-		else b[0]=0x02;
-
-		affine();
-		x.redc().toBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++) b[i+1]=t[i];
-		if (ROM.CURVETYPE!=ROM.MONTGOMERY)
-		{
-			y.redc().toBytes(t);
-			for (int i=0;i<ROM.MODBYTES;i++) b[i+ROM.MODBYTES+1]=t[i];
-		}
-	}
-/* convert from byte array to point */
-	public static ECP fromBytes(byte[] b)
-	{
-		byte[] t=new byte[ROM.MODBYTES];
-		BIG p=new BIG(ROM.Modulus);
-
-		for (int i=0;i<ROM.MODBYTES;i++) t[i]=b[i+1];
-		BIG px=BIG.fromBytes(t);
-		if (BIG.comp(px,p)>=0) return new ECP();
-
-		if (b[0]==0x04)
-		{
-			for (int i=0;i<ROM.MODBYTES;i++) t[i]=b[i+ROM.MODBYTES+1];
-			BIG py=BIG.fromBytes(t);
-			if (BIG.comp(py,p)>=0) return new ECP();
-			return new ECP(px,py);
-		}
-		else return new ECP(px);
-	}
-/* convert to hex string */
-	public String toString() {
-		if (is_infinity()) return "infinity";
-		affine();
-		if (ROM.CURVETYPE==ROM.MONTGOMERY) return "("+x.redc().toString()+")";
-		else return "("+x.redc().toString()+","+y.redc().toString()+")";
-	}
-/* this*=2 */
-	public void dbl() {
-		if (ROM.CURVETYPE==ROM.WEIERSTRASS)
-		{
-			if (INF) return;
-			if (y.iszilch())
-			{
-				inf();
-				return;
-			}
-
-			FP w1=new FP(x);
-			FP w6=new FP(z);
-			FP w2=new FP(0);
-			FP w3=new FP(x);
-			FP w8=new FP(x);
-
-			if (ROM.CURVE_A==-3)
-			{
-				w6.sqr();
-				w1.copy(w6);
-				w1.neg();
-				w3.add(w1);
-				w8.add(w6);
-				w3.mul(w8);
-				w8.copy(w3);
-				w8.imul(3);
-			}
-			else
-			{
-				w1.sqr();
-				w8.copy(w1);
-				w8.imul(3);
-			}
-
-			w2.copy(y); w2.sqr();
-			w3.copy(x); w3.mul(w2);
-			w3.imul(4);
-			w1.copy(w3); w1.neg();
-	//		w1.norm();
-
-			x.copy(w8); x.sqr();
-			x.add(w1);
-			x.add(w1);
-	//		x.reduce();
-			x.norm();
-
-			z.mul(y);
-			z.add(z);
-
-			w2.add(w2);
-			w2.sqr();
-			w2.add(w2);
-			w3.sub(x);
-			y.copy(w8); y.mul(w3);
-	//		w2.norm();
-			y.sub(w2);
-	//		y.reduce();
-	//		z.reduce();
-			y.norm();
-			z.norm();
-		}
-		if (ROM.CURVETYPE==ROM.EDWARDS)
-		{
-			FP C=new FP(x);
-			FP D=new FP(y);
-			FP H=new FP(z);
-			FP J=new FP(0);
-
-			x.mul(y); x.add(x);
-			C.sqr();
-			D.sqr();
-			if (ROM.CURVE_A==-1) C.neg();
-			y.copy(C); y.add(D);
-	//		y.norm();
-			H.sqr(); H.add(H);
-			z.copy(y);
-			J.copy(y); J.sub(H);
-			x.mul(J);
-			C.sub(D);
-			y.mul(C);
-			z.mul(J);
-
-			x.norm();
-			y.norm();
-			z.norm();
-		}
-		if (ROM.CURVETYPE==ROM.MONTGOMERY)
-		{
-			FP A=new FP(x);
-			FP B=new FP(x);
-			FP AA=new FP(0);
-			FP BB=new FP(0);
-			FP C=new FP(0);
-
-			if (INF) return;
-
-			A.add(z);
-			AA.copy(A); AA.sqr();
-			B.sub(z);
-			BB.copy(B); BB.sqr();
-			C.copy(AA); C.sub(BB);
-	//		C.norm();
-
-			x.copy(AA); x.mul(BB);
-
-			A.copy(C); A.imul((ROM.CURVE_A+2)/4);
-
-			BB.add(A);
-			z.copy(BB); z.mul(C);
-	//		x.reduce();
-	//		z.reduce();
-			x.norm();
-			z.norm();
-		}
-		return;
-	}
-
-/* this+=Q */
-	public void add(ECP Q) {
-		if (ROM.CURVETYPE==ROM.WEIERSTRASS)
-		{
-			if (INF)
-			{
-				copy(Q);
-				return;
-			}
-			if (Q.INF) return;
-
-			boolean aff=false;
-
-			FP one=new FP(1);
-			if (Q.z.equals(one)) aff=true;
-
-			FP A,C;
-			FP B=new FP(z);
-			FP D=new FP(z);
-			if (!aff)
-			{
-				A=new FP(Q.z);
-				C=new FP(Q.z);
-
-				A.sqr(); B.sqr();
-				C.mul(A); D.mul(B);
-
-				A.mul(x);
-				C.mul(y);
-			}
-			else
-			{
-				A=new FP(x);
-				C=new FP(y);
-
-				B.sqr();
-				D.mul(B);
-			}
-
-			B.mul(Q.x); B.sub(A);
-			D.mul(Q.y); D.sub(C);
-
-			if (B.iszilch())
-			{
-				if (D.iszilch())
-				{
-					dbl();
-					return;
-				}
-				else
-				{
-					INF=true;
-					return;
-				}
-			}
-
-			if (!aff) z.mul(Q.z);
-			z.mul(B);
-
-			FP e=new FP(B); e.sqr();
-			B.mul(e);
-			A.mul(e);
-
-			e.copy(A);
-			e.add(A); e.add(B);
-			x.copy(D); x.sqr(); x.sub(e);
-
-			A.sub(x);
-			y.copy(A); y.mul(D);
-			C.mul(B); y.sub(C);
-
-		//	x.reduce();
-		//	y.reduce();
-		//	z.reduce();
-			x.norm();
-			y.norm();
-			z.norm();
-		}
-		if (ROM.CURVETYPE==ROM.EDWARDS)
-		{
-			FP b=new FP(new BIG(ROM.CURVE_B));
-			FP A=new FP(z);
-			FP B=new FP(0);
-			FP C=new FP(x);
-			FP D=new FP(y);
-			FP E=new FP(0);
-			FP F=new FP(0);
-			FP G=new FP(0);
-		//	FP H=new FP(0);
-		//	FP I=new FP(0);
-
-			A.mul(Q.z);
-			B.copy(A); B.sqr();
-			C.mul(Q.x);
-			D.mul(Q.y);
-
-			E.copy(C); E.mul(D); E.mul(b);
-			F.copy(B); F.sub(E);
-			G.copy(B); G.add(E);
-			C.add(D);
-
-			if (ROM.CURVE_A==1)
-			{
-				E.copy(D); D.sub(C);
-			}
-
-			B.copy(x); B.add(y);
-			D.copy(Q.x); D.add(Q.y);
-			B.mul(D);
-			B.sub(C);
-			B.mul(F);
-			x.copy(A); x.mul(B);
-
-			if (ROM.CURVE_A==1)
-			{
-				C.copy(E); C.mul(G);
-			}
-			if (ROM.CURVE_A==-1)
-			{
-				C.mul(G);
-			}
-			y.copy(A); y.mul(C);
-			z.copy(F); z.mul(G);
-		//	x.reduce(); y.reduce(); z.reduce();
-			x.norm(); y.norm(); z.norm();
-		}
-		return;
-	}
-
-/* Differential Add for Montgomery curves. this+=Q where W is this-Q and is affine. */
-	public void dadd(ECP Q,ECP W) {
-			FP A=new FP(x);
-			FP B=new FP(x);
-			FP C=new FP(Q.x);
-			FP D=new FP(Q.x);
-			FP DA=new FP(0);
-			FP CB=new FP(0);
-
-			A.add(z);
-			B.sub(z);
-
-			C.add(Q.z);
-			D.sub(Q.z);
-
-			DA.copy(D); DA.mul(A);
-			CB.copy(C); CB.mul(B);
-
-			A.copy(DA); A.add(CB); A.sqr();
-			B.copy(DA); B.sub(CB); B.sqr();
-
-			x.copy(A);
-			z.copy(W.x); z.mul(B);
-
-			if (z.iszilch()) inf();
-			else INF=false;
-
-	//		x.reduce();
-			x.norm();
-	}
-/* this-=Q */
-	public void sub(ECP Q) {
-		Q.neg();
-		add(Q);
-		Q.neg();
-	}
-
-	public static void multiaffine(int m,ECP[] P)
-	{
-		int i;
-		FP t1=new FP(0);
-		FP t2=new FP(0);
-
-		FP[] work=new FP[m];
-
-		for (i=0;i<m;i++)
-			work[i]=new FP(0);
-
-		work[0].one();
-		work[1].copy(P[0].z);
-
-		for (i=2;i<m;i++)
-		{
-			work[i].copy(work[i-1]);
-			work[i].mul(P[i-1].z);
-		}
-
-		t1.copy(work[m-1]);
-		t1.mul(P[m-1].z);
-		t1.inverse();
-		t2.copy(P[m-1].z);
-		work[m-1].mul(t1);
-
-		for (i=m-2;;i--)
-		{
-			if (i==0)
-			{
-				work[0].copy(t1);
-				work[0].mul(t2);
-				break;
-			}
-			work[i].mul(t2);
-			work[i].mul(t1);
-			t2.mul(P[i].z);
-		}
-/* now work[] contains inverses of all Z coordinates */
-
-		for (i=0;i<m;i++)
-		{
-			P[i].z.one();
-			t1.copy(work[i]);
-			t1.sqr();
-			P[i].x.mul(t1);
-			t1.mul(work[i]);
-			P[i].y.mul(t1);
-		}
-	}
-
-/* constant time multiply by small integer of length bts - use ladder */
-	public ECP pinmul(int e,int bts) {
-		if (ROM.CURVETYPE==ROM.MONTGOMERY)
-			return this.mul(new BIG(e));
-		else
-		{
-			int nb,i,b;
-			ECP P=new ECP();
-			ECP R0=new ECP();
-			ECP R1=new ECP(); R1.copy(this);
-
-			for (i=bts-1;i>=0;i--)
-			{
-				b=(e>>i)&1;
-				P.copy(R1);
-				P.add(R0);
-				R0.cswap(R1,b);
-				R1.copy(P);
-				R0.dbl();
-				R0.cswap(R1,b);
-			}
-			P.copy(R0);
-			P.affine();
-			return P;
-		}
-	}
-
-/* return e.this */
-
-	public ECP mul(BIG e) {
-		if (e.iszilch() || is_infinity()) return new ECP();
-		ECP P=new ECP();
-		if (ROM.CURVETYPE==ROM.MONTGOMERY)
-		{
-/* use Ladder */
-			int nb,i,b;
-			ECP D=new ECP();
-			ECP R0=new ECP(); R0.copy(this);
-			ECP R1=new ECP(); R1.copy(this);
-			R1.dbl();
-			D.copy(this); D.affine();
-			nb=e.nbits();
-			for (i=nb-2;i>=0;i--)
-			{
-				b=e.bit(i);
-				P.copy(R1);
-				P.dadd(R0,D);
-				R0.cswap(R1,b);
-				R1.copy(P);
-				R0.dbl();
-				R0.cswap(R1,b);
-			}
-			P.copy(R0);
-		}
-		else
-		{
-// fixed size windows
-			int i,b,nb,m,s,ns;
-			BIG mt=new BIG();
-			BIG t=new BIG();
-			ECP Q=new ECP();
-			ECP C=new ECP();
-			ECP[] W=new ECP[8];
-			byte[] w=new byte[1+(ROM.NLEN*ROM.BASEBITS+3)/4];
-
-			affine();
-
-// precompute table
-			Q.copy(this);
-			Q.dbl();
-			W[0]=new ECP();
-			W[0].copy(this);
-
-			for (i=1;i<8;i++)
-			{
-				W[i]=new ECP();
-				W[i].copy(W[i-1]);
-				W[i].add(Q);
-			}
-
-// convert the table to affine
-			if (ROM.CURVETYPE==ROM.WEIERSTRASS)
-				multiaffine(8,W);
-
-// make exponent odd - add 2P if even, P if odd
-			t.copy(e);
-			s=t.parity();
-			t.inc(1); t.norm(); ns=t.parity(); mt.copy(t); mt.inc(1); mt.norm();
-			t.cmove(mt,s);
-			Q.cmove(this,ns);
-			C.copy(Q);
-
-			nb=1+(t.nbits()+3)/4;
-
-// convert exponent to signed 4-bit window
-			for (i=0;i<nb;i++)
-			{
-				w[i]=(byte)(t.lastbits(5)-16);
-				t.dec(w[i]); t.norm();
-				t.fshr(4);
-			}
-			w[nb]=(byte)t.lastbits(5);
-
-			P.copy(W[(w[nb]-1)/2]);
-			for (i=nb-1;i>=0;i--)
-			{
-				Q.select(W,w[i]);
-				P.dbl();
-				P.dbl();
-				P.dbl();
-				P.dbl();
-				P.add(Q);
-			}
-			P.sub(C); /* apply correction */
-		}
-		P.affine();
-		return P;
-	}
-/* Return e.this+f.Q */
-
-	public ECP mul2(BIG e,ECP Q,BIG f) {
-		BIG te=new BIG();
-		BIG tf=new BIG();
-		BIG mt=new BIG();
-		ECP S=new ECP();
-		ECP T=new ECP();
-		ECP C=new ECP();
-		ECP[] W=new ECP[8];
-		byte[] w=new byte[1+(ROM.NLEN*ROM.BASEBITS+1)/2];
-		int i,s,ns,nb;
-		byte a,b;
-
-		affine();
-		Q.affine();
-
-		te.copy(e);
-		tf.copy(f);
-
-// precompute table
-		W[1]=new ECP(); W[1].copy(this); W[1].sub(Q);
-		W[2]=new ECP(); W[2].copy(this); W[2].add(Q);
-		S.copy(Q); S.dbl();
-		W[0]=new ECP(); W[0].copy(W[1]); W[0].sub(S);
-		W[3]=new ECP(); W[3].copy(W[2]); W[3].add(S);
-		T.copy(this); T.dbl();
-		W[5]=new ECP(); W[5].copy(W[1]); W[5].add(T);
-		W[6]=new ECP(); W[6].copy(W[2]); W[6].add(T);
-		W[4]=new ECP(); W[4].copy(W[5]); W[4].sub(S);
-		W[7]=new ECP(); W[7].copy(W[6]); W[7].add(S);
-
-// convert the table to affine
-		if (ROM.CURVETYPE==ROM.WEIERSTRASS)
-			multiaffine(8,W);
-
-// if multiplier is odd, add 2, else add 1 to multiplier, and add 2P or P to correction
-
-		s=te.parity();
-		te.inc(1); te.norm(); ns=te.parity(); mt.copy(te); mt.inc(1); mt.norm();
-		te.cmove(mt,s);
-		T.cmove(this,ns);
-		C.copy(T);
-
-		s=tf.parity();
-		tf.inc(1); tf.norm(); ns=tf.parity(); mt.copy(tf); mt.inc(1); mt.norm();
-		tf.cmove(mt,s);
-		S.cmove(Q,ns);
-		C.add(S);
-
-		mt.copy(te); mt.add(tf); mt.norm();
-		nb=1+(mt.nbits()+1)/2;
-
-// convert exponent to signed 2-bit window
-		for (i=0;i<nb;i++)
-		{
-			a=(byte)(te.lastbits(3)-4);
-			te.dec(a); te.norm();
-			te.fshr(2);
-			b=(byte)(tf.lastbits(3)-4);
-			tf.dec(b); tf.norm();
-			tf.fshr(2);
-			w[i]=(byte)(4*a+b);
-		}
-		w[nb]=(byte)(4*te.lastbits(3)+tf.lastbits(3));
-		S.copy(W[(w[nb]-1)/2]);
-
-		for (i=nb-1;i>=0;i--)
-		{
-			T.select(W,w[i]);
-			S.dbl();
-			S.dbl();
-			S.add(T);
-		}
-		S.sub(C); /* apply correction */
-		S.affine();
-		return S;
-	}
-
-/*
-	public static void main(String[] args) {
-
-		BIG Gx=new BIG(ROM.CURVE_Gx);
-		BIG Gy;
-		ECP P;
-		if (ROM.CURVETYPE!=ROM.MONTGOMERY) Gy=new BIG(ROM.CURVE_Gy);
-		BIG r=new BIG(ROM.CURVE_Order);
-
-		//r.dec(7);
-
-		System.out.println("Gx= "+Gx.toString());
-		if (ROM.CURVETYPE!=ROM.MONTGOMERY) System.out.println("Gy= "+Gy.toString());
-
-		if (ROM.CURVETYPE!=ROM.MONTGOMERY) P=new ECP(Gx,Gy);
-		else  P=new ECP(Gx);
-
-		System.out.println("P= "+P.toString());
-
-		ECP R=P.mul(r);
-		//for (int i=0;i<10000;i++)
-		//	R=P.mul(r);
-
-		System.out.println("R= "+R.toString());
-    } */
-}
-
diff --git a/java64/ECP2.java b/java64/ECP2.java
deleted file mode 100755
index b13c12a..0000000
--- a/java64/ECP2.java
+++ /dev/null
@@ -1,626 +0,0 @@
-/*
-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.
-*/
-
-/* AMCL Weierstrass elliptic curve functions over FP2 */
-
-public final class ECP2 {
-	private FP2 x;
-	private FP2 y;
-	private FP2 z;
-	private boolean INF;
-
-/* Constructor - set this=O */
-	public ECP2() {
-		INF=true;
-		x=new FP2(0);
-		y=new FP2(1);
-		z=new FP2(1);
-	}
-
-/* Test this=O? */
-	public boolean is_infinity() {
-		return INF;
-	}
-/* copy this=P */
-	public void copy(ECP2 P)
-	{
-		x.copy(P.x);
-		y.copy(P.y);
-		z.copy(P.z);
-		INF=P.INF;
-	}
-/* set this=O */
-	public void inf() {
-		INF=true;
-		x.zero();
-		y.zero();
-		z.zero();
-	}
-
-/* Conditional move of Q to P dependant on d */
-	public void cmove(ECP2 Q,int d)
-	{
-		x.cmove(Q.x,d);
-		y.cmove(Q.y,d);
-		z.cmove(Q.z,d);
-
-		boolean bd;
-		if (d==0) bd=false;
-		else bd=true;
-		INF^=(INF^Q.INF)&bd;
-	}
-
-/* return 1 if b==c, no branching */
-	public static int teq(int b,int c)
-	{
-		int x=b^c;
-		x-=1;  // if x=0, x now -1
-		return ((x>>31)&1);
-	}
-
-/* Constant time select from pre-computed table */
-	public void select(ECP2 W[],int b)
-	{
-		ECP2 MP=new ECP2();
-		int m=b>>31;
-		int babs=(b^m)-m;
-
-		babs=(babs-1)/2;
-
-		cmove(W[0],teq(babs,0));  // conditional move
-		cmove(W[1],teq(babs,1));
-		cmove(W[2],teq(babs,2));
-		cmove(W[3],teq(babs,3));
-		cmove(W[4],teq(babs,4));
-		cmove(W[5],teq(babs,5));
-		cmove(W[6],teq(babs,6));
-		cmove(W[7],teq(babs,7));
-
-		MP.copy(this);
-		MP.neg();
-		cmove(MP,(int)(m&1));
-	}
-
-
-/* Test if P == Q */
-	public boolean equals(ECP2 Q) {
-		if (is_infinity() && Q.is_infinity()) return true;
-		if (is_infinity() || Q.is_infinity()) return false;
-
-		FP2 zs2=new FP2(z); zs2.sqr();
-		FP2 zo2=new FP2(Q.z); zo2.sqr();
-		FP2 zs3=new FP2(zs2); zs3.mul(z);
-		FP2 zo3=new FP2(zo2); zo3.mul(Q.z);
-		zs2.mul(Q.x);
-		zo2.mul(x);
-		if (!zs2.equals(zo2)) return false;
-		zs3.mul(Q.y);
-		zo3.mul(y);
-		if (!zs3.equals(zo3)) return false;
-
-		return true;
-	}
-/* set this=-this */
-	public void neg() {
-		if (is_infinity()) return;
-		y.neg(); y.reduce();
-		return;
-	}
-/* set to Affine - (x,y,z) to (x,y) */
-	public void affine() {
-		if (is_infinity()) return;
-		FP2 one=new FP2(1);
-		if (z.equals(one)) return;
-		z.inverse();
-
-		FP2 z2=new FP2(z);
-		z2.sqr();
-		x.mul(z2); x.reduce();
-		y.mul(z2);
-		y.mul(z);  y.reduce();
-		z.copy(one);
-	}
-/* extract affine x as FP2 */
-	public FP2 getX()
-	{
-		affine();
-		return x;
-	}
-/* extract affine y as FP2 */
-	public FP2 getY()
-	{
-		affine();
-		return y;
-	}
-/* extract projective x */
-	public FP2 getx()
-	{
-		return x;
-	}
-/* extract projective y */
-	public FP2 gety()
-	{
-		return y;
-	}
-/* extract projective z */
-	public FP2 getz()
-	{
-		return z;
-	}
-/* convert to byte array */
-	public void toBytes(byte[] b)
-	{
-		byte[] t=new byte[ROM.MODBYTES];
-		affine();
-		x.getA().toBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++)
-			b[i]=t[i];
-		x.getB().toBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++)
-			b[i+ROM.MODBYTES]=t[i];
-
-		y.getA().toBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++)
-			b[i+2*ROM.MODBYTES]=t[i];
-		y.getB().toBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++)
-			b[i+3*ROM.MODBYTES]=t[i];
-	}
-/* convert from byte array to point */
-	public static ECP2 fromBytes(byte[] b)
-	{
-		byte[] t=new byte[ROM.MODBYTES];
-		BIG ra;
-		BIG rb;
-
-		for (int i=0;i<ROM.MODBYTES;i++) t[i]=b[i];
-		ra=BIG.fromBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++) t[i]=b[i+ROM.MODBYTES];
-		rb=BIG.fromBytes(t);
-		FP2 rx=new FP2(ra,rb);
-
-		for (int i=0;i<ROM.MODBYTES;i++) t[i]=b[i+2*ROM.MODBYTES];
-		ra=BIG.fromBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++) t[i]=b[i+3*ROM.MODBYTES];
-		rb=BIG.fromBytes(t);
-		FP2 ry=new FP2(ra,rb);
-
-		return new ECP2(rx,ry);
-	}
-/* convert this to hex string */
-	public String toString() {
-		if (is_infinity()) return "infinity";
-		affine();
-		return "("+x.toString()+","+y.toString()+")";
-	}
-
-/* Calculate RHS of twisted curve equation x^3+B/i */
-	public static FP2 RHS(FP2 x) {
-		x.norm();
-		FP2 r=new FP2(x);
-		r.sqr();
-		FP2 b=new FP2(new BIG(ROM.CURVE_B));
-		b.div_ip();
-		r.mul(x);
-		r.add(b);
-
-		r.reduce();
-		return r;
-	}
-/* construct this from (x,y) - but set to O if not on curve */
-	public ECP2(FP2 ix,FP2 iy) {
-		x=new FP2(ix);
-		y=new FP2(iy);
-		z=new FP2(1);
-		FP2 rhs=RHS(x);
-		FP2 y2=new FP2(y);
-		y2.sqr();
-		if (y2.equals(rhs)) INF=false;
-		else {x.zero();INF=true;}
-	}
-
-/* construct this from x - but set to O if not on curve */
-	public ECP2(FP2 ix) {
-		x=new FP2(ix);
-		y=new FP2(1);
-		z=new FP2(1);
-		FP2 rhs=RHS(x);
-		if (rhs.sqrt())
-		{
-			y.copy(rhs);
-			INF=false;
-		}
-		else {x.zero();INF=true;}
-	}
-
-/* this+=this */
-	public int dbl() {
-		if (INF) return -1;
-		if (y.iszilch())
-		{
-			inf();
-			return -1;
-		}
-
-		FP2 w1=new FP2(x);
-		FP2 w2=new FP2(0);
-		FP2 w3=new FP2(x);
-		FP2 w8=new FP2(x);
-
-		w1.sqr();
-		w8.copy(w1);
-		w8.imul(3);
-
-		w2.copy(y); w2.sqr();
-		w3.copy(x); w3.mul(w2);
-		w3.imul(4);
-		w1.copy(w3); w1.neg();
-	//	w1.norm();
-
-		x.copy(w8); x.sqr();
-		x.add(w1);
-		x.add(w1);
-		x.norm();
-
-		z.mul(y);
-		z.add(z);
-
-		w2.add(w2);
-		w2.sqr();
-		w2.add(w2);
-		w3.sub(x);
-		y.copy(w8); y.mul(w3);
-	//	w2.norm();
-		y.sub(w2);
-
-		y.norm();
-		z.norm();
-
-		return 1;
-	}
-/* this+=Q - return 0 for add, 1 for double, -1 for O */
-	public int add(ECP2 Q) {
-		if (INF)
-		{
-			copy(Q);
-			return -1;
-		}
-		if (Q.INF) return -1;
-
-		boolean aff=false;
-
-		if (Q.z.isunity()) aff=true;
-
-		FP2 A,C;
-		FP2 B=new FP2(z);
-		FP2 D=new FP2(z);
-		if (!aff)
-		{
-			A=new FP2(Q.z);
-			C=new FP2(Q.z);
-
-			A.sqr(); B.sqr();
-			C.mul(A); D.mul(B);
-
-			A.mul(x);
-			C.mul(y);
-		}
-		else
-		{
-			A=new FP2(x);
-			C=new FP2(y);
-
-			B.sqr();
-			D.mul(B);
-		}
-
-		B.mul(Q.x); B.sub(A);
-		D.mul(Q.y); D.sub(C);
-
-		if (B.iszilch())
-		{
-			if (D.iszilch())
-			{
-				dbl();
-				return 1;
-			}
-			else
-			{
-				INF=true;
-				return -1;
-			}
-		}
-
-		if (!aff) z.mul(Q.z);
-		z.mul(B);
-
-		FP2 e=new FP2(B); e.sqr();
-		B.mul(e);
-		A.mul(e);
-
-		e.copy(A);
-		e.add(A); e.add(B);
-		x.copy(D); x.sqr(); x.sub(e);
-
-		A.sub(x);
-		y.copy(A); y.mul(D);
-		C.mul(B); y.sub(C);
-
-		x.norm();
-		y.norm();
-		z.norm();
-
-		return 0;
-	}
-
-/* set this-=Q */
-	public int sub(ECP2 Q) {
-		Q.neg();
-		int D=add(Q);
-		Q.neg();
-		return D;
-	}
-/* set this*=q, where q is Modulus, using Frobenius */
-	public void frob(FP2 X)
-	{
-		if (INF) return;
-		FP2 X2=new FP2(X);
-		X2.sqr();
-		x.conj();
-		y.conj();
-		z.conj();
-		z.reduce();
-		x.mul(X2);
-		y.mul(X2);
-		y.mul(X);
-	}
-
-/* normalises m-array of ECP2 points. Requires work vector of m FP2s */
-
-	public static void multiaffine(int m,ECP2[] P)
-	{
-		int i;
-		FP2 t1=new FP2(0);
-		FP2 t2=new FP2(0);
-
-		FP2[] work=new FP2[m];
-		work[0]=new FP2(1);
-		work[1]=new FP2(P[0].z);
-		for (i=2;i<m;i++)
-		{
-			work[i]=new FP2(work[i-1]);
-			work[i].mul(P[i-1].z);
-		}
-
-		t1.copy(work[m-1]); t1.mul(P[m-1].z);
-
-		t1.inverse();
-
-		t2.copy(P[m-1].z);
-		work[m-1].mul(t1);
-
-		for (i=m-2;;i--)
-		{
-			if (i==0)
-			{
-				work[0].copy(t1);
-				work[0].mul(t2);
-				break;
-			}
-			work[i].mul(t2);
-			work[i].mul(t1);
-			t2.mul(P[i].z);
-		}
-/* now work[] contains inverses of all Z coordinates */
-
-		for (i=0;i<m;i++)
-		{
-			P[i].z.one();
-			t1.copy(work[i]); t1.sqr();
-			P[i].x.mul(t1);
-			t1.mul(work[i]);
-			P[i].y.mul(t1);
-		}
-	}
-
-/* P*=e */
-	public ECP2 mul(BIG e)
-	{
-/* fixed size windows */
-		int i,b,nb,m,s,ns;
-		BIG mt=new BIG();
-		BIG t=new BIG();
-		ECP2 P=new ECP2();
-		ECP2 Q=new ECP2();
-		ECP2 C=new ECP2();
-		ECP2[] W=new ECP2[8];
-		byte[] w=new byte[1+(ROM.NLEN*ROM.BASEBITS+3)/4];
-
-		if (is_infinity()) return new ECP2();
-
-		affine();
-
-/* precompute table */
-		Q.copy(this);
-		Q.dbl();
-		W[0]=new ECP2();
-		W[0].copy(this);
-
-		for (i=1;i<8;i++)
-		{
-			W[i]=new ECP2();
-			W[i].copy(W[i-1]);
-			W[i].add(Q);
-		}
-
-/* convert the table to affine */
-
-		multiaffine(8,W);
-
-/* make exponent odd - add 2P if even, P if odd */
-		t.copy(e);
-		s=t.parity();
-		t.inc(1); t.norm(); ns=t.parity(); mt.copy(t); mt.inc(1); mt.norm();
-		t.cmove(mt,s);
-		Q.cmove(this,ns);
-		C.copy(Q);
-
-		nb=1+(t.nbits()+3)/4;
-/* convert exponent to signed 4-bit window */
-		for (i=0;i<nb;i++)
-		{
-			w[i]=(byte)(t.lastbits(5)-16);
-			t.dec(w[i]); t.norm();
-			t.fshr(4);
-		}
-		w[nb]=(byte)t.lastbits(5);
-
-		P.copy(W[(w[nb]-1)/2]);
-		for (i=nb-1;i>=0;i--)
-		{
-			Q.select(W,w[i]);
-			P.dbl();
-			P.dbl();
-			P.dbl();
-			P.dbl();
-			P.add(Q);
-		}
-		P.sub(C);
-		P.affine();
-		return P;
-	}
-
-/* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3 */
-	public static ECP2 mul4(ECP2[] Q,BIG[] u)
-	{
-		int i,j,nb;
-		int[] a=new int[4];
-		ECP2 T=new ECP2();
-		ECP2 C=new ECP2();
-		ECP2 P=new ECP2();
-		ECP2[] W=new ECP2[8];
-
-		BIG mt=new BIG();
-		BIG[] t=new BIG[4];
-
-		byte[] w=new byte[ROM.NLEN*ROM.BASEBITS+1];
-
-		for (i=0;i<4;i++)
-		{
-			t[i]=new BIG(u[i]);
-			Q[i].affine();
-		}
-
-/* precompute table */
-
-		W[0]=new ECP2(); W[0].copy(Q[0]); W[0].sub(Q[1]);
-		W[1]=new ECP2(); W[1].copy(W[0]);
-		W[2]=new ECP2(); W[2].copy(W[0]);
-		W[3]=new ECP2(); W[3].copy(W[0]);
-		W[4]=new ECP2(); W[4].copy(Q[0]); W[4].add(Q[1]);
-		W[5]=new ECP2(); W[5].copy(W[4]);
-		W[6]=new ECP2(); W[6].copy(W[4]);
-		W[7]=new ECP2(); W[7].copy(W[4]);
-		T.copy(Q[2]); T.sub(Q[3]);
-		W[1].sub(T);
-		W[2].add(T);
-		W[5].sub(T);
-		W[6].add(T);
-		T.copy(Q[2]); T.add(Q[3]);
-		W[0].sub(T);
-		W[3].add(T);
-		W[4].sub(T);
-		W[7].add(T);
-
-		multiaffine(8,W);
-
-/* if multiplier is even add 1 to multiplier, and add P to correction */
-		mt.zero(); C.inf();
-		for (i=0;i<4;i++)
-		{
-			if (t[i].parity()==0)
-			{
-				t[i].inc(1); t[i].norm();
-				C.add(Q[i]);
-			}
-			mt.add(t[i]); mt.norm();
-		}
-
-		nb=1+mt.nbits();
-
-/* convert exponent to signed 1-bit window */
-		for (j=0;j<nb;j++)
-		{
-			for (i=0;i<4;i++)
-			{
-				a[i]=(byte)(t[i].lastbits(2)-2);
-				t[i].dec(a[i]); t[i].norm();
-				t[i].fshr(1);
-			}
-			w[j]=(byte)(8*a[0]+4*a[1]+2*a[2]+a[3]);
-		}
-		w[nb]=(byte)(8*t[0].lastbits(2)+4*t[1].lastbits(2)+2*t[2].lastbits(2)+t[3].lastbits(2));
-
-		P.copy(W[(w[nb]-1)/2]);
-		for (i=nb-1;i>=0;i--)
-		{
-			T.select(W,w[i]);
-			P.dbl();
-			P.add(T);
-		}
-		P.sub(C); /* apply correction */
-
-		P.affine();
-		return P;
-	}
-
-
-/*
-	public static void main(String[] args) {
-		BIG r=new BIG(ROM.Modulus);
-
-		BIG Pxa=new BIG(ROM.CURVE_Pxa);
-		BIG Pxb=new BIG(ROM.CURVE_Pxb);
-		BIG Pya=new BIG(ROM.CURVE_Pya);
-		BIG Pyb=new BIG(ROM.CURVE_Pyb);
-
-		BIG Fra=new BIG(ROM.CURVE_Fra);
-		BIG Frb=new BIG(ROM.CURVE_Frb);
-
-		FP2 f=new FP2(Fra,Frb);
-
-		FP2 Px=new FP2(Pxa,Pxb);
-		FP2 Py=new FP2(Pya,Pyb);
-
-		ECP2 P=new ECP2(Px,Py);
-
-		System.out.println("P= "+P.toString());
-
-		P=P.mul(r);
-		System.out.println("P= "+P.toString());
-
-		ECP2 Q=new ECP2(Px,Py);
-		Q.frob(f);
-		System.out.println("Q= "+Q.toString());
-
-
-	} */
-
-
-}
diff --git a/java64/FF.java b/java64/FF.java
deleted file mode 100755
index 2e06a52..0000000
--- a/java64/FF.java
+++ /dev/null
@@ -1,974 +0,0 @@
-/*
-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.
-*/
-
-/* Large Finite Field arithmetic */
-/* AMCL mod p functions */
-
-public final class FF {
-	private final BIG[] v;
-	private final int length;
-
-	private static final int P_MBITS=ROM.MODBYTES*8;
-	private static final int P_MB=(P_MBITS%ROM.BASEBITS);
-	private static final long P_OMASK=((long)(-1)<<(P_MBITS%ROM.BASEBITS));
-	private static final long P_FEXCESS=((long)1<<(ROM.BASEBITS*ROM.NLEN-P_MBITS));
-	private static final int P_TBITS=(P_MBITS%ROM.BASEBITS);
-
-	public long P_EXCESS()
-	{
-		return ((v[length-1].get(ROM.NLEN-1)&P_OMASK)>>(P_MB));
-	}
-
-/* Constructors */
-	public FF(int n)
-	{
-		v=new BIG[n];
-		for (int i=0;i<n;i++)
-			v[i]=new BIG(0);
-		length=n;
-	}
-
-	public FF(long [][] x,int n)
-	{
-		v=new BIG[n];
-		for (int i=0;i<n;i++)
-			v[i]=new BIG(x[i]);
-		length=n;
-	}
-
-	public int getlen()
-	{
-		return length;
-	}
-
-/* set to integer */
-	public void set(int m)
-	{
-		zero();
-		v[0].set(0,(long)m);
-	}
-
-/* copy from FF b */
-	public void copy(FF b)
-	{
-		for (int i=0;i<length;i++)
-		{
-			v[i].copy(b.v[i]);
-		}
-	}
-
-/* x=y<<n */
-	public void dsucopy(FF b)
-	{
-		for (int i=0;i<b.length;i++)
-		{
-			v[b.length+i].copy(b.v[i]);
-			v[i].zero();
-		}
-	}
-
-/* x=y */
-	public void dscopy(FF b)
-	{
-		for (int i=0;i<b.length;i++)
-		{
-			v[i].copy(b.v[i]);
-			v[b.length+i].zero();
-		}
-	}
-
-/* x=y>>n */
-	public void sducopy(FF b)
-	{
-		for (int i=0;i<length;i++)
-		{
-			v[i].copy(b.v[length+i]);
-		}
-	}
-
-/* set to zero */
-	public void zero()
-	{
-		for (int i=0;i<length;i++)
-		{
-			v[i].zero();
-		}
-	}
-
-	public void one()
-	{
-		v[0].one();
-		for (int i=1;i<length;i++)
-		{
-			v[i].zero();
-		}
-	}
-
-/* test equals 0 */
-	public boolean iszilch()
-	{
-		for (int i=0;i<length;i++)
-		{
-			if (!v[i].iszilch()) return false;
-		}
-		return true;
-	}
-
-/* shift right by 256-bit words */
-	public void shrw(int n)
-	{
-		for (int i=0;i<n;i++)
-		{
-			v[i].copy(v[i+n]);
-			v[i+n].zero();
-		}
-	}
-
-/* shift left by 256-bit words */
-	public void shlw(int n)
-	{
-		for (int i=0;i<n;i++)
-		{
-			v[n+i].copy(v[i]);
-			v[i].zero();
-		}
-	}
-
-/* extract last bit */
-	public int parity()
-	{
-		return v[0].parity();
-	}
-
-	public int lastbits(int m)
-	{
-		return v[0].lastbits(m);
-	}
-
-/* compare x and y - must be normalised, and of same length */
-	public static int comp(FF a,FF b)
-	{
-		int i,j;
-		for (i=a.length-1;i>=0;i--)
-		{
-			j=BIG.comp(a.v[i],b.v[i]);
-			if (j!=0) return j;
-		}
-		return 0;
-	}
-
-/* recursive add */
-	public void radd(int vp,FF x,int xp,FF y,int yp,int n)
-	{
-		for (int i=0;i<n;i++)
-		{
-			v[vp+i].copy(x.v[xp+i]);
-			v[vp+i].add(y.v[yp+i]);
-		}
-	}
-
-/* recursive inc */
-	public void rinc(int vp,FF y,int yp,int n)
-	{
-		for (int i=0;i<n;i++)
-		{
-			v[vp+i].add(y.v[yp+i]);
-		}
-	}
-
-/* recursive sub */
-	public void rsub(int vp,FF x,int xp,FF y,int yp,int n)
-	{
-		for (int i=0;i<n;i++)
-		{
-			v[vp+i].copy(x.v[xp+i]);
-			v[vp+i].sub(y.v[yp+i]);
-		}
-	}
-
-/* recursive dec */
-	public void rdec(int vp,FF y,int yp,int n)
-	{
-		for (int i=0;i<n;i++)
-		{
-			v[vp+i].sub(y.v[yp+i]);
-		}
-	}
-
-/* simple add */
-	public void add(FF b)
-	{
-		for (int i=0;i<length;i++)
-			v[i].add(b.v[i]);
-	}
-
-/* simple sub */
-	public void sub(FF b)
-	{
-		for (int i=0;i<length;i++)
-			v[i].sub(b.v[i]);
-	}
-
-/* reverse sub */
-	public void revsub(FF b)
-	{
-		for (int i=0;i<length;i++)
-			v[i].rsub(b.v[i]);
-	}
-
-/* increment/decrement by a small integer */
-	public void inc(int m)
-	{
-		v[0].inc(m);
-		norm();
-	}
-
-	public void dec(int m)
-	{
-		v[0].dec(m);
-		norm();
-	}
-
-	/* normalise - but hold any overflow in top part unless n<0 */
-	private void rnorm(int vp,int n)
-	{
-		boolean trunc=false;
-		int i;
-		long carry;
-		if (n<0)
-		{ /* -v n signals to do truncation */
-			n=-n;
-			trunc=true;
-		}
-		for (i=0;i<n-1;i++)
-		{
-			carry=v[vp+i].norm();
-			v[vp+i].xortop(carry<<P_TBITS);
-			v[vp+i+1].inc((int)carry);
-		}
-		carry=v[vp+n-1].norm();
-		if (trunc)
-			v[vp+n-1].xortop(carry<<P_TBITS);
-
-	}
-
-	public void norm()
-	{
-		rnorm(0,length);
-	}
-
-/* shift left by one bit */
-	public void shl()
-	{
-		int i,delay_carry=0;
-		long carry;
-		for (i=0;i<length-1;i++)
-		{
-			carry=v[i].fshl(1);
-			v[i].inc(delay_carry);
-			v[i].xortop(carry<<P_TBITS);
-			delay_carry=(int)carry;
-		}
-		v[length-1].fshl(1);
-		v[length-1].inc(delay_carry);
-	}
-
-/* shift right by one bit */
-
-	public void shr()
-	{
-		int i;
-		long carry;
-		for (i=length-1;i>0;i--)
-		{
-			carry=v[i].fshr(1);
-			v[i-1].ortop(carry<<P_TBITS);
-		}
-		v[0].fshr(1);
-	}
-
-/* Convert to Hex String */
-	public String toString()
-	{
-		norm();
-		String s="";
-		for (int i=length-1;i>=0;i--)
-		{
-			s+=v[i].toString();
-		}
-		return s;
-	}
-
-/* Convert FFs to/from byte arrays */
-	public void toBytes(byte[] b)
-	{
-		for (int i=0;i<length;i++)
-		{
-			v[i].tobytearray(b,(length-i-1)*ROM.MODBYTES);
-		}
-	}
-
-	public static void fromBytes(FF x,byte[] b)
-	{
-		for (int i=0;i<x.length;i++)
-		{
-			x.v[i]=BIG.frombytearray(b,(x.length-i-1)*ROM.MODBYTES);
-		}
-	}
-
-/* in-place swapping using xor - side channel resistant - lengths must be the same */
-	private static void cswap(FF a,FF b,int d)
-	{
-		for (int i=0;i<a.length;i++)
-		{
-		//	BIG.cswap(a.v[i],b.v[i],d);
-			a.v[i].cswap(b.v[i],d);
-		}
-	}
-
-/* z=x*y, t is workspace */
-	private void karmul(int vp,FF x,int xp,FF y,int yp,FF t,int tp,int n)
-	{
-		int nd2;
-		if (n==1)
-		{
-			DBIG d=BIG.mul(x.v[xp],y.v[yp]);
-			v[vp+1]=d.split(8*ROM.MODBYTES);
-			v[vp].copy(d);
-			return;
-		}
-		nd2=n/2;
-		radd(vp,x,xp,x,xp+nd2,nd2);
-		//rnorm(vp,nd2);
-		radd(vp+nd2,y,yp,y,yp+nd2,nd2);
-		//rnorm(vp+nd2,nd2);
-		t.karmul(tp,this,vp,this,vp+nd2,t,tp+n,nd2);
-		karmul(vp,x,xp,y,yp,t,tp+n,nd2);
-		karmul(vp+n,x,xp+nd2,y,yp+nd2,t,tp+n,nd2);
-		t.rdec(tp,this,vp,n);
-		t.rdec(tp,this,vp+n,n);
-		rinc(vp+nd2,t,tp,n);
-		rnorm(vp,2*n);
-	}
-
-	private void karsqr(int vp,FF x,int xp,FF t,int tp,int n)
-	{
-		int nd2;
-		if (n==1)
-		{
-			DBIG d=BIG.sqr(x.v[xp]);
-			v[vp+1].copy(d.split(8*ROM.MODBYTES));
-			v[vp].copy(d);
-			return;
-		}
-
-		nd2=n/2;
-		karsqr(vp,x,xp,t,tp+n,nd2);
-		karsqr(vp+n,x,xp+nd2,t,tp+n,nd2);
-		t.karmul(tp,x,xp,x,xp+nd2,t,tp+n,nd2);
-		rinc(vp+nd2,t,tp,n);
-		rinc(vp+nd2,t,tp,n);
-		rnorm(vp+nd2,n);
-	}
-
-
-	private void karmul_lower(int vp,FF x,int xp,FF y,int yp,FF t,int tp,int n)
-	{ /* Calculates Least Significant bottom half of x*y */
-		int nd2;
-		if (n==1)
-		{ /* only calculate bottom half of product */
-			v[vp].copy(BIG.smul(x.v[xp],y.v[yp]));
-			return;
-		}
-		nd2=n/2;
-
-		karmul(vp,x,xp,y,yp,t,tp+n,nd2);
-		t.karmul_lower(tp,x,xp+nd2,y,yp,t,tp+n,nd2);
-		rinc(vp+nd2,t,tp,nd2);
-		t.karmul_lower(tp,x,xp,y,yp+nd2,t,tp+n,nd2);
-		rinc(vp+nd2,t,tp,nd2);
-		rnorm(vp+nd2,-nd2);  /* truncate it */
-	}
-
-	private void karmul_upper(FF x,FF y,FF t,int n)
-	{ /* Calculates Most Significant upper half of x*y, given lower part */
-		int nd2;
-
-		nd2=n/2;
-		radd(n,x,0,x,nd2,nd2);
-		radd(n+nd2,y,0,y,nd2,nd2);
-
-		t.karmul(0,this,n+nd2,this,n,t,n,nd2);  /* t = (a0+a1)(b0+b1) */
-		karmul(n,x,nd2,y,nd2,t,n,nd2); /* z[n]= a1*b1 */
-									/* z[0-nd2]=l(a0b0) z[nd2-n]= h(a0b0)+l(t)-l(a0b0)-l(a1b1) */
-		t.rdec(0,this,n,n);              /* t=t-a1b1  */
-		rinc(nd2,this,0,nd2);   /* z[nd2-n]+=l(a0b0) = h(a0b0)+l(t)-l(a1b1)  */
-		rdec(nd2,t,0,nd2);   /* z[nd2-n]=h(a0b0)+l(t)-l(a1b1)-l(t-a1b1)=h(a0b0) */
-		rnorm(0,-n);					/* a0b0 now in z - truncate it */
-		t.rdec(0,this,0,n);         /* (a0+a1)(b0+b1) - a0b0 */
-		rinc(nd2,t,0,n);
-
-		rnorm(nd2,n);
-	}
-
-	/* z=x*y. Assumes x and y are of same length. */
-	public static FF mul(FF x,FF y)
-	{
-		int n=x.length;
-		FF z=new FF(2*n);
-		FF t=new FF(2*n);
-		z.karmul(0,x,0,y,0,t,0,n);
-		return z;
-	}
-
-/* return low part of product this*y */
-	public void lmul(FF y)
-	{
-		int n=length;
-		FF t=new FF(2*n);
-		FF x=new FF(n); x.copy(this);
-		karmul_lower(0,x,0,y,0,t,0,n);
-	}
-
-/* Set b=b mod c */
-	public void mod(FF c)
-	{
-		int k=0;
-
-		norm();
-		if (comp(this,c)<0)
-			return;
-		do
-		{
-			c.shl();
-			k++;
-		} while (comp(this,c)>=0);
-
-		while (k>0)
-		{
-			c.shr();
-			if (comp(this,c)>=0)
-			{
-				sub(c);
-				norm();
-			}
-			k--;
-		}
-	}
-
-	/* z=x^2 */
-	public static FF sqr(FF x)
-	{
-		int n=x.length;
-		FF z=new FF(2*n);
-		FF t=new FF(2*n);
-		z.karsqr(0,x,0,t,0,n);
-		return z;
-	}
-
-/* return This mod modulus, N is modulus, ND is Montgomery Constant */
-	public FF reduce(FF N,FF ND)
-	{ /* fast karatsuba Montgomery reduction */
-		int n=N.length;
-		FF t=new FF(2*n);
-		FF r=new FF(n);
-		FF m=new FF(n);
-
-		r.sducopy(this);
-		m.karmul_lower(0,this,0,ND,0,t,0,n);
-		karmul_upper(N,m,t,n);
-		m.sducopy(this);
-
-		r.add(N);
-		r.sub(m);
-		r.norm();
-
-		return r;
-
-	}
-
-/* Set r=this mod b */
-/* this is of length - 2*n */
-/* r,b is of length - n */
-	public FF dmod(FF b)
-	{
-		int k,n=b.length;
-		FF m=new FF(2*n);
-		FF x=new FF(2*n);
-		FF r=new FF(n);
-
-		x.copy(this);
-		x.norm();
-		m.dsucopy(b); k=256*n;
-
-		while (k>0)
-		{
-			m.shr();
-
-			if (comp(x,m)>=0)
-			{
-				x.sub(m);
-				x.norm();
-			}
-			k--;
-		}
-
-		r.copy(x);
-		r.mod(b);
-		return r;
-	}
-
-/* Set return=1/this mod p. Binary method - a<p on entry */
-
-	public void invmodp(FF p)
-	{
-		int n=p.length;
-
-		FF u=new FF(n);
-		FF v=new FF(n);
-		FF x1=new FF(n);
-		FF x2=new FF(n);
-		FF t=new FF(n);
-		FF one=new FF(n);
-
-		one.one();
-		u.copy(this);
-		v.copy(p);
-		x1.copy(one);
-		x2.zero();
-
-	// reduce n in here as well!
-		while (comp(u,one)!=0 && comp(v,one)!=0)
-		{
-			while (u.parity()==0)
-			{
-				u.shr();
-				if (x1.parity()!=0)
-				{
-					x1.add(p);
-					x1.norm();
-				}
-				x1.shr();
-			}
-			while (v.parity()==0)
-			{
-				v.shr();
-				if (x2.parity()!=0)
-				{
-					x2.add(p);
-					x2.norm();
-				}
-				x2.shr();
-			}
-			if (comp(u,v)>=0)
-			{
-
-				u.sub(v);
-				u.norm();
-				if (comp(x1,x2)>=0) x1.sub(x2);
-				else
-				{
-					t.copy(p);
-					t.sub(x2);
-					x1.add(t);
-				}
-				x1.norm();
-			}
-			else
-			{
-				v.sub(u);
-				v.norm();
-				if (comp(x2,x1)>=0) x2.sub(x1);
-				else
-				{
-					t.copy(p);
-					t.sub(x1);
-					x2.add(t);
-				}
-				x2.norm();
-			}
-		}
-		if (comp(u,one)==0)
-			copy(x1);
-		else
-			copy(x2);
-	}
-
-/* nresidue mod m */
-	public void nres(FF m)
-	{
-		int n=m.length;
-		FF d=new FF(2*n);
-		d.dsucopy(this);
-		copy(d.dmod(m));
-	}
-
-	public void redc(FF m,FF ND)
-	{
-		int n=m.length;
-		FF d=new FF(2*n);
-		mod(m);
-		d.dscopy(this);
-		copy(d.reduce(m,ND));
-		mod(m);
-	}
-
-	private void mod2m(int m)
-	{
-		for (int i=m;i<length;i++)
-			v[i].zero();
-	}
-
-	/* U=1/a mod 2^m - Arazi & Qi */
-	private FF invmod2m()
-	{
-		int i,n=length;
-
-		FF b=new FF(n);
-		FF c=new FF(n);
-		FF U=new FF(n);
-
-		FF t;
-
-		U.zero();
-		U.v[0].copy(v[0]);
-		U.v[0].invmod2m();
-
-		for (i=1;i<n;i<<=1)
-		{
-			b.copy(this); b.mod2m(i);
-			t=mul(U,b); t.shrw(i); b.copy(t);
-			c.copy(this); c.shrw(i); c.mod2m(i);
-			c.lmul(U); c.mod2m(i);
-
-			b.add(c); b.norm();
-			b.lmul(U); b.mod2m(i);
-
-			c.one(); c.shlw(i); b.revsub(c); b.norm();
-			b.shlw(i);
-			U.add(b);
-		}
-		U.norm();
-		return U;
-	}
-
-	public void random(RAND rng)
-	{
-		int n=length;
-		for (int i=0;i<n;i++)
-		{
-			v[i].copy(BIG.random(rng));
-		}
-	/* make sure top bit is 1 */
-		while (v[n-1].nbits()<ROM.MODBYTES*8) v[n-1].copy(BIG.random(rng));
-	}
-
-	/* generate random x */
-	public void randomnum(FF p,RAND rng)
-	{
-		int n=length;
-		FF d=new FF(2*n);
-
-		for (int i=0;i<2*n;i++)
-		{
-			d.v[i].copy(BIG.random(rng));
-		}
-		copy(d.dmod(p));
-	}
-
-	/* this*=y mod p */
-	public void modmul(FF y,FF p,FF nd)
-	{
-		//FF d=new FF(2*p.length);
-		long ex=P_EXCESS();
-		long ey=y.P_EXCESS();
-		if ((ex+1)*(ey+1)+1>=P_FEXCESS) mod(p);
-		FF d=mul(this,y);
-		copy(d.reduce(p,nd));
-	}
-
-	/* this*=y mod p */
-	public void modsqr(FF p,FF nd)
-	{
-		//FF d=new FF(2*p.length);
-		long ex=P_EXCESS();
-		if ((ex+1)*(ex+1)+1>=P_FEXCESS) mod(p);
-		FF d=sqr(this);
-		copy(d.reduce(p,nd));
-	}
-
-	/* this=this^e mod p using side-channel resistant Montgomery Ladder, for large e */
-	public void skpow(FF e,FF p)
-	{
-		int i,b,n=p.length;
-		FF R0=new FF(n);
-		FF R1=new FF(n);
-		FF ND=p.invmod2m();
-
-		mod(p);
-		R0.one();
-		R1.copy(this);
-		R0.nres(p);
-		R1.nres(p);
-
-		for (i=8*ROM.MODBYTES*n-1;i>=0;i--)
-		{
-			b=e.v[i/256].bit(i%256);
-			copy(R0);
-			modmul(R1,p,ND);
-
-			cswap(R0,R1,b);
-			R0.modsqr(p,ND);
-
-			R1.copy(this);
-			cswap(R0,R1,b);
-		}
-		copy(R0);
-		redc(p,ND);
-	}
-
-	/* this =this^e mod p using side-channel resistant Montgomery Ladder, for short e */
-	public void skpow(BIG e,FF p)
-	{
-		int i,b,n=p.length;
-		FF R0=new FF(n);
-		FF R1=new FF(n);
-		FF ND=p.invmod2m();
-
-		mod(p);
-		R0.one();
-		R1.copy(this);
-		R0.nres(p);
-		R1.nres(p);
-
-		for (i=8*ROM.MODBYTES-1;i>=0;i--)
-		{
-			b=e.bit(i);
-			copy(R0);
-			modmul(R1,p,ND);
-
-			cswap(R0,R1,b);
-			R0.modsqr(p,ND);
-
-			R1.copy(this);
-			cswap(R0,R1,b);
-		}
-		copy(R0);
-		redc(p,ND);
-	}
-
-	/* raise to an integer power - right-to-left method */
-	public void power(int e,FF p)
-	{
-		int n=p.length;
-		FF w=new FF(n);
-		FF ND=p.invmod2m();
-		boolean f=true;
-
-		w.copy(this);
-		w.nres(p);
-
-		if (e==2)
-		{
-			copy(w);
-			modsqr(p,ND);
-		}
-		else for (; ; )
-		{
-			if (e%2==1)
-			{
-				if (f) copy(w);
-				else modmul(w,p,ND);
-				f=false;
-			}
-			e>>=1;
-			if (e==0) break;
-			w.modsqr(p,ND);
-		}
-		redc(p,ND);
-	}
-
-	/* this=this^e mod p, faster but not side channel resistant */
-	public void pow(FF e,FF p)
-	{
-		int i,b,n=p.length;
-		FF w=new FF(n);
-		FF ND=p.invmod2m();
-
-		w.copy(this);
-		one();
-		nres(p);
-		w.nres(p);
-		for (i=8*ROM.MODBYTES*n-1;i>=0;i--)
-		{
-			modsqr(p,ND);
-			b=e.v[i/256].bit(i%256);
-			if (b==1) modmul(w,p,ND);
-		}
-		redc(p,ND);
-	}
-
-	/* double exponentiation r=x^e.y^f mod p */
-	public void pow2(BIG e,FF y,BIG f,FF p)
-	{
-		int i,eb,fb,n=p.length;
-		FF xn=new FF(n);
-		FF yn=new FF(n);
-		FF xy=new FF(n);
-		FF ND=p.invmod2m();
-
-		xn.copy(this);
-		yn.copy(y);
-		xn.nres(p);
-		yn.nres(p);
-		xy.copy(xn); xy.modmul(yn,p,ND);
-		one();
-		nres(p);
-
-		for (i=8*ROM.MODBYTES-1;i>=0;i--)
-		{
-			eb=e.bit(i);
-			fb=f.bit(i);
-			modsqr(p,ND);
-			if (eb==1)
-			{
-				if (fb==1) modmul(xy,p,ND);
-				else modmul(xn,p,ND);
-			}
-			else
-			{
-				if (fb==1) modmul(yn,p,ND);
-			}
-		}
-		redc(p,ND);
-	}
-
-	private static int igcd(int x,int y)
-	{ /* integer GCD, returns GCD of x and y */
-		int r;
-		if (y==0) return x;
-		while ((r=x%y)!=0)
-			{x=y;y=r;}
-		return y;
-	}
-
-	/* quick and dirty check for common factor with n */
-	public boolean cfactor(int s)
-	{
-		int r,n=length;
-		int g;
-
-		FF x=new FF(n);
-		FF y=new FF(n);
-
-		y.set(s);
-		x.copy(this);
-		x.norm();
-
-		do
-		{
-			x.sub(y);
-			x.norm();
-			while (!x.iszilch() && x.parity()==0) x.shr();
-		}
-		while (comp(x,y)>0);
-
-		g=(int)x.v[0].get(0);
-		r=igcd(s,g);
-		if (r>1) return true;
-		return false;
-	}
-
-	/* Miller-Rabin test for primality. Slow. */
-	public static boolean prime(FF p,RAND rng)
-	{
-		int i,j,s=0,n=p.length;
-		boolean loop;
-		FF d=new FF(n);
-		FF x=new FF(n);
-		FF unity=new FF(n);
-		FF nm1=new FF(n);
-
-		int sf=4849845; /* 3*5*.. *19 */
-		p.norm();
-
-		if (p.cfactor(sf)) return false;
-		unity.one();
-		nm1.copy(p);
-		nm1.sub(unity);
-		nm1.norm();
-		d.copy(nm1);
-
-		while (d.parity()==0)
-		{
-			d.shr();
-			s++;
-		}
-		if (s==0) return false;
-		for (i=0;i<10;i++)
-		{
-			x.randomnum(p,rng);
-			x.pow(d,p);
-			if (comp(x,unity)==0 || comp(x,nm1)==0) continue;
-			loop=false;
-			for (j=1;j<s;j++)
-			{
-				x.power(2,p);
-				if (comp(x,unity)==0) return false;
-				if (comp(x,nm1)==0) {loop=true; break;}
-			}
-			if (loop) continue;
-			return false;
-		}
-		return true;
-	}
-
-/*
-	public static final long[][] P ={{0xAD19A781670957L,0x76A79C00965796L,0xDEFCC5FC9A9717L,0xF02F2940E20E9L,0xBF59E34FL},{0x6894F31844C908L,0x8DADA70E82C79FL,0xFD29F3836046F6L,0x8C1D874D314DD0L,0x46D077BL},{0x3C515217813331L,0x56680FD1CE935BL,0xE55C53EEA8838EL,0x92C2F7E14A4A95L,0xD945E5B1L},{0xACF673E919F5EFL,0x6723E7E7DAB446L,0x6B6FA69B36EB1BL,0xF7D13920ECA300L,0xB5FC2165L}};
-
-	public static void main(String[] args) {
-		byte[] raw=new byte[100];
-		RAND rng=new RAND();
-
-		rng.clean();
-		for (int i=0;i<100;i++) raw[i]=(byte)i;
-
-		rng.seed(100,raw);
-
-		int n=4;
-
-		FF x=new FF(n);
-		x.set(3);
-
-		FF p=new FF(P,n);
-
-		if (prime(p,rng)) System.out.println("p is a prime");
-
-		FF e=new FF(n);
-		e.copy(p);
-		e.dec(1); e.norm();
-
-		System.out.println("e= "+e.toString());
-
-		x.skpow(e,p);
-		System.out.println("x= "+x.toString());
-
-    } */
-
-}
diff --git a/java64/FP.java b/java64/FP.java
deleted file mode 100755
index ab99c13..0000000
--- a/java64/FP.java
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
-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.
-*/
-
-/* Finite Field arithmetic */
-/* AMCL mod p functions */
-
-public final class FP {
-	private final BIG x;
-	private static BIG p=new BIG(ROM.Modulus);
-
-/* Constructors */
-	public FP(int a)
-	{
-		x=new BIG(a);
-		nres();
-	}
-
-	public FP(BIG a)
-	{
-		x=new BIG(a);
-		nres();
-	}
-
-	public FP(FP a)
-	{
-		x=new BIG(a.x);
-	}
-
-/* convert to string */
-	public String toString()
-	{
-		String s=redc().toString();
-		return s;
-	}
-
-	public String toRawString()
-	{
-		String s=x.toRawString();
-		return s;
-	}
-
-/* convert to Montgomery n-residue form */
-	public void nres()
-	{
-		if (ROM.MODTYPE!=ROM.PSEUDO_MERSENNE)
-		{
-			DBIG d=new DBIG(x);
-			d.shl(ROM.NLEN*ROM.BASEBITS);
-			x.copy(d.mod(p));
-		}
-	}
-
-/* convert back to regular form */
-	public BIG redc()
-	{
-		if (ROM.MODTYPE!=ROM.PSEUDO_MERSENNE)
-		{
-			DBIG d=new DBIG(x);
-			return BIG.mod(d);
-		}
-		else
-		{
-			BIG r=new BIG(x);
-			return r;
-		}
-	}
-
-/* test this=0? */
-	public boolean iszilch() {
-		reduce();
-		return x.iszilch();
-	}
-
-/* copy from FP b */
-	public void copy(FP b)
-	{
-		x.copy(b.x);
-	}
-
-/* set this=0 */
-	public void zero()
-	{
-		x.zero();
-	}
-
-/* set this=1 */
-	public void one()
-	{
-		x.one(); nres();
-	}
-
-/* normalise this */
-	public void norm()
-	{
-		x.norm();
-	}
-
-/* swap FPs depending on d */
-	public void cswap(FP b,int d)
-	{
-		x.cswap(b.x,d);
-	}
-
-/* copy FPs depending on d */
-	public void cmove(FP b,int d)
-	{
-		x.cmove(b.x,d);
-	}
-
-/* this*=b mod Modulus */
-	public void mul(FP b)
-	{
-		long ea=BIG.EXCESS(x);
-		long eb=BIG.EXCESS(b.x);
-
-		if ((ea+1)*(eb+1)+1>=ROM.FEXCESS) reduce();
-
-		DBIG d=BIG.mul(x,b.x);
-		x.copy(BIG.mod(d));
-	}
-
-/* this*=c mod Modulus, where c is a small int */
-	public void imul(int c)
-	{
-		norm();
-		boolean s=false;
-		if (c<0)
-		{
-			c=-c;
-			s=true;
-		}
-		long afx=(BIG.EXCESS(x)+1)*(c+1)+1;
-		if (c<ROM.NEXCESS && afx<ROM.FEXCESS)
-		{
-			x.imul(c);
-		}
-		else
-		{
-			if (afx<ROM.FEXCESS) x.pmul(c);
-			else
-			{
-				DBIG d=x.pxmul(c);
-				x.copy(d.mod(p));
-			}
-		}
-		if (s) neg();
-		norm();
-	}
-
-
-/* this*=this mod Modulus */
-	public void sqr()
-	{
-		DBIG d;
-		long ea=BIG.EXCESS(x);
-		if ((ea+1)*(ea+1)+1>=ROM.FEXCESS)
-			reduce();
-
-		d=BIG.sqr(x);
-		x.copy(BIG.mod(d));
-	}
-
-/* this+=b */
-	public void add(FP b) {
-		x.add(b.x);
-		if (BIG.EXCESS(x)+2>=ROM.FEXCESS) reduce();
-	}
-
-/* this = -this mod Modulus */
-	public void neg()
-	{
-		int sb;
-		long ov;
-		BIG m=new BIG(p);
-
-		norm();
-
-		ov=BIG.EXCESS(x);
-		sb=1; while(ov!=0) {sb++;ov>>=1;}
-
-		m.fshl(sb);
-		x.rsub(m);
-
-		if (BIG.EXCESS(x)>=ROM.FEXCESS) reduce();
-	}
-
-/* this-=b */
-	public void sub(FP b)
-	{
-		FP n=new FP(b);
-		n.neg();
-		this.add(n);
-	}
-
-/* this/=2 mod Modulus */
-	public void div2()
-	{
-		x.norm();
-		if (x.parity()==0)
-			x.fshr(1);
-		else
-		{
-			x.add(p);
-			x.norm();
-			x.fshr(1);
-		}
-	}
-
-/* this=1/this mod Modulus */
-	public void inverse()
-	{
-		BIG r=redc();
-		r.invmodp(p);
-		x.copy(r);
-		nres();
-	}
-
-/* return TRUE if this==a */
-	public boolean equals(FP a)
-	{
-		a.reduce();
-		reduce();
-		if (BIG.comp(a.x,x)==0) return true;
-		return false;
-	}
-
-/* reduce this mod Modulus */
-	public void reduce()
-	{
-		x.mod(p);
-	}
-
-/* return this^e mod Modulus */
-	public FP pow(BIG e)
-	{
-		int bt;
-		FP r=new FP(1);
-		e.norm();
-		x.norm();
-		FP m=new FP(this);
-		while (true)
-		{
-			bt=e.parity();
-			e.fshr(1);
-			if (bt==1) r.mul(m);
-			if (e.iszilch()) break;
-			m.sqr();
-		}
-		r.x.mod(p);
-		return r;
-	}
-
-/* return sqrt(this) mod Modulus */
-	public FP sqrt()
-	{
-		reduce();
-		BIG b=new BIG(p);
-		if (ROM.MOD8==5)
-		{
-			b.dec(5); b.norm(); b.shr(3);
-			FP i=new FP(this); i.x.shl(1);
-			FP v=i.pow(b);
-			i.mul(v); i.mul(v);
-			i.x.dec(1);
-			FP r=new FP(this);
-			r.mul(v); r.mul(i);
-			r.reduce();
-			return r;
-		}
-		else
-		{
-			b.inc(1); b.norm(); b.shr(2);
-			return pow(b);
-		}
-	}
-
-/* return jacobi symbol (this/Modulus) */
-	public int jacobi()
-	{
-		BIG w=redc();
-		return w.jacobi(p);
-	}
-/*
-	public static void main(String[] args) {
-		BIG m=new BIG(ROM.Modulus);
-		BIG x=new BIG(3);
-		BIG e=new BIG(m);
-		e.dec(1);
-
-		System.out.println("m= "+m.nbits());
-
-
-		BIG r=x.powmod(e,m);
-
-		System.out.println("m= "+m.toString());
-		System.out.println("r= "+r.toString());
-
-		BIG.cswap(m,r,0);
-
-		System.out.println("m= "+m.toString());
-		System.out.println("r= "+r.toString());
-
-//		FP y=new FP(3);
-//		FP s=y.pow(e);
-//		System.out.println("s= "+s.toString());
-
-	} */
-}
diff --git a/java64/FP12.java b/java64/FP12.java
deleted file mode 100755
index 1242652..0000000
--- a/java64/FP12.java
+++ /dev/null
@@ -1,640 +0,0 @@
-/*
-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.
-*/
-
-/* AMCL Fp^12 functions */
-/* FP12 elements are of the form a+i.b+i^2.c */
-
-public final class FP12 {
-	private final FP4 a;
-	private final FP4 b;
-	private final FP4 c;
-/* reduce all components of this mod Modulus */
-	public void reduce()
-	{
-		a.reduce();
-		b.reduce();
-		c.reduce();
-	}
-/* normalise all components of this */
-	public void norm()
-	{
-		a.norm();
-		b.norm();
-		c.norm();
-	}
-/* test x==0 ? */
-	public boolean iszilch() {
-		reduce();
-		return (a.iszilch() && b.iszilch() && c.iszilch());
-	}
-/* test x==1 ? */
-	public boolean isunity() {
-		FP4 one=new FP4(1);
-		return (a.equals(one) && b.iszilch() && c.iszilch());
-	}
-/* return 1 if x==y, else 0 */
-	public boolean equals(FP12 x)
-	{
-		return (a.equals(x.a) && b.equals(x.b) && c.equals(x.c));
-	}
-/* extract a from this */
-	public FP4 geta()
-	{
-		return a;
-	}
-/* extract b */
-	public FP4 getb()
-	{
-		return b;
-	}
-/* extract c */
-	public FP4 getc()
-	{
-		return c;
-	}
-/* copy this=x */
-	public void copy(FP12 x)
-	{
-		a.copy(x.a);
-		b.copy(x.b);
-		c.copy(x.c);
-	}
-/* set this=1 */
-	public void one()
-	{
-		a.one();
-		b.zero();
-		c.zero();
-	}
-/* this=conj(this) */
-	public void conj()
-	{
-		a.conj();
-		b.nconj();
-		c.conj();
-	}
-/* Constructors */
-	public FP12(FP4 d)
-	{
-		a=new FP4(d);
-		b=new FP4(0);
-		c=new FP4(0);
-	}
-
-	public FP12(int d)
-	{
-		a=new FP4(d);
-		b=new FP4(0);
-		c=new FP4(0);
-	}
-
-	public FP12(FP4 d,FP4 e,FP4 f)
-	{
-		a=new FP4(d);
-		b=new FP4(e);
-		c=new FP4(f);
-	}
-
-	public FP12(FP12 x)
-	{
-		a=new FP4(x.a);
-		b=new FP4(x.b);
-		c=new FP4(x.c);
-	}
-
-/* Granger-Scott Unitary Squaring */
-	public void usqr()
-	{
-		FP4 A=new FP4(a);
-		FP4 B=new FP4(c);
-		FP4 C=new FP4(b);
-		FP4 D=new FP4(0);
-
-		a.sqr();
-		D.copy(a); D.add(a);
-		a.add(D);
-
-//		a.norm();
-		A.nconj();
-
-		A.add(A);
-		a.add(A);
-		B.sqr();
-		B.times_i();
-
-		D.copy(B); D.add(B);
-		B.add(D);
-//		B.norm();
-
-		C.sqr();
-		D.copy(C); D.add(C);
-		C.add(D);
-//		C.norm();
-
-		b.conj();
-		b.add(b);
-		c.nconj();
-
-		c.add(c);
-		b.add(B);
-		c.add(C);
-		reduce();
-
-	}
-
-/* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
-	public void sqr()
-	{
-		FP4 A=new FP4(a);
-		FP4 B=new FP4(b);
-		FP4 C=new FP4(c);
-		FP4 D=new FP4(a);
-
-		A.sqr();
-		B.mul(c);
-		B.add(B);
-		C.sqr();
-		D.mul(b);
-		D.add(D);
-
-		c.add(a);
-		c.add(b);
-		c.sqr();
-
-		a.copy(A);
-
-		A.add(B);
-//		A.norm();
-		A.add(C);
-		A.add(D);
-//		A.norm();
-
-		A.neg();
-		B.times_i();
-		C.times_i();
-
-		a.add(B);
-
-		b.copy(C); b.add(D);
-		c.add(A);
-		norm();
-	}
-
-/* FP12 full multiplication this=this*y */
-	public void mul(FP12 y)
-	{
-		FP4 z0=new FP4(a);
-		FP4 z1=new FP4(0);
-		FP4 z2=new FP4(b);
-		FP4 z3=new FP4(0);
-		FP4 t0=new FP4(a);
-		FP4 t1=new FP4(y.a);
-
-		z0.mul(y.a);
-		z2.mul(y.b);
-
-		t0.add(b);
-		t1.add(y.b);
-
-		z1.copy(t0); z1.mul(t1);
-		t0.copy(b); t0.add(c);
-
-		t1.copy(y.b); t1.add(y.c);
-		z3.copy(t0); z3.mul(t1);
-
-		t0.copy(z0); t0.neg();
-		t1.copy(z2); t1.neg();
-
-		z1.add(t0);
-//		z1.norm();
-		b.copy(z1); b.add(t1);
-
-		z3.add(t1);
-		z2.add(t0);
-
-		t0.copy(a); t0.add(c);
-		t1.copy(y.a); t1.add(y.c);
-		t0.mul(t1);
-		z2.add(t0);
-
-		t0.copy(c); t0.mul(y.c);
-		t1.copy(t0); t1.neg();
-
-//		z2.norm();
-//		z3.norm();
-//		b.norm();
-
-		c.copy(z2); c.add(t1);
-		z3.add(t1);
-		t0.times_i();
-		b.add(t0);
-
-		z3.times_i();
-		a.copy(z0); a.add(z3);
-		norm();
-	}
-
-/* Special case of multiplication arises from special form of ATE pairing line function */
-	public void smul(FP12 y)
-	{
-		FP4 z0=new FP4(a);
-		FP4 z2=new FP4(b);
-		FP4 z3=new FP4(b);
-		FP4 t0=new FP4(0);
-		FP4 t1=new FP4(y.a);
-
-		z0.mul(y.a);
-		z2.pmul(y.b.real());
-		b.add(a);
-		t1.real().add(y.b.real());
-
-		b.mul(t1);
-		z3.add(c);
-		z3.pmul(y.b.real());
-
-		t0.copy(z0); t0.neg();
-		t1.copy(z2); t1.neg();
-
-		b.add(t0);
-//		b.norm();
-
-		b.add(t1);
-		z3.add(t1);
-		z2.add(t0);
-
-		t0.copy(a); t0.add(c);
-		t0.mul(y.a);
-		c.copy(z2); c.add(t0);
-
-		z3.times_i();
-		a.copy(z0); a.add(z3);
-
-		norm();
-	}
-
-/* this=1/this */
-	public void inverse()
-	{
-		FP4 f0=new FP4(a);
-		FP4 f1=new FP4(b);
-		FP4 f2=new FP4(a);
-		FP4 f3=new FP4(0);
-
-		norm();
-		f0.sqr();
-		f1.mul(c);
-		f1.times_i();
-		f0.sub(f1);
-
-		f1.copy(c); f1.sqr();
-		f1.times_i();
-		f2.mul(b);
-		f1.sub(f2);
-
-		f2.copy(b); f2.sqr();
-		f3.copy(a); f3.mul(c);
-		f2.sub(f3);
-
-		f3.copy(b); f3.mul(f2);
-		f3.times_i();
-		a.mul(f0);
-		f3.add(a);
-		c.mul(f1);
-		c.times_i();
-
-		f3.add(c);
-		f3.inverse();
-		a.copy(f0); a.mul(f3);
-		b.copy(f1); b.mul(f3);
-		c.copy(f2); c.mul(f3);
-	}
-
-/* this=this^p using Frobenius */
-	public void frob(FP2 f)
-	{
-		FP2 f2=new FP2(f);
-		FP2 f3=new FP2(f);
-
-		f2.sqr();
-		f3.mul(f2);
-
-		a.frob(f3);
-		b.frob(f3);
-		c.frob(f3);
-
-		b.pmul(f);
-		c.pmul(f2);
-	}
-
-/* trace function */
-	public FP4 trace()
-	{
-		FP4 t=new FP4(0);
-		t.copy(a);
-		t.imul(3);
-		t.reduce();
-		return t;
-	}
-
-/* convert from byte array to FP12 */
-	public static FP12 fromBytes(byte[] w)
-	{
-		BIG a,b;
-		FP2 c,d;
-		FP4 e,f,g;
-		byte[] t=new byte[ROM.MODBYTES];
-
-		for (int i=0;i<ROM.MODBYTES;i++) t[i]=w[i];
-		a=BIG.fromBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++) t[i]=w[i+ROM.MODBYTES];
-		b=BIG.fromBytes(t);
-		c=new FP2(a,b);
-
-		for (int i=0;i<ROM.MODBYTES;i++) t[i]=w[i+2*ROM.MODBYTES];
-		a=BIG.fromBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++) t[i]=w[i+3*ROM.MODBYTES];
-		b=BIG.fromBytes(t);
-		d=new FP2(a,b);
-
-		e=new FP4(c,d);
-
-
-		for (int i=0;i<ROM.MODBYTES;i++) t[i]=w[i+4*ROM.MODBYTES];
-		a=BIG.fromBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++) t[i]=w[i+5*ROM.MODBYTES];
-		b=BIG.fromBytes(t);
-		c=new FP2(a,b);
-
-		for (int i=0;i<ROM.MODBYTES;i++) t[i]=w[i+6*ROM.MODBYTES];
-		a=BIG.fromBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++) t[i]=w[i+7*ROM.MODBYTES];
-		b=BIG.fromBytes(t);
-		d=new FP2(a,b);
-
-		f=new FP4(c,d);
-
-
-		for (int i=0;i<ROM.MODBYTES;i++) t[i]=w[i+8*ROM.MODBYTES];
-		a=BIG.fromBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++) t[i]=w[i+9*ROM.MODBYTES];
-		b=BIG.fromBytes(t);
-		c=new FP2(a,b);
-
-		for (int i=0;i<ROM.MODBYTES;i++) t[i]=w[i+10*ROM.MODBYTES];
-		a=BIG.fromBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++) t[i]=w[i+11*ROM.MODBYTES];
-		b=BIG.fromBytes(t);
-		d=new FP2(a,b);
-
-		g=new FP4(c,d);
-
-		return new FP12(e,f,g);
-	}
-
-/* convert this to byte array */
-	public void toBytes(byte[] w)
-	{
-		byte[] t=new byte[ROM.MODBYTES];
-		a.geta().getA().toBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++) w[i]=t[i];
-		a.geta().getB().toBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++) w[i+ROM.MODBYTES]=t[i];
-		a.getb().getA().toBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++) w[i+2*ROM.MODBYTES]=t[i];
-		a.getb().getB().toBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++) w[i+3*ROM.MODBYTES]=t[i];
-
-		b.geta().getA().toBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++) w[i+4*ROM.MODBYTES]=t[i];
-		b.geta().getB().toBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++) w[i+5*ROM.MODBYTES]=t[i];
-		b.getb().getA().toBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++) w[i+6*ROM.MODBYTES]=t[i];
-		b.getb().getB().toBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++) w[i+7*ROM.MODBYTES]=t[i];
-
-		c.geta().getA().toBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++) w[i+8*ROM.MODBYTES]=t[i];
-		c.geta().getB().toBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++) w[i+9*ROM.MODBYTES]=t[i];
-		c.getb().getA().toBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++) w[i+10*ROM.MODBYTES]=t[i];
-		c.getb().getB().toBytes(t);
-		for (int i=0;i<ROM.MODBYTES;i++) w[i+11*ROM.MODBYTES]=t[i];
-	}
-
-/* convert to hex string */
-	public String toString()
-	{
-		return ("["+a.toString()+","+b.toString()+","+c.toString()+"]");
-	}
-
-/* this=this^e */
-	public FP12 pow(BIG e)
-	{
-		norm();
-		e.norm();
-		FP12 w=new FP12(this);
-		BIG z=new BIG(e);
-		FP12 r=new FP12(1);
-
-		while (true)
-		{
-			int bt=z.parity();
-			z.fshr(1);
-			if (bt==1) r.mul(w);
-			if (z.iszilch()) break;
-			w.usqr();
-		}
-		r.reduce();
-		return r;
-	}
-
-/* constant time powering by small integer of max length bts */
-	public void pinpow(int e,int bts)
-	{
-		int i,b;
-		FP12 [] R=new FP12[2];
-		R[0]=new FP12(1);
-		R[1]=new FP12(this);
-		for (i=bts-1;i>=0;i--)
-		{
-			b=(e>>i)&1;
-			R[1-b].mul(R[b]);
-			R[b].usqr();
-		}
-		this.copy(R[0]);
-	}
-
-/* p=q0^u0.q1^u1.q2^u2.q3^u3 */
-/* Timing attack secure, but not cache attack secure */
-
-	public static FP12 pow4(FP12[] q,BIG[] u)
-	{
-		int i,j,nb,m;
-		int[] a=new int[4];
-		FP12 [] g=new FP12[8];
-		FP12 [] s=new FP12[2];
-		FP12 c=new FP12(1);
-		FP12 p=new FP12(0);
-		BIG [] t=new BIG[4];
-		BIG mt=new BIG(0);
-		byte[] w=new byte[ROM.NLEN*ROM.BASEBITS+1];
-
-		for (i=0;i<4;i++)
-			t[i]=new BIG(u[i]);
-
-		s[0]=new FP12(0);
-		s[1]=new FP12(0);
-
-		g[0]=new FP12(q[0]); s[0].copy(q[1]); s[0].conj(); g[0].mul(s[0]);
-		g[1]=new FP12(g[0]);
-		g[2]=new FP12(g[0]);
-		g[3]=new FP12(g[0]);
-		g[4]=new FP12(q[0]); g[4].mul(q[1]);
-		g[5]=new FP12(g[4]);
-		g[6]=new FP12(g[4]);
-		g[7]=new FP12(g[4]);
-
-		s[1].copy(q[2]); s[0].copy(q[3]); s[0].conj(); s[1].mul(s[0]);
-		s[0].copy(s[1]); s[0].conj(); g[1].mul(s[0]);
-		g[2].mul(s[1]);
-		g[5].mul(s[0]);
-		g[6].mul(s[1]);
-		s[1].copy(q[2]); s[1].mul(q[3]);
-		s[0].copy(s[1]); s[0].conj(); g[0].mul(s[0]);
-		g[3].mul(s[1]);
-		g[4].mul(s[0]);
-		g[7].mul(s[1]);
-
-/* if power is even add 1 to power, and add q to correction */
-
-		for (i=0;i<4;i++)
-		{
-			if (t[i].parity()==0)
-			{
-				t[i].inc(1); t[i].norm();
-				c.mul(q[i]);
-			}
-			mt.add(t[i]); mt.norm();
-		}
-		c.conj();
-		nb=1+mt.nbits();
-
-/* convert exponent to signed 1-bit window */
-		for (j=0;j<nb;j++)
-		{
-			for (i=0;i<4;i++)
-			{
-				a[i]=(t[i].lastbits(2)-2);
-				t[i].dec(a[i]); t[i].norm();
-				t[i].fshr(1);
-			}
-			w[j]=(byte)(8*a[0]+4*a[1]+2*a[2]+a[3]);
-		}
-		w[nb]=(byte)(8*t[0].lastbits(2)+4*t[1].lastbits(2)+2*t[2].lastbits(2)+t[3].lastbits(2));
-		p.copy(g[(w[nb]-1)/2]);
-
-		for (i=nb-1;i>=0;i--)
-		{
-			m=w[i]>>7;
-			j=(w[i]^m)-m;  /* j=abs(w[i]) */
-			j=(j-1)/2;
-			s[0].copy(g[j]); s[1].copy(g[j]); s[1].conj();
-			p.usqr();
-			p.mul(s[m&1]);
-		}
-		p.mul(c);  /* apply correction */
-		p.reduce();
-		return p;
-	}
-
-/*
-	public static void main(String[] args) {
-		BIG p=new BIG(ROM.Modulus);
-		FP2 w0,w1;
-		BIG a=new BIG(0);
-		BIG b=new BIG(0);
-
-		a.zero(); b.zero(); a.inc(1); b.inc(2);
-		w0=new FP2(a,b);
-		a.zero(); b.zero(); a.inc(3); b.inc(4);
-		w1=new FP2(a,b);
-		FP4 t0=new FP4(w0,w1);
-
-		a.zero(); b.zero(); a.inc(5); b.inc(6);
-		w0=new FP2(a,b);
-		a.zero(); b.zero(); a.inc(7); b.inc(8);
-		w1=new FP2(a,b);
-		FP4 t1=new FP4(w0,w1);
-
-		a.zero(); b.zero(); a.inc(9); b.inc(10);
-		w0=new FP2(a,b);
-		a.zero(); b.zero(); a.inc(11); b.inc(12);
-		w1=new FP2(a,b);
-		FP4 t2=new FP4(w0,w1);
-
-		FP12 w=new FP12(t0,t1,t2);
-		FP12 t=new FP12(w);
-
-		System.out.println("w= "+w.toString());
-
-		a=new BIG(ROM.CURVE_Fra);
-		b=new BIG(ROM.CURVE_Frb);
-
-		FP2 f=new FP2(a,b);
-
-		w.frob(f);
-		System.out.println("w= "+w.toString());
-
-		w=t.pow(p);
-
-		System.out.println("w= "+w.toString());
-
-		w.inverse();
-
-		System.out.println("1/w= "+w.toString());
-
-		w.inverse();
-
-		System.out.println("w= "+w.toString());
-
-		t.copy(w);
-		w.conj();
-		t.inverse();
-		w.mul(t);
-
-		System.out.println("w^(p^6-1)= "+w.toString());
-
-		t.copy(w);
-		w.frob(f);
-		w.frob(f);
-		w.mul(t);
-
-		System.out.println("w^(p^6-1)(p^2+1)= "+w.toString());
-
-		t.copy(w);
-
-		t.inverse();
-		w.conj();
-
-		System.out.println("w= "+w.toString());
-		System.out.println("t= "+t.toString());
-	} */
-}
diff --git a/java64/FP2.java b/java64/FP2.java
deleted file mode 100755
index 48e2b7e..0000000
--- a/java64/FP2.java
+++ /dev/null
@@ -1,391 +0,0 @@
-/*
-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.
-*/
-
-/* Finite Field arithmetic  Fp^2 functions */
-
-/* FP2 elements are of the form a+ib, where i is sqrt(-1) */
-
-public final class FP2 {
-	private final FP a;
-	private final FP b;
-
-/* reduce components mod Modulus */
-	public void reduce()
-	{
-		a.reduce();
-		b.reduce();
-	}
-
-/* normalise components of w */
-	public void norm()
-	{
-		a.norm();
-		b.norm();
-	}
-
-/* test this=0 ? */
-	public boolean iszilch() {
-		reduce();
-		return (a.iszilch() && b.iszilch());
-	}
-
-	public void cmove(FP2 g,int d)
-	{
-		a.cmove(g.a,d);
-		b.cmove(g.b,d);
-	}
-
-/* test this=1 ? */
-	public boolean isunity() {
-		FP one=new FP(1);
-		return (a.equals(one) && b.iszilch());
-	}
-
-/* test this=x */
-	public boolean equals(FP2 x) {
-		return (a.equals(x.a) && b.equals(x.b));
-	}
-
-/* Constructors */
-	public FP2(int c)
-	{
-		a=new FP(c);
-		b=new FP(0);
-	}
-
-	public FP2(FP2 x)
-	{
-		a=new FP(x.a);
-		b=new FP(x.b);
-	}
-
-	public FP2(FP c,FP d)
-	{
-		a=new FP(c);
-		b=new FP(d);
-	}
-
-	public FP2(BIG c,BIG d)
-	{
-		a=new FP(c);
-		b=new FP(d);
-	}
-
-	public FP2(FP c)
-	{
-		a=new FP(c);
-		b=new FP(0);
-	}
-
-	public FP2(BIG c)
-	{
-		a=new FP(c);
-		b=new FP(0);
-	}
-
-/* extract a */
-	public BIG getA()
-	{
-		return a.redc();
-	}
-
-/* extract b */
-	public BIG getB()
-	{
-		return b.redc();
-	}
-
-/* copy this=x */
-	public void copy(FP2 x)
-	{
-		a.copy(x.a);
-		b.copy(x.b);
-	}
-
-/* set this=0 */
-	public void zero()
-	{
-		a.zero();
-		b.zero();
-	}
-
-/* set this=1 */
-	public void one()
-	{
-		a.one();
-		b.zero();
-	}
-
-/* negate this mod Modulus */
-	public void neg()
-	{
-		norm();
-		FP m=new FP(a);
-		FP t=new FP(0);
-
-		m.add(b);
-		m.neg();
-		m.norm();
-		t.copy(m); t.add(b);
-		b.copy(m);
-		b.add(a);
-		a.copy(t);
-	}
-
-/* set to a-ib */
-	public void conj()
-	{
-		b.neg();
-	}
-
-/* this+=a */
-	public void add(FP2 x)
-	{
-		a.add(x.a);
-		b.add(x.b);
-	}
-
-/* this-=a */
-	public void sub(FP2 x)
-	{
-		FP2 m=new FP2(x);
-		m.neg();
-		add(m);
-	}
-
-/* this*=s, where s is an FP */
-	public void pmul(FP s)
-	{
-		a.mul(s);
-		b.mul(s);
-	}
-
-/* this*=i, where i is an int */
-	public void imul(int c)
-	{
-		a.imul(c);
-		b.imul(c);
-	}
-
-/* this*=this */
-	public void sqr()
-	{
-		norm();
-		FP w1=new FP(a);
-		FP w3=new FP(a);
-		FP mb=new FP(b);
-
-		w3.mul(b);
-		w1.add(b);
-		mb.neg();
-		a.add(mb);
-		a.mul(w1);
-		b.copy(w3); b.add(w3);
-//		reduce();
-		norm();
-	}
-
-/* this*=y */
-	public void mul(FP2 y)
-	{
-		norm();  /* This is needed here as {a,b} is not normed before additions */
-
-		FP w1=new FP(a);
-		FP w2=new FP(b);
-		FP w5=new FP(a);
-		FP mw=new FP(0);
-
-		w1.mul(y.a);  // w1=a*y.a  - this norms w1 and y.a, NOT a
-		w2.mul(y.b);  // w2=b*y.b  - this norms w2 and y.b, NOT b
-		w5.add(b);    // w5=a+b
-		b.copy(y.a); b.add(y.b); // b=y.a+y.b
-
-		b.mul(w5);
-		mw.copy(w1); mw.add(w2); mw.neg();
-
-		b.add(mw); mw.add(w1);
-		a.copy(w1);	a.add(mw);
-
-//		reduce();
-		norm();
-	}
-
-
-/* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */
-/* returns true if this is QR */
-	public boolean sqrt()
-	{
-		if (iszilch()) return true;
-		FP w1=new FP(b);
-		FP w2=new FP(a);
-		w1.sqr(); w2.sqr(); w1.add(w2);
-		if (w1.jacobi()!=1) { zero(); return false; }
-		w1=w1.sqrt();
-		w2.copy(a); w2.add(w1); w2.div2();
-		if (w2.jacobi()!=1)
-		{
-			w2.copy(a); w2.sub(w1); w2.div2();
-			if (w2.jacobi()!=1) { zero(); return false; }
-		}
-		w2=w2.sqrt();
-		a.copy(w2);
-		w2.add(w2);
-		w2.inverse();
-		b.mul(w2);
-		return true;
-	}
-
-/* output to hex string */
-	public String toString()
-	{
-		return ("["+a.toString()+","+b.toString()+"]");
-	}
-
-	public String toRawString()
-	{
-		return ("["+a.toRawString()+","+b.toRawString()+"]");
-	}
-
-/* this=1/this */
-	public void inverse()
-	{
-		norm();
-		FP w1=new FP(a);
-		FP w2=new FP(b);
-
-		w1.sqr();
-		w2.sqr();
-		w1.add(w2);
-		w1.inverse();
-		a.mul(w1);
-		w1.neg();
-		b.mul(w1);
-	}
-
-/* this/=2 */
-	public void div2()
-	{
-		a.div2();
-		b.div2();
-	}
-
-/* this*=sqrt(-1) */
-	public void times_i()
-	{
-	//	a.norm();
-		FP z=new FP(a);
-		a.copy(b); a.neg();
-		b.copy(z);
-	}
-
-/* w*=(1+sqrt(-1)) */
-/* where X*2-(1+sqrt(-1)) is irreducible for FP4, assumes p=3 mod 8 */
-	public void mul_ip()
-	{
-		norm();
-		FP2 t=new FP2(this);
-		FP z=new FP(a);
-		a.copy(b);
-		a.neg();
-		b.copy(z);
-		add(t);
-		norm();
-	}
-
-/* w/=(1+sqrt(-1)) */
-	public void div_ip()
-	{
-		FP2 t=new FP2(0);
-		norm();
-		t.a.copy(a); t.a.add(b);
-		t.b.copy(b); t.b.sub(a);
-		copy(t);
-		div2();
-	}
-/*
-	public FP2 pow(BIG e)
-	{
-		int bt;
-		FP2 r=new FP2(1);
-		e.norm();
-		norm();
-		while (true)
-		{
-			bt=e.parity();
-			e.fshr(1);
-			if (bt==1) r.mul(this);
-			if (e.iszilch()) break;
-			sqr();
-		}
-
-		r.reduce();
-		return r;
-	}
-
-	public static void main(String[] args) {
-		BIG m=new BIG(ROM.Modulus);
-		BIG x=new BIG(3);
-		BIG e=new BIG(27);
-		BIG pp1=new BIG(m);
-		BIG pm1=new BIG(m);
-		BIG a=new BIG(1);
-		BIG b=new BIG(1);
-		FP2 w=new FP2(a,b);
-		FP2 z=new FP2(w);
-
-		byte[] RAW=new byte[100];
-
-		RAND rng=new RAND();
-		for (int i=0;i<100;i++) RAW[i]=(byte)(i);
-
-		rng.seed(100,RAW);
-
-	//	for (int i=0;i<100;i++)
-	//	{
-			a.randomnum(rng);
-			b.randomnum(rng);
-
-			w=new FP2(a,b);
-			System.out.println("w="+w.toString());
-
-			z=new FP2(w);
-			z.inverse();
-			System.out.println("z="+z.toString());
-
-			z.inverse();
-			if (!z.equals(w)) System.out.println("Error");
-	//	}
-
-//		System.out.println("m="+m.toString());
-//		w.sqr();
-//		w.mul(z);
-
-		System.out.println("w="+w.toString());
-
-
-		pp1.inc(1); pp1.norm();
-		pm1.dec(1); pm1.norm();
-		System.out.println("p+1="+pp1.toString());
-		System.out.println("p-1="+pm1.toString());
-		w=w.pow(pp1);
-		w=w.pow(pm1);
-		System.out.println("w="+w.toString());
-	}
-*/
-}
diff --git a/java64/FP4.java b/java64/FP4.java
deleted file mode 100755
index 5eaa78d..0000000
--- a/java64/FP4.java
+++ /dev/null
@@ -1,585 +0,0 @@
-/*
-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.
-*/
-
-/* Finite Field arithmetic  Fp^4 functions */
-
-/* FP4 elements are of the form a+ib, where i is sqrt(-1+sqrt(-1))  */
-
-public final class FP4 {
-	private final FP2 a;
-	private final FP2 b;
-/* reduce all components of this mod Modulus */
-	public void reduce()
-	{
-		a.reduce();
-		b.reduce();
-	}
-/* normalise all components of this mod Modulus */
-	public void norm()
-	{
-		a.norm();
-		b.norm();
-	}
-/* test this==0 ? */
-	public boolean iszilch() {
-		reduce();
-		return (a.iszilch() && b.iszilch());
-	}
-/* test this==1 ? */
-	public boolean isunity() {
-		FP2 one=new FP2(1);
-		return (a.equals(one) && b.iszilch());
-	}
-
-/* test is w real? That is in a+ib test b is zero */
-	public boolean isreal()
-	{
-		return b.iszilch();
-	}
-/* extract real part a */
-	public FP2 real()
-	{
-		return a;
-	}
-
-	public FP2 geta()
-	{
-		return a;
-	}
-/* extract imaginary part b */
-	public FP2 getb()
-	{
-		return b;
-	}
-/* test this=x? */
-	public boolean equals(FP4 x)
-	{
-		return (a.equals(x.a) && b.equals(x.b));
-	}
-/* constructors */
-	public FP4(int c)
-	{
-		a=new FP2(c);
-		b=new FP2(0);
-	}
-
-	public FP4(FP4 x)
-	{
-		a=new FP2(x.a);
-		b=new FP2(x.b);
-	}
-
-	public FP4(FP2 c,FP2 d)
-	{
-		a=new FP2(c);
-		b=new FP2(d);
-	}
-
-	public FP4(FP2 c)
-	{
-		a=new FP2(c);
-		b=new FP2(0);
-	}
-/* copy this=x */
-	public void copy(FP4 x)
-	{
-		a.copy(x.a);
-		b.copy(x.b);
-	}
-/* set this=0 */
-	public void zero()
-	{
-		a.zero();
-		b.zero();
-	}
-/* set this=1 */
-	public void one()
-	{
-		a.one();
-		b.zero();
-	}
-/* set this=-this */
-	public void neg()
-	{
-		FP2 m=new FP2(a);
-		FP2 t=new FP2(0);
-		m.add(b);
-		m.neg();
-		m.norm();
-		t.copy(m); t.add(b);
-		b.copy(m);
-		b.add(a);
-		a.copy(t);
-	}
-/* this=conjugate(this) */
-	public void conj()
-	{
-		b.neg(); b.norm();
-	}
-/* this=-conjugate(this) */
-	public void nconj()
-	{
-		a.neg(); a.norm();
-	}
-/* this+=x */
-	public void add(FP4 x)
-	{
-		a.add(x.a);
-		b.add(x.b);
-	}
-/* this-=x */
-	public void sub(FP4 x)
-	{
-		FP4 m=new FP4(x);
-		m.neg();
-		add(m);
-	}
-
-/* this*=s where s is FP2 */
-	public void pmul(FP2 s)
-	{
-		a.mul(s);
-		b.mul(s);
-	}
-/* this*=c where c is int */
-	public void imul(int c)
-	{
-		a.imul(c);
-		b.imul(c);
-	}
-/* this*=this */
-	public void sqr()
-	{
-		norm();
-
-		FP2 t1=new FP2(a);
-		FP2 t2=new FP2(b);
-		FP2 t3=new FP2(a);
-
-		t3.mul(b);
-		t1.add(b);
-		t2.mul_ip();
-
-		t2.add(a);
-		a.copy(t1);
-
-		a.mul(t2);
-
-		t2.copy(t3);
-		t2.mul_ip();
-		t2.add(t3);
-		t2.neg();
-		a.add(t2);
-
-		b.copy(t3);
-		b.add(t3);
-
-		norm();
-	}
-/* this*=y */
-	public void mul(FP4 y)
-	{
-		norm();
-
-		FP2 t1=new FP2(a);
-		FP2 t2=new FP2(b);
-		FP2 t3=new FP2(0);
-		FP2 t4=new FP2(b);
-
-		t1.mul(y.a);
-		t2.mul(y.b);
-		t3.copy(y.b);
-		t3.add(y.a);
-		t4.add(a);
-
-		t4.mul(t3);
-		t4.sub(t1);
-//		t4.norm();
-
-		b.copy(t4);
-		b.sub(t2);
-		t2.mul_ip();
-		a.copy(t2);
-		a.add(t1);
-
-		norm();
-	}
-/* convert this to hex string */
-	public String toString()
-	{
-		return ("["+a.toString()+","+b.toString()+"]");
-	}
-
-	public String toRawString()
-	{
-		return ("["+a.toRawString()+","+b.toRawString()+"]");
-	}
-
-/* this=1/this */
-	public void inverse()
-	{
-		norm();
-
-		FP2 t1=new FP2(a);
-		FP2 t2=new FP2(b);
-
-		t1.sqr();
-		t2.sqr();
-		t2.mul_ip();
-		t1.sub(t2);
-		t1.inverse();
-		a.mul(t1);
-		t1.neg();
-		b.mul(t1);
-	}
-
-
-/* this*=i where i = sqrt(-1+sqrt(-1)) */
-	public void times_i()
-	{
-		norm();
-		FP2 s=new FP2(b);
-		FP2 t=new FP2(b);
-		s.times_i();
-		t.add(s);
-//		t.norm();
-		b.copy(a);
-		a.copy(t);
-	}
-
-/* this=this^p using Frobenius */
-	public void frob(FP2 f)
-	{
-		a.conj();
-		b.conj();
-		b.mul(f);
-	}
-
-/* this=this^e */
-	public FP4 pow(BIG e)
-	{
-		norm();
-		e.norm();
-		FP4 w=new FP4(this);
-		BIG z=new BIG(e);
-		FP4 r=new FP4(1);
-		while (true)
-		{
-			int bt=z.parity();
-			z.fshr(1);
-			if (bt==1) r.mul(w);
-			if (z.iszilch()) break;
-			w.sqr();
-		}
-		r.reduce();
-		return r;
-	}
-/* XTR xtr_a function */
-	public void xtr_A(FP4 w,FP4 y,FP4 z)
-	{
-		FP4 r=new FP4(w);
-		FP4 t=new FP4(w);
-		r.sub(y);
-		r.pmul(a);
-		t.add(y);
-		t.pmul(b);
-		t.times_i();
-
-		copy(r);
-		add(t);
-		add(z);
-
-		norm();
-	}
-
-/* XTR xtr_d function */
-	public void xtr_D() {
-		FP4 w=new FP4(this);
-		sqr(); w.conj();
-		w.add(w);
-		sub(w);
-		reduce();
-	}
-
-/* r=x^n using XTR method on traces of FP12s */
-	public FP4 xtr_pow(BIG n) {
-		FP4 a=new FP4(3);
-		FP4 b=new FP4(this);
-		FP4 c=new FP4(b);
-		c.xtr_D();
-		FP4 t=new FP4(0);
-		FP4 r=new FP4(0);
-
-		n.norm();
-		int par=n.parity();
-		BIG v=new BIG(n); v.fshr(1);
-		if (par==0) {v.dec(1); v.norm();}
-
-		int nb=v.nbits();
-		for (int i=nb-1;i>=0;i--)
-		{
-			if (v.bit(i)!=1)
-			{
-				t.copy(b);
-				conj();
-				c.conj();
-				b.xtr_A(a,this,c);
-				conj();
-				c.copy(t);
-				c.xtr_D();
-				a.xtr_D();
-			}
-			else
-			{
-				t.copy(a); t.conj();
-				a.copy(b);
-				a.xtr_D();
-				b.xtr_A(c,this,t);
-				c.xtr_D();
-			}
-		}
-		if (par==0) r.copy(c);
-		else r.copy(b);
-		r.reduce();
-		return r;
-	}
-
-/* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */
-	public FP4 xtr_pow2(FP4 ck,FP4 ckml,FP4 ckm2l,BIG a,BIG b)
-	{
-		a.norm(); b.norm();
-		BIG e=new BIG(a);
-		BIG d=new BIG(b);
-		BIG w=new BIG(0);
-
-		FP4 cu=new FP4(ck);  // can probably be passed in w/o copying
-		FP4 cv=new FP4(this);
-		FP4 cumv=new FP4(ckml);
-		FP4 cum2v=new FP4(ckm2l);
-		FP4 r=new FP4(0);
-		FP4 t=new FP4(0);
-
-		int f2=0;
-		while (d.parity()==0 && e.parity()==0)
-		{
-			d.fshr(1);
-			e.fshr(1);
-			f2++;
-		}
-
-		while (BIG.comp(d,e)!=0)
-		{
-			if (BIG.comp(d,e)>0)
-			{
-				w.copy(e); w.imul(4); w.norm();
-				if (BIG.comp(d,w)<=0)
-				{
-					w.copy(d); d.copy(e);
-					e.rsub(w); e.norm();
-
-					t.copy(cv);
-					t.xtr_A(cu,cumv,cum2v);
-					cum2v.copy(cumv);
-					cum2v.conj();
-					cumv.copy(cv);
-					cv.copy(cu);
-					cu.copy(t);
-
-				}
-				else if (d.parity()==0)
-				{
-					d.fshr(1);
-					r.copy(cum2v); r.conj();
-					t.copy(cumv);
-					t.xtr_A(cu,cv,r);
-					cum2v.copy(cumv);
-					cum2v.xtr_D();
-					cumv.copy(t);
-					cu.xtr_D();
-				}
-				else if (e.parity()==1)
-				{
-					d.sub(e); d.norm();
-					d.fshr(1);
-					t.copy(cv);
-					t.xtr_A(cu,cumv,cum2v);
-					cu.xtr_D();
-					cum2v.copy(cv);
-					cum2v.xtr_D();
-					cum2v.conj();
-					cv.copy(t);
-				}
-				else
-				{
-					w.copy(d);
-					d.copy(e); d.fshr(1);
-					e.copy(w);
-					t.copy(cumv);
-					t.xtr_D();
-					cumv.copy(cum2v); cumv.conj();
-					cum2v.copy(t); cum2v.conj();
-					t.copy(cv);
-					t.xtr_D();
-					cv.copy(cu);
-					cu.copy(t);
-				}
-			}
-			if (BIG.comp(d,e)<0)
-			{
-				w.copy(d); w.imul(4); w.norm();
-				if (BIG.comp(e,w)<=0)
-				{
-					e.sub(d); e.norm();
-					t.copy(cv);
-					t.xtr_A(cu,cumv,cum2v);
-					cum2v.copy(cumv);
-					cumv.copy(cu);
-					cu.copy(t);
-				}
-				else if (e.parity()==0)
-				{
-					w.copy(d);
-					d.copy(e); d.fshr(1);
-					e.copy(w);
-					t.copy(cumv);
-					t.xtr_D();
-					cumv.copy(cum2v); cumv.conj();
-					cum2v.copy(t); cum2v.conj();
-					t.copy(cv);
-					t.xtr_D();
-					cv.copy(cu);
-					cu.copy(t);
-				}
-				else if (d.parity()==1)
-				{
-					w.copy(e);
-					e.copy(d);
-					w.sub(d); w.norm();
-					d.copy(w); d.fshr(1);
-					t.copy(cv);
-					t.xtr_A(cu,cumv,cum2v);
-					cumv.conj();
-					cum2v.copy(cu);
-					cum2v.xtr_D();
-					cum2v.conj();
-					cu.copy(cv);
-					cu.xtr_D();
-					cv.copy(t);
-				}
-				else
-				{
-					d.fshr(1);
-					r.copy(cum2v); r.conj();
-					t.copy(cumv);
-					t.xtr_A(cu,cv,r);
-					cum2v.copy(cumv);
-					cum2v.xtr_D();
-					cumv.copy(t);
-					cu.xtr_D();
-				}
-			}
-		}
-		r.copy(cv);
-		r.xtr_A(cu,cumv,cum2v);
-		for (int i=0;i<f2;i++)
-			r.xtr_D();
-		r=r.xtr_pow(d);
-		return r;
-	}
-
-/*
-
-	public static void main(String[] args) {
-		BIG m=new BIG(ROM.Modulus);
-		BIG e=new BIG(12);
-		BIG a=new BIG(0);
-		BIG b=new BIG(0);
-
-		a.inc(27); b.inc(45);
-
-		FP2 w0=new FP2(a,b);
-
-		a.zero(); b.zero();
-		a.inc(33); b.inc(54);
-
-		FP2 w1=new FP2(a,b);
-
-
-		FP4 w=new FP4(w0,w1);
-		FP4 t=new FP4(w);
-
-		a=new BIG(ROM.CURVE_Fra);
-		b=new BIG(ROM.CURVE_Frb);
-
-		FP2 f=new FP2(a,b);
-
-		System.out.println("w= "+w.toString());
-
-		w=w.pow(m);
-
-		System.out.println("w^p= "+w.toString());
-
-		t.frob(f);
-
-
-		System.out.println("w^p= "+t.toString());
-
-		w=w.pow(m);
-		w=w.pow(m);
-		w=w.pow(m);
-		System.out.println("w^p4= "+w.toString());
-
-
-	System.out.println("Test Inversion");
-
-		w=new FP4(w0,w1);
-
-		w.inverse();
-
-		System.out.println("1/w mod p^4 = "+w.toString());
-
-		w.inverse();
-
-		System.out.println("1/(1/w) mod p^4 = "+w.toString());
-
-		FP4 ww=new FP4(w);
-
-		w=w.xtr_pow(e);
-		System.out.println("w^e= "+w.toString());
-
-
-		a.zero(); b.zero();
-		a.inc(37); b.inc(17);
-		w0=new FP2(a,b);
-		a.zero(); b.zero();
-		a.inc(49); b.inc(31);
-		w1=new FP2(a,b);
-
-		FP4 c1=new FP4(w0,w1);
-		FP4 c2=new FP4(w0,w1);
-		FP4 c3=new FP4(w0,w1);
-
-		BIG e1=new BIG(3331);
-		BIG e2=new BIG(3372);
-
-		FP4 cr=w.xtr_pow2(c1,c2,c3,e1,e2);
-
-		System.out.println("c^e= "+cr.toString());
-	} */
-}
diff --git a/java64/GCM.java b/java64/GCM.java
deleted file mode 100755
index 1422af9..0000000
--- a/java64/GCM.java
+++ /dev/null
@@ -1,374 +0,0 @@
-/*
-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.
-*/
-
-
-
-/*
- * Implementation of the AES-GCM Encryption/Authentication
- *
- * Some restrictions..
- * 1. Only for use with AES
- * 2. Returned tag is always 128-bits. Truncate at your own risk.
- * 3. The order of function calls must follow some rules
- *
- * Typical sequence of calls..
- * 1. call GCM_init
- * 2. call GCM_add_header any number of times, as long as length of header is multiple of 16 bytes (block size)
- * 3. call GCM_add_header one last time with any length of header
- * 4. call GCM_add_cipher any number of times, as long as length of cipher/plaintext is multiple of 16 bytes
- * 5. call GCM_add_cipher one last time with any length of cipher/plaintext
- * 6. call GCM_finish to extract the tag.
- *
- * See http://www.mindspring.com/~dmcgrew/gcm-nist-6.pdf
- */
-
-public class GCM {
-	public static final int NB=4;
-	public static final int GCM_ACCEPTING_HEADER=0;
-	public static final int GCM_ACCEPTING_CIPHER=1;
-	public static final int GCM_NOT_ACCEPTING_MORE=2;
-	public static final int GCM_FINISHED=3;
-	public static final int GCM_ENCRYPTING=0;
-	public static final int GCM_DECRYPTING=1;
-
-	private int[][] table=new int[128][4]; /* 2k bytes */
-	private byte[] stateX=new byte[16];
-	private byte[]Y_0=new byte[16];
-	private int counter;
-	private int[] lenA=new int[2];
-	private int[] lenC=new int[2];
-	private int status;
-	private AES a=new AES();
-
-	private static int pack(byte[] b)
-	{ /* pack bytes into a 32-bit Word */
-		return ((((int)b[0])&0xff)<<24)|(((int)b[1]&0xff)<<16)|(((int)b[2]&0xff)<<8)|((int)b[3]&0xff);
-	}
-
-	private static byte[] unpack(int a)
-	{ /* unpack bytes from a word */
-		byte [] b=new byte[4];
-		b[3]=(byte)(a);
-		b[2]=(byte)(a>>>8);
-		b[1]=(byte)(a>>>16);
-		b[0]=(byte)(a>>>24);
-		return b;
-	}
-
-	private void precompute(byte[] H)
-	{
-		int i,j,c;
-		byte[] b=new byte[4];
-
-		for (i=j=0;i<NB;i++,j+=4)
-		{
-			b[0]=H[j]; b[1]=H[j+1]; b[2]=H[j+2]; b[3]=H[j+3];
-			table[0][i]=pack(b);
-		}
-		for (i=1;i<128;i++)
-		{
-			c=0;
-			for (j=0;j<NB;j++) {table[i][j]=c|(table[i-1][j])>>>1; c=table[i-1][j]<<31;}
-			if (c!=0) table[i][0]^=0xE1000000; /* irreducible polynomial */
-		}
-	}
-
-	private void gf2mul()
-	{ /* gf2m mul - Z=H*X mod 2^128 */
-		int i,j,m,k;
-		int[] P=new int[4];
-		int c;
-		byte[] b;//=new byte[4];
-
-		P[0]=P[1]=P[2]=P[3]=0;
-		j=8; m=0;
-		for (i=0;i<128;i++)
-		{
-			c=(stateX[m]>>>(--j))&1;
-			if (c!=0) for (k=0;k<NB;k++) P[k]^=table[i][k];
-			if (j==0)
-			{
-				j=8; m++;
-				if (m==16) break;
-			}
-		}
-		for (i=j=0;i<NB;i++,j+=4)
-		{
-			b=unpack(P[i]);
-			stateX[j]=b[0]; stateX[j+1]=b[1]; stateX[j+2]=b[2]; stateX[j+3]=b[3];
-		}
-	}
-
-	private void wrap()
-	{ /* Finish off GHASH */
-		int i,j;
-		int[] F=new int[4];
-		byte[] L=new byte[16];
-		byte[] b;//=new byte[4];
-
-/* convert lengths from bytes to bits */
-		F[0]=(lenA[0]<<3)|(lenA[1]&0xE0000000)>>>29;
-		F[1]=lenA[1]<<3;
-		F[2]=(lenC[0]<<3)|(lenC[1]&0xE0000000)>>>29;
-		F[3]=lenC[1]<<3;
-		for (i=j=0;i<NB;i++,j+=4)
-		{
-			b=unpack(F[i]);
-			L[j]=b[0]; L[j+1]=b[1]; L[j+2]=b[2]; L[j+3]=b[3];
-		}
-		for (i=0;i<16;i++) stateX[i]^=L[i];
-		gf2mul();
-	}
-
-/* Initialize GCM mode */
-	public void init(byte[] key,int niv,byte[] iv)
-	{ /* iv size niv is usually 12 bytes (96 bits). AES key size nk can be 16,24 or 32 bytes */
-		int i;
-		byte[] H=new byte[16];
-		byte[] b;//=new byte[4];
-
-		for (i=0;i<16;i++) {H[i]=0; stateX[i]=0;}
-
-		a.init(AES.ECB,key,iv);
-		a.ecb_encrypt(H);     /* E(K,0) */
-		precompute(H);
-
-		lenA[0]=lenC[0]=lenA[1]=lenC[1]=0;
-		if (niv==12)
-		{
-			for (i=0;i<12;i++) a.f[i]=iv[i];
-			b=unpack((int)1);
-			a.f[12]=b[0]; a.f[13]=b[1]; a.f[14]=b[2]; a.f[15]=b[3];  /* initialise IV */
-			for (i=0;i<16;i++) Y_0[i]=a.f[i];
-		}
-		else
-		{
-			status=GCM_ACCEPTING_CIPHER;
-			ghash(iv,niv); /* GHASH(H,0,IV) */
-			wrap();
-			for (i=0;i<16;i++) {a.f[i]=stateX[i];Y_0[i]=a.f[i];stateX[i]=0;}
-			lenA[0]=lenC[0]=lenA[1]=lenC[1]=0;
-		}
-		status=GCM_ACCEPTING_HEADER;
-	}
-
-/* Add Header data - included but not encrypted */
-	public boolean add_header(byte[] header,int len)
-	{ /* Add some header. Won't be encrypted, but will be authenticated. len is length of header */
-		int i,j=0;
-		if (status!=GCM_ACCEPTING_HEADER) return false;
-
-		while (j<len)
-		{
-			for (i=0;i<16 && j<len;i++)
-			{
-				stateX[i]^=header[j++];
-				lenA[1]++; if (lenA[1]==0) lenA[0]++;
-			}
-			gf2mul();
-		}
-		if (len%16!=0) status=GCM_ACCEPTING_CIPHER;
-		return true;
-	}
-
-	private boolean ghash(byte[] plain,int len)
-	{
-		int i,j=0;
-		int counter;
-	//	byte[] B=new byte[16];
-	//	byte[] b=new byte[4];
-
-		if (status==GCM_ACCEPTING_HEADER) status=GCM_ACCEPTING_CIPHER;
-		if (status!=GCM_ACCEPTING_CIPHER) return false;
-
-		while (j<len)
-		{
-			for (i=0;i<16 && j<len;i++)
-			{
-				stateX[i]^=plain[j++];
-				lenC[1]++; if (lenC[1]==0) lenC[0]++;
-			}
-			gf2mul();
-		}
-		if (len%16!=0) status=GCM_NOT_ACCEPTING_MORE;
-		return true;
-	}
-
-/* Add Plaintext - included and encrypted */
-	public byte[] add_plain(byte[] plain,int len)
-	{
-		int i,j=0;
-		int counter;
-		byte[] B=new byte[16];
-		byte[] b=new byte[4];
-		byte[] cipher=new byte[len];
-
-		if (status==GCM_ACCEPTING_HEADER) status=GCM_ACCEPTING_CIPHER;
-		if (status!=GCM_ACCEPTING_CIPHER) return new byte[0];
-
-		while (j<len)
-		{
-
-			b[0]=a.f[12]; b[1]=a.f[13]; b[2]=a.f[14]; b[3]=a.f[15];
-			counter=pack(b);
-			counter++;
-			b=unpack(counter);
-			a.f[12]=b[0]; a.f[13]=b[1]; a.f[14]=b[2]; a.f[15]=b[3]; /* increment counter */
-			for (i=0;i<16;i++) B[i]=a.f[i];
-			a.ecb_encrypt(B);        /* encrypt it  */
-
-			for (i=0;i<16 && j<len;i++)
-			{
-				cipher[j]=(byte)(plain[j]^B[i]);
-				stateX[i]^=cipher[j++];
-				lenC[1]++; if (lenC[1]==0) lenC[0]++;
-			}
-			gf2mul();
-		}
-		if (len%16!=0) status=GCM_NOT_ACCEPTING_MORE;
-		return cipher;
-	}
-
-/* Add Ciphertext - decrypts to plaintext */
-	public byte[] add_cipher(byte[] cipher,int len)
-	{
-		int i,j=0;
-		int counter;
-		byte[] B=new byte[16];
-		byte[] b=new byte[4];
-		byte[] plain=new byte[len];
-
-		if (status==GCM_ACCEPTING_HEADER) status=GCM_ACCEPTING_CIPHER;
-		if (status!=GCM_ACCEPTING_CIPHER) return new byte[0];
-
-		while (j<len)
-		{
-
-			b[0]=a.f[12]; b[1]=a.f[13]; b[2]=a.f[14]; b[3]=a.f[15];
-			counter=pack(b);
-			counter++;
-			b=unpack(counter);
-			a.f[12]=b[0]; a.f[13]=b[1]; a.f[14]=b[2]; a.f[15]=b[3]; /* increment counter */
-			for (i=0;i<16;i++) B[i]=a.f[i];
-			a.ecb_encrypt(B);        /* encrypt it  */
-			for (i=0;i<16 && j<len;i++)
-			{
-				plain[j]=(byte)(cipher[j]^B[i]);
-				stateX[i]^=cipher[j++];
-				lenC[1]++; if (lenC[1]==0) lenC[0]++;
-			}
-			gf2mul();
-		}
-		if (len%16!=0) status=GCM_NOT_ACCEPTING_MORE;
-		return plain;
-	}
-
-/* Finish and extract Tag */
-	public byte[] finish(boolean extract)
-	{ /* Finish off GHASH and extract tag (MAC) */
-		int i;
-		byte[] tag=new byte[16];
-
-		wrap();
-/* extract tag */
-		if (extract)
-		{
-			a.ecb_encrypt(Y_0);        /* E(K,Y0) */
-			for (i=0;i<16;i++) Y_0[i]^=stateX[i];
-			for (i=0;i<16;i++) {tag[i]=Y_0[i];Y_0[i]=stateX[i]=0;}
-		}
-		status=GCM_FINISHED;
-		a.end();
-		return tag;
-	}
-
-	public static byte[] hex2bytes(String s) {
-		int len = s.length();
-		byte[] data = new byte[len / 2];
-		for (int i = 0; i < len; i += 2) {
-			data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
-                             + Character.digit(s.charAt(i+1), 16));
-		}
-		return data;
-	}
-
-/*
-	public static void main(String[] args) {
-		int i;
-
-		String KT="feffe9928665731c6d6a8f9467308308";
-		String MT="d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39";
-		String HT="feedfacedeadbeeffeedfacedeadbeefabaddad2";
-//	char* NT="cafebabefacedbaddecaf888";
-// Tag should be 5bc94fbc3221a5db94fae95ae7121a47
-		String NT="9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b";
-// Tag should be 619cc5aefffe0bfa462af43c1699d050
-
-
-		byte[] T=new byte[16];   // Tag
-		byte[] K=new byte[16];   // AES Key
-		byte[] H=new byte[64];   // Header - to be included in Authentication, but not encrypted
-		byte[] N=new byte[100];   // IV - Initialisation vector
-		byte[] M=new byte[100];  // Plaintext to be encrypted/authenticated
-		byte[] C=new byte[100];  // Ciphertext
-		byte[] P=new byte[100];  // Recovered Plaintext
-
-		GCM g=new GCM();
-
-		M=hex2bytes(MT);
-		H=hex2bytes(HT);
-		N=hex2bytes(NT);
-		K=hex2bytes(KT);
-
-		int len=M.length;
-		int lenH=H.length;
-		int lenK=K.length;
-		int lenIV=N.length;
-
- 		System.out.format("Plaintext=\n");
-		for (i=0;i<len;i++) System.out.format("%02x",M[i]);
-		System.out.format("\n");
-
-		g.init(K,lenIV,N);
-		g.add_header(H,lenH);
-		C=g.add_plain(M,len);
-		T=g.finish(true);
-
-		System.out.format("Ciphertext=\n");
-		for (i=0;i<len;i++) System.out.format("%02x",C[i]);
-		System.out.format("\n");
-
-		System.out.format("Tag=\n");
-		for (i=0;i<16;i++) System.out.format("%02x",T[i]);
-		System.out.format("\n");
-
-		g.init(K,lenIV,N);
-		g.add_header(H,lenH);
-		P=g.add_cipher(C,len);
-		T=g.finish(true);
-
- 		System.out.format("Plaintext=\n");
-		for (i=0;i<len;i++) System.out.format("%02x",P[i]);
-		System.out.format("\n");
-
-		System.out.format("Tag=\n");
-		for (i=0;i<16;i++) System.out.format("%02x",T[i]);
-		System.out.format("\n");
-	} */
-}
diff --git a/java64/HASH.java b/java64/HASH.java
deleted file mode 100755
index 8a484c1..0000000
--- a/java64/HASH.java
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
-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.
-*/
-
-/*
- * Implementation of the Secure Hashing Algorithm (SHA-256)
- *
- * Generates a 256 bit message digest. It should be impossible to come
- * come up with two messages that hash to the same value ("collision free").
- *
- * For use with byte-oriented messages only.
- */
-
-public class HASH {
-	private int[] length=new int[2];
-	private int[] h=new int[8];
-	private int[] w=new int[64];
-
-	public static final int H0=0x6A09E667;
-	public static final int H1=0xBB67AE85;
-	public static final int H2=0x3C6EF372;
-	public static final int H3=0xA54FF53A;
-	public static final int H4=0x510E527F;
-	public static final int H5=0x9B05688C;
-	public static final int H6=0x1F83D9AB;
-	public static final int H7=0x5BE0CD19;
-
-	public static final int len=32;
-
-	public static final int[] K={
-	0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,
-	0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,
-	0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,
-	0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,
-	0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
-	0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070,
-	0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,
-	0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2};
-
-
-/* functions */
-	private static int S(int n,int x)
-	{
-		return (((x)>>>n) | ((x)<<(32-n)));
-	}
-
-	private static int R(int n,int x)
-	{
-		return ((x)>>>n);
-	}
-
-	private static int Ch(int x,int y,int z)
-	{
-		return ((x&y)^(~(x)&z));
-	}
-
-	private static int Maj(int x,int y,int z)
-	{
-		return ((x&y)^(x&z)^(y&z));
-	}
-
-	private static int Sig0(int x)
-	{
-		return (S(2,x)^S(13,x)^S(22,x));
-	}
-
-	private static int Sig1(int x)
-	{
-		return (S(6,x)^S(11,x)^S(25,x));
-	}
-
-	private static int theta0(int x)
-	{
-		return (S(7,x)^S(18,x)^R(3,x));
-	}
-
-	private static int theta1(int x)
-	{
-		return (S(17,x)^S(19,x)^R(10,x));
-	}
-
-
-	private void transform()
-	{ /* basic transformation step */
-		int a,b,c,d,e,f,g,hh,t1,t2;
-		int j;
-		for (j=16;j<64;j++)
-			w[j]=theta1(w[j-2])+w[j-7]+theta0(w[j-15])+w[j-16];
-		a=h[0]; b=h[1]; c=h[2]; d=h[3];
-		e=h[4]; f=h[5]; g=h[6]; hh=h[7];
-
-		for (j=0;j<64;j++)
-		{ /* 64 times - mush it up */
-			t1=hh+Sig1(e)+Ch(e,f,g)+K[j]+w[j];
-			t2=Sig0(a)+Maj(a,b,c);
-			hh=g; g=f; f=e;
-			e=d+t1;
-			d=c;
-			c=b;
-			b=a;
-			a=t1+t2;
-
-		}
-		h[0]+=a; h[1]+=b; h[2]+=c; h[3]+=d;
-		h[4]+=e; h[5]+=f; h[6]+=g; h[7]+=hh;
-	}
-
-/* Initialise Hash function */
-	public void init()
-	{ /* initialise */
-		int i;
-		for (i=0;i<64;i++) w[i]=0;
-		length[0]=length[1]=0;
-		h[0]=H0;
-		h[1]=H1;
-		h[2]=H2;
-		h[3]=H3;
-		h[4]=H4;
-		h[5]=H5;
-		h[6]=H6;
-		h[7]=H7;
-	}
-
-/* Constructor */
-	public HASH()
-	{
-		init();
-	}
-
-/* process a single byte */
-	public void process(int byt)
-	{ /* process the next message byte */
-		int cnt;
-		cnt=(length[0]/32)%16;
-
-		w[cnt]<<=8;
-		w[cnt]|=(byt&0xFF);
-		length[0]+=8;
-		if (length[0]==0) { length[1]++; length[0]=0; }
-		if ((length[0]%512)==0) transform();
-	}
-
-/* process an array of bytes */
-	public void process_array(byte[] b)
-	{
-		for (int i=0;i<b.length;i++) process((int)b[i]);
-	}
-
-/* process a 32-bit integer */
-	public void process_num(int n)
-	{
-		process((n>>24)&0xff);
-		process((n>>16)&0xff);
-		process((n>>8)&0xff);
-		process(n&0xff);
-	}
-
-/* Generate 32-byte Hash */
-	public byte[] hash()
-	{ /* pad message and finish - supply digest */
-		int i;
-		byte[] digest=new byte[32];
-		int len0,len1;
-		len0=length[0];
-		len1=length[1];
-		process(0x80);
-		while ((length[0]%512)!=448) process(0);
-		w[14]=len1;
-		w[15]=len0;
-		transform();
-		for (i=0;i<len;i++)
-		{ /* convert to bytes */
-			digest[i]=(byte)((h[i/4]>>(8*(3-i%4))) & 0xff);
-		}
-		init();
-		return digest;
-	}
-
-/* test program: should produce digest */
-
-//248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1
-/*
-	public static void main(String[] args) {
-		byte[] test="abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq".getBytes();
-		byte[] digest;
-		int i;
-		HASH sh=new HASH();
-
-		for (i=0;i<test.length;i++)
-			sh.process(test[i]);
-
-		digest=sh.hash();
-		for (i=0;i<32;i++) System.out.format("%02x",digest[i]);
-
-	//	for (i=0;i<32;i++) System.out.format("%d ",digest[i]);
-
-		System.out.println("");
-	} */
-}
-
diff --git a/java64/MPIN.java b/java64/MPIN.java
deleted file mode 100755
index f8dfef0..0000000
--- a/java64/MPIN.java
+++ /dev/null
@@ -1,746 +0,0 @@
-/*
-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.
-*/
-
-/* MPIN API Functions */
-
-import java.util.Date;
-
-public class MPIN
-{
-	public static final int EFS=ROM.MODBYTES;
-	public static final int EGS=ROM.MODBYTES;
-	public static final int PAS=16;
-	public static final int BAD_PARAMS=-11;
-	public static final int INVALID_POINT=-14;
-	public static final int WRONG_ORDER=-18;
-	public static final int BAD_PIN=-19;
-
-/* Configure your PIN here */
-
-	public static final int MAXPIN=10000;  /* PIN less than this */
-	public static final int PBLEN=14;      /* Number of bits in PIN */
-	public static final int TS=10;         /* 10 for 4 digit PIN, 14 for 6-digit PIN - 2^TS/TS approx = sqrt(MAXPIN) */
-	public static final int TRAP=200;      /* 200 for 4 digit PIN, 2000 for 6-digit PIN  - approx 2*sqrt(MAXPIN) */
-
-/* Hash number (optional) and string to point on curve */
-
-	public static byte[] hashit(int n,byte[] ID)
-	{
-		HASH H=new HASH();
-		if (n!=0) H.process_num(n);
-		H.process_array(ID);
-		byte[] h=H.hash();
-		return h;
-	}
-
-	public static ECP mapit(byte[] h)
-	{
-		BIG q=new BIG(ROM.Modulus);
-		BIG x=BIG.fromBytes(h);
-		x.mod(q);
-		ECP P;
-		while (true)
-		{
-			P=new ECP(x,0);
-			if (!P.is_infinity()) break;
-			x.inc(1); x.norm();
-		}
-		return P;
-	}
-
-/* needed for SOK */
-	public static ECP2 mapit2(byte[] h)
-	{
-		BIG q=new BIG(ROM.Modulus);
-		BIG x=BIG.fromBytes(h);
-		BIG one=new BIG(1);
-		FP2 X;
-		ECP2 Q,T,K;
-		x.mod(q);
-		while (true)
-		{
-			X=new FP2(one,x);
-			Q=new ECP2(X);
-			if (!Q.is_infinity()) break;
-			x.inc(1); x.norm();
-		}
-/* Fast Hashing to G2 - Fuentes-Castaneda, Knapp and Rodriguez-Henriquez */
-		BIG Fra=new BIG(ROM.CURVE_Fra);
-		BIG Frb=new BIG(ROM.CURVE_Frb);
-		X=new FP2(Fra,Frb);
-		x=new BIG(ROM.CURVE_Bnx);
-
-		T=new ECP2(); T.copy(Q);
-		T.mul(x); T.neg();
-		K=new ECP2(); K.copy(T);
-		K.dbl(); K.add(T); K.affine();
-
-		K.frob(X);
-		Q.frob(X); Q.frob(X); Q.frob(X);
-		Q.add(T); Q.add(K);
-		T.frob(X); T.frob(X);
-		Q.add(T);
-		Q.affine();
-		return Q;
-	}
-
-/* return time in slots since epoch */
-	public static int today() {
-		Date date=new Date();
-		return (int) (date.getTime()/(1000*60*1440));
-	}
-
-/* these next two functions help to implement elligator squared - http://eprint.iacr.org/2014/043 */
-/* maps a random u to a point on the curve */
-	public static ECP map(BIG u,int cb)
-	{
-		ECP P;
-		BIG x=new BIG(u);
-		BIG p=new BIG(ROM.Modulus);
-		x.mod(p);
-		while (true)
-		{
-			P=new ECP(x,cb);
-			if (!P.is_infinity()) break;
-			x.inc(1);  x.norm();
-		}
-		return P;
-	}
-
-/* returns u derived from P. Random value in range 1 to return value should then be added to u */
-	public static int unmap(BIG u,ECP P)
-	{
-		int s=P.getS();
-		ECP R;
-		int r=0;
-		BIG x=P.getX();
-		u.copy(x);
-		while (true)
-		{
-			u.dec(1); u.norm();
-			r++;
-			R=new ECP(u,s);
-			if (!R.is_infinity()) break;
-		}
-		return r;
-	}
-
-	public static byte[] HASH_ID(byte[] ID)
-	{
-		return hashit(0,ID);
-	}
-
-
-/* these next two functions implement elligator squared - http://eprint.iacr.org/2014/043 */
-/* Elliptic curve point E in format (0x04,x,y} is converted to form {0x0-,u,v} */
-/* Note that u and v are indistinguisible from random strings */
-	public static int ENCODING(RAND rng,byte[] E)
-	{
-		int rn,m,su,sv;
-		byte[] T=new byte[EFS];
-
-		for (int i=0;i<EFS;i++) T[i]=E[i+1];
-		BIG u=BIG.fromBytes(T);
-		for (int i=0;i<EFS;i++) T[i]=E[i+EFS+1];
-		BIG v=BIG.fromBytes(T);
-
-		ECP P=new ECP(u,v);
-		if (P.is_infinity()) return INVALID_POINT;
-
-		BIG p=new BIG(ROM.Modulus);
-		u=BIG.randomnum(p,rng);
-
-		su=rng.getByte(); /*if (su<0) su=-su;*/ su%=2;
-
-		ECP W=map(u,su);
-		P.sub(W);
-		sv=P.getS();
-		rn=unmap(v,P);
-		m=rng.getByte(); /*if (m<0) m=-m;*/ m%=rn;
-		v.inc(m+1);
-		E[0]=(byte)(su+2*sv);
-		u.toBytes(T);
-		for (int i=0;i<EFS;i++) E[i+1]=T[i];
-		v.toBytes(T);
-		for (int i=0;i<EFS;i++) E[i+EFS+1]=T[i];
-
-		return 0;
-	}
-
-	public static int DECODING(byte[] D)
-	{
-		int su,sv;
-		byte[] T=new byte[EFS];
-
-		if ((D[0]&0x04)!=0) return INVALID_POINT;
-
-		for (int i=0;i<EFS;i++) T[i]=D[i+1];
-		BIG u=BIG.fromBytes(T);
-		for (int i=0;i<EFS;i++) T[i]=D[i+EFS+1];
-		BIG v=BIG.fromBytes(T);
-
-		su=D[0]&1;
-		sv=(D[0]>>1)&1;
-		ECP W=map(u,su);
-		ECP P=map(v,sv);
-		P.add(W);
-		u=P.getX();
-		v=P.getY();
-		D[0]=0x04;
-		u.toBytes(T);
-		for (int i=0;i<EFS;i++) D[i+1]=T[i];
-		v.toBytes(T);
-		for (int i=0;i<EFS;i++) D[i+EFS+1]=T[i];
-
-		return 0;
-	}
-
-/* R=R1+R2 in group G1 */
-	public static int RECOMBINE_G1(byte[] R1,byte[] R2,byte[] R)
-	{
-		ECP P=ECP.fromBytes(R1);
-		ECP Q=ECP.fromBytes(R2);
-
-		if (P.is_infinity() || Q.is_infinity()) return INVALID_POINT;
-
-		P.add(Q);
-
-		P.toBytes(R);
-		return 0;
-	}
-
-/* W=W1+W2 in group G2 */
-	public static int RECOMBINE_G2(byte[] W1,byte[] W2,byte[] W)
-	{
-		ECP2 P=ECP2.fromBytes(W1);
-		ECP2 Q=ECP2.fromBytes(W2);
-
-		if (P.is_infinity() || Q.is_infinity()) return INVALID_POINT;
-
-		P.add(Q);
-
-		P.toBytes(W);
-		return 0;
-	}
-
-/* create random secret S */
-	public static int RANDOM_GENERATE(RAND rng,byte[] S)
-	{
-		BIG s;
-		BIG r=new BIG(ROM.CURVE_Order);
-		s=BIG.randomnum(r,rng);
-
-		s.toBytes(S);
-		return 0;
-	}
-
-/* Extract PIN from TOKEN for identity CID */
-	public static int EXTRACT_PIN(byte[] CID,int pin,byte[] TOKEN)
-	{
-		ECP P=ECP.fromBytes(TOKEN);
-		if (P.is_infinity()) return INVALID_POINT;
-		byte[] h=hashit(0,CID);
-		ECP R=mapit(h);
-
-
-		pin%=MAXPIN;
-
-		R=R.pinmul(pin,PBLEN);
-		P.sub(R);
-
-		P.toBytes(TOKEN);
-
-		return 0;
-	}
-
-/* Implement step 2 on client side of MPin protocol */
-	public static int CLIENT_2(byte[] X,byte[] Y,byte[] SEC)
-	{
-		BIG r=new BIG(ROM.CURVE_Order);
-		ECP P=ECP.fromBytes(SEC);
-		if (P.is_infinity()) return INVALID_POINT;
-
-		BIG px=BIG.fromBytes(X);
-		BIG py=BIG.fromBytes(Y);
-		px.add(py);
-		px.mod(r);
-		px.rsub(r);
-
-		PAIR.G1mul(P,px).toBytes(SEC);
-		return 0;
-	}
-
-/* Implement step 1 on client side of MPin protocol */
-	public static int CLIENT_1(int date,byte[] CLIENT_ID,RAND rng,byte[] X,int pin,byte[] TOKEN,byte[] SEC,byte[] xID,byte[] xCID,byte[] PERMIT)
-	{
-		BIG r=new BIG(ROM.CURVE_Order);
-//		BIG q=new BIG(ROM.Modulus);
-		BIG x;
-//		BIG m=new BIG(0);
-		if (rng!=null)
-		{
-			x=BIG.randomnum(r,rng);
-			x.toBytes(X);
-		}
-		else
-		{
-			x=BIG.fromBytes(X);
-		}
-		ECP P,T,W;
-		BIG px;
-//		byte[] t=new byte[EFS];
-
-		byte[] h=hashit(0,CLIENT_ID);
-		P=mapit(h);
-
-		T=ECP.fromBytes(TOKEN);
-		if (T.is_infinity()) return INVALID_POINT;
-
-		pin%=MAXPIN;
-		W=P.pinmul(pin,PBLEN);
-		T.add(W);
-		if (date!=0)
-		{
-			W=ECP.fromBytes(PERMIT);
-			if (W.is_infinity()) return INVALID_POINT;
-			T.add(W);
-			h=hashit(date,h);
-			W=mapit(h);
-			if (xID!=null)
-			{
-				P=PAIR.G1mul(P,x);
-				P.toBytes(xID);
-				W=PAIR.G1mul(W,x);
-				P.add(W);
-			}
-			else
-			{
-				P.add(W);
-				P=PAIR.G1mul(P,x);
-			}
-			if (xCID!=null) P.toBytes(xCID);
-		}
-		else
-		{
-			if (xID!=null)
-			{
-				P=PAIR.G1mul(P,x);
-				P.toBytes(xID);
-			}
-		}
-
-
-		T.toBytes(SEC);
-		return 0;
-	}
-
-/* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */
-	public static int GET_SERVER_SECRET(byte[] S,byte[] SST)
-	{
-		ECP2 Q=new ECP2(new FP2(new BIG(ROM.CURVE_Pxa),new BIG(ROM.CURVE_Pxb)),new FP2(new BIG(ROM.CURVE_Pya),new BIG(ROM.CURVE_Pyb)));
-
-		BIG s=BIG.fromBytes(S);
-		Q=PAIR.G2mul(Q,s);
-		Q.toBytes(SST);
-		return 0;
-	}
-
-/*
- W=x*H(G);
- if RNG == NULL then X is passed in
- if RNG != NULL the X is passed out
- if type=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve
-*/
-	public static int GET_G1_MULTIPLE(RAND rng, int type,byte[] X,byte[] G,byte[] W)
-	{
-		BIG x;
-		BIG r=new BIG(ROM.CURVE_Order);
-		if (rng!=null)
-		{
-			x=BIG.randomnum(r,rng);
-			x.toBytes(X);
-		}
-		else
-		{
-			x=BIG.fromBytes(X);
-		}
-		ECP P;
-		if (type==0)
-		{
-			P=ECP.fromBytes(G);
-			if (P.is_infinity()) return INVALID_POINT;
-		}
-		else
-			P=mapit(G);
-
-		PAIR.G1mul(P,x).toBytes(W);
-		return 0;
-	}
-
-/* Client secret CST=S*H(CID) where CID is client ID and S is master secret */
-/* CID is hashed externally */
-	public static int GET_CLIENT_SECRET(byte[] S,byte[] CID,byte[] CST)
-	{
-		return GET_G1_MULTIPLE(null,1,S,CID,CST);
-	}
-
-/* Time Permit CTT=S*(date|H(CID)) where S is master secret */
-	public static int GET_CLIENT_PERMIT(int date,byte[] S,byte[] CID,byte[] CTT)
-	{
-		byte[] h=hashit(date,CID);
-		ECP P=mapit(h);
-
-		BIG s=BIG.fromBytes(S);
-		PAIR.G1mul(P,s).toBytes(CTT);
-		return 0;
-	}
-
-/* Outputs H(CID) and H(T|H(CID)) for time permits. If no time permits set HID=HTID */
-	public static void SERVER_1(int date,byte[] CID,byte[] HID,byte[] HTID)
-	{
-		byte[] h=hashit(0,CID);
-		ECP R,P=mapit(h);
-
-		if (date!=0)
-		{
-			if (HID!=null) P.toBytes(HID);
-			h=hashit(date,h);
-			R=mapit(h);
-			P.add(R);
-			P.toBytes(HTID);
-		}
-		else P.toBytes(HID);
-	}
-
-/* Implement step 2 of MPin protocol on server side */
-	public static int SERVER_2(int date,byte[] HID,byte[] HTID,byte[] Y,byte[] SST,byte[] xID,byte[] xCID,byte[] mSEC,byte[] E,byte[] F)
-	{
-		BIG q=new BIG(ROM.Modulus);
-		ECP2 Q=new ECP2(new FP2(new BIG(ROM.CURVE_Pxa),new BIG(ROM.CURVE_Pxb)),new FP2(new BIG(ROM.CURVE_Pya),new BIG(ROM.CURVE_Pyb)));
-		ECP2 sQ=ECP2.fromBytes(SST);
-		if (sQ.is_infinity()) return INVALID_POINT;
-
-		ECP R;
-		if (date!=0)
-			R=ECP.fromBytes(xCID);
-		else
-		{
-			if (xID==null) return BAD_PARAMS;
-			R=ECP.fromBytes(xID);
-		}
-		if (R.is_infinity()) return INVALID_POINT;
-
-		BIG y=BIG.fromBytes(Y);
-		ECP P;
-		if (date!=0) P=ECP.fromBytes(HTID);
-		else
-		{
-			if (HID==null) return BAD_PARAMS;
-			P=ECP.fromBytes(HID);
-		}
-
-		if (P.is_infinity()) return INVALID_POINT;
-
-		P=PAIR.G1mul(P,y);
-		P.add(R);
-		R=ECP.fromBytes(mSEC);
-		if (R.is_infinity()) return INVALID_POINT;
-
-		FP12 g;
-//		FP12 g1=new FP12(0);
-
-		g=PAIR.ate2(Q,R,sQ,P);
-		g=PAIR.fexp(g);
-
-		if (!g.isunity())
-		{
-			if (HID!=null && xID!=null && E!=null && F!=null)
-			{
-				g.toBytes(E);
-				if (date!=0)
-				{
-					P=ECP.fromBytes(HID);
-					if (P.is_infinity()) return INVALID_POINT;
-					R=ECP.fromBytes(xID);
-					if (R.is_infinity()) return INVALID_POINT;
-
-					P=PAIR.G1mul(P,y);
-					P.add(R);
-				}
-				g=PAIR.ate(Q,P);
-				g=PAIR.fexp(g);
-				g.toBytes(F);
-			}
-			return BAD_PIN;
-		}
-
-		return 0;
-	}
-
-/* Pollards kangaroos used to return PIN error */
-	public static int KANGAROO(byte[] E,byte[] F)
-	{
-		FP12 ge=FP12.fromBytes(E);
-		FP12 gf=FP12.fromBytes(F);
-		int[] distance = new int[TS];
-		FP12 t=new FP12(gf);
-		FP12[] table=new FP12[TS];
-		int i,j,m,s,dn,dm,res,steps;
-
-		s=1;
-		for (m=0;m<TS;m++)
-		{
-			distance[m]=s;
-			table[m]=new FP12(t);
-			s*=2;
-			t.usqr();
-		}
-		t.one();
-		dn=0;
-		for (j=0;j<TRAP;j++)
-		{
-			i=t.geta().geta().getA().lastbits(8)%TS;
-			t.mul(table[i]);
-			dn+=distance[i];
-		}
-		gf.copy(t); gf.conj();
-		steps=0; dm=0;
-		res=0;
-		while (dm-dn<MAXPIN)
-		{
-			steps++;
-			if (steps>4*TRAP) break;
-			i=ge.geta().geta().getA().lastbits(8)%TS;
-			ge.mul(table[i]);
-			dm+=distance[i];
-			if (ge.equals(t))
-			{
-				res=dm-dn;
-				break;
-			}
-			if (ge.equals(gf))
-			{
-				res=dn-dm;
-				break;
-			}
-
-		}
-		if (steps>4*TRAP || dm-dn>=MAXPIN) {res=0; }    // Trap Failed  - probable invalid token
-		return res;
-	}
-
-/* Functions to support M-Pin Full */
-
-	public static int PRECOMPUTE(byte[] TOKEN,byte[] CID,byte[] G1,byte[] G2)
-	{
-		ECP P,T;
-		FP12 g;
-
-		T=ECP.fromBytes(TOKEN);
-		if (T.is_infinity()) return INVALID_POINT;
-
-		P=mapit(CID);
-
-		ECP2 Q=new ECP2(new FP2(new BIG(ROM.CURVE_Pxa),new BIG(ROM.CURVE_Pxb)),new FP2(new BIG(ROM.CURVE_Pya),new BIG(ROM.CURVE_Pyb)));
-
-		g=PAIR.ate(Q,T);
-		g=PAIR.fexp(g);
-		g.toBytes(G1);
-
-		g=PAIR.ate(Q,P);
-		g=PAIR.fexp(g);
-		g.toBytes(G2);
-
-		return 0;
-	}
-
-/* calculate common key on client side */
-/* wCID = w.(A+AT) */
-	public static int CLIENT_KEY(byte[] G1,byte[] G2,int pin,byte[] R,byte[] X,byte[] wCID,byte[] CK)
-	{
-		HASH H=new HASH();
-		byte[] t=new byte[EFS];
-
-		FP12 g1=FP12.fromBytes(G1);
-		FP12 g2=FP12.fromBytes(G2);
-		BIG z=BIG.fromBytes(R);
-		BIG x=BIG.fromBytes(X);
-
-		ECP W=ECP.fromBytes(wCID);
-		if (W.is_infinity()) return INVALID_POINT;
-
-		W=PAIR.G1mul(W,x);
-
-		FP2 f=new FP2(new BIG(ROM.CURVE_Fra),new BIG(ROM.CURVE_Frb));
-		BIG r=new BIG(ROM.CURVE_Order);
-		BIG q=new BIG(ROM.Modulus);
-
-		BIG m=new BIG(q);
-		m.mod(r);
-
-		BIG a=new BIG(z);
-		a.mod(m);
-
-		BIG b=new BIG(z);
-		b.div(m);
-
-		g2.pinpow(pin,PBLEN);
-		g1.mul(g2);
-
-		FP4 c=g1.trace();
-		g2.copy(g1);
-		g2.frob(f);
-		FP4 cp=g2.trace();
-		g1.conj();
-		g2.mul(g1);
-		FP4 cpm1=g2.trace();
-		g2.mul(g1);
-		FP4 cpm2=g2.trace();
-
-		c=c.xtr_pow2(cp,cpm1,cpm2,a,b);
-
-		c.geta().getA().toBytes(t);
-		H.process_array(t);
-		c.geta().getB().toBytes(t);
-		H.process_array(t);
-		c.getb().getA().toBytes(t);
-		H.process_array(t);
-		c.getb().getB().toBytes(t);
-		H.process_array(t);
-
-		W.getX().toBytes(t);
-		H.process_array(t);
-		W.getY().toBytes(t);
-		H.process_array(t);
-
-		t=H.hash();
-		for (int i=0;i<PAS;i++) CK[i]=t[i];
-
-		return 0;
-	}
-
-/* calculate common key on server side */
-/* Z=r.A - no time permits involved */
-
-	public static int SERVER_KEY(byte[] Z,byte[] SST,byte[] W,byte[] xID,byte[] xCID,byte[] SK)
-	{
-		HASH H=new HASH();
-		byte[] t=new byte[EFS];
-
-		ECP2 sQ=ECP2.fromBytes(SST);
-		if (sQ.is_infinity()) return INVALID_POINT;
-		ECP R=ECP.fromBytes(Z);
-		if (R.is_infinity()) return INVALID_POINT;
-
-		ECP U;
-		if (xCID!=null)
-			U=ECP.fromBytes(xCID);
-		else
-			U=ECP.fromBytes(xID);
-		if (U.is_infinity()) return INVALID_POINT;
-
-		BIG w=BIG.fromBytes(W);
-		U=PAIR.G1mul(U,w);
-		FP12 g=PAIR.ate(sQ,R);
-		g=PAIR.fexp(g);
-
-		FP4 c=g.trace();
-		c.geta().getA().toBytes(t);
-		H.process_array(t);
-		c.geta().getB().toBytes(t);
-		H.process_array(t);
-		c.getb().getA().toBytes(t);
-		H.process_array(t);
-		c.getb().getB().toBytes(t);
-		H.process_array(t);
-
-		U.getX().toBytes(t);
-		H.process_array(t);
-		U.getY().toBytes(t);
-		H.process_array(t);
-
-		t=H.hash();
-		for (int i=0;i<PAS;i++) SK[i]=t[i];
-
-		return 0;
-	}
-
-/* return time since epoch */
-	public static int GET_TIME() {
-		Date date=new Date();
-		return (int) (date.getTime()/1000);
-	}
-
-/* Generate Y = H(epoch, xCID/xID) */
-        public static void GET_Y(int TimeValue,byte[] xCID,byte[] Y)
-        {
-          byte[] h = hashit(TimeValue,xCID);
-          BIG y = BIG.fromBytes(h);
-          BIG q=new BIG(ROM.CURVE_Order);
-          y.mod(q);
-          y.toBytes(Y);
-        }
-
-/* One pass MPIN Client */
-        public static int CLIENT(int date,byte[] CLIENT_ID,RAND RNG,byte[] X,int pin,byte[] TOKEN,byte[] SEC,byte[] xID,byte[] xCID,byte[] PERMIT, int TimeValue, byte[] Y)
-        {
-          int rtn=0;
-
-          byte[] pID;
-          if (date == 0)
-            pID = xID;
-          else
-            pID = xCID;
-
-          rtn = CLIENT_1(date,CLIENT_ID,RNG,X,pin,TOKEN,SEC,xID,xCID,PERMIT);
-          if (rtn != 0)
-            return rtn;
-
-          GET_Y(TimeValue,pID,Y);
-
-          rtn = CLIENT_2(X,Y,SEC);
-          if (rtn != 0)
-            return rtn;
-
-          return 0;
-        }
-
-/* One pass MPIN Server */
-        public static int SERVER(int date,byte[] HID,byte[] HTID,byte[] Y,byte[] SST,byte[] xID,byte[] xCID,byte[] SEC,byte[] E,byte[] F,byte[] CID, int TimeValue)
-        {
-          int rtn=0;
-
-          byte[] pID;
-          if (date == 0)
-            pID = xID;
-          else
-            pID = xCID;
-
-          SERVER_1(date,CID,HID,HTID);
-
-          GET_Y(TimeValue,pID,Y);
-
-          rtn = SERVER_2(date,HID,HTID,Y,SST,xID,xCID,SEC,E,F);
-          if (rtn != 0)
-            return rtn;
-
-          return 0;
-        }
-
-}
diff --git a/java64/PAIR.java b/java64/PAIR.java
deleted file mode 100755
index bc815a9..0000000
--- a/java64/PAIR.java
+++ /dev/null
@@ -1,537 +0,0 @@
-/*
-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.
-*/
-
-/* AMCL BN Curve Pairing functions */
-
-public final class PAIR {
-
-/* Line function */
-	public static FP12 line(ECP2 A,ECP2 B,FP Qx,FP Qy)
-	{
-		ECP2 P=new ECP2();
-
-		FP4 a,b,c;
-		P.copy(A);
-		FP2 ZZ=new FP2(P.getz());
-		ZZ.sqr();
-		int D;
-		if (A==B) D=A.dbl(); /* Check this return value in amcl_ec2.c */
-		else D=A.add(B);
-		if (D<0)
-			return new FP12(1);
-		FP2 Z3=new FP2(A.getz());
-		c=new FP4(0);
-		if (D==0)
-		{ /* Addition */
-			FP2 X=new FP2(B.getx());
-			FP2 Y=new FP2(B.gety());
-			FP2 T=new FP2(P.getz());
-			T.mul(Y);
-			ZZ.mul(T);
-
-			FP2 NY=new FP2(P.gety()); NY.neg();
-			ZZ.add(NY);
-			Z3.pmul(Qy);
-			T.mul(P.getx());
-			X.mul(NY);
-			T.add(X);
-			a=new FP4(Z3,T);
-			ZZ.neg();
-			ZZ.pmul(Qx);
-			b=new FP4(ZZ);
-		}
-		else
-		{ /* Doubling */
-			FP2 X=new FP2(P.getx());
-			FP2 Y=new FP2(P.gety());
-			FP2 T=new FP2(P.getx());
-			T.sqr();
-			T.imul(3);
-
-			Y.sqr();
-			Y.add(Y);
-			Z3.mul(ZZ);
-			Z3.pmul(Qy);
-
-			X.mul(T);
-			X.sub(Y);
-			a=new FP4(Z3,X);
-			T.neg();
-			ZZ.mul(T);
-			ZZ.pmul(Qx);
-			b=new FP4(ZZ);
-		}
-		return new FP12(a,b,c);
-	}
-
-/* Optimal R-ate pairing */
-	public static FP12 ate(ECP2 P,ECP Q)
-	{
-		FP2 f=new FP2(new BIG(ROM.CURVE_Fra),new BIG(ROM.CURVE_Frb));
-		BIG x=new BIG(ROM.CURVE_Bnx);
-		BIG n=new BIG(x);
-		ECP2 K=new ECP2();
-		FP12 lv;
-		n.pmul(6); n.dec(2); n.norm();
-		P.affine();
-		Q.affine();
-		FP Qx=new FP(Q.getx());
-		FP Qy=new FP(Q.gety());
-
-		ECP2 A=new ECP2();
-		FP12 r=new FP12(1);
-
-		A.copy(P);
-		int nb=n.nbits();
-
-		for (int i=nb-2;i>=1;i--)
-		{
-			lv=line(A,A,Qx,Qy);
-			r.smul(lv);
-
-			if (n.bit(i)==1)
-			{
-				lv=line(A,P,Qx,Qy);
-
-				r.smul(lv);
-			}
-			r.sqr();
-		}
-
-		lv=line(A,A,Qx,Qy);
-		r.smul(lv);
-
-/* R-ate fixup */
-
-		r.conj();
-
-		K.copy(P);
-		K.frob(f);
-		A.neg();
-		lv=line(A,K,Qx,Qy);
-		r.smul(lv);
-		K.frob(f);
-		K.neg();
-		lv=line(A,K,Qx,Qy);
-		r.smul(lv);
-
-		return r;
-	}
-
-/* Optimal R-ate double pairing e(P,Q).e(R,S) */
-	public static FP12 ate2(ECP2 P,ECP Q,ECP2 R,ECP S)
-	{
-		FP2 f=new FP2(new BIG(ROM.CURVE_Fra),new BIG(ROM.CURVE_Frb));
-		BIG x=new BIG(ROM.CURVE_Bnx);
-		BIG n=new BIG(x);
-		ECP2 K=new ECP2();
-		FP12 lv;
-		n.pmul(6); n.dec(2); n.norm();
-		P.affine();
-		Q.affine();
-		R.affine();
-		S.affine();
-
-		FP Qx=new FP(Q.getx());
-		FP Qy=new FP(Q.gety());
-		FP Sx=new FP(S.getx());
-		FP Sy=new FP(S.gety());
-
-		ECP2 A=new ECP2();
-		ECP2 B=new ECP2();
-		FP12 r=new FP12(1);
-
-		A.copy(P);
-		B.copy(R);
-		int nb=n.nbits();
-
-		for (int i=nb-2;i>=1;i--)
-		{
-			lv=line(A,A,Qx,Qy);
-			r.smul(lv);
-			lv=line(B,B,Sx,Sy);
-			r.smul(lv);
-
-			if (n.bit(i)==1)
-			{
-				lv=line(A,P,Qx,Qy);
-				r.smul(lv);
-				lv=line(B,R,Sx,Sy);
-				r.smul(lv);
-			}
-			r.sqr();
-		}
-
-		lv=line(A,A,Qx,Qy);
-		r.smul(lv);
-
-		lv=line(B,B,Sx,Sy);
-		r.smul(lv);
-
-/* R-ate fixup */
-		r.conj();
-
-		K.copy(P);
-		K.frob(f);
-		A.neg();
-		lv=line(A,K,Qx,Qy);
-		r.smul(lv);
-		K.frob(f);
-		K.neg();
-		lv=line(A,K,Qx,Qy);
-		r.smul(lv);
-
-		K.copy(R);
-		K.frob(f);
-		B.neg();
-		lv=line(B,K,Sx,Sy);
-		r.smul(lv);
-		K.frob(f);
-		K.neg();
-		lv=line(B,K,Sx,Sy);
-		r.smul(lv);
-
-		return r;
-	}
-
-/* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */
-	public static FP12 fexp(FP12 m)
-	{
-		FP2 f=new FP2(new BIG(ROM.CURVE_Fra),new BIG(ROM.CURVE_Frb));
-		BIG x=new BIG(ROM.CURVE_Bnx);
-		FP12 r=new FP12(m);
-		FP12 x0,x1,x2,x3,x4,x5;
-
-/* Easy part of final exp */
-		FP12 lv=new FP12(r);
-		lv.inverse();
-		r.conj();
-
-		r.mul(lv);
-		lv.copy(r);
-		r.frob(f);
-		r.frob(f);
-		r.mul(lv);
-/* Hard part of final exp */
-		lv.copy(r);
-		lv.frob(f);
-		x0=new FP12(lv);
-		x0.frob(f);
-		lv.mul(r);
-		x0.mul(lv);
-		x0.frob(f);
-		x1=new FP12(r);
-		x1.conj();
-		x4=r.pow(x);
-
-		x3=new FP12(x4);
-		x3.frob(f);
-
-		x2=x4.pow(x);
-
-		x5=new FP12(x2); x5.conj();
-		lv=x2.pow(x);
-
-		x2.frob(f);
-		r.copy(x2); r.conj();
-
-		x4.mul(r);
-		x2.frob(f);
-
-		r.copy(lv);
-		r.frob(f);
-		lv.mul(r);
-
-		lv.usqr();
-		lv.mul(x4);
-		lv.mul(x5);
-		r.copy(x3);
-		r.mul(x5);
-		r.mul(lv);
-		lv.mul(x2);
-		r.usqr();
-		r.mul(lv);
-		r.usqr();
-		lv.copy(r);
-		lv.mul(x1);
-		r.mul(x0);
-		lv.usqr();
-		r.mul(lv);
-		r.reduce();
-		return r;
-	}
-
-/* GLV method */
-	public static BIG[] glv(BIG e)
-	{
-		int i,j;
-		BIG t=new BIG(0);
-		BIG q=new BIG(ROM.CURVE_Order);
-		BIG[] u=new BIG[2];
-		BIG[] v=new BIG[2];
-		for (i=0;i<2;i++)
-		{
-			t.copy(new BIG(ROM.CURVE_W[i]));  // why not just t=new BIG(ROM.CURVE_W[i]);
-			DBIG d=BIG.mul(t,e);
-			v[i]=new BIG(d.div(q));
-			u[i]=new BIG(0);
-		}
-		u[0].copy(e);
-		for (i=0;i<2;i++)
-			for (j=0;j<2;j++)
-			{
-				t.copy(new BIG(ROM.CURVE_SB[j][i]));
-				t.copy(BIG.modmul(v[j],t,q));
-				u[i].add(q);
-				u[i].sub(t);
-				u[i].mod(q);
-			}
-		return u;
-	}
-
-/* Galbraith & Scott Method */
-	public static BIG[] gs(BIG e)
-	{
-		int i,j;
-		BIG t=new BIG(0);
-		BIG q=new BIG(ROM.CURVE_Order);
-		BIG[] u=new BIG[4];
-		BIG[] v=new BIG[4];
-		for (i=0;i<4;i++)
-		{
-			t.copy(new BIG(ROM.CURVE_WB[i]));
-			DBIG d=BIG.mul(t,e);
-			v[i]=new BIG(d.div(q));
-			u[i]=new BIG(0);
-		}
-		u[0].copy(e);
-		for (i=0;i<4;i++)
-			for (j=0;j<4;j++)
-			{
-				t.copy(new BIG(ROM.CURVE_BB[j][i]));
-				t.copy(BIG.modmul(v[j],t,q));
-				u[i].add(q);
-				u[i].sub(t);
-				u[i].mod(q);
-			}
-		return u;
-	}
-
-/* Multiply P by e in group G1 */
-	public static ECP G1mul(ECP P,BIG e)
-	{
-		ECP R;
-		if (ROM.USE_GLV)
-		{
-			P.affine();
-			R=new ECP();
-			R.copy(P);
-			int i,np,nn;
-			ECP Q=new ECP();
-			Q.copy(P);
-			BIG q=new BIG(ROM.CURVE_Order);
-			FP cru=new FP(new BIG(ROM.CURVE_Cru));
-			BIG t=new BIG(0);
-			BIG[] u=glv(e);
-			Q.getx().mul(cru);
-
-			np=u[0].nbits();
-			t.copy(BIG.modneg(u[0],q));
-			nn=t.nbits();
-			if (nn<np)
-			{
-				u[0].copy(t);
-				R.neg();
-			}
-
-			np=u[1].nbits();
-			t.copy(BIG.modneg(u[1],q));
-			nn=t.nbits();
-			if (nn<np)
-			{
-				u[1].copy(t);
-				Q.neg();
-			}
-
-			R=R.mul2(u[0],Q,u[1]);
-
-		}
-		else
-		{
-			R=P.mul(e);
-		}
-		return R;
-	}
-
-/* Multiply P by e in group G2 */
-	public static ECP2 G2mul(ECP2 P,BIG e)
-	{
-		ECP2 R;
-		if (ROM.USE_GS_G2)
-		{
-			ECP2[] Q=new ECP2[4];
-			FP2 f=new FP2(new BIG(ROM.CURVE_Fra),new BIG(ROM.CURVE_Frb));
-			BIG q=new BIG(ROM.CURVE_Order);
-			BIG[] u=gs(e);
-
-			BIG t=new BIG(0);
-			int i,np,nn;
-			P.affine();
-			Q[0]=new ECP2(); Q[0].copy(P);
-			for (i=1;i<4;i++)
-			{
-				Q[i]=new ECP2(); Q[i].copy(Q[i-1]);
-				Q[i].frob(f);
-			}
-			for (i=0;i<4;i++)
-			{
-				np=u[i].nbits();
-				t.copy(BIG.modneg(u[i],q));
-				nn=t.nbits();
-				if (nn<np)
-				{
-					u[i].copy(t);
-					Q[i].neg();
-				}
-			}
-			R=ECP2.mul4(Q,u);
-
-		}
-		else
-		{
-			R=P.mul(e);
-		}
-		return R;
-	}
-
-/* f=f^e */
-/* Note that this method requires a lot of RAM! Better to use compressed XTR method, see FP4.java */
-	public static FP12 GTpow(FP12 d,BIG e)
-	{
-		FP12 r;
-		if (ROM.USE_GS_GT)
-		{
-			FP12[] g=new FP12[4];
-			FP2 f=new FP2(new BIG(ROM.CURVE_Fra),new BIG(ROM.CURVE_Frb));
-			BIG q=new BIG(ROM.CURVE_Order);
-			BIG t=new BIG(0);
-			int i,np,nn;
-			BIG[] u=gs(e);
-
-			g[0]=new FP12(d);
-			for (i=1;i<4;i++)
-			{
-				g[i]=new FP12(0); g[i].copy(g[i-1]);
-				g[i].frob(f);
-			}
-			for (i=0;i<4;i++)
-			{
-				np=u[i].nbits();
-				t.copy(BIG.modneg(u[i],q));
-				nn=t.nbits();
-				if (nn<np)
-				{
-					u[i].copy(t);
-					g[i].conj();
-				}
-			}
-			r=FP12.pow4(g,u);
-		}
-		else
-		{
-			r=d.pow(e);
-		}
-		return r;
-	}
-
-/* test group membership */
-/* with GT-Strong curve, now only check that m!=1, conj(m)*m==1, and m.m^{p^4}=m^{p^2} */
-	public static boolean GTmember(FP12 m)
-	{
-		if (m.isunity()) return false;
-		FP12 r=new FP12(m);
-		r.conj();
-		r.mul(m);
-		if (!r.isunity()) return false;
-
-		FP2 f=new FP2(new BIG(ROM.CURVE_Fra),new BIG(ROM.CURVE_Frb));
-
-		r.copy(m); r.frob(f); r.frob(f);
-		FP12 w=new FP12(r); w.frob(f); w.frob(f);
-		w.mul(m);
-		if (!ROM.GT_STRONG)
-		{
-			if (!w.equals(r)) return false;
-			BIG x=new BIG(ROM.CURVE_Bnx);
-			r.copy(m); w=r.pow(x); w=w.pow(x);
-			r.copy(w); r.sqr(); r.mul(w); r.sqr();
-			w.copy(m); w.frob(f);
-		}
-		return w.equals(r);
-	}
-
-	public static void main(String[] args) {
-		ECP Q=new ECP(new BIG(ROM.CURVE_Gx),new BIG(ROM.CURVE_Gy));
-		ECP2 P=new ECP2(new FP2(new BIG(ROM.CURVE_Pxa),new BIG(ROM.CURVE_Pxb)),new FP2(new BIG(ROM.CURVE_Pya),new BIG(ROM.CURVE_Pyb)));
-
-		BIG r=new BIG(ROM.CURVE_Order);
-		BIG xa=new BIG(ROM.CURVE_Pxa);
-
-		System.out.println("P= "+P.toString());
-		System.out.println("Q= "+Q.toString());
-
-		BIG m=new BIG(17);
-
-		FP12 e=ate(P,Q);
-		System.out.println("\ne= "+e.toString());
-
-		e=fexp(e);
-	//	e=GTpow(e,m);
-
-		System.out.println("\ne= "+e.toString());
-
-		BIG [] GLV=glv(r);
-
-		System.out.println("GLV[0]= "+GLV[0].toString());
-		System.out.println("GLV[0]= "+GLV[1].toString());
-
-		ECP G=new ECP(); G.copy(Q);
-		ECP2 R=new ECP2(); R.copy(P);
-
-
-		e=ate(R,Q);
-		e=fexp(e);
-
-		e=GTpow(e,xa);
-		System.out.println("\ne= "+e.toString());
-
-
-		R=G2mul(R,xa);
-		e=ate(R,G);
-		e=fexp(e);
-
-		System.out.println("\ne= "+e.toString());
-
-		G=G1mul(G,xa);
-		e=ate(P,G);
-		e=fexp(e);
-		System.out.println("\ne= "+e.toString());
-	}
-}
-
diff --git a/java64/RAND.java b/java64/RAND.java
deleted file mode 100755
index 1bf6be2..0000000
--- a/java64/RAND.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
-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.
-*/
-
-/*
- *   Cryptographic strong random number generator
- *
- *   Unguessable seed -> SHA -> PRNG internal state -> SHA -> random numbers
- *   Slow - but secure
- *
- *   See ftp://ftp.rsasecurity.com/pub/pdfs/bull-1.pdf for a justification
- */
-
-/* Marsaglia & Zaman Random number generator constants */
-
-
-public class RAND {
-/* Cryptographically strong pseudo-random number generator */
-
-	private static final int NK=21;
-	private static final int NJ=6;
-	private static final int NV=8;
-	private int[] ira=new int[NK];  /* random number...   */
-	private int rndptr;   /* ...array & pointer */
-	private int borrow;
-	private int pool_ptr;
-	private byte[] pool=new byte[32];    /* random pool */
-
-	public RAND()
-	{
-		clean();
-	}
-
-	private int sbrand()
-	{ /* Marsaglia & Zaman random number generator */
-		int i,k;
-		long pdiff,t;
-
-		rndptr++;
-		if (rndptr<NK) return ira[rndptr];
-		rndptr=0;
-		for (i=0,k=NK-NJ;i<NK;i++,k++)
-		{ /* calculate next NK values */
-			if (k==NK) k=0;
-			t=((long)ira[k])&0xffffffffL;
-			pdiff=(t - (((long)ira[i])&0xffffffffL) - (long)borrow)&0xffffffffL;
-			if (pdiff<t) borrow=0;
-			if (pdiff>t) borrow=1;
-			ira[i]=(int)(pdiff&0xffffffffL);
-		}
-
-		return ira[0];
-	}
-
-	public void sirand(int seed)
-	{
-		int i,in;
-		int t,m=1;
-		borrow=0;
-		rndptr=0;
-		ira[0]^=seed;
-		for (i=1;i<NK;i++)
-		{ /* fill initialisation vector */
-			in=(NV*i)%NK;
-			ira[in]^=m;      /* note XOR */
-			t=m;
-			m=seed-m;
-			seed=t;
-		}
-		for (i=0;i<10000;i++) sbrand(); /* "warm-up" & stir the generator */
-	}
-
-	private void fill_pool()
-	{
-		HASH sh=new HASH();
-		for (int i=0;i<128;i++) sh.process(sbrand());
-		pool=sh.hash();
-		pool_ptr=0;
-	}
-
-	private static int pack(byte[] b)
-	{ /* pack 4 bytes into a 32-bit Word */
-		return ((((int)b[3])&0xff)<<24)|(((int)b[2]&0xff)<<16)|(((int)b[1]&0xff)<<8)|((int)b[0]&0xff);
-	}
-
-/* Initialize RNG with some real entropy from some external source */
-	public void seed(int rawlen,byte[] raw)
-	{ /* initialise from at least 128 byte string of raw random entropy */
-		int i;
-		byte [] digest;
-		byte [] b=new byte[4];
-		HASH sh=new HASH();
-		pool_ptr=0;
-		for (i=0;i<NK;i++) ira[i]=0;
-		if (rawlen>0)
-		{
-			for (i=0;i<rawlen;i++)
-				sh.process(raw[i]);
-			digest=sh.hash();
-
-/* initialise PRNG from distilled randomness */
-
-			for (i=0;i<8;i++)
-			{
-				b[0]=digest[4*i]; b[1]=digest[4*i+1]; b[2]=digest[4*i+2]; b[3]=digest[4*i+3];
-				sirand(pack(b));
-			}
-		}
-		fill_pool();
-	}
-
-/* Terminate and clean up */
-	public void clean()
-	{ /* kill internal state */
-		int i;
-		pool_ptr=rndptr=0;
-		for (i=0;i<32;i++) pool[i]=0;
-		for (i=0;i<NK;i++) ira[i]=0;
-		borrow=0;
-	}
-
-/* get random byte */
-	public int getByte()
-	{
-		int r;
-		r=pool[pool_ptr++];
-		if (pool_ptr>=32) fill_pool();
-		return (r&0xff);
-	}
-
-/* test main program */
-/*
-	public static void main(String[] args) {
-		int i;
-		byte[] raw=new byte[100];
-		RAND rng=new RAND();
-
-		rng.clean();
-		for (i=0;i<100;i++) raw[i]=(byte)i;
-
-		rng.seed(100,raw);
-
-		for (i=0;i<1000;i++)
-			System.out.format("%03d ",rng.getByte());
-	} */
-}
diff --git a/java64/ROM.java b/java64/ROM.java
deleted file mode 100755
index 4dc4bd4..0000000
--- a/java64/ROM.java
+++ /dev/null
@@ -1,381 +0,0 @@
-/*
-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.
-*/
-
-/* Fixed Data in ROM - Field and Curve parameters */
-
-public class ROM
-{
-/* Don't Modify from here... */
-	public static final int NOT_SPECIAL=0;
-	public static final int PSEUDO_MERSENNE=1;
-	public static final int MONTGOMERY_FRIENDLY=2;
-	public static final int WEIERSTRASS=0;
-	public static final int EDWARDS=1;
-	public static final int MONTGOMERY=2;
-/* ...to here */
-
-/*** Enter Some Field details here  ***/
-// BN Curve
-	public static final int MODBITS=254; /* Number of bits in Modulus */
-	public static final int MOD8=3;  /* Modulus mod 8 */
-// Curve 25519
-//	public static final int MODBITS=255;
-//	public static final int MOD8=5;
-// NIST256 or Brainpool
-//	public static final int MODBITS=256;
-//	public static final int MOD8=7;
-// MF254
-//	public static final int MODBITS=254;
-//	public static final int MOD8=7;
-// MS255
-//public static final int MODBITS= 255;
-//public static final int MOD8= 3;
-// MF256
-//	public static final int MODBITS=256;
-//	public static final int MOD8=7;
-// MS256
-//public static final int MODBITS= 256;
-//public static final int MOD8= 3;
-// ANSSI
-//  public static final int MODBITS= 256;
-//  public static final int MOD8= 3;
-
-/* Don't Modify from here... */
-	public static final int NLEN=5;
-	public static final int CHUNK=64;
-	public static final int DNLEN=2*NLEN;
-	public static final int BASEBITS=56;
-	public static final long MASK=(((long)1<<BASEBITS)-1);
-	public static final int HBITS=BASEBITS/2;
-	public static final long HMASK=(((long)1<<HBITS)-1);
-	public static final int MODBYTES=32;
-	public static final int NEXCESS =((int)1<<(CHUNK-BASEBITS-1));
-	public static final long FEXCESS =((long)1<<(BASEBITS*NLEN-MODBITS));
-	public static final long OMASK=(long)(-1)<<(MODBITS%BASEBITS);
-	public static final int TBITS=MODBITS%BASEBITS; // Number of active bits in top word
-	public static final long TMASK=((long)1<<TBITS)-1;
-/* ...to here */
-
-/* Finite field support - for RSA, DH etc. */
-	public static final int FF_BITS=2048; /* Finite Field Size in bits - must be 256.2^n */
-	public static final int FFLEN=(FF_BITS/256);
-	public static final int HFLEN=(FFLEN/2);  /* Useful for half-size RSA private key operations */
-
-
-// START SPECIFY FIELD DETAILS HERE
-//*********************************************************************************
-// Curve25519 Modulus
-//	public static final int MODTYPE=PSEUDO_MERSENNE;
-//	public static final long[] Modulus= {0xFFFFFFFFFFFFEDL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0x7FFFFFFFL};
-//	public static final long MConst=0x13L;
-
-
-// NIST-256 Curve
-//	public static final int MODTYPE=NOT_SPECIAL;
-//	public static final long[] Modulus= {0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFL,0x0L,0x1000000L,0xFFFFFFFFL};
-//	public static final long MConst=0x1L;
-
-// MF254 Modulus
-//	public static final int MODTYPE=MONTGOMERY_FRIENDLY;
-//	public static final long[] Modulus= {0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0x3F80FFFFL};
-//	public static final long MConst=0x3F810000L;
-
-// MS255 Modulus
-//public static final int MODTYPE= 1;
-//public static final long[] Modulus= {0xFFFFFFFFFFFD03L,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0x7FFFFFFFL};
-//public static final long MConst=0x2FDL;
-
-// MS256 Modulus
-//public static final int MODTYPE= 1;
-//public static final long[] Modulus= {0xFFFFFFFFFFFF43L,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFL};
-//public static final long MConst=0xBDL;
-
-// MF256 Modulus
-//public static final int MODTYPE= 2;
-//public static final long[] Modulus= {0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFA7FFFFL};
-//public static final long MConst=0xFFA80000L;
-
-// Brainpool
-//	public static final int MODTYPE= NOT_SPECIAL;
-//	public static final long[] Modulus= {0x13481D1F6E5377L,0xF623D526202820L,0x909D838D726E3BL,0xA1EEA9BC3E660AL,0xA9FB57DBL};
-//	public static final long MConst=0xA75590CEFD89B9L;
-
-// ANSSI
-//  public static final int MODTYPE= 0;
-//  public static final long[] Modulus= {0xFCF353D86E9C03L,0xADBCABC8CA6DE8L,0xE8CE42435B3961L,0xB3AD58F10126DL,0xF1FD178CL};
-//  public static final long MConst=0x97483A164E1155L;
-
-// BNCX Curve Modulus
-public static final int MODTYPE=NOT_SPECIAL;
-public static final long[] Modulus= {0x6623EF5C1B55B3L,0xD6EE18093EE1BEL,0x647A6366D3243FL,0x8702A0DB0BDDFL,0x24000000L};
-public static final long MConst=0x4E205BF9789E85L;
-
-// BN Curve
-//public static final int MODTYPE=NOT_SPECIAL;
-//public static final long[] Modulus= {0x13L,0x13A7L,0x80000000086121L,0x40000001BA344DL,0x25236482L};
-//public static final long MConst=0x435E50D79435E5L;
-
-// BNT Curve
-//public static final int MODTYPE=NOT_SPECIAL;
-//public static final long[] Modulus= {0x9DBBFEEEB4A713L,0x555614F464BABEL,0x3696F8D5F06E8AL,0x6517014EFA0BABL,0x240120DBL};
-//public static final long MConst=0xC5A872D914C4E5L;
-
-// BNT2 Curve
-//public static final int MODTYPE=NOT_SPECIAL;
-//public static final long[] Modulus= {0xB2DC2BB460A48BL,0x93E428F0D651E8L,0xF3B89D00081CFL,0x410F5AADB74E20L,0x24000482L};
-//public static final long MConst=0xFE6A47A6505CDDL;
-
-// START SPECIFY CURVE DETAILS HERE
-//*********************************************************************************
-
-// Ed25519 Curve
-//	public static final int CURVETYPE=EDWARDS;
-//	public static final int CURVE_A = -1;
-//	public static final long[] CURVE_B = {0xEB4DCA135978A3L,0xA4D4141D8AB75L,0x797779E8980070L,0x2B6FFE738CC740L,0x52036CEEL};
-//	public static final long[] CURVE_Order={0x12631A5CF5D3EDL,0xF9DEA2F79CD658L,0x14DEL,0x0L,0x10000000L};
-//	public static final long[] CURVE_Gx ={0x562D608F25D51AL,0xC7609525A7B2C9L,0x31FDD6DC5C692CL,0xCD6E53FEC0A4E2L,0x216936D3L};
-//	public static final long[] CURVE_Gy ={0x66666666666658L,0x66666666666666L,0x66666666666666L,0x66666666666666L,0x66666666L};
-
-// Original Curve25519
-//	public static final int CURVETYPE=MONTGOMERY;
-//	public static final int CURVE_A =486662;
-//	public static final long[] CURVE_B = {0x0L,0x0L,0x0L,0x0L,0x0L}; // not used
-//	public static final long[] CURVE_Order={0x12631A5CF5D3EDL,0xF9DEA2F79CD658L,0x14DEL,0x0L,0x10000000L};
-//	public static final long[] CURVE_Gx ={0x9L,0x0L,0x0L,0x0L,0x0L};
-//	public static final long[] CURVE_Gy ={0x0L,0x0L,0x0L,0x0L,0x0L}; // not used
-
-// NIST-256 Curve
-//	public static final int CURVETYPE=WEIERSTRASS;
-//	public static final int CURVE_A = -3;
-//	public static final long[] CURVE_B = {0xCE3C3E27D2604BL,0x6B0CC53B0F63BL,0x55769886BC651DL,0xAA3A93E7B3EBBDL,0x5AC635D8L};
-//	public static final long[] CURVE_Order={0xB9CAC2FC632551L,0xFAADA7179E84F3L,0xFFFFFFFFFFBCE6L,0xFFFFFFL,0xFFFFFFFFL};
-//	public static final long[] CURVE_Gx ={0xA13945D898C296L,0x7D812DEB33A0F4L,0xE563A440F27703L,0xE12C4247F8BCE6L,0x6B17D1F2L};
-//	public static final long[] CURVE_Gy ={0xB6406837BF51F5L,0x33576B315ECECBL,0x4A7C0F9E162BCEL,0xFE1A7F9B8EE7EBL,0x4FE342E2L};
-
-// MF254 Modulus, Weierstrass Curve w-254-mont
-//public static final int CURVETYPE= 0;
-//public static final int CURVE_A = -3;
-//public static final long[] CURVE_B = {0xFFFFFFFFFFD08DL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0x3F80FFFFL};
-//public static final long[] CURVE_Order={0xA419C4AF8DF83FL,0x8BEA0DA375C06FL,0xFFFFFFFFFFEB81L,0xFFFFFFFFFFFFFFL,0x3F80FFFFL};
-//public static final long[] CURVE_Gx ={0x2L,0x0L,0x0L,0x0L,0x0L};
-//public static final long[] CURVE_Gy ={0x65DF37F90D4EBCL,0x38E3F8511931ADL,0x75BD778AEBDFB7L,0x3B2E56014AE15AL,0x140E3FD3L};
-
-// MF254 Modulus, Edwards Curve ed-254-mont
-//public static final int CURVETYPE= 1;
-//public static final int CURVE_A = -1;
-//public static final long[] CURVE_B = {0x367BL,0x0L,0x0L,0x0L,0x0L};
-//public static final long[] CURVE_Order={0xF3D3FEC46E98C7L,0x306C8BD62FB0EAL,0xFFFFFFFFFFEB95L,0xFFFFFFFFFFFFFFL,0xFE03FFFL};
-//public static final long[] CURVE_Gx ={0x1L,0x0L,0x0L,0x0L,0x0L};
-//public static final long[] CURVE_Gy ={0x52D0FDAF2701E5L,0x9A840E3212187CL,0xD502363F4E3632L,0xD6A4C335951D00L,0x19F0E690L};
-
-// MF254 Modulus, Montgomery Curve
-//	public static final int CURVETYPE=MONTGOMERY;
-//	public static final int CURVE_A =-55790;
-//	public static final long[] CURVE_B = {0x0L,0x0L,0x0L,0x0L,0x0L}; // not used
-//	public static final long[] CURVE_Order={0xF3D3FEC46E98C7L,0x306C8BD62FB0EAL,0xFFFFFFFFFFEB95L,0xFFFFFFFFFFFFFFL,0xFE03FFFL};
-//	public static final long[] CURVE_Gx ={0x3L,0x0L,0x0L,0x0L,0x0L};
-//	public static final long[] CURVE_Gy ={0x0L,0x0L,0x0L,0x0L,0x0L}; // not used
-
-// MS255 Modulus, Weierstrass Curve
-//public static final int CURVETYPE= 0;
-//public static final int CURVE_A = -3;
-//public static final long[] CURVE_B = {0xFFFFFFFFFFAB46L,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0x7FFFFFFFL};
-//public static final long[] CURVE_Order={0x8FAC983C594AEBL,0x38283AD2B3DFABL,0xFFFFFFFFFF864AL,0xFFFFFFFFFFFFFFL,0x7FFFFFFFL};
-//public static final long[] CURVE_Gx ={0x1L,0x0L,0x0L,0x0L,0x0L};
-//public static final long[] CURVE_Gy ={0x33FF6769CB44BAL,0xC78CDDFDA60D17L,0xF9B2FF7D177DB6L,0xEDBA7833921EBFL,0x6F7A6AC0L};
-
-// MS255 Modulus, Edwards Curve
-//public static final int CURVETYPE= 1;
-//public static final int CURVE_A = -1;
-//public static final long[] CURVE_B = {0xEA97L,0x0L,0x0L,0x0L,0x0L};
-//public static final long[] CURVE_Order={0x49D1ED0436EB75L,0xA785EDA6832EACL,0xFFFFFFFFFFDCF1L,0xFFFFFFFFFFFFFFL,0x1FFFFFFFL};
-//public static final long[] CURVE_Gx ={0x4L,0x0L,0x0L,0x0L,0x0L};
-//public static final long[] CURVE_Gy ={0x2A255BD08736A0L,0x4B8AED445A45BAL,0xDD8E0C47E55291L,0x4A7BB545EC254CL,0x26CB7853L};
-
-// MS255 Modulus, Montgomery Curve
-//	public static final int CURVETYPE=MONTGOMERY;
-//	public static final int CURVE_A =-240222;
-//	public static final long[] CURVE_B = {0x0L,0x0L,0x0L,0x0L,0x0L}; // not used
-//	public static final long[] CURVE_Order={0x49D1ED0436EB75L,0xA785EDA6832EACL,0xFFFFFFFFFFDCF1L,0xFFFFFFFFFFFFFFL,0x1FFFFFFFL};
-//	public static final long[] CURVE_Gx ={0x4L,0x0L,0x0L,0x0L,0x0L};
-//	public static final long[] CURVE_Gy ={0x0L,0x0L,0x0L,0x0L,0x0L}; // not used
-
-// MS256, Weierstrass Curve
-//public static final int CURVETYPE= 0;
-//public static final int CURVE_A = -3;
-//public static final long[] CURVE_B = {0x25581L,0x0L,0x0L,0x0L,0x0L};
-//public static final long[] CURVE_Order={0xAB20294751A825L,0x8275EA265C6020L,0xFFFFFFFFFFE43CL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFL};
-//public static final long[] CURVE_Gx ={0x1L,0x0L,0x0L,0x0L,0x0L};
-//public static final long[] CURVE_Gy ={0xF46306C2B56C77L,0x2F9375894EC10BL,0x6CCEEEDD6BD02CL,0xC1E466D7FC82C9L,0x696F1853L};
-
-// MS256, Edwards Curve
-//public static final int CURVETYPE= 1;
-//public static final int CURVE_A = -1;
-//public static final long[] CURVE_B = {0x3BEEL,0x0L,0x0L,0x0L,0x0L};
-//public static final long[] CURVE_Order={0xB84E6F1122B4ADL,0xA55AD0A6BC64E5L,0xFFFFFFFFFFBE6AL,0xFFFFFFFFFFFFFFL,0x3FFFFFFFL};
-//public static final long[] CURVE_Gx ={0xDL,0x0L,0x0L,0x0L,0x0L};
-//public static final long[] CURVE_Gy ={0x7F6FB5331CADBAL,0x6D63824D303F70L,0xB39FA046BFBE2AL,0x2A1276DBA3D330L,0x7D0AB41EL};
-
-// MS256 Modulus, Montgomery Curve
-//	public static final int CURVETYPE=MONTGOMERY;
-//	public static final int CURVE_A =-61370;
-//	public static final long[] CURVE_B = {0x0L,0x0L,0x0L,0x0L,0x0L}; // not used
-//  public static final long[] CURVE_Order={0xB84E6F1122B4ADL,0xA55AD0A6BC64E5L,0xFFFFFFFFFFBE6AL,0xFFFFFFFFFFFFFFL,0x3FFFFFFFL};
-//	public static final long[] CURVE_Gx ={0xbL,0x0L,0x0L,0x0L,0x0L};
-//	public static final long[] CURVE_Gy ={0x0L,0x0L,0x0L,0x0L,0x0L}; // not used
-
-// MF256 Modulus, Weierstrass Curve
-//public static final int CURVETYPE= 0;
-//public static final int CURVE_A = -3;
-//public static final long[] CURVE_B = {0x14E6AL,0x0L,0x0L,0x0L,0x0L};
-//public static final long[] CURVE_Order={0x10C5E1A79857EBL,0x7513E6E5074B9DL,0xFFFFFFFFFFFC51L,0xFFFFFFFFFFFFFFL,0xFFA7FFFFL};
-//public static final long[] CURVE_Gx ={0x1L,0x0L,0x0L,0x0L,0x0L};
-//public static final long[] CURVE_Gy ={0x7954C2B724D2AL,0x47EB8D94DC6610L,0x26123DAE289569L,0xBE1808CE7BABBAL,0x20887C87L};
-
-// MF256, Edwards Curve
-//public static final int CURVETYPE= 1;
-//public static final int CURVE_A = -1;
-//public static final long[] CURVE_B = {0x350AL,0x0L,0x0L,0x0L,0x0L};
-//public static final long[] CURVE_Order={0xD92EDED8EC7BABL,0xBBAFB86733C966L,0xFFFFFFFFFFB154L,0xFFFFFFFFFFFFFFL,0x3FE9FFFFL};
-//public static final long[] CURVE_Gx ={0x1L,0x0L,0x0L,0x0L,0x0L};
-//public static final long[] CURVE_Gy ={0xEAA722F2F3C908L,0x5E648DFEA68D7DL,0xF3DB2C1AACA0C0L,0xF8CC4D5AEAEBEEL,0xDAD8D4F8L};
-
-// MF256 Modulus, Montgomery Curve
-//	public static final int CURVETYPE=MONTGOMERY;
-//	public static final int CURVE_A =-54314;
-//	public static final long[] CURVE_B = {0x0L,0x0L,0x0L,0x0L,0x0L}; // not used
-//  public static final long[] CURVE_Order={0xD92EDED8EC7BABL,0xBBAFB86733C966L,0xFFFFFFFFFFB154L,0xFFFFFFFFFFFFFFL,0x3FE9FFFFL};
-//	public static final long[] CURVE_Gx ={0x8L,0x0L,0x0L,0x0L,0x0L};
-//	public static final long[] CURVE_Gy ={0x0L,0x0L,0x0L,0x0L,0x0L}; // not used
-
-
-
-// Brainpool
-//	public static final int CURVETYPE= 0;
-//	public static final int CURVE_A = -3;
-//	public static final long[] CURVE_B = {0xE58101FEE92B04L,0xEBC4AF2F49256AL,0x733D0B76B7BF93L,0x30D84EA4FE66A7L,0x662C61C4L};
-//	public static final long[] CURVE_Order={0x1E0E82974856A7L,0x7AA3B561A6F790L,0x909D838D718C39L,0xA1EEA9BC3E660AL,0xA9FB57DBL};
-//	public static final long[] CURVE_Gx ={0xA191562E1305F4L,0x42C47AAFBC2B79L,0xB23A656149AFA1L,0xC1CFE7B7732213L,0xA3E8EB3CL};
-//	public static final long[] CURVE_Gy ={0xABE8F35B25C9BEL,0xB6DE39D027001DL,0xE14644417E69BCL,0x3439C56D7F7B22L,0x2D996C82L};
-
-// ANSSI
-//  public static final int CURVETYPE= 0;
-//  public static final int CURVE_A = -3;
-//  public static final long[] CURVE_B = {0x75ED967B7BB73FL,0xC9AE4B1A18030L,0x754A44C00FDFECL,0x5428A9300D4ABAL,0xEE353FCAL};
-//  public static final long[] CURVE_Order={0xFDD459C6D655E1L,0x67E140D2BF941FL,0xE8CE42435B53DCL,0xB3AD58F10126DL,0xF1FD178CL};
-//  public static final long[] CURVE_Gx ={0xC97A2DD98F5CFFL,0xD2DCAF98B70164L,0x4749D423958C27L,0x56C139EB31183DL,0xB6B3D4C3L};
-//  public static final long[] CURVE_Gy ={0x115A1554062CFBL,0xC307E8E4C9E183L,0xF0F3ECEF8C2701L,0xC8B204911F9271L,0x6142E0F7L};
-
-// BNCX Curve
-
-	public static final int CURVETYPE=WEIERSTRASS;
-	public static final int CURVE_A = 0;
-	public static final long[] CURVE_B = {0x2L,0x0L,0x0L,0x0L,0x0L};
-	public static final long[] CURVE_Order={0x11C0A636EB1F6DL,0xD6EE0CC906CEBEL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L};
-	public static final long[] CURVE_Bnx={0x3C012B1L,0x40L,0x0L,0x0L,0x0L};
-	public static final long[] CURVE_Cru={0xE0931794235C97L,0xDF6471EF875631L,0xCA83F1440BDL,0x480000L,0x0L};
-	public static final long[] CURVE_Fra={0xD9083355C80EA3L,0x7326F173F8215BL,0x8AACA718986867L,0xA63A0164AFE18BL,0x1359082FL};
-	public static final long[] CURVE_Frb={0x8D1BBC06534710L,0x63C7269546C062L,0xD9CDBC4E3ABBD8L,0x623628A900DC53L,0x10A6F7D0L};
-	public static final long[] CURVE_Pxa={0x851CEEE4D2EC74L,0x85BFA03E2726C0L,0xF5C34BBB907CL,0x7053B256358B25L,0x19682D2CL};
-	public static final long[] CURVE_Pxb={0xA58E8B2E29CFE1L,0x97B0C209C30F47L,0x37A8E99743F81BL,0x3E19F64AA011C9L,0x1466B9ECL};
-	public static final long[] CURVE_Pya={0xFBFCEBCF0BE09FL,0xB33D847EC1B30CL,0x157DAEE2096361L,0x72332B8DD81E22L,0xA79EDD9L};
-	public static final long[] CURVE_Pyb={0x904B228898EE9DL,0x4EA569D2EDEBEDL,0x512D8D3461C286L,0xECC4C09035C6E4L,0x6160C39L};
-	public static final long[] CURVE_Gx ={0x6623EF5C1B55B2L,0xD6EE18093EE1BEL,0x647A6366D3243FL,0x8702A0DB0BDDFL,0x24000000L};
-	public static final long[] CURVE_Gy ={0x1L,0x0L,0x0L,0x0L,0x0L};
-	public static final long[][] CURVE_W={{0x546349162FEB83L,0xB40381200L,0x6000L,0x0L,0x0L},{0x7802561L,0x80L,0x0L,0x0L,0x0L}};
-	public static final long[][][] CURVE_SB={{{0x5463491DB010E4L,0xB40381280L,0x6000L,0x0L,0x0L},{0x7802561L,0x80L,0x0L,0x0L,0x0L}},{{0x7802561L,0x80L,0x0L,0x0L,0x0L},{0xBD5D5D20BB33EAL,0xD6EE0188CEBCBDL,0x647A6366D2643FL,0x8702A0DB0BDDFL,0x24000000L}}};
-	public static final long[][] CURVE_WB={{0x1C2118567A84B0L,0x3C012B040L,0x2000L,0x0L,0x0L},{0xCDF995BE220475L,0x94EDA8CA7F9A36L,0x8702A0DC07EL,0x300000L,0x0L},{0x66FCCAE0F10B93L,0x4A76D4653FCD3BL,0x4381506E03FL,0x180000L,0x0L},{0x1C21185DFAAA11L,0x3C012B0C0L,0x2000L,0x0L,0x0L}};
-	public static final long[][][] CURVE_BB={{{0x11C0A6332B0CBDL,0xD6EE0CC906CE7EL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L},{0x11C0A6332B0CBCL,0xD6EE0CC906CE7EL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L},{0x11C0A6332B0CBCL,0xD6EE0CC906CE7EL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L},{0x7802562L,0x80L,0x0L,0x0L,0x0L}},{{0x7802561L,0x80L,0x0L,0x0L,0x0L},{0x11C0A6332B0CBCL,0xD6EE0CC906CE7EL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L},{0x11C0A6332B0CBDL,0xD6EE0CC906CE7EL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L},{0x11C0A6332B0CBCL,0xD6EE0CC906CE7EL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L}},{{0x7802562L,0x80L,0x0L,0x0L,0x0L},{0x7802561L,0x80L,0x0L,0x0L,0x0L},{0x7802561L,0x80L,0x0L,0x0L,0x0L},{0x7802561L,0x80L,0x0L,0x0L,0x0L}},{{0x3C012B2L,0x40L,0x0L,0x0L,0x0L},{0xF004AC2L,0x100L,0x0L,0x0L,0x0L},{0x11C0A62F6AFA0AL,0xD6EE0CC906CE3EL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L},{0x3C012B2L,0x40L,0x0L,0x0L,0x0L}}};
-
-	public static final boolean USE_GLV =true;
-	public static final boolean USE_GS_G2 =true;
-	public static final boolean USE_GS_GT =true;
-	public static final boolean GT_STRONG=true;
-
-// BNT Curve
-/*
-public static final int CURVETYPE=WEIERSTRASS;
-public static final int CURVE_A = 0;
-public static final long[] CURVE_B = {0x2L,0x0L,0x0L,0x0L,0x0L};
-public static final long[] CURVE_Order={0x75777E8D30210DL,0xD43492B2CB363AL,0x3696F8D5F00E88L,0x6517014EFA0BABL,0x240120DBL};
-public static final long[] CURVE_Bnx={0x806000004081L,0x40L,0x0L,0x0L,0x0L};
-public static final long[] CURVE_Cru={0xEB53D5AB4FCD87L,0x82A5F2BAB11FADL,0x47651504C9764CL,0x4801B1L,0x0L};
-public static final long[] CURVE_Fra={0xF5D14EADC80022L,0x4904D6FACCE359L,0xF190A13211BE6CL,0xC9BBC4394F6509L,0x1328A292L};
-public static final long[] CURVE_Frb={0xA7EAB040ECA6F1L,0xC513DF997D764L,0x450657A3DEB01EL,0x9B5B3D15AAA6A1L,0x10D87E48L};
-public static final long[] CURVE_Pxa={0x8987E2288E65BBL,0xAD1CAA6313BEL,0x325041548B7CCCL,0x4C1339EBCC055L,0x14483FCDL};
-public static final long[] CURVE_Pxb={0x67888808DBE2C0L,0x7FE1F81E34853AL,0xA631A51B57B95L,0x384EC302DA3FC5L,0x87F46B3L};
-public static final long[] CURVE_Pya={0x202C47E020CA1DL,0xB4167E8399F36CL,0xC6E5439F72C94CL,0x102B0BD74A2C69L,0x14E8C29CL};
-public static final long[] CURVE_Pyb={0xD8437C716628F2L,0x27E167BCB7DC6BL,0xA82C7572681D0AL,0x62454BD1EDEC18L,0x17AFE2A4L};
-public static final long[] CURVE_Gx ={0x9DBBFEEEB4A712L,0x555614F464BABEL,0x3696F8D5F06E8AL,0x6517014EFA0BABL,0x240120DBL};
-public static final long[] CURVE_Gy ={0x1L,0x0L,0x0L,0x0L,0x0L};
-public static final long[][] CURVE_W={{0x26430061838403L,0x81218241998384L,0x6001L,0x0L,0x0L},{0x100C000008101L,0x80L,0x0L,0x0L,0x0L}};
-public static final long[][][] CURVE_SB={{{0x2743C061840504L,0x81218241998404L,0x6001L,0x0L,0x0L},{0x100C000008101L,0x80L,0x0L,0x0L,0x0L}},{{0x100C000008101L,0x80L,0x0L,0x0L,0x0L},{0x4F347E2BAC9D0AL,0x5313107131B2B6L,0x3696F8D5EFAE87L,0x6517014EFA0BABL,0x240120DBL}}};
-public static final long[][] CURVE_WB={{0x6140602080C080L,0x806080C08880C1L,0x2000L,0x0L,0x0L},{0xB53904088C4A85L,0xAD2FA352DC6C36L,0xDA436358868EDEL,0x300120L,0x0L},{0x5ADCB204464583L,0x5697D1A96E363BL,0x6D21B1AC43476FL,0x180090L,0x0L},{0x62412020814181L,0x806080C0888141L,0x2000L,0x0L,0x0L}};
-public static final long[][][] CURVE_BB={{{0x74F71E8D2FE08DL,0xD43492B2CB35FAL,0x3696F8D5F00E88L,0x6517014EFA0BABL,0x240120DBL},{0x74F71E8D2FE08CL,0xD43492B2CB35FAL,0x3696F8D5F00E88L,0x6517014EFA0BABL,0x240120DBL},{0x74F71E8D2FE08CL,0xD43492B2CB35FAL,0x3696F8D5F00E88L,0x6517014EFA0BABL,0x240120DBL},{0x100C000008102L,0x80L,0x0L,0x0L,0x0L}},{{0x100C000008101L,0x80L,0x0L,0x0L,0x0L},{0x74F71E8D2FE08CL,0xD43492B2CB35FAL,0x3696F8D5F00E88L,0x6517014EFA0BABL,0x240120DBL},{0x74F71E8D2FE08DL,0xD43492B2CB35FAL,0x3696F8D5F00E88L,0x6517014EFA0BABL,0x240120DBL},{0x74F71E8D2FE08CL,0xD43492B2CB35FAL,0x3696F8D5F00E88L,0x6517014EFA0BABL,0x240120DBL}},{{0x100C000008102L,0x80L,0x0L,0x0L,0x0L},{0x100C000008101L,0x80L,0x0L,0x0L,0x0L},{0x100C000008101L,0x80L,0x0L,0x0L,0x0L},{0x100C000008101L,0x80L,0x0L,0x0L,0x0L}},{{0x806000004082L,0x40L,0x0L,0x0L,0x0L},{0x2018000010202L,0x100L,0x0L,0x0L,0x0L},{0x7476BE8D2FA00AL,0xD43492B2CB35BAL,0x3696F8D5F00E88L,0x6517014EFA0BABL,0x240120DBL},{0x806000004082L,0x40L,0x0L,0x0L,0x0L}}};
-
-*/
-
-// BNT2 Curve
-/*
-	public static final int CURVETYPE=WEIERSTRASS;
-	public static final int CURVE_A = 0;
-	public static final long[] CURVE_B = {0x2L,0x0L,0x0L,0x0L,0x0L};
-	public static final long[] CURVE_Order={0xFB71A511AA2BF5L,0x8DE127B73833D7L,0xF3B89D00021CFL,0x410F5AADB74E20L,0x24000482L};
-	public static final long[] CURVE_Bnx={0x20100608205L,0x40L,0x0L,0x0L,0x0L};
-	public static final long[] CURVE_Cru={0x5027444866BD33L,0x5B773016470EFBL,0xC3617BECF23675L,0x480006L,0x0L};
-	public static final long[] CURVE_Fra={0xB268C973AEF062L,0xC69B33C3BCE492L,0xF67FA37F195BBCL,0x29E8CAB6BD0A41L,0x124E0B8DL};
-	public static final long[] CURVE_Frb={0x736240B1B429L,0xCD48F52D196D56L,0x18BBE650E72612L,0x17268FF6FA43DEL,0x11B1F8F5L};
-	public static final long[] CURVE_Pxa={0xCC92399F40A3C8L,0xCDA4E96611784AL,0x7B056961706B35L,0x9693C6318279D7L,0x16FC17CFL};
-	public static final long[] CURVE_Pxb={0x557A8AD8549540L,0x6F7BE6F6510610L,0x565907A95D17DBL,0xBD5975909C8188L,0x1EB5B500L};
-	public static final long[] CURVE_Pya={0x7BECC514220513L,0x4A78860E737B14L,0x51B83935F12684L,0x761422AA9D4DFAL,0x1E8EE498L};
-	public static final long[] CURVE_Pyb={0xB9328F577CE78EL,0xB746E26FA5781FL,0xA93DBC1FB8E27EL,0xBAE33BDBA29D76L,0x23CEF4CDL};
-	public static final long[] CURVE_Gx ={0xB2DC2BB460A48AL,0x93E428F0D651E8L,0xF3B89D00081CFL,0x410F5AADB74E20L,0x24000482L};
-	public static final long[] CURVE_Gy ={0x1L,0x0L,0x0L,0x0L,0x0L};
-	public static final long[][] CURVE_W={{0xB76282A1347083L,0x60301399E1D10L,0x6000L,0x0L,0x0L},{0x40200C10409L,0x80L,0x0L,0x0L,0x0L}};
-	public static final long[][][] CURVE_SB={{{0xB76684A1F5748CL,0x60301399E1D90L,0x6000L,0x0L,0x0L},{0x40200C10409L,0x80L,0x0L,0x0L,0x0L}},{{0x40200C10409L,0x80L,0x0L,0x0L,0x0L},{0x440F227075BB72L,0x87DE267D9A16C7L,0xF3B89CFFFC1CFL,0x410F5AADB74E20L,0x24000482L}}};
-	public static final long[][] CURVE_WB={{0x9272D48A70A224L,0x20100688A0945L,0x2000L,0x0L,0x0L},{0x5A572CF030EF19L,0x9651763543721DL,0x8240FD48A1B9A3L,0x300004L,0x0L},{0xAD2C96F848B88FL,0xCB28BB1AA1B92EL,0x41207EA450DCD1L,0x180002L,0x0L},{0x9276D68B31A62DL,0x20100688A09C5L,0x2000L,0x0L,0x0L}};
-	public static final long[][][] CURVE_BB={{{0xFB6FA41149A9F1L,0x8DE127B7383397L,0xF3B89D00021CFL,0x410F5AADB74E20L,0x24000482L},{0xFB6FA41149A9F0L,0x8DE127B7383397L,0xF3B89D00021CFL,0x410F5AADB74E20L,0x24000482L},{0xFB6FA41149A9F0L,0x8DE127B7383397L,0xF3B89D00021CFL,0x410F5AADB74E20L,0x24000482L},{0x40200C1040AL,0x80L,0x0L,0x0L,0x0L}},{{0x40200C10409L,0x80L,0x0L,0x0L,0x0L},{0xFB6FA41149A9F0L,0x8DE127B7383397L,0xF3B89D00021CFL,0x410F5AADB74E20L,0x24000482L},{0xFB6FA41149A9F1L,0x8DE127B7383397L,0xF3B89D00021CFL,0x410F5AADB74E20L,0x24000482L},{0xFB6FA41149A9F0L,0x8DE127B7383397L,0xF3B89D00021CFL,0x410F5AADB74E20L,0x24000482L}},{{0x40200C1040AL,0x80L,0x0L,0x0L,0x0L},{0x40200C10409L,0x80L,0x0L,0x0L,0x0L},{0x40200C10409L,0x80L,0x0L,0x0L,0x0L},{0x40200C10409L,0x80L,0x0L,0x0L,0x0L}},{{0x20100608206L,0x40L,0x0L,0x0L,0x0L},{0x80401820812L,0x100L,0x0L,0x0L,0x0L},{0xFB6DA310E927EAL,0x8DE127B7383357L,0xF3B89D00021CFL,0x410F5AADB74E20L,0x24000482L},{0x20100608206L,0x40L,0x0L,0x0L,0x0L}}};
-*/
-
-// BN Curve
-/*
-public static final int CURVETYPE=WEIERSTRASS;
-public static final int CURVE_A = 0;
-public static final long[] CURVE_B = {0x2L,0x0L,0x0L,0x0L,0x0L};
-public static final long[] CURVE_Order={0xDL,0x800000000010A1L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L};
-public static final long[] CURVE_Bnx={0x80000000000001L,0x40L,0x0L,0x0L,0x0L};
-public static final long[] CURVE_Cru={0x80000000000007L,0x6CDL,0x40000000024909L,0x49B362L,0x0L};
-public static final long[] CURVE_Fra={0x7DE6C06F2A6DE9L,0x74924D3F77C2E1L,0x50A846953F8509L,0x212E7C8CB6499BL,0x1B377619L};
-public static final long[] CURVE_Frb={0x82193F90D5922AL,0x8B6DB2C08850C5L,0x2F57B96AC8DC17L,0x1ED1837503EAB2L,0x9EBEE69L};
-public static final long[] CURVE_Pxa={0xAB2C7935FD0CB4L,0xE319E4FCC57C2BL,0x24F6DF763B05A5L,0xF55EA7EA335FB7L,0x95B04D4L};
-public static final long[] CURVE_Pxb={0xA07D0790962455L,0x86BE3D27AA5E38L,0x89E05747F39D6DL,0xC08347B49D42BFL,0x5D4D8A7L};
-public static final long[] CURVE_Pya={0xADCE687A08A46CL,0x2B30E98A4191F9L,0x4C3784B1F16908L,0x25E5313FA16D1CL,0xABF2ABFL};
-public static final long[] CURVE_Pyb={0xDF88D405F306ECL,0x82076ADD13A0E6L,0x1E47819D6A5C04L,0xE679DABDB38627L,0x18769A87L};
-public static final long[] CURVE_Gx ={0x12L,0x13A7L,0x80000000086121L,0x40000001BA344DL,0x25236482L};
-public static final long[] CURVE_Gy ={0x1L,0x0L,0x0L,0x0L,0x0L};
-public static final long[][] CURVE_W={{0x3L,0x80000000000204L,0x6181L,0x0L,0x0L},{0x1L,0x81L,0x0L,0x0L,0x0L}};
-public static final long[][][] CURVE_SB={{{0x4L,0x80000000000285L,0x6181L,0x0L,0x0L},{0x1L,0x81L,0x0L,0x0L,0x0L}},{{0x1L,0x81L,0x0L,0x0L,0x0L},{0xAL,0xE9DL,0x80000000079E1EL,0x40000001BA344DL,0x25236482L}}};
-public static final long[][] CURVE_WB={{0x80000000000000L,0x80000000000040L,0x2080L,0x0L,0x0L},{0x80000000000005L,0x54AL,0x8000000001C707L,0x312241L,0x0L},{0x80000000000003L,0x800000000002C5L,0xC000000000E383L,0x189120L,0x0L},{0x80000000000001L,0x800000000000C1L,0x2080L,0x0L,0x0L}};
-public static final long[][][] CURVE_BB={{{0x8000000000000DL,0x80000000001060L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L},{0x8000000000000CL,0x80000000001060L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L},{0x8000000000000CL,0x80000000001060L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L},{0x2L,0x81L,0x0L,0x0L,0x0L}},{{0x1L,0x81L,0x0L,0x0L,0x0L},{0x8000000000000CL,0x80000000001060L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L},{0x8000000000000DL,0x80000000001060L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L},{0x8000000000000CL,0x80000000001060L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L}},{{0x2L,0x81L,0x0L,0x0L,0x0L},{0x1L,0x81L,0x0L,0x0L,0x0L},{0x1L,0x81L,0x0L,0x0L,0x0L},{0x1L,0x81L,0x0L,0x0L,0x0L}},{{0x80000000000002L,0x40L,0x0L,0x0L,0x0L},{0x2L,0x102L,0x0L,0x0L,0x0L},{0xAL,0x80000000001020L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L},{0x80000000000002L,0x40L,0x0L,0x0L,0x0L}}};
-
-*/
-
-//	public static boolean debug=false;
-
-}
diff --git a/java64/RSA.java b/java64/RSA.java
deleted file mode 100755
index 4ce597c..0000000
--- a/java64/RSA.java
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
-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.
-*/
-
-/* RSA API high-level functions  */
-
-final class rsa_private_key
-{
-    public FF p,q,dp,dq,c;
-
-	public rsa_private_key(int n)
-	{
-		p=new FF(n);
-		q=new FF(n);
-		dp=new FF(n);
-		dq=new FF(n);
-		c=new FF(n);
-	}
-}
-
-final class rsa_public_key
-{
-    public int e;
-    public FF n;
-
-	public rsa_public_key(int m)
-	{
-		e=0;
-		n=new FF(m);
-	}
-}
-
-public final class RSA {
-
-	public static final int RFS=ROM.MODBYTES*ROM.FFLEN;
-
-/* generate an RSA key pair */
-
-	public static void KEY_PAIR(RAND rng,int e,rsa_private_key PRIV,rsa_public_key PUB)
-	{ /* IEEE1363 A16.11/A16.12 more or less */
-		int n=PUB.n.getlen()/2;
-		FF t = new FF(n);
-		FF p1=new FF(n);
-		FF q1=new FF(n);
-
-		for (;;)
-		{
-
-			PRIV.p.random(rng);
-			while (PRIV.p.lastbits(2)!=3) PRIV.p.inc(1);
-			while (!FF.prime(PRIV.p,rng))
-				PRIV.p.inc(4);
-
-			p1.copy(PRIV.p);
-			p1.dec(1);
-
-			if (p1.cfactor(e)) continue;
-			break;
-		}
-
-		for (;;)
-		{
-			PRIV.q.random(rng);
-			while (PRIV.q.lastbits(2)!=3) PRIV.q.inc(1);
-			while (!FF.prime(PRIV.q,rng))
-				PRIV.q.inc(4);
-
-			q1.copy(PRIV.q);
-			q1.dec(1);
-
-			if (q1.cfactor(e)) continue;
-
-			break;
-		}
-
-		PUB.n=FF.mul(PRIV.p,PRIV.q);
-		PUB.e=e;
-
-		t.copy(p1);
-		t.shr();
-		PRIV.dp.set(e);
-		PRIV.dp.invmodp(t);
-		if (PRIV.dp.parity()==0) PRIV.dp.add(t);
-		PRIV.dp.norm();
-
-		t.copy(q1);
-		t.shr();
-		PRIV.dq.set(e);
-		PRIV.dq.invmodp(t);
-		if (PRIV.dq.parity()==0) PRIV.dq.add(t);
-		PRIV.dq.norm();
-
-		PRIV.c.copy(PRIV.p);
-		PRIV.c.invmodp(PRIV.q);
-
-		return;
-	}
-
-/* Mask Generation Function */
-
-	public static void MGF1(byte[] Z,int olen,byte[] K)
-	{
-		HASH H=new HASH();
-		int hlen=HASH.len;
-		byte[] B=new byte[hlen];
-
-		int counter,cthreshold,k=0;
-		for (int i=0;i<K.length;i++) K[i]=0;
-
-		cthreshold=olen/hlen; if (olen%hlen!=0) cthreshold++;
-		for (counter=0;counter<cthreshold;counter++)
-		{
-			H.process_array(Z); H.process_num(counter);
-			B=H.hash();
-
-			if (k+hlen>olen) for (int i=0;i<olen%hlen;i++) K[k++]=B[i];
-			else for (int i=0;i<hlen;i++) K[k++]=B[i];
-		}
-	}
-
-	public static void printBinary(byte[] array)
-	{
-		int i;
-		for (i=0;i<array.length;i++)
-		{
-			System.out.printf("%02x", array[i]);
-		}
-		System.out.println();
-	}
-
-	/* OAEP Message Encoding for Encryption */
-	public static byte[] OAEP_ENCODE(byte[] m,RAND rng,byte[] p)
-	{
-		int i,slen,olen=RFS-1;
-		int mlen=m.length;
-		int hlen,seedlen;
-		byte[] f=new byte[RFS];
-
-		HASH H=new HASH();
-		hlen=HASH.len;
-		byte[] SEED=new byte[hlen];
-		seedlen=hlen;
-		if (mlen>olen-hlen-seedlen-1) return new byte[0];
-
-		byte[] DBMASK=new byte[olen-seedlen];
-
-		if (p!=null) H.process_array(p);
-		byte[] h=H.hash();
-		for (i=0;i<hlen;i++) f[i]=h[i];
-
-		slen=olen-mlen-hlen-seedlen-1;
-
-		for (i=0;i<slen;i++) f[hlen+i]=0;
-		f[hlen+slen]=1;
-		for (i=0;i<mlen;i++) f[hlen+slen+1+i]=m[i];
-
-		for (i=0;i<seedlen;i++) SEED[i]=(byte)rng.getByte();
-		MGF1(SEED,olen-seedlen,DBMASK);
-
-		for (i=0;i<olen-seedlen;i++) DBMASK[i]^=f[i];
-		MGF1(DBMASK,seedlen,f);
-
-		for (i=0;i<seedlen;i++) f[i]^=SEED[i];
-
-		for (i=0;i<olen-seedlen;i++) f[i+seedlen]=DBMASK[i];
-
-		/* pad to length RFS */
-		int d=1;
-		for (i=RFS-1;i>=d;i--)
-			f[i]=f[i-d];
-		for (i=d-1;i>=0;i--)
-			f[i]=0;
-
-		return f;
-	}
-
-	/* OAEP Message Decoding for Decryption */
-	public static byte[] OAEP_DECODE(byte[] p,byte[] f)
-	{
-		int x,t;
-		boolean comp;
-		int i,k,olen=RFS-1;
-		int hlen,seedlen;
-
-		HASH H=new HASH();
-		hlen=HASH.len;
-		byte[] SEED=new byte[hlen];
-		seedlen=hlen;
-		byte[] CHASH=new byte[hlen];
-
-		if (olen<seedlen+hlen+1) return new byte[0];
-		byte[] DBMASK=new byte[olen-seedlen];
-		for (i=0;i<olen-seedlen;i++) DBMASK[i]=0;
-
-		if (f.length<RFS)
-		{
-			int d=RFS-f.length;
-			for (i=RFS-1;i>=d;i--)
-				f[i]=f[i-d];
-			for (i=d-1;i>=0;i--)
-				f[i]=0;
-
-		}
-
-		if (p!=null) H.process_array(p);
-		byte[] h=H.hash();
-		for (i=0;i<hlen;i++) CHASH[i]=h[i];
-
-		x=f[0];
-
-		for (i=seedlen;i<olen;i++)
-			DBMASK[i-seedlen]=f[i+1];
-
-		MGF1(DBMASK,seedlen,SEED);
-		for (i=0;i<seedlen;i++) SEED[i]^=f[i+1];
-		MGF1(SEED,olen-seedlen,f);
-		for (i=0;i<olen-seedlen;i++) DBMASK[i]^=f[i];
-
-		comp=true;
-		for (i=0;i<hlen;i++)
-		{
-			if (CHASH[i]!=DBMASK[i]) comp=false;
-		}
-
-		for (i=0;i<olen-seedlen-hlen;i++)
-			DBMASK[i]=DBMASK[i+hlen];
-
-		for (i=0;i<hlen;i++)
-			SEED[i]=CHASH[i]=0;
-
-		for (k=0;;k++)
-		{
-			if (k>=olen-seedlen-hlen) return new byte[0];
-			if (DBMASK[k]!=0) break;
-		}
-
-		t=DBMASK[k];
-		if (!comp || x!=0 || t!=0x01)
-		{
-			for (i=0;i<olen-seedlen;i++) DBMASK[i]=0;
-			return new byte[0];
-		}
-
-		byte[] r=new byte[olen-seedlen-hlen-k-1];
-
-		for (i=0;i<olen-seedlen-hlen-k-1;i++)
-			r[i]=DBMASK[i+k+1];
-
-		for (i=0;i<olen-seedlen;i++) DBMASK[i]=0;
-
-		return r;
-	}
-
-	/* destroy the Private Key structure */
-	public static void PRIVATE_KEY_KILL(rsa_private_key PRIV)
-	{
-		PRIV.p.zero();
-		PRIV.q.zero();
-		PRIV.dp.zero();
-		PRIV.dq.zero();
-		PRIV.c.zero();
-	}
-
-	/* RSA encryption with the public key */
-	public static void ENCRYPT(rsa_public_key PUB,byte[] F,byte[] G)
-	{
-		int n=PUB.n.getlen();
-		FF f=new FF(n);
-
-		FF.fromBytes(f,F);
-		f.power(PUB.e,PUB.n);
-		f.toBytes(G);
-	}
-
-	/* RSA decryption with the private key */
-	public static void DECRYPT(rsa_private_key PRIV,byte[] G,byte[] F)
-	{
-		int n=PRIV.p.getlen();
-		FF g=new FF(2*n);
-
-		FF.fromBytes(g,G);
-		FF jp=g.dmod(PRIV.p);
-		FF jq=g.dmod(PRIV.q);
-
-		jp.skpow(PRIV.dp,PRIV.p);
-		jq.skpow(PRIV.dq,PRIV.q);
-
-		g.zero();
-		g.dscopy(jp);
-		jp.mod(PRIV.q);
-		if (FF.comp(jp,jq)>0) jq.add(PRIV.q);
-		jq.sub(jp);
-		jq.norm();
-
-		FF t=FF.mul(PRIV.c,jq);
-		jq=t.dmod(PRIV.q);
-
-		t=FF.mul(jq,PRIV.p);
-		g.add(t);
-		g.norm();
-
-		g.toBytes(F);
-	}
-}
diff --git a/java64/TestECDH.java b/java64/TestECDH.java
deleted file mode 100755
index 3027f12..0000000
--- a/java64/TestECDH.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
-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.
-*/
-
-/* test driver and function exerciser for ECDH/ECIES/ECDSA API Functions */
-
-public class TestECDH
-{
-	public static void printBinary(byte[] array)
-	{
-		int i;
-		for (i=0;i<array.length;i++)
-		{
-			System.out.printf("%02x", array[i]);
-		}
-		System.out.println();
-	}
-
-	public static void main(String[] args)
-	{
-		int i,j=0,res;
-		int result;
-		String pp=new String("M0ng00se");
-
-		int EGS=ECDH.EGS;
-		int EFS=ECDH.EFS;
-		int EAS=AES.KS;
-
-		byte[] S1=new byte[EGS];
-		byte[] W0=new byte[2*EFS+1];
-		byte[] W1=new byte[2*EFS+1];
-		byte[] Z0=new byte[EFS];
-		byte[] Z1=new byte[EFS];
-		byte[] RAW=new byte[100];
-		byte[] SALT=new byte[8];
-		byte[] P1=new byte[3];
-		byte[] P2=new byte[4];
-		byte[] V=new byte[2*EFS+1];
-		byte[] M=new byte[17];
-		byte[] T=new byte[12];
-		byte[] CS=new byte[EGS];
-		byte[] DS=new byte[EGS];
-
-		RAND rng=new RAND();
-
-		rng.clean();
-		for (i=0;i<100;i++) RAW[i]=(byte)(i);
-
-		rng.seed(100,RAW);
-
-//for (j=0;j<100;j++)
-//{
-
-		for (i=0;i<8;i++) SALT[i]=(byte)(i+1);  // set Salt
-
-		System.out.println("Alice's Passphrase= "+pp);
-		byte[] PW=pp.getBytes();
-
-/* private key S0 of size EGS bytes derived from Password and Salt */
-
-		byte[] S0=ECDH.PBKDF2(PW,SALT,1000,EGS);
-
-		System.out.print("Alice's private key= 0x");
-		printBinary(S0);
-
-/* Generate Key pair S/W */
-		ECDH.KEY_PAIR_GENERATE(null,S0,W0);
-
-		System.out.print("Alice's public key= 0x");
-		printBinary(W0);
-
-		res=ECDH.PUBLIC_KEY_VALIDATE(true,W0);
-		if (res!=0)
-		{
-			System.out.println("ECP Public Key is invalid!\n");
-			return;
-		}
-/* Random private key for other party */
-		ECDH.KEY_PAIR_GENERATE(rng,S1,W1);
-
-		System.out.print("Servers private key= 0x");
-		printBinary(S1);
-
-		System.out.print("Servers public key= 0x");
-		printBinary(W1);
-
-
-		res=ECDH.PUBLIC_KEY_VALIDATE(true,W1);
-		if (res!=0)
-		{
-			System.out.print("ECP Public Key is invalid!\n");
-			return;
-		}
-
-/* Calculate common key using DH - IEEE 1363 method */
-
-		ECDH.ECPSVDP_DH(S0,W1,Z0);
-		ECDH.ECPSVDP_DH(S1,W0,Z1);
-
-		boolean same=true;
-		for (i=0;i<EFS;i++)
-			if (Z0[i]!=Z1[i]) same=false;
-
-		if (!same)
-		{
-			System.out.println("*** ECPSVDP-DH Failed");
-			return;
-		}
-
-		byte[] KEY=ECDH.KDF1(Z0,EAS);
-
-		System.out.print("Alice's DH Key=  0x"); printBinary(KEY);
-		System.out.print("Servers DH Key=  0x"); printBinary(KEY);
-
-		System.out.println("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=0;i<=16;i++) M[i]=(byte)i;
-
-		byte[] C=ECDH.ECIES_ENCRYPT(P1,P2,rng,W1,M,V,T);
-
-		System.out.println("Ciphertext= ");
-		System.out.print("V= 0x"); printBinary(V);
-		System.out.print("C= 0x"); printBinary(C);
-		System.out.print("T= 0x"); printBinary(T);
-
-
-		M=ECDH.ECIES_DECRYPT(P1,P2,V,C,T,S1);
-		if (M.length==0)
-		{
-			System.out.println("*** ECIES Decryption Failed\n");
-			return;
-		}
-		else System.out.println("Decryption succeeded");
-
-		System.out.print("Message is 0x"); printBinary(M);
-
-		System.out.println("Testing ECDSA");
-
-		if (ECDH.ECPSP_DSA(rng,S0,M,CS,DS)!=0)
-		{
-			System.out.println("***ECDSA Signature Failed");
-			return;
-		}
-		System.out.println("Signature= ");
-		System.out.print("C= 0x"); printBinary(CS);
-		System.out.print("D= 0x"); printBinary(DS);
-
-		if (ECDH.ECPVP_DSA(W0,M,CS,DS)!=0)
-		{
-			System.out.println("***ECDSA Verification Failed");
-			return;
-		}
-		else System.out.println("ECDSA Signature/Verification succeeded "+j);
-//}
-//System.out.println("Test Completed Successfully");
-	}
-}
diff --git a/java64/TestECM.java b/java64/TestECM.java
deleted file mode 100755
index b0a07a1..0000000
--- a/java64/TestECM.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
-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.
-*/
-
-/* test driver and function exerciser for ECDH API Function only - for use with Montgomery curves */
-
-public class TestECM
-{
-	public static void printBinary(byte[] array)
-	{
-		int i;
-		for (i=0;i<array.length;i++)
-		{
-			System.out.printf("%02x", array[i]);
-		}
-		System.out.println();
-	}
-
-	public static void main(String[] args)
-	{
-		int i,j=0,res;
-		int result;
-		String pp=new String("M0ng00se");
-
-		int EGS=ECDH.EGS;
-		int EFS=ECDH.EFS;
-		int EAS=AES.KS;
-
-		byte[] S1=new byte[EGS];
-		byte[] W0=new byte[2*EFS+1];
-		byte[] W1=new byte[2*EFS+1];
-		byte[] Z0=new byte[EFS];
-		byte[] Z1=new byte[EFS];
-		byte[] RAW=new byte[100];
-		byte[] SALT=new byte[8];
-
-		RAND rng=new RAND();
-
-		rng.clean();
-		for (i=0;i<100;i++) RAW[i]=(byte)(i);
-
-		rng.seed(100,RAW);
-
-//for (j=0;j<100;j++)
-//{
-
-		for (i=0;i<8;i++) SALT[i]=(byte)(i+1);  // set Salt
-
-		System.out.println("Alice's Passphrase= "+pp);
-		byte[] PW=pp.getBytes();
-
-/* private key S0 of size EGS bytes derived from Password and Salt */
-
-		byte[] S0=ECDH.PBKDF2(PW,SALT,1000,EGS);
-
-		System.out.print("Alice's private key= 0x");
-		printBinary(S0);
-
-/* Generate Key pair S/W */
-		ECDH.KEY_PAIR_GENERATE(null,S0,W0);
-
-		System.out.print("Alice's public key= 0x");
-		printBinary(W0);
-
-		res=ECDH.PUBLIC_KEY_VALIDATE(true,W0);
-		if (res!=0)
-		{
-			System.out.println("Alice's public Key is invalid!\n");
-			return;
-		}
-/* Random private key for other party */
-		ECDH.KEY_PAIR_GENERATE(rng,S1,W1);
-
-		System.out.print("Servers private key= 0x");
-		printBinary(S1);
-
-		System.out.print("Servers public key= 0x");
-		printBinary(W1);
-
-
-		res=ECDH.PUBLIC_KEY_VALIDATE(true,W1);
-		if (res!=0)
-		{
-			System.out.print("Server's public Key is invalid!\n");
-			return;
-		}
-
-/* Calculate common key using DH - IEEE 1363 method */
-
-		ECDH.ECPSVDP_DH(S0,W1,Z0);
-		ECDH.ECPSVDP_DH(S1,W0,Z1);
-
-		boolean same=true;
-		for (i=0;i<EFS;i++)
-			if (Z0[i]!=Z1[i]) same=false;
-
-		if (!same)
-		{
-			System.out.println("*** ECPSVDP-DH Failed");
-			return;
-		}
-
-		byte[] KEY=ECDH.KDF1(Z0,EAS);
-
-		System.out.print("Alice's DH Key=  0x"); printBinary(KEY);
-		System.out.print("Servers DH Key=  0x"); printBinary(KEY);
-
-//}
-//System.out.println("Test Completed Successfully");
-	}
-}
diff --git a/java64/TestMPIN.java b/java64/TestMPIN.java
deleted file mode 100755
index f883a57..0000000
--- a/java64/TestMPIN.java
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
-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.
-*/
-
-/* test driver and function exerciser for MPIN API Functions */
-
-import java.util.Date;
-import java.util.Scanner;
-
-public class TestMPIN
-{
-	static boolean PERMITS=true;
-	static boolean PINERROR=true;
-	static boolean FULL=true;
-	static boolean SINGLE_PASS=false;
-
-	static void printBinary(byte[] array)
-	{
-		int i;
-		for (i=0;i<array.length;i++)
-		{
-			System.out.printf("%02x", array[i]);
-		}
-		System.out.println();
-	}
-
-	public static void main(String[] args) {
-		RAND rng=new RAND();
-		byte[] raw=new byte[100];
-		for (int i=0;i<100;i++) raw[i]=(byte)(i+1);
-		rng.seed(100,raw);
-
-		int EGS=MPIN.EGS;
-		int EFS=MPIN.EFS;
-		int G1S=2*EFS+1; /* Group 1 Size */
-		int G2S=4*EFS; /* Group 2 Size */
-		int EAS=16;
-
-		byte[] S=new byte[EGS];
-		byte[] SST = new byte[G2S];
-		byte[] TOKEN = new byte[G1S];
-		byte[] PERMIT = new byte[G1S];
-		byte[] SEC = new byte[G1S];
-		byte[] xID = new byte[G1S];
-		byte[] xCID = new byte[G1S];
-		byte[] X= new byte[EGS];
-		byte[] Y= new byte[EGS];
-		byte[] E=new byte[12*EFS];
-		byte[] F=new byte[12*EFS];
-		byte[] HID=new byte[G1S];
-		byte[] HTID=new byte[G1S];
-
-		byte[] G1=new byte[12*EFS];
-		byte[] G2=new byte[12*EFS];
-		byte[] R=new byte[EGS];
-		byte[] Z=new byte[G1S];
-		byte[] W=new byte[EGS];
-		byte[] T=new byte[G1S];
-		byte[] CK=new byte[EAS];
-		byte[] SK=new byte[EAS];
-
-/* Trusted Authority set-up */
-
-		MPIN.RANDOM_GENERATE(rng,S);
-		System.out.print("Master Secret s: 0x");  printBinary(S);
-
- /* Create Client Identity */
- 		String IDstr = "testUser@miracl.com";
-		byte[] CLIENT_ID = IDstr.getBytes();
-
-		byte[] HCID=MPIN.HASH_ID(CLIENT_ID);  /* Either Client or TA calculates Hash(ID) - you decide! */
-
-		System.out.print("Client ID= "); printBinary(CLIENT_ID);
-
-/* Client and Server are issued secrets by DTA */
-		MPIN.GET_SERVER_SECRET(S,SST);
-		System.out.print("Server Secret SS: 0x");  printBinary(SST);
-
-		MPIN.GET_CLIENT_SECRET(S,HCID,TOKEN);
-		System.out.print("Client Secret CS: 0x");
-		printBinary(TOKEN);
-
-/* Client extracts PIN from secret to create Token */
-		int pin=1234;
-		System.out.println("Client extracts PIN= "+pin);
-		int rtn=MPIN.EXTRACT_PIN(CLIENT_ID,pin,TOKEN);
-		if (rtn != 0)
-			System.out.println("FAILURE: EXTRACT_PIN rtn: " + rtn);
-
-		System.out.print("Client Token TK: 0x");
-		printBinary(TOKEN);
-
-		if (FULL)
-		{
-			MPIN.PRECOMPUTE(TOKEN,HCID,G1,G2);
-		}
-		int date;
-		if (PERMITS)
-		{
-			date=MPIN.today();
-			System.out.println("Date= "+date);
-/* Client gets "Time Token" permit from DTA */
-			MPIN.GET_CLIENT_PERMIT(date,S,HCID,PERMIT);
-			System.out.print("Time Permit TP: 0x");  printBinary(PERMIT);
-
-/* This encoding makes Time permit look random - Elligator squared */
-			MPIN.ENCODING(rng,PERMIT);
-			System.out.print("Encoded Time Permit TP: 0x");  printBinary(PERMIT);
-			MPIN.DECODING(PERMIT);
-			System.out.print("Decoded Time Permit TP: 0x");  printBinary(PERMIT);
-		}
-		else date=0;
-
-		System.out.print("\nPIN= ");
-		Scanner scan=new Scanner(System.in);
-		pin=scan.nextInt();
-
-/* 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.
-
-
-*/
-
-		byte[] pxID=xID;
-		byte[] pxCID=xCID;
-		byte[] pHID=HID;
-		byte[] pHTID=HTID;
-		byte[] pE=E;
-		byte[] pF=F;
-		byte[] pPERMIT=PERMIT;
-		byte[] prHID;
-
-		if (date!=0)
-		{
-
-			prHID=pHTID;
-			if (!PINERROR)
-			{
-				pxID=null;
-				pHID=null;
-			}
-		}
-		else
-		{
-			prHID=pHID;
-			pPERMIT=null;
-			pxCID=null;
-			pHTID=null;
-		}
-		if (!PINERROR)
-		{
-			pE=null;
-			pF=null;
-		}
-
-                if (SINGLE_PASS)
-		{
-  		  System.out.println("MPIN Single Pass");
-                  int timeValue = MPIN.GET_TIME();
-                  rtn=MPIN.CLIENT(date,CLIENT_ID,rng,X,pin,TOKEN,SEC,pxID,pxCID,pPERMIT,timeValue,Y);
-  		  if (rtn != 0)
-  		    System.out.println("FAILURE: CLIENT rtn: " + rtn);
-
-                  if (FULL)
-		  {
-                    HCID=MPIN.HASH_ID(CLIENT_ID);
-                    MPIN.GET_G1_MULTIPLE(rng,1,R,HCID,Z);  /* Also Send Z=r.ID to Server, remember random r */
-                  }
-
-                  rtn=MPIN.SERVER(date,pHID,pHTID,Y,SST,pxID,pxCID,SEC,pE,pF,CLIENT_ID,timeValue);
-                  if (rtn != 0)
-  		    System.out.println("FAILURE: SERVER rtn: " + rtn);
-
-                  if (FULL)
-                  {
-                    MPIN.GET_G1_MULTIPLE(rng,0,W,prHID,T);  /* Also send T=w.ID to client, remember random w  */
-                  }
-		}
-                else
-		{
-  		  System.out.println("MPIN Multi Pass");
-                  /* Send U=x.ID to server, and recreate secret from token and pin */
-  		  rtn=MPIN.CLIENT_1(date,CLIENT_ID,rng,X,pin,TOKEN,SEC,pxID,pxCID,pPERMIT);
-  		  if (rtn != 0)
-  		    System.out.println("FAILURE: CLIENT_1 rtn: " + rtn);
-
-  		  if (FULL)
-  		  {
-  		    HCID=MPIN.HASH_ID(CLIENT_ID);
-  		    MPIN.GET_G1_MULTIPLE(rng,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. */
-  		  MPIN.SERVER_1(date,CLIENT_ID,pHID,pHTID);
-
-                  /* Server generates Random number Y and sends it to Client */
-  		  MPIN.RANDOM_GENERATE(rng,Y);
-
-                  if (FULL)
-  		  {
-  		    MPIN.GET_G1_MULTIPLE(rng,0,W,prHID,T);  /* Also send T=w.ID to client, remember random w  */
-  		  }
-
-                  /* Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC */
-  		  rtn=MPIN.CLIENT_2(X,Y,SEC);
-  		  if (rtn != 0)
-  		    System.out.println("FAILURE: CLIENT_2 rtn: " + rtn);
-
-                  /* Server Second pass. Inputs hashed client id, random Y, -(x+y)*SEC, xID and xCID and Server secret SST. E and F help kangaroos to find error. */
-                  /* If PIN error not required, set E and F = null */
-
-  		  rtn=MPIN.SERVER_2(date,pHID,pHTID,Y,SST,pxID,pxCID,SEC,pE,pF);
-
-  		  if (rtn != 0)
-  		    System.out.println("FAILURE: SERVER_1 rtn: " + rtn);
-		}
-
-		if (rtn == MPIN.BAD_PIN)
-		{
-		  System.out.println("Server says - Bad Pin. I don't know you. Feck off.\n");
-		  if (PINERROR)
-		  {
-		    int err=MPIN.KANGAROO(E,F);
-		    if (err!=0) System.out.format("(Client PIN is out by %d)\n",err);
-		  }
-		  return;
-		}
-		else System.out.println("Server says - PIN is good! You really are "+IDstr);
-
-
-		if (FULL)
-		{
-			MPIN.CLIENT_KEY(G1,G2,pin,R,X,T,CK);
-			System.out.print("Client Key =  0x");  printBinary(CK);
-
-			MPIN.SERVER_KEY(Z,SST,W,pxID,pxCID,SK);
-			System.out.print("Server Key =  0x");  printBinary(SK);
-		}
-	}
-}
diff --git a/java64/TestRSA.java b/java64/TestRSA.java
deleted file mode 100755
index 2c30155..0000000
--- a/java64/TestRSA.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
-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.
-*/
-
-/* test driver and function exerciser for RSA API Functions */
-
-public class TestRSA
-{
-
-	public static void main(String[] args)
-	{
-		int i;
-		int RFS=RSA.RFS;
-
-		String message="Hello World\n";
-
-		rsa_public_key pub=new rsa_public_key(ROM.FFLEN);
-		rsa_private_key priv=new rsa_private_key(ROM.HFLEN);
-
-		byte[] ML=new byte[RFS];
-		byte[] C=new byte[RFS];
-		byte[] RAW=new byte[100];
-
-		RAND rng=new RAND();
-
-		rng.clean();
-		for (i=0;i<100;i++) RAW[i]=(byte)(i);
-
-		rng.seed(100,RAW);
-//for (i=0;i<10;i++)
-//{
-		System.out.println("Generating public/private key pair");
-		RSA.KEY_PAIR(rng,65537,priv,pub);
-
-		byte[] M=message.getBytes();
-		System.out.print("Encrypting test string\n");
-		byte[] E=RSA.OAEP_ENCODE(M,rng,null); /* OAEP encode message M to E  */
-
-		RSA.ENCRYPT(pub,E,C);     /* encrypt encoded message */
-		System.out.print("Ciphertext= 0x"); RSA.printBinary(C);
-
-		System.out.print("Decrypting test string\n");
-		RSA.DECRYPT(priv,C,ML);
-		byte[] MS=RSA.OAEP_DECODE(null,ML); /* OAEP decode message  */
-
-		message=new String(MS);
-		System.out.print(message);
-//}
-		RSA.PRIVATE_KEY_KILL(priv);
-	}
-}
diff --git a/java64/readme.txt b/java64/readme.txt
deleted file mode 100644
index c4bd115..0000000
--- a/java64/readme.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-AMCL is very simple to build for Java. This version is optimal for a 64-bit 
-Virtual Machine.
-
-First - decide the modulus type and curve type you want to use. Edit ROM.java 
-where indicated. You might want to use one of the curves whose details are
-already in there.
-
-Three example API files are provided, MPIN.java which 
-supports our M-Pin (tm) protocol, ECDH.java which supports elliptic 
-curve key exchange, digital signature and public key crypto, and RSA.java
-which supports the RSA method. The first  can be tested using the 
-TestMPIN.java driver programs, the second can be tested using TestECDH.java 
-and TestECM.java, and the third with TestRSA.java
-
-In the ROM.java file you must provide the curve constants. Several examples
-are provided there, if you are willing to use one of these.
-
-To help generate the ROM constants for your own curve some MIRACL helper 
-programs are included. The program bngen.cpp generates the ROM details for a 
-BN curve, and the program ecgen.cpp generates the ROM for EC curves. 
-
-The program bigtobig.cpp converts a big number to the AMCL 
-BIG format.
-
-Don't forget to delete all .class files before rebuilding projects.
-
-For a quick jumpstart:-
-
-del *.class
-javac TestMPIN.java
-java TestMPIN
-
diff --git a/js/AES.js b/js/AES.js
deleted file mode 100755
index 39f8aa6..0000000
--- a/js/AES.js
+++ /dev/null
@@ -1,424 +0,0 @@
-/*
-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.
-*/
-
-var AES = function() {
-	this.mode=0;
-	this.fkey=[];
-	this.rkey=[];
-	this.f=[];
-};
-
-AES.prototype={
-/* reset cipher */
-	reset:function(m,iv)
-	{ /* reset mode, or reset iv */
-		var i;
-		this.mode=m;
-		for (i=0;i<16;i++)
-			this.f[i]=0;
-		if (this.mode!=this.ECB && iv!==null)
-			for (i=0;i<16;i++)
-				this.f[i]=iv[i];
-	},
-
-	getreg:function()
-	{
-		var ir=[];
-		for (var i=0;i<16;i++) ir[i]=this.f[i];
-		return ir;
-	},
-
-/* Initialise cipher */
-	init: function(m,key,iv)
-	{	/* Key=16 bytes */
-		/* Key Scheduler. Create expanded encryption key */
-		var i,j,k,N,nk;
-		var CipherKey= [];
-    	var b=[];
-		nk=4;
-		this.reset(m,iv);
-		N=44;
-
-		for (i=j=0;i<nk;i++,j+=4)
-		{
-			for (k=0;k<4;k++) b[k]=key[j+k];
-			CipherKey[i]=AES.pack(b);
-		}
-		for (i=0;i<nk;i++) this.fkey[i]=CipherKey[i];
-		for (j=nk,k=0;j<N;j+=nk,k++)
-		{
-			this.fkey[j]=this.fkey[j-nk]^AES.SubByte(AES.ROTL24(this.fkey[j-1]))^(ROM.rco[k])&0xff;
-			for (i=1;i<nk && (i+j)<N;i++)
-				this.fkey[i+j]=this.fkey[i+j-nk]^this.fkey[i+j-1];
-		}
-
- /* now for the expanded decrypt key in reverse order */
-
-		for (j=0;j<4;j++) this.rkey[j+N-4]=this.fkey[j];
-		for (i=4;i<N-4;i+=4)
-		{
-			k=N-4-i;
-			for (j=0;j<4;j++) this.rkey[k+j]=AES.InvMixCol(this.fkey[i+j]);
-		}
-		for (j=N-4;j<N;j++) this.rkey[j-N+4]=this.fkey[j];
-	},
-
-/* Encrypt a single block */
-	ecb_encrypt: function(buff)
-	{
-		var i,j,k;
-		var t;
-    	var b=[];
-    	var p=[];
-    	var q=[];
-
-		for (i=j=0;i<4;i++,j+=4)
-		{
-			for (k=0;k<4;k++) b[k]=buff[j+k];
-			p[i]=AES.pack(b);
-			p[i]^=this.fkey[i];
-		}
-
-		k=4;
-
-/* State alternates between p and q */
-		for (i=1;i<10;i++)
-		{
-			q[0]=this.fkey[k]^ROM.ftable[p[0]&0xff]^
-				AES.ROTL8(ROM.ftable[(p[1]>>>8)&0xff])^
-				AES.ROTL16(ROM.ftable[(p[2]>>>16)&0xff])^
-				AES.ROTL24(ROM.ftable[(p[3]>>>24)&0xff]);
-			q[1]=this.fkey[k+1]^ROM.ftable[p[1]&0xff]^
-				AES.ROTL8(ROM.ftable[(p[2]>>>8)&0xff])^
-				AES.ROTL16(ROM.ftable[(p[3]>>>16)&0xff])^
-				AES.ROTL24(ROM.ftable[(p[0]>>>24)&0xff]);
-			q[2]=this.fkey[k+2]^ROM.ftable[p[2]&0xff]^
-				AES.ROTL8(ROM.ftable[(p[3]>>>8)&0xff])^
-				AES.ROTL16(ROM.ftable[(p[0]>>>16)&0xff])^
-				AES.ROTL24(ROM.ftable[(p[1]>>>24)&0xff]);
-			q[3]=this.fkey[k+3]^ROM.ftable[p[3]&0xff]^
-				AES.ROTL8(ROM.ftable[(p[0]>>>8)&0xff])^
-				AES.ROTL16(ROM.ftable[(p[1]>>>16)&0xff])^
-				AES.ROTL24(ROM.ftable[(p[2]>>>24)&0xff]);
-
-			k+=4;
-			for (j=0;j<4;j++)
-			{
-				t=p[j]; p[j]=q[j]; q[j]=t;
-			}
-		}
-
-/* Last Round */
-
-		q[0]=this.fkey[k]^(ROM.fbsub[p[0]&0xff]&0xff)^
-			AES.ROTL8(ROM.fbsub[(p[1]>>>8)&0xff]&0xff)^
-			AES.ROTL16(ROM.fbsub[(p[2]>>>16)&0xff]&0xff)^
-			AES.ROTL24(ROM.fbsub[(p[3]>>>24)&0xff]&0xff);
-
-		q[1]=this.fkey[k+1]^(ROM.fbsub[p[1]&0xff]&0xff)^
-			AES.ROTL8(ROM.fbsub[(p[2]>>>8)&0xff]&0xff)^
-			AES.ROTL16(ROM.fbsub[(p[3]>>>16)&0xff]&0xff)^
-			AES.ROTL24(ROM.fbsub[(p[0]>>>24)&0xff]&0xff);
-
-		q[2]=this.fkey[k+2]^(ROM.fbsub[p[2]&0xff]&0xff)^
-			AES.ROTL8(ROM.fbsub[(p[3]>>>8)&0xff]&0xff)^
-			AES.ROTL16(ROM.fbsub[(p[0]>>>16)&0xff]&0xff)^
-			AES.ROTL24(ROM.fbsub[(p[1]>>>24)&0xff]&0xff);
-
-		q[3]=this.fkey[k+3]^(ROM.fbsub[(p[3])&0xff]&0xff)^
-			AES.ROTL8(ROM.fbsub[(p[0]>>>8)&0xff]&0xff)^
-			AES.ROTL16(ROM.fbsub[(p[1]>>>16)&0xff]&0xff)^
-			AES.ROTL24(ROM.fbsub[(p[2]>>>24)&0xff]&0xff);
-
-		for (i=j=0;i<4;i++,j+=4)
-		{
-			b=AES.unpack(q[i]);
-			for (k=0;k<4;k++) buff[j+k]=b[k];
-		}
-	},
-
-/* Decrypt a single block */
-	ecb_decrypt: function(buff)
-	{
-		var i,j,k;
-		var t;
-    	var b=[];
-    	var p=[];
-    	var q=[];
-
-		for (i=j=0;i<4;i++,j+=4)
-		{
-			for (k=0;k<4;k++) b[k]=buff[j+k];
-			p[i]=AES.pack(b);
-			p[i]^=this.rkey[i];
-		}
-
-		k=4;
-
-/* State alternates between p and q */
-		for (i=1;i<10;i++)
-		{
-			q[0]=this.rkey[k]^ROM.rtable[p[0]&0xff]^
-				AES.ROTL8(ROM.rtable[(p[3]>>>8)&0xff])^
-				AES.ROTL16(ROM.rtable[(p[2]>>>16)&0xff])^
-				AES.ROTL24(ROM.rtable[(p[1]>>>24)&0xff]);
-			q[1]=this.rkey[k+1]^ROM.rtable[p[1]&0xff]^
-				AES.ROTL8(ROM.rtable[(p[0]>>>8)&0xff])^
-				AES.ROTL16(ROM.rtable[(p[3]>>>16)&0xff])^
-				AES.ROTL24(ROM.rtable[(p[2]>>>24)&0xff]);
-			q[2]=this.rkey[k+2]^ROM.rtable[p[2]&0xff]^
-				AES.ROTL8(ROM.rtable[(p[1]>>>8)&0xff])^
-				AES.ROTL16(ROM.rtable[(p[0]>>>16)&0xff])^
-				AES.ROTL24(ROM.rtable[(p[3]>>>24)&0xff]);
-			q[3]=this.rkey[k+3]^ROM.rtable[p[3]&0xff]^
-				AES.ROTL8(ROM.rtable[(p[2]>>>8)&0xff])^
-				AES.ROTL16(ROM.rtable[(p[1]>>>16)&0xff])^
-				AES.ROTL24(ROM.rtable[(p[0]>>>24)&0xff]);
-
-			k+=4;
-			for (j=0;j<4;j++)
-			{
-				t=p[j]; p[j]=q[j]; q[j]=t;
-			}
-		}
-
-/* Last Round */
-
-		q[0]=this.rkey[k]^(ROM.rbsub[p[0]&0xff]&0xff)^
-			AES.ROTL8(ROM.rbsub[(p[3]>>>8)&0xff]&0xff)^
-			AES.ROTL16(ROM.rbsub[(p[2]>>>16)&0xff]&0xff)^
-			AES.ROTL24(ROM.rbsub[(p[1]>>>24)&0xff]&0xff);
-		q[1]=this.rkey[k+1]^(ROM.rbsub[p[1]&0xff]&0xff)^
-			AES.ROTL8(ROM.rbsub[(p[0]>>>8)&0xff]&0xff)^
-			AES.ROTL16(ROM.rbsub[(p[3]>>>16)&0xff]&0xff)^
-			AES.ROTL24(ROM.rbsub[(p[2]>>>24)&0xff]&0xff);
-		q[2]=this.rkey[k+2]^(ROM.rbsub[p[2]&0xff]&0xff)^
-			AES.ROTL8(ROM.rbsub[(p[1]>>>8)&0xff]&0xff)^
-			AES.ROTL16(ROM.rbsub[(p[0]>>>16)&0xff]&0xff)^
-			AES.ROTL24(ROM.rbsub[(p[3]>>>24)&0xff]&0xff);
-		q[3]=this.rkey[k+3]^(ROM.rbsub[p[3]&0xff]&0xff)^
-			AES.ROTL8(ROM.rbsub[(p[2]>>>8)&0xff]&0xff)^
-			AES.ROTL16(ROM.rbsub[(p[1]>>>16)&0xff]&0xff)^
-			AES.ROTL24(ROM.rbsub[(p[0]>>>24)&0xff]&0xff);
-
-		for (i=j=0;i<4;i++,j+=4)
-		{
-			b=AES.unpack(q[i]);
-			for (k=0;k<4;k++) buff[j+k]=b[k];
-		}
-
-	},
-
-/* Encrypt using selected mode of operation */
-	encrypt: function(buff)
-	{
-		var j,bytes;
-		var st=[];
-		var fell_off;
-
-// Supported Modes of Operation
-
-		fell_off=0;
-
-		switch (this.mode)
-		{
-		case ROM.ECB:
-			this.ecb_encrypt(buff);
-			return 0;
-		case ROM.CBC:
-			for (j=0;j<16;j++) buff[j]^=this.f[j];
-			this.ecb_encrypt(buff);
-			for (j=0;j<16;j++) this.f[j]=buff[j];
-			return 0;
-
-		case ROM.CFB1:
-		case ROM.CFB2:
-		case ROM.CFB4:
-			bytes=this.mode-ROM.CFB1+1;
-			for (j=0;j<bytes;j++) fell_off=(fell_off<<8)|this.f[j];
-			for (j=0;j<16;j++) st[j]=this.f[j];
-			for (j=bytes;j<16;j++) this.f[j-bytes]=this.f[j];
-			this.ecb_encrypt(st);
-			for (j=0;j<bytes;j++)
-			{
-				buff[j]^=st[j];
-				this.f[16-bytes+j]=buff[j];
-			}
-			return fell_off;
-
-		case ROM.OFB1:
-		case ROM.OFB2:
-		case ROM.OFB4:
-		case ROM.OFB8:
-		case ROM.OFB16:
-
-			bytes=this.mode-ROM.OFB1+1;
-			this.ecb_encrypt(this.f);
-			for (j=0;j<bytes;j++) buff[j]^=this.f[j];
-			return 0;
-
-    default:
-			return 0;
-		}
-	},
-
-/* Decrypt using selected mode of operation */
-	decrypt: function(buff)
-	{
-		var j,bytes;
-		var st=[];
-		var fell_off;
-
-   // Supported modes of operation
-		fell_off=0;
-		switch (this.mode)
-		{
-		case ROM.ECB:
-			this.ecb_decrypt(buff);
-			return 0;
-		case ROM.CBC:
-			for (j=0;j<16;j++)
-			{
-				st[j]=this.f[j];
-				this.f[j]=buff[j];
-			}
-			this.ecb_decrypt(buff);
-			for (j=0;j<16;j++)
-			{
-				buff[j]^=st[j];
-				st[j]=0;
-			}
-			return 0;
-		case ROM.CFB1:
-		case ROM.CFB2:
-		case ROM.CFB4:
-			bytes=this.mode-ROM.CFB1+1;
-			for (j=0;j<bytes;j++) fell_off=(fell_off<<8)|this.f[j];
-			for (j=0;j<16;j++) st[j]=this.f[j];
-			for (j=bytes;j<16;j++) this.f[j-bytes]=this.f[j];
-			this.ecb_encrypt(st);
-			for (j=0;j<bytes;j++)
-			{
-				this.f[16-bytes+j]=buff[j];
-				buff[j]^=st[j];
-			}
-			return fell_off;
-		case ROM.OFB1:
-		case ROM.OFB2:
-		case ROM.OFB4:
-		case ROM.OFB8:
-		case ROM.OFB16:
-			bytes=this.mode-ROM.OFB1+1;
-			this.ecb_encrypt(this.f);
-			for (j=0;j<bytes;j++) buff[j]^=this.f[j];
-			return 0;
-
-
-		default:
-			return 0;
-		}
-	},
-
-/* Clean up and delete left-overs */
-	end: function()
-	{ // clean up
-		var i;
-		for (i=0;i<44;i++)
-			this.fkey[i]=this.rkey[i]=0;
-		for (i=0;i<16;i++)
-			this.f[i]=0;
-	}
-
-};
-
-AES.ROTL8=function(x)
-{
-	return (((x)<<8)|((x)>>>24));
-};
-
-AES.ROTL16=function(x)
-{
-	return (((x)<<16)|((x)>>>16));
-};
-
-AES.ROTL24=function(x)
-{
-	return (((x)<<24)|((x)>>>8));
-};
-
-AES.pack= function(b)
-{ /* pack 4 bytes into a 32-bit Word */
-		return (((b[3])&0xff)<<24)|((b[2]&0xff)<<16)|((b[1]&0xff)<<8)|(b[0]&0xff);
-};
-
-AES.unpack=function(a)
-{ /* unpack bytes from a word */
-	var b=[];
-	b[0]=(a&0xff);
-	b[1]=((a>>>8)&0xff);
-	b[2]=((a>>>16)&0xff);
-	b[3]=((a>>>24)&0xff);
-	return b;
-};
-
-AES.bmul=function(x,y)
-{ /* x.y= AntiLog(Log(x) + Log(y)) */
-
-	var ix=(x&0xff);
-	var iy=(y&0xff);
-	var lx=(ROM.ltab[ix])&0xff;
-	var ly=(ROM.ltab[iy])&0xff;
-	if (x!==0 && y!==0) return ROM.ptab[(lx+ly)%255];
-	else return 0;
-};
-
-//  if (x && y)
-
-AES.SubByte=function(a)
-{
-	var b=AES.unpack(a);
-	b[0]=ROM.fbsub[b[0]&0xff];
-	b[1]=ROM.fbsub[b[1]&0xff];
-	b[2]=ROM.fbsub[b[2]&0xff];
-	b[3]=ROM.fbsub[b[3]&0xff];
-	return AES.pack(b);
-};
-
-AES.product=function(x,y)
-{ /* dot product of two 4-byte arrays */
-	var xb=AES.unpack(x);
-	var yb=AES.unpack(y);
-	return (AES.bmul(xb[0],yb[0])^AES.bmul(xb[1],yb[1])^AES.bmul(xb[2],yb[2])^AES.bmul(xb[3],yb[3]))&0xff;
-};
-
-AES.InvMixCol=function(x)
-{ /* matrix Multiplication */
-	var y,m;
-	var b=[];
-	m=AES.pack(ROM.InCo);
-	b[3]=AES.product(m,x);
-	m=AES.ROTL24(m);
-	b[2]=AES.product(m,x);
-	m=AES.ROTL24(m);
-	b[1]=AES.product(m,x);
-	m=AES.ROTL24(m);
-	b[0]=AES.product(m,x);
-	y=AES.pack(b);
-	return y;
-};
diff --git a/js/BIG.js b/js/BIG.js
deleted file mode 100755
index 4b34100..0000000
--- a/js/BIG.js
+++ /dev/null
@@ -1,953 +0,0 @@
-/*
-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.
-*/
-
-/* AMCL BIG number class */
-
-/* General purpose Constructor */
-var BIG = function(x) {
-	this.w=new Array(ROM.NLEN);
-	switch (typeof(x))
-	{
-	case "object":
-		this.copy(x);
-		break;
-	case "number":
-		this.zero();
-		this.w[0]=x;
-		break;
-	default:
-		this.zero();
-	}
-};
-
-BIG.prototype={
-/* set to zero */
-	zero: function()
-	{
-		for (var i=0;i<ROM.NLEN;i++) this.w[i]=0;
-		return this;
-	},
-/* set to one */
-	one: function()
-	{
-		this.w[0]=1;
-		for (var i=1;i<ROM.NLEN;i++) this.w[i]=0;
-		return this;
-	},
-
-	get: function(i)
-	{
-		return this.w[i];
-	},
-
-	set: function(i,x)
-	{
-		this.w[i]=x;
-	},
-/* test for zero */
-	iszilch: function()
-	{
-		for (var i=0;i<ROM.NLEN;i++)
-			if (this.w[i]!==0) return false;
-		return true;
-	},
-/* test for unity */
-	isunity: function()
-	{
-		for (var i=1;i<ROM.NLEN;i++)
-			if (this.w[i]!==0) return false;
-		if (this.w[0]!=1) return false;
-		return true;
-	},
-
-/* Conditional swap of two bigs depending on d using XOR - no branches */
-	cswap: function(b,d)
-	{
-		var i;
-		var t,c=d;
-		c=~(c-1);
-
-		for (i=0;i<ROM.NLEN;i++)
-		{
-			t=c&(this.w[i]^b.w[i]);
-			this.w[i]^=t;
-			b.w[i]^=t;
-		}
-	},
-
-/* Conditional move of big depending on d using XOR - no branches */
-	cmove: function(b,d)
-	{
-		var i;
-		var t,c=d;
-		c=~(c-1);
-
-		for (i=0;i<ROM.NLEN;i++)
-		{
-			this.w[i]^=(this.w[i]^b.w[i])&c;
-		}
-	},
-
-/* copy from another BIG */
-	copy: function(y)
-	{
-		for (var i=0;i<ROM.NLEN;i++)
-			this.w[i]=y.w[i];
-		return this;
-	},
-/* copy from bottom half of DBIG */
-	hcopy: function(y)
-	{
-		for (var i=0;i<ROM.NLEN;i++)
-			this.w[i]=y.w[i];
-		return this;
-	},
-/* copy from ROM */
-	rcopy: function(y)
-	{
-		for (var i=0;i<ROM.NLEN;i++)
-			this.w[i]=y[i];
-		return this;
-	},
-
-	xortop: function(x)
-	{
-		this.w[ROM.NLEN-1]^=x;
-	},
-
-	ortop: function(x)
-	{
-		this.w[ROM.NLEN-1]|=x;
-	},
-
-/* normalise BIG - force all digits < 2^BASEBITS */
-	norm: function()
-	{
-		var d,carry=0;
-		for (var i=0;i<ROM.NLEN-1;i++)
-		{
-			d=this.w[i]+carry;
-			this.w[i]=d&ROM.MASK;
-			carry=d>>ROM.BASEBITS;
-		}
-		this.w[ROM.NLEN-1]=(this.w[ROM.NLEN-1]+carry);
-
-		return (this.w[ROM.NLEN-1]>>((8*ROM.MODBYTES)%ROM.BASEBITS));
-
-	},
-/* quick shift right by less than a word */
-	fshr: function(k)
-	{
-		var r=this.w[0]&((1<<k)-1); /* shifted out part */
-		for (var i=0;i<ROM.NLEN-1;i++)
-			this.w[i]=(this.w[i]>>k)|((this.w[i+1]<<(ROM.BASEBITS-k))&ROM.MASK);
-		this.w[ROM.NLEN-1]=this.w[ROM.NLEN-1]>>k;
-		return r;
-	},
-/* General shift right by k bits */
-	shr: function(k)
-	{
-		var n=k%ROM.BASEBITS;
-		var m=Math.floor(k/ROM.BASEBITS);
-		for (var i=0;i<ROM.NLEN-m-1;i++)
-			this.w[i]=(this.w[m+i]>>n)|((this.w[m+i+1]<<(ROM.BASEBITS-n))&ROM.MASK);
-		this.w[ROM.NLEN-m-1]=this.w[ROM.NLEN-1]>>n;
-		for (i=ROM.NLEN-m;i<ROM.NLEN;i++) this.w[i]=0;
-		return this;
-	},
-/* quick shift left by less than a word */
-	fshl: function(k)
-	{
-		this.w[ROM.NLEN-1]=((this.w[ROM.NLEN-1]<<k))|(this.w[ROM.NLEN-2]>>(ROM.BASEBITS-k));
-		for (var i=ROM.NLEN-2;i>0;i--)
-			this.w[i]=((this.w[i]<<k)&ROM.MASK)|(this.w[i-1]>>(ROM.BASEBITS-k));
-		this.w[0]=(this.w[0]<<k)&ROM.MASK;
-
-		return (this.w[ROM.NLEN-1]>>((8*ROM.MODBYTES)%ROM.BASEBITS)); /* return excess - only used in FF.java */
-	},
-/* General shift left by k bits */
-	shl: function(k)
-	{
-		var i,n=k%ROM.BASEBITS;
-		var m=Math.floor(k/ROM.BASEBITS);
-
-		this.w[ROM.NLEN-1]=((this.w[ROM.NLEN-1-m]<<n))|(this.w[ROM.NLEN-m-2]>>(ROM.BASEBITS-n));
-		for (i=ROM.NLEN-2;i>m;i--)
-			this.w[i]=((this.w[i-m]<<n)&ROM.MASK)|(this.w[i-m-1]>>(ROM.BASEBITS-n));
-		this.w[m]=(this.w[0]<<n)&ROM.MASK;
-		for (i=0;i<m;i++) this.w[i]=0;
-		return this;
-	},
-/* return length in bits */
-	nbits: function()
-	{
-		var bts,k=ROM.NLEN-1;
-		var c;
-		this.norm();
-		while (k>=0 && this.w[k]===0) k--;
-		if (k<0) return 0;
-		bts=ROM.BASEBITS*k;
-		c=this.w[k];
-		while (c!==0) {c=Math.floor(c/2); bts++;}
-		return bts;
-	},
-/* convert this to string */
-	toString: function()
-	{
-		var b;
-		var s="";
-		var len=this.nbits();
-		if (len%4===0) len=Math.floor(len/4);
-		else {len=Math.floor(len/4); len++;}
-		if (len<ROM.MODBYTES*2) len=ROM.MODBYTES*2;
-		for (var i=len-1;i>=0;i--)
-		{
-			b=new BIG(0);
-			b.copy(this);
-			b.shr(i*4);
-			s+=(b.w[0]&15).toString(16);
-		}
-		return s;
-	},
-/* this+=y */
-	add: function(y)
-	{
-		for (var i=0;i<ROM.NLEN;i++) this.w[i]+=y.w[i];
-		return this;
-	},
-/* return this+x */
-	plus: function(x)
-	{
-		var s=new BIG(0);
-		for (var i=0;i<ROM.NLEN;i++)
-			s.w[i]=this.w[i]+x.w[i];
-		return s;
-	},
-/* this+=i, where i is int */
-	inc: function(i)
-	{
-		this.norm();
-		this.w[0]+=i;
-		return this;
-	},
-/* this-=y */
-	sub: function(y)
-	{
-		for (var i=0;i<ROM.NLEN;i++) this.w[i]-=y.w[i];
-		return this;
-	},
-
-/* reverse subtract this=x-this */
-	rsub: function(x)
-	{
-		for (var i=0;i<ROM.NLEN;i++)
-			this.w[i]=x.w[i]-this.w[i];
-		return this;
-	},
-/* this-=i, where i is int */
-	dec: function(i)
-	{
-		this.norm();
-		this.w[0]-=i;
-		return this;
-	},
-/* return this-x */
-	minus: function(x) {
-		var d=new BIG(0);
-		for (var i=0;i<ROM.NLEN;i++)
-			d.w[i]=this.w[i]-x.w[i];
-		return d;
-	},
-/* multiply by small integer */
-	imul: function(c)
-	{
-		for (var i=0;i<ROM.NLEN;i++) this.w[i]*=c;
-		return this;
-	},
-/* convert this BIG to byte array */
-	tobytearray: function(b,n)
-	{
-		this.norm();
-		var c=new BIG(0);
-		c.copy(this);
-
-		for (var i=ROM.MODBYTES-1;i>=0;i--)
-		{
-			b[i+n]=c.w[0]&0xff;
-			c.fshr(8);
-		}
-		return this;
-	},
-/* convert this to byte array */
-	toBytes: function(b)
-	{
-		this.tobytearray(b,0);
-	},
-
-/* set this[i]+=x*y+c, and return high part */
-	muladd: function(x,y,c,i)
-	{
-		var prod=x*y+c+this.w[i];
-		this.w[i]=prod&ROM.MASK;
-		return ((prod-this.w[i])*ROM.MODINV);
-	},
-/* multiply by larger int */
-	pmul: function(c)
-	{
-		var ak,carry=0;
-		this.norm();
-		for (var i=0;i<ROM.NLEN;i++)
-		{
-			ak=this.w[i];
-			this.w[i]=0;
-			carry=this.muladd(ak,c,carry,i);
-		}
-		return carry;
-	},
-/* multiply by still larger int - results requires a DBIG */
-	pxmul: function(c)
-	{
-		var m=new DBIG(0);
-		var carry=0;
-		for (var j=0;j<ROM.NLEN;j++)
-			carry=m.muladd(this.w[j],c,carry,j);
-		m.w[ROM.NLEN]=carry;
-		return m;
-	},
-/* divide by 4 */
-	div3: function()
-	{
-		var ak,base,carry=0;
-		this.norm();
-		base=(1<<ROM.BASEBITS);
-		for (var i=ROM.NLEN-1;i>=0;i--)
-		{
-			ak=(carry*base+this.w[i]);
-			this.w[i]=Math.floor(ak/3);
-			carry=ak%3;
-		}
-		return carry;
-	},
-
-/* set x = x mod 2^m */
-	mod2m: function(m)
-	{
-		var i,wd,bt;
-		var msk;
-		wd=Math.floor(m/ROM.BASEBITS);
-		bt=m%ROM.BASEBITS;
-		msk=(1<<bt)-1;
-		this.w[wd]&=msk;
-		for (i=wd+1;i<ROM.NLEN;i++) this.w[i]=0;
-	},
-
-/* a=1/a mod 2^256. This is very fast! */
-	invmod2m: function()
-	{
-		var U=new BIG(0);
-		var b=new BIG(0);
-		var c=new BIG(0);
-
-		U.inc(BIG.invmod256(this.lastbits(8)));
-
-		for (var i=8;i<256;i<<=1)
-		{
-			b.copy(this); b.mod2m(i);
-			var t1=BIG.smul(U,b); t1.shr(i);
-			c.copy(this); c.shr(i); c.mod2m(i);
-
-			var t2=BIG.smul(U,c); t2.mod2m(i);
-			t1.add(t2);
-			b=BIG.smul(t1,U); t1.copy(b);
-			t1.mod2m(i);
-
-			t2.one(); t2.shl(i); t1.rsub(t2); t1.norm();
-			t1.shl(i);
-			U.add(t1);
-		}
-		this.copy(U);
-	},
-
-/* reduce this mod m */
-	mod: function(m)
-	{
-		var k=0;
-
-		this.norm();
-		if (BIG.comp(this,m)<0) return;
-		do
-		{
-			m.fshl(1);
-			k++;
-		} while (BIG.comp(this,m)>=0);
-
-		while (k>0)
-		{
-			m.fshr(1);
-			if (BIG.comp(this,m)>=0)
-			{
-				this.sub(m);
-				this.norm();
-			}
-			k--;
-		}
-	},
-/* this/=m */
-	div: function(m)
-	{
-		var k=0;
-		this.norm();
-		var e=new BIG(1);
-		var b=new BIG(0);
-		b.copy(this);
-		this.zero();
-
-		while (BIG.comp(b,m)>=0)
-		{
-			e.fshl(1);
-			m.fshl(1);
-			k++;
-		}
-
-		while (k>0)
-		{
-			m.fshr(1);
-			e.fshr(1);
-			if (BIG.comp(b,m)>=0)
-			{
-				this.add(e);
-				this.norm();
-				b.sub(m);
-				b.norm();
-			}
-			k--;
-		}
-	},
-/* return parity of this */
-	parity: function()
-	{
-		return this.w[0]%2;
-	},
-/* return n-th bit of this */
-	bit: function(n)
-	{
-		if ((this.w[Math.floor(n/ROM.BASEBITS)]&(1<<(n%ROM.BASEBITS)))>0) return 1;
-		else return 0;
-	},
-/* return last n bits of this */
-	lastbits: function(n)
-	{
-		var msk=(1<<n)-1;
-		this.norm();
-		return (this.w[0])&msk;
-	},
-/* Jacobi Symbol (this/p). Returns 0, 1 or -1 */
-	jacobi: function(p)
-	{
-		var n8,k,m=0;
-		var t=new BIG(0);
-		var x=new BIG(0);
-		var n=new BIG(0);
-		var zilch=new BIG(0);
-		var one=new BIG(1);
-		if (p.parity()===0 || BIG.comp(this,zilch)===0 || BIG.comp(p,one)<=0) return 0;
-		this.norm();
-		x.copy(this);
-		n.copy(p);
-		x.mod(p);
-
-		while (BIG.comp(n,one)>0)
-		{
-			if (BIG.comp(x,zilch)===0) return 0;
-			n8=n.lastbits(3);
-			k=0;
-			while (x.parity()===0)
-			{
-				k++;
-				x.shr(1);
-			}
-			if (k%2==1) m+=(n8*n8-1)/8;
-			m+=(n8-1)*(x.lastbits(2)-1)/4;
-			t.copy(n);
-			t.mod(x);
-			n.copy(x);
-			x.copy(t);
-			m%=2;
-
-		}
-		if (m===0) return 1;
-		else return -1;
-	},
-/* this=1/this mod p. Binary method */
-	invmodp: function(p)
-	{
-		this.mod(p);
-		var u=new BIG(0);
-		u.copy(this);
-		var v=new BIG(0);
-		v.copy(p);
-		var x1=new BIG(1);
-		var x2=new BIG(0);
-		var t=new BIG(0);
-		var one=new BIG(1);
-
-		while (BIG.comp(u,one)!==0 && BIG.comp(v,one)!==0)
-		{
-			while (u.parity()===0)
-			{
-				u.shr(1);
-				if (x1.parity()!==0)
-				{
-					x1.add(p);
-					x1.norm();
-				}
-				x1.shr(1);
-			}
-			while (v.parity()===0)
-			{
-				v.shr(1);
-				if (x2.parity()!==0)
-				{
-					x2.add(p);
-					x2.norm();
-				}
-				x2.shr(1);
-			}
-			if (BIG.comp(u,v)>=0)
-			{
-				u.sub(v);
-				u.norm();
-				if (BIG.comp(x1,x2)>=0) x1.sub(x2);
-				else
-				{
-					t.copy(p);
-					t.sub(x2);
-					x1.add(t);
-				}
-				x1.norm();
-			}
-			else
-			{
-				v.sub(u);
-				v.norm();
-				if (BIG.comp(x2,x1)>=0) x2.sub(x1);
-				else
-				{
-					t.copy(p);
-					t.sub(x1);
-					x2.add(t);
-				}
-				x2.norm();
-			}
-		}
-		if (BIG.comp(u,one)===0) this.copy(x1);
-		else this.copy(x2);
-	},
-/* return this^e mod m */
-	powmod:function(e,m)
-	{
-		var bt;
-		this.norm();
-		e.norm();
-		var a=new BIG(1);
-		var z=new BIG(0);
-		z.copy(e);
-		var s=new BIG(0);
-		s.copy(this);
-		var i=0;
-		while (true)
-		{
-			i++;
-			bt=z.parity();
-			z.fshr(1);
-			if (bt==1) a=BIG.modmul(a,s,m);
-//ROM.debug=false;
-			if (z.iszilch()) break;
-			s=BIG.modsqr(s,m);
-		}
-		return a;
-	}
-
-};
-/* convert from byte array to BIG */
-BIG.frombytearray=function(b,n)
-{
-	var m=new BIG(0);
-
-	for (var i=0;i<ROM.MODBYTES;i++)
-	{
-		m.fshl(8); m.w[0]+=b[i+n]&0xff;
-		//m.inc(b[i]&0xff);
-	}
-	return m;
-};
-
-BIG.fromBytes=function(b)
-{
-	return BIG.frombytearray(b,0);
-};
-
-/* return a*b where product fits a BIG */
-BIG.smul=function(a,b)
-{
-	var carry;
-	var c=new BIG(0);
-	for (var i=0;i<ROM.NLEN;i++)
-	{
-		carry=0;
-		for (var j=0;j<ROM.NLEN;j++)
-			if (i+j<ROM.NLEN) carry=c.muladd(a.w[i],b.w[j],carry,i+j);
-	}
-	return c;
-};
-/* Compare a and b, return 0 if a==b, -1 if a<b, +1 if a>b. Inputs must be normalised */
-BIG.comp=function(a,b)
-{
-	for (var i=ROM.NLEN-1;i>=0;i--)
-	{
-		if (a.w[i]==b.w[i]) continue;
-		if (a.w[i]>b.w[i]) return 1;
-		else  return -1;
-	}
-	return 0;
-};
-
-/* get 8*MODBYTES size random number */
-BIG.random=function(rng)
-{
-	var m=new BIG(0);
-	var i,b,j=0,r=0;
-
-/* generate random BIG */
-	for (i=0;i<8*ROM.MODBYTES;i++)
-	{
-		if (j===0) r=rng.getByte();
-		else r>>=1;
-
-		b=r&1;
-		m.shl(1); m.w[0]+=b;// m.inc(b);
-		j++; j&=7;
-	}
-	return m;
-};
-
-/* Create random BIG in portable way, one bit at a time */
-BIG.randomnum=function(q,rng)
-{
-	var d=new DBIG(0);
-	var i,b,j=0,r=0;
-	for (i=0;i<2*ROM.MODBITS;i++)
-	{
-		if (j===0) r=rng.getByte();
-		else r>>=1;
-
-		b=r&1;
-		d.shl(1); d.w[0]+=b;
-		j++; j&=7;
-	}
-
-	var m=d.mod(q);
-
-	return m;
-};
-
-/* return NAF value as +/- 1, 3 or 5. x and x3 should be normed.
-nbs is number of bits processed, and nzs is number of trailing 0s detected */
-BIG.nafbits=function(x,x3,i)
-{
-	var n=[];
-	var nb=x3.bit(i)-x.bit(i);
-	var j;
-	n[1]=1;
-	n[0]=0;
-	if (nb===0) {n[0]=0; return n;}
-	if (i===0) {n[0]=nb; return n;}
-	if (nb>0) n[0]=1;
-	else      n[0]=(-1);
-
-	for (j=i-1;j>0;j--)
-	{
-		n[1]++;
-		n[0]*=2;
-		nb=x3.bit(j)-x.bit(j);
-		if (nb>0) n[0]+=1;
-		if (nb<0) n[0]-=1;
-		if (n[0]>5 || n[0]<-5) break;
-	}
-
-	if (n[0]%2!==0 && j!==0)
-	{ /* backtrack */
-		if (nb>0) n[0]=(n[0]-1)/2;
-		if (nb<0) n[0]=(n[0]+1)/2;
-		n[1]--;
-	}
-	while (n[0]%2===0)
-	{ /* remove trailing zeros */
-		n[0]/=2;
-		n[2]++;
-		n[1]--;
-	}
-	return n;
-};
-
-/* return a*b as DBIG */
-BIG.mul=function(a,b)
-{
-	var n,c=new DBIG(0);
-	a.norm();
-	b.norm();
-
-	c.w[0]=a.w[0]*b.w[0];
-	c.w[1]=a.w[1]*b.w[0]+a.w[0]*b.w[1];
-	c.w[2]=a.w[2]*b.w[0]+a.w[1]*b.w[1]+a.w[0]*b.w[2];
-	c.w[3]=a.w[3]*b.w[0]+a.w[2]*b.w[1]+a.w[1]*b.w[2]+a.w[0]*b.w[3];
-	c.w[4]=a.w[4]*b.w[0]+a.w[3]*b.w[1]+a.w[2]*b.w[2]+a.w[1]*b.w[3]+a.w[0]*b.w[4];
-	c.w[5]=a.w[5]*b.w[0]+a.w[4]*b.w[1]+a.w[3]*b.w[2]+a.w[2]*b.w[3]+a.w[1]*b.w[4]+a.w[0]*b.w[5];
-	c.w[6]=a.w[6]*b.w[0]+a.w[5]*b.w[1]+a.w[4]*b.w[2]+a.w[3]*b.w[3]+a.w[2]*b.w[4]+a.w[1]*b.w[5]+a.w[0]*b.w[6];
-	c.w[7]=a.w[7]*b.w[0]+a.w[6]*b.w[1]+a.w[5]*b.w[2]+a.w[4]*b.w[3]+a.w[3]*b.w[4]+a.w[2]*b.w[5]+a.w[1]*b.w[6]+a.w[0]*b.w[7];
-	c.w[8]=a.w[8]*b.w[0]+a.w[7]*b.w[1]+a.w[6]*b.w[2]+a.w[5]*b.w[3]+a.w[4]*b.w[4]+a.w[3]*b.w[5]+a.w[2]*b.w[6]+a.w[1]*b.w[7]+a.w[0]*b.w[8];
-	c.w[9]=a.w[9]*b.w[0]+a.w[8]*b.w[1]+a.w[7]*b.w[2]+a.w[6]*b.w[3]+a.w[5]*b.w[4]+a.w[4]*b.w[5]+a.w[3]*b.w[6]+a.w[2]*b.w[7]+a.w[1]*b.w[8]+a.w[0]*b.w[9];
-	c.w[10]=a.w[10]*b.w[0]+a.w[9]*b.w[1]+a.w[8]*b.w[2]+a.w[7]*b.w[3]+a.w[6]*b.w[4]+a.w[5]*b.w[5]+a.w[4]*b.w[6]+a.w[3]*b.w[7]+a.w[2]*b.w[8]+a.w[1]*b.w[9]+a.w[0]*b.w[10];
-
-	c.w[11]=a.w[10]*b.w[1]+a.w[9]*b.w[2]+a.w[8]*b.w[3]+a.w[7]*b.w[4]+a.w[6]*b.w[5]+a.w[5]*b.w[6]+a.w[4]*b.w[7]+a.w[3]*b.w[8]+a.w[2]*b.w[9]+a.w[1]*b.w[10];
-	c.w[12]= a.w[10]*b.w[2]+a.w[9]*b.w[3]+a.w[8]*b.w[4]+a.w[7]*b.w[5]+a.w[6]*b.w[6]+a.w[5]*b.w[7]+a.w[4]*b.w[8]+a.w[3]*b.w[9]+a.w[2]*b.w[10];
-	c.w[13]= a.w[10]*b.w[3]+a.w[9]*b.w[4]+a.w[8]*b.w[5]+a.w[7]*b.w[6]+a.w[6]*b.w[7]+a.w[5]*b.w[8]+a.w[4]*b.w[9]+a.w[3]*b.w[10];
-	c.w[14]= a.w[10]*b.w[4]+a.w[9]*b.w[5]+a.w[8]*b.w[6]+a.w[7]*b.w[7]+a.w[6]*b.w[8]+a.w[5]*b.w[9]+a.w[4]*b.w[10];
-	c.w[15]= a.w[10]*b.w[5]+a.w[9]*b.w[6]+a.w[8]*b.w[7]+a.w[7]*b.w[8]+a.w[6]*b.w[9]+a.w[5]*b.w[10];
-	c.w[16]= a.w[10]*b.w[6]+a.w[9]*b.w[7]+a.w[8]*b.w[8]+a.w[7]*b.w[9]+a.w[6]*b.w[10];
-	c.w[17]= a.w[10]*b.w[7]+a.w[9]*b.w[8]+a.w[8]*b.w[9]+a.w[7]*b.w[10];
-	c.w[18]= a.w[10]*b.w[8]+a.w[9]*b.w[9]+a.w[8]*b.w[10];
-	c.w[19]= a.w[10]*b.w[9]+a.w[9]*b.w[10];
-	c.w[20]= a.w[10]*b.w[10];
-//	for (var j=9;j<ROM.NLEN;j++)
-//	{
-//		t=0; for (var i=0;i<=j;i++) t+=a.w[j-i]*b.w[i];
-//		c.w[j]=t;
-//	}
-//	for (var j=ROM.NLEN;j<ROM.DNLEN-2;j++)
-//	{
-//		t=0; for (var i=j-ROM.NLEN+1;i<ROM.NLEN;i++) t+=a.w[j-i]*b.w[i];
-//		c.w[j]=t;
-//	}
-//	t=a.w[ROM.NLEN-1]*b.w[ROM.NLEN-1];
-//	c.w[ROM.DNLEN-2]=t;
-	var co=0;
-	for (var i=0;i<ROM.DNLEN-1;i++)
-	{
-		n=c.w[i]+co;
-		c.w[i]=n&ROM.MASK;
-		co=(n-c.w[i])*ROM.MODINV;
-	}
-	c.w[ROM.DNLEN-1]=co;
-
-	return c;
-};
-
-/* return a^2 as DBIG */
-BIG.sqr=function(a)
-{
-	var n,c=new DBIG(0);
-	a.norm();
-
-	c.w[0]=a.w[0]*a.w[0];
-	c.w[1]=2*(a.w[1]*a.w[0]);
-	c.w[2]=2*(a.w[2]*a.w[0])+a.w[1]*a.w[1];
-	c.w[3]=2*(a.w[3]*a.w[0]+a.w[2]*a.w[1]);
-	c.w[4]=2*(a.w[4]*a.w[0]+a.w[3]*a.w[1])+a.w[2]*a.w[2];
-	c.w[5]=2*(a.w[5]*a.w[0]+a.w[4]*a.w[1]+a.w[3]*a.w[2]);
-	c.w[6]=2*(a.w[6]*a.w[0]+a.w[5]*a.w[1]+a.w[4]*a.w[2])+a.w[3]*a.w[3];
-	c.w[7]=2*(a.w[7]*a.w[0]+a.w[6]*a.w[1]+a.w[5]*a.w[2]+a.w[4]*a.w[3]);
-	c.w[8]=2*(a.w[8]*a.w[0]+a.w[7]*a.w[1]+a.w[6]*a.w[2]+a.w[5]*a.w[3])+a.w[4]*a.w[4];
-	c.w[9]=2*(a.w[9]*a.w[0]+a.w[8]*a.w[1]+a.w[7]*a.w[2]+a.w[6]*a.w[3]+a.w[5]*a.w[4]);
-	c.w[10]=2*(a.w[10]*a.w[0]+a.w[9]*a.w[1]+a.w[8]*a.w[2]+a.w[7]*a.w[3]+a.w[6]*a.w[4])+a.w[5]*a.w[5];
-
-	c.w[11]=2*(a.w[10]*a.w[1]+a.w[9]*a.w[2]+a.w[8]*a.w[3]+a.w[7]*a.w[4]+a.w[6]*a.w[5]);
-	c.w[12]=2*(a.w[10]*a.w[2]+a.w[9]*a.w[3]+a.w[8]*a.w[4]+a.w[7]*a.w[5])+a.w[6]*a.w[6];
-	c.w[13]=2*(a.w[10]*a.w[3]+a.w[9]*a.w[4]+a.w[8]*a.w[5]+a.w[7]*a.w[6]);
-	c.w[14]=2*(a.w[10]*a.w[4]+a.w[9]*a.w[5]+a.w[8]*a.w[6])+a.w[7]*a.w[7];
-	c.w[15]=2*(a.w[10]*a.w[5]+a.w[9]*a.w[6]+a.w[8]*a.w[7]);
-	c.w[16]=2*(a.w[10]*a.w[6]+a.w[9]*a.w[7])+a.w[8]*a.w[8];
-	c.w[17]=2*(a.w[10]*a.w[7]+a.w[9]*a.w[8]);
-	c.w[18]=2*(a.w[10]*a.w[8])+a.w[9]*a.w[9];
-	c.w[19]=2*(a.w[10]*a.w[9]);
-	c.w[20]= a.w[10]*a.w[10];
-/*
-	c.w[0]=a.w[0]*a.w[0];
-	t=a.w[1]*a.w[0]; t+=t; c.w[1]=t;
-	for (j=2;j<ROM.NLEN-1;j+=2)
-	{
-		t=a.w[j]*a.w[0]; for (var i=1;i<(j+1)>>1;i++) t+=a.w[j-i]*a.w[i]; t+=t; t+=a.w[j>>1]*a.w[j>>1];
-		c.w[j]=t;
-		t=a.w[j+1]*a.w[0]; for (var i=1;i<(j+2)>>1;i++) t+=a.w[j+1-i]*a.w[i]; t+=t;
-		c.w[j+1]=t;
-	}
-	j=ROM.NLEN-1;
-	t=a.w[j]*a.w[0]; for (var i=1;i<(j+1)>>1;i++) t+=a.w[j-i]*a.w[i]; t+=t; t+=a.w[j>>1]*a.w[j>>1];
-	c.w[j]=t;
-
-	j=ROM.NLEN;
-	t=a.w[ROM.NLEN-1]*a.w[j-ROM.NLEN+1]; for (var i=j-ROM.NLEN+2;i<(j+1)>>1;i++) t+=a.w[j-i]*a.w[i]; t+=t;
-	c.w[j]=t;
-	for (j=ROM.NLEN+1;j<ROM.DNLEN-2;j+=2)
-	{
-		t=a.w[ROM.NLEN-1]*a.w[j-ROM.NLEN+1]; for (var i=j-ROM.NLEN+2;i<(j+1)>>1;i++) t+=a.w[j-i]*a.w[i]; t+=t; t+=a.w[j>>1]*a.w[j>>1];
-		c.w[j]=t;
-		t=a.w[ROM.NLEN-1]*a.w[j-ROM.NLEN+2]; for (var i=j-ROM.NLEN+3;i<(j+2)>>1;i++) t+=a.w[j+1-i]*a.w[i]; t+=t;
-		c.w[j+1]=t;
-	}
-
-	t=a.w[ROM.NLEN-1]*a.w[ROM.NLEN-1];
-	c.w[ROM.DNLEN-2]=t;
-*/
-	var co=0;
-	for (var i=0;i<ROM.DNLEN-1;i++)
-	{
-		n=c.w[i]+co;
-		c.w[i]=n&ROM.MASK;
-		co=(n-c.w[i])*ROM.MODINV;
-	}
-	c.w[ROM.DNLEN-1]=co;
-
-	return c;
-};
-
-/* reduce a DBIG to a BIG using a "special" modulus */
-BIG.mod=function(d)
-{
-	var i,j,b=new BIG(0);
-	if (ROM.MODTYPE==ROM.PSEUDO_MERSENNE)
-	{
-		var v,tw;
-		var t=d.split(ROM.MODBITS);
-		b.hcopy(d);
-
-		v=t.pmul(ROM.MConst);
-		tw=t.w[ROM.NLEN-1];
-		t.w[ROM.NLEN-1]&=ROM.TMASK;
-		t.inc(ROM.MConst*((tw>>ROM.TBITS)+(v<<(ROM.BASEBITS-ROM.TBITS))));
-		b.add(t);
-	}
-
-	if (ROM.MODTYPE==ROM.MONTGOMERY_FRIENDLY)
-	{
-		for (i=0;i<ROM.NLEN;i++)
-			d.w[ROM.NLEN+i]+=d.muladd(d.w[i],ROM.MConst-1,d.w[i],ROM.NLEN+i-1);
-		for (i=0;i<ROM.NLEN;i++)
-			b.w[i]=d.w[ROM.NLEN+i];
-	}
-
-	if (ROM.MODTYPE==ROM.NOT_SPECIAL)
-	{
-		var md=new BIG(0);
-		md.rcopy(ROM.Modulus);
-		var sum;
-
-		sum=d.w[0];
-		for (j=0;j<ROM.NLEN;j++)
-		{
-			for (i=0;i<j;i++) sum+=d.w[i]*md.w[j-i];
-			d.w[j]=((sum&ROM.MASK)*ROM.MConst)&ROM.MASK; sum+=d.w[j]*md.w[0];
-			sum=d.w[j+1]+(sum*ROM.MODINV);
-		}
-		for (j=ROM.NLEN;j<ROM.DNLEN-2;j++)
-		{
-			for (i=j-ROM.NLEN+1;i<ROM.NLEN;i++) sum+=d.w[i]*md.w[j-i];
-			d.w[j]=sum&ROM.MASK;
-			sum=d.w[j+1]+((sum-d.w[j])*ROM.MODINV);
-		}
-
-		sum+=d.w[ROM.NLEN-1]*md.w[ROM.NLEN-1];
-		d.w[ROM.DNLEN-2]=sum&ROM.MASK;
-		sum=d.w[ROM.DNLEN-1]+((sum-d.w[ROM.DNLEN-2])*ROM.MODINV);
-		d.w[ROM.DNLEN-1]=sum&ROM.MASK;
-
-		for (i=0;i<ROM.NLEN;i++)
-			b.w[i]=d.w[ROM.NLEN+i];
-	}
-	b.norm();
-	return b;
-};
-
-/* return a*b mod m */
-BIG.modmul=function(a,b,m)
-{
-	a.mod(m);
-	b.mod(m);
-	var d=BIG.mul(a,b);
-	return d.mod(m);
-};
-
-/* return a^2 mod m */
-BIG.modsqr=function(a,m)
-{
-	a.mod(m);
-	var d=BIG.sqr(a);
-	return d.mod(m);
-};
-
-/* return -a mod m */
-BIG.modneg=function(a,m)
-{
-	a.mod(m);
-	return m.minus(a);
-};
-
-/* calculate Field Excess */
-BIG.EXCESS=function(a)
-{
-	return ((a.w[ROM.NLEN-1]&ROM.OMASK)>>(ROM.MODBITS%ROM.BASEBITS));
-};
-
-/* Arazi and Qi inversion mod 256 */
-BIG.invmod256=function(a)
-{
-	var U,t1,t2,b,c;
-	t1=0;
-	c=(a>>1)&1;
-	t1+=c;
-	t1&=1;
-	t1=2-t1;
-	t1<<=1;
-	U=t1+1;
-
-// i=2
-	b=a&3;
-	t1=U*b; t1>>=2;
-	c=(a>>2)&3;
-	t2=(U*c)&3;
-	t1+=t2;
-	t1*=U; t1&=3;
-	t1=4-t1;
-	t1<<=2;
-	U+=t1;
-
-// i=4
-	b=a&15;
-	t1=U*b; t1>>=4;
-	c=(a>>4)&15;
-	t2=(U*c)&15;
-	t1+=t2;
-	t1*=U; t1&=15;
-	t1=16-t1;
-	t1<<=4;
-	U+=t1;
-
-	return U;
-};
-
diff --git a/js/DBIG.js b/js/DBIG.js
deleted file mode 100755
index 7523743..0000000
--- a/js/DBIG.js
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
-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.
-*/
-
-/* AMCL double length DBIG number class */
-
-/* constructor */
-var DBIG = function(x) {
-	this.w=[];
-	this.zero();
-	this.w[0]=x;
-};
-
-DBIG.prototype={
-
-/* set this=0 */
-	zero: function()
-	{
-		for (var i=0;i<ROM.DNLEN;i++) this.w[i]=0;
-		return this;
-	},
-
-/* set this=b */
-	copy: function(b)
-	{
-		for (var i=0;i<ROM.DNLEN;i++) this.w[i]=b.w[i];
-		return this;
-	},
-
-
-/* copy from BIG */
-	hcopy: function(b)
-	{
-		var i;
-		for (i=0;i<ROM.NLEN;i++) this.w[i]=b.w[i];
-		for (i=ROM.NLEN;i<ROM.DNLEN;i++) this.w[i]=0;
-		return this;
-	},
-
-/* normalise this */
-	norm: function()
-	{
-		var d,carry=0;
-		for (var i=0;i<ROM.DNLEN-1;i++)
-		{
-			d=this.w[i]+carry;
-			this.w[i]=d&ROM.MASK;
-			carry=d>>ROM.BASEBITS;
-		}
-		this.w[ROM.DNLEN-1]=(this.w[ROM.DNLEN-1]+carry);
-		return this;
-	},
-
-/* set this[i]+=x*y+c, and return high part */
-	muladd: function(x,y,c,i)
-	{
-		var prod=x*y+c+this.w[i];
-		this.w[i]=prod&ROM.MASK;
-		return ((prod-this.w[i])*ROM.MODINV);
-	},
-
-/* shift this right by k bits */
-	shr: function(k)
-	{
-		var i,n=k%ROM.BASEBITS;
-		var m=Math.floor(k/ROM.BASEBITS);
-		for (i=0;i<ROM.DNLEN-m-1;i++)
-			this.w[i]=(this.w[m+i]>>n)|((this.w[m+i+1]<<(ROM.BASEBITS-n))&ROM.MASK);
-		this.w[ROM.DNLEN-m-1]=this.w[ROM.DNLEN-1]>>n;
-		for (i=ROM.DNLEN-m;i<ROM.DNLEN;i++) this.w[i]=0;
-		return this;
-	},
-
-/* shift this left by k bits */
-	shl: function(k)
-	{
-		var i,n=k%ROM.BASEBITS;
-		var m=Math.floor(k/ROM.BASEBITS);
-
-		this.w[ROM.DNLEN-1]=((this.w[ROM.DNLEN-1-m]<<n))|(this.w[ROM.DNLEN-m-2]>>(ROM.BASEBITS-n));
-		for (i=ROM.DNLEN-2;i>m;i--)
-			this.w[i]=((this.w[i-m]<<n)&ROM.MASK)|(this.w[i-m-1]>>(ROM.BASEBITS-n));
-		this.w[m]=(this.w[0]<<n)&ROM.MASK;
-		for (i=0;i<m;i++) this.w[i]=0;
-		return this;
-	},
-
-/* this+=x */
-	add: function(x)
-	{
-		for (var i=0;i<ROM.DNLEN;i++)
-			this.w[i]+=x.w[i];
-	},
-
-/* this-=x */
-	sub: function(x)
-	{
-		for (var i=0;i<ROM.DNLEN;i++)
-			this.w[i]-=x.w[i];
-	},
-
-/* return number of bits in this */
-	nbits: function()
-	{
-		var bts,k=ROM.DNLEN-1;
-		var c;
-		this.norm();
-		while (k>=0 && this.w[k]===0) k--;
-		if (k<0) return 0;
-		bts=ROM.BASEBITS*k;
-		c=this.w[k];
-		while (c!==0) {c=Math.floor(c/2); bts++;}
-		return bts;
-	},
-
-/* convert this to string */
-	toString: function()
-	{
-
-		var b;
-		var s="";
-		var len=this.nbits();
-		if (len%4===0) len=Math.floor(len/4);
-		else {len=Math.floor(len/4); len++;}
-
-		for (var i=len-1;i>=0;i--)
-		{
-			b=new DBIG(0);
-			b.copy(this);
-			b.shr(i*4);
-			s+=(b.w[0]&15).toString(16);
-		}
-		return s;
-	},
-
-/* reduces this DBIG mod a BIG, and returns the BIG */
-	mod: function(c)
-	{
-		var k=0;
-		this.norm();
-		var m=new DBIG(0);
-		m.hcopy(c);
-		var r=new BIG(0);
-		r.hcopy(this);
-
-		if (DBIG.comp(this,m)<0) return r;
-
-		do
-		{
-			m.shl(1);
-			k++;
-		}
-		while (DBIG.comp(this,m)>=0);
-
-		while (k>0)
-		{
-			m.shr(1);
-			if (DBIG.comp(this,m)>=0)
-			{
-				this.sub(m);
-				this.norm();
-			}
-			k--;
-		}
-
-		r.hcopy(this);
-		return r;
-	},
-
-/* this/=c */
-	div: function(c)
-	{
-		var k=0;
-		var m=new DBIG(0); m.hcopy(c);
-		var a=new BIG(0);
-		var e=new BIG(1);
-		this.norm();
-
-		while (DBIG.comp(this,m)>=0)
-		{
-			e.fshl(1);
-			m.shl(1);
-			k++;
-		}
-
-		while (k>0)
-		{
-			m.shr(1);
-			e.shr(1);
-			if (DBIG.comp(this,m)>0)
-			{
-				a.add(e);
-				a.norm();
-				this.sub(m);
-				this.norm();
-			}
-			k--;
-		}
-		return a;
-	},
-
-/* split this DBIG at position n, return higher half, keep lower half */
-	split: function(n)
-	{
-		var t=new BIG(0);
-		var nw,m=n%ROM.BASEBITS;
-		var carry=this.w[ROM.DNLEN-1]<<(ROM.BASEBITS-m);
-
-
-		for (var i=ROM.DNLEN-2;i>=ROM.NLEN-1;i--)
-		{
-			nw=(this.w[i]>>m)|carry;
-			carry=(this.w[i]<<(ROM.BASEBITS-m))&ROM.MASK;
-			t.w[i-ROM.NLEN+1]=nw;
-		}
-		this.w[ROM.NLEN-1]&=((1<<m)-1);
-
-		return t;
-	}
-
-};
-
-/* Compare a and b, return 0 if a==b, -1 if a<b, +1 if a>b. Inputs must be normalised */
-DBIG.comp=function(a,b)
-{
-	for (var i=ROM.DNLEN-1;i>=0;i--)
-	{
-		if (a.w[i]==b.w[i]) continue;
-		if (a.w[i]>b.w[i]) return 1;
-		else  return -1;
-	}
-	return 0;
-};
diff --git a/js/ECDH.js b/js/ECDH.js
deleted file mode 100755
index 35b1479..0000000
--- a/js/ECDH.js
+++ /dev/null
@@ -1,537 +0,0 @@
-/*
-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.
-*/
-
-var ECDH = {
-
-	INVALID_PUBLIC_KEY:-2,
-	ERROR:-3,
-	INVALID:-4,
-	EFS:ROM.MODBYTES,
-	EGS:ROM.MODBYTES,
-	EAS:16,
-	EBS:16,
-
-	/* Convert Integer to n-byte array */
-	inttobytes: function(n,len)
-	{
-		var i;
-		var b=[];
-
-		for (i=0;i<len;i++) b[i]=0;
-		i=len;
-		while (n>0 && i>0)
-		{
-			i--;
-			b[i]=(n&0xff);
-			n=Math.floor(n/256);
-		}
-		return b;
-	},
-
-	bytestostring: function(b)
-	{
-		var s="";
-		var len=b.length;
-		var ch;
-
-		for (var i=0;i<len;i++)
-		{
-			ch=b[i];
-			s+=((ch>>>4)&15).toString(16);
-			s+=(ch&15).toString(16);
-
-		}
-		return s;
-	},
-
-	stringtobytes: function(s)
-	{
-		var b=[];
-		for (var i=0;i<s.length;i++)
-			b.push(s.charCodeAt(i));
-		return b;
-	},
-
-
-	KDF1: function(Z,olen)
-	{
-/* NOTE: the parameter olen is the length of the output K in bytes */
-		var H=new HASH();
-		var i,hlen=32;
-		var K=[];
-
-		var B=[];
-		var counter,cthreshold,k=0;
-
-		for (i=0;i<K.length;i++) K[i]=0;  // redundant?
-
-		cthreshold=Math.floor(olen/hlen); if (olen%hlen!==0) cthreshold++;
-
-		for (counter=0;counter<cthreshold;counter++)
-		{
-			H.process_array(Z); if (counter>0) H.process_num(counter);
-			B=H.hash();
-			if (k+hlen>olen) for (i=0;i<olen%hlen;i++) K[k++]=B[i];
-			else for (i=0;i<hlen;i++) K[k++]=B[i];
-		}
-		return K;
-	},
-
-	KDF2: function(Z,P,olen)
-	{
-/* NOTE: the parameter olen is the length of the output k in bytes */
-		var H=new HASH();
-		var i,hlen=32;
-		var K=[];
-
-		var B=[];
-		var counter,cthreshold,k=0;
-
-		for (i=0;i<K.length;i++) K[i]=0;  // redundant?
-
-		cthreshold=Math.floor(olen/hlen); if (olen%hlen!==0) cthreshold++;
-
-		for (counter=1;counter<=cthreshold;counter++)
-		{
-			H.process_array(Z); H.process_num(counter); H.process_array(P);
-			B=H.hash();
-			if (k+hlen>olen) for (i=0;i<olen%hlen;i++) K[k++]=B[i];
-			else for (i=0;i<hlen;i++) K[k++]=B[i];
-		}
-		return K;
-	},
-
-/* Password based Key Derivation Function */
-/* Input password p, salt s, and repeat count */
-/* Output key of length olen */
-
-	PBKDF2: function(Pass,Salt,rep,olen)
-	{
-		var i,j,k,d,opt;
-		d=Math.floor(olen/32); if (olen%32!==0) d++;
-		var F=new Array(this.EFS);
-		var U=[];
-		var S=[];
-
-		var K=[];
-		opt=0;
-
-		for (i=1;i<=d;i++)
-		{
-			for (j=0;j<Salt.length;j++) S[j]=Salt[j];
-			var N=this.inttobytes(i,4);
-			for (j=0;j<4;j++) S[Salt.length+j]=N[j];
-			this.HMAC(S,Pass,F);
-			for (j=0;j<this.EFS;j++) U[j]=F[j];
-			for (j=2;j<=rep;j++)
-			{
-				this.HMAC(U,Pass,U);
-				for (k=0;k<this.EFS;k++) F[k]^=U[k];
-			}
-			for (j=0;j<this.EFS;j++) K[opt++]=F[j];
-		}
-		var key=[];
-		for (i=0;i<olen;i++) key[i]=K[i];
-		return key;
-	},
-
-	HMAC: function(M,K,tag)
-	{
-	/* Input is from an octet m        *
-	* olen is requested output length in bytes. k is the key  *
-	* The output is the calculated tag */
-		var i,b;
-		var B=[];
-		var K0=new Array(64);
-		var olen=tag.length;
-
-		b=K0.length;
-		if (olen<4 || olen>32) return 0;
-
-		for (i=0;i<b;i++) K0[i]=0;
-
-		var H=new HASH();
-
-		if (K.length > b)
-		{
-			H.process_array(K); B=H.hash();
-			for (i=0;i<32;i++) K0[i]=B[i];
-		}
-		else
-			for (i=0;i<K.length;i++) K0[i]=K[i];
-
-		for (i=0;i<b;i++) K0[i]^=0x36;
-		H.process_array(K0); H.process_array(M); B=H.hash();
-
-		for (i=0;i<b;i++) K0[i]^=0x6a;
-		H.process_array(K0); H.process_array(B); B=H.hash();
-
-		for (i=0;i<olen;i++) tag[i]=B[i];
-
-		return 1;
-	},
-
-/* AES encryption/decryption */
-
-	AES_CBC_IV0_ENCRYPT: function(K,M)
-	{ /* AES CBC encryption, with Null IV and key K */
-	/* Input is from an octet string M, output is to an octet string C */
-	/* Input is padded as necessary to make up a full final block */
-		var a=new AES();
-		var fin;
-		var i,j,ipt,opt;
-		var buff=[];
-		/*var clen=16+(Math.floor(M.length/16))*16;*/
-
-		var C=[];
-		var padlen;
-
-		a.init(ROM.CBC,K,null);
-
-		ipt=opt=0;
-		fin=false;
-		for(;;)
-		{
-			for (i=0;i<16;i++)
-			{
-				if (ipt<M.length) buff[i]=M[ipt++];
-				else {fin=true; break;}
-			}
-			if (fin) break;
-			a.encrypt(buff);
-			for (i=0;i<16;i++)
-				C[opt++]=buff[i];
-		}
-
-/* last block, filled up to i-th index */
-
-		padlen=16-i;
-		for (j=i;j<16;j++) buff[j]=padlen;
-		a.encrypt(buff);
-		for (i=0;i<16;i++)
-			C[opt++]=buff[i];
-		a.end();
-		return C;
-	},
-
-	AES_CBC_IV0_DECRYPT: function(K,C)
-	{ /* padding is removed */
-		var a=new AES();
-		var i,ipt,opt,ch;
-		var buff=[];
-		var MM=[];
-		var fin,bad;
-		var padlen;
-		ipt=opt=0;
-
-		a.init(ROM.CBC,K,null);
-
-		if (C.length===0) return [];
-		ch=C[ipt++];
-
-		fin=false;
-
-		for(;;)
-		{
-			for (i=0;i<16;i++)
-			{
-				buff[i]=ch;
-				if (ipt>=C.length) {fin=true; break;}
-				else ch=C[ipt++];
-			}
-			a.decrypt(buff);
-			if (fin) break;
-			for (i=0;i<16;i++)
-				MM[opt++]=buff[i];
-		}
-
-		a.end();
-		bad=false;
-		padlen=buff[15];
-		if (i!=15 || padlen<1 || padlen>16) bad=true;
-		if (padlen>=2 && padlen<=16)
-			for (i=16-padlen;i<16;i++) if (buff[i]!=padlen) bad=true;
-
-		if (!bad) for (i=0;i<16-padlen;i++)
-					MM[opt++]=buff[i];
-
-		var M=[];
-		if (bad) return M;
-
-		for (i=0;i<opt;i++) M[i]=MM[i];
-		return M;
-	},
-
-	KEY_PAIR_GENERATE: function(RNG,S,W)
-	{
-		var r,gx,gy,s;
-		var G,WP;
-		var res=0;
-		var T=[];
-		G=new ECP(0);
-
-		gx=new BIG(0); gx.rcopy(ROM.CURVE_Gx);
-
-		if (ROM.CURVETYPE!=ROM.MOMTGOMERY)
-		{
-			gy=new BIG(0); gy.rcopy(ROM.CURVE_Gy);
-			G.setxy(gx,gy);
-		}
-		else G.setx(gx);
-
-		r=new BIG(0); r.rcopy(ROM.CURVE_Order);
-
-		if (RNG===null)
-		{
-			s=BIG.fromBytes(S);
-		}
-		else
-		{
-			s=BIG.randomnum(r,RNG);
-
-			s.toBytes(T);
-			for (var i=0;i<this.EGS;i++) S[i]=T[i];
-		}
-
-		WP=G.mul(s);
-		WP.toBytes(W);
-
-		return res;
-	},
-
-	PUBLIC_KEY_VALIDATE: function(full,W)
-	{
-		var r;
-		var WP=ECP.fromBytes(W);
-		var res=0;
-
-		r=new BIG(0); r.rcopy(ROM.CURVE_Order);
-
-		if (WP.is_infinity()) res=this.INVALID_PUBLIC_KEY;
-
-		if (res===0 && full)
-		{
-			WP=WP.mul(r);
-			if (!WP.is_infinity()) res=this.INVALID_PUBLIC_KEY;
-		}
-		return res;
-	},
-
-	ECPSVDP_DH: function(S,WD,Z)
-	{
-		var r,s;
-		var W;
-		var res=0;
-		var T=[];
-
-		s=BIG.fromBytes(S);
-
-		W=ECP.fromBytes(WD);
-		if (W.is_infinity()) res=this.ERROR;
-
-		if (res===0)
-		{
-			r=new BIG(0); r.rcopy(ROM.CURVE_Order);
-			s.mod(r);
-			W=W.mul(s);
-			if (W.is_infinity()) res=this.ERROR;
-			else
-			{
-				W.getX().toBytes(T);
-				for (var i=0;i<this.EFS;i++) Z[i]=T[i];
-			}
-		}
-		return res;
-	},
-
-	ECPSP_DSA: function(RNG,S,F,C,D)
-	{
-		var T=[];
-		var i,gx,gy,r,s,f,c,d,u,vx;
-		var G,V;
-
-		var H=new HASH();
-		H.process_array(F);
-		var B=H.hash();
-
-		gx=new BIG(0); gx.rcopy(ROM.CURVE_Gx);
-		gy=new BIG(0); gy.rcopy(ROM.CURVE_Gy);
-
-		G=new ECP(0);
-		G.setxy(gx,gy);
-		r=new BIG(0); r.rcopy(ROM.CURVE_Order);
-
-		s=BIG.fromBytes(S);
-		f=BIG.fromBytes(B);
-
-		c=new BIG(0);
-		d=new BIG(0);
-		V=new ECP();
-
-		do {
-			u=BIG.randomnum(r,RNG);
-
-			V.copy(G);
-			V=V.mul(u);
-			vx=V.getX();
-			c.copy(vx);
-			c.mod(r);
-			if (c.iszilch()) continue;
-			u.invmodp(r);
-			d=BIG.modmul(s,c,r);
-			d.add(f);
-			d=BIG.modmul(u,d,r);
-		} while (d.iszilch());
-
-		c.toBytes(T);
-		for (i=0;i<this.EFS;i++) C[i]=T[i];
-		d.toBytes(T);
-		for (i=0;i<this.EFS;i++) D[i]=T[i];
-		return 0;
-	},
-
-	ECPVP_DSA: function(W,F,C,D)
-	{
-		var B=[];
-		var r,gx,gy,f,c,d,h2;
-		var res=0;
-		var G,WP,P;
-
-		var H=new HASH();
-		H.process_array(F);
-		B=H.hash();
-
-		gx=new BIG(0); gx.rcopy(ROM.CURVE_Gx);
-		gy=new BIG(0); gy.rcopy(ROM.CURVE_Gy);
-
-		G=new ECP(0);
-		G.setxy(gx,gy);
-		r=new BIG(0); r.rcopy(ROM.CURVE_Order);
-
-		c=BIG.fromBytes(C);
-		d=BIG.fromBytes(D);
-		f=BIG.fromBytes(B);
-
-		if (c.iszilch() || BIG.comp(c,r)>=0 || d.iszilch() || BIG.comp(d,r)>=0)
-            res=this.INVALID;
-
-		if (res===0)
-		{
-			d.invmodp(r);
-			f=BIG.modmul(f,d,r);
-			h2=BIG.modmul(c,d,r);
-
-			WP=ECP.fromBytes(W);
-			if (WP.is_infinity()) res=this.ERROR;
-			else
-			{
-				P=new ECP();
-				P.copy(WP);
-				P=P.mul2(h2,G,f);
-				if (P.is_infinity()) res=this.INVALID;
-				else
-				{
-					d=P.getX();
-					d.mod(r);
-					if (BIG.comp(d,c)!==0) res=this.INVALID;
-				}
-			}
-		}
-
-		return res;
-	},
-
-	ECIES_ENCRYPT: function(P1,P2,RNG,W,M,V,T)
-	{
-		var i;
-
-		var Z=[];
-		var VZ=[];
-		var K1=[];
-		var K2=[];
-		var U=[];
-		var C=[];
-
-		if (this.KEY_PAIR_GENERATE(RNG,U,V)!==0) return C;
-		if (this.ECPSVDP_DH(U,W,Z)!==0) return C;
-
-		for (i=0;i<2*this.EFS+1;i++) VZ[i]=V[i];
-		for (i=0;i<this.EFS;i++) VZ[2*this.EFS+1+i]=Z[i];
-
-
-		var K=this.KDF2(VZ,P1,EFS);
-
-		for (i=0;i<this.EAS;i++) {K1[i]=K[i]; K2[i]=K[this.EAS+i];}
-
-		C=this.AES_CBC_IV0_ENCRYPT(K1,M);
-
-		var L2=this.inttobytes(P2.length,8);
-
-		var AC=[];
-		for (i=0;i<C.length;i++) AC[i]=C[i];
-		for (i=0;i<P2.length;i++) AC[C.length+i]=P2[i];
-		for (i=0;i<8;i++) AC[C.length+P2.length+i]=L2[i];
-
-		this.HMAC(AC,K2,T);
-
-		return C;
-	},
-
-	ECIES_DECRYPT: function(P1,P2,V,C,T,U)
-	{
-
-		var i;
-
-		var Z=[];
-		var VZ=[];
-		var K1=[];
-		var K2=[];
-		var TAG=new Array(T.length);
-		var M=[];
-
-		if (this.ECPSVDP_DH(U,V,Z)!==0) return M;
-
-		for (i=0;i<2*this.EFS+1;i++) VZ[i]=V[i];
-		for (i=0;i<this.EFS;i++) VZ[2*this.EFS+1+i]=Z[i];
-
-		var K=this.KDF2(VZ,P1,this.EFS);
-
-		for (i=0;i<this.EAS;i++) {K1[i]=K[i]; K2[i]=K[this.EAS+i];}
-
-		M=this.AES_CBC_IV0_DECRYPT(K1,C);
-
-		if (M.length===0) return M;
-
-		var L2=this.inttobytes(P2.length,8);
-
-		var AC=[];
-
-		for (i=0;i<C.length;i++) AC[i]=C[i];
-		for (i=0;i<P2.length;i++) AC[C.length+i]=P2[i];
-		for (i=0;i<8;i++) AC[C.length+P2.length+i]=L2[i];
-
-		this.HMAC(AC,K2,TAG);
-
-		var same=true;
-		for (i=0;i<T.length;i++) if (T[i]!=TAG[i]) same=false;
-		if (!same) return [];
-
-		return M;
-	}
-};
diff --git a/js/ECP.js b/js/ECP.js
deleted file mode 100755
index e9625a5..0000000
--- a/js/ECP.js
+++ /dev/null
@@ -1,898 +0,0 @@
-/*
-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.
-*/
-
-/* Elliptic Curve Point class */
-
-/* Constructor */
-var ECP = function()
-{
-	this.x=new FP(0);
-	this.y=new FP(1);
-	this.z=new FP(1);
-	this.INF=true;
-};
-
-ECP.prototype={
-/* test this=O point-at-infinity */
-	is_infinity: function()
-	{
-		if (ROM.CURVETYPE==ROM.EDWARDS)
-		{
-			this.x.reduce(); this.y.reduce(); this.z.reduce();
-			return (this.x.iszilch() && this.y.equals(this.z));
-		}
-		else return this.INF;
-	},
-
-
-/* conditional swap of this and Q dependant on d */
-	cswap: function(Q,d)
-	{
-		this.x.cswap(Q.x,d);
-		if (ROM.CURVETYPE!=ROM.MONTGOMERY) this.y.cswap(Q.y,d);
-		this.z.cswap(Q.z,d);
-		if (ROM.CURVETYPE!=ROM.EDWARDS)
-		{
-			var bd=(d!==0)?true:false;
-			bd=bd&(this.INF^Q.INF);
-			this.INF^=bd;
-			Q.INF^=bd;
-		}
-	},
-
-/* conditional move of Q to P dependant on d */
-	cmove: function(Q,d)
-	{
-		this.x.cmove(Q.x,d);
-		if (ROM.CURVETYPE!=ROM.MONTGOMERY) this.y.cmove(Q.y,d);
-		this.z.cmove(Q.z,d);
-		if (ROM.CURVETYPE!=ROM.EDWARDS)
-		{
-			var bd=(d!==0)?true:false;
-			this.INF^=(this.INF^Q.INF)&bd;
-		}
-	},
-
-/* Constant time select from pre-computed table */
-	select: function(W,b)
-	{
-		var MP=new ECP();
-		var m=b>>31;
-		var babs=(b^m)-m;
-
-		babs=(babs-1)/2;
-
-		this.cmove(W[0],ECP.teq(babs,0));  // conditional move
-		this.cmove(W[1],ECP.teq(babs,1));
-		this.cmove(W[2],ECP.teq(babs,2));
-		this.cmove(W[3],ECP.teq(babs,3));
-		this.cmove(W[4],ECP.teq(babs,4));
-		this.cmove(W[5],ECP.teq(babs,5));
-		this.cmove(W[6],ECP.teq(babs,6));
-		this.cmove(W[7],ECP.teq(babs,7));
-
-		MP.copy(this);
-		MP.neg();
-		this.cmove(MP,(m&1));
-	},
-
-/* Test P == Q */
-
-	equals: function(Q)
-	{
-		if (this.is_infinity() && Q.is_infinity()) return true;
-		if (this.is_infinity() || Q.is_infinity()) return false;
-		if (ROM.CURVETYPE==ROM.WEIERSTRASS)
-		{
-			var zs2=new FP(0); zs2.copy(this.z); zs2.sqr();
-			var zo2=new FP(0); zo2.copy(Q.z); zo2.sqr();
-			var zs3=new FP(0); zs3.copy(zs2); zs3.mul(this.z);
-			var zo3=new FP(0); zo3.copy(zo2); zo3.mul(Q.z);
-			zs2.mul(Q.x);
-			zo2.mul(this.x);
-			if (!zs2.equals(zo2)) return false;
-			zs3.mul(Q.y);
-			zo3.mul(this.y);
-			if (!zs3.equals(zo3)) return false;
-		}
-		else
-		{
-			var a=new FP(0);
-			var b=new FP(0);
-			a.copy(this.x); a.mul(Q.z); a.reduce();
-			b.copy(Q.x); b.mul(this.z); b.reduce();
-			if (!a.equals(b)) return false;
-			if (ROM.CURVETYPE==ROM.EDWARDS)
-			{
-				a.copy(this.y); a.mul(Q.z); a.reduce();
-				b.copy(Q.y); b.mul(this.z); b.reduce();
-				if (!a.equals(b)) return false;
-			}
-		}
-		return true;
-	},
-/* copy this=P */
-	copy: function(P)
-	{
-		this.x.copy(P.x);
-		if (ROM.CURVETYPE!=ROM.MONTGOMERY) this.y.copy(P.y);
-		this.z.copy(P.z);
-		this.INF=P.INF;
-	},
-/* this=-this */
-	neg: function()
-	{
-		if (this.is_infinity()) return;
-		if (ROM.CURVETYPE==ROM.WEIERSTRASS)
-		{
-			this.y.neg(); this.y.norm();
-		}
-		if (ROM.CURVETYPE==ROM.EDWARDS)
-		{
-			this.x.neg(); this.x.norm();
-		}
-		return;
-	},
-/* set this=O */
-	inf: function()
-	{
-		this.INF=true;
-		this.x.zero();
-		this.y=new FP(1);
-		this.z=new FP(1);
-	},
-/* set this=(x,y) where x and y are BIGs */
-	setxy: function(ix,iy)
-	{
-		this.x=new FP(0); this.x.bcopy(ix);
-		this.y=new FP(0); this.y.bcopy(iy);
-		this.z=new FP(1);
-		var rhs=ECP.RHS(this.x);
-		if (ROM.CURVETYPE==ROM.MONTGOMERY)
-		{
-			if (rhs.jacobi()==1) this.INF=false;
-			else this.inf();
-		}
-		else
-		{
-			var y2=new FP(0); y2.copy(this.y);
-			y2.sqr();
-			if (y2.equals(rhs)) this.INF=false;
-			else this.inf();
-		}
-	},
-/* set this=x, where x is BIG, y is derived from sign s */
-	setxi: function(ix,s)
-	{
-		this.x=new FP(0); this.x.bcopy(ix);
-		var rhs=ECP.RHS(this.x);
-		this.z=new FP(1);
-		if (rhs.jacobi()==1)
-		{
-			var ny=rhs.sqrt();
-			if (ny.redc().parity()!=s) ny.neg();
-			this.y=ny;
-			this.INF=false;
-		}
-		else this.inf();
-	},
-/* set this=x, y calcuated from curve equation */
-	setx: function(ix)
-	{
-		this.x=new FP(0); this.x.bcopy(ix);
-		var rhs=ECP.RHS(this.x);
-		this.z=new FP(1);
-		if (rhs.jacobi()==1)
-		{
-			if (ROM.CURVETYPE!=ROM.MONTGOMERY) this.y=rhs.sqrt();
-			this.INF=false;
-		}
-		else this.INF=true;
-	},
-/* set this to affine - from (x,y,z) to (x,y) */
-	affine: function()
-	{
-		if (this.is_infinity()) return;
-		var one=new FP(1);
-		if (this.z.equals(one)) return;
-		this.z.inverse();
-		if (ROM.CURVETYPE==ROM.WEIERSTRASS)
-		{
-			var z2=new FP(0); z2.copy(this.z);
-			z2.sqr();
-			this.x.mul(z2); this.x.reduce();
-			this.y.mul(z2);
-			this.y.mul(this.z); this.y.reduce();
-			this.z=one;
-		}
-		if (ROM.CURVETYPE==ROM.EDWARDS)
-		{
-			this.x.mul(this.z); this.x.reduce();
-			this.y.mul(this.z); this.y.reduce();
-			this.z=one;
-		}
-		if (ROM.CURVETYPE==ROM.MONTGOMERY)
-		{
-			this.x.mul(this.z); this.x.reduce();
-			this.z=one;
-		}
-	},
-/* extract x as BIG */
-	getX: function()
-	{
-		this.affine();
-		return this.x.redc();
-	},
-/* extract y as BIG */
-	getY: function()
-	{
-		this.affine();
-		return this.y.redc();
-	},
-
-/* get sign of Y */
-	getS: function()
-	{
-		this.affine();
-		var y=this.getY();
-		return y.parity();
-	},
-/* extract x as FP */
-	getx: function()
-	{
-		return this.x;
-	},
-/* extract y as FP */
-	gety: function()
-	{
-		return this.y;
-	},
-/* extract z as FP */
-	getz: function()
-	{
-		return this.z;
-	},
-/* convert to byte array */
-	toBytes: function(b)
-	{
-		var i,t=[];
-		if (ROM.CURVETYPE!=ROM.MONTGOMERY) b[0]=0x04;
-		else b[0]=0x02;
-
-		this.affine();
-		this.x.redc().toBytes(t);
-		for (i=0;i<ROM.MODBYTES;i++) b[i+1]=t[i];
-		if (ROM.CURVETYPE!=ROM.MONTGOMERY)
-		{
-			this.y.redc().toBytes(t);
-			for (i=0;i<ROM.MODBYTES;i++) b[i+ROM.MODBYTES+1]=t[i];
-		}
-	},
-/* convert to hex string */
-	toString: function()
-	{
-		if (this.is_infinity()) return "infinity";
-		this.affine();
-		if (ROM.CURVETYPE==ROM.MONTGOMERY) return "("+this.x.redc().toString()+")";
-		else return "("+this.x.redc().toString()+","+this.y.redc().toString()+")";
-	},
-
-/* this+=this */
-	dbl: function()
-	{
-		if (ROM.CURVETYPE==ROM.WEIERSTRASS)
-		{
-			if (this.INF) return;
-			if (this.y.iszilch())
-			{
-				this.inf();
-				return;
-			}
-
-			var w1=new FP(0); w1.copy(this.x);
-			var w6=new FP(0); w6.copy(this.z);
-			var w2=new FP(0);
-			var w3=new FP(0); w3.copy(this.x);
-			var w8=new FP(0); w8.copy(this.x);
-
-			if (ROM.CURVE_A==-3)
-			{
-				w6.sqr();
-				w1.copy(w6);
-				w1.neg();
-				w3.add(w1);
-				w8.add(w6);
-				w3.mul(w8);
-				w8.copy(w3);
-				w8.imul(3);
-			}
-			else
-			{
-				w1.sqr();
-				w8.copy(w1);
-				w8.imul(3);
-			}
-
-			w2.copy(this.y); w2.sqr();
-			w3.copy(this.x); w3.mul(w2);
-			w3.imul(4);
-			w1.copy(w3); w1.neg();
-
-			this.x.copy(w8); this.x.sqr();
-			this.x.add(w1);
-			this.x.add(w1);
-			this.x.norm();
-
-			this.z.mul(this.y);
-			this.z.add(this.z);
-
-			w2.add(w2);
-			w2.sqr();
-			w2.add(w2);
-			w3.sub(this.x);
-			this.y.copy(w8); this.y.mul(w3);
-			this.y.sub(w2);
-			this.y.norm();
-			this.z.norm();
-		}
-		if (ROM.CURVETYPE==ROM.EDWARDS)
-		{
-			var C=new FP(0); C.copy(this.x);
-			var D=new FP(0); D.copy(this.y);
-			var H=new FP(0); H.copy(this.z);
-			var J=new FP(0);
-
-			this.x.mul(this.y); this.x.add(this.x);
-			C.sqr();
-			D.sqr();
-			if (ROM.CURVE_A==-1) C.neg();
-			this.y.copy(C); this.y.add(D);
-			H.sqr(); H.add(H);
-			this.z.copy(this.y);
-			J.copy(this.y); J.sub(H);
-			this.x.mul(J);
-			C.sub(D);
-			this.y.mul(C);
-			this.z.mul(J);
-
-			this.x.norm();
-			this.y.norm();
-			this.z.norm();
-		}
-		if (ROM.CURVETYPE==ROM.MONTGOMERY)
-		{
-			var A=new FP(0); A.copy(this.x);
-			var B=new FP(0); B.copy(this.x);
-			var AA=new FP(0);
-			var BB=new FP(0);
-			var C=new FP(0);
-
-			if (this.INF) return;
-
-			A.add(this.z);
-			AA.copy(A); AA.sqr();
-			B.sub(this.z);
-			BB.copy(B); BB.sqr();
-			C.copy(AA); C.sub(BB);
-
-			this.x.copy(AA); this.x.mul(BB);
-
-			A.copy(C); A.imul((ROM.CURVE_A+2)>>2);
-
-			BB.add(A);
-			this.z.copy(BB); this.z.mul(C);
-			this.x.norm();
-			this.z.norm();
-		}
-		return;
-	},
-
-/* this+=Q */
-	add: function(Q)
-	{
-		if (ROM.CURVETYPE==ROM.WEIERSTRASS)
-		{
-			if (this.INF)
-			{
-				this.copy(Q);
-				return;
-			}
-			if (Q.INF) return;
-
-			var aff=false;
-			var one=new FP(1);
-			if (Q.z.equals(one)) aff=true;
-
-			var A,C;
-			var B=new FP(this.z);
-			var D=new FP(this.z);
-			if (!aff)
-			{
-				A=new FP(Q.z);
-				C=new FP(Q.z);
-
-				A.sqr(); B.sqr();
-				C.mul(A); D.mul(B);
-
-				A.mul(this.x);
-				C.mul(this.y);
-			}
-			else
-			{
-				A=new FP(this.x);
-				C=new FP(this.y);
-
-				B.sqr();
-				D.mul(B);
-			}
-
-			B.mul(Q.x); B.sub(A);
-			D.mul(Q.y); D.sub(C);
-
-			if (B.iszilch())
-			{
-				if (D.iszilch())
-				{
-					this.dbl();
-					return;
-				}
-				else
-				{
-					this.INF=true;
-					return;
-				}
-			}
-
-			if (!aff) this.z.mul(Q.z);
-			this.z.mul(B);
-
-			var e=new FP(B); e.sqr();
-			B.mul(e);
-			A.mul(e);
-
-			e.copy(A);
-			e.add(A); e.add(B);
-			this.x.copy(D); this.x.sqr(); this.x.sub(e);
-
-			A.sub(this.x);
-			this.y.copy(A); this.y.mul(D);
-			C.mul(B); this.y.sub(C);
-
-			this.x.norm();
-			this.y.norm();
-			this.z.norm();
-
-		}
-		if (ROM.CURVETYPE==ROM.EDWARDS)
-		{
-			var b=new FP(0); b.rcopy(ROM.CURVE_B);
-			var A=new FP(0); A.copy(this.z);
-			var B=new FP(0);
-			var C=new FP(0); C.copy(this.x);
-			var D=new FP(0); D.copy(this.y);
-			var E=new FP(0);
-			var F=new FP(0);
-			var G=new FP(0);
-
-			A.mul(Q.z);
-			B.copy(A); B.sqr();
-			C.mul(Q.x);
-			D.mul(Q.y);
-
-			E.copy(C); E.mul(D); E.mul(b);
-			F.copy(B); F.sub(E);
-			G.copy(B); G.add(E);
-			C.add(D);
-
-			if (ROM.CURVE_A==1)
-			{
-				E.copy(D); D.sub(C);
-			}
-
-			B.copy(this.x); B.add(this.y);
-			D.copy(Q.x); D.add(Q.y);
-			B.mul(D);
-			B.sub(C);
-			B.mul(F);
-			this.x.copy(A); this.x.mul(B);
-
-			if (ROM.CURVE_A==1)
-			{
-				C.copy(E); C.mul(G);
-			}
-			if (ROM.CURVE_A==-1)
-			{
-				C.mul(G);
-			}
-			this.y.copy(A); this.y.mul(C);
-			this.z.copy(F); this.z.mul(G);
-			this.x.norm(); this.y.norm(); this.z.norm();
-		}
-		return;
-	},
-
-/* Differential Add for Montgomery curves. this+=Q where W is this-Q and is affine. */
-	dadd: function(Q,W)
-	{
-		var A=new FP(0); A.copy(this.x);
-		var B=new FP(0); B.copy(this.x);
-		var C=new FP(0); C.copy(Q.x);
-		var D=new FP(0); D.copy(Q.x);
-		var DA=new FP(0);
-		var CB=new FP(0);
-
-		A.add(this.z);
-		B.sub(this.z);
-
-		C.add(Q.z);
-		D.sub(Q.z);
-
-		DA.copy(D); DA.mul(A);
-		CB.copy(C); CB.mul(B);
-
-		A.copy(DA); A.add(CB); A.sqr();
-		B.copy(DA); B.sub(CB); B.sqr();
-
-		this.x.copy(A);
-		this.z.copy(W.x); this.z.mul(B);
-
-		if (this.z.iszilch()) this.inf();
-		else this.INF=false;
-
-		this.x.norm();
-	},
-
-/* this-=Q */
-	sub: function(Q) {
-		Q.neg();
-		this.add(Q);
-		Q.neg();
-	},
-
-/* constant time multiply by small integer of length bts - use ladder */
-	pinmul: function(e,bts) {
-		if (ROM.CURVETYPE==ROM.MONTGOMERY)
-			return this.mul(new BIG(e));
-		else
-		{
-			var nb,i,b;
-			var P=new ECP();
-			var R0=new ECP();
-			var R1=new ECP(); R1.copy(this);
-
-			for (i=bts-1;i>=0;i--)
-			{
-				b=(e>>i)&1;
-				P.copy(R1);
-				P.add(R0);
-				R0.cswap(R1,b);
-				R1.copy(P);
-				R0.dbl();
-				R0.cswap(R1,b);
-			}
-			P.copy(R0);
-			P.affine();
-			return P;
-		}
-	},
-
-/* return e.this - SPA immune, using Ladder */
-
-	mul: function(e)
-	{
-		if (e.iszilch() || this.is_infinity()) return new ECP();
-		var P=new ECP();
-		if (ROM.CURVETYPE==ROM.MONTGOMERY)
-		{ /* use ladder */
-			var nb,i,b;
-			var D=new ECP();
-			var R0=new ECP(); R0.copy(this);
-			var R1=new ECP(); R1.copy(this);
-			R1.dbl();
-			D.copy(this); D.affine();
-			nb=e.nbits();
-			for (i=nb-2;i>=0;i--)
-			{
-				b=e.bit(i);
-				P.copy(R1);
-				P.dadd(R0,D);
-
-				R0.cswap(R1,b);
-				R1.copy(P);
-				R0.dbl();
-				R0.cswap(R1,b);
-			}
-			P.copy(R0);
-		}
-		else
-		{
-// fixed size windows
-			var i,b,nb,m,s,ns;
-			var mt=new BIG();
-			var t=new BIG();
-			var Q=new ECP();
-			var C=new ECP();
-			var W=[];
-			var w=[];
-
-			this.affine();
-
-// precompute table
-			Q.copy(this);
-			Q.dbl();
-			W[0]=new ECP();
-			W[0].copy(this);
-
-			for (i=1;i<8;i++)
-			{
-				W[i]=new ECP();
-				W[i].copy(W[i-1]);
-				W[i].add(Q);
-			}
-
-// convert the table to affine
-			if (ROM.CURVETYPE==ROM.WEIERSTRASS)
-				ECP.multiaffine(8,W);
-
-// make exponent odd - add 2P if even, P if odd
-			t.copy(e);
-			s=t.parity();
-			t.inc(1); t.norm(); ns=t.parity(); mt.copy(t); mt.inc(1); mt.norm();
-			t.cmove(mt,s);
-			Q.cmove(this,ns);
-			C.copy(Q);
-
-			nb=1+Math.floor((t.nbits()+3)/4);
-
-// convert exponent to signed 4-bit window
-			for (i=0;i<nb;i++)
-			{
-				w[i]=(t.lastbits(5)-16);
-				t.dec(w[i]); t.norm();
-				t.fshr(4);
-			}
-			w[nb]=t.lastbits(5);
-
-			P.copy(W[Math.floor((w[nb]-1)/2)]);
-			for (i=nb-1;i>=0;i--)
-			{
-				Q.select(W,w[i]);
-				P.dbl();
-				P.dbl();
-				P.dbl();
-				P.dbl();
-				P.add(Q);
-			}
-			P.sub(C);
-		}
-		P.affine();
-		return P;
-	},
-
-/* Return e.this+f.Q */
-
-	mul2: function(e,Q,f) {
-		var te=new BIG();
-		var tf=new BIG();
-		var mt=new BIG();
-		var S=new ECP();
-		var T=new ECP();
-		var C=new ECP();
-		var W=[];
-		var w=[];
-		var i,s,ns,nb;
-		var a,b;
-
-		this.affine();
-		Q.affine();
-
-		te.copy(e);
-		tf.copy(f);
-
-// precompute table
-		W[1]=new ECP(); W[1].copy(this); W[1].sub(Q);
-		W[2]=new ECP(); W[2].copy(this); W[2].add(Q);
-		S.copy(Q); S.dbl();
-		W[0]=new ECP(); W[0].copy(W[1]); W[0].sub(S);
-		W[3]=new ECP(); W[3].copy(W[2]); W[3].add(S);
-		T.copy(this); T.dbl();
-		W[5]=new ECP(); W[5].copy(W[1]); W[5].add(T);
-		W[6]=new ECP(); W[6].copy(W[2]); W[6].add(T);
-		W[4]=new ECP(); W[4].copy(W[5]); W[4].sub(S);
-		W[7]=new ECP(); W[7].copy(W[6]); W[7].add(S);
-
-// convert the table to affine
-		if (ROM.CURVETYPE==ROM.WEIERSTRASS)
-			ECP.multiaffine(8,W);
-
-// if multiplier is odd, add 2, else add 1 to multiplier, and add 2P or P to correction
-
-		s=te.parity();
-		te.inc(1); te.norm(); ns=te.parity(); mt.copy(te); mt.inc(1); mt.norm();
-		te.cmove(mt,s);
-		T.cmove(this,ns);
-		C.copy(T);
-
-		s=tf.parity();
-		tf.inc(1); tf.norm(); ns=tf.parity(); mt.copy(tf); mt.inc(1); mt.norm();
-		tf.cmove(mt,s);
-		S.cmove(Q,ns);
-		C.add(S);
-
-		mt.copy(te); mt.add(tf); mt.norm();
-		nb=1+Math.floor((mt.nbits()+1)/2);
-
-// convert exponent to signed 2-bit window
-		for (i=0;i<nb;i++)
-		{
-			a=(te.lastbits(3)-4);
-			te.dec(a); te.norm();
-			te.fshr(2);
-			b=(tf.lastbits(3)-4);
-			tf.dec(b); tf.norm();
-			tf.fshr(2);
-			w[i]=(4*a+b);
-		}
-		w[nb]=(4*te.lastbits(3)+tf.lastbits(3));
-		S.copy(W[Math.floor((w[nb]-1)/2)]);
-
-		for (i=nb-1;i>=0;i--)
-		{
-			T.select(W,w[i]);
-			S.dbl();
-			S.dbl();
-			S.add(T);
-		}
-		S.sub(C); /* apply correction */
-		S.affine();
-		return S;
-	}
-
-};
-
-ECP.multiaffine=function(m,P)
-{
-	var i;
-	var t1=new FP(0);
-	var t2=new FP(0);
-	var work=[];
-
-	for (i=0;i<m;i++)
-		work[i]=new FP(0);
-
-	work[0].one();
-	work[1].copy(P[0].z);
-
-	for (i=2;i<m;i++)
-	{
-		work[i].copy(work[i-1]);
-		work[i].mul(P[i-1].z);
-	}
-
-	t1.copy(work[m-1]);
-	t1.mul(P[m-1].z);
-	t1.inverse();
-	t2.copy(P[m-1].z);
-	work[m-1].mul(t1);
-
-	for (i=m-2;;i--)
-	{
-		if (i==0)
-		{
-			work[0].copy(t1);
-			work[0].mul(t2);
-			break;
-		}
-		work[i].mul(t2);
-		work[i].mul(t1);
-		t2.mul(P[i].z);
-	}
-/* now work[] contains inverses of all Z coordinates */
-
-	for (i=0;i<m;i++)
-	{
-		P[i].z.one();
-		t1.copy(work[i]);
-		t1.sqr();
-		P[i].x.mul(t1);
-		t1.mul(work[i]);
-		P[i].y.mul(t1);
-	}
-};
-
-/* return 1 if b==c, no branching */
-ECP.teq=function(b,c)
-{
-	var x=b^c;
-	x-=1;  // if x=0, x now -1
-	return ((x>>31)&1);
-};
-
-/* convert from byte array to ECP */
-ECP.fromBytes= function(b)
-{
-	var i,t=[];
-	var P=new ECP();
-	var p=new BIG(0); p.rcopy(ROM.Modulus);
-
-	for (i=0;i<ROM.MODBYTES;i++) t[i]=b[i+1];
-	var px=BIG.fromBytes(t);
-	if (BIG.comp(px,p)>=0) return P;
-
-	if (b[0]==0x04)
-	{
-		for (i=0;i<ROM.MODBYTES;i++) t[i]=b[i+ROM.MODBYTES+1];
-		var py=BIG.fromBytes(t);
-		if (BIG.comp(py,p)>=0) return P;
-		P.setxy(px,py);
-		return P;
-	}
-	else
-	{
-		P.setx(px);
-		return P;
-	}
-};
-
-/* Calculate RHS of curve equation */
-ECP.RHS= function(x)
-{
-	x.norm();
-	var r=new FP(0); r.copy(x);
-	r.sqr();
-
-	if (ROM.CURVETYPE==ROM.WEIERSTRASS)
-	{ // x^3+Ax+B
-		var b=new FP(0); b.rcopy(ROM.CURVE_B);
-		r.mul(x);
-		if (ROM.CURVE_A==-3)
-		{
-			var cx=new FP(0); cx.copy(x);
-			cx.imul(3);
-			cx.neg(); cx.norm();
-			r.add(cx);
-		}
-		r.add(b);
-	}
-	if (ROM.CURVETYPE==ROM.EDWARDS)
-	{ // (Ax^2-1)/(Bx^2-1)
-		var b=new FP(0); b.rcopy(ROM.CURVE_B);
-
-		var one=new FP(1);
-		b.mul(r);
-		b.sub(one);
-		if (ROM.CURVE_A==-1) r.neg();
-		r.sub(one);
-
-		b.inverse();
-
-		r.mul(b);
-	}
-	if (ROM.CURVETYPE==ROM.MONTGOMERY)
-	{ // x^3+Ax^2+x
-		var x3=new FP(0);
-		x3.copy(r);
-		x3.mul(x);
-		r.imul(ROM.CURVE_A);
-		r.add(x3);
-		r.add(x);
-	}
-	r.reduce();
-	return r;
-};
diff --git a/js/ECP2.js b/js/ECP2.js
deleted file mode 100755
index 4c310ab..0000000
--- a/js/ECP2.js
+++ /dev/null
@@ -1,604 +0,0 @@
-/*
-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.
-*/
-
-/* AMCL Weierstrass elliptic curve functions over FP2 */
-
-/* Constructor, set this=O */
-var ECP2=function()
-{
-	this.x=new FP2(0);
-	this.y=new FP2(1);
-	this.z=new FP2(1);
-	this.INF=true;
-};
-
-ECP2.prototype={
-/* Test this=O? */
-	is_infinity: function()
-	{
-		return this.INF;
-	},
-/* copy this=P */
-	copy: function(P)
-	{
-		this.x.copy(P.x);
-		this.y.copy(P.y);
-		this.z.copy(P.z);
-		this.INF=P.INF;
-	},
-/* set this=O */
-	inf: function()
-	{
-		this.INF=true;
-		this.x.zero();
-		this.y.zero();
-		this.z.zero();
-	},
-
-/* conditional move of Q to P dependant on d */
-	cmove: function(Q,d)
-	{
-		this.x.cmove(Q.x,d);
-		this.y.cmove(Q.y,d);
-		this.z.cmove(Q.z,d);
-
-		var bd=(d!==0)?true:false;
-		this.INF^=(this.INF^Q.INF)&bd;
-	},
-
-/* Constant time select from pre-computed table */
-	select: function(W,b)
-	{
-		var MP=new ECP2();
-		var m=b>>31;
-		var babs=(b^m)-m;
-
-		babs=(babs-1)/2;
-
-		this.cmove(W[0],ECP2.teq(babs,0));  // conditional move
-		this.cmove(W[1],ECP2.teq(babs,1));
-		this.cmove(W[2],ECP2.teq(babs,2));
-		this.cmove(W[3],ECP2.teq(babs,3));
-		this.cmove(W[4],ECP2.teq(babs,4));
-		this.cmove(W[5],ECP2.teq(babs,5));
-		this.cmove(W[6],ECP2.teq(babs,6));
-		this.cmove(W[7],ECP2.teq(babs,7));
-
-		MP.copy(this);
-		MP.neg();
-		this.cmove(MP,(m&1));
-	},
-
-/* Test P == Q */
-
-	equals: function(Q) {
-		if (this.is_infinity() && Q.is_infinity()) return true;
-		if (this.is_infinity() || Q.is_infinity()) return false;
-
-		var zs2=new FP2(this.z); /*zs2.copy(this.z);*/ zs2.sqr();
-		var zo2=new FP2(Q.z); /*zo2.copy(Q.z);*/  zo2.sqr();
-		var zs3=new FP2(zs2); /*zs3.copy(zs2);*/ zs3.mul(this.z);
-		var zo3=new FP2(zo2); /*zo3.copy(zo2);*/  zo3.mul(Q.z);
-		zs2.mul(Q.x);
-		zo2.mul(this.x);
-		if (!zs2.equals(zo2)) return false;
-		zs3.mul(Q.y);
-		zo3.mul(this.y);
-		if (!zs3.equals(zo3)) return false;
-
-		return true;
-	},
-/* set this=-this */
-	neg: function()
-	{
-		if (this.is_infinity()) return;
-		this.y.neg(); this.y.norm();
-		return;
-	},
-/* convert this to affine, from (x,y,z) to (x,y) */
-	affine: function()
-	{
-		if (this.is_infinity()) return;
-		var one=new FP2(1);
-		if (this.z.equals(one)) return;
-		this.z.inverse();
-
-		var z2=new FP2(this.z); //z2.copy(this.z);
-		z2.sqr();
-		this.x.mul(z2); this.x.reduce();
-		this.y.mul(z2);
-		this.y.mul(this.z);  this.y.reduce();
-		this.z=one;
-	},
-/* extract affine x as FP2 */
-	getX: function()
-	{
-		this.affine();
-		return this.x;
-	},
-/* extract affine y as FP2 */
-	getY: function()
-	{
-		this.affine();
-		return this.y;
-	},
-/* extract projective x */
-	getx: function()
-	{
-		return this.x;
-	},
-/* extract projective y */
-	gety: function()
-	{
-		return this.y;
-	},
-/* extract projective z */
-	getz: function()
-	{
-		return this.z;
-	},
-/* convert this to byte array */
-	toBytes: function(b)
-	{
-		var i,t=[];
-		this.affine();
-		this.x.getA().toBytes(t);
-		for (i=0;i<ROM.MODBYTES;i++)
-			b[i]=t[i];
-		this.x.getB().toBytes(t);
-		for (i=0;i<ROM.MODBYTES;i++)
-			b[i+ROM.MODBYTES]=t[i];
-
-		this.y.getA().toBytes(t);
-		for (i=0;i<ROM.MODBYTES;i++)
-			b[i+2*ROM.MODBYTES]=t[i];
-		this.y.getB().toBytes(t);
-		for (i=0;i<ROM.MODBYTES;i++)
-			b[i+3*ROM.MODBYTES]=t[i];
-	},
-/* convert this to hex string */
-	toString: function()
-	{
-		if (this.is_infinity()) return "infinity";
-		this.affine();
-		return "("+this.x.toString()+","+this.y.toString()+")";
-	},
-/* set this=(x,y) */
-	setxy: function(ix,iy)
-	{
-		this.x.copy(ix);
-		this.y.copy(iy);
-		this.z.one();
-
-		var rhs=ECP2.RHS(this.x);
-
-		var y2=new FP2(this.y); //y2.copy(this.y);
-		y2.sqr();
-		if (y2.equals(rhs)) this.INF=false;
-		else this.inf();
-	},
-
-/* set this=(x,.) */
-	setx: function(ix)
-	{
-		this.x.copy(ix);
-		this.z.one();
-
-		var rhs=ECP2.RHS(this.x);
-
-		if (rhs.sqrt())
-		{
-			this.y.copy(rhs);
-			this.INF=false;
-		}
-		else this.inf();
-	},
-
-/* set this*=q, where q is Modulus, using Frobenius */
-	frob: function(X)
-	{
-		if (this.INF) return;
-		var X2=new FP2(X); //X2.copy(X);
-		X2.sqr();
-		this.x.conj();
-		this.y.conj();
-		this.z.conj();
-		this.z.reduce();
-		this.x.mul(X2);
-		this.y.mul(X2);
-		this.y.mul(X);
-	},
-/* this+=this */
-	dbl: function()
-	{
-		if (this.INF) return -1;
-		if (this.y.iszilch())
-		{
-			this.inf();
-			return -1;
-		}
-
-		var w1=new FP2(this.x); //w1.copy(this.x);
-		var w2=new FP2(0);
-		var w3=new FP2(this.x); //w3.copy(this.x);
-		var w8=new FP2(this.x); //w8.copy(this.x);
-
-		w1.sqr();
-		w8.copy(w1);
-		w8.imul(3);
-
-		w2.copy(this.y); w2.sqr();
-		w3.copy(this.x); w3.mul(w2);
-		w3.imul(4);
-		w1.copy(w3); w1.neg();
-
-
-		this.x.copy(w8); this.x.sqr();
-		this.x.add(w1);
-		this.x.add(w1);
-		this.x.norm();
-
-		this.z.mul(this.y);
-		this.z.add(this.z);
-
-		w2.add(w2);
-		w2.sqr();
-		w2.add(w2);
-		w3.sub(this.x);
-		this.y.copy(w8); this.y.mul(w3);
-		this.y.sub(w2);
-		this.y.norm();
-		this.z.norm();
-
-		return 1;
-	},
-/* this+=Q - return 0 for add, 1 for double, -1 for O */
-/* this+=Q */
-	add: function(Q)
-	{
-		if (this.INF)
-		{
-			this.copy(Q);
-			return -1;
-		}
-		if (Q.INF) return -1;
-
-		var aff=false;
-
-		if (Q.z.isunity()) aff=true;
-
-		var A,C;
-		var B=new FP2(this.z);
-		var D=new FP2(this.z);
-		if (!aff)
-		{
-			A=new FP2(Q.z);
-			C=new FP2(Q.z);
-
-			A.sqr(); B.sqr();
-			C.mul(A); D.mul(B);
-
-			A.mul(this.x);
-			C.mul(this.y);
-		}
-		else
-		{
-			A=new FP2(this.x);
-			C=new FP2(this.y);
-
-			B.sqr();
-			D.mul(B);
-		}
-
-		B.mul(Q.x); B.sub(A);
-		D.mul(Q.y); D.sub(C);
-
-		if (B.iszilch())
-		{
-			if (D.iszilch())
-			{
-				this.dbl();
-				return 1;
-			}
-			else
-			{
-				this.INF=true;
-				return -1;
-			}
-		}
-
-		if (!aff) this.z.mul(Q.z);
-		this.z.mul(B);
-
-		var e=new FP2(B); e.sqr();
-		B.mul(e);
-		A.mul(e);
-
-		e.copy(A);
-		e.add(A); e.add(B);
-		this.x.copy(D); this.x.sqr(); this.x.sub(e);
-
-		A.sub(this.x);
-		this.y.copy(A); this.y.mul(D);
-		C.mul(B); this.y.sub(C);
-
-		this.x.norm();
-		this.y.norm();
-		this.z.norm();
-		return 0;
-	},
-/* this-=Q */
-	sub: function(Q)
-	{
-		Q.neg();
-		var D=this.add(Q);
-		Q.neg();
-		return D;
-	},
-
-/* P*=e */
-	mul: function(e)
-	{
-/* fixed size windows */
-		var i,b,nb,m,s,ns;
-		var mt=new BIG();
-		var t=new BIG();
-		var C=new ECP2();
-		var P=new ECP2();
-		var Q=new ECP2();
-		var W=[];
-		var w=[];
-
-		if (this.is_infinity()) return new ECP2();
-
-		this.affine();
-
-// precompute table
-		Q.copy(this);
-		Q.dbl();
-		W[0]=new ECP2();
-		W[0].copy(this);
-
-		for (i=1;i<8;i++)
-		{
-			W[i]=new ECP2();
-			W[i].copy(W[i-1]);
-			W[i].add(Q);
-		}
-
-// convert the table to affine
-
-		ECP2.multiaffine(8,W);
-
-// make exponent odd - add 2P if even, P if odd
-		t.copy(e);
-		s=t.parity();
-		t.inc(1); t.norm(); ns=t.parity(); mt.copy(t); mt.inc(1); mt.norm();
-		t.cmove(mt,s);
-		Q.cmove(this,ns);
-		C.copy(Q);
-
-		nb=1+Math.floor((t.nbits()+3)/4);
-
-// convert exponent to signed 4-bit window
-		for (i=0;i<nb;i++)
-		{
-			w[i]=(t.lastbits(5)-16);
-			t.dec(w[i]); t.norm();
-			t.fshr(4);
-		}
-		w[nb]=t.lastbits(5);
-
-		P.copy(W[Math.floor((w[nb]-1)/2)]);
-		for (i=nb-1;i>=0;i--)
-		{
-			Q.select(W,w[i]);
-			P.dbl();
-			P.dbl();
-			P.dbl();
-			P.dbl();
-			P.add(Q);
-		}
-		P.sub(C);
-		P.affine();
-		return P;
-	}
-};
-
-/* convert from byte array to point */
-ECP2.fromBytes=function(b)
-{
-	var i,t=[];
-	var ra,rb;
-
-	for (i=0;i<ROM.MODBYTES;i++) t[i]=b[i];
-	ra=BIG.fromBytes(t);
-	for (i=0;i<ROM.MODBYTES;i++) t[i]=b[i+ROM.MODBYTES];
-	rb=BIG.fromBytes(t);
-
-	var rx=new FP2(ra,rb); //rx.bset(ra,rb);
-
-	for (i=0;i<ROM.MODBYTES;i++) t[i]=b[i+2*ROM.MODBYTES];
-	ra=BIG.fromBytes(t);
-	for (i=0;i<ROM.MODBYTES;i++) t[i]=b[i+3*ROM.MODBYTES];
-	rb=BIG.fromBytes(t);
-
-	var ry=new FP2(ra,rb); //ry.bset(ra,rb);
-
-	var P=new ECP2();
-	P.setxy(rx,ry);
-	return P;
-};
-
-/* Calculate RHS of curve equation x^3+B */
-ECP2.RHS=function(x)
-{
-	x.norm();
-	var r=new FP2(x); //r.copy(x);
-	r.sqr();
-
-	var c=new BIG(0); c.rcopy(ROM.CURVE_B);
-	var b=new FP2(c); //b.bseta(c);
-	b.div_ip();
-	r.mul(x);
-	r.add(b);
-
-	r.reduce();
-	return r;
-};
-
-/* normalises m-array of ECP2 points. Requires work vector of m FP2s */
-
-ECP2.multiaffine=function(m,P)
-{
-	var i;
-	var t1=new FP2(0);
-	var t2=new FP2(0);
-	var work=[];
-
-	work[0]=new FP2(1);
-	work[1]=new FP2(P[0].z);
-	for (i=2;i<m;i++)
-	{
-		work[i]=new FP2(work[i-1]);
-		work[i].mul(P[i-1].z);
-	}
-
-	t1.copy(work[m-1]); t1.mul(P[m-1].z);
-
-	t1.inverse();
-
-	t2.copy(P[m-1].z);
-	work[m-1].mul(t1);
-
-	for (i=m-2;;i--)
-	{
-		if (i==0)
-		{
-			work[0].copy(t1);
-			work[0].mul(t2);
-			break;
-		}
-		work[i].mul(t2);
-		work[i].mul(t1);
-		t2.mul(P[i].z);
-	}
-/* now work[] contains inverses of all Z coordinates */
-
-	for (i=0;i<m;i++)
-	{
-		P[i].z.one();
-		t1.copy(work[i]); t1.sqr();
-		P[i].x.mul(t1);
-		t1.mul(work[i]);
-		P[i].y.mul(t1);
-	}
-};
-
-/* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3 */
-ECP2.mul4=function(Q,u)
-{
-	var i,j,nb;
-	var a=[];
-	var T=new ECP2();
-	var C=new ECP2();
-	var P=new ECP2();
-	var W=[];
-	var mt=new BIG();
-	var t=[];
-	var w=[];
-
-	for (i=0;i<4;i++)
-	{
-		t[i]=new BIG(u[i]);
-		Q[i].affine();
-	}
-
-/* precompute table */
-
-	W[0]=new ECP2(); W[0].copy(Q[0]); W[0].sub(Q[1]);
-	W[1]=new ECP2(); W[1].copy(W[0]);
-	W[2]=new ECP2(); W[2].copy(W[0]);
-	W[3]=new ECP2(); W[3].copy(W[0]);
-	W[4]=new ECP2(); W[4].copy(Q[0]); W[4].add(Q[1]);
-	W[5]=new ECP2(); W[5].copy(W[4]);
-	W[6]=new ECP2(); W[6].copy(W[4]);
-	W[7]=new ECP2(); W[7].copy(W[4]);
-	T.copy(Q[2]); T.sub(Q[3]);
-	W[1].sub(T);
-	W[2].add(T);
-	W[5].sub(T);
-	W[6].add(T);
-	T.copy(Q[2]); T.add(Q[3]);
-	W[0].sub(T);
-	W[3].add(T);
-	W[4].sub(T);
-	W[7].add(T);
-
-	ECP2.multiaffine(8,W);
-
-/* if multiplier is even add 1 to multiplier, and add P to correction */
-	mt.zero(); C.inf();
-	for (i=0;i<4;i++)
-	{
-		if (t[i].parity()==0)
-		{
-			t[i].inc(1); t[i].norm();
-			C.add(Q[i]);
-		}
-		mt.add(t[i]); mt.norm();
-	}
-
-	nb=1+mt.nbits();
-
-/* convert exponent to signed 1-bit window */
-	for (j=0;j<nb;j++)
-	{
-		for (i=0;i<4;i++)
-		{
-			a[i]=(t[i].lastbits(2)-2);
-			t[i].dec(a[i]); t[i].norm();
-			t[i].fshr(1);
-		}
-		w[j]=(8*a[0]+4*a[1]+2*a[2]+a[3]);
-	}
-	w[nb]=(8*t[0].lastbits(2)+4*t[1].lastbits(2)+2*t[2].lastbits(2)+t[3].lastbits(2));
-
-	P.copy(W[Math.floor((w[nb]-1)/2)]);
-
-	for (i=nb-1;i>=0;i--)
-	{
-		T.select(W,w[i]);
-		P.dbl();
-		P.add(T);
-	}
-	P.sub(C); /* apply correction */
-
-	P.affine();
-	return P;
-};
-
-/* return 1 if b==c, no branching */
-ECP2.teq=function(b,c)
-{
-	var x=b^c;
-	x-=1;  // if x=0, x now -1
-	return ((x>>31)&1);
-};
-
diff --git a/js/FF.js b/js/FF.js
deleted file mode 100755
index 5a1aba0..0000000
--- a/js/FF.js
+++ /dev/null
@@ -1,928 +0,0 @@
-/*
-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.
-*/
-
-/* AMCL FF number class */
-
-/* General purpose Constructor */
-var FF = function(n) {
-	this.v=new Array(n);
-	this.length=n;
-	for (var i=0;i<n;i++)
-		this.v[i]=new BIG(0);
-};
-
-FF.prototype={
-/* set to zero */
-
-	P_EXCESS: function()
-	{
-		return ((this.v[this.length-1].get(ROM.NLEN-1)&FF.P_OMASK)>>(FF.P_MB));
-	},
-
-	zero: function()
-	{
-		for (var i=0;i<this.length;i++) this.v[i].zero();
-		return this;
-	},
-
-	getlen: function()
-	{
-		return this.length;
-	},
-
-/* set to integer */
-	set: function(m)
-	{
-		this.zero();
-		this.v[0].set(0,(m&ROM.MASK));
-		this.v[0].set(1,(m>>ROM.BASEBITS));
-	},
-/* copy from FF b */
-	copy: function(b)
-	{
-		for (var i=0;i<this.length;i++)
-		{
-			this.v[i].copy(b.v[i]);
-		}
-	},
-/* copy from FF b */
-	rcopy: function(b)
-	{
-		for (var i=0;i<this.length;i++)
-		{
-			this.v[i].rcopy(b[i]);
-		}
-	},
-/* x=y<<n */
-	dsucopy: function(b)
-	{
-		for (var i=0;i<b.length;i++)
-		{
-			this.v[b.length+i].copy(b.v[i]);
-			this.v[i].zero();
-		}
-	},
-/* x=y */
-	dscopy: function(b)
-	{
-		for (var i=0;i<b.length;i++)
-		{
-			this.v[i].copy(b.v[i]);
-			this.v[b.length+i].zero();
-		}
-	},
-
-/* x=y>>n */
-	sducopy: function(b)
-	{
-		for (var i=0;i<this.length;i++)
-		{
-			this.v[i].copy(b.v[this.length+i]);
-		}
-	},
-	one: function()
-	{
-		this.v[0].one();
-		for (var i=1;i<this.length;i++)
-		{
-			this.v[i].zero();
-		}
-	},
-/* test equals 0 */
-	iszilch: function()
-	{
-		for (var i=0;i<this.length;i++)
-		{
-			if (!this.v[i].iszilch()) return false;
-		}
-		return true;
-	},
-/* shift right by 256-bit words */
-	shrw: function(n)
-	{
-		for (var i=0;i<n;i++)
-		{
-			this.v[i].copy(this.v[i+n]);
-			this.v[i+n].zero();
-		}
-	},
-
-/* shift left by 256-bit words */
-	shlw: function(n)
-	{
-		for (var i=0;i<n;i++)
-		{
-			this.v[n+i].copy(this.v[i]);
-			this.v[i].zero();
-		}
-	},
-/* extract last bit */
-	parity: function()
-	{
-		return this.v[0].parity();
-	},
-
-	lastbits: function(m)
-	{
-		return this.v[0].lastbits(m);
-	},
-
-
-/* recursive add */
-	radd: function(vp,x,xp,y,yp,n)
-	{
-		for (var i=0;i<n;i++)
-		{
-			this.v[vp+i].copy(x.v[xp+i]);
-			this.v[vp+i].add(y.v[yp+i]);
-		}
-	},
-
-/* recursive inc */
-	rinc: function(vp,y,yp,n)
-	{
-		for (var i=0;i<n;i++)
-		{
-			this.v[vp+i].add(y.v[yp+i]);
-		}
-	},
-
-/* recursive sub */
-	rsub: function(vp,x,xp,y,yp,n)
-	{
-		for (var i=0;i<n;i++)
-		{
-			this.v[vp+i].copy(x.v[xp+i]);
-			this.v[vp+i].sub(y.v[yp+i]);
-		}
-	},
-
-/* recursive dec */
-	rdec: function(vp,y,yp,n)
-	{
-		for (var i=0;i<n;i++)
-		{
-			this.v[vp+i].sub(y.v[yp+i]);
-		}
-	},
-
-/* simple add */
-	add: function(b)
-	{
-		for (var i=0;i<this.length;i++)
-			this.v[i].add(b.v[i]);
-	},
-
-/* simple sub */
-	sub: function(b)
-	{
-		for (var i=0;i<this.length;i++)
-			this.v[i].sub(b.v[i]);
-	},
-
-/* reverse sub */
-	revsub: function(b)
-	{
-		for (var i=0;i<this.length;i++)
-			this.v[i].rsub(b.v[i]);
-	},
-
-/* increment/decrement by a small integer */
-	inc: function(m)
-	{
-		this.v[0].inc(m);
-		this.norm();
-	},
-
-	dec: function(m)
-	{
-		this.v[0].dec(m);
-		this.norm();
-	},
-
-	/* normalise - but hold any overflow in top part unless n<0 */
-	rnorm: function(vp,n)
-	{
-		var trunc=false;
-		var i,carry;
-		if (n<0)
-		{ /* -v n signals to do truncation */
-			n=-n;
-			trunc=true;
-		}
-		for (i=0;i<n-1;i++)
-		{
-			carry=this.v[vp+i].norm();
-			this.v[vp+i].xortop(carry<<FF.P_TBITS);
-			this.v[vp+i+1].inc(carry);
-		}
-		carry=this.v[vp+n-1].norm();
-		if (trunc)
-			this.v[vp+n-1].xortop(carry<<FF.P_TBITS);
-		return this;
-	},
-	norm: function()
-	{
-		this.rnorm(0,this.length);
-	},
-
-/* shift left by one bit */
-	shl: function()
-	{
-		var i,carry,delay_carry=0;
-		for (i=0;i<this.length-1;i++)
-		{
-			carry=this.v[i].fshl(1);
-			this.v[i].inc(delay_carry);
-			this.v[i].xortop(carry<<FF.P_TBITS);
-			delay_carry=carry;
-		}
-		this.v[this.length-1].fshl(1);
-		this.v[this.length-1].inc(delay_carry);
-	},
-
-/* shift right by one bit */
-	shr: function()
-	{
-		var i,carry;
-		for (i=this.length-1;i>0;i--)
-		{
-			carry=this.v[i].fshr(1);
-			this.v[i-1].ortop(carry<<FF.P_TBITS);
-		}
-		this.v[0].fshr(1);
-	},
-
-/* Convert to Hex String */
-	toString: function()
-	{
-		this.norm();
-		var s="";
-
-		for (var i=this.length-1;i>=0;i--)
-		{
-			s+=this.v[i].toString();
-		}
-		return s;
-	},
-/* Convert FFs to/from byte arrays */
-	toBytes: function(b)
-	{
-		for (var i=0;i<this.length;i++)
-		{
-			this.v[i].tobytearray(b,(this.length-i-1)*ROM.MODBYTES);
-		}
-	},
-
-/* z=x*y, t is workspace */
-	karmul: function(vp,x,xp,y,yp,t,tp,n)
-	{
-		var nd2;
-		if (n==1)
-		{
-			var d=BIG.mul(x.v[xp],y.v[yp]);
-			this.v[vp+1]=d.split(8*ROM.MODBYTES);
-			this.v[vp].copy(d);
-			return;
-		}
-		nd2=n/2;
-		this.radd(vp,x,xp,x,xp+nd2,nd2);
-		this.radd(vp+nd2,y,yp,y,yp+nd2,nd2);
-		t.karmul(tp,this,vp,this,vp+nd2,t,tp+n,nd2);
-		this.karmul(vp,x,xp,y,yp,t,tp+n,nd2);
-		this.karmul(vp+n,x,xp+nd2,y,yp+nd2,t,tp+n,nd2);
-		t.rdec(tp,this,vp,n);
-		t.rdec(tp,this,vp+n,n);
-		this.rinc(vp+nd2,t,tp,n);
-		this.rnorm(vp,2*n);
-	},
-
-	karsqr: function(vp,x,xp,t,tp,n)
-	{
-		var nd2;
-		if (n==1)
-		{
-			var d=BIG.sqr(x.v[xp]);
-			this.v[vp+1].copy(d.split(8*ROM.MODBYTES));
-			this.v[vp].copy(d);
-			return;
-		}
-
-		nd2=n/2;
-		this.karsqr(vp,x,xp,t,tp+n,nd2);
-		this.karsqr(vp+n,x,xp+nd2,t,tp+n,nd2);
-		t.karmul(tp,x,xp,x,xp+nd2,t,tp+n,nd2);
-		this.rinc(vp+nd2,t,tp,n);
-		this.rinc(vp+nd2,t,tp,n);
-		this.rnorm(vp+nd2,n);
-	},
-
-	karmul_lower: function(vp,x,xp,y,yp,t,tp,n)
-	{ /* Calculates Least Significant bottom half of x*y */
-		var nd2;
-		if (n==1)
-		{ /* only calculate bottom half of product */
-			this.v[vp].copy(BIG.smul(x.v[xp],y.v[yp]));
-			return;
-		}
-		nd2=n/2;
-
-		this.karmul(vp,x,xp,y,yp,t,tp+n,nd2);
-		t.karmul_lower(tp,x,xp+nd2,y,yp,t,tp+n,nd2);
-		this.rinc(vp+nd2,t,tp,nd2);
-		t.karmul_lower(tp,x,xp,y,yp+nd2,t,tp+n,nd2);
-		this.rinc(vp+nd2,t,tp,nd2);
-		this.rnorm(vp+nd2,-nd2);  /* truncate it */
-	},
-
-	karmul_upper: function(x,y,t,n)
-	{ /* Calculates Most Significant upper half of x*y, given lower part */
-		var nd2;
-
-		nd2=n/2;
-		this.radd(n,x,0,x,nd2,nd2);
-		this.radd(n+nd2,y,0,y,nd2,nd2);
-
-		t.karmul(0,this,n+nd2,this,n,t,n,nd2);  /* t = (a0+a1)(b0+b1) */
-		this.karmul(n,x,nd2,y,nd2,t,n,nd2); /* z[n]= a1*b1 */
-									/* z[0-nd2]=l(a0b0) z[nd2-n]= h(a0b0)+l(t)-l(a0b0)-l(a1b1) */
-		t.rdec(0,this,n,n);              /* t=t-a1b1  */
-		this.rinc(nd2,this,0,nd2);   /* z[nd2-n]+=l(a0b0) = h(a0b0)+l(t)-l(a1b1)  */
-		this.rdec(nd2,t,0,nd2);   /* z[nd2-n]=h(a0b0)+l(t)-l(a1b1)-l(t-a1b1)=h(a0b0) */
-		this.rnorm(0,-n);					/* a0b0 now in z - truncate it */
-		t.rdec(0,this,0,n);         /* (a0+a1)(b0+b1) - a0b0 */
-		this.rinc(nd2,t,0,n);
-
-		this.rnorm(nd2,n);
-	},
-
-/* return low part of product this*y */
-	lmul: function(y)
-	{
-		var n=this.length;
-		var t=new FF(2*n);
-		var x=new FF(n); x.copy(this);
-		this.karmul_lower(0,x,0,y,0,t,0,n);
-	},
-
-/* Set b=b mod c */
-	mod: function(c)
-	{
-		var k=0;
-
-		this.norm();
-		if (FF.comp(this,c)<0)
-			return;
-		do
-		{
-			c.shl();
-			k++;
-		} while (FF.comp(this,c)>=0);
-
-		while (k>0)
-		{
-			c.shr();
-			if (FF.comp(this,c)>=0)
-			{
-				this.sub(c);
-				this.norm();
-			}
-			k--;
-		}
-	},
-
-/* return This mod modulus, N is modulus, ND is Montgomery Constant */
-	reduce: function(N,ND)
-	{ /* fast karatsuba Montgomery reduction */
-		var n=N.length;
-		var t=new FF(2*n);
-		var r=new FF(n);
-		var m=new FF(n);
-
-		r.sducopy(this);
-		m.karmul_lower(0,this,0,ND,0,t,0,n);
-		this.karmul_upper(N,m,t,n);
-		m.sducopy(this);
-
-		r.add(N);
-		r.sub(m);
-		r.norm();
-
-		return r;
-
-	},
-
-/* Set r=this mod b */
-/* this is of length - 2*n */
-/* r,b is of length - n */
-	dmod: function(b)
-	{
-		var k,n=b.length;
-		var m=new FF(2*n);
-		var x=new FF(2*n);
-		var r=new FF(n);
-
-		x.copy(this);
-		x.norm();
-		m.dsucopy(b); k=256*n;
-
-		while (k>0)
-		{
-			m.shr();
-
-			if (FF.comp(x,m)>=0)
-			{
-				x.sub(m);
-				x.norm();
-			}
-			k--;
-		}
-
-		r.copy(x);
-		r.mod(b);
-		return r;
-	},
-
-/* Set return=1/this mod p. Binary method - a<p on entry */
-	invmodp: function(p)
-	{
-		var n=p.length;
-
-		var u=new FF(n);
-		var v=new FF(n);
-		var x1=new FF(n);
-		var x2=new FF(n);
-		var t=new FF(n);
-		var one=new FF(n);
-
-		one.one();
-		u.copy(this);
-		v.copy(p);
-		x1.copy(one);
-		x2.zero();
-
-	// reduce n in here as well!
-		while (FF.comp(u,one)!==0 && FF.comp(v,one)!==0)
-		{
-			while (u.parity()===0)
-			{
-				u.shr();
-				if (x1.parity()!==0)
-				{
-					x1.add(p);
-					x1.norm();
-				}
-				x1.shr();
-			}
-			while (v.parity()===0)
-			{
-				v.shr();
-				if (x2.parity()!==0)
-				{
-					x2.add(p);
-					x2.norm();
-				}
-				x2.shr();
-			}
-			if (FF.comp(u,v)>=0)
-			{
-
-				u.sub(v);
-				u.norm();
-				if (FF.comp(x1,x2)>=0) x1.sub(x2);
-				else
-				{
-					t.copy(p);
-					t.sub(x2);
-					x1.add(t);
-				}
-				x1.norm();
-			}
-			else
-			{
-				v.sub(u);
-				v.norm();
-				if (FF.comp(x2,x1)>=0) x2.sub(x1);
-				else
-				{
-					t.copy(p);
-					t.sub(x1);
-					x2.add(t);
-				}
-				x2.norm();
-			}
-		}
-		if (FF.comp(u,one)===0)
-			this.copy(x1);
-		else
-			this.copy(x2);
-	},
-
-/* nresidue mod m */
-	nres: function(m)
-	{
-		var n=m.length;
-		var d=new FF(2*n);
-		d.dsucopy(this);
-		this.copy(d.dmod(m));
-	},
-
-	redc: function(m,ND)
-	{
-		var n=m.length;
-		var d=new FF(2*n);
-		this.mod(m);
-		d.dscopy(this);
-		this.copy(d.reduce(m,ND));
-		this.mod(m);
-	},
-
-	mod2m: function(m)
-	{
-		for (var i=m;i<this.length;i++)
-			this.v[i].zero();
-	},
-
-	/* U=1/a mod 2^m - Arazi & Qi */
-	invmod2m: function()
-	{
-		var i,n=this.length;
-
-		var b=new FF(n);
-		var c=new FF(n);
-		var U=new FF(n);
-
-		var t;
-
-		U.zero();
-		U.v[0].copy(this.v[0]);
-		U.v[0].invmod2m();
-
-		for (i=1;i<n;i<<=1)
-		{
-			b.copy(this); b.mod2m(i);
-			t=FF.mul(U,b); t.shrw(i); b.copy(t);
-			c.copy(this); c.shrw(i); c.mod2m(i);
-			c.lmul(U); c.mod2m(i);
-
-			b.add(c); b.norm();
-			b.lmul(U); b.mod2m(i);
-
-			c.one(); c.shlw(i); b.revsub(c); b.norm();
-			b.shlw(i);
-			U.add(b);
-		}
-		U.norm();
-		return U;
-	},
-
-	random: function(rng)
-	{
-		var n=this.length;
-		for (var i=0;i<n;i++)
-		{
-			this.v[i].copy(BIG.random(rng));
-		}
-	/* make sure top bit is 1 */
-		while (this.v[n-1].nbits()<ROM.MODBYTES*8) this.v[n-1].copy(BIG.random(rng));
-
-	},
-
-	/* generate random x */
-	randomnum: function(p,rng)
-	{
-		var n=this.length;
-		var d=new FF(2*n);
-
-		for (var i=0;i<2*n;i++)
-		{
-			d.v[i].copy(BIG.random(rng));
-		}
-		this.copy(d.dmod(p));
-	},
-
-	/* this*=y mod p */
-	modmul: function(y,p,nd)
-	{
-		var ex=this.P_EXCESS();
-		var ey=y.P_EXCESS();
-		if ((ex+1)*(ey+1)+1>=FF.P_FEXCESS) this.mod(p);
-		var d=FF.mul(this,y);
-		this.copy(d.reduce(p,nd));
-	},
-
-	/* this*=y mod p */
-	modsqr: function(p,nd)
-	{
-		var ex=this.P_EXCESS();
-		if ((ex+1)*(ex+1)+1>=FF.P_FEXCESS) this.mod(p);
-		var d=FF.sqr(this);
-		this.copy(d.reduce(p,nd));
-	},
-
-	/* this=this^e mod p using side-channel resistant Montgomery Ladder, for large e */
-	skpow: function(e,p)
-	{
-		var i,b,n=p.length;
-		var R0=new FF(n);
-		var R1=new FF(n);
-		var ND=p.invmod2m();
-
-		this.mod(p);
-		R0.one();
-		R1.copy(this);
-		R0.nres(p);
-		R1.nres(p);
-
-		for (i=8*ROM.MODBYTES*n-1;i>=0;i--)
-		{
-
-			b=e.v[Math.floor(i/256)].bit(i%256);
-
-			this.copy(R0);
-			this.modmul(R1,p,ND);
-
-			FF.cswap(R0,R1,b);
-			R0.modsqr(p,ND);
-
-			R1.copy(this);
-			FF.cswap(R0,R1,b);
-
-		}
-
-		this.copy(R0);
-		this.redc(p,ND);
-	},
-
-	/* this =this^e mod p using side-channel resistant Montgomery Ladder, for short e */
-	skspow: function(e,p)
-	{
-		var i,b,n=p.length;
-		var R0=new FF(n);
-		var R1=new FF(n);
-		var ND=p.invmod2m();
-
-		this.mod(p);
-		R0.one();
-		R1.copy(this);
-		R0.nres(p);
-		R1.nres(p);
-
-		for (i=8*ROM.MODBYTES-1;i>=0;i--)
-		{
-			b=e.bit(i);
-			this.copy(R0);
-			this.modmul(R1,p,ND);
-
-			FF.cswap(R0,R1,b);
-			R0.modsqr(p,ND);
-
-			R1.copy(this);
-			FF.cswap(R0,R1,b);
-		}
-		this.copy(R0);
-		this.redc(p,ND);
-	},
-
-	/* raise to an integer power - right-to-left method */
-	power: function(e,p)
-	{
-		var n=p.length;
-		var f=true;
-		var w=new FF(n);
-		var ND=p.invmod2m();
-
-		w.copy(this);
-		w.nres(p);
-
-		if (e==2)
-		{
-			this.copy(w);
-			this.modsqr(p,ND);
-		}
-		else for (; ; )
-		{
-			if (e%2==1)
-			{
-				if (f) this.copy(w);
-				else this.modmul(w,p,ND);
-				f=false;
-			}
-			e>>=1;
-			if (e===0) break;
-			w.modsqr(p,ND);
-		}
-		this.redc(p,ND);
-	},
-
-	/* this=this^e mod p, faster but not side channel resistant */
-	pow: function(e,p)
-	{
-		var i,b,n=p.length;
-		var w=new FF(n);
-		var ND=p.invmod2m();
-
-		w.copy(this);
-		this.one();
-		this.nres(p);
-		w.nres(p);
-		for (i=8*ROM.MODBYTES*n-1;i>=0;i--)
-		{
-			this.modsqr(p,ND);
-			b=e.v[Math.floor(i/256)].bit(i%256);
-			if (b==1) this.modmul(w,p,ND);
-		}
-		this.redc(p,ND);
-	},
-
-	/* double exponentiation r=x^e.y^f mod p */
-	pow2: function(e,y,f,p)
-	{
-		var i,eb,fb,n=p.length;
-		var xn=new FF(n);
-		var yn=new FF(n);
-		var xy=new FF(n);
-		var ND=p.invmod2m();
-
-		xn.copy(this);
-		yn.copy(y);
-		xn.nres(p);
-		yn.nres(p);
-		xy.copy(xn); xy.modmul(yn,p,ND);
-		this.one();
-		this.nres(p);
-
-		for (i=8*ROM.MODBYTES-1;i>=0;i--)
-		{
-			eb=e.bit(i);
-			fb=f.bit(i);
-			this.modsqr(p,ND);
-			if (eb==1)
-			{
-				if (fb==1) this.modmul(xy,p,ND);
-				else this.modmul(xn,p,ND);
-			}
-			else
-			{
-				if (fb==1) this.modmul(yn,p,ND);
-			}
-		}
-		this.redc(p,ND);
-	},
-
-	/* quick and dirty check for common factor with n */
-	cfactor: function(s)
-	{
-		var r,n=this.length;
-		var g;
-
-		var x=new FF(n);
-		var y=new FF(n);
-		y.set(s);
-
-		x.copy(this);
-		x.norm();
-
-		do
-		{
-			x.sub(y);
-			x.norm();
-			while (!x.iszilch() && x.parity()===0) x.shr();
-		}
-		while (FF.comp(x,y)>0);
-
-		g=x.v[0].get(0);
-		r=FF.igcd(s,g);
-		if (r>1) return true;
-		return false;
-	}
-
-
-};
-
-FF.P_MBITS=ROM.MODBYTES*8;
-FF.P_MB=(FF.P_MBITS%ROM.BASEBITS);
-FF.P_OMASK=((-1)<<(FF.P_MBITS%ROM.BASEBITS));
-FF.P_FEXCESS=(1<<(ROM.BASEBITS*ROM.NLEN-FF.P_MBITS));
-FF.P_TBITS=(FF.P_MBITS%ROM.BASEBITS);
-
-
-/* compare x and y - must be normalised, and of same length */
-FF.comp=function(a,b)
-{
-	var i,j;
-	for (i=a.length-1;i>=0;i--)
-	{
-		j=BIG.comp(a.v[i],b.v[i]);
-		if (j!==0) return j;
-	}
-	return 0;
-};
-
-FF.fromBytes=function(x,b)
-{
-	for (var i=0;i<x.length;i++)
-	{
-		x.v[i]=BIG.frombytearray(b,(x.length-i-1)*ROM.MODBYTES);
-	}
-};
-
-/* in-place swapping using xor - side channel resistant - lengths must be the same */
-FF.cswap=function(a,b,d)
-{
-	for (var i=0;i<a.length;i++)
-	{
-	//	BIG.cswap(a.v[i],b.v[i],d);
-		a.v[i].cswap(b.v[i],d);
-	}
-};
-
-	/* z=x*y. Assumes x and y are of same length. */
-FF.mul=function(x,y)
-{
-	var n=x.length;
-	var z=new FF(2*n);
-	var t=new FF(2*n);
-	z.karmul(0,x,0,y,0,t,0,n);
-	return z;
-};
-
-	/* z=x^2 */
-FF.sqr=function(x)
-{
-	var n=x.length;
-	var z=new FF(2*n);
-	var t=new FF(2*n);
-	z.karsqr(0,x,0,t,0,n);
-	return z;
-};
-
-FF.igcd=function(x,y)
-{ /* integer GCD, returns GCD of x and y */
-	var r;
-	if (y===0) return x;
-	while ((r=x%y)!==0)
-		{x=y;y=r;}
-	return y;
-};
-
-/* Miller-Rabin test for primality. Slow. */
-FF.prime=function(p,rng)
-{
-	var i,j,s=0,n=p.length;
-	var loop;
-	var d=new FF(n);
-	var x=new FF(n);
-	var unity=new FF(n);
-	var nm1=new FF(n);
-
-	var sf=4849845; /* 3*5*.. *19 */
-	p.norm();
-
-	if (p.cfactor(sf)) return false;
-	unity.one();
-	nm1.copy(p);
-	nm1.sub(unity);
-	nm1.norm();
-	d.copy(nm1);
-
-	while (d.parity()===0)
-	{
-		d.shr();
-		s++;
-	}
-	if (s===0) return false;
-
-	for (i=0;i<10;i++)
-	{
-		x.randomnum(p,rng);
-		x.pow(d,p);
-		if (FF.comp(x,unity)===0 || FF.comp(x,nm1)===0) continue;
-		loop=false;
-		for (j=1;j<s;j++)
-		{
-			x.power(2,p);
-			if (FF.comp(x,unity)===0) return false;
-			if (FF.comp(x,nm1)===0) {loop=true; break;}
-		}
-		if (loop) continue;
-		return false;
-	}
-	return true;
-};
diff --git a/js/FP.js b/js/FP.js
deleted file mode 100755
index 37aa5de..0000000
--- a/js/FP.js
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
-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.
-*/
-
-/* Finite Field arithmetic */
-/* AMCL mod p functions */
-
-/* General purpose COnstructor */
-var FP = function(x) {
-	if (x instanceof FP)
-	{
-		this.f=new BIG(x.f);
-	}
-	else
-	{
-		this.f=new BIG(x);
-		this.nres();
-	}
-};
-
-FP.prototype={
-/* set this=0 */
-	zero: function()
-	{
-		return this.f.zero();
-	},
-
-/* copy from a BIG in ROM */
-	rcopy: function(y)
-	{
-		this.f.rcopy(y);
-		this.nres();
-	},
-
-/* copy from another BIG */
-	bcopy: function(y)
-	{
-		this.f.copy(y);
-		this.nres();
-	},
-
-/* copy from another FP */
-	copy: function(y)
-	{
-		return this.f.copy(y.f);
-	},
-
-/* conditional swap of a and b depending on d */
-	cswap: function(b,d)
-	{
-		this.f.cswap(b.f,d);
-	},
-
-/* conditional copy of b to a depending on d */
-	cmove: function(b,d)
-	{
-		this.f.cmove(b.f,d);
-	},
-
-/* convert to Montgomery n-residue form */
-	nres: function()
-	{
-		if (ROM.MODTYPE!=ROM.PSEUDO_MERSENNE)
-		{
-			var p=new BIG();
-			p.rcopy(ROM.Modulus);
-			var d=new DBIG(0);
-			d.hcopy(this.f);
-			d.norm();
-			d.shl(ROM.NLEN*ROM.BASEBITS);
-			this.f.copy(d.mod(p));
-
-		}
-		return this;
-	},
-
-/* convert back to regular form */
-	redc: function()
-	{
-		var r=new BIG(0);
-		r.copy(this.f);
-		if (ROM.MODTYPE!=ROM.PSEUDO_MERSENNE)
-		{
-			var d=new DBIG(0);
-			d.hcopy(this.f);
-			r.copy(BIG.mod(d));
-		}
-
-		return r;
-	},
-
-/* convert this to string */
-	toString: function()
-	{
-		var s=this.redc().toString();
-		return s;
-	},
-
-/* test this=0 */
-	iszilch: function()
-	{
-		this.reduce();
-		return this.f.iszilch();
-	},
-
-/* reduce this mod Modulus */
-	reduce: function()
-	{
-		var p=new BIG(0);
-		p.rcopy(ROM.Modulus);
-		return this.f.mod(p);
-	},
-
-/* set this=1 */
-	one: function()
-	{
-		this.f.one();
-		return this.nres();
-	},
-
-/* normalise this */
-	norm: function()
-	{
-		return this.f.norm();
-	},
-
-/* this*=b mod Modulus */
-	mul: function(b)
-	{
-		var ea=BIG.EXCESS(this.f);
-		var eb=BIG.EXCESS(b.f);
-		if ((ea+1)*(eb+1)+1>=ROM.FEXCESS) this.reduce();
-		var d=BIG.mul(this.f,b.f);
-		this.f.copy(BIG.mod(d));
-		return this;
-	},
-
-/* this*=c mod Modulus where c is an int */
-	imul: function(c)
-	{
-		var s=false;
-		this.norm();
-		if (c<0)
-		{
-			c=-c;
-			s=true;
-		}
-
-		var afx=(BIG.EXCESS(this.f)+1)*(c+1)+1;
-		if (c<ROM.NEXCESS && afx<ROM.FEXCESS)
-		{
-			this.f.imul(c);
-		}
-		else
-		{
-			if (afx<ROM.FEXCESS) this.f.pmul(c);
-			else
-			{
-				var p=new BIG(0);
-				p.rcopy(ROM.Modulus);
-				var d=this.f.pxmul(c);
-				this.f.copy(d.mod(p));
-			}
-		}
-		if (s) this.neg();
-		return this.norm();
-	},
-
-/* this*=this mod Modulus */
-	sqr: function()
-	{
-		var d;
-		var ea=BIG.EXCESS(this.f);
-		if ((ea+1)*(ea+1)+1>=ROM.FEXCESS) this.reduce();
-		d=BIG.sqr(this.f);
-		var t=BIG.mod(d);
-		this.f.copy(t);
-		return this;
-	},
-
-/* this+=b */
-	add: function(b)
-	{
-		this.f.add(b.f);
-		if (BIG.EXCESS(this.f)+2>=ROM.FEXCESS) this.reduce();
-		return this;
-	},
-/* this=-this mod Modulus */
-	neg: function()
-	{
-		var sb,ov;
-		var m=new BIG(0);
-		m.rcopy(ROM.Modulus);
-
-		this.norm();
-		ov=BIG.EXCESS(this.f);
-		sb=1; while(ov!==0) {sb++;ov>>=1;}
-
-		m.fshl(sb);
-		this.f.rsub(m);
-		if (BIG.EXCESS(this.f)>=ROM.FEXCESS) this.reduce();
-		return this;
-	},
-
-/* this-=b */
-	sub: function(b)
-	{
-		var n=new FP(0);
-		n.copy(b);
-		n.neg();
-		this.add(n);
-		return this;
-	},
-
-/* this/=2 mod Modulus */
-	div2: function()
-	{
-		this.norm();
-		if (this.f.parity()===0)
-			this.f.fshr(1);
-		else
-		{
-			var p=new BIG(0);
-			p.rcopy(ROM.Modulus);
-
-			this.f.add(p);
-			this.f.norm();
-			this.f.fshr(1);
-		}
-		return this;
-	},
-
-/* this=1/this mod Modulus */
-	inverse: function()
-	{
-		var p=new BIG(0);
-		p.rcopy(ROM.Modulus);
-		var r=this.redc();
-		r.invmodp(p);
-		this.f.copy(r);
-		return this.nres();
-	},
-
-/* return TRUE if this==a */
-	equals: function(a)
-	{
-		a.reduce();
-		this.reduce();
-		if (BIG.comp(a.f,this.f)===0) return true;
-		return false;
-	},
-
-/* return this^e mod Modulus */
-	pow: function(e)
-	{
-		var bt;
-		var r=new FP(1);
-		e.norm();
-		this.norm();
-		var m=new FP(0);
-		m.copy(this);
-		while (true)
-		{
-			bt=e.parity();
-			e.fshr(1);
-			if (bt==1) r.mul(m);
-			if (e.iszilch()) break;
-			m.sqr();
-		}
-
-		r.reduce();
-		return r;
-	},
-
-/* return jacobi symbol (this/Modulus) */
-	jacobi: function()
-	{
-		var p=new BIG(0);
-		p.rcopy(ROM.Modulus);
-		var w=this.redc();
-		return w.jacobi(p);
-	},
-
-/* return sqrt(this) mod Modulus */
-	sqrt: function()
-	{
-		this.reduce();
-		var b=new BIG(0);
-		b.rcopy(ROM.Modulus);
-		if (ROM.MOD8==5)
-		{
-			b.dec(5); b.norm(); b.shr(3);
-			var i=new FP(0);
-			i.copy(this);
-			i.f.shl(1);
-			var v=i.pow(b);
-			i.mul(v); i.mul(v);
-			i.f.dec(1);
-			var r=new FP(0);
-			r.copy(this);
-			r.mul(v); r.mul(i);
-			r.reduce();
-			return r;
-		}
-		else
-		{
-			b.inc(1); b.norm(); b.shr(2);
-			return this.pow(b);
-		}
-	}
-
-};
-
-
diff --git a/js/FP12.js b/js/FP12.js
deleted file mode 100755
index 938e727..0000000
--- a/js/FP12.js
+++ /dev/null
@@ -1,558 +0,0 @@
-/*
-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.
-*/
-
-/* AMCL Fp^12 functions */
-
-/* FP12 elements are of the form a+i.b+i^2.c */
-
-/* general purpose constructor */
-var FP12= function(d,e,f)
-{
-	if (d instanceof FP12)
-	{
-		this.a=new FP4(d.a);
-		this.b=new FP4(d.b);
-		this.c=new FP4(d.c);
-	}
-	else
-	{
-		this.a=new FP4(d);
-		this.b=new FP4(e);
-		this.c=new FP4(f);
-	}
-};
-
-FP12.prototype={
-/* reduce all components of this mod Modulus */
-	reduce: function()
-	{
-		this.a.reduce();
-		this.b.reduce();
-		this.c.reduce();
-	},
-/* normalize all components of this mod Modulus */
-	norm: function()
-	{
-		this.a.norm();
-		this.b.norm();
-		this.c.norm();
-	},
-/* test x==0 ? */
-	iszilch: function()
-	{
-		this.reduce();
-		return (this.a.iszilch() && this.b.iszilch() && this.c.iszilch());
-	},
-/* test x==1 ? */
-	isunity: function()
-	{
-		var one=new FP4(1);
-		return (this.a.equals(one) && this.b.iszilch() && this.b.iszilch());
-	},
-/* extract a from this */
-	geta: function()
-	{
-		return this.a;
-	},
-/* extract b */
-	getb: function()
-	{
-		return this.b;
-	},
-/* extract c */
-	getc: function()
-	{
-		return this.c;
-	},
-/* return 1 if x==y, else 0 */
-	equals: function(x)
-	{
-		return (this.a.equals(x.a) && this.b.equals(x.b)&& this.c.equals(x.c));
-	},
-/* copy this=x */
-	copy: function(x)
-	{
-		this.a.copy(x.a);
-		this.b.copy(x.b);
-		this.c.copy(x.c);
-	},
-/* set this=1 */
-	one: function()
-	{
-		this.a.one();
-		this.b.zero();
-		this.c.zero();
-	},
-/* this=conj(this) */
-	conj: function()
-	{
-		this.a.conj();
-		this.b.nconj();
-		this.c.conj();
-	},
-
-/* set this from 3 FP4s */
-	set: function(d,e,f)
-	{
-		this.a.copy(d);
-		this.b.copy(e);
-		this.c.copy(f);
-	},
-/* set this from one FP4 */
-	seta: function(d)
-	{
-		this.a.copy(d);
-		this.b.zero();
-		this.c.zero();
-	},
-
-/* Granger-Scott Unitary Squaring */
-	usqr: function()
-	{
-		var A=new FP4(this.a); //A.copy(this.a);
-		var B=new FP4(this.c); //B.copy(this.c);
-		var C=new FP4(this.b); //C.copy(this.b);
-		var D=new FP4(0);
-
-		this.a.sqr();
-		D.copy(this.a); D.add(this.a);
-		this.a.add(D);
-
-		A.nconj();
-
-		A.add(A);
-		this.a.add(A);
-		B.sqr();
-		B.times_i();
-
-		D.copy(B); D.add(B);
-		B.add(D);
-
-		C.sqr();
-		D.copy(C); D.add(C);
-		C.add(D);
-
-		this.b.conj();
-		this.b.add(this.b);
-		this.c.nconj();
-
-		this.c.add(this.c);
-		this.b.add(B);
-		this.c.add(C);
-		this.reduce();
-	},
-
-/* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
-	sqr: function()
-	{
-		var A=new FP4(this.a); //A.copy(this.a);
-		var B=new FP4(this.b); //B.copy(this.b);
-		var C=new FP4(this.c); //C.copy(this.c);
-		var D=new FP4(this.a); //D.copy(this.a);
-
-		A.sqr();
-		B.mul(this.c);
-		B.add(B);
-		C.sqr();
-		D.mul(this.b);
-		D.add(D);
-
-		this.c.add(this.a);
-		this.c.add(this.b);
-		this.c.sqr();
-
-		this.a.copy(A);
-
-		A.add(B);
-		A.add(C);
-		A.add(D);
-		A.neg();
-		B.times_i();
-		C.times_i();
-
-		this.a.add(B);
-		this.b.copy(C); this.b.add(D);
-		this.c.add(A);
-
-		this.norm();
-	},
-
-/* FP12 full multiplication this=this*y */
-	mul: function(y)
-	{
-		var z0=new FP4(this.a); //z0.copy(this.a);
-		var z1=new FP4(0);
-		var z2=new FP4(this.b); //z2.copy(this.b);
-		var z3=new FP4(0);
-		var t0=new FP4(this.a); //t0.copy(this.a);
-		var t1=new FP4(y.a); //t1.copy(y.a);
-
-		z0.mul(y.a);
-		z2.mul(y.b);
-
-		t0.add(this.b);
-		t1.add(y.b);
-
-		z1.copy(t0); z1.mul(t1);
-		t0.copy(this.b); t0.add(this.c);
-
-		t1.copy(y.b); t1.add(y.c);
-		z3.copy(t0); z3.mul(t1);
-
-		t0.copy(z0); t0.neg();
-		t1.copy(z2); t1.neg();
-
-		z1.add(t0);
-		this.b.copy(z1); this.b.add(t1);
-
-		z3.add(t1);
-		z2.add(t0);
-
-		t0.copy(this.a); t0.add(this.c);
-		t1.copy(y.a); t1.add(y.c);
-		t0.mul(t1);
-		z2.add(t0);
-
-		t0.copy(this.c); t0.mul(y.c);
-		t1.copy(t0); t1.neg();
-
-		this.c.copy(z2); this.c.add(t1);
-		z3.add(t1);
-		t0.times_i();
-		this.b.add(t0);
-
-		z3.times_i();
-		this.a.copy(z0); this.a.add(z3);
-
-		this.norm();
-	},
-
-/* Special case this*=y that arises from special form of ATE pairing line function */
-	smul: function(y)
-	{
-		var z0=new FP4(this.a); //z0.copy(this.a);
-		var z2=new FP4(this.b); //z2.copy(this.b);
-		var z3=new FP4(this.b); //z3.copy(this.b);
-		var t0=new FP4(0);
-		var t1=new FP4(y.a); //t1.copy(y.a);
-
-		z0.mul(y.a);
-		z2.pmul(y.b.real());
-		this.b.add(this.a);
-		t1.real().add(y.b.real());
-
-		this.b.mul(t1);
-		z3.add(this.c);
-		z3.pmul(y.b.real());
-
-		t0.copy(z0); t0.neg();
-		t1.copy(z2); t1.neg();
-
-		this.b.add(t0);
-
-		this.b.add(t1);
-		z3.add(t1);
-		z2.add(t0);
-
-		t0.copy(this.a); t0.add(this.c);
-		t0.mul(y.a);
-		this.c.copy(z2); this.c.add(t0);
-
-		z3.times_i();
-		this.a.copy(z0); this.a.add(z3);
-
-		this.norm();
-	},
-
-/* this=1/this */
-	inverse: function()
-	{
-		var f0=new FP4(this.a); //f0.copy(this.a);
-		var f1=new FP4(this.b); //f1.copy(this.b);
-		var f2=new FP4(this.a); //f2.copy(this.a);
-		var f3=new FP4(0);
-
-		f0.sqr();
-		f1.mul(this.c);
-		f1.times_i();
-		f0.sub(f1);
-
-		f1.copy(this.c); f1.sqr();
-		f1.times_i();
-		f2.mul(this.b);
-		f1.sub(f2);
-
-		f2.copy(this.b); f2.sqr();
-		f3.copy(this.a); f3.mul(this.c);
-		f2.sub(f3);
-
-		f3.copy(this.b); f3.mul(f2);
-		f3.times_i();
-		this.a.mul(f0);
-		f3.add(this.a);
-		this.c.mul(f1);
-		this.c.times_i();
-
-		f3.add(this.c);
-		f3.inverse();
-		this.a.copy(f0); this.a.mul(f3);
-		this.b.copy(f1); this.b.mul(f3);
-		this.c.copy(f2); this.c.mul(f3);
-	},
-
-/* this=this^p, where p=Modulus, using Frobenius */
-	frob: function(f)
-	{
-		var f2=new FP2(f);
-		var f3=new FP2(f);
-
-		f2.sqr();
-		f3.mul(f2);
-
-		this.a.frob(f3);
-		this.b.frob(f3);
-		this.c.frob(f3);
-
-		this.b.pmul(f);
-		this.c.pmul(f2);
-	},
-
-/* trace function */
-	trace: function()
-	{
-		var t=new FP4(0);
-		t.copy(this.a);
-		t.imul(3);
-		t.reduce();
-		return t;
-	},
-/* convert this to hex string */
-	toString: function()
-	{
-		return ("["+this.a.toString()+","+this.b.toString()+","+this.c.toString()+"]");
-	},
-/* convert this to byte array */
-	toBytes: function(w)
-	{
-		var i;
-		var t=[];
-		this.a.geta().getA().toBytes(t);
-		for (i=0;i<ROM.MODBYTES;i++) w[i]=t[i];
-		this.a.geta().getB().toBytes(t);
-		for (i=0;i<ROM.MODBYTES;i++) w[i+ROM.MODBYTES]=t[i];
-		this.a.getb().getA().toBytes(t);
-		for (i=0;i<ROM.MODBYTES;i++) w[i+2*ROM.MODBYTES]=t[i];
-		this.a.getb().getB().toBytes(t);
-		for (i=0;i<ROM.MODBYTES;i++) w[i+3*ROM.MODBYTES]=t[i];
-
-		this.b.geta().getA().toBytes(t);
-		for (i=0;i<ROM.MODBYTES;i++) w[i+4*ROM.MODBYTES]=t[i];
-		this.b.geta().getB().toBytes(t);
-		for (i=0;i<ROM.MODBYTES;i++) w[i+5*ROM.MODBYTES]=t[i];
-		this.b.getb().getA().toBytes(t);
-		for (i=0;i<ROM.MODBYTES;i++) w[i+6*ROM.MODBYTES]=t[i];
-		this.b.getb().getB().toBytes(t);
-		for (i=0;i<ROM.MODBYTES;i++) w[i+7*ROM.MODBYTES]=t[i];
-
-		this.c.geta().getA().toBytes(t);
-		for (i=0;i<ROM.MODBYTES;i++) w[i+8*ROM.MODBYTES]=t[i];
-		this.c.geta().getB().toBytes(t);
-		for (i=0;i<ROM.MODBYTES;i++) w[i+9*ROM.MODBYTES]=t[i];
-		this.c.getb().getA().toBytes(t);
-		for (i=0;i<ROM.MODBYTES;i++) w[i+10*ROM.MODBYTES]=t[i];
-		this.c.getb().getB().toBytes(t);
-		for (i=0;i<ROM.MODBYTES;i++) w[i+11*ROM.MODBYTES]=t[i];
-	},
-
-/* set this=this^e */
-	pow: function(e)
-	{
-		this.norm();
-		e.norm();
-		var w=new FP12(this); //w.copy(this);
-		var z=new BIG(e); //z.copy(e);
-		var r=new FP12(1);
-
-		while (true)
-		{
-			var bt=z.parity();
-			z.fshr(1);
-			if (bt==1) r.mul(w);
-			if (z.iszilch()) break;
-			w.usqr();
-		}
-		r.reduce();
-		return r;
-	},
-
-/* constant time powering by small integer of max length bts */
-	pinpow: function(e,bts)
-	{
-		var i,b;
-		var R=[];
-		R[0]=new FP12(1);
-		R[1]=new FP12(this);
-		for (i=bts-1;i>=0;i--)
-		{
-			b=(e>>i)&1;
-			R[1-b].mul(R[b]);
-			R[b].usqr();
-		}
-		this.copy(R[0]);
-	}
-};
-
-/* convert from byte array to FP12 */
-FP12.fromBytes= function(w)
-{
-	var i,a,b,c,d,e,f,g;
-	var t=[];
-
-	for (i=0;i<ROM.MODBYTES;i++) t[i]=w[i];
-	a=BIG.fromBytes(t);
-	for (i=0;i<ROM.MODBYTES;i++) t[i]=w[i+ROM.MODBYTES];
-	b=BIG.fromBytes(t);
-	c=new FP2(a,b); //c.bset(a,b);
-
-	for (i=0;i<ROM.MODBYTES;i++) t[i]=w[i+2*ROM.MODBYTES];
-	a=BIG.fromBytes(t);
-	for (i=0;i<ROM.MODBYTES;i++) t[i]=w[i+3*ROM.MODBYTES];
-	b=BIG.fromBytes(t);
-	d=new FP2(a,b); //d.bset(a,b);
-
-	e=new FP4(c,d); //e.set(c,d);
-
-	for (i=0;i<ROM.MODBYTES;i++) t[i]=w[i+4*ROM.MODBYTES];
-	a=BIG.fromBytes(t);
-	for (i=0;i<ROM.MODBYTES;i++) t[i]=w[i+5*ROM.MODBYTES];
-	b=BIG.fromBytes(t);
-	c=new FP2(a,b); //c.bset(a,b);
-
-	for (i=0;i<ROM.MODBYTES;i++) t[i]=w[i+6*ROM.MODBYTES];
-	a=BIG.fromBytes(t);
-	for (i=0;i<ROM.MODBYTES;i++) t[i]=w[i+7*ROM.MODBYTES];
-	b=BIG.fromBytes(t);
-	d=new FP2(a,b);
-
-	f=new FP4(c,d); //f.set(c,d);
-
-	for (i=0;i<ROM.MODBYTES;i++) t[i]=w[i+8*ROM.MODBYTES];
-	a=BIG.fromBytes(t);
-	for (i=0;i<ROM.MODBYTES;i++) t[i]=w[i+9*ROM.MODBYTES];
-	b=BIG.fromBytes(t);
-	c=new FP2(a,b); //c.bset(a,b);
-
-	for (i=0;i<ROM.MODBYTES;i++) t[i]=w[i+10*ROM.MODBYTES];
-	a=BIG.fromBytes(t);
-	for (i=0;i<ROM.MODBYTES;i++) t[i]=w[i+11*ROM.MODBYTES];
-	b=BIG.fromBytes(t);
-	d=new FP2(a,b); //d.bset(a,b);
-
-	g=new FP4(c,d); //g.set(c,d);
-
-	var r=new FP12(e,f,g); //r.set(e,f,g);
-
-	return r;
-};
-
-/* p=q0^u0.q1^u1.q2^u2.q3^u3 */
-/* Timing attack secure, but not cache attack secure */
-
-FP12.pow4= function(q,u)
-{
-	var i,j,nb,m;
-	var a=[];
-	var g=[];
-	var s=[];
-
-	var c=new FP12(1);
-	var p=new FP12(0);
-	var t=[];
-
-	var mt=new BIG(0);
-	var w=[];
-
-	for (i=0;i<4;i++)
-		t[i]=new BIG(u[i]);
-
-	s[0]=new FP12(0);
-	s[1]=new FP12(0);
-
-	g[0]=new FP12(q[0]); s[0].copy(q[1]); s[0].conj(); g[0].mul(s[0]);
-	g[1]=new FP12(g[0]);
-	g[2]=new FP12(g[0]);
-	g[3]=new FP12(g[0]);
-	g[4]=new FP12(q[0]); g[4].mul(q[1]);
-	g[5]=new FP12(g[4]);
-	g[6]=new FP12(g[4]);
-	g[7]=new FP12(g[4]);
-
-	s[1].copy(q[2]); s[0].copy(q[3]); s[0].conj(); s[1].mul(s[0]);
-	s[0].copy(s[1]); s[0].conj(); g[1].mul(s[0]);
-	g[2].mul(s[1]);
-	g[5].mul(s[0]);
-	g[6].mul(s[1]);
-	s[1].copy(q[2]); s[1].mul(q[3]);
-	s[0].copy(s[1]); s[0].conj(); g[0].mul(s[0]);
-	g[3].mul(s[1]);
-	g[4].mul(s[0]);
-	g[7].mul(s[1]);
-
-/* if power is even add 1 to power, and add q to correction */
-
-	for (i=0;i<4;i++)
-	{
-		if (t[i].parity()==0)
-		{
-			t[i].inc(1); t[i].norm();
-			c.mul(q[i]);
-		}
-		mt.add(t[i]); mt.norm();
-	}
-	c.conj();
-	nb=1+mt.nbits();
-
-/* convert exponent to signed 1-bit window */
-	for (j=0;j<nb;j++)
-	{
-		for (i=0;i<4;i++)
-		{
-			a[i]=(t[i].lastbits(2)-2);
-			t[i].dec(a[i]); t[i].norm();
-			t[i].fshr(1);
-		}
-		w[j]=(8*a[0]+4*a[1]+2*a[2]+a[3]);
-	}
-	w[nb]=(8*t[0].lastbits(2)+4*t[1].lastbits(2)+2*t[2].lastbits(2)+t[3].lastbits(2));
-	p.copy(g[Math.floor((w[nb]-1)/2)]);
-
-	for (i=nb-1;i>=0;i--)
-	{
-		m=w[i]>>31;
-		j=(w[i]^m)-m;  /* j=abs(w[i]) */
-		j=(j-1)/2;
-		s[0].copy(g[j]); s[1].copy(g[j]); s[1].conj();
-		p.usqr();
-		p.mul(s[m&1]);
-	}
-	p.mul(c);  /* apply correction */
-	p.reduce();
-	return p;
-};
-
diff --git a/js/FP2.js b/js/FP2.js
deleted file mode 100755
index b9b9942..0000000
--- a/js/FP2.js
+++ /dev/null
@@ -1,321 +0,0 @@
-/*
-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.
-*/
-
-/* Finite Field arithmetic  Fp^2 functions */
-
-/* FP2 elements are of the form a+ib, where i is sqrt(-1) */
-
-/* general purpose constructor */
-var FP2 =function(c,d)
-{
-	if (c instanceof FP2)
-	{
-		this.a=new FP(c.a);
-		this.b=new FP(c.b);
-	}
-	else
-	{
-		this.a=new FP(c);
-		this.b=new FP(d);
-	}
-};
-
-FP2.prototype={
-/* reduce components mod Modulus */
-	reduce: function()
-	{
-		this.a.reduce();
-		this.b.reduce();
-	},
-/* normalise components of w */
-	norm: function()
-	{
-		this.a.norm();
-		this.b.norm();
-	},
-/* test this=0 ? */
-	iszilch: function()
-	{
-		this.reduce();
-		return (this.a.iszilch() && this.b.iszilch());
-	},
-/* test this=1 ? */
-	isunity: function()
-	{
-		var one=new FP(1);
-		return (this.a.equals(one) && this.b.iszilch());
-	},
-/* conditional copy of g to this depending on d */
-	cmove:function(g,d)
-	{
-		this.a.cmove(g.a,d);
-		this.b.cmove(g.b,d);
-	},
-
-/* test this=x */
-	equals: function(x) {
-		return (this.a.equals(x.a) && this.b.equals(x.b));
-	},
-/* extract a */
-	getA: function()
-	{
-		return this.a.redc();
-	},
-/* extract b */
-	getB: function()
-	{
-		return this.b.redc();
-	},
-
-/* set from pair of FPs */
-	set: function(c,d)
-	{
-		this.a.copy(c);
-		this.b.copy(d);
-	},
-/* set a */
-	seta: function(c)
-	{
-		this.a.copy(c);
-		this.b.zero();
-	},
-
-/* set from two BIGs */
-	bset: function(c,d)
-	{
-		this.a.bcopy(c);
-		this.b.bcopy(d);
-	},
-
-/* set from one BIG */
-	bseta: function(c)
-	{
-		this.a.bcopy(c);
-		this.b.zero();
-	},
-/* copy this=x */
-	copy: function(x)
-	{
-		this.a.copy(x.a);
-		this.b.copy(x.b);
-	},
-/* set this=0 */
-	zero: function()
-	{
-		this.a.zero();
-		this.b.zero();
-	},
-/* set this=1 */
-	one: function()
-	{
-		this.a.one();
-		this.b.zero();
-	},
-/* negate this */
-	neg: function()
-	{
-		this.norm();
-		var m=new FP(this.a);
-		var t=new FP(0);
-
-		m.add(this.b);
-		m.neg();
-		m.norm();
-		t.copy(m); t.add(this.b);
-		this.b.copy(m);
-		this.b.add(this.a);
-		this.a.copy(t);
-		//this.norm();
-	},
-/* conjugate this */
-	conj: function()
-	{
-		this.b.neg();
-	},
-/* this+=a */
-	add: function(x)
-	{
-		this.a.add(x.a);
-		this.b.add(x.b);
-	},
-/* this-=x */
-	sub: function(x)
-	{
-		var m=new FP2(x); //var m=new FP2(0); m.copy(x);
-		m.neg();
-		this.add(m);
-	},
-/* this*=s, where s is FP */
-	pmul: function(s)
-	{
-		this.a.mul(s);
-		this.b.mul(s);
-	},
-/* this*=c, where s is int */
-	imul: function(c)
-	{
-		this.a.imul(c);
-		this.b.imul(c);
-	},
-/* this*=this */
-	sqr: function()
-	{
-		this.norm();
-
-		var w1=new FP(this.a);
-		var w3=new FP(this.a);
-		var mb=new FP(this.b);
-
-		w3.mul(this.b);
-		w1.add(this.b);
-		mb.neg();
-		this.a.add(mb);
-		this.a.mul(w1);
-		this.b.copy(w3); this.b.add(w3);
-		this.norm();
-	},
-/* this*=y */
-	mul: function(y)
-	{
-		this.norm();  // This is needed here as {a,b} is not normed before additions
-
-		var w1=new FP(this.a);
-		var w2=new FP(this.b);
-		var w5=new FP(this.a);
-		var mw=new FP(0);
-
-		w1.mul(y.a);  // w1=a*y.a  - this norms w1 and y.a, NOT a
-		w2.mul(y.b);  // w2=b*y.b  - this norms w2 and y.b, NOT b
-		w5.add(this.b);    // w5=a+b
-		this.b.copy(y.a); this.b.add(y.b); // b=y.a+y.b
-
-		this.b.mul(w5);
-		mw.copy(w1); mw.add(w2); mw.neg();
-
-		this.b.add(mw); mw.add(w1);
-		this.a.copy(w1); this.a.add(mw);
-
-		this.norm();
-	},
-
-/* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */
-/* returns true if this is QR */
-	sqrt: function()
-	{
-		if (this.iszilch()) return true;
-		var w1=new FP(this.b);
-		var w2=new FP(this.a);
-
-		w1.sqr(); w2.sqr(); w1.add(w2);
-		if (w1.jacobi()!=1) { this.zero(); return false; }
-		w1=w1.sqrt();
-		w2.copy(this.a); w2.add(w1); w2.div2();
-		if (w2.jacobi()!=1)
-		{
-			w2.copy(this.a); w2.sub(w1); w2.div2();
-			if (w2.jacobi()!=1) { this.zero(); return false; }
-		}
-		w2=w2.sqrt();
-		this.a.copy(w2);
-		w2.add(w2);
-		w2.inverse();
-		this.b.mul(w2);
-		return true;
-	},
-
-/* convert this to hex string */
-	toString: function()
-	{
-		return ("["+this.a.toString()+","+this.b.toString()+"]");
-	},
-/* this=1/this */
-	inverse: function()
-	{
-		this.norm();
-		var w1=new FP(this.a);
-		var w2=new FP(this.b);
-		w1.sqr();
-		w2.sqr();
-		w1.add(w2);
-		w1.inverse();
-		this.a.mul(w1);
-		w1.neg();
-		this.b.mul(w1);
-	},
-/* this/=2 */
-	div2: function()
-	{
-		this.a.div2();
-		this.b.div2();
-	},
-/* this*=sqrt(-1) */
-	times_i: function()
-	{
-		var z=new FP(this.a); //z.copy(this.a);
-		this.a.copy(this.b); this.a.neg();
-		this.b.copy(z);
-	},
-
-/* w*=(1+sqrt(-1)) */
-/* where X*2-(1+sqrt(-1)) is irreducible for FP4, assumes p=3 mod 8 */
-	mul_ip: function()
-	{
-		this.norm();
-		var t=new FP2(this);// t.copy(this);
-		var z=new FP(this.a); //z.copy(this.a);
-		this.a.copy(this.b);
-		this.a.neg();
-		this.b.copy(z);
-		this.add(t);
-		this.norm();
-	},
-
-/* w/=(1+sqrt(-1)) */
-	div_ip: function()
-	{
-		var t=new FP2(0);
-		this.norm();
-		t.a.copy(this.a); t.a.add(this.b);
-		t.b.copy(this.b); t.b.sub(this.a);
-		this.copy(t);
-		this.div2();
-	},
-/* this=this^e */
-	pow: function(e)
-	{
-		var bt;
-		var r=new FP2(1);
-		this.norm();
-		var x=new FP2(this); //x.copy(this);
-		e.norm();
-		while (true)
-		{
-			bt=e.parity();
-			e.fshr(1);
-			if (bt==1) r.mul(x);
-			if (e.iszilch()) break;
-			x.sqr();
-		}
-
-		r.reduce();
-		return r;
-	}
-
-};
-
diff --git a/js/FP4.js b/js/FP4.js
deleted file mode 100755
index 35dddfa..0000000
--- a/js/FP4.js
+++ /dev/null
@@ -1,501 +0,0 @@
-/*
-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.
-*/
-
-/* Finite Field arithmetic  Fp^4 functions */
-
-/* FP4 elements are of the form a+ib, where i is sqrt(-1+sqrt(-1))  */
-
-/* general purpose constructor */
-var FP4=function(c,d)
-{
-	if (c instanceof FP4)
-	{
-		this.a=new FP2(c.a);
-		this.b=new FP2(c.b);
-	}
-	else
-	{
-		this.a=new FP2(c);
-		this.b=new FP2(d);
-	}
-};
-
-FP4.prototype={
-/* reduce all components of this mod Modulus */
-	reduce: function()
-	{
-		this.a.reduce();
-		this.b.reduce();
-	},
-/* normalise all components of this mod Modulus */
-	norm: function()
-	{
-		this.a.norm();
-		this.b.norm();
-	},
-/* test this==0 ? */
-	iszilch: function()
-	{
-		this.reduce();
-		return (this.a.iszilch() && this.b.iszilch());
-	},
-/* test this==1 ? */
-	isunity: function()
-	{
-		var one=new FP2(1);
-		return (this.a.equals(one) && this.b.iszilch());
-	},
-/* test is w real? That is in a+ib test b is zero */
-	isreal: function()
-	{
-		return this.b.iszilch();
-	},
-/* extract real part a */
-	real: function()
-	{
-		return this.a;
-	},
-
-	geta: function()
-	{
-		return this.a;
-	},
-/* extract imaginary part b */
-	getb: function()
-	{
-		return this.b;
-	},
-/* test this=x? */
-	equals: function(x)
-	{
-		return (this.a.equals(x.a) && this.b.equals(x.b));
-	},
-/* copy this=x */
-	copy: function(x)
-	{
-		this.a.copy(x.a);
-		this.b.copy(x.b);
-	},
-/* this=0 */
-	zero: function()
-	{
-		this.a.zero();
-		this.b.zero();
-	},
-/* this=1 */
-	one: function()
-	{
-		this.a.one();
-		this.b.zero();
-	},
-
-/* set from two FP2s */
-	set: function(c,d)
-	{
-		this.a.copy(c);
-		this.b.copy(d);
-	},
-/* set a */
-	seta: function(c)
-	{
-		this.a.copy(c);
-		this.b.zero();
-	},
-/* this=-this */
-	neg: function()
-	{
-		var m=new FP2(this.a); //m.copy(this.a);
-		var t=new FP2(0);
-		m.add(this.b);
-		m.neg();
-		m.norm();
-		t.copy(m); t.add(this.b);
-		this.b.copy(m);
-		this.b.add(this.a);
-		this.a.copy(t);
-	},
-/* this=conjugate(this) */
-	conj: function()
-	{
-		this.b.neg(); this.b.norm();
-	},
-/* this=-conjugate(this) */
-	nconj: function()
-	{
-		this.a.neg(); this.a.norm();
-	},
-/* this+=x */
-	add: function(x)
-	{
-		this.a.add(x.a);
-		this.b.add(x.b);
-	},
-/* this-=x */
-	sub: function(x)
-	{
-		var m=new FP4(x); // m.copy(x);
-		m.neg();
-		this.add(m);
-	},
-/* this*=s where s is FP2 */
-	pmul: function(s)
-	{
-		this.a.mul(s);
-		this.b.mul(s);
-	},
-/* this*=c where s is int */
-	imul: function(c)
-	{
-		this.a.imul(c);
-		this.b.imul(c);
-	},
-/* this*=this */
-	sqr: function()
-	{
-		this.norm();
-
-		var t1=new FP2(this.a); //t1.copy(this.a);
-		var t2=new FP2(this.b); //t2.copy(this.b);
-		var t3=new FP2(this.a); //t3.copy(this.a);
-
-		t3.mul(this.b);
-		t1.add(this.b);
-		t2.mul_ip();
-
-		t2.add(this.a);
-		this.a.copy(t1);
-
-		this.a.mul(t2);
-
-		t2.copy(t3);
-		t2.mul_ip();
-		t2.add(t3);
-
-		t2.neg();
-
-		this.a.add(t2);
-
-		this.b.copy(t3);
-		this.b.add(t3);
-
-		this.norm();
-	},
-/* this*=y */
-	mul: function(y)
-	{
-		this.norm();
-
-		var t1=new FP2(this.a); //t1.copy(this.a);
-		var t2=new FP2(this.b); //t2.copy(this.b);
-		var t3=new FP2(0);
-		var t4=new FP2(this.b); //t4.copy(this.b);
-
-		t1.mul(y.a);
-		t2.mul(y.b);
-		t3.copy(y.b);
-		t3.add(y.a);
-		t4.add(this.a);
-
-		t4.mul(t3);
-		t4.sub(t1);
-
-		this.b.copy(t4);
-		this.b.sub(t2);
-		t2.mul_ip();
-		this.a.copy(t2);
-		this.a.add(t1);
-
-		this.norm();
-	},
-/* convert to hex string */
-	toString: function()
-	{
-		return ("["+this.a.toString()+","+this.b.toString()+"]");
-	},
-/* this=1/this */
-	inverse: function()
-	{
-		this.norm();
-
-		var t1=new FP2(this.a); //t1.copy(this.a);
-		var t2=new FP2(this.b);// t2.copy(this.b);
-
-		t1.sqr();
-		t2.sqr();
-		t2.mul_ip();
-		t1.sub(t2);
-		t1.inverse();
-		this.a.mul(t1);
-		t1.neg();
-		this.b.mul(t1);
-	},
-
-/* this*=i where i = sqrt(-1+sqrt(-1)) */
-	times_i: function()
-	{
-		var s=new FP2(this.b); //s.copy(this.b);
-		var t=new FP2(this.b); //t.copy(this.b);
-		s.times_i();
-		t.add(s);
-		this.b.copy(this.a);
-		this.a.copy(t);
-	},
-
-/* this=this^q using Frobenius, where q is Modulus */
-	frob: function(f)
-	{
-		this.a.conj();
-		this.b.conj();
-		this.b.mul(f);
-	},
-
-/* this=this^e */
-	pow: function(e)
-	{
-		this.norm();
-		e.norm();
-		var w=new FP4(this); //w.copy(this);
-		var z=new BIG(e); //z.copy(e);
-		var r=new FP4(1);
-		while (true)
-		{
-			var bt=z.parity();
-			z.fshr(1);
-			if (bt==1) r.mul(w);
-			if (z.iszilch()) break;
-			w.sqr();
-		}
-		r.reduce();
-		return r;
-	},
-
-/* XTR xtr_a function */
-	xtr_A: function(w,y,z)
-	{
-		var r=new FP4(w); //r.copy(w);
-		var t=new FP4(w); //t.copy(w);
-		r.sub(y);
-		r.pmul(this.a);
-		t.add(y);
-		t.pmul(this.b);
-		t.times_i();
-
-		this.copy(r);
-		this.add(t);
-		this.add(z);
-
-		this.norm();
-	},
-/* XTR xtr_d function */
-	xtr_D: function()
-	{
-		var w=new FP4(this); //w.copy(this);
-		this.sqr(); w.conj();
-		w.add(w);
-		this.sub(w);
-		this.reduce();
-	},
-/* r=x^n using XTR method on traces of FP12s */
-	xtr_pow: function(n)
-	{
-		var a=new FP4(3);
-		var b=new FP4(this);
-		var c=new FP4(b);
-		c.xtr_D();
-		var t=new FP4(0);
-		var r=new FP4(0);
-
-		n.norm();
-		var par=n.parity();
-		var v=new BIG(n); v.fshr(1);
-		if (par===0) {v.dec(1); v.norm();}
-
-		var nb=v.nbits();
-		for (var i=nb-1;i>=0;i--)
-		{
-			if (v.bit(i)!=1)
-			{
-				t.copy(b);
-				this.conj();
-				c.conj();
-				b.xtr_A(a,this,c);
-				this.conj();
-				c.copy(t);
-				c.xtr_D();
-				a.xtr_D();
-			}
-			else
-			{
-				t.copy(a); t.conj();
-				a.copy(b);
-				a.xtr_D();
-				b.xtr_A(c,this,t);
-				c.xtr_D();
-			}
-		}
-		if (par===0) r.copy(c);
-		else r.copy(b);
-		r.reduce();
-		return r;
-	},
-
-/* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */
-	xtr_pow2: function(ck,ckml,ckm2l,a,b)
-	{
-		a.norm(); b.norm();
-		var e=new BIG(a); //e.copy(a);
-		var d=new BIG(b); //d.copy(b);
-		var w=new BIG(0);
-
-		var cu=new FP4(ck); //cu.copy(ck); // can probably be passed in w/o copying
-		var cv=new FP4(this); //cv.copy(this);
-		var cumv=new FP4(ckml); //cumv.copy(ckml);
-		var cum2v=new FP4(ckm2l); //cum2v.copy(ckm2l);
-		var r=new FP4(0);
-		var t=new FP4(0);
-
-		var f2=0;
-		while (d.parity()===0 && e.parity()===0)
-		{
-			d.fshr(1);
-			e.fshr(1);
-			f2++;
-		}
-
-		while (BIG.comp(d,e)!==0)
-		{
-			if (BIG.comp(d,e)>0)
-			{
-				w.copy(e); w.imul(4); w.norm();
-				if (BIG.comp(d,w)<=0)
-				{
-					w.copy(d); d.copy(e);
-					e.rsub(w); e.norm();
-
-					t.copy(cv);
-					t.xtr_A(cu,cumv,cum2v);
-					cum2v.copy(cumv);
-					cum2v.conj();
-					cumv.copy(cv);
-					cv.copy(cu);
-					cu.copy(t);
-
-				}
-				else if (d.parity()===0)
-				{
-					d.fshr(1);
-					r.copy(cum2v); r.conj();
-					t.copy(cumv);
-					t.xtr_A(cu,cv,r);
-					cum2v.copy(cumv);
-					cum2v.xtr_D();
-					cumv.copy(t);
-					cu.xtr_D();
-				}
-				else if (e.parity()==1)
-				{
-					d.sub(e); d.norm();
-					d.fshr(1);
-					t.copy(cv);
-					t.xtr_A(cu,cumv,cum2v);
-					cu.xtr_D();
-					cum2v.copy(cv);
-					cum2v.xtr_D();
-					cum2v.conj();
-					cv.copy(t);
-				}
-				else
-				{
-					w.copy(d);
-					d.copy(e); d.fshr(1);
-					e.copy(w);
-					t.copy(cumv);
-					t.xtr_D();
-					cumv.copy(cum2v); cumv.conj();
-					cum2v.copy(t); cum2v.conj();
-					t.copy(cv);
-					t.xtr_D();
-					cv.copy(cu);
-					cu.copy(t);
-				}
-			}
-			if (BIG.comp(d,e)<0)
-			{
-				w.copy(d); w.imul(4); w.norm();
-				if (BIG.comp(e,w)<=0)
-				{
-					e.sub(d); e.norm();
-					t.copy(cv);
-					t.xtr_A(cu,cumv,cum2v);
-					cum2v.copy(cumv);
-					cumv.copy(cu);
-					cu.copy(t);
-				}
-				else if (e.parity()===0)
-				{
-					w.copy(d);
-					d.copy(e); d.fshr(1);
-					e.copy(w);
-					t.copy(cumv);
-					t.xtr_D();
-					cumv.copy(cum2v); cumv.conj();
-					cum2v.copy(t); cum2v.conj();
-					t.copy(cv);
-					t.xtr_D();
-					cv.copy(cu);
-					cu.copy(t);
-				}
-				else if (d.parity()==1)
-				{
-					w.copy(e);
-					e.copy(d);
-					w.sub(d); w.norm();
-					d.copy(w); d.fshr(1);
-					t.copy(cv);
-					t.xtr_A(cu,cumv,cum2v);
-					cumv.conj();
-					cum2v.copy(cu);
-					cum2v.xtr_D();
-					cum2v.conj();
-					cu.copy(cv);
-					cu.xtr_D();
-					cv.copy(t);
-				}
-				else
-				{
-					d.fshr(1);
-					r.copy(cum2v); r.conj();
-					t.copy(cumv);
-					t.xtr_A(cu,cv,r);
-					cum2v.copy(cumv);
-					cum2v.xtr_D();
-					cumv.copy(t);
-					cu.xtr_D();
-				}
-			}
-		}
-		r.copy(cv);
-		r.xtr_A(cu,cumv,cum2v);
-		for (var i=0;i<f2;i++)
-			r.xtr_D();
-		r=r.xtr_pow(d);
-		return r;
-	}
-
-};
diff --git a/js/GCM.js b/js/GCM.js
deleted file mode 100755
index f0fdfc5..0000000
--- a/js/GCM.js
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
-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.
-*/
-
-/*
- * Implementation of the AES-GCM Encryption/Authentication
- *
- * Some restrictions..
- * 1. Only for use with AES
- * 2. Returned tag is always 128-bits. Truncate at your own risk.
- * 3. The order of function calls must follow some rules
- *
- * Typical sequence of calls..
- * 1. call GCM_init
- * 2. call GCM_add_header any number of times, as long as length of header is multiple of 16 bytes (block size)
- * 3. call GCM_add_header one last time with any length of header
- * 4. call GCM_add_cipher any number of times, as long as length of cipher/plaintext is multiple of 16 bytes
- * 5. call GCM_add_cipher one last time with any length of cipher/plaintext
- * 6. call GCM_finish to extract the tag.
- *
- * See http://www.mindspring.com/~dmcgrew/gcm-nist-6.pdf
- */
-
-var GCM = function() {
-	this.table=new Array(128);
-	for (var i=0;i<128;i++)
-		this.table[i]=new Array(4);  /* 2k bytes */
-	this.stateX=[];
-	this.Y_0=[];
-	this.counter=0;
-	this.lenA=[];
-	this.lenC=[];
-	this.status=0;
-	this.a=new AES();
-};
-
-GCM.prototype={
-
-	precompute: function(H)
-	{
-		var i,j,c;
-		var b=[];
-
-		for (i=j=0;i<4;i++,j+=4)
-		{
-			b[0]=H[j]; b[1]=H[j+1]; b[2]=H[j+2]; b[3]=H[j+3];
-			this.table[0][i]=GCM.pack(b);
-		}
-		for (i=1;i<128;i++)
-		{
-			c=0;
-			for (j=0;j<4;j++)
-			{
-				this.table[i][j]=c|(this.table[i-1][j])>>>1;
-				c=this.table[i-1][j]<<31;
-			}
-			if (c!==0) this.table[i][0]^=0xE1000000; /* irreducible polynomial */
-		}
-	},
-
-	gf2mul: function()
-	{ /* gf2m mul - Z=H*X mod 2^128 */
-		var i,j,m,k;
-		var P=[];
-		var c;
-		var b=[];
-
-		P[0]=P[1]=P[2]=P[3]=0;
-		j=8; m=0;
-		for (i=0;i<128;i++)
-		{
-			c=(this.stateX[m]>>>(--j))&1;
-			if (c!==0) for (k=0;k<4;k++) P[k]^=this.table[i][k];
-			if (j===0)
-			{
-				j=8; m++;
-				if (m==16) break;
-			}
-		}
-		for (i=j=0;i<4;i++,j+=4)
-		{
-			b=GCM.unpack(P[i]);
-			this.stateX[j]=b[0]; this.stateX[j+1]=b[1]; this.stateX[j+2]=b[2]; this.stateX[j+3]=b[3];
-		}
-	},
-
-	wrap: function()
-	{ /* Finish off GHASH */
-		var i,j;
-		var F=[];
-		var L=[];
-		var b=[];
-
-/* convert lengths from bytes to bits */
-		F[0]=(this.lenA[0]<<3)|(this.lenA[1]&0xE0000000)>>>29;
-		F[1]=this.lenA[1]<<3;
-		F[2]=(this.lenC[0]<<3)|(this.lenC[1]&0xE0000000)>>>29;
-		F[3]=this.lenC[1]<<3;
-		for (i=j=0;i<4;i++,j+=4)
-		{
-			b=GCM.unpack(F[i]);
-			L[j]=b[0]; L[j+1]=b[1]; L[j+2]=b[2]; L[j+3]=b[3];
-		}
-		for (i=0;i<16;i++) this.stateX[i]^=L[i];
-		this.gf2mul();
-	},
-
-/* Initialize GCM mode */
-	init: function(key,niv,iv)
-	{ /* iv size niv is usually 12 bytes (96 bits). AES key size nk can be 16,24 or 32 bytes */
-		var i;
-		var H=[];
-		var b=[];
-
-		for (i=0;i<16;i++) {H[i]=0; this.stateX[i]=0;}
-
-		this.a.init(ROM.ECB,key,iv);
-		this.a.ecb_encrypt(H);     /* E(K,0) */
-		this.precompute(H);
-
-		this.lenA[0]=this.lenC[0]=this.lenA[1]=this.lenC[1]=0;
-		if (niv==12)
-		{
-			for (i=0;i<12;i++) this.a.f[i]=iv[i];
-			b=GCM.unpack(1);
-			this.a.f[12]=b[0]; this.a.f[13]=b[1]; this.a.f[14]=b[2]; this.a.f[15]=b[3];  /* initialise IV */
-			for (i=0;i<16;i++) this.Y_0[i]=this.a.f[i];
-		}
-		else
-		{
-			this.status=ROM.GCM_ACCEPTING_CIPHER;
-			this.ghash(iv,niv); /* GHASH(H,0,IV) */
-			this.wrap();
-			for (i=0;i<16;i++) {this.a.f[i]=this.stateX[i];this.Y_0[i]=this.a.f[i];this.stateX[i]=0;}
-			this.lenA[0]=this.lenC[0]=this.lenA[1]=this.lenC[1]=0;
-		}
-		this.status=ROM.GCM_ACCEPTING_HEADER;
-	},
-
-/* Add Header data - included but not encrypted */
-	add_header: function(header,len)
-	{ /* Add some header. Won't be encrypted, but will be authenticated. len is length of header */
-		var i,j=0;
-		if (this.status!=ROM.GCM_ACCEPTING_HEADER) return false;
-
-		while (j<len)
-		{
-			for (i=0;i<16 && j<len;i++)
-			{
-				this.stateX[i]^=header[j++];
-				this.lenA[1]++; this.lenA[1]|=0; if (this.lenA[1]===0) this.lenA[0]++;
-			}
-			this.gf2mul();
-		}
-		if (len%16!==0) this.status=ROM.GCM_ACCEPTING_CIPHER;
-		return true;
-	},
-
-	ghash: function(plain,len)
-	{
-		var i,j=0;
-
-		if (this.status==ROM.GCM_ACCEPTING_HEADER) this.status=ROM.GCM_ACCEPTING_CIPHER;
-		if (this.status!=ROM.GCM_ACCEPTING_CIPHER) return false;
-
-		while (j<len)
-		{
-			for (i=0;i<16 && j<len;i++)
-			{
-				this.stateX[i]^=plain[j++];
-				this.lenC[1]++; this.lenC[1]|=0; if (this.lenC[1]===0) this.lenC[0]++;
-			}
-			this.gf2mul();
-		}
-		if (len%16!==0) this.status=ROM.GCM_NOT_ACCEPTING_MORE;
-		return true;
-	},
-
-/* Add Plaintext - included and encrypted */
-	add_plain: function(plain,len)
-	{
-		var i,j=0;
-		var B=[];
-		var b=[];
-		var cipher=[];
-
-		if (this.status==ROM.GCM_ACCEPTING_HEADER) this.status=ROM.GCM_ACCEPTING_CIPHER;
-		if (this.status!=ROM.GCM_ACCEPTING_CIPHER) return cipher;
-
-		while (j<len)
-		{
-
-			b[0]=this.a.f[12]; b[1]=this.a.f[13]; b[2]=this.a.f[14]; b[3]=this.a.f[15];
-			this.counter=GCM.pack(b);
-			this.counter++;
-			b=GCM.unpack(this.counter);
-			this.a.f[12]=b[0]; this.a.f[13]=b[1]; this.a.f[14]=b[2]; this.a.f[15]=b[3]; /* increment counter */
-			for (i=0;i<16;i++) B[i]=this.a.f[i];
-			this.a.ecb_encrypt(B);        /* encrypt it  */
-
-			for (i=0;i<16 && j<len;i++)
-			{
-				cipher[j]=(plain[j]^B[i]);
-				this.stateX[i]^=cipher[j++];
-				this.lenC[1]++; this.lenC[1]|=0; if (this.lenC[1]===0) this.lenC[0]++;
-			}
-			this.gf2mul();
-		}
-		if (len%16!==0) this.status=ROM.GCM_NOT_ACCEPTING_MORE;
-		return cipher;
-	},
-
-/* Add Ciphertext - decrypts to plaintext */
-	add_cipher: function(cipher,len)
-	{
-		var i,j=0;
-		var B=[];
-		var b=[];
-		var plain=[];
-
-		if (this.status==ROM.GCM_ACCEPTING_HEADER) this.status=ROM.GCM_ACCEPTING_CIPHER;
-		if (this.status!=ROM.GCM_ACCEPTING_CIPHER) return plain;
-
-		while (j<len)
-		{
-			b[0]=this.a.f[12]; b[1]=this.a.f[13]; b[2]=this.a.f[14]; b[3]=this.a.f[15];
-			this.counter=GCM.pack(b);
-			this.counter++;
-			b=GCM.unpack(this.counter);
-			this.a.f[12]=b[0]; this.a.f[13]=b[1]; this.a.f[14]=b[2]; this.a.f[15]=b[3]; /* increment counter */
-			for (i=0;i<16;i++) B[i]=this.a.f[i];
-			this.a.ecb_encrypt(B);        /* encrypt it  */
-			for (i=0;i<16 && j<len;i++)
-			{
-				plain[j]=(cipher[j]^B[i]);
-				this.stateX[i]^=cipher[j++];
-				this.lenC[1]++; this.lenC[1]|=0; if (this.lenC[1]===0) this.lenC[0]++;
-			}
-			this.gf2mul();
-		}
-		if (len%16!==0) this.status=ROM.GCM_NOT_ACCEPTING_MORE;
-		return plain;
-	},
-
-/* Finish and extract Tag */
-	finish: function(extract)
-	{ /* Finish off GHASH and extract tag (MAC) */
-		var i;
-		var tag=[];
-
-		this.wrap();
-/* extract tag */
-		if (extract)
-		{
-			this.a.ecb_encrypt(this.Y_0);        /* E(K,Y0) */
-			for (i=0;i<16;i++) this.Y_0[i]^=this.stateX[i];
-			for (i=0;i<16;i++) {tag[i]=this.Y_0[i];this.Y_0[i]=this.stateX[i]=0;}
-		}
-		this.status=ROM.GCM_FINISHED;
-		this.a.end();
-		return tag;
-	}
-
-};
-
-GCM.pack= function(b)
-{ /* pack 4 bytes into a 32-bit Word */
-		return (((b[0])&0xff)<<24)|((b[1]&0xff)<<16)|((b[2]&0xff)<<8)|(b[3]&0xff);
-};
-
-GCM.unpack=function(a)
-{ /* unpack bytes from a word */
-	var b=[];
-	b[3]=(a&0xff);
-	b[2]=((a>>>8)&0xff);
-	b[1]=((a>>>16)&0xff);
-	b[0]=((a>>>24)&0xff);
-	return b;
-};
-
-GCM.hex2bytes=function(s)
-{
-	var len = s.length;
-	var data = [];
-	for (var i = 0; i < len; i += 2)
-		data[i / 2] = parseInt(s.substr(i,2),16);
-
-	return data;
-};
diff --git a/js/HASH.js b/js/HASH.js
deleted file mode 100755
index a5a82f8..0000000
--- a/js/HASH.js
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
-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.
-*/
-
-var HASH = function() {
-	this.length=[];
-	this.h=[];
-	this.w=[];
-	this.init();
-};
-
-HASH.prototype={
-
-	len: 32,
-	/* functions */
-	S: function(n,x)
-	{
-		return (((x)>>>n) | ((x)<<(32-n)));
-	},
-
-	R: function(n,x)
-	{
-		return ((x)>>>n);
-	},
-
-	Ch: function(x,y,z)
-	{
-		return ((x&y)^(~(x)&z));
-	},
-
-	Maj: function(x,y,z)
-	{
-		return ((x&y)^(x&z)^(y&z));
-	},
-
-	Sig0: function(x)
-	{
-		return (this.S(2,x)^this.S(13,x)^this.S(22,x));
-	},
-
-	Sig1: function(x)
-	{
-		return (this.S(6,x)^this.S(11,x)^this.S(25,x));
-	},
-
-	theta0: function(x)
-	{
-		return (this.S(7,x)^this.S(18,x)^this.R(3,x));
-	},
-
-	theta1: function(x)
-	{
-		return (this.S(17,x)^this.S(19,x)^this.R(10,x));
-	},
-
-	transform: function()
-	{ /* basic transformation step */
-		var a,b,c,d,e,f,g,hh,t1,t2;
-		var j;
-		for (j=16;j<64;j++)
-			this.w[j]=(this.theta1(this.w[j-2])+this.w[j-7]+this.theta0(this.w[j-15])+this.w[j-16])|0;
-
-		a=this.h[0]; b=this.h[1]; c=this.h[2]; d=this.h[3];
-		e=this.h[4]; f=this.h[5]; g=this.h[6]; hh=this.h[7];
-
-		for (j=0;j<64;j++)
-		{ /* 64 times - mush it up */
-			t1=(hh+this.Sig1(e)+this.Ch(e,f,g)+ROM.HK[j]+this.w[j])|0;
-			t2=(this.Sig0(a)+this.Maj(a,b,c))|0;
-			hh=g; g=f; f=e;
-			e=(d+t1)|0; // Need to knock these back down to prevent 52-bit overflow
-			d=c;
-			c=b;
-			b=a;
-			a=(t1+t2)|0;
-
-		}
-		this.h[0]+=a; this.h[1]+=b; this.h[2]+=c; this.h[3]+=d;
-		this.h[4]+=e; this.h[5]+=f; this.h[6]+=g; this.h[7]+=hh;
-
-		this.h[0]|=0;
-		this.h[1]|=0;
-		this.h[2]|=0;
-		this.h[3]|=0;
-		this.h[4]|=0;
-		this.h[5]|=0;
-		this.h[6]|=0;
-		this.h[7]|=0;
-	},
-
-/* Initialise Hash function */
-	init: function()
-	{ /* initialise */
-		var i;
-		for (i=0;i<64;i++) this.w[i]=0;
-		this.length[0]=this.length[1]=0;
-		this.h[0]=ROM.H0;
-		this.h[1]=ROM.H1;
-		this.h[2]=ROM.H2;
-		this.h[3]=ROM.H3;
-		this.h[4]=ROM.H4;
-		this.h[5]=ROM.H5;
-		this.h[6]=ROM.H6;
-		this.h[7]=ROM.H7;
-	},
-
-/* process a single byte */
-	process: function(byt)
-	{ /* process the next message byte */
-		var cnt;
-
-		cnt=(this.length[0]>>>5)%16;
-		this.w[cnt]<<=8;
-		this.w[cnt]|=(byt&0xFF);
-		this.length[0]+=8;
-		if ((this.length[0]&0xffffffff)===0) { this.length[1]++; this.length[0]=0; }
-		if ((this.length[0]%512)===0) this.transform();
-	},
-
-/* process an array of bytes */
-	process_array: function(b)
-	{
-		for (var i=0;i<b.length;i++) this.process(b[i]);
-	},
-
-/* process a 32-bit integer */
-	process_num: function(n)
-	{
-		this.process((n>>24)&0xff);
-		this.process((n>>16)&0xff);
-		this.process((n>>8)&0xff);
-		this.process(n&0xff);
-	},
-
-	hash: function()
-	{ /* pad message and finish - supply digest */
-		var i;
-		var digest=[];
-		var len0,len1;
-		len0=this.length[0];
-		len1=this.length[1];
-		this.process(0x80);
-		while ((this.length[0]%512)!=448) this.process(0);
-
-		this.w[14]=len1;
-		this.w[15]=len0;
-		this.transform();
-
-		for (i=0;i<32;i++)
-		{ /* convert to bytes */
-			digest[i]=((this.h[i>>>2]>>(8*(3-i%4))) & 0xff);
-		}
-		this.init();
-		return digest;
-	}
-
-};
-
-
diff --git a/js/MPIN.js b/js/MPIN.js
deleted file mode 100755
index 837b4fd..0000000
--- a/js/MPIN.js
+++ /dev/null
@@ -1,800 +0,0 @@
-/*
-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.
-*/
-
-/* MPIN API Functions */
-
-var MPIN = {
-	BAD_PARAMS:-11,
-	INVALID_POINT:-14,
-	WRONG_ORDER:-18,
-	BAD_PIN:-19,
-/* configure PIN here */
-	MAXPIN:10000,  /* max PIN */
-	PBLEN:14,     /* MAXPIN length in bits */
-	TS:10,        /* 10 for 4 digit PIN, 14 for 6-digit PIN - 2^TS/TS approx = sqrt(MAXPIN) */
-	TRAP:200,     /* 200 for 4 digit PIN, 2000 for 6-digit PIN  - approx 2*sqrt(MAXPIN) */
-	EFS:ROM.MODBYTES,
-	EGS:ROM.MODBYTES,
-	PAS:16,
-
-/* return time in slots since epoch */
-	today: function() {
-		var now=new Date();
-		return Math.floor(now.getTime()/(60000*1440));  // for daily tokens
-	},
-
-	bytestostring: function(b)
-	{
-		var s="";
-		var len=b.length;
-		var ch;
-
-		for (var i=0;i<len;i++)
-		{
-			ch=b[i];
-			s+=((ch>>>4)&15).toString(16);
-			s+=(ch&15).toString(16);
-
-		}
-		return s;
-	},
-
-	stringtobytes: function(s)
-	{
-		var b=[];
-		for (var i=0;i<s.length;i++)
-			b.push(s.charCodeAt(i));
-		return b;
-	},
-
-	comparebytes: function(a,b)
-	{
-		if (a.length!=b.length) return false;
-		for (var i=0;i<a.length;i++)
-		{
-			if (a[i]!=b[i]) return false;
-		}
-		return true;
-	},
-
-
-/* Hash number (optional) and string to point on curve */
-
-	hashit: function(n,ID)
-	{
-		var H=new HASH();
-		if (n!==0) H.process_num(n);
-		H.process_array(ID);
-		return H.hash();
-	},
-
-	mapit: function(h)
-	{
-		var q=new BIG(0); q.rcopy(ROM.Modulus);
-		var x=BIG.fromBytes(h);
-		x.mod(q);
-		var P=new ECP();
-		while (true)
-		{
-			P.setxi(x,0);
-			if (!P.is_infinity()) break;
-			x.inc(1); x.norm();
-		}
-		return P;
-	},
-
-/* needed for SOK */
-	mapit2: function(h)
-	{
-		var q=new BIG(0); q.rcopy(ROM.Modulus);
-		var x=BIG.fromBytes(h);
-		var one=new BIG(1);
-		x.mod(q);
-		var Q,T,K,X;
-		while (true)
-		{
-			X=new FP2(one,x);
-			Q=new ECP2(); Q.setx(X);
-			if (!Q.is_infinity()) break;
-			x.inc(1); x.norm();
-		}
-/* Fast Hashing to G2 - Fuentes-Castaneda, Knapp and Rodriguez-Henriquez */
-
-		var Fa=new BIG(0); Fa.rcopy(ROM.CURVE_Fra);
-		var Fb=new BIG(0); Fb.rcopy(ROM.CURVE_Frb);
-		X=new FP2(Fa,Fb);
-		x=new BIG(0); x.rcopy(ROM.CURVE_Bnx);
-
-		T=new ECP2(); T.copy(Q);
-		T.mul(x); T.neg();
-		K=new ECP2(); K.copy(T);
-		K.dbl(); K.add(T); K.affine();
-
-		K.frob(X);
-		Q.frob(X); Q.frob(X); Q.frob(X);
-		Q.add(T); Q.add(K);
-		T.frob(X); T.frob(X);
-		Q.add(T);
-		Q.affine();
-		return Q;
-
-	},
-
-/* these next two functions help to implement elligator squared - http://eprint.iacr.org/2014/043 */
-/* maps a random u to a point on the curve */
-	map: function(u,cb)
-	{
-		var P=new ECP();
-		var x=new BIG(u);
-		var p=new BIG(0); p.rcopy(ROM.Modulus);
-		x.mod(p);
-		while (true)
-		{
-			P.setxi(x,cb);
-			if (!P.is_infinity()) break;
-			x.inc(1);  x.norm();
-		}
-		return P;
-	},
-
-/* returns u derived from P. Random value in range 1 to return value should then be added to u */
-	unmap: function(u,P)
-	{
-		var s=P.getS();
-		var R=new ECP();
-		var r=0;
-		var x=P.getX();
-		u.copy(x);
-		while (true)
-		{
-			u.dec(1); u.norm();
-			r++;
-			R.setxi(u,s); //=new ECP(u,s);
-			if (!R.is_infinity()) break;
-		}
-		return r;
-	},
-
-/* these next two functions implement elligator squared - http://eprint.iacr.org/2014/043 */
-/* Elliptic curve point E in format (0x04,x,y} is converted to form {0x0-,u,v} */
-/* Note that u and v are indistinguisible from random strings */
-	ENCODING: function(rng,E)
-	{
-		var i,rn,m,su,sv;
-		var T=[];
-
-		for (i=0;i<this.EFS;i++) T[i]=E[i+1];
-		var u=BIG.fromBytes(T);
-		for (i=0;i<this.EFS;i++) T[i]=E[i+this.EFS+1];
-		var v=BIG.fromBytes(T);
-
-		var P=new ECP(0); P.setxy(u,v);
-		if (P.is_infinity()) return this.INVALID_POINT;
-
-		var p=new BIG(0); p.rcopy(ROM.Modulus);
-		u=BIG.randomnum(p,rng);
-
-		su=rng.getByte(); if (su<0) su=-su; su%=2;
-
-		var W=this.map(u,su);
-		P.sub(W);
-		sv=P.getS();
-		rn=this.unmap(v,P);
-		m=rng.getByte(); if (m<0) m=-m; m%=rn;
-		v.inc(m+1);
-		E[0]=(su+2*sv);
-		u.toBytes(T);
-		for (i=0;i<this.EFS;i++) E[i+1]=T[i];
-		v.toBytes(T);
-		for (i=0;i<this.EFS;i++) E[i+this.EFS+1]=T[i];
-
-		return 0;
-	},
-
-	DECODING: function(D)
-	{
-		var i,su,sv;
-		var T=[];
-
-		if ((D[0]&0x04)!==0) return this.INVALID_POINT;
-
-		for (i=0;i<this.EFS;i++) T[i]=D[i+1];
-		var u=BIG.fromBytes(T);
-		for (i=0;i<this.EFS;i++) T[i]=D[i+this.EFS+1];
-		var v=BIG.fromBytes(T);
-
-		su=D[0]&1;
-		sv=(D[0]>>1)&1;
-		var W=this.map(u,su);
-		var P=this.map(v,sv);
-		P.add(W);
-		u=P.getX();
-		v=P.getY();
-		D[0]=0x04;
-		u.toBytes(T);
-		for (i=0;i<this.EFS;i++) D[i+1]=T[i];
-		v.toBytes(T);
-		for (i=0;i<this.EFS;i++) D[i+this.EFS+1]=T[i];
-
-		return 0;
-	},
-
-/* R=R1+R2 in group G1 */
-	RECOMBINE_G1: function(R1,R2,R)
-	{
-		var P=ECP.fromBytes(R1);
-		var Q=ECP.fromBytes(R2);
-
-		if (P.is_infinity() || Q.is_infinity()) return this.INVALID_POINT;
-
-		P.add(Q);
-
-		P.toBytes(R);
-		return 0;
-	},
-
-/* W=W1+W2 in group G2 */
-	RECOMBINE_G2: function(W1,W2,W)
-	{
-		var P=ECP2.fromBytes(W1);
-		var Q=ECP2.fromBytes(W2);
-
-		if (P.is_infinity() || Q.is_infinity()) return this.INVALID_POINT;
-
-		P.add(Q);
-
-		P.toBytes(W);
-		return 0;
-	},
-
-	HASH_ID: function(ID)
-	{
-		return this.hashit(0,ID);
-	},
-
-/* create random secret S */
-	RANDOM_GENERATE: function(rng,S)
-	{
-		var r=new BIG(0); r.rcopy(ROM.CURVE_Order);
-		var s=BIG.randomnum(r,rng);
-
-		s.toBytes(S);
-		return 0;
-	},
-
-/* Extract PIN from TOKEN for identity CID */
-	EXTRACT_PIN: function(CID,pin,TOKEN)
-	{
-		var P=ECP.fromBytes(TOKEN);
-		if (P.is_infinity()) return this.INVALID_POINT;
-		var h=this.hashit(0,CID);
-		var R=this.mapit(h);
-
-		pin%=this.MAXPIN;
-
-		R=R.pinmul(pin,this.PBLEN);
-		P.sub(R);
-
-		P.toBytes(TOKEN);
-
-		return 0;
-	},
-
-/* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */
-	GET_SERVER_SECRET: function(S,SST)
-	{
-
-		var A=new BIG(0);
-		var B=new BIG(0);
-		A.rcopy(ROM.CURVE_Pxa); B.rcopy(ROM.CURVE_Pxb);
-		var QX=new FP2(0); QX.bset(A,B);
-		A.rcopy(ROM.CURVE_Pya); B.rcopy(ROM.CURVE_Pyb);
-		var QY=new FP2(0); QY.bset(A,B);
-
-		var Q=new ECP2();
-		Q.setxy(QX,QY);
-
-		var s=BIG.fromBytes(S);
-		Q=PAIR.G2mul(Q,s);
-		Q.toBytes(SST);
-		return 0;
-	},
-
-
-/*
- W=x*H(G);
- if RNG == NULL then X is passed in
- if RNG != NULL the X is passed out
- if type=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve
-*/
-	GET_G1_MULTIPLE: function(rng,type,X,G,W)
-	{
-		var x;
-		var r=new BIG(0); r.rcopy(ROM.CURVE_Order);
-
-		if (rng!=null)
-		{
-			x=BIG.randomnum(r,rng);
-			x.toBytes(X);
-		}
-		else
-		{
-			x=BIG.fromBytes(X);
-		}
-		var P;
-		if (type==0)
-		{
-			P=ECP.fromBytes(G);
-			if (P.is_infinity()) return INVALID_POINT;
-		}
-		else
-			P=this.mapit(G);
-
-		PAIR.G1mul(P,x).toBytes(W);
-		return 0;
-	},
-
-
-/* Client secret CST=S*H(CID) where CID is client ID and S is master secret */
-	GET_CLIENT_SECRET: function(S,CID,CST)
-	{
-		return this.GET_G1_MULTIPLE(null,1,S,CID,CST);
-	},
-
-/* Time Permit CTT=S*(date|H(CID)) where S is master secret */
-	GET_CLIENT_PERMIT: function(date,S,CID,CTT)
-	{
-		var h=this.hashit(date,CID);
-		var P=this.mapit(h);
-
-		var s=BIG.fromBytes(S);
-		P=PAIR.G1mul(P,s);
-		P.toBytes(CTT);
-		return 0;
-	},
-
-/* Implement step 1 on client side of MPin protocol */
-	CLIENT_1: function(date,CLIENT_ID,rng,X,pin,TOKEN,SEC,xID,xCID,PERMIT)
-	{
-		var r=new BIG(0); r.rcopy(ROM.CURVE_Order);
-	//	var q=new BIG(0); q.rcopy(ROM.Modulus);
-		var x;
-		if (rng!==null)
-		{
-			x=BIG.randomnum(r,rng);
-			x.toBytes(X);
-		}
-		else
-		{
-			x=BIG.fromBytes(X);
-		}
-		var P,T,W;
-
-		var h=this.hashit(0,CLIENT_ID);
-		P=this.mapit(h);
-		T=ECP.fromBytes(TOKEN);
-		if (T.is_infinity()) return this.INVALID_POINT;
-
-		pin%=this.MAXPIN;
-		W=P.pinmul(pin,this.PBLEN);
-		T.add(W);
-
-		if (date!=0)
-		{
-			W=ECP.fromBytes(PERMIT);
-			if (W.is_infinity()) return this.INVALID_POINT;
-			T.add(W);
-			h=this.hashit(date,h);
-			W=this.mapit(h);
-			if (xID!=null)
-			{
-				P=PAIR.G1mul(P,x);
-				P.toBytes(xID);
-				W=PAIR.G1mul(W,x);
-				P.add(W);
-			}
-			else
-			{
-				P.add(W);
-				P=PAIR.G1mul(P,x);
-			}
-			if (xCID!=null) P.toBytes(xCID);
-		}
-		else
-		{
-			if (xID!=null)
-			{
-				P=PAIR.G1mul(P,x);
-				P.toBytes(xID);
-			}
-		}
-
-		T.toBytes(SEC);
-		return 0;
-	},
-
-/* Implement step 2 on client side of MPin protocol */
-	CLIENT_2: function(X,Y,SEC)
-	{
-		var r=new BIG(0); r.rcopy(ROM.CURVE_Order);
-		var P=ECP.fromBytes(SEC);
-		if (P.is_infinity()) return this.INVALID_POINT;
-
-		var px=BIG.fromBytes(X);
-		var py=BIG.fromBytes(Y);
-		px.add(py);
-		px.mod(r);
-		px.rsub(r);
-
-		PAIR.G1mul(P,px).toBytes(SEC);
-		return 0;
-	},
-
-/* Outputs H(CID) and H(T|H(CID)) for time permits. If no time permits set HID=HTID */
-	SERVER_1: function(date,CID,HID,HTID)
-	{
-		var h=this.hashit(0,CID);
-		var R,P=this.mapit(h);
-
-		if (date!==0)
-		{
-			if (HID!=null) P.toBytes(HID);
-			h=this.hashit(date,h);
-			R=this.mapit(h);
-			P.add(R);
-			P.toBytes(HTID);
-		}
-		else P.toBytes(HID);
-	},
-
-/* Implement step 1 of MPin protocol on server side */
-	SERVER_2: function(date,HID,HTID,Y,SST,xID,xCID,mSEC,E,F)
-	{
-		var A=new BIG(0);
-		var B=new BIG(0);
-		A.rcopy(ROM.CURVE_Pxa); B.rcopy(ROM.CURVE_Pxb);
-		var QX=new FP2(0); QX.bset(A,B);
-		A.rcopy(ROM.CURVE_Pya); B.rcopy(ROM.CURVE_Pyb);
-		var QY=new FP2(0); QY.bset(A,B);
-
-		var Q=new ECP2();
-		Q.setxy(QX,QY);
-
-		var sQ=ECP2.fromBytes(SST);
-		if (sQ.is_infinity()) return this.INVALID_POINT;
-
-		var R;
-		if (date!==0)
-			R=ECP.fromBytes(xCID);
-		else
-		{
-			if (xID==null) return this.BAD_PARAMS;
-			R=ECP.fromBytes(xID);
-		}
-		if (R.is_infinity()) return this.INVALID_POINT;
-
-		var y=BIG.fromBytes(Y);
-		var P;
-
-		if (date!=0) P=ECP.fromBytes(HTID);
-		else
-		{
-			if (HID==null) return this.BAD_PARAMS;
-			P=ECP.fromBytes(HID);
-		}
-		if (P.is_infinity()) return this.INVALID_POINT;
-
-		P=PAIR.G1mul(P,y);
-		P.add(R);
-		R=ECP.fromBytes(mSEC);
-		if (R.is_infinity()) return this.INVALID_POINT;
-
-		var g=PAIR.ate2(Q,R,sQ,P);
-		g=PAIR.fexp(g);
-
-		if (!g.isunity())
-		{
-			if (HID!=null && xID!=null && E!=null && F!=null)
-			{
-				g.toBytes(E);
-				if (date!==0)
-				{
-					P=ECP.fromBytes(HID);
-					if (P.is_infinity()) return this.INVALID_POINT;
-					R=ECP.fromBytes(xID);
-					if (R.is_infinity()) return this.INVALID_POINT;
-
-					P=PAIR.G1mul(P,y);
-					P.add(R);
-				}
-				g=PAIR.ate(Q,P);
-				g=PAIR.fexp(g);
-
-				g.toBytes(F);
-			}
-			return this.BAD_PIN;
-		}
-		return 0;
-	},
-
-/* Pollards kangaroos used to return PIN error */
-	KANGAROO: function(E,F)
-	{
-		var ge=FP12.fromBytes(E);
-		var gf=FP12.fromBytes(F);
-		var distance = [];
-		var t=new FP12(gf);
-		var table=[];
-		var i,j,m,s,dn,dm,res,steps;
-
-		s=1;
-		for (m=0;m<this.TS;m++)
-		{
-			distance[m]=s;
-			table[m]=new FP12(t);
-			s*=2;
-			t.usqr();
-		}
-		t.one();
-		dn=0;
-		for (j=0;j<this.TRAP;j++)
-		{
-			i=t.geta().geta().getA().lastbits(8)%this.TS;
-			t.mul(table[i]);
-			dn+=distance[i];
-		}
-		gf.copy(t); gf.conj();
-		steps=0; dm=0;
-		res=0;
-		while (dm-dn<this.MAXPIN)
-		{
-			steps++;
-			if (steps>4*this.TRAP) break;
-			i=ge.geta().geta().getA().lastbits(8)%this.TS;
-			ge.mul(table[i]);
-			dm+=distance[i];
-			if (ge.equals(t))
-			{
-				res=dm-dn;
-				break;
-			}
-			if (ge.equals(gf))
-			{
-				res=dn-dm;
-				break;
-			}
-
-		}
-		if (steps>4*this.TRAP || dm-dn>=this.MAXPIN) {res=0; }    // Trap Failed  - probable invalid token
-		return res;
-	},
-
-        /* return time  since epoch */
-	GET_TIME: function() {
-		var now=new Date();
-		return Math.floor(now.getTime()/(1000));
-	},
-
-        /* y = H(time,xCID) */
-	GET_Y: function(TimeValue,xCID,Y)
-	{
-		var q=new BIG(0);
-                q.rcopy(ROM.CURVE_Order);
-                var h=this.hashit(TimeValue,xCID);
-                var y=BIG.fromBytes(h);
-		y.mod(q);
-                y.toBytes(Y);
-                return 0;
-	},
-
-        /* One pass MPIN Client */
-	CLIENT: function(date,CLIENT_ID,rng,X,pin,TOKEN,SEC,xID,xCID,PERMIT,TimeValue,Y)
-	{
-
-                var rtn=0;
-                var pID;
-                if (date == 0) {
-                  pID = xID;
-		} else {
-                  pID = xCID;
-                  xID = null;
-		}
-
-                rtn = this.CLIENT_1(date,CLIENT_ID,rng,X,pin,TOKEN,SEC,xID,xCID,PERMIT);
-                if (rtn != 0)
-                  return rtn;
-
-                this.GET_Y(TimeValue,pID,Y);
-
-                rtn = this.CLIENT_2(X,Y,SEC);
-                if (rtn != 0)
-                  return rtn;
-
-                return 0;
-        },
-
-        /* One pass MPIN Server */
-	SERVER: function(date,HID,HTID,Y,SST,xID,xCID,mSEC,E,F,CID,TimeValue)
-        {
-                var rtn=0;
-                var pID;
-                if (date == 0) {
-                  pID = xID;
-		} else {
-                  pID = xCID;
-		}
-
-                this.SERVER_1(date,CID,HID,HTID);
-
-                this.GET_Y(TimeValue,pID,Y);
-
-                rtn = this.SERVER_2(date,HID,HTID,Y,SST,xID,xCID,mSEC,E,F);
-                if (rtn != 0)
-                  return rtn;
-
-                return 0;
-        },
-
-/* Functions to support M-Pin Full */
-
-	PRECOMPUTE: function(TOKEN,CID,G1,G2)
-	{
-		var P,T;
-		var g;
-
-		T=ECP.fromBytes(TOKEN);
-		if (T.is_infinity()) return INVALID_POINT;
-
-		P=this.mapit(CID);
-
-		var A=new BIG(0);
-		var B=new BIG(0);
-		A.rcopy(ROM.CURVE_Pxa); B.rcopy(ROM.CURVE_Pxb);
-		var QX=new FP2(0); QX.bset(A,B);
-		A.rcopy(ROM.CURVE_Pya); B.rcopy(ROM.CURVE_Pyb);
-		var QY=new FP2(0); QY.bset(A,B);
-
-		var Q=new ECP2();
-		Q.setxy(QX,QY);
-
-		g=PAIR.ate(Q,T);
-		g=PAIR.fexp(g);
-		g.toBytes(G1);
-
-		g=PAIR.ate(Q,P);
-		g=PAIR.fexp(g);
-		g.toBytes(G2);
-
-		return 0;
-	},
-
-/* calculate common key on client side */
-/* wCID = w.(A+AT) */
-	CLIENT_KEY: function(G1,G2,pin,R,X,wCID,CK)
-	{
-		var H=new HASH();
-		var t=[];
-
-		var g1=FP12.fromBytes(G1);
-		var g2=FP12.fromBytes(G2);
-		var z=BIG.fromBytes(R);
-		var x=BIG.fromBytes(X);
-
-		var W=ECP.fromBytes(wCID);
-		if (W.is_infinity()) return INVALID_POINT;
-
-		W=PAIR.G1mul(W,x);
-
-		var fa=new BIG(0); fa.rcopy(ROM.CURVE_Fra);
-		var fb=new BIG(0); fb.rcopy(ROM.CURVE_Frb);
-		var f=new FP2(fa,fb); //f.bset(fa,fb);
-
-		var r=new BIG(0); r.rcopy(ROM.CURVE_Order);
-		var q=new BIG(0); q.rcopy(ROM.Modulus);
-
-		var m=new BIG(q);
-		m.mod(r);
-
-		var a=new BIG(z);
-		a.mod(m);
-
-		var b=new BIG(z);
-		b.div(m);
-
-		g2.pinpow(pin,this.PBLEN);
-		g1.mul(g2);
-
-		var c=g1.trace();
-		g2.copy(g1);
-		g2.frob(f);
-		var cp=g2.trace();
-		g1.conj();
-		g2.mul(g1);
-		var cpm1=g2.trace();
-		g2.mul(g1);
-		var cpm2=g2.trace();
-
-		c=c.xtr_pow2(cp,cpm1,cpm2,a,b);
-
-		c.geta().getA().toBytes(t);
-		H.process_array(t);
-		c.geta().getB().toBytes(t);
-		H.process_array(t);
-		c.getb().getA().toBytes(t);
-		H.process_array(t);
-		c.getb().getB().toBytes(t);
-		H.process_array(t);
-
-		W.getX().toBytes(t);
-		H.process_array(t);
-		W.getY().toBytes(t);
-		H.process_array(t);
-
-		t=H.hash();
-		for (var i=0;i<this.PAS;i++) CK[i]=t[i];
-
-		return 0;
-	},
-
-/* calculate common key on server side */
-/* Z=r.A - no time permits involved */
-
-	SERVER_KEY: function(Z,SST,W,xID,xCID,SK)
-	{
-		var H=new HASH();
-		var t=[];
-
-		var sQ=ECP2.fromBytes(SST);
-		if (sQ.is_infinity()) return INVALID_POINT;
-		var R=ECP.fromBytes(Z);
-		if (R.is_infinity()) return INVALID_POINT;
-
-		var U;
-		if (xCID!=null)
-			U=ECP.fromBytes(xCID);
-		else
-			U=ECP.fromBytes(xID);
-		if (U.is_infinity()) return INVALID_POINT;
-
-		var w=BIG.fromBytes(W);
-		U=PAIR.G1mul(U,w);
-		var g=PAIR.ate(sQ,R);
-		g=PAIR.fexp(g);
-
-		var c=g.trace();
-		c.geta().getA().toBytes(t);
-		H.process_array(t);
-		c.geta().getB().toBytes(t);
-		H.process_array(t);
-		c.getb().getA().toBytes(t);
-		H.process_array(t);
-		c.getb().getB().toBytes(t);
-		H.process_array(t);
-
-		U.getX().toBytes(t);
-		H.process_array(t);
-		U.getY().toBytes(t);
-		H.process_array(t);
-
-		t=H.hash();
-		for (var i=0;i<this.PAS;i++) SK[i]=t[i];
-
-		return 0;
-	}
-};
diff --git a/js/MPINAuth.js b/js/MPINAuth.js
deleted file mode 100755
index 7cacb65..0000000
--- a/js/MPINAuth.js
+++ /dev/null
@@ -1,517 +0,0 @@
-/*
-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.
-*/
-
-/*
-   MIRACL JavaScript M-Pin Authentication Functions
-
-   Provides these functions:
-
-   calculateMPinToken     Calculates the MPin Token
-
-   getLocalEntropy        Gets an entropy value from the client machine
-
-   initializeRNG          Initialize the Random Number Generator
-
-   addShares              Add two points on the curve that are originally in hex format
-
-   pass1Request           Form the JSON request for pass one of the M-Pin protocol
-
-   pass2Request           Form the JSON request for pass two of the M-Pin protocol
-
-   passRequest      Form the JSON request for one pass M-Pin protocol
-
-*/
-
-/*
-
-Run LINT tool;
-
-jslint MPINAuth.js
-
-expected output;
-
-MPINAuth.js
- #1 Read only.
-    MPINAuth = {}; // Line 61, Pos 1
- #2 Unexpected '('.
-    if (typeof (window) === 'undefined') { // Line 134, Pos 16
- #3 Unexpected 'typeof'. Use '===' to compare directly with undefined.
-    if (typeof (window) === 'undefined') { // Line 134, Pos 9
- #4 Unexpected '('.
-    if (typeof (crypto) !== 'undefined') { // Line 139, Pos 16
- #5 Unexpected 'typeof'. Use '===' to compare directly with undefined.
-    if (typeof (crypto) !== 'undefined') { // Line 139, Pos 9
-
-*/
-
-
-/*global MPIN */
-/*global MPINAuth */
-/*global RAND */
-/*global Uint32Array */
-/*jslint browser: true*/
-/*jslint plusplus: true */
-
-MPINAuth = {};
-
-// Random Number Generator
-MPINAuth.rng = new RAND();
-
-// Pass 1 values
-MPINAuth.SEC = [];
-MPINAuth.X = [];
-
-// Default value for debug output
-MPINAuth.DEBUG = false;
-
-// Errors
-MPINAuth.BAD_HEX = -20;
-MPINAuth.BAD_BYTES = -21;
-
-/* Calculates the MPin Token
-
-   This function convert mpin_id _hex to unicode. It then maps the mpin_id
-   to a point on the curve, multiplies this value by PIN and then subtracts
-   it from the client_secret curve point to generate the M-Pin token.
-
-   Args:
-
-     PIN: Four digit PIN
-     client_secret_hex: Hex encoded client secret
-     mpin_id_hex: Hex encoded M-Pin ID
-
-   Returns:
-
-     mpin_token_hex: Hex encoded M-Pin Token
-
-*/
-MPINAuth.calculateMPinToken = function (mpin_id_hex, PIN, client_secret_hex) {
-    "use strict";
-    var client_secret_bytes, mpin_id_bytes, token_hex, error_code;
-
-    client_secret_bytes = [];
-    mpin_id_bytes = [];
-
-    if (MPINAuth.DEBUG) {console.log("MPINAuth.calculateMPinToken client_secret_hex: " + client_secret_hex); }
-    if (MPINAuth.DEBUG) {console.log("MPINAuth.calculateMPinToken mpin_id_hex: " + mpin_id_hex); }
-    if (MPINAuth.DEBUG) {console.log("MPINAuth.calculateMPinToken PIN: " + PIN); }
-
-    client_secret_bytes = MPINAuth.hextobytes(client_secret_hex);
-    mpin_id_bytes = MPINAuth.hextobytes(mpin_id_hex);
-
-    error_code = MPIN.EXTRACT_PIN(mpin_id_bytes, PIN, client_secret_bytes);
-    if (error_code !== 0) {
-        console.log("MPINAuth.calculateMPinToken error_code: " + error_code);
-        return error_code;
-    }
-    token_hex = MPIN.bytestostring(client_secret_bytes);
-    if (MPINAuth.DEBUG) {console.log("MPINAuth.calculateMPinToken token_hex: " + token_hex); }
-    return token_hex;
-};
-
-/* Get local entropy
-
-   This function makes a call to /dev/urandom for a 256 bit value
-
-   Args:
-
-     NA
-
-   Returns:
-
-     entropy_val: 256 bit random value or null
-
-*/
-MPINAuth.getLocalEntropy = function () {
-    "use strict";
-    var crypto, array, entropy_val, i, hex_val;
-    if (typeof (window) === 'undefined') {
-        if (MPINAuth.DEBUG) {console.log("MPINAuth.getLocalEntropy Test mode without browser"); }
-        return "";
-    }
-    crypto = (window.crypto || window.msCrypto);
-    if (typeof (crypto) !== 'undefined') {
-        array = new Uint32Array(8);
-        crypto.getRandomValues(array);
-
-        entropy_val = "";
-        for (i = 0; i < array.length; i++) {
-            hex_val = array[i].toString(16);
-            entropy_val = entropy_val + hex_val;
-        }
-        if (MPINAuth.DEBUG) {console.log("MPINAuth.getLocalEntropy len(entropy_val): " + entropy_val.length + " entropy_val: " + entropy_val); }
-        return entropy_val;
-    }
-    return "";
-};
-
-/* Initialize the Random Number Generator (RNG)
-
-   This function uses an external and, where available, a
-   local entropy source to initialize a RNG.
-
-   Args:
-
-     seed_value: External seed value for RNGTurn on generation of local entropy
-
-   Returns:
-
-*/
-MPINAuth.initializeRNG = function (seed_hex) {
-    "use strict";
-    var local_entropy_hex, entropy_hex, entropy_bytes;
-    local_entropy_hex = MPINAuth.getLocalEntropy();
-    entropy_hex = local_entropy_hex + seed_hex;
-    if (MPINAuth.DEBUG) {console.log("MPINAuth.initializeRNG seed_val_hex: " + seed_hex); }
-    if (MPINAuth.DEBUG) {console.log("MPINAuth.initializeRNG local_entropy_hex: " + local_entropy_hex); }
-    if (MPINAuth.DEBUG) {console.log("MPINAuth.initializeRNG entropy_hex: " + entropy_hex); }
-
-    entropy_bytes = MPINAuth.hextobytes(entropy_hex);
-
-    MPINAuth.rng.clean();
-    MPINAuth.rng.seed(entropy_bytes.length, entropy_bytes);
-};
-
-/* Add two points on the curve that are originally in hex format
-
-   This function is used to add client secret or time permits shares.
-
-   Args:
-
-     share1_hex: Hex encoded point on the curve which represents
-                 a time permit or client secret share
-     share2_hex: Hex encoded point on the curve which represents
-                 a time permit or client secret share
-
-   Returns:
-
-     sum_hex: Hex encoded sum of the shares
-
-*/
-MPINAuth.addShares = function (share1_hex, share2_hex) {
-    "use strict";
-    var share1_bytes, share2_bytes, sum_bytes, error_code, sum_hex;
-
-    share1_bytes = [];
-    share2_bytes = [];
-    sum_bytes = [];
-
-    if (MPINAuth.DEBUG) {console.log("MPINAuth.addShares share1_hex: " + share1_hex); }
-    if (MPINAuth.DEBUG) {console.log("MPINAuth.addShares share2_hex: " + share2_hex); }
-
-    share1_bytes = MPINAuth.hextobytes(share1_hex);
-    share2_bytes = MPINAuth.hextobytes(share2_hex);
-
-    error_code = MPIN.RECOMBINE_G1(share1_bytes, share2_bytes, sum_bytes);
-    if (error_code !== 0) {
-        console.log("MPINAuth.addShares error_code: " + error_code);
-        return error_code;
-    }
-    sum_hex = MPIN.bytestostring(sum_bytes);
-    if (MPINAuth.DEBUG) {console.log("MPINAuth.addShares sum_hex: " + sum_hex); }
-    return sum_hex;
-};
-
-
-/* Form the JSON request for pass one of the M-Pin protocol
-
-   This function assigns to the property X a random value. It assigns to
-   the property SEC the sum of the client secret and time permit. It also
-   calculates the values U and UT which are required for M-Pin authentication,
-   where U = X.(map_to_curve(MPIN_ID)) and UT = X.(map_to_curve(MPIN_ID) + map_to_curve(DATE|sha256(MPIN_ID))
-   UT is called the commitment. U is the required for finding the PIN error.
-
-   Args:
-
-     mpin_id_hex: Hex encoded M-Pin ID
-     token_hex: Hex encoded M-Pin Token
-     timePermit_hex: Hex encoded Time Permit
-     PIN: PIN for authentication
-     epoch_days: The number of epoch days.
-     X_hex: X value generated externally. This is used for test.
-
-   Returns:
-
-    {
-      mpin_id: mpin_id_hex,
-      UT: UT_hex,
-      U: U_hex,
-      pass: 1
-    }
-
-    where;
-
-    mpin_id: Hex encoded M-Pin ID
-    UT: Hex encoded X.(map_to_curve(MPIN_ID) + map_to_curve(DATE|sha256(MPIN_ID))
-    U: Hex encoded X.(map_to_curve(MPIN_ID))
-    pass: Protocol first pass
-
-*/
-MPINAuth.pass1Request = function (mpin_id_hex, token_hex, timePermit_hex, PIN, epoch_days, X_hex) {
-    "use strict";
-    var UT_hex, U_hex, date, error_code, mpin_id_bytes, token_bytes, timePermit_bytes, U, UT, request;
-
-    mpin_id_bytes = [];
-    token_bytes = [];
-    timePermit_bytes = [];
-    U = [];
-    UT = [];
-    request = {};
-
-    if (MPINAuth.DEBUG) {console.log("MPINAuth.pass1Request mpin_id_hex: " + mpin_id_hex); }
-    if (MPINAuth.DEBUG) {console.log("MPINAuth.pass1Request token_hex: " + token_hex); }
-    if (MPINAuth.DEBUG) {console.log("MPINAuth.pass1Request timePermit_hex: " + timePermit_hex); }
-    if (MPINAuth.DEBUG) {console.log("MPINAuth.pass1Request PIN: " + PIN); }
-    if (MPINAuth.DEBUG) {console.log("mpinAuth.pass1Request epoch_days: " + epoch_days); }
-
-    // The following is used for test
-    if (X_hex !== null) {
-        if (MPINAuth.DEBUG) {console.log("MPINAuth.pass1Request X: " + X_hex); }
-        MPINAuth.X = MPINAuth.hextobytes(X_hex);
-        MPINAuth.rng = null;
-    }
-
-    mpin_id_bytes = MPINAuth.hextobytes(mpin_id_hex);
-    token_bytes = MPINAuth.hextobytes(token_hex);
-    timePermit_bytes = MPINAuth.hextobytes(timePermit_hex);
-
-    error_code = MPIN.CLIENT_1(epoch_days, mpin_id_bytes, MPINAuth.rng, MPINAuth.X, PIN, token_bytes, MPINAuth.SEC, U, UT, timePermit_bytes);
-    if (error_code !== 0) {
-        console.log("MPINAuth.pass1Request error_code: " + error_code);
-        return error_code;
-    }
-    UT_hex = MPIN.bytestostring(UT);
-    U_hex = MPIN.bytestostring(U);
-
-    if (MPINAuth.DEBUG) {console.log("MPINAuth.pass1Request MPINAuth.rng: " + MPINAuth.rng); }
-    if (MPINAuth.DEBUG) {console.log("MPINAuth.pass1Request MPINAuth.X: " + MPIN.bytestostring(MPINAuth.X)); }
-    if (MPINAuth.DEBUG) {console.log("MPINAuth.pass1Request MPINAuth.SEC: " + MPIN.bytestostring(MPINAuth.SEC)); }
-
-    // Form request
-    request = {
-        mpin_id: mpin_id_hex,
-        UT: UT_hex,
-        U: U_hex,
-        pass: 1
-    };
-    if (MPINAuth.DEBUG) {console.log("MPINAuth.pass1Request request: "); }
-    if (MPINAuth.DEBUG) {console.dir(request); }
-
-    return request;
-};
-
-
-/* Form the JSON request for pass two of the M-Pin protocol
-
-   This function uses the random value y from the server, property X
-   and the combined client secret and time permit to calculate
-   the value V which is sent to the M-Pin server.
-
-   Args:
-
-     y_hex: Random value supplied by server
-
-   Returns:
-
-    {
-      V: V_hex,
-      OTP: requestOTP,
-      WID: accessNumber,
-      pass: 2
-    }
-
-    where;
-
-    V: Value required by the server to authenticate user
-    OTP: Request OTP: 1 = required
-    WID: Number required for mobile authentication
-    pass: Protocol second pass
-
-*/
-MPINAuth.pass2Request = function (y_hex, requestOTP, accessNumber) {
-    "use strict";
-
-    var y_bytes, x_hex, SEC_hex, error_code, V_hex, request;
-
-    request = {};
-
-    y_bytes = MPINAuth.hextobytes(y_hex);
-    x_hex = MPIN.bytestostring(MPINAuth.X);
-    SEC_hex = MPIN.bytestostring(MPINAuth.SEC);
-
-    if (MPINAuth.DEBUG) {console.log("MPINAuth.pass2Request x_hex: " + x_hex); }
-    if (MPINAuth.DEBUG) {console.log("MPINAuth.pass2Request y_hex: " + y_hex); }
-    if (MPINAuth.DEBUG) {console.log("MPINAuth.pass2Request SEC_hex: " + SEC_hex); }
-
-    // Compute V
-    error_code = MPIN.CLIENT_2(MPINAuth.X, y_bytes, MPINAuth.SEC);
-    if (error_code !== 0) {
-        console.log("MPINAuth.pass2Request error_code: " + error_code);
-        return error_code;
-    }
-    V_hex = MPIN.bytestostring(MPINAuth.SEC);
-
-    // Form reuest
-    request = {
-        V: V_hex,
-        OTP: requestOTP,
-        WID: accessNumber,
-        pass: 2
-    };
-    if (MPINAuth.DEBUG) {console.log("MPINAuth.pass2Request request: "); }
-    if (MPINAuth.DEBUG) {console.dir(request); }
-
-    return request;
-};
-
-
-/* Convert a hex representation of a Point to bytes
-
-   This function converts a hex value to a bytes array
-
-   Args:
-
-     hex_value: Hex encoded byte value
-
-   Returns:
-
-     byte_value: Input value in bytes
-
-*/
-MPINAuth.hextobytes = function (value_hex) {
-    "use strict";
-    var len, byte_value, i;
-
-    len = value_hex.length;
-    byte_value = [];
-
-    for (i = 0; i < len; i += 2) {
-        byte_value[(i / 2)] = parseInt(value_hex.substr(i, 2), 16);
-    }
-    return byte_value;
-};
-
-
-/* Form the JSON request for single pass M-Pin protocol
-
-   This function performs the client side M-Pin protocol
-   It also  calculates the values U and UT which are required for M-Pin authentication,
-   where U = X.(map_to_curve(MPIN_ID)) and UT = X.(map_to_curve(MPIN_ID) + map_to_curve(DATE|sha256(MPIN_ID))
-   UT is called the commitment. U is the required for finding the PIN error.
-
-   Args:
-
-     mpin_id_hex: Hex encoded M-Pin ID
-     token_hex: Hex encoded M-Pin Token
-     timePermit_hex: Hex encoded Time Permit
-     PIN: PIN for authentication
-     requestOTP: Reqeuest a One Time Password
-     accessNumber: Access number for desktop authentication
-     timeValue: Epoch time
-
-   Returns:
-
-    {
-      mpin_id: mpin_id_hex,
-      U: U_hex,
-      UT: UT_hex,
-      V: V_hex,
-      T: timeValue,
-      OTP: requestOTP,
-      WID: accessNumber
-    }
-
-    where;
-
-    mpin_id: Hex encoded M-Pin ID
-    U: Hex encoded X.(map_to_curve(MPIN_ID))
-    UT: Hex encoded X.(map_to_curve(MPIN_ID) + map_to_curve(DATE|sha256(MPIN_ID))
-    V: Value required by the server to authenticate user
-    T: Epoch time
-    OTP: Request OTP: 1 = required
-    WID: Number required for mobile authentication
-
-*/
-MPINAuth.passRequest = function (mpin_id_hex, token_hex, timePermit_hex, PIN, requestOTP, accessNumber, epoch_days, timeValue, X_hex) {
-    "use strict";
-    var X, Y, SEC, UT_hex, U_hex, date, error_code, mpin_id_bytes, token_bytes, timePermit_bytes, U, UT, V_hex, request;
-
-    X = [];
-    Y = [];
-    SEC = [];
-    mpin_id_bytes = [];
-    token_bytes = [];
-    timePermit_bytes = [];
-    U = [];
-    UT = [];
-    request = {};
-
-    if (MPINAuth.DEBUG) {console.log("MPINAuth.passRequest mpin_id_hex: " + mpin_id_hex); }
-    if (MPINAuth.DEBUG) {console.log("MPINAuth.passRequest token_hex: " + token_hex); }
-    if (MPINAuth.DEBUG) {console.log("MPINAuth.passRequest timePermit_hex: " + timePermit_hex); }
-    if (MPINAuth.DEBUG) {console.log("MPINAuth.passRequest PIN: " + PIN); }
-    if (MPINAuth.DEBUG) {console.log("mpinAuth.passRequest timeValue: " + timeValue); }
-
-    mpin_id_bytes = MPINAuth.hextobytes(mpin_id_hex);
-    token_bytes = MPINAuth.hextobytes(token_hex);
-
-    if (timePermit_hex === null) {
-        date = 0;
-    } else {
-        timePermit_bytes = MPINAuth.hextobytes(timePermit_hex);
-        date = epoch_days;
-    }
-    if (MPINAuth.DEBUG) {console.log("MPINAuth.passRequest date: " + date); }
-
-    // The following is used for test
-    if (MPINAuth.DEBUG) {console.log("MPINAuth.passRequest X: " + X_hex); }
-    if (X_hex !== null) {
-        X = MPINAuth.hextobytes(X_hex);
-        MPINAuth.rng = null;
-    }
-
-    error_code = MPIN.CLIENT(date, mpin_id_bytes, MPINAuth.rng, X, PIN, token_bytes, SEC, U, UT, timePermit_bytes, timeValue, Y);
-    if (error_code !== 0) {
-        console.log("MPINAuth.passRequest error_code: " + error_code);
-        return error_code;
-    }
-    UT_hex = MPIN.bytestostring(UT);
-    U_hex = MPIN.bytestostring(U);
-    V_hex = MPIN.bytestostring(SEC);
-
-    if (MPINAuth.DEBUG) {console.log("MPINAuth.passRequest MPINAuth.rng: " + MPINAuth.rng); }
-    if (MPINAuth.DEBUG) {console.log("MPINAuth.passRequest X: " + MPIN.bytestostring(X)); }
-    if (MPINAuth.DEBUG) {console.log("MPINAuth.passRequest Y: " + MPIN.bytestostring(Y)); }
-
-    // Form request
-    request = {
-        mpin_id: mpin_id_hex,
-        U: U_hex,
-        UT: UT_hex,
-        V: V_hex,
-        T: timeValue,
-        OTP: requestOTP,
-        WID: accessNumber
-    };
-    if (MPINAuth.DEBUG) {console.log("MPINAuth.passRequest request: "); }
-    if (MPINAuth.DEBUG) {console.dir(request); }
-
-    return request;
-};
-
diff --git a/js/PAIR.js b/js/PAIR.js
deleted file mode 100755
index e3a0628..0000000
--- a/js/PAIR.js
+++ /dev/null
@@ -1,506 +0,0 @@
-/*
-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.
-*/
-
-var PAIR = {
-/* Line function */
-	line: function(A,B,Qx,Qy)
-	{
-		var P=new ECP2();
-		var a,b,c;
-		var r=new FP12(1);
-		P.copy(A);
-
-		var ZZ=new FP2(P.getz()); //ZZ.copy(P.getz());
-		ZZ.sqr();
-		var D;
-		if (A==B) D=A.dbl();
-		else D=A.add(B);
-		if (D<0) return r;
-		var Z3=new FP2(A.getz()); //Z3.copy(A.getz());
-		c=new FP4(0);
-		var X,Y,T;
-		if (D===0)
-		{ /* Addition */
-			X=new FP2(B.getx()); //X.copy(B.getx());
-			Y=new FP2(B.gety()); //Y.copy(B.gety());
-			T=new FP2(P.getz()); //T.copy(P.getz());
-
-			T.mul(Y);
-			ZZ.mul(T);
-
-			var NY=new FP2(P.gety()); /*NY.copy(P.gety());*/ NY.neg();
-			ZZ.add(NY);
-			Z3.pmul(Qy);
-			T.mul(P.getx());
-			X.mul(NY);
-			T.add(X);
-			a=new FP4(Z3,T); //a.set(Z3,T);
-			ZZ.neg();
-			ZZ.pmul(Qx);
-			b=new FP4(ZZ); //b.seta(ZZ);
-		}
-		else
-		{ /* Doubling */
-			X=new FP2(P.getx()); //X.copy(P.getx());
-			Y=new FP2(P.gety()); //Y.copy(P.gety());
-			T=new FP2(P.getx()); //T.copy(P.getx());
-			T.sqr();
-			T.imul(3);
-
-			Y.sqr();
-			Y.add(Y);
-			Z3.mul(ZZ);
-			Z3.pmul(Qy);
-
-			X.mul(T);
-			X.sub(Y);
-			a=new FP4(Z3,X); //a.set(Z3,X);
-			T.neg();
-			ZZ.mul(T);
-
-			ZZ.pmul(Qx);
-
-			b=new FP4(ZZ); //b.seta(ZZ);
-		}
-		r.set(a,b,c);
-		return r;
-	},
-
-/* Optimal R-ate pairing */
-	ate: function(P,Q)
-	{
-		var fa=new BIG(0); fa.rcopy(ROM.CURVE_Fra);
-		var fb=new BIG(0); fb.rcopy(ROM.CURVE_Frb);
-		var f=new FP2(fa,fb); //f.bset(fa,fb);
-
-		var x=new BIG(0); x.rcopy(ROM.CURVE_Bnx);
-		var n=new BIG(x); //n.copy(x);
-		var K=new ECP2();
-		var lv;
-		n.pmul(6); n.dec(2); n.norm();
-		P.affine();
-		Q.affine();
-		var Qx=new FP(Q.getx()); //Qx.copy(Q.getx());
-		var Qy=new FP(Q.gety()); //Qy.copy(Q.gety());
-
-		var A=new ECP2();
-		var r=new FP12(1);
-
-		A.copy(P);
-		var nb=n.nbits();
-
-		for (var i=nb-2;i>=1;i--)
-		{
-			lv=PAIR.line(A,A,Qx,Qy);
-
-			r.smul(lv);
-
-			if (n.bit(i)==1)
-			{
-				lv=PAIR.line(A,P,Qx,Qy);
-				r.smul(lv);
-			}
-			r.sqr();
-		}
-		lv=PAIR.line(A,A,Qx,Qy);
-		r.smul(lv);
-
-/* R-ate fixup */
-		r.conj();
-		K.copy(P);
-		K.frob(f);
-		A.neg();
-		lv=PAIR.line(A,K,Qx,Qy);
-		r.smul(lv);
-		K.frob(f);
-		K.neg();
-		lv=PAIR.line(A,K,Qx,Qy);
-		r.smul(lv);
-
-		return r;
-	},
-
-/* Optimal R-ate double pairing e(P,Q).e(R,S) */
-	ate2: function(P,Q,R,S)
-	{
-		var fa=new BIG(0); fa.rcopy(ROM.CURVE_Fra);
-		var fb=new BIG(0); fb.rcopy(ROM.CURVE_Frb);
-		var f=new FP2(fa,fb); //f.bset(fa,fb);
-		var x=new BIG(0); x.rcopy(ROM.CURVE_Bnx);
-
-		var n=new BIG(x); //n.copy(x);
-		var K=new ECP2();
-		var lv;
-		n.pmul(6); n.dec(2); n.norm();
-		P.affine();
-		Q.affine();
-		R.affine();
-		S.affine();
-
-		var Qx=new FP(Q.getx()); //Qx.copy(Q.getx());
-		var Qy=new FP(Q.gety()); //Qy.copy(Q.gety());
-
-		var Sx=new FP(S.getx()); //Sx.copy(S.getx());
-		var Sy=new FP(S.gety()); //Sy.copy(S.gety());
-
-		var A=new ECP2();
-		var B=new ECP2();
-		var r=new FP12(1);
-
-		A.copy(P);
-		B.copy(R);
-		var nb=n.nbits();
-
-		for (var i=nb-2;i>=1;i--)
-		{
-			lv=PAIR.line(A,A,Qx,Qy);
-			r.smul(lv);
-			lv=PAIR.line(B,B,Sx,Sy);
-			r.smul(lv);
-			if (n.bit(i)==1)
-			{
-				lv=PAIR.line(A,P,Qx,Qy);
-				r.smul(lv);
-				lv=PAIR.line(B,R,Sx,Sy);
-				r.smul(lv);
-			}
-			r.sqr();
-		}
-
-		lv=PAIR.line(A,A,Qx,Qy);
-		r.smul(lv);
-
-		lv=PAIR.line(B,B,Sx,Sy);
-		r.smul(lv);
-
-
-/* R-ate fixup */
-		r.conj();
-
-		K.copy(P);
-		K.frob(f);
-		A.neg();
-		lv=PAIR.line(A,K,Qx,Qy);
-		r.smul(lv);
-		K.frob(f);
-		K.neg();
-		lv=PAIR.line(A,K,Qx,Qy);
-		r.smul(lv);
-
-		K.copy(R);
-		K.frob(f);
-		B.neg();
-		lv=PAIR.line(B,K,Sx,Sy);
-		r.smul(lv);
-		K.frob(f);
-		K.neg();
-		lv=PAIR.line(B,K,Sx,Sy);
-		r.smul(lv);
-
-		return r;
-	},
-
-/* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */
-	fexp: function(m)
-	{
-		var fa=new BIG(0); fa.rcopy(ROM.CURVE_Fra);
-		var fb=new BIG(0); fb.rcopy(ROM.CURVE_Frb);
-		var f=new FP2(fa,fb);
-		var x=new BIG(0); x.rcopy(ROM.CURVE_Bnx);
-
-		var r=new FP12(m); //r.copy(m);
-		var x0,x1,x2,x3,x4,x5;
-
-/* Easy part of final exp */
-		var lv=new FP12(r); //lv.copy(r);
-		lv.inverse();
-		r.conj();
-		r.mul(lv);
-		lv.copy(r);
-		r.frob(f);
-		r.frob(f);
-		r.mul(lv);
-
-/* Hard part of final exp */
-		lv.copy(r);
-		lv.frob(f);
-		x0=new FP12(lv); //x0.copy(lv);
-		x0.frob(f);
-		lv.mul(r);
-		x0.mul(lv);
-		x0.frob(f);
-		x1=new FP12(r); //x1.copy(r);
-		x1.conj();
-
-		x4=r.pow(x);
-
-		x3=new FP12(x4); //x3.copy(x4);
-		x3.frob(f);
-		x2=x4.pow(x);
-
-		x5=new FP12(x2); /*x5.copy(x2);*/  x5.conj();
-		lv=x2.pow(x);
-
-		x2.frob(f);
-		r.copy(x2); r.conj();
-
-		x4.mul(r);
-		x2.frob(f);
-
-		r.copy(lv);
-		r.frob(f);
-		lv.mul(r);
-
-		lv.usqr();
-		lv.mul(x4);
-		lv.mul(x5);
-		r.copy(x3);
-		r.mul(x5);
-		r.mul(lv);
-		lv.mul(x2);
-		r.usqr();
-		r.mul(lv);
-		r.usqr();
-		lv.copy(r);
-		lv.mul(x1);
-		r.mul(x0);
-		lv.usqr();
-		r.mul(lv);
-		r.reduce();
-		return r;
-	}
-};
-
-/* GLV method */
-PAIR.glv= function(e)
-{
-	var i,j;
-	var t=new BIG(0);
-	var q=new BIG(0); q.rcopy(ROM.CURVE_Order);
-	var u=[];
-	var v=[];
-	for (i=0;i<2;i++)
-	{
-		t.rcopy(ROM.CURVE_W[i]);
-		var d=BIG.mul(t,e);
-		v[i]=new BIG(d.div(q));
-		u[i]=new BIG(0);
-	}
-	u[0].copy(e);
-	for (i=0;i<2;i++)
-		for (j=0;j<2;j++)
-		{
-			t.rcopy(ROM.CURVE_SB[j][i]);
-			t.copy(BIG.modmul(v[j],t,q));
-			u[i].add(q);
-			u[i].sub(t);
-			u[i].mod(q);
-		}
-	return u;
-};
-
-/* Galbraith & Scott Method */
-PAIR.gs= function(e)
-{
-	var i,j;
-	var t=new BIG(0);
-	var q=new BIG(0); q.rcopy(ROM.CURVE_Order);
-	var u=[];
-	var v=[];
-
-	for (i=0;i<4;i++)
-	{
-		t.rcopy(ROM.CURVE_WB[i]);
-		var d=BIG.mul(t,e);
-		v[i]=new BIG(d.div(q));
-		u[i]=new BIG(0);
-	}
-
-	u[0].copy(e);
-	for (i=0;i<4;i++)
-		for (j=0;j<4;j++)
-		{
-			t.rcopy(ROM.CURVE_BB[j][i]);
-			t.copy(BIG.modmul(v[j],t,q));
-			u[i].add(q);
-			u[i].sub(t);
-			u[i].mod(q);
-		}
-	return u;
-};
-
-/* Multiply P by e in group G1 */
-PAIR.G1mul= function(P,e)
-{
-	var R;
-	if (ROM.USE_GLV)
-	{
-		P.affine();
-		R=new ECP();
-		R.copy(P);
-		var np,nn;
-		var Q=new ECP();
-		Q.copy(P);
-		var q=new BIG(0); q.rcopy(ROM.CURVE_Order);
-		var bcru=new BIG(0); bcru.rcopy(ROM.CURVE_Cru);
-		var cru=new FP(bcru);
-		var t=new BIG(0);
-		var u=PAIR.glv(e);
-		Q.getx().mul(cru);
-
-		np=u[0].nbits();
-		t.copy(BIG.modneg(u[0],q));
-		nn=t.nbits();
-		if (nn<np)
-		{
-			u[0].copy(t);
-			R.neg();
-		}
-
-		np=u[1].nbits();
-		t.copy(BIG.modneg(u[1],q));
-		nn=t.nbits();
-		if (nn<np)
-		{
-			u[1].copy(t);
-			Q.neg();
-		}
-
-		R=R.mul2(u[0],Q,u[1]);
-
-	}
-	else
-	{
-		R=P.mul(e);
-	}
-	return R;
-};
-
-/* Multiply P by e in group G2 */
-PAIR.G2mul= function(P,e)
-{
-	var R;
-	if (ROM.USE_GS_G2)
-	{
-		var Q=[];
-		var fa=new BIG(0); fa.rcopy(ROM.CURVE_Fra);
-		var fb=new BIG(0); fb.rcopy(ROM.CURVE_Frb);
-		var f=new FP2(fa,fb); //f.bset(fa,fb);
-		var q=new BIG(0); q.rcopy(ROM.CURVE_Order);
-
-		var u=PAIR.gs(e);
-		var t=new BIG(0);
-		var i,np,nn;
-		P.affine();
-		Q[0]=new ECP2(); Q[0].copy(P);
-		for (i=1;i<4;i++)
-		{
-			Q[i]=new ECP2(); Q[i].copy(Q[i-1]);
-			Q[i].frob(f);
-		}
-
-		for (i=0;i<4;i++)
-		{
-			np=u[i].nbits();
-			t.copy(BIG.modneg(u[i],q));
-			nn=t.nbits();
-			if (nn<np)
-			{
-				u[i].copy(t);
-				Q[i].neg();
-			}
-		}
-
-		R=ECP2.mul4(Q,u);
-	}
-	else
-	{
-		R=P.mul(e);
-	}
-	return R;
-};
-
-/* Note that this method requires a lot of RAM! Better to use compressed XTR method, see FP4.js */
-PAIR.GTpow= function(d,e)
-{
-	var r;
-	if (ROM.USE_GS_GT)
-	{
-		var g=[];
-		var fa=new BIG(0); fa.rcopy(ROM.CURVE_Fra);
-		var fb=new BIG(0); fb.rcopy(ROM.CURVE_Frb);
-		var f=new FP2(fa,fb);
-		var q=new BIG(0); q.rcopy(ROM.CURVE_Order);
-		var t=new BIG(0);
-		var i,np,nn;
-		var u=PAIR.gs(e);
-
-		g[0]=new FP12(d);
-		for (i=1;i<4;i++)
-		{
-			g[i]=new FP12(0); g[i].copy(g[i-1]);
-			g[i].frob(f);
-		}
-		for (i=0;i<4;i++)
-		{
-			np=u[i].nbits();
-			t.copy(BIG.modneg(u[i],q));
-			nn=t.nbits();
-			if (nn<np)
-			{
-				u[i].copy(t);
-				g[i].conj();
-			}
-		}
-		r=FP12.pow4(g,u);
-	}
-	else
-	{
-		r=d.pow(e);
-	}
-	return r;
-};
-
-/* test group membership */
-/* with GT-Strong curve, now only check that m!=1, conj(m)*m==1, and m.m^{p^4}=m^{p^2} */
-PAIR.GTmember= function(m)
-{
-	if (m.isunity()) return false;
-	var r=new FP12(m);
-	r.conj();
-	r.mul(m);
-	if (!r.isunity()) return false;
-
-	var fa=new BIG(0); fa.rcopy(ROM.CURVE_Fra);
-	var fb=new BIG(0); fb.rcopy(ROM.CURVE_Frb);
-	var f=new FP2(fa,fb); //f.bset(fa,fb);
-
-	r.copy(m); r.frob(f); r.frob(f);
-	var w=new FP12(r); w.frob(f); w.frob(f);
-	w.mul(m);
-	if (!ROM.GT_STRONG)
-	{
-		if (!w.equals(r)) return false;
-		var x=new BIG(0); x.rcopy(ROM.CURVE_Bnx);
-		r.copy(m); w=r.pow(x); w=w.pow(x);
-		r.copy(w); r.sqr(); r.mul(w); r.sqr();
-		w.copy(m); w.frob(f);
-	}
-	return w.equals(r);
-};
diff --git a/js/RAND.js b/js/RAND.js
deleted file mode 100755
index 30b63d9..0000000
--- a/js/RAND.js
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
-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.
-*/
-
-/*
- *   Cryptographic strong random number generator
- *
- *   Unguessable seed -> SHA -> PRNG internal state -> SHA -> random numbers
- *   Slow - but secure
- *
- *   See ftp://ftp.rsasecurity.com/pub/pdfs/bull-1.pdf for a justification
- */
-
-/* Marsaglia & Zaman Random number generator constants */
-
-
-var RAND=function()
-{
-/* Cryptographically strong pseudo-random number generator */
-	this.ira=[]; /* random number...   */
-	this.rndptr=0;  /* ...array & pointer */
-	this.borrow=0;
-	this.pool_ptr=0;
-	this.pool=[]; /* random pool */
-	this.clean();
-};
-
-RAND.prototype=
-{
-	NK:21,
-	NJ:6,
-	NV:8,
-
-/* Terminate and clean up */
-	clean : function()
-	{
-		var i;
-		for (i=0;i<32;i++) this.pool[i]=0;
-		for (i=0;i<this.NK;i++) this.ira[i]=0;
-		this.rndptr=0;
-		this.borrow=0;
-		this.pool_ptr=0;
-	},
-
-	sbrand: function()
-	{ /* Marsaglia & Zaman random number generator */
-		var i,k;
-		var pdiff,t; /* unsigned 32-bit */
-
-		this.rndptr++;
-		if (this.rndptr<this.NK) return this.ira[this.rndptr];
-		this.rndptr=0;
-		for (i=0,k=this.NK-this.NJ;i<this.NK;i++,k++)
-		{ /* calculate next NK values */
-			if (k==this.NK) k=0;
-			t=this.ira[k]>>>0;
-			pdiff=(t - this.ira[i] - this.borrow)|0;
-			pdiff>>>=0;  /* This is seriously wierd shit. I got to do this to get a proper unsigned comparison... */
-			if (pdiff<t) this.borrow=0;
-			if (pdiff>t) this.borrow=1;
-			this.ira[i]=(pdiff|0);
-		}
-		return this.ira[0];
-	},
-
-	sirand: function(seed)
-	{
-		var i,inn;
-		var t,m=1;
-		this.borrow=0;
-		this.rndptr=0;
-		seed>>>=0;
-		this.ira[0]^=seed;
-
-		for (i=1;i<this.NK;i++)
-		{ /* fill initialisation vector */
-			inn=(this.NV*i)%this.NK;
-			this.ira[inn]^=m;      /* note XOR */
-			t=m;
-			m=(seed-m)|0;
-			seed=t;
-		}
-
-		for (i=0;i<10000;i++) this.sbrand(); /* "warm-up" & stir the generator */
-	},
-
-	fill_pool: function()
-	{
-		var sh=new HASH();
-		for (var i=0;i<128;i++) sh.process(this.sbrand());
-		this.pool=sh.hash();
-		this.pool_ptr=0;
-	},
-
-/* Initialize RNG with some real entropy from some external source */
-	seed: function(rawlen,raw)
-	{ /* initialise from at least 128 byte string of raw random entropy */
-		var i;
-		var digest=[];
-		var b=[];
-		var sh=new HASH();
-		this.pool_ptr=0;
-		for (i=0;i<this.NK;i++) this.ira[i]=0;
-		if (rawlen>0)
-		{
-			for (i=0;i<rawlen;i++)
-				sh.process(raw[i]);
-			digest=sh.hash();
-
-/* initialise PRNG from distilled randomness */
-			for (i=0;i<8;i++)
-			{
-				b[0]=digest[4*i]; b[1]=digest[4*i+1]; b[2]=digest[4*i+2]; b[3]=digest[4*i+3];
-				this.sirand(RAND.pack(b));
-			}
-		}
-		this.fill_pool();
-	},
-
-/* get random byte */
-	getByte: function()
-	{
-		var r=this.pool[this.pool_ptr++];
-		if (this.pool_ptr>=32) this.fill_pool();
-		return (r&0xff);
-	}
-};
-
-RAND.pack= function(b)
-{ /* pack 4 bytes into a 32-bit Word */
-		return (((b[3])&0xff)<<24)|((b[2]&0xff)<<16)|((b[1]&0xff)<<8)|(b[0]&0xff);
-};
-
diff --git a/js/ROM.js b/js/ROM.js
deleted file mode 100755
index 7a91844..0000000
--- a/js/ROM.js
+++ /dev/null
@@ -1,620 +0,0 @@
-/*
-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.
-*/
-
-/* Fixed Data in ROM - Field and Curve parameters */
-
-var ROM={
-	NLEN: 11,
-	BASEBITS: 24,
-	CHUNK: 32,
-	MODBYTES: 32,
-	MODINV: 0.000000059604644775390625,
-
-/* Field Type */
-	NOT_SPECIAL: 0,
-	PSEUDO_MERSENNE: 1,
-	MONTGOMERY_FRIENDLY: 3,
-
-/* Curve Type */
-	WEIERSTRASS: 0,
-	EDWARDS: 1,
-	MONTGOMERY: 2,
-
-	USE_GLV: false,
-	USE_GS_G2: false,
-	USE_GS_GT: true,
-	GT_STRONG: false,
-
-/* Finite field support - for RSA, DH etc. */
-	FF_BITS: 2048, /* Finite Field Size in bits - must be 256.2^n */
-
-/*** Enter Some Field details here  ***/
-/* C25519 */
-//	MODBITS: 255, /* Number of bits in Modulus */
-//	MOD8: 5,  /* Modulus mod 8 */
-
-/* NIST Curve */
-/*  Brainpool */
-//	MODBITS: 256,
-//	MOD8: 7,
-
-/* BN */
-	MODBITS: 254,
-	MOD8: 3,
-
-/* MF254 */
-//	MODBITS: 254,
-//	MOD8: 7,
-
-/* MS255 */
-//MODBITS: 255,
-//MOD8: 3,
-
-/* MF256 */
-//	MODBITS: 256,
-//	MOD8: 7,
-
-/* MS256 */
-//MODBITS: 256,
-//MOD8: 3,
-
-/* ANSSI */
-//  MODBITS: 256,
-//  MOD8: 3,
-
-
-/* Specify Field here */
-
-/* C25519 */
-//	MODTYPE: 1,
-//	Modulus: [0xFFFFED,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0x7FFF],
-//	MConst: 19,
-
-/* BNCX */
-	MODTYPE:0,
-	Modulus: [0x1B55B3,0x23EF5C,0xE1BE66,0x18093E,0x3FD6EE,0x66D324,0x647A63,0xB0BDDF,0x702A0D,0x8,0x2400],
-	MConst:0x789E85,
-
-/* BN Curve */
-//MODTYPE:0,
-//Modulus: [0x13,0x0,0x13A700,0x0,0x210000,0x861,0x800000,0xBA344D,0x1,0x648240,0x2523],
-//MConst:0x9435E5,
-
-/* BNT Curve */
-//MODTYPE:0,
-//Modulus: [0xB4A713,0xBBFEEE,0xBABE9D,0x14F464,0x8A5556,0xD5F06E,0x3696F8,0xFA0BAB,0x17014E,0x20DB65,0x2401],
-//MConst:0x14C4E5,
-
-/* BNT2 */
-//MODTYPE:0,
-//Modulus: [0x60A48B,0xDC2BB4,0x51E8B2,0x28F0D6,0xCF93E4,0xD00081,0xF3B89,0xB74E20,0xF5AAD,0x48241,0x2400],
-//MConst:0x505CDD,
-
-/* NIST Modulus */
-//	MODTYPE:0,
-//	Modulus: [0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0x0,0x0,0x0,0x0,0x1,0xFFFF00,0xFFFF],
-//	MConst:0x1,
-
-/* MF254 Modulus */
-//	MODTYPE:3,
-//	Modulus: [0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0x3F80],
-//	MConst:0x3F81,
-
-/* MS255 Modulus */
-//MODTYPE:1,
-//Modulus: [0xFFFD03,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0x7FFF],
-//MConst:0x2FD,
-
-/* MS256 Modulus */
-//MODTYPE:1,
-//Modulus: [0xFFFF43,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFF],
-//MConst:0xBD,
-
-/* MF256 Modulus */
-//MODTYPE:3,
-//Modulus: [0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFA7],
-//MConst:0xFFA8,
-
-/*  Brainpool Modulus */
-//	MODTYPE:0,
-//	Modulus: [0x6E5377,0x481D1F,0x282013,0xD52620,0x3BF623,0x8D726E,0x909D83,0x3E660A,0xEEA9BC,0x57DBA1,0xA9FB],
-//	MConst:0xFD89B9,
-
-/* ANSSI Modulus */
-//  MODTYPE:0,
-//  Modulus: [0x6E9C03,0xF353D8,0x6DE8FC,0xABC8CA,0x61ADBC,0x435B39,0xE8CE42,0x10126D,0x3AD58F,0x178C0B,0xF1FD],
-//  MConst:0x4E1155,
-
-/* Specify Curve here */
-
-/* ED25519 Edwards */
-//	CURVETYPE: 1,
-//	CURVE_A : -1,
-//	CURVE_B : [0x5978A3,0x4DCA13,0xAB75EB,0x4141D8,0x700A4D,0xE89800,0x797779,0x8CC740,0x6FFE73,0x6CEE2B,0x5203],
-//	CURVE_Order: [0xF5D3ED,0x631A5C,0xD65812,0xA2F79C,0xDEF9DE,0x14,0x0,0x0,0x0,0x0,0x1000],
-//	CURVE_Gx: [0x25D51A,0x2D608F,0xB2C956,0x9525A7,0x2CC760,0xDC5C69,0x31FDD6,0xC0A4E2,0x6E53FE,0x36D3CD,0x2169],
-//	CURVE_Gy: [0x666658,0x666666,0x666666,0x666666,0x666666,0x666666,0x666666,0x666666,0x666666,0x666666,0x6666],
-
-/* Curve25519 */
-//	CURVETYPE: 2,
-//	CURVE_A : 486662,
-//	CURVE_B : [0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
-//	CURVE_Order: [0xF5D3ED,0x631A5C,0xD65812,0xA2F79C,0xDEF9DE,0x14,0x0,0x0,0x0,0x0,0x1000],
-//	CURVE_Gx: [0x9,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
-//	CURVE_Gy: [0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
-
-/* NIST Curve */
-//	CURVETYPE:0,
-//	CURVE_A : -3,
-//	CURVE_B : [0xD2604B,0x3C3E27,0xF63BCE,0xCC53B0,0x1D06B0,0x86BC65,0x557698,0xB3EBBD,0x3A93E7,0x35D8AA,0x5AC6],
-//	CURVE_Order:[0x632551,0xCAC2FC,0x84F3B9,0xA7179E,0xE6FAAD,0xFFFFBC,0xFFFFFF,0xFFFFFF,0x0,0xFFFF00,0xFFFF],
-//	CURVE_Gx :[0x98C296,0x3945D8,0xA0F4A1,0x2DEB33,0x37D81,0x40F277,0xE563A4,0xF8BCE6,0x2C4247,0xD1F2E1,0x6B17],
-//	CURVE_Gy :[0xBF51F5,0x406837,0xCECBB6,0x6B315E,0xCE3357,0x9E162B,0x4A7C0F,0x8EE7EB,0x1A7F9B,0x42E2FE,0x4FE3],
-
-/* MF254 Modulus, Weierstrass Curve */
-//CURVETYPE:0,
-//CURVE_A : -3,
-//CURVE_B : [0xFFD08D,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0x3F80],
-//CURVE_Order:[0x8DF83F,0x19C4AF,0xC06FA4,0xDA375,0x818BEA,0xFFFFEB,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0x3F80],
-//CURVE_Gx :[0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
-//CURVE_Gy :[0xD4EBC,0xDF37F9,0x31AD65,0xF85119,0xB738E3,0x8AEBDF,0x75BD77,0x4AE15A,0x2E5601,0x3FD33B,0x140E],
-
-/* MF254 Modulus, Edwards Curve */
-//CURVETYPE:1,
-//CURVE_A : -1,
-//CURVE_B : [0x367B,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
-//CURVE_Order:[0x6E98C7,0xD3FEC4,0xB0EAF3,0x8BD62F,0x95306C,0xFFFFEB,0xFFFFFF,0xFFFFFF,0xFFFFFF,0x3FFFFF,0xFE0],
-//CURVE_Gx :[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
-//CURVE_Gy :[0x2701E5,0xD0FDAF,0x187C52,0xE3212,0x329A84,0x3F4E36,0xD50236,0x951D00,0xA4C335,0xE690D6,0x19F0],
-
-
-/* MF254 Modulus, Montgomery Curve */
-//	CURVETYPE: 2,
-//	CURVE_A : -55790,
-//	CURVE_B : [0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
-//	CURVE_Order: [0x6E98C7,0xD3FEC4,0xB0EAF3,0x8BD62F,0x95306C,0xFFFFEB,0xFFFFFF,0xFFFFFF,0xFFFFFF,0x3FFFFF,0xFE0],
-//	CURVE_Gx: [0x3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
-//	CURVE_Gy: [0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
-
-/* MS255 Modulus, Weierstrass Curve */
-//CURVETYPE:0,
-//CURVE_A : -3,
-//CURVE_B : [0xFFAB46,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0x7FFF],
-//CURVE_Order:[0x594AEB,0xAC983C,0xDFAB8F,0x3AD2B3,0x4A3828,0xFFFF86,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0x7FFF],
-//CURVE_Gx :[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
-//CURVE_Gy :[0xCB44BA,0xFF6769,0xD1733,0xDDFDA6,0xB6C78C,0x7D177D,0xF9B2FF,0x921EBF,0xBA7833,0x6AC0ED,0x6F7A],
-
-/* MS255 Modulus, Edwards Curve */
-//CURVETYPE:1,
-//CURVE_A : -1,
-//CURVE_B : [0xEA97,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
-//CURVE_Order:[0x36EB75,0xD1ED04,0x2EAC49,0xEDA683,0xF1A785,0xFFFFDC,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0x1FFF],
-//CURVE_Gx :[0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
-//CURVE_Gy :[0x8736A0,0x255BD0,0x45BA2A,0xED445A,0x914B8A,0x47E552,0xDD8E0C,0xEC254C,0x7BB545,0x78534A,0x26CB],
-
-/* MS255 Modulus, Montgomery Curve */
-//	CURVETYPE: 2,
-//	CURVE_A : -240222,
-//	CURVE_B : [0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
-//	CURVE_Order: [0x36EB75,0xD1ED04,0x2EAC49,0xEDA683,0xF1A785,0xFFFFDC,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0x1FFF],
-//	CURVE_Gx: [0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
-//	CURVE_Gy: [0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
-
-/* MS256 Modulus, Weierstrass Curve */
-//CURVETYPE:0,
-//CURVE_A : -3,
-//CURVE_B : [0x25581,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
-//CURVE_Order:[0x51A825,0x202947,0x6020AB,0xEA265C,0x3C8275,0xFFFFE4,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFF],
-//CURVE_Gx :[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
-//CURVE_Gy :[0xB56C77,0x6306C2,0xC10BF4,0x75894E,0x2C2F93,0xDD6BD0,0x6CCEEE,0xFC82C9,0xE466D7,0x1853C1,0x696F],
-
-/* MS256 Modulus, Edwards Curve */
-//CURVETYPE:1,
-//CURVE_A : -1,
-//CURVE_B : [0x3BEE,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
-//CURVE_Order:[0x22B4AD,0x4E6F11,0x64E5B8,0xD0A6BC,0x6AA55A,0xFFFFBE,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0x3FFF],
-//CURVE_Gx :[0xD,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
-//CURVE_Gy :[0x1CADBA,0x6FB533,0x3F707F,0x824D30,0x2A6D63,0x46BFBE,0xB39FA0,0xA3D330,0x1276DB,0xB41E2A,0x7D0A],
-
-/* MS256 Modulus, Montgomery Curve */
-//	CURVETYPE: 2,
-//	CURVE_A : -61370,
-//	CURVE_B : [0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
-//  CURVE_Order:[0x22B4AD,0x4E6F11,0x64E5B8,0xD0A6BC,0x6AA55A,0xFFFFBE,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0x3FFF],
-//	CURVE_Gx: [0xb,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
-//	CURVE_Gy: [0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
-
-/* MF256 Modulus, Weierstrass Curve */
-//CURVETYPE:0,
-//CURVE_A : -3,
-//CURVE_B : [0x14E6A,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
-//CURVE_Order:[0x9857EB,0xC5E1A7,0x4B9D10,0xE6E507,0x517513,0xFFFFFC,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFA7],
-//CURVE_Gx :[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
-//CURVE_Gy :[0x724D2A,0x954C2B,0x661007,0x8D94DC,0x6947EB,0xAE2895,0x26123D,0x7BABBA,0x1808CE,0x7C87BE,0x2088],
-
-/* MF256 Modulus, Edwards Curve */
-//CURVETYPE:1,
-//CURVE_A : -1,
-//CURVE_B : [0x350A,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
-//CURVE_Order:[0xEC7BAB,0x2EDED8,0xC966D9,0xB86733,0x54BBAF,0xFFFFB1,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0x3FE9],
-//CURVE_Gx :[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
-//CURVE_Gy :[0xF3C908,0xA722F2,0x8D7DEA,0x8DFEA6,0xC05E64,0x1AACA0,0xF3DB2C,0xEAEBEE,0xCC4D5A,0xD4F8F8,0xDAD8],
-
-/* MF256 Modulus, Montgomery Curve */
-//	CURVETYPE: 2,
-//	CURVE_A : -54314,
-//	CURVE_B : [0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
-//  CURVE_Order:[0xEC7BAB,0x2EDED8,0xC966D9,0xB86733,0x54BBAF,0xFFFFB1,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0x3FE9],
-//	CURVE_Gx: [0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
-//	CURVE_Gy: [0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
-
-/* Brainpool */
-//	CURVETYPE:0,
-//	CURVE_A : -3,
-//	CURVE_B : [0xE92B04,0x8101FE,0x256AE5,0xAF2F49,0x93EBC4,0x76B7BF,0x733D0B,0xFE66A7,0xD84EA4,0x61C430,0x662C],
-//	CURVE_Order:[0x4856A7,0xE8297,0xF7901E,0xB561A6,0x397AA3,0x8D718C,0x909D83,0x3E660A,0xEEA9BC,0x57DBA1,0xA9FB],
-//	CURVE_Gx :[0x1305F4,0x91562E,0x2B79A1,0x7AAFBC,0xA142C4,0x6149AF,0xB23A65,0x732213,0xCFE7B7,0xEB3CC1,0xA3E8],
-//	CURVE_Gy :[0x25C9BE,0xE8F35B,0x1DAB,0x39D027,0xBCB6DE,0x417E69,0xE14644,0x7F7B22,0x39C56D,0x6C8234,0x2D99],
-
-/* ANSSI */
-//  CURVETYPE:0,
-//  CURVE_A : -3,
-//  CURVE_B : [0x7BB73F,0xED967B,0x803075,0xE4B1A1,0xEC0C9A,0xC00FDF,0x754A44,0xD4ABA,0x28A930,0x3FCA54,0xEE35],
-//  CURVE_Order:[0xD655E1,0xD459C6,0x941FFD,0x40D2BF,0xDC67E1,0x435B53,0xE8CE42,0x10126D,0x3AD58F,0x178C0B,0xF1FD],
-//  CURVE_Gx :[0x8F5CFF,0x7A2DD9,0x164C9,0xAF98B7,0x27D2DC,0x23958C,0x4749D4,0x31183D,0xC139EB,0xD4C356,0xB6B3],
-//  CURVE_Gy :[0x62CFB,0x5A1554,0xE18311,0xE8E4C9,0x1C307,0xEF8C27,0xF0F3EC,0x1F9271,0xB20491,0xE0F7C8,0x6142],
-
-
-/* BNCX Curve */
-
-	CURVETYPE:0,
-	CURVE_A : 0,
-	CURVE_B : [0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
-	CURVE_Order:[0xEB1F6D,0xC0A636,0xCEBE11,0xCC906,0x3FD6EE,0x66D2C4,0x647A63,0xB0BDDF,0x702A0D,0x8,0x2400],
-	CURVE_Bnx:[0xC012B1,0x3,0x4000],
-	CURVE_Cru:[0x235C97,0x931794,0x5631E0,0x71EF87,0xBDDF64,0x3F1440,0xCA8,0x480000],
-	CURVE_Fra:[0xC80EA3,0x83355,0x215BD9,0xF173F8,0x677326,0x189868,0x8AACA7,0xAFE18B,0x3A0164,0x82FA6,0x1359],
-	CURVE_Frb:[0x534710,0x1BBC06,0xC0628D,0x269546,0xD863C7,0x4E3ABB,0xD9CDBC,0xDC53,0x3628A9,0xF7D062,0x10A6],
-	CURVE_Pxa:[0xD2EC74,0x1CEEE4,0x26C085,0xA03E27,0x7C85BF,0x4BBB90,0xF5C3,0x358B25,0x53B256,0x2D2C70,0x1968],
-	CURVE_Pxb:[0x29CFE1,0x8E8B2E,0xF47A5,0xC209C3,0x1B97B0,0x9743F8,0x37A8E9,0xA011C9,0x19F64A,0xB9EC3E,0x1466],
-	CURVE_Pya:[0xBE09F,0xFCEBCF,0xB30CFB,0x847EC1,0x61B33D,0xE20963,0x157DAE,0xD81E22,0x332B8D,0xEDD972,0xA79],
-	CURVE_Pyb:[0x98EE9D,0x4B2288,0xEBED90,0x69D2ED,0x864EA5,0x3461C2,0x512D8D,0x35C6E4,0xC4C090,0xC39EC,0x616],
-	CURVE_Gx :[0x1B55B2,0x23EF5C,0xE1BE66,0x18093E,0x3FD6EE,0x66D324,0x647A63,0xB0BDDF,0x702A0D,0x8,0x2400],
-	CURVE_Gy :[0x1],
-
-// Arrays must be padded!
-
-	CURVE_W:[[0x2FEB83,0x634916,0x120054,0xB4038,0x0,0x60,0x0,0x0,0x0,0x0,0x0],[0x802561,0x7,0x8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],
-	CURVE_SB:[[[0xB010E4,0x63491D,0x128054,0xB4038,0x0,0x60,0x0,0x0,0x0,0x0,0x0],
-	           [0x802561,0x7,0x8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],
-			   [[0x802561,0x7,0x8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
-			   [0xBB33EA,0x5D5D20,0xBCBDBD,0x188CE,0x3FD6EE,0x66D264,0x647A63,0xB0BDDF,0x702A0D,0x8,0x2400]]],
-	CURVE_WB:[[0x7A84B0,0x211856,0xB0401C,0x3C012,0x0,0x20,0x0,0x0,0x0,0x0,0x0],
-	          [0x220475,0xF995BE,0x9A36CD,0xA8CA7F,0x7E94ED,0x2A0DC0,0x870,0x300000,0x0,0x0,0x0],
-			  [0xF10B93,0xFCCAE0,0xCD3B66,0xD4653F,0x3F4A76,0x1506E0,0x438,0x180000,0x0,0x0,0x0],
-			  [0xFAAA11,0x21185D,0xB0C01C,0x3C012,0x0,0x20,0x0,0x0,0x0,0x0,0x0]],
-	CURVE_BB:[[[0x2B0CBD,0xC0A633,0xCE7E11,0xCC906,0x3FD6EE,0x66D2C4,0x647A63,0xB0BDDF,0x702A0D,0x8,0x2400],
-	           [0x2B0CBC,0xC0A633,0xCE7E11,0xCC906,0x3FD6EE,0x66D2C4,0x647A63,0xB0BDDF,0x702A0D,0x8,0x2400],
-			   [0x2B0CBC,0xC0A633,0xCE7E11,0xCC906,0x3FD6EE,0x66D2C4,0x647A63,0xB0BDDF,0x702A0D,0x8,0x2400],
-			   [0x802562,0x7,0x8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],
-			   [[0x802561,0x7,0x8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
-			   [0x2B0CBC,0xC0A633,0xCE7E11,0xCC906,0x3FD6EE,0x66D2C4,0x647A63,0xB0BDDF,0x702A0D,0x8,0x2400],
-			   [0x2B0CBD,0xC0A633,0xCE7E11,0xCC906,0x3FD6EE,0x66D2C4,0x647A63,0xB0BDDF,0x702A0D,0x8,0x2400],
-			   [0x2B0CBC,0xC0A633,0xCE7E11,0xCC906,0x3FD6EE,0x66D2C4,0x647A63,0xB0BDDF,0x702A0D,0x8,0x2400]],
-			   [[0x802562,0x7,0x8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
-			   [0x802561,0x7,0x8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
-			   [0x802561,0x7,0x8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
-			   [0x802561,0x7,0x8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],
-			   [[0xC012B2,0x3,0x4000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
-			   [0x4AC2,0xF,0x10000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
-			   [0x6AFA0A,0xC0A62F,0xCE3E11,0xCC906,0x3FD6EE,0x66D2C4,0x647A63,0xB0BDDF,0x702A0D,0x8,0x2400],
-			   [0xC012B2,0x3,0x4000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]],
-
-/* BNT Curve */
-/*
-CURVETYPE:0,
-CURVE_A : 0,
-CURVE_B : [0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
-CURVE_Order:[0x30210D,0x777E8D,0x363A75,0x92B2CB,0x88D434,0xD5F00E,0x3696F8,0xFA0BAB,0x17014E,0x20DB65,0x2401],
-CURVE_Bnx:[0x4081,0x806000,0x4000],
-CURVE_Cru:[0x4FCD87,0x53D5AB,0x1FADEB,0xF2BAB1,0x4C82A5,0x4C976,0x476515,0x4801B1],
-CURVE_Fra:[0xC80022,0xD14EAD,0xE359F5,0xD6FACC,0x6C4904,0x3211BE,0xF190A1,0x4F6509,0xBBC439,0xA292C9,0x1328],
-CURVE_Frb:[0xECA6F1,0xEAB040,0xD764A7,0x3DF997,0x1E0C51,0xA3DEB0,0x450657,0xAAA6A1,0x5B3D15,0x7E489B,0x10D8],
-CURVE_Pxa:[0x8E65BB,0x87E228,0x13BE89,0x1CAA63,0xCC00AD,0x548B7C,0x325041,0xBCC055,0xC1339E,0x3FCD04,0x1448],
-CURVE_Pxb:[0xDBE2C0,0x888808,0x853A67,0xF81E34,0x957FE1,0x51B57B,0xA631A,0xDA3FC5,0x4EC302,0x46B338,0x87F],
-CURVE_Pya:[0x20CA1D,0x2C47E0,0xF36C20,0x7E8399,0x4CB416,0x9F72C9,0xC6E543,0x4A2C69,0x2B0BD7,0xC29C10,0x14E8],
-CURVE_Pyb:[0x6628F2,0x437C71,0xDC6BD8,0x67BCB7,0xA27E1,0x72681D,0xA82C75,0xEDEC18,0x454BD1,0xE2A462,0x17AF],
-CURVE_Gx :[0xB4A712,0xBBFEEE,0xBABE9D,0x14F464,0x8A5556,0xD5F06E,0x3696F8,0xFA0BAB,0x17014E,0x20DB65,0x2401],
-CURVE_Gy :[0x1],
-CURVE_W:[[0x838403,0x430061,0x838426,0x824199,0x18121,0x60],[0x8101,0xC000,0x8001]],
-CURVE_SB:[[[0x840504,0x43C061,0x840427,0x824199,0x18121,0x60],[0x8101,0xC000,0x8001]],[[0x8101,0xC000,0x8001],[0xAC9D0A,0x347E2B,0xB2B64F,0x107131,0x875313,0xD5EFAE,0x3696F8,0xFA0BAB,0x17014E,0x20DB65,0x2401]]],
-CURVE_WB:[[0x80C080,0x406020,0x80C161,0x80C088,0x8060,0x20],[0x8C4A85,0x390408,0x6C36B5,0xA352DC,0xDEAD2F,0x58868E,0xDA4363,0x300120],[0x464583,0xDCB204,0x363B5A,0xD1A96E,0x6F5697,0xAC4347,0x6D21B1,0x180090],[0x814181,0x412020,0x814162,0x80C088,0x8060,0x20]],
-CURVE_BB:[[[0x2FE08D,0xF71E8D,0x35FA74,0x92B2CB,0x88D434,0xD5F00E,0x3696F8,0xFA0BAB,0x17014E,0x20DB65,0x2401],[0x2FE08C,0xF71E8D,0x35FA74,0x92B2CB,0x88D434,0xD5F00E,0x3696F8,0xFA0BAB,0x17014E,0x20DB65,0x2401],[0x2FE08C,0xF71E8D,0x35FA74,0x92B2CB,0x88D434,0xD5F00E,0x3696F8,0xFA0BAB,0x17014E,0x20DB65,0x2401],[0x8102,0xC000,0x8001]],[[0x8101,0xC000,0x8001],[0x2FE08C,0xF71E8D,0x35FA74,0x92B2CB,0x88D434,0xD5F00E,0x3696F8,0xFA0BAB,0x17014E,0x20DB65,0x2401],[0x2FE08D,0xF71E8D,0x35FA74,0x92B2CB,0x88D434,0xD5F00E,0x3696F8,0xFA0BAB,0x17014E,0x20DB65,0x2401],[0x2FE08C,0xF71E8D,0x35FA74,0x92B2CB,0x88D434,0xD5F00E,0x3696F8,0xFA0BAB,0x17014E,0x20DB65,0x2401]],[[0x8102,0xC000,0x8001],[0x8101,0xC000,0x8001],[0x8101,0xC000,0x8001],[0x8101,0xC000,0x8001]],[[0x4082,0x806000,0x4000],[0x10202,0x18000,0x10002],[0x2FA00A,0x76BE8D,0x35BA74,0x92B2CB,0x88D434,0xD5F00E,0x3696F8,0xFA0BAB,0x17014E,0x20DB65,0x2401],[0x4082,0x806000,0x4000]]],
-
-*/
-
-/* BNT2 Curve */
-/*
-CURVETYPE:0,
-CURVE_A : 0,
-CURVE_B : [0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
-CURVE_Order:[0xAA2BF5,0x71A511,0x33D7FB,0x27B738,0xCF8DE1,0xD00021,0xF3B89,0xB74E20,0xF5AAD,0x48241,0x2400],
-CURVE_Bnx:[0x608205,0x20100,0x4000],
-CURVE_Cru:[0x66BD33,0x274448,0xEFB50,0x301647,0x755B77,0xECF236,0xC3617B,0x480006],
-CURVE_Fra:[0xAEF062,0x68C973,0xE492B2,0x33C3BC,0xBCC69B,0x7F195B,0xF67FA3,0xBD0A41,0xE8CAB6,0xB8D29,0x124E],
-CURVE_Frb:[0xB1B429,0x736240,0x6D5600,0xF52D19,0x12CD48,0x50E726,0x18BBE6,0xFA43DE,0x268FF6,0xF8F517,0x11B1],
-CURVE_Pxa:[0x40A3C8,0x92399F,0x784ACC,0xE96611,0x35CDA4,0x61706B,0x7B0569,0x8279D7,0x93C631,0x17CF96,0x16FC],
-CURVE_Pxb:[0x549540,0x7A8AD8,0x61055,0xE6F651,0xDB6F7B,0xA95D17,0x565907,0x9C8188,0x597590,0xB500BD,0x1EB5],
-CURVE_Pya:[0x220513,0xECC514,0x7B147B,0x860E73,0x844A78,0x35F126,0x51B839,0x9D4DFA,0x1422AA,0xE49876,0x1E8E],
-CURVE_Pyb:[0x7CE78E,0x328F57,0x781FB9,0xE26FA5,0x7EB746,0x1FB8E2,0xA93DBC,0xA29D76,0xE33BDB,0xF4CDBA,0x23CE],
-CURVE_Gx :[0x60A48A,0xDC2BB4,0x51E8B2,0x28F0D6,0xCF93E4,0xD00081,0xF3B89,0xB74E20,0xF5AAD,0x48241,0x2400],
-CURVE_Gy :[0x1],
-CURVE_W:[[0x347083,0x6282A1,0x1D10B7,0x1399E,0x603,0x60],[0xC10409,0x40200,0x8000]],
-CURVE_SB:[[[0xF5748C,0x6684A1,0x1D90B7,0x1399E,0x603,0x60],[0xC10409,0x40200,0x8000]],[[0xC10409,0x40200,0x8000],[0x75BB72,0xF2270,0x16C744,0x267D9A,0xCF87DE,0xCFFFC1,0xF3B89,0xB74E20,0xF5AAD,0x48241,0x2400]]],
-CURVE_WB:[[0x70A224,0x72D48A,0x94592,0x688A,0x201,0x20],[0x30EF19,0x572CF0,0x721D5A,0x763543,0xA39651,0x48A1B9,0x8240FD,0x300004],[0x48B88F,0x2C96F8,0xB92EAD,0xBB1AA1,0xD1CB28,0xA450DC,0x41207E,0x180002],[0x31A62D,0x76D68B,0x9C592,0x688A,0x201,0x20]],
-CURVE_BB:[[[0x49A9F1,0x6FA411,0x3397FB,0x27B738,0xCF8DE1,0xD00021,0xF3B89,0xB74E20,0xF5AAD,0x48241,0x2400],[0x49A9F0,0x6FA411,0x3397FB,0x27B738,0xCF8DE1,0xD00021,0xF3B89,0xB74E20,0xF5AAD,0x48241,0x2400],[0x49A9F0,0x6FA411,0x3397FB,0x27B738,0xCF8DE1,0xD00021,0xF3B89,0xB74E20,0xF5AAD,0x48241,0x2400],[0xC1040A,0x40200,0x8000]],[[0xC10409,0x40200,0x8000],[0x49A9F0,0x6FA411,0x3397FB,0x27B738,0xCF8DE1,0xD00021,0xF3B89,0xB74E20,0xF5AAD,0x48241,0x2400],[0x49A9F1,0x6FA411,0x3397FB,0x27B738,0xCF8DE1,0xD00021,0xF3B89,0xB74E20,0xF5AAD,0x48241,0x2400],[0x49A9F0,0x6FA411,0x3397FB,0x27B738,0xCF8DE1,0xD00021,0xF3B89,0xB74E20,0xF5AAD,0x48241,0x2400]],[[0xC1040A,0x40200,0x8000],[0xC10409,0x40200,0x8000],[0xC10409,0x40200,0x8000],[0xC10409,0x40200,0x8000]],[[0x608206,0x20100,0x4000],[0x820812,0x80401,0x10000],[0xE927EA,0x6DA310,0x3357FB,0x27B738,0xCF8DE1,0xD00021,0xF3B89,0xB74E20,0xF5AAD,0x48241,0x2400],[0x608206,0x20100,0x4000]]],
-*/
-
-/* BN Curve */
-/*
-CURVETYPE:0,
-CURVE_A : 0,
-CURVE_B : [0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
-CURVE_Order:[0xD,0x0,0x10A100,0x0,0x9F8000,0x7FF,0x800000,0xBA344D,0x1,0x648240,0x2523],
-CURVE_Bnx:[0x1,0x0,0x4080],
-CURVE_Cru:[0x7,0x0,0x6CD80,0x0,0x90000,0x249,0x400000,0x49B362],
-CURVE_Fra:[0x2A6DE9,0xE6C06F,0xC2E17D,0x4D3F77,0x97492,0x953F85,0x50A846,0xB6499B,0x2E7C8C,0x761921,0x1B37],
-CURVE_Frb:[0xD5922A,0x193F90,0x50C582,0xB2C088,0x178B6D,0x6AC8DC,0x2F57B9,0x3EAB2,0xD18375,0xEE691E,0x9EB],
-CURVE_Pxa:[0xFD0CB4,0x2C7935,0x7C2BAB,0xE4FCC5,0xA5E319,0x763B05,0x24F6DF,0x335FB7,0x5EA7EA,0x4D4F5,0x95B],
-CURVE_Pxb:[0x962455,0x7D0790,0x5E38A0,0x3D27AA,0x6D86BE,0x47F39D,0x89E057,0x9D42BF,0x8347B4,0xD8A7C0,0x5D4],
-CURVE_Pya:[0x8A46C,0xCE687A,0x91F9AD,0xE98A41,0x82B30,0xB1F169,0x4C3784,0xA16D1C,0xE5313F,0x2ABF25,0xABF],
-CURVE_Pyb:[0xF306EC,0x88D405,0xA0E6DF,0x6ADD13,0x48207,0x9D6A5C,0x1E4781,0xB38627,0x79DABD,0x9A87E6,0x1876],
-CURVE_Gx :[0x12,0x0,0x13A700,0x0,0x210000,0x861,0x800000,0xBA344D,0x1,0x648240,0x2523],
-CURVE_Gy :[0x1],
-CURVE_W:[[0x3,0x0,0x20400,0x0,0x818000,0x61],[0x1,0x0,0x8100]],
-CURVE_SB:[[[0x4,0x0,0x28500,0x0,0x818000,0x61],[0x1,0x0,0x8100]],[[0x1,0x0,0x8100],[0xA,0x0,0xE9D00,0x0,0x1E0000,0x79E,0x800000,0xBA344D,0x1,0x648240,0x2523]]],
-CURVE_WB:[[0x0,0x0,0x4080,0x0,0x808000,0x20],[0x5,0x0,0x54A80,0x0,0x70000,0x1C7,0x800000,0x312241],[0x3,0x0,0x2C580,0x0,0x838000,0xE3,0xC00000,0x189120],[0x1,0x0,0xC180,0x0,0x808000,0x20]],
-CURVE_BB:[[[0xD,0x0,0x106080,0x0,0x9F8000,0x7FF,0x800000,0xBA344D,0x1,0x648240,0x2523],[0xC,0x0,0x106080,0x0,0x9F8000,0x7FF,0x800000,0xBA344D,0x1,0x648240,0x2523],[0xC,0x0,0x106080,0x0,0x9F8000,0x7FF,0x800000,0xBA344D,0x1,0x648240,0x2523],[0x2,0x0,0x8100]],[[0x1,0x0,0x8100],[0xC,0x0,0x106080,0x0,0x9F8000,0x7FF,0x800000,0xBA344D,0x1,0x648240,0x2523],[0xD,0x0,0x106080,0x0,0x9F8000,0x7FF,0x800000,0xBA344D,0x1,0x648240,0x2523],[0xC,0x0,0x106080,0x0,0x9F8000,0x7FF,0x800000,0xBA344D,0x1,0x648240,0x2523]],[[0x2,0x0,0x8100],[0x1,0x0,0x8100],[0x1,0x0,0x8100],[0x1,0x0,0x8100]],[[0x2,0x0,0x4080],[0x2,0x0,0x10200],[0xA,0x0,0x102000,0x0,0x9F8000,0x7FF,0x800000,0xBA344D,0x1,0x648240,0x2523],[0x2,0x0,0x4080]]],
-
-*/
-
-	debug: false,
-
-// HASH constants
-
-	H0:0x6A09E667,
-	H1:0xBB67AE85,
-	H2:0x3C6EF372,
-	H3:0xA54FF53A,
-	H4:0x510E527F,
-	H5:0x9B05688C,
-	H6:0x1F83D9AB,
-	H7:0x5BE0CD19,
-
-	HK:[0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
-    0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
-    0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
-    0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
-    0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
-    0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
-    0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
-    0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2],
-
-// AES constants
-
-	ECB:0,
-	CBC:1,
-	CFB1:2,
-	CFB2:3,
-	CFB4:5,
-	OFB1:14,
-	OFB2:15,
-	OFB4:17,
-	OFB8:21,
-	OFB16:29,
-
-	InCo:[0xB,0xD,0x9,0xE],  /* Inverse Coefficients */
-	rco:[1,2,4,8,16,32,64,128,27,54,108,216,171,77,154,47],
-
-	ptab:[
-	1,3,5,15,17,51,85,255,26,46,114,150,161,248,19,53,
-	95,225,56,72,216,115,149,164,247,2,6,10,30,34,102,170,
-	229,52,92,228,55,89,235,38,106,190,217,112,144,171,230,49,
-	83,245,4,12,20,60,68,204,79,209,104,184,211,110,178,205,
-	76,212,103,169,224,59,77,215,98,166,241,8,24,40,120,136,
-	131,158,185,208,107,189,220,127,129,152,179,206,73,219,118,154,
-	181,196,87,249,16,48,80,240,11,29,39,105,187,214,97,163,
-	254,25,43,125,135,146,173,236,47,113,147,174,233,32,96,160,
-	251,22,58,78,210,109,183,194,93,231,50,86,250,21,63,65,
-	195,94,226,61,71,201,64,192,91,237,44,116,156,191,218,117,
-	159,186,213,100,172,239,42,126,130,157,188,223,122,142,137,128,
-	155,182,193,88,232,35,101,175,234,37,111,177,200,67,197,84,
-	252,31,33,99,165,244,7,9,27,45,119,153,176,203,70,202,
-	69,207,74,222,121,139,134,145,168,227,62,66,198,81,243,14,
-	18,54,90,238,41,123,141,140,143,138,133,148,167,242,13,23,
-	57,75,221,124,132,151,162,253,28,36,108,180,199,82,246,1
-	],
-	ltab:[
-	0,255,25,1,50,2,26,198,75,199,27,104,51,238,223,3,
-	100,4,224,14,52,141,129,239,76,113,8,200,248,105,28,193,
-	125,194,29,181,249,185,39,106,77,228,166,114,154,201,9,120,
-	101,47,138,5,33,15,225,36,18,240,130,69,53,147,218,142,
-	150,143,219,189,54,208,206,148,19,92,210,241,64,70,131,56,
-	102,221,253,48,191,6,139,98,179,37,226,152,34,136,145,16,
-	126,110,72,195,163,182,30,66,58,107,40,84,250,133,61,186,
-	43,121,10,21,155,159,94,202,78,212,172,229,243,115,167,87,
-	175,88,168,80,244,234,214,116,79,174,233,213,231,230,173,232,
-	44,215,117,122,235,22,11,245,89,203,95,176,156,169,81,160,
-	127,12,246,111,23,196,73,236,216,67,31,45,164,118,123,183,
-	204,187,62,90,251,96,177,134,59,82,161,108,170,85,41,157,
-	151,178,135,144,97,190,220,252,188,149,207,205,55,63,91,209,
-	83,57,132,60,65,162,109,71,20,42,158,93,86,242,211,171,
-	68,17,146,217,35,32,46,137,180,124,184,38,119,153,227,165,
-	103,74,237,222,197,49,254,24,13,99,140,128,192,247,112,7
-	],
-	fbsub:[
-	99,124,119,123,242,107,111,197,48,1,103,43,254,215,171,118,
-	202,130,201,125,250,89,71,240,173,212,162,175,156,164,114,192,
-	183,253,147,38,54,63,247,204,52,165,229,241,113,216,49,21,
-	4,199,35,195,24,150,5,154,7,18,128,226,235,39,178,117,
-	9,131,44,26,27,110,90,160,82,59,214,179,41,227,47,132,
-	83,209,0,237,32,252,177,91,106,203,190,57,74,76,88,207,
-	208,239,170,251,67,77,51,133,69,249,2,127,80,60,159,168,
-	81,163,64,143,146,157,56,245,188,182,218,33,16,255,243,210,
-	205,12,19,236,95,151,68,23,196,167,126,61,100,93,25,115,
-	96,129,79,220,34,42,144,136,70,238,184,20,222,94,11,219,
-	224,50,58,10,73,6,36,92,194,211,172,98,145,149,228,121,
-	231,200,55,109,141,213,78,169,108,86,244,234,101,122,174,8,
-	186,120,37,46,28,166,180,198,232,221,116,31,75,189,139,138,
-	112,62,181,102,72,3,246,14,97,53,87,185,134,193,29,158,
-	225,248,152,17,105,217,142,148,155,30,135,233,206,85,40,223,
-	140,161,137,13,191,230,66,104,65,153,45,15,176,84,187,22
-	],
-	rbsub:[
-	82,9,106,213,48,54,165,56,191,64,163,158,129,243,215,251,
-	124,227,57,130,155,47,255,135,52,142,67,68,196,222,233,203,
-	84,123,148,50,166,194,35,61,238,76,149,11,66,250,195,78,
-	8,46,161,102,40,217,36,178,118,91,162,73,109,139,209,37,
-	114,248,246,100,134,104,152,22,212,164,92,204,93,101,182,146,
-	108,112,72,80,253,237,185,218,94,21,70,87,167,141,157,132,
-	144,216,171,0,140,188,211,10,247,228,88,5,184,179,69,6,
-	208,44,30,143,202,63,15,2,193,175,189,3,1,19,138,107,
-	58,145,17,65,79,103,220,234,151,242,207,206,240,180,230,115,
-	150,172,116,34,231,173,53,133,226,249,55,232,28,117,223,110,
-	71,241,26,113,29,41,197,137,111,183,98,14,170,24,190,27,
-	252,86,62,75,198,210,121,32,154,219,192,254,120,205,90,244,
-	31,221,168,51,136,7,199,49,177,18,16,89,39,128,236,95,
-	96,81,127,169,25,181,74,13,45,229,122,159,147,201,156,239,
-	160,224,59,77,174,42,245,176,200,235,187,60,131,83,153,97,
-	23,43,4,126,186,119,214,38,225,105,20,99,85,33,12,125
-	],
-	ftable:[
-	0xa56363c6,0x847c7cf8,0x997777ee,0x8d7b7bf6,0xdf2f2ff,0xbd6b6bd6,
-	0xb16f6fde,0x54c5c591,0x50303060,0x3010102,0xa96767ce,0x7d2b2b56,
-	0x19fefee7,0x62d7d7b5,0xe6abab4d,0x9a7676ec,0x45caca8f,0x9d82821f,
-	0x40c9c989,0x877d7dfa,0x15fafaef,0xeb5959b2,0xc947478e,0xbf0f0fb,
-	0xecadad41,0x67d4d4b3,0xfda2a25f,0xeaafaf45,0xbf9c9c23,0xf7a4a453,
-	0x967272e4,0x5bc0c09b,0xc2b7b775,0x1cfdfde1,0xae93933d,0x6a26264c,
-	0x5a36366c,0x413f3f7e,0x2f7f7f5,0x4fcccc83,0x5c343468,0xf4a5a551,
-	0x34e5e5d1,0x8f1f1f9,0x937171e2,0x73d8d8ab,0x53313162,0x3f15152a,
-	0xc040408,0x52c7c795,0x65232346,0x5ec3c39d,0x28181830,0xa1969637,
-	0xf05050a,0xb59a9a2f,0x907070e,0x36121224,0x9b80801b,0x3de2e2df,
-	0x26ebebcd,0x6927274e,0xcdb2b27f,0x9f7575ea,0x1b090912,0x9e83831d,
-	0x742c2c58,0x2e1a1a34,0x2d1b1b36,0xb26e6edc,0xee5a5ab4,0xfba0a05b,
-	0xf65252a4,0x4d3b3b76,0x61d6d6b7,0xceb3b37d,0x7b292952,0x3ee3e3dd,
-	0x712f2f5e,0x97848413,0xf55353a6,0x68d1d1b9,0x0,0x2cededc1,
-	0x60202040,0x1ffcfce3,0xc8b1b179,0xed5b5bb6,0xbe6a6ad4,0x46cbcb8d,
-	0xd9bebe67,0x4b393972,0xde4a4a94,0xd44c4c98,0xe85858b0,0x4acfcf85,
-	0x6bd0d0bb,0x2aefefc5,0xe5aaaa4f,0x16fbfbed,0xc5434386,0xd74d4d9a,
-	0x55333366,0x94858511,0xcf45458a,0x10f9f9e9,0x6020204,0x817f7ffe,
-	0xf05050a0,0x443c3c78,0xba9f9f25,0xe3a8a84b,0xf35151a2,0xfea3a35d,
-	0xc0404080,0x8a8f8f05,0xad92923f,0xbc9d9d21,0x48383870,0x4f5f5f1,
-	0xdfbcbc63,0xc1b6b677,0x75dadaaf,0x63212142,0x30101020,0x1affffe5,
-	0xef3f3fd,0x6dd2d2bf,0x4ccdcd81,0x140c0c18,0x35131326,0x2fececc3,
-	0xe15f5fbe,0xa2979735,0xcc444488,0x3917172e,0x57c4c493,0xf2a7a755,
-	0x827e7efc,0x473d3d7a,0xac6464c8,0xe75d5dba,0x2b191932,0x957373e6,
-	0xa06060c0,0x98818119,0xd14f4f9e,0x7fdcdca3,0x66222244,0x7e2a2a54,
-	0xab90903b,0x8388880b,0xca46468c,0x29eeeec7,0xd3b8b86b,0x3c141428,
-	0x79dedea7,0xe25e5ebc,0x1d0b0b16,0x76dbdbad,0x3be0e0db,0x56323264,
-	0x4e3a3a74,0x1e0a0a14,0xdb494992,0xa06060c,0x6c242448,0xe45c5cb8,
-	0x5dc2c29f,0x6ed3d3bd,0xefacac43,0xa66262c4,0xa8919139,0xa4959531,
-	0x37e4e4d3,0x8b7979f2,0x32e7e7d5,0x43c8c88b,0x5937376e,0xb76d6dda,
-	0x8c8d8d01,0x64d5d5b1,0xd24e4e9c,0xe0a9a949,0xb46c6cd8,0xfa5656ac,
-	0x7f4f4f3,0x25eaeacf,0xaf6565ca,0x8e7a7af4,0xe9aeae47,0x18080810,
-	0xd5baba6f,0x887878f0,0x6f25254a,0x722e2e5c,0x241c1c38,0xf1a6a657,
-	0xc7b4b473,0x51c6c697,0x23e8e8cb,0x7cdddda1,0x9c7474e8,0x211f1f3e,
-	0xdd4b4b96,0xdcbdbd61,0x868b8b0d,0x858a8a0f,0x907070e0,0x423e3e7c,
-	0xc4b5b571,0xaa6666cc,0xd8484890,0x5030306,0x1f6f6f7,0x120e0e1c,
-	0xa36161c2,0x5f35356a,0xf95757ae,0xd0b9b969,0x91868617,0x58c1c199,
-	0x271d1d3a,0xb99e9e27,0x38e1e1d9,0x13f8f8eb,0xb398982b,0x33111122,
-	0xbb6969d2,0x70d9d9a9,0x898e8e07,0xa7949433,0xb69b9b2d,0x221e1e3c,
-	0x92878715,0x20e9e9c9,0x49cece87,0xff5555aa,0x78282850,0x7adfdfa5,
-	0x8f8c8c03,0xf8a1a159,0x80898909,0x170d0d1a,0xdabfbf65,0x31e6e6d7,
-	0xc6424284,0xb86868d0,0xc3414182,0xb0999929,0x772d2d5a,0x110f0f1e,
-	0xcbb0b07b,0xfc5454a8,0xd6bbbb6d,0x3a16162c
-	],
-	rtable:[
-	0x50a7f451,0x5365417e,0xc3a4171a,0x965e273a,0xcb6bab3b,0xf1459d1f,
-	0xab58faac,0x9303e34b,0x55fa3020,0xf66d76ad,0x9176cc88,0x254c02f5,
-	0xfcd7e54f,0xd7cb2ac5,0x80443526,0x8fa362b5,0x495ab1de,0x671bba25,
-	0x980eea45,0xe1c0fe5d,0x2752fc3,0x12f04c81,0xa397468d,0xc6f9d36b,
-	0xe75f8f03,0x959c9215,0xeb7a6dbf,0xda595295,0x2d83bed4,0xd3217458,
-	0x2969e049,0x44c8c98e,0x6a89c275,0x78798ef4,0x6b3e5899,0xdd71b927,
-	0xb64fe1be,0x17ad88f0,0x66ac20c9,0xb43ace7d,0x184adf63,0x82311ae5,
-	0x60335197,0x457f5362,0xe07764b1,0x84ae6bbb,0x1ca081fe,0x942b08f9,
-	0x58684870,0x19fd458f,0x876cde94,0xb7f87b52,0x23d373ab,0xe2024b72,
-	0x578f1fe3,0x2aab5566,0x728ebb2,0x3c2b52f,0x9a7bc586,0xa50837d3,
-	0xf2872830,0xb2a5bf23,0xba6a0302,0x5c8216ed,0x2b1ccf8a,0x92b479a7,
-	0xf0f207f3,0xa1e2694e,0xcdf4da65,0xd5be0506,0x1f6234d1,0x8afea6c4,
-	0x9d532e34,0xa055f3a2,0x32e18a05,0x75ebf6a4,0x39ec830b,0xaaef6040,
-	0x69f715e,0x51106ebd,0xf98a213e,0x3d06dd96,0xae053edd,0x46bde64d,
-	0xb58d5491,0x55dc471,0x6fd40604,0xff155060,0x24fb9819,0x97e9bdd6,
-	0xcc434089,0x779ed967,0xbd42e8b0,0x888b8907,0x385b19e7,0xdbeec879,
-	0x470a7ca1,0xe90f427c,0xc91e84f8,0x0,0x83868009,0x48ed2b32,
-	0xac70111e,0x4e725a6c,0xfbff0efd,0x5638850f,0x1ed5ae3d,0x27392d36,
-	0x64d90f0a,0x21a65c68,0xd1545b9b,0x3a2e3624,0xb1670a0c,0xfe75793,
-	0xd296eeb4,0x9e919b1b,0x4fc5c080,0xa220dc61,0x694b775a,0x161a121c,
-	0xaba93e2,0xe52aa0c0,0x43e0223c,0x1d171b12,0xb0d090e,0xadc78bf2,
-	0xb9a8b62d,0xc8a91e14,0x8519f157,0x4c0775af,0xbbdd99ee,0xfd607fa3,
-	0x9f2601f7,0xbcf5725c,0xc53b6644,0x347efb5b,0x7629438b,0xdcc623cb,
-	0x68fcedb6,0x63f1e4b8,0xcadc31d7,0x10856342,0x40229713,0x2011c684,
-	0x7d244a85,0xf83dbbd2,0x1132f9ae,0x6da129c7,0x4b2f9e1d,0xf330b2dc,
-	0xec52860d,0xd0e3c177,0x6c16b32b,0x99b970a9,0xfa489411,0x2264e947,
-	0xc48cfca8,0x1a3ff0a0,0xd82c7d56,0xef903322,0xc74e4987,0xc1d138d9,
-	0xfea2ca8c,0x360bd498,0xcf81f5a6,0x28de7aa5,0x268eb7da,0xa4bfad3f,
-	0xe49d3a2c,0xd927850,0x9bcc5f6a,0x62467e54,0xc2138df6,0xe8b8d890,
-	0x5ef7392e,0xf5afc382,0xbe805d9f,0x7c93d069,0xa92dd56f,0xb31225cf,
-	0x3b99acc8,0xa77d1810,0x6e639ce8,0x7bbb3bdb,0x97826cd,0xf418596e,
-	0x1b79aec,0xa89a4f83,0x656e95e6,0x7ee6ffaa,0x8cfbc21,0xe6e815ef,
-	0xd99be7ba,0xce366f4a,0xd4099fea,0xd67cb029,0xafb2a431,0x31233f2a,
-	0x3094a5c6,0xc066a235,0x37bc4e74,0xa6ca82fc,0xb0d090e0,0x15d8a733,
-	0x4a9804f1,0xf7daec41,0xe50cd7f,0x2ff69117,0x8dd64d76,0x4db0ef43,
-	0x544daacc,0xdf0496e4,0xe3b5d19e,0x1b886a4c,0xb81f2cc1,0x7f516546,
-	0x4ea5e9d,0x5d358c01,0x737487fa,0x2e410bfb,0x5a1d67b3,0x52d2db92,
-	0x335610e9,0x1347d66d,0x8c61d79a,0x7a0ca137,0x8e14f859,0x893c13eb,
-	0xee27a9ce,0x35c961b7,0xede51ce1,0x3cb1477a,0x59dfd29c,0x3f73f255,
-	0x79ce1418,0xbf37c773,0xeacdf753,0x5baafd5f,0x146f3ddf,0x86db4478,
-	0x81f3afca,0x3ec468b9,0x2c342438,0x5f40a3c2,0x72c31d16,0xc25e2bc,
-	0x8b493c28,0x41950dff,0x7101a839,0xdeb30c08,0x9ce4b4d8,0x90c15664,
-	0x6184cb7b,0x70b632d5,0x745c6c48,0x4257b8d0
-	],
-
-// GCM constants
-
-	GCM_ACCEPTING_HEADER:0,
-	GCM_ACCEPTING_CIPHER:1,
-	GCM_NOT_ACCEPTING_MORE:2,
-	GCM_FINISHED:3,
-	GCM_ENCRYPTING:0,
-	GCM_DECRYPTING:1
-
-};
-
-ROM.DNLEN=2*ROM.NLEN;
-ROM.MASK=(1<<ROM.BASEBITS)-1;
-
-ROM.TBITS=ROM.MODBITS%ROM.BASEBITS;
-ROM.OMASK=(-1)<<ROM.TBITS;
-ROM.TMASK=(1<<ROM.TBITS)-1;
-
-ROM.NEXCESS=(1<<(ROM.CHUNK-ROM.BASEBITS-1)); // 2^(CHUNK-BASEBITS-1)
-ROM.FEXCESS=(1<<(ROM.BASEBITS*ROM.NLEN-ROM.MODBITS)); // 2^(BASEBITS*NLEN-MODBITS)
-
-ROM.FFLEN=(ROM.FF_BITS/256);
-ROM.HFLEN=(ROM.FFLEN/2);  /* Useful for half-size RSA private key operations */
diff --git a/js/RSA.js b/js/RSA.js
deleted file mode 100755
index 5b90770..0000000
--- a/js/RSA.js
+++ /dev/null
@@ -1,331 +0,0 @@
-/*
-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.
-*/
-
-/* RSA API Functions */
-
-var rsa_private_key=function(n)
-{
-	this.p=new FF(n);
-	this.q=new FF(n);
-	this.dp=new FF(n);
-	this.dq=new FF(n);
-	this.c=new FF(n);
-};
-
-var rsa_public_key=function(m)
-{
-	this.e=0;
-	this.n=new FF(m);
-};
-
-
-
-RSA= {
-	RFS: ROM.MODBYTES*ROM.FFLEN,
-
-	bytestohex: function(b)
-	{
-		var s="";
-		var len=b.length;
-		var ch;
-
-		for (var i=0;i<len;i++)
-		{
-			ch=b[i];
-			s+=((ch>>>4)&15).toString(16);
-			s+=(ch&15).toString(16);
-
-		}
-		return s;
-	},
-
-	bytestostring: function(b)
-	{
-		var s="";
-		for (var i=0;i<b.length;i++)
-		{
-			s+=String.fromCharCode(b[i]);
-		}
-		return s;
-	},
-
-	stringtobytes: function(s)
-	{
-		var b=[];
-		for (var i=0;i<s.length;i++)
-			b.push(s.charCodeAt(i));
-		return b;
-	},
-
-
-	KEY_PAIR: function(rng,e,PRIV,PUB)
-	{ /* IEEE1363 A16.11/A16.12 more or less */
-
-	//	var m,r,bytes,hbytes,words,err,res=0;
-		var n=PUB.n.length>>1;
-		var t = new FF(n);
-		var p1=new FF(n);
-		var q1=new FF(n);
-
-		for (;;)
-		{
-
-			PRIV.p.random(rng);
-			while (PRIV.p.lastbits(2)!=3) PRIV.p.inc(1);
-			while (!FF.prime(PRIV.p,rng)) PRIV.p.inc(4);
-
-			p1.copy(PRIV.p);
-			p1.dec(1);
-
-			if (p1.cfactor(e)) continue;
-			break;
-		}
-
-		for (;;)
-		{
-			PRIV.q.random(rng);
-			while (PRIV.q.lastbits(2)!=3) PRIV.q.inc(1);
-			while (!FF.prime(PRIV.q,rng)) PRIV.q.inc(4);
-
-			q1.copy(PRIV.q);
-			q1.dec(1);
-
-			if (q1.cfactor(e)) continue;
-			break;
-		}
-
-		PUB.n=FF.mul(PRIV.p,PRIV.q);
-		PUB.e=e;
-
-		t.copy(p1);
-		t.shr();
-		PRIV.dp.set(e);
-		PRIV.dp.invmodp(t);
-		if (PRIV.dp.parity()===0) PRIV.dp.add(t);
-		PRIV.dp.norm();
-
-		t.copy(q1);
-		t.shr();
-		PRIV.dq.set(e);
-		PRIV.dq.invmodp(t);
-		if (PRIV.dq.parity()===0) PRIV.dq.add(t);
-		PRIV.dq.norm();
-
-		PRIV.c.copy(PRIV.p);
-		PRIV.c.invmodp(PRIV.q);
-
-		return;
-	},
-
-/* Mask Generation Function */
-	MGF1: function(Z,olen,K)
-	{
-		var H=new HASH();
-		var i,hlen=H.len;
-		var B=[];
-
-		var counter,cthreshold,k=0;
-		for (i=0;i<K.length;i++) K[i]=0;
-
-		cthreshold=Math.floor(olen/hlen); if (olen%hlen!==0) cthreshold++;
-		for (counter=0;counter<cthreshold;counter++)
-		{
-			H.process_array(Z); H.process_num(counter);
-			B=H.hash();
-
-			if (k+hlen>olen) for (i=0;i<olen%hlen;i++) K[k++]=B[i];
-			else for (i=0;i<hlen;i++) K[k++]=B[i];
-		}
-	},
-
-	/* OAEP Message Encoding for Encryption */
-	OAEP_ENCODE: function(m,rng,p)
-	{
-		var i,slen,olen=RSA.RFS-1;
-		var mlen=m.length;
-		var hlen,seedlen;
-		var f=[];
-
-		var H=new HASH();
-		hlen=H.len;
-		var SEED=[];
-		seedlen=hlen;
-		if (mlen>olen-hlen-seedlen-1) return null;
-
-		var DBMASK=[];
-
-		if (p!==null) H.process_array(p);
-		var h=H.hash();
-		for (i=0;i<hlen;i++) f[i]=h[i];
-
-		slen=olen-mlen-hlen-seedlen-1;
-
-		for (i=0;i<slen;i++) f[hlen+i]=0;
-		f[hlen+slen]=1;
-		for (i=0;i<mlen;i++) f[hlen+slen+1+i]=m[i];
-
-		for (i=0;i<seedlen;i++) SEED[i]=rng.getByte();
-		this.MGF1(SEED,olen-seedlen,DBMASK);
-
-		for (i=0;i<olen-seedlen;i++) DBMASK[i]^=f[i];
-		this.MGF1(DBMASK,seedlen,f);
-
-		for (i=0;i<seedlen;i++) f[i]^=SEED[i];
-
-		for (i=0;i<olen-seedlen;i++) f[i+seedlen]=DBMASK[i];
-
-		/* pad to length RFS */
-		var d=1;
-		for (i=RSA.RFS-1;i>=d;i--)
-			f[i]=f[i-d];
-		for (i=d-1;i>=0;i--)
-			f[i]=0;
-
-		return f;
-	},
-
-	/* OAEP Message Decoding for Decryption */
-	OAEP_DECODE: function(p,f)
-	{
-		var x,t;
-		var comp;
-		var i,k,olen=RSA.RFS-1;
-		var hlen,seedlen;
-
-		var H=new HASH();
-		hlen=H.len;
-		var SEED=[];
-		seedlen=hlen;
-		var CHASH=[];
-		seedlen=hlen=32;
-		if (olen<seedlen+hlen+1) return null;
-		var DBMASK=[];
-		for (i=0;i<olen-seedlen;i++) DBMASK[i]=0;
-
-		if (f.length<RSA.RFS)
-		{
-			var d=RSA.RFS-f.length;
-			for (i=RFS-1;i>=d;i--)
-				f[i]=f[i-d];
-			for (i=d-1;i>=0;i--)
-				f[i]=0;
-
-		}
-
-		if (p!==null) H.process_array(p);
-		var h=H.hash();
-		for (i=0;i<hlen;i++) CHASH[i]=h[i];
-
-		x=f[0];
-
-		for (i=seedlen;i<olen;i++)
-			DBMASK[i-seedlen]=f[i+1];
-
-		this.MGF1(DBMASK,seedlen,SEED);
-		for (i=0;i<seedlen;i++) SEED[i]^=f[i+1];
-		this.MGF1(SEED,olen-seedlen,f);
-		for (i=0;i<olen-seedlen;i++) DBMASK[i]^=f[i];
-
-		comp=true;
-		for (i=0;i<hlen;i++)
-		{
-			if (CHASH[i]!=DBMASK[i]) comp=false;
-		}
-
-		for (i=0;i<olen-seedlen-hlen;i++)
-			DBMASK[i]=DBMASK[i+hlen];
-
-		for (i=0;i<hlen;i++)
-			SEED[i]=CHASH[i]=0;
-
-		for (k=0;;k++)
-		{
-			if (k>=olen-seedlen-hlen) return null;
-			if (DBMASK[k]!==0) break;
-		}
-
-		t=DBMASK[k];
-		if (!comp || x!==0 || t!=0x01)
-		{
-			for (i=0;i<olen-seedlen;i++) DBMASK[i]=0;
-			return null;
-		}
-
-		var r=[];
-
-		for (i=0;i<olen-seedlen-hlen-k-1;i++)
-			r[i]=DBMASK[i+k+1];
-
-		for (i=0;i<olen-seedlen;i++) DBMASK[i]=0;
-
-		return r;
-	},
-
-	/* destroy the Private Key structure */
-	PRIVATE_KEY_KILL: function(PRIV)
-	{
-		PRIV.p.zero();
-		PRIV.q.zero();
-		PRIV.dp.zero();
-		PRIV.dq.zero();
-		PRIV.c.zero();
-	},
-
-	/* RSA encryption with the public key */
-	ENCRYPT: function(PUB,F,G)
-	{
-		var n=PUB.n.getlen();
-		var f=new FF(n);
-
-		FF.fromBytes(f,F);
-		f.power(PUB.e,PUB.n);
-		f.toBytes(G);
-	},
-
-	/* RSA decryption with the private key */
-	DECRYPT: function(PRIV,G,F)
-	{
-		var n=PRIV.p.getlen();
-		var g=new FF(2*n);
-
-		FF.fromBytes(g,G);
-		var jp=g.dmod(PRIV.p);
-		var jq=g.dmod(PRIV.q);
-
-		jp.skpow(PRIV.dp,PRIV.p);
-		jq.skpow(PRIV.dq,PRIV.q);
-
-		g.zero();
-		g.dscopy(jp);
-		jp.mod(PRIV.q);
-		if (FF.comp(jp,jq)>0) jq.add(PRIV.q);
-		jq.sub(jp);
-		jq.norm();
-
-		var t=FF.mul(PRIV.c,jq);
-		jq=t.dmod(PRIV.q);
-
-		t=FF.mul(jq,PRIV.p);
-		g.add(t);
-		g.norm();
-
-		g.toBytes(F);
-	}
-
-};
diff --git a/js/TestECDH.html b/js/TestECDH.html
deleted file mode 100644
index 6c57021..0000000
--- a/js/TestECDH.html
+++ /dev/null
@@ -1,137 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-<title>JavaScript Test ECC</title>
-</head>
-<body>
-<h1>JavaScript Test ECC Example</h1>
-<script type="text/javascript" src="DBIG.js"></script>
-<script type="text/javascript" src="BIG.js"></script>
-<script type="text/javascript" src="FP.js"></script>
-<script type="text/javascript" src="ROM.js"></script>
-<script type="text/javascript" src="HASH.js"></script>
-<script type="text/javascript" src="RAND.js"></script>
-<script type="text/javascript" src="AES.js"></script>
-<script type="text/javascript" src="GCM.js"></script>
-<script type="text/javascript" src="ECP.js"></script>
-<script type="text/javascript" src="ECDH.js"></script>
-
-<script>
-/* test driver and function exerciser for ECDH/ECIES/ECDSA API Functions */
-		var i,j=0,res;
-		var result;
-		var pp="M0ng00se";
-
-		var EGS=ECDH.EGS;
-		var EFS=ECDH.EFS;
-		var EAS=16;
-
-		var S1=[];
-		var W0=[];
-		var W1=[];
-		var Z0=[];
-		var Z1=[];
-		var RAW=[];
-		var SALT=[];
-		var P1=[];
-		var P2=[];
-		var V=[];
-		var M=[];
-		var T=new Array(12);  // must specify required length
-		var CS=[];
-		var DS=[];
-
-		var rng=new RAND();
-
-		rng.clean();
-		for (i=0;i<100;i++) RAW[i]=i;
-
-		rng.seed(100,RAW);
-//for (j=0;j<100;j++)
-//{
-
-		for (i=0;i<8;i++) SALT[i]=(i+1);  // set Salt
-
-		window.document.write("Alice's Passphrase= " + pp + "<br>");
-
-		var PW=ECDH.stringtobytes(pp);
-/* private key S0 of size EGS bytes derived from Password and Salt */
-		var S0=ECDH.PBKDF2(PW,SALT,1000,EGS);
-
-		window.document.write("Alice's private key= 0x"+ECDH.bytestostring(S0)+ "<br>");
-/* Generate Key pair S/W */
-		ECDH.KEY_PAIR_GENERATE(null,S0,W0); 
-
-		window.document.write("Alice's public key= 0x"+ECDH.bytestostring(W0)+ "<br>");
-
-		res=ECDH.PUBLIC_KEY_VALIDATE(true,W0);
-		if (res!=0)
-			alert("ECP Public Key is invalid!");
-/* Random private key for other party */
-		ECDH.KEY_PAIR_GENERATE(rng,S1,W1);
-
-		window.document.write("Servers private key= 0x"+ECDH.bytestostring(S1)+ "<br>");
-		window.document.write("Servers public key= 0x"+ECDH.bytestostring(W1)+ "<br>");
-
-		res=ECDH.PUBLIC_KEY_VALIDATE(true,W1);
-		if (res!=0)
-			alert("ECP Public Key is invalid!");
-			
-
-/* Calculate common key using DH - IEEE 1363 method */
-
-		ECDH.ECPSVDP_DH(S0,W1,Z0);
-		ECDH.ECPSVDP_DH(S1,W0,Z1);
-
-		var same=true;
-		for (i=0;i<ECDH.EFS;i++)
-			if (Z0[i]!=Z1[i]) same=false;
-
-		if (!same)
-			alert("*** ECPSVDP-DH Failed");
-
-		var KEY=ECDH.KDF1(Z0,ECDH.EAS);
-
-		window.document.write("Alice's DH Key=  0x"+ECDH.bytestostring(KEY)+ "<br>");
-		window.document.write("Servers DH Key=  0x"+ECDH.bytestostring(KEY)+ "<br>");
-
-		window.document.write("Testing ECIES"+ "<br>");
-
-		P1[0]=0x0; P1[1]=0x1; P1[2]=0x2; 
-		P2[0]=0x0; P2[1]=0x1; P2[2]=0x2; P2[3]=0x3; 
-
-		for (i=0;i<=16;i++) M[i]=i; 
-
-		var C=ECDH.ECIES_ENCRYPT(P1,P2,rng,W1,M,V,T);
-
-		window.document.write("Ciphertext= "+ "<br>");
-		window.document.write("V= 0x"+ECDH.bytestostring(V)+ "<br>");
-		window.document.write("C= 0x"+ECDH.bytestostring(C)+ "<br>");
-		window.document.write("T= 0x"+ECDH.bytestostring(T)+ "<br>");
-
-
-		M=ECDH.ECIES_DECRYPT(P1,P2,V,C,T,S1);
-		if (M.length==0)
-			alert("*** ECIES Decryption Failed ");
-		else window.document.write("Decryption succeeded"+ "<br>");
-
-		window.document.write("Message is 0x"+ECDH.bytestostring(M)+ "<br>");
-
-
-		window.document.write("Testing ECDSA"+ "<br>");
-
-		if (ECDH.ECPSP_DSA(rng,S0,M,CS,DS)!=0)
-			alert("***ECDSA Signature Failed");
-		
-		window.document.write("Signature= "+ "<br>");
-		window.document.write("C= 0x"+ECDH.bytestostring(CS)+ "<br>");
-		window.document.write("D= 0x"+ECDH.bytestostring(DS)+ "<br>");
-
-		if (ECDH.ECPVP_DSA(W0,M,CS,DS)!=0)
-			alert("***ECDSA Verification Failed");
-		else window.document.write("ECDSA Signature/Verification succeeded "+ j+ "<br>");
-//}
-//window.document.write("Test Completed Successfully"+ "<br>");
-</script>
-</body>
-</html>
diff --git a/js/TestECM.html b/js/TestECM.html
deleted file mode 100644
index 2010378..0000000
--- a/js/TestECM.html
+++ /dev/null
@@ -1,95 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-<title>JavaScript Test ECC</title>
-</head>
-<body>
-<h1>JavaScript Test ECC Example</h1>
-<script type="text/javascript" src="DBIG.js"></script>
-<script type="text/javascript" src="BIG.js"></script>
-<script type="text/javascript" src="FP.js"></script>
-<script type="text/javascript" src="ROM.js"></script>
-<script type="text/javascript" src="HASH.js"></script>
-<script type="text/javascript" src="RAND.js"></script>
-<script type="text/javascript" src="AES.js"></script>
-<script type="text/javascript" src="GCM.js"></script>
-<script type="text/javascript" src="ECP.js"></script>
-<script type="text/javascript" src="ECDH.js"></script>
-
-<script>
-/* test driver and function exerciser for ECDH API Functions only - for use with Montgpmery curves */
-		var i,j=0,res;
-		var result;
-		var pp="M0ng00se";
-
-		var EGS=ECDH.EGS;
-		var EFS=ECDH.EFS;
-		var EAS=16;
-
-		var S1=[];
-		var W0=[];
-		var W1=[];
-		var Z0=[];
-		var Z1=[];
-		var RAW=[];
-		var SALT=[];
-
-		var rng=new RAND();
-
-		rng.clean();
-		for (i=0;i<100;i++) RAW[i]=i;
-
-		rng.seed(100,RAW);
-//for (j=0;j<100;j++)
-//{
-
-		for (i=0;i<8;i++) SALT[i]=(i+1);  // set Salt
-
-		window.document.write("Alice's Passphrase= " + pp + "<br>");
-
-		var PW=ECDH.stringtobytes(pp);
-/* private key S0 of size EGS bytes derived from Password and Salt */
-		var S0=ECDH.PBKDF2(PW,SALT,1000,EGS);
-
-		window.document.write("Alice's private key= 0x"+ECDH.bytestostring(S0)+ "<br>");
-/* Generate Key pair S/W */
-		ECDH.KEY_PAIR_GENERATE(null,S0,W0); 
-
-		window.document.write("Alice's public key= 0x"+ECDH.bytestostring(W0)+ "<br>");
-
-		res=ECDH.PUBLIC_KEY_VALIDATE(true,W0);
-		if (res!=0)
-			alert("Alice's public Key is invalid!");
-/* Random private key for other party */
-		ECDH.KEY_PAIR_GENERATE(rng,S1,W1);
-
-		window.document.write("Servers private key= 0x"+ECDH.bytestostring(S1)+ "<br>");
-		window.document.write("Servers public key= 0x"+ECDH.bytestostring(W1)+ "<br>");
-
-		res=ECDH.PUBLIC_KEY_VALIDATE(true,W1);
-		if (res!=0)
-			alert("Server's public Key is invalid!");
-			
-
-/* Calculate common key using DH - IEEE 1363 method */
-
-		ECDH.ECPSVDP_DH(S0,W1,Z0);
-		ECDH.ECPSVDP_DH(S1,W0,Z1);
-
-		var same=true;
-		for (i=0;i<ECDH.EFS;i++)
-			if (Z0[i]!=Z1[i]) same=false;
-
-		if (!same)
-			alert("*** ECPSVDP-DH Failed");
-
-		var KEY=ECDH.KDF1(Z0,ECDH.EAS);
-
-		window.document.write("Alice's DH Key=  0x"+ECDH.bytestostring(KEY)+ "<br>");
-		window.document.write("Servers DH Key=  0x"+ECDH.bytestostring(KEY)+ "<br>");
-
-//}
-//window.document.write("Test Completed Successfully"+ "<br>");
-</script>
-</body>
-</html>
diff --git a/js/TestMPIN.html b/js/TestMPIN.html
deleted file mode 100644
index 790880d..0000000
--- a/js/TestMPIN.html
+++ /dev/null
@@ -1,310 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-<title>JavaScript Test MPIN</title>
-</head>
-<body>
-<h1>JavaScript Test MPIN Example</h1>
-<script type="text/javascript" src="DBIG.js"></script>
-<script type="text/javascript" src="BIG.js"></script>
-<script type="text/javascript" src="FP.js"></script>
-<script type="text/javascript" src="ROM.js"></script>
-<script type="text/javascript" src="HASH.js"></script>
-<script type="text/javascript" src="RAND.js"></script>
-<script type="text/javascript" src="AES.js"></script>
-<script type="text/javascript" src="GCM.js"></script>
-<script type="text/javascript" src="ECP.js"></script>
-<script type="text/javascript" src="FP2.js"></script>
-<script type="text/javascript" src="ECP2.js"></script>
-<script type="text/javascript" src="FP4.js"></script>
-<script type="text/javascript" src="FP12.js"></script>
-<script type="text/javascript" src="PAIR.js"></script>
-<script type="text/javascript" src="MPIN.js"></script>
-
-<script>
-/* test driver and function exerciser for MPIN API Functions */
-
-		var i,res;
-		var result;
-
-		var EGS=MPIN.EGS;
-		var EFS=MPIN.EFS;
-		var EAS=16;
-
-		var rng=new RAND();
-		rng.clean();
-
-		var RAW=[];
-		for (i=0;i<100;i++) RAW[i]=i+1;
-		rng.seed(100,RAW);
-
-		var G1S=2*EFS+1; /* Group 1 Size */
-		var G2S=4*EFS; /* Group 2 Size */
-
-		var S=[];
-		var SST=[];
-		var TOKEN = [];
-		var PERMIT = [];
-		var SEC = [];
-		var xID = [];
-		var xCID = [];
-		var X= [];
-		var Y= [];
-		var E=[];
-		var F=[];
-		var HCID=[];
-		var HID=[];
-		var HTID=[];
-
-		var G1=[];
-		var G2=[];
-		var R=[];
-		var Z=[];
-		var W=[];
-		var T=[];
-		var CK=[];
-		var SK=[];
-
-/* Set configuration */
-		var PERMITS=true;
-		var PINERROR=true;
-		var FULL=false;
-                var ONE_PASS=false;
-                var TIME_FUNCTIONS=false;
-                var total_time=0;
-                var nIter=100
-
-/* Trusted Authority set-up */
-		MPIN.RANDOM_GENERATE(rng,S);
-		window.document.write("Master Secret s: 0x"+MPIN.bytestostring(S) + "<br>");
- 
- /* Create Client Identity */
- 		var IDstr = "testUser@miracl.com";
-		var CLIENT_ID = MPIN.stringtobytes(IDstr);  
-		HCID=MPIN.HASH_ID(CLIENT_ID);  /* Either Client or TA calculates Hash(ID) - you decide! */
-		
-		window.document.write("Client ID= "+MPIN.bytestostring(CLIENT_ID) + "<br>");
-
-/* Client and Server are issued secrets by DTA */
-		MPIN.GET_SERVER_SECRET(S,SST);
-		window.document.write("Server Secret SS: 0x"+MPIN.bytestostring(SST) + "<br>");
-
-		MPIN.GET_CLIENT_SECRET(S,HCID,TOKEN);
-		window.document.write("Client Secret CS: 0x"+MPIN.bytestostring(TOKEN) + "<br>");     
-	
-/* Client extracts PIN from secret to create Token */
-		var pin=1234;
-	window.document.write("Client extracts PIN= "+pin + "<br>"); 
-		var rtn=MPIN.EXTRACT_PIN(CLIENT_ID,pin,TOKEN);
-		if (rtn != 0)
-			window.document.write("Failed to extract PIN " + "<br>");  
-
-		window.document.write("Client Token TK: 0x"+MPIN.bytestostring(TOKEN) + "<br>");        
-
-		if (FULL)
-		{
-			MPIN.PRECOMPUTE(TOKEN,HCID,G1,G2);
-		}
-
-		var date;
-		if (PERMITS)
-		{
-			date=MPIN.today();
-/* Client gets "Time Token" permit from DTA */ 	
-			MPIN.GET_CLIENT_PERMIT(date,S,HCID,PERMIT);
-			window.document.write("Time Permit TP: 0x"+MPIN.bytestostring(PERMIT) + "<br>");   
-
-/* This encoding makes Time permit look random - Elligator squared */
-			MPIN.ENCODING(rng,PERMIT);
-			window.document.write("Encoded Time Permit TP: 0x"+MPIN.bytestostring(PERMIT) + "<br>");   
-			MPIN.DECODING(PERMIT);
-			window.document.write("Decoded Time Permit TP: 0x"+MPIN.bytestostring(PERMIT) + "<br>");   
-		}
-		else date=0;
-
-
-		pin=parseInt(prompt("Enter PIN= "));
-
-/* 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_T(date|H(CLIENT_ID)))
-Random value x is supplied externally if RNG=null, otherwise generated and passed out by RNG
-
-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=xID;
-		var pxCID=xCID;
-		var pHID=HID;
-		var pHTID=HTID;
-		var pE=E;
-		var pF=F;
-		var pPERMIT=PERMIT;
-		var prHID;
-
-		if (date!=0)
-		{
-			prHID=pHTID;
-			if (!PINERROR)
-			{
-				pxID=null;
-				pHID=null;
-			}
-		}
-		else
-		{
-			prHID=pHID;
-			pPERMIT=null;
-			pxCID=null;
-			pHTID=null;
-		}
-		if (!PINERROR)
-		{
-			pE=null;
-			pF=null;
-		}
-
-                if (ONE_PASS)
-                {
-                  window.document.write("MPIN Single Pass " + "<br>");   
-                  timeValue = MPIN.GET_TIME();
-                  window.document.write("Epoch " + timeValue + "<br>");   
-                  if (TIME_FUNCTIONS)
-                  {
-                   var start = new Date().getTime();
-                   for (i = 0; i < nIter; ++i) {
-                     rtn=MPIN.CLIENT(date,CLIENT_ID,rng,X,pin,TOKEN,SEC,pxID,pxCID,pPERMIT,timeValue,Y);
-                   }
-                   var end = new Date().getTime();
-                   var t1 = end - start;
-                   total_time = total_time + t1;
-                   var iter_time = t1 / nIter;
-                   var iter_per_sec = nIter / (t1 / 1000);
-                   window.document.write("MPIN.CLIENT: time " + t1 + "ms iteration time " + iter_time + "ms iterations per second " + iter_per_sec + "<br>");   
-                  }
-                  else
-                  {
-                    rtn=MPIN.CLIENT(date,CLIENT_ID,rng,X,pin,TOKEN,SEC,pxID,pxCID,pPERMIT,timeValue,Y);
-                  }
-		  if (rtn != 0)
-                    window.document.write("FAILURE: CLIENT rtn: " + rtn + "<br>");   
-
-                  if (FULL)
-		  {
-                    if (TIME_FUNCTIONS)
-                    {
-                     var start = new Date().getTime();
-                     for (i = 0; i < nIter; ++i) {
-                        HCID=MPIN.HASH_ID(CLIENT_ID);
-                        MPIN.GET_G1_MULTIPLE(rng,1,R,HCID,Z); 
-                     }
-                     var end = new Date().getTime();
-                     var t2 = end - start;
-                     total_time = total_time + t2;
-                     var iter_time = t2 / nIter;
-                     var iter_per_sec = nIter / (t2 / 1000);
-                     window.document.write("MPIN.GET_G1_MULTIPLE: time " + t2 + "ms iteration time " + iter_time + "ms iterations per second " + iter_per_sec + "<br>");   
-                    }
-                    else
-                    {
-                      HCID=MPIN.HASH_ID(CLIENT_ID);
-                      MPIN.GET_G1_MULTIPLE(rng,1,R,HCID,Z);  /* Also Send Z=r.ID to Server, remember random r */
-                    }
-                  }
-
-                  rtn=MPIN.SERVER(date,pHID,pHTID,Y,SST,pxID,pxCID,SEC,pE,pF,CLIENT_ID,timeValue);
-                  if (rtn != 0)
-                    window.document.write("FAILURE: SERVER rtn: " + rtn+ "<br>");  
-
-                  if (FULL)
-                  {
-                    MPIN.GET_G1_MULTIPLE(rng,0,W,prHID,T);  /* Also send T=w.ID to client, remember random w  */
-                  }
-                }
-                else 
-                {
-                  window.document.write("MPIN Multi Pass " + "<br>");   
-                  rtn=MPIN.CLIENT_1(date,CLIENT_ID,rng,X,pin,TOKEN,SEC,pxID,pxCID,pPERMIT);
-  		  if (rtn != 0)
-  			window.document.write("FAILURE: CLIENT_1 rtn: " + rtn + "<br>");   
-  
-  		  if (FULL)
-  		  {
-  			HCID=MPIN.HASH_ID(CLIENT_ID);
-  			MPIN.GET_G1_MULTIPLE(rng,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. */
-    		  MPIN.SERVER_1(date,CLIENT_ID,pHID,pHTID);
-    
-                  /* Server generates Random number Y and sends it to Client */
-    		  MPIN.RANDOM_GENERATE(rng,Y);
-    
-    		  if (FULL)
-    		  {
-    			MPIN.GET_G1_MULTIPLE(rng,0,W,prHID,T);  /* Also send T=w.ID to client, remember random w  */
-    		  }
-    
-                  /* Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC */
-    		  rtn=MPIN.CLIENT_2(X,Y,SEC);
-    		  if (rtn != 0)
-    		    window.document.write("FAILURE: CLIENT_2 rtn: " + rtn + "<br>");  
-                    /* 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=MPIN.SERVER_2(date,pHID,pHTID,Y,SST,pxID,pxCID,SEC,pE,pF);
-    
-    		  if (rtn != 0)
-    			window.document.write("FAILURE: SERVER_1 rtn: " + rtn+ "<br>");  
-    
-                }
-    		  
-
-                if (rtn == this.MPIN.BAD_PIN)
-    		{
-    		  window.document.write("Server says - Bad Pin. I don't know you. Feck off." + "<br>"); 
-    		  if (PINERROR)
-    		  {
-    		    var err=MPIN.KANGAROO(E,F);
-    		    if (err!=0) window.document.write("(Client PIN is out by "+err + ")<br>");
-    		  }
-                }
-    		else 
-    		{
-    		  window.document.write("Server says - PIN is good! You really are "+IDstr + "<br>"); 
-    		  if (FULL)
-    		  {
-                    if (TIME_FUNCTIONS)
-                    {
-                     var start = new Date().getTime();
-                     for (i = 0; i < nIter; ++i) {
-                       MPIN.CLIENT_KEY(G1,G2,pin,R,X,T,CK);
-                     }
-                     var end = new Date().getTime();
-                     var t3 = end - start;
-                     total_time = total_time + t3;
-                     var iter_time = t3 / nIter;
-                     var iter_per_sec = nIter / (t3 / 1000);
-                     window.document.write("MPIN.CLIENT_KEY: time " + t1 + "ms iteration time " + iter_time + "ms iterations per second " + iter_per_sec + "<br>");   
-                    }
-                    else
-                    {
-                      MPIN.CLIENT_KEY(G1,G2,pin,R,X,T,CK);
-                    }
-    		    window.document.write("Client Key =  0x"+MPIN.bytestostring(CK) + "<br>");    
-    
-                    MPIN.SERVER_KEY(Z,SST,W,pxID,pxCID,SK);
-                    window.document.write("Server Key =  0x"+MPIN.bytestostring(SK) + "<br>");    
-    		  }
-                }
-         //       var iter_time = total_time / nIter;
-         //       var iter_per_sec = nIter / (total_time / 1000);
-         //       window.document.write("CLIENT: total time " + total_time + "ms iteration time " + iter_time + "ms iterations per second " + iter_per_sec + "<br>");   
-
-    
-</script>
-</body>
-</html>
diff --git a/js/TestRSA.html b/js/TestRSA.html
deleted file mode 100644
index 6aec8dd..0000000
--- a/js/TestRSA.html
+++ /dev/null
@@ -1,78 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-<title>JavaScript Test RSA</title>
-</head>
-<body>
-<h1>JavaScript Test RSA Example</h1>
-<script type="text/javascript" src="ROM.js"></script>
-<script type="text/javascript" src="DBIG.js"></script>
-<script type="text/javascript" src="BIG.js"></script>
-<script type="text/javascript" src="HASH.js"></script>
-<script type="text/javascript" src="RAND.js"></script>
-<script type="text/javascript" src="FF.js"></script>
-<script type="text/javascript" src="RSA.js"></script>
-
-
-<script>
-/* test driver and function exerciser for RSA API Functions */
-
-	var i,j=0,res;
-	var result;
-
-	var RFS=RSA.RFS;
-
-	var message="Hello World\n";
-
-	var pub=new rsa_public_key(ROM.FFLEN);
-	var priv=new rsa_private_key(ROM.HFLEN);
-
-	var ML=[];
-	var C=[];
-	var RAW=[];
-	
-	var rng=new RAND();
-	rng.clean();
-
-	for (i=0;i<100;i++) RAW[i]=i;
-	rng.seed(100,RAW);
-
-	var start,end,time;
-	start=new Date().getTime();
-	window.document.write("Generating public/private key pair (slow!)  <br>");
-	RSA.KEY_PAIR(rng,65537,priv,pub);
-	end=new Date().getTime();
-	time=end-start;
-	window.document.write("Time in ms= "+time+"<br>");
-
-	var M=RSA.stringtobytes(message);  
-	window.document.write("Encrypting test string <br>");
-
-	var E=RSA.OAEP_ENCODE(M,rng,null); /* OAEP encode message m to e  */
-	window.document.write("Encoding= 0x" + RSA.bytestohex(E) + "<br>");  
-
-	start=new Date().getTime();	
-	RSA.ENCRYPT(pub,E,C);     /* encrypt encoded message */
-	end=new Date().getTime();	
-	time=end-start;
-	window.document.write("Time in ms= "+time+"<br>");
-
-	window.document.write("Ciphertext= 0x" + RSA.bytestohex(C) + "<br>");  
-
-	window.document.write("Decrypting test string <br>");
-	start=new Date().getTime();	
-	RSA.DECRYPT(priv,C,ML); 
-	end=new Date().getTime();
-	time=end-start;
-	window.document.write("Time in ms= "+time+"<br>");
-
-	var MS=RSA.OAEP_DECODE(null,ML); /* OAEP encode message m to e  */
-	window.document.write("Decoding= 0x" + RSA.bytestohex(MS) + "<br>");  
-
-	window.document.write("message= "+RSA.bytestostring(MS) + "<br>");  
-
-	RSA.PRIVATE_KEY_KILL(priv);
-
-</script>
-</body>
-</html>
\ No newline at end of file
diff --git a/js/readme.txt b/js/readme.txt
deleted file mode 100644
index 0662f5f..0000000
--- a/js/readme.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-AMCL is very simple to build for JavaScript.
-
-First - decide the modulus type and curve type you want to use. Edit ROM.js 
-where indicated. You might want to use one of the curves whose details are
-already in there.
-
-Three example API files are provided, MPIN.js which 
-supports our M-Pin (tm) protocol, ECDH.js which supports elliptic 
-curve key exchange, digital signature and public key crypto, and RSA.js
-which supports RSA encryption. The first  can be tested using the 
-TestMPIN.html driver programs, the second can be tested using TestECDH.html 
-and TestECM.html, and the third using TestRSA.html
-
-In the ROM.js file you must provide the curve constants. Several examples
-are provided there, if you are willing to use one of these.
-
-To help generate the ROM constants for your own curve some MIRACL helper 
-programs are included. The program bngen.cpp generates the ROM details for a 
-BN curve, and the program ecgen.cpp generates the ROM for EC curves.
-
-The program bigtobig.cpp converts a big number to the AMCL 
-BIG format.
-
-
-For quick jumpstart:-
-
-Run Chrome browser and navigate to TestMPIN.html
-
diff --git a/js/tests/BNCX.json b/js/tests/BNCX.json
deleted file mode 100644
index 7cf034b..0000000
--- a/js/tests/BNCX.json
+++ /dev/null
@@ -1 +0,0 @@
-[{"SS1": "1520a952de349f533b6aafdf89373840c6cedb5d80c10cbb77fd2977d1260f261bc1aab33387ea29d5a229d03b86b755a1cd958b5465b765789d45d69394254309dbeca19eb8d87e2b68b3b3313d518da6af44cbf7dc99db73345236e0f69ffb049ae528f8ea5f1f431e5292b50206951e0869e471140dbd044533d74c8f35bc", "SS2": "0b5dc395464513d1b8456fb4b1e131855a171693043115db8b9213fc5cb6ab060706ddf77a2d716129f095627102642c916f0528abc8c613dc4e3efc3685407206502735e18685ca4870db8dfaa6bcf65c0ca58426841ce84686b495a2a07f61167068abb790a36d2bd624a6ab2a7de51845d2b5adc990c1a5a339081607d01c", "DATE": 16574, "PIN2": 888, "PIN1": 888, "SERVER_SECRET": "1c73290d1a444dbf7d64d5ef22b152165f84b6bb1bbfb5b961de08294d7194fc0bb8652116b2e5a237706de08731a6b3089cad532a8fb1faa06a1deb36b037e00bcfcdcf98cd043a26cc6ee4b551c6307c57eb56ee5c005fd92d08598db9c47d0926edcb97b370b4542d5bb2ce4fd600b4657ec6abb3503e4172af59cc94d4a0", "SEC": "0402ecbb873cfd1a27d39d28a3e8cf25b9e11b8825aaea42874440e21505a0f5291745d9a15fc477f2228374bdf6a67633a3eb428f6622376ec4ec9522b8a75ee7", "TP2": "04185f9348a8dc152fe4c5c9a3eafa39b8d49302b7c380b26eb50d7a855aef1c340e08b35442a02d2eaade3b1cc4a502b3cfa1532eecb7ea9f2664bd4b86123187", "TP1": "041a5cca30f0a4ce9ebf97052fed980adcba9d486dbe688b4793779f46e0269e8e01239cad9ab5205cfa2b679b9f63c8def786939ffa97e2a8f9d16ddb4f23a731", "CS1": "0401435d98ba070157b3f808c8f07a8ed7719f2717ec65baf631cd8d068a7a43930e9e700a8335caa36bc28c5c673e9fd132eb9b40c90cb66675b049860b07858e", "CS2": "0414130490c24aa99fbc55f242d11ffc5ffdf5c9c3f2430e24a23f068cb10fb6c405ded7a269a807ae2771a8c5984ec3d370a7cc565541b31dd44cd2cd3156b56d", "HASH_MPIN_ID_HEX": "d12467cfb19e88fa1af70615874ad467163a79b3bd666fdaf9ff3a4e76871967", "TIME_PERMIT": "04227accf008a0c0c10a27eb4ae833ef056613b3964c2d4f3b9f7a2dd84ec6a7c819eaa5b37faf57016f5806ac236549c39098bfd6ce50e0a2d1e8f7ea64ab838e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33345a222c2022757365724944223a20223635303366623332333137346332343639353133636337393930346263623435406365727469766f782e636f6d222c202273616c74223a20226166666366356237333965666238386165616337656464396335663961643631227d", "TOKEN": "041739675948c978b2b4ac4b380d93783a4c7482f812b645b26f51dd407bf9c5121bb2cebb06e9b3c5f96b5d6619b52194d8b02e7df5de527497bc42bbf6aefbfc", "U": "040c11c1d9d9202c861ab7920823cb0c83af6bd679fc52ec9604099fbb2db78a8908b7c4d769e9d90f7d9b655526663a9e7bf82ddebb3626c6be0b20464dc2dc34", "SERVER_OUTPUT": 0, "V": "040b8ad73e1199b1e3a0d767accaf340fa1014dde6c5a188523f74c8f4d1318c15028387e61f456f5cede275edb1e04a81bf9214779a5dfb6731f60b21ff46f12c", "Y": "235e6cd2bac4f802c13c6513bce1c11cad6e51f45b2516cc8eb7edc256e5a203", "X": "064bcba79105dac17aab45a810cdc802fcec526fcd4b878f18407a0017481413", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:34Z\", \"userID\": \"6503fb323174c2469513cc79904bcb45@certivox.com\", \"salt\": \"affcf5b739efb88aeac7edd9c5f9ad61\"}", "test_no": 0, "UT": "04155e8411542f9a2d7818c43e539d994f99dd9b8158bb2373704834f2a27fb59f116341daa21cedddb3d4393bfaedc2cfdf2c0983d280e87a9b0e01043bab9557", "MS2": "2243a7cc0e5f776b5ca1426d481a1ce565fded749f242b46f0a14b09c7de37c0", "MS1": "0bc2261afc713cd48b8047112ade92077067c31c6e0a6d732c7d77ebdd0d5956", "CLIENT_SECRET": "0411e119359451da0b6c6f17eceb64a20598c33b213dea3b6891eadd131200c49712a352a5f8ddb3260667758b78ac7f2ed8da5b80926e0abfbaf89a8caed920b3"}, {"SS1": "0f468b9986919bdd7c2d5b1805b0281264fd9e33db0b658b065966733b78d36f1eb4f5981b41b7da15f1386ef10dab2cde16832131374f9fe8b707176c8f5c981c3b3c79218ab6f66746644ae7c321bd466248562832091eeaab9f781bb17378227ce7c682a39864645840036e21437c7132434bae53b3dc9e72bb0c2d2189c2", "SS2": "2171885f0771519da9f347fc923f947c6833a9d5d084005b906856262dd94d7b1ed457dad2ffa72cbc478b4031e7e2567c0ddca977bde0b494dec929f02e517b09aba69dc3f41588db9accfe370501879568b25c91a9f4152ee3d416dadacf481e4ac7c1cf2934e08cb8331a5782ca1cdaf3a83981614acf9b6c6780e7ff0f77", "DATE": 16574, "PIN2": 5299, "PIN1": 5299, "SERVER_SECRET": "03e47ee3315b9cbb277468ed5c488f2b0b3a262b15e628e0d5f4f129e64a1fad0cc84af7acedd5225e7d40df5155db23f4bfa290adff6ca31c4884488c2d55a10be2b0f01e7de752201c4090a3115322e0a76d29c5fcacbd4d049b50f0089bbd1235b5935d93d9c50b521b2ea8af29ac5f52e40125076e97d1395d1fa22b21f2", "SEC": "041abd94a1806a932a0281f8b71d97273dfa73a3b73e41725973e4269944a48457037943bf74f29f9652316a0802ffe914bf6dd721f356caef4fb93cf2a68795e0", "TP2": "04076852c9d627e10361db7a5d1338308c5d92312ddaa4996d4e3767b7bcc6eaa621c9a69d1264329cdf17007dffea8b8053a4dda479dafc775ef059f85add5230", "TP1": "0405c9437dbd17780b5fff9c12230b048a14c14d5f4d51e415c67d51e995f73a5b1a50c5259b6fdf92b704aca052670dd142e48992891b052d6e59ecc142be6a37", "CS1": "0412d3a065010d42084337a9d2e869cc44d7ce84b51c08a1f78cf7522c487f377b1810af8fb5c69ef5585c39eedd462fdf21681c970017aea3539eb1fc46136805", "CS2": "0420a2d7bb34dd1076fbe3ec090b0d33dba435ed26a4ca385e0a443ee4db9f13ed065e9d908a5e174a97335cba95866b5448ce53fae031d22e2102ad45b1d7df1b", "HASH_MPIN_ID_HEX": "55a884c2cf6ea921cf3238a9d489b22c68e096d96a021ceff6f8c220798229f4", "TIME_PERMIT": "040340b91db12b2d3b403227d35043dbccdaab6ebb62955983bd06e5db8822b0261678235685c4cbb5a4169a6390481470fb788dc91a69056a4862ee3697094cad", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33345a222c2022757365724944223a20226330323037316639626664303631353932393935363761383633383363343433406365727469766f782e636f6d222c202273616c74223a20226263633732346535636561373564343065316136633334633933633164333239227d", "TOKEN": "041d50f62c5bf35aad38b7cbd91a919919ff6abb5f7e6dee83450adc9b4900235320c1f4eb7bce4d14143d36c7b362aeed90afb48e84d83bee1c4cc133abf68adf", "U": "041a21408eeb64776ebcce3f814485476f55882cbd797fa6dfbeb6ce5c506081b209308b70ba69efd2594bbb88c2e09bdef9b9b3e49437f2f5f296dc6853661954", "SERVER_OUTPUT": 0, "V": "0405ddbf8a26e7958269f103e8ab5ef45c20cb845cade3041fc98075dd9b50e3d821a67a905a19b694404331986d1ea1e8543b18748efccceb25048584b4b20116", "Y": "1f62d44eb0a0add266210aa2209d3184abc9a9a53d14b6e877291df1d6ff41d7", "X": "104788b501987fbb438213927dc93a4493693d981f350924678f55787c2ffb76", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:34Z\", \"userID\": \"c02071f9bfd06159299567a86383c443@certivox.com\", \"salt\": \"bcc724e5cea75d40e1a6c34c93c1d329\"}", "test_no": 1, "UT": "04047ac3439fe68dc9bab6d4a5511e7770ca1e4dd2a617eb3be500c3c95d669934028e2c0937d7542fd70ea7c623c3181aa832fe3c7160e458f6341c224c5c604d", "MS2": "0d4827f28c094a2c6a29e88c2fa6e36a9aac8e21c9196fb952b26435ac4fe448", "MS1": "1ad3a17e1667901e1e865164eb25480d3dde6d8b350af7ce701f4730f0d26b9a", "CLIENT_SECRET": "040b36db188c8dcd415a9a26e90f9bb043cf7ac0527ca43a5c71bfd95ae9c17c420afa015d0fe3ea8c4da06e9ff70fc444b0ee9f9a1f227baf2687da9e64c2a7a7"}, {"SS1": "21b27fe347dfa66bfb098f848f4a2b474ef9e23d6dce3d6927c8559a0ce901ff20896dbc80ec32c19f6c9d3eb248c397a50cf39bc875c256398ec3d75ec61e520b3bafe5970d46c2671a20ada5a9879f5661bd9f63f5d8fbc0cc56bcd39b9b7a23de3f98dca07e67c7668014e5367a979206b5c98611cfd597319154681daf43", "SS2": "08198a7a3d2820b8987842d2743dbff22daf00078ebd5eaa3983d696f8a3eae91cb1314e7dddf0a47aa4b3570b80368b6573b5062767aaef9a5b9117484d7e5c0ca2f89d23469c747c4ed6cb30dad0000d85926ae5aa6de012ec4d56f35c5cd5231225762c78d43eb15b4d58615191d8302df6f25920ef7da9733bcaf5549f08", "DATE": 16574, "PIN2": 8009, "PIN1": 8009, "SERVER_SECRET": "022802cf792087f376c4b6aa8a980cd569e5f2a3f505b9e0455d3b67c5692d3711301dd42e732d6af6cdd7ba069f51342240b7d6478423ce063c8af04de0ebb70183bead7230e056c34ec775a4fe699bba00772ce5895db260a0a1106cff4b39094e1ecbe035af718f4f00d265bc18eb9cdbc65890ea94f9c95a5e1c8edfe15e", "SEC": "04057389030a78b7b6ea26f59248c37fea17b0e522e3699848ad5301cf1ede99291784540e7418afb2ea6d792fabe2a9b1b04b5871d0a3bc81f4b15d8043d9e283", "TP2": "041de5b1b6e33b2c07743e53b0fc02eb8cf0a480761864dad14966eedf9348dcb21c75bd9a3f56299e814e60ee9e1274eebc18f433cd107de65f5dfe3a67109718", "TP1": "041038ced7b5d89739230f0374851c0319b218c833f55cd09bc253be1077bcd12d11d5edded2d5d4aceb1a13263bda49ee8292f3ecbe07f9e40206da53a4923aaa", "CS1": "04239dd5403d85c3b72638d4a4adcc7bf2046c80b9ac2ad56183025a7caebf18f8101ed98295acffe2ae8444914741aa58eff00aaf0f01828fff2be490c8fe5af3", "CS2": "041f6f4c331a39b7644cf3d7ef6be4ae012bc89223935a23b526d5db5da611af9a10126134ba60e1b2bf01832aa29349c11842153af643a53b6d090dea02865483", "HASH_MPIN_ID_HEX": "935f0d6bd07683250e03081005f149b7bb106a11524733234e5b6516923ce8f0", "TIME_PERMIT": "040f58e86621443f94b7770d0a0916a4a5079748988a98f84bcd253b7044120d96137e6c5b3a331b9e35dfcc6f5991f99b2e7d83f93a4dfb9c118a92a040535e8b", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33345a222c2022757365724944223a20226465666137646565366465633866333161636261383839613731646136623064406365727469766f782e636f6d222c202273616c74223a20223133643563363662393531633931366531653834343434626131376336353938227d", "TOKEN": "042152f07e5fd78a1f843390d41478d2d5f0437285009408f2d63ab190434a83f403fbe78d63da99ed8fdce141ab12625fc36147b48e5a566f3f38a3b7f8b1dc88", "U": "041fb404a10229be4ee993b6d70cf4af1f570b8ab377a07dedf08fcebd02fb44980fd3d85930d15611ba1a2c33015bfbae9ad57757169499066ffd069a1723cade", "SERVER_OUTPUT": 0, "V": "0418bea256f235243219296b7f5e2b0dde4fd54e2d82d80cd7882600756f07d1cd13e4d4b3ec3defcd9e5f45ba110215e3b705534ecbe21d334261cdde1d0a2c9d", "Y": "0a40ff78e525b2bb445a4912a13239942adb5e476f55a0cba5d88eb85b6d40b1", "X": "14fa7ea042f6e80c90c29f031b25233d6122fbf0255a4ae12cd8643c2e9ad749", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:34Z\", \"userID\": \"defa7dee6dec8f31acba889a71da6b0d@certivox.com\", \"salt\": \"13d5c66b951c916e1e84444ba17c6598\"}", "test_no": 2, "UT": "041491587ea612ab06cf8380fd9f4c4865c60069ac42fdc5ffa3077570484f29ed13ff03b544fb28df4143cb89a2f1a01cf2552a621d7b35e2ad9a6a13484252bc", "MS2": "1ea4fc812244b362af1e00ad29a8a20285062ed3df75eb6934b03f733dd8637d", "MS1": "0773c896ecad1274e67f78c45506c5eea2ce4d11b79f650e779c7d5a37d656f4", "CLIENT_SECRET": "0420f67cbe2d0914ea983336afaa737d93e22825578f65d7fd7f6de1550e47eba411d3bdf73908b88a3980e00a37bea16836e7feb5301e02f6c748ff5dfb88a8b3"}, {"SS1": "019a441b3e885442206c4ebda5a811f9e39f7215c2c7494a9271f8174027d7d81381e2c00f01f5ec419985b29ea6313862b57b37708d40e3cce8cd15da76ebd51afd7703019ed8ce53bbadc466831bbf0934868bf0b0ef7b674daf56f8208c9f079af4e6103b4c77e49f3620e1fb0182738f1008befdf51f14f1920fa0e3a7b7", "SS2": "13979da829e50cb10d90168792f0935576bbe606c3b9f4eca4f9859087c16d701f17425a5c08ea5b720e48c43988b3b4a24c8dd88efdc833f3f407b348d0b64719c3a113a1e9a3c75fd037a2dbceb65810ab46a71ed01d102073ee23ea972d1e094cd2577001081dc3d8b33608f7232f2e890487b759fa8bacedc8ec178d78fd", "DATE": 16574, "PIN2": 9236, "PIN1": 9236, "SERVER_SECRET": "183c338d428a1b431460090908981ba162974d3366e920e106647a0518befaa1239e518bd8ac0d0dfdff38e980afbbfe4c8cca7a4df7c80e7a93206540e64d24148a8adbdb6d91a8777d243cc905741e674a216b9830d628469bb44d0a97f93801eeec00b1ac89fe1e41f8995002997c0bebba12a9c5f16f61c8b758069ca7bb", "SEC": "041aa9a4e8ed6fdad96a24cf4b1e542400a80777d2b82c37f8750cbc2be5939c3d04aff95bde7cb335cea825f3a9fd7b17a7b46960f99d0b2f144d54f1a7a889ec", "TP2": "041d9a480dc01508acd380e76853476e409351ac3f5f53792921187703f81519d52162972a19845f4de95267bfea8aa98ed1862864ba99093188b1b58a58fe5dda", "TP1": "041d041c5d8848da82deba27ffe660b0db71aa8ff268186d0defec7cc2593103d31f5cd79818e87cd7fb76b9b888e2882bedaaf254dd2acc1e1dd4746b07039597", "CS1": "040dbb037c6ebade2e1834a15d1f900a7fa526c974b49afebfdf7b98321e6554cc0c7bcebd582600d3510e8ebd43628ae2558a12a7d1ffbbc5b36b84aaf8e9afb2", "CS2": "0405dd5653c55e6b56285b96c627b0b5d19182e306716e6713e7d74d3779f888b60aa7eea6c8c9ac1ee23206d24b63f2a736e4a0e99a05e7f1edf2e150bae894ac", "HASH_MPIN_ID_HEX": "48229e13e1c3180914eab5fb2ad71d51bd42819b105d15084a6ceb27b67b2cea", "TIME_PERMIT": "040844b552d359c4948bb6f682f899eb9be5a4b987521a39c7878d68a8fecec0351b754f5f16396a2e2ac9651054b31f843ebfc610e18ca114026126a01f167e0d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33345a222c2022757365724944223a20226336623261366432326334333063333237393066356633303932646236666535406365727469766f782e636f6d222c202273616c74223a20223330303036663866623736306439396132633736366563343738363162663563227d", "TOKEN": "04175619ead75d0a35c8bc5b363a7b860ba885dd6792da77aad90a84e28e04d89b17acf8c008098af8fa683dbae1f5a21418aa56a6593be85bc62eb4b92778b132", "U": "0417f23a5a7f2a0d73705c1aad04a50cf5383e6bb5bc8f70e754591dfa9608dd3f103707fe6621b2d96c71b67e0f3b7a6c0d9a7e42ccedcbd14570fdb21c1a8afe", "SERVER_OUTPUT": 0, "V": "040d3c4ddd87fb3b6d0cc84806feeb04e97d5a425c0e4f9d57542fbdd93070e02321c76ada3f6f5443e744eb1d07d010a0922f0bba8b7ac38bcd0d869ee9cb08a2", "Y": "0fe1bef7f0c2f00be843cffe52489e800f76bc7f2892d283ace814e4d808d758", "X": "07d69e95baa1873f1d1abc755846a5a2ced5e3ed9a3755fdc218931dc9975258", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:34Z\", \"userID\": \"c6b2a6d22c430c32790f5f3092db6fe5@certivox.com\", \"salt\": \"30006f8fb760d99a2c766ec47861bf5c\"}", "test_no": 3, "UT": "040703a76274cbdf19bdcb64e943d8c6c06769e8c15f275996210a9937490a3a7b2328ac7ecd61cbde145d3896fd9b943f23e46c09910900279dbde4991be081d7", "MS2": "0d1d899d6c396e9415a7ce3520b9000f8f5a5e7d47ae5c739b24b971bb8dccc9", "MS1": "0493c81df73802f88968d6c06c3834ab34cdf740c3d003178cd822e389b9b260", "CLIENT_SECRET": "0401a8a91fba681ed30da9659ac4a09b02a97a6916373a757ccf8902c031ad49c403a5ccc174dee4352ecfa7a439f630fd281c487fa840aa73b169ceb67667c125"}, {"SS1": "1ee4f64244435fac2768c632f7e6e8970e24d0fce21e5012a5bfd0f53ba14e9c0e1674e4d9119fdfa43f312c79594b6d36954628a1ffce8eca03c27d2f25322722d0366d084a8a356be01c5acbb2859efe9c617441c14cb7823fd4197b0fab2e13977f34642ab1fe1a5442edabff21625138348435040f6343c10480f96ea010", "SS2": "0bf923482e8945c8ca68716a5e744e6c8a67551cc35b16b9346f5149e32d3b9706f4a2ff66476452a4323b4d4b24758ab9bbf5f0cf9d7e9a0522d3f9ce78310600a109a9efa30d3b41ab04f86ddc561a00cc9d6a3502abac324dbab1fe42b2dd107ffe6c93c6172de1ca619c17eeeb0d26d52577c2bd4732dd14deb3f23b36e0", "DATE": 16574, "PIN2": 7948, "PIN1": 7948, "SERVER_SECRET": "0a074a16c398ea6b8a55c263766497977efaf5c2dfe22195338b37963dd0a1ad14470fb1f77e83979192697cc21f75552803468ecb447d705401b02aa58a948f10f734727178bce6f079d6d39dc110d87017cece3bed4b57e1284c3acb2dfcfb1e37bbecf67fda8eebe447149042091743195cd15ce2f2048ce753abc3575308", "SEC": "04188a016078f4868432475c62dd5d2328850836c9f7b6722bdd44eedd7b00b2e914b683bb574dcbcc2eb51b7c249b87c378aface89b51f21deda7f9d3f650cd17", "TP2": "041c26065697b7922ea6244242728d606db07670863cd64cabb0d7a9bd23f8232d04069e1badf46d4c3a5983ffcce8a78b57b190eb14c2a81d917b1ca6bac3a23c", "TP1": "0411c27ec8ef5e74f2ee340c5491d07ecf9513a26e92896aa1abbb8e53d1403f7b1365a2148a432fce451ab7e7b5b9c66dc2412355936e5b0144b513414602ab42", "CS1": "040362c73ee7435cf8a78f5c700daf6b9a8404f0c62e2340d4168f84b3bab3e1301c036a644eb8e626ed310a595219d96fc000a0084f85b144c0f06f713b66a58f", "CS2": "04227bf99836c8daa5c0d15169f33edbf29e16c56175b7a0cafdc003432116ef960399c375479aa8e1fedb5c4612344da2bfec4dfbe8653a7a5b806efa51cf8e36", "HASH_MPIN_ID_HEX": "eab4e9530b180aa597ec32a125245d8fb6699da0b3fbebd501e574eb961a3f39", "TIME_PERMIT": "042337defa34c32a3881b2acf801cb935bc382a1f867bf0eec2f1a30a8317f54370582b3a7fdc57a68f6460101884f2a76d90276f19fb56cd66c2043ae4b1a09ee", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33345a222c2022757365724944223a20223836666538343435643066336337333066626665613330646235343035636436406365727469766f782e636f6d222c202273616c74223a20223638363566616361386230303135373064346236376562393462646239323762227d", "TOKEN": "040ae1365789a7381ff442a19ff09a25cc3d31336da12a27f55ba80bb29401abb91607dff8fcf6be38d984c151f3d752a19e81b6e90bbf4385fe678a3e16daaf18", "U": "041108ccf4589d7766ef0ac969f8139525393745ddb18c10a42ab2a325f0287b111bda113c3a09e91d918ec5826ae9d6878697b217aab7b4df4e817f64c3784c41", "SERVER_OUTPUT": 0, "V": "04156927e530f9afc8f0232f99893d84f26d890144698718ce5ad54b717547b67f2252ea5f30b27f3e7b8613c96670f3ac36649461076c3b4bcbc40001f2341275", "Y": "183bc2bde80fba19d0f1ea345068acb2c856fdc8f0699f5051277d7b45f438d6", "X": "0a8a35c4f3ed665bfba479a6a08a125e6a3e41561fb6b11a158ba7ee5c3fc23e", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:34Z\", \"userID\": \"86fe8445d0f3c730fbfea30db5405cd6@certivox.com\", \"salt\": \"6865faca8b001570d4b67eb94bdb927b\"}", "test_no": 4, "UT": "0414498cfa890a2a68cc9aa8041184cad78c93ec04c38409200762f6513513a3462168adfd3f92da74340bce5cf4f35be2259ed7511d1cfabee1484d690f747ceb", "MS2": "2016e100f00700bc0bd6becd5597ad9247907c35ee32338775c6fdd9dcdca745", "MS1": "21c0f1ca115242eb0bb0984ffdf1e1488eba3093ec70ebdd014dde253e203a4e", "CLIENT_SECRET": "041320c0d639bdecb59089e3bb1dca7a34268741f480ab1a184d1b5719805d7cd10e8eedb02d56ba2d3503ea4f13e757f074759a9def22d948e17de3bad79f155d"}, {"SS1": "1b6f46bdee6acff8508a6abdc397dd656677e1e4f3036570a848155e32d84ee605ed99e87230e8e82c9ab3b1546c57dfee6e09f2907e0374728eb12514ac75110b2e551a4cf86dfcb85303832f67c8e518dcb64283678873a756ab53c18c58f51ca355bd2736824fa3346372cc76b48802eae6e85aea0ce052fb7049e1f005d3", "SS2": "0587a37e99aec3d88d75395f180313f41d97afd5296f5bdfdbb31e0f4db7069005d7671c520bb1d4559e1f6ae9736227ab780bf51781b9dd07678de732214ab2139912c4f36ce0dcf76fc417e4721e3b14adf57776764b8ce54e372c9859060f1cca749a6b0411b609360a3e4652d320dd60bb0e585a3abcfcd5a46f947221f0", "DATE": 16574, "PIN2": 1463, "PIN1": 1463, "SERVER_SECRET": "0c336c8babd0b3bc6ec5c7f1cafa17fea49cb1a8076e2ac40b585008f53e8c2d07a06d67c3baf6fe2c6ee58df0124373a0c607165c74f469514b559d9b5ec16a09693fe3af5a8ab0329b49124f41b6771dc6f7194c2934e6bec42fc9db274aec187813c02e5118cec839d3f9d57e5dbcb5e70f4c113f9a366dab425e88b9251c", "SEC": "040b5f13e43d0e152c45754f8dcdd241f55549c86c46567749ded57b2ce29c39e00a01b1fd1022705d6faa2a6f1fa6cd4e9dcaf16270b7630d3a6747378c900721", "TP2": "040c6fa0a22d35dd840b2bddab6b4a15d97b038d4056d3a961c29c1e57158056381e974ea8dd04e08d418948112a60c17ce91c66488984818a14206c32b1d755a6", "TP1": "0405b721c01c1c32091a633887f276c0bd8dd94ef7282ade8031fa1e4b2749442705a656af0aa44f5a2219dfed66339868437678e056349801a437afcbfa7cb429", "CS1": "041c674ed4190bdddb998759f680bc170f75013901972099f93f351ab9316d718d0b856b331c4a0a003be14a7845a76598ab58e144716015842dde9b231439868c", "CS2": "040c39a9aa1327bee91f9f753db352d4ff787eedebac6fe997f08d40cbc53f1ac20811b41a1b67b5f09452723de8086b42a10dd40e6109d4e203e487cf7414088e", "HASH_MPIN_ID_HEX": "e9e2c4ca2c3b579f0ebf4a536f4d7592162446287c88d20911264966102e34f8", "TIME_PERMIT": "0401155572f8f4ad5f54c64592b5c0ff55efd9204b57bc248dbdfb1be8b845acf3089c95534a1693ff02ae81171c113bc77ab09de27083e7bc95b59b0436fd5047", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33345a222c2022757365724944223a20223434623963613539396461306330376134323965306364356164363237666338406365727469766f782e636f6d222c202273616c74223a20226239636433323066623865376530646331363036363931363163303763633535227d", "TOKEN": "040ae7d1376edd21caec2488262f5a76da64794502eb6c91ec24b9a23c936d3c4c0a2dd45f31fd2d6f2b7e13f8c51c5929e7044eb10d691f2a40144dc6302b13a7", "U": "04103e7ba05ba7f6eb06d9eaaa6d5b0939aafb6c72ce417d39572283bf42b0e8d8112c5f64c15fd008a838b40ca7812246a29e31954d08f021f60ded0e33043ca7", "SERVER_OUTPUT": 0, "V": "041c2f73a4bf39d7e3f1eafd400499127efdcefadff8734d8ee061bc2c052fe1b12258ebd8f60861937052b8a86360e5a1a0b5ec2970fbd2f424d03a6b7c5d6ee9", "Y": "100189ca8769a2e2f832dbe8488e0da582b60e71b47290302445688bf0c965e3", "X": "023e85881c4d8d4d9193f9653f1de04d8aae3fc167cc59a00addd2acc48edc22", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:34Z\", \"userID\": \"44b9ca599da0c07a429e0cd5ad627fc8@certivox.com\", \"salt\": \"b9cd320fb8e7e0dc160669161c07cc55\"}", "test_no": 5, "UT": "041d0207f5a3a3f1229bad924f50e229a9acdd8432ef3236a830d813241f2664f804f4dd5983e55066504298808af93e92b8f1b08947166ade9f7e115410095a3b", "MS2": "17d927e498f0fea9c5d712c93416834a1eee4224d451d48d5b41c29fa70e01bb", "MS1": "10eeed159fc3e9d044dab63c56c49f1a99f831e67d2f6a9e15649688f8076bb3", "CLIENT_SECRET": "040ea0a2ea39d57085cfa10ba2e0562f5230c9821e1b691bfaa87ca826a5d2618222019bab9704ef29085e70bb1b61e39b2ce2f66b5f3aadf9f22818053af7e543"}, {"SS1": "157b14bdd0d3473b25d4a5d67d17db205178add1e2a297f7aa4c9b348acdd96a04d5d5dac5f0684133948f7715c5b1ce74ee3b8c6a8e423c4e2bc370b05824f0211e5e4dfdedd92e0a74cc91e76074cc8cdcb4062a791b1e4cbc44de9b77297c06d74ba2099317a3c9acfda4fb9a60babcb641a8010c94e6ec48af7c19bf79a3", "SS2": "0a9d1ed983875415facf49a6f02dc28908c8ae96b47e31995f07211fee22b00b0f6a1017ca12a517c2a73fee8b8a28eab2fb913bdce9267c84b590e1c9a8c5be18132a5d92959868075563f2440d33a53e78e7d9183dfdad21481906c382e6d121a69e8297190256b08d9a126726703ce0431766d3667a71947505d99c39abf5", "DATE": 16574, "PIN2": 4669, "PIN1": 4669, "SERVER_SECRET": "224ac6bc9d4a546ff386a7716ac9a41c5b7e0f713a83967241d26f0f6c1129701b455ffde5e6695a8fd04d51e60488e205cb3b8f4dc356798c96636581456d4f189ef17a237e43cc303f85daf17307e5ff05720dc80958e2622786ceddbb590c23acbedc1d403693198040869d27ee21586893de4a9c912c010349cb56be4d6d", "SEC": "0410f6d7a8c4bfa1a8143e441ec1d9cc5eb843b84f9ec82c01364ea8fcd1e2517105dfc06348559d886a92b22a4cc35df52e82b2cca4725d7215cf29846d9068c9", "TP2": "04137c6b8ff2f13dbdbd4070b3f255f30267a9397340fa1682b04dc65e468765502211e9026b11466679bc39661c8676f63dd4c53bc4624d015bceb57c5fc82858", "TP1": "041ff46177adac17df37f3ab5ab8c48c97ece2311f1a1d593a4e656f935776f9f70658779e3010e44fd8cef31af1faae079e40a51503fd42dfd46c9b280748aece", "CS1": "04066ae71ccb707233e1d4f4bc288b1ba838c9e7483a5ed0d0b3bae30c89e2527b1098823f188abff8eddbd46c17a6d074730288c2ba36ce678bcc4d1404e1ff0a", "CS2": "040d5f8f5ca6aeb16e3955f2bfd1f9a8a4b9d7028233d41666442ff4ab6de06f2609c69e0c3c741145d2802859b132aa511ad7fe3f386b74449529ec680ca8ff23", "HASH_MPIN_ID_HEX": "b684b908a36cdb11caa3f7ff3aaa3803982fb494162e3570e6a80b821e63d36d", "TIME_PERMIT": "0413e6355e2fb9f1339c20a080835eac9503881d34590c78bb0c037fbf815f17d9204e04056b68bed0ba41d4d412e2ce047134add57c2527d764ed963d9db2adad", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33345a222c2022757365724944223a20223431613839386362363566646530303331373433393565383237363862303362406365727469766f782e636f6d222c202273616c74223a20223538373937353363623336363337663134656339393164383435626630363132227d", "TOKEN": "040fc4de63abbcb51a04bff2f296190dce7eb7c9987edee7eca5db4278518ac7c71c6192111e25af1d89763c8c6729cabf12216cd9bd8628e609c0f87f7b718ef9", "U": "040f71ce92ef2fd8e4f66db7417b6fdfceb3644a4c41f07bb490e0b3ed524244180b7c512cf9c511bc305d4c1bf6bf268727d00760d34500caec0e6b4e09922afd", "SERVER_OUTPUT": 0, "V": "0416803454320557fb14b26cc8715a4db95c3b5912776adcc6e67043d8f5ddfaa415205c9f47c8dbf23eabdfc36c1ddf8807d84bca36de5aa122eca80871411b86", "Y": "13ed4a35797b1ddbc6f0cafe2d838bf7067f2a80fabae4e2653e52bcec97d699", "X": "13cf2080bb21ee069256391d3d873bf2b763b3a6091a21d6efe8d84d819d6421", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:34Z\", \"userID\": \"41a898cb65fde003174395e82768b03b@certivox.com\", \"salt\": \"5879753cb36637f14ec991d845bf0612\"}", "test_no": 6, "UT": "04213d409fda21346b2c9b9c9ef5b9cfb72de7f4338ceabef411e5b615a5b38d951ef4570aabb984bf0cdf5903abb45a2dc85a9213b5de5d5583659e70f241e6d9", "MS2": "10b0d5f70d6df2486d6b90652d5e07f558b2ae1069cf08775991c658365329ac", "MS1": "1920c5a556df7c1b2888a6e249a16239ad2918bc73eb1e3123bf28e78e021e23", "CLIENT_SECRET": "040525996f1a9b1b15220662eff4ce3839fec17ba56990ea961104edde7a6ea05922d06e8bb482acf017b69da967ff372075d699599ede766c79a6c2ab5b3ac12b"}, {"SS1": "23822e2afba3617824294e5045f340376d5a6def202b3a3bc34d92bc0b9895170844cdc4e56515a6d3f2cb277aeb38c0d6e1c66477c5b5655678c2f1d2c035ba037b72d8fb714fccfd69051d7f7af2d8198fa90c6d2e91b877940ef3cb05800e0d0eda45d97b19d3d1082e692cbda6089bae132250682ad448584741ced02f7f", "SS2": "100b500226c822d0b106afd6f0f00127f9669e78d84dae2f6fd4a82e543967ad0dd61190959285677647f9235a1dabeca83cb8af533a8ca3fad07ccdf1fb3ccb00084b93954be03410133a73c953fe62db6d924de5c2dde39ad7ede938bd684f097a9adecd5be3d64de34a64ff93c5c369b3e110064367cb03170533b9823daf", "DATE": 16574, "PIN2": 3269, "PIN1": 3269, "SERVER_SECRET": "0709c6699cbfa6ea7dccac48197269e8368f4ff593501a554169500f7a5f3cae22ce9601f032529a3054eff2b7248a84bca013ef3b2ffd8955ddfbc3ff006be11e047878f4d8145781376ff63716dbdcb705c75d6a895ca867688e7e736b26850825d0363abd8ee47683d46d6f651fe3298a7f9a70c9e9324498e7e6f6055b7f", "SEC": "040a091aa68f787dba32ec3a8cd999576a21969c97de5f0e7e8272f15cfc27dd6b01c307cf78f8240b42929716020a8c121317f4d47d3157f6cc558053a716ed79", "TP2": "040c4822278f591c08053ee5a1878255a7f5fdfc1e182e1015e71f291a350d97d722e8d553b505fffec365c02e46debfdd657a36b1d482155ae5be41850518032d", "TP1": "040b4526a4e80e115eed9cf155bb6c757d5355748b8bbd78a34e0601ca22882a1d16213be346ea0ffb547bd1ec72f2cce60329aeefbf7d5aa642b6e90e40e5e57a", "CS1": "041082ad98e1cff3eade4948de1019785a992340db974e4d74592c3185feb5e47613edfbb10ed809d7e88f12f24993ad4d3241017f47f4bc6e70010a4bdb9e53e9", "CS2": "041e96c8cd671e175bdf0e44ff4dcfb962da209e005dc7415613ea7f5b2356d6110fe9e8bb577a560012a1800096c8f1c901a17fe48bc245e50840cc3db68fa83e", "HASH_MPIN_ID_HEX": "1715b99ad82fa6355365501214e02de9095881a09ab2a08ef4fc78b7c4a2a41c", "TIME_PERMIT": "04016dba1c358482cf14604db3478ec7120eb6c15b1a04e72829a41b69d93b224b1ab19bf3b3e5fb9b699761b06b889efbf621a10976e60ede83aeb8da18f4640f", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33355a222c2022757365724944223a20223533333066323463616563373362386661663330616232656130666462356236406365727469766f782e636f6d222c202273616c74223a20223162643761323033306363336430393432336336613434653765313634623537227d", "TOKEN": "0401ebf9931a03d4dc1d9e42724c8949ef849b40e0c71f0369848ad8003a2de7271b6fe016c4e33d9343c6ac42116a5bd3af21b3a575f69be092848dbf13648a21", "U": "041435b30d95569a926cd64e214bc071c8e1d12c73ad9d84268ab906b01d361be404db85f3cefe31ddec1200d577588b19bda4a564686ca4a9e98902f6e196a999", "SERVER_OUTPUT": 0, "V": "041e6d81e34c2435984ca334a568cc3e91828dc693e135a3dc61ea73ba0d3a4e4c1172d46db4a106b02a97dfad58cc101df6fbc20926e489d3f78fa48dd7d8f602", "Y": "181014c18211ccb8349541f8bd16f4b6d55047d21c7fe0b9ad1a2f58f4ece9e4", "X": "0df17910f10ab6f2a0a884d8947c000da5e0624988489f6f0636aea1a3c35245", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:35Z\", \"userID\": \"5330f24caec73b8faf30ab2ea0fdb5b6@certivox.com\", \"salt\": \"1bd7a2030cc3d09423c6a44e7e164b57\"}", "test_no": 7, "UT": "04014a818be8041b171d4c296e637b92f602a5b960f6e0494c358f0c0a86acd0090b0a019f6b46948bb93fed1ca575cdbc07e0550d211b653a7245661d9c01288c", "MS2": "09d177c7f6e20aa6a108d79f18ac7810bbe377b309cbc5df6fce20152d9c46a6", "MS1": "0c8bb8124da22056f6d799a606e18e585d8fcdda48379afb753eaacc64ab2825", "CLIENT_SECRET": "041303e4d26edaf9d9b0887333a48175ebd31dacbcab02c2b4f08168bd8f650e7518f8043e581a918a7736959323fd6068d8b86268b9754456192af6860d297d25"}, {"SS1": "1aaf987aea07740b62662a85705cc5622550ed764d10e1416cf4a7d29fdda35101f5bb89dd2207747b58476ee442238b489aafa36f905312821a1b288b19c0c3199ff698f0eb1a361825f24d97a37732fa8f7e26509d5ff275cebd0bb29e70790d360e19a1f91ce66fd46507bba51548332827fdaa3f5744253c7872e9a026f7", "SS2": "215b0f8a9a0f5f2f28db76eb99dfb764f24027d8fa9cd20b905825ed78f7555303fc9f69f684bf1e51d5f445283e06f976ed12c6ffff8aae985b171f1a3634e420df3876a47f7698284a5b3100a575bacbb9338042adfea68834e50fc01629dd16e145350165ec328cec673afdec0e58644d9fc93a5d62a516b9e013c3e9fcc5", "DATE": 16574, "PIN2": 265, "PIN1": 265, "SERVER_SECRET": "1226eb63865bb16f858fab13ad1b11c671f778de40331245af7e5275f2d18aed10fa29bf5498b970649aabfde78d49dfc14d352a72e67982829d8f9d2f6ea5cf0472843706c1efd31835fc2e4a4eb7811cf3711fc8110cdabfd153e63ec248a21e4d3092ae95d649a6e0b6137d4d266591055a54798b3592010b0c7d3e3a4f39", "SEC": "0413f7bb907c6498e33ffaa70ab26691358a18d48aa96c64cfc1c4cbec10ce274408c74d716feca208036f15378b7515775e947d68bec34149cb79039db53a65f4", "TP2": "0422233779ac696c4df92ee491a1b0e234fe109059578964a63655913cd3e2cfa8123778ba2c9b177f62eb42ae17ff61e0765419f09d7202153313509e9ac3c27e", "TP1": "041d56b5f7bd95a64f82235a8c52188dc858f900ad569f715f6a383d79611d6f581e9468863d4fef5920f813ce7be10bda4a5d113c9a1e31b38fbc6c520fd94e90", "CS1": "041c75ec5376d596b866f16a7fe9d040c67f168b8bbbc9f0dba119dab7d95d8bf603556eea8ff4a28cee6ec4670874b6182d28588c794e3196ef429e455868cec9", "CS2": "040bdc8ecc220ec3ff089d45bec84d591de8a3db61f8b6a1f90dcd8b02c75a1e440622737d9488a8ce7d701aeeb8c327e52da7190d3a6d33e85585012dbe4933ce", "HASH_MPIN_ID_HEX": "0df05a2d80d4cdf014a5a79f0025e1418375e2e4740526885fbab9d40c15a889", "TIME_PERMIT": "0422d2871b4a61eb128427d9083d00d6a2670a5ce2f85f7b38f1d88552378a937e1c13edacfd2ab8bda314cd5b7598933ad2a58d7f64fb798ca1efec99333b03a8", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33355a222c2022757365724944223a20226464633337646237346534313561306332393635346238356665326134393362406365727469766f782e636f6d222c202273616c74223a20223563366630343330323734326465353961636566633731633435613138613335227d", "TOKEN": "04125b145e088618d8f5f364f0a2d1ae52414a295809c4c1f77e5344bb382ee0b2120cc4cbdc1123dcd461c819f61c341264e79635308fb7746187984c4dd51a33", "U": "04184e42422f465bb5e10d1c67854c5fc96647355552e818987df521cd2cb3267f1e7c5ca73b58c536fb92b83cd0292ce9029bc06f4b62a8b207c8c8e06377b3b1", "SERVER_OUTPUT": 0, "V": "0413f70928af39037b4c09a8d97a2c383ad470839b9f5e1a7b8048f8eab5938f0905f7b1bcfc2bd6fff967b497a603f308d458ad24441f6eb4fba19f0639fe8e66", "Y": "0b7614a046159fcaf135adb484ae51d8a5377720342e04730f57e6176f485654", "X": "0b89a7ca7826c7df7ab9008d07a3f5bdbba175a5e74c057276a589b00d9465db", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:35Z\", \"userID\": \"ddc37db74e415a0c29654b85fe2a493b@certivox.com\", \"salt\": \"5c6f04302742de59acefc71c45a18a35\"}", "test_no": 8, "UT": "0400e78c0836df826db3fb68b8dd6fab999ceffe0e8a9ab57e4893947a7f7d4fcd0d902b9e9ff5f8bdac1fbc5c0c531109b9cc0f0eefb74f3c25315174d627a5a7", "MS2": "06fc7c66dc167f1348e595ad58b709fd98b730d9424b3d7a05f50582af4b3e99", "MS1": "04d6a71fb1dc80bf2f767c74b2777ca14b161733bfff16b7dcacd4265ad3beb3", "CLIENT_SECRET": "041f66239b8fd139b5b1e34b912b1096e19e3f2f6c579247ec7657974375713c152399702372667c57439c0a8b99fe116715a9ccd640fc164759fc6b508b38dd27"}, {"SS1": "077ec78557936875e783792c960366beed8d419fe0e52b0f62cd6ed1e602b6da22558873fedb283c39f39d2cec75e6821c36c5237e0bc904e8a80402edda08000a5d7021105b33c8c4ce430a140a7c79d51d6633701ba89dfa906bf3ca3d5f182119ef8db18f7912ad5fb19d782b8117774e3dd89d0adb0063a9fa361e3bce91", "SS2": "057c100cac49d461f129d4f3ba6262d3205aa5ae25a326ad031f0b2de32a36160d4275858c7599c52072862346e25ea211ff4aafb868b91683b3de0a3c4f878308cbe482017d1e09cda118d746328c85fb642cd095361e40223d3a0c4a9073ef0820e747fd79ce7023769d85d9a7a854b8296c2d24134d5d15d47c0cf9d0d679", "DATE": 16574, "PIN2": 1374, "PIN1": 1374, "SERVER_SECRET": "215be51b4e51d677ffed74d28b2d2cbf0b61ce7b8942eea5555c8d8104d4e7410fc11289bcb874bc6d5a4bcf043f950366fdb215ac0c4c5fe61ea14096d1fef513e4d17f30c76b698b6df8f461e8c0405f0f8c7cb26efbbcc315b51680dbd5331b4235ae2320f7b6a048fd63a7488731d68156ea17a18d5f1d140686cfc5a7ac", "SEC": "0419a72dbe62701aeca78ef02e5a3e5f35a24cfe5c9fe689c4ff927d724717798704f2dc03e99a9d214a825750d7d5d5906eaccf0a6948b71208043679c83aafea", "TP2": "04066b94cb6df207f5c5abdd274885c8fc6541f75eb0febe7b42c97136f692164b06dadd00ddd472cb8f5e26597cd568d36ae8e428088ca0334368fbd3d605048f", "TP1": "041b9e372a0fc4feeae27f32f1bb89924a8d74eb77b8b7ab0d210c4e7cfb3e1ffa0e274cb9de3142943b326845ca204bd21032ea88a3b03472a133114c8fedc51b", "CS1": "04059f066274a3d9fcfa9ff114907907fc09c77419f4bd9152e40adfb7435b5cee1348d9ee21b57ea1e54b20f8bf4e695708b60a7474ad185de727659054d79824", "CS2": "040c19970f40576c0df8aa0cb2d6a16e84cc64453a8bd7f6934ce4c8be117f1f5313c1cc20ab2bfe007a4e78dab361b280514b6a42122d565f94af4b7cb66cb060", "HASH_MPIN_ID_HEX": "d9a1c49c654cb360019da5ced0741e1bd27d1b812239592d5192179fbc1d39be", "TIME_PERMIT": "04229e0fb5b82ed0ee0ccf75cb437be7206d5a87b6ffa83cecff58483bbc01dea21a92e5b55aee5e10272c32b95c63e5ea49b7d135ef3cbd917e9d22316c8af30a", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33355a222c2022757365724944223a20223130326261653731343937623566336237343430306136343030313165313639406365727469766f782e636f6d222c202273616c74223a20223337383366633861663731636533353336386538393336653561323266343139227d", "TOKEN": "0414579f668dbe2b9c4dc17ab65a6e43187e55085afe5fe8d8a85c6714215855e51a413b2db997d82f603f36f623bc80496cfaba65e3fd89dd704c41fe758a5eed", "U": "0406bae974d9d3e3f024ed65d4ba00ad479750d042b1954246027e16cc41381be323ae9d15ecdca53e8bf6ac741f01e15d30c6a57fdec7fb1417a19034dc1e4c81", "SERVER_OUTPUT": 0, "V": "0409299c4073f6f699baee9bf7b4df5fabdaee60f6d1ee0e261387756cea9b2f8d1c1e26f2c547976f711d7f465ceb3da82482e903afa154283564155ad0345d6f", "Y": "22bc4852bb2677a8406fa1648619fbee862a07432b8cd1ba598f1b758729eccf", "X": "07caf06575482cc92fe239e9b7039ddabe3b1c8687b01c25361edd6e7924125e", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:35Z\", \"userID\": \"102bae71497b5f3b74400a640011e169@certivox.com\", \"salt\": \"3783fc8af71ce35368e8936e5a22f419\"}", "test_no": 9, "UT": "041cf5a20fe03ba8085dae2f231347163e3042a1068e3207bf16888ef89e9a4bb7051d86a93c125519252d65e665784055778e1e67d76ec268b611dd16923b9667", "MS2": "0517527b78949e130f1d4fe7c37985c2f40f872d9f6b3b148599c8ff0cb25bba", "MS1": "20be103b18a51ad41bd1669e516b5a592a2d820b39d7e57aa56fd9f320ed2c24", "CLIENT_SECRET": "0421591a8877098d2e3e8bd33db017294a55f9ad37c893557b28005b52f4c893a31d64d59fed5ba94a6bbf45b1e6110ed3764296b456609caeeebaa6270f9f99ba"}, {"SS1": "161537311d9db766b78e7ccc21133cf852451e70fcd9998c010001066de6a7d2117aa8c76241d627a874f57ffa0b0522095224f4ee75714d7bece6db92540a6416fde878e356f9268065833fc1795fb4abc607b22b159f47abbd9f31511c19cd230f561112e9a0f4be0d59a73d959e2232389b67f3aa82650afa480be7062e8c", "SS2": "22143c6f24d2deb54995cbd611aca9cfdec0408bbd1d1ee2d844f8e139232d3f18f0420701bb906fd39173bd28ae9fa922ac6cb3e284d424209d6aec445f3ee9055871d26067237fa8f344f218ce81fe016e8be2c22e0a12f3f7ad5a4aa1e3b614d6803c4c212545feb4ea0309dc7051b9db007e50c1aa75f15a79bec8d058eb", "DATE": 16574, "PIN2": 6101, "PIN1": 6101, "SERVER_SECRET": "0748abd3d6b22a234d7c9913030aee75b2099a16abb44a6815c5bae78a46d9bf0e6ec9893f4f81f4b68fa315243369c294f0248e15d356df46563f53c8644bdc0fe7cabd7863c521f636a9d9b97667c14403c3f4bc2e5deadf86305a2c46e2ef195b544f103ac65fc0e0a0c1ae130c8078411056feff9b5e2f5ac89cb5e920e4", "SEC": "04162412fda1ea6482acaa63bab712b448e0e829af08cdfb039e5bfc5f0bfa37fd18aefc66872348ba7d14eaaa9c25eea57fc42e1959549bb17752fc4bfa8c3faa", "TP2": "0416641270e44a6c418b4d0fa5a7c44c807b3ee7a141fcadc790b4b9c45b89541502cd6313c2de28c5906e2a158189fd4d214b028cc0bc1383393dcde5d7f59597", "TP1": "04147e3dd4693518cc13ebfecfd30ed299c32efb5cafbbcd2cb897ad438f86defa17c7b1096e2187fedf36f096870c56940fb08b7d6c22ee21d2c2726759e62f7d", "CS1": "04185e6b815a9a64c53b6453f5b242f256f793c6b50f4f43f62757c189f5de807515cf8d599f0375143644dfe53478876c41b3471e711332a5a1adc84a7ac998ce", "CS2": "041871662b68bd0bb59c015be6dc36b9a77ae40431403b8eccdeb043eb60bb2e3a04eaad67cc562b93e4b603595a080b2e4f5c46383cb7570e3a89463018038936", "HASH_MPIN_ID_HEX": "f6db07145c7d6c468ed29ecc06ff6a4318cdfd592250b88f9be5a42dac9a9297", "TIME_PERMIT": "042271085d8cd61900e0cc0b6df47ed0afae9faacdb6be6ef30a191befbea424e818bd6a937886f66ce7193840a7719ac12e8d64aa16be7b86e5c61d95e96d0647", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33355a222c2022757365724944223a20223030373561353037316666373038336337363263646138343733653466336262406365727469766f782e636f6d222c202273616c74223a20223864316136653235363339393832323166303831643132656636303763323866227d", "TOKEN": "040dc0e42bb78610dc0adcc9df3557d5279aa7ebe9177800010e03e0b2c51430ba060a96e3b9e1e3bd41d24b0d415df089c7e90ef700a2f7b72dcbb7f1510e854e", "U": "0400fee4dc126592852e9d0efee084417b86cc561cfd1b78d61d285db58a4b38d112761c3f6d1980e5737c03187744bd6fe068a2a74091c261efe902c1fa139eb6", "SERVER_OUTPUT": 0, "V": "0404a745e3e88c9f8bc03aa07087210b4da7afb4381f28a005e90df32d08a621220465cff98e4c7ff87ab84fec3860af8151e5d52c8934aeecff904acbb146aa07", "Y": "0c33fae0cb4e845da99d33e7cd33dee9a4e223d232e24f470e056170a121c12f", "X": "0ac764e9d7bc34f78253f451fe4fe8d92f0b89836c9427bc7767fc00f333d725", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:35Z\", \"userID\": \"0075a5071ff7083c762cda8473e4f3bb@certivox.com\", \"salt\": \"8d1a6e2563998221f081d12ef607c28f\"}", "test_no": 10, "UT": "041b79d30c6bd9b406d0325f4ee85b7893c26b53617bc115200d0eb92f325c076505b24ae776f89ec157ae3d15d52f8815e1a1f4c10ffcc061d10297c69e358140", "MS2": "23e63a2f61167a18b0d77b409ac66a4cdacb5672735bed5936b5b634d2d8012f", "MS1": "091c462193b0f5be77115553f9c177532279cd2da2db9fe7f18e04d6d58b97a4", "CLIENT_SECRET": "04098ee839736cd37eccb44c85da595f2dcdf952eafb5ca87a97621c1cf8564b130f5569cac8ab079ded668a2b122f37eb043cecb84169a40c9813416101a4f9dd"}, {"SS1": "1adf9dde5cf9220b54468033d5e2e7d17846cf494e9a1ee82c86a49b7cd94d370ef6758c269ed835f2450817c90ac995357d6ec0213bab935a9215ca54b4426102393addb38dfd83d1191dca5623e37dce076305e01cab4afae54b3895bfacb61c46f87a01d86170debc0772ad6f28eacf24b29cd63483ce54a8555402465d5b", "SS2": "06cc34ceab3bb83473d3fa2d1f597e6d787a21406521a0deb35c88c566d036f220ad373fb162010f732c2a8a6e462e12e5a870656332cf617c00b72f52140af209c8e0ef4fdfb461474ec3b6f0b2d9b0fe5c16071c7c8d40df873aa32db6f9060b88d97cbcedff8edcef1b11940516fb68532ef3c14216646bd5767f4c287864", "DATE": 16574, "PIN2": 563, "PIN1": 563, "SERVER_SECRET": "2228164e16502b40d8946ed06359117e7e5f92fc49db78c61ea86fa12c7b853216e5c0c7297f312827a87a78faba52397e3befee98fcea21dfa802dea96d68bf15c5b10c7fa4faa64efcd70a76e2586dedbb55f191264fbe3a341da4e7762eef1ac0bd927451e1b501478ca789f253a7fec38de7f3ffe650d3e48be17ca59a2a", "SEC": "041a0ef266ae011934b4a1fe8d3565f1a522f0e89c5d71c6ac1754984d222e117200b5f1a96fc5bcbf321365e72292c2db69e26be210b42388cfe7164c4ba4804d", "TP2": "0423a5258117f6c67acd6eb68d39ba75315806d9d40e1043e73c212c2e26713fec2081fca5bb38ab87cbc9c189d6cbb511a9f88f8987921bbc28ce8012b9e2bbaa", "TP1": "041b67a8e8082e7b0bfffe59017ec4a340ca96d77122149257044e3f30dce7ec3315516a4a1456b03331c8531430ab6d86e10e88b7cb06a25ef5a8915553553cfd", "CS1": "04128ad0b5cfeadabf35cf1cde31bf58d5f07ee3f1a71ca9e3e2f384687d48ec6612c7d40c63ae336654b973425b5d2717c62628f24eee2e20dee71405c47bf480", "CS2": "040725d2f3e1524d22da1c4c758e33080a8373cfccf9ae97ce658c3fbb29609c1a1dc5554ef7085147d14d8d330924551132087243f1853c215fdda31468012e5e", "HASH_MPIN_ID_HEX": "b3d6256995a73cef935da5c0a9dee1d53ddc1fe71ba0ac69722f161458c2bc4b", "TIME_PERMIT": "0408fce7597724bc3c3a7d616fff7f665236e348f720aa091be99694c7a14f4fb70917845a946572bec4ea8cc45a730c2d2490d74fafbb9e63518f1a1cd130ebf4", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33355a222c2022757365724944223a20226466313766333439376238353739303662653436303765626564353737393939406365727469766f782e636f6d222c202273616c74223a20226633393232303331323431663365636164343965653536386634366637343337227d", "TOKEN": "0409f3f1a85bd7ef80592bceaf9830be17cbf8cf645775e422093037cc7708748f136787955b59ff58fd6a49172ef79bc2868f9ef6d87762477b42fc81d21aa23f", "U": "040e8fc2c98f1cc6ac3f0b5d7c9ef41e4ede06e853794f05a38862bddddffdb9410d4c000e25f6af4ce372b75f62701a84fab8771f9630af1aade4f5203c5e3233", "SERVER_OUTPUT": 0, "V": "0414952ce518f68010564597937e8e9e5b3b4fe305aab0de089ced2c36cc6d75af1e8bd3520739a033b1ff277af9a457140725d518b4e54e382b52ef1c5e3f6c31", "Y": "0ea4a9775af6ea2d790aab5455b8b3202ce482654075ed7d497ec38db0798146", "X": "0533f448575026bea78b34b5807f3c67bde9b25c67bfa17c942ab5b2e9906a6a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:35Z\", \"userID\": \"df17f3497b857906be4607ebed577999@certivox.com\", \"salt\": \"f3922031241f3ecad49ee568f46f7437\"}", "test_no": 11, "UT": "042176ff883e421eed0ec22714718e1c628bee08fe1394679e004c9e5ca51e114a2260fe786bad156adc8bb9a52d345d2a873e4c9e6a50e5c64d1b2ee1e28ab39e", "MS2": "1caf71dc735f9910424d3916b61a5e9d3a9986779162798ae9ff94489c2f1c2f", "MS1": "205403d6aa8bdb177986a541e19979fa3b6ce20e754f53240f6006cc69eac2ec", "CLIENT_SECRET": "040ad0eb3f2d90b810180d70914324503449006861837de6d7935718ce66be462a1995759f4e2d2099912d3a82ce1f424d0ab29a8e2d0d180cf5e6c801744e0933"}, {"SS1": "1450499a3ffe2c17d751514b0d3c2247650e77511050b0b42b4c46cc629a4708162fdfdfa28a8b78d61b8251a32ab5d43e8d8c10384716cc9b95f91723d499f91e9f34ddc337013ae8b5f84fce2fcba3eea2618a87fa7bac02bfd6f48716bf341433ca62ec3c9c96063f75911925b8bb3991fe9a9870f9080146426bfc094e66", "SS2": "236bf56559c6414d767556200ce0279fe56fae8a209a89f7e9e0dbbf6d9a4b4823b981b5640d565a39d604364c6499c115b3ab5a7a9553f0fe292313be1d8cac1d8f9ddacf0c93eb0596720d9ebe6c9d5a1071d50d4c552a62f67d25629ce770114f3717c0c2195d8b58d42bf6d3a90e6d9334f378d4b42ce01a7b1b0b95f4ce", "DATE": 16574, "PIN2": 3849, "PIN1": 3849, "SERVER_SECRET": "1aa8a4f71766717cd0e935774d8c976da5e4c8decfb0542ebead0af7daeb742720304f977c524fd3d92a023055cd63b42b3dadec803a4f88adbf3b75d49733c9220be6b602c08b578892ef306ab92069cd992b0b1723abaa4bbe73ed49601fca1a5e42231c04a2b348fbe01dbb6cb2951a121b55f7cfe89e1f3e91d38289e5ed", "SEC": "041a8be7564cfafef91709c4b3037125dec2962b0950b7117c22eb57ab974852c20a41e65215e68df7d396f11383bdbf7200a94f52762cda0781beb2cbeb524903", "TP2": "0416084902e4081cca0565176494dc1c607ed78a45b539766960e145f4d242bc870cfb6d9a18e60762f4e669c1153811fbac9006fd34b2137c818db6f4a1975676", "TP1": "0421e92a93e49ef86375afe488434b286b8938b55eb4d22adbca52dd86b2e773c418434ce0d447853d50259bd24ab85dca46577622143dd9f6cd24f70e04a63bfb", "CS1": "041aef0941ae6b60042691e195d09f7638417f65f0e8315e3652e1f2458cfe6dec08d8e459f5e856b3a80cf2bd79f10824aa557271ef9d1293fab42ea65f806b1a", "CS2": "040ce39cd32a7d172a2d5d8bac6e5aaf254a7dc2748067679fee9e8c6ed55b071d0ec1ee184b85959cdc53b861a06819edd21b82034e6303ef005bc6fd14c9d22d", "HASH_MPIN_ID_HEX": "01078df455bcde211ff18edb028b794a847695f0c6e9ba18928021c1fd7f1dc8", "TIME_PERMIT": "0402352c9ccb311ea8e21364cab822c3a47ad87c8bbfe14da66f83cfb7b1b348e81761dc86e3a04f5cc530c97b28d0dfeedb117f6cdc1245cee240cbae79ef46a5", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33355a222c2022757365724944223a20226139653333323863353733313039363261306665313663313365376132376431406365727469766f782e636f6d222c202273616c74223a20226231323535623564323439316664376430356564313033656164386534326238227d", "TOKEN": "0412a024dcfc7a4bc42632f4072f7198a0125978687e5cdc5bf00f5c12ce124edf01e5ebd94cc2c89998d214be71c4e2ca3d69b3ef03873ef09c08873576c71387", "U": "040dda1f55b8d8a6b41761e9af47b30ea28ff8152bee5e43f491dc3bb968686eba1e5d17a3311ce70189ba16d9e863c489bb2601597f99406e2bc57b3423d650be", "SERVER_OUTPUT": 0, "V": "041a696ac17a51e017639e393d019bdd83ec25d315e3f7a5b4afdc942068e5614c1aed6f120f6cbd9f7e06de1381f79ae50ac1aabbd46e2e30836dadcd4bb49935", "Y": "15f9f00ca53f3cf8237dc5bf1e0d90df2af7ab3f462b5ee768bb0bd5510ae26d", "X": "129b7ffa76573ae7af11f1a3c743d993b60f6dba566be4ff74ae93dcffa9f15a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:35Z\", \"userID\": \"a9e3328c57310962a0fe16c13e7a27d1@certivox.com\", \"salt\": \"b1255b5d2491fd7d05ed103ead8e42b8\"}", "test_no": 12, "UT": "041f6abefc3dab041a8e606bdf40bb8cd421a40b725addde477b3b7253da6766c51e9fca2c0f82fc420b679b4f12773c0f2b634fe8146f734393be3fbe882eb7b1", "MS2": "1746f71df355a9879436109ee2f28683973ee2b515817a5d793c95308a5ff311", "MS1": "13fea6350b2560d0fb3f1c27561a5e927518e438aef4416d94df0c3802fe83d4", "CLIENT_SECRET": "041efae623eda57e30a49f9d458d450fc05293790e113aafe4f0d50ee3539b96620c61c967a957586c7a61171c7114f88ee4d34a325f7663d2bb962dfcabc2bbcd"}, {"SS1": "0ce4e56bc0a861ff450ff3dc9b0596ead87a8b573e9969db21c8ad166e07931301f0d457fadb69075deda5fe82f38ab6df960083ed03bb03afcff826109ee8621d24454223a88b05659628d646c0db240da5de7776405263bf97bfd83cc813b220463311a14364ff290e6e9c43cd378133a4835fd06169e5f8026dfc5940c25b", "SS2": "1d439b9377d8a83e9542f4aa51d8ba7e138c38f387c5c8a97784528d97ba0f760e9be3cc0dd9bde7df4080deec9c7d394aff4d23d383928f042cd4eebd4bb16404bd4483d2477c52396e23ff234df5f8c887c5eb22986381947a503117e88d8703585d190dfbe5bb4ab6840d87f97eb8c4e7d8dd66df6520b052337db4e5a7fd", "DATE": 16574, "PIN2": 9822, "PIN1": 9822, "SERVER_SECRET": "0bba8962716a9e27bbdaea996f2ab26aa2e010f147f8d4eeb10452de5eb7de54095c50097c9b4045f0ab6b4524bebb8edc398685ff0368082fa5e6f7117dd5940b6b4c552d42edb6f715651bd2316160fecb21de418a426e81fb1c02abb3b7790ec128fb5d9ef269ac075a19ac2ba4952e872514b7507ccb9c975a4cc7923d29", "SEC": "0412e18a31fd1485ad004e86f12add5e5ddee9c0733b7c90fdc57935586fd4e1601e0b6562e337316e72e22c0dcca9306593f3f6be2c68506ca23edc72df4c9b70", "TP2": "041e56200d430c92980e80a5c4b79ed920abb99c0ec3fa9fa90e872b4564c619f611b333d56d90a68596dcf66133d5420398911119e16961d6ca893b2bd89c3fb2", "TP1": "0403f14c8288d329f6bbdeeed503654bdcf81fbf9f642ed66351b9e673415a006115846dfb16a03d31e7486ab5ed7a6a0f36e40d2f50e65f96c42128c30cda8236", "CS1": "0420eb59ac53543e3851b8e2c8365bdd9e87625fa5db3f9b07d4142e2b05d56d5a1e8ce340273d3bcd3f20176ff509ed3a5bcd2bdda2613857b54518483ee1100b", "CS2": "040167d54054d55a50b9fde1e58af2e654a4ee48a103c2f551cb1c2be03b76fee521ce4f0e921e4cac58965e9d7ee7fd24dcafa9107e193547a6f6521a3f90f942", "HASH_MPIN_ID_HEX": "c4e2adab8f8c58b383dcd0a37bf5f9143a65afeb96ab613f93e1d136771632d6", "TIME_PERMIT": "0419d7dcf372ee0020f3a6f97f64e850295a7aec4f8a2cf8c09220d3d663c861e51f8c53d0574078d66fd58b763ba39c9a3b51c53cec791a20be9face05696d9a4", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33355a222c2022757365724944223a20226131333439653038636634666139336365396130333832323462323164323132406365727469766f782e636f6d222c202273616c74223a20226336363031343832333261373362656536323038653163363038373665343933227d", "TOKEN": "040406cfd472f437f10e49c028ffa2c2f97118f6038380035bfc6afd7c7cb6d45614e8d6005766e608c1cce093ba77f7ec6e00c92363f0ea035dd1840495d8a89a", "U": "040956340ea4934c9b5b5d311fd7cd157a097725d3f34e823cbc0dad409d18847d20a18a897052965cc81170afa96e9e8795a9efd629fe3ad7e369f360b63dd309", "SERVER_OUTPUT": 0, "V": "040c62e57890f914da2f25859b679d638ac0101888ca22a5121c93fb4bb359c0012022810b8c3ebf54eaadf42029f55da98633f0295dbff200ab1a00061c46e11b", "Y": "1a6605aa2db338732276e7ce847216b8585426267e29ed039812d819d5190368", "X": "0d46b94802dc6db73222e697aabe2eb866005773c971e7d30246e2ac80acb9bb", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:35Z\", \"userID\": \"a1349e08cf4fa93ce9a038224b21d212@certivox.com\", \"salt\": \"c660148232a73bee6208e1c60876e493\"}", "test_no": 13, "UT": "041a821b8cf900570c20dd0c908923ad1576d0bca84b42999d2801482498d2febf0288714e1e1b87a08454c4450965941cdfe050043f9a580fd6fc8c9a9c291584", "MS2": "08d458809cafacf6d5d2c679b80947b59368e364df7068de9ccbbbd52e7f3656", "MS1": "2175ba7d2faad16a38750136860a63e61775663fe2ae6d7dffce5ec2298cf0e6", "CLIENT_SECRET": "040a8a4b9f26582b3a4d741bb23e3757f83532ab61edc6a738ef608d4ffe3df6c41c27033e7282f4554d178c166bbab68fae50a2c10685ee77ccb32f04b638213e"}, {"SS1": "135345a8a2b6687c7f748c4c678abc2a691fb25fc0d55aab68d83dd7f8b76dfa142137225dc96031835877b1f7d7128b1d62839c7d28f91571ec17c300a5747821de495df2306945ea3d8462c956932305f188e691f8acf1112297891e79aa51020e3859377c64e98b16c26dc2e8b40ee405d5737a63dc92431041392698db89", "SS2": "195a9ff8c501a74ba336ebe1ac80a97d6301029ccd6fb5013e139cce77de79d20a1b5f4331f7ccaa8056472c9413412303a1fc313cc9744a600d0af1f9c7c1f606ba7d25911d9c85f2f0dc4903eaa6189fa64a6f581ae645bf03d60adb951807107fc3f7a1c7d2e192e335e59062c5abb0d95a162ee197f8d93881b4b19bc573", "DATE": 16574, "PIN2": 9000, "PIN1": 9000, "SERVER_SECRET": "08e3dba688f59a350915967c2ad24f4cc4878cc71813ca4ba71d1b4e477d394f004880362f5d076928811ff4540bc9cbe71b758dd9acef1cf6862b5a3e33e44a0f46c159adf292ad42c3744a1f65008cf88d82a64f369008b2a544de648b621e12b0909fdcbcb693123cf5d261706be8d533cd0ad969c93e18a43922561a2377", "SEC": "040305bc286058ca0d0df7296b349526b9efd24b27e5bdf80ff45ac0c4d7a481271b690017430474c912e647e2e113265fd4eb240660783d4cacb9255e93304dce", "TP2": "041d672ff8a39878102e2892d574ff62dab650bfbcb86940af9de71a49d3128c060564029ed1d5e09c4fe428f111893697a25119e51d701c13c9d064ded21cced0", "TP1": "04052c7e73049e4e47e23b3ac43609c51135f949a5fa4281322a213f345d15893423d801526d2ad0831e687d2425d2228b80bfbbe213b5b848a05c8d0cfb5e2e7e", "CS1": "04071f77fd9450f5e681ed6b8a00d87810ef74b9507f16a7fb6815edc5649031340828e6449f328c14214d905c5dcde8fc0c80dfd1577287a88af55bd69f8d79b1", "CS2": "04015cb93fcd709fb9dfaabf428ef2a6fea1d15cf6db568faaff5a289efab2e5661636edbf1b507010cab541e47f2c9ca6abf828dac4423ef1151a8673998225d8", "HASH_MPIN_ID_HEX": "37652556c5c865056bf1127e1aa3639761afa8c13af6b28cd8ff4e0ede47790f", "TIME_PERMIT": "0402ab624ad2a42041301aec3b792d51abeca3498fc5aa02a99b346f772af316162255593e46779f0c8e801c48e9aa8d2143da777e96e421207890d66ab1ace482", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33355a222c2022757365724944223a20223838336337633234366338613633663334373330663534393039376138616335406365727469766f782e636f6d222c202273616c74223a20226530373432346438366661393236313339623062623664636536373637363862227d", "TOKEN": "0414c6fb67146fd53cf6a77e0983d4a8230faa4d048fbe97ae87643043c1ccb2ca22aa84a879dcd88a721378a5159c5bf28eae093505c573e1aa6607211e51cfd9", "U": "041ae38bde3d3d253a91c6d52d558ab0bd3af84dbec6f6b65bd3559216cb971e89114bf813bb3f6ffaed4a71e938b3a63c9e3c97a2ebebb6f7c6e8b34a4ec22334", "SERVER_OUTPUT": 0, "V": "041d5f84f0a0af6aea3bb26b13bf66aec0d2171d2f35792667310b872eca0aaea10186ba54d6371dcb1badbb11919e1a066beb22058ab14331067bf599140adafe", "Y": "08a134c82f786d23ac5c9d80b343f33c25e0a17e0825b8dab89d325bd92829ad", "X": "12dbc077b838b81831a962b3f46bec551462893aae22fecc6926fd2a2adb4719", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:35Z\", \"userID\": \"883c7c246c8a63f34730f549097a8ac5@certivox.com\", \"salt\": \"e07424d86fa926139b0bb6dce676768b\"}", "test_no": 14, "UT": "041ee91dc24d68c1cd0ad350423d34521acea30330cadc8c3d65530fa7b68b0a3611bb3dd09ea9957082cee6f0a20c58d7173fdf94221221b52418c97596b84646", "MS2": "18c6156545f62c9bc58b03db316df9956cc70f6d2831247e5c6fd093277fcfd7", "MS1": "0e7d97af9a5529c51bcadf77d14af1bdd85d6e49c2151a6765e5d9eea9f4f4ca", "CLIENT_SECRET": "04038d76a45c7bed6ed7ddcb678fb264b057be72c1d5ebc8a6622107df1e22de420874d3d5d2ce29766d38780a79d304a97a797f4f859279d32880024f0bd28c31"}, {"SS1": "23f01e2945b40b6567c2422f5bc11497ec933d665d2713f7ac616b1c7f14452414436f4fb2212033f3e28150e726bfee6797ab8cd74f384dbe248176bb6c670c0c7d9c10c2560de8565e2d74e55e48aea23c906e2d152f15746b5011ab447e591e51d573b94e29f4d36478335e9e1dfc9638c98abdcdd70d4087452b04e7e832", "SS2": "0dd0c025144b24bb439de83b23e426cda964353fa8a4574ed0888702c9ddeeb41de59eaf731cff16e47ff63a68135f9e1ed5d1b9de5ea36df2424f418eec17f32324a41e258b2359c7847d1f0c746321eb5684234da66fec823536b4ca8b15660be756a92c02227a74ea0f156fd28faa0cfaaec8c59fedd9716ecc37df46304e", "DATE": 16574, "PIN2": 382, "PIN1": 382, "SERVER_SECRET": "1331ccb92ee61b3e4832e2c836aec9e1e80ab5af2f2bddda23ec8489962f77a2090c6a9034fbb65ce63cc29387d1d1506cfdf4218d08d927bb5e53658619fe2f0355dd7fe1d6457cea2630d039bc11f7398f57ceb0ff40efec511e87293d2492011d4cb31765d8a9619a19453b19f066c2e76cfa62edd76b177e18b441d8e2ff", "SEC": "04053936b1edebb1aa71449644c7d323cc5afcbf43cf4ffd99a6def70ec38a58a31e4d32dc92744d1ce6ba92e191b29716fbaf4b7d2d3a9b966f5dd70cf848523e", "TP2": "0421ab9f39655ede18e8d1f927ad8380e33fe5c12e260a2bf68e6ca0c41b5646b71f7e4990730dd9f0c954ab90e149a0ddd5f64a1d0a08740241955f169839f65f", "TP1": "0407500865109d89fa9b183dadabbfe88e02d194f9f2e1e6f7edc7703d3cdb19200653206bf6c97b4e2db477a32bacf00bfe83d5e55e8e2199cb504f17180e9eb8", "CS1": "041e31e8717d512621a01d09683da11630f294eec37fdc0c0e0ebd5e706349fdb60c8045bb3302bf577ed32b827819b2e6553ba255ae8616e2dc82d518234d894c", "CS2": "040299d1c6cfc8767f9446d1f680faf0a22e858a6601d9c69b2cebe8fe5b0a27b115f024112352ced9ee488b882c5aa67b38750ef41bb5a7e2bf1d9af21349f2c8", "HASH_MPIN_ID_HEX": "425de93f690b04df0fdf8378c7f0926e592fbf2de9b31bb4834e6efcf4d42952", "TIME_PERMIT": "040c1caeff0da3f2fade230b2804b762f65d373e34360f252cd394e600d191160c0d6c50311abc6657d426abb093330e7fe0567ced0f0bd96be4f38707d8797d7a", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33355a222c2022757365724944223a20223565396362336133333165633861653463623036383330636435313133653237406365727469766f782e636f6d222c202273616c74223a20223635346565353538333831373436373230646532666132393037326462306338227d", "TOKEN": "041aa8a5c165d4e9b4c3d9adcc78aa32cf998fdc4fe6d3ff22b3fbcaee1fc393f50dd50370e4d9209661946f0c9dceaf708d945dd866bc2589d4bc3464949cdce3", "U": "04046bf3a1303dfa92308b7e3f2473f54300169284f1d084b459b197688336db080be03b998b4189fae46a3d8bf4e2b157b22b1c4e17a0ed63d99234902e330829", "SERVER_OUTPUT": 0, "V": "041ad21cfe0d019b5ed405d5eec0fb1c37a8478ad2be80bfaf75921b50481d00561441d45db1ed34a77dcff73aae16335a50351098d4ffb4f51ddde35b0531d3d9", "Y": "13350718959806fb930b367bf19863729ce5bd221882102122a009ab2e4635d5", "X": "055a3f65f94aa6fb7b2c1a9798d863b9adddde78cba36e759448402381902c4f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:35Z\", \"userID\": \"5e9cb3a331ec8ae4cb06830cd5113e27@certivox.com\", \"salt\": \"654ee558381746720de2fa29072db0c8\"}", "test_no": 15, "UT": "040a3e3d7e78b93ae79835344d149d37f46ec8c3d37a352172c04f0bf4d2092aa7046ac417d0acbe4351a3f5510cdd87a90e3424f153a9cbde404ac44e12c4a6f7", "MS2": "1a00f72e27674df8e0db9151af3cfa94a80d84fb57a9166cca002fb0ddc74ab4", "MS1": "1a06b578947fcf8ad95ccb2b8f83aeb338fba26506818315eff599ec2d110054", "CLIENT_SECRET": "04195acb8edb5f37d2c9455285fe696fb68f8c1eb84d3e4a4ae7c136637a4d3f5d221c2bc013aade76dc8fd5dc437dce2cfa45a943f6c52e3aa8e259c339fd6ec2"}, {"SS1": "0189fbf2f7a0febf76294e37d201a724082ad3deca8366967102bf6e21591b07121e3fa8d4439be82b267ff1491eea09f3839d78a072969e0f01a52ff040537f1ea24b1cc34fd3fcd852b2b23ff0068686a0169589a5dbd587d15cb71cbda7221b177da6aad8970d479815841eb6e456ab4523d6d81b59cd7257714ab66b18ea", "SS2": "03160467972fad64ab05306f1352004b3deebdaeff7c42a10d4ee0cc9d3cda64037f44da981da35b2ca3ed322d3b58857b37712768ab5d7575476be816bd55161e7c486511acc10e0dfdaf42a641366abaac0111a1c0b07b423fead1d1e5cfca14203f86e66634d376a61b614624759a261ea6224cec4f08c1d320e0f789ae1e", "DATE": 16574, "PIN2": 5353, "PIN1": 5353, "SERVER_SECRET": "22d93758a690dee8301dc064c20c413d7c8ff167a443adc51898942b5a2ff6dd1ef263a6b91642bbb247a96b324b296027c543a3775e55a64aa9639544fd572623caa7f5a036f6c24801808e0b9d53c1f11ef93855c280288e1535d8f5c0e27623e61e97742b0044cb08b79e380633445550ea5e92e22f5a6f059b55626c8fc6", "SEC": "041d01e37caa3f1614cd37d6d6f7878ff858ec11260494727a476c9a4993857e331ef83368c12cd259d93b20715b04997470a454a261d996f28c11a8a940fd8e52", "TP2": "0403f7956b69fef176d25d6b395cde9c4344adec97c37d083a6e5ad2976d0ccf4a1e4f7716744c82703791c2663d4f6350998d04e782bc95ffbd53cae2c315a309", "TP1": "041c00768f9d787d01e2de9986b41e5665bb1879ca4858736ee0baad2f4806a4dd1ac4505e552a56e5627c60b86ca61d931e866d435ca6642f2ce038eedfe00cf7", "CS1": "0407e389cb74ad4442e20607c7a2579fda1739fdea34fb0ef20c68dd1fe590dd571fa8fc1479b56d97b0c111b3dfa1bbdd76cf2c30935103447e150fb92e93410f", "CS2": "041521c4c8b389de5b4609d9c6bf6f3dce549f71ec53e67725b62a86d3873202db17d81654f02a5f780e395ce7e864a5e86a7ac67bb557dac6775ee91148c5c35e", "HASH_MPIN_ID_HEX": "a552b1f3e327bc8418d7a6590d16a566903de001a24dc0618bfdcb2cea78deb1", "TIME_PERMIT": "041d366b8604154b018b8383b6ff10e2a6d8e47a06c0b20ecc1d85fa951c6de5be088991cd1b313c7691dfb023056fbd1d10a77ed04f4c52dccb0aea78d000f702", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33355a222c2022757365724944223a20223735383661323865336365626436623462626662323065303965643935636234406365727469766f782e636f6d222c202273616c74223a20223763393032666536643366653639306461653935356465333438386463666534227d", "TOKEN": "0414b2bc55fc64290556f1e949bfa10ae91f835cff39e4e7cbf17874dbd0a8a4b21ca5963955feac87082d67cfdc52cb00e9c293f33570c87a17fe4a86c4ed95eb", "U": "0409e42f8ebc6d17995ab4f39685e128873a05da2232e3deb583ca1b4a79852e740dbc062a36067b354247d03d3b878dcaf73e0603571363471b93e693d5ae88fb", "SERVER_OUTPUT": 0, "V": "041d9640407ee762253b122cb07cb6fe13991fe5d9fda4c9d9dacea3c87963b6231e5467b50a7f94d8a7a3091964b9013e3e9c4aa6d899cea9179506c5636471de", "Y": "17531c5cd14d1116460664ccdad477b6331b567c4b81c94f90d229fb9970812f", "X": "1ad62bd1a8732c9a9a7af439e38a815f47e8eb63028373ac32880797d72b41f5", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:35Z\", \"userID\": \"7586a28e3cebd6b4bbfb20e09ed95cb4@certivox.com\", \"salt\": \"7c902fe6d3fe690dae955de3488dcfe4\"}", "test_no": 16, "UT": "041794f855a1b32220c21a6301dd7c443d17bf3e04da21f6ba0b6aa1c8334f950306b540fb8905f189066b717965454f01e5e636d5e0ca24e0dc8968eb0cc6c27b", "MS2": "219bd8a4ac13dd2b6999549d765dbe1b53c33b427f27a346ebe5fbe6e482c7c9", "MS1": "173b225d0ccd1e2ce8b451325d7f2ffa815c306eb01843064e5ddf1205d89005", "CLIENT_SECRET": "040e6abc00f89aca005d36e54dd400980ef773c2d499840e3c2f8b2aa98e3b6c65025f5b81f894fa58529dda81e9acb66f702355fecddd903b01883a5942022ccb"}, {"SS1": "088ec9780f5111ccfda982d9f0f8b3fca4367df1d91effcb12fd78626934b01f05280f2232d17feefb2799b75cfb3c4f5604b3f7e64e099e8c863792968f83b10b49353e0f974b8bc0d2268c2da29a7feca7166f2154af0d4b6b71a49c8eef9801e7c832f58468786dcbb56be45db49c9c10f832117afe3d42cc483fb5ea7449", "SS2": "1fc49061dd32e801f32e974be013ecc08263ed101024c482d861ab20146b58771c6459562c97110c1267989e434b81c869ed82355863b85d35c3fc0698e595460863215497db16aea733b49052074211ba2e65401940e02c0951d56314150b000d25a93b1fc109fd86f0ad0e714c319eee0bc08a34692b3fef9be9061beb78ba", "DATE": 16574, "PIN2": 5351, "PIN1": 5351, "SERVER_SECRET": "09cd15dd57c7035dfc920752ad4f7f368f6cc9e3df7ce571415ad7ee266d08c7123da0ac81acfe96899ee0ece9fb7f669cded96b61b6580462e4d78f38d7df8b10d33aaf5d235d5b884b95a2274dd297339947907c1eebeeb65d8828f69661c61fc808eb15c4b0d4e16a40221bbcd8cdca49fc02f5cb2fc50badf255ee7842f5", "SEC": "0410c1ed7f71a8aa06fad64774307c2f4b322d2f144e2d6bdb273ceb6e3569a02e065ceed1331aa2c30273aa3b0e85cfdf6ab450f374d2151df53c23cfcd4e3a72", "TP2": "04175b2f5cc63010431b88ada49946f2b95ca69a3032962bd2559f014737a4172a11ffa3e23f57529b9adfac27ebd4c5333aa028e45ff96650cdb981c0c88f0928", "TP1": "0415f2dba78ae6f9a80688973b0c985c7652f0f36ec9ac6ff44b0fec01782e44d007674fe7151fe67293bf853b16c2fb48b0b67b7992f2024446bdca674bf4b699", "CS1": "0403cbdd40029445d42ac8738f9b8213fc40e377dd359dff02200d44a055c0ec4c1c3b5b5dcb077e644584594b192d0940131b314d8d49f6f41c3419cf60aad866", "CS2": "041e0b37b51cdf6b0b32eb8e5971049ff8632f2264a74ee556c59b2b839f1d637f10f5eaf5a8c6c2c869af76cfe372a5ea369ab98d61a0e7abddec554067484ce6", "HASH_MPIN_ID_HEX": "2dcae178cc526da024586a4cefcd90f7a1b81ba54534b16f6a66e009b10ba7e9", "TIME_PERMIT": "040f4c367a7e86dca24095ef7e553db7bb6b09875e2109df53d22c0d76be4bc16d01f370f4c21760f11310754008f89d0b7b3dbd8202d044123ea0af6939513385", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33355a222c2022757365724944223a20223762383864326336383437393737366363383564643761663139353331306236406365727469766f782e636f6d222c202273616c74223a20223935343638616464313437316265393933353662656237643534646632326263227d", "TOKEN": "0411e21b3ad2b67a5eae0f2de6bf13756b82f42f9069112ea52d3e16d8cd13072e18e1a56567b8780f72b72c6839979a38ec74e7a2dc5030a86c34a8f23141e4df", "U": "0419a0ddf46a876f0d48d568b32c62bc2d943286c1e7d1648d1957dc4c9f765b50068129a375ff4cf83b34a1a7b6697df08631c6c800bdccb2ad2292a45f549b07", "SERVER_OUTPUT": 0, "V": "040d9ed5a12f40971d3545a589cbff5c25bc28defc5127c9538d985341c88fa2961b9ec7eb2a69bbb4d265f7aa8cdbf55ebad3e6ab5436cd0f0bd68a1f52a51d4b", "Y": "15423f0734c27df8eb7d655aedf0f79d489c1b79c4670d024969f731b9c8bff0", "X": "175821b117a4d69c9156be23ea2f2e1d51215c1dcf537f22ea770f02a4d1eccc", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:35Z\", \"userID\": \"7b88d2c68479776cc85dd7af195310b6@certivox.com\", \"salt\": \"95468add1471be99356beb7d54df22bc\"}", "test_no": 17, "UT": "041c34b51a8c2d3049bd8efece36b0be88342f6fd98d802625a0f5d1c28a876fe00f0bdf14e470952b5f4af97c6761f981aeed159cebec839d7d7c7805db5c63ac", "MS2": "0e31b13e7508005c4c2eeee21cca84f1d0da26689f517083372699b59bae0bd5", "MS1": "1bcd1ee366c077339c170858e06ab6c13934bf3b81c46e2ba21e0fd4e4f1beea", "CLIENT_SECRET": "041f89b50afc3fbce0c99c8ef1081ce0fae6efcbf33c34fd095bc7373afac7c7581cef5cfd6b33c922493a6390fcb58cce8c5f71bd19fd501772a2f6fdf1c08b9d"}, {"SS1": "1b13d5bdd518a0e5bb38e3f5bd71a77fd6b9d40adc72915584167a669ea5411a057283debfb2c5ef071760fa04ba99f623d7b52f69fdca73cabec850040ce38f0c2a6e500acc1b1fb73d44acaf749bfd902d1a1f62c802360563232f4eb8426d0c004a6c1444dc968ddec4d8885fd6fa87bfcf8581c83057682746900f7b4de0", "SS2": "2265b195fe3ca45759ba449bcded1c7ad680ac9b2d02f7157c1f4a374203e05e06927f4216755d9529b7174638f9aee6f71c14c38e27ace0a33e8c2393d8dd2c05400bf13de8111ad2aaad087efcfc8d6442f6308c488be380435cedd6e6d9991832438b175db683c871ad613d36e8a411d9facd0213a83f1b348713ec823b22", "DATE": 16574, "PIN2": 310, "PIN1": 310, "SERVER_SECRET": "1b6309d810f8f389d2dda4924edd397097c988fa8e86507ed8e89505a5cef55e1e10b9176251562fa7af7c79d18e29ffdb99971ba455ec80182318a5a860b67622caac3a484c118d8fcfd4f79e904a23abd9b9c0ddd05e563f56936e5f4b38460a1dcfc24d8c4d8d085902463fbdf42ea2cb8046c0606d31a997a51199c7d8df", "SEC": "0421c6d42d2f5813d039ea120012da0a3a104749bdd1d44cd8eedaa6dc8f41f35009a63a0d00c074825ecf0c69f6eee035dfc73d1aab2a1e000d9e65c2c586fbaf", "TP2": "04038d28a64c904ee881a16218fc186914d9db5f0195bd1828e697a259932da5c70fc0f545fbfa7e5835e3a01e00ddebff42f56f009f2f6371ae4f949549fb039b", "TP1": "040b7996ce2212246368d23b94ee9c1c821b94fc90dad8a76e96de0d0500552dfb01fa0b3b2b4c0dd95bad7e2d5e42f5521bda5f68c82d82a639d26435285e5780", "CS1": "040f749c883b3934c13a5a83fc245fb06482a6e3d0fc866026d1539e5a2d3a2b901ff979b53cde52fa81f4172229c900c4cb4046ca011df29dde50e3e62314d465", "CS2": "04239128a1f91f67a750484d17e24589ecc7e7307d95443348415ca2c07f13aed007c1ddfb587e00329513bea4c780d498399633a4edcab04b497333e51065f68f", "HASH_MPIN_ID_HEX": "8126d16b9133439e351df78f39c7128ac38419154a66c19c534b20a5558208b8", "TIME_PERMIT": "0423c766d8fee75459a98e834187810c539e7d30176fdd5b3daaa886d403fff844220eae68f145a41ff1df998265e8d4b6c612ccbcb7c8c0932a02e3ed3687b529", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33355a222c2022757365724944223a20223162656538313032376663663061333333343338313761623465373531626635406365727469766f782e636f6d222c202273616c74223a20226461363464613362396635346238626235363931663361306435393834373139227d", "TOKEN": "040587a1f51a3edffda7de4e9a8809625d70eaf270a00937ec2bb9118a7cc8add919a5ea5673427fe9442bd7a770e7696ca7adc09f91a31af7c6fb4e3131b5af63", "U": "041943f21db15c14e6cca37d66b00a0f0b6d966555b385afb83610e6250bca60ad1963ea7d6109af95e48bc54cfe140885a51d6563fa1eae32376c5562d35403ad", "SERVER_OUTPUT": 0, "V": "0404283179ad16299a621260a860b0ae0b1422c7cc1e3aac1e00782b585221eae01e9b7ba57a3a2ce9ddbcd4b9b4548db9e8dc29e114ccdda55015e5977d623510", "Y": "176778c1180770a0b00f157ed313fe36bfd62fe03a4254a5c1b7ece95c7cd15b", "X": "029496aaf0a0099ccffd2d23fceee36d2eea0f1ce8df33fd9e2137016f256197", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:35Z\", \"userID\": \"1bee81027fcf0a33343817ab4e751bf5@certivox.com\", \"salt\": \"da64da3b9f54b8bb5691f3a0d5984719\"}", "test_no": 18, "UT": "0402617c055cf2c4ee3392683ae8b22ceebaf23558eba7b51509f68d88c342d56d144a6b0601c98c80e959311b45bf95979d9ff49b2df654c07847c75afca615a1", "MS2": "23f7d88400361768fb46c1acd10725aab7fa0dfe607a7305614d81612336f2d9", "MS1": "175d39d7303e5623ff32aab5832009a5c51f3ec03a35dea1c54f6c473a0d4141", "CLIENT_SECRET": "0403651204ab64db2be813bcf7fc4f40316e09087e9f1cc362ff19a21d43534f4c14341073c908e3e6e4cea94a61881d79af4ad796e7f733689c541d2bd992127b"}, {"SS1": "0c2c4b97dc9969ad66ef20587e883c2d5f867442f9f7fa545026dbd2ce2499200fd6a7bcc34c11dc9278ea58135e368c587d3e934be6d63c356096aa750354ac1296c3c70f62fff5f23c9dbb4b633f12a1a177f2ab0af3a07be54af2a5148ea50d2b4f509483f95b02943004dd1a40501e982fb065e63fe08ad0c5fb334d56e6", "SS2": "1823eb674f874fd72c1df79c1d4e170fd13db98bca78ba16c20726d3a5563d61093efb31be920f091b78d804a7061c9f7951d4652b11dd85f0d99d25c3d8688604c8ea2e8a513897eb2ff883a2ccd66d4d85c2c183bfb0cff4289c08fa302dc31f418337c50d09d03305ef029b70abd0059c6671e26caa3a046a1b326189c665", "DATE": 16574, "PIN2": 1292, "PIN1": 1292, "SERVER_SECRET": "18ba0b042134234a51d5b29ff8aff18a65a2e457d02f740d2004d0874624576902acc637d52681a649d59cea5aa01842e95751f253efdc07f9f262481f37ad2d0e9bbafac56e85676f8f37049747e5fe8fcdc0f5ce309dd471ab3c722e84128d179a639878f36aa5d0169f4aedcdef9008e41a78c1dfae56583b82d93bc6fb82", "SEC": "04198765f06ff5bc5420007d67867cae63ae7a53c7acaaa25ef73b40f34d5cdf820a32c2fb2e5f750b86190fd07e026055c8407b0e6e312f798586ef078815e9d1", "TP2": "040ac3c0786471caa1c483ce36f1555637ffdf0eedf0f387643cc1c4ca7fd3588c22971b28cb3580ee5217c14a12fd2e29cb36aca5058410d9ac67d279cdd530c1", "TP1": "0415e1d84d6c9f42651b4e2a1e44e1715658d21afde5612c85989303e0861360281ee5477620e9d25347033dbeb835bde130588626f19a24d31c7596bb97f7582f", "CS1": "040c90ed265992d63c62203c461f91cda133f6ac3400e834f6af1a508d6b07bf6223e072e91f866424d2896900b34bf2b00b3c23141aac9514fb8fddaaa68aa487", "CS2": "041b63fa2e87526bdfeeeda00ec237ca79111bcf7b28a8596a3f1559de7712f0fe1928d70f21d32d8b11b605b5ee38c4583a196ee0ec508b7f61774a6379ef30f3", "HASH_MPIN_ID_HEX": "f8b557127f626afc32995963b7014077916b427886353d31fe765e3f2b6ce36d", "TIME_PERMIT": "040284b1fb492b506eeab210fee2e1662dbcd76bf32e91dcfffdd4693d89b723b21256abc867fdf0225863900295c1aaaae441df6f072810c6dc344afe875b24a6", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33365a222c2022757365724944223a20226162613537373462306338333239313438303165666265333763366430363335406365727469766f782e636f6d222c202273616c74223a20226636313836663136383834323135643737303830323465393464303836303035227d", "TOKEN": "041c76b545fa858697f1bc8e1b9fd4cb70665c766014ff0d31ff1b5562ca760312225f993733b489552c148f7215d1b160c0489ad0501437c57b4ae588ca76b93c", "U": "041628e73f8c197247653a7dad626d2324af41e3b7e941dc3e9001c67bef3fa8cf0563eecb288ae3bc2a730a5f26592fd694dd9e4983b4c16e1bb6421f94c0f3da", "SERVER_OUTPUT": 0, "V": "0405b053edff721af4378cfbb3b0bef4f1fac179f6ac29db9594fb6faa96b1fff0112f430a43a8c7bcf48fe969efe0a9ec1ffd8a3071362b11737f2710fdd00560", "Y": "18de3bfb920c9c5ea3a0481aa067df6bf4db60083949345a01a113a49a322a47", "X": "20f7f57d7f8b266fb083ef23896b2936c1864c14452bed2b0c0538df2719c272", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:36Z\", \"userID\": \"aba5774b0c832914801efbe37c6d0635@certivox.com\", \"salt\": \"f6186f16884215d7708024e94d086005\"}", "test_no": 19, "UT": "04091f85c760936c842685531e87f0375dcf1541904526a8c9b369dfb66dea8cd4146471eac084c3d2e310d2df7fe0a8b7b70718d684ece3ca088351195db60089", "MS2": "0820d6f4611ea8bba62497bb11a80364c5b03a44fb07b740b405a9777598154f", "MS1": "0e50d70385fb6c0bb4467b156ba603416aef6c215b24c49467c8cd0cc04e849b", "CLIENT_SECRET": "041de41609ec71c8afe088b5702a96c788dfd92e443130c1b288aa2790488467bd0de5a306084e1b2521cb00d1ea142fbfbf84ac2ebce64cf27d48d2cd54be0718"}, {"SS1": "0dd0c970af2e77ca6e2543469f1b3f5d07817a24dc43b3935d041d7c6f5336db160412530bacf15ea14affead9593d11f6fd3789f97f5e95ce9cd36cbcdc26751b3e0604ab0d81714e06f76cef87ec1494231fcb41ef193b5b2023cd74af39d9030d0c618817962d6a82a7fd7cf76385e4903e85c8df5ae17da05fd66ced2135", "SS2": "0c65488a3cb5e84e3d85d65e3303b99ea0dea7659ec9d679615bfe343eb207ca029b78a5fbd66cc46f1a0e7b8f17878fafd94ce7fbb7d76770b927ee083f6cb016745be36acd7844eb93729652c70e2760fa38e4f56eb148787d52525913a87407d5457ea6e7f459ecb545fbbfad566bb2087d36d9572afed5ba513929ad6b24", "DATE": 16574, "PIN2": 7885, "PIN1": 7885, "SERVER_SECRET": "0366f02cfa04a04212a4a9b7c259201b86cf9f93974f93a3d5ff3bf956c33ad71e3cb09e921c9ed104f82f14d737e8818cc6f2546bdc429816477950e965e4eb06e23cde92b42c92bbcae7d14fb4545021d9c0b70f43f9a733657aaeb61ec2ca16abf6fd0c10c4e1a9d01ec066b6bcc3f4ab3a48477fd93b1b9474eafd2a00d3", "SEC": "0402d9d649326090eedfa9685916562753dd62e071d51d72b701ceefdd5d4b9bf123ddab21f8d860addd532e3629a52b6526586181260b84522c48c508f9da16d8", "TP2": "0400040191dbb089037021337c1dd7fce2258dc9b5b45289cb378aca269275b7a3225b43eca6ff00c804ef04421d075e74d8d21b5e89d09c5306900593151fba8f", "TP1": "04209e1b485e3e73d3f3215cac375d13d4669497fe5bd3d6da9eed2a99b4e399b61ab0c903b2b3fdd3e2c44cba8144324ca5d224ddf147150403f5d873bfa750dd", "CS1": "0407d60c02b80685c7778b72fea5b9a149e2b51d969b6b0644c77b74291bae1d3d2134fb7d21eeafeee9c7d67ef050e40a0e418bec4df4da1a51745f345d6e1f00", "CS2": "0411fb6c798909802b581f2aa35740560c679b6e396af76172cfe6b7d07cf469300726ebe61a70f9249a3a7ecf72c6cf5ff219676b9fa90a1632902c4e0c86e79e", "HASH_MPIN_ID_HEX": "caf266b7341eec261b46d4c1bfee08062ac32bc49e4a2b94c9b7303280ded76a", "TIME_PERMIT": "040524e4b847ac3da00347a0aaaf7a7c0561bd92d5fac5ef037bad5a38f268f06421219837249a6376d49344455aeb5dec97e31b10a4cf47ede61effdc40d73176", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33365a222c2022757365724944223a20223062303638336230373936383964616136363062306535646236613437663136406365727469766f782e636f6d222c202273616c74223a20223633306433636135336462343839623535303235626162363435633166336431227d", "TOKEN": "0416a44ea26234ea91d44ae45c7a71ffd8da71d2f7e97e6a0251917cfd32aeb5c51beaa89d67b49897f46140327342ffd0878ef5b44d63d2423efb9bbd505d7df4", "U": "041cb15cccd63d87f2c2cd9cdba9e2cf2f5ffc8e853285fd636565b3955d8e63d91d2b31b5fb1f438af0ce6b517c4512905658c9859dc596ffbda5abd4b8925dcc", "SERVER_OUTPUT": 0, "V": "0405d0927d171fe9e6de34c70c8e6ef25777a6cfbbc670c49fa0c591f976f1b3eb1e4d4121d037d7c2a95753a16637fc650d966cf3b4a0a8df278729564e60b23f", "Y": "17d24953a027a9a5b6f2dcaf3308e699ea1e8c220a3e42714c8208ce6289d22f", "X": "09b77af8686c4a22fee9a8d2d43a962915addaa0a51551f4701e72ca26a4f8a2", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:36Z\", \"userID\": \"0b0683b079689daa660b0e5db6a47f16@certivox.com\", \"salt\": \"630d3ca53db489b55025bab645c1f3d1\"}", "test_no": 20, "UT": "041e3f80ec282a8f8d89306ca3965b961c9b69042e9b4f6ce19a5d27e9616ecfd619bc454e13af25b16e2b234abaaa5fa76e6be2aa0f1f13924fcdaeb231fcaba3", "MS2": "112e87a931c0207981d4bbca28b7f267dff219749acf0989fc6eba551f915e95", "MS1": "193b116c85e827f1b1358f929ef572dda8e9d31f0a7e62cbf89fd85185e2645c", "CLIENT_SECRET": "040f19612ecb8d126e40d3fa0c743d17113c04d5651aa0dd40e526708c627b4ab41497a80c80af7520ae5501c67b72d88a6503c79f5d3c80e1fc02b14b97f76e7a"}, {"SS1": "014ae6a9ce2c392877dbd7d4f9b91b40520af62f45ed1e5b3639415a60804b970a28d2e483b7a8f0178045e2e93582c6413afef812c81ef96683fd54a2468f4a04f2bf13a0801952422732bd65ee86fb8b3cae8448297be2543a720d8551431a061435fb492835e93e738b8612fc5dca577c2e304aa1266f9361a160068060cf", "SS2": "1bb85e0ca1f0a13b63a3378404e3f1985bfb06bab87a1bc2fd0a1ffbf1c092130655a4b2e97223d09acabd9faf31898487ccedbb81f49bec18a16fc1273ac2a209f983324f06423383811d42e913db7eebf12a284571e7905e58cb429261e93b10ae4191b832e83ef83c696d7d702d2863d473d5b8990cc187f9a6664f1ff2b1", "DATE": 16574, "PIN2": 514, "PIN1": 514, "SERVER_SECRET": "0c2637ddf8cf939d0b60582f5fdd18e48e49eeee1a5110f2ebe3979051bbdcd506b9c35f9cdb7b88758b3730511582c0cf80af617c600f866dfe8eaff3dd623f1923ad1879e43e7f2f8738aeff629114c888b7ba5f1657f387730e3bf67556c408dd4376cd423289ab5005118377376a7b59d2b71a2eaa8a400398db58fc8022", "SEC": "041d912fbc7c9f720d58426c6b4d05f4e853804fe665b81fcae7798b71fe14bcc4154bed5df1dd89dffc0226a2399bc29028559ec9034482ea692e4fe3db1888f8", "TP2": "04073f19566003ffb795d62877f7b9a2ac28181f0eb8149620e7bc6a65864afc2b1c13e696e53899cf6f706d5d712cab089206be8e585af095097e9ebd9af804c7", "TP1": "04053256d167e754b4d67e6dd532c65345c34876633f6d9830995f857a119b5bfa033246818fa4b103adf578fd7fbeeac447dc4f51d620e9d876007fb90dd19515", "CS1": "0405fed9dff1769b0def4b20ebb655b961c09f56706ad7735d4277294b3b938ff91726666f4797f0b08324565f3df663030a743290d052751c6d3899245dd0c69c", "CS2": "04185d1af89ed2d1527a019350e795a98d67bfb01aa5a0654cd82c7fc1d524b5da0df64e79fda148a0c0aedaffc4ace71b8ba1cce1c2630260bb393cf47bd2445a", "HASH_MPIN_ID_HEX": "0cacec648e8355ec4034564a536e8ade0ce3188c991342fab92aa2071632f0a9", "TIME_PERMIT": "0415cd48ca7dcac0dfd98dddf0c5ebf52c199d7a8031821fe07da7ff0a74b2f51611fe05cf7f1e86f8d8b4dc18b1407a069acf335ecbae1ee2e20cb9d1f2eab95f", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33365a222c2022757365724944223a20223637346462653664353730326530333164313038306633653436616533373535406365727469766f782e636f6d222c202273616c74223a20226135616632353939613432393135613630363863326461383639343337363936227d", "TOKEN": "041d661b718abb7296faebf974f0f77bc4e47931476c003d0e5bbe2f7e2faa0dee06349b7b72b541030855698f0656d01260d2a8d7316cf7197986a39aa0aa7756", "U": "040e22d7265f10d0ffdd810049e99dd57a1d04ce99331b65c5e1901ddbc26f8d481ae64d1bbd56a1756261bd30096daa469b8ea63e7bf3a4f2185fd3817a138d98", "SERVER_OUTPUT": 0, "V": "041b96190d64c330b4bd04b05406a1a4a9a0e19684a679950f445b050a09addd531dcfed51d0c56cc8a6ca4e40bd729f8ac52adad3dc59182b3e32f005234fff79", "Y": "1dbeee1d8bc8b38c2ee8ac785c7306ee9928cc0a8f7e5f42b881603673ae2aa4", "X": "234eb04090e2787217bba29c5d700b089a481e7d288bdd2ecb2a238c7bc052ad", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:36Z\", \"userID\": \"674dbe6d5702e031d1080f3e46ae3755@certivox.com\", \"salt\": \"a5af2599a42915a6068c2da869437696\"}", "test_no": 21, "UT": "04004df0c878150e3dfac838251434bd860b47db0122c48b96539cb01c3f7e0ddd0d12e1b8e6f7a7fccc9f495b38699512c32cc688afb669acfacecd0dd18274e7", "MS2": "10ab1a81bd404cab14df9c47b0e4b4d7ae3873c05234f617127a7ace06676533", "MS1": "09be2d818b9c0bea45cd557072a866dad7c4602706c6dbf9bd08e0a25ecc25e7", "CLIENT_SECRET": "040de184766f4a9f38d10a28fb3db5fdc027e0b409ef56ca29f3477b5c8eb3690a17d30ba084065cd2be626b8b1ab4e9c4abb3244702f795574d51d331e6b8fe1f"}, {"SS1": "0cc291668f7952b9055779656924b7c198947c8e75bf09edd7b1beb0f2ee5e06172560301b209c69e2bc0b9eb757d6192e87683bb260ce8cd33800dbd1995c5f1762c00d0cacd6de49bdbfafeeb0d35ab8e4686f0f8ec7f26a07e5cb4cb3d0131de18aae447a09f39f5c68714be74e395d00bb40261e71f9bd00f4bc2d6b7ee5", "SS2": "00562cc9c42b112ce89dae86a595e7fc37ab3a0a0adbd573944c264b1912425412d00f32c88c2a4f12c51bddb517f8dd6d52449f5908641cee8f7312775a633d15959fc03d5c503f3d3477822d2e7d3f297884c9f5324ca6d9c2e7732d4b6c6e21eaf402c5774a4ddb022963a8ef421136ff54c6103f2b762a328c4c97f344b5", "DATE": 16574, "PIN2": 6647, "PIN1": 6647, "SERVER_SECRET": "1de34ca400b98aca525864e01937daa168cfc59ef7fbc87283a9cb5d20ad6b840c352c9325af986521016f3df7b641f1772e5f207b6ae874023cbe9ebadc248f18852799f527a077c8ae3c61cf018637719b36afa79038de73ae79e12fa776891545c018c7c9d9bcd82db0fbf6a20ae8563ee4a67fe42fcd5136fcf8dd858920", "SEC": "0420808fff0df89f2183d1b925560657eea5e7c8cefd2f143f996bff9d45b359ab12dbfdfcabbb1d7bf2547da230148bbd793d53bb09bcf484474b0eaf2b9523b8", "TP2": "04075028b3126e036d8d1976f75ae6bb79081a7037f0cffc25d6e60a9e1a1006ca1692d7cc93a8223f10e1a69f639a031b1bf011cdb8be2904eb5ba195a01be223", "TP1": "04071d4a225c688c6e73b5d25c62d50123c009c486df505a3a24c130fd58fb0a8d15f8bc09d150d78d09814e78333b8044bd6045912ec72487e661263051b9b110", "CS1": "04198d5152ecc159e987a63e1f87ee774dcb3773756cd8ac22610ed7537d7f2ba013258a755c9e4f33d628a074d3d9fb7313ae5e90d87daa59487816bdb71c5bc9", "CS2": "0406721b44cd168f9fb5277c9769af188c1f1d44710522e9661b7a210ebc7c882c03c52ed27499816ab2028580e2c0185fdc77dc1025762f9decb44a68114983fb", "HASH_MPIN_ID_HEX": "c3e62a8fb543b5256b5db5b2be0ae8bac8bc94f9b6df95279628ff8ddb8a5c73", "TIME_PERMIT": "0416fbf0f43a1c9355be1fe45a19805c3391999d4454997eea1037005e67b84bfb0d5968bc019285959572f81a66e696e07c63bfbdf49c3134c961e1dbfe54a4df", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33365a222c2022757365724944223a20223734373362613565623538613638316539313839303263323836343362386564406365727469766f782e636f6d222c202273616c74223a20223839353265326438396337333366346166393236653163363936343036366239227d", "TOKEN": "0407750d6b5115a1c9dc66158658aaada1c5fd9868267e3e6064179203241ee30222738d54148d5853ce33aedcadd41dfecd98a908375f360203f0828c95b9a966", "U": "04022bf761b3edc54f519f2c3301ab626323103b962c6f632c2d412017691746e10e07c12ffb85cb95340f2516d3c963d8ab515957d3dabbd23085b97a226cdc8a", "SERVER_OUTPUT": 0, "V": "04230ed63345122cb191cd4bb56716a2737407c581c49fb36b8da1810370367c2b078f755df8777e88b7166e6bf4706f497093d54602577c5eb753238a5ee7cbee", "Y": "01bc4895a4f521ec15802c1243704e1f7a3e516b9ccfe03f7570b42cf446a9ed", "X": "15abce350b88dce401b4f7b518863a0b76ea5d8c42351f78196a5f98958abe84", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:36Z\", \"userID\": \"7473ba5eb58a681e918902c28643b8ed@certivox.com\", \"salt\": \"8952e2d89c733f4af926e1c6964066b9\"}", "test_no": 22, "UT": "0423518d8ee8f13486bd46c158c85a0ff1327b7abfa1dc077869860a4d245a84061337d101e79010aed7ddbc7fce12e73a47b03a99d31841819eeba0a207f6eee2", "MS2": "1812f69ae302f0e4c82141c17ccf0e9ff3e3baa6ba9ac00ef1db858a93762ec2", "MS1": "0d02777320e1a682d3a30b1ec321cce6c3d6efde89dece2667f807e13d320568", "CLIENT_SECRET": "040fd72989e82f0bfab933221639231631f7c8bb7d68e0ce845e4e887f56c68c8604b524766c9137b46cd93f8f867e55db4a00d29eb2fd616c12a16c51d8e772a5"}, {"SS1": "208127511894e2b93a7a19b37923409260b131b56e767358b63eb06419650e1605b69d512e469ab3e72c6266d22274b8f8763e0441ea1b2827ebf6f9cff1621219670bd7fed9c813f41c0e002887049d34afd10fc60e7f8bc2dbe426479f1a8e194c96dcac63b8905b30951d4b70d36bb105b2be634f307e68fbc820a3258127", "SS2": "04cb55f642909b8c2282e172c6be2221d8a423438573926a11687242d2d467c31375c5b53c49c359e83ecef6397c40037e18cac2076825adbb4d4afe812f16ff23b6dd56673cbc7d8cd0af17f4aa661797bf6f8771e554e1464535f0348efd6a16b955a3d96030490626bdc331c9a4c59146a6efc961b6bb8a35205210847047", "DATE": 16574, "PIN2": 7469, "PIN1": 7469, "SERVER_SECRET": "182d2edacc2f4cf6baad75936355e22af31bdfe459813ab3b9e6a90d69fa2b501fc77052784845d3fd7eae3f0f6c9b461f1b0f47cce48c6dcef19767baa6fcba16bcda624ed64ce2c43a9047d30bb25c6efd90cdab7f488c8fa5804655eba4f91c386d4d5a71912acc268adc9eaa6aa5928f3919bf78968ddc6b35569bb2c337", "SEC": "040d982f0e45adfa3321fbc05256502a1e7bde7e617c00f3478898af996aeb346a107ef57165557bdc224fd0a54bf845987e644d633eabfda8cdd0968e6b7d0b3d", "TP2": "040351e5b2157f127e4d1e2c1e71e162adae3a4ce82f2914a2073f22c7e83577b60daa781af3f663cd37583afc93d5535ee6a43131edd1f504f3d95f5317994743", "TP1": "04029e23c070feed99f966fd5ea0c7c5ec2569856147ed95a4cbd3fb2caa89eea7083ca2c048543694572edcaaf405d0de2478b55010078ff2a7088de28513ef44", "CS1": "0404fb860a5f1c200fd2b6fd3c3f3f7e5244ef335a16184dae32ce51a2fad8aa2c20819be6eddf0629e76e31cc42c79d9ec2d380c20bdf4080fceeb0a2edda8870", "CS2": "04190ea3e1c147b9668268d8d985d2788a56f15d7be5db72d490a30e26830769951087aae74754332ae31d59436f727e981a329efc471cf217638bfed88e17c354", "HASH_MPIN_ID_HEX": "74ac22854525087cb79ce41341b006fb38df44b56cd5423b92878e73bc60b86c", "TIME_PERMIT": "04003c3ae91538d28ec3b907bd22c943210e68c024c7c596977b3ab5849b1788dc031ddad391ac09ba5e87f3f7478a6704776880d0a4213d3a3d1df76be46e582a", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33365a222c2022757365724944223a20223338326135393561356363656135653136356564376134646166333361383137406365727469766f782e636f6d222c202273616c74223a20223035373334636535373638303764323534623264636662306537626134346439227d", "TOKEN": "040fb3ffa1cbff82b3c91afab444afeaa6efa9e0ccaaa81b90666355388b7a576c20ac54b7e4629257e10c718ff2864aa560b8b53fb1cf27b1b9913fcad150d036", "U": "0423c338f6ca440713eb3078629a3a0d39158cb2e2b9818136408a450adabb4fdf13393824951d58228aaac3ee4478cd1f3132186b7a9790d9bb8b9454586b16e3", "SERVER_OUTPUT": 0, "V": "040e8e8ef6dec47b5624b9513002c20309384196616a4ab99fb935207f63ee5d870bbbd8bf5a70482bc97e622b4b93bef1bb3c8fb334e5239f11bedbf5f189e112", "Y": "0cce89c6f8ab07bb89e41cc9760d7aeb3f22e302c8ea46defeada61e13b671f8", "X": "042996fc7381b42de783dac27438f93643adb3eb63686108c37a7c014b037249", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:36Z\", \"userID\": \"382a595a5ccea5e165ed7a4daf33a817@certivox.com\", \"salt\": \"05734ce576807d254b2dcfb0e7ba44d9\"}", "test_no": 23, "UT": "040cf4ddde664d96862d209c69e3c98d27a58c32d25e02a8ae76c9fb9f781afa811d954fca80614822e60e2eba2bd6d27cd5cdf9c2448a6a3fd614fb8690235c18", "MS2": "1a69289245a6b45359aeaf36449eb7a7dc2b453e50c678d9b52b6fb334273916", "MS1": "1b6559c93c764f34cce1fb61006b4d418928ba005d0114b9a87f4e2118e5bebd", "CLIENT_SECRET": "0402b6ff92053bf6d4c61c29fdcfee20133867c859905fc9dd98425f95e7f63b420b7f8473b661d9aeb3705f7483474e82b483b6ec6094c91d032facefd2de9cdf"}, {"SS1": "05a2b3a6502e3a59413e52b0ece27c3d308f5a3f30061f600f7c43b277b335bd0bb6a20942855b5cfbe8475b1f5457d681779ddd15c450bb02dd1c7d07c9698b0a8bdd0db6cfef47e28c1887439d395f1cfaac965273468ad33de99325735f2a03ec9d7b086642d5644e563645e30ba82eed30d7c8b673f7caa2963a70e7f07b", "SS2": "02f728de8e8c465251bff7d36baa34e27cd834f9cf051ced7208a9d2f662d930233379515dece8d8deb1ce483f9c5cc11597468a48696cc4776fa29d6bca62d416198e9cf029d806dd0b782e69302f116bf04cf5ed297d0ea0b67c463dd3e50e0c91da01d94bfdbbaeafa874f387f73dbfcd3727e7b2dba9da1a52b47da27e56", "DATE": 16574, "PIN2": 2524, "PIN1": 2524, "SERVER_SECRET": "2371db2e3582241ad7149dc0c52244c7b991137b948e0eafb6a8ef5fedd58840106a6d420ae7d761bf1bd95568d74b5956e1268053ead19ad143a9ac48177b3414d4afc66c654e504ee441e144a58ce247e09085ad4e58f0bf927d8d5376c8aa1ba85ed1f7e94a65da9fbc64db83564f5a9a2c1b959ac54a1d2562605a6f9c99", "SEC": "040aebe499cfa5c24e1eea3c9fe00101eb7d853a60e92194882fe7f1e5ec555d291edffef264e2355c9cf589fc578fe91f7208bc04549e0794aebdc9bbe2f8a5d8", "TP2": "0418bb7a849f5dbcd404dc4a3f14269310e6f028496469bebea6a1c410de14de6b130d5ba6be03562070a8371881ac01ad073956759c5384947d8fc271587765af", "TP1": "040ff0a5c162ea4d0248682a38a0e63ec280a723fefcfb8609981d98d8aed267051119796d262b6e8d33ef45d76b233f869ff1cee68009995ce1dbc1705f144913", "CS1": "041d6fd44cf624bd2d08429c6a666ba054ae51b90b4cfadd7050418cff5da9eda90131aa33f1d042ef25059792d4b9bcde172abf992ac128c1078f5eab80f58298", "CS2": "040b4d67e12b86a9f5d02a148addf4a32d2362c28c4389b4a4e5cd9aed7a5f4e0d196b42b4a98b8a20488f08686e61b9e63b287ddc19c906c5c8b1fec2949a750f", "HASH_MPIN_ID_HEX": "0cd096d8a85c3218afeed65d667a6207b346f198141da3c0e04088ce1de06184", "TIME_PERMIT": "040751bf75401f8bf72712fc30beb17169c2bfce3720ecdfea834e416e3dc3e2630b18168cd4413a0031990bc0a7494b9b1f84def0ee32885817e402e9e560273e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33365a222c2022757365724944223a20223031316562376530353631303837636239306164333263373765633931636262406365727469766f782e636f6d222c202273616c74223a20226463306436396437343561313830633930646165666635316634393533353262227d", "TOKEN": "041889f73f41b7b5cb114dfc33e2d3741d34ace24e0ac888f9ec08d90200c7c25503c9520cd2d7578b4695f4d11cc3b158c443e16df83a6f408f47a7bd802a1230", "U": "040c338e2270e800a65e48750f97463f28eb8e30fb33250325387a7e2c4062401710706ab4c59fea9a407f527eabb1c4c92db43ab4149f5ad6343e201c597ee24c", "SERVER_OUTPUT": 0, "V": "04155b9a44e35577ee8a746c13f8b091f1c2f0683fd3a711e074900a5b05b67d701518bbd9f60cfb21adb5dc20fd207439a825db2ffd1ee41fc2b3d8be4c6b6f24", "Y": "1dda40ba4196de9785aca8623ae51c821beebd515d24f5771b233b656df6a90c", "X": "0a029a60905ff26d4b38859287f721b8dd91f06611859e5198f3c6c771c76baa", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:36Z\", \"userID\": \"011eb7e0561087cb90ad32c77ec91cbb@certivox.com\", \"salt\": \"dc0d69d745a180c90daeff51f495352b\"}", "test_no": 24, "UT": "040c58bb659f9fc19b82df2a5a80bb3efea360219097fc43449bbfa0a81a9a933505dafc717e2e7dc57b984a9019f0dcc1799db781dede3cbe1628b3b0db77ebcb", "MS2": "01f3ccfc7a6f10beb2157a23de28cde18cf6d69afb8ab7dc83047a4ea9fc3457", "MS1": "0038a0f9dadd6658d0690c4aceaa60a696e2a125c696762d3a1c16c56294cd59", "CLIENT_SECRET": "040a301d90524959a4a4791d68e23fb2ca294dd85994a22a8cf7ce634a16d9ec4c1cadf3017bd323bf20914cbd9e3cee9a8981a4a5fdc491b33b94dea6d57877ec"}, {"SS1": "1eedbf8b632a9b9bb18843439adf10de8cdafd5b216b9cf2a0cbc81a2d9bd0f2029ed74a59b1a4deceedcb9603efc41f582c079323af4218c44f71322e9bb2d4060c13f2bc014ad201e30867ed1585b93a846d3d53cf5e7b2e24c9ca08a6a5c4223300b56529773d2a80e284df8f9b0c528a3eea40081178efea218aae0b4f91", "SS2": "1f415014722071871436e174cf43c0ee9de3936979ecb646f970d24a2417ddf515d0217fdc3af8dd3b57353dc29ddbc298e20d74ae0b1ab1ffc40a1303fa41be1f57aeac96174d5bfe479e9fb506df260c083e8ec2b3d120c006a13e6136921b09f8fe6aea21aadabd24e3026a5e0566f35d82520271af8a167e46159bf26c97", "DATE": 16574, "PIN2": 1974, "PIN1": 1974, "SERVER_SECRET": "0d996446b6a8a1172f5ca00af2d4365a3dfc44237b837854a3a2492b350baf2a14dc6fca4e15cd2ad213450bfff376c8779656ad782aad6592e529ccc3cdbca7074e3386f905f8f172b2e6f7a4ec365340c3d46f2c2ebe601493cd677c1998e516703755d45a041b1d6a02d8636b91b6ff63549d3031ead42ba0b2c0eb80bb6c", "SEC": "0417e0c0db3a03c05115dffad812f97912c6aba59538c92ca1c05fff18f4e7e3a703dc12719171e4fae7a14f4466e84535d49d6b8c2930881fa599d079625ea0bc", "TP2": "0409e088916e27b5ed082971e62ba469aa381034270cc56de50fd604270c33dd3618aebdc9ef5ef68fe882e0db4fe9293994aa3c9931430765de53b4e8b72b2396", "TP1": "040ddd64aa91d60f73bc7112678aa94d8266db234343b1baea89bea3f02846cda40eac9aa156d45009ce45951efa06e917ef103ab0d0e435ee90360deaa79181c6", "CS1": "040180e4fb5079f3325e0683621e61fd421f8a93c9009c92d5e3852571a0a88c52158189454143f8b304ee0e7b83eff75fe2eb9948802cc461de4d1f95206e4c5e", "CS2": "040c68898288b44352c34923d7ebc664fa68747c985ea50e67a0949d63f84ce85104d6b1f822e1c424712dc077d493751f17df3154983d25e4d17bbb5b149d72e0", "HASH_MPIN_ID_HEX": "8b1bd9a8c376c90af85f8b4a79fb4c893cda8814584d166ed1fe5e7d6780b853", "TIME_PERMIT": "040bd9d4a26b04d935cce222b6ac1a9a88b4b40b223ba43468b32a5dc899b4131806f25be9989f9b5ec195da7f32a708b138c4b14fdfc95648ed167926765700d1", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33365a222c2022757365724944223a20226234393231666363376337636166636138376430633961376135333766313864406365727469766f782e636f6d222c202273616c74223a20226161666561613066353236393132613330316433623433336131376636343461227d", "TOKEN": "040064efa04e5706c7dc98e6238b22ce5711674dec996f521339bcc1ab8454156714a276233a17871d0f64e2b3aed011dfdabeaa577ebc300bdd064f69dd4dc39b", "U": "0417d5195d07bbe908062c7fabd6ae470ceced46de77ca7f0528a38f36d072111e0563d9dfcf5e261d4eadf5df26e9e75a13870c450139c14d25e3e9471beb354a", "SERVER_OUTPUT": 0, "V": "041839b54091b8da7aabd7ddd8e46bafd830481f8452d4c55e3d033c7314afe1fa1a3da402b9f05bdca7dbc58fa7c0c0cdc8a1a5169025f691aa0b29ed0ca1060e", "Y": "0cd1fe95151666b7ee185fe68bcb9043bcc96e9340c64876ce5ff6385eae73f2", "X": "1771c3c82c75a448095481b869a97b8edae96649291382daef2d5f3778dcde32", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:36Z\", \"userID\": \"b4921fcc7c7cafca87d0c9a7a537f18d@certivox.com\", \"salt\": \"aafeaa0f526912a301d3b433a17f644a\"}", "test_no": 25, "UT": "04043eb58b5a7338066e9b30e81b1d49d233a926027373f117abb380912c82010221a594e12f9caf08cce40fdb845fbdffc170e945793e9c2f0cb255a004401474", "MS2": "0daa0ab5dabdb79d1679a681b3efbb4061b5cc9b5fcfdf0e697612dc2e801cac", "MS1": "1b05a8654de45628cc4a4910589a258a203021c1ea67ff1e1f0bf0c201b24d7b", "CLIENT_SECRET": "0420d61e8c41b014ac3fb5a39922e2a1799ddee41ce03985c940f1e4e506ecb07817afdd244bc63d4ea9d2032a309dff62a3e7d6440b84c249f4fa5896aeb07c21"}, {"SS1": "22bb08ee901c5a370a5b1530eae322fbbbbb526968467ff486c27afd7dc5216a23fbc077285f90f1ff13fc94834938fe2665552ff25965975ecff413fdb2367e089075e4fed42eea2a579736678cdb74b904cdec195540636e9e473fe15b8ad803a6fe497d1c0e0b9f0a6f07cf06e8b63a6534e1bf64fa7a7c16395f01b8c7b0", "SS2": "07ba76f3ed7c975f215bb513d5dc0725208367cebbdb6ed937977313c7c223e805371832fb795c3f5f53296fbb1b256d54377889d7ba3fc23a0b055a6a37088a227a951a6afeb6eda3f79a0ca1e8b7984321b192dc10981ff7d3d57aa2b3c76c0cdab0fdb7e191801287b4ca513fc8e79fc7c963a7ecf766c6be8928a084f69d", "DATE": 16574, "PIN2": 2465, "PIN1": 2465, "SERVER_SECRET": "1f4ebe644e77138ee521641b0bd32e3c102962ab6f90930d7be763476fed117109f420c389c916b21d662072f44fd3b11147ccc20db716fc878d4d6389569fcd078734865cd83f283f9b7a2903cbbf15bd108a0763a6515b25c15268b3e5aace1515fa87dd1069dd1f4484795a5be3370e1a562846516056b6bc43211497b24e", "SEC": "041fcc5fd609c1d21a2ab293c6260f8bf7edebd1015487085d213dcb73c5456dc820fd067b3693ce09e35ea7ce6cc0f517fa4ea64891fb3e79b25b6648570b0501", "TP2": "040f47c57e6ba53014970aa9792ae6879d657ead3c4c0b02d4f809eec1950a663b03524fcff9496b6211ac327e0009e317b9b51901f65b97e630463e6aa4a5f0a3", "TP1": "041cf0279ee48cb9912b7d3c990ec6dc581346baa5deb8319db216c71b335bff7215a79042e9a122af3f358fc6081146701016c5b51e829bdcd4ce9bf36d89ec70", "CS1": "0416f33afb9669b44f3b6fb5523ea5e2b88df8217a937eafc34a15ded9ff0bb2391a4d0a42b14083bd2547b5ef6fe64a41e4de1107f0f576ad2c810992542d24a8", "CS2": "041bf56cccb84cf6addbbecd21af61120921c473e84649734abb10fbace40b0c352291bf79194d7a6cf7ee4727cb24259b4dbda7e363ad1e6d4b86d25d651791da", "HASH_MPIN_ID_HEX": "0de136cda78bdca4bae7d8ab3744a9c7def1742f65816e90e678c7ed1b2f665c", "TIME_PERMIT": "040b6c2f48771fc027dbbca50cccf523106d258a82ce3623cf5c18f3605768d3ee1c153af852fbf90c559a9733e01d56d60cd7c8425089ccd0998afd545f31afba", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33365a222c2022757365724944223a20223633613634656564363363653631663830623639653339643332656635616662406365727469766f782e636f6d222c202273616c74223a20226666353938653761646661343861343764343362373333393062663738386232227d", "TOKEN": "041a011b091be3152ace0578b078001f6615f2f4d3622283e25dc616e8f04ef9472391e574737f278a2608eb14db8c6cc8173dc778fc7925ffde7eec4bb129398a", "U": "041efddb6f20f95cd299962fc537d3552f65e1d28524d821c789677b9e777959c708e2cc2eda986f9d2d647e655e65e26ddcb3f89442b0d4387e60f9bc98f04a73", "SERVER_OUTPUT": 0, "V": "040d0d6c365a5b03b8fcce819752c306c3535703077ad7e113fbb209ccfc7dce1b01859e4e6f3fe9e9a63d8ea5ba8a8b62ced791578d8f4dc7a73801587e8a6e42", "Y": "139a053f55cbaa7218e6803e952d21eee8ec850990cc1f7d856299b4860eb1b0", "X": "04af6d3b0c0238094ac6c5edd812b9604c38e633e571c3393f369411fe0198b9", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:36Z\", \"userID\": \"63a64eed63ce61f80b69e39d32ef5afb@certivox.com\", \"salt\": \"ff598e7adfa48a47d43b73390bf788b2\"}", "test_no": 26, "UT": "041405ea4cfd6195d02bbb2f4f8f63b34df6016fcaa861f5102d6ad21b6bee34c30b0d8d6a5e617d5bfbba2bdfc03e37a8e5789a81c34280a2e41b1516954f5820", "MS2": "22aa5edbf636ff51dec92f530a098e8418d62727f19956be3a5b41ec66d7b804", "MS1": "1b6f7ba281b7d9379466a3c8c6b911bfd4b54b96e02ea7f15cfbb269a3a81a2e", "CLIENT_SECRET": "041973657ac2649af8047512359fbbb9e3e6f88ba43d7d5dcac2bcb36fccc70c4c02d6f0712c8c4d98ab21ae01030a48e811fc511f1c978f5cb7159767a9b22bcb"}, {"SS1": "11a09e13494d7d720d37cf44b3d56205c3ba55d75181fc4e4d8c6090aa5a215904ef7e83533bda75cc464fc69811f85cd7aae2d1411767842788ddb2939555fc2192271f8da605d72b1d2f3a28c09c52f6bfd4d8454a181df614cdce9cd65a8219c34076580ad741883ddcf5a4233051dc74da64c50b0f1fd9735a80cc754b76", "SS2": "1babac685b3dc77683e29d33a31f3d43db6ac83cc03b41667b8ad72a184f13ec04ea0efd0c909f0626582d0c245534463ca9c2231b3fcbdd863f394eccd2b1ce007a6dfbd3f9b79d1c1eccaad8a7127d1f843764ae9fcea4d4b333cb38d16a3d1dac7f6683811626cc5acdd30f936c467731aef076b7510889deac7ad7e4d98f", "DATE": 16574, "PIN2": 4914, "PIN1": 4914, "SERVER_SECRET": "1c3afd660fcbc0b2ab29c1253a82e3f8dd68824431c7ee6ade7521730ddce99c0ce5d745068ab0c02f3fa39bd9a48b31f900f19bde15a29c0fffef0b0cafa83809416848d3f36c8c3ee226027322e0922e9aad17c5e93885873efe0c9e692e010ffc89f61ddbcc1d91db3a45ebf4f7f86ff6e4e44235be722977c3f831048c7c", "SEC": "0412a769d884c71887531042c34eb1e4cdad68d0cb361b24f531537699566ebf61222b4a6ad1e8c78a9dd48197eddc3f9005f602db8647f0815cb811774172fa14", "TP2": "0413580fd5c4c987babbca4fe5936eb5fbff922e82e4067ce106b5b9cf41ccbdb22226a2d1dc2814577ad1a91bf6bda5a30dcbe8b770190f5fe0abbbb967e39eb2", "TP1": "0420d5c346c920c5ab1394493c1316d0576059b773fd163b5e2b05222d8cb478ad18335ab8dff2bf0486a16be2c9d6ee0ff63a38e98ded340d19df954a7cc54cf7", "CS1": "04111ec38cd539f574b59bd5c9fde26a230adf26eec52548b4fa41c21cf1ebeb3b0fbea5b2e10643172837df2709ea414d9015e77dc63eabd0dda9bafc5b70569a", "CS2": "0408e3137a5b04db6c5472869c87e8ca57bdf7061f9a0ae07ca1c42ad36fc3ac37172033077e4b74ddab07e39c28406810de94f0c91932f1e00a207717557b51bb", "HASH_MPIN_ID_HEX": "58e1be73ee19c72b115e7a04904efe983d7b80b04f33eb8c99c732dab559260a", "TIME_PERMIT": "0402acbaa53883c0e87a9257c66a59b8992018a2fedc7eb9793961bf0a05b90b94075c782ac86ef69349b0ea22a6f8a58c117f02a576f59791d144fd74fd68bfa9", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33365a222c2022757365724944223a20226562336232363362333264336138356133313864353339343634323461333464406365727469766f782e636f6d222c202273616c74223a20226538363261373666333930373135653532343633633730313437663565643731227d", "TOKEN": "040543b5f5302eee58ce9afb4f655baff7673ae9efe183bbff43eea93ae9cb86d51cdc4f153195cb7a76b36cc0866656bc77f53786351751d4dda36774488646b1", "U": "0411a9813b58055f1b1957c65ca0c9115de8a6ac68bda13130749dbf988505d6161ac407ba83bb85c725e852da2954821855325b75c96eef75ceb58f72fd9f4e55", "SERVER_OUTPUT": 0, "V": "040e1ef37f1defc2f892dca6621b6a4a8145d0cfd2f9d8c095605e35def584a4ee025dff55b35f2ad4a63cc59924b52462f2e8a87d961bcc4b08f626764785f22b", "Y": "0f33332b9c6a444809c5f7d9460eacd998a0e2cd5eb9c673936bbda4311c1ecc", "X": "1a30e36476c0b271873c777c0a38fa07ff9ce00cb3e927af3f5657dea43dfcec", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:36Z\", \"userID\": \"eb3b263b32d3a85a318d53946424a34d@certivox.com\", \"salt\": \"e862a76f390715e52463c70147f5ed71\"}", "test_no": 27, "UT": "04060ce40e6b4816948a34de5c2e517a278c5587ec157b88c56da10fff4c6be7050bbb2ab6dbcea26fbad23bab71ab2d72f0c7186a9490829da7a1d15a43dd30d0", "MS2": "181e74eaf96a76569609ab1d6389fe109272cef94f786fb5e4ca9b655f7aeaa9", "MS1": "22b9faa7579386637265ca1a93f4f6b3ebba4ced7bc054f0624dee61cdeb558c", "CLIENT_SECRET": "041ffddcf3f5e8c37dce405f5bc0e6e839a8a347d583227707f6dfd3881c6af17c09bf46eca1b9e1adcf823f801ccc673ddb9905bdcd23595db47119a8ea69b359"}, {"SS1": "2363be872ff461794a7373f613c8855463efc8a8e215089ab35cf9ae2f4aa82b0865f72e9ee8cb64c44a3e7dcf54aa542de3ed7445074a49ddf2d3ad39fa9c4414bad4b7e2b978cbb4dfde6ae13cea4743669d7fb59f72b1b9802ecf3b039c0203e876038ab35be86b98038f1b7fa1bdb4f7728db9b1f627d46875a73c1ccc06", "SS2": "173c3b288b657a21693456ca5b2de43f5bbe81c1828ffdff9984d7fa34105422014b42beb663db9472c29a17f6c2e69a82c2991afeb73ff122feb600967cdcff00716d6f1108c9a81aa4bb908c670d32f50764d64620d4870986a405473adbfd0290d71998616367145fee8e4d4503d0821fce9ba209274fe035b3c4261e25a1", "DATE": 16574, "PIN2": 5572, "PIN1": 5572, "SERVER_SECRET": "0ca57968b2addfb4282f5522548b004cafafadc0d2a76c034ced5a7fdb022b3e142e650d7910a21112f55b97551a7b73ec1c7db891f8cb8fb84ece36aeafcc7f2005e1f3ba9b5c9a4a9c69bbdbd93f9ba032bd526c67b1518587be6ed31403b920154bbe578dcd8c943fda0eed9572ba2cf401cf2a84e9fe7e13417e1c05de69", "SEC": "0407a7b0d6815285cfa4673b70b776a50014462c9f8d310eb70bf9d56c28d87fba085033b9260f3eee58ab09b214a6a4129f8b148ed748a112a975675ba5a907ef", "TP2": "04031aad7310e01243e59257e24c3155ade56f4c27dd6cfefc6a50c4792802d65a14e26c01745f6f25bfe2cf339f3217e70ee7ca344255b6589b913181565254f5", "TP1": "04149ba4a279214ca0ecd76718ca81145f97f6bdeacbdfb4e1909d1d2342e316121c27b110a60df342227de06c3d4896fc5ec897e5de84927fad71d78f72ec43fb", "CS1": "040fcf5b7edeb2b9724bd8c8aac8d32074b31fedd0bc6994bdba7fb66f3a813325016caf0dacb1c8ad57ade5855ba178be8be109f0e6be7ec5b71da2d626c7c32a", "CS2": "0400b30791084ac42dfaeeb48db6379c063ab3bd0bff03783195a46ba2bf6242e41a281b0c0b77464e2860b28fe81eeb0647630c60674f006e73d40a1c12eed88e", "HASH_MPIN_ID_HEX": "53ea61dc442d07016134d4e3448fa068f5a198af17ec893d71c17a522a11d24e", "TIME_PERMIT": "040e366d053af01490ce38ed4f71ac8921d93585971541ad1a90169c075fb41eb71a057b1c716f6197f09fdf8e09043b4b541978f686a41d61bb0a4ccf78a6f67c", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33365a222c2022757365724944223a20223139333831366665316635316535663561663534313861323634343236343333406365727469766f782e636f6d222c202273616c74223a20223765616464336637333932356564613333336563383930656163333238636661227d", "TOKEN": "040cbe6c78a70360ca8d10e07c195d6205fe50e79c59107e61f1a8f4d974f8ae0a00b122640e5f0a07290074d6f2dab4695afdec06695edde821adfcd7faae0f6c", "U": "040d5397630c40cd07ae94d9ddce63059593e92d01cfb0d9d2c329a36566635c1f105250393694b88268f47138879a81c21307236c141a7e60ea4ac5e6f87a1c4b", "SERVER_OUTPUT": 0, "V": "04129159b989940ae83166622cd5e8d83ac00ab759020967092d7d61ca194a2ef5120310481b550b412c9b6fb40775063d560ccf07a3209e2f0886d8bb0c3b8ef0", "Y": "0507413453e6c5c4520da1d05a1fa70cef0a1984c1780b1da4e1335bc1fdcfb7", "X": "0e42e9b485bf9ed78c82853734194daefbac3c3593b368dfdef6725a9f7ca0c8", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:36Z\", \"userID\": \"193816fe1f51e5f5af5418a264426433@certivox.com\", \"salt\": \"7eadd3f73925eda333ec890eac328cfa\"}", "test_no": 28, "UT": "0416ca559a83fa9a37e6979bbd629e819c4208c53c1c6a1fee78905de401cd146307114af74d23b3a6fd0989aa3e353d82d39e528cc3e6ccfc64b00125a88691f9", "MS2": "0fadb11a960ccd1f9c118be2bf1bd51bfc5ffdb4420d1eb2df5de1753692249a", "MS1": "145caeccff101b3c2b0c07c03270fb8636a07ab16576a22ca350ff009482e179", "CLIENT_SECRET": "041ec9ce112060adea2ada8532511f4cbda552478f2a833db7043367929cb56a801e32ca60077d0d8983a66456c51793b3bd590a6f88431fd5f2c68740edf1f53a"}, {"SS1": "0bad100e98e4a24b757249f3733a2f2dff1a58f1b7a64556ce6f9ad8fb711be10ac347cc801461a4c4fe8bd8e717e2b5d211816b3f78ba0ff58091c4d8680a1a04d16b694fc92585f3236a876995b94d0d0f4a0df614e8bdb3980a1f71de2aac21f761f0235821ddef76d9c82c39b43050acbb6683e238c01fc55b32d4e2cc15", "SS2": "051d9407762af56e92f28da8e231bfcbedd5170214338f52293f83d6116ac0501c803c228717328821cf10864aab6846963ab6fd3e883f190aea766bfc733f5419187956ebb0c9b76ceee720ca45b6941b698a2695b93d35df2a299ab8b5cfb2057446a46a0cd8676098cd9b4e6d21059895b06f58f8b8efb074e2815e695b38", "DATE": 16574, "PIN2": 8981, "PIN1": 8981, "SERVER_SECRET": "1244ceebc761be3a8b83805e95d3925a277a88116ecd5ed876bd260d6f42dd231988e9f6e198c32f2c2c63c9708186c5c93e52a0592890acfb62d7737ee0dc8b0e2b58af3638c4e734e9d5aaa58a1ecadcc611b7e7b5688bd8ea0d92990595021c19cdc1975f1f10165cd09b0ca8632f70a3761398414f8a4d8d672d4b68666b", "SEC": "04170da7a8b9be584ce66025eae5d89732e98bf29ed69665a2d4be4646a257fa501a95b20803dc9a913a80bc7d813535f82a033ecc543f6381361f605975e624ec", "TP2": "04049d8668c94dce50800f1c93f86dc6832213e7bd6f8f698b4a82430e39b093d00ab8ae9d424fb8794dc2180173adae959f804a84c15621d8a31215b9f24900bc", "TP1": "040d3be2c1b33b232156cd8e5f839fcde2a9cd40af517fd5288f2c0082c45c716308b967721a62523953cab1631296f721f1c410461e27b7c20c9d40a715db5b77", "CS1": "04068326d7a02adf92919264ac62a81b0fb2643121db5f8b742f72cd969459df87179973587c6e9b8f8c1a3c0bbb734ed87d844119d7e028a0d7d1ca6f85298f79", "CS2": "040adacb7f2b753699720f49d821d9afecc724fb954c37fdb554bf5a132917f3810013097452ffcebd402218d6755f4950a750cf0965d445feba68401057bb83ab", "HASH_MPIN_ID_HEX": "1daf02814045c96fc283be036a7fded1d78c5a60199f573e51f4c786f29ca752", "TIME_PERMIT": "0418167460d84858c2787d6a773e4cbdd6adc0f677b5a21341eb75f941754bb7ca2094c7d382f2c362fd7aaf823f0ef61cd9e1813c2605201bcef557db77074e38", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33365a222c2022757365724944223a20223032656537646139336630396563373835633065633064336337313135343961406365727469766f782e636f6d222c202273616c74223a20223031323366366462373136656132643665336236303561363366346133383536227d", "TOKEN": "041277f242dc00917faa2c16cfe9551be86bb9669d4248831787b5aba0c658c3031f91c1432ca62af0ed145802ca84ea2d4da7dc5129ab2a954c00c2827564ce6d", "U": "04011fe5b0bce9d7216631145e34a93fe829d63d668d371c435fcd6f1b846f2bce08be4f8cacaa774b777f79cf2b845b6c3b600080a100b9534b3515e39c4ea4c8", "SERVER_OUTPUT": 0, "V": "0410ceac1e2a281b067890de3da2a57420dcc8baa01cda288603bce3bc3ed2f78002bf646d06f0e76acd9ef94d26d5f3ee6ba1a8a31ef26ea70050db3e73f296e3", "Y": "19dd17ea86e87b2cd123a6763684a1a5d691611cc37031ac2490e844d9af9034", "X": "122adbe43ab708d2e92f833fd9dc8fd07ddb87b81387e58bf50d03bf4a0a675a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:36Z\", \"userID\": \"02ee7da93f09ec785c0ec0d3c711549a@certivox.com\", \"salt\": \"0123f6db716ea2d6e3b605a63f4a3856\"}", "test_no": 29, "UT": "040d99a7cc8c925c5605440b3513143828b2bca50e036330aead4482d293d74f2122f53925db35c940c974de9e75e31d5fa9737b47434103bc0b7f4368662e0f19", "MS2": "09448c8d98704abfc3b0d1986fb2f040789feb5783dd3e8eb946fde8f9da2e10", "MS1": "208a9b0eb9389823d760493d713666f9918997b0462367a43018728bce38e14f", "CLIENT_SECRET": "0417c21a08dc5bc2b5d5641567c5f78e51a4c2e58280b19b09f0f73df1684d191118b6fe367e10215d2263f44c09d42eccc1eec17406aac219b81cb5e6e10a2bed"}, {"SS1": "074b0d72302b4ac89a9bb672ebd744c633f7b0463e13e4f0c162b83e6d39184921bd0290d140d48d6a72343cb783b373bf08fe2eb58700e6256ced4772660d6821293c3d99784508a2713ade6c41d43f47abf1b188217439c20b39a514d5d5531936b800ec65dc1289ef74fe3efd155ecb8e2375ebd0883c6dbc6b495d15e0df", "SS2": "0133dac516e466ecb54b1a1320182e979d5800c57752d686d2c1dfb6d98bcb3a185ac02384cc1832bae5266068e233382a69643fabffa09f5c6eee2a8e92c49810c407d0c72fb80f821f730636512618f4e55b0e340b5b6c68caa332ce2d2fb30609bdd7b6415383de01361e7652a7f4f4e81c9ce9029481315520efb60c819a", "DATE": 16574, "PIN2": 6845, "PIN1": 6845, "SERVER_SECRET": "0cbc592a949e5c96627fee2de30897931b835700b16ee54737f44d74dce639001a867e9c3947b69c8e3c2b22aad72c726e70211150c876c1232b8a5626b5fdec03196e9716d4d29ed92d27003adda9af8576cb1dbf6665e6c7e8651a4333794f1235755277891e3550c274babd8727ce368f3a762b9d00a03d146ae0ef55a75c", "SEC": "0405125c3d454f7686f4def5f614390506f2f77d09e2297d8c3d53ab96474b55f3193044326e9ec297af7226b6c3edccb8a1739bdffe583b28a41d31dc84a5c5f7", "TP2": "04189a25f3b978b4996a21e08220116937ab822b121ce2495c9c8b1feef97ea0730b22876bf7ff0d3f9773bbe2751f1815a862f43ef96231b7a1fcb86e0bac784b", "TP1": "0417912752dfddf983ce62a1a66f5689977fd9c63e605d54c9cd879c8ff1f399121f88a3b4e518209d1848fbebe76efe6fc848fa2b8377dad33a3efbe5e0b7b0dc", "CS1": "040a3782bd3587bcef121b2eeab82e9591b9e0b65701f1a1e7ae513a9054d1b27b1969b9121d0e864d95cd9ec2f2b1ecab2ff45205ab739f76ea95bfe1c9e15e02", "CS2": "041a05c52a0a14e5ea7363be291a80447d352e85a339773ac8b27821e499d6202b1418f57706ec86f55c22fa5fae7cf7eb2e7623c10fdc5bf42ede720598d92cba", "HASH_MPIN_ID_HEX": "aa6d12f8834cc797e7a4202c7a3db7aa9f0b55fb0ea70101688055979d2c4b7c", "TIME_PERMIT": "041ada271a1dbcf6b69946c03088d8a0005c1ff6831370ae5bf3bb8d0394156d83148566c141b6b2bedfd99ba9fb3c8a110f7213385046d79f5e7a338526d883ca", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33375a222c2022757365724944223a20223135316133323135303363643062623034336664373134333435343937643035406365727469766f782e636f6d222c202273616c74223a20223831323031633861346331353638383263373335663766633230323632376239227d", "TOKEN": "0409eaa0baf7429260b80e37fb4cec207807e9bc15bcfceb51645bcb041f0ec65a07650ec1fde103d50ccd5bf6bd377cd752f124340df8cdbe7f9550acaf7792eb", "U": "0404516a91995e6b4b84b4404b61e0d984979e84f09577b84d1a4287d9504701ea097b2ff05e5c463d34b8cda7dfe4025dd724c9af9f2949660053d70464322109", "SERVER_OUTPUT": 0, "V": "0409c3019970848f9dd788b2bf723310bd88de3b8ce7147d8f35f7f9eeff85f8e102cbcc7e00e3e6cac45897d55129a06821762285365fcba49c17b09cfa1a0ea7", "Y": "23cce3472675166beea6c209026888956d24474ebc1f9e43651ade6885bb3700", "X": "148cfdd2d0f4ff16b652c92e2e915c924c7b7ca738d9eecb3609edc531928fde", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:37Z\", \"userID\": \"151a321503cd0bb043fd714345497d05@certivox.com\", \"salt\": \"81201c8a4c156882c735f7fc202627b9\"}", "test_no": 30, "UT": "041ee36db6a4178815078b9c2c9357a7b2dcb1872d271a6fa5723e1ae262e1899e04010e1e93ce064b5e2060afecf159a96c53760f30ba6253e5249991226941e4", "MS2": "092c364db25d8d481816a3a5f1f9ddddb771279ffebb211ece70e70c37343bb1", "MS1": "200c156a31bf817fdb6744627ab07cc57e64ae9f40b3b3c4ecafd618fa9c9a24", "CLIENT_SECRET": "041fa8febea88d9b07e4ef7f8e306fb48babadf0222b173cd9e4912ea32cb2bcee08618fa97a87fc7a86523f09c3052eb52cb36fcff6420195ba89c4dd1119a7a8"}, {"SS1": "1144bdb7c2b807e71a2dfe3697d7fbd34a09e8636148ecaf7c9f528f2bdd437d029b836b7684779737bbc34e9d657f3d958062f4584324a2149130dc67ecaee01342f2b5353a8375642bb625218aee1bd018bb2c8027f4f1459be2c5caf7078703d55a432a8336f670ab359df103cbbb33763f0a5b8923fb8aa6e3e139f66198", "SS2": "2399d30cc3691370a5b325575557c93d24ba5e1d006edeebf98002f9f0b32bdb16d5460d6a964cda7a976c914bc29ab69b6a5f101e939f18ba2b25b79ba2460304705fbd167b6d3e59ace56fb45971683ee6d10b2f97aadf8b3f481a8e55d1ba04eae72afbc5e36e8377b7760cdd7448fb9c6d541acf7848f4e014ffd18d8514", "DATE": 16574, "PIN2": 416, "PIN1": 416, "SERVER_SECRET": "00942626398002eea6d800866e558fd416b39427f2f062d3fa78f634ee2e89aa1f297d5a1566b60ff2bec4a8c88e86e03911f4ad1f93f3b0d1a0e6e27429bf1a097c023f74cecf5481c0326804606d455d1d20040624fd1db209f9c01fb87eb3081cd82bfadd9b1c58693660b3fe6cfbbaea07dcbe4a715cb72e2dd867aeaf37", "SEC": "04018cde69ae0ca6f360d70f4210691ba549f5482506b4556a57d723e0c5df2cbb1b8b6b5ed53abdb39de2794eceeaf2a8cc06e88a8032ec3b36e0c82834f35e46", "TP2": "040bb8dc3d8e0cdaf5484ef2bfeca12bb5cb4e970040176ed1e219c5e29cddab9b183fcdb74dde733a7b0e87b470e59862152a6d0e3dcc9f3f3c1d3d1bdd4d9456", "TP1": "04034cc2f2d50daa77c6bef9aee366e110ba7cc0baf6319d0a8c2b32ace36925e31a0cb86330d4b5fb6005430d9210d256ab1cc37537181a95d1d68f6dd0cd52dd", "CS1": "0402687135b3f83fe3e4aee950a1898a92a66d6e11eb424f64637830681c109b9313848e65c7c78d3fef0cadc3cdcd0d3c8daf88b153aa73cf66bc6dbeb3e0b1ab", "CS2": "040057df7f3b8a59d8a8f22ca74159c24edf563bcafec09b481398804f7ed837a30eebc301b3c33e38f0aa7babe00b0eee845256f94b28b6a9733b3f548595de6c", "HASH_MPIN_ID_HEX": "0eca83d0612b7d9b528cd0358f0cbf8a48c05fd61dfe200cf5842ee3a4d3b372", "TIME_PERMIT": "040c4c06329d77c9502d41576acedb36dcd0562a2b20e9c08ddd34ef4c7c9f70d70530517e2dc880677278b3a314b3fec321cb0ea5bb9fafd37dd9b6d5cde06f45", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33375a222c2022757365724944223a20223138666135323734646634336235333733633439363035326338323866636436406365727469766f782e636f6d222c202273616c74223a20223865643737663231613464313734363434343731373238663764653562393465227d", "TOKEN": "041978382a2e122cdbec581f7f7755cce8d69c15af6b5aa2e3f78b206b6d98044f2311a9f332c715982d0615ffb87d29bc10188f793ea4de27e7ad530577b50b46", "U": "0411984b7e32e93efee2c551bf887d6419b7b61e4cf22c74e5ecb57573432436f110e6d79565394cd243b4b4b4d22ad38dc1205cf62e92bf6e908f0f13d63c8b91", "SERVER_OUTPUT": 0, "V": "041f5edc0ec93381182a30c16012a59d783a4f8ed9ed0bd15e6eb860b04e71840c1559d57c44429aba5b373149f80b8f598c105183687512b4862c69d66ccbd295", "Y": "17e42b32becc187ef207a1a0c5fd3a7e1d48ed5d771b28ce25b69ed19a6536b4", "X": "04bd075a6eaffbbcdcfdc9afeb896384cb779d578e6f4f4f0cc497fd8a914179", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:37Z\", \"userID\": \"18fa5274df43b5373c496052c828fcd6@certivox.com\", \"salt\": \"8ed77f21a4d174644471728f7de5b94e\"}", "test_no": 31, "UT": "041395f9e8b111445d5d4d006907471c4cb4740d848bed6c37445e3dda577e73af2255eb2d34dec0b48fcbc9dc0f64f0120cb3af2746998ba7099e459845269a4f", "MS2": "2225e0930b6c45915f8f0ad80762b4d06d67f7c757611152beaf096613584355", "MS1": "08fd93885cf0071e6928756b32e81db9f99906691767fa9bf3963c79e1a588a0", "CLIENT_SECRET": "041a450e210dab3984f821e76a0088c97193efa02552effaadf053ef60c9d7455306ab2cc133f380da0750242a25421291f2a9828c07d4e32579b9ad7b0b8fde2d"}, {"SS1": "096f7e69f907e53829c38ea777dde234997dac95ad7bec5e5e4f59e3a823faea1e0cc62a9425a45d3b74ea922a18b42e4bb19a880d58a0c166712aaef7616e620d90a245ce6383b41fc5e13e5c812f2f595938d41ad9a007be36fd0da0beab26218746dbf01d7700802ddce920793cb94daaee158029c0a13fa7d6b17235fc98", "SS2": "02cbec1787d0d0740bbe3dbf8bbc7106b05747318c91aad66286388428749365198e129d8b2f69301e01a7514f63af91d85fe7c8b2f0f1f112309dafe0b79be70d5117433321f944f2a9a17706c4739fe254d8c2c775bdc9f0eee46f4dd902c2004cf153a5bd5c56511e3143a9da938278fd37ec1e8a935b1a34d1b5aa54305b", "DATE": 16574, "PIN2": 6628, "PIN1": 6628, "SERVER_SECRET": "0bfe2e0cff2c94bac5c3967b9ac386cd5ed692ca675a5242056e150baac61c301b3009fe3663a40f37663b65382ab2afbac9632e76b7796c3131de082952614f0cbc1ea6a099537b04f4aa637944b8aecc4355f440e7ebc91c587cd18c3ca2881f15c8ffcc076f6803cf51173f27fe9b28eb2b64f255bbd62173d3355077cdab", "SEC": "040df748640b9c6fa258a2772eec41aa3aa2ea47bf19fb3a038a1a30eddeb967701f74b3754852b8c3d2c563a816c0611b55c3db6e54ff56b58f8cd6719cd65e6e", "TP2": "041956a467b30b128b11a83fff74c2269c6cb592bb9031badfe5e069600a69cfa90d778c5a4cfa3889df3d9923cb5ed85df4d7a921424b0a4cbbebff4315cca9af", "TP1": "04210b7a177171984bc1f87b25399ef0daf76b41e70aafec7d00dd7e5c5195d2a018f16ec66bd51a45441d34dc6caf65887013348de434075bc1f57907bf3c4a2f", "CS1": "040bcb195926bf744bb00413131e4029da287b4b54ba8da110e0008a3c79d95dbb019a8eacdd1837c1d5d291526cb35c5292084e2381fe5f9b58da552a1c33d4d5", "CS2": "04140a4f3e6eb125712d41744c34f500f56cf8e002bc62565bdd5ace538675daf01186c535a5c4e8a7183e9eec18ec8a4fbf58417efef89b017084de189c803242", "HASH_MPIN_ID_HEX": "124e8bff836022f414d29c0e717418efaa288716d7e391192558d1e412232a76", "TIME_PERMIT": "040aa74796a12e71cc086e7e6d655ca7148a935f9741359fe2d47b4ac5bb95aaa623c01e42dc07512c13a0a75fd87ec50cc654242bd57522142dbcbdeb711efb49", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33375a222c2022757365724944223a20226234636262396265376337626539393131333664346433626462306562306361406365727469766f782e636f6d222c202273616c74223a20223036663830643763323034633561336161666135623662643463366337366635227d", "TOKEN": "0403f434be91c868e0ac7f30135f639395316f9d00b8abbad5d6550ca92f0a924b0038a1e288cdb5bb4c7f91b9c2a4e42cde9ff79b52a73a07737fb19c2b163184", "U": "04171d76dcd8a9967054a778be9669c1c485242628af4230327a57b160b5287edb16f07830c693662ce47ca80cfaf0d524b83fa2641dde37f23d825fb62677fd05", "SERVER_OUTPUT": 0, "V": "040a3ebc56e80b9fd3f5ca5a4d1d7c9114999be8ef5d80f102b832857b822ced470fb5909753a67e940700d7f7ce36478d9b178528cb1d0058bbcb26cbb6602e34", "Y": "13b3965184897f9d40f82b9e1f53da9e582745dcff37b1bb0022d5a3fb37e0aa", "X": "131ab1f2107c7aca0b5f2c0562ef6aca85d418d4ceba3d06cb534c4b3a64d214", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:37Z\", \"userID\": \"b4cbb9be7c7be991136d4d3bdb0eb0ca@certivox.com\", \"salt\": \"06f80d7c204c5a3aafa5b6bd4c6c76f5\"}", "test_no": 32, "UT": "0406b79902ba8ebd244d7c4ff83140783d836f7bbc4d7b1a273a131e7e67d3a89e079a79a5d5e8c33b86dec7755753255f0379ac9b33368dec2989cbd730eb27a3", "MS2": "2123f3247da868ae25fce81c7423d6ea6a856b6e4f264c2bf84d1935ba065677", "MS1": "0399e0b6e74826c1bf53914a430581c4cf0000c2de16a1cb9b26947f378f4a6c", "CLIENT_SECRET": "040e9da687e9cbfead75726cbd628698d64cde7f4eb6d048c19d9a6b9fc93292fb13a9ec4c4ce9d8807d762294544a931162b2f5c56e3cab786e6a2f69862532fb"}, {"SS1": "20d9eb2b600bc5614f6672c05863372b0f2fc49d2f2b804baa2bff6edc08892a0b5f5ca21fd43b74ff3a1a45508e7f9f9c96e08ad5d72a42f9112d611ac5a2430d23aa13b6309e45ab474e20707fcc32025ed2126dfba5e40439bc4d9924a5081f15423047ea30604761e4d8b45efe26dff031c022583985a94b5e8ddfed4373", "SS2": "04241365aea33f7171a42bd282171421195d01762a27d60cbe0a6c88824687bb1681f9ca2de252b481637200d3311c7d6918035d678e54b14957fcf8aa91cc560213d271529c4f3023eec6ccb4324da97af2f3e71b7ac9e3eb0ecef8b73db99b11087e65d8b54a121090f6214cf97da577f6f3e1013b5a7893ff02be37dc191b", "DATE": 16574, "PIN2": 3415, "PIN1": 3415, "SERVER_SECRET": "04adee1a8e46a311002b4f27a8d168835d18ccac65c0c2a8595ccdaa0df82d921036056e8179861308102a17344a62c3fb38e3691be614a96ccc40991825495b184c8da8bbb78e1c77c89c24062b0d5acc711f93b42323293676ddd4deb34f5d0ca4960a5306209fd5d47fc708bbb48044a4492e0cf7a6f6598e0d074d6fe650", "SEC": "0417a3320a24e073b76f26d18b8bca346624c2e15a896dcb08e29132c43957e1640c2e9eca65a0f2d6157bf47565bfb3f6df953adf26ba5bcc61a4057acc10d65f", "TP2": "040aa8e3646c7212027fb7db7b09de91cc5ddfce7098fb513657bbc2c6b94ba8b41fe9049a26b7278ee0fd9c2b72fd32f7f61673be215e40754831cd1f550718c7", "TP1": "041ee00a2d70ab03258d1f6e2610a3c4d93e1b03812f969360ba4e789f979979110615ad3b3a737a67a8cf2760e13183318a00a97516f89aa9de7ec6cd8fe0b594", "CS1": "040c4884d5d8e06e70494246cdbc530dcd7e9342491c6266af00c16dfef2ba1a6203e3697e1ccc058d9a0aafb5f99cfcc8b389db76fe8e0de92ed0bb3427964839", "CS2": "040fb94982a72b4284091a84aafa313e979d27810c2d1fc131d8190fe9747884c60151e4a6685dc761ddb4466b07bdc01f70cc9608bb5b04ef0614a00ee6619089", "HASH_MPIN_ID_HEX": "a16336b5bad5fb2061c2cc76c581208da797076a0a81d870f6b79f25d83dc664", "TIME_PERMIT": "041c5ff91b959afbff88673a5b6ff1bb30c6c1eb2ae9ac4a5320e193b9cd3affdb02561d9004449c7f8e84e5c81199ddae57fb8f65584f96d204b17dcaf54d6293", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33375a222c2022757365724944223a20223838303431323065353661386631646462663339633264333061346337396561406365727469766f782e636f6d222c202273616c74223a20226335653766666165643163346238636166323463356661313539396162313637227d", "TOKEN": "0420882f53e8687478a9d40a31674a88147f1e4c2e658911f828a975f34970bf5c1065744bfe806eb4be4e9ce258d7a285616300912ba00e532477f46bd47de1fd", "U": "0411e09b2d32fbbecabf7bbd8b301458f63fc6c151fda5c0966473bcc95e90551810b01973e1cfefa27032b77fcb40c2f6118abad1c057c799f9894f983cd16ba5", "SERVER_OUTPUT": 0, "V": "040a3dccd4d8431691e02552965c424968b951a0cd7d3e6ac1b94d4f3fc1965fad1f86cb3de71e74120d1485b970b72b0de9f9f957ef55c3052f516b9ad6f791fa", "Y": "0be81ae6a37aeaa717abfe7d8c91e7e73d076c98fcdffeb4d13f739b6e938d4c", "X": "0352106f5e3ba1e98fdf2c035d03f84774c6933913a2f0d37e047a3ba0632af5", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:37Z\", \"userID\": \"8804120e56a8f1ddbf39c2d30a4c79ea@certivox.com\", \"salt\": \"c5e7ffaed1c4b8caf24c5fa1599ab167\"}", "test_no": 33, "UT": "04122981d485c12f677f83e4c4d99099a0a848c1b318e3cd5c93812556db763227197aca7911eaea067380cf180d60426098d160c5f9de9ba186a181b66aa7ba86", "MS2": "0719e362b158ba1a8a79b98e5fb8b6995d57f63c0aa521b466e3347b5256b22b", "MS1": "162376d5d1863c41b4a0e75192605ced23236cccc12b15f9e4af6ae7931de9cc", "CLIENT_SECRET": "04031ceaff75a1645107ee46553257a02cc9d57a789f55a6261089144481da62761f2020b5d3f41e9f78117384df24898f1790e7afa53d4fca76c1115c995ef48d"}, {"SS1": "21d462f344845826a349478d8389178810708ff3847e41df771addc5718dffbc153bc90a6a284137116e1dc47801e8107fe0bb58b6a3e47964df04821a60c00b1d2f65a4c09b240d11fbde279d113d170d3db70da900a5507fac3ba558f21b8c0c4aa7d0d67d90c38e355c971430395f57d0d55bcb7083b9dc12647ad93315ff", "SS2": "1b79c29f24b2416d9cf5c8a9f2495039f635776ef24c7c182be1cbedb3e663e214bd588975ce12efe071b600a786eb82c9e9280d3111040ac9cbcc99ae3990981074cc811b45172d595732c46bc4719710be33c907be2404d7ce66496c62cc59103d1fcc211c9583412c6e53bb616ad6762ce15422aedf066041468b4db5b492", "DATE": 16574, "PIN2": 6311, "PIN1": 6311, "SERVER_SECRET": "1a3f73994661b85050190c62838348efdfd0dc2ed463101ec3eda3993acd624f1d308f5da9054785bb8bfeed75d12991a6460aaaa239bcc8a4ee841190a36a440addfc2d23745ce34aa19dfdd16ca2536ef81f2bb8533a77b6828ca6bc13e30a1658f3cf02ead5d4424c52805a6782ab5ca33d23797d809e3232b28aa29b076e", "SEC": "04190c20a2644f54e0c8842a8df704634b697035484036caee559f30f56b0a532d0fc5aca565665b0af401d6de87b00e8c20a31aaa7426123e13b31195a2f5299a", "TP2": "0404766e8cb5af17f949d0c5aae6f63715a38cd3fcd5fccaf922cd1f2fb24b87ca13b56d010d8186cb048aad958aeacdea70fc8162d25572dfbf19959f3be4cc8d", "TP1": "04049e157c6e6f40bdf796d106fc6ebaaf75ed2f4f35d26f4bec77c1e52670bf981bb57db45e6a761213d138d4abed29173b5cf8f819e8c122eaa6f93ebc0f044c", "CS1": "04117383aa93f8410eb42aae31ba6fde07267eb6261974e993c0d91dd7a88e1034030822b64ac99f7b09852a25b6b9be0c0460bca73833306f441a5472381fcf1a", "CS2": "041760a2f796f07fc0a4b1d86f3a0183b717fb97cc2e1aded619cefba0911b18920d24019cf380d033ad3134fc5cba98a342a14c850564f9ae3d6f77f8e89ea3cd", "HASH_MPIN_ID_HEX": "fef40c2b9d4deac4d8dda4e1025bee6e9c117dac202d0b2e89a1eed0d2f0839a", "TIME_PERMIT": "04140ef6e8453d5db8bbb9f442d9c33c8febcdcb3de87884272fd3fc058a23adb20c774197203464f202fefc4c0966e9765dcf9d589dbbf2eec4f34d5332983f90", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33375a222c2022757365724944223a20226436633463663431333633336361346161346436366232363764303430363664406365727469766f782e636f6d222c202273616c74223a20223833616162336336356664336234313330653866626466373064376235363132227d", "TOKEN": "040752df94a8b4a5445e9456f7a283ca411f3439b549fc8f1a9cc6011e9397fcff061c4376d5065a8506415aa184c33fd5fe9edafe09c1b0cc755f39a3c19d4b3d", "U": "0411815b8ad39145fe729e7bcecd9d22624b41d2cee68dd8f02dda554598e4999001ae89e16e14384c4a1648582d76c3ec88891fdbc059c916e91b52b463718e53", "SERVER_OUTPUT": 0, "V": "041d60050d7ca8b3b1353afedc6351fb6544c8bb86082313e5ec4195b55360c5d31be11870a1c4b19d29620120eed76d2bcbe5ced0127fb7658e31aa4ecc7e4d54", "Y": "0721485a8fc7c654d4caeade0c201a2eb65fae4bb53b55244497a88d59c8978f", "X": "04cc5c4ce966b9afb57c712f5411aad3b591a13708f5302fa89f63f7fd9ed500", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:37Z\", \"userID\": \"d6c4cf413633ca4aa4d66b267d04066d@certivox.com\", \"salt\": \"83aab3c65fd3b4130e8fbdf70d7b5612\"}", "test_no": 34, "UT": "041ac6062e114b0f98328d0673116ae957752311cf8db2c65b9508e3ceb57dffae13071d661aa7874b29c6812237ce8fde3d301c836217f7027ab386921d788a4e", "MS2": "18b7956be8fbe87a16479a4f41da23028b74d7ab982ea3a6682a48dfda5992d6", "MS1": "203f20dc35b448a9097b91538bfb003f3e8c2a2e76b714f4f7f7fc86662f598b", "CLIENT_SECRET": "04056b651b6df069cc0753e35b66fbb3eb2042f6e198e50752da044ae455bf217508d390c13a32e2765ce05b7cf1d2de56c828a7098de38fee90ad9ce2d94f8fd6"}, {"SS1": "1b9d9ddbb80b2c8aa16f41086ce87b6cbfc778cebfb5bf585241a09b1968cdc30f0403e66b499765cbeaa215e1aece82e26bc898b98debd4ab9da7e1e7b062911d547800e3921c0bd756bb38674cd2e57a1166c9f749def305041b7545f1208f1e8589d35c1f5f757dfbc8c4b0965e4f1c11fd2af02a079a9ef177f680b021ff", "SS2": "070138700c3cd124aab760ce47a5c060bd232e0bb1430f7254b912239cd3314c0cd9d2639e767dcfb5554fd1e38b7ed01757bd5a5bc53eea3d916ac8647e7175107a05c47c12557400cec8aa6d4dff8d31928eb1a4212d2c8a4968df2866d9190e78fa4b5d10ae3581fbe90a83754e4fdb8c7b4e3d0eb84ebc7fea24a6e7f86e", "DATE": 16574, "PIN2": 7895, "PIN1": 7895, "SERVER_SECRET": "1403594866fe5bbbf873bff8d9f5ca3566b2e59c6ad3d0c757d31827baecb0d513b3493e6e6758d0db596bbd85fc414ddb76301fee3f7c1cf7d2f772593627751ed452c8b32d234a545d1e8318531cebf273fd4386d0d15aeba2de2c73cfd790021698caa6f31985fc9b24c5dc9febcb88f4fe5a093e07764b4082c7537c2bbc", "SEC": "04130cf2909e47181711a7ddfc988e32342c87e38fe12180c1d04e07ad1e3e884411f381c8513fc3cc6637727396182167980355d005a52d49d5d2db18b6529c9f", "TP2": "0403dedbe6e90bd93a3d5ab4e07b0aa1d2b3786f4ae9a60e8283b1de776d50b0f605e3de42433d0ca7d337542f20757ef8edae9f84e233771b7e38166082810f42", "TP1": "0414a38a4ec1cdcdd287e777ac2983a22388c175d0723fc1a5bfe47ad287f9134d00ec2988131278de51cbdfd2543892ede0d5338772176da183c6712aa10d9af6", "CS1": "04089e231e22a6edff3388a522a7ef5ece8acb9549798aa5fe45022f4a2aec9eac171c92bf2325f9f2da548e87799e534684ad5a0e04e7496bf45b63e5d41ed35c", "CS2": "041c9cca758c2b7bd49fafffed56f203ec4d65c11161d3bb1ad0467d8b24cd716c195c7d9d487494034cf1a47ff284a8ffd677ecf7af1c9e37a5ce63d932a332f2", "HASH_MPIN_ID_HEX": "5d89808e2e87dca0fa9e356398d9f00f49a12f379bb8d1f6aea40214513759b9", "TIME_PERMIT": "041e0b7c0cb5a385bb27c452926c934f0261b7e2f85e3f235554671a368f3ae6dd0d4a86d85c88b8a41e2617cfa6d110595e9d6f5389fcdab3eabd9507d29fa47d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33375a222c2022757365724944223a20223165323765366534333537366461366637653032303535376130356366313230406365727469766f782e636f6d222c202273616c74223a20223332383733616166316166623038356365306639356464326264633130346466227d", "TOKEN": "04125244bee50d099c547befcbb15b543d238c1808db54f57e11c19999e013319b22ee85d428b9ac64833252eebf606fb95b57c35e61a7e42743df58e6b4a65b8b", "U": "041db4514869692b636d7b9079a9b9e02c587574ad0253517d594def5747ac2d220a9b64d013634ef2ae11a0fdb06db2053b0963c0d3295e9febd2cbb8910f952f", "SERVER_OUTPUT": 0, "V": "04041103d646a6734b472612a2aa78636262add3adbfbfa0bda4d00a0cf6527daa007d5b2ef80bca1555963be1e31d26d82f45095893222894567e10ee2e7a1f6a", "Y": "1eda2ca4db135f1ad32c981170fc7f96de7d5856b4668180d5d863a14ab030eb", "X": "09fd0d06f541d068268c7239aa4028653b3b0cce4a90a0c9e09a91338ff06285", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:37Z\", \"userID\": \"1e27e6e43576da6f7e020557a05cf120@certivox.com\", \"salt\": \"32873aaf1afb085ce0f95dd2bdc104df\"}", "test_no": 35, "UT": "042160ce316f5a5fea3aa555fd53c89d82c1bed0f39389f8e4cac9b2208c411c8c0286d9363bf6b3164fe0a5f5bcd525efa6b10e5f7549c0a5f5077c2dbe0561d6", "MS2": "14dacc51858b26fbc49dc17bea031060b13bfc57acdb70a72c2894a22bd90ad8", "MS1": "0eb32c0274a4cee6bc3d2f3cd0a32cbe8c08943424203059fa08a0b43b1b7ef7", "CLIENT_SECRET": "04172ab74ee3f75989bb98151007a670b4f109ada544eff2ccfabe885d4d57aeed03a5078994e3b06c4172b659b66a77691053b9b35a5d527aee7655b76b7d00a0"}, {"SS1": "1bde14839e35741ec9f9a71bbaf943ed7594a0369c2f55d9724c0800fca01272152a01a99e22e5cc70dacbe51955226db2ce4f69f3b48f2793aca512eb9ebbd400f2376b839881347c1c65750e83d985a56eb92233a5109d74a2793a2755459007fb3f20b858e932a14d1db5f383013d31494289e88801add5edbaa1bf9cd1b0", "SS2": "0857d76d7b8d1da0815d3ffb2ae04f2d021ea67b05d3ba72531e3492bfcce4f4105bd54e55e1f817f97f40b05a574df385307d34d12714e5021d2039be592b830187258a5842057f9078064b17b671ae5030d0d3ddb0e8487ba173644cdb692302208ba24671d1d148f7563aeb5f6f52ab332cf8995d6a8b0c494ab0b0b4a7dc", "DATE": 16574, "PIN2": 8097, "PIN1": 8097, "SERVER_SECRET": "01be14e528ec6f6643b29784decabca2a5f96b788c5b3fa61187cd7cf5b36ec41f98df5aab62a534a6031a8656bda73c54ffe03bced6a7ae8eeb8f79791d0b8413542cf6cb50eae1c84939095ec4269771b41d58d8fa4c7d336bcc35d8f4ccf50e230fa3cd0c241c9146116a9bf8445ffe602dd134e28faa068d059d5b339181", "SEC": "0410ae297f9c97cb748906c9bfba03ca8d0b8c9c9e728bf7442e9ef327962a6f402036589285b191f13a9921e6d4acdcba28e76ab401c656467e15ab052578894a", "TP2": "0418217ce30d0e60d5f907b3659625a37deea148630eff0e3ea021e0748262e5a318a22fcc7e8d6309a8717e58d4e8bbc19336f1fac01c84c4f5a4b1fa8fecd9bb", "TP1": "0405fe40b69326c0ab8106ea44675cf97d6bbe640a5068ac95e6a255842d178952111cad6370a249d4d13067eaecad2b2d79e16f2e82e367037b823c7f2769f4cc", "CS1": "0418bb2148da2639c8600a2957f28a33aa90a0b12fac845fc2196acbc6199f1dba00248e691afd0b956913a59b758e4dc7094208d91245724bebe20ecdbd5774fe", "CS2": "04170d91392cad37e3a89e910cf5f3ebdbe9d99459df998c95db055838611bdc591c3124acc077d377629f608317a4e4c559e94df6a6c1bffb8260b4d7e70abc1b", "HASH_MPIN_ID_HEX": "53bf221efceb556c112ee9559507018c95045dc0d8f2b9d78e1ad30a315f1cce", "TIME_PERMIT": "040ded518204d7835900ce667dde5ed0c23cc2764c1e7aff7a262f543d63a221f00f023c2d775a9115fcd99a55b15be954b5b9dd7ca867fdc84d20e43864b6beb3", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33375a222c2022757365724944223a20223464306232363735326436363137626133623834396565613861306333656662406365727469766f782e636f6d222c202273616c74223a20226633316364363666663638636566356162373962626361373666356233313236227d", "TOKEN": "040be847edc695a47d02bb39b082d768f66a92ca5d7afbddd180d135c968921232007baf09cb91962ed7daf84400f2a84b4e04cbe6f49674395888c26ab1e34896", "U": "041cb6ddd5e10e0e7ceb8c879be1f764353c060fa41fa5d03b97f285eb2ef4a8b413b60c339b68e3c0945ffcb98fd3c44a4fe7bf220557ee6bca925fdaacad7161", "SERVER_OUTPUT": 0, "V": "040bca72fc35fe61c92e675106f58863060addede5266b8dc3b70afba9c3bc9da70738a15a0d7d84a4a4c8eb52925edae7ee7dcae2ac9739b6701c0a71ec5f8382", "Y": "0bfc8a5e3ee8b5b0afc3d3978a618d38b0a33a830a08a58386657ac69c13c905", "X": "1e22fa3b7ba3ba327e971e0fb8ddd8b6277716ff4ebd89b00791f05510a7512a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:37Z\", \"userID\": \"4d0b26752d6617ba3b849eea8a0c3efb@certivox.com\", \"salt\": \"f31cd66ff68cef5ab79bbca76f5b3126\"}", "test_no": 36, "UT": "040fa0f58bdf8da79b93f9e9480b1dff8b8edb4076cb6f4e66f4ca013acde4d035164ffc5bed0d9b493347904135b8c583fcd3114d3be276d896bc2b1e862b3f71", "MS2": "23e4f31823fb383200bc1069cf4d28a028bc0ca1dea8511cfd3b55c450ee7d9d", "MS1": "07cffd63f94806e7c5bf8ac40af15f9f477d75964877d86530ec393f992303ee", "CLIENT_SECRET": "041dea48afc3bf1b60459dc24621ffa8c1fdce5b9170dc8d5a65445296a2eae6ee11e0ac1006475a0b452025a7d20ab72c503bd4299f38b61eb286d2af3209c8a7"}, {"SS1": "1baac3a41cf3c3e9cd5851cca8e49732481e2e2cc3f9e81d37466bef76617f120698cb50f2335595f1f2803db44fa0dc82ce41609de0a694ea569214640a6b5b22ce1936022a2710ab22f588cb10ac1a7974358b75fef517001bd5c789f1ae3d11591c2b36131fc026ee37a4540cdb812ddb74f460c3b8e37620caefa657ca4d", "SS2": "1549a4c6bf7d6cb8d0b73e9269fc08e99f503645a675243e4aaf5c7b9c219eea0ff6e3f2d5341a0dd4d8abe1b73d9fc50750df59a8c8e75e3b39876badcdf4c2127d3192ac45e88bfec261d6b0cbd143404142933df4a0d2397a1ce8766d1f1c008de1cb5e7932274e17ced642b60ad1c6c4acb3fe164e9c112280ce3e878f86", "DATE": 16574, "PIN2": 735, "PIN1": 735, "SERVER_SECRET": "0f030064a0c4fbe4b1999451ee384f764505e68f8adb38446f62c4cbe7d33d7c223f400e20ec1ba9553f047763b0a2620641330ded3bd36427490dfb13aa8efa20aff06bb04c900911918d521cc19fe57465657a226f7b4f45a54307cadcba5417e75532bb0a967a9924a4dca86a6db6511ad72e4313a748eb9482b2f424ea3e", "SEC": "041485a62bd6088e057b3b447c1d605788bb1fb5badca8dfe52d62227b8eee1afd0302914b058772291d8bdbb6e7a7964322dd0cf1feb02d99d1c2f161285654c0", "TP2": "0416a6bdd6e21aaff6d9183e42ca2b3b68dc3fbd03b407eae9890387ac0e1e7dc71664c506f7b4c0fa2d52345e50ae30928ef3c0de4e298577df751c9b307ec2de", "TP1": "04131a78efcadc69133db43bd3af75ed69ffeb01593eb16fed8da005e4c361ce4907531f5bdc1d99bd83dbe48c181576ec0d5e4a05e9733d0aceab241a092d4532", "CS1": "041c31991b68b58f85140abe7e3b0860b76deeeb8c260824f6e76f48c91d5582c003c7a89c7c0693564e8db9362e23f1f91d8176289bd2fc4dc92a1ea28d323257", "CS2": "04108adf24569f39ddcb79554013f8395512836cc599ca93bc09a3fb3b02ed46c70e9f73bf6dc6e672ab27fa5cf6adb5ff2167ea4775bc05c13a846015d6c71feb", "HASH_MPIN_ID_HEX": "29ebc4901e4a5ababe65e315e4e56bc92946fd6e3ea190e1b37ae29a40a91159", "TIME_PERMIT": "0406e79335a76e4f5535bc9fc8366254e87c81adfc9a4f22377fd4e1bda38decd513739cee538b15ff4a34a94212a7b82dc1b113952eacff584fdf4367fb160683", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33375a222c2022757365724944223a20223439336633376164303337363230303936626137346261393535376433393165406365727469766f782e636f6d222c202273616c74223a20223634353333336165373766643532613833636333363565366266333034373762227d", "TOKEN": "0418391c3ca23d4b8928effd7f6f7bf39bcf25aeba85c150e84c5ad3edc55d77bb02838f4a3599860f17d750ee70983ffb5fff14ef55b6bf588d2e6a0052802e5a", "U": "0410fc51bec635f45588a3c1ee21a5e66c65d917b0080f3fe81c039f1ffd1b1a5e046d7b51e19899a35c7aa3f145b1bba896f1893c603cddd08118d3626b263c33", "SERVER_OUTPUT": 0, "V": "04046bfcbd98d1d2a62d4afe7d28a4657bded50b59a466d08ef9aec1f89527391e082177486a1dc9ccf62938c3e3814f246eb72fdded6a53f00792beb88a044555", "Y": "1684a9d98d2b383d519189a65ad4938deed3cbd49ee1965d29c4a63b29df8213", "X": "1f2ae6b6f6594d0a3e4aa2fd778ffd5a970a1bbcb9b5893c85399d676cbb2da6", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:37Z\", \"userID\": \"493f37ad037620096ba74ba9557d391e@certivox.com\", \"salt\": \"645333ae77fd52a83cc365e6bf30477b\"}", "test_no": 37, "UT": "040f9178df240576915762817a2ca6c9cb132bd4a205edc04c262de6b1d9dc45f81b7b80481a1b1ac094c355aacd8fabf90b2bc082aa339a468e2c7f0b487b38b4", "MS2": "1653805021f7a0e0b33f47d991bfd427a3f7f4dec0f1a98f88de7ed9819850c2", "MS1": "1ea10b5074f91390f8947f87f89e8562e8a9bbbe3caed219f023ef3dcb12676a", "CLIENT_SECRET": "0422df73b68cc3a7885147b88e89cb1fdb2e4d3abd1e19e50f8ee3d0d70349cf1718856eba04bb37a15e43ceb391e406e8bd6bdd1f4126dcbc3c1d865b66a7779d"}, {"SS1": "1e358cc9576aee6eeed8455bccc254415523c532de06b01d0a4be621e336b0d101074fccad1adcf2adf2e68826cb0e0101dceb49b9d7dda53a9c5cda95ccec1c05edebff429f5664c3d41bbcc7d7e57a8dbf6f5cc743470ca1ff7f3808401c89204f768227f17c794e26199e697e952181698f260e6444381974333f0a317fe1", "SS2": "0bc4f47125c287326814427f2273effdc2667205f085c6dc64cdf0da9ed110ff00024bc6ac46180458344b6a6ef3b3a8ffda72a95c71738e56c5da39ca889e9b0727d381cbdf87af2e9c987da93633e0539ac05b4389ffa88e8fd4dc56f48b1f01f400d5da3263df72ba29b1ecd61925ba3e560cd3ae3ba946962c598019c88e", "DATE": 16574, "PIN2": 2937, "PIN1": 2937, "SERVER_SECRET": "0a15332fe13ac8b3c0570e0b2d32be4a4e4e70b46dfea5b819612c94ba5ec23517fa20ea39422f0f35b7bc0912338306de6c77bdd793323c36045bd9d2856d441d729a08f1bc1e12631876c7fb5e21b580a691d47257f44edfc2f680dd00e1c51bc6716ad572c40b4f9c72465bee9b9c41d35de9de1435ede2d216ff100eb9e1", "SEC": "041a0657743fd1e140ee7f248da7d308b11c0eec2b12e0951275e1ae81a432468808cd6265c6d7922b6d9f327b55151a6f94fd6a283daf52f71791e305159be537", "TP2": "041954af81e4b2796c7190a6f09899af75d41c1bcd6e4743df79a16d7e34814a981c96b4cc0a4b0b1fdd1668c26cd30257b2db8f2250887709a561922f97145ca7", "TP1": "0406f8287e83f6e0834bea8e3504a6a0a7d5fde165ec120f84b5a61b27e4cedc6020bbdb7eb3cae37fededab479ab2430d0bce49385e721a845e68706f21080423", "CS1": "04183918fb9782787dabdba9319f089aaa5723f82d39e3e0f13e34b96e8833b7871876dfff40901532ae8a52ad270d5c099777b0c628deb74808299798b16b4331", "CS2": "041b2a9a5cc7ae6655bcabde13c5c3ddf21787a0d231711506e902ec4b8984ee1109452d29104b4fbb9c867f70d219abdf2e26c62d72d0e1ba2aff9ba47b7c9415", "HASH_MPIN_ID_HEX": "6313c7ff9993f5a8ceb969f3555aa0af3a96cbc29513f39bfc859f7f9fbc924c", "TIME_PERMIT": "040bfbf55ef234f681f1469e33d88b8d8e9d9724106476500a5e7a7b05ae3beaf723ac2a76898456fd04c4c0ea472f10e3a8b8c14c4a6a8c07fb40fbd6e2b171a4", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33375a222c2022757365724944223a20223236326138306439393039353433353435373734323839336432663737623061406365727469766f782e636f6d222c202273616c74223a20223865333363383733633732313963363637653131343230656262383434653363227d", "TOKEN": "040b10bb7635f76a45d5cbc1fa2f2cd8a33598863b8b7bc854ec1a59f2048ba3381cc2b82e766b5362db000e02dc0fadfa6697796c780d863f835a29b2f8d0fd96", "U": "040158671ff252ff868cc15194c06f5d23b2903eedf3492ea2cea22db4d8d67af001a7eb87ac2985670cd841fd4beceaee1d201d0b3647c4f2b37ecb92b2174553", "SERVER_OUTPUT": 0, "V": "0407c1cf71bae9a7d7c8de2bc03ea7f06a367030b47c2b24d8906d0bc7e633c41c22a66e7ed3593098baa101812bb9ad962489de901f86e2cb88044513f1e2d3a7", "Y": "12decf0c19b3ec4b3dfa9a0bca034a58dac452ea70e57e0e4d59b33baad181af", "X": "1579aa4b937f16033d8746a4128587bbf3106a77f3eaee77e8bb8a130ea12d63", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:37Z\", \"userID\": \"262a80d99095435457742893d2f77b0a@certivox.com\", \"salt\": \"8e33c873c7219c667e11420ebb844e3c\"}", "test_no": 38, "UT": "041d02e0d6553c1497016d185de97a4b96762ef0ee577eb4936e595297f29e524413af4e262c98dbda9380176c0c74b6209d4887c126d014bfaeb80de4302fc53a", "MS2": "07affe4ccf32a40c5617090aa597dac10a3dbe5a50e54f157be89cfece525238", "MS1": "10e8014040f1b52da0a392a0a04e841a68ceea6c8ab9baa5c9fcb00d6fb50f14", "CLIENT_SECRET": "041da83558e9977b4587521fd8d9e414ba70876d3bb841d069c8a48ec6f934832e0ad8f45c8ca500b077b3ea18784dcfe83d72a5b79064e630ada263bdea944a5f"}, {"SS1": "1a833061f4653e317d8a52af953b1f5eb79a82c258d00d9c18fe92fb9badfa9c13189815b9d633fe614a1d4cb28a702f66a0986a1dc54632e1536d3e2142faf2222378d602789ee24907d9db617483c5b7beb930fd97beb8269f2426c321250b079d4a702062efb170f61b0eabffcdb49ac124a99ad2ebb28750d3c27ccee6e6", "SS2": "14eb2d9a580eeccf9174475ad1ea9823f16005ef6189c888f2073e9f4010f36b1838a7145fcff29d12c631e9258ca63e6da6054117a530424638b0de9f9d8c2910234638901cf5608e0ee2610a450ef9c40d91d9278374cb663a4051ae55371e0f4478c59776843a9acfca6b9bf1acb822b9efd3d75707450aabe7f41714d391", "DATE": 16574, "PIN2": 2168, "PIN1": 2168, "SERVER_SECRET": "0ffd217a7f7ca6b4008cc6fc944cbc4b8f409a08371f2ae01635c141e3a020b51f4025c39f7511405e911e6ebebf499af9c9a5bb4d8333571ef7a56591bb67dc01137a191873a1886cfe9d7bb3b8c68c5b0c564993fd00e4982143ee37dc05c518d9ec68694e0e98ab06069dd5462a22d40c2158b59e81c5437a49bd9a5f421a", "SEC": "041d3d636e594ff0f56c4d053609d9281628eca357a137b8e0f6fb9a2ad751da2a085342f869547cd8f15db1044e7685822a35cfe06dd46803d0273728e2c1122e", "TP2": "040d598ee268b169596221d96d6da3b24b323c702fd690f19577f9d74f761b652802b8bcad2b548f5ea4378d6f5e69d73a9182c1c36edd42f3dd8d8cf31722e183", "TP1": "041553b0de7bb98a268cf1c1a209701d4d7ce34bc51b29018722477498d7d93a5918720f09e11fe4843a4a2f7b247069ff53f4fee42cfb699458a350ac2cbf00da", "CS1": "041084579a2b65ce425f44ab6c6f87865e71d3bb7d14bc0277bbc6d7929541ef0717389ac34bb3123678b6ceb90c7ed46a6801f8c64ec90d49886c3dbac41d7368", "CS2": "04134f2753668a4c299ccdc1b1ce525b2824a8812fed4b2bb11471ce58b397491a14b750867251286324ab4a62e8e2efffc62c44e0868a4e57d430a5045b1d0824", "HASH_MPIN_ID_HEX": "3225a1f3f0e0ba6b4266536917e44c50906cdf7ec35fbe99f5beb15e741d971f", "TIME_PERMIT": "0405a1123c81d90fed02e6439caf749054eed2f3766c44daf4a970113602c58b0613f7bb3ebb6afdba9f5d0aa2d7c9b59608fe6e74fe3c7caf38167b01980aa5c6", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33375a222c2022757365724944223a20226161323737303638363436393962393533613830393936303661323530313463406365727469766f782e636f6d222c202273616c74223a20226235343336356238363162626237636666666366303461623732393937376262227d", "TOKEN": "040d8ea5c581905f7358831585040f0740d6162d0a3ad91b51996e021923bf0e4517800c03a30f960d3aad0b77ce7bbfced613059d233797f075ff2f647c8fa426", "U": "0418c6a0804c39b4bcc4fa5f39c38de895442b952ddcdb0589598f1676035e33ca138338d6f8cdcafa759b601640da13eda5f5937ab0c3b180ee4f8a9de83f5061", "SERVER_OUTPUT": 0, "V": "040f3fa6f318fe1c3ac9d62ffab78ac96ace42382387a602a076b69e20760f96b51367c1e73b96b1a6077723b1b7cf898c718988330948055205e72e8bfcbccf90", "Y": "09a274ba30e63b247f95c0d1542519ad5bb47654b36ced1306f2789705df6348", "X": "0b3aef8a6f902ffec2d9513e4a1a4d4665ec6d49903088c27814c1a1aa20c2af", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:37Z\", \"userID\": \"aa27706864699b953a8099606a25014c@certivox.com\", \"salt\": \"b54365b861bbb7cfffcf04ab729977bb\"}", "test_no": 39, "UT": "0405eca5c0f30cf79b2874ac81a1f6f526b42216da9e9aa8f0346c80f6210df5f2050701c8d824d0237c3c436566e43be5264830b02b90dbc8823a3d68fab6874c", "MS2": "08f6d49ba532791d2914cbecfa54e5d644428044979b7248b1a77ffe4901ab9f", "MS1": "23ec91325c0bf427e6b972009250c59993a086a7a25b056a7d2a37c08d294b3d", "CLIENT_SECRET": "0416c1e339a0fb66ab4012aa8334ecb3d991b90eaf874da6aa5f4714a13f78ec751b1fa94a651479fee8e9da93a2cb064d5eaa2a2def09bdb39760bee46b3f0f79"}, {"SS1": "17053e28f6341c7bc09068b531cc8edd5043950b0b3531b351204ca59c13dbc20bfb0bc4b4a03e13ff5ddc6e32ff9d1b2ee92db1dafc1ed3eaedba28d46c3ada22a166dce9b3e38bd558c0564f0c003222b4643fbfc410a61522f5e941ad56bd0da5167c75fb475b534a270a9137ae08e226570b731397816f2f86dc7a03640e", "SS2": "050d87c53b96255de9af65a94363164f9c329e7a6620edc811b82044248d40a91e33f19d8bd5e72b0e699d91c27af30284565b6f2cc332791ebd1fb12db3cfe407ef4dd5fcbf9aa1eb3b7753b24de4c5e8f08aa979638649775bafb40376efd70410815dfa27600c5e7838f3035a6aabe6faa35f6b4b2051546705ca8b8fb473", "DATE": 16574, "PIN2": 5049, "PIN1": 5049, "SERVER_SECRET": "0e5cff3a2284d28a826195703ccc8dd8ce3d0ecff191781b0d3b475034736ff20a216f0cf74bc4ff402a13895271c937a41388c18cf2649488ce7996b27345b408fd979ba3d00db2bbabaa1fa731cbf9aaabcec9172bcbabe204642d8a9fd5cf135c2efc730ff98a53018313af4c91d7f89279f0a274dc6fe122d21a67cd9a90", "SEC": "04036efee0c4a976cb13a25d786b1502fbedee038c57532b5d5086cc4e11e1c40e1077dc340483bafa133f3ecde34087b2410346cfacef14a3f1c882edf5fe00e9", "TP2": "0411de4befbd5fe9be95cea01f4ee220ffa361ae1d92d9e1965be008c2e5a527b10d2e7beddb06577e085aa45341d10a0989072a66dd961c1fe0cc8e2148a5f9d8", "TP1": "04207135f09df697e4901bc43be20d8eaec62f12524249b620b564cfeacd7dbbf30c7bc763225dcba4419952cd0b5c672b9bc5b3a1edebdeb851aa1a43f84cc904", "CS1": "0420a5aedf5b210c6a9af1a054971715ec34b96d51773955030070bccc052241f21be2ff51c9a6715146d9c28a255bfafab034a10c83dbc20a4bb1af3fe6ff9390", "CS2": "0416c44fec43e7f6a772bb1b95f55be8e947771e95e1bc855b9e11bcbf8f66ef5d1c6b1ee6157183f4b04ccd3dd62575e5f384b035cb4012e22372d351e6281be1", "HASH_MPIN_ID_HEX": "787713d0f77aa0f39d299f6b02e3646d96bad76d74e60b5d0777d5bdfff926dd", "TIME_PERMIT": "041a5d4577f454130bfbed0699e3f4871220fb73eaf5ef71b13ac64f099d8c317414128c50cb4395b03d87ce4f257783684584961e7bda1ea96c68634d52a4520d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33375a222c2022757365724944223a20223961366639323364316564303435356332333437653065623664383065373636406365727469766f782e636f6d222c202273616c74223a20223739613432363137633361393239613238363639323639663738613032343133227d", "TOKEN": "040ba65d047de959bc9975e481a07d8044d4f3361de0026f7777caf5afe15cc8250d57f845123d53a4361ec62ba5a1400d0e77c97d2ca300133c543a25e773d06d", "U": "040da0316ca9cf9881df8441f671afd3b1504bc3434b2572c60a0dea3927ec9857075fade9ea54607f92ce49eda1ca6a836db1e0726b9a07066b1c8c70eb98e9b4", "SERVER_OUTPUT": 0, "V": "04009099d51c09237496285fc9e9b4492a8e52476eb96fa9bfb89397650ce8cdc00083ebe986d0e55a74f1a078dca106529374bca2cc70680ce8d4fd8bd3e8bc47", "Y": "0b4b2418136a78877982e8a25d8e35886dfea43db09040d64a5fdb6e0d456bc3", "X": "18c0f9a0e70c1814a556a64bd8977a633aeccbf3ff44d2e02cfd612c5abccfb4", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:37Z\", \"userID\": \"9a6f923d1ed0455c2347e0eb6d80e766@certivox.com\", \"salt\": \"79a42617c3a929a28669269f78a02413\"}", "test_no": 40, "UT": "0406767508abc9d80ec7e188abc989c59bf365762b35333157cf454e61e56b7d22175fed893a3ab101b6f04397f020fc7d78ae1630227a23ed0a3576a0a93e27ae", "MS2": "16b74ba6737b797d86988f332671e7c92a6e347689438f8b58762f358d4f2a6c", "MS1": "17783c084e69597cc078c892442567e5447ae436115095625a2a29af38c84f1d", "CLIENT_SECRET": "04123d64aa1d36ee2c68f1921064c4356ba863cbcc2fcc2f91cc78e7c8f1c5e1e802fb396ce8bc1f6d18a3f7d63fba06a095a50f5e5b1cc94825a7429d7757104c"}, {"SS1": "08fe231434d882cf75288f55a9d1bfacb984331652ffd52a7984afbcecdcdb501e1b5585d5c8ebb08b5cb7c2ec46a5be6c3fa697fa7430d750b8604d01d8695c179a60c22d310d1e6ad04e90ce6012b1dfb45a744c065ad54421a7174353d77f070c14e6d535262c549ae499c5784247e324ce16d2558a037797a913d8e01944", "SS2": "17490ded5b10cce7c73977aa8b03686dd31123adc3d8665d697b7dd61fe7bf3d10dbb955c606ff5c13b19eb16397667d245bb6156e4b3636494ed33eac54df870b0204466c7a4aeb03ba8ea986009b4e2366b78a4b6bb4927ac813772d505cab154f90423ef4647d144cf8d190c6d3e0fd3dde0299b3cf63efb1130978da3b31", "DATE": 16574, "PIN2": 3457, "PIN1": 3457, "SERVER_SECRET": "14ac6edefe7eff003e9be86a8212ae4b4ce748bacfb06bb64b35eec4b23a8dd11893866c063aa6194e5a7c30316b631db975ce638bb86e0352634a1a7fc3960d07217a2ab6f1384060d80ade638eb94d5acff161d5a161589caf0da0724f122e1b800c0ee6d04f2e96ff6e9ebe510a82ac649b415faa735837a1530c23b97fdd", "SEC": "0407b598d932955581f5da5994cc61b958ee73f7c476fc9d75119dce13fcf94683180bed2aac64e4b82d8d9799cb30a60e33c499413765af3741129cad7022af59", "TP2": "0408aed51e92b9512f396f20b0fd34d71378e977d6159b0f870362b4f7c350493716ebf0ed86ffc6de566a7cbd5418efddb1dffb52251a5d6c869e83abce0ddbd3", "TP1": "040e5195746f667bd1443b1bc461a88884579a15c51857fb728f8e158b088a5a6d1026bfb393f6d32baf746f297106d77dde93bb135008fcbfbd0e505e14d0918c", "CS1": "041cdbea83265d968c57507250dcd8d0713663470bfaf8ce24945349fd9f9dba84106fbd85827413c86b76c55f38c4d66f6ad0682584dc3d16e3537a53a2a48b37", "CS2": "0414cc7b69a5b1db3d5a85cd27947bdf27a0e10c2f9cbc607c25d1a210e561b1a21d9a79d09b382570fa412bb06916a0f2baaecab4d28ac76562aad379f7a1fe79", "HASH_MPIN_ID_HEX": "04a119e9645c4b8caa5bfb7879f57ee3877306c89dcdefeb8f94ed6fafe2fb2e", "TIME_PERMIT": "04032d3981f3b51758ebcb616bd5d4eea324653b8998b9f2669e3fec21e1f171961a9f4c835bb0d9de49cb287f95d52e7285fab8a673d5dfa998c95b449b13922e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33385a222c2022757365724944223a20223163386663393039306236313536373665633635346333643038653138356233406365727469766f782e636f6d222c202273616c74223a20226265383936633761616361663665666531386236353764393366333963646331227d", "TOKEN": "040a9b1f0b1001255add0840bd458e79784edab15a69fb535f732d9d01721f008b16826e12598c403e2f73905b5d708afa7d2a141fe0bab71ab6f784496554136c", "U": "0416545d0048618ff88ee82d11c92c00c3b6b3e1a2d0635f84dd886e232ca316e122c584b384b0f3db15e04879e5884826e0cf03f5094f3d6f2ed138594f226e1b", "SERVER_OUTPUT": 0, "V": "0411b5b98c96868a98e03e46af1f58a2921b3e731ce46280333eb49e3962e6f4f1081021e2bdffd303d2ba85e6482ec9b790493c013e0e0ecce20eff0137090bf6", "Y": "16c67213a740fb0d95ebff93d2adee4b25e1f1c9210140e077095dbf2cedc1bf", "X": "1f9dadcffa1d108788b9af0da660f63d17b75c9e97322b1aec00764b330a0da0", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:38Z\", \"userID\": \"1c8fc9090b615676ec654c3d08e185b3@certivox.com\", \"salt\": \"be896c7aacaf6efe18b657d93f39cdc1\"}", "test_no": 41, "UT": "0417634d3a4f55816b33e9d3c111de369530cbd4c33b4467182db17bbb524ba0812052d628e7bb1eb41ff6d4362cd5038bf518d5d7f21275aa56b343f3b6ec5fc8", "MS2": "18eff6f737ee7b81bb025d08ac2165b9a5b9454aac5e48a7c0568282c17ec5e3", "MS1": "14700c735daff2ca05f0b61152201ec33168b509ed40590954b33a76373527e4", "CLIENT_SECRET": "041466ae91da8003559797b55ddc395a3ed1b4d53a90b59b07516d5302f0b57ca500a0fcdc3aebec8e9ab7585b56fb6d25938772a7956d0fb3d1c52ebba64e667e"}, {"SS1": "2065868ff82f9a766ed9c0c1b9b9e4959603c59f8ea15d105e8da6f666ccf1691a57b7a666dc7a646e3cd570620cca08bef710c2be30606d5613fd0d802cfdcc22a8413ca1c41882c2553d5b4344a453095b47f3c23cf3d019c59e1e6c0546d112b91177526de21b0c9f802776e4dbe671c87b5b96f4c0d3989ac1c3411ed724", "SS2": "1ffb646ebf34bed4f1e889a3ff586c2c2860efbcb7564e4192352c2ba0e4d189178e1c8f52c9a073b299610a1da3306ecd45e0ae8d3d50eea64d5359fe3ab4da19856c06d7809d3e193d2af2cd6872611dacd271bc7f8e8397a43344ab08ce6e0f25db666f4f1f16e17a6c5a1e8a47ccaa82a5c21812e5f32da9422e85cd03b9", "DATE": 16574, "PIN2": 4384, "PIN1": 4384, "SERVER_SECRET": "2136595734d228cb3456cc1d4cfa0fbddd71f0414077d14a1ff2a9beb7aea79f145bda5c4c39030db8ab8611c9ce0d1c86bd3c99d2aad4d612001f5369f183b30b18869e71f893ae31d17d18aa339aedaa546605447fd81065d70a7dcd7a8caa1d32de1e91527e7d7a091964d55d5c0d7e1c986cd94baac6f79a93990d1e0215", "SEC": "040f5b9c400358154ca28f36bdb0d430047f40ccc1255ddef1ef8cd7283f6dadc3216232437bf2a408a0bc632baadf005f094f089511b542636d4b3cec3f1d6147", "TP2": "041cbfde5f8d24ebd932e8c1b3265882a9a78d1ff4938987ff93c000195c0d6d6c212a6c327932a0b2b9e0696cfdb91646695f1ea4ea3f309a765fa83d208d88b8", "TP1": "04043f5823887809ef1f3ef2e3062db94322338339e4390f45195e340436e0c0bb0a4c3117b78aabdf80fc9e3a6dcb5eb2747bbb3b997ea80515d960dbb7943932", "CS1": "04224ee0a3f9fc69540103efdcc70653c15a1607eb36d8915550f80da13d3053670fd2b0fb6787329e7091c06cfb724bdabe84e14ba1b5435ddffc5634fb284051", "CS2": "04086ee7c753980749bf15ff82da4e0b9f7096ae265785612a3489a97f5cae969c16acd5e6ac13baafd13e82dac44dd2198afbe902b770e81df0fe837e8b20ae96", "HASH_MPIN_ID_HEX": "79d3852057bafa76ba16d1d4d8a322c480cc521931a66ec81e48c6884628a379", "TIME_PERMIT": "04169dedba0264aa30d576b010a4a76a336dcaa01821fee9f2e3549434de153c70086ae66b68b6a8da8f13bc362eabd157ea6696be2a649966a55d3e4b7a5395b3", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33385a222c2022757365724944223a20223361343564386332626338666262333037623764336466396361636361643534406365727469766f782e636f6d222c202273616c74223a20226135303430346433376139626463376534306263616164393130333931376365227d", "TOKEN": "0402ff3db3f26084fb3747e4ed282b9f4e143eb2cd5ff5761c1ce7b52b7be15e7c10454dce671273adea191bd2751cdb288ed0f0b02f11a6aafd772fe140c8b150", "U": "041823f489058679780fdaeedad83a08994e9ef85b2411dd67088802dadebb72d422466f3587cdc3f5a1ddb0a596908ca4a02c4d3af71ffeafb0f7ca0840d3dcde", "SERVER_OUTPUT": 0, "V": "0419fcdb92ec7d5ede9fb9c42a2746e4888fa1dadc9712f0fcb5bd0cd96dc2f7ae1265aecf3708d2ecfe26a91642d788c5b76056ca396e77a4c2ecc8fa4d566c06", "Y": "2159c48b189b53b38c44c1ebb7f1ed4d8f58154140aa1727e79be2c63b814a5e", "X": "214175e915aca380ec846922c7128682111334dfd6a48b7aa15a09684ef3d4b9", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:38Z\", \"userID\": \"3a45d8c2bc8fbb307b7d3df9caccad54@certivox.com\", \"salt\": \"a50404d37a9bdc7e40bcaad9103917ce\"}", "test_no": 42, "UT": "04115e489190ccfd2b43158cc484c59ed23caa21dadd3d9214102109b391758b010a685622f58d1b12e4666ee7e20df2297860b4101b1bf824fe0dd8dfe0fc71d0", "MS2": "22f46c0e7f1e398e8876aa707983607cd72e37c3ece7c96f343e3bec482546b0", "MS1": "21a10c8e86fb2f44e22f4bd856d601390c843f4f0ddfee8a9f98473576c3464b", "CLIENT_SECRET": "0420e24f6acca73a224ff661338c154455b4d6cfaf34bbef79a7b7948ba7038b3612211967cd87202c9a6130b4855cbf695d525a2cdd5863d2672c9770a1bff7a9"}, {"SS1": "01693056300c8e68a57cc0f7085a900fc760d5afe1c84b51d80e53bd28a78f340091fc7e9914bbfe7a9c8767ef9c4757d4be38065478e9bd46357a5f5dba88891e4a928f3c3fce57c65b1c37988b352f9d3be8db5479bcdadc89f856cee27fe917b97cb5f31ea59099c6ea7e3d9f8c468551294ce613b47ca58a52d29a1d6fef", "SS2": "1e84a33a8ae4b55d9369cfd37b4bda7d6fd59465065025837a015419cf28231107fee1477ed2ada57bcbaea843993711d6ae01797edbf0b20e7e7e78b0acc9bd0de27fcf2feea1167f519b077786a91b7eef53edf6afbc607ff4045962c4642307866a440d56232ca709539126ca6eba181694da13307079c646e4c696e66619", "DATE": 16574, "PIN2": 6525, "PIN1": 6525, "SERVER_SECRET": "1c50b9f4624d5dab1b91f3e08652749af94a34ac6efffa1c0c778393308bca2d23881db82c332e7786f6f11343ed57753f1ad93d483081d1df064e7000e383d3236d5bb1e9ce77cc953d8fab128e0e6dbbb8ff0cf1ae8361edffb4ac23913a7d1bf2d45335c6949955c6160de976afe8076ca89e38b6384b7d260a4578204425", "SEC": "0413625c4fd08bd3553de1b87a82786205a1c9e0a1837170a3d451c82db445cda10895e9b7ffd6539617e8f8820ed1abdf84d1f6653c0092d2d23261f72fbc4e94", "TP2": "040cf2724e78e44b2bd56b017275659a4f63497a54f5b844b7418c7b9dc6691b8e0f7d49b5dbb3367b9d27b80d58c8cee3c01bdd0c74677681918309528faad3ac", "TP1": "041b14f575121d8f14d1cea9d47a0ca6a8f969ccde9f9550f5ec7d72e7dc04679221b75fd3ab23bd7a6a37f274bb47c8673ed4136b9c6b8d6dcbcf7a3c389572d6", "CS1": "040289b4893af86b3a4aa2c819c89c3a483c4a61b9b59eaa9781cdab89506224801ce12e23f2ae98878a4b8f96622dcb2f7c198d173dfd68dc6381544dc9e72fac", "CS2": "04076dba49be5e8be9d6ff52851aec054b5f4d6f1e965b9d488ff5630ef29405e70e67d4764001c07fb689751c439d2956825c2b1f47c843e351d4e92775f9d69e", "HASH_MPIN_ID_HEX": "aab948eca90bc7fd86ba2c0c6a9e0bbebab32defb752c6840e50d2f7cbca9ffc", "TIME_PERMIT": "041b450386196b2c5d5182463a85417ad4e41adfd35b7cf62867f20e0bd450c9d018e625cd29bc44a435389fdbc1d7373945f6ad66cd1bd4e16bb2aad0ae897825", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33385a222c2022757365724944223a20223662623534326432646236313635663932336331326332623563663439336664406365727469766f782e636f6d222c202273616c74223a20223665333161383062363566353237386563653836643435356338653763646434227d", "TOKEN": "041d476b9beeaec8b23d75b528152ca22f290f5f63ad483f41cefff3876ae39b0f1f177445db46f943d2f03a0cdd3f95e8fb817f7f706e85667218461d87f7afb2", "U": "04099f94e2f36f4d44c8963a7d1323b2f5fee28cb8d9c5e04b992bae589941ecfc1b8f0a432a3a0ad96ff172b080566b9a6879ec036661ecc8c2a0fb87c032d73c", "SERVER_OUTPUT": 0, "V": "040a0d71d43108e326816aa582a742d8d3f1bb42a6398036f378081271c2501bcd003b890bbd78cc65a3f53b84b1e61856ee4f1982220edd6f47075632e67f863f", "Y": "1205660fec20886f2c8435538daa60476cd03862e44393eaeece28bcb3c10aa6", "X": "041209f198dc2adc7dbb7a049e4db0b12951f67f5727ddaac30e2820fc076408", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:38Z\", \"userID\": \"6bb542d2db6165f923c12c2b5cf493fd@certivox.com\", \"salt\": \"6e31a80b65f5278ece86d455c8e7cdd4\"}", "test_no": 43, "UT": "04048cfe10789e17aa10d9960ab98d4263706f79c7ebf6ee6ccd6c14cd6b6fe1e5008a24a8e934a2c19afe3deb9e37523d8beb0c3a4803ea5dc3faf5916cb71104", "MS2": "1138de1a55fed269486b3e667ab16eae66e979e52650dd5572ec4508150c14af", "MS1": "0bf734c364d3dd681443f2443c50e0ddf87a887de6f80fb4a6dd1dc4e1610511", "CLIENT_SECRET": "04050f1fc7f146fc37219e12d8c2c5a5c5a00f7d509a50a4aeac3e3bc2dac18d641a44859221c71bb12367fa65b124a7bdaad03c71430668e06464119465344711"}, {"SS1": "23116d7cc1a6f32f8726c8031925e0d9303ee2a0c6b3bba4f72af6d2864773d70a2187b01bed8708b8c149b27261e5098937c79e2a4e19102f9e38a6f92bf5c01218dd47d8d95f70711bd045618ace3a069034633e5c5686424c4c6deba6d4d2163178bc0f690eb5205378d678767d93c5f5a8c878be7d6ea756489db4fdea58", "SS2": "20e42e68e29dea4943fe228e26d1aed77dfa5b7a6cd508d099f9e3d92ccff9ab04ac4b1b1fc972d2d8250489b131b69b6d62a830c1d8a7299a361cae364b05eb20619624ba86c59621ec2471464a8816cf195dd0f07ac95b13f086fb9fb2fff10be9614e306ba8f2db626f8c61ddde31adc08f5140ccc5c23c50761807ff39e3", "DATE": 16574, "PIN2": 3487, "PIN1": 3487, "SERVER_SECRET": "1ac5839c75280ffdd5b1a843fcc46f5fac0af8757dc6ea205f2789efe2e51ca711c51985ae6741bd7d26a976bf9bb18e2d4c1dd7f27696712f1c0cb0171c544a19b4f6ac49408e60839bb910d013b17d6a8d8804f287fd3eee4d9d2a23547d881527617359a3f71cfed6c75e4edf9c3a39bb59b699a80ce41bd7f2ebe21372d7", "SEC": "0420bbd1579b5a992b13acd37203f995825403cabf7aa4d58d55268e26ab6cb2710311df5c470c20e3fa7a4e4a5db1d2eeb170725ad31c72a4dffcc17443e6c937", "TP2": "040a00ecc5455bc5c7d693a56a5c0ff6b30dad5847b859dca72fa11713b0de140a203e470076528539431a31f3a302dc0b600bdbc05ff95b7c6b1be9897a255bf9", "TP1": "0421d219dcfa8b466480855a494b40b807ad330a629eca89b7a4f5115ae6f5ee6805651cb0fd7a9731ea33e0110e10836054ca026e776704b93696439a4ebe718b", "CS1": "0416b17a8f99a1587253ed7c2478a9ada70e49c5255671577ea66feececb249d131f05b412dea681c882f7dd7f96e98dbca8cf09623fe20489b3c4398bae578dcd", "CS2": "0421e23ca925d1e29ecd8bc6bb4e2878b4296c45290cba9fe7bd43b579b41829d810b1210ceac68e6699d63706c2a7dae5c97a19bfb1ee67879afa49ad65d07db9", "HASH_MPIN_ID_HEX": "ba6874db956ecbbc7e99b321670aa3d9d43995f37eeeb2467b4e2524b4ed1f36", "TIME_PERMIT": "0413f246ff0c9ad772c4a2cb928bef03dfdd2f4a25575732b8413c2f9c350d40750730f58f24dd6c255fa5fcdf394d0ede41c94c7e681bdcfc308b8025c5bfa49c", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33385a222c2022757365724944223a20226164376337356238356230623232666264386538346665653235303438663264406365727469766f782e636f6d222c202273616c74223a20223936616134313966663239663663653163633534616565663936613963316165227d", "TOKEN": "040b215c6e018717e8360da151354022f73f0d3af3da0b43278aa7d9af3c6730d0071e32f5b5bb372cc8a0ac4b46172aed300ed8ed474c55e23682f41d528de977", "U": "0420e95e52cef59125e967417395366523d2b405f48984ed6253a3ec9eb96fda1b1fa6ac1bb9c08bcd846a4d3d139961890e0f2a79446c0c698fb28ff4511d1012", "SERVER_OUTPUT": 0, "V": "042338926f63840780911b6778d4a749d1848993dbcefd031a10baf492450b0742072936a7a2eac3ea88bd4887116c2509a27b447309465f6a00f9c75484268e40", "Y": "14f869ed6dcd8b82dacf0521b3a1d292bf09331fe330aa1dd3b48eb2de6e041b", "X": "02bc8ef0742cfe756e9cbad804922c08f4a56077075f33247ec27c511fc67d74", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:38Z\", \"userID\": \"ad7c75b85b0b22fbd8e84fee25048f2d@certivox.com\", \"salt\": \"96aa419ff29f6ce1cc54aeef96a9c1ae\"}", "test_no": 44, "UT": "040fbdfb17e9c06242302957e4b48909a8b5e763341d391a0938ea431117895e9815a0c872313f38382f8d4772dd3c95c2b314d90a0cccb3824aed2d52e01c611f", "MS2": "0df6fa1fcd1d07fcc35085cb11657110b41949fecf766ae868fdb967b1c40c79", "MS1": "1c1243284f458352257871cac3d14e1598aff9f28019535c3dd30971dc3cb509", "CLIENT_SECRET": "040c2b7f618681203f317501b04cc1b7c278c617ce5ae355a77c960394644158ab08e1661e41c16820dd82d63db8f61c61e606f6868046ba7fbf6d1a9fa69a0384"}, {"SS1": "177aac829d24fa6e578a8de3d91abd07f4b9b2ae3127107d2ca8a0562b5248bb00b227291ed11a2ce97cf27ba703a568667dc918cfb35879d6e68d242aacf1f5238bd983d350e9ddbee79a35eb431074776bf5d5dba00990269b168b301a71b4053838352307636f1b03f87f5bc7f707503d961cd7b9292ef150f0a0b916a934", "SS2": "118f148415170414cbd4d4818606c12d41c7229bffcd34091f83c0472aa58f5800ea75717569ce7b3ce40061fd1cb93a48b71a217c806316ff8efda10ce7181b1676602153c3eb2eb6ee5388090ad1204d3e38ee0c7cb4cab2984f92f30f06970b9e5d445a4d9d863afffd338fe76c2deb9211a64d2014b616438cad01ad6697", "DATE": 16574, "PIN2": 6448, "PIN1": 6448, "SERVER_SECRET": "210cf56caed4ec7856797351c79199461f8931da2301f5e1c306165436e147a4139cd42dc0d41d338d7b360ad1cdd5d4bd7066a59d7f73bea8381f7e2e4dc93d117cfda749e7a832e044fa58eab7ec76ec1c3405346b2f091285977b7325d3541cfb8fcf40ced4a1be6e40699448d2cc362414fea834a11d9ee6ecf6db37ef60", "SEC": "0419dcbd4a0ef5255045fcf21a0408c49afd9f35a8b22a2dcdeb411569b0d0fa31224d1731279531d7d2e32b8e2270756ec71d524aeaf7d2a59e99352d993573f8", "TP2": "041ca6695091b7c75b8508c602968fb52bdc735a89ec8d078bfd1b11e07829652013656f7fb08949ede70dd0f7e8952f3a45d6ccdfe5c79afac9b461486e3e1ee2", "TP1": "0420041417f1121802e9d523adc64d70ab538450e4b22f22daa1fb13e9ed87afc209b77f8e48ec7a9c39935328e28639e77afce082523da8d23d23a1039487985e", "CS1": "0409609a407352e7ba92b36f7f914c2163e3366547e8ad0cd28769938d86dd7dc21380ebb8a61764d46589151f6f8e5d46f6d5c925aaeaaf9b06d3497c192be1f1", "CS2": "0423445ececdd189b235480ba2286b5aa17a8d23a09a418782e99f3c402db3c78e229507c5bb4e36017e3c6c048a74f04c29897b8c7c25670954524c6c3119efc8", "HASH_MPIN_ID_HEX": "8657a344024df40b9ca122bcecb70387e3ed394b9b7a2dee130a08709d69768a", "TIME_PERMIT": "0420b0b0d34ec3a2df7c839dd1024b5df2ccad963ef27beb878880005c1b01d246116173913299d48b7a071d64b3ac73979b7bd363f67a3533d09b91dbb099724d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33385a222c2022757365724944223a20223934366531323533646264633133666133373539366633343639626562623261406365727469766f782e636f6d222c202273616c74223a20223533383130306566326462393638646261313464343731303033333566373636227d", "TOKEN": "041353d08a873ad762d45f030d55e799909b82aa33905cd901752ddc9bc1b881860d6ed791c4964e5db4b9ddb07709cc25fefaa78aa826106b11524c148d5df69a", "U": "040d0414b4ef038a471155a704ce83a2f8a6b1ae3171aae02004980efd02c105bf23a6f221a199e610a157d7263db90261308a0aa678aa6142192ffc00cc2f5d86", "SERVER_OUTPUT": 0, "V": "0413c9ac643580fb77baf3d6b4d96695fa4e2808aaeb2afbe3d8519684127992660031e149dfca5c83611f90834c938911d162aaeb4591e34db4a1599bfd84ec1b", "Y": "0c795d1c27d6c143c8b57cfaf7035264307ea084994af621694d08ecf0b057f2", "X": "1fd47331cc24daf7c29b7d17be6c063d840956af0333c85a52680fac1bef577d", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:38Z\", \"userID\": \"946e1253dbdc13fa37596f3469bebb2a@certivox.com\", \"salt\": \"538100ef2db968dba14d47100335f766\"}", "test_no": 45, "UT": "040912ff028b17069162921788e65d17f89e454d8cf0d7ae077534d711d92d9e5f018e1c9dd4739239197e96441d25b6721eaf994392d595062c4cecf8a9278933", "MS2": "17b15686223d70aab9798aa1aab7824dc3212489be33a56c3133f92f209a86b1", "MS1": "1b3a6f03470220c9dbd75e15293ca8103a4d91e963a69ddfd1b012734b723fa0", "CLIENT_SECRET": "04022a40e1a97362d26c3c1092f67c332e1afcd0f10433b07d9726d19cbc02f234058bcb905aa4faa8aee8fd5f14fc8c872ed801ab30aa6b82852377860f6663c9"}, {"SS1": "0c6768d51c5158109d31a9baa4d6ade11a76b1364f7006891d4c771bdbcf9ea8061056ef9799deaec4903d3dd23fff3a9ec5909bd86396b3d30fda369adb63d21100abb3109b7e9f43ae10b014ce1f149c91a0d82c77494bb9e3a9893c02705d0f3fb570dc269eda1daff5fc2192f99f5aecf06e1663659ed00accbccf7eba79", "SS2": "0d4ab3c8716dcbdabba40483950bf49f126098e2ef21d72f6a59edfb633615d10d31e28d43d09a0ea88487d01e11a55e067e265f41d2851f5ba2c4abb6af02fd0d4988f8c50be76b1876f5d7dbdeb1d0275642a1273f7d09579de3f9bc3d028a1641ca845e2f29a7f850f495b52b607bdea21b298153fa36af41cf44e48540d5", "DATE": 16574, "PIN2": 5779, "PIN1": 5779, "SERVER_SECRET": "0d8b13d4e339f2dd824f7c4d0378822706d6786730e6c44cb0c15aca894c6469188ee327a5bb3bc1854ae1387e03002b5fe31ac0a5f52cc613e1ec541636b15308f80ad7e1654c15cb168ebc5d5ae08a52f96700e0a43c004c448e54fc513ea21b2c048b22e52535b7c90706b9e597e34000255998e549aecbc7524be59a2933", "SEC": "04152cd0add58db7354d67c4d9e42f77fda55848966df8f8e276c243c9507f3ac70be25dfd85c06c11c8a6f36b4bcf40d2418632b2893cdbdb9928f97b01ed2417", "TP2": "040d8bd0006e9ef735c59dd9bd3c1a2bfb75c434994953c7df67a7a53e45f3f63a22c86f4db33dc226aba37d3f8443e6e53a4a3f599a68c3f3bcf0a3fd788e5b2a", "TP1": "040dba35b41544f9d6383f4b6af6c86fcc18691f37ea2ddd9ac31c236443b8cc3223f65da3f6dbf376a654fd7ab68d127da135ae837af9030f26b2b6ce275650d5", "CS1": "040e75e962353adbf3384a687fcae8cd395f1e955ecc172123afa8d9af1d6befad09b6208d54ed84103ffb3fdca0e610135c0d0d38a78145757ed96ad5c55d4c4d", "CS2": "04216c2bed79a9fc00582908120917e28d83c13451592c15c25e5c634243bdcdcb1068b33d11885ac2336282b94bf0d9e56a4a44fd97028c0b7cc8e449b9eb51d7", "HASH_MPIN_ID_HEX": "f8780c2d906914f463800552a7894cd7ee0ca0a56feafd4b171c1af0c4b93d07", "TIME_PERMIT": "041fe9478f3366c56e5efe4245e06c6ff3914bbc872a0fa62b191b2324cd440a2c1177ebf59896fcb4940cdb96b591a6af723ac31a5393410f0d0ec7582cf6dd21", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33385a222c2022757365724944223a20226333323162303631303437376666666137313766643635363462643633646437406365727469766f782e636f6d222c202273616c74223a20226462343364613937353437666466616230303835303437616666626362626366227d", "TOKEN": "040c3eeee62310d6dfaa9f6d6b0020935fe15ccc33b19e165eda82eff78ab12283037d2c7f9af7365158ae454353427c7c06543d087b1d261da5aff0bbe2a422f3", "U": "040a950f608ecb6fd6828addad96fee025fb4088fc7b4f37751cecd6f3407024f41ffb988d91d951985b81ff83abc26a4c1da5f67e627b52b2baf52157a69f12f1", "SERVER_OUTPUT": 0, "V": "04116ec3de8c6eaec3cbcee9e4ad34f9955b8fbe9b3f8cf544b1776662a66a368210e1d6e5135e65e31639703f72e8630e7e1d06690da87ad08dbe5f56f0b2f5c9", "Y": "1f0f6707c8e591068b92147af5acae30f34376aaef67e2394213ba78eae537cb", "X": "0b8b87092e06e586ad473dc0b1576c0c984da32b6fd294de551a2e85e267bbb9", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:38Z\", \"userID\": \"c321b0610477fffa717fd6564bd63dd7@certivox.com\", \"salt\": \"db43da97547fdfab0085047affbcbbcf\"}", "test_no": 46, "UT": "0400ffe1db808625133ec4ec681d95094fdb144833d25d3db07ee9f48da6d910a81db91aa2931470f2d58688c6f8979161004ff327939d31c2dc7183f845b3807f", "MS2": "07f322cdbe9622198757cb42e065d9655bce664ea15645345b22df93a7de25f3", "MS1": "176d4524ee6bf7858ec812d28635b5b024a1cab8ce1bf7dbba440094e06eb35c", "CLIENT_SECRET": "04023fc3cc5ee9e968ea85552c76bd48ff06e99d06da157e39ee432341f5e4f4830df3d340139a2b7b38d59e9ef6fee69c15c59f4048faa1b634bba340040136ee"}, {"SS1": "0a1443c4f41dfb6dacf6c59166991cca10dcf42713a0a1c9d331bb50e80a783b23c9808d696e713477ad8454c2c58c3c24a9179039257d4ff4c2dd3f281f06cd1228365971c50c379444186fc93acc84e4a9598e6acecdf976ae71bad52f083317f79ab75e135d0f2130d51a2f17a627b0c95ef68a57a25bc0067930c9f1d824", "SS2": "0dd35674ba9b58a885c573d52333eafba1cae32bcba4a2d6aa1e4ca0b9154ab8141b24d2ebc94455d1624727e03882a44f369b3140d0f2f109acaac5f7b2209a055403ace74760fe9908ee23dc39ddc703239a8ee89c519e0986b22d61d1da74143d7ea31c759eefd88bbfc9b453704d80e7b8bb1ccd6321447784a21aa1e788", "DATE": 16574, "PIN2": 4307, "PIN1": 4307, "SERVER_SECRET": "21dce950941f589369627b1aa450f8e21e06b8221d11cee58aa57d519c6b5fbe1032edba8cd2d57d43b12d3dfe02eee24bec22647f34391731be66197a4606671eedc1366b4cd8e245411fd66398fa646e65f3d75d6982a6992133f52df4d12109154afd41f94bf38a4b305b72482166827db96e6198f775f8889fc9125807d7", "SEC": "040f703a345b59b5a96cd6a6cb9d25d7e06596dc1e04160af23ef2ff96950b7f221b10f62511450b6bc095f26764fa84e96f4cd5ee270a04a846f9b55f37ec14d5", "TP2": "040640f0e94541c51df1465f26f0883ed0ce879731dd9fe50dadcba37d3436a256177502a88ba02bd91fcbf1243e214b6cf7c31c08859e0ae18564cb6a783d628b", "TP1": "041d425bff74a17aebdf9a4e8b5862e01f09466e6ce409c6e512b971451263fb651b4fc15258a5714e6ff44c07c4d3ebb930293f7027df2eb9c4ba1e303f407d5a", "CS1": "040c128d579fd175a88da8f69c5a43a1ce6d1c344de291ee3eea146bf1673ef2e200430726e0268bf72fef93c121ba2d0844b362547265f77541cc98a155b1c60a", "CS2": "040f2b7e2f8276475bef49febb28016a5a043a0d1bc3c1d9f7b89d60375e102462239521b6c41388a48bdf7335d96e55f9d834f4c800565cf68d35006eeae38b0c", "HASH_MPIN_ID_HEX": "9e3d2525923c661c5d524a4e9b34ef00a453288e1dab1fb1edfae6ef2a9f8ddd", "TIME_PERMIT": "041ded1c6daf72b558324867bbf81ff8a03a0758a88645c75355c531cf17c6b033140be2fd52fa94a9d7947434b706bea46069a57187f97a4a0215c210554f3adf", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33385a222c2022757365724944223a20223765313362313432666238316436616433663932306431313966333461383965406365727469766f782e636f6d222c202273616c74223a20223439306462653135663934666235653966343536396334393134653632366130227d", "TOKEN": "041620cf931bdc617b8b51325c9b2d1e8e2f9b12857376af017c53062c38d840860a4856b19d373c85b24d0f1a5765296d61195414072ac2c3d16c51ac81bb79b0", "U": "04130c5a5e5d1fb8ec9c20b5cb389a2ba0684c2bbfc5780d93d91ad7e37c84718a0de7f9840710cdc7755e394d3f53c4b558a4c197b20365b23a061e5ccf35d7bd", "SERVER_OUTPUT": 0, "V": "040acb1871a583db9412f06820fef10bfdc6ef55745f13a0bfa20e79b4ba39740712cee65b98b9c677f906844b4f805d7637f4b7e4d5d30043dc9355c3e2d49894", "Y": "196693e241ff8e6db3696c5fe2b81c752604a9cfb6b2f1e453fe5662764fab01", "X": "0b5b79cbeff4b5c70eadfe26a49c95321f99ffc0b37e31cace7b4e4ecdb50562", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:38Z\", \"userID\": \"7e13b142fb81d6ad3f920d119f34a89e@certivox.com\", \"salt\": \"490dbe15f94fb5e9f4569c4914e626a0\"}", "test_no": 47, "UT": "0412fadea208f8d50c9c3dbe2197303752f31be95b8704bdad8d899ee92c0a913e00455a76d1918c59c1f9a4e2e0d733188291579cc2825c7e08f43384ceab63c7", "MS2": "134f9906977dd413c890075e2f463a46077c9b6482171ac7893d59afa6c949bd", "MS1": "10dd26c48f12d11b4fe7da8e6fc2387163a6a02f4e38f07a4a9a57fcbec09ca7", "CLIENT_SECRET": "041948479111a6bf79ce124ac170d418fc710cb330d6a4c68459551aaf21eda912046296fb62454f9dc47cc99a316402c256686bc336bf23825329fadc1d467b9d"}, {"SS1": "1d3ae8fb7d36214641941a358f5a9e470c7e3e41932fcdff67457a9324744cd1151e48815d64ebacdacfdb27d9389e8010cbb8521a1fe828fbca3cc27fc2a5df1855d1fb11ba3c31604599b8a47dc719d5dc1e5f35235977e34bbce464fd793409675b9163ed171100e8910dd1c60ee228f6f7f57280a56daa032e8fccae1e11", "SS2": "19c23daf668009ed366e81bc0dde81693d27d823749822e674a396ca82babb2a12a317272a41893ed7352c75fbb79a3889e270b2dd258f0758d653ebf0e84622220f5d422203d503c2b8076eec871c710811a638ac442a4bb769d4d6d755b4421ce0ebe4f71c04cf67a9ad828faede828309da1aad2f5519229461bc7751481c", "DATE": 16574, "PIN2": 4758, "PIN1": 4758, "SERVER_SECRET": "0bf6e5486737ec8d7d72dec4bfa870282b7ab9472b0d05ee43d8dec4ea280d3a176b0831187170a7458a1575f4489438470889a9cb12cdb62d21278e182c03fc1915b099a0821fba57b8e2204afe1c126d765d82a9748984efb358e33cb0449404c5fe636c403672380532f1f8d242acc6e216325b7bed66f34087736c6515dd", "SEC": "0404d82823b4783eaf2219064d2ff8fa9878c315a53574daddcf48beb0b797c542156793a696612f6a04c9276638dc3e62dd5ec88ea4d1f112c0e16e1fb6ae4593", "TP2": "0401247b1da9c13a7e0122b9d8c0b89fa70a413291c7488beed5d428993044dd45131664531aaa50e8e1233f305b2f30e1c7a912afab68f5e0a87105fedcb9ab09", "TP1": "040a595f1b4795782d02063120c40d6b69626facf7b94b516adf46c8759e198bd41e351a9cf758d172997bef58f6f517288e08e2235e533f1833e8c981e90bc396", "CS1": "041baf22372abe3bed7d6e85dede7e6319c9173924f43e6903abd0f704e7b9accc1e6822f869cf1cb572671ac821dde744b00c3476926bef03da7a704d8655dc80", "CS2": "0422a527f1e245ae8818ce75c9f008328945bb46a5068f24ebef68a0f8ccbac31518a1eb0acf7338fe5e61af9bae27e9f820e0a30699f1d36b2085a5dce3b2e31e", "HASH_MPIN_ID_HEX": "a630ccc25fa4ab0c568c1182e35c4c955949c884b800443e89bdf6dc1759e880", "TIME_PERMIT": "0403399fc2bdf27684ca52e5ca9d3771d606b6088b7bf6ad2ecead2ba9e7a26d8a1cabd530caaf1b9b1efbbd813f3ca18ff1b5a0f0191be1ed6e72de07b6c531e8", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33385a222c2022757365724944223a20223135383831373661666430393139396233643462313634386661383739353138406365727469766f782e636f6d222c202273616c74223a20223939303165313962386533333132313130656339376636316634643939313564227d", "TOKEN": "041661a2132040b68797ad42d268f7a6393333ab6b04f111b5fa905922c968996f06e267af5cf07fa46ee44d1bcc00efe515c517a1b690763fc10854489e10e110", "U": "04035e1381212bc53f6e4318647cc9ca7604ef8e86cad0181d9de91819c4d3e02514e3f372ecfb4b0bb573a2ca85acae75a6755213f3a3fb65ec123d9a7b5caf1b", "SERVER_OUTPUT": 0, "V": "0419a0382638ea37e7f584d408b19e0b5dfbc5f2cda587d72c97987e54fdb4d2640ea2d204dcac0f65cece5c2823d93c419c6f71782f2f8fceddd0540359db7dcc", "Y": "068ec7610d18fc11857d8473cd6cd3ac79efeeef532af7c7c351052a7356f9dc", "X": "1096ec3ed98e1f3a1e48a48472a25e56a55d3f6fc82a14fe276e148cd44dff4b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:38Z\", \"userID\": \"1588176afd09199b3d4b1648fa879518@certivox.com\", \"salt\": \"9901e19b8e3312110ec97f61f4d9915d\"}", "test_no": 48, "UT": "0407324c7770181cc6e03aed9ea4f8fcc801cdf3026b528b6e8e5c8f39d748972f17dfa77a30acc646caab4787b3e0e9a07e231588ccb46014c557100469a2def1", "MS2": "0cd811b35463cfef930554195ff122b28746203f506b18ec4d6f5fc2cadd56a5", "MS1": "16848fa5d7c563cfa6ca46e922eb3e561492f4407bfa41e601f10c61bc57b5e7", "CLIENT_SECRET": "041e272a5929543e70f0f618d7d96936eca0dab9e6d2fca96df31a81263066e108199c991fd85092cc62131dc5e9dbd0c5320c63970820ec141c611225321e4bab"}, {"SS1": "1ddf77b427521f957afcb68636c3e2665e643f200db2212d291b17c61c3391431b985908c113daf7bb0890669357c0581760cca28b8716d03dd5787fa4bf385107d3d512ba610efa0764c77151540c8b87e4ea5149ae2d09deb309cf4189d1231a022300a9bcc38a209ab68abc14fc5eb622c263a9f52d91e6deb5c76a512d52", "SS2": "142c26945ea314b22fd084f63f2793e829f05308e7ebe45bc370a87a9689e01909865183bb82a1b204e1ea2b4e4f28b8478a8e713194e75111a70f77a1d651f01e89a220f932bc87635e6f0df8af02fec40812710eb6f0b28ef1907ac427e8fc08827e7e97c66b7fcc9f8d49058335fc05a67a78822c36a63f552013b1ab3861", "DATE": 16574, "PIN2": 469, "PIN1": 469, "SERVER_SECRET": "1f56158313653247ce2a834039193a6ecfaa17abc09ba2cd0c9c25694c16fa7217d1889a17c5b10018ea0e676e8f855ed864f575c0e3aa93c5962ff6de4ca23117181023ec8ad4a49edfacb36dc3a700548a184a989dcea327d8b52a609e4c0c0a07610243c7b948c75a588e8f7159b72c9877561b1323f21f5de6453844a838", "SEC": "04026aebd9d21fa4dc0af091892a381fa1f9e29f79dcb644312edf920c428d843901446ab3264cfa5d19d6ee04fdbc491f5c55862fd3513df4def09d0faae92958", "TP2": "041032514ab1d659ffc12679113dc8ed0751e2a39d830add347ea7b5045a943090170078cc63cf0872dcd2600dac6d8a578d288e41a8ae9ecff37fe8e132bcf8f5", "TP1": "04117e77d8fe76a485d69007f3d92be8ddbb3f80569647c531da403d65d46ecdeb056653f2015a204248b8f1b5cbb1427f1d024332e0d0124527cc1d2709453f1e", "CS1": "040804e0981da57b8eba8902be87f2f8392654c142ae820f00335a7fbfe288c9961f88eebd981ff3b6a636686733708bbbc7a2378f3a91d74ea37b1e5608f39f67", "CS2": "04180313fcb800d2fbe582427f43d8017137d658d80b0930bcb4c5acc716ad74062061b3ebe647bffa84ff2c2713530b4820d03934580a3ed062dba088a54f187f", "HASH_MPIN_ID_HEX": "b014ed2387f3a77bda35cd404307bfd393ff096a7dd80a76efe7e78770166a93", "TIME_PERMIT": "040f2b83afa41d6531c73d8ef560fc230663ef6e0c163111bf0c3b4209d981137101dc5c6fd14224a65b9788470bb7dd701e900f64f52788b00fde7e9b3dab0daf", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33385a222c2022757365724944223a20223938343062303365323831613336316432643966653462306431336331303866406365727469766f782e636f6d222c202273616c74223a20223065613238653436383161373934636263323734643333653865663232613032227d", "TOKEN": "0408e6dfda3bbd4c7b342554e14e3c94ad486b819a77640c5d81d871f2c50167fc196c601088648a9f43dc6efb5621d5d96178ec15bd2a5361fe11b462086c6a5c", "U": "041d3371dc55dc12f7456a109d1fc21707b82c7f30f6ecc6d5ffb849237524ba321d4ec63e33b5569e182d6eceda6474d660cb995b6a99ee720e190e52a37e0340", "SERVER_OUTPUT": 0, "V": "04131046b8d835c1663b29abc4ca6a16cc5238ef1f145b2dad6438ad1de48d63f800154cee4de581a6cc068fc05bce10b97e40c62edfc51b68cec82db1cbaa3dfa", "Y": "0b3af42232610877112cab318612f844ee342f80e563d1a85b603b4727857430", "X": "0cf53673c81edcee51c3aa6940c4ca3d48d8b93d3a51598ab858aa5c8e7b1b7d", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:38Z\", \"userID\": \"9840b03e281a361d2d9fe4b0d13c108f@certivox.com\", \"salt\": \"0ea28e4681a794cbc274d33e8ef22a02\"}", "test_no": 49, "UT": "041691ebc79c47b0d91736d438c867bd8b8ced3e8d521b5aeea52034f98397aaf318c342935ee0fa3dd38c83862237c75f54cbe97688c98edbe20022c974376cdc", "MS2": "10814086f6ea2839cf92e88b7270ec1f09008c0fdd3c71a15db27b03aa5caf02", "MS1": "04e961372cd0307a6f7cdf35eb1b7baea02abb8b47df3870264f63618e03187d", "CLIENT_SECRET": "0406bb2f131855bb6e305faae70cbe497ad9c80d903250b04452352bc497bfa7511c729878bbac80b171f3b991bdb97ee7d462fbdce75bb02d39ceefa52de88c3f"}, {"SS1": "1d4ddd8a4332180ef10c29165d87ae62b6548fe552456a75c9dcb596ad5e5d8315a433c4fe74d9d71e92e50462573831a207a97f4f698b46f86a8fa6ecec5d94161f65196ea8eccea05691d72b42e70e0d09c7bdd45bda9a10977775f160d59716401fea50ef6db7edef1bfce1c245b4907aba40b5a85ce0b36451d13aff9a48", "SS2": "1e7b034652c2168dbc3221ded32154e1c0fe52d8cc4a948576930ec05e292106023a7b06907ea0c5c07e2c961093014d8888a1569d2eea77aaccde19fb5221fa0c2a531c2f1f1697d8ff7821609d75a8623068b7982b03d936bacb08f35ffa75103f9ff70555f3df058e02546bc466a6df8562560de8a814127cf940608407e8", "DATE": 16574, "PIN2": 3497, "PIN1": 3497, "SERVER_SECRET": "0c297655228addd008000a3fc1cfa222e5b0789ef4c9c2cb11017435eb33a8d1179ca81e09deafa2b409d754a172c486d0adc024b6cd6515423f0e7fbaef63840d8ce83708c7a4ad4209c863e0ea4316ea887fbb888c0cebb1fe5d5d3db61ad51542394f33b371fe49daacf826caedf128c490b28df37caa2682d93f294a2e70", "SEC": "041d1ce99f9c75a11314783a065cb50648fdb2484379995e3151eb9cfc474320661e8a2c10d8c24d95138c8f668cd631300beaab515d42f9852bed44585edd1cfb", "TP2": "041ac81d8c09bc6b61d927b8a6eaae2d3977cb381345dc9a6849f677cfefcc73b216042320bf5b86b1ee4d6ed323159120d0706da46117390df4b92fac3ff3dfd3", "TP1": "041df296f867ce2a80ebf8bcfd36b8eeba7b5ae3eb0642ff889367adf07af995121a4138f6d158f83c934259bcab51c1dd2dad5f533515a5acb90350610790bffc", "CS1": "04077bb3c3bdae0ae253c9c4539387a3badc266e2c6d44e4f76b1a321c3afb9e69037b9ba65304c6585de2cbe4ebe23e9ba1f33ba8c5394eb68e65c4ac8ae4eefb", "CS2": "041ac819d9a54594dd18b8e7492ffe27aaf71aacabb8d97c2c3a12bb573a8ba7b50bec6b5f30d937e4f349e1c55efe5af8adc2354c4033cad38b663e5b03e51f81", "HASH_MPIN_ID_HEX": "b6358fb8af8a0ef9af994c0176e836ea402de2b4f79e767f1148a64c87945cab", "TIME_PERMIT": "04178856d43f84fe9131898719253973172742837230526c5acb6c16b584ef0ee7002c467a6547d41ae577f4d14199be28833e67e8fcd015a60003f96a49bc56e8", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33385a222c2022757365724944223a20223865336435636537363430313037383234333039626339646339653539623737406365727469766f782e636f6d222c202273616c74223a20223063356531306465336430323036336436373232346334313666383836633530227d", "TOKEN": "0417f6818048ffafd991b916c03214d98ece7b9a3fbca4c8055f1f0f3ef35380cf12d7b3d3d88c8466fa999c46599b354ed19c93190bef28c8c09c10e25f982a7f", "U": "041d4f2078440d79ab342e83d8adcc1d8c75d802ef9c13ace8e015b6f0cbc5eb7602a28b60dd8d270c5bd28595267a399fed42b69fea1d8605445a294ec3a543e2", "SERVER_OUTPUT": 0, "V": "04034a76ab692a7dfb157a266d293c8c27a493e2410712feaff7e958b61195938212b39610534dd5fa7df0cbf88beec099ba7b6fd55ef821cde877ef702e9f184f", "Y": "01fa852348559505fd59bf4c1f396ed4c4d226caa6931508e6aa443337b661a8", "X": "110cf640978493d5eec05e0d63d20716b321ceecaad81abbffbbca1becaf732f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:38Z\", \"userID\": \"8e3d5ce7640107824309bc9dc9e59b77@certivox.com\", \"salt\": \"0c5e10de3d02063d67224c416f886c50\"}", "test_no": 50, "UT": "0414529a26f4bef740cfb2388bf0d8a4de55cc99fed11878bf026513471e3e66c90b2de4c5eac072f61fa72b159d291b3b0b1aa77bf78e1fd45083194a6d4507d4", "MS2": "23349daeb7e762ee26e2375325b2501530abaf826008c75512e710d0686e7622", "MS1": "21350b4d17b9fa0799f5b5b43285e0ce14c3af1b378db3c6c3c8d706482b233a", "CLIENT_SECRET": "0404d8b525fef496f634aed76d47cdc281ff6c77831c3a318558c15dfd957aa98e04523314f6fee443847861c9aaac8e808d7c851b61bf6044850718af04da05b7"}, {"SS1": "13c2e43514e32c1906d74c35c0fcfa4dc042d7348fb349a62db97e23fc9f195d026e808280cf19b2b6d53e5781a4e9e07e91f05cbacc386445b5df61b5997d341af258c9e5d2eacb7f7770047bf5eb21b92db52f81c624634686717290164ec3232bfdc47ffb58a54fd3b1fbc8f6b8c21844c73fda90a7421e019d2f71856325", "SS2": "04d947c86aa00be10545ed97cf03685852bd2851f96b2b8fa5fe80606df17af315e6b563bd81ef356805c4899811307d57da03a61955eed3d1212a041a206b4a032201b256247388b0fd0b0e40bdfe98e63ac8496dad229b1dfb32abde0cfae70cfd906ef58854fb2574b30ddd62b92c049b7488edfb49521d4a9a4d365d78f6", "DATE": 16574, "PIN2": 4694, "PIN1": 4694, "SERVER_SECRET": "1d230e25c52006b8dfc6e83395b4a87c496d94614dab770dd8c057abb06096fc1a76f030306ea31d18ae0679b87c45260acb9aff784316dd92d2f0e55dba371b0ca78f6df3ef8de376c69ea825a8b65dc51ec2c1347d5b192170dc0e4031ae5010e98cc3e95bb13fc708b4ef751fd95ef15d946aff0340b26837227f7b888f9a", "SEC": "04023ccf01acca018c127fa527bf19909e008dbe2a0c10f804b8ef40965b89afc308e7cb8a384ef455ca50513f77abb33c853233ede4eca3f3a8ede7b235a2cb7b", "TP2": "040bb02f6629b79e6d3aa97ae9fddabc7e38d80ccc39c8c028178b3b1bba05c48b0e78df36834be20b16c92e7205ebf45391054bd2a062598eed41af28f505d448", "TP1": "040625504b2fb878bb954567382e23c6d224c51c6ffea512cb32563fe64c143e4309524b17cc03dc4ad88d6854edde705111ddae967cc12f7c0283f5253f5e8a0b", "CS1": "041b980f94cc78af866f9235676ba1d8e1288cd8f1f3e4f54ae78e2fbcbd35fa520be9c3e1978a06e68e4f6b5179e6bcef783c043d7138bc1fb2105f992e8a6d01", "CS2": "0422cd3c66289f4141e1d5c22146eeacde00c3dafd2329b9be417612f33c39d36f024786b9428feccbef6810f84247865f47cb091be809235c907d60a8c1b8b70a", "HASH_MPIN_ID_HEX": "a3d211c0421f61ff434d872d3d4f6f58dca33c3e24afc2334686c1c238296d37", "TIME_PERMIT": "0415fdc80cfb9e4b046d2270f264641878c9c7133e751dc00eb36e208953e3d5cf207136befa7d019bbe80dea963ffbdf1016d21f9851b579b4c5a2ae172417275", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33385a222c2022757365724944223a20226231643161323665383730353163313832633633306634613532663262373532406365727469766f782e636f6d222c202273616c74223a20223230653463633538613464623730643731336436636261623337353231353833227d", "TOKEN": "040086e9ed685bd57d73a589aedccc870b2c14459af91b1c1a12fa5cfffbb3019f1fb6f501c34061d085841ef8b585ad3fecce7a4bcc4e938b53c5a008db823282", "U": "04067963f2df332a4b028010b275a1336c4de6f1865e1586d99fdabcf04eb8b86d1d514db58d12a161d02d76f6fa801937628e144f789c00ec0cbe19eb235a3622", "SERVER_OUTPUT": 0, "V": "041acdf96d7484993aa39ef3d8ba94843f4fadb68f716818aa1edebf027d5193d60318150b7456d739d1b0dfeb4c55c0c77e10872ef60f6a8c2a87496e058cf50d", "Y": "11591203692b68687045f9305fd88a40e861aa5a8cc7f32aeec6cf680e8238d2", "X": "1f8b4260b7e64156b673a1c9dfce515ff1263fc07712a4e2434a84cfdfe6fbb2", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:38Z\", \"userID\": \"b1d1a26e87051c182c630f4a52f2b752@certivox.com\", \"salt\": \"20e4cc58a4db70d713d6cbab37521583\"}", "test_no": 51, "UT": "0422ea3af2002a1066ab314f6359a431fe7f20fcbbb48e4d5367ee9a56f799562417669532c51912713dfc958b8909ef3d0283e8a05050c9bda24f27a641489166", "MS2": "0beab5846ee39091dee358e8d40e5c87b57cae86bf6c5891b892534f4f667b25", "MS1": "2289251afcd56d714c30fee41789d759f27e4628030ded30db98ac8a533092f9", "CLIENT_SECRET": "04092eed6631f90691c322b3b54cbcf36942d3c3c986a2c8036953b3d587698c17001239e1e9f7d5f1ec9556cd75b5c0f2168c4e2b548d414ecd547fa2708a3c28"}, {"SS1": "129ec0b6f77289f510fd96ac0e9191ef1c79e3c7b76c23eb912a0b17cb0036381758022acba113b2df4b71ac92541f0b00061d2ef258d86b47244fbbafb70d590ccdf938b543d7f7763ef4430d717774e9cfc454b76186f80543d55afe2731e615bf45179f439132a098dee7a9086840f139088097f8b1b59b19f515599a23b5", "SS2": "0c12a7f7b7f1001e95b2e99c87593c5753ab17a0ead9a50a52f90446c7176b0514792bd2b5e8c3c96280db5abbdb6cc8bc286a36db51db761da45fdf8602b7c8185857f696776e4751530b0a34a1d9d197024fd65b9fcfd653c18aa5066177fb128f19a977f7ba2c76a8c842c6d92e7efcf5cb3b0fade658dacf125075dbfd03", "DATE": 16574, "PIN2": 8369, "PIN1": 8369, "SERVER_SECRET": "1748448d64e676a30bfbe89ef7b6cd27af59d89ec4ae7a688f656f388637aa94156e868cce7c480e2dfd60cff0420bad3df2274529c6d4eef274259ca7b9a6bd1ea25bbcbbf00d6fd560c487806b93d6dd8e75dfc769980bc90862d2eb20207203c680eb83ae0aaec7ca66849b2d030b7f7dc9f9737a6b61cdabe02254596556", "SEC": "041f29b850d3bad4d91ccb6c67f584dcd765649ee7e6e50b8452697141b9f27b4307cfbb8048342d1ebc5c390aa145b5c22f7b26714a3d16a245813077ec4cf8a8", "TP2": "0403263958b1578cc11f4e32bbda30d21599263e3741f0c5e4cd9040f1c4121b0d20dc68a439adcdcc2b3d01d1e126c3c13359a2dc267947dc1b7cdeac0169573f", "TP1": "0409d563970756792f932a13cfe84d3146ed8ec31f7571b34921bdd42fcee3ec4a0fa2cc150d70576b7b266f57785c5c86d3a3cf545061b13b0bd6decd3b99861f", "CS1": "041da61b610776791d60441b4520e598d9a8b60670c848ea4177bd7af76e9e70c90dde0d035f23f2080129c5250174f6be01a23f6e5af2bb450ab4c235f139852d", "CS2": "041540f58611633bf6c38c5231706c171dcc1ee94c862f141b9e6f6d6fc8c9cffe031b4b65abe395e831ac1f5d332118ce98c2ac81461c3510e163a8e2d741c8bd", "HASH_MPIN_ID_HEX": "1731f765e16a27554100663d6a896376203790879d16f6485a816acb927e5f9a", "TIME_PERMIT": "040aae00b65e1205dd90bd268d3b7252c36ed3ec68b39e553ebc262b23968346782278f3a07d1c89a4c6d975158b235fcd2832167fabc03b5b3d09b50a6b67400b", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33385a222c2022757365724944223a20223362396539326633343737313961653561306564653830376131336163663434406365727469766f782e636f6d222c202273616c74223a20226338633434666465323866653737633336326131353562663764346365623133227d", "TOKEN": "041780c6f85a70c3aff7cedb13d76661e7275478bd8efa4e1a2b2102daad3dce7c0c8d8cf3cccba314c735093e086da988e2339e9fedadb0c25344836905151d97", "U": "040b30cafcc8b9cf2b85b8a89354850341dfe8d295cd7b6455142334bb2051692b0628e16c7a1a8930c3d979e13205105bbba33e1d5d94ebdf79374069e206536d", "SERVER_OUTPUT": 0, "V": "041338d016b2a063c665a2cc8f4ee3623988aa1006fceba2cdf1984e1b0fe1ffb21ec874e038bad1f6b00c739f510408d48117b87ffad8614d8d08f434e59392a0", "Y": "07dc1ccd0b39156741959cfc78d6038ba768060b0932f5601bac66530c7b27c2", "X": "21007710cfb16ce2a9b1e84932b86c2bb25b0510198dd6fcee4e2eb5d6b3fd33", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:38Z\", \"userID\": \"3b9e92f347719ae5a0ede807a13acf44@certivox.com\", \"salt\": \"c8c44fde28fe77c362a155bf7d4ceb13\"}", "test_no": 52, "UT": "0406d0fc08baf703f20c8550f22093efdc40ee81e33029268a8ab2dfcdf155b02115502673516022f7908fa12a29ca099c31acb81ddb6e71adad3e800877fd17ed", "MS2": "133418dc4bd70d1aeb96701ebc004b91f5785929fa844a6cc568fd7404c03887", "MS1": "082e33cd126704d1e5b7745d5365ad9805e3a6f26f7e5cfd3db8c9f1f9eafe7b", "CLIENT_SECRET": "0415723b385f05b7deeaf162ff8c750fd3778ba983ec6bb3351d513c3b1fc63aac1093a06506f8ae5afad432423f0b696dc8c2019195bab66b13bf91a1246cd856"}, {"SS1": "194dc4ffb7a12033d435d37df56f7ba2c1caae2d69579154c49c4c85d22a763306c505df9986180b196147cd5f5e099da1712437e3edfe9e179b4d5eee082bb8101facc9f0a7b01baeaaaf4bf06effb27bb997bedad7b39613deaded00cfab0f062c9084d36bd730342e37374c1536c166356cc59f6f2ffe272c2a0f200d059c", "SS2": "07fad26af633910e802d7267b005d5a93cd05d4136a4b752c54bdafd123b56c620f5f23c1120fcbc4c38292b47fa2bb1708054cb90b5c87709d1533ec3e961a80323d0fe331c356bfa590ca93adc9e274c7c7a3ae1bd1c105cf66095f3c22f2917790d9db749e209d160f5f6cf2368c56b759d36214640ab0d2943a82b27f1c1", "DATE": 16574, "PIN2": 6671, "PIN1": 6671, "SERVER_SECRET": "1ce1260f75ce4c7c36c8e0dc14e67218de76b8b211ff36653ecd74788807acb3191d64dc20ba3dfd91d074b95726606f02858729b296d40388fb88eb26eed2a6136e01ab32f2299dd7af005e4637c5afe7bc3e91bdb044d11119c9c4d7e6ca0401e552215f1052e3c41c6d5a7c9261dec3b966d485e8fee9a4cc0c6558664dff", "SEC": "0418e1d0161482c7173fe703ce656cd9b7dc165197c4aa8185ffa541000bafbbe01651d6fa2506f20e82f1d2019ea2affb8ad3189b1bb6d13471c8446d8961af61", "TP2": "040d20b6b45319cd5da9d3d578a2bf5205cdf838183625b8fa2bcda795440b12820c10871fa45fac4607f5b4adf2e9bf05dd078199be06f03b7ace4b60f6550c2f", "TP1": "0402421782335ba5707e45b80458ea598929285f63b8830a802dc4665a21924c9506058a234d25b148559f7e21f10b8d69cb274313236cc42704931f0d63472deb", "CS1": "0423ccd24818061c24ede8ee39a2711dbf9276ba380af2541197dbabcc332fe51807f2d68aba8c83dba1c8e2cafcd03039243641a4f37cfec82bfb0e9b901cdd06", "CS2": "040c50f156a7ea3791b883f60e0c3fcb9c04e28de435eabdcfc4f9fbc15167385120e5d11cf1f7e19b367d5f2545d2df61eb91b54efc7e415a038fd291dea20872", "HASH_MPIN_ID_HEX": "11310aba22955fa3579b159673f409befa0a8872af458a19639515f9eb719df7", "TIME_PERMIT": "0402e1ea3d2afb19639c3e4cb6abee2c1ac4779ee7d4adb5cf8764423ea448e6ab1bb32c2dc2d04893f55edf5249b85e9d70b1e42fc4e8e3c6b18ee8af93a6e89d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33395a222c2022757365724944223a20226137643065326436346336353162313139303165373437346639666665313033406365727469766f782e636f6d222c202273616c74223a20223835653961653163366561336364326337303236373761633537646336343234227d", "TOKEN": "0414ba058a59f8789fa42e794d0f5cc02727ce7a866d4c9fe16a9a86eb7707382e1c6c3ec3e2ab8c15a5d08a24891d391444e40124acaea99294f87b73fc172e35", "U": "042165774c9d1fc0f807d138a9e6568077a55d2446cf4a00343c186d12eabd8fce121a6f38bc7c72a5474615a200e0a06dddb6d98149705d94c7c9a3f298c0f5ce", "SERVER_OUTPUT": 0, "V": "040b4b83e6045f5f9e4f77d9d9648def737f4cc1f6448f0647b3b67ec3188a16b60b9a45de357b17b255c9d0f043a4772b7fd4f299c728025ba2db59dfb53b37cd", "Y": "123f49c500891862705dcc129bd82902cbf905c8f31553907d695f3b8ea2cbd7", "X": "1e70f53c53102fb7f6667346039ade20c69d0b90baadd21145f770832d86fcd0", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:39Z\", \"userID\": \"a7d0e2d64c651b11901e7474f9ffe103@certivox.com\", \"salt\": \"85e9ae1c6ea3cd2c702677ac57dc6424\"}", "test_no": 53, "UT": "041e0282f556659a1d3ca40756a5b7e725f3bf50848b1581d4424747e4e847110f13104715c4f8e7812cdf5c2c0f95766361194a95b8c917ed27dec270eb128f9c", "MS2": "227e815c47bf019026a87aa2a16fcb1d4a6359c2d19cc64334116c3e09b348aa", "MS1": "1dff723d68dbb95fff7e6170d775a595ff8b97157fc0e1da3c62dcde1a87ae04", "CLIENT_SECRET": "0405d62e6a5218822f8568c7e7f757059f7f3d53408c22ce8f91d60f64c27e01b3185c618c7b2d1636cceaff8a0276e38008f59d5ff27ad57e84961264c6ccd5c1"}, {"SS1": "15ca9e1e71b4c31fa3d4fcca6e9a65af592920bc8f2c0213ba957aa562ca5ace2143f482ecf45aea3e750ba15b83a18a7d82d355109625169059bdeae081528f225112d6e31f9487f50a4bf4b45c1770944f5719e8abcdb3e60e3d9bb12d7e050de68085f8c2bf2f483e517be685f5adb314f64e75a82d31e1550b64195b01b1", "SS2": "214dd8524a723494298e2812f752a95e36265a4bca84f562338e423ab452db2b1b5852fbd27a1efd6a4fbb5c4b11103a78e8a6746a21d556e6a630388cc29f82155fbd194c6f60a08d6f28a36536ccba43a984bc4cae0767b5cdc00fa5859360214982561f5836a43054a0a45ad53601c1b07dd15ebcf1eee53c88e72a40543a", "DATE": 16574, "PIN2": 5850, "PIN1": 5850, "SERVER_SECRET": "1144781d95a4fe22290f1424e4e21448812ccc7d2c125bbc1c76f9283f6a009c0399fd3275383852e48f43fb4b17376986688821450492688bdcd17fb0bba51904c3d943f0e4284031d3dd3cbab155c79eccaf961a0e2f35e28f820d8f1beea01c6ad42d664bed09836af43426d0b409b43842cd7737b30c7c259d71cc874b6e", "SEC": "04181f6f982747d4186b1b47db943b7d67c1028e3258f354e5e2bfe477d4f36b2019cc6b94ac2793b0f9e9472f9f63e7fdb130d7d1fa7e78b200662cf7760bf67b", "TP2": "0400fda156c204314674e2c9d2b598d63ae4afcf1a70985d797ef9c072299f0fb4168794e72ed0b98049930c86d9f7abe67129f383337f1282281e8b5f6207a254", "TP1": "041dca6cb0557e3535a95a6048591906839634676114257217f5eba7ee6e7ea6e013223ad2a6b22106f370a456a374483e1105823c3672071ed8ff56088db8300a", "CS1": "04142fe5a58894c6e0be1bc10acdabd75fdd17aeb82a2823f264f1c1f9d18bab9718456fa9d1887578579b7e569b11163708718d0a212c348dff15510402229560", "CS2": "0418fb567dd87f628a43f742646853b6ac339446a6c840b6dc931c1e9302dbfd201864d405ae94ac30592592aa6158d2249cee0a975271de4c667d9440d3b5e359", "HASH_MPIN_ID_HEX": "c054c0859bfd05ebedc10ec91a4bad892889a31c443d745829cfdf4c95028e00", "TIME_PERMIT": "041988ba911f3be238d72f9d4befd1e975150f6249e49310afa9bf4c56d220b5cf0536ae59bc9dd8079038bfef98a69ddffd67b94b6a292f486fc21d8264bffdfa", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33395a222c2022757365724944223a20226538633564366566633033383365316237626166373264613835623164653930406365727469766f782e636f6d222c202273616c74223a20226233666332386362393832363537386639333662323133643838633435633235227d", "TOKEN": "0403861cfa4426482d95190b3ee40c03fe8b6c2109efb98a5f86a4f9d914847102184cc474de368c71da9524fb611f317e358f9c899e4030908b16d52bd51c6d27", "U": "040d16a51af938b6a325d7891ee14d00b1602bbb5f47d72f75166595b0cfe086672376a775d0bb7b3dd91b93f849b68752db3b4cd49856206c5483db0104fb57bd", "SERVER_OUTPUT": 0, "V": "04113711f9780ca0ac35cfd6847213038baf70040a827d93c3e1ad7f7f2e75e9ac1d38467a8c3c7978bb187bc604a029dbf71831b332321216de2765b7b54d47d8", "Y": "120431aea2869438733f0c5a340c4b55c4dd7ad0142b91cd1f5d9a2961957bab", "X": "0fa6d419e2a332b8f8b3e1a3415d30d40020dff95982684a0478d15be7e5c491", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:39Z\", \"userID\": \"e8c5d6efc0383e1b7baf72da85b1de90@certivox.com\", \"salt\": \"b3fc28cb9826578f936b213d88c45c25\"}", "test_no": 54, "UT": "0405a8390b1c0395a7a0b4f6b60b444d44d587813881fb5e06bdea3a1029270d9306df933f015838f1dae709a114746fb236b87f91f427b3dffb1cf68e1252a743", "MS2": "17b4fd2e3db2aee268621accf33e002dce98ab09e2973ebc3dfa461c93c3fce1", "MS1": "22f91ee60a3e935f08114db87e882c568e2b20822c7438742d0df6d4f0e80a17", "CLIENT_SECRET": "041a1bc66e31a934270546234bd44cc38e39441d515bfea6231e276adf59abd41f0451d61db6b8ddb46d11ceee71b11b5622e52efe8569ba508cbd63c6dd086a22"}, {"SS1": "0574dc399b83d45490d541dc8d01a5e67fb3d01c5dd3100663af3fb77171a45b1b34e6874e7d49e736d302f5f7c43411a526bfa408cba668267a18e4cb599b7610aeb3e873a0bb0f2e63568b1db4ce0c5682b35eed44167a58ccd4af1aeeda492197e72d85a7eed2d78e6d367f8e4c0126c0d9fe2c37bdc7be344ffae160885a", "SS2": "020dbb2be92825c96e6c35305999180b3118dfc6357b911ef1c2e7aa7bdea64223373b54c306bced77d1cdd0dde354af6e1cff169866b02da8b30557370e43b71411e3d122a9724b368024e9d16474e9986965885c5c871128191376354d40c91e84f62fb7c5b146757b9235938f575190c9cebebc01fcd4f191770631f8c770", "DATE": 16574, "PIN2": 9154, "PIN1": 9154, "SERVER_SECRET": "0583092e3b56d0d1365c1118ce822408086ab8b04eb634e3c0c5ffdaf4dd0f111f09d6ac6fbb996d318d83694bc29c9d37746ebb3d89fa8bd938c83f263fa677237f2af40a52453731ea2e5d58ce2faee94c2eb5e9b12d25f473f92415e6e2a61c826e1bab316fdcae4c4915dad2a8b33525083698ecbbdb2d0fb8a1417b2fee", "SEC": "040254540609ed26f13b90bde600b2323dd8ef68cccdde6f5580484465d1fa23711ff6aad2319765e181951598376d3b8b3d7a553e15cf7f668ba912d5d7e5a0ab", "TP2": "041293d76ae6b5f32d72d3634945bb591636f5a4c502353d45694d953cb1a1eedf0b371ecb685a9711e2e5d15963d223282777d444e845502138b8da2106bc95a4", "TP1": "04013ac5773c73d6dc1cb33a28d8c32a4aadf5ba652d10f5d1d10be2423ab380c906d9d6cd522d880a3a3ba1fdea151d0b1e78ffd0c3bbae159511e7ba0ddb9c78", "CS1": "0420435dc4504464d0980b90f06e845a25c57c90b0154fb0f1ec6834f7627cbce31c5ad4e4869bc023121c6f6458a22848cfc0b77d7385d612c3a24067c42d758a", "CS2": "04005b0e4549fd9484f763f2382a2304db044cf53f9814b35b973cbcecf15605cd1ea7b677167a00552e3570665207e667f34ba14c9f6f78e12dde66ebda80b7e7", "HASH_MPIN_ID_HEX": "2cf8d6f7f60562ec35a2e773418ff66f9f7c8422193a330a596067d76e4a5be6", "TIME_PERMIT": "04001c62653fc13a7b584b8d1004b2b9f4b999d2e2a23ec6f1e2abe6531fae88ef2266a906a06bc794135d0b4b9e5e930d99ea32034b01697084454c4f742200da", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33395a222c2022757365724944223a20226632396534366165366561353062343265626637333831663637623138636236406365727469766f782e636f6d222c202273616c74223a20223934323133376139373366613831376162396634343865396536653233366638227d", "TOKEN": "041c83496045499e94eba64a5fec3d7d6113d05dddadcbaf24a4eff835d68cddbe1e2855ad31adfccc42f4531804410a25281b2b2a7a06b651fcc1a724e8097a65", "U": "04143b32345a9d04a5d934daa6344f990db3a9e916ef1b791bf0d0c31d79551b630193ee9f6b20ce10c1e53736d40f11b749617f3e7f1adfea5e7a33226a8dcda5", "SERVER_OUTPUT": 0, "V": "0422d28f08715508db925b7853ef898a67d4bfe14772f6a3e3aef7dd0012e931c21fa1c833f869f36fd77ecc404e9bd00f55cab828c49f09f77e10060823760481", "Y": "0c15e73e00056241c1832642f7756a0ac9afa23fe63f905155a18e581a0a85b4", "X": "032c1dc145986556c960ef2343f78aa3d43a50a8d14e58056cbf07ab9377c025", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:39Z\", \"userID\": \"f29e46ae6ea50b42ebf7381f67b18cb6@certivox.com\", \"salt\": \"942137a973fa817ab9f448e9e6e236f8\"}", "test_no": 55, "UT": "0400fb72ad56167134bbae3c97d7bf81f5ac3988296b337802fd2d108313dc17ac1cc23b27b873b308c6bf8c4b50211ff918d170194c702d8acede997ef6974003", "MS2": "0e554ab7b4d60df6ecd133af01b07cec0cf63a470a9cdb19d84fed43b63cdb32", "MS1": "02bcf806a717c51864333634b8585590cfdb7784358dfed1242fc7d086e790d4", "CLIENT_SECRET": "0411d62afc00cb22df7bed1eee7365ba09b188ca240e44ffb5f7ee7015197e18b8052c5a1fb038971c713c397e6717f934898b4f3082d384cb542ca6986923180c"}, {"SS1": "0e6304c881496e0c263566d435279c409de0c4a63b2aeb65b37b8e7fa1cffd7c1118bc08c4ee246deffbabbbcb3fb4994620d34a36eae5b2a66f03ee9b996f2c0852ada766886e3c2b8cf41c7057e3f293d30d54d745d2cb3b79fab72045aaf22172761583d728d082548f885c6ee725e043c0c3ff80c564dd8d2dea779f0029", "SS2": "0688629f2039bda132ca673ef2194824fcdad464054c957e515eaaa90e68e52f113c2532f7dd3dfc8bae0a898d0c401c82fbb5f5c36a0f93da53c9669a0bcdb504c17337c1ab4d32b93824a248d52f423d712937777c2b04559422674f163f44169edb02326d922a87d5fcb5a66349ee578eb703a0da53c1a4c2094513dc0f01", "DATE": 16574, "PIN2": 306, "PIN1": 306, "SERVER_SECRET": "146ac4dcb5d75b9c1008f681fc367833d45af89cd7c3673eb23ff6465af3d1dc04f714817edb0d1dfee4e1f642a1ea8cb903c3c56b07156fe8ed7217c8b92f0023f2e1f623f236f65f21d3870c5d8e671e3d97281b20a8ccfc9661e73aceca671c166b3dcc6714c1bcc8f186f23b3d61e593cabf4a4d8ed26c6721f005aa4eab", "SEC": "041c9d23431a648a5b6f27d88b3b322d82f9bb867e486dc9813090b44fe314cff61ebf910aa05b9ed91a98047e6d670ef15fde2f6220253246556e2d40427162bc", "TP2": "0412f8d6d54ef7517613cdf297524f42235185e670927fc2bf60bc9ed728d2c0941f6260d378dc61764346ed7fcd32697ec3094fb13585cfad189a5fde8d90fdc2", "TP1": "041d17f673da72a8af9529f48613916b78bef2aad830f81a3906ab7de2752236f117e99277dd5a161605950e4a2a7efe5d4ab605a3488da2a8cc4ca0349a6ab4de", "CS1": "04082949e090ca087ada85728ec005e84eee30ea123645293116571a0a4c7494ac201c5d5c01b5106a3c04b8ee3f7d34fe5c8192593b0b598bd01b86254bb59abe", "CS2": "041a8f2bfa507aeaf2ce8fd8c6f1ed1272dadfc303e914866d6d35428f659d7aaa06819bf0f05ca4c18e287e2493612753d032aeea67c1acec85cbd587cd2a2ebf", "HASH_MPIN_ID_HEX": "af5cde52fc0bc9900f5d582d6144be38de9a20c010fd467a2221dc9fa6f11c97", "TIME_PERMIT": "040f4aa38ab2395f4f414dbc86b8bb2994924550d6f70351944604e1b6c0c6200d0f41c6948f54403c76df99defc363e112eadd37d7dbf6a8b889165404e017c85", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33395a222c2022757365724944223a20223935383964383361663863646639373332333336613437616162333736313237406365727469766f782e636f6d222c202273616c74223a20223561356431653237326230356432383061666135326235623034656532396134227d", "TOKEN": "040261cbf2ba8bff1efa03d19e4b0c3c2354ae9fb03a90e9c97a6f7fc0a94b9dae15816778a3ae2a306a91f04e8be2bbcf1007ddc83fdec75fc12039626405fe28", "U": "0406b7f50c0a9a7c5ef1194966899b9222f82767e7200a6c0a4a857053226237671b817fa2f3eb9b146783637209e6323daf385ee97f648e94301785d1b3e9d892", "SERVER_OUTPUT": 0, "V": "0403b545ab211b77ced1b0d1841fde4eb071c4b9d84509dff61950f8db232c8f730901867b8123ee623592a8e7aaf77506dbe681ec11fef30a69ac6b853d1a1248", "Y": "09450f3f25d2d650d7003aaf96b7a56848cb618c72c985ad212d6b8f9b0de57e", "X": "21858aa5c3c028f9e382d1a3b9b865a1da2e6cf0be97dc06f7d3f5a6ad1ef555", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:39Z\", \"userID\": \"9589d83af8cdf9732336a47aab376127@certivox.com\", \"salt\": \"5a5d1e272b05d280afa52b5b04ee29a4\"}", "test_no": 56, "UT": "041bf275be9eb8b5d781dd5c3d4666cdf1f20a7655aecd7c14991d4b56abf4da0602a7a1feb64fb057fc768940efcf47b5e243342c8c64d76b8fbead4cbb850968", "MS2": "1aab05fe9329664a7e2a7763e40baf6ae36c990162e463c2703f5e8e2acccae5", "MS1": "1b6393ff74e299f935d4215a96a9bfad3eb485d6f00dd0d996f9530f2fcf9248", "CLIENT_SECRET": "040b210b0357c99a124f052bacae0101aa100db132244d13c14fb1974932a32a1c075fa99746b47245b599dda5aefe0f4a19db9bb6ffabb4ac7f951308cde6ad95"}, {"SS1": "04e3cb75671de52effe2c6208ad540fced31543f6a7c3283228329842ba27625032238537a46681a4bee060ae60a1639acb3688c47d8f1f7de4f824532f0d6f317bfe3efa79f879c8b448f7aea6164daaca214f943fc2e298202bc2186eeb0140bd549adfd39caf6807bcb1f15b4701444c598c532e2da815d1d31dfee2d5980", "SS2": "178603e8990e02c633b011124597e6fb1e0dc42a20efe385a4427368319f193809c7358c07aab431af977d1f4e6d72e5bbd3bcf77efa0ea8dae62e7c58efe8a804d5a0e1ef8c26f140b75d70085c4804328ef9ba2c8c28d6fee946c8bfc53f7510fa35d9a62628190bd91fec908c34e0d210c103b03f7a91b9be3ed619b3b586", "DATE": 16574, "PIN2": 13, "PIN1": 13, "SERVER_SECRET": "01859600587f3363adf0f092fbd9b8a3f93badccf45363d81310a40f1cd4d4b413a4000d0a6661257f66775f7a3d9276a6f21b9b0d45c233a4c95bfe01602c820b043d069ab9d86bc83dd9de50b0a5227a8ee367d8dc4a8f4be99edc37f4bf100f6add318338344c3a660e35474e899350799cf64269da8fdc72763ae94d0464", "SEC": "041df599641a9abbc253fd0094a086cf4f2993170fb1ea81c101871345b2c352810faae61da428a0bec3846020ddff80d037eb073ee35c59461ba7094db3e41d97", "TP2": "040de0cfc0ed5a271263816bdb1ec59c187bec00ecc6b7b57d72721244ee405f8b12a0a5e1fb4aadeca1e73b728c494e60ccfb84371f55cbce945597997079d1ce", "TP1": "041e291cf2163b9c8b612a5e9f3ba3906708c896956655f54ad5fc8241d35b0f6018abbeabebd029734412327d9bc25b3f9764f91b13a6caaa2fface901b160ce8", "CS1": "040bac20e780c5f36a618b1da5c2ca6e20bfed2ab341e264e68ccfaace1f4579bb23f0f8782e52ab9f978b1ac98db1345d929ba8bb4ec578cf93fe1f9e7bf2bf9f", "CS2": "04176103ae36207642f04b57c837e191278f2d4710b9ef171f37478a97eccbc65e11a17b1b27877d768f2ae92c75accc9d6aa2e7486b5c525272dd423f641b91a8", "HASH_MPIN_ID_HEX": "76acc9523616e049ef0f55e4399dcd15c2197f39a8d47006a1250d967ed331c3", "TIME_PERMIT": "042235f0b85728c3719a866c3d56b7cc174f62f264740df88cc6473491fca20551183901f60575ef5b6ab571d44f645e4ef74b0cab0f1736e50494cea90a2a577d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33395a222c2022757365724944223a20223561383334616536313630633938663530306361333463333237306633663033406365727469766f782e636f6d222c202273616c74223a20223333373639313339323966393061346534393235333930366536633434303561227d", "TOKEN": "0413c231634714e01b9048bfe6c33911f9cfc47a981985050698351d0d081b99a8091f786be0feec18093206f0f97303ef0b2bc101e1cc221a4953291f9a66a894", "U": "040565620a301461506bbaefd1c5ffdf1f1b8a9f54abf72d220bb7758fb0927d800d9a977bed7a77a423747e4faed33d2ebc8f3b5c2472347154a895c159e381a4", "SERVER_OUTPUT": 0, "V": "0423480209d476f3dab30127ff78eac2da89b5c87b8d8f1fe1c91cfd41574be2d31520c2642cf416e00b65395ff6c2121be268d32d65c258c76bbeab3ba5df3369", "Y": "19caa9e9fc6c1e805d5fc24271e15ca8301fa3144465bae7c4764323871e7154", "X": "0fd3602482dbb186913934a5306a1fd24f1dcf5d492e08fd5d5fabb182e8f88d", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:39Z\", \"userID\": \"5a834ae6160c98f500ca34c3270f3f03@certivox.com\", \"salt\": \"3376913929f90a4e49253906e6c4405a\"}", "test_no": 57, "UT": "0411213c47041682cb5341ec07aceccc2d1685f8a32ff70bae35836a8a9d5e78c6112ae269585bd53f45ab5f9ad7651295fa6843874804a5be51d935b1f8057d9b", "MS2": "03d13692a2ef288d19f03938cbdf45e7bd805ecdc821b409f2b12641256421e1", "MS1": "0b899407781f9d0c9587284a80e8306e85903b45b819efc795ed8b6c0987f211", "CLIENT_SECRET": "041b22c2e195dd6e5b8896b8c22adcd091132011d86a87f67b4b8426e4c6bb442b201ff6338b19ee62236d1f45dd9d182bc23cebec65435eb0ed55f1e9c0ca2d36"}, {"SS1": "072c7195fdb4c7a62a3bb588fc1a57db89f3948917fadbb707f26c5aa3f28f0a092f87fae3895ce7ad12eb4695b286290067779db626e807c12075bf1c5ab2d5068339398ee1a7f134d29ce3e396ed5936d9071bf83294f0f05fea65e8c81b951655ea3267b5af8fed59e63dbea1c01bcbdb3549f0a071ecdcc77b3eefa20d97", "SS2": "18e7e9627765edcb2acbadd46b35358358d562ceafd3c55d622d7e716df70eeb0856a052be8f5c2a264a7f5a6d863ff2c42505fa15d937db7be56751f82e350208200969c255d26703d7bda4eda8450af424574eb28206cc72497ae2c4ff4d77024cd2f2c7d6ff1e4e5e516e374609de83a2868002eb4fb203e3783782756042", "DATE": 16574, "PIN2": 8292, "PIN1": 8292, "SERVER_SECRET": "07747f92e8bba62d59ffedb39daf6e89a38dae6fef5d3fc3acc20814d2dbaf6a2081ba09394efc1aab1e64f465564a90c7ba68fe2d5dcc31164cc9b5ea82e4f12032bcd7ea77c7a0d96cc021252da72fd875cc3e355d3576eec6e9b666723e511c849bbedfc9ef0a1383bd57d3e09a411188f5c04749e564b36153d624a75483", "SEC": "041f05c1ffd2b8fda2da3e3bbd8cc114a7506ad0b486bd3f759c8abb4c8d27bd0414e063e62d1bcc4bb684888e0c16de49a1c0a901d3df60ae4f49afdb9ba99a07", "TP2": "040aea362f8894194f80b77853a75980d2fb6151993c9730d38562051e9f50a93f022366df2a5a4289109fa446c4a0e517a1cec6c8ddd2ca7ca67f73663297ea84", "TP1": "0402b4e83d9788e811a844818e73b50bb104de7e45c9b97037f4c36629e12bfb8616a2c9cf4af98dcfc8b3237c3282d727eb3b67b7b6d1f26a10a5f908593c4e1e", "CS1": "04183891e8c54fed53a0e1abbe7bab6091283774b6a7b4c8ef3bc07a75f7a361160cae9112b2c3a5fb4815344f8ced65138db279e16750df578268b3071f47c898", "CS2": "0401ecba05f14044b5ef74d8f260e7ecbba22d1748879dbd406e2776f4aa559bfd1c98026af1c6b10a027a27398b6284ca624eed2c1d3c0199e7f8322600518f33", "HASH_MPIN_ID_HEX": "ddc3e0babeee2f1739e42a7b5a46680a933fa28166e5604a21f62e7df1bdb4c8", "TIME_PERMIT": "0409b204f5a26e9b30d39d4bb5aeea635a32e9f7a059e3b8863d9681f8a0bec4f10aea0ebd8f959da833210589348aaaf4591159b13e684214a36ab50ba5a0af86", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33395a222c2022757365724944223a20223938643635303533643230363838613131613661333430366266633062633732406365727469766f782e636f6d222c202273616c74223a20223933626465393031373064346231313935336635316237373564306131643231227d", "TOKEN": "04140eedd62bced0687bb47a5821973a22c5442672fdbf59ef77688de41e83c3d315c960bd0336728bca956d25f0f65746bb6a64cc7531d24a7571bcb0bedc595c", "U": "041383ec72c8c14f258c62fa0d9b9c2674476f2c165cbcd30461e610cec7707cfd192ee5659dbf0b56b3e57a98bbe34e80bc035af2761c56ba629e96917bfd2fe5", "SERVER_OUTPUT": 0, "V": "041a7d3b610150f90d3f561cbbc9c303b451c2003d51b9cf8120200c0243f143c70abb3a7ba15fae347fae4a2181c2fb30fb9224262a454fc5f5389be53050a667", "Y": "0bb5f784fc4c655386417b96de58e6afec1b3d2a36749d942faad13031af62f1", "X": "15a2330a02e8e83d9238f466f3f8b6a0633225f55f77b44a863e8c55ac914ea2", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:39Z\", \"userID\": \"98d65053d20688a11a6a3406bfc0bc72@certivox.com\", \"salt\": \"93bde90170d4b11953f51b775d0a1d21\"}", "test_no": 58, "UT": "0413fa623bb2688a881e9b0b16712681832c1e7dceb0b2787707a2c92244a780041b02f88616689c131e49dfabcb28dde56bd7ed1ec6722dc286504e6624fbdb1e", "MS2": "006070233282163b8a7cd1041acddebb6b345e68bccfbdbbd7e221a5cd1f053e", "MS1": "153a075104c9b9f697dff4c8822482151927c47b174d204120714f59556c6f52", "CLIENT_SECRET": "041955e3b3ec63705676848fa862a210365609e68c2050a89433d53d4a1752ded4195f929b4bf72648324106b6dd1ee1559bcd1e99e74fc0b057ca969811b7dab1"}, {"SS1": "078b83be576125203d695d17651bb4f6fa472ba9e6d76be0324658f1c66867ae11aa5b45a91dc48c500d644fa3aca1b291c0e32caeee66892954e4d365ae9cbf06c48059daaad6a6f5a29af05c7a1a10696da5336aa45281dc5de239127db86c1a8030374a08e0692ea3569d76ae9bd55551f9fde25a2624d6fc65765cc11a0d", "SS2": "1e2a4455a323a1415a5df7703ec2fc393b54f7af9fa9afec3ff97395385cdd452112aa6d0a00dd4907e0b6a4e93f9002f15da1b8017d10749058b53034fc79b20591ff3a7dbf4eb7ebe5f737c8dc620b68c39107fb99cced2b4641a3e312328c0712533d929787dbc6b747a4c932fca8e87274bdea0697d4ff0b25c18051d8df", "DATE": 16574, "PIN2": 7866, "PIN1": 7866, "SERVER_SECRET": "1f6f3d82ec506c77a3fb8b0e3132529a693c0bebee28d122fb3d4a6f3e02da4b052bceea91c83784b45af16fdc45036c7e16e54c65ec8ff768bbfc1d117d1d8e1362766f551748914365e1c292e02b64b2a7a6a0d921e4147a7f01a7db9b25cf0386ad997137f9edcb5feb523c324708062edb474398a1de1d437c698be3c5a7", "SEC": "040669b69e2d3eb5b92ab2fec7248d04e1c4f8d79b5184549071d4cf75c48b9f4d22f62c0f8815025b14c77cdc1b21db326a28c51f5e9412b3f64ae61620a85fcc", "TP2": "040b8da1406ebd6b531877433f13c55b0da9ffa5776032644fba22943081408843151ef812582f8daf7fd2f8a92c14853aec2f9177803e68f71859f9437da0b6f9", "TP1": "0410ba29c7eb194a9b10850ea415dd2eed38b375e809c3932a3e6b519b4c9e33101a8f00e2137d4364f8690b564ff78decdbc56b9cf76537cece37255636e664e5", "CS1": "042107688e0410ab1e9d48d1f93d307e4d046cd1fc2189d8b7f657c86176d9634102a747de6eaf789961f944031c3d989f45cd35f77531f51cfad1831eae06c087", "CS2": "04009c1af9a8a78088d47ebbe639c718bb1093f3bf4cbd376b80e144e7b0a35ef82069ed747cbbfa41c9d4402279f22e987c20f61034f55b186205f865370c0db5", "HASH_MPIN_ID_HEX": "2bb20e11053b55e7b40aaef5a4401adf7e1fb8efddae04fd7b9cc567d2db980a", "TIME_PERMIT": "041c590b3578e966a73860b5577225f2152ded2d124cef56bbd90cb3d7e196af9c1718329ca33f606e26b435d85f63604f2c3d60b758d22928f330fb1c6dff87b9", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33395a222c2022757365724944223a20223630613131346366643733616561626137376563653134353964636561336138406365727469766f782e636f6d222c202273616c74223a20223363623735623361656265626632303132613266626638366430386431343162227d", "TOKEN": "041a53bc20dd7a687228193a5b49d8b2afcc3a081df1a17146d1037ba297a4bdd41c6a2865ec897c5a3cef89507f464b6543d97da8676aeed7d940d472c4f83fe8", "U": "041239d25f0d5be7acb61637e9148906d059b0f8b428cf14ca117f2f6de5ecdbd011425ddc2cf9452542648f8c62a44bf8a59b8061fb89a19df25c00d01e7a797e", "SERVER_OUTPUT": 0, "V": "041a5d2c83f00405783ac510d21e2b358e9dfc8334ef5d41971e6cc20a0657a71b2251f81d13502f974845527e316f99a570afa641e4f6adae84fcd2542c104abd", "Y": "11df091677b9108e99b15f88e2c19495fe453b05a324d7dea700c9d9027ad10b", "X": "137402ba59176b1e3ec9e8ba9688c3f5e65fb9ae9c49c5dca8eb518df479f2a7", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:39Z\", \"userID\": \"60a114cfd73aeaba77ece1459dcea3a8@certivox.com\", \"salt\": \"3cb75b3aebebf2012a2fbf86d08d141b\"}", "test_no": 59, "UT": "0413074f27c5d7660617646cd0e481bb6527b0daf62fcec17a57bcfcc6494d5cd80c8397aa541b9e36152440f98fbd03e5b8e162f907af0f0c970e756274be9c0e", "MS2": "18a7df316d8b719d56dd7c8e32dc72e223f2b8bf19faa0d7b7da160e9b3352d6", "MS1": "0bb817e68653c1a98a9f7d6528f1e3b74aebffc8e98f009fe19ca627221578d7", "CLIENT_SECRET": "0403dec038576d6369558520de8be8e5bad528e7875c2f1d1e8011f790f0a2bce614a04fe1f46bde4aa6315456d75107a00a171802ae76757791d8ec12be82c15f"}, {"SS1": "14c01357e752dfff747b85fbc2c6d6778baaeb5c464d0cdb74310ec56e18a7b20c230d67d4a81bbbc731f5e82ead9c9bca9f3e3880ce7096e689684d192fd5b0122de05e73ac9366361338e67fe765dd3b1f93f92473eb47fe423a1729532da41e92a51636d4e908d8d0166bb45807aeb951a1f9bb05a929dcbcdf8263d8a958", "SS2": "0615b4498d7c8a5576a7bf7cc62203e38b3246b3a638fdc1f6c719a8835fa03d1fb37109e568ca7dae9d1aa55ffb07e7ee9ba34cd5303596ca6b4d7735c37c9b0ac8b7da96a74a715a1ab081511b3e84c32c3cea6024e544c8d49c647ffa59550aa1f79e1f4c58c6e7f1792f0d8b1eddb41a5615405302fedd05b5b7746fd7c3", "DATE": 16574, "PIN2": 1862, "PIN1": 1862, "SERVER_SECRET": "23cf5d4372a02f50be2f503cbd0d5a124eb2d8b7f38e1c3db215411cf78fd6491b79fab2ee2b3231118b64b073825097b94c0e8f98b411ae570cf5e9e0a0e1370a3864953e52714778200921495f173990cf22a2b7851748fddcd3d56e56703010010ed24b81b34bc8d4e413d22cbbcfc99bbe7e81be375a2de760b162b8e662", "SEC": "0418e2247b41f09d15339f0fee69d4f787528143473a2a68b7dca5080c0af4dd5613fcc0070b165655764043a6b1ca151f9b9d0b3a0dcec484358ff099c9d9a6b1", "TP2": "040474874bf0e38a890b5348c335c0f22639ffea55d2bd5a79c91f6450143402cc20c9c2f096ed04ad5e4c92ba3dbdea01c38846c73eca5d3120d540747852067a", "TP1": "0422b325096a10fa8f24d4e7128c5343d17e0e71be79dbe7d0c78fbfe46d404dec0bbcf75b2845a23f185506fed870775ada471cd904f5ec04d616dda516ea1b29", "CS1": "041e68bafefb6725d2011b9e07bd91793c9ba0e79040a5d64b1116ce35c44223450f85b67d0878876b4f9538c7b36436dd98b369dc217ce182bef9ef9e65142cbb", "CS2": "040473cdfd2fa3455f520a70d1ccdd1b5dbe84aa669ac64ce9abf58ac0d60bf9200dda8f39e97076dcd4a58a7431851138ddaee68baf7d125a950c413dc8ae7da5", "HASH_MPIN_ID_HEX": "f685b4978542b8c8e191ffe036420d9d500458ea5e7efdd8152c7fea2d9d8ac2", "TIME_PERMIT": "04061c71a0b88350c8d44fef205a9779f36dc7e59d49f0f92b47dcf80e4d594bf70b35d25fe9f6d902b2fccca5a52ce43d5236d9741ff65c2f9573df4eb9193442", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33395a222c2022757365724944223a20223035656666323466646335316162613830383834373836326263386161646162406365727469766f782e636f6d222c202273616c74223a20223063623763616235393537633961623739616563353733346633656361666565227d", "TOKEN": "041f11ddecd0ea572f993ed641ceffe6728292e7e73b4a8544b16d9a1df7e6c0cf0cd194e363a3487dd6d80b64f919c12327cb8eeebc419363b44fb9a7ec4ee1b9", "U": "04079028d23fdba0023edba55291f24e40cb3b126577d658314a7a8104df9093241997a1356a46dc11ba009699305eacb39b33d727590b130ac87c2d91961792f8", "SERVER_OUTPUT": 0, "V": "040e1e4d91d85b225b263039f1cedfbae4d6225da8b596ae868b95248cd3709b300ce1c0fcf261934177a99f67ab1ce4ff54047e8ffc26b91ebfe75d76bf897e41", "Y": "01c3c095b0f399c712f69c64dbb25f0f9aa552da0bb60a384f0088988eb08cae", "X": "18599f25f15ad365146d9a75fdfea275969ed50843b7214049a9d6c5714b74df", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:39Z\", \"userID\": \"05eff24fdc51aba808847862bc8aadab@certivox.com\", \"salt\": \"0cb7cab5957c9ab79aec5734f3ecafee\"}", "test_no": 60, "UT": "040dd09c357c1e0207a65667b9d54d9a1b159e141cbf9e4770e9fe038c8a1f7bd60fac96aa00ab0fa7c0e41fa95c588258283500fcf76938d5ef1f09ecab553668", "MS2": "1906d730f75f674c01f492a55ab62581e0173f75c5f43c1c6540dd98e1111e3f", "MS1": "0a493f3c5461d80542f96e802a59393cbbf052576de5b28c8db5445e61db7231", "CLIENT_SECRET": "04062d9d22a49bb8479aadfc424f5cb9706c589c29faf7e1036d9718cb3acfeffb163638436efad413d90186a374a73bfd20a82a40bbda6037aeaf0ddc3806e0e1"}, {"SS1": "0ea3f9e757be316db2baf323e275022fb932229cc1901e196d93f1b2cef42e5110b3fd334dc224693543989ff62580983b9f4bbd125b873b3fdabed26802fdda09b4ef6f71f13dffc7ed046a407eecbca4c5b878d4498c4482e9283b853323f20c9fc15e195391cdf298b0a3f8edd75d6edb4c0b2b5ac3d9ddd63cf0b2ccdf96", "SS2": "0ac33915724c74c791728a0796d9f675caf07909754c5080189f5a98290bbb7400510f25f536b05ddfe038cddb37887e995490f376935c819bbbfbce8f3dbac422cfe54726c3b7178dec6bb39d7741288a71958d847e9b6c2b9ea918bccdfcc301fe1535dc044c3d6d3e58d3fede1bdb056354bd516ee430044eb8d9ee6ccdab", "DATE": 16574, "PIN2": 6124, "PIN1": 6124, "SERVER_SECRET": "21845f776c534254412df13559a54ea67a9447714581e42c744721534647073d03c450e998c0eb32104c51645dcd25b629fea66297129833a3ac59933ccaad9002aeadd6e6774dc6dbe18355527010f0b6e5f71503e211cb18de89a7c762834606862852aac299e3d9b9d98458b402fe587a3c11c464027db0fe8db651301247", "SEC": "041518e84162d12fedbcc6eb45cf4c2fbd92b0d42283aad8912f44d8f984998b5c106301e135d0e57f92197d3e5070caafd71238f79b515800424bf05180639c3a", "TP2": "040f346ae40a976346ca9a9c42ae2ff26d41e504a185e8a6f8eb30e76f7934efe109cd4977c9c28c062567e761e7e2a576ca48057c71292e3ed82908830cf9f12f", "TP1": "040183f19b04b781d9df48a56986be015c8fb102decfa5a92dc607450462cf466b1c28b670ada759cc51e4bfa2378c3c7e73b96dcb25c79cd91a445ab70c883b11", "CS1": "041aadc432a010bda29a4dc933b862bdbc6fbd2cb9d45aaf01c286d8e1259eb5a7101b77197af04222b1b0b8583d9564996989160bd38f692de1696498ccfc880d", "CS2": "041c89773b02d62afebf042a5997263215b9139dccd39d03bf4e5e12f69ace175e066819b11985b019cb5ee667dc766a3514dcf91535dff53348a91f2538752546", "HASH_MPIN_ID_HEX": "cfa863defc2a1ef0176c0db9489f45f88cd28c04224dcf4fb6f9f5db3ec41548", "TIME_PERMIT": "0414533ebaa0c1fefe3d964016e3114516377385366bbc71ff3ff52b3460dc1ce216941c4de8482881d946070313cd7134f5a547d47612c306b17d58342af26e38", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33395a222c2022757365724944223a20223434623036333838303639623166346466663762316264303035303532383434406365727469766f782e636f6d222c202273616c74223a20223535626537313464613430373530376431313661623933646338386430636161227d", "TOKEN": "0413da749490c816dd433e358b0c583ac6f6ff2e6dcc29efcbfec3cafcbc7555581d531440f8284aa5586e75d6954d01b8c2d5784bc1aa07db8c228eafc0b825db", "U": "04207455992717594748db77bfe7bea8b8dc466d56ebad69ebaa6b449f2d560c0702a20657ff135e1e7a1c180f3092b3821352c242b58fcd5e07f28d218d824552", "SERVER_OUTPUT": 0, "V": "0406902a397b98189553d4be06256f36ea04f18690ca52cfe3e2511660f7fdadec14d074dac887f3bcc9f4314de91b8f9aa17bee4173350a95fa84b96127690551", "Y": "15b070e4a283eaa8aff7af180c7bdc675b88a2268f06b657cdfd3fea3432f199", "X": "140729f3b4d8290e9b052a28a9b8e68bcfa4baa79162e65739a60edb02fc37e6", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:39Z\", \"userID\": \"44b06388069b1f4dff7b1bd005052844@certivox.com\", \"salt\": \"55be714da407507d116ab93dc88d0caa\"}", "test_no": 61, "UT": "04141ca3ebe7eba71574e00499d4456bc2d1f6e06489ffc32c8ff5de35cfac8d5518a641fcdab6418b3d2a13076fe2330542ffdab042ab919c6806e47256c2e671", "MS2": "23108ae9908c84d3ec665b6f141cc6643a943ac06372efe2d60fe007f856aa2c", "MS1": "00ad8ee8975536e11e3ee77ed668af7a9efc1bb9052b58df9d9c698ab2f04ea1", "CLIENT_SECRET": "04143c501423ea9b462ec5a574316ddd105f1c85c33273102ad70c1ab538defd3120235ac8f7800305a2d92f1ef1ee2f0bf76be9cc9c3486d842f505b654c58d79"}, {"SS1": "0272f7c6a684bd1b59c184765bf1607fda1e80d1d63eea62d50100aecc18c10006b468c1c476ab38966126f5e3d9ec9ad7c18590162ad19428983e7d5d154fe5127ae2a98016863c0d11d6bd541f0c61680abc3e8f01a9da7f24a78ca297a0e320d478d1f2dd986d1d1bc5f8cdca5cb948b92756fcfeb96a25adce5c3914e7dc", "SS2": "1ec7ad67b9439b0792ca14d099b6fb500b61ca249a0287cca94238cee2cc78841158f5ca1c659f9a7e975c9e7c8e5fbc831aadba795ac8c996906eda345c18db2116c79be8f2000114e1e0c56305611881f1c591e2f9c4933fb93b67c5847cb6074fd61f006fa513fe96e0c56c987086a079d08333d751fc81cffcc73b26a60c", "DATE": 16574, "PIN2": 5019, "PIN1": 5019, "SERVER_SECRET": "150c1daea00f501a2bd800999ff3ac0ea484e37e98ca7ba01e5f25378a32d4bc199ac07db0dee115b1da11ab25a20af884f6caeba5132929349968df7f9448ed11ecffc3fc40a86f6ac3ff8dc4b1d64352198cf217d17625d1d2cdf8a1cc69710955a3a785b811fa9a7de7a25f6b54c7534def5aeda7757985bd78f0c0cfd045", "SEC": "0405d4c3501b55312b4957fe6ad01715c5a35b3e716a246caa1535b78d1c813c1c1224fb119925124a20538a386d34385d4828bd9a5bc5f405493fd18532562fb6", "TP2": "0420ff1428abd780365ba5366ec85e4e0853ef82f1799c0d9529e679f4b2caaa6110bbcaae974623051e5403a8efe36518abbb0f713bf375a231f78c8ff8546087", "TP1": "040c372eb1fde0469fafc255846f84f0e7e17fd610ac847945d587e2a03c2516920f7a378b51ff6df628bebd0caa3a79d56e9312766c2769047e62e10ee6b9b9fc", "CS1": "04161e8a96b52dc4327f42ef82e4ef05ae3a54d59859abc3c57b209438ca31ba44154bf5551ed72feea1ae9055190bd0de3aa6c1d13197819f61666de9dad0451b", "CS2": "041ba883a3ebe79476bcf877dce6acbeab59371bd012ea7b1df53cc2100ea54ec51422ddfccc5e157093cbb30f63281fd801616cafbda67bd783fd48091fc7d693", "HASH_MPIN_ID_HEX": "de714858ddeb1609b5fabc445214f669f3730118f5ad7771e1b8c5287852907d", "TIME_PERMIT": "04085c93ee7d8cb3a4df466d2ec5d8584a8dbc4b2830ceeb45e449da5654e2fcf20cb32a10592e3174b8d1dd8ba074ac8ac4c42590ddb37a96ea2fcae5f94236a2", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33395a222c2022757365724944223a20223462623937386366363835363332633634366534306236613762326338303737406365727469766f782e636f6d222c202273616c74223a20223235386139326236333361623033336131646638306465643263346531613832227d", "TOKEN": "0401f75d628e9fed80b2d19a7aa7f970984c4950b85a458b7e0886a49113178f10108bd36450aab4e267c3db4d22e3b2633d8e15ca2ed23d2e66712423e8ea0fc9", "U": "041b264efad2f12f3afe94608bcb8c96b81927d89401a5735d4cd15438b829087103ee70d8e316b7cd25d7baf22673239757b74e577efc1405c3e924a6552efca9", "SERVER_OUTPUT": 0, "V": "04200bcafc7fbdcf7141c6aa9ff0f13a4d33c9127d0f8929771785d01b7ce5d6b401da5e377f4128e174b75690ca65be128be676cfd667ad6cc8cee5e76c562fe0", "Y": "0c04e3c82ab3d5159a9c3167009097a82e5bbf9a08c933fc333ae4862e18b012", "X": "0dda4d842be993283453e769f1fc8826e3d06f20b10caf16d6fe9ebc14d9e186", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:39Z\", \"userID\": \"4bb978cf685632c646e40b6a7b2c8077@certivox.com\", \"salt\": \"258a92b633ab033a1df80ded2c4e1a82\"}", "test_no": 62, "UT": "0417974b2b6ff552694eee4e685d310d27c08c7afe8b4c41a9ca195ce3c79e0ce90494e4c68fd214956e978ed1ac91d29cf0355cf834d5073920870443e0148185", "MS2": "14f698cb0982c5b82cf397b37623a47637651808ce1f54eb7fe6a5bbc7af4939", "MS1": "22ef91790d25c64339868e76635befc2b17ab282ba455463c64360adf025a871", "CLIENT_SECRET": "0412b074d78681ba9c2150128a51a943501d06337b1eae1a63b12060670a5ec2a40bbe59e1ed64bf7811f4becb7adea1cef10db7d9088be354d7abdbd56a5b1bc6"}, {"SS1": "1a9b3154fc71e0ebbe46750ed4d5bf28aeb9da6aad03ccf6d678d0ebe6133d3517cfb30aa117dc0effb5249264e384ce2b3c77d61e44d5b201c730f736cc5f990525d07dcb79d68ed6d302df885787a0129bd998c69e6a3f860e88ee5a91bc7912c3f4ed92c794425d252cbffe0272720278ef07bdeee340936f0d82b79257e8", "SS2": "111de1b3b9a0141c0da73bad2e9767f122a5ad365379fac1e1b78946287e890420158812b01b8c0ef71cc4bcedcf4cf229a8123b42248ccd8b8f05fa9fccaa0a12a0757345636a8ba490cb8c92326f5a52be119e35bd2468ebcf15e7710759f11b6e01a21fd7dbca13e9c479c0d1368111deda854e8744a1ca121f23d6b2c5b5", "DATE": 16574, "PIN2": 8298, "PIN1": 8298, "SERVER_SECRET": "22de2450a031c292d69bdaff6d16cc9ad0c4f155b69ffc60da2b47c0e28153b801a0216a5b170dbeea728dad1cc31c9e29847cb8e3c369aa437f42cb8b5d6ab60657d4db2da70eee8e2d013a2e5476e1b8c0e40b5b382a193a4b869792d51a181e72c87baa538df39f1124b2b7885c5fbd35c0f87aa8b6abbfb48c586fcd9ecf", "SEC": "040912eb6b9ed447ea8878f592175a6a2fba95e9222112b74c95cafa330709a892166d4bc45c1b7a82b910288293c742dc1bcd4e4d6e239533d627ef74fee6dff7", "TP2": "040f8d144fd76f9a19ccd82db1fd8e360b6148e088951f850e455c7f7e5dc503cc0e1a02840e83f86fd70fd43684642d781e06ae8f5be8eaac115840c3342c18fc", "TP1": "040b5482bcd2ee216b55158ec5c584d7c6c2fa5d9f5e0224999b0c655d9d1dc17416ce6af0205df57bc19f4bba71d7128f93e5c1cbce2c55c2bac358ed24276bbf", "CS1": "041b3ae2f4b46a899b7aca9eda29151fed22aff8a50301e73f0165f28147535b5c15a832ed5c0a59a93ed06d8db2a479cdebe0ead7174bb1ae825952251b97d93a", "CS2": "040b469509a0aed1ae753e6063c334128161b12fc1e9e71e460196da7a7202f3400954877281397891f3520942c7657e6aaa4eef7fd238b316399ae40e9dabf76f", "HASH_MPIN_ID_HEX": "5bb3ab50a7ad9847daab3a3d865039fac16a96893e887003ce2319c5de3245e1", "TIME_PERMIT": "0409cd1b0420f775bca4c8b16d45e171681ade74fac91e7c6d894d4d1d55edfbc11de7c087c939420cb725041253138a3344e32b6b23951c50ca25e059425c27ef", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33395a222c2022757365724944223a20223965316332386337353864353863646366623963643561623566376334303335406365727469766f782e636f6d222c202273616c74223a20226161643935633238353539306137666133363135316464393366646263376366227d", "TOKEN": "041b392a8c5c5d789b913598c91996aa3aa71879e5607d8e980811372db7af2ca61f6eb8fcdb1704312c1771968dabb2edd69f0dfa647701c93914781209588afb", "U": "04094d04f4e0c9f0d1c865ef18b9725d6ff33a82bb954be4d8377900204dde792a174e467a8a1820552b7e8010d0899c712888174217985a55bcb3332842a0213b", "SERVER_OUTPUT": 0, "V": "041253d5a5b2753c9bd1e0ab2ab1659fff9397b0c4ffe905f60c1c1b381d48056c1f3f428d51dab9b0d0e966111b2c6842d28a11fdabf17f68992a95d771a87ff6", "Y": "1cc615d41e731ca68d314047a945dc0290e49b6565f819cfba4c18069df4e1e1", "X": "21afc146d072c6071488a4777feaa3cc33b636651d4223168c2d693e1d3e221c", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:39Z\", \"userID\": \"9e1c28c758d58cdcfb9cd5ab5f7c4035@certivox.com\", \"salt\": \"aad95c285590a7fa36151dd93fdbc7cf\"}", "test_no": 63, "UT": "04004455a7534f80edffb58f3bee0985bb49b0c11691ea8df44e3c8d924d51c4771f83128fbd97b4a1e8ca0280bdfb315674f036ff72024f3245449710cde2435b", "MS2": "1b5f7c62b0104aebbc852b6559d543025285c82f3073821d1161a44c7a98edac", "MS1": "1fbc923357c92c1e7dc75080d012498324acf55a1e6ad48a632a91acbb706edb", "CLIENT_SECRET": "0410866b1e5364d7ee68c3f511c0b2f4aff5bb0cdaba3850a3d74d262132b5d91e145912bb6bfd6b4b19120bcb1e0bcbdb53b84075f90b799d604b3ce20a647732"}, {"SS1": "0c8ff041df7d6acf53e94165dc468967b5b1113f9755b728691d5ff5e2a550c1096640178c8947657e286c620007200a160bf32e6d4080846a2bf3de70910f9a1fb859ebfaf5ddc5055ec78c5c95f0a97b7002d8f1c7762b6899dba59d1a6ce11a1416c3da1ea4769e814be08fd193b4d7fccaf4ecebdc13817a9ae1741a91bc", "SS2": "007ba3dc3eaa11302f3361b58544983e980024e27f1bc08474f8def9cc930e9812da860653250bf713713cfacb956488367787e788fa7644107d0fe2c8c12e821bb4f3e100a5eb8bdf986ff3944a23e8660b3e4c6550d4c12077f69b0e60a2960147978ce76956abf1cb8258f29b64c6208ba8aa762d5896022e6fa8855367c3", "DATE": 16574, "PIN2": 4890, "PIN1": 4890, "SERVER_SECRET": "0e0626d874074ec9b2d2d38cc8a5cf468fdc261868365b37f70981d2375df7f008c5cb476e2ab3c9bc934c59ee29a2a24f47ac0883f8b7ba355bd5cf0a5d93f519a31562d6e5fadd60585622bad1d7c6e31419530e56f5e1f91455ff7e9cd6581b5d24f2514f03b476250d1a2dfb5edb4a2dd8ee630894dcb99649ced8300352", "SEC": "0402fa4b0b0b4bfa7b1ddae421976825adcee50cf96e314254f2bbc65611ebe4a91362710aa19dac83f9547cf0a954f18c03e3b745fddb4c1bb1091b0f88b7a6fe", "TP2": "041ba387b873363c94254764366df23d0760bc67e2d2f948c9bbf1400bce99dbe20a96d96066991d8e664f5624e50eb9746fd0dc91a4f26ade1d3bbdcc1a47b960", "TP1": "0417ebb4bb4f99e3c6df2bcd28a3aa63565c976a8ac00e4c11f194122a135557441218c7102455601d085419a43d343aae59c5575396668a5a0466fb6280d60a0a", "CS1": "0411324e749c16d2862d9c7d10dbe7bdd2427d1a68bb8fbabb48d9245a910968131a6bfc51454c7f553c1a3d8b7c0bb27e7f6e41e161af0ed3bea87048e9da76a1", "CS2": "040e7b7163a9211826ea91b17ae2cffb00470200a94ded871fe4174e55faf68dd31568e6abf77b5a8a209877896d39e416ad04b3d98f1cbafdfb045f9919231156", "HASH_MPIN_ID_HEX": "60c35acb41061cd1715b8d49dbde73cd92928ee28126b0c202a6f365c5f33d69", "TIME_PERMIT": "0412480a66542e349e3f791a020102499a7613223710995ece0b99858245411d5c196930806537c5f9bcbd1b18955aa674b592bede0ad390ae3839ff1a76fe14b6", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34305a222c2022757365724944223a20223039303166333237393530353963346665333731383263613161333435613661406365727469766f782e636f6d222c202273616c74223a20226339333734386639303766376530623863363763653034366631646530383131227d", "TOKEN": "041f3e7f3e3251cfc75999bfe24fc00ee1a5020232658c28c5e570edad8bcfdce209bfb562de769c589f5115421b6873b9be234e96664f393b33d3cff5c4d9e6f1", "U": "041efff6b50f2e46f74ff8c07b2327c18307e18de8e435ee4949e97ea352d47ce50cacce9f48fbea938df28f704cd2376f8159f9b12c4075b956794ef3c50bc872", "SERVER_OUTPUT": 0, "V": "042386010acaa3a4a24de7a69d262d570bc08c86a0686e2a8a7401069c49c3f6561bba0f9ffcbbd848cf6b9f653351c6d96d3caa837c0364f050635c251fa2369c", "Y": "0193344a406b0a6480f919b3f69bfd6498ebe8e8ab7de7407dab19b42d4816ba", "X": "18cc7acceec1f5e884048efbab4ef0293b66db33fa44e4c3a126662f321d7f99", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:40Z\", \"userID\": \"0901f32795059c4fe37182ca1a345a6a@certivox.com\", \"salt\": \"c93748f907f7e0b8c67ce046f1de0811\"}", "test_no": 64, "UT": "0420692342eb644b4e9e6fba22c3a7f0c47a43005298403728dc0884c7c8023a051f4f1856e60b59cbcd2393bece40c3bab35250623135abeead9b14c0c7f4ad72", "MS2": "00768c95d4920c3b67235e52a6e5f98800200d162522c248e5b2d57ffcca6663", "MS1": "0d768255a85a6c2b29c7b37e2f92b3b2bb37ec4768d1de52e33354b9618f9c7e", "CLIENT_SECRET": "04170c7a1493371c9af51d48aaeb6b988df750649f45b21fadd62063d78dd3634506cc1362970c1d761820ace7427e7dab10b9a91873562050dd7ff2679afabf42"}, {"SS1": "102c657bd161fa87891f1157ccead78437093b25211a3c021725242fe967e14b032652a956755c955b602d74cd7fd53636fdda3579353b6461bb81cd6850ed01085fbf39429c8e0bd4c1fabd24b0d41f24459fe5fdc5bd976ac9f9adc1f237100ad02829cce0c63f5cc0e78e531501d77e4bbb6c4f5c9281e77ded50a2a52a37", "SS2": "0a679ad8e408e335651430c573f4432725f1a38e2427183cdd292410d5ddb14e06b8cc7f2b6e3a23adc4e1742eddec6f5909c7a722509aecfe2c1dc6494b8f1b06f828120482d9348983816d4dc4bd01cf6d468d28286b66a5059f9eba64bd07164493005ff31ab060547753c87c059676329de3714c0e70ec04b2271c221c3f", "DATE": 16574, "PIN2": 8677, "PIN1": 8677, "SERVER_SECRET": "02408e031d9053841507accbbe0f8cdcf5b477faf584534fec6f173057875cc400a1fb404a9e90562b99ae4be37612a84e3943853931e8195051474e8aae58f801cbe9a05668d95acc8fa03a3adc1fa5e0d92b51bec475de915f6c004d49f88e07ce3fce8ee22dbeb9d295186c6e78c049e4b4610d6d7c1da3cc3fa7b22aa63f", "SEC": "041182512deb0d6f2218ccb59235c7bc02f7b993570f7966d33d4303ca513ab39a073c1340116b1c787cf2b7d584971bcdd37d85a6f09d75190fd1acbd42e18dae", "TP2": "0408f0bb0edbaf1e40e157c1d2897dc68ea4c401f038db8a35eb1133f580eaba7009902d8e6f0d4d6dd18efae87d3ccf2ba73eb3063594ac8cf2f845113b349792", "TP1": "0421f1ad17ae3bdb946fc818e67f18bffbb7afeecddcbe23d1b15255029e23a04006e981321c5871ddf21fdf5eb14ee08abadc20d1747cb0c2891a67fd92817ab8", "CS1": "041692591a78f5f89fbc5f75cebf7ae408ee2b1791522b4c536a47d4c86d1b7b390fa054f5cf8c4698005b7cea1a004cbf61a3849dad90c77fac9f3311d97385fd", "CS2": "040ba7fab0c75d7a79ba86711b978ed7bea2cb381703442b52a019da6623dad18f12f43563c785f09295de6a95fd67d0bc2fb71e5eb7a4b1c965effb72544cd074", "HASH_MPIN_ID_HEX": "2a9b4add7d5afb6c9eda237580f6b2057dc8db232180ad4b4f7ebe7537542b1e", "TIME_PERMIT": "0416e131abbd003e633f4d7eab8598abd58690424f182913f6affa6281d19ac4621978a60265b713556f9d65d7d10afdd58be6ae4e65ba48e3982a0ff523b7e9ec", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34305a222c2022757365724944223a20223130373435663530333536323038623738353664303062356563613131353234406365727469766f782e636f6d222c202273616c74223a20226137393639386438323961323164656439323133383431353530643435623862227d", "TOKEN": "0403db3a8825d222584fe249015c839105ee753c3387eee818d975d250dfdb93051557ba90dea7940426e62c17137db878a2f09ff21ed13863664ba4a0f67150bb", "U": "040367799c14a01148f89ef5710f8e5a533ba9e5d9959d561126498e3c0430630819f8e023e6920fdc1f00aba88051080b18712ba628ceba9e6cd5c59e99d62b51", "SERVER_OUTPUT": 0, "V": "042376accf278f06f71dc8343214201f2c596413f050e4d5dddf6a69ba9e56494b17448cf2b3cfdca05d8e7e9498450a50e0d974af0a724730fdb9580952f305d5", "Y": "21c4af161619d87628e94a2b5162be26c891953ada89165700da4efb6a8086d1", "X": "149b777e05c30dd148e3a575755629f022bcc4eda97cc0947084e22528ea7b26", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:40Z\", \"userID\": \"10745f50356208b7856d00b5eca11524@certivox.com\", \"salt\": \"a79698d829a21ded9213841550d45b8b\"}", "test_no": 65, "UT": "040318869adb00e4874a8cf3c71a69ccc2a4f091eac0ddac65f4d390294d3b5fb81fc16b8d943d423edb6f5b697d5b264e53bf886a8a2fbebc8ead8bc1812db723", "MS2": "09a216e807031f723aaffaa828a2c9ab665beede3032a8fe4073e27aa5a1680c", "MS1": "0571ab35fd954e83537d560c7ee88dfae5bacb0f6b673d8d68177a5fc398c6c3", "CLIENT_SECRET": "040b21d43e466376d84a650166d61eec40472cdf6bdb267e9a0640a104ddcee37216ac10339ff86baa4191c76cc91b61a96ee7089a5b5d638814509daa255a9ef0"}, {"SS1": "23bc6a3fe07df034ea298e4e0564c00bc2c27d3383e7fc8b0acdd3bfdfd3a8b20ac49993622bdce2f5b5aad0bf37e860c9b8ef844650746473741efa3aa40c3817af84f9cd260b6d53ee12378a0d39fe844966e7a16b72921fac7370a573d74813b8716592d46487486a469e1c03c44f3aef9d01703c871b6b9bca580a74c2be", "SS2": "061181e78446897e743ecf1d7e84a9e6f251030a883abb6d9f97f87501f24f5e14479a324f148796d632ecf7e8d0bef693a069c7c48e96479e3057ea40c0d1eb15a448c83f75c192df534404f126ebc6c0759a58cf658df7a2f9372505845936023843134b7386380dd7c1de77c62a31c4c52207bff70d06742c837b74d574d4", "DATE": 16574, "PIN2": 438, "PIN1": 438, "SERVER_SECRET": "14d1619e7122783132b1cbaf9413f863dec6b1793ae625602231beace66b610d0a07e5b3426b84aa56e92d4034b7f045eef66729bf47ddc9ff8328d2909eb5a52093f1222ab3da4db78be4c9c959cc035f8acd808b40106aa4ee81d2a777c5a012e64bf67923371620823d694d7913c4452c477b9fde7c74d13d0084c6992bcc", "SEC": "0413a0aaf96540a29dc76b3691556aedaef07055014629de82df877a9e4a126e8b1772f2f04abd8d1ac5eba2e359204ca387708d097e7d482ca4efc5b58cd1db2f", "TP2": "0401772d1be6007a017d3dcb0095ad516fb11bb5df9244d9569e2baca1a77fbd4d0c8866836035068716668fff1492514841e126f95301ea91efa0d9ab19ec6846", "TP1": "040c38cad42417a7c9163f078676a25dd7f2624b5be9c4a05843129134b33159330fb5b04ec92eb13b4f257b50c03c3e5c488b1f109128104bfab60812d10075ec", "CS1": "04166981997b8ee717ce3f4e7702fc340efad3bdeaff04a83a3fac5f373550c5e81cfca49d1d7295fe542123e0a919ee1671a8447ae9ee0116fb905b673fa48713", "CS2": "04105fd64893c85121600573a7a1dd588c958886bba0d199f0001f4a317a9612581cb11a9dbb55b89585696589ffd9eb745ef4cf77093cbb63a218b5e99f82a982", "HASH_MPIN_ID_HEX": "a9700fd149d65d569efd6c1cbd59036598fc7b638792bee3d321524b8f87d9e7", "TIME_PERMIT": "041fcddc3b6829e05e296d29e146b4d5053ae9e7d0ac77a3554441cec8f1a12f2b0e9948b7110719391ef174e38908e87adf814ebe9b320b6b179467ac87593a74", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34305a222c2022757365724944223a20223930383965633736353862343838363863653932666462643862313534363362406365727469766f782e636f6d222c202273616c74223a20223565396533623932343337336566656361636436646361343837303933356161227d", "TOKEN": "041bb93de440b9c755ba2e35ea46fb7a6403cdff4d390591dd5bcbf31f8a31f4431fbe91b52f038ad19a616831c8da71722f96cf1834b37a6b131ff46162c42425", "U": "04167ee0acd0b94f933e70b88397d8b1692fcc31b830bd9f8e93dac3f664c0a0e30972ef2402183fc71ee2d073b70a6a46209c682be4cfda96ec0b7c3ad680a52b", "SERVER_OUTPUT": 0, "V": "0417e7be54bd19e23a400d667d0cd62f4a048497cf32c009d62aa0699cd190617a18da1598267f93ae27436ec788bc55ed1d8400a49eb2ac77bc0bc4965b4d686e", "Y": "0092dd6621f52f8dc3d0d10acc9a6644757191bcb8dcefe4f2986aa9bb42129b", "X": "2194eed73752a5a5d528b8d3a344899c038a89f36821f387c6eddcf1910b4e38", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:40Z\", \"userID\": \"9089ec7658b48868ce92fdbd8b15463b@certivox.com\", \"salt\": \"5e9e3b924373efecacd6dca4870935aa\"}", "test_no": 66, "UT": "0422097fb8c73a51b6d688745f80060fb668b217ff3a6e9beab113347c65ccf6fe1ca9bd17d45fde96258024f8f80f373f1240957f60328df020bc45846ed0080e", "MS2": "1828cc085089899bf73e84bae712ca4811d44abac4ed6fa84f6b081838c78033", "MS1": "0124571350498a74cd4ac21e5793f25b80ffc6a13e9ef787d9d2f4dfe287e9cd", "CLIENT_SECRET": "042173bff2ffb78abc404cbda3e63d2bdda4e7d5f3043bebff0ac6219688ed72210d05dac39dc0e933a56707fbe76f9b291ddfeadcd665e33dfdec7b42670b52c0"}, {"SS1": "0af7873ec74b70ad8b70c9ee9707d78ba0cb4ea3a5262aa6d45328b19847b7fd18c69806014b441ee563f7c5716413e91d5c6dc9e8163134d846d6c2b9131ddc1680d3f411a853ffd94615f8ea2731380baa2ce0f46f7c74603d0b0f5a5666ce1cc919b403b375c30978119ebd9bba996c49313eb488e403bfc4348dcc979701", "SS2": "09684cea3192969f229d6232fe38349be11efe312714760275c75142b20de5c3146556c590541e110122a74daff6a277712823f5f13d10c9e20cfcda6eb43e00099f3191a7c9b5d4183767c07408f18792d0211f7d6b776461271c98e7fa73070f1b2e0194c8de3b1d5eb4cbfb74880b025014636872d579888a65b1da8f043e", "DATE": 16574, "PIN2": 8966, "PIN1": 8966, "SERVER_SECRET": "1d5538cd079d15ffc719846d546dcc4ea728aa46803de23e01354cba596849920a86725c2059c9f8e2983183ca139e99a4133432b88e0a50cdfe3282a5d2cfac20326dbaebef6164cf4f8e2b5b95c70154dee71b14a307843a46d1cd4fbb476d093e6f3db4c8b24119f893781df531ad0e1dc8310618d9a4da2b7ae63de47342", "SEC": "040411d5530e9af5f9807c50c964c1814108da746b9a6466536e36b84d1c80c949149f2f19391b88b7b1259692e67aa52576f3896e7776995bd23224f891e77809", "TP2": "0410f8f1816f8b93b465ce724c48f3742a1add38acee41271785e64e93952deb411f99871c976067d2c81e0df9b341699e298458aff7e71e1eb6d4b80d3dc827ed", "TP1": "040888ab611d77317034ea1788ef312485fc6d5007a6697a85b8061a1ee4578c620f1b9aec2b0fdf1d006da54727376dfc83e3c5c9285e420d1b395086a56cffaa", "CS1": "04084e45872289aa2567e3fe438ea9a64eadf42c956153331e40ab34dbcb1b0f8b087c8acdacc54e8c58c13edb4791fbb1b06c15974973a29a7677787aa29898fc", "CS2": "0405897a9bdb82bb9a72e474e70290bbc4f230c973ce91a6105df55165e34f43b104d10479463f2b094c404f05222f53cf981debdab81d6b360fe136f3afff2fca", "HASH_MPIN_ID_HEX": "28537c17f22db169ce4e26c51891ad2b5423de2244eebe3e8b349fe790e3b5ed", "TIME_PERMIT": "0414be024db2c7a1c6819a655830ef19f074ed4ff09589908dca2e94c5531f1f101d0797ff400478afbaf5fba98e78024bedf9c5a3a8c8ad8405ae2b18f9acf160", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34305a222c2022757365724944223a20223035633764356630333236353962663664363835326130663430643732613165406365727469766f782e636f6d222c202273616c74223a20223335626366336536646137303864636664323563303230383061383662376633227d", "TOKEN": "041f1a21e87fcd719c0aba93a76f322572a54df2111bf85cf037e307de9ab791fa186090f4210d2c5d4e9bf816be408b37b6747d07c60b7b85ac20beebab734482", "U": "04147718a47badbd0695701d19b2d1c3d91c5cdb97e2b8b27f03c6eff9c1d35afa1f80331f864540eee246a8313833b69a31e1604056fd63ce1331b1215c0660d3", "SERVER_OUTPUT": 0, "V": "040b7470769b6e5699e79450d46b808361f7339de8524359dbe1137c6e370ce66c064e21871e87a9b295ea8afc4c19c7da6c7988208d51e2b05e7080e18292c489", "Y": "03696268f9732a6b118a5227e29ddc9acf6f7f86da8b88c31a61dadd082de4c1", "X": "0adc1d878efb791336d2012b422e3d5a9f047a01efed2adde2bbabdfe12b70df", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:40Z\", \"userID\": \"05c7d5f032659bf6d6852a0f40d72a1e@certivox.com\", \"salt\": \"35bcf3e6da708dcfd25c02080a86b7f3\"}", "test_no": 67, "UT": "042141c6d18f1b1105a44c70828f5deed7be58938177cde1a3d28bae9eff3d5f710c0dcf9a90332aedcb5b7a414ba76962a677d7defb24ad942744450d04d10892", "MS2": "116aa8520b994a5145d1b989bacabb48cca6b5b0169243c2d324cd44a41a2a21", "MS1": "1a62be593b45c2ccf622a820734bb15d59d22ff4467952a8d2ca6e6853baa828", "CLIENT_SECRET": "040ad2dfdf4ca42bdb330d618dce1decada2b85b95ae02bffa65d7a7e7a96c866e1d3c31ac71437f89eb2b1b9284c2326c4b48c5c77c98c51d3584c4fcb42db891"}, {"SS1": "204bd6d3732be604794efbf1f31ec9236912149f6fc20087ad14fa8174910f8820e3ff6e6c91019859ab4aee87a90f03d4e6c2d2c477b2aa9a307f9c0491530822bc06135325422d3d1e5858de216ac7ad5cc588ca97585e675a8618f8255bff01f33eb6a733b8a375f83488413fd2cda487d270f8418712bb284b69091df1fb", "SS2": "23f6e58bab031a9dcc430d22d3aa4bd96c3592078d375b6740a1ba02ab39bfec072232ea8c13fbc07f10349b72cd1f7ab034f55c8d1759a4997196ae55d470621df9165074109dc3464d809f4729211c106ffd82706445cd88140334861a6f4a1895655377315d97367400d58b6e687f44de5d2f345d256e5eddebe931d4a5e8", "DATE": 16574, "PIN2": 5893, "PIN1": 5893, "SERVER_SECRET": "23cc86e35e6f6fdabf7273a30a2ba6a4513c3008a61685746fb2ff1b4f5ecb441848c384398ed43b540317b821ccde36ed8a2ce91b3a6b15aa557b55da03ab2e1575337d86c320f8eec56b386767c77d16623c31afc2324b5161aa3f76d0b2190ddec88bfbbb9ee05d036071ae04422f51f20311071034f28f635f0b6430793b", "SEC": "0422a8d092504720cbf6de7650cd80d3d66e5c90094d27c9cc7cc018c6d8a4fcdf135938eaab5e36d7fe879a1a977a43ee0c26074baea9e50540b9f664fdf4e49f", "TP2": "04115a5af992c88f429a189206a2c18be390ae8a8dbe200a86326ee5018d84f6ca0e1684cc768e83a4eaa87ba875a6037bb90f146ef0648b5e4f7abbd3ff2ebbbb", "TP1": "0407cebb6f0f7d21894cf65a5e39122e8eb7dbeb02fab277a6ed5d2dbe4db291380eec7a985b93800bbf099cbdd39595c369855853a3cab4ab54598b2ab09e955b", "CS1": "040a6070944ee1eb8452d82ff988fae3a4a5111caba81b2539765fc945dd41e28b1659e232bc8601f2ecc597c6a0f5ae6abb791e8b0353fa77248e3cc4616e0a3e", "CS2": "041e6f4259f0648da2332a1adaf0289b2b5aa582cba76c3d074e73856cd4c6cba716623205277d2db9e3f011f7b5ad0a68cb0c79f3679dffa2c26f7f657f10c730", "HASH_MPIN_ID_HEX": "abca69e8daabe88616ad19f224bae387137d3f527bfb4a03d20530a82b5f0261", "TIME_PERMIT": "0416d30c3ad582973c8463b46d800a6995d506d4793e0f79955ed2b551e5fe998a07849fa62cbd14053131e9addeefcd144d091d0f88edab5da229709a5a5576a8", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34305a222c2022757365724944223a20226432623736646365356434623633366536303837646430623961343830333365406365727469766f782e636f6d222c202273616c74223a20223635646365653063643132303139643965303561346335323934336632626164227d", "TOKEN": "041913751ad89e733374387ffb4668fc52f36eab572e7c2468a6873a7d3337c1e11f49a745be5dce7835dba9110f336b9304957777dbb365bd37366c970a82858f", "U": "040768cb1393625afbf9d4a8b2f4a4e7d6c9f6619bf3fa4c842550d51aba199ce51fe7f78c1f08a5a1b1f7010e3112f50b5756281fe1446792bcfb2bc16a879cb9", "SERVER_OUTPUT": 0, "V": "04070b10018dc43a6386d5646779ffc8a1232057fc5e098993594e75aaa7b133851f29673f2f557f3f2483dd32eb201dba7310ad931e90648d0313a5b0b32712c2", "Y": "20230abaf21a3c89f4b6aef7b2124ed8d9f7d6b5f80d5f1ca147e2b9ffa43208", "X": "02a848a5f9b4ba9b8aaf8bcc06592922adf9fc72039c1ebb496251e7b35d74ad", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:40Z\", \"userID\": \"d2b76dce5d4b636e6087dd0b9a48033e@certivox.com\", \"salt\": \"65dcee0cd12019d9e05a4c52943f2bad\"}", "test_no": 68, "UT": "04120a7126fdac5ed69e7b418f816ec3f9d5ceccc363e1015158a896877a7e0b7e1ed8e5b1e75c1a34751f472734ca241c1299e734fc77b23eeae15b643a499eab", "MS2": "05a465d9884764378f03cfd23d3ed5a53990b81a43565e08999381eea318e4c9", "MS1": "076011702a4d318f493c475a0169b75d8e170e85b7c49090b24b261812645e36", "CLIENT_SECRET": "041174e40adfa22638791680345790b575864838f860ce25e1df5cc2503617cf300b72f72f22c98dfeaa74ea9dbc99bdd251d32ecc2c6277374cbd651b1b59b1eb"}, {"SS1": "1d4dde0d5bd7dcfcee29ba50d4b9861619ee2c232e0a4f1642776d669b2bc14b0864608c865bc73af3d6efe08537f9e4626e849db38417c5ef3c7da5f103b1fb0dea106f6cfb1d01eeeef3f5c233336120ebd205e1554389338b8fa0b2d927ad0ba8b734f80b9ed107dc5e856fd46877807a96315329345c4cf1393ec4738eeb", "SS2": "09a206e33907751f06bafa3afb7d497e80c1ad8b4d870d06fea12438ebf2105b18c11138c50de0712510af7493cdb7f52e01e2b63cd39b48817de487d34915642005577f51bce85f4f49dd8431f6284a219f80c0f3246946cf04a332dfb4b2241e55586a4f9f4c6f95f17abe02c931e02a5eda9de3b786aa3dfe68dc9ea41dc3", "DATE": 16574, "PIN2": 6773, "PIN1": 6773, "SERVER_SECRET": "1a2cca121e8d787bcd3f3b541d81265bacd7ff4bee4b40b24414411540413efc175d92c140842ceb664ac14a200cde437c67a5ad9aa5339ebf626b2f3581e75f1855bc5030c509fcf9511adde68a4c874b5c0a4d56041c05331e0b5304a22a0420b70b692318bbed3d049fd7768101715b16ec36c321dfd56698cd2a94e42509", "SEC": "040339ffbbd5cb2cde91265261bc9ccb2a0b80c80e097a0062a93bdef01e7e43dc11de58c9e2c3e5148c43eca64f114141f96aa2324a802433cad677c41883ad09", "TP2": "0408fb394128989e758c57f50d9bde5ec3860906fc16e3e1d35970dd8376e295062185ed97eab576ed3ad4fdf2c82fdbf16f5ccb0ec3cf95b3aa268c1bd12e43a5", "TP1": "0409e25d195e57f2d70eedf24e12e5a39a44bf57dd77c55fc73052243df47ad21201b45bdf5645edf2fb2f8d872e93c5d4ff850fdd45011d81c7c3ede0df70fde7", "CS1": "04098381b1cae0f2e9f4316136fcea99d2eb2cc05b0e3713107434fa65899d1d54158f692ab0c375935dcef1f2d24463df84e6e487fccc47c2c7c1792463fab644", "CS2": "040cb897b943623607122c6269855a50415813267e39fb42bf34244886d2f3bf841b7c1654fd40bb1fd3a568e01cea415f52fcaad53d6107a476b78052fe1c47d2", "HASH_MPIN_ID_HEX": "03503fac344abeaec6884b9346298405573171773af2caa64c7b82aeb4db6c85", "TIME_PERMIT": "040e120d462348e8c36507506cbb1e1ac00ab2d063939b2e59f8a4bf01ea3bfd2a0f8aaca57b1110ba20ed22db84e7dbd3c2672f88ca54e2b7bfce87a797503a3c", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34305a222c2022757365724944223a20223833346337653434623061353939663335636633333430666563653164663836406365727469766f782e636f6d222c202273616c74223a20223236356336353834306564666334333238366230336165343062313339346633227d", "TOKEN": "042289479fd0c3ff1c01888d5b1c583978651836b9fe0c9b3e6e8caf1879e54b9313042656c6e9c750d3d925b45eda697051f214222ec8d0fd44e47f9d920fe483", "U": "040794aee464e8b09439fc5ab90fc784778bc2c03b8a4388843c172e2d3cbfc48502491252ab255cf62551b1ebe74468df369fd75eea179b38ac01006f790488d1", "SERVER_OUTPUT": 0, "V": "04150dde0a9cf4c7f7f5310110116edc3a202909f613731c2771d213d092a217e223ee72d4e4a2e8f309f93465ce0b13b3dee710a76f31d3dbc0c9a5ca1c1f4d7c", "Y": "053250c9ccd29dd61f11101fa457873bc69e8f9437ba824e52662c21841fb0f8", "X": "18ff9690fb82cd245c3646e679e32aead89b6a0565a53cc640ed6091fab34889", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:40Z\", \"userID\": \"834c7e44b0a599f35cf3340fece1df86@certivox.com\", \"salt\": \"265c65840edfc43286b03ae40b1394f3\"}", "test_no": 69, "UT": "041fe272f80651371e00cc23ff66935eed19f38c30cc2a7289878b83834eedde12148739a785b235d266fd6dc0db09c6f843282e50a8fcce06ce9a6056a913acb7", "MS2": "00af7c3a6c89d6fccf52101d7acb1672e397d68027eee47ef6208c33ca9d5a52", "MS1": "115000ac71d885c443e54b4d30b2c05601f9ff4d6c22aa79e4bbdb8a2972b0b7", "CLIENT_SECRET": "0400507f2cb2cb01ac088e02136d05f59ad0c2e9636eaad56f69d62cfb8eb5fa3900e74bc3001ce14bc993a48a3e780d0596888d15db44ce732ad95f8e34a45f62"}, {"SS1": "1872586fcac7f9ec2378179a6b94d87cd7dbc88df7bc5a076c2730b76580b1e20f35122b840f89574714f0a3820564288e0f4d066b1e214004017308da939dff20e7a363f7236802b60938a800ee9373ac9bb2d1fbfc3c875263ab5a35105fb91de53606b94679b3fca3d8bc43bf716e5dc732c89276bad3d5e8042e5f2faecb", "SS2": "0e2554f585242d0d25647ac93d29ea1a1ca6fc51f3c448fba21c8547df97d18f1b0838c0c639c5855489324867d59ba2b40d12490e1194bcb3cf95f41bd78a51052584f55303cf58f608d3d73bd982fbd159a0e064a51f1487b00265339c43e006c9b81c1fee8e61501411f3abcacf090b2b28b8eedcdeb03838d05ee879b094", "DATE": 16574, "PIN2": 2305, "PIN1": 2305, "SERVER_SECRET": "0baa4f6456ae33d64f34c7ac3063b5485e152ba7a326648a565ee5df493975371f5fff7adacc964306cc489aa78c63d94d24106f0629d29eaa466eec88d6012c08d9c5e7e37fb05fb5ea3e4d6f1355365423b5a4923e6aa8ad36d6d9e2ef5ee917dce3706b8443e3946bb25bb519b2374c6be07c8d3f5868ebb0c01cffe29df3", "SEC": "041c1d585a6069dd6c89433ddda4bc4353bd9bba5ef72f365942153943c3b3e2bd19b5859727bc78373bac329c8e81ef0e3c8bf8380e2304a2aba0496eb3e29b2e", "TP2": "0415a57e766e066ff841e4189e5a3eced08d188ca125fea68dd2cf47efb16be9f30f54092cf86a919596b1366eeeb426281dad25ceaf904acfa7d90712e48759f8", "TP1": "04040e0a73354295b5c21286f9d2f6f22f00670973b8dbaed54fcf65419f4fd3021935361735d5dbc2b11b1af5ce39ccde45b5cd8bc536e6e55d86dbd6d1aa6888", "CS1": "041e2d1a629653c43a6509963230b0f368d174bbccd79bb1c526abcb2e9b91d549029c9988224f7ab3df90c9523d02782940114276a1f9c094e70c64f89a96be19", "CS2": "042007df401493d50b777f78413dffde09e2552108d8b19bdc709280742b51ebd70c1a46897be2d51c91923059fcf964ec3be21ec8093102abc4e4d233506397c9", "HASH_MPIN_ID_HEX": "9971a420df8871ca2a468b3859e1a538e4aeedd9881d573683c49dab0e95a25d", "TIME_PERMIT": "040d206d0763c2786049d39ca0740134fd0278f7cb2ff26621a01accdfd072c2ae177e8913a3c21156a7b23af1f16a3f96c7b3447e9611608cb5cfdced8bef4ffb", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34305a222c2022757365724944223a20226538323462356337626162323930383531386366323339633133343833353135406365727469766f782e636f6d222c202273616c74223a20226238653762333434373166353964333335613235326437623333326336656435227d", "TOKEN": "0422ab5ce520c170db26de2fa571204dbd9e9dbbf9ecbb1b486a95d220d0ccd71a1e2d2aedc9bcf3929f9b739c341e8b2a5170e55b6b2e34e16d2594edda785da3", "U": "0404958625da6cd947c94f86fa3abd6c36d9814bafa09078dcf192ad6e93e5d2c500cb6d1455824d7c18cf1c7b52e75595068314e7a8f05c146237bdc9b950e891", "SERVER_OUTPUT": 0, "V": "04051236b5a847c0b4a9e0d04722768739ace2d322e7f00be7db7050afba5295421a21f58fb28ac3d82dcc999ba42cfcb7b8907754aeba91ad46492ed00b4c0fe2", "Y": "034b4329e182005e1da22da62147bab395c08099663652ed8a3076826c82333d", "X": "08796585e75b1e7f71a85dc4001f002039a43523b16e50344aea71b9a258b8ff", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:40Z\", \"userID\": \"e824b5c7bab2908518cf239c13483515@certivox.com\", \"salt\": \"b8e7b34471f59d335a252d7b332c6ed5\"}", "test_no": 70, "UT": "0401c3e7cd5d6a0d008da8a2d00cf2edb0052e447b9b5f700d4a25e4664811f55e1114cf880d033a236ba197c7ebf5184ea067fa73217db13d4a44db8bee88763f", "MS2": "155617c451dbe13e6bf3919a275724cf2162e11cbba2c14306135eb124fbc97f", "MS1": "2036eb5fe70a83d543be694b58ee3c143fadf9b0c1bb792aca99e420c715f66f", "CLIENT_SECRET": "040401eeb3752ef2395e719ced3f37fdc113c6ab6cbd87f73818251e729abc842c175951a1d7dab73a1bd8e4c5d664afb9f10083c6769a1a4c1ad02e03cfd5198b"}, {"SS1": "18bd00e26b5f6340ab7dee43b1bd54cea2958b40e2b9b9c9354be8eba33309a10241dd86a1e29bf561276139a78f57f4f62489529d6f1f4d0c124a9e73ea383a1993080220046ba8e7a082f34b241a065a5bcdc7da1be2d9209f66b75614ed7a04048207631faf3f28a1c90b019c34a38e8b36a2f8ab6e25a738888eb25364bb", "SS2": "1815205f091384a8ed8754474a0101770bcacddb1a36b66b0f8bd65b147af8ed1ef0661350899fd67c1ffa2ce3aecdf3d34ad88839bb6dccce16b6e24a65faa710b6023d7e4d039e23c40756d5dc7c4ee02682b022c207aa623c47e7bf3aecb00dab0e640a49831c3aed7b96b4093f7368a00e4464987ce0ba1adb762b6262df", "DATE": 16574, "PIN2": 9018, "PIN1": 9018, "SERVER_SECRET": "0484433b827728cd62e3b2f5d09675ea3167c5e16321a63c874b4e351a2721b90754827d145e4c4baf01337aca449c8d654d8ec6760c23fb5556cb09c2b9f37e1a498e9d6d344c4054c80bbd74d53522e557c5fc8a3820408b93fbbfe732b8f211bb369902687f87620246d06c85e0b43d9df7003534975ae7b26e6b7fcf038a", "SEC": "04111bcad54f9e08606252d02033da70a0f283086dbf27d6c76db16329f345f2f5045c8426d51dc31dd4055b22bf36bf17501043e8d6e01f9da808e605ec0ce1ba", "TP2": "0410134e79cc83cd6822b7a260d32a99397f1749868da9fa58b466e002d287aac3212ea602a26fda13e5c46b358ca35d8acbbd5fa4c2d8238571f6755d09643180", "TP1": "040e915f629e49a46257c09ca2d3ddb2f543592808cf57f3bcdadf6ae40cc6c2641d43b2fadac099c3af1df94d64b465bcaa54035d6b0f7e804f2752904fa1287f", "CS1": "041c1a64e76f1e0831cd4985112290efdac44d412da8efe94eacc16ae95170649209d8e9c964b56f5a45748ec1bb9946b4615b4fc35d88dc0212dc8e6f756470f7", "CS2": "04193ea07eb088ecf13bca78d9bc75e3f699d967baf126be4a2bf3fa6e8948b56921dbf3402c4aef0dc4e06d38e5bfe8460fe72ec8fa1dfe334f8105635bef27b9", "HASH_MPIN_ID_HEX": "c4d001c31805f7bc108230c75a04a8e1841b90090d4455532ddc544ce4f06f3a", "TIME_PERMIT": "0409c3bc85d16ed32b1e6e8aa82341d8ac8968b568fc2fbf9888d3faf49e4090cb08ddf70e89f2b272c5999e2a9a104b8f4de89d3ed2603e5bc36500541ab56e2a", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34305a222c2022757365724944223a20226138346261373539353962653664653631333733353261373534623263613666406365727469766f782e636f6d222c202273616c74223a20226566343735373038663862626463363865373063356163633166366535666564227d", "TOKEN": "041fdf1b1f65b0f159e08fe8172162ce9a09738491621bb44617e0cf420648c2750637bb9937d0b50dd1b09aa8e1ddebdac4421890c690c508c7f272f5f7039d9a", "U": "04231f6efff8db5bbed31ccb13d637ac8369af53fe8e9f5902cc3651976e6a83541a83d477ed194d903fd33db68b54043a9c9ed7883cd3f866c53cf4a445f42fdb", "SERVER_OUTPUT": 0, "V": "0411537c3b32d37e00568d994a6da190d867fcd18c3cfc1c63156503ff6fb02c4220628527d2ac987afd4fe90c8f62954557939ac83c911d9d5c3fc084858abfb7", "Y": "0e9c010cd2b152a74d89029b9e4c1c10457715f80b59a3498a6073e7a485850d", "X": "0c62d537c6cdfc129368781cd139ff36fb6056b7a557cd6d4309e1043cc89448", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:40Z\", \"userID\": \"a84ba75959be6de6137352a754b2ca6f@certivox.com\", \"salt\": \"ef475708f8bbdc68e70c5acc1f6e5fed\"}", "test_no": 71, "UT": "04169f17d8acec3a8e0638cdfe8f0f21fdf290d12dbb09cfc19d89007e13db4353236561116e198120b170959f2c36749e18f1e75c4ef17c7250b00bbf48e60490", "MS2": "1ab243df094f9b69b36ec8e2321f1e5b54add19c811523550b6985576ba1ad5e", "MS1": "1536bf0c344fb5ba1a81cda37d9a8ec02567cc5ecd87e65fea1cffed552f2af1", "CLIENT_SECRET": "040ee60898445c6c38340523a736a277b359cd0e755db39c6a42043e9cb95c58c421ff06eab75ea4306305f9c0246fe2035b1dd6b808a566e3aecb5860dc9fa880"}, {"SS1": "1d4df7dec5f716858e419c708f309b9c7db06006688df7a6bee2ef85b7cdd65d1443b4a9499fdd578f4a681acfc5424780467053c1a1b80d331b936abca1f9e609ccef7b0eeee98fa953160ce0d1ff594d49e8d626087c258d0e2a0f590840430bb21ec72cb2d1a68141c6c5d266aaa972439257c0adcf2080bd6c5e34f6704a", "SS2": "01b3a63690b40ee666f5f676d0ef05f7225db128409ac25726cc3295c9d21b791c7d1241223e0c1b6d22f869bc5881577adeaa3fcc5cb446bf4f617b21752c451e653072bafa5bcda802a86ab3e36289012fc5b186a135a0e7fab21088ce5162087f5d96d5d2c11fcdb30bc9d8437f4b321e3b97da5bd30bdff7051f042de873", "DATE": 16574, "PIN2": 2775, "PIN1": 2775, "SERVER_SECRET": "026aeff487587a29df38c4c467c08cf035c5b6a5f2c6028b0b175cc63d3cc02817ca0ce0c530f95d8a8c82e6dab8be1d88c46f48909bc17127a6de9882648a2f02ae29fa17d633ef4a107ea924616c1af83268ce1971b58867978e11fa7af319127cfbfa8e6d1ecc63a0655605d0e3f83e61deaf2088985b7930e9c7ab0e908b", "SEC": "040c695aa12da2642c87a0f7b8a86b2be08d6f03495a365aac0f900590deae8f6a025cb747ff5990ec2590e9818758a839b820224800aa1ce221c6903e347ebca3", "TP2": "04111e75f3d614b96ec4cef070d4a4ec4af75c2afae4213be98a6c2a30df4f695e06cd5c2765b91d46bbb8a9f435af82d0f5b13fca97c6d30314128f8980143d8b", "TP1": "0422d6240e601e4454a023867a004e957885ce5f3689506dcf8d69713b85aabd360711bad0bddb5de90cf274e82ea1b676cd66ecfe0c214c9d5ae410da46c8537d", "CS1": "04084dbab55abc58d9236ca702ff6bc7126ebd79f5d1503004d9aa041636989ae91bdb66c06026c0e39e25efaf0de94048cd1bcc42acd7e8fc4c2f98879a902de7", "CS2": "04227d91faa9c9e1d399a1193a27e8932ea5d1a37484ce8da4ec45da0346dd7e9f114274aad88858988d1f177ceb12a2400e473b8c694d397388705ee4014c2add", "HASH_MPIN_ID_HEX": "d23310d07ad63165b1693dc519e8f7fdcb7b72d2b0b7fdcf8102bfa2e6a19e46", "TIME_PERMIT": "041c65aa1d398a706db53f9d00b7b9a470965163cd1eba8ec4a89c16d5318e374011b94da889fed386b5946b4d55d436730ee23e123a5e9d4e7417338ebfc3b230", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34305a222c2022757365724944223a20223062653565323532386533643639333035613963363261313262623466646234406365727469766f782e636f6d222c202273616c74223a20226337313865366138373364346635353137376463663931356639326632353930227d", "TOKEN": "041c964f954538c353ad4e3698a3c084ff4a92c08b2b222973b0d5b039c9c796b6100d58ec7516e76317d037ac729494bf05dfa0138b2180256a1cf1e297f282d7", "U": "041d7039915ad1b7e3dedc5640755a36163d117a8b9b854e2cf010abe64128a5af0b07a0a32252a8882995b99844e524604df243f983819dd0e17e8a64ec596a6f", "SERVER_OUTPUT": 0, "V": "040b062d770f759634478235b7126255439d29fcc0b1b824070349f609ea795b3717e1074431ea03ada1f9d0b0ae78380825310bb0a1334bc99fd28ae148ee75aa", "Y": "10fc4c4e7f2c11baf60100084f51bab9971dff90bc5035363a0e07e0aad89001", "X": "03d8e99f32ac533770d3842b3b1349a0fe4a77d1b0e7507467561b2539acc5db", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:40Z\", \"userID\": \"0be5e2528e3d69305a9c62a12bb4fdb4@certivox.com\", \"salt\": \"c718e6a873d4f55177dcf915f92f2590\"}", "test_no": 72, "UT": "040e5cfc0792e3134daa63a5d7e140d146e29dc501eb65198d7588465de9f65eb00650980f02cae9e2950a5705b1c927fe9998690bd23e2675f9d7e8dec97719f1", "MS2": "06bd1e3d016de0a70f8d8e4197521c0ef461e3450abaaee9a93edc817975d895", "MS1": "04357c426000f69ae867881432ba8ae3d89fb3aa515788acb506a84d0425fc23", "CLIENT_SECRET": "0402c4fb0348f121c2c53c681afb8c2f141ffb736c4cacf8ab0c4d4c57d5e704f40586441bf50f7c85340edc198da5de521660215c9d867a0137b0cc1b9ee222c4"}, {"SS1": "15b36aeff406dd4b038924240461a758cfaa0228aebbbe90e583638b29a28a201e00e707b8188f0a5ae6f5e32efc65a382ec168ddde9daaf7c241a27ee4de6f508450e397f05ff478b37d7dfbce938868fc9968fcccd706ec920dba5193d2a5a074f0a51f534003c23dee02f0fca958bff70f168fc2ab27004fe0aaba61bf542", "SS2": "2268785f18ef8c8d9c2a57efcf95fd8f766da389aeaba115fe8a0b1368bd557b0bbd45974a59db401478e1305d731acbf49ee98a337486418c2d2bec775d678d18288c0cd1e0466339ddf10e8fd6ca7b65ed9a8389d402e15239e07ab604e07810d98c36b6c0011cc7b8a786f9f19276dfd240eb47463921ef0bfca729eeb071", "DATE": 16574, "PIN2": 3156, "PIN1": 3156, "SERVER_SECRET": "0a0d6b8d2a351daccbae438fb3175be07c2437ecec64eea7093199b156217ac713cca2795a649cc78c472d3138bddb4841515e77a81c118be7d62e89404a308f11b2b274a174977f5c7373c7938e118a02f379d8af8cfc00ebd78f5ec8260e7a129ff862c3d426d207ecf061d00220c9e27671ff56bdb7c82bc9bb9a681b846d", "SEC": "040eb7e188a3236e469eaa05fc7199afd5a9e93b8d488463d09319d88c23c9e1772091c0d2c2fddf55fa899c322a58f5eb6098870655b9d93145393b7794647f53", "TP2": "04066cd554b41fb9bc209afb1a6603c16124644c89da138b71d169e07b1a6dc75f11c010e493866f94c67db8fb414a43d9a5650138c4760627f2c24a876fc53ac2", "TP1": "0420ca64450f6f9eb96f75f54f9a6d0958717ed85b8f972293decb7c457c4d05eb06f5f597794265c360d37c09ba6dd438eabd7e220d6f7c544302b7264ac9527b", "CS1": "04192079d5ea361a12d571ea168dd7e47091b041a064c797fee3ed94400e493bf4228e7f3cfef638a805f8355c7a1a82f41f13e208f6d8985a11904094d9597caf", "CS2": "040a80cd423b73dd16c11ba2fa3ae434d833396c50047157ee461bfc3c8c6990b622c0fd616f17357237d7a34e7b80fa64ba2509f0cba7675aba98239d88a53324", "HASH_MPIN_ID_HEX": "d4d3916938174ec409297109174444b8a07f03322f571fe7b927c19b36183c31", "TIME_PERMIT": "04014f5e3ac4a06f3d01bd975acf0e90aabea7472ad66864a80ad7f7c47d2d5fdc06c980b880c18276a4b53e05ffdb5435f71d86c0a5eb3a5ae73175fa21744f10", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34305a222c2022757365724944223a20223032626634383239366565616663366664316235643439643235316461303130406365727469766f782e636f6d222c202273616c74223a20223561393137393134373835626633306663323334613561373362313136333334227d", "TOKEN": "040fbc9966e127cdad8a9661fcaf0abb41662b97e81f6442db7f0a77cfd61e247806f10fbcac3823cb6f5b02d9d0482ffdbf53a6bda32cb76d203fc97e0940e142", "U": "04171ffa5740a36f0352c1554fefd567ba4cfd94aa73ca0ccd24a7f636ffbf99c022f7a763796121d3c16a9dd929f5109bd718737ddf863a707ed54a3fa27295c2", "SERVER_OUTPUT": 0, "V": "0416b534d0a8d5e9a4b295fa11eb3e0ba9d8ca7371a4528f4e625b3c51535abef80566d0acc03b6967914557e26866487433f5284fa1005d4159bdddc1cbb72a07", "Y": "028ad379dc8d0c5c94d0959a3fd5adb40618e300793f1feda872dcea0a9fb11e", "X": "1cc99df8e06eac9ee13c0de7b1fd5f8f6ec15a3c1c2f8ff3b1671c702a502374", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:40Z\", \"userID\": \"02bf48296eeafc6fd1b5d49d251da010@certivox.com\", \"salt\": \"5a917914785bf30fc234a5a73b116334\"}", "test_no": 73, "UT": "04198b0254345ff567dda6eb6ddeb712135d6f6c99a6cbb3aa8febd0e4645b25fa1475bc64eb375b8ba8c20d75338504de08cd2fc64029864fad8ecce488b2f4c0", "MS2": "0a51ad670bc1bc75380d3ed74205899fbb3370fae6b2084aaa54855cc73aa7c2", "MS1": "0c9a54fb4e582a3a9e9264bef1975ec6878589a12691734335203ef2308773f8", "CLIENT_SECRET": "041ee79e8a36ea6dea8ec822764d29f11e54e37ef867b717629a2e2476e04d5e1c02725cf44807a8c47495e3e09a9da531c7f7fe5740219acd45ceb23df0579d7d"}, {"SS1": "101fe19150de2d09b9394fce651a8ae6d00b0c42602754b57ec4454d95981176091f1d4a6ca8ce5510ae5be23cdf88cc994f9ee8d41552f974f2d2bc28ff1f880491aced0b5be9af0e0e435e2ed5fc00f205f16c20f538dc857031dfaa5782a60c05afc82d5d1792302420e706f3ce4a13e2a9749386e3bb7db06bbe48182062", "SS2": "08b348c26e9d84bdff7e74f3ed9f5b301681b8a11a8b0ec4888b0d3b75afbb78208b95f153be9982a4e95f70fe4079fa1fca31dbd8f40e70cea6d18d16a172d10412feb5d10edbb70f00627e9c48f56bdbbcff4c851dbb98af2d13a8b6d8d6be22a4673f8906a2f4ff844eb467f8807e45eb07beb6cf1c2ac94a27e4f0defb06", "DATE": 16574, "PIN2": 6117, "PIN1": 6117, "SERVER_SECRET": "12b8fc4a9feb11bc2967ec336545ec3001c6e028281ca05f51b3324844c549dc0ea154b5663f017abbc402a0659ea8bfae5820cf99e3ba837a42be3e461926f61191c167df0c228caa8ce9ccd9ad7f1dca46da71e2204022c28338eab78c981212792f50fc9c800f65072626eca7219fea6951850c0c9af5ed70e15d82fc10a7", "SEC": "0401cb5f49c716bea6bef9e1c9c71812a7d0985d8a277036ba6918fdd651e3cd9e00079b30165763a76434bd6b925cc8f6a756f2b6aba70dfe175193a971554d6f", "TP2": "0414ea3d87d940f3b258c694e11ba864748b30978fbc8f3f6f11f2a71c79aafce5059e67631b6dd3976c3dd9ae69a8ec6da26c50ca73dead652fe50e29f436903c", "TP1": "04151456e952b14d5cb2edf4fbaf1866a13413a35d5f4ed4410d781ea937e2f65c0463a95182dfc6d0aae6c3b965fc122085352242c607177be7ae05afc66e98fe", "CS1": "0406a0d384fbbdf2e687b8be136a1a30ccd5c6b4cff8c400fbbf967af8a16342f0165b126a5df3e01d2d1ca6bb27b4cf177801c2f936afd81b159d21fd09462e81", "CS2": "041fb77daea54560fbc819da7dd4811475a310fd86f0cfa39ec224b27f8df766660ec093cec82dcfc361bb83838bdac5fc3d83ddfac1329f16137e7a5d8b6b0259", "HASH_MPIN_ID_HEX": "3b10b108f06201ef7730818466dee620fb6a6538c97f8b2005641c9d30df417b", "TIME_PERMIT": "041cad85b361151beb4748219b549b27bc403a37bf832b19d785e973df0dc4809c17fa956a90e5df4830dd069d711124e68c834223bc58ff03484f3599b7d9c5ea", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34305a222c2022757365724944223a20223833626366616362343337396666616537653833623538343362646139336566406365727469766f782e636f6d222c202273616c74223a20223238306633633739336331326338643637373030363038653538616162383034227d", "TOKEN": "0422340582d0b4617bb4c351ace0f8e6a0b204dfdfc21acbb321b94883ba29376207e1f713ceacd7e97c5e4f1bc7b83f4f2262f5d97604af84034a4bee493c86b3", "U": "040441c6351e1db32b7f4076333942618856cc5d3538677e332b3b08243031145211894bf43f2771f8c850e42cadac0c6150c2f036dfe23dadf4b372da5019c7db", "SERVER_OUTPUT": 0, "V": "041478a40b5c4daa70dbe5af8016fece68c401822c183a6395641410edfc7d55c321776602b6d41df15b46a89d080949c302509c6a01edc285d7b87552dcbd2114", "Y": "10664d6392b9dc63fc0bd42f6bd05fa538a69dcb10d5ecfbf4c496cf77728725", "X": "206c5478e3f78ef93737afefdfff1882d6c4a559e0d741755d78acb7bbd79e08", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:40Z\", \"userID\": \"83bcfacb4379ffae7e83b5843bda93ef@certivox.com\", \"salt\": \"280f3c793c12c8d67700608e58aab804\"}", "test_no": 74, "UT": "041a28396fccf8a5a1ca449ca28a43d20fa0f6daea9380a0de8cfb9226f1e081390f92b06fc9dd3275a07b77329d7eaf49b64f7ded137f5aade3e28fc2b2154034", "MS2": "1b9754f8566275ec47c592aa5c9b4bc646b95e0ac03d38572875b5368b600348", "MS1": "0b303e32c2c2fed6029942760b00fd25930a8c64e033ac76b04ab0048a95d5eb", "CLIENT_SECRET": "040d52d1918a1fbbd84c6212e9cb9f4d74dae07aba39ae5b314a268bd9904de2301ba3a76e91c427c2c1ec9607a69acde702699165ac14a3695ec5aa2e21c25b06"}, {"SS1": "226d61047ed6811089cff316caa59abf5f26dadda367b1fb4ffb294b6518b37d1499724ff08013a827c795551f8f86342a99259147689bea835983e41a50955e039dc34be01ef3f03c633d9d274144a9540dcedfe5f165e6b6023bf09d9129231decc21179c0a06f31be354181b0db0a732f8acdc17d3853688159d915da7802", "SS2": "141cde714386e227d8e46d994af363714ca5526a62f1d156847ceae29445c0211d843563aad4e4c4bda37cafd64e4af2d68b44d2b00fcb1754ab45ddb30e1e440620740738f41069b44f277355ee5284c09ea65521008a0694225227469f374517a47081740eace6af5c7faa87431cc812c44f7f3eeee62600f21f77597f6ad8", "DATE": 16574, "PIN2": 6793, "PIN1": 6793, "SERVER_SECRET": "0f938261758a22ce716f50d6c86a75aeccc53bde8ad0dc92b0a5b3f50e6c2e6d1b676015a8a68d464e487509fd9ddce62c0ccf1b0b5192d759e808eca167bd401a9af31ac456f14d99f75afbded3c760724d87669e1760e1c0803f8ac6ae02331ad0cfabda6384cb8b725ac75d21fdd6949f446d0602443cc5e268d01a8664c0", "SEC": "040fe18abb2e4a57ba2a3b4c64429f61ecd33f5892479766a6af98cc3475716f3f059ce95d3b469d009075d8f33a48811a3bee49b8b29a3b02abd71ad576210678", "TP2": "04085c140a46792d8f5c95f58e4727173afb423defbaa52622dd5cb43f8563d3b81fbed110bbac1a35b1d9f63a9c0a1ccf291240683977070aacaf6820aada1c5a", "TP1": "0420cc59016f6d73598d483145b3af2ca808f2f39ead4b7a637a6d96f866afbb99083e1179800392cdf5cbc1bc7b8f985ab306f383693e0d7012b313b6e3e26d83", "CS1": "04140ffec91a3d37a2bfb8567e2d04737162b0956bc6770f918c803eade2a3c4f71597613f4f59be66d7bc8ea7a46e61c7e8746c2aabd0b66f17c8ed9b0f4910f0", "CS2": "04064376cd43e17a15a4017eece02a66bd5c8dcc601224313671cbb1e1e35fb6fd011a0b7d80beb08b737ca3935af5be55a52aeaa0ddc2c2836b88008494d90195", "HASH_MPIN_ID_HEX": "0c4ea4f68d98454e1fb3b0ae7dda4c0e0175051f8714c13773c17e4fa5e4fe9e", "TIME_PERMIT": "0412f34e1578617ecad1372d0472ef3f6f491d8b925b6ec85a0db246d49f2bb54b164599274714a5720e59105e50a1679795176ec8679c8ee61d3fbae492e0bcf5", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34305a222c2022757365724944223a20223632656234343734353963646137376631616235326462383461356562303563406365727469766f782e636f6d222c202273616c74223a20223532336236613230353436393561396237656266323734333239353930306266227d", "TOKEN": "0412861f662d6a65879b1a14a492432e3081d501bda49adc9ec13d71115da564aa0416e2631bb8b8a6d4a710c2b0fe5368353b182e4ce7a9e68c5552eac72548f3", "U": "04098b53424d974b1903dc4f87fc5d5e14aee5bfbc184f6ee337b522667a29243c097a632546463558d4d685072bef84f4975bd93d9d915a9636fdd7cd4c7bf3c2", "SERVER_OUTPUT": 0, "V": "041e513f583fb7a8425b79a33fd911a061c21abb86cd0d44f686e9b2a7ccd567560776af6684f1c3fbf00ca578782ce70bb28f6b7b6445e6ace5bfeeec140622ee", "Y": "215ae7dd3b1b78f63cc6e5e9c5deabf9b1c7c1a5d66b9ab1780b902f152337ca", "X": "0efa21af9746e24ff05c5e3f5dff603ebfa5eabd1e3bb3290476769a384c74ee", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:40Z\", \"userID\": \"62eb447459cda77f1ab52db84a5eb05c@certivox.com\", \"salt\": \"523b6a2054695a9b7ebf2743295900bf\"}", "test_no": 75, "UT": "0403292c6d20f9d11c0ffd27e7b0bfa708e5cbd6abc6f2336914113ad3029a3cb71be6d25ce877781cb03fc4b44f827b709790aedf3b82bd32741a7a48930885de", "MS2": "14220e128fae3e2d8362a5e25f431ff3bfc68324ae2c2c18a6c6bcaa853ec9ed", "MS1": "029649662ff561a2c078bc8135e894f9bf95a0d727abdd7fc745f19acd37238c", "CLIENT_SECRET": "04228627c46aabe9e93607e0880249ee2575fa461c34843074688a1a6d69ee01ab1ca7c18cdcbc6d2a970f6271739da118cddac872b2fbd3e56aa5e640b0041ee3"}, {"SS1": "170147757cf74793b70b59067ecb4df28d2de03239302dcced09e00257cbb3d60a21a3e1f19c4857e988941570627058bad89c8cf63034b99fe1cd18dafbcf3d15f24243d5bacfffbe4ccf388b663cf268fbafc960330ed1057a951c4adb41a800f5c10e491b6ff472606e10a8388c678725c0f43c959a4c2d77781aa92b859e", "SS2": "219a29da9fd66027ee6053a902847df5c1f383945ceacf5aa76c8c29aaa322991c7f3792903f3ac4a81c6d5cfb39e76f52b6ba28c0b12013671659ac8d71cca922e2ef1761781480cd9836b7caf1972392912a2936cb4af380c3b5f23ce00fed0b5d2e7d71f3421b0f0be7e40480a9cb846b86143b81a2ee4299da8f31f8ce8f", "DATE": 16574, "PIN2": 1465, "PIN1": 1465, "SERVER_SECRET": "1ba7ca9fb84c8f034a31aad7c9202fbd484e4f7dc86bd1d995d110bb40a70baa07eae0bf76b3e3fbc00bbeba0ddc7b23b279b36f73b5c986678bf1fc37e797011290c9288f03e1eac03d04a74b527a78291d8f5357000310ddcfffdf7a365b750290e9cf078c7173aa099d07535d0b48620bead80377af0db2af9f95bbe6813f", "SEC": "040a1722b8da0aa51d8e2f36fd4cc18cc6eb2dd6b4f75dd455ee83231236e3006c17404de1036a23202f4860a3c53473ee8fe749531564c73e1c64edfddd5422a2", "TP2": "041b724efb07e12f4ab78f8e6e1622ce9f3c1d769f83916f563f81813e35ed57e904e42206d02700e65a7f05a873c3d968f1a063eb697c0e829c9fb84b7ef9072a", "TP1": "040ed250a1fb50b1a5c030c2fc581d4c58fec72f6db36582aa3abea61110f9170f1030cd2b9c1ecbee754171c1604010861ceb1e9371868f6d792917c0199eb93b", "CS1": "0402c14f58bd22c9b20a71c6f109daf497ad67e9735789a66ed4fba1ad918ea3651d675ff5e242f0e82335ad59728b5ea8564f570c977cfaa382d2ae15ef5b62bc", "CS2": "0421a934e6d999d9a0e7ff67dccc535e1db3ebb487dc338aa84c8125c41dfc22401150a7e21850efa24f599e8ea0ef7053cc41b87a64992408b8d2c81d07dc25bb", "HASH_MPIN_ID_HEX": "fabb66971385c63df357eee34944e3bd6bd60176e7d2d7ceddc380ef26572a5e", "TIME_PERMIT": "04176a10f77fe6659f96976e7e3ed033b03437b1622208bbd35a02a9495f38f1df1141b5462b0e02f18ff0052422641e4b3ab72c71511c2c57f1714320c8f66f7d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34315a222c2022757365724944223a20223638343361353635303733326366386464636565333836383136303934353639406365727469766f782e636f6d222c202273616c74223a20226365386636396565356637376234373836323636383164353033643364613764227d", "TOKEN": "04108aa181d56e471ebff7b01b07869064ee1311a448fe1b8851d9957a252a710a1d781279594b4a0353c4f372721f64d49a309ebdeb285597fc6e05229b39f9b2", "U": "042009cd27d5bf6d8f3ee4aaedd3a4f99aa79d1e6486836be203c96949371f4e4b1fbeadecebd5280d5056437cca302f0e1f838e3930a40f820485a58278cb9e69", "SERVER_OUTPUT": 0, "V": "041bd47c21e5409b1d76058589535cbb8bdd07ea7495f786bacbd2be22031d6dc511b81de4823100a236a8260f2716ed2940cecfcd380e6695118112e7983af3c3", "Y": "08f7cb3bdfd9d8dd325dd462ef63b976e715c4daf5b0bc1085f07735f67dc794", "X": "0dce166774310de7967c6f63842c3930ce6970b85bcf66729f65b7eba0744d7b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:41Z\", \"userID\": \"6843a5650732cf8ddcee386816094569@certivox.com\", \"salt\": \"ce8f69ee5f77b478626681d503d3da7d\"}", "test_no": 76, "UT": "0420cf053c43eca91f035b092483299427f7344a6b09aec6182ce62d2c9a728dda0a52dd563fde9a653e65feec4bfb7ae223ea63d6c9ee14ec0b23f815c66c9946", "MS2": "01437bf7b9b068456f6557a334c8e8c059edbb1c4bb6d6338a8ef5a0a221728f", "MS1": "1dadac6d97f09a39ff01abd53cfbbae7a20d97e42a59da4b582b3a5f4a205bea", "CLIENT_SECRET": "040272e317a96ff8ebc806192b29e83a0e8fb76ec2499959cdd9b40d6b0747d52819c7a900216b2d17c8696366eed9f70ad3007e9509548235b763a1a0f2f185f5"}, {"SS1": "1f097c8c65309174315a2898bd6390c264e1df974e6198d70eb7360befdb963a09dd3d8e7419537f8c17cc2acf768a050209b4a73bf424e7e50648e6be753bf7106727b4d8ee9a03c2215c1be4cb01d8ed46d1b7da81a1d7e7a804a92cb31c300a22c7b8b6f77c459a114a71030186fde697a18dc19dd44f13e29b2992ffe5df", "SS2": "02db319acf3de58b8d2bac54ed54d6d3744b6197b49679c8317266535b188ef91b1ab5fa3713aa4a7f257740c140448dd5987a75888c084cffe8cebd42fac050093b992c6d6e7faa565da5e88f2eb58f04ccb154ca8b810119ffe6798becc6a812bd7ec6117c50550a5b93f2605011a157da1f70e20b644fd8aad22bb0f5614f", "DATE": 16574, "PIN2": 4408, "PIN1": 4408, "SERVER_SECRET": "1a214e15115e5681df373f289c645f6f5f77ea9551dc1cba37812cdccf46494614b81f127925c4bd113241ab7c4fa385b3a318c35e9a6e3b2b5dbfcefcb3fd2d16b23d69f7fb46c931304523c4e9fea0654c57021bb8e17ff67dd4c4b889bc700f1d4a1a1696a40b24026ddcb86202e3b1e97e00365b2a4ed0a33959767c14ae", "SEC": "0415bdfbc98a659324cff337acfb4ed2d7992f7fd13e8cb0af1e74f7a5597dc19821ee05ae0d3b0e5cdfce3ee08e17f6b755f7cee1ce48ecfa2355371bb7960484", "TP2": "04197af006f93311c702bd2bc20c8f18b0fc1de2ea10fe1417447d5db7b65c4ffa12936523b37b93ba0362658525d979bbb751c39e110196dc38a0f1e86a297561", "TP1": "04005d534df3c8672942d081ec5308e2e3a97c54043fa93a9920ef96171d9f210f216c3daf2ff98b7e62935d82c2619c49886d82911cc7d9823d14502bf3298436", "CS1": "040fc9c7c32e80bd775c8de0e2eda495f71c8dfdc94b2e46592b19d4cb7d4e819e154033783350ecb8467b137b5236b2ea27eb35d5a98186f43f36206e0c5cb1a5", "CS2": "0421aa97c899a7fc4429d78819dfa58d7bb676bdcbbc2e5b2ed0eb235356984c7c136d8d310029dc7603aed92385d57daf555104ed1a7265190d8416c02764f275", "HASH_MPIN_ID_HEX": "7a84bc16c8edddeb4142a06f20d349c843adbe0e221447e3c068949f31dfa44d", "TIME_PERMIT": "040ed4adfdead7c38b137a0bba9c0f4085704d89a4d56de71bd25d751f0b002481164f4e2286309e1ac74043f553b0191d359a625eb414b9d5b87c518488097b75", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34315a222c2022757365724944223a20226165316232326666616437356462623062666463333933333330323966643065406365727469766f782e636f6d222c202273616c74223a20223033656430613439373338663139373061323831383666316637343830663538227d", "TOKEN": "0404969c30ea63042213bd18d429a870e7a0aee0cc7ef2acef18c1fdaa4fde95ca08fc985cbbcb8605d3061c72add8ea45013d32f4dda5e13966bf308d34eddfe4", "U": "041f19326ff5fc3b0d8055892d28ed5badf537b6c9d260ef95a05f1b3062c54dc203c4dabd30896a2b80dba4cfeac3e432999d592903164e6c485e9d0740111147", "SERVER_OUTPUT": 0, "V": "0419047d4b8ce9e0ce7cb0dfa716614bc373713e7125e2e7d35d213b50127d47201f21dbfbf3753cdc28a2d03dbaf0b14e6b7f26fd7faa781f50091f13897bb58e", "Y": "17f82fec7aa8cb3e66d6d049307cc385ab8ec1c972138791e7331c3f2cb39d0c", "X": "127b3891459ee824aa89b037084205dec1a6a30db1f684d802008ccf580a12f1", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:41Z\", \"userID\": \"ae1b22ffad75dbb0bfdc39333029fd0e@certivox.com\", \"salt\": \"03ed0a49738f1970a28186f1f7480f58\"}", "test_no": 77, "UT": "04188ca601f22cdf502010bd4f2efbadaf9033768fc209739696576c759113cb33055b315099702d80bfd0395cff59f851e29747ba7d9e4bc2153710ea3d4249da", "MS2": "0030a26ecba9c8d1cbbbb577b6da76490d91af26327d09a5d594e0fe573fd8ce", "MS1": "0a215f6ff9431ff0e5c8830a20d70d121561c9191b4cfff7eb6668a516ec0b46", "CLIENT_SECRET": "041178af3cc3ffd50ee8bab2aa5e115bbed9976ad5819564d8cc4b99bc6bad461d130d74bc10c47faaf0d37b43cc0de11b101ddd1dead75a4e0542ef352f19a29b"}, {"SS1": "15be2f85201b0d20c3d4705e6dce7434f94c191bd45863847e3beda2bf6ffba6140db35451e5858a9fcf290269b7ac51c36593c4f6de9846d5f094356f638ef1097f82573be54a2053580f5a28eedcb325e13f59afdd92033659f21eed18b98300afa7845bdc0083d07c014f075592f4bb7fa7c30f3f0a3e3c8bd03888327ef3", "SS2": "16a3baf019539c0315d7692d97b16a83efd3835b5e82104896a7917bdd883b420beda280541de80f6d6298b6b5d5fd339121f9df11af4648af6f575b93e45bfe03719ba4fe901dc8567998a3c617462af099f158d3a28bda998e8e3011598cdf1384db7309a568ab73b184aa300aa3988433d55e6dcc7ffdf31af64785a64f75", "DATE": 16574, "PIN2": 4622, "PIN1": 4622, "SERVER_SECRET": "0d1a81b236f782a3fdb3b1f324b3d3186ed0f7a421c96b356f32cfd36485b09e1b75c12ee0bd8f12ec2ef586557768624bb943bf22d4a2b46fccf867bbba1ae112afe9c30b2aa97aea3f160e7b5e379edfec817e2c17e3fc8c80c71028babfd520b19aaedac2581868441663f5ebb57b11317b7237a4a6a1d92312614de4a929", "SEC": "0402edde4e6922696941c3e27393bcb9c8d165c08e6b85bfedbd903edbed87f98512272d73ebce620505b95bdace1b162eb99ee72c7654e0a9078d6c66c2b055be", "TP2": "040d2afe33d847f77e1e697ff197761874235f0d5fd0cf4c4de165ccab273f846d0836321f823052178d54b2c64bd900c85f6d6276ed773ac29460cac4a337703b", "TP1": "0418a3958f56731b342d0264ac5244d33d3c047f815980e2bec61dfdb0039d33121371da7873f92a6ed65556bc95c060f5859416c7230050ac22efc25eaa72ec8b", "CS1": "040a23127f1c1ef9eae16e821b7e71cda653afd2cc6843f413f9f2cd0f8f86612f05d5d073cd4ef32825b6fd2fe65f6797f7cfcdd30c460c1193ba1f7529c79ca8", "CS2": "041460db2f38dc661e79bab2ef1fd58c230dfab81324684db126f1c3555fc884440a06103a9166a64bb1c3dbc3ff2c81c0fbce3ae3910dc73f2483e16b917fb55e", "HASH_MPIN_ID_HEX": "9a73eb1190bf311de49be4df153d23afcb1fd1dde9ee84c5e51b2a79ccc0e2b8", "TIME_PERMIT": "0411eb94501fca823362cc36a605d38206deaa3e3df831e29a916831933b8d2ef2164118deeb137a2dfd6ea14461f75105361a6445ae1c80f8ed2ab5e6fdfd248a", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34315a222c2022757365724944223a20223365336639303731373830326534643337343032383136313332656135343732406365727469766f782e636f6d222c202273616c74223a20226636636663383365373338323665323935353162366437373132346231633766227d", "TOKEN": "040024e12a3ca2d13675ed01e7b64864c8838b30509474663d12055b42b7aef61e183285a9c4a9fc143ba8652d0a1f10360fad244b3f2393e891206d7d57e7a23d", "U": "0423e640df49b697d1f39cf6a816df89400fe81ab887859fac1de9299e962c51fb155c6e5e91d00e3d00aeb3be079d2d86c39f3eeeb4a5849a9c881ce52f03dd95", "SERVER_OUTPUT": 0, "V": "0401d092d53393fd0700ffa3f205593a15752f4e252fc5fdcea0b1aec7c665bc5e17451168fece0f131c04453ac007d9639382e2389dc7276073a9f04c75d7e106", "Y": "0ec5b89b2f5b94e757807f0e700dc1e007ee5925a5f7d8e131defa0631a748f5", "X": "236a6dcb9f8d942f2a67af6de5f0733ee00896e7071e96cc918a84de171f14fa", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:41Z\", \"userID\": \"3e3f90717802e4d37402816132ea5472@certivox.com\", \"salt\": \"f6cfc83e73826e29551b6d77124b1c7f\"}", "test_no": 78, "UT": "040c176127de1e4120331994f7fc7b78e440d2932ab6c916009f08d8f2b4cd1c650a8b5b497363e59048b99a81b709fff51dafd93142f3d10be183e66c937e47c5", "MS2": "008794ef8d91ebf8f98169651879be71da42381a8916278a52c9e466bf677b47", "MS1": "076613fcc9ad9ca1370e2b1946691e78a484154ecdc02859b970034ce1ea930f", "CLIENT_SECRET": "0407a3117e24b5688f7e509a33421a2f41fdefb162a6c61a6045f84c0fde5dacd10e8a87a0ade99e5e37d20f8f2c9cb53636d355c5e8fea941f6924f3777b2e3b5"}, {"SS1": "19c2a5bca467207839eae1eb9e6ffa3cf940d90921fdfd3502bb5ef3c79dd9a922fb127feb4a48fab5f0d57d1d2376b240b25eed089612e8a5dc5f7d195b01fb0482ecc4778a029b98ac51c9013837dd42c824622d75f1885af330de3785d1b40a2b017143ba60ef8f037c0db5cf6f1573c14df6332d1645d5540e67f9677557", "SS2": "01ff55a792841bdaf02967e58b0142b597182e7db55b6ff811ca54265d71ac200422a3b86c7756f1a4f8ad8f5db935e40fec3d76a6bb89fadd4e6f390d72bcef075c3f68cebedba4de15af5fab3c80e87450eb9c354ae71378cb028d644768820860b2597344d8d67ce7b120fd12ee47aaa7a42bd45cf7c5ac89c8184f3642c0", "DATE": 16574, "PIN2": 4442, "PIN1": 4442, "SERVER_SECRET": "0e2d7effdffa7a8519a7ba122b20268ae1d2e2d59c87670f7e2a6ab3e19b02f5205821e79aa04cbbfd76675d81586f226c7fbfb60a286cb95969011b6fe66cfc1e8d6aa8da36974640c2e4942fb0002406edac903100e5d7c6e5f9a6e9be661b084d1a09d0036a11d7fc5db2bf15956b9435f1d5f784a67fa6be729c88480d32", "SEC": "040a024e929f300c0115c56379564a50917fadcdc4a96fe4a2ca519ad99c17ac661dc19bd8b019f2f76f8f8fdc79a555c1209150a1d9f43da8837d337af14a72b7", "TP2": "041d08b6e0c24809e94910ef1c532bcaaa867edb996b84798fb986100693a7f98e1d5a4b78bf16d09ed69b3d8eb584aea8302e7853bd97da8bebb48db8ac60ffa1", "TP1": "04083efe81e4b221f09730ac6dab7d98ee0f15c4cf7b8ac56358408b280a17fbb8083e7f7fca8123313ac8f2f47b9ede1ed5d1114515835e064781366c89114bce", "CS1": "041d6579f830557bcf1aaac7b3f3319cc6d8b2796b7faaf5be30b7404005e764042101518f6a0332fce7960153dc1240c53f5b8782a2ba08a36dcc5ba92096f4c7", "CS2": "041581cda3d3517838cf757ae7d24d4a7bd1e700cafa8a251aa30881131762eefb1515b9caa7e73e883777ddbb250fe2154fbbb459bb9a89288de6f7a854d09333", "HASH_MPIN_ID_HEX": "ebc1e6567da08600b5f9967f79b7adf2a27ea215e6c6e3b8442b6ec5f6569a45", "TIME_PERMIT": "041fe99e6e9b84a68bca3a065f92e119363cde9815b189aacde9d1eb66a96cdb840b9f79264af4ac05932aab45f9ff094fff5b4d02eba79ae5f23d97807c3e7d13", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34315a222c2022757365724944223a20226463663237313230616566336566316465313339346630636533313236353239406365727469766f782e636f6d222c202273616c74223a20223132333631616530326133643866616135323464626266646130626335353433227d", "TOKEN": "041775afbbc3f488c3a11c43820a089bb4f71b24606714a46b5691bb95dfebcadf176a0fbfe4360c3ece95de8f509f60ad02540635bc311a9cf61fb29c30c5ee6d", "U": "0418b2fca769dca4c179d3f3181cef7f770ffeef954c7632dc039caea273a00d5808f400331a1135bbcaed8e693ffa6355e93bc4334190a74d74f364ccc4e7326b", "SERVER_OUTPUT": 0, "V": "041f91baff6d2d9deb90cc983ae28989015e6fa92518ea402179acc5c0f81c84f40ee3681f5c0c3e34c66ed2780c9f55fbaf0891608c763e2e64ed56cd09fa5227", "Y": "01ea209b6bf28c3f3c7e3ea5e2d04f2e9d47a84e391f9f8adea5f68ac4058915", "X": "1959238e767013547e7f6c28c088f644c0dc044833ad7ab9ddf1f617d4e16c4c", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:41Z\", \"userID\": \"dcf27120aef3ef1de1394f0ce3126529@certivox.com\", \"salt\": \"12361ae02a3d8faa524dbbfda0bc5543\"}", "test_no": 79, "UT": "040e0a8c284fae697b4403bbea279f358e3fd3d6379dbd8a9e2c4cb5369cd33faa1c6022efedb6a4c5e6498b3b9130cecd857cec1c32e536c32f67e96acf41fcfa", "MS2": "151502b83657373acf353061704428ece44311d78a475a1a34ee9aacc694eaad", "MS1": "0008a48f695c6900afd3dc32ede652596ed68a5391b7598d55b71dd96620bfa2", "CLIENT_SECRET": "041d8d5c26e47b11fb6a9ba2f179b08e62401bf0caa17ac71fe522735c88937a5c041e223bbb4a2b0405fa00bff032128977ab9a8a253e6602a4aec1e1790956c6"}, {"SS1": "0f20e679d60df7c9beaa9342cd64f2a1c101544dd644c555c2bbce605ec763d7080c6ffc1fb62f2776f0216f26516b4b151093c5ba5bef4f766335f9a88f634f2283efc7d2ea850b4bf882e1043498be2552d35db2824d52cd4b080e852495921aca612d340d630745dc6f3db2c6083a71be04c4584e0cd33de7248d7b528538", "SS2": "1eaa84995511c5f2e6e4149cdbd0415c9ad458e6184655c00668fd0ea37d69780ac3ff74b3895c6259ec76448b6ba6ec2bd08775541000261605490ab24a4c2c03d65374c6b4d48474fca390c6cc357fb6715ed3bf9ebf2073b46751857696bf030f2649b2881c29cc46ec740aed46e2616fda83def10d99dc2ee9fd8875dff9", "DATE": 16574, "PIN2": 23, "PIN1": 23, "SERVER_SECRET": "17f61d38a668a73f130a301c14076d9edc30be2be7de42c7207d9cff93db863c049e4a2262912941b80ee1f575653f9912e242faae808a328e3b07d33ce366951bf2bcb45eae3fe09806a22edd7cd774816cd426d7bb3d7be891d971f26d8f9400ab1e7e0518fdd83a0048ea466c4fdbb1ea37e1d59d1b9ddda8eaa6514e5a09", "SEC": "0401a8e5659026e9e627a6609f417462e7ebe832a16938b48b093f2a0887d8977b08ce6207db7abb91749514cc65e95c2badf137870ed39aa52bf0fdcd4ad11d57", "TP2": "041f6f54e2460b31082fbf98f9457adccb420d1de95c1198aa2d72bca0a9fd8b291faf1b06e74790eb48a9aa40f78b844e2fef42a8190ebab61300cbdcf87d72f3", "TP1": "04087d65684b87b7d0d52543b68d1f76dbaa93ebc19bebbef5c2d907918ac65b0020228ec3e8ceacf27c65fde38e721ae51f7c8bd9525052a40e9a03687bc41b2e", "CS1": "040728f6b2831bfdbda67ee6332989d5d2e2d532c16ed242224a5f4de78ac0f9d1127d13ea8209a7d2e1684edffd06d1907a390a4e0e6d59ffec9500ddf478a93a", "CS2": "041c4e3f992aeb5393d173ab44742e2208bd73bb8c52b2f25399c6b81cdf6f01c61c91d34d04b5859683309d1f87ff9594be6ec08258ba72ad0cec084b873fed2a", "HASH_MPIN_ID_HEX": "12f0994434062a6d0d580b07c5467bffea14a7c9d04cfaf8d8dc020b0567ec43", "TIME_PERMIT": "04010e6abacf7aa7604c2fcd0a9f25ad8a3f563a04d7f3ab20cbee338d5bcd7b2b168dadb1320d4dd0afd0b6deb279363b8e4f9547308d89f627ce98bda52bb482", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34315a222c2022757365724944223a20223263613565613437636466653434626337306161643365663436613865656362406365727469766f782e636f6d222c202273616c74223a20223161616434643639633433376435396434363165323463336566653935346466227d", "TOKEN": "0420f55223d3c18ed678355d85cbd3ea1e316834049eacad12bf77e0d9fffa76d2147c217c4cae879fe06ef35a9fa3ede51558258241dc4e223690be7f9cba4198", "U": "0416cba9ceb82d657c28f291786daecc503af4f6d30fcaffcfb2ea91baf8f8150e21886732152de9570e4ab6de46e1cd53150fb26358364743743410bdab77a9c8", "SERVER_OUTPUT": 0, "V": "04014b36352b67823b21f79aff606da0c468b01a5a227a4068f07eb90c8e9f6af3239415d1986b3e45c14807379b5cabafc0c49dbb5cb78ac1166baa4b0d3b31c7", "Y": "20af008250abbb6ef856dfd78fd500cab5bc74ab3873206324dcfcc5f327200e", "X": "0afea84d843970329b05aef35e7fd40bd2382cda360ab3767f758df9703348e8", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:41Z\", \"userID\": \"2ca5ea47cdfe44bc70aad3ef46a8eecb@certivox.com\", \"salt\": \"1aad4d69c437d59d461e24c3efe954df\"}", "test_no": 80, "UT": "040a5eaf81be42cd3e42de79ac02d5c59e9edb439e0c451dbdf9eb609e0f2d17d21be43ee7f58d53268e35b954c5ac52fda57db4238a3c660f22f458466a5f35c0", "MS2": "0ae14be7bd65250f0fbfc0420ac52acd468ac77377555a8c418d9fd531c88fce", "MS1": "21a94d01b34275d87f8db7a44a6b2beffaf3d8b0439e71cf93537a51ee799ea2", "CLIENT_SECRET": "041224c1110ca468cf84e5d988bbea9c5e18175320c2da6dc4fa758dbc1fcc36de12d33edd9ac0712a51f9eb7250f5f3580189674bbb0d32fe037f709d3d67fb7c"}, {"SS1": "1ec443bf2e655d3897b19c9c11cd7f5d2a0d580a5d4e8807991694d52e5385bc1a8178e64bfbb11613473f19513c200078a3f9c6cf34378c328503a3e496495b1c4ed4ab72d55efbe4f358abb4d288afea25a20ba6e966011efcc1f3affba32201aca8005714c06fd702f5113f0ecc0470090ed98c94e285360c5b23af9fe0d3", "SS2": "1d675162cd7d2323a0e4714fcf5fa4020f050fa740e6ef5b6a921f60468112ab1b2b4458f744c891c42e5ad16ee7d4ae6098bbfe8cf265ef7df6e76a6fe932241b9d928f01ecb4b6c8ed98add7ea7c0425ee60da0b8d0bcdeffa3eaf6a37b0671423b2b96874bfe7d9364a62fa698945939382bbd496457033456b18c2623aac", "DATE": 16574, "PIN2": 5993, "PIN1": 5993, "SERVER_SECRET": "19ddeb5eba0705e7ecad54c03164a53e2f15ceb84252670aa210f83c9b40c48b07899647734d647ba87417e6aa78e92c17277a599cc1c4f7d8ab176749376b0507b0cb8d6cafeb23998bb945bfe7d21053d4df1430f0212fccbf00cc576c86551d6793b6131433982c401572ea415851c674b96664f741fe80be08870a92c81c", "SEC": "04023233aef05abfb8ee59ee31d4df3249ba04cdc5dc0a5a7702c7940e5d4693f80a55de057a626cdce0ea31182fde9ef5717e1f9c8b7084ca5d0d26c5156af7c2", "TP2": "040bd0e9ddb8387dc29c529951168a1a3415cec884f03807a0d4e595e9be6c88fc17e9b6be282d31dd5846cfd893ff8e48f6687ca68ffa6e4c509874600e32bc2a", "TP1": "04052f3ec1daaeb316739d4808205d4acbe62ed706e35ee36bea0c2ee49386404e173d4b7ec0bec7126201b5d55601feb260c330ce0b111376552be1d1ab565bbd", "CS1": "041fce97a56a08effde4e537996da7f132201fb2af58382c9c88dcc3925b05701b0b408e1427c389e3eded83f58cbcafddfe307c6d4d22f4cd5555fd167572d7eb", "CS2": "042225f2d1baff5f7b96ea689fa500eb82c6326be697da6004333aa7876077280614b3774e1be7d9406e208451e4b25baf159e5177cfd3617553827aa262a42579", "HASH_MPIN_ID_HEX": "a2716f8a63ec8c00a7a123491b5e9ee6458614b510919275f6822affc6bb934f", "TIME_PERMIT": "0403087fa9efb2bd5227d04fa4d27b47fe83065f1f17a4cbf3ae18f8df6a8e354f224c3f34fa90b900bd9c2f3ab7c110dd8536871fe25adac61456ba9a09ba3051", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34315a222c2022757365724944223a20223837313732326133303962383033393535653765326463336136356237636330406365727469766f782e636f6d222c202273616c74223a20223763623464373566353230333161663735343535623736323364613764323430227d", "TOKEN": "0408500bd2c6a29151895dc7f65aa4bb3ed3f9d5b7dfdd40c997b320efd19879de1a550d5c6aaacecf08f0624181c54279212d062f793c88106f5c7b5f8076980f", "U": "041a1225b80573a038bfa01472d1772e5ec5b3dc5dafe27e12ca6e7b3ab8c456562105d8f031d744de02e3755c375dbe86984f04a0defd79daf804685a3d78e870", "SERVER_OUTPUT": 0, "V": "040dc447be830a707cd147e4a4c1fffb94aaf66b5c0fa431f0833c9ed3a91d99871941973c8224c361d4895d4eda77aa6eb7cebf93ff61fdd015211bbed328a27c", "Y": "043628381882a89a91bf31576b2f0e9dbbf3e166a5b1c5a9787c6072b3fdd805", "X": "174694bc19309b54589e67553d480dff826c632152a35f877cd28b96bf594479", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:41Z\", \"userID\": \"871722a309b803955e7e2dc3a65b7cc0@certivox.com\", \"salt\": \"7cb4d75f52031af75455b7623da7d240\"}", "test_no": 81, "UT": "041ade874f9bf4fc1c1af465593fb1dbaa7551d679115179ec851c39f164a877a00d3aa7e3718376e17891c9a72ced5d9d9d71adfadc54619f10648c35ceabd14d", "MS2": "21714c7e38f6834860e6a6552f1d1bc2f786da8f066b5a6991013db9dc32f24d", "MS1": "1d580184fa53378e80cf23f6396a4f7909aad88e1c76f1da22d02dd73a29015e", "CLIENT_SECRET": "041a9e4616077e46e524b9d3b644bc17c5fcdc697ecb595dffb8d7ab170fee0e8a20d35168cf8c7c2e5c1a1ba5379d75706881908352eda3100a7cf6c3b38c70ac"}, {"SS1": "1f8889730642a1532821bc44612e63b33f8e6d4151d19a9b11b40ceb6d3906d910e220bed635efd725048c03c3a10f83d40793a778014260daebce800c76accf130f6114d61385b6950c204f25e3a18351f55a0e7508c04862866b4d5f570ecf11b911d202b9381bb48e1c26a99f5abf3b19b78585758dce6927628697880eee", "SS2": "0593500e95381eeb22053bd998e7021819b2709669b19c67ef7b41b40d6db8010b5e5609ce3aa1cdaf3a137164fa8b22d8bd9fbe888a6c2599d692733658b5360ffb11b24ced8900e7bc1e93b90e1b78b1bf8ca138f136eb97745d8d30662c6e1fd88b172f6dc36874e505913914fab81f4a9e1f91caa786a78ae1e63edb90b1", "DATE": 16574, "PIN2": 1620, "PIN1": 1620, "SERVER_SECRET": "0769211e3e2cf35834ebe6566e2b4ddb27ffcfc567f70b3c51a1f05d7b128d6318ea7b2237a558d1b68ab69969e0c1255c957ef90fb434383fbe3ba13725839608b89e4956d2fe2b4f8dfc8484401ce4d383829bf8be16cc250bc42997287f7a15d7a6ff3c3e9252f4343b7d1984283559db433a9f9a09bf9c589d29a371b994", "SEC": "0421d9b3f6f51e2ae44c52683449bcc063cbb8494d6f9bcc631bd0c52ad74f935318be45a50c9212607a49bd8f251f65b3e95a3605f2167e0e8fc3a3e2a1189363", "TP2": "0421ebb226b079e1e91d3033ea5763f82a4856345dc7e46bb89f8c09393e227629083a9f1bad0708c0e04740d0a9daa61bdd1652aa1744bfb5aec584219288a5b9", "TP1": "040eba02c81508e0ace62b273f851ca57a8d9edd9885712344c366636d17efd09e1b9617cbebd06eca3fbcb5dee22515b958c409c84c03b9d318ff7d86f3ae08e9", "CS1": "040c60f5f0f6918f718cc464caeb532edfd87dd56da5adfa2edc862b5e287f0878018a9bcdd7d4dec21b35f49c6039efe7efc876b0fb2584af901796d7f70bdae1", "CS2": "04008922872e18d28252b2d92138ce47622011470f433d3381d2662f12097e78e11990360c6fa27c5e8901cdb08723df897acd59a4bfbec82f5b1140700ac6f658", "HASH_MPIN_ID_HEX": "e2567996f829a0a577f84c200f4e42b6c0cb478208a5be7672bb19a528602f3d", "TIME_PERMIT": "04186b1b06c8b39e6388989356872db938b045a71609f46000a9d5066f8983edb808674416a9db61b23d3fae796649436645810eb54e23b99ac2cde7d5edcc7809", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34315a222c2022757365724944223a20226662383837326461653463653561356138396162356364616632323862613863406365727469766f782e636f6d222c202273616c74223a20223761356462613737626336623534363935656566636236653633626437313535227d", "TOKEN": "041b4323d3ce6136ad181446f6cce3709b55044ebd6c20ea2ee516388a9fda0dfe0b623bb55d7a4662d0c70ab4d4e6c88d1c4c295bba102e12b1fdb1a03b9aa9e9", "U": "04027d2b281b0cd19c8bee2e6c8724c432c6ea53f560902e5bd31eb5178d3d3cd316f1ed62049908df28fde6f2392b4d0bbc0f51f698ac73e60a5a5059ee71af09", "SERVER_OUTPUT": 0, "V": "040ec1ae6a765ac28b531bbdcad7321f834858a502680b76d099b75f37baeff5aa13777063eebffe1af0928a6dbe74e083cb2c42706f1bcdb6f6cc8247d8244759", "Y": "0a3ba6023e66c2e89441152c946b4d4f51823148487af0ee54518c254f484c75", "X": "19e29eb3ab4b4495b7217f49f9555e68793ad67048e5adea0b67e9234b10590a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:41Z\", \"userID\": \"fb8872dae4ce5a5a89ab5cdaf228ba8c@certivox.com\", \"salt\": \"7a5dba77bc6b54695eefcb6e63bd7155\"}", "test_no": 82, "UT": "041c40d4c2df35af18b632e8956ffaf48d6caba53025e9cbdaa9c170470665a1940d52b726d45ce908f1e23c522e77d3e890158db3e2a93c2c37dd4fabf7e0aec9", "MS2": "1f2e2d456a617fbe59e610ae72eed4dc91a3aa2f4f0de17cec7da135623a50e1", "MS1": "1871746c9369a4a26c5b92bb1ab48dde537cdf8f6700db208ce0ea6bf58a7c0d", "CLIENT_SECRET": "0412aa71f8fb4fc7731b8a047150de68d3ec0994336e54d3c2e356bf345054ad4c14fc9e164169b9a8235158dc4045ce0d16b83b17882eebc82f076d51426b47bb"}, {"SS1": "0ae60ea8957c6e022b94ad59e5b5d8682897af8dc4e0949758fddbcdb496cf1e1f61f7026293774fb153e577d8b31311de48ec247ad31d850d0d6c35a9d8c6e915cbaf0702c01cb45a8e7803189aa89437eaef558a28a5e1cd286af4544c434004abe93f23f6ec45c667cac0175d9da2767490de66bb8732a52def22833513e3", "SS2": "2113c16c6984d53bae2d48d38f616f9665a8c6f3e486116bcf80b0c55478cc8d162e8b9bd46faa967f7576d394c5260792173fed6b3ff7f3a0456013f6fc72a40b4e72bca6ee0bf27229e3701539e2f295e3de40d0a4a9bc07c8399d37a06e5520a7eb7fd7be10d57d793d0c3b44b5dbcd75f6dfd8eec7475f601183857beef1", "DATE": 16574, "PIN2": 2873, "PIN1": 2873, "SERVER_SECRET": "01f0d6e9bbc05967d35fa9d2d8f94c44ebdbc1eebf7a2fde8bf4e75e10b70c221206f1db48834491695159cf3fcce900e7aa8422a479199b672355cfc089573f1b371b8425af5b2b9d8f724512d519e993669ab9154671411de6ef267292db3407a24c8fd06e4a5f29defc52a38daeefd8c64aca397abebbe5925aec45795616", "SEC": "040cc08ca06db551fe4fd783304ef66f04c0ae6c1a39204e97a04a137b5e48d767166cc0fdb3190d5f171a986049f96b87709d79593708a7a7de3809eb4f22af41", "TP2": "041042aded55aaaa105b86d70915032883401cea09df6af47f553e7bb2926ea5141aabd9244d36becfed1994820936e4e20e149e2a32584cb588e332180c73547a", "TP1": "040566545564e51b5e799f1db8c84cb19bb7839a1e5b8b80fd7d90d1d4ce59770a12371db4956f1febaf639c38ce2c251dfd7ba07a7ad84fc248b999c486226714", "CS1": "0413abf837b3feaef0c4c3eec94c0aa74107a450565d6312be39e4a6a60647e21713799ab399b0ad0166d9f10cf079598c7eb62c68adb905edf089d5a5daaa33fd", "CS2": "042298a7463b69ac7899ebc857b4fc52773690f0d7d8090bebffe74a1a045a617723ebc021103c78834f05c2212f16a1af7ea44b58ea1f2a0e1b2547477a1df643", "HASH_MPIN_ID_HEX": "ecae268d1a238d4e7c4d28577ff82f3adcd74a72c7e837f4f2bf09c3b24b78b4", "TIME_PERMIT": "040cee22e56f6df8f2912e4a632b08b8cfad51874c9b48cf5cf043a931f363e3b623ab71bb297b05efbbe0b9befb8a70531c30489d123babd3c1f46a3f7c14dbe8", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34315a222c2022757365724944223a20226565353634643339353935316331356234353032653630383234313338306432406365727469766f782e636f6d222c202273616c74223a20223064343962663862633234666534393932386432306662323230666265343637227d", "TOKEN": "04110e325a92c50769fa37c0b4616a7de2af7bafa25a7984bca7dab82ddaa9dd9103695e35d6e1fbd5124fe5a078b001bc3f662e82619f0061d8f5de8333fbc98f", "U": "0410fa9ae18e411c164917c24ad0200ddd37c49586a8ad1763c63aecf2e5b5cafd01eb9d768ef6b182646f73ab88b9dd9cbc1a5e86e2f1f1e9b4c9c21a1c7a2197", "SERVER_OUTPUT": 0, "V": "04018c714757fc038eff3029d5e7c448ce1be727385e25c3c376743ea9d10e8916079a41a31ed4ad1fb7a3b42473c511082ead35939495dde4b5254aa2429a8758", "Y": "0bc69a74ad5a805679cf45b9b4e03c14a3c67a2a58583e226cf0aa33ab76d07b", "X": "0ce21ba24d2742a82aec722a80563400a6da096a4e791130500d5fc1f2389d81", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:41Z\", \"userID\": \"ee564d395951c15b4502e608241380d2@certivox.com\", \"salt\": \"0d49bf8bc24fe49928d20fb220fbe467\"}", "test_no": 83, "UT": "0406ac3ca14c0d8578636b6310d65ba6f0c0c6e89d0317e79d6a070ed3bf38f688106aa4e338f24185cc466e6329301024397d1e4f94f1908937183a4549776514", "MS2": "117d1464545659a692e0424db4ac07452304e9652d217de4008af5f2f16b6b1d", "MS1": "23effae4c67e7e3bb0f5cb6c37401710d5d132bc5798b55cb5706fe82c66e9e5", "CLIENT_SECRET": "040bb1db220ba19674509713228dfb6121575323eb1f2405381f176b2db8a04e1b1b4b97533be6da35979beea250305cd8fccf0ed354f9531c4eab31c5e446f324"}, {"SS1": "1e4f89dc6cfabdf987bb08a70d423603c9406c9ce969d855860c1e5a1e9695651518cb5c9f456bb2e00ca0eb3e7847c1dec34ebf1255bfe37fb063ac45dc46fd1a4a75e9aa266b5414f82eb978719560d5e05406e583fea9d43d47f86a7293090b86bfef700a5f1956b2d60b3f3c19a27bd574855ddaf49533338d0db8483fd6", "SS2": "17cef6d6cb81bcdd03fc96405459138d8ab96885f5d64ccd15569dbc7d78d27714a001e42d523bca7726d4b7b0585aaf49978ceb8b41e633aa3d61b9a2bff73c0d1aa651ebf0a61ae349f4ed048a54731f9ccad5adadca6fd58bbfb6be1842701b338731f6412f9637ace1077e610102d54c8793b1ae839be5017d6315d5fd66", "DATE": 16574, "PIN2": 6172, "PIN1": 6172, "SERVER_SECRET": "15e01d324c73be77009da990c757e2b8eb3310205c98ff6021c1d057e27719540f364b5a36bdd72f82be2987fefdd69a6bee518b4a6d82629a91c06340e7003701f8f2b2077c24c6806c5daf3ffa3c31daf8d3afdf4a8ef4c46b507050cf868d1034bc6c3823f071c935bb8872eecbe4d47ad42ba187fe9ee3f959ed379ab9f0", "SEC": "040f0eb2a923182ae1be4dade38fe08bacce551c1b793cdc117b09e1027a8b54b70d0ac21d65f6450de696df519fff23b083fde573db03aa1090d3840850b84929", "TP2": "0416f3cf0bc9546cfc3ecd93676113b7b206489e28fed485bc3e785e86fb82a8931049f07b46b737590f653ab2813ef29bf00d29351177e0f41e4701512e7f824d", "TP1": "041a1dd0e4ec5a04028ce2018e27b84805f00ee5bcbd4c2488dd9b2ba4fc8300dd14ffab2d4db96160b7b483c3e01f8c739ea8415d156fe024d532b8569617e554", "CS1": "040dc3a219a5cf3814015a54d36924459b6dd2f6b9afa35b95b617ced0ae8e3e0c2217322dad4eb08ff28c15db0be8f5a3b722cf60ab62ea383095bb986ab4c503", "CS2": "041f026509e87e05327c9e1a8eab3e9c3545d00f8a6010eca802ed1a82d10f438c145a5d5a4353102a3a35b92d5b99ed56ce3ae951dc0b697936db9768f03ecbfc", "HASH_MPIN_ID_HEX": "d4bc97745c37e7f83c23c2f78a64808b57b1ab067bdf7952c63210fcf5be7f41", "TIME_PERMIT": "0417d653a540efd7765948ea8f4eb3ac31f86628333a78ab8a7e341a3deb86644b181cf8618b5b2ddae3b1f9726d66ccd05098f023724291d4fdb29000d07a3aca", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34315a222c2022757365724944223a20223434643366336431633536356335306434373530613832613732366231663063406365727469766f782e636f6d222c202273616c74223a20223030366464643934336230363330363933313833666438613837656339363036227d", "TOKEN": "041901fc38ce2757e6eeb8d91c430ec38aa256200c72c2c9e5494828f3d76f6d051145e8fc979af80ae7ea0afa7d043a78b9ce793110c909d9f543e98699820b95", "U": "04093b42673fb147dfe682720d58f62104508b6631fdc8ad5dddbb9f1afda1e1312165a599dfe47aa5b36edc9a2edabb38864a0e742cc5e5d8dd1ae1b0ce69cb23", "SERVER_OUTPUT": 0, "V": "0419379339a4b26628285f88414e048df2c774ab8799d949d4d376abd809f0b3f707d052197a526caa5d7344257d5975bb3df048ab2111bbb5c60d2055b391f43e", "Y": "0129d676a1477ec0f98e3b9bbcce240506727c8b7694a0c95b4308bd8fe93fef", "X": "23fba0aa380d00d071320aed405d52ec3045fa6c988f55e279d872cda4abeba2", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:41Z\", \"userID\": \"44d3f3d1c565c50d4750a82a726b1f0c@certivox.com\", \"salt\": \"006ddd943b0630693183fd8a87ec9606\"}", "test_no": 84, "UT": "041b4bf15b5d9b23507dbee9df71f80b4476158a5d32cd82d49e72e3d7716c36621e1d66ed4c7e3ac7c6aa65f577a74dfc2a5215f7dcd783eb588c14a93cd61419", "MS2": "1ade1ada200b19432c5f488fb03ab69f874a32dc412961fad1f85684bf841eda", "MS1": "1474a9cdc4c10aa698b3133e95ac43ef29e1b46de68dac3bd59d1b3d2faab6cf", "CLIENT_SECRET": "040afa64681dc3d3eff11b2978bd4590332493bd8c816891fd236548254ce1868219100a9543d1d437d6af5912cac2cf01ac5abab457ec7dabe2922dc5b5f99fae"}, {"SS1": "05c6bb794f9f731153ce1ada5b8505ac042b9fad0e6e3ba1c78095b6c3b4662414911195650e7997636da29da0649e067edb6f37ed5fcf639ef14c95542ac416120a202993001d31d9ea667e34105a1a2900bb891644c6a2e9a1c0400ef53dc609b532b6614c02904e13fc8440357b917a8c1248d71631376794a92b3936ed0d", "SS2": "159e6aa7734a9e499a2c98e3778305ba4ec17c2e3c1a5216dd66611e1bcc52390041bffeca47173533b7d1f75097d183801e172d8f26219c7b61272ee9041b031799a12092b063f233170eb379a306ae3a46c2aa16c77fd014483a608988e42223ded036957e0f099535413ec29310a77510d614b9f1ac22ae399ebfcf3773ca", "DATE": 16574, "PIN2": 1972, "PIN1": 1972, "SERVER_SECRET": "1d3989cebe5db62efcae25430f8a019c6e6cd00392e43d3d03924f78815b77a60503b342a652f1c49237898327f2d39cbb1e22df789dbeb7d6a527c9499ead6e21a22ca045033bf0788aeeb6d6ae073944f6f70ee579aa2f61abac391349cafa08d84a7bd2c49c9bc3c2ce9ccd9d5b7adb655aef81c672abfa1160f5462e7022", "SEC": "041a776ac2bf109a5f5ca008b3f3e8d21b5d91e5e6c61fc915d683c2ab1067648d0377b8ba8c74ddd67aaabd0d67915071020e2d952306f41f19b642f4381e5514", "TP2": "041c9c1e8d0e7152ea1cc16fb2718c0b0af1f43bd154a075df0c2844efce3a7b9e08003c8bb86978c4918f3435579c5ded7ae333bc30d0ba37e70d18244a46d8f0", "TP1": "041daf5f24a75262414ee997e3db4e83a197fc31ca26ef9f364f2c50bacd8666c02295717d495fe1b4d57eb94d033e56c2e60e8c54548eaf629b4801a7e30da0ee", "CS1": "0417b587c94aa0a69a202d141bc01d4ffb32923352eddf950d4ce3822de64b4e52014fb2b1dff48f26e9f04e2d51365a4b80dad7c1eabf6ccc9e0c5f5c32c3e69a", "CS2": "0406a4c03c0de367aa797448c763c30ae698728f15225f0cd398ec8c657a96bfe422c4e8e047a631c7f183c601f7302b52dbd92a8e0ca0ccbe4260d7361947cfe3", "HASH_MPIN_ID_HEX": "9d5ce41b69a2b84e71c4701cdf5c1689beb937467701fa7d27f88ea1952ef31b", "TIME_PERMIT": "04141e694615735e97002dbbe42caf1d0f91feddad6cd4afa35fb1c73887fe25b4045b55ec71ae1a2fc2881149ceddf66daacf24691ac0506807d26752ea86b3d3", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34315a222c2022757365724944223a20226264386130663566333762366463373238626639386261323734666330363936406365727469766f782e636f6d222c202273616c74223a20226238353036303138303233633431376530663264396139313634366433313637227d", "TOKEN": "041165d27adc025aed2919dcb16aef10caba6a37bab8b7e113719608dcbf67a9d208d0c9daa9b4742ca44cffe6953e651815505500958274990bc645c2c1b5bd93", "U": "04063a80a56cb6e513e767513e4a6e10488b67ed46ff79a28157872fbbd59868b60bfed79ed7b9fa57e19f3be82b113ad9069474b680cd45b03c8c2f351794bf47", "SERVER_OUTPUT": 0, "V": "04194cfcb472f416784229735eaae023859431f53f29c3e7d866b021c8f663bc7c212fead382db9c8be2b46329149835e1fd7da24e9ac64d6a29a470813aad0386", "Y": "192fa62c72bd062b8258f655c436bbdb266d2b7111a7eba423af90e5c7203236", "X": "042b670088180ada9d931c812d7600de3bc7cf70d5c8b331a63f6ea23c863443", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:41Z\", \"userID\": \"bd8a0f5f37b6dc728bf98ba274fc0696@certivox.com\", \"salt\": \"b8506018023c417e0f2d9a91646d3167\"}", "test_no": 85, "UT": "040a3d158546903660bb6d681a1ba53579e327fe8ea7ef3bfa7c7f66d07839714a2255b8d63ee0ccf2cf108de258a3a1b976065d4144ab153eedda411b5f22dc08", "MS2": "01177a6a9081a37b1f52fe3e9d3713b146d5e8004729f5d43b6fdc54dbf65710", "MS1": "173ed4de9dfd1c7aa98bbe58645268b90283ed45d5b230e00a2783868927c950", "CLIENT_SECRET": "040234fa7b79e79381f7fb9d4d947e29ba33325b698aeaf5b9c079723d391343bf1ad2664cd4f4fee118de578fdc00833208c9ed1f466904eedd260ae837c967c1"}, {"SS1": "15a9b0476f93ed540b612b854fca4aa1e79342cb593fdd24160ff3583ce59339033b2c8561614bfb65067aff726df6ccaae10e6abbf86b4d4b15f42bd40d81e901b0b5891ecf6746f14038a2e23d10212d52adcea79985f1c05fdb650c1cf8f818c1b29934d2112f1cc9d1cd01e709f61100c3e58d7a33ef771aa8c228137483", "SS2": "12ae9569f0a37c524d181286ab3e7b43011a40b1966283afa78f403b1c2470a30d3010341616e6b9d4bfc75a859205d06c9991154f04de58d727b17b4702eece196b5506388ed2c43023a1223eb3ed7248c40f250c140a27a9bb96920e57ef8913c9d39eca93031f789f2fe967f5305e123f2f4e1efd4e2dd97576e3a4053b6b", "DATE": 16574, "PIN2": 1255, "PIN1": 1255, "SERVER_SECRET": "1028b09e98d7d337dd4e243d600ac6cc955a7953b6494445a78350929ec186cb0e3a61c953d355c799797ccf0bb725e80fdddbb607860b9a84729d7c0399f9dd0014ced30499f276d50eed8cfedde8799dbd4ac9b88d9001bae985cca955f0d11945006f16bd302a9e0d6891a060d927960462ec72b6a0d0179e96154e6c5830", "SEC": "0411bbfdcf8e67a19e20a5d4037d787c188cc1ee798ab6e4adffbf0c9700dad38a1beea0d545875fb4a960adc0d17a25ffe1ea7ffceb36d38203b57d296a784ee0", "TP2": "0420abde83176adfeec81527b1de6630523ce12d7a7ba74866543824f4f7ba51a90fcd1822c47f218bd3f717c76051bb466df1370bdf3f5263ccedb9ed63be1c4b", "TP1": "040bf781e92095fbf95b661e0d90bfb5a4111f61b87e1578d75eaf2dbbec35e40904fdd7a997454764e4c1a257bb08a32dd548b29558f15ef358a731b58f82b5a5", "CS1": "0415877f2d9f055c144812ab55222021c9de65adee3ad0d354f2d14eb6aeaf606d1af4c86276c2432e1426e3e80a6d6f4785a2d2139bea814d376a891eb1e1f251", "CS2": "041fd6aeabf565155e3f979f18babb4a341b07373e763438ffb3e94aa759f41a8c06a799664db9b7ab23753f8cbe1166bcef184d5c7298b807c79796571f6c2789", "HASH_MPIN_ID_HEX": "277a3479f6872328251823c9cd3126d9e0a43bfb919b39cb13bbc420103edc5f", "TIME_PERMIT": "040aa9827300d89f8973956d4489f431f3e36827c2dbd799fa2afded0473e50e8102eaa8216e3a4d5e6e5a9f4baa6eda8407a711d110e97419e18f2d103eb5a0e9", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34315a222c2022757365724944223a20226330326530643761356166396134653435666562616562633334663533663762406365727469766f782e636f6d222c202273616c74223a20226238356130323163616532643838663639623738653539376433663564376534227d", "TOKEN": "0413b151c03422cfa21e278e50a054e65be4f82dc05e9419155382108c889b3fdf0dced28589a129fc37fa08687368bc012f715d0ee4284cbc143f0295d1c354fc", "U": "0405df68a89d66f5fe99f7ed7d501394b478a5ee4db947380f1520614ba8e19758210c5ddf855aba41155277184a0cff69ebfa755ac4a7ea8b4786138645807a24", "SERVER_OUTPUT": 0, "V": "04003ab02ec0b139f361cf7e7e442fc808edc86266fac6c5dbf6c5acc267e6055d1e54e654704303d68d0c462e803cb6966a5f9fc592c593a3a853fc9d618cc504", "Y": "03203bbd9274284566f25b283456fd9bd5e085a68d732069327cbb669f572663", "X": "21637ba1006a794e75a104903cf3175c3358cb42d0c6dc0c203fc6876db71238", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:41Z\", \"userID\": \"c02e0d7a5af9a4e45febaebc34f53f7b@certivox.com\", \"salt\": \"b85a021cae2d88f69b78e597d3f5d7e4\"}", "test_no": 86, "UT": "04184ed877b5ef099d7564772b5b87d316d514619a90c3429531b24e1c000d96721afda95c4b53b809da05ff879b3c7d338ceb4cf8e160550caaef1f8c4f7a89c0", "MS2": "170086639278dc5dc9e9dda5d32bee64be6f38ab60bef05db946f2565231418b", "MS1": "2178223941d4fef253cb594128732388ba97b3ef97ee2e1e2df3c017be568799", "CLIENT_SECRET": "04156627d733796135c0320e567b8952b655d5c9fa5d2b8ac0dc8aa6d4a3536f04229b53e379871e153039c908c04d8c430d34b6bf0d42a2d1f316d8ce570575e4"}, {"SS1": "0a71fb759976aa6c4355fe59a5aa39dacc02d3104f5b5ce8ddbc3dd7d9b0a06a09a4f64edfdf89ff198a32e1e46b71de710b0d55624b754f9473ef252c863e7f1a78cf6773b28a1abbf7ca224588ce8d68b4cc607d8cb0a60d37296ece5ad02907b04b9a4765815daa704e2631bdc616f27ea36a37df1f1ec10008e3b9fb0e66", "SS2": "0ffb0f8f3e278c7ec9cea1f58c7c3276beeb6191dc72732c3c29fc92800c46a5224f51b57b39c9263c6699859b60cfb077d12b37ff81e904a03bce82f93e83ea15e134e5405498042f41057e84ecb586e9fd4cc1941518d147fdc82afb9141751604838e1655db56ad35ca00e3b37565405f6a3a42c9cd9a0849cdec75afdb14", "DATE": 16574, "PIN2": 5086, "PIN1": 5086, "SERVER_SECRET": "0c3e76da0c65d7b6d483d05b82403f46a398e904c73d493e973fa488dc7e02ef1ea6e4e486c025a5a15805ed05956575380834a6db29a581c0f756a02b8bc1041a0828e65320e271ec35604accdac0c1be3063d90c6b0fee0ec6960786fa64191275217108748fa185147404ee9baa6422d938f19daadf137e5616e84cf5ee5a", "SEC": "041ec9eaec0bcea4f3c97b2638c22deade34bd14966367a8e3ed625b8a38da30ed0098c25cb78e38dd29af8378408513cd2f1cdadf36ec5ac37176b711a5e2f52f", "TP2": "04211074f946a006176c18d9b36d9987a3dd1da84075b0c157714a1bc016c835eb15415b6ec13203b7abe744d288691023b1a459bf505218579c0821f599e28355", "TP1": "04140d41a42e00a33d84c26780cfeec3aeb273750294f3c2611bf042aec240dde80fe3691a2e3a6dd76dff0ada1f00a1d96b9f914dcb42bd7bd93e460d30db0ee3", "CS1": "040b40bfae29e5ac0d26470b3fb3d0343000d00e0d75af7294a2f7aa5aebac01851eeb33afde72b94b2ba8fd19ac2dd493f03a53634b10804798864ee3f1c06679", "CS2": "041d0fd3f1e0ebfbc35bb72b8952b1f4a82907947617e59cb6466738df77cea479074bf29294e18de2c6eda495acc915e72151836f1c3d625a703b92cd9d9465d8", "HASH_MPIN_ID_HEX": "adb6304121e26d8009fdbabcdf72dca795a1e24bc50bc14391f34bf974d519e1", "TIME_PERMIT": "0407e604b36849eed7914077876ec75ade4ebdf55e4986c056ba2ff62c707ecaec1fb59c09ad9cc9c03ab27996cd52fe9f4b3325ae9fc481ebce67abef7f09f924", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34325a222c2022757365724944223a20223563336566306335366533363039393734393732646636353439346534343835406365727469766f782e636f6d222c202273616c74223a20226134643537323739326136616639646263363262306436313333636134613237227d", "TOKEN": "040a92c221a99ed3cd1967ea02bb7a262496fadeaceb8d2c9705e2ad0ebc351f1a16eca8fe948693fb23b3feee2b351edefe45a6d6e2500be265bda83a6e3f4b7b", "U": "04180c6fe97b85423b847c697217d7e525d40641a95ba8b93849be5dc1d8332364042dbfcf586a1adbae23e56a4f28503a0fb3ca55e9b730787eb6c96f6848129b", "SERVER_OUTPUT": 0, "V": "0406cbdb31cda5f3f37f37872c4841459646dd622eca5765ab3c10a9645e64a8b80ab8f9526529b5b63e7d9cae5cd8ba9b5826c64efe3ef6baa2a28f4cececbf9f", "Y": "21866651d2ae554c1d8b9d07bb690e642471ed1f6772dd0f951c8068e1054e75", "X": "070115bd969f551e1cdf816898921ba69d6291b91a25fda8cfe0c14c3ba1fa16", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:42Z\", \"userID\": \"5c3ef0c56e3609974972df65494e4485@certivox.com\", \"salt\": \"a4d572792a6af9dbc62b0d6133ca4a27\"}", "test_no": 87, "UT": "0419a6a2965727105ab6c9adc621eb34e1f7c95383647ca044eb4b6b924383c2a108b9275dd265bfde9be11ecdedc110355016a744daaa944f233db54fd040396f", "MS2": "182f0304b00d57eb9ef202f1edc9148b8fda7d5baf34f40a8cbe8f41d95aec1a", "MS1": "061fd8a46a5285f2e2c1c22e0f4a1bbc72adc2daba67b2e3615fb8e33fe2599e", "CLIENT_SECRET": "041d98fbe0e18da73078f44434e9eb0038979af2220b13e75b40ee9cd34f8b0a711924c89543e31fd945f0613254e65796ef98404d05e6b6907377a3fe14f44555"}, {"SS1": "00dfd083edc1f1b217760585b9c0ea522343f8bee6c662c5f1371c3e9654c61b15322f664f9181fab1b381e76c43e5bc742c309266eaf0916e0f8d0c703f705c1d4f50246d1c6f41e29d7311fa406284ac4a3030f7a057e3c6168ab0384d73d513faf162294e3b161b593d514ecacb7ff79fc8a859d730c2e45e049c12f4145d", "SS2": "0c5e5b08242a82941a3b368315e728b3cc3e35fd93d267d75788bb814ca964900f47cab9273648cd86742acf570490ffbae445740d8b54cbfe43c9ca9d49792623e3dde36620f8efe21b8932b5041f5d8f2db768fd68031de8da700055d683bb068213f6e10c77cb566d20c6e36cdabca1097ffe1149aededfac491c432a2e65", "DATE": 16574, "PIN2": 4270, "PIN1": 4270, "SERVER_SECRET": "1879ddecbfa9f51f3940628a6e185340ce25211114e0695a1ff106ee368cea2212ea40ebfdddecdef8509de4ee1c548c8fce555c3fd15b07a3ca43020d9c733820eaa9ba1a2010714041f4f25a5fa2d1daf0cf973fef47d33285036c8ccea3a707e79312fa1692cd359f94ca6ec79841f952b883864fe7d0d1374eb942a56f48", "SEC": "04131d7ebbb9c6cf101b34daf12a0beb526778895acd4855861fe0f76522bb6786193ed045ab1957a42c5e4b24f9f9f934f24c05c8ef3d8b8f9c4191e0818d9722", "TP2": "041b2f1fe394695b1ef702c9831cd0e8d4cc30ae6d40cb785bd6eb576ad9c563eb1f0cd5543072d4c6fc9c712f82cd1d365617c8e772afb30af5d71e9931313236", "TP1": "0418da3a187de45d1bdd5211bab5512f20fafe0866e1915bbf81e0d6c6bd3f96e823ce0b4be07ed143eee083eea43a96c18b1dd224c5186ac03e10d9fc69dfb916", "CS1": "040c5282717c005f556fe8b0a66b4b981fa1b1f6bbed98c049c11756d49483ad84077072553701bad201b6b4681831e21f042e36a86d3098b2efbeadfd89a1e36b", "CS2": "04135183c0dc0ddc5f09c691557974de26ae6ac8b8a9523db6947dc78f6d288c66045bb1398d15a0d74967e5562dfbbf8cfd3b7f6ede518d42a97f29e41bcb19b0", "HASH_MPIN_ID_HEX": "c2880d829778be5cc9d2321f5018688e0c49f0dddb7854974523c5dcc5ba924d", "TIME_PERMIT": "0406cb6faad9eea91f58d15b5ca41a9118a99f98d2b38a7a8f68e98f93592d8c78085a5f435747d44646285b284803e950fca1df0a38b677bdbdde59cdcbdbc96e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34325a222c2022757365724944223a20223231343733623965653964386438666663303738346438396265316632666265406365727469766f782e636f6d222c202273616c74223a20226261343463613236633931336465326663636235353563333437633735656262227d", "TOKEN": "0409808bcd383f45049d881ca2f782193bcdbe150db88686e849ad068d14a6545d1b8800621241f0dcbe052d67c88b1c5ca0169428a63832a4e35842f193d4e470", "U": "0403acb48b996edb4ca18af50f54ff6d04221421ac73250c116f1b136fefe08bc404b98cbb1776fd505a5afcf094189d64329a262079376da1f5131715f46f9be7", "SERVER_OUTPUT": 0, "V": "041186c5fd817d27b4a57dfc9ff21aa3218ab478de8c6550d25c3c203e26ede8030d15a53a5ea38caf5ca356b667c21d9a50a85c07e11fbd39490009051dd0ec4b", "Y": "1cffd28bbf9a36e6502bfb23205e29ae0d9ca2e20a3362ab83e024277c0679a7", "X": "0bffd28119caa01e14b31b99bed485ea8bfda9f5322a9e59c5b732a3916d72ca", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:42Z\", \"userID\": \"21473b9ee9d8d8ffc0784d89be1f2fbe@certivox.com\", \"salt\": \"ba44ca26c913de2fccb555c347c75ebb\"}", "test_no": 88, "UT": "0403535b12cd2377ad948368c94bc5a9d10f18090fef844e1d9dc1e37638c5e2e911a4800fb9eea09b7de4e24a2aa262c1dce634480b0e46aa865347e59da883e9", "MS2": "116e605eaf66011d6865fc5cf466e97d479f8f85bcfc94759045db21d0d42098", "MS1": "00602db989419a861ab8246c5fca5680069c3c5eca104a4e670f60408db96f92", "CLIENT_SECRET": "041fe61b61001edaf2983a1637943d3973b14733b2224296afc5cbe07736af8adf1954e17fdc37169c52ca0cbaa2d936bf3b3b7d560de360ce2bb3ee036e21b144"}, {"SS1": "07a8d11d6fd68f93afc4164e9a31dd947b2cf941dcff2e833196d6524ffcfc7003824deb51fe3fef929758b01adea11db41a1c85a1516c62dd2163e7188e357116c16ea4e8b92ed5672b646cb2dff5a2f7872a9fb0d4af402f02bba666b6241c0d2fe5d5bcf1477e7fd4eed93de9ccaede0a2f00e34dc75f3aa4f4630e4884b5", "SS2": "1ccedf72c90f147ec602ce8c3e3bc8901970c7597f60a54f8a659071b06c26f71c9c47648da517ab0113fb475bf74598c015a23f64d31e471d60efa3af69792613e519a6257e46610c6b7c040af5757e9b0dee8e18334d9f6d5ffcfeb4ebf1140e2fc936b6f182b3d7db9de1c2402f033e04c77bec1989ba4f86f62fbd60e22f", "DATE": 16574, "PIN2": 8933, "PIN1": 8933, "SERVER_SECRET": "02a5e08c1df941747db736856395e9a40bb50fd61d82259f2cbb30551d6d20a817716ac337fe05707a471f2dae136a7a3c0c74f7bdd395a604e4f5cb6beed7af1fbf43f1d5d5739e8e21acfd44f3fecaedcd678e1d27c6d9b279007d807256651a768256817e859c208941ca536ba26b6a8d3a3c1683f1cf114b78caf865d885", "SEC": "040086bd71db49bb5e837f7a176e9ffdbdd33af21b683e9ad1c0ef0833ef60d31d1b5993316eec35e3e0bd5add787cb5fed77708c39fb711778708bf5f8bd7c869", "TP2": "040c2e09381a428571296625211788c467aecb6e4cafbd9eb28a1075a855bfbec51988df72354e6419c669fe217c02b00f11330e023d1c0e3692795201717e0290", "TP1": "0414f99a4a43af4cd5a1dbdb55851dc5e5ff50f55dbb90a48c951d604507f0eae71d283089d39329316ff148e8398a27269ae743fef57abb123f3a5a02086e3f86", "CS1": "041f91d33d7ca42a760084f0f7387b11620dab04d2653cf369eb3606f30ef4879501500997af6df45a94b32bea9a26ea39863696f1a869422db0659d3e0749b35e", "CS2": "041f15b2783f4884fe0497d6196a24f26147a7a32f7f4da8462451f121e5d78ae5219aae126f0278f3dfdbff516e6d44cd08a4adc1e25344d0b529ef2bb3d8c772", "HASH_MPIN_ID_HEX": "632b5388750fc04da59984fca361fae6473375c65efeac1bfa6f05ae92c982a2", "TIME_PERMIT": "041dff9695558ae9954f87e087185f8f14778a123a5322cb739c72a5dfc81ae0b6210fb7339ca4a72be58142513c713fad797d423f011d93e458426b29afd8317b", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34325a222c2022757365724944223a20226334383161373131633533303963643834303265393732333633386465356137406365727469766f782e636f6d222c202273616c74223a20226663633730396666613439656361383934666133343735643962326363623936227d", "TOKEN": "04151e2198fd58a3301533a94ce9a80de13309baa2c1e4ecb001e07fbf8ba8b3fd226374c9a4f98aa8746c5a374e22edd406558d41bba12ba83b1b7510cf05cfa4", "U": "041fe8f22c2ee20cf628186e7a160401de905c1d1c8010966e6a4b45a39c01f11a1fd8ae9c4e3233de9ff27b1fd1d6022ea71afafee5670cb8853b114359b2ee94", "SERVER_OUTPUT": 0, "V": "0403edbec87f67bd87364dfb1ea312ec704c3007fb60cb72dc5bb885a4d01464ba214ac10c870674d2a47ce912fd2feeab8be6a5be7bec21069518874e6273f206", "Y": "065d4fc4bc6f8255ab7959f2e7997271529aa2de2e295c8166cd7f0174aaea7a", "X": "122fbe30638bb58b8f6878b9323ff28661cd56258052d4f22452f5a3d3d6b7e4", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:42Z\", \"userID\": \"c481a711c5309cd8402e9723638de5a7@certivox.com\", \"salt\": \"fcc709ffa49eca894fa3475d9b2ccb96\"}", "test_no": 89, "UT": "04026fe1e10ae217f7f124316e0eb259a6545c34ca7c6438fe44ec4a0d574c77bd0cf81d9a78fceffa45538d94257d6c44fbd4d0b743ea8449cb403aa380a72450", "MS2": "2287f55eb2f99851cba65d12cf662bfe323d5dba9ba74188778f512c7c7acc5e", "MS1": "04650dc8332f75995c6ddb39cf6ab18323e967e49113c7248c043ae0847adf00", "CLIENT_SECRET": "040a08e1280f5094575c54b302012f9352f6e21610dd40aa1dc4e89e208141c497134aafd45e77984d0d1f6fb5b224dbf3466b7dee3b302fc48d2c2032af22b2c7"}, {"SS1": "2347312598b1e70f541a0c493b9d4bae1d294cdd525431cea41513293c0c62e801b14503a68f540f0556893ebe2e3b3ea6f6e46e76d5d7a4b8c52c348e2e9aca05548625be8d86970ad3f6e47f2a1d827defb5b23180d837a18a9290e38defe603aa252d3b441f446a94b6ceb7105d19c05175e8a7d83a1a38f09a036f347f0c", "SS2": "087658a6fd05123d6aafb64cf7adce797b37b70a4b6d88d0f857b9e847961174114da196bb4aad64f21ecbb163ae4184484a54b1bc68d2b2a0e0dd49ff6114cd11e0f299ffc0802b2f2c597c26874eac28145137eed9b7ac3ff3497221ec037c1a15304b88e2b7be55f7eeffb93c815431b424cd5f98af268ada87d2231a7f3c", "DATE": 16574, "PIN2": 8897, "PIN1": 8897, "SERVER_SECRET": "1c1ff4d520ddb6892dae7e7c0ee342383fba38da517eaf73b55a4e542efa133c1a55a110d35decaafd1c4f95c42416797870f40d9e73215934c4a8148cefa17104dd3d5041f9e65f3b47cba3f7ec07b3a3731f04e9b8afece88524f452ec35b4196974b9a98e6467a92233bbcc5e4441f312697d0a4c6287ec80bd022be42834", "SEC": "041e68e9b917a99f733ea980289251a20aef0cf8812bb97b9f2b9e9263a05f195313b29e606dbd8f48fc8daf16e4f40c930b172146e70e72da3a7f7ef40c028765", "TP2": "0413b069f1eeffe9442de46fa5bde4a3465884df8e24b444790587af97db4485cc13ff469bd010a95953fce7d47c4b92b5527e3c09389c84d253543916f3f36067", "TP1": "04232d64ede2229468c1e96a5359d270255faf965830a451b93255702e21adaacd10fc77851fa408b053f9c1dae0c62eae6508d57e1b93adebb3892dc71f25d382", "CS1": "0401064e8bc6627f2bc6612f00c9c7a0dee794681be35bfdb5e5052adcd58e989914e9d3ac430a073d912ade6b83fec767577116cd8c9b26575d1fc667b2d9bec9", "CS2": "041911666887de724e03d0f100a1d5dacc6be9d412da9e84acf027b50e0efd26ff1009bbf02201940fecfadb850c9b4c0bfb696d5bd4891d3c41519095ee5cc278", "HASH_MPIN_ID_HEX": "dfc46edfd82e264554762fa2afe97a682fae9610df4c0ecbf7a02abcfa363190", "TIME_PERMIT": "041bc380b0d8e33ba5da7b925e6cf899c98c1ce68256bfabdd1d3a34ae03aa702212f91bb48a2622c6d2a4b9de23073273af1a59ed4386c7ecab972e0fd1731ba9", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34325a222c2022757365724944223a20226365333434343533373530353432306238386239626438653036613733363735406365727469766f782e636f6d222c202273616c74223a20223064626265386233613237333965653736346534633436386138336533626239227d", "TOKEN": "0404fa97240e58b891cc662a47e0d8abc9e0d42f1a0ed8fe93bd821a8a6bf81c0808b61edbe74cf891715dfb95af0b301965c884c7bd001822490b13d335c1627e", "U": "0420fcc5094063d1ef1260301766b1fc04d73c1a7b46eeda68dc51f69ad70704201b8a2ba2b26d80ed334dd6ec7028edb1aba05cd9cfeb76584de1df2df4983aad", "SERVER_OUTPUT": 0, "V": "041036d0eb774c9cfcbf0a07edd51bff9f85733afbbc41013b5740cf0627382a2007cb3e3d833c16e86bd029f937e36ed52a61d79c3a76f6929910accd237b98e5", "Y": "1b280775648122e96d6528f36149cb6b99cbd4e90e1c74cd747d278cec1e2fec", "X": "08009286a9ffb5e0419b68a64ab5dc0040e8387d63687cfe948fc62ebedec530", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:42Z\", \"userID\": \"ce3444537505420b88b9bd8e06a73675@certivox.com\", \"salt\": \"0dbbe8b3a2739ee764e4c468a83e3bb9\"}", "test_no": 90, "UT": "0415d82022634c8469116d184c4f536b40751729a65a738a07d33d0f243ae084400ec427426a5e1c8459c5593f03e7ca9a1ce1cb5cb2c95912c759fbc1a5ca2dee", "MS2": "09d13ca428e89a7854e528cda041c46692e496b720166640e30d136695e7d705", "MS1": "114671dd75bc56e848ef604d7eb07f37f82a72a631e9cd2998bd6f3a01d02197", "CLIENT_SECRET": "040303705a4584359ad9c94f154185a0cadc735b5e498278782c6cef3f5d33c9c4220ba0a61cd38d11a23c4f32f4ffec829ed7e1b0e52ab5e8d57591d7b9c86ddb"}, {"SS1": "02d604c99dbe8ad96943d17b20601200d8e06b2876d9073162574705d3cfa93909a91c98a780f8ea58aa495e925a963246d7bc0569b2dcce4218886b3093ada4049373f3d980b817f96288090012a235787407cf16c261dffaa3a62a5604ccb6052467d373ac98c2aff97aac8ee9d35aa1fe80fdf727c33a926e5770d1c8466e", "SS2": "0ba8bb63f67b495a640c98076e6d0379dc9daaaab0b76d2a0e53a2d9a950f80503791b79e86cf499e1e84afdec977e25c5f8fb638b1c3377943df9a38c7cdf0f09abf2aed81249590d7268c0b9150728defb174e9e790e80486648aca4871c0a0608e143f8f2eba4951e587f96fe49fedd39a5f160356dfb32eec3001bf3e0e9", "DATE": 16574, "PIN2": 9935, "PIN1": 9935, "SERVER_SECRET": "180d66eac37fafea20d62690a492940044a151243d6ca791d39b7561a10678521367a954237b457d550697f4ad7b5aa074487fba9f6841a7a9745fbd9878842105690ef318de2f1948adfeb971844697c8fedb333e2ab68d458e16cce80f57ce16b522129dc4caa0bf335bcd31dc68746ce46407c93c02675266d9af52beacea", "SEC": "040ba4816166e8c21cc07a4b7dbab13faab9dd93d00a42bd46df45e3bc6b43cc1e081e738f7d8aadea1c4ad5fd368a0e69144af810b5688a83fdd4ac660a46c27a", "TP2": "041f6df10bba046b75f28333be95f6f494c0f4011629d48b2d751011a80411d70b1939436316e6d5920f4242a3cd4c43a7fae1f9b7d14b5398df2b014a7d525318", "TP1": "041ebdc2a27780f8555dcb6149a8ab6d050b81e86d876f0a188e456a47b6de436e0844419e61dfc77b3f36df72fade6235f7c22c9717e10e06c4723b4aa3bf950e", "CS1": "040d9fd1d3e4b50aa260a5b1407298a6ce4ba457412f32d06dfb1df7f84416f1721d6c0b319d35c266e167ee2cc47bcb226350c4e2638a91d8702ed11dc5999de8", "CS2": "040751b3085c081b5ab7c7a62d1708179a8c78d8568978c0145f3470607b126f830377b08876e78130b8838d73695a7937744254513287084a9add948b6e661070", "HASH_MPIN_ID_HEX": "eb5423a25e1526bb3eef42c042ca04685d25449257eb7f0f1ad0dd94e1ae375c", "TIME_PERMIT": "041286723cb8f1605c9ab36eb23cdbc2949d05f9be9550d848c7560fefa3e0da71009ca5f26019fa077d51b7ba2f78d2dacb1bd7a46c2ae31743b03a64f5dac832", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34325a222c2022757365724944223a20223732323539326461663466646433656162663834356466336365313562373664406365727469766f782e636f6d222c202273616c74223a20223932646631373432313266376234373662623161623830343532636230366433227d", "TOKEN": "0411237eac80f598ccc30272d6aaac3678fb61ed5bc8ee40bb75224ed3568173e518a3eabc5c3fe058e2240d50b3ad702f45e9b6459e8f9146a790ca994a80db93", "U": "04045e145cfe8bd4dc9ed0e3530cff7c459e5ba1866b26db043e33dd4fdab776c9187c91f1d763357ba2a8aa1fbbea2298a292944ff54da0e07f06944ed86e199e", "SERVER_OUTPUT": 0, "V": "040f0d67f4e37290a1ad7429ec153353b777a281b4355ab22acbb28e6638d1e14208e6d92a044239abb130217a786155ef457976df86761287390004ab3da36b00", "Y": "03a2d15c45b1353564ea42095af98ba7793c80f4d57c355e7ef7b4481641f95d", "X": "07852dae4e95ebf1659601182f7415be5ccf7b5f1783157365fed2c4aae7307d", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:42Z\", \"userID\": \"722592daf4fdd3eabf845df3ce15b76d@certivox.com\", \"salt\": \"92df174212f7b476bb1ab80452cb06d3\"}", "test_no": 91, "UT": "040d1d31858e34f3c7e0728b42ccd089100a5ee222fa75daf9e3a75d343d8e27d5202a1ec6648ec536b8a8d068836985d6f6c44da10b05cfbdfb657e2bb76f4a25", "MS2": "1982434156d888514628ff80e41c65f0e499dcdb295783bc017ead2955520272", "MS1": "1941454dd79e74480e94ab8fa48cddb341c8e9707338c94a1a6c145f2238e621", "CLIENT_SECRET": "042337024de7446447f0f0f2da7d09c29b9c597c5c62ae72cb878fb18bb9c783b014e00e5877796338d86430d36ffadc032a517d1cfe70e9b286772cc79fe8b0c2"}, {"SS1": "13c17a6b5aee88eb95d37077f20856eba3cd2df11961f914c5ac6fe51f3e79061f281eea12c7f8c143e4ead51fc269d8f3130e8a4dd9deb918133cbc326c7a58009ea6875f8d9bce8a17bf9a31beb6027862b851818d0f5901a0a28855614d930a52a5a0df9290442f30307b64dd652bf3d8b949a227fa1fc8f43d74df7b9950", "SS2": "0793a1ef51a581767ce5f47a1b5ae0722d48aec1c234ea3b4b0a884fb3ebe677187dacdfa211124e063145ce309c8880c0fcae60beeb1b5a56182baaa8c564580a9d5495cccb9f6f5a87ad8434c5a5117aac8fdff2255e6ff189d7b659be198912b2349f5f135a2411ea250af1c6bb174a10150f0729815e897bc07338ac486e", "DATE": 16574, "PIN2": 5150, "PIN1": 5150, "SERVER_SECRET": "13e10c6dfc0d673fad1e3e0dfb042ca0640483257100dda8b9c41770e39e776c0e8186bee193e58069192307d524b741b805360038280eadf9ed3e7879bea3992315f465f428fb2c3bf81710871dc555ca7fd787645049834e36a73025fc882d1d746ca2635a71b3abbe5b3ede6eab10cc86b3dbd65377f50fbe7fa131385b9b", "SEC": "04159974d191e2f0509566136631221f2efcc27da3bc591e4c7d2bfcc51275f8be0258e99713f9634cc33d2277016e4ca762f41bc878d412ff1b1a7b7e8eed4a3a", "TP2": "0407d18bc4c1d01989f2f0ae9bdb3fcbbd0e34814f48bfbdd1ea5c9c6e96e292661d9d47022cc3e9d5f7782780c94b0311fa1ef5cbf32704dc7d400bab40ca9352", "TP1": "0403df0bb9f09b6b8ae4b79f4b71d5ddba68dcecf72aa73d25a838cbd7248db4af1c7ae5812c8d478df6f95bcd0d915e64fb6181f61cb1e405467ac501471a23e8", "CS1": "0403968aed5eb30d20f6fc6d2cc782a780134e1c61295be77a50641f00c6c8683a02c1e993293abfd883e61c197582d12c00ea9bdd9f9efac91c4ecbdbc38e4618", "CS2": "0411d84338d067b6a915139409b5adf50ecb4fe65a852f8a6dfc8dd0f23c3f48ee1037c13f34c35114bb336e50cd957f433870ba442fd18f2d13d4b9cb9bfcba66", "HASH_MPIN_ID_HEX": "50396b01de71f2a5126bcfb46da71d3e04bacf255ebd05561d8ec2aa05398425", "TIME_PERMIT": "041cd33101119a915d6b93d79785855cfae91a772d7c484fa8265e023bef8fb0d22166f1b497bee3070ad304efeefd93f20288892bd257dbe84180be60caff301f", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34325a222c2022757365724944223a20223630643161316335363266326366393237353836393734643634623362333165406365727469766f782e636f6d222c202273616c74223a20223039346537656534666333316662333966393861643937356163616232343863227d", "TOKEN": "0403ca01b3c91e3be4ce7b1e36d2d00b4f82722e6a31cf4275d758783665b9eebe1825ac73e2db1842e756909513aaa56a8a879e9fd44a42b412e929e3e4138077", "U": "041cccff02fe369a404b4f3e7a09a189836213ccb9d0dfe5cacfb00311b06c2ea61772bd144092c5c92c140f4cd99d666f0132f6daf91a3efb06e40711fd172f32", "SERVER_OUTPUT": 0, "V": "041a32eef94abbdf040abd77568df3b19bd489732faaec0983874f886e0f7489761503c4358e352afc7bd8a84bb18f4076f0ec079e514cd5d96570523cee5d2244", "Y": "02f0f8b13b21fb8e9cfebbaf17e9deee35e993b725538ef11bc5694c634ee3cf", "X": "09f639c29bb3814d9b7ab5e0a856b8674f71cbce8a80b7768755ad180a96075a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:42Z\", \"userID\": \"60d1a1c562f2cf927586974d64b3b31e@certivox.com\", \"salt\": \"094e7ee4fc31fb39f98ad975acab248c\"}", "test_no": 92, "UT": "040d939b9e8ec69a8c1f846f86cdfb81bb68dbbff2698f723e1e184ee3ac9da8fa2368327979ece22e09120d44563b2cf57c9a8edc662a49504a9d165b0745c7ff", "MS2": "00d1c86efc3e9d19d8a8bc5c7869995ab72a2b76a4813a5f96afc09e2963476f", "MS1": "0cbc951ca4fd45af267ddf3413bdb9288ce72f39ab23114ea97f4d7d4d9191a0", "CLIENT_SECRET": "04193b5bba30803f9ac0191bd15eb291baddbb3aec31b5caf282cbb599d3e5f8b01f3d2909ec29f76b572b3c2e1ec00844042703b090646097dadd567b03c7da9b"}, {"SS1": "14f6dcc3e21c658deb97eab3c0f3c202928150cc305e0fe097bc32601fec11781e79d74000c83df5fb845012fb4b701045fed9d71fd0cde4de13d0d62453c0b60a9b0c0d1a52d076b62f5ec29e5413e43bb406c10464e3fe1518cbace544c74d1e2f605c53264181991e20e5d2889cf15173493a455ecea8e826400b2e8cbed1", "SS2": "0c712ce3af814d53cda7fcbb9dcaba1439310a6d3c03d74460a710b90d711381201556fee3c9b4103163e39b1cd56feaf9d5fd0fddf4943720fae0bdf95643ef06a4d04582acfc0fdb08e5ea10850d6dfd6cde867e78eef60105b6ba7b5751ec0075a718706acf01aecd7848fced969a334baf941c00ff2fd9863c6f3c1196f5", "DATE": 16574, "PIN2": 5140, "PIN1": 5140, "SERVER_SECRET": "1c1fd8e82eff74a36427f592e16d5152c9cc9b77c3876b4635d04eee006a68c923899fae9ea0bcb1f08e1a2851d651e2939c4eb64bac8a525c616dcd207f0b9223ae04afd0730d71d92539a3986a29263c5828fe84e952d16965db7e28aa6f6505af21d107a3cf2ccf42f895c22b99f2dfb0d11797cc80d2aa61b71e5563d083", "SEC": "0411c36b092fd6918a87b6f4f59c4f00d0b0570be5532c1776b625ba25c1ba4b8d1df3e8380c97e3054c61bd596866104194f3a61ead4b8cc23c0cb3e047db638f", "TP2": "04076886469564d7dcb54de89191eb36d7796d1b651e4851625ac7e34b116365a1131f82b1699425dccf0b53f3cea2120c730996d6a6f90dcdf468c28bdeaf55d1", "TP1": "041a58627128aadd789d4a0c1245cda2d84a706d0db163b5519f7957461a27b65420295c333ed98cd0f49134a2c7bee261d512de19dbfe031d68f7fc6c0f03df8c", "CS1": "040c7f380eb6a178cc1d3bc175dee567db56a6d41831ab81e9547586c7a7d93ed100286cf307fc2ef2b6a50c75782d9c2bb046048a6a6fb831c46c33766f07045b", "CS2": "0411cb09644d4b4795b38e2750df64800562aac4185ab82330d3236a286f6e06990bb74517b32d5f1a815066d18cacce4bb1fa2264369a75c4ac47c093693b5cd9", "HASH_MPIN_ID_HEX": "b88aec13eec2315a764effa6a9f1cd4e17afe0bea682d9efbade7a570ae5b8d6", "TIME_PERMIT": "04131d403abc80b61514dda3cc4e8d2b0949ca9b6fc2d887b27b89933bfeaa97b80ab8270a08b19866d5fa5cfa9561925f6849f22aadcebed2bd586a06230381ae", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34325a222c2022757365724944223a20226535343932363562616263353937633832383238633064356536356234633264406365727469766f782e636f6d222c202273616c74223a20226337343834343363356134316539633532396433373638333437306439333262227d", "TOKEN": "041d5cc6ad81906d8c001c89599997e4397d3fe1ecf93ae13982c44d661517d7c212461d3aadd5fc1c753856335932992c2404b81cc7b562f684dc661293532493", "U": "0406499b0fbc312796a166685aae88cba2904b8d41e3d9934b1945f97829b668c0057a0c230e03f4319a0a85cd7352e2893cd71bea307be407a22722daaa212eaa", "SERVER_OUTPUT": 0, "V": "040105e584712e5a24d8b579df4a6f49377c0148145abfd517ffe229da26cc2e510401e4278d47d2519377decaaca7dda9556da9901ac46d42a595ce3aaebe102d", "Y": "231f39e9ed8ad125f847380c80cc47be5740271db3f2cdc37ebe90df1b5a4824", "X": "232dd145396bf97f683bcabc3a062637cdab880fb6d4a227401adacc6fa8c2be", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:42Z\", \"userID\": \"e549265babc597c82828c0d5e65b4c2d@certivox.com\", \"salt\": \"c748443c5a41e9c529d37683470d932b\"}", "test_no": 93, "UT": "041e64fbbb0286d08a3529ede905d553507e2dbb7ec53917a5f4076bd87ae3ebe90f2fbcf27fb677d4d431a99108e22dc8a9a95838f7edceffa6d9117173182026", "MS2": "0770f5b2cfcb4bf662d767ab0b3a78525e454b411a53e83e26b27ec1e2a37912", "MS1": "08edaff61006ab87c4b2aaafc02cf89ac5543437a4cdc076103fee024933a7a6", "CLIENT_SECRET": "040768fe5cee4a5cf5f73a8b72b3303566a823a4a5074a727bb303313ec75c28b61a041b3c548bbcc1caee215e0635a57e32f2ab18c72e15181fe5486a9a7ec401"}, {"SS1": "07ae0f602308519bcfe9f958f1d7f0bc4d1b951182a1a619042ac5e4433b646f1c0dfda71aa4ffe3bbe4b25e1df94988f14d80b51eb42bbbb99618543fba3f110a569282857ab9b840ff3c0488e2104af22053f10887765668928369bc1c57e80e0b07bcd700399fe491bf0b081147c70c29bec122db8db7aae4e0ea1268c106", "SS2": "1a2f457a33de12d8c675d90bc788071db60373b98bb0fc533b0e7b4aed50823602c7be6faab03ddc0b97c1ffb91e7268193d5d9183cd473a09130cbbe97c8dff0b83052887d5602cb14195b9677d3ed7dcc24b98501b67cf27cc659e5eb9561600d52ad30583ea8a49310fcd73fa9a2bfe503aec39395745ea917cbca57eef66", "DATE": 16574, "PIN2": 4207, "PIN1": 4207, "SERVER_SECRET": "091486c09db4ee4bfba5ca2b4068e6f5bcfc010124f5f96b72fe5a5eb74094a619fe60bc5c7da22562d1589f274cec9b3b8049d805f63bbc5e6063c09916058e128707b5799d5ee98516a1d0cb7e738287e3c9633e383d6fe74b3bf1d70336fb0461977bdecb81e96f8731a8009f71c365bc4c6b276a66f45eaf7bd08b0e8205", "SEC": "041e342741de422033c3c1b3e95606b70995b8ab3410b96abd6670e5da9577453b0ca36b0f13f1dfdd1e390a289c85ec044492a25d4900f501816773cd9fa8b294", "TP2": "0406507696ba8cd2fe7081f21edd9c72053d080f35bc9adf26672a14f666c16a5f2149921dd6168d98952f64d5fb955e1619b5016ba1c09031de2ca08f24f13825", "TP1": "04136cdddd4bcd602181ff5594464b989c22b470c36dc7947db2bb6b03c39aa8f505f22817b39d9efb638f6401d56650c71eb23e3bb7b5094478b9558129b0ad5a", "CS1": "04134199a0d5b7fafde379f9f28e2df6f27d474fe4cf52f9387ba2d9e3b6bd71d901bd2bbd67cd75c1c062015e96b1e92f4b2208d2570709f71a5cc1f043a23e0f", "CS2": "041b67daad63d790d52b901b970535c9ab9831bae7a6ac17948bfda3cb4031e34b0d24ae518ef09f64cf1bee71030b211e8065f7e84c46afa101c69cbb208f094b", "HASH_MPIN_ID_HEX": "42c1f8155ce2f1d0f4e42afa185742cfa5aab343d73604ec3fd45703dce1a2ed", "TIME_PERMIT": "041eb9da7cf51221a23a24abd65865a1b36818428e1269b68a891be668e0f6383a16a5dec1ce57bf56cd412c814d727b8666d9b64da69afe79f00c2c3113cef46e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34325a222c2022757365724944223a20223964653763653134373637323035373465323033626263306434653566643263406365727469766f782e636f6d222c202273616c74223a20223836393666616365663065663766663937643534373130326433666631666665227d", "TOKEN": "0411d83a6c8a2e75e842cbef0fc8d5190bf5bcf504d3da0b64aee6f7d00c02b82a02e65ff843a33a74bbcc860785bd43a90fc729e85d2bd1d7bc8c5d63157550d4", "U": "040ceca0da69b4c4e49df306106e3ab2d0fbce862353a6c6e5af96b9e68fdf41860259db95697bd0d6429a070f9310d814675092086234188142c57435a0d7112f", "SERVER_OUTPUT": 0, "V": "040e0e573515242d285084e50cad2ace8c4bd6fe76f2e33188928a597484c652010c228b23b9abb69c20eea800eb9af9459ad54a31f9eeb233ff767e568019cbfa", "Y": "08ac7bdb02bb654aa5254c8f4dadb42fc5964dc5869c8bf8aadacb76c76260ac", "X": "19e9e77fc0b66b39ec3f094c1743060ecd82951043d66fc7176371f1b2ad4440", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:42Z\", \"userID\": \"9de7ce1476720574e203bbc0d4e5fd2c@certivox.com\", \"salt\": \"8696facef0ef7ff97d547102d3ff1ffe\"}", "test_no": 94, "UT": "040154cdcf5b2adcb286d17c95c905f251665e091510451333957df1ec5221fddc192c517a6e3d7004aa134fd388462634fb4bba42c0706ce9bf05d68760d897e5", "MS2": "20f672e0d167e5aa91d5aea7ed740ad8062cf6ac26b6c06d1fc719356264ba71", "MS1": "0bdef0aa6d92389ae4def2aca7cef69c327a534e001a5002464b039e04ddae46", "CLIENT_SECRET": "0409480df4f22090fff35075bcb6a232d437ee45cd04f633d0d44bc6b43c0111a41fc12c265354f4e0c919ed69d76ebf1d80fc09a1aa674b036b735b9698c22a07"}, {"SS1": "033bbc9c7263250fe4c057ea6bc2745905a19c80a90aad1da4749b1d6558138d205d1d1bf70e95598cf46e1d1343af8c2f262e74e5f4a279032f7bbe6aed4e1e1a331b8f7d0ab4acf5b8c8084b929506b39400511f894ff4ddba03e19c71704016658c8a8620587046c8493ff4564a7715f6a13d04fd11f938637c34ab73e355", "SS2": "024b3b4b2acffe70be2438ada0b83355d009362dc8f246e5ff200c018b7b1b320b7d44dd7c03e7f55a7e85abf910dc62dca6f1507dbfeb6a6743827daec76379124ac2c5593fe2102df95519a8a181eb6b1daf2779c23fb9b192b90fa1ef5315219046f05b6753461031501067c6891ab49f15972450b3961bf73262b850a9da", "DATE": 16574, "PIN2": 8448, "PIN1": 8448, "SERVER_SECRET": "1eb353b1874498946cfbb5f6e845f65b88b351587e193b21959c47a8c0dcbdf41c781496eaf139a09649279d5ad15e70b40f855f04655fb3281291148fa1279f1efa8f54620ee6e2712bcdfd29a6a6818d6a150e7a4e8765145feade19d88688024b3f6001877e9492f198b98b6aa0f1b9180cad5562eb62d8663a3f0f5ad593", "SEC": "041b1b6e7a4f20a40579a602c1470ac514b2b86b9604105518fb5705b3608aabd1124d975d4ecd691c0c9f677a11cf87d8485c6ea613b2f2bb7eea9c07e2cb29e8", "TP2": "04113c347d5cfe50d6631cf8367b66b4c8add52d55cc6eff2f12d8c5c62d6258551a7721401f2c64a893cae506f179ed83019715b5580fa6dc94c4215937077b8d", "TP1": "040b3809dfae74aefd5f340ddb75ff36dd00ad8db107bf7a84129236683297996e14a0b19b78641ba97e1b2fb45c2e18e4836c55b8c2bfb005f7ea85264dc6f058", "CS1": "0412bc1784dfe82c9b209987a78fcfeec4bdb584f30e03b45e65a30e998e655d4f154b0fbe386aba393079b445c2d61f7c3372959f67b027fd334cd01c55475db5", "CS2": "040df15f087cc64ac9d6adda8b51eb0fea283c6af62975dc55dd8d68330b2411de086468d452c9194772ac5ec153af8b17babad6ec22ac239af9e87d0fbfc689c1", "HASH_MPIN_ID_HEX": "b1eadc2680a6b952fb3acc73aff3afc5826258ecd88062f00fb9ebe98e0c914f", "TIME_PERMIT": "041e561a0e15127b94e7edd0937996ebb8d8fa16009e47d7ec551ed38f1048942b16afcd737117fa774eee215dab59abc43b11e6fea469a6d1bcace8f6a904e1fe", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34325a222c2022757365724944223a20226462363062643135353933633534306638666537346465633239666532316166406365727469766f782e636f6d222c202273616c74223a20223364636630356436323930306237326562653034373935373465376537386365227d", "TOKEN": "041a77c0804911d0a0265e156b95ecda06f0e1c2f15acc20a52081d05894d39cd304f0082422370292da36c755c7b4bcbe1970b6b787fbd9c174a4b7ba92b1e0bd", "U": "0406696a5a3b0b02aa7903130e5fe8a46bb45ee6d94c14eace072a2bb5b0df336613b366d59d53a00630369faf445b345b689b278be25f8acf756e4d258c012c6a", "SERVER_OUTPUT": 0, "V": "040376f9bb435608f61155c1e8354aaeadf859c3a5d59535d8568bdc80b944a1270c33dd301f955f07ea42e5586e1424f237aeeffd8fe6ec659c603d4155bbeb33", "Y": "23c047d8fe2774f1b3e3f37dd7e700a83e14888c94dd470462000adc6b370342", "X": "1d595b3770ad373fcc1453acc370ee8c08b24ed9eec47051cc74b354b6dbb589", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:42Z\", \"userID\": \"db60bd15593c540f8fe74dec29fe21af@certivox.com\", \"salt\": \"3dcf05d62900b72ebe0479574e7e78ce\"}", "test_no": 95, "UT": "041e58b99f57b550a019d78f5e0be862f1a477eeeb3ae5c588d5938de1da2b05a704b2e2baabc3064f2eb0b8327e80bbaed123d266a084e18d82613e21abd6f115", "MS2": "0faff5027c2821f57c29eb3c62d29daba279dac83de6d3882d64f9f2b16caca8", "MS1": "16847bb451ed584e57ac0cad81422611fd5bbd77b16589a513e3541853084cca", "CLIENT_SECRET": "042131a50a983994910ea0768e303b851bbd3c8ed876c3f093f22019de18e8705609624991e359829e0f9e930306ea947df12eaf574661ed36df5efacb67476ecb"}, {"SS1": "201da16e56171e757072d481bffa965ab5a0456f06134586aac1dc6097d6ca3323351990391073108253993c5ba0175d3b83f6d4636ce16e4dda494f55c09f8e1d011b56cae3d18f063ed37953f95a71c972324afb34d23f72f75cba789f5a9822d491fa9a3d9313a911c4fca5a7299f8fe9c66d9402bffd76b356b210a054dd", "SS2": "1642a0e24111176ec647a7ef937bc9fc5e96e60ca1590fe9075652733942c0a8180efa02234db1808d31ccbc9a7c45ecbd5f0b9ba3bd2ae4d39eb0091785e43205316367aa0888c220428eb6d96de44f84ea0e643f9ff99fa8090f9a168a9ea414b8a9747b4f8a182f46a90430e10f559a5a8eaa9375150739294fe5a0e36897", "DATE": 16574, "PIN2": 4655, "PIN1": 4655, "SERVER_SECRET": "2246ea9161a2e8e4e2fb619445d924f708f61578e68daa41c13194c0787a7a7d00b1eb1523ef52d3fcf62bcda8f2311975888b9d9fd0af5dcb17e574b6729aa01d5057dc9b27e2ca8cb938fb90fa61b21fed52adbf042167e43e07c228490cdc12b8e40191c8e68d19c6b3d44946b322d360413c153c8f44267c58da85db4d6f", "SEC": "04102a72cc12f5567cd01d3a735cd768034eac11cc1f8c2fc2c80e9d18e90805710ff92bb34bfeb05199536ddcc08c50cbc5d5a80a6d869a94f902a035998db497", "TP2": "0404f8a140f6b02fc05281e0c70c27af3617a8f6e69f05ebd63cd1c9827199e51b0d8d870ce7688404450658aef86e85403095e7f34532b55e2e35af2a3a4c113a", "TP1": "0411221ddb951115300b47746ce712084db1d59f22890069b798396eb4a6a3c427016342600e48011a62d6072247e6df0247fdc1c4d59b7b1523f4217a04fafaea", "CS1": "041fd1c651a6c6534af301f6934ff9b0f1bf904d2888e4c9453e97b887d0f2b14d12199e464d7f6b7255bbc0c31540dfd23ad237b9dd37863bffe6c879fdad013e", "CS2": "040af4610790aa958d284069b8ca72bbb84a29f6322b4bed65a953484174ff6f4d0489be7548106627e43106cf89d799c8d7bc79f591722da903c56182e1a9ae17", "HASH_MPIN_ID_HEX": "6199f7805403d537d61e01752a07140c66ee2baf4cc7d7aa4ea09cf78e3d546f", "TIME_PERMIT": "0405db9b2497caa5231bd7ed742c7bf67ff63eb5b1d9059f02b6921c965d4bb98e1cbc68c75db2912e983ae271263ad161d2519851949c1ec893fa9767b35ed030", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34325a222c2022757365724944223a20223238356430333230643031313937356362306364323136313732363736363333406365727469766f782e636f6d222c202273616c74223a20223463393131383561313231633266323163666335653635353664616333656632227d", "TOKEN": "04131ee62cbfcf807c406dce65b06b680f0128b951694fa4c3e9f4de32dcc4f48d0bcc63acb1492de70bfe9571586a1c554600c5393bc76aff9ee6e89abfe305d2", "U": "040e7fabf872cbee9ba7df044c6ba56b3aecda167e3c47277c9afa54e4d46e973e19283b622fb2b2adcf053634311d39e3481de5655ae13fec961439396c7842c7", "SERVER_OUTPUT": 0, "V": "040ec7664bd087696edb01c43b8f252e3612d14f1db9b7985b09b7de9f1003f1060948c289f414b777961174eed324818510a6944ef4cc95ee76a7223230d7afb7", "Y": "1d0dc6a5fc0c9cb8d0b63c05696f1d346571cb640e9321e7f9db95a53c4bdfb3", "X": "123777779b7fa7e6c098b1e4097f4c082e9ab7394d9a5d401d0de107288e48d6", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:42Z\", \"userID\": \"285d0320d011975cb0cd216172676633@certivox.com\", \"salt\": \"4c91185a121c2f21cfc5e6556dac3ef2\"}", "test_no": 96, "UT": "04069c7e5e5ad69a29b0c5bb73f2e930f09ed47fbea3242a88754289fbf0bd22f5109768953421e01e4a41aff2d4c30c9788d86405d40de26a3ad3c314938f424b", "MS2": "18c670e856d88b070948554e26e1d215ae9cc497c240e3e390ad6e384749a7e0", "MS1": "1d21597713d76016e720944efb930fe2238ddf9a4b465a76e10d62c481f5f48d", "CLIENT_SECRET": "04037aaddd360201dde7d63067f58961bbf2e27d2d6cc82025eaaa49586c03b7810c9fbe40ae9a37f6d797e29fbe1699e47458d43cf632dd7c03a16247cfa17bf6"}, {"SS1": "0a8ed05020a86e5c04d6be28d4d3095f4408c6740350c1c8f8eb534b835c547c005a53a804cf0ade904730318ceb54464e2cf6f6f18f997e639224094e30c6981590b833da4043975e64e5b07e9e8109c45438827b28be1fc60fc8ef0eedc38d03e27ceb99fcaac6bae028bf7d79a3aebaf9cd644824ea4864f23c716bcb0c95", "SS2": "15dd02de8f1f4bcee3b4d2d8113048168318e31b6469ef917f80d7dc886c19780d09ce597875a5b04757d35a15a4820e900ecfb58937a3e250cdb040599f1ff80cc6bc1c68a912ac5cd52de310131515d1d1c11bb471bba977a4b95220e0ee241656925c17cb86cbb3f2d97afcbad184ca314e2d92c4c933f845de47fd7952a4", "DATE": 16574, "PIN2": 3105, "PIN1": 3105, "SERVER_SECRET": "0d1041488e95a7f546d5192571e11bdce0c0be0b9710b27214e2755806b97f3320f0be4200ee90b1f0a008f64b51b8734bf0012ab2ea43a820d6b9656c04c0bf091354b65873e96faf113b2e63918f617b948c54e99f1d44b6ec6e27a284d0231cc135fcd4de66ffc43d81c6ae45b8edc007c74147daa0dca9dae802014423dd", "SEC": "0419302e7bd089b80e357015869bf6f7e87ed017292484200c2e254c7b8fa5c396117e980d4da50fd6bed0fd7c107bb2760ab1614daf8d69c81ebb2c45e2eddad3", "TP2": "040c43791cc2d5b693d92d34157d6078f3161cf6c8a8d09d73c7ae658ce46914021e6df9e3b524d3f474d3dbcd65b3e85a600723d02ca0dc3451084f65d9210324", "TP1": "0409572ea6384ac5d7de14638b2a2ebf5aebacf38c7004482b2110a07cadea92ad0bdfe63f3c05a96fbca70974dc7999376e15757b81f54f31e2b5db9eacef335f", "CS1": "0422646cbca2d42dd4aa8537b1ea2d6ef7593aec59411f2184790216f5f266513c1e2ca63faa9699700cc54e269a7ed651c441b42c319ff290130ffdccc2851280", "CS2": "040a00ce5ed672a7bbdb3c0dbc26663cb254253acac41b279b34f640b8f8ced7040297a333a5784bb466a0b6db1578b38b2821773edfe973930efd987e7c09b7b9", "HASH_MPIN_ID_HEX": "2d111fdda46279e4c6bcc5ee44e79f70819dee84ded3ebcef5e92666741782f2", "TIME_PERMIT": "04239b12ec89e163f4b2e6818bdc53f825452688f10cbd90ad50d9e28056826f6c1813dfa20e324a9213d18e04f1670f26ec790ea465568b9fc0cf56f17767568e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34325a222c2022757365724944223a20226437333334633638373530316561663830626465636437303833306638623635406365727469766f782e636f6d222c202273616c74223a20223461373933323736666565646435626130386439383137663834613735306161227d", "TOKEN": "0421af944b806e4e61a4f8d214f533e0788a29fd5bb06a56ae47177efa57b1a9020b2cf14df998bbbf18a4654383ab6415588ac1391a882408248bcdbb30d87b57", "U": "041018dea602bc55ccd7f2853d57d2785c9c089058500dfeec0725ae8ff0de83d11a45cbdc1d8020b0b878b57738b325fb9bbf7cf0bd3540ee4d3afe71cfe96277", "SERVER_OUTPUT": 0, "V": "040f92d76735bfd3bde7b894d0f2013225c4da1ae74196eaeab3419e263fab60330c9aabc92fab947c2d28b0496e530cacabfcbb01042d223d6d1eca06827f5e3b", "Y": "063c83ffaec3a5ae316854ded47df7c9a133583ba13bef4b2f533a2329585df0", "X": "15059291a21c03d2c51c00b278d5cf063b7b597b42f136417988ea760c1b5274", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:42Z\", \"userID\": \"d7334c687501eaf80bdecd70830f8b65@certivox.com\", \"salt\": \"4a793276feedd5ba08d9817f84a750aa\"}", "test_no": 97, "UT": "04129062df4710a83dc15b7d540f933a9332a7e6ce1eee134e0c653a42c9d1a380124a2e9a79d49e9acd8501269092ea2cfdcf26e51bad9badaa2146f7134aec4c", "MS2": "2011450dcb071d423590352231290ace98c4505706d44eca28bf697de74f6dd9", "MS1": "10afa2fe5051e1a11a613f4ae4b2358856c2f62b1422f11cda342b995ee52e6a", "CLIENT_SECRET": "040dfcfcfe8ad5fbe0e72b007ee608be9b23aad5ecebe252c1fc03f1cc1052fe0c015bc7f8b3a13c096fc63defc306cb0d044176bd94a1aa8a1f99be1c46085fcc"}, {"SS1": "0ef024ac36116414e2a72bdfc7aad26096bef9b6fd470be52a7b9d4167876cf01a724730dfb773425a342f69b0e45ec5266bbfbcf706a45d71a624869420f8480a8d438b04dd2688ad414d462fa765592b5247f051622383934b48fa5712a3e819fb1dc9c79cbd10f0cd21a2359d8d754b1abb2727fd2438893c7293afaf07df", "SS2": "00a8decf6198327e22a17819068d5e4427b09bf61c4e0cf4ec843d62acd50b9e0245047e5d8ebd25078476893bbfef0dc02ad4237467ba9325093479f18dffb81fd7a1d20c019df2b065e9a9b6a36b049b1405aa829926ae5272066521e54ed2008f953fe5a05fd0179bcdbd9967a77120d3e0d8bca4a702f01c8d218f798c4f", "DATE": 16574, "PIN2": 451, "PIN1": 451, "SERVER_SECRET": "0c40160a2b6617316c6230c0eeda0b3e1fa3296e865344e5b656bdf9ce7899e80e9cada544c99c67dc02f05eaf72350de64e357fcb0a5945ebffd5cf1ea4e6cc17b8ad8347cac7ddae0c2ed2613e5fa800b72251541bd47c6b84a83a1a5dc68e1179dad2361195873b47944cf1b53b259d95dffd1ea6a0ca9e9cf83182df605d", "SEC": "040ab8112c6758a6e87782adda13ca686a540cfb3c2a1e514cb8039c146d33739a0e6631f0d49cf578b9f78eff20d0e9395b00ae182d9d9ce3d38ace2496bf14c5", "TP2": "04210130df40ca766d67e7ab0eac69cc13b44f52c61f8996fb2970b3df9d49dc7e132ce62a5ba3c82eda99601eca4fea2314e67287bd4e911fec604edd033d6f5b", "TP1": "040ea646ca771f6c66a1c80d8e937971bae73c3cc73f660fbee59ad013cd9a103f118c1fb7e83ad8c2cd022cc1f6f2a5d839debe22ab3f7b41538da61116f212d8", "CS1": "041f2eece85cc5c2f55a84a475ca6e0379b0502a37d936cdbc56e8ff95a44caddd21d50982a43a706ae6e25c973d5062765eb6de3fac3af71b9bbac76cc8b53725", "CS2": "040d232e9cb689b19f8781866175020e699f571301dd5f796a018d26ebad5aa8941dae23eb56855f0a3bdeb34c3fea0e25be9dc47b87ddf02bc3486461b5aa0abe", "HASH_MPIN_ID_HEX": "3c74f601323f4d7c04d53e9c09c5c4a3aedb182470f88febe4fac51f1bee2dce", "TIME_PERMIT": "04228c8a8760a082d22e15e628c705bdbdc7033a590781f7d8fd9a62f036e2ff1d04c6dd825cb0bfac8b22ab9f733c5de160b56f42dddfbad519e964550c9db579", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34335a222c2022757365724944223a20226464623531396435386664643837613339363438333132313462656239306333406365727469766f782e636f6d222c202273616c74223a20223464316264333631363365393362353066316133323761306436383638353538227d", "TOKEN": "0413be681b96ed3aa6e36e1484d6a9346ff8f6db41c3ee3504c6f2b77c2f6e0010175ef6607a0441b6841e7b402117493d2f069db024b143c386d9c4e8960b1840", "U": "040c6b22a892b830051f144463104b23391b31256333ba692e16443a9e6b5cb48115ea02264e5f361ecc083259c49ba9d9a5a4d5d95cd1f121ce7c5547f725c049", "SERVER_OUTPUT": 0, "V": "0415057641bfec07cf7c79adbfef9c029d545d7a5b6be2b8ac7761e7d6d82af08501913a485de4329d91e80fa221defe91fc7157e160d052dcb76ef49c4a1169d0", "Y": "2062616df893a16ec5b91374e6bc20608e8f2c8e6dea4801aa59db1cad60b53e", "X": "04874c6ee8d356c65c9981d743d3aa92d06b049f755373e62dd937295539486f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:43Z\", \"userID\": \"ddb519d58fdd87a3964831214beb90c3@certivox.com\", \"salt\": \"4d1bd36163e93b50f1a327a0d6868558\"}", "test_no": 98, "UT": "04070e609bde8b432bf4c65694525ec836e7d009959d7e0f8758d5eaf035b925721aefb691f974eafb4d8eb3a6dd254ce2d090ff78822f5349d2dc4eb5fa349f29", "MS2": "1507e181184e973a40e579d6dc4ad337292f5c5b771f45a52f52fc936b4ea234", "MS1": "1bc9be49250969efb85a7fd48063f8b7d28a25c7f890c27840e3647887ec823b", "CLIENT_SECRET": "041e3af68baefa15e423b760d37cab0c2d84a7b5c3805442da6f31e8b5f482982c213b64b7552a3041ef914684d2e6336ac4bd6fc526afaf7bf00306c95b261e4c"}, {"SS1": "117979048a7f7b75f501cdf1a1aa98cf193314504bcfe2f9be9f8211877f9b1715561f0312fc90a18d5a1aa5719fb2ceb8c3b0114ece63426647802df7f530920932e25598d0f385a328e9936ddfd029416cee427065a126bec711c64224d0bb027069c6df0b246bd87f389a69311fc4db51c66843c1aa5d953f9e79e66caaf1", "SS2": "1253c87100d1a70b2c575154aff93ffd1e74e4aaf5270680170635eb2e57035309bc1006046b605b4601aceb3cfc18ac5d3e8941580bb2117e67f27f81a410ef03ba40088e93813fbec31e32e61fbb1f7eb72adab3fbc13dd11e026c4669f76f0b9c0b15afffed5d9850b344c1b2f03e92e4daf650be8a4e7a89895302ca6946", "DATE": 16574, "PIN2": 4471, "PIN1": 4471, "SERVER_SECRET": "117f63b05f8aa7626d3e396ccb46ef1deb179a13fd21cbf2f9d079a595c9dbdd0848a4ee0b198a47d8b1ef6f564b55420c140dd3eb00d81f65a0440e48f9b03016df5877c273cef3001e25deb234fabe63a13d32bda39a38205c618087f62db00fdd97fa31e373932c506ee3c10b9feed68aacd811af163c3330a82b872e1f44", "SEC": "0416281ece500ccf21daa16e42bb3b3355b30399e20d10d14250dbcdd85d04d1e80240deea7649a16da17414abede131491320bfd30f3e96537ebdf82f58997054", "TP2": "0410cf6b55739ad948aece6eb2591b10bc69a0e1b6631cad2ae4d036011bbcf9c2114754182858dfd964da39c46f9e9cda9a9a6834295e7f7dba66274d10654848", "TP1": "042186c8f49eba6547e171adf2f88cef4bcb1646f341f9e9d24cd943dfbf5f464505a3ee29020decb1d8348a6996fc6497954e6bd873117b49890a101790affd8f", "CS1": "0420e7a508d5759334af039beac00776c5802f14800fe260a1cd60e60f4c6f2caa0ff2603935431b999769da59f239e8ff49b8a653747a5ad7be9a2de6cb820fca", "CS2": "04210124c36850b0abde5b4a56f623948116af13c0d5dc0a50b15d3c49cbfb7a2b1d6cfd34a519edb62510c363f1c35e8261aca1d62d117eaa223fb7ec593c8b1a", "HASH_MPIN_ID_HEX": "cf32aeeef560bf9644254504d5e0fbb30036ef1e60fe39ced9746ba441bd2af2", "TIME_PERMIT": "040d429f69f43c7c6f6f67a6f2addce441a52c4960917dea666e34d1556074f4b30bf3368d8b7f990792055be91d98c3fd0c88ca64e8a015ee69ed742d909f8ea2", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34335a222c2022757365724944223a20223866663238393461343465626162323334346163623961303962303962323637406365727469766f782e636f6d222c202273616c74223a20223038656161616461656533356331353866313031623662316530346333306430227d", "TOKEN": "040c8285c2b91edb19b5f89f7c0e923aa59e2ab8d428dc08ad610c5ec361c4f1d5225a4f1c79f2e149dc65d8bc4423333b28e16066173e742e37bba1300c805e35", "U": "040e17b55650d9b2c2cb4a6e2b470287410940397156eb82c704f49c6576d63d9804738628364446696493e8e5074519779d8381957b5da4197b3ffd57f9416eef", "SERVER_OUTPUT": 0, "V": "041e59b02fffbf052cd0a2706d253af2daef39f7035913df02bd29715344ef2c3205ef14fbd726282b923bdbb08f466024ce30ea51c506e6309317f5e946eba26a", "Y": "15b2566680423303c458619762f73c04f174c484ff0cbbf3ec3a56c9829d39b5", "X": "1182be8a617bc1ffbf4f4199a0db39392ac3cb41111b4ae3cfd61f255b182d04", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:43Z\", \"userID\": \"8ff2894a44ebab2344acb9a09b09b267@certivox.com\", \"salt\": \"08eaaadaee35c158f101b6b1e04c30d0\"}", "test_no": 99, "UT": "04107d7dcc2d1c46ce7dfb714f2f8a04a1413c8159833e86c4772da2661d25d9eb11278b6bebac8ca6b2b4e98cbe7e5214cc3f05e0acaeaa356e5f5389c8525fd4", "MS2": "0bbbde2ab6f2bebe8739378fc893dc454e05e50bc57c11b248a3e02e6d3041a3", "MS1": "075f2932c5228ceb35210fd3415e2c062c9da203bde9569875b7d1796ce5e9a0", "CLIENT_SECRET": "0418b94b0e38dbb004e010ae1cc9b4ee9a722bc89ba6e983b5f76c0bd1dc3152a60a0f5c7eb641c2bb0d89af99001438de23d1f5b12e5fa9273ee3f6fcace899b4"}, {"SS1": "09d643a0bef4f43b01fd19cf97a6377b02b9ceef54cd3f01032edf65bcfa6ce2222fb1df7e4f6daba28bf796e4c34bb137bec2eedbf4bc8636272de17aaff568177939fe8a24bc1927303a95c04e1db6db3156516635a04deb7be0533513ecfb2387c083dd2fdc27c621f142f95ba7ef9ba24a087fc7d20026581d0a04c26b05", "SS2": "130437c0788185f59d25f6d82a5a13a63baf9ade12f9e2ab15b3ad67272960af17f79535d3c6eaa73ccdb41f024a75df44d13f8c43caf8ea0c86dd05c1b7657a08f3b1a2211d8097fb6e18218c123b27f758e3312453426853e3f72d234e80750b85de39bfa1353ac5266803ad341d0733231de0fd2dcce2787fada092de68d0", "DATE": 16574, "PIN2": 3975, "PIN1": 3976, "SERVER_SECRET": "16da3e60d4a9815ff7151659a6fb74772145c8d5039f363f21830d9ea34251ab154424c0c2de08073bbc2d7837bb502da21ca56e67fd5356c8182f5663975ea21362cea335228d286973076ed8078a5ad58b2aa51c823b59fafc9ba94a9b37501c468f6e3584dc8bd4386c4a3089009fc12584810ef412891600330818f5c490", "SEC": "040b943626b07cd3713894002282ffe567115a93e9c3d746cab8605dbc9f105113034b3407d5d559ecb1e6ad03fdbe18e1f4ef5d8d29c3caf218b0f3054e91494a", "TP2": "041c1006d7a7978db6f65f37faac2fa6cd6031456ad512168c1ca289324a7c8d251ccab1cfc62dfd6a5ccd6a3459513b8ffb1c93a0b6a607a2072355eedd044abc", "TP1": "04085a59f199c87abeae8cf1accc946e62cfb26a3f544bf1f663ec524094c4b7f70373a84c683895ca8abe3e4bcf51b9e085d169bf2fbf4f3d0054c4b530d08aa3", "CS1": "0422b473e2762c99eb4f53999d3ae7a5b6bdfc8154e32d88b77633505f26378bce191baca57ca1a8eb86028342ae3693bb9b384f4e364a51946e08f5c170cd32a9", "CS2": "04189be78e9534cefd89466d2795308569c35b809deea4a060a3d893e27120ba6c044d2357b4734c56d49468a5971b408d77e5c9239c960308a476651d3872df80", "HASH_MPIN_ID_HEX": "a59c4d255a362630e8ffdab5af2a830156e3d21dd43e9d53e3dbd9548d6c3181", "TIME_PERMIT": "040a1c9dd29d30c563af59613dc2064c1df3102b1517a17945db1e8bcdffd0e44f0bb601c5d16dad959bbd0f1f0e6d69281c4213783785363c9403d673e957bc5a", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34335a222c2022757365724944223a20223366386632633937656365303235363133306364316431316530613833383534406365727469766f782e636f6d222c202273616c74223a202236653738346361336238356563353833227d", "TOKEN": "0412ce0573a9ce924c920014cd27544b82276c805d2775045836c5351fe73e3dcd1b14a29ca1b97cabbbc122701630e6a06ed5d4f09bc3523d020a483ba4f49ac0", "U": "04030348ba0d7a28058c505b714053c1d32040c41cbc140750169448ecddc2ca0203ecddf3142d89d19ab0a3b3baeebe3605fe2c383605bba27d33a22b6da04844", "SERVER_OUTPUT": -19, "V": "04030214369f0216b3fa0743cef44ba7b1935dae13d4c952a24f079d36355ababb0b6d57b68983e36dd1ff8784c4c5ff4418737b19bbd2f2fe9be4d2989d0cfcc3", "Y": "04765cbabc5da009f9cbe45e1ce7f0c33bb1899a71cec70dac6c39a1ecf4c0ad", "X": "1ee6eeecbe3f670979d75722e06610d8fb6778ff3fd7ce9fde6377a437b0d939", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:43Z\", \"userID\": \"3f8f2c97ece0256130cd1d11e0a83854@certivox.com\", \"salt\": \"6e784ca3b85ec583\"}", "test_no": 100, "UT": "041202d7a13487afa9ab18a29dc5abd204b6f5bb8bbfc2d550eae3f8ba431096a01db7bc3a551994a172b7d8b78176a2bd8637d15ae57439878072714c400a8ff1", "MS2": "1db90f475befdd1bf0be340581415f700b79495a1156e95dee0e301eb09209e0", "MS1": "149534f42c7ec3e6d0a81f6ca2641ab82135d345dc28afe8292875b1c6739541", "CLIENT_SECRET": "0410f2c16e2d18ae0dc4f1f021f623de28b382e5ef3afb71d40b26a5cc717afe1a0d55da689fd4e50a4baf49ac82cd48e3f7f2782786e005ad29d7e6abd384dc44"}, {"SS1": "09520aaeb316a3189b93351fdc4b3046a9ab8730382af5799c839d0d7f0d9cd6049ed8db776411b24c9de280c0305c8e557ade3678dd0aac176e585261f4541e139fd34022674b2080cc2ddaeea94ee00d143b268e4dd00c7d74086c9a18bdf3206e785eb169052b5304a305fee5ea2ac5304c1d4f9f8f44bbe91b09b6473232", "SS2": "0466c2d5f88e0248d9ad132eb707ecc42d583d6d3ece870eba00250c3d3289620d86506642f2d0c208b3ab5491e3b4020379309ab5a53edd2327e93a44d8790f22791af5f63320239884d056b2b282f19fb639a58323986237a147e67f72a7912111a144a2385ff308b4f2102313ce071437598f2671b5d206619ef6d8ca777d", "DATE": 16574, "PIN2": 1395, "PIN1": 1396, "SERVER_SECRET": "18db2db8e5c6bdec70a1170167dad0bfc82f69309778a38aec1f3e050a15732a148b2862753493cf3716913a907cb8716a86083c6824f24e97ea58f1776424500222a94f2ec2b69c4fdfea5115667a4ff6cb820e5a3a37efcdd3f8293abdc561115dc81f815c32b181ee65035395432032f369c23ae76d164902459509bbcba9", "SEC": "04095387ea3c36e4e5f034bc068fedcf9e35023b5783330f1baa35131d34ce6aaf0f094cf6c8d18b3e275ae70d57006765df6d9b3abf578a9a3b9375bf8dfa6ef1", "TP2": "041029b8fc97f7c421f4c61bfb6dadae9d504101109947789c5b5951c9c993152a21ef129c9a121ae88665110ba73531ef0ef429a5c875ed254c5ac5b4394946f9", "TP1": "040964a9f33abed4680305428e88fd3c9d5f15403af9024e015601bcc1cd338aa21814a92d2a02c013309f647a5377c3019e0505226184304bd4d1397ef1b54064", "CS1": "0405d73a477825c1918166be2a82d1e7f327c4bd761ff73851947f5b8618a2059810f4cdd51b7c6df81a1acbbfc93efb5cf935081b5318539e3b6acf5d723b8c79", "CS2": "041258810c7ed76583d0e644c7a2e93790deba0ac0a6ced033beda6a9015af65af22a78229f96bd2ef45efbe64293e7f8f3541499772dd5d52faaf7e3e902b9425", "HASH_MPIN_ID_HEX": "2ca0302753c70da4feb8bb5b25787cbdf76f6b006a4beff6f8fba7bc6366dbda", "TIME_PERMIT": "0419ac7bac137f437783bab22d32b16987f672c287aab1ccc6a021267b39213822170f87ebb2e689ac7f3b5dc9be4a74cecf9e8b8a4cf549ba549fcaf4a8893a18", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34335a222c2022757365724944223a20226161363338383563373836643037653764376335373036653732653966613732406365727469766f782e636f6d222c202273616c74223a202236633333663536646264643837343961227d", "TOKEN": "04163c8692cf316aa63ef519c1c5d7099de4835af391b9d97f0bdc98ff9e8219d3044bb18a47cacd809e2decd80604da75e7c039ba0ff2f0b7bf96a16a25c009ee", "U": "041869602ef92ce91b70cddf81573a6e7bdee832efb024cc90858d0afc742bac21027fe71b283891842f36f285e0314bafe54722fff77f96af32e91d6a8891f0d1", "SERVER_OUTPUT": -19, "V": "04218ecd817b4561a7099a01adfa97a030e6d146d62f5f1c9fde38eb01beef46771c6274b1aafd1dd08fb67410ecdbf84fd3263259fd5b2014237dc670f05d65ee", "Y": "07b7890084dfdcf8be34c15e845d1ecd76e0c409932d262a7033fac45fe01caa", "X": "1e5d34d070f64d88383ca50727db0946653ce2a7c9c6d520120a08ed3c0f1184", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:43Z\", \"userID\": \"aa63885c786d07e7d7c5706e72e9fa72@certivox.com\", \"salt\": \"6c33f56dbdd8749a\"}", "test_no": 101, "UT": "041ecb6755d7375e750f9347f7e319a061014b3e964382d42cbea4a4a8af25df560dab56d080757e075734dc1f09518a1033c84e279c0b8639570c00da95d5be38", "MS2": "0bb0d85702ec39dd191a97e45ff0be87fd0b06ca5558a64da1fcc91845c8d2ca", "MS1": "1687b7cd7d87020703368518dfbe6e4c4fff9d3d3e6a26ce0745085a3d5e230f", "CLIENT_SECRET": "0401ad57bb50fe6e824d9ff8fa752d495df0804fe3164e7ea80a869cd5e504ad321ab55546c7d1d5d203546b8629914cfe7e00bced23311b7b25a88256cffd2192"}, {"SS1": "05e8afd51b9afafd205411d325ddefcfd98f084f09abb8ab0bd91982753b42b70f642329012ebc15e0926bca2afdc65105cae7fd69a89686e89ed75fc18da86909e89d49e58db1c4a57d6f69db28f3aac233915f5e528a68ab65ea4fd53f69af0d7e64d1c579f8d341b8602b45ded94de9d2bc407946916cc8fb4d00594621ed", "SS2": "2266a45832b219809178e3859ec68673b4dc50b32b2f96e89fbf969198d46e4c19ea7b0a73d47390236f14a6812e4f633dbd0ddb3991c767e1ef0de425bb08ab200df1677d9f6996269171f99b23f2ae70ef9d649858a69efab6466ca8be54741103b74c0c66ec71b42c92a05d90849b7d9903ebf301438e6a6233f52730f888", "DATE": 16574, "PIN2": 4293, "PIN1": 4294, "SERVER_SECRET": "219b859ec0c6068937894290bbbeba5b37589f9db0fc4a5ebedc81ba4fa732b70c70e4f08f7423b2056a2c30b6d5b77368c37c16d39194af6e0cb4f18eb1d12d1ea3ca7237d7098ed1e1f3d207809f450f2814458822652cb796d4287e2c62c101e18f90368125f9a53a7fdcd082983426c0f631e84f423dfbb23ce865001910", "SEC": "0422f9e523606e0083e44fc41c7ebff8b927a88f7dcb7c5215ba2185db8ca250d20622b53ace122b95216cb2d95737db2e1c5d6110e7bbc7207baa06e715ceb6d8", "TP2": "0418b582cdedc87d924a6a6e2041010babe4424c21c4cb2e1f393d5b96ebb395a91187e35b01a7a30514453a14cafb1533c3612bd1f382d0a2579591292f884f99", "TP1": "04233ac1d3584b4575133778de9d703a971edc1c550e6e8e64cd7c907f0fb57eb50e466f38c61437c9c5837e6a3b2eca9e600b36638ead48c38b13f840bc66c5d4", "CS1": "0406936ecdd6cd1f8bf3a5356ca9f8fae35cb8d7c46c94111db920f579256b0b06063a9b1438c6e22cc2a5844f400980839a28f96ebf396c853a73b3935ab7f813", "CS2": "041f00c8337d2dc0db20d480951463f1b6b11c21c7543119a0c0562983c33f1c46219f243260272912d7abe13fc38ff3135719a41c6408adeba6d9392ee03c644d", "HASH_MPIN_ID_HEX": "8bdaeb64d0b0a471578b99ae15ea93b617d5ef6eaa559b4fcf5a1cae05668e84", "TIME_PERMIT": "040b6db798b46f4a7b9f47b4cef292e3211247dc98c10c1aa7cfbb3ee72caee9a70fd17e7bdb9ccc3fd62218de73c59696fac3026db482d6411b885b2490cfb0db", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34335a222c2022757365724944223a20223833376564336366666164643234656131303933643033656637323666613063406365727469766f782e636f6d222c202273616c74223a202235623730663138303531633063663365227d", "TOKEN": "0404dc0fb2b08e02a549fe3e0715fe81397f6e7283f8f6fb9d947a824909ddf9690a3cd156ebfe0f4c19535be83d1b794fb4f3c57660878c03f237e63f21d44d3c", "U": "040e46b41bcbd4ee54fa26d6fb110fd0129f759bac297c0a9abac84170dcc7e94814c6a0d7c23fc78df6e4d3fbae4c7edb44dd3f011c14fa15fa1efdc8e82399bb", "SERVER_OUTPUT": -19, "V": "041ac9663e7850606f1904ba405e97cbe57d66c34e087ee764e392c34e9c3078c41c44ed7f9c1765cc6b78e9623e86890988cf847286fe0aacccce1aa4aa20270b", "Y": "1f5327a5bbf5f7312c4042504c4e05e21ffe1fa175d8eb0f51b31d9d6b59df00", "X": "1446a09cc89373e872afe81308b8f8317dd4ad9c7a96c8650f2a6f320bd85095", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:43Z\", \"userID\": \"837ed3cffadd24ea1093d03ef726fa0c@certivox.com\", \"salt\": \"5b70f18051c0cf3e\"}", "test_no": 102, "UT": "0411748533389bb9493a957c72aca25548f03765e46836d8084b2444a688d0bbbc2165337d0ce19ae5dbd5e2c5451d9d150c605f2149af2b79106a8ee7691ee9d1", "MS2": "0456625bc422c4c4933d185187365f368d1ffbb31b2c2381aeef9d982ae52665", "MS1": "16420f3a31a369916bbbe777b339ef83be81e5be19c4c51bb7cb56fb6ed3372c", "CLIENT_SECRET": "0409f65c9082687ee533da41fe2ff2ccf6e1d9b41787f50d0b1b8358b4c85af6771faed021bc847fb2eac9c30866e4304e8cae0575ebf5b811d1016ec7ee2aa30e"}, {"SS1": "123c932285624983c8c794828d4068bf4e0070d8728d38c4fe5059688c8874b70b81cfe080a83704477840b2dc0dda977d78d0348791898499defadd3f479aa61b6e1a84b064acbf2b9ecbdfdbe8215ccfe3cc0db772c8194636cda3c030cfe910096295edcb542addacf4636a22e8f927e57c605e454b4c764d028676a052e7", "SS2": "110ed8bffa90b0313b417f6cfb7325fdea576fa1042f99573ba1eb82cd95c9451302a8b444cb04044aadb5d620bcf62c1c555407670e6a0f3164c95198bf080d1193c6b85e3d53695e5fc94c208201c8f8fbd292d26b7693fff514b60ef31482223220879635ec88df53827028f63dcf71a0ef1ae781455c404008bce6df7e64", "DATE": 16574, "PIN2": 2408, "PIN1": 2409, "SERVER_SECRET": "083f581190b852d19955bd6bce0ea2ea69edf84e285fa12f053f54572c1c85330aa53d43c7f679f9322090a61950c0fa5567030550d4999727346acb4290531008c8a3797162f615fadf29951d5d7c33fb65062820daaa2824c4fe6bec38880d23cd81e1af929a2245f3e7ad093f9dc4ea7ee1d849efcd0aad614013de33339d", "SEC": "0402c2de4a99b302ddc45c9a6d2293cabd7e2ec5449a241b621d46c37d249ab9ff12e12519233b6895178911025b75c409ab722b19a99006ee5afe4760fac3f0f3", "TP2": "04000837cf49abf738480bb23ac78e4475fca4e3f95ce133ac2f877c94e2d3431607ab42ee57c8e975ba116bb2c26f60f031f342e1acdc111dd29605f7b55a40e5", "TP1": "04114cf6d213576464e1ba56e68bfda4810fa81fc4a3c53f4a41979a056aeb30d71f5a7cf24e1c05908efcbdfc1fe0f32be6efafe6be0861b7953054aa8f98a8af", "CS1": "041574c50ac297264a0d605a0e3129d8fcdf3150b1d8521315154b8e7ee56cde4d1eb3b31ccfc2e0e5214ac1b2784ab662b0c48396c3697b88d9c3173b89e4016c", "CS2": "0416f0f4c03c37c804c586ddf36c668dc7ac2434f9a5b56ff4a07a224b635252c809d19b58445c627240517ae1b22ea1816c6dfcf880940a82d23c72ec8d7f1a38", "HASH_MPIN_ID_HEX": "d02b361cf8ef872eb7a44351156b2569797d2f97b2a115cd8508ad6526fbb20e", "TIME_PERMIT": "0419ef96f3848b263ce44d3e5cdb8940c98806aeec41e4e8c58ed7df9872555927239644ef8e6678f4abf4add2054a6c525b7382e45420715cdfa67a61c6f64d2e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34335a222c2022757365724944223a20226433393864363464666135643361343133393061336662343738366538663935406365727469766f782e636f6d222c202273616c74223a202266613636306335643933323330343335227d", "TOKEN": "04201e341fd52ea53c95c7f2a7d6208571bf750aa1244a3ab40d61e325f45782a911d82a6d4a09d3dbfecd38427bec93608a69fa316f7edbe01bc2079dd2ce9134", "U": "040f3f76971a4e72da98e11b82560594d78faa8663598d68a7735653913ec7b1e815f8d7dd819717e86e1bf65cf2ceb630852a9c93aead6530ccd6c10bb4d9cc59", "SERVER_OUTPUT": -19, "V": "040f7dbe5ac47ce6a7958215eda2417b1becac26e7f646d34936a4b0b65ac6f8f203dd2652a61fba8d99be0ca758d96a3efe9cde66c97a760546e360e382889721", "Y": "0d0b943a796cece77f5fcbb3cdf29bd957b1cfbdaf4b1505fadcb91e789d0e68", "X": "137ef999c8e0879798432bebb9a1a04c2b8b6f826b98d3e63f6612be7f755331", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:43Z\", \"userID\": \"d398d64dfa5d3a41390a3fb4786e8f95@certivox.com\", \"salt\": \"fa660c5d93230435\"}", "test_no": 103, "UT": "040364375e9cd63213ef55a21ea7c38cdd1a813cef241fb47258ff4c2f79eda0ab0a282458adf728f7bc3e960260ea3435210b33f68d003fd26adfdd3defe65a3b", "MS2": "0de967177386be9297a4483e2bf688a4179229e48c8d2df4f49c96003eff7375", "MS1": "232cee7516f87222b8aab59de61eec339af20e4e44333baa1637f76a2bd6eeb3", "CLIENT_SECRET": "041e16ee1cc27f9c9875292b31520f9a7c20d68775b461c51bac9e20d1ad3405bb111c47607e00e4e4a33b39d7e7f7be3d6bedca967eb87fba38a914f8d52ed152"}, {"SS1": "118265878016442ddb346ce15e7028d8badfe0f7b28fcd753e44c330a0ce189621a04a911e9a8a22193c0748569bb47ce34d3aacef597bcda547cad492e5e1fd1d0d716c808a2b5fe37daba7acfccf5dece03238b9a09d7f6bed5bf2374321d0106c313b26563f9ec3aa1df5deb2173b45850ce77c1e0c5ccf2c3b117931f5e7", "SS2": "1d75c4f9a5f3e37a18fa8da73cf03cb0e776730e2e442551bcc7c58316ea1f5d08b7218bf188531c6d88a85db4a39a696a2ba1d510273b174c0f698d353928e8023f8b46b50c7f14b5fad20897e05a5cf564cc5a2ccdbb1eefa9b1933b02a2ee2209015fd5f64d64e9a997cd3e833d5b630ce68500f4e02e49e585c31952ce45", "DATE": 16574, "PIN2": 7907, "PIN1": 7908, "SERVER_SECRET": "066b4b03346328933b63a446b7a686e0a2ec53f779f6e8b4f1d1a7f717e21964084feb3671f414281c262dd1486a968c4cae0418fec4ed6a8e5eca561b2d0b6b1ef8bba819d144ad9e330d9ee872c89c827690e54d63849e78004fe108628bb80e1ea934b0ac25d374ce02ac31c5d89b1537b8f7ba371842f2d77aaf5514e00b", "SEC": "0411ce735782d9251dec7179b2c4e6dd617480422998d2cdd54cd5dd81d1d9ec0514b03862c07cc37b497f22d78160e01c644e162a5da97e927ee16b028d5ad939", "TP2": "040047b258aa171ab9d2b45113025f9bd90d6e58c9088b5cb8c19ae3733c1d6b741906f6db6a5571c0a5b184de9226a802ecfcb40475723f1411f4bf2d13e6babd", "TP1": "0423883dd6f2632ad0cb7773e2b3e122def96066626f87ae0f3a6c6e5e485854181c0b4af39ebeb240e4f0574f6d19a67fb5a82a02a47728f0b45c101ec0bef344", "CS1": "04034732532725f59ea6930f55d37dc6f9eeb97d96374973e979730af444d6e3a60735a74de4a3cbf2bb0eb0ebe2d78bfc2fd0e0bef37ef09448d0a613ed43fd94", "CS2": "0408fd7da382118b4406386b44bfb02978c53046b0952ab25cc0705bf0c1777b8b0db1510cc715ba1d2c8b24faa972568752e161159d4bce077f5c58f21656116d", "HASH_MPIN_ID_HEX": "d5d04f73cf77ef630fab6cf7b467189e8388374749dc8889cbbb764bf9adb52e", "TIME_PERMIT": "040b0c80a37f27e6b86e20d96e8a75fe7da42224c7d5d0e666df0941d962f6a4ea0868512df0b5dc5c08423b955ba960e05580262beb30fc2155f79a22fa4d9e04", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34335a222c2022757365724944223a20223032616465353236393631356133363131353334343538333234623365353339406365727469766f782e636f6d222c202273616c74223a202233373361613038346539653436623963227d", "TOKEN": "040a59cbd18e0215f28d2852a835f0e7686b8a2b53eba5c5b8596117fc18fb74030e0c66caf635a53e6cc84dd8f30b934232a1ead0a12255ace4c26c2611e15f09", "U": "04052d60a82da08dfd46e015487fb2500f31011b2f9bdabfa61930f9b67057c8651137d058741add7e3dce3afe848648b8e49fee95ff5065a836d5631171c363cf", "SERVER_OUTPUT": -19, "V": "0417dd02e69e3f154a2eed88550dd00e5659f89bf36d366db6a28365bc919d982115be759a5de32969c80f73fe0110baaaff0282389a394c8acbab205afac18ef8", "Y": "00b04b7cc30e69766435598405b34630fd57d9ce01ac5bb6f6ac7beab503a12a", "X": "0ea2a575d1d0a75985cf5d85350f5bbedf07b5086216acee48c29d4c02f66fa7", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:43Z\", \"userID\": \"02ade5269615a3611534458324b3e539@certivox.com\", \"salt\": \"373aa084e9e46b9c\"}", "test_no": 104, "UT": "0401f1756426c89ffa772c0bdd8e5e016ee39ea1bc89b19978a27facb0ad525d2e23f3c18c089918e14aab1e1f94037136f793b43bcd7fbcfa58626882aa22c849", "MS2": "198cf3c7751d199dfc2875485eaac7aedd25d771e55aaebf0a6321b8b977b2c1", "MS1": "0be8473700160ea28330aee1aed15abaa7e358b576fc7634f55e66189851ffa9", "CLIENT_SECRET": "041de1d21aea31964572976641f3cef0964e16804219b628b38720d12d10774258076a6f102140663413d4ac888b9008e6c08a70c35b9806a987d0d7b343eddece"}, {"SS1": "03a0ed68f4dd3726c25b0e9a1b254488d69d8acc377903f60c5884f249eb96071ac0da89e0f0a48fe1af607f4540e67ca64de3bba351169894774456dff9eb230bf9d32dec02bd422b202525ed2464234a5eef40758108399a50a749485541700b3a1dcc85447a17dd5166f212d87e9ff7dd8044fa15233a79563417176152af", "SS2": "13766f03d3dc109972bec68089eac82d150fb024cba43ef7982f3d8fda2c6fe11a69e4aafb3a2bc5c31718bfe3ebee22745a366676433fc343b411f4edd0e0dd0e3dd58c4e5a653dff0c179e90706ad873a9195f6872aee42d04658c231e791411e731092771182d8383a03e885e8dd2b5db502884efc3fcf9ffa78da67ccdf7", "DATE": 16574, "PIN2": 1895, "PIN1": 1896, "SERVER_SECRET": "1ac419792232ad18e437e65d618006b7a82c26a5058c42a6f0ab9e55211fab820599849a56d1433fa7884d639c46438865ea245ae7e93901752d8f367a006feb09f90d0fc2a361171b89974e91e7142e479e78fd84805bce1572a258ea2c663101ec484419905b1a711e552dae5a6f7ef6e27ce04ee5a49860ed94cd666c86fa", "SEC": "0417054ac072d6e5b026b28ac845dd62614c81f4467d7b1412dbdc260cf9ad702c1f4881be7928545d48a67895dff75e070dd6b8b3da378203aeea9ab83a1f6169", "TP2": "040b0f7712017b902f192b71d44cb46d51a519a8c0423019941104118664ad7d9a1c7c12283601480a2d2653c7d93341897234496f142c1060e64fd58d73a51846", "TP1": "0418021a9f5c1db7d742df24927d7a378bbdbcf9fe4b3079d97897fd36d3da1377158719c1c16ab47fa86d324c9f0c5a26ad7bc342fdc77ad4279ed4f9be4b35a1", "CS1": "041ad53a445b48f0c8a1c7ac97450431a73e7225866ec92091078d5f78dafb44042144b66cdb0f3c04b68871c2d1dfc4ba19ad7771bebc76dcccb3c762d5dc0a9f", "CS2": "0422477619f7add302d6f4ae3f7d91ddf0d7b7f785101a8f06021dce32c729a97f1dcba34354063d5c7e2cb65b19333261899c6f33a6ba2ff4b70ca1487a7ee8ba", "HASH_MPIN_ID_HEX": "1daaccbcc6209bf1861c3bbb0c5901f834ba4c5531f0d070de18918c5ecaa951", "TIME_PERMIT": "0401994cc372159b44d265ac763d238670b2ce406737668bcb184d0fd6bbea9e7a00d1bb603d4a395acc0a66bbf618e2150615332d2dd811d653289205235197c1", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34335a222c2022757365724944223a20223832376361336435333562643730613963636262306237616138343564643261406365727469766f782e636f6d222c202273616c74223a202236366339613531633634376134613635227d", "TOKEN": "0400aba9ae96fdb8baed51fac556762c7a25583a26fb6f07b5d95f51322e928ed00d8d8dd10c6dcc71d57952a5faf5ecc02904a25283ece3c910be9251ea2951ed", "U": "0407d740bae70207c86610178bbd006ce6fc72f4087f2310882bc5021df5872db21ff3227cb923b34408b065f7426a4d468008330f7f737f1f01f4cfa8c7953841", "SERVER_OUTPUT": -19, "V": "041515d0b1dc3c6c6a7601f8689896f282143a4fe1114d6338703df79d5033f53606a5aa3bb06b3fdf645f84b612b77c5d6fb07915432eb79c67ecff5a3955ab0e", "Y": "1873df3d6593a9e38da5a3c0c8ee43694586ad03a87906471b00a6f93d3d6d68", "X": "1f9c06871b00cc3d68219f08fae2444ea727286276a0dedc984917aae467d89d", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:43Z\", \"userID\": \"827ca3d535bd70a9ccbb0b7aa845dd2a@certivox.com\", \"salt\": \"66c9a51c647a4a65\"}", "test_no": 105, "UT": "041110d7bbde9fcc0f618ec9375b2e4fbeb30059027393a140d1c030f9a96e87c80486ab51afd372a086a59fb4ed7d32056a1de4eba8a6f7e78f80bcd14612345c", "MS2": "1fbd2bc08497100e61f81a6dd2207c991598cdf0de34e92cbeebba81a230542a", "MS1": "0578a58f0b0054a33acd271dc1506ea0a1ba8f22d38c03759e69d7dacd12ce98", "CLIENT_SECRET": "0420bad0485185402961a0907bdf01d63d5813b924e211b01a1f8c58045846a64b00c55e96cac27f830b26683b919c6cffe30fcd45330993d9ed0e66f6f5987888"}, {"SS1": "1fe25bed4dbf0252f7ba15133f4a19ce13ac29a47a28f152250f72b48e618c6e23c4bf92f819d9a086aa54b5b780c2f00e2a5b21de790f54ac2817aa6817ca891122c39a6bfd4133733060c2c22f2bace87ed2a9ec22eb1fa7d21c86ee4f44c01433fc339fc9dc61156dad9c51d340e225fd5ec6aa638c9d27b3d7a4f7a88629", "SS2": "18d8cf14042042e828d1764507dbcb65a382686e97369a3b9750bdffc0b4719f1cacf064ad5128d0e0177ce01f4b15e1139cba79305e08b10338e955eacdb7a503c3197a4d521e8f250e64a4663fba15091b6b64c152f85556709bd084d37f2d1b1d6e2994a78a08cc090788a4df4da2803b270de1981472ed83f42b02b223be", "DATE": 16574, "PIN2": 3899, "PIN1": 3900, "SERVER_SECRET": "1fcadbdc1572adf43e2e89a3478b3a55f77fb9802655465f09a1aa9ac94e17fb07abb43206aace71fa63d6f17ca773b1750ce42bf7260fe1e031ab35597b65491e34c5b8a72ad93f2276c53e44a790c6a97a5a00ed47efbfa7d779f9e0b7bc7f06cdba939f42ed51b9a41a87c8fa613b1a2e5279739ea03bd2e0893e53d9f15f", "SEC": "0423e4e79f61467e69c3ca7e87650b4eb15fd88d2d523f344c2f3579b2013be76e0d19d65315a2d1d2e45fcdf6ac3be12fa4b17f83f3c2b83f69fab48befc9e7e1", "TP2": "0413d6d848f11a72f41e759589fb3461a854b1a483f397eb4df807098225101ee123785f222df0ff925bf1946c6db4e0069a6a15748cd712a61741f419834c31e8", "TP1": "040e56f2a87c03425735664d1ed2cb0cbc2fdf0e6424769c7d9f904477c57f12201432de7f6d101c99352233d42472c069cd16398536e1118508523ae39743e2b2", "CS1": "0418fcd5d4f0c14c0a923d3200747849d4ce1e43ce88d4f6dcced1f4969b4054fe1c23a35bb506e392fe351be030a678ed2a777764d9d906887bc3ea9513c5e907", "CS2": "041ee89ba0618b9a1e1440856b03dd3ebc78732a1ae0a2e9ecbe766fa10db2b1901442486dddd9dfe27a6549b52b82eb2cc3440bb01fcaa820e6457ce8c4fe00b4", "HASH_MPIN_ID_HEX": "5654ae6593efad8d6122b1167780cd1c424b16777bd1c13bec6d65c97269a391", "TIME_PERMIT": "040520c57a74493414a9b7dfba533965623f15767ab6f5238898fde79c74227bd0133eae2b2e84419bb60df9eb86fffcb950c773fc0cfc05f0daf3c82cc860cfcd", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34335a222c2022757365724944223a20226562303164363664386364373363626663393835643333353633313764386136406365727469766f782e636f6d222c202273616c74223a202265373763633831633333356332383837227d", "TOKEN": "04223be6a39516deea4b6228e4bf73dab86f69278e7e9727e6bbfa8ac824467f4104a7298399b4c42b686f83433188d2e3bbb40ab24ceb594ef0bc442197266971", "U": "040908c026bc274b2737494d7f80387e64712dbeb16cd1669aebdd593bc7a1db7a18edd331ad779e803a17bf861b0cbe07868790188bf30486e4f0387bae1afff5", "SERVER_OUTPUT": -19, "V": "041d5f4938ace5a1f72a4c2ad0db7f7e4b7221ddddb860ad32215d3a6c80b5590c10a44d44e89bad25ca9b140b8d5b263c6e4cb91937014cb8d48b377227a764ae", "Y": "2193640131ff74d608055711242af420721d0c767871cc8be9b1439dbaaf90ac", "X": "02ec41c90ad8573303b06cf1a862d101e8d8d7c35552ebd779b5d8178ac33a47", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:43Z\", \"userID\": \"eb01d66d8cd73cbfc985d3356317d8a6@certivox.com\", \"salt\": \"e77cc81c335c2887\"}", "test_no": 106, "UT": "0419aca7b32614c1d64c05022e6b4043bf64fa46b64ca4519201ef7cc29618fa83192c2d7d5c473eaa93416706978c705c62b5e6ae2ab7691041208a8359d99c2d", "MS2": "03e1081cf37aaabb2b5abde86ca5bded1276efc7a3a9837089c642397be1d5f2", "MS1": "1d1399e291e6eea99b21553cbb0c3c4a5d00bbe11824cab429bda73f3b3ca6d9", "CLIENT_SECRET": "041a602c816cc2976c27e5dcb9316f932cfd3738b5c33046410a56f8fac8b7cf2f0cc71c31765d4a34734bad7fc18505d991f9845988dead97ced5ce814fc24879"}, {"SS1": "0f7a534d79678796f7ee4bb9acac406d7d1379cb7da78e2a927bea68e17526b4133957d48202299980b09a84ca2c3384b64078ed9fc0abe9c0e6b5cafabb4d950039fbf825e3089ddb52979fee155846befa5053903b76002f7f2af5d859d2a9202d653412b49b2c335442bc9f6c294eb2ba325d97753f5948c2801530392ad4", "SS2": "2130f702e727ae3216e60284fa71b3fa4f47cf77cdec89c635d20ead3ac955170bce9f8488aac25e1f01c91c1cd9d471cf0170e3d8911ee2d9adf69390fcdd3e1f63fce09e82136284298c5ddc5b0c631eac6ffa2887c2418604beb0512284de07ae57682695f0779dd2c1347dc4c9e29010e2a713cc63bf6864bcf86b2e76b5", "DATE": 16574, "PIN2": 2381, "PIN1": 2382, "SERVER_SECRET": "025febfc166733103f2e008bef4064a5659a838a616dfe203c99b2e2e7f603d6075bb539546a71c825f945b4899771241942b395e7bb65dea11a2953bd2905030be7cff589e1c12374616cf2f260b7e6763cd05f4aab7c480138a9186634d9650b359bf9aed34af0b378a2dcae7884bcb10463d8cb515900c59eca589f3595f0", "SEC": "0423553c58e6d3047328490d5b7ff8bddfa4153acff2e08c43e12a261d8859c6c70376fc775088db2b7977e05a9e8b185ed19f09f6907e14b925c72a5ae71ff41f", "TP2": "0409efb767aefb3f7955d841c3e02c3ec76b20a53c96c669f48ac8414b30da3b9801fa72d22c46d8b2b78c85cc053511dafa309eeb72a40f86c3322d62e13e1cec", "TP1": "0415f3cbaa43242525bfa9c2a91630103751021d26245cf6b150a724c96ec86e671ddebace92213f16a92604706d8d317710d8272a921c809076efd66cea833306", "CS1": "0413455f33d7b78ce0cfb3399e37efad6498fa708a250459385d719f506aa4a6dd1ab5a90aabf463973c4011f1156a81a24a18113fde7d347c1b17658fc2a35bd6", "CS2": "0416af833271eb2207002040adb3a165375d64884e212d3f402d043873e246c532068bff7c597d99fdbf260e2b28a8f2ac9f2b9f5f16572f8d35a3049153fc351e", "HASH_MPIN_ID_HEX": "5a0c65711fef44c13c1a15043f20742e26c7032eaf8e5bd3da8d99c5a7784ffa", "TIME_PERMIT": "041d80b972d0b8f483c81e27fba98631ab4d8e6bac18a6c9a16b65df4213d256e3059f6bcbba21bd3fe98cb6639a2b4e4265da9eb5cfe40db59dc6fcc2f8886d2c", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34335a222c2022757365724944223a20223735666363633930373265306664643433393966666435643230353261636236406365727469766f782e636f6d222c202273616c74223a202230663235393337316534626339343033227d", "TOKEN": "041c07c7af7a7b283ba6974c332a8a1766ef2a54c7191f688a3998f46791043e4708334266fd521ef09db10789aaf3a8e4834ce6656e06dde0d721078695ff29f2", "U": "040d5728c11b6b7de5111deefbb92c76fbdde13a8b12f9c200ef235b97e24d4eb20c96f14ce150622b4db87b403b9d257ef27b9a56ba2b7dea04146997a405f008", "SERVER_OUTPUT": -19, "V": "041017c51d230e10fd0bb23f052b37b5398e52054ec920f34694781440ecd4b2da0cbda3a8c6b7a266a35c58efa4ceb8b18b0e30360cd470fcb0505851d5e69000", "Y": "09d11d2221a0ddf534cccf63659167cc8bfcde534c9a3e0698d698fd98c3285a", "X": "1599da9d95b206a263b16230d99eca02f399b4e1fb79b01a719fbf6e321bea0f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:43Z\", \"userID\": \"75fccc9072e0fdd4399ffd5d2052acb6@certivox.com\", \"salt\": \"0f259371e4bc9403\"}", "test_no": 107, "UT": "040d59b13619e3d841768bf78c540089948ce2f00baeb01ea1b3f9814c27ccd4e61166e68398f08706184286ca268e67f90961e7b92e74aa5cbca28604dce926c1", "MS2": "1a762e4be078bc16ca76efe064a099b73de6a07367b887c1c321a82d5da4648a", "MS1": "14bddafbde8df8bbafcbd11ee388f1caba37022330cecc3cbc46fea5940c6bf6", "CLIENT_SECRET": "040a5a5b7cd96e56bfebed4fa4d2b2aa6356f04f5db7850a8ae589d63a4b6474540bd5b37d44eabe18c70409c2ea238d7d13eb6de87a0b76a00b38431dd750f436"}, {"SS1": "16985d0c19cf06eca6a8c1129f88554df9b04c8bdd3fc9bd94a0f91a76bd330921c05b10f83a213bbecbba5dbc412daaa11dad4d8db4525cf4c23686eaa1919e03832301010aeb3fcfafff87c27052b10724c82ffbcd5f8f1b9cfced67e27b010c33760f9fcadc06c8821d00571f153df7bedf8cb1174426ee7eb8e2e6da8b9d", "SS2": "0dcb257134bb481a23ff421936f211796e236fc65bf81f809ab9786c94aa52b80688e7edc63038f02ff332a9f708961bfdd1d4d350486a0d2b7865ca1c39e29d11323bb7693daf503b153c8fc0531699df0f83480078580f41f1103bc99709310623262766978d8daf73079b2e19df951d087c07f76ad7456a9a8d9e082fb941", "DATE": 16574, "PIN2": 3763, "PIN1": 3764, "SERVER_SECRET": "1db97c0049e07f03fd316bbdd8f4509cccc1726ef213d0ff8a206ea555c3d4ff22d81795721149164cb0aac669c3bc22c0a6ad88714bb30e1ef1af11a9cc5ff40a0c0ae9d6de5c29bbdb2ea229448ca9f44e7d89b3f5df716f386d1808651f71086736c3be48fc8696d960423e14de72e5fefcf669f95f50fbe9db02124518e0", "SEC": "04106e8562135feaca286c1981e3a3303ce2dc677a1012c24783c3741d99ca7b8e0fed7d39d64f0256be3c721ee40b8a1cdecf690525273c5d037d1f83c6d939d8", "TP2": "0423b61a097119d9ca95c2062be9f6736460cb3828b44125f2f8b5f86f3d9a7dd70023054de62479935874de336075f2f72790f051f24a60bfc0bdecf86a9549fd", "TP1": "040ab395b476d77ac711f2ff7bfbbd1e5af5de6f741e74f7adaa129544d30ed1b21a12a9cd7af36cb08b43b2169f739aee6cdfa6d96a343e69d9512c029900b2bd", "CS1": "0404679f5b388795b9c95268e97f62ec8eff637dab79eb97810d28e75cabb8817019b277149a42d8eda2730ad0c669b4fdf6a6fff8df268f998fc7ceb206b65788", "CS2": "0417957faea6ea669e0df26bb704e7b2788b65abfc49ff7e42493fc7da25d5f9481158075f87e0900569f710cc2987c5d5356bc5732251d388d9ed2fb5baf2e2c4", "HASH_MPIN_ID_HEX": "ce6f7c3e1fd098f05d6705414fca74483bd7ff511fe6f7a62853c363e4d0b435", "TIME_PERMIT": "040f90797b4519094b3c653a905fd44a1f34b952b91f853eeddee0950f64d8e62a1618d895e0b8701ec32448c142572078ef76682759f22b43750298ba532ff92a", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34335a222c2022757365724944223a20226666333530366262306262656634333433383934366439386331343534636439406365727469766f782e636f6d222c202273616c74223a202264353264353433343963666636643235227d", "TOKEN": "04208e93c366ed21baf67d99ed401568c12a4c423271b971fd40b18ed414de8ebb1d6cb55ae4fa72f539bdbdc7e6f06b311b1ee44236fa47c444e93c0b1ca8399d", "U": "0417350f434860818d1e8351654d4cc93645b14da64c4a599e4fbe026cbbe737d51fb4c95ed9a0fa0227ca355616e7dd39b6d5d0d4f09ab8c06b5bdc2c0f7a4996", "SERVER_OUTPUT": -19, "V": "040f27eef8c8e3e20226226c23c66a9265593c6b7e8acc20b6d2290c1acdd5691514f7857b8f17e07588198cb3fcc636c64d6a73be559ef1b9cbb3d541597da3dc", "Y": "11926e5a671740e6676d8b99a9f0fc36ff2d4c791ad11aeb263a45eaace08e9b", "X": "0ca30838b80b1609a17cbb4ba752a57538cfbce357a4e35e65e2978d7bfddb01", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:43Z\", \"userID\": \"ff3506bb0bbef43438946d98c1454cd9@certivox.com\", \"salt\": \"d52d54349cff6d25\"}", "test_no": 108, "UT": "040033455e9a99c74e9e2d8dfc8906469c83b660434b114e89642710cca4f92dff086e49a2e9b20b73b041e446bf71ea1b2c47754686a3386d0bcbe55836ed4819", "MS2": "0e71c192db72d6795e648632177538119522abc0a0c1a0a9aaee79f18ffea398", "MS1": "10acae93ac55c4858f8f1fe157ad8dae147e0de9adcd600b8615c57b6e093983", "CLIENT_SECRET": "04107c2954753ab822eeb008529608f0fc3351920ab68c20e155ad0392efc81e3c1cf9cf33e676effc2cc0b9edb657459a41e11f1bf61000f8296298a44466daaf"}, {"SS1": "04ef133d09c97c08ec2e4992a4abd0eef995dcb7831224115a79d9e2e7bef9bd15e0751faf0fc56a8be8432bf600858e9db7c607247fe5ae30e6552fe03b53321ef34bf7d1d23592db7aff1de8dcc6f3979ce3008f8408a0c125bcdf0c8b3e032391f218ab7ce4d19ced932e7ed0d37bd2834fd0f4a36b7e56ebc0a4b66a0026", "SS2": "024630d1003af45e97f73b6214a387112934c86b505ecd2139b996038ec20f3821b84c83179fa4252a7e0b865d4897dc7be4e69adde50d7972f4714db4d284920474ab278c89a4bd7a76d8e93ee065d15be7bd59c76bf9d686ef5008d2a8e0780b2b9e7ac3901a55de3a85b371c13fe08e0684d4e76d935be79162ca610b3739", "DATE": 16574, "PIN2": 1965, "PIN1": 1966, "SERVER_SECRET": "095acc9267b3ed15b03763679c23bb246d62aa4c56e1d4799fc5bb80e5c02b17013c1a0e81184060551da944cd23da4fbec7814eab0a010b7023ef7e53c9c9540bf56bf132875e791d27ed8b3c2502138d23974113a9653d555a28c7c0fc238b1119af116bfc5d5fe43ced7f7cfdf0507ccaf2d1846f5bf3fc6fd29461592606", "SEC": "0408ceee69b7763553e8283588751e9b6f99efdca0ddef145bf89e67c5b7c1ad40200081ebb0a3e0cd82bf1c18e8af38de714e5c5ea94c3a4cd70f5811ba05ba78", "TP2": "040e93d1709de0b115ea3a00aeec61ee9448fcbc00ad6a24b4fee5f0782fc63a9f03c80d1786b48a00bed720630a989baa23b8a4f0d388414cef44c01887e597c4", "TP1": "041d8072ee07b17ed6828e48632cc4310d06a167c1b4fe852090f64868994d30f602fe557d6164ba4e077334192233c16562aed3d274e54a18c5b9e2d4e56c2945", "CS1": "0411df3792239b69d1896b7b62897ce1116cbe1390f7c0320471595acc1f326ecc190bd8fdb597f3e3e8a61afc0ecd106a743ce99a603d5f54774d8555408a9dae", "CS2": "041729f94107222c4a49b53411c35db345b8a00b74344d73a4765c0f391a968ca70da35db513944bdf4f3918c3fe76f2cc422dc99933a1655b249a96a8968c39bf", "HASH_MPIN_ID_HEX": "b699f9d34d52e1edc989a617b1804f3ab319d5d3ef187619c3bcb91b55eb8e88", "TIME_PERMIT": "04159d8a550bb1130f9efd49b716df16adca660c6059b1703f85b1853d7680499b1df87b3d1f3b417f108bbcdaabb46251f0bb4eddcd938a11b6da0a655ea40bba", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34335a222c2022757365724944223a20223365363864633331353662303530336533656538616663396636323131653135406365727469766f782e636f6d222c202273616c74223a202236623566363834393738353362636361227d", "TOKEN": "04079625609428cd9f594c5ef9a657444ae2b76360a6e310799822348e10d573b50d9729b5365bc87b881c64264c70a6145fab73ba26e299f132c252acc3995f6c", "U": "041052d3835f06f06e5fb1eb781857f7cdc01041013869afa0501d031bd01cd38602811403acc03017a2d4a7bff820b95684c365e5af10e924fc0f87e7d9e73c0f", "SERVER_OUTPUT": -19, "V": "040bb916b093daaf1cb128162ec4749a57397297abdac40131caadc042abb57eb31a16e91450c1881b4ad1615c2de296696cdec400e842ea69d2d710d83aec5fb3", "Y": "0f5d00066194f2206a0eea3a13526273848136b686820a4ded28cc1c40d6b079", "X": "0b26933a5569bacd42b0fad9288caea07910e4266779a037b01f880f15aa2b23", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:43Z\", \"userID\": \"3e68dc3156b0503e3ee8afc9f6211e15@certivox.com\", \"salt\": \"6b5f68497853bcca\"}", "test_no": 109, "UT": "04214c90a02921f46cbe4053d081bcb0e18bd05b920e2651a84e15b90cd8c1ddaf160c618e24a57a905d7059418a2a88dc54898c2991c8baab74bec183729441fa", "MS2": "0619e9a7db82ba4d347c8cb2b960fce206866fff869d84a01b9858df3e83905d", "MS1": "15caa342f8d26ce9b0e79d6fad862c77db6eaa085a5fdfd6a528a288bb7baeeb", "CLIENT_SECRET": "041282a10d67c065d8e19af512bf90f449119523ab7146c74b417ca973054cdd270207360479674a48ada3e694a63d8ac9526071f2b50378aa403c4471e30a5c47"}, {"SS1": "1903eb58d72cb4fb61f71c9fd72daab797b19adad941f7c9b6f9e758b6d272c1085d194d96913c30d57dc77f67886a145661f2313ee6a05d4c3c3dd3f686025508fc9efdcd47847874d474fd8b9b0cd359eba93bf2c45f75873905436e2c16bf1ddfef28d28da382f2494cb2723b62020321cf88f187e35e61001dc5184b5b63", "SS2": "08292524e92f0128d4cc9330a6ef61c8e990bb6e149c19b10cfcbfc5ce37d4161158fe58de44fcf78ca584f483d7fe0c5d69f6f52ecbf7934a516eddb72398350cd6e10cfe158f9320747dc4d8961775e5d6c0e5cf1f28160a99c55598a9d10e0b8549b42d35509aa75413512cce6e5ffeb9d11e8b3ec0f2e7009fe565cfed9f", "DATE": 16574, "PIN2": 2262, "PIN1": 2263, "SERVER_SECRET": "1c6e4a04accb58de726d8b4883182cd61d0e36ca0e6bda93299df229be44f1331c3797a9922edfe4d150623c83801045785415aa612e0623157d280caf54655a1433569b8087a743ed1adbf023847c2265bcdf01cc793cdb7758217e882125bc0c191cde99c4e7fc0ff58c7f2ccf5c505e0f4979ca88c3c59cb5edf1c3e20939", "SEC": "0400c9a2af348df0b111644f81a705a4e9c90216b0aab599ae59170385e3995cc8194a578f162c99f4a57df5bac8bcc8d5c4596a289632d1cd958f4d63a738a2ca", "TP2": "04154ab5baea5855c1e647e94f36dc2f3a34f13507af34cb99acc89edab8e187440df6fda2eee71d2506f2df85a155fc2f3fd67fd71fd3a584a4b6fd76ec43875b", "TP1": "04222ab6a15fd3bcbe4693196e699e9fc458a22206986e1df499ab4063eb1a5dd71801ea78482d24354fa048dc8b320b93fd87be88d4555e38a4ee8e4f2446760a", "CS1": "040d2df2f66ad071728b6e76ffe5be7af0a431edc0e764235733c37bce41cf6bc421a0ef6b3688e5cfff35f0a3bb8c604081934f898c04ebd28144013b03e97ce6", "CS2": "04118927356b6af70c53c79bfcd0fb8dc83b8d26b59a37a9f312ebc964c4233dde1e0d6f3c98309c34bf6240eb5647ba5b6e15c11645a426aee0ac1275ee725db0", "HASH_MPIN_ID_HEX": "4f5a571d6af7d3e6cc390e1cbd944cfc03a2bfbe06869450709cc4e856e971b8", "TIME_PERMIT": "0408f391fa281a7eb6ea50621873183fd5ba870e4f9af929be2038957f394cccd004215c94971ff37eb89ee82ab43d90335509b1ce66bdfd9db337bed5607257ce", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34345a222c2022757365724944223a20223338333432306437643830613064346631313565626665373137396435333763406365727469766f782e636f6d222c202273616c74223a202239363065653631356639656133373535227d", "TOKEN": "041a0bc8de55372c51515ebfda994992ef850ab215d2e347103c5645a846c1811c13574674259921761e6646edcc5bb5e36183dd9c308dbda90a7c2ade02aa68bc", "U": "041404a4459dcf4883f9ba4a250b47008f9917d0a74a8eea49a5f5e26c9e07077604d119bb48cf5af319767ab5e4f958ee1ffbe6b6773ca381b17152ea344f82ef", "SERVER_OUTPUT": -19, "V": "040666ee148aaeac387d3c08536eedfaeef93c70d6397a734487a7389c05a3cb5501bad7188a9e541e2964477c19b0fd8f6b6c466e6a8d857030e2df889aad2840", "Y": "23d7d4be3fa8b49ba623f69d2a243c04d480faaaec6de1640a14c4b4cc167c80", "X": "0556e7df71edd9862f89c478ca6c0089f28f27eb25fde61045e6d1cb77d6ca04", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:44Z\", \"userID\": \"383420d7d80a0d4f115ebfe7179d537c@certivox.com\", \"salt\": \"960ee615f9ea3755\"}", "test_no": 110, "UT": "041bbaf5fc77c9aef5f86ee2f05d9773957a44e4da9bb2d88eba30f161b64035b81c237f9ae47752679906a52dd32085a53db81d4ac94691036a5b5837cf59fc86", "MS2": "040d65661f069c3e51727a5f25ef12e99c4df2051788842f1d752fac0399525c", "MS1": "22591e1ce28c74eac3583fe3cabfd564bab58f9d425a876aae70d5303b43fa71", "CLIENT_SECRET": "04150827142aae998c60c4b063ef3d06d27dc5bb283d311a748be885e7256666cc01ab06c30aa38f404a7beb8909bfe92e5d50a6707d6f22d4db8f01ef7a14c8a6"}, {"SS1": "14a0e6e158dee0d7099a5955d3c909aa42a222bc6b3b999d32401bbb2ae6d5ff17a0d1913e3e2f1aa64b40850e13f858935e0947d066abf0deabf2076b07991f1efc285f42aaa9150795282abfb3c071ab59a56ba63249b3e2790317039bc6430032eeadf5f06fa68a8427dc1b7b8a8f3883514d62ded71f3e2ee9fd6a7d7c25", "SS2": "0c3574777196bcb786f6722703743e2941ae892dd11ed285901db3a22db0c15516111af6bd03f2455da31c5db8aa9652116808297185c9fbd549ca075ec883150b9cd388c510ccd3278e9b31f28422aa5d9529f0b249a923be41b33e265d250f0b3fd846596ca90be80d8794b5d0e50d10dc8a9970904af44e5109376a5f63d8", "DATE": 16574, "PIN2": 3289, "PIN1": 3290, "SERVER_SECRET": "1ebe7f1e3e0058036ff6705a07b588473bb9584724e42d4820c6bbfea5d146501a52be7789efd34236f7fdedd9fdc131f6c979ab56448768041ea8b057220deb1b25d84982697be9dd055f9f9bafd1a8fbdb7429b70f278e9cfa9a4c397bf43a1cbd56971ecbdcb98279680d82e91fa309c75a0ded254a36716b20e50fb1acb1", "SEC": "041d13f8e7c4517eed2679703ef2f2bbfc418ad7bd00fd0808f56aeeaaa3376fd308f46cedeacec5ebe6b89b2acb7518af9af296250efa43db6e8bfbee98881b04", "TP2": "041a46404b2f1c7b762b172827ccea902d58037ba5e5bbaef0414f8a6ea7dfe9af0417b50e8a42cb234efac16a6b2494bbdfa5a24eb5f216473d44d9b1630c948c", "TP1": "04235b5b238d672ffd59abde4110ea1919904cca34478a0d3ef4c6fee4eca6c8512072b59c9bb7faa88bc5c06dcb9e58cc1ca3213434734856591a9b896991a14d", "CS1": "040c677a2877b5a5b332e0a604d0b422b99b165a3d8b468059d0aee58679e629110c3cbfcda3277f30ca542a7cd6a99862ee9f057d16185d2e32e97b153bb61f69", "CS2": "041711e89b116aa56177e049d8ee1f92bc4f36a959ce5a1c8991073a6f3af899ab01187bc113a18f1a5eb00211293b141dc4d72c9d583f1a036934922e186f4307", "HASH_MPIN_ID_HEX": "371303484f023367ce719d398881c1668f7a6637f2f9f19f095412bf0c6bec6b", "TIME_PERMIT": "04083ad0a29022b9ca783cc30d5906f5eea0dd8ff5bb7d9b965768c2ad70aadafe1741e216e6295ea32c0722cc3b97ccd0a485e9e1f36df14ef1985adaeea29e8f", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34345a222c2022757365724944223a20223761613039396637646137366465393232353865316162633666316363353536406365727469766f782e636f6d222c202273616c74223a202261623336316133346162653833343236227d", "TOKEN": "040d13f47d0c93e20c3bd110791c759205350fdd3a2a91e1da104d5673f4a827740028e80310ead932a040f02799a9b852d544faf75c426523aa8089658cde26f2", "U": "04037a02ed5c7cbd3e677df8b20532a15c51b73d451f34a3e852b6c067e74c2d8213e987d01cec7c6fb74fb5ec32d4c9bc4274362259453fa339543cde96f9c775", "SERVER_OUTPUT": -19, "V": "0410401af3e29347f204cc05ff727943c11541cf2756435c8e1306c5730ef5239a2189cad062fe46e31e4f8e8ebfba7146a180480ec72c8c64d7a0a126705166a8", "Y": "13005f496b1d391e1fce79750f303bc24dd161ad552b29b0b7177ef05b8fc0e7", "X": "0825363a6c6bdf9754a5a1ba2900434e8b7631943a529e587d3a2a28102b263a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:44Z\", \"userID\": \"7aa099f7da76de92258e1abc6f1cc556@certivox.com\", \"salt\": \"ab361a34abe83426\"}", "test_no": 111, "UT": "040b7287a88ad98202f12b1b76aa71abaf90827f2a5c682f4c53ff41c94b11150d0cff80d18106af5e6e669807112c99feb3a768b2ae1d379d0b554e34a72ed433", "MS2": "0d64f441906f137fcb399d36fce4ba10770790903e579743a4beb24bc1a0c4cf", "MS1": "054242cde188621955b4752a6b41977915e294dab090a1309cf37bed70a5ffaf", "CLIENT_SECRET": "0421155702ca40f15e0ca37b00d15fcc028e0e65b1de874f519f6fa9a67dc7084f0e0f76aa9f699ebd53b519f6e3c16c0b2498e2b7dfc714badddf1fe7ed1dd8b1"}, {"SS1": "0e0fbb8bea7d5ff953c46d70e95b71933de3972f9218841033933a1c1c2a1d9309fae4085f22fa843e82bb2ba6354c1e8f7e366cb584f308b05f33091cea82eb07cccfbc14fd5de6d660b70a8d190ef8c9e164f659bc5f27b24c5b3d99be5ccd0c77970425750fa1dccfe14238793e3e24b8ca148d482a99773ac20c68aad6c1", "SS2": "0b5e340a5e34176abb49852e5f6dbc01374515c237e8d8f04531c3095e2140de14adb133a038621fad10a2782092dbb813ed6d03b2e1b3aca62b8fc0b291d3f801b94e6428c60555ffe7724a3ade9bff26fa254a39da4a4197c17beb94f375c601b961cf1d2afb2fdce6d0241e0ec3f1ac2052695fbf109403602ae33b13e8ce", "DATE": 16574, "PIN2": 9054, "PIN1": 9055, "SERVER_SECRET": "18bed93901b13b13efdc1e91c7fe63775d6ecb4a54934344a98152e3c1b8154f0fe28347798b37611e6cb374901ac2f48eba672972f2bdfeb898eab7a254bc9e22a9957c974a05b9a0b66fd0ae36d239d645119ba02e4413da621792fb75e0121cbd5340e25472d508cfaada1ae9597f549d4366d85e4b508065fa98853519c5", "SEC": "04135a8c2600c1f4dd62ccf8aa97fb51cf2716c0c2304a84790faa679aabc9096f14872080d15337b44d7f5546dc34b6f6102d18128ebc87fb3faba58ca967af1e", "TP2": "0420fa53a0137b3e648ee84db9292c40149735f704d30d1a117e5f2fd8882f1f4119c1785850235966728d493df676aa49a90d7838af5e741e3e6cc9654a6f909f", "TP1": "0421c58326f8d04c87e4b2dfaaeef1b9875f342979ab794755d590f7af845585cb049e52cc252317923aff16c21b482b05b6efc184fb22ca9e36f3870d7095f4bb", "CS1": "041af3201f8ca56904c82e03230de961b74a23f91ccfa8773711d8deb277b8cfb409fb4a0a3a103ebc6abdb6ed2c9d3f1e0d1dc34696b2d9a1b835e0df643b3bc6", "CS2": "04065a3d330fc2339ab32118efdd226b4de4522c9208b7023e6b21ec7ac4eb638e18c0ae2b79683aef6ca74977f0eb78977c95b21bf41ba901f47450a333f97a17", "HASH_MPIN_ID_HEX": "80dd7252fdfe4d70e1652dec323e1121b589240f8eea52557f7ac8547663083b", "TIME_PERMIT": "041889483a35d694f2506dbda141356266e45d0ab8cd012128ae17eccd17be3e6b015b4267f3f5c9d28f6abfffca1656a96ec2ccb9d809fe40b91f606d41e9b770", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34345a222c2022757365724944223a20226538663738363534343464353339626564333330646665396335626637343535406365727469766f782e636f6d222c202273616c74223a202262666535646665653864613036633136227d", "TOKEN": "0423dbd8d7bf400e6b9c5ccbd5bec751beac35d9f78983b0801fcff790c5f074da032898ceab35133f52cd94c408d86e1cdc61e69ca458d2b81501c63e3cc6a8c4", "U": "0412ad59f8906822035b7aa4e2769cd8428c45d7ddc61880a64031aaac0eb868a70b9900b0a02a1bba16964c03e60f6be6bc23df307580535a8d8357d36c1d5db8", "SERVER_OUTPUT": -19, "V": "0414dd564c720c93f3ead633cf0e2480a2a5b957c59742aef2b90629506640332b21d11645620070c546cdaf08c457f4508d2c56007f36de6987d764bf483ee14c", "Y": "0becc3d11fff2f74cca7a99119e9f8bb004e029655c24842fb789a326f2768cf", "X": "055b0298df67f66a1bc13bc63f21f0beb9a38c60e00be95ccb5c7fa42ec8fde2", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:44Z\", \"userID\": \"e8f7865444d539bed330dfe9c5bf7455@certivox.com\", \"salt\": \"bfe5dfee8da06c16\"}", "test_no": 112, "UT": "040b484849a13fb4afd7cc3aee3b62342910ae6c16f2da0636edfb3e922483f41b220d3b581f2ba7d2dfbd50531893498c62cafa6a16263e3779558a4ccaf6bf00", "MS2": "0b2dd4dcde345c9886b884ba053edfd63f6e5388b8b91b82a8240d7825947910", "MS1": "1f142847222c8c4dab4f5af09a2766839c620edd242bed8240396aee3e721797", "CLIENT_SECRET": "04233a326ae526dc08c819e891147ebe335ec8c20f0dcc26f0d28e09006f60c4970d327d8b6f5b9b76475ccd92cb36af72209bd202684c29a456843c45e20d4659"}, {"SS1": "09feb76580a618e9f80bbc560cce915e9cb9dba0307e659d12a25a2aeb11e41414780a041754ec9485b0ae34f6425c4f191506f0811a63f3534053704f01f3e919962f8159729059eba8a3fe16ae164b44416b4d2a8b079a79c133c737cec9be0d06b2426171b1391097396c1753df6753c4836e690be9eab7e74266de02a4fc", "SS2": "21c0ee951a2d9fffd833c72272ff0fba032736efa38957d4c51b82dffc81ef1307f25050a349e5b05519251440c9b3a6fee801f02c73e9e2959a2ffc67ae489a07925be255bc173777b34b878e79f0565c4cb50a530d1478967da3e400bbf43b175ce1c028389b6263d6bda76274cce85c2985507ef90fee3bc3bb5f715c0263", "DATE": 16574, "PIN2": 3888, "PIN1": 3889, "SERVER_SECRET": "20f0e763eff231d013252ff0b5bf0c61722afd27ef7d7b61034505b3b8b63f5d20b5ecc5b71868267c16bc2a4760c6c71c70ca9b07c6550c08b6a3b05cc48b5116d44c3dca3883d60c10a3a70225862c6c948df50e1a86b1f03946d2747ce51d1db3ba09befdc99e362f4e398afc1e0924046c48853064a6454e1883f508287e", "SEC": "0423436ac445a628f576ee561faf9692abe1e1bbefee9cd03c77a715e44e2c6a4f0d09033fd2b3a2fc3aece384ce65318f8786c73fb891c18639d81af7239ce242", "TP2": "04131b1132ca78e33b29a5521b5cebc70f1716ca2c8d4c5b0093220677de12f06c1b7ecf2f5dd11b73a5c5890ecf46ca6cd7b5bc4fdbc32b0ebf1b7e613333479f", "TP1": "040109bc2ce8516d5bff320ca8a488bc896dc942cb2fc647dee6e8639ad49f58c30e89bfffb94f2c43571f17ea45c748196151f9c5dd698b1d2893841490fa897e", "CS1": "040d8f2b8cd4e0a146aaca11b0411893fc7e57da2e927b4d61b4226769a434711f0b153b0a5bb5e820c905c6e6df17f63e0046f7c09b3a78ceb4e8b529f68b1b27", "CS2": "04098ea8f7a8468182c263a4ea2a8ef9c56327f2b44490e07a7832afcb80ab87741954fd854006a19501d30237075a86422accac49d0d3a8b9849d3c531683b6f2", "HASH_MPIN_ID_HEX": "947bca635ca618b9b70716218004140491f87a61bf7731c30bad71a3c050e956", "TIME_PERMIT": "041815cb16ade3132281928f5b632c68356d621d65c60b913af5e96f2a2a567a3c15b50749410e71a6fdceb9c00725dd4af654e797a66d630882ca0997e136b48d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34345a222c2022757365724944223a20223232336339346265363432383939633131323061373639313764363430323731406365727469766f782e636f6d222c202273616c74223a202234336363626361656239303066653734227d", "TOKEN": "041b83faa1e3cf65143b28930944d5c5975af2a90b877f756f32c4fe92754a463f1382e6679e46428aadfb3821643402d5dfd413b205c7d762dff6be8f300e095e", "U": "0411717865f3a1a602368732481978403c08097300b55d7027c5f226242400f58a182435e8f94642d62ea25e4b21f166298e178affcb27a40e81d018a7a84f4d5f", "SERVER_OUTPUT": -19, "V": "04239afc5520c7e353ce8156c3961dd321a02df02d3af29b4ca7e822840bc6a1501cea7baac1b6406a8932fd6f42e26c987007186a78ba398a583e403c900dabb9", "Y": "2163b8587ac5d60843d766952a9a1eed559982dcdf260d917cc8bf05bcd4f64b", "X": "1605601dc37dd9dda8cd425788e8881a5ba73860851a7e683e33313ef42e3753", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:44Z\", \"userID\": \"223c94be642899c1120a76917d640271@certivox.com\", \"salt\": \"43ccbcaeb900fe74\"}", "test_no": 113, "UT": "04178976131fb4395e2ea090745da8ac87716286d9ffa6f97d97ffff02f924a5f123e424dfb0d7b1f8d45af0234827faa71ebe860bf9e559b02f9e043b3c31e0d5", "MS2": "1c0d96d843f934c88031359af28472ea0403d1e30ff961cf71151d5c937090df", "MS1": "23b4903d41053636f3bf59f521eeb8081c8bf5e067c0992b6a95dfec38989771", "CLIENT_SECRET": "040b92afb3eeb6026587bf32c7b9cf4fc31b05da4e8999f482c9aeefa89303c8791ddd75d6b015976fffbaa1cf999242c4bf14d244a5a3f7469171eb484708a6ce"}, {"SS1": "01dc340e7b6ab29ce4396a96f790175181be52e3481a5e76d735818deee90c171785b2e442ade721561530fe9261582cfa6e4dfe2722715c2a58a591c22c470d0eaa4aac727a4b62b81ce739cc91d28fc7d62450beb6c4cac67d937244a31f6e0b074679d6e50533414d8941b321d9ecd17ae8ed0230f3165b4913f2b0d402f5", "SS2": "0ecc3fad682c930e5a87a0510e0022ab0c265ec34048d44691b33c4767e3f4c420a8f0ec7784fd503d2b1287f5c95287aa7c281cbb0e2a8711c4b201d6eff7c31cc80d188192527d59e4d75f915fb7f0253446608a9d5acc0af2970fffc57d950251a35083d4dda323afbbe4b46a8305f9abed060540d0fc9d005395c5203d82", "DATE": 16574, "PIN2": 8289, "PIN1": 8290, "SERVER_SECRET": "02bd3610049ac089a23f49d25518711d54ab82cab4d324199dd40b6da6b5c3bd00c6e3bc21f352cd4a7f167f5998389217c64409b8304a57dce5fa3f3922f2791e9120fe17bbefb17638d89ae1f702022d4b27ad33bef7627a10f8aff20e86351e52d2307404e356ca87ea020130ed09617f7891107e4f6ea97a8dd42ca87969", "SEC": "0403f3fe8b0574c430e4ac0e3b4a1bda20e9c2f39f692ab237dc174f6b00cfd76d207964ef52cf8811010e7df3a926d74c38de697138d416f1095223d5e2698d13", "TP2": "04127801d48e1c52de565c50b0162b97e2f2cad9ea16c42f376881b1d609ad4f3803aaffdf6ea2d243884e7a405877f75560c6a6237261eac2748ec6c59c825784", "TP1": "041a79bc0ec2c7d973b52c83d7c9951cb480c64d0ab0c35322129b392a25ef1fc115475bc6c4303bdeca7e298dd05985e27bad8ceb2ca9e2e68cf1184589b09106", "CS1": "0406d870eac410bafabf74c589d5b25d94f1271e783394611742ceec1cb5e5a9b108c56958f7a36abe8bc85dadc02f5370933655cddd70da1c6d7363e372bce71e", "CS2": "0406ec369f2a66a455fe2fabfecb6bcbed0dc329c1f792d1eeda4b5fd53d228c1314da8bfbc4b82b5a74c01e81aa3f3fad728cb7d54ebbc54acc6d874bc10197c4", "HASH_MPIN_ID_HEX": "c65afd07db144423ae3822d2e695d6147c5645df34c1fca6fdf626495fdf3103", "TIME_PERMIT": "041155ec4e914bfd232b25a1a945077148a66d6b36563ff96e6f0b8f61a84577b713e38f1cd845767675dbd4f633ed032879f39a29fd59f54ce1f87ac4dfaadaa4", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34345a222c2022757365724944223a20223937646537306330616332366538653634613262313264363631356164663937406365727469766f782e636f6d222c202273616c74223a202238633065626133333134633031323537227d", "TOKEN": "040fffb31e5cfbccfef443d47bf20c900a14fd353d48f4e6510016179b711a80ae16f44edfd0a44a7bcb88a805ea91d9de2012ab8638fa2b7609173dbbbebfbd39", "U": "041e9879c841f81487519437df7d3ccc93500679785157801d9ee66220bffb93701ea78ab2f370695cdce77573ec8d3f3fb2eeefe655492c0dcae545fc121cd406", "SERVER_OUTPUT": -19, "V": "040d0ba48422b0abd5fda91154278ddee7f7df6e435f2d77d5018a50439cdbaecb0df1d9033dab90c0d74cf1f07977b2636bb0ada200530c89cf75b391390461ba", "Y": "22b73ffc88b0d4d69f792a18de2de9b3e07f10aa1e019e90ee1351dcf5a6e1a7", "X": "1ee5c1711581861b1bd0b3e5a32c696bb5d22151b65056dfe175ccc1705a34f2", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:44Z\", \"userID\": \"97de70c0ac26e8e64a2b12d6615adf97@certivox.com\", \"salt\": \"8c0eba3314c01257\"}", "test_no": 114, "UT": "041860b2d41d5849fcbf5e05af16177c28d06704c25cb2112f2fed2cb20dafdc9c082868e22dc50e603eb1301e0c697250e8966beb42aab3c4438dc9b17d263e67", "MS2": "0de016f22c119e22dc6d51886f3a12dd3626841a7301db5c0df8db401ba66317", "MS1": "1eba940066b3e2ca3650ad315e6ba13d89cbab164547767b9a5b76cbefea0754", "CLIENT_SECRET": "040269f2a402168f7d24b95b4a5dd9598fa897343116a7dabeeed0e9455361f56c0dad50099cb063aa0931ad0b0cffe0cb88b32e373c464cd7a2ffcba42df02fc9"}, {"SS1": "0c42a9670f8abf35a27cd9d8e191a42dca2dd56fffdfcfaff4a2b981e6ed3dbf076b0425750e889bd778e94c6937be9e00362efbb6907d637948cbc8d7f3c75f19dcd6c793ef0a33c61eb1d08274ba5171541c3ef59a10de7478190976b8dc4b0ee70e84744bf5331a10c130a3981a0caa76977a64a6c4b3da21ec95bf335665", "SS2": "0ad4bfa10120f94b1614c01df4ff80e014b57fe2ca0d1b9b8249b688f101362212eae04df7ff85547f35c94ea697a3e9d5c456f27a3e0a9d5ce8c062b3d0d5c41c28f1d614fb3b6483521d299f604ba5c27f5bfde655c41efe0facdddf7066e7066011624ad141cf87c99073d39ea4013eb6d5bb0df992aeadb0819913598641", "DATE": 16574, "PIN2": 4685, "PIN1": 4686, "SERVER_SECRET": "1c6b77f32c1ecefce5cf36e6ad84c08fd537773defa114f5c34a7514c36e1d1e0d2cc97916ec4ba1416619b7e3d82951501fc6f29e73fad51e132ecdcbcbfdfc1406344e1631a2c4c9f9ea9c0fc4be4abdbb569ab9ebe8bd212cc6f22911eed8143e78c10179d669a77055e6cafe5f9cd83b0a89741b0b5dbef55a8b15b26d3a", "SEC": "0407fa79b4b2a548b4b88fedac567b5fdad8837c35a2878056955517252e46b6e90eb331aef52bf4b7eac60b528fa99553c2ded34234165d148aa7051e8975a610", "TP2": "04191e1f5040593131d680c3f68b5e4aef0cc67de1f089968ca8f7c94d81b82bb61e3f599f7fc159295cc3de7cde14bc9a08e1eb33cfdd4bb99479cccbeda387d4", "TP1": "040fa2e6acdd5b823247101b16f5cafb7ce82be9c5cb0468e1e5acccad41365141198a43d0682a835fb0eaafa5caf5145b5bb4690cf3370a64bbb74504027d604d", "CS1": "04019661fb1e4cfdd47832eb7c6654af21127a93cfac67c9052833681dac3ece450fca5d47fa0dcc9c6463ef4ba78b2cbbde505b14a8bc407f855854a94917e61b", "CS2": "041e0dedce73b57e0e3a7c1299a8d14a893a895fbefa3cea8cf833ba1f4c0b67291e0417cdebe8445281e50a4d662f9f8f986c4a9ceb2fc787e6533904f1677258", "HASH_MPIN_ID_HEX": "61444ea41a0b2e2ce81392063e9fd39dffe6b20415f47364a313fca0e2baf4c5", "TIME_PERMIT": "040a689c3cdafc3484811688e57086a9171c33d4ebaae0bf1d3c2e3f4a50095651043ade12b588e7fb55185b973202749bf81a9e38dc366f36a598d60f6b635bf7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34345a222c2022757365724944223a20223566646266313734643635383639323134393639616139393739633736646562406365727469766f782e636f6d222c202273616c74223a202236343364346264636637653661646238227d", "TOKEN": "041b513938d7d09649f9d20ee4e0bbd99b608217b9f409e25825e81eb74b6318fc21c9e31b6b5758b3fdfd06605de8d171fa2a53c8a6b750f428d7a36276b70d3c", "U": "04109cf3a47658b146170164cc06122abb4375df882676c0e3071ae5b13f53e01405ef4be9e00ca22c6705a4189299eb7afa33da7ac54745a227e525c66f6a081a", "SERVER_OUTPUT": -19, "V": "04165b8befcfbebda086c6727fdcba4be5892bd50bbac8c64936fb44b51247d3c017de37b1afbfb4d9e9bd55207486f4aa6b2c4c4b6d0a4fdbcb3e51146d1afb7f", "Y": "0442631ce4156cb260e87330cc06b02b5655c0e5a974ad3ab80a47d0a0d913a1", "X": "162849c6088f5856da0f5abe448021e68932f34f941411e479f3b91ea9b80885", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:44Z\", \"userID\": \"5fdbf174d65869214969aa9979c76deb@certivox.com\", \"salt\": \"643d4bdcf7e6adb8\"}", "test_no": 115, "UT": "040b2052cfda5c01f1d6b23935aecbd977c72fef9eda8ae987bccf3e24e931756a14fe5657671a39a44845d5e9851d937ff9c7a3782f929d2c58b936aa8b9f8a07", "MS2": "01bfa525aa166d6436fcf936c2ccd35837ec4ee815668648ed30ccedef1c2eb1", "MS1": "1de45673ea0e917f189a4ea9038d7a5fb3edab79ff30e0a6b9aa4ac8c14d6e4a", "CLIENT_SECRET": "0411f7ef39e48dfab72300953a5b4bfba8845a2f3814dec76cafedab2fbd4c1ca502fd63bfe07fa3a379118faea4b6c4e186c3d3a79fb82f810502e77a7acc5178"}, {"SS1": "189cc991e005a33aa8e4aecaac061ab74f4f76903284968792115794c4239fde006d785a8db2aa3a4620dbd782adb85c013f9d6a379f368a9cc2aea0c37f7bfc0dbf8ffbd2c123465a0b3d00cb209035b9a2726a59444b8e176bf983e5136f070c7ee2149b4ac819077951fe22ef3e01ade1f49b420e1b19ef6bc76f3fefdd2e", "SS2": "13e71e90e5cd6d6e46e1a3ad2b5a71ea6474969f4e92d4e316843199aff5ddb80e57b68daea025d48f3bd0f9dd3dfd410397a549723e4280a8451eb9c8c166de1e2f8f27e0e1b5d20a453d8f9a6a7f26fc14364a23bcace7eb35c9c26181da8419f969725c4e3d9a41381d03bb8e540528063cc8ead3d1bd6f37914a911798c8", "DATE": 16574, "PIN2": 9628, "PIN1": 9629, "SERVER_SECRET": "125905a1d5490f52451aced7ad478da08b89267ef0f9715b2b3b9b0deda8ee31172d0e55b2d280cb0a5c0acabbed947fbf8edafe14437ccce7b04736c0efbe330bdcc5bce941a90510668569d2c97f3272feac2cce5e04a6ee5d9a2bb47099a909d23ee3a0b846836b175beed9271f0cfade6c0f1c847227e12d0413604264fc", "SEC": "0422f3a0df365ef1737d04d5b44d37aeb597f5e6c15c963aa990f7b95636b2cfa713936fe706d99d7feed59462b2ac35f42936a3515285cc5fe3bd61c9479bc2ed", "TP2": "0417a49e30e168124753e4a0cbcc9696c79a76401024c707fbdb21c1458158ff070bbfa0b2b58a95e5e2109b4d5844bb7b7c757e3032de1bd5f2d70a7cf5c2aea8", "TP1": "0415b0c8de7a2e386103440c86dfc631b21ee60da4b280d7be6356fe029af6c54022efe9170c4dddffa872a8ca314611979a673d985c32f74c3a7c64807f509fc0", "CS1": "0413944c1fa7a6e35362545c8b857aa44c659eabfbf4610b91a89b2310abff89ef0b78ebb15a71e529dfbb4057023e12a6cb7afd3159598fdd3a468f73bd7940da", "CS2": "0411eb92fd8c3d666949e5ce2654aa9402223072fac16d502b748ae518be37b1c1117f8f590c08b9e001c30b84953e92fd4979b885a7f2e2f16e20faa773bbe67d", "HASH_MPIN_ID_HEX": "24281fc3b99732d324a86686bfc052c669f9f83a84d6170bfd88c1126f07fce4", "TIME_PERMIT": "04225b84a707469ab61756b4ddbe90c5c04e64a7c44aee1752c5fee688ea0a10e019014fe4460f91bb90dbde9bd778fc5614e84c7a90aac0e1d6b44291d50bed10", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34345a222c2022757365724944223a20223762663631613934323561653036306363663332383565343864363235346436406365727469766f782e636f6d222c202273616c74223a202234343263623162326639326261326335227d", "TOKEN": "040705197c36ff49e2a509775f9e3f02364d5d1f46f57c0702e8fece5ec2a1a0280e06a1eba6dc0a5e03db35a326e3f241436d7d14e6abae804c141489c7fc8943", "U": "0401d060f1e540656723f8de13166e8e8fd37095f751467610dca953d66448e03b12fbc67c0c11e037d37bed4729eae078d975efa43baaf2ad6b2645f490413245", "SERVER_OUTPUT": -19, "V": "041988f53efac016c50032763da2deeaba3949960e70d4c72b506e6a7f685e28191ec8f3d14eb5a799e8650f7f902a7da0c3851b1f740eddfc1d4a7d706e48f15d", "Y": "01ed08ac88b7dc06fc18f500587407dbb9d0d76fb83a41a83364a3a79923eef7", "X": "06f61ad5eb5adba6c179eceac29df77a36f3a1f71699feec95d32a51e0d6ae81", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:44Z\", \"userID\": \"7bf61a9425ae060ccf3285e48d6254d6@certivox.com\", \"salt\": \"442cb1b2f92ba2c5\"}", "test_no": 116, "UT": "040f2182bee0cdea96427bc49982c39ff55922d076b9f907f113e1f9734b2a6abb0c99208879815288def73d3a82f974f2aed728d3fdd4e84c0aa0f3c0f868a732", "MS2": "1523e70ef34ee7a6c0c023422afcd5bfce945ed1a39a5fa6d440cd2781e89e8b", "MS1": "138701abe984e422eea160078ac22b6192565ec01416e78bcf8d3fcc9557469a", "CLIENT_SECRET": "0411cc5452d5b2d8bb6509c9069e63cf3a16c990362ee3c070d18f10626cab0e961f181e839a9d9472a1d11bebdb397f54641e85e2ad5cd3672f81b1706ed7b1fb"}, {"SS1": "1637527def64cb34a9a87321eca65d31a6e20061529d0cfcb5943f5ebe11306b0979cb66c2d55aad93a51c3c74a07f2f02be49010b18c8ea6f6eb8b214a0c177217a0641ee53c2f5f95552be260ca9b3cd79ed85147ee232e3b6e5fb73a9209f05ce14200c0a064f0066c073986dce297d810e9c20d2537cc6df30c80d0a4f51", "SS2": "1e276329b72748ebc87d548ad5f3b2330ce0dd7fab62193d59a8a126d47a16f9079574e9130c5587f5e125c4a6aebed6acc8e24bfd650e6bb3286885d351d60b0d997c948728b30e8001bbf1bacf4ea5c8ac949f77073c88822f8c0a0c04c2a201244f5dbcaa35c2205799d388f15df97bbdfbe1586c38c8c794d872a571ed04", "DATE": 16574, "PIN2": 2352, "PIN1": 2353, "SERVER_SECRET": "0dcf50e404b58fab77b9c22ba0e05080f58b726bfe84fc82fb7cfb26ab656c291c671ace6df3d2088d1a7458d7e992aee4da9b7a82371329b7636c3d98946d5808c6a9e013496624723255874c072ef29fd220d57a8fef4dee1fbf7d97a3394e050996cb56594e8ab3f402c12c0021f3103130bc50f6da99ca3bc157602e5325", "SEC": "0407f04299dbd0c4879eda8ffa64c8c819c3d7201eb7f3193bd056cbdea5526b7b1cb09403e02fb4e940af19e90ce6d65fa8620945107c83f68a676bb3684b4c29", "TP2": "04164e25c9ee8e06f480a7938cb7f6212096f12ad8415d47c637045a4f43185aaf0c0215b6908ceb333380425c081ee9e775b113717d0bfde3988091de816ce6d8", "TP1": "0418b9d767682b49a27ce85511625bd0bacc19d048a335867c91766dd215cd77171ec8ad578829d792da8f3d380876ad845e6df474438980f22a652c1a913098e9", "CS1": "04130b09f84809dc1df5db341e3fa5875e5bb34ad47c455d9a46e9b60897ef20cf044f1b9df4e4aaedc3a1fe8e82ccef40c39ed00e39a2bdef46ef8043fd6a0449", "CS2": "04193b0dd5b452e541bb084e50d257f58480bbb46e591b814c4af29370b949d34320c0b4e00d8612768dfbdb8a8a1a442241d4c7f57f50a8c957a84f45cb6e002f", "HASH_MPIN_ID_HEX": "0fbe08f2ec3a44230d8658e490c4d01a06b1ba9469154d14d9ec38cbeea7f811", "TIME_PERMIT": "04170a34bc85e311f7d70973513f1ec26e171a921e9a7190120fb0e3a81f1e1def0d21006171b12f08c282beb1250a6c7696ae9f38c3ebbd31d4e26d9aad8438e2", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34345a222c2022757365724944223a20223763366631656538333930343864393633393433393061353930356132666339406365727469766f782e636f6d222c202273616c74223a202238333639366636356164346132386332227d", "TOKEN": "040ed9ca6c39e39570698a6e6fcc34e0a67d8807c31d20644fd71d9286d57f3175049c1b322b03a66702635881cf86f2f2cabc164276799487090222a05de4e1be", "U": "041ee51b9556eec8e7d9e7d859c9391cd0a35a9cae4b5d7adddd42b5705210d7f611c17b599701a453e7485dcd4a95d9388f73f69102c215399cd77110eb0c48d9", "SERVER_OUTPUT": -19, "V": "04199cff2fda38777685e494fd7486e3fc16d6ef8d58d5e6784ebda23344d82983019792cde2901e9bac48bfc215b7a469dafe931402e8fc38d8f888ada01f5ee2", "Y": "0d241b6f2a20c81b6e5d949292d2001b59c2de06343d621eca8904bf800aacd7", "X": "0ccb77aaa5990e2251eddc9113d8d4ada239c4fbeff787864196ff8927afeafb", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:44Z\", \"userID\": \"7c6f1ee839048d96394390a5905a2fc9@certivox.com\", \"salt\": \"83696f65ad4a28c2\"}", "test_no": 117, "UT": "04185587d8cb837f908011da0b3c9ff71dc736816e095f3caa9725c769d151ca1b20fea747b2029c7d444dd01f7048bcfed4ad8e3a3f81fd03c5a94a52ddb0b805", "MS2": "23fde34a6587dfe4a31b65598f9f27570ac3905726aa7b4ebb5b439f3c7419cc", "MS1": "02c6dfafb6b6120b2431869965c2614e7299f9f91eb0bdb149a40c5473e19799", "CLIENT_SECRET": "04102c0ac983b480073392f22be27f243499f7a83bf6486fe42a0f197a7317d9c502db1cc1ef3d4d25b20556feafe33cf51cef44c04ee728d4ff4efa36afccdf76"}, {"SS1": "024a40e9cc53d8d6a9311419596fe341e08daeda6cf971ac623db0dfe254fb68200404fbefe5707c716c3bd4d6bb6a859ed990838cde4da3a4526d4f0d708423215d194599e5e691fe063bfe09c3ef670d343f2b475dcd97be5e3e269a9b42bb05697b6978d76e7df40240b7e94438399608a61191731a8d2111cb53c4011c23", "SS2": "168474caa72d38b12a403c2e7b649000361eb05f226b6a99c1ea60b84dee2f060419dcae8221619352418e74ba3ab93c8af170043c7b1df7e675554800f7426d11c329211aea7f8d590cb84ebb5bb154eeaccc4cb680d3ccca967d3d5f20d16820f3a14f0878242bb1dbb791315e5cc39a45d85539466792205334ca2b000a34", "DATE": 16574, "PIN2": 4960, "PIN1": 4961, "SERVER_SECRET": "02ae77488cf662259ee7a1a2deb737d0d5c23cd022e0c71cbe7c6ca37894f5ad1f32c3796531ac35428b8c5f22c565d5b74946987a0de738a46a369755b7aaa50454cfa39de9fdfbdfdb7a8ee53392e52fa78f81d620e646f92684618a348f6b0bb1668f277abcced20dd300d9babfeaab81393394e1c2b74b83c95f1d614e5c", "SEC": "041b9643160e1c881dbcd79b1f6ebd037d7f469819116207c22cfd7f0498d820e01abaedbfc477e6116f2c37c71ce9815c7bcbc37c7b939fa9e026ef7664a03647", "TP2": "04031b421c4503c2f17c580eb076b785c44e098e0fe0a74a6bc80331f3c8628cff0f7e4d351cba7a5b3abd262969a72cea23315efa0a14958fb0a66053d3ddcb91", "TP1": "040198b3c1f25ae5ef62476cbba300a94ebe93278e843b4b72746fe77a0d98af5d2089e419c5cebecfe738b41660ab7964dc9c9f9cca2de86585c377133c17d927", "CS1": "04159a5ed39228856a716bab3ddb8204ca898d9b2a7ec1d56157aea6ec3c757de91970992e95eab168d81c446bf9a1f15bfa0c45f2434be1ef6e63df31c20295bb", "CS2": "040923bf73c5a7063bb7eefb1e593f63ae4b0d9f2acf771e9e0da31ee1893b248f0a132e1361d3b4a9291098f5c66b317b77ca96fa24e6edbfc7de94de6f4c49ea", "HASH_MPIN_ID_HEX": "01d5cfcf89e9e69b0f961ebaad8d90a487b94104b71ef0b1c88d8560f0b24c28", "TIME_PERMIT": "04079bf681497c2bdc26fa87f741326fcc2c1769d9192cf6c831661b9c2ab6927e08d7cd02abf6a2553fcf062288089a15fde6e819f4b7eb6fbe117656f27d70db", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34345a222c2022757365724944223a20226436303537383864623237343135383137316236383863333335303234656165406365727469766f782e636f6d222c202273616c74223a202239363339616534343830303462353135227d", "TOKEN": "041145b420b7b5e0b166ae3fc40b9b291a300144bf84ba4793cf04cc9c0d715a0203f8c5d14957d9b01219a81906a72bbe466af6ccd53e6b37af6184bc26926965", "U": "040cb530c4eadbe910d1a75f001edcb566ed982d6551c9192f849919711350321605a7ee4b39f5647ec899450c31e5565c8c8216acc18ec58b8274c83edc82b6d2", "SERVER_OUTPUT": -19, "V": "040c96bd352228a4e62551be999141a11ecbc75e0dcb0780468f21b3ed303307570bbee55ab0ba4478017cb9a097f94a8e2d6bdbd423495df485986d96e582f524", "Y": "2282cfc2fa113d6e87f32325dcb827a5a67397c3703832191c3f2a3ee23cd4c6", "X": "1d73a56cbf92416693bd99b51f1d39b3363132b8c3165f4e96a500a0c1271f38", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:44Z\", \"userID\": \"d605788db274158171b688c335024eae@certivox.com\", \"salt\": \"9639ae448004b515\"}", "test_no": 118, "UT": "0419cf8120036dd1c3ecc618804db64323cbc626560dc6e931d3f11196d1fc633301d58819b7bef2dc588bb591baf00509e488ba488c93a9ddd56f337c25d1ebbd", "MS2": "0319dfcb1951fd50d8179dab703156ce1a0e2fd453868ca6ac31790ccb341c03", "MS1": "0140c5d153bc77b7697acaa07b95d5aeac15b8426261a4517197595c4dd6f27a", "CLIENT_SECRET": "0419c98b7471dd362d2d5b38977f13633aa7ed117d48c5df856ab746064c99f57e002018b748d8d41616a1bac624c45f669c26cf6826dfaf000df73a8052a8dbad"}, {"SS1": "04e8643a07a48920cd09a4df966f1d2ba6cb83a7d02a140a2a8fa9e322928c75237c7934614b1089d05be5d0a6c3d73b75f58656dc72265d67da797a9b034c4405e5dc0dbacdc0b9d29e281cf46412a63a9f0fb2e5f1cdd63e1184a6e5dcb7ee1358ae118fa484fd8127aca66640609786694557f2726cd61f9c6ff287841f00", "SS2": "0e7b067f98596e62caed1e44cbe4c8d9bedc016cdccaea1f7f337fa2fc40f5451e0143e61411467b498943971b7decd5a1ab32b1ba9c34f70096401fe909138d000392b4c97448728bcfeba768be7bf7d790cb881a5458e1eb1476ab1c3934330c075a37296ad89c266443a71c95f07fcab3bbcc64711c382bcfbc50e85e7a91", "DATE": 16574, "PIN2": 6431, "PIN1": 6432, "SERVER_SECRET": "0b0d12111c466867ac0fa60f2054022c992c1553feeadcd487c7f31bebff2839149d7c99768f1785d6076a9e3d4ca00dc88b3d4e0a948a3afd2862bf19579ed2009af1ad99d697e6379379b088fa1e3b0f31da82106653bf153edc00766dd18e1815bf0a1a747d572c8d3e6efdbd392e7223ce9f36c17d2a0238c8c710a0e140", "SEC": "041d5946af03a4cbe94e18eaa103b4b650346bddb54110e08dc4166b6bdb6bd1aa2299979f430d7294a10947be987cd27cbfd4c176583debd939ba85fdaf536f96", "TP2": "0414dded2a9d6f22baa7a0ce5cc63ecd36c19fc41f66679b58dc3ca9cfb2d6c26810cb8a8a2121ae2f767f59b4fafefddcba90fcd70d89bce4c621a421f657af53", "TP1": "0400f3b538f3ca240587e019876375fd07a76c20f510485a4d7498b2464b35092302e46ef268f11c1b2a6b285380e2a88b0072355f337440aa00d22ac8979db78c", "CS1": "0415f98dc8cf5a8c4571cc73cc568c418a010732d8d91deb395af1e874ece0bab402e3a6be1dad0393fb65b3894311925931a56581344f6e9084794c434177e66d", "CS2": "041e90bcb7eadc37341f7701f5baa0d2bb4a8431738bcd70aaa6af2c2f8893db7913867a53ea6776a15d1df4342961e80acea6ee6258a09b9a3397e5bc2d133b7c", "HASH_MPIN_ID_HEX": "31bcc32b6ef1dd290702af9a514fd5c41ec88b52f9d657f758867b80aacea700", "TIME_PERMIT": "0420c186d0a5e7e7042537f9ef31116a7dc0976e4cf5fe2da4b36567bb736f5eed0d4a1ee2c37b5db40bf8e8bb211e48d7e8e506a08efccfbf51157eae1afed10e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34345a222c2022757365724944223a20226137343733343363643833656432663933623236386536623331393761653566406365727469766f782e636f6d222c202273616c74223a202263643839383964663136646539303938227d", "TOKEN": "0416b22382b63032896e9f0d68cd1044dc620a84bd9a9a408ad5b9b8e58b9b487a18c3ada1a284b2b7b5164d31581a7273da7fab4da421a61e8559b7bd6fe975d1", "U": "0419ac1ad65fe3739ee6323d139a76c8e924f772ae9b9580ca3bcc4e1a65be75ee172497254956c71165567f456683912ec6cbac90580b6140a92ac21d6e13620b", "SERVER_OUTPUT": -19, "V": "041a791a10fa026bbdd27e6fa2fecf9cb73b5b0daf375e711510a252bf17c3c5da225a5612e216439e021407de1d70f89c314c7ca3265844a6ff2255a1f42357d3", "Y": "0670647ae3fe0a9beb3991bcbe44670ff91425f2b76301a2adee3615980044fd", "X": "0bbd3361bdeaaecfb07814a03b6db949eebc4d9e7b20ae38109812277addd815", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:44Z\", \"userID\": \"a747343cd83ed2f93b268e6b3197ae5f@certivox.com\", \"salt\": \"cd8989df16de9098\"}", "test_no": 119, "UT": "0422273b87a67c365bc1b6733ccb921ec5db39a61c55b9500d8b091e2c2a656ad8198369f75262558acb7e4e26873a97a49d42337369d5107b94b2fd2517821d75", "MS2": "11f15ead6901c2362c59ed162e03229c2176e429cf6aa570a5520a0ee953c926", "MS1": "0979ee5251ad623b265b74aa6551763df997b336d681bb6bce4fefc4957c60c3", "CLIENT_SECRET": "0404378794d905c4816aea2a63c57b3fa2e22473f8f1ad92855efe79dabf84034e0a87817e3897dee4f707ab7e1822d6bac06bd8888f93a62e4246d92cee35e2c2"}, {"SS1": "14746859f8444ac8f2edb399d86668ff122b91a220c00d7238c8e551919b89c7172a67d741f0c618958b5e2f30d06aaa25ad80f256a526459d33ad4dce25c19b16188df81f1187d081ddb7ccaf83073788cae9ea02cbbdb5da628c17cfe01ba7159eb0aef1b9abff8f40d747e586cda331840c9123fc816f45d3caf12a2bfc41", "SS2": "133853da7e1365d32da45e6c78284cf403c97fc7cba5949c87ec8d069ba0f7a302886d3aa4a654425295aec1f0e4991f63f79d1db1cc2141f79414eaaf6226e2074d6f6887e21f6f48d0ef75ff960276b5d966ffb44a77c85228aa48894e0dee1923d789791b251d50575a18a24230198710f6ac3de0c4b76fbe2082077dd48a", "DATE": 16574, "PIN2": 6094, "PIN1": 6095, "SERVER_SECRET": "02beee69e8cd6404c936796024e498ec7e817dabfd6e08e86146ac346f1161da1282c59ac30211024332dc1ef364bf75c7d14bc4864ee0ac55880c32f998cefd037888ac4f48103270cf64f8c10aa7fee6d01fb990458479d03f4a5c1e7f33790127749a80d3c35c70ea638988e191d670dff6a52c519f76766b4f141dd89ba7", "SEC": "04119886e61e4679684960138bb52a3da526dc42fda142969e24bb5e60566423cd0a5f5acb3ec485be90f977bb9f66b8dda42ebabf3d991da86b5f57db04f40ee7", "TP2": "04119580b6b74af28cde25d8e3b84257b22f2d8220f067a9b646de0688e53a650001d1a8b5026eeb1d035362b70fac5cdca96e009d606d604e1fd1307414446238", "TP1": "0417736cca0498d082a90e51f3f843bf3be34e95f3ff20cc578e9bbe638332825120bc3cf2faede99df1e9aad0b5fb3d842e187438437e24dff75397612734e034", "CS1": "040799e7f3e489ce75cc2e18ca51eb10d3cd461d48f50fcf5f8b3bed17460869a3100cde64a01f4d10806fffa16f0191369ef3c634f095139bce34cb1b2390c17d", "CS2": "041a0adb6a8ddfe930591e57cfef0118206721beee75177b41a4aa84ce894b711211d79018f47b908fc20099270cedd48b449b1d2097d6de0b331fd66db1a35ba7", "HASH_MPIN_ID_HEX": "bcb0509ae11cfa1234c2660ac5b7a96ba70f7a490b62f8a1477a654a84aed715", "TIME_PERMIT": "040aeade4227117c4ac396702f486ea5f8bbc469cd995fd14faec00f2addafd2c6008075c4f572dc4fe4032dd6b207ed4b1b48c25b5f4751a1233722c483d1a3f4", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34345a222c2022757365724944223a20223833393365346264633132633632356238663833313463636433313938363162406365727469766f782e636f6d222c202273616c74223a202266646361643834653037323033623963227d", "TOKEN": "042230a39bb8032023e9e8662ebb1ad6f9e8f6f13aca0eb9d609d1e61e1029613e1441308ef6b7c455ed39a3d9a74bebe0651728901a3a505051168a16759dd4b0", "U": "040e46abc4012b6533f83596f549e41c6a491c7ed0a2420f4addf227d293a87e6c00a4eec74532e6d55b68125c81642d3301f3fd988abf8ec68ef571f5e2609896", "SERVER_OUTPUT": -19, "V": "040cb6592dca13e04d23cbb14e42d652a1c1cb0ba67cd928fa118e126008239ac021b483f5ffbe7b25e598b8408796329aa19de383661e639e0f33bc739153c557", "Y": "059fc64e08a1e5dd02e26328210f83c76fd18b03981236f4ac2e9145447fa4b5", "X": "12b4dcd8d70c1fac4e37444e9e6f4bd409865f7dfacef497adf7cf1a492fd5a6", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:44Z\", \"userID\": \"8393e4bdc12c625b8f8314ccd319861b@certivox.com\", \"salt\": \"fdcad84e07203b9c\"}", "test_no": 120, "UT": "041605ce1b6b30343d20653d28ebff93e3089c21f6e85c7300ccd99d2788574d5d1dcedc2cc9afed9f05edb4d4c6e799bdf96a6a752702ef2aeb6678c1c4f3bd54", "MS2": "0ff88351c43cc599dd0cbc9e9d252c505562213b38e982b8aa41e2c9a833c355", "MS1": "1e301ce8942bceecebbfdd3e16623d86f11b9ae20b062b2dce59d854cc0b8093", "CLIENT_SECRET": "04071c084b8b685fe70d6af90629c4db75de9858e23b770f6d080c310d0140fd0d0546d0bb8ce338e4bef878e882eee1cebbe47ae1bcbb81536ade277b5e485ba0"}, {"SS1": "06671684aa3649b86c41177ed71106f4390305aec44ea33035ce711f00da61dc12803c098e2f8961439a8c345f37471c9f439a8beaa295ef09ab75e75e05946320dc36feac6d056df61300b89c00068770059bbea2d9c3040f13e0b118f5b2250e4dd6ae1ff90a88dfe433e7d7ced5665100810d1369c9fe9533478dd3151526", "SS2": "0f617d1076f48bbe60c5f579ec67cea9e0e99a1ec4d5a19bb3351515d1b4c7531071d1b14b1b52bc471e73388b80401575a2cbe39e1b6d14564d447bceade0da10828f0df61c449b7bb0b4d506b80c44c14939862c329b880f6aa039561b40f70f555bbb61cd5e6398ed7759553814b22c32e3f5f2d5286925ba32f379c38e8b", "DATE": 16574, "PIN2": 8623, "PIN1": 8624, "SERVER_SECRET": "10f6edf48c5d82a001f33fb15621d511e8cf642946e7c295d2ac33d7a0eaa6a017ac0ad3fc2c0e270d2c25ab5bed8ba04e1ebb69e66d642fdd213206682ba0b70117385d31cbf44e0812be68b78954dfb1aab637cbaead16c580b88cb209147f04abf5341cbd602b855a1be69bfc71d561dd98cd327701bb50b2844d8280557b", "SEC": "040eecdd0b9447b80ae8deea7403bbe770c571aab871331a1e013626a44c0a08a003edf38559b770dc87ace81b3ffbc3724b6b55a75c3ad217744d3f13d6f7479c", "TP2": "0406f6599e6908b4d4e8c79a5c5e79fa3dc04e8860ba3d25728b74ccfd5e9aea1505b09c54c78e5b7f1d685e01df247c963190cbced6ad934a599df47b408c196d", "TP1": "041535ca711881b058ad3e8554461f141020d5a29115b1456ca3184f6f02251753228f35ae0ffd11f023be878a076c691b5725b8be2f63ee6644b2d418e439c2fe", "CS1": "040601c3cb10a13860921f861018ee7eec2fa35d2a955fa3259f57ce60703d44420fab45fa95a1dea13abc828ce12628b2f8274c4e0d18fb8188a0d34381dec0cc", "CS2": "040a28edea1fd43435ac6d5cbc80a3d046882b27e19fb49e008ac4043affdc9c0f0d62b29126e9a40b02907b210a881460156c855ccd707d8fd87e96e94ba9213e", "HASH_MPIN_ID_HEX": "7df4c18cce04025eb20112b9456fbe5bc0539ba54c97fa40e553eaeecd1ee3eb", "TIME_PERMIT": "0423693df49549bf88c67945e093bdb0caf086fdd43146e9e84ca2e3eaf00a6a2f1e099428dc5ec05fb4d9846fa42fd5ffad4e9a42b02ec26ba76108c549dbe97b", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34355a222c2022757365724944223a20226135626334303933633166636630633432653435643334306531333134316339406365727469766f782e636f6d222c202273616c74223a202230316336376633353133356261396362227d", "TOKEN": "0412981281e288f397e98b7d7f8bf18fcd84cc9f1b5d8d37d275e9adcb841c27bd04bf19c35fbad5e012556a7b714dab2d90c0c61169b86a41cb385043e6bdcab4", "U": "041bd021b16a7816b42a9a01f7ccbb5cf3c054a63df983558f02030ad202197a0201dc4c8a9ac5f4759bf0cca693b2db293a110fd4ce1d4cd05ba3e91572d054ee", "SERVER_OUTPUT": -19, "V": "040e7413551cdfd027a35d669eb263b527775c8fcb07e34df0954564ec04da65010f800961c20b1c27b830b74ff5f53dd3b9986b50bc3af27f8a64d5b9bb2b7498", "Y": "020d2ba1962eb5ef02c892fa5a897da1d907c788d1552018755c32fba3e00e16", "X": "210bf7af2ea5ef1ec5380410d1780eb588359de851a78d279717bd2afac4fb94", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:45Z\", \"userID\": \"a5bc4093c1fcf0c42e45d340e13141c9@certivox.com\", \"salt\": \"01c67f35135ba9cb\"}", "test_no": 121, "UT": "04190cc93c7509cfbe982384e22f17691dc04d9468a923028c8bac0daa029d5ed507c74f39d5173ad22381ffec1ec19c2dc17f2954c96ef40f9213ee1a57cb7ee1", "MS2": "1bc1251e6f6192fd00fee1789473e3e53ef3b1888a260c74dfc20b0ec87583ba", "MS1": "009e9f021ad87e5948ecb208ceeb6e27beb5695bc206affc0702d2f2acee09ff", "CLIENT_SECRET": "041f44e435cd45e9dddde9a7fdc2dda35f9b2e6f2041df2865878e7ad0589d40360ea5c982b121a95e166a4b7234291b5f9e2bbbdb213044f8ab8a70e52bd7b45d"}, {"SS1": "163159c9d07284509feffe47d90a06a4570eef3ea8d5f7616e73c0f647a8742e059808445a61b65add1194a678d55ec03b9247a6b8645bf1de8258e9bce13dcc0a0cf4280fea785ab6ce20544444166a3b2969ab5cafe83ff7a068d84f7422310c9af55b6d473ed3b0cbaeb31164479d767bdcbd236dfe901c305301142642d4", "SS2": "1572c8e306328666fdcc6a7db657751aa311b59bf8eba99ee2f9e12b8acc77d4215190e312eb3aebb83590d7a09465387aada6e0e3706d6a9d02c3562721d8251a84ffdc0f4416fcb9861d51c09451d6bffe9c8af014a0a2fe35fe4c7ec547e003f14d714e3bfa25c03c13693c4c13946ced52ed483fec303e5f4f18edc36a55", "DATE": 16574, "PIN2": 6561, "PIN1": 6562, "SERVER_SECRET": "192ea56dfc86b965e05bf4382c9d50c530dceb9edbd260c745197245413967a901db5d5e0f0584c9ddcce3182e9234df483a2cf9f51c04e0e207faae8ab8135e13944cd58a0f79f8372de1c9117239b8dac3124258b93826a067d04d2af736ea1d28f2e158125782e588ec508db54886ddcb01d4a116ba4b0932d406562f3a02", "SEC": "04154de7d23c3827e76216acf6876de9b74f38f7a206309a2cb9ec156aab2144920edb4b16f8b8cb264640e53d7ce736789b7bfd1fac857f66e82a5fa1bff8e496", "TP2": "0423c19d02ee4a9993c73be568d6ef4feb337d414701f3d041b4c9425f6e3ef71f0859d28934611a0f3d0b9281de90eebf09d2c0a7fb6c85b7623049edb6ac5074", "TP1": "0411b4d7bd9a33c1c6d6d96ffffc984e57c829372d48d5bc2d37dd16ebfdb6a3e1113418c9da7fd9ae7adc321f16e8525499aa762ab62aa0073758afe63a1ccc83", "CS1": "041f6563f5c8467793f67a267d983041ed752952ab12ea1bea4bf7bf23f92738cf0536566dce0a7977ff2197debb940881f90f0ba8d87436df9bd8e62bd88d019a", "CS2": "041e064983741760fb6c6fed5344bcb26abf4177c29ff523e7c5a48d24f4b6efcd1f08264956b106e6e0f8ee21c7dac8691796713354fd5736666158fb70f6ba2b", "HASH_MPIN_ID_HEX": "8f67331205c9caebe571b7c9b54ca24a38d5a3ded6a591f43c6621d90cd222a7", "TIME_PERMIT": "041036b417ca9b011a1818c58a57aa2cbbd6cf73fade36eb28e86b9be488599b9c2355eabce0e69b8dda2aaa107fb7bf82559bc2fb9d1ed999df405b1af953636c", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34355a222c2022757365724944223a20223436326666346434366363343837306335336137346236396161323038303264406365727469766f782e636f6d222c202273616c74223a202264383932653537393638376463383632227d", "TOKEN": "040d85a4b913d0d97aafc8255b9d1cd1dcd91a360dfadab435bb187ea6c94278411e879127dd5f8f363cb6c6f3fc1472ead2f93e22c2ac34bbfec1ae2c0bc7b19a", "U": "04046310aaec07a436f6a14f3bed56b22c3d786d9071af70482a42480e6230b7b403465de111f56373f5c5be32312dda8c9c69213983b22c29b0abfffd90c86345", "SERVER_OUTPUT": -19, "V": "04223bd88a8ab01a24297d85035549e4919991ea294de5fe72c0150c73a04c56f811d0a5fad743787c26026a51e76e9331221e24c4749912099a0152dac93b7086", "Y": "165f2909a0889e9743774c8f8c77589f7d4ffeaf3804f5dc746e5b41147449b9", "X": "1b3dd4f54fe09f6623260d628d81b15de9e91f646cc497f527f66872f8acb2b1", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:45Z\", \"userID\": \"462ff4d46cc4870c53a74b69aa20802d@certivox.com\", \"salt\": \"d892e579687dc862\"}", "test_no": 122, "UT": "040a1eec9df73cb102f9e1401e66843af73ea8a304058d2c39e4292acd02ab5cd119c6e340d8b159eadd885cd020b46c05fd3b796848183a1a0a4f5108361e2dc5", "MS2": "0a2cc6fad2fa2f2f1eb5309502bbb09519e528b32fbf2f0afe8d5090862599c5", "MS1": "0944011f5a92584239a7fc84752fb6c12e8c83be85a3f79882871eb59fe5a1ea", "CLIENT_SECRET": "041c3193e51b41cfcfaa95782f3aedd1db3688643cc023150b6c8cd06a6aa14e7e0106cb84cf512d51707671766435064864c06afd220f05ebffdce3778b8d8aff"}, {"SS1": "229183d17d5f508055eb7cca16da16ef2026449f47747edcf9b9e74cbf9d1abe01cca485512805bb66215fd9bb0dd242501e376d113fe9839b7cf93de1e4500d009d27c36b43f41a3f56d35582da00288720c9d5f68762da669a5f34442b80360b03fc731bb672470c47ebffec31236eb3a357d27d95d31c31cbaf070e808fbc", "SS2": "1560850527de7e199ca654b760b66e9554f2ab870d0fcd0d3c7a9fc4835049fe03c993c30618ccaab275d62b849a4da6955d5f3fa52324563debfbf4ac94acb70d457a8a57a9fe67858d02119a0f0fe58378fb883945e3820d1af6a62a3981521d5c9ea33275aaa019503ac86791891e3e339857a2b0e37b6e305ca7a34f814c", "DATE": 16574, "PIN2": 9109, "PIN1": 9110, "SERVER_SECRET": "0c72ab81258f2b1b443049701c1701de185add36888941a453b2bdf943d6bb8f03de6712193727dd1db2c071b043545850311b32c1940ef0605f449dd86b847d16b11b8b35b98ab80ac35f25544f1eb3fc78a11d3eb3302974252a72764db3a112a9c00bd38ce3fbfefacf9c062520538b0e96f985e0a293c515060ede239f64", "SEC": "0411fa63bde422041d15274754edcf0a0e82d04a1393a523b6d2b4f6dc97d1786907f3b828c7ee9e9f241d707855aa1b206d9e78b91d49f0a935325ffb0ca6b0a7", "TP2": "041403e042997865acb89a509ecbac8baa4eb281359f7ea9bc4f8140ea780b6be7207e2058d447feaca629bd542ee97af3e7c4d13c4032260ae59406f16173271f", "TP1": "0400f10769c66f23b0f7e44bc7a9aba97cee4f50802521d084b31fdab8c5a22d3712f46b2367819a7bce47ad1e1cdc1334bc86fb67e5ea2414be7b7b21e95112e5", "CS1": "0409b41c80570a44edfe507c00b3667718c574e81d7969e9d4251d574ab30f0f990cd2ab96269cdccc1a4d7a1f7ad6cfff7cc48c5cd14e709ab791a9dcfa305adf", "CS2": "04033f57b811eb1015c475bbd3e1ebf703d614a1b7c103cc3910c400dc4dce93641326066856fec36af532a5e1ba1957cd1e6df025cdc210e13d4404121de51631", "HASH_MPIN_ID_HEX": "efb9ca86d4636bf87a50b82c56cb5fa306e814dba2a872898d8c1931f918f105", "TIME_PERMIT": "041af7bfe3ca494b36117dc239805a55a1b5630f5b7668eaee7cf1194ec83d794a2258513cd7824524153d6968dbf423a572cd3ffd53ed2c552d8a0a7ad10cbaa7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34355a222c2022757365724944223a20223031623036343537336130636665623563333137643537613530613634623761406365727469766f782e636f6d222c202273616c74223a202233326361316338353138373436656261227d", "TOKEN": "0421280131b1668939962bf1f1d51393d0ba9975caf61f4205e849d72e4f9f909913c00e24276f1c28dff6fa8aeb032a7fa3d9e437708c664738ac385acf3e11d4", "U": "042199077ea361e58e847d9d70c652f971bb98b6e4e6ec8d35e4256e2d63e5dc7612c7200c37eaa82733eb6d879cda1bb7344c2be3ba5508f437c4484891135591", "SERVER_OUTPUT": -19, "V": "0412c99bfdd11822f535557c295ee1a735673d4468896f99f4132280f96777e27318661086b417088a7826b3994f93c4de73ab850308b3fcbefb0c6784dc284c0f", "Y": "016d483d28b1e4f7b9d907a991926c2bf6719c06fe64904be0a24546666048be", "X": "13271ec72291598fa91107e21e7ad1d8193c4ad2303b2f14454e22a1accc5297", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:45Z\", \"userID\": \"01b064573a0cfeb5c317d57a50a64b7a@certivox.com\", \"salt\": \"32ca1c8518746eba\"}", "test_no": 123, "UT": "0420ba459847562fe65b9e381ca8374861d0d4df28757c4eb240307140ae7d425f008410144f5c7d779686b55fe9958a1637a7c8c89e70ab8c407ded53d899dd03", "MS2": "192a2310b259bc87504d88da7751716b16772598f34cf9c6bf9a9c346725c9c3", "MS1": "1fe915d02dfa39a10b56a4e59f5732dee3db09ebfe194dc03c7df21051d95e64", "CLIENT_SECRET": "040a7833b229929dc0d35203663ce54d7d9f8122dfb0288e200ed125b77dfe87b418214d6d771537669631b2aa46e09b06638e87fd011c2957775422a84c1ab1ea"}, {"SS1": "23d1be133a4b25386213ecb2e14ef30b1db190585dda8424e27cde9b1b4ea70e15b8e500d194fd70197b851f9c2f2b043739d44f7869381d256bc3d02051d831213a7520f276f4f5a225aa0a9820b2a0e5210e20f27e894fd1536ffd25cafbb10bbce1c67d4e5b54676c6f19d95a8e9f397085b607ec3e593c132d08cd0798b5", "SS2": "0898e49661491965713aebb5fa91d597e8255ae66897211142fca635e3cd6c9e22f445689042625a76c81f94e28d7903f8e429c5d290579853ac0d0c6957fc3a165bc2beae3c254d03180991a241f47ce25ad6adec503032ca27f19c43ef06ee028f79c5af74b2957df1effde797ba90662b4d4fd824287abb61c8280923ccb3", "DATE": 16574, "PIN2": 5397, "PIN1": 5398, "SERVER_SECRET": "0fa99bafefafa8eb191f4ffa8cd7225bde1da5fffb36836a3342e67bb7cdf3e410e586703ce0a4df0f93e850b98d503b2bb5f5620c124c3210810ab0f9d70c8b0f0e2930931afd478ce222aa3e2e5eb8871c4c00ab745580c09bb70eebe1a79702b7f0de9a629b2dc7377af16c121a2a4c607745f023e68ec8ecf6aab817894e", "SEC": "041b2ffedb28fb44136b94d3d7b1f79175aea00f01e9c4b405ce588b4a5c30800f062564448160a33dbf6cb629b8bde37b55603cb147e3cd1ce70747e35c37a387", "TP2": "0416930ec4d4b38f1cc7bea39ee61cfe5f3f130adade2fe1b57afbeeb78b592a03177810aa7b4adb62ce50966fc5499b7cf8a738491d2071a3744b3b464bd149a4", "TP1": "041982eaedc551dfab4c94f4aa83c96f6d30215fd0a1895664767910f45e10f34405fb53342f6cacfe2303fbf99a441f6f5464ef49dcff8399915b750e6a7f0549", "CS1": "0412f1272903e1d96197404b584c8027316751dc20c112b555557bacab2d8cf6ef0f9079c560542fac2071b6526ee3da2f48f52a115d817d9b18de83a9ceaef1ca", "CS2": "041bad7aebbbf253b7f6e40ac130916196684b5f7649cdd096614e702dc0cd9f8e232dfaa431291033111d7fb2e286fd5d369f5d192856cc60c2c954bf6c63db8b", "HASH_MPIN_ID_HEX": "f9ab9b14435921492bd0ae0b6b8ec31dd24ef50afb3f2b0e63b8534fdf2fa6cf", "TIME_PERMIT": "04098ba2b4c3ac5d6999a0780315e4a91493af75bfbab6687efb0c33e4a042389d006033919c4122b0f7446e510ac45ceb57a515436531331b6ad777165039324f", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34355a222c2022757365724944223a20223234353933616366396130616131636437343238353465313337633865626165406365727469766f782e636f6d222c202273616c74223a202261393339343866383430623662373263227d", "TOKEN": "040acc3ed8a6fa6fe9e08f0cdae12c806523767c867a18cdd4eee27365a13e0e7a13ef5ac55826b13d5e8d89243efcd5593c37fc61bfd45e8b05c0d6eaef3f5f24", "U": "0404d2eaec8d5b872e1375872bd8f53fa59f63483d851e2977eba0fd495ec0720f19ff4817824de7c775853a8be225376bab4b690d81b44cfa808ee52bfaaba451", "SERVER_OUTPUT": -19, "V": "040861978ed013ad7575a328b4cd8cad9c7a93ed32525b88344d062d9a173a2da820773bab1410d226afe1c879fcff837817f4db665d6bc85f5519e4a26a68f177", "Y": "0071ef4c8cb880594343ad2c1c580602670d60f0a0d6860ee41cf6eda26220db", "X": "20cf8d2ca8e74b41106dd42177041846204f604b035b412d2285689de637dfa4", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:45Z\", \"userID\": \"24593acf9a0aa1cd742854e137c8ebae@certivox.com\", \"salt\": \"a93948f840b6b72c\"}", "test_no": 124, "UT": "040befa116d4c4cc729d7346c886d7da607613a553b563acfaf6547b5acd1fc7e80edb99e17b1384cb0e103c6054ab9b296cd73bc50ad5b76787deadaa06e16038", "MS2": "014fd2ce8640d56a8018ee4929bc05a261cce55d53d78e51fdfcd627bfe5ee89", "MS1": "16a232d92aa71a6d4538623ba61f28e6c281cb8280ea863241909ff44aaec128", "CLIENT_SECRET": "040b196ad91f408269a2211663f3def702ea7052c609dff0aae366ea20fb21a29d0435035e7daf2875def94172b2fe7b77e57fd22f6ea6732fc7719cf66554617f"}, {"SS1": "11bc65bcddf46f3260fa4cdc02576e7f961ba36dd69491c75361a6ed3a0563a9084dcd5a814c92ab8c0f0dc46e33e6b4acf18987b89796775b258ac3ab2f49da19f3d879512776c75de26b55204a2c6792852152a19bf35b07e244ddf8acc138059641ec072fac23dc6cc080c9a083b84614c21c939d372af90c6dcbc3e53bc2", "SS2": "01d87c9274de1ff9845575ebd3c2225fd2105b2edc5981996ff35093c7f8e42609ca619da50a0478ab6b37ea1169daca488eece2485ff5f43933d21ed9328f331655afe6d4a4298b8bd7be9aee53a9f44a9aa8ff535927fca6868408549008181ccbed40317036d9274ca6bd64a1c171692696ef671045a6906431dc26176d8a", "DATE": 16574, "PIN2": 7460, "PIN1": 7461, "SERVER_SECRET": "1186dfadef3c252a91ab50d10b60e4b6b7f7b82cc90e8dd39e191c7040df522c1ab1d39fac391b18d347bad48ba0f486c510d82f5461d1237078668837788b2f0dd3bbda252ca7ee3041eb6da1386f6e04ba56e4171ec81adce4459a28f16f7111f0dbdfc1afaf261b48b19807d0cd4f7814448d2d2e954343d86706a738dba7", "SEC": "04202c6f6ee02ac663489f6c40d41114850b15869d84130fdf4c6511879843b5941c052168b2ca00f5b3c5b926f7d571f312ac62db3519ff7ab751534312853650", "TP2": "0418f3942c87395ebd021e7a5e89b6e62a0feb0389f94da73ad9b6294069c4ede01fc21ac91182779b5215b5f3c272814069dd0adf9ce0458f57782af233259c69", "TP1": "040035d424d501af479cc5cf870d6d3f36e7577b86e43a6c5f9d5046be5f3f2eb50bbc65d2801c3ad3691ab9863d0f7252253f1b01036a8a5e2cb03f6b1a2aa68b", "CS1": "0402f07a88c879375120185465780d916a8422107e9d89919f428055457c4cb3ac230b7ccba350ea707515e33b3f1c6d02dce633f119b98b53277ac8d2686cd3c1", "CS2": "040d96da138196e89db12ad697a4c0632703ecab0682852a19fdc3761d34ffa414119e93f0c53f1217f9f785c153a38fe14521ba6e9bdd55f6d115396c830236ff", "HASH_MPIN_ID_HEX": "f2404ccff43b8a04341d88ca00b9c6e4781e360f0e6b771bd710fea1f4fa4514", "TIME_PERMIT": "04151d3d382849e5572bd503bdd632e083acc846deff45fa17fcccb5f8f6fe4e0d0f2d8fafea9a98b20ee4aa3e3f60c73fcd7c716261324e44687ea7ef06c14421", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34355a222c2022757365724944223a20223439303562656233336561363333306262623931353266373263376336386465406365727469766f782e636f6d222c202273616c74223a202265343366653433333930623630656665227d", "TOKEN": "0413e8ab1f1283aee3f424820689d6dde0b3d598a921636ce07c41646fb753b8421be729d604adf5992f5f6fd8faffad3981c07b563d89a8721590028d21258432", "U": "040bf6c00330a865ea3b2238bda9366ae59683b984a7460eec3aa985287a0ab4461035430d66cdff43c7067f990d899c717fab0fc87fa744722cc9bbdc65f1b369", "SERVER_OUTPUT": -19, "V": "040c344d9786b982ead08deec9a6764ee0dad341a65a125c7b6469e243459d6f7c1222f3ede5e7d1d7984f6808862df272ff8e4e82e9a02e91e47ad40805602ada", "Y": "2250967d0aeb1e4fccf4f4ddf8fcfbaf1bc7066ff76346a5ea6fa3d5d1816b86", "X": "0fd636d8f1580f19ab22a63db92b194f1877584488ff03d5bd2e334d1bb78404", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:45Z\", \"userID\": \"4905beb33ea6330bbb9152f72c7c68de@certivox.com\", \"salt\": \"e43fe43390b60efe\"}", "test_no": 125, "UT": "041d5dbafe39e111cc6bad1a4cf1677eaf8a09d6eae61952122236c13f933d6bbe17f0a6fcd9fffab2a6ba08079017a1c448457c82e3757d9f004783f8da2ce49c", "MS2": "17c913a2ec90cdcc53de154dca24bc762f812e350ad2345b6f6c4059ce15a984", "MS1": "2258ef7945469c155a839adcbeedf6a4f61c07266df5a5bd46fa0d92815156d7", "CLIENT_SECRET": "0408aca54626f120138b3a1f4ff5d9fe74296e01174809a0ecb6942da3614d7ee0226c3491b4f355d89139a7e655b1f5779e7f78afbcb4e31ff19e36cc551c1154"}, {"SS1": "164d787a58b65416141cfdcaed23c145acb7e586667f6a7508b47a3c261945ea0acbff4d30a60e12efca3c8ffdab9442293d1c7b95680c90e605f53c235e2bdc1236cfceb60edd80c2511005addfeb58dd852624013692f4692ff4f1f4b6df7d0a4cd499ed8bb203204d14a8522f946aebf06c259619d13981eeef0e56c4d999", "SS2": "0cf947f6574668504a929bf01cebf03ee3c1d7299739009a252db0bfac7cd047224c906ea3781d43cac526da57499588e27a912d583cc51d960a535f968c0846220113c25b4dcfb57cb37f4870207080688bfb894ccc49e1e515c96a3e6feb7809e8426c65a2a76e884fda0fc6ac6f1dedc6e49787334111f7f50db86874d386", "DATE": 16574, "PIN2": 3481, "PIN1": 3482, "SERVER_SECRET": "2067a06e5492b2436ce1655ff6178b683b987f1706fc2d5e00687831077fb23c0a8d9d059fd757f61743fb2f12846317c4636905d065098de54c5347114371d71580ad4a5bbeb2b12071598d45a63ce9a0c1aba3e5577b8abe7a0f59a8211fc90a47b5fb44aa7751cde5b3c77d9262ec8c5d314c763a79c067562885923db496", "SEC": "042134620af92604ef36c828177bbab2700d4fb428d78f8d4475db1d95507c3f4923b36a8eeaa072f9e4d7ba16448ede297df6ec3e01790292dbc32f7ccebda6fb", "TP2": "04109597807bd8179ed3b671a0c5e84eac00313e525e1b87c86c2fac10ad7ba45f136a88d7763d66618e695521ece858f931de9db172ceb278130817f755aedd20", "TP1": "0402b15dc61a273681b68a98a517e165949338ac080cdfd85b2e60004aed972c081508f53b0cd70074249e32c19cd85121d4243df50c8b9402fccb310a1bd4de31", "CS1": "0413f5cdd151fc8ef152b845ec3f6efcc8db0946b555aa5b5ba1dd26fab75982640fd2dd5f76df1e77c8919355ec497965ab943ce048fb74d55d62de12d328fec2", "CS2": "040f261835bb7a395fa8cba9862ec9279dbc10bdc7909026bfe460fb0c18e81e6f1085321455637a84e048a7b53d158594154fcbb009d51086c3cbaf6fe1decd16", "HASH_MPIN_ID_HEX": "a83850fe1fbf72affa9a2d934610050ca0995d4ea7c9fd95b4a88c66303c50d4", "TIME_PERMIT": "040fc5ae788eb2487bdfde53ec675bad68ccf7b665e5182319ed44d8ed57489fa017659aab5b51c51293a6ed2bae2464260eae965d7f87f17868b60843ef08a3ff", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34355a222c2022757365724944223a20226536653932626630323662363764396565373638383132373935356563323131406365727469766f782e636f6d222c202273616c74223a202265313834346364356137343035643563227d", "TOKEN": "040a24977a2a7a2d9d51dbd382953e63d2d36f06c619fe0cd4247c26da4cae4c5322af02c64b3f67b64575420404a996b5412bb1bbfe325ffebe07c92f57a8b846", "U": "040b2ae921bb3f430a7464c544f9769110314478b69253bd9ba4e86a078f8d8f7913bace5cecc4b8f3867a9b869e2594d4a990b9ef1571f4f49778f6e4436f3602", "SERVER_OUTPUT": -19, "V": "04006dee90f43a604c922f59a3bfbd1cd2719d785fd08fce8a2c3fb18f83a693401d55cd724932890fcdf3e3271dca591c7e180da84db7df5ca488c4b12e48db41", "Y": "09f0634e477e56bcdd9e1112013c1977d4af48b5c712c45a51b652c86d39039c", "X": "136b47220c0793e12883eeff43c227c6a363c79ceeaccb18ad661ac5f3979503", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:45Z\", \"userID\": \"e6e92bf026b67d9ee7688127955ec211@certivox.com\", \"salt\": \"e1844cd5a7405d5c\"}", "test_no": 126, "UT": "040226292622574be51100bd2e104cace6b0a3eae0d9b7a899a02781df4dc9fe8c06aee81c3d2a9948db1de764f166cc39d6ecd2f1a64c58aa24499ccfb8ac5952", "MS2": "0a16143e3308bde74770cc116b9a7f8cee97ffef0d6b3a98390a657faee05d11", "MS1": "23526113861888f446fca8c864147d9757fa3ee37869f5021d28198e2c0e64a1", "CLIENT_SECRET": "041a68d0a178537d4d68038e1cf07a09c077b35210f8491bc50211176891ca4e1c038989ed2b6312a0283a82f38ac9e83b996c7dd957c34c28ce2a2bd578af262c"}, {"SS1": "1ee03bd25722b6a4234f76bb612d37c8b2908d98b5f75bbc06dee9c920e2606d1c8c0d4559c977a629dbd11d74934ac6d9910f9c24e83bdf4eb2272ee1f9b9900ca5db09b9738c838d07420de9f74a27f8065101ffc2cae19ae32e0586f1721408b9ea2e6d4b3d9dfede7e62aef203c9935b6cd8ab6d9d6d41bab5047fa0e094", "SS2": "11c0362c05b61150dbce0c5362766b8e4d6f19bf3975d9ec157c7143307503b80624dd54d701d6c9119439cb35eba553f06dc0f3f6c7e82b64b356fe932cef8102c195ec969667396b3efb5b4cef21a0bf89fd89a4f9892fef4ec0db8b783ed909bafd51f368af86f5cab3fd985f05ffb23053646c6b572ab314906a99197706", "DATE": 16574, "PIN2": 7551, "PIN1": 7552, "SERVER_SECRET": "14d57a61371a043be2ce1080f7299c66adc775803b58dfea0abfce885ce30c7820b56f6d7d7ef1489e6c245d11ad4a49e32c79423aa04dc355747e40dd6b049315e0b47f65b0ac4246cf9c04f93a08d53fde8c13230d127723e74b2edcb138db0e1b218c360a64b642cf2407f0b00330b1fc8e4d0a4da5eb239b35b83716a208", "SEC": "0417b24e6d05cca4d5360ee87e093bf74fa89b4bb3c541b3fa747495211f5dd24516b568b67c164cd977b598fdf3c84b33190fc6ea4925de207ed172f468a2899c", "TP2": "042286fc4bb481a8bf922318d862ebc6231f8bf2ccd83e5189d893bcafffe53c0c15a3dda40a55c30756dadd81cc51cdea4195e799a53db97efa93994e8ad8e835", "TP1": "040b2d34418bcf233035be780956ae5cead8b74da02f656a0b4efa6b9f4afbac2922cc00ee08c7a11587faa657010c58618464c8579b3efe0beb24e8f82830c994", "CS1": "041c5dbe9fa5705580a604ad6f7cda55ba1b1599134dfa05959835ab815ef809be1e92cef613d6de3fc70738c54c8f996988b3e9d30ab288b225bf653217fe05d5", "CS2": "040ce4b1a757e90889ec3e0efd1f1ff0a2170254c0e636ff9090716352e85af1791c2f93a11e3e97ed3dd811e6055edb37ee8d5c1230e29020fb4663e1a98d42d4", "HASH_MPIN_ID_HEX": "2073421533e4bb9506699c927d8f5d06a45c7c947df80ee7fc319cce9a37b84f", "TIME_PERMIT": "04168f7ecc515e82dae618dda52ae8c773153b47c011f32532fe50a4f12b43e558194e53003ff886d85f5710d1da7270d970058baf3c3c635dfc2a86163af0889d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34355a222c2022757365724944223a20226237353231663034343064386535313637643035383164333932353336616138406365727469766f782e636f6d222c202273616c74223a202264356366373964616334656663363939227d", "TOKEN": "0422ee3b90aafeb3d2baccc195e2f80fdf3baa5d0580bb305f1feefc618cbfc7e907b8aec6abdceeb3bd843af9a257ae3c7769abdc14e53460c30f82df37c19221", "U": "041b13e835aa0b59dd13c4c3a5ed7fbebf6b42d31a83c43c44b8b56beac0dec2141028211b385c0d8b8e2e0c8cb79d71057193d3605aa1877a1b2cb49dcfcd476c", "SERVER_OUTPUT": -19, "V": "041fb768899e2df7dd04ad2211a8cd3b594b2758140ed51eeed48760fce818163c0458fb76cf4a4ed052d13439f9d31ea49046a2fb3a8c906d49e8914f07120a4d", "Y": "0a5fa56c0074fc4b4a3c0048a8bce783e1f5caa02648c0dec08899a3f65b2403", "X": "1ae2a59888e4c043c87ec7f2959c0b4f74f315ebd95eb6ed1c38c782b81b02c2", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:45Z\", \"userID\": \"b7521f0440d8e5167d0581d392536aa8@certivox.com\", \"salt\": \"d5cf79dac4efc699\"}", "test_no": 127, "UT": "0416def3a6f817d7c816ccbc8b6689ebb3721e46872bdb15fb07e98eb0d133c06a1dca77b180d417e3de89466a70a8ef8d3a1b6fd29431e9ccc3fb85cb6e9dbe6b", "MS2": "13b545412d1375b85025e02e8dab6b430d0c2e9d71031e906fdca39b36f05d35", "MS1": "0aa23354c4fbc14f1fef61bf8f44bc891c560dfe83b22597f2046b0bba05b685", "CLIENT_SECRET": "04021232eab1da52667538d36ed619077e24c584e7752998c0fb508eb8364464f10cd00ecef2222e4c82dc82da0bd7ff0c582191ef95b2a21f68c23b077731f2c3"}, {"SS1": "16f703dc6c6076bc11827bf3c42d03eb5ecc4a90db859a49224111c2b646d8770cc2e88afc2c7c2d5dde46c14f926c61c29044948e430521947e0cfec235ac2307b8c2208f87adb1fcf8545e98a6955311467639f9868b18727b2f4cf26602cd0050572667864b921017bb585447a6bf3edf09474340f6c4610adc57d2d3067d", "SS2": "008da8157bc3c8eb2e69c38d51bd2a79dc45b0aa2cb616286ee32da39915771418e3d5270d086f1e22eeb0791a49f1ca9092f73e1f02a1901eeb52e3a841e6111f692af7a5ec3c86f949df7433520681426fb61392760f3c3fd6a05bc7e996a2232e443f06d9b15f65368dc320a6e82e608d51c550f4e7ced7de0b087849083a", "DATE": 16574, "PIN2": 8403, "PIN1": 8404, "SERVER_SECRET": "02ea26bc346bd3865ccc926df9cef998f8b3ea9d9a540b3a9ef20d648d426182162307f9e58e474cbbb5d7f0f09f75270240a1fa6fce450ace360563dd1427d618e86f197ad3591182c1c7c37b349d7a7d6570531a6558b2d0287a5faa9fac49127e0472bfa81220eb3e1d8bd4d496ebfe0e3fb7557e419b11e5c7e08ab6ced1", "SEC": "04189e7da45012fd8f786313d240f597b01ea15a133123dc4a03db44d0b6172470124e67c31199e8fe88e255261efab22ed1e34a91953811215ee01d5db1ac3b1b", "TP2": "0422ff150fabd29fc1555a313f46a3fb159a3e3347f7ac74e14e8163e146aa10430a8eca3b7ce355cff97fde163d6b12708beb71415beb32bef97379d590e0287a", "TP1": "04186ffd8ed0a0e22618dcaf8f7d6e76c07f40f6e354b06b866dce8db215a64fbd1f76055262e0e452ad584b9efc7560c68c7073dec637c5206ff07acccddf5e47", "CS1": "0412a4ab14063b4cbdd051df5dd0f4f5bf67e2b5d02b0ab916567402f51f5c266300c2c5ce71cfe79da1cc1cdffe19d13722380c183225eeff7935765960a5aade", "CS2": "040e8388fb2b4681ba6136276caf6c677eda346702c6dd4c8cdf89bb08eeb460571768e0c752953ec008f4c83dbc4c367f04a4b6dd7b65c6427eaf2bc7d3a71db5", "HASH_MPIN_ID_HEX": "7ae1d0021e60550764c1fd7e77b5618fcabf32dcf3e99be53fef94fe6315b9b3", "TIME_PERMIT": "041690555d23dbd80d8823d3cbfbd87f892920c9d0dd924db5d0e75d2f96e2784a083657dc05c02807c73dd4d82f5ade32dabd23c088d44593d2793d7f707bba9d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34355a222c2022757365724944223a20223339336237393137393061376230316434623061636238303264316366376333406365727469766f782e636f6d222c202273616c74223a202239653034323164356133373263623532227d", "TOKEN": "04051806d67eebb80fbfd0bb058980144063f718338e2fc1e1750b33ab0666e5a511abf65ecb993180fc2949529c61e9dde5194f76468eeb7afc47a07723947419", "U": "04083756bdf730238afb7379bdb0ce218b396d85023546e80e7425e0be15886a9a0ebfa182f8b52d3743609d8822efc194fc6ef2144549e99e33168973517081c8", "SERVER_OUTPUT": -19, "V": "0404b186718f88133019d30be9a8970b0295458a1402402179cd2b7af7acbfc98611610d0435c01569f53a101ba394e3174f21dc38c5238ebe7f9011de00ab7f65", "Y": "0e2ff05554b7a8594f1e1b0639ae792d1afa84ec74c5f800f53b2dc2a154d02f", "X": "08ad6b9d5e9917e08af08042534c5ccceafa212f1b182ca9fe7c428fba80405f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:45Z\", \"userID\": \"393b791790a7b01d4b0acb802d1cf7c3@certivox.com\", \"salt\": \"9e0421d5a372cb52\"}", "test_no": 128, "UT": "0404366199857bd40002037a4e55048f4ba565e7031bdc466268cbe5379f96d0461bd7e4fe6152cd35c58f2b995c650783162ca478716e134e01e6e5c6fc51b44b", "MS2": "1c0e278b1559288c0d7f7ee481be5d596fb1a001604eaaa4409053d06f2f67ca", "MS1": "090d1a32ec62ee6e513972a6604c2dc4dbe998516f1f5001b4ef673061c649fb", "CLIENT_SECRET": "040bd0b880deee0fed3715f020ffa58462a97d911992917cc7c3a1380b796284ab0f17a9bb16d39d6365a513e27b78b2a0167efa51a6640176b9f745386d25b1aa"}, {"SS1": "1cad25d2d71ece7d58465ab066dacf3100f9179e1b9cc78197efa8f893bd54292181b00fe884fe35f687d425bb669839e0fb0fcbe6d4346cbb48497f1dd7f9311d107cde4d1f788c0bb47c5fc7d3976eed0c0ae2dd081d51ba51c7c64af5099904a6027548f33ebbf35193e36088ad894985beed6ca3dd94e2f5a7a4261aa88b", "SS2": "17f4c4a9435b443ffbf24df3c976e20ef4069caa27fab11954e3473e0dcc8e361fb7b6b6d59d5436d059ff96d6dd2e98c6134059b7c85749ad2c92810d47806d1d9795c59be2ca05d5d10d20b0df39f64aab69776ae3914533e81596d2da5c8a1c0785d9e7d7862f18776dac4ff6adbe20feced3438c2858ada604c99f5460fe", "DATE": 16574, "PIN2": 5417, "PIN1": 5418, "SERVER_SECRET": "17d05af27ac4b104fb1e8583e8de78dd4679ce4fbcdc8ed7a6f9402595ec0f450698ecbe823c69f95c719e4ab1926e77c673af1a509dfa28c70a57d7ca21539e150d93fa78a85934469f938d6b9bc574ba9106b35c7263dc8fceaf4751b9007f1c91e381f6f6c4ab5dbb79f90f8326ec048d39a224deb597e76a8c1bbbe07a35", "SEC": "0403bd7e7e7a020f4f0f97b8a69b9f68d66290eccaa2f41d799fcd896b0ae864ae1764b714c2bdd77641cabe66b0a36a0b1e6c6b998fcc7c1fe0f78343d1e4a9c7", "TP2": "04089b70ecbf17a15c943e98c43085df90af47b4c85f62b83fb15cc912244ff93d02977149e7ea57a02b2e070fa799a093d92aad20c804350df2321327bcd0a0f1", "TP1": "0418b2a1a9302583f636828611dca6d85628f3672df3ed65f3c01f7a2639c51b9a1e34ec654901f43122c1d6ea009c32bc058469df5357e5e1021ea658dc2fee05", "CS1": "041bb09d7030e0fea3c633f5419e2ff84bcd5f1477ed8e56b89b68bd1ab7db1fcc024a3690525cec58e9e958304ae74d7ef0162a72e094e44f20edba6a194c34e1", "CS2": "040aa8ce959c0e846d85f89e46d8fe7f7b87c12b5845ec31e69387c4159d4dad0c11db5eb5a909a435013e6df38fcde951369536688389da31d3e28da89e09a49c", "HASH_MPIN_ID_HEX": "b9afe755cbf7753583bcbee03b75457e9a58efe3826b5c8956a0df9d1ffcd319", "TIME_PERMIT": "04065af2b0c88a6a4441c2a25ea8f4f6ec52e80adf7924f48956a9216bc026688a0169d36c344ec0887a201b1967d2525ae8c49bb5ead52404b4af827509102f61", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34355a222c2022757365724944223a20226430663135306336666665633634616239363134313463376264313064613665406365727469766f782e636f6d222c202273616c74223a202233383139343862376261626238373337227d", "TOKEN": "041a6345be5cb453de4353dee95fd9169bc13bb39f8d6406df47f1a7da34bf4ffe06434e74adffc15e9eee9c338318c26427778b598ed4fa82f31d5da53047c251", "U": "04043e581a39e8148c7af36e1d99dfc44d8de5ec20b596103603c745ca052a74901ae166b18909354017357888bddb426b8a7f4330d6776aa1fba0b6202080f0b5", "SERVER_OUTPUT": -19, "V": "0418a1d0ca29130649efcb197d284b347a5f26b935c798878f3170cc887f7cb6580b2965432ddfd569c695631890ce8eba4bc1fcb68333364b61b11d3d7f09dc07", "Y": "0ef424593e089c8b9d8fbed4d42bbe6f6a393bd3c05c44e53d9001b9a985bdfb", "X": "2369afbfffdef218bbaa68395c6d9e84511c72738064aabf0318f4540a3624b2", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:45Z\", \"userID\": \"d0f150c6ffec64ab961414c7bd10da6e@certivox.com\", \"salt\": \"381948b7babb8737\"}", "test_no": 129, "UT": "0401e81a50ec8635a010144e9fe3be6e7298d582d3fbb83c87588b0fad7ca1579914e97f8da189723d7015d800bd3c65043fd6f48e7cbcc30a4df428d6961342d0", "MS2": "0466a5f6fb9619b7dc2fa6b36a08731fb15884352b0c623dae84703677ac8fae", "MS1": "1a76ae2dad031a38e522c0b866c131445056cfde47a5e0d04181877e0cb4f52d", "CLIENT_SECRET": "040761c0aaccfad1c4c3ff39f62c8a9da993d49ed08d27465dc3882dc52c6b77a00e098b5d5f2acfa8053364bcfc0861b4ec69ef6349e64894a787c9c1ab1db85c"}, {"SS1": "22c564ab1092e7ea5645dfc677b9e3638fded92f6cd9a0af44dd0efa66a5674c13c73f4ac748b4301db19310a571512213d378c29913196d7592ea61302c4041055da40560689199128c82ed984c60d2c226ece53217a63e03158c06a12f84942285fac166b488929dd9260ca26d05942caaeb12473c20d42ab93c58fe5a46a0", "SS2": "1fa99c4f208dab85209323f9bc14dc725562d6533e0356236aefeb6ec5285dca1a1e899959105a671b5a563fdb8d43207c4b578f3082b6fc614169416b9be5c60d56235144686f2820499ec61c5a964eb8a306265cc944af132c21a5bd45f62c1abe38ca3aec1860a325b82bd4d1e35217a3ecb26eff90245305ee1eb79f8fe8", "DATE": 16574, "PIN2": 508, "PIN1": 509, "SERVER_SECRET": "1bb7b13e5e9ea11a78be76b51036be88552ff27b1a1069fc56e0119dbedd6cbb1214640d43abdcc4f3fb4b619c0017d4a423702b7490c0ea819342eb04c5185a01b8823e7e03229362100f5ee26f28e369957ca0008f9a6328318f596197551c181e367f36aaf63ece8d4cb754a5b51abe208a3ae3b32ab961d0c5331ca23257", "SEC": "041a2ff9802a9b9b8eef37058a891a459304fbd1fccf75f374389f3ed32b3b8e941d992fbcfac4b463dbf595232dfeff299f95b0b004628d0db3c30891b815257f", "TP2": "040c25f56b6fbbf83b45c27e1f3157848077d5608f18998ba443cdafb106bf4d9f00f0af0e732686084d39630be70ffe467757dbcf0add7dc349a2bdef438cc87e", "TP1": "04114cc669fc7cdd5a50d548cf1d95c6f09588f68a230156a1c92c181497fd1313093c1756941b141a02a4316fee9704e105d49ff12cd29f8ba925a08286d53e0f", "CS1": "04099da77a86533641520319a709b846b33729708a8ec4f9445800e866349eb4711135b7099d00ae69572a8233ab9279856453b7bb9563d9c4a29ca4439d1d716d", "CS2": "041e48a2cf74f8dfd4ead52e1da1bdd962819621a00be605bcda9ab494d3320c36126cd950d43188d5dee619afc1310bffb319a568c80441ad432d21958b97791a", "HASH_MPIN_ID_HEX": "c829e7065ca50afdee1ccbdba1c4ca16ba1223bc422171fdb4d03a9860a191ec", "TIME_PERMIT": "040aa869b0d6af4c0fc6661ed3a5c60c626da31a62abe41bf31d71ef9705f7fdef1534b7b8af5d1c680e4ac76a7d33354541324c4b22bfd525e567be27842a34cc", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34355a222c2022757365724944223a20223161353138666437636661656163393265303032316563653330626130386633406365727469766f782e636f6d222c202273616c74223a202237313630373463323435633865376261227d", "TOKEN": "041a83242c7317d6b06bbc8234bbe938d666c0e58242da1bc8e92e04648e0ccd6f1f4cdb280b3df8e49c148f4f7d24e00fef9f76dd8333b1ee6c8d0334abff3893", "U": "040d567fe59c7cead14448d4caa48e02fa323b03f70c78be6b78a41d55eea019290a3e610c059ea5b5c7452cfb1a7c738ac6b6937f7f71d05dcebf87ff514a675d", "SERVER_OUTPUT": -19, "V": "041d025ad9bfe24d5a45f14e40bd4b76acfd6b0206ec5b3c8a854a5d9ee2c66dfd02b7612385a3ac25afc3db822a2f0afb8bcfb3bf64af9ed50b1835a20ef96574", "Y": "0372f5236f234fb253dff8ab8af813fa05704e86c17bf75ed405ba7152d80f91", "X": "1a57cd4a32fb93013b2fe947c99343582590a93c7088eebd68df5cf92c7026c2", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:45Z\", \"userID\": \"1a518fd7cfaeac92e0021ece30ba08f3@certivox.com\", \"salt\": \"716074c245c8e7ba\"}", "test_no": 130, "UT": "041b02fba115b58ba2c227321600356a26da7078ba9c4c6c8f834d568c0d31fdc00fdbda5a7a95089b0d3d5cb391e44d6bac87137c54c7ad53ca43617388549acc", "MS2": "046aef08acab2f0f67ac419af77bfeeb0525420b935797083857878677ad9d88", "MS1": "1ce1f8ad6cedd688b485d06c6b7970d2fe42877af5a573fc5cf39f257c0b0e68", "CLIENT_SECRET": "040ca13f3fcf949d96701e1b0a70da07eb57cfa836c81a4b16b4da1ac9a45b4d581a81b9e48cb9b30b6dd977e0ca70e70770209f0244c18b48d68f9019f0ca8c93"}, {"SS1": "039edc06feea6adf26308183a48ae8b98107be8ac0e42f7f17c7103263f59d8b1294c97f7a0a80601ff5ceda68c9c14dc39b737c739d9cae45998d1d333ad4bf147369fb229a5438ad072d3b56f2b4a8dc0388fca57dfad36e700e1e90a6fe0d15c28e38a6fd8d9b34c3261d53c0bc54619e57878b39125c1cd2de99510ada5a", "SS2": "112f20a8f9501f7d228e36dfde55d48b60fae6aac3180202c71fb13cddd1bea608e4698ab086b610cf60b49cc9738221385f3c1f4fde8f4cda414b60f07bbee00921574baebd96cac466fc6095f8553405d4b19c9fad2aab9493df5f0aa55bc61bd83ab5d60bedbce62ce597501676b22d45373412ee0af46ba0ecbb3bbf4cde", "DATE": 16574, "PIN2": 2104, "PIN1": 2105, "SERVER_SECRET": "08efd5fa5f0741a114c1f17d54b82747a0324fddf0110cd6171d4a134fefc91e0976444d2dadde6e3bc5d0384998c8f1a0b7f4b3a5004964fe632a6204bfcd9d10d4c76edb1464706e3463547cb90920d2111ea3c1c016edd82d249f85ef99a418197f45daaf65ca15fd0b3fafe1862cc3cc988fc9ca0a41a7c72cf4d5c06b92", "SEC": "041084f101a2e3260fd22951fd1a9a6b335c1a36776ff848ba1e4bdefa90ff8bb40c8fdaf342c1fd76b9cda865c67464d5657134fe4e1cd596b81c283abec44f96", "TP2": "040bdee0492da1e84e96ed494a19a39c48eba3580263a53fd497318b2f7e16e751098b89609d91a9256e2b06de05277c0e8e951a13a9b7b1a72696eac006b27aba", "TP1": "04051bc56ae2c46ccd639053710b2ca028814902f76d7d84c3ecc44cf72aa782cd1f562cbe29f792a05491f948ef7be3dd355bbf37b46136ad818dc406cde915f6", "CS1": "040b489ef773a645463404c82d5218a5e7b3fed9eb25ab237334b4eb337572fb5b232025e21c9ca7ac67d635cf0f26d71004ac82785d2cfa57a17ff56390bd02a4", "CS2": "0413c587b5dfd3a40625388c1c5e31281f17d972e6a7f4a5fe12522eb8b3e41ca7047fe6cc51ed7421e706bf571396c21e2154a25117fc500d229926a9255e9e93", "HASH_MPIN_ID_HEX": "ea28280697431bfab50d9da240d1c3f890ca67ce866e0274bf08e3226e00ddbf", "TIME_PERMIT": "0405de7dc5116d4bf52e184f4e702074ea6119355bf2a80900317713eeda628e591f2d2ff29e0171060a0a482984c694694d0db9c32c7251c266b1274b37faddc9", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34355a222c2022757365724944223a20223466386665396434613335316263306365363036663537303434333032313036406365727469766f782e636f6d222c202273616c74223a202262353731666262323462623465313138227d", "TOKEN": "04093414fd088afb967c4e816a1528080d3bde110f96b2e9d8baebf4fbd95e6a670de3971db1490ca66cc2d13088f71c9154febaf1669db5c299e57b97b1c1040c", "U": "04106bdbd620ffadc84c4a82880244e6e91b9abd45a166eb4806ec601fd7f7560e1ab9e9fd9d527de9e418776ab2c68731f62d8ee9c18fe6f853fab2571b56637a", "SERVER_OUTPUT": -19, "V": "04107c3ec836594963132f49ce3c1e5f2fda3e2b4096982e7007ad2f944d133d5917e2c8d66b5907514bf9c7c1fb28d72c50ab3697ae02fe495d8c9c68b5ee7737", "Y": "0234b71d4b5e344296d12b99fb1f176dbdaa3f337af1ccd85234a127284d9f59", "X": "169290eca41a623bc19c53f136e42f74ed557f41df3148f66685f630bb75d135", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:45Z\", \"userID\": \"4f8fe9d4a351bc0ce606f57044302106@certivox.com\", \"salt\": \"b571fbb24bb4e118\"}", "test_no": 131, "UT": "040d2c308372cf1fba0f731120b7f2549402c0fb38e63dbcbbc5cc1d20d06fbbf40952ae7f21e520dd1848b4724244a8793c365b5da1f31d9b1e7b8931276ace5f", "MS2": "1eefbbea9a72c328e3a540608434a1a5341c1b74876fd6bb5b919200d5cf775a", "MS1": "03c27dfad89e53ac8a4e8e6d2be4b499513e7583bc80a7701f62cf0ff5ecf54c", "CLIENT_SECRET": "041c4037f00a487f46e53db7c6807a313148cfdf8433a1bcda67f1bc7e641a8a0c225a9befa1483d4ebcceb301870a16904f30e663a8ff198cb6de7490f02bca8f"}, {"SS1": "04f93356e8c5c55c08cb1e942edbf2ebf49c398ef5592b4b442899ef02ae10c421a872f0593e4d150d5f2a57d7d84dcd7d85cded858c1977e65d737c378ec4c6170731b8d5098e40fd0376902538524a02c6261b79a3149288c1908d1e2b17da1fa8218b7e2f6bd1f7a291d217960016f9c3f53cf14dd6b9b1f6618ee83618d2", "SS2": "1076791938ac7aec0fa24bcdecd6fb71b672260abae3760cc03e711baea2fe92143f8f2be497a5b488ed2d6260909361121b2e365bf376fb52d54e80d78e69ef1cba693e40fa54b8af2b411b8958f95e1098c109e478135917da9bd46f70208f1513cb5c4ffcf9b2898681348aacd66598b40502212f377ba866605f1698832d", "DATE": 16574, "PIN2": 2145, "PIN1": 2146, "SERVER_SECRET": "14de76f13823f0b97de97a0e7a3ef70f089ae2f49f5ca1d6b06dd5c6f5997e021506bbf85f9e5d0001c7a7e7c79f40719211b862798ec1b9b8cce72c16fa79e119b192b04da7f43d5b02e225c0d887164efe133215120cefe193b52fd8806a69171b58ac5d054cae854d66ee42371c1a38726efc88b5a5467a698b244de945fa", "SEC": "041cfcb970003a16f877db486f5a97c865f126d12dbd0fd0547a69427670838d1917103af0014324c2bca24ac8f63e42ce720854f1209aa528db4dc49d547abe83", "TP2": "040ab734001fb75b0ac5c3b19ef4b1f129e6b4a98e6cf0e2700d64e8a8f9f1853808597cf60a0e48b18da122fa4ad1fed8eedea49247e59353820f37377de4bdc3", "TP1": "041ff4448d56d791fe8c4ea46f5a44e926f240f8a0ae5715071112bebf59ac759600fe0586ca516b569f2cbe194f965f846f0b8b51d9a652e9104f5a92c522281a", "CS1": "04218a2074d82764d39e428ca0da5b69a3e60f7a26780fef7741481895b5e8ba47010157a50a27b08d56456c7d2d6c691470958c503b5f96954b459311c2602d41", "CS2": "0408717e9abbcab3f0d61a9f05e97722003f8e727a7c45be15c519b7226b8758c400f4ca56b581df813e71f68e33add032d85f4b55a1382e96e091519f0f717188", "HASH_MPIN_ID_HEX": "b06bcfb08b73bf2cc9cccea44cd93e96b4c2b6c9799def276f4d5cd8924e3d81", "TIME_PERMIT": "041ac5a01d6f2b21ed51eb014c2a327c8615bd2be6d8ff94e5303541bd176844680c1b062d745b288f59c3d92b02664d31ce5685e4d63bd728c82efdbb1af65e23", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34355a222c2022757365724944223a20223633613465666662396230636164613166623035656264363330353031623462406365727469766f782e636f6d222c202273616c74223a202239393831333438616137386538636136227d", "TOKEN": "0420e8b28f38563cc3203145ae3fc3867a544fdc49234d81f7ec180adcfb702e62170a75b0b0d1cd33396dfb2c70bedba3ef8fe3046cf700639344a3d10d00b63d", "U": "04123a17cb9e672d4163ba0480e42fcf00a581fd64c35c6af36c4d9a4d05d1b2d50979e1c9f331a6ac9e584b9a98979611b7d544f6975ed44a2af17c5a285c0726", "SERVER_OUTPUT": -19, "V": "041d216f5424ac27e93af8cb630cbfaa183d33ae94a26e82a1b62d08bf7a6d713806d83f2be2946c93f528f20742c5d6f180a5e21ac529c5de5c2d68ba24327ec5", "Y": "1061f6b2ccab251b0c4c4eade84226fb8eba098213307c0787b8b2db14b95c0e", "X": "1ff232dd1f691c320b6bc178e564668d5eed1db00ad65faf688fc44f84632b74", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:45Z\", \"userID\": \"63a4effb9b0cada1fb05ebd630501b4b@certivox.com\", \"salt\": \"9981348aa78e8ca6\"}", "test_no": 132, "UT": "040fde13f50934b68415912d279252b1bf355ab2dacb3545610a32c881f42d52851ba1af38f82a37db98bcc4c661464407f2a57017d6590480a9dd725e2d3a3f2b", "MS2": "21d65011effea424482a794ad0cefaf72e1e3b35c1e266200d4457c340ec9854", "MS1": "02b026ffa463c2fd4cbb11ab86623d89dbbbebab5977e11e1d2e95267f9d1b15", "CLIENT_SECRET": "041741228ff0b7eee93de64f07ea289cb77cb3ecf233d474b3fb7c9eab49f01d6d1c172cafa8662602523ccdb6c705fd60b05c79d6cef2cd403e5fee73c111b7b4"}, {"SS1": "0e11cdedd036b09bf718010d66cb73d2f9c7c2dfe4c8f975ae7a45c4cba093740866110d091953cb443d1eca8fe73a0685df114de33e280407e19fb024a18f9602dcf593867538419abdf9b74cb4537945050261204e7cd9533c33f80c97d31401b3e935cb75d5eec02bdb5c9bfbb19b4e26d1a192196a8352599398927d5e72", "SS2": "23c016151afea97981a8c8f26c84c39b344a18f0fb6142318f42ef6aea162374089eed6014a9e6995e8bf381dfb03a2b1c0d3e231539107a336dcc9411528d8d15d06a87d307393d387945b607aa897fd268962a8e7cdd649d020f33015576070ba7b817d4e4baf5f9dde8fd46290771a8b77db75c773a5b353ff770ea823958", "DATE": 16574, "PIN2": 17, "PIN1": 18, "SERVER_SECRET": "04b148cceaec38e853191f81cd868e4a8c0b99c3a1f51f3e2d6ef017617d668512530f86ca47ae1cd2305d6a0ce5e7bd114cad78aa6a5bb9e3acfac2a065840e185a402acd4426a3c00f6528e6b3afc57041693e65f0403b3a86e702ea1597cb1316494ef083b564e6189b3ff1fe38d5efed4d122d47ec55d6bb465acad4db89", "SEC": "041e60d95ec5e713ced0fb1981beafeb420bf02fef706fa1d659eddb370fa2d10f12fb6c506bb1158fa377abc4f0b88c8cf603fc389468847def1ce4ff722ebf4c", "TP2": "04116c2b9490d61135e586e153d034dfd148a7f14f620e34f46e808e2aa1587c5b1fb00a137292b890f8c2a7c4f3d2b8dfee516b2b453e3825f4d4b6573e9d8872", "TP1": "040810a63ad2f215fc631e20c465ac293a91862e68a4aff1c10c867179b34cd4311549fd9d7412fc23083b74b80c18197009905c20a110cca004766a9588b80999", "CS1": "04053f7266694e068765997032b260b4d0effaf72e7f99a44244931ea72e8db85b00dd8f2d33bafe84dca94081872d2b1c9298e600ecb950afe90746877d4db371", "CS2": "0407c55dc713cfb3b61cd75075c95252409ace2b566ab3af83c29820b13259d5a10cfc0e10b8160900a2cd25ab0d72a549bec4de1f205830e602e35613e39ce843", "HASH_MPIN_ID_HEX": "6894a098c98db36a6bbb3b7926209809b153788260b953ea0a9296567f7c9531", "TIME_PERMIT": "041ab9d1acf6fc0a3e76e9d5114a6068d491667298fe3eb325670ab09add781630211c4e19be27f07e25e4b3cd5d21a9722b3033b3c6bd93769e32296bb064f718", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34365a222c2022757365724944223a20223663373464383035316633646533623163626265636265353032366162363263406365727469766f782e636f6d222c202273616c74223a202235396132363361343866303530653532227d", "TOKEN": "0423dcc36076f36fcc8a5ea63fe046c0fe72213c76050227bba727bc6938513c1708673ad112034669ae15615f18ae27a13ad547b963199d91c6e63fe553fbda5b", "U": "0403b6fd51bd1ae04eeba8a109bb1f1ae249bdcd16bc7d78b1ab06ee82ab13d2f709edea7b4615e9c417796063b28e0c6a8345234f1f6b43b1641689f2b9ea90c0", "SERVER_OUTPUT": -19, "V": "041f49d28345236fb9ab5abeb06dc9e362029fe750d23ccaccebfc2ba2eea4209a028c1be60499620ca2ca904f004a1f11f2444e404b6b7b6d0408b8a0ed218e19", "Y": "006115e35cd43c2aa696c0ae4a73e46b320a1b34cba3132b6be5dc06c309f986", "X": "09e1e7050cce7229a2a343bd27d3e09df585ebc3a4c1c10cfdb4c462ea4d43b8", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:46Z\", \"userID\": \"6c74d8051f3de3b1cbbecbe5026ab62c@certivox.com\", \"salt\": \"59a263a48f050e52\"}", "test_no": 133, "UT": "04131fa8b234139a89d9be79f42951e8d3519541da5350fd7414cfb6e992a91b5214fd928a6bc7112021fea3fbc0ec3b8efb4466c8e1c6a071ab5e9f860c03e33d", "MS2": "0b787b71c88ec697c8baaa0f280b62550b546219f9c83bc9114edd61a83dee95", "MS1": "229fe54bd9e0dfd480ad1cfcb3ac8dea62ce2aeb20188c6a771954cea2f0953f", "CLIENT_SECRET": "040edc5e222de3617f4a3c555feabbd5791fa3d9b3f9739c440bac076499b689be154f15c14775766261ec834def4de4a2cafeb15c0fb5faaafa5da45f848ab9be"}, {"SS1": "0122ea93789dd8f0f432629c35eecdbeac3089938348ed475c5cba136298fa5e1b571cec6d8c081c414331460399a8dedb9b314dd7d8eec105d44ce9ab57bf751ed7c59fbc2a9fb3ef6373f6be003e5c44aaf96ba0310343cfaf0f9647fe505a1dbe2e8019580dfa7ea401e4e803fab2a8e9021eeec220b69ba489e256a8c4f7", "SS2": "21f9bb9f552fff1e2b174edf3e1a7eaffcd5c4cdc96ae7a1d4f639f8db4380991565081cb45d66c84ea2f49ce5a61bfd5d0a0678e71f31ba4f74987c58a4762c1ca32bf10236053777eff533ce9e3b13f7db2d57f10beb73d63389e151a6b3ca1639b8dc8654c4e5efd3707b0e3ee24dee80ea6bedb0dec6dc6de400cc217299", "DATE": 16574, "PIN2": 8292, "PIN1": 8293, "SERVER_SECRET": "0971eba0f2e9c325e0952920aaa0963f96c834e3da4e96d9cd063a89cab4c38f068fae5899433caa14e6ca05796ad41013b86eb067a02fcd400ca118427509e00169c77e1f8b4034bb790cc2f23c2847e9c8693c239d64acc7d20817821d263a1df1c3f4297b88fbe5011b9eeb45a4cbc3c7a59013fbefe522e680647f1ef8d1", "SEC": "041d35b090e6e48bfd3fc57222e2e55aee91abfef61dd3a4cabb02396d84f9a39103b6c34cff64a07776e27f05d7fb87bb7a87f63342d11e942f564c201677a2e5", "TP2": "040a6d571e32883906bdf7d07cea5f7ed75ce5d2b2a1f49083d37ff0065faf4f851b78a4b06918c6ec8f628b542ea64bf10955b7d6c302db9383078497db43eef3", "TP1": "04192087a7bc5e5551b882c3845be46329ce884660b03ea990f726938b54fbbcf81bb6930f24b89cdd1ada65ac7446a66f84812ea156282a2ea1bc840ecaeba0c3", "CS1": "040e2f5f9c44b0831a70ca34ddbf2309c326d0dd39868f196865e43e401fde92ee0e1ed9047d97222285e7256c72e0ead2e490131fb004ca39086b4518258d87f8", "CS2": "0411161dea6b654550ff19b1954ae3f373d7a835d837107b35551a193870e464fd22dcaa23f3b7326595034989ce82977b269a739c1c6af1b309ea5bbe9282e053", "HASH_MPIN_ID_HEX": "d343fc2a17968dfd5414611285cb311a5295f3ceb74d669a58c6bc353b3e22c6", "TIME_PERMIT": "040c5ac04debd0ac72f8bc9e8ad78323d13a7497beabedd0ed36ba39fe4fc507821cba83105a79c68d5ae48c3b476816fb6fea2e19b8de53c69403b60f6b1b8f94", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34365a222c2022757365724944223a20223030363637376630393732633730343264333330306632303332653062626336406365727469766f782e636f6d222c202273616c74223a202235313763333438653065663263393466227d", "TOKEN": "04093a81bcaf89c67768d9dbca694130478ff18cf5908d57e140d1255ebe2d3e6d034ee0ccddabdde6c1d0e4f51706bf36e81f800448b1ee318ee9164830778a98", "U": "0421074255b056f3f2fd076f4d53eeccd1d51396e849852c6e033055d8cf56fabf220d4114d5d00930db868e2cf4137eb296408205e4ade1839b9d9e8028eb7392", "SERVER_OUTPUT": -19, "V": "04018319394d0f51634048992f613ded2e377fe0351091489a66411bcf59bbf6050f4bba21e37d3bd4f5e2c3fd7b19f3971a25bd70adfa0404a8a95e62cdc8280a", "Y": "0697d2ed5539baf317d6c676cad62eebf20fb1fda7708222fb40f25d42753eb8", "X": "10ff7ea68137f97b370d6b1242362b0820c04fcec01215388668ce18611d031e", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:46Z\", \"userID\": \"006677f0972c7042d3300f2032e0bbc6@certivox.com\", \"salt\": \"517c348e0ef2c94f\"}", "test_no": 134, "UT": "0416ca9c5e872291af05f8a71bde0bd23e1063243124c709a6f589b118d0dc36e00711312b299b580ff0ad0c08f02e3b44c954bab9401a9585eaf6c274312f26d9", "MS2": "0f143323574162f03c24a64684895b26d92548a264d2a42c503928ca0e0b8a7f", "MS1": "106874d80282c0396be240d8928c4575dda14965ec7f7ab545beefd75d1cda6b", "CLIENT_SECRET": "0411fb8dfb56087595df15611450b0d4fc93d0a423474d83dbb374f49f279d700e11c0be884b7f3bf4dba86546b05aebf5f6585f1507b8e9ab25c18960dd6614b5"}, {"SS1": "065790d9b133992b98c711f5f27f139a59284a3b0a66219f96ce55a44c10460c23ed750721bd9b804a80c81ebb0867911ae4456b34474337585fbd0488cda486216af46817181fe46ac4f1705c04fc94cad9ce222bef9379b7d1a14a39a4baba08e4ee99dc78fe667218a5e037ccceea506cd289026a5a7daf803ec5b31bb38d", "SS2": "16ede5a298b0522dafe590bb8b6421b888657616c91530dac674143eb025a0710e0f34d2e825664cb4cdf5f7e39509527cb156fde1ceb9d6da4af80d21413b6b17c2b807004eb28b04c37f2adaee340030a04648740600e767cc8782b0faf94f02d13836f1515af6fd30fdc22da2ec99d5400ab0defec11ef47edf95ff645de5", "DATE": 16574, "PIN2": 8119, "PIN1": 8120, "SERVER_SECRET": "16cd74e2f1498ce36fded71f22d010df184ea841250cd93e200f620434281d440ee30e44cf37f6abe82443f6b4d11bf63ba46dc452ddda6ef81ef6552f68e74b00d9fbbf2c5508d7aac965666d96455f84c40ab843e606783e95b5b70f4acaff118d7d170b9f1b3d6a4e6b121874cebace757294522ad4b00c3fe303d2f3a81c", "SEC": "041b0c85056c055b375fc39218ba72965650b5432e3cc995d8037aea6f6564defd1545f40d8631de70b0ae0d65b124a47fbe22cab389607ab1695a20e820636b68", "TP2": "04108e79442fee0232dac1e39cb75e95aef5e1d94988e4acc7913550a8b4b175a90f57e180c850d7599130d7cd70c055f02967ec32149f07b7ef05c71ea4dabb1f", "TP1": "0413f37c746916b8d034154b596679d5195587467cc01664ceff88318b0cab79a602c01492af1dbaacb85ddf1aa91859b0dce7e6ddca908776801c6135205f3749", "CS1": "041696f910d20c542e29d5ae329b92070dbf723680b6649f21cb96056d6d57236a126aea9fc8f9d1dd3e4366f7e68549c65be59e97485dc5438d366c1b254602d5", "CS2": "0413956a78969b514d4ae1d268a365d3fdfc2d38eb10993e4acf4c33cc8030d88a00bf98f6394a9bd66e00c54443e5036726ea2c522b89d1cd8c7bbe6a8eaa5873", "HASH_MPIN_ID_HEX": "26d6172e2d03f37174cdf8ef466797590f1017638e968fcbcf6d0810e611fdee", "TIME_PERMIT": "0402cd6ee2e01e4c649f4e2ce16d6eb922732449c6094390a19255030fb5f5dea00128f0782aac9bca033c32781d5f2d09c9c4cc475578677f5e2c4a928ffe4a42", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34365a222c2022757365724944223a20226561393561343861343930343530623635326632663662363765386634313831406365727469766f782e636f6d222c202273616c74223a202239373538663433396433353831633565227d", "TOKEN": "04146921f265eea1806803cd4f335b15647a71e2a0fd2fe384ee97d5cd570ca4990a7c7b816111114457fcf10a2041e766e6890a8e1ead936ded20c941fbfd8cab", "U": "04089609f78604ee57c37cfdf733b53d504f50d730e7bddb7059dbd04dadade0a511605754468b9e4293589fde58e03022df7c36565db39c53ad8ec13d349f08f3", "SERVER_OUTPUT": -19, "V": "0405fdb03bdd3754a310192cd37d82a7cd4920be500dc69fd4f7ccdf581b311d2a0e8f941de2e962f0c71bc451899f40c88898adaa87138bc50223b336c0e48015", "Y": "06d79d0f1127745d94a68f872111917d47d6d9a29d4d9b0a9b706d54678cf328", "X": "0f6c7c8ff6d46f8783ac213f5438c02071ab05f0e7c800166491898008efc195", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:46Z\", \"userID\": \"ea95a48a490450b652f2f6b67e8f4181@certivox.com\", \"salt\": \"9758f439d3581c5e\"}", "test_no": 135, "UT": "04110d2f16c338934c8fabe90d3b43938dfde14cc794fad400fff0893101cb6e4f182fd20933e2b84b0f2778c27b2587ec72ad64e4eca8be086206f2523d3c1f24", "MS2": "15084e65fc0793c212d2d3678a6dc2e5fb3b0741fe765693e76f88a977ffbdf9", "MS1": "080c0d6f9b9c01f31f0fa084015ed5e6e563035ad0f636d464b8d441de8d267e", "CLIENT_SECRET": "04029fe9a24ac5bc930bfedbd059e5fdd1c6a39a36a5a05cafe2fd5401b62031e0205059f83980b11bdb229be260cc465e804d2f2c756b00f16f0470a5ac1dd48a"}, {"SS1": "20ec756f7bc8eb39a9f61cdc4ec9384423f0467def9c41714b451bb9dac60004187539ab03465a01f98ecebe56877bf476fd4b6770727d1bf8a5c9590b0bffdf0f2dc811817738291bdde5e2442f246225812a72e975e96ea1d3335279db88c410251fb47e6f7c7966b3183ae35ec02199d448c2fc50a4352465d3e6e7277204", "SS2": "019aa6ba0d517e8bd4ec2c039ef632bc5fc55d82e50168d561b2cbfdfde3a87c039e128595c10c28eb39a729e747f97607da50b332b550a84d9d9bb5c0b17bd0091e78f518c8435a9d1fb687cebebe3f8f9c8ddd39e7506490da4d0a096f413520b050bd59394abe3490a9463c718f191948031706d044c5aa33679c82f49e00", "DATE": 16574, "PIN2": 5235, "PIN1": 5236, "SERVER_SECRET": "04a402e80a88105f6a0edb8c4d97c85751699cde9ac30220070b345066acd1250487bcda2854a57a44d6e55cc7381e9ccd4f32fdbaf61a2401b27d464d94e7731596684e409b77b10e2e023178cc7037660bf6c9f1b3994ba6e768f83884622c032c01d1762b39441fb54920d95f2295cdd6e242ca165bc9323b0b87fdcb7a62", "SEC": "0415b5a45bd5021bab23eff41890b1928009c42520e66905cccc1f874869947e091183ce60a32e62816b595bbd55b0376dd0392ed7a43032e5e2ff30d928ff0bb7", "TP2": "040a78f96b42b98c89e2ef3eeb0ce463fe51ca4867386260e6c3d04b18331d13c710f1f5b3f55a2dffb6614f3a87db05bfa657a92a7ec4e8a0d7ac68c17267f2a2", "TP1": "0409abe0e32b3a91a0d794f16e9df87d02da1fea9d72f82bd05529229b22052f75186b5f6c42963270ae3969e43bb913dd12f6faa0dc35fe8c4b9a4e9896f7595e", "CS1": "04027d39b638f51a9b6a75631a27bada47033454d02519edee73f3fae7d0f08eb41e45b6e495f8036edb58c1ab1551f007caa158565346c16162da560f70ee5478", "CS2": "041f3adffa382799d0c3d757303a4b54dc7c183bfa96cc3c5624bd35c50004239e109ef1e9e4358c2afeb7c5a951ed360e1f6fe3a76885eb34e7522571dcf6e16f", "HASH_MPIN_ID_HEX": "dbbbb1822e1733e33e54e29d5b935e43badf36fd5ea2020077fdaa38eef263be", "TIME_PERMIT": "041578cc6b3022ca69638d4bc475935e717a5df31f35d27b4e4033173f5d5516a917f97d9921d1df2947964dced8aa64a31b2c27588f76bf3cc363db2eddd2fc79", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34365a222c2022757365724944223a20223735383965633631313066663938386138386234313537623863646165636331406365727469766f782e636f6d222c202273616c74223a202237313061636165373366313162303963227d", "TOKEN": "0402e007103748977cf1838c5efd5465752f8cc4a7f448b237542c155bfcc9d11f21b43e84bb88ddbcd4c854d5481517ae4920bdba58cdd75fe83f8ce46f70dd4d", "U": "0405ed1077ec4698b2819c499512abb76239235fef721250027d7814ab287154f01c3ea68decff56d012ec2c16bed33069954e651ccc369af88c7859bccee46667", "SERVER_OUTPUT": -19, "V": "040825298be7f237f5a99a6a9d92466598da49819f38113a59afa6923d8ae54f6e0d1c564045cceb62c50a3751faf0067e07917dd80edae77639d04208b480cb23", "Y": "0e9ed0f06d412a17e0a91d5f1c68d24d58a137f202e3de7cdaf72e4d587ad6ba", "X": "1546c98b8d019b94dc4d9498caff4c357ced5a9c2f23b7eb8ddb90b991c842af", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:46Z\", \"userID\": \"7589ec6110ff988a88b4157b8cdaecc1@certivox.com\", \"salt\": \"710acae73f11b09c\"}", "test_no": 136, "UT": "0413b86128cb1a8aedae68a62f66c4ed05039021f5273081968f988b2c8e8232880bb5326e425e2ebe020289a5f9d5d3480bccd1d57b3631dd1de77a6794be5cb7", "MS2": "0e7a7cbb4738dd632d0a8591b2dc5400ab79301b0253179a79a46249dcc0633d", "MS1": "1dfaf1f8fbc1e73ca268da2438779761011f2f323d4e2e0c2e7b7dfdfdc09d09", "CLIENT_SECRET": "0409dba5ada58542b35c6fa821aa7ee0dc662d632d6c048eea0fb276171d86863a14d683220f17c91b4684ff48095704ae1e36ca9b480ea0d2ca2effe19d22af9a"}, {"SS1": "11d04c6be664a9ee8900149c4bd176db72834f46f02925675523a3508325028f171c08a1d6b16ca792a5b8006c17a546b1d2502ae15e7bbdd25a5bd0a306859a208b56293f16dbccbb83781b12ba6158d87fe9992c6c84a5ad156866f6267a380b54fc766ba63ce73f8eacbe4a3d06414cb4b41b4515fa068d30ed0162f93feb", "SS2": "051235d7a207e299654db1d0405ce4bc5be729efcd78ff490cb999069784677f111e18cc268d3064cb4deec9715f9e2f7dc6c72fda4c9d0ee276f44bd06172c116122bd3db7d865cc22a7c33a67062b557f14419f7fc415556661f02f729d09d10897e87d598eab742f8bcc92b960538fd33ae033a7bd32982333bb474de8ffb", "DATE": 16574, "PIN2": 7073, "PIN1": 7074, "SERVER_SECRET": "0fdf53b9e291dca9d4d5f0e44d616e6de62c8c64f9a62fd04cd2a44d3cc67e5b190fd0f4d58d07db7efbbfde577a88d5968321a3761c1052f2cf300cdcedfc091513b708815e9d45b3c1b15b2d4cdac06c18b9a969eac4bc90c3d12d2eab1b291947c1d46cbb8d36485dbf4c3471b06455afe4ffda78b03c5e1a8785b8fabb74", "SEC": "04027a2fc23aa766976be3a2b8475cbe63569c5b2f4f9fcef585523f32e37f1cc02071a8cdd1e09655c36ea663dea1e2d09ee298c7259fbbdda13bc64f65c40347", "TP2": "040dfc8d2a955c1cb5ac104efe3fde67d3bc0bf6fdad88c73e5eba0c3b9cb144471334414a0ac2fb7cdefa122f7afb271e84378eb681bbb4586f5bdcfe74211cac", "TP1": "040a6fbb4d080ade2fe426bc29e53a5f7ba8a47bc974531d67f7a53d2a66cdaba619a8463b32b013c3aaee4085135cc528725b2a017187105c05b0836ff8393f83", "CS1": "0409248826e9213f693acabe93de066f5defffa3c3920733a115b2797093f8f4281bcd7a47492b84382307d1bd4eeb976c2886118ec2e68b273dbf9a8caac9396c", "CS2": "0422f8905740bedf9199ab63afc5053ceb27c66bd869d38ebf5bedbec661b661cd0f071a8930b3c3224fc275012178025ef251f4d9e90e48e03a5edcdf32319c87", "HASH_MPIN_ID_HEX": "8ebfa37a0a384b9d9a2f6ddd0f87a926aaf80ffeaf8f7a7dc10e09a52d27605a", "TIME_PERMIT": "0410780810827441bb3437e7809dcc19a23fdc87a9b731f48923729cca24ba473412a5a01cef4ac35bc679cee5516e2faf14bfb1c1fb09086d6c2df6ec16e93b66", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34365a222c2022757365724944223a20226436343330646131303966303835373033656665613839653435663766343035406365727469766f782e636f6d222c202273616c74223a202230633335376539623831656238386363227d", "TOKEN": "04221d4686d5057721d83318d27a22f4b6b0fad4627dea74a47ae8266b7cfcec241415a3c5ca39fc8546b1103e91d6aac7091d943b7231e906d0277cba1cbf6d8f", "U": "0400c7b46e53984b5c893285e9216c8c69fc17bd5b720c40a3934a43a6cd9de61312a9ed3eece4d1cff318570ea4508eb5f15d542f4fd09a91e5a5aef76e732455", "SERVER_OUTPUT": -19, "V": "041bf41001b7139ac98e56d8c9b12a2ceaa11e78c7b0df931db5939ad368dc12d612ab0b802cf38813d1c1cbc62378f5ff9c5903ffebe91bf9d1d3172a30b6a6d7", "Y": "120bf0906bdcde932377ed05a923a92868507fa7eaa08d28bb48b334251228ac", "X": "17405c8a71473a28dd95d365293f0a58cfcd9d0a961a626edb912dd6f17a75f8", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:46Z\", \"userID\": \"d6430da109f085703efea89e45f7f405@certivox.com\", \"salt\": \"0c357e9b81eb88cc\"}", "test_no": 137, "UT": "0412189c2a25408b085ef46addde9ade6141d8c46bbbe7ca68d9a3b538c7557c4a0fa3a73627d6ee67c16e2185a86e599a55bc41de86d13762dd2aef3ad5f69e53", "MS2": "2025888564f59bee3fd6e5ed942e3118537cab573791c4e3551b66fc500b3935", "MS1": "0d0b57a21386cd2ef8b8334abcac3349d9b0e5e159d0eea7d42ff45ca9da087e", "CLIENT_SECRET": "0401d8a7d3c198285eb35d4494b10c5ac334f24f19f500d5f3f847acb214ae8b63235f7352b3a11cbc5da0ee7bd0dcc717cac2c563787354d39cdfeaacbeae487c"}, {"SS1": "001815697ad18a849601b14f0449782517ca089a1372fa88029b6bdfa171eda415d64e7979b5d391beca8187f21699eac92a438b50ebfdf4aca4b9847ab16dd911036e4ecfd38f12dd89c29b5193ae401ceca280cffb86dca71512d03fe05adf0cf560a4af15add2c50d24e2369e70c01e98ea6d24cf193a4803dfcf9f240ccc", "SS2": "029d97a22bf974fdbcec6985e64a6de091f9954034eff2052e7aff563919cf612138331bafe2eac644d53e8a47ec677c86da391a517d9838a95c38b242da7e581b5cb11700197d49f4df8f8ff17faeac0be5a39c4d263e6ae116b10fc64d15ed19766c6136e424319c3a094bf1eec4cc7ccfd2703d61ef9fe5b569d59cea54da", "DATE": 16574, "PIN2": 8732, "PIN1": 8733, "SERVER_SECRET": "144a62e03bcc9ae5063e61995ecfdcfae1d1ff37bf7a83a87dc7e49fc4ee778102fee32afa09596e8421dbfa56e38b81823b771d8dbb82eb4cd5a7f8abdff8df0adde7c4ac0f5a970877c07a19123b7c786c08369e25fdb6697521219a0c53de13294286cff9c9d3559aa04585429249f722a0c6d5f1988acab24e880e9e88c8", "SEC": "040f93aad3558679a50806f02b0b8d80105d1d6ed281b708ea585a4b6a88bf3a4923d59d96613917e0ca61bd871538d7ac301ba3ac5f501ba833f170437e52ce22", "TP2": "041d37654876cf9a3e61ad90e553f2852b7f7b8491bc672690e829b32d62d79cf40b2d3eeadea509d4050fc623d1240b9d965c32ce85473a8f2da9db2d34b621ac", "TP1": "040c90ad656d9066c48f7f30f27fe30511d8d29f864680a2ac829b0bf95bea49911962e5b80ce6cb68f0267a824a9c34360a98c96f1ee6a03715e810ffc50d18ff", "CS1": "041ecf8eab7da8b9bcf9c55c4a925382cdbc175507421c62f66f2bf3a5bb19ac9b0a64de5e6ab052259ced8ef1feb39565b2684f79bc6c262b6cc789da375e4760", "CS2": "041e66e3a8bbfbbc80c0084daebe6144f4de9946787fb435c5c191654690adefb71c75a5e01461eee6b85cef0b5ce515a082b84f2e27b28721c1c8cfaa8767a13b", "HASH_MPIN_ID_HEX": "7290897e8ae4fdbf5b1088bd740a9a139900d473f26032e07595a5f30138e434", "TIME_PERMIT": "041e7e8315f1b6cd19043c61d0d2a8ebab405c0ad03e7d3a4cb7ec224fd13b335e1d2343068ce2eb28bb46b0347a7440d379231f49f1817e59622b4ba98644c976", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34365a222c2022757365724944223a20223361396261343130373435653638373563663662613938303237343062373764406365727469766f782e636f6d222c202273616c74223a202264643162313666646662313664336137227d", "TOKEN": "0420fd236e8142855eb443bfd9dd54f38932b2558b985fdba45ae4af1c4a9125871e9a20c168a35381c3f3eaeb370b2b004ca569979dd83da203d579939b6ffe8f", "U": "0413635302eb9b7430bc7dfd1ee00407a421bc9a2b538070055fa9c2bd756522061d281881807e0407d1f2ff30b6c29958ccb3a8eb4f11ebcf9b4e05aa722b195d", "SERVER_OUTPUT": -19, "V": "041127dfacd10909980ce3eb6c66140223e3367361aacc52b97c5c4bf27714c476127f3e3e344103b201ce71987b349fbc0d8a6a08a49f97f9d35dc875168fe65f", "Y": "118c8cb2c9cfc05c44058da2b6b9dd73067bce89c8fec003fcd42b4d823dca6a", "X": "226d00e6d09445ce18941f76bb3bd9b23096cb7f4779deb819a1106286dbd438", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:46Z\", \"userID\": \"3a9ba410745e6875cf6ba9802740b77d@certivox.com\", \"salt\": \"dd1b16fdfb16d3a7\"}", "test_no": 138, "UT": "0421b6381f30d4fdec46e39f6e418fe9b4988412ea1dc564f160ff94922415042e00cd7f9841b0c53d743ce767582e356dc8e96a0e915c2188f39010d30ed43e59", "MS2": "1edec98e9726b623b8178c2ef2e5a7c5055a01a8380abdcf6e50b54221309df0", "MS1": "08f27346ee5808a1b5d6a6af25cf1c1381e4c44c8a477a470f563a51563bc094", "CLIENT_SECRET": "041f5ee392116d769be319ba300ae3761825b4e44b2bfc6c2ac974b8cecce8d4ea16e82ce0430e0c1870174a66d41621ae9d1b6659c21069919b07f54c42486bb6"}, {"SS1": "1f4b63fe242d23e10243ec30ba246f2e56c82da3011bf7730b088bb8b7a4f3fa1bedc76e701d37d3d0c3b17af9a2ae5b264ff09a9bbb11d2699f58fc96c1ca140d7234272a566a982232b8a3e16e01e8e855aa39e7a8ee8a69d8a4f0ce1be60e0f54e8fccd6e39ec58735534dc753b1a4cabe877c24edc7b7794d52c8e984bf6", "SS2": "07e38070f13a00d3cfa1e7d3f64762da98e371f7caaa5672348a7730b770ad5119b4e5d1a714c1225069e33eaa224ef236e44a9a5ecf4541d9a8c326411db7c9085d4bc6466157a8d7742ffb3fe16d8bddd2923884e18e30ad3af258e82cd27119c3edeba03ee989d230cc2909e4d3415ec2c55ed9607265562e5dd210f8f5d3", "DATE": 16574, "PIN2": 1301, "PIN1": 1302, "SERVER_SECRET": "1ca4577bce00e37fb10eab32edb3e041b3f72dc65ae13cf7772e6894c750b1c804b938cff5e9d43ffb2dc5837cfb8f8677f740aecfc73c15da30f342e6c6b7160945d47b3249691da435414aa82fa8e3a7d4b4ce9dd2ceedb33ac2e864b754ce1a0b92a0ccba13e4cb0fd8acf7eeecdd71accc439ed6d67d0121d3fbefb2396a", "SEC": "0409308a1361de5393ddfe3c14e9a8957c077468aeb74710c09714ff00e3632409033892f9f1fd8b0da2db277ea830af2ba429ebc47cc1be7822f18e51580405f7", "TP2": "040331024e49ff53d4a593e266321b439672d8662f13abb4532f947de91c17363c1527c950e27ad1c66624fc81186cee585384570b62712c2d4437411fc0138c37", "TP1": "04187907080c23c75dc323a5337cc4e9fa59442fa20e619d2ba3ad796a7da280031cc4eb9407bdb6d5518ae596a890b59c55a4ddbbcd5ad5c9aaa12dad09b7191f", "CS1": "041ecd5e3c359b11721996b22c9d6ce5c3bc1088dd702abadab5fc263d93d441ec0477c0706539366512b8bfa998c8882ce88f1b61f282d55dd29e489f87738ea5", "CS2": "0406cf9836eb2ae5aed7adb21ef2687615accba27de863d49b5e3964a8ea20df112130f5349fc985c4fff2a6222ad2083cb145469129039272c1c859eebdc5ee2b", "HASH_MPIN_ID_HEX": "cb50ca75d22b01a800163bef423bdeeb73fc3f29bac374439bbe6898800dd1cb", "TIME_PERMIT": "040de18d993c024045cd7915f5370fee4d6e611adad137148351a15a6d47f777e91f7fa3f81bb35736a831f8b6cffcef88554e54e00d9a86342c735635fca8360d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34365a222c2022757365724944223a20226466386662613436616363313566383934616334613739366139376461346237406365727469766f782e636f6d222c202273616c74223a202232313230656461653731643664343362227d", "TOKEN": "0406a4d51602280911e5919878eedc2c55e74a37f3c98c1f1353b4a1f51cce426a19892519d8df9befc32ed501e68553035426a7a3ae770aeb7ff3488d7e2ce6f2", "U": "04188e161ae44527452a8622b7a9b11dcc72d946fe30a86ae728fb310b920afeba0c76e7022b7779c2005c1cccc36076f7736362f74241324de1a62cd6be92af3e", "SERVER_OUTPUT": -19, "V": "0409bbc27160051fd0e8c607eba682eae5ccb8749217ea23a3894fc3b6e17204d2143dd4c195df4f9f5476d41642debdb2680469ca7170715f08ad631704fb42b2", "Y": "14805ee73a46e0360c810e1d828797036dc0ef863fb564e210827118dc41f733", "X": "21c28fe77dbc09d3dd2fbaf87f29550505d0cda97996918d59c1a42be1ea48bb", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:46Z\", \"userID\": \"df8fba46acc15f894ac4a796a97da4b7@certivox.com\", \"salt\": \"2120edae71d6d43b\"}", "test_no": 139, "UT": "04233545c90056d506046383427248092266c0bf0c4cc9574c4c4dfabf63b1d4e518f428d07b914158f7f4f12df092748e9c98b1cfcbac5fe29522d0bb57337200", "MS2": "1fe541166971c6aac8a06a0d78873dbce91c9227760cb84ff1aae4748a9f3951", "MS1": "036fb4d528a513ceb7df591de8fe14b1acffe467acbe8d67221e8c1fe4822672", "CLIENT_SECRET": "0419c7065cdc081fbf046539ab41e06166a36ffcdab05561fed990c97ee67e81510efb31a0fc828662d225e42724b5c93a90e6977a5fe1e96d8f301116006b4141"}, {"SS1": "13ff24d0e36c61f79394eac52bcb304c8830a629268e3a4d48756cea9380192e0b858d0c2d65894e6eca16db0bdeba09a2c0b688492f16d602a4e14243da1f5523d53e25f9e0cc46a3dac8caeff0cd54a34688ab924ba50d7f4b0537b76388a21588249ef7cb3d6126ea7dd08a6c53265a86122546275dd02a4ee309c3dd087f", "SS2": "12bd8bbab3abf98ed266ee8742f19456264abcb120bd848a8a53e81dff19dbfb191f1211271a0413ffaf651ec0def512452978ea016826b435b0961b930b79d81a3c43df38dae132e1749e2debd9587c8a81dda480eb283d9784695f9d1a923a074fd41f506c61665b8f77ac54c6a52fa829256043c1ab6c8fd61e91c5e642c5", "DATE": 16574, "PIN2": 4523, "PIN1": 4524, "SERVER_SECRET": "08002f33fe347044ac884d5916c075f2cdd11106bfba33e32b025ff262ba7a8c0a197689c61d12cd7c2fdaf55f3c0e86bf6a6fb23a415add7a56ac58d440a42d228d64725bb8df30af54e1b830f9e27adb777600ef39c29caa62e273eef18f7001f45eb54ec90a3f814f159da990e3d27c3c80a6a24d7a5fdaa4e4da8507080c", "SEC": "0413d71f62c1a08fdd644a7b8a83b959bd4e2c850b768992ebb5859666aa5836dd0f46b1da3919653dfbb402ee15e71c0d2e346d20e51df0217e59b85e1a5c2fc1", "TP2": "041b55cf68dd4dc49e417719f178a9b6325f369e88e4839085597e85939f76057a1b91d785b6e5e50ce85b2df2abb8b0cc49ee36aa78118df33e2c9234bd8a50c7", "TP1": "040be5e0c8dec24bdec065684cb012f792038261258642207bef70a99b19f71deb0fa3e5d24710121ca2974d4a5533d44ae568928b77b2988136719adb75cba7c6", "CS1": "041b73de9198466a4b3595ac00a960fd1f11f43db13e2f9cc4410084b2bef18ce71ffb51ed5d080b823def4e6660746396ecc270f2319fbef5f0493f035e0f9f9e", "CS2": "040ec827576026e94c814fc96f7e14571d64f42cac25907d4815cddc821583138e0104dfa3d4ed8a509964640d842167db8a2d6a7f8274e2426e5ad444c641e5f2", "HASH_MPIN_ID_HEX": "eda39b143c3409f598c986476cdab215049f5554b766d8817232f812bf9acefb", "TIME_PERMIT": "040836f71a0a178cc7b4f9e5ae852f92b6a0e16468c0f5203187b96d0cf0a5aaf30b4b94ff0e98ccebbe0c11e6e7e2ab06a5fe04dd914f69555c890b3c05f288d4", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34365a222c2022757365724944223a20223631636436323734323333306330376432376230633466323064336463386231406365727469766f782e636f6d222c202273616c74223a202232363962343665653963336632313538227d", "TOKEN": "040f87ae8d9c73dad994b4dbc45eb70935400b06ed9fd897e6c9cae16eb0fb07d9125915afaeb0bada63c795de69a9c4375fa1dbf7f62e50b8e026b154e615f4e7", "U": "0416a025edf67a1713d940cbe4c20ce1806709473a2113116fbf06b1aa17a58f3907a2e75a54c344d50cb10fd0ea203d8ccef3bdc1e3844f5a4c4b6effbce33cc9", "SERVER_OUTPUT": -19, "V": "041b180fbda52bd5c51a4de65f79451c1c766344af4221cab6750c0d44879282241157ef7ba03b8d4d2b1da5842b9a3d62c8c5a7f97de7019c43d34ee7c90b964a", "Y": "07807684dcc905e1b33557da131f559109f839a0288aa5fb7b70178d7d1235e0", "X": "0872c7617772acb07351df79c27cb669fba80d72012f1c270902496bec9dabea", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:46Z\", \"userID\": \"61cd62742330c07d27b0c4f20d3dc8b1@certivox.com\", \"salt\": \"269b46ee9c3f2158\"}", "test_no": 140, "UT": "040577f2d1d1502699b7a43c29815c4aa5d90862986df6f57f697809e5f55464b5192d03086bb8e29da4d48f7444092ca288ea9e936abd41f5ad7aeb5c9a07e777", "MS2": "171e12c257544025ffcb835b15ce7172558dcb6d3505d2030ee13d682cd7f899", "MS1": "174eb2389a8a9f2b461ccbf3fb02e38ae649627f4946db22e331a8da5714c505", "CLIENT_SECRET": "0413eddf27f833f4eeb5a57e27834316176a90874f54e6a20d09e0b10ca7944ed400b8b7920cc8d4441fd1b3a712db9132d60bcfd8c0b89a5795488d39da03bc08"}, {"SS1": "0b8a8889b709319b3ab7aa0cfeebd801cddb0ee5418c2b928dd2130a797b4f1c03765310c3af65961f26b9010fc82c7dc16c59c71d19a0e571097e577fe9d3e90a770aa8dfbacf3f2d4280780962f898fa3abc60001d07c7514a3da6b6026be205872f43d8d9f769953730bb84d32f525f211cab28c0386ba51614d1df3cdb64", "SS2": "1fd311b47300ae92147a71194f5a1f0d43903b5e8cd2ff426b1fb7c2521ace1a0d70178af8556d0e75f0e1f8d058909627ae24de6db4fff47832f76d248c918e0c0f23aeee832a448de70b4097a5d5ed9e31a5e5d96d56965aed16e84e89ecff1f89edcd394c2c5f8bec60f0b9f52e9981cf0fa00f05357509f27545545772c1", "DATE": 16574, "PIN2": 5259, "PIN1": 5260, "SERVER_SECRET": "05aa0891492911224a0ddd121102e85206248014c0a91aadf5f97ab46815e4fc228425824020a31294529da63cdf7b56d538f741fc6500c1e507bcb4f04bacd40fcf784881e88cd9f9455bf01f8dd09268a62c18f3d1e4b48afde772e1859acf00561cdde2d8b14c56aeeff128b3de6f52a1b16a4628031633091eea5288225c", "SEC": "04034268f53bf0c5c8bacb7e5d7bd8f06e5b1c2b64ae76141b9b369d4b76468bf2223e917009e935c5c6d1e20c8ffde6cc03db0c85a0794656e4f5019d6cf5e5bd", "TP2": "04110369c6793eb1d4c54af76860999663afbf8999d4a2a29086944934309370cf0b0942069d1c075b18db904b3724740fd05903bd074ef06916f91cd4cc5d0c51", "TP1": "0421c8a39186573ce25dcebb2381ffc9200efc8a15c0c6e47de0aa10390401e18d09de4c1d4532f57d406508b4ab937ce9b75cb36945c46f3fbe7c49f6d13b2d6a", "CS1": "0405b659560713ebd57bb55a52f7f708c015971ea447f998c20365c22950052a1f13abe575b2394a71506172cadc33ac1b0b42cd61d321b5cd21b25cc8f465ab9b", "CS2": "040a4fabfae0dc4194259e595f7867d00a6bc56cefd084cb92caefca18a71ae81d1ce6d90051c77d269fad0273806741234a3b56f1badc73389ca933f171790cd4", "HASH_MPIN_ID_HEX": "b37c9c9a1f30a381179255892631c637aff13337589742838c1b9862f76269a7", "TIME_PERMIT": "040e85e60cd077189cc4b196be477f9ca9ecfb62ccef8f20a3bf4994f09852a70d11642baaaae25670d2e9241789b2e17e637284543e0a4409311d9e5bdc829f18", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34365a222c2022757365724944223a20223461643336663162613933336464346630383862363864353438613439303732406365727469766f782e636f6d222c202273616c74223a202262303965653238373434313363393239227d", "TOKEN": "0416606249ac024b709b635b8d15f587650e433cbefc9ca5cfc5ed80ce830bd14b163f569b4444e7f83fe436b421600cc6c0b54a16cdce10af477cb21e63245a46", "U": "0406b38c0f331f35880d5ef1da737fb33b207bdad99949f385f0c0d37dbcb1680a05c0c0a9099e66820edc6f8558c9718e36c3a5f561004e41f6006008f83d4bbb", "SERVER_OUTPUT": -19, "V": "0419929d9ed60bdcb51fb3766b3af32e4125da5c70b62da5575b74e1363d9a9e83009ecf40ac45016b9ea65592c3a614232c2d1c59db33052ade21771667e1b678", "Y": "1beae979d3cddd8c0a1f44b171818c459f4d507965b847c923ec7b4e578c88bc", "X": "1fc3f573048e10df74d7ceeadea6f32a96de9759058bae5933402892cc94a274", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:46Z\", \"userID\": \"4ad36f1ba933dd4f088b68d548a49072@certivox.com\", \"salt\": \"b09ee2874413c929\"}", "test_no": 141, "UT": "04212efa15234060ff0e291a4aac25bba7a0a20909887f39b08ce89553cf8c6a3c03b972c3de0995faeb587414a987776474392ba762eb4129e16a94f39d66f1ac", "MS2": "114819b14628e0eea18a2be339d0690a34272e6c9d38050afcd66f35eade2255", "MS1": "08fc6c6c0c412970d908eb06d85282de77898d314d5fe4f8b7f9a4c36f25fd13", "CLIENT_SECRET": "04130b52bfaa1cf36d48cc9c0744832dd8d94ea3c17e26fb929c1617a5288203d90aa0ee89a9002946da35f461adab5e5ddae57045bfdfe7862cac6f4632880151"}, {"SS1": "03b6e31f9ff848e51d5839255324e5f068ca5ec61e365482981b3833733071971ada21f03a0dd980931e2b98f08ab5f004992e7a07f57794007b6dcbdb65046a0c094fe61756fd35c3db046db0f82ad444d02af858fa5327e718ee1ae6cdba931b4bdfe5d91d05834e0e3d6125f7cda211fde4d46a76a8507307df7dad4ea9a1", "SS2": "1838c95e9add438846ec55d4918529b59dc147629d8d576d09fb4832ccc3bc321533245deafe599bf839780926ae262adbcd3bd9a2cce4c02fb7a2b9c15fb8b90e29d3753438c15134d7b282ed4312aca1b3245b07e04cad2afd3ed3fd4b15b00276703800a03536dd63a1c4f562f1660f47b6106c2d280732a88e80cba84ad5", "DATE": 16574, "PIN2": 3969, "PIN1": 3970, "SERVER_SECRET": "23466260c3e19611d2717ddc25c902bd62334a5018bd8b84abc58885461d93df1acf55ab6128f154c30ab06d91790a5d74801a1fb4fbae3ab7c87e83ead57fa50bef3b3c898f8737ff2c5bf72b9c2f07231dff2fed404126e675ea48c339a152121e243e7775cf52235fa92036ab20e111faa1e74c4c7492d5ba93bee9549653", "SEC": "0406101bd7bdd1ced0671e6e7693874dd12361896833fc565c6c6f358121a1f0301cf1ce23c456fde786a0aa6d90d9703e3b051d8e1e8ff70414f51a63ac490020", "TP2": "0406a56de46a22676663455d6281bc681a2b0ccae24726a1c9a2dee2fdc59fdb1620da3ede7e752e603fd4457c6d8f4b12db977fe86bc95b16de26085fbb9c87b0", "TP1": "0415bc185e77f77f8a582f6b44cc9eca53f56b0f4d3f50b92d3cdb8c97534bd0bc1f27675dad1e54db9b3a466e9a1356e6a91cda9c9d6f330d99f80b0ba272fcd0", "CS1": "0401197af2cb6d4a2471751d6fa2a7733e42f079886e991261932f055d3d955b8f2347395b00087fb3323e00ae54b9c653273cfe258f8892d045b9f04c264e11aa", "CS2": "041c429cf93d4361ddea0cb68c60edecbb205c45ae19b7b6305968532735c8a5d00f3ff9a4877bce87870de33807502a70878bfa5a5fb4dacc3a7ea12a30d8af41", "HASH_MPIN_ID_HEX": "31f12441e847adc8c836a7c51e4414feea47d904a92243c4996a87f7a9bf7dfa", "TIME_PERMIT": "0401ad066c0f0ac108cdbca1a00ba79ec94e217dc8a140145a34b4273ece3b2c2605868c4e4cefa1958bbb5e3fa22434838321191c3a2797f3ceefad2c13ad4bef", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34365a222c2022757365724944223a20226536343631613838363934663336383766663037646135323334363839616436406365727469766f782e636f6d222c202273616c74223a202231363833396262393465383338616362227d", "TOKEN": "04034a3d055029e3a3073532cfc5c5b6a45436c66f6c48997970e94b869f9de099208176bb789767fb829a58f9c43ad764439a4e635e2901ef5ce3afeb348f1256", "U": "0410dfafec91a0eca4dc8a0b5736b2ec244fef0aa555c500a68d7a1c2579b28dc701edfb5164681ee96c1ed6546dbe25a63c64442c9be1162c546f8d36f7c2cd33", "SERVER_OUTPUT": -19, "V": "0402e945b5c744f9e772ac6edced2dfda5ce065237849463ecc458d3e5c72e5e1509946a27066c28d401c01941e553a66140c2838b3075c1a7f1e1bacdc5135c1e", "Y": "062a90703272d06818403ae3b609f30f7005179bd8b39bbe892490ae62224d1e", "X": "0fb30669017b7f3b7fc7b434f80c5786fab2971d600159270a3ead611dfb2c8f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:46Z\", \"userID\": \"e6461a88694f3687ff07da5234689ad6@certivox.com\", \"salt\": \"16839bb94e838acb\"}", "test_no": 142, "UT": "04000fe52c03cc29fa1158cc1d06946025731decb9c4af9f2c9aca9db946ffa631094549f4f8c6552f99d31f02d3a2388072edd0ef4b284256fbd05b2b817aadd5", "MS2": "0454106091b5654e41e0668f6e6b9b184593b6ce97be87e55aa9d4e5ade595ba", "MS1": "15a848191bfb6b7840ace04e710f3597452f345b8f2fa2a02800b10c7543dddc", "CLIENT_SECRET": "0414d666e6867717d1b81f8475bb3c4466be33d2ef8372bdf4e4e7d452bbb4f5bf193fb33762622c8bfd500bf826c5f369b46c9ed14f059262e8c1717f2de2ae08"}, {"SS1": "03767fc9e4613c6f88c1de2cbc5c59676c79bbe4d729786b90864c600ebdb6270af0ac246a44a01cefcc8f6afda9f06237b48e8f62d8dce4a5425004ef87a6150ea5741bc7503a2d752fa4287541b76fa7edd4121552b9c8c3d1c838b9d8a23115bda66154e9dabbebe164e775aeebb07164c0ce6eb93947b7654e84cd60a9b7", "SS2": "1f3c06bf2ce9e55550cc24b1e56c686e71d59e611d9214532ca1047acc4a290120f83987922a1e706f6696797ece89c2964be251b3b4ad1d1d87d072dd99041b13fff6ea382424db3d845d219eaf4ee54cc554e69d68d187643ceb69b8c1d4e01d7e3565d5aa81e240d6ef89b19db18176320e542edce0e1101881af8035e26b", "DATE": 16574, "PIN2": 2279, "PIN1": 2280, "SERVER_SECRET": "1ae8c45ff5d8ba26970b348754dcdc283df20221f694c89f4573aa67c970e0ef11cbd53b92e405e0d604bac4b149de31a768460e9b85f339e67c93fe8ad17d7b01cb2555810a824754b51d71a46fe905b1c9e6adf7bd33f029c0617ef3e7ff2321bb12f43808198799e13a0697c5887686ea4a503a3decaba7492c20e321fece", "SEC": "0418f8d7806e61f759e90bd630a6960756e15424e7163e3c9b96b7f4ad9c7a13b220e585c68a758d9c31d8e77bbc82bbbde33ea01fdb34e902673dd3416aed03f4", "TP2": "04162b7713c670abd365641530c4244f740da0240e88072659c6cf33310d033df4054a2e74bde6f43813248324a0ab41a5227f763b17e9e96f6b3953078f2ec7fa", "TP1": "04019e9fd103e369a739ed84a811fdc1f648b4e751bf885864b50f504c10ae6de4096247b3e823936a18ea30185c9027176561478172f7f8802175fbb059396c70", "CS1": "04159ca487d4a32c3b0df52051ec85a07b81d744751767c5d79d8b1627a4b450f00d14fb787151453c1be65d1179af7feb7a7abfbcc7e3091185e081b4af96aea2", "CS2": "0410d532734bec683ecd3df7c52b7cfcf0224a99ba363fac76c13f9b5bbeda90b70263baa9f59132526d7655d83c643f1f3ae1264d335c273a81aa17b026400049", "HASH_MPIN_ID_HEX": "d00efc380e9606ffcb7efc4f475940a0613f4ab63211b6fa90ea5152eb39ce04", "TIME_PERMIT": "0415ac082e543ee064cbde541ba2354a45ae474b1d6cc3ec094da9f7492cce2891093166f9a3f0ed9e9f4f8bca0745cbdf9c5de578b5d3cc7c3d58ccae0b912f56", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34365a222c2022757365724944223a20223166303530313634633235666139353238333534376331653465323264616639406365727469766f782e636f6d222c202273616c74223a202237333861623862396463343966613435227d", "TOKEN": "0410e87dc805c9e78a5478de44ca6f0fc9eab0e046bbf176c13fff326f978409301492b1c9305557ee11e1d74349eae085ee4cd269ba974e9a28ef99933ced7dfc", "U": "041d77d5c5bc89402810678050ad7e1871460c57209ddf88c651f600cde2f84c7b0a419ebe9bc842ea059d3d4d8b96a0d45b1e2d1eb80804123823078072ca25ad", "SERVER_OUTPUT": -19, "V": "040fc2a33b3b4f513a9f8177639d4fbb8682e8ec23240d5ee052195ad20689f56914f5ab0334f1f5fbc461f7423deca4db1a6e54e465f7d4e2dd1431c9c8b2c616", "Y": "04568874e06e99bf53b4e940f2d96d7aae7c7e6ccdd1bef9791805171863280a", "X": "1756bb1962347cca26b6bfcfad5ffc128f195c2f526ff9e5f94e58428111f409", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:46Z\", \"userID\": \"1f050164c25fa95283547c1e4e22daf9@certivox.com\", \"salt\": \"738ab8b9dc49fa45\"}", "test_no": 143, "UT": "040dddbedb725f92372129fcb698f510c7288dd80d1a369ebd254092204ab6544d18c6c1cf7cdb18eb1315e59201ccf7cab209ab7fae8b150408cfcefd074dd013", "MS2": "1db27d29f876ed9347ccb2242fe4a84588c73085e1a3f8ef6acaed95d4787dc9", "MS1": "1a4dd771c8d4bb39caa7f8df5eefc271112e6e7113089f1ad341a7798b4024db", "CLIENT_SECRET": "040d12e8f3485c9c00202d7643349c62f1d4b4f355b676da3752d46bfbd3eec51b08b73851f0219adf775a92ce76f214100269dfe9c9fea8b138a0af0b878f6cd9"}, {"SS1": "17287bdff88fb38b3fbd68fba34eacfedff453df24e519ae63581f6a53f0c1f323ed858866b5b2a4167e297d6214dd6f9f7edd4d1f9dd3586589116afa7c9ed623cc2794240e07c227ea84925fd72d0b7fc5a70f5368400e9ef3273d2f207f4a20125b699f7ba86ed54b87d5bfda2eb1a6e76005518f95fcc15efcdda242a0c3", "SS2": "09962998eba6964c9ccb8f8337f54b9c2a47d912cdd8a9c9cf4fed9fc6a13f2804b36e9754c4ae4cce0855f472ae3cc00af82214e4b9ea527ca50d50943274bd044206349d1a61a658ddf9f67d814491fc2e283a3136473468d24aaf3b8c3fea066fc88a5cfcbb193faed580af358bcd34321ca2e36129597a5b4029e9f7c019", "DATE": 16574, "PIN2": 1545, "PIN1": 1546, "SERVER_SECRET": "1f947ce379d478f76f5a6d778633703bb812ee04503239d4adc696a28f4c5f1f00986246cd05e4535a1760187d2cfb426a2bd257a0331fe7053f8a57745e989111bd0f09f3c9f26a7fb7a00a6ec91965d4b5e9e78f12d3cf85c246f4d6d494aa057c92298b0e73911143a80ac17ac8f83f9a7b0ca6d47e1628a8ccee757e2804", "SEC": "04086d0e0c6fef3916ac8a6f7a4a13ff938f16fd9aa9fe9c7ce1dc661797ecde4b0f567f8f8f5f7e5f7e8add33804b313bb66e7ca0aa691e6f4b0d11ce7db31781", "TP2": "041d39d57e5f98d3dede033710fb93520dd3d7cb04fcb6e7069527f698daba83b31777fa1e61a68721f94d50b1b45c5b8357707b9193d4d586456312dfe2da68ea", "TP1": "040f07f0840eab5d9154e3d2301635530816bcf70241b4aca580418ca69133b980050c0a00ac4bd298dd399f4e08846c646bcca8a61df311ff4d60e8d6fb7a704c", "CS1": "0422574c40b4484f25a7b8ad6badf4d3fc908f0bce271a2ed4de718d89b3cea57a1071610cfd70122c468e1ddf3e5445eec583264a47c668a5ae575a1b652728c0", "CS2": "041188b7178fa61e56650ec310eecd6c724a2c12adbb1ae920d78ad9721094fb31127ef95b47c5ecc12bfe78bef2beb4c921840b16c3c078738a18aba27d22410d", "HASH_MPIN_ID_HEX": "caf545ed844bbf58a70725486c5583345831f357b062f7d3f9b30d69440674aa", "TIME_PERMIT": "040742457d9fce308c92b9adabcf79cf003a15496fdc37038e4965be40bd5c309d0728ea08246be9576eda4fa199b8875cf4220f64daf5dea0fd7b9ed2dfb37023", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34375a222c2022757365724944223a20226136623263393561633131313938303939363434616538623238343435393266406365727469766f782e636f6d222c202273616c74223a202237336136623764356336376539353434227d", "TOKEN": "041c66d1e423acce719e00f301598329be465866a48bebe13647f352db0cecde0f04a2dfbbc4dabd778d03e2b38caa72c9fd8185ed2da23c823c2bdd1eb0e5d966", "U": "0415596e0d13b3031b1eb6a9a5a400497d5233ab5763175b6abfde696d18337a820ccdf5c64ed50b98a4abd3ef4bc91b1ccf428e9bdaa382d1c628363607b51584", "SERVER_OUTPUT": -19, "V": "040ae6c29c49d2e9530f6bdf97464a07ec3a0fc0d45ebcfbb7897916b025fc155b145bded9d4b8f6f7c04494949e6f49e50bd4c7d0cb937b0c20c7ddc134cc7978", "Y": "21e1bc57fd84e529c51f287c55f0890fe6c1293362d57e917a05d705eee22733", "X": "053c24c97fd7f7970e7747f1b55342fb40608420e9c02250ed09e2edc47e4635", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:47Z\", \"userID\": \"a6b2c95ac11198099644ae8b2844592f@certivox.com\", \"salt\": \"73a6b7d5c67e9544\"}", "test_no": 144, "UT": "04124fd9c02d7b04ad378dc5d8a507735e8fe79cc6a1a05280ddb8b6865e1396340ceecd05057267535be304ca88d63cf552ace86e8ddda2a84e18f2eb9e551fc1", "MS2": "07a5e530bc2e2082bdfb2a583749a574a7371693381cee3dd5cc59c01016c021", "MS1": "04b04a9aa72545e432ee1e01721302344004c2c1c89b44d9cb3ac8cfe92e2be9", "CLIENT_SECRET": "0408277408ee6a55282102976b5966ae9bdb9d9cb6ee27f07946b38d4960b206630781a2b6b0e393759872714132ffd16b20aef45e4ef651d50704ab8e1177915e"}, {"SS1": "007f73c7bb1d661bdc8274131a349afe18d9ef8ad85736ae447b2cecadf7294b1e358342fff999154259edf18feab1f95816e3d697cf9fdbcf9fcfc5293a9d7b1631a706de327632c2bd30e4ffe41b94d4d361a4ced68519647ef4b9361726fa13b18832640b7c549a0263a5cd9cb4078a3a69286392980dc846d9cae9a87c70", "SS2": "162a475416ec3345fc6131611ad2bc8db2e5c0366f5c185adc94fef7901c42511831207f6d7bb3efc414df78b07eab0f376fd1864c4795aed72516eb83219154133c1db554e67d8b34f76f302497865707e304113e31b5a2335d4bd27f801ed509f7273b78c64a67c3cf95b21b63dac5cb05ebf390c0565fd4faeed466d1a60d", "DATE": 16574, "PIN2": 3478, "PIN1": 3479, "SERVER_SECRET": "08f5b07efeb49adbb4244ef5aea1ad4f0eff07271d764f64abb892eb328d6b4618ab92245280be6820fad90ffe2cc313b047b141c0433f515334231f9c46fb1e196ad112d2875fbcecb67adf605741db388727b59f14525a7bd4a383104470b80c2725740fd9dbbdef49afa547f7ce87716498749a95d8262d02f26c76aac655", "SEC": "04224ec62ea899749065b6a509e043b9b1426a7f6854ded73370ba535a81b498c21155f28e37c105dd5efc5f22df7e1ff5c70442a44ec7d38fe3e54f7e2dc3be7b", "TP2": "041af3d816fd92dbd2415378b8c85b0c37e395d05f4b8c779e457018ef9fe8490b105efe60e01e09979d45fd6bf0c14cb7dbb2afa031c1dcf1bf1d9492bffd77c7", "TP1": "04176d7f0cfb2bf3b484a756a6dfd88e6e237c85f250d41095301a0352fdcd84f914df66cdc6ee071ac0fbc0106823aeccf45f808d9f866cdc796abda210ba0dc4", "CS1": "041fc78b294ff1d2b709c17781b578c5321fd7ef388756480e4288befa4f2efb9b1ca308cdc09c1006be5d599bb08f396e3c0961c6e37908557bdcfb476f93bc3b", "CS2": "0407f68adb7d77447d2d00a033868664f26fccfb997735dc3cb8232ad5531bcaf7173c93c6671c6a3e119e85461536b2f350ab7fd13fd18e24ed511d6f5ec17195", "HASH_MPIN_ID_HEX": "2e8ff438a243c8b6892740c35418cc62abbc80dd67fa2e6ea07af9b7576883ce", "TIME_PERMIT": "04207e00151cf44c28c10553a49b581c8611781c28a3f464a16ba1de0d6af9a75a217d6dd57c6f16642858111dfbbf7542dd43204a1e57edff3e21a26bfbdc25e4", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34375a222c2022757365724944223a20223232653662653036313235636165383532626536336435663839363939343165406365727469766f782e636f6d222c202273616c74223a202230666432306338343935346361383836227d", "TOKEN": "04220137232b375751306026d38a6df81c9eaf05a290c5e873395e34fa5ca1941814915ad7331a5bbd1af5315e053e9081cbf95bb9ff09ce7bb44d2e2915963cc3", "U": "040541446c7a5a13df9e2f256db42e09709b6f98fb32f4a39ba802744e0f3e589e091b00f32aa03e0dc78af67a4042c99b8aea68598ec38f7274d888aa9e27139c", "SERVER_OUTPUT": -19, "V": "0414aa2107cbee7e35d2f7482f8a6780b35ab489079711fa8dca736107567efa620914a913ceb77a55d4c19a3bcfb21c0ae592c584b2652cdd477e54a33fd8da02", "Y": "00020f7cccb4170f8e18c88da9cf16f4514e934e0991f5584f4a418fed7264c9", "X": "1f5b8f9f4b5ac73f0cfd7c84de5e17e76cac8c6de3d6126843fff109acefa5ac", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:47Z\", \"userID\": \"22e6be06125cae852be63d5f8969941e@certivox.com\", \"salt\": \"0fd20c84954ca886\"}", "test_no": 145, "UT": "0408630f4a234c0612783725d792360af088b23ba7e72bfe46877716c1213c429f1e252eb65c3b673bc5196ec886e4b4aaf2f16702bb996cbb350f98417dd4a271", "MS2": "16077c0f9940d3e12b0cf1b7af51f58848ba40100280ad2b7bdfc7514651ec11", "MS1": "1485e4d30520270e76092c132b3f5c566f655d33f0b5ca53140ef9ccdbb599d8", "CLIENT_SECRET": "040874c028c68e6051713fcb86edc4b9a3d6cbe58a3b1a18c85b81ca6c52948e261790711006578bf93c3a0de10b4079069caddc12e08375385ffed04b882c5489"}, {"SS1": "196ff92fc5e46ee3c56a009fe03b977c69e8384135f7d5f807ed09e8c1ba973e21a44d947b24be1340524283b5f20d55db8b49c8cde11695f2396a36d367fb7c15c3378c1ba4373dca3c4e043ee153e25ac4f8090ce5f6beb2070a56fbd8ccbd05f7603a5e7ec2e6ef1a3b9dea57dd551a50af5fe39334dc1a31c556ef7f1028", "SS2": "1c8e41e4f05c7b7e8cca8278475d257ae45b7743254ba282697a51df8fdd8a881a1ebcb733f6cf8405489d07a7fe1fbbd37b62b6b40a3f7f1b2985798c7d19a3068cf0a2b42d76be5d71af618c21bcfb0071fe8e2575263ee72a55dbaf59f2e607697cd63f3e9daeb26fcdc4d3da26ec80c3340dd47eac3fe1b33e89de0d25a6", "DATE": 16574, "PIN2": 5393, "PIN1": 5394, "SERVER_SECRET": "165c50d385c9574d3c9702d973011e9ca8e85048f95fa839a678b0a7606620c91e5dbc0ce85674eb38533ecee47e3f3bd965e8ab5fc0e030b50c0b61a45881fd01eb25da8bb8f808dd2671232358639ef7101b389d2342a060daeecf02bb93d806b3ca16d765f5c84f391f8ef2231dcbeaa5d97234b99550969e04f13fa33645", "SEC": "0407347c815dec503d0bb1400f7a79eb68fb2866c79ccf4f3d15f0b2bf0ffc301f102d2c73f4c11974787600cd6674346a8459cd7f9440a2aa2986c5ff697c8a90", "TP2": "04032dc756a14df304e20a3853709159c383a10b99a9c331ba0a8054f6cf2a1e59172ddf76208deafbec8e50f606964b8ecb339d1418e1be6ebb94486f458e2dde", "TP1": "0414650baf38cfb58a8f33bd06c0bff4ee8b97555d750de0742ce87110a6df6bd004f9ad0e79bb7d2623a34402826f343e017158478ee6001ec82f5c86dafc3611", "CS1": "04174f731b058c507fc9b0d0d4327425c4943f9c53af94d278ca2f8526a91914ec2342e79a007bb87344b6d7a9ca1d4f01cc4b3439c063893f288b5d65ea1902ed", "CS2": "041eec178b44965a948eeb1b5e2c3c39de7418a7093ec9cd318c111c59a0dd4ed410bdae9ae660baaeba9cd9d2cebeea42ff67af375d205639ad2f44614ecaf5d5", "HASH_MPIN_ID_HEX": "19eb870286d2a93bd44bc95dd554c3f2eb386e9a8aed4b314b152cc662d46295", "TIME_PERMIT": "041a0140344e5bae6b9bd70526a4dcd39d812c50c9127371f2b3c5c46876efeda61c8420b4c2079da0436e7fd59181fdc8a69ed79a9d1246a12de90d6ecc2981db", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34375a222c2022757365724944223a20223936623236303038346330376639303838393833336430366439643336626131406365727469766f782e636f6d222c202273616c74223a202236373865386330323931353532646361227d", "TOKEN": "0409454ee990d049031ffd53f04f020ea2e1413c33b659a385c12176a2bf14df02036f9ccb369b8ba48c87e53d3ca4983b3ebe09a9b7893f4f29577d6bfdbff83a", "U": "0400359f2a76ed5c7aad5e8aa44f0440fef7fe57095399f9528941df24a4ee5bea1a939a83986de5b84380014b78d7cab710fe44ada016291235676b80fd7bb531", "SERVER_OUTPUT": -19, "V": "040fc624652e0e07c9b16e0de0376181103a5def457289d8d4ef99f20889bd85ee1808eb5f7130ea359bf756ffa8c7085845392d94dacd71b88db9ea4289549d37", "Y": "04107d7aac1afa0549ddf7bd241854ed77aab46b8ec6f0a6c39af649806e5641", "X": "05f21b76e2dd21c40b902a18924a39e995ed7f929ce79b063404dd8dbf26490b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:47Z\", \"userID\": \"96b260084c07f90889833d06d9d36ba1@certivox.com\", \"salt\": \"678e8c0291552dca\"}", "test_no": 146, "UT": "040b65f5c9193026e92bb921894a10acf1a2a04cb4b2d6582ccab807f1bed0b21c230b3e296a0d721d020bff537b5c86a453fa09ca85c6766c358c1954052ec3e2", "MS2": "1eb50e159c88987f01652136df671d1f7c3b208308d0f6c65efef6243c2560d9", "MS1": "12a7bbcb8de8efb05839fc6b01776cfc2f05520bc8cbe8678ffe2b9482646b54", "CLIENT_SECRET": "041fffba07cbd317c5501a06cb8edeb8baf60bed490707dc7d088b1cfc1fe7b29e02e49836e8e7ffd60eb7ba9d70651df4bb2fa4a903b6c5f898d7330bcba8b2c8"}, {"SS1": "1c6ff96052465b0fec193a96dd5417ac689563e4ba778ad54deaeba915dd52ad08c4e70b78af197eb8c865ae89f7d7d6cf22cd3eb50e95f0718a5618c56c7e4c21470abbebfcb9506fe06a3baa629124b18a3d0e45f7d1760aec53d7e6ceb1d71d03b216be452a95ea60e1abe51409ef9c4708c60075b37dadbcf7b7abc7cdee", "SS2": "0dbbd1e029f212a7b68b32a78fa21ffab6756aae5bf17c2aba8ca636ec4321f61f477c4c71f35ad2e809160baef5f5fafcd607099b728aa848649cc34d7035cc1b2a986a00fe7e8591ea01eee9906c54f342b038d9f66a77b4aba32d0570b0861895722bbadf06a9c94925f538881a64e8e03d74467e57dc2ff4373eb5368ab8", "DATE": 16574, "PIN2": 5560, "PIN1": 5561, "SERVER_SECRET": "0ac971fde7047c97ab728b37342f71d75867ca5d56c4b23126952a25e5650c1c02a53543f06cc4b7d2fff49c1a1910d35ebd04e4425debe0fa7d11d0de8ec8b423a227ad5448a92820f48c7a77126b86fd904cabd3ec43d452d404598487d3db1fea323f51f031b7ab33c8c48140e5fd58ea3e3ef809b78682207027cba7a8b7", "SEC": "041aa0ea01f19c8d12d3f810569d331b569bf6e97563694d5aa0b37f0fcbbc60a5232ceae85b18a26e660cf92c5fe8d626f7479ebb20d777b3bdd34e24dc9e9ffe", "TP2": "040f7d261699e11ab509ea56696258d62e043e402fcad87bdc77d2c2d827e1b84f107b24889b95d17eb39fd76d3cd8477cf8f0b1c6b85b1088f0e44d3894d7e92c", "TP1": "04037682b21924cc5fa6bb129ce79ad3b155900bfa9c6f7cb157c9c572cdc6f8b81c0cd439446ae07ac1b01d86e1fb54c0c25b5bf42a74c418608415879e00a1c0", "CS1": "0415a4894f62608635647b27a39e2172baf52eaf679a9a4cf0d296ccd257e0504d16ed6b45fcc20174868b153a6fd22cf6f867c980b55892efd7589286dc5e543e", "CS2": "04146b4cb82305d163898441b1053480adf08d3d13cd02942f61003f9a0a5d84670272d501df5bcd34c94bd901394a03a6feab82362eac8aabf5f910ba1b271ce9", "HASH_MPIN_ID_HEX": "93a888240a73176d666e5d2bca37289a68ff38bb11b69abe446b605e83c89642", "TIME_PERMIT": "041adb07bec4e2e42be66c49945955e8ca5e87de3861bd3238c1b17e92702ad0e70a1e1f1a8fae5d0beab76d5024b6f5e20a0372a3cb7f97a08fbb69ea5740a674", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34375a222c2022757365724944223a20223565393061313265323533656536643464636165363261616162653734353038406365727469766f782e636f6d222c202273616c74223a202233316666633134396366633832616332227d", "TOKEN": "040a62be0ed4f635099a14ea5b648ead53b2932b00a0c37c1090c671cf8259da43047e7416cab0aeeb032497e089917ad4ca46bd513326a80e0bd0cbebe0438025", "U": "0400cfe364478c635f27378b62fdd477eb6ad60d53e1c66085a1c82b9f07666d70209a4e38776dec36da3f41d66075209c18091f9c64e86ac867dd7f8d54feb2ca", "SERVER_OUTPUT": -19, "V": "040e18751919f66ee0e7f50b96e6d0649dcb6f82602fc78628773063d2303a50bb0ec8347d47339f7bd1712ca50a710442517a0df9638c440433770303679ab1f7", "Y": "1db52bba4444a6e298fe155c2ae576ad09064dd7b1b77a4c6ba2d10b3e3d8041", "X": "00a6b2419ac63dae66e06db68455f629c811ba07d9b4129ec3fc839f5135ffd0", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:47Z\", \"userID\": \"5e90a12e253ee6d4dcae62aaabe74508@certivox.com\", \"salt\": \"31ffc149cfc82ac2\"}", "test_no": 147, "UT": "0413b4014aaa3ab1a5a4f389cb69185fd833d542a166425f046d43577aaed03f771c3308afc004ef794d30cb28f62d6212f41fa602299a35cd5cda006ce9e9a56f", "MS2": "109681b3cfb064af9f13de097a7567e8820331f09f4c95f3f49cb8ea3d177835", "MS1": "07ddc0ce9368f68edbca560682be912d7be8c58f6db1176dc9cd882f75d84416", "CLIENT_SECRET": "0400f2c8f20f97dda31d954cb4820a08b8b181e0b61c55b18d831fd8b371b4aeb00cc6096fe67c126d2bbfdfcf98b4311b46ba26167c30c2636b4f123f21412044"}, {"SS1": "1a9457909e4bb6fed41b696da0377cda6b7803798ff7f0ee2e43e66e5fcf416d223c2d2c22d29ae4b898ab5bef39b6b67dfbf83f9f5c9ad01a9f2c6002c0ddb800d0d47214cc5df61f4a638b832ea764e191b555b5d0b64a754ffcbc96cb2ee5173fa22ed58619188aef0a8413cd6f06e3d4941968afa747d45b4839342cab05", "SS2": "0e6968249ac90e8d4cea2015656ce6ce23b0a662d505c7a3dbc64c411b2a4a791fdc6c50922dd1b2beb1eb58edc67b1dd0b4c6568eb47014c984de47b8c01430222df907bf7b5c9a4ad395d30790b80265c2e2d926cabd0d4cb3a49b305997231716975e02eceafc4d2ad0fadfaa55e8b7dc37c8015414aa921a9c539eed3fca", "DATE": 16574, "PIN2": 9741, "PIN1": 9742, "SERVER_SECRET": "0a62a5cd979aee03aa55552fa46f372db39cca0be509019579de6292efe2e16e2114a47ef31799e6b522b199dd1b7fae57c05421d86c6108aad6196ec1d37a6a22d9c19ad1f831a8cb3136737420596588d4e982045a9ddbf63a0d062c03614907ff69a3b4cc02ffd64be192b4480b56cb2096030bd6714421ff1ba40c3165ae", "SEC": "041db3d797b796dabbc73692f1f49ab8b92739f41c02b9e8d40bd0975bd216cae71620e5b4bed1781b847ad8861591295ca29d27ae845bf70c651daaca3d40f956", "TP2": "04106aaa420c8e170f2d1e602116b15c1d35dd986a3245771222310607cb13b1611fa9091ed82e5a6423e6e22cfa38ed9143cfb0931a736b1d65eea12f52574b85", "TP1": "040bc5c8dfa5d5662e743ac13fa9d1c58e3659a2c4051b9f653a9f67e3419718561768ca86803c445acd58cfb222d1d4f63209d2ba1671ed5aa9b324ecc8417f8d", "CS1": "041216db093e9e84cc1382f3c71438c97e870f139e4936214d6aa1379064b133d710d1fa65c0ea77a2f15d4516686f2ec81d83ec8a30800f07b755f6f4b1a9171c", "CS2": "04125a1fe9ebd6cafd3fd9d3d9188147effe39765ddd6b17ffb81c55c140e774060676511c9dee969f4e602dce6e82d585bca13051919c0cd5cfc80151e66f12a3", "HASH_MPIN_ID_HEX": "007e187afdd5168c6f43e42a3c6171b23eb2e18ae0fe8b48d7da0c6a87c18fbe", "TIME_PERMIT": "041bab8ea80751a601746df014dfb59b28c4b610f9e9a9edcd8dc46dbdc20e24b0227322deb11c3a71f7834d4de82d38063746547337d28a8699d303679785e9e3", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34375a222c2022757365724944223a20223936323039623636373433663265383638663536366539373631376337323037406365727469766f782e636f6d222c202273616c74223a202261346133636130383832313631643939227d", "TOKEN": "040445b984f0a7d11ae13d89087aecec126af5b2a2b68655e188ef7a99cda751ce1070f350e268c8fb7380003b9f9e7eb834986e3283f3703ab54d89f20449dece", "U": "04120b3d6fd1303a8adef222fdb9d14dc4857906cd1a6da26a8db8371b5d75e6420215d2e9ffa3bbc0cc08cd22d24badcf6fb776c1fa9d5bd86716e2ef1e552917", "SERVER_OUTPUT": -19, "V": "042294263a0d5022b7e2ca957e887272887f6d8ba58a84e5f7ed21f4a30cf295261e9259bf52a2749d31ebd992c9242098a12aba99ef8bdadc990347303798de69", "Y": "201a51cc46961302a369123ee31efcbdd556560a7a571dce70f4d59d80e4ea47", "X": "23d675447c2afff5681552eca025a4e389f7a693f13e3b64ea2e0195e0c13ccc", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:47Z\", \"userID\": \"96209b66743f2e868f566e97617c7207@certivox.com\", \"salt\": \"a4a3ca0882161d99\"}", "test_no": 148, "UT": "040e859aca052aba74a66cca945234fb6295d9c733911eef61a6927a17436ab5e4134b4c3f5351acceff51bf66332eb84f3b1a7c068b2ba90beedd5e86e0c2812d", "MS2": "1c30e51251fe38e824b08e5a797f0902b5063084b6c5ac18f16f90aa954e4863", "MS1": "213e9be40594dac90dd6084927b1a354443f832bf609408009dea88b6d6927e3", "CLIENT_SECRET": "0401f60882d09a6c6e6ed6f18d9b53051ec67122f14a09c5d931f8c427449fa2ca1cee2077fa7d25e0d7d0dd935f2fcbb8f02d7c4ab3aa9e44572b56b57840cd68"}, {"SS1": "201762f0317cf85d97a7af8efde13c8154334614158ab1b44053cd9d0af1dd48197ad9ecf80d978f39ebc920f9ac99bd88961c4ce78d501f249374445809825c169be29d814925fede59e7a1de3b1ea9774360cd68564461adcd61a55dcf89dc1da28312f614cfc63141c5ef752d2f7260fdfc88d98a914951ba4dddfd40bc38", "SS2": "019415ce2036692b258f12efa11a98a6a363a2760219976b249357e33c1a5756183636fe7bd46db7f586b0a7fed8fd4b6ce2db0d62b1677e2ded6290441cefac10c039057cbbcff220ff71dc436390dbf1f14af6ba07d2a23b5932484470b69a1d873dcf920643012c9e3c4dce2a6b913b2f6bedb519bcfd82b3fcfbae8c7a78", "DATE": 16574, "PIN2": 6350, "PIN1": 6351, "SERVER_SECRET": "15ee2cd0b86dc5699821b53f064bcf982af8b8405bae3e017df4b8511c9d18471814bcae714fd6532e45597c1e8a1161c20e90d93b73d0629ddb51c3fd7790181fddb874b1094e038f9341c93039358ac009a29d87cc01229286578b14a76f520895fa166de83be8dc14f56bfc81a0835bb7bb3fe99a586606016682fa3954db", "SEC": "041526aa75df54c6b3bc1282c772569dc691550550e91feced49751695262c199208e8cb9254708a4fced4e768edfcedb41e26dae837ae23b8c0fb9b0759dae926", "TP2": "04131131ea21fe7c1ae1c5074e384f2a2cfbffef1c7119b070f6fa605de204937f10c0e355d7db9ae38941b3d503ee7f3d1836711aa856b50766abc8e1ee47da59", "TP1": "042137412a02e8a6b3b24f254ff07d862b2707aee0f21501dfc117ba19cf4c094018eb860a1fdc0ffb1a0ed74d5417542870b1524a8946ae6a7f2914da6bebf7ed", "CS1": "040d7484edd9d82c8fccdf5a0e943c6c74122f978e2078654f18c60aa6420d5efe096b93069951576385a4ad4603fa5acda83361f6d849bc2a583a9933be7169ea", "CS2": "0410614abc7f1d6b9019b443e37bbd3f6cf198acf5f5329c40765071723d07c9f4026c26eccb3167518606a9794b1bcd5b8bef12d6e1313b57ff0fb0d62ceaf505", "HASH_MPIN_ID_HEX": "4cc568f117a4efdf59f24adc656b52b34e3cec6db2e85bb6684cd8401ddcf63e", "TIME_PERMIT": "041a5eb0b5105e53d3337961640be3ac37d262801f9b7fc300574c4b64445ec95501cce1ed3ede9b57af16bea149bde8f8955549b9e3bbeeab90e5a86f462c16bd", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34375a222c2022757365724944223a20226363313935353939326433626462343164393062343838386464373762343433406365727469766f782e636f6d222c202273616c74223a202237366534326234663039323638646335227d", "TOKEN": "0406acbe27d89121cbebff3214ed5a5a315707f901f5db03028372de057160cb8d0d0f98343f879f9b925d2d605e9db5712ff43b0eff374004938d1f9d0dd7a9b3", "U": "0417759898ddb3520fa797147e22e9f24966113750d9d79501da23d5f2728921f71f353dfaca0098aa1ef813895013318dac44b17e6dabf5510c0901a37c801089", "SERVER_OUTPUT": -19, "V": "040490bae2600ad6e6c16f16d169882c13a7eb399029714836c86619f0f32f6fbd1a4a21eab6e826e00e57559fb665493866b53e122b9be8f55082349bfbdacd7c", "Y": "1396c8368292a07a5ec1e944685fce57cc4f3879617c68a394b0c30da431d5f9", "X": "046b0ed474949c19388d02ed51820a9e66c709c35748a78b85abe54dc0734a4b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:47Z\", \"userID\": \"cc1955992d3bdb41d90b4888dd77b443@certivox.com\", \"salt\": \"76e42b4f09268dc5\"}", "test_no": 149, "UT": "040d28216fd86c4c00e1c453c08d0c5e4f3697a4538059ac6c2413cc8a6b2a1ec7052899c386e78de0e1692489f6d1e9f0b0254b484f19e8a67a9e39a495501379", "MS2": "122a1bb9e7edac5ab785d43cc833b6049caf3b88b9367943ed7ca60e6ed103ae", "MS1": "13b40959407d4ca3b03cc813ae4c4c77894437904bf791e869aa01094e64a447", "CLIENT_SECRET": "041f8b6633222d673382decbd87401826ff59a871f492e338bf82ea383e61d92b91687ad1df7bb33cdada8a39dc7ce9d91f063f7327301f86c24ec56c6c64de103"}, {"SS1": "23dcd8d0654388eb853395fe4aab17d53dc110d4566d596df454d64834a87fbc084c8ba880adbfe65f75351e96024ed7893dd8abbd047c4194fa2affc496016d027a2d6c6cfbcc9b6cab6dd892ea9f8b9ca260f6a104419fd5091942116606142366992c274d98b24848f0db78f74148145577009d7b75a5d8667e859a2a1330", "SS2": "18bb48534e46967160f8985f1a4381b5097f4691288732968bb715e6c04169c61ad38609dd4df8edecdb083e9599dcc330114d9ea8054acee8fd2f161bada28d02392109c1ba811cb9e4f60b370d82999a44dbffc9def41feded10e3b0d6073514faa3772174432583c0b19347559cf34ff795d7c46b5fec7788dc41a1203aa0", "DATE": 16574, "PIN2": 8857, "PIN1": 8858, "SERVER_SECRET": "049702ed0ad93b0217f506e059be3903efad0a1607eae833b5313a2811376f531c4a58d68f83a872b241e44edbc06a5cdf4bde2696129bd7b1951c1bab4469361b35b0aca1c79570afbe117927faeff81946caed6a254641b33c527b87b998d812849d8f98cdf3d32028a5bd15eec61301354989c6f42dc5018729306cda6397", "SEC": "040ca2208a482a8d77fe3931048891254a9d97555e04c9e40be655a81ff4db4c2621166e501c75515795f229cce936b7e42948a0aa5ae50dd4d597710560360c85", "TP2": "041701e2c54b8562579327a434c745aa00c691893eb6155decfe26fd766972a11209ec463b15b6d84dd38835700d3f274c6792d39931fb6940aa2ea4aee5bfd9f4", "TP1": "0414ed843660b29847dd619377f1c4a72983ff2020240f5b8e73b5f9df0c3ba9861fd758da9ad5c1b4c8bcef2486552da615f9d6d7eecaf082bf684e74936154f7", "CS1": "0421e212342c55c0691c3f57df3ae38ed7a98ba24f411bd9221aa79d244f75c30e0aee59f8f7d73ee26906daf92dc5d059a70d6c8d9e78e23f7f22d42826ffe422", "CS2": "04164794f322fd99effb18fcb076f81359606a3fb88dd28131422996ef4c55998509d7aca685d91006860cd0fad6adf060471500f51b9850c8ac9472c356162207", "HASH_MPIN_ID_HEX": "0227b58f21dec8a55dd751cebbf35554e642bf4e58894cae0613cd13792c474b", "TIME_PERMIT": "0417cf27b0a357bcb612de2d42108b0276b88c62bc3cb8181eb5c6a844723b0df4218b02fe6ffbb18591a1cdd6c16d85961f093d9b0257d8df887b3a517a3dad7d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34375a222c2022757365724944223a20226534333462303936356463663135393564616133303561633732333639363365406365727469766f782e636f6d222c202273616c74223a202230383732303133646166396464643231227d", "TOKEN": "0405ed45ce5f03dc9bee2874f487a85b887aa74e374f6ee881247bb1c5764d715613127cad871064a62eba46f144a5354a960bb808983c8333ac31109b8084f708", "U": "040095a79a4bdac91931adf68808d754ec1c32f394f84304d0fa825ae37ef9a4020501ebab53a3b6f8ac4ebc9b42d8bfd15a6976e157efbdc1857011bc93a5db92", "SERVER_OUTPUT": -19, "V": "040c31a2936126dd31b369bf5a79bb06e71d89772addcdc7f674b30bbee43b166712c3222f0ff4a9368c57f4a7d51d9e752917efa861a59127f584bd85b1ed0672", "Y": "08e729961ff00c99b2d8da1473cee8c031808aff9254885e588d458222f2b5d6", "X": "03ed50fa9501a5afcfde060f217306d8285140ccb0f05bd4c6e476bd3e9a6eb2", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:47Z\", \"userID\": \"e434b0965dcf1595daa305ac7236963e@certivox.com\", \"salt\": \"0872013daf9ddd21\"}", "test_no": 150, "UT": "0410aea41ffd9cb8ca3c04dcfd679c7a92934065cb41cda1fe6257c1794e3f221f0434ec656faf4614f7fca2661bc21ea4a677902dac38d00425e3a72ea5a4db4b", "MS2": "183633580177ebbca585d56b96dedc0cbde3ea874b76c85571b6107f72ff922b", "MS1": "140afd321b228d12d5be734e0841d5f9bd933002113e7a4990836a4f8aa873f7", "CLIENT_SECRET": "0420e26775029546d8aeb9a5fe1fea7c01cb673d2fd004211fcf9b3ff4af3b7dc803906292278c31e91669fc3028b9315de223f4b76c25567c95cda41604d31779"}, {"SS1": "01f7ce2fe2a6eda27f818b62827bf0d08bc5b5b8e077fae8a8d5831a8f26c0ec102cbf2ce26a5fc22bd4e972b49ec1776c8e29d79b3936f47c1c11c2b5adebb7099b666fd4b26f3bf586c04ec586f9459a312fea234db8b47ae8599a80f4e63d11ca0648974f82173fc397ac2f8ab0c0c64b77fce812b58b951caccc95c92fad", "SS2": "1abdd7cb66f87d9ddb5ebe6332f187e0f747f3f3f2db0cdb8b206290b66f90bf06a6f56c8cba9e45a7327b350b0d72c82089d547b20b2f6aa2a86a44838b024d054332d78aae737d291393c5d4744385f0b30c7d902bf772a5feb8b8ed750660194fa3748b5b9e74806deba9dc0862d6c8bb3ba3b002729f93643681e7ef0019", "DATE": 16574, "PIN2": 8986, "PIN1": 8987, "SERVER_SECRET": "05b4b55929355e0027122acea8755d54bb65194cc0e14efbca30a9583b5a712c1d66da4e7e428602d00225007df73cc664ccd3bf77d76052b05967a1ccde93e31b940df5481cb363217780e70a8708ee674eb5b3a8aa7e8de8e0762cdfeb77530bad2ccbae6d9bccbf703b24e4423cc96c39f6e26f5eed280784a3edc57ec892", "SEC": "040551e0c93fcf42e1997ca93663baa3f0f731955d5a0852d2840d62b5bdfcae160d7a9a1fa246d38a7a881c5265e94b4022958e93f95b53f9b524efef78286ac9", "TP2": "04073dbba21760c923de667531ebef4b5d36665c1679e512b86bebfaa1cb28e0891ed6b3517e2a11faa574c78a0a3a200209a9b8c248cf98d84bbede2e148583f4", "TP1": "041711a2c646a9c4ba76229ee75063c1b9d1c09216d2b44904e5a225c0fa29fd4509667f9d3cec50fdfe7c7d4842c098825024772d2c9e4a20b873953901b98d06", "CS1": "0409e72ecf0e35827c2f041c4eac18e6a2a9aa588af7407944907ff3abd9ba1ef8049a5a5eeb7246b3932cb5849b4766c4f9734c7749f610f015903234ecc9373c", "CS2": "0417d8cdf0b22ef19700f74b828b9bcefc6f48601111c136fff33123f5c994ac2c0d72891db424db7e32dca5bb00d3c088cf0706d32e08e1638a8faeb53361b5ee", "HASH_MPIN_ID_HEX": "3db59e427bc96d1a6d1b17e44e18e2d59de6e85d0bd0149c55cee96606beafdb", "TIME_PERMIT": "04024468132eec5e31ae89fb91f103a4f5ba700c016a8905796ad24d3f6feef72701f41fc763b4ac3fbda940fab298caf24bd038f2c3255ffb8ab7ee069fa9e525", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34375a222c2022757365724944223a20223030653331326531343663663966656335666466323037633539636265643139406365727469766f782e636f6d222c202273616c74223a202235623836626263373138616562333039227d", "TOKEN": "04026de35e0502f0485102667e3dc700d90b6fc60beec7cc1357f4969faaf495a823dc43d2e6a9f4b487d062963b112112d73e4d98b61b8dc6d897f7045b7ce6c5", "U": "04109d95e23b724bb56febce17c8f70ff1aeb3a8e9fdc2b922c198d1633d6fb6520294dde6ef2b1b7b90e58e2d438197243f794f25796a61e4fc31607ee0fd2321", "SERVER_OUTPUT": -19, "V": "040b7f09e1a8f4a52f81d0a2cdf3c9a3b73ffb1ac94cc31bd6b89143676221c7fa018ac01ad76bb8ad2ded61c41a5e464c43902ce04edc6bc41cb8cd635e2e1e0e", "Y": "0c0034c03543a0f76416f351761d48dc283a5fbdd48810e65e55d3c1aa748b18", "X": "17bfe60e15e2c554dee0c5b89b20c2f9a40d909cbd56be06b1e95949000d7e06", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:47Z\", \"userID\": \"00e312e146cf9fec5fdf207c59cbed19@certivox.com\", \"salt\": \"5b86bbc718aeb309\"}", "test_no": 151, "UT": "0413d8eb927eaa9f705eb54a08f9b373c6167284c152d84d9aed0ae646171ff1da1e7874c19b218ffa3f792298dc192674edc5f237d3426d297bc6c77b69462d4f", "MS2": "188ec3d33b6c8de0e8979d316d9b102e452e1a7de860f3f87c71c53637bc704e", "MS1": "0b411bd2801c80db3ee60ce4ad09f0322975070f053c6a390dc79bfc9fb0783e", "CLIENT_SECRET": "0403d6598bde80caf714cdfe2089991e7a700c9e58bf49747837d13589b70b0bc209d22617e0aa99bc91c82b1ba45d9185dc4c042289974a8d05cd9856c4edad70"}, {"SS1": "18e39d8f39dea8526753adfb500ab334dc2b31d00d3e292ed764e5ab494830d60a238561c58774f2ecf203e6d6192ddfc66cf8f3d286c47f3f8396ecf19ad7642280afd2ece120cbea9cb9f1b86b51937cfaea56076d8fb9a14a287100c9a1d81d81c35efb35d2180b7fb81517da535204ac775dfae111e7ae27b45d970cb304", "SS2": "0338e08648f81c6dda47e0513b28b9474dff0d6134ef395b6b1fd19c90c2ba6d1325831a9fcd59dbd6dae420f58317e3adb16a25e99372dbf3b36bfb2c2dc4a90c4f99e78c188130f3d3eddfc7aba1403dfa8a46180f299ebbd5e7d7a88a5fe2042718045091f34e488b37f0203af8097e4c2634ab7de9beb49495fff196ac5f", "DATE": 16574, "PIN2": 2587, "PIN1": 2588, "SERVER_SECRET": "0129af9f3fd3142c85bcf91847dbe6a7bde544125815528fd5caa6287432e78702bfcb343cf96e4f0958080e07cc9cc2f2c9e8c29fb5b12428b247a0f7b620f01c0f178d6812fa900e95f9eaa1c6a6939ff623646532df0eb154b56d59da2beb1c788a5b2605d5b99972bb17751c83abae935c756e1352f279ed0ab5ada3400d", "SEC": "04020ff5bb4a7086072d4c66de88e10267db3c3a0a0ce233de51d71224248611b21bda252dc552ee244fc470e8a5fce12bd7bfb62b236f779cd1aa005c71e84c85", "TP2": "0411f925e05e0d39eef13c2d7da0663c48276464523e7e8075f840f89fbbc820b321d7552c8095abce3e472a3a3ef56b635629df1f7e137b4fa2c90a7b213f002a", "TP1": "04097c92b51f0bffae433a331f75ce97e59295556b029891253baaaea7a606e75208f2710dd5745c27c8e050be43beb4180b013f8d5260bd4a027fd922b8dbfce4", "CS1": "040978b294c826c812ad6eadfc554bae2757c9f1b3a8aa6424ef18acd9a4946bf603f7ebb07e26cf91a44eb1d3aa0308b8e17ba10f44cc791735dcd8a7e27dcdef", "CS2": "04035203ed50397747315f90dbab89c835c9d42d7674855337670821e3d9b87d5d0d38893d06969b14f97a17aa6486228b412a3743d6de992333e7fbd66c9a1237", "HASH_MPIN_ID_HEX": "cfca3b74699510cb07fb528af442430ebebf95cd614ce28e8a61de78b619f531", "TIME_PERMIT": "0413e46d7167cce11cd118cc22ed6aeef576dc1e8cf5ee2c9b25375d37891b57d502976004ab8d725919e329c700bf987ab2baab08c809b0970cdc49c4b95176db", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34375a222c2022757365724944223a20226538616164383964633963626264396537396361353837326332633535626438406365727469766f782e636f6d222c202273616c74223a202264306566623630353834663965636161227d", "TOKEN": "04056da14440c7755318b354bd9e6ab05d57f45527d44499d6ac34e6ea42c217331047be3bc5ca6d2c312d5b203924c95ace2f3563ccfc52ac72f96d6f80456936", "U": "04116fd02e6461ecf9820100e27ff40c0a77fdef2f0a0fe87a9c3c207039e3bc041f10dbba3da56950dc1cab51a5e52249b5efe2ad8462865c7123795ca477ccdb", "SERVER_OUTPUT": -19, "V": "041d807becf63df6c489c855325e8b5b6af9ff40e0e6e08c731c319ce08f68521706f039d50d42e4f13a0dcd0e44ce7ee8de5f0c402d338199822988ba5c2721e8", "Y": "183679131dafcada1725d89570b63f77bc950cd61edde04cb9d9c5db3d0456c0", "X": "1cac0a8c0feb7cfb658c4120f4edc5cbabf3b97c1d08137442215eaff3d70b59", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:47Z\", \"userID\": \"e8aad89dc9cbbd9e79ca5872c2c55bd8@certivox.com\", \"salt\": \"d0efb60584f9ecaa\"}", "test_no": 152, "UT": "040b8253b61833914988dce08811ec5b700bc936feb39ecee9d1952648535ca11a1af1e0e8f1da1292b6d133a5ae999f0ab622a410c1bcfa2dbb8aa1e35b7d6fa3", "MS2": "1136a7d9084838c8ea16ce03af6f25f4bef0b51ea68424766d690bbd243465b2", "MS1": "06e9b7161799cb768eaf7cd11e349cadd2b3b5d1f1eaa237e12ec650a406efb9", "CLIENT_SECRET": "04031ce6263757a629de865818ff56ca52e10cb1566ffffaf9a2c4c6d27f89ce6a2268b6d3dfe24b94d55be41daf1460250f2bfe811850485753e84f060a65e975"}, {"SS1": "0cf71b6a727a0ae73e51d4d623a8e42b02797a5bd51aadb5dfddd236a99e9f8e1d75b42f6c3f53e39513feb2f5eed4df3be624871775be627a6bb6a3fba94b4c07409bcebb530fd162e10ed1acbf90f17476999e22f636e844ce6b65785bf0f40f37c8d5a91c0ecd49fabfaf3e41d4811944d02427763392055b80a252b53e89", "SS2": "1fbcede0aeeae8de4d3dd4ca42845bbdc42d1c073d37d2b1f6ae3e0214320c36232785523559669fdeb5004605d9d59a9612e96009cc2560dd98e387f549afae04279d2cfbec9eec72dee62faa8d9b0ab8bbaa949ff581e7e275392fe9a7573004ac119fa40c52952b3591f571909404b78dba91166a78fc5bb818f755b8cd89", "DATE": 16574, "PIN2": 4116, "PIN1": 4117, "SERVER_SECRET": "00167438b27ddf3026d448bab38671642ee41523e53755c4fca05fc9459e9daa1c9ce850de3f0b639b2cf7418bc1373f2fd806b8456d4f70a824f3c8344e781d1e13966fe209d226a73b24cfe50b1813b09ffa26dbc4376cab3f621f1cf258521e27dadcbaa40f150db85869956e206d01fec631430b888fe782f3f42c9c2777", "SEC": "041279daf2f1e246c42d56becd08930bfe5628f2f2894c09482b3ccf4648818e130fc291e5054d7c720881568b228efa95ae4bf436c91e1e9dd4299898075bcc8c", "TP2": "041ce691098d3ca3a237097ff95e4e9b3130d5885b756f35d0ae5470ff3b6ea7d8070fff716ab2781fe6e6a4a3f0312f356a760def311cb89fec5fbf18cb98584b", "TP1": "0412791183b27733c58b03254abcc5f3458d4951608e334f0a5565ddf0c6001acf11dc7a547eb7c8c5d5bf093b4bfe99185cd89998df27cd21e7f0988cc720bcbb", "CS1": "041a86c9b655745ebb8a5df5b7122eb3b3d9c3e0c83fa417a51abc21ae26164d880dafa6693b87d2730a2172832f6904f072a76a841cef83a2527005c3317d0fbe", "CS2": "041277213da928bd02a4a33c7443a5af33a901e8413a8cfbd306dd21d70277acc5153fca98695e28f334c2013440deabb728efa091b64682718bfab6988e306106", "HASH_MPIN_ID_HEX": "aaead7e50bef59990c7431f569225b68d40b1386dce956c502a6005948506cd6", "TIME_PERMIT": "0404326468118ac861b099eaef375b8bedae5e13498647c380c3d6db769671e19a1b5ff08347dbda0d0133e0cc660ee6ca93acc5886fc53f6e5ee75b3701e78c58", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34375a222c2022757365724944223a20223962663034376565396135656534353733666431663830383031626431383130406365727469766f782e636f6d222c202273616c74223a202232326334363664323362336634316462227d", "TOKEN": "04225a900ca37aac102373c8a0054c490a46f46b76d66d8d59608a85583b58518219b67cea0812fd510dd54e36cc371f18338c45a640ff33162d5a068dc84b425a", "U": "041c9924e83188fd6de41ea88340276da449e252549c0bc1e1f92b4ddcd9becdc30a4f399dbbd855dea3caa1e540823b5f02b24f46eef626a25b3492ddce1c2233", "SERVER_OUTPUT": -19, "V": "04086561ce3151541bb9a7b89e22ed796b89aaac69f6d512f0540dbe959b51b1dc03f8cc3f1cad5d79aa2c6c8df0ca8712e2b74e39516bb7f64642f8b2f11ef5ce", "Y": "0e2207b6ba67fb89af60c89ef739881d008eee725a5bb5d36164953367b62c72", "X": "0a930cc9f09d4ea20a1fa3f2cf2da0456c50578484e2560a5e9ac2f414105dd0", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:47Z\", \"userID\": \"9bf047ee9a5ee4573fd1f80801bd1810@certivox.com\", \"salt\": \"22c466d23b3f41db\"}", "test_no": 153, "UT": "0416f205d7fbf7f31896cdde5099d10e620285f7b5e13d1341065eb51d20af7d001693d9f01fadd286f46cf3a8c0361988105988ee3012a18fc79c7746a70dc6ee", "MS2": "20c736cb9712d4a5dda67a7a738c7a94d75d95f102b3d0132e89c2128697b123", "MS1": "08255c145299093f0e240574a3f05f778c14b61992aff60eff590c7d68541066", "CLIENT_SECRET": "04086d1771b9d66ce7d18eaed2b4860fabc7320a8da4f02b55a0f000d6ec90162d1113f2348da4173b2644cd4e0949c468fa37de4773f8681385435d635f7e63dd"}, {"SS1": "18c6540a5723ebf8becc3226793f8c489b718cb8de26e982661ed732d485c87d0b4059901facbe3a5123d6f4e90d8bb17e964c1e2071bb5ed8c198dd0e7bbec3224df35cb3ad0425470a0fd6a95a1c8f6f98a96d6a91f97dcc799c74a813112b185591e976e52d265f4a90debbb7cb22e1f754030669013e8dd45e635a5ce0a7", "SS2": "0d57bec8d734e20765a06f5cb040756532d0d911fb6725350ee781d50868ab8618d80a5cb38f2952efaaff2cc6b806dc623fd4512b8811a36808b91141e493dd06bfea90036ebac93c53fd0f46f7719818296b1c5187c3f7f0a2ebabc2f7ae600e560de1891a1ab0a3a779f8bf01e2be606fda03a2b35cc23d0609d1425c5a39", "DATE": 16574, "PIN2": 6000, "PIN1": 6001, "SERVER_SECRET": "1d1e4e62087529e840aeb5b61c47dd36064e33bee5acdf7a28d868521ce7210218591ac53ec9b16d5ce6982da282853692b663c7a5722da5fb9c30961989982718931db187d74b7d4a6efb8db7449fe686d2e99a7f390e1716450a4768d1300103af57945e49989d071106f4fcc19e93d5131a1330f6b06928e82aae4f018c5a", "SEC": "04236dfa085c58f071d6c40b431d4cc771486b6b879b021a15d7aa5b669381ca0d00899c78e765ae449ba5b0c1d51240601ba61ec9d8639328a7cd6e0dedb55a4d", "TP2": "041d28336610512c93997dd19d0b1bc9c3b4c401a178e79a09521e4d1bd29cf87018824e06e07ddb842e32fb0d8c2cddba3d7c404e2bd9e6382831c2c3114636f6", "TP1": "04116fe74c460acb4016d323858094e01b954ebf572c6f46b72658ab24f22db02703a106385adb095d59e663c84bb06b4a4d25006b365525c77d274e79a9b3ffe9", "CS1": "042198d6e9bd0f6d2318a402ac1c65c9aa4003e8fe373b27e0ec0f2e76733030680857bd8195733989c9451a7b00f161dab07f61a0fe2a1a7a7c6bfb8541c42c98", "CS2": "0418e66639520cc3938e95badb71e8118d9dd101e6c99acf527a692b733a9a90bc00ab8b6917383a77f910553343013d8fab7bfe0137c21c05ada79053b2349710", "HASH_MPIN_ID_HEX": "7e3f90a7d5191975c975c69990efde49467d08c4026ebab7b6cfa372fe38d7d1", "TIME_PERMIT": "04077780729e0f65ba2f8ee02aa6fda9ae8bcc99999bb0e512a7bb96eb3de24cd906b4f00abf606edbdba0c131143416cadef3e1c66fcceb12bc54e5790e2e04d3", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34375a222c2022757365724944223a20223065346235373466363434366532616366383764313566386337303538313933406365727469766f782e636f6d222c202273616c74223a202261663833663966333561633436303736227d", "TOKEN": "041fb41deaae8bc357b160f08bdef95e5b6f62649f5be012dbd443c4d88bfcb0bb213a6188719cfb47202491bb19c6667ad2133c3298faf78a7c077def7b31b93c", "U": "041408e04d7a576e75bd15696993fc4cd7438c5b28ed4e8f27f3ad2afbda3edabe1784b05c94452f801bb40c1398ca2bbcf919583dd20c3f2347eb2ac42ea26175", "SERVER_OUTPUT": -19, "V": "0402512bad5fbe0ef3542ff30bd3c96951f795351a38df420c06c59f5f241ef7b11c43d2b2df5fa1bb6843c6bd15695890d0e5a24668dfb641a2dd3fac54d6123a", "Y": "1b8b57ccea81a040287c8a154be573808aebf96fabfde8a48f81d56d52a6e966", "X": "1ed7982a69860282148d72f6292ac3e069f54e0f4814b2fdab216f425372136d", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:47Z\", \"userID\": \"0e4b574f6446e2acf87d15f8c7058193@certivox.com\", \"salt\": \"af83f9f35ac46076\"}", "test_no": 154, "UT": "04014f57da53cea28d38278307e25ca1966e9462900379cb94e78af05207734efa0c33dd3af01eb1ba2ca48ba41045b0f95c069ce6e3fa12f82861abd46d170da8", "MS2": "0b2352a7a5d411211129d36a5543fbd5aaadd59e6fdec780a2b5ae48847c2511", "MS1": "1eaf8021283bd5c85b9373d942fc1d96d766b7ecb8b8961a3ec66aa0d85052e2", "CLIENT_SECRET": "041caaa7e22344a95198be8d14f84313bdc4a0ddf8c9eff44322974926a0fe4bbc14237db5a2c8b317ac3ca8fdb2319aa192ac14da0784c55285fdfc30976abb97"}, {"SS1": "213c2085b68ec2b6c2d0c29593734c580fc6fc32d76442be307b4112dd23086d0442d81749e4dbc8bf34380066c299f90b5f1a35d4984e15ef3b3ee4ac11440800fe570f4372e7185142bdd1102e16389523323ba2b0608fb51d85edaecb9c0f11157b8a680d62313a94a3dff9076ee98f1c025d82303ce922f5d3e95f69311f", "SS2": "23e74a26bbb9d3ed669b22feed9a9c54e5fd1c5f22d58cb74e3ef9c9f425bb180b0b40e06679ef11a35c65f058283de3dafd3699535212fbd5f81d01acb644ed1c824a113d75a34d2d5cbc867c9a46758d1d6cd8f94b130cac7958eb70c05ccc0482206377832072ece118cb6103a5e844c230b830ff9a8c1be9afad0e63e389", "DATE": 16574, "PIN2": 4919, "PIN1": 4920, "SERVER_SECRET": "21bd7b74604df1c38564c817a0b6c6060ea435cb69cd551e405fc8a6493aea4318511029071047461925d26f52c586942b72cf66b79242ecec58c23656c7ff4013030d16250ee7a1e2864aacac06ab8885111a4b5b67f495b8712944d70ed2150990a1a2beb59feec9c173facc76e15f7742f9280a0399d574a1cf20276c2cf0", "SEC": "04021f55a6c5aba8529b3f4cee0344b1c6afb027eb2ef93b2a6de1e085cd548c0f09a1c6679e8695e00770d2c75b6bad7380646c17604ba63d405cd506e63d8fd0", "TP2": "0403d46c5c59a280481f8f220208e5d4bd1a6b6b89ddd3357a1ff0a8b89fd69e6f0dd803aa59ca68b193917d4e9c538648e868c636f427eb601c0499bfecac1e27", "TP1": "041e29ba0193a12745365dc4e8e08b72e007da05bf7bbc95f7f8cfd46b9fe2f5ba0f998a12704d83651e6f5078e1403543fae0823123f98110dd249d2ddc5d53f1", "CS1": "04115d86fa1c899aff1cf70ad2390307855df3014ba2eda371169de8e19f38a56b1739e0bf19b03a0f7ac5299089b27443ad370eaf4598e1a476aa0c6c30f6b117", "CS2": "0408459ce53302ff2eeef84bec69fe3acb87e06d84901f206890a5e888f8c1501e0582b306f108013012d6d266ccce508f36a50ae78b23183d785f04b6b1cfc4fd", "HASH_MPIN_ID_HEX": "e86d5c93445f231b7af6eb4a095b71ad077d3d4e89e1aba055fce0c7b20a562e", "TIME_PERMIT": "040572a7740cd13f1b568c3821a8288593ab26d8ebcf95962a2f2d4123ad76592214d9c8d08c2d8e510eda8e49f820d8ddf301b8fec50915d6f391a25380864cdb", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34385a222c2022757365724944223a20226461303961323438363136653339343834323566333032333466396131393832406365727469766f782e636f6d222c202273616c74223a202239663330373939393062306238646234227d", "TOKEN": "0415c348236b88891c92a4d2c8e411324086bf41a26b9127d3e8708da693c26d9b11435557e336cbbd9f1c12a52b65e37f11cd980d4bc807324144353da09fb72c", "U": "0402c9fdb4a4cf8404a317a01a60c3d37d8037d87aede9c4f53e4fa67a16617a3008a9a0016731d262f6aa7da32f81c9eb7ab99ca38ff11fe8688c1c19f3c28097", "SERVER_OUTPUT": -19, "V": "04025b5d0a96e19655b25f8c2e1f4b7859d5221491e4cb01b30a5846c19a37b9231f2c52a79fa5e74ba0b24b6204d1939f49cb6765fa7306c6907f9593f6a73365", "Y": "1740a7e1f08af5b74feb24710814b8d3957327cf6211566777dc3a2fd2113087", "X": "074b5f75481fa51fa964763cdcfe77130741dd7b04073c57a67b0f54cdb17e07", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:48Z\", \"userID\": \"da09a248616e3948425f30234f9a1982@certivox.com\", \"salt\": \"9f3079990b0b8db4\"}", "test_no": 155, "UT": "040aff8ebaa8e8bfc0f2c56daf64a453a2233bf7f670485c8a38ca842a9d33a47f1e1e66c3328d45111c9a83b99b92a2779d301d9a89176f4358e8867bb10d1ba2", "MS2": "00227d5aea56b6ea7388dd9a6aa5f7ef62c2f8630e42692777b87eb8406503a8", "MS1": "1e64352388c5e23564820dcd6ead5782c992ac7956bd5db827079f4df2d91256", "CLIENT_SECRET": "0406d2eb84194d16f6c56e739928f07e298a068b709b94da8c8292a2f92f32b979046d140afda50dbbf87121b6d0787b6f1ad36134babe9c4791e149ba36c67c69"}, {"SS1": "179062b800ce830d966ec0b0f9085e2f2f488e50a4dda7c648df6242cb6d0e831499e20be239d7695ea49e052cac6524b180bdc998fd2ffb652d7053409891910301958e8ee7bccd873b9fdfe5dd3e0e213a6bf22b5f1973e1f3fd2f2728e63e1a01b84d6f34e5127bc35d17f83db07dcfc1ae209f1eb4235e30f4295520386c", "SS2": "077139814959875fceedcf42ff4e4e17165cdb18d6781e95e25f0cc10e600f790e714974a2f06c173ef85cc289f5085c26d0a8398d17113be74abf822e52ca86053131bb14ef151997bbc290d7a3fafe317f7f41b6b9b6d04aaf32152b6ec7231c599935c6a4e1518b19f70c526a9827f475a294e439571edcfd8960c3538352", "DATE": 16574, "PIN2": 4445, "PIN1": 4446, "SERVER_SECRET": "166c46802f66b795bd248c625f7621a9b3a67225755fb2c7d34af67d172447d1040b126d85bb2e9215b109a7f92cb5674a30db39e18062e7df0e2c658146b2bc1fa6fe9d9a041ca8ec19a8f58c4cd446616dbea7903556d0b4e2beb431d19aea07cd6bba42b37d71b7e51b3e67a422bbef18023d62bf5b690c0b29a79defd88b", "SEC": "04085d0ac1a7b42ae968daec0618e2e4f92f8e39bb18755e5c683e1124088cc025098d6ac455707c5e7ca819c2c8c01716838e73935eddc07c8d8fa00cb500d5f0", "TP2": "0411d9436749f781defac5d90589e0909a64a12c3af4a66a751db6a080faea0b721280ed5ce4eddb4f9119974ffb2dc61ba94a76f4afdfaa8d7d0d855eb2a84d65", "TP1": "0408265a2d32cddadc626208701347809d12ce10c8b74265e3410714b01dd7542f02c85d6d08fb38af5a4814fe1335553aa5644931d746028e03dc80b9413bc57e", "CS1": "041863784f3d12389bb7e5c40201c0cdb05a013c8470c220f74a535521497c06cb12646d28c8aaea120fc3affd0198ab3d7b01dd942c96bfef9fe8d50aeaa7cf77", "CS2": "0411ca1da174388c683a9eb1e748e3cffe022ee5f78471694eb390c6e14a83cef10ead9ce7e793ea5755994e087c436c5edee972af5e7033342ae08e360e89f1c9", "HASH_MPIN_ID_HEX": "c53d927bf1e5d850cb87cbdb67e46ff8328d101b950ca8c4ea76a94038fb3950", "TIME_PERMIT": "040e4f4f336be8c8883537075601dd95ccd7fc58cd13e05b429c4069da8b7ba3cd1917d2698bfd9036d559bbd5d57c57544c3fb3ba06386253b428b9f6fd6e3319", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34385a222c2022757365724944223a20223566366131636566336338313166383730383566316563623265333336646265406365727469766f782e636f6d222c202273616c74223a202235663465353964343165373937306264227d", "TOKEN": "0420326ef03912ef844ec07df51c40df6e7ede93829c568bc7862fffc96326eed409b013bd753d177f2fc8301952d8680e0444ca3e93ded098c9a07689c1d82692", "U": "0415d6e1fafb89ba8262ed9c858c9ee32c017756ee413dbc563738f699b46d6e3b121da43f545e5ad15faed71a83d755d1c588f363d4ddc674dea08f1fd4608048", "SERVER_OUTPUT": -19, "V": "04196ce77c49332c3fadacc5bdfb1b4f314b825b313f600e7cef840b46117d48d40e9015bc1b4c3c7891c987c85938d505eefbb105e7b370b117afe068abd55075", "Y": "03b1e8c45e993815175fd38b6342a5c57ca24733945afc0ee813ae7aa3f2c09d", "X": "2066b91f4994025fc800921ad1a1798b4fad2fedb1cd0c82eadb9453e84cdad2", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:48Z\", \"userID\": \"5f6a1cef3c811f87085f1ecb2e336dbe@certivox.com\", \"salt\": \"5f4e59d41e7970bd\"}", "test_no": 156, "UT": "040385827d1609f5247f7e5df3463cdb075892a6a22cca80e57cd253a144098f560fdef5e7c873cd1667c233bc7fe867f92fd09abfdbb4d8d2a27be1801c84f208", "MS2": "17d7e5e462d943809ce4c217d87addc8b9022ba2ffaeb62002418dad67d565d9", "MS1": "1d16a28a0c5609e08c023d8926cce8631b7c09467530ff553a0608b82015e2e2", "CLIENT_SECRET": "0412622cb9db7ed90219c0c0ca0485ca2119eb35bf574c8dddac7f2b89559c1034046be6a1b8ea40135f568ecb33a72cfd362a755ae8c5ea868a8b272b3cf3e5d9"}, {"SS1": "0d9d3745d1bebeb0bce9c3a11beea6f7494308fdf37854a448c4d971a838575a1dd59aa211ec8181d60ad43c9bd94d28e1b64f8a1b0742c43b84c2ed94587c50110fb6a10fa4dcc6489d53ac2ef018d26c7e6d12669c8ceb8523548607a3b1140c005559395fb668fc75a846c50cba7635902d84ed83037158fdaf8b82e1a0f4", "SS2": "0fff2b257999495a1dee01947fdf30e77a42ff67a55e31caf6dea745856cffbc0febb812b305592ca52eac6ddc067bad5fec86880b008c0a1bcb81cbfcbc933615e6d9f9865461195c6774692cf2da1a230a0465f18195495227cc40535ef46b1b7bc31110d32d27525b07cd8e3b30e6331398a32be2b242b678a8276d588d7e", "DATE": 16574, "PIN2": 7124, "PIN1": 7125, "SERVER_SECRET": "0c20866f16f8fda0b648d01954cf65ac8d7b19cbb045a443257a018bceccd9a504bdc7afd919cea42afb75862880c8f801692f8e3c6fa948e8c315ae81f3d32622a7f5806af407fa21699ffda78015e9afea5d9d9c591ab8cb8059ac2ff44c5a093a53a799b552c4441a4b729a6ffeb982c37548950cd0e224818377fab1b685", "SEC": "04087f9edd825daac113b5cc52da367a7e338968872d477335b4e8ac9c578581642329daa8645661904a72c5ac5a8e5c5d321ce5af553371fb5062742869c1d42d", "TP2": "04189c8bf7fd1dea4a742b85cb23a0bc1e0b7506e87fa50113e7a4aca133e733bd14170882b62ecbe5f97fd0dc93abd2ae30287de7aa6474ed0f05b909c7dd44c9", "TP1": "040f0f3c3bb18046255d6b0b0b8f98fcaddbcf3257fa4d222bd65feff7dfa4ad6a18d872ff61b50977cf1468c757dc08508ac941cf3b92fbba5df9cfe8628e6554", "CS1": "041f6ef1af8c2a242eb66af071446171840c94250b97d3742e5db06730858e3ca003dee57b9ab11fb94f3923f64b2291896653c4f29509ece3dbb3333e5180aca1", "CS2": "041feef74f1c391293b0d25e73cc9d67e36fefd50a6e5f283f4d171287488335ad23781e431eb25b6ba2a4b585046c297e0890ae5ae40ea6ae5524679590721784", "HASH_MPIN_ID_HEX": "1b8eab856759b1c92c492f72685924c8d58a8a252181fbbd126f0591d259aa94", "TIME_PERMIT": "041d7cfbaa76df049529a1ae44907a00505532bfb6e01aa0d05015520cdf58a3f2074f13453a83ed6f012e6953f7b27b3913bfe11dd20b174b5759d1d05cc618d9", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34385a222c2022757365724944223a20223865613732353534613230343939623632623164376265343963643430323238406365727469766f782e636f6d222c202273616c74223a202239643765336233373239383531303136227d", "TOKEN": "040b72e33c17d28a7dfaefe29bdafb3604c2bc56f1ed309b35321db66883a53def017e7f3338c024b61da7d78a83e7944268c80e22408bb8851951bd5c76dbd64e", "U": "0417c527c86d8cafa4771bfdd82ee22fb86c59e4e4c910040ca4409539729f8f2d1a7cee04d4911cca5e4b09db82f6838f45b411f67b45970b9a00b5df2ecdddcd", "SERVER_OUTPUT": -19, "V": "0415788ae8b10f9834da9e062300579ac5d407b7fd5c3626ae4298377a01d657ad201f7d35069c39c6fe3ead9dcc32bed0025d37403ee2367ca9e9782ea3f1278f", "Y": "11e82d056ad66db48035cc5c47856d92bb0a40f7fe87ab0305dde3450960c77e", "X": "1aa46c52a1bdf4b43d1609e220d09d7cc4ad90daefb7887928d702af913b18ac", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:48Z\", \"userID\": \"8ea72554a20499b62b1d7be49cd40228@certivox.com\", \"salt\": \"9d7e3b3729851016\"}", "test_no": 157, "UT": "0403c88d52e17682df5d4561cf76bb7eed9eaedde55c937e2385aaddb79931da01031013167b3b22585faa8115a4a54a9b78402d965d7cf7e19b731da7f472d087", "MS2": "20f5020b0417cfbf8037c43c840a2e030ff7bc91d694f3e02ad4e892b82b7c5c", "MS1": "211f9b2b9564f490c08793c14fc4aa87810bdeeaee8d5624fb2e0f8bdb26618c", "CLIENT_SECRET": "042254bc9f1931c97db9e848312f5b25bea4df005ff47e68cd77c3e8e6c35ac2f60f1b3f05948db7ad828911640d97309bdef2bafe92f8539e13e1aa16dd9305f3"}, {"SS1": "108b4d1952a015a3996d130c430a3e1258aeb1a31dd3b894be0513d4121f1f94177dad514bf5017d9d0884f45380b2441d6181543840717740b4e775229ace421ff010ccd66a176d84f8e2441343ef3e38ff56aa3ef620c7bd81e34c3f17d5d70912ba4fcb2b9fa8f800f244c6165d4bcbcacdea119e821382b376e08825d0e6", "SS2": "02bf4f68b46ab7df8f977559f3a702991c9ed7c7a9c1f7915f1cd3dc20d3547f0ffe584dde5b33ed1a1093a60e404fe1e07a5098e9ec9cc0e5ea4e7c96be37b301c122ce2c7585c3b2c1122cf813f4cde52322944cfbb77112d38934f0d02fb1148d1767406398ce81d6a120d904b8f484de81f3e3758aa6a3c803fd5ea61c6d", "DATE": 16574, "PIN2": 3366, "PIN1": 3367, "SERVER_SECRET": "02deb44d797bee28481324665430cfa35f9eb236864d594879eff41c0bea39341f8208e8c9c0690788fe7d8de095b157a03f6d93986b265ce90d63f424962c4b0d0533d33514098d1a197f87a932d6a62115f7391b98b0c9eff140565b721cb21e72c591cf88d85843f870dd423f6199411375ff8339fbd29c2e60eeb2684e97", "SEC": "04073506f8f04fd4c793214daee02508d9317eeced206e3ffa9f72df75b887f53008c9746c3ec7be411036b89f3d8c01f855f68411bb060312eece978ad697a480", "TP2": "040d6808ca2c9b65dd14a4a7665340678fa28f2e3103e2b40973fe7cfc5ae2ee75052d6236dba9c7eda2473c2f911ea306d6a45f508628232a0941e531013d81ec", "TP1": "041415befd7fca9f0e1a2861ee990bd1686d09dec79b71498006ab2896033a7eb210d385a44d93fc12fce6b802c61c2ace3567e900d808da282b83055e8cf12c6d", "CS1": "0403e9fc9a29cd80789915f4124468a81a36e2bbddecb1d28407d5a325577ec06610e81d69c6ac3509fde857432b446694265d8fa2a954d75d28dc35292e7bb300", "CS2": "04011c4354e4c9fb06f552c204540f7ab2971b10537b4f0fbfdde88e42b77757db0abad1e4b889c1370ea36b9f0334c3af5a7e863fe28f302a6f6a9839fbc8def4", "HASH_MPIN_ID_HEX": "381a61f432f2693434b32789ff6b795de7d7430aed020e62e39ba14f7a0d7927", "TIME_PERMIT": "040ea4b3282c53450b0522fcf9ed08f0598c8ed5bb00c5ddfa05154d8cb33135981a71645ccba87b341772f806818b326b04d17536c0d899cd29bc82e74d8d99a5", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34385a222c2022757365724944223a20223463656233666338303264653736383461656332633436363738343836616238406365727469766f782e636f6d222c202273616c74223a202231636361303366326135323665663163227d", "TOKEN": "0410c37613e5d12213960368e073fc5c198351852f958349175f19865b5fc56a01070f617b8ec0827ffd1ceb5cad46689275b72b82281666e2657b01f3cef8fcad", "U": "041c8af58ccb74ea7a6f9014d5beebdfbbe5a9bbc8b30a53239e8e929d92148524165dd5e21839e4ca83be84712d1e5ee56c76e1a027f0c17fea2d122bddaad802", "SERVER_OUTPUT": -19, "V": "04082a5e6c1a4b29af75ababd6e206050ce9a00ece74761faed7037827471ca0af228f164f2158bf9900a2dd2f8147e3f08e52f1f5e92a973f6752e2dbc9d1d8d4", "Y": "1791792fd0e9aefbb5f0358e122195afffdd58dc790f6e8f4dbecade28ef4eca", "X": "123bc2f50e534d7de379e1e57039ed053c9e757f3b3372ccc3cbd34ee09a512e", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:48Z\", \"userID\": \"4ceb3fc802de7684aec2c46678486ab8@certivox.com\", \"salt\": \"1cca03f2a526ef1c\"}", "test_no": 158, "UT": "040fb937e43e7b522b2d43a1cb23c7c8b2221919053179f6e0142a789aeaf6956f1c4f89af10d00bed8b6f9453649c4fafbd4e53cf932955fc918361d077ec87fd", "MS2": "1d573d8ada351bc3d27f2faa4ef8e167a3b6103b9a65eded0f36b6e74c2b65a3", "MS1": "00e15b0132b49489aefba76f0a7344047fabf4632f8ddbaf77d3664166602e1f", "CLIENT_SECRET": "040705b96f9120bfe57ba89ff29dc125030307939c297da6e4b7d14255fc3d705c1c8b5415cbcacbee0cc1d6cf9dc11eed2aec2caa1920ef426e7c28bf1d17bd4e"}, {"SS1": "1b4d71fcf47e52d7fcec37c10f2132da959e364c408e13aed9c0a4012c10e4860b8d20371f003a97d5f189edc67469d8f45effc718b72ae909cc8756059547ab09c576a625c6fe597771a328645dd8a552599aea011ca08e6f291004c59163171895ed5e07e2b35c7ba51b055916756bd545b3191788fc663262a0c9d9f4c1f9", "SS2": "0605afd6f94e10e285c38e681bbb958b9db5a827615b56c75e5e53ecea40861f2011451a75ee370639bd2dccfeeaaf2c24dce0dc13b6ac18024045a3f9b848b9120a5901c9687fad4fd5d9040ece6389dff2c9c40e2e9743127d54f79cccc2e71ddbae35a3b85d067358c669a9d4087a1849880a0edc1516debc1491e36de01f", "DATE": 16574, "PIN2": 696, "PIN1": 697, "SERVER_SECRET": "15fc8883230c04b0d42b4bd5f806622a24266aa8c53a41f62978e80118ad5a4d1cca94a861acfcf5ea309da25c1601c2ff040b0b1a07429f56d0bef09578a079037ad014973a98da0eac64b65a14be51a5f8523516e7d25c2a84a7289b78105d0521e337b3d346a8df62d8126ff2fee48b677eda9d1e24c7cb73f8db5da8a6a2", "SEC": "040f5ae4b04068049d3e3486f2af44a7f509596a2f9bde6dd574e534aad2a0daa71c89138555f741ed0ec00ef93f6957a95bb5d1ecfc2dbd87ea4cbc66c6ee4fff", "TP2": "0422682c5e194ffee40f2d3d1bf7e287934db16b64f705fe73808650187bee3e0c06a3f42fe07c0bb1965391c999716c70b5c1c3ff1987dffe0f9ffaabd638e6ea", "TP1": "0412a1e7df91f6b2b2c0c2c8e85a6afe7d0ba3da54b35649eeb6f005bc8350868616ebdd19d5a4e305af27918e25b7c33cf8d4a408c7e96bcc83616a300ef0d77f", "CS1": "0411c24b950d028fb04dc752fa792bbe68f99b3cfb05f9bdf2736a495726dd867e16f6c90aacb5e0404ac3fe1f692213e91ed4e9661c49b91b1f21c5f73960d1ba", "CS2": "04119ecca6501befc03e0975d5b62e22e67cd0200181112861ceed4d3b2afd42f818a1bc3a3955940dd9e645809bc5f251a5c6d02511d2fde2a5ab89c70aa5a1af", "HASH_MPIN_ID_HEX": "9e2ee3c00fd49234f2c505ab0ca8ffc2566e4e527cb4b3cd48d4715565b884ab", "TIME_PERMIT": "040069581d0741784d6b5e403bf4d69ff6579cb564204fbb087e3bcefd25b53d791316f0097d113067ceffd62364d3b6e53a675cb9483267857e3961432a5ba304", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34385a222c2022757365724944223a20223436616539376230353730363830306333363235313765373965396463663834406365727469766f782e636f6d222c202273616c74223a202264303430656536373862393762366131227d", "TOKEN": "041be45c29551c70f59512b4111d78ccf1018387da6cad05da6643dc298f326b3c176205d2cb663bcc0760b18a09f37f4efcb71330081783f99db3bd8b9dbded51", "U": "040a1a933daccd61a4f3fc9a10ee2715b30761427cc6f4370f0ed05f653844933d000375774edcee69fee328a1400f42d8a4559e35f405ebf86fa33f9612037618", "SERVER_OUTPUT": -19, "V": "041ef312e173d02c59da7e04a694f35c195f5e75b4510ee1baa4f61fb1199d795220fe62026e6c014b4f913b837b41b649ef8fd2098cb8ae297e91cd283b8f8abb", "Y": "12564b92252fe1b67f9490f32f656e0fcb6b8b667dcbed2567072323cabdac46", "X": "16af7ae9b47c0918ad5651b9f752148e0d1fd8f3738c07353a94118404ff96a2", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:48Z\", \"userID\": \"46ae97b05706800c362517e79e9dcf84@certivox.com\", \"salt\": \"d040ee678b97b6a1\"}", "test_no": 159, "UT": "0411fcd029d178df61877f31ab143d91133329ad8bf62c2a5fc80d5bbe6ea74e6716e0adad98e97b0a1fdbeef4a2ba4041067c8fdb6e5925d6a4d24b041ccb0e9a", "MS2": "0809f2a7b44cbddaa264223f5dc58304116f9215a60d9391ee22936f6001eeeb", "MS1": "168b56a4f3a80ce27e8890304c73ebf953f64268e55d147bd2640cd35831ac10", "CLIENT_SECRET": "04072393518aef7711ad57fe3f221091e5a3452f465c75fb1d0fcc37011e67707306aab9b8a139c0ffe8db9d2f8bca91aca7824177aa079b6fac0496f474ba5db5"}, {"SS1": "1ead8aa33b6dabceb09549486f5b5c43f0ff2575f7ab5cde696f2ac3e1a81360107747e65c7154f0fef9d463e366c1e421e2afb371c2a5529f612547a5c694c11ae6388430f961adf3ec52e1df9d2b65b07c4ff45693f0f24bba439937aa606722908e57bef4aaf78061fcc1881d6e113294676f62456798d2fa095d6efbc630", "SS2": "228615126005ffda8111997a373486e215ace9ee3c44e802fb7df8049c131c710029afd4252826cdbbe04e74d192584e5131b51470fcc30031541d2be23e83711add45064da6a5e19b5c51e29da6bdf7e99928429a712dc19964b55fd7d719960204a56cc849c6e91479e1894890bdb69773b832c1b5ac08a48e573734e019fc", "DATE": 16574, "PIN2": 402, "PIN1": 403, "SERVER_SECRET": "0328c9e67f09343f4e78e7a38a60d19e3936e3ff2ab32e2adbd8f3727526b2c716b87bf6958a1515e5ea6d87709764057d3910841f521202cc7bb7550afb798010e82891811930dd0187d71d1eb23d1e968fba3948787e6bd5ef01b0919c4b7205d1c88c023ee9d4e6fbb64b80a8d317298ad2f776fdab5448504019a9b59445", "SEC": "0409f5299325be2a9ec0027601c78cefab55e91af17e4e1a8f7b14770917d3158e086908cfc16b4cd5dc9b58476a1e28fede7d4f76bababfff3d389d281d697760", "TP2": "0408bcf116085b252087ee052e29d649163a670e93d16628eb2ef4c8e1001db50f12a236c18d3736b0097199ab217dd73ebfad810d06fe9b36d746ed6ca98b1f85", "TP1": "0402edb622ba205c4568346350670ab22fa19cccc40886c92c5ab3d1f7bf6904291d6481c4e51c3c2d8628009bc25bb6cc801ab873562a4bcd5ee08778c2950b39", "CS1": "0409a885140ad0b11ed3dc31d23761ba83ff64eb4c40de1a52044f948917326d210bd4bba7465ce1d9bcb8956433cb795c0c0687d464e8c88d61be18f9c86decf4", "CS2": "04111a5fc3776177b5e0f6308f423011615fc4f8f0e78997936495258ab41f01b40bc699c83d2f95211216430c7f0628d2b0b2da665cea29f8d57819b4263bc2dc", "HASH_MPIN_ID_HEX": "31c30458ed0b0b897bb077f1e728b10ad7142978a17f03c5fbb2741fe00caf94", "TIME_PERMIT": "0416602b91b05903bda2a37adbd3bde40e2a1261f00749db82c43b73deee0fbe5309eb014a526c3a6bee4d1e579a5fd9fa482b951aa75f04d99be6e9ef179a0845", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34385a222c2022757365724944223a20223732323862323061323437613937353538656265393539633138333962343065406365727469766f782e636f6d222c202273616c74223a202262343935333233346663303230646536227d", "TOKEN": "040ef6263053f97c93c2465cb264c2ca7649cb6958a79a0bf1464458d4b4682ef5162de288b9edc5e918e7e3c6ed807a5990d9f16a725fcc56530bb1569836ce46", "U": "040c6eff266a4087169d15d1b1b04e99dcc52de404b95b94cd1e8b0f0e2642f1dd191588e388d40e5406aab7e81d4023e8efcfcef7e8892e98e2d53a3c27cde2dc", "SERVER_OUTPUT": -19, "V": "04092aaaaf86032505fb0bb679de6d9f79028b18a5e9f6e7ffe376299b6ec8e7c102b61608b96d15a862254c01da66e0a3fcf79994e262d5dcc4f109d732d0c93a", "Y": "00a7eca4f437d6479f4d2bb4c608200aaaddb7e3f383454c9da3a1b8cfbc3b96", "X": "02f1ea996195fafac09bc1f8b6eb74ad7df4199ddef87d5b155fce2855b43a54", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:48Z\", \"userID\": \"7228b20a247a97558ebe959c1839b40e@certivox.com\", \"salt\": \"b4953234fc020de6\"}", "test_no": 160, "UT": "04001902bd93420c1279664248482e8e13039c030bc299389673e455c866b66ea7192318961f8619aa10b25c88c04b37ea53de748f2e3544a088ea6247fcca777a", "MS2": "2364ded79c95d9abe928e2b35ed7814eac9f4e013a19bd752b1409378e6fb9c7", "MS1": "07fca892f3d5227644d551d75fd53d137e803987244054f7d0153a19f3f433f9", "CLIENT_SECRET": "04188dd74c5539211c726d46731417d8018415eaa1de71cf58b3161426fdcf5d0b1acea71a1cd61c667718d905517f3f97fe558638607f7ad2d774b5cd332fb443"}, {"SS1": "16cd3dfe0a1edcbedf0ae818ff08baa494a85ef1ce59e59c17c23cd77e0d5c50011df8a67ea41a41c0a305da19ba0a30884009541773454a0aa7768a9182fb6c22b724c4fa8cc644a3b836920d1722df719353eafe0c19300ce777e6f048cc9f1b8a33852583a52359d204d31087e23950f10d6e46b6580ed0db789356faa7ec", "SS2": "1d88e459f4032586c7771404bc851007e8956d39e44364a9c067e7000ccc2f7e13c1c42581888eda6d3de8c96b106390658dce70b3e91d7be0bb2efd6680e86e17bc380e4720a0e6a0832467cdddacfc47a16f3150230f725ab6588aa5ff883f06ad6ee4d05947721f8c0515eeefc665d08f8ac4a0fc3a0b8542bdf2f8bae568", "DATE": 16574, "PIN2": 1168, "PIN1": 1169, "SERVER_SECRET": "1f21ff9519fc7d4e06f4d2d64caaa49be592167eb412209effbbd66b908af06912fe5d58d6c581747c9973fefb6d91eeaf245f43b0436f98caf836aa0f07482921adf8bd83ab308be56c31a6cac3d939f0d47587bff1289665996faa52ff38a60b10ac0de89edb3c329aad53dcd8c86cd0758be062ccd94049cde6c8e9d13c7e", "SEC": "0422ec947ba14d3594b4d16ded29af225056892c3d60f1e290ff5c85532e88e36f13eebe93ba04d978525b6527b52f481c49bb7f15af1c3b659f0e2d06b6b7dd0c", "TP2": "0406f98ad95be3fe6baa743b485d5fb199f34d59e60436674cfb8594c98de6a85703642b98c72314223ea6ea2d439ef597a6925a4c36e7dbb5f1ef917d14b3373a", "TP1": "04019beede9f5a70df3966ab3ba72b5bc33384dca9df587a397bf0dd70b2537a5b0f6d1bad4aca9fd6c0d3d520e9492208fda419328e09f97bccd715116be14f49", "CS1": "040e8352c9b1a9f6dd07c6443db0acffd0fb1dd5420b442db40d97e7ffe7017a5121a065868177bea72c427ad73cf443d168579061ac80d179cc3a7466c3fd37d9", "CS2": "041e47102d6a7b5ae719d2f4841bf72aad911d35705610bc973402911c88f35ad8165bd81bf0ea1b4fda6a1e6362e2a750ca5cb276a9233e2eb8af6d96afd7715b", "HASH_MPIN_ID_HEX": "afc7ac5be05f98a0f5f84ed8920dfb80ed60f893ea23d746e198dc9de1c11a68", "TIME_PERMIT": "041fc728ff83017368788e74cc8b7e9c74e8124ad2d1efad24d645ddeba7231644029801508cb6f83e892618bb8e461b1b276d2fbf582465c0d1a1a7e1446d2550", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34385a222c2022757365724944223a20223131333131333332363337303732633436353031333631353965643739663164406365727469766f782e636f6d222c202273616c74223a202265333765626566653633313663393666227d", "TOKEN": "0422f3d115716ea4bf323fedee71ad6769a94ba8b028af69542a1c74920ae46e971f67089b072d706036291b115839b2cde7972d734bd35b7653693a13a4c7f12d", "U": "041ac3850c01ea29925abbaaaaad380d898abcee1a73547ff1f2eabe745dcaab2c100d32b6e75915eac1f394644fc5e64861fe38463f0809a63fc2a295d36b5d18", "SERVER_OUTPUT": -19, "V": "04033c187b370edcc9857699bb3fba67e90432db76c0c06969c2684a6c253ea949188a500620a96ee109d3bc5db0800a5f2cf5a4d30187f943d165849064da218a", "Y": "0093ca00521d7630c12ad06e765730d2e4512c76d3bd47395aead265520bace9", "X": "104c33a191b7bed311ce39c4339ca003ed95744e2a0af8bae6837361d8547277", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:48Z\", \"userID\": \"11311332637072c4650136159ed79f1d@certivox.com\", \"salt\": \"e37ebefe6316c96f\"}", "test_no": 161, "UT": "0401eebc69dfb3bd4a94ea6d1ce1748f9dc79549b76102f8756d988b1985f8b7120cc9646a3aa68c5551f027fd510c80c0966864ba773c5b5069c036554f86c144", "MS2": "071d912e963e505b91ff5c12a091e3b84837e2fc5030e1898eafbd43ba56e340", "MS1": "13eb40750bcc9e9a2933d871712ab62efca087407eb61c502caaecfec9ee611f", "CLIENT_SECRET": "0414c2d3af4eef9e8a8a3b20b126a7782e9d9535c3fd7d6b317fd702aa8f17db26053a0655a4bc998b4a5954126de954503b4f82fc3c347523195018d83fd46a14"}, {"SS1": "23f562bd1d78b552fb5fbcd84804cc0c50ab0b7a68faae5da9386611040981cf1f291a3bee35549e35338b25333ef12e2d0f797d6776d1c26f219f61e224216907feea2d013cd47a0eea0a3c0eb3dffeda997a98f263f13e84e702bd3bc2b2220b6295dae4d5e507bd32b45c6e39848e193eb0afa168c70051e8c7aa157341ed", "SS2": "051e4327f573d9712ee94f520ba92c3e0c07509caeaa803207730fbf407620c40de5f2dd21a5a4e909b2e6dade874bf3790397e1b410bb635f7d54fac362166b077f6398630005f0550b60f212e910971a8b1dd76c3204c803d92def7bab5f910e5d9a5ffc303c0dc5d00a2621d0e3c7b779da66269bb2bb32b6cee7c8d0f77f", "DATE": 16574, "PIN2": 5660, "PIN1": 5661, "SERVER_SECRET": "026f77999ca76dc488f3830cbb39ba7d8d0ebbebcf46399431c0df2636b4097f204241526951fa5c53dd188ce899e1c238d5ca7427542f1c4bb58c9755c10f2a155c058d81e65f7427cd4d73edb6e98135d68987589ba67784bfa1c6ec4d5c7e1729b03252ff2d0dc8b001b9400146b4fbc872e0156c33de4e52f02731de2841", "SEC": "0404cc397d346223108dfbafe9a8f963f76feef0f259588ba3f7b238e1f07f5a180dcede27be9d033d91af7df31af5c32fa4cb91038f7c9d099d498bf73a28a583", "TP2": "0422fb9301295b758efdc59f8cbc24c44e2e25596aa9c50dd785e6c6fcdf56c6d10f01d68aef5638fc9cfb5fe1541b5497a914b9dfa793d8a9cb91cae9cc28f850", "TP1": "04186c32fbcc15266f6c9d670eac47ef1bcd6ee96b5eac254274f91c5d8257b2c00e505f8863d8ae0aca65112f75394dff5e2981d565d9252e624b5dab1820bc87", "CS1": "04075f81a4bb470ee712edf1529b317e014c555506e7554e2f1501f6cdcb4657d208a6c24843caad2148eba1bf4ce4e0b68053026ae2eb0eeba4b6d19fc2703621", "CS2": "04065bfdcdabad7e6f249fd62efc196895b408af1d566fa7ea807ae815945488ba15a1f31fa1e5b4202f03589d6960451ef68c4f471f773b959633e947f687ed65", "HASH_MPIN_ID_HEX": "10552a28dc61b0856272b1c6374b7c6ee93acd7eb31874b87db94d62ca7ef366", "TIME_PERMIT": "0419f6a86ea2246e0268d9681a2063ec3d7050185a1f91076952a015409311594a10d8e259954b2fcd3038164b9084e9930d646c77065b528b2d3422ae7a2054da", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34385a222c2022757365724944223a20226461306365303435393937643366643631633935323863383835656261306161406365727469766f782e636f6d222c202273616c74223a202265363137383632356266613537366536227d", "TOKEN": "0404f4dc5bdceeac78c7a02a2bd56a94a337046748b676a2cf736367e5dfbdf0bd10246e01e80bddad1182983e37aff98fb3662c560b10ea2a977c1c03ef4cbf7d", "U": "0415b22dba7c26d6bb02a1860e1c0bfd3a68a179bfe976965258e1022e2257fcd816a85475133da01525b461c25b3f4a96ccbfa0375ae1f3417d660506911f75ff", "SERVER_OUTPUT": -19, "V": "04180bf8ddc9f4e19d39dc9bbe097440e2182d6b8a7f42317ac9fa279c46887ec01fd3df8477c5e205d13c55a4e2669a9b1de47ec9f7ec23131d0113e0c668722b", "Y": "0205a39ae324412da08b985563e030e72649cddebc2255055301ac898ef9b352", "X": "225f3c1e9f2cd41f8ed10030c96a3fc1b6e66d52d4adceccc1e60ca6b5dea49e", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:48Z\", \"userID\": \"da0ce045997d3fd61c9528c885eba0aa@certivox.com\", \"salt\": \"e6178625bfa576e6\"}", "test_no": 162, "UT": "040bdee3b6b629f20e3e75796b1d7278b182bfb40a083facbb0a8145eb7d2d3ae61018d973cc7e4e44372538181d5bc1e760a9b225563e6ecff31f5bea933663cc", "MS2": "216dc18f9cfdd5523df6c9bb30313efdbb2e9167d9f510590800d67fcb97f614", "MS1": "23469f3ec11e8f7eff460058d1ba345a192ea729d6ba93f12dfb5c13f7dffe5b", "CLIENT_SECRET": "041ebf8b1b2964f70151382122bbb2b7105aa287b0628f1ceb08ab992b21b39049195a99fad7b14a20701bb2ae630bc35ff25f5870214ae8d2e955e81bda6b479c"}, {"SS1": "12d1af365bb97ff4f4429d1cc70e4395879b1a05eec2b61f0517c42c6b08241f02b85c8235be3bbd6f76282aad9eb0d77d8bd84b2acf90e38af683420f4a4f44145a1e2348b8fccda04b89776ac5931f8d2f1823cfb7de8f5c210a8ef5533811226971d5b1919462acc3b06dc00f399d52812a23ae9594d1047c7d4034a95eac", "SS2": "19a2b8f92fdb9dd81c4fcef366b5f0c56f6d6ff00e6a50bc15cdf3d4bec133f00cb19491e9d8b5e80148b04c0af7612065bb21d238e792b46c8b00a65aab0bdb1b1fd362bc4b5dbe95d9a151722009e0060609f99891e8e143d2ade06ea26f3f0cdafc164aeed742e699aca35a8ed6f7242bb2bc8573aadc1fcee8c0c3429da2", "DATE": 16574, "PIN2": 7477, "PIN1": 7478, "SERVER_SECRET": "09769598dd507f1c906abc1ec2db928b5b0a7aa5c5bec3088467e377e8d6602e0b29d7e89dd4a870583ab10f8ad35545e490854f6026f6890cd1e45ececd4aa0213b6d0f09265d5dd4a4a1f8b1983902d356e12b1b2e3e4be7b09480d22a247d1ed7326e5edeb862440e16be43d704fbc3aa6ac0f5476669f8f9c8f4c20a772c", "SEC": "041dab0571eea132d16206872d4070c347d3fbd8f3fe489e40a4ae25fb7abea4ab1408ed8e49529890415aa47a39f8c2d50bba3be8b9089858576f2cc4d39d0253", "TP2": "040463c046fe62fb4942da92d8952cc4e55b1681e493f079dc1a26830985219a9d1ea09625f7e57a49eecf6efffe0d6cd186518da16c6f89486378fde652d73118", "TP1": "041bbfe0f77ec475e456ac45a5ada39831206b0b3222fbc73e240cecb38843b23d1cbc11ae4b000b75a5f8dba810dfb146a039d9c851337d81d535cd16398bc74d", "CS1": "04227a58a1762e9e4c8a4f2373480abaee4de74b6482ad785fcabea6cbe9cebfb503472a6adbe086e4f26f1b2c81a7637894b18c9ad6cc0cd7da74e9da35205bdd", "CS2": "040f4cb69ac20b7babe0d6974a3506920b280b96ad715eee3c91fee63185b2b27f0dcdfd01dda83339c97ead30e35311dbe7229f139fa96f731210989b19eb04ad", "HASH_MPIN_ID_HEX": "7b66049ca9fb9dbadfde3c9435f7e0bfee91b5e9b6e7d9b20989fe835d10b661", "TIME_PERMIT": "0413aa5c83009c1a21a025b969d0150947c0b67962ccf2e144703fb57b25f0c101078a59780a75c649642f6c2bae96998445d6bf3040a1841b6004eb81c20abd69", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34385a222c2022757365724944223a20223063393938383537386430366561373934643932356338656335323763303936406365727469766f782e636f6d222c202273616c74223a202236636533663133333436666437366239227d", "TOKEN": "04047cf7613a760b59ada762267f4ebec8d74850ab518e816b6e51b1538a83f03d05ed7a7b0742ca7fdc5c19b95bf31770b8ac40225b2ebc66631e44c6c5557c7b", "U": "040f77790e1de5cf6ecfae4b65c90a4bd7308868229632551a0456059aceaf427809379925aa08bd73cfac06ac022b617eb552e73b74a372e208f0b96d6c7e3c9b", "SERVER_OUTPUT": -19, "V": "041418dcde5a2014d1461895045da0df00ed3d4a647eaf650846f83d51ad1df50d0c8f7afd6002d670c3a474b1494d1923c599681c1c16a71655489626a396a64f", "Y": "00c6161e47e9f01809826279526df7e9892a3f6bdcba847501e15e1e9de1a7ea", "X": "0cc555607ef2fb06c2088cd508669a4f8ded06c36ae399543688c7e8f7fed292", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:48Z\", \"userID\": \"0c9988578d06ea794d925c8ec527c096@certivox.com\", \"salt\": \"6ce3f13346fd76b9\"}", "test_no": 163, "UT": "04223695407c4c10eabf435ce7120937a223421461066390830df7faef8acdd96a0c330b9a0171522e066cdbe123be69c33acd77e32fc1a7a07f09b90fd1a33d25", "MS2": "15341dc68769aae6f0d1f3c809a9feeb5129b6030eb8432416e7045963eb1fd1", "MS1": "101760e3efbafbf93bf72cf9fd47be6b62cc6dad77f4a0e73b2bea6303f713c9", "CLIENT_SECRET": "040728d08bd59198ea434488e89e212435c3386d9cfabe16cc240c91de9de2a8f70fe4da9b20a18098f00a2f734f70e885301b91a6a6bfa392817bdca3fbc17b35"}, {"SS1": "01e675a8603bc95eecd5a1cba136f5bbeafb9cd675808c04e8e848e5fa79c8e6102dbdb7581eeb09b43be32046e257e67928e7cb148d0e03799fe00e3f071228129c87735780d8d1b2e11a5d4206f354f613047226e962e18f11049fcc2b23520de700bf8bf685788243f05171808447f2dd1a55545f21089a78938ad1baf497", "SS2": "19b02c33ca37036145fd1e2bfe3170c87cb375cb4397020f1cfb17d6a65db626128a937845cfd0ddaee796e0975d22a0369e6e92641b209b0a75968fa94eb8a319af6fdc3ebc723f273ca1e14b503b08fd0c9dd62ce835fb7f4f467c6cd1ad9108052b0135990aafcff4885a482c76cf53f03d22af4af88d4ada9fdb9693aa03", "DATE": 16574, "PIN2": 4699, "PIN1": 4700, "SERVER_SECRET": "1764e6e4b1a98864ff78f38daa01fa3cfcfb7625e3ebbe857c6abac88d53d54d21943ee3be5e7ab9b2330cf1c5f42e996dd0c59d67bf5a0959d61cc970cf1b7604d86d1d1d040399273d5656507651a634647c86212fedac81629443abe636db17bafc94e24d0799c1eff7041b3896c1ab47beefd8c4f59f0b7129626cf0e1f1", "SEC": "040667534c08fb457b89174574735fffd99177c0f91785de90bf2e24c73ea60c0f01236d832c03b7ac87416afd91ea55a1c5a4ffdf5d6045432d4f2c72afdf1283", "TP2": "040108cfbc93006fcb87e428f2ed553d0a43fd3b614316152772324f0b194d1c011ea1f3a68886cb4d21b12ef657f86945df0362d2d713177cee39778951bb3704", "TP1": "040181f2dc11b2c6d61cde2366f2cda9fddc77bd43066f309ee73edd2e62bfff4e18a1a9089221f6b63dacc9c5f48b590fdec26f7a36c63958c694fabacd99e30f", "CS1": "040cbfe51dfec89afc25ac7d0a5f4da3c340d0e1048ffa9977545936c391aafad50a32d2e1ac6a040ff9f05c96838960b3e8c6c7de8a732aadbcf09230b5fe5937", "CS2": "04201363df997cb92cf2d040e2eddf2bd4ebaa4f2c1f52b7f8b2f5d975b8bfe89f17579ed211e9dc6550e1b9cd9098522f3e553110b306326fbedab0ffb665e24c", "HASH_MPIN_ID_HEX": "3b628ead6bf4931ceb296f2073c9c84edebbc870c3a020a4aa0284f197bfc7e2", "TIME_PERMIT": "0402a3ccd161490fd4c3f94cae81f9248f30e5f74e4fa20a885449c7e209f78454073962d195945b234102b652d31aa0a312556b3fbd9b51039f2a46b635592380", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34385a222c2022757365724944223a20223863396163366334626464316663373765336430386637303230353263393835406365727469766f782e636f6d222c202273616c74223a202266346334306266643639393230616661227d", "TOKEN": "040310cbda0f7b8f6e43855a254649cd1d527c6f0e27ebdde167f28bad357617330fe969683e5a7669a2ce4a8dd02e9db13f9d6ae0f9e497e59b29a381a6224a43", "U": "0415e3e9aef31fd4d79aa4d8a846c93aca4e2ad1a4fdbc340e2c4325eb4dc78fb90c1a6aacb4c0e7b9643197e3b551da40437e208180cb1acb511bec5f0fa35eb5", "SERVER_OUTPUT": -19, "V": "040fd01ce192f0d95a07f48d0d7f01dee8c39777e83ef39f16309fafaa05132c960cf325feddec04c522f9a2fd108e74153a63f82d5bbe507a8ba0147a16dd095e", "Y": "22cfa2e5ecbac04fcf73c968f81b3a3144fe640c713f10e7a5f9935d6344db6f", "X": "0272ad152379c8d274876e79b49dbe7a3d649f9e7eda9f9975279e80f50dbaaf", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:48Z\", \"userID\": \"8c9ac6c4bdd1fc77e3d08f702052c985@certivox.com\", \"salt\": \"f4c40bfd69920afa\"}", "test_no": 164, "UT": "0410de158504fc8657be6b441fdf2fdf007d042ce2398a6a64b23154093d00f3700a1fc768dfc4d838b527dd28bca9ee84c0170c5350acec07da24fc3e759b0f58", "MS2": "12e174dbb83093aca891ce13d328af02c087c4ac5fb775e38b890794a47f494a", "MS1": "1b4239f65c4bc694e04f5ff48a45a7042ecd2046c15b1d6eff4c628fd0444bf7", "CLIENT_SECRET": "041a7d3c06189988c3b7f3971bffe1fa735d3677b106d36ed3abd1148b839a94af19411a427849e24368059399f6500b604bad06575d3b842e007d289a1b67d119"}, {"SS1": "1b967bb7c3407e262760f8dea3b7dea643d606f25514b44de6ac0836b95e2e1d17efaf3b6d63d6b7d445196249080c6e3406c76d0f0c51b3a35f1308b177dc341977094ea71e05ddfac6846cb59d048dd39754dcaaf2b5434b13be63d29757d61c4b7d78aebc9b26ea7b5f06391b42eb3edaa7194f2296a5221911fb6eed15fd", "SS2": "17f6804d258d5cd729c69a6f5ed1d44fd05f17dd58fdecfe963967bc8584f650236c00152c271a4106b961df7bc7a2a528be8acf9b855d2d7500601155db83c70ced414bb4cd639c6abf99cf454f5ea50b507fcd45a7ce90248ea6d433b4f3260df6cf17c6fd29475229dd2fdcb26f55af9120dd525d184076b391863970adcd", "DATE": 16574, "PIN2": 563, "PIN1": 564, "SERVER_SECRET": "18a8617e44ae9de479239019107c115997ec1668e2a69ebe0bb44c7bfa0c7a0e0c98162af8190efda7d2f46336d85436d18ef017dbbbe824b68ddbb5395e92de0f295656c157b6fb4f89b44f5c367e68920abffb06aa4490aeca08aa25deb7a71554db841f8f08c2cdf8a35e7de4f8aa23991c16ede108738ae4ffac8ce9a70f", "SEC": "0412d75e48cf950009e61024b13b80e515413429a11a5b0efff61af0358a5e580014f826e216d73be0cca0cf044ec37011cce68599d104a7d6bd132b6b5e5f05c8", "TP2": "0404379966837fec9dde4307b1ec131be7fda5a80f901c8a6e5c308eb0ce91dbc7169f0f83627fd76d9582ddb541baee18f272c6692d956d21a9c64a972ff432e8", "TP1": "04020b57b63f8620191b1ed5284044375dff5bddb3095d5d6e2fa6d41baf714dda0d02d5af432f121a61b8529b6d532318d8fc35a9dc37047aad9eb15186a0395a", "CS1": "0409784e60841a489ca8ede30ea060db059963ebbc4984f7d437e6f6c5e8b183782115a93ba4533653ad89aec034a1be0a21af5c66ccfc0f2b27f113b089c1e777", "CS2": "040c851109eda626c031ea49be0285530bb7c16aea1e50f0376378d1e3b8d4acb314b6c15aad19e9621804b01459219f51f057bba1ce1f344104955c01426b88f7", "HASH_MPIN_ID_HEX": "d121a44d575716c965a0dd5bbe12408fec3729ffef06024760a5d06ddce20d32", "TIME_PERMIT": "0416cedd202dcc7d7feebaa28b09784e15d094bb73b078e693d6c6ce891636eecd0fe63c4c83ff3e92ff35baf839f5234dc5600ee3a29910d8b5c7336b480822e5", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34385a222c2022757365724944223a20223361613162633839306361343135356565636533656331643165393233336132406365727469766f782e636f6d222c202273616c74223a202261353938316639336532323333336136227d", "TOKEN": "042256b70f051ce0b60a848d2389ce7d4288f1f3d8b3fc1bd2adfdaee66ccbd70c0e6117528c069818f8c3968b0050ef4bccd2082b454ba5dd2a2c47f5a8f90cc4", "U": "0407715d830442781b39956b152fae89251d07590ef16798262e7a8da7b578265516a3218d697dd43df57832bc54907c74d940f1f7b72ef1f24549c3ac7bfc0ab3", "SERVER_OUTPUT": -19, "V": "040ec0b41653878ca5733535aff0c4ca8afda66d2891cfd5d3ba65a6df5d02b48506e3dcf4b28610f287df5ff74fbd70bc4393c2e0fb033ad0e81aeb5f3363ec48", "Y": "13a973f9ea71979044503f6ae13f582b04f67bdd216b1868b08df598a564fb3f", "X": "144150a542ca8230d105d613836fa7e8192706bf5f6bf1406d3296773cc76b85", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:48Z\", \"userID\": \"3aa1bc890ca4155eece3ec1d1e9233a2@certivox.com\", \"salt\": \"a5981f93e22333a6\"}", "test_no": 165, "UT": "041d02ab55e8a2b776676217b48ca0ee92634608e5a52968ef98c6118d93a7aa9710b05f4db35934bd42aa0e63f23df86f7a01db9f988c67f7a59d500cf349cc7d", "MS2": "114ace52798862b8825ddfd8f90fd69ef30c87c70e7c193a74e7a37d1af25d7a", "MS1": "1e1628db148d5ab75e41cdd4b8e6c72cb86d0a0042fcdf16b58b9d503505616d", "CLIENT_SECRET": "0400cd1751bd947eaea5a332cb128e2c79885c42b97e702b1b26d9394a992a76f40e2b4e6071bea8c9c09db05d548e34abd931d935e90d84551f839b39e59d0c1b"}, {"SS1": "13f95cc4eb285a26fe920fdd9e035df43548115f9f2dfea76bd01b0bd8dc241e208f355c1158ca46334c2d11767e7dfb3c0e5d4b38a9f74f7aedbd3b4b1ebd7b1fd7eae73da5a170c1e6aa121928393bf88e1be0a6bdd15a940e89955a32b0d109a225716869ce923ae7886ca1031bdc15eec1e313b90beff25776ff52e88de0", "SS2": "0ca6eaaf68d85586ef4efa1d2edd97d9b6ad61e69fe263b2d201220c1a7fe4fe04f27e5996692fed7729d48e00c78f54d82317781197560673e8df14c8de2c62019db735badc5aa95e50872f2c78bf273d539808d3f94082175f1d1ff971bcb70cc1ae5e10215aa4bd0074be33257c14e1d2f4c8ff24c2371192308c6a8e1ce5", "DATE": 16574, "PIN2": 47, "PIN1": 48, "SERVER_SECRET": "20e9c3d2db7b3677a6ae198a4125c1ad047cd3db012ada5973bd351ccfd663c9161865800146f52bc008e398811f5173952963f016b28db419b0b3e49acb4f8711eaf768e46a555f6b3705c99fa849d5d0208019a5ca75824587e879ba1d1af20c7f1f8577bebd99d732f45f9c8de359452389bb90ff4420ac8b137cb6073365", "SEC": "04006417a9ed5d4b617550a27647d4f2482c4a41e0570ba0ecbf02a26653082d9b13c047cf17432367163777d5de720a1b3de85f98258486b3ccc6b3e4b262bff5", "TP2": "0405bec87f1df9fa8acb23b40903e9311067b605548702d819047255fa9a6bbf4f1118af06f921df32edc9c1b185415fb0239b06f65957210cb840232b7971912d", "TP1": "040f940b4b85cf6daaa1fae16006d4b28aa303935fee27944d1fcb2820d99bcdad1761a25456659b2af4b12cc4c34b25df445f22ee19e72fd92598bbb027f96567", "CS1": "0403a130ea540b58d3698336eff3919986f12187e782bda8b5fe1600236645b49019210c97dddb6fe1e197c312160d90d905759926cefae6fb60619b449c57250e", "CS2": "0409f62764111006c33f2ff8caa3440c2223c560af8c2e13f7fb84077ee2f98ba41a185a150f3ce042215d4e902c65006790c76a5fd82e22c3f7dd16f4296a9f3e", "HASH_MPIN_ID_HEX": "210902e62825ca91d24fdf03e4895a0423b0b6981d1f57f54f0e9466d000c277", "TIME_PERMIT": "0421d2c33d010332a4190402138216e2470a9e98640c1a76d323f66d718372c28e01941ec7b93ad5572fd2786eafdc23856d9fd1782d1be6f946666127072ebff6", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34385a222c2022757365724944223a20226364303434633135303262393139363862633735323835646265376433303435406365727469766f782e636f6d222c202273616c74223a202266656263353665333562383931643434227d", "TOKEN": "0409059a2f15929e60502460d33d0018d1466a5e0e88e667a0ecc74688d4da6c0f1ce0b602721463703947a66ef119d868a694711ac91dd56434a9fa9fe6e56062", "U": "041229ff7c76be34cb90d9aca39eeb811afbc7a080d18e65f5fb0509b8b39ef1741df72f2fc859e71c5aba963acefbb24e9ab9e221216eb9a6f892fcb24389d62f", "SERVER_OUTPUT": -19, "V": "04196f334d9701d87304bd6c5971163a2acf74044c56c565b42853b2bb94d034e91e43301829320162778dc2440104a5c6ac08dd60ca8bc7387950f740eb05865c", "Y": "000bb926b714750e4ac5339d24a4430c6db53c45a3976e7cec5000796dd562ba", "X": "14c40ae8ed5571797123cb3d1cd6cb7982051a996cf65bc73927c18af3fdba49", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:48Z\", \"userID\": \"cd044c1502b91968bc75285dbe7d3045@certivox.com\", \"salt\": \"febc56e35b891d44\"}", "test_no": 166, "UT": "040f119a653f68be155e067b9eaf613e84cd0bf3fe29917652123674fae77a036d206db33c37b031a094f14b2b7ff7c75d4d8ad3470624e22f53f2a4e55ed9f8a4", "MS2": "194d1d40746991c4d9c9739ff20a69c15153c0ee6600eb76886b22e8d000904d", "MS1": "0b0a1305989a59d650dae9e4dcb114a64f09a40eb95460c3f86453acdb23a15c", "CLIENT_SECRET": "0418e98000a12a7bd4aa9c9b0b14a7c9087746a98b86ce703b49e720f3ba24d81910b122e75e5b6d1f17a90aad0228b0e63feb26f60b480de2356ce613b0781189"}, {"SS1": "0834316a5e1492cd833a5fe157384064967e1ede860d36ce73d6c7660f722197213deb8bd4e4cebbf67fd99a25aa659cafdae71e3e8f13c92b92608a4e3504070a8a1c66b168472d0ccbdf6c14228556ad9eeabdf8c0cd15f9854ff396297ac101f8bca43a9f0b16d900ef865c845b1c6f9d2dfa4b3a46b9a2f2ee8d28d11e74", "SS2": "17ae6aa631f5791edeccb328027fe13aba0c06538d2022c0f5573f71f2ab3dbc1658b53f506fb46a8305a7ae9298ca2fa11cfc15b510a5808d57baabeda3fbcc1601f833b3f2f2fd850428f2533e6827db987292449cbde7b830c9c26e7b68dc12a9504f5a0bba2fe19a29fbaf9695787acbf3d795c63eb810c18a1f7cda4863", "DATE": 16574, "PIN2": 1980, "PIN1": 1981, "SERVER_SECRET": "0f1135d12604682c5463f3ade13ca73316f6d034f39e29ba5d5eb2d833c0ec681da0a01a5bddd58b51e6fadaab5d33a7d23a83f2e7d4acad7703ace28f6d861800be73095f2af0f7904bc047c3672d1e99e8de315ff8df4fe364e4f9fe6f0d2e0f4f99a61a831fa109bb83a86e5364fe0cf0f5c52bca20117d19aaea75d362db", "SEC": "040832cf92ca5bac7166b111192f4e51446f64e7a547ae969396c0a168d4020bd90bcbc938594fb02d6a0ee294f82544da79a6de6b4699b464b2ec8dce68aae6d2", "TP2": "0400f16f4c9b4db1c6e0eee90b0d080a007ecf67126bd4db39cf65e8db04141d5f234d3cb0f8016c7ca915c43f11e0998b4d637b178fb4b8e7cefba928f9fb2a09", "TP1": "041e9c29ba076e700a6dc8f03206761d02f5e2146adffe8946d0ec42d0f4c208951bda0db753f4e7d3a77967be8d420621a0c76adf09812721f1038c4b4c9eb4d1", "CS1": "0405cd2775cae8238f3027b63dd2f0b618149319f2b23d4b5ccd57f92cfff56f131c2124bf7d3b45a0b43a304128708d2b8c3f7bbf150c4f130b95c5396efaeed5", "CS2": "0418cf3db62b492fc2cb36e047f69c741a01b29e32ff1d76ed9f5a54e0fa8916741f83a04371328d637da4b98450532093d23e295945f57ca2d0604fddbe83160c", "HASH_MPIN_ID_HEX": "906d724d060a2c03a5cc0de91e66d55a544572f7c51ea1e9fa10d9b81bac77e2", "TIME_PERMIT": "04199d687e47988d2e5d98223872511f292bb361d965524bf2b3a441e95b6687d61817caaa4c863b7ce3ff5691121c09044e1668bfb12c82e1727a4df02c92ed88", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34395a222c2022757365724944223a20223037633865666539663963656634636331313233663063393432313461353761406365727469766f782e636f6d222c202273616c74223a202266316333326166303966353663653865227d", "TOKEN": "042300a58c8c1cf95aefbaae861400c30d93ab9e8a915370a4950b41775772175f08279496bc4581b266e09e594fa3801dc187c2451547abfc18fd94e88fdeb0c0", "U": "04173c6ea97002c35ef51b15d3716551f789b26b10f51891d600765193303524941be606cd459162ba405ed3464b16952a8ec0a88a645f7d22cf671a8da726c2aa", "SERVER_OUTPUT": -19, "V": "0416bf5e423dd60fb98752e76490031d3a7cb521d46312156d7f07ec857ecdda422061d00e0b5fc77f3001e56217e00620c95a18a459908805eac546be4ed48ad3", "Y": "00372e8316d871f281b1ad4fa9521e71ae97c0d1fc71ea5d527422fb4adbcced", "X": "12a71c54ac67b9df1d9734495df174518603d4c86883d5d08f9bde3f4a6a236a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:49Z\", \"userID\": \"07c8efe9f9cef4cc1123f0c94214a57a@certivox.com\", \"salt\": \"f1c32af09f56ce8e\"}", "test_no": 167, "UT": "040d01fff2949780341920d7d38f6c54c61525cb16ad059a87fdac61a219447a3123a71162f8e8ae98802e53331fa19d397f7c1621e81dcbc2b882d78cb0ee0893", "MS2": "026c1ab95af931291cd266c9ba4c3733f03e140ef7d935ecd04fa6b2f96e65d7", "MS1": "1b77bd436a5d36e0928511c93cc5e975c46e4b5a42c83e1c201287f8dff5d21d", "CLIENT_SECRET": "041f052f47c465edb3a76429778328de81d07da7024d474fdeb2e3440f8bcaaed11b8667ce63a78f64fe4fd523b92a2149ce2b79000ba371ed72463885ab52e92b"}, {"SS1": "0f57968c5629afbd68b2864b8d1283eeaa986e790c72417bc881a9286c2fac74220f301637aba5cc7cc2eab66d3d4c5122f576f1fd34b396d5f55deae966a5e2012ff3203920a5f96124bf4fa28b02b2392623c2c9f6325fdd3e556c68de538b1f22008739ed25079a2ccbfaa0ff06fb1bafa68559a594f59d661ea21a1598cc", "SS2": "1a0c6300c88e583ea92a98b868021d09c75becf902895da26c70164a7a3cec5911de34aaefe4b7450cb64a90f5a06ba668a64264c077c84881a9339563e2c9410eab6529f9c6f667bfc6ede381e524bedd7bbbc0e5c380cc4d55e06f0c353cdf211981a2923114c406708de4a1b199f2b2f416857e829f8381422d790422a9e5", "DATE": 16574, "PIN2": 5463, "PIN1": 5464, "SERVER_SECRET": "0dc75be4b60d962e30721562d8a154dbbf0d7142fcd9d3bcf68924c32314af6720762db37ac46f0eae41469db066599c36c2badce2cab02ea895b7dd86a9bec2033e48ce52c145af99cb07ba185b44c8d88c08018fcf6f7b91ec29c9b567c24e202f860ae6fb874d2228fca180606b80e8c32cf5afdc47ac4c899f49a0ba02a3", "SEC": "0420c4b06e86abe23bb26d3aa4e8bbcda8912eb4b08b2a6815bef764fc8ebf297f07e8a5b6868dbb6ac8a156908948b47b0e1b6439a6756954f58761ffd711bbba", "TP2": "04010aa6881bb1af4a8e8081de6fd755aea4a91850b3602efdaef127f54bf355a720e156ead088efa698e3d705631ae17363bf9ad8823bdd15b92771a4c4a54b0d", "TP1": "0402fc3ff27da5cf1fca2bfd0225028d5d2c8b1911e4d88db76080272ed5ccbb521a822f1584cf943cd422ab807d84a7cdb74b3428d1aab09efe6a12283982af67", "CS1": "040dcb6357e10bc28fb46fdb0445ed89b95c8b56ba3c60df34539885a17dc33d8c04031766221e47e664d89981115e2c1e860ac3d31e4ce74651518c0c93037929", "CS2": "04201b8fde9ad030bdf031fb05dd91256725b5b202b0373290fac5953ea46fb95306b0df36b3579152cd624cc482a174554a637369f0f78bd900ac6a32c0b4b291", "HASH_MPIN_ID_HEX": "6b98500e9d5d544e09ad19d19726a8398c00e55089fd566c5bf9dd16a2a419be", "TIME_PERMIT": "041b4f7a84ab1104051bf3b0cc701630be66a6b94b9844c013fc1db0d522788ed6015ea6fa34d319f3d6cd59bfe5a5d9028138ca0a8c9b4b7e795ab473564cef1b", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34395a222c2022757365724944223a20226633623265366361386665633762616664643736623530396363326531666239406365727469766f782e636f6d222c202273616c74223a202235323563316464636235376536333832227d", "TOKEN": "0400fe192bd5fdc53a3ff9038e3e3f25a97bf94c889685779a01d93c3890cf99f01d48f977dee156853dda65b489f4dc2930395890c775a25d7feed52cd896fedd", "U": "041ba8da65958fb69b25ed5794c1b55e35a01697aad127dce5829a9d3e66020b001e8e625472ac3a3f7dc78ac88410d746905aa2cae9c1dbb0f58fb71f82b2fdb7", "SERVER_OUTPUT": -19, "V": "04060db9e3396e90367b7b0061c6547d50471dddcab624173686ef5719bc699f540272de6b069f77c5606f9d37f988a6a19f71a5876247a82a5814eac27e21e94d", "Y": "10661a67427b01789a83f58eefc2948af1e9b6ca67ef30e614760ec593b97fa3", "X": "0ade379c47fe2ccc777de9acad3c4077b4c219861cbe1d4568039afb1db8e14a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:49Z\", \"userID\": \"f3b2e6ca8fec7bafdd76b509cc2e1fb9@certivox.com\", \"salt\": \"525c1ddcb57e6382\"}", "test_no": 168, "UT": "041a096f39e98fafdf6b873c14f9bfedf72707b3bc954318b5cac3a95e9ca8fd3712a3a82f4db866efb15fb970855e4008bc629e8f9b0049378704460129d77ee0", "MS2": "194063f1a908a10967555872bf618f228d9b31c66d7f21bbcdfd0ce7b53a0ceb", "MS1": "0b93e11adcccec87eb160d100129d9e327a2ce3f98f9727b3e5782deed0bdf9a", "CLIENT_SECRET": "0423a0c63817ecec2938f3312eae23582a221eb6af089257560b88f387a6077e1f012ef346173968a173fb5942c25557808d7177afed7f5d3f456e956b1af5f423"}, {"SS1": "131203736e865ab5352652e47095b0061698bb350a9c98f00573c181e1834c6a1997aaab8a0ad8e427e89f9d548b6949f8a8bfb900b71d18673ef5525e34de531ee6330f81bcb3eedc5382e6efca6afabb605d00f8aff259010415de8e42128d1524a518b480508512c039d4c0d4af02f6209bd449826ed17df6f36325ad67de", "SS2": "1eee65e99e46452e21160cc7256f67abb1393d05f3bb45c48893dcb41137f909210e77ac81894ed4ed751cbef266809c505053e6992cf393106ec9656cacb5cc172ddd116cc42cc911b8531fef4fdc1c965f01808afb6a0c4bdf6ca03e85c8ca0c3f64a25e240e60e454fdf373a5df77052276ddda486f3758f855325ec1f777", "DATE": 16574, "PIN2": 4772, "PIN1": 4773, "SERVER_SECRET": "1fd6119ee3e35e63845e36696681e5914fbb9e88e3c9875ce31039a8cd1dae220ee8bb6267ff7632eaf66156be0ad8ceff8df559425877c958ee419c218f41730e2033c6d42eadbef863facac335d8caf8163c28e193e872bcb97466e79f79480672ebee9bfaf27e2de8aceb8588aabf2e00fc6ce2b4344f47b709b02c216d3b", "SEC": "040748b41097378da39a146d7b98ecbc155a833ef6bb9e3297d253983b490a73691452327e844a07e005dbcfff58c525803f14063abe58a7fd5de0f0d02e7b1de8", "TP2": "04168a99674d74b8d74850398a217de087c1513889498492c4f41d362175beceef0eefb9a0c430bc70cf1af112a636feee052eed162301437988c8e4957fa1d88b", "TP1": "04165096eba53d31ec8f9b2bf5882fcc696eb52db177232b0a52d892abbf03220922c0eaa2777068de63f2233fe9fa1a2a7ad2693c5c67f020ad231dd5d65d91de", "CS1": "04179f58b71fe3c40b5fa383e4dc610b4b2c0f255d51b1ad869645bd97aeff930005cfd0d3252c95e590c300effa793d1160a9bafc533d9643d0339e1359f51da1", "CS2": "0412d40b33f6a4399aec8512df8c630137cbf7036758db3717baa8c25e8b8698021e1bfec3d989acea4f2d669dd220442e41917dc6442feeec4e0980f4a8b2ca42", "HASH_MPIN_ID_HEX": "016b38d81dc2431a94147838d8fb5bafeff249f30498afe293ebea0d714cf62a", "TIME_PERMIT": "04139839132be04d4a13295af00c348da81a3d6353c382120f18f0da37c1eba0330d215c751855ec5f5ad69bfd60169f07361d0baf2c17b57904d61acbba3e6e39", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34395a222c2022757365724944223a20226262616431346636613338613435303733643535653339623135623563343636406365727469766f782e636f6d222c202273616c74223a202230353265343936393232613630656661227d", "TOKEN": "0423220700caabca27eade7b0c1544863ac7f8d94f3d62c39ddb3c50ad722e70ae04dfefc3eed65303d5d2ac44eb2f0ee7a34e61d28445ffe3831ca94349037116", "U": "041e892139d76329e4d436dde4a96e7c14f59f9067e3e7898fb60d704ad11992790269dd9d29f414bef224d32484b7fa571fb8735dc0bbf7d60de89d8eb75c962c", "SERVER_OUTPUT": -19, "V": "04052e1eda453248c3ab488c931f7c06d28aebeb72aaf24f4d3e8071f91cfc83c9178df5b46a876db5889d4d96787e4a4bc28b8c40217de3aa79c26e54a793ac82", "Y": "143613487c552624103455370de0f6150a8b554a20f4c4b09f56046f86f49aeb", "X": "073f216ee06d896c76fa22f96aec0c0a059508a41d000ff4cbb3264dab9f5b8f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:49Z\", \"userID\": \"bbad14f6a38a45073d55e39b15b5c466@certivox.com\", \"salt\": \"052e496922a60efa\"}", "test_no": 169, "UT": "041de93744beafa9f52fa1d6531dc6c86534e2c151c1ca3a49ee52b2af76e88ee015b1f5d37f9c090928101f996b69fea65e64fd64bb688bf8989a5ee058b9cfd5", "MS2": "1059952e07ca70e38304f254907f70595d1219faf520f7aa754b06a7517bf8ba", "MS1": "0f3e319234af1d6a6a09589888adbb2ab7092cb6ad68f4082eb8b1518b217cda", "CLIENT_SECRET": "04054b6611ad00c92a5c164dc9b2926edb87b91fffe2a0f1832d9c2ae9233fdaf81c7cb7d74fa09239fd127da809678272e2927db0490cb7a26b014b9c6ca2065e"}, {"SS1": "0964712306458d2f4ea53df2d3e96f04bb2bd4183629665dbde4e23273cd58b71e7197136e42468e75113259c8edd85df5dd6436d299a04fcc337a6bff9bc94d0c11b67d6c09d209e4b53fc684e3de9285daac7959d908ce049b6c00638f62f51ead9022d4a2a0bc5afdc7ee17051b884bea4dcc541796bf7a7ef053976c81ad", "SS2": "0f1dc99e7feae2382ecd90639b364838b29c73e10b6144be7c364f18029c16f712a0a7ae38fd32c31fbad0fe2cc838d0dbb2d97091fba2ccdbdb0191ad8c4fa812c0f6e5b07332e6f402bb5124adc8910cd012465eec8f3baded0bac26ad135006c375a56273343dd9d07611badbcde901b0b7d57146002cf3917020e786d78e", "DATE": 16574, "PIN2": 340, "PIN1": 341, "SERVER_SECRET": "138843b6378041cdc39f9a828d5298ce397facc1be6a9ddb27941d5b415435e51c57f858ea38b14603db6a9f5941b6997eaf672d0000970170de5f5d6da4218211f1b1953f6536190c7450f13068de5541a167f12b044dac6347ea643c1ec184014dcf3555662d9ef1a2166e048738e4e1a263a09412bf4c9e0b99585b72414d", "SEC": "04112765dfd98628675a09eab6cfb8fb8583f25676a4db9121afa5e0e159895cb40412b8c5ef86557bfb88c8a8b41ef7ac2609e03911c957e5b008c216338d5b7a", "TP2": "04014bcbdb769da17c0e780e5dd0feeb7b3b6280136ec32f0123e97f30b2d170dd1f0466692ca37c1685d6d779996c9021e7f95c6ac2453ed32b2a8c624e89324e", "TP1": "04037ae5e1b5750fe83d72c98f81d4dedabbfc5b2a261cf9996bb1a22641a50fd50b812f9107b7a703849ba63becef90ba19d6131dc08714c0c6713d5e393a8ba1", "CS1": "0404c266d30fe2c90c394808608e36099e7f14029b37a817cbfac13a87957b594c1bd4f914c2d16dbdf20b9f8a1f56c717cd840c147024c7987ef4091860ce802d", "CS2": "041341ab0e71290fde2c38f5a8ae114fab7391a9da1c8e2b14b0721e4834cb30b423605d7744fbc141a8c388f1066ac5ef371ef27de62e3f833b1f5971940a6a42", "HASH_MPIN_ID_HEX": "dc6c6b5b81d74bbbdaf6516fcb4623d4e833a3d635474a1718f0e10996bb7fbf", "TIME_PERMIT": "04009b1c38961919551f7e396e9b48788f30cc23665b8b18eff595f304ad415e0c2362bb5e58fcde3f292e7b1303219f13d37a31f94474aa675ec5beb4233d6e0e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34395a222c2022757365724944223a20223866323037376564343735653938616334323237316362663332393935343332406365727469766f782e636f6d222c202273616c74223a202234633966656136663134306637343663227d", "TOKEN": "0403c28d3f7b036b12ea15300d5285eed041f488cbac03845fae652e7d305c135d0816a67be0e0cd009ca3cf6242024ac4ed39bfee7123334d4f9ca78ad63e8320", "U": "041f3249cf98e979853de84618a2c7bf3bed64490424fd6c7fcb8afdff8b34f4dc1319f4e5452b4a17007e64e745f8c8358b7c4506b7e91387ad9ff04ea188eafc", "SERVER_OUTPUT": -19, "V": "040b20b440298ddf615c47576602fdce5b4efd587e9947793ffb02124f4c59075108a7a0dbd4e33c97786d957aa8a6b83ea2b05082f8debc91f3fddfbf0c411c4a", "Y": "0ab18100ad5d90186181170b2846c7e545089f1af6b4a435899eabb3d70f2b4b", "X": "024795927cdb21985c089577d8252add23cc29d6e695d49bcac7647454cf6156", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:49Z\", \"userID\": \"8f2077ed475e98ac42271cbf32995432@certivox.com\", \"salt\": \"4c9fea6f140f746c\"}", "test_no": 170, "UT": "040db845655a53b09324eaeab0d2e4e90f31451273b5226899439a6a3142cfa78c0489c9d1ab51eb826645ee17f3a4120737094764c4d3880b85f98e2d0c45927c", "MS2": "1ac22fb0d9068b97b7c467fe45751386f418d97fe2df1c8d77f60c84ec377c22", "MS1": "077c0ccd379c73bea7e674cd3f9dd59c88524ff4bb1b2692dacd488f2fe0fe30", "CLIENT_SECRET": "0407524545ae9652260a817f341001ae0c2cd07d2162ba3700f74d8f6cb32d69811967e3b95f70cc70c0d5b025484eddf9644d663434ee6006cf696e1440a08d93"}, {"SS1": "09d1386b2ce314acaab109718e0e7397ba76cfe07a32b31a5805a37cee5ab6262357d9c1eecc6c0d5ff752d27b1884c29046756d40982f1ac929ba8a77228816122f4aa1d41a196f6a4563cf90ef65497a4481e26d2b3702c39aff9b94fd81cb12aa900c83fed623bb591ed3e2a26bd98196ac448e62cde3508763cfea80c133", "SS2": "20b6723d7375fcd4494dbdf9e538a9e79a329d4ffe8aabe40d9cf506db6a496b014dc8e0c1457a6259971957cf1fce52e1a9b5a1446e00775f48f1556d5385870efd65432b5658681beafc6a881e930856232c965aed12fad25e6d6520f4d94407e8c63598c0c9388d1d415c41984355ac92f15ec2aa1a570546978a208c005e", "DATE": 16574, "PIN2": 4521, "PIN1": 4522, "SERVER_SECRET": "17514f2d574ecfb5c94168c460cbdb9e95467d6967fc18f3e8912949a8de0eaa20f800e79196a32b180a7afe4d70526206b15d7badc934e8837469237edeb2360cefa9befdf05c80ac1134899fef610adace6474c68d156af6f96552ce7c34420e554de877afff47b446e39fcd45033c16502c87f28893cd41a4f55510a4c8a9", "SEC": "041cc9cc832361c42ee871cd59ee740f5ee267715b690540c69dd78c786f68b9281bcfc8a21aee8e9704e330cf9e9dc777f299642fa9b940e4d6134e5bb3788ce4", "TP2": "040ed3833dfe56c2f100c2b12d2ba7dc28ee27e2c302c73f3eca5fe9fe17a9fba315187de752402cdd8bb713cd8a192405a6d10bab646cfc8d090036e1b72a3014", "TP1": "041e3780f2338d8f89bae52dc22dda1b52666a4752c3588f4b40613d8a894fdc0f163513a0037bdab90d22bd8795dc7e4472543dcf63caff31baffe517bb2ae3a4", "CS1": "041008e696cf7717a3a8174743a4438ec620b87a599ef082d9fd45ba6df7fbade02191f18a18f5b9c305768953a073af30ca988157c9b38c706c9d0641a15c561b", "CS2": "04107f958bcfcf5d8632185d1566fcebd068d1a95415084c47a9ee83c19a54a2712337989116a161ea49f56017fbf836c1ef130e71fa59a324987921f2eeecf8cb", "HASH_MPIN_ID_HEX": "f37b5498a5e321581fa924a594a81b151a1f80ad03947954ed6d8a8d05c23d39", "TIME_PERMIT": "040c4cbd1a8bfb6d9224687027bd358e2396d73729f8f47a0a39774176da4dff031ce34df98205e9515ac2d1740a8f5274375c37bf39f98927c514607b85329056", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34395a222c2022757365724944223a20223435316636336566333361653830613265653432633061303031383536363433406365727469766f782e636f6d222c202273616c74223a202238343666653338663137326264373639227d", "TOKEN": "04148a9b1f94eacda5b416d09be945f0bf957f9ff326449f11d11f66502d21409a1b90f861a93514a9d9223ff0eee6dcd3614215b04f1b8e598aafc012675782fe", "U": "040c03a41d14abea397fb17dd24e4aa035b8c36efad8763098f07289b7daf044ef08a5a69c07b0bfbb30a8eea51071dfb20cc968a7ead3c80c30686a1e60f21d83", "SERVER_OUTPUT": -19, "V": "0418073cb1570edd72490bb47b2e0335ce3694e42e130a417cd5786d413def24d7185950e98b7cacd30337cf42c7477ff1cc08402c19c6ed8130dc83f7120d30c0", "Y": "1e65251b58656528266d4d90be082575fb10fd9ecf579127fd8bc6f2542fd6de", "X": "1a42175ce5288fe46443aab38ba25eb0996c39e3f159bed59599e086993c09df", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:49Z\", \"userID\": \"451f63ef33ae80a2ee42c0a001856643@certivox.com\", \"salt\": \"846fe38f172bd769\"}", "test_no": 171, "UT": "041518849dc6b3263df942bbfd42c9464e907f369dae22fdc617c68431d82158c11064259e06d701aff4c26b97bf9dd0712a2b65348fe3c40114bba9d65d0421da", "MS2": "0e56f14984ca1197b1afc938d5a4dd1e85b910489b4c417f4e8fc472f2030455", "MS1": "13fc7595cbc9c659b88a32fce8d3958326cc77708c3905797ce5d77bc41bd9ed", "CLIENT_SECRET": "0402f8aa8c1b2670c0268bdcc96746477bd571e277e1953cdf35dc1c984c581910184f5dd04694a24c3fd7178134ad92b682cd7a42c4d3c21b09982ca8a8334374"}, {"SS1": "23f95fc87b1fe5e195627580566399bb8940be8a20260cc34ccf6ace6092d80c07da62370586ae739ec3893a85176e5cb705d9029f23cc052ebeba12582d1a4716cf405a5fb6cc6d3391a9fdf380d7c3ffb76f7583943cbc30989e206c77f34a04f608748350b2430d186c66a2ea03402ae72724f87c8df5c384e4f8f285866e", "SS2": "067188af2826cecc33ab16153675e2549e6f9bc9052ecaa958ed9d3d5f716bad2018f06175c056879e1eae3b7186d9075834416757ed8c8ddd362f36783d4a5c07259678f7ff7774e735b0f0cb27b4cad168b67e07f44a379c73d91305114b3e18712b20315f55ebafc4f7ffa74d012f8a8cd6186a313d7fd1c8ac85004e8acf", "DATE": 16574, "PIN2": 8725, "PIN1": 8726, "SERVER_SECRET": "21f81017df53b438a30866145b6bc62a341b26f71f9062ef2857eb790822abb42115652c77388d6195f5a1ffd847213c9b46af8801838d4f6d9118ce1eb95dc306c14525274c36f5d656ff6fbbb0f458864af147dddb472d406cf4bc1ea818d11a278e655359dff5d15f0e8de16b9f4b9faa6eac58f7a170e015f20a1bb3e251", "SEC": "041fe6b77e5ac2c5397a158cf7a46fcf78be2246397f945a5b98b2e8af68cbc56815d32d6ead42d2d31058a0af2c4b1c7493aa2ba57c4561524ca91e84435080cf", "TP2": "040a36be8b1b3fd4986c0765c7bfae42467e3637f8d941052adadf4bf293f21bee00959edc2204922b4a9b04a4dc5852d064bffe7eb5029e58d93c2512b37a6866", "TP1": "04178f0698b4144e36fe19c5f125cb94b05a9188ea878030b23ea1ddb9a58472d511fb377a4d04eff3813f4a6a0fddd4ad822d57dcdde6eb2e303789509d326523", "CS1": "0418732511c734c3497ad50ae53cd8da66034d243ece6a762c59b356662bafe7551437a27f69fabc66044eee4835165a88e9ab652cb0d278ab632c2cda6bf4c017", "CS2": "041098463d0c95578dbf1ef0a0d5325449701c4d42b85dc96ca8815117e5c25b5f0977b2e3ab4d692233ec609d5b19ffec32b517e4effd298d950c9d325af8e7cc", "HASH_MPIN_ID_HEX": "d26571fe11b72f86884481bc61e51a5b6c553e098a66f260d9007c13193b00e9", "TIME_PERMIT": "040cb7f0fc71cb0999ca978cd53e256537eae6b42a4336cd7bbcd0551fc505305f101118a25240c67f280e1d57a274716ee7dfb9af172cdf6472092394bac4f3e0", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34395a222c2022757365724944223a20223833396238656439663063303033653433646636666631663766393933313737406365727469766f782e636f6d222c202273616c74223a202236386265643239653830646561303136227d", "TOKEN": "0402c98dfb7515e797afa377d63fc67ea9ce4d899202197c44f6b3eb2dcaaee49301bf6052e3c31b201bc6ebeef7a1b56e92a897c9b27a59c64b8f3ca1052e5e62", "U": "0422d2a8dafa7e2d2cfb9e4c624a678a02f0cb4045e4d9591d10133bcb39ecc2c70ecee206126ae089e5282c2bf151f5b638be631d5899b82f27484b4629a6fecc", "SERVER_OUTPUT": -19, "V": "040c2a5fb6d18fbc10c5c92acf23e7d2869b5a16b71efe38394b79c2a9fd0e93950d35be6cf2cb8b922d835cfcd38fcef127ff0b5278b8d994761dae5c7509e641", "Y": "00440d3e63112f04d01d77b3a6d74887efb344520da6fae9ec4b0f96fb233583", "X": "1e2570d82f0fb017ac99b038d7139910bd250b80643075ac4ad99896455e2f87", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:49Z\", \"userID\": \"839b8ed9f0c003e43df6ff1f7f993177@certivox.com\", \"salt\": \"68bed29e80dea016\"}", "test_no": 172, "UT": "040b79d7d16bd99a0598eed8bf1fd0d575eab8f85350d4d96f3940ff665b90a1e40071f036f8913c8f83725fe5ecb65150a8ef803adc44e4c26077cd8b8b9b3f63", "MS2": "10e79848fc2b98791c0e6098f8b987fd0882d2bad7649e46675983f1b54134bc", "MS1": "12c58847bb28f20cf0c148f0d3d598c0b0af2fb9863025d5e2646a05c84cdc34", "CLIENT_SECRET": "0422b8eb1b30106fe2cfacd3a6adea70f3a088abef305556718bc1dae70981726f19dd66fbc3ddff1402fda10f4c35b9252bfad8174742521000f3eda5f4cb2b21"}, {"SS1": "22c4e20bc18920ed62e294bfa5564739ed8acd16c59c5a4545eae71e6bd35fab0339ddf90934fcdfc4db2fbaf896a9d05d604f98fff90056853e4bb1362b5c420cd86eafa2b90e3cc239e49a89d7a6a539466abfdbee8437d63eb96ca69435af197c094cf02d81f9ece56a03cddca229facd08b7f2a0c7c6422596bb08b08132", "SS2": "02576d557379de9d14f30e4a23dd87a0b1c875d59217b336065b9e005a7743210f2d617af86edcb4e055c1f8141da547eccf29c67664ec972a41b6aa6cbef52e1fad7518130a5bae5787610975820b0cae267760509c752e1c66221d8acf64dd10e830d1be4829c65014250f0b2a0e46a126c8162d9e3f02d238823ea6a3842d", "DATE": 16574, "PIN2": 7041, "PIN1": 7042, "SERVER_SECRET": "1ccba79fc12767c014e671479a41194143d24c9388352a2b292fbca72831b8a90d60b30a755270307ee04ccb08faf05e1f00a36610f37e2506c8185f6d26d89c03a9cc3106c9b80b6fff5b2cc96549092fd4fb19838c0cc2b463ad784aa8a68f1e567f3806ac3a42e250299c15207a01f23d4c01e7030826e1865183a3281d8d", "SEC": "04116a1125892089ebbb4a76c9f4955c48d7124ccfa85b569692a46a068eb402ed0d4090ff0b98b7b19c23f01ab8a464ad8d83b19b77e0cad58dcbaa5adba591a2", "TP2": "0405dac1f2ba879b7172621408de356c56a24b692e8f96c24115969bc38fa4e6f412b7f358da3239eb580d2137fad3f0fc81971d9aca9e39938dc77e21af510e14", "TP1": "041c425e6bea0160129bc74f7025235102e77e78c9fad0386a890e08a7af2c4d57074ec27d39fdb429a5fc3a18aa6d44e05bedc94c00b8fb88ba78a533ae9aab47", "CS1": "041f1cfab3c9b7492ef302c20249051e9f091b1095079a0ed4ce3b84294e8835d4006dbc7cfbfc2ccde453ae2aca51d1bdce5c7b7d152c3a7105abd0ff825b1f0e", "CS2": "041cf412aeb66161ae0de21cfbd8dc435a9f3c3ae0301cbb88bd6a3b350ae6f4341da4afe339d4e8c16c9460ab2934f4f97367ccc3d2922ade993926a2c061148f", "HASH_MPIN_ID_HEX": "e0a6f9455ec42a79e171fc9e27bb14130728ab823360f52ea0b026a7f603b50b", "TIME_PERMIT": "041879652a7c358f34a8b99351d5bef966088287d5b15616c9fa4d2967e051c71a18d7f5808fcf5be647c6089bbdd357a02e733bc87d539fc922d3656d9d425933", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34395a222c2022757365724944223a20223966393263643731623737346265343364633632393736663765613865386131406365727469766f782e636f6d222c202273616c74223a202234643330633530393135303537643066227d", "TOKEN": "04025a20b3c97185ea2163d13b99c938adfe40a498d52b62108d8402aa95f10c6a1b9b46e513e4353ff4dd1dd6a4411251285065571e3637de98ee1fd7c56a8959", "U": "04046c76e2dc1773a34f6416dbe02c5c58b47ccf8aea58e684c360faf37a10e5fc0b098cccd90bf94c55be052a70af28e3016d88f67894ec2ad50fab84253f833d", "SERVER_OUTPUT": -19, "V": "040863747a14430bfaaad4a4a76a547093d60a07880a98ab8771664862bf5e17be047bde202cc41718b0919d53ff4ac70abebae505ae609f719dd047b8aed99eda", "Y": "0a08e986b7741a4035a6a7748b8e71b36079ba589932dc54e22ccef960bfbfba", "X": "237b3de485ae0d3eeb3eac68fe13c50eb80ad6449daf9799358d04292bbb7983", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:49Z\", \"userID\": \"9f92cd71b774be43dc62976f7ea8e8a1@certivox.com\", \"salt\": \"4d30c50915057d0f\"}", "test_no": 173, "UT": "041655bfd0e4c387e86e252b4f14e4b873ceb29871e102f23d75c8fcfe9ff8f8bd18d86904206b992b9ae07236758a693e26acc778a38a6c0f5085e224d6ab834d", "MS2": "1e59c2b7e07010c5e4c384f191de3413f4fc1eb57e02d6397c89b1c2cd1d6ab6", "MS1": "07d69d0a3f330228d61f4bbdaeee7fb04190645665be4958de02cc2643ebdc9e", "CLIENT_SECRET": "0422daa4c33f2d7488ac513d10ea364bf9b68f58044287198a4e53ed5bb0a71c9d0014aa39866b130ab9ebe741af3a835949746f2dc34df9dea42e00793bbdce0f"}, {"SS1": "15f18def9c6b9fb81001a1fb7d531ad6d4edf097048ed071f6b6823238f507451fae13ccf518ce74ac71a875d11b27828b2d3008c786c7ca0ee0b7d93637bff3097a5aa44bb3faebd5e8a9ba2775df8b337f487dbc92fa5d760fee61a633ba1d065e6084bca29c7ee8aeeb48aa32ee10ea7f012c9b8464f2f891b5916d337c99", "SS2": "209d901366a2ab833717305dd50f08fd16668d8aa508906baf8fdb9baf5892e90116b71cf45b4e4742b99d26cd739e63845a4f7c3d9c656d5b2750fb7a0966210d3bf45dcaa3ff41fe1b702628bb6bffa2083f6a0c5ef3e0488b8c112c1426a607dcc4e2e4764afd79cfa0e9951615aaa74322e3e92eb2cc8f73a786688b1080", "DATE": 16574, "PIN2": 5123, "PIN1": 5124, "SERVER_SECRET": "165bee9d1c502b995d8b5074139b1b7826657bfb6e5f598d721322459e11e32d02485863e52c914a7c055940046d876d36285cf82bbc9ec786fbea654b1f460d11ebc9f88b7790b1846681973cb0548d5b247b89f6462bd82501dd472cca45641a209c9a282fa224ae088950ad3385539227f401bf3403547cbef456f334e26e", "SEC": "041ceeeffe736a7f625fc568b452cb8bcaa49d4247c2826ae3d6895dc6f77ba8390223d4a349b3226b2cb0d64253a7654a398a9dbf14d32e93df6fe77a25da4ac7", "TP2": "04068eb9e1a4051e5e51ea0b7f742b854458062d43267e370d3de2d60cfd737c3005a6eea305ccf5298f22a9778c551e4f1c11a6db5fec2cae3da58d3fb4942232", "TP1": "042174ff5b92244bdfea4d5c76c94c4347bcb407c89d22751afdc77c762334b4fa071c082eb61490a99c7934bc616cc99d094fb1cd4e2d7614a28af75890e41b22", "CS1": "040e6da60a0990597f2e21d1e25296da96043a99a005e0e15f64ab2515f0a202c806c98983234d7a2626eb6ab6cb4bc4a5bf78fb6ccaeb2eaca6032b242bc5faac", "CS2": "041b58b627ea86a5d3b8f695b87f843ee0928ee8de265c988b3147bf499c56080f1715024ffc708b49395b9e5d0bdce45b642ba627ba77e0ce81cf5ba6d9825bfb", "HASH_MPIN_ID_HEX": "5ae8061f7712afa45ba8fadd4d5501042e7e23962ce8a0d46406adc8c3ad7895", "TIME_PERMIT": "0400689f35b87bdf37b1c236c4871a52f07ea2279680bfb112480c47fb7dd4d7891d8ab3e65f8dfcfba3ecd555ff90c8c29e16ed0a6a24531e6f793bc1a89ef474", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34395a222c2022757365724944223a20223031386439373632646166356633653436353236613639373633623635666335406365727469766f782e636f6d222c202273616c74223a202266636134393466363363386232633339227d", "TOKEN": "0417f18876c7ccc7fc30d03bcd89b9077f71c4067462f498df66b9079c5172ab581342b23d88d5f4b6f47e48171d93635461f82b88bbf947ae3e3b799839358d59", "U": "041dc1d30551eca7b5fa0cda6796ffd99abf0844a712ed36d8ceb3f9a6a9188eba1528c8c976049eaa8bc79c86332ed9aecc76f34396f21abfc10d1dd15c38d281", "SERVER_OUTPUT": -19, "V": "040d26046a01058d73b5150f21ab7c4b3dfdbd23bd10c9e26e499a67910b8f2a92139d30fcba083db81512f36460178718dfd11631bc9c527205cc4f7f3732e1eb", "Y": "1cc89f566b456e11a7128857e37dbefa8b8789e0eee19e35037df8e4c2a81a84", "X": "1439eb962cd4c7830614a2906e41767933b7d48647e8e2a142f0cda61da356eb", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:49Z\", \"userID\": \"018d9762daf5f3e46526a69763b65fc5@certivox.com\", \"salt\": \"fca494f63c8b2c39\"}", "test_no": 174, "UT": "0411d3d3593265735526a9582cd043d9de9277954c8ffc2f5ce0eef9920945427c020e0bd443f42d851fab774ff72f4e51478e38de9e1e72ce70564e6d1d764c46", "MS2": "1d43682488dde672e8baabf1e45dfd18a916179b4e395d47d70d5ba6ffb0b1a4", "MS1": "0996015d7d2cf19091d3524e5c10dc7ad8016e04c92e9af70eaeb6937f330273", "CLIENT_SECRET": "04222d13b1cf35a03795731d8f70fbc0441591890b54f0773e2fe510365f9dfe141e8d6356fc73591625795d9a7e424bd351c5629bdc6b453c1b4fa3feff311e65"}, {"SS1": "19d593b8127d5a7050fd6d02c2eb2e09722c91003a92bc6054717c8e0a540d3711290e3b279b45cec7b9d1c9e25eb896ed5ff175fa407ae609711de43c8ab53e1512544bda825f84d8c11d136a9f7d7d1139860f3f760d8ce0c1f1a33fb4b8131fe18e6dca9bdba97b36cef318385ce314f5ca763ef4a12422b649a85e6e493d", "SS2": "1c37ee423f38ad6d0d32d5cd1c1d9b52c2e4f5bb3a56db4ea7f7f0a7e4b349c103319f6fec5e1075ed63c73c8450f185c9ae1d387e32232def8467995c7afe010d6e6f10db6b093577c15769d718eb7fd9f7c3a18d231da68f68d62813f60f891c8627930a874a3cf16c6a8e3c03b67efffab768df7367d7c9dacbad2f00bd3e", "DATE": 16574, "PIN2": 4133, "PIN1": 4134, "SERVER_SECRET": "11f45ce9c460ec08958919ee28c378653f96f9a1d0a5cec1c97a7e5e7ba0fc1c024921f7a05fec827a2183367e032746180e80745095973fd2163a5e970ccbb712faf3437617da9f65850472a24d3795c20d60d00edf041699843434188ee95c0899df5b9ef1dbfcbd617dd841c5edd42dab8bd56a02856db018c8fbb95fa9fb", "SEC": "04090cb390188ab16c83a49c1b41a4532f2a03c61c163586c5d4f1362f4e124b0709a2037dc8d1cb851220fbf89b2b8da521b7811d56b528863464d0f8c72a2b7a", "TP2": "041f69c07ae6131d0952cd26dfdba7e3b7b8aee45b26fcb1383850ea4f3b601f7c15540cdc04a060e5ef54a603a6ab6d163119a6a1a41b190f4b6f868ba0db8d8a", "TP1": "0422952ac08e21a1e036a00a9a3a42c862ac1047f7f8515f09876b0f0127497231098b17c440f47bbac349921a4208b2fd41ebf3a3e1736f58960e17aba3b64188", "CS1": "041202a41fd68ef900d3e3f961e27776a3d08bab1b2b5923308d3079ddc173e085115e213f420dc549909510c5b40e54fc1854ea8bc33ddf8dc303d7da48cd4477", "CS2": "040bd5899a4af099f16f8419e08cdcc69537082025ada5b2d2fd522eaea19e0d9700846928b1d6462f434c7be3e27e6e143b37379fac1ab02e351f6de3abcfadb0", "HASH_MPIN_ID_HEX": "53416fe54202104cc8e1aad00012c07b06b0a23cd3040205dd67f1fc512fe51b", "TIME_PERMIT": "04118db9857cc9b15f6f2b10058e4eea91297513f2879b75c7b540c890636c85501a0c75ab08be9688154f82a842ceb65b313255f5eca4a05776902acb0e0f7957", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34395a222c2022757365724944223a20226530666163343432666164613766643131386231613735363165373637616566406365727469766f782e636f6d222c202273616c74223a202238326335303466663861333762633937227d", "TOKEN": "040689451919f63ed2e16fe103a965c5b2f0cc2d9b4a64a4f61ae30b2d93da3dfc20e6ee530cb515ea5b4d486f72c02df7189e73b02a08697e92a75980514fff11", "U": "041e2fef9be4522dbda8b0ed3a4cfb18ad6484a674cec976f80a7580f8067eb39f1fbe22b0193660183ddac22e74aa6cb40ba0dc1b1bffb3441c59d094689c238b", "SERVER_OUTPUT": -19, "V": "0400f8aa1e727742fc827dc5e10ecda6c6d5f28d52d7659df25b0d884f089f39e7064753b2ce4aeffea5e0b7216c77d0b1cef1ff4564e2cc687931994bcc7bbf2b", "Y": "22db1592ebf6474480a6149946e87202ca834695ad7c0fca9996cda7de1f5b4f", "X": "176bba43f567b3e46f329a98f43829401aaad7f9fbb16fd0b2826c0cb5c3ca50", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:49Z\", \"userID\": \"e0fac442fada7fd118b1a7561e767aef@certivox.com\", \"salt\": \"82c504ff8a37bc97\"}", "test_no": 175, "UT": "04039c3de545e087b0cb426928f09932d126f1b9986d6532da51c3ea2255ad503c115b0ed6e9a28ed7f8b48b42d2df2023cf87d3e47cd0436201940591761acdda", "MS2": "0ef67569f1af42666966fe509035acf180c277149d191edc2a39092fad965b81", "MS1": "2360edd2c3c4760aca788879711f9a8c946172c4e3e824ccdd97e60458dbacea", "CLIENT_SECRET": "0409c7137cc113c452cd700a95726900bec31403e4c01a38c7b127d25711a32e3c23ad75f7c33d591dccd0fc2c35e2f6b508df4fe987304c9f0f9ec67dd44026b4"}, {"SS1": "21c2f6a47354515c343fa0dc4bc7b82d45dd21f8f65a5c880719b1fe4de9f1a315fbf255cd464a218e0db9e87869b1ca802a0212b6b45c1bdfd8038ce21fdb9f0d7461d379d17548e909f66aa79f641afc537225defd547c4f0c5382bf5368b61309c15666b52605264c3b3bdaf316f77f8c364441f2a5f4bfc5ece34df376d1", "SS2": "05247f126a474026f1b2ce94329b286bea07fa9c9356f6d2da36610f2773890c1faafb86adc1d063995cd5268d46db0074f174ca8bc3e2a0d507b39a8f7f609219fabdcef94d4160884c128a820bb14e6ab839d52d68d3eec451689c002637290a4fbafd160df31231425341bc4ffdfc650fc42b0d3ccb001d37324f30f53c9e", "DATE": 16574, "PIN2": 5924, "PIN1": 5925, "SERVER_SECRET": "1e737e5a538b829b16f32e1564b0bed0f418bc654f0b04dc30180a276e778e9c19bee37ee8776f64d4cc864bf4b97fabd97a4b3161beb3a61167d0e322bafc23193b6bd45d44ae3225929204f23302b0d7266249a1eeae2d9ad4feac6c5c2bbf1f6a19404ca7d9fbe423bced63f1d0f50581bc09abbb29438e9ae13d9b8828ac", "SEC": "040f92421096f25926ea594e37fb4f540dfc4a8f6d3f19cda7ff7f67c44ae6e2db22f9348f59274d9de893f88510c9afa2dd8c7de54619e18ce156b6456ee26ce5", "TP2": "041dee90f45afb604336b13a825f68ecd6f72dabc1c37feb69ebd69a6c47ef83b61ed2dc9cc0c9abd349989a34bc220e04c8f82062cc24cd7612f416b7728a5174", "TP1": "041fddac7f8000f588672ddc5ecf44ca483717512cbd6e1a7ab6448118f1768f4d19fd66a2936c04884141b6d3f42cc3d3a3ff8bc8fc254f6895e58be2ee6de3cb", "CS1": "040e135926bf6195078474f156668de6c003e1c1b29b32ac0f6c7440af9a24f5d51632764af8a1f0c43755991d607e5380597dc3e69d40909a0c315f8f93f48620", "CS2": "04007b63cc470bb1a0eeaf60a49b32b01b22782215d01cb6bdc1c2da6444486c2c2179b15eda26f0eb40b7b865aa98018f9619b329d70fc2f8000077f2999e5828", "HASH_MPIN_ID_HEX": "bf59f520d00199e0c6e032d8945b6111d2b1c8d001f26c00be25fea1fe0b3cb7", "TIME_PERMIT": "040de2b60885df8d6246cec8b3ae424053c4252da77b1bd359cf1ccb3a67d4fa02239f68fb4725007363268e25b1493c6cf59c350d481ee8d82dbb0bcb74631387", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34395a222c2022757365724944223a20223535396530333661636436663030396532306164383136326637373036303061406365727469766f782e636f6d222c202273616c74223a202237323661303635623330613535316663227d", "TOKEN": "0420747f2ec3587b752cccb1a679e26e7c9a4958d2ff1391c416d309967645f79a02332e26e63a68126974bbd329ffa7d4b620f47e550fa9e427ba89ebe9f8edaf", "U": "0409fb4edd6f032f85505be0438516bb1361492c74071242284408b0d83164b6281107dad66b7383ea3d92e4b6e87dde608ef549b5ec5e9f78e684b73a47ffb343", "SERVER_OUTPUT": -19, "V": "0403b4fba9ed12df5988d947ba15ee0b093223f50ccb1da4c838621c15acae88ea05bab66f7587ccf6947670366549c85f574a092e4293697256c0fa77b640e413", "Y": "084b8d10bc53fe0e1f37f1e032efcb7d406978d007320d3a65a52622017b31d0", "X": "224224ca9d0a0e3de806dcc48f9843c47c19bd69a8a0110275166ace0f6c573d", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:49Z\", \"userID\": \"559e036acd6f009e20ad8162f770600a@certivox.com\", \"salt\": \"726a065b30a551fc\"}", "test_no": 176, "UT": "040c71cda8b22724cbff7458ac87dfcb42a4fce4439df339acee4b600bb4edfc9623534b04aaaea138c79da56bd4f7f15483d954f1367f87020155ee93d95e46b4", "MS2": "0fd9759219b05fe6d6252773f759964f672394cf64457f66bafa18fd9edd4c75", "MS1": "1949ee298bba655e4159c266c7495c00e33eec1eb8d4f0d0b2a0b8d37f3a3a40", "CLIENT_SECRET": "04096037b41f1a42ab1d64e5705aea541ba8231dddd6a0c750f808cab29204b4d512decd4dfae9a2890424c37e4c3415507ce7716e3424cd15b5f321dc20804470"}, {"SS1": "0aa85ff4340d34ca668e65c885cd0a12a950ebdbe58631640e5542f2ce067a0d05a3e1015bc1dcc9eb6913c962663f1f33b161591b89bb9b6e009b01c3b4e5e10f7eb1cdc1ffd5f66ae1cf4b425e01b898bfb27b1ab17365d6bf54eecbe967bc1ec8562722ada6a32fd70d1e6fdda453dc557ee137abd650706ef646e7d1e829", "SS2": "14bf067f0fa0acc806c736d55d4bc875b10d419aa74efe2771831da24062958f16625277bf419dc49ef8095f827c0076e5f7ac5341863cfcdfe272509e20704c04c73c2f9b412e89e8b41dd6ffdf894da125e39f5c4bedcb72361cd033d9b4b421c76ded206758040e9320ad37b28fb4ec08310b4d4c87051cc29c4d7d4fd3c0", "DATE": 16574, "PIN2": 3870, "PIN1": 3871, "SERVER_SECRET": "19d2524879cb8670b3922a993a549bf217a7ee9939cf096da4af4b8e638eca5e0e4b6a6714ed9cd85cf4ea9ed9bfa80ffe031401d8bff1ef598ee634b67e7e5211e71b2792a7283b222ac4f7dd2452f5f6280b56004a6dd82ae2355925e0056a10e64371e1e506fdd12dc37ac65e10288db8315084f6d4f3d61d640988720fd4", "SEC": "0416c90436ff9a46214f509ee49cb8c3f6a62e67db34157560d52b1537fe4e4ad8003e62db961655b6d946c5daac6af11000c8129f67537e3afa8c697765051afa", "TP2": "04173c87ff4a5b3ded380c1c31990c472dae994a6264b90bc1d5bd67ea572ee20a004a73e30bd39a152fd5ef21f23ddbdeb35e00e0718cfc8006632c3d7a3e3c91", "TP1": "0423d8cef7501bbca3f7fc5739719a08b2671376eca63c0aefc271930be8f5dd751772f9359c72c2d49d926d0a2736aa7fea8c64a9dcdbead46fb76ce7431e9501", "CS1": "040b28fce6e8f5db5a655d68845b0451e6bdb9cc126ee49d2112e978bcbb972d2906a57134d3de2776e107522986398213033e7f9eca03cd5e5037b4d319c7c612", "CS2": "04082e90df17a51cb2b13cb967257d24bd3aad52c81799945bfbbf5ab12d619ca10351358b415a818c855121e93a9f003c2640d85cb682a18f15c949e58ad82f45", "HASH_MPIN_ID_HEX": "3d3da7b83a55c772dfe38067a86c5cc4b140578555aee077faae8e7fca3b467b", "TIME_PERMIT": "040ab7617aeeb39f843fa339aefb5be8f5a94fe78ca15a43ce222e52b58f79cc9b086f9264ae6619ab0dfb07e87a0c0f3b2a1fa6a1cdf2cff34acefa31c831359d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34395a222c2022757365724944223a20226633653064366433326661303133323266333663653435306537326437633663406365727469766f782e636f6d222c202273616c74223a202262373164663638326530643962343739227d", "TOKEN": "041882d8f1249915dbff2c73fcfa3d20c629e383acd58ae3b4011f8c20c421acbe0d8d55b641dca6ff6850a361e1f9e2c8e6376cd7ffce1718f73233db87b30b23", "U": "041de0bfec14a310d56912a04e67027348479917d66178ad4554d8d7105605e6c91a013668ad33ccc6643b7775a51a0ef1600d1578b7c9ecbfc525510da21ef945", "SERVER_OUTPUT": -19, "V": "040701d9d530212187ae882b7c0186fe30ed2ec6c2ef974958134610a28a943df811f123bd2da9e11e9324d4acc26f94d43a5a7275e6cca94229fd3ebe11fead3b", "Y": "11de93f562a8599397c6b62dd29163a489a1a1447f228b484a80976ba4b3d1fc", "X": "0c7e537a2bec19e5a0b0a16d5f79fae472e178f7c1730b7a18f89bf8e01e993a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:49Z\", \"userID\": \"f3e0d6d32fa01322f36ce450e72d7c6c@certivox.com\", \"salt\": \"b71df682e0d9b479\"}", "test_no": 177, "UT": "0407c28f84b6a56a2f9d12769ae8a942c5b9344b7eaef91846dc1971217641764800b5b6471fc0203693c19268f3a76807937e1faeab48cba9254501bc59e797c1", "MS2": "1ac1ce5256b037d8e02b08d3566aef529ba89fea72d8c70c693ff13935494db1", "MS1": "0deae51263f10508fe4d30d0a2358e3fc45d728e24ad21709fcbfb9025520143", "CLIENT_SECRET": "0412ad59b7496f5783ebdbeb2b37ea84d371dcc7c4e9342a7afdb139ac87e714770e4bf2d39ec20bdeeb936f2d63404563304d63ec0880ec385a91c445ededb384"}, {"SS1": "01a5bfeee6eef4942d3060f17f4946b32cc2101d03c0bee04ad8df7a5d8d6a1206f38d00ca35b345f8c8c582bf8ed25b60ff0c5b492b3c31c3f5f132b0609baf14ae309ba7bc25667718a1e6272df3a872305e78b271b9bd519c391244a2d6ca0bb38fee909e88b5c44107f2cb6866650baf91257c1facb2b969b44883c09ecb", "SS2": "0bb152c592918071972f786674ea59efc638e0a10c651d924071fffe44de2a980e49c150776b0e7998b501b3f433edffa28d2f3271b2c9724b241197b9b7a6f3101dfff717ded175a72572be1c3f5a41ccac421c81679df20f39232627af840c0e4599dbff49dd3229586b1a5f6fca02d47512b972e36d5752055d02266be7a7", "DATE": 16574, "PIN2": 8808, "PIN1": 8809, "SERVER_SECRET": "0f5e1dd745cf21aa18af4e1fa13373902f63660a2d70fe330e3659b6ae79d1be01577a5f0977b8bfa0b02065924cebdc6e47dfb0fc2cb3bf6d78cd8457869222016341f737038e08603828adf3c8bb370d96b97e436879cab35b84bb2248d3f1065ccd0eb778e48d306df592fac2d863d56aa37af144bbad69eb2c1ac22ce438", "SEC": "0414ae2b589cc4336807fe315566e0626a1099306acd046e3d169bd2ac44a9821c16af16fdd82f84de90de84cf1e4c3a33e4b044300f152c344af216c0627ebd65", "TP2": "0419d7bb91c1daf0bc9e4c19911d7e1106de99358da33405d3e09672b55a628ca30791c2aa8207100e4fd7d3d431429f74e0a9e3682f5b52c63243d8d710a881f0", "TP1": "040e704b1d70d1d14a70e0250ac9275a36bb431f19d54c47353646e0e1c6f2e448036c75a1fef4d08a32b3bd7549c1c2bf3f40697a85440854cfa88f891fbc23a6", "CS1": "0414ae4248be3b65ea3a2f13e502abf8a38171f763a5bff97dc07983911e77de1c0c5c6933f5e9d931c8824a953e78f950dfd69bd2510b0ca7046e90f7fc2c383e", "CS2": "041e857246bcdb80c2864b15356f4c5dfd49752deaaa0f596c4769710c764154fa030698330b33176b18513ddbef151418d3a9a8f00628fee6af471b6f32756dcd", "HASH_MPIN_ID_HEX": "3dcb1cddb86869c4cf84ee83a9d31597fbb55ef69e0a279e67660033c0773a1e", "TIME_PERMIT": "04150231916253d9c7bc74e289ecfbed77fadaab4c44acc7250aaf4f0c35e05b9f0be17ec1222422437a1fb1eceafcbdfbd2a229a25631e95756e592c02cbd042c", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34395a222c2022757365724944223a20223331616364386562663935656664313363383933376662613036613234353739406365727469766f782e636f6d222c202273616c74223a202265373434333836646662333135323566227d", "TOKEN": "0414db2538c30ef918884ce198ed12dbd16b4e32c82f9d44434f8c243d6e6a951f215201b33f8b72468e0b2161229bef114503ca70154bd979d8ef7e650dfd1359", "U": "04157ef141ccc4eab3e6ad788885578dc94131cdafcc81345bc0d7ca79ddefbbbf14c3e5c53df0657d17e04d238c1909a186d014ad5d4ef828d0b6c8bb620cd782", "SERVER_OUTPUT": -19, "V": "0403f4b62e9572c6810bf6f7a0ce1765f0edc5055a8f75e9d5efcd9b35b146bfc610bb3975f0451c9e2b73cbb38efe9e800fed2fc9712489cec8294858634550ac", "Y": "103c80c4fc679520979e25d5d1ace1d2cf981e3bcfc0fc40e437d4268cfe9eb3", "X": "1572cada7c55cca3f36f63c86e28d666a071b592ae75a0ff546a232d92fb295f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:49Z\", \"userID\": \"31acd8ebf95efd13c8937fba06a24579@certivox.com\", \"salt\": \"e744386dfb31525f\"}", "test_no": 178, "UT": "040815fb4083cabbe6e632c13f85b45c987ba7e5d8ee7ff802d67ab1d973ebd98c0c7d6fde62b892a553b71f2f72ff10d13875460df4a2fe4e169eb09a5b4aa4e9", "MS2": "14f0787b0fcb933af936bc5e3d7f6db759b43a437b279f2c2b64c7bcf05ed175", "MS1": "136768bf62b17df6f33afa0b9bef8d5d642775f0e9576f7c32fce976c724087a", "CLIENT_SECRET": "0412c8fe0b9900129f3792dc9473790264b83eaabeecdd54e21ffe43e48315206f14b47df74f80db254ea4ee5ec5efb2d03ec3c43b03fa6414e900c1c7e95fc3d2"}, {"SS1": "070a65ec57dad0e971fea646acaedbf1448d1b4b91a78bf6e196614a7ddfd81e00fb7af6ac3245b56a38d07b94b3abc8fd8145f6079bbf2f46c06448af8fe60623a8dae98faca018bd594fc39ebefafeb44016a5b46f8dc9ae0ddfe8fe06b9531d83b3a9553b121109506b688b572dfc6322e02c1f4ef468ea0548e5ec978425", "SS2": "1f1e5e4c3a85ffd3bf6bcd35e33ad3832e6b53653df7ccc45e0be37069f548b5131d3f2048f3bbf9f95b2892b5c2a64c4bf474453dcdb3f5679be3136c3b6afb0aebb45a4588602976082243b701c1535b888e27e4f41bfa8d5c1aa67bbfdc4321807f53f7e76d19c472b8e1fee605f5083954f75a4bef69209991085623f799", "DATE": 16574, "PIN2": 182, "PIN1": 183, "SERVER_SECRET": "1b04eca08bc7cbdd7288644da2bd2db06f7f0b424bb52233707b0b421634e9350372855006797519ecf7805603de9792b60936547131ca1770076569551f1ea81561d31dd66373bf3b44883e1a35f1df380c7a0057087975ff9194823c8b95a902fd49ffab6fb024991c8f84d93dc1317d6f5a078bd4f49fc2d901e92a914451", "SEC": "041c9870e1a3e5613dfa548e29e2fa5a015c4ff31566e44446929d33b009fce10d024ebf0ff1daca6354be0a8e4fb515ca7dbdee7a52d44a3a81c28c3bffcc7c32", "TP2": "0417db6768ada5b9730ef65b020e71945c08dc2d6f50263973ff3e254836533f300b11507e73708ca4eee0b619f3e8d879e1cbabfd7750e40ab010ab50c7a90bb5", "TP1": "0410d37351b04dee709bf02303fc4fcc58f5bb60883349d9b6bb230c7a977a28a91719de632417fd692b743e453371a46c98b6c8cdcf971ce944f914d42d118d71", "CS1": "0411c91971f9a2301f69062db2099b2e2fe12eafb039bc590a7f6f06adb2e07ece04a53133ee90fa34f80c80503a1bb17bdf03742c06bc2a008d38109554f901e9", "CS2": "041177b5e0f42b55efd397de2c3e2883f5d389252cc066461bb51e6ab1de2da2be0c728dbc664b2cfa30216abe2c188c6a3e9126e9ffbc59f348728e32faff3c48", "HASH_MPIN_ID_HEX": "559051f00b835900c9ad57e8edf6818f06238734b1e3e2c201559929cf4c11d7", "TIME_PERMIT": "04167d77b46cf7af2bd8674af12db60167acd483d2553b0876194a75cf617f1e8b21e1cf09685329551a0af064026e19afbc40af6165617179f6d1b47bd51ba68f", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35305a222c2022757365724944223a20223237393433623366366335393466386434613162613066613566633539313439406365727469766f782e636f6d222c202273616c74223a202233343731363934323533643362656539227d", "TOKEN": "04006c11e92c7d5f7439ce51cde88f63119eb5fe32b1240e372de5346ba0ff820723174b0940bb86520cbcc4972dd17015c2e020b3591c2488d52fe681c200c6ec", "U": "040383f8854fbb0039b520d21e9093437943e4c831c2cc39a6b5195626a04ad92408cfec31bbae99f9db080740649ca2ec99d46a342828e82f10389197a9316358", "SERVER_OUTPUT": -19, "V": "041b57adb346048f9d3455e4401bd9eabc4cfac5cf7d0ae141bdf4a663b81c61c2056a43c4acd79ea7fb67b60af870ba480d207dbd00f1ef4962e470fb484c6e6c", "Y": "0291af284314bec5c3420cd76187c6243a4dc2c5867070e9eafb8bd68254270f", "X": "1e2354cf92feea5872690289e161264fa930adca19fe3bb7e85d22f319cb059e", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:50Z\", \"userID\": \"27943b3f6c594f8d4a1ba0fa5fc59149@certivox.com\", \"salt\": \"3471694253d3bee9\"}", "test_no": 179, "UT": "0408c7f88f31a487e94b49a704e6456c216d1efe8e919763e5f5d3b4beebe2aa460d92dc72014f3814f5151a5ac4e148a24b1bb462b59ee76cdeb7c8b87e2bafe5", "MS2": "23bb58820fbd08c08d389c493f8bd5c2791ba5578c4242917022b21c7300d62b", "MS1": "19ce5ab6ad6d0e465051919728bb6a89a647d3fb6c733af820cf2ec03c3d9691", "CLIENT_SECRET": "04073d9e192b399070f0c5a75d9630e6af0eb92c41680c79a259ff20bf55735fbc1f0db187fd366142f486ce76e386a157556de3ba7c926573088684bd4ac0aa46"}, {"SS1": "0c94d67edcf6a02d987ade2a84f95377c06046d482519c2d022d2d40a82ba280162fa418262b2a17b7d862c4ef3846858361bf6b45174f16c49454e551e76487222e7e3186b8ed4024b9a8db9f92961e8b708079d41800a92e282222de92e96004349e70ceca3007136760b6d34888df25eee760e82d72d50d7096d631b674b1", "SS2": "18a97b4a9b61c1d9bd4ab550fd67f9eb0586815130bf3fd74ae3abdd41eaa2141a9e0f4e88faee702704b345d9daec5caa592aa154bd029b989a6c2675116d9f13d92ac0ddc9100c57e9fd87e44eec61d6751f8092333c51e49faf2e1429bc9b23467fdc7db83186e44217df771bd9ecf2763c0d37517747930d13958b6a1704", "DATE": 16574, "PIN2": 2075, "PIN1": 2076, "SERVER_SECRET": "07f9288c32e6d9462486e3454eb4b331c6be9395fca5abaa42fbd66a4619da12067a9a51724db4132be6cb4af54001d70901b8283b9f4fe97e82a4b5fd7703670c93433122207ef2e74e1374f274374be21c2ecc50376abf33d5dcf4c00c9036045c958c3b31c18c66d512838296308fdfe4c06c7387a1ade4cd4dc21bf69af2", "SEC": "040b52eeb23556b5f034f989a2113c298547e89a2d955cb2f01ca848b1f9fa069211885fa2b5723d7c49df133faa7ac1a7e4fbea26948fc82586d859217f126447", "TP2": "0416e0e28cd24547c7f9ad7f40a5ba261c1428d42b1c159d28a0f408caaca26876162554842195fd65f6c74fb284c560b9fef3e9ad42c08f76b6ecccbdf5bea61d", "TP1": "04112efbe818d4c99cd3d35feb1937361cb099f7a970e9260c79171bc5ecc63dd70b5ececa15eeec6049332952d3d93131d089e0792c5887f25d6a880a767948e2", "CS1": "04110e166721fbb22f3d809d97e51b46c403bff6957f65d2e3722d18845067c83e0aff2bded6685669b36cb9e228047b5d14b588382d411dfd82d356654de7d953", "CS2": "04073bf0dcf37fc6e8604032af2ba131742b9c40aa0fdf417cf4a4373b18322e6b03d976ca29314d471bc50817462bbf3cf81bc303b72696e49dc94e984881ff33", "HASH_MPIN_ID_HEX": "c15b673e038197f3b187e1271dd783b70fad7295efaf44b76a1de25fa78c48c9", "TIME_PERMIT": "04002b6eb9bed31199592cda8e697562253b3480a98030a5528b5ed345b4851aeb1642662aaf8f74c5bea6710ec700a6dee9f82ded65b7ff2b08d874b48f01ae1a", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35305a222c2022757365724944223a20223164333838626333396131623934666561613266623634306637376466353062406365727469766f782e636f6d222c202273616c74223a202236633931393364643337643664383165227d", "TOKEN": "041051ef739916cde494b53fa3891f3233b820b9265ec051f810ad2f0cba8419bf1a6e174a3dc202158c93e6b2545aa5c3d827ca4dea67dcce0f2a9603e825c49d", "U": "0418e61d12001f679c56c3238fab0d2fa8d26e33670969d01bd6de193ec8d08b0a1355a4e3e56c2121a72827bcc0f4639780dda355b459df34aff23e65105ccc83", "SERVER_OUTPUT": -19, "V": "0418470ae1b6281c7dc59a0b9e1b4089ce28cb4852d86e8d9b91ef6fbb2489be780b78c2101e4a5ef05f402fdc87b8feba14f1a6c7da24174bc9fa1d58a3bc5418", "Y": "085d2bc557864d96461336bd81318e70a1203723edc53ccc31097412a8f21596", "X": "11048b386c77e82a67f8aed46584c29844f7e9ab8dc56d30657a10941340a5ab", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:50Z\", \"userID\": \"1d388bc39a1b94feaa2fb640f77df50b@certivox.com\", \"salt\": \"6c9193dd37d6d81e\"}", "test_no": 180, "UT": "040e9e4ba846eb4a14c3eb18b0ac5d52b335b3446d913d588448f8796dea05960700eb69a23fd9d37e9e14c4f0ae894ffd3df923c47c84fc76dbd0d88aee666dba", "MS2": "1d3b171cf94a80ca0886757f05daa706bed2798ef79dbde1c261d7145cfdcaf3", "MS1": "174e75a18068197f39ab8ccba347ec54351f3b72b75062d9ae76160f40b6728f", "CLIENT_SECRET": "040d98936081aae4eba3b0d98672b9e0e7cb146269a18c77de02d2147e770bd53f1a0bfe09d6b7f697d53fd64127f3ce7909715b153874fdd05f51771f472fc78e"}, {"SS1": "1ea049401f520c093b1a9625177b06a5e1d03eb1a319389b58026560291edb2517f725d69562ba5efe14d437787f8bb34d5fc165eb9006f72f6bed17689517fc2321baf96448caf24ab6717538d16adf4809dce8a3be5224de7dcae64314ba4a0f098fac90f7eadc5e5e6f5cdc5b960b08915bc1f061f645b8b8d85450dd9330", "SS2": "0610e705ce09ba2ef6c8f32dfb9aba895b489ff5dc9946c075ddddd4f7d9b5d8174c63dd5900108c05ff24b9e28d375088facb6f8a28a3a6b00f9512ae22b2a510def2d6ac65f1a5d4becc6e0cb5bde08787a7cf2f723176e2c0909053a424ed10a2fe006e02ec0865c6ae41f618d6249bf5e082311df66d60fde2d453c1c29e", "DATE": 16574, "PIN2": 5544, "PIN1": 5545, "SERVER_SECRET": "23589ad8a14697d9dcf5ac2a35cd2fd30708ab864cb25b28310429a815308e4b070d71e237614c59c485cf74a114b19d61513cf2430a6ea077b25f880d3a019b05758ed67560a82e0c3337d3a5ca61b9ca237165624b385e5c72ba3f1f8658ac06b96411d48e24c87110070ebad255f47177a440ba7e8d02512e51a9ba6a9140", "SEC": "04089d62f0056ee44fb7f694fec4474f9ee9aeb8ec8108c7d84a3f84d61cce872309d1ac4da218b4cb5c631436ebd399167487417756781d6c4ee0c5e340b08a9c", "TP2": "040b66d713305dd12f3be74971949f144a49554e44557c2c66ca2e9a0f4690950c0bacadc9ca49663c6f62a10b6e0b9c2c17c80d9efa7faf5434cfee4458d19024", "TP1": "0414239f86ea3043cd5448133122eeebdfbf9a367d6eed4825f085ec8697b56ec819d6066d0005c84f3850f46b228bb8907e5250edca9d4369a1acc91ec49c4c95", "CS1": "042180dcccecc736d1df53fe997bdb0dd394b72d1292c1342d1bb554be8f95b91908353460789b8099561dfcfd68237b6719ed3da285f484c0cb98c90de827aaee", "CS2": "041b55ab9cb9b0527f8ce78f5c7448b97cb82be2509abccd1a11e1613c0616fc9113818a9272a622a3af069daa431a227d8245b37ba03ed43056963d82bcef08c9", "HASH_MPIN_ID_HEX": "4f2ee14b2a86ad6640de41adb9eedd8bcddd3a281399d03924592727dbd9f3e5", "TIME_PERMIT": "041b2ebd733ad9a84770aad89493f4fd054f79a4d67eb03d5745509ffd38af0df9196ab254881290c548d0e18e4a4588d9df343f544b53c63a8d8b9efa45214a2a", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35305a222c2022757365724944223a20223137633562313333613364633738643166336238306464313931373361623662406365727469766f782e636f6d222c202273616c74223a202238663066306139356139643332376562227d", "TOKEN": "040d3e06fa085d4ca8fe6823c7474ad6b5280689342e1f975d16e7aae63e2bde0c009123dc91edfcb68fcf32a61eb5b521e687f35311290acf9e84f2db57cf085d", "U": "0407a5b908ab9a8be4e5c718ad6c2358bd2cdaec50ddc049b6d8c451fd6688eac1140288e9c0769d65bbee1d647eaf65650d6915395420022c15543343d13cd175", "SERVER_OUTPUT": -19, "V": "0407347a654c2cc0c8aac8940222304f951d7c2797a1426bdbd2cd2dbfb27da73f0c98151aa3613b150cfea9d4c571287a395fa394ca4c9cf13834770cfd5a68c8", "Y": "0fe1d5d781cecf59f32a7dfac7f9d17e083db37943b813eb569de05500ea2ea6", "X": "0261af3c24e0e2e097d30c7eade33dee0bd477e7e896cb739150361183e34e10", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:50Z\", \"userID\": \"17c5b133a3dc78d1f3b80dd19173ab6b@certivox.com\", \"salt\": \"8f0f0a95a9d327eb\"}", "test_no": 181, "UT": "040512715fd285626d4c9cd781b10a08f44312828ceaa032070179d2ec93944eff16d9c5dd6db644584b06b19e9c2ed5c38b3e6f79ebc95f11b115c2ce6e2db575", "MS2": "14afce7121aba38e3689cc9f7b067320263c8ef34908f37812291dfd2a22e0ac", "MS1": "045655bb5592dd55681848163ab24fa253473a5d3b352105550f4e72fcb5153c", "CLIENT_SECRET": "0416c6ba2157d7ae8467186a08f0097eb0f7aeef03f7deebba5a6b02f56df7e421135216eee8217aceaf247ab583ed214b3f5be50a2e0b8d08e4d24cb245773e0a"}, {"SS1": "1e15b777f65cba6a5c421790ad5b8369f290c288c49b8ff6025af3193ebca9f203aca8648fb9420c91ee2e6f8cd3dfa5bdbf00d38f1e87ee57fdde235b83aed71dc0452e42d463dd64e74204d2a8ef4f61aa8574c3daafe3b4290fa3065b0a6b20baf5bff41f593f1d4ca524145d560c249f79be83a638136e4891c0c2157552", "SS2": "0aeef93c2d48e17551828e77dea6c41a190b4a00cb81c6b92820e5a1cb246b951c3891397b2f0669f3634c770cc5850210d9fae42d2b9c3c8e126df16e53917513474a8f69bcad1522fe5aa92cd70e1f57b7c0daa58cf53e48190d04951ed7bd1af8a39e09d812fbb2f151e8b2d7935c2e368716639e987e5a5baf04603042cd", "DATE": 16574, "PIN2": 132, "PIN1": 133, "SERVER_SECRET": "0f25f65fc4b18d4401e6fb146e42d7a12fca22143a6617e51acb7d344d602da70e045f5d6757ed15de2a045a5c4bfd965123c00c2f83b02763ea78eac0ea852c1262310ebfe2036a5950b4070b48a9b90195ec28e1543680745a3131cbf2871909b9ea09bec298e8dce17771e400e508d793ff495c372fb026138eac16f1d1e6", "SEC": "040b70ea15a7b9cefd121dd7d3008bbde887b907d41844514905db2b0775b1e8542056343e2b5d63b2a7e6c759ce662828d71fb5d3e93f81fce60168bfae20e6a4", "TP2": "041aba8f6b910187dcc46ba589603db092758d754f7108c31a250e628444fc1dd809b0d263cfa273e1febf3b92bb9145808f285661ffdef0d6ee760c9025bf934f", "TP1": "0401a82cf2ec906952e4c0c7fd74b897dd5ccb01ab499fa35be53ec2fe602687fd0a48faa0b66e686aba5b6abbab6354abdfcd838b88d9f9eb9416dda006b7e175", "CS1": "0403fc1fa9183db21ea2cabbd74845cc0907514f94b892c6f4cc0182582d710a6e23103ae089de4d40a30d1c6dc3264e3e6853a7965c1c629dca8319c6231c87bb", "CS2": "041c83a6feed9623867aeca3dd13ba4b8b64d3b8b7ad5836581a4a34781bc24f4d2135c2cf2fb8cde2b8fe65c859331e6da254b8f03e512e7dd9f345a41fe78b82", "HASH_MPIN_ID_HEX": "bc5a98d8acd349674db40e84470577b77c87daacbd34c890c68a1de4003bffc5", "TIME_PERMIT": "041862d7c5b907c22d9a4b0519612c53e4721939c00be48f6f56ba80e427691c0512346a2edd18587d67b61246ca1cb7e9205c0e6945833ae84b5dd1532fc24434", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35305a222c2022757365724944223a20223562326463666637366265383932623961663030643864343035616365623836406365727469766f782e636f6d222c202273616c74223a202233336163366430633732623037656134227d", "TOKEN": "04234e6f46cbb68da59c878ab68e5a5758b0111c1239625ad25b51cafd8aca6e250d3cf747a91df67e2389daee5c0c8c9fe816c25b26fba1d3b589cfb906982e9e", "U": "041c9fa59635322cd011299a7204c7357607bba6962bb9ab0c7cba571de183140502f58eafc15d5116aa4c2dbc9fe565ab361307151a50d114fae3e40ff9c213a8", "SERVER_OUTPUT": -19, "V": "0407e099a81d4f3b53f16697d9d0930e7751774b9834113d0cd9a136578d44307510f46e46ad9cf84e035a0596224ff18200bf7ce82dd5473e56600b0c003e8fd7", "Y": "1ef85ecf58fc1472686cebae6bbcb7d5990c8b53dc2108804c4873b528915507", "X": "21eb5c8e3a41d4cf0360998b8bcc713e169cc64b1ac04c0e299a65be9db2c5d7", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:50Z\", \"userID\": \"5b2dcff76be892b9af00d8d405aceb86@certivox.com\", \"salt\": \"33ac6d0c72b07ea4\"}", "test_no": 182, "UT": "040e20b49a3a93bc6e1c958d9f5cdc2d5d80899df5004a5163defdeba8794e58c10387773cc0618e202f4bd287138f748e10fe73e77b6a2d3da91dfa983f31640e", "MS2": "0a534d2ed3db5f8a0b5e620a7f9c0a8e3ea080e9071edd599f1b2d3b46655d8b", "MS1": "0e9635c319c5c8f14e999ed12674bdc0f70e4541895a2b07b1231edfd43277bc", "CLIENT_SECRET": "04234bcdb1c96d3ebb24b2aa00875c32b9ab84a29141e3920f2df8c8e7621b3cc714195aaa5685d8e70058d99a9ffe6b3e2235b0c6340aaf32dacc23949c0ab722"}, {"SS1": "175fe43313c8c1c23dfbf0d686a9dd2adeb41c3c509109ebec3269856f4e7e112091b18fd628d2a06ac8ec7ca9eeb44760c8808c4ab042cbffe3c068d436c5311d8b87ae6d7661400d42bf6158ea123691c4529d4c7903b3793e4eb405a7afa412b1f3cf12ee97e931bd4b02d34cb491307b282336567b89366c216e04ddcb9b", "SS2": "0381d447842043acd15403f1a19c39a97c576b9f671927739a9533c4b39da51a0854ce3405619b1c93deccc2188bd51ea0eb36f73493330d8b0b743073ba2c9f18466b22fdf25cb6a098d1121ba513de06b45571c73d8a4418e869a5578f27e91c5b3aaa3c82b035490e58962e33fa85945aed619dc7aa0b8160e905f9f8f4c1", "DATE": 16574, "PIN2": 7275, "PIN1": 7276, "SERVER_SECRET": "1a6ac4b2afec9b918d5c7955b2c9e51460ec66a94587e917275416e62474ed4d18de7d723d3c3c02f4ddf4863f0a78973825000ee5a232b5ab3bb11270d1dcd32345f7f8ae1abc18226b149462d84f0591560348615908ce2ec603251c5aa591153d085b942a2e3b331306f833015c467e4d4ae3950947cabdba763c163f34fe", "SEC": "040e3f8519a24b029dc21d12f35fec9231261e01de4221b01db371bdf9d60b155c0021d57bab41c48cb696a9afded16019f0848a96c3f899f5ad9cf0f51ea053f8", "TP2": "04010b0622a7986d2388ce1f7fdc323c5b250c3e3a5b9e5b24d66c051499a1befd0c860a8efee40abee1c86bca50217386a81ad7571884842d9b3717871dfc2ea3", "TP1": "0408156bdd552c6d25ef7ef911f8d5dcf0fa2cacab8ebd716ca6157dd19fa211691a15225f54e605898c5f1e2c7bdecaac11c8a87d48725ddcc91623f9d75783f9", "CS1": "0414f9e4adfcf36678bab18de48ca85bd552ff7bb6df93a3ea6714e1eefb94ca3f22d286a19a09c20ced43100666a9897120691f9dd91dae94d83632d2bcb9c2c7", "CS2": "04113b7f002e1cd8b061eb43b17982a47576b2178a1434ae59e7c30c21847d0cb80edebde6a727d81fe31d6096815e9bab37e924505fee436ca2a119b5d8489459", "HASH_MPIN_ID_HEX": "dcb8713ff3d0dcf15e7ba4382832ba2aa8df54997948214088c0e473adfbdc27", "TIME_PERMIT": "0418a070a0f58d5d7471ad837c433823c218cb8cdcf66b93b02f5a00d43cdd37ae14f9e7e811d53b72870cd63451393ffbaf14200ea5edb2369b82b8ff47cd05e6", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35305a222c2022757365724944223a20226236613331353063663334313263356666633139666434636231373361626266406365727469766f782e636f6d222c202273616c74223a202233353934623535303438363561663136227d", "TOKEN": "04068f23ad282e6362708c1ed49f4311e8efe9772b3712f655cdfee42c348de6040fcae80743939c65cbd6a86a48e773038dbfce6d48f07da543f88ed313614840", "U": "040408acfeac17af2049444ce2be7ba9f0e9c586c6009ca889bea6a2e87d16986f17bdd3c38d74e5ebd136e313d7dbd7e3cffb412861b6086a876e884e275a3c3c", "SERVER_OUTPUT": -19, "V": "0411abb8221954839f9d8e6c895f4e3df81289af00b89d1f072fca3d3c28fcc97510a8fc968ee4e0552a6559afaa2e87f53a3a8268729351203b7ca8d25b89fc47", "Y": "0bcbef64a7fcc80f9e3869328525c67dfa2cfbfbee2ae8db40d881001001795f", "X": "21e408a05c6ebdff6722605b971611a12d995f14f94bde01c265c35eed792ded", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:50Z\", \"userID\": \"b6a3150cf3412c5ffc19fd4cb173abbf@certivox.com\", \"salt\": \"3594b5504865af16\"}", "test_no": 183, "UT": "041273fb0b378cd20aea45646317d412441ab8325c769a9e964e4afcf280204cff08687a5d004fd0a3f2fea291df87dc63e656220f0a6313daa282bc6ab6ea48f5", "MS2": "13ceb375f1a5c796d519a95755fc1d4fbb75158c2a75dbeea09aea8f4f498d79", "MS1": "01bd4dc8519db84fc068da48532e8972572bd5e3432fdedc74900d82ea02337a", "CLIENT_SECRET": "0422c2743ead3cf37cd95ba163705109c900c677cf516c26fbdf30d793e3f3f9f41a1793617d82ed93c98edaaf67999a0e84d8c871ad37e05816804dd8d064659b"}, {"SS1": "1bbe31dce412ba22411cbb1de224c2c6ea17070e0aaa10d1d6075a83170a8d161a3b93e11b98c58615f756bb2de076871c79b71bf4ba041724bc6f102e129a84019d494603b569e4d7270249a82cd09b4957847b33768b892f21094b0854d8f71401e896ae5a45c4fa0f73050fb060f7a1f3b417b48619f7c8e956cfe310533c", "SS2": "225fc2958f90e21bef01b46c2eea6ca5873b5318fbd552aa8173ee783e71a8dc0f3980c83046b9168b1f4dd94a61958f9fc5feb1819747e93da90529608a8e371e4d513a904ec018501c41a00fd1b84ef3dcd48b220efbe825ee2c1da38a12a00b0a0358d54872f218fa3ab09401e64f5c5b49dce0c7a8a7e7b94e894fb2144f", "DATE": 16574, "PIN2": 9491, "PIN1": 9492, "SERVER_SECRET": "1bb27d079ae63da23ac52d82f6544f01b3807430596cc1b90b73691b4ed68a0b067c85f35b12f077d851ae1106d9becc817794994c6ca6e0f795367c029dd5ba1740018503e926e9b3ebed54292a3bb9980da4d25767ef7465e6a4a1b83dd0e01fdd4af3ddd04d4e85691119002b31107045aa06269ead94a28c4f359055d719", "SEC": "041ee99d91053a433179976eaa0587b4fa2ec5501627153bf965eafed374cf6bbb1e55e8e3400645154eeb2d13e2cd122c3171675e46a8ab78b3a9d15dbfc3dbfc", "TP2": "0404a63102183c358c044810a0cd0fa443fb237e543fa6816aa0eb0a25ab3e50341ca6030faf6ae903711cf0c7bcdd8197893cc8891624170571ffa9a1a5df8ecf", "TP1": "0410e5d536bdb830859f0b2e4e463cf6b3f8ac6a77b5ce288108ac1253bb1cb1741b6a02e30bb8e958e340f001e8a9d1fe1fe043e96cc73b9b91f234b04299d459", "CS1": "041f3e2df7e4e27d1fb0717fd6192795fc6cc304599571bbb9a1a96098e54c387d1264d71d27e8bc4443695ecbe3fc72c7e5b40f27f120b50499599c3dbaeb60f4", "CS2": "041931ea67e53abba7714a198dc946e8d3c1f564109e8df0192fb02a73edb77f6d12bb207fe3bf7b7630d9771149799f2e30a6219d29231337b8feb9a03e2851b9", "HASH_MPIN_ID_HEX": "e453bee0e99d88ccae881a2591c3c2c8f39f16168af720acf2524eda34fa4543", "TIME_PERMIT": "0417f118e01e74dff1e7798609d5119e9bd141b9247fea57cb91a776c4e132dda70db66b1c6e24e2c746f11364d2124d30894a053f62cd54f16c3cfa7efe80ddb2", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35305a222c2022757365724944223a20226432336633636162626433646562393362356333373336313064383331303931406365727469766f782e636f6d222c202273616c74223a202236313735363161326263373738653361227d", "TOKEN": "0414761dbc9c658ac52a6664ea16e81e33371acf37e2552220a072c1728745c0a90d30bd1a722a961d8f35baca7795b91621944e5cd548243b88bea04f4ef9f576", "U": "041a7133662a0ba59eacdd3f9d4c76aa757f9159dc0663bf306fbdcd5540f4c1d30f77bb90b280e0e74e68f8870f800dd8939ab75ab10d5b42cd939a1d3caf6f29", "SERVER_OUTPUT": -19, "V": "040dd5716d09deea8dd30c66dad1ce93920e2432aa93c8399a1c96990d9bb6d1f61925ee34c9417114a47051c07988371be29c8e7bbd6fe97bb6e399f47f611a4f", "Y": "0d6914cae42c4593e6108cb917d901ab977a1bc466e85a54a1ff1dd4e032fae3", "X": "1784fa8c1d7caf3cfe3f2124012cd90d5bbc4c03683504988d147c5cf7d70c11", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:50Z\", \"userID\": \"d23f3cabbd3deb93b5c373610d831091@certivox.com\", \"salt\": \"617561a2bc778e3a\"}", "test_no": 184, "UT": "04159cfde3de1467f4b1e9a23bacd1f86d562815782130cd193cc77fbbf32ade2c13987ce195d7bc1090a11194244c00e3527f421d6c53be5655ecec8199030e6c", "MS2": "0d2947f57143efbd40a2c9486d7f27582310e7f33c6d7afaf7ac27ca7d80ae92", "MS1": "1994ac257afd958e66baf927bf80276d70bfd316de2280e011cbe5d1823e699c", "CLIENT_SECRET": "04024887744f01531cc4bc691f0d5675b72a8d49ca11de94f1a51d7a47be452c341f1398b090df7fe2897eabb7e64c218fa63d0184f06aec859021cf58fcec6169"}, {"SS1": "161f688d45c3b7426a3a14d3917d3c0039c7d85e4a56b41ca9ec33c35dc0af3b08da149bb043f85dc4cccf85e80469b12e6ac22a3397a3f77625ccaf7635fd6205338a36825cc67429591d49e70c9a665f6f75bf32faff39b61157dc63f23bb60b9ca6761e9a2d7987db425dc22c6c45191916b0a55a65edfc656e2f8a8004d9", "SS2": "0dc0fe8d0587dd1b81176e897ee25f8d8bfb5e844e92071c9f15a851fda9a41b00c22fd32268928d87e6c3dd5e79b3f6e69dfb69859c53b61cbe27254ff556630f9bd9f40cddf536674e362b8191497dd2b23877924ce7d8483a4e308c98bb75126d2c7f4cc1a9d5c43ca04905332fcf1042362d001a6a76378f28b2a9fbb90f", "DATE": 16574, "PIN2": 5351, "PIN1": 5352, "SERVER_SECRET": "01c8f0df3d61852fd834cecdc0d6a48872ca30784a5ccd1249bc3da85385ed1c0fb5f6a07476dccdd0de6030d98937ebf284b01f073ea74c99298ab6889043ad050ddafb02ae6e171b849d06e6c497f7cbaa872e501b200c2348a24c369069f623d1cef844b473a11e3683a93a6642567f8d38017db20575126c1627a7347826", "SEC": "040cdce8f295a4998e4287d07710c2ca8c6d86395ef2da1ea97b53f864ef43861f140264cb1b6cd9615472a6b81d931b3498d3713afb66ff0ff8ce0568e31b44fd", "TP2": "041af9c8168534f91971e5c98ea20706fb54a427729a3ce4bde22f2222a8fa3b68025a6fef4e72e3f58aa45703b94a4384e944c1781c198f3641804639d9db7c48", "TP1": "0423286618cacd1c910a1566bae284748f6052148846ed3e8b588f0930d38f1dc40141d595db4c592b436ee752fa3be9ccf6f1966add8b84767c4093b70eaf01da", "CS1": "040c37c86edb407bf624e40d56049bbb328d9c71f36a26a582f69206632b4dde370fb9ec5fd6005b888e4a9f495a765b7f8b01aaa3dd6c96377f4c258df5f3700e", "CS2": "0403400bf60e94332300bd0e2243e198aa5c9e339d2682a6fe099a868ad1618fdd0493deb0b99200fc0b51d7963235b3e38c9a2170881a72ced2b0229fd714c6c0", "HASH_MPIN_ID_HEX": "a889d2c36f3ba8dd4d5f8cb07a413521fa5f1ae323ea3e68d5388b7bd1f69bfd", "TIME_PERMIT": "040860f88bd97061de8ada760efcecee6b61541bde44f721345a54f71ee7b5bb10144f898745baaa84cc2eaeb61b80d85c68bf84e613e8bb458d488eec9310e821", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35305a222c2022757365724944223a20223531393634363766386533353763333637656236656565643631623839393935406365727469766f782e636f6d222c202273616c74223a202234643939643330363262643666333031227d", "TOKEN": "041405c1beb5a1b8488e20c25ef4667cdc1485771a678c63dcc79c33a18c9ad767041b56a205f876ecf4bfdb421536ded876a01ee45da765e59683f034efa0924f", "U": "040a6bae163d8d4283fe0f16fc9b911b7327861a589dfbc25e8001fe5f064718671b125537d0845c45c70265e424ceeefa38a5d0a3dde2c2a859863b3088298ed3", "SERVER_OUTPUT": -19, "V": "040653e7b45c2f03af884ec456bfdd48bee50cee72b5887738c227f7afcb15831a0110bead1e37a078001a0ef538444f75445c9cbdf500f8bee8b014a52c37bd7c", "Y": "0200d02cbea3ee53dc906fb436f2c53b49843aa965889e71b8552d3308eeb796", "X": "18cc26b106fdb2893869aaeb82aca0a81668c7c5a911a70d07f5c6bde9269d1e", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:50Z\", \"userID\": \"5196467f8e357c367eb6eeed61b89995@certivox.com\", \"salt\": \"4d99d3062bd6f301\"}", "test_no": 185, "UT": "04017942776de1bbecd1f09dadccc5336a63837117fc0fde9b75cdd8400817f1a51206b73479c47382997cd43f5e30480dcec38eec59468699249aa0f85c15b86a", "MS2": "0d47cf8da5c65cb0902b213a4700516832c094824453a05c0e5fdd4d5c7dab90", "MS1": "14c81f3f76bf36d5bc83d7b63cb7eed07b18fc7f62ed9a8ed8fb5dcf39a3508d", "CLIENT_SECRET": "041de3d781ae88886e54872a3da6d938a9c97ade3d02dde84eba9f1264876a2135226e44c2fa22443a188cf0d382d33006e7f095bef47d88f6c23b2f5c807f8563"}, {"SS1": "091eed0a01dae0b4243ac32196905c357957923c875d5e72696f062db2d3a6f7098df006c27326b90d5f8b5265d6b9431c897c224bcb8f4b974a65ab4d9f21000eacdceed480ac67da9aa3c04b8a610595f5e8e542b9dd18aa629cd41ae0cc851fd5d95708933bc72bf80aadc15f88d8563c003cd44ec65f2d30a3afdef6cdde", "SS2": "01922f0a37dba0a3bc27b36704dd96134b2ba9dc561675f246e4b0b2a18b98e306934f211a7335af955b9223bccd357aed21b70b7f79e3000a88916a4bb391e00eb290d4d684eea33b5334b7196f8df4631e9c8e72c420edffb467aae8a856d1089f2c4e521a3d28266939147b54ce131f3b837763c01e6cc2568198b0a9716a", "DATE": 16574, "PIN2": 5492, "PIN1": 5493, "SERVER_SECRET": "0bf3a06f168c50b4269c836cc0feef52eeacf14f343ba959a9f248dce4b33b591f25ff96191611c378d6ca413eaabff8457f64f55766d8d1bd7588add6cdfcaf0105d9b3744bdeddebccf86525a4a8e16574c5c456f59404c397eedee4f348a70b0788574b7275a9fb542cca610ff70164368173d4fa0bbbe02698d147c3442d", "SEC": "0419464006a6ebf8e95634ef8270f7f755b7b02d85ec5ea7c358b24fc5f15fce1f102ee9aab72f43583126118af793085445b1e775de939b87006239781308bbb3", "TP2": "0402110b01336eaa9a9e97a5c7322dd7a525cb9a41ae6dce08acb90747935892bb201ba540fcbff8a37a6d795adcb67548d0dc572a5c870b79c1fbddb7de0166bf", "TP1": "0406b6a0da152f8dee3a33332399fd38b58da4238856400600f0a1e67847a346b605426fa6cb0c9dc4e44b76e23fc9e8bc403c99264c7235f5c094b0e01730b47a", "CS1": "04001c741abdb81cc9b0e602b2c3ffb6506449ad5356b78ffa9a81efc8c55010f723473667ce0290d4a0373cfaeff420b81e09dc9c1464d28e36d1f46614e02b9f", "CS2": "0419ca28e5459c84a7cacebf29e800824f9ad0aa194074221c0d624a0db2a4a5160438764822f5a7f0977af78473350e51b1ca28cc89cb641c6e3ffe6b14b8baf8", "HASH_MPIN_ID_HEX": "8b96c8d449ad13958f54440a6ba852f847d5fd281b3519f21b7bd40dc3cb8c6f", "TIME_PERMIT": "0423b6d24435f1e9f8c62ec3f8a24772c9c39725a1867144f63281e27bd873fb742008d44218d7e9fcdf0fe90cf10570e93c5533068efe91e5834ca656e9b01eff", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35305a222c2022757365724944223a20223063623235643565386262346334373262313466316130386233323337613761406365727469766f782e636f6d222c202273616c74223a202263646631343035366331303364353663227d", "TOKEN": "0409b1411de4dd284e5f3d01167379d7b7c2b72b9bff2a4a05d98a313fee19bd9c024d57d5f3f248cbc25309069d4f7b5a1953ab685040ba7a414a2d61ee020dd6", "U": "0402dfcb52f5113281837a88681951321254f09fd9ab54cd6ebb52c61da633ab16076571d5c9d852c33c1971065960adc42217f2c9a0c083963b9e3b8843254908", "SERVER_OUTPUT": -19, "V": "041a37d360d15d5789094c328857870cf947af25de831e2560b30bf5d49c164f1105a1126ad2ea19653b66de91494ce9d711aa758c5871887a47becf6026c2eb6c", "Y": "11f2cd06b59bd60d28991c64b06ab6241d1b20cdb00908965f669b4903cdd3c9", "X": "1e54de4ca4b32f3f219e8ec181984e3c912f1bbf79c9272ae24043f287b26380", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:50Z\", \"userID\": \"0cb25d5e8bb4c472b14f1a08b3237a7a@certivox.com\", \"salt\": \"cdf14056c103d56c\"}", "test_no": 186, "UT": "040f8cb44eade988b1e200e74b93ab3a3ecb40642376e49a7641d65879918e4c5e14ab1094e562e9f0b8b57bf2e02ef12bca063812c5fbec8cc980335511130a32", "MS2": "038f1d92607fc272e056bdc1915c8b3e8977e9aa24dbfbca954c91a3de6fdc09", "MS1": "182f1361f7c05a00f326b1a5a5fb3fb96a2796b1a27b30482f908c5c9f9d6c3c", "CLIENT_SECRET": "040d3967d317828fddbc3f235989d94b70072f9c57197b1cd32b188563bd9b9c41016cddf63ed83883e0f2799996229384ca4bd511e89af8c12464b7430af0184a"}, {"SS1": "0322691ea6324ea9c4d3184b5770ed1e25e51d6af21c1a4582b0cb18424ff09516c7d4ca66959a794a6c90593973ca50dc60fce431c04ee812cfe816c0576cbf165d174b05be8a6698830f979c105f3a89776c86fef11e6930ff803b9453e01520524a765f39e4d29a4e50f61338e6d642a283f0a84ef8e57b54720f01e1cfc3", "SS2": "0cf4741d11585ef366f25d1e6d344d4f36d8a937865bbb7f751b4c941545efde0d37ca543426332fd852ddc9fbe845f3479ca809d77a7381bcf7b6eda480ae8e1168f5069ce624ac0233c71b1cad8cc8e542cd54c39050b52cfd363b81261d281904d7cd82c54f598bd292b86235967bf39c5de6c8f1ad0f58903ea66c0ded8e", "DATE": 16574, "PIN2": 2392, "PIN1": 2393, "SERVER_SECRET": "22d90a907c10cedd49ba5c3207633e2f6d0afd6cb80b2594b623f124e716311a16c7af8157695d01aadd4f57d4abc0b923341c4704238afa9b937f9fd30f6f081feda633b5feeba7fb81bd3a9c02171aa245a9900b3680e54e0c0f6ef132563a103f5ebff7cc5aecee471bd04956cfc7ca471a0d5c271b34587286eac8a71766", "SEC": "040e3a3a26284fe5e37c62896c137cbc35687687999b084a7cfdf01b54a2463bc504a88fdd1549649d90c124c1f277a637268b8504d0eec69683399f14c3a1b93c", "TP2": "0408058488ac1a666b39f71ae697b00a2e9f891c23a36b88abac61e2667c92ffb401eb08664f09f458d0bc873efda15a826431ee839be4d4f084d7a12db9034929", "TP1": "0422cafe84b427700b644c9c329cc717082e14979bf6b81251b9f9af2adc86be9210ec3c22eeab14efee82f3c9cf72cc18cf37dd1e9621ba592b42e82676b52c5c", "CS1": "040c44ca05e2397f290070faf32cb89e6dce2d042d0e6e7b39b1042e0cc0cade4a0aa1fc31a9299d6674e8125595ec7be376ee3c0bac4d4929f8ce616cff3061bc", "CS2": "041fbb6437a9c7eb15903ffb5106820fd46a180043bc29b3bb08fff552d2110062042e3c92f183eeaf57b45a07d169b79c3a8a8a319892e83f07436491e6916fdf", "HASH_MPIN_ID_HEX": "28a859d159b6a869549e0bc5a2a584a94d44c0bf5a9132df9a3899408d84710e", "TIME_PERMIT": "040b1af0fe4e92347bbf53688960dccbbdaa2ec44aaeeeb1b55dcddc00686a003d18c3e65bb70e1f3d7d4fba3570a97e66186352a26a86cf2ce2aabef256420780", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35305a222c2022757365724944223a20223061623264366233393262613433393765626138663036346565353362343565406365727469766f782e636f6d222c202273616c74223a202235646162353230633936336536616433227d", "TOKEN": "0419ebda18bc4e5ebf529379ee9af677ca0cda6c97c47a5866164ce58506b9fd4507d000be5a7f8a35400a2549e822a8a00027c2633f6d4c74a8c394efa831b8df", "U": "041cbb005f34f82ad8b5de92c3d4605b9a51bccc9a9efc4f7446998fb9d2eb41350fc97e26d1da998fce7fd7345c7de77d20555c83cffa8cf9c1533cc3efd44997", "SERVER_OUTPUT": -19, "V": "04147c97cf891ebae5f5ff45e115b524b84f7e92c8229cb9edec5aa5f225f09a9703173be3820e3de97c0c51ffb13010447fbb62a60a05bdb1ad3fd3d2c5be3b4c", "Y": "1b65540ea9ae711ee48988b4653bb6284a8b9acb0c6453f80fb6f2e68d8e80d5", "X": "0d46d1c717e3184d4d8898a35f3f698e5034a71ef9aa003fdd6b60e07a5b36d7", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:50Z\", \"userID\": \"0ab2d6b392ba4397eba8f064ee53b45e@certivox.com\", \"salt\": \"5dab520c963e6ad3\"}", "test_no": 187, "UT": "040ec64fc679965d79e0ae2fd9966465d383d1132959bbc39d176a6ddd3f6540ae0cbd0f2915bc83b351935f547aefd939319a3298f5d84013f01db273742869be", "MS2": "23a2bc3f9cfbcd816270392c137a9fa75402888252b02923edf9441b80844e28", "MS1": "1120b0b0f030bc0a9128feeba6ec621ef0b76962c2e35aac7843e5e19cf46928", "CLIENT_SECRET": "0420c5bb1f01dfec1260c644922e1c5363a3c46d72a298722902ad409c6e50ca60024fdc468b3dacb83a569d2774100dc4fd14cd28e69842c306d9188f4bb53d58"}, {"SS1": "0d3ec1057f7be3259513505931dcfc90074bbc608a45df55b68c43eceb91427015cf69bd12a4afb24f57b894a274efe5d0e204cc2d87ef03259b606fb47fdbf823a2584e26b6973eb819d17c2262cadd09bf2d862c2b9d38dfccab839f2d12441784792e8dd97d792bd0f25784b8acded90ea42c71efd068eb4c14ed5e1a5ea0", "SS2": "047b16df7a4d8ea0594d4072de90bdbbafe8a1172c537178dc048929857a419007a66106f9f4d290439590edbe5d24bc5367dda7e047ea0a9c996aa5de5e6f820a1c8be6ef107943a64d4cac39f77fe17bd622dc390788f43b210b98ffa34af821d4a4a90b89c90ce3a077937afda174dc94fa2001ef2f9cf3ee80ba89b8f2c7", "DATE": 16574, "PIN2": 6324, "PIN1": 6325, "SERVER_SECRET": "10c19ddf215d6dabc64682af320f9f136aa81ee0b08e8e4d6ad78cd938ef1846010c9ee237792b3f96fd56a4e6826e05d85a5cbef471d2697f265641b08cd093073d22ae006bb30e7008118f3bc97a7a841959458c9bfb5dec9c2f1e401d186d193e60913d4e61d39589fb6b76b1635c1e6795ea642287897309e822d4bcadef", "SEC": "040b12780ef8cc4b3aa4876ac4e52299e38d3937b05bf505d66fad7b451f2cc2571c5e58fff52d3b88a472e03dea56ad4f8094666b90bfa62687770342751464e6", "TP2": "040354c8d49fbadd2df00fb1bb7a568674adf2256bf0eafbf1d17c34cefd9663b610c9ed157e31dacf49a004847ce7a4b9b93f72c8c3a3c2d0f998c28bf598c63e", "TP1": "0421fee75f89acb0467abc00f0e393b6cb5b84c369b11bd28809585f962a94184212329db3553fce892fb0d884344eeab90cd753eb8a160c9373ae4d13aa48a87a", "CS1": "0405f1419e4598619d6d1c5d6821761f8013243b90f8c9c17cc23099df170c4c0b08e826a426ba38f868996a1f4c09fd4ad971be80d26f5fd7980d0ad1cd9d67a1", "CS2": "0409305d2a295bfd512b8e201859528adcbcb0e574b6647777da249ea27b5b9e740a23f5b55365129ed23f8fd17c69d74238123ee8a194872636045acbb43104c8", "HASH_MPIN_ID_HEX": "cdc074dc4e7a9d55f5c83ee371985a6c35f86ec19e7c6ff19506b30d7e62b110", "TIME_PERMIT": "0401d79c116390ceb05c1fd790a750aaf60175e8ec8324a997224a2a853d79730d08dc3ad4baf04b87461d330c232216ec820d067dee1ba4aa0ec6f851140796c7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35305a222c2022757365724944223a20226532376339613131663965336337323236303664323933326565316466653061406365727469766f782e636f6d222c202273616c74223a202237663836323461616665343665363862227d", "TOKEN": "04019ffaea0628fb6f6418a284eafdc4027b8b97effdb8fdf5b6600190ef9481c00bc7e079cad1126eda7b1e6a93d768faff8794d19e1608ea987e9343375cc23c", "U": "04208fe74e15db6fb85674b87158abc2a93a8a93fb3f81b63f7ef47bd6a1baed1b0c5a43dd661931b915c777340fd7fdf52e0ebc526cfecf4da1baac7d2291a80e", "SERVER_OUTPUT": -19, "V": "0411c9148f90da0c1e87fff319ccd698caabf7dd1bebd05ab285623a98cf37c727185a3f13649671561440c7b15f16b9c6fe7b2fe395fe54af3af82973bb4d4f8f", "Y": "05cf25973dac92ec3301d223008e16cac0eb59977bd5f28c73d35ab8d54ff10f", "X": "0a480294ae9f5e1f0d03d33b4a6b080dce96c5179876f00da5c61b5649929415", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:50Z\", \"userID\": \"e27c9a11f9e3c722606d2932ee1dfe0a@certivox.com\", \"salt\": \"7f8624aafe46e68b\"}", "test_no": 188, "UT": "041f19add7150c2cbacac77273447781ec836ad0772f33a7ee22fc7c3d8e212f971df2400df90865ff300b7a24796778010abdfb71b59d270be65beef9d7d13751", "MS2": "1466c0f9eae762442872683bd83c99b96567ae799449a0702451205ba264f343", "MS1": "2027d23c6fe37d111537110e23ebeceed548cd67e3c2b638c50247c45dae860e", "CLIENT_SECRET": "04134964aa7cda9497f21ad1495cfbd58e59946834a2e9f21919c496d2ebde3c6223468624260c36075c176b29282dbf6f6b78a7661cada5c02d3313e29994a1a1"}, {"SS1": "1790a10a2592548f11ba4b2661453c2852de3c8b40a60ca1187124b8233cc0b5213a04de756afe1530fadde5d9ea50184bba3833c4bfd9f4b9a9165398b5eaa51e1023a82a162ee4727063a3cd4f3fed1f769efb7ff2d7192c2729730639399c1b06fb72702741cc1887936acb52c426effbddbe751836acb5f7670c22cfcc44", "SS2": "058878402df7e8a108eee462285da27738977c1fe4909d994b2ec963c7a3371c07cb2ca1719ef4898e675153c823cbf92124d16e8efc9c091e62b4f05b4f5c1d0efd579d282d2e188f8c892b0c6d30b6b1e2943d87b1b4f21be0be62e2bb051b1d5486414f374fa717a661ce5f3bc3b537efaa26ec073a92562f08fba0fb4ae3", "DATE": 16574, "PIN2": 8934, "PIN1": 8935, "SERVER_SECRET": "04e41f8fe562d449bd45caa6ff328c03cf4422f9cf122a7f6cc0a89b5122587102c575ad057971b11f68f7a5be0158f7cb405270ec424d8de5488a206b96e5761cfbc76772e58109e80e872d34699fde023a5f332b1715c32eeef29fee62b7e720fb3d2ac97f0f45802043fe7f7123c2dab98b2e81feaf10232f4df51aec0fcc", "SEC": "042114f5d39d274a3badbf7103f1d7b4f2ad3eacbef817ad77161fa14bfdfb44ea07375cc2148fa69e13c26ae2a2c75bddbf101e836fb9f9615a8d4d79ce314dee", "TP2": "040d115297fd143b70955307c64084213098a3eb16228cf730496157dd00eb6c500c35444a5a1435cf6fe88b1969606035aa2384a8352762be696192086e192dc0", "TP1": "0422c30fbfa18372cf86c2c9cf4fe35e2dc1be59956ceff0f6441b904e45924fa512a29231f6c51b11bb270dbfe7a022fad84f4d54f7a13d4b7c4773461a00c637", "CS1": "040ad2fa2e919d531739afeb90bf13ff0c3804cf9ba0f147389d499dccf93c0e92170cd2265ab6f911f9966402489b334cbd9403dfff5ae6f0ee7e91d5fefbbf1a", "CS2": "04158fe4f7fdf0e0abf5f207ed9d5513d6c893c225144603552cd666cebb0877300b2e3c8bb33a835c114480bd0d616fd627c5e3fd3101a1a19d44e448a3c76644", "HASH_MPIN_ID_HEX": "9f6d088f15e112e52c1d8b4ebebbd62b723ed307be0b807a3dfeca86afb309b5", "TIME_PERMIT": "0420d24107ed0e2a1133d394f34cf47f603185e7625caff6ee429d1ac384d4e48003101fce70ff468bb938e23e165335000c7b37eae98b02a26abb9b0d182784c5", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35305a222c2022757365724944223a20223732336537363163323763363032376366643236363134613933323361303665406365727469766f782e636f6d222c202273616c74223a202261313261323663313461623335313538227d", "TOKEN": "040eebfe651963ba02c127d5c200245cc3d7db3977804025bf713f89c150be54660b59f6dc5ec28fb3108e6ca17260a1f7b027bd1dfbd5b1567400b319d4318a2a", "U": "04145462bf5873f407b63e9e2c55d0d59ecfc7ef8b2f2c5b63a92cb7c4ba02e7e612cbd88c189d1a3f1a812a44a4707db2f32ff9f2e12155441b568fdc1bf2e563", "SERVER_OUTPUT": -19, "V": "040ed1749be2722957a5cc8af6826873def3df3d1f687ab56af3fccdbf2cc5a1470ee95d030e79bcd2e5f0cd67ccbce914190a27a11e01b1da65680dd4b4db332b", "Y": "1b86681926bc75f784fe1b54adfd5dd7f507d8676740c54781c45fa470e050d3", "X": "20c925fa695b477ffaebf50dfc12f462cffcb445b8f634f3f4cf7f840c47ef6b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:50Z\", \"userID\": \"723e761c27c6027cfd26614a9323a06e@certivox.com\", \"salt\": \"a12a26c14ab35158\"}", "test_no": 189, "UT": "0403121fd56ce3e89f8754cdd95abc4d37fc03f361db40f5f472ce12b15fadd88a13c982b98fd9e0821e3df4f4dda957d3dd550f24e9c66c8df357efd5f5e39748", "MS2": "00251a473595f4362b916514a2ea911570aaf179ed1c127d6a63ff87bb09597d", "MS1": "014cbf28023ec52e939cbb1db06b040948cf0e7edd93dba953a88491baa3f6e3", "CLIENT_SECRET": "04194386449efb9168ca1c66134b30031262ea7905a9e48e5d103bcd805a5c20ce130372b66c4428257f7314c4031a6bc8f7949370ce3ebcec10ccebe2d89fb9e3"}, {"SS1": "0f1fddeec4b6fff791f23fcc51b0a42ee28eb2625ca21867aa16a4a66ee1512616c1d3d252507701cc34f43d5b7742380c9384f30e88b29cebc5a12ebb62be2b0f7c59078cf60a530e7b0a0666ceafbb3a749637ae0c0869f5b55a6d0eaf53bd099d627ff80024df19631e342dcd12740ae0061df2241257379e91547c6930c4", "SS2": "102c8d13c5ee89117e4edad4ced829f07364e4e1646f3c88a8ca3d0c707027ec2129c52fd6c647ebb1ae1d0cfa33a8753daecebcc78381cd708e46c64b6b278f23b3a67e076693c9d7385c0e789660b8cffef4ab9edc5de9b8d5b86f862bb75f228c8b54d7a77e3ceb9b82f6fd56efddf66aba79734d94694acc4601c30e612f", "DATE": 16574, "PIN2": 7723, "PIN1": 7724, "SERVER_SECRET": "018add7da9c80d053189bc9e0afd5269eb156aa6650fc942d3ded8560c21728e0e9cef4d01199189c507a4366f93ebfb77e1297b901cebdb5cdff9a783f74510017c3600e1c90a189873b69c651524feda9bb90cb473fbb45674c544dc1800a1176cce5e8ac51778db72ffc67498358db645ec1f9a330701d17084fde33913ae", "SEC": "0409068bdc3ad2c55356e40f971ba2866b233a184982d6170215dfebc455153ce004ebfa04c2e341e1af01fcd5a1992988d8307faed56b4cadfaa4bff0bdcf92a5", "TP2": "0415fe72ec708df4a282053a781e16b0b1948ab6696e0bb0db90b3e53e55f3ba5519b7021039efde0dc6afd898cf20b09d3c8c5884ec7e3cc7733f93a5329358da", "TP1": "0417d8e5b0f023849dd97ed9fc3e0c7c25bc0df35436b78f907374315f532f383822e283a74c29ecacb611e33099f076a0cb6db6f6146229b37aa8f83fc6bc5299", "CS1": "0418e6457cbab4dae7b5e6027ff4ed6f565435c5cfa9c9562a467eb5d5e0e377e3097330ba4d8253f915ec893f7308475134c562402d8021d1c01af9f9783ce63c", "CS2": "04078768a8d5554e2b781a12bd4a8d4baa52de1b2420ec0399c137d44989d75366068a2d35583d2e4ee576e6996ce6bc1e42580ffd63f8b09727809884b4d87846", "HASH_MPIN_ID_HEX": "15d501be59160bf10305943e7dd67f2b9232b177a4a346a7583f9c943b8739c3", "TIME_PERMIT": "040eb88298005c26a90408a88eb3f32cf286130f2c32df1a59ad8ad2cbc866e3a90b3cc9292bf0db45532060206f435ca53a656d0476aa994c208d0e78f6de5944", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223533383537663463383561316537393234303664656263323161353336313665406365727469766f782e636f6d222c202273616c74223a202237336530323939353836336565393962227d", "TOKEN": "041369ddd973911db7db6e7dbe59e626f52fe6618613f3814cad45348c012c2e37154c84fa8ee0a37e452b4e900a6709556ecbeecef9f6306feb1fbf339a3ccaf7", "U": "0412fd8b16347e0941d190c1925b077aecea6983b4c6712dff54ea6c9dd81de3091cab171f44329740e65b5d1e866f6d0924051f654e7c8b2ff8cbdfd0e21960e3", "SERVER_OUTPUT": -19, "V": "0401fe242b4e3e05e66d16f5713a83ac98047e6a98127dcebf2d549e617d2ba36d1ac07ff0cb2971619c1bf25b1c917c414e62dbd5868c3f14052d39730abc0703", "Y": "1c0ecdc0ca6aab63597f619af890ee2f87d7091de34656e678235ff963b513b0", "X": "20dc5e440655c92d5aca417e3ece0eb8c03520284a5d20e6a5fada45777eafb5", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"53857f4c85a1e792406debc21a53616e@certivox.com\", \"salt\": \"73e02995863ee99b\"}", "test_no": 190, "UT": "040cc7807c1b7408fd39129aa1c6bdf2364faec522413469d77b1b6b8ce7451f3401ed5af4236b46946f47b4ac198ef0e3392e4debf7b2c51f5907fd3d5b3746e2", "MS2": "1024d2689c125f809a37469f5ed1ed27e6105059c5100fd2adfe452caa18db93", "MS1": "14c3a542bce45d9ed3b2cd3586fb6c4a5ce99bc91a1d891a6fc4f9799a7cb353", "CLIENT_SECRET": "04038b9d3f946fdaf255342412e2aaf37f8b43c49b7bc2d55da6297e1d2f53143700f57528ca96c25349d78560e5e1c6e018aac52b148e1d2333ad16ce26a3c6d0"}, {"SS1": "1fec9aa7134b0d29d629932e1e08f9405d1f5079a514d9a5a30cd3bd21f7f40e15bbf18cbf6c56deb7545ff1ea2fd3686637aa6fb3297ada388a7a3b973570c90ee7c0ee21f99d730c7ed7d2b2d1162b3c410b9a00e18b2e9af9246e6a6406b60ef6796630620fc73990698a0226442f1f27fc371a75e015aa0464db372fd254", "SS2": "16529c8f74a128d41d1d06e363f0938a6322bd1e349b3c270c141eeda7ffd10120cef6e98d6462b118bf49de437e129180743c9049bf355e762a1384d1edeabc001f7abd92f5189bec740b205f2f5076849c21ccb44dadd371f26bf8259ea89c01c479df1b20cc7921241f392013dcfe1a981e2c3181b17ffe3a13c46a57bed3", "DATE": 16574, "PIN2": 3938, "PIN1": 3939, "SERVER_SECRET": "03a0c3a65d6e99158677b53eba4487d5930ca5e27bceca0f90ef2f26744db97d0216dc51b0b9f6635b189c01e829c92c910fde94619c02dbad91ee9370d165022343e9641ba0bd72e0ff0efa6af48c914499f8da9ff412207b68248f48ed335a0c36e68f460a2a383b4feb374cf2db285866e054f99edccfe42e6dac9da50e3f", "SEC": "04214b4b039005c386feb095da04b6d92bad07f334508590104cd2ce25e9c751220bedb582934312d92d8b5a3a6d6ec019ec1d6ba63a89ec9196d6dd0388fa3a32", "TP2": "04196977fa79252afe9c783e8845b2b7a42bfedc882628c5072d2cac0ddb21624413f31259a752df5cc5158a44fbe5b0d6b6cfeaf54db1add88f4d13221706e3e2", "TP1": "04077b35a1dfffff8bf8b92189ae51d1d42ab9d168c688346c1d1ef063595b2fb81114e779c2461b52c2cca255d80497efc58038a6d6e3999bd9d7222eeb5bf87f", "CS1": "0419bfb048e1be411f32a2adc95e9b5c29c371277fd1ba3cf639d0472d2867cdb31f6e7dabe1278b7692f1c4b8886de3042cdd22ec7c554e57f87e31adf63d0767", "CS2": "04191e53ce5640b56ff91500b3a5746149e920b75622af2c6dabfa20ecb073a2871d4f942cbfee598898964631d8cafd820f6afe35932717387eed7874bf1ab520", "HASH_MPIN_ID_HEX": "9178bb2a6b2054a8ee3cb2f49244db4f5b858e4ed116358683350d6f0d82b100", "TIME_PERMIT": "041eff172c7b33272fdf59e3760c5840ed46700cda9b72d290b8715810c28554a6002a92185d47e3a7e7680bc5439fc61332a937f856ba9419d94cb53543bd292b", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223966643631303938373932333436373061316137616165663766336564323961406365727469766f782e636f6d222c202273616c74223a202231666132393964623363386537353335227d", "TOKEN": "041293e646545fc631c20f8e47a49732d9bf5fdad882a9b603b2d4934b2160a4e414fe97570e1590f3c18d2f7f903f8ca0a416aab919e9347efb178b232af5b268", "U": "040ae5c460f228a1b796eaca17b079e36b8d3f0bd79d6ec0b95d449ba3dc5f91be009e3eb24a49d77843c155ec1167bc8df681f8c48be2b2e2d77cb55b20a2e41c", "SERVER_OUTPUT": -19, "V": "041f0ed38019e985fb08341678bd58ca33848f3da13d691e46bcf8be6f019fbd5822903d75a21b3aa6b2e1e21822835eb68fd7ee4a518f9e5bf0cc8d1248378294", "Y": "174115f023863819c0f2dad1b820926c8c73f6daeaf71b912976c82e5e2fa078", "X": "12a01af944fb7610ce194ace3abec30c5a97a600edf2c8d194c45ef37fd66f9e", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"9fd6109879234670a1a7aaef7f3ed29a@certivox.com\", \"salt\": \"1fa299db3c8e7535\"}", "test_no": 191, "UT": "040e17e1f7b06cc5a9d1995c86f8b91bcf4746f92892f6386c1fe19a78dc3e7aa8172411d9fc513f82a2270847a0822850600b52cbf086b6e1c3bb9562e255b5d7", "MS2": "18fcb05a4c30defb7039e897ff20f549a7b3ac6e62a4462057bad50bf25621a6", "MS1": "0069f43f0326244a7a75f7a25dc5273734c848f16547d81c9ef87fe628a95d01", "CLIENT_SECRET": "0406d76ea7ad41da622ad97316f0202250a7cde97c0b727bc7ec8bf9a58f53395f0e4cb6996e12a3a35532135043b76de4bcb66287ac1337dec159d5aa93f047e3"}, {"SS1": "1472b88a37b1479a4d13bb305616e10f073450cf5c5a8b6b1dc7f7efc6ef0638049558bd5055fe9cef48d673ab29e3353c3f2c1346398bf010c82affd4d3125a090d4bfbb0f4f0b3cc5f958011d66e9683baa464a836136df9b94f78f4277b27013223a749d3b19eaeb285df1379925b8fda8d2d09fb2b1ebb1e0c84ab33650a", "SS2": "0e690f5afd8f29c3f7d44555ba5ec9811bc353b4c7ee2b70b5575c3535bed99c108061568a896d08bd8855dd8858a98676a20d080ecc999da054c122c11bd41310ef87739f5b8562e350aad472def518c91fe4f0564378996d4aeb5b5af2b0e706b95a5d81d24664de0c6d79830e01556d7517c3327ac9d5b27b74df4c2053db", "DATE": 16574, "PIN2": 7123, "PIN1": 7124, "SERVER_SECRET": "1435a97d9d5b57a11cd3e3af06d1c3d599b5c8ba0a13a5abf94ca55e14dce3bb0cac0c573d20bd251294a202b48605801ed18aa037ab3c32102149a4cc0404f90edf7cb49fcaffd5c53320c475696d67551f5d83cee9c574aecf9b3c6644a66c10028a57d0e31c5d7c121d20c1116eb78ecb3641c3ba5bd4fb2987a1174f6724", "SEC": "041801acb4b274b2bab3873f74dbbe0edb39be34a10f3565fabbe458c37b96935e16fe77e2fa022dc0a7771fce010a82fb5a2d769a76cc50cd5cad22d2cfea32b6", "TP2": "042325cb4e97c1f5e8c137c52ebc71b1a7c690eadf3bc6d6b2f6ab468a9d9dee462360802b15016d0dcd8e1042eaeb7acbfcbcff57179c46dd5f09bdc8a31e789a", "TP1": "040c17d5ee1e56d145253a3287c5dff4296f043e657360ac6414431ac735579a1c1aa765c1d5e3e567f048d6632495f894d3b132f213ab028f3fc52e46f3f5d3e8", "CS1": "0400a892eeb6878bd0c78b2b7a098119a452a9f6db4e37484cc0aeca77cc3ddd560695d8c299f854074d9d62beb483613e932da48b69d859b8010081549a0224eb", "CS2": "0416e28545a66071cba72eccaff161f8c0a9b2b385c8d48c155787f6d92408ce8219a993f39c198f0ed95dda258475bc87d94460fb6a0e4b159916f4107ae0931b", "HASH_MPIN_ID_HEX": "5c9b0c8bc8772fd166bc5b0e9979ba9c35c6176f949cce2a030543d599ecb5aa", "TIME_PERMIT": "040728f38b441313fad16a130849bb1bf18026e814c562b288ca2b842667914c4b07d38d62fa7bba88a250372a41b41ba0d45610744b796274e30f83bacc847a91", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223731643762306531383733626461333164643130653539396433303964613634406365727469766f782e636f6d222c202273616c74223a202265383030316633366137333331626335227d", "TOKEN": "04079c5b917db8023e367000772fad99c8f7f3ff35e7b133a4a59805ba3891a6bd00e4c1319aca1aabd55dbf365610f796a64d64d79227a57947578c8f0052ce38", "U": "04149d012a197d484b3da848f89b94dc1db3c0b0139d3df85c85e2a94064e884b204e654cca7a91827c91276c75905795ae88fd8deaab52712da2049ca230b2fb1", "SERVER_OUTPUT": -19, "V": "04232f459c123a6e592460ebb0ab66444cb58ab8526a4161e5b6590d162a1eb68604bed43991b78d200297218ad4799547ffbef7c0d75da3452b642e39d4386b7e", "Y": "0b4533d7ef0c5da6ac13c3e5664d279302c2b986cbcd255053fd0f81b67b701d", "X": "0085dabc9914c5b8c05b6629a91deccd2c7d6327f1c613a20ae0c4900e9af0f2", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"71d7b0e1873bda31dd10e599d309da64@certivox.com\", \"salt\": \"e8001f36a7331bc5\"}", "test_no": 192, "UT": "0415ffc411f4366549e764e720bb3d3a44160a600face5a57f6f78b1e1695f47c912f6203b4ad5c640895d807dc83db8c0f5f825879f0d472c75b8850c3886d4f0", "MS2": "008d74957097895817d01f433e88cc9359b1c0ba16a1bcbaabe80adb6e0f2a35", "MS1": "1a2a7f786e8a54f00c052610d7eceb25301a9e0c45888748ed9440c385998cd5", "CLIENT_SECRET": "040f87fdc8fb2c34c1a1713d031a6efa8232aff63b82a405d5d6a321ef10575467029fc0cee578648a1fd17dd47ca27ecfe534ccd430802f1d3bf66bdd74bd043c"}, {"SS1": "1235580430a9129a2e12e1caba62da873b956bf6037cbcae6f714324911fb97318312151d20e8d3f8a9c0d980b390fcb00202e35ccf8ea7b4f40adc5461224e103e0ecb457192f7955442e02b19702099b3e9a22ee6660ada44cffbda61d61f1233f290fe6ba0f2976ed266fed91203658cfaa0d32c3425df2260bd327052f47", "SS2": "010f6ac2b5d7596d26b948d9245fb0a59038a4eb34f34a4ea327039af6730254072825e2444ba3426aed5c318ae454c1de388ce9ccb8784dae31a3a4669566811412677537561e3dc019c17568df073cdc520e1b2966a2c890bd611bacd4c57f0a46d6918b7a5bbecc976d9ec12ca3046bef44c53cb05270a197ed8ee8f3359d", "DATE": 16574, "PIN2": 5737, "PIN1": 5738, "SERVER_SECRET": "192ee014cef7e35f806d0bae16391a40e3c95869319ad3649bb96fe9d3e4eb511ec6890b02cc50488d5dc381c2d2fb275d0883f8de706f37df59f59a9c79fad200485c12df91f4ccd21766cd1c08ea6a0fb5f5899ef556f8768b8ff89067db381316d615d7aad158a596552a2b304f6a087a801f79a4b094b855c584a1442357", "SEC": "04213b7ac2b515bf00c246d350638a5001c8baf724ff16396a35c2e3ef547d97931b5d13da9eb44f958f41889082082c8a021e2bf9c277151833388b80972a51ab", "TP2": "040b3dd92a46c74ac642ff37114e6c1ddb761f02e58ea4da887be474628ecf6b3d08d78a63c6ca996687ade9097ce78d90f50b2727c4fc70cfcf550a34516bfccc", "TP1": "0407815cef43bd53da698941d2ef4f4bcd3eae4750e827fdcf070ff893176fab3b1970844f144a825a76d7a3f6380f76c6fe1bcb6cd1d1b8dc47075b459bd3d718", "CS1": "040673618752cfed57508969114e5944d92a8f1b9ad2668195104fc3768cc280f91847822002a55e8fd6156843c8b5e472a391b4f208e87eb6414096eb619467e8", "CS2": "04071eb3f288557f42fc06a18875f38a778cbdabb130e2440c6560398dfc1f60281a2ed406e79611bd453721e908d0f4795f749f969e98685a480969138fc5f8ee", "HASH_MPIN_ID_HEX": "c2ab680deb13dc6952075ea477a6d823c9bb66750c833f3baea6c9fdb90a7cd3", "TIME_PERMIT": "041588a02c072b80bec0ce4f9bdad082f43a0328180de30cc88737052aa3e36f1d213de7db52366fc8561e48fd5ccbe5bc56d5eea8b961b2636834a74564b20c99", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223833313663306164613065343037613038396230396136643239303263386239406365727469766f782e636f6d222c202273616c74223a202265656164633633333933643564636361227d", "TOKEN": "0421bd07fea32aae95ed357bcbc5028fcf69cecdd851f7f76a6285fe1ff2c1e2e3189be19a22bc383095533d72c2cfcbb0a9b930eb60fb4befb62058eac2149aae", "U": "0400766065de991445a6c68dec2f6674d876d6dcdd595e1ffe2ae9ab3d12ab1b5316cca96e0ae1a42d4eae6dde1f0e90fbbe887d3caecbb2038e630f7985652103", "SERVER_OUTPUT": -19, "V": "040338728b40cab1ed0483fd747271b992e6c40914071026fc3ae6d3d694c4e8391005b4ca54f1986d20844d9db14e686dac090669ce98b7f19da48b5f401bfbc3", "Y": "1fd4f4e6a973127c3940285018203d109ce7495ae329860ac8918ac2982cbb09", "X": "1b4589eabaf6277b78eb6a4a9dd476c63b3ef36064b9e6d50ca6e140ff6efebd", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"8316c0ada0e407a089b09a6d2902c8b9@certivox.com\", \"salt\": \"eeadc63393d5dcca\"}", "test_no": 193, "UT": "042098c5107d03aa8903656143650efd65b6554a7f14293e1cf2bc61fe99f1b76709ee18dbc2a05344844b4bfe131686389d7430e1c83d31524c016281e9e426f1", "MS2": "1d6ec125f6a75cea7e2d33b2b59415d9ab4e0eb2c1331cc08e3b767bf4a6c4a0", "MS1": "23b6dde59c8487255c5ee3ca6f654d8a9c65f442264f56f54f54b43f3d63492a", "CLIENT_SECRET": "0401c7acdf09eafed8cc26b74f18ef97ee387406a04cdd69dc1c3ad366f7600d18176fc540477475ee7152e682180da5e4451d4786ddb3d56b7700cebd75a01200"}, {"SS1": "00834ff80c7299960983cb63fa08cc4559cfebb03a424ef1bc21e3d01a778acd1ed705900025cde61e9e9ffea8171380b4d3102fca90c66e2e5529b43edd8932213d6596cf5befad91e4e7e5a60fa253dc3675617a9dec69e4b9ccbb1ca796021c4048fcf6c1fe6769ead4dab62bf42f78acfa5d02b7a324995461c2be3f4254", "SS2": "23d77c8f634eafac80c9f78d345e6bd0056b3d2ea23a6f1f236fa121c5f97c521ec3d385b77fd72af86d6e49a90d0f285a5e830106739f3facf86eb79ab14ca310ce67d8893f6d95092145a3056354af1df411f09f8d37be77b867395e87976b1a858590a283ae4829b97e86624aeaf0d7b744b80fa38010b0b5b1bd3c02ec03", "DATE": 16574, "PIN2": 5057, "PIN1": 5058, "SERVER_SECRET": "0dc9af9aee0b576523aaa2d73271b33afcd7844573ca58ec0098bf264b71972316e856f138de3874d824cfacf726d929b79623d4ebd2e247319e5fa74e6527021e58baecac45d0edac71187cbdd1e3c96376100264045de6d69c5891dd088d40054ade55e096ec7c7aee16600842933d83ee1e4cb7ad1301ff0922cca410a7ab", "SEC": "042049a737c46b9c853b1cf5201aa22250de6e027550bd527eb2a7d510422352dc04b57a68a0c3a64ba9d6aaecc1988adf51cc3d7645dd486397be2f3c0c601f7d", "TP2": "0412c413ba05bbd33c527fdf6725f28be8b239a8eadcf0fc06608c74edca47785c1086fdd39b3013edec3fdaf4355dcf270fab40ef1610815dc4653b1563010cac", "TP1": "04008bfea9c37c45c37d657c3ea01707862fe6274c536ddad3d679ad4d2da432d713d83dd789be452ad67afb5831f4afb2bf3f3b75512816380d8dc2e64c8e1748", "CS1": "0417eb723d2d4bb34ad68308a75ca6c2240143553239791ba37e2a3c55437b4ffd208ee13c0596ce2fa88101f2b7b97b6d8b30e3910f1f6626dfd28d41532c1754", "CS2": "0402712d9ab265361febaa5bccffa04f5c12c7c310057e3edfc96ac57f65360b9722c05a1e792d0eb62a4f39542700ff3b8c3b55ee9e526b9c17d67e86b7963650", "HASH_MPIN_ID_HEX": "3188ae1720eab5e69c9925765ff0bc401077244e1d10472f016c67af16757f7b", "TIME_PERMIT": "04105042a1df9d5358a32792a730ef3d2454d917e8673231557ce817f836ce25260d6911bdc619e705c3decf0b40580bee1afc072d3f69b89903fe28448ef3a840", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223066323363646233663764653931396435633062653232346330353136346564406365727469766f782e636f6d222c202273616c74223a202230653230323231633837373331343466227d", "TOKEN": "04046b1d8ec5d39410de223b49a8c9f4c8ddce3e53d15781ab17c3215c645e63f60ab85b293f644760034ce06b6168d80e80f9ccd2e8165716ff7fe89af1c9ce2f", "U": "041a71e43fe3d2b3bbbd6f881d339096f436a84b0eea53535f2de12c972705c5f01475b324bb2c7cb12a843a737a5d357a2cd348ea9756ac5a627e99f7f43e0af5", "SERVER_OUTPUT": -19, "V": "0420de0d2e2bc885935f43f7087881bd1a50d1fcbf8401cdee34c6dccbdb3716c90bb7f1b3c254df685832f4df0dd07b71d304b3ce17c2b2417ba45ea4be16680d", "Y": "196e92828cb2426d54ad28e674d7ee1c1ad0206e57c350db99bb0973d5ea7097", "X": "04bc27fc26e8c24b909bc0ac03b4ece426e104a96f755bcac44243dbe9c43843", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"0f23cdb3f7de919d5c0be224c05164ed@certivox.com\", \"salt\": \"0e20221c8773144f\"}", "test_no": 194, "UT": "04162397278b4fa7bf6a390f210300c7f6c4d2183c2f462ab2cd64e53bd7a3cd97058eb59fd50644566a5abe189047b4bcce714d304d9295aecd708f81c0f0c492", "MS2": "13a5641f18b5eb121739282b760974392dbaff039f7e984a71e9e986de92db65", "MS1": "18d9e781a67819f133300ae631d7ccc2d161407d2f3917c5d30b794e298d69d9", "CLIENT_SECRET": "040fd6f07561687903d1936bf492051baa53741cb964a1f28d221bbdddc3477bb21202045e2246c3cc381ad94febd1c58eca3ebdb1dec30abc76a483a709c0392b"}, {"SS1": "0a8c1bfcdbd8075183539dd2a054b08670e4168fc74e488e49f0fad09577551220181064a5f8aacafc30915e9d5290fba7a00a199a9b78f519fe99c1b94ae3140db17251ffa51dbbce5a7b4aa2850d27a7501d6921f5916e2fa937bfa0c272060a5f9b38b3361eedfd154b82e56c78b1d07b528033b2eaa3fc5b9710129dc214", "SS2": "0ff0304383049c67a7df6c0b95e3753be21e13a0fa4175394dee35eec2ea03fa1ca390300a0650a8c3ff3ac9597d5ad92a746def754610eb891a4913a0cf65ef1315d5b9c2ec1319d012863ca25df4b94071524c1d624b8830e1c562f9c7521c0eecc864fdecff5d3c0dd5c77ea7df39b74cd15996240c2f82f675b687d08318", "DATE": 16574, "PIN2": 2473, "PIN1": 2474, "SERVER_SECRET": "23aab3a29ef399db0a25bf748abe7ab31e475a362288d66cbf994d3edd8b857918d0def067f16461f608f697ce43e8270c470cb8db278d0d3b072af15e7b62d71eb386277c6580de9060de23757dbc42d3273e14ddd00d195848216a0116cbc202720ab52d0e70d8ff608ef0fdd842ec3854b47c469582a1b887c38b80cb87c5", "SEC": "0418408417a9888d76a78172181e8d8be75c7e3b37ad59652df2756e2b40cdb29903877b0cfbac677c29a0b3307effb5f0dfd3bf07aea159813f4bd146339dd181", "TP2": "0410e68dba5e9535e7e8ae0ee0eff52171446ed1c4bc0c2d590ad3f9c3226aab011934f8cf1b2e5f36875d88efab2666e6ab329aca8dc9070fbdbc372c02d4d43a", "TP1": "0400f06ea7f02730fae16125afb994e06f7db3a18db684e3de9e495838d28f22fe03cf81a7f8f4a931f7affc524b180975de02479a2f87fa3d771276e88e40d5f9", "CS1": "040238aa7b0c60b3abe8108585ad6c70356923f6fe22578eabb389183a4a2eaf2005083201a899958705afde5ade78f8217b3f9042b4f867532112420b01f77dd1", "CS2": "040d3cebe297af99b286145dc42e47911867ac2a7b18990d28df2de0a7fd6754c10ad2a585123f35d086f87ee5f69e863579823721a6592c5995e5ea299dfd2c4f", "HASH_MPIN_ID_HEX": "a62a372cf0112ad76bcf10b1b56002d98d0a9c1b2a28cd22aa6e07252dcd6dd2", "TIME_PERMIT": "041cba6dbf18814cb239ba032abbfa43825fd3c935732a1b43479811e088d3ab930860e60fa54b0b4bf0c2e91c98634fbbc9be8c0a714e69e7a5398f18120f794c", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223331633163623835643666303531393334653237663664656431323861663738406365727469766f782e636f6d222c202273616c74223a202233353036653466303966663838383835227d", "TOKEN": "0403bcbdf8931fc12ba3ae906360f9c4250c8feda81b2b1d85cd56aaba6cefb3770dddbd9a65942773a2a8ab16c534ab9a83701e051892c8dc583993d866ba48aa", "U": "040c1b65517be6653c1143816f8f71849db474160af0d7cc2648b705386a5237b622b15730cf80a74323903dd66739c34f01598bba9aad17ea24c774f017b1e041", "SERVER_OUTPUT": -19, "V": "0406a267ff4c1f2efec008fe416d71457a60148cc35ffa7ca59fcc7c5ec909391d03f7b7d5c67d83dd853c019c5ff6229857bd1c2e0ff1b71a00f3dd03c1cceb30", "Y": "035bdf66080d8acb9b6944751e9d23e7996fe4b74020f64118ff501586e52b7f", "X": "0423bc32ac18376c8ef1ea984d07f3dd0000c08bee5329cf51f8efca73de2fdb", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"31c1cb85d6f051934e27f6ded128af78@certivox.com\", \"salt\": \"3506e4f09ff88885\"}", "test_no": 195, "UT": "040c5c0761d225b11f5f1512d679fb5be478a57b2033e149a43721f4a1a86a79c71cd4580746310e88a8e51ddb09f477b971690d9135c500949aa41f40e7f14a05", "MS2": "227f7a3e1466c47a2bf743a075730772889e7b6713e14ce8976782a6aea758c5", "MS1": "0bc6dc7b99cb1fff614907d4c44dbe8694dc8e4b53af5373adb4890fac5f8fe0", "CLIENT_SECRET": "04151d03557c3cd034429cdeb85812ba1cdc27bec183687890c9f615464d2b62ba027f58f3093fb9f190da3becd747b25dcfae19bcc567dd0f2b5752f20b89f2b7"}, {"SS1": "1fb9d0825dd83998b21406c1b8a6e80b4890fcadebdad733f818f7e8a77d519208a5c2a22ecd6fd5f6763402d21d973eefef6c96f283c232d2d473f4cee62302161e4dfe1d593b5af40dc926c75793787c398f4e6153f2da4cdbeead06748c2d05ea6b516abf15c9c0bd50e177e1e1772f7d621ab66acd5f15db1d9c477d141b", "SS2": "121356d3cb3ea3287dde349182db8455703ba09ec0d6e2927ef402f16c90de2b202ff3373ca1631eaf5b41ac3a73c599311fa1e176231aa490ae5414f023cd0002cf490a8d44ed47af9305c87e42f32aca6b03ba7555db066464b573dc47e0481a0df083ceb88b159219796e14264e6d04477e1f97e5d637a106587ac214ef0e", "DATE": 16574, "PIN2": 1297, "PIN1": 1298, "SERVER_SECRET": "1f43cec5f7f9cd6f86ef7942ccd87b015ddfbc56dfed2760225391ee2451d96502b0ae2ee8b0221b165a29e2a6dcfc875c45a491780503390fadb163d164640a12c58f6f1d39467bcecbd87ee63a2033e1a8ef02e82de2a6dfbd1f0249be7c881d63dea92b383f3ffd91ff10b82c4f3fe3259a3b6ea61f55b4b29360f22d20e2", "SEC": "04003596ee1402a77dc249b4f3c5e3ddc45bd522e082faa39d2e81b8346861161d1f52416e8307cfaeb1a65bb7e224c489491c2810037ffb036af143c22bfb94cb", "TP2": "04214327e1d6fa6b1016cc8d0f5d553326224ceb9b9b380ae33c183f344cd2c46f0f470f40d35f363d480aac53fb59b21927fc59b6feda1bdcd77168bc5faac46e", "TP1": "0422a0c75d0939f6ece90e1d3480118f590ae80189c4c6be6d83955353b7223d59012c54dfaa9555781dab6e2b492b27b7b61eff6f9f2c2075f3811bf879561dc3", "CS1": "040b44ddda3a3e7f19ff8ee326eb21788ea48722aced7b1ca8445e8c0ac15b639f14ecb605bfc19740f0e972fecb22583e3d6423c7b56cda482e4f84e0bcf2722a", "CS2": "041b78f10465b035a616258e037e268993083397e92301d36e9979731b422739fa1625ad31f576dce0bc7c1583e69f25fe6685d786536cb32258adbf0025645560", "HASH_MPIN_ID_HEX": "3e185260c7d0b945ef5caa9b842d1efc71605ced1803c57ec22f0c457c96a645", "TIME_PERMIT": "0404f59855003e6e0b5bf992c01ba008b484494c287cb5b27fb1c1edc3a1f2b9f21995dfbee4cb80d9f93b755638430e55ba6e885c4020b4bee063fb6f4394469d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20226661313261336164633736353436636463633631366530323262306431336435406365727469766f782e636f6d222c202273616c74223a202232363666333364366231353861326266227d", "TOKEN": "04041af1d46f6a06386ee6d0723996e9a4b95704c9da59e99d11d6a233fff51fc9105f3d486197375d44ea241767bd6557dc41f7748dca437f8ff154feef1c7f92", "U": "041a76f792c56e28b867bec9ede90c14c1b9979cb773c47ea74809fc9cbad418c7160991cd5616580042b286912312d5744a8b5c1b1bc6c17c7ef8ba85b4457352", "SERVER_OUTPUT": -19, "V": "040f749a8e51efbd19467d9103c5d444afcf20db21b1caebabc571185df83a155d17ca590036cd3446804cfd3915809165bd69a5ceeeb79616300c0a4f265a2a4e", "Y": "005e809950d18d6ebc27967189e82cdac38a4d6190eed5f15c2724730653231d", "X": "19e9ce910909788b0821b30b7aef24eca4773a349f5d767d8577f0d9c4868b0b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"fa12a3adc76546cdcc616e022b0d13d5@certivox.com\", \"salt\": \"266f33d6b158a2bf\"}", "test_no": 196, "UT": "041934e20f15b4fe05c816aaf0570d6f3f7d371ba5369b5e157247b1322a95d17408493ac05e1083d42d824409fbc81046e515a20ae83df698162cb3b64fd0b46a", "MS2": "0ad69f23f66599248b4257a680b4289c581aa582ec3be7224430deb81d7798ee", "MS1": "216f6d1020873c0bf2dff17fc37075794d38971d69953ba09d349070b3ecb2a3", "CLIENT_SECRET": "0420cb8006ea4632350826de8043f41c387ec0c0f1eba7111c606d4c40c52d50ff0a9de9d913099575269cb7087fca92c20d94ecbfdb56393e140f9db9acf35bd4"}, {"SS1": "01d68d18902536b71a4e2afa5d796acca2c1fdd8d7441c678ff54434e64d83c71f847c0f3262fa62af30d9c60d2221d4e54558c189df7de31b4d73d17b1f6d921b111b2a279c897d22da5d654df9800cebfc69388ed9022738306f0fac3aa3f419bb2d8f5f6512c048d2ac6e1b8a9756f005840cf42738d5a53ab7b8302a78a3", "SS2": "1d1c0ba3d7d94460d5b817fa983ea203a85a4b163e380eb0b572e2ba34c90c61211e6860669b620aaaae85d8887d0d6e148bc3b1f961bbf28961ccaac29ced1b0b926f1365f6d7f95a5b6dcfe23fc9a00cd10c337e97f535018cfdc7d779295b179746a675d6fd142b4ae0f17562edda3bb8760ae911e9df658c5903494902d8", "DATE": 16574, "PIN2": 5854, "PIN1": 5855, "SERVER_SECRET": "19d92c9e12f8f0a0d9be0da4cb7b4c3ea8083eaa0e4692c94650629bb11e89a116df0a154a0211396b371d1a3a41c6b786163187c24f6963a8ca7bf7a6e9384b167f4b800ae828da6305fea07775c982f2951e29540338418d2b1864c3775bfa194d41e3cd1b66b796621000d7121c9bc05d29a7b194512788a600c17adbabe3", "SEC": "04203dd13e05913db8776f6cb8d1f784cef94c1ba8f30b64da8b9d187594bbd4d71aff81f9b311fba47da14938dd85c408eb931546be5e8074691dcc63be6d2589", "TP2": "04188842c96509a318fc9d8122f121cb63d7542b49793cf2829c51e43824aac0d500db5cb9c1b1f5e24253cfe6e3d2427f2181dea7cb54f4e01106d1e76750f0e2", "TP1": "0403233237d4cf9dfd54071847f04336a39dc6f5a819ccb6c6be3c08a54826ff9506a66f6b6fd45765ff868019dd607ada25cce5cf5239d046f3e3db445f9b38c5", "CS1": "04141cfddea22db370fe19a847dd512180aebd7d738526aef7f0780a519874cb271ad854a28aa4da68322f55138d119436e11d3a59910fcd43425eb81f80486a23", "CS2": "041df3d33cfe0a63e101f8e3fd33b334d79694fabcaed3c0042bef6c38c3a86896191f5804cd285bf9a0592651360fc30316ab943ee75598c85acee8574c735c80", "HASH_MPIN_ID_HEX": "bebe805f54fe3d0063975681ecb339cdfcd1af7b32d6a1261a6b6d27b5e07eba", "TIME_PERMIT": "040bc63f44f3bb9079e60975bdb41826a12e78c395c167037b0de03b476cc31b91031f321ca2228385993682ca6f89b29c0948f6ff0dfb519ef330701c15916533", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223235306139346436646637396237313230336561633337323530623862396130406365727469766f782e636f6d222c202273616c74223a202233313332306232383834323033383664227d", "TOKEN": "0418bcbb1f0bf2911ba40ba5c6576a34b5293b282602a129934769fc0b53ca7c3a1b837a2a69ba18690761ade4675be721c4051b04a1cc629e3b623e9ec6d305ca", "U": "04132b34eac1ffb372ec4479eb96e13973e72d713d76a8a67aaf6a429fc72cefe8062531e8f74316634fcf8ba945c93d09c6263d6c7bae189b3107a0eed524e290", "SERVER_OUTPUT": -19, "V": "040461de05c60571e48a413e4b8921e1a110fa2aaddeaf999dd0719b71f7f65f721b51353f2877e550a17ca9627bdb1b60edcd4087a2a092064a950c80d2ca0507", "Y": "131032f7fc9aed5a307fc196c3751a78cede784babb7cd7e8f8e8e780e4e726f", "X": "0c0b60f53c5ffb0d6c4b0c1880284e67767e79517523a7e3de6703ce107c6180", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"250a94d6df79b71203eac37250b8b9a0@certivox.com\", \"salt\": \"31320b288420386d\"}", "test_no": 197, "UT": "0411c344def7eb610284db341ab3e3a6ed773b8d70ce498f91283ed687ceb276720508e0adbfa154cd6824cccf3ebec6ae1794634e01af42f0baf1712f1b2f7d50", "MS2": "0233acd19f2e533c36c0be18e6b7c3f13ce865b6e60d3ec23fb18d52ffc7b72b", "MS1": "0a4185b2958277a911182ae7abdf4753f39db19a2f8b6640017f8f97c543de0b", "CLIENT_SECRET": "040cfc9bcdb7aa64f85c0e273500e6d6025f873710014e2684df68eb005b2a33eb03b7253ab48e0d43e66efe7d74ce498dd67ff4c49091e62875f4a0ed7979f743"}, {"SS1": "219d5cc0918cfe9847c3d032f0dda5a8ae9efd42cde082af24241b4313d4cea11d06b218a7e5ca0acf296a496ca9c3dfa17d8f9aff9a22ae7a8da206ffae9ec0123b8486ea40e4d955f07d9e317e0cd29dbd1e5dfdf8c4245aaaf13f63d74c55173d9000290becbfb108a33396a4638261a27e1790f0ed991b144be6c052b8f2", "SS2": "1df4545b87c96120c4d09b7d6303cf726bd047067d629a3db0a78a84fa99cdc114a767a9f6fe77b168d299d2cdbc68d4431219ec7ae359e7fe8d4de10bba9c931fc8e349d8a17c632caa91bedbd909ef17f3b8483ac20081604440935811c80819127f864fbba7881e4cf5b5c81150a87f6ac41a3c2ea916277fb5f0adba5280", "DATE": 16574, "PIN2": 140, "PIN1": 141, "SERVER_SECRET": "078855184bd9a66b1af9f12be0ead67b2866fdf8c6242ab0c36f61022eb9e08c2238f3598aa5c9d7529e37699a2c2e49e09d1aebfc4756ee6fc715b4e67f42831802d6e985a978819e19148ce2fac5112983a9636f899d63ff77b6c9764f49d01125266cca66242114d002fd3230030ff37a196860b794d95ea73a4865a94bbb", "SEC": "040627f922c2ae17131e1cce0bc3c7eff67b624cb54770c08125a0fb34b0e138a005393343a79a142bdaf2094c3538a5a6e127a2043666b84d80d2e764495a8dfb", "TP2": "04234609b0f84e7ce3f09f0d2f6e221466dd9619c52085107f0dd3464f2536f081053380a52f37c48a00292bb56b0fee8d95ca246f683b934a2d1375f53e5c03fd", "TP1": "0416c350776bc30b2aee7f51fbeb4a0bd4d4e45bdff925dad977f0535563228e0323b09a89e0c408c09548c41cf383ca25ca263b6f99de2daa593bae03240a37dc", "CS1": "041a838944e215b489062a13f7fef438edf0f8fd7d721129bcdab7fddb9f6e822d1f26408d492db5f45e03c337af774c13be4e61aa8d2fa0873282f74c8b171f3a", "CS2": "041b1b9d5753498c1b6fa673b7416447e81f68c3ca80b7f9413c3259d53ed7ee4017a4776345179691b8ea09c8b28467f9b9b6fb76754ef9547229657e7016efd0", "HASH_MPIN_ID_HEX": "30efad459e096f6472b8c2a28ee514d4654bd41798f439a7a4f576e89c4a8914", "TIME_PERMIT": "042272e772a8ccc0d9c2a9447bc75a85f16bc7ab5fb734c75e0cfedfa8eca6ee9f1bf45bd18347aff03cb4a57dc53ff0a9d5b62f2499560e2a10024eb494713528", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20226137646261366534316435343034313732376630666235613131306533613238406365727469766f782e636f6d222c202273616c74223a202234636234306166393763613735396361227d", "TOKEN": "041730054ba035f80df1648df1d791ff9e13bd09108f1267e222939fc4afc72edf1d28c55fac3f4b34f48765a881157f2e2c3906ec172f3ea5478315c7b9231287", "U": "041cd0a19fab397ca59d1262d3e5aca3f65587da08e85552d903f12dad4b26ac8c0d06b2d9e9b742958ea944ff175618da3c5b1742e8fb63f332bf22f6c23dde5c", "SERVER_OUTPUT": -19, "V": "040f7e239f6cac0584c8d8465a1d38d3d7e96f492719c94c7eccd4c6409baffa401a7c1770fdef0a93b25fe99ebf9e784cf83e911147e3b09046a79508381bcaa6", "Y": "2348514a2e0849de7f0cae94fa5cf74f639f6347b36d1fbfe1056a27c2bb6f7b", "X": "1762d533ef1a9a98ff31d3113e0d9882d2979e152d2ca6d3e3818d24a751bff5", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"a7dba6e41d54041727f0fb5a110e3a28@certivox.com\", \"salt\": \"4cb40af97ca759ca\"}", "test_no": 198, "UT": "040291f50ec613454f6e0e28b55e01c1380ff5de8cd189eab765f4d9bf937af1a0172af0b2734932d75379a274560df22dcdee20b11e3e3237487ef905792b5fd6", "MS2": "1185ace1f418553f1b876b4cc445597b0cecad0012049ea646c674c86a701c9f", "MS1": "208d1291443f0891efa640311758871b4aadb4ebabab0aec6d90f322b623a350", "CLIENT_SECRET": "040606133f002da89f57d0af999492660cb1ae6ff3d5950f580e11e65f3c2d7b0b0c55a0771c9e013af1dc1a74f6eabb291ed0cd0c0117b7f2f55dd39cd243e9e6"}, {"SS1": "10e4bf08f82385bda7f192d23af7f3b4a7b1042dc571ec874192b7f5cd29b0651a57ed84d44f23b64ae8fb88dc00c653d1fa2b9e0ff4563b3ed33740544c67b81ed88ef501e90c428a722fca3908ab7d05111a719455fb75b2414a9b2e50749c17a450d9fde16fa7b1edd6ca2c2012042bf9de6e89d3fd819e92c636d4b64926", "SS2": "073301c8672bdb786ce199703d6c4333250119e957e42c1f998763dece75764a08f2d0f2b11c016b7125971e5b9e5d35094258e90b0f90206ff2db066c5a9dd51d2ef5e4b9f196385ee3f732b6d3c262694dd71891b37e9a68b78e7779e9e7a0033e2bad10a774f5fab610170e4a59cd857a118408c8180693eadb4960384c78", "DATE": 16574, "PIN2": 4780, "PIN1": 4781, "SERVER_SECRET": "1f5d7bdd9e043c2a32466e66f311ff15dbbc5539dbd0c9c9909f25d98db8493c17484a69a937d3cc826d5a16dc063f848c55dbf6f3edd56d8f6bb4ae4b2f3dee2073766a0b8f4b6ad430c80d3c4e9053e506046f1808da035620516d9540e29015ec9ba385754f18c51398121505181004ddd3695118f012291c1629cc35bae7", "SEC": "042126f5f9c938b1eca59a6214406855dddb11898e42a6b1d220718412e483faf321af8de3245188048a3988fdadcb92a324a3aaad89695505f4a2526102408641", "TP2": "041137570c19f7f6e3a12e0fe569dee8f3fd90c74881b83ae15e4eebadeb0b06f6055d88040aca6c8eacb40a2952058da603c9b02dfccc70a74646048200bbe227", "TP1": "040292d3a4b288f947f4a779696c70235f389c1ea8ac45b9b9f5593eeaa0c5c40515c400f30368f918ce4171ed5a9da6ebb1047a5f7e69dab3a4566edeca9fc6d3", "CS1": "041816052a24104d29292ace5839fafc17d46140b41b5e2f89800ca5d13b307b2208964f36d00f5ed3f24bd73ac2434d805a199786f5564eac1f63c0bf9e86badf", "CS2": "0421879203aa7e64d5dd572f482319f4a843cacb000ccb8b1bd11b6ab985c7e3fc1194938b46eb482b992552fd95a9dc22e760cbfa475cc8846d4b20f6c0c09edc", "HASH_MPIN_ID_HEX": "55bf3bc47bf9e8ba162e46813b882c82fdd673be502911dc5598846ce32bb9cc", "TIME_PERMIT": "041a53f83cceb63476b2b6cc5286854a06c397b4ed262f069dc131d6e5537cea6e10264e170dc1f388a665ec55d789e18e1f4e703be99015127358ebc6020dd791", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20226239613336633263343037313334663161313430616534376365353531396666406365727469766f782e636f6d222c202273616c74223a202235306364656661343632323038643832227d", "TOKEN": "04161b9a1382fc7ccb004def91c5bf5105bb99510ce358f8e580a0c45b33694de216e091b13ed126b14f06c5070e1eac79b72b8078d1efc12b63c6ee263e2de888", "U": "04132c140a6ef81c2766523c7af2d9806cc83aa7976f57b027ea32517edfab0d2f0c550c4973692ffb62cae0f75249d5fac0ba201c1ee741b4d657f3353796c546", "SERVER_OUTPUT": -19, "V": "040e91031024f84796935877595f8d70a35cc7854275528f51c4ee06e1444217b21c161b5638d3be43cfd8c38bc8b2362ceb66dc018d2956f13876cb1e9bbf6fae", "Y": "097a08e146c7b1113f94429f41887b12f9b34485733a095f9b32b521b0b1149d", "X": "0c0a502e784bb6cb0992651e8138cfc8cae5434b55a65b2fedfff253d25fcc16", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"b9a36c2c407134f1a140ae47ce5519ff@certivox.com\", \"salt\": \"50cdefa462208d82\"}", "test_no": 199, "UT": "0422de13a846221a093b6fabdb77432f9a0c18688b94ec654f0e73e24aa5570710076987cacfdb600899f1f61c2b4622f0e8507725fdcdbc95dc5ceefc3f4524a1", "MS2": "1eedb4167ed170b2517b1777fd56b1763a802cb4e33d4fe0bae4b66caa13e55d", "MS1": "0dadaa713f962813933da3ab3ce3c931a4e4938a8dd50598d73735f5d52369d6", "CLIENT_SECRET": "042057f2bbd154cc843d653bd8d3269d726408d1780f37cb11f014454749d7572d1b32150ab7aca9773f1f9b6e164c55f7c8c1e9c29e4887b8ec1d796dcd757a67"}, {"SS1": "0d3bc7bc15fa085aa736ac443d783ab1c13fa4088c3eaa4082abd336cdaad43b14d575eabd16755314fe3381a0011f3e8bb3203363689347bdb54e44c38e9a3423e0f556c9ed21cc59021057aa965ca90d542b1ab6d6536e10f6a156aa830da3237aeb996786d15476171a3b5cab6bb83d000a4e7a676ba17e484d256a1f38c5", "SS2": "1df6da37ee19de444ea9ed91e5159713205f7b3cac31ad2d940015344c21460e05791fa813273a7a3a34bc50f451e25785b27d9f3dada5373d22a940291cdda70cae9b7554c7e8bdb0d4b6f804020faa17b952f642812ee9a112f797164aa6c81e4b9610c9e5c28b0ade1d447542a8e01c375ad9d066be0b59268beb3fa888be", "DATE": 16574, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0b6cd4bf911f880c322852e996bd2d213b6dc7472ccfef4e88c72ddcc1c098c52216cf095e5f995869994bb0e0b49814917472c9ef2ff91da73568c74a52af45171cf540d1863c984eb2f5b900f598d475c0c8dab3d797659e55099ad565213d130c582b576daa1da0ab4f1db6d25e934893cea02be9eabc055fc5c54f2e6d4a", "SEC": "040b9c711648addeac9d48337aca64bf5610d7ff02690eacb502cf53c29a0d619508ee4625ef396312c84e72380271fd1037468b6ec806184e339c7c1adf7b7f00", "TP2": "04014cef6a3197d62da2a4099b3e759917d5e67eded18773f880aae99997c508511a7d66700597c0601e1174091e2daf421c8752adea7a422e368c7af94ea026b8", "TP1": "040907f6213a33efd48f2533ac5bac18948677b2d37871502978a954d285b8b3b21305a5ed625d971acfed29cc00b986a50bf997622c94a1e413ba791694f10ef1", "CS1": "040e0a739b74bd255b9cdde11743d1b44ae77fdd403919a00dc5ae0cb7c662508b1ca3f2b5fbabdd7b1c259d0352bd66138e1ab3e8192e3dc4ccb7c076b7b56f3f", "CS2": "040cf8d7ea0d0da48e803b2558eb334d2a5df59d971cf4563c8466849f9b9e6a200996eae9d526628755227f1b919654c3fb4b7360c7a308e402f9fc2260ad583e", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041923d167da62a82de18bcea4e267124f334482d00538b4a3a8a42468c277552b1a81a00651b7971be8bd89b1b42b2a8d9f8bd2f06e8cb0d809e542ee07e67e0e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "04136d1008a88be0fe18fc87e22d0fccb5d1b5747f706e8cfde061a742f2a3819d2272fb24b9774cad1a31f3eadc28404e7ce04defba06fe770fc12621154b6673", "U": "0415b054facbc2472d9d12abe794801f3c054568a976fe59eed1262ac488c5f3e813af20b8c7e4b0554f8b5510c07da327c7dd2e300f22e5a30685353325ed3f5c", "SERVER_OUTPUT": 0, "V": "040a96cd0eaa154d1b090feca4b53bdac2ca774bd943ab49cd71b9bbee786fe1db21aa08819e8f8fa14b65eaf7a21fa7adba97545f6c71c9845292aca9551028b9", "Y": "05775053c52ddc36bcb0cf6555ed8ec67f552f1dc8e76040f386ed78a0fe1e28", "X": "1b879a9bea86499749a5fd18cc20dd477b918f861e6d7d2ea4bcbbbc7f39b28b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 200, "UT": "041ec334910761fc15c80bf5b1ea258a6398b10e1cecccf84d8862ab61934d1be905e8ab172626d95ab8964b098fa1a73aba3696e24c2186effe4ee65552684168", "MS2": "11d95d99b5f1ded62bd1b5177c9bad9ad1bf5905ed4f07fdfae4910c07c62278", "MS1": "0b46b8b0d209d66e494b5d7e8094666be50bac2c364e640702929339a861298e", "CLIENT_SECRET": "040d496eef8d1e4e2b1e60cfc90f4951682fef19fa4bdbb792b7ce93923c1797dc010356a43ccbe69180a4b04b76650a34b4439f4687cf7ca5c45f97f818a753ee"}, {"SS1": "21ccfde40a54f37693754d834ba8578016a104b19d7551586b82bc10c782955d08179d004e3be24ae8f55994288e0d4cdf806126e56972ee5f90b1560401b95c0f948f4117a4f2ce0115ed2d3be9162165b2918722fbc0f9bc4a55370b59046f09ff36f5a68f1e792b6fd5adaf9dd0f7a9080d97090bd1d49aa6dd4448d98bea", "SS2": "1a438f732dda3269dff9394c822b14d9391117acc90e2be16141744734ed5f4e06faf39874840440fa94a707e576b66d4bd0e434aade0b487e87af1f931cbeea2224da232c5a15d1261e9acb37742084c04bdb091dd228377e18b1027e0a8bc91630668c068ee40e73cfc5a368c0993c0bdf0c828fb77e8cc09e5f57b172a19c", "DATE": 16575, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "095eec7f81f15b711a5843035e9653e236ac01694f2bc3f368e1f26e375a7531190a2d93fb427361e6c8d19f776df5e007da0a72563312f6ced700a36cdd5954124703686020d1efb323c06311949c1b4db8b2732071814a129b20a1b114e60210f555bf6f64491c28d9ddce4f09aedcf055813def4c4c9b05fb265884af4878", "SEC": "041daf9ae4810e0915ec97dd2e7c0e01f9b14a2af11c5482b953b5de908804ed2f0cfeee59a39d8c75ae3f087daf42589bf6b255e9b4fa2b091b2ce0206c69b5e6", "TP2": "040ecad54d79cd2fd57e5b0e9c9f595a4533d70ec02bde64e662d7096753f496e312e1488dfc037ca749666e876c04bf4d67cd8185c169e11518675cb83b03e444", "TP1": "041527736d4d22dba1cc8849729c5f8a24c05411f2fa0962c8803a5a0cc6e9ffee2080977bcfb2e7b78dd1a1fd5992dffc9805ac983e4975db9b09d603ca719bba", "CS1": "04143ad89bfd9ffd72cf078f6161186b5615252266cfd3c8693a8dfd1cfc99e0a9031ae7c8cbd78eebca42664c9138ddac2dc5fbfc9cf50a364d03a171f5ee4b1d", "CS2": "0415999d2e22f98e0a7f88ad8a98a3e6b32fdf9e2554ca078d41c3ed86840b6e5517958b9880c9c4c589fdd708b934ef3e8f6a7ec1f82c1b5ca6581e3a9529018f", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04219992dad8a57973946f9a5578331efe7b7bcafe1e2024dcec5196cb545077c01e54b05b8af0d130e59e9c1f5b21d029ba3b44069e1afe86c8aa42227ca22d07", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "04111e44620acc14d4e72f767efcc49016a4431b96f81b1981dec0b62c85de986e0ceb3f60613e9ff6a63f32dc17d6e2e2a392d2485db565a0a40f46a2eb9d94d4", "U": "04220c79da33c4f892cc1a55897057cceabb7c5074ea9e17c0752f90210281c9621ad75b0b37a3342527b23fdd21e5a6e8c649782f02d17ad080c39b1b131a0347", "SERVER_OUTPUT": 0, "V": "04065190b513e2b01f32a053dc23cdb296a0d2a5c871ec08c45fe97fd1626a2e3d12aa7e98403056d0640d3cc1bda96beedebe5c60e8a863f0866be242d232137f", "Y": "0a457c68ad0b612f3c50d32a4192d60ab18e5e9bd0c580db26ccc235478dfc71", "X": "04de807515b20d2799cb1e3daf6cb84731bff85ad93e03dae80b53832e926ba6", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 201, "UT": "041b8029d247665330cfd595dddac2cd505b1e0cba7408e220c8ce5f4f7f1b9c0915cc67b092a6196addb42e99f14aec06c2a1af1ddb9186e0024284f452b38d93", "MS2": "171d0fa8a9471c85d5a1f3c6f9a70f2452c0ae1c9253f19b8e0b1d00e086e9e8", "MS1": "08aac6e25761b857d4e3c80a64843ace561b883413fc25e3a9b31daa015fa01f", "CLIENT_SECRET": "040da92e61077d8921daef1c705eecff120b17b03347c7509d885c45f32a37cb5f0bdd418f3f46a9cb0fbd8abf00d4074071e1b13767d6dc39a1be5bccaee8a0ea"}, {"SS1": "1ee873c2131fcf66b89b27f0fc15a20c6fa1d46bde0bb159b2f66e1b3b4d7a131f6a4e8548665cfa16a696a143c44de4c0e7f4ccdb59e6aee31a6262fdebe1da083c3b45d07b68bb92a8d27c62fa696d5f46b3f1f403708918c634e81bce93981856356fa45727ca36a3d34b1980a1e0610f98dbde4c6164e0583ae5fbd70b1b", "SS2": "0574e83357dfa91b45dfd3b185f8ef7d498ae700da2589ba4687ae99de6554ba1d6b705c02e27fdc77f1c693c0e1aabe5bcb8d84f78d8620b5c7d1afcaacb94c0a4c971c16075876ca2178b485312bb5f2adc1311a2f56483a230fdfcd567a6019c7ca9c6997afdc592889c8bc122a20f6832581ed646bb8ca4d927e2cd3f64d", "DATE": 16576, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "034185d67198c44c6b65b590f6867e2ed4a5fe08604f05a8e5f17c0201b2336910f124dda2e8bd137c3952700e245ef49589467425e8f8533a7de26c7cf527b815e417c04526d8a7615c42c6ef9daa9f8aef2f52146c01cb92eebd421881c0c00e2225c1754013d533538901b99070a8f64e8a7f283646c06dd026b5b1573dbc", "SEC": "0418ea97e0b12c0a6ce8d8e705bddb7a4d61609228e94430fdb518b208f1cd6cd509de16cd6b1da54d67e120bb4d0ef8f8ea6687c9af2bc9bb9ee4b1049ea2d217", "TP2": "0411d70bdbb13ba375822a520903586fc0fcc35c33826c50691179d473678aa04f1b79715a9cdcdad1bc378556086e1f7cc0b1ecf3817ff8bafd31f8891c3b1d61", "TP1": "04186223c79c92e5308d63e6da411f37cb5d0e2a3af1b852321dcbd5398c2b8e6513d5e09209f3f134813ccbef07ab933e20020b369856db4cf8a0958edb398e21", "CS1": "0412569be034eef60f4ffbdc15ec63fd0b8bf71b91e901017a6da1a41817e072af0f7eabebe18ca6f805f01f469cc318c1cbf66e9ffc931dd2b6f49656fc36cc4f", "CS2": "04022ea68c68c4630af58a641f54640dc6258cb14f98d052bf7f4d867504b031330920e6f6f107bed15df021949af9683e80547507b8939318bc07b30963fe6cc9", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "0416d75e723af14e7996b3c455f5a10ff80a8350be41d9c8d8f04b543db27a4721159181a99b4fb57cf4ff7ddf6815b8200d72e977984055afd010189a1e86a1c7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "041b2c1dfa73493240741d62fa80b776f1b1814082acb13af983e4af7452b76ca11097bcafb4401b010ef04fda18b1c6c484b0dba7aee26e90ae21190dd8f6605e", "U": "041e02230abb1aeabe7a585260cfe1375c49bcae1d048c1e72e68669469e9bf2f30037a007b8fb419ef677f255adc8c27816af14ac6a8ec104e3ddf88fefd8cb9b", "SERVER_OUTPUT": 0, "V": "040e01e16fcb6a7be5312dd0d6708b6295b25f33603559e2cd1986e3d3fbd3fefd10c788e94f492494fac0c414393e886f7b4bc4f2593f283c78a59d7e88be276e", "Y": "0fad2ebbfa02e3006d4ffc06fe903963dbfe7136be3da254c4e796167f791670", "X": "061bb88e1ab5379f12d48d9b23dba9a186f9813c6297e5172b7146edffb228cf", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 202, "UT": "0418e97e07f2a2d2d095bd957d3d3619cf9ab3e4dbd7c6325df3c584d706b1968507f320ef5519ef8f921a4b019ae16759760423d9954176840d2ed370bb32d12e", "MS2": "1b65a7a831577349f061b8f2345cb40b0f58721228bab5a1390b42a41c680b7a", "MS1": "07f9c64dba31aa6225f52997f6c1da139c3f5ffa31a94d6a5b9a69554a9bde3b", "CLIENT_SECRET": "04140e8da61b9b13c4901f8f90bb251559ae135f6a66be72989a914b4f5bcceb181b6dbf60ff54746e15aaeb13a1a3677acf061b3e34e10111c93c9fb5523d55ae"}, {"SS1": "099f01b53f0bb97dd17acd05ac8fd58e4cfe260a9c0f262a263d5268f0b6620114990992d82df7cddcadbf0321e8b67ea36aa04c42dc6bdfdb28cb2a41ff6adc1caeca22d83ed34d3f580ea4bfb26f7125ec5fc5b01196b0fa466907044ce9fa18fe7c216945691c9f2ef3b067b964656cb8d6d98905ce1b940f27c9c4583c33", "SS2": "12ac8a8574c8cab00d496e1e55e115a0c69eab56bb88eb1b40060efaa3243807228983223117e053d2360c6d799c592125bd7313d4c8d0305d2750aef3da33ae014f4f7ab3d09d7fa36ffde4ab80da47dd820ef6b5b5573237d3745a4a27b4fc17bfde09407400b446a99c6e16f755d14b1884592d8ac995dadfe3fba3baef51", "DATE": 16577, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "04bb94bbf76801cbc34f09740661e7b45c98f5016775b06f7f374ce9884926d50067a4d6c2fc86fd875513670c485d4f5a2b13cd524002a9c42331336e88c6d11b8e171caa54711a311cd1c7903adee972c5635a8b804ce74f429064785174ff064c23f737fdbfb6dfabebad383abf6b3f6a4a8f69b0a7a6fe2219c268fdc2d1", "SEC": "040164ff3ebeb4f8f8d327970b120b760f9d7c2f1970b80838c4e483bb1ef71b120a972b7e7ba0317265ed497afc9876742c351b00938417c0cc21cc896bfb9ae6", "TP2": "0400c407f449df18273aff0965a6ccdbabf179390032d0f5e855acb03ab912d232175a5749e2d77dd7c1ae6f5a9cf0e4b9a8f9bc5f6fa380f0276185b1279db47b", "TP1": "0418698c8d80b1e354deee1ce05c0e8d9d16cf8964e85ba1d62962b8df96ac24a001732381e99afd6ab60cdb4e364165266e9a73409f0d1b4e61f7aeaf227367f2", "CS1": "040c022f83d55eeb3e7b658640939c9b13e8d8b94db57a3579a05e970fdfec164901b801869e6d81d435973a100623b976cd82ba1cb338764693fa083d49ad3e71", "CS2": "041d7afdacff4b1f34db4e2143aecd56cae572af8a6e0b72a5dcd8512b4cecc2381d910f34ed772b13cf036de5ae2e6f094a0c7ffc96a31ea042b1eb1d65495c2f", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04110b4150d861866811ab5877ab5818e434de35b3e61d58308df9712c17f14b8d178d5a81be871c9359b2a33e13e512307a4e83aa759912c9c12be8fb126d66bd", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "041e878e140477849ba939e14d11dc6be76971e07f2126c69ac4e778f732726e2709e9ba51387db08282cb74db508109a0fce754d5869be6c3a5b6ced15fa46579", "U": "04080dfa4e1887c24e608aa36353e3418ffb9947d4cf274056fe63d23ee5008f840f53780ac4b232c3a7ba08e9bc6da6d710599a527ba80c7be1482cc459e4087d", "SERVER_OUTPUT": 0, "V": "0422667821769ab677b0da6008d50e7f3f815abefd7d796f034e521d9726c333b81e62a62cab0dbb4303e3469dcc5e5356e6292588bc0e4bff4b0f4b567d797a64", "Y": "17159b2f9e48822669481dcd0cbc6f367383586062a0a3a299bea0e6650b5215", "X": "1a302ecd8ec994b7b2f1176bb671a3393bd140a300dd85688a1ed2c92dd06b78", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 203, "UT": "04134ab0a251c82f4e30b0868347af3a186389ff7ccfc26671794bcd007030772904b0be719b5cdc2115f3aed342aea24b92a2ffd0fd475da3f8c91539a55afea2", "MS2": "16b9f63fe8e739d4bc0c8405a2164a5d31a0e4daffae29ec7185cf8c8b736470", "MS1": "00af6f75eaf2606339226361c841d873d7195a51058269b73a89432fbf287312", "CLIENT_SECRET": "041756aa8db396917a58a37be0c8446a855f0419b89966de53153067a772ee99a50a3c4c8383a173740c0e0776c15062b43ac253a56f8b89778f57be0e57765d4b"}, {"SS1": "1132dd8c14351efa5b3eb42a71065b626fa8cbb0856bb68a58dc1273e0a9561a1ef6582add944650602f95e7d4000513212da5bf51722e943e4341221e4543481f5db0b815f33fa427a1565745e1eb630ab2d7696f9088a4f9bc34d5fdaba56a0f051aded1985b14196001ceff417825cd2acfd033924d3a9c94b5b70b741f87", "SS2": "0e765da6685c5063fd141d632ad0dc95d21a04ebc2e7ce251468db2cadb9e5b61b65ab631afffe4516f76654cb2f286442afaa7bf721398f015c10c8666b5f7609b3bbdadc19b33f151c74d3fde67194afabb04b15c740c36a1ba94960d880370e89cc3313755bbdc81b5399d66b42ae0c1fd4443c304519f99bf85b9cca0a69", "DATE": 16578, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "083c60299845576f73cd73785cf63248aa4364f94675761de54e51e7cc2268d00c58046a51eebee7b3b9c485dbe6905ab88f01144962ab02e657b46239a8d1e81f66268da34cf6169a3d8a0f24e3c7f333e72596e07f4942d933cd19a73769951140b878848d06aac9e7792c8220b604bc976c87f5f9e395f82c5f185b5551c1", "SEC": "04139d14875e3c5bb8a6065862ba935ca930e0eb3cb6477bfc06a586bed9b8c174065d0cfd8a382caedc115d9f8d20c5db8f5d4428bf0a8ea09afc5e5eb760f86f", "TP2": "040e2df8581258ab062d7715fbd6bcce44583ec70c555eaa4860d4f64b2416238320d4446a6f68bc2c28975afe04fe9968f6123ccc2d7d64161c51c069718f3fd1", "TP1": "041badb763f92d74fb17d406abcffc78285758c5b8e3cf2ebc3f3a12a99ddc12ce001039885229a8f2e7a82c49565666cbb7c01bf2bdc9a998cf3b365b5acaf2bf", "CS1": "0412464537ff19c8b74b25c10e8258e6585a7608fcdbb43cce01365c01dd662c75081965b0811764f128a383305441338ad812b7e433bd1ae5a44fe537f9e60fba", "CS2": "04032dc8fbb694b4bce24b82ab42f056451f8253250c6c2b83e0a2fde3027f79fe22cb95571d0160377c3c4a5a3589e319af013ee3cbc3c0470e9fcd5072a7a5aa", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04123a3046285eb9b8889d3e2d580f3fab1fd7c10442e9ab5d6277843a9906cda403a3d4f4d38e5f1882eca2ae24b4138ba43eaf4bd63cba47af5d16d301ddbd1c", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "040241aa761962827ed47085c35ae737c7dd513f3f96ab96a005f22325e3a035791098f1d56e6c6e2a662a890e0418ad1c32441e33f3917c4b07b4bf71c99bc6d6", "U": "041ed46e6d027babc7fbbd4cc110121e91006c5fe3428d045263d6ab6fa4601fa3181d8216e43f4bd0802a8b9a67b82d85acf0b4c1707c6f572e74d6d5be4f31e2", "SERVER_OUTPUT": 0, "V": "0410b6f30ade2d097c72b6b93230f2f6dfa26cb8e06166b700fcd460985b435efc20dfb9a561907b0385e24c273de575acaf6362fb19be89613263565b2aeb066e", "Y": "0c332a77845753c1c5b845efd42d5de682d9d3e251af66a8be8d7f46bb2d643e", "X": "20d4123cbc0c892bb4580f2cb3bde97b560c260502d1e537a867658c70e1d71b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 204, "UT": "0402be75c0f934f72bfdc03285fd4dc5383b16c967f5bd736b49190b0ce2256aac03e612c195c3550d9b42982c8041b6d3f5e3fae51ac48b0974be082ba15ebff5", "MS2": "1b9e98d5bb59d209a9acf6ca18016a3972270c32df41e234abce3fd795550e05", "MS1": "18e543f8848a64ca5344d15250dccad9ff703377564860ec29162e4875c684b9", "CLIENT_SECRET": "040a61e9bf8cb430eee827cdca581bf4cf1285fb1ba672cb6f22087e9bad4d37b50b0b5e63199db95d01d1facb3ab74560f25aea69a4ebd98ccd9fb1ba29895421"}, {"SS1": "13f4546955df0ffb2cd02ce1bfbb5de89aa0061d4d4a9b494b6681fc14075faf1a31a775a6143bfe1ad1b950b754d87a9bb95c35d6bb15fe48b946a4a5137cb00a561d21f1d2ef3bc6de78c92f99de1adb4c1e9a3463135eb37df2e4e4bd2c1413aca22a28f830d9d2403ef55d7b381a126a8208516b444c29c5447bf7c48e2f", "SS2": "0a2fd502d7880621aa5c1dc64a367ac146f87c7ffdd94f5b6030d5bcef61c7f615d0a738bdfed64f3d1b2588de94e90e76d53c0d5912321a3d9a3a64d7f4285c19ccefad6bdbdc98c4a52a8ec0736e5f56f695ec16f45a33f6b2e3053c9a860a23418b77f5809e1ea6aaec5eb487e45108b4f872a1cebc31c958dc8d232d748e", "DATE": 16579, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0a03c3fc5207a829383ccea41f23a3bbc10c60da08e3b50dfcc3064e6f8d18a016b38d3727d8de29c7db945d10ed9eb83bd5bae3ad5a4db40b5c113fc87e77b601a3b3fad0d3c51e453058998403c2fa3ee57107de14ac6788b7da599aaab31b0f28c69bcf2b75cbbc1ccd0acb554a0865a84f126e94d53b2b83f9ef221b9c99", "SEC": "041814018a5469a4728e4c0532441ab09bdf10a26896a349424bc256d6db3de59b233de7b213097cbdcde05be36c42dd96f646f87afd1551311a4ddc193066f953", "TP2": "04124ca3ed47e9359e9dbc8952b0f5c25d43c08b1e3d514ad423f3e9d4b56fa9ac10d9f041cdbd8973bd66dce7f46da05a1fbb8d8c33cf9aea01e7084ccb390b2d", "TP1": "04080ba8e71e571118518f6080fc7b23765ac3f2089b2f803210110b25925c80fc16c1730f1d8d0daf909c4725081f9cb7af270281756c3d477f2648c631e87d7b", "CS1": "0407d047e046d63d7f13116b219870800518f76cc421d54e52d0635082398c4af31f988a68fd334358e02a50c7ebfb402e872f1d1f27d7c587577121671e8d52d1", "CS2": "040be4518da61bb3380a8af5548a7d1132e07be922501742bb48e4258d3aba4a97126f76e059a4ac804bd22a35a19553daad53e8dad25aedd0e720c8211559262a", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040e78e9d1df0d544da046abbb0888e5b40075328b92ca953ba7226aee99406a2623abbef1d483b7508a45f990811d8220c33ff72c5ac4e8d9a0e378abd48694d7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "040c83a1a878adae662afc9cd194ff921869f77080dffe5563417fbd0510f3da221742cd6f1fe27640f1088991935310e8f8dc7477e2a7836ccf9a03675692b7dc", "U": "0400643c370e19ac236d270985965d25082257edc3d3eb9dd94faec2f336e8996c15ca0888db5f218101f85e4da3ff9cee8b8297f78d7b0b9fb8dccdeba85eebf8", "SERVER_OUTPUT": 0, "V": "04021fa69fc96f4ff8931b3eb2cb83b8c56b8b5fc1c05abf47aab546d49b3a5db00fcb2426ace66578444cfc4570c56968f3298b0ad207209f575bed0ec38ac9e2", "Y": "07afb6d26589c9815ca51ffede6b1f180c50ccb81dd5d10b53a81ae3fb864f8d", "X": "1426ef6ba1858fc7db666e41b9da3f043dc2b7c2d22f4e0389734615bcec3a2f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 205, "UT": "040e2bebfafa45e379000e4244c1746858c2495f8a81c5728b5ddda94c0da86463125d3b643e0dfc0e8befd70d75bb4166b6aa71effbe1af3a900b57163df654f6", "MS2": "0bc74a0a61c8612f1ff25f725678e0a52aba95569cc85d512e3260a00e754729", "MS1": "2386bbed2fa614246d40ba2dc3d7f1c44a66011577f00d40c36dd75ae0111ca3", "CLIENT_SECRET": "04201d5fb2c7810886d6f3d01f730aa6008f90d44a9d91f6ca63ae88c623cd019717043ff4788d13107286b156a62430c11266f86b6d57c6b90173bfd569e9e320"}, {"SS1": "1f719fa821209496c47170865f91593b1e6a672fbea5a265402899b0aa07551e19cb7d7d8d5c2d1f6cb1ac7e2dffb8c982a9ce369e8d6424796ea44e5b911e69038101458ebd383e2acd588b529374605b04bf4e394e685be30c185eec4c45421177ba34a48db14fc99232d8017c87980b6b505c4869a5ff8cfa9691caf7ceea", "SS2": "1d611000c7215fd87105cf5a80cc8c881755cdaad6ba681a37f764ffa29c29670ceda8f89e42ddd32b7e5fbce28420abe9e4361e49ccca5724a3fb7fe25bf2e000017aa56e134c5c39411489783c97e51254e9f4de3151aa7987657c76740c8106125484e72029770b30f3fad75d78575832f36c655ca1c46e01f80d029787b7", "DATE": 16580, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "019e4a9ccebe61d4beb3c35a5a73fdc5f498ed7e897deff432a21ff9ae4175ec075f1bf8f03f770ce01fc449f5889f096a6394b69da19dedb126aeddb02dc72319c4ae96bfaef3c955fd26e4cc2223a793be4e6aeabb8d658ec2c8441c71c10106caf2b7e73c1f415678bda6f7829b64817588f34a22a1fc2f69c5a5ce790c07", "SEC": "040fcee6d0c30800fb066999d399671985c25a26a0b13a2b2add55475dc80eb5ed22952f71d7bb14af3076300ff5e39ee340000ace924b0bedbbb78e80d1f56844", "TP2": "041f6ede348de627dffa29e970894b8a9c3a9e6361ab0f775e0b207e31c1864297094006244d93654105af1f988bdd2682e90af09aa21302d699e1af9238d9b829", "TP1": "040597a0b06d012385d5737f663530573d3fe1876a50d63df33a92f40f320241d81faf38bf6da9b63d0b7b74b642b1b84e4576200e18005de2ed9f9cd637bd8138", "CS1": "0412519bd4ee30cca1c845251abc031d270e2af73ba90fc56207ac5aef2f4401cd1dee4f0f92e9ee2fa07a43857fcb6abc51c63f7697046657ed51a802142fcc8a", "CS2": "041c7f7d3333bd999a988580049be6a51eefc6d49e7a49537dd1b947b059c2f334082643460265fbd05d5ad91b758bfb95e8c3e054ff9d4d323758bee6e69f3769", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040604899ff4bf50b31ab061dbdedfd2ea6d44da454ea3f31c17b23dc300a3b688051083135832094fffd90894cb627d2512b9654a9012f33ae0603e2b0718054f", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "041a9c1d39acee8b84ae7b8ea456cd718fc4c95de04590f4f62f4f444f41ba0b7503a41ead3f5245be2045ac1de8c5d560237be9a76787f38faeef9fa286647984", "U": "0401c55fa7ae9b3dc62c5ba820eafc7935f5d488a8e99f293f5fa88e02c832d2111c26a539aac1fd6f589528ec42ff3570d21e8e075bc23e0689d36a9c0db701a9", "SERVER_OUTPUT": 0, "V": "0423c2b6f8d0aa23a4ec1287024af2481b1090c02f283ac736c1e1c27893074693058b445e40ff00e38551f5b40e30219614a7d35e7c7d95ae39e67bac725b9a8d", "Y": "08a5961a83abeaf8075602673972f3cb95b93c142d368341d834892b29aba0b8", "X": "094c97c24951b46c4ff3a1f6f11c3723cec7460b8b94a9b7164e19057b697d98", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 206, "UT": "041a265be0f6109e0db83518d9ad81e5c1e04b9c8e12598d1e8e27ae68457356a11fdb24da0d3bb21d26eefb0c9405c2b4a3ababedeba91e2e89a801cd96c8bfee", "MS2": "1fa383d70f3d329134d236795c685a3b0abbdf271412fba4c7fd14f902e64851", "MS1": "1fe204d02f9e8d6af6ecc31c3ffceec3333073db2d9b7c299b2560cab5628a28", "CLIENT_SECRET": "040ff5ee6746c60998a479918896d3ff7dd2ac29350af5fbf878adcb0e0e6defeb126f9da1ed0549835c798fe012fcd8671473f06457ff244aeda5319f850cd4fb"}, {"SS1": "18e071939040ecdaf7734e103a625ec829d7b9478c98c44fee1c877f5379e7a414df57892db312483782409754b48555f9473e0f7bceeee261d09afec05c3d0b1a434780a52db25ea7b3d4dff8031fe4efed3376e184a3eedbcb35001198239702965f841faf9c91e4267309196de92bc72969e28cba37e0fbcca541b8fee0a5", "SS2": "0b8f7905d84441377967cae470c64d94984f553b82d96f42861edca5546efc4b155c63f3ebec09c2c7b91cac4fe8cd22103b4dcf7130702db65162a0fc4a194a1b131895582743bbe640c2487764d6636d199d3ae318ba49238901c9f5eddc2609b967ee7b42486daa344d7e11bbf19dc9aed2bbbf6ce19a9425c8e9a21f7202", "DATE": 16581, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "07bafcf549dc97680d5d03d9142743b84fce222a54a949c3127edb3e47aa805e1c51109a6952bffd475c8a8bc10b5106993683e5f3fb194078b17c1e5875514a1922384aa5bb45b3f6b71fc5361f820b00f70c0a22dcd91a14f948559c48ff96128e392084c92149d338b779b733a08d42afe8df6e2b1562798c1323dcd4d40f", "SEC": "0412be3d760a9eb08981af690d630095c71a18e9134f3dbed6d375c5255d1e7c090900780ac2892962e7f7d9545373480e1cc5f4a46b07850cee0e8886b0deba8e", "TP2": "041dd9c72516d7189d5cf55c3efa5b0d923d2c3d7dd3207da4b339ff2352f3204305fced6c9cf4a0973fc1563f1ceff976c3611d2cb6958d49e5a38cbdc0e88534", "TP1": "0415df589e3211372847f3a3b05e445f1d3d1ce3931f6bebfca47411653e383359140969ac68f3eb8dc917a6578e80dec188e24269c02db073c0db227a2e10c552", "CS1": "040f791ed5030a3d5170dd9d67656b40fc27b843978f8ae1ea7f93c06f61ac61f50b93626b93e277c203d1da473bcd895a06027043dd2d72735550467f7d0d68c5", "CS2": "040c5f5eeb254f04ef8b02143a9a06cb414d2e7b63895cde445a4d83ac7703130522b2af86a4f5a571b92d3d9346bfce79bad4a5419027afe394f98b0b32e46c2f", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040aae717a278247b196fc486057e41db214a33d4a111099f378aee4ec3bffbeb604744fa4002820180aacbaa738892b4d07704c26dcc025011b83b8e50273073b", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0400f1b8394b851f028d72e0a43759b649d07a85decbf05a880f0e513ee5d8d17715344ac4a32e70427904c72339b534c7f5fb9af11a057442705d37c2712f7471", "U": "0406f3364a098c91aeb008bdfc8d7da742c51c22f30151b78d9773b84751f60c3e0ce7f879f66c9cca0ec6da20bec9cbd312111f9639065297873891dd3253632e", "SERVER_OUTPUT": 0, "V": "0411aa0bb26157774950c8c773ae3790675c5702ee65db33646a3043852599ec570350f3c29833b53ef297cbf48047c497287b4ffff110019228e01a33cc64feb3", "Y": "1a83349891bf65852439fe29e56ce3a87d25b4ce4a64347cb3c32ea198201492", "X": "228a9500bb4f4d2cb8a8220a1672b5a35d9f90b879f0339ac37846db01e3f581", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 207, "UT": "041e68b6fcbb517124bfab6cce9297049fc81fb7d9480153d97bda0c4ab9f9ab3e0baf1baee6d89a648b2cd4b5ee817eb29f142b4d21a04d77372c66bef3182bdd", "MS2": "1f0393bb02252f6bd4425c1c3613fddff20974dfcea02d8afd10c2d0f6d9a232", "MS1": "02c3a340ed4c93254a7021d62f6fc0b392499a728071d6ff13eb5dba8b48ac75", "CLIENT_SECRET": "041d8fcdc39cd27d37c3cb511edd74653c1c3db7e8683e7d6433f92e98e6a05a801539b5f4c89042aa37dadcd0ee1686489a7262e621ad83c9346695b920ae2450"}, {"SS1": "132ed8bab703dba834b53e3b79b59025ac3cea61558a67edcce52ee9d3c3c48006e852083474cbd5e8f4fc365a23ccf4a4fc7ede0bbdfce1d0b550fa28a97a441087abaa810a30bd901a3949ec3a500bf61a7ebc713ed555149e465c12b9303c14c8c689c749e4c9180c014b84a0b20d03a6b3bde710e9a42ba81791214f27d9", "SS2": "21b28d7ae470696ee2c26572fec1c14646236350d54748bfebc3f4d41ad327f910d242e6410c37370b10beabb5cd258d01aca3856b4fa2dd872ed2d49c99c73809b8911a84888de344f7aba31573f26ce204db64c83f0f6bdf8f7c9b6fe715b8213c691461ad7aea3f86cd61caf5a776bb1690ecf663f8af2f99000bcf86d898", "DATE": 16582, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1cb7b02b4e20586a544ff9c672182af8c8469db2adfe28a877f6a26058c033201cb770d7e8ee48c843701949163906532087efcd49c5956aab6d97aa58fde39a002367481487f78f045ed91b26f33eea1e3ac0a9433120c3efe6f8209b3808ce19d934a5b4fbbe8b5c99db46f901c32bfa966fb7f5016c6979c13ee3840d92bb", "SEC": "04077335ceae145482d8a26bc21671a99b84b5549714dae052f4747d71a2190d561b05d58650ae0f2b1b51cb1ae8499407cad2c720112b9c192b548dd1bccffb00", "TP2": "040a048ccf8bd0a2c09f6e2244f1b2ce453178fdfc402169eedec7697934a362350bdf2e1dd460438f49db9a0460cbddb9ace78be2be800c1de95cfbe7c340c3f6", "TP1": "04120df1e20ffcde1c33e08e8f930a6ccbe4bd596118044328a6119cd6c5abb0e2174a60dfe0815537fb59b833a85d7fe07bbc42e0694b1edf22db2cf8bd04ddd9", "CS1": "0406ce891b108a74baec4966494558da3c34d8ecc2437033da6db98d467e44334a04f5265cba1920d2b973c222112f2358f75e77a1291bf26d06ab3bd55851183d", "CS2": "041bbddf015ac92a8ce5fa144e9fd488a80c4e913d1b3832941030fce5936e8cea10efe7952130bca6efd1f3e2d1b282c4839c7bf083979862d929ac39891f895d", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041051813c96d169257d2f61e2f57de3d91bac044a0bd93c5db1ebd64d36281c6709e612c6d6b150f9c159114d1c1e8917e36eb718210849b252d4b137d120e25b", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "04052494fbbb002bde392437cc4e58181afec2beca8c3a10c509539a12947b68c104ba87c2361c5ead8c8133d9368f0066ba1b87a57a190aa80c8db9ffd23b9609", "U": "040c716f5daa8b647d14d6c0bbebe64ee496bb7618fd72a7731056cc5c680bd13f19cfaa0b3caed1d9de103e90f179bef4c95a9352b04a1a0f6656e3ca217c1333", "SERVER_OUTPUT": 0, "V": "040392b5eece61a3fdfb8e8992eb38a8bc6164f814c4d3f9e1ddc8b6f0c24451db038293c903d078bfec74a27c378f193133496e3b29f22958b6d0cc804ecb1326", "Y": "15f071d96957255620f415c2412179999bae9a1cf42b9612ab8e2591ae098bbc", "X": "149c20a5e66e23c4e34f0987817b2973e2cf95b12b2b482fde4ca84e63c18f03", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 208, "UT": "04094659ee651852945ac36bb5163cbf4f11815dfa8633aab93a8231671c7dc4fc15630eaa96dc2de4a9a2e21216396953f9f5c3e9c70b9bbea8614222b4993ffb", "MS2": "1022c2d3ec46dbdaaf66e4cb11fc94b0f297df661c4fbcd2a5f7d1de27ad8905", "MS1": "0e10eee9738fdd25fb32d6f6379bb91a3e68454fe55b352e91df4540ce72a2e8", "CLIENT_SECRET": "0410fa2fcb8071c7e7890125798d7471a554da65a5410feb827502c8faf40a7452057e918da9b5cb96b494d4ee77494ebed6a584091bfec60838e0af18dc743b95"}, {"SS1": "1e521b749fe9ea4c961f567c123da1bde81a6080130516dcc7697361a20ae70b020e586c1049082070edb48b7beb4e98172f44b9c234edf8662c8c11c810a61e219db29f06fddfb85ccb183514c4d021ad9b9bbf88343c3f9318062c323b6b0f0f739d414be1b582b28d6231aff2b24175065e5118901dcedab07ac30e4e56c8", "SS2": "009f6ee34597512147f10d83327b28d6660f128ee9ad22e71cc585c993e049760b533d6b32153d3f09d936477a41d7b0083cd17da538fbf05d6d4222f11433a403582d7f4b4f92e69e5be7ad6a2eb8658654d4b3f8d7a00edc6f20cb903d0c7a184ede34320c0584f4fb32e2cfc2103ba19da6d03ffaed6e4056213614ca57d2", "DATE": 16583, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1d28ee97dcd6b79b0ee9e57110e31c89d347afc7d4aeb9970bbdc69089a518af23168d2635bcda3a9458b776ce9b63d9dc87062036596418c1b3b98b7157384b10bd05b596f4dda9ea865bfb5b234b761ac0166c8a76ab00242ac6f77879650a033919b3e2cb80a84ac9d4092f073868fac52a8a61d1d69ff2391ecfdf9aae12", "SEC": "040fa1a1b593c48ca3ed43fe35ff7a9477cfa6b8798664ebdc8599864a97fe9e240ca89e44c626f4ca647be474addbcdf0550ce158a7a53dba522bf431535ebd79", "TP2": "04021f5630ab5d9508f97e40d4929139fab696719bf4abe24d84da87ce0a73fa0500ec49dcf062d1820b169eec4adf1546967802506df66b44b1f8aaa064a1d175", "TP1": "041eab09171c18b40b7f0b10a9864631ab9cdd01d1e8b3365ac9e2064a47bf10ad017296efbfdffcb5ac16af68f299e6fc6a629d60dc2d5856aba7960e6a644243", "CS1": "040efa53e84c899eb4ab2a556034d2de24e818d3ecc069e350a6938d7552ad079217fa9ffe1f3139326d7cc4c47b7ceabad12bd177319ec747ebc6c08c55848246", "CS2": "041ee7eb1c0fd42ea77bcb517064bf536435e1642e688c7fafe109780e7e9c9b470a37244d0184dd0204a855a790fff0440adfa5ccce745f109a97d774ea117c58", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04148300a659432175668e2cccc8ae24fc1a873265c86d43812b238e5c1d56750d0d4e4676408eab85679e75c82af451b34cdd27fb74745d25e70c3211edb2a6bb", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "04152d06c6104c68cee61f42f237735278a33f2b20f66adc847c719460d356a6a90820a3497b6b011a77a6ddde944ffe3c5d455cfd76d2441b7db489f9f5be528e", "U": "041a18aefd88086ab54ddc355766f7385d5a3276f30b4d66d7b39c9adf70b55f431123978830df093a8c0e7bda0eac59207f9615d35fe9214e8d8058b1fe70775e", "SERVER_OUTPUT": 0, "V": "0400507107cc806c5835185a737b8d0fb61fcb363d9ccd38a945e3d6bd243de773178fc2cc3d134d801e5bea74ec67911e6177382b17f3cb9ada494747217191f9", "Y": "1843f43e3b2b1ed1d2046880d756a81fd605c147d981036561dbbc36ba92fdd0", "X": "0979058ab0c1a7c43f4b745492a9def95f4741e13024c98bc46e2f9d9f20152f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 209, "UT": "04077dafd5613402cebe6b1ae420e1a436e3f7be6495c7616f21a3acb321764872232cad1b32844e0b2dec0d61e29a8b5e552bc611b001a6b91c49d521ef7f114e", "MS2": "1fd117c677dfc24494ef16bc58a382c02512448e36e71982e88bba1b25462bb3", "MS1": "07a4439b2488d6cb6e1a83c49a51741360d3b8a91752d8a1b2d53528753c4d96", "CLIENT_SECRET": "041617a5b9cc6f6337c7a86a4bbf765902d91c41ef7a279bafcf012b36de9aa40c0d6675ea79df6c239ba8673764ab0cf5420bcf41f469e7940b3f8638a0be6af6"}, {"SS1": "10e90c502f8cf7f8e60fbe788e12fe553c676bc21dc03e58cc5d79d2475e70720ae6bb2e8927751756e4484059c0d8b7ff5727c820eee9af6c728f2abb27a0461d06d28bb4ab8f480fe8b91f8399443766ba4b81e2f76ba92b358e75228fd0241a9da501ffabba6dc7b3d7beda473f94ae31e927067b6e6063a152e8a7df511c", "SS2": "17a75119c2450bc438b73e503eb97c67dd2d19d995050153f1587ab0c5560d420b8b28bc53b14306a25af29c05d7e890704a92d9bebd2294181d319364513dd31d987c469f2ff990b79e3cfd00abafe10fb159d3e06d6283eeb0732cbaaf0c030e1a9fb7d8f8518db3f7ab90368823953f99c67c9f6a3a4a13fbf4ef376ebbef", "DATE": 16584, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0b5081ceb7d3fed54f7625b1b2b4ee904b4e796fa5dd9c9262eaced71d9b4aad219968ad157818a9dee1cf8f6b6a36c049fb1cc8a4ff7ec0f6738b8d27534ff2057683f19c2cb8296f5a69df596c5e8177bdbc5fb23a6b8750be217f0ea1129007ded84d6eaee7fbcbc95ab5254b6436d149402bb1624a8fa4fe300ba9ca7a43", "SEC": "041b46a853426076bb147eef3a5d83f0aa2d0ab6343557215c40c5e0be0aaafd901732ad7445214dc36e687b78068ec8423ff09f14297b1ca68d938348d108351b", "TP2": "041e2ee5019f7f75eeaa779448740a3675225d0773b564c69ec1adade5b9aafa1c02e35ad8b4390b144851dabc81b293508f72db40ca84cfbf112cbe76d698ad46", "TP1": "04081878575c97930d624ddcaad7d5383f53d6a4c6ea8d8e68faa5ee9914e511401cbb5f070ba77f279e1a6b76fa131abdc24508a01f72647716788b11f9cca49d", "CS1": "0408f1121c6004d878d3e054dd02dfe24e8df50862f0a519c0f601922bb43379210cd8eda8d54034446d3db8251ed8bb17311080ecb2c2bb7a044d45e77bd97573", "CS2": "041e21792ad3d7f1aa64252a96a486a9a6d8d8762959474b12c7fa6cb175c7d0d301343fc43904eb0974487fce0a6a30983c14461d9654c72af1fa1531618f2847", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041619ddd0c48b4c5c253d6e4d7584d126145f1bedb583f6b848a247aab7e9c5331378ad6cf2cff29a62878ce39e227536a61d90ffb4b65c991cbd19481fb5f2d1", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "04079e56c91708d8dd70c5f1ea7d8a2bdee7dbbf708ee810be4387539df0ee72f220c68df84a3ab33f7f27c1656c754d4e915c0f362e0bd8ab19a21881b74a8b87", "U": "0410b35b06200427dc6d9b70d0b2d68dc8915d07d8e0085ace36f9c630c33d39a00a49751fa3801a8099c3b1e76fb28d81713fe6995657ef4efbe7f8888709fdf8", "SERVER_OUTPUT": 0, "V": "040631395a067373d883da294145857bb356ec75e43998f13e58e5e7106c9dbaf6019b928713ade4ba870868ada5dfca82f4ef17e63a1b8532ad363d79342db33a", "Y": "20f5b3b880b657c37980c1c14d442212ae42c44c899a8f9d6d729e47d20e1141", "X": "0a741c8c3e6b7456580f8f664e0525ea9cb105ed17223a4f9a769b8b2ed31402", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 210, "UT": "0414c2243d3265fc7797a71ceae38a88624307bfb67fd6227ba7d541eac0bc456c108449f04e5431934daedbbb2334fc391a1f4308bd2da5d31a462c9e9642eece", "MS2": "129e60202eb40fefc9c258ea02c3ae5ff4599a5e508464746c4f1581365c85be", "MS1": "0baa03a9f51b1e0d9c7df00cbae4c7c0bebdf98cf2c2400d93173db1b1f5470e", "CLIENT_SECRET": "04058346f67b0ba31df4dc352f6e4918567bc5926357be18adc3596b7c7c721cef0a2f107e47f539c9cf5f14880653d0d06949d05c9b6459b5ac03e91a7910db38"}, {"SS1": "2005a0015aacfd9eba77e0bc6ce5459e1af5631dcfb3bddbc7a8e698a8b0a39b1e665abf40df5a4522a36efad4576dc2f8f6542915cdbfb25b7865f33a40024f018739e4992e7c55d85458a2889dede8eb5ab0abb8a793e177faeb307e4e5438031aa1310f0ea43581bd47bda73ac03a9568d67a6dd4589235fc833486f8dfcb", "SS2": "1bc1823c38471c1f181cddbbc2b24db3a1ee43269f0e10d1cb54ed97ddf81e810ae07a9ee7a5ef6e111e19a801603b80eff1a59904d26e1bec9cb8347bba485e0385e9284c974c6618fe8727d45206cb83a734fc87a0ef9f04471f9a6c20fe3a126eed9cbb5a6d7329914f60d147fa4633f5d95f89fcb6bfdf2ce028e5817c03", "DATE": 16585, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0c10bfc96c3da7e7158294a25fb83ed1dfb21f60b89ff34fea437735faaaf2f41f5d78c03d478aa46f7c0bb5abc4a5c0fee41465807c25f34637dd1a86c1430902e0851bfdb69de34b90b495c9416b75e3e260106187c78d570f1f99bb30586f08a3b25a47f761cd954ce7a1ba5f9487340b1df60965be6f03a707cf2fc10aec", "SEC": "0401eb8780696e05e02b04a13b0b959294dfb56162c98436448d0149cbd4dcc66216ebb6e758722611f39d19075b3619cce9d53b711e72d39eb251d842fb737858", "TP2": "0404cf4e677a9bc9724cea272dea637b8a2d83a95a51ef247521bcfecec41f6dce23d8df49eef63ff31bb5c56754e8721639dd8bd6f571e06891767598605cc4bc", "TP1": "0413d2c2d7fc934352091e70b6e4eefb4436bad6217db64fb61fbb041b76d766a7218de4927d4953d42c1bcda8c20c30253e1d3bd717a06f63f4f69970e71d304f", "CS1": "0402178aaaf26e7a1f58d6464c4ec762b00d62a0ec23aa7437dc1a58b250e54f88233f6b6291866d12d02e1d3f98e710185c9ad0a6e49eb565c996409c88de1f07", "CS2": "0417584fc718db605ba5eb1c583d9b9289e4f211ae09c571779edd1f807e942f49104fa007be90ca933b594fc2438bc080e2c8920d18c1453d32990f16085e6a05", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "0410c1275b83da13ef21f5cf6cd895c5bf10852aaecb2ca06ddaa03111d76a974b1d9f1e234c054a389eb6a238e0c4bb884667f739bde148bde8e46b63d5dfbef7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "040eb9701cdbfd450fe9387f2d4163061c14d23eb6f3403af0dc6566ddd3cc353c1289722106bbc02bd73100eef44917229bce85c973cab4b05ff8fa4179bac53b", "U": "041260d3b5662e9df84fdb05e9ce52d42912ecbeff47f3f4f1cf5898a78d2855de0ca2eb3c736e5749b0b7231f9ce471040ed445de6f3f4de13ab95e640c293f2b", "SERVER_OUTPUT": 0, "V": "040017703dcef73984647e78c94e2e3f9c606fb3753dee4b5e2f2e3fd312cdeb8a04ee5d05ee9a66183aa47413e3de611ca7cae9ca43045f11ed24e1b41d427347", "Y": "0fda90a46a78d7bef09ef0d67a21ad270a66e50be63820df2aee3c0ef1c68dc6", "X": "20487802ac73cf03a621bd504fbf8d3c5adc98a43b6bbd73e35208ac1939b5ab", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 211, "UT": "0411975154ed3f3aacf72bd3d6a46064dec73bbcc8cf65af5727cc97a712c62c14053b946c327f3e2aa7b49a793f7cfa513d71599d95791d464d93c813813def9c", "MS2": "0fc56120da81f87dad9e541275191ff54b8882c8a89f001f199aa7216ebc8c4d", "MS1": "226e5316a221feb3bf980d21bdb9fa0be3a1a3d92ab2e19971e0e4f116a311a6", "CLIENT_SECRET": "040559c34e8531e0af93e0331cf22e160b9589d6a20e5c0f117dd7ee3368bdc71f090e0a023d5dcbb7012736072be1c8e9e2e21ec8dc48ff8e55a7b82dfd9efd8b"}, {"SS1": "1e91acb16340dc3c2e5eb084b59cdc13e6f8416db8326a12aaf05989b67d164603c00a27cd18ee32407bd054c171514e8d3db20446b4e5eaa738a40a3eef87ab0275d5918d784d1f9de66fffa2bd03106215a51a6d49dfbd14a3b8584515463f0e7cdaf371f279c79b5e61bb50e4335f0cca826bb60ed721219905b3b9237fd3", "SS2": "176fc48c6477acc413d1007f8901c3fe2a1c459ab24c8f10d5f12a8ead6dcb6d14c951b4c6053b2c08896e93523b89ee78594d7f58f9b6fe795642f18457a6111bd6c06303f2a679e765f217a6f6c23ff5884d632f14ae4285ee39a450f738be1c217faf5c42e1e1522d377985d449f18b7784811debe13166f705bf0c84f76c", "DATE": 16586, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1b3e7f62ab1bfd3ffe2697fb1cf2e43677cd55bbf55b250a2facd83988a5de96073c83f97b4e1a2a0fa7377e859cc604d15452b934654a5afd09c53bf9ca07a108718e8c3e377b23eeeb89354db972275d3c0af54e3542ff500f62dee21cc0cf1379ed5101d035cf0084a970f42f64c3936bf9243e92e7e847bb5247b9585498", "SEC": "040ee94c30d790a5297502c7ac6d454be147f6bd10804ba4fed02b45132a2a197e1c028957ce4230cc663a1f469953490a1b83ffaaba7fddfa110e2a943d743aef", "TP2": "041608709fc13c47614219bec0b254ce3c93ed21fa7219e9a21368e4653b840a8e1da6cad809b0326c806a1351ea3bccf045c809aa32a09a52af6fc958c88e2ae3", "TP1": "041e35948e9936b4ad0af9d4e2cd64bd8bf3665af5791e583e8dbc7c6a5028c2c402e567ba3c877e6d578e01a148833416e43ef7e7039f12e34366fefe1c9f015b", "CS1": "04198d77a0081ec86277b2c424124dfb31633ed83432c13d70b59397d5168d11df13d243e46cdcba1c84405c2ca4e220e18b1c36b6c1706117f1ea20e86c81d9c1", "CS2": "04149a55b3215e436a4bf501e987decd20b209e8bccf6502ab5d0e90fd67ece8d3221e9503a10918e7069817b6b9344fadcb22a23aa22306f4f611a0d25712544b", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "0405dc88512ffef7d86d6d0a23957bcd6d0e4d2bb01c3ec7f725b612be9b70129503765be557df6b231b3677b53ed4aaac0d8d2e1dc31644c003dff2a51c14b8d6", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0413a8ec4df142260627e57b7996378b0d68968d8ff76219f1d69aee30d163723c195c8e0b76d1a7d42091a8d88bbf1f675fbee430aa5b42dcae84f4fae892c961", "U": "0418a9fcf043161311f8c610624517d8070c9d9353cead51d65a3ac5f85f5d471a1b8be8ff787ed3cc020c7d7ecf5ac33e25f778afa62bb957541c261c16160d28", "SERVER_OUTPUT": 0, "V": "040e41641a2ac523d4e941b0c32ccdfb3cd60f2d7e3e342051b53baafa74f1e1f70249a7f1560eb3d3149e3327f244122fc7ebad842d796deb92ad212b63990957", "Y": "12b4cdc3f2781859dc67424945d45ebc3dbad7c094319e7da77e1a2671c5d4df", "X": "055c7050b735c3182b06b6b9e5a2d2d5c6bf17d5f7e910fbc41d52ebbd49c857", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 212, "UT": "04219dc129e45408549e8b6d5497efd3fccb0a0a95ef37ba57ea855576677217ee04cc8ff1c2c0eb3616a2526e57b3c6c176f3ff618476ade5bbb6106aff3d9f01", "MS2": "1f925d4cb81bf97148e10c39b76b7c51f042e7148ac9b602e12efd0fd9d6d176", "MS1": "02bea1c48ecc73916811e65eb3f567ac117aea340180306e36b47a4c86c19b28", "CLIENT_SECRET": "04153a5a3fe9ae83b14e4c33db264a5a28daa2191d51ef80e0dce4e00b4cba3b4a0b54b639784ca2068328de9818839a3202e9b3fbf7a611807fffbfeca26805e3"}, {"SS1": "20886af066b82aabcd2f3428bfbd8fcd6f70f9ef5efcdf54fe186bc89ab45cc31ebb889763af68a3a577d65cb4f6a1aecda13328283049785eb7e0e405a71d86131d2d59877f8745b3d4104f9f5a6e2308f974df5f7c559391bb0634e95320c01f3ffd185f330a7567de91cbdb3f9f2b89b319eeb5de75d91073f4b79074f475", "SS2": "14acfade1b6d7bed5b577ea8c73d3a0b9e9992c9ef03451445ed8eea13b8bf7707888c0f83d5fdd5b1ee7724375479fe6148d33ff1dcdf138bee46ba1493c17f0133429fac3fe924b05a825c8ba29d20808526f0b7bba5cbf6c063a821a6c72f0caba14aa2476935ea22478000324b9658042c57359be7f17c61e78595811174", "DATE": 16587, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0ce955470abd598ae5e5a7fca82ec6f3cfedbfcaacedc85aa536d814eacd35330f0f21268b19ec5c3f678890fe4aa99bff677ab07dcd4446deaa4ae857d374e220012f9e1f4f362720a83b1417eb2f6bba16612ce5c88bf9a443c984a976a1bf1cc2a99a5d91a4e258efb79de2389a4781a8135d571335158231944fc52f0eef", "SEC": "040cdf96320df72db60555fef85362e7d1c62e21d58b2e547f6eec9dd4f96d09ca0eafc8095de6105f617fa18fd0343f40d48cf6677a599c52d4b9c03e0ef14acf", "TP2": "041f2d7c929abbc4f42636baf99bc596228d6124529c71f6f9ce7fb1cdf9d3cef822f96c3ef9a1a9128aeec9dba430fd39c53e237423320121994408f46cb64f8f", "TP1": "04073a8b68bd65b3a940ccedeeedade8f2dc96b85ed866c1cd2f03b3a9667ce5a7092ac15a0e2ad8f950f999a051ecc5c0c08192e73cea2aec4b77c2b4a3df475d", "CS1": "042228d0363fc360931a90eaf60e40f325e0f4ad3911d63c5e54cadc658bf1aa120408502a927b9d449a68db482bcfa70c55b712fcd020f3c6d22117a5b8e53b44", "CS2": "0419b335a45b2a37ce2e3ef6ff0abf24742f444d7f97f207d451920c186d448462152642be94c099409cb4f8afecde4fa276630c3d6535c28c288cb2d9d50b2514", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041ee7474bbfb71ea3d9509c3b64727dc7113de2f8edbfabc407cdbd964f5783bd0199a63b0186267347f83d5659a405daf3922abe7d3d633d66e4540d7cbe6212", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "040179f550e43b8cbddc3495d07e44ddedc850364f1274b98bddc0454f75a2832523d48258d16ec6c8d3bc4fd781a0da385386bfff2cd0bee2ff9f198a95443063", "U": "041f6b6da34af6330921e1357b307ad6d17cb7762e0c00f1466a1c552a3927a70000f8c0ea59c334604d228eda695787a7b4a58543e2bb583d4f1a906356d49e8d", "SERVER_OUTPUT": 0, "V": "0406a8c357d8f18cbd2b74f9a77a007efc70953eb056ff9af09ddd239950a5083b001a2b28fc5756bb63ac11d4c7b928f7bf46c61afe1c3e2743984b1367259623", "Y": "05944b67556284b4fd8eaecfd8fad5de5fdfcefc0dc205c1ec83b55c8ed87861", "X": "00d4e78b7b9373430888be162af4d02b648e1d9627a8e7d59559310a2a73ef55", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 213, "UT": "04200da514bc73c2559e17bc631d3bbb954a9a9576eb7f54b9dd802bc8b3e388c00b8c29b25de2069bd1e28b5546552c1e8177f95bc3505a166b7df8883b3366a0", "MS2": "04eb8146027bd99a00a538672a51a593cb8c9882b309db59343309201acd4a3f", "MS1": "0ad97a89b3e270daade22b7ecfc42ab249153bb234f5a71cf453d91d1ee27ec2", "CLIENT_SECRET": "040b25ec60093cdb2efdeec350ea60143d2e8f53d8e0a292c3204d5815d2238cf8142f91054948f3d4ff6c51cc6ac2a6cbd6ca348ae1fe1674c6c671f300c7d8ab"}, {"SS1": "1a4826fc03e488286a4c67eb5166262f75761ea693c3465a63952004ddd7a6c706b5c60040887bed87a8eeef20700c6bd29758d6652177ef5b217bf2be0346cb05b0f344937896620cd5f38fb10256d9e3314884fd6bc429be4227c75c0ce78013587428dd2ccd9ae122f8f315ee96e29165a116e84e4eac4a7673c0c748301b", "SS2": "13c15214c18fb3111e3e72218172b7bd8ee4c4d2268df71f3d27b693829d7a7702ad00a8c42abacbe2f1f861322a0a9b34a53c82dae7463aa57e19b500b8917a0866aa94df11202afc3dae437b9bfa727691f82778e465444328062daf987e0112359d75d85e822a00792156ae0a15d0f4196430e9ef52e12be005c9fa0e605f", "DATE": 16588, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "00999b7ebdfa734ed659c8ad09ce5f3fce18f853f422ab65f5c728d877b37e9b13280bd0f21fd15706fb77e0b354ada81cbbffce1ab792f24d7cd1453922559320f88922cbb37ef26011222529367b4afc79414ea8c85d07b4f4bb911945cea30b910fb81b2676264a8c3c0c9012a1e7df58739aa4040648e890173af42c74fa", "SEC": "040f894aa55f6860352d42f899acb644fafdd3b799e51ca7ef9008d717f4482d4119185a4aab6de7c9c87155e32b6907d2ea2d6a691aca1611fcedd8501b10261b", "TP2": "04195b1fa1478295ec1ab5e0bbdbaedf2cd5ef670a380d918f195df014bef249040f523560226d1f28a60c695dc53f283da810cacace0492ba7b3473d3863697df", "TP1": "041d545c8409efcaa2e185d9ea7b19cb7dacb2772d13c707119611c7d7680560f317453758dc4c2e4a36ce87592be098bd62ae88ea87535d95058403abfebb0800", "CS1": "040c39eec5cb0c73083ad2e81d143fd7f28ab9b33a2b96c2d856e3654470b4571d162c1254b144c442b11a09cb31fa5a7294e0affcae3ae7a2ebda9154f4786db1", "CS2": "04233ca184a0f8c2374cb987d52c37e272c0d3a615cfc2932bff1a6ce836e71d69061c46bda42e860bcab25a8609a6c49edeaffd841707635baa324d1b5c75106d", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040cd442800fee834dd3bd0fffd8cc98beb6e48f94710ec7cc913ad9abf2317f420c1b18a7bb7ce7c06577dd49d262fdb5273563859d0c40c48521752f13ad7660", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "040099e3f3483c91531cc67b21394e8283d71cd82f884a69f2b1c664b85641bcb6174fb6364ccfb2568dfcbf9c463fc13f230960a7cc28b328458c7be911ddd789", "U": "0406cdbbf5e20d325f5e0b3fa90dfc07137ad3aff574f9d26f2501f8ea3c48df2e1523386c49265343a17748cee360d63f63c9a460e3af3e380110eed8eceae3c8", "SERVER_OUTPUT": 0, "V": "041c9b82def833264fba4a4f7152eb178815e5fe8b7f334095f83effd18d0ab32702220da45551b22013b22c2120e67bc2c3616c7e7cfc9d34c4878e31200d0b28", "Y": "228b34002502c5d692c40d9ee046f062dbb9dd6a7c5f7a692c93f4e2689d0a25", "X": "0b172aab887aceec935bc7ae4124785edc849d9500826fc15870076dbede4ca8", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 214, "UT": "0419a64cc11e036978603d0ff2f5544841ac60b9664d008589c750ffe8e7e995cb0453f88dcc59cb0f3136e3992de5321a62f755aa3d6d911cbec889592be9e516", "MS2": "07b841b46a8724bae78fed54a42e470f4bc654354abfbccd411a077071c7e74b", "MS1": "0fed8bdfae7b5ab136ef72e23934b7134e79e299ba545602673cf2d4c0db3214", "CLIENT_SECRET": "041399b5467c0a9a29de498c3a888ec195c4ec627c668c22d64e5d72751b3071d521446d80a4f0aab821ef80400e980982ca31db6450d9feccbff69cc8dd3dbd74"}, {"SS1": "11808609f12372a395669d8e2792c5c473910364736ee2311ee38fbb59a7cbc810a4d21fb9d6c0921c0e7ab1425788857589d6d2b828f1e1c957ef908075cb220addc8f4376ce0db2c0851c00570288261212cb4fc6a240c85e268c8d96587d014fed3ffd92fc093640700ed36a3608780f893047866c4471a095999278afd9c", "SS2": "1ddd9adf762c7fad8215940eb0d20f3c94b2bab92c5c17a308d4b24c1de9bdeb1e1f5357e31fcacdcde061b3e1a625968b8960e23aeae96a68bba2559e4fa08605d17ecdcd5a1d8f4b2fd70e5f2fe3a8dbba1ec47c8a34fdbe78f6e6311c623310563c9e783348e5a902ae5a88cdc4b50f7017d1bdb51f9d3cf4e5ddf952fede", "DATE": 16589, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0950d1af79d12380b36e0c2554c94124ac58423a509956910bcb69539895670e21fff8d42db3a50790b72d38afe16a7b400997328238c573ec70ecce94b846f913b7f56fee8c1238b1c461c9c2465ef7e93f86424e8fa27c685631d806640b300ffeac55eb21c10433bc2c86dc86b1a734b82b83459f949c89fa4994cb3e67f3", "SEC": "0417d1d5de4aa2f64c2a88f9edac7020686153b8bcc0e9089013669e305ff6a36e23910b27ca004a25bb509166fde00e5efebce52f7de3e2d26141d91ba5c4c3b2", "TP2": "0422c5467967572e6e2e4fe4230b6f04c1fa611c469a90d13e8515ac229fc6059500e1ccdf8e5eb222e3c1d61b649b243599e32a7c4dea4733cf57f3413323e335", "TP1": "0404456c9805c34ac08c94736809bdf2c5bdb0dd2d9e46a91ffa706db629bde2e6195642d5af6c3b7464548deb9a58e02515a3c4a8e28d04f110de9781d31db1e6", "CS1": "041f26060deb8ac72d4496dd227dbbcc211442523280161b45650d775503982c8d0d5355339a79fb2f964fd9b22723032cc10baca18bcc0722071a0e23b0e7a16f", "CS2": "0421be0838570ab258e470cc696d7b22a24bee1502a7e01d2a96777817a5128e4b2200e6e7d8fda239011fe94de2bf9a6615a30f7b01cc8f412701ca9344e3fef9", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040080075a4a17d37fb0368e8774bffb9719f0108bdac51b269994b9fa3bf40bb00d038dc12f486972941c0d2439f3bd3d316027c446566d6bedb3cc490166fff9", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "041b07943e162a87397b1a0bba4208848e25ac387337ffa2253b73924ee061c8011c500cc16c78d0817c630b5913abdc732c7f45103cf56b97d078fbb1a4103d53", "U": "041fa5c86f5a7fcd7dab6e985406445f251b562c0e63548b54af6a1e251a86b4141b18f9cae3c85e8b20f0878529c262c768a70cc93e9a9ca85cf4157c9bdc1b95", "SERVER_OUTPUT": 0, "V": "0400a87ee4cb4570996218bb4462b0ac3fbbe6bcfb870f58050db23b5d857909e01c130337327688d173fec3f3a54006b88a09b76cba21c6b5be00412708abe92b", "Y": "213832698ce469bf5e62438511fdf849ecb70278952b85d0ee5ba52770c857e6", "X": "0d8f640fbee3e7a6b7dc10c53094ee031e8074a0e61f29ad24b2af1c0a1e698f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 215, "UT": "0416950f50ddc7a850323e673741f1fac7cd03106701d3dd4f630b95692f8c5fdb07d571fa6731c47a9f4da54c75714b4499ae15ce2dd1ad7cafaed6cf8492226f", "MS2": "2180e5c7362ab5b861e3e4874548ea676669f6296b0970189857a5fa670b4dec", "MS1": "1b4207aa31dfadcacf89774c75072b974111b5a24293d633b70caef4d52b2a91", "CLIENT_SECRET": "0410983ea485d7bf99b1c7b395fb4db9cdc1c442679d7d91388b6a90d27dae36621b37b6c4466082bd6b6f99151947b07ff11195e5b7eafcae798b6871259082dd"}, {"SS1": "013cbe2b392281208f7bd132148374ae2e2633232bf6b7c3685bcf83ecac9ae31e0e0d8f76c03530195682a045d924d1475cc37e87e5ceca92a75c9577e12c02132a8aa327b1af6642c31f319473c37d15d0ddc2715085b38388c4be24ec6cae073b860e4339b759fbc3e87a1cdb3413a00276cb9abb91e835f39c0c3d7322b0", "SS2": "1555e5a9709d5793a856b601f4e52e1a21c20f27cb206f2006f0e1fa6329a49e2242debb66827c6f39c09e9952cf914b01ea7f3c2e49ebe7fa7f8c36166c122f1db888a84eccf5363ff36cb6d1ebef5b6e80ce597258dc9e9d67594ba6fcef1c21f7d693edbd7c9c24e3bc213ed37a306252ea65c2e42a23c59b580c8ebf6816", "DATE": 16590, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "171f790b0daf9dcccafc5d358a3b7e987b061b61b51573b96dc88d46ccac091e1c38c94f214414741cf99cb39ff357cc44d68e0ec7bf697bc83cfc3a0c4ad82e0840681b46c5a03b7d3b30ee8bac463042a9caf2e9d4bf0c8d821519bf47588b23e9450d8b9bab1032df4c17de2f10b78166ef82e01ac68665e43e0ba9f58067", "SEC": "041ae8396606f4be9c94380ba7da75a228db8731b9434e3a14bdede4fbc29cc6d31ddaffc0e93f66fc5d6f101460a0f0c2ff03fdaec08215cfcb3ea78b74b10d3d", "TP2": "0421948cb93e0efe0383d5ed1ffa3a31d4dabd0771c9328c24247e15ec0fb0c221059b32bc1bec06934f4fefa962900f794f72dce53115c1a4472cee3d66cd68a8", "TP1": "04179d04e17cc069c1155e622c7edb66726d3edab52027c34464c90264f6fc47ff165ff121a809bd945959f384f653c416d96d632b18b08efdaad4e5bc12bf6960", "CS1": "040048f729f262e5d59c06aa446b181ffdb4411c5f28b8afd8f2a0e2e83ecaef73175f7f3e16ae1ead1d886ba191d751917a933b3a4c946f2ad80632d5e08e5fb5", "CS2": "041b9269109ce557a187e4f744afc01496139c79d46df957f918f447aaaf0aab5b1c34a20030135a3f873822f42ce0f1bbec15ab96cbd73a04a0aa390e529195ad", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04008f0d5f44e57026d272dbd34771086898bbc848b3184a6d971f6b35072c643f134cd3d49fad87d833b3ce9565a9f2bb4ff3119c67e0cf9a7dd91373fd690441", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "040c601fe7d7d83bde49a7c957fe35d0d5ebb81320b90cced4e90a57422eff389c1f59c4de38bc9029b2e8e419e72c871e3eb377d61e0d003bcc5a88ec757f4a6b", "U": "040cdbc8b53a217500cef95b024d66171d754a15d8edaee6bcf236807590d47ab32104f969e2e1ca776e977a40c04724b9119c2c864d4119e0fc7672a63013ef92", "SERVER_OUTPUT": 0, "V": "0422fc2b13612962e28c3da8eb0b6474c4fa6a6229475f991c426a3b204cb2de491fe445496ed5e56f6875f115329fd79f36a69fbdd5cd91ff95a2640529720fe9", "Y": "108600f89d8bbc4fa4df7a6bf6a5360c1904fd9464bb96153c949bbae2b04d7d", "X": "176436a4b9637dd194841aafff5cf6b732dc5b3bc717b12ae3397fbc1a1672b6", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 216, "UT": "0414868ae4bacc54c0cb9ae12704f54c89e28fb74a52913bf83582286df02de98f13b0666ec74b1d0964ce709b1593718516452c223f39def457a553f483bbdaba", "MS2": "1e9de368d3e221b1c300b1113207bf8123163a2565f421868a65eff7489d4417", "MS1": "17ed07c9642819f5f8883a3ea2f2a56e96d1ce614c3977c8912d72cdb545d834", "CLIENT_SECRET": "0413d37a9c18e789d462bfc38b0814c45a947f3576125e82c18505c426788e6fd40221fc2f1993fb36f1562f39146ebe7145b2577ffd00914af44bc2c311dda111"}, {"SS1": "18b23f43b620d9c2e572577a379607dd6f1116593023828733e96699c56546f5143e508fa047823243ad5f993fb85ac7399248f754cbc6de0fa022daa3f17f112021f78f59fb3e546f5a4ec78840eb72c4a26e6573f543b0fdc3fe87875b441a186a954cc4a974643bddf7cf3a4d8c5463fc30ff265b5e660512e706b63b7d28", "SS2": "0015a159457939d64619a910b89aaee8e6a4dc2f15fe034b4f92153fe04708350fda5adb95189e86a28a278f01742471d6ace0d3704e1ea561bcf1e1692aface111eb2f40d67726dc56b4c5640a420f72daf0156eafb753d83b47feef518d157137f47caee50d226236b8736cbb755a45ee8e12d1e10481a569a7a2d4cd320c3", "DATE": 16591, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "11aa06e2b392079e78e63ca9615ce1a76d69da0f7f056a45e4e15f2972e001e10b9dd6060110da3392942bb8366077e5518cff65ab8bf8ec0ca16984aeff0e0e17cd9c0b0448cb0633d7b3bfedf1cdbd655c2a89dcfe232b9519392dc76ce75908d84c45ccdf75656f02da70f603aaa396e8f7f13523917f14fa30bd0e33ae7b", "SEC": "0419a14800d2f8f24ac02ac208694c145555c1e406f4bfbe3292a7bfed73a526b20a1493a36dc1b77e54a1ffdd3ee53ac7bd9929ac5ef1e7a1e8156a738f7e53b9", "TP2": "0410a807da6ce2c707b7fe56ed0a3c8622f41fd86c1c030adc57f126a17fc692220755ee3fdfb7451eda0b3c628e0a1753544509d6ae949c44ec8f2848e15bc783", "TP1": "0411501bdf13d6f3d720e0e96bca24a1febf7552f2cf815d314105e9f04a4903bb23944cf03671d7ade2047fb1cab0fa5ad2e065ca309a7053691dfc4d046b4cb5", "CS1": "04160e289cc19981b3c611b35326ec66aac10a4685738e492e24d0b5e5b766fa3803b44382120acc61a2e70e5f34cf930335423f61e48b3d48a7f15e9a5bfc4171", "CS2": "040cb10c31814ed4eb1626bb9a0a9be4a27f33a52137243fa7862f01ce53c9613914523afebc00da8831e42a233e5ae1b479694f8c963ef27d84805f9ddda33b9b", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040c6b09f76cea6122e6da5bfd3b75b877a8bfe8997d633919463ba2c909a3de350bf34532ae4051ada29b652193af238c759c1ff68a9861471535f9f67ab8565b", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "042169c19242fa0667e18be8d8e846a513aa7d11b2bd42f6ceb34ccd0ab3b5470c09c237f41d0137b5fb682884392dc2998ce89452fad42973e04fd755624cb8e5", "U": "0415f44818fa2a336c547344efa9f562aee9af8ea3921d8f6aec17a9643f46f7dd1070bccf88bb2e1611e492fe5859685f82ca2db2e32aa615c9efce16a548474e", "SERVER_OUTPUT": 0, "V": "04104b17957f74450fa2dfebb6ac8507d4af076d9e9e5c277734e9dfece629d3900909c7863546d59a3cec4dbe493a1c3af5c042a805f9e9f071ffad445f165dc8", "Y": "028d0da97c19221727d534e7301d5968157f204da336e8a690697b89a3b42f60", "X": "1815740afac59b6e823a04aaa3f41ae536ca3a709545a1df7e8558e7977115ca", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 217, "UT": "04028c48754feb8ecdbf3fb659e38246724e5fed2156df199a61fcad8fa6f892aa08236eea707346189e2ef5aad77cbdf5243db80187e4eaaa867ccd2a00dce114", "MS2": "1dfa7ec1d5481ff1cbc6d82c8162df70631664da7c522178cac881a99201a903", "MS1": "23f7b9b594a727c63d1c0445cc4c3fa53506c701db8c9811fcabd2bd75c61d84", "CLIENT_SECRET": "0404912624b5a7e1809332e8c033eaebc5e157aaf94a80f7a40582864261a30ffd16d5fdb01176eb946aad4dda0991bcb9c3ed11b30217b7e7706bca1af8b83c74"}, {"SS1": "150c32a5a03b863bc6f082c5050cad2fcc480b91c67677dd8594a2f81db900b4009d026f4ee37a31b69a2a28942cb1c71da127885af833c2310af182ffb7edca1b680964f499bbb55912b54aba776ccfca5bfb35ea400f701abfb47ad25e99f80cff71ae63ac6e28a7fb0db20f06275a04402228cd6eae8208dc0587b4a95029", "SS2": "16507ba35be6ba2fb0eb52ad12e3bbaebd959208e562dff70da6da9f732e0997081da8d23b6382621e77f9709996f33129db8df56f7216b9bd7f47cfbd869481126992102868d5564e8efab65493c89c27af4283d5904663e5f7f118d1caae8311e711d77ad61f68675fc629fa4c2d93f131091cbbee2811b0fb6635a5f8e5d4", "DATE": 16592, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1c65095fec23ffa39420bf0bdfdbaf749d72440d9f16f0fc8c31dc42b580bdc90bea323bd17e17e9ce0307b394f94068e3ebcd66e7a34b4456726a298e51ba181d539dce912c9d8c45894df3014af556f1889326b6e916433cdfb1d5c5801865115f184d3422df0032c1e69d49e6d1b4c61fe322382f47db112c225ee523cb86", "SEC": "040e4dd7539a02726c14d043223d20eb6705cccc99b3bbbee4d84f092d8f350d4b1652a039ca5f5f26d9604836ac9a08e5724357ccbbb1a4c191c4fa16ed05db17", "TP2": "040883129b6717d37d301302689bc25e757c06175263b9fde54780acdeb907f24f18dc015a41c072e41a74e92b2daecaeb26c6c025cfd1a8047e7c1b0cbb94831e", "TP1": "040fe3e93da022fafca0c22ef96e15f389f1aa7b4365ec8377dd291ec35641703e11b80af318425c9b437ecfe5895ccf0c0252629a227e3f7a241e1144532f5e84", "CS1": "04086dc06a281902c92e7e959986eccad430de7aa18c5502dcca575a021bb939b405d412c82722752079558444a6f5682c1eeb0c1c15781df816cbb6aa54f0f86e", "CS2": "04158017a469003195856ab23304504ae2f1ad2df9560f060f476a4084230428151fe35ef3812ca121e64e21f7cd1aea1dfa777833b3672c902efeab92130c2fb8", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04226859407d440d67a8032db723876c822f2dbf246689e7cc3cff8a9fb35e8018053992defccfd35d72b64facfeb55c2a819cc6871f28ebc323d041a2773fab82", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0405f51d3728e68c3a739eafa43d7b5c09ea4371c49f4e468427d4ff99acc76719097f1e43706de291f54a5f80cf97e247844e923185670f8348c9178d5489464a", "U": "04104e0ce79b5d4bcd8e45d01940b5a4e7c422aaeef74b21f8c75090cdedc18c0c2052e905fec75590cfb79d21cd35c9b25a9475daf9eb85b0dacfddbecb4271de", "SERVER_OUTPUT": 0, "V": "0423156ac51366a1309299d6b49dbb1be1db56196bdd687f0843bff21c10444e2700163612dd5519826902f501b9591085db434c06686bb174462d02b6c3809050", "Y": "096c2d76e5b1202ce5a4a1f989bea4cf632b30b03c612fb395e949819867a8b6", "X": "1090c966fbf1c91e33c8bd228d15eaafd036b60a4cfbcc6daa87a4abd2aa4779", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 218, "UT": "041f66a0ff2095b1d7b8f082995a9e523a522e95cd37a7f6f35f7e4ce69165ca5b232855d14272f537bcaf920e73648c18798c7a43dea63c25aa22106a049e6c8f", "MS2": "1236ce4a3fa70ae08d16602c4b79d638f6ccc272fe79c3c627631039f83f5f25", "MS1": "02f9b390ce28e464f04932c995b6cdf20873f70314168164141645671e0df017", "CLIENT_SECRET": "040c66cb8e0498b5b886c5dedf49c1db4b40c073f532e32bfb3d58bda78cc2b1b91fbbd363e69828f8fe9a9e658b2ae461a609ae65b9f0202cc1d4ee375a5988e9"}, {"SS1": "229513b7d6ac0af7a42e3ad393da88dbac95a7f7542694134c558f674200439b1af6b6421e33a19ad97cba3800d31ffc2371e115e477671639eabf818ca308ae1761c128c834365553802a5a302122e662446db36de74827d03f48550cb9cc680e953c5f92c75b4d0559b08f463b7fa24417efe9251fb1f30ba897b85119a34f", "SS2": "036b845c5a6d3a24bf2e2a8643e5675e741b672f22f9eb679264b5c649aaf66016a15a04edcf167e8d11a24ec28537b24992604c8eedc664b901fb277a00d689161b2894f136bd180ee19ba789b817b691db1672da6b50886c1defc5c121a8a51a8e31b9b678c54177d81d90e14c49d862a8cfeb909eea2b16798eb3c7355d02", "DATE": 16593, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "07c001bf7045b08dd0d68c036b10d9215263b959618dd80260f70aeb5dfef947061b63826860be1fa7e48d42ed1e81ae485e0cd347c9aae0a4accaed618d664f0e4e7fe761676be1d84c11c7bc56f635aab043570933135baccdc11625bbaf6b11026b47f8d1f849c68d76681c2f669d85afe0aa287d1019f6a6d17d6aada00c", "SEC": "04027f916b0d14a5fe15a59cbd47d5c99737fb9115efd23f29a9c0d1f0b0458bb10e2dacb24dc7c04479eed542bdd0022e94e82c29d58053214d9b8191e3c1ba77", "TP2": "041b391888c6232f23d66b7bc84324e13a9e566a6989010e99aeab9f53e8b71d311a9bd33a331f2e810878c7f4889a85e08d7dafdd2991049feffd513ae86b6de3", "TP1": "041b484b145efdc3d8a6838cbb2278c020c1b766a16bf41772b12a79e240d50ecb0cb65e49235b69522e83bc9205e2e6a414e1c2aa6843239f2c68ffb4eece942b", "CS1": "04119eaf7bf4fe9ec3c41ba16bf27ef016eb34d91c47f3274cfaaafe35acc6d1e81a6323385ef69722c0372a3b02fc02385c237edc8f77a13f392b3c0a2bc82410", "CS2": "042087086892b12bb0344891d94085797640db9a08b2523f77fe1f7b0ac9b9999120a263b7cc90c6a4a7b2b91d2cb18a56537be166c22cbd9c8f424102d08adc5e", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040fa9db0d099030fd8caa5d0cb5ee2de4f041187d958b60af0b98b8a23c49c8dd022584b0a946aba8b4b32ce4cbfd13e0c97d3608081993275baffade6b1b7416", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "040597900e9bc7514c5e7e34e8ea43aaf521b939178b7e7c610de3762c4410cb5c0a430d3b712bc523e7590ca9a1dfb25ac1d54a0f5398058e4cc3fc89288b6571", "U": "041a1d2f5b0d44db56a5583e71d1e2998e4d063da6d12434686cc2fc2ee3cc057d16570f275fc306f75769f134e1fc9107e2f61f9d9d79d26fe6dccef98cb4540e", "SERVER_OUTPUT": 0, "V": "04235fd92b1d0b3c763db04baac97f20893787a486c0451fc34dab3bd900133e14212afd671486e77787f6ce123f25ef7e188ebd65b4092ed706412bccb109a96d", "Y": "0ff3e1594e9bf2138b401abcc8fa93892c7a08610f02dd87703d874c35aaccd5", "X": "1324fdc2c6acc9901dde749123497eb2905b2aa9c334005fbf3026355cf23862", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 219, "UT": "041d94c9c54e53da0bc925c09cc6d1b1c2159691daca21bb8033081ec123e03e941e0b5ead2eb98b4a3a48bb44f927419efd48b555b464fdb4b2389bf493b87efd", "MS2": "1d253cafd050e4b955011d70dd06ea313994b3154ca427c4cb5f0ff365a0b9a7", "MS1": "111ae854c93be18a04172b9eb5e929d580273d590cd4144005cf4318434140bc", "CLIENT_SECRET": "0412b71da332dfc8a86f23ef0a5b1dd31be88aeaeb4b5a753a0aa1bc1532ece6ee1fefb4c2bd911f8cc8fc0c70bbc32c6f071d958edcd9e4b765078ac01d00d1a7"}, {"SS1": "10d2cd0e0da36bf32ec54eadc15cda99f87403e2f92e4acbd69d536c8dd320f10c09aa785de571206f0b95168d331b1037eac1802fce278d40a775f9f01308af05e0eaf64dc056ab11d141fea918c5215773a94708c02ea0e9873101556e333a2396c5de2847971a719727e9ac1742877ab117f90e20e1c658331dca1ceb8da4", "SS2": "0687d13c8b6646b8d7ee2dba33a857f5fc3df7566b4f0ad15aa1538ff8523ace1299396d0689f6746bae5ebb0c0fbf8db1195436944e1f583b03ed69c6fea6c6022367dec8cbde8faab9086aab65f448ac5930683afbbcc1aeba9b6c71fd2a2917551cb72500b8e85508afc2049218459abf938d14efde62b80584924822cc64", "DATE": 16594, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1de7b3074e1828898756648d9d580317f0fc666348d087631a1abc3c01bd71ad11364b1f771c9ca94166f900b7b13ecb3b28fc73d2e0a4c6e4eee6929bdb22580df4992747f144c6df2f26b277952784f0360e6090ad0438c566f85a85999df01f99d246ab6afc12554271e9ab0e633d99c9d8541552c023bab5a5d0d2000330", "SEC": "0419a4172856bea7f6c47269badb04783911721876b541eb798546ff3c5bcbb7321fe203e7a274c399f798892216f83b3975733eb27ce664cafecaa99e91344e80", "TP2": "04188fe27eb89a6ee8561c36e6496688317476c21d803e92b6a9eded295989bd9f0baccac37088aa5144e710aa2e314fced1dfb26ef0796d1cf5d8815c92cfe14f", "TP1": "041dcb093711272f2b654f66495fd499853b7a50fa7ebca175829f717a4a36a3211f620de177626393e96b717722e2922dcd3be953c7d90abea2996cff53bdefa3", "CS1": "040fe7ba80e8e92a3ee7c5166051e9d00fe6b40dccf73823b60ed8672f86dcdc85196fac3bbf26647ccf158dd21de489a36e0cb1d35ec65253ef94d679668f1b3d", "CS2": "04147b2639913196bc84f72fda36906cc2ecb8953ed9dda7ee6110da77518b0cfc08783d47d7d3dfea5ce9f903be1e1c576c5bf86296a707b2fd148018384a1de7", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "0402c37d9de36d2f305aebed340ee14c82080bd05ee64e25f3947c59bf0f75df2014254825246644f44c2382ca7218af6195d6e4416f557939836d6e9ee4c0c0c9", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "04124846e9e22563baa42770d05ca035d67de1c156fc23c13743a710840c48f9dd232ccc99fee96f436cd9a8935c7a8e7f4756534896094a818b34a524aadd212d", "U": "041e09981d1715b942f65b59ed8e3bad64d01e38269aa5c2b5960e9a35e047843006053763b1d8843ba4bb27b472103bc058ff5cb77a6bc03f13561bf36339c433", "SERVER_OUTPUT": 0, "V": "040547b265f677caecd84c686cb8087aeefbe1cac654e86a352f24d3af7bc506200f3583244a0b0df9e8a9ac9bc9c4148d6b7bd04dc58d9024c577278b99102cdb", "Y": "1fa1a65aa797a058a000c531505a3db87132dada69276f1a98ace80c4b7bb560", "X": "193dba3040f1eb3b2e786901835a4f8a38d84773b328e10d0e09d00a04ab677a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 220, "UT": "040aaf0c599c04b1ad3e949a351a699a62503eea388c1eb73ae0ea3fe321394db90c7e83818062c50f454467f57dc3cb845d269e5c33e770d65c29e29ddb7d60db", "MS2": "02939c4162e90054b972ce7d726ec3dbb89e15398a4df093cb078b12f3058e62", "MS1": "10c88fbf0f7b12e871fbdcf7a1ebaee235caf9817f946cf41a0a1f3158252d68", "CLIENT_SECRET": "041d6000d5adeb00b8528eb7edaf36403ff08732738e065214eec6e40717249fb523447e6e52120f774f5fd3d72c13b4b259a23a5fac729eb2c22bd0939c2d2eff"}, {"SS1": "14cd6fb9fc2ce4c55356d10ad5e5f64635574b358fcf7cad14c3d03142a9b9990bec85f70985aefe563aedaae011fc7b8285f21dd91a22e2605be9d9b9a120301100dc15c3a3ccc0c11b31964ebf5031c07df461ffba89db1bb949631d0e96ea21388d9f5615f2c1ba35eb12b5ea5ca22beaf069420299ea31ade3ed39a16676", "SS2": "0fa90fd619dce7b6c4fb87c30067089a207212e53ac353edc33c790aecf30be71dc95f3978eb86226c5769d713a1a6dddf4cc79750f073151e60a283ab39f3c41f14805354e250bf47c5bceab0e8311fe5d84840e9a3f077bc70d3aef28b9d110435d171d442c44f1955426aaecac5def1f32ad9533674c46cc4e52fa9b03dbd", "DATE": 16595, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "07bad817664bd82f8aa263b7b0dbb757062778d24827d4942ac29ed0603e091a0533f12ac69cd2a5cd78ebdf89524f10176645c993945ef3c56983b2c63b556e13c47fd7f32950002974013179b285af67a8b5ae0bd3f40daea5fb121e164917058826ba121771161e6f958da3ff145b6e2b46fb91390b2fe750cc71f08e5009", "SEC": "040554b4780eac63cdda6adf1058015aa936024ed1277aa023941f6b01d55b0fbd106c60b8f57e148d0262b7c5c739c392a8a37974e89f7032cc39df0e0c12a84e", "TP2": "041484bb0e0b8f3646708411b1c02afba7d27f296fbef16ecf1f04429025d242f523e42c9ee25d314ac32730a917c8eb45aaab47df091584e4b2a9b6af3034a48e", "TP1": "04040e443a88c902d42f2df1f06b4c99a83e23c3c94a9ed0dcd46ed756115049b80bc7d5be2fa61e65a588d3c0654ed12458ac61a670b7be54b9f3351f962e3bfc", "CS1": "041a467dcbba8b81602d92e03450bb6086d09e00168d34d762e5d5554256d2c819238044d97bcb9110374c562af3e5f3be1aff2ee80375396511f695fd787d8fd3", "CS2": "0410d19ea86d863979c3ab83fc70caeb67c4a1abe9a314beaa7f29d9dfd4f384c00aa310c751c40d97583be96c810d7aff3f7a06d855cde67d79944d150340af8c", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040bdfcd9559c130de8cbe14775b3dc38d6cbdb3a538332d5aefbc0cfd1b7412e20e458ee97cebae20eef50263ae8ebac6ba232831dff44a73c82d7c7f5521ec55", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "040ba049bebc604ef0c6c1b3ded5daa79741361b41f6ff01fdbf8975bf6c6ea1531348694577c215df5ecfea66955ae8d3a0f048ef8eac5004317750022cdf2d98", "U": "04034e5963c5adc1a5f6d4138532d6774c83642870ff7e0d831d0e40df55dfd9fb0ecfca67850cfb5017a04bf6dfa5568ae837cfdff2643aafb9d5c267bca6320c", "SERVER_OUTPUT": 0, "V": "040d9b211db2069d67260a411feb23cd8821d0fb8a6054fbc8a10cff407ed47b9111fbcb614ce73753beb5cc4bdbd8582990c42845075730df7ed60bd779f585f5", "Y": "07f77ca18e3f905b0cafb953f66c68b476aff4915532d027c9914ef7fb053327", "X": "082b71737ca18b4aa440d8be39903ab969e4182f940d1b62f5f9251462ab85d6", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 221, "UT": "04217c6b0e4f95687b5ff77fb10d78cd70053fc79b33dac435952dfd127c40f6df0b037016a27c7fa327464298b2d16dbc7b3bc1c85b34e6e37d66155cbfcf2630", "MS2": "1b12ada97ea7882fa2b72ce0552d8d0176697ae99d6c0df4ee0b4dff0f884738", "MS1": "1a48d211cd89564da0278f3ae02267b2721db90900d2b56b2d9d0c2e3ff8cdce", "CLIENT_SECRET": "04029659c163bbd1c33c50c85e4aca2053e80479a5a0d26f33638c90862a236f1d12e6b76aef2868ff9d263bb3283ab7c8c90dfde3ab174a9c40a091c8b39fd370"}, {"SS1": "04c3c4e694c86bc7c5cf6c060dc9ef2a14a6269e43a36ec21d9b1589899d9fcf1b66a83eb1683107931a36497380468c3f09d18971c3e615e81cf61d930adfe71d32d66742729aa64aa71c34b22bbdafc5b0771335a52f6ad8ab0c98256eeb2a07835c72d3c339777089d80ed29513456e167e32ee37c4a4173ff1469f2c85b7", "SS2": "0c19d6d36bca61deb4c398c701dccad602070de43e28d3de4df73524203156162106125277bd7133bbe8ce3daea19fbdcec44a34c0698ac12326b6cf328a4e8006792c382c64f56fbc32c868828f0677f8bdabf6d347f741fb0272db27ad61b40bddb7314575e1f8a22592c109eccb5f325ae5d13b935df6709b4cbbfe5de7a9", "DATE": 16596, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1b6f0009c4ab184fffe4c9967cef2d59c461009fca040f0c5355a1b32037793e048c0335c6d1cf6fb1c37fc38715929f964214567348ae241c133ca2f2810b381ec57d8dd798833249d825c41f6c2cf73e3bccc341ee718a1626bcefe7b54d8b17c232c0542aba378810e0e8797c6d7b1192227bca2a9b3925a8c8ca82caf7aa", "SEC": "040d40638736a2f07e7b5b752dc3d303b1f046334d93e4f59348d6003e1f8087b20927928f5b8a55e7ae51f954854c3df68632deb6877c98fbec846dac5bb2ea2a", "TP2": "04062cc5e8f13fe568897e2175e8db5b9a1985d90c32ca6d1e2f53cc34db1fe3741f16ab40dede6b23cadf33dd6343d02d682f5936c26dc83480c1a0d65bb56dec", "TP1": "0419a7206bda1cbe39120e0dd2de5966e66c166fb0d05535f07fbca85dca1078430a3a74f17dfe0576b4a74be9ca8360fa68ff5fe0cdcc103e42641122c1a751d8", "CS1": "041074e1e3167e0576aec62e82f3ca92a34afd0e301a00ec849b0f844f9cd1a9e21673a4b3115cde159f237a7ddcb5af1775d2b4fe4bd64b8d47839647f0d1fbe3", "CS2": "041ae43ec897deb10133c5aef27c2e970b63fb32c60e4946894cf824b7dea64fb70d0388601c614279252984db0fec34f50934dbeb9b60d35c3bcbe2fea187fbcd", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "0411403566ddb696386d61f4a851c03fa40d6534827a2988d7a0439277d99f1e851cd4f2920ecb64bd14e5a56856ffdd911337ec4826e341819587e584f90be440", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "041e59e03e0e5be147a86b1c975df45a5db0be286108f0d105f37da9d0b22201a71fb76b6d307c07e3f61ca1bd705f80a59d37fd38e52a495bf7ac9dadc643b98b", "U": "0414ced315795487861e7add872703b1a5c979f45fdca21b0772ff71a5878132a10969709f1395f11b820a6691f6e888dc884d3fe91a3ae5b2eaaf317da955da86", "SERVER_OUTPUT": 0, "V": "04195257401de28a5c27e4a506d83b66e9e6ce937ae035f9363507942bd9c5d49f1bd749efd6eb26dcc8104e97989570cdb81797b5ea7943a6d4bb371360cfccd9", "Y": "0202b8a4540624b96a81180fbcb1aedbe93ab38da38c6825dea0d54b64359f9d", "X": "0a0c03011cec93f9ddf3e7aad4dc0b72fd72730c50211dbc60a1c465d4806a30", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 222, "UT": "0412e6c9a4e0eceb170750422901648ca51061d181250bc7c6cad71d572efb046323792877aeaaa6e239f57121c85cc6fee9731a20a89cda490792fdb96054e24f", "MS2": "0a1354050822f402fb1abfd5ca8b4d860d39f3769d23a6374c8acb729a1cfc7d", "MS1": "1e3ccca9178c5de4982691e97be418fa2e6fd253723d30ec1fd2cdd9fa2cdbe4", "CLIENT_SECRET": "041087dd1ce5b8efe9cee3f9ea317e4ff311113cf9be3a2f790db7dae76e0195541adbc0f9b0a3bbe4ebfbeca0fd1e75d48850f8c1e5a3af396763c25d53951f7e"}, {"SS1": "09d6cdfd10d3667c71b6c1a634b529e794f9b73a548ec918687a4cc1e907630603534045cdad8a4e32fa946d4449ed3f3066f68cd1591bcd69727768781e1c1b0c3ba1a4fa3f8a29268b98b765ea7a8a1883192f2f9e7575681a87d6e642657511046ff4db3ca59447a70e1387097212394c8db0112b2c8cd06c77adcf2679d9", "SS2": "04a7214f4efe18039317203789bb572b5212ccf13aa904166f4d4df2317c4c4e0d640c4a879df9ac716ad6a37546b92dcfe87a15289f9465e004146d4d10c9381b5c22ff92cf47cd5b485c5c68eb3c94c0f65066ca76b4f8863769884d17d99e0f061c22f9a2e6f090e1bf5c4926ef1fc8723deacd3da8eba6b05c75b93b5c3d", "DATE": 16597, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1d68b980e1e65587ac7673670dcb33ebbcfd0f697ecacf46e58b83b5f91a912b00e0e1e537b12ac9a4c5caa964cff777db80e1a88dcac86949ed419e57cff49804f832e854f99c4bf833635426ada5907f4a431d003aa7c909ff68b79eb8a0cf118432a99bbdef84ab03eafa798f2080d914e1308a4fc16673e0256156f6a0d6", "SEC": "0401d82131783b33ed20ae4df80c928aaba69bcccb2453dbd249f8575843f5114a083ea3a5e11fac6f618c1cede88fc7f1c9b9d19909ed612a9e381156a1fbef5c", "TP2": "041541e3c1c1a92c6fb29a4179e2d4e8999925558c3c3a8448f6388c33cc26209b003d9e474af0028544cd254b512c7d8ea61e78aa2e92bb11651853783f49ece4", "TP1": "040ead73254890a20051fbe9d1f97d8220ac979bdf84d2aa06b47e291ae947cf79229ed55501a90626d6f1590a855b17192938b32bf5ea96d704370482f8aec855", "CS1": "0410f77b0fe8977635f2a189d83b6fc7654f4781b50266c116c2aa2dcf772036591e037f7aafb8c8e767ddb15ddf2d913a9730e4eceaf842f6e20079acd4b74af1", "CS2": "041f4af3f3dd64ec854aa701c0fd830fbd6e2358af640b342d242bc181946338220afaf405880fd9d012ad1030f8480745c2666f45f10f5f9fd3a9f7979c31cdfd", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "0400be30a34e224afdb2ba05ad1ef266dd4ab76aab247ef0541a561972c8ca92f22345f973548ff096e89d5675f232a844c6bbfbf201093bf069216887251269a5", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0401be47145f6495ccb4078a147d45c0650800e4cb33ac1d4cfd7c17d7225468d619bcf0dbd37bcc8ff93130201ee44569c7a339b1bfc28d6ee1f1f842d6f89a4a", "U": "04097e91778f09c6111632d1f3d6b9c60d9d2eedd5ba00caf9e31b7014023515c1100f5497fa5987a438b22cf43c69aac20435ec15b54c6c91389a8a0718c7b2ac", "SERVER_OUTPUT": 0, "V": "040e57ed3430abfdf44c55eacc1af849ab79fe34906a1394e9240b32d7ef758bdd1b342616e340981a60f63ebf1b05d1ac76cf6fa6f57c03eaa64d0e0af78ab696", "Y": "1a2776b3bba5a95b857971debee1b19bdfffb9dc266a0ac7514c8722dd64e5b6", "X": "20394d70b10347e33201e9a985be8e605102d16b07e452ed87f6602d3bc8ee20", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 223, "UT": "041554e50dbc75f378e00588e38e0a21bd61b4194dc445c8af6b9d9286d06f73aa21cab967a62e87d79fdfed0446dfbff0c3cb991d4905232f0cb02f86cee1305a", "MS2": "1fa167f0cc38bc960ef8b222dddfe14c21ef44a6eccc798745e42ab9b19aea13", "MS1": "05c1485b969db7236badd71aaceca9eb7da99474a3be4cc62bd56ddba3bb2173", "CLIENT_SECRET": "0409e4d39cb457ca0afa30a2b49a33d9f1292382dfd21dc69f6ddc6da603f737cb0356eaa455d5e7aafdf2dbceb6524c74719c652b69c6813a5bac3ec3195af8aa"}, {"SS1": "160486b1ee881458e523323b63366a7bd9ddcab286b887b51ae07f043a9656321e3bee49e4a85f721c8f65b34ec95428abe79f26ba6d963ae9e81f2e7207859c1c6496b3ec10e401cd3a8a114cb4e67aa39caa73533808a1410994e23820865b128dc77953b492c8aabf7361ddd67d776a3f7c193632818a68a9b8e61147b853", "SS2": "09c36f77fae403efb689f971df691782a4b0b37c473b303cef91c1be885ec3e409d1786d0aae3ea6054850ea1ef4d1bf63cf4082d085b504fce398b31b64adf0025b1d3ea98558f1ed793e49f178f7d229777626d08b6706a14d00e69ccfebd115c764ed3616bbcb1ce57c63394c314f43c70123bf16c284cf33397f69155b69", "DATE": 16598, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "040aa9f7248b870c365e545643e87ada716754de30e70c1254e90cdd48cec4fa0e51ab6efbcca2f305fd6ab80fc4df38bb80027c5aca06c789588f631a2c0e070fe671787b2b06766d344e9e5cdbf4beadf45b3c98adc58895935d3455d2d4d00e84d1105c7192ec673f17d38deb3c71e6597bdd6563fcc23cb1570713117296", "SEC": "041d3c6d7a764ead65a1c06938d635d5b081bc85c4330f77037429a3d2e5ec2784064f846d9f1b2634128a282e37dc6741b611a3f801d67d3340af3bdefc870620", "TP2": "041654f5a02cdb31f5d025e902510b25502716243e74536bf0e2d0daf395042bdc19c79a064ec1a72c644cbb3d18c4556b869fd941133caf0c4747874aa1fbc726", "TP1": "0404f529218c97c857b6cc006e3965fc73df3113be7a705e11375148dee24c439a0dcdf5c168ff9591dc29033b1ab19a60f68222a6b78de616afb0befb50913323", "CS1": "04056124df97361034b05948491665fc845e262cb4f83ef3e0d22d5b63d16a219e1803ce55a81f0699c8e82c341a3b778107fef77461b6aa800b459bb873f3359d", "CS2": "0402a3e8ee5b57287baddd85a2c7ddd27f19ab1abcfacf10608baa171bfe811e390fc4e55649eeb7368d3c0c38d75509d7393bafc1f5ca9ec246c4f8db8307a1df", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041cf245deab3d2d6cc4a42567ceb2c0c2c7d5d474b523ee2b17fa5566fbe714cb23e0fa46310d9d01d4f6155cc436742d2c272ca48cd59399e6ad6f9322785a5e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0407628e7baf3de7405d10ea1d5f8c36a131e3dfd09650a610b31a1e7271e798b6039c824f30b81c73418bcea264192b9fb43edff75410d2b3792b1b4ee47a3846", "U": "040ddcd8353f2af8a59e688ccc07e6c8dc0d5f0ed8c1492a78756a265cc3c0444a224ebf13b98130b40de6031911ebcdb2ad8ec49c9bcd1513ece2f406bb4578db", "SERVER_OUTPUT": 0, "V": "041903b539337db5c9452d447b5b78adb9e9d1ca3d0607a3b37f5b0fa7b611cb110204aa56f77cb0784b1bc47ed1b1cfa55d2fda59c67c2158d95bea0207e73322", "Y": "06642ab4acd20712d0d5b1b7133e1186b24209a25d92eee0b3fa3379f55a5ed4", "X": "22727770d0f03947fa0cc96c630e45703ef29e4ab3369561b184f7815afd9688", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 224, "UT": "0404fd52d3d707a1f10453c6bbbcaea6461b17039bb65be4bed095a8318864ef5609d0927e80512fd19f52a15449dcb830924937329b456022f8d0095f53369d74", "MS2": "1f0d1a958a750734cf7d8b95194607e22ca15a1d6649d43b467eac7c6e440daa", "MS1": "13ee895c56955ced33874a7815b2dfa178734f6c6fd0df122ad6458bf962789b", "CLIENT_SECRET": "04002998f95d646423135dbf9239e194ae7a7067226835b8b709b0ddf98f696f6a1f69cb41dde0856782bd11afb7c659142dbd7a47e9eec9e2dee93c8dc630c02e"}, {"SS1": "05aa6a8382abe89d469f2265a4ae675f0bbdac7bd848bc2b2ab5bc78e194a0bb0e89b7d4622892659985cbbf53d3fe9df723be2c1a3d2796b830315a00af8d210b053c01919c9029c4418c03a64d3e6c4005be7fee68edf87fb0d85bc39095c82066ca1f51f6b3d64933b5bde419066b37934b5484b27b123bf551dc9634b6ee", "SS2": "170df0d8820c182c8a50d525fb5a69992ab4d336ff77aa8855caa8c08b18f1240b7b9e4e2f1185e2110102c43934ad1fe5352f38d23767aa1231e265cad1a6fa09a88ca71d39825d728c1913d303b52ed3e26959cab2609f53585e7a02d0d4851cca16542a6681fa6dde5d7f0526ac9a61d8d8e99882448e4e17350c29d923b6", "DATE": 16599, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0abb9748c15680c79396d5387d2a4b7f24047bef38c17d8b16ba88ff83b453a80768c0cb3cc84b3cde09b6e4df49d8d85c298bc3a043094cc24b989c0363a5881cc9ed56a592b59d5b6392e7c319bf13987d2e36d245374d1f190f4c3567591919f1c7cfb0ad0e9f773cdeafe8e4d08af1b1ac3a5ec211072afd83fefe41fa63", "SEC": "0402c1cab95cbb51661eecb2826e864d374dfd7c3664fcf3241f01fc42616975e30c1ea2a6cff1271e87ec8c64bb0c8c93379bda8f98f9b67602ff574c25857cc4", "TP2": "040c31116506d46b66f0453c0f66964841044375538104977967afdc7f328e2b5207eb7503b73b4839acffa4b356af425d42825b6f6b567160744c8476ddfaac12", "TP1": "04034f0d1ff9187c8a87c54b9b1d1ec70128c7b135fd0dbdd46d8df9e78dee7f0c09838c575c8b870b2f78be71f7881dcd3b008b730f8832e9170e927e3da7e801", "CS1": "040080356217224e15add5205035474c1ec3bd6e9e75d6cbb83f31c40df45fcf3509b74fad7df5accad8784517f4b2d5fc60a7c51aee8395dbb625f90e88425ba6", "CS2": "0409a3ae1a7a0fa6494faacc342a246ec9200c9af94047371a3af06e268381f0401dc656c4d30ad84875cf6a233952511d795fe272ade4b46c3499b23b35ac1546", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04044662732e5ed0f7f4c2a191df8a8552fcbabc75757cfa75d82ed842ed42060905580b520936d7c80cb4dca9c52847262d3c720212ef9b928ad61f2e28f84597", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "041e8bebefaf65e0d7796ef57aa63967661795150d5e6d23b265d9b72325177fb616321e376647d9adf7694128780408dcb818838cfcdf526937f314d01549daa3", "U": "0405c3a751094d1da598560c0ca15f10cda808479df5d661142551a7ff86e74d4f16af6a5d5caadd2c781a0b109921de78d81868b9966668eccad8e77769fbe9a9", "SERVER_OUTPUT": 0, "V": "040edb2d873a46814c3af0eb64b28e967f3d799854d589adbd60092e626ea21bc0210cc3aaaf8d2a45861218c1cdf44be566e7c90b70b6e89b97ee01a2fca4a543", "Y": "144d30dbf1712ef0a4a9e1451ab324c24352a2b179742fa741b2e0107db36327", "X": "0b5c520742b222aa1f674fa790a305b4287b410eaa4d83078f6e3d4f43298a8a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 225, "UT": "041fc4ef037786169239df952bb6ca08c946b63b7433ec8a9f65f16d3c2424940011ee4bb7c03a8db94defc22719e7ef2a01d17058d98df855b5c4cbfc7ddd822d", "MS2": "0fe355fad4df5821318e0ab55aea1e8367ab7cadbdd0124e26538c424318710f", "MS1": "0e7a323344c73683d30d70d0b202bb5e20447e021a687bf0dea2f76738cfb072", "CLIENT_SECRET": "040c2d5d83c478fe751a2a25d48d9791e4f21ab585c86a6b50d026d51634e36ab503da591c51d113e16d67141fbe8502a73a4c6f896a709eccda75c67980235eb3"}, {"SS1": "0efefc7ec964a3703172ad3c04ca812b5eb9ecafe648ceb4ef8e837322b5a1b701293cf7fa6053a9592be6e03b80e2ca59233efb8f1c5dfd6ed85d62830ddef6119736441be501d72f843dd645338a9beaedb534e284679cf47fa77a1cb917b12022f7ca98806004fc2f9d48c5d948500f16351a6c9c2ba96430abf0773c5ff4", "SS2": "1d4e25f5e86096925baf764daa90584f9f38e7f63793fd61c3e6d55832fca9c3162df16001b563947b45ffde88ebcf9308c03e60abea8117d271e321115a54da0fcd42d514fad8661b663648636689e17d783d9946d855ad52ddae62a7d571e600191604416cdd239c675ee48b228ac20b63b0d9e32cbbe5d98e2569ed67b5ee", "DATE": 16600, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "16d7f9b201025e40e1aec98b1581db204e84481c266bb2c7e8dc786d4c4f67a41cc7dd2ce48d467b0ac464ded0b5e1eb01d99bde336a1e932c4cbda9091707410e9d7b79a63ee9e6d981a71cc26d555d00c0a9e6197b564b2f4194b5d551f9a41277f8dd02f78662e511178d6d829bfe2e854fb8c1fa49f08f9568a8afc229b9", "SEC": "04070f39c60d2f16be613b4984aae789596c5dda2306970162506586d2fb08077f14c93c3bca6a415e2d5a3b4c38484240f6a3353b8633015a289c59661237bd59", "TP2": "040f6585d22fab0128482d2cd12200487853abb84be42648d3c930b5ff4ab7430c05d5625f7e4edc047727f6c351c542783dcc29b0ed822b687a4fa017c9153aed", "TP1": "041570dfb31b6f62414244de5c04d2285cbaeb57ccb38c3331b4dd9e06448cbd040325c720e17de7cd964bf6bba98ef775965d2a3d977ccd1046e7fe30e710e78c", "CS1": "04036ff533f0d26eb1f3db656ce30fd70ca17b2cc2acc35ae50e068852ba629b240749189d62c477536456b73c27120214debcdb0e8262c51f5df028c13500f319", "CS2": "040a724be25e3cb8c476e3201a1a8b5feac5918c6e39a8ddf7ce37babf6b25add30da5fded3b870f6526e343fe8913c3600a47993330281cf3268465ebdc265e1c", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04024efa30856e35791c18a17e491e4135e13226c8de3c1a96a53f7354b0d47192087b167cb49949fa756be0ebf76c0634ca70c31129946762e0224324cacca47d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0420837812dd1be5e6551a2091d0c79ec118a1ad4e13073f9cd034b00116fdb2e004c2e8e4f2fec53de1e4dd39bdb01f59f6ad5aae227b3ec05bacd8b6a9d29b35", "U": "04075e79c24faa944bee0cbc0a857e5adbdcd6c97da9387238a9349772d8b18faf0e9f416f152b9a8acf447979c8805b6d2102e15228689375297726b51cd3b822", "SERVER_OUTPUT": 0, "V": "04141568dde58f4f849443b64a1aad5392ed84bb0aad59e88a0ffe98551277a7230fd02b5dc54cbe20e41676ee28bdf9b33b054102418a575ad160c8363adeb628", "Y": "078b3008fa1ef9bb6a6026dbc18f62313634425f3033e83e6f9cf119d9a0f5fc", "X": "1785e7d49853a8bf6cef438e7db8838154ada37743e25b56651112e12bec0392", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 226, "UT": "0408ec859833338c0bf18289738eded463c2eaabbacb95cadd4b2e7b9c2f7fcc0420bc770f9b165a6d4bc1f8182285a3b412c86792d7565e1a9cd636271a5dcceb", "MS2": "17510baf89fb35ebe8add5eb694cc2cd9aa726acfe7a51915844194df166be22", "MS1": "12fe201058c959e161382fdbf24516d50c78f0ee2e0ea20180018ba2de1a6fe2", "CLIENT_SECRET": "040d8e009eab7d706c67b157a5b7a474811a80b7322e55b03cd28a4a3d32f0ebac0bdc9c3499431037e5cf390b883a7e0956d4711f140b2a84e0bd065a5e28ecaf"}, {"SS1": "064677ccc24211362a1ba149628d5e9b50f0368f861990ace82ec1a5087cf9970fa2c50403722b76f25a509173de406109962fd0bb9675a93fd36d1fea507c040b5d8b080f9ac33611f09c12b0c7bb98158f7e0f28f790a3ef9119e147391b251719411df8eaf44afd70d48620ab94f782aaa62e1f2ad198eaaf184b8e602ed3", "SS2": "198391c082ab1f2bfa0516e55e3a6086b32058c3428a4869ca4a7be314a5d608015d630bc8cfd6809cfa4ce951a3a050a86ee7e2f82af509c895b736b365b8c200ffdac7e3260a47c00d03cae78357c475d132b412d0a3246ecb6b0d4ca7fe701a5be6d9eef8c678427e7bd90ad63ef8023624c178d2680504ab130c1803f594", "DATE": 16601, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "2302803d281e86d525777b5c84553de04724840f5fa38aaaf6ad99175065c1111a03470b5126bb344f37fa9d0fb34477580a07e1abd8d354570219e3b4e41d390a0bbfe4107c2e03a1ae073f8d9feec5c9eea388c9742e0537fea5a598fa4b35104ae907f583e10d971d732ae819261a0475e91d3793bfdaa1f47dea2662df32", "SEC": "0402a68cc3b3f6fd5ea76e47b85e4d752d51bfdd0e924d3bcd73168fd3f904e2df003e735e19038d725da84d88dc152b51c463f0e5a84259032c5b0c967683e8b0", "TP2": "040ee66545d7b94658c426ba6f8f0bd463aac9becdda4d7ac910583338a2944cf217b7de0259607438be60f313a3485b6a04f2797da6c610d3ba6593bf36473702", "TP1": "040fe02a63d7cd5c4f06f5aec8697d592216522b4fa98a60ec06b36f5d496784ea1aed2975b9e9a734a2d89c3f1c1b0920944ea11c50b3a1424456049701825467", "CS1": "042326e899427c3bfa2557b20f05dd5b3d07081bc48a167f858aef0f3ac66822d4151227fe0927125aa7e1d9bdde9cc1f45edd5730fd0cd94b869061164696220b", "CS2": "0409cc4bdc568d2b7dadae6c98b79acbf72e20a6e9ade61927081a19bcc6ea7c60061243c3d3d0c1056743da5d2c39e7c0344016b9e30bca580ea82bbcec591f5f", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04191ea6dc97f53a4c7bd04f644f3f75f272ac299a78e9ca39db3c54467bfa4e7b03efb3745b6c7d9737c9be70eed86df40520c1e34b24381d46219952ab59e071", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "04007acc143790559192e2faf433b75e5f008c355610f2e4c7e47cacbc831f45bc0faf7ebdc03d9257188277847549da03bc87c01c42e2d90c7896ca5c9d9a03d0", "U": "04123cb42aa831fbf17db5eb9c81a437fbb2dca155bf39f05179a36c9bd10353be032fc2ca3dfa9d8af58bf8ee924b3d711b6b3b93b042f7fadfdfa576bdfd35c7", "SERVER_OUTPUT": 0, "V": "042225359e858101afbf3d5b965eee8ceec663dbd9a42d3298e07461921d73ddec23bea0f36caf9ae232f7b0378da8f9b1ea76ba0a23a234240920e16994e4108a", "Y": "199dd6c303583db6115c9c0c78679b743d2b5ced92cc3edb2051d29b5bfed2a4", "X": "09dd194ce99e3d83f05ef123e20766fd1ab2b73e498550ef3e95d5ef33138ac6", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 227, "UT": "0420a7083a0e0537a018710801658aa8ce9bdae47ad2ed7046e4ab2a56d41b94bb0c73db3933ad47056f1a709b8b88361319a7c9a3c4dba85a426bf6e6c992ea98", "MS2": "1dfabd46cc2146b8a2bab39b23d3e46a7ddd05b359753ca95075c821f1ad3d41", "MS1": "02ac380202a3de8af61f0c3c4fee21b3d5c8d4153a957b0004d9ec5fdb249920", "CLIENT_SECRET": "0404b59a4421d2914f8dcaff4d158383f0243a3a5e45fcf17d99e32f116b985e0a2080d40295c4aaeeef3f3ed030a56f66a1c939fad5b8ffcbc09aa7e2853eb46e"}, {"SS1": "1c6ce3e0d4ff3956669b1f629e338bd6652657c8decce55769136270a56918560399645a1ac125ce6ece55bab1855f9d5979bf5e8ae8d11410ae17db46c3329a096e6b5c270465e0bbb9e40b2be9b3c2a79aab34a08f09ba9db8b2f4307767fd1cdae96c43de085e5dec73049e2e1bc378072201e8952b7ff48467a592d28269", "SS2": "08e335fdc103127119845c86741adb8dfa289dd0f1533d883ed246e68bcf54c60c025c83151e2e06ac9baed06a853b65d81ed1c82889dea88ce797241e21e6d41d4082ad94e3fb6b116d74a271c18f176f4598bcce6c8f5a09ae7e1019acc2510553bf66c8c719f33398b35033c7a507be3b7a909ea11b7c1f695b337b1828dc", "DATE": 16602, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "04fab77d576da917867fe82ed88d31509ff78f57a7a69ccb0bffac8a7f6c8cc92374a20cb6fc9b645d4419a42999f705fa94180f65fb1045617b002f0e8da7e00b161d3fc14cc9b27acdf3cdd8c451f3266dbc0b86e6d852a3edce480b6959880521bb692bf5370d758f5c4b4b94d5b234267933be49c48d152f1d95e88a0f8d", "SEC": "0410a70b012bd2754e309df9003c4bd1fcb4f75b99332242a903fee0d6404bad9b05a0942bb33c6da28f9879693b59672c5c9c3f85348d28411c71d309fb3e581d", "TP2": "041ffeef02c2fae572fde277748f83d65d9066a611724c4c471033baa239349a371d8aaeaed40ae5f1053c23439c0cbdffcdec3a0216c2e916ad686bf33089c892", "TP1": "0415c0bfcd60b448271374a927bcf557230fbaec6766d25d29e16ce8a788c4e89e0952d2b0cb3fc714bf8672fc12d9fc39adf0ad8171987c9c49d6d9ea9733b063", "CS1": "04200b316ed75439f789a4693cb2eda4fb0ad637d9540ae0b4153e1e5f31cd2971163b571007bfeda3478596220111ad88605708e2aac02aeb9de5f379bdbbf9c8", "CS2": "04050bbaf473fffe0162e268dbd0acffcf063cb1d6deea82ca856d9bad64eb281c08b6abb18cddc3afc368ac6b755ce074c82ce89137490b3c45e4e990438cfd1d", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041ecfbd71e590ad90a0c7f0a8ff25a3d44fe8d0a8df99bdbebb814d38c3d8970500bdce59e0d4dce412ee6031f2cb08c7d63f2779b1037dfd8996a6b3129b99f2", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0420149de0317db5d4953af72ad79face5f3d4f91ef2f39508323a917c6da2886a21808b3d07356a9bf09c046f94ccf349c346dd4a23d5b39effb3d867e6498e47", "U": "040c2fd7a074f0a2873f5aec0cbf50209687bcb313ccc75359dd0a2640ab54ddd31f7391fecc39c77158ab761fba19c4cf7bdea461c29800cba456d099da517c68", "SERVER_OUTPUT": 0, "V": "04119606ededb845176730e64c7c8d39ea226625c894037f28a867c27939986f3415cae04857d3ed3a426cc28a34496c298e2afbbb5ed23188126cfcf42b75e509", "Y": "213bf91fd365f5854a46ac6b86b8aae78680b0e5625362d5ee79c16068dd7ff4", "X": "0d7770fbcc21e1e058834329c326838c978b56f7cf61939a875f729fbddafc70", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 228, "UT": "0409dc95e3b808a144de39605f76490a975230605c812892f3887dc09a18072b82239d214dc6c1c2a0ea07da1fd6b48c2c6a1391fc6a5405db8b4053d869ff3c2d", "MS2": "0cd2c1651afdac33be8c015a3829fd0df7296e80dd76196c094180abbb5ab9c3", "MS1": "1c365c67c119133ce3b863dd2e9fdd559c3c76558f65a1d56c8b8fd3171b8a63", "CLIENT_SECRET": "04238a80df8cc3e071f484293bdd943c8cb1155fd41f8da40649a023f73c684d911d1743fb95322013a6b839727e21a30a7e1108d0e0ea19574c2f8c0e8aa66958"}, {"SS1": "0b053efbc7f25a40e1cebb149ff28dd063b8e6702c3697abb5c7923d621c2d9c1ce002e774f14b37458d0c6568476e08b6072ffa66f90beac81f75b1c5b3bd361a559728ce501896a617cbad6ccb32875166a6dd99b6b82d19e087841062589c186931de736ee29b4bf98f6a8fafda204b7a900669af7ad46aa44edba5013740", "SS2": "0d0add6178857d1e3f92aa7c941aa1e1d2c1686c459c77277a6c1221e247f3d814ca6af5082df2ea76c30ecda5608285bdb4f1d21ae1e6fa3d2fabdeb247d81b223a157a2ef4673d0cc69c4f047ad018f50207fa5029b320a2a4aa32015d569c01071f917ebaec3c2e44d5df4f714e424a84d6694d168de5395db831d0bfee61", "DATE": 16603, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "14e542c6127bc84fab651714c356773f5d6b621f02542841b49a2afdad99983f0b7e79ce5c14b693ee8ed5cb01bf3c48fb634d45409a6321ddaa99588e500e5b089d66512037abf62a6cd0ad85fcfc5ed3eb6bf0a4028ad1c5269623eda5c04d1912d900d705c8f85e582b89d2b10f4017a64dfe440e5d91e5b4f9621b933220", "SEC": "041f837d75cf48c0371c5c474871abe0c7cdd34b96f85051299fdc8a75868b7db409390092251d1539e16ed8312091112cb89103f1e78887df9247bc5a2abd21fd", "TP2": "04034e48c021a82888d49d96fbbb2a7ebcfe4bd6f84ffaef8fdf5191dfe48ebf0a17df98844430b174a274cabc03951e7208ce54d8faacf8e7963d31942627324a", "TP1": "04064a0020ee5f0d85a0e8f503b325d039c0d161f77758db231660a8b12f246bb71c0671de8b2d4e3539ecbf1bdfa07cef5f9f5a8f04414fa6dc135bb6c7363b7b", "CS1": "0410b6feea377df81c78ae6542982f97c24deb0f13de59923de3fadbde0fa7735f0cb1219c9e294786389a0d39e585a0e4845ca029e47beebb896a5a577f1b16c1", "CS2": "04189243d6fdaf65bb5b58761e5d6253192ce76fc3a22356664a5eb967f8a7456020f13f291d6f7fc647beadac3357bc5fa4927703ef5899886d8517db7f3159be", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041e3cf30ccd888f54b248af1aa7ee08cad299553fdfab3d4d356be18dcbd003a81b8caab9bc18c4af16be626da98fd9afc735b850661fc971c663ad819ada988c", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "040768a2a58eb0ea23a6e424e13e2eb06c4068740ebfd05ca6ec874afe3d84da2410730206a1910af00f6184acbfe1b68f8d9527444772749ca9b6c780ece69d26", "U": "0423910d20c678efb7c6b0ec57431d658188a3398d5c643ca5e152db98cb6f14d70a05186ce1b84efaa1f2ce2d9c695c6c0a177aecab00916389c7139281c7b5cc", "SERVER_OUTPUT": 0, "V": "0400fac4525f2bfd315e5f3aae377b6f0794366c1be60382b43fd1e1c66d0352730fdbeff92398fef64043088ef909f54cc0a50190b6158ff92b5ade87a958b4e4", "Y": "0fd94048999a93e849185d9fb1104dc1385c21e448eca5cd001d119615562b9f", "X": "1d9f88e929140e194c99d5ed8a62f9c3ab9ecc487dfb352bb50b4cc64e65df26", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 229, "UT": "04220527d92066a00891add49c734bc233e46076643f6429a22f918aaea10b5d98043d774d32fc87afe7fca95387e86eef62ce23d9abab9c10e5108391b5772a3a", "MS2": "0b7175ec4b46c0a7d134382c08150a7ecb58b67e00771271751f6531c916511a", "MS1": "0354cd6f9d7b86ec74ae7e3d274ffe1ca9cb51b516b8099fbd9d5754ed7ba3bd", "CLIENT_SECRET": "04200cec2bcdef43133c40271bf293f5719f48ec4f94fb36ba7ef40c8337116fd61262a2e5c13f55c66c295f3379fdd331930b94e77439a3e504e7be908412744e"}, {"SS1": "015457df5d19346f3894c9126426bc115746a098475e9eb4a6862ed26105c30117b344ffcf37fc1732a9c78a24d8321773b94a94c8dda92826b2d6997f15311417349fc32b9627a04d681033baab6026b8529fec09ad4d397f3d7d85c5f69f3718f10b1bdb498ce1a19439a64a62585f0281f4b9f55f97160ef877b71a1f8e6d", "SS2": "174d4392033067121f27777d3c055a70ba6347079e0b206bbbd6995196a26eb809ec286716a4603b279879612fa5016e61b270ed559e8e136af6f9d89d04495c0459668bf2dfa272f35d817fcd78f3f1114fbe388a4ba78b819a965b4430eba32227d67e5e7c7d4882503a5f3e1b25b3638fcbc1e4835c97448bb0d469cd4013", "DATE": 16604, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "08f074886a0ae63c95552bc5ed25bb7d49182f942ac2dae0664030002116e3932207eb27353433541b7874244f06c4e200958b399f8199db5d2a6eec167b0bb90bbbbd2b034c060c6d7e4042cf5f144d0796e67ec9f2a5731e4e71ec87f8e5f410f15c8ac58c2b8b1c5e71b410320ba9402830a62abad2eaf15c34ed9d432b64", "SEC": "0408d3bc60d6ae27c7ae5dce7b780988ecae94d356c4b0eef6d0214690f0e69830152c044f5358f4f2c3c71514719639eddb3ae80638d6bbb1a415bbaf9acbc447", "TP2": "0406df85880b6b362bfd323acc8fcd1af61a5da73613280cf023d41cf02b5842051a49b0461595dba6b7ad5e69ebfc001a8ae3e11d26f40437b587105dfa0dc476", "TP1": "040701c04cf800453d0c7c2e88922e0bf74cb54a535c866516f8198421251f57981a39bae8f03fed5752ce06389498689ecde097802501c1a39b73775f73e4f422", "CS1": "040ef138aa9d8f0c693578df9306b18b1fa82a294f7b3655afd89fdec27b95bd530b9ff46322946c1e9539623cd746ad12f049940f3bca0e830e9ddb5e81a62c30", "CS2": "040ff2834660d103bcce273a20174cdc4d24eaca1060aac347315088644e5074b81d616d8cd15c9dec1d319a4f070619666e4f8d39b0d4ce7fb8a2acfb9d12483a", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04032c38cc2f8ef2372c11ee43979221009ae732a6e98837cb8cf202f0d4298d3d1e03a8ab489f0a98bfeca6f4ba536f2c2d9449c2930e443573014ca6847fefb0", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "042268606e1ffcf9e779095156e692fab79b05036a7131d1b0b8992bf2621c877119f4b668294bd23681ce1b0a34b12215919826b95c26bf14bfa4a49b1fb01a8b", "U": "040a8fa2855ed3d2c4721f64234904b842975a7dec9467b19f258d1c859cd49b0f07b53a014e7a3414a8f1f15b021add45708105015883f305408a12ba80c5f33c", "SERVER_OUTPUT": 0, "V": "04094068d74f68604ae4859c47a1400f443ebc0371894f637f50cbebf3accaa05c142ae70071a6ff65dd4e5ee64d778c101514c80128b5dd0fcfbfb866a134251a", "Y": "05b562a55ce39faa1b773adf65be24dc487fa5d3cfb619d557c110e05ff9b784", "X": "202b5f856a6a590add5e439fb341864d591c7d5e76df689ee202536099354701", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 230, "UT": "040855e0acc31a2d500232701c0e2fae25e457e3cc8d785240c4f7ba56073d84de09b04a35ce9cb62c8ce63e2944b144ac31e449792b2be8179f03fcbee0f7796e", "MS2": "05dc4dbfdb48f171b043ae26b94c217c69faee85875a04db166911a697729964", "MS1": "1f50aefc420c3ca78ee741745f6895b57d29e0fef1d138811cc56f58fb597e42", "CLIENT_SECRET": "0417d5476ff12d3a2c98f8ec82ba6cea4fdc0a207f7e68323a7f9d25f2e1fa18cd0696902d5446c7178dd827516fd40ea9327bbe8e7f022db83fe64d79cb12c886"}, {"SS1": "00fee45fedec20ed4c40353378981aa4a2240c1d3dc65168c33d435e261b802520af2524eb4194329521b76a68739984f1994bd7a0ab392998dc0a73ebe321910502100e46a7178896c3a1b6955fa3a6474cf7b3d05d4010ff924172ead4fee72007381969f16f34daa26d57d843054e1779b99d27bba80a88c6d3a125949262", "SS2": "20efad83a556b38b5dee54adefffc8bee3167aacc29be36670dc9c6fd9efe84b1419e8545ed76668ec9b9072e1bda71c8110d7cf3c60a841fb5a8c31d1bc093510fd2cbb81b3c9139c5d37a3333e691005b317cbaedea4ed76ec53b321d1b5681ad4b2467f44a9343f1b1a650dadb19695e96e7613f6c1307ae32445a6b8a18e", "DATE": 16605, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1936ca596168e65c61464fcef28eed8150d7f8c929d896a93454287a4a25a0c910e8fcaaa39d6a931d6e255ac7a4771a3d2df10579ea62f7c7850a71d02ca9af0ccfe01ae75e9e2f9b097d7f5cd0d6eb5f9afaae30c2134beceb8ef88809f5021393e59bb6c3293931a54fce34a18ee9b995f653c61087a40618144d5a208e6b", "SEC": "041b2d3416f3c9b94e6e05dcf7fa1b19421cdfc3f9266f395efc8f5ea1866abc260b451d932134d530ddf1ce56fe276037b451f73eadae1a5229bb52cdd2cc4686", "TP2": "041f7a02b4b771dc5ac45c91bc0e4d637acc7156da5918e7398dd63b8170410a5519dd450456fda5348c0dbbf8213575b02ab4ca04069d87729465087d98b443c5", "TP1": "040eb20f18cbbe283d702b26fa64d0bb309b57c9936794e5c43352bdbce72cbbc421078b2351a5718d98c292e5e375bb39c76b51675e6559b4db528d1acdad0890", "CS1": "0400a3c0ff4b9235c3066d59e308cf7c3c11309b17c7d429f14f50363e5cc82d601c21f3fd92d4c3cc55f9572674cd51364c44a14988d2c15dd430123ed17d5ef4", "CS2": "04015db2865e56edc2e9b6fd184a77217645a1b7d03cf65e71654f3e14bc1d9ae61b9eab6184fdee1f7ad4a4603f9f236de7fb679507994334f81e67d0c237c02b", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040c29f810cc108f40a0546d0c0698a0752785b30a05249fe1d23f10fb2f4b442a0de5464eda2aaef227e9e50a773f14007703e4657dc913bed7cb5f5818cebdf6", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0421478fcd1e91b7fd59606d9f3be1ede98efd4b7dcc8401d314155a8ef33e63330ea73328e2fd881456f7661c461b15ae2b8cf4c3d2069c9fbbb226cef80d98b5", "U": "0422e30291e373228fa4695195b9ecc2c3e75f419236ab95e80998713a102a36b320c274da56ee07bd2c06e9744e43900966140df4ec7ec900572d6d6cf5d7b738", "SERVER_OUTPUT": 0, "V": "0418190c1944d4c0884e09a4cbc8afa4af148824274aa3b2a300d964f6809368090a6e20aa777e398ec62833690317d7f3aafe8b12f627323d5613b98dba75addb", "Y": "19a714dbc15f584f9c718b82e841d62f8d9bcc577da168b6d33c85a3503bffc8", "X": "0d82090195bd0f0101a9e1a5c5d43d05eafe51ce48b551676dd45a5367b705de", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 231, "UT": "0405c4a109b217b76cff2279e8bed764d30494d59c0b6201341c54656ffe83a3841d6e20cb45a7c1bfdc9ac9a0863705358c52965e6afc7f088cd5bb5df1ab1cdf", "MS2": "17c06f7d41008c109b67b6f9f6365b4aaa338fe92c258252ca317d4a8a40b888", "MS1": "054a337642b29ef73c57e091da1524125e2de7eb4b34d4bd84fc9574616b8c13", "CLIENT_SECRET": "041a4d2b2d240a94aca8443f14bda104bef4d663791bfd92a0a4e820993a5bdc63099b489dce3e7a65cb11300a562b8c2b87d170a46fb0debee4443b51f65cc9f9"}, {"SS1": "1c7f12bf4aea6a74bd40ce9b3ecaee8470f4f418de51a56b356e2723933e31d30de0a878481179136371dcfa7d5096d25abc84f86bf9e2562fd36d3df44c34a417b7088f4124dc85b5fd3d21156f46467a1dd28e2c67ce03978efe66042018871540f62154cccf1e1049d11e73f28e81b95bef2051c1bede611d07996576bacd", "SS2": "040b0428cecf9a9e37668b6dde69ab021b2f31905cdfc79c664437665a8619741540707cbf2d9249502477d27db8017371c13573597a1c9217f455497d8ae6fb2019941a3ad731c193309b14251fd7eb92aa6775e739a7fc2daccec0cf30c0a21b025338376d48f28d07cf8fd87caf27d527e1a4af387906dbb0bd6055eff082", "DATE": 16606, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "05836ca321ef1f9b2cc77cd027ad145ac3949333516ddf89e6e3c96f4cd48d8b1bd91a22ce993b22f3c65944f343d3f78094fecd00e07e0225e5ef666f14342a10f97f4e1343baf31a8d912501198fc4fe65186477b39c421667bd54c21ee64805dc062b2df74dcf0e9f0d164a9354f1afaedef7c7954b06ce43787fba6128b3", "SEC": "040adf431c080b53e8af90b69b9f2fddba27b8247a81605c8aea415eef9bbf42c20c98bd5204b28ed3e5343adc2b0ab3a80d86c048e41968d87535d2b018efd67c", "TP2": "040a3ff883bb73c535d1bc44e6c366d17471b21719f53035f739ba7e230e42e2c51f7f0d9bec1ef2e475a46c8492dcf972de3d777c41ad42d729db14821f5c88c4", "TP1": "04147bb739a6d9a47e057e5f5898afa2b1014f267c3bd59d350a7241b08e0f0ce004867552f818813720c5ab782f55cfda0e71b47800052e31d0084348b6130c6d", "CS1": "0401d9a51325f4d47fcfdb25db7a44e385801d72633d39c3d8d96de69a2f6d308816606fbe4a21e22a2a7bf46ba60216370ae78141e872393127ff1908ac84c644", "CS2": "041f03e9fe4c0a2c54fcb1df653481b6ee71dab39d5449fe4dde514d9b4fac3bfa0d96fceb579c113425071eddcdd390d30a32cb706aa2b3cc6ac0588d340f79c2", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041c1d5af783062560c63715211fcc583265f11c2997eb2143a8a8884d0550124c04dd07c3dab0636a9dcd6f00212b3802d7f3a9288ac887a44c396ccf9a3370d1", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0419c4b7eed16be1ab931858c50b0a69a296bdf1e02b3d6a6b97159ed18318b2bb124a2f01b6b067f9ebfa527e0b716cae502d22d19e18fc9dee9603563457c17d", "U": "0415f29ee01e74dab9aa0819d9b6f76a6e9a7f6a2603a222f1f2a0b0b7ec37c1c1009a23b91bd12a24d2a1ce6c99a069d7164015e77dad27beaafa7aca176a4554", "SERVER_OUTPUT": 0, "V": "04007f745a8e196a185ed41e145d6728d4ce231613a00775ac2fa55e3990a958b322db5d1ffac0178fbe35f1d9299f06bf89fa6fcf123c68e6f1bd9137a8e4eaea", "Y": "1ac1e1fa5caf1b0bc1d42b3db4d423772aa39464c123aaec27208b649425a9f0", "X": "18d0e79dfa2365a348072b6188e1b8221253e883e6a69e2bfad8ae72fc5c037c", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 232, "UT": "041b3a04841fbd8dd40a79784bfe62dc2838e8998707d3a5703fce2641bd46d2db12090741d3e1d4ef4a772773031d79c5a15c9900430cd57db7c0e482f84f7b34", "MS2": "0b0456ee5d27f35611ecca4abedf35221fe433654e6a9034aa5a1215ae62e89e", "MS1": "131108da081db3b313a2c668594470d0a5e3092fe0f857a00e7ac8de27965b36", "CLIENT_SECRET": "040e2358d1b1d4e4bdc107795e4f4952fb670aad41ec351c63aebaa75526de89bb169186e050f517256afffb179ac6686b21fda48f139c08b8fb6dcd31ef9ddbb6"}, {"SS1": "1685562d3273a8ed3ec36a36e8ddc39d319164797cfeb1ad78ffc6acdcf09ab210d390d4d812ea303693a27c70357e410483489a8e2368d0a75e1cb3c9435d911dc7460cad8eeeb3a5087393e451ad667dbed86e89bf18b2e1db3d9052c044ff1d41c3b09013e30f259c9fbcd076f669cfaabf7efab7545ef5482d5a1f43503d", "SS2": "0b6950b72d5ed2d0ef3b2194709e3043e03a801a957022f456c875392234ff2d0464e7a9bed84bdbcf5652b7600703f7c298a5ffcd2a852430ef4c7e90cba20f1b781049d7ffdc8db0cc35dd8816dadfc59e42aeda1b38716107cb72dfb2cda203bd196b76b4721f973096df273cf6510f1ade0add49572a2ea38c649cf580eb", "DATE": 16607, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "02d10d87a51771f4cf85fd5c6b73b2424b45083a1bcdfbc932df7fe19f7fd62c12158d1b655e2bffc5925ad96b1f04e517822eb104a94f1d619af560da9c26540e1bf7c04521f8647aa845d3e9b5d13fb2a55ba2bc5bb1eee27ede4adf604c7d047d031b50640b1aab20d99496fc226520e2f1e33cd056aae6acc5f1bb1cd7e7", "SEC": "041ca2427a96e35acddb96e1df74b5ac3bfaf221ea03a91d326db64169977b91c90600c8ff4130f02c5f2dc7f3367aac9a1d785500a2546c02485bf5378625085a", "TP2": "04060977fbbafdcc05eba5c0fb8f3011100684f749d238832cd24694bd6a80b02e22d92802911ff210197b41d91dbaf1769c98a5c56f41d7cd72495c92c12e9cd4", "TP1": "040e66be1815e1764f55310e1a15a39431ff06e5506e815101befd268dbdff90ba205c8706a979c53eff55b589b7aa402ec4ec0f0408fe161b206f883a5f7ec875", "CS1": "0418e330833c0499d712f8ec24b1707e3f8d69c6ed4b36a7d6179cf2d2e7bb95bd1bdcf4523e2654e9219ee9d110590d36f6b8f0cffb5104a89626cc8b55fff521", "CS2": "041cb789c0bb4b49215477e6362d8cc512d61d778d59e7508a54305b636820d3b21149356cd6ad14ca36e51d5154d06013caa4c408f7c39b9b5d32d50445f3023e", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "0409ab2a5c44b53a1e8f8cd54b45d05fa737c8458b55dd3b9ba0ff7a333d58715c1ee2f7b3521ca8729169511ce90b78467e705d7cdcd908e3f52ec0a7a5e42b75", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "040f93aced85cc676e8527ef5198bdd496035842c5a6d77b42f5a9b171f2a8174b1c366f2da8c4ca84079d161265ce7ba00001716ccfd460ae65424dfe3d7fcb77", "U": "0421e30152967bfd7234e8e55ac23ae2e327d1649bd4f0bc57348db779741b71c601627dd96cbf9b6b036043608f3d3fbecf8d5c7b2b6084c38e588be2ac93b701", "SERVER_OUTPUT": 0, "V": "040e80a70173e9b0972dfd9154761c68290e3b0fb32d882a70c3a5b3295f4944e10a3eeac0d053d381b1dc02e97c56fa8ae5a26f5037532daef31590f252c793bf", "Y": "0a2cefcca34ce473c93594e58458b1b36c8b2e5aa1a9d0a384b0c6182d4afadf", "X": "0a883903dee3705810cd060d9ac493bc3b79d21c5c363a91410e7e907b3385a7", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 233, "UT": "0401509c00eccdb229f9a29868dd8fae59bdb5c1bec7a8469f5f51bac8fbec570e1e6b66c1bf14d952bf98d83df87e42bf85c0184895665051df013960c5201759", "MS2": "1d5482d1975c326655c5be325f69f5e3e7c74d9027dca455a80704f6733159c5", "MS1": "11e8c88f26e853eab10f63fcf2d6384575f0ba2d8dab529a188ff4e7d2f2ed16", "CLIENT_SECRET": "040d9a75a48da2aca6518de442b398485e2b3a37559634768f683c2ee582244b2d21546501a3714f2612348fa8a24358737d1076e3d89dd0c2150461051e7953c9"}, {"SS1": "167f8beb4b39f7cc6373e4ef86ed10fa237effab001bc419f7feabb227592f130bae52e44c88a5dfd096fdb8983dec3dd0a069494351bb15e290fd1234dc1e4d06994e07ae01c87351b05bde57803bbc13821fe59eb43c8a20c444cb46bcfd9617919bc8019e42447878e576272a8db9d9fc0672ee5d2a73c533548d9275845f", "SS2": "071cd19abfbc02df9b6370dd230f297b1da2325d3e9598269635c2ed6ba21181071fa998097285c4d0d19a507b657891258bb678dad929ba29d26cbc9d525aa7200846a0cfc0c14c4cbf2609fb58108f8ba3f1916300fbc3c60cfddab349ed7a1da878d747e4e861a95eb9554b26334faaad5ce13b9aab234c92267140b456c6", "DATE": 16608, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "12f4ed7c7c71563e99c372afc52df40aef145dedd9f2d9631a6fa9216de9f2b805bf9a3ac0824f4adfa275ffa948d14dfbfc772c8013dc21abd9b5ffc6260e8d083c54ab4ecdf35595fb0bf8d5050ea89adca5b4af1812cfc32caf90c9b8ceee234b3cb8a6984c50ff25c0b7959d42993938c2a5b2004c6be76829ccbcea819a", "SEC": "041550dc3b3e023ca203a83843f3f028c5cf935c129a0eb6d1bc85871766b01740214c7536f7538fda579e096f9279c3547ee6009f955a60c73b4ff9af850fc177", "TP2": "041c34ebd589f6048c174f68b0051182f233deab2502c249586f7da3aa6262179b0eec5c58f22e1bc1bb186eee6a1d6c105c53d412162d8c1d174636425e3d42a9", "TP1": "04236a5592b00426cd56a36a3646681efda6994f21d6978314f25231c7cb8386550d9cd00223f1e4adb41c551b16e4e2e3f32f170438f0ef2173b973cfd9ebd71f", "CS1": "0412625ae8df83269c8900fe87a0771b85dbdd42fd5fbf9abe44aaf6b462fafcd805d919f418897e2632ff931a1da50ffe79f5363b9947e2dc2644dc394e3f4e1f", "CS2": "041d49796cb6891c974effae359e9802418c81954f81c1979813c9797dd2e3a3941b3a4b532801dbf9d0b20634c57bd1b5f83968cdd83dcc4ff7f3ab064c123714", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040eabfeb2cd163dfeb1598c10aa23cc83cb391d15605d3721780ead873914801d1e8e8053919d07b63624b3bb1f92cdb9942db1e1019bc3e50f1a9f5fc1da2bb8", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0411b123fd904a9ea6bc4925c8a0c920cfecfe0da43e73d8b60943f1437e34d7c10d03c996340f0f6b7d8d2939ce5f000784e17497e6f5699ad82350aaa648bcde", "U": "04236385ecc3244cfc6e7ffc0c6a35c373f0754513407977156080f06238090e4c06bc966e595466660e98c0e12b8a18e509a16a9b72d33c817a406e072a79378b", "SERVER_OUTPUT": 0, "V": "04225f9b8da680b982ebf86eca5f7847d07d21b68896a3f904b1c9e0a15c8184461d3788a618f95ac18771ef650e72ae39890ebc04a42288aa88a8b78424333cf7", "Y": "132b5d72ed853e4fce08129e83613619f1240ce7b34231c22b28bfcfe652d3af", "X": "1cb947f3bf6acceb7a04ab1c13b8220ecc4d1fd8942e362dcff2f99e454b174a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 234, "UT": "041f6a637753aaf18362a566ac462bcfc0f646ac7803c2101e1f72116ca5ad8a5f00460c0733bf5a6fc498a69f41d3822b6020ed3cbc4cfa4220533d3f7f5e40e2", "MS2": "01b3420ff49698b3aaf97ed50f14164080ade8c967f6b20ddf6990a258f89ddc", "MS1": "10bebd61d7f48db9fc8b6b41679110d50ea5576b5011466cf10884f327ae6465", "CLIENT_SECRET": "040e191641fd75a50185eca03f3e585d425db130a71eda0dd3b9244d4e9f316791009c02b21ac256afe0a94c742fbe0a41da7c5d0b576417315a571babfb1632c2"}, {"SS1": "1dcf027f136b9ee3b31e0c1dd6c9c7680860e66adc9bf34616672b84ffb95277234e26d7f20789f8a8e01bf27eeb3ebb6b420cf07ea66516125691fab58b857f0fae7854b4a251024c04ff20d9adcf02412de97450738a0e38d8d32cc9336c1b1bdb167763a9e158b1e835be82911b52e5ccf66fbcf1fca22ee05b170444393d", "SS2": "0fb6529de5d740f2cc15676b4d1d8893efe4d8667e1d70dacf01d78b7d0dbcbd1b9d3677a28f49cf10859d134e5b61d05d505670702219f152cf82273a1adece0b410d881cbc8938b81ae12ae36d87caff15be664e37313af9508c41bcb562e40d30dd9f994b506f9932dbb5098ed3b4f0953b9712e9ddd65cfa4dd186a6af61", "DATE": 16609, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0d5579035c58935ebc8955e4629e6fdc9fd8cdb3ef458c32946da1c0dc63afbe000a9b1463611e7bc64f6bec129964b96f00380a9f8bf41cffd586fd75e9c67f0f234dd8d02f588bd31d1f1f4cb0004527e8a6547065af90bc7d15b4927723c9047b5be1cbbcbb25f02e9d8adb6e0c0c971e89c798dda3b3ab07101cb8bbd647", "SEC": "0413c9db51bad83d356846b9a83a9930a5c15e051b81abbfc563fb0c81a7fa8c9712a3d1d070e2a2ea630a9e6912c4a83b3e564cf962c5052fa173accf235c6f75", "TP2": "041430def35ad1e9d4a88bbb441279034875ecb12e74b8dca3724f130e8ddcecc907c0fcd6bbefabd28eca730109faed887f854719dc38bc3a34c0c02e7da4bece", "TP1": "040adc04fa75d2c53c42f87890366109e6e30bdffae71d3db09f25763584a2cebe1f684e0bdfd3ded07c9dcd7d1224651a7de7abc57960d3ec3240c49edcae75e7", "CS1": "0410129557b6852611afa13f28677fbe09b4a0b0a65e7d5236ccced57a8131a2f10f58fe4665779a6de7c1988890f6ca15d29101e6ca5a12c896dadead8ffad742", "CS2": "040a2e532a8d390b03a76e5f782b29ccca0850c25034b374ad2219d41ea5a692f81b38d06c147cb8fc48ab04156a9bb02c4079d8caa847b1c959c2bbb72da6b7c5", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "042282cced10fbda3c7cea8a1fc87607e8df06eac3b4b1b27b132a42ad3285c43c0869d927c893e115e5468f1ca672d305816935b47536a153b0ced7dc790fc4ae", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0413987b0a9484750b7b7326695c840b52cc7e5a9bef58fef03006b2835d0827da03952cf22aef45a3e0d34d8cbc7cf47212eb04b8901c740cc5bb41148e7d8c09", "U": "040c61453bfe32fa93444de8f4c628d7f29d9fe7efc512ac1aa660e983e2c8b5e7234258d9da0043eb959ec24284b4e33f046e40cedb444ec21b3ae9f57b619f2f", "SERVER_OUTPUT": 0, "V": "0409cef6acc9349a7a047d4768fdd3fbabc95ed34be52634f18fe528cb0797df7e068adcb75ae08833c3af43f858338f7d767428a6d0cc240d0dde0bb3c90da124", "Y": "17d1a3fe2488c81fbbc66afafbf4dad223b5b6b0fd254b73f4f68183a59254f6", "X": "1699b2aebe6a0de6e33616d3970cc2efaf39a6ab11a3eced253414a04bbdd268", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 235, "UT": "04175d67163695e9e3ecfe9f715be1930a149fec043b40266b29fddeeb8e10bd9506a5b87aa014b8c2501df7249eccf97693844a98f9c6e9bbb545318029bd1769", "MS2": "01031a18c472c96b644019ace5fcef668c96d4095b342da1845eea3a0033bb36", "MS1": "1f513f526970eff9c9af1565886cb6506228032fedd9160b67849b97ac8f541a", "CLIENT_SECRET": "041391f8bdbee0606d3f065c7f7bc7147c127f5f6ba2851372a90944e69a01fe9311d0505f0950b2c697a70c191aa3343889e883f59561735aad6e3150ea0eac3c"}, {"SS1": "0882368db2214983a694e3f8f05a987c8b6d491369589ff9d7e9ab210232c9c1091e96a8e28616c4c3689bdf84634d1543759e5a84d8742601402ff9c91302c70b07b5a3e13272f1d8f0dcb419be58631b23c8b0ccd0da0a22ab501080a4fbab12236e6e71c0f2967cd221bdbe61419e99a5d7f8562493e6a91e33d202aa959e", "SS2": "02c7fa3fdd2013814d9504251c314b404129af433afbb87d5205a08e0377d8c51262a8b563f35169422a50dd7b820e93827e84256859670995a7896bbd4bdb8c1752a08de3871767ded50a45ec2c7b925ae77e5b4e0c8414b5a66f80df175b6c00f66e9b1eba3581a7306f548a760e40387a6617edfd0a2b9457dcfcdd11c0f8", "DATE": 16610, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1bb6df2d0049d67f53f64c351c583a9ae077d76e83997276becc7e6282200c1607e63fbf3f42049f774809c203a0e69e8f9e421d7ba54f6b3e282e99093a5d69186dc27d53c996fcaa2a409c67d357c4a7c7f4e1f607d53917048576e34bf3061319401b01ff97ca34e03989155fbfd58b93b67c861aabba6e29d2200ebcd6f6", "SEC": "041ad4c659307a9b3a4cfcd4b915f15d1f62290d73dda26e2d6ef4de77788e9e4016029a31009b39ec97aa97799152aa008dd3e9fe725f6279a89ec0688199dfee", "TP2": "0408202e9fad5e60359cba21a92a20f2c85922abc5161c7e33818a4e051e23ae970de9f8a05056ef2a446e7001482cecd86ce4b25c9656346997b127e1d38634f6", "TP1": "040784f1114670c43bf58db4ed19d72c0d6df7ed3ac513f6dc92fb78118b761d601f2b1b198f71394b430ab50adb6258a21df3b195456ed49da65535902d5c0e1f", "CS1": "04059a6264a670a815bb37265d12f96b5b62889b3a1ee96ad0c408199b682e09a701124ffc734d788d5fa3e5e19483cad0a02bafc94e5f32b50366a6c477a84a13", "CS2": "0405135ff851b44fe2c147e85daee2507bd2f05b9367df61aa7f2e9ead3fefb7ae073256ead669c086829659d685d323af8e30ee17eb118a0165fe794c1b9889fd", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041d04901cf068f6cc26ae18283f79f450a56ea1f48c013bc1a10376fb1fe3571420c81ca537db312c30abb469c5d558cf06fdc7602aae356d3d8f77c07659b943", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0414c526997f53c05c0a59ab9220a5435454e5d8197f5ba0cbf08c0ac932e377a81949dabf13d6141dde6f0fee2d5e35d9b73461915f2abd6d8572ae043e30b353", "U": "040110b8d10097679a91fae83d559ad438b1a160a8b8bab1e6b75e56918f2b25a70f43cefdcdcb1ed69f3bed6d37e7b1aa8868d630ea62d72dd58936677b1ef60b", "SERVER_OUTPUT": 0, "V": "04142f7a8152ac83137103d54434de0095099ac2df3a12073641e3deba145a4c930171dac45006fb674975c17a61578748f070d1762c5727ae135f4393249d0d00", "Y": "143e6615af1ed9df83d808a72b69f1cf85af384414199f26ee0ab74c1b4359fb", "X": "0547b179f19b8d99a0a3d64f0823656e7864df031bb926ed8ab09735efd32834", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 236, "UT": "0419668670bbd9e7edfbabd1805bc39e0e7ec6bdfc1223675b19300f37f47a853c0d2d0de04ad004b78fe6fe06f5135ddee6e31bea4c5f815065a26d3a2bdc20ff", "MS2": "0298eaf40bb41ac8a80a53b018795b6d51a318b420a6b9bd14c680ec10060e84", "MS1": "0c7499406fb1bdf5ec2ebe2cfffdae79dbbac9810a6fe9c9f376581164aeeab9", "CLIENT_SECRET": "04163ea9a36b3bfd2caf5f164eeac17a8d53eca90ea22c3a4627ec9d2f4f6e39f314932b668a2f1efeabdecf8a3c46b5211399ed77d0f3b82bc6ed967f4623d2f5"}, {"SS1": "1d10c177fbe5db861560547c8ad092fd95ead4a5cafc1d91df94e994cd99ae501173211a51e2abbd8e33f2beb633b58c2808d028445b5e9099c742d4b314563d0a596bac0da0e30aeb43a8fd14ed96cef799f3559f9193bf81918d1b58429a4810e9a0b27866505edba9858c050066ddaf7a9ad3443aa95cb84dcb2cd8b52e22", "SS2": "061b173e8acb99ba7dc4614dcb0e6f411658639dc32bc75fe5a7205a5f6689700ecc5935d1d2cd9b8d7eb7dc78cb216697dd1aafb1f796104db73ba96213f9b9084eda56459be196d18e8908abbd4f296108239410eb1e9dd8ab0facff01626919a38841c6934dd3c23261ed77dc6a4382b71e9056dd736887b5df72e2400650", "DATE": 16611, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "15fce984cd9202b53c7385e1faa1183d2a793a73abdf53d33f9fc74613e8803a1dc6247c73fe2919368d4a064bcb086b822e995791df0e3f2349e5122c8ba47f1814b098d30ad3f5c55f85121c18115616d7cd2e1dee50562711cbf6ecd1503e15d362e0fdb479e1a7bd52515cddab836eb66970d20ce6c2ed526f5f8ce64f8c", "SEC": "0416c9749d6aafbc116431fb239f58589a3afa7ad571b31c787ca4a74ee7a34fa009c4e87fd1287d76da7db1ea058fd2e078077f2e74c5529feb4b38400651e559", "TP2": "041995d5c8efc8580f2325a66258b6be90fd70a0ac66cb42ae4940ad23020df6b7091a6c769114db3afb2f78178529f145bb238325d11cefa5120257c1aad6e456", "TP1": "04029e48b19d17b41fdbc3f338e0519b7020e1b298da57b6e1236e3785c7487c882344027be8d4e71046edf7d7edd3f0356f5fc6bb6d85cfe4db5c5a1231171b68", "CS1": "0420eb98ecbd71bcc113cc570b855f48e213d4c6afcc895faa3a95cdc8fa2263ca020614e82f9bab654069753bd0f000a5033711f6d2a1bd026204399ec9854334", "CS2": "041c9f323f1d514ce006844c8dcf9ace5b36e870cf9d4c47d67804cb9004f9e9a214bfa2e2b2ba4c894a89fc10039cfd52f0d9199bf0acbda9c30166e8a0ab395d", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040c763c602190ec3f577bcec924ac77052a9a431f33684a33e7e292f6adc51ba6129357f3731354ae1446e072b2c134fe8e74d3d5f4699d257b470c9a68a8e8d7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0419c9df9a5eab5dadee50ec6ae8cf69abd32b43a02de5ad650c2b9e83a7f1a9120db71c65f4749ce682acb5ccd78893e2ad83f5216c1e4f980a8c18280f2e09da", "U": "041bbd7cbf5e4ea17c4f26a6662fdec2cce60b67360361b7f1ce1a082d167221e323deec50fdf698bd6310cba9c5c45c769e11cfd1aed33ba9c7516b221b193097", "SERVER_OUTPUT": 0, "V": "04215fd61c472209c3d47b152d1ee14e33be20129fa765afbd82d9de0a62ffe467164767e7c56a13f968e68660a77ca26d8b75ebedba63d8e99a5f1140402fd7a3", "Y": "0902fdb81bf6245abcd785ded1035ec0993b9be6c581ffa44bc5c9c1418105e1", "X": "1ac98e503dd0625aadea1887fa61efda88a31d698bace1f714bc7adda8d8a3b1", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 237, "UT": "040cfd736712b7583fef06ea9c216d4ac6c8462bf3dfd4076f042434a1ea584f7d1159540ff8c1ddfa0df4e1f0d36ea092d5e5bc22e42c144d0f57504cd4b066d0", "MS2": "1248d21088d7c7c31950f3b9e03678200b4478eede73b3e9ffbc186dc97bf9f2", "MS1": "12ec7693b752cc117119314a8c2a3e8d11475d6e611e197250324f9040f1ae0f", "CLIENT_SECRET": "041a2a01969107ae0db5ba20e2b59ab50094d80265f8e8b793880430f5d74222c918cb66e8af95930cc3184ad8922fffe4b922a7c1ab0794e5e8092eea9671a414"}, {"SS1": "0ab139b15780dcea0c80f370ed7a0dc0ac271d1a433c04db1e508b2c7935db611a0b8a14317a0efe858710ec4b1a694ef882e1efe8aa00591667fc5f1bbbeb9b217d95abd578a27c6f51bccee112de440b86f38e680f1e14288d1c62e89f7d861d208570ad8354859636b17202c361a63ca3924038b44f2d784964e84bdb0982", "SS2": "0e9db6803baa04f764857e15719f012492c31e1947aa0603d30dd3a890e1c3f71f24410dddb66ddf432646a976c370a5e924b4796cde61255a2099ef62101cb00237664652ab5386268fb98bccdea21be3aa79a21ddcefc2ab4ac5a3336c793c0b7bed45aa944ada0f5e7d39f9b3ec441ea5e772172f5d6656654100de15db77", "DATE": 16612, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1389aaeb9f3873b0c33eeec377374886764f54367b3da7dffb7d61c3cffb22d71845730e18344978a533f424ebcfd33f7425f8c003bdcadce26fc534bd32b27b14eeb48c31e690fefa76b22e630c3dc3cae9fea9a599495850c188ab7a91be9301e00331947c421da829b0686ffba6b54236f352c252f0cdd4f7015f326f3f2a", "SEC": "040715f68b99adab36d944aae428279d39a760e917a7306f0b8cea4b82503fcb4b111c032b1fa72f9aa5311619ce6d3b6a4b0a77000efe0c00dfbc3332b22d0928", "TP2": "040c338d5eca93c7f7e537ac0044936336b4420583259a9dabf4c01c5c16185e8211393a1926a795355314c29d129824dd714a0ca3839b14ded1f27c452904f579", "TP1": "040531c30076dcce8d6df04d04dd774e24a4249e37c873a0fdbd2580ef06b88ec61a03976a838378ce4e55e3c1a057edad2eae3c3cc1afe281a1debb4bf4f251da", "CS1": "042224f978bbb93226b730d3bb6c4babd876c486544149f7f1cae19f7b692719961a9470033750ba8332e63d8f2f15003a91003ab9fa9498c35aaffa5c49208aa4", "CS2": "0400c443bd24e58edeaf5a34c70b4bff8678b193cf668db0712436760f93778cef137dfa5968d00f380def5eac06c7f221b1f4518f00fe7f894b64af268d2cae62", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041192caf48e59682230007e12e45e8657520723a69cf1535d65f8a2316ed3002614508a7af7f0a86f8501ee8274e409b041d25ae0120ec945c92307183adbfc86", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "04229203375bf825b99e67db6a1db2dddb5b095d25e889406a409677bfe2afb669150d14151f3ca74a7602d5385341bef8b6d4a79d14e817f4805fc3ca1d303368", "U": "040625454cf64f3a230491058230c013566d9b8228c93a0a7ed5d1e7193ce0d0301d1c0de4aeb17d526bc982e4af486c377b1209a657921d12d5d5df02adaedd07", "SERVER_OUTPUT": 0, "V": "040169292e4a0cc34d6863df558167d2f655e0c58082e47d82529b9ffc0c5e35b410f52595ccfd36bd0d904b3e44b520419d76e886a0d947692417eccdf5fe382a", "Y": "1d19950fa923ece9e90f4de358671b79d452e14fedbb463d5d2786cd22a5b24a", "X": "226cfb94a3dccf7f3b991cfc96a5c9ae5b51a7ccbae9fdbe19ba59e8963766a5", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 238, "UT": "042296fba268ecc9ca7429a5ca60d2e56aaefc84b3b00e4b3d90edb0f1438c5ea81e0b3f6516cdd405ca25c2688d4a1323626e7f23fea554af9af5e6b4734328bd", "MS2": "0196d2db12b012bc8bbbc3ef89c3072b58e8f64f6693cce8debb9ede91e6e203", "MS1": "0c54aad6a52dfc9391827a8b7bc9817dc7b09e02c2b9d128498a77d36d2fc427", "CLIENT_SECRET": "041ef77f47b64a227a2c702edcc16f50c419c94373b7a74ffc4d7144eab6141a23085561b6dd5f322807565d1cd7672db2fe496835a97603e2c3fe65f57d320670"}, {"SS1": "0f4eb28392f7936c6aa50469b5317fa76de314c4749b852d320ff9ac118c890716a4cf04aa05e73bbd97161c21e99774c74e9d05eda9965ab04845bd16b23ed0062296f4c52bf670464696618f3d5dc1f4a4befd8882945ee1f27f097f8d945b133564eaf3251ce8c98ba9fa0a877e83cc502fabf99f32e42d7d1415b1658e7e", "SS2": "1781f9a5560d77ae7335b941d06f91e4590013a84792307b06ec8eceb8d5a7cc0d456affe26f05bea6d2cdd9b9fc4f8738b71bf67918632781f8c0893763da6d221da50ef476c1e6a65dc5653b5218237dfb1d94a9e2665a01568f1d187c826719bbd6ae05b9e95b94919035cc0377e48eca155cd3a435e32e4fbea0972793ab", "DATE": 16613, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "2000838728b9e4dd73c5308caa61559ddb34daf2ade314ada2bb24187bc1e00123460ed6b481336838aff7a64edb70c7fd0d60146aa400dc03bb0ab7c6211b4e1b230bb1409bea5c108e0c72f0746c6a490457c18f240d8d7513a6be002905fa0b93ab13d8c612a2c8dafd63df0b1cffa27f68a7c96b1d5d20ca585f382134e3", "SEC": "0407a20b5aab29e4a8366dc5c013a4e7ab5816c7a026d6f20e97576284e9a136b901019d6ac6ca8db4604be016d2c41bd4f4021588ee31fc7298415459e83941de", "TP2": "040eda0d4e50480cf12d4efbfc117fc9ef07472da33372a8e9c8fa34d32ee225f320833a5e96cf5acac507ae0bf0fe6edcaff74ebd1aa63bf49c440ed1bfaab666", "TP1": "04085d1db05c30cbdb07b809e0ab4b9bf0a53f3de2f3847fe20c270b540d0e2e060421366f21323e66465388c74935c02bfff63e6d1a4fb45f49fc6ef6c3d83d1d", "CS1": "040feb4e184a902faa25c8730ebd97e1eba5366efbece4620f24e64c4e5a3f5adc15490efa69e58a69cc85ace24c532f28508f2997f4eb15032c03b26b3304e32f", "CS2": "0400ee5701628b18006a9e9b76712253562b6f60de53a2f60fddda897cf14bba831234fb48797c07f9f5fabe273564104b02a3ffec0ae6678590a5041d7efa19ed", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "042039c6f7bfd7ac8573a8c5a72c3e2a7b5edc88ff8fedf1f5047c041d905b95e5212d0fa20e01e276f61173d2e54d04b22e9fd94cb105396ee6be364aec87fe78", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "04204b60637e0fad275ae4a792eecf7e3fe9020f6bb91ec2b40827a43dc237930a22bb2eab512654283ccd8ec5e7d8481341b9be03226ca5fa4468d407aa315689", "U": "04202a77e58181b9a995b575e04e9603dcea74c0388e092a0dc4c1934570275865146f70df79110b83e3f650eab971eab386e1dfbe18f2ce960ec3b4c4918e9625", "SERVER_OUTPUT": 0, "V": "041e809f5b2c5d9a568116da655168e4d12b175e15e4372ca781542f3b98181acb1207069e269163e4686b62fd7f5b38238d5282512f78f57c98594f9367199373", "Y": "0a35986aad319855fead7c4fedb6c6c76889fe99d225e46f354e9804bdddb766", "X": "0354a3efce2a17e22204ae800ff77a99265486c8f43bd908a171bf8ad7cd3796", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 239, "UT": "04152efc7906763e071f589aec9d85cf8e7fb9caaf2dc8ad305dd5f2b82860b91220f535113b2f2fedabf32ff481d4cbe96a673e1b1389f01c25900fa965b006bc", "MS2": "02d19236105a827233f03829bc495dc26efa2f17ae77ecfe3e2624b216ebed90", "MS1": "1c685cae5e2de229828930e54f2dae81a464698f326ddefcafd1e7e9f490ff49", "CLIENT_SECRET": "04164b6d346ebafe551d8fb1e56d038971c8291adb19118bafde85693354be411b23114ea465006689c5db6267af12d6399a805f106c667c93bcb804a27aeb84dc"}, {"SS1": "18d9873620b1b471b1ff24047b1295e44c14324cc624e61afed86061a6805a6411dfdff015f59585b999a4e4044277a14238fce5850b15fa0a39362536285169039c0b1bf92832a4a71f72212c503a26d15125d5962e16bd07cf5b19e537c0860b79f7913d096b28f9e3ae4a2ebfbb6e9657bb2d00fd90859d35b79f53b7e6a2", "SS2": "06053de7859dfc178b1953261d4b1b34fe586df86bbc5bc31c8896dabbd052890fb0878dbeb29e004c2ce577bc1422d37375bcf0e26e609e7879ecd02a9bbd2f117b10149be0b04c861b4853cbed5f6c9eedfbda009554049f5cb8d9deed959f1e888b7e4847eac035f355e616ddf589fa215d03c0d8c3471ed0765f167b864b", "DATE": 16614, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0bc0f25100f82748d1d1f6f94e0ce2421d5326bc42d7ad9804e40d222e99732e145c42f66d09d505680627071b81b703ae499513d19ef85bb66a2bf44279e6be15744b10a2d72950f432f74739b303c8ce320fc14ade2b34ceead1516690deab1e08500b6f51f5d2a95d39bfa07daf1fbdfa70b4624e5fd517c8234eec5436cd", "SEC": "040b53d1ab7058354d446eb29642671bb23da7fa7dcb5d56b1a0edca186c6df56a1ad3d8c1073cbea8714a2d4346cbfc321551efaefa51ff8e4ae801444712ab06", "TP2": "040f91e7253e9c5826854f68064bb6b8c29206fc870e52e0787440625b05ab3327007fc27860287a10b121a9e01ff1167327a26b2d9128e782985f514cbb87ccd3", "TP1": "0423783c35db5d4c256b6622c4dd1614278f7402a44bc0606e0edc32d11e9c63781f27c22610fb0c5e020f9315131689ca50c1f2cb21837643805c7d10a760eb8a", "CS1": "040c7ecf5001c0c84cef78a8df60a22366eced9d372bc21c758760c4d8ce595136153bb7df11f6a205ba8dc1d57eb18645a7286ed1b3644be14e046909489b8e21", "CS2": "040c7590bbfd806ec685c757e9b7b8afc344b1eeba4ccb2ae6ae70f3b3a745dbea0800f8b1ffaca3a0029f37e15ee5c7ac2e9a69a5c6d935ddd3d0d69b4b2453ed", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "0410b734cf147bbef9f48c783e52acfd854738a5e5062216dcf6013bc1bc69b89f1b2559c51067e84d0d2bcaf7a9ec6232c88d43c7b18c53fe87fa94870295b46b", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "04142f000a58dd96d59f5e57424ca76075c5a9bdbb0b559dc15dcafaeb17f2c72d223da411d0a28a84451bc71a6edede6db1c0e8afe73f475754e3266c72b54781", "U": "040288dda67af046a17743e252999b39253d7639581301b1e09afae76fef9468b822515c176093c2dff37ebf9b9b7d874ca5c5c3ec66c95a14ea4b0d35f6a60d9f", "SERVER_OUTPUT": 0, "V": "040402fe6a6d4a0e862ec6492a767c69fc6ec20a053d4c06e2e62dff609150d03f12b6bfe097cf0f022da6d999ca7cae02d2f91b91b0dee4c99d9f190d833c526f", "Y": "0dcd082a33e729b4a3ec512acbf3245172861e571b94104b680d9941419703be", "X": "049c65d7fd03aa44b070d0f127d8373b7adbb34dd2b02b931777b8a90ccfcc8b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 240, "UT": "040395396d6b52392133e5333c01319bd6e45eaaa26b7ef5ebb45f18aa07b094d506bd411f26450139b529fd5eb707a2a8e8298bb2eedfb997d9879a9e0c9583b6", "MS2": "004c43c8e36314249dab551808bc8d29072ff6434be6095b3d8da38ed7cd243a", "MS1": "218d1de773c2b6c6b593d4adb393919c5a5c11658ac280b32dfdc71fa8fd2733", "CLIENT_SECRET": "040f169bacf80d279f78b20b0b525c0c73f0fa22cc2da018ecd562ba7ff41b466503e3c809aaf24ce378fd290a244a4086d19f5fb72cdb49f5624771507921bb9e"}, {"SS1": "0b276b59e3ef979e442a49d8c76f7a1deb9409ab22bdad71628d8e52c5ff47dc0b78d60d766c1037ec479ee1df318cfb3349c8e27f4dd3b4c41648098668b4eb0af6b4c5a1c1bfc6cd0568b3436032df8c0a8650ebbcadb463e0b6a7363d44580a1672ece31693ade3386cbb29508196dcfcff3b64c8d833abbd9fcf47bb401e", "SS2": "1ab1d00ef6cdfb4d72026559d0ee51dc240f13910484b002542d2b4598ddf858056d31f185cc8416ef0f816ca88fc5a8a7ea757e17b9c3c66ba239021ff95c95109ee4f78ff45f5952eb705a8b6098bfed529fabf2a0ca46538960e1b54638cc184e22cb1bce5fcbd13c711e33a9d585813f538a3c2318f154768ded3ade93f4", "DATE": 16615, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1e4fe96785b573d32c80cc03e0970c7e90366e057afbc196765c960b04ef1fa606db9b4df89381e3643ccd8e1478a6356fd61b9e532ffd10f7253085376633541d9e350cf7a950c1e179e1398295a3890cf4561322cbfbab0b956c89a35b02ef14f6908831792a7898dfc5ec935bde6ae72ee9aabe3f274bbdc3f1035d8ed7b3", "SEC": "0402a7c248526fad88789e922a521fc04fc9068df042455e622254a34bd5ade7af1d52fd93a15cbc72a0be3fe31cbd193da2e21ca8d403bf923fcba25bd7944bf7", "TP2": "0414307d0dc9d571b4ae976f8874d82b9aff67c34252fc9aba5c292dfe10d05a9b1fe523cde80c2e6536457cc46018fcd86cb6ac288eb059e0c0c80a218cfc6a88", "TP1": "04233de844d6d26755f379a34a23d8a4dac284b81e75a3a32917598e8adbaaffb6144f07504b7980b47f956bc970368ada1df327139e3dc0a71d24997070263727", "CS1": "04070641a4970ef15def4cc5e64ec797d2d98d1b39d1bb895639aa2d4108c905f0031d046aeae84031f05fb6e584057710e3727dc4b49038e4a53e6e15b9826f08", "CS2": "041caa9df15f75eb3ed840387f61d1f917cba3ccac06d02257923d8933ccdc5acd131b67807972f3861710e153e53f0bb7e8e9bc01131f0412c7230b1de3b47475", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041198301586bead2a4ee2af83a4c1638a885b1349425097e86d06b726194fbcc0164b4cbae8272fdd515792b751383e56555819914ad709e71e693748cbc162ef", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0422b8bd877ae1ee725f103f64abe39c633e13c6c6268c98192316e2a13c9e56ad0e7eca66bd5fb91e1e923a2a3dfe71f489d166d4dca9eae21b3d1f79a0607688", "U": "04051f3609967c6c7e84dd7872ee812c5f420480d6f4fb76bb9b0e841455357f20171f45c42bb3d7ddc482d98b0173c81dab4b40e772c9239eb1de8887cd5efed3", "SERVER_OUTPUT": 0, "V": "0403fa06fea9a4a70b743f49ac3dcd69ca99319ffaea0dadf208cd80f81d51650813ec21fc3714325b796e37702d7aefa7eec10a6ece6572203c690eb1e5da327b", "Y": "211d03cfc23496727a551410c2a84a1755d688e4b557d6630bea84896cef90d3", "X": "06ab4bf3865cc8146cbad56a5a240961ebb7c176ec93916a518d9d3f6955cf18", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 241, "UT": "041cf2732f10ed023312ccecc111c77fe2d74148b09ff4f75d7ab284a381be519b0ad0e425868f5c015a732cf7657690fbdbaa18ff92c27407d0698da2363fe987", "MS2": "09bcf1d559f6d9e9bdeb61d1b442ae276fd41442514f86a3bee8ce9b9c3f74cd", "MS1": "0825dfe882cd9c34bc3fd9dca7d906ff9241e82883f9034a3d7db9d6e27c59e8", "CLIENT_SECRET": "0422b39b54e813a06a6f8fa642429a4debde4205033c3da91146a61ef5c60a259f01223203f2e940eaef84278aec975b1a714112b1bccac27bf51a208bc79d0d1a"}, {"SS1": "150827b5363eb02c2e148e08076055e42e36a0ceef945412c050ccb098832133031502af06b2f09fd82c2ab5e392a3b16edf49677ef3de56621aaefa2d33cccc0597afc5ee96672a33c75dd435f1e8fd0d126e55770122626341821c7a91e1de17ae543b6abd46bbab78c1dfc54e5d27092b8e419bb88e97f3539fafbbf16a3d", "SS2": "11d61aa5293417252875d1f4c174240a1e75025a02edddc41f2eb017c3fe29830c69d9fe52d0b17ff4556490c2f47b54df785fec09dd6c033c8107d2f71bac3612fd3ba247bcb48804d6cc0e46bd5f79c6ed856d76c2feb0d3ccc6c9b437f1ff1b6df82d84351ac3516630a68eacb5bce76a0b6db7ae6df2e448102d788e6fb6", "DATE": 16616, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "069dadb22aabdb3b38487cf955a7c09a740e4c827c33b1a0c070322710284d78043095c9f1ec24cfdb434f9c160e5403a1c4aca3d435638daa9772c435f032ca0254753f853bb2181597a9ad8c3c30e651793d035d4fce5c310807566b72ac060398145b14ee7809ddb7eac0e9069795b2576bb7a92a6dc422c67db1480c1fb6", "SEC": "040fadda782fb0affd0ec299969663e76bec1ec15f0459215040f22a0c2d332bb82019fcd46b5b8350e51c126afb085f928942643fd436a85bf270797d1c7c3408", "TP2": "0402001f0cdbf3eaa68ceb6d2c21a54448a4f802e1ae979014c21eaa58cc46d63401981ee2a6de952fe119c3eee77254f2283504a631ba15e9770ba842b4aaec84", "TP1": "04233e46afd751951f77ffe98d87b86ce89b423c9d709b969206436f9bc93e1da2195b159e21d165a7954b67701a2bf16428a0db7ed9a753cf86612b5f996512b7", "CS1": "0412d3f057026bf3536d8df23e4e4f224e45d53cc69ca112b9a26c598053972f500ff979765eee286365af610336310cc9a00fb67860f4dd75f64f6bac3473da20", "CS2": "040eda3547c4a04304938eb05b2b1b0a6ccc6203b5f04e77eeed11dde29b1b999a00cc9a31ae7afaab985f75b28b4a49897e5a1d5f031326b28152038ac273c12f", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "0422c2ada3e6f0411f85b22b29a82aa957692f0d785d06306ca65b5f24c3b6bde81c1962937716e3980c2ebd34502333d46a4dca499a19d0c4eeefbc22c0e5c81f", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0410bb93a3d654c1cf716a22ab474e959a38d5fe2bceff5b4bff9d07cb41fbdb3a05d5e6bf85ff40d94d71ea9fcd9df3ff8587d4374c9ed92f194a30cd10c06a84", "U": "0409f1d2f9e2d57f2e6cf4efcf9fda298c2da3dade4d5f6549e844554c94c237710b5f980b36f134a71f8e687596ef42a2dc7893772ac2baec2539664bfeaa7396", "SERVER_OUTPUT": 0, "V": "04231b0aeb98a0d2182b3fb92afdf12cf6719509319aa4217552f3f02932240b460a72a746d3aebbf3ad1711ad75913b1a83a737f40e2783e3f518fdeb303df329", "Y": "1e9c1e5e858ef0cb461550b213d46933da9920ee7991c6ab3269ece841e22a17", "X": "0208490e938efdc96977634a2529908010fac7563481f35a508f784aafc640aa", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 242, "UT": "041be484e8664a7711b576d9b5816abd929df5530c7faa828acb89ad97e9aa78000edf81ca73e61cf7dba358b2f78dde2707539ff38ea555297e5e3c06d762230d", "MS2": "05002c15ce11161773326569a575f6bc7ab159c1855a78b8634e8e8f666470e8", "MS1": "0a71ac1d49c6fb793510ca2b7e081cc599fa7bfc9467668626a629847ed4b59e", "CLIENT_SECRET": "0410b6b97423dafdf87100e5fcfa32611b11809307da5af3e8eb1c2a00ba966f6d1d6ba2c9cf8adde0f43a92b169ad1eb89e346e7c98d5d61d7cc75bc9d1c3c7b0"}, {"SS1": "2082ff96e8306d2ffe9960524304a9383d59a696a4ca4be567339f5b5a57502811f20aff8d165f1548cfc0a386444bee708c81dd1dae409cf1d9185558f7a54d1642e9317301492acc0e435ba1e8056445680b94b77b0e56d79c58243ee56262211f73ffcd78c55d6942197fdb069f6b9a56043736df2b0154c9c84ad1465b1b", "SS2": "0e7bd11fe5ded7da27aff73a13082adfbdd337891a5638d5ce4bb67c78ea55f60733e3efa74232938e5ed6ffb701a8f28877413bcf54c38da8840b090719e7fa00898919069dc6f566fa217439ce4d7fc3b7b3f2375c6ab7dea0ac84a3c355f71fa6c8b6ae7ca926ba40e76be60669aba2a4d21e9b3fecf5a04fa10b9c10846a", "DATE": 16617, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "013b46910dfef57ebb8c3308a266b70d4ac4bd6d5940128262e4a94a9ea651d822e1ae673ceb6108867aff7d5b4141c20b875b9574afec56525bea54a3b3656b1a7f9210fe9a7d20ee8aa75fb1bf485b863bf7e3921580caf7fd126dcd527f090bb5d0b7cda2ecdcec2dd07f36fcf62db443b328052375defcb05b0a29159a9c", "SEC": "04031ca6801cd084788b8c0f10eccc620ccc95d3c337fa810af6dec1817f33f2971b4b039164fd6b9c1ac7e295139e792fbe6e2b6a509e844395d657e2bb953aa6", "TP2": "041bdf850ad5b194bd0ec3afc00881a10a31a25b6864f3f46c44e657a884f70c2a09994788f5bd9262ba30697f5c4b0ceaf9319d28de2513132c109301f9dff7b7", "TP1": "04209ba7db45abb4437887ad86d4ae89892e6efa12a16c733d76939aea085acd80111e866eb07d961ac631d0a7b85970d7923553a132fa1949c3279c29a242513a", "CS1": "040b42889174373adc0054b0f2786ae7dbac66164f4a3a8da167b6bea5ce21af6d040b793c8229f32f682cd1e343b07e86f674263bf17760ddf7064a94d98b4101", "CS2": "0403922d8c7f53da9079a46e699f184c938cdaa1f450d3f7cb5b655e2e5e6102d70c08189ea0081afa5edc99537670622cd2a65d3e199c8e119ca7c653b4e0e715", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04053c83e514b53c634daade4a9fe5d1f85a7cb63d458258d23eada66db83c012a18ab987a7d455ff17e5b0a404b2a4770265035ae7026f8baf8a6da91121c6878", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "041a10ad6b8526d3f3569f1c28ef3beec7d7f481932bbf5603a5211a617196362505cc1887371a617fa5e2bc3d367516b263d3bc7cc9a0e7b6c5b22bd50bfe818f", "U": "040c5fe0c17ce60f1ea783140c6050472ebeef606bf5852a78faffc68f8ff2859803bfb90e7b961ebfb3bb63661e139295f95d1949ade311ff1ebcae92df55bbb6", "SERVER_OUTPUT": 0, "V": "04132b831a92d8ce73afb7df601093245d7e8312b24b3448b27ec7523040282bca0b5e78ecece158f8dd8b54210b259437cbbab07dd039196760ca8d96dfc01893", "Y": "11be6c1ab2261b08add78764f0dd7db2b1897d8c72080c0194dfde3e8957a4b6", "X": "0ffa390ee7ce608d8a87a6ffd5dd7be27a41dde1050a7f774a08ecea3ddcb1ee", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 243, "UT": "0416cdb9fd2b7565835c64114d654e3c61576d3c709cd36e64e249cbb13fa6d7d721b89927295c139fe9f11ab336dce39b88570924f479e8199ed13377a1857239", "MS2": "050be0f35cba9de14f7f891300c54169af00f9f21e3d36e1768abff4ea6de1dd", "MS1": "1f92f854bdc493cf7f176d6cb846f37438eefe34a52e54e8fac1209b37bcbad6", "CLIENT_SECRET": "04217c88f1898cd03430a411de33d3501bdbae6358476563e7061ee4c2d21a72791062a9a87cb8f9ca28f912396f3d55d6f7fa4de2bd453c94d2c0b2b13d65c800"}, {"SS1": "1d471d7523f3cd66ece800ff45d111f88f184fda86f649fc23758df9c3d09e9f0472a1340494d8ff682dfbeedcf5b491e58e1f18dbcdae6ade78b0712751ffb40741953c9764b0aaf3477d959b0be02079f60cf82b7b451a2794a8d450440de5135705867df0b5fe5001dc013846de9892868d7644e22b5ad4c377df2a62966b", "SS2": "14f4369d5383f7b5d3ac50f96d274eb0179f0dd62adf8a7f4c64350bacf1db9a14afe9b58584a289379c3b77b7779b5534906106b998c673ccfb1c3fbf24de0a16ff4f422ba24a186679e966b5f0ed128a1f67c39ae857e55ce03fb324c6c25709772f6e2e7c19acb4863f2c874d289b2c112b23e00c12bd7df5ac2e995ee0c5", "DATE": 16618, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "17d1fa3511e9d4b45e59e43ae051c71ac629a4a327b3c984180bb50ec0314b3f126d0c059e81a86338cf61412c2fff0253a821083c28b5a1838f46dc0c9d7df71c60d8250348446206f2189c33698aba680f477d2b62874dac91a9be97c943e911b091762013b97c812af72b5f45f799eaa3206f7db3d2172f88412adb79fbd0", "SEC": "04223d0abc381b608598b36ea78aabd0318bbd3c308242ecd11e8d7f66021916f217aaf8af3bbc598d64b3185d3bb955336c876a71736aa1f73ead116a35664807", "TP2": "040b7e36d791d001cf4348f9f34a883045918f78354a37c75e2089923a8f0f7d820af59565d3a529111220373f3d45713fbaab3eccf8b8ffa927e23d9af064f93d", "TP1": "042219184ece5917973d0f6c66cf8a1eba956f1943de58cda4cdfea7a2738a6cde0badad760f3aa2b03ac1a2be81a2f4207d602a51888f77bd9db0790fb9daaa21", "CS1": "0421bffc189baa05819c9c111c5b75b265efa5e9311d758caa55cbad1027c061df1e07e2b015c69f17413ec5f135c3b8041d125d2afa96189c099824f9f9aa4ac2", "CS2": "04141e274bb11faaed7bfb33978a629736650e2107b73a2e647ba51e29de8bd59018677bcc4601dd7565bcf91dfa68d87d8434de00e3cb18c7fccf03b7b9ff1ea2", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04202172aab712bfb24a35985a952136ff67bc5495783f508e7d87984ccfe8b76811de8eb88d4680e23479e45a091da77998b88e638c973d367ebc7d8b32e7e053", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0407c305c62c53950912bb19797a27d5a6aa63c50ea55c4abab6f95585da2e35391910eb01d4fc1eb8d05c7a9923c428376fd15fa2e03b5c9c5b85e1bc9159da40", "U": "040771e1f2993bc84568c1c2d3de1cc5c800362dd6fe239990e21f35f311758b7f182fc09b7bba64e3412ac2874bbf80af30a234b53d4878ae8d3677e2c1ccc7fe", "SERVER_OUTPUT": 0, "V": "041dd568a88607475b5e10422ccd2288f5c71a58a323e1f3ae09514ab370b3ac6210f587ee8c159d910aeccadfbd905bf153c9b83d51fc5555bcd12cfebbbfe84e", "Y": "1ded76079e9e8fb6fcba7384b92d4e1090dce6474776346b7ae13a3d2da68667", "X": "0838dce291915d91ba1602c1502496a9cc2ec602ebb015c66b3dec8d444d6ec2", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 244, "UT": "041bb0771d4266f7a1113485a95b5e28c85a06d932ca39847bc224ad6b2887b6cb0b53386f270fcc25457898414af00afb556b7375afb8e727bd94436876ee5886", "MS2": "1626d1d0f17022085794170e0691321cb379151db2422f603e2147431d03be65", "MS1": "1aa259e0b3aeccd2464a2af32e32c1730c7175609903fbfb8c354196716ec201", "CLIENT_SECRET": "040c0872d0cdfb9b3c0a2db0322ed1098fae286006cf4cf6aa33774b5bcec37b3e0c64493ceb7cb6279f515535f93326831e719ef1a8754ae2f6286ffc5a53d624"}, {"SS1": "0d023335f942690977a73e626c2049a4a3fffa015cc6c3c45c027360a6d41891005433ea3dc145a323c2fe866c97b26123cbb5c766746e137fb9abdd632376b608fc240d179d492e5de65d66024f88384aaeed0e87a67cd4644e23fa0c4cebcd1f0772ab0bc3cd70eb61f1fe3bd56d63d229e24810fb8d6a5b6e305e4500174b", "SS2": "094ce744fe0509a2b5457df8617f88190f6d3e9e1806bb7ed68e736c7b452c530e08539c763f735b8c7ec0865006237976688e816317b931466409695068b7380add100624ce1d5339aba0c71e4f30381b03daede1a4c4ece49bc1aa496c8d320ad022958f4ead641ad1768db693077d8a05fe600592e770e2d7b8e495125b73", "DATE": 16619, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0561b18d1519dc77a6a45f7f499cee7377f311f224097acbbb1597a05d46551204cd2a44d6e28b6dcf6c41df7703001e62bee56697e12f1e6dfffb3ba4a3e59602b12a8ca4c9fc22534e570ff8980f6b7148b8d33eccee74a03e9fb5333f4eb516c7287904c9d66cf0021238d9e2af6e21f5ae5432ae5e70743fdf6615f51412", "SEC": "0413326fd4a6eac98e78161636df46879ab2508591880aff6eb368fd4b86e3f8e008ef591141e7432feabef37a8091f56464799df811488bb013a29308dd46da98", "TP2": "0416837e8116e5bcb053b87e720ad787de5415eac5f59c9b5a1cf5aa475761217706997331f13e2dc7426a84ae37e4956817f88bb28258201dc68215f36df2dd2b", "TP1": "040138f05e8fac390b901ee40aadbe45c2b3772241517c18df22ff14f9ecaf80721a3baa40769daa2e2f17bdf00c14963ff31d529f616eef9632b075f1d8801e02", "CS1": "041a82a30558ebb54e14e193b1c80ceb55df84d5dd4f2f0d69ffd1a4bd3dde620715e681edf4518fe502f7c59ea51cd6e140274beca33baa9bac3fa3af83149802", "CS2": "041394bfee5c53ed348bf007657d70e6f9f7f937b8129e04d75e559a35ffa274d502e1a073a9975bc4a687f6862a2519bdbacdf21800f301fbc148c66204ffcb8e", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "0412e9b170ece824a450d38024b76c359e9625ac71975eff2f539183e65f0bd1bf0701e97a74b1e83089eb1928138a04a8cc988f747ea13b004269287549178e91", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0404a1fe9090ae1c803d5de75545887b08e523d3d7060c571f362b99a7d3f1027d18dca74b7dc087237a660386916dfc450bad88ef02e66292ec3da90514a75160", "U": "0416a14508d1c4a88529694d74a46daecb1bfe923cc5641db75a59766b7f9edfde11e879932077e9ae30eecce422b859049e893da3f63e7f72f72a6e64d9e762b8", "SERVER_OUTPUT": 0, "V": "041f57792ebfb0e0a36fe305e11e92f16bc790f29a44f3107fa370015934bea5e122310940ded00520b4ee3cf36bd4e3468d0e6572a490680d6289be8b23f4ad94", "Y": "032166ad772bf15e2af96eb6b12913927d8e025c28faef6d97a03990c725f8a4", "X": "1a0949edc3d2f2cb5c7d135ba2b7dc7c05c2cca3719343e65495eb52dd0c2d29", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 245, "UT": "04154692a71309fd6f1e4dc0e96b31c35351ff114020f2cd276af0e3cf98301c4b04e368adea8f361e22b489f48fe16cd3fe4db9ad814e11f944883fe72fb4e5d9", "MS2": "00310c3754bdf501f599ab6919e3e768ab6cb31f3cd194e38352d55c2e96006e", "MS1": "0bd92826d363c5af7d398883a78dd551a9f115cd4598e9c9f2ca17a626356f57", "CLIENT_SECRET": "040594b0ccfa07a9578aa4c0b307f9e2c87f89e21cb807c70c2100126fdae853d2206c5fbab335982c22e164353bd2774aeaf75d78370946cece2fcd6476283cf0"}, {"SS1": "1b656d3753a5de58e8c10671904461779d36bbeada3cbda8ddc2237d2d282978206b66ea9eec5804ae6d85b2b2de4da6f1880bbeb429ba4224494d05029e78971f071790f8c4daa62fae31aca286071e9e0ac42a0675fcb7252ae711c020996b1ab29cf457076b48e973e2c6f2bc5d832ebcc026748f0c45e7850606ee3b8f92", "SS2": "145a4e511f5dad7ad8c4c6d4792abd3a030be6225fdf684496fad654533556e50238cda16378eb24327470dc80a1ebca80e73dbcb906a3ea6ba5952af56839a02141d9c6a2981260a80e7e5b4f13f283971ea2580fcb01960cd2c3f21d5e341209b14b26455a5b5bbfe66a8d92fb9d4ebe9551b20b978a98d11f6baf94823e21", "DATE": 16620, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0c2d1331f637c669dc3556a87f2202e068257daae8504e2863e9d096f5891b80218bfa41eef2751042b639bf6999967dcce976d9b3391fa1033128c15b9fb7ce060953c1cbf53ccb364ceb9b963132d3bcfaafc9e0ee7d7f24c73677bef0fa0104aff9bde187d29fd120788c1a862ba41b915199ec13197b74393b58575a47cb", "SEC": "04106d0fd21b65155d01a7057681757cfc73f291b201f55fd506680142680fa18f0b9e8ed50e3fecc2730018d199581abbb1de31601cb76f340faf9e8e788658f5", "TP2": "0400a23cff040526bd873f70173e53c83219fbda97a7b23084ed9361d679cb375b1a9ff755a7cd43275dd3e26067a2247096a82e7983e89de8c1bc6e42efe4e7ad", "TP1": "041d1e39dc9be6c63bda7feb0fe88a7f414e2a1be106be103886e74f78a94dc39621b23a14cef35934d40b1afab30d04a5586c0a844918823a154a5d63ffaaa7f8", "CS1": "04025ccce989e265ad3d30ceb6e5d63e435005e4832ef06653fd44f3f42cee1ec50eed44c187c95f3bdaa1d4a1f4d0c475b2047e282b80a21aa84e0e65b79ef1fc", "CS2": "0423b67bdb2c45c9de36e66f1cbecafa72d3fddadceda6aa738e0d58762724cf32101135343d6d35848592a98714fd5df886f04aee39401c2ee578012db84471cd", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041f69e3fadcda91b5c4f6d0ab1a87020cea5e563e100937c797551769e00935c92357a9226e13fc7a6d684afb179e1cb17901bba1de350caed786cadb11b4de85", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "040ace6630d6362fc24c933329981b97103b91f973d5d79f4961609fdd00cc277e15b44419c20f1c3bfcec0da7f250d3e10e39c832987230b861585948c0a3cafc", "U": "041f752bbef2f6b8e9b1652d3cc4863dbaefc2df1899eb7c81bcb0617adcf8e3250d68a5191205096b84a2eeb22d2cb0a5cbebebf55b6a4501497e7f2ac3aef64d", "SERVER_OUTPUT": 0, "V": "041adcc3caca3b6f8de031d6f26ed332feb505b2f54520d18b6f1d8d55463687c7117c7378a88f300f72738975d083c030adfc0a9a1a284b256ee4171b969c213d", "Y": "0e820aee415b78a95e2cbb720951d04d4495951bed2183bfbfed9cb671d519ff", "X": "1064399408c4960db448eac1b0f6798a234e65f6e0c254baf0bac4c76399e3fe", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 246, "UT": "040491871f55cbdd45e74e3d9f0b5d1046b40deac67bf0e80a0d908f23224445e90e498b5e054b56f409513816c695499a0cd83b07dbab93ae192ee53b583115a1", "MS2": "22324cf52f0cf274396b31f40fe7dc6e85d6114a269ec5991327c6b35a30d888", "MS1": "1f169d0db5698553f50526395bbef7ecee0f48b71d573305cfaadef7bfecb69a", "CLIENT_SECRET": "04072e87dc3fb51279fe86f6d942d4176c73f2ac065594b2974e55013c18300d0f0eae5952593481cf50c931ea4fbcd18940f8f8383e98847fd979fd793539d953"}, {"SS1": "1e38761f98e4c162303958028d30e15a33d4a4b1afeeccd427f2fb2b8e15f8fb07cdb7bcb35e14c077f11bda06b580e35e1385eb48a78ff09b2654420bd8dd1505f65b4657c7172831ab86e0570c710610dd5d7a1e62d2b97521c794c30f853412b48390e3e7d036d174a05b72c062cc27b96d53bbfce84a749440002fd95ab5", "SS2": "1b8cecad90a685aacda81ced3f417e83c389afdb866b306d44db18db51a41a1b16806baae7153929f87813820930cd84741b7a0aecf6939df4cf1465eb8b879423faa6db0885e9bf0db3baaac5ed2ae3d098cac042e74c745ef52baba25771a52236789c1e9cca0564dc251dc8ed42736a581d5e6f762d5f6b2ed5fdc5e1d486", "DATE": 16621, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "236c6cc5122e5b13017b4bdf306d3ebb30d656460c14b965c08ecb8dd674d1380da6d674fe1a5444f67dba8c8d0720cd52f1b5ead4bd06df3289cf88efc680412378fd82cbedad305cfceaab11bba206d16086d7b23fc15d487bff52a89eabfe00349bedd160d9e2d7bc14cbe586dc59cf061af53ee203c9e7cda5ffae8f0d06", "SEC": "04104226502d2ae44cd05d3febc998f7f845209145ed0b046754633ed28265e3d717eff7c6d0ff41189d938b04fc2d6e61ff82404880c0df821837b48578623e71", "TP2": "04228918217fc41e914439f3fe496f510e3d1f690cf902bd4daa8408d2960713ee070cd57cbe9d722e30364727d8b996b1131b5618d4d44c17309dec90f34f0c6e", "TP1": "040a5c1840487ab0052bb82fbc4b45c4f644c7e4cf438f1baee99223e0d7bf01a219891851e5a36014652c9dbe20ea4b334fe39e979778bd2bafa19c7d027bd911", "CS1": "040326557fb42da103ccc21cfbcbac84a613362a12e438af416d59d3834e2d604319ce184729129bc959eeba4bec8b4ca1e3d2835ae4bb5faf48ac1707bdc51cb2", "CS2": "0411071ff58c49aced360ce883377e867089a9392df1758b7967964b3e1a9e02d20b8418c70614b64212ebd805dab644fa527563ebb72ceca70273c4c64dd97632", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "0409d290c7bac6d079e831e5742335620cdbd327b47d295296e4f80b6f33a19c5904f8cd45e519bb70c764052c1a5d45d195634627654b13f8fe80fb50ce9a83aa", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "04144d45d0d02d7c99b8df392951ad713883605ecfaa11bbf27355013a2ffb34f4051bc343705d2f059f334819c13476eac74fc72ea05fe00599022c7c7e39d885", "U": "0403b88661a889b2ceaee2d55fc7403bd95f9fd69e550a3198e48e5d3ec20f3fb3123470085474ce71d1860354c940a7cd771c647b0592dff159f2c3cc6da572a0", "SERVER_OUTPUT": 0, "V": "041d37e2c4090b8f8cbb011bb97ba1cb8df39f3ac854bd1b8a3575c9fb8ec6234716881f69fd8d75d28dd84c46beafeb87b5656f608cfd25d1ab706c54d2318c80", "Y": "00b425e0e907bf0c384f10168f9530279c540b7e81301ce3a98c2d9c06a385a8", "X": "064a0b9aba8f006c9dd4cbcdac8376ea39117d3a9238918c256d881bc6942fc6", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 247, "UT": "040f08148cb3e9068ff6f6c6d7d6224f745e2e31d286a51a4519b047878d4e8341086373c10f6f2dc61675f542527bcf3d319ce5b7d56e91d229ba574fb09cc63c", "MS2": "1a7d3fb0d4a150e9af3c25838f2114d592ed4d3df2c697df022ee69c341dbaad", "MS1": "0e1e5b96b433c1c2f3931c51a2663fb4a8c98647a69e09b28175f275b3c678a5", "CLIENT_SECRET": "041a6d06a0ff47843336717591ca68677461854f06b37ded519468c8501c8712882121d967f840a7d95764dbde9618096629a00e60aa88f840c519af96e1a82ce5"}, {"SS1": "1c94e05b371c97f74d953c5700c42af04bbec72b4ed77c6532bba9a549c4577d0b5488223832d0145f87502f2b47d6fcb3077a020c820bebc38c1a9312b7954514df1b47872ac1db00c063f1cab7a8e2cf20d92341e9bd754902509a79e359321e2ba4bd0e45523afd6bb31e6a64f76279ed6f504f05062c34e2147c9f448807", "SS2": "1b4040f54a16cd7721998e025d6cff66aa1c34862c156c0792d904e682061e8014840097788ddef42e7cdcf6068dbc4778125be3205f1783ccb09e75726e36dd1619716e3409497bc77b5c1727caf7da74d6363cac15d0df65901d7ae894cbb91bd6933d7f03f0f0ae1955ecdfe2cd064f5510cf574061259d83c97fafc43e10", "DATE": 16622, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1dbe70300b242d7c5b25f57b4caf01fd46b2ed4ad1f2553224fb709ff433d14718d9453c4686d62a4ce47e3f17a521cb6227091d401c7d7e515692c25987a0b10405bc29b715849d252c28cb8fbb68ade1508e35b442e76d65c09e6707fb0ceb111155b6b35589f5b9eb66ce6c1d0bb95d5f06383e06fa97240b275ab0c9cc14", "SEC": "0401b1ff0e9ddbd31f3a8fd8cf9bdd8d4eb6cafa5e9cc263e546a6181ba229dc4b162ae1a00dbf65fab976150d9a7e9fdeaff8a4f8dd8a94ad7eed420f0424112f", "TP2": "041b8c62e022a637a453dc79dbafe1ea939898958aa8e2646ae2f50dd64427b9c317996f2ae598362f2b10b3c9628cb87384ccef9872d4994bd763db7e0f10b141", "TP1": "0418d3007393a65b07e3028c69ebfe633d562967ea93d9b575ab2e713958dd071102a376edabaae9ca20e7ebce504c67b3db946277d23d3fa2791673f43a39751a", "CS1": "040fb93bc83d2b32db952548afb820328d50dcf810a694f3d25d88d4bbf75f90eb1e2a6a74272fd697390edf3bd20537ac96ee1b185e1ec2cf262d04193daace99", "CS2": "0419f7746b6f124056bca608e54309f4a736b9f572c6730f433c62b8043e72ce801107158c0e54affac001ec778e5bac809d4f8b80b98716998cab999f6f855ffb", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040829d7d49306094263ae7c6d4bfd73843983af12588805da3ca5f5fc49245b74231766b63ba12be58e139448b47a85ac757a621dc3b926602801e6129d9ffe81", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0412105777cfc2bc05e07789e4f0200b5e132a223e2e6e99cfb2f78f8e5adfd18e1c559e3fea9a1194199fde1300a85b22be8ec225d3acd0697266fc8bff3fe237", "U": "040b03e67e3c029efca4303cd9a9edcbfd858ce76fa2bbfd4996ccae1b9323800311bea1a15bf9dd6b2f470e50a9898f545fd4c9c11a31c2c0cd9622d95a114d61", "SERVER_OUTPUT": 0, "V": "04134432c350c51066fe42976c32578568cc5678e39324b82fc22266f61fab58671e7ec2345823d05d92a2a7e7f397f8c2da2b346ad6b07a5cccc1a1c4990c83de", "Y": "02542ab94834a3e9a2f1d1c9948f4b2b105be14f52d90b1f66a1933ae526414b", "X": "010b1c0162ed924605878e6ba7fcbe1a2a7bf82add37c12e83074779e0e97fb5", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 248, "UT": "04147ab0fea6f0258d883100e3bba7aa53a209737dab98e08291c967943a3a5715217536b419967d6db4c5f549a6aef574a1f672cd28e83993daee75efe75bef34", "MS2": "0953000aecc3618a0a7fd8dc8767e77645410bd0cc99a6f35b96e17575c362b3", "MS1": "0ccc99b80fe77dcb2fcc8a46fa24234dadc088777680b36e2e80f4f1864b51c8", "CLIENT_SECRET": "040a09526857fef668a4bd19dbc24f9d9a06a2d23098f831688fffb17243c1461c1b12d1437fb2d129e438204e30e2f2348fb17b74993db34e4175cbeee0c2dd42"}, {"SS1": "20e5205bfcfe59aa0065f8469681c17f8928687c49495aeff1a64c01e413801005fbcec6953965cfff564b900593d21f0c26beba48dd0516314ecf698255f54913f7fcd291b40c87d0f2603bf87b2f81f944ec528e20384a6826c5846bc440841478d48ecdf5f005f2cd8fea9161635c3248f7575f976b4c618fd769f5d15b7d", "SS2": "0ea82eadc8e7e5ca979325b737140d07c1e770573e9079f576b1dded6027a36713011d4461bdf504e6b33de253a8937f90043703d25c72e8efbeba85807457f722ac96496398da731bdc60ade5418ef286aaf381f16d4ce9c6208196c2eac24f23663865e7a5fbe576947eec2024509ed7045920d43649c59e5ba8ac13b7a655", "DATE": 16623, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "17dabf3e918b8437cbec8bf2ae6f4eb6dcfa50c522eae104f8aaf4ed9d292d461092c7c67099df721f6c04965969db69388c1b52e4c924c5ac874c224387d7ce087dedacc10f39eef4ff5160e72e30867256e4ed21dac8c7587b9d9d7ad7c04501cebd5711f43dc290940f1f9b959956ad02a8bc5df38a5a51a9fcc02b1dd1ed", "SEC": "040ea2bc737da52e3f49f423d959549fb79845f498dc462511f497bfd3a45ff3cc1dc0cdec6225efef71ff68ea97a12b61db809cb062b9a5ed2b61bd211e0e56de", "TP2": "04118ea31cc3d72d771899f187c1b61b09b9b00824ca1a5d631b0e5d6ee0d307e3051146395d51988cf7b7b46c66481eb71e6ae32a6598dac5ab19f2d1cc416241", "TP1": "041ad3bdbd19176a3c2e87cf3904ea14418ba2e64aba93b81dcd09cd297dcdad15150d1b59f5e60763226f1c02fea1392c2ec2936b2812458eebac6a7b1579fe49", "CS1": "04171662131f3dd6c4d10afbee66df0bece0615962ae89fbd3638fc96dbf3d1f1c02dbce1555c82379ec86991e9328b172cf31ab89ecf2dff3681a023bc4d1521e", "CS2": "0400358fe0b8e2f8c6a3871bb3b702c626013cb1da3339473edca74a730c96ca4c07d82b4094d84c862b2a3fb4be9f8023d5d0b00d87271c66a6624ff0f07da593", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04208d27d9deea0aa972bc6211341c7cc63f01016261f37dd6ca9f8f27602a629e12f3c5da7f0576c92188f3b3a0fd7d91d51ba66d3a6b8e8a31107b9fb304677b", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0411babb19a68d6d9e9e832b7bf8b8a0af8b514fdbc4a3b7310dcfe210ba0eb88b16a56fe9d244116e8349c3ca8f6da605590d023f2b175f189a6fc0d59edf63a3", "U": "041bafe2a92cd3e928c08d05dcc7d0a9b4e36c797768a36cc7f0c2848df310843f2313fc65200f44763266aa07ac7ead7abcd90de1e992e85d9a576f3312803262", "SERVER_OUTPUT": 0, "V": "041d5f2ec3ffa150f06c1af42ece85a0cc7d564c6687ecc322aa2ae7be578dbf942345ba76596025f61ff7bfaa3a97c3c05833485eddf66ca0ee933d2213d4a10f", "Y": "1a23d0725b7fa7c5977a66354593c2dc5b1e417d6869e60339310030927e41c3", "X": "1dcdad6bfb00a8a0ee2c6f97b01c28ccfae37208b43e0ce973eef1b04116e4b2", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 249, "UT": "041b51bc7e119a4118c2d5d314de1975666ad1440624a9af96d7cf55354d6367da13c937012388f61a283f1caa77609270aaf2565066040cc9400a61bdfc5e35b6", "MS2": "06e36386972a47d19812409fd6631296546339fc11149e2bbd0ce0b487ec7150", "MS1": "07d8f41f77e9e4d0f73324aea4e9d6df0c5280e8accdaa4ce1d30a7b24a3b621", "CLIENT_SECRET": "04082f6c4534b4316fc3974816ddc85f4587e3c82202b73d827f31f668e1f7202b000c608c1dc4dfcc8dc3ebdb0f5e7c48b3898790e0fb7fab67a056703158e4ed"}, {"SS1": "0515bb22f9bf19e76f232894007bcfcc3686033955ec541096c2e8c0ca8899841a3876400ca66e14052e8920f382d7a8d4d94db65716b9aebcaf7515d93fca7b0e3d665a78e8d4baba42fc6b9533a9cca594b9db707fb08fe34cdc45203c8964076c33c17fccf541ff94ad8c065f07493309614f00f50a91b88fb2802c4e7b92", "SS2": "198be276c46e70b9b285f25d636179bfffc07593a163ca267a0321a01e0ac7670a02e5a786c68e0848eb032592b3f3051a9cd490012499df90ab69add6edb49413816620617f44502ae4b76e9a303f41577998ec79ede89aba6866a66678f5b921881e06eb058bf3f360248b400e7a1aa3152bc95fcecf69d98fe8b98197d019", "DATE": 16624, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "023ada716d5b4f45d7bfc22d2e4d18a67f71ada3e0c0981b50e94907c6c8289c0eb0d0d2fc9fbc0b81371ea29a329ec375432496c0dfc218181dd48930d9a2a60891af05106a285f976e5506b3aeed2f7f394a09e6750ce8a7c607aaeb0765f30abcd93e3799eab716f3f8496bef2daa8bdcfce16da6eefcd5299a1a6caebf29", "SEC": "04239608d5e3e42bc01b9e147a6bd0f31e314c3868d035b21aac3121255db35a06026fab90951727a4376b4fd87e6df53b2b9a4a668447fca89ad5d0da11de12de", "TP2": "040134ca7be8317fd30824abc34f3b752296f28ff18eee3a9ccddfa6cdeec4fe5e186262ecbca5028d91ad33ca0be775d94ad8403efce60c8ea458e826e6768de6", "TP1": "040b1229562e129d28d78b580d2fd54bf551398fab1347598f0752d7c377186833165e0664b7ae9652fbd18475a52daa911ee16ba817d29074d31dfda3f9d79629", "CS1": "0418f4718b420a0369e61033ce3045dded201c83776bd8ae307fc1f437e595470b08f00bf6b318f117adc14fa10aaec27fdec03506d6ed9095bbcda78a398ec6b9", "CS2": "0423d3594dfbb06cc4a2c949d90bd7ace12f43d6fbcb0a46adcf23c7db102c381808975b7ae20c7b521e4f5d1977ed024cf33c2463e88fe25e24c08e6347aaf1a2", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "0404ab36d995914c3d7443b6137ad771c6cdcb4c52fbde79a9afe2e3b2294674c9211992fa762b34567043f1070079d0c0bbfad1215e364ab2723fb003d96a6d0e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "041a1c57adae6b7c1db81139bd2a3cae7fb84ba6d0fbf7bca91c9396526866b48914ea445b855c21c803697150822b9c4bf1d6611a11b5d9fa2a9fd87191305985", "U": "04102a6bc07e6c7c8221aa2f66b661ffff293fba977faee6e08f667120819a0e4321c548cca97b38dc6d2d10385c9a862644ded3fffbf45ecc74194a52aafd7178", "SERVER_OUTPUT": 0, "V": "04145d4967d74b2be02a2d890507c548db0184544c808a75e3e0473403b72daaef1c7cc97b4e0847b02c8cfc5ef6a8646fa36edee4bb7a1efaa2f98adcbf1ab513", "Y": "00aec19e3532d66bcf31718773ca26469c862fe2adaf9155b7df6bdaa1ccb214", "X": "1a782f81bd4067e5641e33b21d201db02ef55cd46e33cd1ce5ab50e3043db032", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 250, "UT": "0409f9456f900980e75fae81bd5663b512debc32c180e323656493a76e8cb89a0b1fe952fb9f3a84a7d5bc815fa399f486f5c4dc38d556db7b7ed000bea3b88699", "MS2": "1d58f919ea91a2b2ca913ef69863f99fc8efbcae62032ac3f307b5b7b3a33f81", "MS1": "191262421a5c92297155bdba02f9c210b7c62b0841751ca6d8608fc34cb1e68d", "CLIENT_SECRET": "040c4440791f4a1b543a9bf5296ef4c2575b1cbe156ca1eda5e67d3abe3c936b75078a9afb822f96d8aff225cd2bbd38d21ac366bf726525f1ae159962299b13d5"}, {"SS1": "1aa21e72d8f7c09c60eb22219176774665bfcc4e9b0e8d860fca679039001eb3097e2470bb93c1c62e9d05e55157545b3faa5cd8f12026d69d3b21288abbdfc70fd96fb85ef4de91d69396fbd81f0797a24d8d17a72d91ae79e1c7a790d2c81602fa9edfa0acc55e1b5728c725dcd5ceb5ad423a81d26b57906e63c49a64c5ec", "SS2": "0b8838696247a7c8cc7c064e93d44e7716718e22e73ed5183f3acd4dead15b3d07c3bebedb95be8b4f01835ca8e6ff1aab48c4450c708b94c374b61a1bf5e30a1e1f8f9be3b2bbc6927470aafc38425d183a4f30e8c271197f5a1bc9b8d9e0701092407848a3b6b45f6ff3b069a3acfc3e8a50feaaa0c56d4e4de9d664a3f755", "DATE": 16625, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1def8cc8bc982a28d29b00332ed8faa120c7e7c1ebffcc2e7224c15937c7889d209fdacfc4a61cc67863be9355db37d3f5fe13c96fb414251156b7404b85cf3f17bfc23ac2c9d8e9554d02ff73a748fc0a0aa06334c8852722bd93697db462ae193d5b203b94997209e1be75fcf9e707e92d7fc1b7c87846c44492f2cdb6d124", "SEC": "04054a067559d736548263c33cf276af004ab058d7d1927ae8dd1527e65f53c1291b5c6b2ecb8834801a906fa90567ac00670d7c75f50038f9cdddff3d403fac2e", "TP2": "0422a1a4a221b16428b14c21877da065a7750365dfa9786b357496dd883213b49505bf9c2094966cb323a1b00c353d3fa1ed542508e4c44b9d3c2623c09b12d397", "TP1": "0415531b2ccacab24e326844fd76c387207a94106dee60ce1d6176431d712ded2f2079e9f46884a4f060181bfb392e1ab72ecf98dfb1dc39b8398081b6881ffa14", "CS1": "040691e9a4c44d3ca89ba09a1bdc7aac8a9b0c1cd429c6c79cd56a4cab007e8d4f0c51a46f862bef2b7db2877f201afa68b0fce4fe1f4ac3f471f320141725420e", "CS2": "04165a3f4daea4a947e56468ad7960324000822a819ab35bab5c42ee8d7b0276b71b042a0eefeda3c582f1fd9f3f9ac432342c10eb37c239fadd55391fbebf1595", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040faf6102af2c3802782d497219a4cbc16483253239d77b4a714c7f6e20c33be31b7ea457b1bff41880eda6bda36036cf2a7671427367bd2c05176fea00d96e58", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "04124aef2613af167ec66679dbf8c6f91bf5f4f8a6dd7aa477b6ca27277ec4f0b7164f277c3c2f3d99844f969befd30013f4cd5e68bbc1ab65335278173584c2c2", "U": "041e19eb012632066890a4726149aac9912c12ede84ab3768370a1554a7a0e07f10dac659c57dec685104c6dffe7b3ee9c071dd0c1ad7414b0f4a709b7d2fd0bd2", "SERVER_OUTPUT": 0, "V": "040442ae1eade9be5d942c6cef98c417cf4b551c2159968e6e7f562eb74180245108a2b4587fe232fd033f9f9c7f133dfab690cf1d3d70ea1b4f9b5d0b6fe4a019", "Y": "0099564aab862139bdfa5ed6f57c0606d433a88056cc8d58474487896c77b1f4", "X": "01a5bacba47ea42d51fa2b1a015bced8bbaab94486247fdfaf3c1a2f514f715d", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 251, "UT": "04222682597e91c4f160b15df8313c365e652a75215ac4037b737ea275ee635bde14351124cc0dcbede1eff23dbb8b416d64101a346e598e07e84131214ce729fb", "MS2": "207506703c3b8d05f1df2ea35bb25c397b7cb43b70dbcb3b5f44e650483824e3", "MS1": "0b037232a57cb0221d9f3dacdcd64b8acf7fd5fa2333ed24c2afd6ee2b1788d5", "CLIENT_SECRET": "040b62769f50409c8a4f277fbb58bf7b58e4c77bced88afc99164d4e43c3b0ae19030a4f850af053aac5d32920ebae1b81cfc71956382dc8f77b430d8fe9df070b"}, {"SS1": "02324a7a8aab9d7d10ff899879c11675906d5e53c7dbb93385e90815227f08841b0fc08a0da35c4f7ac6ea4e9f730031945dec9f37c1b159560da4c30680aef90a0f0fdb06892eeed488d9f8a06b53736264903ec33bf9f8ab9cf8571b73e5bf22026fec5624658a993aecf8c65d4349adb5a58b17550f6a8197e77d0f81abf3", "SS2": "0ff9b5454fe7a6e792537d32a82b854c200aa9f1d0f2352811f54d59a888d518018f8cb6574045bcc50400a2f09a6ccf283b2e50cb44c989bd03b58f1d3494101ccc567f9f72f8f70a2720cf007a80fb1b7a45b7d14ba60739f924084ca85a001cf937cb0c42ba179703bda14f3446870006e3f3347ba8bec35d9125c7295b77", "DATE": 16626, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0101620b560b3f60506c930a817e23259fc37207bb33e8d1309aef966701e9210745d58aa5b0fcec2302fae536116a4bc277163af1152ea0e0a4e02f5b121fbe12e437224346cc8908db61fa91d26bc3692b5a14eae148a466620ef8e74b54ee0bdf079e6eb6d690dd673bf1822f985b91b02c30bb82db4c3f011fc9eac7fc59", "SEC": "0408d760e6db69faaeb42e2e8f590e2421acb75d72a1b20b1e6591a6b86f6da05c1f8606353f99f7f5d24d3d2d99e5516fc40649bc0603569de9ca26760220d9c8", "TP2": "040d670593290d5858aae76f98ce50abddf76b279954d742186e0329e0837ab40f1ecbc36db4d756f9ca2428dbc1fcd5dfd9948954fbe3ee9f40ca0dc16892c196", "TP1": "0400887d3998e8339e2e5dc7b3f446ffa212a6221fbd0707e0ec25f4f041b81f1f09721b52b865de5200d5f25b6672f00a0f5cffe1c1c993ba4c947db4d4d0055f", "CS1": "0417a051b05c798ca527981e7e592f6c6f3698de534e2a2ddacf0530fa3d2b71a8053f7f1f89379b6e3339f5bfddfb143b9f98eb8ad7e09e8472941d52d6df0ea1", "CS2": "040433504699e2dc47044f23154c9762208f2759b6e7c0665511d2340b5fe87159036da8c4f43874a5fc242894310897254d917a7d1cd5c5507f8253d9cd395799", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04153e0ac9e2803d0b4a42e17761dfc9cb800cc71c0f3ddf9c999d89f52b863f8314858fb2cf1bef0818a4bad28117b47cb5c3dec7ab59f6df05bb14814c55a492", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0418b2a47d09581ec7ed0d1bdaa8cbc8fd2bd6ff8e1b0674f7546c521cc6f507261d079805af9e7ae4b883c4292e3b5217837bdb5cda6897915348b741271b7c7c", "U": "041a0c7025c0064536fed86c4c835bda7482267dad558338a5e5907805241233bd0c11f2d86cb5ba2d77be82b6548c935893c29932e4103e0d17180cc886044516", "SERVER_OUTPUT": 0, "V": "040ffb527d73adf383abe24e40fb3fd729ff7c2718feaea8b23e28aa3d8b03dde701e943d6de134b8c2d6bbaad5964fedd5cb535091cd23f15a289bd054068b9cb", "Y": "051e8485c2bca5882607e9b0b2e2a6285b07b42905c99cc0b5b8e2c90f10e239", "X": "11852bb69fa263cd11d534fa36e2437f4330489043d6690c2a9a3017b4833c26", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 252, "UT": "040d8b6076646fa9fc2e7695d66f8b21ac6d7e1727e00c64ff3c5b19dd85678b5c1f6e11b098336c80432acbc0793b423e9c34d104e4cb04c86960c92ccfba28f0", "MS2": "14b0a73671bc222636c893d02beaaa9f51b8111d07df1c6a5bf6b95010ca8e6c", "MS1": "0130c009b050d38f4bac637ad3dae345d4299166d66b5e89ff8db66bf760417a", "CLIENT_SECRET": "040ddf304f3ef2450bb6f284e3888315deaf058e1a387eabe88d3208fd788adc95187efc15bc4670c1bec20ad25adb5878c0936c567700a4da994da4ac17180cd8"}, {"SS1": "05105fc21e8c4b6c4dd78c6bf3b8146e5c014b3e26dc9c656ed2b010c50e7baf02f9f834f5f853d1d637c13acf5d122376f6857563079ec776f71890cec736c319c3311e5534c9a7b79b4b80f2a127e3fcb9e4d808f3601959359219fa8f822c061df1ca8e8a33326eca379d72835b0c37a8b779747f916890471e405adc0c0d", "SS2": "1c8a4209b8c98ec473c3b7b5b8e6f5a046f8a1c10edc613a8072908d4d365e8e1c3f2cc562bbedd216f1ebfeec21f632b2e36431f7ac8205eaaaf0c261c9b51817ed2968beaa1965405acf2581c9d8525e732c102e1e6b33e75364bbc492dfa822cb472f9c4b12b92d61cd0c30c7f894513d24ccdfeffbc671b39ceae0d6f5fb", "DATE": 16627, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1b8dc253e73b4aac42285a0b78b9ad4a67cd475251fd498b8e4a48f8745c355e0fae96314e382994b88adf083bc98f90bec9642ce6ee9a818895b06dbbd3df0d010c086b7e4babcf40cb0bcfabc8b9efcd36de7dfffe0af0ecb7f1d4be1f411a1f90211381d70b8e6a15c3f601f5d9e7b754381c4b617e052b27c1679886bd20", "SEC": "041640249e241513d7b23c22cbd245fffc57b27671206385f52ebbaeec23fc1cfe00764976ebabe4ec121ba237ec376a36d45c1854c35c2bf8abb9ec9a08072ff0", "TP2": "04238b5235518029fe79ce35e0180ff7410acad5d2c6d8b7fb6e40f030ab9d48be1f0d699a8ca8d67df1ad035b9bad8b099d39cfdbfd81ed7e9f0347744ad4c189", "TP1": "041425e3dfb7b3d11e6686ea123ec6f62d6e8cc9ab698c585ef75c78d9ef56f250208c28e2b4250182477ab8226888102699992a3d4a0f072db5cc03a0d3ea1f69", "CS1": "040e2007eb16cd99aa495ab8830dee8ed7700d026d2944d114847cf570d7adcaae19f5b72e58917e808abf1a64fca23b358094fc3b49710d43c9b177dad6f25ea6", "CS2": "040a668c0ef2aa003103236351ff3ad1fca6905141ad90103f386c5b41b453fade17b83731ff74a0614df9273fb0fb226dbf235f41506bd9112f73e8894498695c", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "0413592b5b5d5d22f44f21f3d739c5c93d6a6c251225167dfe299d085f5102bfe8149fd64cb2ab52968d86a6c08761f37091d17c0c8c60aa34335a6a577cea4dac", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "040999d8ec1336a1aa088ac1fdc40d8acf9f3b41626db1b810a4bf3355fb66787b1292b1cb9343202d1ecf21e02e229b65c0edbd9857baf0744ec347236223fe46", "U": "040d3537cb460adc2afbd51077810b9cbb803a9887f29c18b559bfb5c06b23eb8b0f75dbb7345dbf560d7102059438cd0b9de7d3067d69e8be5c8a4bf7b31934bb", "SERVER_OUTPUT": 0, "V": "0408d9732675386d0f969e85d5dc147a7fc17e5855b792f4de7531db7f56362ecd1d5664438d82d06d24c1cd41e074550e726554337235a9d291a014067a3fa3ba", "Y": "0300f5e171f0a7db7e2e47dce5f3bc5ab09cf09366abf4b1f1c47566e8ccac13", "X": "22dfc63fd6718ff625a97589af9d75d7f51e229cdc8266ac0418398f35199618", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 253, "UT": "0421820e66ed6f77b4283fc863d4453168178335d2a453f33e3fb41ae996377ecb0eb296a64c75ae9ee99b313d5745b0f025020d5e3e80c6919729c5c011032128", "MS2": "0fba02ea55742e7f3f4c77e227c01bb3d3f660a365b9f74a1168c7a7a17f4949", "MS1": "0ae3593dccf6a4585a699494bf023f12c1c85ccaa4774d6d25d44497605f782e", "CLIENT_SECRET": "0403759f00439445734555a594a9a27e884514e233483207a5b54527f538b7bcd20d78be80406acf205c938899be1dd2dbe9b82474ec234dd40e7e18e206fe49fd"}, {"SS1": "0a1b1c1f198f3932ad89e41ea662a34c7b2cb3f099ba4a04e5e12e0f284fb0000ebf2fa2a59763947057d7008447a4e78184933621e7c127c6a253ea8dc6547c1eee905d68af218975297b5c7943862e0cd996baab07854b6e00918d7c84938909d3ffe752cc482c6b8e424b4fe167277527f288f5043dc52a0a705c9c8cdf37", "SS2": "006e1467a1a21d8ad257427b2b1e56a351fd16c7d2636df1d5fd3319634abc0e1c3271626126ac00ccaf6ca07291c58f2f95ede6e70ecb92f7e868bb19400f6701a119cd8876834a2755cdd93396130c7e8674b41668e3551b52993513fdb258147564aa373521563159e48e1cf738ff4d88d50fd6f954945046b922c8245acf", "DATE": 16628, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "05f47d8b3793264f7ef3618e42480ab0143db23638b0f17299c2d1b6f892d1c701d286b8308ea60586d90193706936fdb2667e3665cde0acef6b734a365ca5df1e839f951a2dfd40a1ede26f3789383b6950ef029efc24aab93f76ef874b9d6c037fc29008ca9c59d3947b8a4ef8c4aa21a9d93d2c8ba6842fca75c81ac5816b", "SEC": "040abffcd51f33981019e9e2ead70ba5a847a826a9fac5f1a7dd6b3681e008d85522f39af40b4b15a7afc9c72a18b5f3181f3feaa6fbcbdc5514c7d39bdbaa83c0", "TP2": "040e94453a48161ca32f9c3081c09601708b555c9633c207476204d13fafafc64511a756947a62d13c6a713fc4a2c03bd8f3bb8e803015ad28d946e6c30fc767ad", "TP1": "041ad15370d10d79e570465d34dc4ecd2b56f06c3da45ea5f0e4524c4c1ca0d4bd0eee4fff71503ee2159b5b56dd55ba8b18f98a2dadefe5d8756884d6165df308", "CS1": "0407d02d2cd1cf1f52f33dec473936ede641216d7d1b54db0431f1ae3f6680439f1f5800d4013b152611a90a5c5955c18920bf6025b9f685b9efd58992cfcf4673", "CS2": "0404fadab765cf35659abeac35160f00d86fabe153a81fa44dbeb52e2b5f9ab442184c22f27999c0cbd1a66138fa59f83bd73956546ec5bdd2e7d16226d6b456b4", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040f2be9f3218c33401db5fe9bdded4f3604c947548d1c1c1cc945e0e7e6b9363710a9e2aeec245946a8a434e21bdf87f894cb7e4759cf48c8934469d105cecd09", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "041739dbc7b3c2c8a9f4ed0a24d1e08b032191cb6d378c03526b58e07ea179f0d21cd0ae46866b675d1db9a81893615161c82b6ac44884e8e91a04c638b3d44d45", "U": "0401a8bef03d9e0642361110a62c53c00d9c86c372910c130da8e1211e37dfa9f905fc5628642d3a6975744f633f3daeb14b21bc2c7a3533707a0d2a0fd1eacbf6", "SERVER_OUTPUT": 0, "V": "040b064b05258aa7d4b2e0447f41e8071ddcd356c69964f8e7bf014940e2108a0b1c5b1f9eadd60b0d46b12b0da0e23cc641e4246161f7828faea5ff86231d39a0", "Y": "1552a74f265ee667d4a720541ac5e5798a51c915ab0ac4223b834179fcd000fb", "X": "14e30a6f6372119afe6e0f4b97da87ab6c7cde4803e02da431b7d34697c77bf9", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 254, "UT": "040e019b5dc7a8aa777eab6a1f5b91bbbe7ecdbd431a6bc6cef7e18ddbe5de039616756f82601d219f1dd8393b932e26feea02ad336501bce719b0c567e9278d87", "MS2": "15d62050e56c2ff2ddc4534e7462f63ef98e2d5c2f532511e54e2e124864373e", "MS1": "1dd95593d925c547a81efdb0d97d9178217fd98cf77c5e7e4b9f46830df8713c", "CLIENT_SECRET": "041102ab26bb80a13d49f32bb053c90d7103227430509185dd66c40301607f5e330f8263f6bf9003c357bf29b91d3e7d267898161e3a121cdfee3ac5ca90ae3df4"}, {"SS1": "1ae2c9e566cfc7cae2f8e070215bc0ee660eee4d28d28dc99cf11fe0656b4ef41bf7b5fa42e292567bd0b891bb24f8d947d91e4aee090902c5b98424cad6bc0e00d3b5157d5005244dacb8a1f94cc56f38e555876eb589537bef32175d1c5c0c2353f4ea4432cb55e4f7b2784c68aabf17b3989007fe7de3b7795ed24e8d57a5", "SS2": "160857abe88626bdfd2e08407f06cc806896cba969d70b213ccc65efbe1b1b191bd0376c69aa7081b291afa63a5666ea721edf3d39f0d84be5b486c592d79d8907412351f0968f074692759de37ba1e53b2917d37ca5d60d608d7726982f3b9907cc5ec4fdde1fe8943e291d8a222fc79e571d2726c2c001bf7cc14e8b5b6b1b", "DATE": 16629, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1853217d1d092814000469da1b26df1a9291471106fcc6cb72c2f09582cde2ea0b01a7017b38288be8b12023311c69dcfb962442746cc866497ab7e1e5756a8f034439f3f316e6e84bca2ff3712c03ca89ba569758e234469ac67b97e2e0d9e70d190ab1611c90ccb7bc7dff60092773670cd877188764dca94a083b9820325a", "SEC": "04095bdbdfae61ad23be0ce74a1bd1dac9e48167218a25cd5597ccc085730b680215942da6353d6e919ddaac27d07deed646358505544ac403eaa6a187d723ea75", "TP2": "0409b247dcd1e7c4418e371ff3ca2095aa9dbf99a45978731dcd85559f4a05bdf71e21534b1737c448f5f1a29e13a3c8cc68bd8adc4924cb002d2da7955b31d74f", "TP1": "0416a44c85d77cec54e462154bee39168cf7843a5f2fc729e4788ac80d57a3133f1c0a626ef562e7eac6182582e85bbd0de0c1a7d17ac7c392c86100b792f7c0a4", "CS1": "041e33c89dcec7ce5fe86552024defef8be7b487cc98d24a9985e039e54af63545226096efc09569143dc7ee1d042c04e6efaf9ee04b9d2acfd8efa3084f1b1c0f", "CS2": "041067c4425d30d20a7c1ef75718adbc8ff2043155b06995319d18153455aa38c106d03e3fb0fd38387c1f9a51c20b06ed3b7e1482a4fe4830b3efb6a70fb3ffed", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041bafc18e786eea7834ae4aa29f54d884a815019af869587f49cc8dd4da8b3da111491517b997eaeb4c5b3aff1b823a1586867ec8b59f4d570a23fdfeea0c9579", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "040678968d11a7de41692dfee7b1a478ce3f1cb995d5dbdc755444a3c58a7100781d7fd70e788513ec96d531132d1bc27af2373eb739018886c471d979f980f58a", "U": "040cf529942d7c6cb24cc883a3432dad1210cf4a25bf565982691ef43db0c8c9fd19990e1b45795dfe2915b7ea62f9c5b8de892689ae59de1b50c45f6fd9b39ad4", "SERVER_OUTPUT": 0, "V": "04118890edb8156467fb3a88b6889e22017238ab774b9bd3eda04b9837165cdc4f0b48d22a55932b2312b43fc1c80edecc8374ee6e5fff3b9d4b343036fb22f56b", "Y": "017c58072788d0203f6188fea6deca7b4e26fd08d65cdfc14f272af8720b3b31", "X": "07ddff094fe5196db97988936e7f0f84e55b5e3a0d2236290081b2bdde97b3f7", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 255, "UT": "041d54f4e914f1e60e5d2d88efb232c21e4d2e1588e7da405a4544524cd91500e11a6e623c01e1df8759080f924ed838fae3aed0c9c52bb529e2df9af02c3f1346", "MS2": "15f4d657eaa05ba72c617ed88312fb35f26f84ad34c7e418c1be3979ecf5edea", "MS1": "0029781829329d0c574c1c386713f752e06837d74d5755d7e15944b9132df58a", "CLIENT_SECRET": "041326f8c90835ae3893f8ea0a48b747c238376788939caf962b3d54fad99fdd56218da31fe1e3542bf0864f70a2b9d835de02632fbdaa612ff95018d5f85c2dda"}, {"SS1": "132bb880a45cfdad789bca411a8decb5e9349f71b3eed433641118f1353b30d50ec0fe4ef44b886982f65eafd97196ad64d943f24b113366f34ef0f19fd0c0a50c49759b7d36c043d351493de380cc33bc23e18dcd8b55c28cff4116381bdce817738761a897fe3cc411c824b1495f43faa30fbe5107bf60e7dc9aa31e9ce3c0", "SS2": "16595d4bdf299f3d196ba0f79198760259fd56c33f9eb6f4d4288b5092a2967a1c1b908997991d04f69bcac6f1ec1c716517714f9a9f1c3c7a7dcc2ecd8648950e50c9d861560928be1191bdade47653967ba29cca237043c343ce335bf6e46018eaac50234d860fdf16fbc509ec127af8d8e172d686bfd1e262feb1840e38a9", "DATE": 16630, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "069690a742621497e2918a0f927a9d2142810299fc3ddcc89c90b41817bd9ed81b70961503e175c3ebd0ff9b42257cd19b29d7f0d998cd061709e4065f2fba921f8c8d657f7f18667ddfc66b2ee191a3d2d3134c0b7aaab38018e75e43f208da0ff429994548c3eb34ac46371fd901c936e237f8fbe9f4f9ad55773305f8f00f", "SEC": "0413eebb5ab22779585b0a959947c27348d9d62e8f5d4172bb9d1d06a4e444ed521e4140c467542537738db63450d8fdf751fb79585ffcf75f43b7b48823b73c98", "TP2": "041f838a53135725a7e63f853162f4425928d325b37dc38e33eb08899b6022d52704f8f8569f70814b62b6a7a241c88b675950ca674c20361bcb71ab2eab18e7ca", "TP1": "0404fa4d33f9111c84083d9668cd58b1364951ee0af1498d6213e1f1c68662a4fe0ab6f455c9f2f8a10a80a26208545365c9a755ecb65f6b593d27b6b3ad7ae613", "CS1": "040434b74f0dc9dd5aec4eb0e6c18bbe983d01dcc58c107c60075dc98bcfa5ccd9075be83057da678167dbb87f2429d6db0f4609e08f10e940cc5f879e129d5702", "CS2": "0419c7db554c7ea9e15236d487f78e34ad94210b1137060e79c7faeafe06350c3500ef68c19b9688902dc9dc4aa6c01913dec952d259f916480b382cfeb9238c49", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040e872658e40f97c37ffd3982435385aa549bc71e5e54eea505c2da591249c50516d651ea6c166befc3402f2aa77591b978380dd9dddb13316540512aef8e20da", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0423e7f869be4596717ab90594e379385067ea6150070735292e035aac522a48ec19d5a41401dd8d090838de13ef2d6246f9466e8dcdcc597ae198e983caca8f42", "U": "04051e9cb1ab30f620a80871285b15ff51c795f27d2ac91f8b4a58e3800fe47c2e0dc0e95eb39ae790f682fc95e3bab9e829b170ea06001fd9a6780e2acb25547a", "SERVER_OUTPUT": 0, "V": "040fbc0cdf4068768b9f5b0ea5f64f39bb91ab8d7e6aa2680f3e6ac3cd0a55878d07b1cfa8a4677bcb334385f9ed62eeee48e1552866080c9c9624feca29f3d01a", "Y": "14d523a6208f47209f849c2a47d58aa421f45016f37de302b4f61b22c623a34b", "X": "08890153db44e548684e61783a61ca2f601e6b32e71143e0977473566a781257", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 256, "UT": "041bd144792020ea81fa7643d0bbd2ba13089d2411e10043473c94dffd013a72870b1244f07538c91b874b65fc593992e5f10025a3f0c6edfd93c97ca27d11bb2b", "MS2": "00c3fb4316d5dec99b7e5d96ce30fa9a857fb345da4ba57dc8cf358ef7a523a4", "MS1": "1950bce160d212614a172c0879bf034ca2dd43a929e1fedfd1c6626e4b3a369e", "CLIENT_SECRET": "040456ad6c927817e1bc62f3269b7e15717317e3f175fa0bb35195a07905bfd3520b5e5faa040a6169ea30381552ed11382e0be1617c4b82ca869d37a054b97441"}, {"SS1": "1bcb5ab7a64bae1f63aa80c0d59416dfde8115d8be034cdcecba84d40b4efda80d2ff12c37d9ad0cbb5e530c704448bd642f1cf2b6678fec7cb819d42fa126f7231cc897019abb9c65af9934600544e6cc811fa7162275bed8d70ea8085c2b6b199ccf446d9ff417c23c2593aea379a8eab2754cb67babaa507ba1891913e27e", "SS2": "1cd9fd33c7894af0810bab963a405838f95e0908bf47b41c1b932459aba2e00c160b7f682cd95e1f41df5cdec0a6ebc7d76b44e5e6ca037969927b40bfc613920952d00e0c6275ff98d0aafd9d29c4cc06f90a94c2bb88888c4586c85ae40a170e9c3a317069a4476e3d9f40306aad44ce1829f27b4e7124fccbb06ece4fd6d9", "DATE": 16631, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0f9898a0d4167dba72a78ca8ce24a6c313f53ca0f5cac18c49582419e95ec07102fec6ed7e95485a49ffe329bbccb7cf25d323425ec5e038a7e2f36318e99860232091468fc3c60e2f213b9e5791214d4528ec48fac20de84318d01e9abdc19318fafb3c7c4cc5763bec6ac8a360b7b7fb79a3601202252eb1a0d3fc72d22b1b", "SEC": "0410bcaf48bcdca17e935ad42a1a2416373ba63165dc45e80edec43272b233118f0de7128dd5600b0e95939ee0f7d873a999e7c5527ea35d34d06225801b4c12f1", "TP2": "04010648b3e1a3f344529e4eae3e7780f7ab416b6b41b601304fad0d68c4a2179700cd4de9aed842f527c01637019dc1627733fb4dacb0ad37f7140ff4aff4e9e7", "TP1": "040fc9cbc082e19d4ede9d2325b71f8c0b6ceaf06f850d94298842380f35943c4618659f65bb05b8ba5526a0ae0a5d4bf66033b308245ebefcfd0acea1e0b9613d", "CS1": "0412d8e08d6d60260f20faa004f3af1d8c3a7a5b13961ae7a41463630ffe90231b13d01875f9a42426313798ae7fe5829b0049dd2a1ff0fa5b179fb10d861fc5aa", "CS2": "0410425241c3f45e8af088cfafd614d4d8c41031aec5bc4a8a4ebece7ff0756d5f1e4ffa24d5d4759341c14001ebb5ab1d059e83bc56d8472c383116b2e25f320f", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041ec22eec00f388e181855e23eb17ffa4238598e146f2c5d5d2102feb331962fe0c8de3f529d9fcaf42d952ac1d415105268cab18482c33cab25c8c3dd56b3107", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0406f6ab99f9309375e529d90fd8dbcf0e7c0d2043487e7ca4357cff5be00f8b421b8b162921bb1eea389ccd2c8a0e8351db75a937a735f5f9c484f251cc783dd8", "U": "04108ceb88ebd584afff9e2851e728f109d6def827c4f7c735acf8971b2757786b15e7dece7e879b42255c449702bbf1001a8730652d8f78459b72ab35c3459556", "SERVER_OUTPUT": 0, "V": "040464bb308d6ed7a87b2601fc3e4f53387a87c7e9d6c6c5bc4106f5c7b9fa387d0606b26db492493afca928cb7056773d262daa90c6d7391c3a7cac938cad3d00", "Y": "1f35ed19bdd86d317022143ca3cd5f787b8df0cac1516f50b20af9fee751d955", "X": "175463828c1df019a85d436b1f085e0bc69e90019fc84f30d7299ddab3f5bb74", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 257, "UT": "041e448d2b56dbe8095df0965de5d779d43bd28e072c65678dae03535578c948bd08f82b77f51f753ba9f3d62933897dce01f281ba9cb5413b2251a11cca0106b2", "MS2": "1e9aa33115f873a3cef1356ae2ceb61aff69aa602a818f7b7d6de101b8feafce", "MS1": "03568beae5b3d7a80c4d40b3ec4d988342cb9f04342997809dc9472ab5f4a38e", "CLIENT_SECRET": "04207f45e3dcb3f92b1d66f3633eb6bc50c83e7142b9a31a656f3b148df19b4b6322cf40abc6f38e68763e6124f65daaf3f5d1833263b897c768fa57016cae1790"}, {"SS1": "189d7e2c184c6724ee1903066457440c2f8d54d7698b55381a9dfbe4a3a3700108d8b3a23b9b906742bce4011ff00c58377370590b35d6eedf43ec62e8be9eca2219f23c9cb0f6219cc055e52773cc61591f0e7faf8d0af3e7e0afdbbd8276660e82b425da160a8d59fbeaa2480258fe0d24d82e39ad90c2fe45a234a6a17bda", "SS2": "053b5a0aea3a0052c9101a41ca25cf633b4f0b0c5a16c749f5daa71fd72777df1ca690e2fba0af499ccef0bbb99629c4b84750eee8667fa6fb318692df7c80b61ad6bd8060be217c74ad1ea06886d6f7782e9ebd2054243346756a6ca8356c2c0ad86869932c4f87f20b4a86f45699a7faa85584ec608588156cb98723595810", "DATE": 16632, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1e193f24c9607072e3ff686fb88035910157b775d8cf18237df82acbcb42377002fb51984fda23dc24d119c1248f3a70bd497c031d468a600b772bb82a1a6d4322b8f045897b21421c5d12aada201b40877b1961dd233354f6f911bf49bed96f0404fa5351f75a8035301ac6ce00e5a9a39fa3a94cb8cfa94cf6dc2ddc15ee20", "SEC": "0423d61641449fa2bd74c9d7433796fa174f10ffe38c68f3c6f7ea0697c7ef519013b34b7837b13f0d2f992ba39b9598ce4eabd9962098eb002cd01c77a72767d8", "TP2": "0406249fe3df06f6d01fd56cd815a57f6e4c787a9a5971257648384170c968b63e0508019555d97429907eb6a687cbf0357048f02c1337a478f99cf2c2f247191a", "TP1": "0401a5be8242a2a0d7478c87c57c2296c04a8283c486a20829b9a1f320ab25e87311d55c387315b1c0e2abc38ff644726024e378d042d40eadbb71fdd4b04f94b5", "CS1": "04024b67e88fe5afa23b511df130ba02303058f335a470535b8e76cc4842c7cc050390f47a5f491a50dc6d835be11dc3610f7039867e80b4a9406c3d15d61a9343", "CS2": "0414847fe1e4e10c0b887328ac26e837eb27adf356f90feb50afb2390d4569c2b61b37e47e4480ff8d120c96058b711fc22fea1c7875ccaa3db1fef6206ff798ec", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04182cee117d2b5c30c71cfaa712ec2e12f9993197b6eee5bd93ad0e302860f1db226da67ee9ff490dbd0076310c4969706150f3609607a89c2d53327c4f706b53", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0421800717d0fc0cdc34c4c54471aa165349924cb3ab06e3cc922fbea777c795d805faf5aca39189e09710a43b8087b26d1fd57d414c69561f867beae3a138dd8c", "U": "0404971764878c1ed16c4d976a325f42c300d77399a24c7322db64cf6c934bb0e20e5b0c3721115fcabedb1f6f3681f8a83ed770f699c1f0ad744b45946c24f1b7", "SERVER_OUTPUT": 0, "V": "041264e9a447598424cfa75c7e4577a573fcf2960919aa4960079001eefa12318e0fdbe51e83badc1213f8dfacd7d7ca266ee48f30fe6775ef68b3e65885a4a09f", "Y": "1d5392bf78f82b96a9513f806411fdfc0bc85ecc96efea3207448a68308569a2", "X": "1b33cd163957cc982b847cac03de0867a52e5018a73cc6a8ad7c63cad4b6265f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 258, "UT": "04189b40968e44fd5bfe60be9e97332adadf3a2a195ca4f4c60d45456f74d3873e15409d9184c50d35295b40415558cdad8604b15669e3d0f7ed815e580507c36d", "MS2": "0c2a250ab02bf42d2ab08fbc0a040904bac2028fcbb23c5af2fab211a1d2da99", "MS1": "025b5c7a46315531b530fce15cfec1644cb7ff222f20efe199550b637caf1553", "CLIENT_SECRET": "040fc8d32cc079f4f14788e77a2aec7d008d29e5f8f4261ca00cf0fe42c7f585411daeeeb01421a3de9ea65dc50ca90e8e11bd86dc1b116ae61f4b30f7711e0b67"}, {"SS1": "12a726e720fe4b074c43b151039789a63a53147a89d3de02cae5644d4f2e93bb0e8972c4f093b0d469565228899712ecee29ff95346361269261a35b92812d0606383bcd28b9dab4188977bda03bf5a6f3775ea6c1889cdf7de09d20478b09e417d9021722037ab4aa788a4d559a7bff32f8385f49179f240c61f3e7c5497384", "SS2": "046b7bab33a81bde59fc540acd39c7f06d9a221ba5d42282eb289fbcf1ec122d1764a71381cff46e8c764eaadecb7d31dc1f55e5d1f4cae46d609ea60525a8061d901b22e185d594756066a001528fb3a2d1078fbd22cf1987127d4a8a9d0e3f09bb6e5fe6b4559270d993deb10c21085b6e57affe9bef8d2fc3f7d6e3616abc", "DATE": 16633, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "223cc9919fb31d19f062255eb30a4acaac3035006ff17e2779a518c3bd46833c16593c6bab2f251cb41e38f3312a89d552ee31c8d4c96b62d34eae3b7d67098916f5b214a5ae82ff5e28a09de052ab1deb51edbf44bea398f89382965c26703418d469dbc52b7ce89bc9e74f2565d4d33ccd336284c0b12588af164742e588d4", "SEC": "0408d7a4e19bb0ee49c7bf9f02905d22908968455f5d1649556be8ca8eaeaa0d032274daa0e384a3f24960500332361b83ab891551c65d43cd88f418fe4751ce1e", "TP2": "0404ca09cc804c4e93ed4f4e499ad3efdfb00fb4c776441a9c5de911ec9cd147470aa120ad6f7b7943cbae434e2dfcb8965383df5d94484fb5eb98f61ff3c1db0e", "TP1": "04048c05f85c64a5380280be90f7abc3f5779893a8286dae06371a59ed6400cdc30e1d4ed78d9f362e8a3161d977951346a9b5ca3c19ad3e1da437abc729c70305", "CS1": "04163c9418c6d1f034faf91b751e83796fc41579e7297806b1eb59f9526f81e45704c2649dd8f024b87adf32fa1f476fec1dd64e83aea6ea97f044c8ba0e10cdcb", "CS2": "0409cd9085fdbbe7152d7cce62b97c3d9748ed36b40e599d319809a97a008373031c45f6c1adf2a77cb9e3ab753e57680bcc5b4c9943b18db07f30c2b03a44d331", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041b1050173f98c0c6f6fa7d49e20563d4f5bee1357426db86d53c1a75c63a4d4413b2b7af779755015c32b9af40972a2fffb2d5cdef51ac0b4e482a3561877f35", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "041917cd9714a85e46565b3b92c0f83a79d20791f4d5a8a4fcc7670896da8243a302b8c65ef0e9d615dac0c267a03779fc4617f2fb5d514c2937f770984375190c", "U": "040f5742a23d4651736945b6ddca0c74dc57c55dec100d08a7f5db6011e8fa01f20aa1c192d4fbf0f79e46c0b9361a848537cae42071167e178519e1c3a9a7cb19", "SERVER_OUTPUT": 0, "V": "04166cc80c553a527052fcea3bcaf02d200e545b4653eaea2159f160d3f21e40be1a5b5a775ae474fe742c81a67b64a600080d4d2acf2646b653a2e4b205b2eab9", "Y": "003f6f0a547785e232da2ed233ddc94826b0cd2cf6cdf3974d9a2022784fa6b7", "X": "1f14751b03c1460aad03bc9303a6f0964ef78c3ae0bee69e871457e7bcf3ecc1", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 259, "UT": "0409d6214d580086bb7a129f2385aadfeb53d6cc90bbed9503ae6e00619bafbab81b023a124148864a1d9d41bebde775b6a352a4b8ec49c220894360729d9ce8a5", "MS2": "19bbeac61d22100c3a16107cc1cd726f8d45faaf212807dd3768e944e61096bb", "MS1": "036a16353d979cf113939bd97e6356a07735e7d898222b0c8ef5aac40cd867b3", "CLIENT_SECRET": "040e6266723895facd4f2d851acdc06b39d4d8a04dc074dc3c927fbf837ba58092055160b03adca2e6908ac2180f7b30ece80f68dc296af3bc12468845837874a7"}, {"SS1": "02bdfc51abebae8ca7fd18716f2390473b67ea03cbe62cbc53d847dbba84fec303327a54b7d078e25cc5984dac6ba0f848d604444e912b8b33fd1cbea1e016650ae0a106a3fe9225621650ae96d7564ab7b666bf648b905822597776d83b4e7f049ee0812d0bb3e3ea9cbdef4cd9c6cdc97583b7f7fe52408131be687855f42d", "SS2": "15d7811061cfdfe99fe43b3868775c05d32fdd07e0312c8073ecb2853bb2fc5212dd34f82565483239784ca63533db45878be035fef7143fa5c289e39a5d4ecb2160228c4c4aacc8d93db75966f0ef86889aedad1c67ff574744ba2575c9595206663d6dfc1b16ea21e59478b8e32c76e9b791e2557a7ecd438e1988e3dba117", "DATE": 16634, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "18abebc3360d0c182b1b612337efb406f4746b69a8a9a744e3c865c0610aaf0c1d7f6d7073a3a9318ced3fd7a854301b8a244a46db41ac9b05cce0ba04f81d8b2092789040cfa137e3ff6b3905f2d4cfa7506769f32a2857c45e46e2f1171a281f65e001e342a60085595bfaaeb6c7e3c3ee9d794169a5ed7fbea64219eb3597", "SEC": "040233516c1f5e37893df54ddbd244d5fc60cf02d74328c70ccdd35bf0481df4a411f0ac845d06aa61aeccd8c690bfa3d96f53a91d6af4eb7cf1307ede7ae2485b", "TP2": "0402f534f6995380c939bb4dfc4286c6cce1e07bf41f35ce0b7d82e115f4a471be11a944ee5d7867fae5f012a8b6064842742d94099242dd593895a65fade5d8f4", "TP1": "042012329dc8176383df916a74f17fcd1b013a18cbf87e0eb67f26422a4fa6a9fd0a35ef2bd8fa9b98a95098306feb7e9e1a46b791403a92e706cb4022ae814cc8", "CS1": "041889011c5110c952b33d3009f25fd88315c442ffd9a45d6c6afc46474fba692c0a6172acdcc67ce51f4db785016075a90bc342332d9690e43bed4ff8dc486afd", "CS2": "040b8e69bc1b4c227e7e6d5a23a2fc8e71c34f19aa388cc547ab0ead673ab308fa110bd38dfbebd2196a2b0778d711242d7b6ab379f091494fd93d760c1dca51c1", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "0409e51966af412a7c4f7ff203ebc8777e46e3947f068f52721ec6e271b7a9e0e0122565942710fa01684f011c199780113ae96c85b2eab0514a2905182d9cf2aa", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "04228bb53dd7a4ca424df72f4e8b85c6965baf7ef3954e9f4356217855ae35c13e0a5c8d5b2bdde74fc28600a36f464329eb03e006ebd5a977ea85f2bd85bdc76a", "U": "0406c38e31c93cc7494e07b02240ccfb407d752f9563ad5b5b7f748ccb82500d460b022f47e028c1207c67e21052de715ce3883938ec5bf9f9d677481e8225bc40", "SERVER_OUTPUT": 0, "V": "0421c6fca8efb3366f1e30e229f09874f064fa77918750ed8754ef421cb95f2749232a89ee50d650a9bc9cf9339aa1352575f7003f88eea25314186183a8ea0097", "Y": "03addf04e6ebcb3ac9cd1c2a977e29c25b65f772843d20a38a872187020ac215", "X": "19a0f4a47750e6740e96a3fc6711039d71ed36edc8ce4436857988001e95e6fc", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 260, "UT": "040e4ccfb08aad03b4f66a47806331bfecb6424ac237344cb86374325b8a0109f70244367044109beb85f68f1f20bc0d6cc041e2ecf079f212477363be6070890d", "MS2": "0b9a0d21ac377377d25252b3d4ea7d49d36e6f0397907ea02489fec661a56c59", "MS1": "00a8503e8dd53010a285e1b4f3ce86d8a50f56aff34039e0d13223213be83771", "CLIENT_SECRET": "0410cb352dfb20b4f36171e9dbf5646067d39fd40c7aad6f1d683e648487ca542218cddc2230987be412754a4d2fcc1d01e7a9c4781bcbb3dfeba284b7bb86c59f"}, {"SS1": "0081763a51d75ec65c0602eee2b215832cf15f88d20e02d837eba7321b1db11f04c7cf97e6e311d352c8c2b5f1a86aa189ea0ebd168128e5c1ecd27d19727d0e126637211b7c7afdbbe5b5b4fe00cbfb85389e205ca7552882dd121827166be821c90af857da7d287ec75422618c5da769efe4e0fd9d338fcbb2d11fae392239", "SS2": "154043da611726a4eff6ceeab83751e228230b7a8d29619039bfb4835088c31b14464c5429b51218b7d589a6a11b07daf1cd65ae6160cd0e9f411339f0d530551d59f185db47dc11a5c6f731f9eb6dae78eeed93245be78c1e5f64e208edf3bb0baaf2ca557dddcbb0fa9cb348816b990b87842e2c4ecedde0edeb25a45227c1", "DATE": 16635, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "2397df2db16e0e75d65d9aff370a87fcb60b552d7558c19340621ededa5f956f00eda2f22ae49d8b9c1af73863131a26293fcaa806cd571067bf0ee7dc7c7ba816103a9de022aa85780a819560b1c16f6e7e6f8f13ca7bde3a678d23b549240b23bfef3dc8598dcdd50f2c964d5d1afdde04b4865a0740d18f7d9bce4ab244c6", "SEC": "040e331bc6f3e5e662cd32d4a29dd998193213a4faef724fc8fa4754e2c43bf2b010e80dbe4bebb83852ef64bf83880f80ba3e816bf053308cbe98f8cf4122d436", "TP2": "04158c27b376240d34e54d23dd5705f372f03f8b40e63d5dbf2337bdd2c8180ef212d1b73a6672ae74a2ff1423cea54cb694016616968843332a7a6965d778c3af", "TP1": "040c210e7cf5263a60f248afc0532b6c3fde800903fbefd9e3960829fb554d479a0196a5b177456f3f331b4e7790efe5ed231b3cf6ec052e957237114ef4fb808d", "CS1": "0413c834f084294241e98f0c70ae6d608c360fafe8618a03a3e859f34f1781cfff1a2a8035a1367f26446a9f3dd4a06701733fc339135f0b3e0962f2dc8c20e023", "CS2": "041604817708c19ff0f4e01a6fd4c18c081577f0fbac0a2fc728de73f57abf8f2d127e6e1072bd22e4a3dbe41a76e1fdf562c8eb68629ac382d2c169ad8da279d8", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041c792affa4e1f631c8501a9ac07e6d398f4b08b5617de05b9286c334bcaf8846080e8e6ba260aebdb529e2b14323e1e36eb10eed74793d42cc7c0e982f54535d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "040890b4f6fbaa7ceed8d5bb1e857a67f91262e06ca60e8ba9aabe263c3464df7f229a85414d711aa3a61babae03ff10302cb78f58819a63183ccf57c2d44a71e8", "U": "0402eb95cc83c106f5c3d28af3070667adb4f4f01bb01424e2a60433fdf7e2016c17233651ce02a684550f15246e0cbcc65feacb75dd01b975ee4c4c70df0fbc76", "SERVER_OUTPUT": 0, "V": "041d199d6614eedc462d517ec5435cdc01e5b52fadce84a05edf93fb6cbc98be4303063b80b5212660a16353957ff0d49b488124c46a1bf667ad59108480e9f0bf", "Y": "2184d4fed5ab7c33ba6faf497ff4442ecc091c3503b1f2dc142944b590e2c1d4", "X": "02adffaac692b7b9a317029a823310ef43ad9b05acc406d97573559935cf29a3", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 261, "UT": "040391725e99fbce79754995546862f0548c2b7a1f856acf624b05ba7ad63f390408cb92de4fe9fe848c98adf9cdeacd805c837a0625dfdfe7957b8cf5c0d0e167", "MS2": "1a36e3382a5c034b0c0d82b5f1427faadb0a98d62c6db562034e10a6fcf923b6", "MS1": "029ba243f7639bfefe33013aa12e356520b88be51feef71def7499aa1252e93d", "CLIENT_SECRET": "041e0a210aae90cf0fd24acdae413e5bf90c4b5e73e9f25451cb619f84a63b855403fb6ef844d5032137f2572cd062c07c7da57f9d51f763b3fc0a915b37d00d62"}, {"SS1": "19e3d04c3dd2d56fb167b1fd7a0425e983fe6d7aa94f5ab0550b2e279f8c5a331a8d2d927fc36f5e7004773edbd7a4328b14ea64abf12ac7809ca1b4733c96fc19d3a6ca5e0061629de755bae70daf4a270d6a46922ed2d0d7c9027b8a4ef932113d623eb2b83434d6bcdabdfb1a7df813b06e3f4123f2b36549b5c317a3016f", "SS2": "06d9268827ee6f99cee2ee8c217e8f1d0d9747d2f1cc72fe2a73eec7995ed2660601519c19fb68c2751f538be27a5be2431968af468753ec6303e1ae17dc647a1c384737c5a030a62fb107143810249f6cb1ebc8e1bb2478670cf6ee26678bfb034cebcc63d32673376ce48f26214b94d5bebf2fa5a1fa6e5323331f7281ae8b", "DATE": 16636, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0c474804756ab74b38e5ecf2273464e3be7e726682686514ad926fce805e7c5e1675d8072a6981da1205c61304d6ac453e71b98f076eb36d6b7e509738a05467091f007725865b6586563463c261405f3a16637db8ce0c6c2d9a44cec670e3910bbb36665e1ed5e862d31f60c20a60a7ad16dcc0a350fd219007908962b1313b", "SEC": "041d8e56b9cdd7ea02d3cf7f77769628ef96df0d14ad9012f4e084a36b34c59dcc0420db6288ad4c53f24df91f76b6952df6e6f526fee90652087ce971b49c15ec", "TP2": "040b48577e45deb2be768d93a90fa30933777fddd8cef02d5b93ec901688edbc660e1e6ba8ab3724de8137347de8d437f6e88ac659f59872dfd636dc3edf2d4d2f", "TP1": "0422860bcdd6451349cb4986057be83c177251267dc89767b03bef43186eab6ca01ed1b83bf9cab4e59b70f79426e12c4bd7bfe33abf3b445556702caf9ae0d481", "CS1": "0420a351ae8aa923425fe1049885b0aba2c68c3dacb0b69e11c109b61648fa99c611161d3e130c30ec29d81ee4625ca07adfbec43175b1a470dd64a6ca4a5d9907", "CS2": "0423b184b271be93bf906b6f8878ec7404aa9d8bb1d0630033d8917d881c7d5479237810ed734c88167a92b9e23aee07a3e2ce668255e8ccb211c11592fe41b884", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04139e099760c40c194b1ef25473e1c7752d3ee1e6684bb84ac4d00f8599efb2cd1230351c6e7ecc44c455d0d5fbd579ccfe0e706768e8059057bceda4a8f48a2a", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0417ff8807010dd87fe7eeee8a61fab942665dfa254768a17797892a278fb3f58d08f33109a34b68fee911d558939864c60b7709e35bb39f70e178b41ca0559cc8", "U": "040463b37c8770358d01037f35a31b0265bc984b05d4391160eac0207464617a6d19c4003572138fcbe4ebe74033c69ff62a3adc61639d761fe0d529414a3e906a", "SERVER_OUTPUT": 0, "V": "0404288f5c43407449d90b383c81d22e58aeb03dc237cca7cb33988da34502258c18f4204238def73dedc6430e24a84e1c2b736a188fb6d932e84ab806c1c2e67e", "Y": "143fca21cb961cb0a1d15c9a89cbdd21e0549727f4dfa62e519afdac40e68677", "X": "1f5e033bda2cd45b19b928c3444ab1de92db33d40e444ca42ba6c4a415fd55ee", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 262, "UT": "040b0fb248bdf3f41589515814e57af6c249d1aecd5d01ff43e8a37a0e87490efc06689072ee4acc00073bb6eb95712a8bb4d7e2b5d7231faf5d43f72a3bd3b10d", "MS2": "1ef1f2aaa530165284f57889fdcccabfaa2371d74d7017876e498f9c7f32d15b", "MS1": "04d5db99ae8927a1a159d9b0e284dd9c33bd6433f9595c34a274d2ba01bac87c", "CLIENT_SECRET": "0407723aa77dbf1a1ce214a55ad3bfcdd1fdec9af57b4e5134af8073aafa9f6c4a0142dd650683e673cdeb07736ed335748adb36f0e186f61d05a6e866378bf29f"}, {"SS1": "00f2f11672c67da32fe0f68329a87168b5e72daddc38262020162534276542cd045b4521114b15da8f34e02323a4fd2e4b96a9b6542679314960bca114b3684314353b8c53e933acc9187939fbc3cf38df8b51e66d2f70fa230db80f8d2dd67913bbc65708db896b7f58a874592bbd4672aeb02b2b6bdbe79bd74bce60b02b38", "SS2": "1d531acda9a905eea8b22f652249cc0d8062bcbe7baa6fb6b45083ee036e56960ea20436d45e8a0cd61ba9c9fc3cb7855d20713496b9771639b0d978190bdebe177076daaad7e6c6f8657f79c5049697db687f294ce5216a11bdc9c8d8f25871194c482c707c2732aeb0e7b8e6f50eea68405717096d0cfb8d62e251f54e754f", "DATE": 16637, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0f88cc1a542034f3738ea83c52c65ccc18339c2a7f2d71283c151e3832c2d96e14fb721afe4e084702f0d5a2717ffc0d2e48bd55b6fc23e86a3942394588bb8d1a7774a045032e0d015918073b615aafe6f52136102fb65117fdfb30c746b94c0af1bcf1b0b460adecbaf71dfbb9944cb5a2c78499e8ab57e30a2f1d8da826ed", "SEC": "040554ddeb66379b243d49213616729b74e8a1dfb9e1faa74270046a7ca4a731c50755b1ab2127fd3f727d9fc482aa35d3a3796ab48c2dab74890c955e17b3c5d9", "TP2": "0414430695a0f816eb0bef8e54d4638657073b4849119562f0ddc5b0b8cd547a581afcb31bbf32c5fbaef3a129ec97e4008c2287dc9842e9a386e62c79637e3513", "TP1": "040b2c7c8c5696b1be2ebef3b36d132f5547fcd7b75b70b22b086fd30d5b5ab1d512174d8750ea0df00b615149ea38291eea0f39617a517954a9b6c276e0570480", "CS1": "0403c8da6169750b27cee46be36cf5564daeeddf3bd7f21e6cb16512487f3c6aa11640b9bd384f48c89701a327b2d26868e5d6e655f130b5e1ecc4659055f0919e", "CS2": "0415d9c78fd68fb74df13416000f4f02c9a43df2a06a7720338fb6ca34871a797d0945605cde247178ac83a17497645c6cf881f9504ced5548f13e3976cfadc64e", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04197c6b3356925c6879f5be66696f8fb0055435eedbb779ff8fa15434550aa7552013e36460f962790ece6688987097c0da1440f135a5d1d086f997e0b3355ec1", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "041a7ebcb83e594c5d02abbb3d352d0585ebb7579e167afd3b784c02a9706df2f60b765224504bf4223b04e46c657e5a103e66115b7e855f59bca425c12fae7078", "U": "040525cdfb1bb1e711ed9a0d79d4c24e7907f96d8bab4c8f075fc1ba05316ee02c171d45c40a248a0e5b38996c2f6f4aaca43aa69fa3270b0c4250cedc75ac87bd", "SERVER_OUTPUT": 0, "V": "0405058045895866a776886a1ae7592fd4188563c6f1e2972dbe46a6c01fc1ef0511a070bc2150d63e13b9cd0d13e4485a87f122d399a931fee9879a72acdcd12c", "Y": "1f7bf0428383637bbff92e8bfc6a28bdeda96aedb47e97560e0daf3fbae3d6d4", "X": "019f0a84edff48341a54e6a1c77f074fc1a6f438a479da3aab056a21bde00643", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 263, "UT": "040a9184152a47ce30964dec158a5efd3bb1b1c40a07cd00ddd55edea60a6d7f841e32ef75366e28e9d3ca7b934614af787c4a87ef483d3b8df474b7789c3462c9", "MS2": "0562ecd1e9af139bb7929aac40d37c6f1503d23189b8700ca7bd7512c28c55ae", "MS1": "038f40fe76dd8a7a6476485cad8470aec9118296e53d7c89ab38b0837663888a", "CLIENT_SECRET": "041052ba8e0599df3640303551b86e5e238c2d2cdad121007f56bd70cd06a6e1c121b10ec8953a952b7788e07cc4503b677572cda5e45cab72511b1f03c805f311"}, {"SS1": "23360ae3553c75cae1eb0b2fa6608ae033acaba9fc72068aa22850b9c73028db15ca28eaaeb6954aee3dc419b85187e7e0edd6a06c67a6199ae65e7884a38ae807161bd2334161a80f747d533b2bb980cd070d2aade2c63d43b6f6ba58c8645303d7fcde932d8c2e821de7256ca2dd3ede7c28b7de8b4fd1bb48969593b249c7", "SS2": "05ed08e61333695ea5675f137ce28d9e320491f0d3e795c89eac81b41b6b74771333e05ed4ca2cd2666290eb6aed0c38b4d52c693184a9d6a972e26b7abfab701038a9c019ad742b85c7b50726db7f986e9606d1b3f9e6d9ef712088ec88ce9004dcd0f4ad825e087f442cf12b92c783c3dbf7c6d03021b764ac86a26765f0f6", "DATE": 16638, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "010608e45b7a466fe30a13a40b209a9289424b389b860d141dd06999416834e80d6b44cd1f37f3efdace3d1d57eb4d5bb73b0df4ca2517a01de3ffc8840687751df102107be2f0f2d163fbac596cab4d4ba4b901a7411ac1f11ead3fa186256214e90b980a878f4e2d0b483b4f84d9a08802454946a251e38c60a948f87777ed", "SEC": "041262c50374cd069065a82767ac42ff5323c2215697ae9c848c98283a2657ad1408337311e41e461ac40254c1b446b3915998158bb3a037a3b724d31830546e50", "TP2": "042029e6f5c617229abc6b78ca3cc9614222618b221e38e801bfbf3777782c87fc117b41123c9de9eab42d713a799bfe4d889ef07a81295dedf2bdbe45c964524f", "TP1": "04125642d21168ab6f590efecc46a4d8f327fa5e7abe59a3e23847c22a758279ff0b224b2328cb71436f5e0619002a9bbb5083ee345ab66f5bcfbc1b6badb7bd4b", "CS1": "040d891f0bce4531659b0727f887d6c9d19d7bea6a944fba760b153991e195572b19e2610473920732201c800dc55a54877185b0cc459c947709bc259325a50248", "CS2": "0406285cdf4ab6514a2877c0c929037cf54c1f241b6104cf01567b3301522870a503023f606ef2c8b2ec2919ef8a1724c7b76377297a49bc9088fd391bb3b4eab9", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041d2fa9abdb2729288cb152f36b7966102de1a47d1d7f686a284cc1bf020cc2b914ba67f39fcd27dfb86ba5e91e2a6868e65e4a698a1eb2cf26f0009f82177f84", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0408202ab22f6f23e6f3a9302358ed5ecbeae6ed874828580f7c3f6b6497d371961033da7911d0e519cb35137d1b404c053c8b5c85ca5bf23fc81629381738d162", "U": "040d3ae2fee82329942561b44a5217c098ce4aa337e328197893afd7cfd5c7c5c7198e9498778e9654bb370a58856aae6d9529acd52b87acdc925824b017fd6369", "SERVER_OUTPUT": 0, "V": "0409519b418b6213f3ef5cf3f91e3f78d0638b0c8436d72de26378ab03084b6c7a1f17eef034ab25c039ff8e54de296458d3e8fcf7040ee55d4caf4767c66808fb", "Y": "23ea3f32b84ececfc695d8d36bff3d15ba7b28e17e1dd2dcf59621fc1b4d6800", "X": "033efd4d7e842a3223fb9f94282d6805e80c09946617099c9ea0920060085f28", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 264, "UT": "0411a6b3724fc806ec0481ce2af1e82f02e47cb55309851082954dc35dcb9a5b3420e7f587a3fddde9d6b8780d15397baefe84c589ce17e1cacaaa673e04736e12", "MS2": "1df1bb7496d1000b174eba9ac1bdb838b0c372227f7da8ec4282801a7ffa94c8", "MS1": "06e7f75775e7d26a800d328da74899b8f7de5bf4407ebd9c8e799e51b960da79", "CLIENT_SECRET": "0407036e7afc145141e18d10493fa2499fcccc72312f8f85880f7cfb67a63d69021ce6e3793260e52a3d84b935c4dcb1974d873d9df7bd1cf49738d86239fe64cd"}, {"SS1": "026f3cc26ce9ed0a7148553d5b6ce66cca470772773a351b92ae6c2ee6811016127ad9e4116b7e7d345d439922224757639230b6fb0bd2390882d2d07c180727225f92d0641fdc9a3af7b705cc7fbc1efeb2241f3ad1502c77763bf14801d4441c08adcfeae22b9ac118835ac73f8221cb8d4fd83599c75ec377766185cc1a5f", "SS2": "22cb115c1c21dc4c69115b68923e7b0af5c9f72afae7b7227b4bd004d4fbf725166942d2325fb5e69e27813dba80101d14b7aaa51177042fc2e92b98890e9d34214cb7fae171c65ec5f517ddd33f0ded3cd5c944f513dc1f09dc0aab6e0c09890003105485b186a9cdb88d0f7db37edea5a192122c0a99118bf9f47b9556f9d1", "DATE": 16639, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "15090b56d01971794b12264e9fa63546f0aacb7ab03678ef3c10adc29eef0dcb0e2192ae9443157ffc5ef4085f6e7f96d89edc630d680f568fb2fccab857f5021f982c16854cae84e50a16443b687463a5e87d1493feea9bc7420233c7bead6e17b06490bfbafa0e253976fe1637ab4118d18d7fbac29b9b9fea5660358c3afe", "SEC": "041ff2888b25f414e07c0f64a1a5fd9702f2c0af0bbf27d8c880905ceba291af190c06dc33fe4095688189552d81d4e5303ccdb0fbf37487039632947009d364fc", "TP2": "041a5791aa4d98cbdff784449257f77274b46788ac9b1f1e12049adc82d9476465009c7a1e41ac59bf116f3bcff7a2acc32b18f4926aee1effab876a911b585821", "TP1": "0407696ef9a682190784d2b4320435f4259e3d18570bbd1afca2df5b458fec078100fc971565b24f8139ad3453d4306a23f6c67ea42506342046b675ceb854bbdc", "CS1": "040446533e876742e617c01d4c49a68a2fe9302345c7cbb8379d557170d09982111a183e6df6e83ba6d7c02bf3c5b80ffc1927d2f83968f4066970129c26d1701c", "CS2": "0416af76159c0d5c7eb9141cc028ed2524b79c3c5b2c74d2450137f0f616c2c81f13c347e4eb873b6cbbb0191f1f3bf826a4bf5d268d5458ec92044b6972916e95", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041cbcb16d27ab8c010d386281713c728e229bfa593a8880952d7e477a49014a171776f0ca1be245fcf1ddf3b498927670863ae2732c6f2c82986d2515df01c17b", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "040522d6676b49b85aa1778e84392da8def956f8e13b6442d1b9017032f598520513f4294a9cb317127fa8dff97c2d14835b521b688d5cb9c12245037ea6d11965", "U": "040dbec3d36c9b6f1a0d0197c568c05ea170d80cab810a0c4f1e2ece534c3bfa2f1cdc208cfccd7941dc5b6171ed651e9e2cbd4f0960e2738247af88a7f748838a", "SERVER_OUTPUT": 0, "V": "040e6e7564f22e28ee62dfe59c3b8798d7f8e237d84e5d5897ad173a36d631d3601bd9bf99388ed63cd82f3270227184071846be771874ae6ce02f0895d73bec1e", "Y": "19bd3c40d210319a3b1f5ba94fcf6f1cadd67ca0b55ef7a494dde425452d12db", "X": "198fcde3db2d9a6aab196ae801c527e196575a830be5ceb066c8fa4f7a3db1da", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 265, "UT": "040a1a14588a81c150f0a9f692f2a58d30b942b93bf65152d267ac798bb68dba2d131cdb03dfb6e4c64de506cdfaa10e932fdf8b0906aaa2060563f0c292124821", "MS2": "141c4fbea6565c9f37b8a0c9092d4fb2f56822950ec59b8aabcc93cc71b635ba", "MS1": "10ba1b04367ed3e7d4abe2b648e61a9d4127599263a2ee5f1f087099ff124746", "CLIENT_SECRET": "04107c7aed9b583b4d9b1259b68fedcd7378befcbe474f8b75332351c93989a6e20801d3de2e070327aeb1ad32aecfb99e12679e2fe3e1101243fda62a188b6cd6"}, {"SS1": "0d9ca7b04bde026ffb4fee177762ef368abe8e512ff61a7e7e0052f9bec5d2f004c84f616d91fb0795645701250cba9cded8df750258d96afff1c30dafc5111507e29a0e9590adb1800ba713237ffa6ca191e4230c3624f8c781989a96fa242a0709e3ef363ffe4084e4639ec51c5973f6d4cbecc90973703e5bb762dd314f91", "SS2": "045098f45c730f77a58a860df14044ea30b46d2a2fbafd8a97725fbfe1623fb7088bcdc78dc97807c339844141bab43bc6fddf0de4eea43d495d2aa316d47db51cf7e4bcf49d1b2678b69bc579568f9273f615687bf1a020c29f3d84d237467c0920ee89340a4b207870ee404dadbb816b75777136ee17909c2fb1208535579b", "DATE": 16640, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1ba612eb79de5268b0be3b155cf03d43bb74b35c5af44a2cee782591629285930da7d1ec99f47c1ab5867ff7027038811f5c8715a8850c39c155302e402deda11c2730a716b669dd59844620a15ba10957932597d6b6dd0893f9d62d220ce3d41f0d5d4dc59771ad5c1d2f1a1fbfaefc1ee3f8aeed6183c725e9f0306114f4c2", "SEC": "040e5e8db3cc641f823fb69c787b0fd0dbcbbadda14ecd9ed549934b3b2774f52500b51801ac849ada1a9cb15e57a6786ddec0b42a52efa7f3e55d4992ca06c24e", "TP2": "040ea61bb37fe34ca45fd46683da7614bec8dd17d061379a526ef82bbc1dfa2e3a21bc582735e90a5dd7c656a760a6dbdb01f325aed3f3b04067d41a4d336f0334", "TP1": "0416c690854a789a4f6d2544b62c2bb4691e47cb2bf4681a6d30b5dec0f957bd921369e993644dc7e4d3db4a3b488f22ec7d4e0d161fd21c765074a4691120ffb4", "CS1": "0408d6a47061e33316ec778ce165debd4397144ce289626d3aa6f0aaf694fdb0c40a7e93e4cbef58cc596714aad51048a3aa1a01af417cc7a065d3a183777c0cf4", "CS2": "04011ef047badb2dafbf028ce962b796d7d05f7945f69bfd532ab65725398a82ca2234bab18c9697350c50fea380f6ab4e463f5474cf8b9381a8474177d88c93e3", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041cbf5886056fa84c3bb58401aa24f3d3af8e445687c919cdf4bf19d4c2ce1282192f9b88899ee3e121a94f95ba66810546489714ebe6f0db1f377a5523d16829", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "041de6a458afda4bcb91521588959dd578785636d40920d0b612f6947704ab25580c9ffb729a7bcf726198d07487eb83b0a4bf4c8e2a1bf989abdb88a15573b816", "U": "042306542342970180be5d58dc8560a1facb4653c020f69947c16eb3d4a717b3ea1288fdd473e1504ccb8297498cbf41028d553aee19b812dd24163fae4f5da731", "SERVER_OUTPUT": 0, "V": "0412219d37008b75dcc254bdb1ad9f409642393dc3f4943d8aba8a8cdc8020f4641632218c169b362aa8b0c1877b6ee280032d915eaa6882ec8ffec1ff8996cb11", "Y": "03ab3e4d8db4c3d1f03401752b13975dcae5e85d3006c029ea4a427bebe5fdc6", "X": "022bef1aade379aabfc10c2c33c1973fa2e5a981378d27dcc7b993f2de4ec1ca", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 266, "UT": "0404895ad7d5f83c02cd9418dbd1b1aa5269ab2355fb7abead73d6b93421ec74c2112606d6d3d595713cb52fcc9bdf06d42ae97ef7435e43414cc1a9d4f702d780", "MS2": "0934480752f17b638e8cec0ab15f895eb71f2711323ec98ad3196ced984cadb8", "MS1": "13f3374caf10631ea768af4925787a9200a061ae0d5ad11c887b1b8b2be231a5", "CLIENT_SECRET": "041364224726ac4238bbd03c50fe0804f6a4a4eabc5468c44c20385e18549f6d87078a13b3067cc65e0e35eb9c5572c8f86ac89c06002042956ed0e92b13f54017"}, {"SS1": "0917087388e450d96fef65bfe7c04f00a6397564213717e125e360eca64dfc0f0c22bf888704b2e52ece1424e0911a739b4f80d6213e371c8316054461c7dbcd0563bf3c6641b6477b50d31071ac4849e48cdabc9fb652be340594b584d3435011247731fb6a70ffb2c8fe2d77f8f2a419205d3f71f62ddf39a1aad6936fe4fa", "SS2": "1b5046685f4dffbf523a50e701f008ad6116162d1b33cca989d17bc56b3d83f217c90140661711861422c9c48b6dcc5a923f781c295d90dbeb79307b730c73ff1e2faaf48b1e68bdbed5dc989c09668cae5c7e83279fabea10a00ad0871de6d0071ab509d07dd6e4d349342504ac8b84ba9cc010ca89d4041ca6bb55dd0d1712", "DATE": 16641, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "02e4c3612ec965ff0f2746e234e4822be6606f13886a25dd23e922b72c31f71f1871c229ae4ae3fbe95b1ef9e621e1764f274f3886adb192276101d1cd63d5bc0555e08fe5672fa323a9281314c29dc0d76bfd1fcc3c84982ee47be7a090b52011e8a88a4fa07956501ad62b749fc97200cc5fdaa8f0d5316869f9c71ed9dbfb", "SEC": "040ad7e51172b504ac42506c5426c7b81b859124094c4af146005af692c7fbd9341a124522c192407048a3f3bcf590381b914299bd94cc3d7c7a5550885753be68", "TP2": "0401a8eac1872ed0c3aabeaf8f9c613b40b228c0520401637edd5332485440f16a069fa4d43f009dc84496c1ea9237afbe2ec98f135df82fb96f9debe7f433ebef", "TP1": "040e3b7d0cb994224387acde18957c0b6b9915aeb9f6a248d2efb8671ab4cea0f80b638314f82b7d72fcc19e042e69100d385c612abf31445cb86a6f9f9ee1d4c9", "CS1": "04057329ac5414d5ce9e0d508d0f81444aa1d52963ba6501687f5fe8063c9490551c5879f3e2a6d226b553fbb597b5e4a53ad861c8f7b9944673bbcade6c3b4cbf", "CS2": "0408797856d85691253ae12391ceda300f1ef2efd896898c3c9373f94027dc8c690aa52aebb7de9d6aa7807dad9dadbcf6831d3e5603e01378c1bfc87aa0119e3f", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04093fabfff7d5c951303866f20e151ab297b7c32ade7030cc97388db0213a0586137e678a91308878d2f0c38b01aabc4ab3fd562a41e0f60ce30c374a6e63fb82", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0407a42507fbafebaa76576c2846ffc49db691710378b8258658f6a1f0c0cf04e01a4aa605095363a1a9db280b3a7d1831bc8417e89c01f33fbe63463d1736ba2d", "U": "04070a5a3e325eb468a52495d79149f4080f13925c0bdaf3c0a3138ecb9719bee51f2eb3ff484f8dfa8392eed3797fb98e51a6ed0e7441d2d6db835f47ee81e6f0", "SERVER_OUTPUT": 0, "V": "0405e95a05661e8b6e90d4af87f956b0652dc620990fbbb30c9ae3431d4bcbe6d703dbd2d363cb0e28641e5badadb92aca0b71e378995c12707caabd0b1fe585c3", "Y": "0791563d9b7cbc6c90c6f7ad97f5b85251579b93bb0fb55b5579afd51be74ecd", "X": "07a10449fd16d40c1e42ecd7c5d500cd146722660cdd31c4210b75010c4d899f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 267, "UT": "041695f78fa43d035fa7be490c7cbb2e542a268946916fbaddc2641e9547418eff0fbc3ae52939b08e062db449a8c815f9b3d935d059706c9ffa03af362cb12ec1", "MS2": "08742670a706e79403c2421dec61ef795842f4c82c9ae32f30607c7e8c1461d0", "MS1": "080c499765146961da9ae7c5dd4dd35b9300f45aaf18dd5427b209ec8dee12fc", "CLIENT_SECRET": "041826dae59783f70459d8302debccf442542db12210b29527d4943eec5b4fd6cd21932957eb2ed34ea6344eb4d778264e526b32c87da98581598f08c43cf8ba83"}, {"SS1": "0bf2a37b641ee5ba10aa7967613ccbb674d887490941e40fcfaec21f8a11f7781917e56898ee7494dd1d65d79e237381ec053e008312a852b9181fe97e65f681101a7a183e5191bb155f6f58cb551449d3ad50ad2017f5d08bbf190372b38cc105175be2b25043432bf8a4b692297d381a9acf3d603494bcf4ac01a3ea93f6ca", "SS2": "0e2f45d4a8c830e03ceeb4ff75e394917fd3fe40641224a4aa3134f7f9e68c991f15abd375b0a1c340018dace393f2ee24dfc1668cba225c41b84721ca33c62a1c5a30ed87fe787d7b4c28e73719c7356023660f00fcd2a74da4a6a411ad5e1a0f57fb50a1005d15c40d2bf9846be2644bc1426c14dacde609045cafd2fdafed", "DATE": 16642, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0e086bda9e2bc88d02fcb4071718850a88d6d11c666c42e9f5f37780da4d31061ddf16f4c197f38ea1bc928b0ccb452edff58b1e7b5f3f0d08ce5a298cf4b35d136e93c948140a5b7a920c2403385bf9b2b76ea5776ab8451ecca37920cc98d31d6d372456062b213e1d6168ac8320a25a246cb82f7cc7de4064a49e9bc2fb5f", "SEC": "0419d14d45952b33eb29ed53c157a03267704d1028ee73cb774cf2f72ed52eff2417406ad29ee44d4bd390e06fed21d7c9d6ee185d8491fb203e27df279da8bc52", "TP2": "041bb6c6fd024b92658082c6eadbd7b5d6433a51f1b22c96ea4d76b49865d92adc1d6e7d290880d53c3687c6f8341aacae501dc6e55d5c729622c827bd5ed1afa1", "TP1": "0413437dcea84954c81391f53041a59ac9291b4a97be3bbaa94325da666719d76108e36090345eda913f3d2639afe527bbdff732d8b91c29390e55d0647b9a1108", "CS1": "04231ae2a54ae497b99891336f6bcd7729539f64a8a41b8e2df73b95de73b72dc704bef579c80770352db3c875fecbf287284380605ec0f547bd989610fb4f80ec", "CS2": "041214232a4115f16f4ddf0a7ab659ac67c8bbf1943e1ceb1826bf85333637f65f1d99ee12fa6416ae2326be44531a699c80ba94a0ab0f296b0a8570d66f1aeb65", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040736f84bac6ed48a817bf54804ddd6c34e8e0278d498bb234100cb4f7391554e03c1b9388e3af649ed8f6116d390f68b615034c3b2cda54e06950fa252acf290", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0419fe4644d109eef40f00789918fcadfceee1fa2077675dee53aeb33b62cb5d8d1f89173ae5478aff0c80949e017aa54da2f2806fbd3325f1b920f0dbd008074e", "U": "0423e6bd2a40203d3cb06357dbed6012989ccb2bbfae068260346f5799bb9791320670ad8cb94563572b53c4492721a4100ded26073a9c95afd9975a766ff534c9", "SERVER_OUTPUT": 0, "V": "042318c1bb078a6b72dec1bf74de86910b293c9d72ce31c99c8c8fc123b999397500e03ba85a60356c58df5974be129be67cdb1483df58730d670d6bf78f5e7b52", "Y": "1b5bfd2e92c31cedec12657268d90eb1a456d746480e377a51398945f18f132a", "X": "043154c1e4b8a4ad34c25ae8648bd04abdc7b7fa2e0442131b2d73917e7465ef", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 268, "UT": "0402182c8ac37d85b839f79fefc07caa99f90b79a97f3101ea5b0ef5e46397694107657dc227b4af14f617649b42fef3be294595228ef01f3b41918db8d0b241cc", "MS2": "212338e0070cc18018d405deb6fbdeb9477e6c65ffd2934fcef283e248f22374", "MS1": "1b85caa327751dc9c5fb454512dffe02a6a661a1d15c16836501d83a7c3812b3", "CLIENT_SECRET": "041f41821f0c8335414156e180dd6da3cb63482e41efc3c31dfa8736141d0362831dd3d641d3d34d09ee2788d6c7aa71ea643d28d45affa87d8fb9e4897fca848f"}, {"SS1": "1f955c8528c8c45018b17ebb1e0665600551871dac34694a1d961551883ed4571f806825d412e76b2ecaab68df148f28afe97d8749da5c87463ccf017f983c9f16c4e6da2b8f8fab9e79d3406764e23d48e96e653f2fb45a0a0a10ee2656c14018adc2a976eb8bf711983842fd81edb2ddc6cbc4a83370699bc8afa7701b78ca", "SS2": "18b5530a00a12ab1f4462bf7962fc7be04805093a35708edd5cbe749a4d456b51748b8eb734af7bd07aa7fa44c3da4719e705d15bf961125d1c0323e0f2aa5dc1cdc169e3747cea7d55a3ff8dfb2128dbf3f81af2e166d3557bda22e88bfa27b068d194a114319849535dc53d43b078704b153207aa78ef35df7d48a5067a2ab", "DATE": 16643, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "028719e4bf10071fe2d1d0ba36c6a529bb869d1c29d084c7c5653ea8012c8558134efb9b4e5c9cb64cdd7d10d43009824b6f40cbf92e69425e7c018a82270666097776ae1b5493a8d981db67e9b683d91db15b1b3868a6838c70a3ae150dc94206975ab4e580b721c2adbd3a7a937853378e9da9356e23ff440c3e328cb6cefc", "SEC": "040c4a78359605a70452f578ee17af7d94d60bc1ed878445935213c854ecb2a6f01c50dd8dbf05cb4f3820d9d4b3cc81d07869ccaee6071ec0c09d659ad127cbc2", "TP2": "040657aab24216d4ccdc23135ca341a8124a01893059f2f2e0273368069b765ecc20adac66ebdfd3e76a585f2dba1ae572e2a0956641d8e8b8ffb2585818b52d75", "TP1": "041d60d003fc33fb89679cb9435469ac4d2e0e9006ada85238fd3dafaa5a9f1fcb1bf87b8d9775f2a90913a0bea2d3600abc35b81444e300f53c518b91602d9668", "CS1": "040ebf5793e806a9d963c8f074a430b55e6c2dc171722fcf97c4e6a89fce729d250517a88c19012a761aa63684ec2ef23355acffba4ef9f60f37ee11aa6709839d", "CS2": "042251ed64d56a8b7f78b3a1a814718ef550a0f280db185d63e029e6faa9c5b4fd0e407d29a9c64b457dd6262b2bfabaf34e9b7a009b1b8a93b1513f6d623a694d", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "0416ddc14376f67f5509957436989a6e8373300fd23a55c04e00ea3e3bb0d125c70a2f7e16acae7a66a73738b990611878caf6ec3664a9cc8321a0290199bafec2", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "04192a57f1f504f16fb46808ed6981dbe7af889205e4404428d23a8b0946b76ef504155ae0501a28dd4bd5e3ea9a762c4796b3c902ee53aa16650de00dbd244042", "U": "040f946adb3cb3036c74731e088cf81ef9814133da894135adf89d9bcd82f3bd9f078e55b12a95e126a2b5924a097fbc01265825384115c05176c862a4b2ed07f2", "SERVER_OUTPUT": 0, "V": "0401f1e0e917a462abab259fa86579c516811c0e3b091a094433e7a262a32af3cb11ece6d82f9b074d9b5877e0e18036e7f6463ff21b5bc586e005d90134d83ac1", "Y": "03ae5b05ba0226511086c1901a461e5b3d50df6122fec53119af55da8f09c598", "X": "095a74aef38b76510b7198e98d152461462fe4f54a1bfe23971fb12399d3509e", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 269, "UT": "040d937b8fed79fe4953abbb364caa88f47ceb7cadec3777209cedf04f80cd97260c3f50097d0c08e25f7727709b20a75a2c282f095af45e9f1ee8efdc99898066", "MS2": "1f00cd2539fbd054f0dcb9eaf3c2206b6289035268b29b4bdea94cce0963c6cf", "MS1": "10e0a2beb310b3aa2124ec9b8b807cd6630ca6714337613db1f8ace91cfd409f", "CLIENT_SECRET": "040d66bc05bccbb1d62250f863c2d6ddd0b322ec476bdbaab194af7067c6a5723f03f20a5bc22dd77e1f4d965885652f5cb8e92f63fb40fba1269d1d15f1239887"}, {"SS1": "11eeaf656ff6f71e61dc1a32d9ebf52c062515433710eccebf940fd134d5412d0147afbfbfabe178daed378ffc7ed4061b4e065bb055f440025f684111e69f19166d44e78fa94fc11f5007db4119366a94e0944b321eaaf85c8eff8b5daeeee91b26fe3442c0f68b56904fa9f0cb412c70ed09aba3c33421ec7311239884b7c7", "SS2": "0124731e6076352f3c51801cbaa9e11e9c9686479d545e3d29251f925d8acddb012388a0f47b1da878c7023deb93531be95a72c058661ab35376b5d44e2579d10d477e9e31b60fd3259280d6949787a7e5419fb2755f4823426e70e5ee10d3fb20ead44f289028f2f6bdd172eddacd87c53bd154c809ba44a99d117c3ec277d6", "DATE": 16644, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "15c0204f57183d51a5b4b21bc09349f727e727177a754a1c05a2fac94e193d641343059a9fe8e41ad297cffe222ea9482d06f835c7d0d55a0a88cda727f1e98717d1c2df800ce2959f3a21aabb9ba7aae814d825442d5ddac1fe06c45f230ef5094b8f058ed1d4f5a258b84e8cf4e9b9fbfc259b8eea9f7c89aa843695ff33fd", "SEC": "0404edb3f01c5b8754537d0986ebc162ac9f18084b4261fcbedf8de78f4eed8de208f9c76e40bc656844f9ee053ccf40f7004815ab13702638f6f11cb675387bb6", "TP2": "04064d16ad2b62e5c9024bc6353eedc8425f23a79737d62b4f72ae137c31c282620c724b8d4dffa508837e3f30174a88df93236f4d486c8ed847a9e4650af86c92", "TP1": "041298754a0e04b13d6bb4563daf40b602743a3cc8a2c19e891c2b1436231bd88017a40c91cd8334a32d0366b7b0651c7c97dea552aa409ff0eb4eb7419a92a5ca", "CS1": "041daf3214dd78c4c8dca97fb7110967b74d1446dce25933fc47dc10fb2d1162940b956cd9db2005ca00b3d7b0307332f02205843097754490fadf755cfd0993ba", "CS2": "04197c893f9f3ed0582deead49daa5f7de2d7e3972805d7191555154824f7fa4ae2286e1e6b0a7b9283cf4e965ff14eb83bcffc53b886282af12bd5bb4b351e5a5", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "0404bb88d467633c3fd22ac2d09ea4438319479e53f0f60b38bdfed8d1ab7321c5147126be0d14e84a81c344ff88c437465387ee53c318e1e0a9cbadb37425d9ff", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "04121aa6e08ed193fdda4b56e6e53782f27ab7a81b490f7b134f8b833c1b0b7f5713226dd4cb4d83cdc2eda65f308517333db6ba60651f2595da51bc58f59ece8a", "U": "04117065b76c866c6f45ee35705e7ea7ca320129512142be9190c27a1f005fc4e41cddb5beeee0ef4f5076d7a00400adab15a6e04582779226a2e9b1280f361a5b", "SERVER_OUTPUT": 0, "V": "041bc8c3fb3b405d6210d643c667c915397bcf2a7caa3360db4d309fe26076dc211ecb19946d6ac75bccf79b7e7c9639260c0a3214fce70843c22c3efa20f732f4", "Y": "04979189b877ac997113f77459bd6bdfcaf4971caf86a1d37fc1acad1b2ab2c2", "X": "17894da52b9882a05e6684aae0277cc0f7ad180c9b171f8a26e833797c6a788f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 270, "UT": "041ca741d5140cdba48581e889bd8110e883f5a7053f73a4a27e42da51964f2afb1b861a3ed29c8993eaddc16d3f8cacd2c3cc0a4fe4fd44448705ca53295eccbe", "MS2": "123e7ff63f91510754185e128c96183aee73b3caca37164a7973b7d13004d574", "MS1": "07d54acad9883f137d60a237cc389452187d31000978be8316cf7ce2273ecb48", "CLIENT_SECRET": "041291de93a69f485ae7fcdfa20e71bf3d6a926d8a265adf51d51c7fac3eb56d9622ddd48488c44ae7765de08ea2316de0bd5f5207996bbc98a70d7e4e5825e41d"}, {"SS1": "038fead1417efc660243845772147c490030e9efc1765176379331360634bc2723b0419ffcace826f257f1a12f4f63acc9f9d23da357fbf1742d0e250fc520441fa05c0961051bddc69542217a608bb6bf16a66603924612096cdb287ccb7b330401bf4a901ed672a1c0faba7b175d630923de731674490947caa2cae4acd517", "SS2": "197b8578fbb3b5fede94500de8f6e1181004805b0cab1b313f4e3c9da25ecc50173494f8daeda4e7bfc19974fd8f7eb4a2770b767dee1d1176bc017b37762a3e21cb457e6b81a28b7d1df97b2aad74cf4958a9a8ce5e154daa56f1ba50dcf17322e1f726d7af9b083bb3b92d8a186253b4f39113e17c712cdd16be822ae24f22", "DATE": 16645, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "07c5922a063bb0b3bc67263b8ef5e1c28e59a02f6d422231013907da456fab091390d6d890e6d654ed32d2119b676ee52f224f3dcb56fd90b0df0d21b513af5401adb9393d54a7a0b3c7357e45d2350a7c042cdbee8565159003332c5733e28a148c04010a3daf09539723c18785b92da37c11040634d743830e2b6e5da521c2", "SEC": "0413aab3b897b83e5d694f5cd8249cedb5225f4cf6abfb2eb4beb317c56aecbd1512685af96cb4f171247064460bce45e202e0b4469d808fca586c63c3c9b77e52", "TP2": "04156d4965988af8bdaf82e9fa8d728b65794d095d64a8b3dc69b592afd1188e9b127ca29b54ed00fae2708476db644e3a6d8475afe7f4debf3065a64693489dce", "TP1": "042286e169740f5fee8d0ac4823f84509f7a0eb335a937e758f9f0b414653625ae2244bddfeae05ddb0306c0b60e1a2e6c646beed33f3fe9eaffe64093749d51e6", "CS1": "0404ee76d4bd756c68dc8ae576899561f7411c79f9af647034a5fde6304a2462a3193c83804f789d2614248b144743dec52643139aa82c072274fbdd53a081ed53", "CS2": "0402d1fccc55c30fa8e31d3fec632da209db0724449137c8fceac9705c068c9ba018f1240c4230bd22265d20d1677c9974033b99375cc9b90fec62f336fa154220", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04203810a9f7ecc60f2b6e134a28b600ebbaca36729db7222774261bdf2ca7ab0007b174f300b5fa372917095697d4350a07f4bffbbdab99b9bd5c283c19e114f1", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "04093c068369c9477f92bd4195297a4a444594149a4dd3531fe1dd07c5a72c5bbe0e6ff79dc553995e610ad922f26ed5a27cfa12568a33bba7c2db0dc54cb36a43", "U": "0408e93c44fc0cf96ec2be9b0dc5706c92dd81d3b254338d7af0289e0f538751aa171e1482c572afbf445f0c4224a860b61710f0deb00d3ae6e48813f6a8487a1e", "SERVER_OUTPUT": 0, "V": "041c757eb39e6954dd8e11a8c81a9ad540509352c87051d68f19a10c4325a69ae304707ef4b6fb5b069552c24e998cb1ab30ebdac0e7b8a886da29893892822511", "Y": "1d858c589abc686bd8c4b4e0eec45aa69db6f3655818b99ce59e0b61e8d03ecc", "X": "0b4f22867a4f144f9edbfef1bf632ff7d74c589c129459bc4576233bd45173ba", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 271, "UT": "041186885ed44720066f7bc6bee4db5590fa3cb02b3b606d3dde511b467f9d744b155215779ec5e34a23ec89cae4a946debc02b0cddaf5f7b15f9166c1086c089e", "MS2": "16c041895f7b5bcccbfac8c62b6fe0bab0008b7f74c80aaa5bfc3ddecc1f3850", "MS1": "0138cd7777acd936c95c1911fda09d18a7ab107e1c4975ae4912cb7bc9d9c38b", "CLIENT_SECRET": "041e085e7c98689d9109978066f5e2406df0f444042abea2572360748107a90c69151e1e3067d2cdb539c922a0317dc5faa97dab53671cc13fd5ad37c70a762bfd"}, {"SS1": "0aa8c3a9536560b775cecb9eff90e1ff4dfac9b61e2d2ab482f45c476329ad29028b59c3ce48c705fdadebb660d2bec5179e16a16b29ac7dc83ee51301e95e4d2050a97ff487bd0c427d40d79594999ff4182d6724883fa3179cf1571246174b08c3b5633fde6955b47c460ef3132aac7674216220fe1208ffd73c4bb7c7594a", "SS2": "0ade07b2fe1742a4b983a37dea1357d71f5954ced86977c400f01a2e15368e70239ea61e79795501ad73920cd9802e290e9f3212654dc6b119d77ec2f89e1d4b232db0ea36ab7fbe612c660cc47dcd70439fc2e3be4177b402dbc2f3d12dc8041b05356977521026989d1c8487a98ede06ecccc2cc6e12a5f84a39a25158c7bb", "DATE": 16646, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "22d8edbb857961c67e6c22ad8de98442a61644f4db48ee5f71e0ec48fd4661f9011f708ae68ee64b96714cadb5b473ef8ba860f195e863bc4e0a495a237ad6e305fe5ab19290b83ea4714315d7b0aa5b831ceb5302fe762cc3a8c1d0c2f426d316aa0c9cc1443ee7faad7721940e21ab9e48a7002d87bed6c7acac4e2e5312c4", "SEC": "0423f21b2835ef9c97f4b28da429e1984ee309f2838dc1e4d0b577f0856cc183552372aaf3afe4ef5ea9848d93409ba4320bc8ea8a8c05f7a1e86c8a912e580c42", "TP2": "040be13af1eacea6517ba0c2da3f120e63774ef0c77d2b890736a11883f9be49631ed2aa2102f76ca89aa6fa3ba5b295aa3b43e9fea8e57a453557569ee877a31d", "TP1": "041020948850752e9369cfd10060a4190be71295975dd4d750a462e4d48dc0a8821660b7274cecaf84e98984de0b3fa444be60e41f054fa2409203045317e91265", "CS1": "04163691a912b5a5d2918e5253258839ee77c0c7f8d6183b9913b9ac8c7dd9ceae078947c0a95594dd5a711db6666e2ef0149f586e68b6cd88f13873d77b4b924a", "CS2": "040799b59774751de13aefbb59ae0aa817a182cbf12c1457406d9bc8776847a4ef1ce3973c124d2a9db9be46003aa8406819c75f726907cda21413d56b2b2bfc7b", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04057cfc7bb9ba0b487615aaefad9c1ffb7782d3e1d5022478fb142a2abbbccda4178d74d9bc21489702dc8db8ce720ed73a21f621a9e2b3721f9543774dd2ff21", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "041d5072908325d1aed1417c5d659b6acbfc78468db13ea3040d000314e6824b8c046a527c4820efe162585bcbe5daaa4f22e497d663f19cf07866a8f66f6a14c8", "U": "0415213e644e683beb01f5447517df44f76acb1ec7fbd7f4ed7da90adbd5a68ba41ebaf0c35bd049faaa32216e893139acd4edf71d14c1250d6e615a50fcb981a6", "SERVER_OUTPUT": 0, "V": "041b4c39d16534b32cf43a02794567c8634f86a28603e1003d9722b31a76c9b4d8179e5192bc1340294102a21d66108b708db524154e0cf85d17370b4dab5a5061", "Y": "0f076c10f1d7d4273ebfe854cb0930dcc990185ee784de7f05a110d052ac2d83", "X": "09610a5eec7fdf2ea7d996328db8b229d3e30408c4045f5df72d238a4c6d9d46", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 272, "UT": "0421760cb258cbd13d99b69fae945aa1006343bf2d8f3696c661cc4e6a60e403020c88948f96dcca1e87648479dca508274767e18291ee55ab75265272b83edeca", "MS2": "10bb077c75e2c9a6ff99e004181d5168c5a616522af3ee6c7636a5c2c2463d67", "MS1": "1065608c3eaa1dc65390df0c1fa0367e88255d24f35eb6a3187e124e87e7395d", "CLIENT_SECRET": "0401ce3d4b2ba373c80551f7799d66d1d2e486d265ea231954e7531c0c32ebb4e9051829ebf887688b6e753a3fa0d587adac45234ba0f37569a826f3c6f403dfcd"}, {"SS1": "1296462dc0dc0dae7c5aa92a5e17ae26829dec89bcbebb47ce18ded0f28cbae3163bd9bd4d6231102528dbc3993f0eefd5327ec8dc145015482adf8cbc444e160de16efdfec03338ca0f159238ffd06e8765f7cb3d6c0461798f802932a606e40e4451eb12c89990428d8c500727b95b2cc2df6147fd16ca8305fd65523369a2", "SS2": "1bf90107383834ee2b8f36faf7bf855b7aaa2556b7ec56c2439bf1dd1909e2cd052718158f9ca2444491e6cd66590c35add24047d5a2c68567b24fd3ce865b0113e0ef65658677e4c7b3fc903b957e62d8f28c76b8c121271cb98fc64be0c3f218e4fa38538629cc6877d09b3e74fa24530f474b77f9092e89fb6e4ff6fd4de3", "DATE": 16647, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "08768850fc208ee823343be4e3f092d973b1d28e62392dfc21482181cd5b906f058bb17b148cdc313addeb195725905c9f1994e65be9b6957a87006ad7c594ab106d2b086b79caaf6557642dc002b692271e4afc32297dca02375b1106663b9813451ca1ec707cdebb9689d438b74e338b15b8cac7f3f8a2ecb6596495ff1967", "SEC": "040bbd6219c912de8519749d9c307e999ee0d3b69f8f43e92efebde70279fdad401ee3ce9293f6ea2eb5b872e7a387568df9fb2bd42eae899925774ded03f39558", "TP2": "041b9e15ef7c09ce2db62033c028cde77b7d3531f40d94250686751abd163c836b007f2dee0382fa061f4808ac53e177c3ec9cdd7077fd40c5661fb6a82666f533", "TP1": "040fdff2637560c2183d7ea35d613b5cc983449d306935ca7a2ea8df3efaca8a3f15530014d8dd2e8ff44a63efc6dbf74a5d72911432433434c762f670b5c1b019", "CS1": "040b2627c8c0029fa1be954585c84c7f7934677fe9048fa8bf2eb6ae78749ad2b2031470bcec55430452e744956a8e577d47712775aa91676d6288cee3bd249ab7", "CS2": "040c2eef076a2ed7fa94d846d11e572e1c99632314cbacef2d4435605cf4c595a60a5b04fe943d87caf925c34bb7bf1cd80ee354cb82bce3a62936b61f554d2287", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "0412a501cd3f222fc980cfee757e26becd7b2676628392bbeafa66d69a63c55d1303eeca9535a884ba07bf292067fc5ddeac5a72adb9d9071e08990fc71742ce42", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0401a93a11cb4bb6cef4e5e7e488f8f20fb785b16429f2604a06beefd09ff35a5a0b889e729e71dcc6dda73dbab6f0f1dd9a639b3ceffd14d561ba478f092ea7d6", "U": "041090d5778cf70f78f5515c69ee19840f4eba65c8dd58e69f29e66bf683353f6c15999c0ae0c7d09c0818466b7d6593ad48153e9ab7bf49119c6209e44fcfb821", "SERVER_OUTPUT": 0, "V": "042134ca52390233f49aed75ef4bcadf9b91c2fd6067a02df093bdaf567ef67fa80402d388c3fe9e4e90a788fbfec808cfeb87708c4b0f25242cbf4186b4a0441d", "Y": "1c8f5f96b5c5e3388426810a614ad72bce3de03319aa40ffc12c5a7034bf3639", "X": "0e3a2ca73dd20a0216817b9819f525fe85e38dcf53c35dcc65c031e84f9f2a9a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 273, "UT": "041679449685e297af7d8550b9eefd7d22af7a2d10f22ae587296cd7526fa0c0bb1fea55fd1d75c52b6533791c6ae7dacbfdc49dab3fde7a08011b634e3045ccf7", "MS2": "0870f2ba5024153a06b904291b92d68620a03246d056d7d5fa4862efb0b3c341", "MS1": "119c4590fa8d69c7f115635e7a7d84c0cb6580cfa8b89f3ba21855f891206b26", "CLIENT_SECRET": "041c23d4ed0d0afff907b41431cca6db965fa7abddf7744a2d915d89508051954a02159beb8b888a25dbbe2b9611452cf8788a86e538f84b10fce8173d2c37d655"}, {"SS1": "1e19cca9070b2d6d3ecc30217f2f958e5f38994ce72a69f16496af936c880a82231dc401092dd3af21467567b33f557ce439a84d5eb42d38658efe25e4c7930f17e17f82ac77998835cf1c7349ed5126e4771dcec04e0f704eb1a16250a8c83f2045306113620ab854a56cf5fc377400acdb4b0f8062c3f8f8635eaea906856b", "SS2": "0018b705a117e12b3c79eb538f0f3a9b2a1f2fd433835112f091cf18bb52cd1e174233ccc0e0b4548d3b902acf1427eb70f810a9feb236f41c86ba0bdcad2bd8226ad3364f31255ee1e7cb0254bac62cb86bbb4637c6f8d5cd075c443486cabe0fbc3e53e9324b41700f7815587aae971ea8ee4fb32d6650b2d8960f675e4e54", "DATE": 16648, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1691f6dd136aa1f0e456d8a591a58acc46a8e8ffb865a16d28f0e948746f3ced1d113da740bca46802748123f3b7bfb7c76b3bff180e4a9b4ab1c2d70608921d045fa0fa2dfe8f2c84cdde3dabc5c74355c38497a7097a09cb19f8c17190dd7d232bc4a852e82a66e2799d5d24932bfc272f7b0d3776336c767627b780611ddd", "SEC": "04235cd2218d55731e981a326003894d4cae84237046d67df35ea1bfebc07f321c00ebc32458f1d0ce58c4e9d89ca63bac558b5dbbdc0d1db0746dbb041a5d4012", "TP2": "0415bb48bc442df20e8283f74d176849d760351bc3e3d9689afb4702028a0dbd1706c19d86d4e91502f550ea22f2002121f4620155365b3d7e219757de2a2ad09a", "TP1": "0414a7eb33203adc23d43d584e03b781ad010e4958264755c2800cc028c380e21e00782e676f3a966e49fe5648b8ff9bc902720e268ef54e785a35027800bf35ff", "CS1": "0409356a17351c825ea0db87e722c5175b0f84b26a934d8d012b9478c8ac414fba20b61338f50b9c13b95c91a35ff01a58f98fa75a05d4559ca764410e3dbb4463", "CS2": "0416d185835230808e0af1a286f627caeb650883a8ff0d8faf9fd579a1d838a3801ab894054abda071d94d9686e51e4568f3d203051c9dcc5455cbb7e664f315f1", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "0420585eda564d019c450956079d3d2b8341f5eef626d12d135e9592afce76a8641ba632a2a33593519513a8e88fb9134476907d8ef1a957efec46fb545fbab852", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0412b91240c6458f6f0a2de06931a9363f45028ed2baa71b2b023209fbca7a0df208407fdd14ced4713ece2b4293e89a12adf3788851dd1d0b67f9110c794245a5", "U": "041478ac200b8c2ef5734fbf6a00a0dc3426a06e825ca127b74d4bbfa1998a2d9907f74dad3aecfdbf48f5118238aa7ae300d936bbeb27f0993600f07becfbd48a", "SERVER_OUTPUT": 0, "V": "04215947dfff79c8baea780d48a55ad955cebc576bfe1cbc436fdf6be421da2fda07a6e69ece3fd3105405b1367fc000cd8aab2124188ef02ef9e4e45b5b555a1b", "Y": "0c95202258590d5e729e2083905e8fc1eeca4425f682e407153c7daa26e22128", "X": "0fcd1d0e40b14d5c7048e78ddb90e52bd6cf86baf1fe499a637c83109fe30bde", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 274, "UT": "040ad4cfc2be246cb3d57c566bbb169f9a475d27afdd990322da369e78d2bb43aa0340665e8f60d851dd7fdf41b4b9887ea3bb2a6c9f0c00d93d9bf7bae0c1b364", "MS2": "0e9a16cf0025db87e81cf582670fff3259dab736fbb5b2c930f60059a6122a0b", "MS1": "237355128ead1a2574c4b58c7acab6c4dcd8e5657fe28cca90567e2687470ca8", "CLIENT_SECRET": "0409e32e02e256f1c596c01965f846c4dbbebf442b5b04f6d39739d83c7319f1790e96fe2a7734fb191411c882e5106ead807108fc3cf06ab0dbd90dd0e99315c8"}, {"SS1": "0e1b3d2e04e2a8fe1a1319dcc32d723d108f7ad1eb488fe20360bb18d32799f4161d8ea9f2164365247455f9a439c2d473c98588d2e66361e7fef5a2e00c182c0f44c1b4a10163a1aca7aecc69d5cddcdd88a715e1159339731e05bd68aa1cb92241f11348fb83190086e90d742c6253d50bb6bc285e2e262f64d22b6aa85363", "SS2": "1d4962f099a9dfde218bb21d0357f2fd4418332a5136fdc4e7e9d750c47d547b2172987666e09d3ea067c87834281509999802d8a60bc2c0a9ffa32817b46968193cd26772fb620d92f06ba7e19e2b7dde846d79f00fa1e21332460d6d4ca67218bfe4daca363d62ca656b9d9c430540bd9ad2737c7490874d948615a2a56a4a", "DATE": 16649, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "22b624edfe0c2c9251fa3f0a247b65025f38d7cac8797169c42e3588815efde11e87fb2599a6e0fc17929747b2a02e12197ff020410cbb79e47056f43b5c44bc22c594a01d2b12bb7075c60f9155524e8e82722104c6ecc3a25f7d8cbdb481da0017f8b666c1256af7db29efc1dd2800b19b3f992c8a02fb8265a40a77df743a", "SEC": "0410ca3f00eb5a08e686e6c4da95fa25b91633142bc26da30cf1492520de0758650c34c8128eb2d1fbf8ef450aef6710d051b6fb317fae0cb347930d7ca3403b77", "TP2": "041c5fdaa91eac4ca80261551b326a8ddb07d80b640d7415647e25716fe21d2bb61e6e30a1d1e621d3b0ed87425818cd677e0036572b325d2ff94769e49b4b8bc2", "TP1": "040874c2e505dda6ecca584e8f9023f229621c668cee961560d28266cb1cf0877d0191705638bb1062bbe8dad0e4f3bb8aae0e31bea865f7fe7009b1eec1b0aa0a", "CS1": "04090f88c28d378c019c7b04e3817da03bea34b0d0c55a1476ab56c711cbfa758306068d2f18090261302e97ee484df773c94a27cfc6ef5bd06b7ab88ea44f4c05", "CS2": "0405800436b1b3e6f55b11dfcd8b024da7e129b880e0b3e84453838a2feae81a551c202401775c2bc0eb5bbae696fa2007a0cd294b01ac9f3d77d38565803a5d97", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040776de83ce9d8b349b9fcbcd96d3e8b63892ddc887177308ac5a6910e4a3abbc0684711752126c48c717598994bfff5ca0137b27f56f859e6ce2bad0a36c3363", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "04213a99da3dd5dbfb6113caea649b88a74f52b2715dc1b10b503168d766d356e20d10a6a12f1e95b5d13c943186260d8518138969bf1add379c7ff62feb943680", "U": "041c7c42ac021c2a73a4d5cd33b6272f3c0f7db6c48c5fa1795512e7e2bea907e408fb28309a08885f685fcefe9def940a97c94945766fc7e092581f2fa77dfd92", "SERVER_OUTPUT": 0, "V": "04027b4a7325b60799bba7b01b25adcbd6c931faeda1d5bcc16ff62efe128d385e01c3f4286e0878e272d3a01a1da3a1a939e52bebd702abcf566170dd30747f6f", "Y": "1836d2d57ff4d1779e4d8ee25418568c4b4d479344d16b2628b515ffd3397e7a", "X": "0f9e6c6eb24ffd8717b24978d0148443ebe1e3be4f28b2b8d755c78306a02eca", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 275, "UT": "0405d678a36c6f43a3b434e6e0c424a1150e8385b29463bf45c7a6d30faa98907f18e24d616700595335f018765e0d535b16a4e77b3ea3676a829dfa11b3ee6c89", "MS2": "159608cdd789b98d8262852d704c71e7891773a8cbd576360c1871b148fbfac8", "MS1": "10f6f4ad53e280abcc77894de416bdf41cb9eed035d79ab72b4b3e8850439545", "CLIENT_SECRET": "040a9e84c497d39c75b15f6c1baf2c0af1bd063000cde48d76902b0166d0a11f41025b069ecd082cddc04bc330c91c1775cc0bef72bb479a9ee8f50d6304170680"}, {"SS1": "09d7fcc5c1f3791572c8f8f893f71e0b13e9866e274e6b5d7265755ab79278e90da5d211a1f0fc45d9003565d89ef248de556327bf000f8c6739271f5c66bb241d8d9a548323749797dc0cca8b9d8c5f133428256eeb4d271fb152137013c8b50c614902f8ef40a8a23f3d09ae5b3c61b2c78cf27c46d2c711ce44796a22a3b9", "SS2": "1aafe92f6b39db35389480fb76ef1c0867e420c34c1947d3a65c72f6367db60e0b974cfae0e3e60da45470b5d96a248a7bb1f38f9d906307f0aae3ead3d0ae3616da5dc24e312a3062cc16d8b5fbf2b10685deba12ad2d43fa610df8a5e517df1426e583a624fc159ad6cd06d28831f8d9215921742109a3d9c0c52f23e708cf", "DATE": 16650, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "05193afa85f11b1d7555fcad5d0a54341cc88837b797a5d118c65199c0fad9f116bd8dbf4151304fe1487f91be2005889e29fac346633d9def859ee78edbbc070cc637ec21cd44c3cfa59c7d399e405b8aad2a1408524037bccd629e02e6f16f221f0d9c751612b429d7f9062878fb718eb5061f4585e8ba4b6d6df4718e0949", "SEC": "04084ab7d3e9cdc0ccf25c7b6bbac1fabff0adc5b3e4a9b82b6e2c6440883d0d9205d0d523c8fdc692b7872ef061dc7afda4659e1202321a00de0b59c125cdee9e", "TP2": "0406e226bb1b0ec301900a77eb212b52d4cdc11a9d53bd9c64926d8a90fcabefba14824be2a964df8dc8e739066ff091231aba2617bc6e1a2573eafe015aa7779f", "TP1": "0412119a697aa1cb3ae791d277afe06c7b81a746b646aa16448ae1559110c16bc21f817bc60b139c44c19eb4e5efe6a7376ae14d9b9bb33f3a320020fd956a325b", "CS1": "040adf0a51de6e9946197fe0c66fc22d2b7fa4d7f30ab3c1c47256fd53a5b9735011f2fd51289fd3856e6cfb6eee9f730d55a9d89e3be72e6dda890c0588dca113", "CS2": "041acae269383c98d48f2014c60edfb8567ee6d121c8f4b77614f8fcd2698162e31367ee1a828c402ac97263dcfef81c5c2a2d5cd0f42fe79a0a7f8ac7b7e6072d", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040d230340dedd4b09c3a8f522c1851ffea4097462bc19e2ded1cf26aecc3e399c1c2004420b8ddb9f728f91dca292752c89e36db7a294a5d18a0041240afaa1ff", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0406467c79e604e7fd389b4183574a2ab6206cea5edc8414934ebe6ffb05adb01c050626a7a4dfdad984db39006f1e12408f105d374cc37991cb42188d3773c387", "U": "04028501fcb4d224ef52755b5db77da7719263b0b34df58293c5f474ecdbac5b431bf949db19bd7aaa3a7c33a900036bd7f6b07af32e42da853af81a38b7f5375b", "SERVER_OUTPUT": 0, "V": "041203ce3e903a42ca9bebb9a05f8bc8b5ed86f02e51ddfe136e72bb32caa39439167157a8724f006b4d3f0e25882f8c23897ea5e0367c80d6546e7083be5547d4", "Y": "112e7c3c2c7b5dcf7265f65e24f934b1e19f3c56a92051b8a078ddde6c962675", "X": "1a9b234aa1d9969aabd0f473c9697732b02cb54af9b53f0c433e2b91dc7654d4", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 276, "UT": "0423eec0cb97beea3322e1a99039c504591b887cba8e1fea6ccccdb303c5f4a3f821582f6356423346dc344716f69454837b96956d59ba777e3f0d35c544979e64", "MS2": "1d8599d24e88b857e2eb6a52862a45ad3afa81a51dd3dc1ba87cd015a41e4af0", "MS1": "204d838c50bcb19cdd064acc8709e84f807ff1cf14e4f1161c04bade390b75fc", "CLIENT_SECRET": "040efe5d83bed0ae06acbffa772519065a29ed108bf0827363bd6a697fc4de24f51401b54173a02bcc7437c73ea1b4b5732d4e44e9ef7899189a99a4da0b74d6f3"}, {"SS1": "1749cd04c879682918235708429be8f9f89371a9ade48fcbb1e96acb6009814d0767b9ea1c1213e5305038a4a41890ec86fbe955d2e31123b18c474a6e44886b101bfb4895baf0401e9f13ef1138189627fd76be50c7f078aab1bb1565f47b37204e09b31b6663a1068cde345b06be191ce4a5e9308391989571127d4a3f9553", "SS2": "187c1341f313c7b355a074eb71ad9b9d0bd93134e96d0b5a5940d9b3107d244700d9f41ea238c11b849b81cf5ad605b24bce4ab724551315388d93975032f95c045ce5333bad5d65a418da811d961837a36c98ddfe3e14196dfb32f828c0a3e30fe0e03af5adc12c9df073dd98a48e7e46daed6986ca0c5e7c146c2c6557fe1b", "DATE": 16651, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "035447f241cee3a2f4eb0c8bb5d2dc3804f1bfef491a85ea3105bc9d154b1f0a1ff4cb8e682e15abc003a548e000ea6a987a2653ea3d05d5c68105eb14bfb9490178179fa5caece863be8f99c4ddb68b95b2c8669a8d8018009c5e71ed785cfa1c6e6c718bc13820bb834a3d517c5493eec551d6109a577a2d1845501babab37", "SEC": "040c5944a82bf11bd730d66e99bdd0ec9918e8755a199daa84d43a9f4a26cf90881629a07095780d3d88ffa725a28056401b48a4fa3afb4c8bf3d005d06327d33d", "TP2": "04114ed05f8351da53edf14fdbd60c6d9ec45c2ab968e8ff019cb3e3c2d39668e60b5c53f4d5e7f0be25916f38d72741b75e51f1d0e19ff715b202892353a6b8cd", "TP1": "0415acff46102281f8db9948badd9e32475fc057bf41a329bf8c832177e31a472c1bb2fa86b0c44dae3e1ed790378f713c615eb1656713f5eb14c85332b5e94817", "CS1": "0402179b841526984d0d7fe36155ff5c2784d7f5158937dca9f43b99e21c3e47c921b0765596f2ba26d73f1cfa57edf90b723124ccd6ec175eea3f148b79310928", "CS2": "041398c3d21795aaecec0236ef1a5a88f215c01026dad0c6d5201794cf7fb7126b1d21d014af96b975bcc741d40e89209b7bbfc26f03b65e7af03a02c6ca6c6dbe", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041a2a268733c0f6d9951741c93b185d3270a9c21c92c595e78cc1a113519c3cc51496bbdc79b5ab9f0fd2448424c8ac1c0ae6f4448ea6de6dd0a8a837342e690a", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "041009222f008e48b6d234ab685e248941fc4e189f6fe9f24feba1f699346bf5b9235113d02d19319e4b91f136789eddddee200abf7d2d4772ad67c5be6d302191", "U": "0416f0d35bccfd27553e85620d3dfa55329b24fdc217c66ce8a142bff5d2ea4f42014e9d6a06014e0748256a32f1ef015deb36a3df04d76629fa3d31482b7bd7fa", "SERVER_OUTPUT": 0, "V": "0401434201401d46c82d8802fc0c7a2b7c20e33c765c6c873ed7d83d312853f8940595b585143469ddc19fddc1728adf28007da303a90a65c6815ae22bf25e4e94", "Y": "0a4c9541009e3e295eb1a26a8573dc9e36843451457d1ffe8c829586cd8992cd", "X": "171f2ae98aaa4ecd4c687fc88ada271c1962ce184e889ce56f852719fce52e68", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 277, "UT": "041599c39974b5aba8ba487d919e706ba59dae542d8bc334103cc80d2eb1e1855014772ac9754cab5642f984aa216ddebd9e4b74367b6919515041e86075a8735b", "MS2": "0f2a736a1b3e291e181e9735f398010a1c8f48b86d28fa44d8e83e868e0b88ea", "MS1": "01394d5cd97c78daba62979c5003b660fbfee931ad010e089f0ced46154dfdf7", "CLIENT_SECRET": "0413d7c252fe299b01d160249efe8fc38380c87595bca096be2fee68ffe92278c70d9e5f8a672c44cf39b21fc10d0eb075a9e095fbaa07a752b4656280c017964c"}, {"SS1": "17078de6485ed425b4d0c94a637c5ce6e705857edfba97a76d45731ce6d6246e23c3c2b66427b05cf197ed6e059fde0a698732333a1ddf9732464244d6752ee011731af883e5eaa07c6c82498b338650f5773c155432a6fbd51d6aed775eb01d190f55542b11b35a36f97d927436e0da4cd65873f0e1727ac0141c3c5023d580", "SS2": "1db110989ec07a5d42be687dc477a59b617f34ec6e40c3cf9da3e32a988f9bd41b33e01d9b29cf4116500b9a674689674c78a98280a74a034d79af55712d02e716b3de9a25cd41eb1cc1cb85840f4ae821a9d8a8c1c00bcf345efd9bb5f11ac50717739756a798e3bab67b2091171f2041d6a14f745c4148d96bcc81b58b5bbc", "DATE": 16652, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "09269a95dc08c4ee1b9204d9d4106a53c90bfd2d9789c528e43d8891122203c1198067c87b1b63d6eccd8a50dd26327b17a3bc20ddafe1822a8a8a72460e4cc213a39f4471609e6bb16b505c141117d2e0ef4581d6480b328a36a401cc10403811a377206188a051bb5b57960bfbb7980aa407ef71f2cc88a006b305a510f216", "SEC": "0412438f88c41ada988da8fd46afcd5963cf91e3c5c69cfba46a0e93ac53f9e4502275e7d842a48f1485fb6ee70ce6709c5684b64600f6cd80506c73d2f1a5c28f", "TP2": "040b2ddfbacf1fd38c190edfdfadf3a9c8d5b12fedcc4a6e7ee0acec6ac7d00ca0015271b5c34b5d1f5b8c1fb0c8e64a19a13f6451f08ba94b10c6d23503f3e8ee", "TP1": "0403cb3b8a36163a42faf8e14259f51a3f9c54c352c3452342ed79ac3576acf63a11ea70ca0eaa414a1a7d6a4e528157799f6e5f1fea6d98a84ce113ef260f024d", "CS1": "04124d54f8f4718668e27e54df38d93b85601500a5889f3d6c75661cbc549499be1796e0b572c3a417a249a505d666b530245d2e3344776c947cc8e3096a9ded51", "CS2": "0410da863f06f302bf543f61d5130815f97623047b7af03b600d612999714eaa4818a907d17a712b6d9e0ca87a32fddc05afa0145206f327c738f153646b4e2bbd", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040e25f003a39e0f5458cdc9ac6a000c6d4997b7be013b723e34c0ac2dd9dcca1f04e8786c2288bb2a2933b01515f4bf6d493ed4854b7617cd2fc377303b9e038e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "040c82b0531f8c5cccde820d4e6664ddabe08c799abcff44d7fbba5a64a01c80bb198d2211a38c2451a12aa7b5253240101b817018bbc4cec752b0ec9555fcf9be", "U": "04004700e9bcfa9071c9c8a2ea992fd47585af4f9f647216f71c300f0c0118160c1f53197c1f793ac8aa5facf05b4f63a25b6eafae1edb0cd751499864055feb06", "SERVER_OUTPUT": 0, "V": "0418338afda9621fbfae730c301b528f899e38f7572da1c84ac2ec87640aedf35806da1c5a7abaa9d5a5a3af17cb90820fd6ee08b05d38b32890fd559c104e145b", "Y": "1fec920b0ebc10c7bb56706d16552b292f29d3bd3fd61f37f6fea35e7d8637dd", "X": "09cd783b92e35155654be6517dadff712299c72f30eb0b030f47a7f176d5a9bb", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 278, "UT": "04001b584883a6986d001513a7b55aff3f96c896c85d65c984a5b674c3b8cbea9403ee8dd1389765c3835a1d7b544d09488942c3a534f8fc238606875bc16030ef", "MS2": "0a653748bad66205a4ad21dd53a48a2ec94d0d56052e17fca99aabf38c260e53", "MS1": "1d232e3b9f18506bdf9838c10d68d8f4a01158367b862b1931a1f949ae656bf8", "CLIENT_SECRET": "041564acaaa1e97eb2d13c872b07dbe0ed36fee51a7f3fef6f934b2aa81a1c1fe220895a0be6dac81de04e72c9aa4ed0fe437c0b38fd51cd6f304d42528c5678e5"}, {"SS1": "098a03f1017bde7b88071a28ec459db7b15358214f1abdbc02ec49d8b74f8bc920934c5c101480b053bde230b3994eeed43f3d227a4022110c987488be50e69f1fda062364b77aeefd2e69d99053c5ef4b89d4b61916366f91a1a7d8d347ede410ac6860194953e97b263f37ae477f24fb18af28d16592bad77101e9441d3d8c", "SS2": "03291400bc591c2052cc38d7912fd4f601924c29f3769a5b1600df339d1638c019a081a84ef56738bf0f2403cdd64b356163ad1f11879beca637d8d1f178eb4a011eb6f265028dfc5422a85b32483084b7d710d7be556206abb90304fd160a74227e0e1159ca8e48fbbb4ae1379af58e2fdbb9ef7d510dc7ca7153f0908999c2", "DATE": 16653, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1c241cd621e9e1b81d3b89811aebd96de22d511ffde7f0bcf83946e5c64d28d20d4546bf39c2103ce9bb6bd402c58ec9375c99138441d85ec0d30d4f0fb8e4df047687e4c7772d65dd90d8ce3e2cf226db53c64e6ac9f9b961c96c656cfa3b1a1d776b3e9d30d78459df1fc407842dcf86a07ffdf2c38b9e5bba7c02a30e08f7", "SEC": "04119cf430332acb7b65040bb3a79020b34cebe982d14cbf962a8eab905c963bd11b7f912875dc96d75ebecd07b13ecc06a8324a0cd3cd7515329864ae49d76281", "TP2": "0400ad65dce06066442afd7f5991ad0fc42b68b2757f2897073bc49920128226fc22c53d31c090654557ff129ca582d68c057a5251ba660e9623209e61d69c8074", "TP1": "041c6c247788aa8f22173bc750830de8b517dc98e273b6b10953c5d91164d8b67013e769108db9065c1a67ba9ba37f2a5281dd9e6be08721837d2073c016f41474", "CS1": "0415c8b2d01c0105c46a50b304ee027c6bac15d6b706c505de106c0447e8e9281318e8b575eb26f030f03cad023beb3de271b749e2e28fef97948f7bc10775270c", "CS2": "0423544e6361a3c4c4d8ebea67e574e31a80fe3236ed85128f52cf0e84bcf5ebc60729388097a4589798b08e625d73c5a17cad1882a71601a2f1933865501344a5", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040fa7f9164e3821c182f0b296dc3be66dc6f3ad6d6b1086fb5c6e88bc1f89772e22345d9e63aa6e10625aec6407d24da5cf0cdacac594739a3419b0b00d7736b2", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "040a49fdf8910c8b68da17090dcf496af8539c0575aff2adb0618ee1e4a58f015913b1ed90d595ab0acfd37aadff27f0bde3232dfa3ece3c445e8ed51dc95cfdc5", "U": "040e71fc236fd35d4a1fd230e96494c441a0283f69b960321e764f6b1f70077a5c05d1db02163a33bf4484b08e65ad100dbeb89d49cdefdec2d52a945b77a3d33d", "SERVER_OUTPUT": 0, "V": "040accbbddd47f32eee93008733ed96dc555a8992551af3941e9ddfc4c2c58e512076cdde3c5c2108749ff4c67939c74a1f1cc357960a8080b63c8005c2470891c", "Y": "0cf462af2b554e1b7a1fc779452d3b836c9d8ece8f38b7b5955fa68953383d93", "X": "13f40bf283a22c0030c200ce6b4b923ca877e25ed773ba91f2457727a23e50b9", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 279, "UT": "040b83a0705b82154ffe43a284aaee88d3fce2202f7a0280afbb07fc0586ea43da043a1f320850e0dd7f16651fdfde1e462a5119095fbb2ce22b9138c335b80a97", "MS2": "1b465ea4d6e2df89a30e53a784fefa6f046d904d4a647f944560abbd76f2f5b3", "MS1": "091ed7537c5e392ad61c46beb670ca73ddb1ed7f3d9e2c1d6ff1931685111022", "CLIENT_SECRET": "040a357bfa74b2eda1776beab2ef3704074e6fb360728a800a40a97053303ce53a12da9f824119327d778d0f87cf35446c82b12e123199b7d86becff43a69f4176"}, {"SS1": "027c43e30c027713fe709b8ef21d2fe223ed5a2452952332a2d7112f7b392c2b155cd46cb3ddded8642318ca680092e70182b8b30f1d847b33bdf514e4c99b19212a74e9ce21d9cb4db2aa91e2cb747b2554a2d828c8876c93fcc6985e47f3350fed5c470d38feda76c76958a7fa4a6b54b768a2bd5411ac18635f72b39b9f7a", "SS2": "12ef73a1ea9e19555a00c2d4af22fee88b08cc45b52a9c9bdf692a812cd52b93227dcd11a88b54764947ba412080bb1fe7f520fec39df06a48bc88df32e92efc05529fe07c3352391281b6079ed00306fd8a0c010ac5e7ee1cc7c52ada5cc98b1f79c38579d81297994dbecf9618e591f3f506b3e517d11ff070ef69fb1e33ad", "DATE": 16654, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1ccb5b11a2315ea07697329b0864558a3ac0b5bd152f6d06b4d69d6b202d6e8507cb559a4886d1ff765e5d4c8c59487636009a4af876363ef57fc3b9cd0de3fe03419d59dd77ff5f661bcabd647f7ae9cb31f64a18d0fb10681c23bc40d4e96f0bbcfdc25afda2374654866d4751401353db6df88dcf1c5890054c20100c1992", "SEC": "04239e5631be1c961cb2a3c7e80402af2789009d2cd1c106f5b899c918e74e3b99025960b1ba0e51535b04782ab1dd918ab06b4be1453014fe0938204b90913bef", "TP2": "0414f0119a494f4836c44c3e463c59b9d91ea96933a238ee167b7be7424f76af84056fd04e6f63bffd020f1cf7646d3fd6247b13ddbc33e2de5b0298ece9573f92", "TP1": "041c350641fc9358e5e7f5b91ff7d058938615c2314512ee5476d5426622f9c2d81eecafaaa4f4c71bb471082e41c9378af1d6859f556a18edd642c7ebf5fa2bbe", "CS1": "04092ca6ba46fe921e8c3f2ad376ace4e4fdb564457c4bb1831f183a55a4b307f919be61da87f940043acbb8dd040bb7fe8ddbebebd3747495900ed1376ab6bf0f", "CS2": "041c52df95bc279b6c6a8ac93674957c2c69c2a35b341221e58e66d74fe163b552091013060b30628edb83deda0c15d89cf60640caba5f94b51a26e37cceaa3629", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040d7fb083b3b09b8b5be14c65f9289cf71446eeb8446f311688c4425b6ee1145c1036057413f01365989e27a1c093be287c6420809997b8e1399709c6c2fc5d8b", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "04231a8bda180e6e32559e992ba7b2d261e66ad7f9f5363789d0e3e212a097f069131f288ff20b87c6200ba5cb2da8862c7a7606547fe8ed473b0d61d68e814b42", "U": "041e7912f2811f3f2640f12d5f3f9b52600b8472710f09cf236dffe67544e799dc0173f2fa0be7f1f127f451fec444e18fa48c866ad016b19b86230ff812cf966a", "SERVER_OUTPUT": 0, "V": "04139fe056c6138377cbc8309ad553253998b7e48b7ecfa9e9014a0e78343e014e0ab2949bea0914d60d8fe23288bfb04e78c9fad000624a7f0c8401512ffa63f9", "Y": "14b3a511dc2460c8a7bbfc9b3ab6acca62f59ee992bb9a3d54251a7f4a7277ab", "X": "1170d33738b47ac4ef7711d6bac9b55c87dc397daa71c7f9c49b10e587c12375", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 280, "UT": "041fdc223b537529e1fd2c51d7e9325e75d93ad9bd56acb85fbf6e317f69e4219416c685364ee7c062de3cb1b4d532fdd421794018ca9b7aa00307822e24365806", "MS2": "02d168199953ca551b4a3b24989ae2bb8b763aba59dc67a6c03e2311d345703e", "MS1": "132eb1a107faea680f137a8a5db84dd509aebe341f69d0f12e218eef3be75c27", "CLIENT_SECRET": "041aa486bd068670c84088b254ccc02c3a1997013e1340b6058a934cf1facd5f7313c80f5fd2bf1f29b1c8283e7c5e911efb333eec4a1f8e02c0dcff2b6d7cb55a"}, {"SS1": "1a72c166ec451a5f3d01f94c6d108a46e25cbe8b64ba4704b590d2e5da2d4ce311d7e4fdf5cf06bb7bb80690b55f4a32a914d27c50f0214fb18ee1d85f6fd97f14be0851d6a6b38654722bd52e19a6c0cd490f666e578a7e89ca68e78247b25b0b8b8a184daf8ceac660f0344d22df7269561bda3d876062d696e7e8ed91828e", "SS2": "15e549d0d53358b081d8e395a306da1f48b6e4c6c0c3ec95d987619e12c776a70d61853a52f4d1d2cbec8e130e2f9a8fb1c007acf635cc49d8557568174cf5011925e78bc436212956c4909eb04a61ee31d9ebfda3d43ff787ac46230274c44c05b30d79b7cbf27fc9e9570432f4bf9fdc368d49433bb3531f6f91620b1564f0", "DATE": 16655, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "07a3e0950c29aa0bfed2158cb85572ec522cb8eb4472ef915089812ebe58738b11824a3af0f23bb562258aec31025927dac19f51bcc11e5c71a351c20c8b5ef910f35108b219680494fa11e1b070b4aaee8502c0d46715118c79a31fa21b230e1b4eb8d6644312daf8f83feed2a5f34265b4e6bc4f1dc7b8d0d7fd50cde6218b", "SEC": "041a5b98e69a2c3103eb4b5cc22c003a1896d3bd0744ee404f381d5a7b5ba7d8f5234084750a0e5526abbafe3dfa8c0c9dca3db2bf595c4020698d76e10ca2a8fd", "TP2": "041cf706abd7f8bfc56375d63d7d74f1273b541074db4b54e74f7e7b4b2c96585200237837e18adb56abe5273e5b63751eff2c71a2343e0baff24ae9a907d69b32", "TP1": "0411e4dacd742a933229e91f30181d84c768e34cbcf43d486054dd7a7cb0dcb5c020890f66c27a03eb4b297a43735390f531cdfc2593799784bdfea59d374795da", "CS1": "0408e99088cb8a2517d2b3bd38ef6eb9566ec8e6061f11d5e97338ded73aae5bf70f2f2a50b8ec9d02a0cf3c8c7ffde9fd8131fc584676b9f11ad34fe85f93d0b9", "CS2": "04098a2dec07f50d7601c909723dd52f18af8f4adf58b2841dcb5cc28b19e66a770c0325459e1e40fd9079e3f8fe995d2f685edb8c420cd85edfe56736e2c915d2", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040b894bbadf7d5d15fdac812874d5acec5620d10fd051f8c568f293feb8cfe39b1b65ed9b88cf6216e06096e84fcc9d10ff845f94f06f397eb0019a2a2313f760", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "041a04f3594a43c22a4702f7ff8495eba65d0e32d6b4e222d7d75a2966fce60d900033892589251e8a546f2725fed668ec0b900298d236435a0d7d23d1242075d5", "U": "04070fcc7a20b6b1decfd9842441928f0f3796751a0589130b9faf9bdade5798d31e94264b4f699e7013ad384733bb2e05e15424caf8c435e3bc9a73c498195e50", "SERVER_OUTPUT": 0, "V": "0402c4663fea5a4f25d01813c4b25729e96e470dcc2ca62c8b5eb4ded1de241b2b037d25a8e5923b136f307882ff4b5c7c044cdaa0ed974c9ece6bb7eaa35c81b6", "Y": "040f562d67f8a6f8e115bcf75ed1b6deacddf240c14d691bafafa5a547caea69", "X": "22cc83c8dd42ae8ec89a70de50aff6cbb2589ff49cc220387088e03172f06525", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 281, "UT": "0404108378365dc2d088f5e4140b0391f5eb3c903a484dcf93e63505a9ec5c081c20716e9d8618cca2b1472f26d4fa9fef6dd3e3bbe1663591e3f369fe5daca5c2", "MS2": "008915804fcd144861af458bbbb17a44b7521cbeda7e551212b33d2001463ae6", "MS1": "1cac26e22ccfeb10dbe3f32531bf49f2f16bf77746648ee479ce0c4e5f77a5a5", "CLIENT_SECRET": "04116b969da64499f52b208c275c56d10e3727db819c2a2df8c2124203778a41a7111fbe8c3fa86c83936d056bdde65d4ae6771c016dea67d8b434677e7279c433"}, {"SS1": "1fa9e664e0f8bfe7cb2c8200f440589ac44e1b0c3f27d3fbda0dc32b6d3a114a12c4c83ec84541bda6c0f8294dfb0768485e96cdb7b2cea08d2561f4ef34242d05c6e6de4f4019406dc311c61c28077ce9356525a62251ba575b3af7b8e9871b014db761ac5ce26d5c2d3294ca2edf8eca0595fa21e45f70f1d3da4569e0b165", "SS2": "145e88b0079e7fc034468aadbd9d25bc9205c46419ac128fbf78e67eb05187ff10b3e90e975856554c3663898b7141b31f8884d1765ba89e7303af1284ee319b1124c335905faa0812bf43a3803f0af18e42587b040a51c13ff239f9f26509ca1e841ca7b907c6e86f72990e05be4cce132cde2b28690671a41769a7651492be", "DATE": 16656, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "00a72e18ed299222dfd50b3b3621dc1c290aa2ab2bc61398a75d368ae2b123eb1a07d0711a61cd8df63d3f2480bbeba14e1f43d6e06d54327fa880af735ad72d18252183782045c9cba479aa1c6b86cff37190f6891bd9ce6316d358afac1162134a2f1a8e2a2d6a8cdb9380eaeb6aacded5aacc2ef9f22c765d2ff670f0ae4e", "SEC": "040c119b76ac0ee225fa963fc6d9acace61d3f8181db9e6f6c205019ed87346a571ea618a0b607bb8e30263f8df10de0d60c01d66489ac8ef8873981a40afe3b5a", "TP2": "041cce3627242d56e72e3e469855156b4391a5f7c524a624c54fa31b0277d3037717ed7f9bd03abe335cc0452c185d22ea044fbb0a7647039d6d3d099a342e8a22", "TP1": "04101c2e0c1f397d5be2765e97be2a3b473b5b3087385f63d198b07a4e8ec201661957258ccfba1a79707847c8b6a6b1ed39ad1a913507de1d11a735ee372642f5", "CS1": "0414da33624cac0a6ca522cf4edbbc3b47fb6034df698d2a05851b4417b58da35b0f18beb314756826bce39d947c687789e0f79512b08c997bea71813a9890bfaa", "CS2": "0414bf0aa19173ea6e44b1ecaa25759f1305c0f033c7cc85d69eab2bad01d1e0340f73d20df7e4c9c6dac126b8b1ab48fab6366a07165f27a504c0be38d2bacf5a", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041dabf5e58b56e53eb3266ea06133876c2d0a829f9d2db11a7fd89cc2ae5717c300adde1dd5fe6732fb35aa85983cf79864bb5bea1a8f95ffe4c58159bfab8724", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0401360a1326a70d20c087cc7fe19264ab0cb0495b8b183a582d0c90cd37e61e5d1b59a6301c4057edad34755302b7ec5810ec1bd779a89ecc7cba779c29201990", "U": "0417d2853557b992f29be51e77e72ab04afd5972873c8f03cafdbbea286f0258951beb6a13c9dd3faa26bfed7d7f65774e692206b13204694fa36a2f14300df536", "SERVER_OUTPUT": 0, "V": "040a5eab6c1e4bcedde9358b40dec8dd6b9427491cab9a3e8184f450151cf9b5000e99218d84469b13f9ada4e14c22b7dc9568ead0ebaa58526bca993eeeafd3e6", "Y": "15b28343a6395536ecffbe331a50cdb6b53f38c4e5335e791cdfcf1c691286a9", "X": "02923d603efdd5f29a2a7bd4401baedb2d5b2fa7ae3178126672916086e08014", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 282, "UT": "0420f28a1d4001c257c55c86c95489f5fb85310d53a642032583687b600672c05d11a41977d947af5b9fb14d33cb9b8f5505743322f8fc8227d2318ff3dc36bd0d", "MS2": "0c3f8e907ac0ce3b64f0d29962945b481f8fa244d21adb5de3646567501a1630", "MS1": "17a0f999b89d533b8cb3659fd2aeab49b43e0a20b3bfa8f8def0c746bf0ed82a", "CLIENT_SECRET": "040649d76d1ceb0131e2a8bcb201b8b43fe8bf2bfc89fa654814b31c054562ae75074ec1b55f9f46311c6ae2cc11fc00cda2ad3cc2368813a856c4c1831557a082"}, {"SS1": "128e390086428ddd3c0941f9c317edc33d9cbcaea470b650661a41b3064deea40f1cfd8c6d18f82ca683f3e1b4d2bcf06c196605df74bd3efaee547109b8c6350aa74f9242dc2bd6deee308000247b565840884c379bddc745c6948b1b8902151b0d7c6cf5d421852500706cc259223fa91296a69f56a70cebb5ffae2d9e8182", "SS2": "175b63e36a324e7c3920d2e42707e251504f043268766ed13df74a8825595f2a154126f75560e4d89a153742977ba13caf3c798fba870b2bf0a69dc7e07167e91b3bb2036535cd85a7798177c10e86f176eb23ec54e4e0682d56ac73da1078b518ccb9b82ed8e97fbd66c7d9b9d243abff81da273957daffbe7eca864601a00a", "DATE": 16657, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0e48d302c9e7e1c71a9cc65ee7a4b8c905df7850c58c5e82c58562a6b2e922c51f55762ba7412ce0eaf6e2aacb886ed2149075d968f89d006cdf60f485d977831d0c85d5884176a2f9580ad43cb02fcb759adeac403dd816d5a9cee21bae67ce204a0803756e8f565bbc3d306d75f91efc04fb1be46813bd323a2116806b9b26", "SEC": "0412995c68357c0d11a42d3db09793704681c6224ef0d366184911cb4c6bd821fd19c2849204e633c75078cf4cfb6057850faf91f1f021a516719291f68b438332", "TP2": "040d45863019fe04fbc7eebbae9499f2e996f8271d2897b2f916c10b2ff601b12a05c254f3f127a36524e3d07b6be4dc45877fa5489b8b9f403908f42c68d5717c", "TP1": "040fcf9fbd4fdebd4eb7ced6e04cc7ab17457d51b54c5a72a57fcb4b684420ecfd0ead66bae4fd4d8dcfdfc0f8f609e7d146d58c21f19afc9dbe67c2fd0eda7ff9", "CS1": "0403c9fec4d96290833f4d2efb6f9f571ffaa50fdc55e0aa070c489a19e5a50b6f06893df4fa1b6a85113ea98652bfb6c93f7b3d9dcbb4f185ed3bdce61b085bcd", "CS2": "040b36bb17f8ac34ff4de838a309d938995d53667008055d1e3484a7e3a2853aa116ed6a20bdef0af9a43c2b2e900a479945e942b2c94f7649e73019f7f54f7bde", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040f27d6916812d4110722bd0010af769a339bd8b4e290a633725365ea2c7a32bb0db8351310d464b6a90b0e9be3804f4ffca438ee26ea8aad9f4c581c7bd707e3", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "041409664478ce6fe5e0b61d3c64e7232a24e14fa07084a18a9c9ba69f5471a0c50d900566dc3561fce8d0694372488593f8869edde3e88a66ee2157513dacb3ae", "U": "04082dfd5a0e11c47bf82658a50e33ff14ee606f3d63247d5596ed3cad56f50b521cf30b0a4ad08c4d818755ccc12b3a2c3297f9e81ab874eb99fd523cbdd2d8c0", "SERVER_OUTPUT": 0, "V": "04167e22c1f0670164f9ec2d793e280f3bcf9232962a032175015beffa1bf9d09a02022a33e85192935897ff9cfb0d6df8e97b7cacef0f17d00ee1a2cd4d0a0c2c", "Y": "0ecf96fe7de8f3c539bac51cf99ff641e6c2b4832899053acefa5e1cf0423022", "X": "177e60625ace94545e43ab10882c67ce27f9fc0a239ec4b1d9502d7d0038c451", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 283, "UT": "04237a6af3f931e39172f207e3d6efa14bfc313a7c4a908be583d054dd04d7c2cb1039f65c671dcee1164c07a70cfc3ec235c14bbe307a3cfdfb6f178b54a4b2e6", "MS2": "0cd9c1ca972933596cd476be0d48f70886af5d9e064e342ae9efa12150f74e20", "MS1": "0c3cc81fe8a2abfc69f3ea5cadcb89d9938dccf4b8114c4851e8bfd673ee52c9", "CLIENT_SECRET": "0418ade8af2331577ecd81a0462bed2a27eb8aa71e34e2e0854f959becabce941a10da98f7cade401e21e774abe09397ce6ec726e153f92a13612c692927dcc0b7"}, {"SS1": "1b9e8e9ca7acca9579059affb4aed997ee47345f7def7e47f1d410debcd477440b7c488dd98e5be3cba5ec90c65bc5ad974c03942fe4936c9378e37d6d9a418e1c9ff8240b3353dfde10851fd1fb41190b60860a8ffb30e7116272d6e6dc2bcf1d208a72a83c89e54e3928fee6b087d3f6c0fbb2b67057f7cadbcca1144b653a", "SS2": "024dc83de55b7ab9b21817b4b75972ea926017b1270976b5579b921727a0957602fe6351b2a430c66d91c9f8e7129ac3a77a59a1dbba8bc62e751d4c443aacce2155d7b7dc99d789bde23a104160b71d93fb236ca8c298f9d3e489f8dce8c02303dc383ef693db7a4c7407b096e0546a8f6bc964cd9c0f95f6f4ff44e54a6689", "DATE": 16658, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0a41d5c420878405365ddd080efc54c80a65a0b1da3d456b824769ebd52b7ad712383cde36df6ba79cecdbc7c6e4ceeb8d5ac266ab667b6fb58a716bd0c4291722fbafd944517f4b47437ed14fefaa8a3732dff4605cd2020d977955c5b6024a08c830858e8aefe8d3c502f6b661257f26e5189ab1af7444d0d73b68339034b7", "SEC": "04141da15bbc32a198b0528da088b86b86ef5c7b3d6d6c38539edeeb0a42c4d79415c96110d9c9d56c0099f9ab9edc67ae80157d8833ce10871a03bbda93e52303", "TP2": "0414fb8738b6b04dc3ddbb96dbdc40ded89d00a0541e4809c18443f73c78090f881cfeeb6fb008238c9817c5e42a47b26072d9ee8c77c445fa860da65338bdf55a", "TP1": "041dacd7ad268d3e17dcc88325387ebc1f320ef02da5a9683bedccad1475ba0cfe1c367d428fdf108e45be4a0551006523bc81e9934ee14c70e92de30be6626380", "CS1": "040a6d087b3dbf735e81ef30a3af5c00a87e447b900582987fad7250bf7beaa8c31cbce861907f73e7f90d06966a758f8b165df928d0f75f584a2090bff56dc602", "CS2": "0418f63591756a11ed0a8b7e75fd38fd772c5f3f1fcbf3184b78b3eae3ac77595415675a1adf02fe93d0a1c67defc342ca0b3f5d0a8daca7f678cd2af3704de831", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040ef187712046fda3b549dafb6b9621f499f1596297c7d8962afb738ba8b7cd4e2254cd78fe2da8672f68553c36b23df410156a2013418ff6008289a6b3449384", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0405f038ccc87402795cc0ff62d991a189035fc979a8c140740cb4de8d4235171602769dd31c977a40e59d9e1cafa066fd4db554e025a6753ac66aa09b93e90883", "U": "04208e48dc095ea0a6f54a5b3117f952a7adb14a52a4e989243628a1586460df4f1cb698425ec383d026eef9c7d71b8fb4f89deb6cb2b1293963286e740a64c814", "SERVER_OUTPUT": 0, "V": "041f8888d5e104460f0d391d4f5a4b7ee4168cd0447373fa4da468e93bbca50e5a010a412595f1836c214c881d6677001af04d2f29767d645ac0ceabf077bd14e5", "Y": "1c3f7862f83b65f39eefddade55af4903b899b4a37eada3413336d46b829cdfd", "X": "1291f2948c576bd8c6477381290e4fa2bb27d00de3d64921c9046824e38e5b43", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 284, "UT": "041514221aa2c7ac3efddc49006b693b63a7fa1bbea22dba5d2c6c285464e5c291057dd39440c8ffc71aa4ff1789cb57aa3ec6908e3326ed0d836efd129d1ce3dd", "MS2": "1f2523b7ea24e9599bd5cd8672897143af5356fa40c2a61ac7efe19d3b6cb10c", "MS1": "155506f543f0172f6e136a4dfeae6bfde0a7664b98c11ef44bbba7dccc243365", "CLIENT_SECRET": "041a29781721ef8a4b6d163604065ef1efc9d04766fbcdbebade423606b310303105083cd88e3f47c22870129fdbd7077af5072e6bcb51bb0d88b8a9599e743fdb"}, {"SS1": "1ea9cebc8aea00f1250e9b2128f61031e13d8d07058635d41c84023c5f98ca7c2056d2a182e43dda116da1f130da01a223cb621ed6de624217742bda6b4b84c1146c9439ebf96719d6ea96da50f9e9138c84ebc5e1789f62da04abbed21e318d185b270be4d8c57bfcb5b1b886b1645ff9f4005b1be9f0216f395676b6c6a60c", "SS2": "21edac7753eac7c193c3c69848c836717ce73a9d91bd42f1e8be8b56e6e718110068b2e5c4c630c62c677df0318e662c6683e3b8b29e8d4b5f95dd13e35fc8ea013856826bb28398a70efe4ffb8b35fdd08ceefd57412d299e1f5f1aaacd8cab0a1cc9c2103d9d570746ec18d094aa8515b97dd0c035005f270e0847a32ad051", "DATE": 16659, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0a73aaab486ca380f3ea653bd6ab1b1e49835ac9cead3074decf41ca387d4b1d0730ac45a323b82740cbce9dda73e16eff5edaaf5a6023a9bd7131800f00d5c71d8a97b09bc4fa5b4888524fdb253e0980c68e2f8bc49bfdf825484a8eaa34b91b08aa80b978fb3f6cf667fb27fa4d8cdc4dc6cc12933c5f6d95de6c9c3d65d1", "SEC": "0419f57e730ff9ee8b0dab1dcec098811d5678b6dfd32c35e481b5d21d24f7abf810fc2f17fd5a7d10a5a59fc1246a1b44cf8a544145f05509497560a2dfa7cd73", "TP2": "04092ed727974a283e68ee7b7b899cb2b569417eb5aca1e737a92f769573ead6e41fc88d60787c5511569a18b3a42d3deac0267c812cf84ea64c923f202ff587fe", "TP1": "041a43aaa321d6803b1324f6570eb42b3dfc85127da7b81d884749278e2d1f6d7a08f1389a168737e47b84ba2a7cbc90469663a36b33f70f70b1a8bc930727110b", "CS1": "040c5c8c7feeba060053dd414dfcf937c60d1ae0501ca684a001283b87604f4c74010cf8b7fe18bd61c16c9826509c554f4ead5769d5d499c196e08c46a5085870", "CS2": "041f6e5585745402c8c90a4b2a25aa348565249fa4bcec86c617153ffc2f38fc3a048de81b4d455ff6975c6a6aedf09363f888e800068732da282766ea3f14595a", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041bc8bd1ee9569619d3283fa755ea2201c130db494b19f6263e9286144f3e993806242af10daea3249ee94cf39458de62d103a19e0f7e807a6e6224b837a81c01", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "040fe8144801bec8b5b527cf5188ade15fb4ce3532eaf8ba43395a7ef0500b07e71d55f1c6c9b82cc08b0842620b8d0010a4bc2cc929f7fa2d7918882d67503231", "U": "0403325cf3fab04e2718a289b5d1fd69397cd52214616a09f19591c0a10fa16b681d2ab06e9bb681c52445096bb1f9b9da4374b738dbe8a3fa5ca29b1df7c1ae6f", "SERVER_OUTPUT": 0, "V": "0404f7dea1f5f582c1abbf06e1e72a386e5bfd835333abe6bc922d3ccfd6ba112309de248b3d5f322d4802b0ca44cd52f41939dfffc41a12d236e9d088fdbf6e61", "Y": "09e19cee68235653990f306d2c2e32320f58bfc6f11669aef915c02105d87399", "X": "0a839648193e05d21380cc6da88a77d437c4e108032aadf7f41785d94784a284", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 285, "UT": "04189bfc12cedc68af112dac5b45c5428e11b1bdfe4cca3759f7d9d79c0e9500c0172b0d86f619f473e974ff45bae34c64b010ae02fc38ce13cb8b788bf06942bb", "MS2": "176aac0b8c0b47e21d726b4fdaa8eef1ef5b3a6dd81d04fa3ef5515a4f6cef9a", "MS1": "13ef79a7ffcd9a601af4b8a70dc5c84be7f1168bdc7be770025b9741e8866655", "CLIENT_SECRET": "041c07ce1efd8b99cd57355096060061d10e3e3ed5d8894f0dbaf1acb25547d7c31f6f3b19cbf396327b6b8c0c42a0d376249c03fbc431144570816366bef40b90"}, {"SS1": "23fca396f80c61e746f6402265bf0709e29b62411e8867f90a71a11bb84657b50d7e815b31de6a8de8751813dbd2b69f90ea37122f3ab619c51e20b3556c4fa4058966c8f2dfa66048eb4df0de91044debc2ab5198b05665460d11f26de04d480cb466f90e72fb1b902b2f571ca7318793fe4364f523eaa89047760e247e284b", "SS2": "1c75ce5916d9bf56b53c69f5e1d12584cc677fad5b3604edd0393f6c31067ffa13038b3b11253f04db68b58f5d10918c2b4f964e93bd29493f55e34e72345a260e7bcbd3e2c569091eec6a07ede93dec3f60b00e2eb07f6e6f056f1ac1280a5321f9e7c96caeb41163cc6c88a393d93afa745e13453f5319b08f7274f7fe22d8", "DATE": 16660, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1129ac5ccbf43182aeded2c4627a101543ad4c42c2394e193f33207b58718160211e7f6d19d55196482296733de4bec82a0d998b275795aa2364586276ba89a721de23ec03d72fd47a4c71a753d6462aabcf233fd4920a78e06384c3ade84abf1b285f384eba79cf47ed1bc4110c5e5e9548fc13c6bb1c1cabdb85597c78091b", "SEC": "0414f81da21c1535b66ace37a1a472945da12ae30a5086c8e5ad85c9ef32c2d6b2029700eb99424b9e7e742e21c5561083829cc85459070e87fd3012fa693c72ee", "TP2": "0419a9e2110ab9267d6e00028ef4eba2f658e295f31c24fe2c19c7ab60c37c077b1fd0a5552e1d4c9af808d131142bec3cb7f54f1c93824fdf36fefaece8974e6e", "TP1": "04137c8751a9c2f2c769025cd7517542e940a3daba0bef4b765697e005b30ffd5c0f51621af4dab9a85f98a8ddb6c09ae00fca28841d5f929fb1fb56a83f390d80", "CS1": "040976e5abcfbde649f6dab00b2cc646f3a7dbf2c17d3ca1868215be1792105482131c89b64d7f5fb145448ebcadaa0b5fb17e16bf59543b33eeaf980f2628ff4b", "CS2": "04030e97baa72d884c571b55b772cb44b76069c303e50d806e1e12a2619b6fa08105e4f9851ebfdf93f04a97625f4ba6b179672a0f4f24d850ec62ec6289829504", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041f71410c4c6af36dad0a509be7be7608de23a5060ebfed18b2fa8f0de69b76420dc78ae4239064a07cf145dcc846c74a4e019144b06c35de7dedc6a4a774b70c", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "04078479f8ca2998d4df3a20689095f790bbb456284b73c0b39ed420e1b6938806075ae67a4de0dc12335666b69d31244793cc343e138b485a7d5c007a65cf6c36", "U": "041568c6dc9a3a2419e21204993056d2ae5a3745408eb4cf0ce6600eba6e043c6d1b00a07f2a9a124f35548ef3f145398562b1ead7655923402ca79ea8fa06ab24", "SERVER_OUTPUT": 0, "V": "0422214b809f310be752928eb3da8d8b4de20a6d91f068461fefd9e901656e50d413f00396de2b8b9f8ac27ea05125928355c625990008df0172acc394b352442d", "Y": "1450ddb74020ae9207dbbbcbf50a4f540dc497dbb0dd088ccb06ba87918da42e", "X": "09ff4e4a99ab7227039629d6b0c79a4e334d89239d71ca32da183e1b09c19e84", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 286, "UT": "0406a941bd98fa9f4d8da0cf047741a8f52e4ec76a825be4986b9e6e244fe961fe1b363dadcab160fda14b890d571663675f20eb002c5776b092fb05c85845d4f6", "MS2": "13f03e771f82826ecfeaf0e447e842194fba207c395d1fdc346670799768f9da", "MS1": "23a03fb6540f397616df60d4ce19fa58558c09171ed0a6af04deb38887f30564", "CLIENT_SECRET": "0414d5bac48c8d1d7c09752d16c64205bb27efa3bfd29ee794f73773edb40214ed007373aee80c2b1ca6c63c3660805006408df7f43c530b1e0879d8c6c8d45d93"}, {"SS1": "00afa811f5b8eb0184d6d3a94754e4f4bc1b8be9b8c66c2ffe91e48d1fc20b591113f338421506f4aa9f279dabe1362a5ade68794844a49d160065d25a3bbb4121131f901fbe9c3cc856caad1a665c8382e76c0e69450f34160c4c4b9f8f9d6414b9d2ccfa369c5e28352eaad4907596f10e20e4c10b0f0d3d1a1acb68dd01ee", "SS2": "121f0dbd682bc5c9e93ce428be6b2759d46fa3d8a93f6b1e09d4531438caf07e0570485d5a19d06e55a0b61f1c2ca81c182ce23863a957f4d7926faf53166c760ef6a0cf472e38b92ac886b4fe1571a47a703f4e01afe8e2c684f3f1927472cc05001b3264c9de21d557ac98dbbea81977d0a899c0eae1fd8e57c7c5ca1313a2", "DATE": 16661, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0d3c562d3c487321675f70061b9bc54a1e8c8d1a1d34a9c3045529a00ca7d59f002ec0ba18c311fef433e1540799e9211ee858377980fb868f574ff81b4b2ce519d4c0ac6ac213a8621e1e77b168a96acca6f43b72b778f3542f299b7f9d351c1ce7b6ccb4763f1218bf4c8ca46a306d93ea61d7be7ff0ad541e98420a01075f", "SEC": "040b6e430a2833753caf8d42013e18888bb452c434a072eefbb949f9f993a953260c22d034d0d78738e24d7141e417e9085d796846647777179675d35401e56f49", "TP2": "0401202407ca15b45c4ca21e711291ffcef8117f658032508bbac59d72fb52ebe30568fd884142f9b14c674211c840d614559234dcd920f6154fa35d710df8e2a5", "TP1": "040d5494e9b8593ba64b845808166c66c8c16d84fdfd579077bf72e54eb16059a904b98023796997130f4c0959069656ae7aadac91cc78334f6c25f00d37dcfbb7", "CS1": "0403c9e679a62b7369b19bd7c768963bac8a2fe95872caca0cce8dc36be897558a0bf120c6767052aa64a1cb3bd79377dd9523215ea171a1a3c2dffc8f643d5abe", "CS2": "041e9ba7129aa86fc0bfcc27ae1fae52ddf12b0d4632ca51521a1a9b30e9b7373e238ae4dca10b7345c3fdbf88a14dbfeb3760133eef3600e64d67211f120e777c", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041fa20ea07f632f635bfe8fe907920a59e50c913f3d13357d8bf9cb51aca8474c02f65948600096c8b72e54a2de2b6de044be2a7e4b32f7bf4b0a360e87a707db", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "041f6b450eec9d0d86f5295ca093bf9c115cce7f94a7930b7f577652bbea0f237e1a001e47dd0d1a2ea3cf83e45274ab90f65a49114b0f8c3019013270d2a95bc3", "U": "0414b4e7e05bb3999846934226d22e37b901e54ff5cba2a4dd0d11da6ff23c457a078edaf182ae10ee0fa0d567af772026624deeba9fcaa4eb37e2e3a4938d4067", "SERVER_OUTPUT": 0, "V": "042279a8e9bf47653f5e7744fc0c00b9ad018414f3734fa5ed437805f89de66b1d1d128be78f77ad62c8853436fbacfe5b9f70ddf576965378ca012d26feeecb96", "Y": "0ffc629472c776dc3ff7460476d608197666332035c3ccd598d3b16a169bcfe3", "X": "11a77cccf5a2c47913df7f96bdeac89b0421b442bb910f12597e95dceb6e4aad", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 287, "UT": "040be9a2450b1892cb5cf472f38c16804d06b99287c73bc1060e7c258e7ba88f5f20b2d59803bb062c655608fc0490e1149fdd1e4d6ca8d583e5b3841eaee55d24", "MS2": "0a790768b3af6d8a98c0b2eae691eb83a30a9bd2761668524d56405c033c15b0", "MS1": "0961539606949dabb236c094a2346a4ca815a7555c1019eeb542a9a1cc397eb0", "CLIENT_SECRET": "0412f6543801958829528ca97ec0654b1869c24f000f46dc79610e760d6f6f02fb061eb5b1d73aa3d40f119fa13e4a6ddd093fc2cc98139555874c34022c125d5b"}, {"SS1": "0e3525810435aa93c1041101aef225cd549a25102d462c1d286c588a4ca1985c1db5460273f04d923d78ab6f041a0b802385aba94e199cc2bb92dd861aeda9a61b8680b9ef324952339d82287cd6774141865797f53651afa6ac63deb28e7b8a0f81b25729669ace05e60eccdac4dd92ef7592158b210debc25c394d4fed967e", "SS2": "14cdfdd54ecc4c9f59eda836c71ecfbe687cb7f64190b7ded2540275ab9000c20dd4841c8cd147d58d682954afe710973d1cd1c0cbbc2e889720e25cc7afb8630386a9812084e3965048bdad4dfb025e2ac0a8cadf6c1b81584f4ca7fad65914202d3fabb533a7c025702e32050f0432fa1cc6aea7537ee679a50fedfb96dec9", "DATE": 16662, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "01531547a690d0b3948fe9384c9a6d1af1ec8b3790fa1d6ffd6a44ba285fe4280e69746343c9d408c9907ad9e6077f3abc1a6ed58b87ca5b57e914d554ede1db0ba85b173b93f14247731d24d28f733699e33aa67fb4773a8a0eca284a4c55fb14fc1c8535f3e1e7007bce8e44a48316da5b8b3b1cc276cacd3c7cd6fa91dc4c", "SEC": "040980871b3e8ed5867e094e2d168d3263be1a46f5b97a6fbfce487cb015b3fc1a1f622833dc9e68de65cb7cd18d15ed4593a3d2af27894b0feedd4f91facfb424", "TP2": "041626a71b5069dc7ef6de02826d866918c99d8e1bc38b07957a8b171f04590c571fdca440f4fd31b3ab9e964c7af4ae1b29b2eac12e6d32fd1438da828c922839", "TP1": "0419475277c8af9718227686d59ada816192cfd72ce7a0f491a046831dee80b9c00dd16353d87d681d0a23603a165e4c035cc270d73efc078bc5c6667762e3040b", "CS1": "041db6700c8c944a2c7a23f099fc5fc344a36bf81769a4d4eb78608103f1adb00212c110277e3b3c1956cc8e6c3a8172c7910a526fc7e8c388ae01798d2dfeb7ea", "CS2": "041798eebb5f5d2d3031c36318ead665ec47b924984e2b4d032906d1bc9223361d1e760d32b53a3690db3731f83529d021ac2af84351506780a8ac7ba83b4759b8", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04082b913683a0b0f750cd49904c6382233a6fcf2fc0d75952574bfdc23a4cd7cd1c6218bf7c716bd9783114e092fa3056af4c61a0a1f57cf346a2dc9ced3ce23d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "040d801c8242128ad7f191a58276cf166e67cd6cf6129b507a209f70f9cb02b1e40925ddecff89e04ce0558260ba124e9e5ebefdfc8b4e2bad1d8ac441da4f84ae", "U": "041c81fbc23807eb9632090c1b4273809ac8e0d289de70ed68da15b152e6ca7e150f7e9fe9561acca51414b76331c1d785ccce9d1d6d67085fd600ded871eba935", "SERVER_OUTPUT": 0, "V": "0408fcfdcef3f3b4f31cc0a5414bc8941a527a1b678fc52814d46122dc382ff7780f0d92412796612dd84f5621ee4fda26bcc3817497f445fd942ce71b7cb15968", "Y": "22335bbc1261842331dc0263256aa445170bc40ca98f2ec15d39f33bd1ac31cd", "X": "067a27bff5edd9071817e408d0f64324bf22f13fcd2a63075df2b21f0f79ca27", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 288, "UT": "042314e90e1bc3217d84184bdc85cc1a23054d81cc00f04bb2d819b25abf23e2520ba42d791f7beffb0cc4b3c59d90fb0ad5618e6d1b9da00c64ebd1a0c976c84d", "MS2": "006441acc5b2053aff9796f87cdb1e7d499312a0b02218b1fbbf61d76cbd73cd", "MS1": "1636e568ad75e4da92617551cf9c04fb59a33130d7f23e041296b5b78a66cc9a", "CLIENT_SECRET": "04054e0f81fb27e63a92c96bbe590edad11c7273917e97c88c0211dc14ebb33da807cf205e55cd4389ab00048adcf1ad20208300f352af9f9dedb2849104628c9f"}, {"SS1": "1e99b3e69329ef7c1741004a748f6398ce82db9bf9c6301e82714f59b27f56ba1dc9f85cc58d8d51a7b762ab4a1e34d971a27e4c7287e4b21a55c057293c8d040654239b9437c75e49649916d9b85d18d270c6702a620f22d3e7218234dcf332144664094af3b6f8e053c107c4a0272e7b64e84dff9c6018756b81b960bad4d6", "SS2": "17666be8ad767b7ed63512f9753e40084032dd5eeb8cb09726599babbffb921a03956f8dcbc1483cf30f0db6fd4d6426b024c792c77fd44ca4f7225564a7097917c823321e41820026f3f93249ffabd1e9d7a4d8f0f6354e3ba0ad68c978f21706f8543918946dfe14d6d75fbe064cfcbe9dbacc7a479b2b09d40469f4f4c419", "DATE": 16663, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0a0fe088a7c10e1070d5dc667ca01234ce43300b9f26bfe7ad7b87bcabcc56a412a349b81b9f3aee55e2d1415b8becef7ad60d4ee281fe0aca87a394f804c5ab06206823e167632f5f3654e66fe96f753aac395b78dbfd5bf87c25fab216d4d81111bfa85cd453e2482be0be08cafccdb5c6d31401075acbe0020802e39c1745", "SEC": "041906837b38fa85cbc25e6a020b9a8ea74fe67ab2e61c539fda81428d1e2fbb081e459c98a158e99bfbe613317282f93e783fe31f17825359f768dd680a698d66", "TP2": "041f5d097f5f096bfb9200cdbc5734349b71a1aae413c7b2edefcc0ecd10cd2cac1b267c43de85e8ab4f680e350441a9724f4e2d0c3f153c963242a43e92d63dce", "TP1": "040b234e1c4572ea724a8afd90ba4074596b12d8d143dd2c6c3d34e1e94fda808b1009ca6428503ef4effdd0e225627766481d67d0fd79d8c115b55d05d0a9cfa2", "CS1": "0403ad77932ee5990580ffe89566d501cb29ff674ad3d45374a588a16e0ccae3320c77522785b1b27afd09671507ece76e32a95f05f0aa1d56b266c8d6fc2fed47", "CS2": "04129ac53a95fae3e4c9bd6ec0c3b2cd383b0f528af9b48d2f4d556bcd5e761f2702c9ca5674e7a074ee2e8ac84918f74b6f0f88d5b3d9b26a13ef66b153b7e5c9", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040170ac92f7150ddfd8c62f43598ab2bb8dc795cf0a9c48b0904b4c1f4e500754055897ed02729b6b2589d9cdf1c089f5ec03f623dbc25b8e2b0f48ec1eabf54c", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "041a5ef86552b07615cbd64769f0e056db92b71d19fcfef3b31b83e1cc37ece5be22d8531c96142f287783ecf3ebd239843181d2fcdf2556fbd13aa9bac53ecb69", "U": "040494362fffd47e72512fcc14d5d909144093a7102ee9af5ab372c8507045b363088076159fb8aec75d5178b3c487fdd25a22770edcd2d5eb3107073fccb14535", "SERVER_OUTPUT": 0, "V": "0402bcb67c4407c0fa786a1e883ba167844c8f59f6651f3b10db5802a10d5ecf9215718de6d981f71da5c53c2b2e13d64ef0806a205fd40c2d8671c8db6475ef5c", "Y": "0aa55d1a01df1ebb5b3a6dd507681e4c5a4acfd0703ee765e8301c1dcbb39b17", "X": "028605d6f73161c648ccf8be3fadf918e00b682e11b0d10e592df9c21091cf3f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 289, "UT": "041e8908795d20c500752ea173a9a1e04d5fdb539525726649855b21259e4a679f171f88e9d7fb0461b0fde766ad06f8113fc89aa05876497091a5fb92d6ae508c", "MS2": "00e557db2b8c3b5736dcb1f4b750c754758a9815732fc67ffe6e9dcb7c6b7ff2", "MS1": "161e355aaf19cafe1519ee6825b0a7b92cbc3c648ad89d80d05ac02680570778", "CLIENT_SECRET": "041d133cf8193ef1a4f6f6edf28a018508f05a121b128606a33cc0cfd5edae2adb1e552ada4f0f3a13b6d5e908ac9d4367f5a088f3938e916e9f4dae492a6b297f"}, {"SS1": "125034ba66ab8767b7aa5c652142804862c2e88549f1fc7ccae74ee2ec364fb819012925b39d92d1e598c9102acfff940fcdc126687e5892ba2a26b6bcfb323e10392c5a13b444890645fbe7cdeb0704d34b98695038de790fb48573a39b18601e9cd8e787c71671e96be4bd38a031e6564e78437dc1caa3c2f5e4ac3418e2da", "SS2": "173749747d0698ed2a5ca349aa80b6206e714616cb2a97d6536fa944fdefff7a03050f0764408120bb3b69838c8de57dde57f9e29069fefada4a3874708e1ebf0c2db7f57801c32130d88073a5086c0139ea6fa5664571dece369ac0575b77811a0ac2b8e8540520f1229b874741c52bef4c75fb900a58d88e4965f4811f62b7", "DATE": 16664, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0cfd1401eac9836347497ca18173f0ba97e2f212d3b423650b20fefb143cd5b3011ed4d3f25641a5bd0b4cd263d42a5a2eb824a5160e7883632f73360a796d241130b07f78a709983b12fc971981b2cbf018101ce7e41ca4de32ae760d66a5dd1e42fe7ffaae26da65df2eeaefa93a82678497a5a0d1a20dbf0ed8683265736a", "SEC": "0421f88a77921f8fe0739401379834284d20825693532b3a8809d363305f495ab20508edd5451638fa9346fa294298130ad64f0ded007972fe06105ae8a4ba9e78", "TP2": "042355a73546ddfde74c8d724a4bc7d324f926a8d22420908fcfb94e39a41b9d5b0fe6ea1bef90576faf656a4e7abde38b0c921655aa6630a3bcc661afc8355f0a", "TP1": "04236eaa40d5c44f0c46ec60a23cd7e1ca6cd88c34078172a321e664a08a9e3c4022ecd70931412aa1708112b6a430281cceecdf4451a6fb3e50c5168385327b26", "CS1": "04024ab60e1c6b694df1e2e082f48d5ae75f7242cbe55c31a94c99878d091e4e820c8405da96721e71636889489fb1486b9aa02cba38efc33444848e7dc2c7a13b", "CS2": "04120e0db91499bd9474e4940d2dd3d93efa70d745d14abf4aa114630cdc95090e161ef2f626b7d6b5efb00fb359783f052caa7af5bfb8e295dff6653acb2de007", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04080852e87b0d024c94ce04f79a4e9efa173213410d643f5419d762b688bd17f90d7bc647bfe456a6a2c548002633bd08d9e96ef12afd2244cadc48b7f3e8b0a8", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0420c3aed01065cd7eb4e28edb50037a93094c70f66540d1aee0ff527cff92cb1320c6461ebe29cb0c48486b105dc6e2bf636f1f667cd8a6dc5260f706e9aaa261", "U": "0406a1d28169a90bafd4bfa6da8c0552e7f6a7015d650277379c73b581c367f58a2081184a945a8a9de360a0f366d23eb08a9af34605f7c530e11fc3cd626ce7f9", "SERVER_OUTPUT": 0, "V": "040c772e9fcb4ab94a51aa051ac7d0dc2b9108738327be9a34d786a489eeeeecfa21bf27c1f1e88cdd6e78569774f2fcd356cec324de7ef5b3409019de3521831e", "Y": "0ea9992812513a0a8ee41332da0581113682abd4d7190600038c1bbf75988412", "X": "1258da87135dcdf7407f5e5c96b27d8c65832f9c5af934bb900d02f795e4eaa0", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 290, "UT": "041aeed2df1f40d6ff1c468d7a2475fd4f60d27ef0affb5717e61556411baaf986090c07c4e4ebd39f2824892165032fd91fdd4804c5d7ba811ad8e153d4ef7bb0", "MS2": "212753aecfb03f0e9b986dc9291b6824d65ebd287076c5e0c15af1710c809c2b", "MS1": "187042a638cb8b02a4adbbbbcd72426acba38ebd3287f70636469159654a45b3", "CLIENT_SECRET": "0411b873c6ffcf083c25bc42bb24fa10e86f1794a179e93a45e9b97ed7ecc35cc507ed65573bad86693369e268b1b596f7a1ff01891ebcb1da3b0177b025e6298d"}, {"SS1": "1e68bf40946cfd4fc6925d630a566511584310437f139b2c831981eeb08779010976549682b00839d39479aee26f3a8f17b93093fe704b54b29bdfa257c15db515d1d2808527367c2e014525015237e15a0a4fa8c8b65bd39c313255f0ee6db9228be9b078f8782a9c121cb72ec65e1e5fbc1eccb7550f7b2712f6717e788f83", "SS2": "197bd189966601d37c64a31ebeb7a255664977f7278622046361e4b4594a0a6b0f47730f0abe09d74d2156c3cc51c0f82bac21aa3b91a6f6c0310619d269edd40feb7a5c0e014d5120bc918f2ad9da927be8dd037f3db7a3e0737c59803dfa451e096b2e1fbd92ba59b92581d820986a164e9159b1402af154b5d2ff89eb93a0", "DATE": 16665, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0f9d95e3d5375e51eaa18179d1f65b56dfb50fe42f9329300a5374338eacbaee0dbf30fd7038b7cd9387201672b3828127a46f452c2eb7b2637c35c0cdcdd8431f14a0cbc40fee7a05c0a3589359e28e471aba36b2bcc7ca26218b5ba596c041098edeb23f2ee004c90cf27fc6bd3fc6e65fdf9a1066250650935f05c2e2488d", "SEC": "04224267c778bdf389403b25441b302afb97fa5f1675825c2de47d4a935d72374f1b309ada5af2434b6978f69cbe9b9c625422c5502209a695e279cdf7b9a355bc", "TP2": "042194729af2a9b02af889904e40cf89895cad43cc35c8673820526eea33c7f1cd0de12c1a52f996304e642987da7ad85f9f20b9266a6b62fa57cbc9aa38124b05", "TP1": "041aa1daaecf1feea142b9fc7d9db3a6e98f95dba1bb63fe6839b7fb82334199ad096747a431b65661dac690e9dd949780d1e4c004de168e12dd89ede6cb5bad5b", "CS1": "0420ab395a395f1627542974157aab70c07f546e126ce8621080e0b994524b9f7f06e9ef506cfbbb0038b05042655d31c299c3648bbf7e31bb3192fbd5dc4249bf", "CS2": "04079a1acfa9b9e4fa5bc7c6c01269a48f14ec7c7934b3d9d78f3ee0490a3d0acb07f321108bf2ed50dbb95f48463f7b29cb47a3fb1f5569a93d12e050b2c47759", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04179ca22af5a54532a8fda056cc0fd8cf091bc881ac6aeb2b9440e07956d9f35c1cdb84640f4529b684f493e7cac9218322c68468bde575d5c966f82a1ecd1047", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0405da303a74870ef9843e6ecd60f9da44c67f409556ad67aeb77985f837b63e0b17ea7e27a3dea8e83cc779661853014670a02fb1a75186fc704af49b5a0137cb", "U": "0413153f7fb7af048e079e70e555a790a188a99ee93b3d5ec89c65eb896bab5ce30ed419edd596dee92a286aea3a7ffa09a2b7cce51a12c7ed8e6c2858b8179c50", "SERVER_OUTPUT": 0, "V": "041928b15480b1474b4e043025983c74ac81f650dff44c1ad6a7d5408d292fb6c61db2993947ee57ce2993cd1963ae922c696b04fde85a7ccfd8682c3fe7cd0e64", "Y": "0cc25f04703ce2b5b7abd2d0c39e2370fde13448e51cae1be6896b44cdb51b4d", "X": "0691be5654a33ee551b5ca8c4600974ecbfde54e243ce41bd8a56a021972c912", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 291, "UT": "04004c9c30ddb5dda0a0ef8f4639f24ee968def62c653d70497bf723c347f1d01a097ba6f16085235d2109b1e78e790e59f6aa3d7530a927d86ca64198c1556544", "MS2": "0cd40e6553d2ee0e58ea8a88a81e75713c0021ae464fc67d4feb5d83990af63c", "MS1": "0f979ff75bce4b1a32f1d2a7e31b78b4896e853528e52ee63cbc9935e4cc5d8d", "CLIENT_SECRET": "04004b164fa2dc610b53990631c869f1c03c9c901baf101c648b271f5e41bbba0d04fee657f7fb9b4a2ac045073fcacad73e6a95c355dd539628e335177e8bad1b"}, {"SS1": "05c5f84928d76f8b20dd8b1d8ce73c7ac785ab381f0b8b73af90b81cd70144661ebe2aa5847b0b2124fe9249f17f6272594c67483ed2e9df7005b4bff2930b7a0c44c6c170a3b765f208dc352701771ab5b072519527f8032702aefa547c76ec221071d16e2fbcc0cfe62a2840de319eb7c18d2df843eec86eb9b4cd0c0cce51", "SS2": "0947629f4dd55966d7809c2e02026e26de047007ca215faa13cf4ca79b01955d1bb2d41434b1b5d325dd1c0ce395ea35060542ec487c07af1f16814ae9442c861922270d45e0f031d47680d3531fcbd115c30ba4949f0810d0f341415086b95a05a4b8cac172ab041061c1f33f28d2c785baa45754cd4b8d7063e31ac06073c4", "DATE": 16666, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "07ac8fa3e29831f90ba328363b66e83b495eea004592d46a20a9b1f858f8071c168657181f6e00da3443f6541459b39c49a6940c9c4d0d13a9156e81662a2ab805d8448e0d75d72db447724f26c62dd1412face11903e219b9daa6d1cf2724702246dc050a36d53c43bd81194ef3569e99562540ba903adcdb4afdb8c4daf3e4", "SEC": "040f9c035b5b1251783309baa0c958849a29c8d72d0ba64b5675d6a6be05fe48bf1aa0aacaead2914e6ded64312d4a5c2efea7a219b896a1bd62795b9b684645d1", "TP2": "040157b729d5ab96555ee667ca877fae7c501218c7175d5dd7abffe4ea54574da70ce20570d18402a74a8d2bbed9495e5c7bf59ffc4972af40d110d62616feea06", "TP1": "04222eea611858986d20caca777353fc2150c27b57dc78afff7a7c1b18986d3096163734f26c23c327c1d28aaa0a67a1c37730464fbb0aa947bc28dfbca9d02b9c", "CS1": "0415cca87047ac89a5e79640107930f0d570ce139f83f7a604366691b335393d0a1581b169fa610e68070d5fbe38a44f84b7f36006849c997469f365ec8967cc73", "CS2": "0410b4a770911919e66240ca034d11fd10ffb5d385c0ad410e1fc3b853c0c508861ad63a0d54953fbb34c43331056ffc1951882f45baed5dbc6208ad9147695471", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041ff3946ccb23d1328f3b8427f456da70162378794e3576bbbea6e8f41464cf2b00465bc97920929c83e0b8a2f36fc2bc7a43a6d5b963b8ccbfc9dc2b65b2a3ed", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "04051abd9d7d9174c911639febc95f1488ca0d189ccb0c84ca830d16cd9095234d160f1c9591ed3f7b08618b3d0a6bc102c4bc6e4a266b4b0513c9a803d4cbf1ed", "U": "04024e56edb43fe2a8bb64055986314274531f37d91f7735ec06454ffedb807c2c22f91b34883cc9c4e1ccaec9e1214f65063d5d314d3cf3b977cccb61297070b9", "SERVER_OUTPUT": 0, "V": "040bd619dbdc894a9f0b91cadb0fc29a20074202b548733427ef86ce2fd5d6d20e11f4183472c0a56bfae1ff50b6865a4e1187bb8b784855b40eb2138d9f12555a", "Y": "1d28a3d5b3d6e816194a80299323d1432b15aca9002342998bb6eacabb0d9459", "X": "1e38f2ee2a07b994a734957fe8ba16114774334f54205568ce4c3d5e8c003b1f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 292, "UT": "040de2352819f050ac6e66444aaf5744510685755fb38b6965ff334adcfc0f125b1ab292ac45e96fcc37b086d6720056fb84b30e4b466a54bc9337df282b531860", "MS2": "13f4f1637c90cf55493ed0de78ba806c5013f4c09ac1bce598ae9b886782bb3d", "MS1": "0ecf4619dc7bc9b4709309aa9673bab31ea2f52f909488e6c6112fb4c2ea91f2", "CLIENT_SECRET": "041d4078ffbd6a0c5aa9537400ff96f2cf2ea4682707f61c21ba35a420fb13fe8502a987fe8d956c42c5ddc2eeeed29bca3fbc7d5cfc876234f32ffab697e2f1c0"}, {"SS1": "1b8445e2cd365a451b8bd39df1eded4b6707a11f909f189ff0163df9f6dd46cb214297d6fac4ddbe62f5a9224be817f501a21837c035418c9acb7fe09dad4382144c2385e120c8d3edd9cea2070f7a44672fdde5de7a11dcc03b7f954cd2f24c130674b283cfa3c0f702e3bfd8e55841ca00814f6691c3608b36d04dfd3b7887", "SS2": "152ca231086a6113e44ba51529eb0e0caed6c76d78ed83de1ab37b5e296c772606b163f2a7846f867551d1949b0cb6620b3f3424e0c8aa333589b385532beb27042308a01e6a7ebac38eaa82129580c3e4fa27292bc682d039c9b2c345e5c2c8216fa2724160b03ec52cab2992f4f61cc3853b995416751552a1a0e7a2cfbba5", "DATE": 16667, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "02629451711263b6565a433f7d05152a5ef214755a5dc57a8c827c0fba77d26e215e83a4ccbda5c3d4a9225a3e31f47e46580172b64ef92db27f441053d9fa0a0728a45612d7641882846bf19ab8a8a6226a3d53b86024e36b5d57ed5a070ec71d6dc91bb0dda15c93654461acb5deaa6f53b9bce33e2be41787aa462e2b930d", "SEC": "040ed70d2ca4144a258db6cb5d4456b810eb043d1dca897cf1bb1cbed52938a584105a7b456d7a4a58ac8dfa110121be23f3b7ac89d32dd4ced3b13b79f272e538", "TP2": "040c4c4a6bc5b573b01504b0e76f24836bacc87a4fd1eb8ab3c5a9aaa71c0bd6e50352095960da5823530395a387ed02ea9b7933c61c04c646428e49caaa61c757", "TP1": "04121048869b0be287208b7a5158576801e7dde7244b0f75ec74cdb7e65dc7042a1caad8f0a26a1d5f15958638ab576b0911a8056e320632f82da4b12d5a254fd8", "CS1": "040414385f15314279eeba921c4c1ab1fcea5f45b68ce9dbdd996435c649c9fdf81ad5f8cdf714f73276e09252ed8d11ef6c5650fd481802e6e8c49aec94f293e1", "CS2": "0400c1e25dad1ad9a5b8d08720bc70e7e98f2ae24bdbf7c1375b2c2ea41d3a657a04c57fb120f4eb4b9f2207cb583aa6022552a93a6312b60cf7b3cc0986ad504d", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041b041b0325bcfab33b7552e4189f3b289ac406012d74f346f37e6cb6cf7d9da3113c7c95d492098a2d7ff79558364d90f108616c6d75affe53711ecf12c789b7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "040c818701d2c0e19ae5c313dd5e927c32d45434802889bdb8eeec3db051fa63570bcc02ca4b6823afbdb574ae44ab5601f4b5e2120ce48c45dc2da589869fcb88", "U": "0405d9e24b927934bd1047435266bbffe7188f508e959ab3fc3c584c63e2c3e3040f498eb95580368f2012d8b16851a55860d95e5c219133b9326b3991c8ae020d", "SERVER_OUTPUT": 0, "V": "04217ed5a0ccc64601a10f3581389552799cb7973615b26f73070e77267675a7112111a746d8d7bb221c514d013afff35620210ad989580d8132df3cf55394da23", "Y": "01b3ebd04a4915a7b3e45cdddfad1017f58f92fd4a94b27916cf7acfd7dc002a", "X": "19a0f3768a6acee9f44972feecd23bf6e93e74a4bb22a93441a1e4951dee8ca1", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 293, "UT": "04188c3c79f19914431e419216533d0595d49b37b2f93dc988425007032ccb13e70ce2a3e08ea4f59d6b0d70c426597bd66cba309bcc3ac8b3b539986dbb553563", "MS2": "1dcae6cc5bc4d83df2db3d1fcf2fb1fc9f7602d6288cbbe7b0dc75804c076872", "MS1": "1d7f4b899fe4a5622153384a5860ec7ab7290d15ba07293adba9ed461b339788", "CLIENT_SECRET": "041826d7c6bc1426b0d3e8127bfc15a07f02363eb44d2a06128c0ce565d6bc19a519a2eaafa427c237f37baedf492fcf702a71cc1fcb70cd556b7593b5a9240a06"}, {"SS1": "0770ac38fa541579836059d0ee458b18b0a1fbd175ada17f1352dc4bfc9a6d0218e52b01acdab213fc1ed16aeeaf2edcb7e913efcf60c75fd9bbceee3960b12521969ebc595a8338aa54b302ec4824ff76ff1d28c8aad70f3d9d5697fe84e1e42171ad081b2bd654a22fc12b532b71993986d665df53bfac4946e9abfea0f495", "SS2": "0eed4d40169b8128eb4d93803acd9d164c72e73e64a85ae36f5fcc48b1292f0d17474fc76170bec3e96e28e1348589b7989d73afe4db27f683eb8036222bb34722b3782374fcfb515d4ceee49ab76f97fcf4a030e60d8573fa9f9d8802db8be71099c51b4096866bc7bd16b1ab95aea08424698f625e6921bb99c3943c686f1d", "DATE": 16668, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "209bfd9955d509563d746024c71b840831b57a8ab322b7480ee08728d396e01318f86bbe56f8304aed25f02377d48cd38b5deb0d74604ab6a12ff9901bfdd1b80f3dc7189a088503e253bf5fccf6147bf1d91639299a65530a53d093c26b92d212fab81c8f1443c4e80e7d1d31ce736c9f0a093a9300cf2590ea6e4688130466", "SEC": "0407e69badfa7af6fda3ad6dc944ab44a7fa124affeedbd900b41c28942917767516cd94259555307e9524f3c4cd155d0f7bee5081614de9b266c96812367f55ec", "TP2": "040e74db118a0a9e35b88abbc03dfda2ebb873053731d7c31a47695ac09000729005145f7e1e6c272ab38d14ee18e8efd92031f42d6003f905f073db00401c81c6", "TP1": "04207466714d1f21d0f2ea8de7c96c5cdc0c6b76e78fad93e9bbba1e89b176579510d60b41060d439c256f67c11b76c0ceb08f488d82a8c5b23e571f818b0d15cf", "CS1": "0419ebe0be83b4967e2bbccd0a8f811a5af29591e562b5cced97fcc244d6133c6a05376c5b35de0e584259335bc1eadf83730003699bc136be3f1f385c37f3bf05", "CS2": "041cfdb8615aa8a67a03f5c8773794fc173cd9b0457dfc3fb1c13535ca19c8875f0c2d410c5246b03c55c787b83289013ba237bb6e9c625de6e285d2af8f0321b9", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040c497a774d0a12cddfa8064fd51f178f6bdafe2607bc45babc70a362947e92df1a146366b77c6aaa8ddc2320b42b6fc656cca1611dd2c70b653441df450df33a", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0421229fac062f57a6557da6c6f82435b70b6fcb3c51e72976f7074400c2149d091509be8a4a482e9fbea559645bd3632f54baeba38bd6034cc9da7a7fa961934f", "U": "0404a83cba5909a67efa57fec6b78b780827f8a94f26d47f705c804fa36bda7f73065900e176eb20909141e9be05fe7fdc21a7886d5e498ca806f9c100bb97c2c1", "SERVER_OUTPUT": 0, "V": "04071bc182d009b4315eb23a1769ae6e7320140909f6c0dd49ff84b0bfbf7a158a01b50b22f0926ffede45c05d9cae76c179f905d64cc9850b26a301cd6724712e", "Y": "018a58bab61786136c8c4254816b678e4b5da946f3d5af9b91768cf4ee9539fc", "X": "11662c714965409509909716427d95963a1c1330485d61ae3656886ce573ce93", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 294, "UT": "040150cf3906b9ea19e9d4ebeaae81f683670b324dc985482711eab3ae4b277fde025a24ee52fd1bb44a62573bf0295decffbeadb965e11a5d0fe2a38740518fa9", "MS2": "20aff62a65250b9b732f53a0b3461c2cdd6928d62be1fbcd226ac6070dd90f79", "MS1": "19e90cb4426c4edf5a8e3cd1819617d26a66f891df2c13cdcf5db3580d155a94", "CLIENT_SECRET": "041802b67352e2fa92f9527fbb1ed7e082eec2f184e712bea5a77b40c925c26eeb120ffb41b0d83c5e57765918a31a83da8957a97467c9f863ab98220a2c03c0bb"}, {"SS1": "1581943c2842d11d616b9941ee1150f348e952f1203602cd4e1b34860e0005861ec4f3f9a458e5d870ec41c23ff28b561c731c82b4f03fb4415b550c7cc9097810d14be86635aad30a2bcf8e086f4e5ecd4d357c79338a75f4e8cea2c7494b8a0300d8f875baa68ec097eb604c3fe7124af7be2f3daa4514531d27b91b8152ef", "SS2": "1e8bd13b938ccee10d4fdce79ae401592cf5d92763d99f0d50c02ad36d68dbf602ca8bc7c2eeb9d530c6a38e6d6e5a1326a0b69ec240938cf916b542b97d5d46088068039436b47d14cf1c2ba13698272a45c0f907cdf9c2b9c4cde516e11e2707a48ba3754a2f7067fb8a233690e8f08d57afb219d9fe38373d52510a4a00df", "DATE": 16669, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1f9c13cacab740ecd1fab67b13c1f98dbb23e25d619d1ad0d27b725250756abd0962bb4eabb11249d663f84039ec1a7b124cd69a47b7569a44dc5bba3eb2a069097dc319767877fcfde46638ef914fbe2695930183d340cecdfb29269e972e220db404a9c3462401f9df944d2c8a06ca54a4ef54869aebd20697edb2bccd3984", "SEC": "0421ddf4aefa172306e736c840dfd72ffb6f0df5bd57174418f73e93337433f277148148f55a1bf3834f20b6e7c60d87b6efd8c5e3df3b0963523e6169ffa829e9", "TP2": "0412709eb284517df7139a24e173aee147c8820bc26a0730adc9e4d39bd8cadcc415e677733761f6534fc65ba7d86a3a9b2361146c9ea4c3b1951cb295799b9695", "TP1": "041be84612e5f4cb2b27824529b784109c877f7f0854fce9f9e75294545630f4e3168ee66bac80527f297e53287130cbe4f5cf701b607da9d406c78c908029767d", "CS1": "04209784365d6f1ab3296042f536c26eef3a28024bbfb620e3d0c29e2ed0b51c6807ed40200791c7d569b92f9b86dc737f55d908ac928c35f945e4f959f81cb76a", "CS2": "0400e1c7982004268912cf2776f00c8b1b62a522466d0d8f19e1ac86adf5dddb0701ff38546b859ae78eacd07c8043651369f96b5a94f2ae01c10424b3b14930a1", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04239d99a5b45d959688845f5e3ca7cd497f65c00062c109f075169f3eebdbba831990341a08c2e31277bfa4a59c4d440115879d3c349a58b53576ca493d469c81", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "041422cb0de79c4af903688d463b9753d9781279d95ec7d008038a82ceab43d6c5178e2c02f93a9ac5199ccf97bc68af77487c8e160b1dc849aa1077a917ef7144", "U": "0409c61bca875b3861953a3c2706532dcb41b0a3c653c2200aac62ba5320a8cbba22aeffe59706892a733c3f7b1091b84e04b5795530452a357ece2f404f668dd1", "SERVER_OUTPUT": 0, "V": "0411f6367525790e3f42bd6b1c44d5bac2264388555643adacf65e5625b1f553eb09cb75227e8ebb0d2d4d2d571df203e96f00d00580806753ea62be85b7b37576", "Y": "05806584e552414ffe2504f9a52f8cc07759b13c3d55cb2c4f832f312fa75b9d", "X": "0684763456edcff8e94687af417964c6bf7ee005692ac90002f386f92a39d43b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 295, "UT": "0411c218c380ecb580ed1fc704f70b268c8a46813c03ce2d2ddda19daab8b3742922966092f9bad2016ed8fa0beb88b0c4e04291c178e7d38928f14dfa300322bf", "MS2": "01257ceed993f5433dc1bead3c51334b68e74e193f4c2846a669cdf16972f83f", "MS1": "147fb6837d88e14a2ed717200d9e88e289826bf8087addc99ac7d72ad0ef2080", "CLIENT_SECRET": "04125164caee8a416c077769dda9bda4781d425efc1982b269793c1b56d31e1f5b1b01c99f921e60d3030526f3a84d9fe40e046db50b52702460e9d0a28a2f5624"}, {"SS1": "052361bcc3d74822575fd395356e6f6c355caddc579c8c23cb2813cb7ced97c71577415580dc02a1b650d3d6fd2d65a92a75a8eef5ec7b7efd1ee554ea84ce830e0c9d882e4fe54afbb756b199a26b7d094c32976f721388d4a92a3791f2f69002c784d8ac967f3dc87a593a290bd0c5c71914e6ea933e10d8bb2796c36aaa58", "SS2": "0bfd379cceb69d83d06ef20e12528188e2409acf95d826e7f422b82c072da85815e648fceecd680d54be49cc68bb567901149bd5981bab2f75c784547cde3ff31d43fbf4ef1974edc20a947c1a3c50afeb9df29abad41d7e99f2622655f2fac11af235c6f4bc945a2e9d036f9e9fbb099acf11e2261a11593d249d7133f3aa52", "DATE": 16670, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0131db1801b5ed2debce2a3652a900d6fb42b13cce3326e0b3d2d810417b27a21b6ad331af8c0c7377a83fafabddfe2c35cfae57135477c3b34cd8944e8692e508b2ac3713e04f8408a62b0da3dc1838aba25a00c0c1fe31cda61f442e14a2ee1a15f9dfff189a268876b193276ff455c74daa630b1ba62220671d7dc637208e", "SEC": "04054938fd0e41fa10218ad58fce8960ecf9ef3e3515b2b6617b7d50e930669920031e3e99c80498b881688131efca09fab4d3e62087c84e50f4efd9e935e26fc5", "TP2": "0420d25e26ed4a7c190a9f78c7658059a9a9507edc47e13513f82a6a13242d68d0070b3b0b44211a0107ecdb06d5ead9269f8f604386dd9f8990d1e61b1c6dcdfd", "TP1": "0404a85a87239b1e4e7b8f80b90e70ddae06dc4c7806a1512818495d04a294b5fc09ee9030357a1bbd27efef9a424deaf83503dc8c2591a087d25abdaf6c249d5b", "CS1": "0422efa9e0d598324ab68597efc7d6011f9e15e3e8d8d52f3a2395557a81e708a112b118e238ce51441eb76800b68017225751b436c15eb1fe425539c7490e89df", "CS2": "0422de9fc1dca1de4254bd199f26ad823e11c580b9b709fd976efcddaa7cd200ea0099795ef1f353d2369c7053d41b260c5d4c283f600fe1e4204c2e6901982e19", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "0418218742244ee71c0b1e28ed464adcec00c764f9c06ade57119e2395779e4bd6131dc248cfc9de23de68db9f5c80bec253106992261e93a172ae2b616227f60f", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "042011f2ac0e14ccba5f6edb40ee8bae61ee173d4e0b661733aa3caa88f90ebdf603c383edd51d2de19d22f9458b08fddaf896c64f68a5c01f7a0ed9729bd96bdd", "U": "040a537c2a98f80ceacb277a2e4d32c3be2417368a0e3a3fabef43a7a1be50f03703f45e0776652cb660d8adda2207ed90d6ee427aa99da69ec53d41e709375845", "SERVER_OUTPUT": 0, "V": "041d99a5619a8c819214c94a79c61ded7b050fc08705b82c215e43947b7d947e4203c3f575439f53e3493055efaef5634760562343f398b3d373b7be1089164555", "Y": "1eb3e388e30a78e30a30ae00d1aa6e556a0c8abb2273988585d9eb325cb38cac", "X": "20992e687d4cb569ebb33a0e6a3f8ddba08f94b1086bfe1c9c3ec5045b857cd6", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 296, "UT": "04177e061f9d4d6e679331fcb4a88e76e2db439ec55bdb839d152dc9140944e7c50ab81092db5e7fbcfe53bf89b8954288ea456647a8cb5d2ad0e2dde53f8d74fa", "MS2": "15df4c12b2db2aaeede838c37d6c41fb5f8bfbb83cd451daf30cf0ba968d1d4c", "MS1": "0e466a484939d6f3ff97eda039fc6a5c6d69d895d6976aafce34514d1084352a", "CLIENT_SECRET": "0408e2c700d65f9947ff00826121474ca4fd2e0e9568625b9d735da5cf8425b3b2095d43071ffbb5e5231fbfbbac2aff0d69570c6068f4cf4932f5ae88f93fcc2a"}, {"SS1": "1a47d5db4bff0549c999dc46adfd7c853f9ddd51ffb4583d6c6160762c007697064b4a55b956764d977085ae39a6dbfc3bd1efa3e919a7cde30d84851beb09bf0ad0ede71de0acc0e9bfdaf86e01d393e993b2b1affd1e657708b8c852756a110674975eac3dd97634d9ea17661c912d1784731447727074aeaaaff8e5dfd1b7", "SS2": "157ef66639885f2e83437ddaeba727b9e2e6fe24f12efd37e8bd980284e9c8d113a08774c25b5f146432c90ee10d26d1ea35c3cf9401b248c7a8fdafccac18d7123a5759465ccc6a1d81b1df540424c8cff22b9e746f2910bb104b00f64c1d372079c07620b6ac0e61ebe4edc64f9e5d8f98b9d1b534e42446444f456fceb902", "DATE": 16671, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1b665c4fde8a073792bc050e6e09e40f8f62f3f558600d0ece1b74651f18b18d16d4333bfe28852eec1a8fc94cdffd8e6d812bb2d4c45f978372250d978e1555143396c52af96eff5944c350deb3ed4b63dbb0561eac8535175da241fc4b944d1ef6c6f1479058973c461e326643f52a5dd7053b659ba111f42816c48df7b555", "SEC": "0423dbe82ff399cdacea6c3719eef726f6ee532b21628a2fade85656ac5ab28231234bfafcd503dd1b54d9dfa8bf36bf65ad012acb76e800d185beca4f0b08a3c8", "TP2": "040b870219c105d20fda704f7447f5a7da5da03d91f81935952671d2348d005111090961a9268300187659b91d366696b1efbf1b4b1e63826992ef7a690fec3036", "TP1": "041936cb81a5072b2e2fc0489ff3c45a2703770e12ce07bf1276a0e4af5f63f1c903e4c7bb3b961d3db67a8414639934975aeeb2f1167363d75f233e1892baf3e5", "CS1": "0416ab7d9308db1eb4f9bdba0ea19c2c560b724b05047647eddf06309e2c95c9f81894d5ff4953c26bd84e7a23f2b940e5bceda62c302998fa4f5b767ee6a11f35", "CS2": "04019a12ae9989a853794f2eb3f3b48aa9504c721ded001c6ed771ddf2b06ac63304bff1afff9014529096aecbd766686818cdf10ec514cc70f1228d8319d2d88b", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041b99b0b259463f9d7b123d5be7d4a0f3cf4f35e58064eda7d30396df36b5fb6d0591d3e11c7dd9f3ff66120df879bfd6daa3ef1ed71c1633d3dfe29cbec4e166", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "04220b7f11462ae00267a381900f5c07c7370363ccb094e68d71972b09b50c923211976e0e2dfaa7ccba4a0b4cb093e9c9ddb73ffe8e869a518941d5c6aad8740f", "U": "04069f9dd93c43a641215495a678c851aba88d929a2a1092d8b1f9e681916547e801bde8e74c5eca9e2fdeef228a2302ac5d8589f5cd57e15b270139d532dbeffc", "SERVER_OUTPUT": 0, "V": "040703eb6ce2a1a632c779752612e905f09554e60c35320bffd84075d0c5e4f3471c95e0c6f729594e659dcd733bd71374bcfafc5c37bed595ae5b3a7bb2f1de58", "Y": "111bd24363075fbbfb09bc82b22ee8a68cd4548511a15e18ab85b97a3e10017e", "X": "1b51a2a096c35b2e79f2a60241a2fdfea7d94b2c40ec38448cdde86c9ddb2159", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 297, "UT": "040defaab299b7d5efc2b7fcd06e95366fa2776a9d586ebb21215f4ca627ecbe051780e11d9460dcf7bdc3095a8eb8e4fb74a6d47b55cbc218aa1e7d8558fffc98", "MS2": "0e2571c48a2d63d249d254ff72c9fd3ff1aba86d9b93cca56cfbfa077ba5bea5", "MS1": "00d36cbbc097c7de0ac9a22186900409a6930a2667641816fc7ddb92a5f9f5ad", "CLIENT_SECRET": "040cf567b1928a603614af195cac7aff0af750c75f71a630e72ed21f42f6ba7a2810780d7bccc3d7dc2ea932b23a466fcc5f486aaa9023f3c4f9e22ae1cfb8a4de"}, {"SS1": "16d38b0f596a522ff7430485f246831ebbf5fd5c06668f95d729af924229156103e29887b24f4b89fb5fccdb930b411770254fb2e74bdcb59739d4d6fe48dad3114351b7cf2b4279e338a4aed1aac8286efb9ea18bc080067a57eac4ff996188021fa3e6c9662b63c18c4402310a5fb452bd74eb01a63b26a304c78284fec1bd", "SS2": "03475ea1bfb08c46fedb4e91afcbaded8c5c2aed55ae8599540805301ffa7be51ea08064905037235fb5a0c1b3d253053a179661710b52cf66b7e58919d0a7ab10281ff0709b48883e7d9f0332ee7f427f0483641db9ef989e25b4a4c4ef90b3130e1394534a971de83907c254d635d998bb907a0d7327f6ed5ddd04e91f7164", "DATE": 16672, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "17076b202aa25dd7a6eda5db8dee9b963796d33e9646b881c009426b7db42ef7234bb667f23a6dbb58616a7e546e5064753181b6df594bce0000a79ce4cac5f8130042767074bebab6c8aadfe783a933244d6928961ab4b687426b113531657605b77c2bc83d4d56a8d7c5ed81ff1a3538bc567acd1c3fb6e9480400f1d64c08", "SEC": "0415b310cc1e6ee1e5664387b94ff9714cc365298195e4bc964026f9cd450f8175113f849b9b274b5b640364c6eb21bcae4fdd5742b031f9b44f8e3fcd89fc89a6", "TP2": "041501c3737785502e2160c240340979c9db9a58516535e86a04c853c96859c8a208b9907a5691533b769ae3450c153b764cf3c556e0423640cdf63df1a0b60365", "TP1": "040519289a8fd2d262a5c7cc7c865a7837bb2519fba9bdd681cf856da4225d7db70b84d5227f2bfd9724ca799e17ce0d45d1bf2554df10b7dfd839440f97d6f651", "CS1": "0419889fe25abc410f8babd4a35930efb8636c95c666721aacd5cb74ba9587bbfd1f1c87c207c45fdd740c54ef3e1f7900c35ac0d6db5af1e823bc6067df69cb74", "CS2": "0422bb59171c0d2bd6da12e728f472043f0f62b16a8e092fbc124196bd6ceaf1ff0ed5eb12e612dc5102bf3ce19a70ad24cd9b281b8480a30793c4feebf795098f", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "0404976ddf3387de3e5fc84e490f73f9aba744057d34333da16b502be3dea31da011a0a1bc1433c31653cf4b1be2e4a286f1585a93735e9498c782d532c478bc93", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "04066e706c600094373f91d59e5182584ed8e767de5421ff4a9ccde42aa47528821659e053d8a50c26684678aa3372da8ec4ea972060c4604d513ecf116ee4b431", "U": "040fcfe65a438f44385cba190f14b7e944b7c611084b424475c949c0d56295031805bf48d1f3b14de9ad26793ee3cad3565eccd3ba244aae442dde87a9a5396d9b", "SERVER_OUTPUT": 0, "V": "0400aea73305c047102fe8aec0bf9962e6dafeea779ea0eea64a4ecfeb225649f4140a7343a03fadeb0f6c8e8868b2155f891b93263654be8236298bf9831bd2be", "Y": "1a926d82dca206c2ca62ff98dbd3bbbcede73d719022f53bd78816d9f1d7f0d2", "X": "0487b4663690458ee1f3983d9e4bec91078462f21100643480bb2a68bee251a4", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 298, "UT": "041deb7db2eccd7e43f03c7d42bbddd433579bb7fbda75f2953cfcca86dc70b90c0ca731e6c060d837d9a3a328a6172dfb61f9575158e350ab4fa2a3d212141b67", "MS2": "19a94e910cd0c7abcfc8257e9a9c187891ff487be6611c7d3a53067705487abe", "MS1": "0de1deac3c1c0c15d14f73a2da9c5abe39a14c68b02b95b0bf490a4432a8ca43", "CLIENT_SECRET": "0401543be9879806ef13c0ab86926fdd2e934d8ea3ea4c209d22bc78d78ab0892c22086f30509368cdd0602fc0198f1c07be9d68a24573a40444cfe268967f0d70"}, {"SS1": "0ac949052baaa16a5ce48188162d8eb54ea5ad49befa9a91587c23fb0d149ade1e9f8009e5ff418c6113449196be5b4ab1a6b965304e8c8a64aa9bec0c2d7eb9148c2f4412d1f01e73fcb7daa7472a396f4341bdbdfa7af6001a5c07b3688aa71dc81de4a93c2c2750813c6e48c0d7d57c61c8f8d7607752d9db527891e3598c", "SS2": "22bab02df35d87e1e4aa3d8aeb43b03d899bdcc4d4f3d29049fbfd63cdfeff27072604f0535c1993c6e947084486efc5e517cf3e856e832fbdac5fc93715563e1391335137d0400a1694990397e3f9568601d476240df87f059b1ab98f7aa8ea20eeae6e4c9d5fed962a20ef3587f1ae1cfad24b354bba7aac3ab25e7e8ef4be", "DATE": 16673, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "00c865fb5deefeb94f7f5739c6398faae085ff0d313fdeeeb44449c3642d5a3018e4a401758ab207179dcebcd4eaf4715928e4fe11b267b2b27ab4d561f0f5ce009fca2f626f1019dd648829fe124417f669906bc3e3d7f17a0c7ccd0e19e6031ba6ae949c5005a0f7741e1daec6ca83ae0ed84c2c17c0b73224bebd8c3a2ad7", "SEC": "041f10185dbcf27408b66a4856b06b6c78474b20571bdd63a041b88e9b3ab2996c05bd83136567c24cb92d7a17aa155c5adda60566fce56e234103db0dc1d2fd05", "TP2": "0405372884c32692546231c565e5f62c31c247597a2da57f564b7ac8a19cb44cb108a6ed69f6650eaae4123685a5f2400cc7a0fcf68162be1ae6920e0d3f04c611", "TP1": "040c32769a41f8f42d5e7e82b1f9c52ec9941e60b5bff6f8c266333ceca788f0b40432cbdcce613e20374c8eaad1813827c002032a4c318697333980c96c1dc8ba", "CS1": "041e3f37ffa04925030d625f2cca75560048a70b04219d529466037bb785f5a0f7164cc0427e255da00e4dfde37f9a6e3a194f6c3562e1539445cc2a1ebe2199bf", "CS2": "041c47e018a81d8a0a1e0ce407e72cae0a32417ecd08d6eb49f250071f6c3b600f014e85d2b1a4490dcbad813ba98ec03cac9b02e5b18e3c96038ca1b9bc0f49a1", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041402fd00bb813739ffe1c4d3751c6ae70ca03e2b73d155408cfa4dc92c4bd6ed195841224e60c47904923f53dc234039563f347c08a68b8726c518441b876f4d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0423298fc60a7c65d4ef653908187ef2eba6c36aab473760f439ed2ef0d272fde71237e88d49dffeca82f896722d2d8d366ff7de5adbe5e45ef80381f4f9b25b2a", "U": "0421133bbcc33b3c8660382b293723b6c85b2a2cb4c992fee88cc2e3ff69b657441ef3e22ad89c7c2e35cfb709c68964b27e673627add236eb2b40fc15cdf3ed13", "SERVER_OUTPUT": 0, "V": "0402db0a293df55f62740e6c7674a388b1d8c1b998018e068d5f6cdd55403e76ba07ddaf1457e85e10197394d762a02763d7ca53c63a8eafd150e4050a5619f453", "Y": "102566e2e578b456d2045282504c569cd404b096b20c8fea3e44d59e26b80db8", "X": "068c64ee061ca41aea361337bf9768da72bc80bd0f32a8dd9bcea503ef24bac9", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 299, "UT": "0405eccf39bf9e7154ec0ddaca122c4275a641a957c1c659cf2a9bf8083ce3bd561b31a742f5454a0ba765c4507c118b75a860a93e92fecd575c58013922f36db7", "MS2": "024eabed5f481aa665f50738a56c2a94bbd34588ed559ff64d6047c73efea2b1", "MS1": "1df837e6b86130e0f5c738aa921928e7cd65b25c34c8de04f54a374f90aa5f05", "CLIENT_SECRET": "0418e490904d9ebc940bd7373fafda8c40ac0beea15482d25af9506d92caf488ca18f7ef500a0f106d05cf8bd768f5db48348682daa6f9e15651b3a38ec994c977"}]
\ No newline at end of file
diff --git a/js/tests/BNCXOnePass.json b/js/tests/BNCXOnePass.json
deleted file mode 100644
index 4556b1c..0000000
--- a/js/tests/BNCXOnePass.json
+++ /dev/null
@@ -1 +0,0 @@
-[{"TimeValue": 1437055594, "SS1": "082fc0a0f340a1d18b51be28d0fc1c14210361ee9cd89e33bbfbaceaf91b0ef90d00773c9450f6db74a254f4bdcdb0bd501a30de15975b47c82e284d5bd42f1c23e5780693e63da58f50535b2c012f89392df1ed33b476e0b516e78489726edb0002284e932e4a13a0e6e838be28ab8973a5fa9a60760e5682a0d29a8b5dc6cf", "SS2": "2387f35da03b890e44669846486d5d55abb85eb13f6f2929a5f4d65d1953cb670b8eca87941c87a1bc9965b71b023a6bcc5af324c0824789c8b9b45ec38fda1604257638e754f2b7b6ca3b62e6b3478ac5dfc8854aed61366a52febbf4ec475a06ebc4c6b7fb6ef3d180cb8e11d2fde98af8ecec3b35eacb111b594a2cc66d59", "DATE": 16632, "PIN2": 4116, "PIN1": 4116, "SERVER_SECRET": "22a04aa155b9f4e5d5f401cf4a9853a48ebb338703713f8267ce752cfe7f3576209066e00046a2b55c341e2c54420cb57d33cff5e0b5a5ebf924be1210b6a1c808aacef1a6650b76ca10e3cfe7e36c2cdd095c908485da362bb0e82ca4215ca0039fe6f40de85ae2ac6748fe4146b3bedac423bdbfbbc8c496aed0c9fc48e713", "SEC": "0416cc105db6b649eeab5c55d900a7a4e7335b17b20a8ee2421aaaa00a572fa767072fab0d6a85b789bbe9ae2d53508ebb6c63611555926ebc7b63c074ceec5194", "TP2": "0423acc4d0fb3efe6c9083ee97fba7a28999f05b34988117615df402149cb20ea6078794313732ffd3d51b47e7b5f379f493226f643ea3a25d348fae094686e73a", "TP1": "0401404487efc64b49afad56d6ee7eaaf7990baffddcae300c6a0e93d3503175480858bb4d61bf5382598385a4f586b23490b2813ce8e5ab91dd7e44422b72adc3", "CS1": "041b0e0217960c6e3f764e2893ddd54e3f9742964bfb2ae0499a642500dad1101016980875b2b430c432de5201edd774b488800734da6801c9cdedab447bbe3bec", "CS2": "041c110579293baef562105420c760f4a27d85f5890c31483d7e792d4c6ad3b9c405b67d59b286a8645b5695b5d60683e5d2b315fba27b943ee4186f94935bfa17", "HASH_MPIN_ID_HEX": "b9b3d46398bf50c2f8fb451784aa2128de642cec70115b8a31d5e88a388cba4b", "TIME_PERMIT": "0414753542c15d5efcab38b4274252da121be0bc5da5e3f333d86a0a2d5002ce790051ecdbf492b8c5dc6aacd105d173e3e1473fd078cac83233ef01c361c0a5bb", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33345a222c2022757365724944223a20223164363764313438616266363765623934346133393566623434326138623366406365727469766f782e636f6d222c202273616c74223a20226137366465353036623735653539396664316462626363643061376666643035227d", "TOKEN": "041520a19f8a2d6c43a20443572ef2805f0cf21887c7f076b3f503e6ffc09cb21a09b0c5301d32c8726d9f739c358ae5d7dfb3f00b8a8cb4fee84942049d148963", "U": "041ad4e457fb582e4f6cadc63ec7f11ebd4a46e0a9fc695727bbc93de98414e928068540af45c968ec0601a85eb7c0f25ed5d52385558b6052a2fba0bd1f7edbaa", "SERVER_OUTPUT": 0, "Y": "2199a789cdced7bbebb55761cfb254c1979ce5e42fbae192cb2a8eb37899a2e8", "X": "206e3b2c3d64b357970320cead5aafe304c10b8739ad3804fe050c41bfc2c7ab", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:34Z\", \"userID\": \"1d67d148abf67eb944a395fb442a8b3f@certivox.com\", \"salt\": \"a76de506b75e599fd1dbbccd0a7ffd05\"}", "test_no": 0, "UT": "0419ecac47fcd2423252a449ccf49d1b255a150dd9db44ff42ef592510f2d898f5135d587204a8ec7eb49097ada47a2b1ee3d9d004521dff2f009443c6a841a680", "MS2": "17aabd87aedf8cc74004624696c4b9474cd4d0f8003718e3ed09b61cd75c9573", "MS1": "1aa7e48ba225ddb8d714ed9e8d9a1cba19d3d095d7f2ed05e6eed04e4ada9137", "CLIENT_SECRET": "0419b4248967e478922fbb00f66b32a48dc9ce45f2bd3755eac7a03e5b7ce1a5ef06e35f21137b719f3734c193910c8285633cc564e64e84e2606696ed3ed19a2d"}, {"TimeValue": 1437055594, "SS1": "1f0a6786b8453e8bde8df371da4440068931c4bf5c9d7be2e5d09ba7c7ef534e22669c9d3500ee41c7b92c0aa938cead8e467d317e4b27c9cd874c2ed9f58653075b5c163df3b20799ef8a2791eb6d828112ff260feb0fc39dbd0b711ae41ae40f1b689524ddc805cda3b95ee56de97e9d71941fd44da0b3f8993903e56e90a4", "SS2": "1720ca642eb9d2d00fa7c83bb49173015c6ae7c0b5efd879794862da852dd5900924b2daa97a89327f64502fd5427ca1ea41b5e5f44cfb054bfad11239f50f4314ddd241a76b2e6aab9900cf25e2b32bb0bc01e22eaacc496cea8ae7b25c8b7a14359713e43ad650d3b3766af31c1c2dc147d384b8c814a0345ff2695e992d4d", "DATE": 16632, "PIN2": 1535, "PIN1": 1535, "SERVER_SECRET": "1e9be19b9e35406176962ec8bc6e3139573c535579d172e5091ebb5809f9f76f03f4255d2ad17cc3ca16f027fbb89d1166d2ee1987a01e13411955e1237771a70f5cd77a058033890c454c4070f6008c21d637e994531e49161f5b11affcd50716b8f64f0e973f3a1a1491530c33cfb293df5d515d3406badc6cd922160c323a", "SEC": "040fd26f248ead0e35d09fe1c0fdcc7200de11633457d57dd0fbc4c8ddef7c173822d043acdbd252acc52c6b2823a382e0b96c3ba8493ffab4a871b98a0e0838a2", "TP2": "0416f543e42cb00afc875922ae6780cae35b9cf044fe16538bf294785501ddb2b3090e4327d1076d233d6006d39b63a4c8e72c7316613b7d5297537ff103a3ce6f", "TP1": "0407a3c2ceedb560cdeee862a86ce2783d4a0bf4bdf21a37b1de547bddf2cd213714551f555e01a388f4c2a2df07e0f1a53c41f1c096a0c830d50e2a0e4be2c857", "CS1": "0404891dfcd821f15298c948787fc6e94df28140134e9accb92aac9a07de99dbec166aadc9dac65e70f185950e975f7240c1dfd3865d256e5b0806215e13ee95c3", "CS2": "0403bc5f0a236271731e15554d3745498a6abb08a42bf0cf9fa844da1da2788267230eb2bb290c62e5c2ce533f930cccdd1baaa67da6ea5e729bfecce1f8b6d02c", "HASH_MPIN_ID_HEX": "6d3f66cea2c2765cdfea261c240b5fc80c39a4f784d8e35d757e2c2ccea4fb98", "TIME_PERMIT": "041756a2484f5a4c5e07915312580e638b89e83daa2b562b96cbab1872e396d4cd016eb2bb4206260e1764311914b161f6b61c5c115a171b556d8cf2c3cbdd114b", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33345a222c2022757365724944223a20223030666162643461613133643966333161323063363662343665343336626165406365727469766f782e636f6d222c202273616c74223a20223362636264653031623164336334333031363766346437613930623235613561227d", "TOKEN": "0418ba15d2768f38cf0bb1cd4dae432ef784f023f36f4ade3f490d2474cd003df400d491f3e313b4dc68d8773351a38b228a4ef298a42c76c6e629f5739fe00596", "U": "041f0ba9c7aaf9555de4eebcb016e597a75b9dbdbafb9a555565fa3ccb6f8cfec311919858f4586cde88292081617320472fde1f15ae3e29f86cc8c3efb35c5ac4", "SERVER_OUTPUT": 0, "Y": "0b2a71dfa1d0672d86647e29a21d99f9d13d8d6f9f29546c495322f0f13acd81", "X": "097cbbc27ed253d20851d132e7ef3cb223ebc2d42a7d767b765d0ef1f4201cf1", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:34Z\", \"userID\": \"00fabd4aa13d9f31a20c66b46e436bae@certivox.com\", \"salt\": \"3bcbde01b1d3c430167f4d7a90b25a5a\"}", "test_no": 1, "UT": "0406835bc8f692fb8d38e830625583fdc20c910973850a21d5be88d7c34277833b1e21ddfc587ee8d48a4c22723aefa11634aea4bced306ce0a80fef945519fbba", "MS2": "0bd0f9fc9d4c748b7b6da167269a64c3e48642a55176ff791d0343b4306b5cd3", "MS1": "0c7deb224423caf8a06965f2b9246bac63b186c6ec05a028dc6d449e6629f30e", "CLIENT_SECRET": "0402cf0505c978790bf5bc58c924951fcb49a3dc318527c91a4546fc53d5292ac21901d96353861029fa8da9dbd0dbc17e614a5485cc21e3fa71e2360838ee49a7"}, {"TimeValue": 1437055594, "SS1": "11d662c00d0d3f881404d2acfae22db878562936d941a374b54ea509605895e52317a9b55f74077365cf35e4cb543199c00b96437f610544c9c7dd88be2e89ac238b5b4c798fdc4164cdc1b3299178d0859455df40136d484da12517c858f1ac127f812070e326f34837d41d6fb13209ab2604e1365abb267073e5179e43ec40", "SS2": "13eb1f135f668afcc19c6fa675472452d5567fced6da896bf01d3365dbc097f400b3294d460fe49828f1a0377d2876c203ae5515e4d0aed54040b7150f8fe8860649a6f93a270aa7eeedc28777198f920270d74eecad990af949615d60b205fd21b819915ed7fcf77a15e390c4d7d8dccaf18fef2722c1b301995793d0ca8d02", "DATE": 16632, "PIN2": 843, "PIN1": 843, "SERVER_SECRET": "15061b323c65444caca65753324d843014fdadbdf9958ddf516679febb4f973e0eb5d3608dc32d0ed47ddf5c379bc2b724f0358ab8b968521d42ef1c22fc1a520a4e071d2bcb8240d63e3dd2d34646a3934336d126df77d344ac98004eb730a7036176b16db2c0bbd915ff95498ad0a1c98657ba41dfd2744be6942056f31e77", "SEC": "0400120e0d896c0fc3df240c1d87f9ce58b725ee008145f77f0f767fb836d7e3fa1125b87151e9b389255f4a1b85f32ac0ae3c62cb037f6f39fd4dbc8048380384", "TP2": "04237695dd784b268c7a03f11ada42ae65b200630f285876a0812df0f379d9f72b0cd5b68cc0abe0c20e2cbf2359a1a743cff27c79c0c655fd7f95d2820d759558", "TP1": "0407e04b24e6be31a1885f93424401b6a84614feec9dec0fc2ca28cfa962df7eb006a602e3a47b186fbfdde53e98fdd98c785d62a04e8e88dede489bb39ecaab83", "CS1": "04234a4d815221d901b0a37962bfba9bfed0658c55dd115387b1897bbbf63bd7bd17eab98d290564db64e3aa03b542c321760cb3354521ac991f1a24794505159c", "CS2": "041474f00ab39e397b3e7741a3beaa847ef604f819c481e04aee35e629924e008d1d5fd69687cbe1753a774ad27f206dda796064b42a36dabfb4aa4fa04dd3e85a", "HASH_MPIN_ID_HEX": "9b1969fb7539865c49463006891bd589b2bfec0afd10676df6fa942ad115222c", "TIME_PERMIT": "040979b536bd351f19c6feda495cce4705ffa80df29de789c37c9168887041e58e208cb5cd538ad4a1ab6a598112f7cc758159d165742697287a0c01ea216f4312", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33345a222c2022757365724944223a20223436343637353838323234313132336565383137386238373439306639653637406365727469766f782e636f6d222c202273616c74223a20226532383537656137326433373861383061323435653165626531363162343561227d", "TOKEN": "04178da1177afd7bc7787e77749b85714d60424319395c86b96d49b2fb02a4bba60702c87904b0aa6fc678d7dd7223deebac03674ca5367d2cfdd32b554f2af0dc", "U": "0405210ebf2e6f2ed2d4ab9f513d4dd154f93a2649ecbb591dd749b64220b6ed100387b9408a9abe4e7423b440b252447cf9d92bd04cec5288e894979807822f28", "SERVER_OUTPUT": 0, "Y": "141552e7c7d7f6e8e010326b047cdc37dafb5b1a89e20e1d069153571fa7c995", "X": "0a4e225eb772d11ff7453f98fadcedb69e458c66cdce08cb14ee5588edf757c3", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:34Z\", \"userID\": \"464675882241123ee8178b87490f9e67@certivox.com\", \"salt\": \"e2857ea72d378a80a245e1ebe161b45a\"}", "test_no": 2, "UT": "0417f25cacc62825b2ab114d689ab3d5b358c107b920f9405707d7f1a30025241f1c6055dc48c435048e868787bfcb6a4df000d94baf0764e0c4c60a76192b04ad", "MS2": "16bcff53023fc06ab79929a6a6e2ebb780c046868abcff7f17610a6b00ec124d", "MS1": "1066cb3cf8ceb0e0f71e369ba741f80e731b53207b1ce2dd2d3e8a6400bb4edd", "CLIENT_SECRET": "040edb7613c00cc632523466e9582afab0fba870c22793ebc47ec8d37ecbc538da03158232ad98096b902b2ca063da3b582f0b84d06d2afe1eecc2083dc18a55ef"}, {"TimeValue": 1437055594, "SS1": "096184dad48551fc6be718d6ac6cff22b2648c8647bf3e98d57d6b9bd63125751dc9a73d7690d0bf2e7fd158e7dc950ac24c08fc9cedd3cf24a56914037ade1819d97ff25c8461b13ede554e780a15c897a841fd15c49b4fcec3bdeedeb5bb92185d89f0ec9ae915000869f7c9f6aa689bc1dc14949acbae73c73f8daeac3ede", "SS2": "0397ff8864a8a437731f3f70bd2fe73eee5446a626922522691dfe4b8881bacb1e51acdd8ddc023be9f55fd8ed84f17e2d1cbfdc40806b36665ce8819037bd3a2307a22a575c96995011597414e99f3b6c54c7f92650190be2ea70371623fc401b5867fc94fba21916877f5b1611b6ac9cb62a5a223433d58be4c7c88eb1dd74", "DATE": 16632, "PIN2": 7972, "PIN1": 7972, "SERVER_SECRET": "07ecd98bb128b1929360e10fb988bcc4835f2805cf044e4651eb31b0740c9b2522a7f9a2b1e657b94338f52a6c3ae3fa82dd81449c34a2e5711f97885a0337430a171da6d485afbec18b3e3bc9edfb06db32ff83cf53062da9aec4e437bfc04b19765945045a7f6c9328864c67420a83b56730653ae3fa3660e0a9c07fdc05cb", "SEC": "041ff80c769451bf49ebf438834f3881834095a1e6530476eaef9838546a688b4c1826f5dd251bfcf4121bc10ce15ddaf5ac131dff57d09e697afe1f63dc8f234f", "TP2": "0404dd64f2e493cb2dd84094aa0718c4ef7a246d5655352dfe6bd1911466bf35fe1775e0708bb99717b784ca159298f7d69c3c1af4c5f978e8327308fce4023af0", "TP1": "040ef12020fbbd48cf4a6d044bc4cf0b5e5df1e5afacaf4d4ab97fb0e1110ccb521d5c6c2e33712b15df50a69517dbf6531cbb8582ac2cd83cdb442bdd496616c1", "CS1": "0407ec4413c24e35ff0be16a0a555278bd57e0815f351b9d8217cfae896c4f066e18a2b4774ddf99f1cea6b16961abb2a41b306c031dd6736a08df12734ff1dd38", "CS2": "0413b3a31e3bb327d001f5fb4b9a10333cf1f3c2a0676e9f41b78329e34153d0631fb07d132ad8359ef92035ceb43594fcf7c0c5d70bf99b1271fd70c5bcc03d33", "HASH_MPIN_ID_HEX": "723060d6d62776526a40cdcb0234a8ea0b447f54ee16c1bdee7a97f85359cd43", "TIME_PERMIT": "040f7b4da94cc4af4051863a4a27b0c90e09df6d455a25038e011607b7a88a95c904d57bea35811bf625facb56ee00e720fe8d5698dba0567c7a2bfe1e89187abb", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33345a222c2022757365724944223a20223464383335663032663136356436646263643062343339306633343937343930406365727469766f782e636f6d222c202273616c74223a20223066613432636461663133353033396434623335396632383038373934656239227d", "TOKEN": "041aea90e77d809204fc186e391181bee0f87e7a62f967555e0b6c8ec9cf3dac30004f6803588943907ef5ec93c07f1828aaa01453fa364f5a8b1d19f82f08321f", "U": "041ed3f1bac02f8bb2656b014ab5d798da097cea6a6a724b8774cfda0e3f49f5441aeaed71b3eb3d968b7e8f526de58b6eafa51f023a49016c0c706ebd3f537d50", "SERVER_OUTPUT": 0, "Y": "200bd00a38aa3f27fc7a67b344089863ae33ca25d61987f57621ba409139f9b2", "X": "18216cfe7274c2f260dde0d658566844d6feaf9bfb6455607f31b0d7d7defbfc", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:34Z\", \"userID\": \"4d835f02f165d6dbcd0b4390f3497490@certivox.com\", \"salt\": \"0fa42cdaf135039d4b359f2808794eb9\"}", "test_no": 3, "UT": "0419a60643e9d6e8fac87b6b1c6dbd2a2d17b715b098c4a4e362770dc2374fa38c17bdb659f6619b5ececc1a2634da44177df04c695e20ecb11c56c8859e2f1d1d", "MS2": "0bd581f3df3e1d4165ff9abb2609e7b235a2a7b3a871e4ad3d25a1ccd987d51b", "MS1": "22879582bf9698f145408977f6537092b299dfc8a9dc416370b3e27e7051816b", "CLIENT_SECRET": "040645f40aed8439c91174c7af6607927865d72bbe6594a04b5e5edd6e0393abb91ad240f06e2742ec5bef19c2f142435ac57dca003f8646211a80fb639720756f"}, {"TimeValue": 1437055594, "SS1": "0e8146d948b9d70b5572ad07aa8f51dc5d39d85679035ad20cb80cfaaac6ab4b040cb9baac13691e406dc1c321b354bf2c1d42fbe305715e54fa0e1e672b503f14b291275f8773416ea3337ef0b8a08e2f7f688d6a249d215715d7868496990d0866967bb777a97f1f9ea4e7d4f6c1f02f440d2916f78783f6ff51ceace6eaae", "SS2": "1b7fd428ac1b04f55da8832dab02996da7f43afc2947ea7131ff1a2911039fb805267daa99479588aebfe4973c1176f00c55a9c95c4387be2744f1e3e525ef78213d5b5ae859fc6a80963628e20f150f5a775a64e90880c89928b47ecaf067450986f5e2cdb1d7256dbc67f53bef50d1d5c03410589061adebd34595aa4f65a3", "DATE": 16632, "PIN2": 2095, "PIN1": 2095, "SERVER_SECRET": "21b7b1cd48fc25ec6ff595fba12da288a05018fe6bb029b7246509f8da4b777a1e85967ebf2d094cc682dd0528db93445f18f0152a3f4a8c0179dbb46deded0f1cad8fcbd074489bacf272168b5321e4a194682da5dd454e23ed64b37d237f2704f1dfb4e183c04f8b0afa3fbe35a4c629b62539c1dd92911d7fabc30505aa6c", "SEC": "041f7e3b61ea5cd8708f8ad231319f0917c68d313955fd7848e6752334b51dd6511c3d2e23f208ea0241bb3f1817b6d5b645b45ebe6b88e9b122b68cc439bb418e", "TP2": "04006fffdaf9375cd9b278d29c9c0abf39bf0c4a0effb1972bc7721e4977afcf461eeb095e7e3ae1597f51a39543af218af70f506387eb462360379d0cd2848904", "TP1": "04110f5163c1b7702ec14cf785f76aebdfa033a679a26dd0144977724d1c74d8f709780815f04f1d684b53c349e5bd89760352bb9b99a9343976314ca127c1a50a", "CS1": "0402d4c9a2bb32e0b79af40e704d4c2308564bcdf1fcb0a413aef5384966cef45d03b94909206a7b77c8ebe9933e180960dfb0c35925da3be774a08576e8c1d672", "CS2": "040946615a7ca6415e12272626a969352c14f9b27c89ff5c676fadeab625173adf0e7f66fb774c4326b2e9f91696a4e5dabe0aa9f472dccde05b316497fe6951be", "HASH_MPIN_ID_HEX": "d18f4c069b67ef01c59ab00ea108d313357a83a6c7c24245a43203d87189bff1", "TIME_PERMIT": "042105ee8fcf28921e3064bfe42b67742a656f29038cb1e848e077df11dbbb2e671df987b6399e75bad05e28127cadcdf9c0c8731569292407afcfd3d2c17ff947", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33345a222c2022757365724944223a20226262363164616262656262346635353761353635623965383239663762613638406365727469766f782e636f6d222c202273616c74223a20226135316234333239623639633661333739346137376330316630653966643539227d", "TOKEN": "040490b0c665b0fffb5f0deb68b353d527b22553f78ed2b411347f5746b95a437d171cbc02a442ca4ad04a967439f2b68428347d3711820b1a0d6a1bfe63baf1c6", "U": "040b770249bf14a784abb093b016aada2d51fc19fc24e2ebe81b26d387c39d5b1e0a8100b1637afc48f9e652983037a85eab3d7d1521d2fb1ca704d5336ea7b6b9", "SERVER_OUTPUT": 0, "Y": "0657e0e6c275fa357de7efd9da1b0d514a70bb5f433c3202bcf0eaee9efb3800", "X": "046609f66f3a0ed3731b585178396e3223485273fc86896ca4f211010f80c3d1", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:34Z\", \"userID\": \"bb61dabbebb4f557a565b9e829f7ba68@certivox.com\", \"salt\": \"a51b4329b69c6a3794a77c01f0e9fd59\"}", "test_no": 4, "UT": "0417aa87bd03835346b19dea1ec2f36bd1cc11889aa3bc531ebe9dbc16d70c385010ae0ef8893dd44f56d2886381b5e6aec8cc378644b376b7651f74b51943fff4", "MS2": "22c87d06f40485ab525783d3bdd711ddefcd867fbb2928e73568d8740f899783", "MS1": "0dddf02737cad83ab6ffed65fd90c869e019bc554504053da39a7b22d2196a3e", "CLIENT_SECRET": "0418e5906918a219a2fc340c39badc084bcdf3a56f06bc6f4be3cc5ee3365a2fa8046c0c52a140d03723f72469624531aa1c69f24c1fbfd040648880e68c8963ec"}, {"TimeValue": 1437055594, "SS1": "10a3adc1c8741b9ad13f4b076f9e1ac3bf5e8722079cba07c6e5bdf765b4646100b30929076fe47aaa60f9068edf51a513de543f48d20e3475a93e60070ab2910077d4224213c623467e55d15ca099273efcaf25c58130762feff3e4d35876d21224b7ac1cc461d4306e680e03b5a241a71108af57b2222ed27d373a30b3a786", "SS2": "13afc176e27670ad37770822255cf4f6c11f4294d42990448a33a20f7fdd64ff048431f72e300a8d276d60db5920901fbf25ad7a219a5ad1cdcf53540b0a07a907656a8ff8081154c70e3bbc95e0ac7d9b67370555419f061a7f86b1435e29a408eb946f33070d9dd10995e475f88e39525d1c710b169485782f3a2176371dfd", "DATE": 16632, "PIN2": 8078, "PIN1": 8078, "SERVER_SECRET": "00884ad099e601ebf3ec8f215421568d220fb184c873b9f207a0b88fe82760ec11e7d2c74dac247f7ed8c96a04081c2bbc1f1bbc0270fc960cdd1c54f06064c100f4bcfa3c9ee1ef74408bf3e6f91cc81ba0642b42277518069cc65e5803c96c0265a634fdb90aa97a85aa529a0bb48768c239713c041185d795c9975bd8e557", "SEC": "041d06bafb14d9af567985b4b4f8c0962f39bbfe1af8e659880f1aa673c3617a990c9c348c7a930f23ffc58761569fa274a34eaa42ffe5f53fefcb73f0e2cfffb2", "TP2": "04202748065930898ceb38bf60b3977a79a3d4545bed8702f587909acdd35a78bc1350dc58fc5bb5293dbe8be5d4c1062f0eb167e4c3abc14416260be73a5ad19a", "TP1": "0420d58ba4214c220457ecb2d3d074be1cace5fa7ed0417855e85ccf2f7ef98cea2093565db14cab29bf3a56915ad570329215ec6bf1491b48279ed9f6ceb6959f", "CS1": "04158933bd760bcf6e34da8051c8f42a82d6e66476ffcf7aafa594140d2a145e8d14a6765f7a4826e00796513ae46ef490447cdfba63be0e979924dc1e867848a6", "CS2": "042047915e66dcf1dfe0316578848a5c594b20d836a8425b65aad53432df3b668a190d40d269d926e812da35fd78f5953c85cddf9efbb2f856c9f3c8f1750c5188", "HASH_MPIN_ID_HEX": "fb3f7665ed8cbf079670fba05eb827a2d763cd486cb56aec90419d3e6291a868", "TIME_PERMIT": "040288790fafb7a98c9459147501eb077be6733863eb70f71a28b7f102b8319ed406c6bdde46253ac1c2a8772b25c2f67391f091a8d090885039eeb895b39b6ccf", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33345a222c2022757365724944223a20226639636163656331303335346635303836653731386436303538636139616561406365727469766f782e636f6d222c202273616c74223a20223735623266666337613739393839333534343730633438386364383432386339227d", "TOKEN": "040537801d02d60a83f7722fb24e8c0d9c9d12e2c9b013bdd1d2aeb62c6d118a3e1f432ca640d1047ad6e77ecb65fce80477aa1dec572cb9712d39035cebd2ef87", "U": "0400804b917f101a53a7d022ab6196c94a0c7841e085980af4c013b8366f4ca110232c8e1b45862d111ef5bbf8356774b9353571d205b6d36afdc4cf6054db6a06", "SERVER_OUTPUT": 0, "Y": "03ee9a72b9df62462599a9cc2693201543b21a47e9d4409af2669c4ccd2293f4", "X": "0ebe18c010fd571b9c6e07e70a75b0ed65bc8493cbd50dcb43d7ed4f18b51e91", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:34Z\", \"userID\": \"f9cacec10354f5086e718d6058ca9aea@certivox.com\", \"salt\": \"75b2ffc7a79989354470c488cd8428c9\"}", "test_no": 5, "UT": "040a6ae56ecb3db3eef308351e4a4ed31c89d336938f866b8fa4d1ec06ead94e4f19f6ca08e54d35a45a3029714bf72adeb6dc533ff9b3aa0530857a2374403987", "MS2": "0bc993a892c446df37412605ce25c6da06c3c437a4d9d750633f5ad9dd09111b", "MS1": "07b43fa17f0c70a4512c6f68d4707cc074e27ce760838bbc1b8ebb21520d72b0", "CLIENT_SECRET": "040266c959c3443ed20985b29313905d9bb2f04bbb9c8becafcea36643a3a1e2f21955cdc0b0e738898935d05e4e13db7e88e05e0c59716e4d07ca429f57590333"}, {"TimeValue": 1437055594, "SS1": "0f78b32b38ba387fd26ead5e6f4c432deac4690670d1d0f075424f66129cb2ce230fbbcbc83fb5f1c1b1f68556bf56328ee9b1af888ff0514f8c3ad218d24d990dd9c23da8587b973ebf37f6b264460fd2f94b7c33b50421c7a29c1e8191767e14271a3071a0d47119722a51b25b0369ad93e1b624c275126145519101b3795f", "SS2": "02d08830dd0005f363fdaab76e8d1ee272fd3422fb07aaa82f199cb0e76638ee0abb2931638b889e78cdde8c682d6839a439451d68f5f1bf6ca0def20bfc588912d3ba0d2e11b77be1cc002ce4f1005adf8cd3f67f75d00a76669d167782b72a0d5235a3f35c4df015063074bda3dd5d3bf8de5aa48100a94d053cf9576b0ad1", "DATE": 16632, "PIN2": 4279, "PIN1": 4279, "SERVER_SECRET": "00808d5dda133e05e941a1f8d008b570d46d880899177cf31fcd94c6ecaca28321944498857f37c52582961a24440675180374c9ffd06d77fde95e43cfc5d420153314a34813bf99f7bdc14e9725cbcfc6da1c7fe41b93a79e8c281e236df6f80f9f21ba91456fee210f63c7be9f836d6f18a66960eb11fe8125ee3dce9a3f8b", "SEC": "0416b67473f9566599323edf11979b4b76bf103729c451984abf7e4c3539cb67f5166876b1e8bce28027aaec38a79381e48d65fcea0c0c05ea0f4c7bbe5bc1b992", "TP2": "040f8fb9d70f76911319a347183879839b297bd8be0eaa8e3f75e01446513880d8000aa3d2cd9d8bdd8a4eb1a830ada0fbb9bf110d0d776d492b7043f25a4912b0", "TP1": "040fd9f0b5dd776b64ce58bf3ca58fead5b40d6f6cb79ba26f744a4d640f869fd2039b32c0daa0f6ae7e7624c2959ce51e7f333365ec6f45307fa65d3d1a4b029b", "CS1": "0402dd9f72640c50b6e9cd74303b43d90e566aed4bf72cea2e5054c409b6242d0b23f1cce3a1ca0d5db47218e370c8aae17d76fa6cb87d5a844fd36494b7bee915", "CS2": "0404317543e7e1f968d5c0831ea71f9cb928b78f0cefbf6ebd3172bb42381d8a8e160cc4556c1bbf587d92f53b6569c6a4924fb50bb12cf62a468507516697b6b2", "HASH_MPIN_ID_HEX": "54bfd095e20f198fe23a2fbd5eac675fe66b70d041568ab441c8e81edb03cf19", "TIME_PERMIT": "0423394325000be64a6d3f77037021307de7740b873e232689bfb75528f036cda41d33c9b8891eb24e4f389cbe6f9838a7bd301340056508ebd6523024cdb1e07c", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33345a222c2022757365724944223a20223964326437333338363163383864373337646436623039663461316430303330406365727469766f782e636f6d222c202273616c74223a20223137313262376239313532343363386637396566323232316363666662366439227d", "TOKEN": "041dd1ac80e615447d65bbfb0c2f58743be6a8b1fb9dd77bcdedf2f4028afb0ace07f358be0aec025b94e2839f865ab93d5b08f8a668659198718edb82b43de8d9", "U": "040dd5197c3d2713e06f4ed7d3ebb4a49df0b7642b270fff77b815c8ce0d39cdee1558346f5cd01c13acbab64d9bbc5d3b02b0188d75435e6a16b3a0f55cb653c6", "SERVER_OUTPUT": 0, "Y": "09c5df8d16a98f6feada6abc8d4be435176e1020456cd3763f6e71524688259e", "X": "093f87857bf06fa6e997adb38f997a9a0e96b56e541a4bff4bf89cf806422649", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:34Z\", \"userID\": \"9d2d733861c88d737dd6b09f4a1d0030@certivox.com\", \"salt\": \"1712b7b915243c8f79ef2221ccffb6d9\"}", "test_no": 6, "UT": "040c765d42a810f20b1c201169e867c2ca96699dd8bcd992b79736d38cd0a9ef0411844e878dadc48aedc8a2bd3c8f4cbb93f94c7df2a314bcd0846a342f1a0dda", "MS2": "0729216104cbb6bb3896c59f9b8592c9ec108c8e2859f0d6f5a6ca31a23e1049", "MS1": "05bba4fad041639a12dfb112b91ff152bdd3d48f91384474e703faae774ae303", "CLIENT_SECRET": "041cc63c1bfad23602b7a060996aff8e53f93128b4efffa724c5144a1a43c6c5fa0a66969c0c7e903f0c2008882a2840478eed6a8d83208fe576d9d627e41ba22d"}, {"TimeValue": 1437055594, "SS1": "21b6f31913fc69f324654dad9f88234fc2f4115a474d931e96c998871c9989ed0118f1a767072c15625ae67ee9b9dcfaca96b15fdca09f588248ac588964262d0dbd595ccbbea6520f30945537c80b4c118084c894244d979e824c322a1cd1620f88b875cdb1aa21f453bc87baf3b9886bccfa4cfd0ca95f7da84dd7379fe057", "SS2": "22586f28d7b03e1f3a3ba68fceb1ed27b3873ca2c5b998e16906a8fd99ac95221ffc2ddf57ccfead7a2660891787f9275145f4fe8177255eab6633f01ba59d0e18b9b07f51f4d0a3479f035fc94fe86fb005d2411cd2b4669cfefd7b6c238bc7129eab2670df19cfb297d884a8569ff4b24be28578e71300542770f9acd928e4", "DATE": 16632, "PIN2": 5746, "PIN1": 5746, "SERVER_SECRET": "0e87db97f7eceb032600bc40d6d2a84c6993220624d4efc46292e65008d31edc061c3866465985f129cba519e396263f6184ac5c0da5e69d41a3905cecd830a523ecdfb47ca9175a7c6728e5ca02ffb930a0ce5323e7b0c438cfb8fb9faff40d10ad917b37db62905008ed014d1bd2e0b47c1007b0b6e87b5a6c109e01d817e9", "SEC": "040cdf22125169f73aed4f857579d183e03db05d64ea168f55b0275bc57775f2cd06b262e4309ff803bf829ffd6774d04d52ef0786f1a3c41a321cd7a70330afc2", "TP2": "0416c43c08e70511669ce599a2a538be12d3abe3582cc9bbb6621411252f4b55620cf40aac5c8a91a247f3d9c19c4cc41d27b66b4edf7f0e69f806c4cde17f9c33", "TP1": "041c7fa68c05c3e594ad2d9d0e4fe6b6e4bbada23a907945d2818d02aec635158e0b6efe2f6bf1e2424d6df92714ba9a2d4e64a8243fb0a848eb6842a527cd2ae9", "CS1": "0405c2bf4e5c9adc83a276b75f13a905c151ef6ae6c9bb3d7cc0658b7c32dfe91f23afd7edd94a83e7810bf109e1d915047edc7121f758663a89b7d4123424d96b", "CS2": "04046cf112bc3fc901b3d76e54598c007d63db4303f6c06659a2b3772a320fc035233c50c2bb0349b2e9269b8a251874c2ee8909e92c42f3229ecf06b62d3170a1", "HASH_MPIN_ID_HEX": "206f4a9004b84070917957956889423641af811a1492e62ba605048f56fa5eb0", "TIME_PERMIT": "041d957b1f177871d7e6ee918f409c5b2aa1488550c0c102e15dae1f8ccf51d36f01038485126f678541329ba586abd0e9737597eece1021796f13006b894d40fb", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33345a222c2022757365724944223a20226264373731636335613832616433393766663230316463643739616432343066406365727469766f782e636f6d222c202273616c74223a20223132373661306331353562303466383861613139393530626238643734653331227d", "TOKEN": "040613b45b65347385faa4b8b748de0758c16e62f8c0d1c0aeff1153955c4e9f091f5d5a79be1b176c316d20772b6b7bf58091f2cc2e3b8503d47fb2acf87f1280", "U": "04079822951ad9acbb6987ce9658b98f85f0a1e508bc03771fd7ad913726a2fb1600f8e000ea67f1e7fabd7c2ab65a154baa45bf267a77431d73c4d1f79f2d973d", "SERVER_OUTPUT": 0, "Y": "22083153ce467aed9bea168eb47189832661c35ebde5b1408670c212d91b1d27", "X": "0fffbfc5255dfb3edf9acb19266582574be3cd332937db79cf3d4c90bddebb25", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:34Z\", \"userID\": \"bd771cc5a82ad397ff201dcd79ad240f@certivox.com\", \"salt\": \"1276a0c155b04f88aa19950bb8d74e31\"}", "test_no": 7, "UT": "04137640386e8542a5b1b21d70b69136ee38f15615e4f2c621559a544ad144d48802c7a8dd2b9624f430d5d1b804ef4a6407bb3844f6503f73bb5147070dd64be0", "MS2": "0583c820e45d89f38f5510516e8be013c64b81b17dac596589931a0956bc28e2", "MS1": "20d705c20f94e32d379c8bd296897b2ba3d8905bb2bef4536f359d59f32d1e08", "CLIENT_SECRET": "04137540232257b4a070bfad94eeafeb04b9beee811b7762ca389aec02757e4b2921aa0cb981584c00499328e01114970d2f9da4608c5954f681090931edce3834"}, {"TimeValue": 1437055594, "SS1": "20a60f2545d0335b128292a44ec19a0685de6e8e11a7f962a90b02ac3cf54ef5161bf52be280b96a66cca3bfe5d4bd259eaafb205b5ffb8bb1947426fbab40490f679d1a5bd8279cf482f1e58f2ef1b01ef8a2f276f40b5f236b791ba517d01a0c11df7e7bfda3226500dafcfa7b5ac625be94b3a34b85c784ac7f22bde58f20", "SS2": "13ad54fecb98e01a03bcdc960316b28605c4c857b47d0ae6f9ad0e81bb6be1d901c8a16831756e2de7677cdf9a879f6afeb8df5695610dfe3528a4bd9349e53f00268b0b7e3b9582a4c424e57e60ef9e0ec883fa3b39d6791559fbd60a64876c10f32e1464ccd70bd24cf7fae68db26e883c23aa1f728f0caaf3fc5ca9a59d59", "DATE": 16632, "PIN2": 3888, "PIN1": 3888, "SERVER_SECRET": "1559df9b1b6d8f7f920aa73f7ce7f6ec7532405185e962e63ed2ae12351381ca237efccd5acd68df2276e1e09bdb9a3fc30d38d86bac755d6deed0ff61f509282366658f4113a7de19d9646d9f6552b0aeb327a20473e9f1883fd0051739c0111640ab70cf4ed9456fd09529a016f36e98442156d2f7817c185ddbb61f3d2dde", "SEC": "040a051572b5b03aaf2c9f8492c22ede2d6df6511468954aab48375666ad6864e01e4eac5b5c25adc87a8b02884201c17466f2c6046f2fea51de98873c4f0fed24", "TP2": "04202284eeb4dd52548b3c812d6355d173a243cc8e54080b2658197fd36398cfd20083e25a1edd7570833cb4acdadd9747b149ff0ff0d4b8bfa3cb6a9acc302a79", "TP1": "0411b7463d6cfabb4363f66f5b69caf4715f54c6f58da20853bc6b27ab82fbebf31c41b9ce746e4b14c51ac1c0ad4cb95960ad758bf3acf76b0274e490dd25161a", "CS1": "040d6e106c1e31e0a1e43b641b35e62fd9e31b41c513bb7a736d7eddf51613c7830f16e3cad33f63541defc7b07dda7e5a0abf7bab2548798b838e68e0f705b60f", "CS2": "041d6d7163274892d3332e4cc38bbb7bfa8044b822fa766e51b292474719f0bc0508d25f620b4b774ce10edd25527c9ff42c959d6dc3ea835bd33f15032b99f169", "HASH_MPIN_ID_HEX": "366c1db0bcee4f5cf381137eabbef20459ddb79539fe0376164598ba1e83e3a7", "TIME_PERMIT": "041a0469ad551e2134f770b4a617124a5ef45007f84d0d8be133f9736adcf1a4b120ed4638c346c940d0447c4d1cdd251dfe7237ae2bed301ab2fa1123ebed5a5d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33345a222c2022757365724944223a20226333383535623531626539366566633335363565626261373338393334373838406365727469766f782e636f6d222c202273616c74223a20223265303034653133626563613630616465353639376339363238326230626439227d", "TOKEN": "04072981d4a182e4a97810fd7c5b127b271ddb25f642e5c73464452558e495b1ed190932c9dd1629c5f1f2c812b5b3554822bc18444d427f1f490192f47a6d8940", "U": "0402cb9f9df17368decb230ad2e1814d16a3c63dadeee1f0cf4a42e41049970bc821dc8de133ec69bb223d2087bff06f0f29c6053a0e1bbd990d3afdc37002b914", "SERVER_OUTPUT": 0, "Y": "13904ec0396c16e53b85eaffb95feb346911d840356231e2e1080523c2dbdcc2", "X": "1827f87c0832033e94c11021fb9521f41bdeb11e03badc34bcfa7d3c25646d88", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:34Z\", \"userID\": \"c3855b51be96efc3565ebba738934788@certivox.com\", \"salt\": \"2e004e13beca60ade5697c96282b0bd9\"}", "test_no": 8, "UT": "0416a964393c27d2ffdc9a7321ffce937d5928e87f912cd279e621d01a351da8a31a4089da68f56e8d678b6143fbea3ab0a4e521186272e984dc7157ae020ce719", "MS2": "069f5c42f679b13e16427fea489e1c2a8c514b64e0ab645c4ee9fbb2b91d9e88", "MS1": "133a893ca750b4d3a8ea2d8f60a1f1548eb6cb427cc2ee946a1d59c10b51ddd0", "CLIENT_SECRET": "040f8ba4c0b70e5bcf122f44ff03bfa2cead2afa4c9f6861311c021d0230835a090b565ae081547189b254113688ff0ee6a192e8c10150bbc0d80724a9d3ad43ca"}, {"TimeValue": 1437055594, "SS1": "15b45fbd93ddb2bd318f7bc487f92dfb8235d52208d1c830060bec546325ebe706a873544a271cd4c9d0bea6d0ecf6f16b0467280c5ab6f2ebc5040835afb0a61ebe5200737be76a1fc9bd391f34a7306086a4a6b2dcd0397303c29d13dfe1b00c58dabbcd320151fa44de1423c830926fd7fed46423b500c998abcf659f72e8", "SS2": "1dfce70e7c09807952eaef736cc997e4c4ee19b402da0db4378d784f4c3e7a1009d4d45a703792d9cd060948506d69136211cc19d635288c8e64d41470af5c8107e9b6e418c4b6b3bd859da608d691e62b7205df978443dc41ef1d5ac6bba36202f8e0d429f84872be9c1db38b1dfe4253eca8d4af7a3202ad931ed0692a3c9f", "DATE": 16632, "PIN2": 8616, "PIN1": 8616, "SERVER_SECRET": "0bd98bad2de5a88851e2814670e0b3c8e39732f147b333eef47c5361747bc13c16e7fb89d4f8ce663fa125982cacf7aee3a52434847f4c4b3df4edd56c0358480ed5367d49011f07d9542e8aff025352f63c5c90228e461c230f4668d0fd5da41e3ea29515138667be93a9392d7b4643349c907a98d4b97bdd35fbb76e58a12f", "SEC": "0416589fbab198df5b33aa40e0ffd9bca5ef1b8f631ef0e9ef5f6e91e8183762370890d2ce12d9f8eb1a4d6f9d50e25cf0f64c76ee4e43f19f04db56badcd9aff7", "TP2": "041d478719a1858f2be62033ad8b114a3b167d2492f5fd24ec7f0583b11e84903022d14127d8fff71d4eb30e7ab38308ed61d5f680c69342d1b967e97436f18677", "TP1": "0415b0a5f32aef0e790255025bde8c50c90b54ca77a88b8de89677df98148c329101c2541fc654c40b51be9cee188352f32faeab107888416b1dd2a9ebbadafe71", "CS1": "04068220d5205b39a4274be964b0195c9f66581d4bc963b9688a7a4d4b413513ac23bbc9475767a3482f1e50e3594389f8d9a32b718acce405a9485f7f55a89b21", "CS2": "040259c9cbe5e1062653d070ddcb9446b991f70c230a8436028a28668159bf9dbc1ece0f3c5fd56e129194a7147a273ecc415767afe801b2be85cb3ebf923a1088", "HASH_MPIN_ID_HEX": "fecf76c1416f129206e9e2a3fd3bf7230788c1130756e963183521dc2ceb3936", "TIME_PERMIT": "041fcd55a07d40cea6e676d248bd4601707543a721b91ddab9767e27bf2285cad40e63fff0540f193af36f520b9a79ebddf50ba70577b79da52c312f84e5d3a423", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33345a222c2022757365724944223a20226663326237613563393333623638323238386238353531393932333231656637406365727469766f782e636f6d222c202273616c74223a20223137316632613566643065343861303832373336393531313363306566666434227d", "TOKEN": "0416189809d726522f49c6c2775d676ce214724765b96f894214301cb93256d980186884fac7a60baccff492fd0916db5994ba9e1978cd6940df9e30d3b39b0c34", "U": "040e847e2e6a0395afd733602471e1eadf6dd0ccc87fcd6645ca7053869761da29067a5208c9414435ccd16f072660d1ac8070542bb266eee880e2814d08a4857b", "SERVER_OUTPUT": 0, "Y": "210f6f0628759207ccd4afd19008636ee83cec2779107eec7eaf596a29fd51c2", "X": "191bf4d04d0304dfae4ecc5e575e559382543ab85d307854af4587629f311d51", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:34Z\", \"userID\": \"fc2b7a5c933b682288b8551992321ef7@certivox.com\", \"salt\": \"171f2a5fd0e48a08273695113c0effd4\"}", "test_no": 9, "UT": "040df60d0990ed42d0db975d57c668d119f650eceefc9fd7fefb2d62c3b0d4104c0ab892d482172d6ad5a182ebbd430710c44bbdb35bfcaf87f25e075231525fb8", "MS2": "02064a58282ae0e61eea98a840a85babdd77ff3c3b915226ce67bf1076ad03a6", "MS1": "21d5f449b6e3b14728e75da20a2bc1784a5ea9a1d7e59dbc10b91abb7e3c88ab", "CLIENT_SECRET": "041adbb6ca2f4dbcc6a96f29af42bce12a512848d77a8059ca900a988e168a16060172da2257ea7e5b66bffcae658c27a2544d49d07260fe170ce1e9e9a6f22211"}, {"TimeValue": 1437055594, "SS1": "141e3e978728a2fb41e7dab57554a13bfb3b17114aeb68ac060d0a9af0b26ac915769ab2c077e92454dac5f66e202f6ca0ec9729752019de9a335722bd97a3f520bcaf94545b998bfc864cbb415a00adb569c6df1bb4f2f9246ce4a0fbaf745a1b98be2d7681ceaf40a6e691c4b8872a358fa5f8aa1c3e0112d9817d51a7cacd", "SS2": "1741c86e32dd113eb4467b4a78d9e15e60073a2b908d4eb9fb9104b3e8c24a9b1115675a9758a8c4dca4e1ff098ac437afb0d1940089fc4bf738f993cecc0b08135861e863beb76c984604284073801782b1ac9b912aa2d1391bb7323dc752ef21ac7ab855835ef9746f0248d6d8ee4a86b81db96e9c51fa79472a70a0acfe51", "DATE": 16632, "PIN2": 2348, "PIN1": 2348, "SERVER_SECRET": "20337bec3293902531c4444e8284f42d4eb51413918908df12da1d7600575545043ea2e161cfafef6312d7f2edef02bf582c773556d0c8f3501d356245b91e4f04935622d5bd3396aa41dc24e97729b2a4f383e33e265d9ca2d9ea981e63eb641fbd297e09f8e352f191a53f9bdcb074484d1e0a5093c95c9c9787825b153f44", "SEC": "0401fe01b7e74220521184fda7afa64fed847fbe8dd1496b58cbd7aba781555a39087d6dbceffda7a20f62202debf0c74c9bf9d12fadfb4022a8d64e8b78a549a6", "TP2": "041544b09fca7a847edad1b33489c4e3cdc8fe866db6721615fea747fc9fad0fac204a528e6b2e6f24bb0d637ece931a611c276b007b3cfa674e7ea56f2d1ff9da", "TP1": "040a0988593db59971da281052f574d9556c0ee6b793b163b086979b5c142e135802873d6d75a00ac88feced64b97ef0484a6e44a53235c6b9bea9344b0843f63a", "CS1": "0400df063860e4a1b9dda5d14be9310e4483446d6775399e22e934466b5f45aede0fa360ef1bb0d05b37a709a04a796694d05212083a636f858a22280ef4cc329f", "CS2": "040ac186615a7ef8ced8cbd18836b77221ba1399099f730a88ebeb22bb0384c68f1f3c132c629563ddba438e49c7bc2e77dbfd45ed2e372bb2905d1a16ab673f34", "HASH_MPIN_ID_HEX": "3fabf8f342d8349aa7ffde40020677a89327cf8f349b1823757dbf1f08387203", "TIME_PERMIT": "0404e9fec1d87783822a1045c6e6d8097cfeabd0e8c1d207b69d896c783a7cb0390bd98be06f0fbd02f0b992d74a467391df5489c3bf5c481333c3db4b2d736d4d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33345a222c2022757365724944223a20223833323937346433326332333332623232313931653265633562336164366166406365727469766f782e636f6d222c202273616c74223a20223535663234326630353530646533346663626663636638353565353431626664227d", "TOKEN": "040a2556fa51afce0a90f79d1d854d6cdcfb52fa2c438a7ea8945d9038aecdc4fa224bc02b68200b67261de2b19db4e18e04e654718333adadf8a1e5ac62b2e4ad", "U": "041a6e6cb6c049f7a92f571403cdd0b6928c98147ed4c5490a1aec0b6e7b573f4d222a3113af8ef0bbb2e710986cd8282b3a847de08eeb993a05fc9b3897f1b88c", "SERVER_OUTPUT": 0, "Y": "00c868a8618a1f163ab63f253bd9478b45dbeb1058e4ad02997f8fd086b44787", "X": "036c55d0c2e96e8aeebbecd55a614d9b9f52874e5ac8e9f8dc70c10b1c89c318", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:34Z\", \"userID\": \"832974d32c2332b22191e2ec5b3ad6af@certivox.com\", \"salt\": \"55f242f0550de34fcbfccf855e541bfd\"}", "test_no": 10, "UT": "04224c0d3ff73ca962bfb64517f74c66870981dc30fbd85afb88428e910c8a94b71ab4357f81f2d5deb2f06c2b0ed97e349658f986f929444558a157821d9784aa", "MS2": "1ff3d2a38232e47c4c7bc1587e36944c1b19b779104a4c7985a59e96f021e41d", "MS1": "21cd3ca8c4c180f30cd2993a3ce4b3bd21d40b19321aaad9d559054699de6749", "CLIENT_SECRET": "040bcc10475f2544c12f3a60a11b893436184042ee603fa79a02f5cb71c12476e70627ea5043bbcf7402ac8018c3e9450542ce6d7247a1212d4a4ea5533ee7417c"}, {"TimeValue": 1437055594, "SS1": "1efd294fc0c35364e0e6894f044b9e30f2c4c9280f2da012caf742f1336bb72408fc273edfc93cd5a8b150513708219407ca23c7698dc69c2ad9b9b4f169c2881fc59404803590555df0b349eb9d4cc2d2af6743cb1759a4186cdc5ae39ce6631c776911d7db0bde542ec5704d5703c95401bff481081a8f1ff8b6e33b736c77", "SS2": "1664d545c4d86aba5a6a58453a324cd864ffb4465c7b78a41da63f599fb95aea1dbcd23c420c5cc782b21c26126bb9b3d8fee9eb442290854ed3afd8b6f219720daa5c9bc736bd2dc0b157837e5a4f76a34da133aac20f7478119c8d610070701c7d87210bbee7585e80357de1493f76985b191c0886d183829a14f1ee0491ea", "DATE": 16632, "PIN2": 3764, "PIN1": 3764, "SERVER_SECRET": "0b658e649a31f1b2c89d7d9176605f0b252b7ceadf7a46141b3774611f8d778e2391f1dd2cf7d0c753468b6ac07524bffc1843e5c30977ccc746ee8749c1a19720cbc776acee8912ca77ae60f30183fa006c017e6895298e5555db342328376003f5451780568a1e1db743b34f9475e49c66978c3e40aaf6813a6f2c2149f4bd", "SEC": "0418d813ea5d40e21324ee28f99365f5cec138a70fa67413fa93e800e757daf96910379e8b44ea28fce00fdc4d969976eeb8ad288d81b81a492ab66a05b736ba1b", "TP2": "041de26abb8acf859ae9a3c6326e34bad0d1ecd0d3390bd511cca14fd548e1ca9e01c84bcfd7fcaf973c75621cae682085d724af493f76bb5e40befe74c6fbc830", "TP1": "0402c3025492f8c511d2beae8b5fad7bbf5fc5bb512c072a7ab2c61e93b0c27c6f0b3b9e22deebe02cda455f925a360e92546eff933784e91e3ea5196f6df19623", "CS1": "040a35cfc292cc4e5962ba59ca42d53d32947e4c32b621b540cf7c9345a69e4fd61cf29cf801716e2121a9399895ea15b168d622d39e3974699a54628fd9bc8d45", "CS2": "0420259e066fe78067e79e5c0fc6dccfa7796b6220e5c492486dec63bed72d2a3621e35bb562249a268d7f35d45c762e5cd613fc562c976784d2072e1fcd37683c", "HASH_MPIN_ID_HEX": "289ee3fa5a94034840db16087cf301cea714b03ba397b412b6c2d238eda7c9c8", "TIME_PERMIT": "040aaf1c8b0119389eccc9d55067c55fe4c7bc7c4df846f071c36b14e996a1b76206eec4a0734115df02d897053a2748eab9b855b89b2cfd97db279ed95125240d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33345a222c2022757365724944223a20223461383734353165373132386562383931633137323235666664616161333031406365727469766f782e636f6d222c202273616c74223a20226533383063326662613635306136383836323364303136356136613639383930227d", "TOKEN": "041d85d6567e0d54eedd1e422272034058aa1d8b9564eb300f03ce562a03c97e641e9be6092ab136ace2cee1970485f4d25f2bdd03df9c7b3df4e87d57e3184dc9", "U": "0410f7e14f66e78f685c0ca94fb43a6413f186aaee4e80280d02e1edbbd5df1cd30d59ef9b76c9a79e1e75b1d6681eb973e42b3fd8a581f8117054017efac205f5", "SERVER_OUTPUT": 0, "Y": "1313bef2e23b67339555b6636bc3d49d459ef3f160960dcf236ec1bdd5fe4ecc", "X": "1b62ed7d224b20fa452a5376b61693a5eb86a25fcb364f192937fbd901215091", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:34Z\", \"userID\": \"4a87451e7128eb891c17225ffdaaa301@certivox.com\", \"salt\": \"e380c2fba650a688623d0165a6a69890\"}", "test_no": 11, "UT": "0415b479e438845a8f9783496f58c3e0bbc170f5f88aac26ee7749ca40562d752f18880b97b5d5ac266d546c99037c20d397d6855210e54b434f6cf83e6416a438", "MS2": "0eafa15a9a8e4c7abef0545ada244f2cbcfc68cb60ae175fca9506abd4e55ef4", "MS1": "17d6e568724ef2c669b1bf0955d297feb04dce2ebcad5e0e293f312b7bc5eb75", "CLIENT_SECRET": "0411a0107ac787b157e005fb89a255364bd04bbf3ced17a9814128e5d91a54b02e090ed6d82f0e7e04cd4c3f0c166db4eaecb3062f54479145988fddd992fa4fc3"}, {"TimeValue": 1437055594, "SS1": "1f084fcd34b7141975d9be543b44c3112cad21e3727cbff236e05343f1ee2fa422086b6f3d50ddd3da8f7ee496245af4e482e54db6328f84c9cb7eb781cf92151404a2f6756c0989419e503f623c6af9d9ee0a05f83d3c793dfead7643a871b50a14504a13781f12942acc491c9f4bfa8ab7545dcc4d115374bffcb24d9c3273", "SS2": "14bdde43fb67578a7e140d5fdd25ea43b0240cfdb65c6ad1c0a62221f45134b902de451be9f09cf64df6f0778bcaa45f835ed4bfcc793aa28af6b1d774cdc85a1cad226f32ebb0f93e0e7f2a46fa53ece6f10c7ed739c68e0832c3fc5159c6c500ba45c28ff2bd415cc2a985277f42cfa36d9eaffebcda4329699010a01ed345", "DATE": 16632, "PIN2": 729, "PIN1": 729, "SERVER_SECRET": "10886faeb52c1e9537f160f45c59ad13c6cbef0298b424c0bbf208e61316b06521037ca12d451db290461dcb0fc2a451b7872d332bcec4b74e99c78a47a825e717ef5d303331f03bcd840bfb47b57f7c4ba91c072910a1db102a382b804ef9951140cd6d4b47316f0c8d4b60d6372edd7768b81e73dd6adfaf1801719de8f237", "SEC": "041ab7777be5e4ff6999c68b6a529dd7ac5a83771a775dd311ea58facb40d7f652165182ca902c450f268dd3e211f6ddffb432710f713860c5f2b66f56f0a0f9fb", "TP2": "04210a8a1f478d5580722213c7a298ab465ae54e9a3a1c5367a0f9758ddd898b9c0dcf36efd81b3fece50f5ff86d7644fac4e240e82281b1554ff279958701630c", "TP1": "04111a929dc7bd39e9b03a34556892a6a07979182ed75575e5d761a7142e4fae470891df49934011688e91f3ade100070974a4ca455ee5c7a44383536d09143e59", "CS1": "040226a6456a3cbc19c97dbecb7113a43076a97af96d7ce2ebf5c305bf03d054e507d8740a9392edd53a672914fe31d44d379c6d40f7bd65632478e15ddc3ed7a9", "CS2": "0423a6f7b78cc09da0bdc47ac51a1be4c9c40eb822ef0023c71d65f2bed5ff3bc3049167a462b7ec23ca9b2e98885ef631a9419b0742358f6b96f25a0a83604a01", "HASH_MPIN_ID_HEX": "9b1289ae13d277a7903bf91c39f7354b16e520058edbd1582b398bac6a4e5895", "TIME_PERMIT": "040292e7f0988ee3c2b27556133f66609c6cec0e840fef77eb7e8e3d91365bf7a7221043eba23d239ed94bcae8db9e4dfc9e48a110b6cbfa64d4de1920b3daee16", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33345a222c2022757365724944223a20223362623731366431393537323239626261306234323139643131333332623865406365727469766f782e636f6d222c202273616c74223a20223136653432306331306632333731636462323734313663646463396162303730227d", "TOKEN": "041cc54e7d33164efe713a6635e05147067e51c3895e6ccb45afd0f3bd6b9285981bdcf87ef710f2aac842a55a442a31e9baab1796a052ff90344d204c73ef9cde", "U": "041a8e01b282c075739404db6c88c30e839e28ee4caab457f42e678ec13254510d187d4f21d90a83ef986c99694847a758b46659fceeaadf788fb0b3b0bcb10f00", "SERVER_OUTPUT": 0, "Y": "1482a173e217118752fb0a85152834112811c19efef329d22728576dfb630ac6", "X": "10dc5afa64c0f21e055838571419b9bad8c5359ad33acb5f109150e15f81a228", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:34Z\", \"userID\": \"3bb716d1957229bba0b4219d11332b8e@certivox.com\", \"salt\": \"16e420c10f2371cdb27416cddc9ab070\"}", "test_no": 12, "UT": "04160428dcb8acc3ee9723a8b964433e29366172fa1a150d4929400df7be89bb511c31a5029d176c8568b73a0dbc73526064443b38a25e9563705f48de2e90a122", "MS2": "1870a12d9a058102ac5e6bb8b25efd92ee19ecc0bdac840ac2b052b8276bb858", "MS1": "129927756c27b518bda7684658ce9b238a7ae61081d4673363cb080231964ba4", "CLIENT_SECRET": "041a5e935fd79d7941a430752208f6f39a991954e8a8f989f017b1e079e5d146fa126d8ef4f8ecad862ebcda61ad79a8eeaf3b8df671e8969f1ddc0a4a11f5e107"}, {"TimeValue": 1437055595, "SS1": "02ab58c41ba82f7de410e2111eb3ea9e8d5c58efc2fa69abb4a74e2f99966fdd02c6cf185ddea52839c94e26ed7c516a35ae7994f23376c9c4880bead9cb8f7c09f5586f7307190e586e352481bc768d58bb173607017d7ef6a7e39ebbe05134186e74132682b785ace486080d34f4054d4aba9adb64605c0e49b59d12d26d6d", "SS2": "1a7bd72c0c88f97e6764caef54b615a869b81733dfcb7b61b261adb81cd88ce70a331d31721e1fef4c4ee87e24ba80a766d2d40abcf406e6599968d6d28039e11f5191b7307b749ac798ab130ce0e43db6943f3d986fb8ed82f22e52a05d1bb6013dea562ce83ccdec2f7af94f6336dcb28168f49247ed44ba4f45459d0d3b33", "DATE": 16632, "PIN2": 9410, "PIN1": 9410, "SERVER_SECRET": "047ca35946ee57111516f82d51605a1931146b4f351dc86e48f126c90e82a536048efca74438f46efe4659b8f5499abcf9a9918be660fee5587747005327a6ed01b0574b1e4e8698e14cced4657432e05b355117ead11a10fee742312b9fddb91e0c1a64d6da74afe6e4bc12cc47c81fc1d7ef2a01e184e6a172de2da23cc0b0", "SEC": "040e83641ef69e04b1c6ebd461633f5630d5f4918b4d98c82a067d71eb13d957de11cf1a1d917635af967bf7e1aa55881d15625fee69c33328777a9b0741a8c75d", "TP2": "0419f91052f79129cbcc0d8477e06a9f9e2ebaef5338b4c8205b621ed6ca680204217a180a1d223c12260a2ae46cafa6c2873015edf3406d4b5a17a46c4b3373b3", "TP1": "041feb1fede0801e06d694fb6f3957d805c77633ed34f3acd201bddb1c1ff66e8c1ab41301b261cb21245571f9fa1bd458cb507809cf117f212727ced872a8817a", "CS1": "0419545b0377a3a2e3c7a4075bb80330a1abb7b9b27f2f42e1bdae83a46e4fab84008b1dd9832ef635bb92d14d5a779271b18b2b361242d327fc299ea9dd0147ec", "CS2": "041670aca835aa6caca1490566522db9cb088868b19258207950580a33db96010a198d431324f7a52fc21944ef07d473d8fb9a076e319f6f1dc69c04ed35338bba", "HASH_MPIN_ID_HEX": "520253ee9b443098b498723b7cdce97f59a5b4e408193141790af7ae1094a502", "TIME_PERMIT": "04104c3b58d81b87d8ce6b426652626260b3673186ee7f1095cbe68070f7a0443600c748f473e203c0ad9127eab8024d270b646c6946cd985851ca9f6de567f062", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226266343065363033316266363836643562363665383965653465366263633933406365727469766f782e636f6d222c202273616c74223a20226532633533393430303561633863393562323038333334623030663530373836227d", "TOKEN": "041df9ce7195053809b2485775a9f9974ba1366ac4279210f901fffc3515bc5c801652c09676c5037bc08287c5aa5acae3426c73ff9a0fedfffec6624d64abaa5a", "U": "041c21a2c64dc170457cc25be48de8da0dc0afecd99745ec31f237d2d054e6da141e751690638405e6417a279e5b1452cb8040ec4d23593c6e34df54fc1abf1607", "SERVER_OUTPUT": 0, "Y": "1269ee0eef8c8273bbf338dc9be3ee3ab36e8111114c3500e2c107cefb736098", "X": "0151ef94138b5b19bd059b8cf1387ddf7d39a36a74b9b5dc9197eb984876dd04", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"bf40e6031bf686d5b66e89ee4e6bcc93@certivox.com\", \"salt\": \"e2c5394005ac8c95b208334b00f50786\"}", "test_no": 13, "UT": "040042d2b3678fe8bc99e0a19595f5d8b9b4f281e1be9ebfb11969d52d6a5707e81b9038a3c7b1bcad237a984bf2ba12583b059e1aafcd9268a91e46dc3a044ec9", "MS2": "0b396333cd482362b87006aee74762c5ee19971c1f07a2b60ae82390460a68c2", "MS1": "0d076f355ba119bc1b4ec43017ffe0c74dbc56cff41f838b80133dda04070b7e", "CLIENT_SECRET": "0412f4f95ba5441fb0a1e35093b75400bf61ec79bffdb6c34859f98ff43cd6e7801ee6e150e1546b12f4d68300cc8a59b9616c9b0390a6953911a270e1e3779250"}, {"TimeValue": 1437055595, "SS1": "1121461da0b381032d470ec98dc7058e40fd79ac326b001ef311f8e21383c65b13edee07a54b9b8b08ade1522486da58472d9f7f52d3469861de13c2feac3a8604d25c34e7a55536aab04fe961380fa5adaae77288ecec868a8e5adceb075fc60a5eb54a8af7318f66f59c6d5ed88914316213c8c539d197100451a31e043b26", "SS2": "1ee0191720fe5aa927ff15ebaf7ff0af186a265e7a7c19dc545b5f07dc5c7e1117af6959d16c667eec58910e3c91728058b79199002094a56d2bf0996749c04a14426d80134ddb41a2fb9007ad71263658fe19546f84526471779db5d6673e5b0d9126fe406efa3d69921685279f5f2aa0a369cb3477baa226f89f02c48074ef", "DATE": 16632, "PIN2": 4411, "PIN1": 4411, "SERVER_SECRET": "1bd93920323951c7719eba225527dc8cdcbd1127f2ebb16dd7bc0821f37dce371fbec3e9c47a65fdfbfa2e54cf8f53477b213af8e3cb9ad1f3d9c88a614bff42049f75799d64819e686cb971b76810f2d9e8aa8fa660a469fceb6daa33362a31126098b74967f92cc3c4052874b250a15881b0201a62eb0368bd3210c3cc70d5", "SEC": "04011b191e65c4a6c88a3c3d1dda3fd6bcf66ec47d348eb62e65a15fc391e14c0a18e5ec4efa692d85651c36c706fc31d738a112af0c1ba1b6e127b2250b86bf6c", "TP2": "040b5a7d2d8c4943db9b00f83730728b59c0eb2834fe6855acc9d026123adc93441ad84ae4127de8be49b71e00a06bc9f6e864cfcbff96b753863122d83ec52fdc", "TP1": "041a7ae7b493bbc82821c7e4716c194fef2d4035948bec707a465856e0b977b84d1d56d971b6100aa89bd8d0ae1a34537c173973281dbb5929690844a69283e88a", "CS1": "041a8424ebac47a3121e0130eb4db0db13c32de89a565ed16d6719b8cbe9725fbf1c81164d474cbde1e4130553694d5201c20b2ff347d46b6897122165bf428a42", "CS2": "041b2545e8f58cf20edce4347ebf914e5a730faafd78dcf65f8372b78af2ce38920587f9f22c6312bacd61657febf445d814666637a8f2d4abe02ab275508f0da3", "HASH_MPIN_ID_HEX": "16b140879f84bd5a1b8e08a2bcb67d15bc3d4710542244216d4b4dfdbbf5641b", "TIME_PERMIT": "0419f269e2bb7308fdab5a907bc5663ea2d3a00947d57c0c427e3691d97c644fd51559410bc6db6a23ab23aefd3b798c354992e10e4a16eee6ed80313b846581e0", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226461336163663561383662343438643934396165356530373261653565663365406365727469766f782e636f6d222c202273616c74223a20223634306139643435396662383339343662613032313464653430353937336632227d", "TOKEN": "0421d94f37813be32b3995135ade93f649b848edbf68ef064983c6ae6fda44bec71a358324a42be450d154946a8611f06b1870ce4aac15dea8015f9e2f2caa33f0", "U": "0420356c11c152057a16e963d3189bdcdd5814083a5165f65cf20670e2d81207bb1780cfa420f76c06cc1df963d388378d3a9350045b6888bc63d6986d287abd7f", "SERVER_OUTPUT": 0, "Y": "0eeb54be0a5265efd58dec5732f146f92209720e550fbcac0af0fdac50cdd609", "X": "1da8fdbba6e83c6d9f1a89f1fc7c0871b62d965c549c039287f816db9c958101", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"da3acf5a86b448d949ae5e072ae5ef3e@certivox.com\", \"salt\": \"640a9d459fb83946ba0214de405973f2\"}", "test_no": 14, "UT": "040ec352a6b673469d009d015247330d1c9110709095496f971af960fda520683f0d1b4692f9cdce4388190ed5d1f73ed4961986d3a4f9420f3ec904e6fcbebb19", "MS2": "029d7b3191bb5c3501fce6f3fac6e3f9802c799af86d6361ec687cfd5e4f956c", "MS1": "1f0cb6091f001cd40a00c9cf019ea238251685a49d363895fb2223077f617408", "CLIENT_SECRET": "04176eeeae545878791848f41b8764ed54def2fabff17d23a78091100aba053ab018bc977276adb19a1aaa1ae455d42290f926ec7fdc48319bfc45091da3d5b4a9"}, {"TimeValue": 1437055595, "SS1": "005ef11ade21d61ac0eadde02972e2de6d421275a37bfa48df685a74a2fdc70516a6cfae5e86bce0cad7ae18d9239e5b0e3e422872d915f2d251a4173e503a6b0d3156a84d8ddd03f0407d6a486408a7783875fb592d27845b39468b92ef2ccb10f80ab45210d73e0d28b5a310aba2be51543455f4340e89df721b41a56257aa", "SS2": "15302e6012a81ecc8d10bfee41cfbddb5d5caab43570f841833a4df2820fc9792285ff10aac04418dad2110659e439bfb067dc938a09c7cbd6f01bdc0858f73101f0220a23e9837a56f1140cc2335ebda85f51c92434e045bb21556d28acd3f11a32257c8b38bd7b45f1e4fc5b52c48d37676153ed5acf531c28d4699ae11e7c", "DATE": 16632, "PIN2": 1194, "PIN1": 1194, "SERVER_SECRET": "0c1f0a1d84f7ef2050822d0b7267c40ef224c181a1e153323f42c283068e01f105b6b997a6297b509331e09d539be6501da16e9398613790deb4c0bc59ff874622f7e037e9ce8b3c6d1156a7ef89e277dc203a9714f7126a1da793294daffde314baf0cca6df4e69077ef7854d84ee0662dc36ee1c83aad10aba863c0eacabac", "SEC": "0414c3964f2dc9baed7a0fe822da337837fccd71f047a787b4ebf43a1d6c87f67c180a760c788651362369cc05f8ca71e917bfc3083f22670b693f8c15c92a1962", "TP2": "040d5e5a4d5769e5d43c713dd4c1d13c72dd45c841c7bee5b447bd940012f467be01e2a81e6f300d40d5b19091cdef005dc5ea1004a6e80ad366450788503a2b3d", "TP1": "040929c8a9de6b460411a9bdee1fbb1f58770b5505da8742a5e409c262dc7187511d0a85389f9fc6507e1bf128bc84e16224068b17874c890de0c68beda4f55698", "CS1": "040ad6af61f568b0adb40ae1b77de62aaf28fba96d1f99d4da6502574f1e6a589e0b59234b7b67aaff5f74b3b1fd5b4b04ea19ef6068d416abf7896facd3289d98", "CS2": "04203ecff5912724a49ead970bafa49ee5f974905b1589e56ff10c035ddcc4342f12f063cef3ba0a21caffb27ca514d5cb4e6dde44a956635cf17003736eacddea", "HASH_MPIN_ID_HEX": "a4db348d6a3e12686220b7e892dc7a8c2d03369cdafb27c78211846384d74d39", "TIME_PERMIT": "040c000dfab56e9266f8ee90716e966ff5f478bea270afe2968fa3936a0f34f1a820fac6f963b6f7c65b318db7bc1cb883123ab0846f66497a54890b0a2eaddb2f", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226337313336353930643937363864313637353364363864326333343331303634406365727469766f782e636f6d222c202273616c74223a20223335366235316130323839336462353538303430363038363964363731623966227d", "TOKEN": "040929fe71e7d7a3814d3aeba40f9a786c33fbe3b2bccf86b9e83b8638bf16a69222ddd3cf5583476e502ec761311af5acc98e6eb3b4e15fd497ed43ec0df5a5a4", "U": "041f231e85cd33ead8f6f972939966b5b3f8c8a94ff8f573b56b9cce2d53ffd84c0fe624780c96d8454031dcf34bd3d994dbfda83f5aab2f5cce208af47c0123ee", "SERVER_OUTPUT": 0, "Y": "0cd7c161c49b6a196d77a23750d04cd63bd97ffcf4023915a1ac4ce354bd82a5", "X": "00422b928dd2e96614005ba84fc78741c706b2cdf1e6867e712d73d01aa17a21", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"c7136590d9768d16753d68d2c3431064@certivox.com\", \"salt\": \"356b51a02893db55804060869d671b9f\"}", "test_no": 15, "UT": "040c0cf30dcb53d590b1e4cf3a137b8890614ac6d4a13905feeacd41f3882137d120002dd8d2f6337bd910b999e7a199fc21ee49959bf7f775b209c7fdaee1e7b7", "MS2": "021ecb6fd22558fcae0387b205f80d7a029dffc18a0611c434ee2caa0cf90c04", "MS1": "0516497d2e0d85158c64bef07aab7363e919e9e4fd653633600a3018e004a347", "CLIENT_SECRET": "040035cdc25404fed0e2b5be105bcbc7226005dd176a48674d73fde18647649d161823310c66710662de295ff851c52ba63a75020fbe9b81c0b8fb2873c3ac533c"}, {"TimeValue": 1437055595, "SS1": "23dad6d7b3ed7e4cef930e8b3d011dfc6f1dd639bc1fae7fb2cad6827ea6b673170bbf3d94545632da5cc5aad16cb90daae8b710d07cc152f90243bae0fcb17b126c0780f165329d81558c67a99ba5b3c57374959fc5d068d791137a56a61ac41e7179156e2b819b89a9fb5b19c602ef114ae70304535eb05695fbb68bbf47b3", "SS2": "2151d6676be391aad04b74ad9169b1467a5891d93355393b007f3c1b8a3470da145803c0a48cd272ccc65c94e3efbc4a1e23e2d01e868cb9cd8afd4217426de4097ba55e12e54064a971140ca658aca66a09d015600b4d8781a732898b25f582003d71fd218cb4e1f28c61302da41adab06859df6b1d687f760b59e70b9c006f", "DATE": 16632, "PIN2": 3666, "PIN1": 3666, "SERVER_SECRET": "2354cc84b0be0d086235dd5106676f8693e3caf2571b96fff02737c0d7810c7f03db95e7716ff35c4eaf7f09ec2b56b20762605e77a1a86ec7495230cd5b6127114eed4e469f14b30c8d33987700b69212752777dc6d78ef33d40d6aeb275ce51b2b23061ea3d777149b1ec98623e20fcc732b107eba9324c7e7f394d5c33167", "SEC": "04087fd4db3bee68c16fa739fc8d1a483223d8566a188a6ed4e055aff46e78c957171cf4cd69dde39d94ee5a283a5ceb3ea0ad49e90a3ac02b51d6b2c4400cb0f0", "TP2": "040826228e1929139fea73f8637de9c15c609c38c6d9d658d3b12ce06a641995ca10772604069ec77a9bf62317b290fcdfbbdc098302eb12e074f6d273df7854fc", "TP1": "041ae5cb5b45dee4b542b8087191a774a42020f77e62bb409002f2c394137757e8171089a8215c86cef9950f85162848fed0ee06d6b91d537e94bd5b496f2764a1", "CS1": "040a40647d79427687f087efabde69566fe951a867144e282683bb8d42db4652c71371fda7796029e60c69181c9ee9fa209f2fbfef3d6749dff19bce53a9757a2e", "CS2": "0413665be94ad63b94a0deec4c4e90f320eed14ca79f65b134d30279617a3e537f1381fa0905472080863b7669b23b28dcdadc68cd56a8f135331dc80588859f83", "HASH_MPIN_ID_HEX": "9fb97d070dbcf9f02f43ce6c92819472f161cda42a3e573e92ae3139e64a866c", "TIME_PERMIT": "04113d67256d744acfe5dc848a6744dbcaf37c3a3cf403dad667a7f259e4b642e216c8683a8966965ccb76c89b3132bb225afb426fcf0a328b06f244f386cf52c9", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223863643361316134373638376662306636376561396532636431626666363262406365727469766f782e636f6d222c202273616c74223a20223539663466343065376632363031386266313661653434313661326336373862227d", "TOKEN": "0414d94c5363566bb7d58b1c262aa2eebd31b4c8c6a4708423b38f706d28df9159033b999178fcf7b6d010e906c9f24d36214e4c9f9bbae206efbffe8db39356d6", "U": "040ae2c3e19032733458d87778a894fee58bd17584b6c3c3016fe16a8e8fc8075c120becf699a5c842e590c2d416f76814ff620dc76b4bac78df1ea0350ef2c75f", "SERVER_OUTPUT": 0, "Y": "0f36cbf567ea62ef0fb17428388ba8c32e4c736f1435d725a63ad0e1bbcce48f", "X": "0fed17091ee2633e8ce34f753851becb2fb567050dc87140077136ae15caa1af", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"8cd3a1a47687fb0f67ea9e2cd1bff62b@certivox.com\", \"salt\": \"59f4f40e7f26018bf16ae4416a2c678b\"}", "test_no": 16, "UT": "040431d184823b62bd1d96124a67bc6767f763b664b23f279aa2a265e550130c951e00cd459fd3ff49fc77558962439ce0e6f1ddf340a87ccd0e2db6969b2d0cb5", "MS2": "19ce6cbc23b50bc0cf5300dda69b43008224194e1c75739a48017adc4784430d", "MS1": "1851b82bc5867efd663f4cb84f4d3122ccbcc4dcba715c34e44fdf6e6feac37b", "CLIENT_SECRET": "0400490fdcf249375e425bfa5a45016d25a3990b53a4b0beaccf7fe98d5874049322072b915fcf94c7ad8580c451ee2fade519424abeec83f123ab7092ca9e3d83"}, {"TimeValue": 1437055595, "SS1": "1465c8cfdbc267dba7c633b0bfe7bdf5abcb5f1c27590aac10f65105b9eddad21cf5e9a6d02fe5f13d03f00052f4d0b69401412d5653fdbe979fad22fb7a0f14047401bfbeae0501610dbe5ff148cdfa48dfd4f4888ae716353deeb7a5c5b4210bb2b0d0180f9006b8797b352dd721501fa28d81da2b672ffb7adb6b3cdca472", "SS2": "0040dae30b7302d80a3099a898ca47185dd8e189ef2a66b981e9602ee3acd7ed23eceea8b87da9ddb371743a127b21ded6da06ba8259f8673d29e283063d4dcd154f980bd5894bdef38d126097601e19297597707a87079d2389c34b11a2564b189152c688e555fa01500cd3a54d21540409d724556ea6a392d587873bd5256a", "DATE": 16632, "PIN2": 4703, "PIN1": 4703, "SERVER_SECRET": "184e0d80931ac074dd0497385f0eda5499ec7eb4467c1a71356fb5f70d5c8d0b0d8f5a6cd5ad6a4164f26a9041287eb62814ef254a12fac0928b907d4fb4720b025cd8f9b14ea04e3fd11345cc963d6c7a3e7437703e1171f7f6f908bd1c804f1e0ec758abb14f966a58865b4dc563477323c73060487c103ed93a044b0c54a0", "SEC": "0411d04d217ec0ab6aeed1385935e71a33aeeba74817e00d5886ba1226b5e3a851218272c144a2c160b90c4a2906c96d5724aacb017dd6b2c560589c1d951d2912", "TP2": "040dd9b30beec49d625d62910e5c56bd94e848a9922e21b77666ae17ffd471193e2090e2301febda70d27f40ffbebde9fe4776172b732218a4a40688ca6b5779e3", "TP1": "04152c631db2412096d8c363435b220a3f25fe5a2d24ec6c4baecc5555166b17c721de54b4513ed3f27c8dbe25f70e3c30cefe3391212d4f823f8cd0ca3ad23a33", "CS1": "040122e925d5f065abef086c1b63d7efb0cfcf43810c1dc926889b9d9be33d1bde23be99d18dc6d15e2a68f48a485a94173c6fc098bfab74b85af1024fa2792f86", "CS2": "040f023aad490c8b55be81353c58910e8ffc2e4b7f91231ecbd385456e0904fcb80ee1a1ce9b7c8e7064b1e0fc4510853bbd051f4b3638b9d4edef03b0718cd141", "HASH_MPIN_ID_HEX": "4b428e699fc9a420725a076d5413fcb71a747a4a2fbfd1cb7ebc90c08cfb6755", "TIME_PERMIT": "040882e822769978bfe5bf18e2ffc130664a2b4bf6920a2c9f2641db53e431063f1ff5fc746b87ca432aaa855ab24da576b611e6c83dcd7538e1851be64230567f", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223237363735643564333062303335633633373537616537616266306462626433406365727469766f782e636f6d222c202273616c74223a20223836646432333935613364303164303333366530633662323235653063616637227d", "TOKEN": "0419a378f241f8c1210f3619827406bfc4fcdd16832ce90d7997c00870bca47e8018fe17f16deb3d4d18c8a1dd5af16c40c327e235a5230dd0c188d13357613f14", "U": "0408301fe2746039f6d1b933cf136b54b33941642e6ae2ff933030b6b36805557d048b14057093ec9f841ff4ab130c13722849ddc7a23b1546489f2dc69f8442ae", "SERVER_OUTPUT": 0, "Y": "1c1f2cba76c40c464c385fdbc7df270f3dcce1387296ef592d8453ff1aa1c001", "X": "01273f0dee51cf0a7ab547d53f44f85bffb7fa33583a3a9428bfdb4e2d384777", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"27675d5d30b035c63757ae7abf0dbbd3@certivox.com\", \"salt\": \"86dd2395a3d01d0336e0c6b225e0caf7\"}", "test_no": 17, "UT": "040cc1452068bb696b9999f6be7e1b5e75f9cd94c98588fe5ec55e433039bdcb430ddcce810b8ea86ccd5db61e8b643a8b563f07c3a271de038a2d468f55954303", "MS2": "07e8493d8b0d000003928116bb37650b00cdc5b194152cb4c636526b47ed06a9", "MS1": "1a0adf7baebbe316e94ac64c5c86ac431d2f0b708f4f4ea856436fc6bde88975", "CLIENT_SECRET": "041125501e61ef5498d79f475b50318d0d6ffbd76bcb895bc8317631994b272c531dfbcbab019ff73c92fdf7cbade07f8f6e725a46ca27bbf0e00673b62bbaa468"}, {"TimeValue": 1437055595, "SS1": "0818708b4057a6b7b1246bc5c1ae71a84fa402961729edb72e69f3b366ab80e71e984e78ecd3c4dca114a4208a84a1b79e16c088cdadff0c8f60f2543301f1541ce918024251242f3761a3968592c7fd8b4190b91528ca7b278b35dd50bb64da062a96f1e1771cfd8d5f71790912aa39bbac50c229fa8d3948c3313babc98952", "SS2": "1c073c3a5aca34f59f43e1ee8639f402d08d5f31035b71bbc7fad1773c7c69cd0a4c60d1defc6c198da083ad9d6fb18ba9295019bf8999ebb49f4affc378393f0d9c595156090e85fcfba773878145c6d8c6c967375e27c0debc51255a7952581389f9014044f65a22fc8aaeb63696d69e4537e6d94dccbecdf41f677bc0f13e", "DATE": 16632, "PIN2": 5558, "PIN1": 5558, "SERVER_SECRET": "1b23361dc753294af3136729a5302ad7dacad4f4129c1f041870a6f93925273813aa2857b4eda7d70e2fa1e7b1baf87062de7ab8fde1b574c17255b0620ff9d922d2f48a7d49c7673413f36807ff5a78d614e7984f64e48788b54f5f4b69ce17219919647618e4984b22df832d7b29b62885761bc124a85e84621ed87fc3c5fb", "SEC": "041e17b37d06f123edf6931647cb891bc8fff89e3eea460e93f30c58fc84c39206148fc5cd39c2c404d90587bcffcae52c20d777756f5905d734e1387f555e9b19", "TP2": "040dcc09d755461b46cb2dec388815a694d8867a81ff1cfe7d8702d992f297b6bc1ad9b7a86c9f06455a514dc935bcc2d21fb9dac96678aacdbe0533904338afb5", "TP1": "04179065480dac54e4908018f9571d4751e5a41de122780c5fa0051e835d9f05a80969cbd01b13028fa129fb03cd318eb3c9cd0915d733163979108c876dadb401", "CS1": "041d4c7ec996ae43e13d276049a83a9c6ce9405198f8ae511586959533aef478cf1dd08605eca276acf4a94ca9bd66798c659f8ec6a477fc481bc90c2c348a17db", "CS2": "040eb81dd0505b75dd41900d9136515299b416947cd764c7bfa7ac19d109e7f9f9033154e1e5fd127a90139f920d0b9dbd3bbdec675e2b9c6c4faad48eafef519e", "HASH_MPIN_ID_HEX": "92e52fd7a598d3329558b15715cccf3fda6e24ba972197d26b06a67b7ce52091", "TIME_PERMIT": "0419865184919eba5b30638e28b6aec29aa531d52f436e8d4a3bdb14f2b2f1c6b8054f3a5d6dff6ab30f98cb9b37d826d226865a42bc40b539c6c576aa8b1d6035", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223462303438653962326565373530383233653633613931356631623436393566406365727469766f782e636f6d222c202273616c74223a20226564343532363861663161623062336139366531396534333632666365356561227d", "TOKEN": "0418484d420d5cf643aad539e9f52b7378ab8f4cdf8ef7bbe9d6ac9a6e8574201a192d203c66fc76e552d578aa5e5d8da6ab6017586927e43e70ef877766cd17fd", "U": "04214201e8f8cc2604db187df04bd48a50a2cc7a5aac0d6e098e9d44efbb315dcb205a66734278e4b357610f5736b38b82ec02a9fd4f0cbd9152cc2bbc17cbaea1", "SERVER_OUTPUT": 0, "Y": "0d2cc930460731529f003ff6b99a656193ff42acd219bcd9bcd197b35402a685", "X": "1e9c5a4c9440cdc3f5576c0b3569d84badf663ab1e1b9b8ab0999d1689faac3f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"4b048e9b2ee750823e63a915f1b4695f@certivox.com\", \"salt\": \"ed45268af1ab0b3a96e19e4362fce5ea\"}", "test_no": 18, "UT": "04123fb3fddeaffe5dfb2478cc0f1a2013c97e1c41c80a5daf876db9c924ffce1f00fb996f0f656502a28ed0888c5d68dd7afdcb25e43bb2ecee079f923141e9f9", "MS2": "217c13d95a6f57116c25bdd53ce905935b3e72f9e4f87e32b83714197c5a83f3", "MS1": "0809b9fe12a5f12dd625571b799e28dedb3876365258642711fb1c4773fb8418", "CLIENT_SECRET": "041da982bf4b92c79e12320974547dca93d32c32f1f2407936b3a4304f0fe9ad1e051f463ee406d90b2177a7be888418a70e9117ec704b2a356b48c4ccd02c1f60"}, {"TimeValue": 1437055595, "SS1": "2124d878bc05ae18bfd1c1b8fdf06f77189f98e3b2658452e9e29b8e144fc23502c5abb9977897f45480f487801f9a61b0372e42a2100762033a42d132c06c3309ce8f44d18486ed0f2cf36befe624b04cacf33036b001a62409682335a22cdf01312a4ce2a99072745acf80e6f9aa7897ef9e5d41d1f865c5ed5b045877209a", "SS2": "0144c1e5e23be6996ab5291bc5f5ab178d62459ad52fafcdbfa35b38641289d207af3ce235ec7b08f0dc36ddda2edc15fae60b1b4d9d8053242e4d0b839ce43723084451d891609033f5299cfb483a04beeeece181f862e6102fe42434263c5c1fed38dd6b6970c1e4b56e00c43ceb888768fa42dd63cd025480a9f8d4cbd581", "DATE": 16632, "PIN2": 8962, "PIN1": 8962, "SERVER_SECRET": "19e19ac0e2938b6d0789ea420bc80e440ddf6fa22bd494b8ad8c7760f4bed59f05f6819435e9be192adb5c540742c759137301da7ad2177dea93812ca592ae92121551dcdbc0841c9feedc712f78a7a6c96a2becb56b1e8a57bf24d18329aaa907c15539afb7e1f2b8e55ef4fb4608abf73404b2ceb5659b7cd14c83c264aa32", "SEC": "040697a45302c86abb805705faf9109c4ddfe09b0b8dcbd436c89f4b8741a6ba5215f2b5241045eb5fa5880dd4ef3e1b362eb28151e3ee0a1487590495662c1fd5", "TP2": "04195adc282df8e526e5fbc4c4266bb5f06647a59b8ac22c73c7fcae803abb9b9a0db18aa85edea9aa2fe25a7f1017c56fc34602ad6c38bdd9bb77fbae900486e6", "TP1": "04235bf05a09110757c3fdd994278e79bd49a22eeb581cf0856791442bdbaef2831e557b922c7f9a523c7305c797462864579f9a58b9c53fec4bd7cecc3cbfe0fc", "CS1": "041f743ccf91d3f774ecd3ba6014c4d686b860527e1ef0b415f4c69b9bf6031c1e0d9c797c091d3a950c64de89360556126b566466db4ac4a0cb87f2215b9eb465", "CS2": "04092d710891fae6905433a27d29f02c0d1512c34de55f67e2ba02cfc4c8cf71510a9070e17cfce6072a5455fea5b28b606a6f2b0517c3e41dcfa048994eef2d0a", "HASH_MPIN_ID_HEX": "2394aa62d7640ad3c8939742810e9edaa3d21be2262f41fc7eb92685a5a61c10", "TIME_PERMIT": "041db9b7dbca2b8dbb93b077b3f89799b82a07f4f4c090036f56f8fe2cea8d794e1369e5cae38ba6e122b478481037c6c576297e35f774ebbfa93da93f334ea568", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226633646432323764623830383462313965343563393539376538336366613161406365727469766f782e636f6d222c202273616c74223a20226664396633653435663064313638303934343063336661623232633532303166227d", "TOKEN": "0402eac396bdec8929485fd8b3982918e570e9dc99c21c195a105d8a77108497402098ec4824072f1c1b76e145bad6526b5d3099d9b85014193fbff9d9eafe3bc7", "U": "041d68b082675971f81a7b9e07a3e655d9468f68c9c81510072d5bce6d554bc11a1a52cfea598602ef1636e21bf4ec3dd706963fcffc067c1e1efffbe131439dac", "SERVER_OUTPUT": 0, "Y": "1d77eef22ca0c10bcf2c494263578727f331e761cf22022327b853c03ef0ae0b", "X": "069aea8e8552b85654fa45c5d861fad0d4ccfeca5fe882225c195f8ad95f6e21", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"f3dd227db8084b19e45c9597e83cfa1a@certivox.com\", \"salt\": \"fd9f3e45f0d16809440c3fab22c5201f\"}", "test_no": 19, "UT": "04166953130501ee5dfa056241ead9e5604bf8c21a3b6cf2be6120107cda23d1191d3acd2092e601fac897faaae777119fc7b6a04710410102d17bdeeba54eece6", "MS2": "1a96dcff0e5b2aed8a034cd367e1e62cb3f86072daa1eb114c027419ea2aa9f1", "MS1": "119fbde8dd4f5125ffae67b4e3fa8c7925d38522a53e74583ddddf1475cf11c9", "CLIENT_SECRET": "0410b3cc689ba1310aa8fbcdc5535d5c9b24407f9c88ef4a86c157350a21fd80d0018191b9d651fa1c16d423daf96a673db93dbae11c8c6dabdd767ad3324a9822"}, {"TimeValue": 1437055595, "SS1": "167e7c65c25f80a1dbb94dea64e396b34cfa47edeb3476d1f95eef3d050552bc087ce425beee13cd4d388252f3c6c93d4d193c8be52010f6c7c4246682f3e0221cf00340798caa4b01ed402cab0073efd315245c10eca7ef30e833918dcb129707b402ebd0505ee754413f68ea4678475c3705ec3741077216f92f2d4003b5ea", "SS2": "196cc5d90cfee46d847d857ce81d46eacf09cf2d3cab6e39ff94f53be5a1853b198895bc2ee6e0c9f36b21491b64c55e469ea9501f72ffa5fb005d17807230bc0eecf00cc46aee4f0f58edd135c0754da36b8f8a13d6bd64393b2284f73f1c5e018b3be32d1f42d609767c456085be0f9bbd76072b4642f85529e7eac7069d93", "DATE": 16632, "PIN2": 8915, "PIN1": 8915, "SERVER_SECRET": "179c28b95ab04a03311a4fc8e2e6a9a6235a7faa093de973eeecb5fbded1c5881ef8cb0b9dc0fab3ad8e64b668fe9b12dbbcf0761cf076531ebb501254559f750111b0bc82312eaf6ca06c425691bb6cee4908c990061779805c50a238ca1baa0c3f25ac169b043e13af12816512e03b1a16ae44585bb46228c7ff27131311d8", "SEC": "041ef43672c0e6a1212ec033b0bb71f24130b4aa6aad40bff7c50ebefe939fca64109ac419048d814442a1bfb0bf87fd1c3ea07b410fd9e33b7822bdf21c032253", "TP2": "041752454b4e15800bcda5581ae89584144257f03b615a93a04a5406dbb38f7ba112ad21f2e44a96fd4cc32e0688da46b5a34e2ee1a1045586c6d3016afb84a917", "TP1": "0404726736a3d64c7c8b2410b2b1932d2074067b329ee33421cd640abe16380bec1e8709f278eb05b6bf4a4597749c32c0850108697e89669644b8a8b1442e7026", "CS1": "041c2fb362a9d4ffb0afe4cc8cdcafd54304efd682449ebcdd05d4c5bc6f7bc6a1035d60a5351459dd682c86f77aefd37d65719fb54e0cd72c3c33621b0df6fcc9", "CS2": "0415129eff675097c289a3f83f16ad4af59337c927a5b3002aa170c251f1b3ceb007c8fa08b78badfda34f3301c9c937c7f339048939911803d761361aef202c72", "HASH_MPIN_ID_HEX": "4d1c63aef49f8b93d3255efbbab2436ead9177cbbdf72ab816bf2177c464c24c", "TIME_PERMIT": "04190542e10eb28527d27e15e7e7f99118cb73faec830f98d939db0cff66e9f3c61980a64c13e7981b249786178fc47d676c9e832aa4765aeb2065f8c923d866b5", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223763653435633934306636393433646236653731366432386235386538643538406365727469766f782e636f6d222c202273616c74223a20226565663866373434316633633637363766343037623739376262316636373533227d", "TOKEN": "040a94bdf3fd2e2fdccedf0a821a0a857919d3cffabe7e960223dd5ea2ebd9a27e02e6f1875e19cf327053ff39892339ef01024dd6d81e41086a19348ef3205f18", "U": "0406dd2bef46982c600cdf971027c39477efee27e047bbe2ae34d2185b521c66821c0ac4ba00feb7e10e654159e88156f36c584795f1703157a72855d5a64229d9", "SERVER_OUTPUT": 0, "Y": "12bb1d67e34d8cd81c9173240432103d875c19e2310f27009c8f6b868cf5729f", "X": "07d02706a63911757c5b00ae15398bdf24f8ccf487f4041e0ea6bb559e60f4bd", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"7ce45c940f6943db6e716d28b58e8d58@certivox.com\", \"salt\": \"eef8f7441f3c6767f407b797bb1f6753\"}", "test_no": 20, "UT": "040c85281fbb9708ac7fb2c5190274bf7087cf1332c38c2d5fe384f48de8e31b9a10fbb585027474a148a7166fdb5800f1cd07b4324ac6e1e7d75dcfd5f1257e37", "MS2": "174ed4eccf9407b2b36c29cc2b2b64424edb8a5073e7b3fceeb6cdcf666bf166", "MS1": "03112b5d22d677fa7ed698d875132cff1e3615f37664069b49bba3405ef8293f", "CLIENT_SECRET": "0420bedfd98e6e1b3afbba847190577886a84869491936c5eb6455cb60fa367a0d15b7d7b4672b1966b3ba3ab9772ae16ba4f120a723c379c969997dd47bb1bb99"}, {"TimeValue": 1437055595, "SS1": "1c2f71028200c7743973eb5b4cf992278523fddbd85795df04529adcb7dc721c1de51fb07e528562ad9a85afc5607eaf9222f17bd6d4b757a23c184ece0ae56e239cf45452afdd38b0944517e649d2e83ee0929e9c80b825c717e4ffb13904c71343c7afc2a1b67340adbde47c569b339daff386613a363a3d72783ee573d70c", "SS2": "18d90b9554809ddd6e5a848976ac047d3e4e8bfdb00fa303c316a6105d646cef181f8df4662c6cc65bfb2166b76f45188646428d8dbe238a999a75f149d6a2dd1fe1c057e7b14e5c4f0a89a04cccf7d6d6959a286cb517f0fd8a4638b7f1341d19459cd1393f70cc4546ea19dfb3b8063c5717a72bd4f607994d44e5338a1489", "DATE": 16632, "PIN2": 5133, "PIN1": 5133, "SERVER_SECRET": "11a02cf1ab17532996726afddaec1ba9583e17eb7e341504addaa59d3a8a1f4e0866d1847893cc0e492b2c63e88a9f0712dee8ad2fdcf413c5d381aff4aeacbc206d7a1ba8a3633b27f1a7e6f893f09471349b8f8886ce86e2e6df56c0fc147521891be43c631b0611a6d149b5aebee9f4165df4cd6adf27d4b4b3e73a6fa895", "SEC": "0423d9e7d837fdfb13508f39ea03e6931a287a2db022509b407f1209ac6c1bb33014da097913707d83f98686e16a47a8843be104d435f63a4e5b7a0511ee60d807", "TP2": "040105bc5aa447338e0ebea6e8ee1a211d5976aed2cebe1846c545aab2b7c2c4cd1fd9c5f031efdec25687a5ddeaba63229915fc3ae66e00f6cf453b8af89b660e", "TP1": "041379beffe90bf6abd693f8af3c70aae777a121d9fbb837c7da1bc9c1e46f8d20046f03d84c17aed6b6012c94d750af27431a0b6d7a649ad600625fda0fcc13dd", "CS1": "041d35e0e53a90a5ff9307b5b97eac04f4cc6598c280acfb5e19087578bb19d5690cae97ff08e2ddfb3a6e19e13dea1c4a2561bc5067c551250e75c3af85a94162", "CS2": "0414a98b6414877ccefb2ca01b672793db9bc915f4794c8d8a73997e829a380afa1887af1f82e2a1714f0a429d799c129713b89bd7b248bc596ffa5880e7a81243", "HASH_MPIN_ID_HEX": "b003096956cd013eac152ae591bca7c054de788b12c43844c79bef9c76113feb", "TIME_PERMIT": "04167a375c83ab8313938384fefe040b3e2f0aa84cbfba0de7648c22197909fc4a0002114b8209a202925507f5ce1c29157418fef7bd87a33b12166044b1be068b", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223561636463376364313764333537376539326461313332616663346534643638406365727469766f782e636f6d222c202273616c74223a20226564623066363336373461313138313963613134653863376230323939626536227d", "TOKEN": "040aa221e9ee39482dd4b41829a31ec43d884da68199a47f47e59c7f8f4f0e9de61c0a5ff802a752eff1d20446b3c31c8994a2274124d94991033814ab7c380cbd", "U": "041d0793cfa683f2b0a2c68622a3f640cf03760b64d0000f84cb7168641393369309e4ba2fa79fbede4255ecf98aa230d6af79ecba6feeda92284133f63effa1cb", "SERVER_OUTPUT": 0, "Y": "07eff2cb21516f8dab028f07c58c4ba2bb1b477635e6bf9df092178855376d8e", "X": "1ce985372265305a72bce0de62e8d89a6528abe875831f553122d4ba80f6838f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"5acdc7cd17d3577e92da132afc4e4d68@certivox.com\", \"salt\": \"edb0f63674a11819ca14e8c7b0299be6\"}", "test_no": 21, "UT": "0416a5f626609a868610e80fd604195b5161a0901929e8f020b0f952fbee287e020ee611ed055a8f7a4040ad4cf6f8984143abffdff6ac73f9fc3c069bd28a79c5", "MS2": "1d2861a78f1aaeff63d6ea6d8ab029dfba3b5c8fde372a35119a2de53bedd114", "MS1": "11ebf8baa2668df5b16e84095bcbec5f37361887f49434a9ac4bcea2e698e927", "CLIENT_SECRET": "040ce22cca8d2b5cc695e5bf8257faf56ac4b0185326fb2ce03917abf94e7e498d0483e5b336a2d4642e738f95fc0f99e582f77e1de2856ee25fede0224b49874c"}, {"TimeValue": 1437055595, "SS1": "0de2e6df1abd97a21d971e8c23c136f4696f5d76f874988d9d9333890f1b882a12e1475fbec6f7937c216a6e9e2d17ac0cdccb5b781176651600098f2860ffab16cc48d6f5ee290628e75b325ee4b9a8b2daa85ddb29cf9c7a20de9e919f510d23dfef10e5d8ee8cd7c3df1bb7e300f2c4e03aff86f4d2072c66110d139c9c7c", "SS2": "0537ed4c3553b874dbcbd3cf7dada742f32beb9a1f16456d9f875b5e192dc66420fc831947aef46207325d040bbbc1ad60eb12a8c622f3458ee502f0a6538e0922d7aa479e1d28fe5976bd70cc7043763db42bb49c2889869267c85eb8217b56202c0e756ade871a1715632045c3af1057403ce8d98b7812b3748150c64f94c3", "DATE": 16632, "PIN2": 5337, "PIN1": 5337, "SERVER_SECRET": "1e167c030bed8123f52715dc647979c777d5d1399e59dface8de353eb64061d02216ddbb6a926a4db272f2dc08304d32e4dbaa188694875d31531c90f1a13eb617fa2a5bf45430215f329527bc812da1ac46802be880f14c6d48410c860423c821fa166e6d1049259a5f4613c214a231f8a99753c09615a8474b7920a9f2c84e", "SEC": "04061e2d17b4c0e38713618bfb164e312525d4854efa314a22e328e27d559b6f291c1551a4469ba33b990e9303f212da7ccc21dc0bf53830a09c51c3d0daa3e8ab", "TP2": "040d1383c528d29ce6ab256696cc1c32485e96498d4b4c2740693cb20ca033e5fd1727d9b82df82aac69bae640d1660e196ed838f623f12ebb21cd9c7ca9ea0b5c", "TP1": "041874088d4210e3d4af1df0ecef90bdf7b78c37cb6ed682834b3654a0ba7bcad204f335edeefefe1cbc1fd5a6c119f333a0e4ef06febaf07645dff425a31e8f2c", "CS1": "040964897b71b4ee4b8115b839ffaab80c803d767e74c25c1fb76e7183b8219802043618edd91839ef1577b02916cb46c3484204ff012b58527c4d0543ec9294cf", "CS2": "0401a402a9b99429e9b988c14d1e700143c5ca9f253c6c3ae7fdd23f2af1c9886023b23159ed6c657b90885a87647a9ea7c436190a899c9cac70ae16d40adcdb25", "HASH_MPIN_ID_HEX": "810ddaea04c5c1d33f99cd2ca20738147f2618688908c6add5e8377b8354960b", "TIME_PERMIT": "04165d8518383c59296b87c59162fcd8d8018dc770f9ca59ba7a29ef86ef3b1497098c7533296fe76d06944a0146927bd2541bef8b4e5124e623530de32c0af4d7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226166636535343831313065323563303762343262313464313033623736303464406365727469766f782e636f6d222c202273616c74223a20223432663433663332643763653166633935616537303830366237396663623733227d", "TOKEN": "041b08b4d707a900b0ab9212218e8ff782232bcb67d0ad7af0b60d4c639e5d6cf81b97bd65d88f275271f9f0d6828224f7a9a4684247675c88918d74690a3ca51c", "U": "0421e95b832350e86b14a172fb8a692b8bef7a7720e0b28750dec10bfc7db6d968055e183b3e59234c2ecb39833ca58bc2ed9c38343aaeb7735d4f581edbe4aff0", "SERVER_OUTPUT": 0, "Y": "132a35942ae1f78f44b94f3b1679c0be95a885f1230b1189a395bb10e9b48cfd", "X": "16a9570fa23c138241b87c46f694b2b55d7db4330fc276cb30d44ed6828ab801", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"afce548110e25c07b42b14d103b7604d@certivox.com\", \"salt\": \"42f43f32d7ce1fc95ae70806b79fcb73\"}", "test_no": 22, "UT": "0400c108ec2ed1de79cc0cfcddef3e4382626877e1937ccf58798076dc5c6d43b902b67f5941711b5918a6176cab2709b7242bffa9a7bec56293f23130704e1130", "MS2": "059f060052ae587ed62932069bbf449d7aaafab1375353285ce084e6517fb02a", "MS1": "0ffa1676bee9ff7663186aa1ef66cb1fe09ca840bd2ddeb2fc9d06d7c3099f1b", "CLIENT_SECRET": "042093e8117bee91529caed016f9b7d4050ac26ce99a53b17ebda521ae230209b921f193b1352c023ceae47ed49b44a6632778b76e62aedcc68f245906bd2af90f"}, {"TimeValue": 1437055595, "SS1": "074e620a47c53adf4859d4df96bd5ba278f399f2c4434b73d2e5a711cda653e31c5e77295b91bbe8dc942ebf36f04e3c7c853c467cbbb9736061875867d84ffd06169ded374489a178adfbed46345efc5c3f1f2554799487aee929b526c1d5c81d6e76739578069c988516e27ebc2961bef6d24ead425fd720891e1b2f393f6a", "SS2": "0b412345b0ab86801c256a273cb8674d8340dd8c45fb920e09ae90676674d2d40684f28225cc206bb1883b89b378052be06097e2a1519f0f70c63b7f79fd0fa40fa865f48ce4b44e290e7a2a6ff2c3f29b6f81bafc8d23b5e3a61bbea63c15ee1aed6f9e2e3b34130388a869c2d624f683c2f671b34c403e8cd5be025ec8daf1", "DATE": 16632, "PIN2": 4924, "PIN1": 4924, "SERVER_SECRET": "10e6a2722cb79bb2a5542efa260d6a6078f605f58af34f6ae3e468e4c13d779501fd4dd0a767a12e82d2332fa99fca6884182b961b9c0015bb9c2de56aabd4db0710deb201c7af12a0cba3f1d85f544a8d6107f2bb71c16953868f9256cf27c000327d421f01cd561605435a59d06ef6fb2687df759200d1d56aaa68fbc570ad", "SEC": "04066cfb2a767984ce8de6169fe82f1778419015265d3ad7cc7db3058f9358884c1f5bbee103c9d7c0020a6dd484c231d83c3f1dae47807fdf45ea5fbe2ac07f17", "TP2": "040aa39e00812efab4d3754ad6e803166050fb849aae49f62c782449dfd0d1db5a1f7f61a513f5405c4083a1e5b4cabb0923042316754f94e95c05b7a2cb594bee", "TP1": "0407ddc4f87fac6689e93aef04b0a8262f088c28b264e4530172522db87efc1234216abe06d1cc8bdf91824a65167becd839f479d411966de354e290f07f49ac0f", "CS1": "041f6b62915debf363ddb2d61c54f1516f0a88fa01d2af46c81d3488c479eb82d719bf549cee6c84363d038a7242d68310bdb9bd184787fb45cb90609a169e9225", "CS2": "040fde7a3b1a8b7aae6d5a8ae72582363f606957707886a524a0976737b1e03b0810d2ab22e0b9b783c9357b0fe3abb26b3556ef0fb7eb3739cd92a0675fbd6fbb", "HASH_MPIN_ID_HEX": "7ac79a48b5f116cf3eae5cd1e9df9219ba17c32a0ce94913a7d0c7c1d0dc6eb9", "TIME_PERMIT": "040a28f1bfe51615f2a5cea19acf50771868d5bf8fcf90681c515ad75b169ff41617786c0185fdb4b3c00201d47e596c7244df4f2ec559f571d4bdc4734297ebb2", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226464353533306436363965633034386364306664626532373264633266666165406365727469766f782e636f6d222c202273616c74223a20223562623762616434376132636236363233333764333261613538643235393136227d", "TOKEN": "0414493ec8b984218d949ecccb715116a381cc04a6c8cfc6b41000f778130b49f4099d6cf0f1463297c68eeed7d56fe114ae937d6bc78d80111956528ccce18b3f", "U": "0420396f639a5c7d58fecbb68c13c2396c54aaf8c08e00e48b49c137477f4f1cda230ac40cfbf7fcba53f5f9e5548c453444acd3833b1e57240740cf5f7a0c8c7e", "SERVER_OUTPUT": 0, "Y": "225cf1573bd4eee607670d6b79090e174f6ed0939c3733964602db7090a32e71", "X": "1cdc04dfb5d0d9b320de97876c0c75a573b23e4ad3b3178b9ef2148360505a79", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"dd5530d669ec048cd0fdbe272dc2ffae@certivox.com\", \"salt\": \"5bb7bad47a2cb662337d32aa58d25916\"}", "test_no": 23, "UT": "0406261cf77da914a8812d2e75225df0e22fe4b378be2fea32ed9403b7d4dee2fa131363d78d5950d98445c7bed5d6724a88974361fe8b5e0ab60c819ee108f1d6", "MS2": "19737df08839b2c6bda04053818779c8f104363e0a49767896c7ea96bbf5986e", "MS1": "160b764cb78405619e1c0f6f12e1228e21483fb683b130db6210027900e6023b", "CLIENT_SECRET": "04015ac9e6ec0988d052342e425f6c3ebbcd284d7c72c7de38ad3e318282b5cc201738e53120b6b164334c18ec806af4e6060461af6682d2007bd1c74851026cf8"}, {"TimeValue": 1437055595, "SS1": "1dfff407a998e1ae42ba63e9d7468dbd0f3affd46eeb06e71b849e9b7da69f8a0ce1edad5779719277d96676c7d865b669f094f3bebb6426545ff27a02890fe10635dfad2f0c8438ba6743c21e62c87d7827dc00f81ae8feba72d57d85ece5c003a1b4f9d1401a292fe7ca46a9bab5a6709b6b4261ef5e318f1093efdbe3d92e", "SS2": "06a99f6fb31611e48df8511b84191a88dda865608d555a21c2b33542309253180f88dd3f84d1650835bac39a472453cf7595662c780f755892422c959d6b2d9301f0204978248a893f2bcebdaf96923da5494f804694885c3873f228322b58291b48da61c416db1f2681982dcb864a655f1fcf5a32e8a725386d306564e5fac8", "DATE": 16632, "PIN2": 9815, "PIN1": 9815, "SERVER_SECRET": "160d008919bf09dd8b8c5bec1e59cc93af87ca012f94229a77feb6c0dfb4a185233a2fadb561f9fde70ab47e11131c7f54286dedfeb117df6866cf08eab8d1d91ba45c7bc3374caa693c30c5faa32240b36b03f0bf4b865cd5d99d69d0b0d72206a0db6d9fe55e29b8a5c1d8e5e6b31683edd94b3139979c59d74ba368a400f2", "SEC": "04040c58835d1674a02d57438bc34c75904d9c9106f197e10e05687cda0e9c7c9f151933eda2de623126f461a7ba4931afd0f6d7935b591ab15205986fa46e255d", "TP2": "0408853cc6a9fcdc7932eb3ae647e6868adc10dd2e9601e63425d469e4e45daf9c11745425807b8b782158d3730cd8f03777be0f751148f9498d2d9449c3e9c87e", "TP1": "041c9b3a7c918a93893807ed6f82a12e5e586fd709350cee72a4d770c50cc777970d9f5527511bc366ad15493673042cdc0c3515396bd45282eabde97b5828a5d1", "CS1": "0417b32b90fb099fece26252d8ff88256a6bdc27300cc3761f828081730d09860d21b119e5dd11bf4435e6e706b830b68d8b4c60d2a57784a4896f46e5cc22d226", "CS2": "04108fe3a901d83e5b25e9f6350f096ba7b48de4279cb9d37e79d3cdca69e81f9a04dcaa9e0f00f9023fad0d8b1d8aa43474d10435c508f4dd90f01127846be5f2", "HASH_MPIN_ID_HEX": "048f0125345fd1da3cc4d35fd809ea9fdbbbd9d06dcfe4ccfa868d6dcf4cdbf0", "TIME_PERMIT": "04130c52a3796f04670b4b05cc94b0ee1de128fe709eb45210c86ddda7cd13c49a20efc52884cfcb2ab6590fb4f3e733f82cab78109da9374677ae6aadfd2eb84c", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223534363038396336353030336237626438383835353866663232626462656265406365727469766f782e636f6d222c202273616c74223a20223061363066363733616263646539303664666165366466393331633966623339227d", "TOKEN": "041ddf4e0f7be612572c79ab5818d0bd9e0d3538e39b0e566bc0f38f84d101f8ae02c53dec288ccdb536af7dcca995cea60bb88ac319dadc18ecd2246eccaf13f6", "U": "041839b3d5dd0528fe6ebb4b8fe0ca2d82de0d77acee6e2653e22a98937c39d23c0824f604c1a90eaa7a7e5b48ef97495b1d6f17ab99f6081c5851de0d4e022939", "SERVER_OUTPUT": 0, "Y": "0125859bb5998d5d21053a0a32f4149e0ecf0ec2b996997d6506cf09d6acfb4c", "X": "049503ba3a07b667a049ffb092393cb3da468502ef4681fd9dc6bc82b09fcfea", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"546089c65003b7bd888558ff22bdbebe@certivox.com\", \"salt\": \"0a60f673abcde906dfae6df931c9fb39\"}", "test_no": 24, "UT": "0406240ec243897b2817de929e5c29bee7b83f8032b6963086045955aa1f9035a10cb5e09a277daccf493a3b41104e3168bc2b5059259142ae308e05e05fc92a04", "MS2": "18ae401f3f87f35f32a83607ad3d67ba237e62d3f0d6ac5ced86f68bfc2cec9e", "MS1": "12af4d3cbae01080f71957366897cf2ca849604b50dba156e8955a2eef1bf512", "CLIENT_SECRET": "0405510122ce97d8591538ca33435d94aa0a264df45c2cd1b982ff8b43282bd85219e1266c15049d1ff0e2cbb7d0ce94e3b691eb5ff5687b53be531dba9a94b97a"}, {"TimeValue": 1437055595, "SS1": "151ebaa9f4d3850f67200fba397a0e66c6cfbb36b02a11b4a369853ad88ffb800aa782447cb2761c9e2f2045c38a70bbade12aac474cf2b918959e9dd68c22f709d56fcd55a557e83e669e77e2805ff218c7aed19de0038dd14c768d2251fb831dfaf4e9723199e35d4589d80e8502004b1a34da4dead7464c2efcf361ecb5fd", "SS2": "213f546044d639dfa60a24fe91c407d81ced9224ad542283ab2c1740beb5ab7214100dde7ab37e41be05f8d74d0b5ef6a42992b947173ec4fd285f4d38a047700908afac6dbe55512f5aa6417c7648aff1e56b9eba3ea61d3c1500c6a84c0800228824b381be3290cccede00f9c1ba6a4386a0b1cd9ae6454006841345c601c6", "DATE": 16632, "PIN2": 1580, "PIN1": 1580, "SERVER_SECRET": "1809f67bb6b94e6d382adfe85875475d34029a3096e604eac302754ae3af565e0256df4eb52058c5d25daa53a0c021b582065b6ab11ca2124f2895c03ac4130d03db5a46b26f3ff3922275ec33f99e737f3a65ae0b8561d359a7f2ffe8a0cf520af528509690ef2241175e2168c1be52944ff487b708297448d0d79f19549d54", "SEC": "04077364091300f87cda1d16a1ed8d35512639a87fb0e20942c43b71b3e3d90fb2118e893219720f55bd5a906d0122c2e25937e7045370a29c30393133b45b0a41", "TP2": "040b0253a183d292d9bde76392a0bbbcc9cacb978d7c64b5f0a8d55a452fa926c80e50679e27dcb38a87bfe730bfc7c6f94f2676a526c7778bf0c16ad084822cea", "TP1": "0406563cd9d62aa692495965ef7e6a15de10d0882d594d0dbef04b4563914753311814a84493ff21cdd211722b958673f1119bfcbfe30f31cb522a359e08877fcd", "CS1": "040be1c34540b42ce63ce86c8f9bd4d541c5e5b699efb2286685a8ec88169e10c1203d97ff1e4ee1c5b3dabdf48cd6875a2e3f5aac2adc0a73715c83afb3a254de", "CS2": "04133ba77bda07477831747d1986414e9ea4b84ee97fb58c56d0f0d82d34ad84ff0c1d93fc2ea816a69e3c3468bde3fd71bd12a0a8c106b2d388b7f3f06871f25c", "HASH_MPIN_ID_HEX": "18c824e55cd98a799340f188ac38b3364174a1dcf015a5884b3f10a97384d7bd", "TIME_PERMIT": "0400652e779915e7000ce7e584926f4df9af98d93f2c68878f3738d1d13eaf87b01ec26720a9855bdeb48236dc67d1763523f9f17206c045d5524afa9c42725f35", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223037623833363365613330333738383464366539303134373465373435643661406365727469766f782e636f6d222c202273616c74223a20223466326234333631623961626364653564653161643561613633346664646666227d", "TOKEN": "041e5d268cd58583567f3b2f244c30b01f2f646c6d8aafad79330f10a333e2e4af17ef2b1fe4a2f27576ad4ca2092d1d7520d6c3bf70b3c64f179125944d82eff9", "U": "0417d114eb7d1f511ee663cde5c399504b1fa61c410c3b23bf8ceb9af8ac93178004414438a05a6992aa21ed0cb6acbaecddf5185ef02f383192aeb8a707f49f77", "SERVER_OUTPUT": 0, "Y": "0617e2f50a7b1cb0626ecfa797b24900f8d35f3bd97ac978a67bcd59f3ab7536", "X": "2291fa3d3dca7fa8364953daa645072837e5bf239f02323a76a6e4396e2730c4", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"07b8363ea3037884d6e901474e745d6a@certivox.com\", \"salt\": \"4f2b4361b9abcde5de1ad5aa634fddff\"}", "test_no": 25, "UT": "0421729c46379b414cffd7260b9a260dc6d7f796594b411be45db8787ee72ec18608e720ead5711be6e4d8398ccfd5889c840adbcf412cbdca437224d88bf9b1ad", "MS2": "1619d904f1fd6b791a0e81d8a53d35230938605dc79df72c1e064b425fa22882", "MS1": "04a8aaf65175a71ab4bfb39f53d30d29107a3e3bb16319ad4fb5741f31cf5c67", "CLIENT_SECRET": "041d423eedb4e2e0269817014f3a12ff25d28fcb23c54eeb4c86ea77a7dfd3f53a0748f9847d077b45815aa98cf146abb94d6b44eccef833244cc0fc388e8aaeda"}, {"TimeValue": 1437055595, "SS1": "12a09577eb6f6f30595486fad7ebc3a1341162302ef9e433e1d001a9fea78d2b1e594e3678a081e7a07bc38b4fda4951b49756a0357a03e4f7abfa0bf6123b550039c1a85f511491e0f95086dcfbc796378760072bd2a8dd8d7ad8d5ee99b2fd07c9e5a511dee03edca572f6c55924e43965dda4a8fe086c84687796dbb44684", "SS2": "0aadd27990079cda4ae471ff46eea6892fd50a0a8887d5ea3f10921fdedb720419ab7e99af9079b144f4fb09b3f3fb63f0c76c677d1b56705c86df22a6fe760c006c35406106f3fffd0bd663ba1b0d23b89c1355e37f04db4df3e2fb87567fbb11abb1b261f976e2a5bbc00b861c90a9c4005dbd6f4c7c16ba63c077e747386c", "DATE": 16632, "PIN2": 5314, "PIN1": 5314, "SERVER_SECRET": "1104be4d66e7b41da565d7a950a86706f26f67bd7d387776f0bdce4d8207c8c420f1f771998f7fc73d2285401e37c083b1e1e2288e9b3922a8a4982056fee894149e0ec0f477a19c7900bc4626c61825be0c8e0bae19b6bf48a48ddb6d6e095a19612622d9dcfc627697e70d1ed56a2f5a2ba3fa541b00f2c640103c6358b8c9", "SEC": "04074f9aabca040e4c071321575583b917f498b40ad678bedd647e022573a12348003d0bb414033f3ce449f94904af23fdfde2a7d0d338bb79326d5ecb25334048", "TP2": "04076926a1869d6b8cffaf314b5f33acaad4ebdc0d032512ea53224d83606befbe1eecbc6299fd57a7a69ff36e6ccf38d361c3ad2c42466442612e6d6c60d1551d", "TP1": "04208fcc0ac70af091fcc1f11db34cc63d89440f193d652010b1c6a616d0098f341710f5ae655bc9411aec445348207796a029b757df761989eb3f535952c688fd", "CS1": "0406fe805766ea5b737fe5a2d53b6538733636843dbef935e27ea08f0942d10569146777aae7b40997e78e7dff12a2f5dcf64fb941b485e00301012355a9f844ef", "CS2": "040f8cbf8cebbf209ebdca9622819fb3b897cd2bc6474a3badec15cba6bbb2e240218c09039b8f119932320fcf783095c792915d9ee8349dad598587596a35ecb3", "HASH_MPIN_ID_HEX": "5d3cc05c6c82ecdbc5f32478fc0bbd3d29712af25ca03de3ccbf482507826f83", "TIME_PERMIT": "04219c5d61386561f326e77f2e74960bd28e5c399b209eb196ae561a15f2291dbb1f9fb9b4d0669980307ce16871bbebfc03fe2337464651728ce7bf83bfce5f26", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223137383930393265313161616237323635313034386230653661333330323237406365727469766f782e636f6d222c202273616c74223a20226164306261666337343835353363356363306534393530353866376331333162227d", "TOKEN": "041ad8094f5dc854325eb5fb4bdce9a7a700d540d85155a7ab8571615390d62b730dbf614820a78ab36b959e24995fca0882c2fe3aacf1b9527da85fbd1f2d8c52", "U": "042227a1192f9e8880a3b8f207771bf8d6b906e2be97a137dd8b1686d72f5a9f93040e35c101958b467485f57a2253a2857dc18597eba8f66a78b3f21efe9711ec", "SERVER_OUTPUT": 0, "Y": "21fd7d4c993d61a9692b89cf37111744f5fd0c8db752cc7cf487a2a5f83dfdd0", "X": "09e317ac3f6c8bd859d237da5375f29df5a5fc7d2bba61b14c61f79ac409af13", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"1789092e11aab72651048b0e6a330227@certivox.com\", \"salt\": \"ad0bafc748553c5cc0e495058f7c131b\"}", "test_no": 26, "UT": "0407efee2974f26fc61d22d22921f8fde39d38ed3d22fef2c719d56e7d9b19bfc61d6ba818f5118cce77ae4134d408511f9ab26abcd1f3472df8ab0ef54df1610c", "MS2": "149838282463244a61c727b463efccd995c134a0eb7027b41ec0c2fdfdd92981", "MS1": "18058af144c7ca55128252e66a7d6240b08049141b7da23318e3766dc8382b10", "CLIENT_SECRET": "04007862f4ae6ad3b1e2e6d9c8f95e79e30b5cea864e41940e34c4fb08a902a7680c5de89410f45ba2238debb0902c101607ff5dc81104fc4e1aea65b45f573e27"}, {"TimeValue": 1437055595, "SS1": "08b32d422e2e40bbdfd19f615ff8baee2e699bdea2b58dc13e46c6c888f9d3a80e1eae357df01fcb97db7768852a8b423e0fe790378c9f68a1915cfced5bc8ea1b8de66e5eb4a04e3791079a535e10796c9e79cb37743ecf0d26efc6585a418600e79e43953866bf7bbf20648213793ae3ab8d6d1d8a2c08b0d2c4f0bcf0027a", "SS2": "225553cc1c05a2486965787b11c4d0e78995aceb71041eb7008d4c0c8c5eac7c100d30f460de9e518c8bf7c1eb9ce571ef338b16c8e7f3e056856fbaa522dfef07fced161834cea6efdfc7937071196733e2f2f72b0473468e7236f720b1ce381b53bc9b959a697ef92b430fdcba8cd4f4e0abe63901ab022c333ba5400e405f", "DATE": 16632, "PIN2": 8419, "PIN1": 8419, "SERVER_SECRET": "20324c15c492ee1ce313d8f42b17e0cda1b9d3b189932ad02d8183d33ca492e30ad43be29b00bb788b210d12baadce9f56b83a5bc582abf4cd8fcf6767aea78505eac294374643f64cec0dd993be144c7c6d68665f0e9f3d5b21bc73454aa50806d5e77eeb5a762b1371ae4dddf5bacbc0d19b8237d505016d5398c89fa0289e", "SEC": "041d799dc7f51d86dbd34f149157812592b08df03249ee253c5f6a998018bebc6423138bce980eb0eae79a5dac073a352d8742b5d3f8cec422fd163a9ab3e13c30", "TP2": "040befffc5c5ea575766c45a69945640cea75e92006e494037998660e04bf6af93082b6632020cf131e4fa619654f1a1031afb7eeafa9cb1a8b697ba0a4ccc1a0c", "TP1": "0418a17b2bbd9e84ec76abae150a724002a5289dfb9ac30b0f8059eaa018c502a116b576f68defe9dd73a512c3e4e12c1eeb225d484f336ec966360c77c19e4a2a", "CS1": "04103aa39f9f3ef8f6734e51371457bf7479b19f3ad0f412b8cd7a272964c4fd521feebd75306f8389c37cfa606b31a34d2dbbd009e387b7284eba24cc0ab0f134", "CS2": "04047761df0beb8bba110d7ee61a963c6b7746491c914837f5a7ce6aa5f0d08a7f0ba7d6a57745033725b93ad0948d4022779b6237bc1d63611288afe6dc18327b", "HASH_MPIN_ID_HEX": "48761a549a27198d7fcfefe27e94ce74a1df5ba6e1537c28e1bb295142b9a541", "TIME_PERMIT": "0404c0f1d1a1cceb30639101aafcc2bb8735f360aafa6876639feea93c7bc9856c1c95822ed3527d6a2b895169a70dcc859f2bbd2dad1b46d75d3cd8b23d37d844", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223433326463326463366564616632336330323133623063613931653363303233406365727469766f782e636f6d222c202273616c74223a20223530333765376431316436646261656161633566373438356135376561623864227d", "TOKEN": "04064f5671a834234062ec24de3dbe95025e16215db0607d2ed8cfbc09597ab305159148b31c836e5b4c7a6ef5c29e3fddddf62a8c5401bc98bdec26a990ee32e5", "U": "04221cc66d53b647f408f56d14c4a717c4a88675998c012d33b5fc8b092e5e0bc502d77df274d3440d2364ef15a01d3e42c00dbcbf965334d512a4e5d2460e3161", "SERVER_OUTPUT": 0, "Y": "1fbc0962ed01a8ca5d821efa454f8c1af25618445968a9b0fde2552c346868fc", "X": "0936eae62246f5a05b8f4a76b242f9fd08a2355f31a39011046229e9e53a7bb2", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"432dc2dc6edaf23c0213b0ca91e3c023@certivox.com\", \"salt\": \"5037e7d11d6dbaeaac5f7485a57eab8d\"}", "test_no": 27, "UT": "0400dad3324d2e1e2e9ae15c1da7245333b494b024d1027d767147df95e0ed8f8320b4552eca8abb8a8be2c810855b5715ae418ec703d88f2c31e78ec3a97df1f8", "MS2": "17413bd4a1534dc12c8dc16c16d288a6afabf0ecdda2e6083755dea06f08eba1", "MS1": "07c8059aa6255c53001858032d666252c8d16eb0a77a001dea868e83b02f39b4", "CLIENT_SECRET": "0411e7b9411cd38427e2b5f334cf47a3d91e18fa48b76025c8d460750d1bba09c418e425fb3cecb4a3f6027f7b0c9658cf3e2207fbbe5ba161d72a49ba2dc5e9f6"}, {"TimeValue": 1437055595, "SS1": "0c60a9cb7df0b4f865f71cea39809ae806acfe8dcf0a290c739c8ae231de19c518f937161cd674453e8aed3afff37f65d22deab42087934bf8c7c129fa32746e08445f1c91054661adcfe573e65e84ec4a4851274fc2a4fc4818fcead9e2faca161c34ffd8feaab61420decee9fe4f0bca1ebd04026475d4f25e449b58d542d4", "SS2": "1b98684ba8d6d319d4f66ceabd5aa73293b34669465460141569cc8c2756f01e15aafbb7e5812f9a0be1ef09e4cc0daff4ce7462eff8052e2f01cec5a76c8221140c125aabec9dc889ff072578bebb090ec32a870134b046808fd716eb45ffb81a670fe0eb2660fe4e47da08d301c8cd839ba24c0acaff5844a6864069d599c2", "DATE": 16632, "PIN2": 9999, "PIN1": 9999, "SERVER_SECRET": "22284d465e0c67d5c2fbc9612b9db44125b71dc75290fb278045c582cb404b31149b544773ba37c57af18b20b37d73d4f372abc3ad5fa7852013c60172a5af6e052362962bd7d8b7419475d207ed11400f705794fbcc63f60a2f365745eef9e92389b1f198bd4ab6e34f62651d3f95194082e94f4d526df75d5f7b3974898ab6", "SEC": "0423888d3efc6843a013696a3a0240ef6008350cb2b1185582bed5529e8d6704f11f0a02d276e1b7d376a0e15b1728a621eae7bcd7b2e508fe319a7437b39559d7", "TP2": "041507a514a639d5ec7fa05c9a273cac40d299c4482390a078b9a61ad411d3229b097998e8d65c19cf92ab9f84081ec6215e698240c93e0acce14e460b7ca676e5", "TP1": "0404db51d8875f2a7440a87ce6c35d7dfef5fd333a728bfc0693db901a7ffe715b07f37b54980edde7bc9b177e9b9f491227a7eb07b96d97c1d44bbb5257637258", "CS1": "041b01c2446f184624eccab4ff5eb4c98615cfecdff803b5ecf1a8dcbbf424a9d710f063dae5b046628e9cb07dc7c283030512bd4d71c5c30c5f2dd4714041ed39", "CS2": "0407d70e9b9dc9de09b9712db2055f87b8111eb9e632ff897065b651ce9e87deff03c29038c71597d421dbae0403a17999a24327077458c4d75d4661fa48734a82", "HASH_MPIN_ID_HEX": "477636927c711839a9c19de5ae0463c70194ba8f56113b25d0171f82e3b866ee", "TIME_PERMIT": "04056d99e09e7f093197f51b7bef18836b929fb63d5a86ca7dde40fefb904fd518099ca2aaa0c1fac71d76996f068fd64f175d5b51ca4d441e3d645b29957afced", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226139356239373065396636653230303938363934623537306265653439653262406365727469766f782e636f6d222c202273616c74223a20226239313339323137333431353363656464653831623463333766396663343538227d", "TOKEN": "040dd0c1fbc431b40e1484ace8ce4aadbc77e85af4b1f73af696c1dfde8d519dd1147668a78bdfd167f3719ef501a6db2dff033ba498da98b4c54c0d7b5b0c9920", "U": "040823cb8af323b908c5f0bc97d212b5e20949552b826dc661e40c86c3b226410c02174f0690dcad785528805b78c7ef07d4ac729d2f0193175fe181cf28408d25", "SERVER_OUTPUT": 0, "Y": "146c565f46d383254cbe15678da45a78d905571a39950d0a30607fba96064500", "X": "1f058ca4cfe2f7e5390717c26157ef294e6019dd5b9b7b7d62c42ae1bc782bb0", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"a95b970e9f6e20098694b570bee49e2b@certivox.com\", \"salt\": \"b913921734153cedde81b4c37f9fc458\"}", "test_no": 28, "UT": "040013f7d9333f751d44df9133729d84d8730a67a0af0234a4bf7da2651162decf10f48868b43a6e9b855364183169c69a4617ed17608698c245bfbc53e7c251b5", "MS2": "21d16c7b703746f2851b536fa753068b0fbd9c990497a24911fb8c9ed6454352", "MS1": "13e20d1384d089d5d41a9a47408e2a06a73018b7207933259aa414f09c418065", "CLIENT_SECRET": "0407d8169eb02def78f94e4ea04bc8ce69949eb887d4563bb745232956465fd7f1079b5a3d74dd0c993f96463983a2b151944c40b657f1b20bbe73bbb07f04d3e2"}, {"TimeValue": 1437055595, "SS1": "127e5fb5ac44b7c9c1cfe30f900b8204b82561ae33240e76325cded4c32e01981382718ea69409135524dcf45257013626a2128851d6c999d350e197bd2050c60045cde45adc1a750d4fa947e2a2e1ea4b189e2d5198101702fe2e0e9606901306f3ce254b3894313b75202ad2c5720e02a80e68117ae40af0902e587e374eeb", "SS2": "11c9e6507c0db4e449dd406e1c6c38681439f074afc2869c8c05ab64f3f48bda069c405f65d9f79dc15567bb9fb457bc82bbf5243042d089fafb548bc4274c84142d6815345ca1cea11c699fa92edd3c4ead371a4db63f504651fa97556e8658123040913c21509c47258a13228d32f9aca4d39c7548a3213617efb5d7b1be8c", "DATE": 16632, "PIN2": 8311, "PIN1": 8311, "SERVER_SECRET": "00290168f33cbf40f80eaeb5f89abd1271589af492e1be13d6ae422da44462d1005848bf853561e02d130a092b88350dc0c6f12dc83c07f0149a3ede46d8de740f6459cdf65cec8f6059d5c3fe44848b7bb18232d75b29c73c53bf1a5b9e248d1091629582787adbc837ee2cf364e4a77e1aa46e64a8361056f578cf8f315471", "SEC": "041ac4e606ce830766d2f4e342c51f11c80a38c2907fc5a40014b6bc250e18c9031158967e393fc318e91eac3a17d0b7d0b9a5f4d439eae602f2852558c6e01960", "TP2": "0419d8a91f343e09fba77d137451094604dd259c6ca9815b39e9a45f3274202abd1c2b7bb662411557cff66393e598a571c4e7fb39e2db532b171e61fab1a6e69f", "TP1": "0407ba13ed18be3c0a2510044a8df6c932546eea91ce377b728e4f89c09fb33010202deddae7290a9ddf003a931135797887c7ba3cd404b5a2ac62765a8c58fb74", "CS1": "040415fecc150196388a478efce9fe28a45ef0c034d78dba3529a0ec0c15de4196175ed6c6cadb8470c74922e983a3b5baadf32ffab278fee6a35588e1ab802267", "CS2": "04152bb3264fe3a767ac6d507a388df4933f5a0bf56a4d568f1f9ec6b1057c32421e57e00cbdb60f55adaf65ed7eaff3977db388575e02026e2d0103f879f4903d", "HASH_MPIN_ID_HEX": "e84df2833ffb5c966812a5af384740c867be7c9e4f8bd239c8464efec49194d1", "TIME_PERMIT": "040439b0a07544d5b8456eda60d517f34dbfd0f6b1b67d33d14737a586f5a1b44f0d8d7e83ca56eee6304e607c5cf58dc4aa76ea5cb8dd8319bbddf114636eb09e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226438393363323638363136333834386234643735653231633431303639656338406365727469766f782e636f6d222c202273616c74223a20226532356665623362623633326266363862656431346636313233633366396665227d", "TOKEN": "041e8dcb34db6b34b1811cbe9ddb62370e44bd585439128ebb7fea09dd4868d1980fb206b82b1c4a1eec442fda8c060c014e9d776d69d86a7212c94ed8e0063cea", "U": "04014f675010eaf17b22e1e73734ecf028cbd7c0fb5ca06d0cd36b2e6e651d14042021dbda580e5a42dcdfa471f080c7caa235fcdddbe3ddb71052292d33a211a5", "SERVER_OUTPUT": 0, "Y": "0a4c957d5dcc154b41c7a4689f7876825e2957805051354ee34fd733296d7049", "X": "0d4fce3817bebb8a8f167c1032880d02678d38071806ccc02a61cadcb77d7c71", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"d893c2686163848b4d75e21c41069ec8@certivox.com\", \"salt\": \"e25feb3bb632bf68bed14f6123c3f9fe\"}", "test_no": 29, "UT": "040ffa5fc99b2bdc2960d26a1b0759ead70c0494f9fcef4fea913ef10c34df99bf0b3ccc1edfdbbfa5ccb60aa8e432fc528c520a7be0c871f2c010eefbc70f3251", "MS2": "008be08694642734b2700fa1cbf49e10c1bf392c9e7b720c2387f753ad2141cc", "MS1": "0485526651e8c4636c87c16b617f9e8b85129b0b997cdaedac45accc92279ff7", "CLIENT_SECRET": "0410d3419ce709d5628ea431eb60c22fb1a0d335f10793c270b766d5b3b4e5d686083cd3bba94de579678621c24d4eefdbec904b4a007b56fca69e7187097302b8"}, {"TimeValue": 1437055595, "SS1": "1f33bbcb414e773bb083c4d9b3be80e00a644518d0aacf4cc6328093941c2f5b12b66983b94465b0a9a10a5a13879263f0b4a8623bcd4d964d974feaf4ecab250fc71e5242165392bded8be171866025456b204dc45fb55682ebfd15cd17adfc13064e2350967cf203b13d7e5d2436049aebede3ee43b662b01e80b2a5dc18f8", "SS2": "0a256f9da6f1d8adab39777d0fc22d70eaeb3373067bc236fa993512eac21de41ecccf4da447e84b745a2bd9a49868e488c817f86d195a61cde11879af7901271610cbc56ccba88d24b00a406ac595804ff6c0ca89e593de013e3e7446f4e2bf1bea8278e7ca861c0fed8384d1058967f6ea291c7346105b99e18c0f28849344", "DATE": 16632, "PIN2": 4724, "PIN1": 4724, "SERVER_SECRET": "06bc05897c6c9ba2be85e5105ca58a8f360a89d99fc8554fdb5e0e2d89a4e94f225aef6c30467bcbcd686d826e76822569323d1085543bee3f03bde4df6a2b370e08680f1d3316cb2053a921eaecfb5e076393c094aa2d346526f954015918800b0f7495265bba6126d0f3465eff5cccdb0164822f7f49dfbaa470ecb0a6d9b2", "SEC": "0422c2131d8c3ec4d5a29e536087a74ea6d001741a7a1bb8eabfbc26cd390620131f48d38e701d62a76ab52f8865a28c7af3f6cf88a54f669c0df253d6ee0f3220", "TP2": "041f2e80500d837bf81341f8e0f93fec799173d88d1fd9fd182fe107c61ae08ec609f02c71151c84fdc3f3df2d7b7be56ae1663cff90a367ec488b5e7dc612be45", "TP1": "0403f4e8efa0dd7e1c805c7fa75c7ac28ab9595ab61f9a95b671a34a100a7d45362199ae25a88a438666bd04f66859c40b72dc2e7e48cfb96eb0c7d94c431bb31b", "CS1": "041962f1a28de48a608d2036e3e22837fa79b1d0e1839856850f21f87c51570e9000db6180d79481131c5a7fbe659d2cc5399dbaa6c7cacf80b9342b2bd82118ce", "CS2": "040fc328129e1321573e116aae4161fc8bde71cc0073f38311809e0d4a51d2ed051c8061436ca7861ba6e0f5e77dd2fb3add0d0a42b67a35286683d966e30b5845", "HASH_MPIN_ID_HEX": "e9218268dc397fc035b6261a7b8bf52268754315ed6e411547835a1b3da0d803", "TIME_PERMIT": "0414bd6faf1ea9966d8adc86543105c698e7795557a417de6a626db5b3790ce8f92288e057fe1221e97654930852a290f07c69677911a0fa5a46ebe7d25ffd364d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223266643839303863663964646534646263316163633132376135356161316431406365727469766f782e636f6d222c202273616c74223a20223639343563396435333637386234373861633635626439393830623237343932227d", "TOKEN": "042088251bb3a5121d94a199185af5f116adfb72b3c925a889ec4ae058cb583dfa1f623ee3413c929b5aaa1ef7e63f34b98fbd296ef44b28e43de8391646473c0c", "U": "0412c53b9659e7ad533d55b43e54c9e3e6b512962ac8a0af48155e751945599b4301f3c65398932c871f41bc8a52312092ffa7db0cb0037dbc5c70147259f7df64", "SERVER_OUTPUT": 0, "Y": "1bbaaee3f9887d6cb3768139c111c087f99b11fd5fa75fe2da1024ed89b625a9", "X": "03104e488bd2779880f6540eacc06b5da3df0bc85dc954421e83571ad56270cf", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"2fd8908cf9dde4dbc1acc127a55aa1d1@certivox.com\", \"salt\": \"6945c9d53678b478ac65bd9980b27492\"}", "test_no": 30, "UT": "0410a70452a425f195ab4c59d95acf37d50d092d4943588396de625f2210e4104220d15a55ade2216c99e0e688d2a01e627a31610e0954e08ded8662de05768d91", "MS2": "0f9eab17fac6c67c5949ef9409a72578ce875d44a588184075d14d10be2d6b6e", "MS1": "201e0d647978e697f50f22a02155e6008d75f8af32f35f0f95f020574e16b951", "CLIENT_SECRET": "04036320eb698fa593e2ce7fbef881822d72bebc249d53b20fad4fdec14b8217d614717aff86705a83e7b76f391896288b02cdbc8843a130cb3c486d0865509e8d"}, {"TimeValue": 1437055595, "SS1": "1d465309f394ae8011f9d21ad37e08551af11a074b97df141c3704e6e6772c7a172505ccb9833f2b271bf861dd0d2bfc133d77b741d5e589bc9b8efd497e7a57177ad6b4c494f90ce96918763b0217ccdd4524e4105b096f85509e46805ef7ac08c5921f88b9646040bb47b5477ac0030e0d4839d0dcc28561780f492500b978", "SS2": "0da6b1e10f8873d93734a7167c47aeb2f3189c09f4cb5e95d737fcadb649f9c80e08209e75740db4e7dbbfd826aad116521271e003354d5e147a0fe808d944be10f59d565fe0bd82785dec84ba0d83047a7821a12d7fe72252e3a0a478a14fcf1d31388c6dd0f3cd08f9359e538b0c558e3b433660f6a942ecd2f5166268e437", "DATE": 16632, "PIN2": 3162, "PIN1": 3162, "SERVER_SECRET": "125fbd3665f7877caded92937d83bb2f9d090776d0aedd7ae7caa17586294a4604808a61aef3a69d523ef3cb7f0997c8f22d9c8270d66a2d692c7661010905571daea9730a06acedd23e1ccfd215541a3a377b55121abf38b7f95ebbc52eb63e1fada2cb352e7a74a3feeb3aac1daadc6c09b00585700b2b48bd1773fdcc906f", "SEC": "040765abb8b1ba09ac6f5471352d9552a925b8f7e1f18ecff5976341392ee7fcda0c83369261a05b95a7f4908ee7d09663c9c141f03e78a92ccba1855862444581", "TP2": "0410398c4d44be77708533a49e3d6a9a07efab3d22af5a6eb5ec9dda8b22f9546f22ba8b9972958b3e96fb5b9761305255fe9f1169add033ee3e67c335ec3ad749", "TP1": "040ce715dec0f779d1c4fb3f98c7d8ce271c3a9e0fcf22bb43ed67472d07aa2356207b157b52cffcceb326d9fa74a8ffc8f1a68fc049266db461da05d4d4719030", "CS1": "040bcc8a2d463fb79c8300787a62e5e9a0cd0ec20769e5ad90d5b3327a4183689719fdf1bc8461b51e8096f1aa38cd5c284a6952f482bffd1392535ed4ef5929dd", "CS2": "040f189e7ffa6b9345de3ecf0703f7568c7df3abf2b60471ce7d3efc89b0173efc0723ee4b0360d1eff0d9b381a46867e1fefad2875e3caa96f1ada10019ace54f", "HASH_MPIN_ID_HEX": "ee593c7d013e417bab619b9e343122acc348b7c18b93849451fc7a9d1cfd37bb", "TIME_PERMIT": "040a90035339c9a7515f265376a0ace51303532a7c401ab0a951388f557dc5868f1c458d7dcf32f96f8f861a3e1595468d518ba1e4bae7afb59507256a5beefb0d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223362633763636436393239323136663063316535653936653537356262633135406365727469766f782e636f6d222c202273616c74223a20223131633166663761323631353633393732316630343433356165656636323163227d", "TOKEN": "0414a7a25b19179bc9320368ef9c94b70597f509bd1852e3801258a30442d897be079bd558763c69061cfc43c2c4206dedd7a2d65edffe3be4a667a54ebbbb2153", "U": "040e2cdfbae98e9eaabe9882f4624f033d07c776e469245aa89f79aa70df6a7a5806ce162a5cae518aa1cbd0efe7561277356dc91eff5c0478c60c715e11a4cae7", "SERVER_OUTPUT": 0, "Y": "117b28eb91b886cd4bb7b02901c286b099234f901cc986ddadf2e51d7ea249c7", "X": "167f09cf1c2ae3c2048325b6d42e1c4d35a2bb68fa0cf327ab70bb3fe4d947ba", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"3bc7ccd6929216f0c1e5e96e575bbc15@certivox.com\", \"salt\": \"11c1ff7a2615639721f04435aeef621c\"}", "test_no": 31, "UT": "04197626a5c2688d498afaf2169c460741f7d6fae7f9bbbb5c3099678ae823d7b60f15deaa952be03cb440709fb937b2f343706257cc615c3841bdbf3b99f120dd", "MS2": "01ae92ce900defc0722364434077e78f84414825fe822750c7665c37d7099cfc", "MS1": "164eb23ed7c4e6225f4bb198469b4f5e00a22aaaf885dc8a347782f4242d788d", "CLIENT_SECRET": "040fc73d1f448f443b13303e3ec36d1e8dbd554110e4ce20bac7be53d9eb651156146706261c93d7918486e6015ab2695538121c8e9b12c82cdfb92604af1f2f9e"}, {"TimeValue": 1437055595, "SS1": "1f49d6ca4412372e1ab4e0768421e4f6bb249006bcdfb189179964d60ac8c61717900d0fdb5f79dd19c26e74b6ffc38bf719be8437f8a7f3656e6f4565084c5e0534e742040d2e75f230aeb8c9b9d788d6a6e42fde3fb1a801fa2df5a4fbb9081286fd56380ee1d274d4fa49349432fa8a8b4c748f0dd582e72e403d7b5472c8", "SS2": "22127c026c20b259ac7e51753fe76224adfabe829b9db899ecc7768a4cc900381e36fea902207938f4b131be8e0165d641ef543b33574cede95d656c1522631208cbd760e590336eceb7fbe925d6c6f30b25ada89464d80050da82fb6408ee742371da36bc57b081dd30e6b37038160a7be92b695aa4f834f40a5aa14138fd62", "DATE": 16632, "PIN2": 4050, "PIN1": 4050, "SERVER_SECRET": "126670c368a06296b366907da0096196313f67c5570e3d26f65167cc8d5bc6b418d088da207c3207fe9f4070b0840b31eea2b641265520c0a434d46f1698ab5004d2b8b28155346fbfa0be21b1b7bd7a6f132563e1c20e79e65ccfdf624723f50f5fc499347eacd30505236c2bdcc2a5f4810ca8afe7a9d82a90a852bf9c5964", "SEC": "040c114c842aaff729e6879d4fd6e50a8972ac1c46cb6e19843cfb3e94951a816423bf01335210b47e6a6017224a7557bd36063a6c09910d307d844fedc00dd274", "TP2": "0403d7dda152be9c72444b95992b1fbdf24921c36ab95b4cfe3a202983122a9fd01674f41a8c29866dad90a3be995208eaa0526f1d2f9739eb9026e46875bf4a3f", "TP1": "040bec9964c9148170d4fea199485f2d84a6db06f06b7dfba8f24125fc6bf576d10f267040c00f6bad7c2c8d041015ea936314aff5269ae0bf94ef1ce0ddf41ef8", "CS1": "041c5bd20c107bb436ba1b3423e891f45137e2f7995ab3101d012480b0c06db4731c6a4950e37a3b4e01f792a6b0bb0381542502fa367fac726e0f8852f1f68ee4", "CS2": "04214d371f45973b107469e907c9bba6b47bc8c74e7a4928d604e97fc1e8353ace0fe820dbb5fcc304c52d3623f60659d64f24b21467261fe4ee37daf8010b93d8", "HASH_MPIN_ID_HEX": "b2cafd2fae498b8129e646d70f3c323c8c200562d2fb4b53c2addd0ccf5ef1f3", "TIME_PERMIT": "0421e190df16a8e19f606ff1d8d437e04b5b94c4ad3e2e3457d5554e74b9bb83ac21895bcb79545b301c0287d335b3b4e2add8035abcc8e40920f1b501ccad8b5d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226364386234636637386136363663393331356632356338343333663037613639406365727469766f782e636f6d222c202273616c74223a20223066616563646232333264383265326465313264313636393137616537646632227d", "TOKEN": "04040c2e3ff4a984c0a9f0fcdc735c1561d67aed6fa9dd97cb5dd3f972cb80028203e8ccd234ef2e9a0cf9c771ab320d2af7a1cd19c062a4922965362c8b7c433b", "U": "041c08df1a0fb109b390d4491dc64553cd7ddef241d508c7bf50ad0e8f90fedba1128bdbef167bb7705ba44245536d355d308bfbd5b31c0ac3329df7071de75cfa", "SERVER_OUTPUT": 0, "Y": "232c1568a94f777027de0632aa6d79e41f0d10bc7c13cabf4a45ae76861c6a41", "X": "01e17c5856f8ffed235932086b2d406f291a031bbef952bd42a21b6e807a5eea", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"cd8b4cf78a666c9315f25c8433f07a69@certivox.com\", \"salt\": \"0faecdb232d82e2de12d166917ae7df2\"}", "test_no": 32, "UT": "0410c045f9b28e3a05581ca989bd2a42ddd93eb2dc28825eeb400b6887d50d3b031c6caa8aea6031fc6197d15d1eca57609acc46976707a78eff6f705bc61e553e", "MS2": "0f7c6fe63f28c503b12e52a52ecc97d303af20eed2a6e69671757ede2dfc33d8", "MS1": "0d8411e67711eb34d57ad88545d676cb92bd7ee22ed566697037d5c9a009b0a2", "CLIENT_SECRET": "041b543657beded90381c37ea0c05c7f1dd0d94e7999041a6b6d1c9496ff4d9f6511bcb24d1965dbb3ad863b10dd90aee61bfbfdd89667a2bf97bb119dccd73dad"}, {"TimeValue": 1437055595, "SS1": "0104099a3a013a32b07394273a927f16188149f5d20e4a791a2eb7939405bcb30b0c0526bc8b5d16cff4cd4fc74d536fad7f562477fa10cabbd5774c515a15b2185dabbd6956db03823f4ce9861c07e95e58caa4a249bd6ef4ee085bea56f9730605132e3bbd5dc847b3564632fbc75f56a784c73a3862fd944fb62014e98538", "SS2": "1374aac889b689ee3fef322c973e4f209c49824cf10d49803cafd4fd1692f8f301dcb42c13a0dfa8e115a41269db2e66974847ee20554a3f54e10db8ac8fe3421e5ba611b86d55076024fdffb3ef93a2999faebee1f9a038a08478fbfdd6d2e50380bb420ce77dbd29280cc84bd6fc5b3bb31c266279143523e0d3a4890d5759", "DATE": 16632, "PIN2": 9257, "PIN1": 9257, "SERVER_SECRET": "224afd7c356bbd6e5e288551a316996b280174758963f78f5845e4e494cc5eb8011c2ee9269d97f2f602de59361b1b699b1789f8b1c572ff24ad5c54d6633ca70b7c51a113acec31a6d559d0a9c9b2c17457bb2842d9e4e1bfccf7f29faa332818ceca79f5b634388185a56f9c3deb1beb95bf7adc258c1af34567ebd42080c5", "SEC": "0413e53b644fdf41dae31ca3d39fbee78675a5d36a71fcda9bed8a74728eb66d1402fffe7e144265e9cacc53f7ed54dcd8694ee05e3490b72b789547f93c479e39", "TP2": "0416c2f41baae755f02913a1e14b84920f2577f70f84da3c0181169d927aefc380208a23dd62d5c273bed925e5430b1edbefa9d4bf77ae5428bdcc137b8f39110f", "TP1": "040234826c2adaa11faf0a3e93bb25192216cde533deb6f3bebe1ab6596c0f508f17d416ec5864ca56814b7799b065351188d48554f96a8569d9b9d9dad3b91a74", "CS1": "04036e52fd7164584d9844dade01da4cc6e16963d9cf383fcf79ab8a1c81a74dca014cd670495d1092b756e39086a67a644e95f479d2942234fa9cc66fef58fe37", "CS2": "041b62214af43f92bf80c3ef6855199f156db27ea13b4b9c9eeadff1a5d7a8d1b40f8da715a924097eae7907dac1b7e6cfb83c0bc423f18d88122346dc0185c9de", "HASH_MPIN_ID_HEX": "44b21c062f02e107843f7321681e8bb99bd6a3ec5aec65b939be68105cfb6984", "TIME_PERMIT": "0418a27b71c4ee3582c82de00d651f4ce1c384b40ddb02954d70d079eac6e8f68a238507ae64b75c58aebf7fdd36cfe1fba3320c62c7f415186b355bba27525736", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223833383633313530646235356266393462363835663332646662666639653762406365727469766f782e636f6d222c202273616c74223a20226565383532306364383437666536656439313434653066303664663265613964227d", "TOKEN": "042180d2418dd3ec7c5308784b748968b9bb19d659ae32193465b0e17fa00127c41202c146605f7c1b8e14d9fcdd6744ae9d69443036543088365588df2bffcab7", "U": "040ed115f2206b828b1a5b05c8b47e1012aebf6af603d04e7c3368cc82477966a61b6bc66e2f91ab8c9314ef49e8c6ac2f8960720ed4c6b06d676c1eab329c1e59", "SERVER_OUTPUT": 0, "Y": "1840e7e3dc9e79f78bb56a774c1195bb3311d2d4b2248bafa377ecfb91a17988", "X": "1faed519160a762c11a0613ecb1514b0a4012ddabcc09590df385b064bf9f476", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"83863150db55bf94b685f32dfbff9e7b@certivox.com\", \"salt\": \"ee8520cd847fe6ed9144e0f06df2ea9d\"}", "test_no": 33, "UT": "0410adee6d44bb88d51cdeb5487ae038937bcbd4958958c36c5a2733766d18d535235e6e197dd6f1789338cb2f58edbb5b25c53006fe3b9224d1694ba71f89e8e0", "MS2": "189ebe018f7c17c3520fa1870ab82e7c246fd47cecf603c64dfd656fa0f658ff", "MS1": "151ffdebdfe5911190174b161be327d94d605d13009b85f265ba6a93cae24c42", "CLIENT_SECRET": "040234de22991a9faef574aa7c7d242934f8ef5686a50f278f792512f99ec838bb1486c35116b091e9064789e26d938580031d36a28adaf6442e8406874e56bef2"}, {"TimeValue": 1437055595, "SS1": "0a7587e71438e51da53121404efbb3ef0d50d5084d8fa3f05e85fb5b2fa434df1e260f257baf78a55c137064c36479b3927908b45d9960a6da3bb88103fbc3b011e13b175c63fdc3f715aee515ef04eddcf81512e7d483f77481368751982c63125bac7581ed907fa534b40d803cf282d94c0525e3f3dee51f07f9d3904ec8bf", "SS2": "107bde1c6acf16fcf6ca1626690a0ac63df782ce4595b7b6d05e3b211ef21e671d8d4d601e67c520e7d4234fbeeb5bdb47afbcb4912802a1a4f08667ce952ab40df1d0ca4113904338e6a33c160f2cc9f7e70fe24b8e13151587dff532b7c4860e90f97690c44fb9952fd3758bfe3c2711f48afa9af68393d58b5d3d02c1601b", "DATE": 16632, "PIN2": 2443, "PIN1": 2443, "SERVER_SECRET": "07c48f55f24d15f581191f22f317c493bb28d62a761d7ed80e5dce084683c4010473895448057faac094848c5bf8ec3e70b01263aac9adf085a19336835428321cff860957d7a0a84b577149427dc18ac923fdf069e2adb05e2d28871456cf8f0849378a7bc41f9683df8169eec25a72e0e63669f093d91ba7945894d0b8d1bd", "SEC": "04050a7277655beb1e98a8ab369690c20352a149e0a2986d3cd87f31e1f2362ab000da83f64c2a6c888c23cd373d89f4b7569c04a19b6f8faf777a1008e7fc316d", "TP2": "041cbd2f4ef659b4d3123cb41e0de2fa1895f1ac9c60d45ad4b6ba5d1447490a6607085982f3b36029a7833ffc14f48024f8fc9dc6b0c1336aeca6fb3bf505b2e7", "TP1": "04081434a3e85a806bd5c90969aefab024cc79025bfd066185a7facb9a5129e95a150390b4aab18e7c3cfe80e6aecc17e7b2e039d68f72f601c865b3e1f020af22", "CS1": "041690c5335704eaa8e36f6d64f5b25e67a6b71aa1a7c130737e2ffba03e6d120201dd3695025e34b2ca45e7f400c7db74ec1115c984a20beb1ab1a45b71820173", "CS2": "0417606154f62696e29b7b306125b981c8a8ad40b91eddec4b46341a981eb94a4f0549b65362b5b60c459fe3de7f892cd8e76dd9c77509f8e1c824d69e710f38b3", "HASH_MPIN_ID_HEX": "a3d84d1241f8dc40b9c2bf8a9644a05fa22fab7300940166fdcaa01b72c86cb8", "TIME_PERMIT": "0418661624295f7a48471bd9d116b3da90d1781d3196b2039988bf100f7e6ca25518d15b6121590aa7b5615878057338849fd00517962a49e2ae96d47b6d4104b5", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223361663338613437353762633937613136633536343833643866626338636638406365727469766f782e636f6d222c202273616c74223a20223030313765353766353866323364333633646130313234306264323538646133227d", "TOKEN": "04150786064468ab6913dfadc8c7aed87341de5887ea74793ac0ddfb4e1c386cea2032d899fe3d7f4c840ec0554ba170d4362f674656fb951ad3b16009f5f6e4dc", "U": "0406d15a3ed840bcb4a1363fb4874255efa5014c19fb7b6944691311906882dc311b2b1350ffef85d5d75aa60f340bb33f03c10bd9cc31e3ad971e6e63b8cf65b5", "SERVER_OUTPUT": 0, "Y": "12ddd4dd0d4202ef9ee0e7289c91db6ac17dbae4753f1cf0239513961217f0bb", "X": "2360c9958da5a46ced9bc6db0cce94ec3d8afc5a950cbc034ecd891b35281adf", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"3af38a4757bc97a16c56483d8fbc8cf8@certivox.com\", \"salt\": \"0017e57f58f23d363da01240bd258da3\"}", "test_no": 34, "UT": "042311957b7e3c15b8cccbb0b9945a23f61011ab1c70268a0fa4cf2839c77f2ddd1a749e8493fcbb38ee3c9d2c53cbfb31724a252b911b4b03379850982d679efb", "MS2": "2287d15fa1e9fd4a300f3dda4c748bdbbe06df393ffb020211368429a3a75dd7", "MS1": "12543a55ecf65a26854ea0123ac1a3653101ebf071b4aab99cf77e87bc0df77f", "CLIENT_SECRET": "0414d3f124169444f6cae50f996126d57a52e48606f3a0fa7c0121df89c93ca96d0dc0d1a43312c16b9e2b8fa430298b380a9a9d9cdc17c3796489961cb52ebc75"}, {"TimeValue": 1437055595, "SS1": "1cbb9e004144c61dd69f3951c1eb1c576c4ce9d9cc19aefa2f94d6febbf72e990223b510552b2312406725e8a5358ebddd01500e0f393c45ae04c5dd8c79d28d10ff53f30543c0cff4f53a4cef2e7ef6394022a3f217add8eebaf796c6b9fcaa155fcb502dfd9fbda63770ec11e795871fbf6780674d2baad248dfc960fb9c90", "SS2": "13f2582ec3ebd31841f5bb2e407e4b3458fc249b02c31bf6c088d36723ae0b650e9f3ed29172aa172085f98dcff235a71aa3f521bf3c70a74ecbd444c4de755e06471095b6423c319e6c2ce3911e59af7e89b47c0a3116c6826f23c364086f05217fc02bb550cb56fe4979b830f560c8e695ac641a20f3d151aea2e486dd3b74", "DATE": 16632, "PIN2": 9699, "PIN1": 9699, "SERVER_SECRET": "09831989c528340d8e93009f98c8ad06e25cf06ea0d37b4588bf986aba4a09c30cf1884228f835765c3aef1ce5469e7dda549d8a3ecc37fa5221f63a64df1ebd014dc48c3b788486d755623979b59bbea42d0c814cdd367d190d5054d19df3f619801b14009b00c8beecc54dd371de74d47753aa94f630f65f2fbff6a8df7aba", "SEC": "040fbbb722ef00d0fa9e4ab11a54a2541c7e25eb2430f72e3b1698c410c67064a520974f16e447ab881d8194ded2f57d18c9ed17cb97b0d967c22ae796e5d62e28", "TP2": "041697bf514aee344b218bcde90f8e7424ea74d5e563265b3190aa1bc3a71c2c211822372a6dcfa66e38699b342187537e8da98453db8728dbf925220f731ea902", "TP1": "0419e5f212f4d67fd7fbf9f3921399c398fffb3f5b555424621f82a51035b8067d1be44b5d6d44bf6f82fdc429d5c50a7111928b8df274386788d76a9d1347698f", "CS1": "0423be594e69b1a1b7b99ad75ce840f54bf7307b480cf1c4c18f9597e072195a8a2078cd475a4ef41b91217ccd2d94ac254b52c2e06cce443671f9bfffa17f8e1a", "CS2": "0414fe870ac362c5fdac9ef6ae458ca0cf8501094e6d2beb1d48767ef516bf3236195e680f37c1029cbbfa5b22e52cb08488b63150122484df3b2a732c48a627ee", "HASH_MPIN_ID_HEX": "dad30f1f780ee6f18261170daf67957f1d24152c85cee380e7020f0fd4414718", "TIME_PERMIT": "040bae0d3e44ff3fd8d8cfb8469726bc2cacec9e0b34e449155c37a23d482debef14d39a720775737e79f77d507d75b842a6b59897ac5fc9ab0c56a4bef44bd44d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223030333737396432626136396632363431613064663030363530393331333536406365727469766f782e636f6d222c202273616c74223a20223438346430306634663965633465613930653639323563396132613232343930227d", "TOKEN": "041a87f9ffc62a392d6b2aca2894e42c9e289385a410f5b57a7a033c00b9f2c3d70d681e70e06a88da7b7718da14be170e724f919ca28c05b4cc46e3f3307c0a00", "U": "04144298e2a1cbb3f1ccfdde4b858c0660f82c6fd324a9a27264b223a9c71068a320d1830e826a64a8ce72707a2bd6940349fc8a74db3b8441459de9c78189923a", "SERVER_OUTPUT": 0, "Y": "20dfd4ba1d2e887e05c0631d3a8f67a13cc59f4af082d5b23bf7b5312c708e92", "X": "1212e1e0b33d19d72cc72c6d5d0ad9c106850becbbf804a1b0f7d164e0e84289", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"003779d2ba69f2641a0df00650931356@certivox.com\", \"salt\": \"484d00f4f9ec4ea90e6925c9a2a22490\"}", "test_no": 35, "UT": "041fbcd0ac69dbf9899d4f4b9e0244d330830bb3d99b19f0e964bf71af0db6f1dd1c8b1ff6fcf1aeb3818e5529306375f76c21a51cd5656f6029fc5b88d5f6db27", "MS2": "08659eda01947a51add11fc595c19e67a5f8e4c9b4e360d6f8e76d30f87bda77", "MS1": "1bb37c9c7283e3fb6dbfb5ce8a7870533e45b982e129873e11a9b1efcd139066", "CLIENT_SECRET": "04185f288c4de40d4854c1b32d89ff16afdb566ca6e415c36f57dc2ac8f14e181e1920fa2ef9b1db475fe5f772190882875563b650cb0fe036e677bd4efc07ad6f"}, {"TimeValue": 1437055595, "SS1": "1968171cbf42dde6c5095654f64d0f53f8c48ac09a43b9455c91b5ec7623c05b119923aad63fab1cbb4496097698421be05a120b11abe88f2cf326cb5b2cda68100351319e52a1d52225855ab28d9fa323966115f902b10ad3bafd105beef1de12c585f4f70dea47a64953abb158edc86678231a7793c760859a7216de040acd", "SS2": "15e0db0e136c9080efcab81c245b7d2c40c88971e4756e75bdb7ebbce6551fa6116900fe4719b0687bf327c3ff08bb00152d943559778a2776fea0f685171241176302fcd00d8709036600334722bdc1ec81a9bc4705ee7c1d2608717e4d3f741f5d936a853479580ef2f224de0e7c9aeb173034dbe1e33d8ff4d0d73cd8f776", "DATE": 16632, "PIN2": 7941, "PIN1": 7941, "SERVER_SECRET": "0cf1c89289589acb3f9fdef9d017fe0aaf4a789b7a8cd9c92baff759a8e8b18b21870e77a59d3308f6bdd31fcceb5d2af3341095b4bbb7c4985fc86137a03534093f856aeb0ae690efbba2ca8adcf1f90a19e90c688c80e79036552694e4529f0db81462f85c56b7834627e674c836e202cbc4413f02e6f088345cdb38483652", "SEC": "040d2fa1443c068b896e3e05f383e475ee3e24a1fd5f6478a9988d42a23ebfa74a1965f924772a7834aae918d0408e0c442b31a587d2b92cb826992ffdc0b05a69", "TP2": "04239358bf2c90209bffe1f53ffbb4ecab5b2ad0aa9fb52622ef53f4dd4260362708194f851fdca990fa6e12c1c12a9fc1510e199dc97b0c4b06edb795dc15a242", "TP1": "041078f235ce79f72196849c5d17aa3c980eeeea91e4ceade2c72e9a33fcc0f22e15d98e09a1a369ee9c758b9275e9f098fbf30764ffc83d0709fad6b88fb15864", "CS1": "040ccbd6597d34c6a4f86ea93fbc4d47db48fa97c7d4c9797a078ca5506375fa5f057921cda38d562a932b796a5621ac4889a9363b996a73260deef2d5d5181378", "CS2": "042053255a7c220f620aa13e43abb22a54e370b3b1d457ed5993d2156d5a45c9760fa8361e3f95b5bac303b7731df004051b669f0d72b7c0457de149a42d44125b", "HASH_MPIN_ID_HEX": "7733a29c9bb62fd424cbb0fb8179d19ed13bdecd0edd59b4ca56c9dc2395948d", "TIME_PERMIT": "040538fb4ed8c583cbe478aab1f2429b1aeb22b9be06008fe2811a85962706837b02dae13452a20ed0d19646ac44c5a36c6c1827a2afbc650700bccc654a87a552", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226238313934613937323365613161633932343833313461323336336162303636406365727469766f782e636f6d222c202273616c74223a20223461353737363361333734383034346364323334623435373039393534303830227d", "TOKEN": "040d7118fc13e24285f00197225e172c8fd32685d90f2e2e140b3d0c916574d509052aef5cec8453de1f303640f383226295e9378c1882439c6fbab86025f723fc", "U": "0412cf4c17f1b7fe80d6d4e1f802ea75d9f39dc03eeed5c746ae99b1095268b52d0be03fb696d38ebd9c05c43b14cf4952dce2a53571f2dbbc2297770a633b07e2", "SERVER_OUTPUT": 0, "Y": "024974feeef5935483ef1afaddb0d283e8c9c2bbc9ab17b66b54dc114f6fe31e", "X": "07fe24b4c634d6a31ce5b7b847d78135e98ccb02d16ab0ab1eef606d0eef0e51", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"b8194a9723ea1ac9248314a2363ab066@certivox.com\", \"salt\": \"4a57763a3748044cd234b45709954080\"}", "test_no": 36, "UT": "0415c28417b53b0a9a8d644aa2dd9fa13874e9a415caabaf6b16f2047571908e900e1316e63c83bf8b42e978caafdb35057fbdc02cb041eac7ceee7636122ac176", "MS2": "10d3ba2f217edf52f172d164f1c5446f5f30cd4fc1a1e3423759e52651facc3e", "MS1": "05d27d4fdb6399cfcb8dd3049afdfc824c8ad51cd939bf524387a341cebef512", "CLIENT_SECRET": "041319c01090a89cebcb94bd65b142e4e0b389a68e28090590c98dbf3ad21d0e25055e4572428b39b256dd49e21f4d058e988fb615dfdbc0194e003f131a888631"}, {"TimeValue": 1437055595, "SS1": "10b32d10fc4df62c303b99ceb50538dad93f4c235333bfab0748464981505d1912b8e954b5ed54b9e487041c8b19cdfb382c3715184cf8c37c518ba671891f3004b30ede5590c7da7d1bbd7a87406fdf470acc12bbafb5445ed529995fcc8e6204150b338def7e28a295c670dcbe22e0fa83715f21f291c27ef5d2ca70afb7ec", "SS2": "2074022b0ae6adbb8c6d410c1eed4df8484e4dc473013a873cecf13a2df707ad134f4e59b5e90b85365d8f8aa3aa60c10562bbfdbee281cfa8425e0425856051029dac1c25a7f1bffb84804908b9521678d399188b0a6cc5ca6e877caad3dd7b201842dd9f615c56634de3e5e951c2fc644407c9f8601aac0ff0c494a34b3e57", "DATE": 16632, "PIN2": 5123, "PIN1": 5123, "SERVER_SECRET": "157fddf51850b1f37cb616cdce74cd3ef8ccc38cee24cf51e29de76f278891031a2a98ebdbee9a5cda928c322ff4fb61f1e2e990f4d56ce702a57fe8ce979b44029a876c09cb81dbad5aae5734674971c2e78b5ce572c69c31e8f99b3ca5f84c0ba213a366fe685e771467649e15a83cb0fd5d4669f30a80bb7a7e4bf08051a9", "SEC": "040709587d3f3c364b2fb64f2c142ebb22ca41a5bdf4ed20d5ece76b5d9b16559c12292e8cdfd470174fbde0ddf57a16a9e6f0051a937b58c6029eaa1055ef984d", "TP2": "04156c927410349fcb6d3cf85fc588bad165c0f617e9b32735de562b16307af0b900421e6e92f5e8542341cf2e751dcc75be70c5130a0c295c7279f071b568191c", "TP1": "040cd01458da6c1c4062207c3111f311183e7e05c046c39a89ea61a7f1861445c4078519ebbd44089a43264fd22659f913061cd0c325dccb8ffb8bff82851c9d21", "CS1": "040e53bec726ecf161fabec2fd0733a70ccab53a664261addadbe7251ed5159a6e0ea6009da23cb932bbe31c88e85f3c348ca2ec3e0025198756ec4a193cb6174a", "CS2": "04087c66465e5b79613f20cc31a5e585633c5d4c32da9ad8659935f6017b9f548a0554ae69af6b7b5361dec667b7ee64c9e06fb76f0d202103e67f52b33bdb067b", "HASH_MPIN_ID_HEX": "4b6f91941338c28a5e29b0715fb24aac0dcaacfc9612a34e86ce258c0b5adda1", "TIME_PERMIT": "0403f6aed072cd74e17dfa79b3a988cf16b13c9082a84ac9b94e2d90a7dd7710c219f2eb6393bc09fe4745e39a186bcac0ed76863f38ad8eb9a01ba570c526eea0", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223635623466393961656339646565303031656665393566653434363131396663406365727469766f782e636f6d222c202273616c74223a20226166653563303763313137333936326236343734383165623037616165373335227d", "TOKEN": "0412c207b268114f583bbbefce86c72936a31cbe81e1e9a8feb00a83655ae3341214a54e81d26c07ac1ca04ecd5d683303a9d281d916d7d1fa092ada3e7e64c363", "U": "04014abbc90317ae53c427dc519c964137d591c5a532dbdceb5d0ac30ab613f54d201de833ac28af8325e56a75365ad6d65f8be1827fa17ae6b386e91be9fe9922", "SERVER_OUTPUT": 0, "Y": "191667a74ff0b84f33ecd9daa17d445023cff498623756404130cb508b286c84", "X": "18ffa1fbb3b0a6602ba4baf35edbe574c8558c9266f102bb95ecfd7443974bb6", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"65b4f99aec9dee001efe95fe446119fc@certivox.com\", \"salt\": \"afe5c07c1173962b647481eb07aae735\"}", "test_no": 37, "UT": "04187a7c0f99fba112252a686d47b5eaf007323053ea7e429c1eb89e4de8d4349413d8dab20694527585095f08bdf8fef422e8b624b7862eccb39605bdb2f448eb", "MS2": "0213de3c4e03528cd6b9170955e35509e7d5ae2244a8f6762448d46e00ec546a", "MS1": "16e249ce1b2b2d47a1dbed905b7027eed91248537a91a985a3775d266c60aad9", "CLIENT_SECRET": "040e77350a02b780ca3b722dcd0ed12dcfbf20a6909e746fa8f4ceecf0511965af1d68a248c93156f8ebb0b8d46856b0e73b331ee27d4a87feb04fe2be4e5db6e2"}, {"TimeValue": 1437055595, "SS1": "13596507058f46f5da4cccade56f561fdb4ce38791e81cfa9c825c39e40ecd4d1bf948b2b78f53cca66f723463cc17d36d0dbacb6b64fc1cfb6ff1f9e9fe254c1cdaf63ea31fa8f61a3f23723c472a8b2880cfeabdd88157288fe110d97551d500ac4fdf989dc8d42d1dc74a3c6583192fb61ad0bc690586d10320aa4b6b541b", "SS2": "0e92ac9986b50ec25aca1582c71cf25bab90bc78ff26d0804e315beb4f65486a0323fcbfbc03db2ec0cf365b80babe361ca24a5b1089fcd5e61f516549bab1231053a667279cd9437619b559f6b75b5206070d816b3797e953a953c509a5b90b0ec97145de264acce630db0fb6f57cb08ac6decf772bfb5980fe7e5391cbd50a", "DATE": 16632, "PIN2": 1957, "PIN1": 1957, "SERVER_SECRET": "0ec9929b046b6f41991bfab562f76b00be8c4ecf1a965e46e50f4ddf6501db3121954a0f9be1a00c19b35587076e202a89d5d372abf99b8891a8c17d0a15dc7d01b4a24b5d9890041fe8323d425b98ce7c31e9facf1cd58b893291912cba57ff00bd03dde7d8d6cc9e4c4e49d0ec55a1ed729dc50a370dc6348b589683727f73", "SEC": "041313b79f58d4250af361cb9ab6e93160521c4a62f24f20e7b7bdbdcab59d793208124023203c18a5dccbde9a3c98afdbac776b23282a8737bc6c9f1e299bb250", "TP2": "040ec239fb8fc496c2f41e0f62b904d9dba04ab18f67c89bba1214d26092599d860190cf545a40dc19702ce19e2ceaa15558b39b4d185faa83f37f50f108e259c7", "TP1": "040b46bc2682c8ca9ada0a2f57591397d90dd492a59b063d9f598ea248bfce9ae10afea35063cea9edf33a41551d936bfff70a1ad3512ff7434b54bcb42eb6f503", "CS1": "0415ae3002b1bf3963df072d474b79d772109399fe8992b716fe3d374ec8181eda1e201750ea65454b5923a17e7ee0879abff53f83fc94dc58646f6f23c860c366", "CS2": "041ac5dedbeb18663ce62fd307cdca94fce2cc4a0d5d33af079a292f715de4b4510b5fe7b4135fc7c274ea19be339184e1b13c453cd5b6454ae8d8056b2ac0ded4", "HASH_MPIN_ID_HEX": "bbd7b2c6dba19331dc76b041c8ab465d80b8c2194e337fb05973e8539a8018ab", "TIME_PERMIT": "04087dd53d7dcdbe8f861729ebf387a01e9da937335ca6ba570fe3ba851f0e918b0a021cb7084db2dc69b2c524105334b98e3816e4687057bb18930f48b3b3dadc", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226366303534613130623537323438313637633837336466343231363962346336406365727469766f782e636f6d222c202273616c74223a20226362303163376439366635316466646238313662393134336133346561326533227d", "TOKEN": "040c518a500e49fb6f260ab32737d7aa0a49ee1eb4318cc1465e6ebf9e7d72dd1614c48d470304844b34920977696d14a5b4276472280b5a046efd4507cdd14315", "U": "04194c3409ac17bf6295679360e49083bdcc9cf36fb23c016f1cb37b8dcd5a9ba607fd2b3b95fc1a88df72bdc27ad39796708269f9499d1632943577f203c989b8", "SERVER_OUTPUT": 0, "Y": "03b9695ab81f1e4c294c17794c691d0e7953b2e9722944809cf2a40c2bfe6c4b", "X": "08a6df8914e474860a441aaf4b814a86bf3c117ab1a089e9cebb82abdd07a089", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"cf054a10b57248167c873df42169b4c6@certivox.com\", \"salt\": \"cb01c7d96f51dfdb816b9143a34ea2e3\"}", "test_no": 38, "UT": "04105e10ba067fa738bf5c58140657fc5c85a093f8209a94994a898916114d1c551ba505eca9cda3f38f53d69f07c063349d3b42affcb86e4cc51ad8d0374cb13f", "MS2": "00f0aefca3928724f86939fce271cac9c250539a2eff7588cdba83667401b901", "MS1": "03f6d87c2de822fb2334c9745f71a930090378399a3df7512f521f65a9eeb804", "CLIENT_SECRET": "041afc2989a7fe73fdd63297005841c6f7d0bb5d50dd642fdb45d3ba2d2e7242b50f88d422184ef146ff208ee8bcb790558b3b29ba5f73adf808c586cb44257ba8"}, {"TimeValue": 1437055595, "SS1": "08a2a6404689db88e357ace47c8cf9a5539c3628fee88231dfbd3b410d1abdee05ec217867391b99ddd1af1a81d1aa44b0b67c37d6123ca212b57e794c3ead461cf4f33f2f3badffe99851a603aaf91fc9aef5efd28d0022ea9cf7101f7458722087e39325a67e1fb19458f195ac46f24f348b1c38af2c1fd510ee2c55746596", "SS2": "0b232e1c26f0be42a545df0184dff1f36f720d453eed831ea239db4f22f476c8006d4495950b8c176fb0ef0f5519f74402d6bcccf03cf85158e94da423ed368b01144f41e0e64c681fa39664b82fa4f823786d8422ab6b23aa7e1aa424c25086028c1e51fbaac6228d9c5bbc1bb6d5fb8827ba3cd025b6b517a9770379336e92", "DATE": 16632, "PIN2": 5486, "PIN1": 5486, "SERVER_SECRET": "0aa0e371e54939b5d5dd273c7daaffec4fcb3a064bf5156168e2624afb5c25c21b44efb82b3be76cb6751b3ed844e6bf4dcee29d160f5f60c27e8f67ec1bda390036700d0e6ee90fe7cee3280fb57b32b00772ddecc0a7415beb452278a7191517fdd158ff903b42754c6a25b098ca665b1ef1d54cbc653b0c3792d6ad2c9c91", "SEC": "0416dc19427f26cfca296dbdafabfb4aeb12a95cba5086a23c82e9d5e086acf647067ad1c253ee087965d27e2240b2a3f5d6560a81cc30fc70973036f39b6c8b91", "TP2": "04225b9cc4d88be43b852fcef193ca07469f64f75ded58ac28d0eb2c71f40ff9500fdb80fc9c9552c12d31a9119a61b229a956dc7013bb294a023b298d4415cac9", "TP1": "0423fbe89b8c7a2d5f83a4cfc97685e070781665f2c1228143baf39dd842f12f052162d9c5adb3acb5723b539a6c88fa81b6bfbf8e3fe5371bb3dc46e8ab39272d", "CS1": "041c904b5e9a475d4bd996d601f6f0fcf7841b5b28cd2a8bef1d44a4f1ee4648ef015f56d31bd198019a5826417720d635ad69819ed1f6c6a01fbb41c6d7c72983", "CS2": "040aba13ad3f6832030ad2361eb94d266a34f3eb3bb1475f38e594ee39b8d6091e18cb9a997e7a2598013f970b4e901309475df4602670a18223295dc07a8b399b", "HASH_MPIN_ID_HEX": "cd968159425422e0115d74d7e508cc1bea4d2968a6dbaa4bfa6598d5b4815797", "TIME_PERMIT": "041032ea9e65f57d799b9b10a70e290fb4824d4f12cef0c4f585df2eab11fe741008c739adae59d00e7564b88c4be357b7329d08df29fb7bd9192c709010b23126", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226534323463383562613437313738633732643031656433316164373666333739406365727469766f782e636f6d222c202273616c74223a20223366303333653730666561326664376139363264613333323663643265666335227d", "TOKEN": "040388b80e46b7d314d864c7be25d35829764082f0727b86d9b81931a089af1ed8236339c1b5e5eb62a15177e6f64c88fbd13e63015c06d81ce026623a8527351e", "U": "041cf31ab0ef173d34b3443d87c1eba5b751c39d77c4832a8f31e9a4827186842a1bcbb6ec9c5c62f544d9dc37a13e1981483c436c26e2df3229b38778909feb77", "SERVER_OUTPUT": 0, "Y": "04ba899f164095bf64814b428f81b920c2bd333b7c440220a49d2cdcedd6d895", "X": "127d39010725d4645ac79232562f9149d17c4bab46f8165cb08747d07a95bec5", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"e424c85ba47178c72d01ed31ad76f379@certivox.com\", \"salt\": \"3f033e70fea2fd7a962da3326cd2efc5\"}", "test_no": 39, "UT": "040cc936ca58944749c26d4b90ed9fc38d0395e09fae48741154ec5a9e47e295851cf4bc33634f1994244475a8e8a6ec1ab0dd44cdac8d17455b6661a4b102e52f", "MS2": "192286397170671d5b100b8164f4e2cdf45fb4a1f7dfa2b7289a3c5c4af1bcc5", "MS1": "14ba1f9a28221b2e03f5f707ced565c5cee39268e463075e6310470b37ea89d0", "CLIENT_SECRET": "0418f71d78ba57c2a74b9096c7a79ee643a57996908d6f02446edd71559d8e6b7f014437196915d8bfe207759c3a71bbf1b9868bfcf31706c5b132b174dd87339e"}, {"TimeValue": 1437055595, "SS1": "016a0325a594083fff0f3bd40288c6294a8c0f226570a3ab42dd1ed6173bb6f4074c5fa46d38cf601de264e2b6ce7a8a379c44f5096c22c8a45db6712f3e39141aee2820c43c982381c77d23f2a52cf38b4fe91c6101ba1290e75b64cfa524770382da0fb5a14a7e0bcb4c2f59f1804d76777fdbd938f9b64f608b7501e9e0b1", "SS2": "1bf676a0a310b4b6e1db46c397d185a0bb08f72892ab7511c40261b015397c1605974a6a7b9ebceff14c318a1ba879a341a47bed0697af4cc918ced50c01e895079f6a28a2af7a50e409580777e64a892b387b3b10a6ca16d36dfa5f4dc31adf025fcc03da14d6d4b65302b17f6ca39e16f78f188d0dbdcbc9a0ca8d9e4d2c1b", "DATE": 16632, "PIN2": 393, "PIN1": 393, "SERVER_SECRET": "0fa3f54b6c96a8fec36aa2c36598b129ffcf575ff22fd861d6799a9ba96adc011eec688b4f792046aec1d7709a0bdd07e80be7678a6a3145ed8b674d74de5e06062c7a72b586af9c64993dc9118beeb85ad4db7baf81fb1d8d9015ff614ac74c222b5f51ef0accb1a43e8338e4917d29b6450853d050874c9801a3aee03349e4", "SEC": "041295b0be7356cd80880eeeefeeae4c935cebc450e505fdf13d294734303b6f931edf1481bbd9f521b72833ea5d4f111473ffacff0f3284cb4b23030d70fab193", "TP2": "040872bbb02ec8620e46c31584e8f149ff1709747647c5af6092ee05388a40bc850d12a9b4be4b3feb498d49e8b59a249bb9dd7b9ce75c7b2f15bdfe80e466ae66", "TP1": "0407be899ee57ce53ce6038e130ea2713975f06e76c1f4d1d8a009841986bbea38074de99192845254cc3b5d0cf3b8cc3142cf3b85d66f5f1d95c71a15ef8ffa35", "CS1": "0416e0b21637e1b58014adfc061c2f815d4a62ba33fa43042e9d9e7dac100ae255019e9eda994a00620a098b547880925c08e1467defff7085cd083046b1bc2bec", "CS2": "04212160a152c13b0b7ffd9b084783340abc3ef230e0e260da1159e7008e387ae10a75de1fcf7acaf3759b55d2cd94b1251c61f333d22a92e9e3de2805e6617a3c", "HASH_MPIN_ID_HEX": "44fba9946c555eec7e42545fb29b0d0f0915f9b48dd5bfc3bfda5ae5033f7aa3", "TIME_PERMIT": "040737e503d6298b9da718c9ac0673439b580b4e28165bac64237c55b759a51ac41b855610f6b003898a4b9ea1761eed5a9d3c143269281980281e528abc2f515d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223462326464613639393736316234353130343333346335383364336236633832406365727469766f782e636f6d222c202273616c74223a20226233656138363830613832333636656465363463336333373966643265376566227d", "TOKEN": "0410336ea9e2d854f54c8875609de4a3861010cbd22e03f7557a6effde6fc64788061f3be87e0ce7684f5f75e6d46d72282ad8b54dc50ee18c008afc01b4cd5d2d", "U": "040380962b3f886409680e8706aee7e3f9251bf18e76b5b730ec64cedb9511183202f21ad5319653ce468f034999b08c078bc601de776228e797f280f251d0238f", "SERVER_OUTPUT": 0, "Y": "0893829eace8914262d1075a3b00162eb9f76b3b4e8ee619629dce5b5dc15c56", "X": "10159208f18fd3d16087841146e43eefc98e2da6b3cfaa7ea8598f2ee18a75f9", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"4b2dda699761b45104334c583d3b6c82@certivox.com\", \"salt\": \"b3ea8680a82366ede64c3c379fd2e7ef\"}", "test_no": 40, "UT": "04102690fcb4a6ac969a401bbfc6b47ceb90c23ca359e442a3fcd7b93e46ec97940ce7872281bbe0dfba00f9d2e3bab5e4333edee748bbcffc122d68c369bcb8ac", "MS2": "017ceb3d6e52e40596c7bff315f129aa08e3ab21d268ef860a9d531809f029a6", "MS1": "028b6d45ead8a197487542bb601930d4b2c6e53f88481c7d0e329eb2e2e4917e", "CLIENT_SECRET": "040d8d7a6f7dca5385086bc6094d836d36becd2a2a099c2dc6208130017e4904530082c0a5b782c9c624dcb7b9412ea588eafce0ec536aab9a17ca68b71cd726f4"}, {"TimeValue": 1437055595, "SS1": "07949815ce4517b6c4d167abbb322b03ca26fc6540d67eb13c86500b5e78cf50202a8be7b834e1e39950c9a5fa3d228b53195f65cdcfde5b1094fb288fcca037104b5eebfe9714d13d1301cb97d186b0d1b15d175c19af8aedb7d9141a9231970e8c81ef99ad3efc29c230779a2dde39044568f17cbe453e2cc5d5d30cd2cb8b", "SS2": "20b657d70512f73849b96e75e62a6b2b46687fa8cdcb0369f6ea59ba505118192103ecda8564fa4ea8db0897fcddced4d671969852c7ffcecf58fdca71b4af9d0dba37fc0cbf76d0833d8ebd86ddbb64c60651165047be9c2dfb98018c0aca7d0651bf56b8f6e26ff603f4e6cd7aee9c5fecafb58527bcc0aafcf3eba5e8369e", "DATE": 16632, "PIN2": 3858, "PIN1": 3858, "SERVER_SECRET": "14436b903c7943f7a3125371eae76bb0c1d27112398912b02d5f2a2e39ccd277175fc46ca18bf0e9c1380153b76b9996a49cc5f8cb717b99763a54c74aaaacaa12fb502c3d78704410ad937874d74a7f67110850dc88784521a307ae27e20a690134554ded346418e0339e36c048a2d0eef1fa1c1d14dcf82310153724542075", "SEC": "04185690480db61260283410100c4813d442989b93ee9d6f5b640ea4f4221d31b00dd49f1a711f38408d7b62107e78fd72922f2088cca80b798931a99354c7c4c1", "TP2": "040f9ba5f010d6478f1010cfe3a61c0a98e62ea4bb0d7c1965e98d8bfb0943804001b3503f57df31c1cdec14f160319e45f6c3564ec6dbee293d98ac69ff9f7d8a", "TP1": "0401d15b9f984cdd58f17429c6160a0b7495e3f3531ba07fc77d5a8cfc0b3c04ab08ac717a4dbd44d6a4f31c3e154056255b00986dc69cdf568545b21bc00aaf94", "CS1": "04233d8567d7b5cc0d030fec7c495a728df895369dda9ed87d2b3798a44743ca180dd65c5e695da7a622e4d6cbcefda640b99d533069955c3f5f4a678cdedb3a88", "CS2": "0405d99aa0efa6e6b5ca6ff57c146f358f0030a738012215a9a8cf48994d0c5ad70823adb30b214392dae0614d99db12f2178da7038338ca18ab15a7db6cdf9d49", "HASH_MPIN_ID_HEX": "942e5136eb5cc410bd29503023408fdb9d6ac94bb86d1e42b5e7415ffee69bd9", "TIME_PERMIT": "04018180ccbbf5ea3f0181e57e00be5fddf6c9a2866447253b4450e499b6883d1f1361b8a0c715663fe4f030b370c2d4b7a19ac103602c1f3a3c6735fcee9ff9a6", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226236633639396636336636616164326136353833626232613637633763626235406365727469766f782e636f6d222c202273616c74223a20223236323830303139643666616334643563356433363065616362383036323130227d", "TOKEN": "04181cd4dbb3e5763fc41bbf0df549f61ae475b2cda88c6f7254a61fbaea1aaa1e0401dca7c3939679c926640ba8cf712dc19020ed44460466fe7bee1c9e05eddf", "U": "0404bde0073743f28a77089d67c4d57c19e23922cdcf17007c7455ccab8509198110ea02a020cc27a8e19072ac52b599019ff063ae60dbee3585ed16cddd538907", "SERVER_OUTPUT": 0, "Y": "143e6cea01c6537db9f20c16761e547e69913544b1196e65d05d0edc762b8b4d", "X": "04011571b5c66abfb9968284cc6ffebf3b7d9d6f06b5d570dac7d8016aa10d29", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"b6c699f63f6aad2a6583bb2a67c7cbb5@certivox.com\", \"salt\": \"26280019d6fac4d5c5d360eacb806210\"}", "test_no": 41, "UT": "040f6d2456ea2c96ace4b00a2d15d48c8fad5d8322f9f8d8de0fb2b67b92cdcf3c08cd2e981c7b236651a235370aafb1e261ea7a81c46d4516c645872483230c48", "MS2": "0828454fa97e8043867be4ca09eb6dfd7f3e3524bce0ebb8148aa2fb9b88f97d", "MS1": "15fcd026cb971668537af02582787f95f487b2c09d181cc9198b888d7c617924", "CLIENT_SECRET": "0417ee622a001d3837c4f58a1597beae097e88ad0553b9344d478dd8b3160195a2032d0599febab54c87480a8d3203f47ce532a0f5a9db6516d5fe7683aa1f2021"}, {"TimeValue": 1437055595, "SS1": "0039a25e755654857677f8cadc5efac6f919ce5176952853ac5a601f5b8e920a1b07c589429e83969e8e7ce384ea39eb7a7355e119cfaa45751a61cbc7aef6ff1d4b903fb23d034f3c7e110dee1f1635b999af3c8e8a9769e2e63d919b66212a098901c1309a4e3dd50625fb06b81fcbf7e66eb2aa7b4dfb0ec88341f04dd25b", "SS2": "10d376f3659b74757f9a40573c457e892bb1444f83d7e70d5d0bf696a1c2208b08bdf796f60252bf73d30eb605f79bed865460849de449b0f51f5bf34fefdbf6038fd882f05dc314ba2dfa32ef85353f2858ed07dc2aaa7ca8fa467a217a57200dd33e74e3e0b1ab3d65f59875f6c2d1d82c79ae1e0a2872195aa134745fa4dd", "DATE": 16632, "PIN2": 9718, "PIN1": 9718, "SERVER_SECRET": "163cb63279b2a0ad42cdf63e74e7be832be430c3eb4920b0d8f2f9faec3f7909069bf4d364d6aa60d27469efd51081ea720e6b884c338646975b1773ac2add2d1cf8efd45f014b8cd673abed497cea221df41e1e27734e59fb16fc022cea76cc12a48168d6aba3425747b7f82b144c21c819e4b00e1bf2733181b00c099754c7", "SEC": "040b18de2066a251318413651e24835736e4763fd529189abd21b0f2342f2780c601952edc03d7ca27228785b936ab450776d7f11b47b5c1a30672dda958b02b6b", "TP2": "041bb1139111bf8dafa43dbf515fa3ddb75b34c7086d4f8416314fc66f8c484dc610cd69678861e92642f4a285229d8d1cc8ec97b14400123fe4281dfdbad32b8e", "TP1": "041cfa8a6b41eeac318f9b80379de2df68eded45915e37335e36abdec5e3b27cab231d8a7aff8fa02e6e9c45f4c63979313df47387e7baa500307bfdb9961cba9f", "CS1": "041d103a7acb7a216ec918b220398d915d5b49c8154a02df693d24e1c0f08869ff0fc11e9323aef2347d6c82c7025a93b603ae937b89c7a773068da02519718fe4", "CS2": "0414cad0e6de68f8c10906ef2935b22cdadccb3376af9587afe8fd9f0660dec0001bb931e11d042156ac0e895af3d90c31b3794fe80ed0f5796ccb9e5aa2fb7967", "HASH_MPIN_ID_HEX": "85755d523879077fe77780fa0341166a38e7fd72ddba2deb482156b163c9a9b2", "TIME_PERMIT": "040b65c54e6b0caeb52844ee313ec71e1e78783ecf67f1e71d72dc632174b82e7a171d101f2be5c44f9f6e920d65b05df653c5e585d36c6ee228fe8ebc9a1834e4", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223266363937623433636234336539303731643135666664386133656332616434406365727469766f782e636f6d222c202273616c74223a20226235393064316337663562646161333830643363343033366437313737646631227d", "TOKEN": "0409673c08fe06e22df49187dc94d8299512d2d496fefd83e0d82f41d0d43c786b1e8d56b29eb4feaea6eda738347cff3f62ab55c99d871329c45fafe3321fd34d", "U": "040e0d25a0feeec9b2f0719eca553a6de892e7dcf5c96c1f3f056f2b09065d8c3c01912aadd58975924ec8586c54672fb03b4380b9599ba28112b89d41142c4e04", "SERVER_OUTPUT": 0, "Y": "190a06338e696988240a7729cae04bd20664987605b8b39b5fb35ab024934f1d", "X": "020ea81fbe7d9af7549d17039ed1cd34400f130d089609fabf227e772046988a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"2f697b43cb43e9071d15ffd8a3ec2ad4@certivox.com\", \"salt\": \"b590d1c7f5bdaa380d3c4036d7177df1\"}", "test_no": 42, "UT": "0421e42341617dbc320612f34dcd696346f41774a9bee85c4f38353389468a5b2c1d0d8a526b750157653bf0dde0bf41102f3724dcb271fea331d6fc3a296265be", "MS2": "0e44a1a41b8e6205c180e6da203c7859ae231dba7a175e3f106e40f3a28199bd", "MS1": "036eb5fb8af902d128405084d4f543fb758c01f0d87d712c2dbb238e762c5dcb", "CLIENT_SECRET": "0400ed326d905b35f796b17c67fef8f3582b4a82f60a913f839b17c8e4f2f62f6f0269c2d175e09a1dbe7df4cbb3e2154f8e42a0b67c91cbb038ca2fdddd9cb378"}, {"TimeValue": 1437055595, "SS1": "13d420d9e50cef94b80a6c4ca6a800db93719fd478ded8496e94082b221e3a1303ec48f72af5bbfa54ba73ebc8238cc2f6e903446c269a1b0399b63c1fa176d51b70c5da1ad7c79202bc2a12be8ae46dc3bb771488681357a52bc28758103f0c1788165604b987749ac6f899ff6d3fc1c46d416106457df4a4ae15474d2b34a7", "SS2": "1da2c022eda9530f66e6c85feddcebbdc29b7c84ca107d679bedee0aa08ebb9f08d16490b2e754a51a60d68f42dbb1383f2dce829c0a39b12a5bcc67f56c4ea215872e339f301f1b2d37ef3838382f4779ea51516082f36ed45e2b8d4a3b135e1e7ad3c87faf427634bded904fe4557c9d1f2d1266706274e30c3224700a3fa5", "DATE": 16632, "PIN2": 7476, "PIN1": 7476, "SERVER_SECRET": "16135e7df94696b892d1e9b9d37c53d20963e262c7b895bf9810394a95794c981878b4f190e9259ca8571a378cad9bbfa19fa42bf1960d4e43467c3d5872b53c1b7b49f212c4cf0ed477c072b4e2ad873e10bfd1e4cb6c7fd4971e76376323160d592bd16ce73971b4bba25b11ac101b8db8584a52be6ada07726d3fdfac59e1", "SEC": "042160babdeea0c1aac893a69144577bbc8bc1c0658d76f54f4c9a2ea1782d786e22c33307dec2789be912394950e6c2694afadae15df044eb2814485acbcdb463", "TP2": "0420c9a7149f81a06680eaf0b913c396972ac86f977ad4a7df07aa8c012f4d67ed20f0cc23dd31350222384dd297200d5184cd6220ef88b4dc0cd918022900d50f", "TP1": "04179a0272cd4cad8a5a60408fdb672e9292e57520fbd298f391f4db8d36487abd20987821a2a4995aa25b10077b127165e345374612f99c5fb5b7fcc96f3fff35", "CS1": "0406b6fbef891b9d08d279c40cf87c091dd466d52fd47057c0e197af2771a4e1c91040a484337429b25903161ac0d4af57b5346c7e0afc589ecbf1f9d88861c1b4", "CS2": "0400940d58340a4bf29bd74849c9b18446334a641661c5939875f9a5b6df3c6dd1018f74d94907bf0362f67a1af0995017a1a15da86674c2f9d8f4b91595a451fc", "HASH_MPIN_ID_HEX": "9766ed66ccb2828f2266b08c97eb6f51a9046ec75448697b8e9ef35f851b399d", "TIME_PERMIT": "040e9f4646af87d24ddd45f11681a9c906a93fc84b8fb180008ada4c600c7a3f151045b2c16f170bf87b4cec81a30b0b5c9f21ab28043963fd0f838f476ae2fc8a", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223137643365633633336133643437363236303338343830323763396535396132406365727469766f782e636f6d222c202273616c74223a20226566623134353530643038323630666235303632323530613633333061303363227d", "TOKEN": "0414b172cf69c9b3d8752aa3eeae99edfd534d8fc086fc6e5856c91284154702d20a774911deee2702556ad6d3f372489213aca503f0fa9c3a42fc588b57eb142e", "U": "040974cdba49fd29cbc532b5e2501eabdbc856814bdbd72990b2f055132634615209204b789c4eee562deed3834e7d060d755472efb63a2bfaf736e79d2b60177c", "SERVER_OUTPUT": 0, "Y": "023b8d0c8ae2ddea911f42ff0735b97355c36dadd2f8e2fe7995fe7e952faa2e", "X": "0880160c50fbcce3d99f7778da64800918bae52170912b5104958409a2ab86d6", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"17d3ec633a3d4762603848027c9e59a2@certivox.com\", \"salt\": \"efb14550d08260fb5062250a6330a03c\"}", "test_no": 43, "UT": "04143904983ebaa86ba30740f55bf51c6d3a552369522ac174cc0cc323e04d789901901fc44fc88fc76708534f8063df980729905cd6fe13ca16a23056f1d2486c", "MS2": "083f377284ce6219fcd4418cd31e999929eae1e71f70f7d12b7a9f2880d623fb", "MS1": "02de258563c3af4446bcd64ad3b8c8d8338fed6834ce5cd09542bd9ca4fe95d8", "CLIENT_SECRET": "041ac75378eb6ffc239ede8b9fda0bcc7238c962295486c0e9e4c5ba737df2301f0e54fe7525fe8bbac90fc66ebd5f0f3d06d4be0fff5acc9115ef5ebb2f5facd0"}, {"TimeValue": 1437055595, "SS1": "0ae862263da548d48446aef875ee238450231ab813556eaaa600f999d28768f807b5360cd6a3b04414c97933ea932eb1782ebe8431054d0eb8682da5b07dd90e09fb18e0276a0e155e2d6b8ade70041068555e1a969fb51e3472702e1f512b261aa6fa07ea2e308449979fb79e661046182d16010d84f3f62e3a796c6f2cac32", "SS2": "06cee61c9634b11a41572886a88395c9cebb8b4436672d323ee96e4c5800e73006c9e90b52d6982232287470603a5ed079080b682aafc69e2972eb8eecb9a4bf0ee4fbf785fff38b823e6a3a013095603f08f094218e3eaaa8c5d47a83a112a422633ce96f52c6ea9bebfc23bb3343447d93345e7773787af09b3bcd2fa8345b", "DATE": 16632, "PIN2": 5472, "PIN1": 5472, "SERVER_SECRET": "1fac23962953e0f8a97bab81f655d4ac1518501b693a69b1fe15e32b939ce8e30f678438308c66f565d2331b31d5136405df51606e773761119a52d355aa834d1e53719e33f0e9e29f771089889bb2c6ec3faf110016064929cf1cdfb389f0bf12bf0ce2dc8fc4a18bbfaaed28aadb54dfbacc0cc0edc649337431e8da83dd09", "SEC": "04037ca2bbe6c5ddcbd30db95a66c77d7227807003cf03320820e3386b0a21ba2300c88fe53b77223b90abe7b11ce05f90131cf418a33589d0842ab7f7b9bf8c88", "TP2": "040cefd0c173e094b7d03e2e86dc3f7d33d1601ad40841c0303422de309a19f93b04edf489db58879561e12b6217b8677b970c6fc491366b277ee9e4135521d42e", "TP1": "040f678c19a0f97954f0426cff275ed425fae54d21ea25193f472e47c5fe581b06047b4b8579fc010bf2f4a555d481f055cb05e6cab2ce7fa20e457652e3e4c9c3", "CS1": "0410e704fefff8208ac0a790ecc08a600e5ed8625094496dbbc007a3c847ca47ed15d7d54a850857103ad308ee0f984539456bcfe5096bca871ab04bb2fcb17f6d", "CS2": "0408f5dd770a747a3ba43eee4f91170dfb3dbb43bdaa1fb951fb16ccc78debcb93033a800e64face919a7a8f15a3742f5fd395d53290c77deeb50ddd582dbab51e", "HASH_MPIN_ID_HEX": "6536b8071510419f51fa60e3dc8451a5d73d7def8ed088ac8604916c09278a07", "TIME_PERMIT": "041aa437b723a5be7d0ad9c39f82bfadb9c067d46720cd2575d944f4e354f1b8ae18a834e03758f9bd9debc9ba32def7c6edf4cee7342c4053bb985f8c8474f8a4", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223535386539316162626233353063393039386366326264366262346236646639406365727469766f782e636f6d222c202273616c74223a20223734333531653435626238316664363962333636343334303364353231643537227d", "TOKEN": "041e4a404deb0367d909f996f40a109105ff3c1919f59a0b84e181a2acce00b7e0059c0db40bf50f4e1ffaf88ac81a7f6a377a426bf564b938b5f7a7eee5e0393a", "U": "0406b0c472427c43d842774ee9b8243677b6d590046cd9556a9e6d115ed2632d0d162b8c30ef910c2c7338995e025ee9064d666c98a7decbadd8b91235806b36ba", "SERVER_OUTPUT": 0, "Y": "05203f97565dbc7de088dab8d52d9da9ad59074d16612372e30bb13cb6fdd6fb", "X": "1c3422cfdf9b2435e656580a333ded17cffab506ac7625dc2983b3cb2cae5eed", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"558e91abbb350c9098cf2bd6bb4b6df9@certivox.com\", \"salt\": \"74351e45bb81fd69b36643403d521d57\"}", "test_no": 44, "UT": "04159c68aac959721927854fc6bd46e7cd27db02526b26663c3fae27084ba6ae3e0240c994ed104a4f3ca9b5b96629167137b41cefb833f672c870ea25e9ba553c", "MS2": "170672044b0d70801cef84e96e7c3c0c415476f7d95cb96848e8ba4fab049f4d", "MS1": "0725082dcaeb31a90703b4971c890ccfae359e55db822d2e4020165711a09cc6", "CLIENT_SECRET": "04168474603f85ddd274b68dc5d768d566c8b067a0d5029b338be7314b8e4f484e1b0072aace8d9edce09ac632d5bc25b549667be465c61592bf08e5cc5295a9ac"}, {"TimeValue": 1437055595, "SS1": "032f8cf55108c94d029bdac360146085caa34bff95770ce9bf098daed0aeb006171bf5c0da0cd531a5fdbc67d9990f6a6f75a21c52c7d4802744be6ccb1e46df06038769ba452425e21901d5facafce97f9b04fead1a5e155955244b63f9fc280e3a3548885ed6e42dd77edd962b07e618ef03d0972577c4d19eb8f08c8a6e38", "SS2": "05e6e7e9167aa8414f66b8c13abf62d767a253a68578fff84a2276d166db4e0f1e2955769a15faf85fbbc4c3a1c1943f7a0848b454f55a3719b83b7226b082be00b6f7642d2f81c3a8f6e8f63c9eb5f631b46bb5f8d3f2d08ccbd610595473cd00788a48d63c11bbf5de756e8a1ff20b4423a7845799cca1f57799ef2b5bc0af", "DATE": 16632, "PIN2": 8998, "PIN1": 8998, "SERVER_SECRET": "062a14cedeca1071e528c1ced8c458c88c444c07229fceb796cc157ca10d2930238ee9670bd7a0410e5ad0988dc6efd38404fe2e4e65911e1d5811115f51975e0ef5d3d4b41b0d30a1b0157effc96651c078d21ea571d7cbc94aad0fab0260ab1b0c9015327bb48ff52fd801906dc52c2c7e654964f170047f84be20492da3da", "SEC": "0409e2c21a20da9b22a825a88bee39c9e654c4d4eb848bea54df83e948224a1f2d1dde27a98e723301ca584e37cb8b9cf805b3cd20bbcc4fad556fe0148e270d17", "TP2": "04164afd7b5609bf1d397bc60a3e9cc5719cdb4670857537e8b802aadbeec6ce4d1afe942a1d3d0f82c45683be192a1032704c6f8ec1750ff91ab85361d7b2b2c1", "TP1": "041a2f173a7bccb877d95c849cf34ff3b523957e2fd933f3914989a08713d3f7200f0116d398f62d323c28925ca6f66913d11deeca143586815ea9376f2d5e4990", "CS1": "0407af048941981aa14ca89810aee75bc9901dbbb2c5f02ecaa9c50ae97e75ddd820e279d25a98f7e198191f08f745901d7da0005d345edcc3d699edcab4f79aae", "CS2": "0405161e997206919cdb134d5949365e21c7944176968bac0a25f59fd1e33da61d00e1fce4cf05cb33b10b9659739494e8033673f96642087d458c56a4217c95f1", "HASH_MPIN_ID_HEX": "9704b88c8e4ad153322e38cce677b3559aff9031ddfb69f0b105854b49ae9d6a", "TIME_PERMIT": "040083c13c94365a5102f61c9820959cc95ca01b2c40fe8e936ed775736e21b0730876c19a0f03a571c19f956b4bbee7258e651dcebd04fb98cdac747b0a1404dd", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223431373365653261356438636563643366393039636465346262373565656162406365727469766f782e636f6d222c202273616c74223a20226536363032396465643561383964613234303664386563393438613064633261227d", "TOKEN": "040c7446c3f8c5e70373a5503fd72cbe8a8253f05b853fa1285a80c25528cff5c123279973ae643e503bf475e347b04381667833e0ad88ccd4a9b071bed93d6b6e", "U": "041df809abd5c6b44a47d9527d6dab78403c954de3e3f70d15ad4b7f6805e114701354194527d72d4e758d8040682ed4e3b7561f7f69518f11278618fa682df6b6", "SERVER_OUTPUT": 0, "Y": "086b020649a3086cbe0e27331169ab59c75156ac1a32e376f23db71b6d729878", "X": "13b2ab0476a4d1803608ad26491824f1f53cd6ed2fae6a8d6e2ad84af598d2e2", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"4173ee2a5d8cecd3f909cde4bb75eeab@certivox.com\", \"salt\": \"e66029ded5a89da2406d8ec948a0dc2a\"}", "test_no": 45, "UT": "040bf7c8c41f1b7cfbc15b79c0797d873c9b97a3e0ad5280ffcef3ec52024903211e1d50f88852b3678cb2f1b311f6f7a3ebb5d46ca3890256b10f808380b14d5e", "MS2": "1040a03347171590ecf0ff868bed5a3fa412b1486cbcb44fdac5ff8430f8c93c", "MS1": "1c367ec29745ade8dfc637c27135e85ac6e2dd68fa1c379e5ef65d2cc7ece707", "CLIENT_SECRET": "040a3b3c7c7bf06579fcf797668465d9ae2e65b2aeb290440323910f98a4585b90020792551abfe791b2a7383f6e971122f4e0faa452f6ee9dadde022d27387508"}, {"TimeValue": 1437055595, "SS1": "03e5ac5714d8282be779ad8ef76774ed61f4a7922018bbc3e4049ee7d64f71c302112eefb427cd7c7c0c45b45d923f2d094c5ea70e274671e6d0e05e993575c417989db67a60ff0f56ed7d2d329c353816dc8b0ceb8599c5fb638db09f05a89d197156feb420aa5a14eb322c38355b61a5044b3666e36514ccb36751173e78b1", "SS2": "20acab7c0eb1351fa461337927685d345d354d87bf4dd4ac63a2f03689027d3e040897b5ef6723bb6818ccb7991fdabfb65b564103cf455a299095ece8d69b44025ce42306a5f305bb0511140541d98937e403cb4d1d460dda591a7430030c701fcea14cd0a0302a2d246daa209cd1cb0be1c347e047a76ac29d1b0cd8c4e452", "DATE": 16632, "PIN2": 1684, "PIN1": 1684, "SERVER_SECRET": "01cf8f57e0bc0c54e8195ac56cfdfc83e27bfd12ed2432de8cbed55f7d27f6a309060cced85dc107b0d6d6fc2108d13b94a4407a2a24794dd68112ac7d24146d21070fe086eb9ef858007ec53a9f472433d76eaa07c7cf43ae302cfd7cdfbe930929713e7b9a547cd005e9b79cb9666b0d299ec1adb1d567ecbc21ef02886b00", "SEC": "0411a5a60b0b29825bc0f4af9a40dfd44c7fd8d1f72409996796c19568ebb1358d0cafccc656e61048d0be5b63a1e007ed92ce1582763893309d15837ff7f925b4", "TP2": "0413b279b7195ed503f666a54e11badb31c0c9e91f86b7033c1330412f7d907d3104c40a3374275b6de97597330ce9b08d640b2d15984df1680543c55210fe96da", "TP1": "0408bb9314c4c539245b224b12652d95433593dba9c7caabc586ae51aa4362670a0ba65f7eea1d5160accc0652d60592e7e0045bc7434eb3972bd3ac54dc1f9eaf", "CS1": "04189d2bbb060cdbd9618ffac4f5bbf32d87b972081c9ab57780e7a0c6f68567fc10bdf8b4517791be121263c07c6771a10fb3f09bc6c3592f7fd8e35fe8092346", "CS2": "041fa15482880ab3f78d4c1b339ab842fb3b5d03b49441c47d7f6d11453c8b15fa054b19de45399aedc22ed62a85c00565bda0e1d33641a8cd8158253d9c59e5c7", "HASH_MPIN_ID_HEX": "b316b9c1f804a58e3584cb5e36d40a6d578366cfe574d527af2967e1b7d9c869", "TIME_PERMIT": "040cb66b7e879c0187905d547033a745170eeb9788d8312c623091cd6183b36f49103fff3c1d8f0c4bdddef17f500863f6ef43ac12f411667b2423a0cf93992a6b", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226639666262353536353433316234653630346237353334666663333938383738406365727469766f782e636f6d222c202273616c74223a20223962636133376437383733396165373666643765383766383931323432383262227d", "TOKEN": "041f4b6b8c3211b81f678a8e812ebee1b3cfe02c901d77123ab8f22dcee545cd1e01c4d100c17a6b3cdc69756bde421a723011fffa1ee74dd9804ff656e1719482", "U": "041a7736f724a601bec8919e9b6421971649f458bc9ac62dcaf64c1cb06f1435121f2dfa5ce02c7d5c3a6f8b4f578a19e05d220fc0f835566ba51569e95720b7f7", "SERVER_OUTPUT": 0, "Y": "2306c0a87e331b6fddd1729356a2aa74df004ad20ccd582c4a19c2a5b5fcad9a", "X": "0c02f5300afe5d434d0e32b55bb2137cdfe131114e1556df06b71c5a87c63298", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"f9fbb5565431b4e604b7534ffc398878@certivox.com\", \"salt\": \"9bca37d78739ae76fd7e87f89124282b\"}", "test_no": 46, "UT": "04131f7585fc79c96edec4198e8bb317d54cdf208c206dc2f0970df7b0b320e62d03afb38a499d74c1e0015f95bc0c08dfc9d31facb2d52f9f780b746a1ef0235c", "MS2": "0bcd282f92719497c0413ecb53e58b0ea4a2c0be7cf63b8eb2f3c7ee61c5dee7", "MS1": "1897daae656d585f48e744e21432b8325ff57c31e256805cf95eb26d9550b6e7", "CLIENT_SECRET": "041d4c5a523b7f6e257bbf4f344bc71584ad8601e3dafb07a2c3d19665c75dc7df19d21569d60a4e116bf13548ded66d56dc5b4634ae312819544fd39715734b20"}, {"TimeValue": 1437055595, "SS1": "1ce8383fb3ca3ce06b5fd482a0d5ff94c9b632def612db3059b3ef2c9ad8c9771a086216e00bcaff130fba408a936891e9ac3c4028ee83ad2d8b3f1c775b35660b50451e75c4b950d325a19503203709779f92e113b33660c6a7dae69d073cc700e9043bb2013e9707ae9983e10e651fbca26d23a928c0b4096d2af54d733dd9", "SS2": "0114f194ac4b3394ff3da25789fea0176a86e41c89d7f187e2db6549fb2f7a390481f6e1e736602f1cc6b9fc2861dec1528f3ef4c6a59729f5e018db3ed9848c1e6ceb3cfd6973d54e8e124e03279c59173d21acaa477c60dd87af98421dc7dc016f74bb5e188eb70c2e24990b6b251ce11b67cbf150cfc20328b7945d14e9b5", "DATE": 16632, "PIN2": 7965, "PIN1": 7965, "SERVER_SECRET": "0a13af573b31d38189e03c4742f40d0679c04826015cdf54689aa6d04701111b08c3cf8253baec42840c903198f58b85286026830fa8ee7178ac12fa988b93df1802701e96c4253e1df08036f807b6d0098f290e810d084807bbb1e4d0673cdc13fe9d773bebee8e5967e8622d27a51921166389fc751af21c4a50f25ad98fb9", "SEC": "0404037dcf879769608a4b6272f2f87efdceaa7816089b5f02e660946352ea746f07daacd5396fa6a9695e6b969aa879c4d80438470fdcdb53ca67f345ac574e25", "TP2": "0400a5bd25c83bbf7489a12ca17a967d0ba2f0201b5687c9c704f24a8cdd4d63a10040eab090a27c20dfc1517fe0e23661550787df7280e65e53291c9d32b345b2", "TP1": "041f18a100ede0307dc3391ef5ba05ad3884dc26c2396ca99a3d1ec795364464540c8a83cd174ffae220afefc10ed8ac1b4126961e63efe49522cf2c9ac7c622bc", "CS1": "0415d83088bcd108903af26d8c05d1d948a6ba45eb05db697121044767bb6e31ca23cf634d67fb0b0b9a0419fac022147542384d6243bba38eb26c7a2fe905d539", "CS2": "040594ea3d4f78b70e2cdfeb612b1af6ab483d5fd52dc7d84ca024816f3e9f5ffe06f15c2de7662a99c8b0fae0306f02fb4e93d417fade52cf738f05c5d9f5da1c", "HASH_MPIN_ID_HEX": "55acc93ce106b09564b138e81a177d1c7e2fb4c06febe5dea18189aeaefb41f3", "TIME_PERMIT": "040f46bcffde073c8f6fde8acf90deb8c60ce6bc1766321a3f02582810a8a0cd500eab991d265a3e7aecef906adb672c2a8541096e611a2b1d5eb7706e7f3e1277", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223964363734353933336235646132363061306535643635396637336532356132406365727469766f782e636f6d222c202273616c74223a20226634636365623035386534643131376561346330633839313364643039643533227d", "TOKEN": "040b25e56f4592d80a52835ca48faeebbe0669eede0abf0e84ad63e4a2c7ad95ff1d7f37592c102179cecd0a81d224f40c4ce2ce82f074cbc41e0367fa59b31a8d", "U": "041657b685ef4afee91c08a3ec952810f8b9a428bf5e87908669bff5e8d287adf0068d38248999366922ef66d06fe836378d44d20d17abf7dbe41b6ecf9376708c", "SERVER_OUTPUT": 0, "Y": "014445a26b30ce7944283865448306aa6b8ad890a60d14794fb72df2cb1f0607", "X": "0c3227b629dc9d8d3e70f36e5f7e80d68787845d86ce477bc629fa6a1fd90a3a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"9d6745933b5da260a0e5d659f73e25a2@certivox.com\", \"salt\": \"f4cceb058e4d117ea4c0c8913dd09d53\"}", "test_no": 47, "UT": "0420d354cd04f946660a61db3dc33013690737ff73307a5964080bc0c37aa26a7e1a674adc4d87cb1737ba5b4e92d66fd9fec6a389691b997821a6051a2b92fa49", "MS2": "044b3c287c8e1824380d7c996414de31d922cf3c7580bc4354a9a136d1e31658", "MS1": "1862505f3ab5a70224ad9cd370632bcc2001983b6d83083e423adc8e5b6a9a81", "CLIENT_SECRET": "041190cccc5315498827157c590fdd9fd0d2e9ccf3987e243ec2b411dfc4defab91c0a734a686980debdb7d00d03662fd08e470837075302951c5a4d84ffb7f64d"}, {"TimeValue": 1437055595, "SS1": "1a0e52a95392b15cdc2cc9ea9bb858a014d9993d11b62d9558e93fc8a9bea54404468987ea2e4dbc1bc76c40ab2e617c8ca82bd573acc8debe1583fc86664d361828f75ca5573038b3183d74a1c89193ac828574b5d2a3f5db15e51dc49c69a210183b7c864ae5a16ce33086c35f41089122b5777fb75a3b0612974393a92daa", "SS2": "095171d320e7911433074cf869f4ec519f48b3416ef01ef519b30b42baa0157519f9a3909c86cb81e436e7529b0d12a66ff0105635d0a460a8c5552f36d44ade073f5febc149d8edc28e71b59097b1ccd9189c95281a6dde19b90b4dec205a001ed0568e10f54558667ec67afef3b251464ec0abc5f69f1c2faf5ec313cb54d5", "DATE": 16632, "PIN2": 818, "PIN1": 818, "SERVER_SECRET": "149293b7561374255d19109dd9aec44ca225c8975063ad0128dbcb8fcc000df5193934180b42dc17c012d7e8c4f893872a35533799080c8b6ed837a8380de1fd040cf69bf3407849684e23c821a3a139f83883adcf24ce462c82da41bc3010581b6d938f98315582d33a9e16794cc2f5741803d1ffc94e83f993730842e91764", "SEC": "041f1a7af8cf6605c1e22f17eb390199e41b0a3b90fd3aefa83a6807ed8b68fa31083d33d322344e7b0000c9578938112e70ce5fb3331d3d6680a59517daceabbc", "TP2": "04021b33bacd24f826d4c8ee8cf95736060e429d51fb753be1a08533c73089bbd716bbaaea921eb5adfbd3f91b6750188111a57f2027ff4c73f7327f5b7d575432", "TP1": "040cac9c79536b844864d04853b3e3f7ac8c6095f9b208a4f378f60671577b3e0d1d36d0c5d88f592a24b92270f9e4a85308f6ca17f20a20a085573bca951be1ad", "CS1": "041f2b955568ba48f5d72022a3d0f23f9f69bf08169cafb841583f689f8ad99df31427dd7e687453550a58d246ffe6c754eb00c2e40475f4bf3cd9e88249adf439", "CS2": "041f06649b2b2fb0f3bc430f58b72460484fbdd5e489d2fc40aa62041b4aab6cdb17d7b6448c6e9cecb96e35c07dce4a395ccd51a7ce7b8c526aac174193125e57", "HASH_MPIN_ID_HEX": "d7fb1932b4a44d1d449611a2b3862d36abc01a196fdd6989aa4661e5abb503b5", "TIME_PERMIT": "04195a58ed3b0291f4645f250d7355cabd2586b1a1e387e1a05194fbf69c0676821257e73cb2b66a55f47777af2ce3626393b6755b536595cedbac413b71c362f9", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226366626535356239653938666130613336636161626233333531666562373563406365727469766f782e636f6d222c202273616c74223a20226165363331373862306561383937363930336531613835396330613663363035227d", "TOKEN": "041e9fe5fd9a4927ed2e4df4a1d6c7dd121bb26a0070b4f16c98c094075315122523deaf9e65e7a866c9de8fe454d1c1e5ffc3c1404d155ea69fffcbe4c49ada46", "U": "041744b3dc824e434a2ad4d9973134ed2ef8e18e543db9c82ca7a124b8c25f1e6c23b8148e140156933599bf9a8905db3e256610ff943a2465048f541d6a7a68b7", "SERVER_OUTPUT": 0, "Y": "07baaccd9d1dba7eba8fc30159eb49a43014975c5def13fcf07f74ae383d3d39", "X": "1b18c30b259bd2c3928e8dfbef0c2d17ecfe160f39fff0bf25e2504949f90e33", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"cfbe55b9e98fa0a36caabb3351feb75c@certivox.com\", \"salt\": \"ae63178b0ea8976903e1a859c0a6c605\"}", "test_no": 48, "UT": "0416217874dfe7496c70e262c32d9e93a0c448783f1756dbd6c787f2346102a00c0f0f5f6131c653857aa3b92b50fbe68dafd626b10c7fcadb551c97ec735d4895", "MS2": "1d1c9c515fd2a8d50ebb5c20d50c2974e8a7d2c52745ab29e405e5fcb28ab43e", "MS1": "129e361aeec89eb9517ac4c9c6f4fc12572ed2d05b1b7f16e8ed9560c1ec8bc1", "CLIENT_SECRET": "042343b8484bdd7af78a29cb139ba48a992ee8b9d8e16e5ba0c8291a77a8c9624b1bbbcc421fb5ba352baf21eddeef5b6f1ba99b0d4043967e61daf779e1c43b4d"}, {"TimeValue": 1437055595, "SS1": "1b0ac502abcc81c126be1ed026b7c016eb740a3e53edab553767c4d555abb60c185ed41f61008d5e1bd5d973130accd453cc4b38fad451fa28c5739fdd4ce52d01b6fbbdef572dcbd0a77e7772d1a086fd8ea858a0e095af9aed55faed0e5d6c0722a0669a43ae484795fb4d8eae82099e7753384d2131b49f1c85780cf96741", "SS2": "1c5caeb7bb7c1af5613047b5223ed68164741e850fc5395ce4b42c1611faa03009e7fce3786e02271c8383d939508722cfbeb6166f3fb09d0e4d362ddf83c0a8169e600a833055aaa2d45f04f3124aa10b5e9e6454b8fcd342cf684c7e4d550a23d9acc1cb721c451ebdcee7f2ac980114a848df96d8f125a314e771bbd6c295", "DATE": 16632, "PIN2": 4568, "PIN1": 4568, "SERVER_SECRET": "0f39734b764e7ec283d7f609d32a673d1dd864876b11259e72d312c3c226cf01233976289b7d7a8258e289f2d79fb205068d88195a14a198249eb89954a39063023db885d9dbc91f4dffb66ab5481adc6348485cee1ed66e87e7e1854f9f747100f7c9a8cd83e1d08b5b6b7cd93663164cd977633f1e850bf2cb56883bf0d7c4", "SEC": "041e6518054514eecef0efdd41c4c07d1195a24788212f4b16e785063c0e9c375d0d007bae09cb36ab5f4461a19c42f92d0523e1a9b631468b63ddaa74a790ff1a", "TP2": "040c33d3a623e85036ec9b3053aaba431eb18bce32f1d26ad1b47237d83c707da61abdb09cf2a18e02a0d6fdff1aad09e97410e890ab6dddc57e5e0381f0bd1a3f", "TP1": "041ed9ec574d158cddd97c6d814bb22990dc4a8f2966160efd73ae5c282012163204b65fb12b90daaf66290a1ee7b53729f02b1c995c419e057d6d829541330a54", "CS1": "04054bc714a093870c3920f41e8034dba3c8c429acbc390f571a84f834ed522c0d0539547088848720f60039491652c981579713dd2c866acbdd2f5f73dda31247", "CS2": "041864957d7b32f01f29f85af3cf065ac127c98359817d930a59f1fd62fc820ecf0ebb93194d971d7c743944c352bb9bbabb469a39b969dbc1447c84631de043a9", "HASH_MPIN_ID_HEX": "f1d230636993995c75c7b8a5ab566bec6a1d803816d607a403f7f09d4887b3fb", "TIME_PERMIT": "0414a05f284cb6b1004c14622821676edafee00a00009053ed233423ccc65778a20f62c615199523e8bd3bfca1a1f48a6a90a7b232de70cd6840094da7e55cab50", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226335643132653464616636303535356632373462653634346164626333353766406365727469766f782e636f6d222c202273616c74223a20226463313737393935363565663236313037313837613865303966353237383931227d", "TOKEN": "0421fcf94d8ef882726c93f2b3bf9d53221008e1ca9f2e66b10a7eb982a9f156711cdf4108024a6d275ebf925ba8811237635e587d80ac624e7d02f976b3cdff82", "U": "040e0aaf19add42cf022a7ac8fa7b222d787e6780088b9f5f7d70adf18fa8603fa196010235e340d0c76aa4a5be3c716b7c4feb04e39cb0f24b7d5e5c664adec13", "SERVER_OUTPUT": 0, "Y": "09f477ed3614a9bd3fdc9d8b4a73d954b797be01bb6537cee9f2de6170d9834b", "X": "079f5bef37f2db027bc95da9e7362b5d87061eb8c6e984f132dd2fbba4db8aed", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"c5d12e4daf60555f274be644adbc357f@certivox.com\", \"salt\": \"dc17799565ef26107187a8e09f527891\"}", "test_no": 49, "UT": "0403dc5a148843af36d0104ebad867c83732173ffac94666e9f2ab7f49c1a1d057056f828a7b29422722c74718cc24db43f2ff475120cdcdb6ce91e0e7c0397954", "MS2": "1891f0a7aad7e461819a2c32c5118b5e2da7d28e58874486019a361fe4df449d", "MS1": "14cab478a56794a1a18538ab375f36960f356fbf3d9550e4ce29dbd557ffc4ae", "CLIENT_SECRET": "040fd394e12e1b9e5d8701fc7f8dd4f125f877ba0d13f453c037bcde91062b2d5618f49850da75b9ba0420637b931a22cac6d5018229b39e1de0e91ce4adc19d93"}, {"TimeValue": 1437055595, "SS1": "0cac071b74d2229562693d0ef827ea972b4ec38ad3245c4aed23afa72cea2062222b2f9536a679721b2b6f1ec56fddc90413acaeb9d544ed5f1eb4c3e4fef5670d9257b136a0c8c932617d306fe163019a018b2f7a4103d064911abdc8b57b720a5006a894f5c649d8bcaafb89ae82d73be554c683471c0106418f95062f4c42", "SS2": "0b352a81eb839c0b55f2674ff4ea1668508304fe71152826077978b98e1d4c5e05b7f32a1a4809bccc3c910e15077a644fca90a9d0f7f72e249380f3051904ac10b2b35a2ddccb973865de31c838facac04a9eac318458f5195026c52268f75f1c898e1d44acbdd1cec893b09740abda310211b569dc01099634ee1d23a4a695", "DATE": 16632, "PIN2": 4107, "PIN1": 4107, "SERVER_SECRET": "14f10c9228d16402414af8da911514c7df22a57ee6702f0636dee869de51d1b21a1b8ffba3b7c5f6a31379a16f2bf8b8302779cfe8550096821c26ad048314bd0b10d83923a322317d41e12ba1099c0702a8f2bc2944d19e423e335fbe0cf76b065719399a18ab6eaa909ddfa8a15d1e4c01d424293351c6dc7d245350bdf1df", "SEC": "041ce3d0fb890d10fd609041469ea9d1e59ab40513a9e7c5ce017349dde20a7c021d352840994ace6ccf929c121a5889609038c7192ab33fe205f8fbb12f84c439", "TP2": "04134823427268b9ebe717d7ca3b658aeea06c9b8f43a894e8c825c72641a8575d01fd0e9b9457e7b728fdb2d57ae9f4bdccd5045172b292b6b998696bebfdc355", "TP1": "0406baae61ed9e843ea13aa8f103ff71cf1e538dad6b378297f68f1f1081945096123df9319e51b8b3a7d562537d931e3191fba09a3558a784320b3fdc13553a22", "CS1": "040436370b23bdff9e3e2eddc365bbbfcaab7c9b0c9025c478f2fec3a1ce9b5f370570eedba49d5508e1d4268e861aad2add3d5d1a5611c7c49e050dce048904cd", "CS2": "041ee27413033c067f12313e56cb62f8e3e7dca147dce6074b3809fe9b7ed97500106f245557b964e6889af8eac176175f3e9856e45b7858fe9f9a28ed2431a9e1", "HASH_MPIN_ID_HEX": "a04afc5f5c7c11008c049de884aff802f491331cf7cb2a9b3f638cfe452d4b32", "TIME_PERMIT": "0415ce24c50fa7c8fc3bb7891ba65dc3b24c52134e1479484e6fc92ff0922ea8191c962c094154dfac263ffb2de60c743026cef929a071f444134ef9506391f87f", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223830633938666132633061396138623764363733346639663964376235313131406365727469766f782e636f6d222c202273616c74223a20223338373266383666643431376438396634623933323261393965366361623232227d", "TOKEN": "0416bf9169519ab90e0fad9aa8efa507feb6194042df19941b70e83794014afb13091451121ba423508d89376127248cc35d68091213907d8f819fa0d9f9244aed", "U": "04238a9d75f9fd65163072dfbbf26447e3405bd7f183cc7bfc387e8a40815d8a7a1906264346f748a31c348ecee991a65523c9f80d3a27f8e652ff86d68a2e5101", "SERVER_OUTPUT": 0, "Y": "13a6838d2aa6b257a3313b49331b62c9523d27f6d34bcf42b9eaabd56542f8d5", "X": "1cd9a541a4949ef144a7bd29a83c15344e5c49b01a8689b3c30cc4cfa3911302", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"80c98fa2c0a9a8b7d6734f9f9d7b5111@certivox.com\", \"salt\": \"3872f86fd417d89f4b9322a99e6cab22\"}", "test_no": 50, "UT": "040a08edf00b2cf1100b82687fba579de09985572b0b57a51a9e93e4d9d74ac003059323bfdac5fb1b58b1d1d90d469fb1f04880340fa927397bdd9d892fb2fd88", "MS2": "1b4a74867e904b1b8268e858a5a756e2cc94ccafa6bb07ff0d067a84f5e71944", "MS1": "0d76fd99fabc1cc0be493231628884709aa32fdf228b22c318baf65bd27a02a2", "CLIENT_SECRET": "040a559ec4dd7f9a415faa953a384bca55a4a2b0b011bfd97ec73fe0527cdc15e4024504ca9dcddece61d6d5f879c6d02c90fe55abe91301af75da83fbde4922fa"}, {"TimeValue": 1437055595, "SS1": "08af7251b54d5d1840cea9e906d130e32c33f2d3c86b9e96904130852a6f232e07ea57f0a6ae89e65511672c1929ae9fba84c6e3f148291f13454cc5f7405c89232e96e15f2bf47f6ce3786ce2d3fd6971923e78c017de7cbc88c20a371ea7f1122ffb5aea14803a58bd503b07c83478b5806c05295135fc36d93c844ff0c070", "SS2": "043775fef84f691d4ffa6f7b8ee3e1a7f5fe41641edee5eee10a68f890969fdf160c321227e937811e1a1c26c0664eafb3bdb078a7d9ab02887d53119926c8ae01d2a86600ce61ed8545215e30138c82eecc325950c14568d4baed4dd7f1d2a50616e9ed2dd225855dd65264be85c7731cb91031054a76ae8a2ee1c9bac4c74e", "DATE": 16632, "PIN2": 1886, "PIN1": 1886, "SERVER_SECRET": "1c92ccac62910b9e9fd04cd32391ab180dd5126ba9dc3db9610cc202ee861e720cb88d7a71ac15428f64b5c989d56f10ae34190a5a4a4539649d6a99098a2bb1149f2e6ae96bb262df633271f121ae6b07fb8e097819a3eee340105f7311775910de16e550c926c7411f96168e3c817993ab7a78486f520d0240a8e42a639d67", "SEC": "041b37902a5711600ec78adfce99bbef67106f9381411d48486eb0bd76ea3fbd3d004808fa529efff9f9fe5ecab3b61e7788bca07f56f2030310a31a2cf3244f33", "TP2": "04037106d93e1bd6dc4d8a090fddbdeeed92a22a3588a25d18297b315aa209630e1c241b559c89f98cda1ff005a1bf650ea646e11fbc081a7958f7e7e447f3ef08", "TP1": "0423291acbae5a556ad5ab167644247423792418e2640f8111678dc1671c8bb20f1a5491a8d4f354db52d4f966171f7615e8f623cf7be474ebda2b748706c28db5", "CS1": "0411e285f373975d312042c79230b4a44769ed197db4003cbb91fd957a75e6eacf04667789439d4aeebfe6f6291a56a483ad402e3becbf8ea246d842c00400a3f6", "CS2": "04149745a63eddb34851387fcb06af0e0de6d025b7ec23dd1c288c698830417baf22f37c4f16eb2a8e0530e6af61b5f2c21b41961d9f96475ed5f8c228c295d1ee", "HASH_MPIN_ID_HEX": "c5e6887bd897c93a6cf9829c3319de4e0eea7ec57bd1be2ddb3347bf33638514", "TIME_PERMIT": "04084b46151faa4e0305458d38e0ddd0b9bb97b09026b70f0ccc29f77d8bb0ad621381b05b06b0499d46216a06c2f2f3c72363de02e4ddf76208227f24d18e128b", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226132393331323437303831333663353534303635303562336361666663343864406365727469766f782e636f6d222c202273616c74223a20223262376666356332626630666338646365393134653538363961356239376563227d", "TOKEN": "041358cbf3fec42d9d00290f0829be551d765d4c0bb14e69d36a89f3b59250d1370a753bfa5a60cfd6a84703f6aefa7c93ee516a6c6c64a5f46ecc4e60ed691f9d", "U": "0419bc78eb5bb24fbda8039aa6a686ccf2dede3d101cc1ac10d4891baf72d025ea1ffb24af1b80d5cdf586ed695a6613cdb8506465c692c0ffb00c595a1d89c7d4", "SERVER_OUTPUT": 0, "Y": "12f2e88db93071703ef15c080e49aee43eaff24e68773b256f02a7c90ab05a0a", "X": "112dddbc2b25a48a74e6a3c12873b36a0df042ecce50eb3949a8bd124b73d4d8", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"a293124708136c55406505b3caffc48d@certivox.com\", \"salt\": \"2b7ff5c2bf0fc8dce914e5869a5b97ec\"}", "test_no": 51, "UT": "04154e0be07ac17fb2a693775aa589b782e21b2d6b86b6957c97920242b37558f204abb24cb0050b1378a87baef155e48ca58e87ab9c5ea5d2275b6fadecba2b02", "MS2": "204475e335f1fe8605244a4e580f9e0a7ddd18a04f7fc153bd0c757212452558", "MS1": "1ea50b08750853f6e6fc739e66c8c54ef311da1904d7c4d559384c2967fd2694", "CLIENT_SECRET": "0402b0648bb15fc96987a0c759f5a2dcec6c29a4b4215316cc9ea1400b54d2e87707c99b425040a473acac66535f6bbe4f98fc9fc048c828312efca0b6a40ceab8"}, {"TimeValue": 1437055595, "SS1": "1a24cd2399446f18fcf21c5c75a221645d2f20934678c71fbbc2d35c69440dc11bb5b2636214222977b54ad9aca2b995dd9638c46fa6b04c906add2b63ab051814e486a7ee5a7ef3971b709011973b0367f2de9e3195b3d5da4404f5928e0e3b1db1ebd101f850aadc9fcf2b0d3fc9af0578b760544337db3106da72d527b256", "SS2": "07bf3aa287eaa5e286f883af1aac9308506cdd66dd0cd6b59afaacfcd9b62a430ba5f98322f6b67cdc70db9f1ac93b60320aec3de9470ea4fd16b955100cd8fc14b8e0880e5b6b305227b20647d60e8a24d8546bfa3624d0c974445ec46af277048870a5462a43f23cc5c228ad94c3f7a71cec0d2cad0c205a0733af7847e9c3", "DATE": 16632, "PIN2": 392, "PIN1": 392, "SERVER_SECRET": "141029971c1a7e430995c56fbcc0a6d66374f6078264e8511242c1f2550c211213da720d64a360e4d18870096b26de324d7c57e3aed277c549948a1cad60ca0202a2e7163ebf9dc8f7edb7aa07131305068d01a939058b6f357b2770bd062b70000cba4f171de13c741e84775ee0bfad8306c69fa8bc3428082acd1aa069bf6f", "SEC": "041b87b699db67bf35bd2f7e0690192faa8c9d5cfa0fcd5ce197ef8e6f5183911d16256ec71d50255a4ad4a7661f87579999096fc5734230f9baf05b03be2a4375", "TP2": "040d67081f86532a1276f9e3b774a4e20a39f22a1c293902e3f52e99f23f5f04db028eb68eb9637c73698f337ebb4082adda54ef69e3ad0b00e9971f9cee01c948", "TP1": "0412f160ae416da66967678f90f40f841c5d12d4735e2afcb5aa1dfcaafc74680616b9c52594d27085a8cec758fcc9f102a4e95afcb8efe4912d18633563adf517", "CS1": "0421910edf7e943d5ec57e64e99bcd5cbcf6ffb308e5beb42c495becbb1834e5191fd0707b86dba79400ea333dcd51cdb0dafb69f6c514ca7cd2f864d20e65aeb6", "CS2": "040a1e1bb05e0bed9cf78274e696b7fec949fb3022b8092ecff46cc78789df82a11f04f9635ff33603c2939ac78c20f4f393bb2a947de5e2ddbff1c7a08b3c5d4c", "HASH_MPIN_ID_HEX": "df8811395b874dcf274140d9315aadf622f153cac743e642a648592b6ee118be", "TIME_PERMIT": "042327712e188929196c74c6725dadcb6afba3f60b6319c6f223fabfc7f52b267511596f9adbaf82e02da98222adec5db8436a0e078ade02be9bab5a3e6f9ff2b7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223438346664653565333139343839393330363439613266366161656330653234406365727469766f782e636f6d222c202273616c74223a20226563633062323333366339646564626331613634633866303165303137363561227d", "TOKEN": "0401d24a64c68e5b954191c6b00fced59366c5eb0694a7f680c67e462815653d2e0a30932d9d3425811f635720fa8c6c4d4369922b903f05dbb20edce5040015f4", "U": "04151c56dec6b4135ace2676c7ab0940e8bfa7086f41b71572d7193e70852934c90047644e52e721348c0ca0a867664b16c92c55e62c728aeb75948fae030e11ac", "SERVER_OUTPUT": 0, "Y": "00ace6f2fbae88dede2823e0945f777896f26c01d01d96a2d88357476d142759", "X": "031f9a25687201ee4d1303900b603faae4fef3d7bf7c306ac92e9d76cd141eec", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"484fde5e319489930649a2f6aaec0e24@certivox.com\", \"salt\": \"ecc0b2336c9dedbc1a64c8f01e01765a\"}", "test_no": 52, "UT": "04113c79936bfabf5623a983c11ba27d981d6ef28b485220531eb9a402e84cd72f0fcf2cc65b6c94201594e9e37e03613e314e558c4adcb16917ef98fc58179ce7", "MS2": "214549067652ffff2bbb24831b2e5bbd4e55ba32052f00ffadb014914c66d6f0", "MS1": "216ed7042c90704b4cb0a66780917dbf25dbea6f679988cc050b3b58804eb691", "CLIENT_SECRET": "04125a6757618a220a3d9e07b31eb549b72b9bf4a5b4576f690a8b72f9fe1252760c2d68718a423f8cc648c65a1128a74a2dc7ddff580e2dea3abd14162552ba6e"}, {"TimeValue": 1437055595, "SS1": "0794aff04b6901013d7bdba94c0f84fb76357d54a90ce7333d9e77b5050d7d5608ac8d3f9571c8d09891af7dab5e2142b3d1f8a052da13e4b1951416af825bb70cd5dfd431c345e7b1535537b061b0ded3ef2dc7fccbdca5aa504e41f315e0e21052134a91f35dfd7b832a69f1a40d765e563b1ec4549de388be58607ce493dc", "SS2": "2050f1cc96d297e16582d56569bc7173b857c94d0c7fda7e41ca4e31d747c072201b1ea61ae645114974d2fcdd182ff4abf6b01c78ee760b63896b7d7f2e178023e4cb2a3909a54d49cdad0b0e16aa95cd7ed4f2ae967b4d4dc0fc4d71789a7e1f8cab3518784a6669418eb3a91635d993bc77dc7f362b67398a566a48323017", "DATE": 16632, "PIN2": 9044, "PIN1": 9044, "SERVER_SECRET": "0244ba8ba6dc67a32c1f9048fdb327dde3bbce4a82d04d823cdb642db460555317f605920647a9b7cd5bca996cf339743ad8c1ba3f84f5f38aea15d6454fa69005ffde0c2a4005543383314bfa5599fb871246101307c74d2c042cbe971fee2323bd21535f0482b1235b79e19c98183f48cb4fc7a2a033ad703f200b7c37ff64", "SEC": "040e51f2328285d0b7a317f25f4ae11c47e6eb5dac55003476d4263d1a0e17a19520f01eec130b45ad382e7edf990ef13b60486ac94341cb5e078994b138688c39", "TP2": "041aacc6a99dbf8575874c7f44f0871ee1d4b2354e5a1c2404740f40e82f45dd351a9a5eaaded95f064aaca3f58516b11f319afee9646135d75bf4b6840ff80b9b", "TP1": "0415fe9c82a0e0b5978cd90f833af4ef4a773848ce4d481693ea320eb90e902b6f1e385ffddae6ed79fd9e2dcf9fabf03d9b1bca659f30a735094d8c7bc95635b6", "CS1": "04226aa253b54ac0ab9947a06a7c72d80ee615ab94caeed7b69d0e95ba341b178d182f047a46322ea1346b1410dac8534278bcd3cce46b99175edecf012c00d500", "CS2": "0403c9a8e09da0721e975ff94f0e581c7c5bcabac215f6fd7530162be8b3348e371bcde0556452e0bfecf00eeb507da9309f9e146cb989a6a087ecdd50888b1314", "HASH_MPIN_ID_HEX": "7650f0772c444ff29cdb509a23025ef095671e3a11bbcb67359a657da6e32588", "TIME_PERMIT": "0419789998e7baa955dab60fbebaf25701caaaf3be8805613fdcd17845a0411c2214efbeb301175222bb9da0fa1bef1cc9198d70fa100ae9f42ead51e1a1dc8810", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223735313737356163663634383264326464393763366561326364343537666465406365727469766f782e636f6d222c202273616c74223a20223034636635633063366237613931623161376531666662623565643030306436227d", "TOKEN": "040f42e7d223e353264540de31fed544c643ac65421e3ea2635563fcaf3b72f8c8150d6225550e449eaf06ccaddb0495e3d65af026ed752e3c0077f8cff0776d60", "U": "040732bf77497fa903b34e7486f69f0bb8baea67e768f747780b0f960d494044601d47020d112dcd663463612f72e63a13d8e09a5d41ffdc75dd887a1b9843a66a", "SERVER_OUTPUT": 0, "Y": "1343042a356f8af60f18864609534d51ab785443c2b9f62242d0df9e2169e1cb", "X": "190f88100da62eaba80e55726b505018df1f4047a81775a9ef16c7951755d758", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"751775acf6482d2dd97c6ea2cd457fde@certivox.com\", \"salt\": \"04cf5c0c6b7a91b1a7e1ffbb5ed000d6\"}", "test_no": 53, "UT": "040f9b48b5ad159ad7716d24b297fd5dea405ccc2a7c51df68fffe716027d0874f0b54b0173ddf017ae8b7a207a8fd2201baa09c0d37bd086651bc12ac2d41b9a6", "MS2": "06f17921c863079f38817c566ca6d5fcb1461420fa9a7558b8399d58f604b05d", "MS1": "1a00758170263f900efa358d8e32476a531eedcc981adef80f969dcbc200e873", "CLIENT_SECRET": "041c7acb2fc0e1da533715bd39adb164caee2b29f16a5fbd5dd399aff4252d197d08c7e46773ec63845c3f21c3facc52f42dafe25385bbb0c8abcaceb08b6cafee"}, {"TimeValue": 1437055595, "SS1": "009ca5986b76d54ff1a5cbcb68f1dbc42b103be776b19f0eed3fd7da3fceec401716fbba0d347c634af913c68134e3b4f59de4d819ff7f3e1bc79d76dfe87f3f04330a7038fce787d5f4b088b1dc86a40895e635119317735738b08d5be9b024149e201d8516c1800e9e6d9554ff630f34cf34d508198471e9c5a73a8bf8e38d", "SS2": "05ad3fe437eaed1023364667422203ef0fc6daac79678002f28a927b27d2ba3912cca357b2718698617b679db67709ffe68c1a2371bcfcebb86dff840acbcc9516ec0bc79150773fee4e997374ae8cf425339546a5bc8948ab6dea94a0e2d1cb0c83e2021f1ae8bf0a22c043686f1ef4f0f5fa6d2a625f12a5f2d15a8272e02b", "DATE": 16632, "PIN2": 9073, "PIN1": 9073, "SERVER_SECRET": "21151b259c59bd802ec5a5e4a06c38c2fde88f03e2ee8a9190257796777db3670425c785b2bcdecd2275c660c10d527cc8e4591178c4b738eee5d9784ba42cf8116499ccb903e331517002a6bd1f3717f710ee62665bed3f5a9fd4583e8eaf3c1c4ff3773d075a263705a9deda08f9b06b772fa21d0f843f54a123cc18a85128", "SEC": "040e660c31345ba38bf9a59c594b86e1920b5a88025e3088e6b6030d638474dce20c723b7ec50787c7bc8d64560c81b3b845f5cf8815c3c9a6338e6e650b054cb4", "TP2": "04227e37cc08db7dfd48767929390702c19866d11cd661400f1ad7137e643f35a102c713cc0a0c0fcf46f1928eac85ab86f64abfbaa841d4c7162b8137a388e5ac", "TP1": "0423c8f6824fd78cad96658fbb46831d74efbd965a57dd2eca01052bd5db8995241b1aae6b9d943c9741939833a4d78ffbe5016649fc526a14bbf50a2a4725fbe6", "CS1": "0420fb50cc753686815b715ae224816cc88c7e9ce30dad6ad3ecd5fc905a4637d61ce2e07f36425d188fcac001c885fdcca0d292b85f34ef6a9f5a7d7d4054d459", "CS2": "04171f0cbeff5d74ea5acc141ecef5359acb2d64d98e9e7438ddd543917f297ade0b7a4f473d92836d6dfd5faf3a38dcd089c326c1ac1b649257ecf5b953175d79", "HASH_MPIN_ID_HEX": "a82547840cc3a2112e3a59053b31b91205528f663fe6a8a903140aff527e9ad1", "TIME_PERMIT": "0409d69b0cb1b15edfa20aa584cb1ad3b9bbde3f88fb588e4367e5ad82d1006698099f88c9669e2cde7dde347674c55b1747d020bd188db1ed645d9343e6139538", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223566643432613233636232643632373566663836323236613761383930626235406365727469766f782e636f6d222c202273616c74223a20226137353938633963306163343535616230656563636339653934653562663861227d", "TOKEN": "0422b6bd324c12c7a4f152c9d9e9473cf83a725fa59fc8a1876c2b67ef8752ac64035595de7febab2a2602546c9478b5b639f6df05e6739aa35cc550cad9e3acdf", "U": "041046bf9c989bfa479b62c458a623495899228ad3cc68abca683e80618463764b021a866ac7433af9529af4b3d54f687c92709b49edcf70347b408105392597b6", "SERVER_OUTPUT": 0, "Y": "227ec4867ed05b4cf131732a8538670ca0ffc60a54045e9bae06d9e140fb666b", "X": "15d7e79acfb7e24007e8e014e2186334f2ab93f7731131bbfb5cc6d5eaf9267c", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"5fd42a23cb2d6275ff86226a7a890bb5@certivox.com\", \"salt\": \"a7598c9c0ac455ab0eeccc9e94e5bf8a\"}", "test_no": 54, "UT": "0408add6dd7df85ed2c9c2ab221cfbe0943ff11aaf50a25f8a0b209a8e6240b537206ba25dfe5c4ebc4ba3fb52f364593a1e36ec18420b589469a1d1bc18732775", "MS2": "23519eb84d43ca58471a823c9afdd425316929dcb3695f78d7953b946d00c403", "MS1": "0222fc3d41f2afb09f821165b3b2a1fe810884a0462a23969970dcc1a9c4b38e", "CLIENT_SECRET": "040cf3bc1299323a748ee4b5ea7501acbdc2fd653aecaa845f49a76ec2f6131c4221be0efbd92fb7cc48074e31369429dac31114772216ea804633624df2ef6e31"}, {"TimeValue": 1437055595, "SS1": "202b17048efadf59f049fa10dc46479f50abdc1755294458991614786d237f0602437f76d94e877f12d0fcf11931df0cac97e33f5bc4c7675172eeb1c07f3fcc15fe966ffbc535226f865986d3b2340e2ce294bcdd661a2ab457083f185e0a1907c85e2dd611f687b9689e7d1389df307c60714eb32ff4285427360ccf01387a", "SS2": "169abbf768d7d45d82d241b5189ef39ece5ef352f18d67f942739b881d38a8f10a0962ac673deb1abe135845e0b5ddd0595601307022659257b14198d835e9a7084e03c13c75e8667a4ee025edcdbcf31d7e34de9facbfb8bd8190fd665b1d1d1e0d62c70b70de4bbe30bd4967e2404774e8cd7245ed809bc677e4555bb9267d", "DATE": 16632, "PIN2": 8730, "PIN1": 8730, "SERVER_SECRET": "0129f9d6d0b0438fdec69ca3d240706d3307df9aab40e89ec4b3c5eb42890d0e165d14ce243ab0cd45689bd84f94e14829b43fd741d6c00784b4fe7dfa5a2e7a2205fd93490d2d799eccd0443115cad69d5125e3e01bd49cc2839c64dcbd1a34089c323bcf62197549309144fd9e826ef82214137ba1757e149d28372cf41e61", "SEC": "041f6a2d109a461ca05f6a98867239e6c5f79a70942e61fe96675dd1ab9788f68a1b78da4e61cfd0e3684c9f2e841246b00aa5c934ae31ab57961acb2ce81ff59a", "TP2": "040f621f545a715c6c8581e143b322c4c43b40f36bad3ad14c212cef1cff0ed1370fd4e917a28b39723516ab1298b37a34b24984fa6263c1aa9428e2ea539ac13a", "TP1": "0403eb79be636f0ade7d81042ec0fda0a798e304cd46af29ca7dcdd91b79a5eebb10a3abf0b0a26d86ba0ce3ffafd5048debd2cd74b50de6fef21fd11e355e4e27", "CS1": "041d24da08355e4a5f7db9f4b849999592b3e790d47f8827eac0cbcb12951c747a21a4981395908ac0f01a8765571390321b9f17963f88af7c9b93a56c35ad5507", "CS2": "040fd6a87965f4b70684342f4ed9d346013346f880c52001abd8e5d4883744205702a8fd438d0d68abc78eac5137d39cf9955e546010f7786f799cef04e8dbef51", "HASH_MPIN_ID_HEX": "598c7d85dd051b50e68afd0a36230b6db8c6989b7fa7ad40bcc4bcbcd9a4d2fc", "TIME_PERMIT": "041a1ebf161e68be07765abcb307ca3571ce441265b963b024449400b4ac8ff3af224444c6050438c3ef718162d46cd6e46977fc15e0db1bbf350a4fd238f98ba5", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226534336338663263313735373639366163353536363736343237393336643833406365727469766f782e636f6d222c202273616c74223a20223232396633366164323239356337303033376531656334323839343735666136227d", "TOKEN": "0423785e89774dc0c9e6dbab8c6be2ff03367ac02fe3e07f415afc44a59716368f04bdbb397900d5f99d1a24d6e02a6d8752bca7b72d74aa38201bb0ed80ce69a8", "U": "0415e89a2ef8f0e4af142964cc2c175be0246a274c23beb269fbac1eee2e50427c0a0688245afc0b5bf590380caa589e4ae351df4faf0a7b15beb4a0e539f26ce4", "SERVER_OUTPUT": 0, "Y": "143bae531fd7fc53faaaba83e3a9108e859ad8391f8d8de7077ffd1f87f81b22", "X": "15456fd91919bf4218f693f266e7b7107b03553442f257339ec31c267058a0ff", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"e43c8f2c1757696ac556676427936d83@certivox.com\", \"salt\": \"229f36ad2295c70037e1ec4289475fa6\"}", "test_no": 55, "UT": "04171a4a9fd3bcbfc8f999d7f3a96695160cef7e949175a72bdc82049922e979b6118ce3b95ebaa5e8a7dcccaeb547a2af7c01b3d2f152e4a0439fcd1eafae7fb8", "MS2": "04c16815ae9763786a538dc9e89c4acdff83813c7067eab9d04fb066e14da939", "MS1": "1a719f953904e5be222e3bfe388928bdb1cac2ba1f177e53e7e95827bb8c422b", "CLIENT_SECRET": "0413d5467b724f3dca411f3e682ed2b014e1612086033e720c35bb09fd35359d64059ce87dd48af2fb2a45888e21d134c8f645c4036f007ffb9d8d9cde942d4ee6"}, {"TimeValue": 1437055595, "SS1": "06eb96c8f009dadd0d97cb9a86ab89cdb950af18c41bf020db3cf0a6f22100de182591f847c419b31de68b81440bb7009d800296786703461ca7a77516ffdf2d0ebeaae1b5534c7abd971bcfddd46e3e19f84fedc1c67270155800895b1c598c1b89188c4074fd5608dc9ccaa4f56b04bd2611f14cdc0de3b7fc4beb78afd739", "SS2": "0528d0a273012887bc42ad9933770cd666607ee5f3886d54d1bd6ddeba9680b21ce13de4d43004c13399506880f72ef44a3f18f160e2beac63d6f2d280f88f4b0ef6aa451e6e311717962abbc3a189547ba7660c845eb1bbe2c5dc1e7de7129220495f2ede8dc68adb6dd860dd360f1f8ecb7d59d5736b9b4cd849f600d30875", "DATE": 16632, "PIN2": 8432, "PIN1": 8432, "SERVER_SECRET": "09fd13b47e770ffad0dd3317829fb6ac85cd10d669381b20c8a762e6c965149f147c29da02abd77906d91b3eee59e1372652c4cad43ce298fafbd06e2bb31cdd236b1d0eec913825ab8ac94e831e078ae47ab32097a62098a4451ea7d61337e7180a447207258ebcbac49acd2e40f1a71eaffc22725d2c4d95dd8e9f1a2a524f", "SEC": "04022071513512f7d2ca3fec369841978d4e3a681d446bf9f6c1fad9083e09f6480d6198f2875e528b204cb82d15cd437bea2793b193fed6c8f6afddfef72f73bb", "TP2": "041c501abbf624f58d093d41fc5a7a611e1c021e603248891cee9e2fa7a060c11a0bea821f4f46651e80a70914896014502cd90bf19afb321f43d48ab45b6299f0", "TP1": "040db8283f95f41bdba220148fc0e86377b7d0fc3e111ebfeb0dd32d8ebd32c3ad1f2c181e769a878e88b18001043a33eb6299cca4401967fde45bb00c2c199ff3", "CS1": "0407c4c0ee0c066fbb7b3b14f010c670ca56d51ce2b865417b698a90ea8ce7e9b2196a095f1bee2c825ef1ab373b1a3fe3062115cdd36d45f2fb997bf21d7b9f7d", "CS2": "0418421371ecefd4137f6a8b3bbee44bcd2a61ee09ef1fe93e3c48da957c8c99181caccb6345e149802762701aaf2b3647496d29515997a6220eb934d54bbf00fa", "HASH_MPIN_ID_HEX": "1774eef7f335d8ee0d6dd07dc01f98c2ecd7d45d02adfc3b4bbf7f31ffe2994a", "TIME_PERMIT": "0415204648c11b2ce239d58ceefd4fd95c378dc2eeac57c879999860a5040cc08807e3aeb59c2b0417530855bf6678b379cc723a8fe7cebe7bfffe9b504a145e5a", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226231303464316466663532643238623766343736623537386234636132343064406365727469766f782e636f6d222c202273616c74223a20223830393862306665353530366236623531623236333330356639343133353737227d", "TOKEN": "041e4da912401839de2722becb5efe35ba067d1443401ec9a44dfbf1bd07422a7e0c1e4ba8f4662e466c8eb4034dd9c44b46450964361d9d3d7b151e925902f32b", "U": "04220e3c44dc3e76a6af590cbc7fe4b285b31f378a36b41bafa4af3ff81b1e5c881e6f661d052a86f91e43a68910063b43abec4a27adb1eaadf3da9efb5f2e6d40", "SERVER_OUTPUT": 0, "Y": "22aca0fd0c0fb7fd9051c48307958b172217d12554ae6b7bc2157163db06640d", "X": "1a6e5dd260e343c12c61c4deddd1c5bdf6444089d2c3af45e029ac2fb44e15a3", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"b104d1dff52d28b7f476b578b4ca240d@certivox.com\", \"salt\": \"8098b0fe5506b6b51b263305f9413577\"}", "test_no": 56, "UT": "040ac7bc847a6d4023e5271d5c778d1b2c1700c3112aee1cd82b82df9983e85d271522cd571173209c18d0d14ec922292dce93b044ee53ff3bea0c171d6f63fc6b", "MS2": "16ffb4f7bb2bbe08b146e3f936b88ff80fb5c6055144a928f054dfa7f7dce975", "MS1": "1465ba59b8cd8fed33775c9d9fe3b4e2a1db93bb48418252e64a90cc8f698d6c", "CLIENT_SECRET": "040d8c2e642eecb76528ed979d034e9770f6827afd6566ee31003bc71ff71d789912ae2c1c0890f82bfce812463c2574f262e3b04210256c503b91589ff95b2dc5"}, {"TimeValue": 1437055595, "SS1": "1a9a76648ccd25c39980d7de318039c8fe77c650a79a96f4a38bd2850d09ed35110b6cf400151dbef49e06dce4743bb707d0bd0c8a393e1e18c0909f81881f8418ea2a1c7aa91b59187940ba2b1c953ee20dca2f5fc2fac5b75f57f67771a59722155cc8b85938d1d2f4cee795088ff6cb61fd7a313bc7cc675a482839e5dcb0", "SS2": "1193e9d1805fb6cc0ccf11d2ed79ea22ac516fe34e9c9203e2f12132b66edf30075a20a071e5df88374eacf42dc6fb9093e8aebc0b9bb6e90bf1462532cc86e50241b5b5e17c2a8db8b264d198ec3a053a0a35dd2f3a4fbbeef66c28ef8cc93d023064a166ba7b123c343b1254ec589b674ed1135cdb086ba73bc462cd2a9e1b", "DATE": 16632, "PIN2": 3984, "PIN1": 3984, "SERVER_SECRET": "07cd0e913d854fe3eea785402fb69eb6646ddce8277846a1e67c9b14b7b32b3e114e59a3ce2409272e97553efde5bff148c000af481d01b8e8af53a069a9d5b009a96aa67843c7b7e317671cd02d24ac3d55e71f426d4ab12dc1f8c9b03616ed1092929827c3feecac7207d007d3ecaf3b1d6f2f4ffffb42aca3961e2e94ee29", "SEC": "0413e8b4059932ff05c33c8a400b60ccde7f268ef3c217e6aa4d5a17560f399ede0fee4cbb8ef39cdd6528e1ee937b695694fb20adc0bacc38d39b0ac2d1620528", "TP2": "04127d8a069b21e230e4bf216b49d5bedf56567d83ba5efc25ae09ebc62cd70ff408c8eaaaf9816d4ab3ad4ab928111e82fc1b797d4b0b7a8607e34805565cfb99", "TP1": "04177334a7dd36a99fe85901e0f7bd36f3db6a09955f85a5d37f729e5a12d4a1431032913ae19da0a8a7635b36ed2dc952b5d78ae3d76e36292a8bb8e380b6b398", "CS1": "0408da568d8d5dd1e0cf4ee2fe22b60c62cbe0b088a7d306e88da7562eb2e92483049684eb8ba5d992a5be4813eb998dfef87f10d94ad4836ca34cd37217f335a2", "CS2": "04231811af1927fa4c6c4c41ebef2c7e298f1a1b6bf4c93ab065519cb4235edeab02ffdc8c772cd055fd9776c26adc73c3e092864edf585e1755d26741e92ee8aa", "HASH_MPIN_ID_HEX": "3152779d5168eb2b11a77d42e107a20f98164c2c0dd03421789ce12d0d494fec", "TIME_PERMIT": "0415e3a0dffe8e5491f57be38893644fef0fd2ccb8967aae09c2c9ff90323837cf03c1af5b1533dcd883888746e4b6b8e429a270d90f9272bc2051696fc756eb54", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226665326231356637393465333133313432303661626263663862666135393866406365727469766f782e636f6d222c202273616c74223a20223865343466623536323661623663363762616131396434633664613734306465227d", "TOKEN": "041e4aea60927e2fde85df68c987756260fd47a9047dc666a35097c370b19f7a810cf1f2ea8cfe0b5862aaf48f87096c076de52039391185b66f8e1f9d8d36b65e", "U": "04170422cc2568932adf12860d6342699c18f237500832375f4bab68e31af8e9a20ec26f487a4820f9be8f92b16695e153d35e1b11a6c091a76c8adec24f55f12e", "SERVER_OUTPUT": 0, "Y": "0c0c22578d22c47fccfb0d7fcb90ef5a2c29daee4683391216bb20affbd59d61", "X": "0cfc0e43f54ae35a58c3608748787ab7666db1f777b5b1b947381824da35b89c", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"fe2b15f794e31314206abbcf8bfa598f@certivox.com\", \"salt\": \"8e44fb5626ab6c67baa19d4c6da740de\"}", "test_no": 57, "UT": "0400f5f21b3c547be43a035d6047c826263c8bfbdd879c999516d8385ef288333e10961d809dd4f46ba47d5a26c099de3f6d4aea1f38daf5591961dc301ac23d41", "MS2": "1bfe10302a2da4204f9b3fd53410ee2428b2874b0bb81200edab267629d2c8f7", "MS1": "0ceb4310e15241a0d0041b2de316eca6eaeda7eb6b07ccb742da2850fb15dc93", "CLIENT_SECRET": "04100c42d317470b3e5377804b5d05af91c0b7b57f24d699c7fd6fb0907391562611691eb1316caa36800e2ee112bc0483bf2deba407bc136f90ef75b8d65b50a7"}, {"TimeValue": 1437055595, "SS1": "21fab3d41a492a9fd180f473e91e5fba8281cfacb02fb10800efad9b64db6f0c0c096971fa5bf2ce9f56d96db76857f82042bf93b3f59d54942c59c96d36fea713ea775d8fc0fa33e04c980c918a39849cec3810b83e0690624e8d80f04f1a6709589ffb26d140cd8a9028e792cbaec7580ba759cab6c86c9977899df64294df", "SS2": "158fe442535834da0104a2778aa67228044f2c4fb080e8e5ddcbd63d53947bf807cc38b747975bf851ed048192870fee1eec0c6276f2ba9b7679fc9e737dfa0c091af25e5fb22fb6b77af190ea8f09de33827d75989f2ddbf866ef8cf0e2b1c809986501ddb9d75878f8cdfe6ee32b39bb4d6e9916547e089f8af454ece99944", "DATE": 16632, "PIN2": 8691, "PIN1": 8691, "SERVER_SECRET": "22832ca0c09eaba0305bd2fc38892892c829b9dd85126d7c0cd83d49311c0f4a15a052351b822c9dcc03c8c032821078201e36729b428381db46e015815acc4118b08f36b4d21085f04983ea971b1c5faacec0f7a86459bb1fc914c2022df2410f4eb149ee9033b05d3a74521b27c4204b46a6d88789a3692c5818b42bbbab8e", "SEC": "040ce6b717c9ee271af7940d34f6c125874d2ea057de2829afd1de71b6de14fed000f4fec9f90bbceb0170740b3437111cacca283422da1b3d973222145b69f200", "TP2": "041f6cad39bd38e8f7562c8c5963b879fc84caacf5efc8eb3384bf985f50bc6f9714eb1d9feda183fc7c1b9d1a5340966e89650a6bda644e9cc6f83ebea5f4693a", "TP1": "041d13e5661ad84671521a407d83f5b4a96753ba3e711b10616f1da3d93a72bf4b23c701c556eb062a3b427bc8f07182cb5841c2dc9f48b805002be4076fee5de0", "CS1": "041912c4194ee31fac6249f89f4f09511c13d7a3ef73180bf63cf09ebbef7268cf1b2b721fb4f34ce24f13aa6912e8c78905464e924fbdfaedf49fe61e8f6f638c", "CS2": "041986f5f4b49afc86161603c3a86cacd80dcde93804dd7ff49deb2b4c3bfbc75012d80372a85d7a7ee7ee0f7b7c33eb0104495881d4833bd0ef942911ccef956e", "HASH_MPIN_ID_HEX": "c7cc1e221b6f22be688ed83ee88a2dde16f5b66c2f18fc7e0517b08c606a1494", "TIME_PERMIT": "0419c34b9ab91cdd7df53a557a5e218e5558c9180573182942d56fbf1cc51e5631213d9eeff6ed05aa2b9d33a3f945d77111464f5c515dc1a2af9c9fd176543947", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223834353065323833636537336433666136383466656637663837613038303064406365727469766f782e636f6d222c202273616c74223a20226238386366356466666364363665663236396630396564303035366261393565227d", "TOKEN": "0409c123b55f8f9d744b68f1bede0cb6f2e5b9e5d09f6430d83842271d4f6900000a2ac834054806425b55d434a4723eab9b3988cc3765fce9371c9530c9c9ecc6", "U": "0403dec88b66b791888e141bc992be6661e242be3cbf331e637406040a580117521df426b73dceb7aedbf2c0f077b483d8ef565308b18be73d25f7586ee74a2aac", "SERVER_OUTPUT": 0, "Y": "22030d96d291c03c613e233d3c09df4b4ea69bc72a09e31dd564d61b42e69ce5", "X": "0d0dec9824dc989c376bf8029f6aa14c68990b9bc77dbfd3751d23fc775f8dbe", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"8450e283ce73d3fa684fef7f87a0800d@certivox.com\", \"salt\": \"b88cf5dffcd66ef269f09ed0056ba95e\"}", "test_no": 58, "UT": "0416f6514e7bdc6ee649285248f25c4d83c514df4fbe16bfaa5cd1d11c12e6bbc60f0b238a6a64c51bb26a34d9547d1506d099a0dfa0c45527d4372176ba800fac", "MS2": "067dd772bac34f166d9e0e4e51b77d6e4d8a58ae53db574d585f4fcb92fa9de5", "MS1": "1a9c2d3a423fe5e00f078233ec39804f32ebfcd8657f53d8a8f93e922ebab6dc", "CLIENT_SECRET": "040eea5646da20dbead2f4ef6046cb80dd078c9b98acbbbd649a9a3afebc13ddf01ed5de3e35634bb13b0adfbf726d4bb7c48c9b0b749e3d0699bdd1a5cc1c9a7d"}, {"TimeValue": 1437055595, "SS1": "031248af7a2b0204e2da10ad1f1b5288042f4606d870494f9fe835f0380a5f0f0f9ca634f8dc7960f94313c0e60f5cb8b1254a6ef690b6fbfdd693fcbe8b3f661756b059a2fb99bfa663adf5b06a2423184227eee97772e415827d85d6bbdd8c1b0c83ff3f2435ee7e61f83132bd9d3bdfe3882fdf729e6c4a080947fc75b201", "SS2": "05ac734a890c2e3cb95f37ee81934b20afb5c78803acf5563075cdfbc0615004164410a1930e89309d0cab37ba8b33fb4ae306c9e0138b2e8860eef6c54e0d550befd8e087a39053573afa247bf50ae7218e3b3dec1954a1d99c67408e046b6917a5899bde64781ce8d23128ad2d8d199886f7153aad1059c368b1f8029eba7f", "DATE": 16632, "PIN2": 3193, "PIN1": 3193, "SERVER_SECRET": "1df3aa672261833cf9aab89b962a8026ddbaf452ea9f584ab6a12bbf19427eb2148960dff04492a222fda40e32b9be3acbda902198fb7b5c39125b686ccd0026233afb696dfa5e00b744823d8d9aa451cf17dbb1f13c36d67b9117bad36bc9070cc9992bb0499e77b21259a0b6326faaa5e19ccd41b1c1a56a8a6d66287eba13", "SEC": "040f6cb25a2e7e3d9e12189b0a7db9dd66f9dbcce05ac3c050473c41b29aa1452c0f7e3a090e1b3eb50422f1872aadb3f2785ab616033ae3042ea2cda5226e9901", "TP2": "04079578f7e5c2df147acafa6e90b35de81df95de27a2a91baae2aff991beb7c5917f2fef74b323954cd58fa7c205e5380f4adf998eb00da50374e516fa15e7ae3", "TP1": "0421d85c2ecd984db746e3925ee67f96b8826a95c0ae664857e788e5b2ba2d0d8607ace95983d9f7325c49ea1e5847a459daf34f57ad4a7b65f4d46b38a0c809c7", "CS1": "04174f779d7f79c62c97350a1b4d45bc62214192c11d794616a8ac41226a92d2121d54ff1b8742ec51beacff46e06451544288fff213de1dbcda3b4380f7fdfec7", "CS2": "041fc67928d9389e38725970ca56f6353378031955b45a40ba157cf4a7a41e363207c35e9b9466fc7fb61b98a932f2156269ef69cb436bd20357b67d8a91087b57", "HASH_MPIN_ID_HEX": "a7c2f5dab59798bf2fbf2b78573f00c6732af0f6b0414163c9e6481eeb6fccaa", "TIME_PERMIT": "040ad8af67ddd9da3a686be923a369df6e62895d77670ef89ce2ebcf1bf8ec2089211bdeb2c510f7296838fd285cfc75cbb693a938477274ea695dc9b5eca2797c", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226466306162373063396438333638343663366136326636376337356534313237406365727469766f782e636f6d222c202273616c74223a20223262323133376436353762393961363135306664326666626461306563656137227d", "TOKEN": "0405203673da2ccd428b51fffb0d73eb2bfa9a3893deed4926b5b8e7ed45d36bb0144397eec1dc2ea2a563d57b2151b83058ee11bada12678eb97fcb4261a5e057", "U": "04023b484d948dedd489047669d1af7c23cf6f370ec8d7da722140142028cd462e0610b0a4caefd11c49e0e177cd9ede08e347a47d0c597c0acab04031c92cdb96", "SERVER_OUTPUT": 0, "Y": "1333a2793004749cecd4905161c6262296a24349fc4312234e07cd7bd4b80dad", "X": "02e4306b3e7669df2bec9d477837fe884a55a050e8778e6e764b729a3e468d89", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"df0ab70c9d836846c6a62f67c75e4127@certivox.com\", \"salt\": \"2b2137d657b99a6150fd2ffbda0ecea7\"}", "test_no": 59, "UT": "0418ae530d9326ffe3735f19e9aeaa750499f44ed41f6b4dbcd7e538c5174cc4a518360a832418c3fcf949be9c4daa487b3f0e5d8804654647f26daa207bac90a4", "MS2": "211b850db5272175866b588c5fa7d5595842b49c90bb62f84b645c74a4a4f432", "MS1": "076658e393f5f519c00b9eaf37cd20edebb838ef02bf0f4b04aee9150396a510", "CLIENT_SECRET": "041874afbacdc9dc3025a805dab53e999670e2ccbc1945e2f205f16a5d8cba19900d94adce24de1127fe2cd771e5ed503ddd0fd8e140b78aa912d549fa27d4f766"}, {"TimeValue": 1437055595, "SS1": "0831de9c79b3ec90ba9727049f1da874c9bf99f8d8d154316ad846f43d0af14f0c885bba59aace5068418a9ea5019c517daf9048bea09b0d278ae8942a2862c8039f16840db47ac38786b1d56edc260b1d245f8d234b4689ac3ccc543ad7be9906ead179a3ca255e6c2748d145122b3e78d1eced326720e15c9d9d3bc95382d7", "SS2": "138b86433347524386bb0d678aa8d98675cd287df75bbb66cf4d6b68a1060057187c0ddc902e064ef5711f9d89b44fcc4476aa3bfa6ad48f6988066fc9013ae81f2d7294291e12c93b3270fd74de78def655e9da49e46f27a519afeafae88b230fd8354a567eec3e0c01346dcab5f1dd910c97d97978f707c75964713950434e", "DATE": 16632, "PIN2": 9159, "PIN1": 9159, "SERVER_SECRET": "1165932bb9e867f0e121b3de730f9939976f843bd0b7592fa6bb2cf66a5293ad15a36cd4b67efeb39057652f5ad5f6b090b2e7ceaa12fba6118802fac74327970fbeb5e927a3933dcc1acc5f9e886e1cd6a27f191454236b3ae3720d64f2267d15c382e17fc37674b448e2266149b6823efebdff6ff62a3445e0c2e5dbdda23c", "SEC": "04121f47230450de0c1d5a33261b609df260c5c7f7f27a4ddbbb5b2f560c809d8d03fe04ae9be30c9e3e5a70befb2ded5029f55fb01b128cddbe948c8f8b2900af", "TP2": "04117a967dc47003f7d9236785553b6b2df7999b0e91ebb2475e0707c11b4d23090e4c109b6708c7029ca26362add4492f8f93407773623f5e86e4a6cb77649e83", "TP1": "0418ba902ac8b78fff69c6d09a1fde4116ec0ec77c7521577bd3e07676fa27c6df1c1eba6ad90bd71a710b1779864f0f960641338fd790e40a2f85698880e54f99", "CS1": "041800183a86e2d41cc8d472abcf2eb463b9cef27e6d93c79997e3022372811ab4164145bc32eb0dc0742c8a8072792b323358ef7cc7aab70ae466a5d2c4c2bc84", "CS2": "04108a018c7f585f490e43dc6ba6259422866107dc619c363ed5d51f5ea983d3f400eab3721c381b66977177700d13ce78c63331c61973ffd5bb84ce4f6085006f", "HASH_MPIN_ID_HEX": "8a809bfc466ee211e694250dca9653b4f96b6db6fec5299fefbef4c608907117", "TIME_PERMIT": "041828a34a38464d1f9140b2ab081f66e42bf7a2bee01063ab1ad0fabbb615370f2218f21e3ae6c381d125159080bcbf9b34e62f83c33f4fe3088ab9cf0da3451a", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226439663361343264366638313863616662633834376565636463303230346439406365727469766f782e636f6d222c202273616c74223a20223035633536363261613039653736643832333734363630663336306136313031227d", "TOKEN": "040ba24cb72b5b21967cb4583b25792d99c0039ff2ce70a457a56c1e237f67afc40bdcf5f91620d8e2437cf6bfaa9b7a7ddcaa9464c92167048d7434a5c03f081c", "U": "04164ba856f646dd188be176f28791b3be849a72cc3fd62ff57584d5e7b83763861500dc54458607107eb69935f017d285ca70f1703508ca590c67a07c19eba573", "SERVER_OUTPUT": 0, "Y": "22635e51b0c573b8c7eb6999b000f2c839231f6a05e0b1346daf91844ce971e6", "X": "1c34e1657f52b15ddf71723ddaddbd199b4e3ecc516643e37360374f187aabf1", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"d9f3a42d6f818cafbc847eecdc0204d9@certivox.com\", \"salt\": \"05c5662aa09e76d82374660f360a6101\"}", "test_no": 60, "UT": "040252d84b0f56e9574f05cc9cd6ce98500d31efa4fe9e1fecf3322e594142cb5c0121c57b2bd80e8cc9bf00dd8899f2b523c1d81a05c53652c6f441489e13f6cd", "MS2": "18317df3d7846882d7b677619d414539a7b15d3dd4731b697869de7722d08929", "MS1": "114aae07d3f4b95367d82e4cf72cc161e80c53aa08c6813da21754db091a1969", "CLIENT_SECRET": "0423a2867ef236c655ae4bd9235ccf607a06331d16a340401850a6e7ee0ef84af01474e38262be1239996743f37fb6a074eaf4e49888f203bf729bec679d1e4805"}, {"TimeValue": 1437055595, "SS1": "14a65efc465ce3269d66fc546bb7d0a51bff09436af6ae8752292f01f65e18c110564b1605eb58cf4652be41af0286bbbf27422dd7d48555f64615c1dabb447b0606b9188b1a04c36f7a0e1364be47a4ee94a080d6632058b45140034b81233e0487392830cf3ee7304dd0a61e6d18b51f02737e31f19ade5470dcec1e21874b", "SS2": "155f6d087d0d1b21c0dc36a92c35621269e060861dadd1895fc5dc0201de70b101d201a443c16f1ac530c6905943f62f176a16a267e1c541dfc40f681fbd9f4113a5774669838a2bed18332eaa6b38ca2f72a53fe17ae482238bc3df10b2022b0f11168fc56cccd2c75a2f5c36788512f85cb239486585494a1a1aec9b92baa7", "DATE": 16632, "PIN2": 4348, "PIN1": 4348, "SERVER_SECRET": "1339177331bcb6353d94cbb62552e4629bd8310484414886dcda58684258ef63177932b60f43a79f17a902a53c064c2095a85bc303b7a1714b670539768bad4702efec2c15b2fdf9e3a0cc4480b93ba12425651ede0bb332943901830839f2f82008e57028063a636a294b2e0936824c1d093fc4e5795645a8006bfc99c01bac", "SEC": "040221d5d32b4f486a44afbf34203a906f5daa5635d8ac15e13e07d3e70d1876390f1fbd3edac1f85e0fec1e243707784617541caff1cb70b1fff1f62ea0edb015", "TP2": "0403cfc59d83de737ec13c80c2ce6d033c92ae8aea05d03e0ed0e80dd78c2b7b901e81449d1c4dc785adb04da86230ea4b26e0ed4f1bde312bb5f70e52be964553", "TP1": "0413ff1e05bcdb4a1fdd583d18f3fb1b612d770f43db5186de703abf1cc48e306204995042e224412dea3553fe37fe928a69a4f3e78490f6a480f19c6a61489f00", "CS1": "041d26172c08d81e4df73b4ccbdba0fd92baa08421a6672d0c9c0d6db81e4c50f802342c2d51e82953ce093826f0db3ba2c8678443adf323202d2b5da86d5abe9f", "CS2": "0418f293e8265061674806ac7b437b85579892138efc2325a0837aa6ba7c161ec3031b775386154d514422037331c405a0fa6b44c4104262157a9e4b7373e544af", "HASH_MPIN_ID_HEX": "57b66875c3920ee281f5f3eaf9835e4f0306e7f88b1086c6a97233ff995a4bdd", "TIME_PERMIT": "040ba1273beda3f54ff1f3928868bdaed9170fa0440b164dcfa2d84bd7fc060e140bfab3d7bd4e8fd14b45534318ae47b9fc69a1186be6344deeec495ae1c36768", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223131623834376566313235663933613266666136656364653538653334666565406365727469766f782e636f6d222c202273616c74223a20223639663533333633356339636239386661346432316637333130616433363665227d", "TOKEN": "042306952ec7d954ba6997dec7a0f5c18ab7cc75da49bd81af5e533c01d11ff84b1048f8b150b453db4c37f881b009cb8534f13c6d82db57b0a8335d3648f22893", "U": "04235657a884ad4981f9ff32d3487b9d4269994a6d71716e2b6a0ebddcf4fd4d4c151a2b13baea9999ec0420b26bb340d4350ad7ef12f4967ff2f522162f6ce007", "SERVER_OUTPUT": 0, "Y": "0d2c407ec845f5248e525abcb2055901b842ab0ac36f8da0837bffd4e4de1469", "X": "17915451fd088e3584ebdb03b26454beefef8095c6850b96c0ef04c1eb771155", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"11b847ef125f93a2ffa6ecde58e34fee@certivox.com\", \"salt\": \"69f533635c9cb98fa4d21f7310ad366e\"}", "test_no": 61, "UT": "040b8e881328f2fe5d67bfb21f5377ae074097a85625fb7264eabc018f9222251615e769cc8427b087d57dfb9e6077ebe58b987ba12db98b80de0eff89efde7cab", "MS2": "0b50ebfe5ba999dc58e9c2476be7e48c9ed6dfed8f14162c708b5b12cab61603", "MS1": "1e6fe24c11d8e731818e45926201d38c4e34c17aaade3704be1a5446cee1de99", "CLIENT_SECRET": "042229c2ea3885895d30d8493a7d1b292bc4494eeb049a7ef769e962569d17d8dd155c41ac77da5799688dd49ace0bc6215b230abd98a92f37992fcecba757013d"}, {"TimeValue": 1437055595, "SS1": "0d377f323fe58fe4c4011d14427e4f13430719f6faabec744933a7095ad8c9d11a5e6e636113f1ff2d62b10f5718ba7ab8e2f1089031e6fb1dfdcc4bd0a4824c0dcf962064d15e54c052ef816689637bf2beba54955a32a25d3abf4798633863100fd6b4d5e4653611da8aa7215dead6539491892c38dbc70de2e28951cbb726", "SS2": "1759a1e0672c8fde62f31f44941e0fc99cb8edde14208e974a962d289a81d4030a479b1bb05a4a7a5a9876d19877bce0aeb0aedadbec52a6c8c42d9df6ff988b095c52b603cf65c49f8921e3be39019f9b85f1944f5dee05f4d56c2d2bb875711f890c2fa1cc120012c79fd5ddac7c98303b359a56f958a96fd4e675ea2c8d89", "DATE": 16632, "PIN2": 9856, "PIN1": 9856, "SERVER_SECRET": "095be00b18a7402271174887808b6b0c5557acc2d66bf51889ee9d125023336209e872026cf8f7f3e95de214b567b4c0393734af3cd3151476ce0ff9b52ea14a08cdc4029866cf7944cbcf5456eabd450db3f841af587e72a3916b4f2a1437e3010b7759661543e6bb7374ae6e9765d711833f3fa097062fcc4d378666d30415", "SEC": "04031cc2592e9d6be99c58e5d0806519a81ac1d20e003ab1c7c6ff2bd497d29d840865d5fbcf3c9db8d85f769c6c4e6e8834ebfd3b631a0b1a6cde92ad457c76ff", "TP2": "042004cd2193226554471f81f65146fe761cc5f59b6cec805177741518db218939210d805e812e348ccb9df339085195ca9e7798cca6b2ea2b33467ff040d23e5d", "TP1": "040ebe1c5ede55865c1c8eea525191fd2e492b63e583191177ffd9ff20df83c52b0c7160a4e9d2c1e7106c52c95e7a48e32f0789933bc3c884595239f12169c834", "CS1": "040dd09131226bdaeded814c47958b4b4ccc479c91443a1ad5efb850bea720f70f0478788dfd898686ea100c6f793d504ee25417b1e4707cc7a4368201659d0854", "CS2": "041eb48624ca1e2d738aed0ba3d1b332da31f053b50ac24b33532bd660465f72b71af317f06662002c7b5757bbeaa8bdf6772dc5dfdcabe17ead87593361ff0884", "HASH_MPIN_ID_HEX": "d26b10e04af07f8afd5542eed4a2d1c2c557d434586e5266129038211c573282", "TIME_PERMIT": "040fa807169a27916a2eda5af6ff99dca9a1603aaaa624538e3febbf362ae101cd23b36151e383aee7bdfa619a691ed866bf459394616630fe9bcf50aef7064d98", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223832353463343564653733336637326532353564366138333464303239356563406365727469766f782e636f6d222c202273616c74223a20223634643338333532323931313961643065316439353732313335613338303639227d", "TOKEN": "0402636e0464aa35734a98ab4999a21a177695c8d8b7ada9c5de827b65b436fe6a140df6357ee55462fb311be4f7a041457ccb584ba96050a716c20c5532da06ce", "U": "0410c334ee40664d1ff6ff2094b97941bed27897f17b4d34c601d4730e828f1a63090adeb829ebcd8260d8d3c379490e54029fd457d9f87f3c50b9c91fb8eed717", "SERVER_OUTPUT": 0, "Y": "21caf573385a564e4befbecf36bc65dce94aff4e8442d1ee8216e005551c7cd4", "X": "23d2c90e12ca9593d2e8fd0a6a3d94b07ccc1c90d44573d4d9144a9b62b2a922", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"8254c45de733f72e255d6a834d0295ec@certivox.com\", \"salt\": \"64d3835229119ad0e1d9572135a38069\"}", "test_no": 62, "UT": "041a59ffa9dced6486f500dd6a273226d1647891d7cdeca3ff9943ea8da69f4f650f3549a4566664d0c77eb3b999039c95eaadcea657b9bbfc8218501a552f8149", "MS2": "07baae8094512e07902027612c54a9be1810645986d9be47ad70687bb49f01fc", "MS1": "1f06027aa5b37780ce6a72a2a233da776ff7899e0c72ed1464edce7986fa5792", "CLIENT_SECRET": "0411b179ce20c188b28ca6b70721894b9627976c52b9a4c5c001e511086cc798520928d1b5d3ff46846e5f4fa7c125016262a573705e5ebd90f6cb5a345ed76af9"}, {"TimeValue": 1437055595, "SS1": "0b7e54870de25e30efe2af3c14e86b00380140893ea57206fc026179d06681dd07d4117e8e2eda0ddce86ce4db199e910b67a27ece68387401cf33c5319ce0e023e3ccb5861815af225bad03fe49b837c6fc7b7374fc353f663bab44a953b44f121792a05f99d303843024fcd2f5c37a5858e32890d6ecb3fd27199dbd705f47", "SS2": "148df58cb56aa046feeb61f459598c4292bbe8f07dfb2a05966725623bf6a41917ce76af6425b8b9d7cd7406b755c53707e8c5f90bb9611daee86b7d4aa7494a08f1750fc99954c5d98783caf7a936e885636869048c1fe2c47124813243760c01498384a6ef4dad2e3a2980d286726a8979c048ff69372bed93c045df4fe533", "DATE": 16632, "PIN2": 3848, "PIN1": 3848, "SERVER_SECRET": "0a8b9b9a300bd648cae6274ec2a02f46eb8ad0783b35ff7057cd041370c30a6c218384ee2063d313c9c2ee690f3301eeb38ca25e614bbff9e237f827ba3c68491cc481cd33b2125cfee81b8b5fa643fd19c419ac0817b599e3d03ffad8385dbc1e3630479eec1435d21925b1c7f0fe6441d068e91ca368612fa58a2664d7e7aa", "SEC": "040210c03081f76ffdabb12011f6db4ca27de749b66fdf69e3a36e53abb7c0cd1c21a65055cdd86da81949e3421b9a880a29ee9356d1943fdba0d3da7d010849c3", "TP2": "042140d00242edfeb454681c758db3e98aac0397eeb869aa7e862748ddad871f65133d7503e551e010c43af36f72e7ec3e4a96d0a4aa1b7547bbca5f0a462f0b01", "TP1": "0408610b0f97db9473272c734b1f95afcaa84ea4d50798bd87a3c278e95d5bb5c818104d6362226e42d25adcc94ac45792f43af279ee9583dc4c6a146e112f981e", "CS1": "0407157f7030c0d8f2b67612f305836f575b33799ced0f4939722706cde092d674123a7699c437eb82eb50168f5bdb69ed5cbdbe19bc73653cfba3e2a24e4aba5c", "CS2": "0404efb538814d1fdb55d5efedb4461c24bbe21249ed68368d365f5de9ac46712a0d34a95caa066fbd8a05d74d124a1550af7dc6e93e33525763fca0524faa59a1", "HASH_MPIN_ID_HEX": "b93483a64396a751e50f59a0b0ba071eb72df1f0d9b8a44796630edce2fd1765", "TIME_PERMIT": "04195292e9df27d4e7bf8fac4a6bd6ff845bd3dc2fe8f422cd5b5d2b2e9fbc4b7f1d4041219b08763cafaded0e7f9cd170fe625044882688a3325dd7116ae79593", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223534343738356239643162366633383836623665343339313737333838323330406365727469766f782e636f6d222c202273616c74223a20226438646133626462303736343436323866363964666338653562313430393239227d", "TOKEN": "040e6fe5e11cb8a0f115747e463aec73a8ff5404dab7dcf23dee930833badfa8db02acb8d5c2b39659c57aafd69d4e89782ae92e331eeca98e008ae5da5653cbe7", "U": "041da937d11a11e1daeaa9ff22050aae514398cc3c30308ef22c615c1a247e747506eb4e8cf3b47c52e4f052bc020e16485ed009e262977d63c7bbc3483002ad69", "SERVER_OUTPUT": 0, "Y": "14dffa2f4483090a35f3a3ad4eebd2e4415de6c1486ca996ad449bdf1ece0b3d", "X": "2239b9e3e407b9f99e9dcad616577a988572786cfe23b6cfec54fbda771b7e7d", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"544785b9d1b6f3886b6e439177388230@certivox.com\", \"salt\": \"d8da3bdb07644628f69dfc8e5b140929\"}", "test_no": 63, "UT": "0409a710d307dfa16565348bbe3e4d1eeaf693fc106e4f9953ca62b9d3e612f7d81a3037d022fa9f5405824d8c29e8859753b7f9448c7bf2446d50e1969c4e7308", "MS2": "1c14a3914fa11ea0236704dbe73fd4348ca579140168785a97c42b1340201367", "MS1": "1a7299f40b6a4c4cacf40719fbb41527fca1967b331d052b27e0fdec1e929039", "CLIENT_SECRET": "04091496a4765501447cee44284a9ee5e901db385a31d2511fc982f461e9013cbd18e6b50e38402db76cb8384caef4be647c11a11bd0316908aca306d3e6cf2d6c"}, {"TimeValue": 1437055595, "SS1": "13bf607f416e4b196314d57e94994e2cc41001bb33fd61c9e470522a9de20c37110907118f4622945cbf2ccdcc8a005303e4c5b7d653377c69fb2ab259238815162854b5a35fe78600c210c4678bdfdcb9523316d403b51cc4292bc450216bfb074bff4822aff57ff20e6ac44bf6b10a63633ba5cb1edfa2c65341618b98e1fc", "SS2": "1a7ea9f3dbbbab6eaf701a032313145f19d1d1a257af12eacab05aa780d06a9322ceebace02f25ac26a8cf7b702c83a224cf71406179ce80f064b94d477ab0411acf2a88c541a84940da79b0fb1a8c56ee10befb3c97ced769d17591f0228d5701f8a78e0e63fc1090667fdd97b6a43203a2d677a35f1f13c499d70b62eaa29b", "DATE": 16632, "PIN2": 9840, "PIN1": 9840, "SERVER_SECRET": "22b6720c8ce0ca15c31e6322f562052e084f9608bac50f3f2f5b04069e78df0f073b98d95f17d664b25b64a9c343e0eb575d8079274fa9bd605ad4658b4e74e01120b9bb2c0069c26fa6ed458d557a098c4e79a48e85de701d5c27d65acaa33a1e6c8024b64b11fee2f6df62e71977be046d7ed14c387a85435f684ab93b7b2c", "SEC": "041583e8cca5c0da0e96d472807c126abb0d0b3d8c87d5fcd2d2a66607790f5a7005275f9ab5236558f230dd649467fc2004977a9a141219f337e5e8460f6bb976", "TP2": "0412512f56474a4b2dba8eeba796a4a166df94cb181ef8e1a74233c767cc3f330e0f2243e20b5ae645a3da9e94db7b69dfafd9f8d11a982f4b9d168179a27381ec", "TP1": "0422228f69c1ca9a60195760c711be929b8eae79e6e9860fdeb894d05cc9387379095268f4ff6126d6739f4db190f09ff9532f61391498cfdd8dd85fe52c3773dd", "CS1": "040e4112d8ea8ebf20b9e0f5122d039e4457eda245aa937d6f550af9124998ce1f02b6fbeee6d168fae7a449441ca09cf5d4bf4f5ace932c2bf9290d5a8db45b8e", "CS2": "04051ce54b38f9661e265dde6e3d6d0c8ec158ec17dbd1b93523591d62bd37a3261906e3de8e04dea88ed6f638fd170c808093aafc39a2ac556e48527b49ea3647", "HASH_MPIN_ID_HEX": "f049ade308814d878744b832a46175b4d6ce77b56f948be97f924bb1a4c0b13c", "TIME_PERMIT": "040457cbf9b0cdc6db4bba007e0db20e4be518ee4061f019fb9cb3f45d6a23254f0d3f0118108b671a39a40f3c6e78c923bb1a655982e298f316c45ed33d44ebd6", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226436616233653836303539663065643134333437366263386330326363616335406365727469766f782e636f6d222c202273616c74223a20223063363939656235326637316364386638313634616361643738343532373337227d", "TOKEN": "0403fb1ac2fa9296e5c3cfaf484665e9220b763ddc431befff793419ac94d2e7c5138f9d035836e2b513efdbdc40469a86b212b5c9f7ef6d7be6d2e4693c0fed1d", "U": "040557ee4f9f6a6b64880caec8b63b1c781d18b381b3dc48b2edc06fa3ba96bda1138109fb3f32d3255f530d2b8dc44bf9fdbf84ca347cd0e55f14942b59454e8f", "SERVER_OUTPUT": 0, "Y": "1cfc85770474d5caa4ddd0bd44b8ff759e88df5b6800fca79d21a4f1a0097450", "X": "1a742d46d555cd11450448b2fbe7c9c2db074b4c86342be1cbc5bd36964e03a0", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"d6ab3e86059f0ed143476bc8c02ccac5@certivox.com\", \"salt\": \"0c699eb52f71cd8f8164acad78452737\"}", "test_no": 64, "UT": "0411e44886a3829daf9595d61023d4d0291d928bb6df16ff58699c36d5645a43c51030430040c0b2273ddda2559db56e6ad932de93db85403b83cc77fade5eb408", "MS2": "192156d3d9027c76d0c879f32f479eed8e6ec030bba1747c7f36785790dace16", "MS1": "0d432bb1a1dfc11cd810cddb4d0eef78164a95234a58bf770b53dfe9a8571253", "CLIENT_SECRET": "0423081f4e5ae7028010a379d6d08ce23c6ed8179a8f31c6171180e99f63ff507518e52659b1985035ecf642644fecdaf28d47359d1c5b8bdf693f2f1f01e54106"}, {"TimeValue": 1437055595, "SS1": "070cf85fa0d89545dec9a3008d6a0439bca8492f67fac8123a80ddc8b798844509e8825d375467008a5587529508a92deec18b131834c08f845c4ec1d890ac89198d21142179f3b5aa65853bc9ba6bacfb6ced2c650b1cac86651828b49fca3302f0020c770a732ef136e126ac15aaca0bc0dda4638a1d69d19300fc30948f80", "SS2": "120f4fcb2a4d270257117685b66ecaeb592efbf0c39cef94885d68869c9a138c03ca344bb0629a286b69a166804a72f2a99750368f9fcc3c5b0ea5ba8093c9191e5b29f576a9d0757db3ac8ae80787a189e51e896de5dc41c3eac3a64ab423ce23c013b6388c38705c4e2a50997e195153a079f88f19ed238ee9284d07d75a75", "DATE": 16632, "PIN2": 5236, "PIN1": 5236, "SERVER_SECRET": "14e6f1129b4288f3ae0cbf9262b79bb4f01a2a62e3185b0895c971376817c0961432576f21135dc6b515945e7764e549bd3358a0b0c4a9f7165ae2ce1ebfeae91928b9c7513db87173afa3936b264eb44e648f524d22566c3a3bfc669d5c2b27224e7721b9db418052a6e402935ed6867ab0f8177b12cebe356e516e55d882a3", "SEC": "040243bd58c69d4dfe5c23618315935646aa00359025cedd7a32448619d2e0b95b16b99c05d148e29af0e0e72d177bec2a44b9435f47f754a3507d654a0cc5b164", "TP2": "0400114176548f54c0493833bdb0dc8dd359bde589076492cf14f46a65ce671edc1d0be9e505a1bc5d25f1beb0dc1e0bace941eaa8dc09819513e889ec4da27ee3", "TP1": "0407206d8d8709c3f06f167582a1d89fd07c48ecfd140794d32f2ca13db5e85f950381451e405dce977dc0f97066f6a8e761b2ea80a7b6d6824d55fff61f56bc6d", "CS1": "041bff39ee8f42023cace5c99a7ff52cda5e4499440ab8fb36bab95b0c86064ba01883ac30aeb561ba9a6eecc1899f2e58a6a73bcf76d85f43efa00f995c77d82c", "CS2": "0419c6f5f411daf047db1360aa67c247745da2902b490c39d8f503bb47652c75c916466e9f6df596914c8993c5328b403c5647283e8357aa59954cf8dad4c5cd7e", "HASH_MPIN_ID_HEX": "dbfa6db9db662e067412fcf3969f088de30cfac7bbc9e8a6202040ca57b86f70", "TIME_PERMIT": "0418cd22ba9a0ac195297a2cfe897b260486d3340737c6a7deac7815170d17212e0e5f87d3c0d8b55ebe1a1c57329487d60deb9cd76598407c8562559ccfc25486", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223363656133396538396138356236373539386335633134376135363738646362406365727469766f782e636f6d222c202273616c74223a20223762643438316434333162656531346139646636343433313931303131363639227d", "TOKEN": "041cb451dd2bc4f05d8dcc90239acd575dd54d54d12a4b7fbf3b46094084c2974201022d1b4a322bc2d6b8066cc01286c68b998cda5c1eae855b746ebda7159f4e", "U": "0412b9b2317334799803d60db6211daf06718f18c625b2e873012a19d6faa28b7712eeaf27301817f6a11b2f959f1ebbd7f82c8fb4a793fee3ae51cafe8bebc9a4", "SERVER_OUTPUT": 0, "Y": "132da633fa6b06aa8b4611cde0c8e1786db9cbddf5195ce25c61caa400597e1c", "X": "0ac7f75abc61f3e22b93521470929e9d4b573286fba323b21363834b400b2085", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"3cea39e89a85b67598c5c147a5678dcb@certivox.com\", \"salt\": \"7bd481d431bee14a9df6443191011669\"}", "test_no": 65, "UT": "0412da9964c83e5dba6e562e7213e279515ecf107aa432d566adc4e643bdd99b9e203050a7a025d7b1d22937740fd922b10501ce408caa597e90f34670faa058e2", "MS2": "10f951258152ba97bd1cac42ec35cd1abd55977a95376697432f1b71a27c5707", "MS1": "04022e8e44d71a223d9b131fbd210382837e30e36338a100efed0e5e7e0df57f", "CLIENT_SECRET": "04157f27f73a5b0b13e2d1d5dc52acb327be01c19ee47e0af2e73129f4b6db20682291e0f8b25fb541884ed827d3c5aef38aed53d9151789d0fdae5381acec9e85"}, {"TimeValue": 1437055595, "SS1": "05ffda640b1d05f4cfb2494b5b2ee2fdad85002a9a19a2b8c639b5e810e683e10b69bfea265cdba8d34c821aa84611707b36e0825b73748a29167a9cbeef74ca0eef173e538230ae7b2dce0e0bdb1f4c9e90ad84a112170f39c9f6b0616b15f72032f6db8aed5a08b698b78e051c640433f048ef3fa520ef7226a221d7495927", "SS2": "0681edcf2291f1b551302792d78b1a0db07f6ff9ba4a3d57b83a8010a27272a921b301f7034880941a95f19a1109a27af018d3a9510082a8271df25dbf6aabe407438c75768fb92fb1fc1d5f47f8fbb1f53f8b176799de82845fee879a3ce77919b6e5ef5f37e71d02d18bfd5bfc814b503b63c7b82860de73f0eb9e317aefe2", "DATE": 16632, "PIN2": 8503, "PIN1": 8503, "SERVER_SECRET": "16474aefe3132c63973ca7365596cfcee7ff83852c6b9951461899803dae5e6c0d863abaaa1221b3aa15f59e5ee3647bdf8cbf4ce6728d64a85964d74851976c0ee98091a01e610b5ced7ed785354e7ce3f780a3c8a55fb91df91d480e5cd2860f49e7da50b2dd29efdddb4ffcaf16c7b81c6c326b615ef0ded4695d8ae93aa0", "SEC": "04148c5e00053f0f0794b8b36811e4f369244c80e90c452a4e5eeecd9be5bc83b20e3dec8c33cd46226af7a83e5ae2ad14ba2383b59327b96feaf8744f668d9c5f", "TP2": "040f8f4f9c6698c602b271f0265dda9a3006ff6b564ef78418ec4130f96797464c1bd9f185c26a05d56ddd3def4ebe3d497a380a5952ec39aeec166fb67b132dc6", "TP1": "0409c30167955b35290784fc8b7175e8a9e4ca79cc0ed4557d5d8154c80918d0831df9c3e6bb883d039b3254a1f54e8c849f46c4f146e513a360c232fa9476be1c", "CS1": "0409aff2571b9e890ce64b21f98b5d53456987707bbb001b53f4d539e7b67099672361397362cefa694b10db4694728d76a1407403e1fa711c37d11d5a57a2d42e", "CS2": "040fef9c3b30dc526fee755387ced24d960879b0f20c230a7af0591d098da65da910fc613f4c26e82a7a171dda589ef42cd0c2f41a2ba758f39ae7b76ebec05741", "HASH_MPIN_ID_HEX": "c2643e1ae9726a227212d2f6c33f1511fda558ef727150f8ec44a56827ebbbd0", "TIME_PERMIT": "0404320135fec04898f461cb51df983e6271fab4045d37b87a31225df56a328e0c030fa9e89d7f81fd37fcc6febf817b51b5b29c4b636cb103e4fefbca3aafa2c7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223961633534613232396264393962333961666666613264323531356165386564406365727469766f782e636f6d222c202273616c74223a20223836613862333761393335346234613432613464633938333037386338393734227d", "TOKEN": "040b09f9d7c5b4f272e855413462e80c355b1e13e0ea34a597b4bcc0c9330a9cdc1ebca2435274275df355798325b47bc7a0ee72253b5e60ad32ce85954b955274", "U": "041882282d0207aa3202376d63c21d4629ef9a84e99ade446c38a91ece063633ca0c09245d7e97b05098f74ca7556d4cc76326f38ce902055e06c89e18ff9f07b0", "SERVER_OUTPUT": 0, "Y": "0494c49569844a3052c950419599074ab0d9a1bde7f2b20b710b1d3be4386a93", "X": "1c1a3bbe56cdfdbf9af0cef9faec1c6e9489f642101e3ddb1ce691ac918a6fb1", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"9ac54a229bd99b39afffa2d2515ae8ed@certivox.com\", \"salt\": \"86a8b37a9354b4a42a4dc983078c8974\"}", "test_no": 66, "UT": "0418b391d41ba0ecbb26666fea3810f80d2255cc1eb7267d16467bcf05bda565d805f8508f5bebd0ad71b664865243524d71d788012da9a67a023b59a6bf14d1df", "MS2": "0d55fbc392d91a82f02406c5d37654088152b953dd78c455791625deb220a211", "MS1": "053615fc945085b395b9ad8c41096f7b4acf10c540df938533d1c99f385c4207", "CLIENT_SECRET": "041228459f99fe30da1233b95a91150df9f067a8e923ceb2fd8a25e0fbeebb556e19a5b50a0f740a7a16cb8ba94f3eb288ee5a96d95e68409b644c58a388d73a60"}, {"TimeValue": 1437055595, "SS1": "0641a7a9282c99cab1773424a9cf731f735d09c084f30d6fc520620778b924e317a8692bb1da8a9066dc812469eb643b1b89b8ac69400af6fe5947c61bc201c60c608b8d7981d7fac47c2857fa15c810a2cbd9d2dcf61a3630deb590d00e76101d79ce88c68dbb495285969197ffce04813b49f2b3091f8bd52742b557794352", "SS2": "1b3a7b9ab7ccdd22b34e781bcb43cae343767438cc9e3d3f72350f33153d246b1d1191973d3535c2ff3cf02b5c8f6f51bc89cd8e48db78b91a27ac3a75497fa50728e8885134c8746947ab054824676c3e362a04f6cf3f48eb5c385462cabd08020bb53ec669ba3e30847b3714a26ef801711da7ced78a3a8729dc91152a3b23", "DATE": 16632, "PIN2": 879, "PIN1": 879, "SERVER_SECRET": "039f246ddf7de21d752daec90d2e2b75948c038491018fa7f9098669fd67f2600044ec890af8216424564bc8f41b14b7a89fec64411bd16ee3ac389827b27972094b24cf5cfdeebe0e1622d19800b9233c94049f35c0dc9230d0e72cb1f4f2c90252a50e4bb2613d483bdcfaeb657937c0a6304842d779d31edc2911a5500877", "SEC": "041738b400a0b63125adaf78056b4988ba207e056591a3da4ffc0cba7512a445bb0fb62f24ad9361747b2fe1825dae137de9c6e5a5daf3c6f001cb2f6b032887ce", "TP2": "040659d9b2dc06f8705e4bc27c84704e8665055f6a40f65f880d171439acb67f450e4c1766dd7dcf6573456ff55088bd6cf090760bcd5af42b31355e4997074386", "TP1": "04210fe8b689e5cdd5d8b957b8aba16346e98afa322026835a450539491ebda7fa1ce4f01636c0f51419832c2da99cdf01865c74495eafa26e640dd954abc96862", "CS1": "0420f65a70696f7b6ea9ba3c1bfa1e7871b908aff4beb18c78cb6983a4d2c4c50407bb27718da9dc032b54fbebc5bd6af6e365d1381a595b9e4abfb37433a20d97", "CS2": "0410be94bd141431d80150bb4b26c6c3ab8b13a16887f7b3bc031c223081b195eb14ecb142b712b5edf92690cdf65ab050f22f9e3b14b1af1f21c370fd68994a04", "HASH_MPIN_ID_HEX": "0bd6111a0d694461b14bfb9b3a68decdca1985e4315ad50106d65c0657867cd6", "TIME_PERMIT": "04013ed1a4786f72479ed260f912a1704a6cc9ad4feea11028c834d284626fe4360655df0d39403900e02bbdc4168d84bdf74f44ffcd498d796617ee399512d366", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223264323330646434333562336262656437323233303065393532383839363338406365727469766f782e636f6d222c202273616c74223a20226164303532623566383232346462666536353838383065643232313664346338227d", "TOKEN": "0418db4417846857cfd41ce36ed7741c1fcc66d13bf242647651266fb01d6ffcb813eed8dfea3e917e310d78f83c3657d1370064c8e9cc1ffcacaead4517bc3bc1", "U": "041bbe2d39f6e1b4cdb84144c65af5b01dfcaadf6f17a6611fe3aa8d37c45385cf02dc80fd7a4e211a9fec57733a5c92a2d192201f7b16f03782e6528d3d952c3b", "SERVER_OUTPUT": 0, "Y": "0c4fa4b6ed7f90a4699721a86de2075e76691f6809ea4b7f203a69108545b9db", "X": "03dd42e2facb5577f9ec20c3b70333b1a1dfc027b3895c59aa95766d017b8d58", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"2d230dd435b3bbed722300e952889638@certivox.com\", \"salt\": \"ad052b5f8224dbfe658880ed2216d4c8\"}", "test_no": 67, "UT": "040714067cfcc44f65cebce4b9031621110c8b74705b50d09d9963f0d6ef302c530b452e4870b2490bea030917f751c13bbd4d7d5a690c0c6886a25072225b69d2", "MS2": "116b105495ab1bd510dd33b2d52a9e66b10a0165877267987132b95f012bc7e6", "MS1": "1e2a82de27f2c4ee26be22250eb7f2f7c3d94b353da6a94be52731f2c172ff44", "CLIENT_SECRET": "04164a46ce49c1e8db2ffcadfc7e0cbe94480538b00b6095dcc5f0f6e3c20e8f070e4d1f6fb80e4d4c6ec728fbaac3d78da8f6db23661b9064091f4b9a29bf57a5"}, {"TimeValue": 1437055595, "SS1": "193036f341e3f4b8e292e0d06282dac204eb75508f0bb646e3545fe712c45020001ecd91d479c95e341327a147dd92068ac3a52e1041974846e60c5dd02f2ffd13ed66bb227248d5762a6abf3698edc76dc5eeeb3536f7680207264733a87a5500d5b5162f861d271a08c4d84a37a362a9b750d9524b1203d59dd234d82952f6", "SS2": "0af4a0de3b8dc9ec7575f68736551fca841ba3e0a06743ae1ea250bc37b653700bf0560a3d602a0743fc0dba7ff167e6fb7b0dcbbd3ba12b04531449f7442935016045de11d62ff2d3a464e3ef87a0c63ae4ba77e30eb5782fc1384fd475f92f070cc6b80a8609bb105a942ad17ccfa6daae20d19fff7d1322ba5abc0718a6cf", "DATE": 16632, "PIN2": 4240, "PIN1": 4240, "SERVER_SECRET": "19b9c8eff655f4bf3aa4a91711cb8e906b0d30c966c94e2d7cdba743d03bd86d0ac6b1bc2302b15f164d6cb3832c0ee4a60dfdff97733d79e24631101877f25d01b30fe71569a4735bb1ec916b9f7710b82ff903cd57aa31f93b10a21559989100a6ff2c8b965089c64502e943aa21766853672aa90fec73fd871e7e25f12eea", "SEC": "0412c8fe176f9cc23f52b1a508900175e3e9111ae950ccf2b946aa450cbb151c2106e681844eb5ee98e05f174975014b1122805cfdc04c6feeacc8af7ff1c84f1b", "TP2": "040eb034f170301b1e5bd886918101a729f9d1f0439567a70ab362933d42586e9a0f945a1179d68b192abcbd19fec561d022b3c52aaa3282cec96f1191fe4249ba", "TP1": "040f64d4e520056a6e003c51e248f7159992e11e50a2f1156e2d0893fdba82dc672118d2a80302982d5fb45f03b13b5856495d694848febf751ba2c8f3478e8f89", "CS1": "0419d750e8744831c45e4cf2de6bf6f680c38787af616787fd62a7eecbbfcbeb67017e634ac5d10b903e6e571e58992f4658620eb79e71c31f68375be7441fbaee", "CS2": "0412740f4a5bdb4db3ca6f7ac61a81298eca47011196e0c78176d76419834efc7b1e31ec143352e3687c1501770c3d1c1e25af56d87d6ea46ef8a0608af0975259", "HASH_MPIN_ID_HEX": "33f03db9575e4a1e9bec68c725e9dd671a64586cd1ebdd3b48cd0ae05a7b8ed5", "TIME_PERMIT": "040380bc1106ab5d6514b7925d0ff6202af4c0f951f05f80111b41445d4aa42e490bb2e1efb57a0b1114f81c4f77cd658d8ff40f9d071ce02350168486472b25a5", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223439383031346361366630376464386166356163616235356130643162666664406365727469766f782e636f6d222c202273616c74223a20223966646362353336646137353162653739353239653263323239336333616663227d", "TOKEN": "040baf79944e8df04673f9246761cadf26a673aaa3dbcb6012ac46c519163858a723ec522540df3f4472e067f15279003edf7eebf176cdd9cceda410ec40eeff57", "U": "0422fa41bb241ad6d69ad7a30aad127f6b4e4234a06e35f57862ac392c100ca4040cc2c39de2fed9f20bf8edb5b08817872dba7504f231e24693764d6b3ba836cc", "SERVER_OUTPUT": 0, "Y": "085e07675628313e28c71d031325cae1b4f6cc3f9bd3d6b05f670fd4a41b5cdf", "X": "103f6beee094d9056afe23435e9dac4aa20d26e289bdbf407e202fdceba02e40", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"498014ca6f07dd8af5acab55a0d1bffd@certivox.com\", \"salt\": \"9fdcb536da751be79529e2c2293c3afc\"}", "test_no": 68, "UT": "0421a3e14d8b466e1428d3c9a436757df53db2a31874df19eedfc69fcfd67002b506ac330074a1d8c112be16fd71e39dd0d18642a93fda7718e2bb76ef4d80a867", "MS2": "1c9085b520e4f1504e6a9ed93bd907c28a1abc3fc09327ef0fc09db08c30616f", "MS1": "007b1e50d2d67a4cad69b097b1f1ed7d062affe837f70c8983fe7efec390867c", "CLIENT_SECRET": "04217ab17a3b78f31e7b6638b2dafae7a329dd9d0316cdbf66b07b28599de80bfd1b7e6eae97dfab60828dab421eec5b7bd86d3701e2dc320505fb14af07d15e96"}, {"TimeValue": 1437055595, "SS1": "0189807352039396bf746e832e132e5a3b10eb99f91455d871506baa7eb4be7512f307ba36b015d49ab241639797e244cac595edcc29395e6483ab27a011966403875df8475148af66466f5afa44ba66f6aad281414907357b05c79b155c687e0945bb3f0baa8a0545311e6a452224ca024636d42adad4208e19f3c56d5a73d3", "SS2": "1f95d0077f7390850b234dfef8962b91ac8c88d4d406fbe87287e86a521a03fd075a18a4c71f3d32eafd3e41baffc62eb02bfc0166ac2e188b5f76dd4fc1b7de01655cf36d40d83c5c2eece5e3662520f0b69eac52a13f8c93f9bdc61c66ba1d0b1f0a59e35a0fb9164594425c3c46b1a1b27b7054ce3dcfc25f53900f549849", "DATE": 16632, "PIN2": 5646, "PIN1": 5646, "SERVER_SECRET": "11b9ee643b49d43161eebcdb9398b72de6ab638f5258429477b8583a76af372c091f33d4064cda1cacabc31070da8c44790c32723d768040d89ac8ca67a2345f0c969e95ba4e1e5235d093ba0bf0a196aceae1c3ae9fb881afb30d223b3cd5d421776dc7d27d1e9514c95a12066979f2d92c44a05562e10a5d159251297b6f5f", "SEC": "041c6ae9ab05356c9a060420e315d5b85616f69b2d763c7e61e1ea12f9b3467c93074e604f17655e2e2fe73101930a1ce2a962138392ab33e786727b14d4429158", "TP2": "041c963402ce36b3d6aa3a1a11d9011860873a6f661fbec8d4865261c9485929bf052eb7cf403c2f323e607a73078766a1d85fbaf1294cd01bcda0a530de62095e", "TP1": "0413ff9b9b650c41d9b74b9fc77de684fd2df518c55cd6acf6fe1852c10f1f1a31044a35bc84051049e4997bc9c02c59c72f07f5997bd1b5a0839526077147682e", "CS1": "042096cf5deeeedf4193ce7ba178deb8e2c12492cbcb0fa775edfdbd3687257ae51768c4c6f8b6b785a555129360c63e33653036b5af73660b8778caace2f1cd26", "CS2": "040d5364b789bfd9015498412bcf659ee710cf934e4e33ca6bf68899fc6d665b2b1397fac74678820543343ed00bb99da1ffac2f46712343bd5ce6c33be91e90be", "HASH_MPIN_ID_HEX": "6688f89c990fba85fec8cb353d0555a4046147810cfed22b9d764967ba5b105e", "TIME_PERMIT": "0406c5fff12ed831922f1e44300e2d964afd0b591d28c3a6720ac2a6799f05a60b0c21cbb5506433a6567735687f59bf30426923b8ca9db988aa5e97a0e1012d83", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223061653430613135616563306537666466366534353564313966633634663133406365727469766f782e636f6d222c202273616c74223a20223963383937626133353530633864366165343133356166613337343231653862227d", "TOKEN": "041831a75e76cdfbffa6c4af5723e56e2d31ad80fe7201a11ad4c6da540b8164b303399dfd1275bda5a1f1680113b73c6a6fe5c4d80eb63baad3f4ce14396715bb", "U": "041b2adb0edfcd2675faaa4efdea25efb00bf177bcfece356565207a653bd71c59226bed7c1481175088de48e1071c58ea39668177035f4ec20dd8173aca06c564", "SERVER_OUTPUT": 0, "Y": "22818ca61f8fbaeb8369936e37ab5800c30edc5a0f84ab4b0ed0e6316e335a15", "X": "182ce9b9cf77b47859ac4c8f322430298b9cfd323811bedd2309b89028a8c283", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"0ae40a15aec0e7fdf6e455d19fc64f13@certivox.com\", \"salt\": \"9c897ba3550c8d6ae4135afa37421e8b\"}", "test_no": 69, "UT": "041cf49acd37983dce2723cac665b2bfeab0dd76a80febb770773dd5856bcc33b007c0811991020dd0db4be2ee6e6aefb1f2cc6be6aee4a5b9f00900781813d6f4", "MS2": "1ea665822f723cd62c46c7612985622b01a6a94988873ea67c0426327c08cb93", "MS1": "09ed7ff1127d9532856749b95a1c379e18502c3b0d860af2a15498e5f6fc16dc", "CLIENT_SECRET": "04035eda11e9c15bf4d509f4ffcbb76090b7eb9d9cd62121dc76aacfaec562178c0869699f04565c3d299572e5768759e0ed57b256ac37f0042df3ed4f83cc5070"}, {"TimeValue": 1437055595, "SS1": "1dc69d600865e29fdc80043b71485752f03da1cf7de284e0dee501c40fab9a82189553cdf36c7ef5f763bcf132f7f8808ff1d373516181b77c5ff009a5ac99ed1c12ed49c0bb004f7b99173d9396866db0c123bf3a73819a6a1701eafbc2056a11c326668a4b2cb1b725173151cd10d2895f79399b2cea8ea470eec1d3241d79", "SS2": "1f533f8308665da45dbd09d5d5c0dc61bebcb6de6c5dcd39a7c5b22adf3ea3ef15719afe96dfee4e11d47f317348854436940751ce2228e6634228d44fac61280c5b82b4127132c9d6889a948d0d989f16a7aa834f4746384f2ed38ccaee8e7800799d6038d3702949c90bb2cdfcb6908cc3c60dd3b30c4c22a72b1e123de0a8", "DATE": 16632, "PIN2": 7928, "PIN1": 7928, "SERVER_SECRET": "0c3661f52525de99a9c4cbb102681983e831100db268b7a7367023449076587311b4dd64288bafc937ace2fdf30ef4b1d7c731023920bfce3262dedf778fd91f09a4ae1f6c5d616eb62bd575aba8e6a3ebd8e53682773913be6b2454a55649e41b45e13733060a97b1b79edcbd74c0f1abc03453d6a74bafda77315885a0a53f", "SEC": "040403f7dee4f646826b02edbcd622d373d60ebee6a9007450d086d6b8a6da84a6019af96348abec81ff0f1648a92d930f2a7a866b2b410ee1609e3c328934254b", "TP2": "0406b30c5402e878f2a30533ff93b73aa33492fbb8ca702b20f6cc1ac5ff844d451540734e0bebd604b677d93e2cd020d3fc1179c7485ec119c79adfb2508db5a0", "TP1": "041ebd94d0ce070afa2b5fbe9a20c8473a59b445a11f6a1ff0e1d355ea9cedefc80e09bda676857652168ed0c585bbb88d5fef0b8179c68be5b16f523d19b640ce", "CS1": "041e9a8fc1bac79645d503fe40bb76f5762bce24f5fb88d7734d64ed3b9ce123f012816148a82ee0e1cfbadcee56ec9da6fdf2f75b525a458a43a1f303a49439a8", "CS2": "04212b0a57568830e6a2de3ca1993f58ac12a7fd59b4dbd48078ae829502f2c8fc2077e4d189fe099a5d9efcf531eebe17d8a0a756b76911c78d42cc6eae1b0286", "HASH_MPIN_ID_HEX": "c4e457663ef7be36e408722c1ac4d6b48f1a1c578962d129527872c7a68aa862", "TIME_PERMIT": "042225fd0d5ae53f228782b6b344baafd916f72196d91dfa7340f650a6db3483400f2823294a53e3c8d1e271192540430661a56dc7647232384bcaeeaf7c923689", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223236333732383032383566303837336265653435383734633064313938656235406365727469766f782e636f6d222c202273616c74223a20223432613635333136633062393939383065346138366437386332316662363734227d", "TOKEN": "041d67817e83b7818d70f5048c34fa90ebfcf74038b8dbade2c1690dd1a96fd8fe0bdee83d1939f95e6865efd3ebb67a891696c066bf5a449335e989a82ff2b954", "U": "04046a33eb3ac68eb72235948c4f949126b1f66e6a917f141a3f3d181eca84c9281939212814ac2e256dacb163ba3e66a18abdf150e33358e25afe0380ef5e77e1", "SERVER_OUTPUT": 0, "Y": "0bfa52e68e0f5111119a2ae02bb50b1a112522eb9c3c4b76fc057324d86ee759", "X": "11e1844119c80fe4f08c53bac24e22946ec4b9061866ff8d964195347aed319b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"2637280285f0873bee45874c0d198eb5@certivox.com\", \"salt\": \"42a65316c0b99980e4a86d78c21fb674\"}", "test_no": 70, "UT": "041d45355d6e81cb954f42211daba806fb3b834966f0614c3b2c3c3b8aa99071bb0de39950d26672fa0a5f8b6b27ca142a957eeb60c2cb4121dabdccba06466136", "MS2": "213ade5784a343964d93d60ac12b0be3f75d833e855e50858b3ebeb44ead75d1", "MS1": "04b2c6d3b98eba4cccc0524ef4d68c985382c0aa2f0d5bf6cd25de032739fde1", "CLIENT_SECRET": "0415488b7e0b6ea6013e85ff94a7c0f65917dbcc0db4f1344b35caf518e109b02f19a6596f58ed4cb426f06c4e3ea08630b81a727c839b25cb16015ee0a7c4de46"}, {"TimeValue": 1437055595, "SS1": "0bc7637e2c8b0d57a67b9112f09f5e4a6d08974a2fd07e352aab0e391ecb7ccf0d3d083936b5fc9dbb147ee65d76ca9686508d4227f9573665e36fbf9192ddd20b2dae65ae6891b2b62930f409ea9533703de66984f8d281a051d9589ad950060dfb0b022972f9abf07f6f5a89cd3b9f635c7fafb83082417a7b96997de844f1", "SS2": "09801c1221a9f3b18953b59c8cd8bc1999461249b3eb1533bee5c01e14fc946d08ecea4210e1870de7b36101d36284d512e5ac144cccaaf63cde763b29c83f9e1039ba4d748ddad8d7658fc8b6dc6e4bbce118c179bf035bcba682921ad7c30c12820d8acba830b8d36410deb13c1d99579b6d0451e449a91c88446245a799f4", "DATE": 16632, "PIN2": 4781, "PIN1": 4781, "SERVER_SECRET": "047430ac2d9064471eb251fdc3c26e7ec900e16026c0c09760c72abadf86ae601a12558fe287a09b48a087999b0447596aa4e2cb39e97015e07e72e9d75ca3410375294e52f6907556ee91bf5f81752c8ef2379394a55fe2687347ac5d524569203dba279b08061abb6db08b9efcc42f3fe85eeec0186ca0cef119b2b15bcb0d", "SEC": "040894f0ba10aa734342764f39e8daa634fb19f3e35d7ea74b24c3dca85b58502721d358a3fedcac0c15c2c273024e9797465568db51ce229d17eab4597df688d5", "TP2": "04170a37f20fd2edd03cf488c8de82a007a3a7a404ae853a2c566b5e0b6e444a4a02bc17e4c25a99b033ddd40f063bad38706bf39eee08d805fa9b8f757e7d6d0f", "TP1": "0416e7b5cc4f87d16c064694c4a1e79583ab0385e019f75fee1cd33631c2d9784216fb3f687b3dfb5bc20dca41cf5219720708164d8aff517d98035f994206dd35", "CS1": "0404834a7ea86b8887bec3673edc40c059b27ce0449a16460070422e40988c6d2c107cacd9402855b919068ca9b3ba59feea2c485042474cfd939d1b57fef4312f", "CS2": "041372c6f36846fe530d4f6f21e502757662feffc2f17ff96816b126acbb35922e17e46f0a148d51dc0ea3e17f9750ab8e8d5b91387b7579964190feeabbb5d84f", "HASH_MPIN_ID_HEX": "66b878eb26032e7b4e77c60afbf468d2eb930745a9f19b5d857acfac7a4fc679", "TIME_PERMIT": "04217eb24220731200ce84f8b0584b615b5de14046c35fe42b0a106827d7b6ecfd123bc0e6efecdbf6128c2b1ade581ec237c5cab9118254b4422e38e7324ae1dc", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223832633936626533333232633137646565666662633364646330353264616437406365727469766f782e636f6d222c202273616c74223a20223531373632373339336565613738653561623535636262393539626132623964227d", "TOKEN": "04092131b1d87fa614718a2a97a31623382d7afcca7c1e9b263c0829daa25b558723af3d7bf38b79ae728332d6d97251a386a0b9433c1ae9b698eca7fd92070a33", "U": "041a715d94d3606f44acfad7d2ec438a0cc647639b727a45a8ea338f134e47ad1c05bbdd445226c252e460fc950862e78bb7f3f03b89da8ff42cccaa4993cc0527", "SERVER_OUTPUT": 0, "Y": "1dbdb46190f1f0d8be9aac74b7bdc9a208fa4aefaa0fea0f1b28b96a5541605a", "X": "0bf48c6f508be743bb7e4d593c04efb3584702b605ce12967f181674aae75f20", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"82c96be3322c17deeffbc3ddc052dad7@certivox.com\", \"salt\": \"517627393eea78e5ab55cbb959ba2b9d\"}", "test_no": 71, "UT": "0409957528dabdce9b233af294ed80c5725792370e130829ba6392133cfa7c8fdb109b5d3f2ace43a07a2eb4216a9dc3167dbb4c529ccd30cb5efc8371246a248c", "MS2": "20b271ddc4a6cb5050b36370b439211dd0d4c46a5e28c47f81a9cd9bbb51e509", "MS1": "0a030dd0471e7c1879ee6339f3aea4d263e5da759c4614027e42002cf2073c1d", "CLIENT_SECRET": "0414bcdf88d9192814a081b2ee3bebe01f07c1e4541bca15428d725156f9d438421aef5a320d77664984237b598dd577e7184733a2feebe8bb858ac77f7a5ab39e"}, {"TimeValue": 1437055595, "SS1": "1f1cd01287134e7d76b276089b2eceaa8c8cc594e3cb8217ae75fa5a4107cda922050904cdbcdf4be725bcf2f18f0f4866276ca28f0fbe37f93bc23966b82d2b12cf5208e2e0a8b715a9961569263ad2144b96c1e3a269ce5a8695937ce75d0d03158dd92a470f6879467bab830c5f8bc813ecf78f1485d74e2564809a8a4a58", "SS2": "0530588a083bf57ab10913a81e4a90a610986b01a5806876404a44d2069960560906e027e1a14e3564ecf2adea33c75e6190b72d781e452a4744ac8f81ef354b0373b1611b4114e617189c1236ba66161fef064a25f1397a4df87adce92c47b80887c64b7c7647a8b532a508df47ace4186d954dce104956dc572ff47be8ea3d", "DATE": 16632, "PIN2": 9385, "PIN1": 9385, "SERVER_SECRET": "0759bdc1f4476b725829901f5cd56358ba7b3b1e51d5859d98a4e1daee86b30923fc8e5c5ca5d1e1abf335d20e7c3d7183e3ebc92b42a18681c08f528854bacb044ae46780b50e6017920ea76aadeaaea10668c6a3000dc97d131a7687ca664e0936798a224f3a3a98b22579eec384cf6dd143da31f1e84fef172bce9a720901", "SEC": "040ef29a9a968ebcb6e78840207aa13f3f1f0ca47bb4634d5fd8833b8a9ddf2e22230e80b98c15e21c3d6d1c667c849efeff70cb2baf0548a9038fc73b264aaccb", "TP2": "041ce54b5be92380e9d283787e387fb724c138ca18ba8092c9126527c318d845eb0b56ccbe20451c2803b19172d505c83cad81692683dd61209c8d76091c034a9f", "TP1": "04126443ba246230faaf71151c6fd6ee4984e89d6dbf06c2e505c42e34d52d1e8615cec1e54ab7c7b5c20858ec37383bb5de6654919d9805b7b2b1534d2891771e", "CS1": "04213ff60dc656c26582c97083393867ef9171cf3bb01e6b84788afabc55146c48175cf8c527126d3288e3bd8c3480eaae8f7559cad44eecf1bbf0676751ec19be", "CS2": "04112558f378412e47329d9fe606cbd2aed63b4ebdb8d0711519c223c82fca37cf1423eaccd4145876d78120634dcb47c693da94b0ebfaa92a903f5d624d5acd5f", "HASH_MPIN_ID_HEX": "75bd9a09558e13fcf51cd41e95340c29600cb574c014515c403b958d658cab26", "TIME_PERMIT": "04145a8d0cf2d5b481d294fecc6fdfbde71b582833abe8c46ba101823bd7a338f50a07653a6d4c4fc17d504127db84125a67edb9f1bf53d0439589f2d60bee94cb", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223730613630376639333736613234656233613335366139646362313764356438406365727469766f782e636f6d222c202273616c74223a20226231356362653934336631323439343030356330386364636132353830383034227d", "TOKEN": "04067ee83c866882467813f92db6c1c468a8e0900d6baf06c256e9f24ce1fe36f90a2873c1971102e647921bc31e274967c82add5a760efe8c624386960429c0df", "U": "04087a70ceaadbdd9c2d1a41ac58473a0396c8e216f487d62d5cee429ff156446f1ea92e3bbeaf81495cf254339f6bca67c26192c18e9303329b01a3714a074403", "SERVER_OUTPUT": 0, "Y": "161d3a3f83afc35f8c227ff96822c28aa920dfad0249e8988e769f932ee9d98e", "X": "13311bcb72914e359be8865e536a5a4e7d8dd9b5867eb8351caa3c70fb53819c", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"70a607f9376a24eb3a356a9dcb17d5d8@certivox.com\", \"salt\": \"b15cbe943f12494005c08cdca2580804\"}", "test_no": 72, "UT": "040981296b66b2777e46141ca7cee2f13acedb0dc086271042f3e09fd871355fbb1f1c91abc4b577d7782bb723394eaceb53f4d59a22f472e531b2315ce1337c70", "MS2": "1405b3e8c5e5070db608f449ccc7039dd8fe13db90f50f0ad21234f26c72d2fe", "MS1": "1257d346a11a1ce02fea2ea4c4f0940994e42fd5f6b4ce0193bf1d5f81d2f4ee", "CLIENT_SECRET": "0400fbcedf0e1ea818189b27926b3a5ca2937e365fa30febbfd491c55fd8096dcc229f4b15209aefaa3799e0bbd8adf230b10d212e81d6a02f88503f3478f03021"}, {"TimeValue": 1437055595, "SS1": "176a6be271e9d4eab197763d86a5edfb02c8949002d7ec088777372e3efc53dd067b52045f8456d1cbe717bedf6c14f3a551c57019d2af0f0472fa31dfffa62a08584e6ca878836b4dffb2490c245131623633b2f494617311c40a7fcb3c1d521ed6eb3eaf8d0302a46e6b5e8bc7b702c7956a73092dfa58e6afc7ae3e0f6469", "SS2": "00d5c532cfb0628655e6af9a3e27ac787c68021ff96c46dfc0ce76b4daa14212064cc2c087110be6174dbf330da3d55476fe56156e49d1725be36713fe8b433813172b6e91a72b5942e56b15dc4c2099e61dfc714a02971715c482a47c4a70fc1532e72414fbe1dfff3306fa5784b4981107f4f9e5044b20eb39400862fd9036", "DATE": 16632, "PIN2": 2941, "PIN1": 2941, "SERVER_SECRET": "1ed6898dbda7fb42c292a488cb3b3b2900f22a7cf476bb438e2b7d76aa28ec3305b9e6962a63aff2c9bbb1ad166b95f2cae9ca2b01e58c7577fd7c6d101f1dd70a7fc002b414c29a72c076194e26cac8ed43267ecb60a9baa7ee977ad3fde66002d6cc285a5264ddcc678d6209029670b67ef093197a5ace49a32090bd35f68d", "SEC": "0408074438446265b292770070cfb03dd7c31c87888698412cf60ee0ad73629b7421e9870f5f85c91f7878cbd450fa0352f39de6bd3ad06dc3cf50198a81238302", "TP2": "041c1bf05a7713dd1e4c2fb76da584f7d9f7be8dd86f903be9122b3c90d32a241306e851c3032a2e100f7aa90e415b2fa6e93680c397c39f79eb64da34f7fd8692", "TP1": "0405f90879618d1de4f4f453b7fb002ebddf3ef4603dfaf7c4b1e0c7b29eacac9a2094ab7ebc0f687745b5f642afe8b7f735f633e87bad2af4e3d32f353d9001c0", "CS1": "041d5cae883ca2309434dbcad14b6f9fa98d747ba1b0eb855c58ccffcfc7ce25320483aa573f2efa4b29de945ba517f5dde45359102c70e31afb8fa5d0b1e12b8b", "CS2": "0402a996e5170b9898ffbe67f85b35fa87a5b6967e4f4afc34b033e7fdb9db785616338dc75a1a5ba893955abaf9038835f7ca14ace70c40e33c77a841875e5037", "HASH_MPIN_ID_HEX": "3a76e3aaa88ae4f7feb14fcfff6913bd3e908df2d15dea69d158f6b04dc434c8", "TIME_PERMIT": "040016193ee5773084eb154dbb85da27acf77681acc21bc6195e11cd7e4f94f56a1055575ea041bcf1a268e89f8a89ee1467188094145ed35393844fdc22e63b6d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226638326438346330376366636333653638643963343463663561386532383833406365727469766f782e636f6d222c202273616c74223a20223937323064353031336534303239613435363933353764636432623133626465227d", "TOKEN": "040a2cdbea9a1dcd92044552598aa5c14359d9c63daf0f2fe9e984313a77eae4db00bf12c4bde6908c4f56cb916c96e967a93e8f2f5b04cf5088fe31b4818ba693", "U": "040cc2ee4cf4d1f3721481da2d2ef20fee019b5929cf320fbd72662c4be80191bd0314e27bd3637bad041e87f507abbc0aa40c90a0bb64d291d061abb677737d54", "SERVER_OUTPUT": 0, "Y": "077edd5d112df898f9a1bdd8c9cd8c552785dbd9cdeb4fdd4c7a39536883edbe", "X": "1cdf0c7d96b2661765061a8ae5819b80c989630db704cfa990b865f3f788829b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"f82d84c07cfcc3e68d9c44cf5a8e2883@certivox.com\", \"salt\": \"9720d5013e4029a4569357dcd2b13bde\"}", "test_no": 73, "UT": "041831fa58ff9e996ad80c6e3bdd3adc7b2a3f3228875d625f1dc4b0ab7c56c533051fef8cfa01360e00ba87ab3176635ecdbc834c3822289914fda17ed2b601fe", "MS2": "2277a05523445c3a4173952b62471c25e04e12cb563449f3d655b3d00ece2b0b", "MS1": "19f9d2dc0b42f595f8e07224ca91efd537785bae939c828e4b9329929fb0e0ce", "CLIENT_SECRET": "04225235a9864868a20e1f69fb398c48ec3f32276a83cde9a7d29c919eeb9fbecd0e26887fabcbfe812d1af8c49a859311da772d029de40c23da6e0a0df7ee4505"}, {"TimeValue": 1437055595, "SS1": "0582f7fc41b3e00ce2ea0c1ad29dfe42eed782b77703a28e9e032f57c27f14d200b5b2cc2cd1f3f705c5f0a2bdd160ef3184319c6017861a30bf060ed459742b1c59fc46655aec2daede7c7531c0661b91a199215911abd2b69683c726d933fc098729500c9e627e7d3351472267b09a2878f2e5cc24355272e7c6de8924ab8b", "SS2": "0e3155b45c95900722c64bd36e2d3a597acabb5c1ca56dd5d64c9f4a37db5f771da8c2a229363ab0190319727482826b6ded3493fcd6f9946a6c0fbac345dd260d925cf29e0f14b97b08c1357753b8ebb9035ea4da61fe95235441115be572d21a7ccab66835c622ead6ef0d2cd97c1d7ccd0152cbc2a3b9a6faac9eb9263dc3", "DATE": 16632, "PIN2": 3637, "PIN1": 3637, "SERVER_SECRET": "0084b883c49b8de7ffbdfd82dc2c474c0ddfa906ccf7d9edf516ccdadaddd7e512c1667fb1c81574408a5a514f47bee9d09407155a14efb5b9d401f39325e4a621c9554f39dccf45479ff8029e465fde80cda18873acf2a6268e2494f993dd8a22799ad4aea999a1d0f38f1e6ce244440d1d12965d409cb973704d1b0eaccbed", "SEC": "0403954b96092825b6bc2872efc1ab8b7510713903579e2b94ee3836bc8910d716068febd09c8d878f2e6402244763f8af4328dae61d08e524ca11b069741043e4", "TP2": "0405d546eb80f4a08462daf1f97df2469ed03e409c89e2fd6c5201afe6c03de8e413e44675ac3404233901057a218638a5f749034c298fad3a9d0958689ee73d33", "TP1": "0417065f0f6ab39c4b2cddfc6c499efdce1a5376cc6d06966d897a63d3839c546b04bbc12350bf31118318ac923baad7d972b970c0d5b91fa83df47a814c034258", "CS1": "0423a20043403ef8e03e03fa9a659c59fb1989680393b9f34fcdc494926a71196e22bc2a83a95eb458573cc9ea965694013dfa0a16a0518a4da21af573cc2bd3ba", "CS2": "04193130c30411f57e07752117530bca614de8d68e759b740999bb62f08859cedc0c5ab149da92a259c41e62a059d7aadea824382f9c28f58ff54e6bb16f2a5dac", "HASH_MPIN_ID_HEX": "c02c1a63880fbb79fc9b61dbcb0b34efa828a2c7f1563dc0f05fb4cdd13a6af6", "TIME_PERMIT": "040d1feb2a7d613fdf0f4a92b924617d1bc386ac92b145c230229d9b2660ea4d1e1434206a2b384dca54f5acd6c5a5f6f2c11552d14271000d804062e569ca8645", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223365386235393439613133323133343037383534643535613966653961396538406365727469766f782e636f6d222c202273616c74223a20223030616539396363343664333731616264313936633232393266393933633231227d", "TOKEN": "0404483ca89c9eb6db4862f556005ae8247d38b6ef8a873247a27cc635a4fce580220ce7ed6b0b6db1b62ba368a7ba19db3b0e2ab02ec500eeff1f4b6ebd616b2b", "U": "041a44cd1ac49ba2423ce2bb4745754a9e932f1dc0c4993bff036ae5888524cec3123686836ee371e444ebe9fcb774f3a6028d03e3def8ed289472f84735a99ac4", "SERVER_OUTPUT": 0, "Y": "1d7222988c370a467caa0bd4ba24e18582216b6525dab4b9777e7a411d2ef492", "X": "0ce41eb8f59503ea58385f46c5c3878485e2421220c50bcb6963606fbdcb085c", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"3e8b5949a13213407854d55a9fe9a9e8@certivox.com\", \"salt\": \"00ae99cc46d371abd196c2292f993c21\"}", "test_no": 74, "UT": "0402cbaac158da514e50e516c8c3672b732a1615f03bf5eaf1119cfa2c6075529d0a900f18fb37d7e2bfd6ddc41b1b57c25b17d25b299e76670eebfcb6e3265d05", "MS2": "1ca7d4517f3148d88b8fbeaf223e98bd3d11b9e4d3cd87af778b9c8c3a02cd05", "MS1": "0491120046f61898b984d65c56112db16318289375a94c5a347482493ee90502", "CLIENT_SECRET": "041d1a3296b45895f5dfe7cf36654eee86f8e5aeec38c2969ec693b23b715c6e620d601e169d61dc2b66ae1c8247ff812cff1c48518fed61cd6b9d0bbc55ce11a9"}, {"TimeValue": 1437055595, "SS1": "03665ee3daa01016e738640357e4207049498a53c8e545f8c8f8c6cb5fc3a2fa22869fcd9a4bab7df57b2c9d41b5b2d6c0bdbd176b47d937295761f074cb80330d3971e74ae10ddaefe4d4887993a0cc68305866c660d3641b99a2f27761eb3c039326f043df8b912e48bfb63c9fd1cd2189fe3b41ccb41ec212e9b02845dae1", "SS2": "04d4a3e1b916a1eecc2298c6cbbd22fe225f3bd7f182b99d9618fd7346f4f6c11e6d5a125935c6f49297c06d1dcbd9adb6ee53ed47a5dee2b3569f593ec139500df92fd6d3bfab9e137f0c1d3a744dc44a1b43dfe425cb1dd03ffbd1ff7ddf590faa75d43b4b115bff23b6c6610c996355e087557c89699727e165cbd374aef2", "DATE": 16632, "PIN2": 8914, "PIN1": 8914, "SERVER_SECRET": "18263cb384bfc389e3e0ff87174aca2fdcea70109ac85ef3f6dc4c8e32d2a6df0bef98d120c04698b9f23b03feefa4dbeb742e380310eeafe25cc844b2540e52176e2610902578c079966a1b34a6329d813b6ea10fe53dd53882a7deb7b3614222cca520d428f7584c023d4693551b9f487e7cae25f016dca8bd0a45698badd6", "SEC": "040f3aaafccdd4bf593c5ac7b97f29347f09bac808ee042c8544d2a9d3bdcdf53d05ee64b682beabade539ec6fbff75eeab20a45e255ee0627f5b1fac82637acd1", "TP2": "0416595dca24ffb33b9a2983f655e1ae18c155ededc0631285927623910617f77f0711bedaa78fd3d28f541ce9c613b7cb41fb9937a9400fb810c2f40213105948", "TP1": "040ee34c74b93eb2224af3c20631ab4bef33266917bd4a83f6f096f0ac1b5270a71d1d95ffaafee0b7f8dcb01986dfc2c81fb73d2e4a04110279b19d7000fe3a6d", "CS1": "041c0ad777636108ca862f01beea3126dd5ae7333e77bceeaa7c7847a0ade4816b1dded9d76e766cd99b7e0b01a886985563d8d43338ba1b74951f58999732d91e", "CS2": "04080376de837307c96c97890d1ae4330a6e3e02407ab8c85e1654cf70aa30a1cb22f105c5b08f952b80e0e032ba04fa377e987a0e78c310dc8f88d4d907a7ca0e", "HASH_MPIN_ID_HEX": "ab3fa339c4f68be267a069f57b03e428a09d1501b99c40a9857d566aa21faa3e", "TIME_PERMIT": "041fa91d4831cd8bfe665c246280a191850205b91aff117d2ec0dd75239b523dbd12cd92aad4810197b48c9b94567890763f00c76a6b9ebb429278f78530d052ba", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226631373636333736636261303835396630396235646462623339343162306639406365727469766f782e636f6d222c202273616c74223a20223963663266346431306536643832363963366433366636346236313039363131227d", "TOKEN": "04122d2523f2ae2dbb55ec5adb1d243105dbc530c5bf97de0698e3165d2535546b200b75287edfb2a7d32a99d0a878bfdd0c0b6405cdb1de0f5dbba2fea38e1630", "U": "04035fb2a237771e7d8cb5963870497d1d4580932d9c7de72fe17cc1bc6c6569c8063bc16b21edf46af840db9ebcf6224c794ecdd09ddd932d55523ffe464e177c", "SERVER_OUTPUT": 0, "Y": "20821766c597f1c814c7ebcf3736f552da6a9dbcf1aeae6fccb881de34bfbcf7", "X": "12be3251f475ae30d5598cccde5956978a11e21e579b2fbbdb488c5e5295f852", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"f1766376cba0859f09b5ddbb3941b0f9@certivox.com\", \"salt\": \"9cf2f4d10e6d8269c6d36f64b6109611\"}", "test_no": 75, "UT": "040f871f5f7ffb812b593a68915e462394b9cc0457e8c58c746a0822143848287a1d1f1436a43ed975a106f9a0affff707a2c3497201d02a5a9e64a8641199c512", "MS2": "130b50c14ca6f3428ad31e23c374534d9b41011767f3189942a4fd5a91a783a7", "MS1": "1cfe19f418fa9128ba45f7c8aaa0ecfb8db9fc4b5f7c03c51288d02bcd103f00", "CLIENT_SECRET": "041243f5efdd24faa380edaca2a9f36b2e5f00935e06d11e735c442106d2f54e57034854231bd0c9eb1a701a892e61cb7fb8ed19a7d6b9abfcbb831d4d63bcfb4f"}, {"TimeValue": 1437055595, "SS1": "014bef385f3ae9c1c1bd3be2288d86e4559057f1ffceea7054eeb2d0f785f9081dfe56f3241e4dcd5ec04a39f062536d82306567be7b85ccc5644086062550640950b3a356c59c3cab66418d1bedd3ff3a0bea6badf92e7f366b9a4adcf53fd3111fb257ca510a7eb66b5ca7895566c0f49506dd3d335281afb865c3493aad5b", "SS2": "09af691fd20a904972a761379b21343766285d931b59a426a67a19562fd288c4239674d172f655a0c9b3782f7b5e3d6adcefd96b9f33ddcffceb8f775c42079a105ce6bd8a77fe204f5cee2649df7810a7fca37a69b547ef059b9fde706677bd0a1ede725d31c42814968946318c3cc6d489848771a7bd0ab915f90fbed75252", "DATE": 16632, "PIN2": 448, "PIN1": 448, "SERVER_SECRET": "01f63bb8f2fd887ae9e5fa8d7adb549c2725ecb9f040b8cff658be29bfd70e5c0f9bc9ba89d261f4a0fc20b7533a5187bfa3ac84df40422be1e86e28859010b2058e947f3c2667e7f0092aa5ae7802a3246c5449ba67ae3afef2166de64886e708f8968994e63af581c8d8498668961d8c27ba9285973cc36abd77dae82ed5d3", "SEC": "041ae7bf73d3637331097661a5c93cf248bcbd8a1ac9b1fee23e8f1df56f69e92d021b758418c95e7f76e6f61cbe440807200659caf26ae6d30a904a30f33564a9", "TP2": "040b7fe1aada81727f65bc8de2fb1af8abc3b0651fa86c934ba0154bf063e4d3d91637223d37c715da7a045ce9121cdeb85569215cee28bd16baaf25a8114d7e7b", "TP1": "040c0d1469332b6900b9a5a1b454b339e0aadbabd0ecf2bd92fc28ded187cc83b604161d6d14c1ae79df6345b5f135b0dd38697104ad3bf0b56d32259cd38e390d", "CS1": "0400a01ebe1d4912d4e9aa511437ca0db8eecd1288b37f9852424801373802b95f208b763763047dac326ff8007b92028d4efdd3eefad4c10e24572f158b39cbf5", "CS2": "040e66914d24ee502e83902336184f92b13fcbe08cfa1f7b7248e998a4f838af2507024d3b531c632167b0172a5a006247931cf94a6f3415d587cab55d46aa72f2", "HASH_MPIN_ID_HEX": "aed840057bbb09e67770cc1cf0b00a94a0774f2c9a7b6a93fecaf3361c4c62ad", "TIME_PERMIT": "041e91a8195b5d45ba20a1297dd9f48902f67f887317abe6f7ca3a45e9ad229ef5231499e820b554ad7a20195378261fe2582554e96b51cae7a2cb3aecb4b4ac61", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223339363936356633393736663338633932646131313061333961356266376337406365727469766f782e636f6d222c202273616c74223a20223039646564393035323162306466383631303431653365303733373562333332227d", "TOKEN": "04184dbc1bbb7e637f852d6e80e292176591311bec72f44b40e5540f06387b43d11d7c88d1af87dcfbd9ccc88e7c5fb5dfc01dcc61c121b6432eb196ddb96c0066", "U": "041f49173392575d069ed2060739e792bd8b4005d1597ca7426d35bb02ebe722610345ee70427cacc8ebb95f96a6581794ac1b344f352bef16137eb5220535c219", "SERVER_OUTPUT": 0, "Y": "1cdcf3ad34d7afcf7f36843e84d8237a0895ae9e30b0bb03930eb209022c60dd", "X": "179a10244ed2c2433da4cb1cc3c9f1017c72f1d9552167adcd3a4101a7758bfc", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"396965f3976f38c92da110a39a5bf7c7@certivox.com\", \"salt\": \"09ded90521b0df861041e3e07375b332\"}", "test_no": 76, "UT": "0416ecb70c38d47dc7acd1238e3f468dabb7d9c7337f8dcf53d61b3eb64179403510b55441c3630f4ff1d2344bc59662a63dcca0a20e0cc31adf1ba5459d37dec8", "MS2": "0f74432d783451c7ed650c666c5a0477da22bd884421d350c763d40d8049a9e0", "MS1": "0a33b025de142da4c87c27ea95b9a92cd60fa515dc0bc6dfd3933d0cf314e627", "CLIENT_SECRET": "04143b262267230f6b0dfe9c652b2bb9d929eaba0324f30cde8abd76ddab821397182607dcb2aa4cd8bd5dbd8f88b60193dd046527b796814845e0ff31e7eca018"}, {"TimeValue": 1437055595, "SS1": "18750f4f7eeee1fe0408664ea8120b4d41b75b3dfa9f74ef62c9b52c80bbaa7721b5a4b9074cbae0e38b97945905cbd06a00744e8ba0fc08e2cdeb7cd2cec6e4037f97e3e19afe0d2d7a40fc6c70f2f706036de7aff9330f0747ad0896778884166bd2e8bb62f3a9f3340179cdaec1acc25728601ccf92e61c0825e1d07cd7ca", "SS2": "1715ac3a39b8d134c87ddff3494d7cd70795e622903ac15773eb52ddf8cec9421e29b0aa99c679f77ffc363389eff908e425991ffbf1e8e9fd6181679721b6532255295cbd71bf1d0e579a1e0affd225385feed7b6fdea9bf45f19dac13a479b00761bf0e08d3f208d520d8e834b2dc1ade7da9d93de5a5e4acc7f2f206a4dc2", "DATE": 16632, "PIN2": 9772, "PIN1": 9772, "SERVER_SECRET": "0eb8c2256b02695f294e9bb8d39cdf5d68ca6d971ccdaa8010844de7979b848e19f2d8a78d1b35f0211b6db579fa21f7f24c1d2e9ab1ed998b10c50697bc12f0172f74f1d972aa61df1a1851b2ae4773822476db8685287bf8f3cd7c6d456e861b8d16097b4d6d4a62b7d6b6ed7a4aa6bd0d5525247125d42d376a73f0bf8a6c", "SEC": "0421b4a9166467b6c2beadf2973d588c9c8f9c84a9fa0ae826f31f380cf966541f099b0c49d44d23dc4225897e9ec8c21153b01f193ca6e4298cc50ca0a13adb1d", "TP2": "0406ab38c659f1f232e4c72dcfe79772dfbf4bebfdddfdbee265e093247a251a6e1936e25dff91318cedbb4a584a73574e9dd110d14c4d8c8c003663078f224552", "TP1": "041d83b4b3930872df424fddd8161f1037e5d4723021ce5dc2e42a112473ad9a3b0f5ebbcce1cf7fc20d30436583ee22651b97ad8e6b05a81aceea7841e417259d", "CS1": "040b76fafd1c4323f3d296851db008cfc8b48e7e4cd638be472ff43c3d757c952b20e7b5a16d7451e28651a21fdf31bc8fc7a43e6ccf51e0075d10b38c182df1c3", "CS2": "041c51e184be9de9f06940cf3e4c13ac83787b46fe84444277567c6966002a54a10e29c10083acb33abeb179f6f56790bc02caa649085fc0ca71216393716aece1", "HASH_MPIN_ID_HEX": "379e49c5d667d34e267b394a4ac2456c7c7b3dbb8084e476386d4b665c614023", "TIME_PERMIT": "0418ca2bb86fadc730c3d80b70d8f207a1c810685ce9370e19f3008c72198e37d9083670dcc92ce303c045b97ea2eddc6eb58c392e2b9a4098ca60a78539894063", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226466623765393566623834663764616334393763316233396536633163663539406365727469766f782e636f6d222c202273616c74223a20223534663366323064356363353132343937306239663566333639386265353830227d", "TOKEN": "04235ab40f0b9b4fe11aa2bd5cb49dfa14db5a496ee8091630f4dea9f323fb83610831b7c2341215fc0b3998a4541977ba3acd660a9199a0bb211c3b78e668b4aa", "U": "040f0e1674d8549330db161727267c7685686f3ea2110c5303728d812326b2870b1d1e8b5849f3bd86eb9db27ef21cbe0b56b7e4619efd8a3dffbee943d27025b4", "SERVER_OUTPUT": 0, "Y": "08b2f2e79cb6f78f87ea027091ecf00e152e99231319495908900c4207128dc3", "X": "053460bace17b39355aef09f882ce2839bfe42d1de10c1792f4de02e4feb183e", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"dfb7e95fb84f7dac497c1b39e6c1cf59@certivox.com\", \"salt\": \"54f3f20d5cc5124970b9f5f3698be580\"}", "test_no": 77, "UT": "040aaac7af6fd82339302618b9557372fd4e1c96e7468997474c87706f57672a1b07904627ea485401eb844dbdf1b3941f9927116d7de111f01ba283ec3db69282", "MS2": "03163e72baa5d8a46037e9fd1ce8fd9fc264a4429996e5c10e933f5c77043342", "MS1": "0040f0c81bdfb514425218367a2235ca4f327da814891da632f09186e6bee69a", "CLIENT_SECRET": "04056cbb49eeedadecc10a5cb4ecab4f0a53541920a15c8d6f2218cd4d18da6bad1669140d1b01be6b65cfd579fe3f03471dc180076f3ded3468f7985d08461719"}, {"TimeValue": 1437055595, "SS1": "1f288c258a6adcb96bf1386145f748943b5a05e121bc59114039b85c1dff125f1c95b8d7a897d0019842e67e170d36ab6de8414c931c564f517251fe7cbc39551fbe29186b4306b7f5008764ba4eb769637c0160c6abbedc8005855112eb9ca00861fdad42d2a7a623ec6915d0678e4c8839d0ace883d80fc2d1658e086f1063", "SS2": "06765712c78b9e21ac8d19e9a95831615aec8bebf64a556aacaa32ddfaf9ed70089c19042a1fef2b324dfff22192bac6fc4da043e4d50d3972b85db4e8492b0c10f7165e706a58be584b934a3bb007e21b4730c45c1e3b03ee538a7fb82fc8fd090ff8205f221c20ae1cb6808f18a7c517456df1a6e7b5cb6bfbdb8f0d5b4d77", "DATE": 16632, "PIN2": 4233, "PIN1": 4233, "SERVER_SECRET": "228db6ceba466510c046b26819606f499b2d8811d09ca6e9e8eab98b3ad3419f063ad107d71c077490a927f1dc8c970e071211bb4dc88d2b036125eae6b7454714f0c0f9041ba49df7a2005a37668356fb6c43aee476d07d2c046ff429a62d4918a2c249ae3a7eb43bf24c23a97408f91b60c738fb7ceb54ee4a866f85bd8991", "SEC": "0408903d8476365cf731d49a14322f8984abe79bbff5a8ee4310543e620af1eee30f0ac82c2189ee67605bef4974505ef6136da638f15efbc2856ba9b7c3de353a", "TP2": "0402b958f57676dbdb90368bc710de3b83da7352547da8af6716e441af59bcd80304c637c3dced78a9c05d8573d33745e77a6f73945c68c6d5da715f1f2d7bb7e5", "TP1": "0410f9448e49b6749a694647bb7c839f819a6e6872294ea31c458c71f3da0258ab076dfa7708f045fa0b217322e79c14369d8e6d54d1f647f3ce49b59c8a9fb455", "CS1": "041fc878793a357902262baacc671c3d42ef4e165531cda6b92b62d027123dc92a0ccbc2f8cab86260868599e1c25dc60d182e8167b5359aa873caed59477a240c", "CS2": "0416147d51a8c776b122f09ea652edf84d0c593d9227bcb2d488b147e945ae011321aac1ff6afb9b242984bbfab32bf835cb06893041f45a404803fce9493262c1", "HASH_MPIN_ID_HEX": "a880193bcf5d5cb7e39434353155258524531523abc6f9e69179a804ed3ff7c6", "TIME_PERMIT": "04010f0c3cff43fcff4a99b3204135de51b55fd81bff1a30a61db91fd9c50987c113ede68c7259886d5de297a135982eb1e2f2f2ab3071d7ab8dd8da621d0460c3", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223231323939353132383832663835623730313435383563656665613366353665406365727469766f782e636f6d222c202273616c74223a20226338383263323538316235633939336632366363306335613339663861343763227d", "TOKEN": "04209e774b69d606183d6c7c3aa496ad9e8f800b5e036ad444ebb035ac3f6b1ede014694283bba694974d77bb86125b7f3437b67e1f4044a034d7d0fcb34972576", "U": "0405889868a22c3bbaa3b3fd9f32e1ccf00ea572eed9026f555f6ab681fa6d7da0071ae0414d0f8935957e21fa722b048a5252dc92f48a9a5fb6d228137d9038d0", "SERVER_OUTPUT": 0, "Y": "0391d4f0986fc72b0e584b40c71735366f413bb5a89f1ef672a13e717bf2b175", "X": "12d607fa84faba7edc8599b8a9eec4cd50f20ca500485dc015c4527bca9a11cb", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"21299512882f85b7014585cefea3f56e@certivox.com\", \"salt\": \"c882c2581b5c993f26cc0c5a39f8a47c\"}", "test_no": 78, "UT": "0420a1422e0b1d18efa57f736c436451738553342c2ab994d3b7277fb7212b4d532114a769d0d06eebdc22cde865488d91f44323a1e343309c9d95865b7f4b95d7", "MS2": "0fbfedfcb4ed0765cbf76bd4b89b1a13a3837e592700229ab72f2e8615403189", "MS1": "0a5dd2e5a5e4d61cf8108092058e433a0af6bd530d5bb6129a51cd2e591a0c78", "CLIENT_SECRET": "040dc20047f0defa2aaa74e0a8361167826c13a4a587355c2b761dd567c92f0f51035d29306e87e70727c63766b5af5a004b54e1dac83e3b42f372e998e6e89ea8"}, {"TimeValue": 1437055595, "SS1": "13577405ca599e37a28228ed2484eda1000468aede65a709e53cc334aaba258617353706b4f31bdabc2c09b11d9fc67511ccd83fe7f6f04e29a6a79c027756250cc138f0f13319475e775638f51a3c7fa8c461c0626326d04016fd668f7bccd807fe34c35fb0d30de389eb90a8b6d0c12956909846577c7fff49cacdf79473a4", "SS2": "09ed33ace5745905668e2f14c5eae11e5cfc5a073337c19914d5ddbb9a3838fb16e07378df55186fe65288fca6245246777486697e2187e6aa0625d154b22e7c0212f0f9bce451a4e1fe17ccd983138636e732653a9efd9c73b55c1f5af34a2119c3e506015e84d30567bc8ef750eb161514613916d259ecfdf7ea38228e2082", "DATE": 16632, "PIN2": 2174, "PIN1": 2174, "SERVER_SECRET": "13dba1589935f997862c286d943214cb3fe98cf24ff4c50007abbcb8f09e473c0e1dc65fa3cb6d0b77464086ffe53fd425747aa30819a80db4f2dfa224cf3fd0040bba1da7217a0fab40d9393ce5699355860faba5bc9d91c5877b4524f810a315b7dac32e996cbe4804f79b2b9159d2c52a1dc3149915d777d517b7e127a383", "SEC": "0402cade8260fbfe98d5132572e1bae79aa519de5e208e28a075dbc451f9a4e59e0a9227fbbb9692fa38881808c35202a21a7a3802ef42b6a7b932aa54f049cc33", "TP2": "04058f027383ef93e7d8279d08845007e62cdee8fa48a5976571fb18b60bc38e8e04751514bb496c65ecf2fe1a62f502310c6f8df53d27e287b80db874b8fcb5b0", "TP1": "041838f5552c88020f707abc63ba78cc8cc044770bdb141f4cf000ec6f21b3646c10de623c4130eb1f5aa2d89b1e874c1268c4d6295b2168f4e8de2c41acd7e360", "CS1": "040c93f531bad93f6d55dc7de296eef07675a25df5bc7f3d28d5c26411408213e606ef5b513b1c7f6eb595a27a2d6bf34e24e4febaad995955a69e744b5e101a89", "CS2": "04036ba43a387d7ec7ff7d810849d55ede70262c5873d3b7e8b455a8e8ee6df5fe02373d54d5080f18b2a82ae5bc2a03c501264e555d3359ee4813564b579058f7", "HASH_MPIN_ID_HEX": "4f897b532a509331144495de0d645f848a114d0ba88363ce9557390be9df159e", "TIME_PERMIT": "040815c7461867ab0dcc6dd3b8da4837631cf759148f4c3d1f06246346e83f69610be044c7bde1c6cb66a4fc032e63633b7a36f4e33c1175cfab787de8e952746e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226430663664386232343037356132363535643430623636366366373035356565406365727469766f782e636f6d222c202273616c74223a20223364323132306161393133623833616233383832366235353336646662653964227d", "TOKEN": "0400cc68af0e4ebde168ccc404e251a1284f327c4c529d0d32730b14e249207fc71fe09d91d74e8398f977be79d22b52fe485734cbdab193302be857614dcbbab6", "U": "04091393f28ca834073db01ab5e9c3ec0652884f6974cc74ef337ed4b9f36258971886f4cd3346c3adc71eec3884732f509239074a50d1611aa8192763b39c4ecf", "SERVER_OUTPUT": 0, "Y": "02d54ce9e66152af30aaaf18a44b1adcc2b950149f5deaf055884e5167e43997", "X": "0a10501b227e36afe7960d842583a8e9ea5f5c8813ef4b3542554f831771ac46", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"d0f6d8b24075a2655d40b666cf7055ee@certivox.com\", \"salt\": \"3d2120aa913b83ab38826b5536dfbe9d\"}", "test_no": 79, "UT": "04092068c7798aae3d55b4c83cfe03fd2fe6efee733221f3b41ac0d4afc68b8a901817d1557cca8accf6b718c9179d4bd25fe3c8d92d4153bb42934ee14807ccee", "MS2": "0ee60b09cbdd4b538621c75ef042ba3bbe33ac54ab8485d0ca84c006bfa4b704", "MS1": "088ed2b8a9b2bc763fd8515c3076315693fbe0ddc7e0aeb13e4815bfa6ab3aff", "CLIENT_SECRET": "04077768e9026a73b418471ce9df7940d37fc1c747bd38e15be23db8e5827e2e9a0325cebd4606ecf44a4985c09df4909c0608c92042e2f7c5f78a5659d274e23c"}, {"TimeValue": 1437055595, "SS1": "0cdc019567564746951f565c96bd03790bbdca28bf3030b85382a11bd5a274462193147279d912d978a2140be9f1303ef60276d445d54c516a089fa28162322015d7bad226dbea06b9b16e4dc80cfda19c5412d2583d3938e98e19292c334ee8066c39763296238f3a384f77f54df6efcd2327486a7f43f5231464cbf7cfb497", "SS2": "143f950e63a472ae28b848e844fc56292c03a9eb73fdfc4c2c4596c13817c63e030314f053e8cbdfddcfe637d2068b6145e4700377ce147a6f5abb2556994657095ada771be7f682d6c7af6fc044baf71da9793bfa45a7c313916b840690cc821faa10dbd63713a4f1e3da1bb6c594b48bc80af7509339d987aafcea48a610a6", "DATE": 16632, "PIN2": 8887, "PIN1": 8887, "SERVER_SECRET": "00a5c5ee3bdcf0b911ba02adfbd946d6c652299a65b2b1d14ae1c4e70153631023bc79a201380387b4fb8758c0116cc3262111c9ebc30b1997a9ea6860b2a8fc0c705a4a9a57e26fcf2fdc3be8c8a48f7c927693a95b92c931dd7ea1f2fe621c0345595c382379673d9313750a0f444ebe9bd0c37f097eb9d570fba5d58296fd", "SEC": "042302827ecb1c091de4091c90e249003d374529cb3fe4e63cfc873b5469fd150005f3dbbf7fbbdb81f651be8ecbc0aabcf17ebb4629497889e962b398f6d0966a", "TP2": "040bcba2b34ff60484d9f377c7f15f5c92d4b52f90cb1e337a8d28402a28fba177182c0c74418ad9a7a445fd437d2b9313451a09d5d111af992b5149a41bb68f93", "TP1": "040ad2efa9bd69f333f3ddf52171f0ff0f8fe320b8b2aa9186859946c6dc4d721b1d40bce66d903f1720b2b0c8e0ceaa6ec29ec0d25ea2f63b589ee74833731b1b", "CS1": "0406d1ec50c7372c44dfb82731b991e9f17ca0205a7d4362ffaad4692d0f8841780c0b6fc2bb07a94b0c00d46a9ac1e57469833a91acb3a14f8d1b7b507f2a1518", "CS2": "0419a9bd04a0e15822594bcaddc649a24847a9fc448d84b0526fc2ab3050a12f621e86dc5d5d971065c8c570dba333d554373a8cdf245920065956db44acef82ca", "HASH_MPIN_ID_HEX": "77258941bca2c5268ba13b4ef2da76965638eb0d725f1ac51e771ac3e9460c23", "TIME_PERMIT": "041310789f6291d6d459cd8173c298fcbca822ac7e1d2ef6f58311d2a4793c35710a498b030f72a82bf67b7b44bcad00a68d6115be82f5681d70690851021d740b", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223033336465326363343531393666396364666130396639373933646666343935406365727469766f782e636f6d222c202273616c74223a20223336376239303030626330643933366462323232326236343537303166313933227d", "TOKEN": "040246d0ebbf1ef1fbcc770dcff5d9ed14677421a570cc036322f04b40a6b832611ca77ce17193ffeb485121fe05e1118ce815edba305ff7cdc26ddd1b01204075", "U": "040ffc38649b30643dd7c1040b29f69e6775388afeb670356e65c9bf9db2a090de0072e1b3bef3eb33cc08d9873e3a3da631c9ed04272ec547f7fcfac8e7bc4c03", "SERVER_OUTPUT": 0, "Y": "10c6c5b9b60e91e67a12a936c185fe1f9cc4e576e69cfdaee25b5bdbef62fc00", "X": "013fba0d25b8e02bc6ba1885f0762b4b2e9247b3dcbb9472d5192038d6ae3909", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"033de2cc45196f9cdfa09f9793dff495@certivox.com\", \"salt\": \"367b9000bc0d936db2222b645701f193\"}", "test_no": 80, "UT": "0401b9cee474f968a182e1c9e3b60d6cb3ffa278e83e778af2f144e25a69771a780b5d87ccaed34affb084beeb3fd34088f1983f3ce6d27852ffda0a9d6ecbfc2f", "MS2": "1757b38bcda53b5a4dfff11a8ba0767ca549fc75fc8df82e1228dcffc7a0ef7e", "MS1": "22e5f18a90e684a1b5c55def357d3280d91b1f7627d1e681e0e5ae42662e84ee", "CLIENT_SECRET": "041034fa32296ce93844b021c250d6c9d56c9bf7b3eb4d418276ecc469527d811b1072b5f3f2cfe77ecbca4d9997405b686f2fea5e42f11da15573025eadc9f508"}, {"TimeValue": 1437055595, "SS1": "13ca345207ddec9a8cb8645c34cbd532aa9f32dd44ec6b6180f18e294257acc20d17909a87e918d345fb7b8951ce5509696f65e0eb287ab3adaea016e1b8951e20ddc1d4b490b957c3bb6bef42e314b3a50427635919815e683e16c81571dda5126d35cdca5e1a6d678741c373dd5e491961cdcf83323fa3757da9daa06811dc", "SS2": "049b72729f32894462722da3f7c34cd3d26606240005599620fe5949cbe23d3e0b4980b98259bc5521620a43971bc6af9d07b6f0db30bf9992588460115523fc05764fbee60a6871d09e0db3c24aafbaa1ee73dd597f8560a1af8d53c5b052bf006aba53ddcb634ebf987d89762f3f4dee535f134e2e6ccc9c0c9959f78ef604", "DATE": 16632, "PIN2": 6690, "PIN1": 6690, "SERVER_SECRET": "07c38aae06a77e28b1cbc4fcc5529765e16e246333ec074c74fc1f791da653c6225e10a9e8a34ae13003d76c820ab9f19e46f0679bb04c2efd9432d2b2d52fa71a5c3fbcfbf0be42941812378d7e3b80c7f56bb71e7bb038a8519c74d59bb554132a18e169b0e27c64c75b808368c9115b09eb9f811d68a6e33f2189a20d07fc", "SEC": "040944b67ab40fc9d750542d6012a1781c4296bb819d491eb324f9aca500e904080d333145df8f3aa1542c9ac479211c08056cae16055f37a2c94c899984432235", "TP2": "0417cdfb0ce476f91d499caad5105d9390b5f393d3bb319095c40936dd25fe53860ee6bf64c1a39c0eb024c8230be02b520fe720a5c5d2af1c61304b60e84aded8", "TP1": "041048c91292f19469f6b4706576aa38c31cd68e169f2701dd5eebc31ea3a94e7014063d2cfc0ca76ce8eaf0f7099e00948f57dc6acabba9072d74bf488f21db4a", "CS1": "040d6a7789a1d2ba778e1746425d29d76e00b2e6de08b2d175899ff638fec480ff0ae8e26a5585d3d4dc695be5194009d7bf71a1f113710f23291576e664fdb29d", "CS2": "040134414542b9d7357c4571aedae20babd160dcd8c69ea14799e5c59edef59c0e038dcd7fbf8ee1e579173c7a978960e7ae2bc293313549646103c9b337e9ad94", "HASH_MPIN_ID_HEX": "ef72d6a8006508c3483b21f96f35df00146aea66aaa96b11c11ea980d18b49af", "TIME_PERMIT": "0411cc44492ff758e8067b352531b07fc57c5e51f585c7abfef4e79dbaae2db78f1a5bf25e62493ee21a011a1437464f6b207c07111092239abbfb95fbda6905b5", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223831323337626665626163333966653235656637383933396661386264626662406365727469766f782e636f6d222c202273616c74223a20226438303766616230303632636335356461333934623437626138366136383363227d", "TOKEN": "04231a2deb3f54482e9a893ede79acb11a9bdea22169448ac455bff2ad36bf26771731d0535e5fd018ae7b2a6b6b1ccc47543b99d58e0932514b4e42ec5bc85b3c", "U": "0415f6d77ae9a14e217bce860ee819d6c2c255c399daa898facf846199b51d44c71a86dc7a3b62d1004e225955eada33b5a370bc66ad0fd49bdb06e8aad9b2ee82", "SERVER_OUTPUT": 0, "Y": "03c841d08f734872def0b90e5ec1b57571648024599c554d26eb8509b7b490d9", "X": "151c4cd2f0016a8b0494ac3151e90b2f859a6f6f0f03e5b188eea1e0056f6f2a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"81237bfebac39fe25ef78939fa8bdbfb@certivox.com\", \"salt\": \"d807fab0062cc55da394b47ba86a683c\"}", "test_no": 81, "UT": "040651b70881e6272380bc52367d6ecd178acdb685c3fb1b30ca00c8e8064db52c08339cb3ba487adea0131c9e54d54015ba1c60e5a7de5be0dd46be89568bcd20", "MS2": "11a395a3fcb5c25064221caa960e8b723195df2d92f3e999ed6536ee02a42a77", "MS1": "168ef35aa5c33167f5c1686dc899f7ece78de3d1540a72c269bc67a5f4540d55", "CLIENT_SECRET": "0413358654d74483cb4018a332903a19576f22088c6c755c68f2a9e8dfc59ef9b707d9296c4953d68bfce7ecbd56defd11611c43f51e0ea754fd92b05969ed14e0"}, {"TimeValue": 1437055595, "SS1": "038e16e89c02d9e87e60c0b907cf5ab5c9f54bce0f5d92de5b9e4980253a2ed10181bbb6a58c47b4936b38a07a00220ca1013f2d74863704331485e174e4a6ed1602c55c1341b9d51922799ecc6ec7dd3daac66a4efccd4c3fc76d2b53bf203c1ffd4acbfee9508366b0f9b6e6aaf2f05738506be2545b0f88e691949b58f49d", "SS2": "051a6b13f08068c9c4921a2a1c138c43c6da88faf65c1a94f7ed43e158d6a2ed069d867120e990b1ef7dcc15dfda6589e97cb16fb972735bd7b0f55b95eb983916868f0ed20e3cfc116f8c76737faf47c4e440c0adc50f7ab97eb1f42d14d8f4220aa91fb8bf3b0f88e9bcc944289737d59f1c5f42ec646164a67d785a4edf58", "DATE": 16632, "PIN2": 4110, "PIN1": 4110, "SERVER_SECRET": "0a2fa9f1b1de7b65c907c596fde01c2792cd48a3fb1d35d4d1956209c9feddde0bf0fcd5c4516446290c4eb8ef73e45f72e92d573cf3e54c4345388431d6d56a0a0cf880c8ef1d4d080078ab9df390cc159392e25de58a64a28569e4d10b56360722f09a5e33a62538f0a0cdb7c284cf3788cf62254f3f76674b6fa9150a7f8f", "SEC": "0403c2898733bcf4ed652f30fb812d88f9d211318f9d29d60769115483f84a9b191e29f3b7955324863596020bf335764f1d77233096eabcfaf779862ef0c41cbd", "TP2": "040cb0600abf445eef373538f70f9a5a76031f5bb88478a1b52c147bc851f15f17053b35be8c1eaf5147c2a59a9c4aee7c4ad19c819af99de096ab4cd49cd0a97b", "TP1": "041a78a1cff2e12ceec3ed24f4985b5fad501f4cdd0a11a080c4b7f9890b09acbc1143fd7a37ce7a61022b0176a1b5a7c3c0d7bbc7b1639ce810f630ca8a3a3c01", "CS1": "041d0c4af82a85183bc5d4452bac3e932b1cf2b30ca7bb0f91c0bacfa20ded2b8821f01fe1e34edc647608d04f9ac78f6e2f2906a1e5e84a6c0474b70b4494e1e6", "CS2": "042143974ef6532b76ef285121d47f039aeecd5dec888e2c37890275715b6c950514e5ae22e375355dada1c948be7bf44e2694b0d4c29a02e04c1b6b1703f11f05", "HASH_MPIN_ID_HEX": "db9fc81a176dabce8484f7f2fdb3a1b00b743af1ea2c70d9d9dd463f46c9df13", "TIME_PERMIT": "041bd61112ce778120a934caeb01239dc9813be43ec5a0b7245e5a8ec05172475b06c1847e9c109d6e3fe747c6890552f5c0a823374ec4ff4bdd17906d3939bb08", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223734383365336163643035396435356634356161393236346365343031356362406365727469766f782e636f6d222c202273616c74223a20226161363631623735616264303630303564623063623164356332313232366339227d", "TOKEN": "0417415f3ad8ecb0d00f7998a4fb25fe3d87439b56d766749941320d8a4717174d0f9d7432fe41bca083eecc32e9b3e5aecccff2d25e766cee07722295b8125f4d", "U": "040e96c015353c9ca209052ae533dca5c96f580afbffc1f1f196f1e1160ddc352a21aebd5115ebc29dd962b546e086cc862c02fc6eb802432b5ec797251f6699d3", "SERVER_OUTPUT": 0, "Y": "1cba7505700ec15d6f8b116c6d5025b4c0a8ee45abef0d887ffd71afff9738ce", "X": "0a456eca508b447877ed41dfa66a11db4c9cb1203462580d8f784f6cc34a6251", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"7483e3acd059d55f45aa9264ce4015cb@certivox.com\", \"salt\": \"aa661b75abd06005db0cb1d5c21226c9\"}", "test_no": 82, "UT": "04038bd9e0190c7f2abb4fcc4804485750c994f426a71bbce19149d7df7f23633a1ef7420fa3f5e06808d56e178c72f64bb5af2e1ccee25d186e31bcbba86073e3", "MS2": "1325f41756156aaba548096b7c8822bddd1788ddfc9e36acf77333d45194cdcf", "MS1": "123c3af8fdaabec161583cd7689f315127aa3b60f1a97edcb640e76acbedbc50", "CLIENT_SECRET": "0414354942e1379dbb9397524f67ceff52266f58eeaa1dd4202d2fe172726e11da06613ab186dece97635b1d9c66f671f0354d1b0eab9ad2a74f1654cc58931909"}, {"TimeValue": 1437055595, "SS1": "15eb14655f55715abdccbec0d07b1f659f2c9dae236c294944c67c9c821f76c20d1ba1597bc0c17ae80b03a74f193d5f2d5b49286d10e8c67af6286d79013e361e8ccb79bd5897de99830374ee8f30a62141ed49775fa4d011851c4ea6b19a9520cd968d748794d4a34d9dfbab43e4601c1e8ea1beebdae6ddc908ff546bbeda", "SS2": "1329ce1b3781d7c86ade297ac22392ec44af9a6df94e212b71f69ed3135bd4dd1c71037cb7caf59f86ffaf1f41ae33815d1285ff32161ab509af87e28d5b482f21fa749abb7577db8869652c2a235a99cd0745851bd193b3c51a3e695d7f491821037dcc750689a02425a00c7decbea18bc1a922654054fd3758406f07158ca0", "DATE": 16632, "PIN2": 2452, "PIN1": 2452, "SERVER_SECRET": "16b46e62d5e1909817b0b4a2df83836cd2b58117f8567865c87735bfef578b7d195f3431dab03975c42c806e28cb9972f95dcf9f5c40ea2af2b026e6fe2bf87411bb04adbc1f67c1eb19f38c6b991e0b049169d651af051df8de7e76cdfc45f31055e837303a2add4fd1a99fae088b7176056cbbb44796f0aa2d66af3f484ee9", "SEC": "04103f39f5d6ed237146759b20a91d73f2763cfd86bd1284d1916a4f0e6b582bb60639053380ae697c4f3013020f2c8eeeaa55a69728e024a18ce4952ab2e2745a", "TP2": "04025f4fcd0d828307add741389bf3fa9fa6b3c73594a64dd53b9f70de6fbc039b04fe6596e5635fe352ed934ffac0aa2887c4bc6ecf8c7986d5e20295d8526616", "TP1": "0419ddda7589d8eb849e5a5c19eded2649ee91af8e37198d41dc9b9150e3a4057812991d7a4f916175da85d3d83d71b426a1823d03b4cb9127ffb8843939ad7abd", "CS1": "0423f97691fc70e900d1ae1acfc46122b4d4adeafb9466733b4448435d2294fc761051a4b5c0ed5c580c14827d3bf0b8e722a81c9d1c50ffd3f6e005e00c02b093", "CS2": "0403afa0890b6ce4fdef4e068aca89f378bb7d0be9534695978b1c3f8475306b941ac2e89b8c934a7ff18e8af6aa65586a3a7cbcf086d5b75a97f6b2ccbf0ff4a0", "HASH_MPIN_ID_HEX": "5b5c390dfb545c1eb365c05f545603be11328b40a7cc1d3ae56a791f83b173f0", "TIME_PERMIT": "0420129dd2f2d917fe2032975e7da0aa69ecb085a77da50e4027df86ecd693edf211f00db4c293a859ab45b8e36f897b9150c30873753c0df282a7b25cb96f05de", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223432366134333665633531393233646330333762353963366661323038393063406365727469766f782e636f6d222c202273616c74223a20223266376239336262363133363762363739616330376536363932396664616539227d", "TOKEN": "041cd0ab29ef22623a6a1f600c4803ca1cd4c78bcb74d6461cac54487b6d394a8d20d712bea473a77e0c10c5928d285b75ce5fe9801709e09d70c35b3d630d233a", "U": "040a7aa4662b508e5dbcf3992cb275bfed80efa49b75135fefee2d2865c96b6d1906ae2f2c0d36c39eda9938db6b4e67d9ab9f46fe25c425bd9fd4dfe688a525aa", "SERVER_OUTPUT": 0, "Y": "1c5fa46a0a666f7be48e17fa667aca3d38d08c48340082f4137dca4542792231", "X": "1457bbb76c72b01319958ddaa013fce69c3a00f4e814383ceb50d7b5d0ffb347", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"426a436ec51923dc037b59c6fa20890c@certivox.com\", \"salt\": \"2f7b93bb61367b679ac07e66929fdae9\"}", "test_no": 83, "UT": "041fbd04220ed06354eb67a7bfdbc6cfd95fca0c61c06f70ee84bb27b35ad5c7c90294131a8e9cb678e0dcaf6713f172a0056e39c6d96f133d932a2e676c8514a5", "MS2": "221d05c9e83a8fb508f9946e55240112e157eccf9942b7eea683ae139f1252e8", "MS1": "016f05b68848e591c883eb7caa6b612cd244c1149908bc08ce434ef998cea16b", "CLIENT_SECRET": "0419c534e30b50146ff819dd5d331dadc75e57fa6431d3ae236159e48f4cb02f47014aed0efd295b82f00931c525836f38a43a38cc75dcb9bde166f9420297181b"}, {"TimeValue": 1437055596, "SS1": "0257d052951c3d55893aba56b6d8723a973c5e48361dc2a5e16100137d7e17741a053da4495a05693db60f88ba886142350ce7b7436c8d7c47adf00fc8eb93a0176dc0512b65b093f9c767e334c5a48b48184e6296ee1f5741a631dc1dac0ce90e610aa87ae5c7aaf7a1030b0155d9303101e2a2b9931b981a8ba01c09f28008", "SS2": "236031465af503389e33e881ae32fa767076b23dd5c6aa949369fcd59a299ac11f1ff708f39cb15faa42a25e60dd0f8f36560ad0f4729e0f436fb5f8fbae72a8233df55b5e55ca67b3239e5fdc3a7fb293d41c497cae5c5449e797758ad3e4ae1ba90168517b4470b259a46bd4f21d48288bbd64e2af3f59c28dc07f1252b639", "DATE": 16632, "PIN2": 1879, "PIN1": 1879, "SERVER_SECRET": "1c0fcd9eecc73a17e75956e9bf6b1580d15e1fb7cdde278c5abdd9fcf158d4ea03ef5bb7743e84d28b62472cea71b0a8c29979a5c4e3e46067ac2a08562cd18f14db0bf50cb7f61ca9830d428653ba7cfef71c4f630352d9e164d225e3d15dfe0a9490f971202043dc5444411f088df4cf8ced6727da720fce338dac4dfa92bd", "SEC": "040931603b2b9fe16c9de6fc134e0df43e798dffc193c0f0157d0434d6e662c91b1ff109f8a2dc73a62c15fabffff43b32627ee624b54a4f33955a9f9fd3731bc4", "TP2": "040eda076c7706cd0cb06eb14179b57ddee66aca6992676e1637b00e2173087cd316d124ce67a4589b759658c9e6fcbf1652e81f7d9b953780093b583d5d0e009e", "TP1": "040d49e4ce5e05adc5abc83b5750141947d0a650a2bae106255fd59d93748adcc618809b6b618e5c0e77089265a83aefa6057040a36096c46b5c8e88bac9f88b82", "CS1": "0423666a9ad6259487e18ab7f5e094160528bb5ad790f7f655172aa7e0fa66889603b9e199c181c9e2d47e75eb6a0e2e382e973bfb9e27a42b3cf50d0d7148e149", "CS2": "041935568d89b83aa8b7a77e22cae785633aed1936554fbd1e4169d2168017ac6d22db7a40a2cf98f6fe1b41d93e37c4fe7c37da739e434a34900c4d5fb71b4f88", "HASH_MPIN_ID_HEX": "7c899e9dea578c81a10ccb5d93541836dae4f7ce95cab9bef482083ef3bec13b", "TIME_PERMIT": "0416818c4b65e5b43f90d1c6fd95c242bb93d0d38c5fa81aa43a786f3a397717c60d40e1347777908d30d9f26b6e07f699739378c9d2e9df1e49401fb21aa8c9e5", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223361393137323037376361636638363861636566356436653731383036343230406365727469766f782e636f6d222c202273616c74223a20223465626566663761633334383932306262373065623461356134326436653562227d", "TOKEN": "0415b5279b65e4157cb7d01e40d4c3fe2127441cdb3e5985ecbc23d389b83dc0810fad2b2f6f790ccf94236cb667e7ae8161b314495a97b4eba13fd8f75565d6b2", "U": "0418285fd826c3bae6b9a0602804e275694a0d6b2f5ea9035ef34f1b46df302b8f1aad417ef130c97a273b46204144d6e0b15d6f264e3b66b34a3384a695bb37df", "SERVER_OUTPUT": 0, "Y": "1af453f8c2a8b26f6fd24c8764eddf13706e1a7058f8c61eea6844571d1bf365", "X": "04e483382535a89c1a7c06df3463c1ddb23822101d794571c1b4138beccbda04", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"3a9172077cacf868acef5d6e71806420@certivox.com\", \"salt\": \"4ebeff7ac348920bb70eb4a5a42d6e5b\"}", "test_no": 84, "UT": "041be33114798663ae9a44a10c94a84f2a147fb2463fb0ddef5c64807f402593c60150828fc1c081248d249e7b7ee962cef376743f5feaad71823bfdf57487c670", "MS2": "010f0506d148210c280595dce5fdb76aa8cb6f38511ac35c2fc2ab0f3ce8c221", "MS1": "0c98c6bb81793ab5b9ad67f71e9f7fe4fdc9a4c6c1ea5a0d42723d35c07ca4fa", "CLIENT_SECRET": "040bf1b096802489caade680bbb6c8b50f9b69d2117c00157fe7dc1829c715612b22fff56ebba7f13e8484968e93704fb22a3d0fbffa2bc39971b7af09c480ea8b"}, {"TimeValue": 1437055596, "SS1": "06d29fdbcda974e6e3f1d745fef10d0ebf82d06c977290d20632e94ce0ffb2d515524b80f7d58442e5e4c4dc7358cbea7c21f36247fbb9f198119cfe0402310a02113591b5a642c6b4c28ec9c900489c125d0537020807aa7e942098656d3bbc23f476a636a7a2f9b123a5eecc53e03f39a4758f8eb101f8ea11127a2a59bff1", "SS2": "12875b352b0e4bda1d44046cb0a355ee5f5a7f068b74623ec7de91a258d6a01101d50378d3f81f9dee608f3c21d12edc9d2eb1223c8041d94bfe0c35337c14f2111baf7d24ed0d53646d792609126cedf9ade308dd1b8f2e54337cee23b52cbe028d15b90cf525ff80641201e5f0c928e030ead39c90891f441c4a0bf1cf448a", "DATE": 16632, "PIN2": 6702, "PIN1": 6702, "SERVER_SECRET": "1f38c646ef08c5d54af774e6231c6cbd463646705ce29af0d2f93a7b1fc366f31ae042ac6f4d73f09557ab8e246c425bbfe905d888f4c95d49b6d69b81cf5f881a461490a2a0cdcc353491462a42c7903f559b91856372ed0b50e7a628b4151218945bd5d2150a817c582b85720ed6ada3f41e47e53a7929fcc38b736538daa7", "SEC": "04034084e94ae7a5576f9e14da406a399aee0e077578356740ddb1a792cf6a29ac1b87c92cba5c313a9a7fd484139e183c2e7fa5eb4d7e7005bce3e8183a646a5d", "TP2": "04034354f0a3b1406c404a45420c5291912cad0d067819246e84687e7a56a16b9b12a04c516e048b75e1696486542f89a28cb0115557b1992af5234e9fdb25b07f", "TP1": "040adf69961221b08bcf6381a0e66d1b410a21bd9d5323da0051147ec2300f5ce01fda545f1e36decf711bcca4c686283c25c4592639b043f4f2ab510c72a2ab21", "CS1": "0415d1bba89bb6227819091c9dcf45c94f4156c0dd3b7ca1d0a7f0fb92039b4bef1cdcfd06011853c549f5fc7bf525e22a889b45c8e375a5dfaf7d4af28e2e866b", "CS2": "0403bd880bbfaf49ff6a3a8474070502c089a5e740dd8a7f90f9fffc903b6b9de1213c38ae08bc1b7c96f69a71cfad4673895fbb7c9357cc3fc843c36ad83d88a1", "HASH_MPIN_ID_HEX": "2f75bf7efe13b3c965d73ade4dce6bb31dddd85d68ecd7553f96547469be7fb3", "TIME_PERMIT": "040bca050f5c9475b49800392aeff2c74b2212010074a054e4992f828d773a7f1a0526368ef08ca7d76364c0b03898a4dd488725e68a5169eb2a789c961758d046", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223663376261363464646262383032363433306633306562666263383739396361406365727469766f782e636f6d222c202273616c74223a20223030666165323034613432383764343536666362636235316536626138323066227d", "TOKEN": "0416f185046c219295b34ed631d4bc793ada0501c26d7e5ae22df09773df8a2b3a18c6081a8c8e34cf3111ffc91bd8f67f2958f785f5f755e863a568fd1b873ef5", "U": "041e79e93463a48afbd37ec65e05bc63e257f5f36ed1ac62e745b6715bcff72a3b16dddbe48bee190633747e1106d5524b411649dc4a22bab795bc4278819bb775", "SERVER_OUTPUT": 0, "Y": "1b495418ec7b854513443c7f7b6cca9773a8cc04b4146d9954e983311f9c0664", "X": "0e0e1919fa69aeb924af316cad4d53518ac84eb9639469b56c293d045d48dbce", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"6c7ba64ddbb8026430f30ebfbc8799ca@certivox.com\", \"salt\": \"00fae204a4287d456fcbcb51e6ba820f\"}", "test_no": 85, "UT": "0401f6f36fb7950e23131e6a3acebb9e2ad2e1e30f032142dc69d9eec213fa098216e0ffa3f588c3f046fb7f8a2dd3e6c9666c281b5fb978c27b30f5fe6b1b5335", "MS2": "13842e276f21cb334f9dceceffc4c99665f7ea355b7c8a48adb09118e549a90b", "MS1": "11098797b81aa45566e0e862f37bb6b7400b2ff2a4563826c902fa097a783d93", "CLIENT_SECRET": "0408a274aa2ec0863198f7397c1684c6320000bb307efd92ede420c9cc26a1cd3a141a6077509c4bc09930722bb0de19900d1a6944339d9812def1f3b1662cb3de"}, {"TimeValue": 1437055596, "SS1": "19f16b6483722d77cbc002e9c49a415fd2e01792c3f45480ff526031bf08e6470bf679b6ae274cbe749941bde5179031db46e0382cb90e87c7401dd7c413bd1d023125ad5095499c407dfa527995a87fa7e1fd3a1be61ddfb921269e55fcc78616f16b816ab7cf0d481b055208e22478f14f266a61b1dbf090a7f1a8b4140e75", "SS2": "230cb549d47b76a39b0628851606ed373bb50ac37c6d846386868f7b01b6516c03c635c2f671e94c3b5fcc95d78a774e6c788a79e74f4cc1737ea9db6a1615e5235dced0fd47d5816c5a5217e6f16f79318cd75f969e8d7c151b2046f724d6fb1fb42b58f02f8df0540d25bfc3e6c0ce39e37a4d8042ecd311d21278712d77d2", "DATE": 16632, "PIN2": 5189, "PIN1": 5189, "SERVER_SECRET": "22489b355e9da3493c8278e2cda9b55b883f2db23463d48b34d599a36522c01b090656c06c53cd66f434cf1f997855d101ef1bf2533db7f675c255900543bf5214e84dee6a99c507716bf41da164c863649c40b36eb96d33024a723e16b01e9101064ab52d517a01e6edcfe385b53d318e4fb066febabf9491cee8cbef441f2f", "SEC": "041215587d000485101037349dc3bf64d62d2546025cb19002a3145ec259bdf06a0604d0444ae64db6775ada19f74339a181c3804e788c1c132a20f7ecd56b0af9", "TP2": "0400047f4defefc8baed56f30cee2fa742347bbbdd88feaa0cf8056171da916c3f1462a91761fddbaf5e0c7669865ae007638ae55a821e7473b6e771a435ee14af", "TP1": "040713c49aa96ab4172a8ef20efe5f9508d9ca440aadedff869bc0295e71cc9b440b3d95d55ff9b3ebde957e286f562c00e57d2ec2bbde104772c68ebe9d8b1a50", "CS1": "040273cb33e885433a5533f258921a5824a6b9c4ea55f85f253d954f2c01e730f202cbdc689495fba3ecb20bf8b86c6b0927ec5a3899dc8db0f5b91c9218b531bf", "CS2": "0416f20471ef105c0c8dadaf79d1414f24b35aca82a46218466fb96587bf23c77e0b8eb63440204e38736af00d5fd967c20b5e9a7946ab879ec44b9e5fe0647455", "HASH_MPIN_ID_HEX": "ca1ba9aea2fdd203eb37c55593db0f6682a254c8b265cb58626b50da531ada53", "TIME_PERMIT": "04237caa62583655ee7c7bd1098ccfc58f73c463c4eb2350916e3fd71c878a66491d1d4c057d1f8ff374e729465bc1ae6f0faf7746695c0a9ea1dff8504c102e83", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223337393666313832646566656632356263626666393166653863623834643266406365727469766f782e636f6d222c202273616c74223a20223761346237343863393632643431623537363333623666626435376234666630227d", "TOKEN": "041d679876b431ff74079c739bef6acc67fe5331228a7cf58bb3b93668a30049190846cc6b3c6c7c96b2ff4f245e4a9362d9be47f20dc879bbb2f116c91a354b46", "U": "041b03a357f3c6c340ba63c4ef65c0fc34a77bd47608e08277d4c7e40dcf879a7709de89691ad35aeb326061247f31bca352ed3e16494b35208c370c2f6ede67b3", "SERVER_OUTPUT": 0, "Y": "1e59897045d73a76719292eea817c81ae0ab256f564995cbc4cd7bc119b5013f", "X": "1139109cf6dcf873238be3e814a8d9ab4a7ea90b4bec27788589b2295262e8de", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"3796f182defef25bcbff91fe8cb84d2f@certivox.com\", \"salt\": \"7a4b748c962d41b57633b6fbd57b4ff0\"}", "test_no": 86, "UT": "0404d139f3f5dcd02f953255424f85c980ac06f6dc9414adc069ce8072f2330b42074c266659b2ed16f69b0332c708338e0b43cc049185412949b464a99bbdf0b4", "MS2": "12e014f0d720296e6949816c0807b184f0c823b597ea560f576b308f0f28adbe", "MS1": "013a350f4a37c7b0b0636e74671992df99fe0cf7f5a71951fb89ea1b31142b36", "CLIENT_SECRET": "040637a877ae778971f3dbe0fe32b5274a9a7350f2809aec266040401944533fc01c7d2a14d2731fde56356c58cc754ae629ef9ff1ac21f939d5b98fefd92a0769"}, {"TimeValue": 1437055596, "SS1": "1af716976c8a862131075b0dee0a510668b39abc747f7efe8f95bf26f1e99c2e1e8f3501166c64d82dbaeeaf6492d663017f4e7bcef3c6dd278847b05685629d07e4959a2ae190d4aa11a67110bcd6de4823151c88d2c6ea8e7d02a32b174f5c18843201d4c8bc4d72eac8debc71ad3cc85b34a0fa580f928cb56cc7879f3431", "SS2": "204067ef329b482dbd70b2003aaf434a6510260492b8508b291e9018fc8414e60910d1109b0b2e26b7c1bde2c23b8aa2b263c1f1c04adf7c1fd2b2e4df1f91b41ae95b1da612bb29284b1e6da79627448109b1fbba7c86359bd3eb32fee7c2b50e8b3bc731ca49d64d52528162be2d7100732e67ebc200b01846cf0d21aa5b22", "DATE": 16632, "PIN2": 478, "PIN1": 478, "SERVER_SECRET": "05f38ce4cbb30fa7332a44ccdfea42df5d47259a4ae12accd05edf3c672c77b906b8967b72acb9c1c31d99d9f0f78cece7eeffe8509fd839ed582165b655be9119b66419cb989b5fdeae09a1420aab42c638d6075cd9826d3a177063f21b220709d399430157650815c9672c8a54c4d9cef8eb2f9e4d0d2d844526b7d1c02247", "SEC": "040d5191c472d0b9af10ff7ec7f5d90366355b7c9ddfc823d2c84dcbb3b9f8596411683499c5a73b15f687431806498bb9af21f197308a8abbb615804e04126709", "TP2": "041593ba996fc0cd9ed58faff93e2d5ac954a7b6075b994b247072348d76d7206203c2bcd8f033d90efe35821fdef886896e7f2c8801f67788cb09af15080c206b", "TP1": "040b30420a1974500ff1cf01af9d81af01a2e34a8d01f5f30b60dc40ec6bfbcfec1b5f674067dddb7233f742bc31a3f13f34ffd7e96ff5232e15f2ff8b7f53d73f", "CS1": "040695e52cb89392ada8563f5a9ddcb31c11a29e82ab748a2b8dd1bff1c070d4b31c3709c07a842f7ee6df7cedaf63437b82ac64cc3c678c03ddce8c1dfc2138bb", "CS2": "040a9d9459684ac0f94767430585172880013510a7c22c99353d871898ece163410ebfbe0bfe438807e80530958adda3905ae457b0ca0b130ba2c1615017da3eec", "HASH_MPIN_ID_HEX": "6db6f73e735ab0f2d42634da42fedd72b2c98e0ffc73880b996144a7ef77a59c", "TIME_PERMIT": "0408eea858e60c1c506bd74d6584c6efcbbc8e087f26fc44a2267fb89dcbbd14ee230518e5bbe27127d951498327478c661357adba12dc0f436edb57db2b6b7bf7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20226561373036353662316665383862663537663832356434393434383832623866406365727469766f782e636f6d222c202273616c74223a20226466386337323839333933313166623366326437643762623861383033326463227d", "TOKEN": "0401229cbdf3d0a20b588fc68c89f74e33218700285a2f6bc813f857c78ac3757116325f9bd00d8200d182a6d1b5aaacfaef2e0a35605559d89f01aa4e65a6c472", "U": "0412b02edeee3d96481bf5fa089e7924fe855c00d53403d6ec91fddb6428f7759d02fe11658ad00af6e2f647e432081ef0daab5401191e637ecfbe01b5894f4789", "SERVER_OUTPUT": 0, "Y": "0f2117dff59b69123aff2b6ca7a46fc361d3e1a76aaa879c0a2869f4bdd9d451", "X": "23d32e9733f29980400bf6e872d3a6b69b5c60ff1f2c8253cb77610d2998440c", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"ea70656b1fe88bf57f825d4944882b8f@certivox.com\", \"salt\": \"df8c728939311fb3f2d7d7bb8a8032dc\"}", "test_no": 87, "UT": "040aa4a20b53e86ee47f62d0b157ea6decb54c3ba7108e269f037001a18cb858820307b066c43ce12cb8f60df88e714996080e7daf68eb5bd738151f654ede056a", "MS2": "02c51b0630539ed2a0cc7818f7a7645cccde6df8730f038d4bc17ccb60d3d91d", "MS1": "187f38596e55e0ea8fcb067ff4ee7c205685e2ca37156d2208b185ca0324c7ae", "CLIENT_SECRET": "04101a02ab2cadbae6cdbd15d1441b508fa131647240c91657dc00abd7426c3dbb069fbc48db93151ab399090e0fe08e1cf51f6cfc7979db4b70ad51494bfb7d18"}, {"TimeValue": 1437055596, "SS1": "0227d08bea581a90d17b53039f53367c5159b4f9ed57efefc6d1a7f8d63c050a1e6e5720fef1b76f83b5054ca058ca70fd88a0ebb314522ecc7f9628684e75d90f6c70b98a46a1bfd88d0e98031644513efc2ef4228123dbaa812b98d93055560d61a73a0f1b2883d9ae2add025a4f6db0c87190fcfa40f40102890484190cef", "SS2": "147bfe601ffb8fdebdb1a7f8ec86890cbb695815d0f29fb581317c6da06a1350032e836e5128b5a85e9c6721ccfc9f26b771de05b46b15ead301acdb0998736e0b7117ae21cff6398605d35ded665a23bfaedc6c0f8a0bc1990d42445dab25b0109e85a2bdfd8e96a6d71b2a36ffbdb6b8f393168d7eba9fdf349dbcf4901850", "DATE": 16632, "PIN2": 3037, "PIN1": 3037, "SERVER_SECRET": "22e2cfff645bb45e00c65fe5ed89fb47c23e838f2eca3a1abbdb18f771d16f601a5f5c2c5e55053490718e68806a6f9d37bab1de4990c8e090f2197a43bfe42d169fd11cbefcd1ac5a7317c96725dae8c3f6ba42b1fa36271abc8ae25c0b2f3b09a0bae0668dea92caac980d9cb442546e5086bbc08211b8e31b73d5ec8af9c2", "SEC": "04069fdc2bd8f4723c81887aa9ae0fb7f40eeca08412c990e21ec6d76d2f2c9a491d6b9c48e0cea7d196a11265981e50077467086544f2201ea30eb342826bd57f", "TP2": "040e2080f51dfe416aee7e835f7e269d7ec3d20537d4970422874bcb77fe29553f1e7d0eb0cc68ceec12ecd9ce037a5863f5b29d83dbe35abbbe711ac84f834010", "TP1": "041cea02f8cb2df510093630fb9ee43a5e4e347403249027e4312c5edca35c290f21d61e3eb3f88faea20e78179d478b984125696a395d5023dab9e2260ceb36dc", "CS1": "041b90ee70919a4f7876ef809573b709a7eeaffc66c779ce31c9350d3efbe4bce2194348e7a2eaf95291cd77a63abfd7483cbfc5227c8d0905c5927ba5990f3ff3", "CS2": "0400d928615e36796f5d5059c4ea0647be95251526f14e49316ee62652825ec5d016005ab2c977f99b09497867f6dbd1664e53c389422428dcecbf351d48ed198a", "HASH_MPIN_ID_HEX": "61921da344d9c5a481be2f8cf1a8a2efa8f44b820d27cdfa34aa4f9b1d9bc2db", "TIME_PERMIT": "040b2f926f3c4ede026ca6d3bcfce3bc0618f0c79917db689790b667ac7047a9602314a2d4850c9b2bfa000f1cd8f5a98a81c5f0a0510ae66dfbd81b6efbffae08", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20226232643337343934653863633835663337663230366434346130363939366361406365727469766f782e636f6d222c202273616c74223a20226339666538656137306531383332396664306135396436313837656639306435227d", "TOKEN": "040f968aa98921abdad33eea6adb2c957d5e356190f0e01a4a9647a1f1a8e141d515ace5a5e1d4a338e43ab1ba03440d7275acb5744b8110b14b400dd4a67accbc", "U": "0403c9a342b783bbe8843ca2ccbc6a1ae99fbfbdd28e1b169cc3b4839b8dd1ae5404e85aaa15310de903f3ce7406a15125bfa0e309998f5d06e328fcd879c74094", "SERVER_OUTPUT": 0, "Y": "18c04b4565530e2199bfb14afddd8a4c774139095b37ed00f5eb3e624d4d2a07", "X": "1e464a65b1aca6ca21e012156a5ef2fbcfd3c00bc6624a3ed353598eb80f14c1", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"b2d37494e8cc85f37f206d44a06996ca@certivox.com\", \"salt\": \"c9fe8ea70e18329fd0a59d6187ef90d5\"}", "test_no": 88, "UT": "041d1049abd1b7d1a98cbc969e2a258aa8758732091074eea3363b10f9280ba5d9041c9282292f7925460b2d23f44782a97439379bbaa231a124a4b946ad9aff64", "MS2": "16817f03b7a53160d0d1d16cf396c7d5bccf4fe7665d63488dc13fdf2b9a81b0", "MS1": "0a35d7e3b92e77859743cf660a7a87ce018a9bebf14676aaf275ecce3e37a804", "CLIENT_SECRET": "0405a61b54202a5c85486e5fcbeebd113784779fd3bf591d66627052d844d9c6871675c659135db7d81c38f0ddabb0837162e48783c32147b97a1732a3bfc7d06e"}, {"TimeValue": 1437055596, "SS1": "0bdf1f88a14de07132a7d582cb4f3d518e7917da46a084e6e5d035bdbab933b8157ab40129fd7ac6b34b6242c8bdfc5a7fae8d31793eb50316f0c2ffd3c23ff922dc6333bd54bf441603c3ddbcdb7a68d68c44b109df446ec0262fba117108e40b34b796f736e094539d59165a50b73cf6e72246b8a6d1079b3098ae88c2c71e", "SS2": "1b063121582946256baec54409ef82d7b03a919d6c308d41e1d01646ec0617681caefa1640159ebb10c08c6b214d703d5ec456cf4dda46998e8790cb230dd57d215b47dee24962ad9c6a02fb2be27ca84eecacf91a8371eba3c07b68ec762fe10934167a47485f2bbe548f6c4d29a429471c475d29a321532c3cee8cbe828ff3", "DATE": 16632, "PIN2": 9773, "PIN1": 9773, "SERVER_SECRET": "14ef204b08f4d9cf1618d2c84b6114aed8065b35354ce837004849527159293e1bcccb4fe8f05062ad9095a845b853e28a338e4e207729d1a0ce55a8ff0f0f4a16158651f42b51fa73653c22f068054df49b8463c39ad2587f58552c1139cc531128352fe118b270a07e5e944d152ac91a06e22c4fb1760de5262bb004714f24", "SEC": "0400e3c08e55a869cb30b29e2eb27e4e29dec5c6ce41913cfe3ce65b857d3c39e11b033a99cd8d034336ea71067c530a9a49e76dc33c07a7bf3df93df21d572a7f", "TP2": "0420dc73d91a639eba64acb2eeda8749753a0e81934f7ed603a4c136302416b8d009f12feb7e33d433e2dac50e9fa63ea042041bdf618f83079d89aa138efe056c", "TP1": "0411dc7d38acedbc0f2decfa7df0ab66e37dfb76b3e30b695d3e2c9f981cc788fe1c40759ce29be2b7d0627d1f35180c42df0b18a7feb9ea45d74380e5ab3dc35b", "CS1": "0412dee57601a75f1355e4fd9d0e76775e61f200ae3cfd1c72b2a2c27fd8627a3d121ae5a42c822762503b55b342d1e035886ca35348e59a740a13c3d7391f12fa", "CS2": "04124eae3d95195d90ba961729a5cbb33bc525edc65fba4602fdcfe0a169e9509914a4b23be8bb1b1af743c61a42f18310f68504f9774dd4675a4849858607b025", "HASH_MPIN_ID_HEX": "22f77d051b530d14b603483eb2b0cd1c309fa9148bce58a4a28914c347832ec9", "TIME_PERMIT": "040f1bf904e8f3587fa7d922f7b427cb64c6f7ba9ec46e9a049a07522d5ed6dc7c19861791629355871a85b08bf36bbb012f1812ac48a131d117203cfe3fe97a73", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223032633433336330363836306165303262353330663263303236643661383266406365727469766f782e636f6d222c202273616c74223a20223633613536323831636630386166623139383238356131306535623736656137227d", "TOKEN": "0421404e579662dd46ccb0742fda4cc225bfc884a6db91fe67576ec167f40579841cce296aa697bbfa7736d7f838d87a9fe2532c9fe043e5ecd047246a6f14b63a", "U": "04003d5bf162e451ca5e4b2695214f0297439f94d1a69796556d59766c56de076d1b9d1ce0bb0154342fb4bab770236bdd8d2689e2c39044736ed60b5a5a49a4ef", "SERVER_OUTPUT": 0, "Y": "09264ed22adae1dcdc83bb65b67dda4621c7aba53707dd1e73c6454d94354b63", "X": "08d32a555208be390f96e7d34e660313efd66b1c81a0410f38c0305d2cbeac4b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"02c433c06860ae02b530f2c026d6a82f@certivox.com\", \"salt\": \"63a56281cf08afb198285a10e5b76ea7\"}", "test_no": 89, "UT": "0410cce976eaaa5ba36d91046b5381feeee0f53d98bb0cf24793e4c12f86c3ba4a23c5855f7f8b78c9c97c884d38c6f04f4e14c97813344d3774fefda4621fe28a", "MS2": "0d1c1163483528ad00e8feb30b6c033a2a7ff0ee2ef72201277bd636617c8732", "MS1": "1900a8d5d0f2447c33cd83653d0f1a734a0d99d96547f6965646959d5a31cfbc", "CLIENT_SECRET": "0412c1e66db20b4be510a7a86d236f926bf6fd58d8174ebfe930b40f209c9bc7a02010d30fa2a09fbb5cb7e8158fe8e0d1701d4974c6d1001fcaadba83e503482c"}, {"TimeValue": 1437055596, "SS1": "21be87bb72bc8fe66384537f85b635979030b35bd21eacf0bc123452014706c107ecd53d30dcab031a0efa6e387c8f85ca7d4fc39774366690f402b39d506c330bb1a649f27f57d773078996a6b76f396d5636b19fb64ab75e23be80efa4bd1c08db50da7550d0ed8351be08e252e961c8439c2430d685f03106140670f2f760", "SS2": "091eb45cda41dece55800ca1b6df9ec44bbf697fa7cf36e9ca84eb18cb2f0c98089262d2d6a2a2af27b848ed78887d4895909e9d94e2e43a6d2ceec61b45dcff0445dda567e1df244c5f89fc4f7bbe4c5dc1346d181e46d1a2d37984322cf5b2109f122cc5ccfc1c892989ab295d2dfd3367745853c4205d5a3fc14e939bcfc7", "DATE": 16632, "PIN2": 2864, "PIN1": 2864, "SERVER_SECRET": "2008580c231ebdaca4cda148e3b1fc24c8f920820af41cdc17ebc35ddb0605910dc89303cdab25cdf0296f64d3385c5ce21bf83bbfe04600ed682d714f26f3921c42c4f5abc587e7935606538e983097b1a446af3b3055d24bd7e1660a76bfaf050e34c8b425964ef4f2c2e717a2ae6f07bd704f9f0268fea3d5a7cbd7a406e5", "SEC": "0418b0d0560ef4eb5964fe40d4fe092c969ff418f46607cb6dfd569a45e095b9fd043fa4f56719763a6beb5b3801baafa7f7e124f9c4a1bd32e7a1cb821fc07554", "TP2": "041a79bb1aa3acca0d623c265f71cb633c55a4b0ea0c9a3db238be65830dd87b830d757eaa00da2ff97496b755ffbb6eee806ad055138c3c93f8c09865cb18e299", "TP1": "0416da32a3963e8000a0d54fb2190c29a01a8e87e54c8b9504a9b35b4e8bf6ed15221ae04582ec484caf00cadafd8fa20a578ae0ccf2215784c46a6bd942258424", "CS1": "040ad3e4d548d7ce5c4e79828e91168478ca1a4ff09980be079bd305191ac315c71f22444618b3cefc994e08094e13409e95da4de087aa7fb639729fcd10338884", "CS2": "0411df83d95c894688cff1cf1fa562860592e6ed3fd8b1a4fe62757831c3d325202090077de87102fb6928d3b8e1381ea9feeaf985469f8562d3c2b234230453bd", "HASH_MPIN_ID_HEX": "efb105f920f916ffffe4c79aee60cf535ab171888a8a7d3fcfab25c7ab68cc74", "TIME_PERMIT": "0408e33e6a5405e3c05b66e9d08e629aa9689142a06b62c07c95cdd93558e8d6390513816b6ed2021f1d5d386ad4c1ff3a2daa25fbba35a31bf0ff8b400a52983d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223731326333376531353030393766303434653062636233393361383539653331406365727469766f782e636f6d222c202273616c74223a20223965336663333131653330343662646137376665313466666438346565376138227d", "TOKEN": "04138a4fc973ac44c254a19e1dff73309f79fb7533bbd90fb3e9aa1e6656825e6512e175a6a5fe336910803fdbf99c287cef440589062e4c735e990decfbd0ee0e", "U": "040d9d53f8ce584cfa9eaa8c30eb50b7458a57c4ecb53999011becab33a9421dd9032724d008b5274d5a3ad70c5b8fee32f89681b84c642cc636bf6de4a349b8b7", "SERVER_OUTPUT": 0, "Y": "03178f4a995d4f425274504e9f1987c28b41d4e4ca5556276eb732990ce56931", "X": "18be8b89731830fbde61e811db30bab996075eb264dea2383c53896b96f0d2c5", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"712c37e150097f044e0bcb393a859e31@certivox.com\", \"salt\": \"9e3fc311e3046bda77fe14ffd84ee7a8\"}", "test_no": 90, "UT": "040539c236e034908c0dd2cfa0738abd68f6a092c30171c7e8c37f0bbff603601c16fd7f09d2ffa50a1f7802500189537993b9cb4cb2988a56d75a5f990724f1ec", "MS2": "169dc4e502846e14c31e1af7e417f4fb2ad3326031678e8859dbfda864b182c5", "MS1": "11d9316f23270c4d850cc18d666b484245b2e505fa5e90853e7a649d3a6754e0", "CLIENT_SECRET": "0412f98e1f41fb8cc27e43eca679c2a90a7624acb14a6c5011183cb9d4b2db92bd1db9775d7b6559625a8a564c85f570ee54a73e68093e146db2735957f0d7b687"}, {"TimeValue": 1437055596, "SS1": "0e331ca81fc9fc682c5857bb8a3ce7166b8a06ce612cf609bc63dd0fafce9cc4094b6e80b356ec90cb523fb45783c3a41f5c1338a4545723cac1240c7b3160770a2c8cb851ac7f2b42c2bb7bcd83ad452a71c261699bae57db3318d0efdc91cb02d50f3b08dcc3075162044cad033d1745629c73ac48e9dc7cc431c89e15b4f5", "SS2": "010521f2dd837cda4292785f348f2c50e9d17520b58b9de4f45d5b2aaa69760d19107d3f4c8a67acd65be6ceab5012bdcd5a8d3ef75ad02480c178553994b06d0e2cab081300e0d59b76b14689fa1382bb94ad83e9f5f4f75bde3b0111aba49d0c11a6005f4a87448c1f5e620a09d84c6da9f28b1bf2375ed1e54674f2954818", "DATE": 16632, "PIN2": 4988, "PIN1": 4988, "SERVER_SECRET": "0c475a6492090efbe317ac0e44484c335f43d201be4008f4da57076950cd5bec0b34cb9f1cc47dc8914fbcb1a4c30844a03d06f2471ec3caa911c9cc0011b3321358f73b6c3155223831901d9c95a58e881b3d58fc84936ecbbb41c404ca316e15a261aa1fb3d605f6e54b96f996688f52162b49e31ba89141f8e4162d9133d7", "SEC": "042132d3c9ac6ef79f535041d1f76cd14478531ac319903c55e2d6afd718d15daf055946aafb888e791aacb75de318479865f0a9d0b8734477de62b26f42a70914", "TP2": "04029f0e7b3d4c40c71ec90b78d436b3830b1d41820f60906017e0c03fa9770dea0b7940f6640513f5724475f7ead72c8c92f3387b44768e5d418c699746f05632", "TP1": "0419be869003bf44de02e146edeafeb399a2af8a52820a5e57ab8a308cf154091e18d9e5c95bbfb7e35951c6845b323a7d5c7afcd021e31e06c26e914ce6fa233a", "CS1": "0416a213d567c9b5a3738f675f692ae268a6d3a15de1eacc835fee40ba35c58df90971978cc0873c09ca2306fdb21545e9d213214b8d03f791cfa0b0cf4fcac2d7", "CS2": "04221bd48e779ae5671bb438e4428d7ed03e11429d08f9cee4172d6aae09fd545909dc451c935bd43dbb1d625c03b912e1fc4026c0b4e7061f688a14dd610428ee", "HASH_MPIN_ID_HEX": "7ae193782e92fb3021070597e146640b0e4f8bf0790089cfedec1ecfc39bd2e9", "TIME_PERMIT": "040e128bab689c918cf41fc8a263bbeafa4574d6b478d9771843210d3c40c1405e0807d14079a51538d3e76987946fac9ba9cc9fa33242bce0d8bb7261a9dcbfc9", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20226463383530633636306664343165636562316530323833383161633430336439406365727469766f782e636f6d222c202273616c74223a20223431643632383032323334666238353637346566616331316463373262303765227d", "TOKEN": "0406ed584ea0610226fecc6e7d270525b1c0a128558c5bf4d640c19615ce0254a508d71b2bfe1e1f2d13f22c714e43a7b400017140b33c35130b2ddbe5d5ce436b", "U": "041854c8a1fc1e0a87d992fa85f77cad0c999ba84cce6bd39ad9b40742e030df2715e98a8e64ba69f0e8c1ee26e594b9cba0985cfaec706d03e381d8dc7728e848", "SERVER_OUTPUT": 0, "Y": "10ffb3d007921d3e96d3723e104074a527acc40c5760679488f88a7c2cc286b3", "X": "18bf87e1767e4dcc2818470e72daa2053647ee38a019490f26d1bddb12c10cc7", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"dc850c660fd41eceb1e028381ac403d9@certivox.com\", \"salt\": \"41d62802234fb85674efac11dc72b07e\"}", "test_no": 91, "UT": "040aff841e365744625ba64549dd26181a685706add98d3f639aa9ad731d73bdd7178787b8b8a0fcde4d8ab5227bf5e3735680bb70713f1113acebd29dfb52c8a1", "MS2": "07f25f38f79379041b0dc3e87b0f29a6e8fd9544c4360ab78970b904315c5352", "MS1": "0aa0b003569cc2699585877083a3c38711ad1a1cd9dedb4a841904d097381974", "CLIENT_SECRET": "041de1eb3b5cb2035bafb561788898b62e3d473b0e9bf3ea748abbbbce9b55e326182640ac8510443d9651b5a0aa36bd7cdf084d3aceba8b7bf7d6a45e8213c33c"}, {"TimeValue": 1437055596, "SS1": "07775195ff82445fa5fde6b31c45e74b8fea11568ee8a92dea9eafdc959e379c02fcd05f39000b085ebc34ef8ebc58b68916fd2adb1e5dc4fa0b9ceae9ddf52a025ab9a1fddcac5a7d58fef4fe83d2baf12c8f9253f197728fe71e373e64c49e22ea0cd45eddbbfbaf8ebf8f18d46b340d5aebf99d02fffb45ad1848b6fafc17", "SS2": "1c9c1fec3f19dd3f38db6eb6e201c48d9163391cf1a5936a79f149161940d19c06ecaf8a8cbcb9b64b2af065ed13c50c518de60625051ae25897a798a22ab9780aa970e0dbad979d265f0e67c1fd67cf5e8974a2242b4105f492c1dfadcebbc40db810bdadac196b4be44b78d0239babe9dfeefaa4dea67b24c1017e2fe7423e", "DATE": 16632, "PIN2": 1258, "PIN1": 1258, "SERVER_SECRET": "0a36b789fda4753071ed42e5cad23a22f268072961cd4fa0ada92b97abe4184e02035340d5b62c97e5d479bdd2ccc6af5d3f4a634de89bc94fbf891b9fc0cf2b1e88395ad17b2b49b3cc35fa73bce3691673fa70a6138c0000c0fbda2c71105d1e5182cf045e532344feea683bf72daee526d8b1e480930bcc2414eb5923a439", "SEC": "0410ded5ca637761642be821813cc32c5d7acb3c763ae1d7e802e9938f0dc0495a1236198f91ac1c8472f1a50c0c9632b215db7505030f86caf3c8cb1490351949", "TP2": "0419afd41bb9bc978c71127d8c2a1d9a40c68b8977eb1aa89857fb47c30e7d9e6e066d1578fde875153a3e45ef03283074cd8c9b77af10d0491d3e5b0741dfd7e4", "TP1": "040b23388d49eae5c474d962f7d4a260fbe832780455d923f23fc3945bc619f44804c930679366484b564aef5c697c7bd7a578aded88eb5d3a4115f6c42b299049", "CS1": "0410114f319fb4b0dfc1f19d2587454e8a6d4220f7b8f7f013f8e5eda175b3aee522a48585af3d1e4e0d6b1b3663e048e68e3a8eb1a40542eaefe7c6c761e6a0af", "CS2": "040935ea7d9621f5d3d133923e761dd3b281c5bd02a40b2ac2dee61c622041e7a41eb2073b89738a085207ed178f0d21ad5b4c95146b7dae8c21a640c0eb1d393a", "HASH_MPIN_ID_HEX": "eb44ee7deb087c407e0959e98253a5934905e3bcc02f57676e04e0a3c26be95f", "TIME_PERMIT": "040aec918f2179aca4b0faa6510bd8e386684fee5489c210b92dc2395507f48ed907604b60d31f13bd282b93bca7363e41267cbe3029887bda055b51be6a3734c2", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223630386565306566353035313336353565303333396331343835323034663135406365727469766f782e636f6d222c202273616c74223a20223938666637613938393436323637383531333335343063393933333632393965227d", "TOKEN": "0418e55c0e822803dab01721ff14f8671b599a07328747f98441284b46ee68ef860165a91b6c9e30869178e4ee7399e1306d4283303df4d80cf75de21a6ebc78c6", "U": "04233305a50efe38b233c161184d75ff5aba85ac14300793b4b79abc621e06a5aa1f9fe1cd39590788c9a85d9eb97d131c8599211f7cf96a555fc3f56469402a8d", "SERVER_OUTPUT": 0, "Y": "119406d3f9b6f71ae5b3b4045b0b8b185f0d286219a554dc96205c83445d8997", "X": "03fe6d7c5ecfca58dfe42d14d5a8968fbcbe70aee9b05dc99cdb7f1e6bff7d0c", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"608ee0ef50513655e0339c1485204f15@certivox.com\", \"salt\": \"98ff7a9894626785133540c99336299e\"}", "test_no": 92, "UT": "041b337e777cce6792af25a8e1fc67f84c097983ec91f251d81e1b412b21ab35c414bb41a83b7e2a71410e0c8141932585e9192920e1dbe703a728cfaba1db1f49", "MS2": "11cd74cb60254fbb470085d03bb23921cfc0e950178bf9a046c70c881c4cb122", "MS1": "0ed5414e75ee06decac9bcb7c6866c4377e06305b34dfb18187277ef4bbe0b42", "CLIENT_SECRET": "0410898dcf874c74f3a123335c1100ad9622015db843802903ebbc44c461b92967159fc52b3f744164b35ef7e8d0a154e7a0391d6387c4545dc3cec08edd15b198"}, {"TimeValue": 1437055596, "SS1": "12e0a6e9f87d3c3ee5037363577cded5b955b7e38704cbf660c874b09b62921011a24a9292c8e12269a9df3c4a6d641d32116f43818bdf80a3763b7378ec8caa14e9ae2f943bea9f6ad6ffc639db39e538278cdbbc5b5f3fda905807bf5696e31e1cf2fca1fc5c54a7af8d890c3f848fa52634d33df5251a2e8342a9ca6cbcfb", "SS2": "10e63ecc9ae8a8c19f373507a43c8c2255bb9b9a2c269a3b5fb579b1e4822012077d4239d7f43c2104a0e96283c198800d0b1b08b9af768184ca62803976486c038ad10310fb9eaa4640f2fc96c2d53ae3f7d755fb6eb194f042b5e47695d5880e616cd32151f5ea28750b870f8228aafe9cb8d138e878ff3082c32255ac5619", "DATE": 16632, "PIN2": 7885, "PIN1": 7885, "SERVER_SECRET": "10f465853a25883f12cb96f491cba612119180424ec3163aa019bc3de39272bf05f19200f8434d39db174e8aeb67d2aa54800b628b9fdaad5c476dec58e5542f062ded6aab7081d17592b92f1ff33898f58edac3902ac5460dcbb192f4fd77c10e400849061d970b4937ac1053a65dd9432ce89ee263a8023520b385d6ba705b", "SEC": "0413bcb2e0a445b9ad55d2e35388c6a3dee490bb3aaa61825d290191e4beabd4bb0c460c2943c79beb1eb35ce99098479698c8ef366f124e2dbfa3352b957cea3f", "TP2": "040cc81d0f04ca07d8855119d6449a174724626a565ac61f719e0815b35005509d1d34e32257bd69e8f02ba348f4382faca2200c7c1ec70f95aed26993991d02e6", "TP1": "041bc25892ae2fc145e9e30e066887b60439189ab54c868d822c75439a4692aea222478137fb66a65ffa28dcf97955a99635f8543d1ee6923b3e48afd53d50db42", "CS1": "0406164d085def04524dd8666fe8893fb42a8681fa2e1ebfad172972c2e26d455321dfb4a2e4f45992bebfccd9de3e1d41898331c93fb546941d963d468e1f9115", "CS2": "0418eea5102a09912a8910a5189d7721d7047dd4d016fa7340a7e262b3ccea35fa0050cef2665f78aa3f1d9b5d8975e3d5aaf250c65960af60c1a03ce0186109d9", "HASH_MPIN_ID_HEX": "30cdddf6beeb7f4d669cbe5d8424be67a58baf9ec74bb7bec49a575c8bbd96ba", "TIME_PERMIT": "040d24bdc37ca89e81e807a7fb66501902228422812d5bd47fdf28210765baf8cb0806be78bfbcfd6515f0e23275377673d3c630c97aade0f3fe023df9f0c6a366", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223663386165633362346334393935353238343334396535343339383230383538406365727469766f782e636f6d222c202273616c74223a20223362356266613932366133656563643564646566646664393432326230303535227d", "TOKEN": "041a061127ae2d3a78f1f390ce4f1b4d36c92d78e0be73a193d3faf86bb61e1f3b01e1c8275a0934d3b522dab699ac376baa9e6125697cdd8d2167ac561c2f8d8a", "U": "040e8ea8a3f92741f34e354e3dba119549f24f22eed9b760833dbb174cfbb2f1b0141a7d91f2095f48a65d3c17dba6f17b42f1a30e996d32cfb8fde5f712340a57", "SERVER_OUTPUT": 0, "Y": "03f73d0ede5cbafef072258fd2c8f71df4b3dbe7948fc14bc33a210dc7683eb5", "X": "09feee9778734f65a5da8b9c2882a7228325820c36573e5f56ca87580be31069", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"6c8aec3b4c49955284349e5439820858@certivox.com\", \"salt\": \"3b5bfa926a3eecd5ddefdfd9422b0055\"}", "test_no": 93, "UT": "040e4c1d8e9abe5e7480ec36cbe894bdfcc5b9b925670278678b3ccebe50747a3007ca2c46f819fbe17efe8e8884528392675e14058896f4a22c136c14af1f24ff", "MS2": "0f9e2249dfb746238a929414451ca99726fe49e0ec5b09ae249d97e793d8c892", "MS1": "05b713d68901f2df89c997da46c6744a665a98ac93abe82f3e3a702b2ffee7bd", "CLIENT_SECRET": "041c902252c7a4c3f286faec720c20195a2146ce86e8cbeefac2e0ff8e6d498f011579845365bf334185977bb3a96b132fba437c30ad0d60d2ba5ea9bf9f79b307"}, {"TimeValue": 1437055596, "SS1": "0fbcc4da6bf439d5f95c139e8e07cd107ba12d4413ca2b8e0a2eba2dd4fe4eb71e87d561b8e35cfd6a729b6a900241a80396a66072271c4fcd546d1f670586a60b0bb50129f7030ba54fc6a336edf8913546d21edd9a48a34d5ae975f7a9ae620a31fd37fb761fd81c308e74be8dc92aba7fc9fdc1c92b6431e8c985f4754450", "SS2": "04d78e2e2a0b356d0775ecc8031ee976fcfbbf78d3a03ef8416067dabe10ff0d22ce90ae30e391c7e74713d6e649f8893075033e27a9a7280d4d1f35c5c0d35d0c0e603cab52cdb37f1647b11ad194a42292d0fa69622693bc6a14056cba18e0152b332d545542befaf27ec63216b3bb56dae563798ef5ace7397249f4f29129", "DATE": 16632, "PIN2": 1845, "PIN1": 1845, "SERVER_SECRET": "1a4f93e8bbff8e61b8d28f6a63351e251d59472d5cec550609e7a835bf88c66416933c1ae7cfd1f50963d2efeae36254aa6e1884a29c215defe03f970d04b77610a6e03c4ca0c84f8a338a445808598628f84803119ecf708b68e099b987908503be3f90d5b9f9f58a52c2ed2e013331c86c0bd32dc6b596d75f0a41dc10b296", "SEC": "0400e65de3e5f97623406d6cc6baccb16f1c042f9d8f5c1d0ea20d65bf5b89e23d1f1886b27f58fd5d9262b673d3b2f4fd1618e7832c3a9139c7034562044241bb", "TP2": "040df909947a47f6175b89a79aeedd7071021ce6b2512d0c9f3192d40f1260084f11bfde30aa2a12896614647de3846b9c065203a63549db004514aab87ca6ae5b", "TP1": "04218a9595f78a712af38ff477f6831cf258c14208f6ca91434648c3989793b00f217f3288dbbd9b2aa1e742f8f4a69e476fd7ec437741b0cafc5848a96c3dffb6", "CS1": "040e0c5c36402524f7a3e07d3f0e0fec09d7fee7aaa6fec76f710b44e8dd1ac9c11626557e072d7ea338eb8a744983c043bb670aafadf6c278d0d02fb81a8da4f8", "CS2": "041b3f6ad496a22c17c6288f0362450da27aa3a68c59bdce635290044772f765cb03ed0e04b218188d64b5ee4aa88b8ea31216d7bf978eb4362f615ced48079bf0", "HASH_MPIN_ID_HEX": "91647bf89230fdce7f550ef5efba5bec39e78c2e292a22e7c705f5e378d3201d", "TIME_PERMIT": "0420eb4dc6847cd410edd3398681b51477d2abaeb972f0bc4ae95c9e3e7c73b30f191bddef0904be3404baa3b4e5c7b514d7a3520fc70c3894255daf89f7bb669e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223665343432633761326364393130326661653765303139366537653065653133406365727469766f782e636f6d222c202273616c74223a20223531306361316631643030376638396263323766326139346236393565386331227d", "TOKEN": "040056183a6b018940b523c084805bc92ca9d2535d22cf604aee16663bbb23927617fb211614b15ae7773d448a389ce382ac219bb61fbb6866e3b4d835727a83a0", "U": "040fe740829d0f13a3a2abe25e96608be559981b23b4d52222c4b99d019b8b532a223d9f681c3ab49237d737de0e9580d85746c0dd9701a3e6aad71ee80213572b", "SERVER_OUTPUT": 0, "Y": "0dce23519e0326996979509873c6edc1b81f6937d18d4909989a7f3e3bb9e151", "X": "0bd93d99d758d171d2ff8534a8fb6832a43adbbac491850a8fcfae2acd1f1b16", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"6e442c7a2cd9102fae7e0196e7e0ee13@certivox.com\", \"salt\": \"510ca1f1d007f89bc27f2a94b695e8c1\"}", "test_no": 94, "UT": "040b07be6f0028feff7b29eed0a397b6bd8798279443146d58d54e1f87a955477a1aabf2e34631a62799c306b4a5335ebbfdb83e3b1f97983559b3ac44e21ce77c", "MS2": "00c7e7a33fb03964dbb5141aeff6c5f1131a1da1a93456b4403a7752cd8cd14c", "MS1": "05990b9d894fdcef972ba17763e3b8ba67b81d38454a82c25a53736f85132054", "CLIENT_SECRET": "0420753390fb186e00f66996e0f1b440b5ba8d1467e8a214b0185f9a73fae2692e0878a5aede8d88a79b90f6aee0486e8c1876e0c219ad6ef66a0dea4e17df9815"}, {"TimeValue": 1437055596, "SS1": "08f8d49ff457dc7cb3310343ad8bd2127790087cec61dff564514de872c22ce6209a6f9179778e57bde653d994ba30b1100fb6c11a535b01d0c1b3adbd0c0e7c0f712a3531ceeef0e956624494b2b0f6510f74620ecc487ac511061244d8ad251512c1ece8cad487dbafeb959d7facbf93091adeea6d5710fcae2b0723aa55c9", "SS2": "1c76cf7b5bdcf0979e45f35e9969589a5df1a28b39f15765b35549f02b0d252005706ba6c37e1d19e5fc1204d8ba6213a5bf9a990892f730954b083fefb0c817061b4c6e4d72513bca2a4f7efec0fed1cc5ec2119fb3919b32c01256827f1cdd028eea91ffc8685c9461fa091041e5786f1a954593a46ac5ca1e0995eac6327e", "DATE": 16632, "PIN2": 3446, "PIN1": 3446, "SERVER_SECRET": "05033508e4f57537c1991db0717f1dc6942e3d91c63d74155ed51d75a47283e31db2e21190e11c1e8b61a767764fc693b72efe15c5bbd01f3a1efa9bb901fd2113d0d8294d2041196a905d092dcc1310d955260fc041e27882a83c47ee0885b71b7b05354502a82d29c4d69136954aaabcacd39400665e91c5a61f351172eb59", "SEC": "04153181d3344953b2a68e1770aa9ddf6ed249fa6128364ed4417c2a49aa06ab0108cd7ef622ecf694ecc0a84f4d96703b673baf63e27926049c25ccdb578949fe", "TP2": "0405968bec2ba5b9d4f47769c21bc477d29e62b8c4d1a10a21c64a7ed40c536f76111ba0c1fb95e4ad898cd073f3a0898facee2243aadf875fb89564d65fa33f36", "TP1": "040f34f94e6fa6b50af6dba6fee69646ce39c3ed5cb88b7d15e6f86568434d0e9812a7d0e769e99e34ca8d2ebee52bd21dbeb4aec43e7d1bf9df2def9ef8b272ff", "CS1": "0402d7788fefabcead6ee422855681fa0c652fea39cbb3f38fafbc3c146fc251571918a2dfe2e6a1fad19daaac05aa29bc801910b5648f8b35412525954da103bc", "CS2": "040451ee3567f2f77aaf7c8130f9e33be023703d53aaec087511a8d287c1ad73330ebeb4b3dec5b56e7471ddcaa80de8472f3c550599d4b6263ea8f5b64b740d92", "HASH_MPIN_ID_HEX": "296836f8e07b586a75fd7e783f7eec082bb419f81fe31930b84081e6514634a1", "TIME_PERMIT": "040843b3b5bb297b3651fa0e4ada45f1ce29c62de1d0c2b7eaf0d9d23937101f290bf4fae870e271d083ce0094026a40030369d403f29074f95fad3ca3929ebea2", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223530653562663032323234663661373136333237373230663866633664363037406365727469766f782e636f6d222c202273616c74223a20223464663530366137636435303463383239306534363938666362346662653534227d", "TOKEN": "041fea2fa38d343d56a232dfd3139eddf515eec9a906e842bcfaaedf9dca549d3104b192438a5244450f8e22e71138ba4ccd231c63f7a0402ea3cf545b5255bbff", "U": "04109f98ec8b3fd842651429d09aea32f95b2a440cfc229f8495acfd37f731145903aa29da1a55d0546e30f2204ba8d03f08c04fb29201c8d6ffd2a8ef4651b053", "SERVER_OUTPUT": 0, "Y": "1f713517d66ffe0438d4f01dc07cd130277dd56e68ee0a3be0562f45cec8f8b4", "X": "0a1afab2ee3239a8d44d292d8eed33d62f1a595c0efcd33b7f1fd7fa0c6da620", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"50e5bf02224f6a716327720f8fc6d607@certivox.com\", \"salt\": \"4df506a7cd504c8290e4698fcb4fbe54\"}", "test_no": 95, "UT": "0411c32adb0c09ab89efa0909e4c655d3a561a028e04209dbb5b488eaec07c30110166711570e2ff3dc510ce7e2afce867b25774d5669ed59c799faa7a5bc59458", "MS2": "1b39721d2d49c2b9ecfd6975eb396bd0e390fde3dc13f7d7016b25627af42297", "MS1": "0ba4a0a3ca2c66817791016ba7c87a987c8da59d5167dd1dcf06d344546c3ba4", "CLIENT_SECRET": "041a4353f3aee8cee9135360858f1605232243f5957daf242a93427c139369677a1ed230c97636b22497b41fa5350e2fa4ceb8e3d60dcd5f2b2fdcf0bd2dec2535"}, {"TimeValue": 1437055596, "SS1": "2375704040c42c0fa19613c0e023f073e919c6c2566811a59e572c7fe193d3560dd70780fb30db1e965c26d06000ffea429da0fca4a9d194a3b101dec47b87a2008b0f87eb35e0f5ffa31288db5aed7fd7ebfbf69755b951f4bc44ba5ec3b98a000f62b291ce2fdb093d711316c7633362b1b4a719da64ebb9d29c97648ebfc4", "SS2": "0b6d3e005bfb7ad4d77c1886e5c5fc342fef3c42d99091f44b49b3636596374304439718bfac78e989535aaba7306b0230a08727c5b80241765edafa2e3d983213028058b4a136647a9cb0540a4a2686b9a211347d458dbaf790212a9314d80802ed46ec090d11adbe473ae8600a1d52150c66f019b77bfeb835234b42c24955", "DATE": 16632, "PIN2": 1269, "PIN1": 1269, "SERVER_SECRET": "1babb18ce759212361c9d65509c473149476b41c1cbd582a06113b2a759624300d4ff678085e5969ca5f3ea6ee3d0387bc3447f8e0c06e98b0f8788b314e17e90891d2f09ad626bb944d8a9430aee1c35e3d992a6d6680b4ca77a2e8fafe2aa60ef0e90996a174197a973512351d502640a77a5afc43161dedbb0f6380c0acbd", "SEC": "0420ab751b7b268897c6a2fb88331499862a42d43aac06cf888fa4e054eed7be410e9f684224f1e36ac7555e6552b64ff72be6fa1eb358cd8f8603551e14119abd", "TP2": "04205dfb0dab70abe40be2b08a82524e295c707e489c7d79100cc6ae1f0e02ac9d2126f3e984c10ba53f16ad87f58df9550bebfaa968da749dd8f2d79328a24154", "TP1": "0420815c7398499208e77ef5c4d1e5fb3c4f1b8a770fe9d98a3be85ded790d219f1fec187ad397d67f16e06d8e367a60d1b5870e7248c770e58db010a7ec8bafaf", "CS1": "041a0df94439aee880751dddb63a4f5e7dbe23f7e0ffdf6a497f527e829be935141b7e1a67c4fa454084a5e60eb85e17687fc339fd81a60d9e80e50b0e08e57877", "CS2": "0415181e3f47abad54ebf66a327f64b75705ee7fdca7599f02d7bcbcba5deff4aa22010bb29dd0dc5bf21f2402ab341a60ed3f2a14d1fe32d2fa57272dc7809d02", "HASH_MPIN_ID_HEX": "a132835a6c92889002d508d6005b4ddc755e65fa2ebf26835ce3887c8a81b69e", "TIME_PERMIT": "04078d251f51673e2efaea258f553b7f8295b0bfeb546b69e8d3d59b67fb4131411bbaeb4928754323207e6826e8ebaa76c490087e8abcba0e1ddbc9107817d2a2", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223533666664376262653465353663363166653730313764333266346666356465406365727469766f782e636f6d222c202273616c74223a20223263366231636265313637316438356462313437333430313366623466323530227d", "TOKEN": "041fc92813eb8a4c26be2c5be8029007bad4d762f91c1b4260db2973a56f96a3061e11aaf3be59f65b801427daebd077dd905bf730d2e8749e1bc3d7b7cebdb316", "U": "040b0d7055aeb57b25da0d459609bec14281c0752afaec904c80d0325b97e9a10014d0aa981a916a8eadb52c7165b16d771cc54716008dc6f45fe401138f3b4305", "SERVER_OUTPUT": 0, "Y": "054c6cdbf8e3a1bded4b0a1930ebf21657fcfa1069afdc2bc865b569d1d4907f", "X": "21a44c0333fd3ddaee812ef8fb6ae4529c19c58dcb4c7250fe73b55f384a219e", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"53ffd7bbe4e56c61fe7017d32f4ff5de@certivox.com\", \"salt\": \"2c6b1cbe1671d85db14734013fb4f250\"}", "test_no": 96, "UT": "040fdcedd1c8323e57682b8c1e119b33d22af8395e4bd637a43d831d8c640a82f419d8292c58731365b5153b691ac054bbcdfd3e8e3b4e8608aa3197d768126ad3", "MS2": "22390a2ff4a68024721827334b61464d48dd49d9ee98c0505ab5e227d9bdf458", "MS1": "0ded5d569cb573066bb399b8a5161e16a987d3694ab6695ba8eb7af0215b1272", "CLIENT_SECRET": "040c22308036c04c1a2b32919ba90465f2e4a7e9a84ff944746bd54251162e857c10f8106c064f87b76c95eac6cb59034a94a566bb6ae5a57c66a36ed0133b7b0b"}, {"TimeValue": 1437055596, "SS1": "0cf8c7032ffd61cb4669bea4e5d6299370c5350ae4d2b6ad91b1b0ad6bd1a10a15e241870377970fecf163f1ee994f44efc2e4f9f9c90f842a7f1320edaecf51206c45665d5ad2adcf5f070dbd9e7557e523cb2c75e7217de4882a697d27847f100476dc5ecb069e75d948b8e5ec2c4039b30fe431d5ca420759d9f1ea9f8756", "SS2": "1dda3fb581ff70aeaae6cce8d2a682c549f01344ba2d4d8842322c47846cbbaf05675b44fd58ebd19a698c45a0e449a6560362498b604266f7286b1687cae56e0b63f615a06a4c8f6a6a3b2aaad39358e55ec65a3f340f6c37c70f765efe5ba1072974b4e95809fdaf690c8edb626ac930b442a2b186fcbeb0795609ef4f66bd", "DATE": 16632, "PIN2": 8118, "PIN1": 8118, "SERVER_SECRET": "211f44dcab3d47125c2444601839b3941e93b4949321875a16956483544cfeb80b67c63957e4223c71a404f7ac3ca853bdf3706dabdb07f4497dd7dec70277040c0b58785c939918d646a6e2235736aeab1882c0f564788150652e7341e3b73d168c588cf68799214f9b1c583c5395b88a3f9219cd26aac064a2993afc9dc0cf", "SEC": "0417983991ec61b61d3ba6f5b0ec7645548c1b27334fea6fd4ce2e122fe7f13030220b13014dc6a752b1a6d7693a4ce5bf63af1016a182918c4a41c56ff86d6c07", "TP2": "0415eef6b1c841a11c5cffeea694ea8e13c4d2a636bbd61d5fd44dcbc4214b1ebe164474c974f416b35bc4e964e52252515db58e1a9d10bd7e256c378d649c9e02", "TP1": "0405d0d4c2a61c9789093a859c78d9e2bcdd4fabe25178bed483b0714513d67e0702a0b3611b4e6fd9dfe5e15407b3c7b054b31075fa8a72fc36eacc987b23ef33", "CS1": "0412d2af75aa20421cf4d95cb00a3e527bb684c38fbac4156897e6fe90090c1f860c9751eacbe7e8595ca555bbc23de5014b9669b28e45379055634e3ec016fb6e", "CS2": "0404c00a9edd002bc41c2f2b910419ecfd72297921ccf734d00cf777d73bedc1192267b72c46936a19163a7173f69cc514893997ace82aa029d9f771adb972e19e", "HASH_MPIN_ID_HEX": "58088d5c9c1ab8f4c4b692963eb37e66cdff4e585774673b66088c04820ff41e", "TIME_PERMIT": "041de835d1d026f0e82e6169254b7f655ff1aafad49042d702acda467462f129d311ef9af09bbf216edc12b775862b6c113409c7b3e684265bd6ecc57d720a8a4c", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20226431373131326236363938303461343737303135626132356434323832613332406365727469766f782e636f6d222c202273616c74223a20223432366132653764323039613361623061326664353834373063613830333062227d", "TOKEN": "04049dfcc4067b66699a448091ef15fc0b803e6ac2488d309a1f1a9627edac727d01925d9fd5c46d487f2d2fd468e006125eebf6873ab275d409395f04c81e2fb5", "U": "04086be4a061a04f6c1e232613f7c3758bf2780e7599b3c15508f403a32d3b95b80854b04d3f6f97f42814114c9e0b5a08447d6158f7c9d6217d2cd7d29137aac4", "SERVER_OUTPUT": 0, "Y": "07c40a48b0fd79a4280f6cfce9a9eb7982de8163d8b6c5cae276d93943dd51a0", "X": "20d9fb3dcda97095ea2353abc04ea1b63bf2947bb64848edaff70590770fe1a6", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"d17112b669804a477015ba25d4282a32@certivox.com\", \"salt\": \"426a2e7d209a3ab0a2fd58470ca8030b\"}", "test_no": 97, "UT": "0415c8a546c8ed072a455e9a793e37372c1c1c4636442eec29db2bde04fb032e14158a7ce8e1592109452e4072216ef2694499ebdf450de8886305969b3ca37819", "MS2": "0027c139902e81c45d98cc62feb1fae4de1857467885dd38cd1ccaa17c09a0ae", "MS1": "17e402e839a4f736b3760ec3ea8cadd7c9689fabc381da57ea20b2e4a33dc7ed", "CLIENT_SECRET": "0409df58e18a5b4f04e8388a82254f5b60cf00f21391df20e7a3ae1d3ad1f43caa02affbc281532b7233ec6817dc87cf4641e7f9a933923f81b49086971c20fde7"}, {"TimeValue": 1437055596, "SS1": "0b004f6da2a3a75c6a5da2d63a1233512e70391e7a54ca8cd08402e6b76a03fa0d35da14c9a6cd8fc9a259a2f70839248aee9b5b831b0e431a526eb29883f4fc03c5401011f2dd12c09b1726dec5a7386452a997c45d896e3f107c90b1689bcb1538a11cf9c1dd7c1c8fcddba62cae11d1afddf29374d0f903bb7673e0e6c910", "SS2": "084447cafda97dadd4b2217a58f944fd95d0024968345fec707d402814aaa7d2201c79f5ec34cf14ba224391a9d2efe9ca03735088cae1662f76fa5ff86c9eee1f6e66b8e7d11d66f50126728d2c350eeded968bb1561c9f85320c235c87da01116a269a3b80e6bf7ccf66e7c2c4da04a8d9d0e260d0d4ed9d1ad66d679ab04c", "DATE": 16632, "PIN2": 2706, "PIN1": 2706, "SERVER_SECRET": "0f4a9785a16627bd90f113bc71279417e2ec352634829f72c07e63e9e968606f23c2c5614795f97aab3851c9900f75887ad39fa3d5d9d12eb6f6f132a5e7f3e11c8d95344494cb58a431503fbf84e528ec117c924b8f1452dc89a8ef479e9dd4102249ca37e29c315fc0ef335cbe5c679da9b9c0e084f7a631e06896581b542c", "SEC": "0421f660638e521615bba5bcb7e4732451d045b2c0c879b44077c350c65887ce80105fba784a47ebe856dd08bc7591ba9921c03566a1972498ebdd6d53c91e3223", "TP2": "040c1b2aa9116178231b505c5bce386737a18c0c62e302662e90288ac1ebbe9c28181ed908f722c00b510d63e5dc52946a5e6f07cb40bc3a2471ccc8fe4ec61d58", "TP1": "040565bc8686b55279f2772380cbeb15b61bffd5b911b51c16aa840721861438440567ca011bd164509459fac958d5ea18c3dca0812e42d8402beb98893802336f", "CS1": "041ea79bc1a3edb9beca5325342e9e04b29c17c94591fe28a557e691266ec1060f23f4b177704a6904f5d97c21c7c5f7a2c565462a579c811483cd9aa243bc9182", "CS2": "0423b5dc4832368a3ccf9b560b9128977bf69a642ec613a623a639d0415be247560b9ba6ce26a0d6b7bc2a87490141d58c58e36328825d0e007bbe579c4b8d6604", "HASH_MPIN_ID_HEX": "b4964dc32f59dfb9c386321f7d580874565e0f4c6d729a1bffa3283f37c672e3", "TIME_PERMIT": "040489f6e839aed756d31d90d36458c732da325770a290f9c9519aaa2fe5d1d5b10652b23cd079252a93964c0f33958fa2c733cfbfebbea4f3d2c0bfe5dd97ffd6", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223336303433323262656135393533373934356133333463373638313538333064406365727469766f782e636f6d222c202273616c74223a20223632346266646561343362326466323236626538356537366330333739646136227d", "TOKEN": "0417ec1dbe46dbd90c62a53e68913e915166758daea7366a8cd3a835f19dfd479e048df368d023446c6e4bbf3c0baab74a54e80e104968e10bd82f95e28b0633e4", "U": "04009f96f0a83cdcfd17127abb5320e0c7e7cac92b0622fb8c38210871008a75b4085700a7886ef975fee4b5be8177b863a0fbacf550405478a5391c51e4bfb2a5", "SERVER_OUTPUT": 0, "Y": "1f5fc56ab270858cdc9b7d8e1546d6502d806c32044fc3249cd92642f5f4bf15", "X": "1223df883e5069c6851baf59cfe8d3bea1f67b506fa755970c29530b38a00d58", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"3604322bea59537945a334c76815830d@certivox.com\", \"salt\": \"624bfdea43b2df226be85e76c0379da6\"}", "test_no": 98, "UT": "041218de86b8c0aacc9b23b0cfb70efa40762573e48bcfd01b94ae9a23b6fb2b3d027b7a3dff3767fdf64df87aaaba037deda3c742ef1cb0b9c3cc98d2840ed662", "MS2": "0b6658cbe289a163159ac0883b32e0fcda1983199c92c433e1c15a7e20f8f02c", "MS1": "164522d646665c306996dd231c0868aad57fd07fdf28fd406a255846fc7e500c", "CLIENT_SECRET": "04089dac53f8c2e9a424c8bbab1cdcd7fac084bb49189e9e0dc1eaa5fb60cbb85a0411d2bdc00683ccc71029bbfdf14f1879e621aa8a0c94cc9a2680b2a8a0db15"}, {"TimeValue": 1437055596, "SS1": "232ca589c5917561a3c7b8c45c8093aa9f54eedeaf99a44651638bc736b714b316325ae8d4f1ab84269db55447ee90969c8026b485cd6365e1a5ff7edd475b00130aaa7018a73308283c394b6ee4e543576b93905315570b87732f00c159720213511643fafc781973c6e768b857ceb352e436aeda65d9fb8d95abb67d55801a", "SS2": "11789018ca0cea35d72f0549d2e23a5c5267e56f50f29ec418fbc0ec450fcd7f0ef874998f5ecf40ddc36feadfae6c4ad179f62a80098e91fcc07731f2185f580175fe0ac1aa99a50e7ded5417c2bdb94eab7c0493e24d0c0985184c26c97c3e028740ecc8a8dd788bcff3f82c8fe2e97d75810981d1fb5a5f43b21a5a980dc8", "DATE": 16632, "PIN2": 4632, "PIN1": 4632, "SERVER_SECRET": "1f5fd0ff194945dfe731045552513b2abb669a41f0d2cf02da22d3d0091ffcc72051dd35df3b8dc9e5c92e4b204ffd4c9bb3b0c612bc34f4b4ecc3019882cd8d1798e305ac911898f79ef2ccbe7c4e46ec25e8312e6741c6c0de3a10df30bb451d956cd1774ad9dc138e459ef39ed507ae333bfa2d085c85eff6426528d02257", "SEC": "041cad2b78c2b5e156c260b4bf4853e70077b738a252424c4dcb3f7cbd36e2047f0433daf3cf8e89cf9ab5ae03493a0d9898e857ed1831a43d19ace023b7b97a7b", "TP2": "041014e259e153c0d25ec2244bbf26e5caa1bc4990ebc2d99639f0d6fa7c4203c917b33850797a0d808b2a9d2709dc40e8cb235beea9e273bfd87bab2177bfb3f4", "TP1": "04222fbf092a36c9dfd4a9298a9ab4917c40c1fcb9d5600750a2c10618347592c3225062ccc12d09c3100f749f777d2492ee5182612a57bf6b48a66ce61b174bf7", "CS1": "042235a103c0683917a934d76bbe9621a46e68d09b819181f16ba77186cbaf76c9073e3cc9b8d2f02734afb15b731cb2c3cc55c4cb5ae7a2747a6b08045253bb5c", "CS2": "0406f17743cbf823c8e9afb825f2b5b583b9822ecf5711b9c05d15ee9b83a11e01040d17aa16101e8fb8464649e0182b4e097b154453974cd43c16f1e5c575946a", "HASH_MPIN_ID_HEX": "7940ee8598fde4b3298fdae68a68fd854b5a24e0229d64e094ed9088ff6b71ee", "TIME_PERMIT": "041f870e7310459a3e48abc651e20307401780c625dce0ab7cd1c6ec6eb07e0244100a0d539e5c6b39947db89cce8bb0edd37a143e16f7951ff7eaf97dad0334eb", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223934303863666366643761333231386438633436376331386365393432653832406365727469766f782e636f6d222c202273616c74223a20223037383965303961333963643966356238633563393466373839633839653935227d", "TOKEN": "040270d946f220f442131ebec67d56f4e3c1039feaa3752faf2f7fbf8ae8c9500e0d67138f439321fae1419616492148f2013477c8fd02b6f848f2ccd511e5a3a4", "U": "0418b3aa7069b548b21cc29345922c9c3f40a057f1df6f34b7338d21842ef0bee41f70ea5ffce2f52e36687e1fea11eaa77905282378e22342f91641300b599143", "SERVER_OUTPUT": 0, "Y": "1c0fb063648c878a0e470bfb32b002e3f964f58c1571847e94db69a5bb5666a4", "X": "07c34f1d1c9c4b012a0af12de0af3ebc543b6adfba672d854b8bc213a9ea905a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"9408cfcfd7a3218d8c467c18ce942e82@certivox.com\", \"salt\": \"0789e09a39cd9f5b8c5c94f789c89e95\"}", "test_no": 99, "UT": "040abbb093a0bcfdd575de98797284b95328c2b72ca4492393d1fb509cb423e20214c833a6e2567f374c8f94946d3c1ee10b5c139bada048f062a6b4911ef5658d", "MS2": "17ee8cc15b0dd1ac742c93a16ae2f8c4ae5306384f3814106bded7d3f2d2fa89", "MS1": "1d52c0d144b0ec072f2dc4518144c50c7a066bff88aeed17231378f234e8bf3c", "CLIENT_SECRET": "040b77e32b0b502d3469c7ab7f1bf9432830fc70a2dbee79d1daf1048f0b500cdf1c3d2b869ea0944ffb38ae58d7d3c324da1f09b3b183ec21be3b0adeb5647c7c"}, {"TimeValue": 1437055596, "SS1": "12e06a4620e48f0baef1547c0fabd27e434645135b890f5f33da67ae2d5a3d0507492ab8eb515b9091b094ec850c7a5160866ad94e45c5f9a25da5e91b025d8d1aba0fd74e73dbd01b04fa3b9b07ea6e75d653d89fa6f4875d5b37dafc5648590208260dc9ea2c2f7f10da2016430fcc177e2d22183976450c37e79581bab3b9", "SS2": "1c69654b6dac115954dbe80ed87008653a0127b3adfe320bf585fac2078460f820d54c622be2a03f086671f0a9c3069de679be7db8ac320fedd80a6c924cd0851d0e0819d0721b3c31d12ecfe316fa9ea012d02403b6a79c7381a108a6aca23f142c33455c011641d68b78a24f4b1049b41963be85b48cff76c9aac3668ad6fe", "DATE": 16632, "PIN2": 2863, "PIN1": 2864, "SERVER_SECRET": "07628bbf10df97f554fb254035966db75f45d2b4d897635eff60a80d29e2b46007063d5a2aaf337b43d520c982004ec9524034075e07e573e14536ea0625fac70ae6edb1659129177688d5ef97c7e729c404ac11bb2fa66715da62838d6b1ef207dbb1e1db7497fb156627184e5498d369823e3f17efc3cc864e1e5212332ec5", "SEC": "0404a8cbec5a645713cee832aeef9b67aebb6a0cec45f0b9ee56a916be996c24d7059ec2b8af58e50198d9834eab539b3d5eaa534dc91d394dd5ba6d45c9d95795", "TP2": "04144e53b7aa91706fea3e54b170b5ebb1432744eae237e648844d8e27f7cd6696013dc4f3adb44a0a79ea9f53a22822ddd59d73f4d2b937b695c7a17b90ec8c5b", "TP1": "04051afa407ff2cb9c10a54ec0903aecc87c685b05bee97a2bbd496d7eebb01dde0dea7657c157533a127117327ad2a6da56294410c4db7e209d214769681e3555", "CS1": "0412718d4a2108fa3cecb937ac8ef967bafb7d0776d10ce723d27480edad482ba40e067ca9e1f212740585cb4e8821adf2909a0ab15ff00b57ac00fc942d6be81d", "CS2": "04063af749c5e9c336671c9e40540704361dd1e454d783711d8bf76ec502c3de1403b1cd98e383dba92f5b7a413cadbdbe65d7d6bc79b1c4eb58a80705a669cec0", "HASH_MPIN_ID_HEX": "90d1b22f534377dce6772dcafaa1f2968616a91d1381bee21810c0a2fcc71c5a", "TIME_PERMIT": "041298d659e3a38cf4d81c9e1d4acbe64df6e50b91269558c5b465d6f7313417e41edd5e6890306ff6af8b92debaed252185b62ec7c1811c7f46b676bc274c0519", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223661373134666161653761333963333361323764326566633336643661313831406365727469766f782e636f6d222c202273616c74223a202263373761306236363333663038373564227d", "TOKEN": "040104704da99c46bc7111886832b75db894279111a94b1f2118595b6f3d7eb9b11536fc03dfbf23dfa36247148c3b39a53fd0ebfa61b2d9e64157b0daf2a723ea", "U": "04065adda797146615e03bfdc45838a07378a4a606d0041c5802b489f3d271819f1baa30b9bdd78ea97924a34a344cf57e4425eb04e6a22213a31ff791b2d8ec2c", "SERVER_OUTPUT": -19, "Y": "1e378776f4c465a30d593cde3afc3dac0b61e4c7fb791adbf9340613c8aa4696", "X": "025fd1c1a7147c7f087c012798f2a96727e19bde91d48bb3e8144f45ab75c7c9", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"6a714faae7a39c33a27d2efc36d6a181@certivox.com\", \"salt\": \"c77a0b6633f0875d\"}", "test_no": 100, "UT": "040fe23e93adfcfde9cc8e232be44e6e10ae0a3a6472c037c41ee9542ac370aa6a034429f671ac6b8064fe42391b77d2a2f68493a84ff93297ccbc65e96e4d0166", "MS2": "03b84665449b9ba46f8bd021de4a0d62937f026845d16ed89d1a93db30ef377c", "MS1": "167b3a5e6cf4cc967b613fb46988af9332da80b5c73737bad340886495f6c52c", "CLIENT_SECRET": "0404c95c1b2a01e3ac8a292daf375680c693a27adbd0c32eca1e39c4baab0c6caf1fd7f54217f564c4369d11cd6aa348d90f93a2b608d219d5c3552b36b67a3a84"}, {"TimeValue": 1437055596, "SS1": "2021f58d665e73beebaddacf5886e425f7507794dc1d78b2fdacdb37c187c9361284481e7154a4f16b10355ee2471c2b64dc4b23f6540370dc1714a9d98b838a04a8e8cb955857386a92d72eef907f388ef4a0737f74131e80863f74fd38a8b3018ccfe952ea1221fceb932a75411b37d6b8ea296d4eac5309fd13805836d382", "SS2": "00170282b27e391b8cbc505ffb895013d0e8bf33423a36c6e531d4748cac7cf40e7bf6b233074c97630fdabb5f230b6f98e7efa85bb9756d3a83c983b979f19c185b14e02a54adf1e974c1a6b4b6924c0c29f648e66a83be63d1958d8c4a5d6d1639c97ab8d57f53e22712a77e32eda4239a2db9e4991b2b33e7c1d81f39da94", "DATE": 16632, "PIN2": 6782, "PIN1": 6783, "SERVER_SECRET": "0b1c4edc44ca301d00f6e2efa1459722a10c53aefb914e6b5f81b37f8321f59606f8a7d7351fba67da419671558273410ae162fd1074bfd8c3a3c51e3e602faf087bcfdcddb529bdee9ccc47027600a4bcfabc7f34f2f6f23ef64f1b08cc769510d2dd41b6274e87a99d059d85381824415a1208cb7c5f1d75b61f575a2e213b", "SEC": "040566c74f74ab966cd154969a081398c994677c9397acd1e509021cf4ce50090911745450526c9be7581e929f798ea4d71b4be53cfa6e8619093462c889ae3582", "TP2": "041c24bb34d742ab6b1284498d106f13f5a9bba2ec6e9f0f9b11dcfeec1db3bd5d02a4e6ffb5cf9e3cd258b27cb4651c17d369b6fd0021d6de6965be863e879b6a", "TP1": "041283f583a4c314e437eb70a37fb0da8e4edb0f57a260ab4c945c056568c1cd52159ba2f4ecb877c18009df3cfb180ea4d1df2ae2d03619441b09d4e5c26aa545", "CS1": "041480507b811a2b85fe5d3658dc686393c874c8ac827e0c9cc3f53bf2198df18723c8876326e3fd1852efcce72a24d537614e23a234a3fbbd45544f0fef2b96ed", "CS2": "04121c8360fc39a49040e12abf78c50bdc5946d351088772b3ec7289849e0647341f373c9570b1cba9195ad8d6da011a40a70d3292c4d4e8ce542bfe4ba1e9ce2e", "HASH_MPIN_ID_HEX": "f021a566d9fba1d909823659e5e839d38da072a52c27746519647390d8ac87fc", "TIME_PERMIT": "04183044865c0ff7380a918cc1605ecf7adb6cb802679d87ff41e17f31efd12e7d0d9ab14a4b5ac6ee2439f0c184b43381ace1b7b619a2cb7091b0b369cb5fa350", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223765343239636333396136333833393562393434363266373265383630663131406365727469766f782e636f6d222c202273616c74223a202239613932306637636335623262396564227d", "TOKEN": "040d9cb2ca84c6abc14e52dace8d6e537ed44b474ef186d6e7074844e16b0046ad0970229e4e9d3615d9bb71eeb02b1faada16abbe555c1185799458f93343e69e", "U": "04188be260fbe9ec3a900aa14c83d4db61690d62c876c9bf7b8aebbd8706099edd183d383e0cf62de73279c3273a9c210836c7ac9c7d32e1f89765f1a0d344e10d", "SERVER_OUTPUT": -19, "Y": "00bba3fa3728400a934cb1eb6874bba5644242ab4006caead5e491ba30f6843e", "X": "1dc25f4a7f97badcea5c9a057d13f12780bef4229567e936fedee4b733adc48c", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"7e429cc39a638395b94462f72e860f11@certivox.com\", \"salt\": \"9a920f7cc5b2b9ed\"}", "test_no": 101, "UT": "041b15412bfdff52d2f50799eb826ae902fbd1a9a6df46f42bbb2664c1cb2507d91166047d064748c7729013cb3b620776c6fb23243447e67f8def96ae00134d3c", "MS2": "11f9c28f4c90347e523a71f5011213a5ea89c1c98be571bc248aa990dd63485d", "MS1": "22b60f7cac13dba6943b766b86fe52041cb3564914bb0224660bda52a0354a4b", "CLIENT_SECRET": "0421752491644b979916ce14db63717edd9987f13fefa52b6b424f5ff3327e3ec30eb4dac3ec68acc5ae8609036a2188f171df7b0e81a2ca9200bf2d26c5be3dc5"}, {"TimeValue": 1437055596, "SS1": "225670f9c55c6e55ba9e9358992f4397b96efdecd67c51b5b289c9b451804f8f1dd3795f39815924fa52c5ab1195e7e91508450df7a5bbb04de6c73f5b9e2b2902e03e4f5bb753c80897f0b32979bc2ad70efb38c22e70d92e876b634757acee03762c4817855b625fac6ce7dafe66475795b5f826ac6f6ec3ef3e0615a8e67e", "SS2": "1fb75b8ce91f648df2fe7c22eea8ab1d79c2ee930e177009e18a11a7c5666d991d6bd3504200f9e5585f3b64027f1208976d31380b98b063a532dab65c45f40711eb02f555080b32b043f5813972208121fc2d0dfd89e5d30ba9b022db49601c223bbc193c886b48cdd9a58b3fa5be54bd3d1e0e2d6b368eb61bf05171af45ef", "DATE": 16632, "PIN2": 6882, "PIN1": 6883, "SERVER_SECRET": "19d7894de44d412ecd700cf592a074988d0612df7e7dd05822943cb013d4394a060938059b0c40371c75687d5b4d7c080c77a1aba5f1464f5fb73bb140d2e299076315a0c19f6fb9221a323dc54c63cf94e98acfe38b531c056bd322a5f8ccea1297e3ef089697ba3f6c301070df0813f0138fcfaeeb1d5f65455403c2fab221", "SEC": "04147a79cbe1c02c7615996e74af8eebafc16caffe038896e056a399b77d9636a21825db1d5911de38dfde0605f24d1062f82bc4a0821129247d5a5afc8786e04b", "TP2": "041c40524901230ee740c7de191ea07622bd1136c9ecede84709d3e4b18cef9cab117946900bfb44f808ac6dbcb51e95daf600a5271fc6e435af4d03d501f6aa44", "TP1": "0418a35e5f91850657b642b73ea6e71bb3869f67ce3262d09cd3391aafddc5563b17bcb4be976388940e40bf5cd55f4337776b7da79143c87806392d2a87079863", "CS1": "0419812dc345f58cdf0e1c4d13a60005c49d09b2dd920badbead726083e29c6d410b1496114166e9e4d8360bdd7c08e36752eb368b1f93590130c169c92021a290", "CS2": "040895c37f84bc732711e3248ba1da9e54dcb98acab11e1ea2945adaefeb0fbf9d07e1e3cde7cce521ad5afdea9e893004afa15b96fad5d94ca6401316a059c17a", "HASH_MPIN_ID_HEX": "4ac1c07c92cb51535dbe06d8544a0296235136d3b953c1242b5a4000944d9ef2", "TIME_PERMIT": "04118bd0b76c96f73a001fb5b995a1513237fb533060a1b3a800d4741021f05767099298fe24625eb688047d46e292cf8b0138b71f97e2ec7c56205d411806a9d2", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223634373565663239353162373165343061626663653065373562393963373832406365727469766f782e636f6d222c202273616c74223a202265336663363763343039353265346263227d", "TOKEN": "040043a5074bc9faf84193b81462f2eaea7bb0541ace65ce3456a630c7ab2cc82900e46461c4f67769b7f834f3c3826976f0c73ef83980add8677933e1588365e8", "U": "04235594f10c694307eb89a61927d0cebe749d60a9a1f89ad51e37312e109f3ea31fc880a828da0a5fe3c210f4c3e2676f25921ba6d1876d16adfb680e6258df25", "SERVER_OUTPUT": -19, "Y": "0035da307ac15174c5b0e3999665dee8ace46e67fb91565e509c6c7f2ac2a99c", "X": "156a975f94e696d0fc8f09ce3fd17fda1fb60c6aa758046c1a316846508f1006", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"6475ef2951b71e40abfce0e75b99c782@certivox.com\", \"salt\": \"e3fc67c40952e4bc\"}", "test_no": 102, "UT": "041befea37fc0fd5ae12e979d4175ad0d07644881ccbe956a07c2548c23bafb7ac064c28d40892c29c50a17c286f72d2b8366c3f8cf04342365e2d476b8ffc1882", "MS2": "03d74d1c42d0b7777f7b38afde4d403b431d58c8e13f15ab17113f467e9b917f", "MS1": "0ec2d88a1c826fb572a5f35a99bb6e2012da29fb6eb848c6bbc023f164931b3a", "CLIENT_SECRET": "0407f5569ff61e37a0f10c0ee215979565ffe4a1b23c3413540e2c100057c652d4077ac6695fa9c813be8594602e42be407e48b309e5bc4876290fd7d678a17dba"}, {"TimeValue": 1437055596, "SS1": "04b184b38d20ccbd0d2a839d710abca720e3313a3bf44db57a3d74ff436c7db70c4e6bca4835a44156e9f9efbe2c3dd0f2e23a1e19bfedc6735907ada30867aa121b5f9466aa73a6ecacd9fc569a36e10fc603033971daa0668ca853ac48b3bc16cf92f40b475ab0af31a1410188a2da7269911314453e61e6b77c68e3555f45", "SS2": "1035a8d512011b9c683359b33588273bb07ceb6107894b99c50985b1dd69108a17b6d8d50f895684e1eaf566629692f60c9edb1d31d3f1e31a999553d0c803e601f04adcb6869717a5d2996cd0b791b7e06f9254c9961474709d9a258e89f43618b71a46277d481b90d15a31097da69d3f36f6df769aeec04e81181e59666546", "DATE": 16632, "PIN2": 6267, "PIN1": 6268, "SERVER_SECRET": "1c44d71e2722fcc54bf3c88bcea2185f8ebcf2c1f527e35972b0186e1707b99e0702d7e20c4b6e2d6a4184f1fd52bd6b2146e3935111e880573fdd017931f8330a9827bced09fcbecc2ea8b11bad4d17dc00874ee1f102c991d80013fb6c85eb0d0d30e0b023256e7dbee036b5150905d1a90b3ce11efbf4b2ed4586454ce8b6", "SEC": "0421e61c792e8ed953ee0f028a28da41c42bac199d374b30978722d7b19d13100a1d56e4a24cb6977ea2373ffb472743988c29c478d0465d65d51c291c82796785", "TP2": "041117f41cd1c69aef11e3cd96e6202bd593544e4ba240158af5860917d82c03d904321a4e813d5e9265310521f5274665714c50f123c1b9053543756bfdac0a43", "TP1": "04005ed388d94a691f8cd571ef924ba457b2b0db57c454abfd31b7fab1d2de3add03b89988e6f510a3663d8e1aee310cfb0e2aa531fa312fe2ce61f90f1c379fca", "CS1": "04234e11f172e346d02b26d2062da3cd74605e4fbc97223dbfe23fab3f70516421160056ac9fb66be03531c708c9b4d4c586b6ce7b5b5a5b678d7b9f160f46dc4f", "CS2": "0421f0812a828d0d2372516593a5eca85e0d3c21366a3dce515c0e119d44fb2007035659e27214a5e9a31bb2d3444dcf7722be9a8755439eeb2fae629f330a1e2b", "HASH_MPIN_ID_HEX": "f45457c22c9443b5d667e52fc19b002fe8d6edeb9004b78930427adf67cb4a5f", "TIME_PERMIT": "0403bff786d963d99405193445e1e42d3c172aa81890215700126e7fcc0c72961b1566af0ad67512db6dbb43bf8fcdc86d5373de1869000732c7b4ffac7584c986", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223966666531646430643935623837653734633036306137626435356261356666406365727469766f782e636f6d222c202273616c74223a202261616336663033653963313466643665227d", "TOKEN": "0403ee5e87fb674ead4d8b90f7b3824ed0dbebc55ec7359a4917f20f9dc092376e1947511f15f2dfc241c3a080c9581fa14bc69b659707ff4fd595ce7c5d8573e9", "U": "0409889217416c4de08f62fc021c53e32997dbe0bd3f29b13aef94987871d5396219a953297537940594baf63183761acf995692ca21a264e34a0ef711c2429bca", "SERVER_OUTPUT": -19, "Y": "06752f8ac43cc5340c791a9a0487129a2d2a8f83310cc09519c009cd35dc4275", "X": "106a51363b0783f3d2dd3485ee1f5d863dbe538f643e7247794927ddb6b2bf1c", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"9ffe1dd0d95b87e74c060a7bd55ba5ff@certivox.com\", \"salt\": \"aac6f03e9c14fd6e\"}", "test_no": 103, "UT": "0406617995923ded5215c89838c151191f7010f19ade01adcc13543e4d5ed36762168bc61bbddc4d5d4fd36e6326a41a37881bf4241045c55f4403d1eb5326f2dd", "MS2": "027295f21dc85e27cbb63f31219daf8bcd4286cebfabadd026abbc899f16ff77", "MS1": "1b59ee246497899a30a7cb1a2dac3232eb62cc81a692b3eb47055e28879b1b78", "CLIENT_SECRET": "041507364ab4438cd4f56d2c35ebcf50a6d35f2879064c77201aeaa61473509b3a1de46b862702937e1909c30ed2488524b511960704ebcd7e493a2e9e468f823a"}, {"TimeValue": 1437055596, "SS1": "06b4136da83250d985f73821998e2d8573a395041eca273d4729e4115ef259b501d96f68bada94a65e7210f27ef92c31ceffa567b695898ffb13fdbc776509fe1e9142d2ff7ce10eea365ea9f8c5df207b7e4c272ca8b41d0009bc794e8c10a81c77bd4453d2ef24e34057513896e9a9a9582c3fc71899e740e3843ac0d96116", "SS2": "09ca8a03f051b5eddd91849a5c447cb74c2eb9823a63009e38a63d32aa2ca4ad0aeb9f77018ecdc9f3ba343ad0abf4f03289437a8fec44e5f87a11c682c4dd5f138d4ac81e449ce5cc80709fcc476282ae1710519884ae0b86cb75bfb0ead5661c0f3eb9f63f2d846c7fcdee32d8eec159129ad57f0c7a676c2ed32baa1b206b", "DATE": 16632, "PIN2": 5285, "PIN1": 5286, "SERVER_SECRET": "1d7c59d0b18e853e50601fd1677814558fc09484977dc411901a745851488efb199671bb55e6eed28c4c6f77e28ebe3665678757de7e3752c76c78270c9905bb148ba5548875a5fc2caaa2850de1edd87554684146b890795a65e37a291726790c41669a81753bd068957558d4a19e02a8b8af3104469c4937003a3f04677d9e", "SEC": "040a529604eeffd1bba2f7fa89ba71d9fe40b01e2001ea0429790edf8497160ea81a438efd084b631c315c5bb1b380df6f7c963d2e94b5dd01fa51c44da1b3dcc6", "TP2": "0420ba988f3755d31f44153d4d191a99b3c7e28a15b4b883359ff17f94be9745570ea83cfd0dc6fd09d735d2b0e40736e72847864139338620792e7a548d1a0ea8", "TP1": "04145e69f1375a8d567fdf1620a7b87383c83386996ccf52c99a0e468873c458bc03a8e2eae20cbf6c1fa7ec424a109a9b4083cd959b39b48fa2a2887201e8dbe4", "CS1": "04147a0c6a4b3084b4724effd42344fcb88b83004dbaa6b40c5f8af6c039eb860a222de136847da557032e4299173229fa27cd6bea6e65c56fd97d9b710f45979a", "CS2": "041801b5cd72cbeecd3cb8d836594b74468e8750b838b41a4fa865b3ed42c448a31a4682d5983be6052b576c863654880bfc1e9b9343521d5e3e10db6d099762e7", "HASH_MPIN_ID_HEX": "eb850a58d158eec807f216222880c1246c17040db48081eb93860f4a9bb54843", "TIME_PERMIT": "040c0855e3d89af364af12b96018f2468e9ee7efcf2161d930178bfdbe6e45263f1487de86d0bb6b5351d891072ff05f5e484b6db0fcbbdb4883c8d1dc9fe348b5", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223663323462653034383938616330356538363765633439623130343839616639406365727469766f782e636f6d222c202273616c74223a202233613233306333633566653237313039227d", "TOKEN": "04010ba3ebbe39994c0c61e0cd439e962ce59293161c44ab8a3f2c160d0318edd60006972f0e1676a2c59b790196377c2cd53d14c4148f061cd220be4caf32c47c", "U": "0400fe4c635e884fdcc4c77314d27f9b362bea55a5d2385930b89258846e56003c11af72e5257dcf0a9ee7c91c25bb2c9d8003b19d390d46688bec8b6a5a79eefa", "SERVER_OUTPUT": -19, "Y": "133de13a673dbc1e356c0e3ea5aff2acd66b48505b9827badc8a92ea950c670f", "X": "02369823393a62d4e1d258f14eeaaac2133f95599ea61e870c2df6ce049629f7", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"6c24be04898ac05e867ec49b10489af9@certivox.com\", \"salt\": \"3a230c3c5fe27109\"}", "test_no": 104, "UT": "0411ff91bc8f38c928d0e4b2bf9a933cd5e7d94ccd784f27e5473140ef2b879d7c1af71bbc84c59770795fb1a4a91f9f3b264067c2dacee1485cc17700062df47c", "MS2": "014ff2756b035b7d53b5099045e227c800ae6c89092aa5491d661ae5a7a1601f", "MS1": "1de078f3f7100d1733e752b63fa065c982a663134b0d8b18c2c82b6f1e634e67", "CLIENT_SECRET": "040daad48dfd9e99a6ebc736f3faf99999a217a2d8e6d13b0b221714132dc5035d05e2de33fd664906fde819ab2886f18a2772937b7d4f9e6d939c0345cab9afd7"}, {"TimeValue": 1437055596, "SS1": "0182e7e894682fa24bf4a2a279783c70044aa60509dbbeb89376a60dedca737e1e771c48360ed41949762adc29c1485dd965f77cc80293cd9d60b16750262088091513ae18b3c3a6a63678c15aa0366c6c5f673bc91e7b51a292a0179a32fd5605a997233e689e1bed37e76a7826e4087cb3ecf7a3c33f3007ae25217aa20807", "SS2": "0615e8bf677c7d53d95690511939007efc0755fac8fd208e5a002c147ae6ee8f1be170b61a12158028e60955e4f3a3437a9d21d833fcaae56b944421fd6f6cf8181a6a11c80e87f8fa2be5eaca93175dd0efe3ba9bb0a75eb014da1c0af444990d0b09eccd21cec2f40998ad7841a72721620ead0c52c8279774cc9f6f543af6", "DATE": 16632, "PIN2": 7647, "PIN1": 7648, "SERVER_SECRET": "016542b22ec8bf016264dde9348a7d003a5d7480b5fadac57e87988fffec230f0d9a10249fa2d813be947f8164da54d38decf48e6bd646b9c1ed480303d2e09c0c664cd55832b6f371f3535b86e2fb765b10268105cd716600821d34406fe23f0fdfaac6a5e81bdd3da61a6a9d1a34695381640368dec8d517f340a0ed0d7a71", "SEC": "041dc36a16a63c55bd62db23e45f6e59cd2a5907faaa6a5b6a6099baccecf4852c0ba44ea7beedef58ad41fe9abf856718bfbd0d04fee18c0064fc17720d133dc5", "TP2": "0414bfa74cd952e38a8f2723870e4fa59c4f69d6ed2b92051a883cdc0917e444fb1e9752b0f306512afc6b8320c4305b765d208b7f497b4b0f244becc23f0044bd", "TP1": "040a26ef66abc170b3b9e6ad4f3b4aea41187ea0030c85a88ce872db0e89e39c1114835a8531467446b6e3637efba29e2f9b6675b0ce4b82afab90aac115727ce2", "CS1": "04079a1e33d1b7b93103d8c4475c74b929d8a36b4d02f0a25079c62ae07b69e05a034e5229c370569477166d2c530ea4da723b2e8da7c5114dc8d66fe472e94fcd", "CS2": "04095c9b1792c0d8397fd2b56af158e6afd701e795a0ff892f809df854260c8e470426dfa58ab44237dc0f18d5a3797c24b3e96eb75c1a54ca772bad4f1f2843e7", "HASH_MPIN_ID_HEX": "113834ff5a57f29ca273ce104ef2ef9ac1d3df62c168e93dd52ddb551fdaa185", "TIME_PERMIT": "040e990d958f2d6ba7d1491b4985244072a710daf432de1e99f58e675ee0c0498812e694856e618274b8004e902797686e5843e5a2a93ba6c34c167bd342c20f9e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223165646638323036643239663837396233636233353238316266323433646166406365727469766f782e636f6d222c202273616c74223a202237333163363866376162386339343933227d", "TOKEN": "040469ad313be29da619c3eb33e75fe68fb5950347e987c289917906286837fad111cc29bacb4696c7aebc054698d5a897699c557cd5ce1cd9d15409fa178e4483", "U": "040530095e32d52eaea70ed45d5a0e15f80816dec33329f9b6ca76112a1506cf6b2169eadf10adcb9600368dc1fbd659c2972b9682f85d12d000a444e33e9df8a5", "SERVER_OUTPUT": -19, "Y": "14a9294d442551cbf7be4d6f32f3df0bcc40313c59e679b5b9a272294cf277dc", "X": "23e19434748695c0ccef7fc9496dcf2582eae7970414f26978e4a662e31591ca", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"1edf8206d29f879b3cb35281bf243daf@certivox.com\", \"salt\": \"731c68f7ab8c9493\"}", "test_no": 105, "UT": "0420ad010d53a32d6caf2661454ebadb30ade8f81d9594c6a22365c96f83b69a970d07ccfe4f70f4a4c7b5e9bc964a3ccba0646d4df6abc1c93a537132feb7c7ca", "MS2": "160a2d932ae72834984c30f856207615abf6a4699c9f1f08186a0d876cdcfb98", "MS1": "0fdf3453cafe2a40eac515d2b620e675e5ee8353a51cc84c1835ffcee40cd4da", "CLIENT_SECRET": "0421a7175e261a8897a16af8a90c028aa7b6e76400483bb8d28d6d031c12bd11061988862e1b7725bec961babc4bf904781705cd229f3320e3ee97dd9e43d5334d"}, {"TimeValue": 1437055596, "SS1": "231c28453011fb5189159368cd299d5eab7c39a4c8b3e8f587df9dec6048b0e013848bb643b23bab9aff88dcf82b296cbc03078fec65cd024caf1288f6ef72c10b3ba88d3ac129881868a0aa91978c6bdc2a4c8b0dcc3c5be2a37bc09f3cad5604cce7466ee6dcc803f1f2eb10cf2533cee317d4b4fe8b3c75c8157251fe29cb", "SS2": "18e7ee96617fa7ebfb3332ef6b80ffaa9be7b263cd3730701224510711bd1cb406c78044fc129a0f52a30fd95df41e1e7af8cb57c3d66792034f2f4923be39e61b90d7059af823f794c1792a25c4dd7ab412aa65136a86cd0e4fba8049cc3b6e0550fe361a90ca8b5818bce79d65dd104ca0d601af22fc09e2277bac2cc02bb3", "DATE": 16632, "PIN2": 3817, "PIN1": 3818, "SERVER_SECRET": "02cc9b5e05d4d2b5b8229d21b7d48d957055f7c17cc0e5b179951102c15fc98b014afaa0ffbcb080370fd9da18e37983e762b47a9badae80cfcef84c4c44028b0f31f801a68302d73279271a6c7b1665a805ddb6e241490ff0a96d7d54069e351c8ababfd5dfaee1459ae3d177b263c37d584fa6545a749dd27117fa9e6e824a", "SEC": "0421abaca8927be4d33b66c3fcb2d346421c924e74cdb0a4abfc32814c0cd8854922bb1fd9bc685d607f4ce5aeaaff18427e19872b405b7497a4b4793fd3b0f9df", "TP2": "0405f42f2f69517a73f31a49842f4c17f84cbd8a2af7fabfeb5d519b06328c266f0a1565acb59420a7df03d587267c04acdf68a70e515c0569b2271216e5ccd83e", "TP1": "04109a3b2b658715db46ec956778e15932dfba4063ce24d98635955881c411c33107f7e11a87c5a821843db5a9c4d077eff6e89f9a0edf87d82ea6c29270360599", "CS1": "041bf24c29962fc451a3e540571cbdd9c57e446769d95f5b5182dc711c32aa5bbd0febf7b286dfed5d187f98686075299337b1c1da3d4be04a48ed6339ad3ba27e", "CS2": "041c930ab5cdfa5d4213b8b283cad97161bc983e303c1dbfeb6b6f7e5017f321870e7642070ca3780f30ed9866553f3abf641cb424f600f1a7fc53ec665ab3b18d", "HASH_MPIN_ID_HEX": "0637640b8610e41d40a658bda97dc9a3b9d6851bec4b72e4c54a848172412990", "TIME_PERMIT": "041b497d5556b927b59190251d35ad2cb12c7b7f66b0126577661e2898fb4c1d651582495bf44e9ccad34e83a2e7ce3a59d8d3f64895cbb2a274a5bf08dd14c986", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20226130376533353734653739633465383137313762306462343866303536366230406365727469766f782e636f6d222c202273616c74223a202237346664343065373465323936333635227d", "TOKEN": "042151cf3cb8a6bbfef31d6ae3f97709c568a320a3ec0a55fa7959707ff164997821bf8cfa5bbb0d7e7a2bc16d8d45417f305f5c9195b93d394f58cbc84dae9a35", "U": "04079cb9d121d62876b0454f90f372ac2ddde8a1e17c7c66a680cba8160df15d07026fdecd94fc0f9f86ea3ab919ca980b7eb1fa93e38cde0cf15428bb09065615", "SERVER_OUTPUT": -19, "Y": "143a08402d60168a45d532b1b719515e4173b46d9d8a37e606dfee58d4f9d01c", "X": "148e9c2f66c03de1d12a7698d3cc328494f14a00e0600362de2440db379299ad", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"a07e3574e79c4e81717b0db48f0566b0@certivox.com\", \"salt\": \"74fd40e74e296365\"}", "test_no": 106, "UT": "041e9176041b4fe36d964f07ac5aee0cb46dd66ee586508006e37962dd54fcb35b2004e70a6bdb212c085899a55e774bede455420e816fc7bd9e18d665d50fce35", "MS2": "20132c835f800f71b6b17499fe91c9273bc092a4620a80b172644ebddcac550c", "MS1": "160fba953d2e5c27c996c003c6e74d3334a26355e7edbd91d81e8ec9076d35b7", "CLIENT_SECRET": "0417bcd66abf493a347e7a8d8e242685e139d91c53aa1bf88970cdc567894cadc105b4f0d8368213c6a9fae9dd6ac9d80b5ab04f37ae2ec6d6544b54449ad0f735"}, {"TimeValue": 1437055596, "SS1": "0a3ef6ac8f56c91cd0c7a027c2b70bf1cd46ba73391c43de87756fdc47464c08232698ec26707479f0f6df547cb18cbd32f5fb13b64d6db8b9982c399eb9646a206e4656aa092a9bedbdc82e9db2aa43d43d5ed4c692f981a4cee346ac46efbc1c28c3b01bf8019459e0614915b4b499d5845bb43bce6002baedbd582a59e859", "SS2": "2380239b4eb3b745b08d78b237c0fd1ab55385865795b15beafdd1845ad9b80902ac0f1ee4cf0b040bfca7a0e9c912a1650a578f312c5a6b58af966240bf4adb0e93d4bf91f738d04a2b65a6bb3b0b01d24ee6a482e63e89fad16c63fc09966f15d844793f195fa4fc5e7936e2fc12b489b258fc282abbccbccb8ef0cfed7ed1", "DATE": 16632, "PIN2": 5884, "PIN1": 5885, "SERVER_SECRET": "2252d60bf332a5f966e0f987080ee9607fb3e62b880657425da376c5c21b0bba077b7fcf3a041a21003141283156798872e3d4aaaa72764daf3c0d7b5d76aedb217019ae27bf20e51dbf2840eac24209ef3f79357c27599202c4acc8f5e3754a183373d686b898af72aedb728a5ae5614b95f33391db52b695ba7711ca4abe1b", "SEC": "040a54450fe0d30b9784cb861798fead13fdbc272077ee8b64cc11d520112508760c2c972a2abd36d2f55cb98bcde463ac1fed130f5be3e8b4509eb82c1f1bb6ce", "TP2": "041d379553ebf8c0bd0e583c0b0f208eb3c03e0260f99c897fb5dca59d37b8683711f13de3adbcf7c6180e355c74a6a95aa917ebe9b82ac2ad0e0b2dc3ea24b885", "TP1": "0413e82c1bb73bacf86dab105b247c6d39a3198e852388386542ce4b910859c7cc02d93f170bad95e227248fbd0ea8b07da45090e5654eab8d46b6e9d3f6a3d243", "CS1": "041fd1ce64b2f09e5bdce82658a8c1e99cf43b7a397237d8f62a1cce7b4e0c8805132be2a3f60038549d751b3f970564cadfd7284b0623f8ab9e37b0c45d2dfb50", "CS2": "04170135613d625d4847a29542f909db633bbaf692216d278e6ebfb2ef88a2ad4d001d3bcc13cb5089418033a11188ca0392e02bcb080f8865eca2a94f6789fced", "HASH_MPIN_ID_HEX": "06f1e00461d733e74b523883483a38e99a1b5249f2837a8edfe7f1d2d7ef75a6", "TIME_PERMIT": "041bcd889b6cae9677633ef462ca6e6e39c7e0d28ecf9b97645436db8ae1c63f6a13ca4630fdac7242abfc595e1e04a9947c72769c2b7eac2592cdd5cfb4f99463", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20226164313664626461323365656634633933633937626436343165663631313563406365727469766f782e636f6d222c202273616c74223a202266386466653964633031663666313438227d", "TOKEN": "042354cbb8e1f8a7e18f19c79dcc77f400e5b1241f5609f099366613c67d528c7d139072e35e6f0cd6744026202485730df56b10c1673fe0734b0995048306ca93", "U": "04095ee15fd09a2c74a0379058c476edc37a207298a1cc4389703349dee1a5b803019095049b49b932edded339575a4b207a40b566494be7eab89d9fc90e47619f", "SERVER_OUTPUT": -19, "Y": "18aa819fc33f8c1cdf049414c8106d7a8ba97c5e35988f8e772f37eef7cc9f4b", "X": "12984746c742eb493e5b13b33403879f38b0bfc9d593ff340e0a0200ebf568e2", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"ad16dbda23eef4c93c97bd641ef6115c@certivox.com\", \"salt\": \"f8dfe9dc01f6f148\"}", "test_no": 107, "UT": "0407196a356991ac2725bc32eb483d2272d084d0b5c4859a5b0852888697edc1ad103061f635c4ae0750876b9f924e61757c141037e43e48987be4b78cd0f37b97", "MS2": "0c5da236e47ab07a5f48e24accbd0428fb0c2071ecca705a761eb0da06358390", "MS1": "205b1a9baa97ab6b23bd9e858c7f04d566e7ccb126174218ed14395c0ccf2a71", "CLIENT_SECRET": "040fc3cea5f1aa2eba07b6b0bdd02786777c229b618569ea70ba72ffe4628fc5580f67c605053bd1f59fce8a06f889ddb00c3c3ce16573cca1d6d7cffa11a70cc4"}, {"TimeValue": 1437055596, "SS1": "05156b6a71ed40159861cc42679dd2d673a4b9c7ab5aa2a82d83db815f690ec312d5438a646cf523c6611c33c7c8ecf839fca30de5a510cc333608d455b1d9250b8a42b4cb1a6c70b8374faeb976de07b057d45f70fe16dbec7b5cceb42d63121b5b22514ef27f8a0879f6c17dfdc0acb63ce09d676cb5307eaddf518b60caab", "SS2": "08d6f4a61b64d1ec5e284f47214c3512044f128b8b900e49f577503ad32a13ac0b54e0fecc5a94750848ec09c11442ceac8fdd97b39c5b5231dd986b837178870c77ef56f40f2442078e65d52fa0e484e740a78f1b7c472e88f331800b1f0cc91e1048998f30981fb8dfacdcb4262bd6f9c183f363fc61b5f6eef5e542bebefc", "DATE": 16632, "PIN2": 4490, "PIN1": 4491, "SERVER_SECRET": "1571b7d9f10d4dc4e70c099875e883792608d8028a986f926ffa8731f62bc511227fc7770a994bb202f798762e5c5ee7f28551f7e4ae0efc400880bf7eb8e1b8101045ebee38bc74025139cd2dc41cd70eb9906a33f1d4133e34e54b37f71571235e75531784eeeac1585492a09cf83f1499ef88f22283967f7a19d97524e05b", "SEC": "04193f0805117013d92edf7dff1c71f527e6f958edacba019d6a3028d488e07e7e0e15b270dbbf3c8c5604f7458569d46e1a965e1a748f5e3f8a5ab0ea56b9db6a", "TP2": "0413984da8f2fba69db247f26ff6cccbedb53de9f31eda10d8d2df88e4a80aa07c129dc9642606b1ca6a2c83e1c69bbbca967b04a748163afa2605aadf9332fe15", "TP1": "0405436cb4828ef0c4453b8aff0ed24922fbb1a0ed70cf561a43a71eb9c782599d094a9dc0f13e4d8c387ba34d934e6495b0bae970ca3d8d42ffa0eace467dcaa5", "CS1": "040f8311ce1d97ad0fa1da56f4f1088c13623e51fc9a69ef242f09914e8635da270223ead337542a75b9d83723ba1e320c8852463a05f24c3edacf823104f6c573", "CS2": "041e81def61c19cee1d49a32c37e7b3e513e44e13dc69dfe16c7b5e92d1460612d0943115e5642e5e1abab7140e51c15e0a3e0a95e1d187c443b81c87e627d11c4", "HASH_MPIN_ID_HEX": "dbf0ac63a7d05f316cffb18bc0ccbbd53aca5af4a6d20ac106c6487079d4cec6", "TIME_PERMIT": "0402cfbb915268fcff232fd6dfa515ff9b015d17fb29587c14cf4ffb64a208b50012f947f205734626831841848f935b58e86f78d616f57b438e80f37b43cba1c8", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20226665316138373964303630363833653861656161656563653337656661356536406365727469766f782e636f6d222c202273616c74223a202264373135623664623835613861393633227d", "TOKEN": "041c6893c325095161574fa48156223f148a6e56e583d3e36c8c3a8f018495feff14d7a00a54589c887cbc416f7d85fa3c774bc59dc513311cdec7f7db0eed6cfd", "U": "040630c335e611b19143c3815d26d5648a16f35133370e07d836d040d7f2ccff3e167faf8074cc68cb3a8c2ef2981afb6b8ab8bddd7a91ff0a5ef632910d1cd305", "SERVER_OUTPUT": -19, "Y": "1eee4d3903f4f2d1cd315e6db9f1ba004b1e0b17f3d28c8d00c3141f1d8ee6ef", "X": "0ee1be994984d2359cd891f9642660c7307025af01c828d0777120566e6352d0", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"fe1a879d060683e8aeaaeece37efa5e6@certivox.com\", \"salt\": \"d715b6db85a8a963\"}", "test_no": 108, "UT": "040153386d9ccc2bbdd486cf5e0533a9953504c4f8091cbec07761b7309fd1548c20923c1d8a73a68e5db475f58710aa779d1ce68e87dc759c9687a598c93bc1d5", "MS2": "1dcee98a8a6b3f5eb89e5142611d339c4d2c537cdf992e5fb81fb626008f5e73", "MS1": "17f66731761da4e4eebe60940f1547dd348ce38ca9ab1aa7a65377ba2bdbed84", "CLIENT_SECRET": "040a54a9bb59bb6247a16bcda26b52d634e7cecd630c30d93e25e3acb2d12487c90a9d4955a45f22482d54d1b30a6c3d6d61eed41d332ac59cbcb952a797c85b89"}, {"TimeValue": 1437055596, "SS1": "1294c03b56e5666f4f8524025b2be2fc103e1b47a137a8fe411b2984d2b9d029092bb81223a0eaf244cf09d9f2315f57f8ae22dcd8f6899fee9e1c91246dcdcb07220aa16b029e99a05e22ebb85c26a12f0bd1d9214dba23dff81125388e986617d806f9d5a8568f14c2cf16db97d6a61278c7825f80090452e1c8795b5d5503", "SS2": "08f740cd42874055a7df10a13be538bd5fe4f7b9c19b6245875a6cc6331c5b15169a2c773e24b97fea3789e248080443fc34af4f73d54e3ec08f2678624c7dbc1e5b941fc183c03c0dec5e6df1d921ffc49386bde2aaee2145b6e6cc1a3f69f91f5e64422207c84cc15e6b033b9a962b4efa3e7c9f25ae8217ab3d9a73a00cf2", "DATE": 16632, "PIN2": 949, "PIN1": 950, "SERVER_SECRET": "23c5cfce81dd8bfe510de27379fa0e6f223c1507b77242047e29f20af0ccbab220b104c51c2fb3ba8aae87675a345779592ec1fb8708160321f6e280fd40d8240d983e8d57898d2cf271ce57e7cb0cfb9d14bb97fb5f4196d39e4f10082d6bd91dd29e6a16d4997c326b306e4727675f2f299848df001b90ad744f6929c2fac2", "SEC": "04046f980a39409a59c622032937c1762900f8877abe23da48e6057ac4eba4eba30163d6f02e4014350a9283592be08a213259b5e51f4c709ad06df83e83e09f4e", "TP2": "0405172e8670909654eb4b19c554ee47e46011fdbf28c1cfdafdf8f66a5873ddf01e1c6c7118a5c0a4504997c010f2e678e5f047393ae05efc6368eb38bbbef08d", "TP1": "0411e05df64736acde1c945b71c1c5372ae69e620491148315817ea9e1bac509d6168aa8c33fe667d76a20d395b41c5d0b3659b0e71da691a427f07a4b396503c4", "CS1": "0420d72f203c86a02f6cd678f4b65fafe8d399c12d1ccd310fd5874b13f614a596215bf3e320ed08109d526b240d6b9e5613a69ecfb19ab9dc6f27118eea903e90", "CS2": "040147ac1527d4d766ead2c9849951c149df59b41d38169c2d8bb2744e2101a21b0797d2a10b30cb0ba3a5c8db0bfb36b43d23329b3f5e67b98d795d3d8c3b910e", "HASH_MPIN_ID_HEX": "f28156ad8e58038466c893205a0bb0dac67c97fea75dd7c5ce03fd3149d254ae", "TIME_PERMIT": "040b401af43b8ba56669db5777e8348ac90dec4522831a6a9ebe41bce879cd1722167706073e415c7aa4fa0b249d4daa630e60cdce0990fdc3fa1925afc33a36d2", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20226536656362333361373264613638333661336135636261303237383832656533406365727469766f782e636f6d222c202273616c74223a202236633063623766366562616336393031227d", "TOKEN": "040f34b221d7dcdcf29893a43a43001e6f777eca455d7a6f9f145c0b4db039c801196aea7f14cd4b47efbaec65247815ad490ad9c4a425bdc8cb4df45b136096a3", "U": "0415b539ee7c9bb2798cbf06edbab49e6ffc69a8bc448c2fa06c334a5e95f83bfb07634a2f4478452bc9d6a2c9e853fe16339e4f368d4f7186282d1010ca3838b5", "SERVER_OUTPUT": -19, "Y": "18afcf03858ff1dad9d45a61d1c9f0541674b6581d08cf43160694fef4369343", "X": "0d1ee1ac7abbe24cab288d625eb130be98bc41b3628015bdc033742ce84a2d52", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"e6ecb33a72da6836a3a5cba027882ee3@certivox.com\", \"salt\": \"6c0cb7f6ebac6901\"}", "test_no": 109, "UT": "040c057ff9af284be936da8492a8e3374cdf731d0b8749fbf85e1b73e14502b48e019ea06412ed838aa76a58a9b07dec855669d81d2412c9d8b30feed98a585575", "MS2": "15fe0226fd8e5ef83a984bfc812f38f5d69c5f225fe16e4d0986bb6c2cf88983", "MS1": "15dc01b0006b945adac0656d344456a887e5c65aff31b9222e1e072d2f162959", "CLIENT_SECRET": "041a31601f8132044e58392f15328a565201fafaa48d970aa8329beb68ddcddcf5037dc5baf15d052dc169ac747e59d1b40ce0fb6b31adbd5a514822a863bc3439"}, {"TimeValue": 1437055596, "SS1": "12095baea80d8535eaf5c2ce6ada586252b25c69ba6dae39a53f66fc32cb6ebe066cf9add46a3818046a17c81370c09a4ab60587d80f19f026fcdecd11e5602b1d18e785c31fe8e51c0c1151cc8dc7ad37ada66ceb54c85884ea0896f46eb6c9208ba585337281990ef26e55963dd9a5066cccc35ed7462a320fee9917c437d8", "SS2": "147d4aad1dcee44973f1031d30a899aa4189119303631856dc4c9c32a16d9a681a47b6b62896f58c074e6c2e1b2f7b911105022dea3e9515eedbd081595cbc6d13042ae7792c8750869f11c9e40c9419d9e9ed323c3adf097e7accbc394a1a3903e21c15db71d7267bfad9a8e6966dc3e6a52d2c757234b623a971459da045b4", "DATE": 16632, "PIN2": 9442, "PIN1": 9443, "SERVER_SECRET": "0e044af549a1faf5e6601b4ba14fef2dc2c82b756f28d3b2d9ad6f88ee5b9b5207c9d137634732170256b848f8aeaf7b4390ec91f448ee8c49b98a62d0cab6de09ba81f634b12b2904ed4ca543e7e05ead7e9ab934c71ebb20347fae3d044ad7197f6ff7ae5d3ef46377dc160949baf7c38cee5d7069539b59d076c617758751", "SEC": "0405e11da4df3b43b3abd1ee2f4edfb2bc31a507a5cb12952578cf29bad77bbcab1ca2d472287f2a3a350da02f71d98f7d80c68db95a1f852bd1942499d3894b3c", "TP2": "04158a7ca8d903883a42c35859a7f07abf62a46480da329a43a2870c09b9b97a2f17fe36a28fcb093220621b0ca2e4621cd5aff1efcc0500893c540557fa8dd65a", "TP1": "041063d958c5b95f6777e725cefcc33c90773bdb1fb8d18415f990dd2a831bae0a17bcfd7b92cfc6fc8e8ab0ccca1887ebf7e0e476c20dced8cf2c428eff35d3f8", "CS1": "0406f4ec06ce86f63fae785efacc5d82f533180bb55b648e41f37a660462587ca41da817c3646041163e56352b7fe6dad729c4bf6915525ce72e44eade8e3e8407", "CS2": "0404e4f755166eaf694f8133a01f6a2731e158e0e775e14faf3732722985fc1a49160c85759a24d197856427eb06329245892c317de659bf82e71d9fe193e260f6", "HASH_MPIN_ID_HEX": "5cdfc7c93298e3d4c5179a5361e78cc06466e298d4b26770f82e67f4b681de98", "TIME_PERMIT": "040ed0231df960b82a2bf193be9a90c254ccb8ae038d0d9ae7d60e9315374aeb5a20d32efb49fd37bcc1e0bef631cf0a90fabc71ed597fe0d55793bb403dd709f6", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223961373930356464313231366532653162313966636535613933373361373731406365727469766f782e636f6d222c202273616c74223a202265643637363161343731646464393638227d", "TOKEN": "0416f146ee14601c029cac62d06a810c2c44e9c4850e59ec05c39d53737a0ebb85052568f53d1a897e1e927a25ffeca971bdb23520628da85cf289cdd8b5f6f9ad", "U": "040d2c623b43f9dfde785a8c63a87fcce8bee804a4752ef63e6a6dca5c0011d3c60813fd4ffad348c4baa3f7f36fc6744a52431828aaa4f8cf24007a40b8ddcb1d", "SERVER_OUTPUT": -19, "Y": "07592fb0c693cd5916266e352f519a1a53a64e4d302387f013926c4a8d3000c4", "X": "043a5626157b6d0bc8c1ae8873afcaf77ff15f6131cec50e84529904a4a2184a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"9a7905dd1216e2e1b19fce5a9373a771@certivox.com\", \"salt\": \"ed6761a471ddd968\"}", "test_no": 110, "UT": "04179182ad06823173377a49118176dd694212f182c59cd6b92ef772e70d654eb906eaac3dc839582b90c4550704a1a34a919b877e4df265d3c308708e0af30232", "MS2": "1652c4b08f9813654936e30013bfd24b37570ed9bee3d8482febdce53cb31877", "MS1": "0f9a25a1c2c96b904d6c77d1edb8f610b7094915d34715c8544758389855e6af", "CLIENT_SECRET": "041f85b60274c68533d9863a4b0764ee3e341998c722dde9958798ed751d1b1c3c0326ef05a37846687332ded368b22eeab0297f1e3697edda144eef9a9f40ea3b"}, {"TimeValue": 1437055596, "SS1": "0fd7c297e4bf551ffe991a4a00ba1f0551cafef3d87169399d7c058b4833a92e198b36204687455895b2dfc479bf810e8da119cc6e5a422ff56ed13dc6d121230552068b9b6e9a6a992118b844f3a391e3d4e2a097c3ee55175e094919d7975210242300d0eae76d4a11098f95115c24eb5b82eda23d6f7b7d6b35200d2d7ca3", "SS2": "02d5e884a2ac75170027c8e38dfa595575a41e0aaf5b5d8c2c3dcdd364af84611b563d5ab4e81460e78e7b4107ffceece57f0bae196c588a194d9ef6c86694161489b5d74dc482539f26d857890d29fcd3c9dfe85a25ef7aa205967154bd317f19b2b815dbfb68d8d81deea6d8d4366145e1fdd20fe1ee250d2bc0a6455085a2", "DATE": 16632, "PIN2": 7708, "PIN1": 7709, "SERVER_SECRET": "19ad3963c4dc91fc5ac96b64c96acae4766c6755f01b94e4a2c792bd5fa91eb3225b82298d8ad119128cf7ba53c6846853b3ead26cb275e982e56c0876ff44c8093d8d447cd2156ce717fea7c588a5d6b8c63c57db9a6a2533173723c1dd8b960f2bc04514180b6531c3f18b97666554240c72684bbab3cb697645743c3ff473", "SEC": "041586dd1fbe4fe82b51d0921ad56ea3395288f44d9316b9d4f6a4e423940bfa8e0421252fcf8e406f86b5a1fc3ef2ff235581a5707897a166e05966a98b553048", "TP2": "04225dd8dfd75cd6ce9cfc5a14d65d004275f4e078e39e7306ccc9ed0724f935b10553398de412ee0260c92251fd4f9a62c560d101205f8da21aa63ffe11981ba1", "TP1": "041432c904e93fbaff643af9ae9f9a0f516329afe66a357f9cef02c1480a66898b01df28fd732a8861d9063797b5251e7bd84b1d3a34854cb708850712fb7d2ac0", "CS1": "04150c38cea729c900b5d92d0eb50293f45311c425ec11fd4fc7c0b1de7f30be38116022a6ef339c5247c0f856f306a5ebc244624dfb6719900a8267fa2d23b830", "CS2": "0423406ea49df87c46f066e5e7424251f010c8a19beb22988fa9b68ee6230e88fc0f1051e0aee8053c2d8a27d6bfcb81483790a74cd950a1470f346845374952dd", "HASH_MPIN_ID_HEX": "21a48d32f5e5a237c3700950cc91a93badc59c13e342e7bfb66b6f243543938d", "TIME_PERMIT": "041407431d55ba249e6ab255810340fc52ea3f9e72aa370ea3eed28bb05fc30cef21967b4405e5df4b80f42557d12dfed6a8168ae228646c2119021002e891870d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20226136646235316539376639356433653232333132663632323430323338663630406365727469766f782e636f6d222c202273616c74223a202238333464643332613738333036316339227d", "TOKEN": "041ef0bf9c21ca748916be19f22829e09e41fd8f9859748ed8bfce31132f304da8128e3050577e40adf2f0d28dab788653bbabecc3f314cf1007ac848e53f54a12", "U": "0413bad0a29b645fda48bd35fa942d77818db96a30b54289e133f87cdc5703d3e10660957dbfe688d6e596b829ebf1425d946131f7fd1a6a6a54eac8dbb7046125", "SERVER_OUTPUT": -19, "Y": "181262c25ed8667f173a23f254857cd39614a7508dd8ff8ebabc162f126bb819", "X": "13aa464656804f642bf60f6fca2dd508932e6a5d19e86f025522cdf4384d75b4", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"a6db51e97f95d3e22312f62240238f60@certivox.com\", \"salt\": \"834dd32a783061c9\"}", "test_no": 111, "UT": "04182cbf5fc1ca27a3cd974f118473f838d146e912320b0f5e9ff478cdc8f032c31e1ad79300f4458de30ebe8cd42c3a694a4130a9b120b6cd980a5f423de5cf07", "MS2": "179ee9d8417137ce6f71508d57126221931d7ad15223c2cc7d61b9fe7eefbd61", "MS1": "018f7a7d853cd65b5954df6657d10b8d2e4fb0173ad2eca876ae88b4d29fc50c", "CLIENT_SECRET": "0422f88ca9f58845f22fc86d98ccd63e44045a355b2d50f133c0458b6ea3b0601803deb2cc1c0f7c69b50dcda84a3e59d9b7122c6016be53311ec74e7e78d8ccc3"}, {"TimeValue": 1437055596, "SS1": "0629fcd214466a17865b22a2ab30545e197cbcebd54ec4c6565062d0390436bc0e93d3f6fab5d22ad2c94438eb952fdd3498d931f7ac90d44c00f444675f48be0d8a013da508e6101323c8bd3b96cb537654cd026f044965a4b1a7f632073d46235863675d7a80a1757422025b55352704729fa06a7e990f0ab8bc8d00378b4c", "SS2": "05c5939fac44310da07f529478efa0ca27003abcad5e5e14749407d544728c3b208793f0b593ba04ce71aef31f6ac5a4e18d3c2ddd44bf425bc53022fdd98a0615a3eb47464dd4613396161b57adc31932d17960fc0c857da728cde2766366331524979690af8978a6f606929017b1f69351fbf5d49016230136802e80210bc2", "DATE": 16632, "PIN2": 7197, "PIN1": 7198, "SERVER_SECRET": "0b46f020d382329fc4fa8d59c2f845a311471c5e0a07ab624c58caa7cfa4d9f908ab87a00715ab4fb996910bb4d0cf8b13e8555cef158cdf873d7f377fe289f60a3c74686e255001e9859600dceaa10e0b183cae22c1c69a24f408ec859810e3046a3d3e8454289af67c557840bc09774515c58ff8f1ff5bbde8ec95eab14c86", "SEC": "0412e7bf9749180d234da58fade747739b89ee8e73a4b22fbc3e2f2a7a3ff0177d0bb83e069a308cc848bebc4b9aa23de0299f5e2d12f05ab37c8bc6fd1b6a95b6", "TP2": "04023b019804fa0867c04083cf2b7df1366a46b3d009d418e94466bc74a0610c371a36a8b446a10fcf6a2ac310cf43c3074821a4e9303c6f93bf9e494a4e4d8a42", "TP1": "0412ea34e83947bd3284d3ea00e842faca223c5b0f74d2d19218ef09f6e278c21b16c9019f48675d943273e10296b48c3f1524565df17203388bd70758f495dc78", "CS1": "041a91c0c324b5b486a5aec1a0563d5ff0101124dd1cc4bd6c4d4fcb2e74d7c3191009eb81d9d35c4bbe4e2307ba0bf81f2aa53cff34d7bfa393f3e5f30695735a", "CS2": "04167c2241ec7b6078d71dfee7d82eb7b32dd3290ef813a739dc34086d63edc362181eb52c2bdc46c0eac8982e332608ebbc713add12d2e95efafddd1506f4ad5b", "HASH_MPIN_ID_HEX": "3e7e0aeb88dda225dfab34b7c65f13887bcf63ebb302108f664de62d115ee477", "TIME_PERMIT": "041dc4a6cf1663e3710f307cfe3f1bad69fab9c7bad1554a11b4efc36323d61f9b03fa203f14ca91b4f7b7d2d1f2e8113d46edd71b4d276d661528b884227a29fd", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223061316437346139643833366434323466643539383837663637663337623063406365727469766f782e636f6d222c202273616c74223a202239333862376661336332346362316533227d", "TOKEN": "040c91754feabddb24726fb81d18c51028c198b9c464e1371deeffa2908aab2eb8074fd3106b46acb7f33db05f353b1b9280b26e86cb007b456219e6f08e091e26", "U": "0410cdee86ce21167d8804d8c40bc90cd3ced0b6b151431122814bf28e40608b2f0edaac84ceee9339d0c2340bfc7404f9104a4d14c4285f90f620fec0f3381bdb", "SERVER_OUTPUT": -19, "Y": "02b02e93276a4fd327fe243f61f085b6daeae75707a4f5cce1b65d7222dda1f0", "X": "0839dcbd8f3c99bd73121af0edc10686d5f72164192daded89b45a1723c4749b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"0a1d74a9d836d424fd59887f67f37b0c@certivox.com\", \"salt\": \"938b7fa3c24cb1e3\"}", "test_no": 112, "UT": "040e42a402abb6028b2f16c48c64a5a780db4530af57dabd9167222e17d29fbf92127ee3aeed050209fa1328eb356eed72e6bac6ff6dbacb14ff0dd80b7f7f77e2", "MS2": "07151248b45625b40f6c50a6187205fea160f014d139597f645180b6d2bce8cc", "MS1": "0f4399e7efb262f8dfdabd09515ee56fe30ed0f1ef4d3d8ea32e1a271f5726e0", "CLIENT_SECRET": "0408944c935453a134c8dfa717b62f804745916011a2462883ca60d64b47038f500657b00eac001f5224048067c7473532a03c6e9b93b402975e706bb9f0d8462c"}, {"TimeValue": 1437055596, "SS1": "20086914d74de8697969447783782782612fcfef12e300c770a9d5ef04ccab4a23e7da35310a01a02137696b35e0e425bd197d0f2a7339301090168b8de666580d3bcbb90d6af371fe96683f17909928cb54a4892febeef06715f761851edc1c0ec284e575c862a30a37530be64dad47e05a8694f189c142b9635f7a9eda6fda", "SS2": "07dedb6769a9c7bf18ac10c0926395a2368cfa6d86cf123c48f793399afd6403186bf60a5cdc5a6947fc82082ee8a7da0b6b1d7539dacb78d5f22ec8478883aa0429f6d574e7331c6769f5196515631288b350f20604fbc0dc65890ff40991581ea9212961b2dcdcd72ba0f9c3ddc9a6305603dfa49350901b8ce5d2dd20381b", "DATE": 16632, "PIN2": 1327, "PIN1": 1328, "SERVER_SECRET": "1b51913858834c948f03c49e8a084cf6d1479da51c55325c65fd2ccd849365a60835a7f63a382c61165303e4be96e8c2599c758456e49bde5edffe94dd5e3515212729086652424589ed53e208f2bd1bddfc33898425f03a8a0efaf84db4a37d185d6e4155e820b1ec9802a593982a3bf531514609235009d8650600fbce7194", "SEC": "042365bfc2cfb71414d9e8e743ea82f6437578476ef94fc3d682af6880746864731b50dd9f80f32dd125626797ca10d33172c0dff1be3bb982725d5e177a9c2db7", "TP2": "041f98bea24ac4e2bf64acfeb2308fdb272c635fd01a0d29b7ace0a1fb1168fe6e02d627536d55292eb902cb44ae58540c80fa884c47f17c7686cb988c965657d9", "TP1": "04090af7defbf2f71a09861289bc5e8a778e633da06c2005748d6bda1d45946030145314d57b458ee566891a6017981c5f137f37fc1f259615a7e9b8027848c574", "CS1": "0418d6b993ca3f03be3208989062446f08180a9a0e5789575be1c984af9f95ad9916669332fb3cf851d1d26ba3fd78499b99e5a388a207695b981067c600592994", "CS2": "040fe90923622aadb435031bf7f3efc4176af6f701854f100673231123bd92362f0899666bcf46992074c6bd6047405b16f4848706706d7531b69433923708cacb", "HASH_MPIN_ID_HEX": "08e81dd3a2c38746757bf40539893ccc8b2ffea6dba13c0464e286055e60d5c1", "TIME_PERMIT": "040d9892e9248c6faf040d6e5f6860e06bcab83bc761943998eab6706cfd4d672d11ac058d67fe1f6926d0781f2ee6a10d2c785e60652c3b9e657815ac441853f7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20226134376565303433646663383561633434373736323037643034316439663939406365727469766f782e636f6d222c202273616c74223a202262326133306233323838316637373566227d", "TOKEN": "0409169a2a16dd97d8705bbb1e211f54d0308b81e46155c73db1733dad7c5d8eea07feb5f6b733642a53b048de6e45a40b1f1fa7c4b03e4b710082d62fd883f077", "U": "041b8e84eeb8c43bf1f4625fe1ddfb3331b4c10aecd21edc32943251c2e86e7054034d51d13870e55ab097d13b21e772f733a0fa4ba7f8e7ecf9651aeca61d9cd1", "SERVER_OUTPUT": -19, "Y": "12fc51b817fadaebb8b6f07f4d9567495405d0a8cc9656cbb55ea64613f6acfe", "X": "175bb18d330e63d7ccde524116777c6a2a58c4b6a5ae4740f3677a5391d12d59", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"a47ee043dfc85ac44776207d041d9f99@certivox.com\", \"salt\": \"b2a30b32881f775f\"}", "test_no": 113, "UT": "0402035ccaf811e411eb12c9d592830849e733fbb001f790b65d620cee3e45ade8048d1c12a9d71f817ce5cf1cea17cb6a4f9d7273c547e701715b74d875aa5713", "MS2": "1c1f23eb966a0b21825a02a3f8afbcadab19b30c5110a10ec63b43e4b68234f8", "MS1": "1c4a0ecf115fc0285085808fb7a1cfb8ae0339b4a9c9025abe63238362fd4b84", "CLIENT_SECRET": "04023672af7d3d98e8faf2d9160497d7e9d513751268055e0ecc25cd56d2ccf4e104211ed5de0e50de1e3d25673b2b92380919a0af3e63c0ff3e7048d6244588e0"}, {"TimeValue": 1437055596, "SS1": "14272f2843bffaeb312a015d21e9f04c11606036544c33a1cc4a59b9215ab6ee0d342bd962cee75db43c90d53a4df54ffddd127455bb8c9ce97d3d8db834eee70661572e62c3d830a21f3105ebee4d02855c76732e37256cfefd3c223c5304ea22bd4d3adda7d03bea352dbeb97980aac816e4774d9c5072a9df861a90e937fd", "SS2": "079b80ef83f01177bbd165660b9b527a9d5744625e07d37bb9fa2e69d9032885033ea088eef5bd831fd06f2129b5b0d1ca2f1365bacf674bdac44a0aafe963ab1fa96008f9b3ddc88e3f355f339a6a1de227f06a5be0155c81ed623ee6237211103cb26f0fe24aabaf2fe99e4ff892c0acf77370fa71b093b9eb5bfc86f3d1b6", "DATE": 16632, "PIN2": 2077, "PIN1": 2078, "SERVER_SECRET": "109ca99606fff8b1d55097ca462097ecf1b2297fd3fb075499901345b1297b4e12299a1b3f1262663076db67c0f255ed9c5f11b927da312b382e9a1cf837a8b410686dd46951aa6e6b7ff51a48784758b06967ad5a6bc772fcf1a31ab1bcccbb0fc6491b7d6d180ca14bafec995c275feda1adf954c55c451c4916443e8e259e", "SEC": "041e8b908040b99618e4df6637ac9fc79e3a62f4ea9fb7b6fe04f76b8db6b0a2121feeb940887ef22b2c5dabd2893cfb95884fc091f230faf4c4358edaca5ccaec", "TP2": "040cad3b1ae4cb0d825ad0ae4c10fe6fd648570f16960ea906be45039a476d7dfc07d97f20df379f2cbf88789357faf6cee21422b553cdb91b72969ef1b1032444", "TP1": "041083b80ed2a3fa0ad70680fd006c29c0a27fff8f3a4000e36ebdee1ac66637a309e9da89282e587e4ff5733fe72bade2ec778e75fb33c4d4bec255e014ccd118", "CS1": "041ba2a1d56d41a4411addba4d88e952d0e02012ea056ee4dbb4a9b572e1068e8620862b6fcb383d48a7942327b4b0783db4fe5941198bfffa165baa4b52852439", "CS2": "0407f93094f84cf549a785c26c0f2ab3a3bb7b8240affcb2c93ba2da91159dae1805d6ad6c47d8a127a0aa4b1f71dbf5692ac4d2129cf7769bf10aaf7d101bde29", "HASH_MPIN_ID_HEX": "db17cb003d4accc1be25eae5dc4962071a8897a3b7a434cbde71e7324f7459e7", "TIME_PERMIT": "041b2f99efd02d6383542af941070b6a0199aaec7021fff9d38d4b175f13800fad14717beee8dc3f1c25f421334535c7bf64b4f8fdeb63b6d4c950ee7c47346619", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223935303561343865636138356532333137346639663564353139303265313233406365727469766f782e636f6d222c202273616c74223a202233366364383933633132326364383861227d", "TOKEN": "0412c5e8265c17c57a63c48f02787fa7a3e8787f34d052b262139e45b4fc992383089f6aed6c1404aa13d3d26ece69864ef6e3387598990ce7a9226b6f8ff45cf1", "U": "04223ca0460ba6616f3fec286e85243ac39dd3b17ba501f957f4f164ef76d9c9be1f2f807c0077828e87f5ee202627c7ed370f210da31fa02de36dcfefd3563b41", "SERVER_OUTPUT": -19, "Y": "1c3bd236b505b7e6bd6fb927aea2125078babaf567a0ebf13cb3b3aeb726547c", "X": "159bd24390cc48c5557803268964efee832970613ca1bebe1f97562902b901b1", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"9505a48eca85e23174f9f5d51902e123@certivox.com\", \"salt\": \"36cd893c122cd88a\"}", "test_no": 114, "UT": "040c2c52423979bd60bb101acf9c2e4c28e45e6acd28f379c756788caea367f5fc0859863b24324f2dca7ba3f20e83cbc9e11ee8b6abe66f0ba3f92c2e5381a9ef", "MS2": "1f883381f6b590305d67ac110b9cd06fa17c2b99e4667e8aa50c17c46abe69ef", "MS1": "18f1b2bda7eaf6b4691986604a8cbfdd74bed3018b698108b50340b19315c8e9", "CLIENT_SECRET": "040db4d70146b129e022c3cb01cd24ec578bfcaa0f752e5bee34c972ef210e08f310c8bf8a590e5fb666ce54100d22f489f2fe23132810cc6800d346f300698a9f"}, {"TimeValue": 1437055596, "SS1": "0053ca3829035a7b5f7de33077bc55a26745000f23f083d8c3745b1fddd7810d1e0fb0d3fa774f98c1580fe1d39817673e2f7175f775a699fa421143a9582613041ef92433c9eb41b9e4b4c9738b844afb6a9a5da9e8736ceb9e7ff75c74e7b51c30fe4ae3f7ae552ea396ef26dab6a3a81207b557cd6448e10dea4c57a359ca", "SS2": "1bd76e2a44c852d4c5ae49feb8ade43944644e22cfd444b171c1df42357e298010d41ab501e85389272c0963d8f48ed90a76b4116a046301ffcb5459e7e29c932193df3be4d626bad1fc523c085f78b504f4b7d39c0ca3e34426ea272e659e5422f804ea2d3bd569504a64b3f0897642e34d5b036e8c9aab2622f5b01dde62f4", "DATE": 16632, "PIN2": 3334, "PIN1": 3335, "SERVER_SECRET": "13e709bc359c4b8615172c458224bfd918b9783f112639402daa874cf051770f1b0fc08e67df9306b80a590ca7ea3d34beabb5fd23fc2d296ad2bcaf869983c71654ff542b9c81a73c519e18a742cd5de2a8277cb3d5d91ed02a14f65230de2d21df85098f9c1dcbfa999d1ea6abbf456e25602eeff43631adb474f9c1c76817", "SEC": "0414f62f5d1a9d7c66fcb126cdf1f76a388c401208ad1fbf9eeba70dc1a8c9835115cfcf6d6b6e382556ded18063e6ac36960d07011693bd46f1b1ffadbb65557c", "TP2": "0405abc9d0da8daa1628f024a8706d0bc580dc864c6244af0a941aaead01b3121410b888bfa92f37a16b664cdb02b70fad72060fac6afb5ac837806b99f7083f2e", "TP1": "040fd3f57a13cea9e3abe4f78d047e49cc6a7e6495502f6dc5df39c22ba3eb833d1edfc59bae17bc88fa5e627d010de7deb1bdd4424676730832309e38de693e69", "CS1": "040369dd91af322f6d02906c761b0b8fe4916bcdb0c200e5b20ff913395957ee9b20ef153bd175a648d1d739efa981c7058776cbd211255623df25f60603432666", "CS2": "04057019b921244e94f3e02e19a22dad3dd9d7c9c0a1e22dfa583c4cb0d70ad9870b2ab1b962426a759123ee588e2990cc76696dfd264fc0e6a8410d4509810b0d", "HASH_MPIN_ID_HEX": "4fb4121d4ae5b63a5d9c2e146648ecba8eee52c3b76be8555c84d08fa1eb03ea", "TIME_PERMIT": "041a7d0619e90cab7b8198d72e16431c723bcd6fa0b0178bfc8be0dbb7de1b6e2f197c74636e1d8df8dee176928efa18121098eebaa30acc8fa6c85f802b31bc25", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223930656665303064613337653736656434616561326464316561333961323764406365727469766f782e636f6d222c202273616c74223a202230366561666133666265363631363331227d", "TOKEN": "0414799c22c8d57699ebd5edccdfd05828ae25bd6d6367b80cbea83f25cb62aad0133d7ac71a970cb4228049f958b005c08752cb5b305cf79584dc7de310550b25", "U": "041bb0e2e4a04e7ec78eaf83779060690482f3c7fb0d3700cc0a6f8d13cf78282111b170c23121f6d5af922c22293633546369a5d1c44f6da113dd8f3405a09d1b", "SERVER_OUTPUT": -19, "Y": "19d4b258a8ed494c8977ea59710b0154894418f8d3d377127f7b6f2a9edbfbf8", "X": "148fecf5d9d870665d50be980c8523ff1014ff8d57128e5f1c9b37792caa486b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"90efe00da37e76ed4aea2dd1ea39a27d@certivox.com\", \"salt\": \"06eafa3fbe661631\"}", "test_no": 115, "UT": "040d30ae7d4b887b8704c7c4853d6c5614a2e2de4488d68e580eeeb38ce73dd429189d540e8508499fc4986d358e4fc9457ed102651095d437c7afe1e84a6ec7fc", "MS2": "10ea147627701571d7cde7b47a0eac18a20ba9f257c9546d2a5a5edc2487711c", "MS1": "026024ec983da0acd02aba012375aec0b29e7c16103eff2e398d920e289a72dd", "CLIENT_SECRET": "041e382b092b911addff062b9e26c801f3b5a6250b4b9f6bd6075e0613f235bd9b164d04044c883c79fe3a5e605aaf4264c4c3970e0bcc0df57aa5d21720f8b32f"}, {"TimeValue": 1437055596, "SS1": "09458444b39b36ca6a525893a80535aa53e20357937ab476abfea4b5f4f27a900fb00243ca0cd46951ab94a26183955300dd923a596a01a40245e9e9a229fff40e0a5d2a50fb2994a6bf51ea34af8346462d9a5a40eb640b7a22e59f8110d3f3004476b0bba12bd13922de29fa847b4b852536eb87a50934854845a0a6818001", "SS2": "1600f77518de2729d723a988c693663c97253c358a0a617609587cc2fd30dde11fe1631c6cd854fc90a84fb8adb071441b97576f1b1b9281d1f47d54ef36113e1507e531c463d5a2f200e71434a1ae6002300a336a3906001bd106c618c1053b230acb4a57064d571885931518140e3b3b9d593f7d010557fd4a7f817876ebcc", "DATE": 16632, "PIN2": 8849, "PIN1": 8850, "SERVER_SECRET": "1e6d9389388fbdb49f1980600fe5cec741c8cca85e2656654954768dbf31aa9b0f88865e6aeb98c0f492624cd1ae9c0ee45661b4c5d2ff9adb566c350e57448b0fdf5f6618386261356f5cfb2fdc24d810fc097e3648e367910b9ef4a27b52781793251980d49546eb075f16222fa881a9eb26c56d8bc6aa7e88baf99d89e3ae", "SEC": "0421ca46887b24e6b5596496aa0223bb89d3882f827ab82f717017fa23be3720ea1ce46e93ac305712c4014f84b72f533e7e43ec194881cea9c01532d9908ed149", "TP2": "040d72eeb89edbb1b45042bb5d5bc78f66b2fd6257cea8b8a26291f319d86a448c179faf4d2dd374dc5c929ae73c5d6ad5d3323680adcf08f23ce7ed1ce5a50cfc", "TP1": "040649a1f2090bcaaa4f178ecbd8cffc3bf80b35580546d9c993ce87aea742365402c8be9d001f3efff0320eb9f534f867c4c53abdcef5f6dcc2fdac03a8fcfea5", "CS1": "040f3d3bb14e5f8b487f46fbf2e2006629316734e7c997fcb23fcfdbdef944030e0e516fab0a3f323b7b9264ab588ca55085a8993b0f424429c68088afd3fcbb78", "CS2": "042233731abdebb2050bab06d596f88f01f758f891fa1cebf624a6d9b0927482e600a1504d47c0adfcd36d98e7044e5866696498c3d5dca591930cb42c380d7589", "HASH_MPIN_ID_HEX": "ca1c03997c03145027c70ad695d478e6c6f582860d81864b4c53504dab38e419", "TIME_PERMIT": "04192a7d80712083c0435d5742052408d77e460aba6863311e35f92807264b10861945cffe515047c36c8b151514002702e4483ab33b4d6ea61a4819e8f4efceef", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223563326135393566326532343565646336303731336230323635646238626461406365727469766f782e636f6d222c202273616c74223a202232383031383636333665643035663334227d", "TOKEN": "041f2ea6a2e50727103923695cc9c302306994f10a77601b313e437b30cb2e682914bbb3ab4a63c7b42214f911220ee33cf8c5aa826893fe9ce9bc4c4764c15c69", "U": "040c573964473308a1028588a73b921b8b80987cc43cfabea8088d75f3bb44eb751644f3ef2d975fbf27d6fdaed2a9a1f428bdeade5bfbd3c34afe37f5cfd95177", "SERVER_OUTPUT": -19, "Y": "0963dd9027e74e53ba76f28e97b124f11445ea629d64b75534e9580ab37c7a5a", "X": "073dac142bc4de46f44c7515e4a5b340e94de5447bd5824686484e3d9ea09eea", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"5c2a595f2e245edc60713b0265db8bda@certivox.com\", \"salt\": \"280186636ed05f34\"}", "test_no": 116, "UT": "040fecbe0777d6eb118be3b7abe520f180d36738a13f6a09eca2e5f425c91aed7600284f55bb64c4091faf81b0c5508975b95672736e7761767d4825a3697a9a2f", "MS2": "16d0b9b486703e3df5c5d02b2b8440d097cd034be355065b909db01a9473e3a0", "MS1": "04797c0219262c78d7dc7f4b24a1a3e1b4078ba6971e2890007d1cfe069a6113", "CLIENT_SECRET": "041261e4f90043eab8bc64fa1e2e9bb91c15240bc7199fb95044c56b742b65596300b7b53a1366ee74fc83aa05056d79e65eb3aede4868a8a3ab9d5b87e150bb1d"}, {"TimeValue": 1437055596, "SS1": "1eb39d133a8284b98dd6a28b17dfb187685b821fd2132ec1ef6658a9301e5bc80a12f5c79509d0dc89d39c11de8a234c23f99de6b322b0a6c9c211ac604ee46b0a97948e036727f5f9e1462956285b7f05eb8a7b19aeba00496b85061ab13d5015760ba236a6990ac76002a7e83f84a4e4e6d38f5255e9251bf4e52a80cfbb40", "SS2": "090af47234ce4d484cc0d582a4b4b99e3cdff16a106f768d373480a1bd0de3de011e4256c11dd00188a49243da6594d0e1b7e5e0ea4bb31b9305d32eb82d81cb22445636ca33a2d7e7e1e4b1295efdad449458bffaccc8fe2cef0d011e82f65a0b01a23538933a9b166d03350829fba23cc931c3ab18c59f382e4daa568be5d2", "DATE": 16632, "PIN2": 6233, "PIN1": 6234, "SERVER_SECRET": "07f7a92b5ccc06a80b57099bdd47d8ae3f3886e33904fbbb7b99387e04ed738f01aef71eae3df4d41e9945ce07c8ebff945c2ebed834d0300a240bae3d7fee5500090f4086ac0e8504524e6cf93e845fe12f00abceade9c57920c01209a17535207cb40b1744656a24af81d96504e42d791beb9599ed3de595439befb97985c5", "SEC": "040ffbfd4506fe6ebee5d21f5d36b9bebfa85f2ef799837ad4a19df5b8c61d1b1a1fde8d948f6863b9ca83b0e61b0befd15f04a6ccbe81292af02f503dcdb26c18", "TP2": "0415531ab6727a0578e08b657d9b70a9e6ad7aca87b1ce2a94715efd9502fbcf4a1d723a193348b5d82ed3b86ce1d3d269451a747f5dd6537b4dfd8398ecbc6c6a", "TP1": "04233facb1b14562b79ad8b3e2bbfd84ef34ab93bb9a425fdf82684a969523ab11141cb2d41d5484a078ca0d9f77031e311eea07f1c32b0fd19b6bf98a43a61542", "CS1": "041c0c519642bd83889ea66c469893b7672aa0521122a37a2b62ed354d149384010c3fa8402e3df419d7c99202fa0310032d7068d701bb56f6817480c1fc093326", "CS2": "0418fdd1c3e54b68bf6db168cae28ebaebe3582c7fe3406fc1181dbf4347e7ef5521fc09e17b499d2ce16eff8b0d7917d46bffcf71576fc19dcd72d75c7b741f63", "HASH_MPIN_ID_HEX": "05348b83ca223b5a79389f69dd3934bb3f6ed2483e9e2c12d946111bf4e1f61e", "TIME_PERMIT": "0417cb213f986fa98457a8eb3ad0c905a6553eee4c82196c530684ca035b49be2507b94ca45bf3c8744b857425e5c3c5aede2a9f5c5a45bd5b1565165e7507f8b7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223633393331326134313636313236313131343835386430663835383631386136406365727469766f782e636f6d222c202273616c74223a202263643238663231363034366566616637227d", "TOKEN": "0420baf989c5c469ff13ae61954e74d74f148dd74a94d6bb65f0b293f36ced12010a2acde2d7345f42d1dc8c2f6b0ab6f3f972bde48350ea977475e2752e8dab6b", "U": "04147d701d0c5a9c7b1cf4d1edb38875210c2de08cbb2a197de53f9b491747dd7c101e67516511a6a33d43a59faeae4f99b09f86a1043435644da6dcc7acb66014", "SERVER_OUTPUT": -19, "Y": "011830ba187f3ad2d5e75a8d714b0d81e26c8f6c5881ce329719b19e00a38056", "X": "13885769a9c666b1337e975f540a6eaf7a8ac38339ce38f426ae57dfae25e5bd", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"639312a41661261114858d0f858618a6@certivox.com\", \"salt\": \"cd28f216046efaf7\"}", "test_no": 117, "UT": "041054b0c35847c89513f2efb76f270e8834ae4bdadbf91cde255a9e2f10d925ef0b32e221da7a837339c135e6277a1f719661e9938f74e12ca6ceecd637e963c4", "MS2": "135bdc971797ea32cc43331dc9ad6b0323336621855fe026be1d3a4a81383476", "MS1": "13bc6ed122d44f5f5598045509215b9fb0d4aa1a3711792cb121530a1953f1e1", "CLIENT_SECRET": "04145147a94910ec5eef791e42672e254db7efd0464df94861a662d3abd64905a91cd2889efc893467591c5a1f03971e18d28c6b7b68c5184b83eb34d9481020d5"}, {"TimeValue": 1437055596, "SS1": "202e3fecb7ec4d6e0eff8fd2da3b5cef2d051b7cb321da9491723a6017d818051b6c6c6baa11a67782c216095a95ea992c35e012d1657a055e73c2eebb815dc70ffcddc8372fc3713fa4baf87970df962c2e759b80d53be581b759cc7b227182084ece3a8ce84a787f446330b3bcf54e0740d79acc71fc7f3ed1b5b35f507dbd", "SS2": "14a585d23ba4eb51e7cc077e785442c54f8b304c636fa574403d751f982cf73310992319c31705946dab86e3b12a6d5dd1dc643cf4b60ef60a5b6b68aa97c03b133fd815d79bdaec5cbbb5aac7beadeca2b8807a26706057890599953aa9e5c41ebd8083d8e86d68b8eca7bdaf8d5a00aa28027af97d1630ebb466303c1e799d", "DATE": 16632, "PIN2": 2096, "PIN1": 2097, "SERVER_SECRET": "1702da708cbdecd64a3febf99b9385ffdb252000276254bc7ed8e0b5e8eebf2b0dc394231ce4165af7544ce5d7ce7461fa0570aa28bf2098836d4d3ddf1c4b8b112e7da84e129c666b43ea6e53e2efeb6fb1e8fd8545e0a399d91fe1ba443af103dcf8a1b25004b050b131a36bc4cc9a8594af393354b3bb565e1de58f6c4541", "SEC": "040229dae1589e2f073748993e70c05ffc4e990eb5db27ec2a73dc0d55fa5bb7aa073a84018cea62c4cf3e3d4418ffa003df58fface1d01e8dedb2eccfb5799329", "TP2": "0416884705279c3ee95f7f5e9bc65eb14c0e37c9935d5f2bc80af5e376ab3084200b1cd7577840431a0b10451add22da0191a275327fc9cf68f84ec120e64f32d1", "TP1": "04015d9a1e60f9cdf66fbd1f6debc51aa083d7ed50778df3c3ab0060da2c3c494819444beee4e7c4213cabe66fd0dc7f042bfeb41ea05356260f35a53ee2fbc61a", "CS1": "04151cab4968ada1bd2e32689f253b69f3f9fdce6f260ad36189961d2e2727bcac21278d8a4f272f18343d4ab4393edef471abb80e5ca2515e66b07e534323f3d0", "CS2": "040697128a83c6e5fcb8422b6c0d8c438cc8c08086b548ad2164e943be9481ca87008fe70ba851da614b8617e5dc3db4a8098b553e0a25fa199d450e34181fb0d6", "HASH_MPIN_ID_HEX": "5662d3e474451df2c82be520c4cc028da42e488e0543ab2ad3af4c5117690806", "TIME_PERMIT": "0407b30190e3c455c3f5f55204af5f7c140efd08e9a7cc3fda86dd9e57f8c46b631d896853f71406da6d21dcdd4238f46a33c40976e5eec3ffa51b784d95a631cc", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20226537373333386436373766313662326537323363383532663534363530383665406365727469766f782e636f6d222c202273616c74223a202265323136663761633234333231643664227d", "TOKEN": "040474e10908cc718e946547b4e2e58bea09b9ff16345113750a6ad92efee5f0cc026b413952df0feab10d0a3902e7b5d2e6a31e7873dadf86ded12166f9135ef6", "U": "0405252867ce84ee8af23ee05df886a8bb84aa400755daa13b755b6e8091a92c70124aebe87280fda84d2ff3e0a80aa94d69d728729c866a1e5421d471fc6f7033", "SERVER_OUTPUT": -19, "Y": "07fcabfb8df10bc698f79db00faf93dfa86c940d46aeee8d6cd9a47fd4e3f03c", "X": "182c27f4596013d091b09ee3a438ec239fcc0c1a0ea91d00dd58ec30aaf82868", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"e77338d677f16b2e723c852f5465086e@certivox.com\", \"salt\": \"e216f7ac24321d6d\"}", "test_no": 118, "UT": "04225feaff166d72237dc2df79ca2b1c2787f6c92652d8ebd9a52baa0890638daa22fb1e5750cc162b5273c9e8002d318f2476e61a136f1e2d21015bd6d67ceae9", "MS2": "040fba7bd591e5469d4c3b804c51f83d52c2577ca0d3d99342e74664953f8cf8", "MS1": "1547ba8262fafdb0528fecfb73e24ef2d31bf2f1f5c38f48e9c7fdc1a20e1f33", "CLIENT_SECRET": "0415c12dcd0f8003233a37e52245af85a2947eaf543586df03d36f61161e9d22d91970a90f0826f7d522b281458b1ad4b39c5e6402bbf3a027ef4732a69d9700db"}, {"TimeValue": 1437055596, "SS1": "0a15f4914b26841fbb86ccefd9e29a9621fe5e5dd1331ef621765251bd60c8f10960b4a8e58ee4b734b6c8cd268c9a63539bfb1bfe79eb249fc4ba9a538aaa851ffd4f981f1c0c99ba1590c553ab1b6de3acb377032e060ff2fcaad24b14eb54049ed808552b1a69e0910999e56916426bb89945bb9daecd85554963a09653aa", "SS2": "1e0eb97117d9ebaa8a2596b9a1a5b4ad52f2da91bb58ded7d7c44ea8f843dbf011df09e347089291501a5022fe693ed7b8dee2e268e686395f6264975ea75c552324664c2d5b81a7653dc68c971d4c6f73343c58427b69ad654de65bc24f01bc113b7dd6ace1ab3ae4426142d624ac12af23173406f892baae76865967a02a9a", "DATE": 16632, "PIN2": 8165, "PIN1": 8166, "SERVER_SECRET": "0c008ddb999e4a4335d528e89407c90b7d63c0acff0550ff5e4fc9f594d1781313f91ee9b127983b78779deac5588ffc8c9f4a374fe09ce2dbc55af3e95807c01bf5a1c827ca2d7abf432ea9cac94f0cc510e68d3f145145050ea45cd220185f0000256bc926b1cc8f8f90e6723dc2a65f547e9154944ea93dc59f2f7cc0a02d", "SEC": "040daa7d15e18f420e517ba79b908b2a317bdaf3d16f931e05cf709ce4d46676bd074fedc28eb4dc2357fb2779f0c028083d8c376466db07a72922040e0ac794c1", "TP2": "04041c7f9133c9c99171a5561a80e7b00333313863c6b95c8367f5b133a461b5f00b9a4f7c687307217055ff687a36df0d48165d4c8d624fd7cabcb4b67b726282", "TP1": "0421e24914375a0866ace11689c54b750b2ea3903f96de3e5262bd142bd4592b9f06bc46ea3e454637c8e9ded11c29078e8122ac86abbd668c44a887a02c075c85", "CS1": "0416be055eb727264cabf0eac7266fb9362bc46811e56a584d69affbff4e86ee272178408a02a26df9bc3b90edf6ea493d05bc27914d7b8a88d601dc336310f541", "CS2": "04007da2f5aa32ed3a970449b99bf5ea3b9f901e6d71484b924e6b71196e094d5613f61219a03522034d94a13271378606c7f4b054f8a9fc5ce251dbc0037fe5ef", "HASH_MPIN_ID_HEX": "7775474775edc1ada71c2f5b7d13cefe74dfdb16a4bdb7cbea1f9ba3ce11eb19", "TIME_PERMIT": "040bc9ec56ad9d56feb4775a15809630f5dcd0bb4a647a472dfb6f3c96b27297471d1cdc6e02bbef416de50e4f7e456d4aaaddf04f413cdd00bdabefd618dd1e86", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223135646562353964393666303739393864626635373966323264333462656630406365727469766f782e636f6d222c202273616c74223a202233363235353836396532383537653937227d", "TOKEN": "0418fa8f724d3e7e690099152ee490fba5607a88792eaa555a54e29d1ba6bdd20207098cd99f00ef52240ac6d080dbe49418a0d2a0faa6824a9c98b7f5cd187da6", "U": "041f5079932e65f33712ab7fb2883272ed72a917c2f2600d96b8190d40d0663ea12369b8eef078f0ce2bfc2cfd912c152c4fb882ca3911f33fa1fb6bcd53c45984", "SERVER_OUTPUT": -19, "Y": "1ca95fd364f6cc5803f2918aae9ebefe0f2b7089f52f0bffbd8e13759ec040a7", "X": "1df45f672e29a7ec92b3df60dd6ecaa46319a9bd0b890ad1c42b481632a68c50", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"15deb59d96f07998dbf579f22d34bef0@certivox.com\", \"salt\": \"36255869e2857e97\"}", "test_no": 119, "UT": "041b043c234825f320815c14641c25b13eac7867d81b52c1256788308db7fa3d2c0bcd312a568397e952571240bbbb543448f13de83aa8e2376238e51781ed0d4a", "MS2": "0f22ff1dce98874b3334e0c1d2d5995f8905946935d145fe7fbc5cfbe776f0cb", "MS1": "1145daba97cb82c95e7a6102431861f8a8bc49cec7dacaf21e1ba3259d4d4369", "CLIENT_SECRET": "04129862fbb7fb5e783b342c71c3800d17412d24e41b4f97a523ffca4f4f540f820bb8b34938636a2e65a6088bb13e399fde215e435bccd527b075a5618d26cfd5"}, {"TimeValue": 1437055596, "SS1": "22037c6c69b42c82304baf147c401df060e09f5d5e830f818e1b703abbfac5790ee34cd96c84b9817b1bf971f9aae0d2f9cbb1d295ef55dd96f58dae7f7e68161806d3bbd5b7c84324410c800d3edc18f2ed1cf7e95e7449264a05e2d95d9d2b16a682b2ee6f46619b39536bcb6072a2b4f06825af6a9b092e6f65cd5de3fc4c", "SS2": "1d75b1fe6e1da2969d728036b4586a710ab908d0ba7e2245b9dbc32e184fc1230426f5a604fd26c2953a54381ecf46128c942efa4a867cffd6f61c7a9472ee4f0aa7c5cf16228cb4ac837ad871c3a744e8af665a8b242fd8fa6de2df5c34ab491a928adf87dd1fcab317576f1359bf7eb98323747d265d04c95b9e2f28b0118d", "DATE": 16632, "PIN2": 4979, "PIN1": 4980, "SERVER_SECRET": "0d501a2c189e3962acc8ca8f0dcfa564ad03223f9f67ae01307ca974ef65b32b1b7da892880dd6860b21a7ec1c13a161e8b021ce1b0e9c958132ff1a5abda32811c197e57208132f671bf736e36f043ecbbcfe464ceaba83b609e36febcfc7c92067a8ee54e4e901be73e94a1cd78a10e1dd94ed5006208a6ed6e1a4b52a76c5", "SEC": "041edc9daeb8e0f3a6f2fff344e617b5dbc18a06d2ff583183dd8c52e6941d1a2207b678b31d168f24b436ba8d86e39017c8722c9afef8fc5701b21438fbd5da49", "TP2": "04179996a335e4fa309dc7d7942cc36401be9be08969da647943ec405d27f6ea4c1d911306eede08194d505eab8c7e9016e6ff99888a5dbf68465841e54cbfebb2", "TP1": "040c51f518576723b42a52a5ec32229282bed88fa758be22f310776dd469760c71092b25f980f531a855318167273653cc692bf641d3303a22b23e1f89b5d737cb", "CS1": "04114180651115fd82c8738a9c546c177709d2d5dcf809a13e974b1c3229dbed831be4a8ed1329648731230a615891eba7c4ab99093a1f7e1be6f0cbc909309aa5", "CS2": "040c3255e24dde4c72296b4aaa5b3c293815b2a0524b6a827e97488102c2ce5047230a25d62b3aa47e67db35cc6e69a6bb88cd8cfdaa7e3b5d7e7cdd2d659c565b", "HASH_MPIN_ID_HEX": "d09834cf4dda3e0dbc867486426db3a12ba46e1694f89cdf56851ba3333bc93d", "TIME_PERMIT": "04120790f4c600c9d97196bfba5d240fbab2ba27327118587aa4af9c98c5f441ee1372d43d6e272f839b92ab188e8f079637fbc2ecefd77428dadc92177f323a3f", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223166633834336432323136363962333065333235303438636238663966616365406365727469766f782e636f6d222c202273616c74223a202237323134346365633933616634316363227d", "TOKEN": "0411a67cb4a228d908d87d88937601067d20f6fcafc2eceac38a5d2562d0f386ff1274c54af803a65dafb150bca7f16925f94ef809036ddfc7d557dbde11c7c6be", "U": "0403bbc39da870c5d946bf74d2ea9c8adbd98b1fe85c45aced6f661ef752b5b448139bd3d69dcd9343cf5d5d08f5047954ce0d2f7451ba291abb16e304b04263cc", "SERVER_OUTPUT": -19, "Y": "16be4b9b2f5619dd911175999b9b0fea1c7138d3333bc0af3a3b012e667626e6", "X": "06e1700c56a2738b9610c238c6856b4b1a8b36f0f55fb8ea68db182650a7c5be", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"1fc843d221669b30e325048cb8f9face@certivox.com\", \"salt\": \"72144cec93af41cc\"}", "test_no": 120, "UT": "0409fa49e0e810ac318165dcf7523a3aea559a49a8bda7db0eed493790c888bd232279e000c68255912d5cd5aed7a4263b3a2f66eb7418f365d98dddb4c495b5bb", "MS2": "0ceaa7f0a9d8d57620a7166d2c1d8f1c4feabb527ee9ac00d59d3cff0f97d828", "MS1": "069bf1ad23c3769a89983f7e997d85810a2b948c677a504e49d0b65a177507dc", "CLIENT_SECRET": "040c20bab5ec0b3bc309e9e29d0ca128da9f9f3d42b1302acd2b8c0110bbec8cff10151277e46ba3a450e42fffb38dceebebbb31797a4a35f649f9db993033e6fa"}, {"TimeValue": 1437055596, "SS1": "1d0b45b6fdd9582368922c8f1b0964ef0aab482aefe18df6f6735e2f8805324015a5d870168e3e1082d58f7bdfb6ea829f53c4510563c35d54e993c6c0b0419b0b91a460fda9aefe92a6633f4e18dbbef476019e7c8bb5e8e21ba627438f8df01acacda6af077dea85780b3bd7df0065358f3c1e61e77ab0905c7a651e36a351", "SS2": "1320c91419bdd98a4f2ca3b36ae3e7eeffffbd4f009e04e0945a87eef8223dba0519332583a7763b7bd81c2db643eef2ecdaaab187a728bfa09cc3ffe572b2731758bcb9b1715e811c1e798236f6d7e7bcb7c852fd9fc2b32f77fb8a2d8ebcd816e5d9b9fc2c438cb6ac671a364a18d3bce932943b243aaf8d96a0460d0b1e7c", "DATE": 16632, "PIN2": 7421, "PIN1": 7422, "SERVER_SECRET": "1c532c92efa196014c741a52e32bbedff5bc129c90e0adea06465eeccb1d59442015937603e399a2f23f47936d70996ce9f714a15c39193a426f157122f449200147e8a97c7da0330e311c7385485cbb91c024fab3e63aa4435550c92036cc8d0c4066a1b338aaef2da91a2400f563962ef6884a7229e295394a34634f12f2f7", "SEC": "0422f291505276eab80cfdc9d601811245e209ccadf1b08c0662089bf5693af92612ba3acbc0365837fd284635dd26499d2fd97878ddfde22db857e3c6f5cb153a", "TP2": "040eb22148ed57b4a0321ec54df242491cf05e39921f47c83a9241f6a0dc97e9bb1167020fbdb13a8d2d5b0865953a7897820b52f32fc2d3b4e93be27890766a8c", "TP1": "040c594782849e7498bd72cea6cba155bbcff17f1495bcd56ad46689ae93cdd4ac223be994f2c7d28e276ba4b6be157b5c90e902d98fb5bac5cc43e9f1c0b30f1d", "CS1": "040628eeb1edd0ca3848efd182a3e3322047fbb16af887a2a53cdde029305271b008032a1b2a8ad3f9c959f48a8bffcfac4c717954eb3e7605fd7cb7f63d1158af", "CS2": "0408c7e2a89485f6a28c9c5c8d3c5f7f9cdeee773c722796d60d5e34b01bebc0f61fdba196197266160767c6a02d388e708d19abdf0d36ea54e67c831290b57720", "HASH_MPIN_ID_HEX": "54f6633777292cf06ab7a1530c1e7c209a035daefe78d655aec182adb13a89fe", "TIME_PERMIT": "04120ac7ff90bd6fe27edcad5ed74fe5429d47f8baca7fbd1ee34740d399401d5201deed8c07675ac039abeffa2cabf85789ce3bdac91e8533c3bcabbadaa41564", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20226634343137313736303761383265636363633430336366353532373035343339406365727469766f782e636f6d222c202273616c74223a202230633736353135636362383438386465227d", "TOKEN": "0407cb6b362822005b150ef40edb975d6549adb71633cef4be4d4f68ed46102ea90ac53e277ba7fcdf77d6ee4b8a96949a0956066ab3ce95b7bf1b8ea0805e065e", "U": "04227a439b09db1317603014fa480e30a54ebb84b12509313853f73ddc07c836c31c09462f9f2ca9d42aa34ae4d240b67f5a6d8fe9f0033709acae1dc50e2a4bee", "SERVER_OUTPUT": -19, "Y": "03da60d542fc7b07c1e9fd4299999b0436fb036653f6e215982b903a50e4077a", "X": "0aa629b4d621c87b5d808771b142808d87e65767ff24f694aa2fddaba50ca500", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"f441717607a82ecccc403cf552705439@certivox.com\", \"salt\": \"0c76515ccb8488de\"}", "test_no": 121, "UT": "0400ab99d014f73b2d2adf23e9bef97d4c1bbf8ed95d0f7e4727a30720763d59fa0648b6e554e35be019bf64dc15fdc15191f9dfe58075f0cdcf41a6e424929fc7", "MS2": "1a417e81d2f3eaf1e32dca27c99b6333ae22e883220237a509a7997fb534a2c1", "MS1": "1b8546b7d38cec1ac8821852570235e8d531d8a1a9f0fd2f949c0b7a5d0a0d58", "CLIENT_SECRET": "0407930c78efe96ed6f97aecd52069cdad2eb49a878c28164a70d06cc99f8765001638a76e175877424abe3253c000c59cc19034ccedec022b18a85a3112d37185"}, {"TimeValue": 1437055596, "SS1": "0e33f7e6e974e6f39661e6c0c1e8860d31e370be0223faf768e87e4f804f98f60ba76b5fa373a021416ce3a955f34ee8eac5b88623e63ce30006d51a04a6200c09003262d1fde078bd9bec6a680032a9dfbb22970ed1c9d8ce56423b6107b78a157739a4bd8d9474140e3ab82a2b045af2a99fbdad8d56f532ef0b9b98285d6c", "SS2": "0d00b496394e216dfec4253977c58454e7d5457757f91271cf3a3ab2476e6d9b0248eb70dda0b4992f748e78ec4d547fab50d711bdac72a3f347fa05722ed8f51f13cc1db9a9b79620c093a56690e5cff2421583475b16e2fe5babbbca5ada3113f95631c8a53f37c16dca894ecc52ac06bd5d84b536349cca23b24959122a8b", "DATE": 16632, "PIN2": 4596, "PIN1": 4597, "SERVER_SECRET": "095c30782d2b51a5c8e9f8751409c1265a033d18ed13cac2c86880ac3230e7821f5b649b65d707c4235babc584726def1868a8e8271960a58430b1b1b087a3c311aba082b445c06b8a26f8c08cc4e7269a7822eaf0b9dbb430de3ae09bdb34ec126bf168989dda5af0069b9eabe39a2f5dfdeefde9bd030661959df640447b4e", "SEC": "041ebc84f3d71a4d868959dd23c1a519385fade0f4452754cd769870081ee068ba1539380f2f2c33d1af47f32534b6026402137e7b1fe3b6d0340f28998d5e8d3b", "TP2": "0408f035c676669d21281f02959289c12c5fd828eb8468a8013cb05133d9cb26b9050398666b9ff66f80a0d939bbe81eaa9373d375b15e9b14610b8accb88e73d0", "TP1": "0401ba7cf51a60d34ce88acd9ede0beadf402d431b87066d466dcda8637889f96e168cf35d823fcbfb8648f9d076d0bdd1c0101c4451930e7dc021fdc826ff5ec8", "CS1": "040042f29791ec2a832fba2dde8d074006309e6f06296aa4c9283d9c16534e60fd1795c21f07cfd5954ce93510a01c315a06ffbc9b0c0742b9998cd07a0e477363", "CS2": "041365dfafdc8032f0b99547983a37b87c39062e5a92d238047d63ce5ba53d68a72347f296936ed6a141a5e09b650cadbaf4a69d218de9719e12a4219261d79874", "HASH_MPIN_ID_HEX": "7a73b6127018bf5be655139ec538f5c36b6217de2babf311f589f890d679d174", "TIME_PERMIT": "040c670f93e4e355ee048d11ea10bd3b76ef452e7eeda7a87958fc5329e505dd581e1bf3a9aaacd79f89baffad9cc8d66356abc33e8bdc0884e6a707538f69181f", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20226633633164623865366532336163393834636336306466316430653762623166406365727469766f782e636f6d222c202273616c74223a202237343837346162336634383835626533227d", "TOKEN": "0419e752cdfa39d41e7e354ec59004771193a668494b74681c3fa7c03b972a598b0a581a60409e27668fe4bf3d4eb1b303170955e64bb2e6fd05bf082c6ee71647", "U": "04118a4971e789bd3f02d8f87ab9f0bdc262f504219396bbd18b50061806643e1f014ff9665ae7ff84db3b0ce7b9f7f7f8161f650930300f9fd43dd366b6ab6298", "SERVER_OUTPUT": -19, "Y": "1063aebc073feea70ec94b72867f082aec4369de0a6ef5822201fd6af179005e", "X": "0aa849fb7881253fb4e613617e4f0b4e7661902c5c77f9326c5ac1771ed4e5b3", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"f3c1db8e6e23ac984cc60df1d0e7bb1f@certivox.com\", \"salt\": \"74874ab3f4885be3\"}", "test_no": 122, "UT": "0410f8709247e5285576b268abef50514dccb2e887114a3f1070e146e0b420a7c716afd2c23727b4a84a64b92a811732ab484d0952e51831fb067b0b66b5e67b85", "MS2": "1e920e0d0d1a3acfc8a6a0509853b27902d5fc24296aa203c8be822e56d8a0a4", "MS1": "1da089dd64d71e13b68234949abd1a9073fc00bf76ff4b7791cfd89df642d98d", "CLIENT_SECRET": "040f203584e1fd6c996238bc0e252e0eb908f565a4fa4233531bb9b0d91a08e4131d7416b707b8e8e88d4ba0c2c34eac26e3eb233890298446458c70f56abb48c3"}, {"TimeValue": 1437055596, "SS1": "1d9c276b2c582dbf8d8fafe6c6c93dbf494cbd576bf0559b606a9b87c4da3b5810949cfa11d4ca44c1b30e27f06c50da74b25c66006c8100432f9aa9dfe450bd0b2f9d51d68298873a980743426809d331bcb6ab33d5beb3f288b1ca976e8df2138c7a48e19e32cdfc06107211e121f0e4d187e542c8541fa7d75d58065866a2", "SS2": "017f4586429ea363e5f434b929dc7ba6a5f2e4e81dddda0c1495f170518b55be04dd8f38ab8474457a68afe127adeec462a5f8b3b71bdb25b7a20042e851bc5e175d8bab7d5557ed6a467c10132106b812ec45b5f9bfa89cc88042a401d36eb505f7e90df32bdaa7ce72e90f5b9d52bd44bb3a147a939fed601cb1919ccee0c0", "DATE": 16632, "PIN2": 3000, "PIN1": 3001, "SERVER_SECRET": "152467057551c6d31c148c590e68a42e7c0aef3eee2a420603cb6e73cc1310640d152cf83ad2c070766e13dbd5855e9066b2fc4d23cf5657b8daf70313f096b1110ea73888da5e53f6732539262903eb50cbf8aa6c54a7384af34a5efd374a4619bde1b9a8c5ad2e6976ef0fdac5b398ebd2058724cba22f037c90dfebb956c2", "SEC": "04014d1cca472b284623d46e8b7c4a0d8c4a1c8a110bc959be0bd62cbf8e20d76a0e17e7864bbd7d5d9e61e7bfffc42bd509b2f5281ef06fe95e81aa12fdf0ac15", "TP2": "0413b29770bd44e423b4981131081161e31f0ac555b697306894fcac250f8cf4641257494fce343093dc8f2fb29e0664061678d5ba4068210310b660b3df9e9746", "TP1": "04022d42d58c226147ff7297240f5ffe534a153e692052044366fac5031a1ec2f91dbceb047c0270a03250a295ac6e35ff66c53af5f941f525e4548d18858ebdf3", "CS1": "041b6618b11c0a05d46bd3cab9849b41b7198e3d4b13e10016b80f86ff289d15d821c5b212d7f942d43fbce24ecd183051635dcf1903196128e38520178e22bd3c", "CS2": "04121f04662270bc9f17b89f614e580390460a85c4bd0693b8d52b7b9fee49bf341ee3eab40f58acdc15f7fa0c90639a9f8e9c5a41d90d348f7f2edd8328dea3df", "HASH_MPIN_ID_HEX": "192a075b039c0cd9e872927035761666d2e702c049f813fd91c757123f87656f", "TIME_PERMIT": "041bf4aa631389073a9ec56fb731ad141cf5cdd804d4df8a2ffbd30bb1537f63ee0ac264ef8487c3c8d6a9370db1a708070541cf8cc96ecffa8b17291e536b9d97", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223038656561663961623265353137666661336437396636323530613935323362406365727469766f782e636f6d222c202273616c74223a202236376635383835373030643639313136227d", "TOKEN": "04119daa0c4658543e4b464a08f21e2c0ad2f033ea6d24034440c6cadbcb4dcd6902ea7615ccdbccd3c29146f74479b10bebbf671bd37bdeee7edb4190511b106f", "U": "040d6f7393c9c15dbb4524bbd0c4ed3920c193234cb817fd252e8ba3e20924bde71990c9469e92b27d75949a200872ba543a359adb287560d1aae515d26f707e47", "SERVER_OUTPUT": -19, "Y": "1015c2c812707b6f3d4f76f86994aa34fe279ef6569cf187da11cad2bd88ea8e", "X": "11fe07509d145bbb09d4d2986dd6f24044c5893ec09e56ea7406543a91d1ef74", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"08eeaf9ab2e517ffa3d79f6250a9523b@certivox.com\", \"salt\": \"67f5885700d69116\"}", "test_no": 123, "UT": "040f5dc70fe57711605e925ce4045dc7a42010585507757d7f1b1b6fe5f596a76e2044d1e980de535b2edda2d41c435f6168de69826080cab11537ce6526d06893", "MS2": "17ff2024651cd30d8583a8b91d047844166496fb35cfaf9a973c4e6943c75887", "MS1": "078b33124e766a05ad6f652275ad543af48832ebdaf9ff846cac764b91912f8c", "CLIENT_SECRET": "040affffb64d18ac02715f54534e91fe54b6fc2387904cd47c2785fbaed889248d0e299d960a0a72d5765c07a123ed6a3a946fe97c9f6a7b18ec9a42e5b033dd37"}, {"TimeValue": 1437055596, "SS1": "160589d88c35d49886f12206f3d937eab08042c1584e17a33588970b6d6bdff704f72fffe240bed291b1af8d94072bf3652e6cfc16dce609423eab339aac06191b8a764834b3a67893c1a2249dc8acf8f2c76874f37c2fd53fbc7a33e6f5b0d210574b5e572c16ea2fb935a62d6f391202937e4ffe58aa9e6b6802902f8ddcf4", "SS2": "1ab0b63e6f892c7d41171cb07d2471cf24ee0ca9b4c1ed5720ba94858083da710c0520f65bc7f518c8717bb20a45c5c5e9827baa98170aceadadc56a67747b070825da7036974a1a6e15ea74fb2bf8a45810c17b91167edc5e3c148e01becd7414c105a4cbf766f0ff1897cd428495e2e471619fae340802caba8f8b2831e338", "DATE": 16632, "PIN2": 3937, "PIN1": 3938, "SERVER_SECRET": "1f2a7fecff305aae4f7c923a42b0991afeeb4d84f6e9f6449c2a1ac6f71009991ad1dd90e3eed34a81a95cbd1a620599fd7938e9c518bac426b0765bc9f412450d96605522386678d357bafa05cbbdcfe623de8f20cd66f191dc7edb7acd7c7206a6b980f7f499a4e641d3ffe217605a55a0b9363792513a0457f3e667324ccb", "SEC": "041804b95d713a8c551c2d2b4a617e9cbc73b70c9ecd9bfdf9a919ca8b581df0f41ac749c762c5f0d56dde6fb71847830a75221d6e5dc2d57bac62a16a52b47ac9", "TP2": "040d96c9573b1bbbf7edffda0d012b08ed9f4806a8fa08c4fa4614d57a8b012185044060bc1b035294f7edc30f1ee29d2c57fb193df91d2a35329a7045e4c21ce0", "TP1": "041bc746a5309b31288c30ee26c6ae97c57fe912eb75d939782e15f2a49093b5cd14cf8d3ff5a609ba9dc8272379a08703f1002022527bfe7d2efe51b643fce76d", "CS1": "04167ae05e4b7d70dbd8ca0b966814330603ce293ac33ac954279658a4b8205bba13ab86454a7b0a8bf224c51eff081b2aefaae512f42073ed8957375fa5524fbf", "CS2": "04030357efd9c848c9484d6a41ebb16ff3de1556208d4e9bf26fb03ce0135461cc0403b7513e7fb8e15c03707d8ec0a33f9bbb963ac397be4500ff8842998af18b", "HASH_MPIN_ID_HEX": "580418e67b1806fd7c0392d0ad83928b29bcac5518efbfc4e94c17bfb459889d", "TIME_PERMIT": "04172212ab03f5695c39563d1a69b1990a4689605dc070e35a59ff82c0e26ed6a61568695621ed133f0f8071b695d77e560a84f3ceb953ae460326a1ecdb7773ff", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223934653963613564663362393039633065363865653262633435336132383131406365727469766f782e636f6d222c202273616c74223a202262613035633733656637663466653039227d", "TOKEN": "0419eef5eb1bdc7b924200213984e6491dcaa957a5f76736442f1232f960b884e00576c1d8776626e6b3dd41324f141f516d8145579b6b0dcd8b153c65fe47d278", "U": "040cbd59f1e887b79ccc6f938b665f84598fab7dc596f99ff77be4ec7524454613194560cc6027d8bc15c7a847a684f96f8097624ab5eb16af414901962c5c9cfd", "SERVER_OUTPUT": -19, "Y": "00aa78fe681a8728a87eb11d4078b2ed426c4ed91302ec5865b5fa6a12b78c1d", "X": "0df0a2ea7e2dde086f027ef0e30e5a6c66d9f80ffe599a86edb362330bdebeed", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"94e9ca5df3b909c0e68ee2bc453a2811@certivox.com\", \"salt\": \"ba05c73ef7f4fe09\"}", "test_no": 124, "UT": "0420dba4a1e10b4d0a339c854030d8b9fdb7014d50b6f89bd0ebe4f592de1b7f4c1c0b5c47bb0d1110282a25466cb60fec1a9a0d48bcbd33bae798d96acb767055", "MS2": "1e9c5024e1bd7c9230652a19ae5c33c300b628bdd028e658bfdcbe7e23c94ecc", "MS1": "09ca23c31dc0a1d96aefff7cd478bc0fdfd5d5b40718a8b70eb31cfed353e786", "CLIENT_SECRET": "040a0c564b4735bc2dff6940fad2180399efa3e5877de6a8f80ae19b2dce260bd01b282bb017ad308f81c1f6a693f19139de51648ace1ad2c042fca6410e861ff9"}, {"TimeValue": 1437055596, "SS1": "1eaa9ddd88023d691895900d8b275f8ebaba9081ecec5b44d019cd0dd1e34d291c0ff2c151b293d72355b4cd764279c348c6a24112574a8fb57e81e19fa0d38c02b32970c613f649ae8c424dd96ffb268c70e25c74deed78fcefa6ac5f37eaa8058e2c457ca09598d4542826bfba25c220e3e906687dbdca605cd37d275419d8", "SS2": "07b80bf10f1e7f8a65bb5a8e41ec1144cf33e5f9f83813dde3ede7e3b78dd2ad16b47483158a9f515728cd2d4db8cc623d6687c85b5f333f9d78212cba462bec0b2b385ef34a18ff3838a3eb54240c31246620fc4a9e36719f4ceea907c9206f0e0789c58d035ece82aec2123c458d29b070db9ba9ba71e42bab79b524aee146", "DATE": 16632, "PIN2": 9673, "PIN1": 9674, "SERVER_SECRET": "15ea18c713be245999317401d6b88e370a6db740e1b95a03a3093b076ed516ed235942b894364152576fb310fe7cc452ed8526a2e25f1eae9c8e7337cf03e616037b84e2246083bd0a17e2938da5f649d97cfae53cc48ef3ab345c63f945980a09d1ec7975c58f132a4578fee4bac4c78741855466536a1b2a4b832856307fb6", "SEC": "040e7f13f002940096ed243a810928e7f66f0fff8d6bfb86c64d72265e3db91e311aae2dc75cd9946356ccd772122a314d85ae8a2cf072214a918b6f8787f42026", "TP2": "04070f594455405651ee98163d38ce42eca79c8b3bac44b14061e76cb9687941ba1c3a3d33a43248f152007860f52ca2fabce392a40dfbc218043881d7a0411a2b", "TP1": "041415424b058d14bf8212ccb96881fb8e8e8746b6cc018cb53f83e649cbe61a6a107297a2fe987baecc208d5e9e1278ed8902add03268511e24e7eb394d1b854f", "CS1": "040e7dbfedd63e4e8063432a45f95da8cee3bf793582dce8cdcac39e3f2cee403e0842e64cf584077394a1f5038f5fa8e70b82e00cf63b0876e2c02f86b3263708", "CS2": "04134f4a3bb51196c56f0debc0770f773335f69c77a4519693375ba88d1c46fd3b15d8ce3bdfd61392060291c136b1d34cbc6d3fadf7934b4b7ce8001451bb61b4", "HASH_MPIN_ID_HEX": "a360e862eceb734856801633fedab0f904e853271df4cfb5fd913dc8d157adde", "TIME_PERMIT": "0421ad8188ceeba263c22fb10c9be6aa496735ec97a9503eb5836f7a90278ef8be0ccd3ed95a55252108923805ff8eee985b29f3138bfce7417a565f8d14b0c3a9", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20226638353430333830363535366237346438323031623235393639643335653139406365727469766f782e636f6d222c202273616c74223a202262366331643838626239386664666162227d", "TOKEN": "041b36741f372f875ec5743355acc89bedb5758cd4562c1800586114505a85523a0fa3de450a42ead5d7a960d7a2131e6e0795c1c577e22a54e02de19b714d648a", "U": "041c4443431837a11a6222deb40f658ae137260723e4968005d8079dcad2da34990054d83866b3ce4042f2cf607ffc3beb30a1a6a96d4612a9f01d65a5fe2e27e5", "SERVER_OUTPUT": -19, "Y": "23148e1d3550135e2b4ecfdbcaca4e9c017277c1e77d547fa98ad77cf299e16e", "X": "20c4f42c4400e0671b66cd55f8f2553f99efd805f8fa16c2348842378a42bb8f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"f85403806556b74d8201b25969d35e19@certivox.com\", \"salt\": \"b6c1d88bb98fdfab\"}", "test_no": 125, "UT": "040984f82bcb7b913b9e4b0e4ae3c297687a3fc19e6496921789d823f344f3c2f51dcbbc5d376096e184c0f30da40d856970f1b039a644c135d07af3c77d1bed18", "MS2": "14cf616ef9d7f286bee5e41918f30a881942a25fa90a3982360071938f1d6b67", "MS1": "0930e9e27853951349f3d898e290931b79bb17ca89d651319fb0b9b7c4a3690e", "CLIENT_SECRET": "041a8350a701eab4261ac2a9fc1c914a8f2723ff32778dfa817f8af8d84a3057591e2f41dc2100c40b2262d1751555a04b8b55a38f97808b7e14a5b7997bdd8c93"}, {"TimeValue": 1437055596, "SS1": "1b842454534e5fe75a7131d1ad376f14cd5a11dab5342f4f02cb1e165fd1925f09d4c507bc4e4ab0eecd7a279895eba1e9a383f85ad3012d143ea1e422e2ff91104c1c2b2148cb316e987e80969ebfa2b93cf1ae0008d04918ab3524eb6916791295f5ca6ad78e0395f3dc042953148af3eb83342185b2cc3e8d5949a8ad6328", "SS2": "1690d324416788306c9e933e91550004a4e45185f6d950bfeededaec22c52a370944a7ef9022d6dea51f0690cbf925f788fe3d40fdec694847285e565d365b150eee8b405266687d3d3ea565e8a11b3de2f60f6b8f042adcf40212cc584bc8d71bad38a1a71d489c7a6213910b8051703359014efecbc450f235bcdd1419afda", "DATE": 16632, "PIN2": 4986, "PIN1": 4987, "SERVER_SECRET": "009b724199855f6c492648a60c7b6e08c2fb4264f718b45d78fa31aa62845bc21956d565634228045cd71e51a05b7a85a7a16a2cea343b1f4544b25a3cce9b471136e02ad9a79aa4d47f6098244abe058d0702526709fb2262dbde96d624fb1a06382107e9e172aec9e5502e395905ca0b75bf75ee58c198adc3d3ae1997810e", "SEC": "0412e2769617e157d667456bde4d0b1fe6bbad7cd928b11263da82e3ed0bd9eb9617496e848d4f3a26aee95c38ab3bb9c39283ecf803a78939eccf670a773a9078", "TP2": "040d8f98e5e8820a6f9a8db717395f7c9ccb30abb94888d63277bc1b863d28629f23fa0d79f62007f10813171716669dae793cbc977aab320bfc6a795088ac840c", "TP1": "04168a3a514b705878a44335c45b37430a9100e5f07e5e9a408cb5da9c50333ee11a3320c4ebd10a17ecf007454c5e0ab6a3c2431aedc125f12c44809ae2fb7dd4", "CS1": "040e19050dff4538cef86c0802d7fd1a9e9b56552d99bedb8c9a52c7ea1de834f40383b2394105259c2744b70a698576ab2daf2be3409c54f8017b0974bd5d8db4", "CS2": "040afbc9047cad6ebc29b8e68ce25510b9bd1d5730664c25c4aafdbe287d3e2f951be2b3fa166771f0be154012d90def36e42df01b8028ae065dc4e96f0447b132", "HASH_MPIN_ID_HEX": "5f0b7baffc2f4c62c39cff723fdcff82b245853b840654f0cb85c313b3bb86d5", "TIME_PERMIT": "041ed5d46ec2739ff674cfdccae0c2a694dcaf1d4ced7e0aed63bd6390458187cf1c1703b4dd9cdcadb85a101d9be7d02c3d17c9a3a1e8353397877baed8d5ad39", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223536666564343738376632613638623762366331303638366461303263373230406365727469766f782e636f6d222c202273616c74223a202238323232396462633766363862626433227d", "TOKEN": "041c0c1e0baf81088292ae3999258e31b00abfb0f430da121daacc0a5f824512690570a726114913b3d5ff11a3ab159895bd69679ae7aff27337b31a35286c9145", "U": "040149b2fdb642d6752dd2f7495c1ee43f1ef88829b750ebbe6284262fe1e1c50d18795c7300c1437694ec4439784ac88aabb68c3927aab37716fa875f926a4a0d", "SERVER_OUTPUT": -19, "Y": "04c578ee20259d0dce69606c6b1756671589ad4dd33ee4920f42749f9bc3c1ea", "X": "18ab4a26c7b0f1d19a33d494068034b9c25a0d9c90a44b7a9a3975e01862203c", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"56fed4787f2a68b7b6c10686da02c720@certivox.com\", \"salt\": \"82229dbc7f68bbd3\"}", "test_no": 126, "UT": "041770597c88d09d67b6b5e1ee97f9c5fc97ce7860e938b3e58065cb8545c6537303c70f5d21761a22301462333b6327bcd83587034b20f26f2c0670ff7c8477ff", "MS2": "190520c461c166535abb701f99c87645655855a7dd12d8ea3fca038f6c1ec2ca", "MS1": "059c8022364d3a300f4b66a4622fbd923b80c32cdd8498371820089fbb8884d7", "CLIENT_SECRET": "0414e9bd1fe55b8b9844c3d5632aa076ad0588590fcf1627610eb9505a04cc45af0c17750f351cf385ecffe30739e10f1cb8ac70bdc2ec188d9ecb34b76c64396d"}, {"TimeValue": 1437055596, "SS1": "0d9ee897c7440f4e3e33a6e849b15f9f7ff8711f47a12f3407a8953bbadc5aa31fd54f248b75fe8074c9c2504b7d9a3417c41ecd304a78c424d364d26ec8e11812cbd6e452c64912bf5cded24ade92dfc7a90efb057ed0d81ad59e195f23b98e03fcf59fc8f4854a1f759ac72efbb8133ad80fe4d975d07eb1d32b42de952eed", "SS2": "21928c90fd6021e3f735e6806853eb33b3dd0c97aabb8379fc023095ccf4f11f1266ae0434cbb41c94fc4acf33b567e963af08c368afc86665118c6c054c888219532ae52657dd2d28dac87edd7899e1163c93b9bcdeeb516e8c6178e2e357d51bfaad528a3b002e95c7f2fa4293c4534015c75362a38854cb371c2ca5bc15d7", "DATE": 16632, "PIN2": 1236, "PIN1": 1237, "SERVER_SECRET": "1099b3b7d7a57510b68194b32426247fcdb34caff60a95eebb41fc142760183d0fe2acd485893d8fe6354b5818b73422213af83d8e670631fa07ba95bb4d424823936bde8b6e973f5751619a42fa8b3da1f9b782c03c1b0ff7b864a96c206e390f8ed57b3b6b9955e731238d2b0016db68a4d72c717f4a26ee8a6865e0751673", "SEC": "0422485b71a27c1515f7fcae7b9df60d1b6e1795369fb1e8eaffc56cd65c5192220acbc5b58c7750e6ea92cbbb4517d8553a5fd56b151c15be38b88b8b974e589a", "TP2": "0400c4a5c12f1e273c3395df1a69b078ab35fb86884b23d2ddd2b6d550f1d2851b19faea972e9a5e7f89110e6a98a7fba5741d3847091cc2a96a77fb3c866f7039", "TP1": "04152940a7e521aabc8e2c46a6ddc8ec5fe29981c83bc1f0d6ad21eaece288888d169df192b5ba3a4c0a4d1a654e38136bf71b23fd8b8391d6166f6ff5f051028b", "CS1": "041f043371a43c37087a539afd338b052ff2bf0b34c8eaec8c3d07190fa5c767360c021141f8d2f75459a433ce85a3db8cf5897cd8c9991aaab2dfc888ce429784", "CS2": "04211a364ce52b9cab55e0d98afe242fa50878a1bb14400d47cc811ca73457e6fc0a45afcb72d29cdb6d65f77f00fc0dcd3bafac78dbccd4953f08df962100b981", "HASH_MPIN_ID_HEX": "c65b2e843262513ee6a99766a760832fca68a9151f2765388893d444771e16ed", "TIME_PERMIT": "04063ad2375da124dbb8b5b719f71297175ce7923b4ce399ed862d78e1a305a119225d9e7f8b76c470e258b3f96e85d57966ed6245eda8beb3d9c04c9735762124", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223433323164306530326438306638333065613131303434646664353065356365406365727469766f782e636f6d222c202273616c74223a202232366465616432343233666131353463227d", "TOKEN": "04203f4b20c729c94a36268ffd747d22fd9d1a2993eaa3b62b3f6c506d1f0f21170ba18dbf274914c9c9532c9f7ca7b7d2731378532ef597ec355407b3ce8e106c", "U": "041309c8e7cec4b853de15c4b37d673659619bceec1f798f72e93a87fdcc10e0f511c87eda0460840a705e0028ec98b7f2df68c4b633c47c1f99bbf204e516ddc8", "SERVER_OUTPUT": -19, "Y": "1382473c84fb8d7820586fccebfa22895e4ecb97a4fc97569519db6cefe2611c", "X": "1fb0bd6044b84edfa87e40b43c5d41dc6431fdc7c30830cee8211407a4c011a7", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"4321d0e02d80f830ea11044dfd50e5ce@certivox.com\", \"salt\": \"26dead2423fa154c\"}", "test_no": 127, "UT": "04143df5a05f26efcce6b97aec17d2ca4febd0786359a4e4b04e2fb36bb252d2e00d7b889b69b537e47598bf559c4edc7b7475fb42d04054305bf94b1580fc70cb", "MS2": "1bc90185680d58cc1b924dd2ea0a792324b623ee3d03c4c5b03812257f673372", "MS1": "2146df6b20a177484a541b76a64d18681193cf55cfea11384372d7e353b4fcdb", "CLIENT_SECRET": "041e4291d11bfe3d40b98573d2e23ae333a72d412b8973d57295daa1d52423eed31d6ca51f56bf539572d7224b18998c6dc548525b5cff96ca293a37b53bccb1bc"}, {"TimeValue": 1437055596, "SS1": "1fe03b5870e947ac498d8501ffcedc9775417241ff7e26382c9dc980588787b311a57ac03e04fc0c2f711c654dca4fe7cdde207c30f24884df6c23951141b058169e191bae12e2dd3bc0707b047a6e95f2bd1a0d31cd077bea25932d80adb141082a5c404a60f3d610f67bbd767158f0b659ba7ce05d2c500759543402b4de09", "SS2": "0cd9d588030180c90da7c0f4c3baf396f1c277f27505c34a0c51b8eaa2ea177319a3b5fd0dee55e5e72d661572fa04e849198e643b12a54d8a6c03ab7006895a0b6a8ecc57fe23d017008db5d8424c4c887d26065447a79611d3932abf61ddcc06c9eb78d4c7e5aba26cb2606406a325874ff8c43a9158d3c6566215d091aad7", "DATE": 16632, "PIN2": 55, "PIN1": 56, "SERVER_SECRET": "1040209c4f29d46b2ae9871280c45da5b96cce3a74fa13716486de8c802e52d51fedeba55d39b379fa9441bf26c7bf0257b9d0112402a374d4d21c46be99668f143eb80a7e7615365e2347a5b22a970126e0c364e357914e9e67eb688a8a47f70d06315b80f9928f3a2303499e70e72361a11af9421b7f2f56304b77a0b0d3fd", "SEC": "0405b5c1628e24a1a96c9814fec2f577993b9914aa62fca3a51edb24c4786d31471db7ecebeb6086719b7226c26d82d53e85ff98cd8b90f4733bcc492cd1935dc9", "TP2": "04038a85a924206c145700b3264f847c7ca2adbcfa4129e7f116d79b5945b70b6901e2d9bfda09f52041b1fe901c055c27cceb73e9b1578742cf8d651265369b55", "TP1": "041a0c3435f79edc84df147f8134b100df974710ebd936320b2f15e0ec2eba3e641e96147bfd7c64a6417cb0df4cf4560fe54e1acf6593d4a45ee72bfb61534325", "CS1": "0423b602a1ef46dfad05182d4011999123a9435110bcbf6d11194c75cb11ed8da514da78a1618377d88d3be5b12fae36be12528d444f2ea2100e4bf4c424ebb0e9", "CS2": "0403f13fab0a604554e9120c35e59e0498a12ca904cabd87a633ec9049ea201656133a525a9a750f1e70f6562d0fa7f01aab11833c6302b20c4947aa88a7e461f1", "HASH_MPIN_ID_HEX": "eb91131d1c22106bf452d00fb09b841adf5d4234ab4b89f02ce0e1028bba8a02", "TIME_PERMIT": "0414dfd4f85da8272f6a1281bdcf04775e23255f462dd2885684561849308f4f3f2366c23eded7abc538edefe9471fb48b850c13d3bd7b658ab42540bf296e8513", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223133373466316434393534323532633430646666313539666330373935626366406365727469766f782e636f6d222c202273616c74223a202266393439643436396339373866393536227d", "TOKEN": "040534bf82631f2d4f5bd8a3e5b791ef571cbe7cf08562121db8d590b5e1ffbd740cfbb27f86b213ad510227bc7c5fa94ccf1e565d60f0df753e333a36b6ea30ff", "U": "0411d2f1d33866fc69c01e7a4a12eed8f0aa5e6b045ec8491475c25b34df3b299f029b2c26217c128fb1d702dd311bac2db091add49bd175fb7f2a779ecf54ed61", "SERVER_OUTPUT": -19, "Y": "1981cc81f15b383b5d2e3e44d639e3b340d037ce64ceaf0ed84e54b6fc8d6297", "X": "1aeb6981043d3a2a8e1be7ad19e01ed9641a219f4b2781440d4e782140081973", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"1374f1d4954252c40dff159fc0795bcf@certivox.com\", \"salt\": \"f949d469c978f956\"}", "test_no": 128, "UT": "041da33bb00a5189488691469724698a7a57f3db53399cb4b7d100d647421ff7d6230b1c1aa3ce3df70eacdcbd70c6d23cdb962dfddd433870e196ff5e9d5fbc1c", "MS2": "1883f65289af52139578990e2619f71e62cbe8577961a127e22b867d2223be2f", "MS1": "1939bc7491bde9cf1a5d1a5faf7510b720d7868854e23c648d1971d363b47dbc", "CLIENT_SECRET": "040db8019dc7ca503f2af8e8424b7fd8dc2d5f3c92b9ed85c163808919fa8f0cec0d290e9af46e37dc72514ffbf78fe6f9a985f3296182c5d60ec0277e022a0c47"}, {"TimeValue": 1437055596, "SS1": "1cf3f75331df885fc0a9533ed1d918b25c338819f37651e5127aafb11c9d52e20a639f86e9208e05a2a2ec4bfcc8b28cab5b0e607d57a64bfed724bebdab95462375473d9c1ed2d1810e0418a7fdc23f0a2d7d66aea844adec778c877b5142930022fad882fada25812b850b10c86afeb9d8677a237cccdeeb8a1532457b2c4f", "SS2": "0cbe29bafbfc4d1e65623ca3f59e19db1dab48d01af7519fda7aefbe7f63f524159c2edf38bd7153554e03aa3fdd0ae9657ef23d1cf0024e6d05c827c8432e670a7faf18326f10c8eac5fffcfbdedf1c1c80aa778513d54f7d8ea8142ea14dc31b3c091326cc28e66e3aae7398398af268200da798bd6d20c0303b06f6f279de", "DATE": 16632, "PIN2": 1543, "PIN1": 1544, "SERVER_SECRET": "1d0c2f1c188069023594100163913e8ba5ebbac0e0e6f22687eff1280bbb45af14d90343bbf0d7f0c4201e4532a46c16dd2a09162d490f3034bd79801c41ceb405905b97d929e01e21e2107ea2fbec97a3faecd32a0ac4b2448f073741c4efb51022132c6bdc4c669a99d0013140a197a1f18a47d5503858f8c2da26ee919a4b", "SEC": "0400da1e69cc3f47e1a9131effa6e34c91e1425f22409c8a2383e1fe1600775644031d5c3ac7b5aa7770bce3e5583eb047b7f4c64be32269d2a388cafaded02ec6", "TP2": "0421ad1612956ff63d4a77a4a35c46f7abf7dccf98df96e954470c1bf78585fca7215dfe1f7672f2da624ea3d8328c82dc6ef6f27f280966bcd0c5c837df74caac", "TP1": "040aa1a143c660bb4e545fc14f61fe69e8eeabf6e011517ee5f0c141cd472fc37c222d98d98b21712b750ed4457533a6a525017082d7814acbd0c02c6463ef8ec9", "CS1": "040d3bf89687ebe181cdf45286210219c57d6befabb7f488e69e58d9e061088127006fe7ace725edbfa751154fa1fcb839f73eba3b6000f3b308a03841bc3c2fc1", "CS2": "040511bd548071d0feac1a66294d5cd51ab842991c8d1276deedfd3bbcd0fcec920a2e0dc71c3d74553de7963c26830bc041289f8db99dc3297933f6086c3bbd5a", "HASH_MPIN_ID_HEX": "e5dccfeaf7b35a1d5a85ad3bbd7c2af83b5763f933ec817984ea57efcd5c7a2e", "TIME_PERMIT": "0400b3e2e5a9d4614b27731f6b06dfc2166ba2f9cfca722985e4f356c6775c21be04722441f3fdc1d5dafa60e71acae29c1cebc2811e8ec1620cb87550fd5d938a", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20226466623936353138323533623564366466353265366538313361326634326461406365727469766f782e636f6d222c202273616c74223a202230356266303961373432663830633636227d", "TOKEN": "040513efb84bf9376ac1996e9c1ba30dc7d4129a72a99803691205d1d4f2735e0809dd2e7dda8e9bf5275b6928efd7247798d31fe9bfffe2b8de3b30a2bf96af09", "U": "040355f54e64c80c013906397d42f929f559271a1a8a77f70317cf343f503147dd2286423ce20d09058247b23db1bd19efd61f57675fa50967c485bcdab43f243d", "SERVER_OUTPUT": -19, "Y": "1ce63f331d2d92acc7f3b81753e971683c09faaf7dd23f4349246dd374c2d48c", "X": "0127dd845f12dbe8384ae1787aea1cdea8ce28e55753ecda4e7e8cb3cb5f6d6c", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"dfb96518253b5d6df52e6e813a2f42da@certivox.com\", \"salt\": \"05bf09a742f80c66\"}", "test_no": 129, "UT": "0416f67c7cbdd7cb012d4e2f38766008df134c6b3e9b35409b7d974c07b1946ac819ce297e8e1a67f6c3779f2e61425457c5f13ffa630188c3de199fc1218bb1d6", "MS2": "20abcea82b121a7a04717d7c38d1111a3b27be2eecc4d269f56d99e5a7022bdc", "MS1": "1e972a7fc32aaf19a1c0b46dace4d0d694680ebd51f11f2f1eecc8065b92bfe4", "CLIENT_SECRET": "0418a6369e24a6645bc49a9caff064c3077f9fb7f1d976b3450dfb8d15baee7db4083a0950d958843c4d1832f6a8ecd4148ad711e9481b52bf02cd40b66d3787e0"}, {"TimeValue": 1437055596, "SS1": "1f25079e5441bb78c66cbc61433888f51953aeca712dd20390b3c8c379fcf16810e6e17b0854c36f0a45396ecdb7210ee6e5da5ba9aa3157096197282042d4e019385d3f5e3700522241a3201a54082cdaef326f2de0da61ad107eafe24916161f684ffbb87a92bc07ed76650d4031475813498bc1c0eba06b32cdd6131cb74b", "SS2": "1ec134f763c7d5de9f1d7d8e16289ff2cffbd8b0a5fe5218407cf442ffeb190b0f48810b2bc36d69bd84b45238a62fed90bc90fd0ace49d87f19ff7b960f41b410ff49c53724280b1c14b66655e23b18a42d75783bd2fee541480ecd7d55358217c7d024c4db5f909444be8698d1ce34d83c69f9c1c13f8ba7e6282f8c6cd9db", "DATE": 16632, "PIN2": 9578, "PIN1": 9579, "SERVER_SECRET": "1395cab47b7e500eccc36f61c6cba5e83bbd322b1f5f8f39fdb0033df49c9c26042cc912ec6623ae58880d14523c0c3bb3a41d1099324e5992641d2ac2cee3861b3c641eb636c36eb030161afc2c32cbd3404acc8ae94929049fe7d314f70a38109b8f57a51f44138bb263cd571fc31a81a5ba9339abae182065186f8600d777", "SEC": "04085dc0e887619774d67af8c029c1c3534432b18ca7da018621cbaa31c1138d211625d4cddd4a4f2d914045f344dbc0430680bf47c6716f6f9f87e1232978f53e", "TP2": "04106da07b46c3187001aae52c859ae228eefafdf08b48a1a141d5f168c26e3477170f70ff621d4d875a8d5c34840265cd05c865dde86d77d0bf38c936a539de9c", "TP1": "041cb05af677526e755bd48d0bf3817e0b4b97b63dbfab27ed83f7bdc08ba7cb1418f41ce4395e39176748b70cf77308f31d15a4572397ae9368b660b2551f7139", "CS1": "042234ee27e88f292503f78c9b5329ab6ba85453f0c2a5dd2fac0a6a87831a59851ae8e8f177539138e01de643a88fb21862c05bd087b80a9efd7d099cc6104f4f", "CS2": "0417e8f59b8e02778747ae2e2977c8573de79795ceac78615f3470c43d70ae71720d11da4674bdbc2a660a5a9d6c6684904b1ed274885b482b62f42806b87df8c1", "HASH_MPIN_ID_HEX": "cbb4e12e24119c0c16b6007979d5fdf08b7eab47bbc4638bc69057d2ce8c12ff", "TIME_PERMIT": "041a412f1d3b0151cdace6a543dd9cc1c09a666f3fa51ff88b9a9fd2468ebca2bd0735a2c9e0d9f08c73eef80e48e5a8dcda263332de006f1de7cb191c538d6247", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223366623333646366666533333836383035613337316335306334333934663631406365727469766f782e636f6d222c202273616c74223a202262373134343361616539623366363136227d", "TOKEN": "040ad9e57a0d0bb11debd13ea958b161e3bb151edab8e5faf96b9b5da9e7e09b620a1e74717364a1cd6b957fd0ba28437c6bb59134d569d39a74aa463a0f9e167d", "U": "04102a98d8f717cfd6978a731694a5c6c192bb439262ca66fbae313ab6a186e5d713b1eba50804e227a15a45902a4509c8324293c5d873fe4307fa662d146187c6", "SERVER_OUTPUT": -19, "Y": "196df456ff62a104e161ed1c4d71896fb299278cdfd7acebc63f4745b53126c9", "X": "0119bea99ba3cea76964e2faea34045a1d75f3ee514dfaf242433a49700b55d9", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"3fb33dcffe3386805a371c50c4394f61@certivox.com\", \"salt\": \"b71443aae9b3f616\"}", "test_no": 130, "UT": "04006ecf6110ec27f87707b4b68af34830ce8191f7f1e354989379100a0c2726ca03fcf06c764d3d1ce472bbae60575a1c072777ed9c081b53a2af99e3fa5c3988", "MS2": "1e9c3935a24f2bee033f489aa94652234a4d7fa2185ac59c5e98c90d7627383b", "MS1": "0a30ebf12ed3434ec57a2c28939b031c42818e28ade4cc6c34fef25a9afce6f9", "CLIENT_SECRET": "041318cb4b93c264aeb0791878bf85a3d852debaa42c4d1d63594da3f1b525a249052643919484fde9b8335dc932832cebf04feca379cf0200bcaf6edb392bff4c"}, {"TimeValue": 1437055596, "SS1": "10bbb2b018c35ac53f856c9412f735251011b38060655456218f45f6e91f4cb8021a1748f19e74113168601eb17e88de49f4a2a88ddf94a9b2f0c1c70cf7cd2d0932aafffdc6b123a70d37283e1b1553d27f9ba86a64ef11de3562df94a5d3951745e58cfd2cbf117a0885bff45194b1981a5fcd0cfab2515e9714434857235a", "SS2": "0f1c172351ec30d875b323f5221982479d500ae7f098b7f0fa18d7225422eed8118955e38cff4a200e85046d801ae25585d0e3f249e2be6d8557d902af9c800d20d6c92f309a3f73044323c241b25ad0df085d6bdbc49e7a240403d3c650994e139e469e51fd0f4c2b7c6412ed9ece4c26ea5d651c0947d1df24e3036b61a1d5", "DATE": 16632, "PIN2": 7556, "PIN1": 7557, "SERVER_SECRET": "19a4b4a116b49ea674ae2a2cc4d20aa0346548a355e8ecf0f795492c5f3dcbf221ff3d204b6d138bcbe97535f3f275eb8113a21b19f259ff993cfc1c99747ec60f421914c8edfd590959f53be62331cd6cb7be0a3009003c046d69d0b97c0eb7011da36c591bd0e3a92011437fd9b7b01e58f11d2bea365006389eca6fa9d748", "SEC": "041fd16bc0397a67728fac5429e0de2aecbf5c5fe7fdfd448a7f629ab85d22f952163dec08314499dd95f10a785fff3447dc2173ae95c2955b1b1b824ef79c0c4f", "TP2": "0401fccf9b2a51b460f6c8740397c213b9ae95d781277f4431753f170749dd88231c0a3f9ff507e06138b752d036bfe0a9e63a659ba0b295097e95d50d5e111c09", "TP1": "0404754711af8c0cfe05f67e98f89bdb76c9909a7beae835de166f71afc0355d622212ddb78ecee639ead4f6bf3d8c462bf007dd2cade9f8067bb7ca706d6ecb0b", "CS1": "0412693ae702dea1c656d5bf0a75abd2edf79195adaefd4ce434e2010e0f5afeea1c47fae73f138c668775c0121a8bda50c9cf02d1f23a05bdd780ad93e7a55457", "CS2": "040188a92c0a8bba32536d77083ddefeb2c295758f5545f258f6e96841060ab995010918dde0c49c0c4e3aeddf4df981defa0ad4859a34dd36e99220ba57871c86", "HASH_MPIN_ID_HEX": "0705cce71f06ab34d1752cf66e1f034fd23368b3b38312c62064fdb935069766", "TIME_PERMIT": "041720f95c6bccc00cac06ce4b12c9d342432f51da4986e2bfbd4bd68641d3e5ec108b0db7617334a662be58aafec882ee33bb7bdddd47aee0cdf0cc42027ab910", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223763313730623734633964383665376531353364623135393837393761313735406365727469766f782e636f6d222c202273616c74223a202230626138663161643231653630336163227d", "TOKEN": "040390497b24dd244399b9a0d53bba98d4bb283072150e96fefe7ba43524a2555e12568a9b2bbbb3745b8edbf1add4c738d43a36e5e4aaf2bd704dd7361d746c6e", "U": "04145677bd7077a4badee44757ee0da4d3ba2c21f9ab8866f1b159ccdc14200cbb206ad01185a104580b18892f7270258301a0a5d16737595d7e882676f58c9f30", "SERVER_OUTPUT": -19, "Y": "1ee086e8a556a0c5db6c49c163853bead139226fc2570c5bd0216ba6279f008d", "X": "144562e1603d24343d7e4773a4cb31c46c03eeb6190719d4fa902fd1da11d493", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"7c170b74c9d86e7e153db1598797a175@certivox.com\", \"salt\": \"0ba8f1ad21e603ac\"}", "test_no": 131, "UT": "040424e9ff98eb8ffce620a7081ec345b8e3862c77651209d55c0da7f8e722f6e4004003920045a895ed0df26f26d3d84ba76d36151411bdbaca4fe4e469694499", "MS2": "1dd459edfaae29836bf7d0a1e2555c87e366b35919595c9879137e9f3f93151a", "MS1": "21147f08e437baa1091e98a6e7c773019c10524db2c944befb34d4b962bbe732", "CLIENT_SECRET": "04184aecd1aa94845b709d4868ebcc54b94be09e96f4cd317bd319c156e2ec23a91e5d7abc21151d415594e6c13f214a477518a28e9eb2f83c174b76975ffcc48d"}, {"TimeValue": 1437055596, "SS1": "17351f926d3642cdd5c206023a588d4a0debb48d8a936a9a0474c23d3960bce9083088401743f56dced4dedd7dd6bbb72d79b5665901392e388acc7bd859483e04eb9da3c4bf4b183a3f5e1a625cb9c4f81bb98a1e34a76c735947670376dae620ad938490265d309a3c62eed7023eb9be7a54098872e9d7c87679bc308d9520", "SS2": "207a7a2320b54668120cff5942895e9613b44e698d370f268bf4ba6592c707c610119f85412e50a108db5cf00ffd351aa1d4bfbfa84893769e2733d64b504c871b28ccd3956320211c179d07cbc4bd265e6b2aaeffb3852efd2d9aa1f055e6151a1394dbf94a9632fd40437255cd9abc5a88ee115cfc57af431848fed50b8e35", "DATE": 16632, "PIN2": 3856, "PIN1": 3857, "SERVER_SECRET": "20b56e03c827caf78b7f0082ca0197740adfd7def6ec7159b68d8c5e70311e03132e759ec30ed71628af3f038bb1ae13dd1a68aa65c05f5fae35f7ad86fba19305194b7d713fa77c158533d03a26ddded8971a70a14eb5f15915c26b061b86c31cf2e37ff757cb74358d0f6103463e3fbd0f49fa4ebe55841b1a2ed7237a822e", "SEC": "0411486e52d37dfeb72172abf42a44b8f0d6ec099c84480969181312eab9908a0712c3ae6893ee1336a6cda84520903f4988d017eb8b4993eca73aec30d381889d", "TP2": "041579565ba491e87564993e7fd16641871a255e98fac3d65903fb232e57db56b615150a64d07ab45c4266a4f5da9218f550f13479b671a7b4b3ad8d9dca07420d", "TP1": "0405f71d35f9891392f79df4576b74048d824e535699582e2b02434cc339ff9d96146a36110129ca917443997e2c48d73a64374ed6cd18323ac24896be82373065", "CS1": "040404564b1130488d1b2ca1a60e305f847fcc93d7482baf7ac65dbbc2e76985a8215fb7c26f2d42f608ddea38f300b3e23e182cd1dfbc75b4cf5099ba7446feba", "CS2": "0406efc6e497e143871a4fdf684ea991e6fb2480195788bcac7dddf04c3374d08d219af0dc1eaa5d59edffeac26aba47ac8328d1232f5dd5e88ec6805712e977dc", "HASH_MPIN_ID_HEX": "2319471c4e5f61675e19eac04aa4ac1fde62186e841ad7f1d4525fad7de63847", "TIME_PERMIT": "040648a98be966c0eef4c84aa4e5c3848107c69feb5a36400c6db17a3024a3e16707d2142df9c5f459f7cf2d8bc90d45a91f4afad94083493af15b84cc078bd9f8", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20226565326530326435396436643039366432303962323762356337623761356437406365727469766f782e636f6d222c202273616c74223a202235316636386237336561376166306637227d", "TOKEN": "040d430a6496a695d879c88dd96f50eb7f5a51c78da049f18c743bdfd14e37958b06f69d688e3a75e41882f027590dc3f6ffcbf2c17aa9d1e6e5c5971efec17ef9", "U": "04209fe9133f924f3b7e00d8e228b284489dc43f56a39b757f05c3cfcbb0c7fe27054891a192d257d2bcd022e26e368002ad287ea2b8327d698d15dba4cfe46135", "SERVER_OUTPUT": -19, "Y": "20aa779980d2878820e4bde760fd90b673e94c8550e896717e9c0aeba63c437e", "X": "0642c6a6c4c33761fc13c03b5b6bf6d38b8b341c4fdd35c4e0837a743f834763", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"ee2e02d59d6d096d209b27b5c7b7a5d7@certivox.com\", \"salt\": \"51f68b73ea7af0f7\"}", "test_no": 132, "UT": "04169e0b5732f20d417f2d273b7eb533565fcf88f9fc991a4e180b8ce42a7b7e5c1d07573661e746c3337b2e91c6aa5261a87cbe3e624390ab76f3d3a5570e30dc", "MS2": "0745409497fc9fa74ce409d1facdd55b63b976f92329c65892404b7e1ce37296", "MS1": "22d391b1eb38057a1a7b80bfc8eee41ed01d00f992a92650ddd74ad48714c06a", "CLIENT_SECRET": "0401fc4c0871012ccba9f92bd2794027cc3745db56a66976875ad87bf9d501f42803cfec755a33fa851411bb1d11b65994a133822c069f5d1fb32e5fd275c2df65"}, {"TimeValue": 1437055596, "SS1": "225f926d09082525a0ca031e164e335b1391f60525756ae4942b9402c58d3ffc0f8e972cfa8a36b96402656dd941220360252017a9f8968f32198fb5f7408f00078ee9b898a75d5f6a5fcd5d40d54f04d0dfe0ccbac69af4e8e5c70d714352a400455cdb1eb689f6b950263688aae048610dd8eac566d151605c0b271ca4a107", "SS2": "0e66e11c3227996871b24546b63e7275be52702f558dcbe67c137c54ed9cfbce0ebca46099e0a0218a05abd6a83c173cc1ac420e04a7a59bb5e07d73159570160d7b2e1165bc7245010fcac43541c808986fed205ae32de5e766dfa1a68c1e95087ffd84b2c4de6df6cf491cf822ac80176377c08d755f0179bff902e1c4031e", "DATE": 16632, "PIN2": 6990, "PIN1": 6991, "SERVER_SECRET": "0b4e5b1c2269951bc04b1620709e4f5ff49ea07ebe7454cb422297fabea2f6a2052d3c921d8977738e2cac7200962c27050b6e7c2d12adec5b7d08ca5964eb1f12fe87a0c3c6608ac7e89a2715d1ee8580f9630b9dc1418d390753c786de2a1e019d793c6f0e8309724fcf5d63098b3fdbcb6a5ea2e98130f891670e4d6d2c97", "SEC": "041756b21117681e4814fc7fcfb557b16c345f91f331eaf6177f76fa9eef67af7e20cfa332ff447337c747659164f8259d90564631b003e6985bc8f3adc6bea082", "TP2": "04011a5826d05bad778f6b7e2b81e8cb212ef39eee44a6493fdfabfa20e64de01d1f7b566d8a715a9c9ade84193b8c6eac056f162964c45f6b8cefc1403f4deddf", "TP1": "04051bd9d1022569c4bdb86346b5abd549740cea640d169c2bc7b4e76a74fbc6fc0fdaf6ce8877603a4e8c29781eb761553f4e042b65061bd50b91ae9514647909", "CS1": "040740eba333c5887e0b6570933aaa2b7e075e3fa5ca8bdb97e6abc6c4fd0bfb430adb5fa8cbc152abb7f41d85aed3c45af134703cd52d518fd780a1ceff0a9b9b", "CS2": "0406e2bcf37c019a9b324166db3bc0ffc7b8b5a190d71cb03c9fc806ea34873373064a23456cd98919d46edcc40d409006f22c1baac33accf0cc2206b14d56e419", "HASH_MPIN_ID_HEX": "4c4da2190a642dc3f880e36e44d45f6ce71f134b96048479d205e40081835693", "TIME_PERMIT": "04157e6c52c8994bd2d33b4ae80d781fdd2b9678bdf177cb576687b658a86f46450c04c78d2002da55baa74023db4f8875978287581e06f51668c363786dceae4c", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223265643334356335383362656137303966373933316531303864396662643530406365727469766f782e636f6d222c202273616c74223a202230356234353132353935643530323132227d", "TOKEN": "0419412d250fe985aa466837abdb190de46575e6d67cebee662e8fbd9d74545f941b013a32cb1b1a1b3f9ca5e045848ad50032487289a3fae4a3bd4f3ef8d70934", "U": "041014dfc9364384b8ad40fb3ccd49b72810c3e41617eeaafd6179ff9d72ebfbc022b2cb01935a7ad9a8e637c280d162107a407981b50bc4ec34fa9d3cf1e4ce3b", "SERVER_OUTPUT": -19, "Y": "199c70a2753c5b4e536ce28d9c921fd78ea4756c95bfc0683ae99657f82f3529", "X": "01dfaf115e3578120be69f6f95d24b8495aff02e11e75cf3dd2327b8f740814a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"2ed345c583bea709f7931e108d9fbd50@certivox.com\", \"salt\": \"05b4512595d50212\"}", "test_no": 133, "UT": "0420f7147ecbedc641cd66f4b97f78d06795aa0948a0dd0afbb5b7625da5a5b8f0220a7cd33a08e35eb9005c3a40be084325bd2b9ae71c68a3794fc704012d6d85", "MS2": "221071e6425762e63cad9acee2c092599c6a72ee75f830d3b4c270286b02efb4", "MS1": "04b11a81cc023301be80174cf42a111d7a8e1ff2218c14bed4a8c1cef572ca04", "CLIENT_SECRET": "041ff909f624740299de7c33d922d80f69391272e0e08596a680becdc766b94e0a04d5a8a1641f47e7992ea6842822998ffa445f7f543a7685c5c712f54567a7c3"}, {"TimeValue": 1437055596, "SS1": "147be61b6cb9fe9fe8af58b52431b3f48be6b9bd26a9c755a42f3837cc09078722d48e2a4ac8496e02d043a5d93c86664947dd8e0c4e221517d5707cea2681b2233c49f3d0ad3786a7398be96484d20f3923b7cedaacff2845d7131385f6f69917a937047d323aacd87d6dde30c385fb1ead10f49236af3d2364e572541997eb", "SS2": "0518e96b1aa704521e2a5cb73a3d92c6ec481d7b1665b7c2b1eb455197268e93110e0c88f7982ff17b402847260bdbf19adb736937d2656e83afc1ba5ea740b504ed041431cebdd98d90986ec440c78d74f951b76f46d1238916df4f621cbc90060ac811e2b475cddbd8f4b3ab10742456763f872364dd41ef69008cb5f740af", "DATE": 16632, "PIN2": 3342, "PIN1": 3343, "SERVER_SECRET": "0c7ff8e2a412c9c2a740ddd30dd7010f56d74a49abc5d6b549ace9b08008621002f2e89a14723a11231096050868245ff59f4db4a2b73838a361fec85c5c70b51f9b4f5df0493a976273939942d49b6f7257a954ddc1162c394f2c24c3e09b1a2064f2533ba5a4b87501161c0d5c619574b5ae93bfbb2cbecf714f990636599a", "SEC": "040f12200b1810b33dee355348f5cac41b3ac2e093aa5fbf51324ca172698499630f4d52ed6bd269fc7ade71006411828f2718602ac33bf9f9ea56520a138628de", "TP2": "0405b3ecbdcc61153d30caca3ed5fa07aa4add4bc5b16a9d72ccbebcdef536e415029265af7d3f672d129b5b436c760b260452b36500da8038fa44820c2a993a43", "TP1": "0415faf92fa81ebcecc30e1f39e2dad1af07e8b1f2408d9aa4369202ccbcded81b200ae729bf39e66c3de680a26cb8fa07ddb0fa11a0f8fa3e37035670f3c20227", "CS1": "040858f473029c7db76196e92bcdf4a608e5b8549d6398f514630b81e1a56e0e9a1906039b849cbb6a0876b0671154306856cf6cd76ab00282806dad11215a52da", "CS2": "0406a2a3f8edd50bc41b6ff9c66dc818fc09629f0e1824add499de5fd65bad166f0962d8b063efc14c7e20c1f3d3229bca86ac72b5ac851e3a62623f1389ed152c", "HASH_MPIN_ID_HEX": "e90bcc87803308da38c75fb471776da121851387d640573744913eb58435a088", "TIME_PERMIT": "0406589a8875dfa505b3ba5282bebba852ffc3bdcf39fd5cee7811f69d7b57c32b00fa4d3cfd116d8ec1787b30d00e82d3c55e1d4f2e82eb0a139685e7dce18acc", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20226431643766343137613362323138633739303438386664313937323433353835406365727469766f782e636f6d222c202273616c74223a202261373336366139633539303666626536227d", "TOKEN": "040daf8369ea70091792cef13e20a950c51df2233da11508c5cc819d2ea0b57b10238b6ed8941dc265a6bc98c40afe7db46a638034aa4f017809ce664cd10f8711", "U": "040f7683000e2993e709748e1a0e1166ff4df080d41d24b4bbbbcc24ae4e022d3c22abc47aecc9d3a8cde860daaf52bf171c9bf2d23e1af818ee01af812679946e", "SERVER_OUTPUT": -19, "Y": "17967d0527beb9f5a81fd0fc35a1e0bf088b1c8844c2fa0f990ee98c7c8caa03", "X": "1623fdf20c4f32076221724f229228fe7a763f12ac52dfcb9266249799af973e", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"d1d7f417a3b218c790488fd197243585@certivox.com\", \"salt\": \"a7366a9c5906fbe6\"}", "test_no": 134, "UT": "0417cbe6f2b0cbb4d009b67b23d5bbe80503c7dc10ce3810bba2390d6d242d678b17a6ff441068a4dc0d21d4b2cd2387f48959c62b7be7219f67b874bb723adbbc", "MS2": "1ccf040ba9f4bb9222da8719827c1e292a21a7793b18cea137481915f5f2dd15", "MS1": "022fbcef0a021411c5cdcd7030ed9e7eea4182f77f6621028c6f7acfd308ed94", "CLIENT_SECRET": "04006433be0bf708bf332df8e966ca6fca85382d92d4a8304148d4640d297aac2e0273bf6d91f2a493bf0c58ce6ab3fadb867929bef73c8a1dfeca4751362bca87"}, {"TimeValue": 1437055596, "SS1": "212951fbf4ba971e2d24f7902a40786c46211b3108540bbd53273b193aa03e1a222d4e841128b7ea387e2003c5570e9981e1543d587bb03c023b7675bd40b23715d18c64239e5abfbb5afd48b859e6cdb0f94ca81294d504f2e26cd72253a00a02185fcd8c95fa40e868f5813cb6f51e2315db0480b37c762e25818d7c668fba", "SS2": "08ce3bc369de4cabb8e42c2921139eb8ea4237b824a4d94429c8e4e4d7e969991298d457931b7d6941ba91fc6ec344923ed0d93372e70eef602c9b8da78e6d89100cc7b05401752dca6c578cae716e86ec08b98f36d3d011dfdd53ae3df54be203243f64badf2e75c36cfcfb4d1b7445c45572ad0e4e76dea60026cfc460aeaf", "DATE": 16632, "PIN2": 7524, "PIN1": 7525, "SERVER_SECRET": "0783899e9b08c3069001b73c786584bdc5bff302288b5c06a25c122f59fdb6af13c5f2476f1740be9198bef6c8bb38d503f1c0a0c34ee357ca37dde4c3d9422001e0c2f180e87ae1c804e97ade849fbca591d4322b85678663172994cdcd93c5198944528b83641ea93e377f82ece582dc54432aae645071670f91371015b14c", "SEC": "040a3e5998431313bcce80908e26c36596cccc1b7aa7203d6c177f6f0a6f5588821863059e73818ec73a6263bdcf6b9c1e92b306c205079fb02ad6a58fa5feef7a", "TP2": "0415700d562282e6ad787266438ad54f487cd60816c53ae3d62061eb9bc92e3ae301e3c211dc64c788b4f4b82b490d2d9621a84bcd45fea338c3875c4927725610", "TP1": "0421ac0cf5fdadcfafeea005d0b792419076ee20318462641b88af9914c6e659bc0762c198f9bd2679c3c7c3a3dddd0ad46ef392210acdc1cb11c57395b10d0325", "CS1": "042284a290fce37857370b3b7f1aeecb6b2520714d6705dfc08c137dcef57db49d0be3e5e2a501db96659b536f77601a3ea608aaf00849200efaa1beb499483c6c", "CS2": "0419e647fb4a5061391b1ebe617457ba507327419c9a9bd96390a01de4e88871f517f5029b66432743d7079ccdf95d6492f2ce9ace27a7c36c7f6f1e2524741db9", "HASH_MPIN_ID_HEX": "ad0ded9abff8aa6b6f1aeb6360d6e0861ae3ccc39d411303706d30bd5ef8ae23", "TIME_PERMIT": "040fce5c369086a54bec2b954b4cc0dcdab17fffa8516f8501d3a7fb51611c513b18b3d6372e913925482462fd6bae822e6b4cfa596953be5e40207475ea221c6d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223239646261376339313136386665623165323664616635393531366363343434406365727469766f782e636f6d222c202273616c74223a202239396464303962303734363337316464227d", "TOKEN": "041fe738a786d72266e375a87e17a8a55f2ba098dbbbc8bd7512426185e50a2811096baad24fbeb0b959ee47a43e1fb751d7a3b08e0b06e8567785f28daed8f60e", "U": "040037d4c7f026ed4ec80e96795d594e58120dc2fc54a514f186e52fd7c343a29b157f35ee91b57bbcfd17c184d5c180b6c98a065a954f6512b63a54b4d0b05a71", "SERVER_OUTPUT": -19, "Y": "0cfeb2edb8b4cd304d8b371861ba658897c50c7c5fc9cca0612848a910b63593", "X": "1e0b4e5bb9a0af8e92944bd5711ec3fe0ae105ab56e7788929df59332c437070", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"29dba7c91168feb1e26daf59516cc444@certivox.com\", \"salt\": \"99dd09b0746371dd\"}", "test_no": 135, "UT": "0411d1dc8028c86f22c04f10334d182c7b99bf957847a75835264450c2d93468e517b13054b559410c86dd81e7ef354723e4b8e04144f39d86b44a4a2a7e325a4e", "MS2": "139abcab8cf88911af19eb16422aa89f5aa65e5dd547ba1d3e8efa1079d4e28c", "MS1": "124d28c78cdce10610d99a0c64c2299d3c73e17ee9b8a7602523b5550a1aaf8a", "CLIENT_SECRET": "041517c8d93cdbc293ddc09b96485f5793ea1e4c21fe3e585532e76978a400f5340a49e85331d1c28687e9ace7e8d4a74883e857b68a8f2af2114be9add983c657"}, {"TimeValue": 1437055596, "SS1": "1cbb09629d10b909dd2fee44b34f2a6cdbb01bcb1fc7610bd92ec020721709b60a70f5a26516b9f705cd4fd62534aa5d1e3f9e9d6aaf9bd819ca5b0d430dcfb62201fcf30ac5a570a4816cf022fd67b17ef521ba093e06317c9f424b30a2ce7615cf32c6e3d651e2c0160bdd171725b1cefd29702aa9770f2ad097680a1c2dff", "SS2": "09782b6e04f0b33327f8a4a7ca7e0635005b9623129858ed8798c339d0cb0b381314df242599fc46c3f239d7291a714d46c68c641e933ddef5d2572daa9b0f4811521042bb790f8d5115aaf5472b4b79d28bcbbbb654c5f45371b9896c9394d316e37188df862a2bfd07529e1bca04bd2d5ab9177f937a243a31ae698d696d84", "DATE": 16632, "PIN2": 4109, "PIN1": 4110, "SERVER_SECRET": "0cf25682440cf033e9f6058c2f8cbd6f7601a9f32e12142078d9178751e9a1541ea01e1c36fcf5606c31eaacbe2be3e3340e5739ad36dff45a3d18175c6399800f485076d8e5f61afac7007a538a066d4b3d50f7e7709e7225c858c495a3d9c0013c4ad69b29af11645cc3dfa1e4d5b26367cc40e889fb620ad0537735497e6a", "SEC": "041104f476ec525f9d0936535755aab4b1485cbd401b06f0c35c352a0821e33e6700e42dfbc1aacbe9ef7dd524a561e4856d549154f7355b20b3d1da3b94a44f94", "TP2": "0408e010fc086373344a3b95900e63d9fe30bb353f2fa4027f18809d7dbfde9de220548d6c20d677e2bcdbcaf3527236ce8315b24fb2d4903fb3d7adcda18660f6", "TP1": "041f639b6af059ad93e76027b4a287b0b398b9107d3b262b69fc7b29a980656870129ca702f0cd91d7289e3eedffb744a798e7218acb6eb818481d9ed3ab407847", "CS1": "0412eda48028b73c0fe7ec7926151fa2505ad417680fd05ea08f3de74091c468260b406b239a57e1d647daaf2f73751ed3ff5640841fd0c61b54806649151d6c3c", "CS2": "0404d8195d7d2162c6e790aabe2a7c866149513e3a708da887f8c10ebe3e33299e12232dd81cc57a4e7160aa8a410791e7e116a1f3c67baddac4553c13e378a7e9", "HASH_MPIN_ID_HEX": "ad58663f3d999959a293e63553ce382089d375c27db76ba6774f466be19223b1", "TIME_PERMIT": "0415b687c791c919f17d5ab48d1665ead56b16eed140453a4b2fc71747b90cded21d700bd450bf112653fe25ddf8b1ded53281f221db95f8b2e986c8919de2b104", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223832363237656536396561383764376232316533363465353330333530366139406365727469766f782e636f6d222c202273616c74223a202265323130316530666633393661316638227d", "TOKEN": "041da27e28a90743d51572704a0d2cc6cb0c2fbf22fa050ca25819382f45d1694b204e1ad1c81278b887c21ebe19fe3dba0d76da4a1ca43d090d942ed7bd211fb7", "U": "040bd02b2bc76ef35a0616e3c4c31be91a11ea52a7911b839091e24d715b0e90a002ca5d2645e93305c20bf9718b5b1e7aa31a2a46b51228d1cccf42dbdb4cad6a", "SERVER_OUTPUT": -19, "Y": "0eb1f3d70bd58af1dee210a038a78ff74c3e3a7bfb5c35e5956d13f707426d55", "X": "0c1747b4b10fe8b29a798284124f3e34cc53ad95f3d899f35b130657157eb0f7", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"82627ee69ea87d7b21e364e5303506a9@certivox.com\", \"salt\": \"e2101e0ff396a1f8\"}", "test_no": 136, "UT": "041fc3116ce4bfb058353577126e25af4427d7f0c1edd05fd0bfdbe79fcc3059010fa794933fc19fe4a09b49631c9eae720759646b59edebc308e76b6bac80336b", "MS2": "07fb9cd4fb227418c1a486848b04b41fb3c96712a0297ea617a9dba9979cd8c0", "MS1": "0e9cb04ffe836bef974dc8681fbea1c61f50e9aa43e9a803a2f79a35e7e16ee3", "CLIENT_SECRET": "040a54dda7b5d1be39f9574f2ca13463410845b8c5bb798d8d1b814f3381b1cddb18073fe828786c0a4e8f8419faae5a99b1ff34815f4a8b4c129e487f371dda5b"}, {"TimeValue": 1437055596, "SS1": "16d985475b42d39d97c5a59160083bbd73ff0bf377f33bc4d8dcab11a84164ea02c5de7292ae3c541fc9add41652740ba67707171b52269f1da2a95155c0a353049036e2ede01b4a06f3647077a9134ba0b7acb16193198528abcd29f9067d9808071a1df1bf71a28cd79e6216548774add261d07c34a7875e8d68c765537b3b", "SS2": "1531070f13c0dd4eb33f55dffc1c304c8169ad474eef356692b1f3a4600087210731ff2b3d20392e69812ac6b0d2848a87ddb723096e728af1484dc4006def401c361de2e730dadb92acbe44079de93e29f3baf2963b1af62507a271ed95698311e1cafea24530ee273880347c32db23413ee7d323a0455fb0650bac5af10a05", "DATE": 16632, "PIN2": 9391, "PIN1": 9392, "SERVER_SECRET": "2038f70e2a0b2da625c044ce39bbf45b6ab213410dc1d1896d7143467b47486a20b47ad1a5132891b5c70c1e843ac616ec825da3ebdc8d6b42bbe596397651d01bcf45d6b16c62e2139b045a73d3be0fb96fa5ec2d5b857754dbd86c122b13660dbb226ba87b009768bf2dc39528323e1a8067b28deca84f5d6a74d9d7b9ff10", "SEC": "0415f5566faab272850ecb361eeb3939b80b3132b3045e408d9ce02da2fc3de2571dc7fb6086250aaa06534360606478b9a63303687b17553807b6e4164d7b01b7", "TP2": "0406e98a6a3a2b8b1799c919274cb7ccdaf7d188bbbd3b96352b57c9207ebc1dac18c5e19dccd901c25fb8b5084fe213ca4ab755d3363786ca74032f1a5505602b", "TP1": "040e672a2a8155d6dec71f72a61da2d82c4e9fa7f0ced27218707111eb54ff9b3a23677b9518f8fd0135f695bef3dd77cd277c67ec2b965a6cee989a927db63f8b", "CS1": "0404c41ff45283786f3677e0ca6207022e9742e0a8af18f18c1ca648e1db79451f011707dc3b3e3c664c95dc9809887c8a5f3072388863633b2858d25cb4a1eb6a", "CS2": "040ccc55c8b0377a637801e68bffa1d1a6852a4b652b9f1adb6d9b55c1f34d0e5722067f932d312a5ba95f14bb67b67392e82eee2b8b4c4140d51d6d397f5ff9c2", "HASH_MPIN_ID_HEX": "7a482142570ee366c5b1fe93a1423dfe94c6546e2be10e76ebd0aa3eca7db967", "TIME_PERMIT": "04198e6f6abc7fedaa37a0f2217b04b97fcdd60ca7ade12aa7bba0eb0e4ea8c6780ba6493f8c68ba9226d7272fa0edc8bb25a46156eca85a1ad42b56b4a93a0df7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20226562336235363437386362313130373366633566353734393162316432663533406365727469766f782e636f6d222c202273616c74223a202236663662343035323361346662383866227d", "TOKEN": "04057ed04672e7b5624ffc4dde2d4d59d97760090a2d7776817b15c24b962ed72a0e4a4b1c6f8786f86523df7a183edee6627e93d93a0962eb2031969a4649fa46", "U": "042146838fe90adf177692f2bc42df309e4ff75954f897fa8b10a6ac142840751e1984d905bfdc0191fb983b5ca16c6c6f9ba7c616446bf3eea50d777352049216", "SERVER_OUTPUT": -19, "Y": "10c6bf640f71c2dd4a1d7e0433c79dbb499688cc5f1970368d71e111bdbb2b36", "X": "167ca46abd5ddf6ed63fab1b663b5c35f8c65afe42704ed5c90c5b81c07937c3", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"eb3b56478cb11073fc5f57491b1d2f53@certivox.com\", \"salt\": \"6f6b40523a4fb88f\"}", "test_no": 137, "UT": "0413a450b353ce8551385ef33f601b4f3599c10dde68025a440280a995684f53c100284a7c0a1aa6b2fcdbef5429281586efedc8af9eeb1023d6dba2ec14734a83", "MS2": "03247cc1401b0ed818a8504bc3aada0e8be887f690814e0be665af29425c4a12", "MS1": "098ceb8755581a8e837b9be92e140f362d83ac83f15e1742ed869b0708668c9c", "CLIENT_SECRET": "0412507684cb18efd66053711bc891e3046cb5cbc75a8e125291b56aecf12967f819ecd7a8dda226f229fbc08c127d29f57ad8b7b1c8580f4bf76c22403050f2a6"}, {"TimeValue": 1437055596, "SS1": "1c58ad31e5d6a61715699edba01323b1ec60cb9cb69725cd99aec61a1bafddaf1a0df7808ca7ea977a86267afaafd7533c2bcb3ee3ba5c407e584a0eb89fa28a08579aad7e31c3c67f1af1eb23a01c76b27a034994cd76b8a8075597af541f5f0fd1882e62d5385c066985117531cfd392bf678840006ca364cc52502728dbaa", "SS2": "1c7dbfb3c234ccd2c7b137ad253b0e6c4604f8432afb2a540eb3bf7f30a856780f8c109a080f3402f81b9dbd06778e59b2f15514eaac357c5b595d2b6e4ab7f504b2f19db3b0f35fd3c438ec6ea5508c879bf7bbc6d98b118c296f7a362813dd138816842382a8717f6bfc813d9b0ecdef780a83ae9fb8fc2cdc4645732f140b", "DATE": 16632, "PIN2": 9340, "PIN1": 9341, "SERVER_SECRET": "0f747782b81ffe1da49114d6c4e6b417fad4e9783105b537d5bb427641e889701a4c8a7972b41d6b6a5ea2d2fb3302b4aaebc24edcefb358a800652fb0124f1f1b8ff9b9683d67ba5fcecc43d2728801562d3819cd3607ec9da438ce3a42278a1c26166eafacffd8132b8f7eaed7c04f53a5eec032695faa329fd401758ee4b8", "SEC": "0409a2c9414c010027fcd6220272c3c7bab6a67cf81d9380ebdda35e7cfcbd7b291e72ac92f22c529c7c7cb4afab4767a9c9d7b0e666dbaec70e5ece6696737f15", "TP2": "041c69ff33e0306044cf8a149744199d827218c54a8ad7f49faa1d752b6aa20e1d1d27cce2858763943a0d3fe4337ac220ecdf18a363f98bee085766d108e9b812", "TP1": "0407b639e0ac574ed0cdeef9cf81d46117ea9761d629ae02693d2ac6d2463ad70910c56b796922439927a65ca08d69e6e3debdd5db90c8281cb136bb952956cec1", "CS1": "04122c38b33fa0b78fa868f03716c7fa10747aea89903b3af08cf2080b436512381aa01b931b14bc66f4a11ac8077d4e96e9c2b3a1c457b8d8bb6b6813cef8cedf", "CS2": "040210f3f060903854c5d9070107b4a54c3febd008853498bcbbd6c4390861a6331c5a72656dffc49ae51f0e8ebdd78a9d3d5bea0d729502b7cb643033d0360ff2", "HASH_MPIN_ID_HEX": "9caaf642aa085039dffdcd613f9b95eaebb1efb9a6b92868263a6dc7270cb9cd", "TIME_PERMIT": "0410f3724325d304b18100c6eb2c39e55a8d5393638f040af018dadbb0dc80481a2333cd979d732d597e9ebe4de75fe50908a84cb44a28805e3adbc1d7491f2ac4", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20226230343565386535336637393131343233613464666265376535636630363164406365727469766f782e636f6d222c202273616c74223a202235346462303636616134666564323131227d", "TOKEN": "040c729a3c2b4734c0a6cf84d02cf1bad16dff20a318cde194aed13ee2ec6f25ce117c164839e34d2d0102f337b84496c410f51acc687ccfd4a998184045b153af", "U": "040b5e3ff259f3167623c543e2790cb1a1a4f753877058397e6bbdf6d09d11ba71181acbf35c3e51038d18eff4f17ae800334eb288670104bc90441416518a2dd9", "SERVER_OUTPUT": -19, "Y": "0da0be5f4c9676b6724900026bc4aa66a319c9ec0e016ed331179eb073590a43", "X": "05dc3d1437d1df2607b2c7e5c342678b063b3db60427e8ffa8e255a78206e075", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"b045e8e53f7911423a4dfbe7e5cf061d@certivox.com\", \"salt\": \"54db066aa4fed211\"}", "test_no": 138, "UT": "04117267beb32d1a059cbcfed6cb998413ae9ff9343e396e44d7a8904a9020a113024680aeeddbd195fb7cb0e8f309aebfbe97b84af4dad8ab2813ede8b0a35e8f", "MS2": "02a73b00bed65e5b3491031183c9916890efd7c7e32f50b0aada6ef3ef0144b1", "MS1": "18f709f3ce55f585486fd633d60ddd131b038763f430c069cbd8207e0fb59969", "CLIENT_SECRET": "04048acc7846a137f8af06190b5750b34dd0b0efa652ea4c0b379d382f5830ef6612ed7759b2723b278cd452d1564e7ca23369f7badaff2c041b9d1ce506ad17e0"}, {"TimeValue": 1437055596, "SS1": "1fbc8c193abf87c37ff79467a2d473429f4d65cca9b716abc1ad884bf4b8c4191b99275f87a98808bec3d305352e1db8a9d10495bf152a4ffa588976638278e109c463f96c282aa379ebcdb6890ef7f82fcdc69be28f9882509a5bf4d602df7521265a6db23dc544d80a1f7f305ea9c0714b0a30584382c5b563cbc97716a8b0", "SS2": "1862aae6a7695b12f958e44cae458461a70bdf9249902c74e51d6291361f6dcd1e24fb42c1bdf8c1ede42f13220167d81071a604122f8082fef10efdd010ca97196087a6fd8775f17369617f71e2837fa4fa8621d1aab6019348789d6c28ce7e0ebf1a82be2d160163973e011817e95ab31b5d18da0d1463d5aaf8f27489079b", "DATE": 16632, "PIN2": 4269, "PIN1": 4270, "SERVER_SECRET": "1d57665bde8a7e87c23d10dacbe36b4bef913f357bb2cc3c2382c3fd5930f3d204d2e15f62e0bce64f207c82443e8f4cb611a5de5a59e3e157366d36c849f392003a8164990546bbfa32266716f7e3feda8b355e5660189af84df735f59a2ba7047d3af0d9b59467d7f20f72f355d6d06b8f5ae4eb5ee16dc88380a60055c5d0", "SEC": "0419809c7dc06fd525e32fc1ab821752511c270f4f8e87b0cc38b33c885aa5055d178c86779dcccf0c07939b833715ba9337f2c5f8fd4b1b4dae35d2d053d8469d", "TP2": "0407985555bfc311d41ebf920f6ec22e7c6a459dc8b9add30b99ac91aaf4bde3c414583c0c51be4f56b1aac0789342a0c40ad2602afff221e68241797b8080cd04", "TP1": "041c2bfe70eb7cc2817e35d6c2a05c8601ad859c76070578978fd3a3cb04471b9422cea662ac1df553ee07aa72441242eb4926ecfedf37c43cfa778b813ce81770", "CS1": "041b3364e0b72b0c73cc51ff73506070ef2fca6d08359f9ff4db35394e24e5c21c1fe2c8562776d97edea51fba07d0ee2bf8e7baf01c4cde4f1b507abfc8e54bbb", "CS2": "0408f0de87bf3f602e1bd9f14508e43f9aeb5fedfe2538c49d582c1b55cbdff54b14326e7967a00c4c7a6e6a0cff370e70e2429678d9354e2ae7d4e6fa7c2ce8df", "HASH_MPIN_ID_HEX": "94e3f02198c18b6cd6bea3c71ad6e4ea615aaf1d0f948777b0d8e2711e22e4a2", "TIME_PERMIT": "040ad63113f9e92634b8d063844b5ebed2c95ebbb8d626e7ced53cdc619244d1d60f1ef894d4b72c69e7ad1710188267760604bd61d14520f289942912d4ad691a", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223461323532303762613139633730616335303465393231343066613630366666406365727469766f782e636f6d222c202273616c74223a202234323439303061333863666364363063227d", "TOKEN": "040917c5ffba0ac21860094fdba3948c8325ce0820a0d4db4b28cbb4625387630b197662fbbf46b1f6ce31bc69ab98a6a54792fd7167acb61f1b8b673a6b2a5d51", "U": "040154002d034a47b56526e063c64c2630a96e171558570c41653be539071e4dc6162e53aa78589139e3b7e4ee8ecae8213c2c19990c1687857abbfd37f927f474", "SERVER_OUTPUT": -19, "Y": "0a2b3640530b3d84c3b3b189bd52dfda5b41c1a108a1495cf73c0be0fdb0dbf4", "X": "1715550a390561ec9ebe8b0ec2a60005f2da21d8a8d55bbd674c725ece91b377", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"4a25207ba19c70ac504e92140fa606ff@certivox.com\", \"salt\": \"424900a38cfcd60c\"}", "test_no": 139, "UT": "040caba80dca136eba2cdf7ae94059e9959e967d9ccbb5c85baf7062afb337eab10eea628d95fd2debba916d6ba2e22981277916a8a0dae6aef8e7dc9badd9b049", "MS2": "0669f6c9866973ddad40211897f8f6808faef7ad4b97f933ed3740e678384c76", "MS1": "12deb9fa6b1cf00b96b41e7d7bccd8c7ae5ffbcff956ba5affa935bb3a8f5bde", "CLIENT_SECRET": "0410803563bf7baae27e37321285cefcdb6a84885f4e3f48cea6988090aa25b0130faf30f5019f0de8543866615066cc7b5819537b794e3cd5ba00593f457774dc"}, {"TimeValue": 1437055596, "SS1": "1c438a2cf1311a06efa3839b024745b19e6a74235dba9911dcb40c33384b7887147a7dd4318556f04558ba4b5bf24fa44c708c08370458857b0e95bca6b4e91b0663011bb0cf3cedcb92cc6f02390ed603eaf98ecdd07ceaa59faca42e7574151f1b3afca4c9f21bd713f23b066eb98460896ed821aa555f507a1e24912ec130", "SS2": "16902c324be3a4d8f683a1b6a03d433f3dadb49954c8a3792838d3d4c800a8f6211c0d36264f229dad3cace431a32d1e0aba88ca6babd1bb473bf017187cb4ce19c0eca38c3e4b93ddd4065df32bf755324aebd389001d9f12b6cb31f155936a04893433a04feb141442ca7e13c364dd1b5054a1d7b71b66b03010a2a2dd53c1", "DATE": 16632, "PIN2": 6106, "PIN1": 6107, "SERVER_SECRET": "018061807bd1dad8e214571c0688d4a8a842c20d66ddece1389b9f68b4d88aad0fd4ce1aaf93eddaede0ee08879768420c139b697c282260bf4344dfe717e6c619b3ec70d2b55258f7baa89a04ac3179a69bf6a1483d0a2ac7cace39eb71e54e0e7b25bf5938fd85ffedff352eda3236dda5c6ac893089542777761fea3f4e1c", "SEC": "04157190eb56f3d90acca1a2f7ffa235937156ff8cdec0ab7a1a1713d87a2df2d51f0e4d14090f64f99cd783607a77ff4982663851cc6c1b156b2b7aaede2b5e90", "TP2": "0411d7b8d5c9bd837f9617ad71ebe04187bed47b4f76d4c461ec681dac2d4bb4001f772698069fcbde2cceac946fb1dfd5a5ed0293546feeaab8efd5fc55786971", "TP1": "040a87e2f85e8acfef97f17f3631715ee2aa8b7e93b1c2e66ef33f4ca33db16fdb23305c508ccaf9384b3cba89adf4b1bc02558ba052a5633e522bb8cb6f9a4c25", "CS1": "040331a647393b7be5f0f2a3df1c7dd07e82d308452083ed9be97fa7b6154eda0803fd48ea4fc61759794b15e3f3b6db0051e24f7631a78558ef49d2a7003adb71", "CS2": "041a052aff4fbc492729a2610ed3b129fa783a0eebd5ff5eaef4454186286e98df13c21fb290eca3f53d295f803b2cd200f101cf8f5c63233c0930fd4f7e9473e7", "HASH_MPIN_ID_HEX": "1f9de43aa86c9e4966ee70ef6665714354db66fc62cc71383b5c8e570057aca0", "TIME_PERMIT": "0412bd9ec39d4a9c6c8972c6a9e3089255924a0d58d973e81300ef916c6ff6a66f12975b10ab8bd0daf4ea3f56d4c29c33bb85d1fc637d25ce1a863db27ed5c1b4", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223536653462616532653365393833373439616634346461646436346566623131406365727469766f782e636f6d222c202273616c74223a202262386330343261643633343062333164227d", "TOKEN": "0409e82acca278ea1cbe497d412efd48a7ab74fb5019f0941d4ec2af04c7b6b992004ad644ceb35be108945b5ce4894df34e2fcc8f874c38a8d8b11ff8f655678d", "U": "04032691e5f6fc2a7eee265eedd78282e1ac75c8b7573d03e0a9f3b93565ea3b6f1f37f211a18a04a3dd28d3a57f73546891383b9e917aac869a11453b6569b622", "SERVER_OUTPUT": -19, "Y": "1282e9ba104fdf8266616e6045c4842455cf8f8aa6184b5d83fba446262715aa", "X": "1eee2c881a2f703ef0c8abd467e47e2e13fae98ca0d83dd678524451bd77ba41", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"56e4bae2e3e983749af44dadd64efb11@certivox.com\", \"salt\": \"b8c042ad6340b31d\"}", "test_no": 140, "UT": "04159e5d55fb7c4bede88b15382db4885fcd6e1618611805540b4615bc3609ec090cacf80364c60eeb5d761c697ddca8fad1bfb85caa563f072a4398256feba739", "MS2": "071d1e9f339f135573a05c512cde801f56f809aa7cfb3cbfa7737050f8139000", "MS1": "1e32c1c633f33371c0cea894346814038cac37a6a33ff738bed49cc37327b4f8", "CLIENT_SECRET": "0411964c851fcf91d1057872cf0b663d4a85978011c5f61ab1d3a00e3e6556e0e01877cc29239fbfa929126e7da23c0274dc7fab2221af341f43bbdd41816df584"}, {"TimeValue": 1437055596, "SS1": "0919dc15900cc1a9cfe245a93e9a06c173b69663fbd4bb3706c712d32b03789f089f51e4b387ccbbe2ed8c13f354765c32f16f1b5045a7a6acb593f0f51adf7002a16edd29592336471178ffd5aaf991d6a77af6284c460132f3f6e107177d8d1f8f77b5a6a4ba7ba7ed9eb7f68a87a9205c9de44912025957d937159462b494", "SS2": "02ae1b845f2a4e59b368c4993ffd7fcddedb40f801e4f8f75b7f123adb38560b0944c62c916f8bd0181bcf796e18d4a679564289b3ff07701b108e4b10c426eb0606653f2b2721305320509e9dfdb9463893f958d28500156d8c094c09ad14d1209dc2526c2962ef584c2f386e3bc4da6775078765c67ba2a725045ce17ca2d3", "DATE": 16632, "PIN2": 8710, "PIN1": 8711, "SERVER_SECRET": "21ac5e6369283094d4082d44c52f74ff59e7669164bb996c42a8cc7c48fb426623a1a40e020eccd7b3908814147fbca0a7b52bc3229f312189f5bc0cf6f22aca1d1ce01d62083fd993fbc34a9212cf6e12aef47bfdc8c8278996a644a3a4cd220cac6deaa2f35287e70dd9ebd95960572fa96f9c5ee49146125fbd68ddc65aee", "SEC": "0416e662f12076ce986a539cbd70562e6a230b58c99f437115d42dce28f77179ee112788416cdae666ce493afca86e45327ee9ca8dadc30721b5e8cea018720861", "TP2": "040837094f69c7cf51dcbe75b34e54ad4bd3d84122778aa7d355721df875754e141e152fa7f98e6570fa3c39faf94bb61c5286e1a4d671cf2482eecdd3a8c77d1b", "TP1": "0404d6821e0023047db46fbe9e894e4ad4a3168164762f2985f94679dae522e7540c375e2bd70291391995a4a26fb0419252dd8250c3743cdf65739eea1661df1a", "CS1": "0423ff497f6f8f28d63d1266217a0a6596e631dd2bee8772ab51dec8b03765ff5a211af7d126beb99a1e014bad6f60108752949981786062cd8e2eab914cc30bbf", "CS2": "04003fc38dfaecb66c5555ec2de0ab027cfe202840bf2f1ff815de3fe19a7f1b8b06aa0497ab2ce716936721c71cf330cd8ebbdeaa7718363e416d6d2e2b14c438", "HASH_MPIN_ID_HEX": "7deef0b4345ac06473b313aaa12182f39c158eb1b03931c8dcbb0cf954f94748", "TIME_PERMIT": "041de014b0527188fa6a1abe70875f1f30a43573ac24e9098ac8ce4334b155fb7f00779792a439422829b71cfc8036f1c1754956ff54741e7af288bbabc63d7906", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20226239353161393539303761373334323065353961616666633265393439336331406365727469766f782e636f6d222c202273616c74223a202234623935376639636334623634386437227d", "TOKEN": "041b8a4b2ac89975be6495e8f687607319444d6bd1c86ebddc4e337e5cb82cfde71d59182af0361a3ab2e08cd993d180e39d457d97d4b188b0be16fde2b83f229a", "U": "040cc2ed25a839a1e5f7e7823ad115269ccc28aa535c129504a88e0e7f339772e8191f65b4274e9d935efcd57a800b491a06fc43e66c857480f4860fd139c98958", "SERVER_OUTPUT": -19, "Y": "0929d219692cc654ebf4ddd0f01ff02457cc906696ae7278487e11d9fa39fb0b", "X": "22c20d56952fe7482021a027a91c449fd29dde09577ba91652018d5e48e80e2e", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"b951a95907a73420e59aaffc2e9493c1@certivox.com\", \"salt\": \"4b957f9cc4b648d7\"}", "test_no": 141, "UT": "040ddd609fc1f516724d7ec703f146b653b434108c7b446657273a83d3b22200f515733d02b9deb1ff66107f2ca0603de401e2fdde1c0c10f0f917af29a2540af4", "MS2": "1bb16167a310859535d91beb6fa761bf316065d9327336c7f76097997de0dcfa", "MS1": "0a365890facc7cbc18d510708854c73c82de86d8389cddeb54fc59ff4f4e54e9", "CLIENT_SECRET": "04153c8f816781ee8c1241120d74ce92170590860f9671fe448f629267a63531c81ddb9b95548d47151f5a660a4449c887d628616145dfdd9ae1b6d25feeb9dd98"}, {"TimeValue": 1437055596, "SS1": "10925475198d51c75588ff8d7acde3a719959203e75596fc4820da819a0520ff0dc02126fc233a7d99647f499d8cb816a8f9e131c7c26ddf27f70c8dfcd3b71009d952f15ccbf4a3238fa7ac31de1d47adc7acd4fd85344a7cf050e8dc0fb551085922557c6dd49e04cf50a746bbfd6eb339be714acecf34dfa8bee6e7482417", "SS2": "19ad43ffb5c4bc32a7f86bc7a98953c77258df2677ae4f2766613fae95be5adb03ca6334aa3a987447ea14fdc99d256191f0159814f8b02f4fd6b66aa453222a17d98063936a3a40805514f1769f1e334fcb91ca5d584781d4f29b6e1aaf085c23685a45483c48e96b5cc6e729b2a72b68337df99068dc075e59e9de97ba6122", "DATE": 16632, "PIN2": 4377, "PIN1": 4378, "SERVER_SECRET": "02f4ec371283c247bfce0dd4b28d29e18a1918443a37418ff1a139b978e0e0a122cf704921daaf119bac70dc3a62088fc17d15d9e9c1bd1d98d79fba8b1326c0212c1ec924a9824ca043e5f59db70879e6841cab2b1d29dba1a53e42404de2651b4ac35e35510bf1ab71642d30e79aac843b900fc430ad751da3e1c24a657c84", "SEC": "041dceb98d7bd250d0c4851a7760f620bb21a430295cbd26b301926631ea9f599703ca12320dd74908ee474ffca5966154bdd7eb80e1d41c148cf4541595347710", "TP2": "040074d0ddde1a9889ac12ab81ad4978c6861e60d3c8d8653f2affa7786bb622671459fa0e9f07fef03608c627482de2a8c0269b717857ee4e5489b29db544f5d7", "TP1": "040d99e887f4f3493042a5a50cae3d10624066dc1a6d82769c0846919fd477bba41fa1193fffe8f14db0a826139cdf2a604eb2f903efa90f8c36f298c82ffd2d18", "CS1": "0416bbfcc1da3dd7dc7a54feb5fcaeb761c21519182fd9b386ed357479a6a330760566d952b4630dd02a661f21fa716064b9e6aa98dd8b8119de9b2a5bc5c854c7", "CS2": "040ec9ac6006055d6f43af4142ec0fdb5b51c57777de2eb29a0936adf9fe8dcb77211b6851190adcf6fc936fe192d179bc2c262c0f63a4303ca9c0a4442c742b26", "HASH_MPIN_ID_HEX": "fed8b530a7108c98d897a86647bc3253863b84df35c656a2d44b66b2eb888ea5", "TIME_PERMIT": "041dc190e59b76906dd0c3de5ecb5dc6620b8ad3529ca33bfa8c03ed5129dc07231af5a3328c84cfed4c9b1569eec1d2f93408551c369feaf751c6720f9d9a1041", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223835356135623765373735363634373838656533373732393334343066666162406365727469766f782e636f6d222c202273616c74223a202263373563376633353363643234373164227d", "TOKEN": "04119bc197dbd362525c169761465267a4a8234a888ebb7f19dcfd3f9d72bc04dd0e7e9b6b390e8d99256517faff9b389a8dec1deef3ca5148d78103194669fc65", "U": "0402a402cd428b38dca7b533864734c718fa4b77d9abc2c38d26e1b7c7324f5c271d57c5547c4256d3124b0d80ef7151b1180d45ead85def66291384c3624e97a9", "SERVER_OUTPUT": -19, "Y": "026ef6e293bac07eaf81bb058a1f706f3202b75209354113f821ef4de49a3582", "X": "16dde8e14875a39c0499a0eadeed2e6fff6c52a2e3538c175f3373f4d719c891", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"855a5b7e775664788ee377293440ffab@certivox.com\", \"salt\": \"c75c7f353cd2471d\"}", "test_no": 142, "UT": "0417392f502a517972b656a4dcbbcca3f684833551720e403961d677d45acee663011ee58e54bbeb642f39bea1bedf40509b241715dd989e0056bfcbe5cabd00fb", "MS2": "03510ef755cc1457395d11453eca5416f52f65b5afb41cbd59dd6655a4755cc4", "MS1": "1a1d1805ed547ccd47429468161abc0d9f8549044d542befc198eaebf6b1c7c4", "CLIENT_SECRET": "04141cc864504c7bda3b5fde724f86149fa9edd0fac16b894246bf00b13d62838e15315dc5de63fc077d4c7844330270ae462bff8c99fb558860659b229095bb4d"}, {"TimeValue": 1437055596, "SS1": "0f137361251c82abcc5e92688cd9c3ebfe0557636606f735d7115e105654e3750c3aebaa9c98718c2b0bd3e8824803608ee2d67ac160a7c7170561eb113cd30a1fbc5d077fc39b8b862027f0c0f04ab67464c5a78f624999f50ffd5cf36fa5ef20f1b0f46e39b76044b15db33944f8cffe89102c8dca844807fd16f691cff2e0", "SS2": "04b3f13aea2f3a49cb0278e84715d151d64f82b2f2b84a7ba88b3d177641587101d96b6ab14c965c4fc88d4109f5f518901a4802514d30500d1ee1a6122a171916efb1b1db46a59175b361468a6333e74b4da011a1fc94f8c1942bb599d13c9515acbae6559018fddbd4dc1943ac01d23d554d1ff10853c44cd8cbb3ea8625e0", "DATE": 16632, "PIN2": 3315, "PIN1": 3316, "SERVER_SECRET": "1d8560be032c1f606161eeb56f1ed07516ed1a9dc8f7a6d592a16c9ce62b0f05207797228ad20f3355d9ef5a16eb8d16a81f7022557a060804217e12b9e5361c2180c524705769d99fd503aff4734351faa26b0e43195c80bb2ae0014756474219d848670f18baa68fc121785d59d4b5b45cc89720de48bfd7c64648d39e306b", "SEC": "041afe4a6ec2d956a67550f0da3c9a31582ec5da4d67529e23e05622c55f2edc9b0ba655ef699bad4a7831d9eff1578e4d5d68103ccb34822d4727604f527445e9", "TP2": "04219d437c5655b57bfb14d90aa33ea49131dc351d6bcdfe6e1c1630f4c3c4a36700d55dda776b40b2cc311a7215a7a1d5cf3155fded0765201e9c526e493f6c5f", "TP1": "040e2ccd846a0350165f90cb3949b267be5f11adf14fed5ea6de12dffb3bde3203131ef5a8c0c0f720ae8655063acddc6db87133a9bb558e4f3cacb3cd76c6a53c", "CS1": "04161af46b63ccd50d40cebcc978da3af313a018634ea28b9762cba6d4d59d64e721c7caa009691944b35b3c54fdd257aa796ed79fee454dc8a37de3bc0fd5c3e9", "CS2": "04017c18038b2454d6441487941f120d0518b1701cfd6a3faa54769dd8c41316770660907ffe6148250dc99e08ec088c17bd8fbc607a452b3635cce7c6cc1c4551", "HASH_MPIN_ID_HEX": "48fe147303b6036b2cc5f187ee620912a81d844757f8f831c27d7b189b66ef3d", "TIME_PERMIT": "041a6b87aa47926ca6bd6534437ee95f11e6248336554a8c539a81ce4f8078658f0170fcac57e64f270655b440bc086e5a8fec10b3d99021fa1b963640d33f10fd", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223964346531316134373665616135303865333337316437373231616332653262406365727469766f782e636f6d222c202273616c74223a202264386338356532356435313931666338227d", "TOKEN": "040b7cd4a00d964d2058cadf51ac762b83c33f40dfe6a8f4eb204a73b9357909a50263023d91e63cbebaacb904c17b9ce0ce869b28c7576907dff3438a7edd0189", "U": "0412bf3d8e163ac79706ae2013ac0a31aa6266c1940ac6f4a3622b71c6263b718511af62c828bdf97c0e24cbbb6fdad57cfc0e6e675e15abf95b7f7b08a688877e", "SERVER_OUTPUT": -19, "Y": "067cfb56ccf65ba581a74584a6584110a4f261af0b81a45bc7f713ffe79f7966", "X": "09fe51f9fb70379d8679b2ce29e50ce60cd9eb3751caa678d37e5e6c0c1ad8fc", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"9d4e11a476eaa508e3371d7721ac2e2b@certivox.com\", \"salt\": \"d8c85e25d5191fc8\"}", "test_no": 143, "UT": "041924731c354980f0e3b827a7a0dc09cb050e03df3732de2eee56c09cef0cd6400dbc13a4a3a4b2d5dcc3e4b386a5e2e70ff9fb3c59d18a0f3eae7940ffdf255e", "MS2": "1d52524c38e2d15400421eeddf929300ad57625828ec926aff43986b17ad057d", "MS1": "1d09c0179cb2c409e003317a93a912921d667773123a586bf4776075955f3cb4", "CLIENT_SECRET": "0407838b09b80fa763329cc4b4b34fba3e8c08ee3880d0ab3243ef48b698246b2911be6ab64f1104f7aa9104d71f0359af63a73d988b15550f24f28db71aa6e2cf"}, {"TimeValue": 1437055596, "SS1": "1115df9816dd88e70e4eaa634da6c863a214e8fb4d5af7eab1a9858f1dc67f5c0cc8af81db39fb0742c09af2823a7263c143fd543aa5128ef4b1f139c24f9b64180ae4cefb4c12b3cd0dd6beb67ea8bb58fdf0644008732857afcaad936bf1000c84203b3884c091e5b9f80d6a346402b2edd5144f71235d3afa4837d711a964", "SS2": "0ff16bb44a0ae5e3b0bf93d7421bdf586a5520a7462716a187a0a3c82266ca021f2c8fc9c6ad92f4e86efdd5e7506e5c3fa5ae80876a49e4fb6a833a6928bd330b67af2f4198afce538bdd36567c339e5876be988ff4522eff15229d92f731810a0186a23ba61f656f7fd339dcd7b46076db1206a70b0389a3b601437be6fc3d", "DATE": 16632, "PIN2": 7640, "PIN1": 7641, "SERVER_SECRET": "2060736f063492eec25303837bafccc6a9375fe157c4f5257a5316e7c37f37f019822ad949f5047887afcc8332be6a0c4cecc7a14547a9ea93cfe01e857924530783a0e9d8daea7efeb8957e336a14d0cd2d324db28b2e9efed3a2271ad4ffd50581ac4fd0efe74950ac62e47698a87f929df16f56307418994b2454563b67c8", "SEC": "0419de6fd42e8550f8b44c1f9ec1c1daed8bd59fed47089d5b4f84f83448f34ef9132137142f3e2a70de9a7a365ad2e0a12797e86ea92fbb5c03745b711aef3669", "TP2": "04021fe5a96d4023d4ba4ef18d9d9ad426290ea815d7df4d64b3ffdb045eaa75b11d7b491fd97950311d469c281be1ddab74b246164ce7aafb675dc9fc770c917d", "TP1": "04043639abe0bc9418adc79b1caffca8119f829e3dd31428efc90120eb4d22bb36131b61378661586581364dc28418459290e6194b0675f88d5800230763f50600", "CS1": "04035234742c2abda2e8cc2e2ae62c209ac2fb4ced18c64a6de4ba47cf86cb7ed215999f7dd6dd3843e323de55c46f921e69cd46962f199173972f430b0cb953be", "CS2": "040be751c4d535a7111606c46e74227ab7b5581de56458ecb217f6099ea3638dbb202b8199e0f2f42c2dc4f9db50cb9125d39a1ac9a3f1992aa51ef6f2f452630c", "HASH_MPIN_ID_HEX": "03e8485922a0a68b33667d86e2f6c51010df4812a18520d8e2611e262c1903c4", "TIME_PERMIT": "040beebb6a0686ebdaab3bfe6f0b8f1e743124ccff7bee70a95b08e0038932f0380bfed79cb60c16ce61e05b8dbd07fd1814931dc7661655ae4e29710f750d1b83", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20226231666536353935303232313934633935613139306139633463316535326564406365727469766f782e636f6d222c202273616c74223a202232366465373832373633636333623363227d", "TOKEN": "041c00bd24982adc1596a17a9eee4af1c481e1772beb6e22d06e06a1f189496fb908da985418a3db5eafa7deaee13e4e2174df1d88acbfc4caf8963044a2d9bdda", "U": "040539a501be7d9f1ff9b1e1e6fd1f10f072c107a506693f5926762ca822f267610bcdedfc284b393e569167fbc6b0b5d046367487825ebd0d724c04ea2b4be1aa", "SERVER_OUTPUT": -19, "Y": "10d1f66cbaa4dd738dbffa39513690bdb620ae4d08c5eca07f53dd457893e674", "X": "1a0fdfbc88f1a6bd346f883e8354d40239c13358bc5c73320e9d956d25eea853", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"b1fe6595022194c95a190a9c4c1e52ed@certivox.com\", \"salt\": \"26de782763cc3b3c\"}", "test_no": 144, "UT": "04106e120fade48db94a97bf4e55ab9a7b8fafe6e88dae80593d69f9864981c3141a3bf631246513452dbb3a88124392066cf175dde427290b553e798935d67b98", "MS2": "143892e69563584b77a1bd1cf3ecb56c126dd88e1d316bd6418972307d8a00aa", "MS1": "02b7c9759ba2f8b2dd2137565a6d1541a96c3c5f623ce364e2fa99e839439740", "CLIENT_SECRET": "040b06a57e83109ac8694c35ab23c9f9b49a621e11763b5eee0579c6d0b43df7e205c77c61d78ce5b9e626170b386275d33a39d75f7fa66bd3416d1859a0a0faa2"}, {"TimeValue": 1437055597, "SS1": "0e982d5fb680baae5cf0e435c11deb286e49bd9a348b10c8b27f61a0d244b46c1f44d26bf5dd0e09dfa89c488d23fc0a0ec0cd31111a4cc5b3f3e88b918c178e07e385304ee7e5168e2362c53f79bedf57e2cc6febbef874ed1d44be2e4e9aa904ec0c9602d10ed3bec670aab21f0973736e2e3b1bae733ced148785bca10aa1", "SS2": "0cd2ce566589e1fd4bc726489900c1621b35b5bc018f8899d246f6c1ae05b162174710c5913ac729b44746e023d0dffe0593ee8f263d7dcd984520e2cdb4c84206f21b52599f32f40c02bceaf8650d6aaca56864a76732d1895136ed77ee67d21daa9f7bba6d8a9a17aa269dc000be2778163d1ae2ea8a4993280e192c6dd158", "DATE": 16632, "PIN2": 6324, "PIN1": 6325, "SERVER_SECRET": "141622ce13a2ea3b2f7facd1877831fd0b37dc3e1827fad44e84ba017431cfaf1e1b1a3656b0664378ee668d02ee74c521b8ed1087f52c17f622e0717c96beb01570b24a2fa5aa3d1ef849edc423447c382eef7bd3977d8a7e8780b84726a4380e9a4a7e29a8775a9d7f4e37138cd2fe6694da5470a102d74bdf5bca8330b5ab", "SEC": "041586647dd817b79eb289a1725ccf12dea094dff6b5ff53793407596b59e1d8ab1230f4030cfed2a15db077fcd0bb87f050841e1d7ccfc61b6a56c5405efe3e97", "TP2": "040126772b5019fe4aae4cdbfbe6c6c8ff5723219dc492fb1b0135225f2b1bee660a768dfa52796b1abd8f42bdc36be9142e4c0554750a6d5672f01177d1478245", "TP1": "040c26c2f23e05e50651e6b8e3903e06359afde3564bd84f6347993aa2b60a024f23cac0617f3d11d5a48183c0747b6094166912f2c2582a9669a24fc87437afeb", "CS1": "0409a925151d2017004a0c30b2ae0dad24d8bd9b75a5f633673faa94ae8cff05c92043e4dc114c68e61920ee6968c184535c0a7cebb5c889c3d25ad71927d0116f", "CS2": "041ba523cc36c92a65c3f03acb444e8491b826f502940ca16d5078f577804439221f3c41b0c7c5508efdbb882f5ba7c6c85636bea91d8b017a9b5b9ad7e60dd15e", "HASH_MPIN_ID_HEX": "8a1e542e254240fd41abf19c5f2e58b164dd8fcd5be667e2eb1395a4f44e334a", "TIME_PERMIT": "0419bd110eed78164336d87c31ccc5bb5517e718fa727dce4a8a52b3e039b29b5b221fc49041d3e840ed49a5e43abd850d2db430ddbb17ad2d417515961ea7c714", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20226136613230303137613734623738306364346363303736613130643530303434406365727469766f782e636f6d222c202273616c74223a202231636139383330626536336434616232227d", "TOKEN": "04157c58ce3f8311767dd07afcc50706c6491afcb5aed40e718fcec81dfc164cf7025a4733256a12fc5ad08f7ce7ec647a4f438aedfd75be0a5adedd4c0b1d4b00", "U": "0422daef39791f98462fad80dbc28d83fcf8a5aa30d06b91027ab78303697bb0b10ab663f0bfc2cbb2ccaa65fe5631c5206e20bfee1ea177115790447cb1876474", "SERVER_OUTPUT": -19, "Y": "058f58427539152100ac58a24df37f59ba3929e1431b8c53be06f5a6299a62c5", "X": "206808ca92746f8c82207146abe0c002a0258f24fd2333122706092b376201ca", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"a6a20017a74b780cd4cc076a10d50044@certivox.com\", \"salt\": \"1ca9830be63d4ab2\"}", "test_no": 145, "UT": "040a37fd0f7485f3fe192ee2153f02b1cf5939eaa62d8cc3c12cf055c9c096441f0f6197d936ed406357f8bcd086443c6a9b39348a00cf7b3d7584e023c93b7500", "MS2": "20a2e6816996064adc7729e935761f736fe6090b04eca42fcb6fdb62a253aff9", "MS1": "1482196e4ab530f77e9b8d65226b09b69e9049e18f82009df74d8aa115fdb384", "CLIENT_SECRET": "0402f27d887fc4416e9a5c7a598efdd4e8969d01d81c48f6c451671b22b8bf859f10b392ed044476752dce9e65457b8a60a86e506d43784472966617cddd28c544"}, {"TimeValue": 1437055597, "SS1": "16c9cff94058abe7cb7e085894f147be7666ce3b221d05234b3ca7241b463284075039d65faf1ab7b602bded402b0721fbbaa2f4016c227b0ce223632d5e612a0bf386d5fd4ce86f7f37948652dcb013de549dd74bce746059da472c72d868761fe984deae3370ff238e82039b45514bd833509f52f55fa9323003ff75a3c18f", "SS2": "0b1702558c9173e64537019976409f22a1d69a81c9b705ed4dd65d161bc1a0390ef6b4a91831239243367324ad82a02fd2ab3e16013fbe2cf286956069b2019e09aca7a0c34801f76596ecc11a631666dc596670005b33ba8ba28ff34cc7f4431e9845a9de909b11ff8580ba766cc687221faad1e667da390f7865480a517296", "DATE": 16632, "PIN2": 9556, "PIN1": 9557, "SERVER_SECRET": "122ebb7560370447b105930a818b345240a725007261ec446fb07ea1bcb6510a0b3a3bd489f41f8cc9e26fce347facc574b62f90da1b1b50abccdfcedb02074b1ce0004be969089450e942fb1aaf760107e646cd560b61f46c3a1383987edcf5007854e40376caaea37c86b4747f9828a6b009076fab9f3fdebf15ecc0411dab", "SEC": "041f9f83eb8fa70d95922b69605c1a9e11c42d85a306b3bdec36578cfe7ea2c52a02710e996fcce2900d032d7248ae2e808ba2c9e858a0c04508d329a386fad802", "TP2": "040e7ca51263022ff42a7702c5acfb5d99c39e04e08f77df1216c25ca052c47a8304854e4e6319cdfe1e89ff5ef6fdb35e6e12abf27aa8cb2c4d515b932d32bb75", "TP1": "041f2647c6dee5dbbe53936fa1cad7563f09178a4e4fa547623f639a8d1b1f9d6d0928c8be58e93cc66eeb70956101fe6ab91420952228ed05d2913a9c36e0cf52", "CS1": "0400dbbf19abe5a67e80790f55dc22fe4eb8759ae5f4a060707b57a101db9b10731e5c384241365f130ffbd2ad8e257936a9b8994848c1bb5a3eeb83d61abcb8e1", "CS2": "040130cea3559401213231463f08e06fbd83ff379d0562c78440b9a7b5137d126a1c725048c7be9621eeb9aa678cb2b105de31f843b3f4c10a612f2c5587ec485d", "HASH_MPIN_ID_HEX": "00f0fd5f6a78aef02985f125c16c4084687b62b55886444b16151c050dbe7b8e", "TIME_PERMIT": "0411a086231347ee9b8f18aa54fe0a9ff5236b063c13e87d73bb76ecb15eef18650f1a4605723b60ceb59c2c821254f50ef8c450e73c8a1bf7c5ee0843e87470fa", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223638623831633965363430393266303438643663663237353130653131633339406365727469766f782e636f6d222c202273616c74223a202233393336326539323735353038663862227d", "TOKEN": "040ecf54ed61bf265347e63914b176dbf6a547722f0421ba8c3429d6e0454913b704cacb77d21da918fe3d93d485d2d27eb3f4d7dec839bde801b5c44d2509335c", "U": "040b003ef3e8945a6387e5063bb79c91778a527b8054da85c95f80437411e9f5f20e2f4229a1434b8902953efaf71ac4af82a6b8f65efb24db51d559fcdb65eac1", "SERVER_OUTPUT": -19, "Y": "1b74729857367bef65086f272d068435d0b1cb555fdf3144e012b260a977db83", "X": "125856f369f6a17ed4726e1733b42184cb211bcc5c48b2cf9dfcda7c7ee34816", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"68b81c9e64092f048d6cf27510e11c39@certivox.com\", \"salt\": \"39362e9275508f8b\"}", "test_no": 146, "UT": "041bf11398b9fb3c5128d6c469a03902f02b63dc922fe5f717ea2092cd70fa02811b5325f0d1c7779fc1fc5ebde7226f9ed992d2a10a3fd707c9d91a51b7ef737e", "MS2": "12828d2012b5b37cfe75753acb4097d5d8ca73d7515f86d3ac1a97be9b2e8634", "MS1": "1b9d386944d7d8b8a7eb8391570a29e20c06e74a39dd14f2e05e2b846d82e09e", "CLIENT_SECRET": "040a53b4bd374ce9242ce252fc7b76d090114c9858fc5378e232a9aea920c0470622a5265b0f0b018b5315e32beb6fa76c7e94d6e8d9934e57466940b08088d402"}, {"TimeValue": 1437055597, "SS1": "22eaf2daf03919afd51993f6dde485c961915bfb5aa00bf2a5edfd118eb0768d0694992e8f545a5764e0085e6180e436bcc50211f97545287570f6057c5817ff00e2fc984123635e0941500461b1373e6aa195fcd003fb3fad55d2ee92cb903920b0ebac9cdc9b2075345f63ae49feba1cc7e665905a319665160b94c2793192", "SS2": "1d5a9949d0a7e8e70e65bde6260acb597fe3ec46b46d7568a4b3b1a52f934425092dc4b5a7813a739b18f858b35b5453996bf9dd2246650761e02f0e0f01e75d1ee0a2ccea902e16875c3a2a4bcccb206cebb4fa46a55cd8f1e592a1863757f905e58cdba2986160ff196e9d17355711edc22778d9dc73e544645bb10085e4c7", "DATE": 16632, "PIN2": 8037, "PIN1": 8038, "SERVER_SECRET": "00d5867d875422145b0dff65ca725263bc9c77ded1b8b2941c338d23fc3c35620826bd205557ce210ef96a05d2444436e39e7e0805c43ccb60f5f7096eb2d03b10feb7e3ad2c6fddaf95964966c8e0eb5923118ca4430957042662d7caca9b1d08344e954b5e08548de4af2088a2236ef1942467b74e7b47bd5d73a0370e8d52", "SEC": "040fc96ffa9f2ba2ddcb9bad2febb86961974cc8959e1f04e45654fdf3fc5506430bf5cae59215bfddf86dfeb5e6eede78f596fd20fb562bba1f37eba8802aebb7", "TP2": "041e352dfedc89f26d013627d4245027941a651c0cf787005e0f7fbcade3e8fe4e1e0efa4daa3f9d38c91ac1fde8b48509cf80eb379c6cbdc83113483031c7b540", "TP1": "040113daeca40631a4595d6290d1ea90317835cd255d69a90b4bfcf984fcc896fd23418f413ff348795dc20affefcfe128938ceaf1ae6b82d9367ce75d814f376a", "CS1": "040d16db1c128fcfda5edf063b43541c3a7f4f75e30ba33cb68973fa0c8b9a8ea4026a3166f7610c5c750054bd1aa5071939c48332199ecd6b41f4fbf257ba2b48", "CS2": "040bd79349be6c7cab17acda26286b637e80426f0597fc2ca4f3ed761c9a09ec590a1de6aed0c1e39e107c1a0ebb7531166e0ba527d6856dfbfcce3d1579f4dcfe", "HASH_MPIN_ID_HEX": "98d35437347fa19c4c55e107e27d388b6a4f75bb888303315865bffcef02b073", "TIME_PERMIT": "041574fec3a705a4331a1eb71c9a9306f61e228914482218b4d5064bbf76bc193d19985ab439c59300fa3bce4d1ddd3347a1f138b06f6275e3d0cef4e26810156e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223234643666396261333061303938333534316462313231656261343630636166406365727469766f782e636f6d222c202273616c74223a202232613162613937323038396362346664227d", "TOKEN": "04044388115c9f7931cd7fd7c8a4b829a584df441c888947492ade862e0a33468202a46542300ca3caa9abca8e535187907470d0a50f92f839dda71ecdd0ca947f", "U": "04028c658c392c4c748653b8ddffbfc2c040b6fd7eb74a6d02cea4c3300d397b011eac01fc49e87c297570275d638dd8055cc5ca98f67f1b287dbf8c89ab9a494f", "SERVER_OUTPUT": -19, "Y": "0869df41de93d26f29a7d57befdd499b356244c01794ef531bdc72c6324a6f1a", "X": "17b8245bda407ea4eb3b8d5f83bf39d92fce8240ccc9f69ba457066dd8dde464", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"24d6f9ba30a0983541db121eba460caf@certivox.com\", \"salt\": \"2a1ba972089cb4fd\"}", "test_no": 147, "UT": "040234fb35908825769b1ed3266a82cc833194f2cb9337f4378b142e39d263dbe705d1aad23bedf39f1673dd5e5819982b215f624151da58716c7187d6176fa06b", "MS2": "00e0bfce9ffe5c6ef8af3832490833b6d924eca4ab5e528a84c1333f05307ae6", "MS1": "0b191dced79effdde8a701538cf3395f56fa17788779437632b68deab3e6d497", "CLIENT_SECRET": "0401d2ffcee21109b677a00f69057f80ed0a025800b1268d0a023cc0a4cfadb93c10fd49127aac2f0fcdb61723f30af883ff79538764c2a2c9a2d81d600a0b304f"}, {"TimeValue": 1437055597, "SS1": "159b1f97a761e004c8a1f30760ad20a2c114aa310a0e5f9e72fa21e27d64bc0f125eb596cba6150166b8aaa216ee207cf6f9fd3713b847886d07692fb85f09a423c74efeec7de6a7d38de8b3c436285a1a5df056dd46d1401990947a9ce418eb1c4b0ec7308a9534ff6a1be276a73f2e3e418fb06cdedc30cf87a56f45df79fb", "SS2": "12fb8de9e3dfc95f4eecd4833721539c82e11811578cc0b922b42626ff1c15d910c4ea43ed86acdc6da7c9cbda8ac04edc52a7dafc70de3753c00717d7413a300fb3a8a87a4ce3aac8a1e34dc6817438a34434bdc4e270062441ae9ef862018016a825ffdb7110263a33eb109a819904db8b4d29fb47dc8c8110d622130ba4f3", "DATE": 16632, "PIN2": 9644, "PIN1": 9645, "SERVER_SECRET": "19b031aab12aa8086c06dd0b71445ad1df0d362d339da9a570a26bb74da6f63d2394e82c9182bfb32fae1587bdcadde68b5b15c57e3d088ff64c9ca258b61ff7222cd61825e39233efda530beda295acc8301bb8440141638df54eb2eef5c0b71582fdd5da4cc0ba55b775ad640e52b2da059169ee25d98b0ba1c6a6d6a25f26", "SEC": "0406f1d83f15dc57cf3efebdc454216f351ea65a9a85b14f9eccc803f59237a6cc031f4b7fb186be3bc6964cea644ebe84299f61180672b7f03062d50a3dfa9094", "TP2": "041feb8a882740cba2f664781f919bf4e1ff713f0f81cc20154d1d89a7a0e7e2811812cdab5df4449a568bea37b0a8b4a8852edc42feee187b221657aed0fc945d", "TP1": "0410686faf1e88995ec1d5883601690c64bd7db49d5d16ad1adb620c294ca124a51298e11e394d1340f2f00b19dfdff7fd744870fe9200f512011d87a56f5bc1d6", "CS1": "0418e868f58b911d4243903ad52980e36d62ca432d4458a4e9da3c72260bedbb410287d4c35c448e633a87560b2f6cbdfed5eca7bd4ce95c9a090dba66cfb66613", "CS2": "04220be0e5b1ecb447e3832daea493f8366fd88062b6b66beba3aea9915a05f2b60be37933953648437ac2ccee9a1c00ce2b8c0bdbe702ba08063d94c9f29fc542", "HASH_MPIN_ID_HEX": "bc45e823db7c075ed1e68048eb970a01b40ed8ea3b0b495215212d4e4ea5fb89", "TIME_PERMIT": "04184336094a7b3858a06ad5fb51bd1414cbd191c0485504c31d72d2c75b31120c11d85c83075d6516633ff066ce80280ae9e1b8352bf6321844c4305c525b6135", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223539663432663032616139373965323335383133363536373230383637626263406365727469766f782e636f6d222c202273616c74223a202238393335646536393637336266616535227d", "TOKEN": "0400770633ec68ff1e4066cdb5baac9c82603911882ac5fd867afd09bb959ab565109db8eadcacbc80e684e0b01a806fe86f2692176ce33c12f1ae98fbe1c7e794", "U": "040b1f824166a16cc0b13ebd88fff42fabf93ba8ebb94d8dbcdce062bf0c15488422463564395d3bc4fe55a47fd888ae52a96b114c7b8aafe381e2f5ddbd6c7cbf", "SERVER_OUTPUT": -19, "Y": "11603f519d7eae765b449a92c4ffec0c9d01a790c4c58da437ccccd61e61a658", "X": "0cad07ea8b2a758890a4c7afeb8757b215e5d1ec4cfaf9067ccabb80b742348b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"59f42f02aa979e235813656720867bbc@certivox.com\", \"salt\": \"8935de69673bfae5\"}", "test_no": 148, "UT": "0421064645c5183b239ac243c88eceeea78cc6c3826747818cd822ce53f7aa154a10d6536faf56951b9eea39bd8f887725546487a6729625903c9119ee6f38921d", "MS2": "1c7ec1a00d40f5ca513843d681aedffd69da33f7f250d354cfd8f2c9cf81cceb", "MS1": "2022fe9d1daafb05d3e25e703f04c68700cae22c623a6077797c7967a3171ed9", "CLIENT_SECRET": "041ab4c598d46b4f51c5e0e27b69a7015520d324e1eabbaa840627357a8f6f3df41af72088e92879162c97649c48a562fdb49aa2fcf292ac20c0061da4b82b0b96"}, {"TimeValue": 1437055597, "SS1": "23dd9d4d940f2ab4b87e8d54f7a3dd462b01f48c008cb6f4d7f659417cee80511f678cd419e3e0a278f5e0d75caa1613ec1bb96648715b9c655af919234974d40bcf659d988051fe078b777a01dd0c0e4ada1c522a4528e8bdaa518d5311f9c502187ec663bf9e47ac24201a90440ff2c1239001bdbd66c40a47f9b344e64765", "SS2": "20ffc5dc4a4daca27bc2b63a3bc2822a7e71497cffb37ea2285aff57de9427971c0956aba610bb9df9dde4b0f03a6279bdad67abc60b5377182806a4911a9ba11ef6d0dd262659279389266f9fca199b4198b6a408be1678fbf168e2f9b058f7118d3da04eaa797fc5d7e7cefb206f8d3eaa5087c7b31cf183a731469e3662f0", "DATE": 16632, "PIN2": 3963, "PIN1": 3964, "SERVER_SECRET": "0d7a4224d0a2e11c140c131199e830be682853b5197ae0996ca01972eb26281d0bc36b44a3672069946a23bb2517fc0d2bd37db86878ea11b4945a118667a1ef0b5c55ef289787b5b4eb7598412391f81b611e73186b8a112221637ab988fb6405d6c03ab08605c4eb71c88c0af57c8706c500507091192e955388b89d719f5a", "SEC": "0403dc76185f31037bad84649e561019faf43a02425486719a2b811837e42b4a900a65cf7e40f9d7396b6388f90edfce0cb801654ed0e6703af7e3148cd45bf6fd", "TP2": "041c27be24cdc050264d37139faf663e117cd575feb14faaa18d9db4087fd4bf6b0710b87f83d41fe97a1c2da6dbf3582ee9dac29d46b70dc9b04dd9a4dfa62c05", "TP1": "04196670145e76839b7a5cfe460a8fe9b571c2fd1140d2e7f675ae808708a25026004afe8b48014f5cb4be2a5aa694a0d6de77060801e2c5809fae6cb85f3a63d4", "CS1": "041b3022c1125af049c57e9c61aadbb8f23bd2fbbc58caa7372410d8ba04dcf3cd0736d33bc0d3c2bd859f7e05bb4a1f7f6ae86147fd6b1a832fbd19f373488f8e", "CS2": "0414846837643c93c884dd5b95cf18537001260abb58da1eac82e1743e6e6f40d0046ad8f03cab4149edfe2f72af3a1410b1b3031d6c40ae299602dd314293a589", "HASH_MPIN_ID_HEX": "478ef8725dac8c8c3d8a4e0a31dbf48157388cd98f00da50a9eafa6b2a0dc306", "TIME_PERMIT": "041cceb39e3464308e2daedae54c9d5f6ac1f269739ac36083a65cc587e8322fc211077c9f7d56c2ba1e2a83c84adb0d6c47e13ec09a301f144c53285a3e19bdc9", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223130626661633336653437613232663833653432636639323865323962363433406365727469766f782e636f6d222c202273616c74223a202235626139383039313361323065626266227d", "TOKEN": "040bf87b03665a8d40d9c7cb886178cb180fa2bda3356deacf1697fcb5672d44f5112f696d3772925ecab59f6161dffc5c68c0f7cd68190170ed86aa65fbcb5448", "U": "0407b199ed39b126cb55b699ddc1c9134643420fb49b53247d0de11ee0459d133e1432276ebbdb0d731a342bab0c09d3d760ce10c00a30465a7207fd933e51fd6a", "SERVER_OUTPUT": -19, "Y": "1ebdd7c9820950e1ca1e0249d55c4e1dd85aa6b8a4350d49654f45d4625e5dc5", "X": "0859b59eecfdc366fcbaf8e67472750aaca89b6e4c3f05e8f815067ac74affb3", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"10bfac36e47a22f83e42cf928e29b643@certivox.com\", \"salt\": \"5ba980913a20ebbf\"}", "test_no": 149, "UT": "040a7b87eb193eb38b625166bacac615d180fcecb3d29b00a7640295f5443e122b0ce57cc5169a298411eef9ccdf224c889d8553cf5f1d29733c57b1e8560107a6", "MS2": "0b2e4bbc07f0f6aab93c5e1159ed97eb5633190afcb5922e7579d270f1ed352d", "MS1": "0c82c7a322000dc2e036ec98b392a708b865d874d0cb8108ca909d7f865827f9", "CLIENT_SECRET": "040a1199631863e336c1951eeeb9c5bd5ecf5515bef234da3ec3682a488ba7904a1ce17f1e32178cf557b76d3b66c17773f0cd404638dc6da06ef19f68ab29b13b"}, {"TimeValue": 1437055597, "SS1": "22556d17e5372285c894185ad14995c46bed17975829247a3efddf3dc67428850888f5dc5b7708bc4eeb57dd3ec08631fe1084242ee89afeb51567778a90976402ab7a3dfc9ad25c82ce9d73e33af5eb1a92d145c43a70037fbe55165a4ae1d61358cbcdb4627d1071477084419821c702810f4786749c43a91f774bcc66dbd9", "SS2": "0948b03ad2f1340c33e7dd3ee6ded8d1701dd44b905a02e4a3f4f501b64e57700e1ee63905a8afd571f0e1ee2c90639afbe894e5523c3a580be6e85eeda9009902b450df3846d034be3b34bf3237532ad4e4f01179c9c8efb44658be1a3b57d600691207eb991ba5e0b46852686bb36f6345484f5127a0e9652905e5a3a9d4d1", "DATE": 16632, "PIN2": 2467, "PIN1": 2468, "SERVER_SECRET": "211b03d65539d917b405318c7501097c553a3cec160b1e84ed64e6802e97ff58021b998a9b0879bf73223e9dc3005be0446635a195adf4535a17acb2d999f77a1fff21ff6ea53de9e295b95d049739c9086070f66713ba34477f0634ab1afb1e051bf4c0f0635f6514a35c4d5c8b89e35b3a97111f803071bee8b5426cb9897e", "SEC": "0415be516561b96c7e3d02ef1c519597add1f5a5e983a8c8c36e2b190a6974668b07d16896e4de0a2aa3dfd342081d9f5fb251ca29d2d0023b024830805b5d12a5", "TP2": "040ec8135fa4f62079140c2a6fb8e0a4e0f9742f1df8c75b387f430d861fe89e0004a3164052f81ec1336ce7769b9734c85f43c8cebf0a79b1e5a8a048ad3825b0", "TP1": "0415a23964bec98a80e420fc8db0786ab9fca04baf3189456cd78e57313d8c06341baa93de1ecaee0c57fb8177c14b2256bceb6b8458c6010bff3c861db59e6da1", "CS1": "041ca6b81003c0085dc2f1884d0d7913f5b7d5d82bc0c34c06fae1b9c60443ce73218650b59213f4ef7d215268f46e1dc3646ed721b291c286ef0ffbadff84c57b", "CS2": "041a73f63d89b3864c8f1397b4512b3ca0b6648f4c104ed86db3789eb3c8954ffc0525382c313d1ce61faacb20520b2894dbe8c288ac0b246f44474a7b578975a7", "HASH_MPIN_ID_HEX": "c45f8f8bba8af3346ce15fbb37c66886e36ab9bcc49999a0f704b609f75bfeb8", "TIME_PERMIT": "040efdaa97a1569a72485f5a85d6922fb20d7a9d8ebafa7896c2e53e5f891613961d987daaa3281490114bfa611314b6f61fe8e4ba233a003b69d7fa41bd6596c7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223935306465646435646136333166386634346530353437396232333039313734406365727469766f782e636f6d222c202273616c74223a202239653135633237383634323339373761227d", "TOKEN": "04175f0f88e9d6c12488ebb43ea1264d27c739207ffab1e0a2b1c09499891761db0f7e7e516f2e0ed2af8bae5ed202be68266e3e8572bf976ee74d3c70f14b683c", "U": "0415bbd819e0994fbb29067c948e4d1144af8626c549dfe14955c62a598fcfc78d1f5644180e7367221c057e909227340d930d550e7d88bd574e941b855663bc35", "SERVER_OUTPUT": -19, "Y": "1e64dd4ec922b6c5a0bc4cbdcbe51e642c4b8469c4e7cef1de6cd346bb818409", "X": "04e9065760e26e1575a5548055e16746cea0c829933cfcea4647946f1b4b20cb", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"950dedd5da631f8f44e05479b2309174@certivox.com\", \"salt\": \"9e15c2786423977a\"}", "test_no": 150, "UT": "0414874a52aa940848fda3f616e5e42cb8f3e1f5d67305cf9ec8f525f9d2bed44c01920560cbc94f80877f3a9fa3a09e743d0bb3d8eafc9bb40fc9cc41817f28f7", "MS2": "1ec2d6c0b7a7b394d724655183c8dd8eec9c6874f942ab059ff281842d9c1614", "MS1": "026599716b2461608634490bdf4d9489d6a868301e39e96203f4b191ac311183", "CLIENT_SECRET": "041cb27a434840cd0d1dc06c761bdf285ede522baf65446c2c67eec57b2529094518f48d724538981417445e2883aba474728e416a624eab2ea700435ef4c0efe3"}, {"TimeValue": 1437055597, "SS1": "029193671dd24f314d7d64ec3e858e3930a903369ff9e674c1a6250fcf4b51e41b6abc4eac11efe55b3f7980138b6614647751173129f80a61e7b51107f300cc02837e916bea61215379d25a76451d1e752c5d89e6ecc6255405985097b8ff75148b80aa7885dd114ca50814f8d6ea390c6c68ce8e8b04c02a820dcdc74e2e83", "SS2": "04e207e128f1bf5db63aa4bf67a8543008f1265213c4feed7fd2757d8dd14a1f02474d96ff027239b7c98a81722e806292e600c996d46e111320b05ed12806a01d9fd1b269bdd530e970b19fe038b7b2cb93142ac38f98e78900ed7587f3e2ed173d5027dab61fe0379fbe02a1ba3cb7ad3a8ac4ff52bd7f7abd558084354350", "DATE": 16632, "PIN2": 3953, "PIN1": 3954, "SERVER_SECRET": "02421470569df47fd453ded3f368902047ccf1c59ac81919fc626c8fdaeb3459121b3f1481de65fb58a027582f2d97bd456619a7ab47f6a7e9efd77238ceb22015a19ed0e1e0f7205fd08608c527b7969ae3ebac44da33b6e5a40fb9473a12ab14926cde87730930ecfa94a9e054dd0b2b2bcbc43fd3569ddaed17ee27adcd22", "SEC": "041eba98774b435ee77f36953bdc3acbee57135e6e67e4a4911276056a7d66ab54224f2c202b5c034f2a8edc0c29a0e84ca868cd21560919b87a61fc78dd935de2", "TP2": "04209f86d4c32dd44d2cfe51905aef614e22e097a137cbfec2767826a456347df91c29e2b4e40be428393e721aeff1b5938a1b36f6bd10508b676c41206a03ae03", "TP1": "0410048632348ecdecdc4a1b2f5e9072671dabe499cc0aba2671602edac1d40ba0119c1d1adeaa878ff7441b5c30f53f0f26f73a6c740fcf54a1abcbd311ce4da9", "CS1": "041ff4180935f66f3f5404c6e156b101d659c6a5363b6cc90546f77ecac8d2c1080727e25dcb5cdfe4ba0a090f4aa0d93fe4954b92c1d7acf7ecd457afffabb5d4", "CS2": "040b3c8f549f233141e8797dd970498b3d1bdb3813acc81589d8beceba0921874e2102c1378274559e1ff2ba8dec18e97cd4f3a56e7a04bde24535448dae52caf8", "HASH_MPIN_ID_HEX": "51c579c6539b204325eb23805912a1b1c5c42452548b92e38bccce5865d656ac", "TIME_PERMIT": "0411d024ac5beaf7f3952f0aa6c1003cc1e0664b0e4a0a574f14b2f1a6b38f244c0716014f3dd4a15ba377da4ef3531c0461e469189b248b87a863d4331ace55e7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223062396238363032343866386162626164363964333836323636303366623466406365727469766f782e636f6d222c202273616c74223a202239386436323962643465656131386664227d", "TOKEN": "040c9f456164d9740a3b7857e11eff813b27d3a81cd4d05f073e781fa5ba018fd41db0779dc7ead3adac87821ff4d0c377c239e883676b4896ab21fb3a9b36cf80", "U": "040d39012e770ac15f13b7c0adc0def57b81a4d75120c75c12d1396722a794b1fb1f1743ae7600b25d2b2d61c790b07ff1949b79e45fe321ec5ac816c266b2a31c", "SERVER_OUTPUT": -19, "Y": "1387dec4e0a1eca784bc0d66131aa7abd8a812bcd4bcb65ba0feb1562aded855", "X": "11b80444130c4534b108021ab70d6e8bbdb86a7346433c2003327d8daa38f0a4", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"0b9b860248f8abbad69d38626603fb4f@certivox.com\", \"salt\": \"98d629bd4eea18fd\"}", "test_no": 151, "UT": "0420a42e7a312d83bc6f2b9754b48f7e4e5b7235ec553a8637cce92be8b5766e0c084851abd6d0ec063dcb90c6b42ba3235db5fd3c55e9b7f1a51a03ed343d5bf1", "MS2": "1e63e643d1fb0d9247843c238dbdc4be2151b162c84a616eea962d1fa2172d62", "MS1": "0aca2b6e01a0be13891d9fda4c17b4c191d5688307ff1600ffaf42dafef4f19b", "CLIENT_SECRET": "04173f3d4590491f0585fe2e34ae8199e72b89b0426a89ba644df0874e856a2c9e08a4b605d213d12ecfde4851bf8ec6ca246ad4b7232fd549640109c8a745d970"}, {"TimeValue": 1437055597, "SS1": "10c3d21cb925a219fc239ec6b73ea9c21ec2315d60a200912d279d435dbf94e61e9e51ec7834f237de1b37cf0cfe14dc3f256e144e63b0ebaba79b97f0eaf377154dbdf7ef38587cdc257464b34bf0a0989c15aa5cbe871a860a064cfbf20aae0bf90dbaaf39ea46aa8537301d327ffb25cadd6993ba0d1595a0edfa630b3d3e", "SS2": "039ee70efa588e10d985b5783e5767737a8264431ef7d1afb5a0a8634c60d19a17d95274af40d53f76d2d03264f11984f9501da3300de7461098ef6df056e3d00e8982f61eaabef6f7066ddc79c7fbad5355081ffbf9b8fcaa17074fc852394f0cd4ee4782dd5e5fc49fb945a71d81133a4e9bdf63259ba9db57b36600d6cefa", "DATE": 16632, "PIN2": 2768, "PIN1": 2769, "SERVER_SECRET": "1b096c1af817d930dc5bff116e77643e84008a2bf148a6698135621593d58b811c1a73abd478606e3affce3206317dfbfe63665f42090310b77db921321bb5ba08b0dc101598eb9db7aee1f7cf0ef157e881ee8c6f57441cf82ff2120f96bc7d1796d172f4c82f8d144fcca7df7f039a28fa5f4087fedff47553b3502b2edb0a", "SEC": "040088ac868785b6340b6866867f3240b15e75039067437befbc5b784131c54a171bdac25fbdb9719aad1c45f6c83ae19f040365c52870bdf1ec5a9fca29fa4990", "TP2": "040bb1afc7952d6e3c3efa4db5e5c19d08d5e6fbdd7f428612b62bce990dadde4f203ebe00d3c707b7fdf5ff62263c26b352b43f9eb7184ae4fef78a42712b06e7", "TP1": "040511e3d56fa06608f4f5eccee37affe87d3e2c6ee95035c10e7e65dd12243fbb1e58248b4ecaabe1b01e157c227fe92e940152778eceb97d282962ff8aaf98ff", "CS1": "0423034827d315f9d97b34bed4b0ff695a18b26dd0d5129e4df872d0427f9a9e980523a8e35d4c837ce56760e169c20b96a1997bf355748d4904f8a79132e9bc0d", "CS2": "042114d29b1441a6f8eba14384925cc56b1d23a49f0f43f83bad5aca05973e78b20e6e268777c1eba98802ca76978a560dd9b777935fdad5d75f0e9cad8f7663e1", "HASH_MPIN_ID_HEX": "f567f344ad6b19506acc411ecd6d1b3bf5985bab6ac3bc268a2be3bc995972d9", "TIME_PERMIT": "040cd4edad2f955ff9b0535796c09a8f9d526cf5984901633fce1860e17cdf6a291e3a7d61d644155fc283c255bd7702d625c743ecb31c332639b9bb6b18aa2b63", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20226639393838316436386636633761363639306661633938653434343064323664406365727469766f782e636f6d222c202273616c74223a202265343339333738636163316330633734227d", "TOKEN": "0407b1dea7e0d0f1664e0ab60124869645cd298c3b6217122495d07fefa538cfc11c2a74283f1f9f47295a0c66f81b4a7a1883a7d623c2c8be25df99f15478266b", "U": "040d99fa074106815664ecd0058cde78f1ab94b3ab0232db434f7f4dd25f271e270eabd422380e1fdc3a78199753c81476b9ec15531d4e39901b2c0afba4f7da84", "SERVER_OUTPUT": -19, "Y": "0f6e980890e172ebddb704453f5db2b53e98c6c6b62098a40805ddda99c8c997", "X": "1221fedb9668714da937e0a17b10d6ece39e6e3b5fa21dd071a5b9666589d84b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"f99881d68f6c7a6690fac98e4440d26d@certivox.com\", \"salt\": \"e439378cac1c0c74\"}", "test_no": 152, "UT": "0419a6e5f738a6fcc301ddca180c3445f8cd288f217c2bb7f170246b3960fea878040da6f016520043b62d6e386ba7b0fa1b2c99145caae481b0c1d214797bee79", "MS2": "0ee2676f73f9a693dde6cee22274292d82fa95b16f0f447fbf898e19d488a2a1", "MS1": "099c330d23246f74b2955f630a5f6280b1b8b5ca37e5ed1459e7932978913de5", "CLIENT_SECRET": "04153e5ca7000672e30590f66471327acea351d249bdc0ecb7941ce3c4d2c70f85207ba6dc80b06426da404a9d19fcc3648e9191e3cf993ef774861d087e0646c8"}, {"TimeValue": 1437055597, "SS1": "064f564c2479234ca45b1b59ff589a7849b69ffd08357553cf2879a7802f923e16f862813a7e57c1a4159595f159d5d4b73a8f372ab1a48943173beda0605b441129a2498d634e4da99072facdd46245c3a4d87f93dabcc6d04e1b96edbe6e6519c74aff0f3cdcc9c357b4aaef155e7376a8aa0fa27255e63cc3accc2d7f57d0", "SS2": "0ed890524547849119fad27f1d86ab68ecd96136a556cb1a29fc3150d8aa6e321f92f9bfb731008e99cec35b4346233e61db03c1864371040d06bd8fefd24a3f0c8f2185ee019cf280fa1558d978db5e863a296e084f787930c721ce988aa126108278f71795cb965c264f2c3bc1a404e1ccda424e2e0a14a8e824dd0530d481", "DATE": 16632, "PIN2": 8693, "PIN1": 8694, "SERVER_SECRET": "18bee110f3d6cfaaf161b981cd7ad7f50564290efebd2aead22bb8d661bc11c521fc990efd95dea1290eb6c5ebbcf7431444fbba97c7ace6cde27e3e643cf9240aa9c6550e8917b6f5ee675246145656510b0b2046910c8d923cbc0d5c3590e90c63aff61ee9e2792fd10d0bdedfd6985839a02b9e9f02380fabb15d7a676a78", "SEC": "0405f54e5da022ac1a535b86620ae0bc3f49b007947d8d1a25943e0baf7fe207b811d450418792e560ee8b6bb336661bdd67b66d783c12fab9f8fa37533d9a13b8", "TP2": "04132b6e411b447bf023081829485d064f0fb1afc12568af121f45222fda7aec0101f5e0c05ef4c0801a87606ec40fd8214f7bd0f40fdc889f5eb39552d1bd7476", "TP1": "04237856abfa82a5f584106ced01ca00eaf8cdc4c3e98d1fb34f6d030b95e56772187011d027b444d79b786e1b131d19cef3ddb0018c2778e7d0c526d3e009b508", "CS1": "0419d0f404fcf24c6c4d18f7fa4a9f7f3ebe0b29107e5af5a89e2add58ff35a47e0f06db285f1aafae1a7f1f5872a385d90bd8faf23f53d8bd93ba2ef863bf31b7", "CS2": "041470e2a01dc5c0e4ac22de6bdee6864885592a44d86c373209ef61122185b5ca1e47497b8c1519f69764b9feaacd9493b84f9965706dafe57d97852284ed0749", "HASH_MPIN_ID_HEX": "121d216b59de7b8ee85b826ab68d3c2077841498e97f9bdd9cd85cbec9bb5eac", "TIME_PERMIT": "040294b6e3a76ca0202573263291481b0de41fb324e45070a23820cc03d918c97009480edceb9374ccc59a97f98262e8b90a24be458a2c43f069da86889da31c6b", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223034373833303536333762346463313066333531326436643833656237376238406365727469766f782e636f6d222c202273616c74223a202230383261396330383633613736633266227d", "TOKEN": "040c0984a006182d23e941f57751feb196c94927de5621ebcd3d0e88e9db8a1f9e11e7f98467e702e1b34f262ad8ce306724cf8f98d790be6cb5b0fa6a2334ffee", "U": "0403bc19d7ceaa8bbb11f89cb7e4217100994f31a1133708786b50c3bac40d2c62126f7098ef04a28fc8d10d3db7123208465b047ae8ef1529104658d47f55b1f0", "SERVER_OUTPUT": -19, "Y": "07eb7a8eb187cc756f9e0bd9711a63d2f75b1a93c24fa4a82a1b435c1add3e7a", "X": "190ac894c24037221774b2ae1d7186f7abd38147818cd36c81926b84fa917e62", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"0478305637b4dc10f3512d6d83eb77b8@certivox.com\", \"salt\": \"082a9c0863a76c2f\"}", "test_no": 153, "UT": "040045bdbd44c1e6ed4e89ebbf10dc5c9677ce017a82538924e59a2c9aa7f291830ee1b2cbd7f16abf30c8d081524d1ef035e6461f5c6d4ca2bf66348fb4df466a", "MS2": "107b165b9dba2b718f0d258f64fd09b6ab515a478f5802bc1e7df22b69ed8d1c", "MS1": "0fd9bbba6f669f94e37a56e4871fbdb5b05e40af8564a7957492a1d454cd50bb", "CLIENT_SECRET": "0413d9e039cbd29e2fc22d61965e17283d9802912dc28308a1044095a40647aa671f1935a2a7aff0e6468cd8534544c262adbe648becde13fa86d5b7f9e420c994"}, {"TimeValue": 1437055597, "SS1": "1fd68bfcca6a9894daf329727369a8037ffea968d1fb53f5e71569f2abc7e91d1db282fa71c040422176ddf2e92e89ee8823f3f653d8d86b207407583514463303e81f2f8764ef2d0816e37d4bdd4970fe2cc5770a9a56359668e6de098240f3057191099655a1147b641ce39e47b87fe6127d54d4fd68bdcc09883e69cdcd0d", "SS2": "13d6136dd6bb50358150f7073cbe39345e455a12b0108bbf052a2ca9673661ef20a53fbc0ba0eaa865c61bd78d8ecad13b0d4b01559dcf3cbcdf9cf920c7a50604a417518e6a3741ccd88eea73922303f100769f656ce165c58484c84818c8671a1a669438c5958982fba0b70b61386f6ad0de0c976ea13c48db9573b04a9723", "DATE": 16632, "PIN2": 3947, "PIN1": 3948, "SERVER_SECRET": "1453f086fc685a44bb5e1d7cda422bf9a39e4ef7ddf0f6362e48132b3c0f82c80314e0493be4e4026ce3b2a4110b6c423924a77189283b5e26353cc23a7869de160dead8cca33ac7c817f5fe7213056dc624fcf3ad602e076629254ba1f27ad617f678df8a7f72b31e297d2185df5cc7b1c5c3df47b16c02adec788b63331f55", "SEC": "041b93dfbc73a41573df27eb6e50cf84b3ace6bffdddf7bdf9703d78e899b3734c1ff08d26bdfd3fd6a6187dfe56d3f75142244547b69c74044117d0c26e030347", "TP2": "0400e7d82dfa6299bb2b21708ebcb2f0e102a25eb7bf0d276f1bc7a793f8e284b810d878415c5641fae3d8969a7812035455c13563b0feff071d45476f619bb328", "TP1": "040d383072f3a9817226ddfe80910d8bf9ab1c02c2daf3d2bf6800735ee48d44131bbba41812d952eb4370b1a6a432ac76488b97d03219c6659b9ce4cca5610680", "CS1": "04036a769cbc4b233d86b38491eac273501253a514f2f58a1503078fc32f81e06322d0589af72be19075ab9f35f92ab724534978626270397dced0557957a1aad5", "CS2": "0420cf7f12cf769b5d50612258e0e184011e05d0683b4666e502822b57148538560d7cd3a0322000341af095f4c50146c518ab939d7df8e62913c884851863bd35", "HASH_MPIN_ID_HEX": "4329d9dcce1415f393907c0a1bf41be82f81a635d81ecea4c97e134a43810de7", "TIME_PERMIT": "041d5b6d57ce992b6d56a4bda118c526e199ed36a3753220f1f502923a5a3715c6062db63a9d37e1cd9d26ad074ca7698eef01d2b6f22f5ac45db4bb5d0b4f2cbe", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223938343732343563323361333239366465323138343739616366333933333365406365727469766f782e636f6d222c202273616c74223a202232333234316435343563323338303664227d", "TOKEN": "041f953de855c3b8511bff288f440eb2f38525e9a7eb7de84b07ffd8c7171eb29e08f2b93cf95d1927ff85a3bf95e61d2be42c51c3f5f303660ea3bf33f705d19d", "U": "0405833e8a379fb4b7cc09ac6abdefdb6edfb621dd853ca331d13e8fc2551fa27b05540e907d28d93b2042e5f5e25fa0018baeadaa14cb1c0f0ca68aa162308e82", "SERVER_OUTPUT": -19, "Y": "19986189a6a830855e86658628748c9a84a6b8953c1c380ac31430aa8ab0b8e5", "X": "09033225472be74848d82a39eeb70c5407adb0c2cf260c826ef37859b945a96e", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"9847245c23a3296de218479acf39333e@certivox.com\", \"salt\": \"23241d545c23806d\"}", "test_no": 154, "UT": "041530e55043734fe0c91d376320925045b0db6031fd5d80def103b647c2f86fbf11b74781ec1809630737d5218dbb5f2230bc943dc0cfc9df2d271f6490f1f70a", "MS2": "045b2cc795e306232b84eff0f4f4e6df52a5e699d002267719b416c8e8c08489", "MS1": "0012f8d7b65a85db24163e75bc49198f7ed16a9e603eef2b29c38d9a8061c84a", "CLIENT_SECRET": "0401686c6a81fa13b056af37cc82f8f7cf430de7906b761353667706bab9a2987715e2c34ffb248b8946cccc7d7a96542d29aa4dac2b06aadd38fcbc8ebfe10e26"}, {"TimeValue": 1437055597, "SS1": "1bce70c94af28bc71eeea5bc753a3d2b7986bf84b226cc024e0235b0e09deff41759871e54df63e9de8f99415844c78922921ef1d9fd054469b32e51510840b919637af776fbfc7d03472a289cfe0d5e264d22dff7a7159b3c4662e9380e25d911c2f9b2af0752ef7022f5ff50fb18f525ab944803b4403b632eb38288b0dc26", "SS2": "08aaaa97ada53809f0ca76dbba9e1b0c479a5b4bbadf773be846e50dc8c00f0a10007aeb67cedca06d3e12a2706656a88f061b9e41c1ce778f4f9c94f93765e619ec71197fe79700477831cd35d0f22d87cc033a6de193e957861003e46c8e0d0077086aa7cb9aa2d1a62d540ce835adcb0e247ac5383bfc55eac92f6a4b3aec", "DATE": 16632, "PIN2": 8521, "PIN1": 8522, "SERVER_SECRET": "01a554db1a8bbc15c8d60dd9f791e78fc4da429a0bbe4fd55641ae19d56b8757088596558ea508825528a43053d637d70dcdffcf6ff8d12d800fd27226eed2c31b8f7a853eb08dc4941bb2d91a2b75b9c134bb6ebd6d7c6d7b8e7fd4050c21c61367a33d799bb74853bc17e31f84e3f7a07d5244960df10533862f0a02e93f74", "SEC": "0407412746d1685eef41253b8d9d32387321519d2931c4f0e55370597297b7c5380d00b4e2d21777e68bc52cceffc169c2e21606aa7c37d112b61a8a5d66152e2c", "TP2": "040e2c08fdd26a248100dc8518cfd47867fce5397f7cf53262cb17a47ddaed4c5e1b2c2b2a5bf9a0b65776173b2dd7efac02ff15aec0495adc8df004360daa1bd0", "TP1": "04028e2c48855f5d81bdee85afb60523aa6e842def6d1a7fae34676c0144b4f6f52180b6b3e603620b2300769677a24d65a15020acd4fc8d0d93f9b587b95f90f8", "CS1": "041c453433bdf297bc82cd6b74d5d5e0e9c1f49501594b032ed71768e266eaaa7b02322322471c640cd461896f6d2108e057b2fe8f5a379d3036d0b519f9a59ef4", "CS2": "04029ee3456385afe505cdd2934166ce5c546d5656447c67650f0f80f26e973e1208ebde83cb76325c3c1840542c717344bd71014e2a23214fab7c08ba3d3d514f", "HASH_MPIN_ID_HEX": "b3fc4918434fb851107f58cbc06399ca300de1999e5a93fa2c6baeb37eaa87ff", "TIME_PERMIT": "0419361f9302dd62e76779134a71c23cc8fc6368c8e1dc6434ae6eb89393c014b51cafc6e3fc02c0682a4a27c17c42c4272cc3c4cc3bcb8e2df06941099aa3e399", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20226630356263393337643938356430363862393938366166373765323431363232406365727469766f782e636f6d222c202273616c74223a202265633638323338643833333165663065227d", "TOKEN": "0416cc60925b5a06cd6b29013ffa138307f95346c494cbd72bdf268eb7a42ee587153e36333c98b1598203afae53bd3b96d5a4a6de49cc6f6724a5f26f721c97f2", "U": "0404a7f36d6a7b8fb35b5672b8f2c924d0ff4ecb55d670ead9473a4867c0b8968d2103363f4239e4bf5edb80146ca2127741888094b93594a929a2f795047a899d", "SERVER_OUTPUT": -19, "Y": "230306216cfd0a1587943a758a9d5ed25dfc6221f4ef8e81f96fd6b95dd53015", "X": "1ef2c28732ecad8e32e3043a937e06e43422a2dcb1020767413cbbcce5a858aa", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"f05bc937d985d068b9986af77e241622@certivox.com\", \"salt\": \"ec68238d8331ef0e\"}", "test_no": 155, "UT": "041f9d73a8208923c2c15b4fb1b49d4cfd820749414ea27dea7d3e9c36a160ed20162e6113ec70c1c9ec9ba871d68ac800c529083f5045ed4b6b0dd98422e418a4", "MS2": "0347da7892f18d9d94a339c3ae6e81e2ed5e1c080fad249fac132ec08dbc704c", "MS1": "031bb2295dd4080d07aea89c71129d7d9f7b93ecfc5f2b40204d4fd7041320c2", "CLIENT_SECRET": "041ac9cb69696c4a18541475aee613ec6e81dd40b66d802da6361b3e7835481bb113a4071e3fe175e63ab0056ef7910dc41fc857f4685cc999c396d37bc9dacc03"}, {"TimeValue": 1437055597, "SS1": "21bc4292e0baf9500c4257605552a67459898d4f8ba3f3e115821c9a2f23f9d318028c45a6babdcf91f4b077b278f94a9d3d60f3afe664e68eda75a78822caee1505d8c8bdfabc41d3a286449cfe69d9b9e5d0a34ca06357ff57f4e27d1de27b1476b68560ec0e3b89e6c1a9ad04eb520560fb2e4fc41c5a393399409351a70b", "SS2": "0c0c7fea2b0e755f0002e4e28b54388899ee4829b325d61ac1b162b87e70d95610651c30a51447d4a8d1b1290ed7f34bf898fd911eb84e68f34fce149ea202ec0dd1acdb2cdb00f90475eda6e771fb0c1946fbf40d513d434fab58c7d3fffef70ec7ef891af498c0fb4c7eeb90bb05a7c6ffc9e16a56af881459b5f3ef2e78ad", "DATE": 16632, "PIN2": 2072, "PIN1": 2073, "SERVER_SECRET": "014571a8337862d72ad139723c83f56524e504cfc6445a7c09d0303d31973457034dfd2e8cf4736034617f160cf0914e1b5b7b2948fe422a25505a8ab872bc9e1896309d49772598dd527d9c8babfb2adb3f1ea1330b015bbba2e9206b81bc0a112bb95409afb05d981ccd4112da2b8dd3f9d6e06030b1a97885ff439db7d378", "SEC": "041d873fb866db88f6bc759349f147d90e79cd01aa0b742d299b3a65c51313a15b0a4c31ddaee324271c12affc88da99b49ef19cef1dbea6266fc2e6cbfc2fa778", "TP2": "041b42715a9798c229d4f037cdfac1696230711446706a842f8e6a6efd3651f8cf1eb8d870925383f333ea7689493c00b97a1f80bc843bea639e03f40975fcec4b", "TP1": "0408214fc2f3e194cb1fb4f99bc527b163c3afd951f019038ee7e3ea1e070ea47f02c335cd8601f77c85d53fc73af7f6ce5fd999f73aa2957501a501689cfb1e30", "CS1": "040fea54d5c6777a872e64085ec62f0eac59994aa0e68642b49b1ba27377118dfb042772a22f6468712b4541d914b067bf8422e5286b94d32acbf20036d9b3b7d2", "CS2": "04089ac75c662cddc8625ce9d6626847d25a0a26e86989d2f4081c7cb76f4254930123241dc421980c6a7ecf803456bde7c7a8b542dbc7a6c040ed196474c5da92", "HASH_MPIN_ID_HEX": "2455e617a67088153730baacd2cac683a9cdf44c7dce224cad3713f74ec46fa0", "TIME_PERMIT": "0412c8eb8a78d4dbbfa7f3b831eae5c7cccd19bc590fe319015d8ec06db4e9e65f024d6bec9d0cc3eda91faa4d9c82b6498af710dc90f9c7acc94e99230b053a21", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20226432343439633439313130366234366231326632383561346264643237303164406365727469766f782e636f6d222c202273616c74223a202239343936326634346663366133656637227d", "TOKEN": "04021a27bafc43234917bffce0ee2816ede64f180bd7b1f84833f5139b0978d3d916c45f341520c90cd7a6c1b812ded6655796894ce81e3a492d86697927b22e81", "U": "040ead1d23b70325feb5ba89d3998f05e2c0300004ff895dcb20d0f406cf5bc36604fd71b56263ee7b67039e4b3e67c75fe39dafde7e042081291e665a226023c4", "SERVER_OUTPUT": -19, "Y": "16dfca521b09b26b02867455f179d54c49869314fff6645d1ecfcc342d1a4da7", "X": "0130351cedb53a20efea5c6f90a179cea9fd6f605ea64cfa2132fc279f6d7da6", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"d2449c491106b46b12f285a4bdd2701d@certivox.com\", \"salt\": \"94962f44fc6a3ef7\"}", "test_no": 156, "UT": "04219c3d602623c0b3db9abebb2bf5a02cce901e1ca211f4c09b2cabb24593f8962003de81a05d283a24f5dc2f8cd72d78e82a436850c476ba5b9a1464cc65d9b4", "MS2": "192dfe2a9a145663d1dbec247f946ea185b2efc6cc5c9b235aa5388218461069", "MS1": "18356983440f8ecd85b9a62bab90d0e7a1560d98a9041d9e97b4abd42b854479", "CLIENT_SECRET": "0421b235829daab7afeac167dd92498a9fca627ec65ee0ec8ec6c14d750a831a3012906eb13c3840e63780bb73b5a709cfdf6afb48872f6994fc0aa5e4fea7d957"}, {"TimeValue": 1437055597, "SS1": "01d8a82071434ef470c7d4030c9cb80cca50ed5479bc812cc1b5993aa98a299d23e52b70ed14a3423a40a15d1e84158e87d3929cc61d94391746725b988b6e2f0b96d54b2dee0aff8beca663d5c26616910d186a0e5bc0bb4f08dea5fe328fed0a3f85c13a9512674225f1a99cd1fb58ccb91d9378f44c3961e116c31e068eee", "SS2": "0946d409ea78b8e11ddeff2227155dab6c69b05fe6476a05a51140d86627971d10a40158df0da03cbc730f9baf005a6f1698012e3906bd91339cbc63e6a192101e9637d5ad5e892c6b9d687d83cce54510d744fa643673fb5d39db2e466fcc71227e6931cee267e74a9495b50a6b1d9d09fa6f98547ad6ec0f18977c50341b61", "DATE": 16632, "PIN2": 8722, "PIN1": 8723, "SERVER_SECRET": "09ff570922ab01c330aaeacea626fd07ed909118eb76ad4f5b1e764f0e040a881769aa4c5fff37178deace03cbd1e19f52d10770abff8305e0b6d69fd5cc18c316d30ea79e726fcda5ca5457e37ee409934832e3660794a09d9fa54093ab93db0fa3eb0cf057ec0101efb827ec8e25bb83592163607c11289cff6a0239ec0c87", "SEC": "0402751d221c8988cc403b97684eb0c51082d6c63b313d56194f5928738325407f0e6fe95865d02fbc39703e747d19cc9f8892122f4a8b0e6871deb378a9187588", "TP2": "040b7d4f0e73d30bfe08e6a42b4d2dc1e8c1cf28478d9bcdb8e84f15eb025b35cf134ef7959b70844b9a571f21a140eb415254326d1c0718153c912b6efa89419d", "TP1": "0416758deed85c4fb143f65c4f3912458e5f336dc724f892701792f33f64eca8d00e577f6a5627c45f9b0755a6a238e8ccb8d61f433d83c60d39865a6c484ccf25", "CS1": "04166ed2a64c5f83a8f313354a0346379807baa713ced1b67b88eb810983cf7e8f215c77acae85892ceaadbaf1e791945bd79585f5d82963b88ee54d9b3135ffb3", "CS2": "041da0036407d6416ab9a26539b6bdf3d64e5a183cf468e7eab552d3c53593cf7e0559e8b4dc17de8119d5dfdd293b742c5696545b7fdf037c5d7915d29f3f2609", "HASH_MPIN_ID_HEX": "152e263bb831b7c2412f669accf07ecfe86d3776eda40095993bccea813a28c9", "TIME_PERMIT": "040a43877bee96e3e7ee3c9ebbcf29691bdb9f7b4241df2bcc92ef2f37c14df86b0c24ef67017915ff34f34714e52705d1140e7ead571189a0a0c53fbe52554233", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223764333930653734343263373936313539616139613133616438373963646265406365727469766f782e636f6d222c202273616c74223a202232633936653435643966383131643337227d", "TOKEN": "041b1e2bbcbacadd5d61dfc6bef804008d037121b43a5204ff63e6dd37eceeaf830627ce3349e414261aa7218b433b0ad3ed8b69e70d407b96ec1f213645a05141", "U": "041982403ac1bacb83e25fbba6e267a33a0ab66ca7c4f3f9a9fff8ddec2de947aa1cc68dfd6864a692c1b8b9eef68f97075b3b7f8579d094a2cdfdeb37a711905c", "SERVER_OUTPUT": -19, "Y": "08225e8f30f629159be3cb280a0c8eb4140c506f2132332d6a41194815e34f7c", "X": "1bd6e0a127258dcf43bbf7db324b1fd0e281992b916d6f5aa4ebbfc724cc0024", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"7d390e7442c796159aa9a13ad879cdbe@certivox.com\", \"salt\": \"2c96e45d9f811d37\"}", "test_no": 157, "UT": "0401e4ab61df267a1f2caa414fa97b3d248d00e942ee4f0ba0a01d3f2b1f494c8418c57b3eba6117454167f1fd790d9cb3d01d99dc1cb88011e4be62570b00f475", "MS2": "19a4e1a8929f750e95b04f771f4d1c7e7a596d4be9616e31218590d40599e898", "MS1": "19e6d48af1e73fba880caa4ed8286673768fa83abdf91a62f35dba10343619cb", "CLIENT_SECRET": "0407f78326e32506db05aac7777bfb3fd2877ba37ab39ec8b30039080fd1d8ae1f20266bf3c9d3055aa6b31827b26af0c47ddc2e1fcfc94bb30044b8bbbf00de99"}, {"TimeValue": 1437055597, "SS1": "0927cb2c772937b8b37d3fa7ab5cc54864ce770844ab5275d9fde09953abee3509fd773d5c408c21499bebdd5b039d71e3d3144b96b21fe5c2155af1edbbfde70e7a74341d161be34303dcb591ab1b3dab549426696115381af4c8c104213ffe13073aaef0873d65544ec071d44c5b95f59aa2be332fe25edc20d87364cc03d9", "SS2": "1349304d9d2c8322255903814c70c3d395d7edd3f932e061c423073a2ff06e9300a61cd46dca582424d2f44d6566abc57bfe038650813c72aaf0c69cd8747d1e1e22c6f1576d6a3168402ad70674b66d44d0a6be1e36b014c7991ec218fb12f7183bd25633e3e24082b8e422b8138a2abfcacf7b4d48aa1c69861295c4e7b833", "DATE": 16632, "PIN2": 4894, "PIN1": 4895, "SERVER_SECRET": "0a124046aa8a727891ab6a9f7e7f174ee6e553ebf4fe7003b7bedf1a0eeea9ca0bcf2ae577d08c227abe678ce7851d9a62abb6ec8de97197beffe9091b3b5e5f00105677ce6d0690fc2637810b21f4c36db5b3585bd51f9bc2943383a2d64e8516475ce60ee264025c210c7142a6e60f539afd1bc1e62e7e08b9f66c791d8e91", "SEC": "04034033108945cbfd0a4f828484a2b12e25900d46e85bf99757131e56964e568300532b4dbef2bc774e102f0c5c9204521b6bcb03b0203692380d7cf8e4d237d7", "TP2": "04066d669229468351df19b56500796119c972d6a491ac619c7e5c57b0e707f38d04811ecab4f3fbc73bad882488613f4019328493ccc1974cbd01454cd9e6b028", "TP1": "0400854a22c8cc0496dba13e7656e9e3354beb0259bb86cc5bd91e64b1f2e0dd47027dd1650d8c2478acc08285f7b0c9f651ccd448f546478f542c34bf9d08aa38", "CS1": "0409733063af1481af8384f6f9f9a5c4fdaa34595151d1e444b26c88d5f01d191c1a31475fc1646338e3d9ebecc3dfdbe6059c855cae3e5cacd1bac2cbb191c830", "CS2": "0408806ff6abdf12cec3097fcba8d058b2daae566493d186dc23e3d856edb9b67919a3f834b2936756250fa0940a2b119496b35823c1dc08ab473645bf3418c089", "HASH_MPIN_ID_HEX": "76e228da1b96dba4458858562405319ca7704012e0485bc651641556407cd0cb", "TIME_PERMIT": "041929c1639d8713f1eacaaa4e81b44f356b7164fc2a2e0f180f8bbe2ec8b679af07cb8e42d75f50acf456a6d6bcb169fed4d1a87ff3052091f82cd93fd71188aa", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223061343930663866316231633161353639333031653961366232363932353365406365727469766f782e636f6d222c202273616c74223a202265366366623337363636343061623837227d", "TOKEN": "04158cafd1a8fa6c820f61410e3cc6126bef48e49be3e0b6e6963fdc9c02569c5e22fa7dacf9ce204fa40b95bc1c7932027520680280f00a97e48b0f77110bff81", "U": "04195fe9e8f71f0ce5b4d8ba74a4316e1ba6f8642ceb93c1860f8c76b8268bb7ba07ce76862666031178f02cf07dce914222d247b3dd7618114fe4985fdbdf9068", "SERVER_OUTPUT": -19, "Y": "1e76fa4c5d11e1ecda56fd8c978214d5f72e85c1669e501861be966c8b0c4b96", "X": "0883b17cd3acd57c174ba8a71051aaf6d5c2642f6cf1fe6a2c8888c9c028c720", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"0a490f8f1b1c1a569301e9a6b269253e@certivox.com\", \"salt\": \"e6cfb3766640ab87\"}", "test_no": 158, "UT": "0423635d41fe0fb862c7e19c831a3609529c6077ef491292c07c6351557c1e62e50be874aa3eb2fe1bc15320ed4eab18e9ab9586bf768aa7f2c8d124164d745d18", "MS2": "20629696309bae7b167b9eb74c8a19aa13c8eaa3e8fc282aa050b2c04b6bbc5b", "MS1": "2113d1171248d821ee846e32b5ceb636e6bd7f94a7b4c3ff2f988f247a94363a", "CLIENT_SECRET": "040d254390ef862d5a59a3371bfbb27ae795130114c77b42a3bfb58209312c44780a4bd17f1296175d76d7e423f0a3264b986d36adf03165ab46df23a5f328e2c7"}, {"TimeValue": 1437055597, "SS1": "0e2d09df4daa3e5fd57a983d04291f1cc813a1496500e263a06012569ac28031106a80320aeeeab42ed1805f2247960b501e47fae7d26f4ee664c4a75a4dbdc71d4679cdfa20327d0d6ded7b1a62c05b16ee09a98d3910a7a50e032b479e4c43123300919ba4d4e0352f5c577862270277c208fb1d6d92cf790ab04d740427b9", "SS2": "191c001ac8ea9892b39e97d5b5beceb5ee86a5295588f7041f3a08dfd9082736189df929bd4221e84887cbece9673896952c2f6b0a1b42331a220ce323aec2081126bda53802041e8b82160e41fe9e003b6ad07c2452c4fa65aa442da64d0dbb0e485ca10cb17e2e25d8925ec19fd75df9482c43cbfbe39690d350333a7b9e17", "DATE": 16632, "PIN2": 6440, "PIN1": 6441, "SERVER_SECRET": "12a947def1f5687ab5757bb5b3e9d083ca72072423c154283ba7db459b55145b079c5345ccdfa7510f92bcc64a2b8337cf303f62cd1346d352c11b37c682f79d0468cd89c5126e605259780b7532a07f7cf79b259d8cd6a313e8145bcff560a2212f5b152234a74a23aad6b8278f35573d6173b2dae0f480357bdfea8f94690d", "SEC": "041d26c7d1baae5a321607c551855eb884e195e5b7c9db8a8d49435413425b5b6a0abdaabc613ca8c85d5043ddb20393081589fea5e464206a1ad2aac69d084d16", "TP2": "041f3ef655080cb9d669660a8f37a78ffac454cc286d8e7ffe715556d85c9b5f7d0346f22bc7a7b16ca0848611b2016ed5b03eacf4d7898afed0f4b458e211cb70", "TP1": "0422fde12d4f39279191ee0cd7c0aee935239daca5ceb051b2ed972f1dda8dd66a101d695b3cb8a654042ad238be5be5c09de726c977a908d7b0bdc3b4eefa8adc", "CS1": "040158a8ab90832a3424ac6a4be3b6189e33a6ea40b6dcc9b0502e858ebaceff4a0cdbd5aac82e8c504117636233a39a72673565834799082dfd3be4a773f1fd3b", "CS2": "041f31becc7dc502fc22e428733fcc99c69b98e893d5e60eab2854a73aacd61887027643a64d75f2a8415916495e3839748f923ac4fc70c411f659297c5a3d7424", "HASH_MPIN_ID_HEX": "1f54a3c0d9ef3a627cfa566098130e9d0331b5c267a859f3553cc1d9fc4d507b", "TIME_PERMIT": "041523b9a65da889dca6ea663bf2c7e449f863b3ef1643feb87df2585c7aa0fda817f29fc87ea6f52544b5e5e9c1aad4d8d5d78ceba673373e679abfa94d85f6af", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223431313264613536623561303037336335343033626664623563373862376162406365727469766f782e636f6d222c202273616c74223a202238643834393637656232303964353365227d", "TOKEN": "041ea683ae8b42dee883c85985f9ec6009c6945060b2c6e925167907e22311839607fa8f89ee55613c5b994adfa3a94c531934adbd232a6b7205f7e8d8ee9b563d", "U": "04008ed86127baed7ea23a3055d319fa83051924156dbf886d23cf9a7c75fef1860c5deef1c02d28056419a15418d310260d4b0e0ea73011523c3175fdf4860e80", "SERVER_OUTPUT": -19, "Y": "0e96b25ca43334eae9808896ded35f3fe18d3ff136d4a6222d5652475e766a92", "X": "11d238fd1709c68aa17def158771172b9c15448b2527bf3583d77fd54de8ac45", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"4112da56b5a0073c5403bfdb5c78b7ab@certivox.com\", \"salt\": \"8d84967eb209d53e\"}", "test_no": 159, "UT": "04165883450283ce105b532596369797f0fa5205c82e36bde54135bc7844afa52b00d4f37996aaded2e721c67128ece9e428b5238502248ef6f1f52b98f48ce673", "MS2": "1fce678f7727db4098caedffafb8cff4e87a0350f3886fcc1cb7fef5aa69302b", "MS1": "10488305b71a538509cff08dd11f0bd1d2967d7a8e16e3aa29b9dac73a249027", "CLIENT_SECRET": "040a96dae657ce6844de86f2c2aa114a3ce2598d64dedb70d508af065fc8b0c50517007c91a0f834e6034a99a3a1b4507bc96173d19e8c96e361e81a0021cb5a5f"}, {"TimeValue": 1437055597, "SS1": "0222b0ae70344d2fcfdbdf3f745fcd6f13ca6e204de3dadfa0f0d4a6def4b20114e7dee3aa82c730ba33d594bfdb2abfbf8052f4be0df2402f173bfaabb5b9bd1c4eeecb227efba53deb14415218105f4bfc6a990357fd60fb48c7dd84b6d115209e17e4d6191ee9dd4de11ab22e9fc9ec0aa39f476c2f2d9d8c6b0e714306cc", "SS2": "207d66fd017ad008d7281d5894a7da2d48fb87385c99c76da318b68ece1971160fcf0eda29603576a00de30d0ea4b79fceb494259167404a7fe5b806b730227a18a42c34b6099e92ebf0fc00836a972b70d57a72203251572797ce954200b69f07f90178f10e87e7811eeba700c6a2dd13085dd1921f51c53f0da1ddf4fbb532", "DATE": 16632, "PIN2": 3163, "PIN1": 3164, "SERVER_SECRET": "1c54ece9408511c3d7a4ea79c267700ab3838064abe837347f5e3b1dba9a6e4a1935dccf9ea725dc27da161d1c97391be60bdeb7c7284e7545acaf548c6c189723f1a4c5e5097ba7a514b418fca98f0d44ba0aa643b9af226494d900fbef7fe51ba9a07694aed64f87b36bf51d66dc377000d9f4c63d2251de596184b4a1cf55", "SEC": "0422eec87fe0d530e2298d6396400e00ca8900451c5a5578c030989120bacf202f0784fff626f21724a64d79cd2c6fc5edc1cff1b9881769178bac268826b9a400", "TP2": "0400acff93d415773a726813bd6c3229bd9cebcc00c4d17cf643ce2af82fe1237a02b3c92e604e4b080017fa2fccb9d4aa8fca2b1481e7fbe197b4fcf93c5b0c21", "TP1": "0422050316eb026fd2227822e517d7f9fa70644d0ce15a811dc8aa0443e174e76d10585bb15aa0c2801ee3242031ec2bcec2ab305ce48baa3ca3927e946aa9c7fc", "CS1": "040ca1c6b620d6d3701b95d93e0f8eb7887f0b814e660f5bfebd8bad1dfd688a5915f43fd0af3a5c4786fecd461a27a70617d7608ba612d2578eda46fc59c631c7", "CS2": "04216d347c1050bd4fb13fb260994ddcfb7ee6da27b2dddf0ec04a36c72e9d32f70f1811551d0ea439418f2120227c57087c824e2826cf971914a014c4de32a62f", "HASH_MPIN_ID_HEX": "cc8ef56cd8575779cc0ac29969273c1bcf0111260881bd37c685271b0d098fed", "TIME_PERMIT": "0416f471d1773ab60ada73c44ab3a9c873f2cd39af478234e700a5575d61e1666b17449fd9445cb28f725b3a440a38622f90206fcaa4ecbe064f46626c521f7386", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223539613332346236636334633135313166623431393239646266303363333637406365727469766f782e636f6d222c202273616c74223a202266346434626136623933663739643836227d", "TOKEN": "0404b7edf04af982baa60f481c9f9ea8e56cef6ba08efa2891eb3d11ad08b3fa40017922e6ea55c000d398284a54ceb345d6296a34da677c306bbe02201efe1479", "U": "041d11169b897e82a1fa10672a8e6269dcbcda756dd0301872124f1e188b3344910b986cde1f943a2ad0580de77bd03e606fbd2d63d1c400246013e0c7d1efacc4", "SERVER_OUTPUT": -19, "Y": "00c96c929e9335aaa3b05b91e62bc5c62a84061d73210e9a94e9d2aa3503d61f", "X": "087b6245c1b171d90c281435fa6b952b7e695e1cd74b8e3425d9341552f6661e", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"59a324b6cc4c1511fb41929dbf03c367@certivox.com\", \"salt\": \"f4d4ba6b93f79d86\"}", "test_no": 160, "UT": "0423beee2c551787015b24bd2b4027d307453078c0882c07d60cd6e76d693c080e224ecdd3b91ea80879a8377877db34d85e037c870a33a55f51c9580cb983265f", "MS2": "00b5c0d97c86ae3e5aaf4cee7aa41e3e1b343034ecf624021eb8ec8b95d9f84f", "MS1": "17cbd3d6b91915ba1ce8ac516f177a89e31fe66c787fe6e81a5f21faef8263a4", "CLIENT_SECRET": "0401305516916a196cde881fecb49789416d18dfc6fc37ccc735bbfa5de748322e0cb62da7081728df0efb242de031cebb312826de916e56152d92f10272877dd0"}, {"TimeValue": 1437055597, "SS1": "1a928bebc12cb1c0f088339a4d23952e0be0b0c2edc6f9b62293c6658eec7c4d04ff8b96e6c9a62f9e9c61337a7bff3ed4b18bc137a0a84b9deff448f3e4278e0c473532945b08e0de03c9f0c39726f88b3574adf10d7c2c39b5903cd55445e612aa323f548d69a02748374a3aafc2d794f0609ea9e8d4146bd8674d4c102fd6", "SS2": "141a14e8653aa33d894e6a238290e6011df5af9b2cb6e6f80c5970dc13dd7e1d07610de414866a042316bf87f86172c7527b0c1fbacce6be48155a112041d4041dda59aec6c6d9fe6df53581766845c0b6477c7cfa514d59a8559f4ae078fd9e15511160fa618a26c6c3c1f8ff1febf7b0fbdbb154f9a91f2e21a8ac74447d2d", "DATE": 16632, "PIN2": 2367, "PIN1": 2368, "SERVER_SECRET": "17e8e9235db0b6e6e392eb0ab380ae85ffffef226c335eada09f6edebd2fa63d01908b44db7edb77866f1e482abaa5f138d305a6162d855e8b40cbf8ba10453c22cd876e34ccfe91738f5e1e712d8a9fb2f173e40fa2a934acc30cb850182fdf0d43782b7f45818b049750a251f144340f2b291e2803e939bb468e3b9085c241", "SEC": "0405b141796eeb3365baa90290efcae18ba3df9c09844fd1fd7cee614bd34db51e143ec1ea84333572575d2569f71d4ecf3742164cdbb851e47bfc453220e0dc0e", "TP2": "041785b6f7df3e33645caa4cd2736427f622a0cf104cd3d37f6b6ad9b79ce7b43805098f923eb38eed50927b3e235c86c777c82a484f482627092a3710f072f2f9", "TP1": "04113f83303f3abc1369f47d3946705aa6adf3fb39121b6913716f3892ae2ee86f1a11b2bade64161b5b93a190a97b94e6e6f1234c0475e06bcd0143d72a1fef8f", "CS1": "0404abec23ac29d3bc177a464d27113d283234493607928ad0e358bc81fcef7405171256d2020d920e02a69c94a35395bef377bb56635f8a973e722d8b0b099f6a", "CS2": "040c20c9493ee71791f76da324eba2850e3598c276f21534b57cec59087ce27b4502bccdc1698c73ba5b7004afe5faa463745a17a45b4b313639adf7cca218736c", "HASH_MPIN_ID_HEX": "e4a83dc66bfe1f865a5ebfae2094068d145122e4b59b90f62efaec3a61e86afd", "TIME_PERMIT": "0414c5221f702585ec3e2ae1dd4e0349477b8016aa2d318c92d311571a07d3c84300b5a7044c19245ba0d99aa8634baa1fc922eab61bc23fdd441b52304669593d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223962353265323235663630386534396435616364613139393637363065663530406365727469766f782e636f6d222c202273616c74223a202262633235393863373637656265323461227d", "TOKEN": "040b982d92816ba90aad852c3050f8c2b68265509f6bc8d65a7782c5cf0212bf96210fb8bff069e39f76cc0610ed4cd7e04468384c655ab4cfae61ce0124cbe5d1", "U": "04238630bdc39160f09112a91efd3c427b15bdbd94b70fed76170a9267447bbbf00c1a8bffabd6248a8045c4340aa49000048dd55c687952f7add8bd1afb52bf19", "SERVER_OUTPUT": -19, "Y": "2103a08ac0b89607f545dd65992b6037c57ef522fa98939ca33104f560eafb24", "X": "011fd58742f6730d472c4c969bfb554091644857b825757b2fe5561d886b2b5a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"9b52e225f608e49d5acda1996760ef50@certivox.com\", \"salt\": \"bc2598c767ebe24a\"}", "test_no": 161, "UT": "0407d72646b50f385f4cb6e5fc4e70b8be9baf2d46efd9a5a9edf03d9241c277d708ff8609d3005619662a5ee4d297e150f51738d69825f86aded7e80b20da657c", "MS2": "1dcd5af374633d24ac2aa051549c4207cd51e4e752ea002c1bf565da2e78cc8a", "MS1": "1dd815be75a2bcc96fda34eb14f65470ba665dad9a69fd3abe64862e793eb321", "CLIENT_SECRET": "04123e884575327751c9821e1d511707323a96eaeff670d7ea4a7215167900e1b51ffe1725ad9737db2e38c1df4c0439f3f3879ed4dade3fcf51f47dfce34fe556"}, {"TimeValue": 1437055597, "SS1": "0844a95419a74e3e1031b351f2998ff3f252f4b6c435cf13217b4fa52ba48deb104ec9edea27e9ebaa1a490069748d75ae33dd8d4935cae4e80a87e9e6c8893218bd97674af0b4e4aa251fab2054700e7638fad16a1e70d8c91faacd6c73f71a0947169e826aa70c260e7143b7c96566ce5e52ea945d94b1d8ee3a775d370458", "SS2": "1b10b9c697d9b5df19e77b56562266c97817cfbcde65bea031438855052761b621867ddf787ee238a5f8fe5185e5825afd7bf70ce102e53ddb02d8a1018a25bc0f471079eed2dad2754baec74eb8e59394e180cfd032d96bdfafd8dd5e2cae30078b3c407fb5cb4ced6af4d8a2c1159e8c111d5dde1fec09a07c28bdd235e982", "DATE": 16632, "PIN2": 5563, "PIN1": 5564, "SERVER_SECRET": "0ab4c90b12f2464ee6920f85bb9fb68c9559795edaef1702a897a11fe73a276b23891e29f0e27ad4accd53b4eaa7d42372b8f2b453aef36a82a9663fdfeba95e0a5165b24c69c0c89293dce2d9bb05e1e44595e3f09936d8945b76c896430f34139db6f214b2f58bb6907ec08bb0c39f5c93c877760e463362fd87ab1bfdd04d", "SEC": "0402570c28e874bc409ec2ff882173e2670ed1e07d2b37b1adc3a722637dc9737105fecf0e946971fb28440b5ad3d121f2a2924fb41d4ffef7f2ff6581d1fdfbbc", "TP2": "0406d505595c3522978fb6d47986bec918d1de5d8de17440b71bf1821a8f086cef2236eb091cefbc8a2efbd03f3f09d37ae839c1a91f23ea587b6213306c4bf431", "TP1": "0406098fc78dddffc2acd45322bd48ddcd22f3d2e895b82f3df74afb78d9ab54ea0d613e4595a147c415f4c3b28896fa0b1c7341197fdac814e8eba186889433e9", "CS1": "04216f73ae4dc50cc4ccf0dc1108fed9ac51de2a5372fa793e4f6056b72a2a21ae23d64023600f1233b6d4c7e2a93d9e52bf448cd92ce6e68ae6e05d5586314194", "CS2": "042092ffbb1472317132345b99386d8e1c341fde0f8b45ce9cbe873c7f0ddc56531a42227514edec8e2af1d67d275b8870cbaac8ea0658b53a212e8324010a4f3c", "HASH_MPIN_ID_HEX": "1bd1d785db0237849ec4e7e9d374e3e62ed3c88db90552fc6a0e78d3e92f7a97", "TIME_PERMIT": "040ac54df072d82cc71ca974288e703796e18cacf4ec094738a867595e031037dc0d1cb4a46edf2a35c635c282e30706681690de735658780f3b4f32260f975ec1", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223536613762366463313937333436623762613464656430636262373561666536406365727469766f782e636f6d222c202273616c74223a202266646165623236626564316163373734227d", "TOKEN": "04020bce64e0f3828c3982d7748627822a67a19b2f2472b08aaeda52ba2c843ad804c7f412a5cad2cb2c48b84262e6879bb159913282260cfe41c33e7369422436", "U": "0418aedac09266d0ed6d335864c1f23fb2b9c87d13f18c16bdcd5d2eeae611a23e20d2f5f8768a74a354f3f5c85034be0fe9775a7e822a80adb711b46cb963080f", "SERVER_OUTPUT": -19, "Y": "200b3ba2085df810c398c49f7dddf76d832a0c1eb41ada6f1aeb08353ace98d6", "X": "02767e158395d3bb685dbb51a492e09d16de1ecb46abb21ffbc2babcb2de2306", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"56a7b6dc197346b7ba4ded0cbb75afe6@certivox.com\", \"salt\": \"fdaeb26bed1ac774\"}", "test_no": 162, "UT": "041e4f3054535f124e18fa69ed43f7d46a31abd0a0dff9126a8f29c07c3fdffc10005118c9b21c75825610b90525bf186c4a96413040f120b61bb239bd01a12ee7", "MS2": "04ad1dd96d942a4a5e9db1c04f3796ba113aeff893e3450047373ef0058ee17a", "MS1": "0d931b2b10d61071b71edb3987c8658143aac6b86f51df2a7c66b589c9cec16f", "CLIENT_SECRET": "040032a7d7d059d2ce2a0a95060aa58b2975599ee23721a69fe24f3fa1fadd2581184c79ebe5debd27c00a4239fa21a54645d7c4645394ab34e67ab2da0d35ad39"}, {"TimeValue": 1437055597, "SS1": "05249c8c78f9c43eb2f89d0efeeffde6ece70e72e20e13419500bb6f7835f9e01562d5b1fd96fccba745114dad7cc786455c91c60cbdf22d76bf379610c80c281a7e4bded4f96f599783274be7a3a43100a89b0fbd37a1ae7b3bd5e8c2a8e59d0a6aa7917ccc1aa040923096930b79ed65b7d2fe007a934300eb6da675427df2", "SS2": "161eaea0c427b11881956952a45d1e2680ca644e7be336f42c14ae26d9c9dd7c11ef144e1ee2816d6d8ba17d767e3c4ac04e861041689d920afc334cee41202a07a9b38079d4530d4bd91642a9a8e92b351ca96109f97941a961f5a7b903e78e160eb5a166fbbe636b0667e664273bfa7f439ab5f183e498caa0b47cb71ed1c0", "DATE": 16632, "PIN2": 8939, "PIN1": 8940, "SERVER_SECRET": "016712e5188b099ff9ce077676fbff5911d7ccd9ffebac9cdd3c35ba3eb9195c0e35fb72ec11d3231440649bc568a0e2cd411c63ee3f1dc028c0a39ea61a2dcf1f38ed0bb5ef9a23c8cfc2f492a74845ed0596a1b396f3d6dc4a27efebf27ef5031bd714981a7cf09ebb881f03fc36b99506ce81325ac40320dc111a63347f97", "SEC": "041c7276bacf8cdfbd937ec1f58e437392f3dcf8ac324d888b13ce1cae2e5af3fa1a4b6b9e018f4c3dfd0280daa7de2df0bc9297976a167205ff3b2b3355338cb5", "TP2": "0414b243446f64125886e9da8e7b19fc35065133a583e3f4ffceeb659298ae982113bae748b6de635c2331318074b3972ecf17e27a28afb269e873c4cb8c291356", "TP1": "04055b6a23898a9627037addbaf3db48100d5834e63122f8476b32dfc7c2001fcd0426737f621e41d760f1cbed38046ca5ab3ce7e29f0579e27ee8f2f06d7a077e", "CS1": "04219379a7123c6a1cf5884c23ed7d799d507dad64279cfc0d58edbe74d4cfd0ab23344c0b79cb4c37fdf992890828be29dc0f1e85a040c88b0f70ec51400c0f1f", "CS2": "041be7d7b47b0f1d4ca60f82bfa613cdb930549cd14c181aec036089fb6e4c711c21fdb88371826e48d8bf766c35f02c126684d7b49a17484748aeac5ecbbdaffb", "HASH_MPIN_ID_HEX": "70b1a3bf5af045b7d8d62d4feeecbc099e8044adc0398a7b99d209348bc8de2e", "TIME_PERMIT": "04014ef477a18c62c5a2275b47ba83ff4d68a66580e567b9b7b1efbf25a56fb90922b57504fe899fcee02eed8320781e778d7b12ca902d0438f824502ae78967c5", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20226163346165306364343932636661313834303534333333613336356266346337406365727469766f782e636f6d222c202273616c74223a202232333836343563643662613366386461227d", "TOKEN": "0423939d3a0ec693d682c8a88cf138fd6b8952aef0726c118d6ca43d20b25538350809eea19cdb98a7d456b705ca821c066bf01bf49edae42d1c1618c3bffa6fa8", "U": "04054ad80aa5837926efeb7f7c90dd50606fa15eec5da7fb48329e1eb4bddca3a91463a66f277f7966d41cff75e175a3a0e96bf2fa092ceb720d141a481031ad65", "SERVER_OUTPUT": -19, "Y": "22bee87f6d102b428a5409ee6afa20f47c878753853d630a900be647c5780942", "X": "12c796c9fe061d1184ace72910edfd10e2661b9dedf64d45d6ce776d667c9ea4", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"ac4ae0cd492cfa184054333a365bf4c7@certivox.com\", \"salt\": \"238645cd6ba3f8da\"}", "test_no": 163, "UT": "040b9f50c4733da6fc5f134af21da729d4d00d26344b7d7f5c542d88b5c873b0a703c0261ae824cc51dd40fc5c86ee914704580aa41fa3d1fc96f4f6dd0db65bf6", "MS2": "1beeb5353aa33e327c0e8c73c493d3a59ae0ad78d78416ce0da11273464fbdb8", "MS1": "1a553b43d6c11ee235beb52fc21d7e1ee0ec2d8c0a89d41e3f80e5ebfb8363d2", "CLIENT_SECRET": "041f0f2f7501c4081ca48b71d57b62a40520f7de92c92a55b2d9eb15b6180292540a5d911d1f727dc9f75ded2e738a2b2847414e8cc6187a6a50faaecd245ef7b9"}, {"TimeValue": 1437055597, "SS1": "0f9dbab6e0f26f9aa60bbb085fef54b8f416984f864027c7c0665b9b696c233f02439371e39d8c93fa94ce754e83cf750cc93856110281d520c71e558bb37d30060083d6322721bb550446006d2e09c62b83351defe61f2077ebbce623c4a8080cb9507598928798cfaf8e3e4b9102fffa158ab713c7017b8e24e97afba1c754", "SS2": "0eb7206945a67c0767266e40b1d055d1d2281bec19aaa75bfe4ca0d4d506253d1ca5e3c4cb2dc27ee1e697c50828fc24d92d3ed24d22131ef936ccfabfa47f9502dc3e2062dd4462b6fef5f12d1c60f0a637b91a9f948b506d5b41ed3b2e4afa0e009adf9353a9fd535b8652b4ac546cde0bb6bd0d6e1eba4b2b3f9da4ed4094", "DATE": 16632, "PIN2": 7457, "PIN1": 7458, "SERVER_SECRET": "1e458ddac40b67e471d596990744d3be22c2aa6a9a98763370aac366637eb6de22d3049e1c3c343f12afb236c6565e4da548e5d6f64d1d701abf99feb5ea2f6e0808f4ce7f89a0036cc6d381c463a9ff0013eb50f87d75b136b9b985c353cde81e82a741207ec465c3da66fc9c49b05d5913210772533eda29be6007731b0972", "SEC": "040a8915226ca4f3a0b463228c939b43155f2e8d440b7e9155bf78668eda1faf870a656a355af90609cefb7dabda556752e4c863f47b1028cc7161e2d824b2454c", "TP2": "04197e806061223f017bf4fd3cb3c7a02770a395fb2979600d5df29f9886639b290af1b551c93f14383f869441c81bfa10b4644a1698b3a79da515d6c05cd32825", "TP1": "04185d29113187ff91bd4fc0d379015a6f818485d12f440433a16aecc9bc6fbe190a1ed6266cda6eaa94bf2966f59de14971d948865852d3d902e1f8a4d6675935", "CS1": "04144b899e3e8e0c977940a3d0e912d1fd5cad7c8738d02f134786aa067efcc41f180389798ca53ee3f2430ea5f7c784488ae19972946181e3f719a5eec2488d9a", "CS2": "040fe3226756cf21a792e9d18b29bbc70634476444409b46abb783ecc807f1d60d1160d908fc69c679928028ae8b5251a34dc9d6610e3ea313cf11c5753b81f120", "HASH_MPIN_ID_HEX": "f4d1fbb59cd2c6bfffdfe3a5783abb7ea02670857eff702917aac032fd3294f4", "TIME_PERMIT": "0417cba401db4f9591778b3db8c6a9dfe65df4236f6018cc8688a1cdd613eda68421bc703c54357fbe138e5aad53e2d5d45481bc87d59d27b95a7e303e8c192bf7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223334623135613538396434653561303432353566393465323063353464373338406365727469766f782e636f6d222c202273616c74223a202232316462326138316439633039323339227d", "TOKEN": "0419e6f224048ab45a7bbbd1e4552ab0c3393bdc3ca9807963a9da9eb27a7576b421f820df36560219ac524376c25c2fc737cc61f28b3c7432f34e759a5ff8d32d", "U": "04106c633807973aa142a88872733078aba222ec40eaff3b53a772d67c2d3191b70ced05216bb93fcbdbc830b8b649c3e56e02562cab2605f362cbb3e1760747ba", "SERVER_OUTPUT": -19, "Y": "1ba4ba39db3bb9009ea9e277fe72bc324c9ac5fb6c047c5c81a2ae959e851e4c", "X": "0962094ad35f6a2d7691f435482125ca2c7ac6637863632881eb6a8bc9d413ea", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"34b15a589d4e5a04255f94e20c54d738@certivox.com\", \"salt\": \"21db2a81d9c09239\"}", "test_no": 164, "UT": "041ee9595320367ea5db8b9484bee9ea79a76438036c738ee249a210fb00601eaf05ddf89a4f35564e51cae55dfdd66c617953350151529c4bda22e6de60a80310", "MS2": "07f36e36dbc187a771c17f7f156c404feb4d34ba8002cd4cc5683701a19f3ff9", "MS1": "0ad56e09e0f80286c08459dcc1d3c1991f0928751a7e24f1527df2c2da74cf0a", "CLIENT_SECRET": "0406e2096b084adde86f1ceac40f882af1e503b6bcb739a6adf73de558434087bb14665b1529ac2b9ec06de04794bcf26599bf571fd808f3300a0c2f2598a59771"}, {"TimeValue": 1437055597, "SS1": "11e1bdb6e0766c0e29e99ca8b377d92434ba3c5ec63c9307924993648e18568f032a091246f2496b9abe3f952be9d71173c378a0e901f5b656e3879e5d95fe14059959cbc3b321a0043ce70102007e70e666364e683e961ce8ce1edc8fe8bc7a1930e7afc0d4cf54380b9d1bb73208cf9ee3cba8cdc98cdc9fcbdf4eaec9d84f", "SS2": "0460e02e9186fd97f9dcc5b80d48735b04531f1ca01e3e9b5af8d7ae2427459011ef40d70e08f07c3ec7b3f1aaabb9d306de449c50124fc05f8fe50ef1e184d70dcc542d52fedd313a5387a7d3f17bbfdb57550a5702f524392091de7ea9ff5215c7047a7995194e5f2702e0163cd1cf92a1372a314b6912cccd8fadfb3f9866", "DATE": 16632, "PIN2": 8274, "PIN1": 8275, "SERVER_SECRET": "0a624d933b60cabe833ed8d8ffe6ca16ad3d711e8e3ee606bd51b97490544c8d1faffedd6fb9e737be666f28d7b88ccdceda0ea1131ef403fb7e7aeccbd880980cdb36b11e8f84d639b3e56daa1f89ff9fb3e7705671d2a66a26a7e2f0891bf31cd1c0e6ce86ea022d02177fae806c8d9f167eb029557763f7965831c1998e39", "SEC": "04169da81530640acc16c713d50b890a99f59e9d18714a133d7308e88e9b8284e119b14844b7afa4d4111fed078cba5404d24401fa833e5af2b7c6778203f0fd01", "TP2": "04154e30528260e16622ae485427a15b22cfe6d3e1e56db2e9d7672b2b2c0b116712ea850be09672677b1db0801d27717c3a75e80881e48ec0416506c62410f86f", "TP1": "04074ade39c2d6b9c31ced290ef5568983dd43eb7a54b480a6394897f1d892a0b60e9e93be7b20f49b51efb703d1544711b00b1a23f0fc8d5d1e24414615d69b7f", "CS1": "0403e695af488a5cf885e4ec9d6ac51337cb9f3d6f27e45b51e016cbbd436a6d2d1535d3a7b7a71b3cdbf08a5eba3a5fb4f4770d2d85a03a8e0db7d464ba4e2b88", "CS2": "041586b94124a61476953d3b4e029d8b86dc44636c586241b0ab7702b4d794b29903cd3ca9dc7b33442e8439af3d7a346c59ba81af21ec6e363bfff8fca9485acb", "HASH_MPIN_ID_HEX": "6c37f9c074984990e6f0256ea9b4cbb1c3f1199bcd5be2c24a8f67b7461c5663", "TIME_PERMIT": "04173b356543eff7cb97d7710d67f12b73b3087b9b6d4268506a0d1b464cfeb90322ed72424b34ca295d58d8d54c28daf847d0c5801caa8471a8fd2d925480af08", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223536383465343961353137633639666161626561653230373034366438363330406365727469766f782e636f6d222c202273616c74223a202266346665623463643938366333623761227d", "TOKEN": "040c031102fbff1dcb28e3895933492fcf6677bd0b75d01533ce6f3b1fbc81d0dc22657cdc4e2c9820ac45d254ebbc2e7afabc76fa372cde278350e8b6475d7cab", "U": "04015243bc626d0edfcffd9afd46fb43fdf0b5456cd7b622d9ecd0ee51f70dd1971a78e69f190ff246a82d5d3571b1d6b73d73fd49d4811d1ed35cc771e0f61342", "SERVER_OUTPUT": -19, "Y": "00df3123132f164cdad6e68d73a27a8618f703b05ab04109f68db7cfb3c139c5", "X": "0450519d58ffb79d5092fffc9a994fbdd1f805c5610302478fc768d1d1acc20a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"5684e49a517c69faabeae207046d8630@certivox.com\", \"salt\": \"f4feb4cd986c3b7a\"}", "test_no": 165, "UT": "0423e5a6ddd401e76a16f6c16cefff2d82430aec1f13a49ae78fd7bf81e6fcfcfc0a20086a7d17b118ca7a5cc12cee4c1373479221a52fa775f3c8c6d79d5f1e1b", "MS2": "01799e62fecebb023dc93091309983a61aad953d23ab4ac6769dc91ff6ed3d5c", "MS1": "12f412466d75c1f9cbc10b3f9b4d23c9e12f761f4b421fd590a934bc2f860fd9", "CLIENT_SECRET": "0413fca66e5404fb269bcdbd773618cd9d1036ede0ee1a10520ba1473ce534fb8402d89e399e0f5a8d476d5df82528ce7aa86a6528e890683731ccd3afb496ba38"}, {"TimeValue": 1437055597, "SS1": "20ef91a225835349d422378096d272c096fb5c91feed80ff330d20277989d4170fbd121aca6831baad353598936b586b93929138e77102e2d9306ef51f854fcc07ee168f0a60c4306c896f726ada9566c6214e1ed5813d21ad8a0e6b3d3ca3c90b15e5e2098cbbcd40a33665545e35fd42e42f07973a535131c8b0f883d873f6", "SS2": "06480d1452ac19068c2d1152c24a40be1c93810393f00c5f62ff7f3be6a03e1505a9064876ebca434eb91ab5db415fe8f68dd201744fef2bdfaba9c439ecdd6b05d5a6724e53b66c609cbea74235f25ab9eb4c6855c00424de7b739cc4e9a8150d8841c3c969d8a2f454d07c5d3a5948074434d0dee00c1d0fd6c3075cbe26ca", "DATE": 16632, "PIN2": 8400, "PIN1": 8401, "SERVER_SECRET": "2348fdb5986423fb2a103665122c3c5092c7b79e24c69faa45b2f15fc1891d2420f774d1ec328602b44abac2670f3f1679c030ea74e085848457a0272ec516a70e4f0ca02f919d2b6444d3e403718bcba38a048c19a3a77b3498a014d8b15974216394bf1b3b0f6597045553c3388acf21c8cc242df4fd6026bdb2675a9aaf19", "SEC": "04169af15775cefb98d282f76b30db1dc980977837bf0817379912e2c77a6ebc751cbd866cab9968be0fcdf8790cf0a1d2313f091c10eb81201288fa3487f552dd", "TP2": "040557fc96e2e324f61162d290812544570c666d2cc571ad2ec90fa01fa7f86f4a1bf2c1f02fbe1f056249ebde4cc31a7883296b9bd20482067fed5090eb3171f2", "TP1": "04184f8e9f86afc7c33e8c55e908e58e1f0a686b2f8e6cdab0a3760c172a2254f61def6ec784110b4f90c368e7d7df2bfa280d447ac9ded5700029e3fcf41fcd67", "CS1": "041e55194800ac1719e32d2f5bdd4aa0e5ba6715f1d9037d275ffb3b55f5bac99623098dfdee517ff1a0fda760e0be2e2714ab87dc2c0bcb0bf065aa7566ef7c17", "CS2": "041aa1d08ae14cd0cf2232b969839e70e2a292fa56cab12d18597ab0c34bad44540da17ce715d15eb65bf359d1b897a53a6eb0501ae4dbf019aae5a4a31090ab3f", "HASH_MPIN_ID_HEX": "74d5f06e7e9b9395fda107c9f77b14dbad826dfccf3c145ab5925b54e36d701e", "TIME_PERMIT": "0422ac00361e3246c87d683a9bba9b6a31403a608610d49c94043cd7d11963786417a3a3fa224f4217eea2bd7a8087baf191c0b1b39cba0cdda579ea45a753526b", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20226264633161616230326335653864346238383534303061646536313132333431406365727469766f782e636f6d222c202273616c74223a202266303465616161366165316364343137227d", "TOKEN": "0422468559846b8fb538a2d0b965f1cab374e314d6d52b87ec0b12a44cf219dcd909ac679dbfc8509c9f5cbd2319cf3fb6b0292d52b9738bda73614e7c7aa0d741", "U": "04207f5f1d15ff8c8c2bf4a91c712d24f46212e2fa732d5a2eb95f33b3d798e3010bc7536c0cb46880812c16aed586ded8f19ebc852a1e2f857a3eb5a99d1c0b03", "SERVER_OUTPUT": -19, "Y": "22b61609319b60d1c3b88d9ed6ff3c3e5c4eed6955ca51e4b6e1be817d554867", "X": "0aba13b222cf8161022957d5f98b8a62f37ed1debe556640f14a2adbf84bbc6d", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"bdc1aab02c5e8d4b885400ade6112341@certivox.com\", \"salt\": \"f04eaaa6ae1cd417\"}", "test_no": 166, "UT": "04031e991d5b6e52e0b2acce983a183c53d1c134c1557bc195854f40f647c3770a1b9fb73cfd26a2cec2634c068700ec32ae210afc523eec55f1e85035f342407d", "MS2": "00190d2b2e223d420b50a1b36384b7393ec8cbcb9236bce62825e2dc3047d551", "MS1": "0731bcfd8dbd211b0d78c5be9f7d1af92bf48c62018437c8ea32322cc6aaf295", "CLIENT_SECRET": "040654548e20f1aa309c7c04078bf1f7e2299f214f2f617df69dc3be897a5a6c4c20b4c5f27bac67687bd3f3e4ec441810067ace01c170e42776d7e7d4d91a03bf"}, {"TimeValue": 1437055597, "SS1": "226a60fbf5142ae33168d43b91f9b794df5a9bf39272fd981ca7e9e41c9d03a20700dd9531ba6e2c37e0bb4c5f4ec9d87a366b0969745613b5d51b46bf4b48ae02bdd7b9d62303c74c6443b89f25264d87679f1840ebea813f6e2cddedd3476f1be33dd6c758fc61911bbaf7be620bb447e4577078da0f9dc7fa7c6274820858", "SS2": "01da5f47e51825a3df46700f7e0e431b372cab590b146082170180e9e4cb1ace16bc1c68b54814bc07baf030f83f037fbc9051e01c9b097dd9dd44ff8fae9cb71ac741bf752887d8d71f41caddbec9aee3fecb5687970bcf3008abb2e53757bb20f1a527fdebe12969b0f77f737a9e0f9d3315bfe9111368a3817aec46a58de7", "DATE": 16632, "PIN2": 3131, "PIN1": 3132, "SERVER_SECRET": "21090da3a48a7fd7678b5c9632ce0f080e7eee8f3e676bb514887d1ebf5ac7af0e252a1da721c3d10feee67f2f9f835e1db1bb8bd4ca112007f74dd71669ffd909ae1238c0b620c488f7b442756e03b426d92f1409738f9a48f9b11d1e6f7a3f031a2287c56973227b296d0d21faac0aad4b38fee1c96b3e1fc57b684f822d0f", "SEC": "041e534e3d91ae3aac4d50048172c541d96b24be7f99271fce34ccb07bf06adc07099fabe6c3042d11deb7cfffbc60013d4513b835d34de0baff4273097e3a4a90", "TP2": "0406bd06f342c04bbf09bd8043394a35621a33c182c1b75f102578a850826fd9a8024b836118b45f1ee15a3534ce0a2bd9e3630e5987cf4d27be434f6fc4332e71", "TP1": "040e1073c63f5d237ebbffbc94ae21645e7a1f1e48e4eaaf9f409a9af8014d09070ac3d9a79197b3d591483c86eefc09b126da39ec0b70cd21406872327dd99b96", "CS1": "041110e4e7f2813021370652b2035b225a90bdf0adbbac21213711a0a4752c2b2809d6e292f12e2ae88c5121acaa0463c3c7feede64a8db71f5d765c4df07e4697", "CS2": "040adb0bb6bb285dc28d5ecdb62c943686e9ed658c47916874a184fafcabbedeb61e28d0d8deb7b4d4f1b36c838572d69e2aa1e43cbee8f68e0d15048ff65e20c7", "HASH_MPIN_ID_HEX": "d2d435217a862738cd5a2df1f647f7bf6fe45de0608098577457573ea08693a9", "TIME_PERMIT": "041c83b1d0eeed3a4d866f857fb74a82fdcbeb6f879e9772befef859bfda33c44023f29125a5869a38b1067de2901bdccee6d375c85c8e5374db58e8d451d8061c", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20226538646334373136373239366565643130316363336562393939613164316231406365727469766f782e636f6d222c202273616c74223a202230353535313939636130336231646562227d", "TOKEN": "04017c91ce13770ca33de5202ab1fccbdb1abace116db56cad922e5926690785ef01fc2c01899d3b62d59115afdf849c289ddc1e7c398fa72da4ef123c3e9b534a", "U": "04185ff31e3d732b2787555fc6fa1bc4938aa038adca6df8a071755b2ae5959c8f1b43aa7df5263aec5236ef5da4fb26e1e7cb020cba4ea9f9c1ef9d06031d90bc", "SERVER_OUTPUT": -19, "Y": "233edd5ee030481db760db064fecc38bcf5b7fdb812be9d088f9300d11aa793c", "X": "1543b18bd59d52e585a7bd5981eb1cdfa2339baa28e84fb8c98f6543599a7556", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"e8dc47167296eed101cc3eb999a1d1b1@certivox.com\", \"salt\": \"0555199ca03b1deb\"}", "test_no": 167, "UT": "041859248d127b08140d03b95673772f13a80bd17938214d9baf433478f635fb7c049a6859aab04ed4a9d896b0cd04e645f65bc1db04efe9c58344ef7c3e0d55dd", "MS2": "018c6965fa83ba286ca0c4a960857639d9d9597a60ce9a8fbb9dcb53089a5bab", "MS1": "06974d4e644b9fbd8af4e5dc9439b614f20183913a37e1c61398d173b70814ac", "CLIENT_SECRET": "041c01ae727007d758de21c5dbe035f6f4a962dc26b078af3e32ae2f6d5334cd491e22a9070c678d653657d181129f32fe9c73694ad6659f823318c0e4060f5d19"}, {"TimeValue": 1437055597, "SS1": "0eb0eefbb1c6bdf385ab181d969bb170a74356f895c11b28ce1bdb74abc2faab1fdef9026c39b70a198f27c2bdc4f53140e28b34e7c9b404941ceb31624499f01e25ecff5a6410cebdedbeeab5e68726f5fea62564ba988d758d4d16bc23ad940ca930ed130772e9b51166b289c74b8d28b6de617dcc23c54a477364b1d24e86", "SS2": "0ac1117dba931d85467355ad9ab177e9a2f49f9ca1f013e7557804e07ee3cd2f07147330e83ef4b62947c7d7b44c9050d5e97cbad8329ebe5251396109c4ce81191ddfb2fb21fa88754f5f8e119fa2a16bcee21bf44cabeeaf8d638e47c7ce770df3a8df8833f627a7a345b67a3a7b7e667c49b49964204f9fe1c21de1e820dc", "DATE": 16632, "PIN2": 5795, "PIN1": 5796, "SERVER_SECRET": "03383c77f51b71a38efe1e1115c48fe9aecc0128e0b93c2fec8123b6653fdd6d15e9d0d95caa3c3faeb20c828d48e32d43fd0dac9c22015f0677c2db6feeec6f04343e1423d6ab6d019becba6340580edee7fb75f2d9a491f9bd5b1030adafe217d053c2f3a7d02ddd890c95d3773026cac494793e591edb135177fae4deb13f", "SEC": "0414fe7f8b6fddb7342ae5211b316cd021fff49616b7d990a75eca4ddb3532a9b510d7ec34c30130a5f016809176fee3407fee928df6a3b89941ea4eee6a5a87f4", "TP2": "041f0a5dc89bb4cfbda75d528edbf7aab5408f5e0866d00380d1faa944c1ec41b713c11193b082aecee81749366601d8a20cb9293f842a0e12976105d46587a7c7", "TP1": "041cd1ff9cc59c6071c051ebb3e60b0950ee14d8402f9c9ce71353c406f5b5d094014b993cd15cf11cb8d11fa92094fdcfcf831c237072d94569d9fc939de8860a", "CS1": "04131d842b9b85c0a56e46878cc78d253e6ef6a4792c596796ea87488a4af73afa07866b815edcdb219e2adcf8348f89ce76f49895bcadd224d157434ea2a49092", "CS2": "041cd0da51d0353fe964eb5f3abaf3eb190191c5e3f22f770a1226c085481f52ad06c83750d877b4ac16e2175defe23a007e69a082758df0627555ec5a1e01f9ce", "HASH_MPIN_ID_HEX": "85857cc4263cb6de97facdb351b713da0fdbbce9de61b506d2bf6ca1d55d7a55", "TIME_PERMIT": "04135fe7a0f992e9a032e9bfff940336a92425ddc36e8a243d38c32c4b2410a6500944ea420de5272da6be1e116f109f067b0fc22edb0782ac78f306ae316c1415", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20226663633134666366346564313465626632623330396366393136626639356230406365727469766f782e636f6d222c202273616c74223a202237336363666139396134386237393630227d", "TOKEN": "040e4e18a8968f35b7f820e57466dfecb27e037fef63892f2c97e63032e9ce7874016c567a729034a3ba6ad6e04c06d81cb8154855a7f688ce2bc7979116f8887d", "U": "04193c8a0a301f9a1a6388ad4f909286f7802f70fbed57a0fa5878a7fb1d1e5fe215028b822dbee415d8597664aec10ea466deb85c3588e6c4d25e3632a08312f4", "SERVER_OUTPUT": -19, "Y": "21e042eebe4b47ce18391089b58223a3e0da9addb4ff51a6540742af6394fd87", "X": "23721058dd8128429f0efba42d9abe6b701b68cc916031bc082302d226a24185", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"fcc14fcf4ed14ebf2b309cf916bf95b0@certivox.com\", \"salt\": \"73ccfa99a48b7960\"}", "test_no": 168, "UT": "040a8c6a6aab4cf2ee6b7526e78be75dc6ae3f338424b39b8ed560d262f64b3c1a11af104e6bebfb362557d2e31e027bf7611e44b0d892b5e69eb53de6a366fa13", "MS2": "0487069986b462bfb2bdfdbbbc6aae20a41b678a02f99a3695e0110801693223", "MS1": "0cdffdf8a8cf3464f220b16c67436a56b2583d59edd6422bb450925a0a69cc9c", "CLIENT_SECRET": "0418649816f53bcb659ffc2c15b251ec82f16d43d969063241605c3dbac3d6db46015add566207b4270be028ca5268174abfe34894468b0117cebf2147bff210dd"}, {"TimeValue": 1437055597, "SS1": "05fe8b2714ec68943535aa710d3d79ab0e428bdd303cf4fbabd07cf1d788375f1ae0d96bb25ebcd0f7063dc7f0452ec2f94adcd387333d28dfd3d250f93a110209fc7e71cb1245c0f62089a344c464a596ae7b6d44da6eafc07cbd3e4ab492d3043b019ad361902b22f4a27c7599cac92c674c88f16782efee74c8ac6f230c99", "SS2": "14330b27f596b20d138175b5d9b9d7de36689d565c0e6a578d365a072d289b5720b28e3acd43e4a769d275b424e3ffb5ef8133d82e6dc67bf5d7bd4bfb362a751ef0e78292f88c2231e367b8a86a6e0c56f12b44b4ddceca58cbeaa481173bb42294feaef3fc20f88af3567b58b73c313529bf42fdd5ea3ce13356dc830b2383", "DATE": 16632, "PIN2": 3215, "PIN1": 3216, "SERVER_SECRET": "096e344cc58b421a6a7c714afff017ce5e7273bf9ea2acc08ddf91258cf8e5c908eb93f2f84bef8a6d07682ab49f3903a835cddf1283a635c8707c4b188937180c429436b1c224faff01aad6545d8ae0d864cd608e3c7f5305a2e39e08a9f076044ad7981389103e590932c70a107b61194aa9982f0632fb2bca4a11f8528c84", "SEC": "04178676e73ca5c932f340d1e4b98ea4e160de926f785416a0bc8faa17a78b5e5009010b710de0c5ccbfd92f9cb73b9f9d9298fd0f7105c50f0cfa42094f462a37", "TP2": "0418dde7415279f8ba3ea2570ecb5df6d0f6ec6fe8763336e98946e059941109a6021c1165f774281cc6d87f65ef78136e1ad4db3221accaf5c0919a910dc6d156", "TP1": "042034baf42396b9ffa9068f06d53dd746800023a35a29ef264b83a88e245c30bd1cd2b3d5057f861a6528926bb4b578bebebc16cf71af31fcee1cc9bbceb4efaa", "CS1": "0408def084ab23d7783e3473bf411320d100a91f7b0dbd98cb94c9393cfaaa7aab1b9b595d4bb4a87f61529d6ea939658a7e78381efda51f7b932febbec27693a6", "CS2": "0406f1383e1b9fa073ba34195936f1dfc68c30c5f2065c49968aca035b0b91648e06f0bf4a41c6c54eaf30f5464edba0466a8b87d517146cebd642cc5c0e95df2d", "HASH_MPIN_ID_HEX": "a64b78ba99acbb9a6b4dcde22ebceadec8779435ec55446b39ead553f4e7d56d", "TIME_PERMIT": "041a06c32e7e9e859e5230786da50d915a9a2f99495f3e880df12bd00fe25ef9e20942e70d950530aad823f1d5bce1f17ee9b92a3f5e276e6d9db7ea6b56e3f4dc", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223662353463336635326662303631336236306163663435633161373336343933406365727469766f782e636f6d222c202273616c74223a202266663862653333396531646163313363227d", "TOKEN": "041c075056d29bee4da64c69e80c0f1c3e35fa4ac18845a7d82bdcbf0c6c51aae4105943999661b3cfb66d513254ebf344a2cca79e1ea007deb9fb9674a92e4cfb", "U": "042113ab3fb7e8b0781495052b5035e86d49c6029f223a1e0f4ab009a7477e44c20efa93b0e133dee6d6385657fc517dabbe63ed95fe1ca072a74d6fc50625f196", "SERVER_OUTPUT": -19, "Y": "10437e519bc519016650ccd1a84aca901cb32ef7b41dd883b67ba814e45f06f9", "X": "1ac5f4781835d86d1b2c9ca3883f3ca6fe5f9c189625c9b72304f13babb9116b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"6b54c3f52fb0613b60acf45c1a736493@certivox.com\", \"salt\": \"ff8be339e1dac13c\"}", "test_no": 169, "UT": "04070aa670ccd675e1fd23254592d2ff43f7a69d13473c3feaab787857aa6cb2c5109199d05ad3274bbd3cd6cdcf97b76025eb18c75a8828ca8bb857932f6f7ae4", "MS2": "0f380dc40a223ae7a376a783756563109a7b0e86494c9c4e6d2cb9325cc508ec", "MS1": "048c60d0a6c015adb15387ababd94270f680c57ecd1c10c8f68a70324e3d4783", "CLIENT_SECRET": "041e4dceb804785c01fde8e65e7ccff64c5bbe3eb19acf8b0af15d5b535e5e032f04c83f0bb39f400efbb47e52cedb77764d5abd4803b10cf7b1e9b8c4517b1d00"}, {"TimeValue": 1437055597, "SS1": "00a52c4e8391b76105655c9769386b80242c55642a6e45221c9539ed6ea8b90d0cfaa2ef288a4719f8b91dc5a18a31234b0d5a204ee61b467d03e11f6a9d956623d8c775f4889a96c8d84c6b456449868053b1e96139778c59dd3b53f05295651ada7e9bd9ce4d22ce0ee8229126a0c1704d2b7d825c25da92249a721ae3e98d", "SS2": "15fc85a9a352dfefc968d504e0375593d92c2b65537df8ad9b88889f4b7c046703453cc78c22a4001223f113044e8878f4e88c4e96e89b4a232d0cbaa8a4ed80012c1c3e496a22d07b075ff34edb47f81960f73d6146972707acce6c8e7a8109102c6a2b7562bd7cfb8ab8b1715f8e24bbdb926f9903383fde1e0b01f14619f6", "DATE": 16632, "PIN2": 1452, "PIN1": 1453, "SERVER_SECRET": "2135e18dae6f56634e5856ab90d05f548f51154ed16adcea93a38f5aa044be1c0a008a983b63c92d854617c7c5b502cdbca13e637a10f5b86fe08d0b148549cb0acbe180400f2f893c278ce5eea4d52f70f9ba7b2e73d0f8f5f093b506ea74ca0a5ba4a4d4b615f3ddc254b31811091f9eb6544e9aeb6d63699243fb6b4ebcd1", "SEC": "0411540b0b4eef5633e3fdff4ca31805c3d1bfbb8a48168a01e36263f51e4775d304226836bd0adb4f303f0fcbcb99ee19a86228f8b4c1e3b28195b804b74a3c6a", "TP2": "041d763d326eff91289b545f0ef9c55cdb5ca5ec46339c9a389dea94b32f3d0a6d1ac84d05b47da8d65856c190e03b613b7fa5ccaeebd25e2ca84314abe48bd22b", "TP1": "0414bf186f8d77eec564c74403b66a8f1222ab55ce98e89937e8349292bc7a3d8a1e13ebc186a05f124a87d0ceb1c69bc5592a01071c7b5dcb1febc151427d85db", "CS1": "0406dc1e4d11c296c9897013ed047798e7470c4500680b40131d42c45b89666a2219e5751385789e9cd1a4a4f3db847cd0fb88c02d973b7d39199fbea08597418c", "CS2": "041b615af622561b20f25e42eec9705feda703b09a352e5e6b309427a251479b811a7f401490c341a3ca9197879c53774df33a7b62caeb7d583077430050d2c96d", "HASH_MPIN_ID_HEX": "ef7442e9fbd496d51f32dafe55475f1468ec340bdcefcf64a68efba62eb9c5da", "TIME_PERMIT": "04009a548db4fcd25b39aca88bc55904e4258606d4d4824a7226d26491fbde2c4e0a5f5566e0bdac5d2182b1634f4e42c70dea90da7a9ef2a3c96692655b69a772", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20226662326130316465383664626563633834613232393633623835363861663661406365727469766f782e636f6d222c202273616c74223a202230616138303261306237303334656161227d", "TOKEN": "04000549236e4326217722eaf6d8911175218037b2150b5c242586bd4466443b691d8568a880b98a09184a2a242f4216d2f9ac2b672f95657f1739962c1e5189b1", "U": "04065cdfeedb058f418aeda9d7f721e334f82ad0a6bcb77af07cbf14dc03c4fecc0cbf76318b84d176dd8c5e921effe536bf01c58ba689429311822158856e6748", "SERVER_OUTPUT": -19, "Y": "1731367d255a2177313c5afeccf2c27506ca39574bcd58927c657ed1b4dc6eac", "X": "18764d68dc71e44bb41f1dc67ba0542be50d431c3d746c996add00135b2ead8e", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"fb2a01de86dbecc84a22963b8568af6a@certivox.com\", \"salt\": \"0aa802a0b7034eaa\"}", "test_no": 170, "UT": "040086e4e746ccea89ffe508726cc0e5206c77b7c2cbea5a578951b092baabfedb004ba1acae45f28afc21006fd77d1d9da66917d68f2fdfd48b86040b859f1406", "MS2": "2062c1125aef80576dc2ae73a44e69c71ea9c0a8e3c219cc1068e84d14c9c440", "MS1": "0f76ce3b91d1f2323a24b94bb9bb6179efade3d2d59c6c5a60b9e2fe92816157", "CLIENT_SECRET": "0416e4d82b741774cc73ebb9d0bffa86a37fba0296e6f3b9665821b0fcaa9c9ac120c87a9865a9021a5912f8cc99ef5a368c98bcbdbfb6d28a6346439910f4da23"}, {"TimeValue": 1437055597, "SS1": "18b96d96ee29a31e286c56fc862092d8275532591d22f399420b7e93b883534607e7b4a15719afe11c4ced83486769f54653debc48217abc63ef49d9f6ed5a7c1855f22b0d46e5084dd637ae10448032519a74e034c84fa234e92bb84e64f14a0e37ea604090a868806549f02b419071e7b60eff982c954c7ac04aca04c1ad4c", "SS2": "026e4a7e30f38249355cd1c8db7d4759ad1886080c8e18245d5a9508e5c8abde01a2115f1b922bb1658808ad9ac27b67641f925c3d076dbbb263108764caf9b9202b68c024f5ae3220ab62fff5cb36a349033df1f49d3c11102f1f006bf1c4560b4286566ad1e4afcb05502267ba07fd1e52a2c100764339ceaf6b24c3f7c925", "DATE": 16632, "PIN2": 466, "PIN1": 467, "SERVER_SECRET": "1dba55e5a7a3a8d4c91c9448b4d232975e5b8f31070266d1f5321005e15cc2ad009d3a3d7f28283aa8e712c45357d2782ec4900200460a8e3f01a1b9abc3413016354e6c799dd03116c79030f68f11f1d5baf6a1d07c755834812a3a9b901cb01bf42c650687056b69eca4e7b57951e5dcb5aabc5d8f7b8f0d49250914d1199e", "SEC": "041d218bd24eb9579123f6d07e83883b1378dbb03734c58e4f7df1c9363e91f53720fe867f87b6a780920d1f6ec69ef7cc16e0d458dd5c459673d63918955b81ac", "TP2": "040aab950183b7f6487d0332fccb40876612e1c801a27e7c87806e867e0e85be2220cfaac2e15e825e6c356464e155a06e94f00974acd787f8c7fc222425dbd1a8", "TP1": "040a0aee66c9de0fdd973f72b16bfeb72f8346220a910d9a71918ee8db898e97771b8ded862e22f0141e2d7594ad41d2e55c43fe3fdcb6de7b2b0c32f1cfcb2174", "CS1": "0419f5d2771dbbf7c79d10752c93db37fb09350891a6fe667831ce63fd698e0ab40d669b11ff77856f8bc7d96b88ed0028a4d3d527445c8f07f32dcd9b2549dc6f", "CS2": "0422a995d2a64a6ad1cced9cc7e4bd20f6c6d7d61f4a41a4132973497cdf6004a4104860d08c39c23b2a7cca964f70f55c7b2034dd55d38df42f095648cc1c33d3", "HASH_MPIN_ID_HEX": "4c1429594d9772eeced099f952363dbf8fc161a2be35cabb111569f2f390a6b8", "TIME_PERMIT": "0402df09a420097545faa889263ee675f05563a050facbdd255b5dbd9c49616e9023645ed35f5b8ed988732bd740f39baa9060ba049780428a3299f6e06621f330", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20226631376362363036616561323735623530333938343539636431346264356666406365727469766f782e636f6d222c202273616c74223a202265346632353365316361343862623564227d", "TOKEN": "042071b8f32de9cddd1b7db263f4ced8a4b8b33bcab23f5c4925b25f45e29f34c319c8a73d8bd70416b877dbe92fe0a8281cd6b9a1cb408300cd493180abda0023", "U": "04069230a15b61e1e22deafcd5272d89984bfbe4f879b76006c1dcfdcae822a42013942efa5b9fe8cd6f4222c1ad24a78fe5214946ab3eb3a65906c3e5666d11e1", "SERVER_OUTPUT": -19, "Y": "1e753a6ca0543d90fb8bca13244cdf7839b3e8775774de54ac8aab4d8e628ada", "X": "09d9bb027338d4ffbdd461c845325387ddd0dcae9cdc8e73cb2f04d501986b55", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"f17cb606aea275b50398459cd14bd5ff@certivox.com\", \"salt\": \"e4f253e1ca48bb5d\"}", "test_no": 171, "UT": "040e5f0dd133f997a7095c4cf3c844a1ac01223d9f7009d42d6191db2f162799221e82b81e248657aed55f6528c35994fdffd27dc8243eabf13990e7355ab16f9a", "MS2": "0911e408e476b00151d69bc78a6ce105cc364d5a39abd38367ae8fad0b4c4b00", "MS1": "169f68cdf48ae7d5b762222d379292881b05ffda9939fc1131b22e4071419e64", "CLIENT_SECRET": "040d732b8ac866a744e54ddb323c877515e064f990ff4893f8534b7ad6ec7835ef12a646120d57187b47ca514296055ae48f450ae6649d160f6bba4a00f4692780"}, {"TimeValue": 1437055597, "SS1": "05cb948c2729e3ec1487afce2d65dcaad42f2ae1c051d46424403e82bc7502401d82ed107fcaef5ee3e8eef4bedd53404c3f715d6aacee02122aa53f0dc364a622032cb07d43a70a7e6408222e7fc69ca1c8570e4eb57f03209b1bf3df8ffe5c18ad1a9342246333b045a8e13745499d363c3f4092a79e9d6fac266803810015", "SS2": "02de229a71cdff69f572fed01de00fb082d5298aad078ba71db1009ed301f66a0cfccd8e0b4794811e5e59c5788e6a195ea4cd8f82c4fb61b039d1a66db07ada051abaca65864feb6b8cd6974b327ef44e08c24080492363bf4a9152a23f1ccb032c447ee69001f8c8cd3f629b77ce2201be0254f68f436f4b156702ecfbbe4f", "DATE": 16632, "PIN2": 4390, "PIN1": 4391, "SERVER_SECRET": "1c181903337e25150d0d7f0f476e711f3e0a68f9f0ddad83df4435cb8be5236618c944d9a2e87e9892e3da8a18ca3e129272d6c2ed027b9ec7d9666b78cb9f9d193291118afce7649f8019231b1c7ef9b5ad61642dce15091a640c2ea93cfa0c0615b351b92064044c38ef6fa9bea8e6e5ccd29fc0ebb951e15d66707dc6a5c4", "SEC": "040ca2301eb7d56f02a7a92bbbef1b4752e1210ecd05a13a72edd28a825f9e07e309605d53e9958801576f2bceeb99ed3e8afd300ea06c1e013d516607f0173662", "TP2": "04193b120c35f475cbbe4c27d153b7aa7b8077dcc67df7c018807bd58cc818564112e2c2294c337c32af81117a9a59875c9b44da637ce048e11ba8d6e9c813d93a", "TP1": "0408317944143e6d66302fb64d1e8d0f00c1c812181f3e18825a949e8dc04d18af140d3b6f4b0f2dcd79305951b8531522f05d82546d3699a87d5d486f80f93074", "CS1": "041a3a82dbff50495b62a9a8e1bd76526d9baf18e6f0f4cecbcfa7fe4155b6005c0fb14f0c449360e2c36f4d8c214e48124eeccdb9bcddca66df2a79a1c715e2f9", "CS2": "0408b0c78afa91e7ddfee0ac7bb9140531f67e201853d831c8db23da826485c7442033e073f6b9ca5744ca1669b63435a8a2ed975e485753f455d6ebe167aa3d0b", "HASH_MPIN_ID_HEX": "c86cbc977ce747df9f5fb16c9be01f35160a726a0717afa407f5d5569e2ee00f", "TIME_PERMIT": "040b77ddd29e654ae2d83942162640fa8f191763573b94573a518f8ed65b6f6be2073d3743e9bce459c4d6c79b1742c1dd8eac59464a9729ffa094cdcbedc36a0c", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223938656637663438626239643434333162666639623034643739363865646634406365727469766f782e636f6d222c202273616c74223a202237646164306635343364333537613461227d", "TOKEN": "04122b0a97869d5eea2a9547c3a91e3d0db2febe73bd12fa20c05f28d1b4909b9c0e6bd814d2411052ce2aa632bee3d367bcf62d59f4bfce64519f77fabc5363eb", "U": "0401a0fe79635985afa5c396c1e202f71284c35cbe2d02329210b808d0edda767b0505bb93a3daa549f3eaac4869da993d01fc5908dd7b97b974f417fd1d2f8e22", "SERVER_OUTPUT": -19, "Y": "11d8872a7a3023329d4745fefb2e3ed1237599d8cef758fe99d5df42841ea873", "X": "14bb7d01c7e38e0089c10c0acac082cec3c305635cd6e8abee9a1a2401a52303", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"98ef7f48bb9d4431bff9b04d7968edf4@certivox.com\", \"salt\": \"7dad0f543d357a4a\"}", "test_no": 172, "UT": "0420941f3a742ce8bdf4e6e1573e6a020041b1a996fdbc30ab1da9bea6e290ce2a018d6f61bc4d4b17ea7675fef61d926b110250f33241a936cb7037dbd1ed50a1", "MS2": "13caacfbe7fcfb1a06ba1a5e1289ee4e6a923a487d3a9667944e79f03b414e83", "MS1": "0666103858e9f931881b472ba871001c1528e2dfb4aa9668dd79a88c9fc3232b", "CLIENT_SECRET": "040d53b3288732758cbc99ab5913f7e10dc65f314acee873506ea73ba859f9bef11cc1ecf923f128939f5a2d956dda7cbbfecbd434f8c87f450133921ba70db347"}, {"TimeValue": 1437055597, "SS1": "0583fcfaa25d486011bbf117da1d8b798cd6624bee8bff2c692e15da11c0128205f0352a26a5546a2f86b2912c19302c8ab9e81acf9aba0d29eb63bb93e21f24173f25755ba9e95d6c39b088c5251a7ef4df58ba3df35feddef51c1e2c3cf166057cebef9aa1a4ca076ee810cffd9b158adafbfa45ad890023c823e1e3b343c8", "SS2": "0ed7aa021c2b0713fa9333a40d56911c9e4a06769ca4811698a15fae05d8ba2a0233e99413fac25c0f614123167839c9eef4d414b7442c0420d1dbabdaf1fb730ec960ac279fe379a709a55aab3856779c4ec90e621305a04c88d3feb69a05b106ce9998217cdb24fec335b062f441aaa57aaa98f4e6293bc8188e3df33675dc", "DATE": 16632, "PIN2": 8304, "PIN1": 8305, "SERVER_SECRET": "1bad0e12e1f054456540209ccc2acf9261802a7aed6e4aac9dd16a247db26bc317629c39103fb2b3fca522bc4cbc6059e6c2d2963bbc7619c97b9250495e884c14763383e30081045e081340c2bc8fba72430e295439a4e256e56539e1276f3a0344e45f7d8fcad7449a3cb6b549396087fbba0c6ac9692ef9b3e268889c4d63", "SEC": "0401e7f1c8c51a45892bf1de919dbcc5e5a786b86b78c4b33c4290176bfe6ec82f1420416eee6714f144d6e9ad627bef93662b057a92bfcdd4ab91a5a6f81fec54", "TP2": "041b0160040497ba77aca59aaba1b49d0354284999b1cb6787cb264d28069787101378aa980811bdee39ee6ec10ba371b8c52c0fdb007e75f9a96e1d9c1e87e798", "TP1": "040ee058a80959851ec85cf6ea599bdab983f9cf6e551e32caf5fd0448dd13cb5d1337b2a0d1d282dc9190715f4f6b7eaa021c110424df483b61ee3dea3c46a76a", "CS1": "040203187750ea0722e82072fbabc11bcab74bc1fa6266682f9b05ec6c311950462170829667d6106130028101b102742348a8f387df4e3e42e155c984c028c931", "CS2": "0407a205c837db0d2f19ed0eeb900f873488e513872da5ee3668e46b2e4b3bd3d823a766266138237844a4c0ca526e1f307b38b913617dfdb12dd280ea77199f9b", "HASH_MPIN_ID_HEX": "2d225c96dc711a358c2a158a41305090cb747ef84a0bc7037bfc4437b239523f", "TIME_PERMIT": "041db5649423feeef6d0f7641fc8644613379a35ec30e4f88929373cb2a32a16080cc5fbfe945f6c47368bef4ae0ce887e17782002b38afdc1d96454bf3a1157e5", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223161373366666164333532646334383563636138633865363131353034636432406365727469766f782e636f6d222c202273616c74223a202230613366313639366131643664393636227d", "TOKEN": "041b4318dd16dacb7154524b64a5cb040e4196ac24897110c96ba5d76996885c1e1ce061d669ae09d3c1e0596d5c212380d443fe0da34938b9cf89d906bfda3e8e", "U": "0406a627d713cc4eacd44826034b38cdf9d6d05d8149c423cf2dc749acfe84795812d28e58bad1e1681c9edbcca07648a793d4b9f16e07529f0d97cad9103170e0", "SERVER_OUTPUT": -19, "Y": "04608a3bf4919cf226dcc1a95f96094c948978df3ab3186a0931c665b2c8f9fb", "X": "1992797c465f3a734479bad8a1aa9aeb31e05ec288ae8318d447e0d374581dcb", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"1a73ffad352dc485cca8c8e611504cd2@certivox.com\", \"salt\": \"0a3f1696a1d6d966\"}", "test_no": 173, "UT": "041f30c94bc0d721a5526cb15dafebd8561203ba0d3686cb9b79230b460737ea3b121e3ea4d2af78369e8da941001d0ffda71e16c1b4027e9341e5b899bcd9f8e5", "MS2": "039532ad512c405be8932660d128c50fab9e711038f009a92e33cd3f3c55b1a8", "MS1": "1d7ccf412535a9b558cdc897aa59bbb3000a10fd96741e1c054458bfda67abdc", "CLIENT_SECRET": "0409fb572c9e30bdd95c2b16a2cf3f31f69d38192f1180ee82d5c50e0c6165c83c0d5ccefb18ca02bf9200fe0b3650f1ca75b02dc8f0e5e60647255ae78ac73fae"}, {"TimeValue": 1437055597, "SS1": "21bdcf464326555976fa2ed7c5b4f203a3f3b56f3fc29283c538ef08e7a2fa2718f322e888bf79cd575f16e1267e8b2bbe38af18c675b9ac6e1d4102f88f656a148361b7e3d52ef4e0c990ae26a623e149e5a002655711ea9dbcd0651e1c8c09042cfe0126ed79658ec08977d387e49aefcb43bceb0243cfb6783d00e1faf6e9", "SS2": "125c7c40a4c987a1ee42e557f08dde67ea71ff71b119556526ea5aad029b5b40191f50655ee1e232abbe52193dd82a56ae779355558c2ace4d119aeef42de3a52257801ac43da748eb4f761001ab2f0ee222e3e1f63a47f0893ace415d4a44841f658f607049b269993fc845130afbdfaac09d5104fda858f1174c8d9507c3ab", "DATE": 16632, "PIN2": 8347, "PIN1": 8348, "SERVER_SECRET": "15bbd91d3595368c27959687e80ddee6868d88269703b1869b4dc6ba9853e0700bc640bf4432f9b1b7e2261d7141a32a3535a7f10cfed792241d01e4750ee11f16facc821dacc310ccb02d65adf09e72acb84b8d6be154da854edc93bc55781809246087119988c7692580043ba93d442c76de8766371179868b3741d9349d84", "SEC": "0403d07ded21f22481028e70496c5febadbd82790631bf5e6a6e6ae4f46b01a5dc216bbb947cd9b66545ab03e55a9b54bea2164164ebe604becb7d68c1289432cf", "TP2": "0408453b55aa273b38886cfadcdb6bedd8f7c61ccd6bbcd28c18772fa9a760dad50e01e807b7ba2347d921cb176a46dd63380884695fea8069831c8b873dbe3fbb", "TP1": "040931734ce22ce07da1b4a0b9d1d396d1975af8a2730d0b93cfd488a55899e5a6005ade89d87f6340144aa52853575a583c086523d4daac9289c8b15097104bf8", "CS1": "041cab4cb614395937d1fbf2ab2eed23b4f24b0dc78300b38042186d7f604ffb38001798caaf56b22d03ce2c728c96083ac83b1ddc5ed316b3525db292a3889bfd", "CS2": "040a19ef1ac5373550c4bc62561e7ed61d4b781bca40f69887bde0f7e8287bc06f11369b2baa4ca64db80ce1065bcbeb582ca5cdcf5a971ebacaff1684309158c3", "HASH_MPIN_ID_HEX": "0af5c7064c43ef069a2f3d52c5495b83b428adb2b7f956024510181001e4f2e2", "TIME_PERMIT": "0420081725c2cba24c39afe02bf0ca833428c8dbdb00b1facc7669fa916bcf29e20ea3ab88bab52d1603f581a2a78979449a7d7a550ab92318d4efbe62a74c4ce6", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223433363334326664326531303932383639343866656162323932353730613765406365727469766f782e636f6d222c202273616c74223a202236313732366531666139396637323465227d", "TOKEN": "040549cbb33ba917d218709092eb2137906a0005051a31e0d1a1266babed06f5eb1ca3d71c90c900310efa2edf6b7eef2bf39aa4667724d7996b858e36ca2433d2", "U": "0402ded680fcace6f352e7aa126cd5de23d0c5f61a09b0de175fecd729348037fe0661ff181e4257f3d52be53eeaec822bdd38380c877c8db7c3d0f6f5e2f9aa74", "SERVER_OUTPUT": -19, "Y": "204a64ffa1a40c6fa097abe6fede16f708bbe629974a5167a105b5b9740119b6", "X": "05ef5cd5011b92e77941719f75ed8c9ddbf3f5de1aa9571fc417a3fb3f9ef3af", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"436342fd2e109286948feab292570a7e@certivox.com\", \"salt\": \"61726e1fa99f724e\"}", "test_no": 174, "UT": "040b0127a21354063530f875bb51c6fdc2351cb62bf0bed26a9872bbec4a9dae2b0413783e919cb13590e9115a8e329249850dd7f0b5d753e7f92e704085ac8168", "MS2": "1541ffc1a40138ab8aeffd963ec052cd350d9f6094e113af2ca061a0762c1feb", "MS1": "17aa4cb6564ea061f84299749b9989adcee6250f979994b876870ee9b6d8d5d7", "CLIENT_SECRET": "040f5fcb875db7199506f8e38ca32f3c5e31265b5476a2c26994b51309421f715b11f54d7529560a7518975587b77f9c345ecfbe41fb7a87732da0876ff4d6c5d2"}, {"TimeValue": 1437055597, "SS1": "129911c60d1688b81b56bcaca6ef8fcbf2e05efc153de97bbf565c9ea0ddcfc71fc0857c0e00e300ee3e922911097df1f9910934225dc98d3ed007bdf56f982614a75328074b53eed527cbf2c0089a30f867cdd0d9b8e4429719d8b46abf30c3221580974c3849b8879e6f47545a3a2b05331e38ed901b6c10c9bf19434c5d7e", "SS2": "233b92eeef2329ba4d7f1dd205af5d4568b94aa7e207ddba6b1bf1a035b5079005e4ac48ff9503b34464233172c6da2b9ff4edb34fd7df2ccb0410f70e23e8f91910135d078f203eb42c6d2a4b0c59f6a3e979658e7140a56f753e531925ba1a0e08064590875c2c694715c7053467da258c9b458265536d6d37d125f3605d31", "DATE": 16632, "PIN2": 7101, "PIN1": 7102, "SERVER_SECRET": "165274865f82f94f6aa987a02b5f32fd86467fb68f46c6090ffc0f2b9b51ef6802108996ce459ec80d9cf5f966924067c657f2b069fb2d44c906cc2eebb714ec0e1dd81a868bbee12adbe61b28e7128263307f5fc0baca0a991bad5769094f1923d6124f92f10df4deb25bd8181a8e78bf37f2469fa1784fa3be608ea3cad517", "SEC": "04233a8b437e34a1d756a970277cf0f16d7c159fbc8f7924c1c1d00bfd049e8eb318f2490a52ad8313032d76016bf51fc71d966097c4c87a49d65716dbb9799a5d", "TP2": "04060c66e5d956f527640a9d3392c2362ad2ded104af97a5abf5fe0ea252c70ebc21cdbb5156683f203b9870fed532023846c7495746cac3b7673d59c9a4f1417d", "TP1": "0412a10b601f306ec5e710ff8698eecc22f06c664435df2d045abf9be0508b042c1baa61d79f0cdfe8fef10d112553c6b9892201ebc1ec97abee1addb30f83d41a", "CS1": "0414292a044162ea556504536896659f8a8b008721dbb415dc963018ec71297ded0394f22200b0ebb4feba0ce8c05882adee5da8694f47c1d044257d02f78c5461", "CS2": "0423793e3002df68e9e7283baece6210da7fed8d110cbf7762ef2f2b4d1459b0d70def95cf2210b46dfac6af5e01bd4acd01976fb280484230b28ec89d18b61aa4", "HASH_MPIN_ID_HEX": "c916a8db3e1a247f9dc99f78fef9b88761a17ae3061cdeb76fffecddbf6a820f", "TIME_PERMIT": "0400cddb8d60dd8d0afdd28592ce9e89b9ab3c6b6f5d58de3577868eca16366c2207999d2fc6bbb1c22edae2b42f446ffa12157e6ad5d5c0a90c705e486419c9dc", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223235323536643465323038643933316534376532393062326533633331373566406365727469766f782e636f6d222c202273616c74223a202264316565326531363261663330356532227d", "TOKEN": "040bdb5758e86f0a8502a7ae47dc4af4fdcbf0c65d4411b8df760c6a0e3f9d085209e3bfa410f08b22053e5c7d5c2f34e0aedff699bae70317d0ccc6c72ce55a6b", "U": "0409fb3e7eba58edf241e5487cb19da82b13b5b39ca5117309f689cb3433275a0702d1b0b22a9b87004482e1809203e2b163877d6a1da5fedc35f6d3e1b3f496af", "SERVER_OUTPUT": -19, "Y": "006589194b2124b246efa3eb7118d62fbc8b5b22013b564e7285ce54cecd728d", "X": "167ecbd7a4b557f2ac7f5f68cbcd9e0a637a828ecc643a6adf9b94079bec3bcf", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"25256d4e208d931e47e290b2e3c3175f@certivox.com\", \"salt\": \"d1ee2e162af305e2\"}", "test_no": 175, "UT": "040cfacc5e139ef0d0915c5326fcc4445b7fa29753f982f1133de6d2201d1252081ba2f24ef970cc572e95ff88d732be4ea9c9330c7d4d319f92eb0820e81ec8bf", "MS2": "059101b1f5659a3ea1d3a9b0e6e05ee638f5810df84410c90f6d75dc661c8663", "MS1": "03a2eb62b0fc77c8f04a53614249f171205750e0524de9abc31a902b370ed17b", "CLIENT_SECRET": "0400b0145d1895d9b6705defdcef1132afda17aa9c0fcdbc62a1213c1ff6858d4f1b82c4e9e2e437c2d40faccfb5de669262c47fd1acf93e1b65a88a397792f320"}, {"TimeValue": 1437055597, "SS1": "0e449e07e715acee46352f8ae8ed8bcae481421f9fd9700f5fb37dc0a3efeedc14869dd2dcc301b56babe9f4d10bcab30b3f943351e1a631be26e0ae42617e0b07d4d9b6ad9e2e23f705794fa5cd72d6e78cc67d2ebb7c6f72381bd2f0e4ce5d1e02d457d83c61f89f78de8ba9ab44899cb5a5e26cbfcadb91bf4a29f81ed4dd", "SS2": "218281d81996005c20480c0421840e63456151098ae4c1b562d5b299d938be4d113249f8ac726a4d61bb78b14fe639278b3a62bf78ea66eb8f59f0051205cddf1e45d9a2f1e2889744d0ee66f84de90e31c46cd7d49ff4ae88fb3e5808414ef107d8cb52e59f1998013b399f7a0e0a00356a3e4b72937a8a871eea3eac836b91", "DATE": 16632, "PIN2": 1499, "PIN1": 1500, "SERVER_SECRET": "1d7fd7118ef4ea295693d36872f956d58d80921e7adfcc7c1d264c9b1d03ee9e0d80f8e89bf223db5a1595538e56e1eef5ebac0a76073ca9f363e89dbbbefe53209b79870e64b45bb8aa643fa6f88378d6e6bbe506802c8b5388d9ecd74afd9e001f38463cf25910f09550850c6d631d1d6af324c6a78a73940ae5435d094896", "SEC": "041e7a42098e9767f05086e28e1d1e8df5e2aa120562063caf6ea1dec4b8196bc31d6756c553c2ddaa58d5a8a612d6ba48bf88673cb454e61238a46c8fd37fd69d", "TP2": "041b19d5f00dbcac5f84507d72bc4450559e21e87a9be138de4f1bdc4e797d1bfc115ace3c4034d05c10c22d27d08dbd9306900e515c8d77897aec5de2feecc5b1", "TP1": "041f4e3c45d92bf9602e49a8afaea02dc07cc822ee9bedd36dd028ced0494f26890558cf4a05b3182165aed289b3088eddc74bc9792335847ac0d77a204bdedd84", "CS1": "0402826a435d3e0683a9b0ef977bba352ba14722038cd9770d81bb3bacfc6c737700ce2d5f027ad07fb4c779c3cc56f4453df51bce0473e23b243d249c145b27bd", "CS2": "040eb4a3f5dcb05b11cc1f23136563568b923079edb3282941f5b72bfe78ff62261b3f6a337d0cff475f530ed4176a063b5495b3e2b2c213e375debe7603905b15", "HASH_MPIN_ID_HEX": "7e396c0d6f712dc9bc33bc39796a53552e3d94fadb3a4ba56d0ebbf02bcade76", "TIME_PERMIT": "0408f0a26893147d2c746157c3936729bf0e5c95594beb70d75088f1e3e151efe31a205bb73c9b2a0a99c6236013998764410f9cf033c7b0e2581a4ccb60362b71", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223664383364333130643965366433656561326566623938306335616234353230406365727469766f782e636f6d222c202273616c74223a202265373132623462633332653731313336227d", "TOKEN": "040f610ed9e3d0029fcd4a7c9936eaefec4bfac1ddf891c610413a0af1758de28e17b3b9ef6684b15424bc771e066e595795d4d2a75ffcfb472d61d025cd87a051", "U": "0420ee098bfdc69ff5cbbbb0cd168acc563a19dfc608dd68f41f823f89bd77b83f0dac459d0d4d95b066efda07c59e661d42a73151c89a6941511efc16c887432d", "SERVER_OUTPUT": -19, "Y": "23feb9ec1cc8ec4c41cd2b4173dc4c6397ca4a62d5faef5328e894b50c831163", "X": "21b9f658565376d6811395fd0b384ea32b378353aa3b50cb8a1685275529adb0", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"6d83d310d9e6d3eea2efb980c5ab4520@certivox.com\", \"salt\": \"e712b4bc32e71136\"}", "test_no": 176, "UT": "040e5778060be1feddcfc2422ac1136852178accfdba4c5f10ed5888d249b083df086d57538ac489f35459c3e3016ea1fd8382a80745f5afe8f80480cb53bbf86c", "MS2": "150d85f81cd38f48870b8547a8ca275e40b2c0ff906ebb392456bf9e65bbbe75", "MS1": "0a4307cbb4e9a30d50a6f6055db89a3b05eda54ce5de7d2eab9cbceb820a2aaa", "CLIENT_SECRET": "04104ed91c3ee99bd2cfa95cd621d799d2c89a1d967dc8806beeefd6b4bc280125071d45f4867b6461ed16b8be41edfb4fdefbebf87c79d8fd7ccf811cbdd3cf56"}, {"TimeValue": 1437055597, "SS1": "102cd06fab632e2704c06610148cd5ff66a9d9ccbc388dde73f1981c32dfc09c0116cda5421ab0c058ba1f08d41089d1652f99eced2aea31b9e93c6ec4ff98b90f127e93d8631136aa2e1a748a6a690c72525f0edaf41608b6d7c402384394c001f14ec72525fde157fc003cce77e930abc504fdead86915b4c5f13053bd297e", "SS2": "026ebff0848602f45bf94d7fd10e676a08b2bfef8d64e9a05393754f59db32de02273e8c045bf8580fcb2c2da4b77dcba5d1a4e1ca88f108059b2b30c9dc387212cba8c705512b599d3a59187f828aac05fdf36826fd87ca10e1ea03a7951b4313fd34bb0f00651727f116abdde2172116a8f66d0775cb630a816026005c6daf", "DATE": 16632, "PIN2": 3235, "PIN1": 3236, "SERVER_SECRET": "011a9b5c30fea6e43bb1f19f09b20a69f7ce1785537663d9251167e54e9384a2033c8faa896261d9baf7d1bcfb85c04a843c0c2046248dfc53ac7fd3f4f6b39008b4b9e4a4d20878d708dc86792c67ab9c5a99fe9ca7d9ad03eb6f717704cd970ffe9e26cc77bd1152703798c9d0bc8351c00034bb9fc805bc18debb354d99e7", "SEC": "0415d28925fb6cc8d8c337dd1e3fb2dfe943681313a0c9ba664e8ecb2d1df31b260c255be26013320931f8ca995cac070c082a67287be84db5f0170f4d34e93680", "TP2": "040e0268167492a7f376e6cdf566f9577d6ab3a260e1737bdd4fa8606a44273ace15e27db846e0195bb7316ea25debfaab4491f8f95d16c05b39fbaae2526d12a3", "TP1": "041f51305912b9d150466c0392e0761e8cea0028604b81e44c93badabc003fcbc917c71593a2114180343e31f7d63d0cc337e234f787ad98e08df482027c320e83", "CS1": "04229817df41ef060e3e4ad5e710b82635ef713d1f42f10be6f630ab4ca124a8040ee72dee1e81cf7e357877609e10d42aaeb3f4fe142003374ea9c8d91ea8758f", "CS2": "0410d34c44e7ad32ed2c1bdb81b2ad1235c464e1fcc8c1e3e4b3b6980c771f62700a474202ef4f83532e8d99c7a31d64620a9fb5a7bbce89d478d18cdb2a3afb1d", "HASH_MPIN_ID_HEX": "ef24052188b1eb7d1b43d8bc048f2b1ec5f42df7f4b03b3c3f295fdfc2b93b3c", "TIME_PERMIT": "040d644974c898c23dfbcd4dd2599508e06828ec645491749ea114922ba306fcd1166090212be75f9c4513e254c7d218f1d44665641332780c0db41ce063bc2085", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223535386161333266353966393435643063343861376164656335613563633333406365727469766f782e636f6d222c202273616c74223a202237623866373266343761353235303739227d", "TOKEN": "0405e8339ef6ec823a8031de44209756af9c4ac5a9979fa417bf089fda22680daf20b62d2000d5c22fe2f6d944b3fe830def8b515e65116e3475509441d40945e4", "U": "040b44459373d88d851e5b420d9eec6904f2ca8f328f1787766b9c117827ae565a1e125172b5e9ea00b0bd4ff677157418819b8fa3b4f7198fde37ef7b142b7967", "SERVER_OUTPUT": -19, "Y": "1562f2062eaf1e36ff799d4a8a185f78bb1f8808c60f359b394b6792db441910", "X": "0c166f836ac2c0be56ba5bfb561ce1bf512563401b5cca69088d969d7ce1a42f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"558aa32f59f945d0c48a7adec5a5cc33@certivox.com\", \"salt\": \"7b8f72f47a525079\"}", "test_no": 177, "UT": "0421e4d9f2dabf7ae913dde1a3062883fe0742789094685ec69e08a99f31303a901072d65680a9a2ee67297221a022f78a9fe4999890eb90b04d1aae180f5ac7fe", "MS2": "108c6578e5979f92e61e72e0efb5ae0eb0af37e2fe0cb4065dac6a19d90b5f0e", "MS1": "1cc0a81d94b2a757c93baa12aebf54bf4ccb8163c9b8fc2bda03a2bb26784e94", "CLIENT_SECRET": "0404c20dcbf5617f726b5c6a13cf266684aa924afe01d604d27ff1eb360510d6c019394182dd805ccbb948a39c365d54df9ad991aa40611ce6c762eb21d29933a2"}, {"TimeValue": 1437055597, "SS1": "1df0099b68130528d8c1f173b9c87799ce44642742bb5a13747d439aa425adc01dc07202fb7bf8c35f08883e936139eef3fbfdefa6d6535c56dbbb2541e9d2aa0e1f6834e9ca202b444115b422b1603d362dee3e31f6318cbb9977a6c4110239137a263994e1ecf5c69dfa6dde2748934282a6c4d74e894511ecaf52acccce36", "SS2": "0f582047e37d392520b6cd2a2d6391d39f1809c0330b9d4959de0f2369ec9bb1231d06f748d8a32944373a5ca6943357902e6c99acdae50058f5c15fca4836780f15a0285100e80669a9055a7fc365c8c0bc681b0a25db460d1e44e50163f99307ad47ef74ea9057d246e8b5ce38e7d9df4a8db03e11ab9f5fd262dbe7050ad2", "DATE": 16632, "PIN2": 2361, "PIN1": 2362, "SERVER_SECRET": "0942f98f5c9988bb70aeffeafa117e4bb37b07444709047b64095b190322196523ca3502261afb3bc473d5c3ae6efe9aa30df55c2c4390971a051472f096a90014a7d10447585c6937dc65daee5ffe5178056cfeaa08b07edd08c3e107958dc803d39659d62637862f2ca6bafd715dc35a4e4ecf6140ea5b1b588fa0252c1563", "SEC": "0423704019ea154c4fa4a678952459fd4e70149e45826b6c4621c3dea1c9cdfc4d15826b931c5515dd8eb9d4adf29c9ae12300813cdf907d6412b60c3c191a7140", "TP2": "04118ba834dad9f02f75179916ba167f8a4067f706b3a1aa46f8d0e6b7c43f1a001c63087620308ebd170778519a9c44386e8827fbae27aeb483c6885e153c9c38", "TP1": "0404a91c07116fadd1160369b0c11bb516fc0c6b27611d798c5a90e21499274bde1a52c352a864d57b68f02436e69a45c2d6a75dd4ffa2b0e4d7a6a92ce793d89a", "CS1": "041208f597dafb7513804cc847724c43ebfba987b29b982f2216cd7dd8d60bda7d0c185d2616c2c014011c148cac43d6a8bb30630150b110984c9249e1775ac4cb", "CS2": "0419c82f6d29fb6dfd8efe3f8090cd963638e7d4402b2cd96dacbd637c1e3c224614c0fc593f240f4c2c7552032f2f75a153c4486beef0985f80fe7714ccad4be5", "HASH_MPIN_ID_HEX": "614c02c83083b3ac37bf50980827eaeb838347d1869a305fc397073abb6299cf", "TIME_PERMIT": "040a32250286a631f9103e0701d5cb19e6af179cd2a645a4e5f190d8fda045577c0fa1d6d404ec9cc6e588d997e427bc06a4b901d67f7014c93c8a24131232990f", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20226562643931313530623239326633616439663834303037333863656564343738406365727469766f782e636f6d222c202273616c74223a202232636631656565356330623332306336227d", "TOKEN": "0420ae9c6a1ff4fcd7d84feb1bf68b59601ac712b5eed1ca892785263e32a5c96819607f8817b2c7457fb3a4b6156729623d3d6966176888a26c359e1ecd84ad5e", "U": "04231522de2f1acdc759d9f654f639730f3e1855599e648399b4778336d25769c12377bbf5f41689d77a5cb2e70abd9cda168ee559e8cb4e3960b8835de0cd8480", "SERVER_OUTPUT": -19, "Y": "135a457fca91fdce9ebec016d50524b38a2f00272fc631d5bc23fbe78a805e54", "X": "14ac8ecb24abcb66468bb894ee4c71c47e9775d8e08e1433f43667a799929af6", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"ebd91150b292f3ad9f8400738ceed478@certivox.com\", \"salt\": \"2cf1eee5c0b320c6\"}", "test_no": 178, "UT": "0419d48c4f607f45b06001a0de2013d123cdc5a2dd89a6fbcc76083056e3030f33188ec7427ce26ecf4321f81ebbaa49cc5008230ad7c1861f1fd788bf6c490d26", "MS2": "18a9fe1d8ebf202dd8784f9fce0ea4fc287d1865afbf20b7fd69ce52a00c6416", "MS1": "13ae2763c03ecc505c3bd1ea90b1ab62af7f58f1a61bec8ad4bca24642424bd9", "CLIENT_SECRET": "040089388290d433f2aee155a8026909033e1239de0ea699a3889173ae63d26a0709361cc49cb4fb3c6d91d1d196dfc66b9ed1a5dfc57500c20643d5722791a86b"}, {"TimeValue": 1437055597, "SS1": "032aaa10b5cc95ebe464d7445b9716507f9ec41a1c1814c0cc945521e35a2d65042cfab806276480401cc46a850a7a946b519116cef3b2e3e291300f960f3a1b08f70cf4d6f0c03b27cc30f73b743c6229406c41ab664788fb3510acf0d3782d0e979b37dffda3719bfa04a1ad86e7eb02029a28a113657806d7f3bb77c6c19c", "SS2": "05603e781f2f3e3e9b8016a0518a4de0b939cdf285c2d4890787ef2e15db55ac108166b29d7e8689608f0be64555e198cdb4875aaf2bd80ec0f2bb4102e407ab0ca5d747954d1411815430caf18bab2ba68fea03c89e3e65bb58e3f7911c9749073a7d67bf6178a22209795f414de225f714566c40ebf13d55bf78b271bdd1d3", "DATE": 16632, "PIN2": 3732, "PIN1": 3733, "SERVER_SECRET": "071229b134b88c37238526a0cfa0a343a01a966f7c44b73b9eea7c41167fdcae1430aab791404202ccf30f21b4723b1314033d2d92061357b52a696e0d8b8fee17ac462532fed1885c3624958acc18a3189d53ffa69d4efa84a0958d1cde21441055124913cc8787d9a3ed6794a218b8c79ca321f0e65b970644a775078a0fbe", "SEC": "04096cd7750cbbec6bc358d3d1c93d1ba4057b9d6cb5ae44d8f9fc9e9394d23c1f11a2e12fd6435f66714eee5ac927b6877cac01ddd4280540b79e251d158ed1ad", "TP2": "0420e047fa492b8a636be878aa994cc96f14f3d3fd49d3c5b8d59a51c850a5aa322154ffd94444fa91a3c01b66cae6c52ad3b3915b7bff9b6910f52f60c0ece4ff", "TP1": "0405bec4e695256af17258cbabd6730fd5a40e3d831cc2d2e749c54ad15de9f8e213eebe78b6e130d5465995acebba7bc4cce451a6788e110ecde27e92889c9dc2", "CS1": "0408055d73b45a1252b9ac85e1d9a3743d70b2a6cc1a9baad92bc200d123cfc7451497485b52955595157854916c35bdde524a685624740dbb48ee0984bc9aeae8", "CS2": "041d9e4da83148611bbe8e6cb8ba441519ad5d02427677913d3a65041f1f4d64e109437368fff97eb189567722649d8ab48cd179206690fcbae6fae6fede97a91a", "HASH_MPIN_ID_HEX": "a4968fe75a0d90437f6cd8b63eb6d6a0f25913fca6f83902a9ecda741a54ea60", "TIME_PERMIT": "04036035079c1d43ef1f29da30b7046c5f027966ed36e9ffba45a36e518f73f16b0b89a9a28e6c4d57340228c0dd1f99f483a0122e6da047b069775d2b842076f5", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223136346237313766333532303038393939393832646133326564623761613965406365727469766f782e636f6d222c202273616c74223a202264356364383361643761643038346631227d", "TOKEN": "0418a8f100fc4ade7a6fe6d8340850f0ad54ee2c9249d40f64a3748eca158e1edc04ba7878f84775739b01b39af22979935f606fe1dbb035dd1ad8a73bccb1abb6", "U": "041cab7cec8c1b36fc51526d7b35d2b42b2905a9e821a992e49f7a70e96240220e0d924b041c186723b6a4ffecb59a2605d2bd23eaf540351b67c0d0fe6c3d7435", "SERVER_OUTPUT": -19, "Y": "0f25616bc7505679ab8d6328296683eade9f2fe099c3cb310c720ccdd837ab1c", "X": "1014f9ce5a1529b7adad9895c3cf8610b8a2e12efd7287159cd97e89dbffbc4c", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"164b717f352008999982da32edb7aa9e@certivox.com\", \"salt\": \"d5cd83ad7ad084f1\"}", "test_no": 179, "UT": "040daba1fa19aef057018beb3319227b5157fd2e46ae45c1f31458899c9a6a94121bd86f7634a633c42c569fe47ab2a81b671977be9d16f5d507a1bdb31fdea6b5", "MS2": "0f54ab5adb5b2bfe0f8d2c68158e4835a6125dda55aa6be4f9a319fbc67cec8b", "MS1": "071e20bf1eb666a057ce7bb909f6b8df10447e1abea11ac7de86c8555e5502ec", "CLIENT_SECRET": "040e9f7422c69adf944d37dfe7c031c02146ab298dffb90b1a2538f50df2ba1ecd0f465e3789a4d987afacd686648a435fc63420a8cb03ae3fb8d7d1a48d492eab"}, {"TimeValue": 1437055597, "SS1": "057d576f6c0f4005a00f147d87e8fb696abc88160fb960b4a8d1548d4707e17f01f58f588e88835692b168e4b6f67d27e0b2afc55da99df9fee6349d4b8f6082036176c60ab2870d324e1e1af0610799f2f5968fb79581003f2ded2424f0925a182bd9133592f3ddd3b31752d8401d1c0dbbb27fcaa705507f14f19be1dc967a", "SS2": "0af6dd30067d284407db3b90952321d21b4c8b5d263024570559380279dbdc00111917f26e6b76833370437200dedbdd09817c14ca6ee4539ae1cb06cdc5a83405516aaed137fd6d46397273c462e11577756a1b04968e1fb15568d26db6fe5420a089cec1f8589dad7b8d270793dbf95ffd9915f7d07c950ab48db2eab44a72", "DATE": 16632, "PIN2": 6740, "PIN1": 6741, "SERVER_SECRET": "207c3198bdfabd45860fd91fd8166208204aac325ad0b705b48b4e69618ce407218f259e931262a8171d6b78959168cfd64b0f9a3f399e4919d4bd37a3cd7dba1f387fb58ab44f9256a3792f1e82a60f99c5e87a57b9c22cb4b986b3bede41260e9845d42e0ca8caa2c51db11f1ecc49f04e28e2e7ef0d5eee5a5cb6292d64ea", "SEC": "041074dbdda8f55ebd0bdcc3edb3ee2d33b8910b06c9d4f537ebd19be3b40d8c6c1e9d5deb0db6cf812a341f8c561f8e1a630a6e42f39887c571e2791238734d5c", "TP2": "0418bb175e562bfc520ac760a5d1663ccd37527b37c6db9435b5b331379548d38f0426ad0bc6c39a7762594f0f95111e6d336639ee72e4a3836f8f14465edd28b8", "TP1": "0407cec3ed29dd4fbd8016c830e69dbcc728fc57e4ca088094f1baf612e216043113f34951af5ec0ace334ef49c3c130ab6daed070418d43d1ab938863e83d4219", "CS1": "040cf9e97386053bdf4e5cc48dc412a3023b6a591b9f0485fe353e972f14c5e916070f8920e74485680a7dbe6254748ca04f2a399b172e04ba329a0482431cd13b", "CS2": "0423fab28fdffc3c244f2dff452febd9afc2932e910a40649f0e75146c7790de370f1401da48b92a786c3ed2e148f588849d8b7b7e8fa0c098b4fe2714503f195e", "HASH_MPIN_ID_HEX": "314f852b1cee0b2605472aab0616a4e56c8959bbb3bebe94fa927750b4d68e2f", "TIME_PERMIT": "04120a8735484bab742aa2ef45eb3f9b8468eef9dd4455ea33b2952ba4b060203e07c7b0efab8754d8e4b4b7c385d5402e6699bfb7d458a873f0e0774c8d37a58f", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20226361336436643535366365626236386362373338613233353362646330663133406365727469766f782e636f6d222c202273616c74223a202234323737663239323664636339626636227d", "TOKEN": "040602ca6212bc9d2157a19b6b24e821c424493b253ba719ca8fb506e036a0104010e50b022bb1e80e2f7ad6baf452c483e91d472571d5cb4ac9b010756bc9f6f6", "U": "0415f6799c0f00b2052cf82d1aafb53dad6e826f71930bb939d4ccf78ce3ac4ca608bd0796fc735f69e73c7e70f00fac87f35050d5055dfd18ac33a4913ab9414f", "SERVER_OUTPUT": -19, "Y": "0e09c629bb0716f517efd4fdc454c84b38893d8d877b56d231761e1abecab293", "X": "0b89b359f77cc164e31c1dc31102a28902b7437f418e502f9a6aef8c03769b3f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"ca3d6d556cebb68cb738a2353bdc0f13@certivox.com\", \"salt\": \"4277f2926dcc9bf6\"}", "test_no": 180, "UT": "040dab2a8395903e706ac5fc6a1993fcb88921bd1b12a3a931e1dc7596f55f319f0143d8598a966bd6b7cfa97ca371ec774e3bec50c6455fd833565365c2356e5e", "MS2": "160ec8118a02dcb140c95d839e0dab5ee17babbe20e84403c41f926b71985784", "MS1": "0f948f9d0727207ef0e03f3b1f28a1222b00f3deb6aba328044f7f62e6090fdb", "CLIENT_SECRET": "040d175d6917b607a321c9a3809e0a74c1ab21b08d0dcab8a36a97c0292ac340d819baa02caa7f01b838d3a6464dc8732cb3bbc4308ae2bcc735daea8ea2bbb5fa"}, {"TimeValue": 1437055597, "SS1": "1a352ba52bac950ae4ad19c864746016fc6e34dc492e135d7f74890afb7f9c79209122d5f20cb4b386a3fb56fb202d5c3e2e1a4f6b0d9b2bad1204c6f1c6b205030010af07afc8ee8d926dc25fa25fc2e3b352a09ddf2a3246e142a946924da20419e2ca52d44d564d6dfc561c9c4608d105846db6c2cbf82785364f913f8e06", "SS2": "10461f6dfa0e876bf61e44698c3875b4753acb0c140c01affba3ed5815f852ae0560cd1f2ba3d476296a65a7d2f3324acdae7692afbe4828f1c01fa26497de431ed5f7d92f74523f2e835a0924784678e6b70ab98e20d8c2717e8b01c6f61f950e68661a1e10a51adb888fc562387bea642a90d0456619a60a67b2a6f3476a83", "DATE": 16632, "PIN2": 8999, "PIN1": 9000, "SERVER_SECRET": "1e8f3b1c658e512f4f70509fc151084e990029c7271fbf5a4d4768c05a20953214c7d9143ad9f7267bdd1f0cf723f4d5e5382d9360ea646c94173b354478096b0b0eefeaf351edb5fca3f1bf9a9f22bf9112322d7db69252892a7431e40c9d7b15f1b816f3174689d4d253bf2bb139cbaf1c07fb39515daf141b50f9790a2804", "SEC": "0409173120e8b594b1e58fdb5bf50f9f3cc4d76c5435c4127d4d6c4d66aa6fe7cd02b00741cab03678390203bf355b76e6c3283e49f13304edac13e6a568ad1239", "TP2": "0417156724e523b4da3ff9c91f382a041a5219a58604e73beafb388d696823e7a40c535bd3ca6b6737ee63e396b63087cc7a0be0dd876af092cafd1e9bc93fa5b0", "TP1": "041d7af3fe647f8096753d0601a61ea31019757cf2e67f68f86e9dd4c0a0dd7e41092516d4b5c79c34e828926605a7670aa2044c67e6ec5d6372330b06cab802fd", "CS1": "041889a71f37402c438eaa809c12930e66cd5f6f0d1db76dff1abb9aa77710d5ee21fce9355009c6455eba9c59a17cd306f7f10021ed1de2630a434d2effde95d7", "CS2": "040ec524e7d02a286d006008ae588958383b119ebeae12ba728097bc2e2f9faad9054df6ef1f00a448e96c017e1f5f246b616eb242b89e3364eed275067488360c", "HASH_MPIN_ID_HEX": "83d325882a4409118306c91e06d0a382ae248ea8cea1ac14ed1fa2b4f926d6a7", "TIME_PERMIT": "041212393b2bd7de4c24ceb7e818d58c394327845717bd1799d3cadd23b3cdae3214204b3c63eb9c6f68f459c8bd10cf37d9dc364c59cef33bc57ebfd29bfe82ac", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20226133326235343733386639633330663734646263643966396666373230613362406365727469766f782e636f6d222c202273616c74223a202235643364303663623236373162383036227d", "TOKEN": "0411b01f415a208f92f8c1ed4e12b0d91233b30ddc73d441a2a3ebc06a58f73ac5005a105ea14d79e93e700b5f33da1f8d3404c4e6b364676b7c24ea151cbd8c09", "U": "04017377c90d62dc72fa7df63cb7216534cbf0354fefd2a4bc7bd79233d0308d180ad624e0a18b46227116daf7acef8d48b388ce371c196ab09546059b0e3fd056", "SERVER_OUTPUT": -19, "Y": "01ccf34129b9db549b7fa129398bea0b331833b4ae890ef0691110b38d3cf252", "X": "1ae13446e5b21f107d8171f9cc4aec420955f47eca34695f008c858ddcbf5216", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"a32b54738f9c30f74dbcd9f9ff720a3b@certivox.com\", \"salt\": \"5d3d06cb2671b806\"}", "test_no": 181, "UT": "041edaccf820d6b877560c1be7e2385e1a310a24070cdc240313a28c5dc449e96c1be8869fd202880bdde6dcdcf0a2e76f89464a50bc9824dd3c849bdaedbb91cf", "MS2": "0c111c619883e805ad1a98b9ac8691e54f0c86f2d7d5c6b6b68875e2fa58f738", "MS1": "011391e726986df37a7db7cfd195cb37cb4f984d76e02a4f5871d48eceec6449", "CLIENT_SECRET": "040f2a23a4a3675ccef9f105fa51404936ffd30ca575e62152c9ce2df34d14eb280289a745dfe8fbb492e0e5317dd97133fceabdcbce751c94830e4cd646ac46f2"}, {"TimeValue": 1437055597, "SS1": "036403d6cb6c979f28db11d14d12c915c07d5d339466888dd7c69ef47c3b57cc0fd77ec3ce01674a8235fb101ece0fd00f5b16dee91dd0f64fb0a0f9e0a3392804b703d1e1dd2ae57812ab274305a775185a990653777bca732335989312db26077392445b9d0cc15d9ab624a0fe9d48d7522c49f58f4f7692113613085f49b3", "SS2": "01ded965da9ac193925c7da2b84e0463f6e7f18b42110993dc3295ea15ff924c1c8b3ad38676ae371e445acb3c1dd027cdbaf34ef7d26fbd023591fd039ab21c21ec57608e8ffa23a50899fe40f70baed8f3da90eb10d1ccd593261d9b4db5420ace89cab47d4f770e3525950957c9e3778874f176a87510bb5d1dca228727e7", "DATE": 16632, "PIN2": 4622, "PIN1": 4623, "SERVER_SECRET": "08fb34774657afc7bb446ae16e09eba1f7fa27d3cf361cbb4ba9ad4b911c721418df3145adf98823a0a34a05fb308fc25061385c3adabce2e062c56bba43a285083d19fff51c9feffd51fd064b667332dc0b6b7b2cd01482e146d115983703ee10e601303518395d9f0c2404804b0728583cd95fb2fc365759becc6eec145509", "SEC": "040c738e64c3406ee72e3164106821ecfa5f29f99bf4bb8b6fd45511a1e680b69509c24d5c9cd4af6fe6c50dae80f8c208d90a0b6c666fef837b3d276147e0317b", "TP2": "04008af42c308e2e2ec99bf191bc849f21719f326dc3ad969b050bd2444284aded01603e7bf50c52e0f688f48e7037edf46c8e4ea79436d09b5ce6a035c694e1af", "TP1": "0415855b50fe887eec4254c0d9ec8a87015de882ada7fd3749781cbe6c0b841b18083e375cbe8712a488d457453d836056c44fa73fa97be3fbab64b37b8d318eca", "CS1": "0423d3f5f85b29abce7d803a493de2b6e25d2372723a5262524f96e0594d88a3e10a0856a9ad181fefbe1ecd3507aca52855d0af935993ca238952f77afddf2843", "CS2": "0400de5a3cc53bdff85a6a65a06fead4bee65ad4a19bfbd9905011970fe25424280308fda122e88ba945159a3e1c3843c7b61504032519c59438ef6df83fe88af6", "HASH_MPIN_ID_HEX": "8eaffba0a310cc4f704b36a94623d52db166b30260f7b8ed7ae6c6a1b7b3dc1d", "TIME_PERMIT": "0409e99c8055275ffe8158523cdb8ef2daf08baf67616d195b2138a90109ca1f39060dcc323aad79db2ae1381f58998f3b99dd26a5bc026dd93c2fdcf2a4807b80", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223234343263306138376434323537613362666136376439616131656134353736406365727469766f782e636f6d222c202273616c74223a202231326465656535393165633966373863227d", "TOKEN": "0423cf1bfb374091bae0487af9559be7ef2cf9916ecda7985039ce958a9a0ac47e1a04271aae510a733a92e0cc6e132934eae1b78a939b1b4efcf5c209d4a28dd3", "U": "042161a9ef8d953cb12ba09226699520dcb62b042d9a2181a9216b0a23fdabc1a9044b757553773cfa6565715c72a7e3dba8e80dd9f507c248f85d4790ea13af3d", "SERVER_OUTPUT": -19, "Y": "15856fd3888e4d3ce5cfe0d0d2388f091379c39f1d24d8bee03492373fc25425", "X": "20f8662d49d2dcbd7baf1586df898ea9877364afcebea9a4a81a377d94cd1f85", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"2442c0a87d4257a3bfa67d9aa1ea4576@certivox.com\", \"salt\": \"12deee591ec9f78c\"}", "test_no": 182, "UT": "0423b6435711878a60929f6821b9bdba16b631a399c46118d4c97888fcba8186bd12cf0dc281388e8210d6ff521a061e83713b73844ec5fd41c55bff758b41b4df", "MS2": "045772696a76fc17a384326d36f93c697d80b3153781107efb4b6b5aab884fed", "MS1": "21d4110bb77f49995fc84a9ca02925af778ea2a69b2db773a123f0c460ea4492", "CLIENT_SECRET": "040bb2aa157e1f8101df3d00e9bef0f6d3519b908ef2ce547b63e95e8310f27b160775711948a9d586dec889a7b87c11ad31acdd8ebc90ef82dbfd00a6c772ee88"}, {"TimeValue": 1437055597, "SS1": "17f3128fc08e069094876ba762cae963665098cbbe9ff858393874ce930c27c70e2874567bdff7936ed5e0d070521abe6a5ffd12de89781555ac50be84de54cd22389fc731f56358bff233ac54cd6d920bc8ce5f4c35e5908e622d0f55f217c2049f8de5a507d33d6659ae3b93f4375fb14890e58828f4f9ace866bf4945cc8c", "SS2": "07b2620a5eb1e78d77b18a828c3b8563a3f6ea2e22df37a3484fba0cdb763a281ae1f693309ac6b2996e7574bab394edc78a4b080773415018ab7937de501c2113c420f515969868e9c324dc371049e99a4fc320cb28e82ce198f741da524e6b1c83599d59fd557fc26ec8ee3f86993f6a48cc1cd1f791f099a95b81ba771e6c", "DATE": 16632, "PIN2": 3156, "PIN1": 3157, "SERVER_SECRET": "0b7bf347aa3a31b4f4e0b094a532d7c3b5d794d82860c38e7463632acd00d71607bd6a2a98df02b9b4ace65eb08e78f31a4475fe3b70df235171a8f10a4b09a213041590646f0f89f718ffff4e52edf156912d548ab28b0b2e48e8c6172ab0e715d89e9774a99a002c8b635c7c09c7531e2a95b99b12724cff6d34bb961fd214", "SEC": "041d5ee53db17fccdcdc9c1a6ae90c767079ee60e44c156b93a527a05432f0463300d4b397688ce01295d41c3fa7bd3b7f89026571a0e461ed2a7dbfafd8f17acb", "TP2": "0412e5732b5dc86a4bf0ddd8655fe07b076291ac85791c05ae9d5214ff315a1023181e2274b5c64cddbf413b7905b30cc8f4152482fddcbb646e98285ade620466", "TP1": "04047be104a83a391399c1e76c097112ef18f996ff0609a126c10c9f9a922809f70200c7988ff85e2c42e8a2f89346e426ffc6d312e72c87ceb6e54b362cff24ab", "CS1": "0420c636dd8cd462efff77d1f9c6e5261180e0f7bad8db7e8be7ecbd8c8f8465ca0a3b7b123397021035c84a5d6164019bd1dcd9cbae16faf5110d066a155301ac", "CS2": "040bf1f9268463603b597358e897b9b296ab769112a7e4cff6a623636ac2e62be011cf620bc229785d5dd1c1148308f7f750fdef27409c0ecb839f3fc4135e8498", "HASH_MPIN_ID_HEX": "36a33ae9ed9a24acde28c29a18feda9eb8b8419640bba618d1f14311924129e4", "TIME_PERMIT": "04223be50a4cd3a91ac436b97cdce7b586db889253b76f9e769fc4d23e5bcd6b7215fe523df6e0d0c590a293f9dffa8445b69c7cc77821cdbf7b8b3cbc87d0ae29", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20226164343030373863393166656365636465643236313166316665666432663462406365727469766f782e636f6d222c202273616c74223a202238653932373539623664336435666663227d", "TOKEN": "0423c1c18d322f27aededc3e3c12a9a7ec117671afb7366b57737907c000d26483009656683cb4ac503ddf8bdf418c2f41870834bf2cff8967ad4f5cb258fcfbb7", "U": "040800c3619f58aa9df36158025c1b87f3d9bfe1bc7d2e953cb675f0f64b10eb4008a276c154f34c5c36a4a478eb10e707c741921f31bcba033aec020391fb152a", "SERVER_OUTPUT": -19, "Y": "02da1ece5474b9c683106ca86170b1c364976f201306f841a60104fc0291991e", "X": "010d819710a3ba67621b0d3647eb412f7791c386eab862dbcd51803d7aa2b21f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"ad40078c91fececded2611f1fefd2f4b@certivox.com\", \"salt\": \"8e92759b6d3d5ffc\"}", "test_no": 183, "UT": "040a4bce4df04c275d20e2c8af5ec669f244d2041587ce2242280ba4b84e4955aa0f1f371b4761230f897389baef3b1029ca5f132498110da839d0e55276845738", "MS2": "18722ba7f6e0863ee6fd0e3602abf6bcb845261ae697af9c898c7834c40e1dd9", "MS1": "0985617bc68872deee1c5fca48e0106f5000fa940d964baed31503dde76f698a", "CLIENT_SECRET": "0407058c3897037a6bc5d38776cd809fe56c938995e38221c291b4954e4aa0ddc9041c7882bcce54a71747649076d9210550035ad93137cbf942b8153e8f852c60"}, {"TimeValue": 1437055597, "SS1": "0d02bb246531b388a7d076dca96b8581e33a3171eec305a407172a0b262ed16620f0780eec87819faadcaa5209d870f743bc0b59fb315de4148e7e8d1e4749b718786400af0f77c324f8c7a59badb2dd312a7c09a8b53ceb7805e8193a10eed61080c63c030c90fceb30afbc24abd9c78bf223ab328726975adf348dfa98244e", "SS2": "0e5aeb0d6710dd9072ce0855096fc252991229b4c4262671cae0672eb180132c00a4ae72419bc5891afa9e21ba24724cc457f4dfd9de22e3c0bd41d17d94dda215d492fac8b93d8b1073da94fe350d76fae46d51af15a5b93c3e7f8e9e961475036cf819a7538f0563fa67199af33b01be794e75855f60b4f1c58c218763e154", "DATE": 16632, "PIN2": 1488, "PIN1": 1489, "SERVER_SECRET": "21d4ca21fb9694ed13ddd17cef2eb5959b97eb7d7f114ef0084a2500a742a2ac12f8b495e3c46e73906c76baf151d0ea2b85144cbb0cda5b4b9d8c28665d50b40aa7cdeda65068ea1065373661af59a5f7c0210fe9acee4474940efa8e5c36380256bcd35e3857923f58b029f6be4c97c0640347fe340a4729c75f4c71ae48cb", "SEC": "0410542af53a01c3a9c474d96882766fc4e70873f86b7f91f322e11fb2f404978a00340961f93becf160dc98402d3057e7674c21c87246c94cbf09a5b7527ecac1", "TP2": "04127d870ecbccb02f3d016e021383c16d79660250c620851c3502ddfe93bef62e13f075875f1dc185622d9705c4f758ea1445fc96b1546f4fa7a91824573ce5b7", "TP1": "040595308b61d2ab55c2db4f99a64fc3d848fcecbe0a17c995aa4633fbfcacdcc50af2f0e546630c1678b970713fcc0eb742cad81640364653f387e75c53852127", "CS1": "040c34cf50b95b1095b319de73164dd4ab4dff0ad818f153c391edb2f1fcc684c60346909641bbed242b0d1f0c469a48ca8decf4478957b6da44f64a7a056cc35d", "CS2": "040ca4a481b9aad401a7e3edb30c831052ea240866ee0e886a7c5ea8b26dc4ec1420becf3764b6512a6bb6112fa70303240e913a958dc1fe71811dea60e983b6e4", "HASH_MPIN_ID_HEX": "24ab9fe92f83f5f6ce33917d65940449984223c9e7bd499a73c1b9cb31bde1fb", "TIME_PERMIT": "0420a3a32701ea37b3e4132c61a57ae6d221df0645348a70bd17d6d3a94def54571cc2e64ad75b17c4c410cd226fc7f86a98266166405dc120a55a4dd374a252f0", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20226364376239353232653361326239353930623530343737363834646366323963406365727469766f782e636f6d222c202273616c74223a202232333434376235313835326261353466227d", "TOKEN": "04123c353ae2618b0037cc1e8418b60c60e54cb7c04f90c0806ea8000ce29e9baa0dbcc488b99fcb03246069e800ed2c912782cb3cc73ac1e09c4f5a3db9f234bf", "U": "041faca872c782bcdcd40ab2809caa1a54a7a2f651f4093e38c3860a04d4e1185000181ad8f47bec09be2390fdadcbc42e7d7dad754168342c3f0cbcd1d96dd7c5", "SERVER_OUTPUT": -19, "Y": "1ca0b94c10403a4dd7f465675d2dbf9769969b2e9901bc440948fbf6d6c1a4a3", "X": "1918b977f970d93ab4ea16b71962ae7c42f306bf0eddc9cd8bf14dca42e2f5be", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"cd7b9522e3a2b9590b50477684dcf29c@certivox.com\", \"salt\": \"23447b51852ba54f\"}", "test_no": 184, "UT": "0415a9b131ebc60688b7be95f33bc4696a46cf8be26211a99a49d5a2291b719d3b1eaf6b1eadc4adf4b4032ae80772c2b86d73f56030eabd39bbeeaaf8d8655088", "MS2": "04f0db11bfda842a6e2ef3e9ffeb830c092111131e789e876ea17255542a0726", "MS1": "0220e60dff5f92e482773235e6f7d7dca3b130a2343ea57513b506ba80da4998", "CLIENT_SECRET": "0407d9d97d74e76a87748bf5ada82ac2ee9a44164170d300d48a7f899ef2df54e1209129b73409ce0662fd193db425eb05cd74587551e2116fde4910b23665a8b8"}, {"TimeValue": 1437055597, "SS1": "0ec8b99c8e51426ea0ce73c8ac614a9f612c75b01c043ce6b755916b37c7a7fb050ceec55a6f5704f5b973c7728ab8b998e26366e33ba838af27986ca96a348311b1753682881c3bcd13a54d6ca34b8acf9535faf1a9e3dc9671867ed80cf57d1631e72656f85a7e464682035505fd9f523cad73181d55b1dd91950d28789a9e", "SS2": "054d463cb6f400d07abe32038b3e2056c52b938d854e3199e1620d394324024e186eaad8228f129bfe00c84a501bb7951d747d70dd20af12678fb0ea652d9ea4167cdd2506796df0e48da5060f33c5865ba9d75cd32ae3f6d76b911bf30e786110e359e96043e8f67bf962159588dd74319571e9be1311a17ad84d502edb7cd6", "DATE": 16632, "PIN2": 9893, "PIN1": 9894, "SERVER_SECRET": "0a509dcd50b77b25826565dd209d3e033d1bb514283ae6d7c61372ca4fda886012a0365439d18d228c5157c55a77c95f84e059fc31292ca3bede27adc0593a141408e779fb17790b0caad090c5d77b862e629377a193110ab150715af733123818b3bb2ed33bb251ba19eea399cfd664052620d214206ac7007c7000be01283c", "SEC": "0420a4bd1e8623531a86506b8f7446965d170cf96976589ee2ed6fa16cf6197ea323162804f9cf522cecca8044d8298d183b8f1c9f5d81150d1282bb5cfba5aa8b", "TP2": "0403ddeb0199e7dd1e9ec71542ba11b708a6cd9d5c7913e154c03704d85c801b511e73849b331bee7af35d9e0265a9432da8386d4f234e9f00785de00e1d77ad5b", "TP1": "0412599350c652e924787d086ea2ee3b33560dd9f1eacddd14a2589ea502dd10640548838cb1261e998408efa88e005a35d2e91a873315ff5a997848e92a210ca1", "CS1": "0407690d810ccd137cd75d60cf85a0f2ee031a970c506414131ff25ab62e2ad6de21d0a47e81ef2a3c4103f3b35c4714056611b8985f7d60aa3cd1f4f4644b8a2e", "CS2": "0407041738814d1fabf8ece6272df17cffd89bb0cbea24ad17eaed501a7f60fd7016b52d709ab2e99806a98f427bcff035c533dd2f8cd99bcae0d2b54d605dc5eb", "HASH_MPIN_ID_HEX": "27625a972d937fbf4f1f9e7c12b9e1543b5bbb434a06e74289a85dced292c677", "TIME_PERMIT": "041c31a8f7eeeda7f6dc73e3ba0381b1af8b60fd439a56954246342360c929430c08f573c0fb317e1c34511a1e52ab6e079d8420800e20c471a393ee9d77d846a0", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223264333666643631633161393530646161313666323762393932616530303631406365727469766f782e636f6d222c202273616c74223a202232306535303533366465666638346134227d", "TOKEN": "0405d27fbfc308d9d938951fd5c8c2ebed1eadaff078c6b680a8bc29ae051b69d60b6900e8859762eaf1f5397d47136a9dfad6a98e0b1e9e42c720c7b8745ba414", "U": "0402a4978378acfef89a9b9c726e33900d48b07e7b2976e884d0557c364a5b3d3716d340ba941bcc2c119c2c82e75ee764e4618187e60f5bee343b09454e87632b", "SERVER_OUTPUT": -19, "Y": "1bdae999a23b993daab6952e2e152be875d39a02714460e710bc925af11b9542", "X": "0510e28c714222d76f43da50bce1fda2f7139ebf0e0b00e8bdee91ed9c0e5588", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"2d36fd61c1a950daa16f27b992ae0061@certivox.com\", \"salt\": \"20e50536deff84a4\"}", "test_no": 185, "UT": "041fee641e9840c5a3b4d191e2a3fa6c0a5f0c090f10c98eb2d7017f4e7c6f624e19998639e21a22e045ba5cde0069aff4776e94a08da39d410306bf9eabafef64", "MS2": "17fea29347d1093bafa1c80a0c4eb29ae93141a3fcde0b4ce9307c422722e82d", "MS1": "237bb959466d396c8e483671ed62f920df4a6b33769e97fcccbc57c2fe1ffc3e", "CLIENT_SECRET": "0408e86e842f81d851d12283f1a41505ec82b29cc22ce03de252609fc69232c7ae1dca2d62d4167b685f7ef523ec1cbc37e4575b338af12f44f008cb360ea0a33e"}, {"TimeValue": 1437055597, "SS1": "180f9af758066614991ce3a4e83f3191cfcc8294599ac8eb360921b340d373fb1b864b657bba1cdbe3e370c3dc7388540bc7825294ebbaf21a261b843969e3931275d8c9c21e9cb0f7d7ee69c065cc3129eaa30de351aebf8d889cc9c4a79fe1214f4b852d8b09571260c8236d9ff4eabece633bda1c3716698a31dbc761bc19", "SS2": "059b899b7acb651d9b8e3e8fcaf3577a92f63f6c550879c49381145702e85ead14a13d42c8af1251d20f266ca3f3d7d9c21bb2556474950d6f9995e31ac7ab751063dd7ceac7a4c5a3ca2a36277642b41408eb66a701025c565bc3df2639afca233ff66c559131e2fb7853adbfc742de068c5f313133addfb703d7bb1adeddbc", "DATE": 16632, "PIN2": 8329, "PIN1": 8330, "SERVER_SECRET": "05ca15dea155e079dd51c45b502a796bb80ed1b79c8e8fb4c1e22480c56a3fdb1000b87feef9c3756482e648987525cd6bb3eda4ad17cde776d21b0f6ee191c22103a065adbac95a36861671690337106c4557f3f8a5f7b7c1f5d9ca856cb5d910d117ddf3deb985be79f66c49f4f7043bd9552cf25d8a12486f43ba86e38b94", "SEC": "041fca148d19641472106e6263903dcbe81fa863f52161a473a36bed118b31f2d1208d1ea3525451fab0369f13fcc911415f92fbaeeeef8a3421863818cffe0568", "TP2": "040e469b7b90c7ac6a27a34c65fac83989fb34b53bc1ea706e496305113fce71a803279c097dd2b57817c24d06a1a43c5014c4a66fcb13fb1c5c04b7b54ccb2167", "TP1": "040930b9dbff61e21a63dc4940221322296eac3ed33e66d5e4b5f829c3f7c83a4d05dcf4131294651daefa88f29abda223de4ffe0a79640eb867105a0f3762e1f2", "CS1": "04050bcc73ea187817a88d79d21710120571e73dd719aa9bc1fedf58295b862531053dae1753820ed7ed35dc54475f21f37ba33e5b2edb77f85f7e0a2fdebd691a", "CS2": "040b1e5c69b23128dc8c84749b5c0ca129977f9fb872b21a216eed8f1ea853faed1b7cac801de1ab4eaa688b14a4af3fd5ec0ef0bf38d5ef7700b14eec8ecbad99", "HASH_MPIN_ID_HEX": "f661abc8a93361acee54a4c333c31bc29f105ac18d43ece2c991a1380c99980d", "TIME_PERMIT": "04215bdda5bb7fc400f6973162642ed55d707db77c85b78892d2e3c18b00a4a0931ec86af64aeabd7dc5d6daad48310badd32c0499b354c5e42f5167ab5fe959fe", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223534303736306231663638613062326133373835306637333035666262303438406365727469766f782e636f6d222c202273616c74223a202264333937326462666361643135613035227d", "TOKEN": "041b308f7c12ff63d7f1ac50b6eccc23ade9b4ba603c240997eda22b70b4b75d0d1ad8460b6624e2a712bd26e8d6994679fc15e5cd09ae8935f9dd06fdb4bb4c7a", "U": "040de119fa4d52b8fb4dfb940fa0f64a0ec03f875701253a0911817a7bf24d8fdc1cbb12232aa4fcd4eb8e64feb73c1ae168b6473b06972571ea2f56a6ffaf7d8d", "SERVER_OUTPUT": -19, "Y": "2350235f167d8776fa085ee2fd096724374194012993c681862d1ac9966ca235", "X": "1ba82298cd047c8b542dea302b17c4e477d39d372946bace272c1f5e11535225", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"540760b1f68a0b2a37850f7305fbb048@certivox.com\", \"salt\": \"d3972dbfcad15a05\"}", "test_no": 186, "UT": "041a86b3363b1326b343cb4d77a6f4615b9b7670f18cf818f5668a500fe5f01a6d20d87ed4ca1e616d8835b0edb8aa6d10466b55a90c4bd66dd691de35d6cc1f28", "MS2": "01a8ba47b7b897a9c885f187a49ce96838a117f950b5a54903c92edd684fceba", "MS1": "045181cb05a6568ee9743eb87c7bfe1c579be4333417573aa7f96be4ac48b4aa", "CLIENT_SECRET": "04068f25f65ce22fb7343fe6c7f19ebb8f5bb4756d6b6750d3179616152d2cadc818769884e09aeef01c12710eacd482a16816f12512c36b78e72d1c2774306154"}, {"TimeValue": 1437055597, "SS1": "192c87450eacf126b2dae716aa4b166cff41906e285db17a56f152e7f9dcd2831bb806c201d9f4c3c757ef8b47bb3fa16f6cf808504aaf7bc6b395dd979b277422896fef96379fd0b10aa2c89bda70de2ea3cc1dc24b9220de9d065abce1c4030fbc7177e3195c3276a5e8464cd08e1ff2fad9762a2ad5c829af2abf871f5727", "SS2": "055a430773becc2ad78863282af0fb698325b483ea16e0efdfc0f78d980c47fa114dea90082387d50c381768134fad7fae24d68db4a8c2c7362c2e0248d23e9501ffa599b9dd7c474072601f1f7f88da9ed9c72fcd83ed476f47f0a33c782bd319c3190d8672784f541205aafd9049bdbd7b86c7e38e846e5564386e83d3fdcb", "DATE": 16632, "PIN2": 7273, "PIN1": 7274, "SERVER_SECRET": "0bfdebc160884650fcbba5439e13400ed6940d503a6ece8e3251d93a711e3985163a300d3632f2ee508d8f0e4e1b993baf3e716bc596c50028f42929def267b207eb0dffbf7b09ecf3ee83193d156bacb2b91a553808edbcfeff3c94a541e5351d1fb42d6111b935ebc4d847fe6a1ac9bfda3cf19bbe13775d428276829b58c4", "SEC": "040dc844e7b5cc125466152800ce6602e1ede3e0346f894443027efec3e44091e721125a677f0a39c8846ef979bc8cf3a92025177ea5cb586d47f2a7117a0e3128", "TP2": "0420ad5e1c089a2f55872679492e46eb84705b643aba7b38fc1f469ed822ef2fae22f27f526a48a02d1e07f03a1e983b36bfb74c92ccee842ea86ef7a9eb239b12", "TP1": "041cc737dd7c9698ee646d2654b2934fed05934cfae566a3df6417fc1c31231a12164095b34348b5e62a8278f7db79ef5693485e044e0a42ef88c8b98bbb1b98d3", "CS1": "042143e43bad7ae55663c80e57eaf8a96386c4b7a6ffaf5756a29d8b87d3f5af7b06e8b4e0d616c559ebfd745c97f303d0379be284b26975e9ce0195cc26e00da6", "CS2": "04065bf9bd39ebeda32dba275fe979651355065235e805a6091645192972875a59194bca14ddbbbdb1a272ccaeb92da9c7b44ac1c1a5481fc8ed81b8020be65e0d", "HASH_MPIN_ID_HEX": "4951e939ea92b95871734630a5b88bee7fc490b6c19948b4e4533f050c2bdb36", "TIME_PERMIT": "0410a766c798f11b1ad3382f6fc7279ae6336d1a2896d8dd3e7ae2d2e9409aa6dc236d306f108fb03e5e3df4c53e98971d17e275a3d9045a675e8108bc4882907e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223265656566623762323730376234386537383963313734373532613164316332406365727469766f782e636f6d222c202273616c74223a202237653637623831653239623936643032227d", "TOKEN": "040cce06e0e38dfc22d95530997005b745672363bc4876eef3e638060f728ae6b212fb4277aeca42ebe1e7581bb999bcb053ed73529555278331c173382e919961", "U": "0400c9e23da20712858f205c79cd9ba0cc6cd91084e818a6b4f600eb0f59369b1c0d19d85f99dd1e66f6290d7392d0302141e4e67b02a980acdb5f09916ee20391", "SERVER_OUTPUT": -19, "Y": "173e77b6a7a8409e32dcae98410fbf71db84dc864367bad9bbf50873e948530a", "X": "21e65d8c10b414741e243f2c4d145c8320cb9127f178953bca3bfeadf729d008", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"2eeefb7b2707b48e789c174752a1d1c2@certivox.com\", \"salt\": \"7e67b81e29b96d02\"}", "test_no": 187, "UT": "040e11e66b59f16f07d683dcf21b2a5bf64899bc602fc793046109cc4e7c4edd6f12f73ca3e24f799af51545f7d190fdfdefa48f0dce032a862d0a7360282fbab0", "MS2": "056fd46ff421a8d71e92bb40f8b876702f31f352d42fcbe800d29743bd0a7320", "MS1": "174cfc48a9119e41207d5205512035cf0a68c8205251a989b62da9edfa17c179", "CLIENT_SECRET": "041525cce7dd0187611bed41b53eb75ecde74e7124de4190e880d6648a50323d9d0af9ef6caaf2b9a6b7ce223c5ba4b62c32c93a7a218befc414e0de3bb5b400b9"}, {"TimeValue": 1437055597, "SS1": "003c20f6c309ec447865ec1fbdbfa1dc3fe995ae423f50655af8e45ead35c28b128f8b3ca739d03d841afd23ead5c7fbbcfe188fa3607b7fbe4c4e1c99975aab1af7bb718d8216ed32ad7d5c0799c54e667f885916d319276f13e0dc08334cc01f5cdaa54aec3ee154c26e17102cc39ab302753e94cd681933c5aa179b12b3e7", "SS2": "23ff2a3d95e10f753c0842599b688f30ca2f5784539c29f644e2c5bb48bbaa8217888539dc855b9c1112665bb1d88e0224a6b2d298a874060da435ee94d9e9281016bb9d8de52120b8242dbbfaaee864c6d7a16f3f329dbaf7b84613f19af15b1d7addc32a63793e4386b2bd96f4031a4090ccd9d2546ad9afa630bb89be1416", "DATE": 16632, "PIN2": 6548, "PIN1": 6549, "SERVER_SECRET": "0b309cf7671cd067e313b44733bf932dd871a806933bea8b5a14bd5943d4182c0c4f4029a58182f690e3103d45bab4943b9df62f39f323115b2fdca7368b164b1e70b6c5b450cdd2f14343cf1b7c3a484dd1b83891d20cb94acc0faa80d4da390024aae181b9e80c58bef6bd7cadeedf85e79e6d2a7bf06a696370d84d5a0c6e", "SEC": "04125e1decbf42a2cba5473fec75f446fd4e5368bba1a6b60dff8d07e8d3b466b00e3b4228a9a8b5afd5033bf0a4a4b636af4469b7c706b136093cdf8066fc9036", "TP2": "0415ab6e0048f40273814b8a699381970a6325540a435e06e0324966e65cc416a61793c12d0da3549eeb5174b8bea8d13a8f4e0e51281c4efe117e50f6d59385c0", "TP1": "04109b53ad41c36a34f54d4efaa123257994c25abd2c90f01025cfce941fd08f4d11d67488aa58199755123c32b6c88ddcbaa7214eb2675913441ff62eb60ac7da", "CS1": "0411fd329c1d8a10cc4d30d08851a61b6b315bf09880fe6dc64b432c9463e3b9e30dc641ff1e9f9703b8033e4f2513641724e40446e0669a973fe5ab634ee3e89f", "CS2": "04057c898a7ed4626aace2f59a31020382dfaa88c73548daf9d603852e5e3ef25a021fc17e372b8eb32cc5cdbc49022f500bd5c44f7243573c80b745648283f598", "HASH_MPIN_ID_HEX": "85d7af71b68dc5a26f61be74ac54e22b93cf2d53734f4454059f3040bba9c10e", "TIME_PERMIT": "04216d3e11887d5f834ca5f996d80a0e67992a28fe9038f7e4a34772e50346792518cb680b7ed90342966d9b314fb37f06d0f8490f3595bb3a7c6092044b89e426", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20226164363365616463633633303762333833393365656465303033333938333036406365727469766f782e636f6d222c202273616c74223a202235313436336261323837306136613862227d", "TOKEN": "040dc0a5ef81bb6ac682e2918d4c5703bc79e59511a6c31cd56421eca39cdcf214049effcabfe75aad8e9b95f9d2a6a000d1f4a8c2fce36ad442d193ac882c9deb", "U": "041bd451ea275a30b0027d465dbbf48b84367b63c40442fd560ef79eb6c629e42a21efe778d8a785a40eb54d088b070b410a0335e974537985b7a0133611ec641f", "SERVER_OUTPUT": -19, "Y": "0bbcb7b8db318bf00f526fc5f1d8c08dc401c2ba9560167c7ce8f25ad102b4b3", "X": "187416d46265f601e2028d1284bd832ec02ea48420f74cc15f6c246fa0ce2c85", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"ad63eadcc6307b38393eede003398306@certivox.com\", \"salt\": \"51463ba2870a6a8b\"}", "test_no": 188, "UT": "0417e3c25ad834e9fb54509e2a86623e7395ac5e56e3d843d911ee546db3a7d6f00e59814f3b1a6329df2a8fdfab21270b1440aba49a3a40b93fd3146dd0440a92", "MS2": "1ffb70c5ee14598f43d540782abf64651bf3d60278467f2c7d21c1a2a45f9abb", "MS1": "14635767c56e1c3922ccaafd91e52e80f4b941b30b4e9cd9370006aee0443b54", "CLIENT_SECRET": "041e89d00310a6059c52d1736d7b3108877dca4fe2c47cc7aac3ef94081582007f1e16f8d511b0e15dff9691134f7ecba4aaed9e2cab6c8f0af070f5bfb859c870"}, {"TimeValue": 1437055597, "SS1": "1eefc7a8e2ad6e615c517a875b26c6e852c83417fcffebdc7714760f117d15db032aa98648d4a0676b9e890f101d4a9937c6ea356ae6eff80958e784bb3a35ac1f89489f621c795c56e29f11ff77b6f67522050c439800ae9cad0fce89257402009f6580030c8e140f0b609cce539b1b6fe3f55f3efdb4339ec35188a3e3e917", "SS2": "01de5ec976d95f730ba390899caa0c21ce1261f811bd322e39c851f7b515ed690b8384e152761c3c31d812c244aad4256163a91bb4e77f4a75d0525fd257ec1d1a0045884ca736370a476fbe0c13a4f5ff494ce02e84d0fbff930d58644a4b5510b188a2414767617fb9761f58c9727d4e61e45c8486ac635102b79bd519f528", "DATE": 16632, "PIN2": 2894, "PIN1": 2895, "SERVER_SECRET": "11dc375c1a7e6f8196d79d75c6df3bde20025d86706d5ef3af22df24b55fc73901b26ea96c3b27243d8d640bb695652d36656d72b8d0af4173885a2c7ae93ab007b9f968d89c393494f945e4a14266a59dc76e3a46fff324563dcf735fd5e3b8124558599b93e89f862f153ef36cd922619e5e6c4a320d383ee5ae2f77cde9cf", "SEC": "040d71047124fe432f36b29e269f5f01872568379fb6690b579fe1ee68a8b2a46d0ee4433347ab90bb200ad22854165a64f994b53adfec512fe987d31ce7323553", "TP2": "041f59dba539a237f2c1fc7a7c13842236c487bba9a3fd77ea4261d571842ebadc1197281c903e267856ebab36054273c64940aa643534ffb65fe985ebf241163c", "TP1": "0400edaced839f0db7984866792232efd902f914e7e9ec3d4c4f750e970b7466ca199d872ccb6e5f0d75108a9f2242d4e49a6e271a5d8fd0e8c097c160bf4a2d49", "CS1": "040d36ab25b2db821a0386cc23c82676177dc341cc4957f89b7607dcc4d874396503381593cac4f340b17a0b4e4762af6b5663df2ffd82160d3c7dbda7a8933b5f", "CS2": "04039a71bfab64343cbc08747af5d244b23b52e3a7b43c41ba4fab900c5c0eb1710987734afa20879e1881a0f2c628d8cd8b6497985d2020780db63052028018c8", "HASH_MPIN_ID_HEX": "997cda29e5a1ae694437ee08e2c5b0dadd10b71e6de7537df38872527c5f8a60", "TIME_PERMIT": "041936564ac239b90b2428b2fbb1063798c9a00d455febe383fa01d641663a03e02270a2282b69eaaf035e15a75bde3f3472a5137fa4836696741b553051f8336f", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20226430393433316161393130316561386634393862373135643062373331383232406365727469766f782e636f6d222c202273616c74223a202263376662646461396637636538366638227d", "TOKEN": "0405979d7e41a65acc6d06be67bf9846f295efd6e6ba666f838b12372478dbf2ae0b49bc5d5ec7f0f7e4bcb2e6d58c79adb02e021b28694b4f964e4c8f88c7160e", "U": "0416a8600505c851117b42c082e79c5c204b5d8f9d7201053a2f419f8cc1400c940d1505ade60cf2ba49db5bc5d350d96d0e9fc297f96a7f7dc67257ae8d7f988c", "SERVER_OUTPUT": -19, "Y": "0076736a77a49d90292c9113961a069e56a785026c97658e7c954677aea15063", "X": "0845f810a4c652061c479890ec786711addbcc19c70fbd482e180e1a3d7c98d6", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"d09431aa9101ea8f498b715d0b731822@certivox.com\", \"salt\": \"c7fbdda9f7ce86f8\"}", "test_no": 189, "UT": "040886bb29161b0192cc8989b73e3f308fa01a6c29d1d8086eb86742263b670c201dd0fd5371290345bd59d1571eeae6fda52c894958d920ac52b17d55d053d224", "MS2": "11964d73b03c98383998a63062cdde9b1a4c255ae3611ac55d6b2767d1169c03", "MS1": "1df9ab1406f8c2e3726136c8fb56bcaf010e19e94f16d49a48845b42a38e28e0", "CLIENT_SECRET": "0411005e210fbdbb50b39329473e2aab36e7035a8ed75dcb06626d918f9f62981f1eb886450ae4d1cbac7e931eaa5b68f19eec3566d87eb61208c7e51fd2385245"}, {"TimeValue": 1437055597, "SS1": "02c0bcfc32f0840de5ddbc1d5aec20731a16041d4be3820838a22590d5bfbfaa1813945d7637e606c4b9e811a01a481412a78e5cd09e5aa158f51bcd65e840a50d71d1d497245d19194b80fb5eb924258fe5a276f2bd1582ea5bb404093876e9014e4168fca8c792146683ed0572f608c3f203651ef2717f4b827edc6127ebde", "SS2": "1347b73220c2b23e4276eae257fb7743386f0905e9243da500929104d3964376176e320fe347cb6c0c888b7642b435b7c2d0c4dd3f7e032bf98c122d5ac0c3ff016e85703f120a744b8a3f8008e8b720b438ae6a9eead7bb2f97147fec6d86e307bfb7227c4d754e71e1d77e747b73ac7edf8efb3f95552b40535c6d0df6c367", "DATE": 16632, "PIN2": 1475, "PIN1": 1476, "SERVER_SECRET": "1eb656f60427c42c849a1d0581e5ba5b33ca730d7ba5ad041bdc9b9239749cfb00bfbbf641be58f3d276edfb2718e2f2a47ddba467d745ba2b848fdbb2af9a93185bdbcf9d24b8c19f409dba79d5489616dac86160cd654123409c4e047cb6191ccf7d6babde5cb3a3dcb73c954baa10f9e312714a90d0ccaa47354f35474315", "SEC": "040655122e6eb9b875a4343e08dbaecc68a83fc797e64dd23b478f39d209729b201a8a6b3a307d7007b19d3839d3131a91fd1e28dbce4d0e3d3a610a8134894d93", "TP2": "040d3f0f9965ca016cc727893fde54370f999016b737aabc53a084eb521bfe4b810d38fba17271a240847d3232455d5da26f66381907e75d49924d694cdcfbf670", "TP1": "0422eccc4165fe334d42bc5ca0d8bef15408bca1821c07f189536484f7bca3d6a4049bd3df08c4e4820d81119f60a4649188934d66630c1c80f6abfb688b5e97d8", "CS1": "0415b701522c727c2fa40a22de57eaf263941861a7c3b42f68e9a3c5345a9957e816be27756fa3360b6e9e946f986596fb9d10452c5c75d8a3ae15c3d1576dacea", "CS2": "04207e92f90c19a50347388feadebd964d694003db6afc68cd3a9c1cee2de714770924cae30620931f6b4c949aa8e961abe65b9ecd0fc495986689b58966172210", "HASH_MPIN_ID_HEX": "13eab167f67b796f484ccef3c79c6c4bd9bd99b4461145d47c721a28cbd4d851", "TIME_PERMIT": "04184ee9cc5b977f2ad73f3d3031c254f270a98f207f0062c6153afdf5fe733137039c6061cf9e7fa03386e5bfb91e1c8a05dafa1c2dd8d8c4b2ce983f737ce39a", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223833323562373064323630323539666637633863653937306663363937383536406365727469766f782e636f6d222c202273616c74223a202230323439303963376235626436383366227d", "TOKEN": "0411424888238a2e981b353a43342acdc15422ec31356334a80f1dcc1b47b3d2341897ea7618427310501f9634d23e90f42fcd6047b019e8d4cfadb864edc3c852", "U": "04155ba0b309e9a983010847a4f87e3261e52708fb491e314fba3557becac51ea50e92c3181ae65e1e85fcba20901a91fa3cbf2a9cc0b4f0f1690249f593ee1d80", "SERVER_OUTPUT": -19, "Y": "2184be604111030be78b6423b7c03879c9420a7e3d618eccadf8bfb2e2a2f9f6", "X": "186472981d3521d9a821355de93b8a8d6bfd107a8d1ef4f6c1df59d3f923d29e", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"8325b70d260259ff7c8ce970fc697856@certivox.com\", \"salt\": \"024909c7b5bd683f\"}", "test_no": 190, "UT": "04069352f70dcaa134868fde73b4fdf909b1766858aecdbba8096250ffda0eb6631d8ec232e3ef1c10f0f54d2f145acd7f92950f3796e61a0ccd58fb814917332a", "MS2": "091ebfaa542265af9b179b9077974da1d74d39182a5929195fe40ef0d88d17c4", "MS1": "1c21127ea6d24ce1e2b030cf3119bd54a185db0cafa39c9d83369d73e8c63e78", "CLIENT_SECRET": "040c5db105a47888796f8849abdfff26e5fc573b5843bdffaaaaeaa2196903c90b1ad9225a89671705ea4cc093f827ed1f1d0e896296ef4cb565a2fb7ec6b43018"}, {"TimeValue": 1437055597, "SS1": "0bcdb5671827105a1e90c4ed11f5f3f25fd9ee9448f5c92a8ead8afbed14990b04b3e546d42dcc148ca24c085bcfa19b11612734794389575f386cf0f6a9ac0214b9661e2b0ea4c3c5364ccba62370757029b5e217ca4bd100dc3731c794de2708b3a382029d8a3d4a97b508920f8e0f5419230662bf3b603c2ac2d594f0c1ad", "SS2": "0a897a575168807f36af70accea5ff77c355c5c885c1f5dc5dd4c75a60a18a3506c1d39cd81089c7bf80be25eaa5399bc8ccddef005bf33407692d9cdc764d9823148867c9b9f57eb675faf82b117a7c5cbedd2c65475fcedba868d3d455641c06cb1746727335252333f6a6a0c0e401038264cba248648d521a82817bfb7943", "DATE": 16632, "PIN2": 8183, "PIN1": 8184, "SERVER_SECRET": "09c687c35f50adbcb7e6b43d0b41178f5e829a4ea179490548249d6768e52c3103616770997f5139b387517a31739f01625993c35fcca6956cee85fca8c6b6c516365c8a4c3d4e0e69dd6b782eea439309e7f262aeae11e16b9b1d1c4fb226be1dbe9e1de86a51cc19a09091003f73f8084c5338cb87615f9dadea0e2435a473", "SEC": "0413b2a8021b21a31224ea8b86a84ac0670f43121f95e5d680fd5270374dcaa9520497d85bec9459c8a089e4deedf3244d60c52118cd255a2d0fd9d9b8640c508f", "TP2": "04169e32a13f0271d9c42c4fc030bd3d36cf655bbd656ebba23dd59045a72b2eaf049bda76b6d06c0c692df925de48575493974f0e2edfcea0704f6c1b830c217b", "TP1": "041688db30665e7525fe51fa9bbb64bc90955ba92813c56f2808b47fc872681c641b1f13eea8d502f4cd686464f00cd9f5e6eadee3db32d5cc9380385d0e4454f7", "CS1": "040c2b0bb49ca6b4a6abe64e321ea65d0a78ef2345a99e4723023058933edd09d00d59b6cfadfd8127fd0dc8d08be46439119950434ec372dad4bab2a762578d49", "CS2": "04228b6d375a55a03b76d422ac5df54aac92c881a24d5933028133913ba6a239011a15f65ef467bf1c3059bcf72061675b4d330ed054040b709ad92bf9cd327ad7", "HASH_MPIN_ID_HEX": "426d572c1456cc4a7c68d85acc96c52786cbe8161cf6154ad7b1e4979c1528b4", "TIME_PERMIT": "041b329f1f86029917efc9a2c41cb9fb30f30b92e718cd25f6fdda754ff9f514bf015565f74b60b55b06779bede63e1d01348a98f45b2f01e4a514ba7ee8160137", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223532373636323465376432633033316634613739643131306232626666336233406365727469766f782e636f6d222c202273616c74223a202235366639383930373633616330623437227d", "TOKEN": "040f7a8cd01d139c9d89ea23f2936dd5973d07f7ef010a239539f0f85452bd753e1011ee1b68ca1948a3b7248a35f9563c74ecd8bffc746eb2b9eaafd423dcd508", "U": "040879d09baf918aefb822626e1a70b5976d47469d6b256c228d32f728df435dee0979bc4bb86ef3153294bff8157ea22ae7ce4593c02002a49391602c02e82ee1", "SERVER_OUTPUT": -19, "Y": "000f74a05b66d01cff2c3e6fb5d6260dfaabe5029816bd93b79cb3aaa2354051", "X": "007e6f360a8c1e5a69b0eaf5edb6f15c48b961a0e0fb313db29725bdafdce34e", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"5276624e7d2c031f4a79d110b2bff3b3@certivox.com\", \"salt\": \"56f9890763ac0b47\"}", "test_no": 191, "UT": "0412dca32319720126ef1a4d537656ceb9a1f64ce304aaf01b148fd1be7789cc7418314ce3860e174cb7783418c118c567c52fdd279bec4283012beb404f6775b2", "MS2": "182db01d23eb2bcfc90c52f1491d13f8288b2f4289f738823cbbce3341c7b99a", "MS1": "1e447c98b1aa8c2f6ab292e98d0159a37cea034a9ee52c1ed9a350a0e013b76f", "CLIENT_SECRET": "04068a9a7a5f8ff039dc2d2cb382637682958b7af20ddbb10c4154c9dadb873ac806439c4a5317f966220490a69050b0310bc77f4f15044fa2a834f2057059f93e"}, {"TimeValue": 1437055597, "SS1": "140e9aea7ee6e60f564b9db3f04ec26e3ce1a6a8dd8577a4af70bdf98bf98f1200aa51c43b89081b7f851d9fa984d97a50d2c58d1a127a6a1d7baa414497436f1003b7385a44fe88aecd7d7d463d818d1b888c5654d14a917bda5db0adcfd09b1faf0b255ad62fd6fc3e3b5a07f65e5ce27f69f561f3b084b2119c3cf2065e4d", "SS2": "0d52f2b7c775302af47b01f279b04dfe29aa4e165d8681b3873e20473e4a6d4f221a0bf9d4fcb233a7858bd396b2e3ebd47a2f2335ef3bf7e94496a9c8bbd02400d45cffd2053c151692dc21f367c87f88c33ff27eb9990280cdd3bd88f2378806d1a643005b75aeb6f8814c796df98db1d0e57aa212f02cd719fb98db5c4bbf", "DATE": 16632, "PIN2": 4011, "PIN1": 4012, "SERVER_SECRET": "23549c4571bb919814f0c7b947ec0992dde51074ee8106e488584254bcd898fe1a401a3e1020fa04d296a921b6766b983f7bf50e0e9be21e853f8c8113f178911084e01f2d4a16c8d58d73652a1e7b65da95ce4a7c11f27aa98468dee0ace1151eec346a584ae69e220cb9e1ef9e21e23dee3ab3b9be0ff12db1e294d6b954c4", "SEC": "0411d44378630aaef06ac2a2b2d5c6b2f72db842b75e91a0311d0b0ad5796c5bde0cdb173e4c0442318778a201a2de6b56ecdba776fa0a0bb503dcb0e84cc28e22", "TP2": "04219ab43595f909e456ab7af26cb25e78734b5c0cf88b4bca4a4fe1c0aea933cd04cdf55acf943cb70378e101028714a06c719d75192e30bd2a6670bfb338af4e", "TP1": "0410a876f824082a3fc81c786ca7c005304424bd9cb676fc3c0a7f0aa3c30df1990be49be1cf3557bc385aee6ba0200df98807888fe5e213097ea1d8a0f282239b", "CS1": "0413cf18e251659f576eca595102baeda3e2e9d0a263170664cec152f34d3facbb0924d91046629a4a942fbb8d75352f94eec1d4c90e59f4d18e6942a582217994", "CS2": "0410df510ca85ac26b2f746832a4c3b99b4e4e466d98a62788e8821f13f1b5616c1364047f8988f7cbdb164820b0bc06a4797b81c188c9be66bd8bc424e36e02f4", "HASH_MPIN_ID_HEX": "946017c2cd6467568ee959cc33f98755e7342d25739b34da6e858ff408d00279", "TIME_PERMIT": "040487ead8f037fd7e0041c62497fa292997e4aa4d8bd46130db0cb3ccf424916a2154d1cdb1062712a0576ce3b514a384093631522a2deb5f640e43e5f5041d2e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223635343335663935303139343635623630393261623231623635313464353964406365727469766f782e636f6d222c202273616c74223a202230316239646230396631393238383339227d", "TOKEN": "0422d9d7f5540b58993f251a83ad26d415aea47cbea9b96a3a38e71c4e3f2b3c0720c302584742a0d172e05ff5cfc64a03b6ec30d9d3ae74a3fd2b8dfd273f52b2", "U": "040be36f9c88ead0edde9e0e6c5139742f189f37f7e8362ecfbf69c37666bc2104002b5952a72becefb7c740c166e199dff9c94b96dbfc2989a3f82a0676d9ffeb", "SERVER_OUTPUT": -19, "Y": "1282934e9d0694fa516e48c07457773b9d0dd3da7d550f5b5ea021c5de6bbb7c", "X": "140d1f58e882b9660524eb626aa0ab8da8c427cf437144ef670cdbcaf8e020b9", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"65435f95019465b6092ab21b6514d59d@certivox.com\", \"salt\": \"01b9db09f1928839\"}", "test_no": 192, "UT": "040560b70f3b01291489b537fc003d65a27df0309c7dc84b08b5d3257e65980eb601a29d2071d373b4a796e3292baec8a45ffe00cf99a86b22ebaae5b240407eb6", "MS2": "1258f7a5a96f7e603492be6f15c20e75b43ba76e95a8da1eecd6662528ab673a", "MS1": "0061fb0ab5140f42c0a5d378cd403d86fb845d93044c5605c79fb99ee45dd25e", "CLIENT_SECRET": "041398508ebf52bb06560025c607a74b47523be30bdadf2d44fb4107ef6aaee3b11e6e72c8ebe358cf7fa4d32e3aeb6b8bb0e83ddf9526f3821863f42584961e8f"}, {"TimeValue": 1437055597, "SS1": "09233c511d0a3615211da99ecca80bf02bd70cee7cee67a407ff8cae08e7b3c212df43f50ac1ebfc3e56d8b00a6359198cfbf309c5b3a47d3374145f8d7cbce1236365edb76d5ed73772950cfa19e695132216ae5bc40e67459218fa6b14144b0e00deb2a9850519ab4d9eb3fe0591289c106e3c8332fb171945f331f5e88b91", "SS2": "1a8b06b4e6f5011f753dcc308b3a0e8d3f7767b9e551587e432e0e1dc81e4dcf16cc3a19bb04e9d2909dd56f2ea17dcf638eb10abc8d183a4bdccd5f8d5c414d007ca15c0f293a1543917f5ea7538256305827db1d4e6053ddcf99077ec93d9c0d31497272782f17007a519d378228c612f3738c83a03e2acd872710f6fe1e08", "DATE": 16632, "PIN2": 7275, "PIN1": 7276, "SERVER_SECRET": "12c3972bea74d5d941a0826fd357eb933fec672496e1c6ce97b1e47dd31055311a3cef0bc62bec36f7429ba0ab6702a066e1ec88b341351b9f78c511e5d162a71e3feea337736c129ce663ef2e8f33e0a793a433eee0882b6a43d7232a7c347f027d18e083de4d93f4e1ad4d1141d27f1801183d8580196ac6f86619aba431db", "SEC": "040198fb3a322187a19a03aab7af401b40bd8b18ddc065a993c8df6705abc978190b68e8a8997a52f73cbf4e11115dfc8935f3f8b0a8ee35b13d8b4b9da561e1a7", "TP2": "040e6a896d6533df792d3157d294b085d59d6cc82dac39fab1dc88724c6237fa83027060e405af00e46a4cac82ded6db34e737da842fe28ed39ece20f0c3845fb2", "TP1": "040d40f5b0098793b5e62c7c4babd0856c8cc5e358c720feebb733233a34b9c4c51abf4385322e34cd7b6dfd658becc43142bf98774ab8268ef99cdacde0eeef32", "CS1": "040fa6fcbddc1d34a29ecd8d260b8ed1b75dc755d02ea8fc23586c7964a177da0802c60e840ce6cc6654d80ed6b3a034cc54a4322837d444d697b61295a4e3ec80", "CS2": "0412018d0e02aa3491a9785f0cc1dd42cfc9b84b707c01517f02f8f1162bc183422086f8c74bcbde9e887597401d7c8c891ea5811aa356ee1439b3651ef264dc5a", "HASH_MPIN_ID_HEX": "a689209964190381648429d3b780ceb603e41e1903c60ce575aa06e4661c7960", "TIME_PERMIT": "04097806919b5c4365cae91030e36e0d9c34e4498f683b1049cb11626282f59a2a23b74ab554fff7f2425440505447f4818b89c28a007a7cdbe26907a5f33e5955", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20226132326163346162303466623938653635393139356466633865613234333930406365727469766f782e636f6d222c202273616c74223a202233343636383738306339343263323966227d", "TOKEN": "0413f5f2368ac8596c5418b03c37affdbb620439ceacad122fc0a219b819381fa111a9e68073fd08e147af42feb44252b958836d4f42d18ab38e3aa2a7833e1c63", "U": "0423dda66ce30882c6fddaf79747cb79113a9c5302157ac05cbdf162f8d0d398ac115a601cc45011fe88a507332cbb1545affa01f492d20fc1beef3d9984a085ce", "SERVER_OUTPUT": -19, "Y": "074532ae010c63123a8e2f4748a8e4611abbc865a06a1042ec1e3a41d381b48a", "X": "051746f6224f87c36d43e39d9fefcbac9949ac726d790117e63c50dab970cb98", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"a22ac4ab04fb98e659195dfc8ea24390@certivox.com\", \"salt\": \"34668780c942c29f\"}", "test_no": 193, "UT": "0405db0c5b545eedafd2dcd9225db6df064f6470f5d10e6caf38a25cb615ad2c1f04a96b9e4fd8331407c24bd0c215a873ebc45a44d8ebcbb88289160c929271f0", "MS2": "22904109a592344c443fe0466683b5a34d6a313e7eb85edb18d62ba6eb770229", "MS1": "04f40ad58531b2d612fbb265d88bd0c5a1367bc896cb5950c3df45906271e86e", "CLIENT_SECRET": "0402f05e96abb98f122379927dd623271f716edf5df057c2133da2333d7d0564a4023c17b2427531a5768b81061952f88e804b377f4264de2ced61c011f6309904"}, {"TimeValue": 1437055597, "SS1": "1e5ea096f1f1b94f2558a541b5b6dd6ba646baac29f88526a99b0b84f5fd8b0e073585e5cd9013cfb49beac588003088b104ca97dc8d2a86be742bbd5b0afcab093f7f40e36d2aadddefc3c05ba8b0d8ff8795f0954f13d28a699507672e85161d72f5c8a886ed087850011d798deb35c22b7a8621692939b9260162a451fe67", "SS2": "09a049072085872986fa743cbfecbfdae6f3b6b1331a851034f5203b7078cde8067dcd7c3f7ae3e25f7ba01f27e15f0294d39f6c284e8e2c329fef2960ea1c9a0092a9a96ef3a0af3cd46d98b16fb10c29392d613da462a761fdf51935fd6c9222e758ba024c2e1cdcc79233d7e4e6df940dfd160332025054574ff6adce8acf", "DATE": 16632, "PIN2": 7745, "PIN1": 7746, "SERVER_SECRET": "0b2ce45291ff77fbe9ab900df5ba54cefe3296f325b37d8fdadd2d1015d63a001f17d405cb9dcc316465c1c40a0df4d18bac020fddccff19f591a91d7bd15bf507a7b80de215b678bbf9b4e7208760f6c2a681e85b3d004e6437a9182661496a233b426d497066fa9158a8701528e8f8a52c40509ba92bb1bd68150bd0b3c331", "SEC": "0408c47460c7a9fce952ea4261054456c0d2e2fe595009445d463eddad4d62eb0a16dddfcc1661e8c2b2b8ac29e1380f5c4cbffcbd1c779d459341d691c17160bc", "TP2": "040b080f02a6ba8b9b422133148b7fdd9e22085c28ee7529d6f77524c9ee6c0ce5221790f289d920ec63b4028242343ec91daf1a018bec8f62fd6c48c6e3a9b23f", "TP1": "040d22b6da6e376362ba7d2b91f18f428400c3a6cd5c1378bd794570ba2261bd0e0d61825d297448d02289498d3d4379ba0312cde36c3ed6daeb34b39b8e4c3b1d", "CS1": "040a7ccc1b5ff76133981162f2ef923584aca63e54196d9e2b5413b22d7adb6ec809b703aee050d4f338cb957459a7abe292ad9b83009339dcbaaa8c05621fd0be", "CS2": "040480efb24679a987f64f3eab0dc602361b86cda26a3cd98f707c63e2c7539f4202420a0ce0a34057de2cb8980eff537c6a1c4758ce5f5dc5d5938712a008afc8", "HASH_MPIN_ID_HEX": "3b6e3dda375fb8712291f3212b86d39ff0ed46ff15176b91c6c4089be09cb3a9", "TIME_PERMIT": "040e245cc53653c7273eaac75c663991ccd07a3e76f4127a8033387a1e2294b77f1d9af3d1c962a21187e8e42e7631c16ae78c25bff6454527108b12ac94cc3118", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223630616230353265666663373161653961646532656265386532386431316638406365727469766f782e636f6d222c202273616c74223a202233316166363166313331363539323561227d", "TOKEN": "041a44ac859c85af85b932e5bbabc5cd4c62e4e2d42a356f4f6fea907a536654f30d05b7455a57751127a08cb4ce3c6c4fce741bfa603a2070928b5d225fcd6961", "U": "041c6ca0c426a170ba9fec6533845fb76171cf126811d16425531220c48257d6c11a662c08e9647980f7515553da7a13859d65b8f82df761ea923f7a0f466bcb86", "SERVER_OUTPUT": -19, "Y": "0ca59c911c58fe9273f62f0c10d1cc1baca6be3432ad603f407c709115bca7e5", "X": "014d23ffffb93d7a9dec05b94bfd533918e38607269c5e8c9cc39cc2824186f7", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"60ab052effc71ae9ade2ebe8e28d11f8@certivox.com\", \"salt\": \"31af61f13165925a\"}", "test_no": 194, "UT": "041232fe4c439d4ab83f85bee3e79c7f51635797e7cf08c1b36cb3e55bc50c3b2408f6700a56e914e53137e04fc4d0a734f3d6b7cbb2f7e00a5bfe27855673e8b2", "MS2": "1265e214395ce9f3b0a97faf43ffaebcfa6c3957039342bbf8f73bae505b96db", "MS1": "02e9bd3c8fa9d8f47d674e3c304f5140d11b870992b6a0db32a74de9e5d3e5a6", "CLIENT_SECRET": "041946495c8d6f446156dd7ca43ee5ef062aec4649e0062c74030621bddf2810021d4e74c58d6dbef787ec2fdf34e9de9696739bb81ce3add39a421ee5b1a4f0ac"}, {"TimeValue": 1437055597, "SS1": "0ada0ab924c48675c91c1bbda8a2a9b04cffd84a8cf7c46a5d8b1c33877f5120062b1518d97f9bf52b55ea7848867f9cc62c367bd0a921c214de79d7286d86fe0a0c522ce95afeb7a25bc579f90d29eaf91ea23f2f1d5972c474a550818bb98220bff411f8c2235c1d207c0e44bed6f6665d7d0c393ff59b6567e6382434b049", "SS2": "1e8942c1c425fa00ab8e185081af640f86b62bc1b8ef1e0a641516fbb1666b600d9ba0a323faed1a6fef0afd3c07225a0dfe9ccd5e8a5158a94edcc6bf519f980da243751044f63fef2d68389b7cdc924a2e9f8e9b4d10d54b890ba3da9606250ab1982843257b235e5ff3d95b3f7fae3a1ada7303ab933ed618554543c06aa2", "DATE": 16632, "PIN2": 2925, "PIN1": 2926, "SERVER_SECRET": "0b4de9c5d0d3178b454808bab59391d6f57d22752735b5afa44e8ef09735ffeb13d2a7600e7ca806184ac64f4f1352dee0dd6aecabbfe77766852fe01a1cc70b12e70c82af7c2df2553bb2c38b1070da7895b9e556148d7e943568bfcae1a87e1ad641a854c35cf4b9b7a7a29808248d5df7b4fba2e3ee66c78651497ae32f18", "SEC": "04112e38e32943756c92b56c7a05dba4ced67b26c947395124d6b74ec36b19b6d207aedf340134157d861262ded2fe7fbce45e554ce1584f1f8f9e1f2ef24021af", "TP2": "041b75cc39ddb70ac94c5e8f2202b9c5d8a7c5bfa9d8457e8037d03c17eb8552de07d75be9fd5e802cb31f6b3c7a1958eb1a6d3df470b5ee406cd541ea40e48b3f", "TP1": "040204d2e0f9488cb3f45c33a4027febe83cac89efe9ebd42b786ddebeea5588131d24d26033f740a72842622098a6033f5dc87ab2b1ddc47e6341ee009b9a9fc3", "CS1": "04156ec88b685071d89ec6fb4fba8b354fcd21a56d77a3f1e7b19e4ac7c5a8ad671fe57cfaab39bc333fb033260cc96e5a420178c7b26f3192719847cf80471679", "CS2": "040a372b23a9606ebb8b3b00e72cc1edb1f759d38f33b38d108098557fce21cd610394d241a752c6b419593fbe293ead56f1abdf41d7c1f044a8a0c9ad6b919847", "HASH_MPIN_ID_HEX": "2fd18ecdf7ee7c591984455b56e4cf79e25a4adebe7885605285a079e4f1ca31", "TIME_PERMIT": "04139a2d53dda8735657adc6ee09e7d778327e072585a66483e0130d3fa039f8590842853c3e87c56de9d2c05fd42100e6a479b7e935ed5f2ff64b46535e50a6be", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223166323764646634343535653965643065316638336136346332643361383363406365727469766f782e636f6d222c202273616c74223a202237623231363534336663333030626538227d", "TOKEN": "040711a7b84aa33156b1e85bcbe31978ea5b56abbe5a372a171e8118fc99587a661bea08a24079619a598285254aac1f6717802dd3a9f07b64eef4a483258ab44c", "U": "0422b3fef5b6cee4e76fb41b4936513f40167e1ccde7516decc422877ede12f0b414a672168f964a20d8b9a19ec4f780e77ee2baaebc0ec4cfb9b42481a7a4e8bd", "SERVER_OUTPUT": -19, "Y": "205a4efad8232aec1e8a14156fcc7848f55de1fe609d3a3b671aeea32fb6dd5c", "X": "0b748853f8275ce5694fbc25ad8002055c6d437d8bed4f7186b6801b5d5e4ec5", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"1f27ddf4455e9ed0e1f83a64c2d3a83c@certivox.com\", \"salt\": \"7b216543fc300be8\"}", "test_no": 195, "UT": "040573ab29cf8c204b9d6e5935313ec9a78bc368d3cf239ab0fa94b446064562de0b093872eb6bf2ada3d39cbfeffa8e1efe20068b23e78d8ebb1af41b84db1c17", "MS2": "0a78b090acbb523b7bd8e5abf58817ad1e5bb61379a3ec534f5ae8b077e59627", "MS1": "2365abee5ce19da1e9eb34719a7cb8535a34b21dfc167b1de879bec4dde2b6c5", "CLIENT_SECRET": "04237e3b5bc1f61bed3470afbceda91625dc4b0c862acc75c1d507a01a6f72d47116933e80faeb7908f0a8361e1d49657eab46819d46e4ed7610736fdf337b11ae"}, {"TimeValue": 1437055597, "SS1": "1c9a985c819c91dfcb64e7fa0deb8b2427e5460008e22f538f4434b4a0ed9a2110774894d78354a8879ceb81ef34ff2db3ef0f95715f5b0102b8f4cacce7c35e007578b1bac39e805c2f86a261d620dae3368484bfba3ad04f293187539a6b3c013d65a0cffdfd726b231b4700060e72665d66ce68131d72a818584444073f53", "SS2": "0f33b2836581ab5e23fc83942f060905dbea44e019646a192f30854a7ba7b2fe16c869fee0ffe8e9723f545ef6fdb23c7eaf85e0214c20199486875ce25d00b71cbd4a08c5352eda5a3585d4c2ad5191f9d27afba502cd7c01a68f4f5145f7d4089cc6d537d42b3ad3e05e5314d582a58d4d17f13dde535dd54d05f2d675ba35", "DATE": 16632, "PIN2": 3010, "PIN1": 3011, "SERVER_SECRET": "0ca6ec48f57028b21d9d6a69c756ee5d05b9f9122ba82e75847fc557ad990f491ec53e9ab2b07cc7b7a715dc33729c61fb6cb7160d18277fc66c2fb984a9f7580c6859a490611a67b0ba44223c6d085e9877bee9f1af816ecaeb34126eec6bed0480de123f7899116c9b6fa9502c3d5e1b90b74d21e50ba994acfd7c91fdad27", "SEC": "041f54f3b6141b7367d0e822dad15757ca6c5e212373a430da495750095e438cc51c97c463fd05f4a21115808fb2c878bc23a95e91a3c5dbbcdb5c943a8b120834", "TP2": "040caff671bc62cb8a082f5935936516033078897e38cae7d860f2416ecdc0be9306c78b76156935d344676c3d95a7c0d16e3a944e68111bc481eac98661b6f657", "TP1": "0422e5d8042c4b7061d867d3fca23b9df9a9a26b6c9c80d3f2d432871ea620ee281b41699c9fbcd68d61b6f57f2f8590e0b4b0945d5c7beed1c2040c7b69a94020", "CS1": "04027423b56fbf1e10d713c260a30e7d2f7884ba4db7cab6804644f6a2445b5bbc0049820f23175807d481095828c96d764eb95f9d632b253da14f3d5131aeef24", "CS2": "04184cd96405cd1160fd2acbecdc83770c31b243e0d8b3f96f2ff2efbf651e3bf71ac992f403521cb89817e68538a48d3b656c7c8d367f534198d4c6de764dfb8a", "HASH_MPIN_ID_HEX": "241ed4f022020662d9e407903c7be70550975cd57edbf4e19c7e88f856582f0e", "TIME_PERMIT": "041129afcdd7c7c5b1c7949725f779fc124c0c99cb9eaf57212de133aeb8a3a1ff153e4b50dac4877a30ddeb60b9ecdc43a861ea8d2fc7bf968c0c1822e90da32a", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223363343735666534636533383839383133666438303164393034303966616166406365727469766f782e636f6d222c202273616c74223a202230396562396535313465626635666133227d", "TOKEN": "041763aa37c8eb5b041eacac81b97bcfe1d6e0d290e4fa1993dcb41c808cc56feb113c27656447f4f8b5a6406e031d88b21e4aa3f5c4cf940b39a4993c9437632f", "U": "0404b426b59dbdd5cada5529373973caa2c46f3840f6ce54540329dad335a924bd0d3a01a368d7d6d83ed63fdf5d195386efb7eb89543b5bd347f2024a6ec9264d", "SERVER_OUTPUT": -19, "Y": "17f9514aa67e1d041255b60fe006559e4ce9c925c08931021f791da9070ef944", "X": "15d393ea0f03b2ebb366eb38936995ada296ee191d7c64f49028abd783c8b1c5", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"3c475fe4ce3889813fd801d90409faaf@certivox.com\", \"salt\": \"09eb9e514ebf5fa3\"}", "test_no": 196, "UT": "041b9385336eff03b72d8448c0ff662e54c68c83fb3bda06bc2dca773a2c73a59410c37ba653b04d05da96cbc5fed8510212dcad625b9ad71ec4a0d42f2266562a", "MS2": "0b6db675091934eeec6b387fa985ff2d0382c38b9fdfeae8199bb91b6b0dd4d3", "MS1": "1fe8ca49c7233adbeec0c56920777655dff217b75d970789ac7300e5071152c4", "CLIENT_SECRET": "041e48852f69fd0f57afb345d5f29d3446b9f8a3e597d74f4134e4cd5bac5803980d8e32b85598022e514bbc6b4ca702d82abbe45d8ff4032f840408e3a897b52b"}, {"TimeValue": 1437055597, "SS1": "1d9984eba57d17aef43a8cb9e9758238392b395d57b5d4194d77b378d732f88c03a17b9fbdbe67c4da2b5c5d15552d20d55167ad09c24b2906edb902e917210c196630601bcb35985fd35c5a42d0d5f8a77275aa9d91769c6633239f2ca650fb010a746c568183fa040ab546dff7ea9896f1e28bb89fc13dbfa61d2b51826709", "SS2": "010c8df37a14aea87ad8dc0b514c4380e1c37e599dff41c04f21c8bd92485f250ff9fde77d54bdd7bebcf62a8d08320fa43b4d8853cb22e114858ba83a8764f91d59103bace4d251e210fb4e12947c1fbff0ffdab8739018ede6b25138d59e791920d0643cd9fdee74736c4c6ccd7f354ea6438ed194d99a8f3a43a701f6af40", "DATE": 16632, "PIN2": 166, "PIN1": 167, "SERVER_SECRET": "1a19aede2a68d3550bbced5440436d284ea0beee114c58bcbab026bd88521fe81a0e937ee221eefa3dbe26679e11436ced366f1bd3f8ae98993c24694a225c82211e058acdd506a8a5e46bc500e6aa354e24840f2b5699183d63c7a18e26b8ed1811633b53f4e0a56c01c7555d57a0674c752728c6670342824f86248d8585be", "SEC": "04181c57ee941ca4916ff4164c4a0dc5b98e5cff64aac4f2289800f57b42f3ccf0154f8594a12353091db11f01764ea994bd708d09d87590d1700fef691a4282cf", "TP2": "040e15bb9125ff2044694a14316728cd1caf9a6a936b76d411a1285beb921c11771799c3efc9d2ec76a2e928cc1f4771a13f2accaab8ee1902e74ea46220d6ba90", "TP1": "04053ffb362227893f2aa6dad419b32c48c75c71b7f0b8a030aacc0fd17c6ec21f067d6b73f234cc8b5c410c59298bb84fec1439619ed3aab61cc29f19059a0927", "CS1": "04137bd61ae33170f2c3892c245147ff6fa36e734beb3851d7113a8b74d4313b611fc1071ff58653190b3b70c86274eb7741f64ab4cfd04ea7e72be88516e8e6b2", "CS2": "0412840b027edc274b4596baf9caa342b03c15076d4840e36950bbee0ad034d53b00f117dcc515365a8caa68bf40e49b28a81f1a637813dd6faa45a5d9255f654c", "HASH_MPIN_ID_HEX": "8ca9e07cb48be9cad5478c25172366b3541a9339faf185098bb9a58ed991ac41", "TIME_PERMIT": "04238f0d78523953a493adb89bea7c99f0ef11ba2ce580cd1d12b12d9405ae853c1d03ac1694f27f7e87a1c4c2a052ebe14afb7d3671f73fb45f3b21294ee67727", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223935333236336537613334376262386432653838306638316339356135383466406365727469766f782e636f6d222c202273616c74223a202261326135636537343834343034323031227d", "TOKEN": "0410ef24c0dd0992a0aed757d9d97ff2d65137708b0725d03937b1d4b83ac7ce1b0ba02b5ad086787bc8f5fcd5e03a8bd694129f6938d549c636d02cf543e2952a", "U": "042226300b38a8cf29dc4b9aa08879e1cd38370124aae2024f93fb9ebc0a35f4ae08abf0487845de655a3bf51ecbd81bac645edd1295db002a61cffa4038db27aa", "SERVER_OUTPUT": -19, "Y": "0a5c24d9897bdbffb26b719033b1d26e7f33951e89614ce21d84d9b199ca0232", "X": "08370e5519274c2388d876c8810412ae64cea2c7ca0d8975926959513f7f21cd", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"953263e7a347bb8d2e880f81c95a584f@certivox.com\", \"salt\": \"a2a5ce7484404201\"}", "test_no": 197, "UT": "041a2e93aa80e76e3e97d45712a0c6f324e7f25f2d20bf1dcbc70dd984afb04d16058f303d8d039054373979ae87dfbae7d0a17af6e90b83d59f4fcc1d688dc48b", "MS2": "1ea7b9e3e9ab975bce380934d1202073e6f66aad08c49a221987526f8088a4ef", "MS1": "0649a0b8ab6cc059fe9c3ce6e4f92eba69c9600e2c37d439eb5eed0ec95e9b19", "CLIENT_SECRET": "041549c78e482dd2daad2aea957eebe2dbfff947ffb112161857c76faaae49a53d12a1e92f3860d5909c8bec922bb489097693181a47b73c7a2b7f9cf47363f485"}, {"TimeValue": 1437055598, "SS1": "1f25c8338c866d720227553518226625c3952a90e940ac29114b00bbf2cc49d21c5e6e5d281b5151a889495ceaf450ce775004307e1c0c037a75b125222ed2621c55411f8a28d5892d2d1da8a263f249e579caf2f1502500b79ce279ab20892123a20e8b4ea98346772aa59355c860123da247cf1e2747cec5df5cdb37fca87a", "SS2": "2004ee6a7de853cbbbebf59bd26caa2ba1d988bb000a84eeaf81b3a036cec2950be922cc3c1247b754ce25c41b46da940733c1cff3c4cbcd25fd3c88748580fb09085b3a4dd4022d46d02e4de18055a6b1408c217b36b4333f05d5d63a8771711331a25e218de5a8a5fc8845c94ec5580c03eaef0bf848a570d81b13b027684c", "DATE": 16632, "PIN2": 5740, "PIN1": 5741, "SERVER_SECRET": "20c20cb366f466a231603a33eb8b33583e5d627ae66c5bc65e0167c2e0e40b49200fee007fa604a60888a3eb1ecbd354318ffcc96a9ae6a2c3b17533c7dbc2920fb56fd443fae3322d796f01990f169198becec83590d1d9219fb2c06f795d4b1336eb71845b0cf07b0e13278804bc9d87c718f564b18cb96e9b118d081866a3", "SEC": "040bc65344cbbc2e75654cbf97823d16c15617222b88e7305b141317f7943222560b8b5636e0dee70c482d41b9b774faaefcbf17f5eabc81a2a023e68ae6af818c", "TP2": "041c0076dbe4a4d671910457bcba6fe889d74f6a947ce56351c050ccfae49a4ec80e68883d2cfa7680598bb2feb1450c49fb8a23e5258f5af416a73f1f891a5850", "TP1": "0414bcf2b319bbb65efc7b90ca2f06ddc49c3b617b32c7992019760acf111791db16cf7358773953b40e03faa9a760911413c474dcf8ae97775e6fa0b7b61b19bd", "CS1": "040371949a76166fb3f0e18c49d41a99f3ed5b70b0e6f6d4e38c92714bd5fbdf671e8e92167ccf5c263cfebdd04593b15efd27317f237db498f0a079034d4fa9aa", "CS2": "041cf0231bdeb35f5cdb6e32b741607a50a6920f76b673cd713ed9e1ce216e82ba0df28750d31f4103261966590e28246a1c4d545779dd72179530c6572ee00880", "HASH_MPIN_ID_HEX": "6eef0931129b1e09183cac1939f3e9f2eaf99485dc3e07fb27d9d5e2a7f01066", "TIME_PERMIT": "04021154003ccb6479411ccfb88f36c9d7dfbfb280b7b70b9bd91eaf01e78cb1e21efccc3a7e843ad1fa701b3c28d3d628f2481deca6ba9d28bdc0ec19f77eab61", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20226638326334303238313130383239306164656263386564333363393162623336406365727469766f782e636f6d222c202273616c74223a202231313865633361306533396536313636227d", "TOKEN": "04024504f12f2bd5c446e2e4d4ca4b926b3f04a0f2bf2e0e5db419e59ac8c8e26e14095b592c321ebf59a2d4f54ae51bb9d1d87568b79282939f958d392ee70d52", "U": "0415ece13e50a88a68ceb840a0edc010fd02da93f3bd695a7a5ec3c7552c0c417c231c140e749d2286faf68910ade1b444a68ec3ac71b9ef37cece33cc6074b8d9", "SERVER_OUTPUT": -19, "Y": "01e9b80e9f43ffcf7bf98e1f770ed67a914b6e5cb6c98d5ac2703041c257fa68", "X": "203c5a3bb4516d69acc8dfff86b8bfd48e88b7f0919bf38779529dfc672e71c4", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"f82c40281108290adebc8ed33c91bb36@certivox.com\", \"salt\": \"118ec3a0e39e6166\"}", "test_no": 198, "UT": "040de4bcb6a2e91b45e7fda12c1ecc976b56741af3d8db1f85b18178750ec6af2214f66306e7d3eb64ca9a9f9d9f42d6bf2fb9afc0186df36819d6ae517171739d", "MS2": "0bcc23f5b3765d70e5fb954b4e0274a063a2ded11f5d22056a6799975cae543d", "MS1": "0b419eb4c0f5ef725dee440ff65e1fc9ce977002368d47d6e435ca3249d3a0d0", "CLIENT_SECRET": "041be1e5945edc2562c8a2c9f6bcbac7fac68bcbc15878abedbccbb27b4a8ba76a1ac10752912c5cf7a0f896b65b1bbc98785e3137638f9d5bad0ae6140cfaedf6"}, {"TimeValue": 1437055598, "SS1": "0f0b6d11d51c5c4876835390b9bec380f930aaba421388db56af38f9c6ebbac917708ad8cfe55d437a83ec22b7e95e61a43388e34606a9e5c7f3c50fc67a375523d46ef3184004c19d9bf814730e4cc7ce313b72f87439ee424a125d8ae054781df85f9c9b3d3a0e8276314c3bd6dda98d7a323130fd1f81cc7321833ec0a184", "SS2": "056b9daaaa2bd16581fda51b1cff8ffc01171b59fa6f363419615e29f4639bea0368b3fb47610c2d4acce676212df95711e39b361ef970bb7913a359b6d35c2e077bd155a102bb619f2c57fd0a491f00329db0376879914f4714e1be7290345c003f1f1a20e220ff1a4b03312660582ec78c3f662c97b18a056944f166506ca6", "DATE": 16632, "PIN2": 4013, "PIN1": 4014, "SERVER_SECRET": "1e37ad39e3e97a6286b6cf87845c781232c6c1ac99f5bd72160ee0eae1297af816d58da7c5965a3580fe85fd55e4b2e4284e6b6ac19509d2ff8746cf7e3d136e03d9cc30835e32b0c8436575e435be51eb45eb031722d93be7b6b5bd69015bff0e793159e5b7aa777b1e74c27d520e5c69685e166091cd29bdc666d8e4cff393", "SEC": "040b567f94e0335c8c2d6c8167a3d95868a48fd3d07038df196a35c46acc76b62e04ee8904629b1031b7a409366b3e821e0383b0f5726fe4e43cd057477abf21c3", "TP2": "041e43e9495921d3885ed698bfba248f5a34723edf5c15df79f28abaafbf8cfb001ec5c364c1d91a863a5891f1d5e902318d1d3257727d70fdcf2fe57508515f1a", "TP1": "04009a7163b6c095579215b3a2aa02b6e705eaa1876c7cee3c383c564ed837edad0bf2d4b9ac04192586022b0e55f338952fe826c9913930a459dd55cbe49efbd7", "CS1": "0405cce6dd8fb3ebb10a0452bcc5c72bfd085f961875890774dee9d5209347b5cf045a9cf0d7060cb32b2ee11eef3c88630d8c7736c1ae9a28af725aadd05db80a", "CS2": "040897c9cf4ed37f415ce60fb947fae44e435428deb2df0dfd0ca4710c8cf742261fd1bb8d08a4e7bc545bb8cb0bed12e2111f18e8db6b59b6f872d096944daa3f", "HASH_MPIN_ID_HEX": "38b9239886a67326e8cb46dea1d53e1079e689e411e28fa9b16be74fa80211c5", "TIME_PERMIT": "04109d7f0cec776c4781b4adb72ced0b56a86cc6092af2d219511a825ab87eaa8a1c06147a169bf3bff72031a281b6b1b1c8587ccc4ae296781ccd302645576955", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20226636633462313065303932323438386235623834653133383636393361623437406365727469766f782e636f6d222c202273616c74223a202234396432623139663536653130313730227d", "TOKEN": "040bd88bdddc487117107bf03c3cddff0e5bc857ed1d6460b8d78dc1c0e1360a241681600856d3fb6f4692cdcfeb3ab92ba8e38e386360cf817392723070cca616", "U": "0410fb560c630dde4fe5d67b666dbc5f48b058b969a746ea48994c13fff4568be113ef0a3704334e7868a1969a878c3a0b242512faa10c440dfe5e4b18af0e4dcb", "SERVER_OUTPUT": -19, "Y": "0fbd5a46654f1845cb81aebd163b3a68ae51ca505ecfc6de28be47d417e514a2", "X": "1005ab71024a16fde49b4bdddd9fdf211198b2d27e0f2c230c1ee179d0648539", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"f6c4b10e0922488b5b84e1386693ab47@certivox.com\", \"salt\": \"49d2b19f56e10170\"}", "test_no": 199, "UT": "04069f827737845d1701f772feb9c9a3933855cd0bbba55d6a79f44a54afa751021bbe9bafab2729c6c14340a5ca0ebc52c8da67fbdbbca26cec3c238340c22f7c", "MS2": "09f02297d15f60761df58ec9adf6cffb331461ae4d605254a9493aa812d27cc9", "MS1": "1e4c31850f72d3079c2a830f60546d6f975011bd0888da0087133a7a32d11350", "CLIENT_SECRET": "040921c08bea40a4571d1c2c6db0c9bcadd570a539a6c183e7e9554dffb6d7a3f301a7ab653f3f71ebb5dbc5d301e7c59b2bf98fe8233b2102ce4d3ed95b98a530"}, {"TimeValue": 1437055598, "SS1": "0a2e23694b86e8ba3f0046dcedd29ac66bf223427ee74152be81fe10578139b80c819a2bab8ea60de4b9b57faeb03281067bb73cafda0e14c43997eb3a2a6c1622171fd14113b7a2abf3ca280e8ef1304d03d22bb96a7e376e7c56646ab3178102b7849cd5fa99e015d7f284965b0adaab1acbdfe536389bf636ed56316f1253", "SS2": "1fc758c5c9b09ace93ad20ebc1b57c162ff4c28b26dbfa70fad4088a12b6b6901a0069b19e7a0f97fe0116b5308ae5c508d9d58fd7d776e4dace002f3255f4d407efebfd44bb53a9f412706661c5c1fd013556d7a1a1701144bf1ff85d28c000142adbaa7d48bd1c599ffa6b5daba18a4c973d409b050179f8e2de351515f066", "DATE": 16632, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "005def4e415d23a65a94b7c70c3000c9e9c5d5416ab17837bca30e307c6c2c730c9308c844bc8ad2c49ceffad6f2f5098b50ffc6bbdacadf0d4756e91783c70621f72a88df7808ca787520101a6aa61d5600fe3671a26be6ab28c44c6411406916bb9b3d9833dce38903b85c13864fe60e9536fb0aae8c93845087698ddac09e", "SEC": "040b99fb0da53103272dad03f6b49afde100916823b88e44479aa739c35bd0863f0b207c53d68c043fb9e9f7a5bb1b6e170ba970da21d0e67384fc5a85a6c8340d", "TP2": "04087bc0bcd6875cf040c7d7146bfc59689459403eec9a868ce76bf31e5b0b807716b4865a1d8e0a45630acf9cf6bb5cc29e64d8f4359b3c2db30c826b9ef92532", "TP1": "0401cd35f9b276e0a69f27a61ada4daa93bead3294ead790c088633c91782e197c2346b9a588c0fda36ef00fa012980e50ec7fa27a7a54b6822f4f6777714a0e3b", "CS1": "04177d71e2971cf99ab82fa8a53f5f27950681d6d976faff28975d5bd4582e6728177519c54823c81dbb6739b0c3566b80f422a9ef4a081a0acbf4413ed80cb10e", "CS2": "04020e9eed5f0db761e23553374c7fa52186754dfa23f5a7bf29fbca68fde62409029d269e5d3a21fd8c85e8eca3a28470f2886706afa25ca432cf716f9c958240", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0403e0e884ec6a01853a68b363c77806d26b300881a9cbc79c60e7a0f75ddb29fc046cd632310ca77ca55f0bbd7a9f2f3715f6ee8b71021fd7be1e8209d3e81dc3", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "041229e8022cb0af23edddd68d7d6abc049ab9b97376c7c7ab45a0cadaf4cbbacf1d9c1fc92ced80e5c4c4d7f72c4f3bb69a8e38a26513f5c6656392786e8a4c6a", "U": "04213d577584e869b4467487729e71edb518f674e7bbda5c82d87cb5fde8e3ae95209d010b0d352d5a0963f18a5f885a587aac4ac6b1c3723ecdf15684489ce547", "SERVER_OUTPUT": 0, "Y": "0ef5b18c22254d77195f721965c7f037fac0ae754378ed94cf777162c1a7913c", "X": "1896d6eb45cac618abaad13809503609d458dc0bdf00b2c7c129809e21f868bf", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 200, "UT": "041e45f2986425d43601948eb766b51bbc79f4bbc6a5db68024e1056cc243d53da07b2a4ba3f04b9d6b9f360cf7ed0b686281e9ed57d19f7d91b271a8c80d5675d", "MS2": "16a1a6f885a9218f708da31945150071f59f8c4cbac009ea0fb1e8708a79d48f", "MS1": "1b8d228b45aece74b399b230e8c801475f3c95b47bd55d448e52fe075de1cc0a", "CLIENT_SECRET": "041a429e32396a3beedaca9a81767b3adb966bb559317d5a7d4ee5d0d96e7dd5c71f1b753f86f2b1944059c7147cb381b13f6b4fb58d6c4577cd97b9f756f18f97"}, {"TimeValue": 1437055598, "SS1": "11a30c2e1a14a29ef895839e915fbb1289a73ebe22313a88811dc944e73dba8f0f8c390d6cf592bfb5624aeffb121a07135908ead0afebe54e508f5a5fa84a6612a701347c4c50ee62bc7c3b72b5ec4a0b44dd2a5131460032f19021d5a8c3931e2a5a78a62998916d158dd05dd91367926842cd6dfc2d91fe2513032409d19f", "SS2": "22463956475ee5dcc3f52722f0717c6c199bf48909c89e081fd4526b13cb59581e8257b74f24398108d20c265c41292f858626099e800cea364e898818dd90ca19d24d36544ed19c59c3cc4a0ec9594fd0478c21bb55cd991565924ed1524f690fce6b7f669fcdb0458719f92bc26819035f45f8ca508961c0154d3bb2f61120", "DATE": 16633, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "179b6190eda32d4ee0b2a7ccd726babc468a5a69080769cc712b4c7d64b2e50e19e60f1b68e0ee3d8deaaf298d4da6a2dfa55d524bcee32ba8fc2457367961d91b4831c7b50a0ed65abcda742b41f69035a297a04566f6784b6423f6ce9f72ba23cea00162e181b78bc3d8921977e377213b8c9c429ed9712bd2e8f51051ba22", "SEC": "0421679ab70ba8bf311ff2aa2ecdc3c5fc8b71040cbd5caf71ce674e25dc070106069ff6b28142a746eef64d04fba95bda65ce950b516240f3a562a78fe48d8d6f", "TP2": "0421ec345eee6a6c1cc11f8a04672298ccc024124417ee42cc1bbea494c82c25f51de0015dac4b9341a00b2283c1d94096df7bf32eee90ac57b6d2ddbe81c621c2", "TP1": "0400b26ce37f9f17bc3d46f6c0c77e91daf0e85c26bf45a720cad2d748104f49c40e91f2c5ed7659cb8d87ad9e847c3112d504d4a6fb15b446d269657bc35c327a", "CS1": "040b001a727eeaa443b7b49a9e01d387fefc0eae1e40c962b6f2e9c1fe730e0f92199ca7f36525c1eae07836757a0dc9af845e633954dc1baf164e9e83c3bd64ce", "CS2": "042129f2ae45c396486d08bfbf1e76a7f803a7968d6dd0275ddd4460192e0fedea158d63053bf1d3fca7d3be49d5cba540b69fa03dc27cc7988a3aee048671ecf6", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0415b45c18842597f6da96f214d01bd58f87c82713140b2b5865b3c4b4890963b103cca7fbb04626689797d9ad0f4e4e87e36d938b9a45b0a2904aeb45c102eedf", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040a8f09fde0c1e7a6a75fd8ffb1c1eda7a8f75608cf2515458e4579ae5536fe271db53826aa1124f1227fa7235c697144d83a33cf4f42bd2635f35b6bf571f363", "U": "041ba82a3a2be68ebf209986f4159b39d6aee6bb7ba65a4732edaa4c89de5d69d3047f0d3f32ea1032d30e78a9a59a7bbc61bbda19d5f7b6c80add4e626d02f296", "SERVER_OUTPUT": 0, "Y": "2230f2f912231c766b27b09dc0a463c611919b0dbd0fdc1adeb5187c711a07d2", "X": "0a595d21afd1957adbd2355c9effffb67b70d331584369c1b6af42baf34c4126", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 201, "UT": "041eca95a22ebb5aca0d9b8a51c97e1916d3c1348f7b35d323751076f933c5ae2e1f017935931349dee6052cfcca4542581d34c93d85bde5f6124c052c5c30ca2f", "MS2": "16852b403d226a811f66139ce681aef9c8a2c917e3d4ab26a48a8b935c854f6d", "MS1": "17a11402557cfac207fd037cc8090a812316e9bc45ca9b9f6883f42f8cc45291", "CLIENT_SECRET": "040fca6ba70f9cf6dadb13b4007b729dd55ad6c19c982e01a79eb815dc04302c59232ce186f93b23efa3549d1891bfec40e670917d8c4924856993974a32bd892d"}, {"TimeValue": 1437055598, "SS1": "09f804faddda16248a130da27c819240d084700a2cd1390d1a9eae91e15b1dd21846751043f37cd1b5327c2ca2abd4b86bc5c709295e5dcff3c6a78ba6ed3b83150f2dc0dd25bb1c5ac130d8e8878410fa2754ea1266ff93045df61f5fcfb3200f6653ac44dbfe99a5b3507fafe1f51e8d9d9e6c05ec76395f84ea9fae808d49", "SS2": "17671a41105be83be56ffdfbf3600c276bf42bb0ead1ed32e9ccea4f1f94db2f1e3ff04d7125a0c0791966269fd97c70299755f66e934edaa29f38c7b0be2bfa1abfc7f40e8318de0a47339304067b101d159e03c90c0c96f22fc71eac45541318201e929a4bb6ed0beeab8e739fa4141322d08034ceff2ce42ee8788c676123", "DATE": 16634, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "14aca23922ad8638ef504985db7e046d9332d22dd37c06c3073d2471aab9f29e1cbeb3e2eb73abb79dd978a50e6f5d61bcff5e232c06af026b0fabae27c5a99a09e8477c4e3e619c7a5bac052ccc1cf25699af6402f8a48d9cdfd1dfe7e661d520b5bcbf8583466aca7016c282ff79d6746b76c1041116e97110dc7572d5a443", "SEC": "040ac4323e0e87fa10498bd5ae912c885facacc669ac80c54e4fbaff5c089a1d1b0b67ba407dc4818cf07a25254095a5b28b9986df515cef8d3d960e76cdc35339", "TP2": "041426934768b4a2fbeeea733d4fa30494c8ced78574ce2d5ea3ae0e4e306ab04b208dd84f1198ae5bfdc7b7557e477d8a25912ef2de0472999566b3eb20d90cfb", "TP1": "040dde7b616d32bbd6a903e4b43034c2ee94d1b2e83ac72b5461204e7e8af8381c1f20c309273bf80451ba724219c29d6ae895a2f44b178c4a612fccf61dd4a5ec", "CS1": "040b8551740e078655d6c30289386bc4c3296746e3ba7142a3b0ccfcb4ec32f6c500dcf82862842190a79dc0bb6d52e7fff1ce7cf560655daf473db4a99a446c32", "CS2": "0404be9775543d42a6547b570dfb4c204be77bbc3276cac7345a13b907ce0a6ac409948ebded78ec903cd8208bfde14528ef0e5cf6a65f4d8a0d8ddcb6da14227a", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0400dd8c67e115e896ac6ec267b5cbf840676a0d8f4943b62e1ef72be36e89570e0f09cdf19e523ec30192906a767929b87f04fd0130782e96197b9c6e349c48df", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040289b430d5194d6a3f8362a469d5c23eaf0770a7e2e66e296a4634d7cc084a240a0b3ff40e7574a0cae5e503880aaebb937d8a1bf0de5b6bebf8375785916b2f", "U": "041cef086748237f35c26a9587d84f7a53cde7566bea03184840afec114f8a58f00572809f223f36691bc0b2692b8a288ec61432ec6c16ba0660fcbeffc8a40ed2", "SERVER_OUTPUT": 0, "Y": "22849bdae8eff0fb8f894da90f16103eaf70841512f5676e7b7807ba4a7d2608", "X": "151aee4e317fd8662d2ab4aef45532642e477628fe05d46805acc4228ea606ec", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 202, "UT": "040816b357a3262a7717cb16354a8e622dc2545d8fb91bfa3f61b8bfc3a376acd91aa227dc3f1fb378aa3478554af6166c369097b06f5d4923deac1cc61567446c", "MS2": "1c990b48839ffb487ec245e70c475bd1cd1e8257af3b89b1e2658d445ea2166d", "MS1": "0ce6ae28754d5b1adb97f87f8ffc3631b0e989d0e1db861a308b1536f7c3502b", "CLIENT_SECRET": "0412a9bff76e9fe3ab0029703ae6f0f6aebc6d31ddce765f956147610f07d9dbc60866d39698712f67835cdbca78923795d02a9e6c6da8866ea8a386069a0c838f"}, {"TimeValue": 1437055598, "SS1": "1610f0ee45faf5874dbbb7f102ae3a107a1d869f57c0d47196794e1e13bec5c41d5d0e119e1a69995e82f31d480d93f94ebba27ee786cb8d6325f13ab96014e000f1c1d57d7cc78637c1133f6bbc3fc27e034cc8fb5a58004c9b10c6eed59fa50d2bf231cb162c224deff2b26d60f194b7927662b948f114d41620068e9f98ed", "SS2": "18b34be804faaaed5e20e7c5e366569c60d264a427fda0d505243660500fc33c02691b3dd36ad3c7db9d0ed4c2c5a588cc3e01c49216b6bae5c91d6993cd7adb0bb0ee21529c33d8da846eee5250d1ffa8d2ee464b16b2fdcac3e0f20b363ac50f88dd78b21d200a68e053b94380a302f7f8797eb7a9d0409a3a9594c91bf98b", "DATE": 16635, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "22b859281f8ed0d7e970143b1b38bf1da7450e5e9e413c6391a4239060a64864094c11ff1577925a7feb5249a90acadf883608bf2ce2b3b9a9a38db06660c63c175f7e701679d1adb7a8771d62a8fa5de4e00f208711fa0b8eb5ba78fc023a8306f52f61e6922c24326332a1fd18aa78a85dacdfde405866086327aacd29cc19", "SEC": "040de583b1604c35265c3594654ebc32a118f8e0f9d69b8b114e57127836408ddc131719d1fe8b43db72a65864a24168abaa977e437b717985f44900f454fb13a1", "TP2": "0417b244d04cf24096d126616c2c637bb676fbad2ffcb31f13281710e22ea3fd5219acd170069a870f69e09a3e8bdf6acae32e83e31c2cb9bc6ff4d5337fed91ec", "TP1": "0408f36f4518023bc3a36a6af9c71de89297fa3f6d7d8f9ce217ea2a4c4d9e64e723ce97e0f65a6d61e7d01baa9f27899e4c6ba8b20e9c05117c75f7796be71eda", "CS1": "041bdf0e43cbb4f39f0ca2ad73e2f2d70730bf286c03f7afe6fe186be2156c1b060e5bae7ac80cb7a06e2e6475d93eaaca567b7a35f5bc03f490d8d1a4d0c7573d", "CS2": "0414710bd00c7b115a6c60a23f1e794e581a7fafd52c65e272bef69a3cdae7e4350a6befaa42723cc4cf2a561945110bb59c2c4604d627bffe111a9f27c67aa3d6", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0406fa768d90259361bf20c96695bf239946ae817c99aacda77ccbb669266d6b21017193d312553462a929f69e910a5ade04c6af3c32ce592792f7f76a57a2a6c7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040129e7f4269a5817cffe067448d57268a0942dcd2b715d1e658bc6cc13994e4d17314cbbc411ce59e70519921f821507ae4d044036d024fe0da43a98ad18126e", "U": "04099b347389404d2ae54ee8c5e67fb29e2b058b137c7bb5511c62daaaf264d15001f2f58acbac7fe6ec0476b4fcbca185649b42f0ad377aab9ef920f195c541c4", "SERVER_OUTPUT": 0, "Y": "13698400a4795561e7c8d84e800944af734856efa6dac378f4a5e42764b7d3c2", "X": "14ad53738a0508066096f55f1f714cd9495331866883966409034749bc3cab0f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 203, "UT": "040a13497f7e7b0cc920d843296f48517ce99c9759a0f7596b2cffbd6fa1e241fb21b3315ff2e123e0ab69a363402841941d83889e70de73878ea77bd1ab3d1171", "MS2": "0aa1e684b661ca882f54b9ae570468799508aaee750b580adf7c3db99269d77d", "MS1": "02c2136e1f18314adb7c41f79ab85e6a9fd59289b4d90df15203c7a1f8f94561", "CLIENT_SECRET": "040569dd6e56ec02f67a7241982dd820798c4e6a62409d83e1668b8adb3b40358d13f4d7eba5ad8ba1f00e3159561028f3631de06f2f52ad40a80dfca62911d571"}, {"TimeValue": 1437055598, "SS1": "1f7b4daac07bf420937943ffe0ae8ef7d3ffa5b3e2dbfdae6361901f01c124fd1450d217aaa4ae8ce464b50a4d33bbed54a89777cf9b7bee35e6b70497e648d50319c2955f6942382f8bea73a46a131ea0a01d14168ea70931b1c7be036f08c90a5e27845f50f2277cdd07d8a2781762e73510288e9a97248a9b34a60143ba04", "SS2": "0611ae2bc5df032b7c6f6776347e3d9a810f745c6eaf688fb8d3e0f2dcf8104112435db849fc3848b871bee1b8e7c5fc09fab0847dc296c6f0edd7761e03a655198046c7ec28222d94f10b12db59ab458fd26aac764557ebdba58e4fc1f82fa8021b861a2ce7141c69f2ced978a2fb82fa6ed47cbfd866537386c75ee645845b", "DATE": 16636, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "0df01621ec587171cd670858a8d4778aff66da87cf80a684adc03b9e20e9ada020bd3bb5051156ffd616064a6b79ea9931b9071f95331dac494af20d98bf03301f60da36c98fe40939047892d72c97035833a254620f634f20b1a67dd27aab9212bd0fd66f0ec963fa089c33d3ef5abdb087a9ea332cfb31594f0521ea678297", "SEC": "041aa55b955e533989324b952f8e4292ee587d9ed58786c1269163e2d69d15b48e12b9133a07247d26c5f7d27c4c10ae31328d0f40236ebdcd9ac470e884375891", "TP2": "040a552bb9730506bed2b44252b435273b89385462c8639408ff9fead59b4de14819d2c29dfbbd5fa052c6351dab1b5e50e87dfa7b514c1ca766bbe30fa5157c17", "TP1": "040990d9422cd9b0e2fa0adf25f4bcac7060d851828e0dbf1030bf35f915cd928819b94fc9df149d413cba5e56e2ec9e09d380f02c05fe8af29b08dcc086a67efd", "CS1": "0410eac9d5a0a7fb9f48a18c318d9d2fe9f02b58085afc99d58a3935ff05ae2de51cc04a95d984e3c579e1e4c951f9045ef4021b3379dee55769d4ad55dea07e8f", "CS2": "040f7a0f7391e8310397af0c93e67091af63f1f4f081f7b3b5412b9efcf13ad4a2219d167f07e22497a9e2aa93c29505846a69ce64dfcb89c4831c5014de246f12", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "041370972075eab58467d77537b0544d9ac76bb2b033287b24cac8f1d88a1f2bee19c2ef94879cab9cdaf605d6a403e4ab050d88261fd78909d6718a4903ea34eb", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040d0df086691bc0347664e2bfb82f5c4ee72785f5cd3bb04bcf40f2e8b8f16a570fea6a5d2262a6bbbabebf61f3eb5ed0e7756e7dfd0dd495739e5df911a74a4d", "U": "0420dbdb1bb205efd2b97fcfa0095e759d45b5dab980c9408bce72f4e1d0654b6b0df08662e82a6ddbb159b39eaf25c27f3ed28387442afe3d8c062624c99c34e8", "SERVER_OUTPUT": 0, "Y": "1011307e2e980e21b6c9fa368d5cfb5478c686f04ed6d25cd8436edb6fab89e2", "X": "079a0b01f2e1f6b670467f85395919df2c0e096655ee7dd6af5d91674c9c456b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 204, "UT": "040c9721f1fe58fb22f5b96c9163196135104a1150adfef354304830551d6701330de86ca6c86d7cc5b4be284c591fe2e9986150133e87dd99cc72693b2ae3522d", "MS2": "11e934733051b383816725e6f8a9794c023c912976c212cd341649c8ad9efe7e", "MS1": "04cd02a0e13319f4eaa735fc7388e34f4d61d2957c89f8fff63a0d1b3f5ce40b", "CLIENT_SECRET": "041ab1642937308299d945986cc5c3e9703b91873e7eed56d0b94661b47f46df320185ee8b57f994688efc021c6c0d0a9a7d4f755cfbd2a888a01bf75ff0e02fd4"}, {"TimeValue": 1437055598, "SS1": "1cf3f2db888f84146fb2df0272414a59fcccd1c89b6cdd1092254c1ba293401205d86703451491c314e64dcbdae5d13e1b8eb6ce3cb25bc8472d583262081b5214414fb698223af49872043c6159348a9ac3e615ae196398ada1ddcb6f56f58a1bc330405d834dad608aa670c7efb564e0f15ff8eda65943b8673402870ff3f6", "SS2": "0a8b77b370fff4023f6e6511adc95c799062ca00114517c21a7b739e140ea3af0259cd7dcce2dac33816b4c45e4c0ec4869b6e39da56dd097335934099efbb0b00703ae79b01c892b87d81405ed249bdc64958a93bb2670f30ea467de3131b75100fccf3f5d996150f396811bacf3f92ab9e366b974c5b110fff910e1bb4a400", "DATE": 16637, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "0899f0277aa74f663e3ff9860425f9300b806f72c4f25193c7102a549227b768057a17a9d21e0f704871eed3aa2168e786086946b8ab546df1356846e5e2a72b0dbc4b379cc096cd8b1607246392648c53ed0e462a816c6a90fde0041fddc7b01d143f2d2444da3fa71c51799a78b960b7ab61afdad0cd9c6dd40dc2af702a4c", "SEC": "04132702066cdad05ed7ccd2f992baa87f2f40ce865ce8c9ab13975825b81be56c0edc4bee6d3b6034f57a758c17ff208ceb61740472ff6b1a3ca1b01bc9173345", "TP2": "042199be248888203f4e9f781724dafe3a8405a8b3e2b8b28016583e5d7344c8db0038951f41999c66daa410c3cb2a4188c9ca1aa8baa81d5cc4adc99f6d1f7717", "TP1": "040f05900ecf736845dcbb0636b850c8167d3106a73389f67eca0a8f77caa54ae521b0cf54fb15255e1c4fc6f983ec8dd6608847ac67313f7a274b869f0a18e1ae", "CS1": "04222d3839a6f2dad05e91186be959113b97774bf9ef8294fbdbcb9d977ca5eecd00e61968ecfdf881538577fb6a9e7c89c6648d6f53afab6f8c98e523dac8720b", "CS2": "04022481e483e64e6273f19f24286012a23eb6c319368afc96bcc4bb22766b10651598a96cd6cd8c637490de06529bb1829ddfed4c8cd5e56211cfb5269b6d79c6", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04049dfbc5646187c0591e751b5977f40cd4bf7f0931c6da528994cf757998aab404cf47759cd2d5ce746c6e1d8034f4b0c4333f94884bf03a3c371a471bec5550", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040932f5f42cce19b7caa5eaf1f94556c4a30959cf55cd2d8a37a2e9b496195f0a16c673a8441500c3447497205a6de47da0fb4c3587d601e4d19800673b31a69f", "U": "040364258447402db9fd21e51c448dd93164c50de2a5428c279105f69eaf5ac4cc149bb8add547902e434e94c3c86dcc4763c832df0d9062b73eac3d4dbc470c49", "SERVER_OUTPUT": 0, "Y": "0920110d2781820a25bf8cd32fcaed5db6e0b77502303bc3fca3239c338714e9", "X": "0a574aa17eb0caec6d5ce7902c9e788c452cc12dbaf441c9cc6fcb3befca48c2", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 205, "UT": "041908f58cdfc38b595e270583169e8a82d8dc4949383e625b7e02b014ad827b3d194cdd5e72d8ccccd800a3eae9e5da23550c2735eee1c010136b8e83741d1cab", "MS2": "1f05bacf85e80000e0eb550a6e41d7408735bcd66c569fd3377554634649c1e9", "MS1": "16053fcec64fe50bcc0d6f7fd522f9ba70053d1f525cbd413c1c4c0c197e9ebc", "CLIENT_SECRET": "041b82943bbde4cc96ae042093e460f990d1cd3f2bdc8a6789ad0f70058330e45b08a4d3cae8033126eaef732a7760c0423872dae2c8179ee5b3083f8800bc7781"}, {"TimeValue": 1437055598, "SS1": "112c134d421cd76eac04c9d917cc334653b0a7f7badd0e08c48beb8665f14a9717ed0bef423b14bd4770e78389f9bac4cc36da91b2cb7a63cf6dd2ef3d3984ad061c975ccdc49bf45754ecf349c2ca1881437dd409cb453eb7c5555eb7adf84a094502feafdb43b336f77e85776952ffe31c0a140d6ad20c2869eead132456aa", "SS2": "0b8dc8e3b5dfca7f1d7edc91a0210bbb25929637baa72ef1cb98282a2e3b1a2322e6ac96a7351492f37c737fb426af8a0150fae89acea22ca15545385337dc2703daf3c5602aac5e678756484ffe845909306a71e263a5eb1661e18b48f9731312e2f6bb983e948601e79069ff90cecf73e31b315712de11d01132d2e16cdf97", "DATE": 16638, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "21d354176c3eb38fde06b65d467749c5d8fb9bc2cb647d9b854a4d1237e09e2706e4a48c2617d386c65c50aeeb2ce79e7f73595160fbcee54a1b98c7dc606738192f333543477f4305aab77a58bd1df9a76a74553179411a62ab1a6a3dd207f20270dbfdfd536ec723099c9cd0110cd245e60a65f02cb4b989c92a2b3204b0a0", "SEC": "04148a451d9b07298e8f594c0a6f18bd6d8667d81adef7fd4b060bd349991f1de221dfa2382b767a899f2ec9758a2b3c5ba615d0989efcb4bab68728b1aea38a81", "TP2": "0402eb387dde82462a2f32729cbd16fd5faba4533c62a2cd5da63b406f1265df9220fec0e7a7de8e08d7fab5b7825ac7a879163bbb7df2f23853912c160c9ab483", "TP1": "0411350dbe97eeca12a6644c756dfad9cb20090c506232d42caf0638acda3a1cd21c1ee79acff3a493fb750f66f7f771424eb82dad2eee62c342597840fd06c0fb", "CS1": "0407aa63d742f5f426daa908b535f14d02a837c568ced5d2933e6071d87d68aab20796541c1b749f752c32a9c95e17099dfc0ae5521293ed56c13ed074222ebcbb", "CS2": "04001c1072ea069fe4bfaa5c111feef52a614773567762578d66f18d45ba47a673103c120e3718dd7637e58442b4aa6968f353cf149ee8a2f62f9ed7bed682c2af", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0404d47edf5e9cd5498520e7160d78959a6af64e13268e57d182ad7c550fed7f00063508606b2c568fbcafdb192e0c1ae0606c339904d417c23e3ab4d5027aded9", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "04133c0ef467105f66a9e9623fc1a8ffae284ab5785bae796c06cf871f0a03287c0566d15a7c79ee78838251df9d9730f1ae02b5f7bdce8d7ce896818d300f60fa", "U": "040a49e6c06c2e9e70b920178af53f116a83c2a57cfdcca03d667e2ea6aa8a92e015787932fb631db1347a32141a22b0b4c2d810326b65a57690e79b93be7b212f", "SERVER_OUTPUT": 0, "Y": "0111a281b780ef56661c25bbf61f9253ce3f8a126f971455c3bb845eb80425df", "X": "075e3105819940785b8f8ef70da101780a47a510a6a3f9dd63ee0b529d574070", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 206, "UT": "040c211ea354618b4f8c74ee928118cee32128b8f387f09dde651007904dc1a2d00b0da5d2ba8158ae7c1b2de5293103e10f7261dbeaed12964401b016328f5b4a", "MS2": "22a9af4944eac209b764a8ba0f641b1f736eedc5675da6928b1483b8f28e6d4f", "MS1": "02672673d816994d7f37ce4e0a97c3a09020db021c2b9b863d3eb104fe5ee86d", "CLIENT_SECRET": "0421cf9cc6b61bffef9861d43b8be432b9272c59d24eef03620322225699b7f18c134246dcfb7f8cb5a614401a5895004b8df077da30125cc783affee9a1e2e378"}, {"TimeValue": 1437055598, "SS1": "0c2dfcc879c417a3331b227a220320becef1dd20bc7cbe6c99bc929faca321fc21cee37facc846d778ce8d449351f1cf46e24e3bc6787a98a8d710086e17dd261e653bda7dc9c98807340ff1bdbc3af24d37339fd97e6443134bc9893098785a1d3608e715c3df0d004b304b82f5962eee94704e850e7d7581a3544f19676c30", "SS2": "01b6003df5e64480e716e2c4988a4dbbfe3a005fb8dfdd8b54dbf57ca82a47b023ad9f9f6a4a02245023c4a518906e485799100cbc13da711ac467f788f9a140229b51f09640ab7d4e9608edc1b3de8f12c46a320e542a1859b00cff19f8b6080686a1d623062da3e6fa6920fd109da878863b4155aabe5c197b9c0353515d29", "DATE": 16639, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "0db395d33f6ad65f0ca7c6ff6b757910ba0a7106785cc021a844e3d76523313f192c32a0ca0c3096b1cb70dbac1d22e7f147511accfae49e04d944f3d8cd42c1071c2c9dc119d8e271d854302969f80b8b716def168994dcfc8b79bb1ee0cdf6151ac149eeb6a77769436a24b783fe04e5ebb72b777bb279755c825aafb4c9ea", "SEC": "04170c78ff50364407a175dbe97b6e50162744bd8ff77e10bdf10bf35349975d8423571f947ea02bada9109ec92276d6e539fea7ed1d852f145512ea6aed8cbaa2", "TP2": "040519cd445b06142dd342ff6ab416bfc5ecc7cf97d9da78702eae55008ef646cc158a0800d28dea8eb971c20d687acc7906ecce3766b0baaa8368187ebaa66402", "TP1": "0415af0eebd821a5942e20c986661be332c93a58d6c7617dcb9c98613d3151506e0d02576c9d625a091506431b0fdf197687fb580fa5636d60c8236baf49492e33", "CS1": "04206fa7bbf7dbb5b0bb290272dd0bb943b4f2b4d0a21f6b1684468591bb244cb01300c28b8edc47ff2b8bd40a9677474e33e5d9d4e53ca2ca54c87f599261b244", "CS2": "040ef0d08bd6cb7d39cc07e7cc38f45f886836290f3122b4df3004946e1eac6fe023bc5f8c20a418f2f3a4b055d3eebd08642417e417da32454566b0d94db9e5ca", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0402c5b21df96dec0d1deec8de23d6333025bc8baa94050857b327c07df0f3730420142132a8c84cf58268802a161dcf6d968d84ed1f76a5af9a9a2cbfb696a8bd", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "04106db9ea3505f2424f793735bbf96fb02c85ffa6e63cd6fd6f72fa3e988df74b0c99eabb1f1347668a3da47a821a58b80c5aefab9f2c526861d31c91746599fb", "U": "04090ca78a15058eceb00dccd7432c55b204e291b7063cb214c5e3596dbf686f9d2175e17f6a26e9eae12c0e14e751f25edc83dc8f8604552ee3fa76944aed7e75", "SERVER_OUTPUT": 0, "Y": "1e78e32cce43c6bae8795d2a2ad730916afc252a8445dd6b887fbd55e826c169", "X": "01216328811ea0b97672d520084786fbfe7e1e771f96e8836a0c2d5fd55a0e92", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 207, "UT": "040b6da48b2019ee3fb376f71aebe810453a9c533983d3c119e9c9986d7f71b8bf0a632e3c4e1b528439449e92d329cccc053ac8e49491c030ecf71261cbfdfa14", "MS2": "19e7874aa0bf353f77cd1207e6a7e0081ebca34e965d10f8ea53aba1eff3bb69", "MS1": "047a35c476cd500bc648cac4b8c15e48e5b0e833c27afa56560bc71461a62a2d", "CLIENT_SECRET": "0404c211c5f092c26b1c95fef2a559a4cb46a4eb0ebd0b1c5d37833e699c0a3e651e76d9b66def747683a20264de41db150b2f6092bec00353f4d09553b35a337b"}, {"TimeValue": 1437055598, "SS1": "0b036a6a0d6531950b3d72a2a0278e11682a466a357d9d139ab30978bcd8cfd11b8c5de8a61b58941448885161cc5a608e015f1dc4ec9e10daf0e1048965c2fd1d7411aef8960d5e0131b07477fdc50cfeb01d8f1477e327fcfd8e517d918bf81d98bafb07f5ea2210da0f4486c2a1e25d9ea5a790f6dadb0b6a8bd6f55fa917", "SS2": "13c337278ddb115cb5fffc1938f1734bace38644d6166b82c8df3ef947543d0e090694e317c594a7093f8019e6595a3286eba3cc9339eb4f8ff3dc82343c81f1225b32dccab49e32c88366ad38952d8ed8793f3fd396734415295a214a3181a30d5807e8e94ead8131dba1cdc5f2c52031e2c60ccea86ad52c1ad7ad98732d42", "DATE": 16640, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "18971ffad15df4f352397794c2fe075ab998b07094440e3a1fbb2407bd49b48223ce88de88257de6a2fa87d0741355724a58d0607a94dcdbb3295e010daee3e41deb80935852183b64deb30cc5b75c96bcd3510fc8fac408f3cc058903af4b221c209840919998c10e45eb56cb63543413defc4efa34a6c8dd16c2d91bfb0c5f", "SEC": "040b702eedb60a9a4a0996e002b6d59a3b963d2c78b60eba1e546693eb99f0cc8e107f186390b82691eada719dfc570cdbc2a532a219f09db6f852b268ff8303ad", "TP2": "0420c0a69e58a6fa615eadcf3f89c28298902b8c56f3f17693edc1f86edf539665112dd66843ad4e11d297e0e78d8df306bea793c9de404843ae1a6ee71296d928", "TP1": "04035267471120d32d3a47f81845564f812e99e5db0ad80d81af9446404c070d630602e374839211f9826e8c78d063094d56faf3bb8603e210ef014487cd4b5ead", "CS1": "041f3221027edbcff26710d81cffa01c28167e04fac1d75d3c0e34115d82c13120136543a638bba5ee24d7bce618d9870938eb75c820dacab443f7e1adb47d6b68", "CS2": "0404d12982ebc0fc59d98700c543ed6545eeb01f7295ad0ad517f9280005e84f13223de2a207e1cc90b0b43ac47366b773e818cdc8465a536cb65dc82e2e192ad7", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04229bd6608411773e77b51bdf20e976dab7b2333cbfaa761e946230eb97ee969b1e237f1023e8ed64ebe65f853b81ef10e9bf7dc8622990568a81d5b22a67a848", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0422bb8199883d4186b2a62c17cb87105bf52ca84567b849b0013633c61e600fca217fb3a9b90f3ae26b64a556a5dcfb39f161158f0f9b5dee56fd37f89512c81a", "U": "0400fdcc0e8516b85f4333331bf8d412482352bbbb76d93c6244de86fba9c6351a1377f7768bcfcb1e8eeb158c6f9379dda05b86bbf834f8a09588255f583aef09", "SERVER_OUTPUT": 0, "Y": "030280d22a052f5c158e16e5a955beb22d3a495fc5fd649467bd108b47974979", "X": "119a92b990d729bcf3ad39e346f9221320df88d733ea191b5ca6bd77e506261a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 208, "UT": "041f1e76c925f226baa16caa6c58c0af540dad6562019922e3ba54fb11966bcf38159ae98a7e39abee05660de07b7af55e24224691412a10aed64fd983e3a3b3c8", "MS2": "13c2093e53f1405729f6bd0ee549897bd93b54f108799b252a2616ac73c885b8", "MS1": "04ec2454c5f51f5929d3493f5c0275f8ced97a4f4e3ae70114b7b7ee5b715a03", "CLIENT_SECRET": "040d546a85884eb5ce598339386a118c930a37d1ad15760f9718429a5d06fd07372069c0d3c6e15ab9d8f6c0453232579217b09457afe68d730ff4590895b89d36"}, {"TimeValue": 1437055598, "SS1": "16a62bbdec450329406ff57428573cd185a3c055e4e51aa235a1c9ae494c3c9b1251c08a3d7ab48a47fd428bd5e2246b2484aa983ecab944ca7cfbba6304e2d807cf7ac382a87036e5922d81cb83282b6f18de9f0e32b34e34e5e51deb08055c183bdeaa491cdd5e98f7521ec079597959645276c0888d0af3c5bad933884c17", "SS2": "0aeab61741dcda87a52a3a0487ddf9450f1eff56ecfc9b4dd7a744bd5a6c45571fa623ce489b9cf8ab5cb9e9c89455344d698540c84c6887bde55d35c880470201d251ccdf60e319590388e60d908a1af4f3599dd5c05264eea8e9be0996dd6a1b09190d86d9a668ca89b642a0b71712b993a4be1de59f43028009b867886002", "DATE": 16641, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "0eb308f65b58a557859bd16fc961e533c2fd734722a53130379fd29590e33c7a05c38169ce0fa161c00df555331a5b0af8f0c2a6f545e4fdc5044113c23f9b0122af88ea3b0da3cc9e4d8c1b797149b10923c94beab5ed63d15395ef43fcca6a06fe5e35f08a5ae39929682c92c07f7f08144488037cdcce9a2f9d162c4739e0", "SEC": "04059bf0bde3a601746bcb86644b83273b417a05f0c6cc80ca8d14f42715429dee10c5e170ba417fc9ee5418ab4a8dc05350389fd7541f2582b8054c62d177f7ae", "TP2": "041b8ef0c4b8455dacb750184c698b0ea4221dcb0a3a13557e47226d36858ab7361cb644d0f1ec50c94eb35618fe621cf71eb11a124aa6611ac3b2c657ef144542", "TP1": "04172b9352c87c10bb958f1ac068a2b6898ba268907adca2c7088be48b2ca40c101b2be62c480c9e0132fa539def15afa32be1dec818ccecab51ae31f11cb73e9d", "CS1": "0423a2917328a53239cfb8942e803a5e2cd771e607c022ae1fbab3ca8990b4aaed1371f7fa067d4bb440aab647099401bf2d42900aa1c1d12a52d80a7491a60821", "CS2": "040bc0c1691e82b10e162535e7177b91db91b06609e4f540b58f1e7a0ba42c37320401ee53b453179697d88e4f412dddaf244f20b74d156f316d29a41b5b3d20e2", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0401b3d0ba601300b3f6687a3e9f03eeb1ff980fa30c39cd5fb72b974076f694cb0491a7de0b55949a1dda51f4c9521e684a39529f4e7685fe7c5b0e8612f36651", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "041e99da53eb9415faf3a01c50b6ccb126dfe1d4d07204f6c04d7086719a625b1e137845333a7fb6a11681b4be62c231f8523cf6634bb30f6c0cbc16e150e4e41d", "U": "0400f0859a36ed5c0d34895b21baa9d9bfbb5ecec43d1ac04eedecf0a409a381ce02065509eeb6930f61f057b43279c5b6a6e7ff8670adb5d3d93368a35b9e43af", "SERVER_OUTPUT": 0, "Y": "1366b9a76c88bdeb34cebc419019ba1781f0e9fb431e7f8b23c7bedd611b52a4", "X": "0b598d46d307255ac5e8f2d1a9739a0e491898ac603784775e17762cfbd40034", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 209, "UT": "0412450b4d0db2813fd4aa8221eb9dd6338098fead3d436e823fdf15e839ac41f40d552dbfbe7998299634d9f7b728afb08b1ffbcd3bcfc8fa43a60658c3e85782", "MS2": "21b8fa44cc9c300fa5ed685130218372bbd7953ede25d9ceaa84632712c7c74f", "MS1": "0d799a540cb64ce943a46c00ade5a0198998c70ef635e5d293ec71505ed70137", "CLIENT_SECRET": "0409bcfe6a2fad0703dc6049da37f61d016947e107e2c3090a42ba63352629876709b8d9dcfb6b8b85802de5ca8f6ab6d30f31ed76562acb9e6cb79c0729aeee24"}, {"TimeValue": 1437055598, "SS1": "22a7b3a723d2fa3000f645fa6bae9c009f6c837bffe26e7de0707ebf66a1b2241b5355c3cf52580cda6e93f51b93e7c105480ab98396866e5328b53052e75eaa01b368a58ee0950979981b6776a675e8758f9eb4cdc50920748d8300214c00930b05e87494f6a781aff974a5202898c39d126132d0fa9d38f04f1231f22ddb63", "SS2": "12a87f67302b50023199d3feba2ad889aca6d5fd811dbe247003f1fcf9e64d941de3dbe1b0b6ca00e746683f2c9f56a877c314cb0b7d0ea65ec20f52746796a31bfc1058c2b5c39058786060cd63575e3352a4ee2dddca56ab1362b8249b8e4f1ffa4c6e4d9f5954e28904174ee1bfce9c07648682292be730e19178f3d0b898", "DATE": 16642, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "001f5a4f86243e652fca4e0985d1207f1ded97769fb1e7e524c8a081c963b40c083cdf1b74af4a7a411ae9dd416320da9536f08fce11a06a4e7c6f0b44c0aed30bdf99c89171cbd1e4ea93c974a53767489b2fb06c5ff6c21a84012e98bb84361c60f1c84338c3b90029fcffd2021a0ca4325cbffb56e49e131fcf4f4a080248", "SEC": "0408437dc272f5c0b14dcd7c2d8353820b7dcdbee1138afcf901000eaeb671c1b501724817d970aedec8bc26e7508003594b794c61814e87366703c4cae049d1cc", "TP2": "0415a74418098e318a199a4763d0b5676d522d69c8f12221120ae5ecc48e2069251eda8c783035b82857e9a67bf217263f362ea50e8ec614ed775314abeb4ce715", "TP1": "04043813860e5817d1ab0da1f17a24f81992c26d127e7ac7ed3eecf0adde3168c012f58d50cdf47a1d88f038304a4fc571337de3c2d32ab8b9dbf21bb3bcc8ac50", "CS1": "040058871d61e6e289690eeb820a13a0aaa1dafe8a1ed40977c9a6831be010c277213ae17727a6d3467c4701200c47ed76ec536679db9f797194434221380921e6", "CS2": "0405258d16835d298b53f4543d6a1555f96bde7594399430d4d50f1f9eef46ea5f19f9e214c0a7437f65434ba8fef0f932bb28470c0c7b4f17bff7618989511544", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0421177211d5dadececc17441cd6115ec117322f4ae342fa73df3edd88d7f611fd13c1678821fdc5e98d6dd6d51c0d1f081eb560923a4eb95e0971feaf23052c25", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "04086f796e309ef7a1ee4f22c5ac73c6594b019bab9bce198c02838bb6aa527ded196c7e15899914875b0ae964ff3570db3c443211d957745d8e5847a6cabfd06d", "U": "041888202fa015c2d03a99a9b1a098f968e2f9eb6272501d3631d2fd77b970e7eb02f5e4dd060ab95efce931b695204829b814f261ee0f0841ba64911beefe9b7a", "SERVER_OUTPUT": 0, "Y": "0d3efc40f79135d25975cff25c1482672f133949fa298bcc5e06ce6a5cb04577", "X": "17eee45c6cb1fe96e93204073bc4d26cd763c23254fdc2917720515074a6d9f8", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 210, "UT": "041425a805bead8021dfdf918a29e50e95d4002b58a85f70bd97ea9f5a5855efce1fbe3ce483dc50ceaa80298ed28f72e64545e336234dcec0c9ca28fd0f7858ec", "MS2": "1a5f359e62832ab46215c88abc9644814157573f1448435a5936fb2559f53c34", "MS1": "23d37e18efa2ca3cbcd1a393ad747c15ab65ded61e76681f05ee016e585125ae", "CLIENT_SECRET": "040d175813be1febe5ba6cb8f5031c01a23532bf56b136430bf556962f8d3bfdae0ec3102ac13d067af07b81942f5afbeccd2a4a6b7bbd098ef0db0ba92060c50c"}, {"TimeValue": 1437055598, "SS1": "1585b8b62103577a69cd89070543eb5b427a30ec3f07c4c0c64d308324837f8e08d46b3c105a4ab4e9ee30caa539057d1ea149ef92e4c8e80a6d59f0e41816f514f31f5df9ae2e6037c1775737d0cac3de9010708082d4cbee3c6522de502ddc096104cdd4254ab7f7f1a0740b90e255d45fe48be13610a493f01d39731c42d7", "SS2": "001c7deb089f4fb189cc4b4fc78d8c44a3a88441067ac0d9bcd5ddc945f01dd81509715bd5efad50e4c248917c7ccf29e3bd4dfc52577a2d344466b19a6509d11d002367e39cd7cca440cc458a9b73bf1b3ccafb192dd79828b3e369243d083a23707c83d47ebc0aa447995ccd4d6e5e664647e904865941fdd597ac27e86477", "DATE": 16643, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "1a65f8c1f7fcb31c242fa4be4f644a8b46beb866969bb7198cd510b8a8ac09c5081cd0f01c8010e0af2691f389476ae3ba0febd95b2d3185515c39f927e52af4128aa5d719ffa87a35715ddeb6b55c3a1bfac0773795b6da50200d3e77af2eaf143567289973beac5210f5251da0afbf10b9e601d33b77160c472d4d72f2319c", "SEC": "0418006bc67935b0158122fb1076dd4554ed57a1ed7a9595f4a5ba2553f73143e915f51e00ef10aad38aa3d5cdb41d5e3a2e06482d145196879a40b60f0be0d672", "TP2": "04136f0a08c803bd16b3992d99f3aedea0cc0daefcc924d72355cbdb09edac9b6b0ceeae1ce183fb333be8f56e7c9c63fc9b66bc40043de7c9c28f126278b6ab05", "TP1": "041023b4afa540da01f23816a04ef898aaade2e630c80d2c399e4db8f8b372c2c01c92d8dfb6d745566d67d5f2f6e7103b1b8bf994126d593f2180cd5972863077", "CS1": "042385868e5fb5cbc893f7f1a96f36b79bc49f85ae70ebc1de9997110bd9b8bedf0d8ffa8e6067933cb0d48f28e1d9d1e5f62ef1030123842126d08310d390fa87", "CS2": "04001dacc79add94ed6ebe2378a7ca779f92d80b31e563eca809ce22d67fd613210a29221ac2485e8bd0ff90637c7d1978dd9d6d7d4ede873ca502c2903e3730fe", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "040808c3915a508edaf36f8a6cc8f197b1b95da293b118ebfa8944d018790d6a630973a757590c4794bcb751314e878db0a786e878771bde67f73a0ca89e7dce9e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "041f66f03330022557ee8d85a602ab4a14c45afa07284158a3fcb6585efcc914230ab9957f395823970ce58e81d9797d99b2b9d70ea421a3203c5de459196f68cb", "U": "041e930bd5becdfd0f358942b00ada8c9f1d38f47a602e7d407dfe10a4969dc455173867a674c9cb976174ef884a3fe8e01094ac00b115460b9749e46a12f82612", "SERVER_OUTPUT": 0, "Y": "15b1626f02665c6f8e24efbd8256ac90eb8abf5add5217d89a6f1c307359c49c", "X": "00a68b76f3b121d4c94b81cb24fc5302e17d20798b975e54f12c7a88f671b465", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 211, "UT": "041f8b76168f352aa5d4d4d17d42b96ba6319ef904f6ae8e178c99451e24e3580c22bc5923fd348b11acd9edb662d10d8f281ab16098f9c3f9f05b84abe4d9ebc0", "MS2": "0772a8c4a415403e64412766a1dddf8c8abf396fc6c615e9a001b35909c3e581", "MS1": "171ca4fc3e268644901bcb9bbab801f83b2db5d5bd6b1a763c472050f8569a41", "CLIENT_SECRET": "040d3e4719752beb9dfb6b97b0ee0b2e13407cfdf7ae7818da3b96fed8e59976d913da9675e81514cc6c67ebbe331ccf7268fb9cf032607b70032d5a3662f90fa3"}, {"TimeValue": 1437055598, "SS1": "106ed8189340b884c37259c731a700378af91b12de5f3715020df38cb7dea1000448cbeb5748db62395a437dc8c706156db42d3e8dafe7015d00a6bcf78c1e73152a71dab8ca77f7eec77da429da9a05b61940d984e5073842bb7962b5329ec41babc72820725f8a01a42566d0ba0969c72e8706680988efbb1753c986b2e234", "SS2": "0b0a6ff1dd5dd7e54c350ecdd2a99a191aef0cada4b5a2468eb2eaf7c67903bf227752e9d75d8b5c903840cebac639d9d70186e8f6a53fb9ac7bed891e0ce7e52089659ae7c1d2400641513342a92feaaa731c189decaea8c4b87750c03bcdc21ec98d165f4cb5ff5b5adff234b85dca7c753d74bb3f7de70182b391e9b48a06", "DATE": 16644, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "147256f0d8b7db1b0dfb9f6a0b9b204aa5f6dc34edc71c864b2579d0fc5eacf214a132583c0b324b77bcc3122d845690a178ee7ba99a0c807860403d9fed136c12c1c1884704eac093e12887fe9569c4caa169c519061721d1f86540fd8ee08908aa940f49d1fdb3bac5f8cecdd8d46b7a370b2f413121bfb40044b3c390e37b", "SEC": "042046529cec6030e49fd978fd72c1f94076c5ea1164486b344eb402cbcd50b283033919541bcc7a066b9307da50527e13af9675ffdec94f4466ef9e1aba5f47d4", "TP2": "04232909ebe507feeaee12a30f89dcff3fe0c4e07cac55dcf45ad54facb12ca77b02361de1850933571e87097d01d962a5e5e23c9bbf30a818b165043ca5aef57b", "TP1": "04009ce59139883b991a806666c54e9fe2f184a37ca0b5f7918733c0e13abb2c521d08b98fdf41f826a0979d46cb527b492dee21d3c1256dcadc6643f6e0f6f42f", "CS1": "040e236e1f55adada27be45910fb87a35babeee9cfa6f9c80547cf37606a9bdeb1236b7e4edcaad0a6b929a1e799c0bb436468030b2abea75a828dc5568c969d92", "CS2": "040a57a7dd55d2ed4414d8e2c98432c3bb6d45748b76ad05e1dccf4312573d28aa0600ea54a0ee468f73ff1904fe7ef7b70e3024441434217f5659cfe577dd8423", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0403e8b6f8eb5af8a4547abe99adbf613e986d502f626d229a3469af5184ce54e91358a613e279a0d3cf30d3f8e9724a1f9eac9c2682142f6e347a012b349a0d2e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0401e0b5e62ddc992d9fa923252c6eff7a8558a2ed21cd782bc4d375560bd646550bc3f1183495d070b5179c20bd15afb711f257a19137e4e9255c5c1d69c315c0", "U": "04077d546aa8552ed1f3fd67444b986fe36b34b1088bc76b4fa41985300d5be81916d76feb159c2d5ca67567a4a0b1e0f387eb5261d83c592d6c56c9a81ee44e45", "SERVER_OUTPUT": 0, "Y": "0e8ae0d8b9ef938a178d0a8aee91515f735abe6b8c25d5c9902d53f3c0fe0203", "X": "16271e873057e69ee80d8652e454ae279b4fcfc1f632e5376a1bd4d573ce4fcf", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 212, "UT": "04029302486729eec515b87137ef0c077168167687448082f37ede06d5c60a785417efbad3888de1640e952edca4d4b4659c94bb28730e43d25d68c533e8f34c99", "MS2": "086234ff9b9ed934a535be7fbc5cde613f696880db1ce684077877806641d19b", "MS1": "110588e7b90b6ec2da71ca0869cf296655fb2cb1cb428469a27fb08078a74696", "CLIENT_SECRET": "0417137e330aa79e629830e3d68639500a103e2a965de4ee4fd5fd684fb1ad01911340c6a3a9cd3d448788b323397c938679f1b11a58a180e568b303b07fa063f6"}, {"TimeValue": 1437055598, "SS1": "08652738cee1b741d630bf2af34ee55624261441a44b7f02f8b8e924cad632b90c94af10d1070ec73190c67ef5e05d792045a1bcab1c75f5ded786efb1ef41e915cf5379e13c9e75275b544cadd2a80a0e104570c50e636d21ec6004ed0a2d8e1b595ea00645fda6babf428f99023e175bb0de662a8aa216af06f2be6be86375", "SS2": "04ab46102fe67057e5b4c2ee2fe213a8d2042598ec82cf9ce06fc34d3fd9e7ca03903748848e03065fcddae79cc9e7a98c8843c0202eff9d12a67482dc88a72723eaef4995dbbf9ea6acede4897adbe358f215bcf0227905ab23c2068fc10eac1ad037b9ba7a76bcd0f2082c20ca5db67654b99c7421d345ecbc8bf990a138e2", "DATE": 16645, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "1919e577fbbc8b301346c04530a976d7eeaf5ad2ae26d8e06e1701411c95360c1678587babf098fa1f8e8af1420db5e60a7cb51f1d51858f2491712996126d6b069b5b9b73f4c4e4c9a7fc5308d7d7f5ab7750b8bce65d7233a5ad4b2262bbb61eab6c2483adf159b6c7f642cc4265697ab36b24e0391aa258b93527ca9acdeb", "SEC": "0401c57844629968bf724079f374cacc190c33db69b843cf63b3661a6c20accb0c189ddb9c1bb38f71e41401aabd72509cfb5ded77618651a0b94af446fb297746", "TP2": "0421f2755429ca690c4d830ea4d10bec06bdde198bd52935a437c884fb11e27d840404fbf50558dfc1ff474ac5b19b318df756acd76c1ffaf1ba21379eaefe5285", "TP1": "0409fbc066c8c4b93bef9e33a3ac3090845c175660a83029d09e2b60e77862bdf80f84b5ce26fa0bb42b07204ac7ee805610ac27edc1b0c5878df658f6aa173126", "CS1": "040615f9d1e00830d5d51bbe9f77d80b7ee95ae82b205682bf86665928b7ba9a39014aa9962653f3b80c47655f7ac58d03a279b2268cbdee477611b282f89b6faf", "CS2": "040ce6bb1f4d4c87c1812085cb816afd6c9f514b049fb08271e8e09eb60ab20a0801dfc56a8887b547ffd66973e50ddddc2de029b14a2d9c3b6d774885d514ab29", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0417ffcf8b32577874dbd24d35a05a84caf2bd82312abd5240f1485ce1319719f3196584002926ba776d6bebec9beeb70186ef806a013ef58ffbe776d052bc16a5", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "04120c46ccfb0ea8c554deccab28fd329ba3ef248f0cd2d89fda1792bc2588ed2e05fad3d01c8f7a64ffaece4bfcc46318aa9b6b567aed79911b1b3c0f2abf046c", "U": "041bd50072652d01a50c45361e7c692579f295ee2006a38087bfdd9849b88281f318e0c35e546bcdcb305edcdea379d33ea30438eeb143e9d4221a650ce7075a79", "SERVER_OUTPUT": 0, "Y": "035b40f6b124ce9adcd7306450f2acfc1e045f39859c78f04371e0bf6befddf7", "X": "00f1fc1c2cfc7b8849ed3f60d511de902840adcaac9a33302d3bb0a36177c487", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 213, "UT": "040eafd3f7e012277658b6b1dd24daaf6c7e2e34b8b3272ada1df7219a20767d0c147e3d9cc4eac273ede385f50fc1b367c6c9d1946d7741788bccc88b78c4e968", "MS2": "014e6a988ae91f421335c6acfd3083be0f7aaa77ef2226a82255229493236b2d", "MS1": "0f1b31920fd07bb60aa7987095bd1028cf346816cebfa0ae2a0bed399096e569", "CLIENT_SECRET": "0414cbf80241005248524399968293451e9f940712eb86ea901a5235f28d9dbf951f425e24932b3e871fb2fe0fd5ec1adebdac4411d3215dcc82e2389ff71755a7"}, {"TimeValue": 1437055598, "SS1": "13155f722ace543a8367d41913b8dae0fda494e4bd2c121d8899254cd72969140ee5c40649e3f4f5dface0386a6d1714232d742bc0aa20039ef401fba0f9db4306b75301073612a83b54826f0bf0f52c2e7138850dda5fda66f7e08fb9b346d919e087419e58c9093350dcf12c04d0de8cc2f420b9a065fe9b9079e9ace1c86d", "SS2": "07448275015c68c58155fb140d054908bb83bb5db613cca2515a4201f89a18781c1c7206dc07220d9d5b5c744274ae23da6dd3895d292b5e8cfbd2bb30aca39e120e42bd2ea93c8b28df6e983676bdee7011efef9f9328eda970c0421ad7ad0000ede955ec5959253f74d0597ca7029be2ce7714951485e46ba80e691c82be1f", "DATE": 16646, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "00c09fb82b284a72f82269fcec6ee8fe0119b3a4a6a391ccea3b4ff7ecd8afbb09080bddb2b8298591c100d1f64982404bab383f3c7b886082dd3e19e6fbcc091e1f1a81abcc3ede2176a1cc71b9a0fff17de93c8ac4b9633c80c37226d7a8951415084262211669e79a766192aebca1023461c45780bd3aeefeccd3bf6a8634", "SEC": "041032fa436d77c0454cc27d220490306d5b1f39b85b07fd35158e548794086c5e1148cbc253f8b11e35c583ab4bd861bf12ad01768ae010540c00e923996b3239", "TP2": "0405a9e4d094152bf54d194e8c3e862ae7bb84d968914e61f101f4b5f7e12aaf8b12c989e3ad9d97b5ba0591e94053175f0d3eab0ef6873041111d5a68512c7838", "TP1": "040c2160aaf1d3f26433bc27c08488629c654be84871359dd47926e2cf16049a241829555cc396ec2417fed8349b3c2dbc5e90e0bce80770202c67e9d08c126795", "CS1": "041d65cb5e88c4c477e4e24ff715970282c45f678e3a1f4f4321d97a2eea67b76717c4139258e226fc4f3f0833a4be42184f02d61c318b939c80bec1a4c89a1209", "CS2": "040b41a197bb9e3187cd294da2aea43180d2e04ec4d15d4b5f19163d2b3650cadc1be0d269b463f08d2a40bc4e874fc5adfd16809a79f57424131e7d62dddbb0b4", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0405e5d2a4d7855c5a76ec8dd65b70fead3379327d41b1623cfc3b43d9d15652040dc80fcc7257f4cbbb830a92e158d555c78d554be5c4461841e85002b03f492f", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "04126235d474b9a77cb5c56c915cb48a4a9da465539cb6804577638b30c5058424197c98be07233dbee461b753c3476dc05221a6abbc573ff88c4abcfa47ed4e64", "U": "041872a1546792b5530f74923f04deac2bf0156caf1e30f88d7e864d87329439861195180868b6422314c24aafb44e990963209a9def113ce7e9a3fb8e96f49376", "SERVER_OUTPUT": 0, "Y": "18b8d7e1e60ab6702345830145b467e91c1fe53c75322b7d3f1b0bbc0193b1f4", "X": "1feeb808bda2dd83beb6c3b87e7970118976974fd074553f86ae2668538b9f1b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 214, "UT": "04194a7e713bfa2bd4cac10a23e20aebe22189652f918e1141f515027daeb92e1c095b0e429c8ee2a563634bb13b321127c7947e5e1ef04911ea49a007cfad9700", "MS2": "04ed475266fea0c296ee18ae21c0f188a919173a1d9e17ba6241788fe05bf274", "MS1": "192802a31f684fe8121b689f5e6b16aaedde745c5786628c4ee47d2ae3b64f94", "CLIENT_SECRET": "041024ac0beaecacb2d3311e62f4e52e1b70dc5798c06294d72e617010680690d21b5a3fe79cc5c77af332276693d9be56cb99377d2af9f11106539fc875cd9a02"}, {"TimeValue": 1437055598, "SS1": "07bff558d39dc947fe917c6570caed9a6a1aa5f8e3136e6322a7070811255d6e1e19bdd06a9dcf1b244cf0e1acebd3bc784e812ef7b77730e504c4bb9be31573009b8414e021851fc7a2f92af1226cb7352c23e60910e425b1297a105844cac5178bd77622e857a90e0f08925dc3f15808a154ef76a3ed9a1562522ce9cefdd9", "SS2": "14ebc4ac162288f751519d984894594decfae2f0820b92a8176430412330bd4f14c7ccc0c6d06db72e8e0bcad6bbc05bbcf7f2df41099fe1d1f50ada6d605b7e078d2fe345656dd04d92c16483d7ad97b1a270e6778995c8e9c8e6e56254859e0ae811fccb7002336e06178cd2f9669dd2eb57292f9c13a100b97808388128df", "DATE": 16647, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "1adcb038b702ccabfc6eb3e1eaf1c1768a8c7482c1f2d9a8b66e1345392885bb06510e0c0338605d1f45001e938d043cd92623354c6059765c29c014aa177987102a413f6210b846073416b6830ca6b4a69ec3b45a2c6c51340ebe8d28022c831f5930defab5e13b6810c252488242853a91a9fb856d7e9d4a623baedc82f6d6", "SEC": "04061b94bbb1de9fe30324748545a9ca927aa46927abdf156e70d0236a8a557ce323febb03c701e2eb40b5d50d4335068f9f71da78b0f2df033871d70b34cc43a8", "TP2": "04060d06aa68f6e216177a8e45a20cebcc2b5204724a25b7c97e0650e0c92914d90454a8e1f0876bcf13ba6041fcd4a0d3de639f4c79a656a67b4be879265b8270", "TP1": "0423ae04073adb9ae46ee731e165dd37378d71f1889356c560c0632a577419cf3f1d588804641b7e752f82ac2a43e5e374ce3266ce7da9743eb78d367a601faf8c", "CS1": "0410e4dcaf53d7b9a7a6a3d8123a7908cef742f44b4a8b63e92643fc4b4125c668140c83a1f1dff4f5bebc2cd7596393023f66c18af0d81dd669ef24fcc352bd7c", "CS2": "040bc47accec4852feafb185976161474c6a58774f818298ddf0944d97172c5efc0936a48bc3881fa2a34ac1545f4556c8ebbcfd27aec5cf4b1aeabf24c79f00e7", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "040c2e0fa8ee59daf0d7b7ffeaacb64fda5ed08b6bf94c5b06726d12e7b4ddfdd01534679e42db7bd4f3fd8e3e83504a231647d709da082e1ef8a574f05d45547f", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040154f6742a7359f59f444174adbff0eab5c09f8e1700cb675ffa27b536a7672a10e38f97a622efa00b4e8f156e286875b71e99171f29dcbe046455861806cff3", "U": "04148883a6d564438c6d94f287755b68275fb942eea134c414b12def9b59d093920b5c9aeb25fa4c8664815b8a4c7130240fb1fd9096108aca540d2757ef6bb39c", "SERVER_OUTPUT": 0, "Y": "0dd24f6e34d3332aa2f410052e91247ee16a99fb8017022cecdc932d764c371c", "X": "03874593e2ffa7a54358e88793e95699b2d320741c0579d48f46d587ee0d772c", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 215, "UT": "04213fb2d3837082b21277f39de271abfde01d459a503fa7e361ac319cf82a34ba1b201710061fe0091c8ee289d2cfb4a72693b6325647ace786debf2547d22454", "MS2": "0fb24e7de55c379154fd7ebe68ec856ae903f2fc1c238f4fe6710d0becf044b1", "MS1": "10d09fc7001290673b57b3cb40cb99857d7595ccbcf57e36fef312cbb3fc10d5", "CLIENT_SECRET": "04192e2018221efa72b4940e48c1d28f1637b54de8d1fd2f97ea58a9bf37003b942270ea8837fb898062ceaf84554a4c0c15fca7bebbaff67c4063de4d15af667a"}, {"TimeValue": 1437055598, "SS1": "174a407e6eeae21cbd5dde81d011592d9722b2d5b89887bd1a4c39117b96c4ed1a9f6a05a90d862a09c1f075c9116ba35c06ab48dbc16d42e23ce74231a359d612a26367ce653cca4bf17355e3dadecbfd5c417662b4b83564dcb0fb51350daf1041e3dca7c2ce3f8e958b39b627d563cd43cdd08461ceffe5ea678209006cef", "SS2": "1440568426c42bb64c950d438882533fabc1ffa9664b091d7c52064bb3c78ee60b99d8de0113b1bf1209e9b3add89ff3d502af7e318265101c018051e761f22f05f19a5e150497d05b7075ad1781f06fe028abb132b7aed961bd6bc06e31ba670e486ffd19ade36904623f288c1dfcffc035cf5984223907d81b4e6ad9de5808", "DATE": 16648, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "1a32b8a2c625e9dc5be40f0164b513a40a0731990ccd89416303a2f4b7b87eba23ca8c4d8126dabef4fac01b616652d9bebe9cef0d005fff2796dd1fdbc4617e10b6bb698dd3bd5050e84b57da9d79a3a6679dcf7ecbc46ec72b4236fc86309b203d31d6b99c438335110275c7ea29049f0e348a9b911812ae58a29c73f5a823", "SEC": "0407b39c70be8568b72cb03421c33214bbcd80691f4959655cd5323f76f31b9a13068497b3f060246879ffca7e6bc3b2f84b64d749d5d8247a677e91a7f4b86841", "TP2": "0422b316ffca9c513dc2b72f94afde1390199b64cc927fcf18d5ebc359147ca8d903f3c742cdf66d7d90faeed80331e169afa33819dbce961924cbe61dc60b49e0", "TP1": "041cdf2403cceff74ccf8027b6dcf54965ecfc6f08b8e964b2b2db613c7bef094b184687a1df6095d9d69b567c4baf1bbf2b3b88c1d1440ebd12031101972c358f", "CS1": "0421267ae7783cfbdf84df49a33390d275d68d80b2364f63682e4a8d21a08f24191a4d0b655d5b460d9592d3d013b177e9f77ffb2a6de6416300abc2feafdea0b0", "CS2": "040af81bf34cf5d93ec03471871915defb50cd8d52c75bec628baa95bb275738450149eee66fb08e168fa020ef0d50f9153ee54c8089d7e4123d3e334ce89ca428", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04140a42bc16bbde18519d8b97477a762491894608000779369cd3eaa37e8515bb1703e3697f62e3a2c2ef63073d49277342cc9ae59408b1c031511db354222765", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040c4f8a37a13900007063c29964e62e3ed3f6a1dd8a6b6b19806f59e5d6108c48103eac6ce635fd8b6e8da57115b527ae864bc20ad2426d851e33a348c8b295a3", "U": "04005fafda6a1a70ce4c3d70af015a3af4bb1e91b0d424da4078b9f6ad4174f657225b13e4c8da6810e5ffe2bbc03ac2eed794ed0b5141c93ae8a39f7467a7abd7", "SERVER_OUTPUT": 0, "Y": "1a7e2b877e17ebf6d1a4180f3daa0d0e90bf2b561b4439800529d5e2de715f60", "X": "13453b13255ad2453e2f8a6b897fe777bdccbc3ca07541e109c59a124246e1a9", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 216, "UT": "0412e5a8dbe6e39d19ae530ed8a98117c20e30a88c67d27be81236490b5547c6890930cc13d67eb2e7fa5ea1d9f0ef36a168e5b57b82971949e17ad527cea8025d", "MS2": "1780ec1f26d0dc29f7f5f1e09c9a233022b7805b125b3bcb569b2a9e5c9ad777", "MS1": "078dd7eaa7a947191a0749c140ee0b4dd900d52b74efcbb064567596b2c5af07", "CLIENT_SECRET": "0421035c0b4e4cfa907681003d0e8f5dec22012161b193fa5dd839599efa9bc7a8075a1b98fc03602c542d59e630dada53f6c29a4356a7bea0002624409a279891"}, {"TimeValue": 1437055598, "SS1": "17f6d88797f63cb47406ea6896f24f8559725f442af44b30397b771ca1245d3701cfb6d66170e6f7932ed708ba188e8d684481f0bf4e7133ad7d5188e5d51e0e0196f12c80f5bbafdb1709499f1729fd31471aecd1d3957d659c0892c85765a31104d66fb0a8abdda6c27b575a3922506e1e232e4c4e926f3b9ff297aed5a867", "SS2": "1602a96bb4f1bdd48bb2dc10561ca5d5ebefe06d2ec3c694c48a2fcf57793e0411d51993243bb2b42d46e616dde3609879bb4c69f0e4d1c18239e1a7ca103c7a23c8ccce1bf7058fbb2a49fbdc588c5d6fddf04ef2b184e847b9b3a6d6b25127177d6fa3d385e75f220afd6067f160b1d0721e3977705f5e0380f5efc1701106", "DATE": 16649, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "2098626ec3ab32247646c44d0743c225f6cdc7a0d50db6d89b10d52e7a41c1990171223d43b493f7cd8fbcf2f9219889590bf225d9ae6d67b835504747cb25a9005e57e2d4db56bdf4f7d9041bfdb7d3a66a7eea769c971ae8143f1b47d01c001ad6292455cfd34f327339f2e4d5689fcb4757e799e02fe321589b776029bcfd", "SEC": "0404cc822588a024f39c1a2d9ead1fdf2e19318cb4823ca3c75610cfdb6b766b9d00e157f6eda21d7c79fd2171195657b76a764b95d8820feaab327218e1897e46", "TP2": "040b5fbb46b2f4737ed29c0890910d593adbcba656903e5b5319ab93c7c17bbb13093268a75b0f01db8854d03915ca205af5fc6b4b3a93f8cd3af410a80a5d25d2", "TP1": "04110d95dcdea8f8865eeafabc9261e3b0e823fa5412d16f4bcd4fb1379b8f2c1a1a4cccdf6a49803f0507f2cb1eb9b909245c186c48b0ee1a32e7c5a79b6db199", "CS1": "041bfcbece9da1b171f0f250d2686e1c80c73e24c9fbdac61a22ac554ca06d2b6b0193241eb78fd7e037414b0c61c49e840522a9ee0c21c129212862d1df345d67", "CS2": "040ec69a164a0969a5e22cce6f682d1fc8f2cf5c384fd0699ed72b33053c9014c51c06d8c67de932849fdd73c504c971ab2822ac564b8287f41a63c1d785531654", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "040099f4f63d04b9f6de7b42c6b671cadedcd19e0e4caa55c2aae2ae21108d377416bab4ac65ef0acae933f0b2ec3cc9df9dbd6d7739eb112b40876100c431a455", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "04176f476961b1f07447939991fd6220feb8010c3bf0a827fcc5a99f1b765ca70c0b655b1d512af4d5988b3666df5f0275ccf3d7c086f367f4935545b3775a689c", "U": "040af15b38276c9aec2defb48780933ad0c220da46789c59a2ef88344a77fb945b14c37e353c1201fec259f2224aacbccea3f24698bc96c0ee6ff9837ee18725ae", "SERVER_OUTPUT": 0, "Y": "050456cec087964126ac8e83833e87ea60119ffbe0bdbf451ef47f88045f22ac", "X": "1c07730a32983ca3c673c02fef9b724c481fc1390f59a60334306ab264537d9d", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 217, "UT": "04138b8e2765352e11a77c621d40d027b350640ecd76711e477be58fd4b7d4af832329103e3d4515191996418ddb8f7fba12c5fb75db81df4a6d9981413a785a5d", "MS2": "002156f0bf1ea7bad468ace72fa21f5ae8aadd7e1d27b204f5915e3a286c611d", "MS1": "03a50b805b8dd326e7ac716e2ae6124d9cdf18b8c2d5f59b625bb82e3788480e", "CLIENT_SECRET": "0401bd0800030df92d16888418614beeb380c60f6f0eaaad8bfd3279b4e8258dd91a0d23c90df58c7ef437f16776a04163089decfb1a5cfbd942dfd41d6264fc97"}, {"TimeValue": 1437055598, "SS1": "1deb17abcecb51419643f68e0701c62ae84f78ad743a89648140a05f903864ca1bc05fd11a88bdd0c908f2728860caadadf5b046dd9fbc98cf920b5752a34c4b1a4f189ea547383d1f641ee168cc8670ab41da389c11cc04e8981ab4e5a97787180bf9bf1f3899c6673475f13542f903580e9393bdecc19ba54fcd52526ddb0b", "SS2": "0cc03d2eafc5db494c421e49c34bf3a87f0db93de6c455d61e8d5577f617c0c801976479c8c6b8792f4f35324eaf9c6cafe981740d1f038ed8bb4979a78da693033795caf2e30f66037b3a5cf3f17ea58c5387e65e7fab96156404d0e67ff7351ec873a06d6b6c339ce6c441e921dae74cabb18f2325fac31c7c4b805d8053b7", "DATE": 16650, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "1b13aee2632fff849d9d54dfe16e59512c897fee966af71a455cc214bc6d90e4156ebf4d0e87a5b62f54b96985c994c06d3066a22f3e4a71eaffe310036ac3801a49a16e5e58c8464e1cb1ad606f22b3b5f51d1ec89e89c24f1a7d6084ce1d9e055f8631c61fb8822bec63f447b6d96bcca7726e1b4ea6c9fdd5bda3f98d4961", "SEC": "0421aaf4e5f8823bde0f27a831af6284636bda3b7db03217420861b098b9aac1af132aee16d9a9e9484540fb366717ea3e5cf4a08364120d5bddb28d8766e0ce81", "TP2": "0409c85d0b71d154dc0015d3d3c0fa3ce75a501637db41197f56fcbed64f1f14941e79810983458971e232c10d774f2a44ef43d37e03ca9b18da943a6daf572585", "TP1": "04224ef9134044837edc6bd998ba18f8796415e2003304fa4693e5926dcfeb9dee11119d4b989bc1af978ba3f91de7dcaa4847acfd0b99856b4c7e4a27d5ad81c1", "CS1": "04226f22b379813d102734cc1a03cd9e4626d40190f1523e6ef8ce655f25f68c6d1c4a6eb7be412838109112ff3842110252a462d67dc273c0b262e660386cf638", "CS2": "040974851be271d71a807e9e13617415382fc7846a1e51c9b304ef7fe21176392912d4f1f9a0c159900843dfaf70c1269ffbab38e06caf0779d3997aa7c5da86a6", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04083f47a9a793baae730f8a6bfda99ba92549bac0ab89d08715dbe00b42e53d7813197f151913f136278fdc228be97d9a3625d70b14b22c4cefdde3815d0effb7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "041ccb77f20fa46eb08b0ecd680e7ae39135a35b8a3dcca4d1cd9f887a6489990520732bea979e6508edc6bc1585ceef367c5ca3d7a83bff08f42f50367e5c879c", "U": "041646ab9f346d50035b8d58e1055722e707fff46c943abf961ad07867eb48957a15b4d1e3924030e7b5d640fa6f886f1815ac07b96e8b0690ff2ad63a63ced059", "SERVER_OUTPUT": 0, "Y": "0c31f00a56f1ad3edeaec1757543d9c34ff36ac1e583cab6c3879f57dc3a8b1f", "X": "193752bcb87338f68ddc9fae7d8f19404d44c1d7f7b76b7668fc182c23d7abb7", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 218, "UT": "040261fa9df7729c7f74ced6d1dddd7b344f75b8abc485d988c0d3215aa5941c6820b453035852b353853ef52b4bb15c01b1b2dbe16f1340d89747430671225923", "MS2": "09bd727128aa434ba711d5f9a1476912693ba5c6c33baba27fa923e213f32409", "MS1": "1ac84ee7189b8e12b756e634e3e991dbc4b0dd21dd875bf170ca19e60b976142", "CLIENT_SECRET": "040a91e79d318513986c17b512a242720654d91399734266a79069af17a3bf09ec0d52b9c68d17adc75096fecec483384aced49bddcd492d2a9141ab267c64ca58"}, {"TimeValue": 1437055598, "SS1": "1c9f989091fc1d463d2039a87f9981873614000a531223f3b2497db76fdf807c12c216f86091586f665d6d92929e2c66c27b86e8f5ca084f6aa93220c7fb743d119c779a0f2758b9583025ac577fce89f04c672e70bceaa23222299e9cc9ca0e0345de475155a3beb7b3759676d31ca48402e91e885826408f0b40fa722ca40f", "SS2": "164a65deb9e33283399dd4f315f2fcbf5b0c4d86b8cb8447cf903b2408b8844518987d05d6585287d618e13de6fc19726a0bf964cc02948e0a0f1ff8a9f204be11c83a949b23c2e8ec99c6147f9e59df8700800c6ac62517a4178ca75ac0a32b0ace7e5cff251740b16d8a748758078ad967e8b9f4fd68a026eff9c6ee8064ce", "DATE": 16651, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "12720103e6b15f19f4d5fbfda23e9942027373a89c6745d65ffcd350b4ef86461258017a3463ecb36149e7a3d44bbc3deaad073a26f3c13325ea4a02dfe9ad101b158c2fdc92bc2a0096dd2ea9b6bf6c081ceff6b5005258817ca763fbd4940309682b1b4197fec8cd846a3a6d67e77295a27094bfee711220a8eb4d4cc94063", "SEC": "040e29322b035ce515fd756724900dfbc3073564d87ddad85e91bd0535dff0df1322a137d9b5f06f66eee31386c659540b18dcf3948fed8ace45b40d8de7386fa8", "TP2": "040d140dc1a3ee83baaca802a8c907bbb847d997a3161a1e2c78bff036864233031f77b62ad1f4f57b39d9567c4b574d213dd3aefee39686853aaca8075603bcbf", "TP1": "040a0676de83ba85fe00b886ccd044634e20219dfd19784139c840855d375496391eb53d10a40bcaebe5e404c9869ef96ceb6fa19dde398cfff15bf4cdefea395e", "CS1": "0407d394bf6af25bdc9a8db6649489cdca7717b27c3af6033420ea8d1aa0f8d67f03df9978d1e42fdeaddf65e44e8922db370b944e785e6a53edc91d55e62ca974", "CS2": "0406fd63aa4fcd0a9ea3c1001a05fe4a76a6e02f68be26e6569bdf9df8d1d388c823ea85e577bce461209533bf108c08ffed87b1f37d8c3da03ef3506bbb870029", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "040a161349fb69408e61c91beb142ede712db06d3a77c657f7267862bd1203238c0d55e7a8c68c1a4186d90edd5c8121e3190dcc5eb669feca83062ce96f8b060f", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0406e61bc958a95eacbbdb13c88fa61b723c7671b7784e63b6e5bbef05c32b07640dd23335e2c8632496395017b3c8cef1a38d327e2545939746fb09c3acd82614", "U": "0413b6c5d93bf6b1197d41f828546a7181cb75e9c6b81756a4f3948793e47b9e6505159ca918d91979b77baf548d70cab100d2291da7ae483e2d7372bb638b6b61", "SERVER_OUTPUT": 0, "Y": "0c1ec8cb2fb2620ab020471d19c9f6c2e1f855c1a5f40db8c4d309baf59d4933", "X": "0ec2b2fb224f71e6cb335dd88a1e5e1759c244cc404f023bbd20e509dfa068e9", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 219, "UT": "0402fc70c2ee579a6e78ed8fac8c8102c4cb9879689bb22f4c78beea56e492e1910719ab9186de17a06b105647c55c0c6abac08cc1a199f1e2d5b6bfe6b3905dff", "MS2": "1e36f99def827d6f0d9dd94796fe706b3e76f061a57e78d2d563452de2e0e115", "MS1": "198cdf7c4deacd4a31c29e89d635e3c484f1e0740bd92e20f80b59865d29535c", "CLIENT_SECRET": "040a4acbc334978a97d21483144ae714e01c2be40dfc731c7205bee0eea14b43b50aa97f6dbc98c0043e5a575ccc96a6f60fe9bb5b52d52134be6eb73641c0a616"}, {"TimeValue": 1437055598, "SS1": "1d56633e29111200f91e1c4992e3a731609adcca0ad9833d5d11cfe04b05b5591f8353058f7b8fb62a2971235d56dd1db8e6494d69a5fa16ea790f3177f64c26176fab58f1a62f1574c45710cd87aa48a1af6617797cf656f70290a1b6e96faa07f2cc8194ff32cadb45821bf347b2466767896d5c28fb182ac36098614a9d47", "SS2": "0ca80f19aae6b2a490e7579060a90ba60ac730203caac37c28b450617af01faf00e66342ee7693c26c1d38e7713e8afa7aae0918e13a9a09e25a3838d68677ea22739cf69b4fd6fb00d4d73a2471639fd2cae9059aa36426ad97f4531cd206e404e0d4e3a33ab081dc5d6659152c3d389da6f314482a9477cd644ab84e3f5a68", "DATE": 16652, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "00e78b78811f67a43e2e237dde2ca38608828bc4219bc3f31521d2bc98b250250d2fd30f25e205563bd862d4d2ab6d284277e30ff29c35b41adc2533f995f8240ba1b878cb74978c982921d2b1f759c0ebeade62b19baa70def7cae274b7ce7d18f4fd631f4399323c5fde8461bb7528b55f2472660abd3acec9d0581cf23708", "SEC": "040ea940924922dc0b3603e3e2cc6ec52306cdac7551a1faa8e807f9a8bb4eec9322bbe84081a31b8aedba85dbc89523d496d1704f5bbd5756158832dc0715d944", "TP2": "040a6b60c1251416d563353a9baae6473424ff7fb807bd90d33f2483bd38ab23431fe4f42b4bbf734df312d4967fa0142af3eb767602a39f86e0e81aed2482a90c", "TP1": "04011cdeb4bc39e876b3e22f16aa0afade085a885767088e1767da0673a2d6fcfc018b09c7dd3b99eeac8f755ce8cbfdedd90190ff4e1f6e0f97ad39a5305eb214", "CS1": "04041c41c7d15a9a4bb721b5738587524e4dba82de8cff9403a730fd829faea0a119f4c14c44a3283ab8e838cdf75cfa67fa8620c40ac8c3088c8514ba3573b7f5", "CS2": "0406e40f87d66163b1fd9697d6558c0a743a6d4853af13c6f86ac32b2f6fb7a4070e7270447c216e6b248ae1343cfefd8afc05002272bc8f24c516d373ff197fb9", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0419b57b7c2798b83b7ef7987d3685743afc169d2db895a42bd194821384f251ee02691b67dbdb5c7828fd46e9d5b034fc16f1297ecf854468cc10edc178d22bcb", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0406aa32d3397f4a0872373939df9ac911de1463e38eaa1badcf76ee2adf6a913a19c890aa78fa6c14f0c72a7e8336b9969fe7f40eb10f06b9a4249bbfd7cfc8e2", "U": "04219ab32298c0fa7be50f56086a6cc6de424824eb6c31ca971fb37d28300e2cc9100f7a2ff65b716144b369602942a2f20317ecb9ed0ee2f993132e017ce6825a", "SERVER_OUTPUT": 0, "Y": "1f8f10dbf6a0869116a7702f3a9dbd228bfd0710f1e8fc8020b0c4ab41cd5368", "X": "0775428b7780c376c10d24a99ef0315b20721e17691a032c20d492e9efa4d66e", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 220, "UT": "0418503730da0a718b59742ad8a76a8297c1746b126329c8a0e6eb8538291eb11622902503ce3d4d23bb4c080b899ed62d28804cd0a4902588f2e5eafcf29c35b5", "MS2": "1b4a52d2fbd40861ba3966ef8f65921c8e272f92581025422468fb50426421e9", "MS1": "229ab5d3114ca4b6c85960610fae9e3c54a391625f32f09bbb005218bc04bece", "CLIENT_SECRET": "041f0a2fbfc1dab2a2b00ab1e11370a268319c823b4f6eb393fe420872b27b0980076fc9b566fb12fda578d0ed4622aff4cb92961cdf5d71c233008bde8b57459e"}, {"TimeValue": 1437055598, "SS1": "058cddabb80af768243cdb5b06a6761e1bb29ec8cca2e8d90afb8e129933c5261424ff2e132e135f50f9077eff0d760b0cc0668e80d2496c78f99163e608d0540916d35247dc99792dbcebd9fbb44389d43c4978faca5199214f168f591a003d222becb3f1039cbe345725ec70cf76a48fa7c04df2c7aa924a158a4b7c44f52a", "SS2": "02374e826b97f9f29941a2752bb7789737be84f3367ba07bc07ef9297688e277194042821333010d442941938f7434b01a6ea3290f87ecb9d549482a9fa5735a14c6fb8e2e5f5456e10375502e59793cdc0538ddba215fbc4a115715b4dd986500e16f014c89347ec6c3d48423f84450f63682359aedd925bb53c4f50af559c1", "DATE": 16653, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "054530664efd8b6ca2f2c94b8dd4e03db55a4690dcae4f39a05e4942699a146b0cf9703a8fa65d4458f431ea8e73d8d17aedc37b873e5ea0f2280d1589f8ab3d0ae471094b2feba6e2661a6d23af8069adf0de950797e6744feb71df30a816c40ad7673716804e7f3e2509e696c4a0ff028e827a3df689adb6b7bc96ab1f03d8", "SEC": "04208a7f1195aa2e9c99143c7739edbaedbd7eb259405e0030de41179e5dac0fe71984193fbe98c7f2c732dfffe6c0dd1eb516aea52899e279fd3e1a159e0cdb99", "TP2": "0400cb86a08f2fcf5e385e0d8796395be2b30a549a30869fd38b0e7b92bb15c5c400eae0aa8912f1232bc297d90c2e9947502a3b04df2d53bad60a5ea8231fefbd", "TP1": "040efcc168acbc5283a809e0053e31b50aadbfb12b35f3fcf2f0e11bc0eb05b990020daf7b387e4676c8ebae5619860195dcb729950bea8c247169be7f06b3c003", "CS1": "042389f37589e4af2f217f0d024833e537add6397678c8a8f32d41d5bdbbf7d40311bfb947f1dc161b1acd5b1f0612225e346c27bc986519e8d2255c0a9a43b413", "CS2": "0408823e7a9f3443f5b022c231648ce7bab60f5287115de11b0f21400502a4f2af0a82890cf22ed1a06d04f52b9c1807b29511cebf97947b761c8b2e7e8bd13f30", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "041661e95d3f4b266a817f589e0a656ee915456e41f2a964b4fb8a93023c6d069e11e1361494d4c2d7b27504469ab15b7bd00cb5a2b32a0b1b6852429c310a5f10", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0406122e10f77e6445b4f98590ab1ef38ceaf5c8f68d5d38a6f5a2329f21c47f9b14680d6403ff28989284029afe8c21bc70e9756fde8b3570e413f5ad85f8a455", "U": "040b30806030868764aec93a477555e2549dcf3ae9caff710f619f0131ade47ea41ef23325ec8d0ef3bd357baef3a5c1f5fe954b9508e26ec25e485601e624a8ad", "SERVER_OUTPUT": 0, "Y": "221fd8caf4e718e515c455ba1f0c61642b98cf213a51fdc7ca61d236f76adff0", "X": "06bbe7ca31c985255006ebbe692df373d7a59959f62273f79e2767ba5405b2df", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 221, "UT": "0422700dfdbd35eec4561dd90ef0f0e6e78261446ac5082867f2ec2b9853043ea918133d65e3a2a99d3c8c19ae289c0a49132c6e31ba8deaf5e75abf353334b516", "MS2": "1694f0534c4e196315364cf53b8da6c97c511989708592700176153a1c77c437", "MS1": "0303978a580bfacadc976820126c144d59d4784b67d37fbe65f21cfce7943a8a", "CLIENT_SECRET": "041b2e430a7f8f5c549f8cbbe2cb144dcee109d9ea692ce115d82f2a385a0e18971eae777214b605c6c9cf04dc029657620b97b21659654d9bfd53ee48b8e20ea0"}, {"TimeValue": 1437055598, "SS1": "06cf93d729f8ea31ddaeed25bb818340e3d36b54fa0ddb2f082e43b2c124626123545033a9434dcb9f036d1cd50897faed0f93179a98a36f3bb8ce4f842759c723f41560b561aed14ecc860cec7a0c5f36dbc4266dbd9da1a14d08798c3cea252220db7985b0a6e84c32af5f290fc9e16cf9d7d64fae7e034fe5a5904091aba9", "SS2": "0fb85c9bda12532e4647d7fce4d6aeacbc528829a5199e56010dfc7f7a02bf400578f86169557d04f8b58171f62e5f2f7015e52278befd606a17a1e2173dde05147057423a8e67816a677af9c4a9b909cd7fa99f03d594df82da96374a27508d0b6e91e74eb90d29cc0bff42070de504efbde19a4a84710bb2a8e00e95adce62", "DATE": 16654, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "22ca016a1da28aec09fd2c0ff445ec0ce92e95d2aef9a493447dd0603b08bd700ec8177a28d8627529df3ef06571db758a8c7c1a221ccf7f18c88711ec4837ef1b72c1c126132c15b1e5e26d2142299877177dcb7d66a4ca942d5d6b268a418b2102e5297980ff6a00d5ed7d3cb87079956e8e4bdc9fdf4b2ac447d5ec0f59ce", "SEC": "0422dafa66fc35b1dcb1579ed961b55883306d6b0615fb8d01e52cb9e2ea38b301033e3f106d9c8efa236d57d35b0d62511ec05da895c81838d9920799ac40b3ce", "TP2": "0414524a7dffc202677fba175378cc9e7e0a4f679c762153c434f9d5bacd75930a0dd98ea224f4549238680b425c2a4a0c95d0bd5283764bdc7c2743bb549f7e69", "TP1": "0407e6ca11343b50ea066766ab26030a3237acbb81447d92a7924914660b0d600c1066d36794741b08fbbf3e9ec073e09928418e5587792d99dadecfb16c2456dd", "CS1": "041ffd4fadbf20fd33ee26b2ef5cd408ac132277b3404cb0df70e4d8059ddbb75701d88d75152b728c8a52f8fd88bf47019bc43c540bcb5789ef86633dac7e574b", "CS2": "0414acc9da587f50fa17e1c2318bbebbae619b9646ae6bd2ccac7039a9e802164e22cc4fcf74aea64fde8422cfecd276485881f86a2839b2e6a96f2bf992d01680", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0403335166022fbc9974df15d888dd34fe9e47542977a28bbe48ed2d483f10351f172ad815a40694e1efbf98a3ef595624227e274964d8f15351f28207e1007c0d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "041912e1a757b8d8cd04b49c8f8df8c420a03227f7ee6173571673fedee7d57d0a05ef3ef23f23b1ea4f0947bb5e350471da51d6ae2a88b41def85ba839f497a67", "U": "0415af6330bdd55eb8e54121e75b375257cec122430b6f1a4a170d4f4e7015cc691a2e5c58ea0797f1ca3bf3d34e8248e0d0b51772807209dc335efcf65578505f", "SERVER_OUTPUT": 0, "Y": "141ddf63343cb13a607f685db4a7bb49fc718570c5c09bd3cec0310e9e228c98", "X": "02137256a77a447b0749db17f801ebc551b7a25b8a8813f3f0c528b9a9471b70", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 222, "UT": "04065919e0e40ffc634109b2a48d859fbc1111f0af810f09b630988088d3af4d5515f3d4b58e27f827de85e041723383a7bf42c0350c6a4d6094b304508b356d28", "MS2": "151960a0f1173aa9f5b2fca4d1103b0c89279588ba8dc19117bdc508b2ff3ae2", "MS1": "193d80b08da455e05b254096b5711f0b0406607cd47380f95220103713c7cfc5", "CLIENT_SECRET": "0420a8c12003c197a0f79372084763d7d4c358e0104aa85ff0cd46a850a3df047017ceb9cb0fef473a04d697bc02dc4ca52ca4569330a4a65f78f22ed2d54bc700"}, {"TimeValue": 1437055598, "SS1": "2029a58d0dea53ee3c05627b3b151e849ea7e3816b2b595d7ded9302626645781d75a780791b8a59cb1ef205167273a54906ab26a644dc609c421746c5421b4f232024d8bc4620bd9d42cdd926d6c476a8bfbf91fe5c38c36e469b7bbbaf84f50ccf7e56e7ca49b7dda4b5acebbe5d3e0d01a1aaf87bc463ef03abc8ba91de87", "SS2": "039ab5b7bbc6aa8f40a9f79932c5d0c6d05dc7d0bc82d9d753305c62dac1b03104822761e127903baa5391af0228babde94fc827e7ad0c0a9c64f4ea6c61affa13f833597ad1a48c053c06ef4691d2bd7a609b37d2e6fc235bca24f9f50b23661ee74f28d8f77d10ad31ddf1aa9eb5c040af56241cbb411286942e81a07d7662", "DATE": 16655, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "2239be842a7f8cba6bf2e426e6b4f8de0b93592e002a0278e5eb464b12bebc1a0ac5d9b66936c605b0447f46b8b3ef4a903034583253b8d8cc23f4f60dd9e28904bd8f164908e585203c5783358f084168f6100f0de80dfc31cc62f4cdaff8081c03efe70d0b36edd81ece6fcdd1e8808a03a96834cd1f9772d50550519d608b", "SEC": "04101a09037271c3827d102ac5eced12b3d1ed4b14fff2031c0edff3b4c3f1220119644c5f3c7d5e7e272bcba0ce82cea76e0867356169a75ce55a3cecee1d60cc", "TP2": "041d028f5a3233162c1af39bd6e1b023366d65e5f860ac6a3549b72253414c03620c0264fa0e4645ee4e5fd7fb9ef2ab17cb0d0e3adf91e4a6fd636e70ee3f458d", "TP1": "04214cc7464e17265614aa7ad87a38c6b0b32b094fbbde5c00d2ca46d6da8d28a51e76e4daec3521978d6c5425a6cdf79e6ab67b86c2f5e302341f8ef7bceb1d7d", "CS1": "041cc3230509fe8524eef3132f1b5b750280fca269d440352c310a10b14aa6e6ac0d37adc4e239ac41f11f22905ae0e289b433cf6722b8a9aa880151b9ff569c3c", "CS2": "040720bcf0171c4bf09f3a306687ba9a6a61bc70821a84f44f14b63a23c34700ff0adde45cc778e79dca2cabf89d9e50eee3c07db8c9b579c074fc7cf2763441ea", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "042196f62dab41fc82ebb40eca3efd5ca6ddb19dff295b727f6c8ff62d6058eadb19d1c92647e181f8575ccb81b2792034bf4fd7bd1743ac60cc9d808be081f3d1", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040be398282a4087ddee0702f58320be93b83945377aad1912759c1d77a02a774019e8b882c39c57e0a30883e552278387537d98a7c381a245a8111212aae4ac6d", "U": "04083b808a46bcd984e8a96cb1c56d93c74f7665477945e5096348150e4a3143f11ca5630670e0949bc98a50e27c387ef706b73bc4226d0174b5624d35addf38a3", "SERVER_OUTPUT": 0, "Y": "1dee85a792b9a3406e2e0f24903dded97877c83aaa33eba0e3afbc0591a6d098", "X": "053a00a3e01bc9575d15680830a15e0078b91d0c72f7c2b3ac98a5c1fc662b0c", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 223, "UT": "0417d8da00124065af34c55bee7da6c166f2bfb8cab1e8dcc424fe87d2b82dea7803fae98438d3b44ea91f8464bc736739ae87b75d5508b5f6ce593cbb73e993bb", "MS2": "134122c67372a17a1905fb72c865048ab10e14865d87c546c71ca5d7bb1eb7c8", "MS1": "0806b6bcda84c8336b09041ecff46e10cc4d842b49ecca8664ea056e1c53789d", "CLIENT_SECRET": "041ec9bcc86bcba54592eb14c8d5d204384cd0b7c060768cf6de7faa9b58652c990385dd8aad559edcbb5c8bfc5de78e35b9b7ec3384c94607e10de545691cc9b7"}, {"TimeValue": 1437055598, "SS1": "19ab2925ccf7d0671600c12eb6dc5994add3fe59ee75f8d86379b66fc70a03331f5d83e9afb6ce78c726fbcd0a8899d608ff5825c8317bd7aca84113bf1212fb043906ef5d98cd5e1ab7c710e92f1a5e7b60f29bd74ae9ec6bbbeb5e720b455a1e93dc33d7a6259eea1272c8c55e80e6a7587b066125baa473b19914489ad9a3", "SS2": "1e77585348eba9e777c60a3a3c6ae28bd9038d3cd9c935064dd868aecb6fe7f91efefd57a021ec8b31e8a57cfd56436e1c8235c54c5425b89567273ff0ee8bab1d2eef862ab6b12be0936e29679c3efb4a21957f09b066abd111a62f7c4b5fd911e43eb7d06346c3acc00d44c4609c9c7bfa23fcf9dc48cc66d7571a1d3eb84e", "DATE": 16656, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "1d99e6169159aa77b3356a3fd88a55adf7f760a088964caf8417906828faedd216180e48a3e426d2c42cd5cfc36bd0c27a40e64d73cbdba15dae6a98752eb5c40e63cb6941508da171a9d710543078aa97f1f6005d027a59f047604121b4d129005a22230f9359ce8a7e4488282cc7bf61d0d1293ce7a36ccef7f5338b9fb2dd", "SEC": "04008add4db44abbeed14c86a2fff3d32c5d06a10e23faa9eb4e799d0f43f0ae7f20bc58faee20e0bcf8d058a49c69275ea3fca7735d35408e8cb28f232b31ca4e", "TP2": "0414a7d206621f41780999d7fc80a62ebd471ee7d2664f5c4afb44c4f4ec1d953f227277d3ff3cf98561344ef305eb05c2f8c33dffa7f75e7970853a7b0709a473", "TP1": "040ebd82a90071a54d8e730f0e6a3ab82dcbe15d104696bb4516fad28cdff4c8951b80db6daff64bf5ec828173247bde2f3285e58877d8b456a3e5d9d6ad0b69bb", "CS1": "041b56a4d672fc7c48425e547d4336d72b1b221e5776e5385b20a202614bcb105618073779a6edcf5ecda1458ea2f97938fe18ab63001967ccac6814f8a551b03b", "CS2": "04228599595a6a98ed80d44af883a6442d3d3ce774e3a302a3883d6590c64f40ec1ff13be71dbb0b429cc85eab8cb912c384ae478f4b31ec8c3d53b69e0c3658df", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04209454bdc12c6facf0ddef3468b74cee4ee65027629f3d6e7248bc6693923e3310b2c83a1ec65d3f2883b0ec3eaede19401d698b01c06e4d919c704dde081ded", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040e3952944e5b14602ee0cb3a03e3f0313f51026377e352589c044f9425a6fa5a0d6cd35cfae8b0307665fe078e0dae151424d7de7b388557292a0e0cfb607745", "U": "0412b61aa9df93e6023fbf4ffe28d313b7fd9497f0f06a1d755c30a68cefa5e4f1209912a96208d7d005961d262c9989e75209b609c35ab106dcd62183a31bda63", "SERVER_OUTPUT": 0, "Y": "011b0780f72ad82e2f8f166b09ccb141a5a149e449f513f032071fd1ed615c7f", "X": "0d55b71349b595e892751e88288b3d0d194899b8fc893e4b1be3b7e73a2a774d", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 224, "UT": "040d46e985f6c8c59a948912da54974f87578b5fe0929e091c16aecbd0ab38b74e20dfd09cbfd47498a3d1254119a60f9b7d34558a94c1af0b1e3f008b2a7cf677", "MS2": "08fab4bea65c82681521fe2259aadf385343500cb38a2daf8c4f16352acb71ef", "MS1": "1fb3bf791dc70b5fb05993a98657c5d3aa20ba0c92804cb1ddfcfd4ed353b285", "CLIENT_SECRET": "0401a50cdb8f5b427d0bbe1139d3544a86a5944669ee5e22fe386b7582d6a01b6618ab6d1552d3fcde3f0e53b784af7e2036b5c7aaae8d10f0ab137dfdffddfef1"}, {"TimeValue": 1437055598, "SS1": "0055c6150d5598a194277605ee2467a81148ee16b68aee6fb738b2aa92cc6b390eaf301571421420f066c5597a8e14c5f17579f1e23421dba00dc0fea12a07da141450804d6a367da841e22e456871c68a1a9dfe850b6807bbabb1d0fe21bb670e1697f8bc77e5b711b09fec4e9b06c89fd612e4efa4bd5daf558d012dbfdb34", "SS2": "13aa24918ad9f02a2105958af58dd08c9c9951c50aa36d7dc557755f8c3f5aa51698fe8ff53df196013c4ab887d14a62f28837576f467cb385a4bd30763f8e260842f34da423477c51cb3d2fe4b25896f023bcd3aee439d9f2a58acbe720831904fdfbeec4e7c0a440ce2b5b567d8e243f7f4f6e88c6b825938b9ba4c2bfe493", "DATE": 16657, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "09cc5b2321c3b7c039c981e6c02855172e50758f6adec63cf79542e65278a2d400c5f708f53008a5a32023c0edc222175edbc78750cf065c7ed2ac051cbb3aed238ee3edab49622de577763e6e2cc2d709a6ccd6eeb6741b66ecae26b2729f7513da75988a1307a0e67d847e3abd412abb95c26532d867026cfe1dd40abe792c", "SEC": "0402f3d2a532a876e50b5e040a8c033ffea7aad1ab7d579fa1720a9d038164a27601eabacac8faccc43ae1273160ac684e317cb76335e67bc3125ac292f1f7da08", "TP2": "040be6964621b9cd0a0da865baccb02b28478fd2f629dd358ba894fe2ed19ffc0a0b469d877676241332770169e1c610729cc38b8932e390c9efd38732911d1ab3", "TP1": "0404e880d3a95325e412ebdb0fcbd5763dcfa7d04649c6b0de48cce1b61001d26c1196c5b4f6252d512ea66cbe7acc41834a342c9380646f5eb439bc385b6701d2", "CS1": "0413c61df00ffd1bb50ee401e556a8a3384fdca12149f2d46448babb2cdf0f6443006909ce61499e16eaf1ceb51600931daf864485989bfabcb4058287cb52d637", "CS2": "041c5dddb68939edb6e26cd25271867c74267c6a111064d157823a3e75df2e43db01c8189fa5d39cf4dec0bfe5d81d75ff341fe38afff82ba589098040b41d04e0", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04221441aa312644ec829e27aaac221b8b848e98d767db3cfd10c64198b8617e3c21235788f017ef04b1a8a13c04d6fe44d69ed83649a64539782aec92b11af7d7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0401e54735f017445f57052457f530eff4d01ce275cf00a778becdef3df83a5970236942c645711a135d393e8cc31c6f7248b5ed54e147b669da72934b7f87ed85", "U": "041be3fd2d0adf0f58f8e8e033634ae0687c471704cc510368d3e063429dbfa56f169a4fec631bdb79619ed313d074881fc1a38fa4a17cc6c40de62ded3d63517b", "SERVER_OUTPUT": 0, "Y": "009546b531e7d1857982d06c2afb4b1d35344efeb9c2b30fb77b3f475735a2f8", "X": "0b432bd3a649ddd55aecdfd67a0623089011de4011506ced7b974a4ae6ba6c4f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 225, "UT": "041321a283b14ece94e8f4645480c1c4f885494d4bad0ce75fa6b5baaa7cc4b0f1073ae580338f91650cc8a5a76dd0fa8a9db8a95fb66742f47ca8ef9ae179d20c", "MS2": "13fc58bf70bd7b289237733ff26e1f9a2063498553c11a1962581fe240c7ba2a", "MS1": "03cf91401f062804950f1f267d9a466ae5b3f6214d530c06926be0d1929fae44", "CLIENT_SECRET": "0416b0eefebaa6aa9f6a370d60426897a9ddc06006f4d5805ee6e2150d38b04f3a040545077b45e6f5943db5c8f1b8da252babc0f07a9eb0af850bcfb33ebf13a2"}, {"TimeValue": 1437055598, "SS1": "056574a7e420e12d021fd409dbd47d32726ad5ad57393e58bcd0d15de57f570d06ae67385f60ba8cf3759433b40fee8061b642d96278cd1591a8e0ae13916bf70cd7bf59384c143a857285223a4960e90b7e2791e26ed9befd27f2127f5305c811a7d7d2a7555d35fd753b1fb9a174735bfa340938ed98ba972e58aadc03186f", "SS2": "0d4ee55a339b9c0a85add759176b98602bf57d7836edf6df28310005f6e80e56215323575e7615cab46e9dff2ff72098be670b163a6f9ff3dc8515b31c672f5618d8a939787bfeb39db569787faef5e3e1792e190352759136af93db4bb2739212f44258de61dde2b8df04b2e5ab2db98be6299d4991bb1882967f55b77fdfaf", "DATE": 16658, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "0f7dbb851e530a8616f61832665520451d587f10abbf76e08964f979bb33c09007801f92d16ef15311d522e0452520f3ff8f248c78a3c44d592bf9814d5901610113d8df0aa243200485ea8ee03a840ba893df23e53e51f5764f75600894a75f1fb5eaeb4c3813fc461d3d7bd9637d804b63873b94ec000aedb70e33d03a1c0c", "SEC": "041201c0a6b5ac0ee1c4347decfcfa92e13e30e7b00fc3f70792f7b6c35829c261176ca6f9a7c18557c483f86a78d7299409a594fd99ae6673b1ee12e9b875b987", "TP2": "0419c0a64b59d29cbe9e3926a6c3caaf1148680375783304580bc1542dce77c20612084bc0d5cbbc1fe2773ef9cec758c4c991a3af02fc4de3f46596cd1afe88b0", "TP1": "0409448564b27e572c8e82b0a175e611dcc9bc2ec87d0783cf4e048033b107fa271685352838146783ecf77ea27f8e74bf03abff0781ac11720c8e99a56c2ccc8d", "CS1": "0410b0bb941225e8c3412cd9b9e9f8788297923fee95187178f37ab6457417f52a0a79a18d68b72d5de3f688ffe893991703dbd88bd273c4064c635dcb926b41bb", "CS2": "0402d8b1a1bd8a767d350fdb0583186a8e89928fc7ebbb333443fbce8fcc53335618f7171ecdcc4962c30378daf8ef5319af8f5e8f4e6d5b66ee5341c01a1902d8", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04068218b3f87f74447b65c8004c9774214b18c52883440bba190e63720f2f8bd506e65a78f165630ec2718b608d793a92a2dd6678d3ec603c61bfe5fb6de18cf2", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040e20517b19f17f2df5153b423a870fae7a7fbec0396e9b6a3472c05f48ec81440c8ab0a28979ab64d285838f262e283183ac0b80a1897fd5bc0764d491a500d7", "U": "04014b07dc82d822bcffdf2e0713546a973e1a8b63e3b612bcaf81d9534ec93aab1f313c78fce789c76600dbe08aac9b10020b69a9989f7e367bc3825f77885250", "SERVER_OUTPUT": 0, "Y": "162c68c72dda9cddbf911d256e8706bd714f9c4e1ad4d036863b6c5272919820", "X": "107112ba7b750d8ad7da882601b92ccb4fb84b099885c589bccd3734ecab4120", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 226, "UT": "040ec0bfbeb72bb4a1c5b5da4377ff74b19e3bf1122664e4136cfb95a24ae6917d1a6dbb073738a10934e4f8ef1495957aeaa1e587a76299d1efc7873f8a15fea7", "MS2": "075e8f47ce2b51bd7ccb8280e5b1479ed839d5710d996cee4c7e6c82c1b726e5", "MS1": "10735e3953dd0ca1f58a226be677e916ab1a7e825e6fab3e56832b99f3f4315e", "CLIENT_SECRET": "040507cfadbf55bc671ffed1b37968d786cbc5646d435bf4ca67d215212cfcf80722fddadb6fc94f050bf856bb830d7ca3f97bfb50142c2fa2b77a548cffd05ee4"}, {"TimeValue": 1437055598, "SS1": "01cbf0e1c0b3bfb3b5e5b0d330d5f608c5bd61841c8c0e62f008ac9c45a3e4b612a04670f7fff4b5c48f7c6178c537c76a7d9063010b8eb471789670f8c962dc1e051f2ae04b59de6295d4386eeed7c190b423035ce61288d281f99c53924cad1bd4da0535153a4fc777439f7818cb82e41d3f4bdc8d552022b21ed0bbfedf51", "SS2": "1012651ce6b6f71a64884be5cba5cf256417f28add68818d70d9ee1f2d0d40ac1cc0ffa96fff26308dc9fb6257deeb037107d6afc9cc86707caf7da15060d9400efe9203595808034b492f38f7aada4b34496b55eb53e69a38b590c52df674bc1bf508acac077ef2a33199faa0ae4cfbf5d7f00b47c2e950e90d3da15983608a", "DATE": 16659, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "1d7ccd8125e6c89ad0f36bc2fafb03e02d8d200f57ff90cc909cee244d60adab07716ac0ecda6fdc56ab3039cc8f24d06a2e6ad79559b2f2ac8c2898ad50ce9d2201579a58e32347b4f1eb2532f9c9e9d3891ad3938030b6411cc53191e9065e111a1168448098578144a8c2c261b268b06f0e14dede05d3606c87e835261020", "SEC": "0400a8b5224d0fe1511fe3ff38c733c79ad09c0b188879adf741347517cb4170980692fed17a3a8cf3f121f54e241d1cd9d898f4e192dcaecce19d6ca61b61b391", "TP2": "041a32a5ac6a285978715d730dd7551e8a36f8598d80d521dda33651c8c46d3bb81e724c62f1f0e99c08ff4ce1a068633080ac77f25d90154dc19cba810cb80f86", "TP1": "0411759afaf2ace70c3bb96260f9085b71eb017edceac94df5ba19b41de63b0bea01d1cbc2fd829e5a248173df810afce22b85ca6d4fad8dc05ffee97f373bee33", "CS1": "040217999a4675e735513fa131e9a6ca48c3eeb2a01945d1b77f933ec70a9f5b680d6bc60913431d5fb0424dc82d15087f9221c829d815b83c45fd4625acca148d", "CS2": "0418d158119ddd1c6a20a4ff0511aeb72f53b8bf070523c5c4d54301752553135d0386f24b6d598068a23532214ddfa14530fa01bebebd259c77fbe4ade5fbfafd", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04143de1ae0bed8c96e003598cd708ee0f2751aa2a6658fb462e3e50959612d5a105a9029a40856c0661306f84a7d3e5962dee3c138c79f687824aab2ff7de499d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0421b55a76582dfc2962a1f0322c83b6653afb803056fcce3bc47618f80acf65ee14ebeef662b6c4faf75d34f55942beb3e1b11b193438759143c5e32052971905", "U": "04188926462754474f9fd654df0c697157ecb9f3d708f7d9ed7696fcf81396724b23628f8dec3429efc1b232b6f1d6462172245843b3f9eb30641a44edb84936ec", "SERVER_OUTPUT": 0, "Y": "0d42c21b3271d571afebbadd8c454ad36d72158a187771ee65ad3e858de10b78", "X": "0ae05b22ed4479ae9c22008f85a7d325640d49a8f49c737e0600b653dc25340d", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 227, "UT": "04157dabf15c40fe1c79e4b3190768d7f6e81582ec24d6ad15405f96b2000cc6120ee0fbf2b6b5feb78c9df2dd1d411364d820a2d1013779cdcbab0fcd6fc9f1fd", "MS2": "08cc4c80d01b719b43d133298ff9b6af0bd26496fbb4269bb322c162aba0c247", "MS1": "1f7ebf22417e823044e3a5420a52585316881d8519b3a4d82b459dff8e3026e2", "CLIENT_SECRET": "04232ec0b7950947b2343a8e001d45735f7cf9592c1ea5e5f9b1e4a484e4eb9d291f0609edcdedbbf6354f153db8226fedb33cd2cfe760b6eaf8e82f342f79ab04"}, {"TimeValue": 1437055598, "SS1": "061199f905f149fe6c3e85c6bd0fab33ae9031a19aa8d62af7f6cf5100c720da1efc32b573cdf6cbd924becf83ee36fc4806f5ac62876f2e7fd91abe51a8dc55026a8b12a6609ca13188a7649ec08e2e8faff8081c562e62daab7f49a96d888202250b73de7c51e9d02a8df3d3666978c19b6991c7cdad7318855065263075c4", "SS2": "1ec0651831e5f5e1e6d4bda9a7f255698d5f59f0ee12647c27e5e4f61523861902151d32b1f6166d08049f1849e7b040f38b8e4fa26ddd055bb7a86b4a9162ca06a4ac0648375f59bb288d1482df0b14ad4c4a915203557a5185b1f2b2ea52971b53241a11197aa20f53bf5465f620fa1c3be429adeffe6005a88ebdacddcd21", "DATE": 16660, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "046db33937a6c489d264929a59ca3380c415b5b57da60c18953b50ad2d18866e1baf8827e3cfdd143504ff1b037203e9a06d60e96563728be00af1f4bb31106800328a1cf0b709750af6daf01a0b5e6508d002860c95c6c9b8229a3e285670de085d0636feebe185cc349955046970970769267b601ca4c6326f358cd061107d", "SEC": "04175c9703363437d860437a2302fd4704e826edd94fa52e083d779eafad5d15c5205dbcac4e5b623699999e7dd067ab7748a28417507f63544146ba68f87bfb52", "TP2": "040a0bdbd62838913a448e0b50fcea2212a35ed0a05970daae69901e7eb840df85106edf8dba86021e145646359b84f5770971f66bf4eac0fe569ea250cf3004ce", "TP1": "041d6b754d6e5175cc0789c1daeb784feba1c6bbf4ccccd630f61bedbd5a3c7fb20af506ab8c6d042b4160f8a07670c4545e2c5ae99022db6b1b31de3e9367b27a", "CS1": "040b4ca17b4c1fc60cb07a9e07c90827a0dc6c12fb98b1f37a4231ddb6e202ec9505e8de61b2c9094b69b255c1cfb6d25572cd009d099205acae86636936db073f", "CS2": "0414282da9dde7f62ac3e38e83e1d3ef420181d405778500481344ac7be37417361ec25ebb344acc6b04b36b39667fdb06315160710b0e4e3318c86371ab0230db", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "041d6c6951251033498f68884bb1defd112feb24b210c0d8a18398402b57117e5515f423c89d02fa893ed175b236cbe38620b986023a7f858b5e3e18b5b944d928", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0412f25ca56c332b977b1000cfe1248b3462e84fbba15c93c0b6afec7e6c957570142efc7fe7116a04f15484f18ed208cc8b8872900d1ea9394b7d3b36d5c85c9d", "U": "041127a1298d56bb7e9fe6b03f05a29d60630915b5b34a4ffd63bb77365e5a644d092c318e77ae3ff8f0b06316331659cb22d7e2d7f388bcd1b334bded0b0b0165", "SERVER_OUTPUT": 0, "Y": "009a9639cd8ad8cb728dcc8aa450c80f5715b1532f92f0548c2ca1d7140a130a", "X": "062b0a097fb7a27a655247cab63dbeffab71be5fb02d9a296ac8a8dff4a9e45c", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 228, "UT": "0413e5479517f828a968c71a6d77fd9ab7e2b62a92f87ec31802941e093b82f3ae0c420c56589efdb159de2ec69df312315339f73de72c2a35ee725a9f268f4323", "MS2": "12dbbf928876546366e7d23439dc2ec0b9cae8eac6d5e66ad6d320c65594d525", "MS1": "017d062a983ac2d519f3899a4e5cec6be252927a65ef24bc04405c99f67bf6dd", "CLIENT_SECRET": "040e113bed15a1d417735f4d202955be215ec8f7f8224eac24bc1592f7ea1fc56d19cdd5391fc1c3ff82c1722b4b931842f78406e29d2324d29051444c9a9927d9"}, {"TimeValue": 1437055598, "SS1": "1a15118ba946d2161dc0b2ab44786f4bc62421a3e0e08e676e586e1eb326a4e21d9291cc138526ab5a035d51fe7eb7a719a9450e7638dee613cca2e4e2985fe12343fa2670f35a86df8df157c4d5060bfb822d6065fad9075fef8838620e314a16a4a8868d7d2e9096a45e72b149e5caac046da028124573f77722cc0dd619ca", "SS2": "02f1781807e575b8828f3e57b528b2370c27ea65c5c45b64b25b52db35e444cb21cecf83ce045dc468df798ae9b0314c98fae2bce9ed78d529d468fa92c99f821cfb4771f865fd7b037313fb76233c17f1e4905409524716adc93389b8b7803d01b1929cf42f727e971615106f5e874a1c2f8a576f6779f5f8dca1b15b5009a2", "DATE": 16661, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "161597b173f38cd54b45ae78857696c35ac0cc22d1d959cd795809e37def5ee82054f735388f891bed8658e7c796480d1d62b1e230b0966665a85ca9970c5e940f33cb5e10287b24ddc747e86333a45006def37becf4189c3388e75d5dadb0b103769194eb4925fb47cd62a6612cb2ed6cbb8f317d5e83cc2ef6e14d2559bfe6", "SEC": "0421b2ee8de964e28119e0c044a9623a5a9ffc08ae429eb3e25f382a9a39b2df12142f453f8460e138983e8b17f4df7e40c149a15c309be3b5215bbebae3b09889", "TP2": "040fb971118fa51c28b28764263daaf22b99e9c785ca772964419fa585ce2f150421aa4ea45664795b5e2c419c4cac3dcc57992db9049780694c8d556924879454", "TP1": "041e05a62120e9397de6e6961fc76641c4c2fd6f569048d83f9d2d71e07f70f1e60c253f925221cde3affd7243824048500741e5ce97787a01226be5825c47cadb", "CS1": "04105184b739883e6b282fbdcd747f4501f45436a2c952808042a78dd385e3a9e500dc216ac6e7e6921a49054946602bb41b2678ee86b5c0e20f7aaf198d83044b", "CS2": "04173df305867245cb91a030a8d9e078b87d74414665b5bd56446def815b0ec64223f96fe9ca2b56139a3ad635e0d0e24c13234667c4a6625609b9a14bd8b623c8", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "042257bced1f3be627630658029e303f5397f7a206f084e1ba13fec349d6a37dc2136e45d9034671275b7f76e87caaad3ca8a4442149e4c7e1b8ec6a2f60d66dd7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "041c3ec0a1f27ef852fd851a1b3d93760ef4efd10535864fad45345d6c4c4dab090fbf59966c7eeac7cf43b3b77a1738977d9eadcd4e3e95edf1f52bd3891f55fd", "U": "041af2380d49b6db11c60227d009322505bb101a5e83b42e8c022a1461ce122603070b9786beb9f12a7c2577e756a29ebdf0745ddff9891b6c6c5c634f8092d4a0", "SERVER_OUTPUT": 0, "Y": "0a113d76bd55b3a6a4ae43f42cd6d3a6513791466af9d71f7ae7fd26e7c0b1b6", "X": "15fa2ca89ddab0ae8f2d2fc755d1dc0b81aba58d0f2b9042d6e8a62ba7bcfb06", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 229, "UT": "0404ae93e5012000d82a5c3734a0ab2b7a50bcf6a94feacc94f16c28eb08117d3005a6e640f330cd70d0c0dc46b912e69b35bbfa991d4508a5e0238d4c5ba480a1", "MS2": "0f1ac0084612f2cab1cfd2f5d25867bb933cb7015185688d42599210f368d7a5", "MS1": "216a4d7a43e4da280196fcc69e8867e8a0ff56062b34d15d44914c1567f5e744", "CLIENT_SECRET": "040775430f1e90eac4c0e3f7783ff6e0f1fe990007fd688cd8fea6c739374ba9272272dab74e5a92da628e7e5865e5a39d6f13d9b9463b418c14a3f0991e74fa4e"}, {"TimeValue": 1437055598, "SS1": "153b12e6365ea4ecb24e969cb533cd45db618c0bfd2509898e91d33c8ec81d9e05d6ad419e0e42947c85a75ea076e3087ee993c085828fdb1479c07acde9297b1a66b4bbca8b05fe4a0f6297b88f8f4b1d51d1c4378699f1c3720550545455320e1663a0fac019eaa39c966222ac234fe3cdca333dac098afc98b0a9cbbc56a7", "SS2": "077e058d40be0e5393411e870a04e12fcc0f11162087c2b70d206f7a0e2f52f00b208ebfb9806477e35aabc7dc010a0e4fd63fa17b193ab1c5cfabe94396ce76085fef2ce3d1e10a9e3c309a8c87e9b1c48f05dd8d057e23a249782adae7a569052ad690f4757994a4dd20da4df25fe67cc55f4d44e67e61767bc22126de431b", "DATE": 16662, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "2351aab3372987731ae807903bc767320e9f2ef01f198a4da6fef0df8916ce6b0420c814e575cd7c45653f386c0dc3f87d58fee5911df508aaebf4f7f588f0321b485f2e38bbb3e36b1706c4d72e03a7e93da9c8a233d2cd600a2b2353598f211cec17255102a8a50810ed015ad1c7d91a9bc9ef8f75e8c43c17280c2856d7d4", "SEC": "040dc9ab92abc9cf3557f9763606ca6d9c701cf33a45b39c248d42972e86fa02b90d5a9eae9dee647e65ee61cb6f26698501d4e70f82d0a4ed8515b47ec7ca9a73", "TP2": "0407d95e0fc0de19aa7038b3f273b45eaeb17449f25e634904ac2417f9a8ec49c50ee6944fba2795f5182732e2b14992d9e46e404713cfdd690b9e66817b68d69b", "TP1": "0406a0121fd0b1dfe7a94b6c9a31da60deb5da027586ebc0522440d4e0580177a8229c8dce3f2979a090757282353692c3794e62b1a561e50de18520cf48c2da6e", "CS1": "04164b1050496ad310c1f4ce6f10570efbe005d84a01126eb9661f8cfe9fbc6e3a09f8ec72336739dc4f13d0a5ac351889b67cba9fa7dd4240beeb81b3413a74a8", "CS2": "0400d9b817c6fd1a2bc2d6ed6a79ae19e41bcc0de8d6b63da21cdf7c077a1d5e2f0bb2a752ef5c52929e2e86a5a5115baca82a51be03babf676fee6db944b9347b", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04119af10569ac24a86ecf5469f12dd8b2a03d10deac3adedd520beb679a0e27781559ccff6180c08e1236e60a957fe4376888ab2b48c9177fae8702d3e25464ab", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "042043247c7863346cf7e54480e37cdbb2218e0b5ec0032c0ca9a3576a7cbe9e98011d55e646eed9ddd16f42122faeab78b3075db2f28b67e7530a3241008958a6", "U": "0403de3fee61e81a28208e6da505279cd198b52511405ae44785a82d742671b6a51f7a79e03d6289613d557776cf331dcd648996d99e1d970273ed5721bc2374fa", "SERVER_OUTPUT": 0, "Y": "00d16fb1ac081ef4402fa5b140bda9f622f1912b30e1785bf7a0a31e56b4d3b5", "X": "1a1ddd05535e578ca05773ae405bd4ceec9b3ce6b361de47eba7b460105e933a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 230, "UT": "041b871e47b75519b375dc71f76856c6b405964aa6b9385a27074b704f8914bc7c0e80a98799fcd9a005ae92f735745021a3ac30afc5bce1ac369e0ac0374ad9b0", "MS2": "1f11226fc7621f0fb4e0197444f566fb3fea2427c211ad9ec3c39c685c66b12c", "MS1": "194f3ac28e84a02422f8a020fbd6d4140a7a04f91d670c92b82a3449602524f7", "CLIENT_SECRET": "040c22d4a53ef9c05032fee35c46e76a7da47697349bfa4d903291e277482311c500a619ef3a884d5fc79dbb2d6b13fc995902471a0087e7f53e56cbc21056bce8"}, {"TimeValue": 1437055598, "SS1": "14afe3e44ea9cacee6bd1f6cf6c80bc001a11965bac01f70317823f0fe643d4513c2f7ce8a3d8141e1ca3498b32ed343019fd1b6b4d6f8fe7884a92cbc86676c1b7a0e03db5a7a98024b0332d804b4542ffb1699b5637c867310261714cf198112582f4ef6cd6b3d1c140a8ba6b46b32f997d411ac9280586abf986c5dd15a3c", "SS2": "0136345a63aa430b78653887e43fa0b16bf68fdf40cf95eecaae1950de7d99e41329d4bfff3e32c896614a06f92d4145f996d3ae34f88379233245bce1f3419f21ad89a6223976d88c0a51dec9da0c13da7396c7158501cf3df8befa02126669209ddd7ae09f17f913761b8e85f2533e34d88434a3d9bac1dc0b6276db04dc50", "DATE": 16663, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "197039721a023ee6c15d2eea3b63a274d0d84ec6f8f454c7dcde303629ffb5e010300f14c2368bddd9025d63e98fa7d4a571adf49381d9164a96ad506539348a1fa169349d9d9907e270ae725b72b3a268705e0d8c22e13615db66d3462eeed01ba3291e5caf73eaf7460092dd28845690d57aed8d885d07935a00096398b73f", "SEC": "041c72827ceee0c1e58ffeded05fac2341f51605002fb0abffa7383e03885ebbaf18a3d161f498d1351bec861854a74a844f0c1084d230832d518b02b215f1fbc9", "TP2": "041d098f9d50611e0964bb59150f2d6ed45cbf5b3b418dfb3139935159740a98e51474ecd1b8da2badc5a2adfe3c9655bd0e8d3c9e721be32daa281ae54529c274", "TP1": "0403bd79f6386946dff468a947caf7caf9e3aa90e06680a7ee4eec54e213d7428011fb8b63e053de036496ebb543aeb4ec5297121e3f73a1a19068fc07b0307599", "CS1": "0403a5d65086814619e6517f21c393b763a4a4ae296f34ba476a71632b5bdac2f615dc12cc979ee82cf7a46e55e3629fb8d676027dcb29856b11344b8bd64698c2", "CS2": "04227b276785578489afe065a0306deac6bf35266c9c86494da369e9d7b91a980303f7f31cef674b56e517cc74a8618f4b11f019889d34416579be1ff9d58fc699", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "040a5d9b3c61ba36cecd98cc7127e2873688fe9c6fa361c5c90b907de689e0de0e217e9a7858a91dc0e855e9fe8787fda4ebd3bfdc057d8a8504b82f4e8332b40c", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0417b9db8e0c881d67aca8435ab8574568b648cc814bf827174f63f26503adc3df1894e8947ea972ce1fa03c95d580b301dafadccfc5a424d9ae774472fbf4f575", "U": "04215ab730bfa0ffda476edce89899ed6b6b9ec73522e21980ba593f8eaa89ca9a0165d6365d3b2cd4612fbf22212718e4ee3a337f2d4a0f4ffa2f56693411c92e", "SERVER_OUTPUT": 0, "Y": "148b7cfab7cee7d047681231d2a1df3b356c2e2c749e5f16f2dd5d5bee1366e9", "X": "18b053ec571854cab5916d9c11538eeeb8d089c8d1b639ffa50d0bb4a986176d", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 231, "UT": "04193f9184f5351515c4419efc6e078cb1d73d728c001d29b8c679bc8c4587ef89010419f4368d71f320aef4db19df67bde7a72b6d40296953875ac00a26cfcbef", "MS2": "22343eba37ad77d595423a756b14dabe82a75cb84ee53635c8cb9e89b940e408", "MS1": "04b655441fef8ba27595109d2c863a9a13fcfad1b2ae6ba7b3d9bf17b97a7779", "CLIENT_SECRET": "041e393424f7c79d13dd4afd410afe1c5401bb7a330cdf525012c9479c3ca40c720188679196f4296c1846758b9b97719ba3e6dbbdc1934dfdd2c14356d675f480"}, {"TimeValue": 1437055598, "SS1": "16d6863ca482786a6af208c8b3d257e277e592c6c3bb21be4554cef498e4e4db056276c7e68358731e73ff9e3f73973feff5e5dbc451027921f4f9e31e7f5cf7055c873af125231e4072242f15fdabbf0ef1fdc38742cbb4b8eea60afc712049232a428d0a1403f5b6e3851234ec306a1c4114d2b7e155ec71a59d895ee1c692", "SS2": "0011a0ed452609c8013b20cfa6be5a47029785944ddea25c7e7deae612df18ad1afc782b9d68502fc1363e44d8a8a1eedff11ef613d48c12977f2f5f18e291cc07c181037556a494dfb8ab9a1733529cc468a79f49c57e287f88b92de34b57fc1b51754cb613968b664454868e2a333cb40c214552461e9acb7e46bc229ed097", "DATE": 16664, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "0b2f3ee93627d3c18b01295f30a6476058ade925462933370ea397be406fac391e897abf75c91514bd17784abf814361f72cd76a163828faade716e7c264b1020da8811e25d8aa19ab323b55e63f08d6e5a37c3149425577d51c4c281d1ef9b405ed599a3c7c6533ea34654f1d5b796206f43c09e008bdf1ee351dc3798e6801", "SEC": "0411ce1a2638f6b6ec1dbf82420130761e6609f697d5177a64d8b518f30936823423c10c1400107d33b1b17de0a25e7e07edcd18bff57a6ac14b9c7ef087f541ba", "TP2": "04120b107a742ac340487ae6af6ae42ebefb65296e83a28398659f60b76e10c6ee002535daf7ac0ab88f43038784f83f424985fd76c44a691dbe02dd3e94109c4c", "TP1": "0406d4481c65ddb0614959f7cabd48030e8a3252453986c656a25eaf456b41c6dc05d50e955eb5afc6226baa640872930016d3a59917cfb92625f985a14e41af6c", "CS1": "041f7f5468aa0b0bd039d1e773e875d20fc44af3ba043e240a2f8543a3282fd67703553611c52217a10d14ee6b3398631fd11985be0c04a60bec29233e33b26d9c", "CS2": "0415b06a8bd6290f8c01de3da9664b6b1cafcc5afe7562a2da470191cdb94ecacc0d00dbd7f6e78a061e21e132d6a347047a58d5a8d5c8430a6e548c9d0d73d1c7", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04152a6da07d28b2911c497f5d023558286cb5f9731c5f3954b4ae02605de5dc121e3822310b7936a3074602fab91c57c3aabe463d0f6a61976560849aaa48f34e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0418e02904f0aec182bc04f979ef2781380eccb9b610806750942f84e0fbe25be523d700a4fe8e0a4c9542ae7558b10ae018009e7317ee6ed4c07a079f1a5b68e7", "U": "0401fd7d10f1be8501319392086a7b29df9e6d36ac24ed9e857f978a4d8f67f77112d37ea412e685de2f5cf1c9d35b4b27ea8b776404689118e89dcb181bf35e38", "SERVER_OUTPUT": 0, "Y": "140adb04adf666aeeaac589210267fba0f9818db96bd59edb0ee0c732d0e58d5", "X": "0ae6ed0e8639cf37e71e31a508baa4ecb369e4dd070c794c0a6cda7464110358", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 232, "UT": "040e66ad8c3724b0a2d5f6c5f6388ef8a392b9eb798985fca3428e604fc46ccda41320a183c52385eb7974f1914035f18a497e6777e0c9a3740d00c48b66105f16", "MS2": "0027ecba05f6d5fdde8f52a20425b2140637843d247012a36215d43be8500616", "MS1": "1be3092c5e4d0425eb96bf91323721afd5731e2fabcdee00981b03d9472de23f", "CLIENT_SECRET": "04106e1ddf5eb583f7f63c3be9fcc182e5ad4bef6c4abfd6f0ddd765c41cf14375198423112512733622d329c8de35bd603c3c07f7bf86a3114e1812935a27e994"}, {"TimeValue": 1437055598, "SS1": "123221dac36d47e028836d859e5df2d9fe6b3b14d5906915c4f77346e1394caf1fd9b16f9e4a4fe7e155a0f4442ddd908a0a5999053b73e386fb26982aad7a550a91f8887783c3985fc09b3bef9b6b31231ea5bcda31f7be2020ef2c5415e92f1724eac815c66ec2910f9d6a4dc6f29219fa186773fda85a8023900857d9b1d3", "SS2": "1d96e969ceef5f00601967da0e6b87f0089e2d30d427c94306ceac9a3af1a8b317f96591d952e00e57477933b68f9475f7e4980902e7a2c4eb5749cac4da0d96039fc44753dd478d1517584d39717cc0250132d7992f13ae703ecc00b967664c146f2a4387f71aa6ec3e0e18541ef66266fa75194faa11b4df7ba87ece6373a6", "DATE": 16665, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "09f84f7896e6eecfd81c7d20bc535f468e25041beb9f01e2b1116e92cf58874b23be686becc34347eded60a9648cfba37c36afa3b062c1aa34b7a013fcf042f11446ecb9bcc95ce4b717c3ac4b16eba493ea1556eeb27a8a10e058fb4ffb4ce10fb8ddd6044e36950203447ac7a846d0c108de4d1fb7fc4814b8106e3cd2e1e2", "SEC": "0415d996e13416eda19f62c6fe3cd7e306a5be1c428bd5a33b886e33462cca8f840071e775035fe124b30ce15cdd1e1b59b1bceed84c672e48984ddcea26ad0116", "TP2": "040e85aed6630f277806bb00d867fc769e4d9d91b52040608e5cf3ca10f49689ab0eb35e6f1d1d3c461b42ec2f75ac7bee4d6d4fbeb870b20ff6fa1d0746db0c06", "TP1": "040e9910cfac682674e413bf4fc104df3d7c39117b53c8848278995903007de4f21a82a742c818a8e7b5a7f8ae528c370a6e97fd7d84cb34259a8583a73672d43e", "CS1": "0411a66d52bb3114469e33986aaa42aca991e78cc07a018d04fec71048b9fac8c40cc75402b38e64fe662949a4bee68948eb638345edfcd5492a883c7a2b5aa23c", "CS2": "041c0bf19cf2e97b0f123ff1662cc21185deb1426da3726bc037164d840824c7441f2cc92ad6d363561fef76044ce56e3c06ebc5467721e5b9f0cc2dca0c3d9af7", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04101486831de17317552a2ad7b6b7c3dcc89c8ec8552c68baaa539e2075e66d660de2d6f62f13161e06014dc7ac356ce60e94ddc12c4431da620591e567a77e7d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "042032ffc4e82ac0b4a0fcb469944b6c029b68a716c8ff8258477dc8e3fb4523bb18420aa4ce467ee40969073d633b91991acf9be6466222ed8ea27d4749dfaab6", "U": "0409c6e439e26d89f7f06eb77a1c7c06aef367c6114e240984547d54c13204f69d05af8af5856ba3356be47b8e7237cc1b835bf843661cb7cfb9a62bc0c8a92f1b", "SERVER_OUTPUT": 0, "Y": "188d4f5156de9a4c89508559fee085f90d0b25c20176433a0d9a490a34f832c8", "X": "1bf059e150d85229eda664e675dec6f13ffee255f93cf47084521981158ae563", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 233, "UT": "0409be31b172757d358e1428bb9c9ffbeeb97ef9edb99e1b6ef7778c1a34d906481cbfa9a12d596e06b8f361b64e2ff6e47f0c8626a72ccbfa662dd4b793e96474", "MS2": "070ba20b8a2f4cfca56232b70c3bb4bdc0fe75dae156e8f94686ceeddda8c374", "MS1": "10502633a0beefb6f248a71840171c45b7a5f311f840caae35932b0bd4f49619", "CLIENT_SECRET": "04029bab8b8ace02fb8aa884795f6630e00b24b6d8da818ed17a1164efcade302b1fd0bdb9acff59d94b4d9f6b253de570184407cb19713ec1b9c8c056c940c49e"}, {"TimeValue": 1437055598, "SS1": "19e160f21806e6cd66ffc0676b8bdbc42d2f544f59ffe3f9bfbb6425b78747df08c9a011e5fbd8f12f476ec075121c4e2049200c1482de10ee8afad3532f78471b055981e274f5a2d1da2a38d566962a6d75b75e065e6f23ee886fa8825907541f0b32d4d943192a09500a874efccee39c8fbc3f7605d47ca9962acad59f4607", "SS2": "0e26674fb15bafd8699916e461947750cdf860effd8b7a713160aadc38d9785a0105a48837cf73f37fe7fab63b26228d5ac82a9e6c67495118bf557673338d4207cbc9a331f3161998e3300c00353a5927a7c3ffe7b44c727e94dd9f59d3843b19fbfc173ef9b8f84af3ed5814f4e173d2818e7f815e6810a4eacb263c741e4a", "DATE": 16666, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "0e78c55b15af18efa63b76b596bc131f357d7607cd246cf5048ee7b42d28d10119068709e37b1e8925e4f21c71c6840ae05bf5e5267c59628ebd407b32b3becf16fc63a4744592edd60be21cb862998902df1a5e42ca3b5a923bd6f43174d8030b4dbb1aa94e82e4879cff3b6abf5b5a7ab0f0673d2fdbd5387e5f6a61779331", "SEC": "040558ffea65a35780c801858cb5f183f52458d8b249938ae2e29d9d22e119670a103a3d60c1bf1e5c07246aafd01a2dc9c4d19d38a46db267c92c3f4886b39602", "TP2": "0403a781b10611d59901d2dcf1a7df51deb85233ca45b52f0911a0de1204af86de175acf2d08b64e8c6564e5c1a580875cc5b021eb399e0a02b49829448e2ecc45", "TP1": "040d61a90c0104f712528fb6a93e4c39db8f3d1fde97cfecb4890d6fb8dfc50f801db7ed09c903d093f5f36568058d227c25001ad684dfa1ed715b7a7d20bba0e2", "CS1": "0420f72ff4205732bf1dfec6ffd7b49d774fec1671301c1be074b989d6ad612c7e168451fa198cd944de349a145c8f3894ab3a2128cb171650fd445a009d3acac0", "CS2": "0419d7025502178f7a16822c64535d6e63479e2d309c99cc4d5f02d79fe35f04ba140510e13d4db289d6feef84eeac4f637e04627d47ab4c06e6ca33336b1b37ce", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04122c4818faaabe174e5657dddb43f0b5f7ac7c843dc6df6c03c9684d50e8c07a0909d9a08c25a51990990bbfe4145975571749f5fb63881a83d0d36b7f4eb24f", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "041446db800132883f475823fd7384e52db9f736ba3e45ca93a667fd2f87ab8e9b13f5656754ffca6f106570263161a1a7940b135ebabb71e57d61ed1d60784684", "U": "0410073330dc8dcced985e5751bb7341dd910d172cc5f7ff0bdce377230d2262f801220607f06ac6bc2c3a2d9a4de008e5a75a40ab9e10b167cec064c7e6972514", "SERVER_OUTPUT": 0, "Y": "21342eed5aaf1177112417d37dd1321ad297e892f80767ea36fb751ec6bdce4f", "X": "0e39326e034bf2ed24de45925417bfb1a5ae3b23a5d7aa667726873e4fefe5cb", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 234, "UT": "040b01b0606b0beb940c6ac9bed3394ad0a0888b408b372386512096223f99aa6020a990a32d67c01860ec66d861bf377ef2de99a3c847a0ae9742a490fae5ba13", "MS2": "114b22eb07d78825568100ef8cff3d2dee8be4cc5fa604d44198f140a1d646d4", "MS1": "090fe78cc965cbc854096237c63a78e55309f9ca39e994bfcd038df6928b5b97", "CLIENT_SECRET": "040e5d4e5dff5a7e26527b7bd5b9ee3ffb5cf17ab4e758223ebb76a218ba7ad2140e6408c7894a2643635f8138fc0465f9736e4d5c70cf10651f8b1ba4eaa3f9b4"}, {"TimeValue": 1437055598, "SS1": "012ed60a1415934f305430b405c9f9aead7983a9332e581491a9225690fe3684095632802b8b35f768885b6cb7681816056369bb4b8ece3138aaf49d46d8519b05f36a93cf51baa7444a77967dfb6d5a8e7d49c4e816efebd648dbb2d718aa841d04e9f0429ccd1074a33b711af173828056cc44b2244ed841e2c2fa723a6f5d", "SS2": "107156ab21fc92a5f9c43c919a8affb6fa15ede4f0fb81d41cd8a0b08eb85ecc0ac14a1419c6b36eb28b3c60750a52ac343067ca8c29c1904b5cd63a946f8f0f137e675c911252d6ec365a38097b606e0fb7abaca6eb8a0bea436cd776adee630430b1754185b620b36f6b52d4b3065dbb81c9feb8f1633e88c1f6d80158be02", "DATE": 16667, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "1c314316d3e059ae676c01191012365dc2850fc59e318ae8f229705068e83c9c1fb9451a6a1673c25caf746c4c9b26184d2823b9d0683b4aba1443b08a3065ba218482e254abb6d5d9a8e5ef53fdf80187b735c678691e4a0f4f69ee6019e7d409ba8cd5e329ef13dd826490b8124838526189a259a0e64879f6a9706d47854f", "SEC": "040ad74cd1247a99f24428d02d5e6725443bfdbc2d2be2780696c36f913634b58e0959e6839ba999e3975636922d6c06224deda57f5cf665c81d52ec22f0d28a54", "TP2": "040cf133a15147b2404b8db187f2d394a08a9f15d37ddc9894a8dde979344a00ec0d5e7b0c84c76e592304e4596a7ef70dcd493ed14a0438d34817191a8f36db8f", "TP1": "040ab18a9b4cea26f4fa24d992baf055e662517ed15ce599e483eb469fb314245c15c4031ff93b367beadf55fda2adec75695f164364ec669262943f0e3fb88dd4", "CS1": "0402fb46731e85ff94eff6c5982235f2acf5860b16e4a755f65df9a6b6500d12450ed791cabd0943b026b7c1fb60a067f3c64abb0e26441a0a9b1a3fff0c5ce077", "CS2": "0422e5ef6534818727c1bdd1371105de5103c3c4194f73d73aee51974d4c1deecd1143ed59d2f621a9b771557745732e0811ecaab62e089343f6d180ae01b606f0", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04022e147c08e81eff7178a550e09ee757f98d6cc24299362c942363cea0cd5ef51406858985eab73165c85ffee5945ce97412257fb0a404598d0f7b8ff39bcc09", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040043aed7c9df208c7ef9b2a0c6eb0d92bbb2aad5bf4b4c28d4556cf045d1125c17bdf33f94ee35f3ed4899ab476fd227f8071573c2925b66a144d4a21aaf8e6d", "U": "040db9b9c56b162cd0dd82b39fcad77f782679b4bd01ea5a32c11a8bccd0ccb09c22e6615099a90e935fc021ecd514c36d5f36186019f83c52e7102ad1b951a610", "SERVER_OUTPUT": 0, "Y": "00a09c8c7f2cc0ce9ca6290b7f52abc5ee3b1995d744324c57a45817d15c35bd", "X": "0973546109e2efedbaf65b28b5085b01c58a6489003eaa9bf3abd060d3fd5344", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 235, "UT": "04136648209231dff0f3d1aa46abb06ba7703b6ec76e1582fafc5a9c92d0a296ac126cd18b7b1786fbea615fc437640cc5ff9478058f860c67e56bd78354ac3e3f", "MS2": "22a2981dee712bee4754862c451021c4a95eaedfbae24d12a046bf0e66586a97", "MS1": "1626bb9782598371706a94786760db73025cc5536d4aea55877c1e5e1a9b3877", "CLIENT_SECRET": "04071e6b202439c5a15a812411cfae931238b14156be36517d11628351d0238251160e0592dcabb756c07c066f3e6a16eb485f5831d2bf6c2bbc82e98a21ee9ffa"}, {"TimeValue": 1437055598, "SS1": "1f13adcdc5bdb6395581b416e5f0182d5adea77df8760da54e005d8ac688910f2160124dddf994ab3d8927da0db8e3d866a1024c712e0b48e3980a0964efbe621336c843ec966c1bf6adc5b8ec47a2bda4b8f1053f7f40055031bf8e0e92dccd15a6aba3e1e8aa9d2a88f750ebeea021bb5aaf0a41812855a0f782ef779d0e70", "SS2": "20406742f08d25b12893d141ed7867f22f23b2829e32ccbf73b79ad0e684bc520438b81e97e37cd81c3de02a0f9a9e8fdde18b36477eb1ab2cd7b2e8de653ebc1fa3266e5ab4c553e34bc26a066621b3cf280386099dda937dea76a2f7d768f403c2a2da71c48d3408a9c498d9a1ad6bad38f3a38ef9ef4f2c8ba7d462c491e7", "DATE": 16668, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "020fc336441402d419e75ef7a3ea2c54ad0ed5b3b47d7ab897b71c542d47163c2146ac62409f85cb020ca4c0747f202abab28c63ed8748e87f7fb8ffb6483f9d0f40bd9051f68b7509f62c80c1e8f449f1708eb05e0973f65fe9f8487f1cee720fbc53e5a02802e0ff39525254163ea4eb5c59334c1fc253852ce10679be3d26", "SEC": "041a47b9a0e776f1af1e27db37adc04e7e7cf76db9a04ca3060c3d1ff1c8e8bf3c1d2282a447fe5ea269b7f1e1b3dabd686794c41f84e1fbc64df5eb3c62537d6e", "TP2": "040308085708eb184bd0a4f9f993865a0fc4380d300fb642370b1ed62e54384fe6056be338e0def7550b5c40297ec79ab914230e0b9d4039435db3234c5ee6b1d5", "TP1": "041a35d96dab0708c6d99326fea9ec3a78de7b2aa724354931a945d798153180352001bba0fb8f3faed2bc6fc71b926cabff1343816fa83b39f2b7fe547a93d15e", "CS1": "0416fd59312f1b59a38911615490be7d8357b256fa33185f12cfd402ef78cbef1c00739e74704fcd405999c063c064899d90749cdf86c8ce78c87c65524a2aedf5", "CS2": "04074dfd0a3a094a3878f3a4a320794fd9e9da3322bcfbec72eb80f071e858321d182f551b30e73b357cda591ab0a7f6d81dd924d8eb22b6d26a8cc1c2f2d9c733", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0410159ae50de7ea3c9920b8a7ce6119f0d97a153573d5b4fc51be16674d8bf5e01d5cd077cc3dcaa9143ab84b3a4c287d5bdd8eb75629e1619af8b3c664fe9fb6", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0416cad56937c560e746397c987fd87596b32e659bf7ff82c22cc87d90cf4480231b093e14a082ccf81ea3d9f98c6c4eead7128808c884cd255392b00dfa15a5b5", "U": "0421f0e024ca1503a064ce9afae1c1513e64c76ecd6e9be72779db648bfa90344c117fb144195349deec71fb1e8718abbe4f296a2f156b0834784e69db71b522cb", "SERVER_OUTPUT": 0, "Y": "0dd341097114ea99a9ee03ba19ae1f58af30efab67a8a3cc79e10bff30127f59", "X": "06195bb6717ec3a9aa7aa682b5b83f694c63202fa5a28eda150130601ff9df98", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 236, "UT": "0421248c0c2989038a04bfdfcda32d28315a45b07db84c0a42f551783f001869a81ac3f82a8b1842177396677242268b09c634c007edbca366b745bfd03ca1bcae", "MS2": "203062cb263455f49a3a67f93c01b3955d8f7603993b2efd5f50b9c0e7dddbc9", "MS1": "07faa2684953ebd79904a7f271d424cc84501a507c18aa4a72ed762fbde79df0", "CLIENT_SECRET": "040eca2bdf861f4954f6bfc1ffc2567a58f38e43f3c40bced5479df732725162490e35e0b991d462e10c36f24d0f9ade763d94af3e15057b69edaf5a4d7a36c322"}, {"TimeValue": 1437055598, "SS1": "0f25d78765d3cf9c0c1c35b2402c412f7b6913e16ab32a6ca997f454d14223701bac614aa78117c3e360411946054f9045d1be0dd68cc352979b3c74202be2f40ddf611945e7b59daa3155cb1437401b25496e598243bf6e2f51fa0e9d5c86af1d225745125d2baa909fca48d01e6b3eedbe9726aadf032cc54e196c5ccced0a", "SS2": "10ee4bd38ff6ea95e99c7b7e5fa467152b43b76bea2a5c4cb1333453d186e5fd1f2e8316a58f3d4e27be39cf13235df07210bbf1b34c9e2bf6064cae4a674b191b441366e8bd09152ec4c62cb6158ef5fc0ad3f4a58b793880074285c9b8d1c211eee153d959a567ae499bebcd12be6fa1da47c130d37fc37e8c09069c9184be", "DATE": 16669, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "14495ef8fdb5fd0e13868696ea14372e01d32b1eaf80deaa65683d46cbba26dd061fe8830477a786ac36a2d0e631bc3033b230eee52bf831aa05e0806456169621d00f89114bd8519fee74d66da078b744c598ed2efe0eefed15f98f7361aafe047116570f0e9e34481796518f9a28cf9ee14d378d18075266d213062060a98c", "SEC": "0406fd23315b83f0317f480e27691a859c59e97ced3d0ef88c62d3994379c71dc81c150ab4da7c02f27112dc2f45234b62c9a3e7e0eeb69e867342e740e9b4c419", "TP2": "040913a3002966345e0826a17ed895f055103cb7fa7d99dd2a6b7613520512dd5d238850851d8678c37fd36f33712f5e2ec745d95ffa8e79797e2670710c1dcd10", "TP1": "0403379e9afc547b2d3cb42499e054be604dadf09f58ead852444faafe6e01cbc21e38dddeef24ed17e61542bfded9a0e69364a4465cdcba5dfacfb0f259fce126", "CS1": "041ad5951071cca09e8ade2c6cb86b545af499b31646f086de4005aff8491971481f893576dcf0281b02f8576c37286ae6f7603809473d06ffada49ae4e0deffce", "CS2": "0418c950b8e3533f50d21f6d3f2d4c258a65c6799439ea7474f3d1f05eb66ff12e04f185063de3e487b893bb0008aefae5959c06a38178271b5b4c323e3bcdb712", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "040d48749ddf3599fc64ce22f29914271f8cdba969f9c0c4ac9d910bb2ff319a0716893fb49f219c682dc9bcbfc6b1eb8506f299070331787a46b41f39ec61833b", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "04209b84718c9956379aa98f5e8560da81db3b9b914ee6592f697ba26d987de9b102313b926d3e287a6071aa35567b7bcc74ce4079aacdf8525854ad75d2af3c88", "U": "041ce7faea606377ac9a4c056f2d536f25c66279423958036f60138e2aa01d99501703fbf267f38c6f369c99a330f5a4442920fd360b8646e609ec8069aecdbfbf", "SERVER_OUTPUT": 0, "Y": "0ee6c740b79c25c24aebefc67ef12c58beba3e710f250a44d9c839516ffa8db7", "X": "14274030e85a8b8ffb0914d3f0ecab3e5ac7a433146623df252e42be7e73ee54", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 237, "UT": "0408afb6a520e89d5ae4b98245d0f497ecce6a77e7a65a7610f8aab42e58b36535160c17a8117c991252c08e05e2e400cb064c62d5fd60aa530162f2d007093b3b", "MS2": "1d85905910a26b7e1b4966e878dc72914eca95ac09d388f81b1266146d46169f", "MS1": "18879310d93dfe2228f88d54d742fc629ecd84f78d654a951926ac12b7381030", "CLIENT_SECRET": "0416287ae6d86c10a5baf14859c86505f880a4743648c3344ed2ccacf47113c46821fe579679b96e3e5b450472bf84fac18797221478676164178df80d83dcbceb"}, {"TimeValue": 1437055598, "SS1": "207c5818d161db9abb97af8ba18c31a5dc9d60383f0e0e5ccacefbb146842b77238ff30bb47cead9af004f8af6efdc0c1aa2e2b1f423419a0d1ea2fe807a510b23ab4ab84ac75d2027b611c5933811604e35b5d298a9bb37121245a5f0818faf013a636877ace661d67f51c8ebf4e7c4987351263efaa6edbd12ddbd3db874a0", "SS2": "18be97237e517bbe9c1de9b35b50539dc8f6016dfeafc926b7be5f314849ab4f0809228decc9c9a35105f6c32f91989c07247e55771579981024d3c14ec984e9172efac508cbda3958179752cfc32522181d9d8a804606db4445f2313b7deca41d4fa19d94d8dfaa3a040af583827cfde757e41d1f465cf2bde516b00074dc9e", "DATE": 16670, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "0c2fa810c9ada206a93c75e759b58f0ad93e5252320b9034f0175c45261dfa6e06f0f4e9f7005a0728cab9fc9086fca713e258864afee3fc28c70c9c3b1ef0280b4ffe89557fa53fcc606a436e672d9700b024ad49a367d68c8855258e6f61a90e4c46d66de62e4b7c65cb9dd94f131f992ab4fbfcd8e8459df99ed916343abd", "SEC": "0401d26dd8410e6082ef4274899dc50579c5b8016f4100e0137b1cf26990fb2f32232a8efdd5bc87469749aaadd94c99563b70cb545e71b07e1cc3a2cd0be6af4d", "TP2": "041989f7396e80c4535f3e67e65b8d0163f26d2b875a2ae072347f9e78989c76b707f258c3a79a7c67cb481319134763d709b0bc33abd79baadeb9d3921bfc5310", "TP1": "04211c0f9fa5beb9bf21d99b1ca74913cccaf1f0c9a170776024455327c6d6c2420f13cbcc9fed288fa61f69805fc25d6e4a294652fc3a2e12e8cf1fb86bb5d97f", "CS1": "0407942b87784e951b3b8f57973c152dcc2cdfd2e191059a60df21dfbf409b285805ebee4c4b0d83d448fcb482d38f8f4a3a613ecfeb37c23ffe5847490cbcbac9", "CS2": "041f569c027eb7a994d796aa259e575b3f0c83c9bdb8314a55f563429000a5e7bf1a120397ac1cbdded7dafcdcaac010fcfe2b455a31d16f23ab2d0d578e8dbca8", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0411682b3a0e0787594f4a439ffef6678f2704436b9f1067dcbcc0c34706189aa30cbb04a62e4b6c52e20b1e41f68068c4807ff0b400ed456a7a35da748220e114", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0409bd53ee6fa337527c5258034eacf0ce814d491378f25e67194344231b0559bb13089f9c315927cb109372e12bf79d4e523a0dbf802f17ff52fd0969914ac4f6", "U": "04119eab782b1dd1df7c3163d12ef4530538981e358822562790ee4608a781540d05d8e83bd68aa21b12a93a9fa1fa58034b6e30544b9a84a122858c8ce1eda7a0", "SERVER_OUTPUT": 0, "Y": "08789de55cbdb1014f9bdda102435d47fa96ae05e9e1cb28b33550d08a8cb479", "X": "14b7d91302c6c18e0bc374d84b32cd0993ccca1101ee9580048ba34d5be8f03d", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 238, "UT": "0416f46422b0829170a6955cff47bc6522d968d5e861fb96d480e12566fdae5508062cf1d12f63a7572377443b0ce41961637a25fc0965ebbe34717cf0c10e3425", "MS2": "1f8371261e6ff378b4018f0d696564e645bd3329036a134087a143de625e4c92", "MS1": "1c05e7d437adc24fd6131f10cbb7d023268fa175db1412d81137b1d198ce2725", "CLIENT_SECRET": "042093139d503ef51cf0b6d343d118bce35a71da8f9d5ab6cc4badaedec1b89ad40124ea02cc66bdbf406be523a2b39b87622b934523cd9e1a2a692682a2063911"}, {"TimeValue": 1437055598, "SS1": "0505604916f86cf8f76e3a8576ac3587e4d3a0797d2be7a59e12d2084fcfecad1e105cab295ab5b106de27c52d504a80def18dbdb2003703ce8e4888ef85df402233112fd1fb721805c056f075f8234400f7814dfa2fb6effb26e01a12d9172f0d0fa5f60c355d4cbaa7902c66dce14cb8bfd4ff17b787199279602e3ad197fb", "SS2": "23286ed51b265dce67d5dbcbfa2f59c35575b0f8c6a6c886a157d908ca2ad8ce03ee5c0f6207c68b88959e18649969e5f45b6b6e633836a871dad15918a7674c1f9e49ebbaea48f7641a446d891ed78ee3c8884422f56e27e174490edcf81c3d22d57ac81c7e5bf8d0845c94da758ffc92f2ef3863fa49a179e3b6ab2422d456", "DATE": 16671, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "0beecfda8aaec14bf50ba100d5fa777848152643d8ea2c8a872717141aa9dbf0087be3efa41dde4b603274c803600a6c32c32c84072116fd8769b1ef95e725f91ede287212b424a6d3bc8cde52c30067d710b3663da52172cc1f9fc171a4183100ba7513778064da328692f126f484771ef2902e3140d2ab771c72116862b3d1", "SEC": "0410f963a131e9a91a65a6e2026d008a1c16d57c8b1d7c97042a8fe30e099e2ad51ba276583b579c1fd3604f2ed6c1b8d17185e912876bc8bc7dba923bd22ecdcd", "TP2": "0422bfd0a3d282cf3c9a66de1f50257f26bf3114cc8420aadd2e6472c6d38c1e931f6fd681ab91df157d25bf9330b4f7f160a9cf0b592259224bf0cab2c82c699b", "TP1": "04043e74a873fb673f55ab1d3d974c193878268b2aaf5dd9756555f66c29e211f90208d2a308d52c18647df60fd4cf49d7d12499107089aa439ddb6a7615200643", "CS1": "041c9221dc84f28f0f546bf36d88b841c71dc2d23bf62d13b8f7e1ddb56b627e2b09d9fc9baadce799a06bb121914c9aee1831d60ea2dbb6d09c22d657bfc562c1", "CS2": "0416f17207481f48f30fa21a7288421ce68cc25de9fdc67315bfbeb427797d85d819ffaa2a121791f07529a15b8c8c17142fa57a12be5818f897183cf0a1bc9a22", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04129f76c06396b408484faf387730c87bdc9f89d062a1f8f30ceb8e66923a17b816bd59903962d675008d7f24105959d1855d4179e857b4d6224afa1502b1dc82", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040720a205b043e4d9245b167046a2afec01da472cdbbcab7566e3fa89cbadc0c02205dd149893d1b5db77bcaa1c4b97d20647fac4d4ceaea1ed27371f05b50e66", "U": "0420bf2a9b0d4be3fdc542a6717dbc3797ae259c1f2b1176d288848f4d58824b0b09b15d8f1b9453c36094c0bc9f9088f2b336f621ecdaeeb902914c45b27e4e6f", "SERVER_OUTPUT": 0, "Y": "1403c0727cf134a2613f7f7a51b1132a1ce27e153de293b60ed393aca4ddcd7a", "X": "18f47c5324177b90d5dbe92e190253077eeb99b3e7fd464f2a94a4c7b6395b1a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 239, "UT": "0403daba16919b86390ef61d8f7ff753951f7c0555b0b9f62fa6412da47175b0131e25e93e458f675600d26193da538a5706850d6f44b3c91979630dfb5309ea2f", "MS2": "12dfccf20a17a3c16f78bc9d5559474bd90a51e3c28df177798be64ef33e53b8", "MS1": "0ff82166f474806f6be576dd8a6c119530717204e6b975fa69ee09f63acd1c32", "CLIENT_SECRET": "0410ac50a5db67a6d2715ef1866bee6c72a430012ffe91f1fb0f4fa8b9ef9b909f17725122eb1db4aa6a88f0c7b22ed45cc35462557a6dbe8ab7bd3cf5bdb6b341"}, {"TimeValue": 1437055598, "SS1": "0b3a1a386d250bdd686a9b886bdcf032fb9346baa5a45072ff6b7cae5a94a72e0eedaad099d1d866bb5e0a2e7631764d035c9cce356bae021e99648b9e38af550e69860ff734f0ee0d04db669d4d130917cec0c3ed70d627d261df4dd05b21c722b9720164ccf3b20f853d485343bf9a4d7155e6617ac6b934f335758c6bac0a", "SS2": "218116dee1e196dfa1e7511a4ca196f97dab498a244bd2a9bc3a333a1de191790112a6a96287aed302ffbf3499c1a9987865cbe8aa4a7e283dd19d55be91e6e916b76513788031ea620b23f4bf1476e9c82e9ceacac2a2ab4e5527428b72883020fbe5c321d9752efd839e4be0d9097c6d34ea620b048ce8a0a49b804b83f876", "DATE": 16672, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "149f39c946e8e5f6d17562edc83486550c6ba264a956b5d6451c4fc2dc41d3451d425da5440cf4015475eb17098f0660f1a72e3c9c1998c20b89b90efe2051300f5516f7834d303913383ef5970e093c9b9e9b18fe44b6939d01b508b4df67880ebf2d7dfb312e42e2876f8ed40540713113da464d9933af2c2f479acc5ea251", "SEC": "04028aef80e749a0b79a7474afa20357c7e411fa76f8c614bc080deb5313f343df09499fe6c2a78bcd843d8e84d6dd50be86f0f30ef2a51c306b2e2b9ff709f437", "TP2": "0406d0fe8232ff23425114b02e554a6e164249d7a2fc118e1649d234d9e344e47a13ea23bfa2f3cb2449c4e9832f1313c4d2fd68e706b36f1f83938d5aed60edf9", "TP1": "04165e77f784b204ee727d7b0fc5f778426d0a434a9e20e22e28ecfbebebd78f382127bd77232e204aafb0c786b1427fed6e9e0276fe5a0c6f52773aba33cb6a4c", "CS1": "041f061670c1f9e3676a55c7454910770572540506a1e0b64d977d808997de234a20de15fd9686b7513cc8dc5524295ff8b2f9d2fa9d1f02c4eed8d7f272b663cd", "CS2": "0402b449308d9248d412a6f36831131cfe3d235a219b83288a14c68a46679d7f8611d1aac70c3cb34ca07ad1e06020be253e72e459d2707befb4e3f8c2a6d4d5c6", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04154ccfcc618652f9be9f8f897c4a3a037d8d9b4176a2a26416bb9908ac144ba51a174ae7546613cd140c3176cd72fb918d28920f373781e28257625b25640766", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0407f08d8b00985658321b6f6cb50a1c6c8bafde9362ee5a4e098e37176b1d5eb21784268a1af8c6ee71bc4551ea6b726d2333bbd16c5470800078b687208687f7", "U": "041220e84139f4033969769914a48111aad0915c56b58fb117501e53b3127152fe1f74d502622dedbcf92418c77770e21c69e19e94e33a91feb656208bf787954b", "SERVER_OUTPUT": 0, "Y": "229a5687272e08462a02b2f420cfdaf8ebfe27f473a3dc0f858eba46f93039c6", "X": "1801ba0472343894b312528017c3e3f772e3954abf4e0976cbce6ef00ec72582", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 240, "UT": "040f05ff17c18819164c793a400d0bc32f395cc664d8db503de463193f9028fc59160c42dd87f2252d4a959f8643892243d6590fea09d0d86cc532b8dbb7e0b8c3", "MS2": "067ac0276b1e83e70eb1480d06fbdde835f0349117b44fd9039852cf5d198cb9", "MS1": "0f741b6c3e57c809dbce2c436da9f6cb5b7c108aefcb64d158828c9cdfb25755", "CLIENT_SECRET": "0419642189535d29b431640fd930a716fae749293eb6143f1db10476a2b08352c91591b2977bb9a2fd4e8ee58bc41631850333fdc4c8d5d89ed4d2de5a16ca2d72"}, {"TimeValue": 1437055598, "SS1": "17852f6895c0fda988e2f30a6afa9cd4805f1155e3bd329c30c3e5f3873bd89e1256bf1805493347a1dd0374a16c3d14dcf055a4ebd7fe0066254b29072fc39f04ad976de849d674c455af01b3edbfb188ed8886da7df70cb6e4376e7db250c807f18c52ceaa0f187b3f0daf1e0cc12151ab6aaeb56b7f78a933e6a0d442cab7", "SS2": "1be9e2611c9c754045d9cb48dcbdd1e612dc4c78e9e51c626e04d79a8b8d584b1fd7a7b7a4bfe7e79a140c7f998d855ae8ea629a55810e4c89b5bdb6dfa960020540929b7ba56e65092d4d76bf0e79f863614d38244a76c4652bc7b28447478605a01828d8cbdf61c31a40ac6582b1530ae0ec504e1295f63c7f0c4422ee95c2", "DATE": 16673, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "083f79b7e3fe31401007a7e64a95e54f1c66f2a78eb1061dc5682d11ed8d808d1c8fec7492d73c97dc9ef4d6d3e0986494160ff76b62264214a2f8cb9b89ad2c08e4861e7d4ef1d42ca1775a04e02cc7e9436a05ee1cdbd788d125f80fe8306505d0c90c11e6e13c11136f7a54d15e3a30209dc728df52d6bea1c3202e5dbfd0", "SEC": "040c6218263dc286e7a057a2df69495e91bed4331bc868d55ca5981549baf0ba66105be5d598d42f722ce05e3c50302a54e55b24821d2ab592f50999f22c22f94b", "TP2": "0421a45ccd4bca71809e24fde8877d71fcdbd8bf16b6a1d95a93b28a3295a5d2e823291832a9f68b23c2c2dd760fd10a3a106317ff6125347c35a6b2cf05ebb639", "TP1": "04074e58bcb63d1ef29d50dda0224bd44f5fa309a6f230c9b9836f5375fbe5da371e64931790ac8db3e80add68fafcf82fdf320dffceb6705069d71bb5df1ea0c2", "CS1": "040089883d1b9c0282641ed21adef4c48adca1f23dca476a12b73fef56ec29ab060c7920b6b7b1ddad14e28791671d6f5abe4decfe66eb6e03a9ae9b969d77cda5", "CS2": "042015a249d18a2af2f4f0729f28e5100374a2663ca6e489391a2edb19e84f05671b4be53ae288c7fcd42ad4b519fd454997a34d3b9cff83103c22c0d2c1d7c026", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0423f08071e451d60dc0929c8531143a142428b85362493c5aa1f870ef7f780a7b0ea88342449af0a3aff3124a16101cd0fcad78835d1346d9df303dea2da08f1e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "04098a11d61d9fb181885d04922bd88dd042cc3d5f1f0cc35cb252e1664081ed1923c38155f68a74979152cb737f99613b98722472870522002d3c81acedd6a705", "U": "040e3c5fd53c46f9ffaf3f44162d47d768a6abf3b164bd59f984530d2408d9cf2f01986522484311bfd7e19887a02685232d21c08dbaf4aaa89b058edd51695195", "SERVER_OUTPUT": 0, "Y": "16c98996110a5b19d0a4c743565720f4018033f74be347c81b5949eb0de765c9", "X": "0216ad773559432d4f7939764c808f4aa305b474ed37414ea9619aa6c04787ad", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 241, "UT": "04061049e1b33450f8b3084fe6dc9ee38623f06bee00de12fc361a5369cb9ad1341ef1b1fe094c2bd42d9b03b785372e945d36da2f847fd5652115d3a00f1eb430", "MS2": "069cacf11ce2d9e572bb49375c8953b6a4f15edceb59739ceb6a6967dcd23097", "MS1": "1103c4353fb921ff4be8d1eb22bbd134954969015ed722290ff794222b409616", "CLIENT_SECRET": "04146851eaf5e6de600c5f0854fe96e404894bf2701ef1d2bda7deef8cb1ebcb271dc968c829e2a5124d8442cfb62d5a40964d17ff8685e0240704e9d25fbad127"}, {"TimeValue": 1437055598, "SS1": "1a68391f7c5240f82c48f197fbd682ec6006f0eccb418ba5fa38c9797dd2f3dd057e362bfe908be5dc39acc8822e1098d92d20e16501715d9e18974ef151a6950007a2a5bf9a4ae1849d8672d146be7da4f8604435e2fdfc97f56cd717118ddd04fc1abd351679485511287b4c1742252706103bdaa6d32b2277f0cb7290f1b1", "SS2": "1b4d89ea0b2ef5cf577839be55acf75d68830c798959e6c9a65ca4c3d859a6a314b141b26423b1325fb2f0f6078ad565c2ffbdb809a2c983afe7648e69da12da0cc52fb31ff9f03621c0687e2ae64a0d77292121de41cc801a2ca870a40e9592143f47115e79580b310504ad91ade86df8b2ea055e4e568862eaa89880c21f15", "DATE": 16674, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "143a8a6acd2a4b7019ef35981434867c74ee4d1232691be0cf397d93eaf41ed81637e0f391d2e2addc8a5e200ca8ff8f7503917143ec24485e167d57a8e75180198e7ae7f7146ab2b50ac246332c9cdb0fd5952e2356847a6c045443bffca74c04250f74fa48d817617b2a569a727ddad0bb9db8d72441459773983adab072fd", "SEC": "0422bcffb481c6449e0dc63ab54cf17ea5098c1048c1969bf55ba451da1d0a0ddb218d173be0cea556e23859e49742545b26fd153e0f4c9e3131f2d1bf25c72052", "TP2": "041922a48c724b5848ac989e812e6ac7c4efb1c44a9691f13736e7f920f1ba1ea31015da0aa14cc346008ea68aaff07c6efe8fb41cd68ef9c9ead75b4818b1c5cf", "TP1": "041cb302102d41f13f48a4ea9bfa590dad7cba7e24c00bf5d6ee2224ea69769a191435fd12ebc58d7b6fb6392e29959e900dad808a03912301a89e2b301e0842c8", "CS1": "041c38dc29848754222eeaedaa1e0da49721b0b38a0d70de2bd18d465f9cfe398e138cf1330291f2372778a1965445182d43217494e27fdcd5668498b13ee26b05", "CS2": "0405a6355eac2a41a138e957fde8cb7da67cc18b6e799244fd13b1b38b798ae34f03508bc1a55d773d1fd5db537207a7cddab4c3fb3b7fab6fc4add100aac0def2", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0414267d0107944e0be08a63f02033f61f45adac8b680dd0fe25fd6b1d719e246b0436b6109cd1a526cb2938937cc3bc4d7221af4c23853e4d4914fe4720479b58", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040903bc896c6a76b3456fe3b2d0202ca7b0342d598495dbe56662481690c6d79c1c9944b3e5843b3c6ba6f214a7569c2200cfa04d66eb8d14fbcd10af27f67975", "U": "040d39527cf68a6c69ac90a9a07299e2778a938363b9800417554c880268a596ae0c87aee8fbf19ab8bea8bac2628259583afa8a40b0d39da78aec03758d033eaf", "SERVER_OUTPUT": 0, "Y": "0c30e847ec2ea1abfe7e84af121c19080257d9fb17d87cfd2ef8f02dab3d5327", "X": "211694302722aa0ec8dccd6e4a1130590becfe1353ef30de205302253eb34009", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 242, "UT": "0406c8ff67ca391ae1a65be96bd4ec9a58829ad8cdcb2568667d10eaef5eb517f00ebba2cde11b371d0c6cfb0d1a47c6fdfd34eabac5920db66c5c31f56192596a", "MS2": "1ed163b6f521df4802ae1ea2604b3b3bd09e50233c8fa0b46478419a9340eeca", "MS1": "1dbd17a575e9a4d8470a674082201a69b12eae2ec313952a657631738b6fa27f", "CLIENT_SECRET": "040c79263f71890763ff15c91a5e8f52f7dab061eeba987aa6f20ec4cca59f66251b36c460444a1089a46ad53d90523249290f837140aaa6d9235d0f59994fcb50"}, {"TimeValue": 1437055598, "SS1": "13b382dd3da188f2102507ec4130fb3ed497e5a2e803ffe42d9b0e70b52cd4ca052510b6e15b8b92e5cf1525af63fc0554e02b7a3d9a1610f25e10c254a2e5ad05f7294f9d9f3129b0b96b4eb6ef16512b4fd044ed23b8486786234310f1d87b12008650fff9ae7a2eb9c608c061e03e2032c45a5a786f85cfe1edeb5a7b9e2c", "SS2": "03df176f98bf95081c2ac0820f5dec445ebff7d344d2cee18a86255499013e390f9f741adc353ce89a067352d8092a50336bbb27a7469cb130285c7d3adf1b6600dad41619e26de1b552ade12203afdda68079b410437af353b8e75c457ae5ef1d1962788b28952d82c588eeb37ba6332778d05569b89beb220001c6eef86a7f", "DATE": 16675, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "096b5bffbeb274659b185fd7cae267a4d991280d1bd7775b799f62928289276e1c458e481ad560a93436f7e4de33a55f92b63a8cfce98d56b2657bbf2f6e0c8510b91df4ab38a1c123bfd6f7ca1245d161b8357e85516ed4e8d3f302b37424da15402a1f6b0b60a942f995a0849c3dbfe72778e3be12406c361e62b00f43c0cf", "SEC": "04226ba0203b59424d8a0e62cb8ebb3b76239fc75072af3f245f7c4f3172656afc00a9346908a30b5c79c1dd1a24449817d46d7d28e2138678033ef2122cb27313", "TP2": "040a97f617c6e8c386c0d01a36978f896abea002762b274240fb6b29611073adf921cdbf2ad1f6180fade3ec36d6fbe9a6969bdf58ef696346fdb37db67a35d45f", "TP1": "040aa034d93006012a100036ecab08f689916d5c4604582bcc6eae9878401587c008f8a88401d587f109a4456a8ab5214e7c4fe0888764790016b4627cb94bf626", "CS1": "041b25da87f1d8c1a0e340516dc8e94e27d23eff1552992ac0b79584f90dfe1c4a1981a9a60827f8de5c377b2715efe788a7d1cf9fca4ad064ee6ee704609e5ec3", "CS2": "0419854c903b8bec472031809899b6e69b4bd08e1820fda6122911373e4e6cf457143d83658a0644a6a458ddbf44bb1441c6198098297917deeaccdbea493916e2", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0414ea8e5a4945b065303dba51ede79be4dcb8a209f8f663b6e483da70135b744922df37415cad7ba2f3f50f530441db7444aeb3962cf490353a52a38fc1c1fb44", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0417c5f0082704d40e52fecfe3d3a897f3a9dafe32cdc3d3be6b6c18495867c0f218ea420ad9b21ad06e2821d59882a89c2a179ff2dbde6d0c4cc8db666061e60b", "U": "0402cb7f01af1aeda9b4ad88964e1b39c50a637cdf371d0334a78bef3843fe5501025eb3c053ff8e1d02183d2d6a8786d8a856f308135b795da8ccbc0b9b55ccab", "SERVER_OUTPUT": 0, "Y": "210667b182152b606923b1e0868e452f9ed3c7334248edceb440bad7ed0cb6e4", "X": "1a5cf3e4e72b9a000bdb31bf5e710dae85fc34a57e56c4a9d584b6809ffa7715", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 243, "UT": "040aaaa02e3d3347b8a8428028bbc1673e89106815852dc3eb588dd5ef77dce4e91a3c23dca0d31e4c6d1d5dd073814c89769472b1515a304b67fcd77a648c9a8f", "MS2": "0368f3dc00b45d867b2c4900d4006b049874c2ae2f656653e4b24bf70f392bec", "MS1": "047c8fb532400ff0731e6bc00062d82025e3ddc59de3a23cd0595ff5052eac60", "CLIENT_SECRET": "0407287b16309385ad6238613af0dba4cf0251c03cca957c573524d669a3ecb8da1954ea1708e64332d6f9f03671163b3b966442ed3ee1576d44584044267d0cda"}, {"TimeValue": 1437055598, "SS1": "08ab2879efe7ed83f42320cee5a67ed789f313a68f3345361b038f6c201153771f56cc6c79922284de3a62dc5eb24965a62ab10055f6edfd5c55ed7c6df3c85603bfe1446090034bf9489ec1359dc17b80eeee669449046cde3bf0997c7f09a90c3628a3eb45d90c8956c6dbff084324f4067fde5c91da2578de9c19191a7878", "SS2": "18d324d51f63e6b69b670cb37026e3ab02db4d0bc22645e4ce1277bfcbbd2b7311b76548720656430ded7af2acb048c16afed90a94ccc43cb5e7dfe65d564f680fe49ec077593887b5deb2f887faa465fae364b783836572c9a746d7547d868418a3af7a77a55c3ae6eb66dafe203c14280f10fa4bb7407b7628852aed7e3d05", "DATE": 16676, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "16e23e47ecc7b2ba27ca82d1795b3cfba8caeac6b6aaa610692b30c66568ff5901ebac775d8a194d38c99772a439987c476b3f96e7624b8a66657098429373db23db5171ca83366420b9c9184c6c74bb5ccece82319b17ad11cee39b6d68f51a0192e6cb0a66320049d5348e249cfd9e56d6859211dd1c521c253c34e935c4a0", "SEC": "040f225832346a4f6ed00acf3df31c7fb80cfc7fd7e0ae72d9560d29286ad25f5e0021ecff5902d3e1979c6d3c9039ffc9c91694c1c7b42886c301104b0b151583", "TP2": "040e6f27724f81557842a3d648c392a1702172b935525072547775c19e8ecfda2d00e9d0fcb54746498b778dad2184ba9567fd00a7f3c9e63793b322c69cd08ff7", "TP1": "041eb6e68faf6ba209cdd751efc287214a7642af1405fdc2c5147a19e2f41883fb159e8ae92b4ef18a460b4f3bfd2ef17c73e685e92372918f512c89ed29570114", "CS1": "04111287c46dac0d86632a2c0e23369c26abfc8f8cb8e7b5573493be3f7754f80c1ab51bd346d72e2a7599a8d76f566dcd7e1b07e7013ade36e01fc4ee976bdc4c", "CS2": "041923e0a2b62f01375193bda9ee8de338421fcc21caab593897d40d5d8271ae5d224264a16940593ac3c5d0b22c72bce8960f606bd1ce1ca09ee3467d12d1ca0b", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0413e3cfbcbc7715d52cc5d744df76211220db94753248223e838e3b3c3d4fa6f416a2c9571f1fc3e6f70332ad3066481713a6084952b6210237be5ac3124ab08c", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0402a6aab74616bc087d58563d7b8c0621b6bd760e50ebc5425238e55162436be900ab06ea50fafd151b7034bffa7ca1849e180680bec0d7e13eb01b460508e13b", "U": "04048256c518a9b27eb7db0aceab77bf4827cafafaaa0d913e54d544a760bdc32206bf67ff4fb74ade66596e004648a58f1700818d631923bc6c2dddda5a7f791e", "SERVER_OUTPUT": 0, "Y": "1d3b8660df1f999b8b12a20c5e45be95a3aa7f28aca92c1d077127e9e1422dbc", "X": "11cec882ae9146e01e66d6c8a1f6d1e17f8d5b2bd2186458a426d979f34beb3f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 244, "UT": "040ff589d2c19313768ed3682411e2b4915e6cbc62a3a02d32edfd78ea6b9a422a1a8eebaba91068efb1292930f08f02cf2d8d56a3e0213821c555afdfaa3cd344", "MS2": "1c67a03df7b29b7e05310add98b19b5b4126ee5f47eee2933ce604daf93a0783", "MS1": "109bb3da4dc684eac54f5404ff40e3c24bfa22c80cb314fe3a1db6ce41ecf2bf", "CLIENT_SECRET": "0413f574679a8d4f82d9041a876b79bed8e197247e83e26ca7a0785af67460c9db0f311f9a7a8c2344bfee7f79e8c9e6180a21c6d44a9c0026e6882f6e6a24f541"}, {"TimeValue": 1437055598, "SS1": "166785573e8c70ae58566a47c1969e4832b90d79164bb1abf70aa2586530181601e5a8c7d7b0f9b29b936d58f6ba374fcb5be66499a83d57a8f3c4eb6f79730519f05c3a0042522df2d82eb407d0b66f9a6d0a357513442663fd64deece6f56f0bf6735a4ec14a07d74cbc49162fe40d887526e5c69d0261c0ed96fb41f50802", "SS2": "0c9791d610684500a766de3f34c3f1976d2e2e35307185a5b325050986cc0b91054e0ab24adc129db204601fd7dae9d25f70dc6878e775bac9a1f9fa7fc6b95404fe9769bf1a69b1317664d39f0b6237d684fc22b5586579e7dfc91f174b97bf0923078050d70b51d7c80381cd2c2f9ea046296d2eba6e63c38fea450e6d5704", "DATE": 16677, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "02aeb77d782000e4986c93e44f66bf1c65711011f62fb27770d62651936b86f70eeb2a9c2f26b0867e32323dcd0c66a0205ad14a90d3ed5573492ff695b6fa9f1f7c52c242eec062985f519c725e80826f10c54de17d149fbdeeebdc7f7d480f031c0eb5195eba0f6de1591af1ef5db2dac14c5b972bf6e55ffa72eda40300e8", "SEC": "04060ceac1bd6bf27317e39a97d8dd7bdfcf570f6bc84641611b624f0143e2bd700aa8bcdcd1195b21bc61dccd2e2a56e1b2ff6750a5290755ffea13d4726467ee", "TP2": "040239c090b258d463b4edcf2d5a67a5d5367071b492816dd280cb7ef5419c65c51a1ff960e069edd9409b4469f1fc58f74956d907dc89e6ccb2849be2728b2f2b", "TP1": "041b178cf757cf8f30254454551ffa16e1cc3fba7004cb4e3b7270f771fb71f83f1fbb6f7654aaa36e399c7fe6b397be06a05b3cf30937fff5eec99863ff6e8908", "CS1": "041c66b7084874cc260862a3073d45cea3efc9678ecf62c082c8a73a577c596a900228a816320faf7940b369503bf75a3a6028269406d5ac5c6680537523d79e00", "CS2": "04024d679e7c3515eba60e118986f75c4a1f655203ade09c30ee37269f4dbbb3031b34d59f8a8ec749422fb0816f74a90f7cd404b7c61d9024b82aa382f2129db2", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "041330594012e0a4eb84319c116b7d866d5a5972f753b2d21b4c928c07709ca6831a049ac3f762d165969d9a716c742ad82a8a7fe0907b1d91ed379f1ec9d322e1", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0407c8213be770533f2b794b24ad2d85598761c4ba96477fb1dbb0b3e2f01f40bc0c616cc8733ea21372aae473882987d77c7fcc3fb7dd899dd6e33e3627de6bf2", "U": "0420ebb61057131bd2f3e446a70581c30e2ec7a0ea3b9d86a19227b0263843e44e0ef4331d9ff143999761af08bd9abe9358df08856257613059d0caa694bd92f4", "SERVER_OUTPUT": 0, "Y": "1feaed6fb8d80c0601226c784cb2555b5fa5e7a066d4cdf7eb627c7d50d6eab3", "X": "02f82dbad9b53a707b63ef40a252595c51364cb6413d0dba8149ed9f82eb2548", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 245, "UT": "04223c41bc54f1211c0c9ac9cf8410abb03a4f291b8c6348f96a058bb98db5d0921898b2bf1bd4730b83843b5d7e4bff3bad761f1c1d5270429b9c38d075cdbc42", "MS2": "205e6897231c6bdff6803c73755d67f0f1f07e2646bcca04ab3548ca9c8b3816", "MS1": "044890d832e6c2044da0a45f36f7817d6466f9cf4c56b440cb233f7afb2a4d44", "CLIENT_SECRET": "04203083b3232659e49d90af154e5701556d42196e35756b4cbc97e75faf00dea9067f32b5ad73a39310f4c687ec16f71a0451713e86a89a1ba7390b99ba627f95"}, {"TimeValue": 1437055598, "SS1": "04a76e404d8e4a8f238d26eec0662d6bec8b861f2bef24f00bcb702b7652c6071e6519faa0f2e9605be3a1645549089887454268b5d480a299a25ceaefc018e60eb44e87ea7bd57af191663bbdd097e86b1d8df77228c128fd1d45d6099e954a174bebac65becdd2d2ce5919ddd5e6737050a8ea3ae2ad21979ca3c8df0457f8", "SS2": "08e11b1b1cff8df26932325478458c89b40ca87388c264dcad58f93c30d5a9660ddf23c25d494b025164ac21a2e3ce95ed8f9fe6c980fbf43a51db1cb3d6df831bae57b1e11569139fd550f66e554a9b960da63be955cf7c449f00b46a49f0d50b51236980eb6700bb57b8cb26452114e5a110fb2e40566adf05e5894fc8cdcb", "DATE": 16678, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "17edddf977b6dfa97d7d633358ac4b40c9a5b8c8d34aaf0cabb2ecea9a5a737c0d2bb77461f34a80e9dc90e79ade65783e34cf3917ab1a241dc2b130fae1076b144f924b4966fe810f89988865f1d4544382b3b0d4f842b9dc9b7f15487e2bc91a596de07249e6ef632fd09a68f1a1678bb5765a7d94d75b69fe570501dd43ac", "SEC": "0403edbf05f72107739806c616bba6a02238d4d917c4dc35c8e53dd4f24f49ad710f44ae11faa590ce960829eb17e1ea54d63409c66a9f9ffb39218872779bf11e", "TP2": "04239070419d870ee1ee57a960476ec17c1673c42d7ccfaac069f6457034b51d301ab81f5b2468b744888aeb6b473d2a3db9a6d3a3ffeb11af7c9903524df94249", "TP1": "0406c9e6e87ca293bbf78dead61151dc684da6803bf8cf1fe25028749153e945451599d68e964e4c2d691ad98b95da9b65642c615cf2233c94a457b5084759420a", "CS1": "040e8aaf238458aaac4d68322710ded3d0b3ce8b6c971fcb970ef5a05076770ec60108b217d3236ab12b703857760d7780a64de019f6c7a94b800bcc97aaa9a979", "CS2": "041dacd97df15d91cdac1f8739529dc32510819f1abee42523209bb690b4ca0c4802a66173ad1a2cfa50ab5b981056e602857bdba42df9471edc6c8ddaae975422", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0418931f685ce02b15b6404df92af34be01803913e4da37ef4dc43ae116d4d98471300c6ed6f37c61dfdc149b90a584d4dc607a288b43947081ae4e22875ca5ffd", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040b6dc8831864d3ae5c3366db23bd43808e4356e5ade902cbbf5684dd591748b72192e21fab11c4f47fae06734c36c4e64b6739520e9cf3e9ee18c31f7485eaa9", "U": "0400641282eae991e5b7d1fd3f943e0757acbb441571b970723262dd0d1f37f13f20de59f943b6102d1197cfac65a391b5fcd0ca1f64ba4ff9495fadf001550775", "SERVER_OUTPUT": 0, "Y": "1afedd87f1eea542f57e442c4ac1a672fc5884c6d664137ad731eb6dec3398e0", "X": "0dc91cbfe8d916e1c7bafaf874ca6ebff0eca340dc301f22d35f98042824d3db", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 246, "UT": "0409fd3af95dc9f137b610b62391d3f52c41c3f2986c4f93c04eda9f6a3724d47214826cfe56b8d40804caa7f7f21039751fd235e72522eb5303d841fc89939ef0", "MS2": "1bae8530a3376cfcfb5baf25ccf8ff225420118073acb4b586aa123fc0e23a4d", "MS1": "08e7abbd862c51d1d55450a80c863468ba94bb6c51f7c9c2dadad4cfb7791b9b", "CLIENT_SECRET": "0410b0f918cf0d9ebd2c959b8b838325cefcac453a882903c975d6c726adccffd110328332fc6abd4ff95115258030af7c21bf57116882863e32325f31abe1da95"}, {"TimeValue": 1437055598, "SS1": "196653bc155d9f5e57659fe713d408557715ea0e23f5ad12dcf06899b609809205ab27062e4b2b95867eaab559c10216652721e2d5ca5d1db8a77168c021e3e81552c9887bdcaeaad48be89f708bf2ebd8c38aa4a3c9f633c889610bf5c16ec51c84f0d6f9a846213b679bacad6e16c1b7b4895d1a7483036cf489076957ba65", "SS2": "0cef62f2bb3947c9d037ef3efedf6061f86bfc0025722978ef1197ba05cc064911b7223c40ae953fd09186bad75ddc37a4d509b6dbea8532da58cf170304a43f211418ca5ebc09895454f286c3eb69f4b777b18411942df3e700385b353e65472332f569daeffce90efa5c5cf1fa113621c48f92d8760de1f42be1d5153b48ff", "DATE": 16679, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "10654236486d2c4dacedf4d0132af3befc635437629d056df9f5f029a761583616624f898c0055c4697683e05e414ed5bf132db49ddd4f28f943685a5c1fc6ba0d607eb1e20898caaf0af0a676e2b2efaa4f6bc733c3dc9504484dcbe76afdfb07a823f175b61cbce05c155273c560e0f27b13911bcb069607b124fb93a248cf", "SEC": "0402466f951a5ec592c2bb792e01b460abe6ce1515e179da7288df7fb83d22b1571ada64e475b4b964664c7bdfda095013ccaffeb1ed441025ab69d6571bfbbbfd", "TP2": "0408802bb89e6d387d21f9aecc7843b7b9eb4d5195b3318e914d1e2baddf015a6004d5df332da66e4295513e9bbd5f48dac1c7ca87aa0909dfecb5b9a7d9238b5b", "TP1": "0403932438ff5f634d654c368a47d10be85990130a0f7b93f8339d42e30f24624b1695e78de20cb478365f13d729fce5d16d17f2201d1e795daff47dd96dc59e8c", "CS1": "040db39c6a87e884ede954c8cc570e5161057c8ea6642477b01a6e29165e7f6743149943df5e4d6b4ec8abfbc4bb9229bc091961979bacd2e56610958ed61a553b", "CS2": "040a0b41e04421c7aa49a9023dc00777c94271dcf9332f43b0f1a04ddd8429c2951aeb14c4d885b2eafc842c724b98b342d9d8d288ee7fd5f739c1be990f563e4b", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0406a1cb6a4291241fb674079356c4bbc74675f11ceff9fffe5e72c6021fa675b10df84c9d0979ea8f9ea9b53a5753c532c98869a613819bb18be032fb29a216a4", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "041f0fad35c40738eb26dae8fc3898d8a302d7ef22ebfba2c9f8f5f13a73001d99212872f6cf299cfbf1629f9435ac89f330cf619e29da8cb9532077dbf85a7baa", "U": "041ca8ddeb1f4d4faa3b8e92c6475b08bb153f7a9e432d5d64d5aab613bfbfdaf104dd5122c23c571aab946ab84dbc974ef3392dbf3d59cf2cbc1d2c416974243f", "SERVER_OUTPUT": 0, "Y": "0419b7c74fddf418ed336348d81db4affb9c63ec4470140c27f6d02e8cec00c5", "X": "1c182493c3d6241b1686ba44100be37af08d0f74b27f3b136a46bfb66f11c92b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 247, "UT": "040d1836d4f942adcbe771ce155cd601a82d4a6566bb481670859a2e7efd42b68e143b29b1cbbd0a8e19438dbec1d3c1fda3e37da9e35925e7f58858c447205ee1", "MS2": "14a34bdf3cf25f760879c4e2970b47218d2be0f3f2a22306b3064ed441b1ad82", "MS1": "1ceb53eb8f64d9e6eeb652c692b6b0cf3ebb14fe9179545a1d3fe31942be2bdd", "CLIENT_SECRET": "040d638072e5ae1e13590f8037ce517472bdffa2ec6ff39c9600a2ba6add718d4e0d37a4ed492bb7a57bc19128fbcd4c39b2ea6ee8e54e4b3e91e36e11beb733c3"}, {"TimeValue": 1437055598, "SS1": "1ad0eb511695be8199fdb57519b8f8249432cd9229e001492d130dce7c11382b21117a79fd5a146d72e5bda7f085cc0b86638515dda0ce83e62341aa9a8c75ba027b8fbd13f65dd43b39b348895b4e65a23328495e88d64ddbc395f1e921e30d1090c5f6722fc2921394a600850c6e7345ad95b4bda15bcfcd5458cf9de8d3d8", "SS2": "1abef475d78361b670f1e8ca11481af3cc3e67bfd913ae51ed7e58eca16e782000156c951fc1de4741e062c55280fe3e92e67c0fcc6ee861d1a8abb02d978ffd1d10fa94df693c5aa3850401479ad27207c09acc3178f9b5d7b8ccadd7b28e3c1619e4ee1c75b67dc46dcee1f9c6fb18ddd6c6c20117a20307d1574005a60607", "DATE": 16680, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "0c344a8416bb2da7c9bf82ebd448c3cdde10fc6b1df26f493fd8ca8db4f975af1edb29ce28db04185e0a5ed405d57cedf9702edb8c5f7acd6a1d69af8a017a8e1371094095ad0f50046bf4431f2ee1b7a64811199521bae16c1a2df76cad226d004093d9c342f38e8be2eebb6c31c44fbae50c31c878d3827b2aae98b97be07c", "SEC": "0405976d1d326b02fd31e7b11edb09eaad740db19b5d80ecdc08dd5005eb6991e921d1a2834ec2a95032314a61dead697206f4af3553c6dc2f9b470fbec4edb290", "TP2": "040a34f7d80ee629dfbf35bd8987a8cc0be304b76610e091ae69c345f5db28581c22f266a32a281f65deb1e2e12cfe37e589dcd7c92a919cd266151fa3eab4415f", "TP1": "04003b5472ca5a8e10c5c52a5e2f7830270250626cb078a7b9f53a36f9f87cb08a02f2f530065188729f1fdcda9e666bf3f9cf0c77d24d6592c66530b54047dbe7", "CS1": "0404780d0b7abbdbc0d6b7c4858b329365f77a8f82120befa99f3789bd45b473a60ccdbf15df106a106bcbdcb0c50994ea3246c482ea87f12db1e15ec339e75536", "CS2": "040a9c96696e008ef5971bcd1995644465b865234bea611f28d836b38a62efafa018966ce0ff29281869f2e8973738c87fc443f8856905460767b09933380ccee9", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "042198f986a36dd8c7bf5e33a5711c5c14bd04d7374a3bd450c058f2245738b42a08d5b166363dc4132a0f0a2ebbf25d44d237b67ed7665c3ab4a120b639b6d50d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040a7feae76897f94976ac8e7470f730a63572d6b87048acfa6d81eca9b8bc532e0ccc63787c8262e11ece8453dbb24fcaab70119a3fda0f5a51808cd8940dc21b", "U": "040eea1ac12db97f06cb5f4d7d40055defcea56a16b0262c064a205b82f467b05b1f44ad364cc8a82dccd4e15601f5d75c64d7d874383bda40e2cf8a1642090800", "SERVER_OUTPUT": 0, "Y": "024ec018df07ce2a869ad7422eef6d572b96d447397c44a6cebb52c228b9a6ca", "X": "118440c931d753ab832d7abd9947a028f891ad1394457d5ee4bf1a1e15fd29ad", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 248, "UT": "041d57c8f5987152d953e7ddc9cf759bf83d6770f42cd7ae81d7a25e0d7f44d84d1b9cac11fadc3aa07f7297d924736a4ce8632252208fd0ab5873d40754c932f1", "MS2": "1766bee1ef609cb74ffaebc93fb3dca4861b89470d5465d2727a6215b521edbe", "MS1": "1ca0a1233f3d097c83711cea4532b4cf5045b76a88a1f265ee19f7a5aeb4c58e", "CLIENT_SECRET": "0400cf937ed072b4a25baa962c0218ad6edd14366af8ee98bdd7bf308cb0cf547b1b77fd2a2ec688942b25311ca535ffc31576f9859d1c7ca378c525ab4a25a798"}, {"TimeValue": 1437055598, "SS1": "0fd8e7adb2556c3a4ff14917a6a185a8f802af912bb019f408f85156d452bd191bbf8ccc36ffa472a3c18246625b9232bc2ab3568d5eaa94f57deb4dcb79972d1fd3b441b861a875dcdf9c497798d46d2e8c80299e93376e4da4364d971e2b280365c7e9ef8697837edd1b123d6cce8c1ea16c7c5e8afd674ed55f08cd338618", "SS2": "1c31e4819e05b9b7e6a50e0486b691fcc9f769a329d9b42312fb278c45a82a4f14b378d2872a651fc59faee38b8a9876b7c735b8691b8f5537e6e7cb3d65ff8504d08709e3ca930758cd24277cc99450c737f0919b9035173db6e97e71708f7819e2c3fcdf93688480e82364754542182ec1a248bdec7b0e020af6c3c584242a", "DATE": 16681, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "05a8534272ad8dadfc06cc43b15a94b1dae92d2c9e73bd04b7e8a298f9c356d510b7c7d21dbe3af1631e406e0cc3ceef55df65048844378be1ee982768fb487919890626469225df40ae7b3e09b7d1120ecf4e51a180078b458b96954689a67f0f420f53d55315d0d5201f18f187797d04d38a6edf84df2badd350db185abaf0", "SEC": "042023b3cd6c8384c4458825aeb06b319249ee9f3ca231052614efe1ef1cff07521b674f89c9babe994fe74946ecb20db47fb7556ce213e031d9188fb32b36ed95", "TP2": "041901eea9a082253fbf05ee88f0dddfce1ea11ccc401f77b77ed4e5a5b64477030da5f83cad681aa0d526d698aa029aebf3babcd62fe0f2271a2cb9304a3e5cbd", "TP1": "040c0b1ba8b147a4d36e3d239a008b040a7daa742e7703a5ab11e54ba61cdb7a78157116f6dbdd46704919b9e56ebffb42f1d6d86a20c88db22dd63ecb41eaa43c", "CS1": "04036c0ac30b9a8bf9e7394eaec0a4286b74d74e8d4b23dbf41b22e40691b43d3103ba7501aa04f5bceeff366ffbe75e3b6b0358cd87ce985d8e405ca34dd49131", "CS2": "041cd11e37191ac6f4674a2b65a8799106725e071e07db71ae643c884ad95e601c1bab3c83bfcd114f35428ef9fec7aa3164754ef5d60dac8a130a05b7b8db5a77", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "041c413cfead3d57766eb02ff8498c857c251bf16412b14dee161db913613cbae91dc74246e3c2349388fbda6e29cfbf390e6ce09719357f558d758f8fe3c66ae8", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0415ec9c220b0a3a7bfc0f8f09d5e41c76f8f575229c68538872b89d9c72f523a203652b517ce2c00d29f66c818454e5aea6939c64ca73b105439abf40d905cf63", "U": "04151c31a6d5bcb0cf4bde9c071671fe099a7399b0ae6a9dc2a7e14093d2893deb01ce767c93fefef9b4f8dd46f7a63a9fcc83a0d53b575f7c3eb2b47c1e465464", "SERVER_OUTPUT": 0, "Y": "1e855ee24d49b54a9c64122044942c655e6f5aeb4382859906691a6886a6c02d", "X": "135c9ff7c20a8c1bebb1fab27df5486813eea8a7f2ad16f8538f1d1f85a5e8cf", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 249, "UT": "0414a443f31d4039e002bc108f51c7a6e8fe62b0d8e78a4a804536abc48ad2a7df143dc91c41a7b352e001372a038bf6dd4917e232bfba08ef3babf6d046e84805", "MS2": "15b303ad984c3b756ba916b5fc6a44ff0e8a8fcd7d38ec7f95efb09bac255a32", "MS1": "1addb41575d4aa27f4c23ac86cd167345e84a2624736b8bf79f61614265bf876", "CLIENT_SECRET": "042242dffa5830b13b2907c408b75ac53cf1050466339a58dcc8cb01fa81248e3e1a2308da7e83f21f799b9c3bfba8fd5ea54de07157c3de9bcdb4e1794a658f48"}, {"TimeValue": 1437055598, "SS1": "123245a55c22190778ff4415c159b18d74927cc59250e9b76b08fd0d94d0166819728ccceac01c62f0d1759c7e24a02087ef571804d8e64c71c680834a2ca85b0c360f5ac4fc4ec0cab573c584d1268e6bbef225cac1336ca49661d8adafbaf41e8c2213f93138201b97210b59c90d98dc593f337ff332572e05154b99d5fa5e", "SS2": "16c824e60c1196d5d8b41b64df8fed2518ff042a56021877137da2ff43a10ac61b5ed6930505ec6477d97d995bf885c3d5d039a196e3ba56e7cdcf6d1d36f07c137cfa8380a5ef9544180884b7dc6bd7e1607105ade4a56d70593501593585511bc7368cc66b666c29e20f408babdb68e992b135d7f5745e90984f20ecc6b49c", "DATE": 16682, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "1d7f7e51d3b1e6c3a100e81b8baa513b0e017ae2fcf842708e9fb2b9fb54ac62120580faa221bd92b133bb0f955505323db7b7bd0dc2087aa0bc0222420f51b1060c9531fccf27ecb8111fd55c33d5fb855edc9305ce3861bd596be52e6de6211fdace9348656c10b5bb6206853f48fbb8536926cd61cf10ff14666e306162f0", "SEC": "040445277a7bec3b755bfa4a1d11859d1bd0ff0595926fd486247260bee23973270497a123a86efcb12b3053a9528ecd4eafc9574eb22ed7edb1b8b90c6d0b7062", "TP2": "041a09f1ae35abe814562dadf43b2dbd9e34f73135532048864b069c1aef9ca32a20c3b57faf57578bfa8c7c69eea38e2617083b3ace8f2f1876a5b1c5525a61df", "TP1": "0409f471f9a714ce2092962701ef3601ad82364eedcc95740f29e41ce316ecfba512589d90be471db49832491378c6699a9091bf9d6343795f597b714f62932a86", "CS1": "0408d0edd194dc7e5924c172a7185118970c469fef2114dd3c21e2bd227096eeb70e906d7162929ba8b970bc1250b993ea8bfe5639759d25ea7beb4941d7950b4f", "CS2": "04003850cb7d8424e938b7047bfe48a01d1ba0b7a28a17167ce343b1640920ab6420b8decc6c3e0961e54bdb5c146d06f0bd4a66697a7b390a7e7dadeb50494bb1", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04156af90f95083b31b23a5d57e02c57327cb8c08f3feffa687f5a17eb9d0cd2b817cb93d2fefcfd24bf4e9fd7e1cd6f333031ad1421cb7556da12dbeb383dec27", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "04226400583cb132db788840ac3d47796a24e1a749f357189451e28fd93ac4b102046446e0cf34862ae484044022e80884526878442fbfb43c2c4adb05e6bb2ff4", "U": "0416f31346151962a3ea76a405957f586058be940cf6b35461c2c59a63fd8ad3e4029e88f6e85147da749d5d6e00d4c8e35339c6408b9dde6dea9661b190b01884", "SERVER_OUTPUT": 0, "Y": "0b552e1f385c6520b778b311ca2b5bd797f87e2bec1a7230f06e2e8c2bdcd372", "X": "145921c66f7feec9cacf08aff99244af73a326cd894c791539354e9a0a86c51a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 250, "UT": "0401e1e2fbf9cf3501fe95424ef86e382a731af5539abb8c432a6b931ce48035180baed2da23fbfce757358f6fe856a24ba34b6c2e1f027da813fc373a00156e95", "MS2": "0e1da8a62bb0657806fbad1852f1cc1626e03b581c5e1d75129edf3f857948c8", "MS1": "208f11c77bd8b2efd3a7e36fdc84f9df2b0b9d9c890a0a27ed85829f9a912a6b", "CLIENT_SECRET": "040426d4895f21414c5fbe00367ebeb8aad110512c7b84a723534c6d052aa29b6f1c2f944825fe945980c542b59af32e7d31cca45b63939ba805c5d3ed19e28c6e"}, {"TimeValue": 1437055598, "SS1": "0181b597ab297ad50f2f78812fde9e857e5abaf17b8fba127f846b31b7203dc4214a14986c6faa8b10f00cd17f01986299c3ac6ab2144d179092dc0fa6b0ba1b15cc95dbeb93047cbec53e6ef694461d239a54eaa376ec99de5ae5f529f4d39218c268b3e0755df2c4e217ec9e020fc997a26c4c405b826f33ecd71728994a7d", "SS2": "15fcbab680b1f403a2475d00a0a72ddd4dff2a5347a3fffa5b3b094e627e32130f7b03b0527b4c96b1de6e1d1e6beb2de6ef3d55aa0f6cf939ada92474716ce40edbea82a1a89a6c91862c723ca39eeea19a432d0ea9c9dd83e3125db06246ca0c8ca0b3376834073f4581162930a3783d7a84791b4167ae692c5b3e1576db9c", "DATE": 16683, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "03acbf6052aa636510a7a72a5bb47dcd83f5d976bd1782ae0652b5de60103bc912ead0931e89a6a132cb376969aa2de5d5fb33a43e9662a7e904a227e43c1f68098b804a1a72b1742b9def5ad1ec0f8aedc144a6f294567189218aa1143da82d07502cc994810c8de4f5d0aaaccf3dce54cd4801d95427d806ec1a307da9487d", "SEC": "04103560a1d61d35000b0c9620b55d7197df18c0636a3b698adbceb73ab5637fdf198e453cc7e834383488dbc0b629f20150882d5755f9df305d92f51298b70dff", "TP2": "0408d51e947e89d09c01a6874858f4bf3ec487cc4343a7f54b9a9974c439bacbc603652ed64f1a2f5f27ab1b7daffbd1b7382cff1f4331da3fc55bc30dc30f8eb9", "TP1": "040511f2e767ceb364b37fd7c7423d6338d684442aee773b1670421689a8310261056ed151b24bc2f5e6161b2298f969ba662508ee2b9720af6c4002a24d594cc7", "CS1": "040546f23ea6095513d2a99eddbee1a74074f0a3ad61e0ff1458ab28d59ec5f4b1232e71e06e6645bacef0064d5703b7a0b3c4553c91157a7504c2e08f53458cc1", "CS2": "041a0f0fb1b0904a2449042da0dda5b8e2b1b451d76ddf1b00594d86dd10637e2b0e42d8f36d7aa78d209a62b7a72898b8fb50f4239c2e6e62946a7603f84dc63b", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04085cd9cb343b3bbaf85ac3a502284caf85c86f0e76169dc6db1bfd601ea7620318f3770cd72f3f3896f9726d949b425ef26cacde7ef410dba39070e3d13d238f", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040e3e0e41a47092b3329fcabdba2d7c0e8ebe8827665c07e580d9f60e58ea9cd11133f17eb4d84747f845130e6c7d9d4baa30d4d28c218fd8d082a211530332a5", "U": "04148e3e746d4f207fa5c29b79799df8e7d5e0df6f3209ec2bafa4fa0d77cef71614b7e46d59d375cacdb410c501b7399394928ca772f5b50588598dd5e1c8691f", "SERVER_OUTPUT": 0, "Y": "05c71070427891840e6a61b9aadbc72f8053db4d47b559bbb36cb61431720f20", "X": "1bc83ecfdffc1f9c81bee0a7fea2c08586423de2ebf211710a2bac91a9a0f81c", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 251, "UT": "0414b2db90dbf95244eef85e93fc8e08a0b42d6cc07b36f35fc5529d5801e15ac10acf2454f9cc93205d28b39864686298483237d1dcde2d7c2dff861f8a183774", "MS2": "0d6ad64e1a34f6f2c12f056b01322bc62b89b509a8337ac847b4359567058936", "MS1": "0b634cb0e1984b4e0048de167fe51ca8db2460488dd50ef8f9950e21c6b7d9b2", "CLIENT_SECRET": "04127e7bcc48ba0108cfc2db0e976683556bfb2bdc8c714af44debc16b66addf5e0f12aa3f505f7b4f112aaf54bfdab91658f9fe97454538e0323f43588bbeb203"}, {"TimeValue": 1437055598, "SS1": "01c7719d68df865fef363eadfa1920c862fb636c46886bfa2bac1234eb36181c00faf3bb40ab3319866ac04ea8a509d9c18d501e002d10a31de2383743a3c74516e90759aa96bda1e51dcd67f7e4d2ceffaef96423eaf6b14e68a521c21d06ab237e2f6c3a7ee79d966efbcbb44849585a6dd725ff4c9b980db5e658c0609ded", "SS2": "2210bbf78b53aa683237edb0681b5fe97651390cd64b50c2ca41660c0c86a0e70e279e9c3ac08abac668e324709aeeac3463ec0bdd15946af360fe1718ff8948079a802af12f6d8cc161367b345f2f1dd80a440f14de0ce3bedbcd8254691dd81beafa8a6c22fb9a80ae5794559a24bd4ad6894790a302cc8828ca8e2c003248", "DATE": 16684, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "03ce32e6d2614ac9a18904d959f3373905aadc4fcf7c55fc6daedbb8ef9af17f218a400537a42373ce27ae816c0e747da129ed3681cf0f01a6bf9853fc45d54c1e9cc2cd8e3c3c84732848f3691d65afdc991fc1d6c5a1a98ca6e8d37a7a553717fa349282dea6fd3e26143f00b109d41ad75f33c1c371ec620e55006fb9ade3", "SEC": "04097d99662d9d5dc0fa5096696f1e202cfb14002052b6509a2595481f47ed40d212aba0cb5170d005e64f520d9d4cdf1011660acf05f728530801e02d600556c4", "TP2": "041210557cca3464c8fd8d555c713a90c8d920fbf3d556a1940efd274c83c0169c028c2759b211e0f7c289dfb6b5052a95d84d62d2c6373855ce107c155cdbbbad", "TP1": "0415bc119a7feea8e4e2673c5fc8df4be28cd622aa7af3ae64d5e6c31551f88c051ae1e473442e02217b5578c0625506a3549b15bcbeeeafe36d7eda3e3a1018b1", "CS1": "04105c9e7b4e0e440a76e57dd6f39a276f71bdd7b4b72512f66fa45d97d8d75524029472a2806fd43b72fc999ce4a740a3837cc3ca9ace1dd37e86d38d40895fcb", "CS2": "041cd095d2713b434cc7a6fb84cd01aecc6c39bed0cd9938acf62dd78c27bec81410cab1ef0e496f97d1b202c19c33352bdcdbabdb467e6ca07b4bdb220d3836fa", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "041beda639dfbe6b2f0ed04a251dd8d0c1637ecd45e86b3759613f4cd8defe51680bb4f636ccd9466102cddc883c4228db0d5ec420752d131cb01103adf0c5dc78", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "041c352c93aa33824eaa71d4336472a3f5db8686d5747a8b398076644a8d62f56708697b211c785618bd365ae49870492cc79e2fe6f1f038a30ea74887c10f4490", "U": "040c9653e8681f182a9387254c0c5510b5a6041b1684ac6c79e9fc3a314427c49d0ae912f78a1f7f1f9eff51ecc4d8ba3de831f3c930e4ceb5db81f67f020ad604", "SERVER_OUTPUT": 0, "Y": "09df9dd50babe11a4c32f683cd492eceda77a4dcd96ab2353cc59d0776cb4cdb", "X": "087567188f92072b92a35cead7d19949027cc207cf7808c30874a69c9c8677de", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 252, "UT": "041e62f7cf130be02ee2dafe8a3e5ffe8fdb998ac1f21c79c617ecab93fa39d419097d3788435a055acbca69e9ef106673dada888e10688ec68c35873b80aceb64", "MS2": "03955d539b87382e3935a252c7e6be908b4899fc878c4b2923b47b9e16584822", "MS1": "110d5f5f3aa54ecc98a077f7d3a834bb1344601547383a419474d697914a3fa9", "CLIENT_SECRET": "041f8df27c139c15720b1d9143fbe85962583abfeac34fe70eb5db874494a0df5801456e88e9fa3d49cf0180e80fa0aeb610f5aeb9dfbc9c4a5e25f4f3e7b95f7f"}, {"TimeValue": 1437055598, "SS1": "1fdbe2701eec12ed9e08349f0570cdb4f164d5fcc5cf3f4e3ca16bf07e3324990d35c8a10e29be7f8abec49696bfc4942824017e34a689f697818ac937ef85fb0ef383ebb05a1baf88be5212052929319eb495d73a4b6e278fb384d0bd4b0dc20e893e52864d4e7936a72f42b755902d632e1308d03695d824a31dfb0589db98", "SS2": "0b00e15b8f70924b2a35db569a27600358844959108acab0ea8c2c5f24c327de132fdf77d322922e3e9f2ac07c97ff23ae07376991d27a4405b3f49bbacba6821caaf41eda84aa20ba5769081fa65c7a7872e75b408c82a5eb235a9bfb4399371a5ca11a34426e62b5a99c322a7be4590e2f27ea3e8dc054f543b057d9cde9a3", "DATE": 16685, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "1e413093ca4263cdc5df4662e8195ab9de84c6c6db798bcb3f873347b8f16d420a7178724f5b4aa0c247512de31a64c877dbb014fa7f8fce3a5959e670cb99a4138ebda2b1834d8e228544b6599f270335a5478edcec8610d68e9850e2ffb97816ba9d888cb8ed75a1ba8fa4a350a8fe50a7e126bc0c34431f585164f8b3ea18", "SEC": "040e01e0680d1e28e9746dac692cdc650a86ca8f7af88e31a0492a96dddfde298a1f18745c42c4e0618d7d2924858f7ab065b318a60851245028039be3657dbbc5", "TP2": "04218387f2f946c15d3334a09fd5b5af09fb2c1ceb2028e2249702c1d5bc991ae519f8f1fe6a3e0fc4033b6fec4a6233bf26e290fc14b3e28f8cb9cc5fab4d9ddb", "TP1": "04059a04625361b934e3fa3e596a9342f892fa0ac566a653b7647a4c30af6bc9b20653ada40a7ced2a0e4f2b5698acc205e2b66109e0d11cf456e0bf5479386f1b", "CS1": "0423dd86f509116a72465e0582c160bc47dd789cdc5b4d4741e9ad2a979ba9a275017452ffd3cb97564157a0eee9957add0aa9a92c55a5d4f1cf6b2f17b4621fc2", "CS2": "040d14013a5a902b95935e40465d895aa5de9fbb9bb3c21b86b712528964e91d931090e4d284c6ee3329b2f9e8d644ea9ab62466f3b0997e3841cbda4d6c717d34", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "041a110306af3caf808ee04468ee6f1501635251563effb880b00b2093283c772f084da3d29cd6d9d8d237802a3f7823b43583dc1810ac93bb39f7e9f48645868e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "04073431a9ae6bd7049530cc64b773183a3893c5642d57fa650378d660c4e073e409b9f0ea827b8e4f44a5a9482e9f4605c205156bd90bff6a955c3e19f1fefe2f", "U": "04140a23d473e57032ea9ec6f7d89417d8072bf35f877deb1d0165e50b10a5ddd003a97d31db3d0f5f55cbc76c77274e5ef19dfa9937e84b8d9487799d4b318a79", "SERVER_OUTPUT": 0, "Y": "0247349ab5cf3072893e80cb1a46814a407c7044ab8519f78390d961f8788929", "X": "05449f3b78ff06b31447ccbc30fa00eff4402a4373bdaa7a55a2aaedfe36e4ba", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 253, "UT": "0402388dcb889b87664949ca4c4eeab5a4d87cbc8c8056f59182f7f47f1d004e9f0af939fac8f292c6114d1fad51df1a78cb885efdd70c403f31a9f8d1603ca5c1", "MS2": "017c1787cbdd3f97ecb541c696e1aa8a72c8c22ae54908697a83df904143f208", "MS1": "10ae4b3e2f49fb7772763a360186c633d17cdec483cbbfe7036dc05fc9d22248", "CLIENT_SECRET": "0412283994ee915dc73adcb9af1845fdb7920e6ff73cb8d61789f809c149af9d551ce23043f7fd2056022e1130eed0b99dd99360bd677556f11888623b626c269e"}, {"TimeValue": 1437055598, "SS1": "2222999e42c84958badb1b4d76e3cdf8ac5d51a68744090129cc35714ff17c2d22ba2a62606b524d9508a39ce9749e8bde3e28381f020df075a796413bbeb0dc0de36eb7110bbd77fa687211e1d5d3ce9d1804520c10cfc5264716cfa6cf6f200319b87d616d6c3f99eeec76e0794a795b16487ec2d1eb59143d6694477c4a44", "SS2": "0f63451d3ce0c76f716ca10ab0bdee168dfa1de01479e038e9a466031b102cd9026aafecfa1526c984e66b5480807e4245a05e8c57bc53eb2b3c76682a2979110b0e0af7aa9d6c971d53e9783978af042806d1d34bec2b4153d0bab9b73d26380b95412dc260bc7ab9869fc13a98075f5cb0a8a2ae1b9a7fb48e092efb682dde", "DATE": 16686, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "01eda67338e071cb4b87c6573f4efb7921362eb2eb1ff0ec88dd675390bfe6fd0f4e715d5dcbe0713299da2b3a34fb482b344e0be559caf483a303b0f576e571102ab8db34118e923dd29c5c8b8476816c3447a522cc24e836865b30af6f58950b841f080ee2fb401a6437e54d65ef065bd5d4b596e5fee484e16603aac6a354", "SEC": "041e7fca9152b6d63cfaa8f527037e484bdc7493de8cc2ad515b0ee1c2d480c6fc1ac86afb322ed0feb810d02af2b2ae46b4df84d49f3fa02d69aaad0d14fb9168", "TP2": "0416061c58f91db51c819fcac870ea931f32bdc9e0a0ea32f69544853d7bb12c731d90b8869a0179e02a889bd5398e9e16e950c22f5be004c6910e7062e52dd44b", "TP1": "0420a92a8795d86f8e16611884acafa95e440ac3498b39018e4574cd4b5e7e8e8a156d437041db9970ab065908b8bf28807d78f216304fc45b0e874fd45a516b0e", "CS1": "04016a4c4a15334a824203ab6eec6a954e296e3767bf0c1c51b0f3da3ae3c8f6ec0b640d1e40a1e55a3e075583d25ef72cdb5b2e75cacc041b57210d5ce5092bb2", "CS2": "041e3063a78983fdae1c2fc6154bd910636fd1ff1a65fe0a6657d346d6a2970b3410aa7828e8717d47f60ba46621985d8aed8197d5a14141b17ea23b3565136673", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "040f870d21a98e8b37c860aeb2c385eb1d2bf980c282b5bde1334a53c97065c513164e142e5f46d99e019344e13be885fde6b7a04a2306226d8dff812ae6ac39d1", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "041d05b28e6388fbe4e4b6e6eb930318344914be42110e497ca1a81e503a401d9a0bbd01d2c3277eff3eb0cb58b59258c1e9d9ef9973162dd50135dde854ad42d5", "U": "040001529fb6fa55825033b127ca6f3cb5f0bb1c2b9da14a31f85ba880c3919139090e8cf2ed3b34f532d6cba2fccb9a05f50489f3d0de91b559f303cd7eac1d22", "SERVER_OUTPUT": 0, "Y": "0e4227bff58036157c0b65e935d0c0bae242e21952edb40e695ca95694f17a0c", "X": "00b9b60b92ab7f9f6ff84c89073404ca19080cc900e552842889875b711baf56", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 254, "UT": "040656ee4c4ea4e6a04456fb5896e20ac83387de9cf2c49319af5dc9bf91cd43960f5ebbe55ab155100f6f56b7aadc64136968cb2d15cb2d2a0fd99c7285eebd63", "MS2": "1802ccf05485d95dc32ec73f452350408f0e5cdef4dde11f5b4f61b3a6215018", "MS1": "0ef77c44ccb44a84d551db84c8ed69d655e805a9657e1ecd99a61f33cc0c5069", "CLIENT_SECRET": "041bd233a0c9732ba9247c93a97b4eb9c57132fd33d091040a3226093183389eed0d1a76843a7c0b154bcb7d45149508045f1e468e55cb9f93425617b1dd02b958"}, {"TimeValue": 1437055598, "SS1": "0032618667be87e8faa2524a74f1d15009d7ea462a99e24769e25c786b20a42d0c223095bd471bee5f81dbe889d8285286b1321b17847575954b4fb7c521313104f7a5c9d4ab318dcc02a9c96c830874f09da91fc888a42d08025226403e1287165ac0210103afc6c8e09ea45e75732cdd1851c9a492a8cb89e3e764d7164f55", "SS2": "0bbfa2778da785919563383b5b1a2967e0009994de9de14fa6c54ed47caf0ccd0493d6cf04b159bdce78af526aec43dbb2338e0b280c1d20dd145d4da0b8e0020fb6d213f0bfc922716419e7096cfffbb44f39ffe36cf837ac2c443716ccf7f511b60390145a3c18c0096bc41105e52344d2e0398f9d3aff57bf05d2a659eb97", "DATE": 16687, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "20fe31d488f6b10a55bc04649e24ccf0aae29ec4797a50e0e8fb68ad92e47e2c0e2ad9a4714ce0f429e6f09c30599d3530dc99b2a72ed60c3761273f91535dcb12236e2d4edf9c5f571d18ba28a9b26f2ce5653a1e6a641cedf6cbc457badae705a5b4bf2beb5c71d342c2d1448a6cecaf11da14d65b92f7fd39bf1691f45b83", "SEC": "040c01db9cefca5ed1a0158ba1ef152a09802346a0f92c0b68f8ec47ed3522407f12b8948ca8a5388099bcab560353dc2afc7fcddfa682b18c7396576f041b2e9c", "TP2": "0407b30ef7b319342273dbfc48208f7bb7cf11d360282d7bb41c902db3b3d64a610b4cebcb08439becf25e5ecdc644aed0aad1ae5d04f1439e492163a081691974", "TP1": "0422e42a37e72d393de9efc238c18463c8b0ec39b43080c6fd9adcb7e6c8c121971dfc815d12fa915046790eeb28279d22d7971b8f6ce70c8aa27794cc689ade4c", "CS1": "0418283597aea64f6d36bfd88fb61f23fab57d80671a5e5785ca3a22275fa6b81808a1a9da7a8ace21af90a34ff579d5d73eeb0ee5bde250d9814634eb3918d14b", "CS2": "042143b0d69a98623ffb3120de08e0cd71b782393d8c37e312949f8ffb1151f03401cd940c2da065659de286def983125d1e5d5793c2f39833472c708b3279fe82", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04137b3d9195743d1a81e98e46d179d65acbc7bfac8aee1965efff93bbe93cd52e16039bbc6d15d7870f1cf8b44616a7870fa2a31ea945f2f21b95d5c1522c6ad8", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0405014f22646328b1d2622e23f7c4a2fc984fd05ce3d990cdac3e1f5d1a9a2b830c803435c575eaf1e11d0bae9d3a07007d4a9ed9e15143ac72090b353f22f79d", "U": "040d41021bf707d5b3c8a708c1d785a42ccfdaa8a719c80b8d3ed0bfffaf43924e1af0992de7d42b68126eb3ff6c9929fa8330fc92b5deba0704b3b13085e52ac2", "SERVER_OUTPUT": 0, "Y": "1d69f49583642d4ca861bd234bd678c71c9137704e9e55410b11543bab34ea49", "X": "1a9cce56f7ced517c68890377d0013dd99b1e96c5c775174bb8980b1e78af57e", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 255, "UT": "0415f14daec40327512f479ea754e3a3d7ab625eac545636f07a3a6e88f629fa8b0a7ced99ea92b768c3095ed3e8175972a59dd38977fb17dceeea798d8ca8fbe1", "MS2": "090c0e9b1042b178bd59a4abd933cdf7f554a80f25e23ee7e9e8c76f08fb903e", "MS1": "0b74a067cab2c2dd382d964a0db5987bf7ecc103db83e863554d7f608b2bd8d5", "CLIENT_SECRET": "0401f09b18c1267662db97b8e0b68cd03e8ff5e1277176da78570952a0c90a8f050619e81afec14ede9f9d8a3ff41a3fa9bfc7244f685cc6e94cab7bbcf68bd866"}, {"TimeValue": 1437055598, "SS1": "147deb56a546f01587582f0afcf8f7eae2cee9837fc57322d229989fd79f32141cd5244b345eee6add3e65c3d81fc1236ec3961ef3d93873429ce4d596675d8a23bf2579a414da566552de585e3feeae576f5f6a26e81dad379db18feb2c6a6a1b59f7d2e06b95794e40112137ad029df901188167d198b92e95da13acb389c7", "SS2": "236e33ad72b9e1e0192701e6fe267ca7a088ad200f70eb458bfb1bd6d83b9b7c23f5d14f8efbc134072f62a3f0213b210aeb7970dfec6b3911a5b6bdbbccce2f06ea811367b75d1c1907987e6c30b31967bf75518e4a8eab397a3c7ac6e04db2148e840f0bb2307d6f9b4a9af0d101e53024f6560d433ad97518ac5ebdd2b2b3", "DATE": 16688, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "020807c41528cd4058c30f14e7b5c761cb50a51d88c5958988b98be64f37651e1201c8ba0729f379053c3175c0343bb6790c696883bf8a4a497339c55164467002dde27cbee9afde4e0199c02b600822507c13186c2163ff33f8de623eea00a90a70902f274485a3ecf30f73114bd707eb56b2777c34c57710553a53db3bdab9", "SEC": "041f723588583b88bad52190b7cbc2fdda131bf1a038b7bb6bb11b36d1e6ab3564203dc118685d6a5cde363a499453d035d95802ba6e515c5dff9fc370cc0133d4", "TP2": "041d3345d03452417f85e7a0da3f8011f41e40ad755c97d0645e88964e34367ee10a8da226817b88e5beb4d94c2442bb3f47a9976604160be778865015a3dad112", "TP1": "04020965f7d876e5c45f808b0c67a01bcadf4c56c3dd7f79b3e566c3b2ef92e4da12e82d16ed4b1f9d20d719c0ca505969484d2d9b693b724381c16e235f036189", "CS1": "0400a2cee99f86dfc8ae73cf1eb32f3a939e4dacfe48264863da70d15e7363ccee2364cf71c0bbee0524325120a36d6a8d0d0d9fa3c6659cbb9be3531584b74f51", "CS2": "04085a883ae3a4d379a36b4ba759c6fd3b5e0f77ff9b17f0d432b4fd811aaed5f8165621c3d6692e4e3db158bc160535e9baef42acd329283c840d9845a548f225", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04155beeb38b126803c76f10267aca5e2af480f1e9a31bdf1bf89b56a2099d82f80847aac131a22ab69f2d7fd6857aef14ff578a7abc59c9d289f3891fa8468c65", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0414bd84e8d698ff7b1897d5fe46932226e67bbf9d4280881a1d1a9cabbdf8abf9123ac4d0fbfa6af57e8e2aac32ea0c1cfec7125d3194de0c23b082e1f4c6ba5e", "U": "041871c7c72bb6bd8eb1be8f0bd993b20aa26e18e0cc5967a5d42a2f29c7d08d0e0dbfb6953d8e8a53294e5478e92c40fb253e57908cb6e998ebddf9a9d28bcfd1", "SERVER_OUTPUT": 0, "Y": "005524b75428e0ef84ad06288575f9a81bbeadd020582bec392555d47bc2696c", "X": "0bcfa4d9e432b6cf7ed17ea8806d93963d780824738907f96ec507360402b518", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 256, "UT": "0422206cb1857d60698515342aa145eb31dd9b26062daf07ad264485b175d53876042e01d658d748372b06320deabb267bab77e8a92b30ad60e466c68b52c14e8e", "MS2": "15b2f71efab9f570866658e93f75e056f34526091c309444f911ad905f219b66", "MS1": "0ad22bf718144de9a879148b22ea1d9938b4ea735be81d8a916560812e6501f5", "CLIENT_SECRET": "04066a028db83207c3eb88d44798c146163681586a1c434b40320f245e8dd470cd01b063e7461a107802c71d41c0c5e003063727fc068f096d01e47a0e7ebed675"}, {"TimeValue": 1437055598, "SS1": "099db012411b8b1c9d5fee92b3a08f94b5b37e079d9ea51d256aebf801aff62e0abf092a47cf6bdf9229eb6a7aba3ad599974d7e0b1666969be7699d96fa9f9b072d4116771e8a24652ff3eabe70dee896b10118e69e8f549d5fab24b44f8acb1c2b80e5fbb668a58b560ae4eecfd46eab18d6643358b0b23ade7ce2b3df9cf8", "SS2": "20e8f4d57a25570015b56c265f9e205e5f388d01a9a4cc12852b1cfd0a0eedbc0040dd4a1df83f5f67a2120fb5afe70016d0dc7fb7e389247a7fd91e3ec678b01cab3d6878b2e2225b96c70449cb0205b46c472af774fd7d921aaedf9a0a15f008035babd6fa3b078b42ad13dc02a29b7e0c5ce8875706ab64e95939981dfb34", "DATE": 16689, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "0fc45d1202662f3065d8b37773f79fcc7919807a085456e738514e2efca4090c026d6aa89b6a59fad26ddf80ef917e14da14ef0be6fe52780d733148e9abb1d8067efaee7394aefcd69ed740afa020f0cae820399096b6860d0682668f72900b043167a70a838cf440493753df59326f5346bc9d617adea8c761ef95779af7e3", "SEC": "0411143a10da87db2c883a8606798c7fb7303d3aa4f1aa179890ee2d4f5c14af411bc6b010316ee7581aa8db4713f4279fb53e01707e92e38bdce20b5e98dfa199", "TP2": "041f03d31837739488d033a121fee195903c980782c78c396aa20c1775dcce788d0524e2a3cfc0a3657202dbb3014fbc73227ef969c15aa749b7c308b4895c7089", "TP1": "041677e40fabba0296e5bfa2401b7d3c04bcc263a3c4503c65354743fe7fa11bad1eb92745e1a9644f529b949faa4d09fd5bfcb7f6333b7dbb02b82843e0db6fdc", "CS1": "0410cc5dc49a82ff51ea1b7c60ef6a77eb7b0b962f9c113404f84dfcf7bcf6f393002e77aad6de7e18f200befcc0c9c0a4344414197673e3db646ff9bcc1676ba5", "CS2": "041ec5c5443578f52690cfd1afe75ef3b118cff4e2b62962ea657c720e6e1e9a542038fab73c102e39b8a34e8a9a5efcb96a3d6dc4b09edd0309a650af001dba9f", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "041dc15467f7c75cec9d50c8f6d7562d8b76921f762d831a78a9ec625376abb5d10d850707549ed777ea52a4c7d0093efdf10e03b5529c055ca6495a7c591ebfcd", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0418a29f850074cf6d743e2c34386aba7737d1113c36cef11b77ca179333614079090271b34656f6bb1a0e784edd305de37b29e20d8c6049b8331952eee3a39fb5", "U": "0418a4a9971f764ad072c87593b80e80df9f09b0564dbdc0a35e93f6523e6d31a715d5925742f06763c2f3f50f0d318bee426056fbeab45fc2e232105207d8aef2", "SERVER_OUTPUT": 0, "Y": "19f437985d5df72812945b2a0d235b33d24221b92be001bc7b065a75b770041d", "X": "1693532fad5aca84d0068d157c0c881ebada11961269c84f2870426c7050ec59", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 257, "UT": "0418ec8a68e1367fa31f9c5d28bffa454b286067e72f495ad4164f8c1e885c47d40f1c3e181ff8bc27aeefb53168bd53b03be2a96f7abba2331fbe1cbe0b14ab8c", "MS2": "086d3bca4c8bb15436967d350ba1532cbee323f2b56ad3b405d8ef9c9714c1fa", "MS1": "059f73160ff923c873747d85bef91b0925a4d37da4ff300ae63021bf952e1176", "CLIENT_SECRET": "0419b8982406934d33ab871561f9f08f71cebf22b63cde43d56e9ef988a5fe68ba0c15071410892be18a951b7a4090d0b0622a0f967af530d0b07af25312cf6f15"}, {"TimeValue": 1437055598, "SS1": "03025fffcdc27dd36f42eecda87b6396945c121b7597927aba10b5fc426dd4fb0d23ee5708a7f2b5a2f9983f9ea6f8915a7b64dc41acab23dd36874ad7ba8bf91af06a04b8563aec34fd8a5bdbbd6924bf95c1f88441dd87ddbcbf5dca6f5ea82076c09482bec43f2eb0934fad85b22f532384ee68a853f7934118e8721a9d89", "SS2": "1d196a31fd7905d40fddfdba0e482901f9188b8638b9e5bcf240ac45993de4e508961dffe8b019e051bdc1fbee76beba7b4b179d90ecebfe6a99b1bde65da388224197809f68b988c74e545d6eb5d87e8c4b6065896a348392b9d4652c784073163e87bcf107e9206e36c8bbef0fedf900eb2f50a50c4d5c5f258e78f5e47d16", "DATE": 16690, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "18fdd72f36cfd89f71202cab261894d2dc7a1d6ed477b7eb03ad854c09d3ddd91a7c654f70c8633f510bb8c29bf0e05485a98b60d73c799fa7ca0347a1c0ffee03048954e1caedb76e3d078028d81a763b1b5e92fc652a14ef24e29c2afe9640115fa4e581f2189304a3e0a8f2c9bb3209fb5b9db42c84a1b06ff64b108b5edf", "SEC": "041f53c2d0ebb942d78b66f88efbf4104297946a8706ee7f64999514c18dbfcd11075fb103a2b16bbb63d5bacdac15c72d100cfb5516886a969816c759cb1a0705", "TP2": "04150bb4d613393d0167130ddbe4fda632f0863d6c41f570394270e2ec91e06fa11ef74bc788dfd1a39589cb4f7e2b3fc9ad9f21cabfcc4eadc42c1c384ddcbbce", "TP1": "040afa952db382d58aafbbb1700b35b5a68f63d2686860ec9d1dd6f715f4ccd806095ff0318495cf220dedf175f692f098deba025e917e54203ebcf0fc3d28b1e3", "CS1": "04182aa66c817557f805d3945e07ff3ac5a281cac16e340d25b167a4f39334cb1f15fc1ce8dd378f838741b73140d36d83865adf2bfbaf8c19feb64bb77437b05c", "CS2": "0409116fa292f1267d39189ab48586d9f9a6f68ee1446d95c349a1948c1c50adf50964ee9a71bbead548eb4bd20a72c73f800f463b85fcfaad78b257ff4e61f8b6", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "040bb0aec13ea2799cdc07d88de6de15232f45f291e5358a92990742ac305fec651d851adf9a7c8977fda9d638dec9be2f4b6e59bfdfddbf879a1dc2068f01a1c5", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0404e8babc6eac97d48604833a3b4e0e1653541022ec1ea0606a732e575b66e33a1c84e5f7f697eb6c5183bf828e0c731ad87d41790276f385a6523753c975c14d", "U": "041036bdfca6d83a7ce6b80eadec39badcce6833cda0c9c8fac634228c2894cf970b05486864e6e6804dfceef9fdb8820c1c510bac5ab93a3d3cf5ec39cdfc21ae", "SERVER_OUTPUT": 0, "Y": "02fad975a9daaa4090d11d92d2921f9bd9540f75a7d8cbabdbcbf98a55ae0a67", "X": "0d7be1bca404d3f61f4d7652ff1b4d84196019f943bd9d2a69ee5ffe3f6ee86b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 258, "UT": "04003480cd1616e69740d4731e4ee7b216f91255961c12a4d8c8da10ad2c3a588f08bb1e21b0fa71fa3116f8b4fb82fd648054d184ccbef4278ba5fafb0126f17e", "MS2": "10287078650c8678d86319e65065e9e196ae81c8b3c7c86832109fb363aae4b0", "MS1": "1c6237b5cfcf9e84c31814ead37cbb7422bcf401ddfb51cf2342dad72409648f", "CLIENT_SECRET": "0413edb37ca1101837655fb53ae4318917b004b52c811bcc0f9d20d6ac00b1f00c0200cfb683ad303d10783dedbf284cd298841d226ed57e69eeb5bbcb23f7c37e"}, {"TimeValue": 1437055598, "SS1": "078b0698d346135a7605b73fdfad54c6a690fac3b6be3e1136007c57cc9b70ac21f66879be7474daf32f3911d90d9a03c9be72b848738c19a56b249c62e58481047d77408dd79bc575fe92a0052fd8958bf345bea833dee6deba8452dce829f61c384053db59e8f1f991df63ee7435e4b0c90319b5d6d5d693dd7de35494596a", "SS2": "024fae47d0d3b14dc4e95d16eea7a27430695e83b4ea48de9c2f41c3f19bca140aa29dd077df10b6be711f560741c10c0e4903fb969c345d06a84cf419974951179bab49f9eaa27a1dcb5f77a4f1aca2dfdbe3c60090c44ba20813ce8739bae307a089f1bd733d05339706bec4e687471dbb24fc8932a876ba5e21e96f060b23", "DATE": 16691, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "1e7d7d70d400bcec5a852a0d4b5cf057f34bcc61ac565fd08779905a4fa658e6056947256140f1067ea42d54064340606936e5892ff4765187871786bc34ebb50710f1b1ddfba671e34288538f4050670fd46b45ae169c2ed7d54cc701da4fa90f7d9e91544a6eb79200d0d3a9d816d43a4710cdcf9d798f244a06c2dac4fcf7", "SEC": "040e9b038f30948323679903ae9f4c289d22c5152dc3e3cf9308979a35af7b20970e7dbb5b39d31d9d15f7b48be1f08657a671a9f4eb62093589ee772cebf72378", "TP2": "040cae2f481c369e2c98d9d19ad40471e5aa1f1f415693f0ad45ae6a1e1f995ff6130b88ecaa03529faa37629087f8b1317c8525b82623fbc5a433e80ea16965d8", "TP1": "0405e051da910d09796e59bb984952907feb8a5238fad024c30a2cea1b4709ad9406a7de29f092b6f51a10e420fd34cd22f5656a2994d9ce5a6c8bd396d90fc5e5", "CS1": "04096f04f850c13bb100e61f0eebc0402eab4b6158c05f76771c2de444ee21adbb04eafe25c31bc8d73ba46c60dc732218b81ff0ffef820127d31df4a6b01dae13", "CS2": "0406e64c0ef5ef5b19648b28d4c80742ab58dd6ba6e88852e35b6d837a3f6c93fd05a5dd25cb5fd57ccc557c17d3aacf09e29ed42a491012f4b5be87121648716b", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "041550933b4da8153508ce39bd88c696bb2c1a0b5f67ba28c1e35377d8f782b3861365a71ed54c8a2589b4905fe327c69b3089b90bed2e91074d64f43ab5186688", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0411ef3ec7874b7e1d4214779442a5ed2cdaecd64c3d8c756b11d5093488ae68e7057468d8c7d657401b48a0af6171dbf12c7b0c5242df36b486fa83bf9152d3b5", "U": "040d64850bdaa8f7578f950803a846eeff2d93a6ad2d7c37df93b61be86e955160168f7e92957ff6b97107b2931df44b81f2ccd456772cbe34a23e6cda5427832a", "SERVER_OUTPUT": 0, "Y": "1ade2d757ff5377395a7360a8466fe2c59c528a91c8594d437d8581704ddfab7", "X": "0c5579627ea81928799a615091494cab9db99b25685b68d44254d0bc77fe8e8e", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 259, "UT": "04210de07ff07079878dcd98f94a7066b4a54c24f80dc02adb4bf0bf518c3523f119e9e9a2b87aaf41dd69fcfd06d16e1cec86a2ae8fa1e1a06acd92b0541f3c73", "MS2": "037a489d4fbc4ee9331d416fde347062e3d738d2033963022e79c940f60dd736", "MS1": "221ae1920fbff9d1887d74cea3e82267871bad4d4c962f9f66f9530bb452d17a", "CLIENT_SECRET": "040a2e38379d06cbec038e2ebc03e11d91fd71d4beefbaadfcb0821df5d39c42f7046dc2ed03a4832177303572e5a98001b6c30c3cb346f20c3caab7d3d5574754"}, {"TimeValue": 1437055598, "SS1": "0fc2ecbd4d390a0ba26119a38a27e936bf04443d32f7152e4fb553be0e3a6ab10be730e4bd5f7e993078cc098f1a90307412b74db5899b32474fe9a6630655e60b9ffd98b560d028b34e5e22ed9011ae552f892c76b73e37a6318fb2180350c91762bcf1d99d404863463fac9b9310ddad1b5cf2abf815db227202ac7f2cdab8", "SS2": "206590b585f37dc40047a511393ed5babbd038f46ad94f6c7cad55532b7577db219a9837245e2506e5bca0b921d8aaf6d9413314de50889b531b96f2572e27cf1659c50107e5e54014bebd27c8c65eba7aeaac5b821631f827bf1963f44b5a6e0d3a95ccd27019b0cf25786cf3eaf1d2b9bdf05296165184a92a8f83ca2012cf", "DATE": 16692, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "1ceffb0a66f72d468ac4312241867bd9c7efc2fca1055a5e0c3c35bd28c9956f1246d0b9d2a06cc3b0840e46ee2c9e3a3026a7cc9c88316092660f8d15da088b1e0904f3dfd9224b95529b214581c36fedc0c320fc2f2e36210fde28be2416340152ee2f21cf06be897db0241cb14463da2b49fa88b3a124f9c01b02f23d629a", "SEC": "040a089a5af5a57f3d1c3b13db3b15ebd313e4d6be44495f6f603aee896b86e3001afecfd4515d2ac7df46a18b9b6caba3f03bbb6696041c82868a87b0b7beff59", "TP2": "0412be541e0ce43be39f2b0aa48a1e99f4c0009e6551686c266dd91cda6240b3751bdb7f896fa23498a1505783cf2e809dfe33cef397abd932586a684341aaa1c3", "TP1": "04097b6ebe8f3c6f6da1073166edfda1d7f6ec330088ee49b9f3f08c4466fa3ee007475b61957557ed3fb82b2d9af7387508f4a5aacabde845ca6b372e2d006ae3", "CS1": "0406ea6162043e62fe47c92b70edc37f3f2d3543624b47af6fd7ec0bf1aff445cf1189b48c9132ee60b705d2727e9b4f311627d91dec3a7ea0f8b1c1e62a42a962", "CS2": "0415c6c184cdaf053f37a36e3f08d7fe536926680e5324bc100527d362059ba519212f79d2038d463aa4edd87158b65318211dc78d8c2e7ff74fd588c90e25b4fe", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "040531a67334eb8c82ac3978978eb7e9105f3aeb00bbc63b9f40b05b01c90014251403d59a4c5b6ea18e9dedc9f9a9a680167edbaedcc759bbf2465d673e7a6938", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0420bc43c32229599578ab572b2fee399eff8bb360f5f0299148d696df81028ca821247a8490832a20e8b533942980c56ea631a1c7d9228b62b20255954bd02868", "U": "040fa70839d185507365e395f2db5f3fd1d6d76c254f9b7a772f4186c7b44333e8135d292598ff6a55ae4e3dadc5bdb8426db9ebb040d3e6d9937e5570003707e0", "SERVER_OUTPUT": 0, "Y": "0b9d7414e755c6ea33e05200bc132d4c29f82ccb94df119d01a5114266da5bc8", "X": "1380a5a6e781cfe80f77ebee04c6ba7e0376fbdd1c02f2e3ece0b64cf41cdee8", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 260, "UT": "040fc148900d6afdf7890bd74549437af39f8fb52e12a656079c441833a1866aa218b6788a500cdf7c370a5128df877303a4d99a26cb723786a1141f1dd8243cf5", "MS2": "0ff960d9dd3ed04cb900c2a86d890a460c09d107ad809b7309b1780d02c08487", "MS1": "0d46dd456c1957420e48b55f87a2d8adbeaa101f7d47523216173209c7e32b1a", "CLIENT_SECRET": "041cb6429aed1775ebb9a81e2f6ace43165551f981ef08a9909cd84f89040b8a3f23335b91a8bf6338a58b116b74afb60734511c90de6160f9484bf93308ee2006"}, {"TimeValue": 1437055598, "SS1": "16bd9c128293bf9495aef7406a52372aa4a7e24c85a2b51a9c93bd2d9cb4c90b1fba4ba190c252ee706c3c016f3ff9abb2789105a56d0e7ce3f7b50473ff37fa0ccce2a57864fc039e6c5ebba6149d861df1c7a20ce4ad915b3b46a3768237fe157f06ab5315be47f1b58a5b6e8da52a7613cdbfea2540a612df622165b46cd2", "SS2": "1d1b93baf686edd0a5d43a23b9b8b2571e44fb34ddfc2360e1b0eb9f4e2c7b011ddf85cfef9c740220140a9f5a98baca1f4045c6e56c9543e9c30fc0650b83e0132c78e06b1810517595d2306bd14f45bf77a13b3128e06415e110f3fd2fc054028335c0916e814d8ebe08f6431258cff527b17246c906054dcb569c6611c888", "DATE": 16693, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "0f7523ec62b7df85cfb08e8c193e1403e740da679c6c16a2c2b44697092d630c0dc3a389be0b83e113ee5f49f4a73ab72f1f08ae3d08527a873da82773205f6111edc6855aa0569d4897e37c7dc16a881c9ec36ba3c3e3f18652bf928be1a97418716a8ce96d7c5c0f904e835d0f6fa50e4d89d7e7a010d7e51867a211f9c136", "SEC": "0410c4736c63d30b24354a4fa27b7a5c9183c146b37c60ecb798c137af554988281c474c0f8a37c46c86c250cfccc272e8e1fcd2e14d36d822bdc1ca1f41293ff2", "TP2": "041210a19ad11f6f2f00eecd904177dbc21b555b67393a577e202ec4a7403d10da2077719570230166a2d15315b0549dfb140d0ff2f2b2fb9ef9d1dd60914ae304", "TP1": "0403be2a0a46787724677bd748ebe0f9a06525e3245c5ce926d6bebc324440b08a18f34a415876bc5d598ec0cff5e4dd845c986b82b1a6d1020e206a46c7577f36", "CS1": "040dc257d1c4eba599bdb162ed85640f9f0f0048f0cf9ce6e5269592b6fb817f4603e1126028b39bc25baed7891e584a2b1d86ab67cdc62279ad2853e2b938e3ad", "CS2": "04034027fdb30db9875866be4deb969084e7a6f937c4345ed3213d5bd7a2d3b732069b9848d63fd4375b726cc21ca544c61a61da94ad8d6c1e4ab5ae4599c5c7ce", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0413977ed86d2c05ce305d2b21198a8f9cfafc93e974c7ff7b1b5d4f791ea4eacd22dd0bfe11dcbd218e0f1d8a288e10e74902f8816e73d93a50b955eb8147ab87", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0404588d58e967bb8be65c533256123bad42b2b234b19b8f10520c3d42d95bda0f01f48cbf58e1a80cb0721bb2694a0962e4235e927337faf06e6699fd5ddc2d40", "U": "0419b69e00466a3da8105fcef29bd2f329860fbe34c0f5daf94398748269afa5990118f6939f79217374f0fc9c75baa8c892b87e6fcf2879b3fb51920cf22aa763", "SERVER_OUTPUT": 0, "Y": "1ee4cf43265e753ef64deb3204e2bad5b4e344c281bcea6240e9428d6ac0d79d", "X": "00491e82bbb4eeaafa154b7760c32382321d534df23c9180e74f27a9e2675749", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 261, "UT": "04163b9dd9e8c72a00eaf22c7a50d8bab9a59f1814fd23c5bde9aaf0db2c4221c01bdbcc7fa5db310dfc70f51555e162b9f3adb7d4760fb40ae6f1dd75f7eea54a", "MS2": "1ecf19b805d39951be58f3013442bb602fdc0dccff761bc3d8f1ccaff3b37f6a", "MS1": "0c8da0ebedac0f8c882efc6e6e9382aacff166b0ac375505708b2ce92329be4e", "CLIENT_SECRET": "0406cef4e32dc9460bd173f360b61c9b2f9e2a875c65d2fd3ed16c7659f2e78ea1170286e744586ce35317f122b7fb8f927afe013deba70d75a081c06e9f7ca4d3"}, {"TimeValue": 1437055598, "SS1": "1d0f377a2129dd18c503474f075f974adae5469c66a1e5c54fa10e97141e294402f0ee81ea22b7dc618fa3a5a347bff68ea44c3e6598529d86bc5d602278a8ba164defe5a3e1708d3e9dac66809135f202b498076c789ffc3b3a26dda23c5dd41bc53b7fd20bd8946c5f1d0e6ea4685961d7ac85400cefda9c85a272b4db99ea", "SS2": "12a4a67c238dc1e600802a7df307c1442ec59530d215ab512ad0b60b40ec71d0148d2840903186e986135b8ffda27d13e03abd34c97a5605c800b7f5f89e728c0e34320d94496cf6c1c2496dae2c36893edda669c2793be95edf294e288a5d280cc1ec22a023909328b90a859ac968844383b03e77f10b78e4f27005f7d0d298", "DATE": 16694, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "01a8c96330180f128bc22f101c703ec4d466133ae081b9d6f006863f65748cfb06783f863c5dcfd4830a19b6015937b169d2b09eff1ed1c11baae4e7758128a50ff59ea90708e3badbe483bcd93087cf4316cba5610eeae925eca3b20a3b5dd91969cdc1832a2dfbfa2a2155c27f20a5d273277984f8e975b08935612d2350fe", "SEC": "0418ac3c8a7e042d3094714b181d554a5adad327269ac829787a4a26d1122116a006d2794c987e269c7116a78adc79c8507b3695d66f618f4e40849b6457e99cd1", "TP2": "0413064b2e82263bb8e2f445b4c7a84067c42050f847bfe0512441206005d56a021fa5ec37cf04204ce59e7aefb6b544faab6aa5220edad262c0d799336362d8d0", "TP1": "04186360c249c38fff72293772d7e9949d716c4c3f2b161a5793bbd10e6224b2aa2338c438a49dd4935b912cfb1ce39cbf2263f0b626c817127c03bd855f925a8f", "CS1": "040eae1c2ce000783ecfb75eddf1e021df985f07cfc7eacee7d54642721252b8d61916a2992e932cf366f4e0dec2141e688ed15d4da9ccf6ba592bd8741a1b9df8", "CS2": "040c8e83074128d4efa922d8fe9acb9064787c5c2d1ef2ddeaaa0b64dbc6e0c39b0e7775a23f794eb5b07374503cbc0b48bbf6fa77f56fd59e2e4f8436d755f756", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0406cc4d487e0f97487d44dfddbad6162df49487590ead32e834d745a81cba00d5047e907f36a763cd05054738a491f598c44052c2fc3d66f7c665961fe781f9b1", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040cca67ed39413243165b85e740721269f97972ba73d5fd640169e964db7768a821045142dc6408d3461dfd58a3a6892bce62006ca784166444c7740043d17374", "U": "04195736a4dee1db2b78932ce0056c477fd481a1618629b7b152135b959b13f0e2053f7246d49f738ff4c946f14d25fd536a3ce4fd05b69a60772dfdaba79e8dbe", "SERVER_OUTPUT": 0, "Y": "06ab3e2d39cb22dc9270df8edcc41ea1939636411c0e445296972f3ebd414dd0", "X": "0c765fbecd68bc3d6160044c7158c90b15d6c102e57cc7a8f28906f45626422a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 262, "UT": "041c386377e2fe4000150793f3e13f946826d99b77ef10428421857fc362e8bc91086e72f9adafff979566c98dd6a90ca2c475e3b56b1320d57d8b92f352088106", "MS2": "06d4c0a5c32c474d7bc6bd5ffbed13f9640161034af3366d1f49d5c85ae2f0f9", "MS1": "0b4c8397328a8ca5ebbb4144c937bcb622dd341e03d7c220128dc87632947a6d", "CLIENT_SECRET": "0406fbc2a1eb2f7ac5b5012ea63a6e272e763ddb3ab9b4f395cfd598ac3c08578519ed713b973544a8a36502e3759261fe0ccff7062ac20297f0d472d252c38c5c"}, {"TimeValue": 1437055598, "SS1": "1ed06b192416f17c979bbe90f3debe040ce631db97d8be6828b1c2a3896ee1730801c01408ccecfe9acf8ab92d6697e65ba949b5e89808a827432e91eb82eef102de3ba1b3023167c0c55604fb31dcc09dde4cb364d1a397df15872e2e21ff181dd152e3a42bbdf5df22a50d7a31fba760dd2a19ed03d0728dc0851f0ddf027c", "SS2": "0981e944356f86a72a6d65fbc215e52a9dcd9bc7c5f22e41e35f636c3d6d513615e6df13c27897c0d58693ffe9771a5542567b6d1601f31172e5739dbb4ce94d22c39e0f6e0d7fcfeee231f2453819ace4a1c53b12ef5646846e922c89e38a4a0e84e09892b76069c58edfff9546b5b2ee99e4453bd4dc027586a49426e0e12a", "DATE": 16695, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "0351efd9d8161a6917e00a2b89fdd3ed221c3c28768894549ced35fe12de879406e3173e737b1e94df899a735a9f3ec043fb50e5a9666b147f877f3a4923db1115c66a64b8f412a5b0f0490c4fbd076e9976f11a85e6149a85a97209f0b6a0ea040f1e2161d151a330b9209812ededb6fa11b57e5021f29039623839e252e73f", "SEC": "040e6da21c618c28663b9207c289b0ff29827242e6c29ec5bc9e63d081109714e31e55dc5bca1c5869642cf640a4019c509827244f8132247384eca254ad55ec69", "TP2": "040013fbe12e6c3d52a40664414daf24761f3db0a6ac41bb0b34747f48edb36d7c0e38b1d830fd99b0a98a064045281789823254f0b74e9fcbbc4294db0d7bf975", "TP1": "04052098dce0fea2b9f52a7d04b5cce077c8e4dd9ff6c88ed1136163ab6f431abb0803c6a75438e0b93d36911841de6ff1fcc90cb6566c7e270c2758c5e882586c", "CS1": "041718ddd80ec140aa7623f1f454a7aa2b78cd908e5d506de0350deb66cdd7940a1c8a96aac7ab9e361fd3ec9f0c3fa8695ac4fc03bcb18b073c834dd8a45d2cbd", "CS2": "041b3b22f4e446fcd4f0de0f255534450ab173f186ecb8f2e1d7dde38f1f56c785141c94517913899913950722818e139cbd1f0d17a2f57cf9f7ca85df1deb0da1", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04102a7b2c43ca6bc02eab39cf1a3358cfc547e1341996d5f9b205ed4d58ee696517025d9a3cc1455d035c40fecb1993822b5b856e1ae1254f7c93b0bcabc554cd", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040ff56030912e29fc796764e2e6f2c0999422166d6442d75f5b49b0ac051e1d5408e5f9f025e0cb23d35f14f4317a7502250126d4ed96d7361eaf21a203cf3a07", "U": "041b5e821d346d8b0a1296116b0defed040ec25cb4ec91ee5622193f50ab689db918d0ea7079048b30c0187638123d31e40983c59158e488e214f4b0cd89ff2fe9", "SERVER_OUTPUT": 0, "Y": "018d5f45b8b31516150bb2352e714e792bf60af829d00aa15bf9acf331a4cd8c", "X": "02cd760245f3bae7b34835dd23c170a293ab93637da4a7a05ab85b27ad8a438b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 263, "UT": "040f700613d4012ac024e3eb6cf00f015d57a4c55116d387f9c1e36a0a4546dc2f13796f0f3f37d1dc6e4d30c6c7d9736bdd5f6ff7c88dabef9fafb9cdbf056ca8", "MS2": "13f4d24e5d5e4bb0279daabdfe69b1fcb61ccab6a4b9de6ca0feb616b38f9c1e", "MS1": "0b0290e167281256fb781133649161cefe51e8ed1b0ffa23756c0c73bd796460", "CLIENT_SECRET": "0416451783e5a052ffa6199e90a931028e7d0aef0986da8fcbeef0e1a9a179570f2174de3f4811655d256ce265a99e7d1cc016d58f229391bea19a285b3f852ef7"}, {"TimeValue": 1437055598, "SS1": "15530eebf435f16dabcab1492bd29a4a3c550f598e6dba6f1a4260c0f93b4a6d23046066265422bb95d0106db0207d5de778bb7208ee68fef6c8520daa59a8f90d6a411e883ebd1f48a0a9ebfca7a1420bfc5a9699b25db759fe8ef581c861320443a45731acc3f886b8f93c1816c5fd1dec6137b22441cfbaac268e817af214", "SS2": "01da9c35cdd3a5c2af06b14b5b15b214415c1555b4ef97385493da79c224a67b10c21ec7f2fb51234fa3828df25ed2122362ef0d174ca92f03472424473b0e5505f938e538a86553746058208dbbd0f7ab2afc3d4bf4833df2b73a0bfd74118800c873599bc5063431b4e0e7ffba3bbddc58a5ba8df9995358d108cc6fb2b697", "DATE": 16696, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "1cebee9ff8846f82ab4d3f1b279908fa952b7156828565f8e73af7fc9c20210722e5e6451e887471f1d358a506539af56a61bed971470d5ba690346a871de2950818676f1af514996467f89651039cbc2cff2971d2a54336b1c2c39a3e97597d1f219f7e229443834ba79f6fa6805102143404378789c942164faabc09086e25", "SEC": "0405e6e686934ba40227345041470a4059916febf015cf53aa9c3eea092b8d700023b2050fd5ad0e629c8b9a6fb193d1b19ed5c2c57de794a30d0fb66167fe5976", "TP2": "04227334198cff5f0640c79e29f096ad5407917235c04a9650bbd23219874fa5ec1ba72612e8449aab7f9547c7823599d780640721666fdad4027ce644474acf1f", "TP1": "0411f9e38515401986a4cd8491307a9f9f5fba318df189f221fb9761eeb993a6a402d8f3ea67031b9507cd42c50b144292d2a775ebde21ac9996d1d89ab6576f7b", "CS1": "0406df056e89afa3129f2f276c658d1b5f6e411d544f3a14c04e63a0bac8abfc5108e7b6870bb7e30401222ad48d7eb294a539cedd77ba006e5a17da268e825f45", "CS2": "0415f27984c7faea6c436934eac2d60cf9d5b46b27dd951cc700cecef77098c0980f4b265c960231721421025a7cc62880c9410bca565da8bc6c8094a9dcacf313", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0412a6cfdb936c409e21e20959e38e4b0b1aa0a66f6b42d6551189867d47d02c900f186f522c5066a72490dd3e6b10a200f1c24e774c6eed2660ffa2a091a353ef", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040a93fa15c48681500ec455ad246926dcf26a90e7440ce2a339ae83ddf746c490187f286c904f46ff6c2482975b64cceb306a42950755bd9690054f675a488db7", "U": "040e1c093af6f80f1328f5ee409d2b0ef1a36b2c2bb73de9bb661d094c3d3149720be9d078feedf9e19bd23d7a1b49460a2f19b71375286ef1d000a2a01ab3fba1", "SERVER_OUTPUT": 0, "Y": "01537ebfdfa1a9fb1297df8fa1dd3efed05e8748418554d9a2a0d69b0a26c200", "X": "186a4370116e156ff78728906d150a7e7501228db85e51e2baac8f5ae7cae388", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 264, "UT": "04054bf7da84f06e339e2ae0d6bc973e6ae0b30b102a3abe6fd749634aee6ad76705216883a6f442ae429cff07d53123ed022625fbd963724c4c3f485785ec0de7", "MS2": "1d08ea84e9f1f4e758ce82e98450a1b501bf16a9d3e505c952c23666f6fd0b38", "MS1": "0c8a078138b7eac25816c7d96e4dcb9277820f2c6cebfee2e34b0e4879546cce", "CLIENT_SECRET": "0417ffbe57acf5c2e90b9e8cfd4e85e9819f45b730fbf56e3a13a863be70a0041a19e0af06030f9678d8bf7d37b8f56f0ac6ddf7accd6436621a7dedffd88a5eea"}, {"TimeValue": 1437055598, "SS1": "1db081b8564fff642a1510392452fc8c1cc156214cebb3498e4a558d1018910119a49c88cac82f7464802c5e207b6618e3b05617bb5da65ff22d498fb57571c20a9c9ef5ef9288a61a2e8c0e957d65aea599bd3bdc6b0d00b162b561a1253d320b87994ad1bd39edf12d3ebea622ccbed7b136d3843f9a33c60f45fb4d69f155", "SS2": "2140c038586022d84713689556b8525b98e4d9f9820fd8458130bb26dd4f8c2c226b565a92f65243500551dbc46fa3ea656d4ec29297fc316013e283430d9f5b0d91867a586e39e07d5f0d4f345dfac15e24efbe5abe7cb0c20e3bfa19acd62202a40eaa1a997252ed1935cfa484dce1ace38ba448f2d32890de5db83aa58b13", "DATE": 16697, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "072412f16aafe74e17697337ea9f19581d3aa477c98e85d4740a5295c284b22a16bab5f464f19973207a62846eca7fb2bb95f2017e9ec6588cd568c07b20c8bb1a062e2caab9600dfd6ed451ab4a207d7c44efc4d4585211a72ec67f0da6caf20b2855618a82161c91425970125478956ddfa2af7b7001d0c9f7ca957eef8793", "SEC": "040a210bec1fa4c0ae6816ea2173ebad7bda8a034ef8f9f519a9b54746cb2af0c412ecc8e672e26299af616d1fcaa209e29e4abef17b5b367ab7a5ab6f9dc69135", "TP2": "040ade8ac992daca6c1f459a07e311784a0e5cb7d9da4490bebcbffaecb8544dc306653aa76bb78981fa5ff36b43ee83c264c15ae1cbc05d4dbdca97c3a30e9a2e", "TP1": "0419c527fe2ef063568f5eb4553dfffc1c813b78c20431262f35ad964cecaab6260aa55121f27d2b182b8ba5c4d42360ff52ae1b44a1715318545a17a85b4c3836", "CS1": "04111aa9b1f024c198adda2b40a178b42089cd879279d7ac320083ffe1a0f2cea10f547d2a6062ff6d8df50a94e51e93231863db25e391902aeb9d1179a2da340f", "CS2": "0419e5e93637398eae0ce4f729f7f804071846bb9b1eefc1323e6521aeff9c14e21fe7bc05abde1294e43eb785e58ec569e66f920e1b8bafab7dca3bbe3de40c0e", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04084259d8b41dd7f12cfc8cd78e6e379ad7f347737fed128ac86a6d111112c42111a0bcce196713a13baf9c537e9e834e4fd10e275b1e45b0464cdb6caacb9f88", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "04070399376f9d1134fc593bf6808afbcaf73990bb0a8c3d7f9a1a09c0bc75eabd0ae3ff8e33e4121376a830ae7e112933097c36b0d90f4d53cbc2a0da943596a3", "U": "041bfc3d6439f75e700eaf4582a9ac8b9eea98612dc38f3f69b3138ff30925bc661882bc85078a689dfda18b6b9fb1d8c77cfe9f45f34edb1040a3f60adcf0a8d9", "SERVER_OUTPUT": 0, "Y": "02a297916924c4a967731d1b7ede586560e414704227b55ee5274966847c572b", "X": "150881a0a011bda9e53824501ddf19f1237d828ba9d29cddd5f1f61f777f4ba3", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 265, "UT": "041b586f5681c231cf0160cc2cc2ab30fbf8c304ec2763434532a943818bec72091d9ad0a4c0764bcc1d0d9fe3c269f9ab178df36da6648d833891bfacb41ef782", "MS2": "117df6b89be72a954aeb4b81a384809ea35c76f54e7b2187d4761a069f87426c", "MS1": "0a74f3131798ec67dfdd8e7708b0bb9dfee0c70e01f5dab991e7d7c397b5efa5", "CLIENT_SECRET": "040ca4ee0763746b1fb35bc9540ec84e3b826b6780a8b3ce091c345dba9208071f135b903fd5ae2ab8fca468d61397358f4ad5ce9521cea90a2bb108771455c7b5"}, {"TimeValue": 1437055598, "SS1": "23da239df785e49d838a40d576a95e602da621109d8f8fe35bcb547467318f4f1d25ed18cbb4a2cf62d6c5aa5f24adfcfe9fe86288644e7ed61faa8e85e0c997005962b95d1ce1717ada32fd157fa68f128384a51b351884ec9e6c979934aeec0e8b1ab50f23e18871e555f280ae22ffc1330d80c23c655be676c1ae9a656415", "SS2": "10b64df8fa65cdc14eafe56baec8ee7f1b62d72156c9313bd63fbffe7e70a94406c58e0bdffab4493c84d0c8a9d7d0e52b40af820e76d3f4216e4330d15aceaa0ba16ca9f5cae16515386d073d2b36023b630a05262ff39eebbc7d58a93b65851816cee2d50a1107c92458a5097c68162b370217fcf13b2794988fba6bf40089", "DATE": 16698, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "01488a75acdba5b21e52f57487abfceb4c8b740a182d3d48ddc978d62696511d1a21f45b6c9d3ddf29d5ec62c8cab1a923b12adc298cb0dee353c8cfecb0ea950a3966962e9d2fea97892223568967bf73bb13f680e860ae7684aef8bffc70a90f703bf54f2361698619c700e04440e1cb2c8e6996e892c885fabe2a521fbf8b", "SEC": "040eb9bc2f0b159c10f4782d311f2379ea2f8b960e59c7968897a708fb46fa1d76051a1dfb3c1beb2598e0c46fc16581d4d0dab584900cb1ef264fcdbe2073574f", "TP2": "0422d3fece24bb10bdae04f3e36b47c062ca0685e9f6d29ec4d0ddcdcc311e9f8f1d3870e817e12eed379901a7cc4a3fd63190e71b5c5a6e9a855550784fc881a2", "TP1": "040a5f1277a4548884963beb89943d37c77fa4de90ac543c3410f1fc1958623175202b7d8b680181d814ad121730ec11d9806077f9d4733cf2a811cfc247d9971c", "CS1": "040f6847d05847c404957519a2fffa72f4f3f40f91db9185110b890e1fb27db28e088deccb73b97a1e99e4f96025327d94814db7326afacb84413447356c5fb2a3", "CS2": "041deabbdb4c8db611503100ec12a8a9d300578e67ff28e41b96b900212dc29b5b0c06d68792e68ba34b8d520f05be45b520042d6626791f5ac0801caf5869911d", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04090fb5e6aa7292c22d78d1d4ea40155bd397353311ea2f6cb3fe34fc275566e3036ae1bb8ff480707f11cc1c9afc2a7644187116cc239d2a0764e54053c98366", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "04033804f5d94828131a50aa5c98c408183f469bfdf50f0fe9bc2f6da25b67df5a0028c3114bddf2a9c7f3022b23521554d85d8d52a052992e1f90d1ed075c12b5", "U": "0414a46401efd6fe8b26bdc01aa5d828b0b4d25dbcb8e0da74705b942db8505151135d7a35ceb1d71daf98fda775a9ce794e049b4d2e93932e6a87cbc6b94dbb91", "SERVER_OUTPUT": 0, "Y": "0af7e62e8890175fc1ac808a34a160cd8a0928e92e7186d797edb87ebe8b29e2", "X": "20b8fabde6542ccae1f76e19497172c7b5d9cc3cf433bb7ded54b457a1555f5c", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 266, "UT": "0405dcf95480b6815d63933d48e073c36b205948f866e2ad20bd9faf9e0628c77a16c58d6fb15f01c03ddccfb670a82fd52f75a63d0018517db03b325de87aaf4c", "MS2": "09eb1e35d89cb3a8e0ce5bd16f69c1968a3401b1acf5dd955ac40259fe5c1632", "MS1": "18906602a4d156d507714fc03735186700e650b40cdb085ce129f698f36128b7", "CLIENT_SECRET": "0403ba1365824efc10c1c71ab80a99f83feb6443a22881c5a2af07886dff7e237b0be49cfd173493a16f852358361e6fd3e5959ab65d68e973feb51d2667fa6b22"}, {"TimeValue": 1437055598, "SS1": "0b24c5b807482673ecd1b5fe554bc163217419074ecc14bf86187a1798dae93b1edf477bd72bc568c9905072d73590acfdc3b6ea68b1e3603b692fe9121795800526de0f10c5eb9a9344f0b66ce0434d30eb881161261060ff3e98a5625003a009bda20a67b3192ea1c5ed50617a205a53c34e4b40b1d2aefdeb62cf7c3d06f5", "SS2": "0b49ba128d56b84a57ff415f69585c5258007d6a31c6046ef9a664ebe78de28207f4659f8a0611796b27a7a7ecc77f3bfb0d905fdc52dffaf3153b76be3dd68e0b1fa58d0302ea77ad0c558072b068129a27b6dab93ac4ad0896f0f117c6b1a80292b687129a4d7400a54de62ede2fd9662db36a28730557215a469da3dc305b", "DATE": 16699, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "21d67b7cc662156ac7babe85e9c15e40d69546ca0c0540b10e8f7f5a162e2ddd11b903f2c758244e0d9279c25d49e8fc6a81d3a4717f02b9d546e6bdcaec31ce1a78d5504ad22e415bf4703c001ed65e871e5499d737c3d57a73cd9980327238012d3e07e3398eaf11f9289b5d417a92ee91486211bedcefd3218b95da7aec8b", "SEC": "041bfe4914a4bd526a2884ddb9022f7208a5ebafdd18b93b4f26579519cd7bdcf5227bec09b7a935a3063dd00f924044b9be426861b1dc08beb490b0ad79eb2a36", "TP2": "041855b61070f7d39d89d32329f0e156a137551b29dc5208d44b0418154393dddc068f4e543c642d6d99fa29a7091f4fc560efb5a85285b2040e6e4c5b6579f426", "TP1": "040da24fdb09c54dbf8364be4690306cbf7a6ff92590897c715aa98c77747ea0e523cb8a0e45b70a4d521d3aeb357fbd9785cbaed53c97546f320cb81e5a830ce8", "CS1": "0413cce03da3a2c54859eff484f0ebec19dfd5fc4cba0477504dd8f645f8816d17072804a7b49e11dbf788f500f2a6cb4ab8230228d663010508b61940c3449c5d", "CS2": "041d17919e2c009bfecf567d84087f913db77b4b50fbdf50ddcdb3d60095284f4e1a9f8a132872eacf07dc60725a028b79194b0538935162fa83a6de6b5002763f", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "040cb3a8ff36ea266179c5e64b7aaf1337c6189103c20f7360d4c988b0f4bb7ea10a2a24d6a15d38e92d450f897664f73a4925c53a02b7c81616111478fb485edc", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "04049769a731566986d6b017738f052d3142d77bc21cfb4e822ea1ccda22d9e7f20f02506d02a0a36b2d655aa357f6f50dc6229b6331ac283ef31b8a835cb1cb1a", "U": "0404eef6aadf8b650ed81d7da2e11579ec77b81049d6df63775b9e8137c5fc0b1721fdf8ecec3458a253bea946cffdd9d1ba9d83a85fb5d990f9aab96aad2b0a61", "SERVER_OUTPUT": 0, "Y": "22f5f284a5f81ffea465956833e36363e87e50e610e32fdf3d5167ebc8cf8462", "X": "10875415c02c32f4479bc3a618d5c12c5c599272eb5306131444eb97ae2ea309", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 267, "UT": "041564c98a945e8729d331669c7ea5ef0940308d1409301181f44337b70e2291e71613080c64ac25eac4712470d710d3105e1c09c84a368122df1d4d9000caac85", "MS2": "174cb9e6df38eb2900db986333ca01809693dadba96c1396749858120f2ab78f", "MS1": "1543c1c27cf14eb88b7009d41e71b30a83b3c4b83805bfde7429697257ab0626", "CLIENT_SECRET": "04028750770c9782a18af97615312229a6256b9d14f36dde9eab0c069ca98531130422c94a79a715ace1b49b38a83a73bccb27c4aa832664b63bded93525fa0117"}, {"TimeValue": 1437055598, "SS1": "0ebd69a58da99d6f37395431da17bd128d6da1272086b26823c33ffa4ece1f790fb1045f969824e44724a2c1b28af3fcf9f7c47ca65e93af130bdfd5c771030804fac99eaa60b0e845424ff961d2381f1730087d33ef093e6d8856c68feaf01313270c265214aac2303bf9fe84e27e892aa7048ec73d888ebfc5a73d93fc8804", "SS2": "12a3c83c26334b5f3859e8d40427e6e618b08fb120414b7db7a089da7dba93e61ed57b0aa5154aa15b40bd1f4c69d5e1e864ef451c3cbbfb3aa0275302ebb02008a3b9878d721e52e0e55d7c3f3cce645745f2334dc7643d414c07b28cc957ae019711fb817a2de79a4180672c35516f0473e81c75d08a9e309ef43dd86c7adc", "DATE": 16700, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "0064fcc7f6df2a53ca79d415463aef8657e2d63d1117d422d411a3dffee0adfc17705d2a88d1248dac253a8a7a50f996e243d05de6e4318d2e6725a1f047b6ad1ae01d18d431b25d77c8e92a92061d59940a795c4bd329e3e8b0eb30f71c896d024d10ba34545a0e6553475bf2e2473219c7cecb54809791234b2d19ea0d712e", "SEC": "0415b262818ced784ce811bf881897be12f09bfdff41a33109db9fc81ead8992c301a76ceadee182cba8c6c2f080df4dda5b15c743fbb2cbddf26c5fc64166714b", "TP2": "0418292de29f18ff1acfe92c4705c28fa67a385869c4d9de134aa407b556e8cf3f1668b279b9294a16ae54e663be3279334f2a426223fca34f6ee277eb64696cd4", "TP1": "04123a63267a5baf13e416e004f80777e0c6d70c4dd65b7f2e3ed9c9f9f74920b61d472e47d68fdbcc0acc45fd09bbb415d195007e69daf1555480701142797a84", "CS1": "0417312954d0d41f5907d62099fffa4f609e30dfc8f36a10dd36e6b4a68356ad1d23aeda1b55d9f50405e0fc83a29534d9c9eb0c87b524accd44c6adc5656dca86", "CS2": "04231d703ca404cd92aca6cc1bb4d45130821210a254c2cd0f9ce0cad8e6bc5a6c17cc5e98d51333660679bed60945722996c763e0b56b99d3bf520f5a1b4224af", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04018d37666f0eb1e77e60c17ed8b3dd6e7b4d6487db006cbf9aa2f3546712b42a1dc791461f7518bcf3c0cd2f5588aaf5fca64d789617aabd8c038254383ffa02", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "04061db5bfda6fa90fea37bf6b186afd2dc5ae477c72f1c4ab87feb5fa997d68fb18b854496d593e1a8a742edc440987757ac476669a76c32001ff684e442cc5bd", "U": "04066c076274fb85370612ba97c27ca899a04b7be8c7bfc2567e565d089d0f69600147bf9cec2a38f3023f8b927dfbfe994d2d5472e917d0b16574e6428cc3eb64", "SERVER_OUTPUT": 0, "Y": "0fe6222fe13268dda629830a2b6de9b75d52f5e84d7464c147968a348c2f5d65", "X": "10b4fbdf6f42cf1fa9ed9bae73f4aad581d9214fb5a23bfb1dd7593286d31003", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 268, "UT": "04094eba6f0d6d3ab0bc6a1d14f6ecb2ee531e3e146e14da6b1a1f3b5c4082b3a222195b44b0a8bac0008fbfed448f52914e913c3b3a29afe074cbac5fcce56529", "MS2": "01b6b0bc4705a7cf63ffc61280cfd84e847ceaac82aaf73ce704120a9647fcf1", "MS1": "06fb33583beb28b68b1438b685d64bc5a7e2610e3d25dd4d3619824f3e92f4fe", "CLIENT_SECRET": "0404585aad83c30d658be2d9e8d1cd5683f689235f19a1cb2c195e7a1b4b43ed8d0c4480f67c006aba0fb248139bc30afd881641e387a76c140c4ba9d9c072f232"}, {"TimeValue": 1437055599, "SS1": "0c419436637fac26066fb4b0b4fbed59ff7cbcd282c87d01f6408556f6674b4105d095246ce76c1d2e9da43790a42e13d2fbfe3ccad22c451d3d077b7237ebd712977959e833ee1e51d8529c8daf112b959a968149274dfa4495e460d05ba7040e9a4650ac6ae309b674ac10990197459d56a6d6bce7cba4d11d5e705ced9faa", "SS2": "0a0b2716502ab2b85ee7ffbc62018c2d80f3737d67db7239a2ca54279f5e596f1a0cf837a2f7740cd64ef7ebb205fc6342acc1fd3c3348b7edb824193e95c1951d3ac91c76a3b46529d6b55cbd12fbd6bbbb9cae4348ac00d67e6f3bbb2692492174abe6e38721403720a0bb5352ac2825d27ee7820b43e4f2e9b09c6db243c3", "DATE": 16701, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "1df08b04a699f92bf2c4c77e6959507d34c465c8633a46a215f5f64b6d87828a1ed66c683e485e101d536208a87985f34fb979e85f5f4f182f416e9cebc36309036b5e2ceaedf843bca55a20fde294a806ef781fb4b5fd41415871566359853309f3982b97eadcd8957d17f9180f60eee837b34d991c7a6bcac59ff95f7232d2", "SEC": "0416f090deb6d7cb2a869e36e3af0a35df32f772dc93883ef21e5252c64982d57f171d26c8bb7a709d785aebaeaf98389bbe5ff742f2ad8d50eccd93554793b1bd", "TP2": "04149683dc9615d0a61ff08808afce6ea73930948dfe3fb6e6e1a984c6493ceb65229c750385f6158c58a2d78d115dd132ca594917efc535b3b510eb31e7222380", "TP1": "04012480ab2cce1cc4029c7b4ff8a1005ecc5113aacc1343ea27a9e0a62dc48cf507b16bf7850f96f5a718017e3fd7f47f9e67bf0628d34b16d05f17d9919acce4", "CS1": "041ddc974bceade1f8bffe7b5a35244916a01c477e51cc6a675c5407d4b24ccfdd1b6c46b1547d0d07ffaf596fc47a2a6e1158dcb43aed4ab1372a8976901f232c", "CS2": "041548420e033d7be3b30230f95fec9276b48af7e28b02f9f54b5cbca730be21440731dffbc723ac3c92806a302fbc9a0fc2a06ef89d03eeb98e213b3c295671e9", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0408941dd0eb47a7e9ce77d70ab334a76a901cebcb81d5d63a845cad6ee176e1c3056ba0b8ae901280947467e4b99d22713c5f86517191c8df3644a8490efbd1ed", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0402b8cfe89b42f74c73a701d6b61d797f0a45d444b40644b7f4542072976f83380e6c04eb69913eb987b284ed8ccabf46f57bb87945d6383a7f4559ce641bd563", "U": "040450665e1c09c79c4f95cebf31e8da0ffd4411e1fc4de1664725d0192aa4b0b51202a87946de916c1ff4797fe963f248ea487dc60da24ce13ba24248e64e783b", "SERVER_OUTPUT": 0, "Y": "1bbbed610703bf40eced499d47a85463a5ff487d9cc3683bad91cde84e0d3b32", "X": "1610401bd44e582877f68402a42d49b31eb00f239982dae997079e41b1d0a8b6", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 269, "UT": "040e133db6299f185f77a6ae3e743fe19354bf91349de91ef7968073879e1b684e189dfb05b888e80110238d16f7787c2f1285eefc552b4c9239095f5157077476", "MS2": "15df438537280e6e68f1ebfecba24f48553493942e6e4975bef5a3744bdf53d1", "MS1": "0f1ce4643ffaea362bb317fadf609c4b41f440d09fd0cbfc70307a6569e4b023", "CLIENT_SECRET": "040c14b139054d06034a892044342eedca1ec96c0527d7d7a0b15568e3e6c453a113d6a52b466096f152c43e523260d05310ee0125619ff6bcdd78bb932c3e4b53"}, {"TimeValue": 1437055599, "SS1": "01847e5c3f809edde2edc0078c8bcd40801ec20f3d67a581f2f4e8c6774545d30287159f1bada0294092e6d6a0deaf17ead9cb4d740b479873b4c9647d259d1c0a7e4706cb011ba48cda3cb5d79596cf2207f737b5eb3afdb5457b05720db2b720c07018c53f23b0adc7e189dfa4c98d9733ac42545735cbc82611941c164b64", "SS2": "0ef101942f049eddbd1b902ca3b58d62041d5c0d8ab325a17d74c6db8eced27c11da115211c678893646a7dd0e3e64c4513fae2f0610ef6b3ecad389162d4a8e21104f6bc7979304d859d338db4c32979bd73a20e91d33f5a9d67eafba943bd71a574ca4b5eb640146de45653e530268c27eef63d58968e064d47d1e707619d2", "DATE": 16702, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "1f92d9ee3c76f099b435758bb39815c19028754433bc541fe11b8759286fd04520f485d89620c22c9ae7d90028e675782b5392af344d0f9405e75f0208d023e515ca6a03676045266527238794570fd8027b9c8c4db767695ab16da94ce1159704826213a66445087857d5803769a7b1dda453aa2a0ef3c836e4e642d5206479", "SEC": "04186565dfc0a75157352710b8ac1e8146e362ee316193778fd71e9bb277f4d7ae16bed9cc89eb3b2283480f8ff7d748f7c47dc983798dff0296c569fe7a280f06", "TP2": "04035b6afe69fde9e695b78b823d238a76555a34061a9118d77c1c7e9637c8930b007268cedc3d66747002c725b06b1a0cd86b340320a05bfe8a2149bfc385e096", "TP1": "0412bcb65df18a2db5c3fb48b5c9d51d8e92b40dfd8e143eb1511d7b524ac57f721d3715adc61af2eeb50f66a0ae549893d82f3d6e105d3cb70d963242fdf92690", "CS1": "04002885a1639b08198c7ce79ced79bc4fabb71cce6944fd60a6d256d40ce3ac5b20d790e6476497880240303470fb17c60c261d7f7668c4596b687cb29bc74b44", "CS2": "0403e6b56e86fe6f622d8dcd9036a6356bd85ce3a2c1cec21b414c1d5ff64184a616ca86f2d76dda6113b82dd514af51d2d7114c13149b42f541e38e745430fd0c", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0413219aca232acbc5eedd46774527f2ee7c8f9d7dea358dcdb693621006cfe9a1195c48afed529d30bcbfa56281fb7b94640bbb9875ac215ef696e6ccc60b45ba", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0402380d2246099c7c4340b911dd3bd5d254955dffc32a3612a53a78e681d0ca4c0bbef0fa3f15b987af963ce9b38b4cb5a9eabaa9369174f770d11e7b542d53f9", "U": "04148ce1cb0d3e309d065c25927b69b82e8be29a1b645033f2e6b2c7c0f34e4cf90e44491c49f079fd6746acb24a4576ba7f7a11f397aa259239386eed1bb2a840", "SERVER_OUTPUT": 0, "Y": "026c684d25d0efc6356a186a20a8deee3bd092303519ce0be0bd22bfd5ad5913", "X": "08b9f82ccd70cdf2eeffeeff0b14d64df53faea51d2d086d9dc864b7f7c8b3a5", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 270, "UT": "0416f7b02bd164d507fd879bd12c0b0e48e5cf26cc113ee70f95b73ea1af0a181113589a8cb38b2742a77b2f488498a07d220332434d384798633d0a25e5c50475", "MS2": "183df1e039803e09fea032f88c4d38614b78aa77b19cc5ebe6e3261103e5f3c3", "MS1": "07b1d3d7d19b4ad49052fbf9338f0ad9b975bf7ae70a5b8515421011b12321f9", "CLIENT_SECRET": "040f79d9f877919e4ebe928f43558fc9b4e48260a21b26b4281ed55c3c211c7eac06dc8abfb939c482d28c2c8a60cb331a7ce45e00174675f32102e2c61bf994be"}, {"TimeValue": 1437055599, "SS1": "19327f44042d22424856dda7f0435f532d617c1f68daefbb516b0588fa81a6f921cfa5ca0cf79652f2b3156a3120e3302333352870f5a2ce68abf256ee61ac410508f6c78055373f78cceec381478483ea9700467a042c907309209bddf5bed61b0eef960e225901c2c48711602dcd899fa8e0c08333b517ee066f80b75ef824", "SS2": "18a0599b3297b97636e8d8199b5e3bc850235eb1ac785df5baefecea19d29b69119970c1ad4c5500bfd5f2041509b762d6baa51ebb4d63fcf2b54205b3355f5005c14e9bb00a7a907bb13f8c61f820e7bb825ea19d875cbc757e00bd22ac13dd151044741cd7b8344e985c2aa19d44dad0091e1cdc8c6f132ac9f90422d3319b", "DATE": 16703, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "11f50e6910faa09e638f4ac3c4850dadf2e9affae2b28c8cf1b7537e6c43eb290622b860f6268c797ac6ed570801c231b8fee0ae01df4818439519a3c9babe2c0feb636d6aa1c07d317ea7a6b077e06424ebd2d3e53f44f7fbcae5f94831a235009b12d0f190a715b1c10070a0b54f17f9fc2ad2527f76b2806c0759c05af704", "SEC": "041620587a3e9b634f6a45bd175c8382a89742ac47948a2ba0cc1bb5f24eb437ca10b50e5c1a0a4f40b1c2314f7377976d2e2221ea66cf0f7f0053bb100aa6cba2", "TP2": "040fa8ab1c515a1762a1582454b02fb3286c95c6bb96e22ed8d953a7419e5ed9d614b8715fc14d47c171f91a42507955702f8a4565fcebc324cd0586315a16186b", "TP1": "040e4e4d608a611ca36c05c9863a34334bd76d780aff12835f09cda76285f8ec0d093af050c1ec13adf9aec4f27a7d1f7a38e6459a6acf28e251391b88770cb201", "CS1": "0415af2affa73b9137cf6b15b7b6b9b62c567a6809a2b255bcbf82c19d850cae7d1dc49ead70b1a943dce17987ad60cdeeca9846ffb9df26000c79046e61e11787", "CS2": "041c66442614397c0921574b01e72d5db31e414fc43b6d37232c77ea55492d20100bd33a5b29ea1051b89aecba11484c2e80aae88c74063fe2469f083794d8c289", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "040026ad4dd753c73a21f7b6c3763b30896a118f79f4ef609c58586b294515501d1ae446441466722c152835776dbedf04bb6279ae055e273852edeb6e24050b1e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "041336d5f9bb4b937471639f7d3187e493617d5e3a6b495bb7e52522a80f5cb2f310a7f73f8d773db5cd39a5d8c9796d41918f49588f0221fea3dc8e00e44d65ae", "U": "040f08096b1b703361d58941bd98184b85cec77701fe535db0ea0dcd775b99ebec2318f4c76106be22fc34775743610f392a6098286105660d9613c68d516b4a5e", "SERVER_OUTPUT": 0, "Y": "00e71b5b9288e123f06a7c75b4c6944cb7235beb942bb3cca9443a23ae254ea2", "X": "0288d534caed66828008f0bb209970d80612c82cc2e2cc4168401cc5fc9a1945", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 271, "UT": "0402a90413ef25d34160485c74df762357d15efce5d64ca6fb98d136d202a4b8e4005c88ca541861b091df2b18bd280235292b3808b05b7190b666c913bb5cdabb", "MS2": "17ca7af9c1b688f8dd66381f89b479326300e7586eb64fd99e441797ad68084d", "MS1": "05c1054876e97b3c29392a264dbf657d63774b71a243652008d22987a64eb67d", "CLIENT_SECRET": "04075fd3e269dec6d19ca9c15aa0596a86197cd58b66b243c90f728d0626e2a1ed20569a3103714ae421c9a988befd637609b05bbfd20f7d1b7419d830ef230cc8"}, {"TimeValue": 1437055599, "SS1": "07799781cd3291ddb7b389409f0930bf4fee5a2f7104afa7711d7389abc67a350a12cee3ea5640ca22d45d11a04544ca75d3c9539293237efb420f9d3abe14961c02e0ba82038349b9af048f67f219e4b26a4cbef7c19ecebfe5ab6df047f835231a8f7695511355e8f003fb5ab7a94fd3121ae952248f3e3aed5df6d2663bce", "SS2": "116b032de446f349ff6cf729bf14f594edceb12d364e5626c3a32c98c510c32a1e7e8ac8a72a1501b3be0a76666ae7c99b5348ed574bdff623397c17a0f8d9d00d25adfed2d5be8cdd15d2c6526c24859e4322534ce8e89e9e3977a1dd02428311e390bfeacd22fb3428470bc36e9b8adb3109ff5ee856068121b47de197ce3b", "DATE": 16704, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "0c59492c5eb38b5f9b4e723b075d8105e8390e77fc7af651895283a41727672e008ecf00de18eb398f90c36af76c41d025c4c3f5e297145962cbb0facf6fffa0196f768bd4c765eaef8f68fa1e83e0a1d99b85a637e60676caf5bdae27597f170005a11f294bfdb958d805d9f3b05c11cd91e38c1871e4c9b0906aea8df22b75", "SEC": "040ca0486df89068c1e26a64d697e570f43c22076da130ccfcd4d00adc3232aabc06abb2bb86c33d307b99b65f0b2256e93a8a087d8b6c63731cd1029df25e4ff3", "TP2": "0406cc18545c69aac58aa883373973ddf290609da14201d2a26b84b63e1c64de911f37404dd024c3860364a80bed4cc985646ac3c48a07a7166dbd2c7a45bc2ca1", "TP1": "0423c39dd52073f64e01691f55c3f0c91985df322efa8531591b8b6f01cee3665f222b5628b7732b22af2edce66736ca7ed1672cba28f18d2a85b9ae5b33d4b31f", "CS1": "040226974fb0e2c4b8a9c37297aeaad50a184c472c829791f5d125e48c6532d1cb2173190ba6b7264744b86becb262de35ea9b381f42fdaa63e85f86bb916ea934", "CS2": "0400f4c354fd190966dd00cfb196cb4da44d5d6089937d0584ae86f63ff86a47e205a46b73b22a20a225af91f04e41ca0c86c50ea0287a0875f99961d6689889f8", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0416e4fcd0ccf9ff75f5ee9c1fcc7a3c734a1da0468ed6628d78d21f6227fd297e14d9cea427ecb139aa766ceb271ce81e435ea4c59bd9bd9e6819d7226280f23c", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0402fcedbc18f273ef0c8ae3d723d1001c5ddd3de41e8b642f4b51e42761e994cf004a4501f119a6c82f33bdbbb4fee4d1f669782b02bfccc2f323c069c40b10b3", "U": "0402e262d31bddc7204f287514f1660400d35abfb3aeb3426403eb4bf2f2e47894058d0828cfa073e28a1347492a6dcf1ce68c62faa06436c066761be38771b078", "SERVER_OUTPUT": 0, "Y": "0c670ee2d115ad404dbb8c9c7d399ac088cd1458df8c998bc9d53d3f4771a4d8", "X": "1c6a14cf90cbba639181185dd47548c9a506a723c818eece373f52dc13a1e9d3", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 272, "UT": "04101f88d9d9416c35611d660a07513a612ee9ab3e0cbac50ba0aece57b17b99e60b769b74075e4d33d161822ac272198298f2f513290847279ff5173e885d0e4e", "MS2": "17682ff8c5fb60e811e2449aadf940aa760a5965933e7306b9c144ce599c31ed", "MS1": "1cab27cc84ac4a8d627cd3a50222366e9685c70a33d574c1042ca059d32dc3db", "CLIENT_SECRET": "040d982fa68b748c84e5e0cd33bf56318665f18ca5ae8c1177e40690398971b7760f4a8b71c8eeffe478c463209c4b4b24aaade96a277b466f46d78efdf9544214"}, {"TimeValue": 1437055599, "SS1": "1522d79f411120ea6943194ab37c03f8590d1f319950d60a4f393f7d4a03b94c21e9163291898312437b7f6418e314a88f517f969158e3e3487e50641716ce9b17d7a1dfe04397b80798bceb76f91f2039a63d064804fb05ccefd3800df0ac581d48482b3a0197e7a7c363289d68ae3ed440046164e64187a80e3a7cce5b3fc0", "SS2": "20f447a6f16f50f8eefbdebbd91d09caf376cf0e05e8ed09b897d2ba8e5804f61ffa57b8fce01f17acc9d7f043d16cb98e81b12cb90672e5c3a65728d697c217114565fc5fece849dc28c640d0dde4a968334053ead919c0c92c2647c0b1598c20bf443e4b24105ab853e7d2f3474566454af02356a936b68c45ef15dd87ce3c", "DATE": 16705, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "137f016693d5e3e165b29d67bb5eff56b996810067815cb2b2845e379ede982a00cee0d5e101724baa59ce9a1525e92e1ecdb742df1645785f70d8874678198b07e5c1c1164921a8d11345a746e5cc74a6becf42efe302c7917688541cc16df605a204ebf90b551c122d0c888b792c9242ec12c4c0ae2c654a8490f6bb987f78", "SEC": "040c68529025e8600a03f0ef54699f2df69deb72b29ef52e8a30aedfc49c6d5be004be9b15cd96f1095903a6b03835bd2a026fbfecc41f2413a36df8ec110d5cf4", "TP2": "040df49ee0c577ab05ee985a11ef6b96896faba7d0e2a447b8d44fd3974a0f8b620eabb0fa24534d4ae9f2bd21cc98a8130ad217f9d13c63a50e1eaad951f159f1", "TP1": "0407b30b563c99fdc78af51caa1ab74de982d0cd1d8c5e868d101aab3f2c794f6806392720202e867184e22a3fc38f4aa057572246faa12d31fc686c174496d897", "CS1": "0413fdf33dab991fbc3f9b20b6e6e8bed9062830b077c1d42371101792c8e70e5222a455548a0e34862be60aa41fb4beaa49ac119912f0a1f454068c352689c5c9", "CS2": "041430cc8972ba838c33d01132f07bec827614445f4db9f8bce08df37ac39c29ef142a1ca121d85be7007f7ad74dfc34ee3cf94b6c39a37e78da7fb4d9f1809ab3", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0423b1f4a3149a4eda89b9950705693a5810e9c235442c14f9bef06f17fd33bc1508c0751ffb67717bd0d232617099b0fb9886b1c5b977652827783ed2e15a7cc6", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "04208cb582df7771a7946470fb3f0707082bcde342dc0b6b53adaf628d4ba724911301a78d0d99bb27e111c2b439f2bf169a9b671587969f91351ace582d22d3ab", "U": "04056d98c1535feea52351d5ca55003102c6676ec84edbf05c07525b037df9292013a3680451aa85bfe719f2a1e1b58c61893cdfd86c6e673981e02dd441a36782", "SERVER_OUTPUT": 0, "Y": "0a63ea62db943e7e56109a191f152680f96e40c292ce2c8a70fc20227ff9e946", "X": "124ee274ca8845bc2047694e6c8cc92c06c4dc2916f4fddcfb60fc82cef115f7", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 273, "UT": "040b25c9299bee07ab6c4fc40d5d3feaa7993339929d718a16a30a9aa94f44461103b10e67f18e475d0ba98fe0229f9899e8fed4ca2e710e587f3e62ba036997dd", "MS2": "156aa4f8aca43383dca9599373dfa94cb225b03ce3af538c682968422800da1e", "MS1": "0d323b71f5f5bc4091a7b0c8374b67530eaab38137206cb154611fd0e2b62478", "CLIENT_SECRET": "04087ce410b883f816e61a5d3cc7ec86962d7a91a11a4f1f61e0aa7f30ebb652281313e0116d6fc9574e72c792c26860ed6222f6b178c6eff1bee2c4d7a69f3be6"}, {"TimeValue": 1437055599, "SS1": "15f974ed20b52cfcbb983169e593bf7266980036009af202fb8c0ed716daf1260e206eed245553c9a8734b6fbe058bdb61b58e6f03cd4f2ab8a1d9094784aa0106e57b5eb72685ea5356c6e6e46161dccb0886398fb2e6a8667bc7c49f04fdd10dcf68bcbed5702d06ac12a392183619b6385550cf491765e59681758f66eb97", "SS2": "00475040235869af9b9513019ac1f8a4627609d69ceb5c69fee561e5c79af25001daff4b7c838fcff9e2bb4132e458d58524ef3ae67f36a2f954cdfa989a985e217dadc5be3160a2be394957c5e3fdf4b838ae8e4cf1bac088ecd0b260864c2c118417de188fbee046dbbdb71d3ed83e0a0eaf8c2b6c0f0d593ba05898f91c08", "DATE": 16706, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "12727862d0e358a5a49f48903ec856b164e74d393a0b7152c525463a59a39b6812cab8da4955f59529f08bc967d5c207f29518c30da41aa46c0b347fcc70888a1d504c671557402e8244a60aa29a64c829193634a6bcf777484005d2acc2c0f50b8bcd01cf8552b17ebab432a7f851c7d6441c33b4238717f85f98948cccabc9", "SEC": "0404ef3a9360b6bdf861c30fe4dab5e0809f5af043ef9675f0782009eea72751be2230b44364da546b8bf404e16d6fd61acb460dec076d48c781452dce7731f78b", "TP2": "04127402b6333e8531ba4a23cdba030e69362ab5b2da69295307c4b39044cd7596193ebd350670492e6552896b71a09ea6810b0a701771087dd0a217380488eddf", "TP1": "04074d957c94b7ea21c5e0bf890ab78ac4dcf919e7c7d73b72c4e5e148d45853101555d8383235fbfec2cbb7fc1a8bdcfe3b931b9071313123a1bd4cad0a616a25", "CS1": "041557ba606434eecfbbc60c8127a92e3d8f6f432d07435a8cd21c0f2ddd2f400b00f2d625137c4be31cba0b6dbb3dc4d2cc249707efeec101118697d8ba5cabc9", "CS2": "04042d27cd0b17bd200a19325356e18ef7d7a2e599a431bdd3b744e463551e87bc1e2297b2568937984ffbe18a0a6711a8c73b136f89c6210221b57b03f0d8e63e", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "041718abba421f5b12e61d7b4a741a140cf2f66f007daad0d89481fde9f70e059a1ed4249615c94ff5fca6b4287b4fad43803cb03137b2f0282c38dd286eb0258d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "041c0af93a53998181d1e966131bb1bae2c2ada017f284bf9dcc3f2ef05275d3ad15158b2aadf458cbc51ba785f0ea1a11f50a54f4214eb9c1e08e4e7bb028e339", "U": "0420b940b8d247b1277c06eb7888b6453ff9d53e19a47412d20b32533ec3280f1721b30fe9e8086d49ad61322c85855b15aee719fd30e641a61b62a95e85272376", "SERVER_OUTPUT": 0, "Y": "0227ca02ab504201c0954680bda4d1f45dd39a38d81a9901c173c9877f2266af", "X": "0decee8c483d57d24cf24ab76a8a93edab5056791bd9a25d05da44defebbdc9f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 274, "UT": "0410558511019b75f95da52515470d9ff3c4533eb30243c184ef2f7284660205c3005d2bcff28a6fbf3f96624e6c4535101496fa9fc2ec042ccf70a35085ae2c7a", "MS2": "13bcc835d4c514cb657cc0f5483c82a1602f2be5992287c908bd05057912d8da", "MS1": "0230cc4837e4f1fa390f825346566319fd41b2fd90690a963f2974fd56ec072b", "CLIENT_SECRET": "04033d4bd5d08e5f0c9e5bebe638e2058258dcfdf891dd159e6945c01f823432db05dd838dcc2b784c8a49fec3d363be5c6428a29085d7782be73464679052139d"}, {"TimeValue": 1437055599, "SS1": "0bbe132aca41537fc1efb63ce9f438aeb8f13bed7e83f2b96a976a56f144b3fa1cab3f7a04f4fb4cdf955a97b78076bab7b905c3acc431d1b45b1e3187e311eb005983c5127bd9b39050c24e3b29380e92dde2987e05cd935f81852131f820f902e18c66a2ae525ad3e74a9cc5bf45398317055830a3051e8cbd3af2e94648b2", "SS2": "18ed8ddb7212d37ce2bc98ec7905f4d0025aea8948d9862afe877f86b2b59a0b1bb236c9a435c9e5833ffbaa714c49b00e7bb7c507a09bdf3162984778d19734074d265df8a7f6eaf9083c09c43999b6e80b22db91840f4f92f50130851e83d2067c74d72f96e8956979cdeaed25aa895b47ba69ec4d406caf28d0e01de8febe", "DATE": 16707, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "0b65d6b93cf31ea7b653b1caa7ebeac038081acfb92048d91e440acd80d89d4d01a0d8a3447e3fd1b52a2978f7ce14905f463518430244a09073156b085068851bb81707aa7014697eee28c3083975f0d5ab75eb826a4f896769846c7bf9572f170c1c6a9647396814436626206c1ebfefaafd011322b16b8a5356a65b0c4840", "SEC": "042295226946cc92c41181dc7753dc32f28fa4a81f8118c6fc2c7a35f3accd57ad1113f203f12aa8d0b4ab73915d2f3d9213f86f6a038479cbbceb5593a37c8374", "TP2": "040837d20adbaaecec37a9ff538a93cc1cdd00173e729e05279239d1e4e70fc442012e42803f29c9418981317a64a2d0a6c4dc8af4b079d3887bd6a3b844e6dd81", "TP1": "0405edf31fcbec97fce62ed982a5baefd1deedfebcab79f0108843df6f50477dfb23c7b5362b78b27780cca76ce654af54ffd9630762584b9fbabef4e548653743", "CS1": "04170801d41bd87be637a46354aaab1dc74d4411c8fad73748420fcd33dab4f37a0c5ad04bef3827fd478a25af57ac43603062fb8a9736fe2c05a1ebc584837988", "CS2": "041727294611cb2e1afb1fbeb249a8b04ea88b2c61bb4a5dc27621d8488cf66434148f005288182e4b28c2b3b9a0f3658607d5dbc73c1606299501e2fce421627d", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0410b625bb4ebd484d1a273006d64aaf5846cd7bd2c0cbbc62e0f21af3fc079a0d0c7e84be97fdf88c9fba450f4344955ba8cec99ca4ab41042e5c84c2b5c5cc88", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "04019eef30a103a693793a661d727ff378e5011bc23dfb94b54e0ec849999bfc0903c052fd41782c22388cea13af4a85838af5c9bef2dd1dfc5f0c5237d3f3f521", "U": "040549326f9a711e447d73631132439810b601526df33e2df73ad2958f1cccaccc1761996a792c821006f92478dbe6f44a5c5a20e79d7f0664a986096b83f8f81a", "SERVER_OUTPUT": 0, "Y": "0852ecdb2791a7e879f58590ee01fbc8639548bd2683f3042b78f21e33e74d24", "X": "0eb11c77c815e420767237e6361cf39f67d432e28e7034750322746f0fc7adc5", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 275, "UT": "0403b6a14df1f89265744e5f62ee66b11ec5b951a1fa50f98af8dc3b590a337acb0a5c28e4c653f5058ed54f0b3932a67ace1321765a4cddc5542f298ef7e25859", "MS2": "203719adc2dd6a5d3011b47adfb27b2cbd6f84c8d5be71bc465f64e14c609acc", "MS1": "10ac6953ac96d86d0258d385924172f2b311d0db5e92120b6e4b2b365e5256c7", "CLIENT_SECRET": "0413ec00084f2e148ba34ea2d73441b5bcc2b034722f016c59d50f807a596276791b6ffb7c7a29f6cc19f4400998e1b8b3e75ccafe27f6a7977003d2372eeebb68"}, {"TimeValue": 1437055599, "SS1": "048d8fd1bbaaff9887f7ea04f3e00e91a06e6c8ae35efd16874d91f2678ac61305dc5cce0cfb65999f62c85944f888c372f89f5534eb21391074fd1e9a6bac8e22995b59cbdf6bc39ecaa34b57f20327609570c71dcf513f88a6b29bb31093381fe5a173b0c6243804afb1e7436466cc3e211ff46253f1b7183c3b7f3d86c66c", "SS2": "19d158323eedb8a431f60e3d914dc6f50cd06d77f2af56cce8e4c83c2450d2830032679f4b11977777f2ebd41c9101a635074a0ca895e8b8b53e7433d5ed74da0c98ba15fe03f3e398c973a5f48dede7222025e7efe8b8024c497dda5002fd7e053e39f499bac374387caf3af1d7177d9f3a5229896565b7a39e8b37183db924", "DATE": 16708, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "02bbc0882a44ca2610a0b1d202036eac20e89e80d4e1b34cf8b62335adc9b97d0ce8672f29e53e6b49c8a12f2e7398dd1ad00b3ba18bad04d1b240e3a02faca405c947c96e1d69c7c6bb6ead9b142f73c628ff7d672a28e86de7a2c7124da54d2217d6f23781a4fe245556a6aec034c98d52c468475b9a6ba310e67b461acabf", "SEC": "04051e25b7780c6aab5d9e941c1220f9ba691c807b7563f8bc85f7fbd937c1e8e60f2534bb7f221869c3cd4c60dda65d32a2493a0c985a48165b4b8a86842bf9ae", "TP2": "0400216263865b6d3102b0f7e8cecffc6e70d2627adac4aec668244b0343eec70d1159bcd4dcc868d726d2e039e0ff5363e01d8e5cca8723fa592246f1ee110640", "TP1": "041eaab429fe02f070c12d05cbacbd8dfc6f5d56da68c21a153f77e1632b5d057f059984402b31e732328c1224003bec0135d3ec63f660652abea3fe8b207ddbc9", "CS1": "040f3014c0f54dd629964ffff34a411dd959d69b269da49ac98cc0d9448c54763604766f6503ebf764aa4962a529e09b86c3f6168fbd80c46394f64e8cb78496e3", "CS2": "041facbb0e077a488d353002e6fe556e591d34c021c374a7735616fd22df9e8a7a10cfabb0f7a1870e773af80eae0dac5d1eff6c8d1ea81ce2becb94fef227d35f", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "040b0975a73d7eb75cb9c5c90d3fe974f66f1e903739bf811584896b6639eb2bd806caec44b7754f2854b89517f595691e70d9d7187a6a0b0e9f6fd617a15138f2", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040c46a02d187296d0c05941fb6cb4ad5a5eb04aa8675ee58ba8c63c9c22bad2151d3c1826905871999b5f01ebf9c7dc421349262d5f69f1ec8be8f20d4b984246", "U": "040f57d9337a078b33a269cb802ea9792f4e8cbd099f20d5eb78916997798b1e2e20edcd4c98cb5b4a5a9778af1f5896e213e837e6fbd3925b307e93dd33e0537b", "SERVER_OUTPUT": 0, "Y": "0fe5c385228d21041e886fcdb6650bd5649084ce204746ca5d4bd7b3b5a53048", "X": "11653fb17262e31cebbd333a9b0b2ea0e27c77a53d4e3b7c89dd2c7c9e716c63", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 276, "UT": "0415f046a880e5a6c3b2ca4b83528c81788970ef9dee1eeb8e9f84c37458a1421c1ff5c4ec988c1cb4a07ca8ca3eb2b76194c9fa4f9b18c89755d77b3f4c1dd755", "MS2": "17f307f43889691cff3814269b78af38cf0ecd3c4afd588156d91beadf1c4694", "MS1": "05cd2774f34f7a5b52aa6f15bcf265d09f6071947684cca146ff7fd3617d062f", "CLIENT_SECRET": "040c7314bc6c1879e534e5ab592683cdaa72130d2bd95b10281f30eabc17649a37130a353d53f0ac530889b1058bd937013d911f743ec70caf1b25e19f12236d7b"}, {"TimeValue": 1437055599, "SS1": "156234dfa0111d95465033e515fa2a5eb51df754e16ab049afbec52ccf2dc6c40af74d13b770ba317cc611cac77d3805ffa6c153f2f30c64d0d860137139b8c022e505022e15d228e1f7d1701d345d7053df6e2462a22fa1b9756a3f0fdf4a6a002737603f5fbb98ad371f9de5a76bc2a39643bdfd1fb513aa567c4cfb3017ea", "SS2": "0a472095e76ae4596de509a4f391bac192ac9043795b0a3ab855e6874151fdd000f91a1b5d9cf0dc5bf0c2d2459453098c36d6cc2ec9c5a79902c9e31a3679b40c19ef131b7d86b5e93c46b3c0df887443140a169280cd7fa541d00d4f0f42750707b4bad4c3d47bfe3478bb62602cfde0046d683e822df679902fffc1c55298", "DATE": 16709, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "115a0c848f998c1f48de9c389db0026b5ebb196f693d5faad943c76d54aa987e12a17ce6de2dc0951340fa454528ca27bb8a13c9925cc57296c636f78a71e8ee1365f62b0a656656d7af33cd4b7b0d5333ec6e73a7ab79e612f3728fd48dba92001ec68b9436f7d63c597cf1900a12ef52431eb246eb3303cdacdfc1f2a43897", "SEC": "041dd7f56386cff7c35a405aade20ff388aafcc06e4878ae3c427ccb2c56443e50008791e9fea8f7a5a785bd18b4bb104f39ab22530abb7734aeca5e5ba61ab8dc", "TP2": "0411140f14e88646659d670c260a8001935fe64119aa5c161f79e40c49ad3c9fd304539a9f5818797bd01810568cdb03bfa32d0d94e9451e2726cb7f16065204a5", "TP1": "0417b113eccb94d87b8eeb8a52b7085e9b246ac0f77822ddc5480070394cf9c14e1a1ff05a5811cf33cc21794d965298da34863c1edc81f95296236a83b54497c9", "CS1": "04066625cbe6e3bfeec65e3c7b237da50ac52e040009f07b8a22651910bc3a30250a58cca19784fc934bc079809c4d00668586de0d9a614eb0e781b7618a900860", "CS2": "04222994260a1be510102dff877f89f1f01b5b1441d29789899f275a2ffd6c62c409020e005878ad0c798f9f0b00d70303268896c187579946f4c46e1a0f18e0a8", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0418c86c2fcc81a719aa5e43f7f2037dcb0c358b5927dedb591b1e122c275cbf511c434260adf04eeda095eae3b4d92d2bdb33e345ddd07c1f56b5083c8cf774de", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "041bc7e2ee2933b6a409ff88f910c3862bd1f00345ba8c40a9d65a81952706279e1ae9b87d8d7c4e5371aefe0e26253524cdc1c7144611f6940bc59ee5417a1785", "U": "040d3aab7010fdcadd5fc58794b7f23dcfbeb8f6ef78275825ec24c261f5f6452301705dae63d07f074ce21d3fc3d3c17039fb4a4f3883090c08de99601bfcc1be", "SERVER_OUTPUT": 0, "Y": "0888f6c94150690fbc23643bfd6c156d7f4a7702b49885b807b82e817b87d8d0", "X": "1ddc57862c68f309a1dac3ea69fb067be75168e72049b17b2fa33e819b285a09", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 277, "UT": "041e0c62382c1b48f64fec740ad7c5dc62335294fdc7a011057ac5d308dcf3064622b62dba0fbef9be29a590b2addc89e0e324ad0fd0f9036814522604d8918f6c", "MS2": "074634e1552f0545537ba5904f40c497e4e33d1ebc32a088fb5c8fedb4e19bbe", "MS1": "1dd273153d1fc22a4a89c8f0af3d55625402ce913ebdb19fa51d1c47f1bfb58c", "CLIENT_SECRET": "0402e1cd060fc0f843b38b47ce6c2db99b20e0232042e9b86f8601162ecc8f187c10b06c5a2672841509e4bd303d2403252bd58a7ff98d01b2459c425f84ba869f"}, {"TimeValue": 1437055599, "SS1": "11e5f77e4e61b217bc5d6099c9af922dd5cdc325ef56e0bd95a1f47021a4321015f9e2b4d526c62557e5c43236d9be5f7a4ac0aadeaf8e80b836a5d13f22b7041a25af8b8ad7189c2cb08c292b3d2bcc77631944ba1b2cceaa15ec4067f91c9921dcf1a0623a360c1d55adba0b9b5cb0a69740935905dea908b92ca6d1d29e1f", "SS2": "097b87a433bf081851df26670f3f0ab38612b01e23e5dfb3968b4fdd9a0fde8923e9110acf1d619c827ace3722f4c372a4c2768664e2dbed6edb299ee037d633129941276454698235eaa8a2c9cf260e1e81f35438bb6489e13462cdf74af09708c4006caef411eb49b9529c49fbf0abe3d11e50be09e2c07b67cdb8ee9597b6", "DATE": 16710, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "15ff2ca1ac8d2b63fa0fc8359e723526b529363aba2303f95bae18368927f4240630423a75f2ab4feba8441b7ab9a074e98610e55d3b3d5f08a155313da9bb08096e158bdd04a587880f346ac89e41166260cd2b38260c443bb227d53194630b141f39186d3c6b29f3c965cf9293dee8fa8fa0ab79c2872c5976a2c52fe2d528", "SEC": "041b033048a166e8d3e6746ce7c9f0d7fb54a6803482b64061aa7ba419b2048760044ad6113613e6a82b63638637a75a72aca2d580f1da2a3734a3dff2737a391a", "TP2": "040aca72c8834ad0781a1c830411c5fbb6875ce5a3427821d25ff7782be581eb3e13766cc85a074948502323166aeb5b13320858409325881360af487419ea93e9", "TP1": "040b5faa0f45735ecc8a6b36de341946e4e3de3c487d5207b8be077f810a4d7f4618ef3f2cb35140697c8ab4d58f9b42e4d44bbb85cfbbebf8f8696bdf247f3d10", "CS1": "040196eaa216433e55f9adee56535730fa986e170252b02f99736f7ad2707b2aa61a411574d83fb5a878b0c45d8d34ece54d8eefb12baf304e1d79185116da4553", "CS2": "040a6c9f9f3a3c3cbc67a422de12c3b2f25ac943249d4deb30b0d709083210a27e138eb0e69d5889431de6ec59bbfc789ac598f4e4f087ca51c0da6b251d657571", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "040e75c997f9cb28a2a39663b00372a0f68b88fd04c8a6c2b7b5e4c15f5d714f4417144d7379765cdb5fbc6b3fbb1b9482d3c388eae225e5e0a7a6caa716738f46", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "04123ea83332920afa883fd5ba9049cbf7bcdcd5fb5b1862d3bbb4480ef350f0d20b77e5ff634be533838561d3a66318f1bb2cf2910b97a157cc1fbc293ff72bef", "U": "0414cffd2490fde16477e23e71e597cb9a5b2f73cc2cc9bf3cd5107830f3f55f540c0226c1fdf13113ae08d1bf8d8002a630d76f2e3458bd083869dc582c1e2caf", "SERVER_OUTPUT": 0, "Y": "0ccd74c3d73521ad7d2025935e49ebc0792e7a48ef63c4c3d11e20a8294965cf", "X": "1736aae7e19a3972268c937753f7847e861a4a87afce6b4076a4dc62e509dc5a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 278, "UT": "041f815dfeadf071a83e57dfeaadfff73b0938e877afbd1498ae8f7576990c98b3232494f88046ba6993f560266eb9ff1be939e97d1ce8d7ab174f925a5ebd1d7b", "MS2": "1061a9ff30327dd55ee20e3b04080897da0cd2e7d58bf31bd41afb6b79e3ba1e", "MS1": "1cfb3326bc84821a1228ec328090e8fd6a58536ed4d020253110d327ce9a5dc2", "CLIENT_SECRET": "0404d4c5029d1976c73f02978a85a670fe315914c09868bf4e713a02d6f832d69118d781532fb1cadbcdbd580d93d57351f76535d818903f492c33bbf3a72dd863"}, {"TimeValue": 1437055599, "SS1": "0061f273c4ee058facf420bfbfd858bcd0ac50c26cb76cae8a1761b66cb7ae79203d3917214562d2b5a45e6f1083a5a3c7573408d647699371e1d8727de9fec32062e28d257c2ba043d4bb92123764cf8c4be25e74f1f179f4759f8f2cda1f26212388cd0aa0f21b768a822e7fd4b4d69e457991a60741213e0f0e09a67beec7", "SS2": "17766a6f5604dbf490bbf92aff202da8dd3e7baa04f81421e00b649ab7bd09f112de9f305b6681d647cef2c4ce608a07d97d5a27a068fe058cde7938f50d7c2413a0f15f71bc7d06e6a115dec2c7ded721762619542f875270b691a107deedb1137274db72ab93f463f429a6b6907f4fe757765b14cb8065cf820c9380be5eb8", "DATE": 16711, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "0b2834e2097d3abb8e85f68f34d6210046790c0fd7b0d01050bb35d39ab0d9061d08b4e27e275eec567859c45c4a5455ee7eccd34fad4a45ae3e9e41d9e0ac5f0f6792b91f6ba26057bf2f1e3c80391d2fde7529a4a5ad706f64194098847dc01b7152ca772703508cf75a1ba6f2fd9bd80e80c1e08b46bbbaeb8a34fe169156", "SEC": "040eb0567d1640093ccdb90f474fb1343fe0b87b0ab8972e5563a955b759760a2a21276e7615267532f5733fc27810c0e228ab8849cb09f3aee9247868a24bda4f", "TP2": "0409bd8fefd1d2a535ff5d7b4a53a64e20a042b66e7be3964ee8f6ab9c591b5a59225870334759fedd56b0a37b1d20d87978f61fda8dadca801194babbe1266e34", "TP1": "0406312c42e5a4f1221b1460b406bcd30fd12b657808ea0e7fbdaab01f6012f2930354117be859abe7c256c8379193b6a2c3fb7422398e90a9672cc58168a65eec", "CS1": "040f0065d77fe6e852949a8bcc5cd21c78f1d83cffbab71b1e6e2fe884c55b388c1369a0ce57ea709edf023e149faca0eb7607b2d04eced3c5291cd948b26f9fc2", "CS2": "041fcb56cfece86ffdb6c4561e1899343cea6539b6ef4c85b2b3edc96df35bda4b0b0064209b593b473514c594081fe15e949a3d9cc99135ff91b36a00ac543284", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0406010fba53e51475846e1e93723323ddb3885a17363d41c5d38fecd2fefe0ba9019fc9d83a093de1eeb4263848f1655aa2a665dac1eac7099085ba491ddb5b8e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040da709bbeaea879321dce098f0e81b1e241270162b2c8c516e4173d410b5a8bf0613ae021c0fecc515eb2c0c9d9a9d579582dd234f2be9286d96c017d5ef47f6", "U": "0406a9d53b07c465e4958e3e190df9036232506e0c42f37da02d6a85c2fb1ae6131bcd270d1e8e8f9dea82f8c8090e408d821bc087767dab83418a69702f6bf61b", "SERVER_OUTPUT": 0, "Y": "052ab0533196f03a8eb5cd2fdadaf08f2526b34e931a9c79de704d7fe7f1f6c5", "X": "209f95cfe82300b5d07f65524a3ecf14d28a3ff3d9899ebdf2fce5c24f14b19e", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 279, "UT": "0402037e5eb62bb3423eb6a938a0cc718d458add0414e53f6eff411bac1eba0c3e0d953114352744f4fadecfe95f5651bb3c1bf6ba0fc294db948f5691e3d90955", "MS2": "0658537383c78a0c1306802559347214327cd52bfd886be208e23db0f510703d", "MS1": "2233802847dbbbab583bf8317d1f50f84d8a6982b4dfe5ffb216c7b959a26c78", "CLIENT_SECRET": "04153107f29ff12b159a4b68c9cf72cac69fa8697040cca3de712231178d5996031edc3e23f5fc8f024917ce7e899bdf9d6036a45e426872ee49aa7b8b11bc80c4"}, {"TimeValue": 1437055599, "SS1": "123afe92e22a9f34456d0e21645abbc74ec064916cbb7342b800b8b2e392f8b401e38915b20f559d1ef3a091f7e1374e726053726029ab9f5b9f650abe454a910c2ac1595357281abc99932cc039ebf23c47f1ef4ce3bdcc4373b28d8ad02b8d0157ea3fb30dbe4491e08e4e6b185fd0f797194be00602b49e0562c4ec54b71c", "SS2": "1af7ea77832aab7a5165c79f7645abb47c8b7722ab6f6fe6b88ec5f2bfeb3c201f56853e0454f249199db6e7cd0aa16992816aef3115ed0e864639c621e5b54222238ac2546332551d33f7b57353e3f69344b671fcdac5adc4e2b595ed273dae059b2d56d1a50fa209d7ab82832dde7089e9d7e536057b6f676cfa32700aa462", "DATE": 16712, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "16b0685d89060749b67acabf17cfb8bf1f7ae085edc4b1b29e67f816e5cb30190d12c78cee182b7ffa6fa747c4e19f0cfe343ec97c982eb0365cd6964b67ff04105b14c7f9445c96a34f7590b6726d786bcfa01afd02d990df0b3267a2f0ed4905bf4fd408d327f6f22351b8d4fe1f99c81d5f1378d20c758b98c9001b6561c8", "SEC": "040a646ccdbabdd99a76fc34553f12b94a2ca1e5a154ee72e16a4879f28736c6c715bf7b33bc96afd6de75b343f83df3d754b533e52d2b53a5a1814099e39ce33c", "TP2": "041636c2d712feed0c8243e87452843a770c25c9c97956faa511728e8d71ba04952223c17b878d5b7d2152b13e64fe9dd7a1dcf873e849985eebc858bc3b4a73c5", "TP1": "04183a89e9c8985c0ddeec3516742209e6b560de373fdd482e955d55135544d1ac136ae5b4fea6f567233d0d3dc58103daa3376b37be7dd38d0e67d78929dbf81c", "CS1": "041c824ec5f0d56c2ba8deec09f51b8e8e0da1940f23f047104c789219db03809611f20a0cb34fcf71830fc3a2f50740dcab6d753881ae86d9c1c72af7082411a6", "CS2": "041478a84d00eb78f046c656d1188efe1f1699f14283a75d4151542500e065528e111071f07d1f9e593cec0339f9361fe2eb10ef9b2aa1b106b8ffbe1aae779da0", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0414fe6f5d04a92b6b4a7e99c00c0109fb5b2fbaf71769f4492786c90aec7d1e2713e3f5de832e70197e25d077ba4b76e49b9bcace2f2f8f5f923418be627a5773", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0417280bba82223d0dfeda9b790f7b1894f3ced0a93870250250cb353db9bfcdeb21a056881ebdedfef4082c9bbe349955b57678d5cf82092025fbec31443a0e8a", "U": "0416c59d3a9c182f9a3414cc228aacc6d1fddbd23008c3fd84e619f2e9897f8d451af72edcd27e7ff27b4c1c6f2f12f1fcf3f366242497aa27342bd38d5b01eeee", "SERVER_OUTPUT": 0, "Y": "1a8be2b14aea4a8f2909b702c9efdfbbedfe49fef7106c1d68e653acb1b49897", "X": "22a4ffe23e103aceada9d9513e7ff6c411e0a61ee726b27aac069654c6ffe41f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 280, "UT": "04198c729d9bbc56b8c4b2c20b89515dd20f21ebbbe8e7f34b9827c8f6d8d0b9b52128ac3545f7c1615a216fdd8ddca096f7c7122d63d0ee380da614c50978980c", "MS2": "1a299fdedd86474145e2af5fe02026db802c33bf18f558306e70ea176b5d810e", "MS1": "1ce4f43c0e72439b550978bd29077822af36521cdf0e56b2eb9056ceb744edf2", "CLIENT_SECRET": "040d645123a4506b8498da84f557e2686033b458787d9de6b82bcd0ab3e9fdd6a81f9fa16cc8f466cd81b7f7e02ecdf8c0101c5013c69352f53b7f659a5ffd18bb"}, {"TimeValue": 1437055599, "SS1": "06d633ef0b985b11e4824d55e77b9554bdd4d238b6315e72073a4fbfdc3d715023f57296a8243f42bb4ea4da8f36561c554414acafa801a5ab81232a9caf1c19063c292f805f9fd69f5f25e8aa162473ba8ca5845137d0da642d02209346a01a20b27731f4ccd1568e3c2c4686d939e8c3f762c04e9967a2a19f276a4e0697c0", "SS2": "0a59701b249d04af9af7365f3329b65638a8620ca52bbcf0d008b9ffc9e4155021034fe613ce0c4e10709e1fbb11610435339daf55ba37a8b5939740318ba4de1bef383197c37d0b1bfa8ab5d5864454cbf41627cfdaef9d102d2099523166e51052e34481cd14ca167bb630b0bd32cbdf26449ef24ea1f3eac6806c0d5b3d94", "DATE": 16713, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "16ccad281474d4a324e6fd99819b067721cc454a683582b9cb64e16da397d6e206424d0a78b046eda20fb71e83afd70da756b53d23c6918c209b83478bcd0683035b54d3b9a50eb0261f46348f56830fb314f20ee291415aaf47bc45e6b4d3851cd7abaa740359deb984956ae3994bd64edacd672859b64e2cbab962473f6ed0", "SEC": "042121a3c51c46b90f7dbf8a501438a3fd8b5b0192c2835012320f947dd81fa10b15c91405e4205d5cfe2f1cb81dd235caaff12018869d28f13eedbcb345c8af46", "TP2": "0416fe2f1674fbf5118c4f8a580db40928bc98eeaf5b5b6d6932e43b1d926a5d910a5ba8400aa3106a76b9d0f29c24edad07fcdb05e32c900d06c0991509384e07", "TP1": "04231313048dc9bea81065fb02f0ddfd3b2e93464d000ec5d6ea3717507f6157620703e84969beac6b871f7f6558592e995c58dde177a4efc2aa1bd5671f0ee8ad", "CS1": "040d6c20365b9ec29e9b6119ccc43d70b427d0ece084cad69bf24dc6af5d1b72c919de65852b0abc18e8e1b895616d57c68ab35f260692f687bf624937be41648f", "CS2": "040100032d198dd05a0268e87fadbf65ab214e5fb0e0b24750dfe2e0361d8e197f1e44d0ce36722aed3d6b85061af82da9ebc26f7b83db809aa48522856ff0fecd", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0408334a677a48e09189af2c37f6612e1400781771a8c03429a9cd7e2ec0055a981edfc5a4120f881890c0c1ff430a2a8e483b71cc106d8b350d72ac93e505eaaa", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "04001fbdffa04ed2e1772ff57f6b287e988d20df072bd0b811f4fa4134d1787cff0e95ee797dcefe7be3d2d84a50f9524fd6592e7858f1347870403c01ab7caa8a", "U": "04019061a5edf17c86b1f323a4f680ae8b6fbd254369fbbf7f388210ccb89561770b440fdc12dcbb9360e2110a733386484c8407eeedb192c01b3fcff0d41818ea", "SERVER_OUTPUT": 0, "Y": "17884bf064aed90147fe8fca6c566e839da39570bab133e464741e3174867734", "X": "22bc61a1f37e58b6b24d676a3814372ded6339f1a6a869659142ced3d827c497", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 281, "UT": "0409f5784cf99b71d1608e175126531dd5c69b3259adb6c1b45f6c6fe6edae673918ca06a4d6b4188a5be731620c845fd6fd1badb7e1b01552e2c848b63af101de", "MS2": "142271ff20828e5f810adb40edbd46572372d97ebd3f748bc07d120873b8382a", "MS1": "02b21f3a8449579a4e93e205a15539cc41f6d36eced7db57a5225373c7a8b586", "CLIENT_SECRET": "040e55491a89fd9192c55e83b8d5f9892cd5e1fe2e41d187fe0f3e96404610ef6010ac18e3302ee55c7f07c5f4731f0b368ad0930e0920354dc95a033d60ac9dab"}, {"TimeValue": 1437055599, "SS1": "1464d36f4308780fd768a52c92f60b5f0e52c404418144a91af25f38577a08d618fc7105ff75401dc16d571e4ea99283e3e06015cf8518ce13480a415759bb67183ce2c70692e911c6deb40076a914690e14dfba25ffdfab9b4751806fb52df81cde9ecb78de79a53f63453bd89f686ec11c711411593856bbf2480f0340820e", "SS2": "1815b3e4651e454d9daa0c9f0fd096cbb75846244c1ec802a485d8b19f901cc50d3adb8007275996f04f4160075e90dd6a7a0f726250ed5544ae70b8c04810670b9dce7e84fc922c5c42b1bea4b47eba85667962277e07a4d7aa35d13f455ce703a70e6756cbc9a5c657203b7353c58f82be0a1a9fa3dfe86bd6fcdcfefe7dd3", "DATE": 16714, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "138c9cf8849ca61b2d7ab0820a648f8427f2efd3ba32973daaa625127aa569db05e62de6c246497fcb04f7015bf7d3deef0b50b11348399292c23c4c562ac77016bb0bf5550ba8fc2c0afe724c8e4beec7d254cb54bdcb904b95f15417bba5b41b91714e6ee6ecb04d564c420abe6319db696c5ae8a0561f241e45f964d1a59d", "SEC": "041a7b79a4668b6fe306871b71016043622ca352c83bb6e9a641e217e1ff3c5ffd09e2bf4e31ea501cd74065fdf45e5b6789a60a434fb4625ef3c0f58f8fec1d75", "TP2": "0403fb6cf956851fcfbded04975b9ea403af8b9c065c382b41090862a6797b5754220f68e343a4a6e76d41dbda14c22024d16f2fda683520c32c80b041bc1ecbfa", "TP1": "04170554704673e436aaeaf89d83eae425b0e730b1a5816c40eb5021e4f8727fed022f13a3b895900a81b1fb263da654d08a5b708e6d396a5c26bac459cad4d8ef", "CS1": "0405bb3705ab446a5fb568ca0c66491425452f0cb1c01bb85b2fc610ff6408d9801e48776a31c0dc274ff2772fa767ff9b873937875082a9029f75cbe48383e8cd", "CS2": "0409eaaa949a48fc846787ac76d94748f557300ac519dc248956ca8bb2bfd99eb501bc482fff8663d7787d5ad79a26378e04b01f486cc8765ec4ff2034da3bd48a", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "040d3645c3096e23adf73a3d1c131dea3d9520e20e8816ded2ff30728c74c67acd1b8623e06719e01b91c598efb0280427c20fdce91e8ad14e14f765ba5da07cc8", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040d08de26b8cebbcfdb4fea31c29d5a8732d0806cc727a7ed1307d13a8e64c105171eb96110bac9c7111ae93eb3a512b7c018493b7cc2ca985077a2464117d95f", "U": "041af31b2aaa35a8aa3ec4dff9d5302e1272555561dd22933c55e79ad0bb1fb68516ab691094312ebd6530b648a1c4ed7b8701b746e2232e0127434f47e6c7f201", "SERVER_OUTPUT": 0, "Y": "03f651fe4446ff1a3f1eaa05d859049d4e164530970ecc8f0d20577ef2378378", "X": "0cbf92be21bf6c3cea3c074f57200d25ef87adad6e11f84d696123b01af75496", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 282, "UT": "040227a4be8adfd4a647d00ca517553f921a347b03152ef6c9f653212800ccd17e0cbd629caa69b871661452f28df898b91ddd7353ad4db46d0c4996359159ed5c", "MS2": "161f028098941ca6f5239de3e569d254755745058e24b8f64e9be4079f7fb4df", "MS1": "0e64804caced3dcf7e1b105b8486f70157c5bec35df7490711930003e95e553c", "CLIENT_SECRET": "041f28bfac353a1b06f50533cbfd39ab7ff2f40ee6b4d46fdc9cff2645a25cf4710c73ff4040e8c1363e2cdf61e9e7cfe2a8861c6584861cf483f03c3fefb9b30c"}, {"TimeValue": 1437055599, "SS1": "1dafb0881644f27d9e798e100ec98a2a69b869eaec93c5e7509d64b4343d421c0ac27f6c90bae355abd7460af0d5c818d63cd2e38d2d7e8df837502b5a7759591d688f2fdf76dfee863f8647a9a5a1dc137f70feab9a37c36ed27dedf359f00b135531a565e99abf3b23bab1120ac1c65e29ad53dd844d86b9ba13d4b87e635f", "SS2": "07aceef537675d2ff8aa640d102b8609f77ee129e2e54096254414220fca1146070086a0e73a7d062224d6c836ed264a46d5d6e272c079c04227ad11b6a9a7e3211739c3490d3658f8c8255603be6388ef9fc47f0f21807336eac5d4bdaafde2044170c0cc72c7621813cc45ad4f37572296adb6fcac2201485097dac8436785", "DATE": 16715, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "0d34b16138148df5099705473e19a28ca27136e80619150b0ea5d488a29ea2a522a610ee4363784c0b4b412742a53430a5384ff771abb8bd732ee10a03698cb608cda0ba2d9bf3d3d40e3497545a3162ecb6e9943143c4aa00ea283c84bb31d22124d44a7427c6303c12fbfca69873aaad918f8dd4e97646ad2f8ca60ab558f6", "SEC": "0422715fe3b4806d0ba8fe557cc9b23c9701192a5a04a0ef001e4967ba1d8e51f2060cf4006374b2d080e53088ffa28c808c5ca1d007078ab1c09d8ee4c977a6f9", "TP2": "041aab2e23374afbb547c69c57e1f7a589e679d26541c4032dd86afd3a4e2819792080e1d86aa4a482c254d63b1ca89ce94ee1adc7411f95f3e12f35d1519b6c44", "TP1": "040d5e1b68e5cb157da89583079c142644c40d5ecca9728c07d2fb8d9a541ec9be14564c64427f31cbacb080be1e4595d92c1d140e099576979b1845bde52b8beb", "CS1": "0409cf45ec67163fe2b6c9d08a2b503eeb436695ffb10c86f713c4abbec8db9b910ac07c9e3a47de4cb8c5322c5e01f1a0e6616e33704d4cf5254b56cb2fead14d", "CS2": "040a7f9ff8039cf6bd80583b2b1bd2a46501a38a1f026d2dff84d9fc44487c0a2816e618b9655004f213f9c91d1e8317c9e8ae719a509a225a8199fd875f5a2634", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "041ef99ed4be63660f1c17823b5b09cb357ee29e3fadbc451a4f7859b29c63554320a56de59902ae12dbd093b418a1aacd556b02654fc40aaef17a5c796cd7b930", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0422ead4474b091e429de91e60200f34986925b2b61460e67968008e1c1251d3220dced08fac2f914691c6a7a7f74fd7fee45d2ff0384e4655638d0dacd8caac11", "U": "0402938e90aac27796bf2882e12aa62cb26487c803699f1b1ec4be02d03e842ae41b6193f5a1150c1ab330b29b629d3ee401ef9e21bc4b4413f7805e6935d2d09d", "SERVER_OUTPUT": 0, "Y": "1f92ab5d79e09234bd2558bcf7619204ff38ec085f6ba70944b3ba1297643517", "X": "1128ad25aa7e00f7786529aa1ffc886f0879bce38b3ddf4936a12fd5dcd6093f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 283, "UT": "04221b89a52313ada647b2e1129b74d433ce8fc876a290af294b708f4774d66282067df4afbe3f8af3ab8ae9d5a08d5a98070ebe40fb25c92a48d67df52833cb6f", "MS2": "0d62b82ebddf8fbb4ace9ed73ed2e259fdfaaf393896417a684472f4efc1839f", "MS1": "00e65c94124a1d578d563c7247dc10a02422d608ef5c90973934f0a20965ee1d", "CLIENT_SECRET": "041a0969dad94e8e5ead108984d050b023b9c1ebaaa29320ecc59d63c47529478912d750af77f971b3311c6ad369d7ba27a747dd51732a6dd22af30e26f0006310"}, {"TimeValue": 1437055599, "SS1": "1af52ea42013efce43deadba22111b155c44eb244701f99dbe477f04c68f920f0f241763b690ff262cf9395aa1195b77355dcb086b0aa6c0dde2d15787386f9c22222bc19f4a9d55a36a383791f212934161d3e17b905dda921629d5f2db47c11f8558b9a1fb07e172aac3aee4b97fb5532aa2c85b78a260a2ee2f1c7fa5d42b", "SS2": "06c9d4074d99a09438f2a85fbc6e4e36dab68ffe27ee9c08e44ca4c61868685c08e3bc849956df604f05f9e121f1b5d9e7907836a83c8b3adc66ec09b34cc88b1ed8f0c3a3c27c3a384dd3be8d4145450a1af878a6571c9a0bd505b6a6cbafc516a21b2ee15d315780943d3bbac6e3f269871ed279547f32074549251edad052", "DATE": 16716, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "0c66d65d844ebdd81e5ed37f4301a92415dd589d2b8ec920c922dca1e617496413bbb525da146a23881b72d8e483511786d706aeeed22ddf25da7619d97231f507d534851936a7bc43229aec2a234a6fb0b87ddc83744229115c4748efbfa27a1e53faf6f1095ccaee6754fdcf5cba0b59d1917c870d0c716d0899db6e428f84", "SEC": "042341d33447648f0602295f544b6e229c1de5ed67ddb38d598c40ffb7bee147cb07dbd5b47a2b8575b5f472d6785d35e5458df8d638e53576ae850dce132a91b9", "TP2": "040d7e69229a4127c15a57573ebf1ffb367996346c2eda0ce5c643887020717e0a1d49a4fb14d4cbd3d090f4a5f17b5d934c8f216b4365cfd10311d0d8d4034e8a", "TP1": "0402b106e0586f7ad3afbdc068294029f2d01a30bd901d95a7ebce803387cdcf412023d0dfbe35b74b7cac7c16fdb53950dc2ffc95a721515db4de1af3870a9f45", "CS1": "040ba36ca369b4637dd45e040c4bfce178d9cc8cc1eaedc335cf2b4f2594ee2cd822c5343d6374451f68e3599d1427bb1eed56aad9969829346082f261b84f35e7", "CS2": "041c814e128d3aef6e1d1b09b4cb9012be8541cf5b743307f47b6bf05733870aed07aa674f160f0d9f91eac7f8594c6d79605fbbf1ec244980ddfd39fc958e8278", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "040f2d715b242ec221a353e5374ecea85e58da1c6d7fd923b1c74d23d706eee5d21aec0582fcc24f728ff41ea5f1a9a2425a160aa73523c7c4370388c88e708a4b", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "041dff13c9bb6d4679903145623a177696a2afa59101db364d437b931d2fe79bbf0f6a4c1c505108f34b8d037c435bcbdd06946eeff29a28de17fa56080a4d6b93", "U": "040e5216ffaec04aa182520aeb5a9c8e79c8da6dea62bba0bd88d8034ecaae9ded05865707be541ef6fc25f18a82e8711e2aafab72591f742621965888761e13c9", "SERVER_OUTPUT": 0, "Y": "156cc772621bc30255114838ff2f8bb5f39ba0169946d154c4c3ccbb772ecb70", "X": "22ec95da2b46800e23921f0f38ee4d39d0a4636e57d9958831623ecf0441573f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 284, "UT": "040ada19138a3d1254bc55aec1325b6f08c9d72cad558dfe02bbdb41cc5a0e00950b6d516d8111570b3fe8ded9aeb35e57f6ed6a0e01ab6a442a2e8ae635e299ad", "MS2": "22d1e68a9c4d118376569315ff1d6f8a53faaf319f3338ebe3eafcae305018aa", "MS1": "0badccad11c7fd0863b4a6eee16f279607e808f28ea80d8190bcf62c435b9f30", "CLIENT_SECRET": "0404a45ba6d574d9bc3854d780f0fabb91edd961a51a1d1127d9d097baa86ddd3d0751820e042ac060a19643a53cd8cf40e3cd63b5969a5fc99e131c35c0891347"}, {"TimeValue": 1437055599, "SS1": "0bf5670a55cb15908c197725f4a73a77c82cd0fb9f719061cbe1cf7b2361ec7211b53f7117155f1e97e043e67ce7618bed697efaaa5cda3831b1b41f699cddc910e69d0e64e1519817622600bfbfc21e5768e0751bcee358e28865b1052e450d1ec0755915d67136aa85d39d7db052b1917310c27e01d575b447033186d14a36", "SS2": "029ee705642d52b66ef77b21192905013e270a37428c9af0d4610f3dcd2d128a070d031b5b633a5cd7df2d88d846e4f78822af5c32f4f05bf10cb71480df43660ce7dabe14663faae3a4c0ca1a879481f60591ab7be44c6a5ca7045b61f07e7b22425d8b2c081ead0b56ce51f539d9a32b3c1e9116890f0f16c96c6f461359e0", "DATE": 16717, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "00f148ce8400f5c71835056080a0b2e67df611301cfce61d4a6eba81487c2cec103dc71d45584999202e3775cbeae60539182c6a3a36c0c0c26b16f043689b731cb555ccb7dd507ef4e1e6c117eec338d9cc54fc97310272c39d0302a0f3573e0780961565fd93385decf340b4f6c40106e2067d70069727c1a48e536bd97086", "SEC": "042355efcbabe0b9a8f8d157f9f28ae0960ed1d860129276cf82927708a926b1740669f743f3259c9f6d27c2737d070b91b8f0d0af7b0ed33d3f94a89bde582343", "TP2": "041316f52f022d4b7f16c7a8570e0b3512425dbb997688ae3b9b0f93a36f19e8d81d277ccfc97ee595e440e7cffe50f1d14318c7e7d7c5ece0c42ef7e6cf4f7db8", "TP1": "04031eb5af1eaf8c6ee4f1179aafc834d7b75979736a7045bd5f738b09cbfba2b3066061799ea43b7f5f0983b674508a12f1d24e6eaab9ab7f394174bd728e5b06", "CS1": "041c358ba88406d8a407aebf39d51276a5ac6478eabaa925be1c112e3bef3237eb117dc6a650d0caf58d022c44ae89a5c889d4a4594d2fae1fca637cb2c944025b", "CS2": "0401b5ae5865a9afbcbb47237c3e92132a0503f2e430097afa8a455510cc43e68b093a460cde9aac627015c5e242c215f9d6b88ab7e780a2ec1e99b684948466fd", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "040c9d42518cbe504e706509854ad50b33f8c004d4cbce6df9bc10964bb735cdc41499a43f37027bcb5f80abedf369a7dbc11886f37148d92340c009c81e6d4fc7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040d678c1fc88752be09f95fb7485201c1550073336495dd0eb146e53fb51e586a06313cc63e36302c3904c0aee29e589fc79b25ceb7ea3830f6e30752b6b790a7", "U": "0405a6919f348824c92634f30317c0e59acaa26e94e7ec539bdd75bb6fe0dfc72e13a8627803c7f37c42b8127306d3bf7495e0f5985f39afdfc8dac0dde9ff8beb", "SERVER_OUTPUT": 0, "Y": "03bdbdb36e90acc8a4473c2d6d7bc2c9eb353bf2e7254657219ffe549de0e4f6", "X": "0f83339d9b1cd9857ca12fa866eacbe6edd5c57738e2ae6fee826ee9d3e3c026", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 285, "UT": "040df739c09778b8836d50fd323cde4a3b020e72d97f5916c3373e107542155c301ac57ea9ecddf012d6e37e7502e80dd0fe6c41080fbf1be99a8f662fb21ced2c", "MS2": "0a590f973122c685c2b429a515e1215ac3c8fddd9976158c44c328c14e58e7a5", "MS1": "107f588ebb83906788f061b740a57d51bbf2f63aa858c647add007ce1355a36e", "CLIENT_SECRET": "0419622f54671738647c50fc3498f82d2a7af496fd79a90b2dd0b52d53c770c4ae19de284a1c496a48c88bddeb7f57f32d063438f5a5bd56adf97495d56fc4dfc3"}, {"TimeValue": 1437055599, "SS1": "1b31b2d80642933a1991317450aaff712b7583fe196b9ad57d70f47801425dcb0385fca30f5e5ff6e861a85007adc1654376301d95fcd13d2431c02ee9f92c611ee6b41e3bb320f08a645815324c7c36bd84680ddef889651299cdbb67cfd65a237a32638ccc2aac9da47f4434b4ccbf49af448cca5c9a5f208a5bf6bde9e703", "SS2": "1a26fe020ec65267c2d2d6cf49e168f0024fe754aaa4a83ee683ae5632ef844b1e707f0d3e2668e8e492c2b5efe15769f7f6b27e4bfc7a0863184d043563a8c721a4db70155d22389b42380a08d449b54636f2c45deb5587601863858248cb89102702336e3d698e1ae1951e258b0913769f0cbe5be33419006e28d6a4947b8c", "DATE": 16718, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "23bd0c04e4bb013331eb149546d910f08ee6ef8bbfd6a228e278be756e083f6e12452e65681ded2b8634046f2c916d802b2508b51b48abfd3ac5575844bdecab130ac7227756b91225bfaa21a9cc0787c192af540a2109176f43afd2204e3ba91df84b49baf4abe742a46b84808fc293c3f9db31dba72be29af590b2accbbfd9", "SEC": "040da330bae3bf6e004403db16c80f8b7c632ef4a3016fcbedd77ef1b03869ab59105ef2dbe57750981d8c49307bb2b51fe029ba37316a36502c60c27353887ee1", "TP2": "041766bf4b5e4d6b9e6f9dd39fbc82ec252ec5322f2793b2f1bf23d282469e7439116411dd6086312c2c32b53e014124071d7c3bf98c276c08606d35cf7b0749da", "TP1": "040d608b6bc90358c0defa7e139572a92f462535f4d2a6b0c48cc8b98573f87f2e04df4c889e193ff4c1580defb93ff525958df141b452936bc4e5b2432cfa3867", "CS1": "0403703518c7463e20be5100982c7b07810c7a9c108c19b8b96f61b3960d6bdb530039b5bb241687777bc050fc64b8ad5dd3a7be5be07d535fca109dbe1b37d524", "CS2": "040ec8016ea02b615007fbf47e0d3e560e953957a8a2bbb05fe6e29d893de2b8471049da9b850feede6d8e3c4ec3ac5c396d203cbfbba8361b625f72f2bfef603a", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0407613fdb62bc5c42fee0236dff7e9519ef9db0548e53679ac298c15cff98ee570bdb4e8f5b95145f783446d0f40fa9bade8130ad8a84aa8a619a238455bc4837", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "04160765f6588e3b15fa35fb2ee5de2729c0a14467b54cc59c5b97bfaeed29288500d061e308ad0a7ca63b30326411b902fb11dd6f1f1b5a5f990a2584423cca60", "U": "04167a10d2456888fdd4f2938b62a5eb2753eeb5ab88f483acdf7bba8b2f7d1c3202b6b132ae1cc2050e09d55de458c97f68ed50643024c8bbb140d37654540034", "SERVER_OUTPUT": 0, "Y": "120bd9ecb811d912aa91295ff333fff93bb843fb96b5d3230081a82acef59f53", "X": "1dcae075674e9babb6805210099a3aba1cddfbbac3747092ea5a08059c8ac1a9", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 286, "UT": "040b40a48a70f03177897109a218ab70894318a86cfa8abab25e932b14abe8fab7218b2e5f1578229377584a32267d5c873accb2b1965afd1152327fc775d14388", "MS2": "16d4be27521cbe1a39974f73f96c92d8df504dfdceb93468f5fd8b99e5603625", "MS1": "0145065bf5b14db0a7bbe253a0fb8e1ccb5358d260ac77b49ce4aedb36c91e9d", "CLIENT_SECRET": "040f44edb931e5540bb0932e1e2a557d0254d524ebc4bb10e333da69a2a00e5659020aebacc357b0979bf797a91c63293f93853d3652dc002fb48308316c5f6992"}, {"TimeValue": 1437055599, "SS1": "12778f2c23ea7ea52a613197c3a8f33a4b4ba4e829102e7ae053baa3832be6d2022ee0a0fb94190e4cf804e54c718a5570854ab5fbe7e5d2fc036a097f122ef818ead5b6ccef9822bd548e3f627c1b559e591e692e68e9109e4223992fa23a170587db9c5260691da6dbf7997c8402c4c18ba0f99e16b657c00d5de38636f515", "SS2": "23a306f61b897989a677d24451da91e976172501a5796c0c602f9069b4363e1e01bf258ea4460e7844e4c6f75458076652cf903b6621d08b59818205eee4e3f602e5ae9751d8a13e067d0ec0e07b959d97ff06b194317ca6ac4fd11adba2bb1415e4584aa8495846f1c209d6a056dac325e5b29e6e8dc4b4cfe5d119a1eea818", "DATE": 16719, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "192893aaf7d46ad49bd4b60432cb2e6df15b374961cd6a359a52afca95412a690cc4161ee16f3255191cab564be229ef098d57dd2e242458e136238b2a97505211a48903c478683736e627f4f214cec33098a5301d81eeacc71a936e35e6be3b0ac6472f466df1360b64c147ad9f141c8d57e46ba1a06c9f45a156f076a411f5", "SEC": "041e48511b25a8b93ec7ed16e5131bd9516c6845202683aa6907e17cad5526ead814bfd03d76617a402eab948ddcdce26c354a98997474c6c0f090db43990e9b03", "TP2": "0404e2f52744a695138e316f7b2e13b66e8a2891e9aaf34c309061f05204954caf05e7c0878483347da201dbe5e11be8b69529bc7ec1ba210a1dc6fda2a9c09726", "TP1": "04088d6b9bb10f507ed073660425303f508cd79a7cbf56d1014785614c3816f84a1c67d88bf04729d7b31ff19bfebe06258a796147d250c4885a634e52e2944ce5", "CS1": "0403b6d02dcefcd2a4370e4addca1542049034a6daf28a684edec312c24d58a8d11a92df9748e63aef89d13bf35cf654985d831da2b20c5a79b4c2aef5675d2b2e", "CS2": "04082732aa6688843c6354027228e8c311021eeb4d0fb1924a8f875343f42305b103a2afb2da97e4368e20e1307852bbe2e4e66c20fb2020fea02b75645300a8a5", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "040b41b95ef7cd5f1793e17af47818ba7218bf0a71b1e31655f80b67f0c2580371006a4360e2ab116253d0e2858cc4524a97fc67d8ff9bdeafc95a3dc4c6ccfbf9", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "041c2bfcee1f374884779d95b766a6514f03637de44795053dbb8ca0247fdb6459098a5d32ba68fc7b5ee082cdc859a937b4cd1576ff57410195165b84ca382e3b", "U": "04201d1a768fb22c849e3fa51cac3fce5db83aa02ca06089f65ba1863b14287cdc004e738c27042cc19655a4e256b7a5ebc6f68682e5a76528d0bbb6c9326a05d9", "SERVER_OUTPUT": 0, "Y": "00375affc82cfd8531703f3c62faf8d41e6d083298bc03d70d82bfd0ad3bc891", "X": "07d9e537f28192e8a533bc65f2c32770393da1d30c4817e390d6ace95ea4cc7d", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 287, "UT": "040ccf71dac08148456c92b854b06eaaf6b5df2e369af7adfae66d2467935ef56a1678351e9a2b8d59e5193874e80b1345389b229be11b98f559487f7ffc4c8de6", "MS2": "173fcb7e36e7e2980b54c82ec3b25cd5fed99d60da2b62203606418fa722a726", "MS1": "0321753f01e14b5dfdce9ad81944b570c592d302870242ea7ed82bcae3619aaa", "CLIENT_SECRET": "040e387e3e5770ebaf558abac62747f9a49d4c3889f2920b6f0e4e4d61e1e15b5811ac72ee96403d3973be5e987693803b1f36a4b095f3ae734f32b94a23cabce9"}, {"TimeValue": 1437055599, "SS1": "046dbe9a034c101b83c20ccbaa0aa6b3248078824f03a33b1cdc76c518e0e5e111ada2181cb557841ec4b0b438551ec0c5426c41b098e3c5fed6e6fb78f08112215756ebd249dbbc8b72e5b42ab285e5738a5dbb5173aa66683da2ee482fbe8a05e50bed54e165d2d3613c2ca875989cba8ff615f4bc4bc3cca9e502e4591d23", "SS2": "1f0cdfb8d7291c45a91fd78d1ec54b2b0fe328e933c2fd9fc1d2fdf593ec5d840e57a4ace831b094f8cfa0b09ef5547b31123fef43e6923261883ec49d5df23b20a6e6ebe52d57bb20c1565e67c7532f6c6218d55396d6ed0df004d7e2831a1207e92947a17f49b98be4df2d25bc5c2c74295b3fae9eb1810e57e0394b3dcdac", "DATE": 16720, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "2384afdd8f0507f1f74b876ef9694fde624bf61423ea6662d6c9b8082300fdff0a25233ac8dcbb4be2db0c8e0577f1707708353bb787e05ca55dfa9fff78acc1022bdd97ce42eb4517fb161469851b5516ea00568f7db6cba501da075c6fbafa0023921ed193444ee4e791ca46861cfeaafba4d423b1f513b44ddab8ebde3aa5", "SEC": "0404a2d2ac07923626c2a098f4e27b6204d996151baca86e10989b93dbc995bcdf04e2b49b498539c125e5abe89325b062eb3db0a2d0d6b7be9a7180fdc2210c3c", "TP2": "041b0a90d0bb57a35bb3a6ab9575be07028ac5f2d30d265c9257243071ab55aaf70b136cdbe54c7e75a2f1bdf24a53ce2b33faa51779c276e8720088f28661118d", "TP1": "04105fa1508b4bf8e5d8a729686a50f3f15b2fa0c2b81116823931a7d2c5091bd0132defaa75681a56a61850c747b77a453c235be6438c0ef00612df64ee829510", "CS1": "0419b39641738c875b1133ea9d4a67ae916fff8c538cd9d4c0c532d2c6f1d511ab1daad988fb1ffbfeffd15fc3bb0fe95934a88c982925d40ebc77160aab44d4ae", "CS2": "041c309ca0d65f079e58963327676f352a4b729a53e978713773a4b89e5f617c9b140e6ffb9e4f736c9946115eaf94fc858f7b158a606d6dc5d032d2cff96c8bc9", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "041d1970ec5b3dfe50eba4034d14db65ac4c428c6fc5cef9bfab4eeffa78025b93201072f07161501e171a08debd2bc6c5308df6cc9d499c183ec1dee8f25b00de", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0404907df24769e0f9d54df022014a4360a1134fb52073fd357e16dc75010456fe049c579a4795685c2aeb3faf024f7109026689eec9c5a7aba2f1de3127009c2a", "U": "041b4a9acc535600cbe935240cf7ca67ef66fb9590a6e3528bb84ec2255e3e4f190599b50c84bf8d5d3889a4865e6b23af6061a3ffcae9027ce7347e9f5b61c60b", "SERVER_OUTPUT": 0, "Y": "1dfcf47666844e411dddfedb2695377bfe7cce13bbd17db6733de2171ada371c", "X": "03bf1cd40f868c2709ead872829276ef1e8cfdf006de3028e62dfed9b3895065", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 288, "UT": "0405e19272bfa2f93aad7f9448feadb88a09a8317bda8a655c168e36b49f3290d819c9c7f917ba8f28b820abc279892293590a719880b33277a415e8f59a707513", "MS2": "00a408576739492af2975e2db2937f191534b36bd41b26d8b519a35574e48017", "MS1": "0da2a87a499ff9662b5d3725581bf1100ec0ce9137a7f8ff4880da151c8050d0", "CLIENT_SECRET": "042096820b2e2f8a4279b23f530cc1f1a10f9c9ef5009ab220293fa55ca26408fb0ce5adb3e435883368f55f4a55ae9bc85c96eada72c21969fb1c1c1d85d5a208"}, {"TimeValue": 1437055599, "SS1": "018c48447ef2f8b495891feed86bd872543af803407a4d6c700cf2931140161e044ef27f474facc608af42d6f0b559b6038f7e6c28469b931eba96fcf140b32d05e581e4ac2b85a307b8cc13079eebca896b7a2112e2918e5ddadda4319fd1df0fd6156bc638ff73672deff14adc41c8309200d7d16fc32416fcb93577110d57", "SS2": "18f0593d8fdcab0244f73ce333f30166897df6f6d37ff29f9dd99d6aa071c86d05430a678df0b02325358cf4d96f341c4f9365a1d7d9639b1b6b66b63876bd641ca69c827a99d3cc372ab243dd3a5081ad1953eb4fb16cb2e4047fde110d294c1b14736aa446597ce1efdf91d887306a66773a0d6cff2ce226d2f3c1806870f7", "DATE": 16721, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "1c958e11ab5d32facb7f62bea075283097a397cd8ea118d23bc260a55508ca2c0d5a9463ff57823a00e402740b363914e19f05fade5754dd8a1c65b331f6dc3a1ea1b9595f9f02177e64da0411cc7167ab09a26ee8d7ebec2febc46cc1138811208f68f5ea8a3a149e17ca1113af95cbc3397992ab35024a20751d05b315ebce", "SEC": "041b9a44c4839048730ec79cf2d724a97f3f481336c5e82ec51e1726a897f11fcf0c5d98b4069ae23c872af3879f3e9699cedbe70485bb4ae32688a8733f5c29a7", "TP2": "0421cf8c46c91165627ed35d8dea422d2c3e1ca7e2bbfe99c4ac925c6e8620443f225061c61b994571dbcd5094304708bcfd5933f90feb5b319aea464f58de926e", "TP1": "0415d251aa413408f81d0b3c569048746daa84f01e01ab9fe4c6c9e0c42c611ac41ec3710c9401f1e7b8da7ed7abeb3f01ce20d5421521d13dd6a2729381bc7c77", "CS1": "0421fa0aac1ad0d2b999edc60c18e3191956c561f89c32d55a6a4a56635bb08e1c09e9169d8f5e2c4311423247e11736c4aa9560072b41dfcc3fda669132d4f608", "CS2": "0414bdc6045bd16aa2ff1d7b9c62c40fff8212fe3d0113b24b3fea7bca2e9aec960d8e63893ea565a147fba83fed71874ebed65925d7fb29d3880948aad5e7e401", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04087926eba9966fa404fcab00d54663c42ab0338c5214a00e07cd2f9fa3bbd57f00d11c9d61270e71aabe353f3a441209149844b76d935da41b28c513cb26f5d3", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0402f069285a8ca697cbae7eb208a0aeb26b26ad6e3a500220d5c977ea35cbe0d60580fc502f43b14474ba181497206da7a13eb4966f086b3e1d2d91f74087f74b", "U": "041beb1bbd629861191ec40d0888c20131ee35a6ee8326f5b7c035fc86e4c41a27079b9a3d1690ca08c767721a7b772f6ae22ca1b8293b0d78b8b7be2944975d3f", "SERVER_OUTPUT": 0, "Y": "11db1d196d566f7d0800e4400fe38d5656866922d546dac6ae16780d339d9b80", "X": "05504cd9965e6bc71f352e2111806b2e9d31088c83240edd5eb4b58f58100350", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 289, "UT": "04147aafeadc535e672b03246a2d2dd9efbf2344ea22d90f140fa70ae495c1061314a8e56f5d3562d8f010d7a245a45e715f6539ebf77d868a94e300f0d446d184", "MS2": "1e0d35617bf5dd5452926de4bc2bb7306201af22ea6d60e07b882030fad3cb0c", "MS1": "1e4390ef9be1fbed4255f5a40f9ddda9e69bb0186e5309793c23416a9725971c", "CLIENT_SECRET": "041d3b2902b898a1e2d6bb4bdc5c47901966e2fb18a161fc1a74f955c4472f60ef06027de53a55257ff5895295db9fb7d408663c824cc7c30fbae6302bac01f2a1"}, {"TimeValue": 1437055599, "SS1": "1800caa31953f77312bf53e4555e412dade63287821c941effa03642679c20211a3309231c3666c7652afe41c72a185ce4b4ce31485e573a50562d44b2c7c0ef19afdd5c985092c539bcc86acb2614ab402c825e55d20b0d45eec2bb2ad291421feb86bf4d4bb64da04a132a96908e1e84a6ac5090d14f096237b1e2e561e6fe", "SS2": "097fcdc42e6d6e1c34a1476f3f452068dc6a04fbaf66db3573c37f0b404525571b7aee8788ebc7e5e3d57c981e520662fb4362542f1c9ec6e57c7a5b7460345005389df6b2e908cfe5e19bbe1d618df20449e9e7099180974c3fba92484033881980f99cb62f87aae6d46757722bee2e79407c4f4746bfeee6a04e2d8586a221", "DATE": 16722, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "0b7b936c05dfe639dd22c920c0c415cac7116940703c6dfabbbcea574c1a427b1146d5c330dabb8d6d6ef6e9da7f17a3eb9ad4a06022c2079dbbcd72ce3ff7760b71f9d4b3488ccc926c7ade84296ece2659dc2fd2aae208e56b16a0a2050f070d71006ee0a57aa79910be6180acbd0aee06f2a09cf5be7b0ee8c6fd109261c0", "SEC": "04186d97fdd565fb1052ccdbfb3d2bd5b987a3870e046eab2dd2f6fcbf5cd28f9c01c92780edfce6fd648ccb9b1ee65ca7652e61020fa4944f149c0a977de4dc17", "TP2": "04143e96b8762486f0ba3edf24efe862318a83865242fdeca4f283e114b1d8b59610d87a724c71d76d773e11fb1cbb4190221dcad81e0e5d0ad6287cd8c63fa950", "TP1": "040ffba6c8e9734a2c53ccd8444bc444884109d3acf5404e95743c2c3e967832d819fb10f378da3260d1b6a4a897cbb38b5cc2f444bf2d72dca035a51c64cd859c", "CS1": "04149a036f38a7ec8050754f8a69753fc720dab9d5e11a850f2852e8e9086e521013a4508c0e619402bd03e9ece054a2d64b30dd46f3c884c1bdf4f3b797b53471", "CS2": "041019bd7d4914522c6be1d12d5ae9983d38503980798cdf97750c3f4243f0f8db1607e63bf0c5a8d500bd780da513a74322929ff6bd1cd371ef4d528e0c8800df", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "041470d6bab35926fd33edb5a2781569e4c2e248b4907cc7a62625b10cf26b647c14881b67772a8c99e2e43003ca6b74cfccbddd504331443815cd4d3c23360139", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "041b8b3baad6b5918cf47cac228c61e33b0a2772a21b8f78aff56549e7f99b9a0200c836b9d9940366f8dc6452fa53b5a9da58e315398c2c1411b62b41ba127c5d", "U": "0411836947fd14b928c3028756575d6c726e91a20e2926973dfdea6124bd801c00098f26e02fbfaea2b6b709a7cdb3f363d7692f74858327c35592b6a0a1e069af", "SERVER_OUTPUT": 0, "Y": "12dde030d7ec11141cf2fee7511b5ef153032276df40cbfe8638f0848e123057", "X": "0b4039d05cefd07973b9c90f41e36ccd5299d1de9d58ffb49ba5a7015738084d", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 290, "UT": "04218e9300dadae0bb5f11275bfc1f008af8af21c22af89f1d2e527b289377d6dc2064a821eb1e99ae3bef6a19e6a9fcfbf23c2f0b9f85a63b5ad23bd033359b9d", "MS2": "1c1d88a35bd5d8dd582ce4304099aa5b7ee9991dff40ae0e16e343d4c6e1dc17", "MS1": "18cdfc7ad7a0b11dbf429dc2e2dcc88f234b5c5825321cd6391784aae84ace6d", "CLIENT_SECRET": "0416444fa37f0cfa2c43cf553c0b80b8a7f6a682d12153de243c5e389aa6d6bf6c1a32862ce0f0458a72f5e5a04a362980d6cb90d78bcea31349e9632d98202136"}, {"TimeValue": 1437055599, "SS1": "06db0f6017447eae3da91131c485c4dee7aac5659ff9fd525e218c64d416784e04167d49437e2d14054627cef9448ea25c9f6ce37960ea3564b016069e367fb00a2dff150129d05d37cba5f714c8ea22b7616d2a5509537f3ca493818212452b0828caf1ca46b733440e5d6910d039da729408c7292882840ab8e6a39ca149e2", "SS2": "0644d4feec0d0908059696c54768addf3444617d147741e998f17f0f20d4358a066a46427c3568f2325d1ba64f1c6d265202fc781916c1b53d2bc73e4b6771f91273541c71d8baa905def50025be6637c9d5c364b71fca30f35efcf02aca245521f80098bdb992936f5eae408f1a7edf2313d62fbd80f8094c130768782a506a", "DATE": 16723, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "15dbaea249f39aaa5843f6a6260d6e5131bcd626f355b94f8053c30749ae6ab2216d88f2007e9b2ef0efbe03dc914e1864e178f03e57e72cd0212570a09c264511848c292f72621044ddacc53b73351c0ee8cc150166bb35c8da4633cdec419b0fce4b9be168d52d6f3f68170b82cad5daf88ef5cf0781e36a4361119600f840", "SEC": "0408ed58be5cd5e6fc73dd89b95fd1dc3812c4bcf1a323e3b2869861e9c7e7ed960dcdabe50e77f241ea1ee3cd9acdf09e1b4274a0b33a4a660af916a3bef3326c", "TP2": "0413e845fd1dc20ac5b3cf82c06cb14e1691ee938d60bdd8f48f4d6511b9f77f0010510fae6c9c8f5d275e4900d05003f58f840eecbef1845ee4f852d9bedf9fb1", "TP1": "0418f49189bc66fd7e99fec1fd910f2322a7e69727d1317cd59bf6e151cf97a6da1d6a54294a274c2b6aa3f5a4d66c662efe03c4af0c4a0723b6f57d8f3d7d6d6e", "CS1": "041f81c135e0ec4ac5b8c2a226736dbad3e38b31313c296ea2d4487df8160d3e10229bbfbb4e5e8daf037dae9fcde6f45a3954c1be1d2e5fd36c528901f59bdd6a", "CS2": "04024639f6bedf6d5901a523ce763c70279db6b06706911d373eee22157012bc010ebbf234a065d992cc5a833e9e67c8cecdb749fd957f4ac16376de3945e4f171", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0407276b2112285832a59d0452a5c1067bd0bf95f84775642fc2479155fd6d7be90ad1587ba290bfd1d872b77f96a9be5b9ed09b867e29821715427531172945bc", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "041545fe0bdcfc435a920bf4482c920cd6928df9b802bfb3d116d06f704dd72cb81c351e1192c7be164dc93672e4bb08afbae03f7324b6842848b59d0c79eb577c", "U": "041e6f088f4a9fde0b782c4b0684b27de336771c7562408c11c2b195f3d73745d402e5819701ebf25ae4ec558506ed7fd057b3e3ebabcf262dddfd8fa874384cb8", "SERVER_OUTPUT": 0, "Y": "183cc7c53b01c7378829c1734a413861c4b4423e09e9a767bd0701299822daa5", "X": "0917139e1b47ef68f965583ea00c801c26b09313e33194bd0b9954a81b50ffa7", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 291, "UT": "04081be7e9adfa0e3662d4d52ce1dbc59362a1df49baafe096e792aadf6d27497716d131cd78cccfe0db7959e2674cb2750faeeeb309e8853d3dc2675193a2293d", "MS2": "14ae20b52e491e609c694153cf668bcb06ff9a198712e5f6ef23dc1404dc0b20", "MS1": "09040e21eab5455dbecedd91e3e5341d4727191ce0be7c9dd80617aa81d97953", "CLIENT_SECRET": "041ffd49e01279d825fa1afeb85a3510b10f388b48389b50c491ecc3649ba1b22003d34190fb10532f4e71d5e526c44942fca2afbeadf53076aa9bf1fa089cf1d1"}, {"TimeValue": 1437055599, "SS1": "1d4bb5aa3d38f7e29d1958a570b7ff0ea2aa4d09ac3c2a0a5c0174da0322fcbf043dabe41ec13f05110c2bc5cda7b60d92978670e349c23a8f8e31ddfa46959015761f61a29f86e1bb5e48a881e7cc46928bd2f0f6df39f661d5e91cf4247b561dd72fe8b373792a9a88e20ffc658e2d7fe8061ee349b716ac1407f654c8fb2a", "SS2": "217365f90a6335b1dcf962629186e7719da00e975ecd5c08dc726f80433912910eae04d4c32949575377491a20296ef841cff8e8ff09a2279449c7a977db5b131e4008332226362dd3153d3b67dc251d85639553ba52319bc28edbaee1c4097a03087f990ecbc26ff179e9f9f8d24df6b788f084232008fdca8a483fe52e9974", "DATE": 16724, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "0399d6a542065d61705d479715189d8b558a0f0e9381cf4429c0ed9f588b8efe0609c8a5114b5320a82cb62c6e447e58a9473873841136c2486f85d67a49f1811614369fe3c4274aba7ccb34fa4f13ee1173e2c33fe3ced4a4d5e3f2a7d56d4c1700318a7cecbabc648d0f0bf24b3ca0bfc63c5691671bc158e6d9fcd78dc96a", "SEC": "040d98d7c2438b77e04a3c85cefba72c8196b15006dd46b6930f93533980bc0a6f02504b2ffbfc921d27042022174e7ebf842a79201b1c854c5ed8047f90bed495", "TP2": "04186b7b6001168886831ee668b6fc4698a86838f97595277d8298a78f890c7f3e1b8321d6f958558007a9a7f7ac332f10a11e5fea40030f8ec953e9c3fe21e169", "TP1": "040eeebd93a7e3946f7724f4e40ee96f67ca93111eb47efc35989d06df1971245f156cb96d1a4aeb5e41318b21c594bb64863d9bf58d84e4771f4e0810be3f041c", "CS1": "041ccf1ef1d1476004644e9ee9ba78a71f49d0a68d6fb06d15218bb67f529005121a68bf6ef0fb9aa87a86141c0d054e8e4da6e40c35a786789c49a0249f688d89", "CS2": "041a934db3626cb9b61fb1314ece327e3d21a4dabcdc2c37f5f572fd463cdf915810d08fded210929b22c34fb4bbc5eb372f58bca6ab39e66654bb9e5a0b2edc33", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "040b552293f15907fb84bd9f220b69523c6d14d141bfecc62489351fe45f6bfcc017fd513674f52530e60812c29039cd46ebbc7339cf2127d6011edb7f360fe6f0", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "04031359dd810041f1a3f3927d11647a09f305d46441005240a494583fbb6a870a0105be1d614fa45234098f3f1a21aacddacf1f4e772863e36589573f24938ea0", "U": "04054bce1c7bcb5367b9f593bbdd845c14185bd234abbc7e9160f63f98834940c419bed3272ffec84f99c4f41fb293a765d3ad7cd28cffc9f7ada11ff39710a92f", "SERVER_OUTPUT": 0, "Y": "023a9e62c815440efb738440b3051c719ac9028b950946062957ef2498be807a", "X": "2305cf7ae544e2fb9d4383fc15f11fce03272010e8424228cb01766b21392781", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 292, "UT": "041a686d4ef486357b143d14123783ca92b8aa0dac6cc7c9a57238476b3519a1c2230fd8f77b32ec714c11fd99b0f5e7545b91b129b5443a8d8d9047e77346767c", "MS2": "15eb8fb5d5141ca975310dd576787ec734dd5c860891d5bf3c390e7cebcbadba", "MS1": "0c9155c2d74797a89fb901d923ba1205b08510e59facaba3bbe6e212b54a8508", "CLIENT_SECRET": "041e7b324914259ba2dad7eaae72ea9fb7ec352e1f7b69a159e391f827ed4536ca0dd6fbbce3345fda06962cdf03324cc1c46ffc5ce8b46f54f1bc3c198553053c"}, {"TimeValue": 1437055599, "SS1": "0c47367ae1afc8ea5e1118e2cc151da7692634bce4079e3c1ca936324ec068570c10b135871b5a2260f9697fa1196a8593df11d9be41a5acd21f0f99d61637f418c32055d54d66de546e3a6db5c0320a74a182f785b98b52294462746c546e9c08e519a996c9980ed812d030841efeaed09a681b8dbf45b8bf45bee9eb8f8232", "SS2": "093c78d7eccfc1eebcd36e4c7ce42047445666bd88dceb1ee91a1584a4c2094b05cbbbfd7aa872cfade33da96275aac1a09e2c7e1a0d97b2f2d6416368c1258e0cc1ee8b92e2b60fc201ba8e56ee357969f449b5d73df4e22b4b4db3fc2f23ab07ec030e59420c427c5418655173ea6ca05f5f8500f28e64b1c3345132a19640", "DATE": 16725, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "15ba9c72ab7e82fadfcc3a5f0cec91997f3572e5cdf5b52de4779954da65a61023074fd29cd2917c230d9d00e2ff098aaed5463dc9ab0e307ab9cb0bebdd2e4a06f3ca8e8dda3981c49084b67dd8f827f751496792b680a12729bfa2c564dffa14ebd49d1a7384902964812771dea8e421902766c005901fd03bd68e1fd64a5c", "SEC": "040f8cec49ff67a1ff6a896f7a1b3913ee6226b7c43d17a7f11c7e95a628e9fb0f1a05e84f9cd7a50c5b16bda6019c7f1d8dc05995be1d7d6994390cb78acc4654", "TP2": "0400606c7add82e6f8e2d20d247f656a3445423d50496eae4eb071c2ae48cd4a4d0383da275087d833a6da525d12765b68d92747985ca3e493edd289fd412d5d41", "TP1": "0416085e0df25fabcff2a0adfc2c73362c8917734ea4c7663310db7bc384c4183c0c4697456f19bb3962930a7005651fbb446aeb3ca7cb0cb3f12c46e57d17a376", "CS1": "04022db81060608f14dcf5d39a7fdf8e2d9b9c7141f1dd3b618b5bd7ec3d34f0671a6136195d453e78542ebff9651d702cef1b789cb0eef5ddf75fde0bb3296b39", "CS2": "0406f21efa5608a4e5a61ca20e1ee3f103b8fe7c49df39e41eccdbaa891a6e41ac1ef895c65e7268b46600b7c44bb5ab1a3ae63c640c5bbb28abcf9726f3b9f9e5", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "040f21083e8510041ca6a05fbe0ecf1cd1c62c0e1d7a7adf200e2ea17f64a4d7f60c009c2ee788fe3858a3307dcfa31c724e845089def34a671dbec638f8a389ec", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0411dcde2676cbd5fb8f54a53419b2299f72c2542487811c3cab8ccab22625c68f1cce11c1c340171093aecabcecf7c8d6d09927155f97a8f14c6c0cfc58b2ac77", "U": "04006eb8cf84307fce4ed7afd93b2050fb278172a65e44bc745c65849215a4b0fd07e6e263fd47d700405a61c3c131db33a76039d091c57ea854e04853f4b1c4cf", "SERVER_OUTPUT": 0, "Y": "0b481c6a95061c8dced68d3a85e2cca3b59fb742b88315fe80801d2c0d7a3ba8", "X": "22e3dcc96b6df9a5cc1fd090d1ba976350797c4bf2719079c2a5c5aeee4a23d8", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 293, "UT": "04204fa38848662d3277fa35335cbd65207287abc9356869574de56cbfff9934b70415ef6bbbf4159081f84376d93622de1e691d79524c76473b641eb4ac72dac3", "MS2": "22e6c37031e4bc13023675b17a2879c4c464e883797ad1f699e41590450ce994", "MS1": "12fb3c742bacfad537c7950ab5c236c8a6b7128d78a23e261b9184fa1a324437", "CLIENT_SECRET": "04169bedf02d2feef6769928ca7f17d2beba609066d86404369a870520ef4ee5801fb741a2227778c6e2112b6b78eb7906ca163aa3b61a48f3f0ae4480edfa94ec"}, {"TimeValue": 1437055599, "SS1": "0d0f48f6fd8cd0631d53272770048eb9c32e6261a3f2845d7bbf0e2368f786c7115e59d2c95e2186a467236da93b903489647c931dcb9c280743bc7b93496762106ae0cd8febaa0e39d1b24d21fc2e5f4393a23e514f4bbe487824ee27a76e6915e8b30c3a012cf2891b880aafeb2d6ac9974657bc76aa57d5617be27680934d", "SS2": "20a20bf7f7eda923a5b05cb3ccdf58777143466f451416e841e2dfb6b2f223ca0d81098bab66de58620c01597cc3b415c346975e636d5653772d591b0cc824da01182d9d965d3f0bc9f2bfa4db8824c080a5da3664f5fa0fa6ebdee55fd6915c0482ab97e29ade48b3e78f45e088b4f244d0857e2dabe00ca88309f29f689f00", "DATE": 16726, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "1550debcde21e86e2fead6040fc85783bbf537f7983f4f18cbd4c184644540fd104c4ff528ce7b64da23651acbb4c32fea5a3188c317bdf61ad002d1b99f3f871922a253196f28f99d0b6ff900499c58763bea3215f181e35b865eb8e650a8ba203e9fb3a8411b979c5f82a4a6abf4816dd582e49e5806a7ce8999af4899cd9f", "SEC": "04024bde19424220160073e952b6d5e34d2a6ea459b37efd03af6448fef135f51b039c5382813f9df6bc0a11225b4334fc7b5ad1c59087056f316e271c7b43a7dc", "TP2": "042094522e057fa8cf8ac3dd46f4cb1305b97a3d0c9b6958069dd90aba01da43a70df848db2442ade21be0d39fe79df7a7c3ba1bdf4ff7f1b5af7e9629ce9344af", "TP1": "040e711658ffc69a8efac36bd2411bc4d5af6df5eb6ee5e4dda308af1c2eaee07d0c35ae6d00fd91d093c51f77856e06cd91cef7fb12b27347b3ce133efd81ef6d", "CS1": "041bcd1d4573faf347aab7ef03e39f23e95a558f90ef414c48eb1ca1bda011f55305e02f9e5c6d31c709fbf2086062fc08de45a506ba06a4f62ed4eef9972388b4", "CS2": "040dcee2f6cf16a7a942a98eab074e9ead0dffc3b1472c8a23a1b9e06ab3162fda10f2b516f8e5f43e8c448cace02014e26830d31891ef13424afab6cc2b41b441", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04027c50fc28febc2d5a05a07a13d2324ad6ef36ca4056f7ca5d25b5575fd1059a0071c0a2722f813fd8cf861d5f540cac8b5148e42af3363e5d3f2629005c778a", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "04179f161d7d8217208d2042575b39365265dd12a1caeaedd6a71f7130938257d01cc84b1427fe6d661e8cf5499b653ce284ebd1e7a9215bd2fd2ad048f61ed50e", "U": "0405b5117f41fa50ab2c5a2e0c1d3195e5db4ca25d2dd745ddd9c528db7d4b177901edb33a1a6a57c1d437f8598652b888a084af000c01e97e127a77151530a4fd", "SERVER_OUTPUT": 0, "Y": "0a7fb8e7fb2e3428b39078497ca32837134dbf110df42a75e03cccc6046480ec", "X": "0b24f7ea3d6c7167bbe8df0ab436f36a8d9bd797651487fe6e953896b406fb5d", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 294, "UT": "04177c739343e7bac779527de41b0eb82f7862b9bf5f3225c715f5a288247ed5ae23127e11df83a896ca2bad63035ed818fa3f5830e263f076b828dd3dd6b5a169", "MS2": "0a17b1f1230d4acbc213b8eb9586116cf03753c6d49c2da45288a433e0bac306", "MS1": "201bec6edcbbea75ef394f9d090a99ab44c8ede3cbd01a6bc83b5b65f146dcd4", "CLIENT_SECRET": "041bc800b6f2a0ad0e0ce9d9f5a1770797a335c601e8d38873ef38fdf4ce8ddae000694ca074cef5045c89ede665d048cffe1c91e205e7b3439674fb152e32948a"}, {"TimeValue": 1437055599, "SS1": "0edcf5fe6281fe6543510e3bf746028f9e4ce1b57f2e8bc4fc53fd016901cb4f15439c51f55c8438dc74763c12a1ffd0cdf683b0d49b5359bd65bce45e7a28ab167e2e6ac45578e1f31e62d881feed38d3ef48f4b5d455c566e549036d9178511f7dc6bdc485ca907f447bb5f340abe9245aef2a0a89e29c6eef7097ff69e229", "SS2": "0bc9cacddeddac2f29fe07127b2411705d82512e531553c8916c5baa17339ca40acb7454f850f079caca97c543ce1c6c06f709173bd43e2a24531b80f006f4971dc13b1ffc03c55d640e0d64fa0b8416e097959e6687acec9bce68f6c0836fdd1831145aaf2d13a459db80a1ee6c01e284a101f6d65ba119fbe8c557d60869cf", "DATE": 16727, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "022c2ec34704ce35138adc3976e9bdf3d6f77376fbacc85c34694a546229108b11a02b2a57daa46a05103dfedc26697b6fca221cfac7b8834239f8689bce29d6025fcda0c0d972fcfee56c932e6f8bfd3584b7d985cc7402a5326d16f20c955a0f4e5a01629c5ea9fa9ea14858accb3b1fd776c9761daf88538f6cd36b177973", "SEC": "04038da2fb04c55ddcc5d60ce7d48d03586c882402fd97f5ed2d27c31d965cdaf20eb8a0f90c509f78a9f0cf26960b45b3715cdba01537a3ed3e8fe599933671ea", "TP2": "041293633ef2e3e3455f4f1b99cc67b2c6c1f574c1222d46de1e91e3e0dcef674621cbbb61457649850745b0039ef215e529fd434b2e5ef6a2c39aad38d6a9bfef", "TP1": "041f292b1fdf0f6e89db618a2ffd6954fcbea6e452ad6f07a6d75ea3d408fae33016008e2425c4a47142ca18574f7fc32de5bae580f8e3ac293f9bdac04383e8d9", "CS1": "041e508bfb51d8c825c61de7ac0166d8799f57dd0cd88bc32360554c01e7eae8001d0ad2cabb020752bdf964f109c105b553d6154ea29d4049034875bc0ca2f77f", "CS2": "04171eb06598bac089c17e9d8f57322a81e9d51386b2a64cb2212172a007bb895c1d7b8777790723cfde7ff10865dc8be6d7ecb05b368d921b013aa477be3d83d3", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "040f653272e6f706f8d99ed4ef5649b48de61abe80df52d8c6ae37690d8c93ee4715cb2f00c4d0f32437873949ae755d62a65c475cc93dc1f1ec3fd30c64b8ba7d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0407aa341c7d90e588a3cd39450a120d51d8dfe23ec7be3e3e9bf73b372b35310c22545439505ab74dcca8b26b0df21bc3b9be3a00e3125d13f74c21d6356cec9f", "U": "040979195804c7bc75936f5e200ba8163b6437df159fce9720e695aad6434b4ad50b4a4991ad066842f0f68ed9eb9c90f42a7fd163648a255dcd9b8a79de434a6c", "SERVER_OUTPUT": 0, "Y": "204c9a9088bd422fa25b65b339946d1811623dc436df657f31f8862d2b682c95", "X": "047a1cba4dc20eedff0e0a409466c678d637d19e43e0903ac295db8f6adb90e5", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 295, "UT": "041bb27f75bc7d4eae44c06a50ddbc56b3bff5ae2898e23f6097fa2692976b0260163e60511e2c948fd7aa19c231cd4eb4be78979a6bff57a9e913e441f3f8c48d", "MS2": "1c9070df56f53df9e6e4793e80e932375b9018ebade0b34a361b6888fdf37362", "MS1": "1629c419479a0f4599cff79f8ae4660a9ff7abedc172d6a085dcf7b7111f8427", "CLIENT_SECRET": "041d67766d6c1a83ce3143f007aed50418981aeb1da39221bdeab50c7777593fc121c64de75c9afd53c90c2ef21ee836f07ff5154811ad40ef611e5d80b6cd8a0f"}, {"TimeValue": 1437055599, "SS1": "1bffdabfc7b124b565b63c68cd7d729d58731de2efeeef6c0d2ff990079d801e072cf1de9a7241288e2493bb56a58302bc93c051d5b6fbc2d2759fb200729df4043d21c3d4b1b924a76cebcfe291a216bbde558528a4dc1bf39a887c8cf505b0124b561bc0f2981e68a99c9f1d928f5786d623a1243155550d9efdd06ac3b2e5", "SS2": "045cc0441fb3b8445de7f3bad3b1ea052b345755a6be34ef4202e772430da71a0a8231939951f8bd4fa0c3b90150eae122493a355bc002e2bd84d64d0293c49707f1dce15592a0b619b658bd2c0114ab9b3fec031a5fdcebcdccfb0a361bba5d0b49b34088b5da55b64b4ea02960510c3264337f244a0a810c602d203272ee61", "DATE": 16728, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "13c9e266dec853d55771a206a2173048a5e338199f8960e170769541d79ab8c82365cfbb8e3526dfddd1db92247ae5d04ae59d2fe69d0dad5580df1543b1b9b21d9d9a86d60634a85035912a480a7de262de96f19b02777c6cff09975e71e652235b1bd87cef05a1451ad7ca246d4d04d49eeeb6f69b87337b2f22944f58bde3", "SEC": "040b99a1f5bd70ba3273537d45ae1cd54963ef9647535963d6cc31b5eb958a4fa61aee9e6a5210b5923ec710d8bc0e08d8e6357c13e5e6cc0ef6e8bfe0b759f4af", "TP2": "0412c26ae4d4f1fd4a83479582d57b35e6a170e721e19117b3c6cbf094bc5be0d521238d5a0b12f3c7fd96bf95f7427d16c309b04b348c242e9785ca0dd3ba821e", "TP1": "0419e5e632c5bef67e09220310cb2669e44f22003657b8d30bc97b241419b7857f1fab984824cb47f6b0b7b6890a1f93d646163184ef93358d60693d3e83b80577", "CS1": "04074a6fbc697e4a963927872fa2c829ebd1e538ce0b8bc11ccfbf39025e3623201173e3eb1ddf4ebead2dc36c22995f28258c28ae798db47497a63351958f30f1", "CS2": "04220fb08d38b101f09764fa302e28ea1d8d2105a729a2933cdbb508012ea7d3ea1e0604cc5f2e49b2ce1389b4931ae7177eb396abeb252b2ec6216441b9d36849", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "040357a71293ad35fd57a1bb13c81d9f2f0da146586ceaf9ccb43bcf0309636c631672b865056404678def84ac6c9962683622eda24ff8365602e4f1c9426e2bb1", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0412bbdc364eab5f1f633739f790d2e05205e3d621de8fc3decea436891a481bfd04380212197ec5010e264597f12892bad082c8bb2d10ca2d83208663d8c79ce0", "U": "040a6cf11160ff167d644c08802c9196dbc93abc9727e3d8bb3ae8ce9d03af47ed1470f190b35b36da421627c24fa019085532e639dd07ee476a8043afd4b5126e", "SERVER_OUTPUT": 0, "Y": "142ce655deabd8b75e6ace6eb421bdd6a8b1f2f3849a418e269543bdeb47dc4d", "X": "199bf825945fc2f03f25cc23740ca688df3c24fb0ec6f48ef71bef65cf260583", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 296, "UT": "041f4c977efdd77552a1fc534abbc46a2dcafcd8a7d3b94326367684670fe056520306c5c4e8fd5b118b69dbf577b2743f503325e0e132433ff904e1e9cec20fcb", "MS2": "23f1d03d5605cdba987afa073a08196fc693d1d2f52d4e3b0ae04d77cab57b89", "MS1": "19971f1fc24e4ab0a7c1964e9cc364ab6dba4a33e522abf9fb989c8319d4ce7d", "CLIENT_SECRET": "04115947fb92b8fcc745dda580775d94d09ada2b502cd2a80aaa2c666d18fbb5e9179c3c474c3192550eabdb3e48980e5db8807596620ed528599251099a0680e4"}, {"TimeValue": 1437055599, "SS1": "13e6be7a8b27caffb62e30ce4a09c142201b6681864ea90b67b9772e230857ea1a1fede53c25c6fa1bbd95624201e1b589fa872b0b2db57cd91ed72360b767480ab2e27088eb26f475b5c26b72b21eee400ee3748ab8e41b7eceb86781e95d630ef83d45b8ddf24c2a3a778f2a44c76d6975874b3c44acf744bacb4c0b4300b4", "SS2": "11bbcd2b0744e3b2c6dd9c24f27231190488201d2e2e323c7d947908b18b1b680192191fa7354fb60d5e6e58fa2b1d7df1ab9f335f0759b548ca39472e05c77f022cc8db0deb573ae288f36c6969244b7e836d2df8f245a469ce87f9ec8b979d1fe2d982803d8fc62735e4a1fd8e37e0f6538443f3b6555ed31daffa0100d746", "DATE": 16729, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "15e65dcba90c7ec484e8a440596da81c0371f1d936efd9b32939f12db6637fba0bebcbf0a0d413586656246cba7c0f9cdd0e31a53fc9d97e8551c2ba3cf83de81b404060a00058ba36497175a6be198fd870bab16719a74245fb03722979e16d17b3ef6960df82c09377b96e57d6c6130047304118c0eadf2c4a027a050df53e", "SEC": "04183d8bae963d4848ebb67e20798935a99e9e21b13be3327e388b40b191d0ad8d23bd218fbac4d3ac725c547305e9f89d0738c51fe2136b2762ffffc8e0392095", "TP2": "04035b3462cc4802a2ea54e5de36bc75b6523d68f2aeb8f79fdfef0d93b718661910ccb8fa5d754282c00fc3ba123f09f9af8ef5f17f29dbaac528d8ea046e5fa4", "TP1": "040ee419c93c3e080e2ea6d30c14c7785802c706c03fe5bbfcf9cbf3ab28f70a9e15eeec76dd765d7531381cab7e28cbfa996052b6de74622c4625a477ae8eb139", "CS1": "04135d0b1a26af91ff9f66e771ba534ef07149dcf076a7f9a82167478303b5a2eb0ff7671d8d9a73c5639327d042e9370cdfaaeef0436ce0758d1e469340add52c", "CS2": "0420abdcc62397e80afee44b0233f3538c95e6f92a8ce4b6d88a355f37fe5000c80bffd21219df5e1c7d733d85611b65e0522033084df2f148646dd28246fe3f89", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04048c166d27a41cbafc9f5000739efae130ac1ad81273057b8151d7f7cf8953c219adbee5848c84136050e9846090bf0ba79e8eb8e36532ab24c16432ee709609", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0403a7ad8f6de6e76cda38934afd68717a56086e9c4d363b698901a023cd4e1ab60204410d8071b4b4a5bb5f5d149d77bd8d87dd159310456e0dc9d7c0c25cae31", "U": "04103fa56dfec35d6082a29b442d14e2471f80c175762fbf49af4e95719e45679b2249b2bc5b81d2dae828988cca4ae6a1e81dbb5631b26e4a1c8e240d41a0c805", "SERVER_OUTPUT": 0, "Y": "0512449e491edbdd455b46affb331566acd2e15b1bd4427cab899237962a5444", "X": "112e8901cec278b59f5bc6cc4e7f6415c19ea8dfda8e0b76e97d342ac0dd7d04", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 297, "UT": "04209d4d222411602e0ab95685052117f422ad8c68708ecdc6a5df1c89fe545eff1429496160e3fe49096383d55339d65037b842bda7b377d0f0377c11d765141e", "MS2": "21d9195a1ae6687f79609a35f4c9107680f81df918c6e33b9a118cf81c08da16", "MS1": "0d5a51beff31d1a54e9d8d3b0a95835e9e3da964801053acaf4f89a4da1e7f60", "CLIENT_SECRET": "0414a2f3584aa0bfbf305826c4183c7de266dbed7fdc434ac424a9c12407505e99042e793456b8d5612cc05e3da0a981769cc3da8ecc9f39e784a0ef0c414b699e"}, {"TimeValue": 1437055599, "SS1": "208c6171b8d9ecca1dbf9b241e10bcf91dfb1fba536cbe2c6af8fb18fe761a270007b51d902e041dee53b8bec96cc5ee9a537f9e9d95f42de2aaded9ae148ac7071641ead08ea82ab473b28a1a1e8a64b3bedc0d195398a30fd39b35089cef71224d9054e71fddcf157e2d2ce3a285a276c4310fe485f34563072cd99d37b9f1", "SS2": "2375c770b2bdd8c189bd88a7ed9d2699a5915e64651c226711a0c09e56ed489c1d589d875082422315a38074cb679f981e99f7c75eccda6fb75b3bdf72484b0d0d90d69384c09357c5a4677a091ffc0713067e44e8c494efece27941f4c955750655f1c17ee9aa782f19a9edcf6bd92b986aac1a52f3c1fd4ddaf03a1d65e695", "DATE": 16730, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "0264b6e8039a8889398c1d4ca9fc31c1690631e8f14135d250da3c65ef76458f0683b580ec3f216022003e1e581a78bcbce7f723d333255d2a41c5d12d6b547c126539fbc6340a3469d0bcff2e5c62a25aeca401d59898933640a13a8cde25c10788baf7298de01e0d23f3d56fc42f37dd7914448f183b355b301825947e9e65", "SEC": "0403a241fec0988dd5649e9426b439de2864b5fb35c80e18e2f2eab07197a1bde503aacb392e9f1a2294af2fdee0ea652340c1fc8411eb97a493d3c2532e519c7b", "TP2": "040e429d090bcc43698f15a677dc3478e11f45fedc6d45cc149f9a7d6c77c256a4180fdf865e2359fa31076d4a564e85e98b844a1cacc7333d268b554f03d09cd2", "TP1": "0420beacb0b75c9bf385bdaf1ceaf67902c3591c0350acb1ea332c5de3155e0303177845d11ba0c80aa39df2845b83bf73638916997352b4f8a87b839ed7391c28", "CS1": "040d3adc4bc70505c2b11e8ed6341d8b1cdafed0d261029de21647de25c51e962507cc157b1fd06dd098e171f46862e1205e49975497235c43e3b0e2609af997d8", "CS2": "04228ee9171b85ed3a41cd68ba34e235ebdc2b1ce7c021efcb017fd696997fd57d04bdd188be8b3abc9b8dbc8916018205358299275450e21be720fe20f49761b1", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0415f5d852594337504e774ee98178325c18e0ae0dff2554250350d767ed7c4c2a0f6a14bca94d1919caebaa10f82da2ea809e892c7cb2b2ee6f40091bc40797fe", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "041c94ce80164abc42e2dab4786ec7ce4e19fb01a4f71d694b391112ac670944b0220ee94102704428a030d02e4084435cbeb94104aaca84cbf8d747fe456717d5", "U": "0423c388e02d0571b3f7d436e2e57709f89beef80566681caba80189d44d76879f1014ea59fa343d7a9b6c14be9f1eab2f0a2cb0bff88e617ee97d6ada41ae3326", "SERVER_OUTPUT": 0, "Y": "0ee73012d3c452e58d4595195f9acba47f124b0003bdf14c64d0b0aad2565977", "X": "0d4e12d3fee376c63a570939cac53bb0740a75bdb075b41ed08b74b3b974f5af", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 298, "UT": "0403442ca5119f39c70031ae5fd7131ca981be42b60e7141136e58d37c838060be0c1f3cace932d4c881a81b0f9e580ab799fdc8c999f24c84d6f374c7fe0d90ea", "MS2": "1e3f7f3b083d53aee701de7c3079f29af639ffa1a5fe781102a1125be4e7270c", "MS1": "13d749ea9797c1af393a3c47ab7e17a32b33790be8a1b2d2bd4c86755dac5fdc", "CLIENT_SECRET": "0408fe63a20c8469456ca8cde0736710cb40db5e71923d23713045dfca69f99a881b0a04ed4c4c95947e7b88ef8bf259071160b73e474084f106b07f3d4559a592"}, {"TimeValue": 1437055599, "SS1": "189b380f7a912de8c3360d929c8412b286c0be1a7e101646c56e0616941408f3185d8801325011c31404268a39a8c8efd014e161fd39f701a68a9866a3f4eea20efe26dc1360584a3e7ca98ef5c3a6255b9a881e68eb2bbf8e33aa2f7d68cf291e8104d88337c62d7a7049e758e646d123c956ab68042f80d202ef6af9d68064", "SS2": "227fb8bbd6d530666cc12fb9a1b2f1deb84ac029db87c8d5b6d31c4342af6f1519bdfb7c135f122d5ac6cea431e56f96c0c236ac541fdfcabbf6745262ef555315ebee85f38564baa0a2388ce807025ec035c5b91b7136352413c22472a5496612ccff59d69f544cc522d586efdddac12ecf38fd812bccc10ae8b2a4f99728ee", "DATE": 16731, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "239c29371918bf1a4bee6692da73f69cbf3a90b92472feb7d4ed173155e9a31a209579cd2459d68cc68fba9ee1953a7fae81c45a2f5ff2890b6e0ead69714dc3146e5d621eef6d9bbd5fe330bb3fb229c10ea1e466b9ff5e68796a6abb1d22dd1a2ad2093cf5a6e6a7bcfb61950ab60dd80b3d3bb32e3ff73e9c73c160357864", "SEC": "0417334b3497b96006077a42cb3a240b2a60a0e1aaea4bf33244d2c59d4ba750121452e2b0140939052412597111207dff2369b2a0d654a5fa019cf50af846f03b", "TP2": "04000b3a8a8134021fcdda806c0b42172aef10f64b954cbcbb4856d170b3e592ee176dddb6255be23bd52b22a9743155fd699c580b934612fc9bc0ea604df19064", "TP1": "04103a0faa1075c5cabbc2dff9f9f30cad0f032cdd5d449e6f929c38a4258b45370a83c1a926696fd3a5a9b98b51a4b99f6b8cfdd08706e86cc4bcdb8a7c61b017", "CS1": "0416e57ab4973e7e11b7828a70653ffc94b38695f71bcbef9a53b18dabee680cb107b4f7f8b866c478196cdc1956ffc4bbe7e99246621cae1d0bf94a25cc06fa42", "CS2": "040fa5aa89178a8bc651777972f660f9a5d0a2ecbc95f6ec9760e42172537dec66147bd8e3d537317980fd636818688ab9b3280ca46a52e004c6a2f25c074a2a8a", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04119076f8054f9d4703756fc5fa41e8877a5fbbfae2034c3d6b02a6b474dfafe1168d6b6a8de5209d5447c6d26967c7e27b6c192a05017e4041bd7065d668dd93", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0412942be63c7281a8ca64cd18590977cf936c7c1013d66137695d77a14ff147b71e96b32eee9fcf8010b22511413508c27284f14f136898948d7f114a0d3a2c03", "U": "04010a0eeaea17b3dd890a78b0ba667a82253065ac184833ea41cfe49b966101781aee0d0e2d58ef027b745cce95f73b4d426a3907aa3dd6017c8ed0de9fe70b68", "SERVER_OUTPUT": 0, "Y": "23f11458aadadedcaa8e6d7de4c393ca239b4419c9c24ca245a425ae8c60555d", "X": "22f3de9dc2bbbfbf15fc5559cd56950dfe06a8b2d26393ac9d2f62958bc36dc4", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 299, "UT": "04182893c0d34aa7813dab39233de98e31b49f407f70f540143b09aa1f3c86632a165720e339431a20151589e238b0d6fbc43e27d10556d194e67d82bfeffe971e", "MS2": "0cfe5e3726423f7bbf18a3060afc402cb179d0a993eed30ab92474432159e425", "MS1": "02d118e5ce70145d74c91b2b3b1f2ad384589d8b3788c16bedf0dd06531434fc", "CLIENT_SECRET": "0415e3a660ec8cd98875d30186c474f1dadcd332742225e3fec0aed078fad549550d44bc055807767c03e78cb10853a7ad5f9d4eebd5e8046574cc9759d0e02ce2"}]
\ No newline at end of file
diff --git a/js/tests/README.md b/js/tests/README.md
deleted file mode 100644
index 477e136..0000000
--- a/js/tests/README.md
+++ /dev/null
@@ -1,25 +0,0 @@
-# JavaScript tests
-
-## Description 
-
-These tests read test vector files that have been generated from the C code
-implementation of MPin. There are two test vector files; BNCX.json for three pass 
-and BNCSOnePass.json for one pass. The only curve tested in BNCX.
-
-### Dependencies
-
-Install the following node.js modules to run the tests
-
-npm install assert
-npm install fs
-npm install crypto
-
-### Configuration
-
-If required set DEBUG = true in config.js to enable more verbose output.
-
-### Run tests
-
-./run_test.sh 
-
-To run individual tests look inside the script for guidance. 
diff --git a/js/tests/config.js b/js/tests/config.js
deleted file mode 100755
index 818bdc1..0000000
--- a/js/tests/config.js
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
-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.
-*/
-
-var DEBUG = false;
diff --git a/js/tests/find_duplicates.py b/js/tests/find_duplicates.py
deleted file mode 100755
index f9c6772..0000000
--- a/js/tests/find_duplicates.py
+++ /dev/null
@@ -1,40 +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.
-"""
-
-
-"""
-   Find any duplicates in a list of x values
-"""
-
-import sys
-import json
-import json
-
-values = json.load(open("./randomX.json", "r"))
-s = set()
-for x in values:
-    if x in s:
-        print "TEST FAILED"
-        sys.exit(1)
-    else:
-        s.add(x)
-print "TEST PASSED"
-
diff --git a/js/tests/run_test.sh b/js/tests/run_test.sh
deleted file mode 100755
index c6415f1..0000000
--- a/js/tests/run_test.sh
+++ /dev/null
@@ -1,68 +0,0 @@
-#!/bin/sh
-# javascript tests 
-#
-# This script runs tests that compares the js
-# with the expected output from the c code
-#
-# usage: ./run_test.sh
-
-output_file="log.txt"
-if [[ -f "$output_file" ]]
-then
-  echo "rm $output_file"
-  rm $output_file
-fi
-
-ln -s BNCX.json testVectors.json
-ln -s BNCXOnePass.json testVectorsOnePass.json
-
-echo "cp ../MPIN.js ."
-cp ../MPIN.js .
-sed -i 's/var MPIN/MPIN/' MPIN.js
-
-echo "TEST 1: node test_add_shares.js"
-echo "TEST 1: node test_add_shares.js" > $output_file 
-node test_add_shares.js >> $output_file 2>&1
-
-echo "TEST 2: node test_token.js"
-echo "TEST 2: node test_token.js" >> $output_file 
-node test_token.js >> $output_file 2>&1
-
-echo "TEST 3: node test_pass1.js"
-echo "TEST 3: node test_pass1.js" >> $output_file 
-node test_pass1.js >> $output_file 2>&1
-
-echo "TEST 4: node test_pass2.js"
-echo "TEST 4: node test_pass2.js" >> $output_file 
-node test_pass2.js >> $output_file 2>&1
-
-echo "TEST 5: node test_randomX.js"
-echo "TEST 5: node test_randomX.js" >> $output_file 
-node test_randomX.js >> $output_file 2>&1
-./find_duplicates.py >> $output_file 2>&1
-
-echo "TEST 6: node test_sha256.js"
-echo "TEST 6: node test_sha265.js" >> $output_file 
-node test_sha256.js >> $output_file 2>&1
-
-echo "TEST 7: node test_onepass.js"
-echo "TEST 7: node test_onepass.js" >> $output_file 
-node test_onepass.js >> $output_file 2>&1
-
-error=$(grep -i error "${output_file}" )
-if [[ -n "$error" ]]; then
-   echo "ERROR. Please review ${output_file}"
-   exit 1
-fi
-
-failed=$(grep FAILED "${output_file}" )
-if [[ -n "$failed" ]]; then
-   echo "A TEST HAS FAILED. Please review ${output_file}"
-   echo "A TEST HAS FAILED. Please review ${output_file}" >> $output_file 
-else
-   echo "ALL TESTS PASSED"
-   echo "ALL TESTS PASSED" >> $output_file 
-fi
-
-rm testVectors.json
-rm testVectorsOnePass.json
diff --git a/js/tests/test_add_shares.js b/js/tests/test_add_shares.js
deleted file mode 100755
index 8d97ac6..0000000
--- a/js/tests/test_add_shares.js
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
-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.
-*/
-
-console.log("Testing addition of shares");
-var assert = require('assert');
-var fs = require('fs');
-
-// Javascript files from the PIN pad  are included here:
-eval(fs.readFileSync('../DBIG.js')+'');
-eval(fs.readFileSync('../BIG.js')+'');
-eval(fs.readFileSync('../FP.js')+'');
-eval(fs.readFileSync('../ROM.js')+'');
-eval(fs.readFileSync('../HASH.js')+'');
-eval(fs.readFileSync('../RAND.js')+'');
-eval(fs.readFileSync('../AES.js')+'');
-eval(fs.readFileSync('../GCM.js')+'');
-eval(fs.readFileSync('../ECP.js')+'');
-eval(fs.readFileSync('../FP2.js')+'');
-eval(fs.readFileSync('../ECP2.js')+'');
-eval(fs.readFileSync('../FP4.js')+'');
-eval(fs.readFileSync('../FP12.js')+'');
-eval(fs.readFileSync('../PAIR.js')+'');
-eval(fs.readFileSync('./MPIN.js')+'');
-eval(fs.readFileSync('../MPINAuth.js')+'');
-
-// Configuration file
-eval(fs.readFileSync('./config.js')+'');
-
-// Load test vectors
-var vectors = require('./testVectors.json');
-
-// Turn on DEBUG mode in MPINAuth
-MPINAuth.DEBUG = DEBUG;
-
-for(var vector in vectors)
-  {
-    console.log("Test "+vectors[vector].test_no);
-    // Client secrets
-    if (DEBUG){console.log("CS1 "+vectors[vector].CS1);}
-    if (DEBUG){console.log("CS2 "+vectors[vector].CS2);}
-    if (DEBUG){console.log("CLIENT_SECRET "+vectors[vector].CLIENT_SECRET);}
-    var client_secret = MPINAuth.addShares(vectors[vector].CS1, vectors[vector].CS2);
-    if (DEBUG){console.log("client_secret "+client_secret);}
-    try
-      {
-        assert.equal(client_secret, vectors[vector].CLIENT_SECRET, "Client Secret Addition failed");
-      }
-    catch(err)
-      {
-        txt="Error description: " + err.message;
-        console.error(txt);
-        console.log("TEST FAILED");
-        return;
-      }
-    // Time permits
-    if (DEBUG){console.log("TP1 "+vectors[vector].TP1);}
-    if (DEBUG){console.log("TP2 "+vectors[vector].TP2);}
-    if (DEBUG){console.log("TIME_PERMIT "+vectors[vector].TIME_PERMIT);}
-    var time_permit = MPINAuth.addShares(vectors[vector].TP1, vectors[vector].TP2);
-    if (DEBUG){console.log("time_permit "+time_permit);}
-    try
-      {
-        assert.equal(time_permit, vectors[vector].TIME_PERMIT, "Time Permit Addition failed");
-      }
-    catch(err)
-      {
-        txt="Error description: " + err.message;
-        console.error(txt);
-        console.log("TEST FAILED");
-        return;
-      }
-  }
-console.log("TEST PASSED");
diff --git a/js/tests/test_onepass.js b/js/tests/test_onepass.js
deleted file mode 100755
index 6304cdb..0000000
--- a/js/tests/test_onepass.js
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
-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.
-*/
-
-console.log("Testing client request generation");
-var assert = require('assert');
-var fs = require('fs');
-
-// Javascript files from the PIN pad  are included here:
-eval(fs.readFileSync('../DBIG.js')+'');
-eval(fs.readFileSync('../BIG.js')+'');
-eval(fs.readFileSync('../FP.js')+'');
-eval(fs.readFileSync('../ROM.js')+'');
-eval(fs.readFileSync('../HASH.js')+'');
-eval(fs.readFileSync('../RAND.js')+'');
-eval(fs.readFileSync('../AES.js')+'');
-eval(fs.readFileSync('../GCM.js')+'');
-eval(fs.readFileSync('../ECP.js')+'');
-eval(fs.readFileSync('../FP2.js')+'');
-eval(fs.readFileSync('../ECP2.js')+'');
-eval(fs.readFileSync('../FP4.js')+'');
-eval(fs.readFileSync('../FP12.js')+'');
-eval(fs.readFileSync('../PAIR.js')+'');
-eval(fs.readFileSync('./MPIN.js')+'');
-eval(fs.readFileSync('../MPINAuth.js')+'');
-
-// Configuration file
-eval(fs.readFileSync('./config.js')+'');
-
-// Load test vectors
-var vectors = require('./testVectorsOnePass.json');
-
-// Set OTP switch
-var requestOTP = 1;
-// Set WID
-var accessNumber = 123456;
-
-// Turn on DEBUG mode in MPINAuth
-MPINAuth.DEBUG = DEBUG;
-
-var RAW=[];
-for (i=0;i<100;i++) RAW[i]=i;
-var RAW_hex = MPIN.bytestostring(RAW);
-
-// Initiaize RNG
-MPINAuth.initializeRNG(RAW_hex);
-
-for(var vector in vectors)
-  {
-    console.log("Test "+vectors[vector].test_no);
-    if (DEBUG){console.log("MPIN_ID_HEX "+vectors[vector].MPIN_ID_HEX);}
-    if (DEBUG){console.log("TIME_PERMIT "+vectors[vector].TIME_PERMIT);}
-    if (DEBUG){console.log("TOKEN "+vectors[vector].TOKEN);}
-    if (DEBUG){console.log("PIN2 "+vectors[vector].PIN2);}
-    if (DEBUG){console.log("X "+vectors[vector].X);}
-    if (DEBUG){console.log("Y "+vectors[vector].Y);}
-    if (DEBUG){console.log("U "+vectors[vector].U);}
-    if (DEBUG){console.log("UT "+vectors[vector].UT);}
-    if (DEBUG){console.log("TimeValue "+vectors[vector].TimeValue);}
-    if (DEBUG){console.log("DATE "+vectors[vector].DATE);}
-    if (DEBUG){console.log("SEC "+vectors[vector].SEC);}
-    var passSingle = MPINAuth.passRequest(vectors[vector].MPIN_ID_HEX, vectors[vector].TOKEN, vectors[vector].TIME_PERMIT, vectors[vector].PIN2, requestOTP, accessNumber, vectors[vector].DATE, vectors[vector].TimeValue, vectors[vector].X);
-    if (DEBUG){console.dir("passSingle "+passSingle);}
-    try
-      {
-        if (!vectors[vector].DATE){assert.equal(passSingle.U, vectors[vector].U, "U generation failed");}
-        assert.equal(passSingle.UT, vectors[vector].UT, "UT generation failed");
-        assert.equal(passSingle.V, vectors[vector].SEC, "V generation failed");
-      }
-    catch(err)
-      {
-        txt="Error description: " + err.message;
-        console.error(txt);
-        var cur_date = new Date();
-        console.log("TEST FAILED: "+cur_date.toISOString());
-        return;
-      }
-  }
-console.log("TEST PASSED");
diff --git a/js/tests/test_pass1.js b/js/tests/test_pass1.js
deleted file mode 100755
index 5258087..0000000
--- a/js/tests/test_pass1.js
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
-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.
-*/
-
-console.log("Testing pass one request generation");
-var assert = require('assert');
-var fs = require('fs');
-
-// Javascript files from the PIN pad  are included here:
-eval(fs.readFileSync('../DBIG.js')+'');
-eval(fs.readFileSync('../BIG.js')+'');
-eval(fs.readFileSync('../FP.js')+'');
-eval(fs.readFileSync('../ROM.js')+'');
-eval(fs.readFileSync('../HASH.js')+'');
-eval(fs.readFileSync('../RAND.js')+'');
-eval(fs.readFileSync('../AES.js')+'');
-eval(fs.readFileSync('../GCM.js')+'');
-eval(fs.readFileSync('../ECP.js')+'');
-eval(fs.readFileSync('../FP2.js')+'');
-eval(fs.readFileSync('../ECP2.js')+'');
-eval(fs.readFileSync('../FP4.js')+'');
-eval(fs.readFileSync('../FP12.js')+'');
-eval(fs.readFileSync('../PAIR.js')+'');
-eval(fs.readFileSync('./MPIN.js')+'');
-eval(fs.readFileSync('../MPINAuth.js')+'');
-
-// Configuration file
-eval(fs.readFileSync('./config.js')+'');
-
-// Load test vectors
-var vectors = require('./testVectors.json');
-
-// Turn on DEBUG mode in MPINAuth
-MPINAuth.DEBUG = DEBUG;
-
-var RAW=[];
-for (i=0;i<100;i++) RAW[i]=i;
-var RAW_hex = MPIN.bytestostring(RAW);
-
-// Initiaize RNG
-MPINAuth.initializeRNG(RAW_hex);
-
-for(var vector in vectors)
-  {
-    console.log("Test "+vectors[vector].test_no);
-    if (DEBUG){console.log("MPIN_ID_HEX "+vectors[vector].MPIN_ID_HEX);}
-    if (DEBUG){console.log("TIME_PERMIT "+vectors[vector].TIME_PERMIT);}
-    if (DEBUG){console.log("TOKEN "+vectors[vector].TOKEN);}
-    if (DEBUG){console.log("PIN2 "+vectors[vector].PIN2);}
-    if (DEBUG){console.log("X "+vectors[vector].X);}
-    if (DEBUG){console.log("U "+vectors[vector].U);}
-    if (DEBUG){console.log("UT "+vectors[vector].UT);}
-    var pass1 = MPINAuth.pass1Request(vectors[vector].MPIN_ID_HEX, vectors[vector].TOKEN, vectors[vector].TIME_PERMIT, vectors[vector].PIN2, vectors[vector].DATE, vectors[vector].X);
-    if (DEBUG){console.dir("pass1 "+pass1);}
-    try
-      {
-        assert.equal(pass1.U, vectors[vector].U, "U generation failed");
-        assert.equal(pass1.UT, vectors[vector].UT, "UT generation failed");
-      }
-    catch(err)
-      {
-        txt="Error description: " + err.message;
-        console.error(txt);
-        var cur_date = new Date();
-        console.log("TEST FAILED: "+cur_date.toISOString());
-        return;
-      }
-  }
-console.log("TEST PASSED");
diff --git a/js/tests/test_pass2.js b/js/tests/test_pass2.js
deleted file mode 100755
index 09a27d4..0000000
--- a/js/tests/test_pass2.js
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
-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.
-*/
-
-console.log("Testing pass two request generation");
-var assert = require('assert');
-var fs = require('fs');
-
-// Javascript files from the PIN pad  are included here:
-eval(fs.readFileSync('../DBIG.js')+'');
-eval(fs.readFileSync('../BIG.js')+'');
-eval(fs.readFileSync('../FP.js')+'');
-eval(fs.readFileSync('../ROM.js')+'');
-eval(fs.readFileSync('../HASH.js')+'');
-eval(fs.readFileSync('../RAND.js')+'');
-eval(fs.readFileSync('../AES.js')+'');
-eval(fs.readFileSync('../GCM.js')+'');
-eval(fs.readFileSync('../ECP.js')+'');
-eval(fs.readFileSync('../FP2.js')+'');
-eval(fs.readFileSync('../ECP2.js')+'');
-eval(fs.readFileSync('../FP4.js')+'');
-eval(fs.readFileSync('../FP12.js')+'');
-eval(fs.readFileSync('../PAIR.js')+'');
-eval(fs.readFileSync('./MPIN.js')+'');
-eval(fs.readFileSync('../MPINAuth.js')+'');
-
-// Configuration file
-eval(fs.readFileSync('./config.js')+'');
-
-// Load test vectors
-var vectors = require('./testVectors.json');
-
-// Turn on DEBUG mode in MPINAuth
-MPINAuth.DEBUG = DEBUG;
-
-// Set OTP switch
-var requestOTP = 1;
-// Set WID
-var accessNumber = 123456;
-
-for(var vector in vectors)
-  {
-    console.log("Test "+vectors[vector].test_no);
-    if (DEBUG){console.log("X "+vectors[vector].X);}
-    if (DEBUG){console.log("Y "+vectors[vector].Y);}
-    if (DEBUG){console.log("SEC "+vectors[vector].SEC);}
-    MPINAuth.X = MPINAuth.hextobytes(vectors[vector].X);
-    MPINAuth.SEC = MPINAuth.hextobytes(vectors[vector].SEC);
-    var pass2 = MPINAuth.pass2Request(vectors[vector].Y, requestOTP, accessNumber);
-    if (DEBUG){console.dir("pass2 "+pass2);}
-    try
-      {
-        assert.equal(pass2.V, vectors[vector].V, "V generation failed");
-      }
-    catch(err)
-      {
-        txt="Error description: " + err.message;
-        console.error(txt);
-        var cur_date = new Date();
-        console.log("TEST FAILED: "+cur_date.toISOString());
-        return;
-      }
-  }
-console.log("TEST PASSED");
diff --git a/js/tests/test_randomX.js b/js/tests/test_randomX.js
deleted file mode 100755
index 9c7e8bb..0000000
--- a/js/tests/test_randomX.js
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
-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.
-*/
-
-console.log("Testing randomX");
-var assert = require('assert');
-var fs = require('fs');
-var crypto = require('crypto');
-
-// Javascript files from the PIN pad  are included here:
-eval(fs.readFileSync('../DBIG.js')+'');
-eval(fs.readFileSync('../BIG.js')+'');
-eval(fs.readFileSync('../FP.js')+'');
-eval(fs.readFileSync('../ROM.js')+'');
-eval(fs.readFileSync('../HASH.js')+'');
-eval(fs.readFileSync('../RAND.js')+'');
-eval(fs.readFileSync('../AES.js')+'');
-eval(fs.readFileSync('../GCM.js')+'');
-eval(fs.readFileSync('../ECP.js')+'');
-eval(fs.readFileSync('../FP2.js')+'');
-eval(fs.readFileSync('../ECP2.js')+'');
-eval(fs.readFileSync('../FP4.js')+'');
-eval(fs.readFileSync('../FP12.js')+'');
-eval(fs.readFileSync('../PAIR.js')+'');
-eval(fs.readFileSync('./MPIN.js')+'');
-eval(fs.readFileSync('../MPINAuth.js')+'');
-
-// Configuration file
-eval(fs.readFileSync('./config.js')+'');
-
-// Turn on DEBUG mode in MPINAuth
-MPINAuth.DEBUG = DEBUG;
-
-var x_vals=[];
-
-// Initiaize RNG
-var seed = crypto.randomBytes(32);
-var seed_hex = seed.toString("hex");
-MPINAuth.initializeRNG(seed_hex);
-
-mpin_id_hex = "7b226d6f62696c65223a20312c2022697373756564223a2022323031342d31322d31385431303a32303a32395a222c2022757365724944223a20223531306263313033353530616465636332316438393730303835323763323666406365727469766f782e636f6d222c202273616c74223a202234656233336433356366323963653161227d";
-token_hex = "040128e30db2a7e5a26770498f558eab68920f58b4f707e738390160b2b4883bfb0521fe217597f279286818496a303e8d4b1a7e97b9c30d6c9fae99362c043e26";
-timePermit_hex = "041019f24b3dbae8727fef08323e38fd36dcd1193f6de3286e7c4b224c539850a8200ee94fa5c45fa3350b14d015ebc4834ac57c4705712206655252a1a57939be";
-PIN = 777
-date = 16639
-
-// Assign values of x to array
-for(var i = 0; i < 10;i++)
-  {
-    var pass1 = MPINAuth.pass1Request(mpin_id_hex, token_hex, timePermit_hex, PIN, date,  null);
-    x_hex = MPIN.bytestostring(MPINAuth.X);
-    if(DEBUG){console.log("iter: "+i+" X: "+x_hex);}
-    x_vals.push(x_hex);
-  }
-
-// Model re-rendering of page
-var seed = crypto.randomBytes(32);
-var seed_hex = seed.toString("hex");
-MPINAuth.initializeRNG(seed_hex);
-
-// Assign values of x to array
-for(var i = 0; i < 10;i++)
-  {
-    var pass1 = MPINAuth.pass1Request(mpin_id_hex, token_hex, timePermit_hex, PIN, date, null);
-    x_hex = MPIN.bytestostring(MPINAuth.X);
-    if(DEBUG){console.log("iter: "+i+" X: "+x_hex);}
-    x_vals.push(x_hex);
-  }
-
-if(DEBUG){console.dir(x_vals);}
-
-// Write values to file for further processing
-x_json = JSON.stringify(x_vals);
-if(DEBUG){console.log(x_json);}
-var output_file = "./randomX.json";
-fs.writeFile(output_file, x_json, function(err) {
-    if(err) {
-        console.log(err);
-        console.log("Error writing to "+output_file);
-    }
-});
-console.log(output_file+" generated");
-
diff --git a/js/tests/test_sha256.js b/js/tests/test_sha256.js
deleted file mode 100755
index ceabd4b..0000000
--- a/js/tests/test_sha256.js
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
-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.
-*/
-
-console.log("Testing sha256");
-var assert = require('assert');
-var fs = require('fs');
-var crypto = require('crypto');
-
-// Javascript files from the PIN pad  are included here:
-eval(fs.readFileSync('../DBIG.js')+'');
-eval(fs.readFileSync('../BIG.js')+'');
-eval(fs.readFileSync('../FP.js')+'');
-eval(fs.readFileSync('../ROM.js')+'');
-eval(fs.readFileSync('../HASH.js')+'');
-eval(fs.readFileSync('../RAND.js')+'');
-eval(fs.readFileSync('../AES.js')+'');
-eval(fs.readFileSync('../GCM.js')+'');
-eval(fs.readFileSync('../ECP.js')+'');
-eval(fs.readFileSync('../FP2.js')+'');
-eval(fs.readFileSync('../ECP2.js')+'');
-eval(fs.readFileSync('../FP4.js')+'');
-eval(fs.readFileSync('../FP12.js')+'');
-eval(fs.readFileSync('../PAIR.js')+'');
-eval(fs.readFileSync('./MPIN.js')+'');
-eval(fs.readFileSync('../MPINAuth.js')+'');
-
-// Configuration file
-eval(fs.readFileSync('./config.js')+'');
-
-// Turn on DEBUG mode in MPINAuth
-MPINAuth.DEBUG = DEBUG;
-
-// Compare M-Pin sha256 with crypto version
-for (i=0;i<100;i++)
-  {
-    console.log("Test "+i);
-    // Data for mpin_id
-    var randomUser = crypto.randomBytes(32);
-    var userID = randomUser.toString("hex");
-    var cur_date = new Date();
-    var issued = cur_date.toISOString();
-    var salt = crypto.randomBytes(16);
-    var salt_hex = salt.toString("hex");
-
-    // Form MPin ID
-    var endUserdata = {
-      "issued": issued,
-      "userID": userID,
-      "mobile": 1,
-      "salt": salt_hex
-    };
-    mpin_id = JSON.stringify(endUserdata);
-    hash_mpin_id_hex1 = crypto.createHash('sha256').update(mpin_id).digest('hex');
-
-    var mpin_id_bytes =MPIN.stringtobytes(mpin_id);
-    var hash_mpin_id_bytes=[];
-    hash_mpin_id_bytes = MPIN.HASH_ID(mpin_id_bytes)
-    var hash_mpin_id_hex2 = MPIN.bytestostring(hash_mpin_id_bytes);
-
-    if (DEBUG){console.log("hash_mpin_id_hex1: "+hash_mpin_id_hex1 + "\nhash_mpin_id_hex2: "+hash_mpin_id_hex2);}
-    try
-      {
-        assert.equal(hash_mpin_id_hex1, hash_mpin_id_hex2, "sha256 test failed");
-      }
-    catch(err)
-      {
-        txt="Error description: " + err.message;
-        console.error(txt);
-        var cur_date = new Date();
-        console.log("TEST FAILED: "+cur_date.toISOString());
-        return;
-      }
-
-
-
-  }
diff --git a/js/tests/test_token.js b/js/tests/test_token.js
deleted file mode 100755
index c82ffc5..0000000
--- a/js/tests/test_token.js
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
-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.
-*/
-
-console.log("Testing token generation");
-var assert = require('assert');
-var fs = require('fs');
-
-// Javascript files from the PIN pad  are included here:
-eval(fs.readFileSync('../DBIG.js')+'');
-eval(fs.readFileSync('../BIG.js')+'');
-eval(fs.readFileSync('../FP.js')+'');
-eval(fs.readFileSync('../ROM.js')+'');
-eval(fs.readFileSync('../HASH.js')+'');
-eval(fs.readFileSync('../RAND.js')+'');
-eval(fs.readFileSync('../AES.js')+'');
-eval(fs.readFileSync('../GCM.js')+'');
-eval(fs.readFileSync('../ECP.js')+'');
-eval(fs.readFileSync('../FP2.js')+'');
-eval(fs.readFileSync('../ECP2.js')+'');
-eval(fs.readFileSync('../FP4.js')+'');
-eval(fs.readFileSync('../FP12.js')+'');
-eval(fs.readFileSync('../PAIR.js')+'');
-eval(fs.readFileSync('./MPIN.js')+'');
-eval(fs.readFileSync('../MPINAuth.js')+'');
-
-// Configuration file
-eval(fs.readFileSync('./config.js')+'');
-
-// Load test vectors
-var vectors = require('./testVectors.json');
-
-// Turn on DEBUG mode in MPINAuth
-MPINAuth.DEBUG = DEBUG;
-
-for(var vector in vectors)
-  {
-    console.log("Test "+vectors[vector].test_no);
-    if (DEBUG){console.log("PIN "+vectors[vector].PIN1);}
-    if (DEBUG){console.log("CLIENT_SECRET "+vectors[vector].CLIENT_SECRET);}
-    if (DEBUG){console.log("MPIN_ID_HEX "+vectors[vector].MPIN_ID_HEX);}
-    if (DEBUG){console.log("TOKEN "+vectors[vector].TOKEN);}
-    var token = MPINAuth.calculateMPinToken(vectors[vector].MPIN_ID_HEX, vectors[vector].PIN1, vectors[vector].CLIENT_SECRET);
-    if (DEBUG){console.log("token "+token);}
-    try
-      {
-        assert.equal(token, vectors[vector].TOKEN, "Token generation failed");
-      }
-    catch(err)
-      {
-        txt="Error description: " + err.message;
-        console.error(txt);
-        console.log("TEST FAILED");
-        return;
-      }
-  }
-console.log("TEST PASSED");
diff --git a/linux.md b/linux.md
deleted file mode 100644
index 40556e0..0000000
--- a/linux.md
+++ /dev/null
@@ -1,55 +0,0 @@
-<h2>Software dependencies</h2>
-
-CMake is required to build the library and can usually be installed from
-the operating system package manager.
-
-<ul type="disc">
-  <li>sudo apt-get install cmake</li>
-</ul>
-
-If not, then you can download it from www.cmake.org
-
-The C Foreign Function Interface for Python <a href="https://cffi.readthedocs.org/en/latest/">CFFI</a> module
-is also required if you wish to use the Python module.
-
-<ul type="disc">
-  <li>sudo pip install cffi</li>
-</ul>
-
-In order to build the documentation <a href="http://www.stack.nl/~dimitri/doxygen/">doxygen</a> is required.
-
-<h2>Build Instructions</h2>
-
-<p>The default build is for 32 bit machines</p>
-
-<ol type="disc">
-  <li>mkdir Release</li>
-  <li>cd Release</li>
-  <li>cmake ..</li>
-  <li>make</li>
-  <li>make test</li>
-  <li>make doc</li>
-  <li>sudo make install</li>
-</ol>
-
-<p>The build can be configured using by setting flags on the command line i.e.</p>
-
-<ol type="disc">
-  <li>cmake -DWORD_LENGTH=64 ..</li>
-</ol>
-
-<h2>Uninstall software</h2>
-
-<ul type="disc">
-  <li>sudo make uninstall</li>
-</ul>
-
-<h2>Building an installer</h2>
-
-<p>After having built the libraries you can build a binary installer and a source distribution by running this command</p>
-
-<ul type="disc">
-  <li>make package</li>
-</ul>
-
-
diff --git a/mac.md b/mac.md
deleted file mode 100644
index 8c24982..0000000
--- a/mac.md
+++ /dev/null
@@ -1,56 +0,0 @@
-<h2>Software dependencies</h2>
-
-Install <a href="http://brew.sh/">Homebrew</a>
-
-<ul type="disc">
-  <li>ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"</li>
-</ul>
-
-Install  <a href="http://www.cmake.org/download/">cmake</a>
-
-<ul type="disc">
-  <li>brew install cmake</li>
-</ul>
-
-The C Foreign Function Interface for Python <a href="https://cffi.readthedocs.org/en/latest/">CFFI</a> module
-is also required if you wish to use the Python module.
-
-<ul type="disc">
-  <li>brew install pkg-config libffi</li>
-  <li>sudo pip install cffi</li>
-</ul>
-
-In order to build the documentation <a href="http://www.stack.nl/~dimitri/doxygen/">doxygen</a> is required.
-
-<ul type="disc">
-  <li>brew install doxygen</li>
-</ul>
-
-<h2>Build Instructions</h2>
-
-<p>The default build is for 32 bit machines</p>
-
-<ol type="disc">
-  <li>mkdir Release</li>
-  <li>cd Release</li>
-  <li>cmake ..</li>
-  <li>make</li>
-  <li>make test</li>
-  <li>make doc</li>
-  <li>sudo make install</li>
-</ol>
-
-<p>The build can be configured using by setting flags on the command line i.e.</p>
-
-<ol type="disc">
-  <li>cmake -DWORD_LENGTH=64 ..</li>
-</ol>
-
-<h2>Uninstall software</h2>
-
-<ul type="disc">
-  <li>sudo make uninstall</li>
-</ul>
-
-
-
diff --git a/pythonCFFI/CMakeLists.txt b/pythonCFFI/CMakeLists.txt
deleted file mode 100644
index 557a8e6..0000000
--- a/pythonCFFI/CMakeLists.txt
+++ /dev/null
@@ -1,138 +0,0 @@
-# Install M-PIN module
-
-if(BUILD_MPIN)
-  if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
-    INSTALL(FILES ${PROJECT_SOURCE_DIR}/pythonCFFI/mpin.py DESTINATION "${PYTHON_SITE_PACKAGES}" PERMISSIONS
-            OWNER_WRITE OWNER_READ OWNER_EXECUTE
-            GROUP_READ GROUP_EXECUTE
-            WORLD_READ WORLD_EXECUTE)
-
-    if (USE_ANONYMOUS)
-        INSTALL(FILES ${PROJECT_SOURCE_DIR}/pythonCFFI/TestMPINAnonInstall.py DESTINATION bin PERMISSIONS
-                OWNER_WRITE OWNER_READ OWNER_EXECUTE
-                GROUP_READ GROUP_EXECUTE
-                WORLD_READ WORLD_EXECUTE)
-    else (USE_ANONYMOUS)
-        INSTALL(FILES ${PROJECT_SOURCE_DIR}/pythonCFFI/TestMPINInstall.py DESTINATION bin PERMISSIONS
-                OWNER_WRITE OWNER_READ OWNER_EXECUTE
-                GROUP_READ GROUP_EXECUTE
-                WORLD_READ WORLD_EXECUTE)
-    endif (USE_ANONYMOUS)
-
-  endif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
-
-  if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
-    # Windows specific code
-    INSTALL(FILES ${PROJECT_SOURCE_DIR}/pythonCFFI/mpin.py DESTINATION lib)
-    if (USE_ANONYMOUS)
-        INSTALL(FILES ${PROJECT_SOURCE_DIR}/pythonCFFI/TestMPINAnonInstall.py DESTINATION lib)
-    else (USE_ANONYMOUS)
-        INSTALL(FILES ${PROJECT_SOURCE_DIR}/pythonCFFI/TestMPINInstall.py DESTINATION lib)
-    endif (USE_ANONYMOUS)
-  endif(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
-
-  if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
-    # Mac OS X specific code
-    INSTALL(FILES ${PROJECT_SOURCE_DIR}/pythonCFFI/mpin.py DESTINATION "${PYTHON_SITE_PACKAGES}" PERMISSIONS
-            OWNER_WRITE OWNER_READ OWNER_EXECUTE
-            GROUP_READ GROUP_EXECUTE
-            WORLD_READ WORLD_EXECUTE)
-
-    if (USE_ANONYMOUS)
-        INSTALL(FILES ${PROJECT_SOURCE_DIR}/pythonCFFI/TestMPINAnonInstall.py DESTINATION bin PERMISSIONS
-                OWNER_WRITE OWNER_READ OWNER_EXECUTE
-                GROUP_READ GROUP_EXECUTE
-                WORLD_READ WORLD_EXECUTE)
-    else (USE_ANONYMOUS)
-        INSTALL(FILES ${PROJECT_SOURCE_DIR}/pythonCFFI/TestMPINInstall.py DESTINATION bin PERMISSIONS
-                OWNER_WRITE OWNER_READ OWNER_EXECUTE
-                GROUP_READ GROUP_EXECUTE
-                WORLD_READ WORLD_EXECUTE)
-    endif (USE_ANONYMOUS)
-
-  endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
-
-  file(COPY mpin.py DESTINATION "${PROJECT_BINARY_DIR}/pythonCFFI/")
-  if (USE_ANONYMOUS)
-      file(COPY TestMPINAnonInstall.py DESTINATION "${PROJECT_BINARY_DIR}/pythonCFFI/")
-      add_test (TestMPINAnonInstall python TestMPINAnonInstall.py) 
-  else (USE_ANONYMOUS)
-      file(COPY TestMPINInstall.py DESTINATION "${PROJECT_BINARY_DIR}/pythonCFFI/")   
-      add_test (TestMPINInstall python TestMPINInstall.py) 
-  endif (USE_ANONYMOUS) 
-  
-
-  if(FIELD_CHOICE STREQUAL "BNCX")
-      if (USE_ANONYMOUS)
-          file(COPY TestMPINAnon.py DESTINATION "${PROJECT_BINARY_DIR}/pythonCFFI/")
-          add_test (TestMPINAnonBNCX python TestMPINAnon.py)
-      else (USE_ANONYMOUS)
-          file(COPY TestMPIN.py DESTINATION "${PROJECT_BINARY_DIR}/pythonCFFI/")
-          add_test (TestMPINBNCX python TestMPIN.py)
-      endif (USE_ANONYMOUS) 
-  endif(FIELD_CHOICE STREQUAL "BNCX")
-
-  
-endif(BUILD_MPIN)
-
-
-if(BUILD_SOK)
-  if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
-    INSTALL(FILES ${PROJECT_SOURCE_DIR}/pythonCFFI/sok.py DESTINATION "${PYTHON_SITE_PACKAGES}" PERMISSIONS
-            OWNER_WRITE OWNER_READ OWNER_EXECUTE
-            GROUP_READ GROUP_EXECUTE
-            WORLD_READ WORLD_EXECUTE)
-    INSTALL(FILES ${PROJECT_SOURCE_DIR}/pythonCFFI/TestSOKInstall.py DESTINATION bin PERMISSIONS
-            OWNER_WRITE OWNER_READ OWNER_EXECUTE
-            GROUP_READ GROUP_EXECUTE
-            WORLD_READ WORLD_EXECUTE)
-  endif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
-
-  if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
-    # Windows specific code
-    INSTALL(FILES ${PROJECT_SOURCE_DIR}/pythonCFFI/sok.py DESTINATION lib)
-    INSTALL(FILES ${PROJECT_SOURCE_DIR}/pythonCFFI/TestSOKInstall.py DESTINATION lib)
-  endif(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
-
-  if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
-    # Mac OS X specific code
-    INSTALL(FILES ${PROJECT_SOURCE_DIR}/pythonCFFI/sok.py DESTINATION "${PYTHON_SITE_PACKAGES}" PERMISSIONS
-            OWNER_WRITE OWNER_READ OWNER_EXECUTE
-            GROUP_READ GROUP_EXECUTE
-            WORLD_READ WORLD_EXECUTE)
-    INSTALL(FILES ${PROJECT_SOURCE_DIR}/pythonCFFI/TestSOKInstall.py DESTINATION bin PERMISSIONS
-            OWNER_WRITE OWNER_READ OWNER_EXECUTE
-            GROUP_READ GROUP_EXECUTE
-            WORLD_READ WORLD_EXECUTE)
-  endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
-
-  file(COPY sok.py DESTINATION "${PROJECT_BINARY_DIR}/pythonCFFI/")
-  file(COPY TestSOKInstall.py DESTINATION "${PROJECT_BINARY_DIR}/pythonCFFI/")
-
-  add_test (TestSOKInstall python TestSOKInstall.py)
-endif(BUILD_SOK)
-
-
-if(BUILD_WCC)
-  if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
-    INSTALL(FILES ${PROJECT_SOURCE_DIR}/pythonCFFI/wcc.py DESTINATION "${PYTHON_SITE_PACKAGES}" PERMISSIONS
-            OWNER_WRITE OWNER_READ OWNER_EXECUTE
-            GROUP_READ GROUP_EXECUTE
-            WORLD_READ WORLD_EXECUTE)
-  endif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
-
-  if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
-    # Windows specific code
-    INSTALL(FILES ${PROJECT_SOURCE_DIR}/pythonCFFI/wcc.py DESTINATION lib)
-  endif(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
-
-  if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
-    # Mac OS X specific code
-    INSTALL(FILES ${PROJECT_SOURCE_DIR}/pythonCFFI/wcc.py DESTINATION "${PYTHON_SITE_PACKAGES}" PERMISSIONS
-            OWNER_WRITE OWNER_READ OWNER_EXECUTE
-            GROUP_READ GROUP_EXECUTE
-            WORLD_READ WORLD_EXECUTE)
-  endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
-
-  file(COPY wcc.py DESTINATION "${PROJECT_BINARY_DIR}/pythonCFFI/")
-endif(BUILD_WCC)
diff --git a/pythonCFFI/README.md b/pythonCFFI/README.md
deleted file mode 100644
index e672502..0000000
--- a/pythonCFFI/README.md
+++ /dev/null
@@ -1,15 +0,0 @@
-This directory contains the python module that
-interacts with the c code using CFFI.
-
-To run all MPIN tests
-
-./TestMPINInstall.py -v
-
-To run all SOK tests
-
-./TestSOKInstall.py -v
-
-To run all WCC tests
-
-./TestWCCInstall.py -v
-
diff --git a/pythonCFFI/TestMPIN.py b/pythonCFFI/TestMPIN.py
deleted file mode 100755
index 24cb516..0000000
--- a/pythonCFFI/TestMPIN.py
+++ /dev/null
@@ -1,326 +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
-
-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
-CS1[0].max = G1
-CS1[0].len = G1
-
-CS2 = ffi.new("octet*")
-CS2val = ffi.new("char []", G1)
-CS2[0].val = CS2val
-CS2[0].max = G1
-CS2[0].len = G1
-
-SEC = ffi.new("octet*")
-SECval = ffi.new("char []", G1)
-SEC[0].val = SECval
-SEC[0].max = G1
-SEC[0].len = G1
-
-# Server secret and shares
-SS1 = ffi.new("octet*")
-SS1val = ffi.new("char []", G2)
-SS1[0].val = SS1val
-SS1[0].max = G2
-SS1[0].len = G2
-
-SS2 = ffi.new("octet*")
-SS2val = ffi.new("char []", G2)
-SS2[0].val = SS2val
-SS2[0].max = G2
-SS2[0].len = G2
-
-SERVER_SECRET = ffi.new("octet*")
-SERVER_SECRETval = ffi.new("char []", G2)
-SERVER_SECRET[0].val = SERVER_SECRETval
-SERVER_SECRET[0].max = G2
-SERVER_SECRET[0].len = G2
-
-# Time Permit and shares
-TP1 = ffi.new("octet*")
-TP1val = ffi.new("char []", G1)
-TP1[0].val = TP1val
-TP1[0].max = G1
-TP1[0].len = G1
-
-TP2 = ffi.new("octet*")
-TP2val = ffi.new("char []", G1)
-TP2[0].val = TP2val
-TP2[0].max = G1
-TP2[0].len = G1
-
-TIME_PERMIT = ffi.new("octet*")
-TIME_PERMITval = ffi.new("char []", G1)
-TIME_PERMIT[0].val = TIME_PERMITval
-TIME_PERMIT[0].max = G1
-TIME_PERMIT[0].len = G1
-
-# Token stored on computer
-TOKEN = ffi.new("octet*")
-TOKENval = ffi.new("char []", G1)
-TOKEN[0].val = TOKENval
-TOKEN[0].max = G1
-TOKEN[0].len = G1
-
-UT = ffi.new("octet*")
-UTval = ffi.new("char []", G1)
-UT[0].val = UTval
-UT[0].max = G1
-UT[0].len = G1
-
-U = ffi.new("octet*")
-Uval = ffi.new("char []", G1)
-U[0].val = Uval
-U[0].max = G1
-U[0].len = G1
-
-X = ffi.new("octet*")
-Xval = ffi.new("char []", PGS)
-X[0].val = Xval
-X[0].max = PGS
-X[0].len = PGS
-
-Y = ffi.new("octet*")
-Yval = ffi.new("char []", PGS)
-Y[0].val = Yval
-Y[0].max = PGS
-Y[0].len = PGS
-
-lenEF = 12 * PFS
-E = ffi.new("octet*")
-Eval = ffi.new("char []", lenEF)
-E[0].val = Eval
-E[0].max = lenEF
-E[0].len = lenEF
-
-F = ffi.new("octet*")
-Fval = ffi.new("char []", lenEF)
-F[0].val = Fval
-F[0].max = lenEF
-F[0].len = lenEF
-
-# H(ID)
-HID = ffi.new("octet*")
-HIDval = ffi.new("char []", G1)
-HID[0].val = HIDval
-HID[0].max = G1
-HID[0].len = G1
-
-# H(T|H(ID))
-HTID = ffi.new("octet*")
-HTIDval = ffi.new("char []", G1)
-HTID[0].val = HTIDval
-HTID[0].max = G1
-HTID[0].len = G1
-
-
-class TestMPIN(unittest.TestCase):
-    """Tests M-Pin crypto code"""
-
-    def setUp(self):
-
-        # Form MPin ID
-        endUserData = {
-            "issued": "2013-10-19T06:12:28Z",
-            "userID": "testUser@miracl.com",
-            "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_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, 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'])
-
-if __name__ == '__main__':
-    # Run tests
-    unittest.main()
diff --git a/pythonCFFI/TestMPINAnon.py b/pythonCFFI/TestMPINAnon.py
deleted file mode 100755
index ae332c5..0000000
--- a/pythonCFFI/TestMPINAnon.py
+++ /dev/null
@@ -1,326 +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
-
-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
-CS1[0].max = G1
-CS1[0].len = G1
-
-CS2 = ffi.new("octet*")
-CS2val = ffi.new("char []", G1)
-CS2[0].val = CS2val
-CS2[0].max = G1
-CS2[0].len = G1
-
-SEC = ffi.new("octet*")
-SECval = ffi.new("char []", G1)
-SEC[0].val = SECval
-SEC[0].max = G1
-SEC[0].len = G1
-
-# Server secret and shares
-SS1 = ffi.new("octet*")
-SS1val = ffi.new("char []", G2)
-SS1[0].val = SS1val
-SS1[0].max = G2
-SS1[0].len = G2
-
-SS2 = ffi.new("octet*")
-SS2val = ffi.new("char []", G2)
-SS2[0].val = SS2val
-SS2[0].max = G2
-SS2[0].len = G2
-
-SERVER_SECRET = ffi.new("octet*")
-SERVER_SECRETval = ffi.new("char []", G2)
-SERVER_SECRET[0].val = SERVER_SECRETval
-SERVER_SECRET[0].max = G2
-SERVER_SECRET[0].len = G2
-
-# Time Permit and shares
-TP1 = ffi.new("octet*")
-TP1val = ffi.new("char []", G1)
-TP1[0].val = TP1val
-TP1[0].max = G1
-TP1[0].len = G1
-
-TP2 = ffi.new("octet*")
-TP2val = ffi.new("char []", G1)
-TP2[0].val = TP2val
-TP2[0].max = G1
-TP2[0].len = G1
-
-TIME_PERMIT = ffi.new("octet*")
-TIME_PERMITval = ffi.new("char []", G1)
-TIME_PERMIT[0].val = TIME_PERMITval
-TIME_PERMIT[0].max = G1
-TIME_PERMIT[0].len = G1
-
-# Token stored on computer
-TOKEN = ffi.new("octet*")
-TOKENval = ffi.new("char []", G1)
-TOKEN[0].val = TOKENval
-TOKEN[0].max = G1
-TOKEN[0].len = G1
-
-UT = ffi.new("octet*")
-UTval = ffi.new("char []", G1)
-UT[0].val = UTval
-UT[0].max = G1
-UT[0].len = G1
-
-U = ffi.new("octet*")
-Uval = ffi.new("char []", G1)
-U[0].val = Uval
-U[0].max = G1
-U[0].len = G1
-
-X = ffi.new("octet*")
-Xval = ffi.new("char []", PGS)
-X[0].val = Xval
-X[0].max = PGS
-X[0].len = PGS
-
-Y = ffi.new("octet*")
-Yval = ffi.new("char []", PGS)
-Y[0].val = Yval
-Y[0].max = PGS
-Y[0].len = PGS
-
-lenEF = 12 * PFS
-E = ffi.new("octet*")
-Eval = ffi.new("char []", lenEF)
-E[0].val = Eval
-E[0].max = lenEF
-E[0].len = lenEF
-
-F = ffi.new("octet*")
-Fval = ffi.new("char []", lenEF)
-F[0].val = Fval
-F[0].max = lenEF
-F[0].len = lenEF
-
-# H(ID)
-HID = ffi.new("octet*")
-HIDval = ffi.new("char []", G1)
-HID[0].val = HIDval
-HID[0].max = G1
-HID[0].len = G1
-
-# H(T|H(ID))
-HTID = ffi.new("octet*")
-HTIDval = ffi.new("char []", G1)
-HTID[0].val = HTIDval
-HTID[0].max = G1
-HTID[0].len = G1
-
-
-class TestMPIN(unittest.TestCase):
-    """Tests M-Pin crypto code"""
-
-    def setUp(self):
-
-        # Form MPin ID
-        endUserData = {
-            "issued": "2013-10-19T06:12:28Z",
-            "userID": "testUser@miracl.com",
-            "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_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'])
-
-if __name__ == '__main__':
-    # Run tests
-    unittest.main()
diff --git a/pythonCFFI/TestMPINAnonInstall.py b/pythonCFFI/TestMPINAnonInstall.py
deleted file mode 100755
index 7d67721..0000000
--- a/pythonCFFI/TestMPINAnonInstall.py
+++ /dev/null
@@ -1,703 +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 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
-CS1[0].max = G1
-CS1[0].len = G1
-
-CS2 = ffi.new("octet*")
-CS2val = ffi.new("char []", G1)
-CS2[0].val = CS2val
-CS2[0].max = G1
-CS2[0].len = G1
-
-SEC = ffi.new("octet*")
-SECval = ffi.new("char []", G1)
-SEC[0].val = SECval
-SEC[0].max = G1
-SEC[0].len = G1
-
-# Server secret and shares
-SS1 = ffi.new("octet*")
-SS1val = ffi.new("char []", G2)
-SS1[0].val = SS1val
-SS1[0].max = G2
-SS1[0].len = G2
-
-SS2 = ffi.new("octet*")
-SS2val = ffi.new("char []", G2)
-SS2[0].val = SS2val
-SS2[0].max = G2
-SS2[0].len = G2
-
-SERVER_SECRET = ffi.new("octet*")
-SERVER_SECRETval = ffi.new("char []", G2)
-SERVER_SECRET[0].val = SERVER_SECRETval
-SERVER_SECRET[0].max = G2
-SERVER_SECRET[0].len = G2
-
-# Time Permit and shares
-TP1 = ffi.new("octet*")
-TP1val = ffi.new("char []", G1)
-TP1[0].val = TP1val
-TP1[0].max = G1
-TP1[0].len = G1
-
-TP2 = ffi.new("octet*")
-TP2val = ffi.new("char []", G1)
-TP2[0].val = TP2val
-TP2[0].max = G1
-TP2[0].len = G1
-
-TIME_PERMIT = ffi.new("octet*")
-TIME_PERMITval = ffi.new("char []", G1)
-TIME_PERMIT[0].val = TIME_PERMITval
-TIME_PERMIT[0].max = G1
-TIME_PERMIT[0].len = G1
-
-# Token stored on computer
-TOKEN = ffi.new("octet*")
-TOKENval = ffi.new("char []", G1)
-TOKEN[0].val = TOKENval
-TOKEN[0].max = G1
-TOKEN[0].len = G1
-
-UT = ffi.new("octet*")
-UTval = ffi.new("char []", G1)
-UT[0].val = UTval
-UT[0].max = G1
-UT[0].len = G1
-
-U = ffi.new("octet*")
-Uval = ffi.new("char []", G1)
-U[0].val = Uval
-U[0].max = G1
-U[0].len = G1
-
-X = ffi.new("octet*")
-Xval = ffi.new("char []", PGS)
-X[0].val = Xval
-X[0].max = PGS
-X[0].len = PGS
-
-Y = ffi.new("octet*")
-Yval = ffi.new("char []", PGS)
-Y[0].val = Yval
-Y[0].max = PGS
-Y[0].len = PGS
-
-lenEF = 12 * PFS
-E = ffi.new("octet*")
-Eval = ffi.new("char []", lenEF)
-E[0].val = Eval
-E[0].max = lenEF
-E[0].len = lenEF
-
-F = ffi.new("octet*")
-Fval = ffi.new("char []", lenEF)
-F[0].val = Fval
-F[0].max = lenEF
-F[0].len = lenEF
-
-# H(ID)
-HID = ffi.new("octet*")
-HIDval = ffi.new("char []", G1)
-HID[0].val = HIDval
-HID[0].max = G1
-HID[0].len = G1
-
-# H(T|H(ID))
-HTID = ffi.new("octet*")
-HTIDval = ffi.new("char []", G1)
-HTID[0].val = HTIDval
-HTID[0].max = G1
-HTID[0].len = G1
-
-
-class TestMPIN(unittest.TestCase):
-    """Tests M-Pin crypto code"""
-
-    def setUp(self):
-
-        # Form MPin ID
-        endUserData = {
-            "issued": "2013-10-19T06:12:28Z",
-            "userID": "testUser@miracl.com",
-            "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_1(self):
-        """test_1 Good PIN and good 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
-        rtn = libmpin.MPIN_SERVER_2(self.date, HID, HTID, Y, SERVER_SECRET, U, UT, SEC, E, F)
-        self.assertEqual(rtn, 0)
-
-    def test_2(self):
-        """test_2 Bad PIN and good token"""
-        PIN1 = 1234
-        PIN2 = 2000
-
-        # 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
-        rtn = libmpin.MPIN_SERVER_2(self.date, HID, HTID, Y, SERVER_SECRET, U, UT, SEC, E, F)
-        self.assertEqual(rtn, -19)
-
-    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 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 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_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)
-
-    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_8(self):
-        """test_8 AES-GCM: Successful encryption and decryption"""
-
-        # 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
-
-        # 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.assertEqual(toHex(TAG1), toHex(TAG2))
-        self.assertEqual(toHex(PLAINTEXT1), toHex(PLAINTEXT2))
-        # print "Output message: %s" % ffi.string(PLAINTEXT2[0].val, PLAINTEXT2[0].len)
-
-    def test_9(self):
-        """test_9 AES-GCM: Failed encryption and decryption by changing a ciphertext 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)
-
-        # Change one byte of ciphertext
-        CIPHERTEXT[0].val[0] = "\xa5"
-
-        # 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
-
-        # 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.assertNotEqual(toHex(PLAINTEXT1), toHex(PLAINTEXT2))
-        # print "Output message: %s" % ffi.string(PLAINTEXT2[0].val, PLAINTEXT2[0].len)
-
-    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))
-
-if __name__ == '__main__':
-    # Run tests
-    unittest.main()
diff --git a/pythonCFFI/TestMPINInstall.py b/pythonCFFI/TestMPINInstall.py
deleted file mode 100755
index 3c36c55..0000000
--- a/pythonCFFI/TestMPINInstall.py
+++ /dev/null
@@ -1,703 +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 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
-CS1[0].max = G1
-CS1[0].len = G1
-
-CS2 = ffi.new("octet*")
-CS2val = ffi.new("char []", G1)
-CS2[0].val = CS2val
-CS2[0].max = G1
-CS2[0].len = G1
-
-SEC = ffi.new("octet*")
-SECval = ffi.new("char []", G1)
-SEC[0].val = SECval
-SEC[0].max = G1
-SEC[0].len = G1
-
-# Server secret and shares
-SS1 = ffi.new("octet*")
-SS1val = ffi.new("char []", G2)
-SS1[0].val = SS1val
-SS1[0].max = G2
-SS1[0].len = G2
-
-SS2 = ffi.new("octet*")
-SS2val = ffi.new("char []", G2)
-SS2[0].val = SS2val
-SS2[0].max = G2
-SS2[0].len = G2
-
-SERVER_SECRET = ffi.new("octet*")
-SERVER_SECRETval = ffi.new("char []", G2)
-SERVER_SECRET[0].val = SERVER_SECRETval
-SERVER_SECRET[0].max = G2
-SERVER_SECRET[0].len = G2
-
-# Time Permit and shares
-TP1 = ffi.new("octet*")
-TP1val = ffi.new("char []", G1)
-TP1[0].val = TP1val
-TP1[0].max = G1
-TP1[0].len = G1
-
-TP2 = ffi.new("octet*")
-TP2val = ffi.new("char []", G1)
-TP2[0].val = TP2val
-TP2[0].max = G1
-TP2[0].len = G1
-
-TIME_PERMIT = ffi.new("octet*")
-TIME_PERMITval = ffi.new("char []", G1)
-TIME_PERMIT[0].val = TIME_PERMITval
-TIME_PERMIT[0].max = G1
-TIME_PERMIT[0].len = G1
-
-# Token stored on computer
-TOKEN = ffi.new("octet*")
-TOKENval = ffi.new("char []", G1)
-TOKEN[0].val = TOKENval
-TOKEN[0].max = G1
-TOKEN[0].len = G1
-
-UT = ffi.new("octet*")
-UTval = ffi.new("char []", G1)
-UT[0].val = UTval
-UT[0].max = G1
-UT[0].len = G1
-
-U = ffi.new("octet*")
-Uval = ffi.new("char []", G1)
-U[0].val = Uval
-U[0].max = G1
-U[0].len = G1
-
-X = ffi.new("octet*")
-Xval = ffi.new("char []", PGS)
-X[0].val = Xval
-X[0].max = PGS
-X[0].len = PGS
-
-Y = ffi.new("octet*")
-Yval = ffi.new("char []", PGS)
-Y[0].val = Yval
-Y[0].max = PGS
-Y[0].len = PGS
-
-lenEF = 12 * PFS
-E = ffi.new("octet*")
-Eval = ffi.new("char []", lenEF)
-E[0].val = Eval
-E[0].max = lenEF
-E[0].len = lenEF
-
-F = ffi.new("octet*")
-Fval = ffi.new("char []", lenEF)
-F[0].val = Fval
-F[0].max = lenEF
-F[0].len = lenEF
-
-# H(ID)
-HID = ffi.new("octet*")
-HIDval = ffi.new("char []", G1)
-HID[0].val = HIDval
-HID[0].max = G1
-HID[0].len = G1
-
-# H(T|H(ID))
-HTID = ffi.new("octet*")
-HTIDval = ffi.new("char []", G1)
-HTID[0].val = HTIDval
-HTID[0].max = G1
-HTID[0].len = G1
-
-
-class TestMPIN(unittest.TestCase):
-    """Tests M-Pin crypto code"""
-
-    def setUp(self):
-
-        # Form MPin ID
-        endUserData = {
-            "issued": "2013-10-19T06:12:28Z",
-            "userID": "testUser@miracl.com",
-            "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_1(self):
-        """test_1 Good PIN and good 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.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_2(self):
-        """test_2 Bad PIN and good token"""
-        PIN1 = 1234
-        PIN2 = 2000
-
-        # 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.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, -19)
-
-    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.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 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 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_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)
-
-    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_8(self):
-        """test_8 AES-GCM: Successful encryption and decryption"""
-
-        # 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
-
-        # 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.assertEqual(toHex(TAG1), toHex(TAG2))
-        self.assertEqual(toHex(PLAINTEXT1), toHex(PLAINTEXT2))
-        # print "Output message: %s" % ffi.string(PLAINTEXT2[0].val, PLAINTEXT2[0].len)
-
-    def test_9(self):
-        """test_9 AES-GCM: Failed encryption and decryption by changing a ciphertext 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)
-
-        # Change one byte of ciphertext
-        CIPHERTEXT[0].val[0] = "\xa5"
-
-        # 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
-
-        # 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.assertNotEqual(toHex(PLAINTEXT1), toHex(PLAINTEXT2))
-        # print "Output message: %s" % ffi.string(PLAINTEXT2[0].val, PLAINTEXT2[0].len)
-
-    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))
-
-if __name__ == '__main__':
-    # Run tests
-    unittest.main()
diff --git a/pythonCFFI/TimeMPIN.py b/pythonCFFI/TimeMPIN.py
deleted file mode 100755
index 5273322..0000000
--- a/pythonCFFI/TimeMPIN.py
+++ /dev/null
@@ -1,331 +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 sys
-import timeit
-import warnings
-
-from mpin import ffi, G1, G2, HASH_BYTES, libmpin, PGS, toHex
-
-warnings.filterwarnings("ignore")
-
-
-def time_func(stmt, n=10, setup='from __main__ import *'):
-    t = timeit.Timer(stmt, setup)
-    total_time = t.timeit(n)
-    iter_time = total_time / n
-    iter_per_sec = n / total_time
-    print "func:%s nIter:%s total_time:%s iter_time:%s iter_per_sec: %s" % (stmt, n, total_time, iter_time, iter_per_sec)
-
-if (len(sys.argv) == 2) and (sys.argv[1] == "DEBUG"):
-    DEBUG = True
-else:
-    DEBUG = False
-
-nIter = 1000
-
-if __name__ == "__main__":
-    # Print hex values
-    DEBUG = False
-    MULTI_PASS = False
-
-    # Seed
-    seedHex = "79dd3f23c70bb529a8e3b221cf62da0dd4bd3ca35bd0c515cd9cde5ffa6a5c4d"
-    seed = seedHex.decode("hex")
-
-    # Identity
-    identity = "alice@miracl.com"
-    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
-    MS2[0].max = PGS
-    MS2[0].len = PGS
-
-    # 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
-
-    # Client secret and shares
-    CS1 = ffi.new("octet*")
-    CS1val = ffi.new("char []", G1)
-    CS1[0].val = CS1val
-    CS1[0].max = G1
-    CS1[0].len = G1
-
-    CS2 = ffi.new("octet*")
-    CS2val = ffi.new("char []", G1)
-    CS2[0].val = CS2val
-    CS2[0].max = G1
-    CS2[0].len = G1
-
-    SEC = ffi.new("octet*")
-    SECval = ffi.new("char []", G1)
-    SEC[0].val = SECval
-    SEC[0].max = G1
-    SEC[0].len = G1
-
-    # Server secret and shares
-    SS1 = ffi.new("octet*")
-    SS1val = ffi.new("char []", G2)
-    SS1[0].val = SS1val
-    SS1[0].max = G2
-    SS1[0].len = G2
-
-    SS2 = ffi.new("octet*")
-    SS2val = ffi.new("char []", G2)
-    SS2[0].val = SS2val
-    SS2[0].max = G2
-    SS2[0].len = G2
-
-    SERVER_SECRET = ffi.new("octet*")
-    SERVER_SECRETval = ffi.new("char []", G2)
-    SERVER_SECRET[0].val = SERVER_SECRETval
-    SERVER_SECRET[0].max = G2
-    SERVER_SECRET[0].len = G2
-
-    # Time Permit and shares
-    TP1 = ffi.new("octet*")
-    TP1val = ffi.new("char []", G1)
-    TP1[0].val = TP1val
-    TP1[0].max = G1
-    TP1[0].len = G1
-
-    TP2 = ffi.new("octet*")
-    TP2val = ffi.new("char []", G1)
-    TP2[0].val = TP2val
-    TP2[0].max = G1
-    TP2[0].len = G1
-
-    TIME_PERMIT = ffi.new("octet*")
-    TIME_PERMITval = ffi.new("char []", G1)
-    TIME_PERMIT[0].val = TIME_PERMITval
-    TIME_PERMIT[0].max = G1
-    TIME_PERMIT[0].len = G1
-
-    # Token stored on computer
-    TOKEN = ffi.new("octet*")
-    TOKENval = ffi.new("char []", G1)
-    TOKEN[0].val = TOKENval
-    TOKEN[0].max = G1
-    TOKEN[0].len = G1
-
-    # H(ID)
-    HID = ffi.new("octet*")
-    HIDval = ffi.new("char []", G1)
-    HID[0].val = HIDval
-    HID[0].max = G1
-    HID[0].len = G1
-
-    # H(T|H(ID))
-    HTID = ffi.new("octet*")
-    HTIDval = ffi.new("char []", G1)
-    HTID[0].val = HTIDval
-    HTID[0].max = G1
-    HTID[0].len = G1
-
-    UT = ffi.new("octet*")
-    UTval = ffi.new("char []", G1)
-    UT[0].val = UTval
-    UT[0].max = G1
-    UT[0].len = G1
-
-    U = ffi.new("octet*")
-    Uval = ffi.new("char []", G1)
-    U[0].val = Uval
-    U[0].max = G1
-    U[0].len = G1
-
-    X = ffi.new("octet*")
-    Xval = ffi.new("char []", PGS)
-    X[0].val = Xval
-    X[0].max = PGS
-    X[0].len = PGS
-
-    Y = ffi.new("octet*")
-    Yval = ffi.new("char []", PGS)
-    Y[0].val = Yval
-    Y[0].max = PGS
-    Y[0].len = PGS
-
-    E = ffi.NULL
-    F = ffi.NULL
-
-    date = libmpin.MPIN_today()
-    if date:
-        HID = ffi.NULL
-        U = ffi.NULL
-    else:
-        HTID = ffi.NULL
-        UT = ffi.NULL
-
-    # Assign a seed value
-    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)
-    if DEBUG:
-        print "RAW: %s" % toHex(RAW)
-
-    # random number generator
-    RNG = ffi.new("csprng*")
-    libmpin.MPIN_CREATE_CSPRNG(RNG, RAW)
-
-    # Hash MPIN_ID
-    libmpin.MPIN_HASH_ID(MPIN_ID, HASH_MPIN_ID)
-    if DEBUG:
-        print "MPIN_ID: %s" % toHex(MPIN_ID)
-        print "HASH_MPIN_ID: %s" % toHex(HASH_MPIN_ID)
-
-    # Generate master secret for MIRACL and Customer
-    rtn = libmpin.MPIN_RANDOM_GENERATE(RNG, MS1)
-    if rtn != 0:
-        print "libmpin.MPIN_RANDOM_GENERATE(RNG,MS1) Error %s", rtn
-    rtn = libmpin.MPIN_RANDOM_GENERATE(RNG, MS2)
-    if rtn != 0:
-        print "libmpin.MPIN_RANDOM_GENERATE(RNG,MS2) Error %s" % rtn
-    if DEBUG:
-        print "MS1: %s" % toHex(MS1)
-        print "MS2: %s" % toHex(MS2)
-
-    # Generate server secret shares
-    rtn = libmpin.MPIN_GET_SERVER_SECRET(MS1, SS1)
-    if rtn != 0:
-        print "libmpin.MPIN_GET_SERVER_SECRET(MS1,SS1) Error %s" % rtn
-    rtn = libmpin.MPIN_GET_SERVER_SECRET(MS2, SS2)
-    if rtn != 0:
-        print "libmpin.MPIN_GET_SERVER_SECRET(MS2,SS2) Error %s" % rtn
-    if DEBUG:
-        print "SS1: %s" % toHex(SS1)
-        print "SS2: %s" % toHex(SS2)
-
-    # Combine server secret shares
-    rtn = libmpin.MPIN_RECOMBINE_G2(SS1, SS2, SERVER_SECRET)
-    if rtn != 0:
-        print "libmpin.MPIN_RECOMBINE_G2( SS1, SS2, SERVER_SECRET) Error %s" % rtn
-    if DEBUG:
-        print "SERVER_SECRET: %s" % toHex(SERVER_SECRET)
-
-    # Generate client secret shares
-    rtn = libmpin.MPIN_GET_CLIENT_SECRET(MS1, HASH_MPIN_ID, CS1)
-    if rtn != 0:
-        print "libmpin.MPIN_GET_CLIENT_SECRET(MS1,HASH_MPIN_ID,CS1) Error %s" % rtn
-    rtn = libmpin.MPIN_GET_CLIENT_SECRET(MS2, HASH_MPIN_ID, CS2)
-    if rtn != 0:
-        print "libmpin.MPIN_GET_CLIENT_SECRET(MS2,HASH_MPIN_ID,CS2) Error %s" % rtn
-    if DEBUG:
-        print "CS1: %s" % toHex(CS1)
-        print "CS2: %s" % toHex(CS2)
-
-    # Combine client secret shares : TOKEN is the full client secret
-    rtn = libmpin.MPIN_RECOMBINE_G1(CS1, CS2, TOKEN)
-    if rtn != 0:
-        print "libmpin.MPIN_RECOMBINE_G1( CS1, CS2, TOKEN) Error %s" % rtn
-    print "Client Secret: %s" % toHex(TOKEN)
-
-    # Generate Time Permit shares
-    if DEBUG:
-        print "Date %s" % date
-    rtn = libmpin.MPIN_GET_CLIENT_PERMIT(date, MS1, HASH_MPIN_ID, TP1)
-    if rtn != 0:
-        print "libmpin.MPIN_GET_CLIENT_PERMIT(date,MS1,HASH_MPIN_ID,TP1) Error %s" % rtn
-    rtn = libmpin.MPIN_GET_CLIENT_PERMIT(date, MS2, HASH_MPIN_ID, TP2)
-    if rtn != 0:
-        print "libmpin.MPIN_GET_CLIENT_PERMIT(date,MS2,HASH_MPIN_ID,TP2) Error %s" % rtn
-    if DEBUG:
-        print "TP1: %s" % toHex(TP1)
-        print "TP2: %s" % toHex(TP2)
-
-    # Combine Time Permit shares
-    rtn = libmpin.MPIN_RECOMBINE_G1(TP1, TP2, TIME_PERMIT)
-    if rtn != 0:
-        print "libmpin.MPIN_RECOMBINE_G1(TP1, TP2, TIME_PERMIT) Error %s" % rtn
-    if DEBUG:
-        print "TIME_PERMIT: %s" % toHex(TIME_PERMIT)
-
-    # Client extracts PIN from secret to create Token
-    PIN = 1234
-    rtn = libmpin.MPIN_EXTRACT_PIN(MPIN_ID, PIN, TOKEN)
-    if rtn != 0:
-        print "libmpin.MPIN_EXTRACT_PIN( MPIN_ID, PIN, TOKEN) Error %s" % rtn
-    print "Token: %s" % toHex(TOKEN)
-
-    if MULTI_PASS:
-        # Client first pass
-        rtn = libmpin.MPIN_CLIENT_1(date, MPIN_ID, RNG, X, PIN, TOKEN, SEC, U, UT, TIME_PERMIT)
-        if rtn != 0:
-            print "MPIN_CLIENT_1  ERROR %s" % rtn
-        if DEBUG:
-            print "X: %s" % toHex(X)
-
-        # 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.
-        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)
-        if rtn != 0:
-            print "libmpin.MPIN_RANDOM_GENERATE(RNG,Y) Error %s" % rtn
-        if DEBUG:
-            print "Y: %s" % toHex(Y)
-
-        # Client second pass
-        rtn = libmpin.MPIN_CLIENT_2(X, Y, SEC)
-        if rtn != 0:
-            print "libmpin.MPIN_CLIENT_2(X,Y,SEC) Error %s" % rtn
-        if DEBUG:
-            print "V: %s" % toHex(SEC)
-
-        # Server second pass
-        rtn = libmpin.MPIN_SERVER_2(date, HID, HTID, Y, SERVER_SECRET, U, UT, SEC, E, F)
-        if rtn != 0:
-            print "ERROR: Multi Pass %s is not authenticated" % identity
-        else:
-            print "SUCCESS: Multi Pass %s is authenticated" % identity
-    else:
-        # Client
-        TimeValue = libmpin.MPIN_GET_TIME()
-        time_func('libmpin.MPIN_CLIENT(date, MPIN_ID, RNG, X, PIN, TOKEN, SEC, U, UT, TIME_PERMIT, ffi.NULL, TimeValue, Y)', nIter)
-        if DEBUG:
-            print "X: %s" % toHex(X)
-
-        # Server
-        time_func('libmpin.MPIN_SERVER(date, HID, HTID, Y, SERVER_SECRET, U, UT, SEC, E, F, MPIN_ID, ffi.NULL, TimeValue)', nIter)
-        rtn = libmpin.MPIN_SERVER(date, HID, HTID, Y, SERVER_SECRET, U, UT, SEC, E, F, MPIN_ID, ffi.NULL, TimeValue)
-        if rtn != 0:
-            print "ERROR: Single Pass %s is not authenticated" % identity
-        else:
-            print "SUCCESS: Single Pass %s is authenticated" % identity
diff --git a/pythonCFFI/TimeMPINFull.py b/pythonCFFI/TimeMPINFull.py
deleted file mode 100755
index 6ca5022..0000000
--- a/pythonCFFI/TimeMPINFull.py
+++ /dev/null
@@ -1,444 +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 sys
-import timeit
-import warnings
-
-from mpin import ffi, G1, G2, HASH_BYTES, libmpin, PAS, PFS, PGS, toHex
-
-warnings.filterwarnings("ignore")
-
-
-def time_func(stmt, n=10, setup='from __main__ import *'):
-    t = timeit.Timer(stmt, setup)
-    exec_time = t.timeit(n)
-    iter_time = exec_time / n
-    iter_per_sec = n / exec_time
-    print "func:%s nIter:%s exec_time:%s iter_time:%s iter_per_sec: %s" % (stmt, n, exec_time, iter_time, iter_per_sec)
-    return exec_time
-
-if (len(sys.argv) == 2) and (sys.argv[1] == "DEBUG"):
-    DEBUG = True
-else:
-    DEBUG = False
-
-nIter = 100
-
-if __name__ == "__main__":
-    # Print hex values
-    DEBUG = False
-    SINGLE_PASS = True
-    TIME_PERMITS = True
-
-    if TIME_PERMITS:
-        date = libmpin.MPIN_today()
-    else:
-        date = 0
-
-    # Seed
-    seedHex = "79dd3f23c70bb529a8e3b221cf62da0dd4bd3ca35bd0c515cd9cde5ffa6a5c4d"
-    seed = seedHex.decode("hex")
-
-    # Identity
-    identity = "alice@miracl.com"
-    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
-    MS2[0].max = PGS
-    MS2[0].len = PGS
-
-    # 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
-
-    # Client secret and shares
-    CS1 = ffi.new("octet*")
-    CS1val = ffi.new("char []", G1)
-    CS1[0].val = CS1val
-    CS1[0].max = G1
-    CS1[0].len = G1
-
-    CS2 = ffi.new("octet*")
-    CS2val = ffi.new("char []", G1)
-    CS2[0].val = CS2val
-    CS2[0].max = G1
-    CS2[0].len = G1
-
-    SEC = ffi.new("octet*")
-    SECval = ffi.new("char []", G1)
-    SEC[0].val = SECval
-    SEC[0].max = G1
-    SEC[0].len = G1
-
-    # Server secret and shares
-    SS1 = ffi.new("octet*")
-    SS1val = ffi.new("char []", G2)
-    SS1[0].val = SS1val
-    SS1[0].max = G2
-    SS1[0].len = G2
-
-    SS2 = ffi.new("octet*")
-    SS2val = ffi.new("char []", G2)
-    SS2[0].val = SS2val
-    SS2[0].max = G2
-    SS2[0].len = G2
-
-    SERVER_SECRET = ffi.new("octet*")
-    SERVER_SECRETval = ffi.new("char []", G2)
-    SERVER_SECRET[0].val = SERVER_SECRETval
-    SERVER_SECRET[0].max = G2
-    SERVER_SECRET[0].len = G2
-
-    # Time Permit and shares
-    TP1 = ffi.new("octet*")
-    TP1val = ffi.new("char []", G1)
-    TP1[0].val = TP1val
-    TP1[0].max = G1
-    TP1[0].len = G1
-
-    TP2 = ffi.new("octet*")
-    TP2val = ffi.new("char []", G1)
-    TP2[0].val = TP2val
-    TP2[0].max = G1
-    TP2[0].len = G1
-
-    TIME_PERMIT = ffi.new("octet*")
-    TIME_PERMITval = ffi.new("char []", G1)
-    TIME_PERMIT[0].val = TIME_PERMITval
-    TIME_PERMIT[0].max = G1
-    TIME_PERMIT[0].len = G1
-
-    # Token stored on computer
-    TOKEN = ffi.new("octet*")
-    TOKENval = ffi.new("char []", G1)
-    TOKEN[0].val = TOKENval
-    TOKEN[0].max = G1
-    TOKEN[0].len = G1
-
-    # H(ID)
-    HID = ffi.new("octet*")
-    HIDval = ffi.new("char []", G1)
-    HID[0].val = HIDval
-    HID[0].max = G1
-    HID[0].len = G1
-
-    # H(T|H(ID))
-    HTID = ffi.new("octet*")
-    HTIDval = ffi.new("char []", G1)
-    HTID[0].val = HTIDval
-    HTID[0].max = G1
-    HTID[0].len = G1
-
-    UT = ffi.new("octet*")
-    UTval = ffi.new("char []", G1)
-    UT[0].val = UTval
-    UT[0].max = G1
-    UT[0].len = G1
-
-    U = ffi.new("octet*")
-    Uval = ffi.new("char []", G1)
-    U[0].val = Uval
-    U[0].max = G1
-    U[0].len = G1
-
-    X = ffi.new("octet*")
-    Xval = ffi.new("char []", PGS)
-    X[0].val = Xval
-    X[0].max = PGS
-    X[0].len = PGS
-
-    Y = ffi.new("octet*")
-    Yval = ffi.new("char []", PGS)
-    Y[0].val = Yval
-    Y[0].max = PGS
-    Y[0].len = PGS
-
-    E = ffi.NULL
-    F = ffi.NULL
-
-    # MPIN Full
-    R = ffi.new("octet*")
-    Rval = ffi.new("char []", PGS)
-    R[0].val = Rval
-    R[0].max = PGS
-    R[0].len = PGS
-
-    W = ffi.new("octet*")
-    Wval = ffi.new("char []", PGS)
-    W[0].val = Wval
-    W[0].max = PGS
-    W[0].len = PGS
-
-    Z = ffi.new("octet*")
-    Zval = ffi.new("char []", G1)
-    Z[0].val = Zval
-    Z[0].max = G1
-    Z[0].len = G1
-
-    T = ffi.new("octet*")
-    Tval = ffi.new("char []", G1)
-    T[0].val = Tval
-    T[0].max = G1
-    T[0].len = G1
-
-    TATE1 = ffi.new("octet*")
-    TATE1val = ffi.new("char []", 12*PFS)
-    TATE1[0].val = TATE1val
-    TATE1[0].max = 12*PFS
-    TATE1[0].len = 12*PFS
-
-    TATE2 = ffi.new("octet*")
-    TATE2val = ffi.new("char []", 12*PFS)
-    TATE2[0].val = TATE2val
-    TATE2[0].max = 12*PFS
-    TATE2[0].len = 12*PFS
-
-    SK = ffi.new("octet*")
-    SKval = ffi.new("char []", PAS)
-    SK[0].val = SKval
-    SK[0].max = PAS
-    SK[0].len = PAS
-
-    CK = ffi.new("octet*")
-    CKval = ffi.new("char []", PAS)
-    CK[0].val = CKval
-    CK[0].max = PAS
-    CK[0].len = PAS
-
-    if date:
-        HID = ffi.NULL
-        U = ffi.NULL
-        prHID = HTID
-    else:
-        HTID = ffi.NULL
-        UT = ffi.NULL
-        prHID = HID
-
-    # Assign a seed value
-    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)
-    if DEBUG:
-        print "RAW: %s" % toHex(RAW)
-
-    # random number generator
-    RNG = ffi.new("csprng*")
-    libmpin.MPIN_CREATE_CSPRNG(RNG, RAW)
-
-    # Hash MPIN_ID
-    libmpin.MPIN_HASH_ID(MPIN_ID,  HASH_MPIN_ID)
-    if DEBUG:
-        print "MPIN_ID: %s" % toHex(MPIN_ID)
-        print "HASH_MPIN_ID: %s" % toHex(HASH_MPIN_ID)
-
-    # Generate master secret for MIRACL and Customer
-    rtn = libmpin.MPIN_RANDOM_GENERATE(RNG, MS1)
-    if rtn != 0:
-        print "libmpin.MPIN_RANDOM_GENERATE(RNG,MS1) Error %s", rtn
-    rtn = libmpin.MPIN_RANDOM_GENERATE(RNG, MS2)
-    if rtn != 0:
-        print "libmpin.MPIN_RANDOM_GENERATE(RNG,MS2) Error %s" % rtn
-    if DEBUG:
-        print "MS1: %s" % toHex(MS1)
-        print "MS2: %s" % toHex(MS2)
-
-    # Generate server secret shares
-    rtn = libmpin.MPIN_GET_SERVER_SECRET(MS1, SS1)
-    if rtn != 0:
-        print "libmpin.MPIN_GET_SERVER_SECRET(MS1,SS1) Error %s" % rtn
-    rtn = libmpin.MPIN_GET_SERVER_SECRET(MS2, SS2)
-    if rtn != 0:
-        print "libmpin.MPIN_GET_SERVER_SECRET(MS2,SS2) Error %s" % rtn
-    if DEBUG:
-        print "SS1: %s" % toHex(SS1)
-        print "SS2: %s" % toHex(SS2)
-
-    # Combine server secret shares
-    rtn = libmpin.MPIN_RECOMBINE_G2(SS1, SS2, SERVER_SECRET)
-    if rtn != 0:
-        print "libmpin.MPIN_RECOMBINE_G2( SS1, SS2, SERVER_SECRET) Error %s" % rtn
-    if DEBUG:
-        print "SERVER_SECRET: %s" % toHex(SERVER_SECRET)
-
-    # Generate client secret shares
-    rtn = libmpin.MPIN_GET_CLIENT_SECRET(MS1, HASH_MPIN_ID, CS1)
-    if rtn != 0:
-        print "libmpin.MPIN_GET_CLIENT_SECRET(MS1,HASH_MPIN_ID,CS1) Error %s" % rtn
-    rtn = libmpin.MPIN_GET_CLIENT_SECRET(MS2, HASH_MPIN_ID, CS2)
-    if rtn != 0:
-        print "libmpin.MPIN_GET_CLIENT_SECRET(MS2,HASH_MPIN_ID,CS2) Error %s" % rtn
-    if DEBUG:
-        print "CS1: %s" % toHex(CS1)
-        print "CS2: %s" % toHex(CS2)
-
-    # Combine client secret shares : TOKEN is the full client secret
-    rtn = libmpin.MPIN_RECOMBINE_G1(CS1, CS2, TOKEN)
-    if rtn != 0:
-        print "libmpin.MPIN_RECOMBINE_G1( CS1, CS2, TOKEN) Error %s" % rtn
-    print "Client Secret: %s" % toHex(TOKEN)
-
-    # Generate Time Permit shares
-    if DEBUG:
-        print "Date %s" % date
-    rtn = libmpin.MPIN_GET_CLIENT_PERMIT(date, MS1, HASH_MPIN_ID, TP1)
-    if rtn != 0:
-        print "libmpin.MPIN_GET_CLIENT_PERMIT(date,MS1,HASH_MPIN_ID,TP1) Error %s" % rtn
-    rtn = libmpin.MPIN_GET_CLIENT_PERMIT(date, MS2, HASH_MPIN_ID, TP2)
-    if rtn != 0:
-        print "libmpin.MPIN_GET_CLIENT_PERMIT(date,MS2,HASH_MPIN_ID,TP2) Error %s" % rtn
-    if DEBUG:
-        print "TP1: %s" % toHex(TP1)
-        print "TP2: %s" % toHex(TP2)
-
-    # Combine Time Permit shares
-    rtn = libmpin.MPIN_RECOMBINE_G1(TP1, TP2, TIME_PERMIT)
-    if rtn != 0:
-        print "libmpin.MPIN_RECOMBINE_G1(TP1, TP2, TIME_PERMIT) Error %s" % rtn
-    if DEBUG:
-        print "TIME_PERMIT: %s" % toHex(TIME_PERMIT)
-
-    # Client extracts PIN from secret to create Token
-    PIN = 1234
-    rtn = libmpin.MPIN_EXTRACT_PIN(MPIN_ID, PIN, TOKEN)
-    if rtn != 0:
-        print "libmpin.MPIN_EXTRACT_PIN( MPIN_ID, PIN, TOKEN) Error %s" % rtn
-    print "Token: %s" % toHex(TOKEN)
-
-    if SINGLE_PASS:
-        print "M-Pin Single Pass"
-        clientTime = 0
-        serverTime = 0
-        TimeValue = libmpin.MPIN_GET_TIME()
-        # Client precomputation
-        time_func('libmpin.MPIN_PRECOMPUTE(TOKEN,HASH_MPIN_ID,TATE1,TATE2)', nIter)
-
-        # Client MPIN
-        ct1 = time_func('libmpin.MPIN_CLIENT(date, MPIN_ID, RNG, X, PIN, TOKEN, SEC, U, UT, TIME_PERMIT, ffi.NULL, TimeValue, Y)', nIter)
-        clientTime = clientTime + ct1
-        if DEBUG:
-            print "X: %s" % toHex(X)
-
-        # Client sends Z=r.ID to Server
-        ct2 = time_func('libmpin.MPIN_GET_G1_MULTIPLE(RNG,1,R,HASH_MPIN_ID,Z)', nIter)
-        clientTime = clientTime + ct2
-
-        # Server MPIN
-        st1 = time_func('libmpin.MPIN_SERVER(date, HID, HTID, Y, SERVER_SECRET, U, UT, SEC, E, F, MPIN_ID, ffi.NULL, TimeValue)', nIter)
-        serverTime = serverTime + st1
-        rtn = libmpin.MPIN_SERVER(date, HID, HTID, Y, SERVER_SECRET, U, UT, SEC, E, F, MPIN_ID, ffi.NULL, TimeValue)
-        if rtn != 0:
-            print "ERROR: Single Pass %s is not authenticated" % identity
-        else:
-            print "SUCCESS: Single Pass %s is authenticated" % identity
-
-        # Server sends T=w.ID to client
-        st2 = time_func('libmpin.MPIN_GET_G1_MULTIPLE(RNG,0,W,prHID,T)', nIter)
-        serverTime = serverTime + st2
-        print "T: %s" % toHex(T)
-
-        ct3 = time_func('libmpin.MPIN_CLIENT_KEY(TATE1,TATE2,PIN,R,X,T,CK)', nIter)
-        clientTime = clientTime + ct3
-        print "Client Key: %s" % toHex(CK)
-
-        st3 = time_func('libmpin.MPIN_SERVER_KEY(Z,SERVER_SECRET,W,U,UT,SK)', nIter)
-        serverTime = serverTime + st3
-        print "Server Key: %s" % toHex(SK)
-
-        assert toHex(CK) == toHex(SK), "CK == SK"
-
-        iter_time = clientTime / nIter
-        iter_per_sec = nIter / clientTime
-        print "Client nIter:%s time:%s iter_time:%s iter_per_sec: %s" % (nIter, clientTime, iter_time, iter_per_sec)
-        iter_time = serverTime / nIter
-        iter_per_sec = nIter / serverTime
-        print "Server nIter:%s time:%s iter_time:%s iter_per_sec: %s" % (nIter, serverTime, iter_time, iter_per_sec)
-
-    else:
-        print "M-Pin Multi Pass"
-        rtn = libmpin.MPIN_PRECOMPUTE(TOKEN, HASH_MPIN_ID, TATE1, TATE2)
-        if rtn != 0:
-            print "MPIN_PERCOMPUTE  ERROR %s" % rtn
-
-        # Client first pass
-        rtn = libmpin.MPIN_CLIENT_1(date, MPIN_ID, RNG, X, PIN, TOKEN, SEC, U, UT, TIME_PERMIT)
-        if rtn != 0:
-            print "MPIN_CLIENT_1  ERROR %s" % rtn
-        if DEBUG:
-            print "X: %s" % toHex(X)
-
-        # 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.
-        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)
-        if rtn != 0:
-            print "libmpin.MPIN_RANDOM_GENERATE(RNG,Y) Error %s" % rtn
-        if DEBUG:
-            print "Y: %s" % toHex(Y)
-
-        # Client second pass
-        rtn = libmpin.MPIN_CLIENT_2(X, Y, SEC)
-        if rtn != 0:
-            print "libmpin.MPIN_CLIENT_2(X,Y,SEC) Error %s" % rtn
-        if DEBUG:
-            print "V: %s" % toHex(SEC)
-
-        # Server second pass
-        rtn = libmpin.MPIN_SERVER_2(date, HID, HTID, Y, SERVER_SECRET, U, UT, SEC, E, F)
-        if rtn != 0:
-            print "ERROR: Multi Pass %s is not authenticated" % identity
-        else:
-            print "SUCCESS: Multi Pass %s is authenticated" % identity
-
-        # Server sends T=w.ID to client
-        libmpin.MPIN_GET_G1_MULTIPLE(RNG, 0, W, prHID, T)
-
-        # Client sends Z=r.ID to Server
-        rtn = libmpin.MPIN_GET_G1_MULTIPLE(RNG, 1, R, HASH_MPIN_ID, Z)
-        if rtn != 0:
-            print "ERROR: Generating Z %s" % rtn
-
-        libmpin.MPIN_CLIENT_KEY(TATE1, TATE2, PIN, R, X, T, CK)
-        print "Client Key: %s" % toHex(CK)
-
-        libmpin.MPIN_SERVER_KEY(Z, SERVER_SECRET, W, U, UT, SK)
-        print "Server Key: %s" % toHex(SK)
-
-        assert toHex(CK) == toHex(SK), "CK == SK"
diff --git a/pythonCFFI/mpin.py b/pythonCFFI/mpin.py
deleted file mode 100755
index 7032e45..0000000
--- a/pythonCFFI/mpin.py
+++ /dev/null
@@ -1,572 +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.
-"""
-
-
-"""
-mpin
-
-This module use cffi to access the c functions in the mpin library.
-
-There is also an example usage program in this file.
-
-"""
-import cffi
-import platform
-
-# MPIN Group Size
-PGS = 32
-# MPIN Field Size
-PFS = 32
-G1 = 2*PFS + 1
-G2 = 4*PFS
-# Hash Size
-HASH_BYTES = 32
-# AES-GCM IV length
-IVL = 12
-# MPIN Symmetric Key Size
-PAS = 16
-
-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 unsigned int MPIN_GET_TIME(void);
-extern void MPIN_Y(int,octet *,octet *);
-extern void MPIN_HASH_ID(octet *,octet *);
-extern int MPIN_EXTRACT_PIN(octet *,int,octet *);
-extern int MPIN_CLIENT(int d,octet *ID,csprng *R,octet *x,int pin,octet *T,octet *V,octet *U,octet *UT,octet *TP, octet* MESSAGE, int t, octet *y);
-extern int MPIN_CLIENT_1(int,octet *,csprng *,octet *,int,octet *,octet *,octet *,octet *,octet *);
-extern int MPIN_RANDOM_GENERATE(csprng *,octet *);
-extern int MPIN_CLIENT_2(octet *,octet *,octet *);
-extern void MPIN_SERVER_1(int,octet *,octet *,octet *);
-extern int MPIN_SERVER_2(int,octet *,octet *,octet *,octet *,octet *,octet *,octet *,octet *,octet *);
-extern int MPIN_SERVER(int d,octet *HID,octet *HTID,octet *y,octet *SS,octet *U,octet *UT,octet *V,octet *E,octet *F,octet *ID,octet *MESSAGE, int t);
-extern int MPIN_RECOMBINE_G1(octet *,octet *,octet *);
-extern int MPIN_RECOMBINE_G2(octet *,octet *,octet *);
-extern int MPIN_KANGAROO(octet *,octet *);
-
-extern int MPIN_ENCODING(csprng *,octet *);
-extern int MPIN_DECODING(octet *);
-
-extern unsigned int MPIN_today(void);
-extern void MPIN_CREATE_CSPRNG(csprng *,octet *);
-extern void MPIN_KILL_CSPRNG(csprng *);
-extern int MPIN_PRECOMPUTE(octet *,octet *,octet *,octet *);
-extern int MPIN_SERVER_KEY(octet *Z,octet *SS,octet *w,octet *p,octet *I,octet *U,octet *UT,octet *K);
-extern int MPIN_CLIENT_KEY(octet *g1,octet *g2,int pin,octet *r,octet *x,octet *p,octet *T,octet *K);
-extern int MPIN_GET_G1_MULTIPLE(csprng *,int,octet *,octet *,octet *);
-extern int MPIN_GET_CLIENT_SECRET(octet *,octet *,octet *);
-extern int MPIN_GET_CLIENT_PERMIT(int,octet *,octet *,octet *);
-extern int MPIN_GET_SERVER_SECRET(octet *,octet *);
-extern int MPIN_TEST_PAIRING(octet *,octet *);
-extern void hex2bytes(char *hex, char *bin);
-extern void generateRandom(csprng*, octet*);
-extern int generateOTP(csprng*);
-extern void MPIN_AES_GCM_ENCRYPT(octet *K,octet *IV,octet *H,octet *P,octet *C,octet *T);
-extern void MPIN_AES_GCM_DECRYPT(octet *K,octet *IV,octet *H,octet *C,octet *P,octet *T);
-extern void MPIN_HASH_ALL(octet *I,octet *U,octet *CU,octet *V,octet *Y,octet *R,octet *W,octet *H);
-
-""")
-
-if (platform.system() == 'Windows'):
-    libmpin = ffi.dlopen("libmpin.dll")
-elif (platform.system() == 'Darwin'):
-    libmpin = ffi.dlopen("libmpin.dylib")
-else:
-    libmpin = ffi.dlopen("libmpin.so")
-
-
-def toHex(octetValue):
-    """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::
-
-        octetValue. An octet type
-
-    Returns::
-
-        String
-
-    Raises:
-        Exception
-    """
-    i = 0
-    val = []
-    while i < octetValue[0].len:
-        val.append(octetValue[0].val[i])
-        i = i+1
-    return ''.join(val).encode("hex")
-
-if __name__ == "__main__":
-    # Print hex values
-    DEBUG = False
-    SINGLE_PASS = False
-    TIME_PERMITS = True
-    MPIN_FULL = False
-    PIN_ERROR = True
-    USE_ANONYMOUS = False
-
-    if TIME_PERMITS:
-        date = libmpin.MPIN_today()
-    else:
-        date = 0
-
-    # Seed
-    seedHex = "3ade3d4a5c698e8910bf92f25d97ceeb7c25ed838901a5cb5db2cf25434c1fe76c7f79b7af2e5e1e4988e4294dbd9bd9fa3960197fb7aec373609fb890d74b16a4b14b2ae7e23b75f15d36c21791272372863c4f8af39980283ae69a79cf4e48e908f9e0"
-    seed = seedHex.decode("hex")
-
-    # Identity
-    identity = raw_input("Please enter 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
-    MS2[0].max = PGS
-    MS2[0].len = PGS
-
-    # 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
-
-    # Client secret and shares
-    CS1 = ffi.new("octet*")
-    CS1val = ffi.new("char []", G1)
-    CS1[0].val = CS1val
-    CS1[0].max = G1
-    CS1[0].len = G1
-
-    CS2 = ffi.new("octet*")
-    CS2val = ffi.new("char []", G1)
-    CS2[0].val = CS2val
-    CS2[0].max = G1
-    CS2[0].len = G1
-
-    SEC = ffi.new("octet*")
-    SECval = ffi.new("char []", G1)
-    SEC[0].val = SECval
-    SEC[0].max = G1
-    SEC[0].len = G1
-
-    # Server secret and shares
-    SS1 = ffi.new("octet*")
-    SS1val = ffi.new("char []", G2)
-    SS1[0].val = SS1val
-    SS1[0].max = G2
-    SS1[0].len = G2
-
-    SS2 = ffi.new("octet*")
-    SS2val = ffi.new("char []", G2)
-    SS2[0].val = SS2val
-    SS2[0].max = G2
-    SS2[0].len = G2
-
-    SERVER_SECRET = ffi.new("octet*")
-    SERVER_SECRETval = ffi.new("char []", G2)
-    SERVER_SECRET[0].val = SERVER_SECRETval
-    SERVER_SECRET[0].max = G2
-    SERVER_SECRET[0].len = G2
-
-    # Time Permit and shares
-    TP1 = ffi.new("octet*")
-    TP1val = ffi.new("char []", G1)
-    TP1[0].val = TP1val
-    TP1[0].max = G1
-    TP1[0].len = G1
-
-    TP2 = ffi.new("octet*")
-    TP2val = ffi.new("char []", G1)
-    TP2[0].val = TP2val
-    TP2[0].max = G1
-    TP2[0].len = G1
-
-    TIME_PERMIT = ffi.new("octet*")
-    TIME_PERMITval = ffi.new("char []", G1)
-    TIME_PERMIT[0].val = TIME_PERMITval
-    TIME_PERMIT[0].max = G1
-    TIME_PERMIT[0].len = G1
-
-    # Token stored on computer
-    TOKEN = ffi.new("octet*")
-    TOKENval = ffi.new("char []", G1)
-    TOKEN[0].val = TOKENval
-    TOKEN[0].max = G1
-    TOKEN[0].len = G1
-
-    # H(ID)
-    HID = ffi.new("octet*")
-    HIDval = ffi.new("char []", G1)
-    HID[0].val = HIDval
-    HID[0].max = G1
-    HID[0].len = G1
-
-    # H(T|H(ID))
-    HTID = ffi.new("octet*")
-    HTIDval = ffi.new("char []", G1)
-    HTID[0].val = HTIDval
-    HTID[0].max = G1
-    HTID[0].len = G1
-
-    UT = ffi.new("octet*")
-    UTval = ffi.new("char []", G1)
-    UT[0].val = UTval
-    UT[0].max = G1
-    UT[0].len = G1
-
-    U = ffi.new("octet*")
-    Uval = ffi.new("char []", G1)
-    U[0].val = Uval
-    U[0].max = G1
-    U[0].len = G1
-
-    X = ffi.new("octet*")
-    Xval = ffi.new("char []", PGS)
-    X[0].val = Xval
-    X[0].max = PGS
-    X[0].len = PGS
-
-    Y = ffi.new("octet*")
-    Yval = ffi.new("char []", PGS)
-    Y[0].val = Yval
-    Y[0].max = PGS
-    Y[0].len = PGS
-
-    E = ffi.new("octet*")
-    Eval = ffi.new("char []", 12*PFS)
-    E[0].val = Eval
-    E[0].max = 12*PFS
-    E[0].len = 12*PFS
-
-    F = ffi.new("octet*")
-    Fval = ffi.new("char []", 12*PFS)
-    F[0].val = Fval
-    F[0].max = 12*PFS
-    F[0].len = 12*PFS
-
-    # MPIN Full
-    R = ffi.new("octet*")
-    Rval = ffi.new("char []", PGS)
-    R[0].val = Rval
-    R[0].max = PGS
-    R[0].len = PGS
-
-    W = ffi.new("octet*")
-    Wval = ffi.new("char []", PGS)
-    W[0].val = Wval
-    W[0].max = PGS
-    W[0].len = PGS
-
-    Z = ffi.new("octet*")
-    Zval = ffi.new("char []", G1)
-    Z[0].val = Zval
-    Z[0].max = G1
-    Z[0].len = G1
-
-    T = ffi.new("octet*")
-    Tval = ffi.new("char []", G1)
-    T[0].val = Tval
-    T[0].max = G1
-    T[0].len = G1
-
-    TATE1 = ffi.new("octet*")
-    TATE1val = ffi.new("char []", 12*PFS)
-    TATE1[0].val = TATE1val
-    TATE1[0].max = 12*PFS
-    TATE1[0].len = 12*PFS
-
-    TATE2 = ffi.new("octet*")
-    TATE2val = ffi.new("char []", 12*PFS)
-    TATE2[0].val = TATE2val
-    TATE2[0].max = 12*PFS
-    TATE2[0].len = 12*PFS
-
-    SK = ffi.new("octet*")
-    SKval = ffi.new("char []", PAS)
-    SK[0].val = SKval
-    SK[0].max = PAS
-    SK[0].len = PAS
-
-    CK = ffi.new("octet*")
-    CKval = ffi.new("char []", PAS)
-    CK[0].val = CKval
-    CK[0].max = PAS
-    CK[0].len = PAS
-
-    # Hash value of transmission
-    HM = ffi.new("octet*")
-    HMval = ffi.new("char []",  HASH_BYTES)
-    HM[0].val = HMval
-    HM[0].max = HASH_BYTES
-    HM[0].len = HASH_BYTES
-
-    if date:
-        prHID = HTID
-        if not PIN_ERROR:
-            U = ffi.NULL
-    else:
-        HTID = ffi.NULL
-        UT = ffi.NULL
-        prHID = HID
-        TIME_PERMIT = ffi.NULL
-
-    if not PIN_ERROR:
-        E = ffi.NULL
-        F = ffi.NULL
-
-    # Assign a seed value
-    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)
-    if DEBUG:
-        print "RAW: %s" % toHex(RAW)
-
-    # random number generator
-    RNG = ffi.new("csprng*")
-    libmpin.MPIN_CREATE_CSPRNG(RNG, RAW)
-
-    # Hash MPIN_ID
-    libmpin.MPIN_HASH_ID(MPIN_ID, HASH_MPIN_ID)
-    if DEBUG:
-        print "MPIN_ID: %s" % toHex(MPIN_ID)
-        print "HASH_MPIN_ID: %s" % toHex(HASH_MPIN_ID)
-
-    if USE_ANONYMOUS:
-        pID = HASH_MPIN_ID
-    else:
-        pID = MPIN_ID
-        
-    # Generate master secret for MIRACL and Customer
-    rtn = libmpin.MPIN_RANDOM_GENERATE(RNG, MS1)
-    if rtn != 0:
-        print "libmpin.MPIN_RANDOM_GENERATE(RNG,MS1) Error %s", rtn
-    rtn = libmpin.MPIN_RANDOM_GENERATE(RNG, MS2)
-    if rtn != 0:
-        print "libmpin.MPIN_RANDOM_GENERATE(RNG,MS2) Error %s" % rtn
-    if DEBUG:
-        print "MS1: %s" % toHex(MS1)
-        print "MS2: %s" % toHex(MS2)
-
-    # Generate server secret shares
-    rtn = libmpin.MPIN_GET_SERVER_SECRET(MS1, SS1)
-    if rtn != 0:
-        print "libmpin.MPIN_GET_SERVER_SECRET(MS1,SS1) Error %s" % rtn
-    rtn = libmpin.MPIN_GET_SERVER_SECRET(MS2, SS2)
-    if rtn != 0:
-        print "libmpin.MPIN_GET_SERVER_SECRET(MS2,SS2) Error %s" % rtn
-    if DEBUG:
-        print "SS1: %s" % toHex(SS1)
-        print "SS2: %s" % toHex(SS2)
-
-    # Combine server secret shares
-    rtn = libmpin.MPIN_RECOMBINE_G2(SS1, SS2, SERVER_SECRET)
-    if rtn != 0:
-        print "libmpin.MPIN_RECOMBINE_G2( SS1, SS2, SERVER_SECRET) Error %s" % rtn
-    if DEBUG:
-        print "SERVER_SECRET: %s" % toHex(SERVER_SECRET)
-
-    # Generate client secret shares
-    rtn = libmpin.MPIN_GET_CLIENT_SECRET(MS1, HASH_MPIN_ID, CS1)
-    if rtn != 0:
-        print "libmpin.MPIN_GET_CLIENT_SECRET(MS1,HASH_MPIN_ID,CS1) Error %s" % rtn
-    rtn = libmpin.MPIN_GET_CLIENT_SECRET(MS2, HASH_MPIN_ID, CS2)
-    if rtn != 0:
-        print "libmpin.MPIN_GET_CLIENT_SECRET(MS2,HASH_MPIN_ID,CS2) Error %s" % rtn
-    if DEBUG:
-        print "CS1: %s" % toHex(CS1)
-        print "CS2: %s" % toHex(CS2)
-
-    # Combine client secret shares : TOKEN is the full client secret
-    rtn = libmpin.MPIN_RECOMBINE_G1(CS1, CS2, TOKEN)
-    if rtn != 0:
-        print "libmpin.MPIN_RECOMBINE_G1( CS1, CS2, TOKEN) Error %s" % rtn
-    print "Client Secret: %s" % toHex(TOKEN)
-
-    # Generate Time Permit shares
-    if DEBUG:
-        print "Date %s" % date
-    rtn = libmpin.MPIN_GET_CLIENT_PERMIT(date, MS1, HASH_MPIN_ID, TP1)
-    if rtn != 0:
-        print "libmpin.MPIN_GET_CLIENT_PERMIT(date,MS1,HASH_MPIN_ID,TP1) Error %s" % rtn
-    rtn = libmpin.MPIN_GET_CLIENT_PERMIT(date, MS2, HASH_MPIN_ID, TP2)
-    if rtn != 0:
-        print "libmpin.MPIN_GET_CLIENT_PERMIT(date,MS2,HASH_MPIN_ID,TP2) Error %s" % rtn
-    if DEBUG:
-        print "TP1: %s" % toHex(TP1)
-        print "TP2: %s" % toHex(TP2)
-
-    # Combine Time Permit shares
-    rtn = libmpin.MPIN_RECOMBINE_G1(TP1, TP2, TIME_PERMIT)
-    if rtn != 0:
-        print "libmpin.MPIN_RECOMBINE_G1(TP1, TP2, TIME_PERMIT) Error %s" % rtn
-    if DEBUG:
-        print "TIME_PERMIT: %s" % toHex(TIME_PERMIT)
-
-    # Client extracts PIN from secret to create Token
-    PIN = int(raw_input("Please enter four digit PIN to create M-Pin Token:"))
-    rtn = libmpin.MPIN_EXTRACT_PIN(MPIN_ID, PIN, TOKEN)
-    if rtn != 0:
-        print "libmpin.MPIN_EXTRACT_PIN( MPIN_ID, PIN, TOKEN) Error %s" % rtn
-    print "Token: %s" % toHex(TOKEN)
-
-    if SINGLE_PASS:
-        print "M-Pin Single Pass"
-        PIN = int(raw_input("Please enter PIN to authenticate:"))
-        TimeValue = libmpin.MPIN_GET_TIME()
-        if DEBUG:
-            print "TimeValue %s" % TimeValue
-
-        # Client precomputation
-        if MPIN_FULL:
-            libmpin.MPIN_PRECOMPUTE(TOKEN, HASH_MPIN_ID, TATE1, TATE2)
-
-        # Client MPIN
-        rtn = libmpin.MPIN_CLIENT(date, MPIN_ID, RNG, X, PIN, TOKEN, SEC, U, UT, TIME_PERMIT, ffi.NULL, TimeValue, Y)
-        if rtn != 0:
-            print "MPIN_CLIENT ERROR %s" % rtn
-        if DEBUG:
-            print "X: %s" % toHex(X)
-
-        # Client sends Z=r.ID to Server
-        if MPIN_FULL:
-            libmpin.MPIN_GET_G1_MULTIPLE(RNG, 1, R, HASH_MPIN_ID, Z)
-
-        # Server MPIN
-        rtn = libmpin.MPIN_SERVER(date, HID, HTID, Y, SERVER_SECRET, U, UT, SEC, E, F, pID, ffi.NULL, TimeValue)
-        if rtn != 0:
-            print "ERROR: Single Pass %s is not authenticated" % identity
-            if PIN_ERROR:
-                err = libmpin.MPIN_KANGAROO(E, F)
-                print "Client PIN error %d " % err
-        else:
-            print "SUCCESS: Single Pass %s is authenticated" % identity
-
-        # Server sends T=w.ID to client
-        if MPIN_FULL:
-            libmpin.MPIN_GET_G1_MULTIPLE(RNG, 0, W, prHID, T)
-            print "T: %s" % toHex(T)
-
-        if MPIN_FULL:
-            libmpin.MPIN_HASH_ALL(prHID,U,UT,SEC,Y,Z,T,HM);
-            
-            libmpin.MPIN_CLIENT_KEY(TATE1, TATE2, PIN, R, X, HM, T, CK)
-            print "Client AES Key: %s" % toHex(CK)
-
-            libmpin.MPIN_SERVER_KEY(Z, SERVER_SECRET, W, HM, HID, U, UT, SK)
-            print "Server AES Key: %s" % toHex(SK)
-
-    else:
-        print "M-Pin Multi Pass"
-        PIN = int(raw_input("Please enter PIN to authenticate:"))
-        if MPIN_FULL:
-            rtn = libmpin.MPIN_PRECOMPUTE(TOKEN, HASH_MPIN_ID, TATE1, TATE2)
-            if rtn != 0:
-                print "MPIN_PERCOMPUTE  ERROR %s" % rtn
-
-        # Client first pass
-        rtn = libmpin.MPIN_CLIENT_1(date, MPIN_ID, RNG, X, PIN, TOKEN, SEC, U, UT, TIME_PERMIT)
-        if rtn != 0:
-            print "MPIN_CLIENT_1  ERROR %s" % rtn
-        if DEBUG:
-            print "X: %s" % toHex(X)
-
-        # 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.
-        libmpin.MPIN_SERVER_1(date, pID, HID, HTID)
-
-        # Server generates Random number Y and sends it to Client
-        rtn = libmpin.MPIN_RANDOM_GENERATE(RNG, Y)
-        if rtn != 0:
-            print "libmpin.MPIN_RANDOM_GENERATE(RNG,Y) Error %s" % rtn
-        if DEBUG:
-            print "Y: %s" % toHex(Y)
-
-        # Client second pass
-        rtn = libmpin.MPIN_CLIENT_2(X, Y, SEC)
-        if rtn != 0:
-            print "libmpin.MPIN_CLIENT_2(X,Y,SEC) Error %s" % rtn
-        if DEBUG:
-            print "V: %s" % toHex(SEC)
-
-        # Server second pass
-        rtn = libmpin.MPIN_SERVER_2(date, HID, HTID, Y, SERVER_SECRET, U, UT, SEC, E, F)
-        if rtn != 0:
-            print "ERROR: Multi Pass %s is not authenticated" % identity
-            if PIN_ERROR:
-                err = libmpin.MPIN_KANGAROO(E, F)
-                print "Client PIN error %d " % err
-        else:
-            print "SUCCESS: Multi Pass %s is authenticated" % identity
-
-        # Client sends Z=r.ID to Server
-        if MPIN_FULL:
-            rtn = libmpin.MPIN_GET_G1_MULTIPLE(RNG, 1, R, HASH_MPIN_ID, Z)
-            if rtn != 0:
-                print "ERROR: Generating Z %s" % rtn
-
-        # Server sends T=w.ID to client
-        if MPIN_FULL:
-            rtn = libmpin.MPIN_GET_G1_MULTIPLE(RNG, 0, W, prHID, T)
-            if rtn != 0:
-                print "ERROR: Generating T %s" % rtn
-
-            libmpin.MPIN_HASH_ALL(HASH_MPIN_ID,U,UT,SEC,Y,Z,T,HM);                
-
-            rtn = libmpin.MPIN_CLIENT_KEY(TATE1, TATE2, PIN, R, X, HM, T, CK)
-            if rtn != 0:
-                print "ERROR: Generating CK %s" % rtn
-            print "Client AES Key: %s" % toHex(CK)
-
-            rtn = libmpin.MPIN_SERVER_KEY(Z, SERVER_SECRET, W, HM, HID, U, UT, SK)
-            if rtn != 0:
-                print "ERROR: Generating SK %s" % rtn
-            print "Server AES Key: %s" % toHex(SK)
diff --git a/pythonCFFI/wcc.py b/pythonCFFI/wcc.py
deleted file mode 100755
index efd991d..0000000
--- a/pythonCFFI/wcc.py
+++ /dev/null
@@ -1,478 +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.
-"""
-
-
-"""
-wcc
-
-This module use cffi to access the c functions in the WCC library.
-
-There is also an example usage program in this file.
-
-"""
-import cffi
-import platform
-
-# WCC Group Size
-PGS = 32
-# WCC Field Size
-PFS = 32
-G1 = 2*PFS + 1
-G2 = 4*PFS
-# Length of hash
-HASH_BYTES = 32
-# AES-GCM IV length
-IVL = 12
-# AES Key length
-PAS = 16
-
-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 int WCC_RANDOM_GENERATE(csprng *RNG,octet* S);
-extern void  WCC_Hq(octet *A,octet *B,octet *C,octet *D,octet *h);
-extern int WCC_GET_G2_MULTIPLE(int hashDone,octet *S,octet *ID,octet *VG2);
-extern int WCC_GET_G1_MULTIPLE(int hashDone,octet *S,octet *ID,octet *VG1);
-extern int WCC_GET_G1_TPMULT(int date, octet *S,octet *ID,octet *VG1);
-extern int WCC_GET_G2_TPMULT(int date, octet *S,octet *ID,octet *VG2);
-extern int WCC_GET_G1_PERMIT(int date,octet *S,octet *HID,octet *G1TP);
-extern int WCC_GET_G2_PERMIT(int date,octet *S,octet *HID,octet *G2TP);
-extern int WCC_SENDER_KEY(int date, octet *xOct, octet *piaOct, octet *pibOct, octet *PbG2Oct, octet *PgG1Oct, octet *AKeyG1Oct, octet *ATPG1Oct, octet *IdBOct, octet *AESKeyOct);
-extern int WCC_RECEIVER_KEY(int date, octet *yOct, octet *wOct,  octet *piaOct, octet *pibOct,  octet *PaG1Oct, octet *PgG1Oct, octet *BKeyG2Oct,octet *BTPG2Oct,  octet *IdAOct, octet *AESKeyOct);
-extern void WCC_AES_GCM_ENCRYPT(octet *K,octet *IV,octet *H,octet *P,octet *C,octet *T);
-extern void WCC_AES_GCM_DECRYPT(octet *K,octet *IV,octet *H,octet *C,octet *P,octet *T);
-extern void WCC_HASH_ID(octet *,octet *);
-extern int WCC_RECOMBINE_G1(octet *,octet *,octet *);
-extern int WCC_RECOMBINE_G2(octet *,octet *,octet *);
-extern unsigned int WCC_today(void);
-extern void WCC_CREATE_CSPRNG(csprng *,octet *);
-extern void WCC_KILL_CSPRNG(csprng *RNG);
-extern void version(char* info);
-
-""")
-
-if (platform.system() == 'Windows'):
-    libwcc = ffi.dlopen("libwcc.dll")
-elif (platform.system() == 'Darwin'):
-    libwcc = ffi.dlopen("libwcc.dylib")
-else:
-    libwcc = ffi.dlopen("libwcc.so")
-
-
-def toHex(octetValue):
-    """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::
-
-        octetValue. An octet type
-
-    Returns::
-
-        String
-
-    Raises:
-        Exception
-    """
-    i = 0
-    val = []
-    while i < octetValue[0].len:
-        val.append(octetValue[0].val[i])
-        i = i+1
-    return ''.join(val).encode("hex")
-
-
-if __name__ == "__main__":
-    # Print hex values
-    DEBUG = False
-
-    build_version = ffi.new("char []", 256)
-    libwcc.version(build_version)
-    print ffi.string(build_version)
-
-    # Seed
-    seedHex = "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20"
-    seed = seedHex.decode("hex")
-
-    # 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
-
-    # Alice Identity
-    alice_id = raw_input("Please enter Alice's identity:")
-    IdA = ffi.new("octet*")
-    IdAval = ffi.new("char [%s]" % len(alice_id), alice_id)
-    IdA[0].val = IdAval
-    IdA[0].max = len(alice_id)
-    IdA[0].len = len(alice_id)
-
-    # Hash value of IdA
-    AHV = ffi.new("octet*")
-    AHVval = ffi.new("char []",  HASH_BYTES)
-    AHV[0].val = AHVval
-    AHV[0].max = HASH_BYTES
-    AHV[0].len = HASH_BYTES
-
-    # Bob Identity
-    bob_id = raw_input("Please enter Bob's identity:")
-    IdB = ffi.new("octet*")
-    IdBval = ffi.new("char [%s]" % len(bob_id), bob_id)
-    IdB[0].val = IdBval
-    IdB[0].max = len(bob_id)
-    IdB[0].len = len(bob_id)
-
-    # Hash value of IdB
-    BHV = ffi.new("octet*")
-    BHVval = ffi.new("char []",  HASH_BYTES)
-    BHV[0].val = BHVval
-    BHV[0].max = HASH_BYTES
-    BHV[0].len = HASH_BYTES
-
-    # Sender keys
-    A1KeyG1 = ffi.new("octet*")
-    A1KeyG1val = ffi.new("char []", G1)
-    A1KeyG1[0].val = A1KeyG1val
-    A1KeyG1[0].max = G1
-    A1KeyG1[0].len = G1
-
-    A2KeyG1 = ffi.new("octet*")
-    A2KeyG1val = ffi.new("char []", G1)
-    A2KeyG1[0].val = A2KeyG1val
-    A2KeyG1[0].max = G1
-    A2KeyG1[0].len = G1
-
-    AKeyG1 = ffi.new("octet*")
-    AKeyG1val = ffi.new("char []", G1)
-    AKeyG1[0].val = AKeyG1val
-    AKeyG1[0].max = G1
-    AKeyG1[0].len = G1
-
-    # Receiver keys
-    B1KeyG2 = ffi.new("octet*")
-    B1KeyG2val = ffi.new("char []", G2)
-    B1KeyG2[0].val = B1KeyG2val
-    B1KeyG2[0].max = G2
-    B1KeyG2[0].len = G2
-
-    B2KeyG2 = ffi.new("octet*")
-    B2KeyG2val = ffi.new("char []", G2)
-    B2KeyG2[0].val = B2KeyG2val
-    B2KeyG2[0].max = G2
-    B2KeyG2[0].len = G2
-
-    BKeyG2 = ffi.new("octet*")
-    BKeyG2val = ffi.new("char []", G2)
-    BKeyG2[0].val = BKeyG2val
-    BKeyG2[0].max = G2
-    BKeyG2[0].len = G2
-
-    # Sender time permits
-    A1TPG1 = ffi.new("octet*")
-    A1TPG1val = ffi.new("char []", G1)
-    A1TPG1[0].val = A1TPG1val
-    A1TPG1[0].max = G1
-    A1TPG1[0].len = G1
-
-    A2TPG1 = ffi.new("octet*")
-    A2TPG1val = ffi.new("char []", G1)
-    A2TPG1[0].val = A2TPG1val
-    A2TPG1[0].max = G1
-    A2TPG1[0].len = G1
-
-    ATPG1 = ffi.new("octet*")
-    ATPG1val = ffi.new("char []", G1)
-    ATPG1[0].val = ATPG1val
-    ATPG1[0].max = G1
-    ATPG1[0].len = G1
-
-    # Receiver time permits
-    B1TPG2 = ffi.new("octet*")
-    B1TPG2val = ffi.new("char []", G2)
-    B1TPG2[0].val = B1TPG2val
-    B1TPG2[0].max = G2
-    B1TPG2[0].len = G2
-
-    B2TPG2 = ffi.new("octet*")
-    B2TPG2val = ffi.new("char []", G2)
-    B2TPG2[0].val = B2TPG2val
-    B2TPG2[0].max = G2
-    B2TPG2[0].len = G2
-
-    BTPG2 = ffi.new("octet*")
-    BTPG2val = ffi.new("char []", G2)
-    BTPG2[0].val = BTPG2val
-    BTPG2[0].max = G2
-    BTPG2[0].len = G2
-
-    # AES Keys
-    KEY1 = ffi.new("octet*")
-    KEY1val = ffi.new("char []", PAS)
-    KEY1[0].val = KEY1val
-    KEY1[0].max = PAS
-    KEY1[0].len = PAS
-
-    KEY2 = ffi.new("octet*")
-    KEY2val = ffi.new("char []", PAS)
-    KEY2[0].val = KEY2val
-    KEY2[0].max = PAS
-    KEY2[0].len = PAS
-
-    X = ffi.new("octet*")
-    Xval = ffi.new("char []", PGS)
-    X[0].val = Xval
-    X[0].max = PGS
-    X[0].len = PGS
-
-    Y = ffi.new("octet*")
-    Yval = ffi.new("char []", PGS)
-    Y[0].val = Yval
-    Y[0].max = PGS
-    Y[0].len = PGS
-
-    W = ffi.new("octet*")
-    Wval = ffi.new("char []", PGS)
-    W[0].val = Wval
-    W[0].max = PGS
-    W[0].len = PGS
-
-    PIA = ffi.new("octet*")
-    PIAval = ffi.new("char []", PGS)
-    PIA[0].val = PIAval
-    PIA[0].max = PGS
-    PIA[0].len = PGS
-
-    PIB = ffi.new("octet*")
-    PIBval = ffi.new("char []", PGS)
-    PIB[0].val = PIBval
-    PIB[0].max = PGS
-    PIB[0].len = PGS
-
-    PaG1 = ffi.new("octet*")
-    PaG1val = ffi.new("char []", G1)
-    PaG1[0].val = PaG1val
-    PaG1[0].max = G1
-    PaG1[0].len = G1
-
-    PgG1 = ffi.new("octet*")
-    PgG1val = ffi.new("char []", G1)
-    PgG1[0].val = PgG1val
-    PgG1[0].max = G1
-    PgG1[0].len = G1
-
-    PbG2 = ffi.new("octet*")
-    PbG2val = ffi.new("char []", G2)
-    PbG2[0].val = PbG2val
-    PbG2[0].max = G2
-    PbG2[0].len = G2
-
-    # Assign a seed value
-    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)
-    if DEBUG:
-        print "RAW: %s" % toHex(RAW)
-
-    # random number generator
-    RNG = ffi.new("csprng*")
-    libwcc.WCC_CREATE_CSPRNG(RNG, RAW)
-
-    # Today's date in epoch days
-    date = libwcc.WCC_today()
-    if DEBUG:
-        print "Date %s" % date
-
-    # Hash IdA
-    libwcc.WCC_HASH_ID(IdA, AHV)
-    if DEBUG:
-        print "IdA: %s" % toHex(IdA)
-        print "AHV: %s" % toHex(AHV)
-
-    # Hash IdB
-    libwcc.WCC_HASH_ID(IdB, BHV)
-    if DEBUG:
-        print "IdB: %s" % toHex(IdB)
-        print "BHV: %s" % toHex(BHV)
-
-    # Generate master secret for MIRACL and Customer
-    rtn = libwcc.WCC_RANDOM_GENERATE(RNG, MS1)
-    if rtn != 0:
-        print "libwcc.WCC_RANDOM_GENERATE(RNG,MS1) Error %s", rtn
-    rtn = libwcc.WCC_RANDOM_GENERATE(RNG, MS2)
-    if rtn != 0:
-        print "libwcc.WCC_RANDOM_GENERATE(RNG,MS2) Error %s" % rtn
-    if DEBUG:
-        print "MS1: %s" % toHex(MS1)
-        print "MS2: %s" % toHex(MS2)
-
-    # Generate Alice's sender key shares
-    rtn = libwcc.WCC_GET_G1_MULTIPLE(1,MS1, AHV, A1KeyG1)
-    if rtn != 0:
-        print "libwcc.WCC_GET_G1_MULTIPLE(MS1,AHV,A1KeyG1) Error %s" % rtn
-    rtn = libwcc.WCC_GET_G1_MULTIPLE(1,MS2, AHV, A2KeyG1)
-    if rtn != 0:
-        print "libwcc.WCC_GET_G1_MULTIPLE(MS2,AHV,A2KeyG1) Error %s" % rtn
-    if DEBUG:
-        print "A1KeyG1: %s" % toHex(A1KeyG1)
-        print "A2KeyG1: %s" % toHex(A2KeyG1)
-
-    # Combine Alices's sender key shares
-    rtn = libwcc.WCC_RECOMBINE_G1(A1KeyG1, A2KeyG1, AKeyG1)
-    if rtn != 0:
-        print "libwcc.WCC_RECOMBINE_G1(A1KeyG1, A2KeyG1, AKeyG1) Error %s" % rtn
-    print "AKeyG1: %s" % toHex(AKeyG1)
-
-    # Generate Alice's sender time permit shares
-    rtn = libwcc.WCC_GET_G1_PERMIT(date, MS1, AHV, A1TPG1)
-    if rtn != 0:
-        print "libwcc.WCC_GET_G1_PERMIT(date,MS1,AHV,A1TPG1) Error %s" % rtn
-    rtn = libwcc.WCC_GET_G1_PERMIT(date, MS2, AHV, A2TPG1)
-    if rtn != 0:
-        print "libwcc.WCC_GET_G1_PERMIT(date,MS2,AHV,A2TPG1) Error %s" % rtn
-    if DEBUG:
-        print "A1TPG1: %s" % toHex(A1TPG1)
-        print "A2TPG1: %s" % toHex(A2TPG1)
-
-    # Combine Alice's sender Time Permit shares
-    rtn = libwcc.WCC_RECOMBINE_G1(A1TPG1, A2TPG1, ATPG1)
-    if rtn != 0:
-        print "libwcc.WCC_RECOMBINE_G1(A1TPG1, A2TPG1, ATPG1) Error %s" % rtn
-    print "ATPG1: %s" % toHex(ATPG1)
-
-    # Generate Bob's receiver secret key shares
-    rtn = libwcc.WCC_GET_G2_MULTIPLE(1,MS1, BHV, B1KeyG2)
-    if rtn != 0:
-        print "libwcc.WCC_GET_G2_MULTIPLE(MS1,BHV,B1KeyG2) Error %s" % rtn
-    rtn = libwcc.WCC_GET_G2_MULTIPLE(1,MS2, BHV, B2KeyG2)
-    if rtn != 0:
-        print "libwcc.WCC_GET_G2_MULTIPLE(MS2,BHV,B2KeyG2) Error %s" % rtn
-    if DEBUG:
-        print "B1KeyG2: %s" % toHex(B1KeyG2)
-        print "B2KeyG2: %s" % toHex(B2KeyG2)
-
-    # Combine Bobs's receiver secret key shares
-    rtn = libwcc.WCC_RECOMBINE_G2(B1KeyG2, B2KeyG2, BKeyG2)
-    if rtn != 0:
-        print "libwcc.WCC_RECOMBINE_G2(B1KeyG2, B2KeyG2, BKeyG2) Error %s" % rtn
-    print "BKeyG2: %s" % toHex(BKeyG2)
-
-    # Generate Bob's receiver time permit shares
-    rtn = libwcc.WCC_GET_G2_PERMIT(date, MS1, BHV, B1TPG2)
-    if rtn != 0:
-        print "libwcc.WCC_GET_G2_PERMIT(date,MS1,BHV,B1TPG2) Error %s" % rtn
-    rtn = libwcc.WCC_GET_G2_PERMIT(date, MS2, BHV, B2TPG2)
-    if rtn != 0:
-        print "libwcc.WCC_GET_G2_PERMIT(date,MS2,BHV,B2TPG2) Error %s" % rtn
-    if DEBUG:
-        print "B1TPG2: %s" % toHex(B1TPG2)
-        print "B2TPG2: %s" % toHex(B2TPG2)
-
-    # Combine Bob's receiver time permit shares
-    rtn = libwcc.WCC_RECOMBINE_G2(B1TPG2, B2TPG2, BTPG2)
-    if rtn != 0:
-        print "libwcc.WCC_RECOMBINE_G2(B1TPG2, B2TPG2, BTPG2) Error %s" % rtn
-    print "BTPG2: %s" % toHex(BTPG2)
-
-    rtn = libwcc.WCC_RANDOM_GENERATE(RNG, X)
-    if rtn != 0:
-        print "libwcc.WCC_RANDOM_GENERATE(RNG,X) Error %s", rtn
-    if DEBUG:
-        print "X: %s" % toHex(X)
-
-    rtn = libwcc.WCC_GET_G1_TPMULT(date,X,IdA,PaG1);
-    if rtn != 0:
-        print "libwcc.WCC_GET_G1_TPMULT(date,X,IdA,PaG1) Error %s", rtn
-    if DEBUG:
-        print "PaG1: %s" % toHex(PaG1)
-
-    rtn = libwcc.WCC_RANDOM_GENERATE(RNG, W)
-    if rtn != 0:
-        print "libwcc.WCC_RANDOM_GENERATE(RNG,W) Error %s", rtn
-    if DEBUG:
-        print "W: %s" % toHex(W)
-
-    rtn = libwcc.WCC_GET_G1_TPMULT(date,W,IdA,PgG1);
-    if rtn != 0:
-        print "libwcc.WCC_GET_G1_TPMULT(date,W,IdA,PgG1) Error %s", rtn
-    if DEBUG:
-        print "PgG1: %s" % toHex(PgG1)
-
-    rtn = libwcc.WCC_RANDOM_GENERATE(RNG, Y)
-    if rtn != 0:
-        print "libwcc.WCC_RANDOM_GENERATE(RNG,Y) Error %s", rtn
-    if DEBUG:
-        print "Y: %s" % toHex(Y)
-
-    rtn = libwcc.WCC_GET_G2_TPMULT(date,Y,IdB,PbG2);
-    if rtn != 0:
-        print "libwcc.WCC_GET_G1_TPMULT(date,Y,IdB,PbG2) Error %s", rtn
-    if DEBUG:
-        print "PbG2: %s" % toHex(PbG2)
-
-    # PIA = Hq(PaG1,PbG2,PgG1,IdB)
-    libwcc.WCC_Hq(PaG1,PbG2,PgG1,IdB,PIA);
-    if DEBUG:
-        print "PIA: %s" % toHex(PIA)
-
-    # PIB = Hq(PbG2,PaG1,PgG1,IdA)
-    libwcc.WCC_Hq(PbG2,PaG1,PgG1,IdA,PIB);
-    if DEBUG:
-        print "PIB: %s" % toHex(PIB)
-        
-    # Alice calculates AES Key 
-    rtn = libwcc.WCC_SENDER_KEY(date, X, PIA, PIB, PbG2, PgG1, AKeyG1, ATPG1, IdB, KEY1)
-    if rtn != 0:
-        print "libwcc.WCC_SENDER_KEY(date, X, PIA, PIB, PbG2, PgG1, AKeyG1, ATPG1, IdB, KEY1) Error %s" % rtn
-    print "{0}'s AES Key: {1}".format(alice_id, toHex(KEY1))
-
-    # Bob calculates AES Key
-    rtn = libwcc.WCC_RECEIVER_KEY(date, Y, W, PIA, PIB, PaG1, PgG1, BKeyG2, BTPG2, IdA, KEY2)
-    if rtn != 0:
-        print "libwcc.WCC_RECEIVER_KEY(date, Y, W, PIA, PIB, PaG1, PgG1, BKeyG2, BTPG2, IdA, KEY2) Error %s" % rtn
-    print "{0}'s AES Key: {1}".format(bob_id, toHex(KEY2))
-
-    libwcc.WCC_KILL_CSPRNG(RNG)
diff --git a/readme.txt b/readme.txt
new file mode 100644
index 0000000..5469379
--- /dev/null
+++ b/readme.txt
@@ -0,0 +1,41 @@
+The Apache Milagro Cryptographic Library
+
+Note that the AMCL currently comes in two versions, version 2.2 
+and version 3.1
+
+AMCL v2.2 is presented in what might be called a pre-library state.
+
+In the various supported languages the source code is made available,
+but it is not organised into rigid packages/crates/jars/whatever
+It is expected that the consumer will themselves take this final step,
+depending on the exact requirements of their project.
+
+Note that version 2.2 is no longer supported.
+
+AMCL v3.1 uses a standard Python 3 script to build libraries in all
+supported languages. New users should use this version.
+
+The main improvement is that AMCL v3 can optionally simultaneously support 
+multiple elliptic curves and RSA key sizes within a single appliction.
+
+Note that AMCL is largely configured at compile time. In version 3 this
+configuration is handled by the Python script.
+
+AMCL is available in 32-bit and 64-bit versions in most languages. Limited 
+support for 16-bit processors is provided by the C version.
+
+Now languages like to remain "standard" irrespective of the underlying 
+hardware. However when it comes to optimal performance, it is impossible 
+to remain architecture-agnostic. If a processor supports 64-bit 
+instructions that operate on 64-bit registers, it will be a waste not to
+use them. Therefore the 64-bit language versions should always be used
+on 64-bit processors.
+
+Version 3.1 is a major "under the hood" upgrade. Field arithmetic is 
+performed using ideas from http://eprint.iacr.org/2017/437 to ensure 
+that critical calculations are performed in constant time. This strongly 
+mitigates against side-channel attacks. Exception-free formulae are 
+now used for Weierstrass elliptic curves. A new standardised script 
+builds for the same set of curves across all languages.
+
+
diff --git a/swift/TestECDH.swift b/swift/TestECDH.swift
deleted file mode 100644
index 7070770..0000000
--- a/swift/TestECDH.swift
+++ /dev/null
@@ -1,164 +0,0 @@
-/*

-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 clint // comment out for Xcode

-

-public func TestECDH()

-{

-    let pp=String("M0ng00se");

-

-    let EGS=ECDH.EGS

-    let EFS=ECDH.EFS

-    let EAS=AES.KS

-

-    var S1=[UInt8](count:EGS,repeatedValue:0)

-    var W0=[UInt8](count:2*EFS+1,repeatedValue:0)

-    var W1=[UInt8](count:2*EFS+1,repeatedValue:0)

-    var Z0=[UInt8](count:EFS,repeatedValue:0)

-    var Z1=[UInt8](count:EFS,repeatedValue:0)

-    var RAW=[UInt8](count:100,repeatedValue:0)

-    var SALT=[UInt8](count:8,repeatedValue:0)

-    var P1=[UInt8](count:3,repeatedValue:0)

-    var P2=[UInt8](count:4,repeatedValue:0)

-    var V=[UInt8](count:2*EFS+1,repeatedValue:0)

-    var M=[UInt8](count:17,repeatedValue:0)

-    var T=[UInt8](count:12,repeatedValue:0)

-    var CS=[UInt8](count:EGS,repeatedValue:0)

-    var DS=[UInt8](count:EGS,repeatedValue:0)

-

-    let rng=RAND()

-

-    rng.clean();

-    for var i=0;i<100;i++ {RAW[i]=UInt8(i&0xff)}

-

-    rng.seed(100,RAW)

-

-

-    for var i=0;i<8;i++ {SALT[i]=UInt8(i+1)}  // set Salt

-

-    print("Alice's Passphrase= "+pp)

-    let PW=[UInt8](pp.utf8)

-

-    /* private key S0 of size EGS bytes derived from Password and Salt */

-

-    var S0=ECDH.PBKDF2(PW,SALT,1000,EGS)

-    print("Alice's private key= 0x",terminator: ""); ECDH.printBinary(S0)

-

-    /* Generate Key pair S/W */

-    ECDH.KEY_PAIR_GENERATE(nil,&S0,&W0);

-

-    print("Alice's public key= 0x",terminator: ""); ECDH.printBinary(W0)

-

-    var res=ECDH.PUBLIC_KEY_VALIDATE(true,W0);

-

-    if res != 0

-    {

-        print("ECP Public Key is invalid!");

-        return;

-    }

-

-    /* Random private key for other party */

-    ECDH.KEY_PAIR_GENERATE(rng,&S1,&W1)

-

-    print("Servers private key= 0x",terminator: ""); ECDH.printBinary(S1)

-

-    print("Servers public key= 0x",terminator: ""); ECDH.printBinary(W1);

-

-    res=ECDH.PUBLIC_KEY_VALIDATE(true,W1)

-    if res != 0

-    {

-        print("ECP Public Key is invalid!")

-        return

-    }

-

-    /* Calculate common key using DH - IEEE 1363 method */

-

-    ECDH.ECPSVDP_DH(S0,W1,&Z0)

-    ECDH.ECPSVDP_DH(S1,W0,&Z1)

-

-    var same=true

-    for var i=0;i<EFS;i++

-    {

-        if Z0[i] != Z1[i] {same=false}

-    }

-

-    if (!same)

-    {

-        print("*** ECPSVDP-DH Failed")

-        return

-    }

-

-    let KEY=ECDH.KDF1(Z0,EAS)

-

-    print("Alice's DH Key=  0x",terminator: ""); ECDH.printBinary(KEY)

-    print("Servers DH Key=  0x",terminator: ""); ECDH.printBinary(KEY)

-

-    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 var i=0;i<=16;i++ {M[i]=UInt8(i&0xff)}

-

-    let C=ECDH.ECIES_ENCRYPT(P1,P2,rng,W1,M,&V,&T)

-

-    print("Ciphertext= ")

-    print("V= 0x",terminator: ""); ECDH.printBinary(V)

-    print("C= 0x",terminator: ""); ECDH.printBinary(C)

-    print("T= 0x",terminator: ""); ECDH.printBinary(T)

-

-    M=ECDH.ECIES_DECRYPT(P1,P2,V,C,T,S1)

-    if M.count==0

-    {

-        print("*** ECIES Decryption Failed\n")

-        return

-    }

-    else {print("Decryption succeeded")}

-

-    print("Message is 0x"); ECDH.printBinary(M)

-

-    print("Testing ECDSA")

-

-    if ECDH.ECPSP_DSA(rng,S0,M,&CS,&DS) != 0

-    {

-        print("***ECDSA Signature Failed")

-        return

-    }

-    print("Signature= ")

-    print("C= 0x",terminator: ""); ECDH.printBinary(CS)

-    print("D= 0x",terminator: ""); ECDH.printBinary(DS)

-

-    if ECDH.ECPVP_DSA(W0,M,CS,DS) != 0

-    {

-        print("***ECDSA Verification Failed")

-        return

-    }

-    else {print("ECDSA Signature/Verification succeeded ")}

-

-}

-

-TestECDH()  // comment out for Xcode

diff --git a/swift/TestECM.swift b/swift/TestECM.swift
deleted file mode 100644
index 36101b5..0000000
--- a/swift/TestECM.swift
+++ /dev/null
@@ -1,112 +0,0 @@
-/*

-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.

-*/

-//

-//  TestECM.swift

-//  

-//

-//  Created by Michael Scott on 03/07/2015.

-//  Copyright (c) 2015 Michael Scott. All rights reserved.

-//

-

-import Foundation

-

-func TestECM()

-{

-    let pp=String("M0ng00se");

-

-    let EGS=ECDH.EGS

-    let EFS=ECDH.EFS

-    let EAS=AES.KS

-

-    var S1=[UInt8](count:EGS,repeatedValue:0)

-    var W0=[UInt8](count:2*EFS+1,repeatedValue:0)

-    var W1=[UInt8](count:2*EFS+1,repeatedValue:0)

-    var Z0=[UInt8](count:EFS,repeatedValue:0)

-    var Z1=[UInt8](count:EFS,repeatedValue:0)

-    var RAW=[UInt8](count:100,repeatedValue:0)

-    var SALT=[UInt8](count:8,repeatedValue:0)

-

-    let rng=RAND()

-

-    rng.clean();

-    for var i=0;i<100;i++ {RAW[i]=UInt8(i&0xff)}

-

-    rng.seed(100,RAW)

-

-

-    for var i=0;i<8;i++ {SALT[i]=UInt8(i+1)}  // set Salt

-

-    print("Alice's Passphrase= "+pp)

-    let PW=[UInt8](pp.utf8)

-

-    /* private key S0 of size EGS bytes derived from Password and Salt */

-

-    var S0=ECDH.PBKDF2(PW,SALT,1000,EGS)

-    print("Alice's private key= 0x",terminator: ""); ECDH.printBinary(S0)

-

-    /* Generate Key pair S/W */

-    ECDH.KEY_PAIR_GENERATE(nil,&S0,&W0);

-

-    print("Alice's public key= 0x",terminator: ""); ECDH.printBinary(W0)

-

-    var res=ECDH.PUBLIC_KEY_VALIDATE(true,W0);

-

-    if res != 0

-    {

-        print("ECP Public Key is invalid!");

-        return;

-    }

-

-    /* Random private key for other party */

-    ECDH.KEY_PAIR_GENERATE(rng,&S1,&W1)

-

-    print("Servers private key= 0x",terminator: ""); ECDH.printBinary(S1)

-

-    print("Servers public key= 0x",terminator: ""); ECDH.printBinary(W1);

-

-    res=ECDH.PUBLIC_KEY_VALIDATE(true,W1)

-    if res != 0

-    {

-        print("ECP Public Key is invalid!")

-        return

-    }

-

-    /* Calculate common key using DH - IEEE 1363 method */

-

-    ECDH.ECPSVDP_DH(S0,W1,&Z0)

-    ECDH.ECPSVDP_DH(S1,W0,&Z1)

-

-    var same=true

-    for var i=0;i<EFS;i++

-    {

-        if Z0[i] != Z1[i] {same=false}

-    }

-

-    if (!same)

-    {

-        print("*** ECPSVDP-DH Failed")

-        return

-    }

-

-    let KEY=ECDH.KDF1(Z0,EAS)

-

-    print("Alice's DH Key=  0x",terminator: ""); ECDH.printBinary(KEY)

-    print("Servers DH Key=  0x",terminator: ""); ECDH.printBinary(KEY)

-

-}

diff --git a/swift/TestMPIN.swift b/swift/TestMPIN.swift
deleted file mode 100644
index 8827eb0..0000000
--- a/swift/TestMPIN.swift
+++ /dev/null
@@ -1,253 +0,0 @@
-/*

-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.

-*/

-//

-//  TestMPIN.swift

-//  

-//

-//  Created by Michael Scott on 08/07/2015.

-//  Copyright (c) 2015 Michael Scott. All rights reserved.

-//

-

-import Foundation

-import clint  // comment out for Xcode

-

-public func TestMPIN()

-{

-    let PERMITS=true

-    let PINERROR=true

-    let FULL=true

-    let SINGLE_PASS=true

-

-    let rng=RAND()

-

-    var RAW=[UInt8](count:100,repeatedValue:0)

-

-    for var i=0;i<100;i++ {RAW[i]=UInt8((i+1)&0xff)}

-    rng.seed(100,RAW)

-

-    let EGS=MPIN.EFS

-    let EFS=MPIN.EGS

-    let G1S=2*EFS+1    /* Group 1 Size */

-    let G2S=4*EFS;     /* Group 2 Size */

-    let EAS=MPIN.PAS

-

-    var S=[UInt8](count:EGS,repeatedValue:0)

-    var SST=[UInt8](count:G2S,repeatedValue:0)

-    var TOKEN=[UInt8](count:G1S,repeatedValue:0)

-    var PERMIT=[UInt8](count:G1S,repeatedValue:0)

-    var SEC=[UInt8](count:G1S,repeatedValue:0)

-    let xID=[UInt8](count:G1S,repeatedValue:0)

-    let xCID=[UInt8](count:G1S,repeatedValue:0)

-    var X=[UInt8](count:EGS,repeatedValue:0)

-    var Y=[UInt8](count:EGS,repeatedValue:0)

-    let E=[UInt8](count:12*EFS,repeatedValue:0)

-    let F=[UInt8](count:12*EFS,repeatedValue:0)

-    let HID=[UInt8](count:G1S,repeatedValue:0)

-    let HTID=[UInt8](count:G1S,repeatedValue:0)

-

-    var G1=[UInt8](count:12*EFS,repeatedValue:0)

-    var G2=[UInt8](count:12*EFS,repeatedValue:0)

-    var R=[UInt8](count:EGS,repeatedValue:0)

-    var Z=[UInt8](count:G1S,repeatedValue:0)

-    var W=[UInt8](count:EGS,repeatedValue:0)

-    var T=[UInt8](count:G1S,repeatedValue:0)

-    var CK=[UInt8](count:EAS,repeatedValue:0)

-    var SK=[UInt8](count:EAS,repeatedValue:0)

-

-    /* Trusted Authority set-up */

-

-    MPIN.RANDOM_GENERATE(rng,&S)

-    print("Master Secret s: 0x",terminator: "");  MPIN.printBinary(S)

-

-    /* Create Client Identity */

-    let IDstr = "testUser@miracl.com"

-    let CLIENT_ID=[UInt8](IDstr.utf8)

-

-    var HCID=MPIN.HASH_ID(CLIENT_ID)  /* Either Client or TA calculates Hash(ID) - you decide! */

-

-    print("Client ID= "); MPIN.printBinary(CLIENT_ID)

-

-    /* Client and Server are issued secrets by DTA */

-    MPIN.GET_SERVER_SECRET(S,&SST);

-    print("Server Secret SS: 0x",terminator: "");  MPIN.printBinary(SST);

-

-    MPIN.GET_CLIENT_SECRET(&S,HCID,&TOKEN);

-    print("Client Secret CS: 0x",terminator: ""); MPIN.printBinary(TOKEN);

-

-    /* Client extracts PIN from secret to create Token */

-    var pin:Int32=1234

-    print("Client extracts PIN= \(pin)")

-    var rtn=MPIN.EXTRACT_PIN(CLIENT_ID,pin,&TOKEN)

-    if rtn != 0 {print("FAILURE: EXTRACT_PIN rtn: \(rtn)")}

-

-    print("Client Token TK: 0x",terminator: ""); MPIN.printBinary(TOKEN);

-

-    if FULL

-    {

-        MPIN.PRECOMPUTE(TOKEN,HCID,&G1,&G2);

-    }

-

-    var date:Int32=0

-    if (PERMITS)

-    {

-        date=MPIN.today()

-        /* Client gets "Time Token" permit from DTA */

-        MPIN.GET_CLIENT_PERMIT(date,S,HCID,&PERMIT)

-        print("Time Permit TP: 0x",terminator: "");  MPIN.printBinary(PERMIT)

-

-        /* This encoding makes Time permit look random - Elligator squared */

-        MPIN.ENCODING(rng,&PERMIT);

-        print("Encoded Time Permit TP: 0x",terminator: "");  MPIN.printBinary(PERMIT)

-        MPIN.DECODING(&PERMIT)

-        print("Decoded Time Permit TP: 0x",terminator: "");  MPIN.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

-

-    if date != 0

-    {

-        if (!PINERROR)

-        {

-            pxID=nil;

-            pHID=nil;

-        }

-    }

-    else

-    {

-        pPERMIT=nil;

-        pxCID=nil;

-        pHTID=nil;

-    }

-    if (!PINERROR)

-    {

-        pE=nil;

-        pF=nil;

-    }

-

-    if (SINGLE_PASS)

-    {

-        print("MPIN Single Pass")

-        let timeValue = MPIN.GET_TIME()

-

-        rtn=MPIN.CLIENT(date,CLIENT_ID,rng,&X,pin,TOKEN,&SEC,&pxID,&pxCID,pPERMIT!,timeValue,&Y)

-

-        if rtn != 0 {print("FAILURE: CLIENT rtn: \(rtn)")}

-

-        if (FULL)

-        {

-            HCID=MPIN.HASH_ID(CLIENT_ID);

-            MPIN.GET_G1_MULTIPLE(rng,1,&R,HCID,&Z); /* Also Send Z=r.ID to Server, remember random r */

-        }

-        rtn=MPIN.SERVER(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  */

-            if date != 0 {MPIN.GET_G1_MULTIPLE(rng,0,&W,pHTID!,&T)}

-            else {MPIN.GET_G1_MULTIPLE(rng,0,&W,pHID!,&T)}

-

-        }

-    }

-    else

-    {

-        print("MPIN Multi Pass");

-        /* Send U=x.ID to server, and recreate secret from token and pin */

-        rtn=MPIN.CLIENT_1(date,CLIENT_ID,rng,&X,pin,TOKEN,&SEC,&pxID,&pxCID,pPERMIT!)

-        if rtn != 0 {print("FAILURE: CLIENT_1 rtn: \(rtn)")}

-

-        if (FULL)

-        {

-            HCID=MPIN.HASH_ID(CLIENT_ID);

-            MPIN.GET_G1_MULTIPLE(rng,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. */

-        MPIN.SERVER_1(date,CLIENT_ID,&pHID,&pHTID!);

-

-            /* Server generates Random number Y and sends it to Client */

-        MPIN.RANDOM_GENERATE(rng,&Y);

-

-        if (FULL)

-        { /* Also send T=w.ID to client, remember random w  */

-            if date != 0 {MPIN.GET_G1_MULTIPLE(rng,0,&W,pHTID!,&T)}

-            else {MPIN.GET_G1_MULTIPLE(rng,0,&W,pHID!,&T)}

-        }

-

-        /* Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC */

-        rtn=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=MPIN.SERVER_2(date,pHID,pHTID!,Y,SST,pxID,pxCID!,SEC,&pE,&pF);

-

-        if rtn != 0 {print("FAILURE: SERVER_1 rtn: \(rtn)")}

-    }

-    if (rtn == MPIN.BAD_PIN)

-    {

-        print("Server says - Bad Pin. I don't know you. Feck off.\n");

-        if (PINERROR)

-        {

-            let err=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)

-    {

-        MPIN.CLIENT_KEY(G1,G2,pin,R,X,T,&CK);

-        print("Client Key =  0x",terminator: "");  MPIN.printBinary(CK)

-

-        MPIN.SERVER_KEY(Z,SST,W,pxID!,pxCID!,&SK);

-        print("Server Key =  0x",terminator: "");  MPIN.printBinary(SK)

-    }

-

-}

-

-TestMPIN() // comment out for Xcode

-

diff --git a/swift/TestRSA.swift b/swift/TestRSA.swift
deleted file mode 100644
index 5167c69..0000000
--- a/swift/TestRSA.swift
+++ /dev/null
@@ -1,78 +0,0 @@
-/*

-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.

-*/

-

-//

-//  TestRSA.swift

-//  

-//

-//  Created by Michael Scott on 25/06/2015.

-//  Copyright (c) 2015 Michael Scott. All rights reserved.

-//

-

-import Foundation

-import clint   // comment out for Xcode

-

-public func TestRSA()

-{

-    let RFS=RSA.RFS;

-

-    var message="Hello World\n"

-

-    let pub=rsa_public_key(ROM.FFLEN);

-    let priv=rsa_private_key(ROM.HFLEN);

-

-    var ML=[UInt8](count:RFS,repeatedValue:0)

-    var C=[UInt8](count:RFS,repeatedValue:0)

-    var RAW=[UInt8](count:100,repeatedValue:0)

-

-    let rng=RAND()

-

-    rng.clean();

-    for var i=0;i<100;i++ {RAW[i]=UInt8(i)}

-

-    rng.seed(100,RAW);

-

-    print("Generating 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(M,rng,nil); /* OAEP encode message m to e  */

-

-    RSA.ENCRYPT(pub,E,&C);     /* encrypt encoded message */

-    print("Ciphertext= 0x", terminator: ""); RSA.printBinary(C);

-

-    print("Decrypting test string\n");

-    RSA.DECRYPT(priv,C,&ML);

-    var MS=RSA.OAEP_DECODE(nil,&ML); /* OAEP encode message m to e  */

-

-    message=""

-    for var i=0;i<MS.count;i++

-    {

-        message+=String(UnicodeScalar(MS[i]))

-    }

-    print(message);

-

-    RSA.PRIVATE_KEY_KILL(priv);

-}

-

-TestRSA() // comment out for Xcode

-

-

-

diff --git a/swift/aes.swift b/swift/aes.swift
deleted file mode 100644
index 016388e..0000000
--- a/swift/aes.swift
+++ /dev/null
@@ -1,586 +0,0 @@
-/*

-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.

-*/

-//

-//  aes.swift

-//  

-//

-//  Created by Michael Scott on 22/06/2015.

-//  Copyright (c) 2015 Michael Scott. All rights reserved.

-//

-//   AES Encryption

-//

-

-final public class AES {

-    var mode:Int=0;

-    private var fkey=[UInt32](count:44,repeatedValue:0)

-    private var rkey=[UInt32](count:44,repeatedValue:0)

-    var f=[UInt8](count:16,repeatedValue:0)

-

-    static let ECB:Int=0

-    static let CBC:Int=1

-    static let CFB1:Int=2

-    static let CFB2:Int=3

-    static let CFB4:Int=5

-    static let OFB1:Int=14

-    static let OFB2:Int=15

-    static let OFB4:Int=17

-    static let OFB8:Int=21

-    static let OFB16:Int=29

-    static public let KS:Int=16; /* Key Size in bytes */

-    static public let BS:Int=16; /* Block Size */

-

-    private static let InCo:[UInt8] = [ 0xB,0xD,0x9,0xE]  /* Inverse Coefficients */

-

-    private static let ptab:[UInt8] =

-    [ 1, 3, 5, 15, 17, 51, 85, 255, 26, 46, 114, 150, 161, 248, 19, 53,

-     95, 225, 56, 72, 216, 115, 149, 164, 247, 2, 6, 10, 30, 34, 102, 170,

-     229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217, 112, 144, 171, 230, 49,

-     83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104, 184, 211, 110, 178, 205,

-     76, 212, 103, 169, 224, 59, 77, 215, 98, 166, 241, 8, 24, 40, 120, 136,

-     131, 158, 185, 208, 107, 189, 220, 127, 129, 152, 179, 206, 73, 219, 118, 154,

-     181, 196, 87, 249, 16, 48, 80, 240, 11, 29, 39, 105, 187, 214, 97, 163,

-     254, 25, 43, 125, 135, 146, 173, 236, 47, 113, 147, 174, 233, 32, 96, 160,

-     251, 22, 58, 78, 210, 109, 183, 194, 93, 231, 50, 86, 250, 21, 63, 65,

-     195, 94, 226, 61, 71, 201, 64, 192, 91, 237, 44, 116, 156, 191, 218, 117,

-     159, 186, 213, 100, 172, 239, 42, 126, 130, 157, 188, 223, 122, 142, 137, 128,

-     155, 182, 193, 88, 232, 35, 101, 175, 234, 37, 111, 177, 200, 67, 197, 84,

-     252, 31, 33, 99, 165, 244, 7, 9, 27, 45, 119, 153, 176, 203, 70, 202,

-     69, 207, 74, 222, 121, 139, 134, 145, 168, 227, 62, 66, 198, 81, 243, 14,

-     18, 54, 90, 238, 41, 123, 141, 140, 143, 138, 133, 148, 167, 242, 13, 23,

-     57, 75, 221, 124, 132, 151, 162, 253, 28, 36, 108, 180, 199, 82, 246, 1]

-

-    private static let ltab:[UInt8] =

-    [ 0, 255, 25, 1, 50, 2, 26, 198, 75, 199, 27, 104, 51, 238, 223, 3,

-     100, 4, 224, 14, 52, 141, 129, 239, 76, 113, 8, 200, 248, 105, 28, 193,

-     125, 194, 29, 181, 249, 185, 39, 106, 77, 228, 166, 114, 154, 201, 9, 120,

-     101, 47, 138, 5, 33, 15, 225, 36, 18, 240, 130, 69, 53, 147, 218, 142,

-     150, 143, 219, 189, 54, 208, 206, 148, 19, 92, 210, 241, 64, 70, 131, 56,

-     102, 221, 253, 48, 191, 6, 139, 98, 179, 37, 226, 152, 34, 136, 145, 16,

-     126, 110, 72, 195, 163, 182, 30, 66, 58, 107, 40, 84, 250, 133, 61, 186,

-     43, 121, 10, 21, 155, 159, 94, 202, 78, 212, 172, 229, 243, 115, 167, 87,

-     175, 88, 168, 80, 244, 234, 214, 116, 79, 174, 233, 213, 231, 230, 173, 232,

-     44, 215, 117, 122, 235, 22, 11, 245, 89, 203, 95, 176, 156, 169, 81, 160,

-     127, 12, 246, 111, 23, 196, 73, 236, 216, 67, 31, 45, 164, 118, 123, 183,

-     204, 187, 62, 90, 251, 96, 177, 134, 59, 82, 161, 108, 170, 85, 41, 157,

-     151, 178, 135, 144, 97, 190, 220, 252, 188, 149, 207, 205, 55, 63, 91, 209,

-     83, 57, 132, 60, 65, 162, 109, 71, 20, 42, 158, 93, 86, 242, 211, 171,

-     68, 17, 146, 217, 35, 32, 46, 137, 180, 124, 184, 38, 119, 153, 227, 165,

-     103, 74, 237, 222, 197, 49, 254, 24, 13, 99, 140, 128, 192, 247, 112, 7]

-

-    private static let fbsub:[UInt8] =

-    [ 99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118,

-     202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192,

-     183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21,

-     4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117,

-     9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132,

-     83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207,

-     208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168,

-     81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210,

-     205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115,

-     96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219,

-     224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121,

-     231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8,

-     186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138,

-     112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158,

-     225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223,

-     140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22]

-

-    private static let rbsub:[UInt8] =

-    [ 82, 9, 106, 213, 48, 54, 165, 56, 191, 64, 163, 158, 129, 243, 215, 251,

-     124, 227, 57, 130, 155, 47, 255, 135, 52, 142, 67, 68, 196, 222, 233, 203,

-     84, 123, 148, 50, 166, 194, 35, 61, 238, 76, 149, 11, 66, 250, 195, 78,

-     8, 46, 161, 102, 40, 217, 36, 178, 118, 91, 162, 73, 109, 139, 209, 37,

-     114, 248, 246, 100, 134, 104, 152, 22, 212, 164, 92, 204, 93, 101, 182, 146,

-     108, 112, 72, 80, 253, 237, 185, 218, 94, 21, 70, 87, 167, 141, 157, 132,

-     144, 216, 171, 0, 140, 188, 211, 10, 247, 228, 88, 5, 184, 179, 69, 6,

-     208, 44, 30, 143, 202, 63, 15, 2, 193, 175, 189, 3, 1, 19, 138, 107,

-     58, 145, 17, 65, 79, 103, 220, 234, 151, 242, 207, 206, 240, 180, 230, 115,

-     150, 172, 116, 34, 231, 173, 53, 133, 226, 249, 55, 232, 28, 117, 223, 110,

-     71, 241, 26, 113, 29, 41, 197, 137, 111, 183, 98, 14, 170, 24, 190, 27,

-     252, 86, 62, 75, 198, 210, 121, 32, 154, 219, 192, 254, 120, 205, 90, 244,

-     31, 221, 168, 51, 136, 7, 199, 49, 177, 18, 16, 89, 39, 128, 236, 95,

-     96, 81, 127, 169, 25, 181, 74, 13, 45, 229, 122, 159, 147, 201, 156, 239,

-     160, 224, 59, 77, 174, 42, 245, 176, 200, 235, 187, 60, 131, 83, 153, 97,

-     23, 43, 4, 126, 186, 119, 214, 38, 225, 105, 20, 99, 85, 33, 12, 125]

-

-    private static let rco:[UInt8] =

-    [1,2,4,8,16,32,64,128,27,54,108,216,171,77,154,47]

-

-    private static let ftable:[UInt32] =

-    [0xa56363c6,0x847c7cf8,0x997777ee,0x8d7b7bf6,0xdf2f2ff,0xbd6b6bd6,

-    0xb16f6fde,0x54c5c591,0x50303060,0x3010102,0xa96767ce,0x7d2b2b56,

-    0x19fefee7,0x62d7d7b5,0xe6abab4d,0x9a7676ec,0x45caca8f,0x9d82821f,

-    0x40c9c989,0x877d7dfa,0x15fafaef,0xeb5959b2,0xc947478e,0xbf0f0fb,

-    0xecadad41,0x67d4d4b3,0xfda2a25f,0xeaafaf45,0xbf9c9c23,0xf7a4a453,

-    0x967272e4,0x5bc0c09b,0xc2b7b775,0x1cfdfde1,0xae93933d,0x6a26264c,

-    0x5a36366c,0x413f3f7e,0x2f7f7f5,0x4fcccc83,0x5c343468,0xf4a5a551,

-    0x34e5e5d1,0x8f1f1f9,0x937171e2,0x73d8d8ab,0x53313162,0x3f15152a,

-    0xc040408,0x52c7c795,0x65232346,0x5ec3c39d,0x28181830,0xa1969637,

-    0xf05050a,0xb59a9a2f,0x907070e,0x36121224,0x9b80801b,0x3de2e2df,

-    0x26ebebcd,0x6927274e,0xcdb2b27f,0x9f7575ea,0x1b090912,0x9e83831d,

-    0x742c2c58,0x2e1a1a34,0x2d1b1b36,0xb26e6edc,0xee5a5ab4,0xfba0a05b,

-    0xf65252a4,0x4d3b3b76,0x61d6d6b7,0xceb3b37d,0x7b292952,0x3ee3e3dd,

-    0x712f2f5e,0x97848413,0xf55353a6,0x68d1d1b9,0x0,0x2cededc1,

-    0x60202040,0x1ffcfce3,0xc8b1b179,0xed5b5bb6,0xbe6a6ad4,0x46cbcb8d,

-    0xd9bebe67,0x4b393972,0xde4a4a94,0xd44c4c98,0xe85858b0,0x4acfcf85,

-    0x6bd0d0bb,0x2aefefc5,0xe5aaaa4f,0x16fbfbed,0xc5434386,0xd74d4d9a,

-    0x55333366,0x94858511,0xcf45458a,0x10f9f9e9,0x6020204,0x817f7ffe,

-    0xf05050a0,0x443c3c78,0xba9f9f25,0xe3a8a84b,0xf35151a2,0xfea3a35d,

-    0xc0404080,0x8a8f8f05,0xad92923f,0xbc9d9d21,0x48383870,0x4f5f5f1,

-    0xdfbcbc63,0xc1b6b677,0x75dadaaf,0x63212142,0x30101020,0x1affffe5,

-    0xef3f3fd,0x6dd2d2bf,0x4ccdcd81,0x140c0c18,0x35131326,0x2fececc3,

-    0xe15f5fbe,0xa2979735,0xcc444488,0x3917172e,0x57c4c493,0xf2a7a755,

-    0x827e7efc,0x473d3d7a,0xac6464c8,0xe75d5dba,0x2b191932,0x957373e6,

-    0xa06060c0,0x98818119,0xd14f4f9e,0x7fdcdca3,0x66222244,0x7e2a2a54,

-    0xab90903b,0x8388880b,0xca46468c,0x29eeeec7,0xd3b8b86b,0x3c141428,

-    0x79dedea7,0xe25e5ebc,0x1d0b0b16,0x76dbdbad,0x3be0e0db,0x56323264,

-    0x4e3a3a74,0x1e0a0a14,0xdb494992,0xa06060c,0x6c242448,0xe45c5cb8,

-    0x5dc2c29f,0x6ed3d3bd,0xefacac43,0xa66262c4,0xa8919139,0xa4959531,

-    0x37e4e4d3,0x8b7979f2,0x32e7e7d5,0x43c8c88b,0x5937376e,0xb76d6dda,

-    0x8c8d8d01,0x64d5d5b1,0xd24e4e9c,0xe0a9a949,0xb46c6cd8,0xfa5656ac,

-    0x7f4f4f3,0x25eaeacf,0xaf6565ca,0x8e7a7af4,0xe9aeae47,0x18080810,

-    0xd5baba6f,0x887878f0,0x6f25254a,0x722e2e5c,0x241c1c38,0xf1a6a657,

-    0xc7b4b473,0x51c6c697,0x23e8e8cb,0x7cdddda1,0x9c7474e8,0x211f1f3e,

-    0xdd4b4b96,0xdcbdbd61,0x868b8b0d,0x858a8a0f,0x907070e0,0x423e3e7c,

-    0xc4b5b571,0xaa6666cc,0xd8484890,0x5030306,0x1f6f6f7,0x120e0e1c,

-    0xa36161c2,0x5f35356a,0xf95757ae,0xd0b9b969,0x91868617,0x58c1c199,

-    0x271d1d3a,0xb99e9e27,0x38e1e1d9,0x13f8f8eb,0xb398982b,0x33111122,

-    0xbb6969d2,0x70d9d9a9,0x898e8e07,0xa7949433,0xb69b9b2d,0x221e1e3c,

-    0x92878715,0x20e9e9c9,0x49cece87,0xff5555aa,0x78282850,0x7adfdfa5,

-    0x8f8c8c03,0xf8a1a159,0x80898909,0x170d0d1a,0xdabfbf65,0x31e6e6d7,

-    0xc6424284,0xb86868d0,0xc3414182,0xb0999929,0x772d2d5a,0x110f0f1e,

-    0xcbb0b07b,0xfc5454a8,0xd6bbbb6d,0x3a16162c]

-

-    private static let rtable:[UInt32] =

-    [0x50a7f451,0x5365417e,0xc3a4171a,0x965e273a,0xcb6bab3b,0xf1459d1f,

-    0xab58faac,0x9303e34b,0x55fa3020,0xf66d76ad,0x9176cc88,0x254c02f5,

-    0xfcd7e54f,0xd7cb2ac5,0x80443526,0x8fa362b5,0x495ab1de,0x671bba25,

-    0x980eea45,0xe1c0fe5d,0x2752fc3,0x12f04c81,0xa397468d,0xc6f9d36b,

-    0xe75f8f03,0x959c9215,0xeb7a6dbf,0xda595295,0x2d83bed4,0xd3217458,

-    0x2969e049,0x44c8c98e,0x6a89c275,0x78798ef4,0x6b3e5899,0xdd71b927,

-    0xb64fe1be,0x17ad88f0,0x66ac20c9,0xb43ace7d,0x184adf63,0x82311ae5,

-    0x60335197,0x457f5362,0xe07764b1,0x84ae6bbb,0x1ca081fe,0x942b08f9,

-    0x58684870,0x19fd458f,0x876cde94,0xb7f87b52,0x23d373ab,0xe2024b72,

-    0x578f1fe3,0x2aab5566,0x728ebb2,0x3c2b52f,0x9a7bc586,0xa50837d3,

-    0xf2872830,0xb2a5bf23,0xba6a0302,0x5c8216ed,0x2b1ccf8a,0x92b479a7,

-    0xf0f207f3,0xa1e2694e,0xcdf4da65,0xd5be0506,0x1f6234d1,0x8afea6c4,

-    0x9d532e34,0xa055f3a2,0x32e18a05,0x75ebf6a4,0x39ec830b,0xaaef6040,

-    0x69f715e,0x51106ebd,0xf98a213e,0x3d06dd96,0xae053edd,0x46bde64d,

-    0xb58d5491,0x55dc471,0x6fd40604,0xff155060,0x24fb9819,0x97e9bdd6,

-    0xcc434089,0x779ed967,0xbd42e8b0,0x888b8907,0x385b19e7,0xdbeec879,

-    0x470a7ca1,0xe90f427c,0xc91e84f8,0x0,0x83868009,0x48ed2b32,

-    0xac70111e,0x4e725a6c,0xfbff0efd,0x5638850f,0x1ed5ae3d,0x27392d36,

-    0x64d90f0a,0x21a65c68,0xd1545b9b,0x3a2e3624,0xb1670a0c,0xfe75793,

-    0xd296eeb4,0x9e919b1b,0x4fc5c080,0xa220dc61,0x694b775a,0x161a121c,

-    0xaba93e2,0xe52aa0c0,0x43e0223c,0x1d171b12,0xb0d090e,0xadc78bf2,

-    0xb9a8b62d,0xc8a91e14,0x8519f157,0x4c0775af,0xbbdd99ee,0xfd607fa3,

-    0x9f2601f7,0xbcf5725c,0xc53b6644,0x347efb5b,0x7629438b,0xdcc623cb,

-    0x68fcedb6,0x63f1e4b8,0xcadc31d7,0x10856342,0x40229713,0x2011c684,

-    0x7d244a85,0xf83dbbd2,0x1132f9ae,0x6da129c7,0x4b2f9e1d,0xf330b2dc,

-    0xec52860d,0xd0e3c177,0x6c16b32b,0x99b970a9,0xfa489411,0x2264e947,

-    0xc48cfca8,0x1a3ff0a0,0xd82c7d56,0xef903322,0xc74e4987,0xc1d138d9,

-    0xfea2ca8c,0x360bd498,0xcf81f5a6,0x28de7aa5,0x268eb7da,0xa4bfad3f,

-    0xe49d3a2c,0xd927850,0x9bcc5f6a,0x62467e54,0xc2138df6,0xe8b8d890,

-    0x5ef7392e,0xf5afc382,0xbe805d9f,0x7c93d069,0xa92dd56f,0xb31225cf,

-    0x3b99acc8,0xa77d1810,0x6e639ce8,0x7bbb3bdb,0x97826cd,0xf418596e,

-    0x1b79aec,0xa89a4f83,0x656e95e6,0x7ee6ffaa,0x8cfbc21,0xe6e815ef,

-    0xd99be7ba,0xce366f4a,0xd4099fea,0xd67cb029,0xafb2a431,0x31233f2a,

-    0x3094a5c6,0xc066a235,0x37bc4e74,0xa6ca82fc,0xb0d090e0,0x15d8a733,

-    0x4a9804f1,0xf7daec41,0xe50cd7f,0x2ff69117,0x8dd64d76,0x4db0ef43,

-    0x544daacc,0xdf0496e4,0xe3b5d19e,0x1b886a4c,0xb81f2cc1,0x7f516546,

-    0x4ea5e9d,0x5d358c01,0x737487fa,0x2e410bfb,0x5a1d67b3,0x52d2db92,

-    0x335610e9,0x1347d66d,0x8c61d79a,0x7a0ca137,0x8e14f859,0x893c13eb,

-    0xee27a9ce,0x35c961b7,0xede51ce1,0x3cb1477a,0x59dfd29c,0x3f73f255,

-    0x79ce1418,0xbf37c773,0xeacdf753,0x5baafd5f,0x146f3ddf,0x86db4478,

-    0x81f3afca,0x3ec468b9,0x2c342438,0x5f40a3c2,0x72c31d16,0xc25e2bc,

-    0x8b493c28,0x41950dff,0x7101a839,0xdeb30c08,0x9ce4b4d8,0x90c15664,

-    0x6184cb7b,0x70b632d5,0x745c6c48,0x4257b8d0]

-

-    /* Rotates 32-bit word left by 1, 2 or 3 byte  */

-

-    private static func ROTL8(x: UInt32) -> UInt32

-    {

-        return (((x)<<8)|((x)>>24))

-    }

-

-    private static func ROTL16(x: UInt32) -> UInt32

-    {

-        return (((x)<<16)|((x)>>16))

-    }

-

-    private static func ROTL24(x: UInt32) -> UInt32

-    {

-        return (((x)<<24)|((x)>>8))

-    }

-

-    private static func pack(b: [UInt8]) -> UInt32

-    { /* pack bytes into a 32-bit Word */

-        var r=((UInt32(b[3])&0xff)<<24)|((UInt32(b[2])&0xff)<<16)

-        r = r|((UInt32(b[1])&0xff)<<8)|(UInt32(b[0])&0xff)

-        return r

-    }

-

-    private static func unpack(a: UInt32) -> [UInt8]

-    { /* unpack bytes from a word */

-        let b:[UInt8]=[UInt8(a&0xff),UInt8((a>>8)&0xff),UInt8((a>>16)&0xff),UInt8((a>>24)&0xff)];

-        return b;

-    }

-

-    private static func bmul(x: UInt8,_ y:UInt8) -> UInt8

-    { /* x.y= AntiLog(Log(x) + Log(y)) */

-

-        let ix=Int(x)&0xff

-        let iy=Int(y)&0xff

-        let lx=Int(ltab[ix])&0xff

-        let ly=Int(ltab[iy])&0xff

-

-        if x != 0 && y != 0 {return ptab[(lx+ly)%255]}

-        else {return UInt8(0)}

-    }

-

-    private static func SubByte(a: UInt32) -> UInt32

-    {

-        var b=unpack(a)

-        b[0]=fbsub[Int(b[0])]

-        b[1]=fbsub[Int(b[1])]

-        b[2]=fbsub[Int(b[2])]

-        b[3]=fbsub[Int(b[3])]

-        return pack(b);

-    }

-

-    private static func product(x: UInt32,_ y: UInt32) -> UInt8

-    { /* dot product of two 4-byte arrays */

-        var xb=unpack(x);

-        var yb=unpack(y);

-

-        return (bmul(xb[0],yb[0])^bmul(xb[1],yb[1])^bmul(xb[2],yb[2])^bmul(xb[3],yb[3]))

-    }

-

-    private static func InvMixCol(x: UInt32) -> UInt32

-    { /* matrix Multiplication */

-        var b=[UInt8](count:4,repeatedValue:0)

-        var m=pack(InCo);

-        b[3]=product(m,x);

-        m=ROTL24(m);

-        b[2]=product(m,x);

-        m=ROTL24(m);

-        b[1]=product(m,x);

-        m=ROTL24(m);

-        b[0]=product(m,x);

-        let y=pack(b)

-        return y

-    }

-

-    /* reset cipher */

-    func reset(m: Int,_ iv:[UInt8]?)

-    { /* reset mode, or reset iv */

-        mode=m;

-        for var i=0;i<16;i++ {f[i]=0}

-        if (mode != AES.ECB) && (iv != nil)

-            {for var i=0;i<16;i++ {f[i]=iv![i]}} /*??*/

-    }

-

-    func init_it(m:Int,_ key:[UInt8],_ iv:[UInt8]?)

-    {   /* Key=16 bytes */

-        /* Key Scheduler. Create expanded encryption key */

-        var CipherKey=[UInt32](count:4,repeatedValue:0)

-        var b=[UInt8](count:4,repeatedValue:0)

-        let nk=4;

-        reset(m,iv);

-        let N=44;

-

-        var j=0

-        for  var i=0;i<nk;i++

-        {

-            for var k=0;k<4;k++ {b[k]=key[j+k]}

-            CipherKey[i]=AES.pack(b);

-            j+=4;

-        }

-        for var i=0;i<nk;i++ {fkey[i]=CipherKey[i]}

-        j=nk

-        for var k=0;j<N;k++

-        {

-            fkey[j]=fkey[j-nk]^AES.SubByte(AES.ROTL24(fkey[j-1]))^UInt32(AES.rco[k])

-            for var i=1;i<nk && (i+j)<N;i++

-            {

-                fkey[i+j]=fkey[i+j-nk]^fkey[i+j-1]

-            }

-            j+=nk

-        }

-

-        /* now for the expanded decrypt key in reverse order */

-

-        for var j=0;j<4;j++ {rkey[j+N-4]=fkey[j]}

-        for var i=4;i<N-4;i+=4

-        {

-            let k=N-4-i;

-            for var j=0;j<4;j++ {rkey[k+j]=AES.InvMixCol(fkey[i+j])}

-        }

-        for var j=N-4;j<N;j++ {rkey[j-N+4]=fkey[j]}

-    }

-

-    func getreg() -> [UInt8]

-    {

-        var ir=[UInt8](count:16,repeatedValue:0)

-        for var i=0;i<16;i++ {ir[i]=f[i]}

-        return ir;

-    }

-

-    /* Encrypt a single block */

-    func ecb_encrypt(inout buff:[UInt8])

-    {

-        var b=[UInt8](count:4,repeatedValue:0)

-        var p=[UInt32](count:4,repeatedValue:0)

-        var q=[UInt32](count:4,repeatedValue:0)

-

-        var j=0

-        for var i=0;i<4;i++

-        {

-            for var k=0;k<4;k++ {b[k]=buff[j+k]}

-            p[i]=AES.pack(b);

-            p[i]^=fkey[i];

-            j+=4

-        }

-

-        var k=4;

-

-    /* State alternates between p and q */

-        for var i=1;i<10;i++

-        {

-            q[0]=fkey[k]^AES.ftable[Int(p[0]&0xff)]^AES.ROTL8(AES.ftable[Int((p[1]>>8)&0xff)])^AES.ROTL16(AES.ftable[Int((p[2]>>16)&0xff)])^AES.ROTL24(AES.ftable[Int((p[3]>>24)&0xff)])

-

-            q[1]=fkey[k+1]^AES.ftable[Int(p[1]&0xff)]^AES.ROTL8(AES.ftable[Int((p[2]>>8)&0xff)])^AES.ROTL16(AES.ftable[Int((p[3]>>16)&0xff)])^AES.ROTL24(AES.ftable[Int((p[0]>>24)&0xff)])

-

-            q[2]=fkey[k+2]^AES.ftable[Int(p[2]&0xff)]^AES.ROTL8(AES.ftable[Int((p[3]>>8)&0xff)])^AES.ROTL16(AES.ftable[Int((p[0]>>16)&0xff)])^AES.ROTL24(AES.ftable[Int((p[1]>>24)&0xff)])

-

-            q[3]=fkey[k+3]^AES.ftable[Int(p[3]&0xff)]^AES.ROTL8(AES.ftable[Int((p[0]>>8)&0xff)])^AES.ROTL16(AES.ftable[Int((p[1]>>16)&0xff)])^AES.ROTL24(AES.ftable[Int((p[2]>>24)&0xff)])

-

-            k+=4;

-            for (j=0;j<4;j++)

-            {

-				let t=p[j]; p[j]=q[j]; q[j]=t;

-            }

-        }

-

-    /* Last Round */

-

-        q[0]=fkey[k]^UInt32(AES.fbsub[Int(p[0]&0xff)])^AES.ROTL8(UInt32(AES.fbsub[Int((p[1]>>8)&0xff)]))^AES.ROTL16(UInt32(AES.fbsub[Int((p[2]>>16)&0xff)]))^AES.ROTL24(UInt32(AES.fbsub[Int((p[3]>>24)&0xff)]))

-

-        q[1]=fkey[k+1]^UInt32(AES.fbsub[Int(p[1]&0xff)])^AES.ROTL8(UInt32(AES.fbsub[Int((p[2]>>8)&0xff)]))^AES.ROTL16(UInt32(AES.fbsub[Int((p[3]>>16)&0xff)]))^AES.ROTL24(UInt32(AES.fbsub[Int((p[0]>>24)&0xff)]))

-

-        q[2]=fkey[k+2]^UInt32(AES.fbsub[Int(p[2]&0xff)])^AES.ROTL8(UInt32(AES.fbsub[Int((p[3]>>8)&0xff)]))^AES.ROTL16(UInt32(AES.fbsub[Int((p[0]>>16)&0xff)]))^AES.ROTL24(UInt32(AES.fbsub[Int((p[1]>>24)&0xff)]))

-

-        q[3]=fkey[k+3]^UInt32(AES.fbsub[Int((p[3])&0xff)])^AES.ROTL8(UInt32(AES.fbsub[Int((p[0]>>8)&0xff)]))^AES.ROTL16(UInt32(AES.fbsub[Int((p[1]>>16)&0xff)]))^AES.ROTL24(UInt32(AES.fbsub[Int((p[2]>>24)&0xff)]))

-

-        j=0

-        for var i=0;i<4;i++

-        {

-            b=AES.unpack(q[i])

-            for var k=0;k<4;k++ {buff[j+k]=b[k]}

-            j+=4

-        }

-    }

-

-    /* Decrypt a single block */

-    func ecb_decrypt(inout buff:[UInt8])

-    {

-        var b=[UInt8](count:4,repeatedValue:0)

-        var p=[UInt32](count:4,repeatedValue:0)

-        var q=[UInt32](count:4,repeatedValue:0)

-

-        var j=0

-        for var i=0;i<4;i++

-        {

-            for var k=0;k<4;k++ {b[k]=buff[j+k]}

-            p[i]=AES.pack(b);

-            p[i]^=rkey[i];

-            j+=4

-        }

-

-        var k=4

-

-    /* State alternates between p and q */

-        for var i=1;i<10;i++

-        {

-

-            q[0]=rkey[k]^AES.rtable[Int(p[0]&0xff)]^AES.ROTL8(AES.rtable[Int((p[3]>>8)&0xff)])^AES.ROTL16(AES.rtable[Int((p[2]>>16)&0xff)])^AES.ROTL24(AES.rtable[Int((p[1]>>24)&0xff)])

-

-            q[1]=rkey[k+1]^AES.rtable[Int(p[1]&0xff)]^AES.ROTL8(AES.rtable[Int((p[0]>>8)&0xff)])^AES.ROTL16(AES.rtable[Int((p[3]>>16)&0xff)])^AES.ROTL24(AES.rtable[Int((p[2]>>24)&0xff)])

-

-

-            q[2]=rkey[k+2]^AES.rtable[Int(p[2]&0xff)]^AES.ROTL8(AES.rtable[Int((p[1]>>8)&0xff)])^AES.ROTL16(AES.rtable[Int((p[0]>>16)&0xff)])^AES.ROTL24(AES.rtable[Int((p[3]>>24)&0xff)])

-

-            q[3]=rkey[k+3]^AES.rtable[Int(p[3]&0xff)]^AES.ROTL8(AES.rtable[Int((p[2]>>8)&0xff)])^AES.ROTL16(AES.rtable[Int((p[1]>>16)&0xff)])^AES.ROTL24(AES.rtable[Int((p[0]>>24)&0xff)])

-

-

-            k+=4;

-            for var j=0;j<4;j++

-            {

-				let t=p[j]; p[j]=q[j]; q[j]=t;

-            }

-        }

-

-    /* Last Round */

-

-        q[0]=rkey[k]^UInt32(AES.rbsub[Int(p[0]&0xff)])^AES.ROTL8(UInt32(AES.rbsub[Int((p[3]>>8)&0xff)]))^AES.ROTL16(UInt32(AES.rbsub[Int((p[2]>>16)&0xff)]))^AES.ROTL24(UInt32(AES.rbsub[Int((p[1]>>24)&0xff)]))

-

-        q[1]=rkey[k+1]^UInt32(AES.rbsub[Int(p[1]&0xff)])^AES.ROTL8(UInt32(AES.rbsub[Int((p[0]>>8)&0xff)]))^AES.ROTL16(UInt32(AES.rbsub[Int((p[3]>>16)&0xff)]))^AES.ROTL24(UInt32(AES.rbsub[Int((p[2]>>24)&0xff)]))

-

-

-        q[2]=rkey[k+2]^UInt32(AES.rbsub[Int(p[2]&0xff)])^AES.ROTL8(UInt32(AES.rbsub[Int((p[1]>>8)&0xff)]))^AES.ROTL16(UInt32(AES.rbsub[Int((p[0]>>16)&0xff)]))^AES.ROTL24(UInt32(AES.rbsub[Int((p[3]>>24)&0xff)]))

-

-        q[3]=rkey[k+3]^UInt32(AES.rbsub[Int((p[3])&0xff)])^AES.ROTL8(UInt32(AES.rbsub[Int((p[2]>>8)&0xff)]))^AES.ROTL16(UInt32(AES.rbsub[Int((p[1]>>16)&0xff)]))^AES.ROTL24(UInt32(AES.rbsub[Int((p[0]>>24)&0xff)]))

-

-        j=0

-        for var i=0;i<4;i++

-        {

-            b=AES.unpack(q[i]);

-            for var k=0;k<4;k++ {buff[j+k]=b[k]}

-            j+=4

-        }

-    }

-

-    /* Encrypt using selected mode of operation */

-    func encrypt(inout buff:[UInt8]) -> UInt32

-    {

-        var st=[UInt8](count:16,repeatedValue:0)

-

-    // Supported Modes of Operation

-

-        var fell_off:UInt32=0;

-        switch (mode)

-        {

-        case AES.ECB:

-            ecb_encrypt(&buff)

-            return 0

-        case AES.CBC:

-            for var j=0;j<16;j++ {buff[j]^=f[j]}

-            ecb_encrypt(&buff);

-            for var j=0;j<16;j++ {f[j]=buff[j]}

-            return 0;

-

-        case AES.CFB1:

-            fallthrough

-        case AES.CFB2:

-            fallthrough

-        case AES.CFB4:

-            let bytes=mode-AES.CFB1+1

-            for var j=0;j<bytes;j++ {fell_off=(fell_off<<8)|UInt32(f[j])}

-            for var j=0;j<16;j++ {st[j]=f[j]}

-            for var j=bytes;j<16;j++ {f[j-bytes]=f[j]}

-            ecb_encrypt(&st);

-            for var j=0;j<bytes;j++

-            {

-				buff[j]^=st[j];

-				f[16-bytes+j]=buff[j];

-            }

-            return fell_off;

-

-        case AES.OFB1:

-            fallthrough

-        case AES.OFB2:

-            fallthrough

-        case AES.OFB4:

-            fallthrough

-        case AES.OFB8:

-            fallthrough

-        case AES.OFB16:

-

-            let bytes=mode-AES.OFB1+1

-            ecb_encrypt(&f)

-            for var j=0;j<bytes;j++ {buff[j]^=f[j]}

-            return 0;

-

-        default:

-            return 0;

-        }

-    }

-

-    /* Decrypt using selected mode of operation */

-    func decrypt(inout buff:[UInt8]) -> UInt32

-    {

-

-        var st=[UInt8](count:16,repeatedValue:0)

-

-        // Supported Modes of Operation

-

-        var fell_off:UInt32=0;

-        switch (mode)

-        {

-        case AES.ECB:

-            ecb_decrypt(&buff);

-            return 0;

-        case AES.CBC:

-            for var j=0;j<16;j++

-            {

-				st[j]=f[j];

-				f[j]=buff[j];

-            }

-            ecb_decrypt(&buff);

-            for var j=0;j<16;j++

-            {

-				buff[j]^=st[j];

-				st[j]=0;

-            }

-            return 0;

-        case AES.CFB1:

-            fallthrough

-        case AES.CFB2:

-            fallthrough

-        case AES.CFB4:

-            let bytes=mode-AES.CFB1+1;

-            for var j=0;j<bytes;j++ {fell_off=(fell_off<<8)|UInt32(f[j])}

-            for var j=0;j<16;j++ {st[j]=f[j]}

-            for var j=bytes;j<16;j++ {f[j-bytes]=f[j]}

-            ecb_encrypt(&st);

-            for var j=0;j<bytes;j++

-            {

-				f[16-bytes+j]=buff[j]

-				buff[j]^=st[j]

-            }

-            return fell_off

-        case AES.OFB1:

-            fallthrough

-        case AES.OFB2:

-            fallthrough

-        case AES.OFB4:

-            fallthrough

-        case AES.OFB8:

-            fallthrough

-        case AES.OFB16:

-            let bytes=mode-AES.OFB1+1

-            ecb_encrypt(&f);

-            for var j=0;j<bytes;j++ {buff[j]^=f[j]}

-            return 0;

-

-        default:

-            return 0;

-        }

-    }

-

-    /* Clean up and delete left-overs */

-    func end()

-    { // clean up

-        for var i=0;i<44;i++

-            {fkey[i]=0; rkey[i]=0}

-        for var i=0;i<16;i++

-            {f[i]=0}

-    }

-

-}

diff --git a/swift/big.swift b/swift/big.swift
deleted file mode 100644
index 3ac9c63..0000000
--- a/swift/big.swift
+++ /dev/null
@@ -1,920 +0,0 @@
-/*

-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.

-*/

-//

-//  big.swift

-//  

-//

-//  Created by Michael Scott on 12/06/2015.

-//  Copyright (c) 2015 Michael Scott. All rights reserved.

-//  BIG number class

-//

-

-final class BIG{

-    var w=[Int32](count:ROM.NLEN,repeatedValue:0)

-/* Constructors */

-    init() {

-        for var i=0;i<ROM.NLEN;i++ {w[i]=0}

-    }

-    init(_ x: Int32)

-    {

-        w[0]=x;

-        for var i=1;i<ROM.NLEN;i++ {w[i]=0}

-    }

-    init(_ x: BIG)

-    {

-        for var i=0;i<ROM.NLEN;i++ {w[i]=x.w[i]}

-    }

-    init(_ x: DBIG)

-    {

-        for var i=0;i<ROM.NLEN;i++ {w[i]=x.w[i]}

-    }

-    init(_ x: [Int32])

-    {

-        for var i=0;i<ROM.NLEN;i++ {w[i]=x[i]}

-    }

-    func get(i: Int) -> Int32

-    {

-        return w[i]

-    }

-    func set(i: Int,_ x: Int32)

-    {

-        w[i]=x

-    }

-    func xortop(x: Int32)

-    {

-        w[ROM.NLEN-1]^=x

-    }

-    func ortop(x: Int32)

-    {

-        w[ROM.NLEN-1]|=x

-    }

-/* calculate Field Excess */

-    static func EXCESS(a: BIG) -> Int32

-    {

-        return ((a.w[ROM.NLEN-1] & ROM.OMASK)>>Int32(ROM.MODBITS%ROM.BASEBITS))

-    }

-/* test for zero */

-    func iszilch() -> Bool

-    {

-        for var i=0;i<ROM.NLEN;i++ {if w[i] != 0 {return false}}

-        return true

-    }

-/* set to zero */

-    func zero()

-    {

-        for var i=0;i<ROM.NLEN;i++ {w[i] = 0}

-    }

-/* set to one */

-    func one()

-    {

-        w[0]=1

-        for var i=1;i<ROM.NLEN;i++ {w[i]=0}

-    }

-/* Test for equal to one */

-    func isunity() -> Bool

-    {

-        for var i=1;i<ROM.NLEN;i++ {if w[i] != 0 {return false}}

-        if w[0] != 1 {return false}

-        return true

-    }

-/* Copy from another BIG */

-    func copy(x: BIG)

-    {

-        for var i=0;i<ROM.NLEN;i++ {w[i] = x.w[i]}

-    }

-    func copy(x: DBIG)

-    {

-        for var i=0;i<ROM.NLEN;i++ {w[i] = x.w[i]}

-    }

-/* Conditional swap of two bigs depending on d using XOR - no branches */

-    func cswap(b: BIG,_ d: Int32)

-    {

-        var c:Int32 = d

-        c = ~(c-1)

-        for var i=0;i<ROM.NLEN;i++

-        {

-            let t=c&(w[i]^b.w[i])

-            w[i]^=t

-            b.w[i]^=t

-        }

-    }

-    func cmove(g: BIG,_ d: Int32)

-    {

-        let b:Int32 = -d;

-

-        for var i=0;i<ROM.NLEN;i++

-        {

-            w[i]^=(w[i]^g.w[i])&b;

-        }

-    }

-/* normalise BIG - force all digits < 2^BASEBITS */

-    func norm() -> Int32

-    {

-        var carry:Int32=0

-        for var i=0;i<ROM.NLEN-1;i++

-        {

-            let d=w[i]+carry

-            w[i]=d&ROM.MASK

-            carry=d>>ROM.BASEBITS

-        }

-        w[ROM.NLEN-1]+=carry

-        return (w[ROM.NLEN-1]>>((8*ROM.MODBYTES)%ROM.BASEBITS))

-    }

-/* Shift right by less than a word */

-    func fshr(k: Int) -> Int32

-    {

-        let kw=Int32(k)

-        let r=w[0]&((Int32(1)<<kw)-1)

-        for var i=0;i<ROM.NLEN-1;i++

-        {

-            w[i]=(w[i]>>kw)|((w[i+1]<<(ROM.BASEBITS-kw))&ROM.MASK)

-        }

-        w[ROM.NLEN-1]>>=kw;

-        return r

-    }

-/* general shift right */

-    func shr(k: Int)

-    {

-        let n=Int32(k)%ROM.BASEBITS

-        let m=(k/Int(ROM.BASEBITS))

-        for var i=0;i<ROM.NLEN-m-1;i++

-        {

-            w[i]=(w[m+i]>>n)|((w[m+i+1]<<(ROM.BASEBITS-n))&ROM.MASK)

-        }

-        w[ROM.NLEN - m - 1]=w[ROM.NLEN-1]>>n

-        for var i=ROM.NLEN - m;i<ROM.NLEN;i++ {w[i]=0}

-    }

-/* Shift right by less than a word */

-    func fshl(k: Int) -> Int32

-    {

-        let kw=Int32(k)

-        w[ROM.NLEN-1]=((w[ROM.NLEN-1]<<kw))|(w[ROM.NLEN-2]>>(ROM.BASEBITS-kw))

-        for var i=ROM.NLEN-2;i>0;i--

-        {

-            w[i]=((w[i]<<kw)&ROM.MASK)|(w[i-1]>>(ROM.BASEBITS-kw))

-        }

-        w[0]=(w[0]<<kw)&ROM.MASK

-        return (w[ROM.NLEN-1]>>((8*ROM.MODBYTES)%ROM.BASEBITS))

-    }

-/* general shift left */

-    func shl(k: Int)

-    {

-        let n=Int32(k)%ROM.BASEBITS

-        let m=(k/Int(ROM.BASEBITS))

-        w[ROM.NLEN-1]=((w[ROM.NLEN-1-m]<<n))|(w[ROM.NLEN-m-2]>>(ROM.BASEBITS-n))

-        for var i=ROM.NLEN-2;i>m;i--

-        {

-            w[i]=((w[i-m]<<n)&ROM.MASK)|(w[i-m-1]>>(ROM.BASEBITS-n))

-        }

-        w[m]=(w[0]<<n)&ROM.MASK

-        for var i=0;i<m;i++ {w[i]=0}

-    }

-/* return number of bits */

-    func nbits() -> Int

-    {

-        var k=(ROM.NLEN-1)

-        norm()

-        while k>=0 && w[k]==0 {k--}

-        if k<0 {return 0}

-        var bts=Int(ROM.BASEBITS)*k

-        var c=w[k];

-        while c != 0 {c/=2; bts++}

-        return bts

-    }

-    func toRawString() -> String

-    {

-        var s:String="("

-        for var i=0;i<ROM.NLEN-1;i++

-        {

-            let n=String(w[i],radix:16,uppercase:false)

-            s+=n

-            s+=","

-

-        }

-        let n=String(w[ROM.NLEN-1],radix:16,uppercase:false)

-        s+=n

-        s+=")"

-        return s

-    }

-/* Convert to Hex String */

-    func toString() -> String

-    {

-        _ = BIG()

-        var s:String=""

-        var len=nbits()

-        if len%4 == 0 {len/=4}

-        else {len/=4; len++}

-        if len<2*Int(ROM.MODBYTES) {len=2*Int(ROM.MODBYTES)}

-

-        for var i=len-1;i>=0;i--

-        {

-            let b = BIG(self)

-            b.shr(i*4)

-            let n=String(b.w[0]&15,radix:16,uppercase:false)

-            s+=n

-        }

-

-        return s

-    }

-/* return this+x */

-    func plus(x: BIG) -> BIG

-    {

-        let s=BIG()

-        for var i=0;i<ROM.NLEN;i++

-        {

-            s.w[i]=w[i]+x.w[i]

-        }

-        return s

-    }

-/* this+=x */

-    func add(x: BIG)

-    {

-        for var i=0;i<ROM.NLEN;i++

-        {

-            w[i]+=x.w[i]

-        }

-    }

-/* this+=x, where x is int */

-    func inc(x: Int32) {

-        norm();

-        w[0]+=x;

-    }

-/* return this.x */

-   	func minus(x: BIG) -> BIG

-    {

-        let d=BIG();

-        for var i=0;i<ROM.NLEN;i++

-        {

-            d.w[i]=w[i]-x.w[i];

-        }

-        return d;

-    }

-/* this-=x */

-    func sub(x: BIG)

-    {

-        for var i=0;i<ROM.NLEN;i++

-        {

-            w[i]-=x.w[i]

-        }

-    }

-/* reverse subtract this=x-this */

-    func rsub(x: BIG)

-    {

-        for var i=0;i<ROM.NLEN;i++

-        {

-            w[i]=x.w[i]-w[i]

-        }

-    }

-/* this-=x where x is int */

-    func dec(x: Int32) {

-        norm();

-        w[0]-=x;

-    }

-/* this*=x, where x is small int<NEXCESS */

-    func imul(c: Int32)

-    {

-        for var i=0;i<ROM.NLEN;i++ {w[i]*=c}

-    }

-/* convert this BIG to byte array */

-    func tobytearray(inout b: [UInt8],_ n: Int)

-    {

-        norm();

-        let c=BIG(self);

-

-        for var i=Int(ROM.MODBYTES)-1;i>=0;i--

-        {

-            b[i+n]=UInt8(c.w[0]&0xff);

-            c.fshr(8);

-        }

-    }

-/* convert from byte array to BIG */

-    static func frombytearray(b: [UInt8],_ n: Int) -> BIG

-    {

-        let m=BIG();

-

-        for var i=0;i<Int(ROM.MODBYTES);i++

-        {

-            m.fshl(8)

-            m.w[0]+=Int32(b[i+n])&0xff    //(int)b[i+n]&0xff;

-        }

-        return m;

-    }

-    func toBytes(inout b: [UInt8])

-    {

-        tobytearray(&b,0)

-    }

-    static func fromBytes(b: [UInt8]) -> BIG

-    {

-        return frombytearray(b,0)

-    }

-/* set this[i]+=x*y+c, and return high part */

-    func muladd(x: Int32,_ y: Int32,_ c: Int32,_ i: Int) -> Int32

-    {

-        let prod:Int64 = Int64(x)*Int64(y)+Int64(c)+Int64(w[i])

-        w[i]=Int32(prod&Int64(ROM.MASK))

-        return Int32(prod>>Int64(ROM.BASEBITS))

-    }

-/* this*=x, where x is >NEXCESS */

-    func pmul(c: Int32) -> Int32

-    {

-        var carry:Int32=0;

-        norm();

-        for var i=0;i<ROM.NLEN;i++

-        {

-            let ak=w[i]

-            w[i]=0

-            carry=muladd(ak,c,carry,i);

-        }

-        return carry;

-    }

-/* this*=c and catch overflow in DBIG */

-    func pxmul(c: Int32) -> DBIG

-    {

-        let m=DBIG()

-        var carry:Int32=0

-        for var j=0;j<ROM.NLEN;j++

-        {

-            carry=m.muladd(w[j],c,carry,j)

-        }

-        m.w[ROM.NLEN]=carry

-        return m;

-    }

-/* divide by 3 */

-    func div3() -> Int32

-    {

-        var carry:Int32=0

-        norm();

-        let base=(1<<ROM.BASEBITS);

-        for var i=ROM.NLEN-1;i>=0;i--

-        {

-            let ak=(carry*base+w[i]);

-            w[i]=ak/3;

-            carry=ak%3;

-        }

-        return carry;

-    }

-/* return a*b where result fits in a BIG */

-    static func smul(a: BIG,_ b: BIG) -> BIG

-    {

-        let c=BIG()

-        for var i=0;i<ROM.NLEN;i++

-        {

-            var carry:Int32=0

-            for var j=0;j<ROM.NLEN;j++

-            {

-                if (i+j<ROM.NLEN) {carry=c.muladd(a.w[i],b.w[j],carry,i+j)}

-            }

-        }

-        return c;

-    }

-/* Compare a and b, return 0 if a==b, -1 if a<b, +1 if a>b. Inputs must be normalised */

-    static func comp(a: BIG,_ b: BIG) -> Int

-    {

-        for var i=ROM.NLEN-1;i>=0;i--

-        {

-            if (a.w[i]==b.w[i]) {continue}

-            if (a.w[i]>b.w[i]) {return 1}

-            else  {return -1}

-        }

-        return 0;

-    }

-/* set x = x mod 2^m */

-    func mod2m(m: Int)

-    {

-        let wd=m/Int(ROM.BASEBITS)

-        let bt=Int32(m)%ROM.BASEBITS

-        let msk=(1<<bt)-1;

-        w[wd]&=msk;

-        for var i=wd+1;i<ROM.NLEN;i++ {w[i]=0}

-    }

-/* Arazi and Qi inversion mod 256 */

-    static func invmod256(a: Int32) -> Int32

-    {

-        var t1:Int32=0

-        var c=(a>>1)&1

-        t1+=c

-        t1&=1

-        t1=2-t1

-        t1<<=1

-        var U=t1+1

-

-    // i=2

-        var b=a&3

-        t1=U*b; t1>>=2

-        c=(a>>2)&3

-        var t2=(U*c)&3

-        t1+=t2

-        t1*=U; t1&=3

-        t1=4-t1

-        t1<<=2

-        U+=t1

-

-    // i=4

-        b=a&15

-        t1=U*b; t1>>=4

-        c=(a>>4)&15

-        t2=(U*c)&15

-        t1+=t2

-        t1*=U; t1&=15

-        t1=16-t1

-        t1<<=4

-        U+=t1

-

-        return U

-    }

-/* return parity */

-    func parity() -> Int32

-    {

-        return Int32(w[0]%2)

-    }

-

-/* return n-th bit */

-    func bit(n: Int) -> Int32

-    {

-        if ((w[n/Int(ROM.BASEBITS)]&(Int32(1)<<(Int32(n)%ROM.BASEBITS)))>0) {return 1;}

-        else {return 0;}

-    }

-

-    /* return n last bits */

-    func lastbits(n: Int) -> Int32

-    {

-        let msk=(1<<Int32(n))-1;

-        norm();

-        return Int32((w[0])&msk)

-    }

-/* a=1/a mod 2^256. This is very fast! */

-    func invmod2m()

-    {

-        let U=BIG()

-        var b=BIG()

-        let c=BIG()

-

-        U.inc(BIG.invmod256(Int32(lastbits(8))))

-

-        for var i=8;i<256;i<<=1

-        {

-            b.copy(self)

-            b.mod2m(i)

-            let t1=BIG.smul(U,b)

-            t1.shr(i)

-            c.copy(self)

-            c.shr(i)

-            c.mod2m(i)

-

-            let t2=BIG.smul(U,c)

-            t2.mod2m(i)

-            t1.add(t2)

-            b=BIG.smul(t1,U)

-            t1.copy(b)

-            t1.mod2m(i)

-

-            t2.one(); t2.shl(i); t1.rsub(t2); t1.norm()

-            t1.shl(i)

-            U.add(t1)

-        }

-        self.copy(U)

-    }

-    /* reduce this mod m */

-    func mod(m: BIG)

-    {

-        var k=0

-        norm()

-        if (BIG.comp(self,m)<0) {return}

-        repeat

-        {

-            m.fshl(1)

-            k++

-        } while (BIG.comp(self,m)>=0)

-

-        while (k>0)

-        {

-            m.fshr(1)

-            if (BIG.comp(self,m)>=0)

-            {

-				sub(m)

-				norm()

-            }

-            k--

-        }

-    }

-    /* divide this by m */

-    func div(m: BIG)

-    {

-        var k=0

-        norm()

-        let e=BIG(1)

-        let b=BIG(self)

-        zero()

-

-        while (BIG.comp(b,m)>=0)

-        {

-            e.fshl(1)

-            m.fshl(1)

-            k++

-        }

-

-        while (k>0)

-        {

-            m.fshr(1)

-            e.fshr(1)

-            if (BIG.comp(b,m)>=0)

-            {

-				add(e)

-				norm()

-				b.sub(m)

-				b.norm()

-            }

-            k--;

-        }

-    }

-    /* get 8*MODBYTES size random number */

-    static func random(rng: RAND) -> BIG

-    {

-        let m=BIG();

-        var j:Int=0

-        var r:UInt8=0

-        /* generate random BIG */

-        for var i=0;i<Int(8*ROM.MODBYTES);i++

-        {

-            if (j==0) {r=rng.getByte()}

-            else {r>>=1}

-

-            let b=Int32(r&1);

-            m.shl(1); m.w[0]+=b;// m.inc(b);

-            j++; j&=7;

-        }

-        return m;

-    }

-

-    /* Create random BIG in portable way, one bit at a time, less than q */

-    static func randomnum(q: BIG,_ rng: RAND) -> BIG

-    {

-        let d=DBIG(0);

-        var j:Int=0

-        var r:UInt8=0

-

-        for var i=0;i<Int(2*ROM.MODBITS);i++

-        {

-            if (j==0) {r=rng.getByte()}

-            else {r>>=1}

-

-            let b=Int32(r&1);

-            d.shl(1); d.w[0]+=b; // m.inc(b);

-            j++; j&=7;

-        }

-        let m=d.mod(q);

-        return m;

-    }

-

-    /* return NAF value as +/- 1, 3 or 5. x and x3 should be normed.

-    nbs is number of bits processed, and nzs is number of trailing 0s detected */

-    static func nafbits(x: BIG,_ x3:BIG ,i:Int) -> [Int32]

-    {

-        var j:Int

-        var n=[Int32](count:3,repeatedValue:0)

-        var nb=x3.bit(i)-x.bit(i)

-        n[1]=1;

-        n[0]=0;

-        if (nb==0) {n[0]=0; return n}

-        if (i==0) {n[0]=nb; return n}

-        if (nb>0) {n[0]=1}

-        else      {n[0]=(-1)}

-

-        for j=i-1;j>0;j--

-        {

-            n[1]++

-            n[0]*=2

-            nb=x3.bit(j)-x.bit(j)

-            if (nb>0) {n[0]+=1}

-            if (nb<0) {n[0]-=1}

-            if (n[0]>5 || n[0] < -5) {break}

-        }

-

-        if ((n[0]%2 != 0) && (j != 0))

-        { /* backtrack */

-            if (nb>0) {n[0]=(n[0]-1)/2}

-            if (nb<0) {n[0]=(n[0]+1)/2}

-            n[1]--;

-        }

-        while (n[0]%2==0)

-        { /* remove trailing zeros */

-            n[0]/=2

-            n[2]++

-            n[1]--

-        }

-        return n;

-    }

-    /* Jacobi Symbol (this/p). Returns 0, 1 or -1 */

-    func jacobi(p: BIG) -> Int

-    {

-        var n8:Int32

-        var k:Int

-        var m:Int=0;

-        let t=BIG()

-        let x=BIG()

-        let n=BIG()

-        let zilch=BIG()

-        let one=BIG(1)

-        if (p.parity()==0 || BIG.comp(self,zilch)==0 || BIG.comp(p,one)<=0) {return 0}

-        norm()

-        x.copy(self)

-        n.copy(p)

-        x.mod(p)

-

-        while (BIG.comp(n,one)>0)

-        {

-            if (BIG.comp(x,zilch)==0) {return 0}

-            n8=n.lastbits(3)

-            k=0

-            while (x.parity()==0)

-            {

-				k++

-				x.shr(1)

-            }

-            if (k%2==1) {m+=(n8*n8-1)/8}

-            m+=(n8-1)*(x.lastbits(2)-1)/4

-            t.copy(n)

-            t.mod(x)

-            n.copy(x)

-            x.copy(t)

-            m%=2

-

-        }

-        if (m==0) {return 1}

-        else {return -1}

-    }

-    /* this=1/this mod p. Binary method */

-    func invmodp(p: BIG)

-    {

-        mod(p)

-        let u=BIG(self)

-        let v=BIG(p)

-        let x1=BIG(1)

-        let x2=BIG()

-        let t=BIG()

-        let one=BIG(1)

-

-        while ((BIG.comp(u,one) != 0 ) && (BIG.comp(v,one) != 0 ))

-        {

-            while (u.parity()==0)

-            {

-				u.shr(1);

-				if (x1.parity() != 0 )

-				{

-                    x1.add(p);

-                    x1.norm();

-				}

-				x1.shr(1);

-            }

-            while (v.parity()==0)

-            {

-				v.shr(1);

-				if (x2.parity() != 0 )

-				{

-                    x2.add(p);

-                    x2.norm();

-				}

-				x2.shr(1);

-            }

-            if (BIG.comp(u,v)>=0)

-            {

-				u.sub(v);

-				u.norm();

-                if (BIG.comp(x1,x2)>=0) {x1.sub(x2)}

-				else

-				{

-                    t.copy(p);

-                    t.sub(x2);

-                    x1.add(t);

-				}

-				x1.norm();

-            }

-            else

-            {

-				v.sub(u);

-				v.norm();

-                if (BIG.comp(x2,x1)>=0) {x2.sub(x1)}

-				else

-				{

-                    t.copy(p);

-                    t.sub(x1);

-                    x2.add(t);

-				}

-				x2.norm();

-            }

-        }

-        if (BIG.comp(u,one)==0) {copy(x1)}

-        else {copy(x2)}

-    }

-    /* return a*b as DBIG */

-    static func mul(a: BIG,_ b:BIG) -> DBIG

-    {

-        var t:Int64

-        var co:Int64

-        let c=DBIG()

-        let RM:Int64=Int64(ROM.MASK);

-        let RB:Int64=Int64(ROM.BASEBITS)

-        a.norm();

-        b.norm();

-

-        t=Int64(a.w[0])*Int64(b.w[0]); c.w[0]=Int32(t&RM); co=t>>RB

-        t=Int64(a.w[1])*Int64(b.w[0])+Int64(a.w[0])*Int64(b.w[1])+co; c.w[1]=Int32(t&RM); co=t>>RB

-

-        t=Int64(a.w[2])*Int64(b.w[0])+Int64(a.w[1])*Int64(b.w[1])+Int64(a.w[0])*Int64(b.w[2])+co; c.w[2]=Int32(t&RM); co=t>>RB

-        t=Int64(a.w[3])*Int64(b.w[0])+Int64(a.w[2])*Int64(b.w[1])+Int64(a.w[1])*Int64(b.w[2])+Int64(a.w[0])*Int64(b.w[3])+co; c.w[3]=Int32(t&RM); co=t>>RB

-

-        t=Int64(a.w[4])*Int64(b.w[0])+Int64(a.w[3])*Int64(b.w[1])+Int64(a.w[2])*Int64(b.w[2])+Int64(a.w[1])*Int64(b.w[3])+Int64(a.w[0])*Int64(b.w[4])+co; c.w[4]=Int32(t&RM); co=t>>RB;

-        t=Int64(a.w[5])*Int64(b.w[0])+Int64(a.w[4])*Int64(b.w[1])+Int64(a.w[3])*Int64(b.w[2])+Int64(a.w[2])*Int64(b.w[3])+Int64(a.w[1])*Int64(b.w[4])+Int64(a.w[0])*Int64(b.w[5])+co; c.w[5]=Int32(t&RM); co=t>>RB;

-        t=Int64(a.w[6])*Int64(b.w[0])+Int64(a.w[5])*Int64(b.w[1])+Int64(a.w[4])*Int64(b.w[2])+Int64(a.w[3])*Int64(b.w[3])+Int64(a.w[2])*Int64(b.w[4])+Int64(a.w[1])*Int64(b.w[5])+Int64(a.w[0])*Int64(b.w[6])+co; c.w[6]=Int32(t&RM); co=t>>RB;

-        t=Int64(a.w[7])*Int64(b.w[0])+Int64(a.w[6])*Int64(b.w[1])+Int64(a.w[5])*Int64(b.w[2])+Int64(a.w[4])*Int64(b.w[3])+Int64(a.w[3])*Int64(b.w[4])+Int64(a.w[2])*Int64(b.w[5])+Int64(a.w[1])*Int64(b.w[6])+Int64(a.w[0])*Int64(b.w[7])+co; c.w[7]=Int32(t&RM); co=t>>RB;

-        t=Int64(a.w[8])*Int64(b.w[0])+Int64(a.w[7])*Int64(b.w[1])+Int64(a.w[6])*Int64(b.w[2])+Int64(a.w[5])*Int64(b.w[3])+Int64(a.w[4])*Int64(b.w[4])+Int64(a.w[3])*Int64(b.w[5])+Int64(a.w[2])*Int64(b.w[6])+Int64(a.w[1])*Int64(b.w[7])+Int64(a.w[0])*Int64(b.w[8])+co; c.w[8]=Int32(t&RM); co=t>>RB;

-

-        t=Int64(a.w[8])*Int64(b.w[1])+Int64(a.w[7])*Int64(b.w[2])+Int64(a.w[6])*Int64(b.w[3])+Int64(a.w[5])*Int64(b.w[4])+Int64(a.w[4])*Int64(b.w[5])+Int64(a.w[3])*Int64(b.w[6])+Int64(a.w[2])*Int64(b.w[7])+Int64(a.w[1])*Int64(b.w[8])+co; c.w[9]=Int32(t&RM); co=t>>RB

-

-        t=Int64(a.w[8])*Int64(b.w[2])+Int64(a.w[7])*Int64(b.w[3])+Int64(a.w[6])*Int64(b.w[4])+Int64(a.w[5])*Int64(b.w[5])+Int64(a.w[4])*Int64(b.w[6])+Int64(a.w[3])*Int64(b.w[7])+Int64(a.w[2])*Int64(b.w[8])+co; c.w[10]=Int32(t&RM); co=t>>RB

-

-        t=Int64(a.w[8])*Int64(b.w[3])+Int64(a.w[7])*Int64(b.w[4])+Int64(a.w[6])*Int64(b.w[5])+Int64(a.w[5])*Int64(b.w[6])+Int64(a.w[4])*Int64(b.w[7])+Int64(a.w[3])*Int64(b.w[8])+co; c.w[11]=Int32(t&RM); co=t>>RB

-

-        t=Int64(a.w[8])*Int64(b.w[4])+Int64(a.w[7])*Int64(b.w[5])+Int64(a.w[6])*Int64(b.w[6])+Int64(a.w[5])*Int64(b.w[7])+Int64(a.w[4])*Int64(b.w[8])+co; c.w[12]=Int32(t&RM); co=t>>RB

-        t=Int64(a.w[8])*Int64(b.w[5])+Int64(a.w[7])*Int64(b.w[6])+Int64(a.w[6])*Int64(b.w[7])+Int64(a.w[5])*Int64(b.w[8])+co; c.w[13]=Int32(t&RM); co=t>>RB

-        t=Int64(a.w[8])*Int64(b.w[6])+Int64(a.w[7])*Int64(b.w[7])+Int64(a.w[6])*Int64(b.w[8])+co; c.w[14]=Int32(t&RM); co=t>>RB

-        t=Int64(a.w[8])*Int64(b.w[7])+Int64(a.w[7])*Int64(b.w[8])+co; c.w[15]=Int32(t&RM); co=t>>RB

-

-        t=Int64(a.w[8])*Int64(b.w[8])+co; c.w[16]=Int32(t&RM); co=t>>RB

-        c.w[17]=Int32(co)

-

-        return c

-    }

-

-    /* return a^2 as DBIG */

-    static func sqr(a: BIG) -> DBIG

-    {

-        var t:Int64

-        var co:Int64

-        let c=DBIG()

-        let RM:Int64=Int64(ROM.MASK);

-        let RB:Int64=Int64(ROM.BASEBITS)

-        a.norm();

-

-        t=Int64(a.w[0])*Int64(a.w[0]); c.w[0]=Int32(t&RM); co=t>>RB

-        t=Int64(a.w[1])*Int64(a.w[0]); t+=t; t+=co; c.w[1]=Int32(t&RM); co=t>>RB

-        t=Int64(a.w[2])*Int64(a.w[0]);t+=t; t+=Int64(a.w[1])*Int64(a.w[1]);t+=co;c.w[2]=Int32(t&RM);co=t>>RB

-        t=Int64(a.w[3])*Int64(a.w[0])+Int64(a.w[2])*Int64(a.w[1]); t+=t; t+=co; c.w[3]=Int32(t&RM); co=t>>RB

-        t=Int64(a.w[4])*Int64(a.w[0])+Int64(a.w[3])*Int64(a.w[1]); t+=t; t+=Int64(a.w[2])*Int64(a.w[2]); t+=co; c.w[4]=Int32(t&RM); co=t>>RB

-        t=Int64(a.w[5])*Int64(a.w[0])+Int64(a.w[4])*Int64(a.w[1])

-            t = t+Int64(a.w[3])*Int64(a.w[2])

-            t+=t; t+=co; c.w[5]=Int32(t&RM); co=t>>RB

-        t=Int64(a.w[6])*Int64(a.w[0])+Int64(a.w[5])*Int64(a.w[1])

-            t = t+Int64(a.w[4])*Int64(a.w[2])

-            t+=t; t+=Int64(a.w[3])*Int64(a.w[3]); t+=co; c.w[6]=Int32(t&RM); co=t>>RB

-        t=Int64(a.w[7])*Int64(a.w[0])+Int64(a.w[6])*Int64(a.w[1])

-        t = t+Int64(a.w[5])*Int64(a.w[2])+Int64(a.w[4])*Int64(a.w[3])

-            t+=t; t+=co; c.w[7]=Int32(t&RM); co=t>>RB

-        t=Int64(a.w[8])*Int64(a.w[0])+Int64(a.w[7])*Int64(a.w[1])

-            t = t+Int64(a.w[6])*Int64(a.w[2])+Int64(a.w[5])*Int64(a.w[3])

-            t+=t; t+=Int64(a.w[4])*Int64(a.w[4]); t+=co; c.w[8]=Int32(t&RM); co=t>>RB

-        t=Int64(a.w[8])*Int64(a.w[1])+Int64(a.w[7])*Int64(a.w[2])

-        t = t+Int64(a.w[6])*Int64(a.w[3])+Int64(a.w[5])*Int64(a.w[4])

-            t+=t; t+=co; c.w[9]=Int32(t&RM); co=t>>RB

-        t=Int64(a.w[8])*Int64(a.w[2])+Int64(a.w[7])*Int64(a.w[3])

-            t = t+Int64(a.w[6])*Int64(a.w[4])

-            t+=t; t+=Int64(a.w[5])*Int64(a.w[5]); t+=co; c.w[10]=Int32(t&RM); co=t>>RB

-        t=Int64(a.w[8])*Int64(a.w[3])+Int64(a.w[7])*Int64(a.w[4])

-            t = t+Int64(a.w[6])*Int64(a.w[5])

-            t+=t; t+=co; c.w[11]=Int32(t&RM); co=t>>RB

-        t=Int64(a.w[8])*Int64(a.w[4])+Int64(a.w[7])*Int64(a.w[5]); t+=t; t+=Int64(a.w[6])*Int64(a.w[6]); t+=co; c.w[12]=Int32(t&RM); co=t>>RB

-        t=Int64(a.w[8])*Int64(a.w[5])+Int64(a.w[7])*Int64(a.w[6]); t+=t; t+=co; c.w[13]=Int32(t&RM); co=t>>RB

-        t=Int64(a.w[8])*Int64(a.w[6]); t+=t; t+=Int64(a.w[7])*Int64(a.w[7]); t+=co; c.w[14]=Int32(t&RM); co=t>>RB

-        t=Int64(a.w[8])*Int64(a.w[7]); t+=t; t+=co; c.w[15]=Int32(t&RM); co=t>>RB

-        t=Int64(a.w[8])*Int64(a.w[8])+co; c.w[16]=Int32(t&RM); co=t>>RB

-        c.w[17]=Int32(co)

-

-    return c;

-    }

-

-    /* reduce a DBIG to a BIG using the appropriate form of the modulus */

-    static func mod(d: DBIG) -> BIG

-    {

-        var b=BIG()

-        if (ROM.MODTYPE==ROM.PSEUDO_MERSENNE)

-        {

-            let t=d.split(ROM.MODBITS)

-            b=BIG(d)

-            let v=t.pmul(ROM.MConst);

-            let tw=t.w[ROM.NLEN-1];

-            t.w[ROM.NLEN-1] &= ROM.TMASK;

-            t.inc(ROM.MConst*((tw>>ROM.TBITS)+(v<<(ROM.BASEBITS-ROM.TBITS))));

-

-            b.add(t);

-            b.norm();

-        }

-        if (ROM.MODTYPE==ROM.MONTGOMERY_FRIENDLY)

-        {

-            for var i=0;i<ROM.NLEN;i++

-                {d.w[ROM.NLEN+i]+=d.muladd(d.w[i],ROM.MConst-1,d.w[i],ROM.NLEN+i-1)}

-

-            b=BIG(0);

-

-            for var i=0;i<ROM.NLEN;i++

-            {

-                b.w[i]=d.w[ROM.NLEN+i]

-            }

-            b.norm()

-        }

-

-        if (ROM.MODTYPE==ROM.NOT_SPECIAL)

-        {

-            let md=BIG(ROM.Modulus);

-

-            var sum=Int64(d.w[0])

-            for var j=0;j<ROM.NLEN;j++

-            {

-                for var i=0;i<j;i++ {sum+=Int64(d.w[i])*Int64(md.w[j-i])}

-                let sp=(Int32(sum&Int64(ROM.MASK))&*ROM.MConst)&ROM.MASK

-                d.w[j]=sp; sum+=Int64(sp)*Int64(md.w[0])

-                sum=Int64(d.w[j+1])+(sum>>Int64(ROM.BASEBITS))

-            }

-

-            for var j=ROM.NLEN;j<ROM.DNLEN-2;j++

-            {

-                for var i=j-ROM.NLEN+1;i<ROM.NLEN;i++ {sum+=Int64(d.w[i])*Int64(md.w[j-i])}

-                    d.w[j]=Int32(sum&Int64(ROM.MASK))

-                sum=Int64(d.w[j+1])+(sum>>Int64(ROM.BASEBITS))

-            }

-

-            sum+=Int64(d.w[ROM.NLEN-1])*Int64(md.w[ROM.NLEN-1])

-            d.w[ROM.DNLEN-2]=Int32(sum&Int64(ROM.MASK))

-            sum=Int64(d.w[ROM.DNLEN-1])+(sum>>Int64(ROM.BASEBITS))

-            d.w[ROM.DNLEN-1]=Int32(sum&Int64(ROM.MASK))

-

-            b=BIG(0);

-

-            for var i=0;i<ROM.NLEN;i++

-            {

-                b.w[i]=d.w[ROM.NLEN+i];

-            }

-            b.norm();

-        }

-

-        return b;

-    }

-

-    /* return a*b mod m */

-    static func modmul(a: BIG,_ b :BIG,_ m: BIG) -> BIG

-    {

-        a.mod(m)

-        b.mod(m)

-        let d=mul(a,b)

-        return d.mod(m)

-    }

-

-    /* return a^2 mod m */

-    static func modsqr(a: BIG,_ m: BIG) -> BIG

-    {

-        a.mod(m)

-        let d=sqr(a)

-        return d.mod(m)

-    }

-

-    /* return -a mod m */

-    static func modneg(a: BIG,_ m: BIG) -> BIG

-    {

-        a.mod(m)

-        return m.minus(a)

-    }

-

-    /* return this^e mod m */

-    func powmod(e: BIG,_ m: BIG) -> BIG

-    {

-        norm();

-        e.norm();

-        var a=BIG(1)

-        let z=BIG(e)

-        var s=BIG(self)

-        while (true)

-        {

-            let bt=z.parity();

-            z.fshr(1)

-            if bt==1 {a=BIG.modmul(a,s,m)}

-            if (z.iszilch()) {break}

-            s=BIG.modsqr(s,m)

-        }

-        return a

-    }

-}

diff --git a/swift/dbig.swift b/swift/dbig.swift
deleted file mode 100644
index 9a3d124..0000000
--- a/swift/dbig.swift
+++ /dev/null
@@ -1,222 +0,0 @@
-/*

-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.

-*/

-//

-//  dbig.swift

-//  

-//

-//  Created by Michael Scott on 13/06/2015.

-//  Copyright (c) 2015 Michael Scott. All rights reserved.

-//

-

-final class DBIG{

-    var w=[Int32](count:ROM.DNLEN,repeatedValue:0)

-    init() {

-        for var i=0;i<ROM.DNLEN;i++ {w[i]=0}

-    }

-    init(_ x: Int32)

-    {

-        w[0]=x;

-        for var i=1;i<ROM.DNLEN;i++ {w[i]=0}

-    }

-    init(_ x: BIG)

-    {

-        for var i=0;i<ROM.NLEN;i++ {w[i]=x.w[i]}

-        w[ROM.NLEN-1]=x.w[ROM.NLEN-1]&ROM.MASK

-        w[ROM.NLEN]=x.w[ROM.NLEN-1]>>ROM.BASEBITS

-        for var i=ROM.NLEN+1;i<ROM.DNLEN;i++ {w[i]=0}

-    }

-    init(_ x: DBIG)

-    {

-        for var i=0;i<ROM.DNLEN;i++ {w[i]=x.w[i]}

-    }

-    init(_ x: [Int32])

-    {

-        for var i=0;i<ROM.DNLEN;i++ {w[i]=x[i]}

-    }

-    /* this-=x */

-    func sub(x: DBIG)

-    {

-        for var i=0;i<ROM.DNLEN;i++

-        {

-            w[i]-=x.w[i]

-        }

-    }

-    func muladd(x: Int32,_ y: Int32,_ c: Int32,_ i: Int) -> Int32

-    {

-        let prod:Int64 = Int64(x)*Int64(y)+Int64(c)+Int64(w[i])

-        w[i]=Int32(prod&Int64(ROM.MASK))

-        return Int32(prod>>Int64(ROM.BASEBITS))

-    }

-    /* general shift left */

-    func shl(k: Int)

-    {

-        let n=Int32(k)%ROM.BASEBITS

-        let m=(k/Int(ROM.BASEBITS))

-        w[ROM.DNLEN-1]=((w[ROM.DNLEN-1-m]<<n))|(w[ROM.DNLEN-m-2]>>(ROM.BASEBITS-n))

-        for var i=ROM.DNLEN-2;i>m;i--

-        {

-            w[i]=((w[i-m]<<n)&ROM.MASK)|(w[i-m-1]>>(ROM.BASEBITS-n))

-        }

-        w[m]=(w[0]<<n)&ROM.MASK

-        for var i=0;i<m;i++ {w[i]=0}

-    }

-    /* general shift right */

-    func shr(k: Int)

-    {

-        let n=Int32(k)%ROM.BASEBITS

-        let m=(k/Int(ROM.BASEBITS))

-        for var i=0;i<ROM.DNLEN-m-1;i++

-        {

-            w[i]=(w[m+i]>>n)|((w[m+i+1]<<(ROM.BASEBITS-n))&ROM.MASK)

-        }

-        w[ROM.DNLEN - m - 1]=w[ROM.DNLEN-1]>>n

-        for var i=ROM.DNLEN - m;i<ROM.DNLEN;i++ {w[i]=0}

-    }

-    /* Compare a and b, return 0 if a==b, -1 if a<b, +1 if a>b. Inputs must be normalised */

-    static func comp(a: DBIG,_ b: DBIG) -> Int

-    {

-        for var i=ROM.DNLEN-1;i>=0;i--

-        {

-            if (a.w[i]==b.w[i]) {continue}

-            if (a.w[i]>b.w[i]) {return 1}

-            else  {return -1}

-        }

-        return 0;

-    }

-    /* normalise BIG - force all digits < 2^BASEBITS */

-    func norm()

-    {

-        var carry:Int32=0

-        for var i=0;i<ROM.DNLEN-1;i++

-        {

-            let d=w[i]+carry

-            w[i]=d&ROM.MASK

-            carry=d>>ROM.BASEBITS

-        }

-        w[ROM.DNLEN-1]+=carry

-    }

-    /* reduces this DBIG mod a BIG, and returns the BIG */

-    func mod(c: BIG) -> BIG

-    {

-        var k:Int=0

-        norm()

-        let m=DBIG(c)

-

-        if DBIG.comp(self,m)<0 {return BIG(self)}

-

-        repeat

-        {

-            m.shl(1)

-            k++

-        }

-        while (DBIG.comp(self,m)>=0);

-

-        while (k>0)

-        {

-            m.shr(1)

-            if (DBIG.comp(self,m)>=0)

-            {

-				sub(m)

-				norm()

-            }

-            k--;

-        }

-        return BIG(self)

-    }

-    /* return this/c */

-    func div(c:BIG) -> BIG

-    {

-        var k:Int=0

-        let m=DBIG(c)

-        let a=BIG(0)

-        let e=BIG(1)

-        norm()

-

-        while (DBIG.comp(self,m)>=0)

-        {

-            e.fshl(1)

-            m.shl(1)

-            k++

-        }

-

-        while (k>0)

-        {

-            m.shr(1)

-            e.shr(1)

-            if (DBIG.comp(self,m)>0)

-            {

-				a.add(e)

-				a.norm()

-				sub(m)

-				norm()

-            }

-            k--

-        }

-        return a

-    }

-

-    /* split DBIG at position n, return higher half, keep lower half */

-    func split(n: Int32) -> BIG

-    {

-        let t=BIG(0)

-        let m=n%ROM.BASEBITS

-        var carry=w[ROM.DNLEN-1]<<(ROM.BASEBITS-m)

-

-        for var i=ROM.DNLEN-2;i>=ROM.NLEN-1;i--

-        {

-            let nw=(w[i]>>m)|carry;

-            carry=(w[i]<<(ROM.BASEBITS-m))&ROM.MASK;

-            t.set(i-ROM.NLEN+1,nw);

-        }

-        w[ROM.NLEN-1]&=Int32((Int32(1)<<m)-1);

-        return t;

-    }

-    /* return number of bits */

-    func nbits() -> Int

-    {

-        var k=(ROM.DNLEN-1)

-        norm()

-        while k>=0 && w[k]==0 {k--}

-        if k<0 {return 0}

-        var bts=Int(ROM.BASEBITS)*k

-        var c=w[k];

-        while c != 0 {c/=2; bts++}

-        return bts

-    }

-    /* Convert to Hex String */

-    func toString() -> String

-    {

-        _ = DBIG()

-        var s:String=""

-        var len=nbits()

-        if len%4 == 0 {len/=4}

-        else {len/=4; len++}

-

-        for var i=len-1;i>=0;i--

-        {

-            let b = DBIG(self)

-            b.shr(i*4)

-            let n=String(b.w[0]&15,radix:16,uppercase:false)

-            s+=n

-        }

-

-        return s

-    }

-

-}

diff --git a/swift/ecdh.swift b/swift/ecdh.swift
deleted file mode 100644
index 9f74372..0000000
--- a/swift/ecdh.swift
+++ /dev/null
@@ -1,531 +0,0 @@
-/*

-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.

-*/

-//

-//  ecdh.swift

-//  

-//

-//  Created by Michael Scott on 30/06/2015.

-//  Copyright (c) 2015 Michael Scott. All rights reserved.

-//

-

-import Foundation

-

-/* Elliptic Curve API high-level functions  */

-

-final public class ECDH

-{

-    static let INVALID_PUBLIC_KEY:Int = -2

-    static let ERROR:Int = -3

-    static let INVALID:Int = -4

-    static public let EFS=Int(ROM.MODBYTES);

-    static public let EGS=Int(ROM.MODBYTES);

-    static public let EAS=AES.KS;

-    static public let EBS=AES.BS;

-

-    /* Convert Integer to n-byte array */

-    private static func inttoBytes(n: Int,_ len:Int) -> [UInt8]

-    {

-        var b=[UInt8](count:len,repeatedValue:0)

-        var nn=n

-

-        var i=len;

-        while (nn>0 && i>0)

-        {

-            i--;

-            b[i]=UInt8(nn&0xff);

-            nn /= 256;

-        }

-        return b;

-    }

-

-    /* Key Derivation Functions */

-    /* Input octet Z */

-    /* Output key of length olen */

-    static public func KDF1(Z: [UInt8],_ olen:Int) -> [UInt8]

-    {

-    /* NOTE: the parameter olen is the length of the output K in bytes */

-        let H=HASH()

-        let hlen=HASH.len

-        var K=[UInt8](count:olen,repeatedValue:0)

-        var B=[UInt8](count:hlen,repeatedValue:0)

-

-        var k=0;

-

-        var cthreshold=olen/hlen; if (olen%hlen) != 0 {cthreshold++}

-

-        for var counter=0;counter<cthreshold;counter++

-        {

-            H.process_array(Z); if counter>0 {H.process_num(Int32(counter))}

-            B=H.hash();

-            if k+hlen>olen {for var i=0;i<olen%hlen;i++ {K[k++]=B[i]}}

-            else {for var i=0;i<hlen;i++ {K[k++]=B[i]}}

-        }

-        return K;

-    }

-

-    static public func KDF2(Z:[UInt8],_ P:[UInt8],_ olen:Int) -> [UInt8]

-    {

-    /* NOTE: the parameter olen is the length of the output k in bytes */

-        let H=HASH();

-        let hlen=HASH.len;

-        var K=[UInt8](count:olen,repeatedValue:0)

-        var B=[UInt8](count:hlen,repeatedValue:0)

-

-        var k=0;

-

-        var cthreshold=olen/hlen; if (olen%hlen) != 0 {cthreshold++}

-

-        for var counter=1;counter<=cthreshold;counter++

-        {

-            H.process_array(Z); H.process_num(Int32(counter)); H.process_array(P)

-            B=H.hash();

-            if k+hlen>olen {for var i=0;i<olen%hlen;i++ {K[k++]=B[i]}}

-            else {for var i=0;i<hlen;i++ {K[k++]=B[i]}}

-        }

-        return K;

-    }

-

-    /* Password based Key Derivation Function */

-    /* Input password p, salt s, and repeat count */

-    /* Output key of length olen */

-    static public func PBKDF2(Pass:[UInt8],_ Salt:[UInt8],_ rep:Int,_ olen:Int) -> [UInt8]

-    {

-        var d=olen/32;

-        if (olen%32) != 0 {d++}

-        var F=[UInt8](count:ECDH.EFS,repeatedValue:0)

-        var U=[UInt8](count:ECDH.EFS,repeatedValue:0)

-        var S=[UInt8](count:Salt.count+4,repeatedValue:0)

-

-        var K=[UInt8](count:d*ECDH.EFS,repeatedValue:0)

-

-        var opt=0;

-

-        for var i=1;i<=d;i++

-        {

-            for var j=0;j<Salt.count;j++ {S[j]=Salt[j]}

-            var N=ECDH.inttoBytes(i,4);

-            for var j=0;j<4;j++ {S[Salt.count+j]=N[j]}

-

-            ECDH.HMAC(S,Pass,&F);

-

-            for var j=0;j<EFS;j++ {U[j]=F[j]}

-            for var j=2;j<=rep;j++

-            {

-				ECDH.HMAC(U,Pass,&U);

-                for var k=0;k<ECDH.EFS;k++ {F[k]^=U[k]}

-            }

-            for var j=0;j<EFS;j++ {K[opt++]=F[j]}

-        }

-        var key=[UInt8](count:olen,repeatedValue:0)

-        for var i=0;i<olen;i++ {key[i]=K[i]}

-        return key;

-    }

-

-    /* Calculate HMAC of m using key k. HMAC is tag of length olen */

-    static public func HMAC(M:[UInt8],_ K:[UInt8],inout _ tag:[UInt8]) -> Int

-    {

-    /* Input is from an octet m        *

-    * olen is requested output length in bytes. k is the key  *

-    * The output is the calculated tag */

-        var K0=[UInt8](count:64,repeatedValue:0)

-        let olen=tag.count;

-

-        let b=K0.count;

-        if olen<4 || olen>HASH.len {return 0}

-

-        let H=HASH();

-

-        if (K.count > b)

-        {

-            H.process_array(K); var B=H.hash();

-            for var i=0;i<32;i++ {K0[i]=B[i]}

-        }

-        else

-        {

-            for var i=0;i<K.count;i++ {K0[i]=K[i]}

-        }

-        for var i=0;i<b;i++ {K0[i]^=0x36}

-        H.process_array(K0); H.process_array(M); var B=H.hash();

-

-        for var i=0;i<b;i++ {K0[i]^=0x6a}

-        H.process_array(K0); H.process_array(B); B=H.hash();

-

-        for var i=0;i<olen;i++ {tag[i]=B[i]}

-

-        return 1;

-    }

-    /* AES encryption/decryption. Encrypt byte array M using key K and returns ciphertext */

-    static public func AES_CBC_IV0_ENCRYPT(K:[UInt8],_ M:[UInt8]) -> [UInt8]

-    { /* AES CBC encryption, with Null IV and key K */

-    /* Input is from an octet string M, output is to an octet string C */

-    /* Input is padded as necessary to make up a full final block */

-        let a=AES();

-        var buff=[UInt8](count:16,repeatedValue:0)

-        let clen=16+(M.count/16)*16;

-

-        var C=[UInt8](count:clen,repeatedValue:0)

-

-        a.init_it(AES.CBC,K,nil)

-

-        var ipt=0; var opt=0;

-        var fin=false;

-        var i:Int=0

-        while true

-        {

-            for i=0;i<16;i++

-            {

-                if (ipt<M.count) {buff[i]=M[ipt++]}

-				else {fin=true; break;}

-            }

-            if fin {break}

-            a.encrypt(&buff);

-            for var i=0;i<16;i++

-                {C[opt++]=buff[i]}

-        }

-

-    /* last block, filled up to i-th index */

-

-        let padlen=16-i;

-        for var j=i;j<16;j++ {buff[j]=UInt8(padlen&0xff)}

-

-        a.encrypt(&buff);

-

-        for var i=0;i<16;i++

-            {C[opt++]=buff[i]}

-        a.end();

-        return C;

-    }

-

-    /* returns plaintext if all consistent, else returns null string */

-    static public func AES_CBC_IV0_DECRYPT(K:[UInt8],_ C:[UInt8]) -> [UInt8]

-    { /* padding is removed */

-        let a=AES();

-

-        var buff=[UInt8](count:16,repeatedValue:0)

-        var MM=[UInt8](count:C.count,repeatedValue:0)

-

-        var ipt=0; var opt=0;

-

-        a.init_it(AES.CBC,K,nil);

-

-        if C.count==0 {return [UInt8]()}

-        var ch=C[ipt++];

-

-        var fin=false;

-        var i:Int=0

-        while true

-        {

-            for i=0;i<16;i++

-            {

-				buff[i]=ch;

-				if ipt>=C.count {fin=true; break;}

-                else {ch=C[ipt++]}

-            }

-            a.decrypt(&buff);

-            if fin {break}

-            for var i=0;i<16;i++

-                {MM[opt++]=buff[i]}

-        }

-

-        a.end();

-        var bad=false;

-        let padlen:Int=Int(buff[15]);

-        if i != 15 || padlen<1 || padlen>16 {bad=true}

-        if padlen>=2 && padlen<=16

-        {

-            for var i=16-padlen;i<16;i++ {if buff[i] != buff[15] {bad=true}}

-        }

-        if !bad

-        {

-            for var i=0;i<16-padlen;i++

-                {MM[opt++]=buff[i]}

-        }

-

-        if bad {return [UInt8]()}

-

-        var M=[UInt8](count:opt,repeatedValue:0)

-        for var i=0;i<opt;i++ {M[i]=MM[i]}

-

-        return M;

-    }

-

-    /* Calculate a public/private EC GF(p) key pair W,S where W=S.G mod EC(p),

-    * where S is the secret key and W is the public key

-    * and G is fixed generator.

-    * If RNG is NULL then the private key is provided externally in S

-    * otherwise it is generated randomly internally */

-    static public func KEY_PAIR_GENERATE(RNG:RAND?,inout _ S:[UInt8],inout _ W:[UInt8]) -> Int

-    {

-        let res=0;

-        var T=[UInt8](count:ECDH.EFS,repeatedValue:0)

-        let gx=BIG(ROM.CURVE_Gx);

-        var s:BIG

-        var G:ECP

-        if ROM.CURVETYPE != ROM.MONTGOMERY

-        {

-            let gy=BIG(ROM.CURVE_Gy)

-            G=ECP(gx,gy)

-        }

-        else

-            {G=ECP(gx)}

-

-        let r=BIG(ROM.CURVE_Order);

-

-        if (RNG==nil)

-        {

-            s=BIG.fromBytes(S);

-        }

-        else

-        {

-            s=BIG.randomnum(r,RNG!)

-

-            s.toBytes(&T)

-            for var i=0;i<EGS;i++ {S[i]=T[i]}

-        }

-

-        let WP=G.mul(s)

-        WP.toBytes(&W)

-

-        return res;

-    }

-

-    /* validate public key. Set full=true for fuller check */

-    static public func PUBLIC_KEY_VALIDATE(full:Bool,_ W:[UInt8]) -> Int

-    {

-        var WP=ECP.fromBytes(W);

-        var res=0;

-

-        let r=BIG(ROM.CURVE_Order)

-

-        if WP.is_infinity() {res=INVALID_PUBLIC_KEY}

-

-        if res==0 && full

-        {

-            WP=WP.mul(r)

-            if !WP.is_infinity() {res=INVALID_PUBLIC_KEY}

-        }

-        return res;

-    }

-    /* IEEE-1363 Diffie-Hellman online calculation Z=S.WD */

-    static public func ECPSVDP_DH(S:[UInt8],_ WD:[UInt8],inout _ Z:[UInt8]) -> Int

-    {

-        var res=0

-        var T=[UInt8](count:ECDH.EFS,repeatedValue:0)

-

-        let s=BIG.fromBytes(S)

-

-        var W=ECP.fromBytes(WD)

-        if W.is_infinity() {res=ECDH.ERROR}

-

-        if (res==0)

-        {

-            let r=BIG(ROM.CURVE_Order)

-            s.mod(r)

-

-            W=W.mul(s);

-            if W.is_infinity() {res=ERROR}

-            else

-            {

-				W.getX().toBytes(&T);

-                for var i=0;i<ECDH.EFS;i++ {Z[i]=T[i]}

-            }

-        }

-        return res;

-    }

-    /* IEEE ECDSA Signature, C and D are signature on F using private key S */

-    static public func ECPSP_DSA(RNG:RAND,_ S:[UInt8],_ F:[UInt8],inout _ C:[UInt8],inout _ D:[UInt8]) -> Int

-    {

-        var T=[UInt8](count:ECDH.EFS,repeatedValue:0)

-        let H=HASH()

-        H.process_array(F)

-        let B=H.hash()

-

-        let gx=BIG(ROM.CURVE_Gx)

-        let gy=BIG(ROM.CURVE_Gy)

-

-        let G=ECP(gx,gy)

-        let r=BIG(ROM.CURVE_Order)

-

-        let s=BIG.fromBytes(S)

-        let f=BIG.fromBytes(B)

-

-        let c=BIG(0)

-        let d=BIG(0)

-        var V=ECP()

-

-        repeat {

-            let u=BIG.randomnum(r,RNG);

-

-            V.copy(G)

-            V=V.mul(u)

-            let vx=V.getX()

-            c.copy(vx)

-            c.mod(r)

-            if c.iszilch() {continue}

-            u.invmodp(r)

-            d.copy(BIG.modmul(s,c,r))

-            d.add(f)

-            d.copy(BIG.modmul(u,d,r))

-        } while d.iszilch()

-

-        c.toBytes(&T)

-        for var i=0;i<ECDH.EFS;i++ {C[i]=T[i]}

-        d.toBytes(&T)

-        for var i=0;i<ECDH.EFS;i++ {D[i]=T[i]}

-        return 0;

-    }

-

-    /* IEEE1363 ECDSA Signature Verification. Signature C and D on F is verified using public key W */

-    static public func ECPVP_DSA(W:[UInt8],_ F:[UInt8],_ C:[UInt8],_ D:[UInt8]) -> Int

-    {

-        var res=0

-

-        let H=HASH()

-        H.process_array(F)

-        let B=H.hash()

-

-        let gx=BIG(ROM.CURVE_Gx)

-        let gy=BIG(ROM.CURVE_Gy)

-

-        let G=ECP(gx,gy)

-        let r=BIG(ROM.CURVE_Order)

-

-        let c=BIG.fromBytes(C)

-        var d=BIG.fromBytes(D)

-        let f=BIG.fromBytes(B)

-

-        if c.iszilch() || BIG.comp(c,r)>=0 || d.iszilch() || BIG.comp(d,r)>=0

-            {res=ECDH.INVALID}

-

-        if res==0

-        {

-            d.invmodp(r);

-            f.copy(BIG.modmul(f,d,r))

-            let h2=BIG.modmul(c,d,r)

-

-            let WP=ECP.fromBytes(W)

-            if WP.is_infinity() {res=ECDH.ERROR}

-            else

-            {

-				var P=ECP();

-				P.copy(WP);

-				P=P.mul2(h2,G,f);

-                if P.is_infinity() {res=INVALID}

-				else

-				{

-                    d=P.getX();

-                    d.mod(r);

-                    if (BIG.comp(d,c) != 0) {res=ECDH.INVALID}

-				}

-            }

-        }

-

-        return res;

-    }

-

-    /* IEEE1363 ECIES encryption. Encryption of plaintext M uses public key W and produces ciphertext V,C,T */

-    static public func ECIES_ENCRYPT(P1:[UInt8],_ P2:[UInt8],_ RNG:RAND,_ W:[UInt8],_ M:[UInt8],inout _ V:[UInt8],inout _ T:[UInt8]) -> [UInt8]

-    {

-        var Z=[UInt8](count:ECDH.EFS,repeatedValue:0)

-        var VZ=[UInt8](count:3*ECDH.EFS+1,repeatedValue:0)

-        var K1=[UInt8](count:ECDH.EAS,repeatedValue:0)

-        var K2=[UInt8](count:ECDH.EAS,repeatedValue:0)

-        var U=[UInt8](count:ECDH.EGS,repeatedValue:0)

-

-        if ECDH.KEY_PAIR_GENERATE(RNG,&U,&V) != 0 {return [UInt8]()}

-        if ECDH.ECPSVDP_DH(U,W,&Z) != 0 {return [UInt8]()}

-

-        for var i=0;i<2*ECDH.EFS+1;i++ {VZ[i]=V[i]}

-        for var i=0;i<ECDH.EFS;i++ {VZ[2*ECDH.EFS+1+i]=Z[i]}

-

-

-        var K=KDF2(VZ,P1,ECDH.EFS)

-

-        for var i=0;i<ECDH.EAS;i++ {K1[i]=K[i]; K2[i]=K[EAS+i];}

-

-        var C=AES_CBC_IV0_ENCRYPT(K1,M)

-

-        var L2=inttoBytes(P2.count,8)

-

-        var AC=[UInt8](count:C.count+P2.count+8,repeatedValue:0)

-

-        for var i=0;i<C.count;i++ {AC[i]=C[i]}

-        for var i=0;i<P2.count;i++ {AC[C.count+i]=P2[i]}

-        for var i=0;i<8;i++ {AC[C.count+P2.count+i]=L2[i]}

-

-        ECDH.HMAC(AC,K2,&T)

-

-        return C

-    }

-

-    /* IEEE1363 ECIES decryption. Decryption of ciphertext V,C,T using private key U outputs plaintext M */

-    static public func ECIES_DECRYPT(P1:[UInt8],_ P2:[UInt8],_ V:[UInt8],_ C:[UInt8],_ T:[UInt8],_ U:[UInt8]) -> [UInt8]

-    {

-        var Z=[UInt8](count:ECDH.EFS,repeatedValue:0)

-        var VZ=[UInt8](count:3*ECDH.EFS+1,repeatedValue:0)

-        var K1=[UInt8](count:ECDH.EAS,repeatedValue:0)

-        var K2=[UInt8](count:ECDH.EAS,repeatedValue:0)

-

-        var TAG=[UInt8](count:T.count,repeatedValue:0)

-

-        if ECPSVDP_DH(U,V,&Z) != 0 {return [UInt8]()}

-

-        for var i=0;i<2*ECDH.EFS+1;i++ {VZ[i]=V[i]}

-        for var i=0;i<ECDH.EFS;i++ {VZ[2*EFS+1+i]=Z[i]}

-

-        var K=KDF2(VZ,P1,ECDH.EFS)

-

-        for var i=0;i<ECDH.EAS;i++ {K1[i]=K[i]; K2[i]=K[ECDH.EAS+i]}

-

-        let M=ECDH.AES_CBC_IV0_DECRYPT(K1,C)

-

-        if M.count==0 {return M}

-

-        var L2=inttoBytes(P2.count,8)

-

-        var AC=[UInt8](count:C.count+P2.count+8,repeatedValue:0)

-

-        for var i=0;i<C.count;i++ {AC[i]=C[i]}

-        for var i=0;i<P2.count;i++ {AC[C.count+i]=P2[i]}

-        for var i=0;i<8;i++ {AC[C.count+P2.count+i]=L2[i]}

-

-        ECDH.HMAC(AC,K2,&TAG)

-

-        var same=true

-        for var i=0;i<T.count;i++

-        {

-            if T[i] != TAG[i] {same=false}

-        }

-        if !same {return [UInt8]()}

-

-        return M;

-

-    }

-

-    static public func printBinary(array: [UInt8])

-    {

-        for var i=0;i<array.count;i++

-        {

-            let h=String(array[i],radix:16);

-            print("\(h)", terminator: "")

-        }

-        print("");

-    }

-

-}

diff --git a/swift/ecp.swift b/swift/ecp.swift
deleted file mode 100644
index f7d84f5..0000000
--- a/swift/ecp.swift
+++ /dev/null
@@ -1,923 +0,0 @@
-/*

-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.

-*/

-//

-//  ecp.swift

-//  

-//

-//  Created by Michael Scott on 30/06/2015.

-//  Copyright (c) 2015 Michael Scott. All rights reserved.

-//

-

-final class ECP {

-    private var x:FP

-    private var y:FP

-    private var z:FP

-    private var INF:Bool

-

-   /* Constructor - set to O */

-    init()

-    {

-        x=FP(0)

-        y=FP(0)

-        z=FP(1)

-        INF=true

-    }

-

-    /* test for O point-at-infinity */

-    func is_infinity() -> Bool

-    {

-        if (ROM.CURVETYPE==ROM.EDWARDS)

-        {

-            x.reduce(); y.reduce(); z.reduce()

-            return x.iszilch() && y.equals(z)

-        }

-        else {return INF}

-    }

-

-    /* Conditional swap of P and Q dependant on d */

-    private func cswap(Q: ECP,_ d:Int32)

-    {

-        x.cswap(Q.x,d);

-        if ROM.CURVETYPE != ROM.MONTGOMERY {y.cswap(Q.y,d)}

-        z.cswap(Q.z,d);

-        if (ROM.CURVETYPE != ROM.EDWARDS)

-        {

-            var bd:Bool

-            if d==0 {bd=false}

-            else {bd=true}

-            bd=bd && (INF != Q.INF)

-            INF = (INF != bd)

-            Q.INF = (Q.INF != bd)

-        }

-    }

-

-    /* Conditional move of Q to P dependant on d */

-    private func cmove(Q: ECP,_ d:Int32)

-    {

-        x.cmove(Q.x,d);

-        if ROM.CURVETYPE != ROM.MONTGOMERY {y.cmove(Q.y,d)}

-        z.cmove(Q.z,d);

-        if (ROM.CURVETYPE != ROM.EDWARDS)

-        {

-            var bd:Bool

-            if d==0 {bd=false}

-            else {bd=true}

-            INF != (INF != Q.INF) && bd;

-        }

-    }

-

-    /* return 1 if b==c, no branching */

-    private static func teq(b: Int32,_ c:Int32) -> Int32

-    {

-        var x=b^c

-        x-=1  // if x=0, x now -1

-        return ((x>>31)&1)

-    }

-

-    /* self=P */

-    func copy(P: ECP)

-    {

-        x.copy(P.x)

-        if ROM.CURVETYPE != ROM.MONTGOMERY {y.copy(P.y)}

-        z.copy(P.z)

-        INF=P.INF

-    }

-    /* self=-self */

-    func neg() {

-        if is_infinity() {return}

-        if (ROM.CURVETYPE==ROM.WEIERSTRASS)

-        {

-            y.neg(); y.norm();

-        }

-        if (ROM.CURVETYPE==ROM.EDWARDS)

-        {

-            x.neg(); x.norm();

-        }

-        return;

-    }

-

-    /* Constant time select from pre-computed table */

-    private func select(W:[ECP],_ b:Int32)

-    {

-        let MP=ECP()

-        let m=b>>31

-        var babs=(b^m)-m

-

-        babs=(babs-1)/2

-

-        cmove(W[0],ECP.teq(babs,0)); // conditional move

-        cmove(W[1],ECP.teq(babs,1))

-        cmove(W[2],ECP.teq(babs,2))

-        cmove(W[3],ECP.teq(babs,3))

-        cmove(W[4],ECP.teq(babs,4))

-        cmove(W[5],ECP.teq(babs,5))

-        cmove(W[6],ECP.teq(babs,6))

-        cmove(W[7],ECP.teq(babs,7))

-

-        MP.copy(self)

-        MP.neg()

-        cmove(MP,(m&1))

-    }

-

-    /* Test P == Q */

-    func equals(Q: ECP) -> Bool

-    {

-        if (is_infinity() && Q.is_infinity()) {return true}

-        if (is_infinity() || Q.is_infinity()) {return false}

-        if (ROM.CURVETYPE==ROM.WEIERSTRASS)

-        {

-            let zs2=FP(z); zs2.sqr()

-            let zo2=FP(Q.z); zo2.sqr()

-            let zs3=FP(zs2); zs3.mul(z)

-            let zo3=FP(zo2); zo3.mul(Q.z)

-            zs2.mul(Q.x)

-            zo2.mul(x)

-            if !zs2.equals(zo2) {return false}

-            zs3.mul(Q.y)

-            zo3.mul(y)

-            if !zs3.equals(zo3) {return false}

-        }

-        else

-        {

-            let a=FP(0)

-            let b=FP(0)

-            a.copy(x); a.mul(Q.z); a.reduce()

-            b.copy(Q.x); b.mul(z); b.reduce()

-            if !a.equals(b) {return false}

-            if ROM.CURVETYPE==ROM.EDWARDS

-            {

-				a.copy(y); a.mul(Q.z); a.reduce()

-				b.copy(Q.y); b.mul(z); b.reduce()

-				if !a.equals(b) {return false}

-            }

-        }

-        return true

-    }

-

-/* set self=O */

-    func inf()

-    {

-        INF=true;

-        x.zero()

-        y.one()

-        z.one()

-    }

-

-    /* Calculate RHS of curve equation */

-    static func RHS(x: FP) -> FP

-    {

-        x.norm();

-        let r=FP(x);

-        r.sqr();

-

-        if ROM.CURVETYPE==ROM.WEIERSTRASS

-        { // x^3+Ax+B

-            let b=FP(BIG(ROM.CURVE_B))

-            r.mul(x)

-            if (ROM.CURVE_A == -3)

-            {

-				let cx=FP(x)

-				cx.imul(3)

-				cx.neg(); cx.norm()

-				r.add(cx)

-            }

-            r.add(b);

-        }

-        if (ROM.CURVETYPE==ROM.EDWARDS)

-        { // (Ax^2-1)/(Bx^2-1)

-            let b=FP(BIG(ROM.CURVE_B))

-

-            let one=FP(1);

-            b.mul(r);

-            b.sub(one);

-            if ROM.CURVE_A == -1 {r.neg()}

-            r.sub(one)

-            b.inverse()

-            r.mul(b);

-        }

-        if ROM.CURVETYPE==ROM.MONTGOMERY

-        { // x^3+Ax^2+x

-            let x3=FP(0)

-            x3.copy(r);

-            x3.mul(x);

-            r.imul(ROM.CURVE_A);

-            r.add(x3);

-            r.add(x);

-        }

-        r.reduce();

-        return r;

-    }

-

-    /* set (x,y) from two BIGs */

-    init(_ ix: BIG,_ iy: BIG)

-    {

-        x=FP(ix)

-        y=FP(iy)

-        z=FP(1)

-        INF=true

-        let rhs=ECP.RHS(x);

-

-        if ROM.CURVETYPE==ROM.MONTGOMERY

-        {

-            if rhs.jacobi()==1 {INF=false}

-            else {inf()}

-        }

-        else

-        {

-            let y2=FP(y)

-            y2.sqr()

-            if y2.equals(rhs) {INF=false}

-            else {inf()}

-        }

-    }

-

-    /* set (x,y) from BIG and a bit */

-    init(_ ix: BIG,_ s:Int32)

-    {

-        x=FP(ix)

-        let rhs=ECP.RHS(x)

-        y=FP(0)

-        z=FP(1)

-        INF=true

-        if rhs.jacobi()==1

-        {

-            let ny=rhs.sqrt()

-            if (ny.redc().parity() != s) {ny.neg()}

-            y.copy(ny)

-            INF=false;

-        }

-        else {inf()}

-    }

-

-    /* set from x - calculate y from curve equation */

-    init(_ ix:BIG)

-    {

-        x=FP(ix)

-        let rhs=ECP.RHS(x)

-        y=FP(0)

-        z=FP(1)

-        if rhs.jacobi()==1

-        {

-            if ROM.CURVETYPE != ROM.MONTGOMERY {y.copy(rhs.sqrt())}

-            INF=false;

-        }

-        else {INF=true}

-    }

-

-    /* set to affine - from (x,y,z) to (x,y) */

-    func affine()

-    {

-        if is_infinity() {return}

-        let one=FP(1)

-        if (z.equals(one)) {return}

-        z.inverse()

-        if ROM.CURVETYPE==ROM.WEIERSTRASS

-        {

-            let z2=FP(z)

-            z2.sqr()

-            x.mul(z2); x.reduce()

-            y.mul(z2)

-            y.mul(z);  y.reduce()

-        }

-        if ROM.CURVETYPE==ROM.EDWARDS

-        {

-            x.mul(z); x.reduce()

-            y.mul(z); y.reduce()

-        }

-        if ROM.CURVETYPE==ROM.MONTGOMERY

-        {

-            x.mul(z); x.reduce()

-

-        }

-        z.copy(one)

-    }

-    /* extract x as a BIG */

-    func getX() -> BIG

-    {

-        affine()

-        return x.redc()

-    }

-    /* extract y as a BIG */

-    func getY() -> BIG

-    {

-        affine();

-        return y.redc();

-    }

-

-    /* get sign of Y */

-    func getS() -> Int32

-    {

-        affine()

-        let y=getY()

-        return y.parity()

-    }

-    /* extract x as an FP */

-    func getx() -> FP

-    {

-        return x;

-    }

-    /* extract y as an FP */

-    func gety() -> FP

-    {

-        return y;

-    }

-    /* extract z as an FP */

-    func getz() -> FP

-    {

-        return z;

-    }

-    /* convert to byte array */

-    func toBytes(inout b:[UInt8])

-    {

-        let RM=Int(ROM.MODBYTES)

-        var t=[UInt8](count:RM,repeatedValue:0)

-        if ROM.CURVETYPE != ROM.MONTGOMERY {b[0]=0x04}

-        else {b[0]=0x02}

-

-        affine()

-        x.redc().toBytes(&t)

-        for var i=0;i<RM;i++ {b[i+1]=t[i]}

-        if ROM.CURVETYPE != ROM.MONTGOMERY

-        {

-            y.redc().toBytes(&t);

-            for var i=0;i<RM;i++ {b[i+RM+1]=t[i]}

-        }

-    }

-    /* convert from byte array to point */

-    static func fromBytes(b: [UInt8]) -> ECP

-    {

-        let RM=Int(ROM.MODBYTES)

-        var t=[UInt8](count:RM,repeatedValue:0)

-        let p=BIG(ROM.Modulus);

-

-        for var i=0;i<RM;i++ {t[i]=b[i+1]}

-        let px=BIG.fromBytes(t)

-        if BIG.comp(px,p)>=0 {return ECP()}

-

-        if (b[0]==0x04)

-        {

-            for var i=0;i<RM;i++ {t[i]=b[i+RM+1]}

-            let py=BIG.fromBytes(t)

-            if BIG.comp(py,p)>=0 {return ECP()}

-            return ECP(px,py)

-        }

-        else {return ECP(px)}

-    }

-    /* convert to hex string */

-    func toString() -> String

-    {

-        if is_infinity() {return "infinity"}

-        affine();

-        if ROM.CURVETYPE==ROM.MONTGOMERY {return "("+x.redc().toString()+")"}

-        else {return "("+x.redc().toString()+","+y.redc().toString()+")"}

-    }

-

-    /* self*=2 */

-    func dbl()

-    {

-        if (ROM.CURVETYPE==ROM.WEIERSTRASS)

-        {

-            if INF {return}

-            if y.iszilch()

-            {

-				inf()

-				return

-            }

-

-            let w1=FP(x)

-            let w6=FP(z)

-            let w2=FP(0)

-            let w3=FP(x)

-            let w8=FP(x)

-

-            if (ROM.CURVE_A == -3)

-            {

-				w6.sqr()

-				w1.copy(w6)

-				w1.neg()

-				w3.add(w1)

-				w8.add(w6)

-				w3.mul(w8)

-				w8.copy(w3)

-				w8.imul(3)

-            }

-            else

-            {

-				w1.sqr()

-				w8.copy(w1)

-				w8.imul(3)

-            }

-

-            w2.copy(y); w2.sqr()

-            w3.copy(x); w3.mul(w2)

-            w3.imul(4)

-            w1.copy(w3); w1.neg()

-            w1.norm()

-

-            x.copy(w8); x.sqr()

-            x.add(w1)

-            x.add(w1)

-            x.norm()

-

-            z.mul(y)

-            z.add(z)

-

-            w2.add(w2)

-            w2.sqr()

-            w2.add(w2)

-            w3.sub(x)

-            y.copy(w8); y.mul(w3)

-            //w2.norm();

-            y.sub(w2)

-            y.norm()

-            z.norm()

-        }

-        if ROM.CURVETYPE==ROM.EDWARDS

-        {

-            let C=FP(x)

-            let D=FP(y)

-            let H=FP(z)

-            let J=FP(0)

-

-            x.mul(y); x.add(x)

-            C.sqr()

-            D.sqr()

-            if ROM.CURVE_A == -1 {C.neg()}

-            y.copy(C); y.add(D)

-            y.norm()

-            H.sqr(); H.add(H)

-            z.copy(y)

-            J.copy(y); J.sub(H)

-            x.mul(J)

-            C.sub(D)

-            y.mul(C)

-            z.mul(J)

-

-            x.norm();

-            y.norm();

-            z.norm();

-        }

-        if ROM.CURVETYPE==ROM.MONTGOMERY

-        {

-            let A=FP(x)

-            let B=FP(x);

-            let AA=FP(0);

-            let BB=FP(0);

-            let C=FP(0);

-

-            if INF {return}

-

-            A.add(z)

-            AA.copy(A); AA.sqr()

-            B.sub(z)

-            BB.copy(B); BB.sqr()

-            C.copy(AA); C.sub(BB)

-    //C.norm();

-

-            x.copy(AA); x.mul(BB)

-

-            A.copy(C); A.imul((ROM.CURVE_A+2)/4)

-

-            BB.add(A)

-            z.copy(BB); z.mul(C)

-            x.norm()

-            z.norm()

-        }

-        return

-    }

-

-    /* self+=Q */

-    func add(Q:ECP)

-    {

-        if ROM.CURVETYPE==ROM.WEIERSTRASS

-        {

-            if (INF)

-            {

-				copy(Q)

-				return

-            }

-            if Q.INF {return}

-

-            var aff=false;

-

-            let one=FP(1);

-            if Q.z.equals(one) {aff=true}

-

-            var A:FP

-            var C:FP

-            let B=FP(z)

-            let D=FP(z)

-            if (!aff)

-            {

-				A=FP(Q.z)

-				C=FP(Q.z)

-

-				A.sqr(); B.sqr()

-				C.mul(A); D.mul(B)

-

-				A.mul(x)

-				C.mul(y)

-            }

-            else

-            {

-				A=FP(x)

-				C=FP(y)

-

-				B.sqr()

-				D.mul(B)

-            }

-

-            B.mul(Q.x); B.sub(A)

-            D.mul(Q.y); D.sub(C)

-

-            if B.iszilch()

-            {

-				if (D.iszilch())

-				{

-                    dbl()

-                    return

-				}

-				else

-				{

-                    INF=true

-                    return

-				}

-            }

-

-            if !aff {z.mul(Q.z)}

-            z.mul(B);

-

-            let e=FP(B); e.sqr()

-            B.mul(e)

-            A.mul(e)

-

-            e.copy(A)

-            e.add(A); e.add(B)

-            x.copy(D); x.sqr(); x.sub(e)

-

-            A.sub(x)

-            y.copy(A); y.mul(D)

-            C.mul(B); y.sub(C)

-

-            x.norm()

-            y.norm()

-            z.norm()

-        }

-        if ROM.CURVETYPE==ROM.EDWARDS

-        {

-            let b=FP(BIG(ROM.CURVE_B))

-            let A=FP(z)

-            let B=FP(0)

-            let C=FP(x)

-            let D=FP(y)

-            let E=FP(0)

-            let F=FP(0)

-            let G=FP(0)

-

-            A.mul(Q.z)

-            B.copy(A); B.sqr()

-            C.mul(Q.x)

-            D.mul(Q.y)

-

-            E.copy(C); E.mul(D); E.mul(b)

-            F.copy(B); F.sub(E)

-            G.copy(B); G.add(E)

-            C.add(D)

-

-            if ROM.CURVE_A==1

-            {

-				E.copy(D); D.sub(C)

-            }

-

-            B.copy(x); B.add(y)

-            D.copy(Q.x); D.add(Q.y)

-            B.mul(D)

-            B.sub(C)

-            B.mul(F)

-            x.copy(A); x.mul(B)

-

-            if ROM.CURVE_A==1

-            {

-				C.copy(E); C.mul(G)

-            }

-            if ROM.CURVE_A == -1

-            {

-				C.mul(G)

-            }

-            y.copy(A); y.mul(C)

-            z.copy(F); z.mul(G)

-            x.norm(); y.norm(); z.norm()

-        }

-        return;

-    }

-

-    /* Differential Add for Montgomery curves. self+=Q where W is self-Q and is affine. */

-    func dadd(Q:ECP,_ W:ECP)

-    {

-        let A=FP(x)

-        let B=FP(x)

-        let C=FP(Q.x)

-        let D=FP(Q.x)

-        let DA=FP(0)

-        let CB=FP(0)

-

-        A.add(z)

-        B.sub(z)

-

-        C.add(Q.z)

-        D.sub(Q.z)

-

-        DA.copy(D); DA.mul(A)

-        CB.copy(C); CB.mul(B)

-

-        A.copy(DA); A.add(CB); A.sqr()

-        B.copy(DA); B.sub(CB); B.sqr()

-

-        x.copy(A)

-        z.copy(W.x); z.mul(B)

-

-        if z.iszilch() {inf()}

-        else {INF=false}

-

-        x.norm()

-    }

-    /* this-=Q */

-    func sub(Q:ECP)

-    {

-        Q.neg()

-        add(Q)

-        Q.neg()

-    }

-    static func multiaffine(m: Int,_ P:[ECP])

-    {

-        let t1=FP(0)

-        let t2=FP(0)

-

-        var work=[FP]()

-

-        for var i=0;i<m;i++

-            {work.append(FP(0))}

-

-        work[0].one()

-        work[1].copy(P[0].z)

-

-        for var i=2;i<m;i++

-        {

-            work[i].copy(work[i-1])

-            work[i].mul(P[i-1].z)

-        }

-

-        t1.copy(work[m-1]);

-        t1.mul(P[m-1].z);

-        t1.inverse();

-        t2.copy(P[m-1].z);

-        work[m-1].mul(t1);

-

-        for var i=m-2;;i--

-        {

-            if i==0

-            {

-				work[0].copy(t1)

-				work[0].mul(t2)

-				break

-            }

-            work[i].mul(t2);

-            work[i].mul(t1);

-            t2.mul(P[i].z);

-        }

-    /* now work[] contains inverses of all Z coordinates */

-

-        for var i=0;i<m;i++

-        {

-            P[i].z.one();

-            t1.copy(work[i]);

-            t1.sqr();

-            P[i].x.mul(t1);

-            t1.mul(work[i]);

-            P[i].y.mul(t1);

-        }

-    }

-    /* constant time multiply by small integer of length bts - use ladder */

-    func pinmul(e:Int32,_ bts:Int32) -> ECP

-    {

-        if ROM.CURVETYPE==ROM.MONTGOMERY

-            {return self.mul(BIG(e))}

-        else

-        {

-            let P=ECP()

-            let R0=ECP()

-            let R1=ECP(); R1.copy(self)

-

-            for var i=bts-1;i>=0;i--

-            {

-				let b=(e>>i)&1;

-				P.copy(R1);

-				P.add(R0);

-				R0.cswap(R1,b);

-				R1.copy(P);

-				R0.dbl();

-				R0.cswap(R1,b);

-            }

-            P.copy(R0);

-            P.affine();

-            return P;

-        }

-    }

-

-    /* return e.self */

-

-    func mul(e:BIG) -> ECP

-    {

-        if (e.iszilch() || is_infinity()) {return ECP()}

-

-        let P=ECP()

-        if ROM.CURVETYPE==ROM.MONTGOMERY

-        {

-            /* use Ladder */

-            let D=ECP()

-            let R0=ECP(); R0.copy(self)

-            let R1=ECP(); R1.copy(self)

-            R1.dbl();

-            D.copy(self); D.affine();

-            let nb=e.nbits();

-

-            for var i=nb-2;i>=0;i--

-            {

-				let b=e.bit(i)

-                //print("\(b)")

-				P.copy(R1)

-				P.dadd(R0,D)

-				R0.cswap(R1,b)

-				R1.copy(P)

-				R0.dbl()

-				R0.cswap(R1,b)

-            }

-            P.copy(R0)

-        }

-        else

-        {

-    // fixed size windows

-            let mt=BIG()

-            let t=BIG()

-            let Q=ECP()

-            let C=ECP()

-            var W=[ECP]()

-            let n=1+(ROM.NLEN*Int(ROM.BASEBITS)+3)/4

-            var w=[Int8](count:n,repeatedValue:0)

-

-            affine();

-

-    // precompute table

-            Q.copy(self)

-            Q.dbl()

-            W.append(ECP())

-

-            W[0].copy(self)

-

-            for var i=1;i<8;i++

-            {

-                W.append(ECP())

-				W[i].copy(W[i-1])

-				W[i].add(Q)

-            }

-

-    // convert the table to affine

-            if ROM.CURVETYPE==ROM.WEIERSTRASS

-                {ECP.multiaffine(8,W)}

-

-    // make exponent odd - add 2P if even, P if odd

-            t.copy(e);

-            let s=t.parity();

-            t.inc(1); t.norm(); let ns=t.parity();

-            mt.copy(t); mt.inc(1); mt.norm();

-            t.cmove(mt,s);

-            Q.cmove(self,ns);

-            C.copy(Q);

-

-            let nb=1+(t.nbits()+3)/4;

-

-    // convert exponent to signed 4-bit window

-            for var i=0;i<nb;i++

-            {

-				w[i]=Int8(t.lastbits(5)-16);

-				t.dec(Int32(w[i])); t.norm();

-				t.fshr(4);

-            }

-            w[nb]=Int8(t.lastbits(5))

-

-            P.copy(W[Int((w[nb])-1)/2]);

-            for var i=nb-1;i>=0;i--

-            {

-				Q.select(W,Int32(w[i]));

-				P.dbl();

-				P.dbl();

-				P.dbl();

-				P.dbl();

-				P.add(Q);

-            }

-            P.sub(C); /* apply correction */

-        }

-        P.affine();

-        return P;

-    }

-

-    /* Return e.this+f.Q */

-

-    func mul2(e:BIG,_ Q:ECP,_ f:BIG) -> ECP

-    {

-        let te=BIG()

-        let tf=BIG()

-        let mt=BIG()

-        let S=ECP()

-        let T=ECP()

-        let C=ECP()

-        var W=[ECP]()

-        let n=1+(ROM.NLEN*Int(ROM.BASEBITS)+1)/2

-        var w=[Int8](count:n,repeatedValue:0);

-

-        affine();

-        Q.affine();

-

-        te.copy(e);

-        tf.copy(f);

-

-    // precompute table

-        for var i=0;i<8;i++ {W.append(ECP())}

-        W[1].copy(self); W[1].sub(Q)

-        W[2].copy(self); W[2].add(Q)

-        S.copy(Q); S.dbl();

-        W[0].copy(W[1]); W[0].sub(S)

-        W[3].copy(W[2]); W[3].add(S)

-        T.copy(self); T.dbl()

-        W[5].copy(W[1]); W[5].add(T)

-        W[6].copy(W[2]); W[6].add(T)

-        W[4].copy(W[5]); W[4].sub(S)

-        W[7].copy(W[6]); W[7].add(S)

-

-    // convert the table to affine

-        if ROM.CURVETYPE==ROM.WEIERSTRASS

-            {ECP.multiaffine(8,W)}

-

-    // if multiplier is odd, add 2, else add 1 to multiplier, and add 2P or P to correction

-

-        var s=te.parity()

-        te.inc(1); te.norm(); var ns=te.parity(); mt.copy(te); mt.inc(1); mt.norm()

-        te.cmove(mt,s)

-        T.cmove(self,ns)

-        C.copy(T)

-

-        s=tf.parity()

-        tf.inc(1); tf.norm(); ns=tf.parity(); mt.copy(tf); mt.inc(1); mt.norm()

-        tf.cmove(mt,s)

-        S.cmove(Q,ns)

-        C.add(S)

-

-        mt.copy(te); mt.add(tf); mt.norm()

-        let nb=1+(mt.nbits()+1)/2

-

-    // convert exponent to signed 2-bit window

-        for var i=0;i<nb;i++

-        {

-            let a=(te.lastbits(3)-4);

-            te.dec(a); te.norm();

-            te.fshr(2);

-            let b=(tf.lastbits(3)-4);

-            tf.dec(b); tf.norm();

-            tf.fshr(2);

-            w[i]=Int8(4*a+b);

-        }

-        w[nb]=Int8(4*te.lastbits(3)+tf.lastbits(3));

-        S.copy(W[(w[nb]-1)/2]);

-

-        for var i=nb-1;i>=0;i--

-        {

-            T.select(W,Int32(w[i]));

-            S.dbl();

-            S.dbl();

-            S.add(T);

-        }

-        S.sub(C); /* apply correction */

-        S.affine();

-        return S;

-    }

-

-

-

-

-}

diff --git a/swift/ecp2.swift b/swift/ecp2.swift
deleted file mode 100644
index 058ff5f..0000000
--- a/swift/ecp2.swift
+++ /dev/null
@@ -1,614 +0,0 @@
-/*

-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.

-*/

-//

-//  ecp2.swift

-//  

-//

-//  Created by Michael Scott on 07/07/2015.

-//  Copyright (c) 2015 Michael Scott. All rights reserved.

-//

-

-/* CLINT Weierstrass elliptic curve functions over FP2 */

-

-final class ECP2 {

-    private var x:FP2

-    private var y:FP2

-    private var z:FP2

-    private var INF:Bool

-

-    /* Constructor - set self=O */

-    init()

-    {

-        INF=true

-        x=FP2(0)

-        y=FP2(1)

-        z=FP2(1)

-    }

-    /* Test self=O? */

-    func is_infinity() -> Bool

-    {

-        return INF

-    }

-    /* copy self=P */

-    func copy(P:ECP2)

-    {

-        x.copy(P.x)

-        y.copy(P.y)

-        z.copy(P.z)

-        INF=P.INF

-    }

-    /* set self=O */

-    func inf() {

-        INF=true

-        x.zero()

-        y.zero()

-        z.zero()

-    }

-    /* Conditional move of Q to P dependant on d */

-    func cmove(Q:ECP2,_ d:Int32)

-    {

-        x.cmove(Q.x,d);

-        y.cmove(Q.y,d);

-        z.cmove(Q.z,d);

-

-        var bd:Bool

-        if d==0 {bd=false}

-        else {bd=true}

-        INF = (INF != ((INF != Q.INF) && bd))

-    }

-

-    /* return 1 if b==c, no branching */

-    private static func teq(b:Int32,_ c:Int32) -> Int32

-    {

-        var x=b^c

-        x-=1  // if x=0, x now -1

-        return ((x>>31)&1)

-    }

-    /* Constant time select from pre-computed table */

-    func select(W:[ECP2],_ b:Int32)

-    {

-        let MP=ECP2()

-        let m=b>>31

-        var babs=(b^m)-m

-

-        babs=(babs-1)/2

-

-        cmove(W[0],ECP2.teq(babs,0)) // conditional move

-        cmove(W[1],ECP2.teq(babs,1))

-        cmove(W[2],ECP2.teq(babs,2))

-        cmove(W[3],ECP2.teq(babs,3))

-        cmove(W[4],ECP2.teq(babs,4))

-        cmove(W[5],ECP2.teq(babs,5))

-        cmove(W[6],ECP2.teq(babs,6))

-        cmove(W[7],ECP2.teq(babs,7))

-

-        MP.copy(self)

-        MP.neg()

-        cmove(MP,(m&1))

-    }

-

-    /* Test if P == Q */

-    func equals(Q:ECP2) -> Bool

-    {

-        if is_infinity() && Q.is_infinity() {return true}

-        if is_infinity() || Q.is_infinity() {return false}

-

-        let zs2=FP2(z); zs2.sqr()

-        let zo2=FP2(Q.z); zo2.sqr()

-        let zs3=FP2(zs2); zs3.mul(z)

-        let zo3=FP2(zo2); zo3.mul(Q.z)

-        zs2.mul(Q.x)

-        zo2.mul(x)

-        if !zs2.equals(zo2) {return false}

-        zs3.mul(Q.y)

-        zo3.mul(y)

-        if !zs3.equals(zo3) {return false}

-

-        return true;

-    }

-    /* set self=-self */

-    func neg()

-    {

-        if is_infinity() {return}

-        y.neg(); y.norm()

-        return

-    }

-    /* set to Affine - (x,y,z) to (x,y) */

-    func affine() {

-        if is_infinity() {return}

-        let one=FP2(1)

-        if z.equals(one) {return}

-        z.inverse()

-

-        let z2=FP2(z)

-        z2.sqr()

-        x.mul(z2); x.reduce()

-        y.mul(z2)

-        y.mul(z);  y.reduce()

-        z.copy(one)

-    }

-    /* extract affine x as FP2 */

-    func getX() -> FP2

-    {

-        affine()

-        return x

-    }

-    /* extract affine y as FP2 */

-    func getY() -> FP2

-    {

-        affine()

-        return y

-    }

-    /* extract projective x */

-    func getx() -> FP2

-    {

-        return x

-    }

-    /* extract projective y */

-    func gety() -> FP2

-    {

-        return y

-    }

-    /* extract projective z */

-    func getz() -> FP2

-    {

-        return z

-    }

-    /* convert to byte array */

-    func toBytes(inout b:[UInt8])

-    {

-        let RM=Int(ROM.MODBYTES)

-        var t=[UInt8](count:RM,repeatedValue:0)

-

-        affine();

-        x.getA().toBytes(&t)

-        for var i=0;i<RM;i++

-            {b[i]=t[i]}

-        x.getB().toBytes(&t);

-        for var i=0;i<RM;i++

-            {b[i+RM]=t[i]}

-

-        y.getA().toBytes(&t);

-        for var i=0;i<RM;i++

-            {b[i+2*RM]=t[i]}

-        y.getB().toBytes(&t);

-        for var i=0;i<RM;i++

-            {b[i+3*RM]=t[i]}

-    }

-    /* convert from byte array to point */

-    static func fromBytes(b:[UInt8]) -> ECP2

-    {

-        let RM=Int(ROM.MODBYTES)

-        var t=[UInt8](count:RM,repeatedValue:0)

-

-

-        for var i=0;i<RM;i++ {t[i]=b[i]}

-        var ra=BIG.fromBytes(t);

-        for var i=0;i<RM;i++ {t[i]=b[i+RM]}

-        var rb=BIG.fromBytes(t);

-        let rx=FP2(ra,rb)

-

-        for var i=0;i<RM;i++ {t[i]=b[i+2*RM]}

-        ra=BIG.fromBytes(t)

-        for var i=0;i<RM;i++ {t[i]=b[i+3*RM]}

-        rb=BIG.fromBytes(t)

-        let ry=FP2(ra,rb)

-

-        return ECP2(rx,ry)

-    }

-/* convert self to hex string */

-    func toString() -> String

-    {

-        if is_infinity() {return "infinity"}

-        affine()

-        return "("+x.toString()+","+y.toString()+")"

-    }

-

-/* Calculate RHS of twisted curve equation x^3+B/i */

-    static func RHS(x:FP2) -> FP2

-    {

-        x.norm()

-        let r=FP2(x)

-        r.sqr()

-        let b=FP2(BIG(ROM.CURVE_B))

-        b.div_ip();

-        r.mul(x);

-        r.add(b);

-

-        r.reduce();

-        return r;

-    }

-/* construct self from (x,y) - but set to O if not on curve */

-    init(_ ix:FP2,_ iy:FP2)

-    {

-        x=FP2(ix)

-        y=FP2(iy)

-        z=FP2(1)

-        let rhs=ECP2.RHS(x)

-        let y2=FP2(y)

-        y2.sqr()

-        if y2.equals(rhs) {INF=false}

-        else {x.zero(); INF=true}

-    }

-    /* construct this from x - but set to O if not on curve */

-    init(_ ix:FP2)

-    {

-        x=FP2(ix)

-        y=FP2(1)

-        z=FP2(1)

-        let rhs=ECP2.RHS(x)

-        if rhs.sqrt()

-        {

-            y.copy(rhs);

-            INF=false;

-        }

-        else {x.zero(); INF=true;}

-    }

-

-    /* this+=this */

-    func dbl() -> Int

-    {

-        if (INF) {return -1}

-        if y.iszilch()

-        {

-            inf();

-            return -1;

-        }

-

-        let w1=FP2(x)

-        let w2=FP2(0)

-        let w3=FP2(x)

-        let w8=FP2(x)

-

-        w1.sqr()

-        w8.copy(w1)

-        w8.imul(3)

-

-        w2.copy(y); w2.sqr()

-        w3.copy(x); w3.mul(w2)

-        w3.imul(4)

-        w1.copy(w3); w1.neg()

-        w1.norm()

-

-        x.copy(w8); x.sqr()

-        x.add(w1)

-        x.add(w1)

-        x.norm()

-

-        z.mul(y)

-        z.add(z)

-

-        w2.add(w2)

-        w2.sqr()

-        w2.add(w2)

-        w3.sub(x)

-        y.copy(w8); y.mul(w3)

-        w2.norm()

-        y.sub(w2)

-        y.norm()

-        z.norm()

-

-        return 1

-    }

-/* this+=Q - return 0 for add, 1 for double, -1 for O */

-    func add(Q:ECP2) -> Int

-    {

-        if INF

-        {

-            copy(Q)

-            return -1

-        }

-        if Q.INF {return -1}

-

-        var aff=false

-

-        if Q.z.isunity() {aff=true}

-

-        var A:FP2

-        var C:FP2

-        let B=FP2(z)

-        let D=FP2(z)

-        if (!aff)

-        {

-            A=FP2(Q.z)

-            C=FP2(Q.z)

-

-            A.sqr(); B.sqr()

-            C.mul(A); D.mul(B)

-

-            A.mul(x)

-            C.mul(y)

-        }

-        else

-        {

-            A=FP2(x)

-            C=FP2(y)

-

-            B.sqr()

-            D.mul(B)

-        }

-

-        B.mul(Q.x); B.sub(A)

-        D.mul(Q.y); D.sub(C)

-

-        if B.iszilch()

-        {

-            if D.iszilch()

-            {

-				dbl()

-				return 1

-            }

-            else

-            {

-				INF=true

-				return -1

-            }

-        }

-

-        if !aff {z.mul(Q.z)}

-        z.mul(B)

-

-        let e=FP2(B); e.sqr()

-        B.mul(e)

-        A.mul(e)

-

-        e.copy(A)

-        e.add(A); e.add(B)

-        x.copy(D); x.sqr(); x.sub(e)

-

-        A.sub(x)

-        y.copy(A); y.mul(D)

-        C.mul(B); y.sub(C)

-

-        x.norm()

-        y.norm()

-        z.norm()

-

-        return 0

-    }

-

-    /* set self-=Q */

-    func sub(Q:ECP2) -> Int

-    {

-        Q.neg()

-        let D=add(Q)

-        Q.neg()

-        return D

-    }

-/* set self*=q, where q is Modulus, using Frobenius */

-    func frob(X:FP2)

-    {

-        if INF {return}

-        let X2=FP2(X)

-        X2.sqr()

-        x.conj()

-        y.conj()

-        z.conj()

-        z.reduce()

-        x.mul(X2)

-        y.mul(X2)

-        y.mul(X)

-    }

-    /* normalises m-array of ECP2 points. Requires work vector of m FP2s */

-

-    private static func multiaffine(m:Int,_ P:[ECP2])

-    {

-        let t1=FP2(0)

-        let t2=FP2(0)

-

-        var work=[FP2]()

-        for var i=0;i<m;i++

-            {work.append(FP2(0))}

-

-        work[0].one()

-        work[1].copy(P[0].z)

-

-        for var i=2;i<m;i++

-        {

-            work[i].copy(work[i-1])

-            work[i].mul(P[i-1].z)

-        }

-

-        t1.copy(work[m-1]); t1.mul(P[m-1].z)

-

-        t1.inverse()

-

-        t2.copy(P[m-1].z)

-        work[m-1].mul(t1)

-

-        for var i=m-2;;i--

-        {

-            if (i==0)

-            {

-				work[0].copy(t1)

-				work[0].mul(t2)

-				break;

-            }

-            work[i].mul(t2)

-            work[i].mul(t1)

-            t2.mul(P[i].z)

-        }

-    /* now work[] contains inverses of all Z coordinates */

-

-        for var i=0;i<m;i++

-        {

-            P[i].z.one()

-            t1.copy(work[i]); t1.sqr()

-            P[i].x.mul(t1)

-            t1.mul(work[i])

-            P[i].y.mul(t1)

-        }

-    }

-

-    /* P*=e */

-    func mul(e:BIG) -> ECP2

-    {

-    /* fixed size windows */

-        let mt=BIG()

-        let t=BIG()

-        let P=ECP2()

-        let Q=ECP2()

-        let C=ECP2()

-

-        var W=[ECP2]();

-        for var i=0;i<8;i++ {W.append(ECP2())}

-

-        var w=[Int8](count:1+(ROM.NLEN*Int(ROM.BASEBITS)+3)/4,repeatedValue:0)

-

-        if is_infinity() {return ECP2()}

-

-        affine()

-

-    /* precompute table */

-        Q.copy(self)

-        Q.dbl()

-        W[0].copy(self)

-

-        for var i=1;i<8;i++

-        {

-            W[i].copy(W[i-1])

-            W[i].add(Q)

-        }

-

-    /* convert the table to affine */

-

-        ECP2.multiaffine(8,W);

-

-    /* make exponent odd - add 2P if even, P if odd */

-        t.copy(e)

-        let s=t.parity()

-        t.inc(1); t.norm(); let ns=t.parity(); mt.copy(t); mt.inc(1); mt.norm()

-        t.cmove(mt,s)

-        Q.cmove(self,ns)

-        C.copy(Q)

-

-        let nb=1+(t.nbits()+3)/4

-    /* convert exponent to signed 4-bit window */

-        for var i=0;i<nb;i++

-        {

-            w[i]=Int8(t.lastbits(5)-16)

-            t.dec(Int32(w[i])); t.norm()

-            t.fshr(4)

-        }

-        w[nb]=Int8(t.lastbits(5))

-

-        P.copy(W[(w[nb]-1)/2])

-        for var i=nb-1;i>=0;i--

-        {

-            Q.select(W,Int32(w[i]))

-            P.dbl()

-            P.dbl()

-            P.dbl()

-            P.dbl()

-            P.add(Q)

-        }

-        P.sub(C);

-        P.affine()

-        return P;

-    }

-

-    /* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3 */

-    static func mul4(Q:[ECP2],_ u:[BIG]) -> ECP2

-    {

-        var a=[Int32](count:4,repeatedValue:0)

-        let T=ECP2()

-        let C=ECP2()

-        let P=ECP2()

-

-        var W=[ECP2]();

-        for var i=0;i<8;i++ {W.append(ECP2())}

-

-        let mt=BIG()

-        var t=[BIG]()

-

-        var w=[Int8](count:ROM.NLEN*Int(ROM.BASEBITS)+1,repeatedValue:0)

-

-        for var i=0;i<4;i++

-        {

-            t.append(BIG(u[i]))

-            Q[i].affine()

-        }

-

-    /* precompute table */

-

-        W[0].copy(Q[0]); W[0].sub(Q[1])

-        W[1].copy(W[0])

-        W[2].copy(W[0])

-        W[3].copy(W[0])

-        W[4].copy(Q[0]); W[4].add(Q[1])

-        W[5].copy(W[4])

-        W[6].copy(W[4])

-        W[7].copy(W[4])

-        T.copy(Q[2]); T.sub(Q[3])

-        W[1].sub(T)

-        W[2].add(T)

-        W[5].sub(T)

-        W[6].add(T)

-        T.copy(Q[2]); T.add(Q[3])

-        W[0].sub(T)

-        W[3].add(T)

-        W[4].sub(T)

-        W[7].add(T)

-

-        ECP2.multiaffine(8,W);

-

-    /* if multiplier is even add 1 to multiplier, and add P to correction */

-        mt.zero(); C.inf()

-        for var i=0;i<4;i++

-        {

-            if (t[i].parity()==0)

-            {

-				t[i].inc(1); t[i].norm()

-                C.add(Q[i])

-            }

-            mt.add(t[i]); mt.norm()

-        }

-

-        let nb=1+mt.nbits();

-

-    /* convert exponent to signed 1-bit window */

-        for var j=0;j<nb;j++

-        {

-            for var i=0;i<4;i++

-            {

-				a[i]=(t[i].lastbits(2)-2)

-				t[i].dec(a[i]); t[i].norm()

-				t[i].fshr(1)

-            }

-            w[j]=Int8(8*a[0]+4*a[1]+2*a[2]+a[3])

-        }

-        w[nb]=Int8(8*t[0].lastbits(2)+4*t[1].lastbits(2))

-        w[nb]+=Int8(2*t[2].lastbits(2)+t[3].lastbits(2))

-

-        P.copy(W[(w[nb]-1)/2])

-        for var i=nb-1;i>=0;i--

-        {

-            T.select(W,Int32(w[i]))

-            P.dbl()

-            P.add(T)

-        }

-        P.sub(C) /* apply correction */

-

-        P.affine()

-        return P

-    }

-

-

-

-}

diff --git a/swift/ff.swift b/swift/ff.swift
deleted file mode 100644
index 0491a77..0000000
--- a/swift/ff.swift
+++ /dev/null
@@ -1,918 +0,0 @@
-/*

-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.

-*/

-//

-//  ff.swift

-//  

-//

-//  Created by Michael Scott on 24/06/2015.

-//  Copyright (c) 2015 Michael Scott. All rights reserved.

-//

-

-/* Large Finite Field arithmetic */

-/* CLINT mod p functions */

-

-final class FF {

-    var v = [BIG]()

-    var length:Int=1

-

-    private static let P_MBITS:Int32=ROM.MODBYTES*8

-    private static let P_MB=(P_MBITS%ROM.BASEBITS)

-    private static let P_OMASK=(Int32(-1)<<(P_MBITS%ROM.BASEBITS))

-    private static let P_FEXCESS=(Int32(1)<<(ROM.BASEBITS*Int32(ROM.NLEN)-P_MBITS))

-    private static let P_TBITS=(P_MBITS%ROM.BASEBITS)

-

-    func P_EXCESS() -> Int32

-    {

-        return ((v[length-1].w[ROM.NLEN-1]&FF.P_OMASK)>>FF.P_MB)

-    }

-    /* Constructors */

-    init(_ n: Int)

-    {

-        for var i=0;i<n;i++

-        {

-            v.append(BIG(0));

-        }

-        length=n;

-    }

-

-    init(_ x: [[Int32]],n: Int)

-    {

-        for var i=0;i<n;i++

-        {

-            v.append(BIG(x[i]))

-        }

-        length=n;

-    }

-

-    func getlen() -> Int

-    {

-        return length;

-    }

-

-    /* set to zero */

-    func zero()

-    {

-        for var i=0;i<length;i++

-        {

-            v[i].zero();

-        }

-    }

-

-    /* set to integer */

-    func set(m: Int32)

-    {

-        zero();

-        v[0].set(0,(m&ROM.MASK));

-        v[0].set(1,(m>>ROM.BASEBITS));

-    }

-

-    /* copy from FF b */

-    func copy(b: FF)

-    {

-        for var i=0;i<length;i++

-        {

-            v[i].copy(b.v[i]);

-        }

-    }

-

-    /* x=y<<n */

-    func dsucopy(b: FF)

-    {

-        for var i=0;i<b.length;i++

-        {

-            v[b.length+i].copy(b.v[i]);

-            v[i].zero();

-        }

-    }

-    /* x=y */

-    func dscopy(b: FF)

-    {

-        for var i=0;i<b.length;i++

-        {

-            v[i].copy(b.v[i]);

-            v[b.length+i].zero();

-        }

-    }

-    /* x=y>>n */

-    func sducopy(b: FF)

-    {

-        for var i=0;i<length;i++

-        {

-            v[i].copy(b.v[length+i]);

-        }

-    }

-    func one()

-    {

-        v[0].one();

-        for var i=1;i<length;i++

-        {

-            v[i].zero();

-        }

-    }

-    /* test equals 0 */

-    func iszilch() -> Bool

-    {

-        for var i=0;i<length;i++

-        {

-            if (!v[i].iszilch()) {return false}

-        }

-        return true;

-    }

-    /* shift right by 256-bit words */

-    func shrw(n: Int)

-    {

-        for var i=0;i<n;i++

-        {

-            v[i].copy(v[i+n]);

-            v[i+n].zero();

-        }

-    }

-

-    /* shift left by 256-bit words */

-    func shlw(n: Int)

-    {

-        for var i=0;i<n;i++

-        {

-        v[n+i].copy(v[i]);

-        v[i].zero();

-        }

-    }

-

-    /* extract last bit */

-    func parity() -> Int32

-    {

-        return v[0].parity()

-    }

-

-    func lastbits(m: Int) ->Int32

-    {

-        return v[0].lastbits(m);

-    }

-

-    /* compare x and y - must be normalised, and of same length */

-    static func comp(a: FF,_ b:FF) -> Int

-    {

-        for var i=a.length-1;i>=0;i--

-        {

-            let j=BIG.comp(a.v[i],b.v[i])

-            if j != 0 {return j}

-        }

-        return 0;

-    }

-    /* recursive add */

-    func radd(vp: Int,_ x:FF,_ xp:Int,_ y:FF,_ yp:Int,_ n: Int)

-    {

-        for var i=0;i<n;i++

-        {

-            v[vp+i].copy(x.v[xp+i])

-            v[vp+i].add(y.v[yp+i])

-        }

-    }

-    /* recursive inc */

-    func rinc(vp: Int,_ y: FF,_ yp: Int,_ n:Int)

-    {

-        for var i=0;i<n;i++

-        {

-            v[vp+i].add(y.v[yp+i])

-        }

-    }

-    /* recursive add */

-    func rsub(vp: Int,_ x:FF,_ xp:Int,_ y:FF,_ yp:Int,_ n: Int)

-    {

-        for var i=0;i<n;i++

-        {

-            v[vp+i].copy(x.v[xp+i])

-            v[vp+i].sub(y.v[yp+i])

-        }

-    }

-    /* recursive inc */

-    func rdec(vp: Int,_ y: FF,_ yp: Int,_ n:Int)

-    {

-        for var i=0;i<n;i++

-        {

-            v[vp+i].sub(y.v[yp+i])

-        }

-    }

-    /* simple add */

-    func add(b: FF)

-    {

-        for var i=0;i<length;i++

-            {v[i].add(b.v[i])}

-    }

-

-    /* simple sub */

-    func sub(b: FF)

-    {

-        for var i=0;i<length;i++

-            {v[i].sub(b.v[i])}

-    }

-    /* reverse sub */

-    func revsub(b: FF)

-    {

-        for var i=0;i<length;i++

-            {v[i].rsub(b.v[i])}

-    }

-    /* normalise - but hold any overflow in top part unless n<0 */

-    private func rnorm(vp: Int,_ n: Int)

-    {

-        var trunc=false;

-        var nn=n

-

-        if (nn<0)

-        { /* -v n signals to do truncation */

-            nn = -nn

-            trunc=true;

-        }

-        for var i=0;i<nn-1;i++

-        {

-            let carry=v[vp+i].norm();

-            v[vp+i].xortop(carry<<FF.P_TBITS)

-            v[vp+i+1].inc(carry)

-        }

-        let carry=v[vp+nn-1].norm();

-        if (trunc)

-            {v[vp+nn-1].xortop(carry<<FF.P_TBITS)}

-    }

-

-    func norm()

-    {

-        rnorm(0,length)

-    }

-

-    /* increment/decrement by a small integer */

-    func inc(m: Int32)

-    {

-        v[0].inc(m);

-        norm();

-    }

-

-    func dec(m: Int32)

-    {

-        v[0].dec(m);

-        norm();

-    }

-

-    /* shift left by one bit */

-    func shl()

-    {

-        var delay_carry:Int32=0;

-        for var i=0;i<length-1;i++

-        {

-            let carry=v[i].fshl(1)

-            v[i].inc(delay_carry);

-            v[i].xortop(carry<<FF.P_TBITS);

-            delay_carry=carry;

-        }

-        v[length-1].fshl(1)

-        v[length-1].inc(delay_carry)

-    }

-

-    /* shift right by one bit */

-    func shr()

-    {

-        for var i=length-1;i>0;i--

-        {

-            let carry=v[i].fshr(1);

-            v[i-1].ortop(carry<<FF.P_TBITS);

-        }

-        v[0].fshr(1);

-    }

-

-    /* Convert to Hex String */

-    func toString() -> String

-    {

-        norm();

-        var s="";

-        for var i=length-1;i>=0;i--

-        {

-            s+=v[i].toString();

-        }

-        return s;

-    }

-

-    /* Convert FFs to/from byte arrays */

-    func toBytes(inout b: [UInt8])

-    {

-        for var i=0;i<length;i++

-        {

-            v[i].tobytearray(&b,(length-i-1)*Int(ROM.MODBYTES))

-        }

-    }

-    static func fromBytes(x: FF,_ b:[UInt8])

-    {

-        for var i=0;i<x.length;i++

-        {

-            x.v[i]=BIG.frombytearray(b,(x.length-i-1)*Int(ROM.MODBYTES))

-        }

-    }

-

-    /* in-place swapping using xor - side channel resistant - lengths must be the same */

-    private static func cswap(a: FF,_ b:FF,_ d:Int32)

-    {

-        for var i=0;i<a.length;i++

-        {

-            a.v[i].cswap(b.v[i],d)

-        }

-    }

-    /* z=x*y, t is workspace */

-    private func karmul(vp: Int,_ x: FF,_ xp: Int,_ y:FF,_ yp: Int,_ t:FF,_ tp:Int,_ n:Int)

-    {

-        if (n==1)

-        {

-            let d=BIG.mul(x.v[xp],y.v[yp])

-            v[vp+1]=d.split(8*ROM.MODBYTES)

-            v[vp].copy(d)

-            return

-        }

-        let nd2=n/2

-        radd(vp,x,xp,x,xp+nd2,nd2)

-        rnorm(vp,nd2)

-        radd(vp+nd2,y,yp,y,yp+nd2,nd2)

-        rnorm(vp+nd2,nd2)

-

-        t.karmul(tp,self,vp,self,vp+nd2,t,tp+n,nd2)

-        karmul(vp,x,xp,y,yp,t,tp+n,nd2)

-        karmul(vp+n,x,xp+nd2,y,yp+nd2,t,tp+n,nd2)

-        t.rdec(tp,self,vp,n)

-        t.rdec(tp,self,vp+n,n)

-        rinc(vp+nd2,t,tp,n)

-        rnorm(vp,2*n)

-    }

-

-    private func karsqr(vp: Int,_ x: FF,_ xp:Int,_ t:FF,_ tp:Int,_ n:Int)

-    {

-        if (n==1)

-        {

-            let d=BIG.sqr(x.v[xp])

-            v[vp+1].copy(d.split(8*ROM.MODBYTES))

-            v[vp].copy(d);

-            return;

-        }

-

-        let nd2=n/2

-        karsqr(vp,x,xp,t,tp+n,nd2)

-        karsqr(vp+n,x,xp+nd2,t,tp+n,nd2)

-        t.karmul(tp,x,xp,x,xp+nd2,t,tp+n,nd2)

-        rinc(vp+nd2,t,tp,n)

-        rinc(vp+nd2,t,tp,n)

-        rnorm(vp+nd2,n)

-    }

-    private func karmul_lower(vp:Int,_ x:FF,_ xp:Int,_ y:FF,_ yp:Int,_ t:FF,_ tp:Int,_ n: Int)

-    { /* Calculates Least Significant bottom half of x*y */

-        if (n==1)

-        { /* only calculate bottom half of product */

-            v[vp].copy(BIG.smul(x.v[xp],y.v[yp]))

-            return

-        }

-        let nd2=n/2

-

-        karmul(vp,x,xp,y,yp,t,tp+n,nd2)

-        t.karmul_lower(tp,x,xp+nd2,y,yp,t,tp+n,nd2);

-        rinc(vp+nd2,t,tp,nd2);

-        t.karmul_lower(tp,x,xp,y,yp+nd2,t,tp+n,nd2);

-        rinc(vp+nd2,t,tp,nd2);

-        rnorm(vp+nd2,-nd2);  /* truncate it */

-    }

-

-    private func karmul_upper(x: FF,_ y:FF,_ t:FF,_ n:Int)

-    { /* Calculates Most Significant upper half of x*y, given lower part */

-        let nd2=n/2;

-        radd(n,x,0,x,nd2,nd2);

-        radd(n+nd2,y,0,y,nd2,nd2);

-

-        t.karmul(0,self,n+nd2,self,n,t,n,nd2);  /* t = (a0+a1)(b0+b1) */

-        karmul(n,x,nd2,y,nd2,t,n,nd2);          /* z[n]= a1*b1 */

-    /* z[0-nd2]=l(a0b0) z[nd2-n]= h(a0b0)+l(t)-l(a0b0)-l(a1b1) */

-        t.rdec(0,self,n,n);                     /* t=t-a1b1  */

-        rinc(nd2,self,0,nd2);                   /* z[nd2-n]+=l(a0b0) = h(a0b0)+l(t)-l(a1b1)  */

-        rdec(nd2,t,0,nd2);                      /* z[nd2-n]=h(a0b0)+l(t)-l(a1b1)-l(t-a1b1)=h(a0b0) */

-        rnorm(0,-n);                            /* a0b0 now in z - truncate it */

-        t.rdec(0,self,0,n);                     /* (a0+a1)(b0+b1) - a0b0 */

-        rinc(nd2,t,0,n);

-

-        rnorm(nd2,n);

-    }

-    /* z=x*y. Assumes x and y are of same length. */

-    static func mul(x: FF,_ y:FF) -> FF

-    {

-        let n=x.length

-        let z=FF(2*n)

-        let t=FF(2*n)

-        z.karmul(0,x,0,y,0,t,0,n)

-        return z

-    }

-

-    /* z=x^2 */

-    static func sqr(x: FF) -> FF

-    {

-        let n=x.length

-        let z=FF(2*n)

-        let t=FF(2*n)

-        z.karsqr(0,x,0,t,0,n)

-        return z

-    }

-    /* return low part of product self*y */

-    func lmul(y: FF)

-    {

-        let n=length;

-        let t=FF(2*n);

-        let x=FF(n); x.copy(self);

-        karmul_lower(0,x,0,y,0,t,0,n);

-    }

-

-    /* Set b=b mod c */

-    func mod(c: FF)

-    {

-        var k=0

-

-        norm()

-        if (FF.comp(self,c)<0)

-            {return}

-        repeat

-        {

-            c.shl()

-            k++

-        } while (FF.comp(self,c)>=0)

-

-        while (k>0)

-        {

-            c.shr();

-            if (FF.comp(self,c)>=0)

-            {

-				sub(c)

-				norm()

-            }

-            k--

-        }

-    }

-

-    /* return This mod modulus, N is modulus, ND is Montgomery Constant */

-    func reduce(N: FF,_ ND:FF) -> FF

-    { /* fast karatsuba Montgomery reduction */

-        let n=N.length

-        let t=FF(2*n)

-        let r=FF(n)

-        let m=FF(n)

-

-        r.sducopy(self)

-        m.karmul_lower(0,self,0,ND,0,t,0,n)

-        karmul_upper(N,m,t,n)

-        m.sducopy(self)

-

-        r.add(N);

-        r.sub(m);

-        r.norm();

-

-        return r;

-    }

-    /* Set r=this mod b */

-    /* this is of length - 2*n */

-    /* r,b is of length - n */

-    func dmod(b: FF) -> FF

-    {

-        let n=b.length

-        let m=FF(2*n)

-        let x=FF(2*n)

-        let r=FF(n)

-

-        x.copy(self)

-        x.norm()

-        m.dsucopy(b)

-        var k=256*n

-

-        while (k>0)

-        {

-            m.shr()

-

-            if (FF.comp(x,m)>=0)

-            {

-				x.sub(m);

-				x.norm();

-            }

-            k--;

-        }

-

-        r.copy(x);

-        r.mod(b);

-        return r;

-    }

-    /* Set return=1/this mod p. Binary method - a<p on entry */

-

-    func invmodp(p: FF)

-    {

-        let n=p.length;

-

-        let u=FF(n)

-        let v=FF(n)

-        let x1=FF(n)

-        let x2=FF(n)

-        let t=FF(n)

-        let one=FF(n)

-

-        one.one()

-        u.copy(self)

-        v.copy(p)

-        x1.copy(one)

-        x2.zero()

-

-    // reduce n in here as well!

-        while (FF.comp(u,one) != 0 && FF.comp(v,one) != 0)

-        {

-            while (u.parity()==0)

-            {

-                u.shr()

-                if (x1.parity() != 0)

-                {

-                    x1.add(p)

-                    x1.norm()

-                }

-                x1.shr()

-            }

-            while (v.parity()==0)

-            {

-                v.shr()

-                if (x2.parity() != 0)

-                {

-                    x2.add(p)

-                    x2.norm()

-                }

-                x2.shr();

-            }

-            if (FF.comp(u,v)>=0)

-            {

-                u.sub(v)

-                u.norm()

-                if (FF.comp(x1,x2)>=0) {x1.sub(x2)}

-                else

-                {

-                    t.copy(p)

-                    t.sub(x2)

-                    x1.add(t)

-                }

-                x1.norm()

-            }

-            else

-            {

-                v.sub(u)

-                v.norm()

-                if (FF.comp(x2,x1)>=0) {x2.sub(x1)}

-                else

-                {

-                    t.copy(p)

-                    t.sub(x1)

-                    x2.add(t)

-                }

-                x2.norm()

-            }

-        }

-        if FF.comp(u,one)==0

-            {copy(x1)}

-        else

-            {copy(x2)}

-    }

-

-    /* nresidue mod m */

-    func nres(m: FF)

-    {

-        let n=m.length

-        let d=FF(2*n)

-        d.dsucopy(self)

-        copy(d.dmod(m))

-    }

-

-    func redc(m: FF,_ ND:FF)

-    {

-        let n=m.length

-        let d=FF(2*n)

-        mod(m)

-        d.dscopy(self)

-        copy(d.reduce(m,ND))

-        mod(m)

-    }

-    private func mod2m(m: Int)

-    {

-        for var i=m;i<length;i++

-            {v[i].zero()}

-    }

-    /* U=1/a mod 2^m - Arazi & Qi */

-    private func invmod2m() -> FF

-    {

-        let n=length;

-

-        let b=FF(n);

-        let c=FF(n);

-        let U=FF(n);

-

-        U.zero();

-        U.v[0].copy(v[0]);

-        U.v[0].invmod2m();

-

-        for var i=1;i<n;i<<=1

-        {

-            b.copy(self); b.mod2m(i);

-            let t=FF.mul(U,b); t.shrw(i); b.copy(t);

-            c.copy(self); c.shrw(i); c.mod2m(i);

-            c.lmul(U); c.mod2m(i);

-

-            b.add(c); b.norm();

-            b.lmul(U); b.mod2m(i);

-

-            c.one(); c.shlw(i); b.revsub(c); b.norm();

-            b.shlw(i);

-            U.add(b);

-        }

-        U.norm();

-        return U;

-    }

-

-    func random(rng: RAND)

-    {

-        let n=length;

-        for var i=0;i<n;i++

-        {

-            v[i].copy(BIG.random(rng));

-        }

-    /* make sure top bit is 1 */

-        while (v[n-1].nbits()<Int(ROM.MODBYTES)*8) {v[n-1].copy(BIG.random(rng))}

-    }

-    /* generate random x */

-    func randomnum(p: FF,_ rng: RAND)

-    {

-        let n=length;

-        let d=FF(2*n);

-

-        for var i=0;i<2*n;i++

-        {

-            d.v[i].copy(BIG.random(rng));

-        }

-        copy(d.dmod(p));

-    }

-    /* this*=y mod p */

-    func modmul(y: FF,_ p:FF,_ nd: FF)

-    {

-        let ex=P_EXCESS();

-        let ey=y.P_EXCESS();

-        if ((ex+1)*(ey+1)+1>=FF.P_FEXCESS) {mod(p)}

-        let d=FF.mul(self,y);

-        copy(d.reduce(p,nd));

-    }

-

-    /* this*=y mod p */

-    func modsqr(p: FF,_ nd:FF)

-    {

-        let ex=P_EXCESS();

-        if ((ex+1)*(ex+1)+1>=FF.P_FEXCESS) {mod(p)}

-        let d=FF.sqr(self);

-        copy(d.reduce(p,nd));

-    }

-

-    /* self=self^e mod p using side-channel resistant Montgomery Ladder, for large e */

-    func skpow(e: FF,_ p:FF)

-    {

-        let n=p.length

-        let R0=FF(n)

-        let R1=FF(n)

-        let ND=p.invmod2m()

-

-        mod(p)

-        R0.one()

-        R1.copy(self)

-        R0.nres(p)

-        R1.nres(p)

-

-        for var i=8*Int(ROM.MODBYTES)*n-1;i>=0;i--

-        {

-            let b=Int32(e.v[i/256].bit(i%256))

-            copy(R0)

-            modmul(R1,p,ND)

-

-            FF.cswap(R0,R1,b)

-            R0.modsqr(p,ND)

-

-            R1.copy(self)

-            FF.cswap(R0,R1,b)

-

-        }

-

-        copy(R0)

-        redc(p,ND)

-    }

-

-    /* this =this^e mod p using side-channel resistant Montgomery Ladder, for short e */

-    func skpow(e: BIG,_ p:FF)

-    {

-        let n=p.length

-        let R0=FF(n)

-        let R1=FF(n)

-        let ND=p.invmod2m()

-

-        mod(p)

-        R0.one()

-        R1.copy(self)

-        R0.nres(p)

-        R1.nres(p)

-

-        for var i=8*Int(ROM.MODBYTES)-1;i>=0;i--

-        {

-            let b=Int32(e.bit(i))

-            copy(R0)

-            modmul(R1,p,ND)

-

-            FF.cswap(R0,R1,b)

-            R0.modsqr(p,ND)

-

-            R1.copy(self)

-            FF.cswap(R0,R1,b)

-        }

-        copy(R0)

-        redc(p,ND)

-    }

-

-    /* raise to an integer power - right-to-left method */

-    func power(e:Int32,_ p:FF)

-    {

-        let n=p.length

-        var f=true

-        let w=FF(n)

-        let ND=p.invmod2m()

-        var ee=e;

-

-        w.copy(self)

-        w.nres(p)

-

-        if (ee==2)

-        {

-            copy(w)

-            modsqr(p,ND)

-        }

-        else

-        {

-            while true

-            {

-                if (ee%2==1)

-                {

-                    if (f) {copy(w)}

-                    else {modmul(w,p,ND)}

-                    f=false;

-                }

-                ee>>=1;

-                if (ee==0) {break}

-                w.modsqr(p,ND)

-            }

-        }

-        redc(p,ND)

-    }

-

-    /* this=this^e mod p, faster but not side channel resistant */

-    func pow(e: FF,_ p:FF)

-    {

-        let n=p.length

-        let w=FF(n)

-        let ND=p.invmod2m()

-

-        w.copy(self);

-        one();

-        nres(p);

-        w.nres(p);

-        for var i=8*Int(ROM.MODBYTES)*n-1;i>=0;i--

-        {

-            modsqr(p,ND)

-            let b=e.v[i/256].bit(i%256)

-            if (b==1) {modmul(w,p,ND)}

-        }

-        redc(p,ND);

-    }

-    /* double exponentiation r=x^e.y^f mod p */

-    func pow2(e: BIG,_ y:FF,_ f:BIG,_ p:FF)

-    {

-        let n=p.length

-        let xn=FF(n)

-        let yn=FF(n)

-        let xy=FF(n)

-        let ND=p.invmod2m()

-

-        xn.copy(self)

-        yn.copy(y)

-        xn.nres(p)

-        yn.nres(p)

-        xy.copy(xn); xy.modmul(yn,p,ND)

-        one()

-        nres(p)

-

-        for var i=8*Int(ROM.MODBYTES)-1;i>=0;i--

-        {

-            let eb=e.bit(i)

-            let fb=f.bit(i)

-            modsqr(p,ND)

-            if (eb==1)

-            {

-                if (fb==1) {modmul(xy,p,ND)}

-                else {modmul(xn,p,ND)}

-            }

-            else

-            {

-                if (fb==1) {modmul(yn,p,ND)}

-            }

-        }

-        redc(p,ND)

-    }

-    static func igcd(x:Int32,_ y:Int32) -> Int32

-    { /* integer GCD, returns GCD of x and y */

-        var xx=x;

-        var yy=y;

-        if (yy==0) {return xx}

-        while true

-        {

-            let r=xx%yy; if r==0 {break}

-            xx=yy; yy=r;

-        }

-        return yy;

-    }

-

-    /* quick and dirty check for common factor with n */

-    func cfactor(s: Int32) -> Bool

-    {

-        let n=length;

-        let x=FF(n);

-        let y=FF(n);

-        y.set(s);

-

-        x.copy(self);

-        x.norm();

-

-        repeat

-        {

-            x.sub(y);

-            x.norm();

-            while ( (!x.iszilch()) && x.parity()==0) {x.shr()}

-        } while (FF.comp(x,y)>0);

-        let g=x.v[0].get(0);

-        let r=FF.igcd(s,g);

-

-        if (r>1) {return true}

-        return false;

-    }

-

-    /* Miller-Rabin test for primality. Slow. */

-    static func prime(p: FF,_ rng:RAND) -> Bool

-    {

-        var s=0

-        let n=p.length

-        var loop:Bool

-

-        let d=FF(n)

-        let x=FF(n)

-        let unity=FF(n)

-        let nm1=FF(n)

-

-        let sf:Int32=4849845; /* 3*5*.. *19 */

-        p.norm();

-        if (p.cfactor(sf)) {return false}

-        unity.one();

-        nm1.copy(p);

-        nm1.sub(unity);

-        nm1.norm();

-        d.copy(nm1);

-

-        while (d.parity()==0)

-        {

-            d.shr();

-            s++;

-        }

-

-        if (s==0) {return false}

-        for var i=0;i<10;i++

-        {

-            x.randomnum(p,rng)

-            x.pow(d,p)

-            if (FF.comp(x,unity)==0 || FF.comp(x,nm1)==0) {continue}

-            loop=false

-            for var j=1;j<s;j++

-            {

-				x.power(2,p);

-                if (FF.comp(x,unity)==0) {return false}

-				if (FF.comp(x,nm1)==0) {loop=true; break;}

-            }

-            if (loop) {continue}

-            return false;

-        }

-        return true;

-    }

-

-}

diff --git a/swift/fp.swift b/swift/fp.swift
deleted file mode 100644
index 0bd0f46..0000000
--- a/swift/fp.swift
+++ /dev/null
@@ -1,290 +0,0 @@
-/*

-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.

-*/

-//

-//  fp.swift

-//  

-//

-//  Created by Michael Scott on 20/06/2015.

-//  Copyright (c) 2015 Michael Scott. All rights reserved.

-//  Small Finite Field arithmetic

-//  CLINT mod p functions

-//

-

-final class FP {

-    var x:BIG

-    static let p=BIG(ROM.Modulus)

-/* convert to Montgomery n-residue form */

-    func nres()

-    {

-        if ROM.MODTYPE != ROM.PSEUDO_MERSENNE

-        {

-            let d=DBIG(x)

-            d.shl(ROM.NLEN*Int(ROM.BASEBITS))

-            x.copy(d.mod(FP.p))

-        }

-    }

-/* convert back to regular form */

-    func redc() -> BIG

-    {

-        if ROM.MODTYPE != ROM.PSEUDO_MERSENNE

-        {

-            let d=DBIG(x)

-            return BIG.mod(d)

-        }

-        else

-        {

-            let r=BIG(x)

-            return r;

-        }

-    }

-

-    init()

-    {

-        x=BIG(0)

-    }

-    init(_ a: Int32)

-    {

-        x=BIG(a)

-        nres()

-    }

-    init(_ a: BIG)

-    {

-        x=BIG(a)

-        nres()

-    }

-    init(_ a: FP)

-    {

-        x=BIG(a.x)

-    }

-    /* convert to string */

-    func toString() -> String

-    {

-        let s=redc().toString();

-        return s;

-    }

-

-    func toRawString() -> String

-    {

-        let s=x.toRawString();

-        return s;

-    }

-/* reduce this mod Modulus */

-    func reduce()

-    {

-        x.mod(FP.p)

-    }

-

-/* test this=0? */

-    func iszilch() -> Bool

-    {

-        reduce();

-        return x.iszilch()

-    }

-

-/* copy from FP b */

-    func copy(b: FP)

-    {

-        x.copy(b.x);

-    }

-

-/* set this=0 */

-    func zero()

-    {

-        x.zero();

-    }

-

-/* set this=1 */

-    func one()

-    {

-        x.one(); nres()

-    }

-

-/* normalise this */

-    func norm()

-    {

-        x.norm();

-    }

-/* swap FPs depending on d */

-    func cswap(b: FP,_ d: Int32)

-    {

-        x.cswap(b.x,d)

-    }

-

-/* copy FPs depending on d */

-    func cmove(b: FP,_ d:Int32)

-    {

-        x.cmove(b.x,d);

-    }

-/* this*=b mod Modulus */

-    func mul(b: FP)

-    {

-        let ea=BIG.EXCESS(x)

-        let eb=BIG.EXCESS(b.x)

-

-        if (ea+1)*(eb+1)+1>=ROM.FEXCESS {reduce()}

-

-        let d=BIG.mul(x,b.x)

-        x.copy(BIG.mod(d))

-    }

-/* this = -this mod Modulus */

-    func neg()

-    {

-        let m=BIG(FP.p);

-

-        norm();

-

-        var ov=BIG.EXCESS(x);

-        var sb=1; while(ov != 0) {sb++;ov>>=1}

-

-        m.fshl(sb)

-        x.rsub(m)

-

-        if BIG.EXCESS(x)>=ROM.FEXCESS {reduce()}

-    }

-    /* this*=c mod Modulus, where c is a small int */

-    func imul(c: Int32)

-    {

-        var cc=c

-        norm();

-        var s=false

-        if (cc<0)

-        {

-            cc = -cc

-            s=true

-        }

-        let afx=(BIG.EXCESS(x)+1)*(cc+1)+1;

-        if cc<ROM.NEXCESS && afx<ROM.FEXCESS

-        {

-            x.imul(cc);

-        }

-        else

-        {

-            if afx<ROM.FEXCESS {x.pmul(cc)}

-            else

-            {

-				let d=x.pxmul(cc);

-				x.copy(d.mod(FP.p));

-            }

-        }

-        if s {neg()}

-        norm();

-    }

-

-/* this*=this mod Modulus */

-    func sqr()

-    {

-        let ea=BIG.EXCESS(x);

-        if (ea+1)*(ea+1)+1>=ROM.FEXCESS {reduce()}

-

-        let d=BIG.sqr(x);

-        x.copy(BIG.mod(d));

-    }

-

-/* this+=b */

-    func add(b: FP)

-    {

-        x.add(b.x);

-        if BIG.EXCESS(x)+2>=ROM.FEXCESS {reduce()}

-    }

-/* this-=b */

-    func sub(b: FP)

-    {

-        let n=FP(b)

-        n.neg()

-        self.add(n)

-    }

-/* this/=2 mod Modulus */

-    func div2()

-    {

-        x.norm()

-        if (x.parity()==0)

-            {x.fshr(1)}

-        else

-        {

-            x.add(FP.p)

-            x.norm()

-            x.fshr(1)

-        }

-    }

-/* this=1/this mod Modulus */

-    func inverse()

-    {

-        let r=redc()

-        r.invmodp(FP.p)

-        x.copy(r)

-        nres()

-    }

-

-/* return TRUE if this==a */

-    func equals(a: FP) -> Bool

-    {

-        a.reduce()

-        reduce()

-        if (BIG.comp(a.x,x)==0) {return true}

-        return false;

-    }

-/* return this^e mod Modulus */

-    func pow(e: BIG) -> FP

-    {

-        let r=FP(1)

-        e.norm()

-        x.norm()

-	let m=FP(self)

-        while (true)

-        {

-            let bt=e.parity()

-            e.fshr(1)

-            if bt==1 {r.mul(m)}

-            if e.iszilch() {break}

-            m.sqr();

-        }

-        r.x.mod(FP.p);

-        return r;

-    }

-/* return sqrt(this) mod Modulus */

-    func sqrt() -> FP

-    {

-        reduce();

-        let b=BIG(FP.p)

-        if (ROM.MOD8==5)

-        {

-            b.dec(5); b.norm(); b.shr(3)

-            let i=FP(self); i.x.shl(1)

-            let v=i.pow(b)

-            i.mul(v); i.mul(v)

-            i.x.dec(1)

-            let r=FP(self)

-            r.mul(v); r.mul(i)

-            r.reduce()

-            return r

-        }

-        else

-        {

-            b.inc(1); b.norm(); b.shr(2)

-            return pow(b)

-        }

-    }

-/* return jacobi symbol (this/Modulus) */

-    func jacobi() -> Int

-    {

-        let w=redc()

-        return w.jacobi(FP.p)

-    }

-

-}

diff --git a/swift/fp12.swift b/swift/fp12.swift
deleted file mode 100644
index 05617be..0000000
--- a/swift/fp12.swift
+++ /dev/null
@@ -1,581 +0,0 @@
-/*

-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.

-*/

-//

-//  fp12.swift

-//  

-//

-//  Created by Michael Scott on 07/07/2015.

-//  Copyright (c) 2015 Michael Scott. All rights reserved.

-//

-

-/* CLINT Fp^12 functions */

-/* FP12 elements are of the form a+i.b+i^2.c */

-

-final class FP12

-{

-    private final var a:FP4

-    private final var b:FP4

-    private final var c:FP4

-

-    /* reduce all components of this mod Modulus */

-    func reduce()

-    {

-        a.reduce()

-        b.reduce()

-        c.reduce()

-    }

-    /* normalise all components of this */

-    func norm()

-    {

-        a.norm();

-        b.norm();

-        c.norm();

-    }

-    /* Constructors */

-    init(_ d:FP4)

-    {

-        a=FP4(d)

-        b=FP4(0)

-        c=FP4(0)

-    }

-

-    init(_ d:Int32)

-    {

-        a=FP4(d)

-        b=FP4(0)

-        c=FP4(0)

-    }

-

-    init(_ d:FP4,_ e:FP4,_ f:FP4)

-    {

-        a=FP4(d)

-        b=FP4(e)

-        c=FP4(f)

-    }

-

-    init(_ x:FP12)

-    {

-        a=FP4(x.a)

-        b=FP4(x.b)

-        c=FP4(x.c)

-    }

-    /* test x==0 ? */

-    func iszilch() -> Bool

-    {

-        reduce();

-        return a.iszilch() && b.iszilch() && c.iszilch()

-    }

-    /* test x==1 ? */

-    func isunity() -> Bool

-    {

-        let one=FP4(1)

-        return a.equals(one) && b.iszilch() && c.iszilch()

-    }

-    /* return 1 if x==y, else 0 */

-    func equals(x:FP12) -> Bool

-    {

-        return a.equals(x.a) && b.equals(x.b) && c.equals(x.c)

-    }

-    /* extract a from self */

-    func geta() -> FP4

-    {

-        return a

-    }

-    /* extract b */

-    func getb()  -> FP4

-    {

-        return b

-    }

-    /* extract c */

-    func getc() -> FP4

-    {

-        return c

-    }

-    /* copy self=x */

-    func copy(x:FP12)

-    {

-        a.copy(x.a)

-        b.copy(x.b)

-        c.copy(x.c)

-    }

-    /* set self=1 */

-    func one()

-    {

-        a.one()

-        b.zero()

-        c.zero()

-    }

-    /* self=conj(self) */

-    func conj()

-    {

-        a.conj()

-        b.nconj()

-        c.conj()

-    }

-    /* Granger-Scott Unitary Squaring */

-    func usqr()

-    {

-        let A=FP4(a)

-        let B=FP4(c)

-        let C=FP4(b)

-        let D=FP4(0)

-

-        a.sqr()

-        D.copy(a); D.add(a)

-        a.add(D)

-

-        a.norm()

-        A.nconj()

-

-        A.add(A)

-        a.add(A)

-        B.sqr()

-        B.times_i()

-

-        D.copy(B); D.add(B)

-        B.add(D)

-        B.norm()

-

-        C.sqr()

-        D.copy(C); D.add(C)

-        C.add(D)

-        C.norm()

-

-        b.conj()

-        b.add(b)

-        c.nconj()

-

-        c.add(c)

-        b.add(B)

-        c.add(C)

-        reduce()

-

-    }

-    /* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */

-    func sqr()

-    {

-        let A=FP4(a)

-        let B=FP4(b)

-        let C=FP4(c)

-        let D=FP4(a)

-

-        A.sqr()

-        B.mul(c)

-        B.add(B)

-        C.sqr()

-        D.mul(b)

-        D.add(D)

-

-        c.add(a)

-        c.add(b)

-        c.sqr()

-

-        a.copy(A)

-

-        A.add(B)

-        A.norm()

-        A.add(C)

-        A.add(D)

-        A.norm()

-

-        A.neg()

-        B.times_i()

-        C.times_i()

-

-        a.add(B)

-

-        b.copy(C); b.add(D)

-        c.add(A)

-

-        norm()

-    }

-

-    /* FP12 full multiplication this=this*y */

-    func mul(y:FP12)

-    {

-        let z0=FP4(a)

-        let z1=FP4(0)

-        let z2=FP4(b)

-        let z3=FP4(0)

-        let t0=FP4(a)

-        let t1=FP4(y.a)

-

-        z0.mul(y.a)

-        z2.mul(y.b)

-

-        t0.add(b)

-        t1.add(y.b)

-

-        z1.copy(t0); z1.mul(t1)

-        t0.copy(b); t0.add(c)

-

-        t1.copy(y.b); t1.add(y.c)

-        z3.copy(t0); z3.mul(t1)

-

-        t0.copy(z0); t0.neg()

-        t1.copy(z2); t1.neg()

-

-        z1.add(t0)

-        z1.norm()

-        b.copy(z1); b.add(t1)

-

-        z3.add(t1)

-        z2.add(t0)

-

-        t0.copy(a); t0.add(c)

-        t1.copy(y.a); t1.add(y.c)

-        t0.mul(t1)

-        z2.add(t0)

-

-        t0.copy(c); t0.mul(y.c)

-        t1.copy(t0); t1.neg()

-

-        z2.norm()

-        z3.norm()

-        b.norm()

-

-        c.copy(z2); c.add(t1)

-        z3.add(t1)

-        t0.times_i()

-        b.add(t0)

-

-        z3.times_i()

-        a.copy(z0); a.add(z3)

-

-        norm()

-    }

-

-    /* Special case of multiplication arises from special form of ATE pairing line function */

-    func smul(y:FP12)

-    {

-        let z0=FP4(a)

-        let z2=FP4(b)

-        let z3=FP4(b)

-        let t0=FP4(0)

-        let t1=FP4(y.a)

-

-        z0.mul(y.a)

-        z2.pmul(y.b.real())

-        b.add(a)

-        t1.real().add(y.b.real())

-

-        b.mul(t1)

-        z3.add(c)

-        z3.pmul(y.b.real())

-

-        t0.copy(z0); t0.neg()

-        t1.copy(z2); t1.neg()

-

-        b.add(t0)

-        b.norm()

-

-        b.add(t1)

-        z3.add(t1)

-        z2.add(t0)

-

-        t0.copy(a); t0.add(c)

-        t0.mul(y.a)

-        c.copy(z2); c.add(t0)

-

-        z3.times_i()

-        a.copy(z0); a.add(z3)

-

-        norm()

-    }

-    /* self=1/self */

-    func inverse()

-    {

-        let f0=FP4(a)

-        let f1=FP4(b)

-        let f2=FP4(a)

-        let f3=FP4(0)

-

-        norm()

-        f0.sqr()

-        f1.mul(c)

-        f1.times_i()

-        f0.sub(f1)

-

-        f1.copy(c); f1.sqr()

-        f1.times_i()

-        f2.mul(b)

-        f1.sub(f2)

-

-        f2.copy(b); f2.sqr()

-        f3.copy(a); f3.mul(c)

-        f2.sub(f3)

-

-        f3.copy(b); f3.mul(f2)

-        f3.times_i()

-        a.mul(f0)

-        f3.add(a)

-        c.mul(f1)

-        c.times_i()

-

-        f3.add(c)

-        f3.inverse()

-        a.copy(f0); a.mul(f3)

-        b.copy(f1); b.mul(f3)

-        c.copy(f2); c.mul(f3)

-    }

-

-    /* self=self^p using Frobenius */

-    func frob(f:FP2)

-    {

-        let f2=FP2(f)

-        let f3=FP2(f)

-

-        f2.sqr()

-        f3.mul(f2)

-

-        a.frob(f3)

-        b.frob(f3)

-        c.frob(f3)

-

-        b.pmul(f)

-        c.pmul(f2)

-    }

-

-    /* trace function */

-    func trace() -> FP4

-    {

-        let t=FP4(0)

-        t.copy(a)

-        t.imul(3)

-        t.reduce()

-        return t

-    }

-    /* convert from byte array to FP12 */

-    static func fromBytes(w:[UInt8]) -> FP12

-    {

-        let RM=Int(ROM.MODBYTES)

-        var t=[UInt8](count:RM,repeatedValue:0)

-

-        for var i=0;i<RM;i++ {t[i]=w[i]}

-        var a=BIG.fromBytes(t)

-        for var i=0;i<RM;i++ {t[i]=w[i+RM]}

-        var b=BIG.fromBytes(t)

-        var c=FP2(a,b)

-

-        for var i=0;i<RM;i++ {t[i]=w[i+2*RM]}

-        a=BIG.fromBytes(t)

-        for var i=0;i<RM;i++ {t[i]=w[i+3*RM]}

-        b=BIG.fromBytes(t)

-        var d=FP2(a,b)

-

-        let e=FP4(c,d)

-

-        for var i=0;i<RM;i++ {t[i]=w[i+4*RM]}

-        a=BIG.fromBytes(t)

-        for var i=0;i<RM;i++ {t[i]=w[i+5*RM]}

-        b=BIG.fromBytes(t)

-        c=FP2(a,b)

-

-        for var i=0;i<RM;i++ {t[i]=w[i+6*RM]}

-        a=BIG.fromBytes(t)

-        for var i=0;i<RM;i++ {t[i]=w[i+7*RM]}

-        b=BIG.fromBytes(t)

-        d=FP2(a,b)

-

-        let f=FP4(c,d)

-

-

-        for var i=0;i<RM;i++ {t[i]=w[i+8*RM]}

-        a=BIG.fromBytes(t)

-        for var i=0;i<RM;i++ {t[i]=w[i+9*RM]}

-        b=BIG.fromBytes(t)

-        c=FP2(a,b)

-

-        for var i=0;i<RM;i++ {t[i]=w[i+10*RM]}

-        a=BIG.fromBytes(t)

-        for var i=0;i<RM;i++ {t[i]=w[i+11*RM]}

-        b=BIG.fromBytes(t);

-        d=FP2(a,b)

-

-        let g=FP4(c,d)

-

-        return FP12(e,f,g)

-    }

-

-    /* convert this to byte array */

-    func toBytes(inout w:[UInt8])

-    {

-        let RM=Int(ROM.MODBYTES)

-        var t=[UInt8](count:RM,repeatedValue:0)

-

-        a.geta().getA().toBytes(&t)

-        for var i=0;i<RM;i++ {w[i]=t[i]}

-        a.geta().getB().toBytes(&t)

-        for var i=0;i<RM;i++ {w[i+RM]=t[i]}

-        a.getb().getA().toBytes(&t)

-        for var i=0;i<RM;i++ {w[i+2*RM]=t[i]}

-        a.getb().getB().toBytes(&t)

-        for var i=0;i<RM;i++ {w[i+3*RM]=t[i]}

-

-        b.geta().getA().toBytes(&t)

-        for var i=0;i<RM;i++ {w[i+4*RM]=t[i]}

-        b.geta().getB().toBytes(&t);

-        for var i=0;i<RM;i++ {w[i+5*RM]=t[i]}

-        b.getb().getA().toBytes(&t)

-        for var i=0;i<RM;i++ {w[i+6*RM]=t[i]}

-        b.getb().getB().toBytes(&t)

-        for var i=0;i<RM;i++ {w[i+7*RM]=t[i]}

-

-        c.geta().getA().toBytes(&t)

-        for var i=0;i<RM;i++ {w[i+8*RM]=t[i]}

-        c.geta().getB().toBytes(&t)

-        for var i=0;i<RM;i++ {w[i+9*RM]=t[i]}

-        c.getb().getA().toBytes(&t)

-        for var i=0;i<RM;i++ {w[i+10*RM]=t[i]}

-        c.getb().getB().toBytes(&t)

-        for var i=0;i<RM;i++ {w[i+11*RM]=t[i]}

-    }

-    /* convert to hex string */

-    func toString() -> String

-    {

-        return ("["+a.toString()+","+b.toString()+","+c.toString()+"]")

-    }

-

-    /* self=self^e */

-    /* Note this is simple square and multiply, so not side-channel safe */

-    func pow(e:BIG) -> FP12

-    {

-        norm()

-        e.norm()

-        let w=FP12(self)

-        let z=BIG(e)

-        let r=FP12(1)

-

-        while (true)

-        {

-            let bt=z.parity()

-            z.fshr(1)

-            if bt==1 {r.mul(w)}

-            if z.iszilch() {break}

-            w.usqr()

-        }

-        r.reduce()

-        return r

-    }

-    /* constant time powering by small integer of max length bts */

-    func pinpow(e:Int32,_ bts:Int32)

-    {

-        var R=[FP12]()

-        R.append(FP12(1));

-        R.append(FP12(self));

-

-        for var i=bts-1;i>=0;i--

-        {

-            let b=Int((e>>i)&1)

-            R[1-b].mul(R[b])

-            R[b].usqr()

-        }

-        copy(R[0]);

-    }

-

-    /* p=q0^u0.q1^u1.q2^u2.q3^u3 */

-    /* Timing attack secure, but not cache attack secure */

-

-    static func pow4(q:[FP12],_ u:[BIG]) -> FP12

-    {

-        var a=[Int32](count:4,repeatedValue:0)

-        var g=[FP12]();

-

-        for var i=0;i<8;i++ {g.append(FP12(0))}

-        var s=[FP12]();

-        for var i=0;i<2;i++ {s.append(FP12(0))}

-

-        let c=FP12(1)

-        let p=FP12(0)

-

-        var t=[BIG]()

-        for var i=0;i<4;i++

-            {t.append(BIG(u[i]))}

-

-        let mt=BIG(0);

-        var w=[Int8](count:ROM.NLEN*Int(ROM.BASEBITS)+1,repeatedValue:0)

-

-        g[0].copy(q[0]); s[0].copy(q[1]); s[0].conj(); g[0].mul(s[0])

-        g[1].copy(g[0])

-        g[2].copy(g[0])

-        g[3].copy(g[0])

-        g[4].copy(q[0]); g[4].mul(q[1])

-        g[5].copy(g[4])

-        g[6].copy(g[4])

-        g[7].copy(g[4])

-

-        s[1].copy(q[2]); s[0].copy(q[3]); s[0].conj(); s[1].mul(s[0])

-        s[0].copy(s[1]); s[0].conj(); g[1].mul(s[0])

-        g[2].mul(s[1])

-        g[5].mul(s[0])

-        g[6].mul(s[1])

-        s[1].copy(q[2]); s[1].mul(q[3])

-        s[0].copy(s[1]); s[0].conj(); g[0].mul(s[0])

-        g[3].mul(s[1])

-        g[4].mul(s[0])

-        g[7].mul(s[1])

-

-    /* if power is even add 1 to power, and add q to correction */

-

-        for var i=0;i<4;i++

-        {

-            if t[i].parity()==0

-            {

-				t[i].inc(1); t[i].norm()

-				c.mul(q[i])

-            }

-            mt.add(t[i]); mt.norm()

-        }

-        c.conj();

-        let nb=1+mt.nbits();

-

-    /* convert exponent to signed 1-bit window */

-        for var j=0;j<nb;j++

-        {

-            for var i=0;i<4;i++

-            {

-				a[i]=(t[i].lastbits(2)-2)

-				t[i].dec(a[i]); t[i].norm()

-				t[i].fshr(1)

-            }

-            w[j]=Int8(8*a[0]+4*a[1]+2*a[2]+a[3])

-        }

-        w[nb]=Int8(8*t[0].lastbits(2)+4*t[1].lastbits(2))

-        w[nb]+=Int8(2*t[2].lastbits(2)+t[3].lastbits(2))

-        p.copy(g[(w[nb]-1)/2])

-

-        for var i=nb-1;i>=0;i--

-        {

-            let m=w[i]>>7

-            let j=(w[i]^m)-m  /* j=abs(w[i]) */

-            let k=Int((j-1)/2)

-            s[0].copy(g[k]); s[1].copy(g[k]); s[1].conj()

-            p.usqr()

-            p.mul(s[Int(m&1)])

-        }

-        p.mul(c)  /* apply correction */

-        p.reduce()

-        return p

-    }

-

-

-

-

-

-}

diff --git a/swift/fp2.swift b/swift/fp2.swift
deleted file mode 100644
index 3682e34..0000000
--- a/swift/fp2.swift
+++ /dev/null
@@ -1,329 +0,0 @@
-/*

-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.

-*/

-//

-//  fp2.swift

-//  

-//

-//  Created by Michael Scott on 07/07/2015.

-//  Copyright (c) 2015 Michael Scott. All rights reserved.

-//

-

-/* Finite Field arithmetic  Fp^2 functions */

-

-/* FP2 elements are of the form a+ib, where i is sqrt(-1) */

-

-

-final class FP2

-{

-    private var a:FP

-    private var b:FP

-

-    /* Constructors */

-    init(_ c: Int32)

-    {

-        a=FP(c)

-        b=FP(0)

-    }

-

-    init(_ x:FP2)

-    {

-        a=FP(x.a)

-        b=FP(x.b)

-    }

-

-    init(_ c:FP,_ d:FP)

-    {

-        a=FP(c)

-        b=FP(d)

-    }

-

-    init(_ c:BIG,_ d:BIG)

-    {

-        a=FP(c)

-        b=FP(d)

-    }

-

-    init(_ c:FP)

-    {

-        a=FP(c)

-        b=FP(0)

-    }

-

-    init(_ c:BIG)

-    {

-        a=FP(c)

-        b=FP(0)

-    }

-

-    /* test this=0 ? */

-    func iszilch() -> Bool

-    {

-        reduce()

-        return (a.iszilch() && b.iszilch())

-    }

-

-    func cmove(g:FP2,_ d:Int32)

-    {

-        a.cmove(g.a,d)

-        b.cmove(g.b,d)

-    }

-

-    /* test this=1 ? */

-    func isunity() -> Bool

-    {

-        let one=FP(1)

-        return (a.equals(one) && b.iszilch())

-    }

-

-    /* test this=x */

-    func equals(x:FP2) -> Bool

-    {

-        return (a.equals(x.a) && b.equals(x.b));

-    }

-

-

-    /* reduce components mod Modulus */

-    func reduce()

-    {

-        a.reduce()

-        b.reduce()

-    }

-

-    /* normalise components of w */

-    func norm()

-    {

-        a.norm()

-        b.norm()

-    }

-

-    /* extract a */

-    func getA() -> BIG

-    {

-        return a.redc()

-    }

-

-    /* extract b */

-    func getB() -> BIG

-    {

-        return b.redc()

-    }

-

-    /* copy self=x */

-    func copy(x:FP2)

-    {

-        a.copy(x.a)

-        b.copy(x.b)

-    }

-

-    /* set self=0 */

-    func zero()

-    {

-        a.zero()

-        b.zero()

-    }

-

-    /* set self=1 */

-    func one()

-    {

-        a.one()

-        b.zero()

-    }

-

-    /* negate self mod Modulus */

-    func neg()

-    {

-        norm();

-        let m=FP(a)

-        let t=FP(0)

-

-        m.add(b)

-        m.neg()

-        m.norm()

-        t.copy(m); t.add(b)

-        b.copy(m)

-        b.add(a)

-        a.copy(t)

-    }

-

-    /* set to a-ib */

-    func conj()

-    {

-        b.neg()

-    }

-

-    /* self+=a */

-    func add(x:FP2)

-    {

-        a.add(x.a)

-        b.add(x.b)

-    }

-

-    /* self-=a */

-    func sub(x:FP2)

-    {

-        let m=FP2(x)

-        m.neg()

-        add(m)

-    }

-

-    /* self*=s, where s is an FP */

-    func pmul(s:FP)

-    {

-        a.mul(s)

-        b.mul(s)

-    }

-

-    /* self*=i, where i is an int */

-    func imul(c:Int32)

-    {

-        a.imul(c);

-        b.imul(c);

-    }

-

-    /* self*=self */

-    func sqr()

-    {

-        norm();

-

-        let w1=FP(a)

-        let w3=FP(a)

-        let mb=FP(b)

-        w3.mul(b)

-        w1.add(b)

-        mb.neg()

-        a.add(mb)

-        a.mul(w1)

-        b.copy(w3); b.add(w3)

-        norm()

-    }

-    /* self*=y */

-    func mul(y:FP2)

-    {

-        norm();  /* This is needed here as {a,b} is not normed before additions */

-

-        let w1=FP(a)

-        let w2=FP(b)

-        let w5=FP(a)

-        let mw=FP(0)

-

-        w1.mul(y.a)  // w1=a*y.a  - this norms w1 and y.a, NOT a

-        w2.mul(y.b)  // w2=b*y.b  - this norms w2 and y.b, NOT b

-        w5.add(b)    // w5=a+b

-        b.copy(y.a); b.add(y.b) // b=y.a+y.b

-

-        b.mul(w5)

-        mw.copy(w1); mw.add(w2); mw.neg()

-

-        b.add(mw); mw.add(w1)

-        a.copy(w1);	a.add(mw)

-

-        norm()

-

-    }

-

-    /* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */

-    /* returns true if this is QR */

-    func sqrt() -> Bool

-    {

-        if iszilch() {return true}

-        var w1=FP(b)

-        var w2=FP(a)

-        w1.sqr(); w2.sqr(); w1.add(w2)

-        if w1.jacobi() != 1 { zero(); return false; }

-        w1=w1.sqrt()

-        w2.copy(a); w2.add(w1); w2.div2()

-        if w2.jacobi() != 1

-        {

-            w2.copy(a); w2.sub(w1); w2.div2()

-            if w2.jacobi() != 1 { zero(); return false }

-        }

-        w2=w2.sqrt()

-        a.copy(w2)

-        w2.add(w2)

-        w2.inverse()

-        b.mul(w2)

-        return true

-    }

-    /* output to hex string */

-    func toString() -> String

-    {

-        return ("["+a.toString()+","+b.toString()+"]")

-    }

-

-    func toRawString() -> String

-    {

-        return ("["+a.toRawString()+","+b.toRawString()+"]")

-    }

-

-    /* self=1/self */

-    func inverse()

-    {

-        norm();

-        let w1=FP(a)

-        let w2=FP(b)

-

-        w1.sqr()

-        w2.sqr()

-        w1.add(w2)

-        w1.inverse()

-        a.mul(w1)

-        w1.neg()

-        b.mul(w1)

-    }

-

-    /* self/=2 */

-    func div2()

-    {

-        a.div2();

-        b.div2();

-    }

-

-    /* self*=sqrt(-1) */

-    func times_i()

-    {

-        let z=FP(a)

-        a.copy(b); a.neg()

-        b.copy(z)

-    }

-

-    /* w*=(1+sqrt(-1)) */

-    /* where X*2-(1+sqrt(-1)) is irreducible for FP4, assumes p=3 mod 8 */

-    func mul_ip()

-    {

-        norm();

-        let t=FP2(self)

-        let z=FP(a)

-        a.copy(b)

-        a.neg()

-        b.copy(z)

-        add(t)

-        norm()

-    }

-    /* w/=(1+sqrt(-1)) */

-    func div_ip()

-    {

-        let t=FP2(0)

-        norm()

-        t.a.copy(a); t.a.add(b)

-        t.b.copy(b); t.b.sub(a)

-        copy(t)

-        div2()

-    }

-

-}

diff --git a/swift/fp4.swift b/swift/fp4.swift
deleted file mode 100644
index d86e59c..0000000
--- a/swift/fp4.swift
+++ /dev/null
@@ -1,513 +0,0 @@
-/*

-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.

-*/

-//

-//  fp4.swift

-//  

-//

-//  Created by Michael Scott on 07/07/2015.

-//  Copyright (c) 2015 Michael Scott. All rights reserved.

-//

-

-/* Finite Field arithmetic  Fp^4 functions */

-

-/* FP4 elements are of the form a+ib, where i is sqrt(-1+sqrt(-1))  */

-

-final class FP4 {

-    private final var a:FP2

-    private final var b:FP2

-

-    /* constructors */

-    init(_ c:Int32)

-    {

-        a=FP2(c)

-        b=FP2(0)

-    }

-

-    init(_ x:FP4)

-    {

-        a=FP2(x.a)

-        b=FP2(x.b)

-    }

-

-    init(_ c:FP2,_ d:FP2)

-    {

-        a=FP2(c)

-        b=FP2(d)

-    }

-

-    init(_ c:FP2)

-    {

-        a=FP2(c)

-        b=FP2(0)

-    }

-    /* reduce all components of this mod Modulus */

-    func reduce()

-    {

-        a.reduce()

-        b.reduce()

-    }

-    /* normalise all components of this mod Modulus */

-    func norm()

-    {

-        a.norm()

-        b.norm()

-    }

-    /* test this==0 ? */

-    func iszilch() -> Bool

-    {

-        reduce()

-        return a.iszilch() && b.iszilch()

-    }

-    /* test this==1 ? */

-    func isunity() -> Bool

-    {

-    let one=FP2(1);

-    return a.equals(one) && b.iszilch()

-    }

-

-    /* test is w real? That is in a+ib test b is zero */

-    func isreal() -> Bool

-    {

-        return b.iszilch();

-    }

-    /* extract real part a */

-    func real() -> FP2

-    {

-        return a;

-    }

-

-    func geta() -> FP2

-    {

-        return a;

-    }

-    /* extract imaginary part b */

-    func getb() -> FP2

-    {

-    return b;

-    }

-    /* test self=x? */

-    func equals(x:FP4) -> Bool

-    {

-        return a.equals(x.a) && b.equals(x.b)

-    }

-    /* copy self=x */

-    func copy(x:FP4)

-    {

-        a.copy(x.a)

-        b.copy(x.b)

-    }

-    /* set this=0 */

-    func zero()

-    {

-        a.zero()

-        b.zero()

-    }

-    /* set this=1 */

-    func one()

-    {

-        a.one()

-        b.zero()

-    }

-    /* set self=-self */

-    func neg()

-    {

-        let m=FP2(a)

-        let t=FP2(0)

-        m.add(b)

-        m.neg()

-        m.norm()

-        t.copy(m); t.add(b)

-        b.copy(m)

-        b.add(a)

-        a.copy(t)

-    }

-    /* self=conjugate(self) */

-    func conj()

-    {

-        b.neg(); b.norm()

-    }

-    /* this=-conjugate(this) */

-    func nconj()

-    {

-        a.neg(); a.norm()

-    }

-    /* self+=x */

-    func add(x:FP4)

-    {

-        a.add(x.a)

-        b.add(x.b)

-    }

-    /* self-=x */

-    func sub(x:FP4)

-    {

-        let m=FP4(x)

-        m.neg()

-        add(m)

-    }

-

-    /* self*=s where s is FP2 */

-    func pmul(s:FP2)

-    {

-        a.mul(s)

-        b.mul(s)

-    }

-    /* self*=c where c is int */

-    func imul(c:Int32)

-    {

-        a.imul(c)

-        b.imul(c)

-    }

-    /* self*=self */

-    func sqr()

-    {

-        norm();

-

-        let t1=FP2(a)

-        let t2=FP2(b)

-        let t3=FP2(a)

-

-        t3.mul(b)

-        t1.add(b)

-        t2.mul_ip()

-

-        t2.add(a)

-        a.copy(t1)

-

-        a.mul(t2)

-

-        t2.copy(t3)

-        t2.mul_ip()

-        t2.add(t3)

-        t2.neg()

-        a.add(t2)

-

-        b.copy(t3)

-        b.add(t3)

-

-        norm()

-    }

-    /* self*=y */

-    func mul(y:FP4)

-    {

-        norm();

-

-        let t1=FP2(a)

-        let t2=FP2(b)

-        let t3=FP2(0)

-        let t4=FP2(b)

-

-        t1.mul(y.a)

-        t2.mul(y.b)

-        t3.copy(y.b)

-        t3.add(y.a)

-        t4.add(a)

-

-        t4.mul(t3)

-        t4.sub(t1)

-        t4.norm()

-

-        b.copy(t4)

-        b.sub(t2)

-        t2.mul_ip()

-        a.copy(t2)

-        a.add(t1)

-

-        norm()

-    }

-    /* convert this to hex string */

-    func toString() -> String

-    {

-        return ("["+a.toString()+","+b.toString()+"]")

-    }

-

-    func toRawString() -> String

-    {

-        return ("["+a.toRawString()+","+b.toRawString()+"]")

-    }

-    /* self=1/self */

-    func inverse()

-    {

-        norm();

-

-        let t1=FP2(a)

-        let t2=FP2(b)

-

-        t1.sqr()

-        t2.sqr()

-        t2.mul_ip()

-        t1.sub(t2)

-        t1.inverse()

-        a.mul(t1)

-        t1.neg()

-        b.mul(t1)

-    }

-

-    /* self*=i where i = sqrt(-1+sqrt(-1)) */

-    func times_i()

-    {

-        norm();

-        let s=FP2(b)

-        let t=FP2(b)

-        s.times_i()

-        t.add(s)

-        t.norm()

-        b.copy(a)

-        a.copy(t)

-    }

-

-    /* self=self^p using Frobenius */

-    func frob(f:FP2)

-    {

-        a.conj()

-        b.conj()

-        b.mul(f)

-    }

-    /* self=self^e */

-    func pow(e:BIG) -> FP4

-    {

-        norm()

-        e.norm()

-        let w=FP4(self)

-        let z=BIG(e)

-        let r=FP4(1)

-        while (true)

-        {

-            let bt=z.parity()

-            z.fshr(1)

-            if bt==1 {r.mul(w)}

-            if z.iszilch() {break}

-            w.sqr()

-        }

-        r.reduce()

-        return r

-    }

-    /* XTR xtr_a function */

-    func xtr_A(w:FP4,_ y:FP4,_ z:FP4)

-    {

-        let r=FP4(w)

-        let t=FP4(w)

-        r.sub(y)

-        r.pmul(a)

-        t.add(y)

-        t.pmul(b)

-        t.times_i()

-

-        copy(r)

-        add(t)

-        add(z)

-

-        norm()

-    }

-    /* XTR xtr_d function */

-    func xtr_D()

-    {

-        let w=FP4(self)

-        sqr(); w.conj()

-        w.add(w)

-        sub(w)

-        reduce()

-    }

-    /* r=x^n using XTR method on traces of FP12s */

-    func xtr_pow(n:BIG) -> FP4

-    {

-        let a=FP4(3)

-        let b=FP4(self)

-        let c=FP4(b)

-        c.xtr_D()

-        let t=FP4(0)

-        let r=FP4(0)

-

-        n.norm();

-        let par=n.parity()

-        let v=BIG(n); v.fshr(1)

-        if par==0 {v.dec(1); v.norm()}

-

-        let nb=v.nbits()

-        for var i=nb-1;i>=0;i--

-        {

-            if (v.bit(i) != 1)

-            {

-				t.copy(b)

-				conj()

-				c.conj()

-				b.xtr_A(a,self,c)

-				conj()

-				c.copy(t)

-				c.xtr_D()

-				a.xtr_D()

-            }

-            else

-            {

-				t.copy(a); t.conj()

-				a.copy(b)

-				a.xtr_D()

-				b.xtr_A(c,self,t)

-				c.xtr_D()

-            }

-        }

-        if par==0 {r.copy(c)}

-        else {r.copy(b)}

-        r.reduce()

-        return r

-    }

-

-    /* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */

-    func xtr_pow2(ck:FP4,_ ckml:FP4,_ ckm2l:FP4,_ a:BIG,_ b:BIG) -> FP4

-    {

-        a.norm(); b.norm()

-        let e=BIG(a)

-        let d=BIG(b)

-        let w=BIG(0)

-

-        let cu=FP4(ck)  // can probably be passed in w/o copying

-        let cv=FP4(self)

-        let cumv=FP4(ckml)

-        let cum2v=FP4(ckm2l)

-        var r=FP4(0)

-        let t=FP4(0)

-

-        var f2:Int=0

-        while d.parity()==0 && e.parity()==0

-        {

-            d.fshr(1);

-            e.fshr(1);

-            f2++;

-        }

-

-        while (BIG.comp(d,e) != 0)

-        {

-            if BIG.comp(d,e)>0

-            {

-				w.copy(e); w.imul(4); w.norm()

-				if BIG.comp(d,w)<=0

-				{

-                    w.copy(d); d.copy(e)

-                    e.rsub(w); e.norm()

-

-                    t.copy(cv)

-                    t.xtr_A(cu,cumv,cum2v)

-                    cum2v.copy(cumv)

-                    cum2v.conj()

-                    cumv.copy(cv)

-                    cv.copy(cu)

-                    cu.copy(t)

-

-				}

-				else if d.parity()==0

-				{

-                    d.fshr(1)

-                    r.copy(cum2v); r.conj()

-                    t.copy(cumv)

-                    t.xtr_A(cu,cv,r)

-                    cum2v.copy(cumv)

-                    cum2v.xtr_D()

-                    cumv.copy(t)

-                    cu.xtr_D()

-				}

-				else if e.parity()==1

-				{

-                    d.sub(e); d.norm()

-                    d.fshr(1)

-                    t.copy(cv)

-                    t.xtr_A(cu,cumv,cum2v)

-                    cu.xtr_D()

-                    cum2v.copy(cv)

-                    cum2v.xtr_D()

-                    cum2v.conj()

-                    cv.copy(t)

-				}

-				else

-				{

-                    w.copy(d)

-                    d.copy(e); d.fshr(1)

-                    e.copy(w)

-                    t.copy(cumv)

-                    t.xtr_D()

-                    cumv.copy(cum2v); cumv.conj()

-                    cum2v.copy(t); cum2v.conj()

-                    t.copy(cv)

-                    t.xtr_D()

-                    cv.copy(cu)

-                    cu.copy(t)

-				}

-            }

-            if BIG.comp(d,e)<0

-            {

-				w.copy(d); w.imul(4); w.norm()

-				if BIG.comp(e,w)<=0

-				{

-                    e.sub(d); e.norm()

-                    t.copy(cv)

-                    t.xtr_A(cu,cumv,cum2v)

-                    cum2v.copy(cumv)

-                    cumv.copy(cu)

-                    cu.copy(t)

-				}

-				else if e.parity()==0

-				{

-                    w.copy(d)

-                    d.copy(e); d.fshr(1)

-                    e.copy(w)

-                    t.copy(cumv)

-                    t.xtr_D()

-                    cumv.copy(cum2v); cumv.conj()

-                    cum2v.copy(t); cum2v.conj()

-                    t.copy(cv)

-                    t.xtr_D()

-                    cv.copy(cu)

-                    cu.copy(t)

-				}

-				else if d.parity()==1

-				{

-                    w.copy(e)

-                    e.copy(d)

-                    w.sub(d); w.norm()

-                    d.copy(w); d.fshr(1)

-                    t.copy(cv)

-                    t.xtr_A(cu,cumv,cum2v)

-                    cumv.conj()

-                    cum2v.copy(cu)

-                    cum2v.xtr_D()

-                    cum2v.conj()

-                    cu.copy(cv)

-                    cu.xtr_D()

-                    cv.copy(t)

-				}

-				else

-				{

-                    d.fshr(1)

-                    r.copy(cum2v); r.conj()

-                    t.copy(cumv)

-                    t.xtr_A(cu,cv,r)

-                    cum2v.copy(cumv)

-                    cum2v.xtr_D()

-                    cumv.copy(t)

-                    cu.xtr_D()

-				}

-            }

-        }

-        r.copy(cv)

-        r.xtr_A(cu,cumv,cum2v)

-        for var i=0;i<f2;i++

-            {r.xtr_D()}

-        r=r.xtr_pow(d)

-        return r

-    }

-

-}

diff --git a/swift/gcm.swift b/swift/gcm.swift
deleted file mode 100644
index 85ee8fd..0000000
--- a/swift/gcm.swift
+++ /dev/null
@@ -1,314 +0,0 @@
-/*

-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.

-*/

-//

-//  gcm.swift

-//  

-//

-//  Created by Michael Scott on 23/06/2015.

-//  Copyright (c) 2015 Michael Scott. All rights reserved.

-//

-

-import Foundation

-

-/*

-* Implementation of the AES-GCM Encryption/Authentication

-*

-* Some restrictions..

-* 1. Only for use with AES

-* 2. Returned tag is always 128-bits. Truncate at your own risk.

-* 3. The order of function calls must follow some rules

-*

-* Typical sequence of calls..

-* 1. call GCM_init

-* 2. call GCM_add_header any number of times, as long as length of header is multiple of 16 bytes (block size)

-* 3. call GCM_add_header one last time with any length of header

-* 4. call GCM_add_cipher any number of times, as long as length of cipher/plaintext is multiple of 16 bytes

-* 5. call GCM_add_cipher one last time with any length of cipher/plaintext

-* 6. call GCM_finish to extract the tag.

-*

-* See http://www.mindspring.com/~dmcgrew/gcm-nist-6.pdf

-*/

-

-final class GCM {

-    static let NB:Int=4

-    static let GCM_ACCEPTING_HEADER:Int=0

-    static let GCM_ACCEPTING_CIPHER:Int=1

-    static let GCM_NOT_ACCEPTING_MORE:Int=2

-    static let GCM_FINISHED:Int=3

-    static let GCM_ENCRYPTING:Int=0

-    static let GCM_DECRYPTING:Int=1

-

-    private var table=[[UInt32]](count:128,repeatedValue:[UInt32](count:4,repeatedValue:0)) /* 2k bytes */

-    private var stateX=[UInt8](count:16,repeatedValue:0)

-    private var Y_0=[UInt8](count:16,repeatedValue:0)

-

-    private var counter:Int=0

-    private var lenA=[UInt32](count:2,repeatedValue:0)

-    private var lenC=[UInt32](count:2,repeatedValue:0)

-    private var status:Int=0

-    private var a=AES()

-

-    private static func pack(b: [UInt8]) -> UInt32

-    { /* pack bytes into a 32-bit Word */

-        var r=((UInt32(b[0])&0xff)<<24)|((UInt32(b[1])&0xff)<<16)

-        r = r|((UInt32(b[2])&0xff)<<8)|(UInt32(b[3])&0xff)

-        return r

-    }

-

-    private static func unpack(a: UInt32) -> [UInt8]

-    { /* unpack bytes from a word */

-        let b:[UInt8]=[UInt8((a>>24)&0xff),UInt8((a>>16)&0xff),UInt8((a>>8)&0xff),UInt8(a&0xff)];

-        return b

-    }

-

-    private func precompute(H: [UInt8])

-    {

-        var b=[UInt8](count:4,repeatedValue:0)

-        var j=0

-        for var i=0;i<GCM.NB;i++

-        {

-            b[0]=H[j]; b[1]=H[j+1]; b[2]=H[j+2]; b[3]=H[j+3];

-            table[0][i]=GCM.pack(b);

-            j+=4

-        }

-        for var i=1;i<128;i++

-        {

-            var c:UInt32=0

-            for var j=0;j<GCM.NB;j++ {table[i][j]=c|(table[i-1][j])>>1; c=table[i-1][j]<<31;}

-            if c != 0  {table[i][0]^=0xE1000000} /* irreducible polynomial */

-        }

-    }

-

-    private func gf2mul()

-    { /* gf2m mul - Z=H*X mod 2^128 */

-        var P=[UInt32](count:4,repeatedValue:0)

-

-        for var i=0;i<4;i++ {P[i]=0}

-        var j=8; var m=0;

-        for var i=0;i<128;i++

-        {

-            let c=(stateX[m]>>UInt8(--j))&1;

-            if c != 0 {for var k=0;k<GCM.NB;k++ {P[k]^=table[i][k]}}

-            if (j==0)

-            {

-				j=8; m++;

-                if (m==16) {break}

-            }

-        }

-        j=0

-        for var i=0;i<GCM.NB;i++

-        {

-            var b=GCM.unpack(P[i])

-            stateX[j]=b[0]; stateX[j+1]=b[1]; stateX[j+2]=b[2]; stateX[j+3]=b[3];

-            j+=4

-        }

-    }

-    private func wrap()

-    { /* Finish off GHASH */

-        var F=[UInt32](count:4,repeatedValue:0)

-        var L=[UInt8](count:16,repeatedValue:0)

-

-    /* convert lengths from bytes to bits */

-        F[0]=(lenA[0]<<3)|(lenA[1]&0xE0000000)>>29

-        F[1]=lenA[1]<<3;

-        F[2]=(lenC[0]<<3)|(lenC[1]&0xE0000000)>>29

-        F[3]=lenC[1]<<3;

-        var j=0

-        for var i=0;i<GCM.NB;i++

-        {

-            var b=GCM.unpack(F[i]);

-            L[j]=b[0]; L[j+1]=b[1]; L[j+2]=b[2]; L[j+3]=b[3]

-            j+=4

-        }

-        for var i=0;i<16;i++ {stateX[i]^=L[i]}

-        gf2mul()

-    }

-

-    private func ghash(plain: [UInt8],_ len: Int) -> Bool

-    {

-    //    var B=[UInt8](count:16,repeatedValue:0)

-

-        if status==GCM.GCM_ACCEPTING_HEADER {status=GCM.GCM_ACCEPTING_CIPHER}

-        if (status != GCM.GCM_ACCEPTING_CIPHER) {return false}

-

-        var j=0;

-        while (j<len)

-        {

-            for var i=0;i<16 && j<len;i++

-            {

-				stateX[i]^=plain[j++];

-                lenC[1]++; if lenC[1]==0 {lenC[0]++}

-            }

-            gf2mul();

-        }

-        if len%16 != 0 {status=GCM.GCM_NOT_ACCEPTING_MORE}

-        return true;

-    }

-

-    /* Initialize GCM mode */

-    func init_it(key: [UInt8],_ niv: Int,_ iv: [UInt8])

-    { /* iv size niv is usually 12 bytes (96 bits). AES key size nk can be 16,24 or 32 bytes */

-        var H=[UInt8](count:16,repeatedValue:0)

-

-        for var i=0;i<16;i++ {H[i]=0; stateX[i]=0}

-

-        a.init_it(AES.ECB,key,iv)

-        a.ecb_encrypt(&H);    /* E(K,0) */

-        precompute(H)

-

-        lenA[0]=0;lenC[0]=0;lenA[1]=0;lenC[1]=0;

-        if (niv==12)

-        {

-            for var i=0;i<12;i++ {a.f[i]=iv[i]}

-            var b=GCM.unpack(UInt32(1))

-            a.f[12]=b[0]; a.f[13]=b[1]; a.f[14]=b[2]; a.f[15]=b[3];  /* initialise IV */

-            for var i=0;i<16;i++ {Y_0[i]=a.f[i]}

-        }

-        else

-        {

-            status=GCM.GCM_ACCEPTING_CIPHER;

-            ghash(iv,niv) /* GHASH(H,0,IV) */

-            wrap()

-            for var i=0;i<16;i++ {a.f[i]=stateX[i];Y_0[i]=a.f[i];stateX[i]=0}

-            lenA[0]=0;lenC[0]=0;lenA[1]=0;lenC[1]=0;

-        }

-        status=GCM.GCM_ACCEPTING_HEADER;

-    }

-

-    /* Add Header data - included but not encrypted */

-    func add_header(header: [UInt8],_ len: Int) -> Bool

-    { /* Add some header. Won't be encrypted, but will be authenticated. len is length of header */

-        if status != GCM.GCM_ACCEPTING_HEADER {return false}

-

-        var j=0

-        while (j<len)

-        {

-            for var i=0;i<16 && j<len;i++

-            {

-				stateX[i]^=header[j++];

-                lenA[1]++; if lenA[1]==0 {lenA[0]++}

-            }

-            gf2mul();

-        }

-        if len%16 != 0 {status=GCM.GCM_ACCEPTING_CIPHER}

-        return true;

-    }

-    /* Add Plaintext - included and encrypted */

-    func add_plain(plain: [UInt8],_ len: Int) -> [UInt8]

-    {

-        var B=[UInt8](count:16,repeatedValue:0)

-        var b=[UInt8](count:4,repeatedValue:0)

-

-        var cipher=[UInt8](count:len,repeatedValue:0)

-        var counter:UInt32=0

-        if status == GCM.GCM_ACCEPTING_HEADER {status=GCM.GCM_ACCEPTING_CIPHER}

-        if status != GCM.GCM_ACCEPTING_CIPHER {return [UInt8]()}

-

-        var j=0

-        while (j<len)

-        {

-

-            b[0]=a.f[12]; b[1]=a.f[13]; b[2]=a.f[14]; b[3]=a.f[15];

-            counter=GCM.pack(b);

-            counter++;

-            b=GCM.unpack(counter);

-            a.f[12]=b[0]; a.f[13]=b[1]; a.f[14]=b[2]; a.f[15]=b[3]; /* increment counter */

-            for var i=0;i<16;i++ {B[i]=a.f[i]}

-            a.ecb_encrypt(&B);        /* encrypt it  */

-

-            for var i=0;i<16 && j<len;i++

-            {

-				cipher[j]=(plain[j]^B[i]);

-				stateX[i]^=cipher[j++];

-                lenC[1]++; if lenC[1]==0 {lenC[0]++}

-            }

-            gf2mul();

-        }

-        if len%16 != 0 {status=GCM.GCM_NOT_ACCEPTING_MORE}

-        return cipher;

-    }

-    /* Add Ciphertext - decrypts to plaintext */

-    func add_cipher(cipher: [UInt8],_ len: Int) -> [UInt8]

-    {

-        var B=[UInt8](count:16,repeatedValue:0)

-        var b=[UInt8](count:4,repeatedValue:0)

-

-        var plain=[UInt8](count:len,repeatedValue:0)

-        var counter:UInt32=0

-

-        if status==GCM.GCM_ACCEPTING_HEADER {status=GCM.GCM_ACCEPTING_CIPHER}

-        if status != GCM.GCM_ACCEPTING_CIPHER {return [UInt8]()}

-

-        var j=0

-        while (j<len)

-        {

-

-            b[0]=a.f[12]; b[1]=a.f[13]; b[2]=a.f[14]; b[3]=a.f[15];

-            counter=GCM.pack(b);

-            counter++;

-            b=GCM.unpack(counter);

-            a.f[12]=b[0]; a.f[13]=b[1]; a.f[14]=b[2]; a.f[15]=b[3]; /* increment counter */

-            for var i=0;i<16;i++ {B[i]=a.f[i]}

-            a.ecb_encrypt(&B);        /* encrypt it  */

-            for var i=0;i<16 && j<len;i++

-            {

-				plain[j]=(cipher[j]^B[i]);

-				stateX[i]^=cipher[j++];

-                lenC[1]++; if lenC[1]==0 {lenC[0]++}

-            }

-            gf2mul()

-        }

-        if len%16 != 0 {status=GCM.GCM_NOT_ACCEPTING_MORE}

-        return plain;

-    }

-

-    /* Finish and extract Tag */

-    func finish(extract: Bool) -> [UInt8]

-    { /* Finish off GHASH and extract tag (MAC) */

-        var tag=[UInt8](count:16,repeatedValue:0)

-

-        wrap();

-        /* extract tag */

-        if (extract)

-        {

-            a.ecb_encrypt(&Y_0);        /* E(K,Y0) */

-            for var i=0;i<16;i++ {Y_0[i]^=stateX[i]}

-            for var i=0;i<16;i++ {tag[i]=Y_0[i];Y_0[i]=0;stateX[i]=0;}

-        }

-        status=GCM.GCM_FINISHED;

-        a.end();

-        return tag;

-    }

-

-    static func hex2bytes(s: String) -> [UInt8]

-    {

-        var array=Array(arrayLiteral: s)

-        let len=array.count;

-        var data=[UInt8](count:len/2,repeatedValue:0)

-

-        for var i=0;i<len;i+=2

-        {

-            data[i / 2] = UInt8(strtoul(String(array[i]),nil,16)<<4)+UInt8(strtoul(String(array[i+1]),nil,16))

-        }

-        return data;

-    }

-

-

-}

-

diff --git a/swift/hash.swift b/swift/hash.swift
deleted file mode 100644
index 1768971..0000000
--- a/swift/hash.swift
+++ /dev/null
@@ -1,188 +0,0 @@
-/*

-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.

-*/

-//

-//  hash.swift

-//  

-//

-//  Created by Michael Scott on 17/06/2015.

-//  Copyright (c) 2015 Michael Scott. All rights reserved.

-//  SHA256 Implementation

-//

-

-final class HASH{

-

-    private var length=[UInt32](count:2,repeatedValue:0)

-    private var h=[UInt32](count:8,repeatedValue:0)

-    private var w=[UInt32](count:64,repeatedValue:0)

-    static let H0:UInt32=0x6A09E667

-    static let H1:UInt32=0xBB67AE85

-    static let H2:UInt32=0x3C6EF372

-    static let H3:UInt32=0xA54FF53A

-    static let H4:UInt32=0x510E527F

-    static let H5:UInt32=0x9B05688C

-    static let H6:UInt32=0x1F83D9AB

-    static let H7:UInt32=0x5BE0CD19

-

-    static let len:Int=32

-

-    static let K:[UInt32]=[

-    0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,

-    0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,

-    0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,

-    0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,

-    0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,

-    0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070,

-    0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,

-    0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2]

-

-

-    private static func S(n: UInt32,_ x: UInt32) -> UInt32

-    {

-        return ((x>>n)|(x<<(32-n)))

-    }

-

-    private static func R(n: UInt32,_ x: UInt32) -> UInt32

-    {

-        return (x>>n)

-    }

-

-    private static func Ch(x: UInt32,_ y: UInt32,_ z:UInt32) -> UInt32

-    {

-        return ((x&y)^(~(x)&z))

-    }

-

-    private static func Maj(x: UInt32,_ y: UInt32,_ z:UInt32) -> UInt32

-    {

-        return ((x&y)^(x&z)^(y&z))

-    }

-

-    private static func Sig0(x: UInt32) -> UInt32

-    {

-        return (S(2,x)^S(13,x)^S(22,x))

-    }

-

-    private static func Sig1(x: UInt32) -> UInt32

-    {

-        return (S(6,x)^S(11,x)^S(25,x))

-    }

-

-    private static func theta0(x: UInt32) -> UInt32

-    {

-        return (S(7,x)^S(18,x)^R(3,x))

-    }

-

-    private static func theta1(x: UInt32) -> UInt32

-    {

-        return (S(17,x)^S(19,x)^R(10,x))

-    }

-

-    private func transform()

-    { /* basic transformation step */

-        var a,b,c,d,e,f,g,hh,t1,t2 :UInt32

-        var j:Int

-        for j=16;j<64;j++

-        {

-            w[j]=HASH.theta1(w[j-2])&+w[j-7]&+HASH.theta0(w[j-15])&+w[j-16]

-        }

-        a=h[0]; b=h[1]; c=h[2]; d=h[3]

-        e=h[4]; f=h[5]; g=h[6]; hh=h[7]

-

-        for j=0;j<64;j++

-        { /* 64 times - mush it up */

-            t1=hh&+HASH.Sig1(e)&+HASH.Ch(e,f,g)&+HASH.K[j]&+w[j]

-            t2=HASH.Sig0(a)&+HASH.Maj(a,b,c)

-            hh=g; g=f; f=e;

-            e=d&+t1;

-            d=c;

-            c=b;

-            b=a;

-            a=t1&+t2;

-        }

-        h[0]=h[0]&+a; h[1]=h[1]&+b; h[2]=h[2]&+c; h[3]=h[3]&+d

-        h[4]=h[4]&+e; h[5]=h[5]&+f; h[6]=h[6]&+g; h[7]=h[7]&+hh;

-    }

-

-    /* Re-Initialise Hash function */

-    func init_it()

-    { /* initialise */

-        for var i=0;i<64;i++ {w[i]=0}

-        length[0]=0; length[1]=0

-        h[0]=HASH.H0;

-        h[1]=HASH.H1;

-        h[2]=HASH.H2;

-        h[3]=HASH.H3;

-        h[4]=HASH.H4;

-        h[5]=HASH.H5;

-        h[6]=HASH.H6;

-        h[7]=HASH.H7;

-    }

-

-    init()

-    {

-        init_it()

-    }

-

-    /* process a single byte */

-    func process(byt: UInt8)

-    { /* process the next message byte */

-        let cnt=Int((length[0]/32)%16)

-        w[cnt]<<=8;

-        w[cnt]|=(UInt32(byt)&0xFF);

-        length[0]+=8;

-        if (length[0]==0) { length[1]++; length[0]=0 }

-        if ((length[0]%512)==0) {transform()}

-    }

-

-    /* process an array of bytes */

-    func process_array(b: [UInt8])

-    {

-        for var i=0;i<b.count;i++ {process((b[i]))}

-    }

-

-    /* process a 32-bit integer */

-    func process_num(n:Int32)

-    {

-        process(UInt8((n>>24)&0xff))

-        process(UInt8((n>>16)&0xff))

-        process(UInt8((n>>8)&0xff))

-        process(UInt8(n&0xff))

-    }

-

-    /* Generate 32-byte Hash */

-    func hash() -> [UInt8]

-    { /* pad message and finish - supply digest */

-        var digest=[UInt8](count:32,repeatedValue:0)

-

-        let len0=length[0]

-        let len1=length[1]

-        process(0x80);

-        while ((length[0]%512) != 448) {process(0)}

-        w[14]=UInt32(len1)

-        w[15]=len0;

-        transform()

-        for var i=0;i<HASH.len;i++

-        { /* convert to bytes */

-            digest[i]=UInt8((h[i/4]>>(8*(3-UInt32(i)%4))) & 0xff);

-        }

-        init_it();

-    return digest;

-    }

-

-

-}

diff --git a/swift/main.swift b/swift/main.swift
deleted file mode 100644
index a9bf70a..0000000
--- a/swift/main.swift
+++ /dev/null
@@ -1,30 +0,0 @@
-/*

-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.

-*/

-//

-//  main.swift

-//  

-//

-//  Created by Michael Scott on 12/06/2015.

-//  Copyright (c) 2015 Michael Scott. All rights reserved.

-//

-

-TestRSA()

-TestECDH()

-TestMPIN()

-

diff --git a/swift/mpin.swift b/swift/mpin.swift
deleted file mode 100644
index 66c876e..0000000
--- a/swift/mpin.swift
+++ /dev/null
@@ -1,728 +0,0 @@
-/*

-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.

-*/

-//

-//  mpin.swift

-//  

-//

-//  Created by Michael Scott on 08/07/2015.

-//  Copyright (c) 2015 Michael Scott. All rights reserved.

-//

-

-import Foundation

-

-final public class MPIN

-{

-    static public let EFS=Int(ROM.MODBYTES)

-    static public let EGS=Int(ROM.MODBYTES)

-    static public let PAS:Int=16

-    static let INVALID_POINT:Int = -14

-    static let BAD_PARAMS:Int = -11

-    static let WRONG_ORDER:Int = -18

-    static public let BAD_PIN:Int = -19

-

-    /* Configure your PIN here */

-

-    static let MAXPIN:Int32 = 10000  /* PIN less than this */

-    static let PBLEN:Int32 = 14      /* Number of bits in PIN */

-    static let TS:Int = 10         /* 10 for 4 digit PIN, 14 for 6-digit PIN - 2^TS/TS approx = sqrt(MAXPIN) */

-    static let TRAP:Int = 200      /* 200 for 4 digit PIN, 2000 for 6-digit PIN  - approx 2*sqrt(MAXPIN) */

-

-    /* Hash number (optional) and string to point on curve */

-

-    private static func hashit(n:Int32,_ ID:[UInt8]) -> [UInt8]

-    {

-        let H=HASH()

-        if n != 0 {H.process_num(n)}

-        H.process_array(ID)

-        let h=H.hash()

-        return h

-    }

-

-    static func mapit(h:[UInt8]) -> ECP

-    {

-        let q=BIG(ROM.Modulus)

-        let x=BIG.fromBytes(h)

-        x.mod(q)

-        var P=ECP(x,0)

-        while (true)

-        {

-            if !P.is_infinity() {break}

-            x.inc(1); x.norm();

-            P=ECP(x,0);

-        }

-        return P

-    }

-

-    /* needed for SOK */

-    static func mapit2(h:[UInt8]) -> ECP2

-    {

-        let q=BIG(ROM.Modulus)

-        var x=BIG.fromBytes(h)

-        let one=BIG(1)

-        var Q=ECP2()

-        x.mod(q);

-        while (true)

-        {

-            let X=FP2(one,x);

-            Q=ECP2(X);

-            if !Q.is_infinity() {break}

-            x.inc(1); x.norm();

-        }

-    /* Fast Hashing to G2 - Fuentes-Castaneda, Knapp and Rodriguez-Henriquez */

-        let Fra=BIG(ROM.CURVE_Fra);

-        let Frb=BIG(ROM.CURVE_Frb);

-        let X=FP2(Fra,Frb);

-        x=BIG(ROM.CURVE_Bnx);

-

-        let T=ECP2(); T.copy(Q)

-        T.mul(x); T.neg()

-        let K=ECP2(); K.copy(T)

-        K.dbl(); K.add(T); K.affine()

-

-        K.frob(X)

-        Q.frob(X); Q.frob(X); Q.frob(X)

-        Q.add(T); Q.add(K)

-        T.frob(X); T.frob(X)

-        Q.add(T)

-        Q.affine()

-        return Q

-    }

-

-    /* return time in slots since epoch */

-    static public func today() -> Int32

-    {

-        let date=NSDate()

-        return (Int32(date.timeIntervalSince1970/(60*1440)))

-    }

-

-    /* these next two functions help to implement elligator squared - http://eprint.iacr.org/2014/043 */

-    /* maps a random u to a point on the curve */

-    static func map(u:BIG,_ cb:Int32) -> ECP

-    {

-        let x=BIG(u)

-        let p=BIG(ROM.Modulus)

-        x.mod(p)

-        var P=ECP(x,cb)

-        while (true)

-        {

-            if !P.is_infinity() {break}

-            x.inc(1);  x.norm()

-            P=ECP(x,cb)

-        }

-        return P

-    }

-

-    /* returns u derived from P. Random value in range 1 to return value should then be added to u */

-    static func unmap(inout u:BIG,_ P:ECP) -> Int32

-    {

-        let s=P.getS()

-        var r:Int32=0

-        let x=P.getX()

-        u.copy(x)

-        var R=ECP()

-        while (true)

-        {

-            u.dec(1); u.norm()

-            r++

-            R=ECP(u,s)

-            if !R.is_infinity() {break}

-        }

-        return r

-    }

-

-    static public func HASH_ID(ID:[UInt8]) -> [UInt8]

-    {

-        return hashit(0,ID)

-    }

-

-    /* these next two functions implement elligator squared - http://eprint.iacr.org/2014/043 */

-    /* Elliptic curve point E in format (0x04,x,y} is converted to form {0x0-,u,v} */

-    /* Note that u and v are indistinguisible from random strings */

-    static public func ENCODING(rng:RAND,inout _ E:[UInt8]) -> Int

-    {

-        var T=[UInt8](count:EFS,repeatedValue:0)

-

-        for var i=0;i<EFS;i++ {T[i]=E[i+1]}

-        var u=BIG.fromBytes(T);

-        for var i=0;i<EFS;i++ {T[i]=E[i+EFS+1]}

-        var v=BIG.fromBytes(T)

-

-        let P=ECP(u,v);

-        if P.is_infinity() {return INVALID_POINT}

-

-        let p=BIG(ROM.Modulus)

-        u=BIG.randomnum(p,rng)

-

-        var su=rng.getByte();

-        su%=2

-

-        let W=MPIN.map(u,Int32(su))

-        P.sub(W);

-        let sv=P.getS();

-        let rn=MPIN.unmap(&v,P)

-        let m=rng.getByte();

-        let incr:Int32=1+Int32(m)%rn

-        v.inc(incr)

-        E[0]=(su+UInt8(2*sv))

-        u.toBytes(&T)

-        for var i=0;i<EFS;i++ {E[i+1]=T[i]}

-        v.toBytes(&T)

-        for var i=0;i<EFS;i++ {E[i+EFS+1]=T[i]}

-

-        return 0;

-    }

-

-    static public func DECODING(inout D:[UInt8]) -> Int

-    {

-        var T=[UInt8](count:EFS,repeatedValue:0)

-

-        if (D[0]&0x04) != 0 {return INVALID_POINT}

-

-        for var i=0;i<EFS;i++ {T[i]=D[i+1]}

-        var u=BIG.fromBytes(T)

-        for var i=0;i<EFS;i++ {T[i]=D[i+EFS+1]}

-        var v=BIG.fromBytes(T)

-

-        let su=D[0]&1

-        let sv=(D[0]>>1)&1

-        let W=map(u,Int32(su))

-        let P=map(v,Int32(sv))

-        P.add(W)

-        u=P.getX()

-        v=P.getY()

-        D[0]=0x04

-        u.toBytes(&T);

-        for var i=0;i<EFS;i++ {D[i+1]=T[i]}

-        v.toBytes(&T)

-        for var i=0;i<EFS;i++ {D[i+EFS+1]=T[i]}

-

-        return 0

-    }

-    /* R=R1+R2 in group G1 */

-    static public func RECOMBINE_G1(R1:[UInt8],_ R2:[UInt8],inout _ R:[UInt8]) -> Int

-    {

-        let P=ECP.fromBytes(R1)

-        let Q=ECP.fromBytes(R2)

-

-        if P.is_infinity() || Q.is_infinity() {return INVALID_POINT}

-

-        P.add(Q)

-

-        P.toBytes(&R)

-        return 0;

-    }

-    /* W=W1+W2 in group G2 */

-    static public func RECOMBINE_G2(W1:[UInt8],_ W2:[UInt8],inout _  W:[UInt8]) -> Int

-    {

-        let P=ECP2.fromBytes(W1)

-        let Q=ECP2.fromBytes(W2)

-

-        if P.is_infinity() || Q.is_infinity() {return INVALID_POINT}

-

-        P.add(Q)

-

-        P.toBytes(&W)

-        return 0

-    }

-    /* create random secret S */

-    static public func RANDOM_GENERATE(rng:RAND,inout _ S:[UInt8]) -> Int

-    {

-        let r=BIG(ROM.CURVE_Order)

-        let s=BIG.randomnum(r,rng)

-

-        s.toBytes(&S);

-        return 0;

-    }

-    /* Extract PIN from TOKEN for identity CID */

-    static public func EXTRACT_PIN(CID:[UInt8],_ pin:Int32,inout _ TOKEN:[UInt8]) -> Int

-    {

-        let P=ECP.fromBytes(TOKEN)

-        if P.is_infinity() {return INVALID_POINT}

-        let h=MPIN.hashit(0,CID)

-        var R=MPIN.mapit(h)

-

-

-        R=R.pinmul(pin%MAXPIN,MPIN.PBLEN)

-        P.sub(R)

-

-        P.toBytes(&TOKEN)

-

-        return 0

-    }

-    /* Implement step 2 on client side of MPin protocol */

-    static public func CLIENT_2(X:[UInt8],_ Y:[UInt8],inout _ SEC:[UInt8]) -> Int

-    {

-        let r=BIG(ROM.CURVE_Order)

-        let P=ECP.fromBytes(SEC)

-        if P.is_infinity() {return INVALID_POINT}

-

-        let px=BIG.fromBytes(X)

-        let py=BIG.fromBytes(Y)

-        px.add(py)

-        px.mod(r)

-        px.rsub(r)

-

-        PAIR.G1mul(P,px).toBytes(&SEC)

-        return 0

-    }

-

-    /* Implement step 1 on client side of MPin protocol */

-    static public func CLIENT_1(date:Int32,_ CLIENT_ID:[UInt8],_ rng:RAND?,inout _ X:[UInt8],_ pin:Int32,_ TOKEN:[UInt8],inout _ SEC:[UInt8],inout _ xID:[UInt8]?,inout _ xCID:[UInt8]?,_ PERMIT:[UInt8]) -> Int

-    {

-        let r=BIG(ROM.CURVE_Order)

-   //     let q=BIG(ROM.Modulus)

-        var x:BIG

-        if rng != nil

-        {

-            x=BIG.randomnum(r,rng!)

-            x.toBytes(&X);

-        }

-        else

-        {

-            x=BIG.fromBytes(X);

-        }

-    //    var t=[UInt8](count:EFS,repeatedValue:0)

-

-        var h=MPIN.hashit(0,CLIENT_ID)

-        var P=mapit(h);

-

-        let T=ECP.fromBytes(TOKEN);

-        if T.is_infinity() {return INVALID_POINT}

-

-        var W=P.pinmul(pin%MPIN.MAXPIN,MPIN.PBLEN)

-        T.add(W)

-        if date != 0

-        {

-            W=ECP.fromBytes(PERMIT)

-            if W.is_infinity() {return INVALID_POINT}

-            T.add(W);

-            h=MPIN.hashit(date,h)

-            W=MPIN.mapit(h);

-            if xID != nil

-            {

-				P=PAIR.G1mul(P,x)

-				P.toBytes(&xID!)

-				W=PAIR.G1mul(W,x)

-				P.add(W)

-            }

-            else

-            {

-				P.add(W);

-				P=PAIR.G1mul(P,x);

-            }

-            if xCID != nil {P.toBytes(&xCID!)}

-        }

-        else

-        {

-            if xID != nil

-            {

-				P=PAIR.G1mul(P,x)

-				P.toBytes(&xID!)

-            }

-        }

-

-

-        T.toBytes(&SEC);

-        return 0;

-    }

-    /* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */

-    static public func GET_SERVER_SECRET(S:[UInt8],inout _ SST:[UInt8]) -> Int

-    {

-        var Q=ECP2(FP2(BIG(ROM.CURVE_Pxa),BIG(ROM.CURVE_Pxb)),FP2(BIG(ROM.CURVE_Pya),BIG(ROM.CURVE_Pyb)))

-

-        let s=BIG.fromBytes(S)

-        Q=PAIR.G2mul(Q,s)

-        Q.toBytes(&SST)

-        return 0

-    }

-

-    /*

-    W=x*H(G);

-    if RNG == NULL then X is passed in

-    if RNG != NULL the X is passed out

-    if type=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve

-    */

-    static public func GET_G1_MULTIPLE(rng:RAND?,_ type:Int,inout _ X:[UInt8],_ G:[UInt8],inout _ W:[UInt8]) -> Int

-    {

-        var x:BIG

-        let r=BIG(ROM.CURVE_Order)

-        if rng != nil

-        {

-            x=BIG.randomnum(r,rng!)

-            x.toBytes(&X)

-        }

-        else

-        {

-            x=BIG.fromBytes(X);

-        }

-        var P:ECP

-        if type==0

-        {

-            P=ECP.fromBytes(G)

-            if P.is_infinity() {return INVALID_POINT}

-        }

-        else

-            {P=MPIN.mapit(G)}

-

-        PAIR.G1mul(P,x).toBytes(&W)

-        return 0;

-    }

-    /* Client secret CST=S*H(CID) where CID is client ID and S is master secret */

-    /* CID is hashed externally */

-    static public func GET_CLIENT_SECRET(inout S:[UInt8],_ CID:[UInt8],inout _ CST:[UInt8]) -> Int

-    {

-        return GET_G1_MULTIPLE(nil,1,&S,CID,&CST)

-    }

-    /* Time Permit CTT=S*(date|H(CID)) where S is master secret */

-    static public func GET_CLIENT_PERMIT(date:Int32,_ S:[UInt8],_ CID:[UInt8],inout _ CTT:[UInt8]) -> Int

-    {

-        let h=MPIN.hashit(date,CID)

-        let P=MPIN.mapit(h)

-

-        let s=BIG.fromBytes(S)

-        PAIR.G1mul(P,s).toBytes(&CTT)

-        return 0;

-    }

-

-    /* Outputs H(CID) and H(T|H(CID)) for time permits. If no time permits set HID=HTID */

-    static public func SERVER_1(date:Int32,_ CID:[UInt8],inout _ HID:[UInt8]?,inout _ HTID:[UInt8])

-    {

-        var h=MPIN.hashit(0,CID)

-        let P=MPIN.mapit(h)

-

-        if date != 0

-        {

-            if HID != nil {P.toBytes(&HID!)}

-            h=hashit(date,h)

-            let R=MPIN.mapit(h)

-            P.add(R)

-            P.toBytes(&HTID)

-        }

-        else {P.toBytes(&HID!)}

-    }

-    /* Implement step 2 of MPin protocol on server side */

-    static public func SERVER_2(date:Int32,_ HID:[UInt8]?,_ HTID:[UInt8],_ Y:[UInt8],_ SST:[UInt8],_ xID:[UInt8]?,_ xCID:[UInt8],_ mSEC:[UInt8],inout _ E:[UInt8]?,inout _ F:[UInt8]?) -> Int

-    {

-        _=BIG(ROM.Modulus);

-        let Q=ECP2(FP2(BIG(ROM.CURVE_Pxa),BIG(ROM.CURVE_Pxb)),FP2(BIG(ROM.CURVE_Pya),BIG(ROM.CURVE_Pyb)))

-        let sQ=ECP2.fromBytes(SST)

-        if sQ.is_infinity() {return INVALID_POINT}

-

-        var R:ECP

-        if date != 0

-            {R=ECP.fromBytes(xCID)}

-        else

-        {

-            if xID==nil {return MPIN.BAD_PARAMS}

-            R=ECP.fromBytes(xID!)

-        }

-        if R.is_infinity() {return INVALID_POINT}

-

-        let y=BIG.fromBytes(Y)

-        var P:ECP

-        if date != 0 {P=ECP.fromBytes(HTID)}

-        else

-        {

-            if HID==nil {return MPIN.BAD_PARAMS}

-            P=ECP.fromBytes(HID!)

-        }

-

-        if P.is_infinity() {return INVALID_POINT}

-

-        P=PAIR.G1mul(P,y)

-        P.add(R)

-        R=ECP.fromBytes(mSEC)

-        if R.is_infinity() {return MPIN.INVALID_POINT}

-

-

-        var g=PAIR.ate2(Q,R,sQ,P)

-        g=PAIR.fexp(g)

-

-        if !g.isunity()

-        {

-            if HID != nil && xID != nil && E != nil && F != nil

-            {

-				g.toBytes(&E!)

-				if date != 0

-				{

-                    P=ECP.fromBytes(HID!)

-                    if P.is_infinity() {return MPIN.INVALID_POINT}

-                    R=ECP.fromBytes(xID!)

-                    if R.is_infinity() {return MPIN.INVALID_POINT}

-

-                    P=PAIR.G1mul(P,y);

-                    P.add(R);

-				}

-				g=PAIR.ate(Q,P);

-				g=PAIR.fexp(g);

-				g.toBytes(&F!);

-            }

-            return MPIN.BAD_PIN;

-        }

-

-        return 0

-    }

-    /* Pollards kangaroos used to return PIN error */

-    static public func KANGAROO(E:[UInt8],_ F:[UInt8]) -> Int

-    {

-        let ge=FP12.fromBytes(E)

-        let gf=FP12.fromBytes(F)

-        var distance=[Int]();

-        let t=FP12(gf);

-        var table=[FP12]()

-

-        var s:Int=1

-        for var m=0;m<Int(TS);m++

-        {

-            distance.append(s)

-            table.append(FP12(t))

-            s*=2

-            t.usqr()

-

-        }

-        t.one()

-        var dn:Int=0

-        for var j=0;j<TRAP;j++

-        {

-            let i=Int(t.geta().geta().getA().lastbits(8))%TS

-            t.mul(table[i])

-            dn+=distance[i]

-        }

-        gf.copy(t); gf.conj()

-        var steps=0; var dm:Int=0

-        var res=0;

-        while (dm-dn<Int(MAXPIN))

-        {

-            steps++;

-            if steps>4*TRAP {break}

-            let i=Int(ge.geta().geta().getA().lastbits(8))%TS

-            ge.mul(table[i])

-            dm+=distance[i]

-            if (ge.equals(t))

-            {

-				res=dm-dn;

-				break;

-            }

-            if (ge.equals(gf))

-            {

-				res=dn-dm

-				break

-            }

-

-        }

-        if steps>4*TRAP || dm-dn>=Int(MAXPIN) {res=0 }    // Trap Failed  - probable invalid token

-        return res

-    }

-    /* Functions to support M-Pin Full */

-

-    static public func PRECOMPUTE(TOKEN:[UInt8],_ CID:[UInt8],inout _ G1:[UInt8],inout _ G2:[UInt8]) -> Int

-    {

-        let T=ECP.fromBytes(TOKEN);

-        if T.is_infinity() {return INVALID_POINT}

-

-        let P=MPIN.mapit(CID)

-

-        let Q=ECP2(FP2(BIG(ROM.CURVE_Pxa),BIG(ROM.CURVE_Pxb)),FP2(BIG(ROM.CURVE_Pya),BIG(ROM.CURVE_Pyb)))

-

-        var g=PAIR.ate(Q,T)

-        g=PAIR.fexp(g)

-        g.toBytes(&G1)

-

-        g=PAIR.ate(Q,P)

-        g=PAIR.fexp(g)

-        g.toBytes(&G2)

-

-        return 0

-    }

-

-    /* calculate common key on client side */

-    /* wCID = w.(A+AT) */

-    static public func CLIENT_KEY(G1:[UInt8],_ G2:[UInt8],_ pin:Int32,_ R:[UInt8],_ X:[UInt8],_ wCID:[UInt8],inout _ CK:[UInt8]) -> Int

-    {

-        let H=HASH()

-        var t=[UInt8](count:EFS,repeatedValue:0)

-

-        let g1=FP12.fromBytes(G1)

-        let g2=FP12.fromBytes(G2)

-        let z=BIG.fromBytes(R)

-        let x=BIG.fromBytes(X)

-

-        var W=ECP.fromBytes(wCID)

-        if W.is_infinity() {return INVALID_POINT}

-

-        W=PAIR.G1mul(W,x)

-

-        let f=FP2(BIG(ROM.CURVE_Fra),BIG(ROM.CURVE_Frb))

-        let r=BIG(ROM.CURVE_Order)

-        let q=BIG(ROM.Modulus)

-

-        let m=BIG(q)

-        m.mod(r)

-

-        let a=BIG(z)

-        a.mod(m)

-

-        let b=BIG(z)

-        b.div(m);

-

-        g2.pinpow(pin,PBLEN);

-        g1.mul(g2);

-

-        var c=g1.trace()

-        g2.copy(g1)

-        g2.frob(f)

-        let cp=g2.trace()

-        g1.conj()

-        g2.mul(g1)

-        let cpm1=g2.trace()

-        g2.mul(g1)

-        let cpm2=g2.trace()

-

-        c=c.xtr_pow2(cp,cpm1,cpm2,a,b)

-

-        c.geta().getA().toBytes(&t)

-        H.process_array(t)

-        c.geta().getB().toBytes(&t)

-        H.process_array(t)

-        c.getb().getA().toBytes(&t)

-        H.process_array(t)

-        c.getb().getB().toBytes(&t)

-        H.process_array(t);

-

-        W.getX().toBytes(&t)

-        H.process_array(t)

-        W.getY().toBytes(&t)

-        H.process_array(t)

-

-        t=H.hash()

-        for var i=0;i<MPIN.PAS;i++ {CK[i]=t[i]}

-

-        return 0

-    }

-    /* calculate common key on server side */

-    /* Z=r.A - no time permits involved */

-

-    static public func SERVER_KEY(Z:[UInt8],_ SST:[UInt8],_ W:[UInt8],_ xID:[UInt8],_ xCID:[UInt8]?,inout _ SK:[UInt8]) -> Int

-    {

-        let H=HASH();

-        var t=[UInt8](count:EFS,repeatedValue:0)

-

-        let sQ=ECP2.fromBytes(SST)

-        if sQ.is_infinity() {return INVALID_POINT}

-        let R=ECP.fromBytes(Z)

-        if R.is_infinity() {return INVALID_POINT}

-

-        var U:ECP

-        if xCID != nil

-            {U=ECP.fromBytes(xCID!)}

-        else

-            {U=ECP.fromBytes(xID)}

-

-        if U.is_infinity() {return INVALID_POINT}

-

-        let w=BIG.fromBytes(W)

-        U=PAIR.G1mul(U,w)

-        var g=PAIR.ate(sQ,R)

-        g=PAIR.fexp(g)

-

-        let c=g.trace()

-        c.geta().getA().toBytes(&t)

-        H.process_array(t)

-        c.geta().getB().toBytes(&t)

-        H.process_array(t)

-        c.getb().getA().toBytes(&t)

-        H.process_array(t)

-        c.getb().getB().toBytes(&t)

-        H.process_array(t);

-

-        U.getX().toBytes(&t)

-        H.process_array(t)

-        U.getY().toBytes(&t)

-        H.process_array(t)

-

-        t=H.hash()

-        for var i=0;i<MPIN.PAS;i++ {SK[i]=t[i]}

-

-        return 0

-    }

-

-    /* return time since epoch */

-    static public func GET_TIME() -> Int32

-    {

-        let date=NSDate()

-        return (Int32(date.timeIntervalSince1970))

-    }

-

-    /* Generate Y = H(epoch, xCID/xID) */

-    static public func GET_Y(TimeValue:Int32,_ xCID:[UInt8],inout _ Y:[UInt8])

-    {

-        let h = MPIN.hashit(TimeValue,xCID)

-        let y = BIG.fromBytes(h)

-        let q=BIG(ROM.CURVE_Order)

-        y.mod(q)

-        y.toBytes(&Y)

-    }

-    /* One pass MPIN Client */

-    static public func CLIENT(date:Int32,_ CLIENT_ID:[UInt8],_ RNG:RAND?,inout _ X:[UInt8],_ pin:Int32,_ TOKEN:[UInt8],inout _  SEC:[UInt8],inout _ xID:[UInt8]?,inout _ xCID:[UInt8]?,_ PERMIT:[UInt8],_ TimeValue:Int32,inout _ Y:[UInt8]) -> Int

-    {

-        var rtn=0

-

-        rtn = MPIN.CLIENT_1(date,CLIENT_ID,RNG,&X,pin,TOKEN,&SEC,&xID,&xCID,PERMIT)

-

-        if rtn != 0 {return rtn}

-

-        if date==0 {MPIN.GET_Y(TimeValue,xID!,&Y)}

-        else {MPIN.GET_Y(TimeValue,xCID!,&Y)}

-

-        rtn = MPIN.CLIENT_2(X,Y,&SEC)

-        if (rtn != 0) {return rtn}

-

-        return 0

-    }

-    /* One pass MPIN Server */

-    static public func SERVER(date:Int32,inout _ HID:[UInt8]?,inout _ HTID:[UInt8],inout _ Y:[UInt8],_ SST:[UInt8],_ xID:[UInt8]?,_ xCID:[UInt8],_ SEC:[UInt8],inout _ E:[UInt8]?,inout _ F:[UInt8]?,_ CID:[UInt8],_ TimeValue:Int32) -> Int

-    {

-        var rtn=0

-

-        var pID:[UInt8]

-        if date == 0

-            {pID = xID!}

-        else

-            {pID = xCID}

-

-        SERVER_1(date,CID,&HID,&HTID);

-

-        GET_Y(TimeValue,pID,&Y);

-

-        rtn = SERVER_2(date,HID,HTID,Y,SST,xID,xCID,SEC,&E,&F);

-        if rtn != 0 {return rtn}

-

-        return 0

-    }

-

-    static public func printBinary(array: [UInt8])

-    {

-        for var i=0;i<array.count;i++

-        {

-            let h=String(format:"%02x",array[i])

-            print("\(h)", terminator: "")

-        }

-        print(" ");

-    }

-}

diff --git a/swift/pair.swift b/swift/pair.swift
deleted file mode 100644
index f768d36..0000000
--- a/swift/pair.swift
+++ /dev/null
@@ -1,501 +0,0 @@
-/*

-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.

-*/

-//

-//  pair.swift

-//  

-//

-//  Created by Michael Scott on 07/07/2015.

-//  Copyright (c) 2015 Michael Scott. All rights reserved.

-//

-

-/* CLINT BN Curve Pairing functions */

-

-final class PAIR {

-

-    /* Line function */

-    static func line(A:ECP2,_ B:ECP2,_ Qx:FP,_ Qy:FP) -> FP12

-    {

-        let P=ECP2()

-        var a:FP4

-        var b:FP4

-        var c:FP4

-        P.copy(A);

-        let ZZ=FP2(P.getz())

-        ZZ.sqr();

-        var D:Int

-        if A===B {D=A.dbl()} /* Check this return value in clint_ec2.c */

-        else {D=A.add(B)}

-        if (D<0) {return FP12(1)}

-        let Z3=FP2(A.getz())

-        c=FP4(0)

-        if D==0

-        { /* Addition */

-            let X=FP2(B.getx())

-            let Y=FP2(B.gety())

-            let T=FP2(P.getz())

-            T.mul(Y)

-            ZZ.mul(T)

-

-            let NY=FP2(P.gety()); NY.neg()

-            ZZ.add(NY)

-            Z3.pmul(Qy)

-            T.mul(P.getx())

-            X.mul(NY)

-            T.add(X)

-            a=FP4(Z3,T)

-            ZZ.neg()

-            ZZ.pmul(Qx)

-            b=FP4(ZZ)

-        }

-        else

-        { /* Doubling */

-            let X=FP2(P.getx())

-            let Y=FP2(P.gety())

-            let T=FP2(P.getx())

-            T.sqr()

-            T.imul(3)

-

-            Y.sqr()

-            Y.add(Y)

-            Z3.mul(ZZ)

-            Z3.pmul(Qy)

-

-            X.mul(T)

-            X.sub(Y)

-            a=FP4(Z3,X)

-            T.neg()

-            ZZ.mul(T)

-            ZZ.pmul(Qx)

-            b=FP4(ZZ)

-        }

-        return FP12(a,b,c)

-    }

-    /* Optimal R-ate pairing */

-    static func ate(P:ECP2,_ Q:ECP) -> FP12

-    {

-        let f=FP2(BIG(ROM.CURVE_Fra),BIG(ROM.CURVE_Frb))

-        let x=BIG(ROM.CURVE_Bnx)

-        let n=BIG(x)

-        let K=ECP2()

-

-        var lv:FP12

-        n.pmul(6); n.dec(2); n.norm()

-        P.affine()

-        Q.affine()

-        let Qx=FP(Q.getx())

-        let Qy=FP(Q.gety())

-

-        let A=ECP2()

-        let r=FP12(1)

-

-        A.copy(P)

-        let nb=n.nbits()

-

-        for var i=nb-2;i>=1;i--

-        {

-            lv=line(A,A,Qx,Qy)

-            r.smul(lv)

-

-            if (n.bit(i)==1)

-            {

-				lv=line(A,P,Qx,Qy)

-				r.smul(lv)

-            }

-            r.sqr()

-        }

-

-        lv=line(A,A,Qx,Qy)

-        r.smul(lv)

-

-    /* R-ate fixup */

-

-        r.conj()

-

-        K.copy(P)

-        K.frob(f)

-        A.neg()

-        lv=line(A,K,Qx,Qy)

-        r.smul(lv)

-        K.frob(f)

-        K.neg()

-        lv=line(A,K,Qx,Qy)

-        r.smul(lv)

-

-        return r

-    }

-    /* Optimal R-ate double pairing e(P,Q).e(R,S) */

-    static func ate2(P:ECP2,_ Q:ECP,_ R:ECP2,_ S:ECP) -> FP12

-    {

-        let f=FP2(BIG(ROM.CURVE_Fra),BIG(ROM.CURVE_Frb))

-        let x=BIG(ROM.CURVE_Bnx)

-        let n=BIG(x)

-        let K=ECP2()

-        var lv:FP12

-        n.pmul(6); n.dec(2); n.norm()

-        P.affine()

-        Q.affine()

-        R.affine()

-        S.affine()

-

-        let Qx=FP(Q.getx())

-        let Qy=FP(Q.gety())

-        let Sx=FP(S.getx())

-        let Sy=FP(S.gety())

-

-        let A=ECP2()

-        let B=ECP2()

-        let r=FP12(1)

-

-        A.copy(P)

-        B.copy(R)

-        let nb=n.nbits()

-

-        for var i=nb-2;i>=1;i--

-        {

-            lv=line(A,A,Qx,Qy)

-            r.smul(lv)

-            lv=line(B,B,Sx,Sy)

-            r.smul(lv)

-            if n.bit(i)==1

-            {

-				lv=line(A,P,Qx,Qy)

-				r.smul(lv)

-				lv=line(B,R,Sx,Sy)

-				r.smul(lv)

-            }

-            r.sqr()

-        }

-

-        lv=line(A,A,Qx,Qy)

-        r.smul(lv)

-

-        lv=line(B,B,Sx,Sy)

-        r.smul(lv)

-

-    /* R-ate fixup */

-        r.conj()

-

-        K.copy(P)

-        K.frob(f)

-        A.neg()

-        lv=line(A,K,Qx,Qy)

-        r.smul(lv)

-        K.frob(f)

-        K.neg()

-        lv=line(A,K,Qx,Qy)

-        r.smul(lv)

-

-        K.copy(R)

-        K.frob(f)

-        B.neg()

-        lv=line(B,K,Sx,Sy)

-        r.smul(lv)

-        K.frob(f)

-        K.neg()

-        lv=line(B,K,Sx,Sy)

-        r.smul(lv)

-

-        return r

-    }

-

-    /* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */

-    static func fexp(m:FP12) -> FP12

-    {

-        let f=FP2(BIG(ROM.CURVE_Fra),BIG(ROM.CURVE_Frb));

-        let x=BIG(ROM.CURVE_Bnx)

-        let r=FP12(m)

-

-    /* Easy part of final exp */

-        var lv=FP12(r)

-        lv.inverse()

-        r.conj()

-

-        r.mul(lv)

-        lv.copy(r)

-        r.frob(f)

-        r.frob(f)

-        r.mul(lv)

-

-    /* Hard part of final exp */

-        lv.copy(r)

-        lv.frob(f)

-        let x0=FP12(lv)

-        x0.frob(f)

-        lv.mul(r)

-        x0.mul(lv)

-        x0.frob(f)

-        let x1=FP12(r)

-        x1.conj()

-        let x4=r.pow(x)

-

-        let x3=FP12(x4)

-        x3.frob(f)

-

-        let x2=x4.pow(x)

-

-        let x5=FP12(x2); x5.conj()

-        lv=x2.pow(x)

-

-        x2.frob(f)

-        r.copy(x2); r.conj()

-

-        x4.mul(r)

-        x2.frob(f)

-

-        r.copy(lv)

-        r.frob(f)

-        lv.mul(r)

-

-        lv.usqr()

-        lv.mul(x4)

-        lv.mul(x5)

-        r.copy(x3)

-        r.mul(x5)

-        r.mul(lv)

-        lv.mul(x2)

-        r.usqr()

-        r.mul(lv)

-        r.usqr()

-        lv.copy(r)

-        lv.mul(x1)

-        r.mul(x0)

-        lv.usqr()

-        r.mul(lv)

-        r.reduce()

-        return r

-    }

-

-    /* GLV method */

-    static func glv(e:BIG) -> [BIG]

-    {

-        let t=BIG(0)

-        let q=BIG(ROM.CURVE_Order)

-        var u=[BIG]();

-        var v=[BIG]();

-        for var j=0;j<2;j++

-        {

-            u.append(BIG(0))

-            v.append(BIG(0))

-        }

-

-        for var i=0;i<2;i++

-        {

-            t.copy(BIG(ROM.CURVE_W[i]))

-            let d=BIG.mul(t,e)

-            v[i].copy(d.div(q))

-        }

-        u[0].copy(e);

-        for var i=0;i<2;i++

-        {

-            for var j=0;j<2;j++

-            {

-				t.copy(BIG(ROM.CURVE_SB[j][i]))

-				t.copy(BIG.modmul(v[j],t,q))

-				u[i].add(q)

-				u[i].sub(t)

-				u[i].mod(q)

-            }

-        }

-        return u

-    }

-    /* Galbraith & Scott Method */

-    static func gs(e:BIG) -> [BIG]

-    {

-        let t=BIG(0)

-        let q=BIG(ROM.CURVE_Order)

-        var u=[BIG]();

-        var v=[BIG]();

-        for var j=0;j<4;j++

-        {

-            u.append(BIG(0))

-            v.append(BIG(0))

-        }

-

-        for var i=0;i<4;i++

-        {

-            t.copy(BIG(ROM.CURVE_WB[i]))

-            let d=BIG.mul(t,e)

-            v[i].copy(d.div(q))

-        }

-        u[0].copy(e);

-        for var i=0;i<4;i++

-        {

-            for var j=0;j<4;j++

-            {

-				t.copy(BIG(ROM.CURVE_BB[j][i]))

-				t.copy(BIG.modmul(v[j],t,q))

-				u[i].add(q)

-				u[i].sub(t)

-				u[i].mod(q)

-            }

-        }

-        return u

-    }

-

-    /* Multiply P by e in group G1 */

-    static func G1mul(P:ECP,_ e:BIG) -> ECP

-    {

-        var R:ECP

-        if (ROM.USE_GLV)

-        {

-            P.affine()

-            R=ECP()

-            R.copy(P)

-            let Q=ECP()

-            Q.copy(P)

-            let q=BIG(ROM.CURVE_Order)

-            let cru=FP(BIG(ROM.CURVE_Cru))

-            let t=BIG(0)

-            var u=PAIR.glv(e)

-            Q.getx().mul(cru);

-

-            var np=u[0].nbits()

-            t.copy(BIG.modneg(u[0],q))

-            var nn=t.nbits()

-            if (nn<np)

-            {

-				u[0].copy(t)

-				R.neg()

-            }

-

-            np=u[1].nbits()

-            t.copy(BIG.modneg(u[1],q))

-            nn=t.nbits()

-            if (nn<np)

-            {

-				u[1].copy(t)

-				Q.neg()

-            }

-

-            R=R.mul2(u[0],Q,u[1])

-        }

-        else

-        {

-            R=P.mul(e)

-        }

-        return R

-    }

-

-    /* Multiply P by e in group G2 */

-    static func G2mul(P:ECP2,_ e:BIG) -> ECP2

-    {

-        var R:ECP2

-        if (ROM.USE_GS_G2)

-        {

-            var Q=[ECP2]()

-            let f=FP2(BIG(ROM.CURVE_Fra),BIG(ROM.CURVE_Frb));

-            let q=BIG(ROM.CURVE_Order);

-            var u=PAIR.gs(e);

-

-            let t=BIG(0);

-            P.affine()

-            Q.append(ECP2())

-            Q[0].copy(P);

-            for var i=1;i<4;i++

-            {

-                Q.append(ECP2()); Q[i].copy(Q[i-1]);

-				Q[i].frob(f);

-            }

-            for var i=0;i<4;i++

-            {

-				let np=u[i].nbits();

-				t.copy(BIG.modneg(u[i],q));

-				let nn=t.nbits();

-				if (nn<np)

-				{

-                    u[i].copy(t);

-                    Q[i].neg();

-				}

-            }

-

-            R=ECP2.mul4(Q,u);

-        }

-        else

-        {

-            R=P.mul(e);

-        }

-        return R;

-    }

-    /* f=f^e */

-    /* Note that this method requires a lot of RAM! Better to use compressed XTR method, see FP4.java */

-    static func GTpow(d:FP12,_ e:BIG) -> FP12

-    {

-        var r:FP12

-        if (ROM.USE_GS_GT)

-        {

-            var g=[FP12]()

-            let f=FP2(BIG(ROM.CURVE_Fra),BIG(ROM.CURVE_Frb))

-            let q=BIG(ROM.CURVE_Order)

-            let t=BIG(0)

-

-            var u=gs(e)

-            g.append(FP12(0))

-            g[0].copy(d);

-            for var i=1;i<4;i++

-            {

-                g.append(FP12(0)); g[i].copy(g[i-1])

-				g[i].frob(f)

-            }

-            for var i=0;i<4;i++

-            {

-				let np=u[i].nbits()

-				t.copy(BIG.modneg(u[i],q))

-				let nn=t.nbits()

-				if (nn<np)

-				{

-                    u[i].copy(t)

-                    g[i].conj()

-				}

-            }

-            r=FP12.pow4(g,u)

-        }

-        else

-        {

-            r=d.pow(e)

-        }

-        return r

-    }

-    /* test group membership */

-    /* with GT-Strong curve, now only check that m!=1, conj(m)*m==1, and m.m^{p^4}=m^{p^2} */

-    static func GTmember(m:FP12) -> Bool

-    {

-        if m.isunity() {return false}

-        let r=FP12(m)

-        r.conj()

-        r.mul(m)

-        if !r.isunity() {return false}

-

-        let f=FP2(BIG(ROM.CURVE_Fra),BIG(ROM.CURVE_Frb))

-

-        r.copy(m); r.frob(f); r.frob(f)

-        var w=FP12(r); w.frob(f); w.frob(f)

-        w.mul(m)

-        if !ROM.GT_STRONG

-        {

-            if !w.equals(r) {return false}

-            let x=BIG(ROM.CURVE_Bnx)

-            r.copy(m); w=r.pow(x); w=w.pow(x)

-            r.copy(w); r.sqr(); r.mul(w); r.sqr()

-            w.copy(m); w.frob(f)

-        }

-        return w.equals(r)

-    }

-

-}

-

diff --git a/swift/rand.swift b/swift/rand.swift
deleted file mode 100644
index 1026433..0000000
--- a/swift/rand.swift
+++ /dev/null
@@ -1,131 +0,0 @@
-/*

-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.

-*/

-//

-//  rand.swift

-//  

-//

-//  Created by Michael Scott on 17/06/2015.

-//  Copyright (c) 2015 Michael Scott. All rights reserved.

-//

-//  Cryptographic strong random number generator

-

-/* Marsaglia & Zaman Random number generator constants */

-final public class RAND {

-    private static let NK:Int=21

-    private static let NJ:Int=6

-    private static let NV:Int=8

-    private var ira=[UInt32](count:NK,repeatedValue:0)

-    private var rndptr:Int=0

-    private var borrow:UInt32=0

-    private var pool_ptr:Int=0

-    private var pool=[UInt8](count:32,repeatedValue:0)

-

-    public func clean()

-    {

-        pool_ptr=0

-        rndptr=0

-        for var i=0;i<32;i++ {pool[i]=0}

-        for var i=0;i<RAND.NK;i++ {ira[i]=0}

-        borrow=0;

-    }

-

-    public init() {clean()}

-

-    private func sbrand() -> UInt32

-    { /* Marsaglia & Zaman random number generator */

-        rndptr++;

-        if rndptr<RAND.NK {return ira[rndptr]}

-        rndptr=0;

-        var k=RAND.NK-RAND.NJ

-        for var i=0;i<RAND.NK;i++

-        {

-            if k==RAND.NK {k=0}

-            let t=ira[k];

-            let pdiff=t &- ira[i] &- borrow

-            if pdiff<t {borrow=0}

-            if pdiff>t {borrow=1}

-            ira[i]=pdiff

-            k++;

-        }

-        return ira[0]

-    }

-

-    func sirand(seed: UInt32)

-    {

-        var m:UInt32=1

-        var s:UInt32=seed

-        borrow=0;

-        rndptr=0

-        ira[0]^=s

-        for var i=1;i<RAND.NK;i++

-        { /* fill initialisation vector */

-            let ipn=(RAND.NV*i)%RAND.NK

-            ira[ipn]^=m

-            let t=m

-            m=s &- m

-            s=t

-        }

-        for var i=0;i<10000;i++ {sbrand()}

-    }

-

-    private func fill_pool()

-    {

-        let sh=HASH()

-        for var i=0;i<128;i++ {sh.process(UInt8(sbrand()&0xff))}

-        pool=sh.hash()

-        pool_ptr=0

-    }

-

-    private func pack(b: [UInt8]) -> UInt32

-    {

-        return (UInt32(b[3])<<24)|(UInt32(b[2])<<16)|(UInt32(b[1])<<8)|(UInt32(b[0]))

-    }

-

-/* Initialize RNG with some real entropy from some external source */

-    public func seed(rawlen: Int,_ raw: [UInt8])

-    { /* initialise from at least 128 byte string of raw random entropy */

-        var digest=[UInt8]()

-        var b=[UInt8](count:4, repeatedValue:0)

-        let sh=HASH()

-        pool_ptr=0

-        for var i=0;i<RAND.NK;i++ {ira[i]=0}

-        if rawlen>0

-        {

-            for var i=0;i<rawlen;i++ {sh.process(raw[i])}

-            digest=sh.hash()

-

-            for var i=0;i<8;i++

-            {

-                b[0]=digest[4*i]; b[1]=digest[4*i+1]; b[2]=digest[4*i+2]; b[3]=digest[4*i+3]

-                sirand(pack(b))

-            }

-

-        }

-        fill_pool()

-    }

-

-    public func getByte() -> UInt8

-    {

-        let r=pool[pool_ptr++]

-        if pool_ptr>=32 {fill_pool()}

-        return r

-    }

-

-

-}

diff --git a/swift/readme.txt b/swift/readme.txt
deleted file mode 100644
index 708054d..0000000
--- a/swift/readme.txt
+++ /dev/null
@@ -1,45 +0,0 @@
-AMCL is very simple to build for Swift.

-

-First - decide the modulus and curve type you want to use. Edit rom.swift 

-where indicated. You will probably want to use one of the curves whose 

-details are already in there.

-

-Three example API files are provided, mpin.swift which 

-supports our M-Pin (tm) protocol, ecdh.swift which supports elliptic 

-curve key exchange, digital signature and public key crypto, and rsa.swift

-which supports the RSA method. The first  can be tested using the 

-TestMPIN.swift driver programs, the second can be tested using TestECDH.swift 

-and TestECM.swift, and the third with TestRSA.swift

-

-In the rom.swift file you must provide the curve constants. Several examples

-are provided there, if you are willing to use one of these.

-

-For a quick jumpstart:-

-

-From a terminal window in a /lib directory create a dynamic library using the command

-

-swiftc big.swift rom.swift dbig.swift rand.swift hash.swift fp.swift fp2.swift ecp.swift ecp2.swift aes.swift gcm.swift fp4.swift fp12.swift ff.swift pair.swift rsa.swift ecdh.swift mpin.swift -Ounchecked -whole-module-optimization -emit-library -emit-module -module-name clint

-

-This creates the files 

-

-libclint.dylib

-clint.swiftmodule

-

-Copy these to a project directory, which contains only the files 

-

-TestECDH.swift

-TestRSA.swift

-TestMPIN.swift

-

-And create and run the projects by issuing the commands

-

-swift -lclint -I. TestMPIN.swift 

-swift -lclint -I. TestECDH.swift 

-swift -lclint -I. TestRSA.swift 

-

-Note that classes and methods that need to be exposed to consuming programs, 

-should be made "public" when and if needed. Here we have done this as needed 

-just for these example programs

-

-

-

diff --git a/swift/rom.swift b/swift/rom.swift
deleted file mode 100644
index aaf6c76..0000000
--- a/swift/rom.swift
+++ /dev/null
@@ -1,296 +0,0 @@
-/*

-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.

-*/

-//

-//  rom.swift

-//  

-//

-//  Created by Michael Scott on 12/06/2015.

-//  Copyright (c) 2015 Michael Scott. All rights reserved.

-//

-

-final public class ROM{

-    static let NLEN:Int=9

-    static let CHUNK:Int=32

-    static let DNLEN:Int=2*NLEN

-

-/*** Enter Some Field details here  ***/

-    // BN Curve

-    static let MODBITS:Int32 = 254 /* Number of bits in Modulus */

-    static let MOD8:Int32 = 3   /* Modulus mod 8 */

-    // Curve 25519

-//    static let MODBITS:Int32=255

-//    static let MOD8:Int32=5

-

-    // NIST256 or Brainpool

-//    static let MODBITS:Int32=256

-//    static let MOD8:Int32=7

-

-    // MF254

-//    static let MODBITS:Int32=254

-//    static let MOD8:Int32=7

-    // MS255

-//    static let MODBITS:Int32 = 255

-//    static let MOD8:Int32 = 3

-    // MF256

-//    static let MODBITS:Int32 = 256

-//    static let MOD8:Int32 = 7

-    // MS256

-//    static let MODBITS:Int32 = 256

-//    static let MOD8:Int32 = 3

-

-    // ANSSI

-//    static let MODBITS:Int32 = 256

-//    static let MOD8:Int32 = 3

-

-    static let BASEBITS:Int32=29

-    static let OMASK:Int32=Int32(-1)<<Int32(MODBITS%BASEBITS)

-    static let MASK:Int32=((Int32(1)<<BASEBITS)-Int32(1))

-    static let TBITS:Int32=MODBITS%BASEBITS; // Number of active bits in top word

-    static let TMASK:Int32=(Int32(1)<<TBITS)-1;

-    static let MODBYTES:Int32=32

-    static let NEXCESS:Int32 = (Int32(1)<<(Int32(CHUNK)-BASEBITS-1))

-    static let FEXCESS:Int32 = (Int32(1)<<(BASEBITS*Int32(NLEN)-MODBITS));

-

-    /* Don't Modify from here... */

-    static let NOT_SPECIAL=0

-    static let PSEUDO_MERSENNE=1

-    static let MONTGOMERY_FRIENDLY=2

-    static let WEIERSTRASS=0

-    static let EDWARDS=1

-    static let MONTGOMERY=2

-    /* ...to here */

-

-

-    /* Finite field support - for RSA, DH etc. */

-    static let FF_BITS:Int=2048; /* Finite Field Size in bits - must be 256.2^n */

-    static public let FFLEN=(FF_BITS/256)

-    static public let HFLEN=(FFLEN/2);  /* Useful for half-size RSA private key operations */

-

-// START SPECIFY FIELD DETAILS HERE

-//*********************************************************************************

-// Curve25519 Modulus

-//    static let MODTYPE=PSEUDO_MERSENNE

-//    static let Modulus:[Int32]=[0x1FFFFFED,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFFF]

-//    static let MConst:Int32=19

-

-// NIST-256 Modulus

-//    static let MODTYPE=NOT_SPECIAL

-//    static let Modulus:[Int32]=[0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FF,0x0,0x0,0x40000,0x1FE00000,0xFFFFFF]

-//    static let MConst:Int32=1

-

-// MF254 Modulus

-//    static let MODTYPE=MONTGOMERY_FRIENDLY

-//    static let Modulus:[Int32]=[0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3F80FF]

-//    static let MConst:Int32=0x3F8100

-// MS255 Modulus

-//    static let MODTYPE = PSEUDO_MERSENNE

-//    static let Modulus:[Int32]=[0x1FFFFD03,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFFF]

-//    static let MConst:Int32=0x2FD

-// MF256 Modulus

-//    static let MODTYPE = MONTGOMERY_FRIENDLY

-//    static let Modulus:[Int32]=[0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFFA7FF]

-//    static let MConst:Int32=0xFFA800

-// MS256 Modulus

-//    static let MODTYPE = PSEUDO_MERSENNE

-//    static let Modulus:[Int32]=[0x1FFFFF43,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFFFFFF]

-//    static let MConst:Int32 = 0xBD

-    // Brainpool Modulus

-//    static let MODTYPE = NOT_SPECIAL

-//    static let Modulus:[Int32]=[0x1F6E5377,0x9A40E8,0x9880A08,0x17EC47AA,0x18D726E3,0x5484EC1,0x6F0F998,0x1B743DD5,0xA9FB57]

-//    static let MConst:Int32 = 0xEFD89B9

-    // ANSSI Modulus

-//    static let MODTYPE = NOT_SPECIAL

-//    static let Modulus:[Int32]=[0x186E9C03,0x7E79A9E,0x12329B7A,0x35B7957,0x435B396,0x16F46721,0x163C4049,0x1181675A,0xF1FD17]

-//    static let MConst:Int32 = 0x164E1155

-

-    // BNCX Curve Modulus

-    static let MODTYPE = NOT_SPECIAL

-    static let Modulus:[Int32]=[0x1C1B55B3,0x13311F7A,0x24FB86F,0x1FADDC30,0x166D3243,0xFB23D31,0x836C2F7,0x10E05,0x240000]

-    static let MConst:Int32=0x19789E85

-

-

-    // START SPECIFY CURVE DETAILS HERE

-    //*********************************************************************************

-    // Original Curve25519

-    // 	static let CURVETYPE=MONTGOMERY

-    //	static let CURVE_A:Int32 = 486662

-    //	static let CURVE_B:[Int32]=[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0] // not used

-    //	static let CURVE_Order:[Int32]=[0x1CF5D3ED,0x9318D2,0x1DE73596,0x1DF3BD45,0x14D,0x0,0x0,0x0,0x100000]

-    //	static let CURVE_Gx:[Int32]=[0x9,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]

-    //	static let CURVE_Gy:[Int32]=[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0] // not used

-// Ed25519 Curve

-    //static let CURVETYPE=EDWARDS

-    //static let CURVE_A:Int32 = -1

-    //static let CURVE_B:[Int32]=[0x135978A3,0xF5A6E50,0x10762ADD,0x149A82,0x1E898007,0x3CBBBC,0x19CE331D,0x1DC56DFF,0x52036C]

-    //static let CURVE_Order:[Int32]=[0x1CF5D3ED,0x9318D2,0x1DE73596,0x1DF3BD45,0x14D,0x0,0x0,0x0,0x100000]

-    //static let CURVE_Gx:[Int32]=[0xF25D51A,0xAB16B04,0x969ECB2,0x198EC12A,0xDC5C692,0x1118FEEB,0xFFB0293,0x1A79ADCA,0x216936]

-    //static let CURVE_Gy:[Int32]=[0x6666658,0x13333333,0x19999999,0xCCCCCCC,0x6666666,0x13333333,0x19999999,0xCCCCCCC,0x666666]

-

-// NIST-256 Curve

-    //	static let CURVETYPE=WEIERSTRASS

-    //    static let CURVE_A:Int32 = -3;

-    //    static let CURVE_B:[Int32]=[0x7D2604B,0x1E71E1F1,0x14EC3D8E,0x1A0D6198,0x86BC651,0x1EAABB4C,0xF9ECFAE,0x1B154752,0x5AC635]

-    //    static let CURVE_Order:[Int32]=[0x1C632551,0x1DCE5617,0x5E7A13C,0xDF55B4E,0x1FFFFBCE,0x1FFFFFFF,0x3FFFF,0x1FE00000,0xFFFFFF]

-    //    static let CURVE_Gx:[Int32]=[0x1898C296,0x509CA2E,0x1ACCE83D,0x6FB025B,0x40F2770,0x1372B1D2,0x91FE2F3,0x1E5C2588,0x6B17D1]

-    //    static let CURVE_Gy:[Int32]=[0x17BF51F5,0x1DB20341,0xC57B3B2,0x1C66AED6,0x19E162BC,0x15A53E07,0x1E6E3B9F,0x1C5FC34F,0x4FE342]

-

-    // MF254 Modulus, Weierstrass Curve w-254-mont

-    //    static let CURVETYPE=WEIERSTRASS

-    //    static let CURVE_A:Int32 = -3

-    //    static let CURVE_B:[Int32]=[0x1FFFD08D,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3F80FF]

-    //    static let CURVE_Order:[Int32]=[0xF8DF83F,0x1D20CE25,0x8DD701B,0x317D41B,0x1FFFFEB8,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3F80FF]

-    //    static let CURVE_Gx:[Int32]=[0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]

-    //    static let CURVE_Gy:[Int32]=[0x190D4EBC,0xB2EF9BF,0x14464C6B,0xE71C7F0,0x18AEBDFB,0xD3ADEBB,0x18052B85,0x1A6765CA,0x140E3F]

-

-    // MF254 Modulus, Edwards Curve ed-254-mont

-    //    static let CURVETYPE = EDWARDS

-    //    static let CURVE_A:Int32 = -1

-    //    static let CURVE_B:[Int32]=[0x367B,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]

-    //    static let CURVE_Order:[Int32]=[0x46E98C7,0x179E9FF6,0x158BEC3A,0xA60D917,0x1FFFFEB9,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFE03F]

-    //    static let CURVE_Gx:[Int32]=[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]

-    //    static let CURVE_Gy:[Int32]=[0xF2701E5,0x29687ED,0xC84861F,0x535081C,0x3F4E363,0x6A811B,0xCD65474,0x121AD498,0x19F0E6]

-

-    // MF254 Modulus, Montgomery Curve

-    //static let CURVETYPE = MONTGOMERY

-    //static let CURVE_A:Int32 = -55790;

-    //static let CURVE_B:[Int32]=[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0] // not used

-    //static let CURVE_Order:[Int32]=[0x46E98C7,0x179E9FF6,0x158BEC3A,0xA60D917,0x1FFFFEB9,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFE03F]

-    //static let CURVE_Gx:[Int32]=[0x3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]

-    //static let CURVE_Gy:[Int32]=[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0] // not used

-

-    // MS255 Modulus, Weierstrass Curve

-    //static let CURVETYPE = WEIERSTRASS

-    //static let CURVE_A:Int32 = -3

-    //static let CURVE_B:[Int32]=[0x1FFFAB46,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFFF]

-    //static let CURVE_Order:[Int32]=[0x1C594AEB,0x1C7D64C1,0x14ACF7EA,0x14705075,0x1FFFF864,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFFF]

-    //static let CURVE_Gx:[Int32]=[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]

-    //static let CURVE_Gy:[Int32]=[0x9CB44BA,0x199FFB3B,0x1F698345,0xD8F19BB,0x17D177DB,0x1FFCD97F,0xCE487A,0x181DB74F,0x6F7A6A]

-

-    // MS255 Modulus, Edwards Curve

-    //static let CURVETYPE = EDWARDS

-    //static let CURVE_A:Int32 = -1

-    //static let CURVE_B:[Int32]=[0xEA97,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]

-    //static let CURVE_Order:[Int32]=[0x436EB75,0x24E8F68,0x9A0CBAB,0x34F0BDB,0x1FFFFDCF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFF]

-    //static let CURVE_Gx:[Int32]=[0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]

-    //static let CURVE_Gy:[Int32]=[0x108736A0,0x11512ADE,0x1116916E,0x29715DA,0x47E5529,0x66EC706,0x1517B095,0xA694F76,0x26CB78]

-

-    // MS255 Modulus, Montgomery Curve

-    //static let CURVETYPE=MONTGOMERY

-    //static let CURVE_A:Int32 = -240222

-    //static let CURVE_B:[Int32]=[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0] // not used

-    //static let CURVE_Order:[Int32]=[0x436EB75,0x24E8F68,0x9A0CBAB,0x34F0BDB,0x1FFFFDCF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFF]

-    //static let CURVE_Gx:[Int32]=[0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]

-    //static let CURVE_Gy:[Int32]=[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0] // not used

-

-    // MF256 Modulus, Weierstrass Curve

-    //static let CURVETYPE = WEIERSTRASS

-    //static let CURVE_A:Int32 = -3;

-    //static let CURVE_B:[Int32]=[0x14E6A,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]

-    //static let CURVE_Order:[Int32]=[0x79857EB,0x8862F0D,0x1941D2E7,0x2EA27CD,0x1FFFFFC5,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFFA7FF]

-    //static let CURVE_Gx:[Int32]=[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]

-    //static let CURVE_Gy:[Int32]=[0xB724D2A,0x3CAA61,0x5371984,0x128FD71B,0x1AE28956,0x1D13091E,0x339EEAE,0x10F7C301,0x20887C]

-

-    // MF256, Edwards Curve

-    //static let CURVETYPE = EDWARDS

-    //static let CURVE_A:Int32 = -1

-    //static let CURVE_B:[Int32]=[0x350A,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]

-    //static let CURVE_Order:[Int32]=[0x18EC7BAB,0x16C976F6,0x19CCF259,0x9775F70,0x1FFFFB15,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3FE9FF]

-    //static let CURVE_Gx:[Int32]=[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]

-    //static let CURVE_Gy:[Int32]=[0x12F3C908,0xF553917,0x1FA9A35F,0xBCC91B,0x1AACA0C,0x1779ED96,0x156BABAF,0x1F1F1989,0xDAD8D4]

-

-    // MF256 Modulus, Montgomery Curve

-    //static let CURVETYPE = MONTGOMERY

-    //static let CURVE_A:Int32 = -54314

-    //static let CURVE_B:[Int32]=[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0] // not used

-    //static let CURVE_Order:[Int32]=[0x18EC7BAB,0x16C976F6,0x19CCF259,0x9775F70,0x1FFFFB15,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3FE9FF]

-    //static let CURVE_Gx:[Int32]=[0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]

-    //static let CURVE_Gy:[Int32]=[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0] // not used

-

-    // MS256, Weierstrass Curve

-    //static let CURVETYPE  = WEIERSTRASS

-    //static let CURVE_A:Int32 = -3

-    //static let CURVE_B:[Int32]=[0x25581,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]

-    //static let CURVE_Order:[Int32]=[0x751A825,0x559014A,0x9971808,0x1904EBD4,0x1FFFFE43,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFFFFFF]

-    //static let CURVE_Gx:[Int32]=[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]

-    //static let CURVE_Gy:[Int32]=[0x2B56C77,0x1FA31836,0x253B042,0x185F26EB,0xDD6BD02,0x4B66777,0x1B5FF20B,0xA783C8C,0x696F18]

-

-    // MS256, Edwards Curve

-    //static let CURVETYPE = EDWARDS

-    //static let CURVE_A:Int32 = -1;

-    //static let CURVE_B:[Int32]=[0x3BEE,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]

-    //static let CURVE_Order:[Int32]=[0x1122B4AD,0xDC27378,0x9AF1939,0x154AB5A1,0x1FFFFBE6,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3FFFFF]

-    //static let CURVE_Gx:[Int32]=[0xD,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]

-    //static let CURVE_Gy:[Int32]=[0x131CADBA,0x3FB7DA9,0x134C0FDC,0x14DAC704,0x46BFBE2,0x1859CFD0,0x1B6E8F4C,0x3C5424E,0x7D0AB4]

-

-    // MS256 Modulus, Montgomery Curve

-    //static let CURVETYPE = MONTGOMERY

-    //static let CURVE_A:Int32 = -61370

-    //static let CURVE_B:[Int32]=[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0] // not used

-    //static let CURVE_Order:[Int32]=[0x1122B4AD,0xDC27378,0x9AF1939,0x154AB5A1,0x1FFFFBE6,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3FFFFF]

-    //static let CURVE_Gx:[Int32]=[0xb,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]

-    //static let CURVE_Gy:[Int32]=[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0] // not used

-

-    // Brainpool

-    //static let CURVETYPE = WEIERSTRASS

-    //static let CURVE_A:Int32 = -3

-    //static let CURVE_B:[Int32]=[0x1EE92B04,0x172C080F,0xBD2495A,0x7D7895E,0x176B7BF9,0x13B99E85,0x1A93F99A,0x18861B09,0x662C61]

-    //static let CURVE_Order:[Int32]=[0x174856A7,0xF07414,0x1869BDE4,0x12F5476A,0x18D718C3,0x5484EC1,0x6F0F998,0x1B743DD5,0xA9FB57]

-    //static let CURVE_Gx:[Int32]=[0xE1305F4,0xD0C8AB1,0xBEF0ADE,0x28588F5,0x16149AFA,0x9D91D32,0x1EDDCC88,0x79839FC,0xA3E8EB]

-    //static let CURVE_Gy:[Int32]=[0x1B25C9BE,0xD5F479A,0x1409C007,0x196DBC73,0x417E69B,0x1170A322,0x15B5FDEC,0x10468738,0x2D996C]

-

-    // ANSSI

-    //static let CURVETYPE = WEIERSTRASS

-    //static let CURVE_A:Int32 = -3;

-    //static let CURVE_B:[Int32]=[0x1B7BB73F,0x3AF6CB3,0xC68600C,0x181935C9,0xC00FDFE,0x1D3AA522,0x4C0352A,0x194A8515,0xEE353F]

-    //static let CURVE_Order:[Int32]=[0x6D655E1,0x1FEEA2CE,0x14AFE507,0x18CFC281,0x435B53D,0x16F46721,0x163C4049,0x1181675A,0xF1FD17]

-    //static let CURVE_Gx:[Int32]=[0x198F5CFF,0x64BD16E,0x62DC059,0xFA5B95F,0x23958C2,0x1EA3A4EA,0x7ACC460,0x186AD827,0xB6B3D4]

-    //static let CURVE_Gy:[Int32]=[0x14062CFB,0x188AD0AA,0x19327860,0x3860FD1,0xEF8C270,0x18F879F6,0x12447E49,0x1EF91640,0x6142E0]

-

-    // BNCX Curve

-

-    static let CURVETYPE = WEIERSTRASS

-    static let CURVE_A:Int32 = 0

-    static let CURVE_B:[Int32]=[0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]

-    static let CURVE_Order:[Int32]=[0x16EB1F6D,0x108E0531,0x1241B3AF,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000]

-    static let CURVE_Bnx:[Int32]=[0x3C012B1,0x0,0x10,0x0,0x0,0x0,0x0,0x0,0x0]

-    static let CURVE_Cru:[Int32]=[0x14235C97,0xF0498BC,0x1BE1D58C,0x1BBEC8E3,0x3F1440B,0x654,0x12000,0x0,0x0]

-    static let CURVE_Fra:[Int32]=[0x15C80EA3,0x1EC8419A,0x1CFE0856,0xEE64DE2,0x11898686,0x5C55653,0x592BF86,0x5F4C740,0x135908]

-    static let CURVE_Frb:[Int32]=[0x6534710,0x1468DDE0,0x551B018,0x10C78E4D,0x4E3ABBD,0x9ECE6DE,0x2A40371,0x1A0C46C5,0x10A6F7]

-    static let CURVE_Pxa:[Int32]=[0x4D2EC74,0x428E777,0xF89C9B0,0x190B7F40,0x14BBB907,0x12807AE1,0x958D62C,0x58E0A76,0x19682D]

-    static let CURVE_Pxb:[Int32]=[0xE29CFE1,0x1D2C7459,0x270C3D1,0x172F6184,0x19743F81,0x49BD474,0x192A8047,0x1D87C33E,0x1466B9]

-    static let CURVE_Pya:[Int32]=[0xF0BE09F,0x7DFE75E,0x1FB06CC3,0x3667B08,0xE209636,0x110ABED7,0xE376078,0x1B2E4665,0xA79ED]

-    static let CURVE_Pyb:[Int32]=[0x898EE9D,0xC825914,0x14BB7AFB,0xC9D4AD3,0x13461C28,0x122896C6,0x240D71B,0x73D9898,0x6160C]

-    static let CURVE_Gx:[Int32]=[0x1C1B55B2,0x13311F7A,0x24FB86F,0x1FADDC30,0x166D3243,0xFB23D31,0x836C2F7,0x10E05,0x240000]

-    static let CURVE_Gy:[Int32]=[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]

-    static let CURVE_W:[[Int32]]=[[0x162FEB83,0x2A31A48,0x100E0480,0x16,0x600,0x0,0x0,0x0,0x0],[0x7802561,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0]]

-

-

-    static let CURVE_SB:[[[Int32]]]=[[[0x1DB010E4,0x2A31A48,0x100E04A0,0x16,0x600,0x0,0x0,0x0,0x0],[0x7802561,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x7802561,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0],[0xBB33EA,0xDEAEAE9,0x233AF2F,0x1FADDC03,0x166D2643,0xFB23D31,0x836C2F7,0x10E05,0x240000]]]

-

-    static let CURVE_WB:[[Int32]]=[[0x167A84B0,0xE108C2,0x1004AC10,0x7,0x200,0x0,0x0,0x0,0x0],[0x1E220475,0x166FCCAD,0x129FE68D,0x1D29DB51,0x2A0DC07,0x438,0xC000,0x0,0x0],[0xF10B93,0x1B37E657,0x194FF34E,0x1E94EDA8,0x1506E03,0x21C,0x6000,0x0,0x0],[0x1DFAAA11,0xE108C2,0x1004AC30,0x7,0x200,0x0,0x0,0x0,0x0]]

-

-    static let CURVE_BB:[[[Int32]]]=[[[0x132B0CBD,0x108E0531,0x1241B39F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000],[0x132B0CBC,0x108E0531,0x1241B39F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000],[0x132B0CBC,0x108E0531,0x1241B39F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000],[0x7802562,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x7802561,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0],[0x132B0CBC,0x108E0531,0x1241B39F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000],[0x132B0CBD,0x108E0531,0x1241B39F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000],[0x132B0CBC,0x108E0531,0x1241B39F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000]],[[0x7802562,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0],[0x7802561,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0],[0x7802561,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0],[0x7802561,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x3C012B2,0x0,0x10,0x0,0x0,0x0,0x0,0x0,0x0],[0xF004AC2,0x0,0x40,0x0,0x0,0x0,0x0,0x0,0x0],[0xF6AFA0A,0x108E0531,0x1241B38F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000],[0x3C012B2,0x0,0x10,0x0,0x0,0x0,0x0,0x0,0x0]]]

-

-    static let USE_GLV = true

-    static let USE_GS_G2 = true

-    static let USE_GS_GT = true

-    static let GT_STRONG = true

-

-}

-

diff --git a/swift/rsa.swift b/swift/rsa.swift
deleted file mode 100644
index 1c6ac27..0000000
--- a/swift/rsa.swift
+++ /dev/null
@@ -1,323 +0,0 @@
-/*

-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.

-*/

-//

-//  rsa.swift

-//  

-//

-//  Created by Michael Scott on 25/06/2015.

-//  Copyright (c) 2015 Michael Scott. All rights reserved.

-//

-

-import Foundation

-

-/* RSA API high-level functions  */

-

-final public class rsa_private_key {

-    var p:FF

-    var q:FF

-    var dp:FF

-    var dq:FF

-    var c:FF

-

-    public init(_ n: Int)

-    {

-    p=FF(n);

-    q=FF(n);

-    dp=FF(n);

-    dq=FF(n);

-    c=FF(n);

-    }

-}

-

-final public class rsa_public_key

-{

-    var e:Int32

-    var n:FF

-

-    public init(_ m:Int)

-    {

-        e=0;

-        n=FF(m);

-    }

-}

-

-final public class RSA {

-

-    static public let RFS=Int(ROM.MODBYTES)*ROM.FFLEN

-

-    /* generate an RSA key pair */

-

-    static public func KEY_PAIR(rng: RAND,_ e:Int32,_ PRIV:rsa_private_key,_ PUB:rsa_public_key)

-    { /* IEEE1363 A16.11/A16.12 more or less */

-

-        let n=PUB.n.getlen()/2;

-        let t = FF(n);

-        let p1=FF(n);

-        let q1=FF(n);

-

-        while true

-        {

-

-            PRIV.p.random(rng);

-            while PRIV.p.lastbits(2) != 3 {PRIV.p.inc(1)}

-            while !FF.prime(PRIV.p,rng) {PRIV.p.inc(4)}

-

-            p1.copy(PRIV.p);

-            p1.dec(1);

-

-            if p1.cfactor(e) {continue}

-            break;

-        }

-

-        while true

-        {

-            PRIV.q.random(rng);

-            while PRIV.q.lastbits(2) != 3 {PRIV.q.inc(1)}

-            while !FF.prime(PRIV.q,rng) {PRIV.q.inc(4)}

-

-            q1.copy(PRIV.q);

-            q1.dec(1);

-

-            if q1.cfactor(e) {continue}

-

-            break;

-        }

-

-        PUB.n=FF.mul(PRIV.p,PRIV.q);

-        PUB.e=e;

-

-        t.copy(p1);

-        t.shr();

-        PRIV.dp.set(e);

-        PRIV.dp.invmodp(t);

-        if (PRIV.dp.parity()==0) {PRIV.dp.add(t)}

-        PRIV.dp.norm();

-

-        t.copy(q1);

-        t.shr();

-        PRIV.dq.set(e);

-        PRIV.dq.invmodp(t);

-        if (PRIV.dq.parity()==0) {PRIV.dq.add(t)}

-        PRIV.dq.norm();

-

-        PRIV.c.copy(PRIV.p);

-        PRIV.c.invmodp(PRIV.q);

-

-        return;

-    }

-    /* Mask Generation Function */

-

-    static func MGF1(Z: [UInt8],_ olen:Int,inout _ K:[UInt8])

-    {

-        let H=HASH();

-        let hlen=HASH.len;

-

-        var k=0;

-        for var i=0;i<K.count;i++ {K[i]=0}

-

-        var cthreshold=Int32(olen/hlen); if (olen%hlen != 0) {cthreshold++}

-        for var counter:Int32=0;counter<cthreshold;counter++

-        {

-            H.process_array(Z);

-            H.process_num(counter);

-            var B=H.hash();

-

-            if (k+hlen>olen) {for var i=0;i<olen%hlen;i++ {K[k++]=B[i]}}

-            else {for var i=0;i<hlen;i++ {K[k++]=B[i]}}

-        }

-    }

-

-    static public func printBinary(array: [UInt8])

-    {

-        for var i=0;i<array.count;i++

-        {

-            let h=String(array[i],radix:16)

-            print("\(h)", terminator: "")

-        }

-        print("");

-    }

-    /* OAEP Message Encoding for Encryption */

-    static public func OAEP_ENCODE(m:[UInt8],_ rng:RAND,_ p:[UInt8]?) -> [UInt8]

-    {

-        let olen=RFS-1;

-        let mlen=m.count;

-        var f=[UInt8](count:RSA.RFS,repeatedValue:0)

-

-        let H=HASH();

-        let hlen=HASH.len;

-        var SEED=[UInt8](count:hlen,repeatedValue:0)

-        let seedlen=hlen;

-        if (mlen>olen-hlen-seedlen-1) {return [UInt8]()}

-

-        var DBMASK=[UInt8](count:olen-seedlen,repeatedValue:0)

-

-        if ((p) != nil) {H.process_array(p!)}

-        var h=H.hash();

-        for var i=0;i<hlen;i++ {f[i]=h[i]}

-

-        let slen=olen-mlen-hlen-seedlen-1;

-

-        for var i=0;i<slen;i++ {f[hlen+i]=0}

-        f[hlen+slen]=1;

-        for var i=0;i<mlen;i++ {f[hlen+slen+1+i]=m[i]}

-

-        for var i=0;i<seedlen;i++ {SEED[i]=rng.getByte()}

-        RSA.MGF1(SEED,olen-seedlen,&DBMASK)

-

-        for var i=0;i<olen-seedlen;i++ {DBMASK[i]^=f[i]}

-        RSA.MGF1(DBMASK,seedlen,&f)

-

-        for var i=0;i<seedlen;i++ {f[i]^=SEED[i]}

-

-        for var i=0;i<olen-seedlen;i++ {f[i+seedlen]=DBMASK[i]}

-

-    /* pad to length RFS */

-        let d:Int=1;

-        for var i=RFS-1;i>=d;i--

-            {f[i]=f[i-d]}

-        for var i=d-1;i>=0;i--

-            {f[i]=0}

-

-        return f;

-    }

-

-    /* OAEP Message Decoding for Decryption */

-    static public func OAEP_DECODE(p: [UInt8]?,inout _ f:[UInt8]) -> [UInt8]

-    {

-        let olen=RFS-1

-        var k:Int

-        let H=HASH()

-        var hlen=HASH.len

-        var SEED=[UInt8](count:hlen,repeatedValue:0)

-        var seedlen=hlen

-        var CHASH=[UInt8](count:hlen,repeatedValue:0)

-        seedlen=32; hlen=32

-        if olen<seedlen+hlen+1 {return [UInt8()]}

-        var DBMASK=[UInt8](count:olen-seedlen,repeatedValue:0)

-        for var i=0;i<olen-seedlen;i++ {DBMASK[i]=0}

-

-        if (f.count<RSA.RFS)

-        {

-            let d=RSA.RFS-f.count;

-            for var i=RSA.RFS-1;i>=d;i--

-                {f[i]=f[i-d]}

-            for var i=d-1;i>=0;i--

-                {f[i]=0}

-

-        }

-

-        if (p != nil) {H.process_array(p!)}

-        var h=H.hash();

-        for var i=0;i<hlen;i++ {CHASH[i]=h[i]}

-

-        let x=f[0];

-

-        for var i=seedlen;i<olen;i++

-            {DBMASK[i-seedlen]=f[i+1]}

-

-        RSA.MGF1(DBMASK,seedlen,&SEED);

-        for var i=0;i<seedlen;i++ {SEED[i]^=f[i+1]}

-        RSA.MGF1(SEED,olen-seedlen,&f);

-        for var i=0;i<olen-seedlen;i++ {DBMASK[i]^=f[i]}

-

-        var comp=true;

-        for var i=0;i<hlen;i++

-        {

-            if (CHASH[i] != DBMASK[i]) {comp=false}

-        }

-

-        for var i=0;i<olen-seedlen-hlen;i++

-        {DBMASK[i]=DBMASK[i+hlen]}

-

-        for var i=0;i<hlen;i++

-            {SEED[i]=0;CHASH[i]=0;}

-

-        for k=0;;k++

-        {

-            if (k>=olen-seedlen-hlen) {return [UInt8]()}

-            if (DBMASK[k] != 0) {break}

-        }

-

-        let t=DBMASK[k];

-        if (!comp || x != 0 || t != 0x01)

-        {

-            for var i=0;i<olen-seedlen;i++ {DBMASK[i]=0}

-            return [UInt8]()

-        }

-

-        var r=[UInt8](count:olen-seedlen-hlen-k-1,repeatedValue:0)

-

-        for var i=0;i<olen-seedlen-hlen-k-1;i++

-            {r[i]=DBMASK[i+k+1]}

-

-        for var i=0;i<olen-seedlen;i++ {DBMASK[i]=0}

-

-        return r;

-    }

-    /* destroy the Private Key structure */

-    static public func PRIVATE_KEY_KILL(PRIV: rsa_private_key)

-    {

-        PRIV.p.zero();

-        PRIV.q.zero();

-        PRIV.dp.zero();

-        PRIV.dq.zero();

-        PRIV.c.zero();

-    }

-    /* RSA encryption with the public key */

-    static public func ENCRYPT(PUB: rsa_public_key,_ F:[UInt8],inout _ G:[UInt8])

-    {

-        let n=PUB.n.getlen()

-        let f=FF(n)

-

-        FF.fromBytes(f,F)

-        f.power(PUB.e,PUB.n)

-        f.toBytes(&G)

-    }

-    /* RSA decryption with the private key */

-    static public func DECRYPT(PRIV: rsa_private_key,_ G:[UInt8],inout _ F:[UInt8])

-    {

-        let n=PRIV.p.getlen()

-        let g=FF(2*n)

-

-        FF.fromBytes(g,G)

-        let jp=g.dmod(PRIV.p)

-        var jq=g.dmod(PRIV.q)

-

-        jp.skpow(PRIV.dp,PRIV.p)

-        jq.skpow(PRIV.dq,PRIV.q)

-

-        g.zero()

-        g.dscopy(jp)

-        jp.mod(PRIV.q)

-        if (FF.comp(jp,jq)>0) {jq.add(PRIV.q)}

-        jq.sub(jp)

-        jq.norm()

-

-        var t=FF.mul(PRIV.c,jq)

-        jq=t.dmod(PRIV.q)

-

-        t=FF.mul(jq,PRIV.p)

-        g.add(t);

-        g.norm();

-

-        g.toBytes(&F);

-    }

-

-}

-

diff --git a/testVectors/mpin/BNCX.json b/testVectors/mpin/BNCX.json
deleted file mode 100644
index 7cf034b..0000000
--- a/testVectors/mpin/BNCX.json
+++ /dev/null
@@ -1 +0,0 @@
-[{"SS1": "1520a952de349f533b6aafdf89373840c6cedb5d80c10cbb77fd2977d1260f261bc1aab33387ea29d5a229d03b86b755a1cd958b5465b765789d45d69394254309dbeca19eb8d87e2b68b3b3313d518da6af44cbf7dc99db73345236e0f69ffb049ae528f8ea5f1f431e5292b50206951e0869e471140dbd044533d74c8f35bc", "SS2": "0b5dc395464513d1b8456fb4b1e131855a171693043115db8b9213fc5cb6ab060706ddf77a2d716129f095627102642c916f0528abc8c613dc4e3efc3685407206502735e18685ca4870db8dfaa6bcf65c0ca58426841ce84686b495a2a07f61167068abb790a36d2bd624a6ab2a7de51845d2b5adc990c1a5a339081607d01c", "DATE": 16574, "PIN2": 888, "PIN1": 888, "SERVER_SECRET": "1c73290d1a444dbf7d64d5ef22b152165f84b6bb1bbfb5b961de08294d7194fc0bb8652116b2e5a237706de08731a6b3089cad532a8fb1faa06a1deb36b037e00bcfcdcf98cd043a26cc6ee4b551c6307c57eb56ee5c005fd92d08598db9c47d0926edcb97b370b4542d5bb2ce4fd600b4657ec6abb3503e4172af59cc94d4a0", "SEC": "0402ecbb873cfd1a27d39d28a3e8cf25b9e11b8825aaea42874440e21505a0f5291745d9a15fc477f2228374bdf6a67633a3eb428f6622376ec4ec9522b8a75ee7", "TP2": "04185f9348a8dc152fe4c5c9a3eafa39b8d49302b7c380b26eb50d7a855aef1c340e08b35442a02d2eaade3b1cc4a502b3cfa1532eecb7ea9f2664bd4b86123187", "TP1": "041a5cca30f0a4ce9ebf97052fed980adcba9d486dbe688b4793779f46e0269e8e01239cad9ab5205cfa2b679b9f63c8def786939ffa97e2a8f9d16ddb4f23a731", "CS1": "0401435d98ba070157b3f808c8f07a8ed7719f2717ec65baf631cd8d068a7a43930e9e700a8335caa36bc28c5c673e9fd132eb9b40c90cb66675b049860b07858e", "CS2": "0414130490c24aa99fbc55f242d11ffc5ffdf5c9c3f2430e24a23f068cb10fb6c405ded7a269a807ae2771a8c5984ec3d370a7cc565541b31dd44cd2cd3156b56d", "HASH_MPIN_ID_HEX": "d12467cfb19e88fa1af70615874ad467163a79b3bd666fdaf9ff3a4e76871967", "TIME_PERMIT": "04227accf008a0c0c10a27eb4ae833ef056613b3964c2d4f3b9f7a2dd84ec6a7c819eaa5b37faf57016f5806ac236549c39098bfd6ce50e0a2d1e8f7ea64ab838e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33345a222c2022757365724944223a20223635303366623332333137346332343639353133636337393930346263623435406365727469766f782e636f6d222c202273616c74223a20226166666366356237333965666238386165616337656464396335663961643631227d", "TOKEN": "041739675948c978b2b4ac4b380d93783a4c7482f812b645b26f51dd407bf9c5121bb2cebb06e9b3c5f96b5d6619b52194d8b02e7df5de527497bc42bbf6aefbfc", "U": "040c11c1d9d9202c861ab7920823cb0c83af6bd679fc52ec9604099fbb2db78a8908b7c4d769e9d90f7d9b655526663a9e7bf82ddebb3626c6be0b20464dc2dc34", "SERVER_OUTPUT": 0, "V": "040b8ad73e1199b1e3a0d767accaf340fa1014dde6c5a188523f74c8f4d1318c15028387e61f456f5cede275edb1e04a81bf9214779a5dfb6731f60b21ff46f12c", "Y": "235e6cd2bac4f802c13c6513bce1c11cad6e51f45b2516cc8eb7edc256e5a203", "X": "064bcba79105dac17aab45a810cdc802fcec526fcd4b878f18407a0017481413", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:34Z\", \"userID\": \"6503fb323174c2469513cc79904bcb45@certivox.com\", \"salt\": \"affcf5b739efb88aeac7edd9c5f9ad61\"}", "test_no": 0, "UT": "04155e8411542f9a2d7818c43e539d994f99dd9b8158bb2373704834f2a27fb59f116341daa21cedddb3d4393bfaedc2cfdf2c0983d280e87a9b0e01043bab9557", "MS2": "2243a7cc0e5f776b5ca1426d481a1ce565fded749f242b46f0a14b09c7de37c0", "MS1": "0bc2261afc713cd48b8047112ade92077067c31c6e0a6d732c7d77ebdd0d5956", "CLIENT_SECRET": "0411e119359451da0b6c6f17eceb64a20598c33b213dea3b6891eadd131200c49712a352a5f8ddb3260667758b78ac7f2ed8da5b80926e0abfbaf89a8caed920b3"}, {"SS1": "0f468b9986919bdd7c2d5b1805b0281264fd9e33db0b658b065966733b78d36f1eb4f5981b41b7da15f1386ef10dab2cde16832131374f9fe8b707176c8f5c981c3b3c79218ab6f66746644ae7c321bd466248562832091eeaab9f781bb17378227ce7c682a39864645840036e21437c7132434bae53b3dc9e72bb0c2d2189c2", "SS2": "2171885f0771519da9f347fc923f947c6833a9d5d084005b906856262dd94d7b1ed457dad2ffa72cbc478b4031e7e2567c0ddca977bde0b494dec929f02e517b09aba69dc3f41588db9accfe370501879568b25c91a9f4152ee3d416dadacf481e4ac7c1cf2934e08cb8331a5782ca1cdaf3a83981614acf9b6c6780e7ff0f77", "DATE": 16574, "PIN2": 5299, "PIN1": 5299, "SERVER_SECRET": "03e47ee3315b9cbb277468ed5c488f2b0b3a262b15e628e0d5f4f129e64a1fad0cc84af7acedd5225e7d40df5155db23f4bfa290adff6ca31c4884488c2d55a10be2b0f01e7de752201c4090a3115322e0a76d29c5fcacbd4d049b50f0089bbd1235b5935d93d9c50b521b2ea8af29ac5f52e40125076e97d1395d1fa22b21f2", "SEC": "041abd94a1806a932a0281f8b71d97273dfa73a3b73e41725973e4269944a48457037943bf74f29f9652316a0802ffe914bf6dd721f356caef4fb93cf2a68795e0", "TP2": "04076852c9d627e10361db7a5d1338308c5d92312ddaa4996d4e3767b7bcc6eaa621c9a69d1264329cdf17007dffea8b8053a4dda479dafc775ef059f85add5230", "TP1": "0405c9437dbd17780b5fff9c12230b048a14c14d5f4d51e415c67d51e995f73a5b1a50c5259b6fdf92b704aca052670dd142e48992891b052d6e59ecc142be6a37", "CS1": "0412d3a065010d42084337a9d2e869cc44d7ce84b51c08a1f78cf7522c487f377b1810af8fb5c69ef5585c39eedd462fdf21681c970017aea3539eb1fc46136805", "CS2": "0420a2d7bb34dd1076fbe3ec090b0d33dba435ed26a4ca385e0a443ee4db9f13ed065e9d908a5e174a97335cba95866b5448ce53fae031d22e2102ad45b1d7df1b", "HASH_MPIN_ID_HEX": "55a884c2cf6ea921cf3238a9d489b22c68e096d96a021ceff6f8c220798229f4", "TIME_PERMIT": "040340b91db12b2d3b403227d35043dbccdaab6ebb62955983bd06e5db8822b0261678235685c4cbb5a4169a6390481470fb788dc91a69056a4862ee3697094cad", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33345a222c2022757365724944223a20226330323037316639626664303631353932393935363761383633383363343433406365727469766f782e636f6d222c202273616c74223a20226263633732346535636561373564343065316136633334633933633164333239227d", "TOKEN": "041d50f62c5bf35aad38b7cbd91a919919ff6abb5f7e6dee83450adc9b4900235320c1f4eb7bce4d14143d36c7b362aeed90afb48e84d83bee1c4cc133abf68adf", "U": "041a21408eeb64776ebcce3f814485476f55882cbd797fa6dfbeb6ce5c506081b209308b70ba69efd2594bbb88c2e09bdef9b9b3e49437f2f5f296dc6853661954", "SERVER_OUTPUT": 0, "V": "0405ddbf8a26e7958269f103e8ab5ef45c20cb845cade3041fc98075dd9b50e3d821a67a905a19b694404331986d1ea1e8543b18748efccceb25048584b4b20116", "Y": "1f62d44eb0a0add266210aa2209d3184abc9a9a53d14b6e877291df1d6ff41d7", "X": "104788b501987fbb438213927dc93a4493693d981f350924678f55787c2ffb76", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:34Z\", \"userID\": \"c02071f9bfd06159299567a86383c443@certivox.com\", \"salt\": \"bcc724e5cea75d40e1a6c34c93c1d329\"}", "test_no": 1, "UT": "04047ac3439fe68dc9bab6d4a5511e7770ca1e4dd2a617eb3be500c3c95d669934028e2c0937d7542fd70ea7c623c3181aa832fe3c7160e458f6341c224c5c604d", "MS2": "0d4827f28c094a2c6a29e88c2fa6e36a9aac8e21c9196fb952b26435ac4fe448", "MS1": "1ad3a17e1667901e1e865164eb25480d3dde6d8b350af7ce701f4730f0d26b9a", "CLIENT_SECRET": "040b36db188c8dcd415a9a26e90f9bb043cf7ac0527ca43a5c71bfd95ae9c17c420afa015d0fe3ea8c4da06e9ff70fc444b0ee9f9a1f227baf2687da9e64c2a7a7"}, {"SS1": "21b27fe347dfa66bfb098f848f4a2b474ef9e23d6dce3d6927c8559a0ce901ff20896dbc80ec32c19f6c9d3eb248c397a50cf39bc875c256398ec3d75ec61e520b3bafe5970d46c2671a20ada5a9879f5661bd9f63f5d8fbc0cc56bcd39b9b7a23de3f98dca07e67c7668014e5367a979206b5c98611cfd597319154681daf43", "SS2": "08198a7a3d2820b8987842d2743dbff22daf00078ebd5eaa3983d696f8a3eae91cb1314e7dddf0a47aa4b3570b80368b6573b5062767aaef9a5b9117484d7e5c0ca2f89d23469c747c4ed6cb30dad0000d85926ae5aa6de012ec4d56f35c5cd5231225762c78d43eb15b4d58615191d8302df6f25920ef7da9733bcaf5549f08", "DATE": 16574, "PIN2": 8009, "PIN1": 8009, "SERVER_SECRET": "022802cf792087f376c4b6aa8a980cd569e5f2a3f505b9e0455d3b67c5692d3711301dd42e732d6af6cdd7ba069f51342240b7d6478423ce063c8af04de0ebb70183bead7230e056c34ec775a4fe699bba00772ce5895db260a0a1106cff4b39094e1ecbe035af718f4f00d265bc18eb9cdbc65890ea94f9c95a5e1c8edfe15e", "SEC": "04057389030a78b7b6ea26f59248c37fea17b0e522e3699848ad5301cf1ede99291784540e7418afb2ea6d792fabe2a9b1b04b5871d0a3bc81f4b15d8043d9e283", "TP2": "041de5b1b6e33b2c07743e53b0fc02eb8cf0a480761864dad14966eedf9348dcb21c75bd9a3f56299e814e60ee9e1274eebc18f433cd107de65f5dfe3a67109718", "TP1": "041038ced7b5d89739230f0374851c0319b218c833f55cd09bc253be1077bcd12d11d5edded2d5d4aceb1a13263bda49ee8292f3ecbe07f9e40206da53a4923aaa", "CS1": "04239dd5403d85c3b72638d4a4adcc7bf2046c80b9ac2ad56183025a7caebf18f8101ed98295acffe2ae8444914741aa58eff00aaf0f01828fff2be490c8fe5af3", "CS2": "041f6f4c331a39b7644cf3d7ef6be4ae012bc89223935a23b526d5db5da611af9a10126134ba60e1b2bf01832aa29349c11842153af643a53b6d090dea02865483", "HASH_MPIN_ID_HEX": "935f0d6bd07683250e03081005f149b7bb106a11524733234e5b6516923ce8f0", "TIME_PERMIT": "040f58e86621443f94b7770d0a0916a4a5079748988a98f84bcd253b7044120d96137e6c5b3a331b9e35dfcc6f5991f99b2e7d83f93a4dfb9c118a92a040535e8b", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33345a222c2022757365724944223a20226465666137646565366465633866333161636261383839613731646136623064406365727469766f782e636f6d222c202273616c74223a20223133643563363662393531633931366531653834343434626131376336353938227d", "TOKEN": "042152f07e5fd78a1f843390d41478d2d5f0437285009408f2d63ab190434a83f403fbe78d63da99ed8fdce141ab12625fc36147b48e5a566f3f38a3b7f8b1dc88", "U": "041fb404a10229be4ee993b6d70cf4af1f570b8ab377a07dedf08fcebd02fb44980fd3d85930d15611ba1a2c33015bfbae9ad57757169499066ffd069a1723cade", "SERVER_OUTPUT": 0, "V": "0418bea256f235243219296b7f5e2b0dde4fd54e2d82d80cd7882600756f07d1cd13e4d4b3ec3defcd9e5f45ba110215e3b705534ecbe21d334261cdde1d0a2c9d", "Y": "0a40ff78e525b2bb445a4912a13239942adb5e476f55a0cba5d88eb85b6d40b1", "X": "14fa7ea042f6e80c90c29f031b25233d6122fbf0255a4ae12cd8643c2e9ad749", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:34Z\", \"userID\": \"defa7dee6dec8f31acba889a71da6b0d@certivox.com\", \"salt\": \"13d5c66b951c916e1e84444ba17c6598\"}", "test_no": 2, "UT": "041491587ea612ab06cf8380fd9f4c4865c60069ac42fdc5ffa3077570484f29ed13ff03b544fb28df4143cb89a2f1a01cf2552a621d7b35e2ad9a6a13484252bc", "MS2": "1ea4fc812244b362af1e00ad29a8a20285062ed3df75eb6934b03f733dd8637d", "MS1": "0773c896ecad1274e67f78c45506c5eea2ce4d11b79f650e779c7d5a37d656f4", "CLIENT_SECRET": "0420f67cbe2d0914ea983336afaa737d93e22825578f65d7fd7f6de1550e47eba411d3bdf73908b88a3980e00a37bea16836e7feb5301e02f6c748ff5dfb88a8b3"}, {"SS1": "019a441b3e885442206c4ebda5a811f9e39f7215c2c7494a9271f8174027d7d81381e2c00f01f5ec419985b29ea6313862b57b37708d40e3cce8cd15da76ebd51afd7703019ed8ce53bbadc466831bbf0934868bf0b0ef7b674daf56f8208c9f079af4e6103b4c77e49f3620e1fb0182738f1008befdf51f14f1920fa0e3a7b7", "SS2": "13979da829e50cb10d90168792f0935576bbe606c3b9f4eca4f9859087c16d701f17425a5c08ea5b720e48c43988b3b4a24c8dd88efdc833f3f407b348d0b64719c3a113a1e9a3c75fd037a2dbceb65810ab46a71ed01d102073ee23ea972d1e094cd2577001081dc3d8b33608f7232f2e890487b759fa8bacedc8ec178d78fd", "DATE": 16574, "PIN2": 9236, "PIN1": 9236, "SERVER_SECRET": "183c338d428a1b431460090908981ba162974d3366e920e106647a0518befaa1239e518bd8ac0d0dfdff38e980afbbfe4c8cca7a4df7c80e7a93206540e64d24148a8adbdb6d91a8777d243cc905741e674a216b9830d628469bb44d0a97f93801eeec00b1ac89fe1e41f8995002997c0bebba12a9c5f16f61c8b758069ca7bb", "SEC": "041aa9a4e8ed6fdad96a24cf4b1e542400a80777d2b82c37f8750cbc2be5939c3d04aff95bde7cb335cea825f3a9fd7b17a7b46960f99d0b2f144d54f1a7a889ec", "TP2": "041d9a480dc01508acd380e76853476e409351ac3f5f53792921187703f81519d52162972a19845f4de95267bfea8aa98ed1862864ba99093188b1b58a58fe5dda", "TP1": "041d041c5d8848da82deba27ffe660b0db71aa8ff268186d0defec7cc2593103d31f5cd79818e87cd7fb76b9b888e2882bedaaf254dd2acc1e1dd4746b07039597", "CS1": "040dbb037c6ebade2e1834a15d1f900a7fa526c974b49afebfdf7b98321e6554cc0c7bcebd582600d3510e8ebd43628ae2558a12a7d1ffbbc5b36b84aaf8e9afb2", "CS2": "0405dd5653c55e6b56285b96c627b0b5d19182e306716e6713e7d74d3779f888b60aa7eea6c8c9ac1ee23206d24b63f2a736e4a0e99a05e7f1edf2e150bae894ac", "HASH_MPIN_ID_HEX": "48229e13e1c3180914eab5fb2ad71d51bd42819b105d15084a6ceb27b67b2cea", "TIME_PERMIT": "040844b552d359c4948bb6f682f899eb9be5a4b987521a39c7878d68a8fecec0351b754f5f16396a2e2ac9651054b31f843ebfc610e18ca114026126a01f167e0d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33345a222c2022757365724944223a20226336623261366432326334333063333237393066356633303932646236666535406365727469766f782e636f6d222c202273616c74223a20223330303036663866623736306439396132633736366563343738363162663563227d", "TOKEN": "04175619ead75d0a35c8bc5b363a7b860ba885dd6792da77aad90a84e28e04d89b17acf8c008098af8fa683dbae1f5a21418aa56a6593be85bc62eb4b92778b132", "U": "0417f23a5a7f2a0d73705c1aad04a50cf5383e6bb5bc8f70e754591dfa9608dd3f103707fe6621b2d96c71b67e0f3b7a6c0d9a7e42ccedcbd14570fdb21c1a8afe", "SERVER_OUTPUT": 0, "V": "040d3c4ddd87fb3b6d0cc84806feeb04e97d5a425c0e4f9d57542fbdd93070e02321c76ada3f6f5443e744eb1d07d010a0922f0bba8b7ac38bcd0d869ee9cb08a2", "Y": "0fe1bef7f0c2f00be843cffe52489e800f76bc7f2892d283ace814e4d808d758", "X": "07d69e95baa1873f1d1abc755846a5a2ced5e3ed9a3755fdc218931dc9975258", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:34Z\", \"userID\": \"c6b2a6d22c430c32790f5f3092db6fe5@certivox.com\", \"salt\": \"30006f8fb760d99a2c766ec47861bf5c\"}", "test_no": 3, "UT": "040703a76274cbdf19bdcb64e943d8c6c06769e8c15f275996210a9937490a3a7b2328ac7ecd61cbde145d3896fd9b943f23e46c09910900279dbde4991be081d7", "MS2": "0d1d899d6c396e9415a7ce3520b9000f8f5a5e7d47ae5c739b24b971bb8dccc9", "MS1": "0493c81df73802f88968d6c06c3834ab34cdf740c3d003178cd822e389b9b260", "CLIENT_SECRET": "0401a8a91fba681ed30da9659ac4a09b02a97a6916373a757ccf8902c031ad49c403a5ccc174dee4352ecfa7a439f630fd281c487fa840aa73b169ceb67667c125"}, {"SS1": "1ee4f64244435fac2768c632f7e6e8970e24d0fce21e5012a5bfd0f53ba14e9c0e1674e4d9119fdfa43f312c79594b6d36954628a1ffce8eca03c27d2f25322722d0366d084a8a356be01c5acbb2859efe9c617441c14cb7823fd4197b0fab2e13977f34642ab1fe1a5442edabff21625138348435040f6343c10480f96ea010", "SS2": "0bf923482e8945c8ca68716a5e744e6c8a67551cc35b16b9346f5149e32d3b9706f4a2ff66476452a4323b4d4b24758ab9bbf5f0cf9d7e9a0522d3f9ce78310600a109a9efa30d3b41ab04f86ddc561a00cc9d6a3502abac324dbab1fe42b2dd107ffe6c93c6172de1ca619c17eeeb0d26d52577c2bd4732dd14deb3f23b36e0", "DATE": 16574, "PIN2": 7948, "PIN1": 7948, "SERVER_SECRET": "0a074a16c398ea6b8a55c263766497977efaf5c2dfe22195338b37963dd0a1ad14470fb1f77e83979192697cc21f75552803468ecb447d705401b02aa58a948f10f734727178bce6f079d6d39dc110d87017cece3bed4b57e1284c3acb2dfcfb1e37bbecf67fda8eebe447149042091743195cd15ce2f2048ce753abc3575308", "SEC": "04188a016078f4868432475c62dd5d2328850836c9f7b6722bdd44eedd7b00b2e914b683bb574dcbcc2eb51b7c249b87c378aface89b51f21deda7f9d3f650cd17", "TP2": "041c26065697b7922ea6244242728d606db07670863cd64cabb0d7a9bd23f8232d04069e1badf46d4c3a5983ffcce8a78b57b190eb14c2a81d917b1ca6bac3a23c", "TP1": "0411c27ec8ef5e74f2ee340c5491d07ecf9513a26e92896aa1abbb8e53d1403f7b1365a2148a432fce451ab7e7b5b9c66dc2412355936e5b0144b513414602ab42", "CS1": "040362c73ee7435cf8a78f5c700daf6b9a8404f0c62e2340d4168f84b3bab3e1301c036a644eb8e626ed310a595219d96fc000a0084f85b144c0f06f713b66a58f", "CS2": "04227bf99836c8daa5c0d15169f33edbf29e16c56175b7a0cafdc003432116ef960399c375479aa8e1fedb5c4612344da2bfec4dfbe8653a7a5b806efa51cf8e36", "HASH_MPIN_ID_HEX": "eab4e9530b180aa597ec32a125245d8fb6699da0b3fbebd501e574eb961a3f39", "TIME_PERMIT": "042337defa34c32a3881b2acf801cb935bc382a1f867bf0eec2f1a30a8317f54370582b3a7fdc57a68f6460101884f2a76d90276f19fb56cd66c2043ae4b1a09ee", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33345a222c2022757365724944223a20223836666538343435643066336337333066626665613330646235343035636436406365727469766f782e636f6d222c202273616c74223a20223638363566616361386230303135373064346236376562393462646239323762227d", "TOKEN": "040ae1365789a7381ff442a19ff09a25cc3d31336da12a27f55ba80bb29401abb91607dff8fcf6be38d984c151f3d752a19e81b6e90bbf4385fe678a3e16daaf18", "U": "041108ccf4589d7766ef0ac969f8139525393745ddb18c10a42ab2a325f0287b111bda113c3a09e91d918ec5826ae9d6878697b217aab7b4df4e817f64c3784c41", "SERVER_OUTPUT": 0, "V": "04156927e530f9afc8f0232f99893d84f26d890144698718ce5ad54b717547b67f2252ea5f30b27f3e7b8613c96670f3ac36649461076c3b4bcbc40001f2341275", "Y": "183bc2bde80fba19d0f1ea345068acb2c856fdc8f0699f5051277d7b45f438d6", "X": "0a8a35c4f3ed665bfba479a6a08a125e6a3e41561fb6b11a158ba7ee5c3fc23e", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:34Z\", \"userID\": \"86fe8445d0f3c730fbfea30db5405cd6@certivox.com\", \"salt\": \"6865faca8b001570d4b67eb94bdb927b\"}", "test_no": 4, "UT": "0414498cfa890a2a68cc9aa8041184cad78c93ec04c38409200762f6513513a3462168adfd3f92da74340bce5cf4f35be2259ed7511d1cfabee1484d690f747ceb", "MS2": "2016e100f00700bc0bd6becd5597ad9247907c35ee32338775c6fdd9dcdca745", "MS1": "21c0f1ca115242eb0bb0984ffdf1e1488eba3093ec70ebdd014dde253e203a4e", "CLIENT_SECRET": "041320c0d639bdecb59089e3bb1dca7a34268741f480ab1a184d1b5719805d7cd10e8eedb02d56ba2d3503ea4f13e757f074759a9def22d948e17de3bad79f155d"}, {"SS1": "1b6f46bdee6acff8508a6abdc397dd656677e1e4f3036570a848155e32d84ee605ed99e87230e8e82c9ab3b1546c57dfee6e09f2907e0374728eb12514ac75110b2e551a4cf86dfcb85303832f67c8e518dcb64283678873a756ab53c18c58f51ca355bd2736824fa3346372cc76b48802eae6e85aea0ce052fb7049e1f005d3", "SS2": "0587a37e99aec3d88d75395f180313f41d97afd5296f5bdfdbb31e0f4db7069005d7671c520bb1d4559e1f6ae9736227ab780bf51781b9dd07678de732214ab2139912c4f36ce0dcf76fc417e4721e3b14adf57776764b8ce54e372c9859060f1cca749a6b0411b609360a3e4652d320dd60bb0e585a3abcfcd5a46f947221f0", "DATE": 16574, "PIN2": 1463, "PIN1": 1463, "SERVER_SECRET": "0c336c8babd0b3bc6ec5c7f1cafa17fea49cb1a8076e2ac40b585008f53e8c2d07a06d67c3baf6fe2c6ee58df0124373a0c607165c74f469514b559d9b5ec16a09693fe3af5a8ab0329b49124f41b6771dc6f7194c2934e6bec42fc9db274aec187813c02e5118cec839d3f9d57e5dbcb5e70f4c113f9a366dab425e88b9251c", "SEC": "040b5f13e43d0e152c45754f8dcdd241f55549c86c46567749ded57b2ce29c39e00a01b1fd1022705d6faa2a6f1fa6cd4e9dcaf16270b7630d3a6747378c900721", "TP2": "040c6fa0a22d35dd840b2bddab6b4a15d97b038d4056d3a961c29c1e57158056381e974ea8dd04e08d418948112a60c17ce91c66488984818a14206c32b1d755a6", "TP1": "0405b721c01c1c32091a633887f276c0bd8dd94ef7282ade8031fa1e4b2749442705a656af0aa44f5a2219dfed66339868437678e056349801a437afcbfa7cb429", "CS1": "041c674ed4190bdddb998759f680bc170f75013901972099f93f351ab9316d718d0b856b331c4a0a003be14a7845a76598ab58e144716015842dde9b231439868c", "CS2": "040c39a9aa1327bee91f9f753db352d4ff787eedebac6fe997f08d40cbc53f1ac20811b41a1b67b5f09452723de8086b42a10dd40e6109d4e203e487cf7414088e", "HASH_MPIN_ID_HEX": "e9e2c4ca2c3b579f0ebf4a536f4d7592162446287c88d20911264966102e34f8", "TIME_PERMIT": "0401155572f8f4ad5f54c64592b5c0ff55efd9204b57bc248dbdfb1be8b845acf3089c95534a1693ff02ae81171c113bc77ab09de27083e7bc95b59b0436fd5047", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33345a222c2022757365724944223a20223434623963613539396461306330376134323965306364356164363237666338406365727469766f782e636f6d222c202273616c74223a20226239636433323066623865376530646331363036363931363163303763633535227d", "TOKEN": "040ae7d1376edd21caec2488262f5a76da64794502eb6c91ec24b9a23c936d3c4c0a2dd45f31fd2d6f2b7e13f8c51c5929e7044eb10d691f2a40144dc6302b13a7", "U": "04103e7ba05ba7f6eb06d9eaaa6d5b0939aafb6c72ce417d39572283bf42b0e8d8112c5f64c15fd008a838b40ca7812246a29e31954d08f021f60ded0e33043ca7", "SERVER_OUTPUT": 0, "V": "041c2f73a4bf39d7e3f1eafd400499127efdcefadff8734d8ee061bc2c052fe1b12258ebd8f60861937052b8a86360e5a1a0b5ec2970fbd2f424d03a6b7c5d6ee9", "Y": "100189ca8769a2e2f832dbe8488e0da582b60e71b47290302445688bf0c965e3", "X": "023e85881c4d8d4d9193f9653f1de04d8aae3fc167cc59a00addd2acc48edc22", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:34Z\", \"userID\": \"44b9ca599da0c07a429e0cd5ad627fc8@certivox.com\", \"salt\": \"b9cd320fb8e7e0dc160669161c07cc55\"}", "test_no": 5, "UT": "041d0207f5a3a3f1229bad924f50e229a9acdd8432ef3236a830d813241f2664f804f4dd5983e55066504298808af93e92b8f1b08947166ade9f7e115410095a3b", "MS2": "17d927e498f0fea9c5d712c93416834a1eee4224d451d48d5b41c29fa70e01bb", "MS1": "10eeed159fc3e9d044dab63c56c49f1a99f831e67d2f6a9e15649688f8076bb3", "CLIENT_SECRET": "040ea0a2ea39d57085cfa10ba2e0562f5230c9821e1b691bfaa87ca826a5d2618222019bab9704ef29085e70bb1b61e39b2ce2f66b5f3aadf9f22818053af7e543"}, {"SS1": "157b14bdd0d3473b25d4a5d67d17db205178add1e2a297f7aa4c9b348acdd96a04d5d5dac5f0684133948f7715c5b1ce74ee3b8c6a8e423c4e2bc370b05824f0211e5e4dfdedd92e0a74cc91e76074cc8cdcb4062a791b1e4cbc44de9b77297c06d74ba2099317a3c9acfda4fb9a60babcb641a8010c94e6ec48af7c19bf79a3", "SS2": "0a9d1ed983875415facf49a6f02dc28908c8ae96b47e31995f07211fee22b00b0f6a1017ca12a517c2a73fee8b8a28eab2fb913bdce9267c84b590e1c9a8c5be18132a5d92959868075563f2440d33a53e78e7d9183dfdad21481906c382e6d121a69e8297190256b08d9a126726703ce0431766d3667a71947505d99c39abf5", "DATE": 16574, "PIN2": 4669, "PIN1": 4669, "SERVER_SECRET": "224ac6bc9d4a546ff386a7716ac9a41c5b7e0f713a83967241d26f0f6c1129701b455ffde5e6695a8fd04d51e60488e205cb3b8f4dc356798c96636581456d4f189ef17a237e43cc303f85daf17307e5ff05720dc80958e2622786ceddbb590c23acbedc1d403693198040869d27ee21586893de4a9c912c010349cb56be4d6d", "SEC": "0410f6d7a8c4bfa1a8143e441ec1d9cc5eb843b84f9ec82c01364ea8fcd1e2517105dfc06348559d886a92b22a4cc35df52e82b2cca4725d7215cf29846d9068c9", "TP2": "04137c6b8ff2f13dbdbd4070b3f255f30267a9397340fa1682b04dc65e468765502211e9026b11466679bc39661c8676f63dd4c53bc4624d015bceb57c5fc82858", "TP1": "041ff46177adac17df37f3ab5ab8c48c97ece2311f1a1d593a4e656f935776f9f70658779e3010e44fd8cef31af1faae079e40a51503fd42dfd46c9b280748aece", "CS1": "04066ae71ccb707233e1d4f4bc288b1ba838c9e7483a5ed0d0b3bae30c89e2527b1098823f188abff8eddbd46c17a6d074730288c2ba36ce678bcc4d1404e1ff0a", "CS2": "040d5f8f5ca6aeb16e3955f2bfd1f9a8a4b9d7028233d41666442ff4ab6de06f2609c69e0c3c741145d2802859b132aa511ad7fe3f386b74449529ec680ca8ff23", "HASH_MPIN_ID_HEX": "b684b908a36cdb11caa3f7ff3aaa3803982fb494162e3570e6a80b821e63d36d", "TIME_PERMIT": "0413e6355e2fb9f1339c20a080835eac9503881d34590c78bb0c037fbf815f17d9204e04056b68bed0ba41d4d412e2ce047134add57c2527d764ed963d9db2adad", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33345a222c2022757365724944223a20223431613839386362363566646530303331373433393565383237363862303362406365727469766f782e636f6d222c202273616c74223a20223538373937353363623336363337663134656339393164383435626630363132227d", "TOKEN": "040fc4de63abbcb51a04bff2f296190dce7eb7c9987edee7eca5db4278518ac7c71c6192111e25af1d89763c8c6729cabf12216cd9bd8628e609c0f87f7b718ef9", "U": "040f71ce92ef2fd8e4f66db7417b6fdfceb3644a4c41f07bb490e0b3ed524244180b7c512cf9c511bc305d4c1bf6bf268727d00760d34500caec0e6b4e09922afd", "SERVER_OUTPUT": 0, "V": "0416803454320557fb14b26cc8715a4db95c3b5912776adcc6e67043d8f5ddfaa415205c9f47c8dbf23eabdfc36c1ddf8807d84bca36de5aa122eca80871411b86", "Y": "13ed4a35797b1ddbc6f0cafe2d838bf7067f2a80fabae4e2653e52bcec97d699", "X": "13cf2080bb21ee069256391d3d873bf2b763b3a6091a21d6efe8d84d819d6421", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:34Z\", \"userID\": \"41a898cb65fde003174395e82768b03b@certivox.com\", \"salt\": \"5879753cb36637f14ec991d845bf0612\"}", "test_no": 6, "UT": "04213d409fda21346b2c9b9c9ef5b9cfb72de7f4338ceabef411e5b615a5b38d951ef4570aabb984bf0cdf5903abb45a2dc85a9213b5de5d5583659e70f241e6d9", "MS2": "10b0d5f70d6df2486d6b90652d5e07f558b2ae1069cf08775991c658365329ac", "MS1": "1920c5a556df7c1b2888a6e249a16239ad2918bc73eb1e3123bf28e78e021e23", "CLIENT_SECRET": "040525996f1a9b1b15220662eff4ce3839fec17ba56990ea961104edde7a6ea05922d06e8bb482acf017b69da967ff372075d699599ede766c79a6c2ab5b3ac12b"}, {"SS1": "23822e2afba3617824294e5045f340376d5a6def202b3a3bc34d92bc0b9895170844cdc4e56515a6d3f2cb277aeb38c0d6e1c66477c5b5655678c2f1d2c035ba037b72d8fb714fccfd69051d7f7af2d8198fa90c6d2e91b877940ef3cb05800e0d0eda45d97b19d3d1082e692cbda6089bae132250682ad448584741ced02f7f", "SS2": "100b500226c822d0b106afd6f0f00127f9669e78d84dae2f6fd4a82e543967ad0dd61190959285677647f9235a1dabeca83cb8af533a8ca3fad07ccdf1fb3ccb00084b93954be03410133a73c953fe62db6d924de5c2dde39ad7ede938bd684f097a9adecd5be3d64de34a64ff93c5c369b3e110064367cb03170533b9823daf", "DATE": 16574, "PIN2": 3269, "PIN1": 3269, "SERVER_SECRET": "0709c6699cbfa6ea7dccac48197269e8368f4ff593501a554169500f7a5f3cae22ce9601f032529a3054eff2b7248a84bca013ef3b2ffd8955ddfbc3ff006be11e047878f4d8145781376ff63716dbdcb705c75d6a895ca867688e7e736b26850825d0363abd8ee47683d46d6f651fe3298a7f9a70c9e9324498e7e6f6055b7f", "SEC": "040a091aa68f787dba32ec3a8cd999576a21969c97de5f0e7e8272f15cfc27dd6b01c307cf78f8240b42929716020a8c121317f4d47d3157f6cc558053a716ed79", "TP2": "040c4822278f591c08053ee5a1878255a7f5fdfc1e182e1015e71f291a350d97d722e8d553b505fffec365c02e46debfdd657a36b1d482155ae5be41850518032d", "TP1": "040b4526a4e80e115eed9cf155bb6c757d5355748b8bbd78a34e0601ca22882a1d16213be346ea0ffb547bd1ec72f2cce60329aeefbf7d5aa642b6e90e40e5e57a", "CS1": "041082ad98e1cff3eade4948de1019785a992340db974e4d74592c3185feb5e47613edfbb10ed809d7e88f12f24993ad4d3241017f47f4bc6e70010a4bdb9e53e9", "CS2": "041e96c8cd671e175bdf0e44ff4dcfb962da209e005dc7415613ea7f5b2356d6110fe9e8bb577a560012a1800096c8f1c901a17fe48bc245e50840cc3db68fa83e", "HASH_MPIN_ID_HEX": "1715b99ad82fa6355365501214e02de9095881a09ab2a08ef4fc78b7c4a2a41c", "TIME_PERMIT": "04016dba1c358482cf14604db3478ec7120eb6c15b1a04e72829a41b69d93b224b1ab19bf3b3e5fb9b699761b06b889efbf621a10976e60ede83aeb8da18f4640f", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33355a222c2022757365724944223a20223533333066323463616563373362386661663330616232656130666462356236406365727469766f782e636f6d222c202273616c74223a20223162643761323033306363336430393432336336613434653765313634623537227d", "TOKEN": "0401ebf9931a03d4dc1d9e42724c8949ef849b40e0c71f0369848ad8003a2de7271b6fe016c4e33d9343c6ac42116a5bd3af21b3a575f69be092848dbf13648a21", "U": "041435b30d95569a926cd64e214bc071c8e1d12c73ad9d84268ab906b01d361be404db85f3cefe31ddec1200d577588b19bda4a564686ca4a9e98902f6e196a999", "SERVER_OUTPUT": 0, "V": "041e6d81e34c2435984ca334a568cc3e91828dc693e135a3dc61ea73ba0d3a4e4c1172d46db4a106b02a97dfad58cc101df6fbc20926e489d3f78fa48dd7d8f602", "Y": "181014c18211ccb8349541f8bd16f4b6d55047d21c7fe0b9ad1a2f58f4ece9e4", "X": "0df17910f10ab6f2a0a884d8947c000da5e0624988489f6f0636aea1a3c35245", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:35Z\", \"userID\": \"5330f24caec73b8faf30ab2ea0fdb5b6@certivox.com\", \"salt\": \"1bd7a2030cc3d09423c6a44e7e164b57\"}", "test_no": 7, "UT": "04014a818be8041b171d4c296e637b92f602a5b960f6e0494c358f0c0a86acd0090b0a019f6b46948bb93fed1ca575cdbc07e0550d211b653a7245661d9c01288c", "MS2": "09d177c7f6e20aa6a108d79f18ac7810bbe377b309cbc5df6fce20152d9c46a6", "MS1": "0c8bb8124da22056f6d799a606e18e585d8fcdda48379afb753eaacc64ab2825", "CLIENT_SECRET": "041303e4d26edaf9d9b0887333a48175ebd31dacbcab02c2b4f08168bd8f650e7518f8043e581a918a7736959323fd6068d8b86268b9754456192af6860d297d25"}, {"SS1": "1aaf987aea07740b62662a85705cc5622550ed764d10e1416cf4a7d29fdda35101f5bb89dd2207747b58476ee442238b489aafa36f905312821a1b288b19c0c3199ff698f0eb1a361825f24d97a37732fa8f7e26509d5ff275cebd0bb29e70790d360e19a1f91ce66fd46507bba51548332827fdaa3f5744253c7872e9a026f7", "SS2": "215b0f8a9a0f5f2f28db76eb99dfb764f24027d8fa9cd20b905825ed78f7555303fc9f69f684bf1e51d5f445283e06f976ed12c6ffff8aae985b171f1a3634e420df3876a47f7698284a5b3100a575bacbb9338042adfea68834e50fc01629dd16e145350165ec328cec673afdec0e58644d9fc93a5d62a516b9e013c3e9fcc5", "DATE": 16574, "PIN2": 265, "PIN1": 265, "SERVER_SECRET": "1226eb63865bb16f858fab13ad1b11c671f778de40331245af7e5275f2d18aed10fa29bf5498b970649aabfde78d49dfc14d352a72e67982829d8f9d2f6ea5cf0472843706c1efd31835fc2e4a4eb7811cf3711fc8110cdabfd153e63ec248a21e4d3092ae95d649a6e0b6137d4d266591055a54798b3592010b0c7d3e3a4f39", "SEC": "0413f7bb907c6498e33ffaa70ab26691358a18d48aa96c64cfc1c4cbec10ce274408c74d716feca208036f15378b7515775e947d68bec34149cb79039db53a65f4", "TP2": "0422233779ac696c4df92ee491a1b0e234fe109059578964a63655913cd3e2cfa8123778ba2c9b177f62eb42ae17ff61e0765419f09d7202153313509e9ac3c27e", "TP1": "041d56b5f7bd95a64f82235a8c52188dc858f900ad569f715f6a383d79611d6f581e9468863d4fef5920f813ce7be10bda4a5d113c9a1e31b38fbc6c520fd94e90", "CS1": "041c75ec5376d596b866f16a7fe9d040c67f168b8bbbc9f0dba119dab7d95d8bf603556eea8ff4a28cee6ec4670874b6182d28588c794e3196ef429e455868cec9", "CS2": "040bdc8ecc220ec3ff089d45bec84d591de8a3db61f8b6a1f90dcd8b02c75a1e440622737d9488a8ce7d701aeeb8c327e52da7190d3a6d33e85585012dbe4933ce", "HASH_MPIN_ID_HEX": "0df05a2d80d4cdf014a5a79f0025e1418375e2e4740526885fbab9d40c15a889", "TIME_PERMIT": "0422d2871b4a61eb128427d9083d00d6a2670a5ce2f85f7b38f1d88552378a937e1c13edacfd2ab8bda314cd5b7598933ad2a58d7f64fb798ca1efec99333b03a8", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33355a222c2022757365724944223a20226464633337646237346534313561306332393635346238356665326134393362406365727469766f782e636f6d222c202273616c74223a20223563366630343330323734326465353961636566633731633435613138613335227d", "TOKEN": "04125b145e088618d8f5f364f0a2d1ae52414a295809c4c1f77e5344bb382ee0b2120cc4cbdc1123dcd461c819f61c341264e79635308fb7746187984c4dd51a33", "U": "04184e42422f465bb5e10d1c67854c5fc96647355552e818987df521cd2cb3267f1e7c5ca73b58c536fb92b83cd0292ce9029bc06f4b62a8b207c8c8e06377b3b1", "SERVER_OUTPUT": 0, "V": "0413f70928af39037b4c09a8d97a2c383ad470839b9f5e1a7b8048f8eab5938f0905f7b1bcfc2bd6fff967b497a603f308d458ad24441f6eb4fba19f0639fe8e66", "Y": "0b7614a046159fcaf135adb484ae51d8a5377720342e04730f57e6176f485654", "X": "0b89a7ca7826c7df7ab9008d07a3f5bdbba175a5e74c057276a589b00d9465db", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:35Z\", \"userID\": \"ddc37db74e415a0c29654b85fe2a493b@certivox.com\", \"salt\": \"5c6f04302742de59acefc71c45a18a35\"}", "test_no": 8, "UT": "0400e78c0836df826db3fb68b8dd6fab999ceffe0e8a9ab57e4893947a7f7d4fcd0d902b9e9ff5f8bdac1fbc5c0c531109b9cc0f0eefb74f3c25315174d627a5a7", "MS2": "06fc7c66dc167f1348e595ad58b709fd98b730d9424b3d7a05f50582af4b3e99", "MS1": "04d6a71fb1dc80bf2f767c74b2777ca14b161733bfff16b7dcacd4265ad3beb3", "CLIENT_SECRET": "041f66239b8fd139b5b1e34b912b1096e19e3f2f6c579247ec7657974375713c152399702372667c57439c0a8b99fe116715a9ccd640fc164759fc6b508b38dd27"}, {"SS1": "077ec78557936875e783792c960366beed8d419fe0e52b0f62cd6ed1e602b6da22558873fedb283c39f39d2cec75e6821c36c5237e0bc904e8a80402edda08000a5d7021105b33c8c4ce430a140a7c79d51d6633701ba89dfa906bf3ca3d5f182119ef8db18f7912ad5fb19d782b8117774e3dd89d0adb0063a9fa361e3bce91", "SS2": "057c100cac49d461f129d4f3ba6262d3205aa5ae25a326ad031f0b2de32a36160d4275858c7599c52072862346e25ea211ff4aafb868b91683b3de0a3c4f878308cbe482017d1e09cda118d746328c85fb642cd095361e40223d3a0c4a9073ef0820e747fd79ce7023769d85d9a7a854b8296c2d24134d5d15d47c0cf9d0d679", "DATE": 16574, "PIN2": 1374, "PIN1": 1374, "SERVER_SECRET": "215be51b4e51d677ffed74d28b2d2cbf0b61ce7b8942eea5555c8d8104d4e7410fc11289bcb874bc6d5a4bcf043f950366fdb215ac0c4c5fe61ea14096d1fef513e4d17f30c76b698b6df8f461e8c0405f0f8c7cb26efbbcc315b51680dbd5331b4235ae2320f7b6a048fd63a7488731d68156ea17a18d5f1d140686cfc5a7ac", "SEC": "0419a72dbe62701aeca78ef02e5a3e5f35a24cfe5c9fe689c4ff927d724717798704f2dc03e99a9d214a825750d7d5d5906eaccf0a6948b71208043679c83aafea", "TP2": "04066b94cb6df207f5c5abdd274885c8fc6541f75eb0febe7b42c97136f692164b06dadd00ddd472cb8f5e26597cd568d36ae8e428088ca0334368fbd3d605048f", "TP1": "041b9e372a0fc4feeae27f32f1bb89924a8d74eb77b8b7ab0d210c4e7cfb3e1ffa0e274cb9de3142943b326845ca204bd21032ea88a3b03472a133114c8fedc51b", "CS1": "04059f066274a3d9fcfa9ff114907907fc09c77419f4bd9152e40adfb7435b5cee1348d9ee21b57ea1e54b20f8bf4e695708b60a7474ad185de727659054d79824", "CS2": "040c19970f40576c0df8aa0cb2d6a16e84cc64453a8bd7f6934ce4c8be117f1f5313c1cc20ab2bfe007a4e78dab361b280514b6a42122d565f94af4b7cb66cb060", "HASH_MPIN_ID_HEX": "d9a1c49c654cb360019da5ced0741e1bd27d1b812239592d5192179fbc1d39be", "TIME_PERMIT": "04229e0fb5b82ed0ee0ccf75cb437be7206d5a87b6ffa83cecff58483bbc01dea21a92e5b55aee5e10272c32b95c63e5ea49b7d135ef3cbd917e9d22316c8af30a", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33355a222c2022757365724944223a20223130326261653731343937623566336237343430306136343030313165313639406365727469766f782e636f6d222c202273616c74223a20223337383366633861663731636533353336386538393336653561323266343139227d", "TOKEN": "0414579f668dbe2b9c4dc17ab65a6e43187e55085afe5fe8d8a85c6714215855e51a413b2db997d82f603f36f623bc80496cfaba65e3fd89dd704c41fe758a5eed", "U": "0406bae974d9d3e3f024ed65d4ba00ad479750d042b1954246027e16cc41381be323ae9d15ecdca53e8bf6ac741f01e15d30c6a57fdec7fb1417a19034dc1e4c81", "SERVER_OUTPUT": 0, "V": "0409299c4073f6f699baee9bf7b4df5fabdaee60f6d1ee0e261387756cea9b2f8d1c1e26f2c547976f711d7f465ceb3da82482e903afa154283564155ad0345d6f", "Y": "22bc4852bb2677a8406fa1648619fbee862a07432b8cd1ba598f1b758729eccf", "X": "07caf06575482cc92fe239e9b7039ddabe3b1c8687b01c25361edd6e7924125e", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:35Z\", \"userID\": \"102bae71497b5f3b74400a640011e169@certivox.com\", \"salt\": \"3783fc8af71ce35368e8936e5a22f419\"}", "test_no": 9, "UT": "041cf5a20fe03ba8085dae2f231347163e3042a1068e3207bf16888ef89e9a4bb7051d86a93c125519252d65e665784055778e1e67d76ec268b611dd16923b9667", "MS2": "0517527b78949e130f1d4fe7c37985c2f40f872d9f6b3b148599c8ff0cb25bba", "MS1": "20be103b18a51ad41bd1669e516b5a592a2d820b39d7e57aa56fd9f320ed2c24", "CLIENT_SECRET": "0421591a8877098d2e3e8bd33db017294a55f9ad37c893557b28005b52f4c893a31d64d59fed5ba94a6bbf45b1e6110ed3764296b456609caeeebaa6270f9f99ba"}, {"SS1": "161537311d9db766b78e7ccc21133cf852451e70fcd9998c010001066de6a7d2117aa8c76241d627a874f57ffa0b0522095224f4ee75714d7bece6db92540a6416fde878e356f9268065833fc1795fb4abc607b22b159f47abbd9f31511c19cd230f561112e9a0f4be0d59a73d959e2232389b67f3aa82650afa480be7062e8c", "SS2": "22143c6f24d2deb54995cbd611aca9cfdec0408bbd1d1ee2d844f8e139232d3f18f0420701bb906fd39173bd28ae9fa922ac6cb3e284d424209d6aec445f3ee9055871d26067237fa8f344f218ce81fe016e8be2c22e0a12f3f7ad5a4aa1e3b614d6803c4c212545feb4ea0309dc7051b9db007e50c1aa75f15a79bec8d058eb", "DATE": 16574, "PIN2": 6101, "PIN1": 6101, "SERVER_SECRET": "0748abd3d6b22a234d7c9913030aee75b2099a16abb44a6815c5bae78a46d9bf0e6ec9893f4f81f4b68fa315243369c294f0248e15d356df46563f53c8644bdc0fe7cabd7863c521f636a9d9b97667c14403c3f4bc2e5deadf86305a2c46e2ef195b544f103ac65fc0e0a0c1ae130c8078411056feff9b5e2f5ac89cb5e920e4", "SEC": "04162412fda1ea6482acaa63bab712b448e0e829af08cdfb039e5bfc5f0bfa37fd18aefc66872348ba7d14eaaa9c25eea57fc42e1959549bb17752fc4bfa8c3faa", "TP2": "0416641270e44a6c418b4d0fa5a7c44c807b3ee7a141fcadc790b4b9c45b89541502cd6313c2de28c5906e2a158189fd4d214b028cc0bc1383393dcde5d7f59597", "TP1": "04147e3dd4693518cc13ebfecfd30ed299c32efb5cafbbcd2cb897ad438f86defa17c7b1096e2187fedf36f096870c56940fb08b7d6c22ee21d2c2726759e62f7d", "CS1": "04185e6b815a9a64c53b6453f5b242f256f793c6b50f4f43f62757c189f5de807515cf8d599f0375143644dfe53478876c41b3471e711332a5a1adc84a7ac998ce", "CS2": "041871662b68bd0bb59c015be6dc36b9a77ae40431403b8eccdeb043eb60bb2e3a04eaad67cc562b93e4b603595a080b2e4f5c46383cb7570e3a89463018038936", "HASH_MPIN_ID_HEX": "f6db07145c7d6c468ed29ecc06ff6a4318cdfd592250b88f9be5a42dac9a9297", "TIME_PERMIT": "042271085d8cd61900e0cc0b6df47ed0afae9faacdb6be6ef30a191befbea424e818bd6a937886f66ce7193840a7719ac12e8d64aa16be7b86e5c61d95e96d0647", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33355a222c2022757365724944223a20223030373561353037316666373038336337363263646138343733653466336262406365727469766f782e636f6d222c202273616c74223a20223864316136653235363339393832323166303831643132656636303763323866227d", "TOKEN": "040dc0e42bb78610dc0adcc9df3557d5279aa7ebe9177800010e03e0b2c51430ba060a96e3b9e1e3bd41d24b0d415df089c7e90ef700a2f7b72dcbb7f1510e854e", "U": "0400fee4dc126592852e9d0efee084417b86cc561cfd1b78d61d285db58a4b38d112761c3f6d1980e5737c03187744bd6fe068a2a74091c261efe902c1fa139eb6", "SERVER_OUTPUT": 0, "V": "0404a745e3e88c9f8bc03aa07087210b4da7afb4381f28a005e90df32d08a621220465cff98e4c7ff87ab84fec3860af8151e5d52c8934aeecff904acbb146aa07", "Y": "0c33fae0cb4e845da99d33e7cd33dee9a4e223d232e24f470e056170a121c12f", "X": "0ac764e9d7bc34f78253f451fe4fe8d92f0b89836c9427bc7767fc00f333d725", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:35Z\", \"userID\": \"0075a5071ff7083c762cda8473e4f3bb@certivox.com\", \"salt\": \"8d1a6e2563998221f081d12ef607c28f\"}", "test_no": 10, "UT": "041b79d30c6bd9b406d0325f4ee85b7893c26b53617bc115200d0eb92f325c076505b24ae776f89ec157ae3d15d52f8815e1a1f4c10ffcc061d10297c69e358140", "MS2": "23e63a2f61167a18b0d77b409ac66a4cdacb5672735bed5936b5b634d2d8012f", "MS1": "091c462193b0f5be77115553f9c177532279cd2da2db9fe7f18e04d6d58b97a4", "CLIENT_SECRET": "04098ee839736cd37eccb44c85da595f2dcdf952eafb5ca87a97621c1cf8564b130f5569cac8ab079ded668a2b122f37eb043cecb84169a40c9813416101a4f9dd"}, {"SS1": "1adf9dde5cf9220b54468033d5e2e7d17846cf494e9a1ee82c86a49b7cd94d370ef6758c269ed835f2450817c90ac995357d6ec0213bab935a9215ca54b4426102393addb38dfd83d1191dca5623e37dce076305e01cab4afae54b3895bfacb61c46f87a01d86170debc0772ad6f28eacf24b29cd63483ce54a8555402465d5b", "SS2": "06cc34ceab3bb83473d3fa2d1f597e6d787a21406521a0deb35c88c566d036f220ad373fb162010f732c2a8a6e462e12e5a870656332cf617c00b72f52140af209c8e0ef4fdfb461474ec3b6f0b2d9b0fe5c16071c7c8d40df873aa32db6f9060b88d97cbcedff8edcef1b11940516fb68532ef3c14216646bd5767f4c287864", "DATE": 16574, "PIN2": 563, "PIN1": 563, "SERVER_SECRET": "2228164e16502b40d8946ed06359117e7e5f92fc49db78c61ea86fa12c7b853216e5c0c7297f312827a87a78faba52397e3befee98fcea21dfa802dea96d68bf15c5b10c7fa4faa64efcd70a76e2586dedbb55f191264fbe3a341da4e7762eef1ac0bd927451e1b501478ca789f253a7fec38de7f3ffe650d3e48be17ca59a2a", "SEC": "041a0ef266ae011934b4a1fe8d3565f1a522f0e89c5d71c6ac1754984d222e117200b5f1a96fc5bcbf321365e72292c2db69e26be210b42388cfe7164c4ba4804d", "TP2": "0423a5258117f6c67acd6eb68d39ba75315806d9d40e1043e73c212c2e26713fec2081fca5bb38ab87cbc9c189d6cbb511a9f88f8987921bbc28ce8012b9e2bbaa", "TP1": "041b67a8e8082e7b0bfffe59017ec4a340ca96d77122149257044e3f30dce7ec3315516a4a1456b03331c8531430ab6d86e10e88b7cb06a25ef5a8915553553cfd", "CS1": "04128ad0b5cfeadabf35cf1cde31bf58d5f07ee3f1a71ca9e3e2f384687d48ec6612c7d40c63ae336654b973425b5d2717c62628f24eee2e20dee71405c47bf480", "CS2": "040725d2f3e1524d22da1c4c758e33080a8373cfccf9ae97ce658c3fbb29609c1a1dc5554ef7085147d14d8d330924551132087243f1853c215fdda31468012e5e", "HASH_MPIN_ID_HEX": "b3d6256995a73cef935da5c0a9dee1d53ddc1fe71ba0ac69722f161458c2bc4b", "TIME_PERMIT": "0408fce7597724bc3c3a7d616fff7f665236e348f720aa091be99694c7a14f4fb70917845a946572bec4ea8cc45a730c2d2490d74fafbb9e63518f1a1cd130ebf4", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33355a222c2022757365724944223a20226466313766333439376238353739303662653436303765626564353737393939406365727469766f782e636f6d222c202273616c74223a20226633393232303331323431663365636164343965653536386634366637343337227d", "TOKEN": "0409f3f1a85bd7ef80592bceaf9830be17cbf8cf645775e422093037cc7708748f136787955b59ff58fd6a49172ef79bc2868f9ef6d87762477b42fc81d21aa23f", "U": "040e8fc2c98f1cc6ac3f0b5d7c9ef41e4ede06e853794f05a38862bddddffdb9410d4c000e25f6af4ce372b75f62701a84fab8771f9630af1aade4f5203c5e3233", "SERVER_OUTPUT": 0, "V": "0414952ce518f68010564597937e8e9e5b3b4fe305aab0de089ced2c36cc6d75af1e8bd3520739a033b1ff277af9a457140725d518b4e54e382b52ef1c5e3f6c31", "Y": "0ea4a9775af6ea2d790aab5455b8b3202ce482654075ed7d497ec38db0798146", "X": "0533f448575026bea78b34b5807f3c67bde9b25c67bfa17c942ab5b2e9906a6a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:35Z\", \"userID\": \"df17f3497b857906be4607ebed577999@certivox.com\", \"salt\": \"f3922031241f3ecad49ee568f46f7437\"}", "test_no": 11, "UT": "042176ff883e421eed0ec22714718e1c628bee08fe1394679e004c9e5ca51e114a2260fe786bad156adc8bb9a52d345d2a873e4c9e6a50e5c64d1b2ee1e28ab39e", "MS2": "1caf71dc735f9910424d3916b61a5e9d3a9986779162798ae9ff94489c2f1c2f", "MS1": "205403d6aa8bdb177986a541e19979fa3b6ce20e754f53240f6006cc69eac2ec", "CLIENT_SECRET": "040ad0eb3f2d90b810180d70914324503449006861837de6d7935718ce66be462a1995759f4e2d2099912d3a82ce1f424d0ab29a8e2d0d180cf5e6c801744e0933"}, {"SS1": "1450499a3ffe2c17d751514b0d3c2247650e77511050b0b42b4c46cc629a4708162fdfdfa28a8b78d61b8251a32ab5d43e8d8c10384716cc9b95f91723d499f91e9f34ddc337013ae8b5f84fce2fcba3eea2618a87fa7bac02bfd6f48716bf341433ca62ec3c9c96063f75911925b8bb3991fe9a9870f9080146426bfc094e66", "SS2": "236bf56559c6414d767556200ce0279fe56fae8a209a89f7e9e0dbbf6d9a4b4823b981b5640d565a39d604364c6499c115b3ab5a7a9553f0fe292313be1d8cac1d8f9ddacf0c93eb0596720d9ebe6c9d5a1071d50d4c552a62f67d25629ce770114f3717c0c2195d8b58d42bf6d3a90e6d9334f378d4b42ce01a7b1b0b95f4ce", "DATE": 16574, "PIN2": 3849, "PIN1": 3849, "SERVER_SECRET": "1aa8a4f71766717cd0e935774d8c976da5e4c8decfb0542ebead0af7daeb742720304f977c524fd3d92a023055cd63b42b3dadec803a4f88adbf3b75d49733c9220be6b602c08b578892ef306ab92069cd992b0b1723abaa4bbe73ed49601fca1a5e42231c04a2b348fbe01dbb6cb2951a121b55f7cfe89e1f3e91d38289e5ed", "SEC": "041a8be7564cfafef91709c4b3037125dec2962b0950b7117c22eb57ab974852c20a41e65215e68df7d396f11383bdbf7200a94f52762cda0781beb2cbeb524903", "TP2": "0416084902e4081cca0565176494dc1c607ed78a45b539766960e145f4d242bc870cfb6d9a18e60762f4e669c1153811fbac9006fd34b2137c818db6f4a1975676", "TP1": "0421e92a93e49ef86375afe488434b286b8938b55eb4d22adbca52dd86b2e773c418434ce0d447853d50259bd24ab85dca46577622143dd9f6cd24f70e04a63bfb", "CS1": "041aef0941ae6b60042691e195d09f7638417f65f0e8315e3652e1f2458cfe6dec08d8e459f5e856b3a80cf2bd79f10824aa557271ef9d1293fab42ea65f806b1a", "CS2": "040ce39cd32a7d172a2d5d8bac6e5aaf254a7dc2748067679fee9e8c6ed55b071d0ec1ee184b85959cdc53b861a06819edd21b82034e6303ef005bc6fd14c9d22d", "HASH_MPIN_ID_HEX": "01078df455bcde211ff18edb028b794a847695f0c6e9ba18928021c1fd7f1dc8", "TIME_PERMIT": "0402352c9ccb311ea8e21364cab822c3a47ad87c8bbfe14da66f83cfb7b1b348e81761dc86e3a04f5cc530c97b28d0dfeedb117f6cdc1245cee240cbae79ef46a5", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33355a222c2022757365724944223a20226139653333323863353733313039363261306665313663313365376132376431406365727469766f782e636f6d222c202273616c74223a20226231323535623564323439316664376430356564313033656164386534326238227d", "TOKEN": "0412a024dcfc7a4bc42632f4072f7198a0125978687e5cdc5bf00f5c12ce124edf01e5ebd94cc2c89998d214be71c4e2ca3d69b3ef03873ef09c08873576c71387", "U": "040dda1f55b8d8a6b41761e9af47b30ea28ff8152bee5e43f491dc3bb968686eba1e5d17a3311ce70189ba16d9e863c489bb2601597f99406e2bc57b3423d650be", "SERVER_OUTPUT": 0, "V": "041a696ac17a51e017639e393d019bdd83ec25d315e3f7a5b4afdc942068e5614c1aed6f120f6cbd9f7e06de1381f79ae50ac1aabbd46e2e30836dadcd4bb49935", "Y": "15f9f00ca53f3cf8237dc5bf1e0d90df2af7ab3f462b5ee768bb0bd5510ae26d", "X": "129b7ffa76573ae7af11f1a3c743d993b60f6dba566be4ff74ae93dcffa9f15a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:35Z\", \"userID\": \"a9e3328c57310962a0fe16c13e7a27d1@certivox.com\", \"salt\": \"b1255b5d2491fd7d05ed103ead8e42b8\"}", "test_no": 12, "UT": "041f6abefc3dab041a8e606bdf40bb8cd421a40b725addde477b3b7253da6766c51e9fca2c0f82fc420b679b4f12773c0f2b634fe8146f734393be3fbe882eb7b1", "MS2": "1746f71df355a9879436109ee2f28683973ee2b515817a5d793c95308a5ff311", "MS1": "13fea6350b2560d0fb3f1c27561a5e927518e438aef4416d94df0c3802fe83d4", "CLIENT_SECRET": "041efae623eda57e30a49f9d458d450fc05293790e113aafe4f0d50ee3539b96620c61c967a957586c7a61171c7114f88ee4d34a325f7663d2bb962dfcabc2bbcd"}, {"SS1": "0ce4e56bc0a861ff450ff3dc9b0596ead87a8b573e9969db21c8ad166e07931301f0d457fadb69075deda5fe82f38ab6df960083ed03bb03afcff826109ee8621d24454223a88b05659628d646c0db240da5de7776405263bf97bfd83cc813b220463311a14364ff290e6e9c43cd378133a4835fd06169e5f8026dfc5940c25b", "SS2": "1d439b9377d8a83e9542f4aa51d8ba7e138c38f387c5c8a97784528d97ba0f760e9be3cc0dd9bde7df4080deec9c7d394aff4d23d383928f042cd4eebd4bb16404bd4483d2477c52396e23ff234df5f8c887c5eb22986381947a503117e88d8703585d190dfbe5bb4ab6840d87f97eb8c4e7d8dd66df6520b052337db4e5a7fd", "DATE": 16574, "PIN2": 9822, "PIN1": 9822, "SERVER_SECRET": "0bba8962716a9e27bbdaea996f2ab26aa2e010f147f8d4eeb10452de5eb7de54095c50097c9b4045f0ab6b4524bebb8edc398685ff0368082fa5e6f7117dd5940b6b4c552d42edb6f715651bd2316160fecb21de418a426e81fb1c02abb3b7790ec128fb5d9ef269ac075a19ac2ba4952e872514b7507ccb9c975a4cc7923d29", "SEC": "0412e18a31fd1485ad004e86f12add5e5ddee9c0733b7c90fdc57935586fd4e1601e0b6562e337316e72e22c0dcca9306593f3f6be2c68506ca23edc72df4c9b70", "TP2": "041e56200d430c92980e80a5c4b79ed920abb99c0ec3fa9fa90e872b4564c619f611b333d56d90a68596dcf66133d5420398911119e16961d6ca893b2bd89c3fb2", "TP1": "0403f14c8288d329f6bbdeeed503654bdcf81fbf9f642ed66351b9e673415a006115846dfb16a03d31e7486ab5ed7a6a0f36e40d2f50e65f96c42128c30cda8236", "CS1": "0420eb59ac53543e3851b8e2c8365bdd9e87625fa5db3f9b07d4142e2b05d56d5a1e8ce340273d3bcd3f20176ff509ed3a5bcd2bdda2613857b54518483ee1100b", "CS2": "040167d54054d55a50b9fde1e58af2e654a4ee48a103c2f551cb1c2be03b76fee521ce4f0e921e4cac58965e9d7ee7fd24dcafa9107e193547a6f6521a3f90f942", "HASH_MPIN_ID_HEX": "c4e2adab8f8c58b383dcd0a37bf5f9143a65afeb96ab613f93e1d136771632d6", "TIME_PERMIT": "0419d7dcf372ee0020f3a6f97f64e850295a7aec4f8a2cf8c09220d3d663c861e51f8c53d0574078d66fd58b763ba39c9a3b51c53cec791a20be9face05696d9a4", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33355a222c2022757365724944223a20226131333439653038636634666139336365396130333832323462323164323132406365727469766f782e636f6d222c202273616c74223a20226336363031343832333261373362656536323038653163363038373665343933227d", "TOKEN": "040406cfd472f437f10e49c028ffa2c2f97118f6038380035bfc6afd7c7cb6d45614e8d6005766e608c1cce093ba77f7ec6e00c92363f0ea035dd1840495d8a89a", "U": "040956340ea4934c9b5b5d311fd7cd157a097725d3f34e823cbc0dad409d18847d20a18a897052965cc81170afa96e9e8795a9efd629fe3ad7e369f360b63dd309", "SERVER_OUTPUT": 0, "V": "040c62e57890f914da2f25859b679d638ac0101888ca22a5121c93fb4bb359c0012022810b8c3ebf54eaadf42029f55da98633f0295dbff200ab1a00061c46e11b", "Y": "1a6605aa2db338732276e7ce847216b8585426267e29ed039812d819d5190368", "X": "0d46b94802dc6db73222e697aabe2eb866005773c971e7d30246e2ac80acb9bb", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:35Z\", \"userID\": \"a1349e08cf4fa93ce9a038224b21d212@certivox.com\", \"salt\": \"c660148232a73bee6208e1c60876e493\"}", "test_no": 13, "UT": "041a821b8cf900570c20dd0c908923ad1576d0bca84b42999d2801482498d2febf0288714e1e1b87a08454c4450965941cdfe050043f9a580fd6fc8c9a9c291584", "MS2": "08d458809cafacf6d5d2c679b80947b59368e364df7068de9ccbbbd52e7f3656", "MS1": "2175ba7d2faad16a38750136860a63e61775663fe2ae6d7dffce5ec2298cf0e6", "CLIENT_SECRET": "040a8a4b9f26582b3a4d741bb23e3757f83532ab61edc6a738ef608d4ffe3df6c41c27033e7282f4554d178c166bbab68fae50a2c10685ee77ccb32f04b638213e"}, {"SS1": "135345a8a2b6687c7f748c4c678abc2a691fb25fc0d55aab68d83dd7f8b76dfa142137225dc96031835877b1f7d7128b1d62839c7d28f91571ec17c300a5747821de495df2306945ea3d8462c956932305f188e691f8acf1112297891e79aa51020e3859377c64e98b16c26dc2e8b40ee405d5737a63dc92431041392698db89", "SS2": "195a9ff8c501a74ba336ebe1ac80a97d6301029ccd6fb5013e139cce77de79d20a1b5f4331f7ccaa8056472c9413412303a1fc313cc9744a600d0af1f9c7c1f606ba7d25911d9c85f2f0dc4903eaa6189fa64a6f581ae645bf03d60adb951807107fc3f7a1c7d2e192e335e59062c5abb0d95a162ee197f8d93881b4b19bc573", "DATE": 16574, "PIN2": 9000, "PIN1": 9000, "SERVER_SECRET": "08e3dba688f59a350915967c2ad24f4cc4878cc71813ca4ba71d1b4e477d394f004880362f5d076928811ff4540bc9cbe71b758dd9acef1cf6862b5a3e33e44a0f46c159adf292ad42c3744a1f65008cf88d82a64f369008b2a544de648b621e12b0909fdcbcb693123cf5d261706be8d533cd0ad969c93e18a43922561a2377", "SEC": "040305bc286058ca0d0df7296b349526b9efd24b27e5bdf80ff45ac0c4d7a481271b690017430474c912e647e2e113265fd4eb240660783d4cacb9255e93304dce", "TP2": "041d672ff8a39878102e2892d574ff62dab650bfbcb86940af9de71a49d3128c060564029ed1d5e09c4fe428f111893697a25119e51d701c13c9d064ded21cced0", "TP1": "04052c7e73049e4e47e23b3ac43609c51135f949a5fa4281322a213f345d15893423d801526d2ad0831e687d2425d2228b80bfbbe213b5b848a05c8d0cfb5e2e7e", "CS1": "04071f77fd9450f5e681ed6b8a00d87810ef74b9507f16a7fb6815edc5649031340828e6449f328c14214d905c5dcde8fc0c80dfd1577287a88af55bd69f8d79b1", "CS2": "04015cb93fcd709fb9dfaabf428ef2a6fea1d15cf6db568faaff5a289efab2e5661636edbf1b507010cab541e47f2c9ca6abf828dac4423ef1151a8673998225d8", "HASH_MPIN_ID_HEX": "37652556c5c865056bf1127e1aa3639761afa8c13af6b28cd8ff4e0ede47790f", "TIME_PERMIT": "0402ab624ad2a42041301aec3b792d51abeca3498fc5aa02a99b346f772af316162255593e46779f0c8e801c48e9aa8d2143da777e96e421207890d66ab1ace482", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33355a222c2022757365724944223a20223838336337633234366338613633663334373330663534393039376138616335406365727469766f782e636f6d222c202273616c74223a20226530373432346438366661393236313339623062623664636536373637363862227d", "TOKEN": "0414c6fb67146fd53cf6a77e0983d4a8230faa4d048fbe97ae87643043c1ccb2ca22aa84a879dcd88a721378a5159c5bf28eae093505c573e1aa6607211e51cfd9", "U": "041ae38bde3d3d253a91c6d52d558ab0bd3af84dbec6f6b65bd3559216cb971e89114bf813bb3f6ffaed4a71e938b3a63c9e3c97a2ebebb6f7c6e8b34a4ec22334", "SERVER_OUTPUT": 0, "V": "041d5f84f0a0af6aea3bb26b13bf66aec0d2171d2f35792667310b872eca0aaea10186ba54d6371dcb1badbb11919e1a066beb22058ab14331067bf599140adafe", "Y": "08a134c82f786d23ac5c9d80b343f33c25e0a17e0825b8dab89d325bd92829ad", "X": "12dbc077b838b81831a962b3f46bec551462893aae22fecc6926fd2a2adb4719", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:35Z\", \"userID\": \"883c7c246c8a63f34730f549097a8ac5@certivox.com\", \"salt\": \"e07424d86fa926139b0bb6dce676768b\"}", "test_no": 14, "UT": "041ee91dc24d68c1cd0ad350423d34521acea30330cadc8c3d65530fa7b68b0a3611bb3dd09ea9957082cee6f0a20c58d7173fdf94221221b52418c97596b84646", "MS2": "18c6156545f62c9bc58b03db316df9956cc70f6d2831247e5c6fd093277fcfd7", "MS1": "0e7d97af9a5529c51bcadf77d14af1bdd85d6e49c2151a6765e5d9eea9f4f4ca", "CLIENT_SECRET": "04038d76a45c7bed6ed7ddcb678fb264b057be72c1d5ebc8a6622107df1e22de420874d3d5d2ce29766d38780a79d304a97a797f4f859279d32880024f0bd28c31"}, {"SS1": "23f01e2945b40b6567c2422f5bc11497ec933d665d2713f7ac616b1c7f14452414436f4fb2212033f3e28150e726bfee6797ab8cd74f384dbe248176bb6c670c0c7d9c10c2560de8565e2d74e55e48aea23c906e2d152f15746b5011ab447e591e51d573b94e29f4d36478335e9e1dfc9638c98abdcdd70d4087452b04e7e832", "SS2": "0dd0c025144b24bb439de83b23e426cda964353fa8a4574ed0888702c9ddeeb41de59eaf731cff16e47ff63a68135f9e1ed5d1b9de5ea36df2424f418eec17f32324a41e258b2359c7847d1f0c746321eb5684234da66fec823536b4ca8b15660be756a92c02227a74ea0f156fd28faa0cfaaec8c59fedd9716ecc37df46304e", "DATE": 16574, "PIN2": 382, "PIN1": 382, "SERVER_SECRET": "1331ccb92ee61b3e4832e2c836aec9e1e80ab5af2f2bddda23ec8489962f77a2090c6a9034fbb65ce63cc29387d1d1506cfdf4218d08d927bb5e53658619fe2f0355dd7fe1d6457cea2630d039bc11f7398f57ceb0ff40efec511e87293d2492011d4cb31765d8a9619a19453b19f066c2e76cfa62edd76b177e18b441d8e2ff", "SEC": "04053936b1edebb1aa71449644c7d323cc5afcbf43cf4ffd99a6def70ec38a58a31e4d32dc92744d1ce6ba92e191b29716fbaf4b7d2d3a9b966f5dd70cf848523e", "TP2": "0421ab9f39655ede18e8d1f927ad8380e33fe5c12e260a2bf68e6ca0c41b5646b71f7e4990730dd9f0c954ab90e149a0ddd5f64a1d0a08740241955f169839f65f", "TP1": "0407500865109d89fa9b183dadabbfe88e02d194f9f2e1e6f7edc7703d3cdb19200653206bf6c97b4e2db477a32bacf00bfe83d5e55e8e2199cb504f17180e9eb8", "CS1": "041e31e8717d512621a01d09683da11630f294eec37fdc0c0e0ebd5e706349fdb60c8045bb3302bf577ed32b827819b2e6553ba255ae8616e2dc82d518234d894c", "CS2": "040299d1c6cfc8767f9446d1f680faf0a22e858a6601d9c69b2cebe8fe5b0a27b115f024112352ced9ee488b882c5aa67b38750ef41bb5a7e2bf1d9af21349f2c8", "HASH_MPIN_ID_HEX": "425de93f690b04df0fdf8378c7f0926e592fbf2de9b31bb4834e6efcf4d42952", "TIME_PERMIT": "040c1caeff0da3f2fade230b2804b762f65d373e34360f252cd394e600d191160c0d6c50311abc6657d426abb093330e7fe0567ced0f0bd96be4f38707d8797d7a", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33355a222c2022757365724944223a20223565396362336133333165633861653463623036383330636435313133653237406365727469766f782e636f6d222c202273616c74223a20223635346565353538333831373436373230646532666132393037326462306338227d", "TOKEN": "041aa8a5c165d4e9b4c3d9adcc78aa32cf998fdc4fe6d3ff22b3fbcaee1fc393f50dd50370e4d9209661946f0c9dceaf708d945dd866bc2589d4bc3464949cdce3", "U": "04046bf3a1303dfa92308b7e3f2473f54300169284f1d084b459b197688336db080be03b998b4189fae46a3d8bf4e2b157b22b1c4e17a0ed63d99234902e330829", "SERVER_OUTPUT": 0, "V": "041ad21cfe0d019b5ed405d5eec0fb1c37a8478ad2be80bfaf75921b50481d00561441d45db1ed34a77dcff73aae16335a50351098d4ffb4f51ddde35b0531d3d9", "Y": "13350718959806fb930b367bf19863729ce5bd221882102122a009ab2e4635d5", "X": "055a3f65f94aa6fb7b2c1a9798d863b9adddde78cba36e759448402381902c4f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:35Z\", \"userID\": \"5e9cb3a331ec8ae4cb06830cd5113e27@certivox.com\", \"salt\": \"654ee558381746720de2fa29072db0c8\"}", "test_no": 15, "UT": "040a3e3d7e78b93ae79835344d149d37f46ec8c3d37a352172c04f0bf4d2092aa7046ac417d0acbe4351a3f5510cdd87a90e3424f153a9cbde404ac44e12c4a6f7", "MS2": "1a00f72e27674df8e0db9151af3cfa94a80d84fb57a9166cca002fb0ddc74ab4", "MS1": "1a06b578947fcf8ad95ccb2b8f83aeb338fba26506818315eff599ec2d110054", "CLIENT_SECRET": "04195acb8edb5f37d2c9455285fe696fb68f8c1eb84d3e4a4ae7c136637a4d3f5d221c2bc013aade76dc8fd5dc437dce2cfa45a943f6c52e3aa8e259c339fd6ec2"}, {"SS1": "0189fbf2f7a0febf76294e37d201a724082ad3deca8366967102bf6e21591b07121e3fa8d4439be82b267ff1491eea09f3839d78a072969e0f01a52ff040537f1ea24b1cc34fd3fcd852b2b23ff0068686a0169589a5dbd587d15cb71cbda7221b177da6aad8970d479815841eb6e456ab4523d6d81b59cd7257714ab66b18ea", "SS2": "03160467972fad64ab05306f1352004b3deebdaeff7c42a10d4ee0cc9d3cda64037f44da981da35b2ca3ed322d3b58857b37712768ab5d7575476be816bd55161e7c486511acc10e0dfdaf42a641366abaac0111a1c0b07b423fead1d1e5cfca14203f86e66634d376a61b614624759a261ea6224cec4f08c1d320e0f789ae1e", "DATE": 16574, "PIN2": 5353, "PIN1": 5353, "SERVER_SECRET": "22d93758a690dee8301dc064c20c413d7c8ff167a443adc51898942b5a2ff6dd1ef263a6b91642bbb247a96b324b296027c543a3775e55a64aa9639544fd572623caa7f5a036f6c24801808e0b9d53c1f11ef93855c280288e1535d8f5c0e27623e61e97742b0044cb08b79e380633445550ea5e92e22f5a6f059b55626c8fc6", "SEC": "041d01e37caa3f1614cd37d6d6f7878ff858ec11260494727a476c9a4993857e331ef83368c12cd259d93b20715b04997470a454a261d996f28c11a8a940fd8e52", "TP2": "0403f7956b69fef176d25d6b395cde9c4344adec97c37d083a6e5ad2976d0ccf4a1e4f7716744c82703791c2663d4f6350998d04e782bc95ffbd53cae2c315a309", "TP1": "041c00768f9d787d01e2de9986b41e5665bb1879ca4858736ee0baad2f4806a4dd1ac4505e552a56e5627c60b86ca61d931e866d435ca6642f2ce038eedfe00cf7", "CS1": "0407e389cb74ad4442e20607c7a2579fda1739fdea34fb0ef20c68dd1fe590dd571fa8fc1479b56d97b0c111b3dfa1bbdd76cf2c30935103447e150fb92e93410f", "CS2": "041521c4c8b389de5b4609d9c6bf6f3dce549f71ec53e67725b62a86d3873202db17d81654f02a5f780e395ce7e864a5e86a7ac67bb557dac6775ee91148c5c35e", "HASH_MPIN_ID_HEX": "a552b1f3e327bc8418d7a6590d16a566903de001a24dc0618bfdcb2cea78deb1", "TIME_PERMIT": "041d366b8604154b018b8383b6ff10e2a6d8e47a06c0b20ecc1d85fa951c6de5be088991cd1b313c7691dfb023056fbd1d10a77ed04f4c52dccb0aea78d000f702", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33355a222c2022757365724944223a20223735383661323865336365626436623462626662323065303965643935636234406365727469766f782e636f6d222c202273616c74223a20223763393032666536643366653639306461653935356465333438386463666534227d", "TOKEN": "0414b2bc55fc64290556f1e949bfa10ae91f835cff39e4e7cbf17874dbd0a8a4b21ca5963955feac87082d67cfdc52cb00e9c293f33570c87a17fe4a86c4ed95eb", "U": "0409e42f8ebc6d17995ab4f39685e128873a05da2232e3deb583ca1b4a79852e740dbc062a36067b354247d03d3b878dcaf73e0603571363471b93e693d5ae88fb", "SERVER_OUTPUT": 0, "V": "041d9640407ee762253b122cb07cb6fe13991fe5d9fda4c9d9dacea3c87963b6231e5467b50a7f94d8a7a3091964b9013e3e9c4aa6d899cea9179506c5636471de", "Y": "17531c5cd14d1116460664ccdad477b6331b567c4b81c94f90d229fb9970812f", "X": "1ad62bd1a8732c9a9a7af439e38a815f47e8eb63028373ac32880797d72b41f5", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:35Z\", \"userID\": \"7586a28e3cebd6b4bbfb20e09ed95cb4@certivox.com\", \"salt\": \"7c902fe6d3fe690dae955de3488dcfe4\"}", "test_no": 16, "UT": "041794f855a1b32220c21a6301dd7c443d17bf3e04da21f6ba0b6aa1c8334f950306b540fb8905f189066b717965454f01e5e636d5e0ca24e0dc8968eb0cc6c27b", "MS2": "219bd8a4ac13dd2b6999549d765dbe1b53c33b427f27a346ebe5fbe6e482c7c9", "MS1": "173b225d0ccd1e2ce8b451325d7f2ffa815c306eb01843064e5ddf1205d89005", "CLIENT_SECRET": "040e6abc00f89aca005d36e54dd400980ef773c2d499840e3c2f8b2aa98e3b6c65025f5b81f894fa58529dda81e9acb66f702355fecddd903b01883a5942022ccb"}, {"SS1": "088ec9780f5111ccfda982d9f0f8b3fca4367df1d91effcb12fd78626934b01f05280f2232d17feefb2799b75cfb3c4f5604b3f7e64e099e8c863792968f83b10b49353e0f974b8bc0d2268c2da29a7feca7166f2154af0d4b6b71a49c8eef9801e7c832f58468786dcbb56be45db49c9c10f832117afe3d42cc483fb5ea7449", "SS2": "1fc49061dd32e801f32e974be013ecc08263ed101024c482d861ab20146b58771c6459562c97110c1267989e434b81c869ed82355863b85d35c3fc0698e595460863215497db16aea733b49052074211ba2e65401940e02c0951d56314150b000d25a93b1fc109fd86f0ad0e714c319eee0bc08a34692b3fef9be9061beb78ba", "DATE": 16574, "PIN2": 5351, "PIN1": 5351, "SERVER_SECRET": "09cd15dd57c7035dfc920752ad4f7f368f6cc9e3df7ce571415ad7ee266d08c7123da0ac81acfe96899ee0ece9fb7f669cded96b61b6580462e4d78f38d7df8b10d33aaf5d235d5b884b95a2274dd297339947907c1eebeeb65d8828f69661c61fc808eb15c4b0d4e16a40221bbcd8cdca49fc02f5cb2fc50badf255ee7842f5", "SEC": "0410c1ed7f71a8aa06fad64774307c2f4b322d2f144e2d6bdb273ceb6e3569a02e065ceed1331aa2c30273aa3b0e85cfdf6ab450f374d2151df53c23cfcd4e3a72", "TP2": "04175b2f5cc63010431b88ada49946f2b95ca69a3032962bd2559f014737a4172a11ffa3e23f57529b9adfac27ebd4c5333aa028e45ff96650cdb981c0c88f0928", "TP1": "0415f2dba78ae6f9a80688973b0c985c7652f0f36ec9ac6ff44b0fec01782e44d007674fe7151fe67293bf853b16c2fb48b0b67b7992f2024446bdca674bf4b699", "CS1": "0403cbdd40029445d42ac8738f9b8213fc40e377dd359dff02200d44a055c0ec4c1c3b5b5dcb077e644584594b192d0940131b314d8d49f6f41c3419cf60aad866", "CS2": "041e0b37b51cdf6b0b32eb8e5971049ff8632f2264a74ee556c59b2b839f1d637f10f5eaf5a8c6c2c869af76cfe372a5ea369ab98d61a0e7abddec554067484ce6", "HASH_MPIN_ID_HEX": "2dcae178cc526da024586a4cefcd90f7a1b81ba54534b16f6a66e009b10ba7e9", "TIME_PERMIT": "040f4c367a7e86dca24095ef7e553db7bb6b09875e2109df53d22c0d76be4bc16d01f370f4c21760f11310754008f89d0b7b3dbd8202d044123ea0af6939513385", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33355a222c2022757365724944223a20223762383864326336383437393737366363383564643761663139353331306236406365727469766f782e636f6d222c202273616c74223a20223935343638616464313437316265393933353662656237643534646632326263227d", "TOKEN": "0411e21b3ad2b67a5eae0f2de6bf13756b82f42f9069112ea52d3e16d8cd13072e18e1a56567b8780f72b72c6839979a38ec74e7a2dc5030a86c34a8f23141e4df", "U": "0419a0ddf46a876f0d48d568b32c62bc2d943286c1e7d1648d1957dc4c9f765b50068129a375ff4cf83b34a1a7b6697df08631c6c800bdccb2ad2292a45f549b07", "SERVER_OUTPUT": 0, "V": "040d9ed5a12f40971d3545a589cbff5c25bc28defc5127c9538d985341c88fa2961b9ec7eb2a69bbb4d265f7aa8cdbf55ebad3e6ab5436cd0f0bd68a1f52a51d4b", "Y": "15423f0734c27df8eb7d655aedf0f79d489c1b79c4670d024969f731b9c8bff0", "X": "175821b117a4d69c9156be23ea2f2e1d51215c1dcf537f22ea770f02a4d1eccc", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:35Z\", \"userID\": \"7b88d2c68479776cc85dd7af195310b6@certivox.com\", \"salt\": \"95468add1471be99356beb7d54df22bc\"}", "test_no": 17, "UT": "041c34b51a8c2d3049bd8efece36b0be88342f6fd98d802625a0f5d1c28a876fe00f0bdf14e470952b5f4af97c6761f981aeed159cebec839d7d7c7805db5c63ac", "MS2": "0e31b13e7508005c4c2eeee21cca84f1d0da26689f517083372699b59bae0bd5", "MS1": "1bcd1ee366c077339c170858e06ab6c13934bf3b81c46e2ba21e0fd4e4f1beea", "CLIENT_SECRET": "041f89b50afc3fbce0c99c8ef1081ce0fae6efcbf33c34fd095bc7373afac7c7581cef5cfd6b33c922493a6390fcb58cce8c5f71bd19fd501772a2f6fdf1c08b9d"}, {"SS1": "1b13d5bdd518a0e5bb38e3f5bd71a77fd6b9d40adc72915584167a669ea5411a057283debfb2c5ef071760fa04ba99f623d7b52f69fdca73cabec850040ce38f0c2a6e500acc1b1fb73d44acaf749bfd902d1a1f62c802360563232f4eb8426d0c004a6c1444dc968ddec4d8885fd6fa87bfcf8581c83057682746900f7b4de0", "SS2": "2265b195fe3ca45759ba449bcded1c7ad680ac9b2d02f7157c1f4a374203e05e06927f4216755d9529b7174638f9aee6f71c14c38e27ace0a33e8c2393d8dd2c05400bf13de8111ad2aaad087efcfc8d6442f6308c488be380435cedd6e6d9991832438b175db683c871ad613d36e8a411d9facd0213a83f1b348713ec823b22", "DATE": 16574, "PIN2": 310, "PIN1": 310, "SERVER_SECRET": "1b6309d810f8f389d2dda4924edd397097c988fa8e86507ed8e89505a5cef55e1e10b9176251562fa7af7c79d18e29ffdb99971ba455ec80182318a5a860b67622caac3a484c118d8fcfd4f79e904a23abd9b9c0ddd05e563f56936e5f4b38460a1dcfc24d8c4d8d085902463fbdf42ea2cb8046c0606d31a997a51199c7d8df", "SEC": "0421c6d42d2f5813d039ea120012da0a3a104749bdd1d44cd8eedaa6dc8f41f35009a63a0d00c074825ecf0c69f6eee035dfc73d1aab2a1e000d9e65c2c586fbaf", "TP2": "04038d28a64c904ee881a16218fc186914d9db5f0195bd1828e697a259932da5c70fc0f545fbfa7e5835e3a01e00ddebff42f56f009f2f6371ae4f949549fb039b", "TP1": "040b7996ce2212246368d23b94ee9c1c821b94fc90dad8a76e96de0d0500552dfb01fa0b3b2b4c0dd95bad7e2d5e42f5521bda5f68c82d82a639d26435285e5780", "CS1": "040f749c883b3934c13a5a83fc245fb06482a6e3d0fc866026d1539e5a2d3a2b901ff979b53cde52fa81f4172229c900c4cb4046ca011df29dde50e3e62314d465", "CS2": "04239128a1f91f67a750484d17e24589ecc7e7307d95443348415ca2c07f13aed007c1ddfb587e00329513bea4c780d498399633a4edcab04b497333e51065f68f", "HASH_MPIN_ID_HEX": "8126d16b9133439e351df78f39c7128ac38419154a66c19c534b20a5558208b8", "TIME_PERMIT": "0423c766d8fee75459a98e834187810c539e7d30176fdd5b3daaa886d403fff844220eae68f145a41ff1df998265e8d4b6c612ccbcb7c8c0932a02e3ed3687b529", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33355a222c2022757365724944223a20223162656538313032376663663061333333343338313761623465373531626635406365727469766f782e636f6d222c202273616c74223a20226461363464613362396635346238626235363931663361306435393834373139227d", "TOKEN": "040587a1f51a3edffda7de4e9a8809625d70eaf270a00937ec2bb9118a7cc8add919a5ea5673427fe9442bd7a770e7696ca7adc09f91a31af7c6fb4e3131b5af63", "U": "041943f21db15c14e6cca37d66b00a0f0b6d966555b385afb83610e6250bca60ad1963ea7d6109af95e48bc54cfe140885a51d6563fa1eae32376c5562d35403ad", "SERVER_OUTPUT": 0, "V": "0404283179ad16299a621260a860b0ae0b1422c7cc1e3aac1e00782b585221eae01e9b7ba57a3a2ce9ddbcd4b9b4548db9e8dc29e114ccdda55015e5977d623510", "Y": "176778c1180770a0b00f157ed313fe36bfd62fe03a4254a5c1b7ece95c7cd15b", "X": "029496aaf0a0099ccffd2d23fceee36d2eea0f1ce8df33fd9e2137016f256197", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:35Z\", \"userID\": \"1bee81027fcf0a33343817ab4e751bf5@certivox.com\", \"salt\": \"da64da3b9f54b8bb5691f3a0d5984719\"}", "test_no": 18, "UT": "0402617c055cf2c4ee3392683ae8b22ceebaf23558eba7b51509f68d88c342d56d144a6b0601c98c80e959311b45bf95979d9ff49b2df654c07847c75afca615a1", "MS2": "23f7d88400361768fb46c1acd10725aab7fa0dfe607a7305614d81612336f2d9", "MS1": "175d39d7303e5623ff32aab5832009a5c51f3ec03a35dea1c54f6c473a0d4141", "CLIENT_SECRET": "0403651204ab64db2be813bcf7fc4f40316e09087e9f1cc362ff19a21d43534f4c14341073c908e3e6e4cea94a61881d79af4ad796e7f733689c541d2bd992127b"}, {"SS1": "0c2c4b97dc9969ad66ef20587e883c2d5f867442f9f7fa545026dbd2ce2499200fd6a7bcc34c11dc9278ea58135e368c587d3e934be6d63c356096aa750354ac1296c3c70f62fff5f23c9dbb4b633f12a1a177f2ab0af3a07be54af2a5148ea50d2b4f509483f95b02943004dd1a40501e982fb065e63fe08ad0c5fb334d56e6", "SS2": "1823eb674f874fd72c1df79c1d4e170fd13db98bca78ba16c20726d3a5563d61093efb31be920f091b78d804a7061c9f7951d4652b11dd85f0d99d25c3d8688604c8ea2e8a513897eb2ff883a2ccd66d4d85c2c183bfb0cff4289c08fa302dc31f418337c50d09d03305ef029b70abd0059c6671e26caa3a046a1b326189c665", "DATE": 16574, "PIN2": 1292, "PIN1": 1292, "SERVER_SECRET": "18ba0b042134234a51d5b29ff8aff18a65a2e457d02f740d2004d0874624576902acc637d52681a649d59cea5aa01842e95751f253efdc07f9f262481f37ad2d0e9bbafac56e85676f8f37049747e5fe8fcdc0f5ce309dd471ab3c722e84128d179a639878f36aa5d0169f4aedcdef9008e41a78c1dfae56583b82d93bc6fb82", "SEC": "04198765f06ff5bc5420007d67867cae63ae7a53c7acaaa25ef73b40f34d5cdf820a32c2fb2e5f750b86190fd07e026055c8407b0e6e312f798586ef078815e9d1", "TP2": "040ac3c0786471caa1c483ce36f1555637ffdf0eedf0f387643cc1c4ca7fd3588c22971b28cb3580ee5217c14a12fd2e29cb36aca5058410d9ac67d279cdd530c1", "TP1": "0415e1d84d6c9f42651b4e2a1e44e1715658d21afde5612c85989303e0861360281ee5477620e9d25347033dbeb835bde130588626f19a24d31c7596bb97f7582f", "CS1": "040c90ed265992d63c62203c461f91cda133f6ac3400e834f6af1a508d6b07bf6223e072e91f866424d2896900b34bf2b00b3c23141aac9514fb8fddaaa68aa487", "CS2": "041b63fa2e87526bdfeeeda00ec237ca79111bcf7b28a8596a3f1559de7712f0fe1928d70f21d32d8b11b605b5ee38c4583a196ee0ec508b7f61774a6379ef30f3", "HASH_MPIN_ID_HEX": "f8b557127f626afc32995963b7014077916b427886353d31fe765e3f2b6ce36d", "TIME_PERMIT": "040284b1fb492b506eeab210fee2e1662dbcd76bf32e91dcfffdd4693d89b723b21256abc867fdf0225863900295c1aaaae441df6f072810c6dc344afe875b24a6", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33365a222c2022757365724944223a20226162613537373462306338333239313438303165666265333763366430363335406365727469766f782e636f6d222c202273616c74223a20226636313836663136383834323135643737303830323465393464303836303035227d", "TOKEN": "041c76b545fa858697f1bc8e1b9fd4cb70665c766014ff0d31ff1b5562ca760312225f993733b489552c148f7215d1b160c0489ad0501437c57b4ae588ca76b93c", "U": "041628e73f8c197247653a7dad626d2324af41e3b7e941dc3e9001c67bef3fa8cf0563eecb288ae3bc2a730a5f26592fd694dd9e4983b4c16e1bb6421f94c0f3da", "SERVER_OUTPUT": 0, "V": "0405b053edff721af4378cfbb3b0bef4f1fac179f6ac29db9594fb6faa96b1fff0112f430a43a8c7bcf48fe969efe0a9ec1ffd8a3071362b11737f2710fdd00560", "Y": "18de3bfb920c9c5ea3a0481aa067df6bf4db60083949345a01a113a49a322a47", "X": "20f7f57d7f8b266fb083ef23896b2936c1864c14452bed2b0c0538df2719c272", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:36Z\", \"userID\": \"aba5774b0c832914801efbe37c6d0635@certivox.com\", \"salt\": \"f6186f16884215d7708024e94d086005\"}", "test_no": 19, "UT": "04091f85c760936c842685531e87f0375dcf1541904526a8c9b369dfb66dea8cd4146471eac084c3d2e310d2df7fe0a8b7b70718d684ece3ca088351195db60089", "MS2": "0820d6f4611ea8bba62497bb11a80364c5b03a44fb07b740b405a9777598154f", "MS1": "0e50d70385fb6c0bb4467b156ba603416aef6c215b24c49467c8cd0cc04e849b", "CLIENT_SECRET": "041de41609ec71c8afe088b5702a96c788dfd92e443130c1b288aa2790488467bd0de5a306084e1b2521cb00d1ea142fbfbf84ac2ebce64cf27d48d2cd54be0718"}, {"SS1": "0dd0c970af2e77ca6e2543469f1b3f5d07817a24dc43b3935d041d7c6f5336db160412530bacf15ea14affead9593d11f6fd3789f97f5e95ce9cd36cbcdc26751b3e0604ab0d81714e06f76cef87ec1494231fcb41ef193b5b2023cd74af39d9030d0c618817962d6a82a7fd7cf76385e4903e85c8df5ae17da05fd66ced2135", "SS2": "0c65488a3cb5e84e3d85d65e3303b99ea0dea7659ec9d679615bfe343eb207ca029b78a5fbd66cc46f1a0e7b8f17878fafd94ce7fbb7d76770b927ee083f6cb016745be36acd7844eb93729652c70e2760fa38e4f56eb148787d52525913a87407d5457ea6e7f459ecb545fbbfad566bb2087d36d9572afed5ba513929ad6b24", "DATE": 16574, "PIN2": 7885, "PIN1": 7885, "SERVER_SECRET": "0366f02cfa04a04212a4a9b7c259201b86cf9f93974f93a3d5ff3bf956c33ad71e3cb09e921c9ed104f82f14d737e8818cc6f2546bdc429816477950e965e4eb06e23cde92b42c92bbcae7d14fb4545021d9c0b70f43f9a733657aaeb61ec2ca16abf6fd0c10c4e1a9d01ec066b6bcc3f4ab3a48477fd93b1b9474eafd2a00d3", "SEC": "0402d9d649326090eedfa9685916562753dd62e071d51d72b701ceefdd5d4b9bf123ddab21f8d860addd532e3629a52b6526586181260b84522c48c508f9da16d8", "TP2": "0400040191dbb089037021337c1dd7fce2258dc9b5b45289cb378aca269275b7a3225b43eca6ff00c804ef04421d075e74d8d21b5e89d09c5306900593151fba8f", "TP1": "04209e1b485e3e73d3f3215cac375d13d4669497fe5bd3d6da9eed2a99b4e399b61ab0c903b2b3fdd3e2c44cba8144324ca5d224ddf147150403f5d873bfa750dd", "CS1": "0407d60c02b80685c7778b72fea5b9a149e2b51d969b6b0644c77b74291bae1d3d2134fb7d21eeafeee9c7d67ef050e40a0e418bec4df4da1a51745f345d6e1f00", "CS2": "0411fb6c798909802b581f2aa35740560c679b6e396af76172cfe6b7d07cf469300726ebe61a70f9249a3a7ecf72c6cf5ff219676b9fa90a1632902c4e0c86e79e", "HASH_MPIN_ID_HEX": "caf266b7341eec261b46d4c1bfee08062ac32bc49e4a2b94c9b7303280ded76a", "TIME_PERMIT": "040524e4b847ac3da00347a0aaaf7a7c0561bd92d5fac5ef037bad5a38f268f06421219837249a6376d49344455aeb5dec97e31b10a4cf47ede61effdc40d73176", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33365a222c2022757365724944223a20223062303638336230373936383964616136363062306535646236613437663136406365727469766f782e636f6d222c202273616c74223a20223633306433636135336462343839623535303235626162363435633166336431227d", "TOKEN": "0416a44ea26234ea91d44ae45c7a71ffd8da71d2f7e97e6a0251917cfd32aeb5c51beaa89d67b49897f46140327342ffd0878ef5b44d63d2423efb9bbd505d7df4", "U": "041cb15cccd63d87f2c2cd9cdba9e2cf2f5ffc8e853285fd636565b3955d8e63d91d2b31b5fb1f438af0ce6b517c4512905658c9859dc596ffbda5abd4b8925dcc", "SERVER_OUTPUT": 0, "V": "0405d0927d171fe9e6de34c70c8e6ef25777a6cfbbc670c49fa0c591f976f1b3eb1e4d4121d037d7c2a95753a16637fc650d966cf3b4a0a8df278729564e60b23f", "Y": "17d24953a027a9a5b6f2dcaf3308e699ea1e8c220a3e42714c8208ce6289d22f", "X": "09b77af8686c4a22fee9a8d2d43a962915addaa0a51551f4701e72ca26a4f8a2", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:36Z\", \"userID\": \"0b0683b079689daa660b0e5db6a47f16@certivox.com\", \"salt\": \"630d3ca53db489b55025bab645c1f3d1\"}", "test_no": 20, "UT": "041e3f80ec282a8f8d89306ca3965b961c9b69042e9b4f6ce19a5d27e9616ecfd619bc454e13af25b16e2b234abaaa5fa76e6be2aa0f1f13924fcdaeb231fcaba3", "MS2": "112e87a931c0207981d4bbca28b7f267dff219749acf0989fc6eba551f915e95", "MS1": "193b116c85e827f1b1358f929ef572dda8e9d31f0a7e62cbf89fd85185e2645c", "CLIENT_SECRET": "040f19612ecb8d126e40d3fa0c743d17113c04d5651aa0dd40e526708c627b4ab41497a80c80af7520ae5501c67b72d88a6503c79f5d3c80e1fc02b14b97f76e7a"}, {"SS1": "014ae6a9ce2c392877dbd7d4f9b91b40520af62f45ed1e5b3639415a60804b970a28d2e483b7a8f0178045e2e93582c6413afef812c81ef96683fd54a2468f4a04f2bf13a0801952422732bd65ee86fb8b3cae8448297be2543a720d8551431a061435fb492835e93e738b8612fc5dca577c2e304aa1266f9361a160068060cf", "SS2": "1bb85e0ca1f0a13b63a3378404e3f1985bfb06bab87a1bc2fd0a1ffbf1c092130655a4b2e97223d09acabd9faf31898487ccedbb81f49bec18a16fc1273ac2a209f983324f06423383811d42e913db7eebf12a284571e7905e58cb429261e93b10ae4191b832e83ef83c696d7d702d2863d473d5b8990cc187f9a6664f1ff2b1", "DATE": 16574, "PIN2": 514, "PIN1": 514, "SERVER_SECRET": "0c2637ddf8cf939d0b60582f5fdd18e48e49eeee1a5110f2ebe3979051bbdcd506b9c35f9cdb7b88758b3730511582c0cf80af617c600f866dfe8eaff3dd623f1923ad1879e43e7f2f8738aeff629114c888b7ba5f1657f387730e3bf67556c408dd4376cd423289ab5005118377376a7b59d2b71a2eaa8a400398db58fc8022", "SEC": "041d912fbc7c9f720d58426c6b4d05f4e853804fe665b81fcae7798b71fe14bcc4154bed5df1dd89dffc0226a2399bc29028559ec9034482ea692e4fe3db1888f8", "TP2": "04073f19566003ffb795d62877f7b9a2ac28181f0eb8149620e7bc6a65864afc2b1c13e696e53899cf6f706d5d712cab089206be8e585af095097e9ebd9af804c7", "TP1": "04053256d167e754b4d67e6dd532c65345c34876633f6d9830995f857a119b5bfa033246818fa4b103adf578fd7fbeeac447dc4f51d620e9d876007fb90dd19515", "CS1": "0405fed9dff1769b0def4b20ebb655b961c09f56706ad7735d4277294b3b938ff91726666f4797f0b08324565f3df663030a743290d052751c6d3899245dd0c69c", "CS2": "04185d1af89ed2d1527a019350e795a98d67bfb01aa5a0654cd82c7fc1d524b5da0df64e79fda148a0c0aedaffc4ace71b8ba1cce1c2630260bb393cf47bd2445a", "HASH_MPIN_ID_HEX": "0cacec648e8355ec4034564a536e8ade0ce3188c991342fab92aa2071632f0a9", "TIME_PERMIT": "0415cd48ca7dcac0dfd98dddf0c5ebf52c199d7a8031821fe07da7ff0a74b2f51611fe05cf7f1e86f8d8b4dc18b1407a069acf335ecbae1ee2e20cb9d1f2eab95f", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33365a222c2022757365724944223a20223637346462653664353730326530333164313038306633653436616533373535406365727469766f782e636f6d222c202273616c74223a20226135616632353939613432393135613630363863326461383639343337363936227d", "TOKEN": "041d661b718abb7296faebf974f0f77bc4e47931476c003d0e5bbe2f7e2faa0dee06349b7b72b541030855698f0656d01260d2a8d7316cf7197986a39aa0aa7756", "U": "040e22d7265f10d0ffdd810049e99dd57a1d04ce99331b65c5e1901ddbc26f8d481ae64d1bbd56a1756261bd30096daa469b8ea63e7bf3a4f2185fd3817a138d98", "SERVER_OUTPUT": 0, "V": "041b96190d64c330b4bd04b05406a1a4a9a0e19684a679950f445b050a09addd531dcfed51d0c56cc8a6ca4e40bd729f8ac52adad3dc59182b3e32f005234fff79", "Y": "1dbeee1d8bc8b38c2ee8ac785c7306ee9928cc0a8f7e5f42b881603673ae2aa4", "X": "234eb04090e2787217bba29c5d700b089a481e7d288bdd2ecb2a238c7bc052ad", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:36Z\", \"userID\": \"674dbe6d5702e031d1080f3e46ae3755@certivox.com\", \"salt\": \"a5af2599a42915a6068c2da869437696\"}", "test_no": 21, "UT": "04004df0c878150e3dfac838251434bd860b47db0122c48b96539cb01c3f7e0ddd0d12e1b8e6f7a7fccc9f495b38699512c32cc688afb669acfacecd0dd18274e7", "MS2": "10ab1a81bd404cab14df9c47b0e4b4d7ae3873c05234f617127a7ace06676533", "MS1": "09be2d818b9c0bea45cd557072a866dad7c4602706c6dbf9bd08e0a25ecc25e7", "CLIENT_SECRET": "040de184766f4a9f38d10a28fb3db5fdc027e0b409ef56ca29f3477b5c8eb3690a17d30ba084065cd2be626b8b1ab4e9c4abb3244702f795574d51d331e6b8fe1f"}, {"SS1": "0cc291668f7952b9055779656924b7c198947c8e75bf09edd7b1beb0f2ee5e06172560301b209c69e2bc0b9eb757d6192e87683bb260ce8cd33800dbd1995c5f1762c00d0cacd6de49bdbfafeeb0d35ab8e4686f0f8ec7f26a07e5cb4cb3d0131de18aae447a09f39f5c68714be74e395d00bb40261e71f9bd00f4bc2d6b7ee5", "SS2": "00562cc9c42b112ce89dae86a595e7fc37ab3a0a0adbd573944c264b1912425412d00f32c88c2a4f12c51bddb517f8dd6d52449f5908641cee8f7312775a633d15959fc03d5c503f3d3477822d2e7d3f297884c9f5324ca6d9c2e7732d4b6c6e21eaf402c5774a4ddb022963a8ef421136ff54c6103f2b762a328c4c97f344b5", "DATE": 16574, "PIN2": 6647, "PIN1": 6647, "SERVER_SECRET": "1de34ca400b98aca525864e01937daa168cfc59ef7fbc87283a9cb5d20ad6b840c352c9325af986521016f3df7b641f1772e5f207b6ae874023cbe9ebadc248f18852799f527a077c8ae3c61cf018637719b36afa79038de73ae79e12fa776891545c018c7c9d9bcd82db0fbf6a20ae8563ee4a67fe42fcd5136fcf8dd858920", "SEC": "0420808fff0df89f2183d1b925560657eea5e7c8cefd2f143f996bff9d45b359ab12dbfdfcabbb1d7bf2547da230148bbd793d53bb09bcf484474b0eaf2b9523b8", "TP2": "04075028b3126e036d8d1976f75ae6bb79081a7037f0cffc25d6e60a9e1a1006ca1692d7cc93a8223f10e1a69f639a031b1bf011cdb8be2904eb5ba195a01be223", "TP1": "04071d4a225c688c6e73b5d25c62d50123c009c486df505a3a24c130fd58fb0a8d15f8bc09d150d78d09814e78333b8044bd6045912ec72487e661263051b9b110", "CS1": "04198d5152ecc159e987a63e1f87ee774dcb3773756cd8ac22610ed7537d7f2ba013258a755c9e4f33d628a074d3d9fb7313ae5e90d87daa59487816bdb71c5bc9", "CS2": "0406721b44cd168f9fb5277c9769af188c1f1d44710522e9661b7a210ebc7c882c03c52ed27499816ab2028580e2c0185fdc77dc1025762f9decb44a68114983fb", "HASH_MPIN_ID_HEX": "c3e62a8fb543b5256b5db5b2be0ae8bac8bc94f9b6df95279628ff8ddb8a5c73", "TIME_PERMIT": "0416fbf0f43a1c9355be1fe45a19805c3391999d4454997eea1037005e67b84bfb0d5968bc019285959572f81a66e696e07c63bfbdf49c3134c961e1dbfe54a4df", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33365a222c2022757365724944223a20223734373362613565623538613638316539313839303263323836343362386564406365727469766f782e636f6d222c202273616c74223a20223839353265326438396337333366346166393236653163363936343036366239227d", "TOKEN": "0407750d6b5115a1c9dc66158658aaada1c5fd9868267e3e6064179203241ee30222738d54148d5853ce33aedcadd41dfecd98a908375f360203f0828c95b9a966", "U": "04022bf761b3edc54f519f2c3301ab626323103b962c6f632c2d412017691746e10e07c12ffb85cb95340f2516d3c963d8ab515957d3dabbd23085b97a226cdc8a", "SERVER_OUTPUT": 0, "V": "04230ed63345122cb191cd4bb56716a2737407c581c49fb36b8da1810370367c2b078f755df8777e88b7166e6bf4706f497093d54602577c5eb753238a5ee7cbee", "Y": "01bc4895a4f521ec15802c1243704e1f7a3e516b9ccfe03f7570b42cf446a9ed", "X": "15abce350b88dce401b4f7b518863a0b76ea5d8c42351f78196a5f98958abe84", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:36Z\", \"userID\": \"7473ba5eb58a681e918902c28643b8ed@certivox.com\", \"salt\": \"8952e2d89c733f4af926e1c6964066b9\"}", "test_no": 22, "UT": "0423518d8ee8f13486bd46c158c85a0ff1327b7abfa1dc077869860a4d245a84061337d101e79010aed7ddbc7fce12e73a47b03a99d31841819eeba0a207f6eee2", "MS2": "1812f69ae302f0e4c82141c17ccf0e9ff3e3baa6ba9ac00ef1db858a93762ec2", "MS1": "0d02777320e1a682d3a30b1ec321cce6c3d6efde89dece2667f807e13d320568", "CLIENT_SECRET": "040fd72989e82f0bfab933221639231631f7c8bb7d68e0ce845e4e887f56c68c8604b524766c9137b46cd93f8f867e55db4a00d29eb2fd616c12a16c51d8e772a5"}, {"SS1": "208127511894e2b93a7a19b37923409260b131b56e767358b63eb06419650e1605b69d512e469ab3e72c6266d22274b8f8763e0441ea1b2827ebf6f9cff1621219670bd7fed9c813f41c0e002887049d34afd10fc60e7f8bc2dbe426479f1a8e194c96dcac63b8905b30951d4b70d36bb105b2be634f307e68fbc820a3258127", "SS2": "04cb55f642909b8c2282e172c6be2221d8a423438573926a11687242d2d467c31375c5b53c49c359e83ecef6397c40037e18cac2076825adbb4d4afe812f16ff23b6dd56673cbc7d8cd0af17f4aa661797bf6f8771e554e1464535f0348efd6a16b955a3d96030490626bdc331c9a4c59146a6efc961b6bb8a35205210847047", "DATE": 16574, "PIN2": 7469, "PIN1": 7469, "SERVER_SECRET": "182d2edacc2f4cf6baad75936355e22af31bdfe459813ab3b9e6a90d69fa2b501fc77052784845d3fd7eae3f0f6c9b461f1b0f47cce48c6dcef19767baa6fcba16bcda624ed64ce2c43a9047d30bb25c6efd90cdab7f488c8fa5804655eba4f91c386d4d5a71912acc268adc9eaa6aa5928f3919bf78968ddc6b35569bb2c337", "SEC": "040d982f0e45adfa3321fbc05256502a1e7bde7e617c00f3478898af996aeb346a107ef57165557bdc224fd0a54bf845987e644d633eabfda8cdd0968e6b7d0b3d", "TP2": "040351e5b2157f127e4d1e2c1e71e162adae3a4ce82f2914a2073f22c7e83577b60daa781af3f663cd37583afc93d5535ee6a43131edd1f504f3d95f5317994743", "TP1": "04029e23c070feed99f966fd5ea0c7c5ec2569856147ed95a4cbd3fb2caa89eea7083ca2c048543694572edcaaf405d0de2478b55010078ff2a7088de28513ef44", "CS1": "0404fb860a5f1c200fd2b6fd3c3f3f7e5244ef335a16184dae32ce51a2fad8aa2c20819be6eddf0629e76e31cc42c79d9ec2d380c20bdf4080fceeb0a2edda8870", "CS2": "04190ea3e1c147b9668268d8d985d2788a56f15d7be5db72d490a30e26830769951087aae74754332ae31d59436f727e981a329efc471cf217638bfed88e17c354", "HASH_MPIN_ID_HEX": "74ac22854525087cb79ce41341b006fb38df44b56cd5423b92878e73bc60b86c", "TIME_PERMIT": "04003c3ae91538d28ec3b907bd22c943210e68c024c7c596977b3ab5849b1788dc031ddad391ac09ba5e87f3f7478a6704776880d0a4213d3a3d1df76be46e582a", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33365a222c2022757365724944223a20223338326135393561356363656135653136356564376134646166333361383137406365727469766f782e636f6d222c202273616c74223a20223035373334636535373638303764323534623264636662306537626134346439227d", "TOKEN": "040fb3ffa1cbff82b3c91afab444afeaa6efa9e0ccaaa81b90666355388b7a576c20ac54b7e4629257e10c718ff2864aa560b8b53fb1cf27b1b9913fcad150d036", "U": "0423c338f6ca440713eb3078629a3a0d39158cb2e2b9818136408a450adabb4fdf13393824951d58228aaac3ee4478cd1f3132186b7a9790d9bb8b9454586b16e3", "SERVER_OUTPUT": 0, "V": "040e8e8ef6dec47b5624b9513002c20309384196616a4ab99fb935207f63ee5d870bbbd8bf5a70482bc97e622b4b93bef1bb3c8fb334e5239f11bedbf5f189e112", "Y": "0cce89c6f8ab07bb89e41cc9760d7aeb3f22e302c8ea46defeada61e13b671f8", "X": "042996fc7381b42de783dac27438f93643adb3eb63686108c37a7c014b037249", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:36Z\", \"userID\": \"382a595a5ccea5e165ed7a4daf33a817@certivox.com\", \"salt\": \"05734ce576807d254b2dcfb0e7ba44d9\"}", "test_no": 23, "UT": "040cf4ddde664d96862d209c69e3c98d27a58c32d25e02a8ae76c9fb9f781afa811d954fca80614822e60e2eba2bd6d27cd5cdf9c2448a6a3fd614fb8690235c18", "MS2": "1a69289245a6b45359aeaf36449eb7a7dc2b453e50c678d9b52b6fb334273916", "MS1": "1b6559c93c764f34cce1fb61006b4d418928ba005d0114b9a87f4e2118e5bebd", "CLIENT_SECRET": "0402b6ff92053bf6d4c61c29fdcfee20133867c859905fc9dd98425f95e7f63b420b7f8473b661d9aeb3705f7483474e82b483b6ec6094c91d032facefd2de9cdf"}, {"SS1": "05a2b3a6502e3a59413e52b0ece27c3d308f5a3f30061f600f7c43b277b335bd0bb6a20942855b5cfbe8475b1f5457d681779ddd15c450bb02dd1c7d07c9698b0a8bdd0db6cfef47e28c1887439d395f1cfaac965273468ad33de99325735f2a03ec9d7b086642d5644e563645e30ba82eed30d7c8b673f7caa2963a70e7f07b", "SS2": "02f728de8e8c465251bff7d36baa34e27cd834f9cf051ced7208a9d2f662d930233379515dece8d8deb1ce483f9c5cc11597468a48696cc4776fa29d6bca62d416198e9cf029d806dd0b782e69302f116bf04cf5ed297d0ea0b67c463dd3e50e0c91da01d94bfdbbaeafa874f387f73dbfcd3727e7b2dba9da1a52b47da27e56", "DATE": 16574, "PIN2": 2524, "PIN1": 2524, "SERVER_SECRET": "2371db2e3582241ad7149dc0c52244c7b991137b948e0eafb6a8ef5fedd58840106a6d420ae7d761bf1bd95568d74b5956e1268053ead19ad143a9ac48177b3414d4afc66c654e504ee441e144a58ce247e09085ad4e58f0bf927d8d5376c8aa1ba85ed1f7e94a65da9fbc64db83564f5a9a2c1b959ac54a1d2562605a6f9c99", "SEC": "040aebe499cfa5c24e1eea3c9fe00101eb7d853a60e92194882fe7f1e5ec555d291edffef264e2355c9cf589fc578fe91f7208bc04549e0794aebdc9bbe2f8a5d8", "TP2": "0418bb7a849f5dbcd404dc4a3f14269310e6f028496469bebea6a1c410de14de6b130d5ba6be03562070a8371881ac01ad073956759c5384947d8fc271587765af", "TP1": "040ff0a5c162ea4d0248682a38a0e63ec280a723fefcfb8609981d98d8aed267051119796d262b6e8d33ef45d76b233f869ff1cee68009995ce1dbc1705f144913", "CS1": "041d6fd44cf624bd2d08429c6a666ba054ae51b90b4cfadd7050418cff5da9eda90131aa33f1d042ef25059792d4b9bcde172abf992ac128c1078f5eab80f58298", "CS2": "040b4d67e12b86a9f5d02a148addf4a32d2362c28c4389b4a4e5cd9aed7a5f4e0d196b42b4a98b8a20488f08686e61b9e63b287ddc19c906c5c8b1fec2949a750f", "HASH_MPIN_ID_HEX": "0cd096d8a85c3218afeed65d667a6207b346f198141da3c0e04088ce1de06184", "TIME_PERMIT": "040751bf75401f8bf72712fc30beb17169c2bfce3720ecdfea834e416e3dc3e2630b18168cd4413a0031990bc0a7494b9b1f84def0ee32885817e402e9e560273e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33365a222c2022757365724944223a20223031316562376530353631303837636239306164333263373765633931636262406365727469766f782e636f6d222c202273616c74223a20226463306436396437343561313830633930646165666635316634393533353262227d", "TOKEN": "041889f73f41b7b5cb114dfc33e2d3741d34ace24e0ac888f9ec08d90200c7c25503c9520cd2d7578b4695f4d11cc3b158c443e16df83a6f408f47a7bd802a1230", "U": "040c338e2270e800a65e48750f97463f28eb8e30fb33250325387a7e2c4062401710706ab4c59fea9a407f527eabb1c4c92db43ab4149f5ad6343e201c597ee24c", "SERVER_OUTPUT": 0, "V": "04155b9a44e35577ee8a746c13f8b091f1c2f0683fd3a711e074900a5b05b67d701518bbd9f60cfb21adb5dc20fd207439a825db2ffd1ee41fc2b3d8be4c6b6f24", "Y": "1dda40ba4196de9785aca8623ae51c821beebd515d24f5771b233b656df6a90c", "X": "0a029a60905ff26d4b38859287f721b8dd91f06611859e5198f3c6c771c76baa", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:36Z\", \"userID\": \"011eb7e0561087cb90ad32c77ec91cbb@certivox.com\", \"salt\": \"dc0d69d745a180c90daeff51f495352b\"}", "test_no": 24, "UT": "040c58bb659f9fc19b82df2a5a80bb3efea360219097fc43449bbfa0a81a9a933505dafc717e2e7dc57b984a9019f0dcc1799db781dede3cbe1628b3b0db77ebcb", "MS2": "01f3ccfc7a6f10beb2157a23de28cde18cf6d69afb8ab7dc83047a4ea9fc3457", "MS1": "0038a0f9dadd6658d0690c4aceaa60a696e2a125c696762d3a1c16c56294cd59", "CLIENT_SECRET": "040a301d90524959a4a4791d68e23fb2ca294dd85994a22a8cf7ce634a16d9ec4c1cadf3017bd323bf20914cbd9e3cee9a8981a4a5fdc491b33b94dea6d57877ec"}, {"SS1": "1eedbf8b632a9b9bb18843439adf10de8cdafd5b216b9cf2a0cbc81a2d9bd0f2029ed74a59b1a4deceedcb9603efc41f582c079323af4218c44f71322e9bb2d4060c13f2bc014ad201e30867ed1585b93a846d3d53cf5e7b2e24c9ca08a6a5c4223300b56529773d2a80e284df8f9b0c528a3eea40081178efea218aae0b4f91", "SS2": "1f415014722071871436e174cf43c0ee9de3936979ecb646f970d24a2417ddf515d0217fdc3af8dd3b57353dc29ddbc298e20d74ae0b1ab1ffc40a1303fa41be1f57aeac96174d5bfe479e9fb506df260c083e8ec2b3d120c006a13e6136921b09f8fe6aea21aadabd24e3026a5e0566f35d82520271af8a167e46159bf26c97", "DATE": 16574, "PIN2": 1974, "PIN1": 1974, "SERVER_SECRET": "0d996446b6a8a1172f5ca00af2d4365a3dfc44237b837854a3a2492b350baf2a14dc6fca4e15cd2ad213450bfff376c8779656ad782aad6592e529ccc3cdbca7074e3386f905f8f172b2e6f7a4ec365340c3d46f2c2ebe601493cd677c1998e516703755d45a041b1d6a02d8636b91b6ff63549d3031ead42ba0b2c0eb80bb6c", "SEC": "0417e0c0db3a03c05115dffad812f97912c6aba59538c92ca1c05fff18f4e7e3a703dc12719171e4fae7a14f4466e84535d49d6b8c2930881fa599d079625ea0bc", "TP2": "0409e088916e27b5ed082971e62ba469aa381034270cc56de50fd604270c33dd3618aebdc9ef5ef68fe882e0db4fe9293994aa3c9931430765de53b4e8b72b2396", "TP1": "040ddd64aa91d60f73bc7112678aa94d8266db234343b1baea89bea3f02846cda40eac9aa156d45009ce45951efa06e917ef103ab0d0e435ee90360deaa79181c6", "CS1": "040180e4fb5079f3325e0683621e61fd421f8a93c9009c92d5e3852571a0a88c52158189454143f8b304ee0e7b83eff75fe2eb9948802cc461de4d1f95206e4c5e", "CS2": "040c68898288b44352c34923d7ebc664fa68747c985ea50e67a0949d63f84ce85104d6b1f822e1c424712dc077d493751f17df3154983d25e4d17bbb5b149d72e0", "HASH_MPIN_ID_HEX": "8b1bd9a8c376c90af85f8b4a79fb4c893cda8814584d166ed1fe5e7d6780b853", "TIME_PERMIT": "040bd9d4a26b04d935cce222b6ac1a9a88b4b40b223ba43468b32a5dc899b4131806f25be9989f9b5ec195da7f32a708b138c4b14fdfc95648ed167926765700d1", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33365a222c2022757365724944223a20226234393231666363376337636166636138376430633961376135333766313864406365727469766f782e636f6d222c202273616c74223a20226161666561613066353236393132613330316433623433336131376636343461227d", "TOKEN": "040064efa04e5706c7dc98e6238b22ce5711674dec996f521339bcc1ab8454156714a276233a17871d0f64e2b3aed011dfdabeaa577ebc300bdd064f69dd4dc39b", "U": "0417d5195d07bbe908062c7fabd6ae470ceced46de77ca7f0528a38f36d072111e0563d9dfcf5e261d4eadf5df26e9e75a13870c450139c14d25e3e9471beb354a", "SERVER_OUTPUT": 0, "V": "041839b54091b8da7aabd7ddd8e46bafd830481f8452d4c55e3d033c7314afe1fa1a3da402b9f05bdca7dbc58fa7c0c0cdc8a1a5169025f691aa0b29ed0ca1060e", "Y": "0cd1fe95151666b7ee185fe68bcb9043bcc96e9340c64876ce5ff6385eae73f2", "X": "1771c3c82c75a448095481b869a97b8edae96649291382daef2d5f3778dcde32", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:36Z\", \"userID\": \"b4921fcc7c7cafca87d0c9a7a537f18d@certivox.com\", \"salt\": \"aafeaa0f526912a301d3b433a17f644a\"}", "test_no": 25, "UT": "04043eb58b5a7338066e9b30e81b1d49d233a926027373f117abb380912c82010221a594e12f9caf08cce40fdb845fbdffc170e945793e9c2f0cb255a004401474", "MS2": "0daa0ab5dabdb79d1679a681b3efbb4061b5cc9b5fcfdf0e697612dc2e801cac", "MS1": "1b05a8654de45628cc4a4910589a258a203021c1ea67ff1e1f0bf0c201b24d7b", "CLIENT_SECRET": "0420d61e8c41b014ac3fb5a39922e2a1799ddee41ce03985c940f1e4e506ecb07817afdd244bc63d4ea9d2032a309dff62a3e7d6440b84c249f4fa5896aeb07c21"}, {"SS1": "22bb08ee901c5a370a5b1530eae322fbbbbb526968467ff486c27afd7dc5216a23fbc077285f90f1ff13fc94834938fe2665552ff25965975ecff413fdb2367e089075e4fed42eea2a579736678cdb74b904cdec195540636e9e473fe15b8ad803a6fe497d1c0e0b9f0a6f07cf06e8b63a6534e1bf64fa7a7c16395f01b8c7b0", "SS2": "07ba76f3ed7c975f215bb513d5dc0725208367cebbdb6ed937977313c7c223e805371832fb795c3f5f53296fbb1b256d54377889d7ba3fc23a0b055a6a37088a227a951a6afeb6eda3f79a0ca1e8b7984321b192dc10981ff7d3d57aa2b3c76c0cdab0fdb7e191801287b4ca513fc8e79fc7c963a7ecf766c6be8928a084f69d", "DATE": 16574, "PIN2": 2465, "PIN1": 2465, "SERVER_SECRET": "1f4ebe644e77138ee521641b0bd32e3c102962ab6f90930d7be763476fed117109f420c389c916b21d662072f44fd3b11147ccc20db716fc878d4d6389569fcd078734865cd83f283f9b7a2903cbbf15bd108a0763a6515b25c15268b3e5aace1515fa87dd1069dd1f4484795a5be3370e1a562846516056b6bc43211497b24e", "SEC": "041fcc5fd609c1d21a2ab293c6260f8bf7edebd1015487085d213dcb73c5456dc820fd067b3693ce09e35ea7ce6cc0f517fa4ea64891fb3e79b25b6648570b0501", "TP2": "040f47c57e6ba53014970aa9792ae6879d657ead3c4c0b02d4f809eec1950a663b03524fcff9496b6211ac327e0009e317b9b51901f65b97e630463e6aa4a5f0a3", "TP1": "041cf0279ee48cb9912b7d3c990ec6dc581346baa5deb8319db216c71b335bff7215a79042e9a122af3f358fc6081146701016c5b51e829bdcd4ce9bf36d89ec70", "CS1": "0416f33afb9669b44f3b6fb5523ea5e2b88df8217a937eafc34a15ded9ff0bb2391a4d0a42b14083bd2547b5ef6fe64a41e4de1107f0f576ad2c810992542d24a8", "CS2": "041bf56cccb84cf6addbbecd21af61120921c473e84649734abb10fbace40b0c352291bf79194d7a6cf7ee4727cb24259b4dbda7e363ad1e6d4b86d25d651791da", "HASH_MPIN_ID_HEX": "0de136cda78bdca4bae7d8ab3744a9c7def1742f65816e90e678c7ed1b2f665c", "TIME_PERMIT": "040b6c2f48771fc027dbbca50cccf523106d258a82ce3623cf5c18f3605768d3ee1c153af852fbf90c559a9733e01d56d60cd7c8425089ccd0998afd545f31afba", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33365a222c2022757365724944223a20223633613634656564363363653631663830623639653339643332656635616662406365727469766f782e636f6d222c202273616c74223a20226666353938653761646661343861343764343362373333393062663738386232227d", "TOKEN": "041a011b091be3152ace0578b078001f6615f2f4d3622283e25dc616e8f04ef9472391e574737f278a2608eb14db8c6cc8173dc778fc7925ffde7eec4bb129398a", "U": "041efddb6f20f95cd299962fc537d3552f65e1d28524d821c789677b9e777959c708e2cc2eda986f9d2d647e655e65e26ddcb3f89442b0d4387e60f9bc98f04a73", "SERVER_OUTPUT": 0, "V": "040d0d6c365a5b03b8fcce819752c306c3535703077ad7e113fbb209ccfc7dce1b01859e4e6f3fe9e9a63d8ea5ba8a8b62ced791578d8f4dc7a73801587e8a6e42", "Y": "139a053f55cbaa7218e6803e952d21eee8ec850990cc1f7d856299b4860eb1b0", "X": "04af6d3b0c0238094ac6c5edd812b9604c38e633e571c3393f369411fe0198b9", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:36Z\", \"userID\": \"63a64eed63ce61f80b69e39d32ef5afb@certivox.com\", \"salt\": \"ff598e7adfa48a47d43b73390bf788b2\"}", "test_no": 26, "UT": "041405ea4cfd6195d02bbb2f4f8f63b34df6016fcaa861f5102d6ad21b6bee34c30b0d8d6a5e617d5bfbba2bdfc03e37a8e5789a81c34280a2e41b1516954f5820", "MS2": "22aa5edbf636ff51dec92f530a098e8418d62727f19956be3a5b41ec66d7b804", "MS1": "1b6f7ba281b7d9379466a3c8c6b911bfd4b54b96e02ea7f15cfbb269a3a81a2e", "CLIENT_SECRET": "041973657ac2649af8047512359fbbb9e3e6f88ba43d7d5dcac2bcb36fccc70c4c02d6f0712c8c4d98ab21ae01030a48e811fc511f1c978f5cb7159767a9b22bcb"}, {"SS1": "11a09e13494d7d720d37cf44b3d56205c3ba55d75181fc4e4d8c6090aa5a215904ef7e83533bda75cc464fc69811f85cd7aae2d1411767842788ddb2939555fc2192271f8da605d72b1d2f3a28c09c52f6bfd4d8454a181df614cdce9cd65a8219c34076580ad741883ddcf5a4233051dc74da64c50b0f1fd9735a80cc754b76", "SS2": "1babac685b3dc77683e29d33a31f3d43db6ac83cc03b41667b8ad72a184f13ec04ea0efd0c909f0626582d0c245534463ca9c2231b3fcbdd863f394eccd2b1ce007a6dfbd3f9b79d1c1eccaad8a7127d1f843764ae9fcea4d4b333cb38d16a3d1dac7f6683811626cc5acdd30f936c467731aef076b7510889deac7ad7e4d98f", "DATE": 16574, "PIN2": 4914, "PIN1": 4914, "SERVER_SECRET": "1c3afd660fcbc0b2ab29c1253a82e3f8dd68824431c7ee6ade7521730ddce99c0ce5d745068ab0c02f3fa39bd9a48b31f900f19bde15a29c0fffef0b0cafa83809416848d3f36c8c3ee226027322e0922e9aad17c5e93885873efe0c9e692e010ffc89f61ddbcc1d91db3a45ebf4f7f86ff6e4e44235be722977c3f831048c7c", "SEC": "0412a769d884c71887531042c34eb1e4cdad68d0cb361b24f531537699566ebf61222b4a6ad1e8c78a9dd48197eddc3f9005f602db8647f0815cb811774172fa14", "TP2": "0413580fd5c4c987babbca4fe5936eb5fbff922e82e4067ce106b5b9cf41ccbdb22226a2d1dc2814577ad1a91bf6bda5a30dcbe8b770190f5fe0abbbb967e39eb2", "TP1": "0420d5c346c920c5ab1394493c1316d0576059b773fd163b5e2b05222d8cb478ad18335ab8dff2bf0486a16be2c9d6ee0ff63a38e98ded340d19df954a7cc54cf7", "CS1": "04111ec38cd539f574b59bd5c9fde26a230adf26eec52548b4fa41c21cf1ebeb3b0fbea5b2e10643172837df2709ea414d9015e77dc63eabd0dda9bafc5b70569a", "CS2": "0408e3137a5b04db6c5472869c87e8ca57bdf7061f9a0ae07ca1c42ad36fc3ac37172033077e4b74ddab07e39c28406810de94f0c91932f1e00a207717557b51bb", "HASH_MPIN_ID_HEX": "58e1be73ee19c72b115e7a04904efe983d7b80b04f33eb8c99c732dab559260a", "TIME_PERMIT": "0402acbaa53883c0e87a9257c66a59b8992018a2fedc7eb9793961bf0a05b90b94075c782ac86ef69349b0ea22a6f8a58c117f02a576f59791d144fd74fd68bfa9", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33365a222c2022757365724944223a20226562336232363362333264336138356133313864353339343634323461333464406365727469766f782e636f6d222c202273616c74223a20226538363261373666333930373135653532343633633730313437663565643731227d", "TOKEN": "040543b5f5302eee58ce9afb4f655baff7673ae9efe183bbff43eea93ae9cb86d51cdc4f153195cb7a76b36cc0866656bc77f53786351751d4dda36774488646b1", "U": "0411a9813b58055f1b1957c65ca0c9115de8a6ac68bda13130749dbf988505d6161ac407ba83bb85c725e852da2954821855325b75c96eef75ceb58f72fd9f4e55", "SERVER_OUTPUT": 0, "V": "040e1ef37f1defc2f892dca6621b6a4a8145d0cfd2f9d8c095605e35def584a4ee025dff55b35f2ad4a63cc59924b52462f2e8a87d961bcc4b08f626764785f22b", "Y": "0f33332b9c6a444809c5f7d9460eacd998a0e2cd5eb9c673936bbda4311c1ecc", "X": "1a30e36476c0b271873c777c0a38fa07ff9ce00cb3e927af3f5657dea43dfcec", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:36Z\", \"userID\": \"eb3b263b32d3a85a318d53946424a34d@certivox.com\", \"salt\": \"e862a76f390715e52463c70147f5ed71\"}", "test_no": 27, "UT": "04060ce40e6b4816948a34de5c2e517a278c5587ec157b88c56da10fff4c6be7050bbb2ab6dbcea26fbad23bab71ab2d72f0c7186a9490829da7a1d15a43dd30d0", "MS2": "181e74eaf96a76569609ab1d6389fe109272cef94f786fb5e4ca9b655f7aeaa9", "MS1": "22b9faa7579386637265ca1a93f4f6b3ebba4ced7bc054f0624dee61cdeb558c", "CLIENT_SECRET": "041ffddcf3f5e8c37dce405f5bc0e6e839a8a347d583227707f6dfd3881c6af17c09bf46eca1b9e1adcf823f801ccc673ddb9905bdcd23595db47119a8ea69b359"}, {"SS1": "2363be872ff461794a7373f613c8855463efc8a8e215089ab35cf9ae2f4aa82b0865f72e9ee8cb64c44a3e7dcf54aa542de3ed7445074a49ddf2d3ad39fa9c4414bad4b7e2b978cbb4dfde6ae13cea4743669d7fb59f72b1b9802ecf3b039c0203e876038ab35be86b98038f1b7fa1bdb4f7728db9b1f627d46875a73c1ccc06", "SS2": "173c3b288b657a21693456ca5b2de43f5bbe81c1828ffdff9984d7fa34105422014b42beb663db9472c29a17f6c2e69a82c2991afeb73ff122feb600967cdcff00716d6f1108c9a81aa4bb908c670d32f50764d64620d4870986a405473adbfd0290d71998616367145fee8e4d4503d0821fce9ba209274fe035b3c4261e25a1", "DATE": 16574, "PIN2": 5572, "PIN1": 5572, "SERVER_SECRET": "0ca57968b2addfb4282f5522548b004cafafadc0d2a76c034ced5a7fdb022b3e142e650d7910a21112f55b97551a7b73ec1c7db891f8cb8fb84ece36aeafcc7f2005e1f3ba9b5c9a4a9c69bbdbd93f9ba032bd526c67b1518587be6ed31403b920154bbe578dcd8c943fda0eed9572ba2cf401cf2a84e9fe7e13417e1c05de69", "SEC": "0407a7b0d6815285cfa4673b70b776a50014462c9f8d310eb70bf9d56c28d87fba085033b9260f3eee58ab09b214a6a4129f8b148ed748a112a975675ba5a907ef", "TP2": "04031aad7310e01243e59257e24c3155ade56f4c27dd6cfefc6a50c4792802d65a14e26c01745f6f25bfe2cf339f3217e70ee7ca344255b6589b913181565254f5", "TP1": "04149ba4a279214ca0ecd76718ca81145f97f6bdeacbdfb4e1909d1d2342e316121c27b110a60df342227de06c3d4896fc5ec897e5de84927fad71d78f72ec43fb", "CS1": "040fcf5b7edeb2b9724bd8c8aac8d32074b31fedd0bc6994bdba7fb66f3a813325016caf0dacb1c8ad57ade5855ba178be8be109f0e6be7ec5b71da2d626c7c32a", "CS2": "0400b30791084ac42dfaeeb48db6379c063ab3bd0bff03783195a46ba2bf6242e41a281b0c0b77464e2860b28fe81eeb0647630c60674f006e73d40a1c12eed88e", "HASH_MPIN_ID_HEX": "53ea61dc442d07016134d4e3448fa068f5a198af17ec893d71c17a522a11d24e", "TIME_PERMIT": "040e366d053af01490ce38ed4f71ac8921d93585971541ad1a90169c075fb41eb71a057b1c716f6197f09fdf8e09043b4b541978f686a41d61bb0a4ccf78a6f67c", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33365a222c2022757365724944223a20223139333831366665316635316535663561663534313861323634343236343333406365727469766f782e636f6d222c202273616c74223a20223765616464336637333932356564613333336563383930656163333238636661227d", "TOKEN": "040cbe6c78a70360ca8d10e07c195d6205fe50e79c59107e61f1a8f4d974f8ae0a00b122640e5f0a07290074d6f2dab4695afdec06695edde821adfcd7faae0f6c", "U": "040d5397630c40cd07ae94d9ddce63059593e92d01cfb0d9d2c329a36566635c1f105250393694b88268f47138879a81c21307236c141a7e60ea4ac5e6f87a1c4b", "SERVER_OUTPUT": 0, "V": "04129159b989940ae83166622cd5e8d83ac00ab759020967092d7d61ca194a2ef5120310481b550b412c9b6fb40775063d560ccf07a3209e2f0886d8bb0c3b8ef0", "Y": "0507413453e6c5c4520da1d05a1fa70cef0a1984c1780b1da4e1335bc1fdcfb7", "X": "0e42e9b485bf9ed78c82853734194daefbac3c3593b368dfdef6725a9f7ca0c8", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:36Z\", \"userID\": \"193816fe1f51e5f5af5418a264426433@certivox.com\", \"salt\": \"7eadd3f73925eda333ec890eac328cfa\"}", "test_no": 28, "UT": "0416ca559a83fa9a37e6979bbd629e819c4208c53c1c6a1fee78905de401cd146307114af74d23b3a6fd0989aa3e353d82d39e528cc3e6ccfc64b00125a88691f9", "MS2": "0fadb11a960ccd1f9c118be2bf1bd51bfc5ffdb4420d1eb2df5de1753692249a", "MS1": "145caeccff101b3c2b0c07c03270fb8636a07ab16576a22ca350ff009482e179", "CLIENT_SECRET": "041ec9ce112060adea2ada8532511f4cbda552478f2a833db7043367929cb56a801e32ca60077d0d8983a66456c51793b3bd590a6f88431fd5f2c68740edf1f53a"}, {"SS1": "0bad100e98e4a24b757249f3733a2f2dff1a58f1b7a64556ce6f9ad8fb711be10ac347cc801461a4c4fe8bd8e717e2b5d211816b3f78ba0ff58091c4d8680a1a04d16b694fc92585f3236a876995b94d0d0f4a0df614e8bdb3980a1f71de2aac21f761f0235821ddef76d9c82c39b43050acbb6683e238c01fc55b32d4e2cc15", "SS2": "051d9407762af56e92f28da8e231bfcbedd5170214338f52293f83d6116ac0501c803c228717328821cf10864aab6846963ab6fd3e883f190aea766bfc733f5419187956ebb0c9b76ceee720ca45b6941b698a2695b93d35df2a299ab8b5cfb2057446a46a0cd8676098cd9b4e6d21059895b06f58f8b8efb074e2815e695b38", "DATE": 16574, "PIN2": 8981, "PIN1": 8981, "SERVER_SECRET": "1244ceebc761be3a8b83805e95d3925a277a88116ecd5ed876bd260d6f42dd231988e9f6e198c32f2c2c63c9708186c5c93e52a0592890acfb62d7737ee0dc8b0e2b58af3638c4e734e9d5aaa58a1ecadcc611b7e7b5688bd8ea0d92990595021c19cdc1975f1f10165cd09b0ca8632f70a3761398414f8a4d8d672d4b68666b", "SEC": "04170da7a8b9be584ce66025eae5d89732e98bf29ed69665a2d4be4646a257fa501a95b20803dc9a913a80bc7d813535f82a033ecc543f6381361f605975e624ec", "TP2": "04049d8668c94dce50800f1c93f86dc6832213e7bd6f8f698b4a82430e39b093d00ab8ae9d424fb8794dc2180173adae959f804a84c15621d8a31215b9f24900bc", "TP1": "040d3be2c1b33b232156cd8e5f839fcde2a9cd40af517fd5288f2c0082c45c716308b967721a62523953cab1631296f721f1c410461e27b7c20c9d40a715db5b77", "CS1": "04068326d7a02adf92919264ac62a81b0fb2643121db5f8b742f72cd969459df87179973587c6e9b8f8c1a3c0bbb734ed87d844119d7e028a0d7d1ca6f85298f79", "CS2": "040adacb7f2b753699720f49d821d9afecc724fb954c37fdb554bf5a132917f3810013097452ffcebd402218d6755f4950a750cf0965d445feba68401057bb83ab", "HASH_MPIN_ID_HEX": "1daf02814045c96fc283be036a7fded1d78c5a60199f573e51f4c786f29ca752", "TIME_PERMIT": "0418167460d84858c2787d6a773e4cbdd6adc0f677b5a21341eb75f941754bb7ca2094c7d382f2c362fd7aaf823f0ef61cd9e1813c2605201bcef557db77074e38", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33365a222c2022757365724944223a20223032656537646139336630396563373835633065633064336337313135343961406365727469766f782e636f6d222c202273616c74223a20223031323366366462373136656132643665336236303561363366346133383536227d", "TOKEN": "041277f242dc00917faa2c16cfe9551be86bb9669d4248831787b5aba0c658c3031f91c1432ca62af0ed145802ca84ea2d4da7dc5129ab2a954c00c2827564ce6d", "U": "04011fe5b0bce9d7216631145e34a93fe829d63d668d371c435fcd6f1b846f2bce08be4f8cacaa774b777f79cf2b845b6c3b600080a100b9534b3515e39c4ea4c8", "SERVER_OUTPUT": 0, "V": "0410ceac1e2a281b067890de3da2a57420dcc8baa01cda288603bce3bc3ed2f78002bf646d06f0e76acd9ef94d26d5f3ee6ba1a8a31ef26ea70050db3e73f296e3", "Y": "19dd17ea86e87b2cd123a6763684a1a5d691611cc37031ac2490e844d9af9034", "X": "122adbe43ab708d2e92f833fd9dc8fd07ddb87b81387e58bf50d03bf4a0a675a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:36Z\", \"userID\": \"02ee7da93f09ec785c0ec0d3c711549a@certivox.com\", \"salt\": \"0123f6db716ea2d6e3b605a63f4a3856\"}", "test_no": 29, "UT": "040d99a7cc8c925c5605440b3513143828b2bca50e036330aead4482d293d74f2122f53925db35c940c974de9e75e31d5fa9737b47434103bc0b7f4368662e0f19", "MS2": "09448c8d98704abfc3b0d1986fb2f040789feb5783dd3e8eb946fde8f9da2e10", "MS1": "208a9b0eb9389823d760493d713666f9918997b0462367a43018728bce38e14f", "CLIENT_SECRET": "0417c21a08dc5bc2b5d5641567c5f78e51a4c2e58280b19b09f0f73df1684d191118b6fe367e10215d2263f44c09d42eccc1eec17406aac219b81cb5e6e10a2bed"}, {"SS1": "074b0d72302b4ac89a9bb672ebd744c633f7b0463e13e4f0c162b83e6d39184921bd0290d140d48d6a72343cb783b373bf08fe2eb58700e6256ced4772660d6821293c3d99784508a2713ade6c41d43f47abf1b188217439c20b39a514d5d5531936b800ec65dc1289ef74fe3efd155ecb8e2375ebd0883c6dbc6b495d15e0df", "SS2": "0133dac516e466ecb54b1a1320182e979d5800c57752d686d2c1dfb6d98bcb3a185ac02384cc1832bae5266068e233382a69643fabffa09f5c6eee2a8e92c49810c407d0c72fb80f821f730636512618f4e55b0e340b5b6c68caa332ce2d2fb30609bdd7b6415383de01361e7652a7f4f4e81c9ce9029481315520efb60c819a", "DATE": 16574, "PIN2": 6845, "PIN1": 6845, "SERVER_SECRET": "0cbc592a949e5c96627fee2de30897931b835700b16ee54737f44d74dce639001a867e9c3947b69c8e3c2b22aad72c726e70211150c876c1232b8a5626b5fdec03196e9716d4d29ed92d27003adda9af8576cb1dbf6665e6c7e8651a4333794f1235755277891e3550c274babd8727ce368f3a762b9d00a03d146ae0ef55a75c", "SEC": "0405125c3d454f7686f4def5f614390506f2f77d09e2297d8c3d53ab96474b55f3193044326e9ec297af7226b6c3edccb8a1739bdffe583b28a41d31dc84a5c5f7", "TP2": "04189a25f3b978b4996a21e08220116937ab822b121ce2495c9c8b1feef97ea0730b22876bf7ff0d3f9773bbe2751f1815a862f43ef96231b7a1fcb86e0bac784b", "TP1": "0417912752dfddf983ce62a1a66f5689977fd9c63e605d54c9cd879c8ff1f399121f88a3b4e518209d1848fbebe76efe6fc848fa2b8377dad33a3efbe5e0b7b0dc", "CS1": "040a3782bd3587bcef121b2eeab82e9591b9e0b65701f1a1e7ae513a9054d1b27b1969b9121d0e864d95cd9ec2f2b1ecab2ff45205ab739f76ea95bfe1c9e15e02", "CS2": "041a05c52a0a14e5ea7363be291a80447d352e85a339773ac8b27821e499d6202b1418f57706ec86f55c22fa5fae7cf7eb2e7623c10fdc5bf42ede720598d92cba", "HASH_MPIN_ID_HEX": "aa6d12f8834cc797e7a4202c7a3db7aa9f0b55fb0ea70101688055979d2c4b7c", "TIME_PERMIT": "041ada271a1dbcf6b69946c03088d8a0005c1ff6831370ae5bf3bb8d0394156d83148566c141b6b2bedfd99ba9fb3c8a110f7213385046d79f5e7a338526d883ca", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33375a222c2022757365724944223a20223135316133323135303363643062623034336664373134333435343937643035406365727469766f782e636f6d222c202273616c74223a20223831323031633861346331353638383263373335663766633230323632376239227d", "TOKEN": "0409eaa0baf7429260b80e37fb4cec207807e9bc15bcfceb51645bcb041f0ec65a07650ec1fde103d50ccd5bf6bd377cd752f124340df8cdbe7f9550acaf7792eb", "U": "0404516a91995e6b4b84b4404b61e0d984979e84f09577b84d1a4287d9504701ea097b2ff05e5c463d34b8cda7dfe4025dd724c9af9f2949660053d70464322109", "SERVER_OUTPUT": 0, "V": "0409c3019970848f9dd788b2bf723310bd88de3b8ce7147d8f35f7f9eeff85f8e102cbcc7e00e3e6cac45897d55129a06821762285365fcba49c17b09cfa1a0ea7", "Y": "23cce3472675166beea6c209026888956d24474ebc1f9e43651ade6885bb3700", "X": "148cfdd2d0f4ff16b652c92e2e915c924c7b7ca738d9eecb3609edc531928fde", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:37Z\", \"userID\": \"151a321503cd0bb043fd714345497d05@certivox.com\", \"salt\": \"81201c8a4c156882c735f7fc202627b9\"}", "test_no": 30, "UT": "041ee36db6a4178815078b9c2c9357a7b2dcb1872d271a6fa5723e1ae262e1899e04010e1e93ce064b5e2060afecf159a96c53760f30ba6253e5249991226941e4", "MS2": "092c364db25d8d481816a3a5f1f9ddddb771279ffebb211ece70e70c37343bb1", "MS1": "200c156a31bf817fdb6744627ab07cc57e64ae9f40b3b3c4ecafd618fa9c9a24", "CLIENT_SECRET": "041fa8febea88d9b07e4ef7f8e306fb48babadf0222b173cd9e4912ea32cb2bcee08618fa97a87fc7a86523f09c3052eb52cb36fcff6420195ba89c4dd1119a7a8"}, {"SS1": "1144bdb7c2b807e71a2dfe3697d7fbd34a09e8636148ecaf7c9f528f2bdd437d029b836b7684779737bbc34e9d657f3d958062f4584324a2149130dc67ecaee01342f2b5353a8375642bb625218aee1bd018bb2c8027f4f1459be2c5caf7078703d55a432a8336f670ab359df103cbbb33763f0a5b8923fb8aa6e3e139f66198", "SS2": "2399d30cc3691370a5b325575557c93d24ba5e1d006edeebf98002f9f0b32bdb16d5460d6a964cda7a976c914bc29ab69b6a5f101e939f18ba2b25b79ba2460304705fbd167b6d3e59ace56fb45971683ee6d10b2f97aadf8b3f481a8e55d1ba04eae72afbc5e36e8377b7760cdd7448fb9c6d541acf7848f4e014ffd18d8514", "DATE": 16574, "PIN2": 416, "PIN1": 416, "SERVER_SECRET": "00942626398002eea6d800866e558fd416b39427f2f062d3fa78f634ee2e89aa1f297d5a1566b60ff2bec4a8c88e86e03911f4ad1f93f3b0d1a0e6e27429bf1a097c023f74cecf5481c0326804606d455d1d20040624fd1db209f9c01fb87eb3081cd82bfadd9b1c58693660b3fe6cfbbaea07dcbe4a715cb72e2dd867aeaf37", "SEC": "04018cde69ae0ca6f360d70f4210691ba549f5482506b4556a57d723e0c5df2cbb1b8b6b5ed53abdb39de2794eceeaf2a8cc06e88a8032ec3b36e0c82834f35e46", "TP2": "040bb8dc3d8e0cdaf5484ef2bfeca12bb5cb4e970040176ed1e219c5e29cddab9b183fcdb74dde733a7b0e87b470e59862152a6d0e3dcc9f3f3c1d3d1bdd4d9456", "TP1": "04034cc2f2d50daa77c6bef9aee366e110ba7cc0baf6319d0a8c2b32ace36925e31a0cb86330d4b5fb6005430d9210d256ab1cc37537181a95d1d68f6dd0cd52dd", "CS1": "0402687135b3f83fe3e4aee950a1898a92a66d6e11eb424f64637830681c109b9313848e65c7c78d3fef0cadc3cdcd0d3c8daf88b153aa73cf66bc6dbeb3e0b1ab", "CS2": "040057df7f3b8a59d8a8f22ca74159c24edf563bcafec09b481398804f7ed837a30eebc301b3c33e38f0aa7babe00b0eee845256f94b28b6a9733b3f548595de6c", "HASH_MPIN_ID_HEX": "0eca83d0612b7d9b528cd0358f0cbf8a48c05fd61dfe200cf5842ee3a4d3b372", "TIME_PERMIT": "040c4c06329d77c9502d41576acedb36dcd0562a2b20e9c08ddd34ef4c7c9f70d70530517e2dc880677278b3a314b3fec321cb0ea5bb9fafd37dd9b6d5cde06f45", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33375a222c2022757365724944223a20223138666135323734646634336235333733633439363035326338323866636436406365727469766f782e636f6d222c202273616c74223a20223865643737663231613464313734363434343731373238663764653562393465227d", "TOKEN": "041978382a2e122cdbec581f7f7755cce8d69c15af6b5aa2e3f78b206b6d98044f2311a9f332c715982d0615ffb87d29bc10188f793ea4de27e7ad530577b50b46", "U": "0411984b7e32e93efee2c551bf887d6419b7b61e4cf22c74e5ecb57573432436f110e6d79565394cd243b4b4b4d22ad38dc1205cf62e92bf6e908f0f13d63c8b91", "SERVER_OUTPUT": 0, "V": "041f5edc0ec93381182a30c16012a59d783a4f8ed9ed0bd15e6eb860b04e71840c1559d57c44429aba5b373149f80b8f598c105183687512b4862c69d66ccbd295", "Y": "17e42b32becc187ef207a1a0c5fd3a7e1d48ed5d771b28ce25b69ed19a6536b4", "X": "04bd075a6eaffbbcdcfdc9afeb896384cb779d578e6f4f4f0cc497fd8a914179", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:37Z\", \"userID\": \"18fa5274df43b5373c496052c828fcd6@certivox.com\", \"salt\": \"8ed77f21a4d174644471728f7de5b94e\"}", "test_no": 31, "UT": "041395f9e8b111445d5d4d006907471c4cb4740d848bed6c37445e3dda577e73af2255eb2d34dec0b48fcbc9dc0f64f0120cb3af2746998ba7099e459845269a4f", "MS2": "2225e0930b6c45915f8f0ad80762b4d06d67f7c757611152beaf096613584355", "MS1": "08fd93885cf0071e6928756b32e81db9f99906691767fa9bf3963c79e1a588a0", "CLIENT_SECRET": "041a450e210dab3984f821e76a0088c97193efa02552effaadf053ef60c9d7455306ab2cc133f380da0750242a25421291f2a9828c07d4e32579b9ad7b0b8fde2d"}, {"SS1": "096f7e69f907e53829c38ea777dde234997dac95ad7bec5e5e4f59e3a823faea1e0cc62a9425a45d3b74ea922a18b42e4bb19a880d58a0c166712aaef7616e620d90a245ce6383b41fc5e13e5c812f2f595938d41ad9a007be36fd0da0beab26218746dbf01d7700802ddce920793cb94daaee158029c0a13fa7d6b17235fc98", "SS2": "02cbec1787d0d0740bbe3dbf8bbc7106b05747318c91aad66286388428749365198e129d8b2f69301e01a7514f63af91d85fe7c8b2f0f1f112309dafe0b79be70d5117433321f944f2a9a17706c4739fe254d8c2c775bdc9f0eee46f4dd902c2004cf153a5bd5c56511e3143a9da938278fd37ec1e8a935b1a34d1b5aa54305b", "DATE": 16574, "PIN2": 6628, "PIN1": 6628, "SERVER_SECRET": "0bfe2e0cff2c94bac5c3967b9ac386cd5ed692ca675a5242056e150baac61c301b3009fe3663a40f37663b65382ab2afbac9632e76b7796c3131de082952614f0cbc1ea6a099537b04f4aa637944b8aecc4355f440e7ebc91c587cd18c3ca2881f15c8ffcc076f6803cf51173f27fe9b28eb2b64f255bbd62173d3355077cdab", "SEC": "040df748640b9c6fa258a2772eec41aa3aa2ea47bf19fb3a038a1a30eddeb967701f74b3754852b8c3d2c563a816c0611b55c3db6e54ff56b58f8cd6719cd65e6e", "TP2": "041956a467b30b128b11a83fff74c2269c6cb592bb9031badfe5e069600a69cfa90d778c5a4cfa3889df3d9923cb5ed85df4d7a921424b0a4cbbebff4315cca9af", "TP1": "04210b7a177171984bc1f87b25399ef0daf76b41e70aafec7d00dd7e5c5195d2a018f16ec66bd51a45441d34dc6caf65887013348de434075bc1f57907bf3c4a2f", "CS1": "040bcb195926bf744bb00413131e4029da287b4b54ba8da110e0008a3c79d95dbb019a8eacdd1837c1d5d291526cb35c5292084e2381fe5f9b58da552a1c33d4d5", "CS2": "04140a4f3e6eb125712d41744c34f500f56cf8e002bc62565bdd5ace538675daf01186c535a5c4e8a7183e9eec18ec8a4fbf58417efef89b017084de189c803242", "HASH_MPIN_ID_HEX": "124e8bff836022f414d29c0e717418efaa288716d7e391192558d1e412232a76", "TIME_PERMIT": "040aa74796a12e71cc086e7e6d655ca7148a935f9741359fe2d47b4ac5bb95aaa623c01e42dc07512c13a0a75fd87ec50cc654242bd57522142dbcbdeb711efb49", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33375a222c2022757365724944223a20226234636262396265376337626539393131333664346433626462306562306361406365727469766f782e636f6d222c202273616c74223a20223036663830643763323034633561336161666135623662643463366337366635227d", "TOKEN": "0403f434be91c868e0ac7f30135f639395316f9d00b8abbad5d6550ca92f0a924b0038a1e288cdb5bb4c7f91b9c2a4e42cde9ff79b52a73a07737fb19c2b163184", "U": "04171d76dcd8a9967054a778be9669c1c485242628af4230327a57b160b5287edb16f07830c693662ce47ca80cfaf0d524b83fa2641dde37f23d825fb62677fd05", "SERVER_OUTPUT": 0, "V": "040a3ebc56e80b9fd3f5ca5a4d1d7c9114999be8ef5d80f102b832857b822ced470fb5909753a67e940700d7f7ce36478d9b178528cb1d0058bbcb26cbb6602e34", "Y": "13b3965184897f9d40f82b9e1f53da9e582745dcff37b1bb0022d5a3fb37e0aa", "X": "131ab1f2107c7aca0b5f2c0562ef6aca85d418d4ceba3d06cb534c4b3a64d214", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:37Z\", \"userID\": \"b4cbb9be7c7be991136d4d3bdb0eb0ca@certivox.com\", \"salt\": \"06f80d7c204c5a3aafa5b6bd4c6c76f5\"}", "test_no": 32, "UT": "0406b79902ba8ebd244d7c4ff83140783d836f7bbc4d7b1a273a131e7e67d3a89e079a79a5d5e8c33b86dec7755753255f0379ac9b33368dec2989cbd730eb27a3", "MS2": "2123f3247da868ae25fce81c7423d6ea6a856b6e4f264c2bf84d1935ba065677", "MS1": "0399e0b6e74826c1bf53914a430581c4cf0000c2de16a1cb9b26947f378f4a6c", "CLIENT_SECRET": "040e9da687e9cbfead75726cbd628698d64cde7f4eb6d048c19d9a6b9fc93292fb13a9ec4c4ce9d8807d762294544a931162b2f5c56e3cab786e6a2f69862532fb"}, {"SS1": "20d9eb2b600bc5614f6672c05863372b0f2fc49d2f2b804baa2bff6edc08892a0b5f5ca21fd43b74ff3a1a45508e7f9f9c96e08ad5d72a42f9112d611ac5a2430d23aa13b6309e45ab474e20707fcc32025ed2126dfba5e40439bc4d9924a5081f15423047ea30604761e4d8b45efe26dff031c022583985a94b5e8ddfed4373", "SS2": "04241365aea33f7171a42bd282171421195d01762a27d60cbe0a6c88824687bb1681f9ca2de252b481637200d3311c7d6918035d678e54b14957fcf8aa91cc560213d271529c4f3023eec6ccb4324da97af2f3e71b7ac9e3eb0ecef8b73db99b11087e65d8b54a121090f6214cf97da577f6f3e1013b5a7893ff02be37dc191b", "DATE": 16574, "PIN2": 3415, "PIN1": 3415, "SERVER_SECRET": "04adee1a8e46a311002b4f27a8d168835d18ccac65c0c2a8595ccdaa0df82d921036056e8179861308102a17344a62c3fb38e3691be614a96ccc40991825495b184c8da8bbb78e1c77c89c24062b0d5acc711f93b42323293676ddd4deb34f5d0ca4960a5306209fd5d47fc708bbb48044a4492e0cf7a6f6598e0d074d6fe650", "SEC": "0417a3320a24e073b76f26d18b8bca346624c2e15a896dcb08e29132c43957e1640c2e9eca65a0f2d6157bf47565bfb3f6df953adf26ba5bcc61a4057acc10d65f", "TP2": "040aa8e3646c7212027fb7db7b09de91cc5ddfce7098fb513657bbc2c6b94ba8b41fe9049a26b7278ee0fd9c2b72fd32f7f61673be215e40754831cd1f550718c7", "TP1": "041ee00a2d70ab03258d1f6e2610a3c4d93e1b03812f969360ba4e789f979979110615ad3b3a737a67a8cf2760e13183318a00a97516f89aa9de7ec6cd8fe0b594", "CS1": "040c4884d5d8e06e70494246cdbc530dcd7e9342491c6266af00c16dfef2ba1a6203e3697e1ccc058d9a0aafb5f99cfcc8b389db76fe8e0de92ed0bb3427964839", "CS2": "040fb94982a72b4284091a84aafa313e979d27810c2d1fc131d8190fe9747884c60151e4a6685dc761ddb4466b07bdc01f70cc9608bb5b04ef0614a00ee6619089", "HASH_MPIN_ID_HEX": "a16336b5bad5fb2061c2cc76c581208da797076a0a81d870f6b79f25d83dc664", "TIME_PERMIT": "041c5ff91b959afbff88673a5b6ff1bb30c6c1eb2ae9ac4a5320e193b9cd3affdb02561d9004449c7f8e84e5c81199ddae57fb8f65584f96d204b17dcaf54d6293", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33375a222c2022757365724944223a20223838303431323065353661386631646462663339633264333061346337396561406365727469766f782e636f6d222c202273616c74223a20226335653766666165643163346238636166323463356661313539396162313637227d", "TOKEN": "0420882f53e8687478a9d40a31674a88147f1e4c2e658911f828a975f34970bf5c1065744bfe806eb4be4e9ce258d7a285616300912ba00e532477f46bd47de1fd", "U": "0411e09b2d32fbbecabf7bbd8b301458f63fc6c151fda5c0966473bcc95e90551810b01973e1cfefa27032b77fcb40c2f6118abad1c057c799f9894f983cd16ba5", "SERVER_OUTPUT": 0, "V": "040a3dccd4d8431691e02552965c424968b951a0cd7d3e6ac1b94d4f3fc1965fad1f86cb3de71e74120d1485b970b72b0de9f9f957ef55c3052f516b9ad6f791fa", "Y": "0be81ae6a37aeaa717abfe7d8c91e7e73d076c98fcdffeb4d13f739b6e938d4c", "X": "0352106f5e3ba1e98fdf2c035d03f84774c6933913a2f0d37e047a3ba0632af5", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:37Z\", \"userID\": \"8804120e56a8f1ddbf39c2d30a4c79ea@certivox.com\", \"salt\": \"c5e7ffaed1c4b8caf24c5fa1599ab167\"}", "test_no": 33, "UT": "04122981d485c12f677f83e4c4d99099a0a848c1b318e3cd5c93812556db763227197aca7911eaea067380cf180d60426098d160c5f9de9ba186a181b66aa7ba86", "MS2": "0719e362b158ba1a8a79b98e5fb8b6995d57f63c0aa521b466e3347b5256b22b", "MS1": "162376d5d1863c41b4a0e75192605ced23236cccc12b15f9e4af6ae7931de9cc", "CLIENT_SECRET": "04031ceaff75a1645107ee46553257a02cc9d57a789f55a6261089144481da62761f2020b5d3f41e9f78117384df24898f1790e7afa53d4fca76c1115c995ef48d"}, {"SS1": "21d462f344845826a349478d8389178810708ff3847e41df771addc5718dffbc153bc90a6a284137116e1dc47801e8107fe0bb58b6a3e47964df04821a60c00b1d2f65a4c09b240d11fbde279d113d170d3db70da900a5507fac3ba558f21b8c0c4aa7d0d67d90c38e355c971430395f57d0d55bcb7083b9dc12647ad93315ff", "SS2": "1b79c29f24b2416d9cf5c8a9f2495039f635776ef24c7c182be1cbedb3e663e214bd588975ce12efe071b600a786eb82c9e9280d3111040ac9cbcc99ae3990981074cc811b45172d595732c46bc4719710be33c907be2404d7ce66496c62cc59103d1fcc211c9583412c6e53bb616ad6762ce15422aedf066041468b4db5b492", "DATE": 16574, "PIN2": 6311, "PIN1": 6311, "SERVER_SECRET": "1a3f73994661b85050190c62838348efdfd0dc2ed463101ec3eda3993acd624f1d308f5da9054785bb8bfeed75d12991a6460aaaa239bcc8a4ee841190a36a440addfc2d23745ce34aa19dfdd16ca2536ef81f2bb8533a77b6828ca6bc13e30a1658f3cf02ead5d4424c52805a6782ab5ca33d23797d809e3232b28aa29b076e", "SEC": "04190c20a2644f54e0c8842a8df704634b697035484036caee559f30f56b0a532d0fc5aca565665b0af401d6de87b00e8c20a31aaa7426123e13b31195a2f5299a", "TP2": "0404766e8cb5af17f949d0c5aae6f63715a38cd3fcd5fccaf922cd1f2fb24b87ca13b56d010d8186cb048aad958aeacdea70fc8162d25572dfbf19959f3be4cc8d", "TP1": "04049e157c6e6f40bdf796d106fc6ebaaf75ed2f4f35d26f4bec77c1e52670bf981bb57db45e6a761213d138d4abed29173b5cf8f819e8c122eaa6f93ebc0f044c", "CS1": "04117383aa93f8410eb42aae31ba6fde07267eb6261974e993c0d91dd7a88e1034030822b64ac99f7b09852a25b6b9be0c0460bca73833306f441a5472381fcf1a", "CS2": "041760a2f796f07fc0a4b1d86f3a0183b717fb97cc2e1aded619cefba0911b18920d24019cf380d033ad3134fc5cba98a342a14c850564f9ae3d6f77f8e89ea3cd", "HASH_MPIN_ID_HEX": "fef40c2b9d4deac4d8dda4e1025bee6e9c117dac202d0b2e89a1eed0d2f0839a", "TIME_PERMIT": "04140ef6e8453d5db8bbb9f442d9c33c8febcdcb3de87884272fd3fc058a23adb20c774197203464f202fefc4c0966e9765dcf9d589dbbf2eec4f34d5332983f90", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33375a222c2022757365724944223a20226436633463663431333633336361346161346436366232363764303430363664406365727469766f782e636f6d222c202273616c74223a20223833616162336336356664336234313330653866626466373064376235363132227d", "TOKEN": "040752df94a8b4a5445e9456f7a283ca411f3439b549fc8f1a9cc6011e9397fcff061c4376d5065a8506415aa184c33fd5fe9edafe09c1b0cc755f39a3c19d4b3d", "U": "0411815b8ad39145fe729e7bcecd9d22624b41d2cee68dd8f02dda554598e4999001ae89e16e14384c4a1648582d76c3ec88891fdbc059c916e91b52b463718e53", "SERVER_OUTPUT": 0, "V": "041d60050d7ca8b3b1353afedc6351fb6544c8bb86082313e5ec4195b55360c5d31be11870a1c4b19d29620120eed76d2bcbe5ced0127fb7658e31aa4ecc7e4d54", "Y": "0721485a8fc7c654d4caeade0c201a2eb65fae4bb53b55244497a88d59c8978f", "X": "04cc5c4ce966b9afb57c712f5411aad3b591a13708f5302fa89f63f7fd9ed500", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:37Z\", \"userID\": \"d6c4cf413633ca4aa4d66b267d04066d@certivox.com\", \"salt\": \"83aab3c65fd3b4130e8fbdf70d7b5612\"}", "test_no": 34, "UT": "041ac6062e114b0f98328d0673116ae957752311cf8db2c65b9508e3ceb57dffae13071d661aa7874b29c6812237ce8fde3d301c836217f7027ab386921d788a4e", "MS2": "18b7956be8fbe87a16479a4f41da23028b74d7ab982ea3a6682a48dfda5992d6", "MS1": "203f20dc35b448a9097b91538bfb003f3e8c2a2e76b714f4f7f7fc86662f598b", "CLIENT_SECRET": "04056b651b6df069cc0753e35b66fbb3eb2042f6e198e50752da044ae455bf217508d390c13a32e2765ce05b7cf1d2de56c828a7098de38fee90ad9ce2d94f8fd6"}, {"SS1": "1b9d9ddbb80b2c8aa16f41086ce87b6cbfc778cebfb5bf585241a09b1968cdc30f0403e66b499765cbeaa215e1aece82e26bc898b98debd4ab9da7e1e7b062911d547800e3921c0bd756bb38674cd2e57a1166c9f749def305041b7545f1208f1e8589d35c1f5f757dfbc8c4b0965e4f1c11fd2af02a079a9ef177f680b021ff", "SS2": "070138700c3cd124aab760ce47a5c060bd232e0bb1430f7254b912239cd3314c0cd9d2639e767dcfb5554fd1e38b7ed01757bd5a5bc53eea3d916ac8647e7175107a05c47c12557400cec8aa6d4dff8d31928eb1a4212d2c8a4968df2866d9190e78fa4b5d10ae3581fbe90a83754e4fdb8c7b4e3d0eb84ebc7fea24a6e7f86e", "DATE": 16574, "PIN2": 7895, "PIN1": 7895, "SERVER_SECRET": "1403594866fe5bbbf873bff8d9f5ca3566b2e59c6ad3d0c757d31827baecb0d513b3493e6e6758d0db596bbd85fc414ddb76301fee3f7c1cf7d2f772593627751ed452c8b32d234a545d1e8318531cebf273fd4386d0d15aeba2de2c73cfd790021698caa6f31985fc9b24c5dc9febcb88f4fe5a093e07764b4082c7537c2bbc", "SEC": "04130cf2909e47181711a7ddfc988e32342c87e38fe12180c1d04e07ad1e3e884411f381c8513fc3cc6637727396182167980355d005a52d49d5d2db18b6529c9f", "TP2": "0403dedbe6e90bd93a3d5ab4e07b0aa1d2b3786f4ae9a60e8283b1de776d50b0f605e3de42433d0ca7d337542f20757ef8edae9f84e233771b7e38166082810f42", "TP1": "0414a38a4ec1cdcdd287e777ac2983a22388c175d0723fc1a5bfe47ad287f9134d00ec2988131278de51cbdfd2543892ede0d5338772176da183c6712aa10d9af6", "CS1": "04089e231e22a6edff3388a522a7ef5ece8acb9549798aa5fe45022f4a2aec9eac171c92bf2325f9f2da548e87799e534684ad5a0e04e7496bf45b63e5d41ed35c", "CS2": "041c9cca758c2b7bd49fafffed56f203ec4d65c11161d3bb1ad0467d8b24cd716c195c7d9d487494034cf1a47ff284a8ffd677ecf7af1c9e37a5ce63d932a332f2", "HASH_MPIN_ID_HEX": "5d89808e2e87dca0fa9e356398d9f00f49a12f379bb8d1f6aea40214513759b9", "TIME_PERMIT": "041e0b7c0cb5a385bb27c452926c934f0261b7e2f85e3f235554671a368f3ae6dd0d4a86d85c88b8a41e2617cfa6d110595e9d6f5389fcdab3eabd9507d29fa47d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33375a222c2022757365724944223a20223165323765366534333537366461366637653032303535376130356366313230406365727469766f782e636f6d222c202273616c74223a20223332383733616166316166623038356365306639356464326264633130346466227d", "TOKEN": "04125244bee50d099c547befcbb15b543d238c1808db54f57e11c19999e013319b22ee85d428b9ac64833252eebf606fb95b57c35e61a7e42743df58e6b4a65b8b", "U": "041db4514869692b636d7b9079a9b9e02c587574ad0253517d594def5747ac2d220a9b64d013634ef2ae11a0fdb06db2053b0963c0d3295e9febd2cbb8910f952f", "SERVER_OUTPUT": 0, "V": "04041103d646a6734b472612a2aa78636262add3adbfbfa0bda4d00a0cf6527daa007d5b2ef80bca1555963be1e31d26d82f45095893222894567e10ee2e7a1f6a", "Y": "1eda2ca4db135f1ad32c981170fc7f96de7d5856b4668180d5d863a14ab030eb", "X": "09fd0d06f541d068268c7239aa4028653b3b0cce4a90a0c9e09a91338ff06285", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:37Z\", \"userID\": \"1e27e6e43576da6f7e020557a05cf120@certivox.com\", \"salt\": \"32873aaf1afb085ce0f95dd2bdc104df\"}", "test_no": 35, "UT": "042160ce316f5a5fea3aa555fd53c89d82c1bed0f39389f8e4cac9b2208c411c8c0286d9363bf6b3164fe0a5f5bcd525efa6b10e5f7549c0a5f5077c2dbe0561d6", "MS2": "14dacc51858b26fbc49dc17bea031060b13bfc57acdb70a72c2894a22bd90ad8", "MS1": "0eb32c0274a4cee6bc3d2f3cd0a32cbe8c08943424203059fa08a0b43b1b7ef7", "CLIENT_SECRET": "04172ab74ee3f75989bb98151007a670b4f109ada544eff2ccfabe885d4d57aeed03a5078994e3b06c4172b659b66a77691053b9b35a5d527aee7655b76b7d00a0"}, {"SS1": "1bde14839e35741ec9f9a71bbaf943ed7594a0369c2f55d9724c0800fca01272152a01a99e22e5cc70dacbe51955226db2ce4f69f3b48f2793aca512eb9ebbd400f2376b839881347c1c65750e83d985a56eb92233a5109d74a2793a2755459007fb3f20b858e932a14d1db5f383013d31494289e88801add5edbaa1bf9cd1b0", "SS2": "0857d76d7b8d1da0815d3ffb2ae04f2d021ea67b05d3ba72531e3492bfcce4f4105bd54e55e1f817f97f40b05a574df385307d34d12714e5021d2039be592b830187258a5842057f9078064b17b671ae5030d0d3ddb0e8487ba173644cdb692302208ba24671d1d148f7563aeb5f6f52ab332cf8995d6a8b0c494ab0b0b4a7dc", "DATE": 16574, "PIN2": 8097, "PIN1": 8097, "SERVER_SECRET": "01be14e528ec6f6643b29784decabca2a5f96b788c5b3fa61187cd7cf5b36ec41f98df5aab62a534a6031a8656bda73c54ffe03bced6a7ae8eeb8f79791d0b8413542cf6cb50eae1c84939095ec4269771b41d58d8fa4c7d336bcc35d8f4ccf50e230fa3cd0c241c9146116a9bf8445ffe602dd134e28faa068d059d5b339181", "SEC": "0410ae297f9c97cb748906c9bfba03ca8d0b8c9c9e728bf7442e9ef327962a6f402036589285b191f13a9921e6d4acdcba28e76ab401c656467e15ab052578894a", "TP2": "0418217ce30d0e60d5f907b3659625a37deea148630eff0e3ea021e0748262e5a318a22fcc7e8d6309a8717e58d4e8bbc19336f1fac01c84c4f5a4b1fa8fecd9bb", "TP1": "0405fe40b69326c0ab8106ea44675cf97d6bbe640a5068ac95e6a255842d178952111cad6370a249d4d13067eaecad2b2d79e16f2e82e367037b823c7f2769f4cc", "CS1": "0418bb2148da2639c8600a2957f28a33aa90a0b12fac845fc2196acbc6199f1dba00248e691afd0b956913a59b758e4dc7094208d91245724bebe20ecdbd5774fe", "CS2": "04170d91392cad37e3a89e910cf5f3ebdbe9d99459df998c95db055838611bdc591c3124acc077d377629f608317a4e4c559e94df6a6c1bffb8260b4d7e70abc1b", "HASH_MPIN_ID_HEX": "53bf221efceb556c112ee9559507018c95045dc0d8f2b9d78e1ad30a315f1cce", "TIME_PERMIT": "040ded518204d7835900ce667dde5ed0c23cc2764c1e7aff7a262f543d63a221f00f023c2d775a9115fcd99a55b15be954b5b9dd7ca867fdc84d20e43864b6beb3", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33375a222c2022757365724944223a20223464306232363735326436363137626133623834396565613861306333656662406365727469766f782e636f6d222c202273616c74223a20226633316364363666663638636566356162373962626361373666356233313236227d", "TOKEN": "040be847edc695a47d02bb39b082d768f66a92ca5d7afbddd180d135c968921232007baf09cb91962ed7daf84400f2a84b4e04cbe6f49674395888c26ab1e34896", "U": "041cb6ddd5e10e0e7ceb8c879be1f764353c060fa41fa5d03b97f285eb2ef4a8b413b60c339b68e3c0945ffcb98fd3c44a4fe7bf220557ee6bca925fdaacad7161", "SERVER_OUTPUT": 0, "V": "040bca72fc35fe61c92e675106f58863060addede5266b8dc3b70afba9c3bc9da70738a15a0d7d84a4a4c8eb52925edae7ee7dcae2ac9739b6701c0a71ec5f8382", "Y": "0bfc8a5e3ee8b5b0afc3d3978a618d38b0a33a830a08a58386657ac69c13c905", "X": "1e22fa3b7ba3ba327e971e0fb8ddd8b6277716ff4ebd89b00791f05510a7512a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:37Z\", \"userID\": \"4d0b26752d6617ba3b849eea8a0c3efb@certivox.com\", \"salt\": \"f31cd66ff68cef5ab79bbca76f5b3126\"}", "test_no": 36, "UT": "040fa0f58bdf8da79b93f9e9480b1dff8b8edb4076cb6f4e66f4ca013acde4d035164ffc5bed0d9b493347904135b8c583fcd3114d3be276d896bc2b1e862b3f71", "MS2": "23e4f31823fb383200bc1069cf4d28a028bc0ca1dea8511cfd3b55c450ee7d9d", "MS1": "07cffd63f94806e7c5bf8ac40af15f9f477d75964877d86530ec393f992303ee", "CLIENT_SECRET": "041dea48afc3bf1b60459dc24621ffa8c1fdce5b9170dc8d5a65445296a2eae6ee11e0ac1006475a0b452025a7d20ab72c503bd4299f38b61eb286d2af3209c8a7"}, {"SS1": "1baac3a41cf3c3e9cd5851cca8e49732481e2e2cc3f9e81d37466bef76617f120698cb50f2335595f1f2803db44fa0dc82ce41609de0a694ea569214640a6b5b22ce1936022a2710ab22f588cb10ac1a7974358b75fef517001bd5c789f1ae3d11591c2b36131fc026ee37a4540cdb812ddb74f460c3b8e37620caefa657ca4d", "SS2": "1549a4c6bf7d6cb8d0b73e9269fc08e99f503645a675243e4aaf5c7b9c219eea0ff6e3f2d5341a0dd4d8abe1b73d9fc50750df59a8c8e75e3b39876badcdf4c2127d3192ac45e88bfec261d6b0cbd143404142933df4a0d2397a1ce8766d1f1c008de1cb5e7932274e17ced642b60ad1c6c4acb3fe164e9c112280ce3e878f86", "DATE": 16574, "PIN2": 735, "PIN1": 735, "SERVER_SECRET": "0f030064a0c4fbe4b1999451ee384f764505e68f8adb38446f62c4cbe7d33d7c223f400e20ec1ba9553f047763b0a2620641330ded3bd36427490dfb13aa8efa20aff06bb04c900911918d521cc19fe57465657a226f7b4f45a54307cadcba5417e75532bb0a967a9924a4dca86a6db6511ad72e4313a748eb9482b2f424ea3e", "SEC": "041485a62bd6088e057b3b447c1d605788bb1fb5badca8dfe52d62227b8eee1afd0302914b058772291d8bdbb6e7a7964322dd0cf1feb02d99d1c2f161285654c0", "TP2": "0416a6bdd6e21aaff6d9183e42ca2b3b68dc3fbd03b407eae9890387ac0e1e7dc71664c506f7b4c0fa2d52345e50ae30928ef3c0de4e298577df751c9b307ec2de", "TP1": "04131a78efcadc69133db43bd3af75ed69ffeb01593eb16fed8da005e4c361ce4907531f5bdc1d99bd83dbe48c181576ec0d5e4a05e9733d0aceab241a092d4532", "CS1": "041c31991b68b58f85140abe7e3b0860b76deeeb8c260824f6e76f48c91d5582c003c7a89c7c0693564e8db9362e23f1f91d8176289bd2fc4dc92a1ea28d323257", "CS2": "04108adf24569f39ddcb79554013f8395512836cc599ca93bc09a3fb3b02ed46c70e9f73bf6dc6e672ab27fa5cf6adb5ff2167ea4775bc05c13a846015d6c71feb", "HASH_MPIN_ID_HEX": "29ebc4901e4a5ababe65e315e4e56bc92946fd6e3ea190e1b37ae29a40a91159", "TIME_PERMIT": "0406e79335a76e4f5535bc9fc8366254e87c81adfc9a4f22377fd4e1bda38decd513739cee538b15ff4a34a94212a7b82dc1b113952eacff584fdf4367fb160683", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33375a222c2022757365724944223a20223439336633376164303337363230303936626137346261393535376433393165406365727469766f782e636f6d222c202273616c74223a20223634353333336165373766643532613833636333363565366266333034373762227d", "TOKEN": "0418391c3ca23d4b8928effd7f6f7bf39bcf25aeba85c150e84c5ad3edc55d77bb02838f4a3599860f17d750ee70983ffb5fff14ef55b6bf588d2e6a0052802e5a", "U": "0410fc51bec635f45588a3c1ee21a5e66c65d917b0080f3fe81c039f1ffd1b1a5e046d7b51e19899a35c7aa3f145b1bba896f1893c603cddd08118d3626b263c33", "SERVER_OUTPUT": 0, "V": "04046bfcbd98d1d2a62d4afe7d28a4657bded50b59a466d08ef9aec1f89527391e082177486a1dc9ccf62938c3e3814f246eb72fdded6a53f00792beb88a044555", "Y": "1684a9d98d2b383d519189a65ad4938deed3cbd49ee1965d29c4a63b29df8213", "X": "1f2ae6b6f6594d0a3e4aa2fd778ffd5a970a1bbcb9b5893c85399d676cbb2da6", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:37Z\", \"userID\": \"493f37ad037620096ba74ba9557d391e@certivox.com\", \"salt\": \"645333ae77fd52a83cc365e6bf30477b\"}", "test_no": 37, "UT": "040f9178df240576915762817a2ca6c9cb132bd4a205edc04c262de6b1d9dc45f81b7b80481a1b1ac094c355aacd8fabf90b2bc082aa339a468e2c7f0b487b38b4", "MS2": "1653805021f7a0e0b33f47d991bfd427a3f7f4dec0f1a98f88de7ed9819850c2", "MS1": "1ea10b5074f91390f8947f87f89e8562e8a9bbbe3caed219f023ef3dcb12676a", "CLIENT_SECRET": "0422df73b68cc3a7885147b88e89cb1fdb2e4d3abd1e19e50f8ee3d0d70349cf1718856eba04bb37a15e43ceb391e406e8bd6bdd1f4126dcbc3c1d865b66a7779d"}, {"SS1": "1e358cc9576aee6eeed8455bccc254415523c532de06b01d0a4be621e336b0d101074fccad1adcf2adf2e68826cb0e0101dceb49b9d7dda53a9c5cda95ccec1c05edebff429f5664c3d41bbcc7d7e57a8dbf6f5cc743470ca1ff7f3808401c89204f768227f17c794e26199e697e952181698f260e6444381974333f0a317fe1", "SS2": "0bc4f47125c287326814427f2273effdc2667205f085c6dc64cdf0da9ed110ff00024bc6ac46180458344b6a6ef3b3a8ffda72a95c71738e56c5da39ca889e9b0727d381cbdf87af2e9c987da93633e0539ac05b4389ffa88e8fd4dc56f48b1f01f400d5da3263df72ba29b1ecd61925ba3e560cd3ae3ba946962c598019c88e", "DATE": 16574, "PIN2": 2937, "PIN1": 2937, "SERVER_SECRET": "0a15332fe13ac8b3c0570e0b2d32be4a4e4e70b46dfea5b819612c94ba5ec23517fa20ea39422f0f35b7bc0912338306de6c77bdd793323c36045bd9d2856d441d729a08f1bc1e12631876c7fb5e21b580a691d47257f44edfc2f680dd00e1c51bc6716ad572c40b4f9c72465bee9b9c41d35de9de1435ede2d216ff100eb9e1", "SEC": "041a0657743fd1e140ee7f248da7d308b11c0eec2b12e0951275e1ae81a432468808cd6265c6d7922b6d9f327b55151a6f94fd6a283daf52f71791e305159be537", "TP2": "041954af81e4b2796c7190a6f09899af75d41c1bcd6e4743df79a16d7e34814a981c96b4cc0a4b0b1fdd1668c26cd30257b2db8f2250887709a561922f97145ca7", "TP1": "0406f8287e83f6e0834bea8e3504a6a0a7d5fde165ec120f84b5a61b27e4cedc6020bbdb7eb3cae37fededab479ab2430d0bce49385e721a845e68706f21080423", "CS1": "04183918fb9782787dabdba9319f089aaa5723f82d39e3e0f13e34b96e8833b7871876dfff40901532ae8a52ad270d5c099777b0c628deb74808299798b16b4331", "CS2": "041b2a9a5cc7ae6655bcabde13c5c3ddf21787a0d231711506e902ec4b8984ee1109452d29104b4fbb9c867f70d219abdf2e26c62d72d0e1ba2aff9ba47b7c9415", "HASH_MPIN_ID_HEX": "6313c7ff9993f5a8ceb969f3555aa0af3a96cbc29513f39bfc859f7f9fbc924c", "TIME_PERMIT": "040bfbf55ef234f681f1469e33d88b8d8e9d9724106476500a5e7a7b05ae3beaf723ac2a76898456fd04c4c0ea472f10e3a8b8c14c4a6a8c07fb40fbd6e2b171a4", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33375a222c2022757365724944223a20223236326138306439393039353433353435373734323839336432663737623061406365727469766f782e636f6d222c202273616c74223a20223865333363383733633732313963363637653131343230656262383434653363227d", "TOKEN": "040b10bb7635f76a45d5cbc1fa2f2cd8a33598863b8b7bc854ec1a59f2048ba3381cc2b82e766b5362db000e02dc0fadfa6697796c780d863f835a29b2f8d0fd96", "U": "040158671ff252ff868cc15194c06f5d23b2903eedf3492ea2cea22db4d8d67af001a7eb87ac2985670cd841fd4beceaee1d201d0b3647c4f2b37ecb92b2174553", "SERVER_OUTPUT": 0, "V": "0407c1cf71bae9a7d7c8de2bc03ea7f06a367030b47c2b24d8906d0bc7e633c41c22a66e7ed3593098baa101812bb9ad962489de901f86e2cb88044513f1e2d3a7", "Y": "12decf0c19b3ec4b3dfa9a0bca034a58dac452ea70e57e0e4d59b33baad181af", "X": "1579aa4b937f16033d8746a4128587bbf3106a77f3eaee77e8bb8a130ea12d63", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:37Z\", \"userID\": \"262a80d99095435457742893d2f77b0a@certivox.com\", \"salt\": \"8e33c873c7219c667e11420ebb844e3c\"}", "test_no": 38, "UT": "041d02e0d6553c1497016d185de97a4b96762ef0ee577eb4936e595297f29e524413af4e262c98dbda9380176c0c74b6209d4887c126d014bfaeb80de4302fc53a", "MS2": "07affe4ccf32a40c5617090aa597dac10a3dbe5a50e54f157be89cfece525238", "MS1": "10e8014040f1b52da0a392a0a04e841a68ceea6c8ab9baa5c9fcb00d6fb50f14", "CLIENT_SECRET": "041da83558e9977b4587521fd8d9e414ba70876d3bb841d069c8a48ec6f934832e0ad8f45c8ca500b077b3ea18784dcfe83d72a5b79064e630ada263bdea944a5f"}, {"SS1": "1a833061f4653e317d8a52af953b1f5eb79a82c258d00d9c18fe92fb9badfa9c13189815b9d633fe614a1d4cb28a702f66a0986a1dc54632e1536d3e2142faf2222378d602789ee24907d9db617483c5b7beb930fd97beb8269f2426c321250b079d4a702062efb170f61b0eabffcdb49ac124a99ad2ebb28750d3c27ccee6e6", "SS2": "14eb2d9a580eeccf9174475ad1ea9823f16005ef6189c888f2073e9f4010f36b1838a7145fcff29d12c631e9258ca63e6da6054117a530424638b0de9f9d8c2910234638901cf5608e0ee2610a450ef9c40d91d9278374cb663a4051ae55371e0f4478c59776843a9acfca6b9bf1acb822b9efd3d75707450aabe7f41714d391", "DATE": 16574, "PIN2": 2168, "PIN1": 2168, "SERVER_SECRET": "0ffd217a7f7ca6b4008cc6fc944cbc4b8f409a08371f2ae01635c141e3a020b51f4025c39f7511405e911e6ebebf499af9c9a5bb4d8333571ef7a56591bb67dc01137a191873a1886cfe9d7bb3b8c68c5b0c564993fd00e4982143ee37dc05c518d9ec68694e0e98ab06069dd5462a22d40c2158b59e81c5437a49bd9a5f421a", "SEC": "041d3d636e594ff0f56c4d053609d9281628eca357a137b8e0f6fb9a2ad751da2a085342f869547cd8f15db1044e7685822a35cfe06dd46803d0273728e2c1122e", "TP2": "040d598ee268b169596221d96d6da3b24b323c702fd690f19577f9d74f761b652802b8bcad2b548f5ea4378d6f5e69d73a9182c1c36edd42f3dd8d8cf31722e183", "TP1": "041553b0de7bb98a268cf1c1a209701d4d7ce34bc51b29018722477498d7d93a5918720f09e11fe4843a4a2f7b247069ff53f4fee42cfb699458a350ac2cbf00da", "CS1": "041084579a2b65ce425f44ab6c6f87865e71d3bb7d14bc0277bbc6d7929541ef0717389ac34bb3123678b6ceb90c7ed46a6801f8c64ec90d49886c3dbac41d7368", "CS2": "04134f2753668a4c299ccdc1b1ce525b2824a8812fed4b2bb11471ce58b397491a14b750867251286324ab4a62e8e2efffc62c44e0868a4e57d430a5045b1d0824", "HASH_MPIN_ID_HEX": "3225a1f3f0e0ba6b4266536917e44c50906cdf7ec35fbe99f5beb15e741d971f", "TIME_PERMIT": "0405a1123c81d90fed02e6439caf749054eed2f3766c44daf4a970113602c58b0613f7bb3ebb6afdba9f5d0aa2d7c9b59608fe6e74fe3c7caf38167b01980aa5c6", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33375a222c2022757365724944223a20226161323737303638363436393962393533613830393936303661323530313463406365727469766f782e636f6d222c202273616c74223a20226235343336356238363162626237636666666366303461623732393937376262227d", "TOKEN": "040d8ea5c581905f7358831585040f0740d6162d0a3ad91b51996e021923bf0e4517800c03a30f960d3aad0b77ce7bbfced613059d233797f075ff2f647c8fa426", "U": "0418c6a0804c39b4bcc4fa5f39c38de895442b952ddcdb0589598f1676035e33ca138338d6f8cdcafa759b601640da13eda5f5937ab0c3b180ee4f8a9de83f5061", "SERVER_OUTPUT": 0, "V": "040f3fa6f318fe1c3ac9d62ffab78ac96ace42382387a602a076b69e20760f96b51367c1e73b96b1a6077723b1b7cf898c718988330948055205e72e8bfcbccf90", "Y": "09a274ba30e63b247f95c0d1542519ad5bb47654b36ced1306f2789705df6348", "X": "0b3aef8a6f902ffec2d9513e4a1a4d4665ec6d49903088c27814c1a1aa20c2af", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:37Z\", \"userID\": \"aa27706864699b953a8099606a25014c@certivox.com\", \"salt\": \"b54365b861bbb7cfffcf04ab729977bb\"}", "test_no": 39, "UT": "0405eca5c0f30cf79b2874ac81a1f6f526b42216da9e9aa8f0346c80f6210df5f2050701c8d824d0237c3c436566e43be5264830b02b90dbc8823a3d68fab6874c", "MS2": "08f6d49ba532791d2914cbecfa54e5d644428044979b7248b1a77ffe4901ab9f", "MS1": "23ec91325c0bf427e6b972009250c59993a086a7a25b056a7d2a37c08d294b3d", "CLIENT_SECRET": "0416c1e339a0fb66ab4012aa8334ecb3d991b90eaf874da6aa5f4714a13f78ec751b1fa94a651479fee8e9da93a2cb064d5eaa2a2def09bdb39760bee46b3f0f79"}, {"SS1": "17053e28f6341c7bc09068b531cc8edd5043950b0b3531b351204ca59c13dbc20bfb0bc4b4a03e13ff5ddc6e32ff9d1b2ee92db1dafc1ed3eaedba28d46c3ada22a166dce9b3e38bd558c0564f0c003222b4643fbfc410a61522f5e941ad56bd0da5167c75fb475b534a270a9137ae08e226570b731397816f2f86dc7a03640e", "SS2": "050d87c53b96255de9af65a94363164f9c329e7a6620edc811b82044248d40a91e33f19d8bd5e72b0e699d91c27af30284565b6f2cc332791ebd1fb12db3cfe407ef4dd5fcbf9aa1eb3b7753b24de4c5e8f08aa979638649775bafb40376efd70410815dfa27600c5e7838f3035a6aabe6faa35f6b4b2051546705ca8b8fb473", "DATE": 16574, "PIN2": 5049, "PIN1": 5049, "SERVER_SECRET": "0e5cff3a2284d28a826195703ccc8dd8ce3d0ecff191781b0d3b475034736ff20a216f0cf74bc4ff402a13895271c937a41388c18cf2649488ce7996b27345b408fd979ba3d00db2bbabaa1fa731cbf9aaabcec9172bcbabe204642d8a9fd5cf135c2efc730ff98a53018313af4c91d7f89279f0a274dc6fe122d21a67cd9a90", "SEC": "04036efee0c4a976cb13a25d786b1502fbedee038c57532b5d5086cc4e11e1c40e1077dc340483bafa133f3ecde34087b2410346cfacef14a3f1c882edf5fe00e9", "TP2": "0411de4befbd5fe9be95cea01f4ee220ffa361ae1d92d9e1965be008c2e5a527b10d2e7beddb06577e085aa45341d10a0989072a66dd961c1fe0cc8e2148a5f9d8", "TP1": "04207135f09df697e4901bc43be20d8eaec62f12524249b620b564cfeacd7dbbf30c7bc763225dcba4419952cd0b5c672b9bc5b3a1edebdeb851aa1a43f84cc904", "CS1": "0420a5aedf5b210c6a9af1a054971715ec34b96d51773955030070bccc052241f21be2ff51c9a6715146d9c28a255bfafab034a10c83dbc20a4bb1af3fe6ff9390", "CS2": "0416c44fec43e7f6a772bb1b95f55be8e947771e95e1bc855b9e11bcbf8f66ef5d1c6b1ee6157183f4b04ccd3dd62575e5f384b035cb4012e22372d351e6281be1", "HASH_MPIN_ID_HEX": "787713d0f77aa0f39d299f6b02e3646d96bad76d74e60b5d0777d5bdfff926dd", "TIME_PERMIT": "041a5d4577f454130bfbed0699e3f4871220fb73eaf5ef71b13ac64f099d8c317414128c50cb4395b03d87ce4f257783684584961e7bda1ea96c68634d52a4520d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33375a222c2022757365724944223a20223961366639323364316564303435356332333437653065623664383065373636406365727469766f782e636f6d222c202273616c74223a20223739613432363137633361393239613238363639323639663738613032343133227d", "TOKEN": "040ba65d047de959bc9975e481a07d8044d4f3361de0026f7777caf5afe15cc8250d57f845123d53a4361ec62ba5a1400d0e77c97d2ca300133c543a25e773d06d", "U": "040da0316ca9cf9881df8441f671afd3b1504bc3434b2572c60a0dea3927ec9857075fade9ea54607f92ce49eda1ca6a836db1e0726b9a07066b1c8c70eb98e9b4", "SERVER_OUTPUT": 0, "V": "04009099d51c09237496285fc9e9b4492a8e52476eb96fa9bfb89397650ce8cdc00083ebe986d0e55a74f1a078dca106529374bca2cc70680ce8d4fd8bd3e8bc47", "Y": "0b4b2418136a78877982e8a25d8e35886dfea43db09040d64a5fdb6e0d456bc3", "X": "18c0f9a0e70c1814a556a64bd8977a633aeccbf3ff44d2e02cfd612c5abccfb4", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:37Z\", \"userID\": \"9a6f923d1ed0455c2347e0eb6d80e766@certivox.com\", \"salt\": \"79a42617c3a929a28669269f78a02413\"}", "test_no": 40, "UT": "0406767508abc9d80ec7e188abc989c59bf365762b35333157cf454e61e56b7d22175fed893a3ab101b6f04397f020fc7d78ae1630227a23ed0a3576a0a93e27ae", "MS2": "16b74ba6737b797d86988f332671e7c92a6e347689438f8b58762f358d4f2a6c", "MS1": "17783c084e69597cc078c892442567e5447ae436115095625a2a29af38c84f1d", "CLIENT_SECRET": "04123d64aa1d36ee2c68f1921064c4356ba863cbcc2fcc2f91cc78e7c8f1c5e1e802fb396ce8bc1f6d18a3f7d63fba06a095a50f5e5b1cc94825a7429d7757104c"}, {"SS1": "08fe231434d882cf75288f55a9d1bfacb984331652ffd52a7984afbcecdcdb501e1b5585d5c8ebb08b5cb7c2ec46a5be6c3fa697fa7430d750b8604d01d8695c179a60c22d310d1e6ad04e90ce6012b1dfb45a744c065ad54421a7174353d77f070c14e6d535262c549ae499c5784247e324ce16d2558a037797a913d8e01944", "SS2": "17490ded5b10cce7c73977aa8b03686dd31123adc3d8665d697b7dd61fe7bf3d10dbb955c606ff5c13b19eb16397667d245bb6156e4b3636494ed33eac54df870b0204466c7a4aeb03ba8ea986009b4e2366b78a4b6bb4927ac813772d505cab154f90423ef4647d144cf8d190c6d3e0fd3dde0299b3cf63efb1130978da3b31", "DATE": 16574, "PIN2": 3457, "PIN1": 3457, "SERVER_SECRET": "14ac6edefe7eff003e9be86a8212ae4b4ce748bacfb06bb64b35eec4b23a8dd11893866c063aa6194e5a7c30316b631db975ce638bb86e0352634a1a7fc3960d07217a2ab6f1384060d80ade638eb94d5acff161d5a161589caf0da0724f122e1b800c0ee6d04f2e96ff6e9ebe510a82ac649b415faa735837a1530c23b97fdd", "SEC": "0407b598d932955581f5da5994cc61b958ee73f7c476fc9d75119dce13fcf94683180bed2aac64e4b82d8d9799cb30a60e33c499413765af3741129cad7022af59", "TP2": "0408aed51e92b9512f396f20b0fd34d71378e977d6159b0f870362b4f7c350493716ebf0ed86ffc6de566a7cbd5418efddb1dffb52251a5d6c869e83abce0ddbd3", "TP1": "040e5195746f667bd1443b1bc461a88884579a15c51857fb728f8e158b088a5a6d1026bfb393f6d32baf746f297106d77dde93bb135008fcbfbd0e505e14d0918c", "CS1": "041cdbea83265d968c57507250dcd8d0713663470bfaf8ce24945349fd9f9dba84106fbd85827413c86b76c55f38c4d66f6ad0682584dc3d16e3537a53a2a48b37", "CS2": "0414cc7b69a5b1db3d5a85cd27947bdf27a0e10c2f9cbc607c25d1a210e561b1a21d9a79d09b382570fa412bb06916a0f2baaecab4d28ac76562aad379f7a1fe79", "HASH_MPIN_ID_HEX": "04a119e9645c4b8caa5bfb7879f57ee3877306c89dcdefeb8f94ed6fafe2fb2e", "TIME_PERMIT": "04032d3981f3b51758ebcb616bd5d4eea324653b8998b9f2669e3fec21e1f171961a9f4c835bb0d9de49cb287f95d52e7285fab8a673d5dfa998c95b449b13922e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33385a222c2022757365724944223a20223163386663393039306236313536373665633635346333643038653138356233406365727469766f782e636f6d222c202273616c74223a20226265383936633761616361663665666531386236353764393366333963646331227d", "TOKEN": "040a9b1f0b1001255add0840bd458e79784edab15a69fb535f732d9d01721f008b16826e12598c403e2f73905b5d708afa7d2a141fe0bab71ab6f784496554136c", "U": "0416545d0048618ff88ee82d11c92c00c3b6b3e1a2d0635f84dd886e232ca316e122c584b384b0f3db15e04879e5884826e0cf03f5094f3d6f2ed138594f226e1b", "SERVER_OUTPUT": 0, "V": "0411b5b98c96868a98e03e46af1f58a2921b3e731ce46280333eb49e3962e6f4f1081021e2bdffd303d2ba85e6482ec9b790493c013e0e0ecce20eff0137090bf6", "Y": "16c67213a740fb0d95ebff93d2adee4b25e1f1c9210140e077095dbf2cedc1bf", "X": "1f9dadcffa1d108788b9af0da660f63d17b75c9e97322b1aec00764b330a0da0", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:38Z\", \"userID\": \"1c8fc9090b615676ec654c3d08e185b3@certivox.com\", \"salt\": \"be896c7aacaf6efe18b657d93f39cdc1\"}", "test_no": 41, "UT": "0417634d3a4f55816b33e9d3c111de369530cbd4c33b4467182db17bbb524ba0812052d628e7bb1eb41ff6d4362cd5038bf518d5d7f21275aa56b343f3b6ec5fc8", "MS2": "18eff6f737ee7b81bb025d08ac2165b9a5b9454aac5e48a7c0568282c17ec5e3", "MS1": "14700c735daff2ca05f0b61152201ec33168b509ed40590954b33a76373527e4", "CLIENT_SECRET": "041466ae91da8003559797b55ddc395a3ed1b4d53a90b59b07516d5302f0b57ca500a0fcdc3aebec8e9ab7585b56fb6d25938772a7956d0fb3d1c52ebba64e667e"}, {"SS1": "2065868ff82f9a766ed9c0c1b9b9e4959603c59f8ea15d105e8da6f666ccf1691a57b7a666dc7a646e3cd570620cca08bef710c2be30606d5613fd0d802cfdcc22a8413ca1c41882c2553d5b4344a453095b47f3c23cf3d019c59e1e6c0546d112b91177526de21b0c9f802776e4dbe671c87b5b96f4c0d3989ac1c3411ed724", "SS2": "1ffb646ebf34bed4f1e889a3ff586c2c2860efbcb7564e4192352c2ba0e4d189178e1c8f52c9a073b299610a1da3306ecd45e0ae8d3d50eea64d5359fe3ab4da19856c06d7809d3e193d2af2cd6872611dacd271bc7f8e8397a43344ab08ce6e0f25db666f4f1f16e17a6c5a1e8a47ccaa82a5c21812e5f32da9422e85cd03b9", "DATE": 16574, "PIN2": 4384, "PIN1": 4384, "SERVER_SECRET": "2136595734d228cb3456cc1d4cfa0fbddd71f0414077d14a1ff2a9beb7aea79f145bda5c4c39030db8ab8611c9ce0d1c86bd3c99d2aad4d612001f5369f183b30b18869e71f893ae31d17d18aa339aedaa546605447fd81065d70a7dcd7a8caa1d32de1e91527e7d7a091964d55d5c0d7e1c986cd94baac6f79a93990d1e0215", "SEC": "040f5b9c400358154ca28f36bdb0d430047f40ccc1255ddef1ef8cd7283f6dadc3216232437bf2a408a0bc632baadf005f094f089511b542636d4b3cec3f1d6147", "TP2": "041cbfde5f8d24ebd932e8c1b3265882a9a78d1ff4938987ff93c000195c0d6d6c212a6c327932a0b2b9e0696cfdb91646695f1ea4ea3f309a765fa83d208d88b8", "TP1": "04043f5823887809ef1f3ef2e3062db94322338339e4390f45195e340436e0c0bb0a4c3117b78aabdf80fc9e3a6dcb5eb2747bbb3b997ea80515d960dbb7943932", "CS1": "04224ee0a3f9fc69540103efdcc70653c15a1607eb36d8915550f80da13d3053670fd2b0fb6787329e7091c06cfb724bdabe84e14ba1b5435ddffc5634fb284051", "CS2": "04086ee7c753980749bf15ff82da4e0b9f7096ae265785612a3489a97f5cae969c16acd5e6ac13baafd13e82dac44dd2198afbe902b770e81df0fe837e8b20ae96", "HASH_MPIN_ID_HEX": "79d3852057bafa76ba16d1d4d8a322c480cc521931a66ec81e48c6884628a379", "TIME_PERMIT": "04169dedba0264aa30d576b010a4a76a336dcaa01821fee9f2e3549434de153c70086ae66b68b6a8da8f13bc362eabd157ea6696be2a649966a55d3e4b7a5395b3", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33385a222c2022757365724944223a20223361343564386332626338666262333037623764336466396361636361643534406365727469766f782e636f6d222c202273616c74223a20226135303430346433376139626463376534306263616164393130333931376365227d", "TOKEN": "0402ff3db3f26084fb3747e4ed282b9f4e143eb2cd5ff5761c1ce7b52b7be15e7c10454dce671273adea191bd2751cdb288ed0f0b02f11a6aafd772fe140c8b150", "U": "041823f489058679780fdaeedad83a08994e9ef85b2411dd67088802dadebb72d422466f3587cdc3f5a1ddb0a596908ca4a02c4d3af71ffeafb0f7ca0840d3dcde", "SERVER_OUTPUT": 0, "V": "0419fcdb92ec7d5ede9fb9c42a2746e4888fa1dadc9712f0fcb5bd0cd96dc2f7ae1265aecf3708d2ecfe26a91642d788c5b76056ca396e77a4c2ecc8fa4d566c06", "Y": "2159c48b189b53b38c44c1ebb7f1ed4d8f58154140aa1727e79be2c63b814a5e", "X": "214175e915aca380ec846922c7128682111334dfd6a48b7aa15a09684ef3d4b9", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:38Z\", \"userID\": \"3a45d8c2bc8fbb307b7d3df9caccad54@certivox.com\", \"salt\": \"a50404d37a9bdc7e40bcaad9103917ce\"}", "test_no": 42, "UT": "04115e489190ccfd2b43158cc484c59ed23caa21dadd3d9214102109b391758b010a685622f58d1b12e4666ee7e20df2297860b4101b1bf824fe0dd8dfe0fc71d0", "MS2": "22f46c0e7f1e398e8876aa707983607cd72e37c3ece7c96f343e3bec482546b0", "MS1": "21a10c8e86fb2f44e22f4bd856d601390c843f4f0ddfee8a9f98473576c3464b", "CLIENT_SECRET": "0420e24f6acca73a224ff661338c154455b4d6cfaf34bbef79a7b7948ba7038b3612211967cd87202c9a6130b4855cbf695d525a2cdd5863d2672c9770a1bff7a9"}, {"SS1": "01693056300c8e68a57cc0f7085a900fc760d5afe1c84b51d80e53bd28a78f340091fc7e9914bbfe7a9c8767ef9c4757d4be38065478e9bd46357a5f5dba88891e4a928f3c3fce57c65b1c37988b352f9d3be8db5479bcdadc89f856cee27fe917b97cb5f31ea59099c6ea7e3d9f8c468551294ce613b47ca58a52d29a1d6fef", "SS2": "1e84a33a8ae4b55d9369cfd37b4bda7d6fd59465065025837a015419cf28231107fee1477ed2ada57bcbaea843993711d6ae01797edbf0b20e7e7e78b0acc9bd0de27fcf2feea1167f519b077786a91b7eef53edf6afbc607ff4045962c4642307866a440d56232ca709539126ca6eba181694da13307079c646e4c696e66619", "DATE": 16574, "PIN2": 6525, "PIN1": 6525, "SERVER_SECRET": "1c50b9f4624d5dab1b91f3e08652749af94a34ac6efffa1c0c778393308bca2d23881db82c332e7786f6f11343ed57753f1ad93d483081d1df064e7000e383d3236d5bb1e9ce77cc953d8fab128e0e6dbbb8ff0cf1ae8361edffb4ac23913a7d1bf2d45335c6949955c6160de976afe8076ca89e38b6384b7d260a4578204425", "SEC": "0413625c4fd08bd3553de1b87a82786205a1c9e0a1837170a3d451c82db445cda10895e9b7ffd6539617e8f8820ed1abdf84d1f6653c0092d2d23261f72fbc4e94", "TP2": "040cf2724e78e44b2bd56b017275659a4f63497a54f5b844b7418c7b9dc6691b8e0f7d49b5dbb3367b9d27b80d58c8cee3c01bdd0c74677681918309528faad3ac", "TP1": "041b14f575121d8f14d1cea9d47a0ca6a8f969ccde9f9550f5ec7d72e7dc04679221b75fd3ab23bd7a6a37f274bb47c8673ed4136b9c6b8d6dcbcf7a3c389572d6", "CS1": "040289b4893af86b3a4aa2c819c89c3a483c4a61b9b59eaa9781cdab89506224801ce12e23f2ae98878a4b8f96622dcb2f7c198d173dfd68dc6381544dc9e72fac", "CS2": "04076dba49be5e8be9d6ff52851aec054b5f4d6f1e965b9d488ff5630ef29405e70e67d4764001c07fb689751c439d2956825c2b1f47c843e351d4e92775f9d69e", "HASH_MPIN_ID_HEX": "aab948eca90bc7fd86ba2c0c6a9e0bbebab32defb752c6840e50d2f7cbca9ffc", "TIME_PERMIT": "041b450386196b2c5d5182463a85417ad4e41adfd35b7cf62867f20e0bd450c9d018e625cd29bc44a435389fdbc1d7373945f6ad66cd1bd4e16bb2aad0ae897825", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33385a222c2022757365724944223a20223662623534326432646236313635663932336331326332623563663439336664406365727469766f782e636f6d222c202273616c74223a20223665333161383062363566353237386563653836643435356338653763646434227d", "TOKEN": "041d476b9beeaec8b23d75b528152ca22f290f5f63ad483f41cefff3876ae39b0f1f177445db46f943d2f03a0cdd3f95e8fb817f7f706e85667218461d87f7afb2", "U": "04099f94e2f36f4d44c8963a7d1323b2f5fee28cb8d9c5e04b992bae589941ecfc1b8f0a432a3a0ad96ff172b080566b9a6879ec036661ecc8c2a0fb87c032d73c", "SERVER_OUTPUT": 0, "V": "040a0d71d43108e326816aa582a742d8d3f1bb42a6398036f378081271c2501bcd003b890bbd78cc65a3f53b84b1e61856ee4f1982220edd6f47075632e67f863f", "Y": "1205660fec20886f2c8435538daa60476cd03862e44393eaeece28bcb3c10aa6", "X": "041209f198dc2adc7dbb7a049e4db0b12951f67f5727ddaac30e2820fc076408", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:38Z\", \"userID\": \"6bb542d2db6165f923c12c2b5cf493fd@certivox.com\", \"salt\": \"6e31a80b65f5278ece86d455c8e7cdd4\"}", "test_no": 43, "UT": "04048cfe10789e17aa10d9960ab98d4263706f79c7ebf6ee6ccd6c14cd6b6fe1e5008a24a8e934a2c19afe3deb9e37523d8beb0c3a4803ea5dc3faf5916cb71104", "MS2": "1138de1a55fed269486b3e667ab16eae66e979e52650dd5572ec4508150c14af", "MS1": "0bf734c364d3dd681443f2443c50e0ddf87a887de6f80fb4a6dd1dc4e1610511", "CLIENT_SECRET": "04050f1fc7f146fc37219e12d8c2c5a5c5a00f7d509a50a4aeac3e3bc2dac18d641a44859221c71bb12367fa65b124a7bdaad03c71430668e06464119465344711"}, {"SS1": "23116d7cc1a6f32f8726c8031925e0d9303ee2a0c6b3bba4f72af6d2864773d70a2187b01bed8708b8c149b27261e5098937c79e2a4e19102f9e38a6f92bf5c01218dd47d8d95f70711bd045618ace3a069034633e5c5686424c4c6deba6d4d2163178bc0f690eb5205378d678767d93c5f5a8c878be7d6ea756489db4fdea58", "SS2": "20e42e68e29dea4943fe228e26d1aed77dfa5b7a6cd508d099f9e3d92ccff9ab04ac4b1b1fc972d2d8250489b131b69b6d62a830c1d8a7299a361cae364b05eb20619624ba86c59621ec2471464a8816cf195dd0f07ac95b13f086fb9fb2fff10be9614e306ba8f2db626f8c61ddde31adc08f5140ccc5c23c50761807ff39e3", "DATE": 16574, "PIN2": 3487, "PIN1": 3487, "SERVER_SECRET": "1ac5839c75280ffdd5b1a843fcc46f5fac0af8757dc6ea205f2789efe2e51ca711c51985ae6741bd7d26a976bf9bb18e2d4c1dd7f27696712f1c0cb0171c544a19b4f6ac49408e60839bb910d013b17d6a8d8804f287fd3eee4d9d2a23547d881527617359a3f71cfed6c75e4edf9c3a39bb59b699a80ce41bd7f2ebe21372d7", "SEC": "0420bbd1579b5a992b13acd37203f995825403cabf7aa4d58d55268e26ab6cb2710311df5c470c20e3fa7a4e4a5db1d2eeb170725ad31c72a4dffcc17443e6c937", "TP2": "040a00ecc5455bc5c7d693a56a5c0ff6b30dad5847b859dca72fa11713b0de140a203e470076528539431a31f3a302dc0b600bdbc05ff95b7c6b1be9897a255bf9", "TP1": "0421d219dcfa8b466480855a494b40b807ad330a629eca89b7a4f5115ae6f5ee6805651cb0fd7a9731ea33e0110e10836054ca026e776704b93696439a4ebe718b", "CS1": "0416b17a8f99a1587253ed7c2478a9ada70e49c5255671577ea66feececb249d131f05b412dea681c882f7dd7f96e98dbca8cf09623fe20489b3c4398bae578dcd", "CS2": "0421e23ca925d1e29ecd8bc6bb4e2878b4296c45290cba9fe7bd43b579b41829d810b1210ceac68e6699d63706c2a7dae5c97a19bfb1ee67879afa49ad65d07db9", "HASH_MPIN_ID_HEX": "ba6874db956ecbbc7e99b321670aa3d9d43995f37eeeb2467b4e2524b4ed1f36", "TIME_PERMIT": "0413f246ff0c9ad772c4a2cb928bef03dfdd2f4a25575732b8413c2f9c350d40750730f58f24dd6c255fa5fcdf394d0ede41c94c7e681bdcfc308b8025c5bfa49c", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33385a222c2022757365724944223a20226164376337356238356230623232666264386538346665653235303438663264406365727469766f782e636f6d222c202273616c74223a20223936616134313966663239663663653163633534616565663936613963316165227d", "TOKEN": "040b215c6e018717e8360da151354022f73f0d3af3da0b43278aa7d9af3c6730d0071e32f5b5bb372cc8a0ac4b46172aed300ed8ed474c55e23682f41d528de977", "U": "0420e95e52cef59125e967417395366523d2b405f48984ed6253a3ec9eb96fda1b1fa6ac1bb9c08bcd846a4d3d139961890e0f2a79446c0c698fb28ff4511d1012", "SERVER_OUTPUT": 0, "V": "042338926f63840780911b6778d4a749d1848993dbcefd031a10baf492450b0742072936a7a2eac3ea88bd4887116c2509a27b447309465f6a00f9c75484268e40", "Y": "14f869ed6dcd8b82dacf0521b3a1d292bf09331fe330aa1dd3b48eb2de6e041b", "X": "02bc8ef0742cfe756e9cbad804922c08f4a56077075f33247ec27c511fc67d74", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:38Z\", \"userID\": \"ad7c75b85b0b22fbd8e84fee25048f2d@certivox.com\", \"salt\": \"96aa419ff29f6ce1cc54aeef96a9c1ae\"}", "test_no": 44, "UT": "040fbdfb17e9c06242302957e4b48909a8b5e763341d391a0938ea431117895e9815a0c872313f38382f8d4772dd3c95c2b314d90a0cccb3824aed2d52e01c611f", "MS2": "0df6fa1fcd1d07fcc35085cb11657110b41949fecf766ae868fdb967b1c40c79", "MS1": "1c1243284f458352257871cac3d14e1598aff9f28019535c3dd30971dc3cb509", "CLIENT_SECRET": "040c2b7f618681203f317501b04cc1b7c278c617ce5ae355a77c960394644158ab08e1661e41c16820dd82d63db8f61c61e606f6868046ba7fbf6d1a9fa69a0384"}, {"SS1": "177aac829d24fa6e578a8de3d91abd07f4b9b2ae3127107d2ca8a0562b5248bb00b227291ed11a2ce97cf27ba703a568667dc918cfb35879d6e68d242aacf1f5238bd983d350e9ddbee79a35eb431074776bf5d5dba00990269b168b301a71b4053838352307636f1b03f87f5bc7f707503d961cd7b9292ef150f0a0b916a934", "SS2": "118f148415170414cbd4d4818606c12d41c7229bffcd34091f83c0472aa58f5800ea75717569ce7b3ce40061fd1cb93a48b71a217c806316ff8efda10ce7181b1676602153c3eb2eb6ee5388090ad1204d3e38ee0c7cb4cab2984f92f30f06970b9e5d445a4d9d863afffd338fe76c2deb9211a64d2014b616438cad01ad6697", "DATE": 16574, "PIN2": 6448, "PIN1": 6448, "SERVER_SECRET": "210cf56caed4ec7856797351c79199461f8931da2301f5e1c306165436e147a4139cd42dc0d41d338d7b360ad1cdd5d4bd7066a59d7f73bea8381f7e2e4dc93d117cfda749e7a832e044fa58eab7ec76ec1c3405346b2f091285977b7325d3541cfb8fcf40ced4a1be6e40699448d2cc362414fea834a11d9ee6ecf6db37ef60", "SEC": "0419dcbd4a0ef5255045fcf21a0408c49afd9f35a8b22a2dcdeb411569b0d0fa31224d1731279531d7d2e32b8e2270756ec71d524aeaf7d2a59e99352d993573f8", "TP2": "041ca6695091b7c75b8508c602968fb52bdc735a89ec8d078bfd1b11e07829652013656f7fb08949ede70dd0f7e8952f3a45d6ccdfe5c79afac9b461486e3e1ee2", "TP1": "0420041417f1121802e9d523adc64d70ab538450e4b22f22daa1fb13e9ed87afc209b77f8e48ec7a9c39935328e28639e77afce082523da8d23d23a1039487985e", "CS1": "0409609a407352e7ba92b36f7f914c2163e3366547e8ad0cd28769938d86dd7dc21380ebb8a61764d46589151f6f8e5d46f6d5c925aaeaaf9b06d3497c192be1f1", "CS2": "0423445ececdd189b235480ba2286b5aa17a8d23a09a418782e99f3c402db3c78e229507c5bb4e36017e3c6c048a74f04c29897b8c7c25670954524c6c3119efc8", "HASH_MPIN_ID_HEX": "8657a344024df40b9ca122bcecb70387e3ed394b9b7a2dee130a08709d69768a", "TIME_PERMIT": "0420b0b0d34ec3a2df7c839dd1024b5df2ccad963ef27beb878880005c1b01d246116173913299d48b7a071d64b3ac73979b7bd363f67a3533d09b91dbb099724d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33385a222c2022757365724944223a20223934366531323533646264633133666133373539366633343639626562623261406365727469766f782e636f6d222c202273616c74223a20223533383130306566326462393638646261313464343731303033333566373636227d", "TOKEN": "041353d08a873ad762d45f030d55e799909b82aa33905cd901752ddc9bc1b881860d6ed791c4964e5db4b9ddb07709cc25fefaa78aa826106b11524c148d5df69a", "U": "040d0414b4ef038a471155a704ce83a2f8a6b1ae3171aae02004980efd02c105bf23a6f221a199e610a157d7263db90261308a0aa678aa6142192ffc00cc2f5d86", "SERVER_OUTPUT": 0, "V": "0413c9ac643580fb77baf3d6b4d96695fa4e2808aaeb2afbe3d8519684127992660031e149dfca5c83611f90834c938911d162aaeb4591e34db4a1599bfd84ec1b", "Y": "0c795d1c27d6c143c8b57cfaf7035264307ea084994af621694d08ecf0b057f2", "X": "1fd47331cc24daf7c29b7d17be6c063d840956af0333c85a52680fac1bef577d", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:38Z\", \"userID\": \"946e1253dbdc13fa37596f3469bebb2a@certivox.com\", \"salt\": \"538100ef2db968dba14d47100335f766\"}", "test_no": 45, "UT": "040912ff028b17069162921788e65d17f89e454d8cf0d7ae077534d711d92d9e5f018e1c9dd4739239197e96441d25b6721eaf994392d595062c4cecf8a9278933", "MS2": "17b15686223d70aab9798aa1aab7824dc3212489be33a56c3133f92f209a86b1", "MS1": "1b3a6f03470220c9dbd75e15293ca8103a4d91e963a69ddfd1b012734b723fa0", "CLIENT_SECRET": "04022a40e1a97362d26c3c1092f67c332e1afcd0f10433b07d9726d19cbc02f234058bcb905aa4faa8aee8fd5f14fc8c872ed801ab30aa6b82852377860f6663c9"}, {"SS1": "0c6768d51c5158109d31a9baa4d6ade11a76b1364f7006891d4c771bdbcf9ea8061056ef9799deaec4903d3dd23fff3a9ec5909bd86396b3d30fda369adb63d21100abb3109b7e9f43ae10b014ce1f149c91a0d82c77494bb9e3a9893c02705d0f3fb570dc269eda1daff5fc2192f99f5aecf06e1663659ed00accbccf7eba79", "SS2": "0d4ab3c8716dcbdabba40483950bf49f126098e2ef21d72f6a59edfb633615d10d31e28d43d09a0ea88487d01e11a55e067e265f41d2851f5ba2c4abb6af02fd0d4988f8c50be76b1876f5d7dbdeb1d0275642a1273f7d09579de3f9bc3d028a1641ca845e2f29a7f850f495b52b607bdea21b298153fa36af41cf44e48540d5", "DATE": 16574, "PIN2": 5779, "PIN1": 5779, "SERVER_SECRET": "0d8b13d4e339f2dd824f7c4d0378822706d6786730e6c44cb0c15aca894c6469188ee327a5bb3bc1854ae1387e03002b5fe31ac0a5f52cc613e1ec541636b15308f80ad7e1654c15cb168ebc5d5ae08a52f96700e0a43c004c448e54fc513ea21b2c048b22e52535b7c90706b9e597e34000255998e549aecbc7524be59a2933", "SEC": "04152cd0add58db7354d67c4d9e42f77fda55848966df8f8e276c243c9507f3ac70be25dfd85c06c11c8a6f36b4bcf40d2418632b2893cdbdb9928f97b01ed2417", "TP2": "040d8bd0006e9ef735c59dd9bd3c1a2bfb75c434994953c7df67a7a53e45f3f63a22c86f4db33dc226aba37d3f8443e6e53a4a3f599a68c3f3bcf0a3fd788e5b2a", "TP1": "040dba35b41544f9d6383f4b6af6c86fcc18691f37ea2ddd9ac31c236443b8cc3223f65da3f6dbf376a654fd7ab68d127da135ae837af9030f26b2b6ce275650d5", "CS1": "040e75e962353adbf3384a687fcae8cd395f1e955ecc172123afa8d9af1d6befad09b6208d54ed84103ffb3fdca0e610135c0d0d38a78145757ed96ad5c55d4c4d", "CS2": "04216c2bed79a9fc00582908120917e28d83c13451592c15c25e5c634243bdcdcb1068b33d11885ac2336282b94bf0d9e56a4a44fd97028c0b7cc8e449b9eb51d7", "HASH_MPIN_ID_HEX": "f8780c2d906914f463800552a7894cd7ee0ca0a56feafd4b171c1af0c4b93d07", "TIME_PERMIT": "041fe9478f3366c56e5efe4245e06c6ff3914bbc872a0fa62b191b2324cd440a2c1177ebf59896fcb4940cdb96b591a6af723ac31a5393410f0d0ec7582cf6dd21", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33385a222c2022757365724944223a20226333323162303631303437376666666137313766643635363462643633646437406365727469766f782e636f6d222c202273616c74223a20226462343364613937353437666466616230303835303437616666626362626366227d", "TOKEN": "040c3eeee62310d6dfaa9f6d6b0020935fe15ccc33b19e165eda82eff78ab12283037d2c7f9af7365158ae454353427c7c06543d087b1d261da5aff0bbe2a422f3", "U": "040a950f608ecb6fd6828addad96fee025fb4088fc7b4f37751cecd6f3407024f41ffb988d91d951985b81ff83abc26a4c1da5f67e627b52b2baf52157a69f12f1", "SERVER_OUTPUT": 0, "V": "04116ec3de8c6eaec3cbcee9e4ad34f9955b8fbe9b3f8cf544b1776662a66a368210e1d6e5135e65e31639703f72e8630e7e1d06690da87ad08dbe5f56f0b2f5c9", "Y": "1f0f6707c8e591068b92147af5acae30f34376aaef67e2394213ba78eae537cb", "X": "0b8b87092e06e586ad473dc0b1576c0c984da32b6fd294de551a2e85e267bbb9", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:38Z\", \"userID\": \"c321b0610477fffa717fd6564bd63dd7@certivox.com\", \"salt\": \"db43da97547fdfab0085047affbcbbcf\"}", "test_no": 46, "UT": "0400ffe1db808625133ec4ec681d95094fdb144833d25d3db07ee9f48da6d910a81db91aa2931470f2d58688c6f8979161004ff327939d31c2dc7183f845b3807f", "MS2": "07f322cdbe9622198757cb42e065d9655bce664ea15645345b22df93a7de25f3", "MS1": "176d4524ee6bf7858ec812d28635b5b024a1cab8ce1bf7dbba440094e06eb35c", "CLIENT_SECRET": "04023fc3cc5ee9e968ea85552c76bd48ff06e99d06da157e39ee432341f5e4f4830df3d340139a2b7b38d59e9ef6fee69c15c59f4048faa1b634bba340040136ee"}, {"SS1": "0a1443c4f41dfb6dacf6c59166991cca10dcf42713a0a1c9d331bb50e80a783b23c9808d696e713477ad8454c2c58c3c24a9179039257d4ff4c2dd3f281f06cd1228365971c50c379444186fc93acc84e4a9598e6acecdf976ae71bad52f083317f79ab75e135d0f2130d51a2f17a627b0c95ef68a57a25bc0067930c9f1d824", "SS2": "0dd35674ba9b58a885c573d52333eafba1cae32bcba4a2d6aa1e4ca0b9154ab8141b24d2ebc94455d1624727e03882a44f369b3140d0f2f109acaac5f7b2209a055403ace74760fe9908ee23dc39ddc703239a8ee89c519e0986b22d61d1da74143d7ea31c759eefd88bbfc9b453704d80e7b8bb1ccd6321447784a21aa1e788", "DATE": 16574, "PIN2": 4307, "PIN1": 4307, "SERVER_SECRET": "21dce950941f589369627b1aa450f8e21e06b8221d11cee58aa57d519c6b5fbe1032edba8cd2d57d43b12d3dfe02eee24bec22647f34391731be66197a4606671eedc1366b4cd8e245411fd66398fa646e65f3d75d6982a6992133f52df4d12109154afd41f94bf38a4b305b72482166827db96e6198f775f8889fc9125807d7", "SEC": "040f703a345b59b5a96cd6a6cb9d25d7e06596dc1e04160af23ef2ff96950b7f221b10f62511450b6bc095f26764fa84e96f4cd5ee270a04a846f9b55f37ec14d5", "TP2": "040640f0e94541c51df1465f26f0883ed0ce879731dd9fe50dadcba37d3436a256177502a88ba02bd91fcbf1243e214b6cf7c31c08859e0ae18564cb6a783d628b", "TP1": "041d425bff74a17aebdf9a4e8b5862e01f09466e6ce409c6e512b971451263fb651b4fc15258a5714e6ff44c07c4d3ebb930293f7027df2eb9c4ba1e303f407d5a", "CS1": "040c128d579fd175a88da8f69c5a43a1ce6d1c344de291ee3eea146bf1673ef2e200430726e0268bf72fef93c121ba2d0844b362547265f77541cc98a155b1c60a", "CS2": "040f2b7e2f8276475bef49febb28016a5a043a0d1bc3c1d9f7b89d60375e102462239521b6c41388a48bdf7335d96e55f9d834f4c800565cf68d35006eeae38b0c", "HASH_MPIN_ID_HEX": "9e3d2525923c661c5d524a4e9b34ef00a453288e1dab1fb1edfae6ef2a9f8ddd", "TIME_PERMIT": "041ded1c6daf72b558324867bbf81ff8a03a0758a88645c75355c531cf17c6b033140be2fd52fa94a9d7947434b706bea46069a57187f97a4a0215c210554f3adf", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33385a222c2022757365724944223a20223765313362313432666238316436616433663932306431313966333461383965406365727469766f782e636f6d222c202273616c74223a20223439306462653135663934666235653966343536396334393134653632366130227d", "TOKEN": "041620cf931bdc617b8b51325c9b2d1e8e2f9b12857376af017c53062c38d840860a4856b19d373c85b24d0f1a5765296d61195414072ac2c3d16c51ac81bb79b0", "U": "04130c5a5e5d1fb8ec9c20b5cb389a2ba0684c2bbfc5780d93d91ad7e37c84718a0de7f9840710cdc7755e394d3f53c4b558a4c197b20365b23a061e5ccf35d7bd", "SERVER_OUTPUT": 0, "V": "040acb1871a583db9412f06820fef10bfdc6ef55745f13a0bfa20e79b4ba39740712cee65b98b9c677f906844b4f805d7637f4b7e4d5d30043dc9355c3e2d49894", "Y": "196693e241ff8e6db3696c5fe2b81c752604a9cfb6b2f1e453fe5662764fab01", "X": "0b5b79cbeff4b5c70eadfe26a49c95321f99ffc0b37e31cace7b4e4ecdb50562", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:38Z\", \"userID\": \"7e13b142fb81d6ad3f920d119f34a89e@certivox.com\", \"salt\": \"490dbe15f94fb5e9f4569c4914e626a0\"}", "test_no": 47, "UT": "0412fadea208f8d50c9c3dbe2197303752f31be95b8704bdad8d899ee92c0a913e00455a76d1918c59c1f9a4e2e0d733188291579cc2825c7e08f43384ceab63c7", "MS2": "134f9906977dd413c890075e2f463a46077c9b6482171ac7893d59afa6c949bd", "MS1": "10dd26c48f12d11b4fe7da8e6fc2387163a6a02f4e38f07a4a9a57fcbec09ca7", "CLIENT_SECRET": "041948479111a6bf79ce124ac170d418fc710cb330d6a4c68459551aaf21eda912046296fb62454f9dc47cc99a316402c256686bc336bf23825329fadc1d467b9d"}, {"SS1": "1d3ae8fb7d36214641941a358f5a9e470c7e3e41932fcdff67457a9324744cd1151e48815d64ebacdacfdb27d9389e8010cbb8521a1fe828fbca3cc27fc2a5df1855d1fb11ba3c31604599b8a47dc719d5dc1e5f35235977e34bbce464fd793409675b9163ed171100e8910dd1c60ee228f6f7f57280a56daa032e8fccae1e11", "SS2": "19c23daf668009ed366e81bc0dde81693d27d823749822e674a396ca82babb2a12a317272a41893ed7352c75fbb79a3889e270b2dd258f0758d653ebf0e84622220f5d422203d503c2b8076eec871c710811a638ac442a4bb769d4d6d755b4421ce0ebe4f71c04cf67a9ad828faede828309da1aad2f5519229461bc7751481c", "DATE": 16574, "PIN2": 4758, "PIN1": 4758, "SERVER_SECRET": "0bf6e5486737ec8d7d72dec4bfa870282b7ab9472b0d05ee43d8dec4ea280d3a176b0831187170a7458a1575f4489438470889a9cb12cdb62d21278e182c03fc1915b099a0821fba57b8e2204afe1c126d765d82a9748984efb358e33cb0449404c5fe636c403672380532f1f8d242acc6e216325b7bed66f34087736c6515dd", "SEC": "0404d82823b4783eaf2219064d2ff8fa9878c315a53574daddcf48beb0b797c542156793a696612f6a04c9276638dc3e62dd5ec88ea4d1f112c0e16e1fb6ae4593", "TP2": "0401247b1da9c13a7e0122b9d8c0b89fa70a413291c7488beed5d428993044dd45131664531aaa50e8e1233f305b2f30e1c7a912afab68f5e0a87105fedcb9ab09", "TP1": "040a595f1b4795782d02063120c40d6b69626facf7b94b516adf46c8759e198bd41e351a9cf758d172997bef58f6f517288e08e2235e533f1833e8c981e90bc396", "CS1": "041baf22372abe3bed7d6e85dede7e6319c9173924f43e6903abd0f704e7b9accc1e6822f869cf1cb572671ac821dde744b00c3476926bef03da7a704d8655dc80", "CS2": "0422a527f1e245ae8818ce75c9f008328945bb46a5068f24ebef68a0f8ccbac31518a1eb0acf7338fe5e61af9bae27e9f820e0a30699f1d36b2085a5dce3b2e31e", "HASH_MPIN_ID_HEX": "a630ccc25fa4ab0c568c1182e35c4c955949c884b800443e89bdf6dc1759e880", "TIME_PERMIT": "0403399fc2bdf27684ca52e5ca9d3771d606b6088b7bf6ad2ecead2ba9e7a26d8a1cabd530caaf1b9b1efbbd813f3ca18ff1b5a0f0191be1ed6e72de07b6c531e8", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33385a222c2022757365724944223a20223135383831373661666430393139396233643462313634386661383739353138406365727469766f782e636f6d222c202273616c74223a20223939303165313962386533333132313130656339376636316634643939313564227d", "TOKEN": "041661a2132040b68797ad42d268f7a6393333ab6b04f111b5fa905922c968996f06e267af5cf07fa46ee44d1bcc00efe515c517a1b690763fc10854489e10e110", "U": "04035e1381212bc53f6e4318647cc9ca7604ef8e86cad0181d9de91819c4d3e02514e3f372ecfb4b0bb573a2ca85acae75a6755213f3a3fb65ec123d9a7b5caf1b", "SERVER_OUTPUT": 0, "V": "0419a0382638ea37e7f584d408b19e0b5dfbc5f2cda587d72c97987e54fdb4d2640ea2d204dcac0f65cece5c2823d93c419c6f71782f2f8fceddd0540359db7dcc", "Y": "068ec7610d18fc11857d8473cd6cd3ac79efeeef532af7c7c351052a7356f9dc", "X": "1096ec3ed98e1f3a1e48a48472a25e56a55d3f6fc82a14fe276e148cd44dff4b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:38Z\", \"userID\": \"1588176afd09199b3d4b1648fa879518@certivox.com\", \"salt\": \"9901e19b8e3312110ec97f61f4d9915d\"}", "test_no": 48, "UT": "0407324c7770181cc6e03aed9ea4f8fcc801cdf3026b528b6e8e5c8f39d748972f17dfa77a30acc646caab4787b3e0e9a07e231588ccb46014c557100469a2def1", "MS2": "0cd811b35463cfef930554195ff122b28746203f506b18ec4d6f5fc2cadd56a5", "MS1": "16848fa5d7c563cfa6ca46e922eb3e561492f4407bfa41e601f10c61bc57b5e7", "CLIENT_SECRET": "041e272a5929543e70f0f618d7d96936eca0dab9e6d2fca96df31a81263066e108199c991fd85092cc62131dc5e9dbd0c5320c63970820ec141c611225321e4bab"}, {"SS1": "1ddf77b427521f957afcb68636c3e2665e643f200db2212d291b17c61c3391431b985908c113daf7bb0890669357c0581760cca28b8716d03dd5787fa4bf385107d3d512ba610efa0764c77151540c8b87e4ea5149ae2d09deb309cf4189d1231a022300a9bcc38a209ab68abc14fc5eb622c263a9f52d91e6deb5c76a512d52", "SS2": "142c26945ea314b22fd084f63f2793e829f05308e7ebe45bc370a87a9689e01909865183bb82a1b204e1ea2b4e4f28b8478a8e713194e75111a70f77a1d651f01e89a220f932bc87635e6f0df8af02fec40812710eb6f0b28ef1907ac427e8fc08827e7e97c66b7fcc9f8d49058335fc05a67a78822c36a63f552013b1ab3861", "DATE": 16574, "PIN2": 469, "PIN1": 469, "SERVER_SECRET": "1f56158313653247ce2a834039193a6ecfaa17abc09ba2cd0c9c25694c16fa7217d1889a17c5b10018ea0e676e8f855ed864f575c0e3aa93c5962ff6de4ca23117181023ec8ad4a49edfacb36dc3a700548a184a989dcea327d8b52a609e4c0c0a07610243c7b948c75a588e8f7159b72c9877561b1323f21f5de6453844a838", "SEC": "04026aebd9d21fa4dc0af091892a381fa1f9e29f79dcb644312edf920c428d843901446ab3264cfa5d19d6ee04fdbc491f5c55862fd3513df4def09d0faae92958", "TP2": "041032514ab1d659ffc12679113dc8ed0751e2a39d830add347ea7b5045a943090170078cc63cf0872dcd2600dac6d8a578d288e41a8ae9ecff37fe8e132bcf8f5", "TP1": "04117e77d8fe76a485d69007f3d92be8ddbb3f80569647c531da403d65d46ecdeb056653f2015a204248b8f1b5cbb1427f1d024332e0d0124527cc1d2709453f1e", "CS1": "040804e0981da57b8eba8902be87f2f8392654c142ae820f00335a7fbfe288c9961f88eebd981ff3b6a636686733708bbbc7a2378f3a91d74ea37b1e5608f39f67", "CS2": "04180313fcb800d2fbe582427f43d8017137d658d80b0930bcb4c5acc716ad74062061b3ebe647bffa84ff2c2713530b4820d03934580a3ed062dba088a54f187f", "HASH_MPIN_ID_HEX": "b014ed2387f3a77bda35cd404307bfd393ff096a7dd80a76efe7e78770166a93", "TIME_PERMIT": "040f2b83afa41d6531c73d8ef560fc230663ef6e0c163111bf0c3b4209d981137101dc5c6fd14224a65b9788470bb7dd701e900f64f52788b00fde7e9b3dab0daf", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33385a222c2022757365724944223a20223938343062303365323831613336316432643966653462306431336331303866406365727469766f782e636f6d222c202273616c74223a20223065613238653436383161373934636263323734643333653865663232613032227d", "TOKEN": "0408e6dfda3bbd4c7b342554e14e3c94ad486b819a77640c5d81d871f2c50167fc196c601088648a9f43dc6efb5621d5d96178ec15bd2a5361fe11b462086c6a5c", "U": "041d3371dc55dc12f7456a109d1fc21707b82c7f30f6ecc6d5ffb849237524ba321d4ec63e33b5569e182d6eceda6474d660cb995b6a99ee720e190e52a37e0340", "SERVER_OUTPUT": 0, "V": "04131046b8d835c1663b29abc4ca6a16cc5238ef1f145b2dad6438ad1de48d63f800154cee4de581a6cc068fc05bce10b97e40c62edfc51b68cec82db1cbaa3dfa", "Y": "0b3af42232610877112cab318612f844ee342f80e563d1a85b603b4727857430", "X": "0cf53673c81edcee51c3aa6940c4ca3d48d8b93d3a51598ab858aa5c8e7b1b7d", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:38Z\", \"userID\": \"9840b03e281a361d2d9fe4b0d13c108f@certivox.com\", \"salt\": \"0ea28e4681a794cbc274d33e8ef22a02\"}", "test_no": 49, "UT": "041691ebc79c47b0d91736d438c867bd8b8ced3e8d521b5aeea52034f98397aaf318c342935ee0fa3dd38c83862237c75f54cbe97688c98edbe20022c974376cdc", "MS2": "10814086f6ea2839cf92e88b7270ec1f09008c0fdd3c71a15db27b03aa5caf02", "MS1": "04e961372cd0307a6f7cdf35eb1b7baea02abb8b47df3870264f63618e03187d", "CLIENT_SECRET": "0406bb2f131855bb6e305faae70cbe497ad9c80d903250b04452352bc497bfa7511c729878bbac80b171f3b991bdb97ee7d462fbdce75bb02d39ceefa52de88c3f"}, {"SS1": "1d4ddd8a4332180ef10c29165d87ae62b6548fe552456a75c9dcb596ad5e5d8315a433c4fe74d9d71e92e50462573831a207a97f4f698b46f86a8fa6ecec5d94161f65196ea8eccea05691d72b42e70e0d09c7bdd45bda9a10977775f160d59716401fea50ef6db7edef1bfce1c245b4907aba40b5a85ce0b36451d13aff9a48", "SS2": "1e7b034652c2168dbc3221ded32154e1c0fe52d8cc4a948576930ec05e292106023a7b06907ea0c5c07e2c961093014d8888a1569d2eea77aaccde19fb5221fa0c2a531c2f1f1697d8ff7821609d75a8623068b7982b03d936bacb08f35ffa75103f9ff70555f3df058e02546bc466a6df8562560de8a814127cf940608407e8", "DATE": 16574, "PIN2": 3497, "PIN1": 3497, "SERVER_SECRET": "0c297655228addd008000a3fc1cfa222e5b0789ef4c9c2cb11017435eb33a8d1179ca81e09deafa2b409d754a172c486d0adc024b6cd6515423f0e7fbaef63840d8ce83708c7a4ad4209c863e0ea4316ea887fbb888c0cebb1fe5d5d3db61ad51542394f33b371fe49daacf826caedf128c490b28df37caa2682d93f294a2e70", "SEC": "041d1ce99f9c75a11314783a065cb50648fdb2484379995e3151eb9cfc474320661e8a2c10d8c24d95138c8f668cd631300beaab515d42f9852bed44585edd1cfb", "TP2": "041ac81d8c09bc6b61d927b8a6eaae2d3977cb381345dc9a6849f677cfefcc73b216042320bf5b86b1ee4d6ed323159120d0706da46117390df4b92fac3ff3dfd3", "TP1": "041df296f867ce2a80ebf8bcfd36b8eeba7b5ae3eb0642ff889367adf07af995121a4138f6d158f83c934259bcab51c1dd2dad5f533515a5acb90350610790bffc", "CS1": "04077bb3c3bdae0ae253c9c4539387a3badc266e2c6d44e4f76b1a321c3afb9e69037b9ba65304c6585de2cbe4ebe23e9ba1f33ba8c5394eb68e65c4ac8ae4eefb", "CS2": "041ac819d9a54594dd18b8e7492ffe27aaf71aacabb8d97c2c3a12bb573a8ba7b50bec6b5f30d937e4f349e1c55efe5af8adc2354c4033cad38b663e5b03e51f81", "HASH_MPIN_ID_HEX": "b6358fb8af8a0ef9af994c0176e836ea402de2b4f79e767f1148a64c87945cab", "TIME_PERMIT": "04178856d43f84fe9131898719253973172742837230526c5acb6c16b584ef0ee7002c467a6547d41ae577f4d14199be28833e67e8fcd015a60003f96a49bc56e8", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33385a222c2022757365724944223a20223865336435636537363430313037383234333039626339646339653539623737406365727469766f782e636f6d222c202273616c74223a20223063356531306465336430323036336436373232346334313666383836633530227d", "TOKEN": "0417f6818048ffafd991b916c03214d98ece7b9a3fbca4c8055f1f0f3ef35380cf12d7b3d3d88c8466fa999c46599b354ed19c93190bef28c8c09c10e25f982a7f", "U": "041d4f2078440d79ab342e83d8adcc1d8c75d802ef9c13ace8e015b6f0cbc5eb7602a28b60dd8d270c5bd28595267a399fed42b69fea1d8605445a294ec3a543e2", "SERVER_OUTPUT": 0, "V": "04034a76ab692a7dfb157a266d293c8c27a493e2410712feaff7e958b61195938212b39610534dd5fa7df0cbf88beec099ba7b6fd55ef821cde877ef702e9f184f", "Y": "01fa852348559505fd59bf4c1f396ed4c4d226caa6931508e6aa443337b661a8", "X": "110cf640978493d5eec05e0d63d20716b321ceecaad81abbffbbca1becaf732f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:38Z\", \"userID\": \"8e3d5ce7640107824309bc9dc9e59b77@certivox.com\", \"salt\": \"0c5e10de3d02063d67224c416f886c50\"}", "test_no": 50, "UT": "0414529a26f4bef740cfb2388bf0d8a4de55cc99fed11878bf026513471e3e66c90b2de4c5eac072f61fa72b159d291b3b0b1aa77bf78e1fd45083194a6d4507d4", "MS2": "23349daeb7e762ee26e2375325b2501530abaf826008c75512e710d0686e7622", "MS1": "21350b4d17b9fa0799f5b5b43285e0ce14c3af1b378db3c6c3c8d706482b233a", "CLIENT_SECRET": "0404d8b525fef496f634aed76d47cdc281ff6c77831c3a318558c15dfd957aa98e04523314f6fee443847861c9aaac8e808d7c851b61bf6044850718af04da05b7"}, {"SS1": "13c2e43514e32c1906d74c35c0fcfa4dc042d7348fb349a62db97e23fc9f195d026e808280cf19b2b6d53e5781a4e9e07e91f05cbacc386445b5df61b5997d341af258c9e5d2eacb7f7770047bf5eb21b92db52f81c624634686717290164ec3232bfdc47ffb58a54fd3b1fbc8f6b8c21844c73fda90a7421e019d2f71856325", "SS2": "04d947c86aa00be10545ed97cf03685852bd2851f96b2b8fa5fe80606df17af315e6b563bd81ef356805c4899811307d57da03a61955eed3d1212a041a206b4a032201b256247388b0fd0b0e40bdfe98e63ac8496dad229b1dfb32abde0cfae70cfd906ef58854fb2574b30ddd62b92c049b7488edfb49521d4a9a4d365d78f6", "DATE": 16574, "PIN2": 4694, "PIN1": 4694, "SERVER_SECRET": "1d230e25c52006b8dfc6e83395b4a87c496d94614dab770dd8c057abb06096fc1a76f030306ea31d18ae0679b87c45260acb9aff784316dd92d2f0e55dba371b0ca78f6df3ef8de376c69ea825a8b65dc51ec2c1347d5b192170dc0e4031ae5010e98cc3e95bb13fc708b4ef751fd95ef15d946aff0340b26837227f7b888f9a", "SEC": "04023ccf01acca018c127fa527bf19909e008dbe2a0c10f804b8ef40965b89afc308e7cb8a384ef455ca50513f77abb33c853233ede4eca3f3a8ede7b235a2cb7b", "TP2": "040bb02f6629b79e6d3aa97ae9fddabc7e38d80ccc39c8c028178b3b1bba05c48b0e78df36834be20b16c92e7205ebf45391054bd2a062598eed41af28f505d448", "TP1": "040625504b2fb878bb954567382e23c6d224c51c6ffea512cb32563fe64c143e4309524b17cc03dc4ad88d6854edde705111ddae967cc12f7c0283f5253f5e8a0b", "CS1": "041b980f94cc78af866f9235676ba1d8e1288cd8f1f3e4f54ae78e2fbcbd35fa520be9c3e1978a06e68e4f6b5179e6bcef783c043d7138bc1fb2105f992e8a6d01", "CS2": "0422cd3c66289f4141e1d5c22146eeacde00c3dafd2329b9be417612f33c39d36f024786b9428feccbef6810f84247865f47cb091be809235c907d60a8c1b8b70a", "HASH_MPIN_ID_HEX": "a3d211c0421f61ff434d872d3d4f6f58dca33c3e24afc2334686c1c238296d37", "TIME_PERMIT": "0415fdc80cfb9e4b046d2270f264641878c9c7133e751dc00eb36e208953e3d5cf207136befa7d019bbe80dea963ffbdf1016d21f9851b579b4c5a2ae172417275", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33385a222c2022757365724944223a20226231643161323665383730353163313832633633306634613532663262373532406365727469766f782e636f6d222c202273616c74223a20223230653463633538613464623730643731336436636261623337353231353833227d", "TOKEN": "040086e9ed685bd57d73a589aedccc870b2c14459af91b1c1a12fa5cfffbb3019f1fb6f501c34061d085841ef8b585ad3fecce7a4bcc4e938b53c5a008db823282", "U": "04067963f2df332a4b028010b275a1336c4de6f1865e1586d99fdabcf04eb8b86d1d514db58d12a161d02d76f6fa801937628e144f789c00ec0cbe19eb235a3622", "SERVER_OUTPUT": 0, "V": "041acdf96d7484993aa39ef3d8ba94843f4fadb68f716818aa1edebf027d5193d60318150b7456d739d1b0dfeb4c55c0c77e10872ef60f6a8c2a87496e058cf50d", "Y": "11591203692b68687045f9305fd88a40e861aa5a8cc7f32aeec6cf680e8238d2", "X": "1f8b4260b7e64156b673a1c9dfce515ff1263fc07712a4e2434a84cfdfe6fbb2", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:38Z\", \"userID\": \"b1d1a26e87051c182c630f4a52f2b752@certivox.com\", \"salt\": \"20e4cc58a4db70d713d6cbab37521583\"}", "test_no": 51, "UT": "0422ea3af2002a1066ab314f6359a431fe7f20fcbbb48e4d5367ee9a56f799562417669532c51912713dfc958b8909ef3d0283e8a05050c9bda24f27a641489166", "MS2": "0beab5846ee39091dee358e8d40e5c87b57cae86bf6c5891b892534f4f667b25", "MS1": "2289251afcd56d714c30fee41789d759f27e4628030ded30db98ac8a533092f9", "CLIENT_SECRET": "04092eed6631f90691c322b3b54cbcf36942d3c3c986a2c8036953b3d587698c17001239e1e9f7d5f1ec9556cd75b5c0f2168c4e2b548d414ecd547fa2708a3c28"}, {"SS1": "129ec0b6f77289f510fd96ac0e9191ef1c79e3c7b76c23eb912a0b17cb0036381758022acba113b2df4b71ac92541f0b00061d2ef258d86b47244fbbafb70d590ccdf938b543d7f7763ef4430d717774e9cfc454b76186f80543d55afe2731e615bf45179f439132a098dee7a9086840f139088097f8b1b59b19f515599a23b5", "SS2": "0c12a7f7b7f1001e95b2e99c87593c5753ab17a0ead9a50a52f90446c7176b0514792bd2b5e8c3c96280db5abbdb6cc8bc286a36db51db761da45fdf8602b7c8185857f696776e4751530b0a34a1d9d197024fd65b9fcfd653c18aa5066177fb128f19a977f7ba2c76a8c842c6d92e7efcf5cb3b0fade658dacf125075dbfd03", "DATE": 16574, "PIN2": 8369, "PIN1": 8369, "SERVER_SECRET": "1748448d64e676a30bfbe89ef7b6cd27af59d89ec4ae7a688f656f388637aa94156e868cce7c480e2dfd60cff0420bad3df2274529c6d4eef274259ca7b9a6bd1ea25bbcbbf00d6fd560c487806b93d6dd8e75dfc769980bc90862d2eb20207203c680eb83ae0aaec7ca66849b2d030b7f7dc9f9737a6b61cdabe02254596556", "SEC": "041f29b850d3bad4d91ccb6c67f584dcd765649ee7e6e50b8452697141b9f27b4307cfbb8048342d1ebc5c390aa145b5c22f7b26714a3d16a245813077ec4cf8a8", "TP2": "0403263958b1578cc11f4e32bbda30d21599263e3741f0c5e4cd9040f1c4121b0d20dc68a439adcdcc2b3d01d1e126c3c13359a2dc267947dc1b7cdeac0169573f", "TP1": "0409d563970756792f932a13cfe84d3146ed8ec31f7571b34921bdd42fcee3ec4a0fa2cc150d70576b7b266f57785c5c86d3a3cf545061b13b0bd6decd3b99861f", "CS1": "041da61b610776791d60441b4520e598d9a8b60670c848ea4177bd7af76e9e70c90dde0d035f23f2080129c5250174f6be01a23f6e5af2bb450ab4c235f139852d", "CS2": "041540f58611633bf6c38c5231706c171dcc1ee94c862f141b9e6f6d6fc8c9cffe031b4b65abe395e831ac1f5d332118ce98c2ac81461c3510e163a8e2d741c8bd", "HASH_MPIN_ID_HEX": "1731f765e16a27554100663d6a896376203790879d16f6485a816acb927e5f9a", "TIME_PERMIT": "040aae00b65e1205dd90bd268d3b7252c36ed3ec68b39e553ebc262b23968346782278f3a07d1c89a4c6d975158b235fcd2832167fabc03b5b3d09b50a6b67400b", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33385a222c2022757365724944223a20223362396539326633343737313961653561306564653830376131336163663434406365727469766f782e636f6d222c202273616c74223a20226338633434666465323866653737633336326131353562663764346365623133227d", "TOKEN": "041780c6f85a70c3aff7cedb13d76661e7275478bd8efa4e1a2b2102daad3dce7c0c8d8cf3cccba314c735093e086da988e2339e9fedadb0c25344836905151d97", "U": "040b30cafcc8b9cf2b85b8a89354850341dfe8d295cd7b6455142334bb2051692b0628e16c7a1a8930c3d979e13205105bbba33e1d5d94ebdf79374069e206536d", "SERVER_OUTPUT": 0, "V": "041338d016b2a063c665a2cc8f4ee3623988aa1006fceba2cdf1984e1b0fe1ffb21ec874e038bad1f6b00c739f510408d48117b87ffad8614d8d08f434e59392a0", "Y": "07dc1ccd0b39156741959cfc78d6038ba768060b0932f5601bac66530c7b27c2", "X": "21007710cfb16ce2a9b1e84932b86c2bb25b0510198dd6fcee4e2eb5d6b3fd33", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:38Z\", \"userID\": \"3b9e92f347719ae5a0ede807a13acf44@certivox.com\", \"salt\": \"c8c44fde28fe77c362a155bf7d4ceb13\"}", "test_no": 52, "UT": "0406d0fc08baf703f20c8550f22093efdc40ee81e33029268a8ab2dfcdf155b02115502673516022f7908fa12a29ca099c31acb81ddb6e71adad3e800877fd17ed", "MS2": "133418dc4bd70d1aeb96701ebc004b91f5785929fa844a6cc568fd7404c03887", "MS1": "082e33cd126704d1e5b7745d5365ad9805e3a6f26f7e5cfd3db8c9f1f9eafe7b", "CLIENT_SECRET": "0415723b385f05b7deeaf162ff8c750fd3778ba983ec6bb3351d513c3b1fc63aac1093a06506f8ae5afad432423f0b696dc8c2019195bab66b13bf91a1246cd856"}, {"SS1": "194dc4ffb7a12033d435d37df56f7ba2c1caae2d69579154c49c4c85d22a763306c505df9986180b196147cd5f5e099da1712437e3edfe9e179b4d5eee082bb8101facc9f0a7b01baeaaaf4bf06effb27bb997bedad7b39613deaded00cfab0f062c9084d36bd730342e37374c1536c166356cc59f6f2ffe272c2a0f200d059c", "SS2": "07fad26af633910e802d7267b005d5a93cd05d4136a4b752c54bdafd123b56c620f5f23c1120fcbc4c38292b47fa2bb1708054cb90b5c87709d1533ec3e961a80323d0fe331c356bfa590ca93adc9e274c7c7a3ae1bd1c105cf66095f3c22f2917790d9db749e209d160f5f6cf2368c56b759d36214640ab0d2943a82b27f1c1", "DATE": 16574, "PIN2": 6671, "PIN1": 6671, "SERVER_SECRET": "1ce1260f75ce4c7c36c8e0dc14e67218de76b8b211ff36653ecd74788807acb3191d64dc20ba3dfd91d074b95726606f02858729b296d40388fb88eb26eed2a6136e01ab32f2299dd7af005e4637c5afe7bc3e91bdb044d11119c9c4d7e6ca0401e552215f1052e3c41c6d5a7c9261dec3b966d485e8fee9a4cc0c6558664dff", "SEC": "0418e1d0161482c7173fe703ce656cd9b7dc165197c4aa8185ffa541000bafbbe01651d6fa2506f20e82f1d2019ea2affb8ad3189b1bb6d13471c8446d8961af61", "TP2": "040d20b6b45319cd5da9d3d578a2bf5205cdf838183625b8fa2bcda795440b12820c10871fa45fac4607f5b4adf2e9bf05dd078199be06f03b7ace4b60f6550c2f", "TP1": "0402421782335ba5707e45b80458ea598929285f63b8830a802dc4665a21924c9506058a234d25b148559f7e21f10b8d69cb274313236cc42704931f0d63472deb", "CS1": "0423ccd24818061c24ede8ee39a2711dbf9276ba380af2541197dbabcc332fe51807f2d68aba8c83dba1c8e2cafcd03039243641a4f37cfec82bfb0e9b901cdd06", "CS2": "040c50f156a7ea3791b883f60e0c3fcb9c04e28de435eabdcfc4f9fbc15167385120e5d11cf1f7e19b367d5f2545d2df61eb91b54efc7e415a038fd291dea20872", "HASH_MPIN_ID_HEX": "11310aba22955fa3579b159673f409befa0a8872af458a19639515f9eb719df7", "TIME_PERMIT": "0402e1ea3d2afb19639c3e4cb6abee2c1ac4779ee7d4adb5cf8764423ea448e6ab1bb32c2dc2d04893f55edf5249b85e9d70b1e42fc4e8e3c6b18ee8af93a6e89d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33395a222c2022757365724944223a20226137643065326436346336353162313139303165373437346639666665313033406365727469766f782e636f6d222c202273616c74223a20223835653961653163366561336364326337303236373761633537646336343234227d", "TOKEN": "0414ba058a59f8789fa42e794d0f5cc02727ce7a866d4c9fe16a9a86eb7707382e1c6c3ec3e2ab8c15a5d08a24891d391444e40124acaea99294f87b73fc172e35", "U": "042165774c9d1fc0f807d138a9e6568077a55d2446cf4a00343c186d12eabd8fce121a6f38bc7c72a5474615a200e0a06dddb6d98149705d94c7c9a3f298c0f5ce", "SERVER_OUTPUT": 0, "V": "040b4b83e6045f5f9e4f77d9d9648def737f4cc1f6448f0647b3b67ec3188a16b60b9a45de357b17b255c9d0f043a4772b7fd4f299c728025ba2db59dfb53b37cd", "Y": "123f49c500891862705dcc129bd82902cbf905c8f31553907d695f3b8ea2cbd7", "X": "1e70f53c53102fb7f6667346039ade20c69d0b90baadd21145f770832d86fcd0", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:39Z\", \"userID\": \"a7d0e2d64c651b11901e7474f9ffe103@certivox.com\", \"salt\": \"85e9ae1c6ea3cd2c702677ac57dc6424\"}", "test_no": 53, "UT": "041e0282f556659a1d3ca40756a5b7e725f3bf50848b1581d4424747e4e847110f13104715c4f8e7812cdf5c2c0f95766361194a95b8c917ed27dec270eb128f9c", "MS2": "227e815c47bf019026a87aa2a16fcb1d4a6359c2d19cc64334116c3e09b348aa", "MS1": "1dff723d68dbb95fff7e6170d775a595ff8b97157fc0e1da3c62dcde1a87ae04", "CLIENT_SECRET": "0405d62e6a5218822f8568c7e7f757059f7f3d53408c22ce8f91d60f64c27e01b3185c618c7b2d1636cceaff8a0276e38008f59d5ff27ad57e84961264c6ccd5c1"}, {"SS1": "15ca9e1e71b4c31fa3d4fcca6e9a65af592920bc8f2c0213ba957aa562ca5ace2143f482ecf45aea3e750ba15b83a18a7d82d355109625169059bdeae081528f225112d6e31f9487f50a4bf4b45c1770944f5719e8abcdb3e60e3d9bb12d7e050de68085f8c2bf2f483e517be685f5adb314f64e75a82d31e1550b64195b01b1", "SS2": "214dd8524a723494298e2812f752a95e36265a4bca84f562338e423ab452db2b1b5852fbd27a1efd6a4fbb5c4b11103a78e8a6746a21d556e6a630388cc29f82155fbd194c6f60a08d6f28a36536ccba43a984bc4cae0767b5cdc00fa5859360214982561f5836a43054a0a45ad53601c1b07dd15ebcf1eee53c88e72a40543a", "DATE": 16574, "PIN2": 5850, "PIN1": 5850, "SERVER_SECRET": "1144781d95a4fe22290f1424e4e21448812ccc7d2c125bbc1c76f9283f6a009c0399fd3275383852e48f43fb4b17376986688821450492688bdcd17fb0bba51904c3d943f0e4284031d3dd3cbab155c79eccaf961a0e2f35e28f820d8f1beea01c6ad42d664bed09836af43426d0b409b43842cd7737b30c7c259d71cc874b6e", "SEC": "04181f6f982747d4186b1b47db943b7d67c1028e3258f354e5e2bfe477d4f36b2019cc6b94ac2793b0f9e9472f9f63e7fdb130d7d1fa7e78b200662cf7760bf67b", "TP2": "0400fda156c204314674e2c9d2b598d63ae4afcf1a70985d797ef9c072299f0fb4168794e72ed0b98049930c86d9f7abe67129f383337f1282281e8b5f6207a254", "TP1": "041dca6cb0557e3535a95a6048591906839634676114257217f5eba7ee6e7ea6e013223ad2a6b22106f370a456a374483e1105823c3672071ed8ff56088db8300a", "CS1": "04142fe5a58894c6e0be1bc10acdabd75fdd17aeb82a2823f264f1c1f9d18bab9718456fa9d1887578579b7e569b11163708718d0a212c348dff15510402229560", "CS2": "0418fb567dd87f628a43f742646853b6ac339446a6c840b6dc931c1e9302dbfd201864d405ae94ac30592592aa6158d2249cee0a975271de4c667d9440d3b5e359", "HASH_MPIN_ID_HEX": "c054c0859bfd05ebedc10ec91a4bad892889a31c443d745829cfdf4c95028e00", "TIME_PERMIT": "041988ba911f3be238d72f9d4befd1e975150f6249e49310afa9bf4c56d220b5cf0536ae59bc9dd8079038bfef98a69ddffd67b94b6a292f486fc21d8264bffdfa", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33395a222c2022757365724944223a20226538633564366566633033383365316237626166373264613835623164653930406365727469766f782e636f6d222c202273616c74223a20226233666332386362393832363537386639333662323133643838633435633235227d", "TOKEN": "0403861cfa4426482d95190b3ee40c03fe8b6c2109efb98a5f86a4f9d914847102184cc474de368c71da9524fb611f317e358f9c899e4030908b16d52bd51c6d27", "U": "040d16a51af938b6a325d7891ee14d00b1602bbb5f47d72f75166595b0cfe086672376a775d0bb7b3dd91b93f849b68752db3b4cd49856206c5483db0104fb57bd", "SERVER_OUTPUT": 0, "V": "04113711f9780ca0ac35cfd6847213038baf70040a827d93c3e1ad7f7f2e75e9ac1d38467a8c3c7978bb187bc604a029dbf71831b332321216de2765b7b54d47d8", "Y": "120431aea2869438733f0c5a340c4b55c4dd7ad0142b91cd1f5d9a2961957bab", "X": "0fa6d419e2a332b8f8b3e1a3415d30d40020dff95982684a0478d15be7e5c491", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:39Z\", \"userID\": \"e8c5d6efc0383e1b7baf72da85b1de90@certivox.com\", \"salt\": \"b3fc28cb9826578f936b213d88c45c25\"}", "test_no": 54, "UT": "0405a8390b1c0395a7a0b4f6b60b444d44d587813881fb5e06bdea3a1029270d9306df933f015838f1dae709a114746fb236b87f91f427b3dffb1cf68e1252a743", "MS2": "17b4fd2e3db2aee268621accf33e002dce98ab09e2973ebc3dfa461c93c3fce1", "MS1": "22f91ee60a3e935f08114db87e882c568e2b20822c7438742d0df6d4f0e80a17", "CLIENT_SECRET": "041a1bc66e31a934270546234bd44cc38e39441d515bfea6231e276adf59abd41f0451d61db6b8ddb46d11ceee71b11b5622e52efe8569ba508cbd63c6dd086a22"}, {"SS1": "0574dc399b83d45490d541dc8d01a5e67fb3d01c5dd3100663af3fb77171a45b1b34e6874e7d49e736d302f5f7c43411a526bfa408cba668267a18e4cb599b7610aeb3e873a0bb0f2e63568b1db4ce0c5682b35eed44167a58ccd4af1aeeda492197e72d85a7eed2d78e6d367f8e4c0126c0d9fe2c37bdc7be344ffae160885a", "SS2": "020dbb2be92825c96e6c35305999180b3118dfc6357b911ef1c2e7aa7bdea64223373b54c306bced77d1cdd0dde354af6e1cff169866b02da8b30557370e43b71411e3d122a9724b368024e9d16474e9986965885c5c871128191376354d40c91e84f62fb7c5b146757b9235938f575190c9cebebc01fcd4f191770631f8c770", "DATE": 16574, "PIN2": 9154, "PIN1": 9154, "SERVER_SECRET": "0583092e3b56d0d1365c1118ce822408086ab8b04eb634e3c0c5ffdaf4dd0f111f09d6ac6fbb996d318d83694bc29c9d37746ebb3d89fa8bd938c83f263fa677237f2af40a52453731ea2e5d58ce2faee94c2eb5e9b12d25f473f92415e6e2a61c826e1bab316fdcae4c4915dad2a8b33525083698ecbbdb2d0fb8a1417b2fee", "SEC": "040254540609ed26f13b90bde600b2323dd8ef68cccdde6f5580484465d1fa23711ff6aad2319765e181951598376d3b8b3d7a553e15cf7f668ba912d5d7e5a0ab", "TP2": "041293d76ae6b5f32d72d3634945bb591636f5a4c502353d45694d953cb1a1eedf0b371ecb685a9711e2e5d15963d223282777d444e845502138b8da2106bc95a4", "TP1": "04013ac5773c73d6dc1cb33a28d8c32a4aadf5ba652d10f5d1d10be2423ab380c906d9d6cd522d880a3a3ba1fdea151d0b1e78ffd0c3bbae159511e7ba0ddb9c78", "CS1": "0420435dc4504464d0980b90f06e845a25c57c90b0154fb0f1ec6834f7627cbce31c5ad4e4869bc023121c6f6458a22848cfc0b77d7385d612c3a24067c42d758a", "CS2": "04005b0e4549fd9484f763f2382a2304db044cf53f9814b35b973cbcecf15605cd1ea7b677167a00552e3570665207e667f34ba14c9f6f78e12dde66ebda80b7e7", "HASH_MPIN_ID_HEX": "2cf8d6f7f60562ec35a2e773418ff66f9f7c8422193a330a596067d76e4a5be6", "TIME_PERMIT": "04001c62653fc13a7b584b8d1004b2b9f4b999d2e2a23ec6f1e2abe6531fae88ef2266a906a06bc794135d0b4b9e5e930d99ea32034b01697084454c4f742200da", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33395a222c2022757365724944223a20226632396534366165366561353062343265626637333831663637623138636236406365727469766f782e636f6d222c202273616c74223a20223934323133376139373366613831376162396634343865396536653233366638227d", "TOKEN": "041c83496045499e94eba64a5fec3d7d6113d05dddadcbaf24a4eff835d68cddbe1e2855ad31adfccc42f4531804410a25281b2b2a7a06b651fcc1a724e8097a65", "U": "04143b32345a9d04a5d934daa6344f990db3a9e916ef1b791bf0d0c31d79551b630193ee9f6b20ce10c1e53736d40f11b749617f3e7f1adfea5e7a33226a8dcda5", "SERVER_OUTPUT": 0, "V": "0422d28f08715508db925b7853ef898a67d4bfe14772f6a3e3aef7dd0012e931c21fa1c833f869f36fd77ecc404e9bd00f55cab828c49f09f77e10060823760481", "Y": "0c15e73e00056241c1832642f7756a0ac9afa23fe63f905155a18e581a0a85b4", "X": "032c1dc145986556c960ef2343f78aa3d43a50a8d14e58056cbf07ab9377c025", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:39Z\", \"userID\": \"f29e46ae6ea50b42ebf7381f67b18cb6@certivox.com\", \"salt\": \"942137a973fa817ab9f448e9e6e236f8\"}", "test_no": 55, "UT": "0400fb72ad56167134bbae3c97d7bf81f5ac3988296b337802fd2d108313dc17ac1cc23b27b873b308c6bf8c4b50211ff918d170194c702d8acede997ef6974003", "MS2": "0e554ab7b4d60df6ecd133af01b07cec0cf63a470a9cdb19d84fed43b63cdb32", "MS1": "02bcf806a717c51864333634b8585590cfdb7784358dfed1242fc7d086e790d4", "CLIENT_SECRET": "0411d62afc00cb22df7bed1eee7365ba09b188ca240e44ffb5f7ee7015197e18b8052c5a1fb038971c713c397e6717f934898b4f3082d384cb542ca6986923180c"}, {"SS1": "0e6304c881496e0c263566d435279c409de0c4a63b2aeb65b37b8e7fa1cffd7c1118bc08c4ee246deffbabbbcb3fb4994620d34a36eae5b2a66f03ee9b996f2c0852ada766886e3c2b8cf41c7057e3f293d30d54d745d2cb3b79fab72045aaf22172761583d728d082548f885c6ee725e043c0c3ff80c564dd8d2dea779f0029", "SS2": "0688629f2039bda132ca673ef2194824fcdad464054c957e515eaaa90e68e52f113c2532f7dd3dfc8bae0a898d0c401c82fbb5f5c36a0f93da53c9669a0bcdb504c17337c1ab4d32b93824a248d52f423d712937777c2b04559422674f163f44169edb02326d922a87d5fcb5a66349ee578eb703a0da53c1a4c2094513dc0f01", "DATE": 16574, "PIN2": 306, "PIN1": 306, "SERVER_SECRET": "146ac4dcb5d75b9c1008f681fc367833d45af89cd7c3673eb23ff6465af3d1dc04f714817edb0d1dfee4e1f642a1ea8cb903c3c56b07156fe8ed7217c8b92f0023f2e1f623f236f65f21d3870c5d8e671e3d97281b20a8ccfc9661e73aceca671c166b3dcc6714c1bcc8f186f23b3d61e593cabf4a4d8ed26c6721f005aa4eab", "SEC": "041c9d23431a648a5b6f27d88b3b322d82f9bb867e486dc9813090b44fe314cff61ebf910aa05b9ed91a98047e6d670ef15fde2f6220253246556e2d40427162bc", "TP2": "0412f8d6d54ef7517613cdf297524f42235185e670927fc2bf60bc9ed728d2c0941f6260d378dc61764346ed7fcd32697ec3094fb13585cfad189a5fde8d90fdc2", "TP1": "041d17f673da72a8af9529f48613916b78bef2aad830f81a3906ab7de2752236f117e99277dd5a161605950e4a2a7efe5d4ab605a3488da2a8cc4ca0349a6ab4de", "CS1": "04082949e090ca087ada85728ec005e84eee30ea123645293116571a0a4c7494ac201c5d5c01b5106a3c04b8ee3f7d34fe5c8192593b0b598bd01b86254bb59abe", "CS2": "041a8f2bfa507aeaf2ce8fd8c6f1ed1272dadfc303e914866d6d35428f659d7aaa06819bf0f05ca4c18e287e2493612753d032aeea67c1acec85cbd587cd2a2ebf", "HASH_MPIN_ID_HEX": "af5cde52fc0bc9900f5d582d6144be38de9a20c010fd467a2221dc9fa6f11c97", "TIME_PERMIT": "040f4aa38ab2395f4f414dbc86b8bb2994924550d6f70351944604e1b6c0c6200d0f41c6948f54403c76df99defc363e112eadd37d7dbf6a8b889165404e017c85", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33395a222c2022757365724944223a20223935383964383361663863646639373332333336613437616162333736313237406365727469766f782e636f6d222c202273616c74223a20223561356431653237326230356432383061666135326235623034656532396134227d", "TOKEN": "040261cbf2ba8bff1efa03d19e4b0c3c2354ae9fb03a90e9c97a6f7fc0a94b9dae15816778a3ae2a306a91f04e8be2bbcf1007ddc83fdec75fc12039626405fe28", "U": "0406b7f50c0a9a7c5ef1194966899b9222f82767e7200a6c0a4a857053226237671b817fa2f3eb9b146783637209e6323daf385ee97f648e94301785d1b3e9d892", "SERVER_OUTPUT": 0, "V": "0403b545ab211b77ced1b0d1841fde4eb071c4b9d84509dff61950f8db232c8f730901867b8123ee623592a8e7aaf77506dbe681ec11fef30a69ac6b853d1a1248", "Y": "09450f3f25d2d650d7003aaf96b7a56848cb618c72c985ad212d6b8f9b0de57e", "X": "21858aa5c3c028f9e382d1a3b9b865a1da2e6cf0be97dc06f7d3f5a6ad1ef555", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:39Z\", \"userID\": \"9589d83af8cdf9732336a47aab376127@certivox.com\", \"salt\": \"5a5d1e272b05d280afa52b5b04ee29a4\"}", "test_no": 56, "UT": "041bf275be9eb8b5d781dd5c3d4666cdf1f20a7655aecd7c14991d4b56abf4da0602a7a1feb64fb057fc768940efcf47b5e243342c8c64d76b8fbead4cbb850968", "MS2": "1aab05fe9329664a7e2a7763e40baf6ae36c990162e463c2703f5e8e2acccae5", "MS1": "1b6393ff74e299f935d4215a96a9bfad3eb485d6f00dd0d996f9530f2fcf9248", "CLIENT_SECRET": "040b210b0357c99a124f052bacae0101aa100db132244d13c14fb1974932a32a1c075fa99746b47245b599dda5aefe0f4a19db9bb6ffabb4ac7f951308cde6ad95"}, {"SS1": "04e3cb75671de52effe2c6208ad540fced31543f6a7c3283228329842ba27625032238537a46681a4bee060ae60a1639acb3688c47d8f1f7de4f824532f0d6f317bfe3efa79f879c8b448f7aea6164daaca214f943fc2e298202bc2186eeb0140bd549adfd39caf6807bcb1f15b4701444c598c532e2da815d1d31dfee2d5980", "SS2": "178603e8990e02c633b011124597e6fb1e0dc42a20efe385a4427368319f193809c7358c07aab431af977d1f4e6d72e5bbd3bcf77efa0ea8dae62e7c58efe8a804d5a0e1ef8c26f140b75d70085c4804328ef9ba2c8c28d6fee946c8bfc53f7510fa35d9a62628190bd91fec908c34e0d210c103b03f7a91b9be3ed619b3b586", "DATE": 16574, "PIN2": 13, "PIN1": 13, "SERVER_SECRET": "01859600587f3363adf0f092fbd9b8a3f93badccf45363d81310a40f1cd4d4b413a4000d0a6661257f66775f7a3d9276a6f21b9b0d45c233a4c95bfe01602c820b043d069ab9d86bc83dd9de50b0a5227a8ee367d8dc4a8f4be99edc37f4bf100f6add318338344c3a660e35474e899350799cf64269da8fdc72763ae94d0464", "SEC": "041df599641a9abbc253fd0094a086cf4f2993170fb1ea81c101871345b2c352810faae61da428a0bec3846020ddff80d037eb073ee35c59461ba7094db3e41d97", "TP2": "040de0cfc0ed5a271263816bdb1ec59c187bec00ecc6b7b57d72721244ee405f8b12a0a5e1fb4aadeca1e73b728c494e60ccfb84371f55cbce945597997079d1ce", "TP1": "041e291cf2163b9c8b612a5e9f3ba3906708c896956655f54ad5fc8241d35b0f6018abbeabebd029734412327d9bc25b3f9764f91b13a6caaa2fface901b160ce8", "CS1": "040bac20e780c5f36a618b1da5c2ca6e20bfed2ab341e264e68ccfaace1f4579bb23f0f8782e52ab9f978b1ac98db1345d929ba8bb4ec578cf93fe1f9e7bf2bf9f", "CS2": "04176103ae36207642f04b57c837e191278f2d4710b9ef171f37478a97eccbc65e11a17b1b27877d768f2ae92c75accc9d6aa2e7486b5c525272dd423f641b91a8", "HASH_MPIN_ID_HEX": "76acc9523616e049ef0f55e4399dcd15c2197f39a8d47006a1250d967ed331c3", "TIME_PERMIT": "042235f0b85728c3719a866c3d56b7cc174f62f264740df88cc6473491fca20551183901f60575ef5b6ab571d44f645e4ef74b0cab0f1736e50494cea90a2a577d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33395a222c2022757365724944223a20223561383334616536313630633938663530306361333463333237306633663033406365727469766f782e636f6d222c202273616c74223a20223333373639313339323966393061346534393235333930366536633434303561227d", "TOKEN": "0413c231634714e01b9048bfe6c33911f9cfc47a981985050698351d0d081b99a8091f786be0feec18093206f0f97303ef0b2bc101e1cc221a4953291f9a66a894", "U": "040565620a301461506bbaefd1c5ffdf1f1b8a9f54abf72d220bb7758fb0927d800d9a977bed7a77a423747e4faed33d2ebc8f3b5c2472347154a895c159e381a4", "SERVER_OUTPUT": 0, "V": "0423480209d476f3dab30127ff78eac2da89b5c87b8d8f1fe1c91cfd41574be2d31520c2642cf416e00b65395ff6c2121be268d32d65c258c76bbeab3ba5df3369", "Y": "19caa9e9fc6c1e805d5fc24271e15ca8301fa3144465bae7c4764323871e7154", "X": "0fd3602482dbb186913934a5306a1fd24f1dcf5d492e08fd5d5fabb182e8f88d", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:39Z\", \"userID\": \"5a834ae6160c98f500ca34c3270f3f03@certivox.com\", \"salt\": \"3376913929f90a4e49253906e6c4405a\"}", "test_no": 57, "UT": "0411213c47041682cb5341ec07aceccc2d1685f8a32ff70bae35836a8a9d5e78c6112ae269585bd53f45ab5f9ad7651295fa6843874804a5be51d935b1f8057d9b", "MS2": "03d13692a2ef288d19f03938cbdf45e7bd805ecdc821b409f2b12641256421e1", "MS1": "0b899407781f9d0c9587284a80e8306e85903b45b819efc795ed8b6c0987f211", "CLIENT_SECRET": "041b22c2e195dd6e5b8896b8c22adcd091132011d86a87f67b4b8426e4c6bb442b201ff6338b19ee62236d1f45dd9d182bc23cebec65435eb0ed55f1e9c0ca2d36"}, {"SS1": "072c7195fdb4c7a62a3bb588fc1a57db89f3948917fadbb707f26c5aa3f28f0a092f87fae3895ce7ad12eb4695b286290067779db626e807c12075bf1c5ab2d5068339398ee1a7f134d29ce3e396ed5936d9071bf83294f0f05fea65e8c81b951655ea3267b5af8fed59e63dbea1c01bcbdb3549f0a071ecdcc77b3eefa20d97", "SS2": "18e7e9627765edcb2acbadd46b35358358d562ceafd3c55d622d7e716df70eeb0856a052be8f5c2a264a7f5a6d863ff2c42505fa15d937db7be56751f82e350208200969c255d26703d7bda4eda8450af424574eb28206cc72497ae2c4ff4d77024cd2f2c7d6ff1e4e5e516e374609de83a2868002eb4fb203e3783782756042", "DATE": 16574, "PIN2": 8292, "PIN1": 8292, "SERVER_SECRET": "07747f92e8bba62d59ffedb39daf6e89a38dae6fef5d3fc3acc20814d2dbaf6a2081ba09394efc1aab1e64f465564a90c7ba68fe2d5dcc31164cc9b5ea82e4f12032bcd7ea77c7a0d96cc021252da72fd875cc3e355d3576eec6e9b666723e511c849bbedfc9ef0a1383bd57d3e09a411188f5c04749e564b36153d624a75483", "SEC": "041f05c1ffd2b8fda2da3e3bbd8cc114a7506ad0b486bd3f759c8abb4c8d27bd0414e063e62d1bcc4bb684888e0c16de49a1c0a901d3df60ae4f49afdb9ba99a07", "TP2": "040aea362f8894194f80b77853a75980d2fb6151993c9730d38562051e9f50a93f022366df2a5a4289109fa446c4a0e517a1cec6c8ddd2ca7ca67f73663297ea84", "TP1": "0402b4e83d9788e811a844818e73b50bb104de7e45c9b97037f4c36629e12bfb8616a2c9cf4af98dcfc8b3237c3282d727eb3b67b7b6d1f26a10a5f908593c4e1e", "CS1": "04183891e8c54fed53a0e1abbe7bab6091283774b6a7b4c8ef3bc07a75f7a361160cae9112b2c3a5fb4815344f8ced65138db279e16750df578268b3071f47c898", "CS2": "0401ecba05f14044b5ef74d8f260e7ecbba22d1748879dbd406e2776f4aa559bfd1c98026af1c6b10a027a27398b6284ca624eed2c1d3c0199e7f8322600518f33", "HASH_MPIN_ID_HEX": "ddc3e0babeee2f1739e42a7b5a46680a933fa28166e5604a21f62e7df1bdb4c8", "TIME_PERMIT": "0409b204f5a26e9b30d39d4bb5aeea635a32e9f7a059e3b8863d9681f8a0bec4f10aea0ebd8f959da833210589348aaaf4591159b13e684214a36ab50ba5a0af86", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33395a222c2022757365724944223a20223938643635303533643230363838613131613661333430366266633062633732406365727469766f782e636f6d222c202273616c74223a20223933626465393031373064346231313935336635316237373564306131643231227d", "TOKEN": "04140eedd62bced0687bb47a5821973a22c5442672fdbf59ef77688de41e83c3d315c960bd0336728bca956d25f0f65746bb6a64cc7531d24a7571bcb0bedc595c", "U": "041383ec72c8c14f258c62fa0d9b9c2674476f2c165cbcd30461e610cec7707cfd192ee5659dbf0b56b3e57a98bbe34e80bc035af2761c56ba629e96917bfd2fe5", "SERVER_OUTPUT": 0, "V": "041a7d3b610150f90d3f561cbbc9c303b451c2003d51b9cf8120200c0243f143c70abb3a7ba15fae347fae4a2181c2fb30fb9224262a454fc5f5389be53050a667", "Y": "0bb5f784fc4c655386417b96de58e6afec1b3d2a36749d942faad13031af62f1", "X": "15a2330a02e8e83d9238f466f3f8b6a0633225f55f77b44a863e8c55ac914ea2", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:39Z\", \"userID\": \"98d65053d20688a11a6a3406bfc0bc72@certivox.com\", \"salt\": \"93bde90170d4b11953f51b775d0a1d21\"}", "test_no": 58, "UT": "0413fa623bb2688a881e9b0b16712681832c1e7dceb0b2787707a2c92244a780041b02f88616689c131e49dfabcb28dde56bd7ed1ec6722dc286504e6624fbdb1e", "MS2": "006070233282163b8a7cd1041acddebb6b345e68bccfbdbbd7e221a5cd1f053e", "MS1": "153a075104c9b9f697dff4c8822482151927c47b174d204120714f59556c6f52", "CLIENT_SECRET": "041955e3b3ec63705676848fa862a210365609e68c2050a89433d53d4a1752ded4195f929b4bf72648324106b6dd1ee1559bcd1e99e74fc0b057ca969811b7dab1"}, {"SS1": "078b83be576125203d695d17651bb4f6fa472ba9e6d76be0324658f1c66867ae11aa5b45a91dc48c500d644fa3aca1b291c0e32caeee66892954e4d365ae9cbf06c48059daaad6a6f5a29af05c7a1a10696da5336aa45281dc5de239127db86c1a8030374a08e0692ea3569d76ae9bd55551f9fde25a2624d6fc65765cc11a0d", "SS2": "1e2a4455a323a1415a5df7703ec2fc393b54f7af9fa9afec3ff97395385cdd452112aa6d0a00dd4907e0b6a4e93f9002f15da1b8017d10749058b53034fc79b20591ff3a7dbf4eb7ebe5f737c8dc620b68c39107fb99cced2b4641a3e312328c0712533d929787dbc6b747a4c932fca8e87274bdea0697d4ff0b25c18051d8df", "DATE": 16574, "PIN2": 7866, "PIN1": 7866, "SERVER_SECRET": "1f6f3d82ec506c77a3fb8b0e3132529a693c0bebee28d122fb3d4a6f3e02da4b052bceea91c83784b45af16fdc45036c7e16e54c65ec8ff768bbfc1d117d1d8e1362766f551748914365e1c292e02b64b2a7a6a0d921e4147a7f01a7db9b25cf0386ad997137f9edcb5feb523c324708062edb474398a1de1d437c698be3c5a7", "SEC": "040669b69e2d3eb5b92ab2fec7248d04e1c4f8d79b5184549071d4cf75c48b9f4d22f62c0f8815025b14c77cdc1b21db326a28c51f5e9412b3f64ae61620a85fcc", "TP2": "040b8da1406ebd6b531877433f13c55b0da9ffa5776032644fba22943081408843151ef812582f8daf7fd2f8a92c14853aec2f9177803e68f71859f9437da0b6f9", "TP1": "0410ba29c7eb194a9b10850ea415dd2eed38b375e809c3932a3e6b519b4c9e33101a8f00e2137d4364f8690b564ff78decdbc56b9cf76537cece37255636e664e5", "CS1": "042107688e0410ab1e9d48d1f93d307e4d046cd1fc2189d8b7f657c86176d9634102a747de6eaf789961f944031c3d989f45cd35f77531f51cfad1831eae06c087", "CS2": "04009c1af9a8a78088d47ebbe639c718bb1093f3bf4cbd376b80e144e7b0a35ef82069ed747cbbfa41c9d4402279f22e987c20f61034f55b186205f865370c0db5", "HASH_MPIN_ID_HEX": "2bb20e11053b55e7b40aaef5a4401adf7e1fb8efddae04fd7b9cc567d2db980a", "TIME_PERMIT": "041c590b3578e966a73860b5577225f2152ded2d124cef56bbd90cb3d7e196af9c1718329ca33f606e26b435d85f63604f2c3d60b758d22928f330fb1c6dff87b9", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33395a222c2022757365724944223a20223630613131346366643733616561626137376563653134353964636561336138406365727469766f782e636f6d222c202273616c74223a20223363623735623361656265626632303132613266626638366430386431343162227d", "TOKEN": "041a53bc20dd7a687228193a5b49d8b2afcc3a081df1a17146d1037ba297a4bdd41c6a2865ec897c5a3cef89507f464b6543d97da8676aeed7d940d472c4f83fe8", "U": "041239d25f0d5be7acb61637e9148906d059b0f8b428cf14ca117f2f6de5ecdbd011425ddc2cf9452542648f8c62a44bf8a59b8061fb89a19df25c00d01e7a797e", "SERVER_OUTPUT": 0, "V": "041a5d2c83f00405783ac510d21e2b358e9dfc8334ef5d41971e6cc20a0657a71b2251f81d13502f974845527e316f99a570afa641e4f6adae84fcd2542c104abd", "Y": "11df091677b9108e99b15f88e2c19495fe453b05a324d7dea700c9d9027ad10b", "X": "137402ba59176b1e3ec9e8ba9688c3f5e65fb9ae9c49c5dca8eb518df479f2a7", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:39Z\", \"userID\": \"60a114cfd73aeaba77ece1459dcea3a8@certivox.com\", \"salt\": \"3cb75b3aebebf2012a2fbf86d08d141b\"}", "test_no": 59, "UT": "0413074f27c5d7660617646cd0e481bb6527b0daf62fcec17a57bcfcc6494d5cd80c8397aa541b9e36152440f98fbd03e5b8e162f907af0f0c970e756274be9c0e", "MS2": "18a7df316d8b719d56dd7c8e32dc72e223f2b8bf19faa0d7b7da160e9b3352d6", "MS1": "0bb817e68653c1a98a9f7d6528f1e3b74aebffc8e98f009fe19ca627221578d7", "CLIENT_SECRET": "0403dec038576d6369558520de8be8e5bad528e7875c2f1d1e8011f790f0a2bce614a04fe1f46bde4aa6315456d75107a00a171802ae76757791d8ec12be82c15f"}, {"SS1": "14c01357e752dfff747b85fbc2c6d6778baaeb5c464d0cdb74310ec56e18a7b20c230d67d4a81bbbc731f5e82ead9c9bca9f3e3880ce7096e689684d192fd5b0122de05e73ac9366361338e67fe765dd3b1f93f92473eb47fe423a1729532da41e92a51636d4e908d8d0166bb45807aeb951a1f9bb05a929dcbcdf8263d8a958", "SS2": "0615b4498d7c8a5576a7bf7cc62203e38b3246b3a638fdc1f6c719a8835fa03d1fb37109e568ca7dae9d1aa55ffb07e7ee9ba34cd5303596ca6b4d7735c37c9b0ac8b7da96a74a715a1ab081511b3e84c32c3cea6024e544c8d49c647ffa59550aa1f79e1f4c58c6e7f1792f0d8b1eddb41a5615405302fedd05b5b7746fd7c3", "DATE": 16574, "PIN2": 1862, "PIN1": 1862, "SERVER_SECRET": "23cf5d4372a02f50be2f503cbd0d5a124eb2d8b7f38e1c3db215411cf78fd6491b79fab2ee2b3231118b64b073825097b94c0e8f98b411ae570cf5e9e0a0e1370a3864953e52714778200921495f173990cf22a2b7851748fddcd3d56e56703010010ed24b81b34bc8d4e413d22cbbcfc99bbe7e81be375a2de760b162b8e662", "SEC": "0418e2247b41f09d15339f0fee69d4f787528143473a2a68b7dca5080c0af4dd5613fcc0070b165655764043a6b1ca151f9b9d0b3a0dcec484358ff099c9d9a6b1", "TP2": "040474874bf0e38a890b5348c335c0f22639ffea55d2bd5a79c91f6450143402cc20c9c2f096ed04ad5e4c92ba3dbdea01c38846c73eca5d3120d540747852067a", "TP1": "0422b325096a10fa8f24d4e7128c5343d17e0e71be79dbe7d0c78fbfe46d404dec0bbcf75b2845a23f185506fed870775ada471cd904f5ec04d616dda516ea1b29", "CS1": "041e68bafefb6725d2011b9e07bd91793c9ba0e79040a5d64b1116ce35c44223450f85b67d0878876b4f9538c7b36436dd98b369dc217ce182bef9ef9e65142cbb", "CS2": "040473cdfd2fa3455f520a70d1ccdd1b5dbe84aa669ac64ce9abf58ac0d60bf9200dda8f39e97076dcd4a58a7431851138ddaee68baf7d125a950c413dc8ae7da5", "HASH_MPIN_ID_HEX": "f685b4978542b8c8e191ffe036420d9d500458ea5e7efdd8152c7fea2d9d8ac2", "TIME_PERMIT": "04061c71a0b88350c8d44fef205a9779f36dc7e59d49f0f92b47dcf80e4d594bf70b35d25fe9f6d902b2fccca5a52ce43d5236d9741ff65c2f9573df4eb9193442", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33395a222c2022757365724944223a20223035656666323466646335316162613830383834373836326263386161646162406365727469766f782e636f6d222c202273616c74223a20223063623763616235393537633961623739616563353733346633656361666565227d", "TOKEN": "041f11ddecd0ea572f993ed641ceffe6728292e7e73b4a8544b16d9a1df7e6c0cf0cd194e363a3487dd6d80b64f919c12327cb8eeebc419363b44fb9a7ec4ee1b9", "U": "04079028d23fdba0023edba55291f24e40cb3b126577d658314a7a8104df9093241997a1356a46dc11ba009699305eacb39b33d727590b130ac87c2d91961792f8", "SERVER_OUTPUT": 0, "V": "040e1e4d91d85b225b263039f1cedfbae4d6225da8b596ae868b95248cd3709b300ce1c0fcf261934177a99f67ab1ce4ff54047e8ffc26b91ebfe75d76bf897e41", "Y": "01c3c095b0f399c712f69c64dbb25f0f9aa552da0bb60a384f0088988eb08cae", "X": "18599f25f15ad365146d9a75fdfea275969ed50843b7214049a9d6c5714b74df", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:39Z\", \"userID\": \"05eff24fdc51aba808847862bc8aadab@certivox.com\", \"salt\": \"0cb7cab5957c9ab79aec5734f3ecafee\"}", "test_no": 60, "UT": "040dd09c357c1e0207a65667b9d54d9a1b159e141cbf9e4770e9fe038c8a1f7bd60fac96aa00ab0fa7c0e41fa95c588258283500fcf76938d5ef1f09ecab553668", "MS2": "1906d730f75f674c01f492a55ab62581e0173f75c5f43c1c6540dd98e1111e3f", "MS1": "0a493f3c5461d80542f96e802a59393cbbf052576de5b28c8db5445e61db7231", "CLIENT_SECRET": "04062d9d22a49bb8479aadfc424f5cb9706c589c29faf7e1036d9718cb3acfeffb163638436efad413d90186a374a73bfd20a82a40bbda6037aeaf0ddc3806e0e1"}, {"SS1": "0ea3f9e757be316db2baf323e275022fb932229cc1901e196d93f1b2cef42e5110b3fd334dc224693543989ff62580983b9f4bbd125b873b3fdabed26802fdda09b4ef6f71f13dffc7ed046a407eecbca4c5b878d4498c4482e9283b853323f20c9fc15e195391cdf298b0a3f8edd75d6edb4c0b2b5ac3d9ddd63cf0b2ccdf96", "SS2": "0ac33915724c74c791728a0796d9f675caf07909754c5080189f5a98290bbb7400510f25f536b05ddfe038cddb37887e995490f376935c819bbbfbce8f3dbac422cfe54726c3b7178dec6bb39d7741288a71958d847e9b6c2b9ea918bccdfcc301fe1535dc044c3d6d3e58d3fede1bdb056354bd516ee430044eb8d9ee6ccdab", "DATE": 16574, "PIN2": 6124, "PIN1": 6124, "SERVER_SECRET": "21845f776c534254412df13559a54ea67a9447714581e42c744721534647073d03c450e998c0eb32104c51645dcd25b629fea66297129833a3ac59933ccaad9002aeadd6e6774dc6dbe18355527010f0b6e5f71503e211cb18de89a7c762834606862852aac299e3d9b9d98458b402fe587a3c11c464027db0fe8db651301247", "SEC": "041518e84162d12fedbcc6eb45cf4c2fbd92b0d42283aad8912f44d8f984998b5c106301e135d0e57f92197d3e5070caafd71238f79b515800424bf05180639c3a", "TP2": "040f346ae40a976346ca9a9c42ae2ff26d41e504a185e8a6f8eb30e76f7934efe109cd4977c9c28c062567e761e7e2a576ca48057c71292e3ed82908830cf9f12f", "TP1": "040183f19b04b781d9df48a56986be015c8fb102decfa5a92dc607450462cf466b1c28b670ada759cc51e4bfa2378c3c7e73b96dcb25c79cd91a445ab70c883b11", "CS1": "041aadc432a010bda29a4dc933b862bdbc6fbd2cb9d45aaf01c286d8e1259eb5a7101b77197af04222b1b0b8583d9564996989160bd38f692de1696498ccfc880d", "CS2": "041c89773b02d62afebf042a5997263215b9139dccd39d03bf4e5e12f69ace175e066819b11985b019cb5ee667dc766a3514dcf91535dff53348a91f2538752546", "HASH_MPIN_ID_HEX": "cfa863defc2a1ef0176c0db9489f45f88cd28c04224dcf4fb6f9f5db3ec41548", "TIME_PERMIT": "0414533ebaa0c1fefe3d964016e3114516377385366bbc71ff3ff52b3460dc1ce216941c4de8482881d946070313cd7134f5a547d47612c306b17d58342af26e38", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33395a222c2022757365724944223a20223434623036333838303639623166346466663762316264303035303532383434406365727469766f782e636f6d222c202273616c74223a20223535626537313464613430373530376431313661623933646338386430636161227d", "TOKEN": "0413da749490c816dd433e358b0c583ac6f6ff2e6dcc29efcbfec3cafcbc7555581d531440f8284aa5586e75d6954d01b8c2d5784bc1aa07db8c228eafc0b825db", "U": "04207455992717594748db77bfe7bea8b8dc466d56ebad69ebaa6b449f2d560c0702a20657ff135e1e7a1c180f3092b3821352c242b58fcd5e07f28d218d824552", "SERVER_OUTPUT": 0, "V": "0406902a397b98189553d4be06256f36ea04f18690ca52cfe3e2511660f7fdadec14d074dac887f3bcc9f4314de91b8f9aa17bee4173350a95fa84b96127690551", "Y": "15b070e4a283eaa8aff7af180c7bdc675b88a2268f06b657cdfd3fea3432f199", "X": "140729f3b4d8290e9b052a28a9b8e68bcfa4baa79162e65739a60edb02fc37e6", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:39Z\", \"userID\": \"44b06388069b1f4dff7b1bd005052844@certivox.com\", \"salt\": \"55be714da407507d116ab93dc88d0caa\"}", "test_no": 61, "UT": "04141ca3ebe7eba71574e00499d4456bc2d1f6e06489ffc32c8ff5de35cfac8d5518a641fcdab6418b3d2a13076fe2330542ffdab042ab919c6806e47256c2e671", "MS2": "23108ae9908c84d3ec665b6f141cc6643a943ac06372efe2d60fe007f856aa2c", "MS1": "00ad8ee8975536e11e3ee77ed668af7a9efc1bb9052b58df9d9c698ab2f04ea1", "CLIENT_SECRET": "04143c501423ea9b462ec5a574316ddd105f1c85c33273102ad70c1ab538defd3120235ac8f7800305a2d92f1ef1ee2f0bf76be9cc9c3486d842f505b654c58d79"}, {"SS1": "0272f7c6a684bd1b59c184765bf1607fda1e80d1d63eea62d50100aecc18c10006b468c1c476ab38966126f5e3d9ec9ad7c18590162ad19428983e7d5d154fe5127ae2a98016863c0d11d6bd541f0c61680abc3e8f01a9da7f24a78ca297a0e320d478d1f2dd986d1d1bc5f8cdca5cb948b92756fcfeb96a25adce5c3914e7dc", "SS2": "1ec7ad67b9439b0792ca14d099b6fb500b61ca249a0287cca94238cee2cc78841158f5ca1c659f9a7e975c9e7c8e5fbc831aadba795ac8c996906eda345c18db2116c79be8f2000114e1e0c56305611881f1c591e2f9c4933fb93b67c5847cb6074fd61f006fa513fe96e0c56c987086a079d08333d751fc81cffcc73b26a60c", "DATE": 16574, "PIN2": 5019, "PIN1": 5019, "SERVER_SECRET": "150c1daea00f501a2bd800999ff3ac0ea484e37e98ca7ba01e5f25378a32d4bc199ac07db0dee115b1da11ab25a20af884f6caeba5132929349968df7f9448ed11ecffc3fc40a86f6ac3ff8dc4b1d64352198cf217d17625d1d2cdf8a1cc69710955a3a785b811fa9a7de7a25f6b54c7534def5aeda7757985bd78f0c0cfd045", "SEC": "0405d4c3501b55312b4957fe6ad01715c5a35b3e716a246caa1535b78d1c813c1c1224fb119925124a20538a386d34385d4828bd9a5bc5f405493fd18532562fb6", "TP2": "0420ff1428abd780365ba5366ec85e4e0853ef82f1799c0d9529e679f4b2caaa6110bbcaae974623051e5403a8efe36518abbb0f713bf375a231f78c8ff8546087", "TP1": "040c372eb1fde0469fafc255846f84f0e7e17fd610ac847945d587e2a03c2516920f7a378b51ff6df628bebd0caa3a79d56e9312766c2769047e62e10ee6b9b9fc", "CS1": "04161e8a96b52dc4327f42ef82e4ef05ae3a54d59859abc3c57b209438ca31ba44154bf5551ed72feea1ae9055190bd0de3aa6c1d13197819f61666de9dad0451b", "CS2": "041ba883a3ebe79476bcf877dce6acbeab59371bd012ea7b1df53cc2100ea54ec51422ddfccc5e157093cbb30f63281fd801616cafbda67bd783fd48091fc7d693", "HASH_MPIN_ID_HEX": "de714858ddeb1609b5fabc445214f669f3730118f5ad7771e1b8c5287852907d", "TIME_PERMIT": "04085c93ee7d8cb3a4df466d2ec5d8584a8dbc4b2830ceeb45e449da5654e2fcf20cb32a10592e3174b8d1dd8ba074ac8ac4c42590ddb37a96ea2fcae5f94236a2", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33395a222c2022757365724944223a20223462623937386366363835363332633634366534306236613762326338303737406365727469766f782e636f6d222c202273616c74223a20223235386139326236333361623033336131646638306465643263346531613832227d", "TOKEN": "0401f75d628e9fed80b2d19a7aa7f970984c4950b85a458b7e0886a49113178f10108bd36450aab4e267c3db4d22e3b2633d8e15ca2ed23d2e66712423e8ea0fc9", "U": "041b264efad2f12f3afe94608bcb8c96b81927d89401a5735d4cd15438b829087103ee70d8e316b7cd25d7baf22673239757b74e577efc1405c3e924a6552efca9", "SERVER_OUTPUT": 0, "V": "04200bcafc7fbdcf7141c6aa9ff0f13a4d33c9127d0f8929771785d01b7ce5d6b401da5e377f4128e174b75690ca65be128be676cfd667ad6cc8cee5e76c562fe0", "Y": "0c04e3c82ab3d5159a9c3167009097a82e5bbf9a08c933fc333ae4862e18b012", "X": "0dda4d842be993283453e769f1fc8826e3d06f20b10caf16d6fe9ebc14d9e186", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:39Z\", \"userID\": \"4bb978cf685632c646e40b6a7b2c8077@certivox.com\", \"salt\": \"258a92b633ab033a1df80ded2c4e1a82\"}", "test_no": 62, "UT": "0417974b2b6ff552694eee4e685d310d27c08c7afe8b4c41a9ca195ce3c79e0ce90494e4c68fd214956e978ed1ac91d29cf0355cf834d5073920870443e0148185", "MS2": "14f698cb0982c5b82cf397b37623a47637651808ce1f54eb7fe6a5bbc7af4939", "MS1": "22ef91790d25c64339868e76635befc2b17ab282ba455463c64360adf025a871", "CLIENT_SECRET": "0412b074d78681ba9c2150128a51a943501d06337b1eae1a63b12060670a5ec2a40bbe59e1ed64bf7811f4becb7adea1cef10db7d9088be354d7abdbd56a5b1bc6"}, {"SS1": "1a9b3154fc71e0ebbe46750ed4d5bf28aeb9da6aad03ccf6d678d0ebe6133d3517cfb30aa117dc0effb5249264e384ce2b3c77d61e44d5b201c730f736cc5f990525d07dcb79d68ed6d302df885787a0129bd998c69e6a3f860e88ee5a91bc7912c3f4ed92c794425d252cbffe0272720278ef07bdeee340936f0d82b79257e8", "SS2": "111de1b3b9a0141c0da73bad2e9767f122a5ad365379fac1e1b78946287e890420158812b01b8c0ef71cc4bcedcf4cf229a8123b42248ccd8b8f05fa9fccaa0a12a0757345636a8ba490cb8c92326f5a52be119e35bd2468ebcf15e7710759f11b6e01a21fd7dbca13e9c479c0d1368111deda854e8744a1ca121f23d6b2c5b5", "DATE": 16574, "PIN2": 8298, "PIN1": 8298, "SERVER_SECRET": "22de2450a031c292d69bdaff6d16cc9ad0c4f155b69ffc60da2b47c0e28153b801a0216a5b170dbeea728dad1cc31c9e29847cb8e3c369aa437f42cb8b5d6ab60657d4db2da70eee8e2d013a2e5476e1b8c0e40b5b382a193a4b869792d51a181e72c87baa538df39f1124b2b7885c5fbd35c0f87aa8b6abbfb48c586fcd9ecf", "SEC": "040912eb6b9ed447ea8878f592175a6a2fba95e9222112b74c95cafa330709a892166d4bc45c1b7a82b910288293c742dc1bcd4e4d6e239533d627ef74fee6dff7", "TP2": "040f8d144fd76f9a19ccd82db1fd8e360b6148e088951f850e455c7f7e5dc503cc0e1a02840e83f86fd70fd43684642d781e06ae8f5be8eaac115840c3342c18fc", "TP1": "040b5482bcd2ee216b55158ec5c584d7c6c2fa5d9f5e0224999b0c655d9d1dc17416ce6af0205df57bc19f4bba71d7128f93e5c1cbce2c55c2bac358ed24276bbf", "CS1": "041b3ae2f4b46a899b7aca9eda29151fed22aff8a50301e73f0165f28147535b5c15a832ed5c0a59a93ed06d8db2a479cdebe0ead7174bb1ae825952251b97d93a", "CS2": "040b469509a0aed1ae753e6063c334128161b12fc1e9e71e460196da7a7202f3400954877281397891f3520942c7657e6aaa4eef7fd238b316399ae40e9dabf76f", "HASH_MPIN_ID_HEX": "5bb3ab50a7ad9847daab3a3d865039fac16a96893e887003ce2319c5de3245e1", "TIME_PERMIT": "0409cd1b0420f775bca4c8b16d45e171681ade74fac91e7c6d894d4d1d55edfbc11de7c087c939420cb725041253138a3344e32b6b23951c50ca25e059425c27ef", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a33395a222c2022757365724944223a20223965316332386337353864353863646366623963643561623566376334303335406365727469766f782e636f6d222c202273616c74223a20226161643935633238353539306137666133363135316464393366646263376366227d", "TOKEN": "041b392a8c5c5d789b913598c91996aa3aa71879e5607d8e980811372db7af2ca61f6eb8fcdb1704312c1771968dabb2edd69f0dfa647701c93914781209588afb", "U": "04094d04f4e0c9f0d1c865ef18b9725d6ff33a82bb954be4d8377900204dde792a174e467a8a1820552b7e8010d0899c712888174217985a55bcb3332842a0213b", "SERVER_OUTPUT": 0, "V": "041253d5a5b2753c9bd1e0ab2ab1659fff9397b0c4ffe905f60c1c1b381d48056c1f3f428d51dab9b0d0e966111b2c6842d28a11fdabf17f68992a95d771a87ff6", "Y": "1cc615d41e731ca68d314047a945dc0290e49b6565f819cfba4c18069df4e1e1", "X": "21afc146d072c6071488a4777feaa3cc33b636651d4223168c2d693e1d3e221c", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:39Z\", \"userID\": \"9e1c28c758d58cdcfb9cd5ab5f7c4035@certivox.com\", \"salt\": \"aad95c285590a7fa36151dd93fdbc7cf\"}", "test_no": 63, "UT": "04004455a7534f80edffb58f3bee0985bb49b0c11691ea8df44e3c8d924d51c4771f83128fbd97b4a1e8ca0280bdfb315674f036ff72024f3245449710cde2435b", "MS2": "1b5f7c62b0104aebbc852b6559d543025285c82f3073821d1161a44c7a98edac", "MS1": "1fbc923357c92c1e7dc75080d012498324acf55a1e6ad48a632a91acbb706edb", "CLIENT_SECRET": "0410866b1e5364d7ee68c3f511c0b2f4aff5bb0cdaba3850a3d74d262132b5d91e145912bb6bfd6b4b19120bcb1e0bcbdb53b84075f90b799d604b3ce20a647732"}, {"SS1": "0c8ff041df7d6acf53e94165dc468967b5b1113f9755b728691d5ff5e2a550c1096640178c8947657e286c620007200a160bf32e6d4080846a2bf3de70910f9a1fb859ebfaf5ddc5055ec78c5c95f0a97b7002d8f1c7762b6899dba59d1a6ce11a1416c3da1ea4769e814be08fd193b4d7fccaf4ecebdc13817a9ae1741a91bc", "SS2": "007ba3dc3eaa11302f3361b58544983e980024e27f1bc08474f8def9cc930e9812da860653250bf713713cfacb956488367787e788fa7644107d0fe2c8c12e821bb4f3e100a5eb8bdf986ff3944a23e8660b3e4c6550d4c12077f69b0e60a2960147978ce76956abf1cb8258f29b64c6208ba8aa762d5896022e6fa8855367c3", "DATE": 16574, "PIN2": 4890, "PIN1": 4890, "SERVER_SECRET": "0e0626d874074ec9b2d2d38cc8a5cf468fdc261868365b37f70981d2375df7f008c5cb476e2ab3c9bc934c59ee29a2a24f47ac0883f8b7ba355bd5cf0a5d93f519a31562d6e5fadd60585622bad1d7c6e31419530e56f5e1f91455ff7e9cd6581b5d24f2514f03b476250d1a2dfb5edb4a2dd8ee630894dcb99649ced8300352", "SEC": "0402fa4b0b0b4bfa7b1ddae421976825adcee50cf96e314254f2bbc65611ebe4a91362710aa19dac83f9547cf0a954f18c03e3b745fddb4c1bb1091b0f88b7a6fe", "TP2": "041ba387b873363c94254764366df23d0760bc67e2d2f948c9bbf1400bce99dbe20a96d96066991d8e664f5624e50eb9746fd0dc91a4f26ade1d3bbdcc1a47b960", "TP1": "0417ebb4bb4f99e3c6df2bcd28a3aa63565c976a8ac00e4c11f194122a135557441218c7102455601d085419a43d343aae59c5575396668a5a0466fb6280d60a0a", "CS1": "0411324e749c16d2862d9c7d10dbe7bdd2427d1a68bb8fbabb48d9245a910968131a6bfc51454c7f553c1a3d8b7c0bb27e7f6e41e161af0ed3bea87048e9da76a1", "CS2": "040e7b7163a9211826ea91b17ae2cffb00470200a94ded871fe4174e55faf68dd31568e6abf77b5a8a209877896d39e416ad04b3d98f1cbafdfb045f9919231156", "HASH_MPIN_ID_HEX": "60c35acb41061cd1715b8d49dbde73cd92928ee28126b0c202a6f365c5f33d69", "TIME_PERMIT": "0412480a66542e349e3f791a020102499a7613223710995ece0b99858245411d5c196930806537c5f9bcbd1b18955aa674b592bede0ad390ae3839ff1a76fe14b6", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34305a222c2022757365724944223a20223039303166333237393530353963346665333731383263613161333435613661406365727469766f782e636f6d222c202273616c74223a20226339333734386639303766376530623863363763653034366631646530383131227d", "TOKEN": "041f3e7f3e3251cfc75999bfe24fc00ee1a5020232658c28c5e570edad8bcfdce209bfb562de769c589f5115421b6873b9be234e96664f393b33d3cff5c4d9e6f1", "U": "041efff6b50f2e46f74ff8c07b2327c18307e18de8e435ee4949e97ea352d47ce50cacce9f48fbea938df28f704cd2376f8159f9b12c4075b956794ef3c50bc872", "SERVER_OUTPUT": 0, "V": "042386010acaa3a4a24de7a69d262d570bc08c86a0686e2a8a7401069c49c3f6561bba0f9ffcbbd848cf6b9f653351c6d96d3caa837c0364f050635c251fa2369c", "Y": "0193344a406b0a6480f919b3f69bfd6498ebe8e8ab7de7407dab19b42d4816ba", "X": "18cc7acceec1f5e884048efbab4ef0293b66db33fa44e4c3a126662f321d7f99", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:40Z\", \"userID\": \"0901f32795059c4fe37182ca1a345a6a@certivox.com\", \"salt\": \"c93748f907f7e0b8c67ce046f1de0811\"}", "test_no": 64, "UT": "0420692342eb644b4e9e6fba22c3a7f0c47a43005298403728dc0884c7c8023a051f4f1856e60b59cbcd2393bece40c3bab35250623135abeead9b14c0c7f4ad72", "MS2": "00768c95d4920c3b67235e52a6e5f98800200d162522c248e5b2d57ffcca6663", "MS1": "0d768255a85a6c2b29c7b37e2f92b3b2bb37ec4768d1de52e33354b9618f9c7e", "CLIENT_SECRET": "04170c7a1493371c9af51d48aaeb6b988df750649f45b21fadd62063d78dd3634506cc1362970c1d761820ace7427e7dab10b9a91873562050dd7ff2679afabf42"}, {"SS1": "102c657bd161fa87891f1157ccead78437093b25211a3c021725242fe967e14b032652a956755c955b602d74cd7fd53636fdda3579353b6461bb81cd6850ed01085fbf39429c8e0bd4c1fabd24b0d41f24459fe5fdc5bd976ac9f9adc1f237100ad02829cce0c63f5cc0e78e531501d77e4bbb6c4f5c9281e77ded50a2a52a37", "SS2": "0a679ad8e408e335651430c573f4432725f1a38e2427183cdd292410d5ddb14e06b8cc7f2b6e3a23adc4e1742eddec6f5909c7a722509aecfe2c1dc6494b8f1b06f828120482d9348983816d4dc4bd01cf6d468d28286b66a5059f9eba64bd07164493005ff31ab060547753c87c059676329de3714c0e70ec04b2271c221c3f", "DATE": 16574, "PIN2": 8677, "PIN1": 8677, "SERVER_SECRET": "02408e031d9053841507accbbe0f8cdcf5b477faf584534fec6f173057875cc400a1fb404a9e90562b99ae4be37612a84e3943853931e8195051474e8aae58f801cbe9a05668d95acc8fa03a3adc1fa5e0d92b51bec475de915f6c004d49f88e07ce3fce8ee22dbeb9d295186c6e78c049e4b4610d6d7c1da3cc3fa7b22aa63f", "SEC": "041182512deb0d6f2218ccb59235c7bc02f7b993570f7966d33d4303ca513ab39a073c1340116b1c787cf2b7d584971bcdd37d85a6f09d75190fd1acbd42e18dae", "TP2": "0408f0bb0edbaf1e40e157c1d2897dc68ea4c401f038db8a35eb1133f580eaba7009902d8e6f0d4d6dd18efae87d3ccf2ba73eb3063594ac8cf2f845113b349792", "TP1": "0421f1ad17ae3bdb946fc818e67f18bffbb7afeecddcbe23d1b15255029e23a04006e981321c5871ddf21fdf5eb14ee08abadc20d1747cb0c2891a67fd92817ab8", "CS1": "041692591a78f5f89fbc5f75cebf7ae408ee2b1791522b4c536a47d4c86d1b7b390fa054f5cf8c4698005b7cea1a004cbf61a3849dad90c77fac9f3311d97385fd", "CS2": "040ba7fab0c75d7a79ba86711b978ed7bea2cb381703442b52a019da6623dad18f12f43563c785f09295de6a95fd67d0bc2fb71e5eb7a4b1c965effb72544cd074", "HASH_MPIN_ID_HEX": "2a9b4add7d5afb6c9eda237580f6b2057dc8db232180ad4b4f7ebe7537542b1e", "TIME_PERMIT": "0416e131abbd003e633f4d7eab8598abd58690424f182913f6affa6281d19ac4621978a60265b713556f9d65d7d10afdd58be6ae4e65ba48e3982a0ff523b7e9ec", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34305a222c2022757365724944223a20223130373435663530333536323038623738353664303062356563613131353234406365727469766f782e636f6d222c202273616c74223a20226137393639386438323961323164656439323133383431353530643435623862227d", "TOKEN": "0403db3a8825d222584fe249015c839105ee753c3387eee818d975d250dfdb93051557ba90dea7940426e62c17137db878a2f09ff21ed13863664ba4a0f67150bb", "U": "040367799c14a01148f89ef5710f8e5a533ba9e5d9959d561126498e3c0430630819f8e023e6920fdc1f00aba88051080b18712ba628ceba9e6cd5c59e99d62b51", "SERVER_OUTPUT": 0, "V": "042376accf278f06f71dc8343214201f2c596413f050e4d5dddf6a69ba9e56494b17448cf2b3cfdca05d8e7e9498450a50e0d974af0a724730fdb9580952f305d5", "Y": "21c4af161619d87628e94a2b5162be26c891953ada89165700da4efb6a8086d1", "X": "149b777e05c30dd148e3a575755629f022bcc4eda97cc0947084e22528ea7b26", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:40Z\", \"userID\": \"10745f50356208b7856d00b5eca11524@certivox.com\", \"salt\": \"a79698d829a21ded9213841550d45b8b\"}", "test_no": 65, "UT": "040318869adb00e4874a8cf3c71a69ccc2a4f091eac0ddac65f4d390294d3b5fb81fc16b8d943d423edb6f5b697d5b264e53bf886a8a2fbebc8ead8bc1812db723", "MS2": "09a216e807031f723aaffaa828a2c9ab665beede3032a8fe4073e27aa5a1680c", "MS1": "0571ab35fd954e83537d560c7ee88dfae5bacb0f6b673d8d68177a5fc398c6c3", "CLIENT_SECRET": "040b21d43e466376d84a650166d61eec40472cdf6bdb267e9a0640a104ddcee37216ac10339ff86baa4191c76cc91b61a96ee7089a5b5d638814509daa255a9ef0"}, {"SS1": "23bc6a3fe07df034ea298e4e0564c00bc2c27d3383e7fc8b0acdd3bfdfd3a8b20ac49993622bdce2f5b5aad0bf37e860c9b8ef844650746473741efa3aa40c3817af84f9cd260b6d53ee12378a0d39fe844966e7a16b72921fac7370a573d74813b8716592d46487486a469e1c03c44f3aef9d01703c871b6b9bca580a74c2be", "SS2": "061181e78446897e743ecf1d7e84a9e6f251030a883abb6d9f97f87501f24f5e14479a324f148796d632ecf7e8d0bef693a069c7c48e96479e3057ea40c0d1eb15a448c83f75c192df534404f126ebc6c0759a58cf658df7a2f9372505845936023843134b7386380dd7c1de77c62a31c4c52207bff70d06742c837b74d574d4", "DATE": 16574, "PIN2": 438, "PIN1": 438, "SERVER_SECRET": "14d1619e7122783132b1cbaf9413f863dec6b1793ae625602231beace66b610d0a07e5b3426b84aa56e92d4034b7f045eef66729bf47ddc9ff8328d2909eb5a52093f1222ab3da4db78be4c9c959cc035f8acd808b40106aa4ee81d2a777c5a012e64bf67923371620823d694d7913c4452c477b9fde7c74d13d0084c6992bcc", "SEC": "0413a0aaf96540a29dc76b3691556aedaef07055014629de82df877a9e4a126e8b1772f2f04abd8d1ac5eba2e359204ca387708d097e7d482ca4efc5b58cd1db2f", "TP2": "0401772d1be6007a017d3dcb0095ad516fb11bb5df9244d9569e2baca1a77fbd4d0c8866836035068716668fff1492514841e126f95301ea91efa0d9ab19ec6846", "TP1": "040c38cad42417a7c9163f078676a25dd7f2624b5be9c4a05843129134b33159330fb5b04ec92eb13b4f257b50c03c3e5c488b1f109128104bfab60812d10075ec", "CS1": "04166981997b8ee717ce3f4e7702fc340efad3bdeaff04a83a3fac5f373550c5e81cfca49d1d7295fe542123e0a919ee1671a8447ae9ee0116fb905b673fa48713", "CS2": "04105fd64893c85121600573a7a1dd588c958886bba0d199f0001f4a317a9612581cb11a9dbb55b89585696589ffd9eb745ef4cf77093cbb63a218b5e99f82a982", "HASH_MPIN_ID_HEX": "a9700fd149d65d569efd6c1cbd59036598fc7b638792bee3d321524b8f87d9e7", "TIME_PERMIT": "041fcddc3b6829e05e296d29e146b4d5053ae9e7d0ac77a3554441cec8f1a12f2b0e9948b7110719391ef174e38908e87adf814ebe9b320b6b179467ac87593a74", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34305a222c2022757365724944223a20223930383965633736353862343838363863653932666462643862313534363362406365727469766f782e636f6d222c202273616c74223a20223565396533623932343337336566656361636436646361343837303933356161227d", "TOKEN": "041bb93de440b9c755ba2e35ea46fb7a6403cdff4d390591dd5bcbf31f8a31f4431fbe91b52f038ad19a616831c8da71722f96cf1834b37a6b131ff46162c42425", "U": "04167ee0acd0b94f933e70b88397d8b1692fcc31b830bd9f8e93dac3f664c0a0e30972ef2402183fc71ee2d073b70a6a46209c682be4cfda96ec0b7c3ad680a52b", "SERVER_OUTPUT": 0, "V": "0417e7be54bd19e23a400d667d0cd62f4a048497cf32c009d62aa0699cd190617a18da1598267f93ae27436ec788bc55ed1d8400a49eb2ac77bc0bc4965b4d686e", "Y": "0092dd6621f52f8dc3d0d10acc9a6644757191bcb8dcefe4f2986aa9bb42129b", "X": "2194eed73752a5a5d528b8d3a344899c038a89f36821f387c6eddcf1910b4e38", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:40Z\", \"userID\": \"9089ec7658b48868ce92fdbd8b15463b@certivox.com\", \"salt\": \"5e9e3b924373efecacd6dca4870935aa\"}", "test_no": 66, "UT": "0422097fb8c73a51b6d688745f80060fb668b217ff3a6e9beab113347c65ccf6fe1ca9bd17d45fde96258024f8f80f373f1240957f60328df020bc45846ed0080e", "MS2": "1828cc085089899bf73e84bae712ca4811d44abac4ed6fa84f6b081838c78033", "MS1": "0124571350498a74cd4ac21e5793f25b80ffc6a13e9ef787d9d2f4dfe287e9cd", "CLIENT_SECRET": "042173bff2ffb78abc404cbda3e63d2bdda4e7d5f3043bebff0ac6219688ed72210d05dac39dc0e933a56707fbe76f9b291ddfeadcd665e33dfdec7b42670b52c0"}, {"SS1": "0af7873ec74b70ad8b70c9ee9707d78ba0cb4ea3a5262aa6d45328b19847b7fd18c69806014b441ee563f7c5716413e91d5c6dc9e8163134d846d6c2b9131ddc1680d3f411a853ffd94615f8ea2731380baa2ce0f46f7c74603d0b0f5a5666ce1cc919b403b375c30978119ebd9bba996c49313eb488e403bfc4348dcc979701", "SS2": "09684cea3192969f229d6232fe38349be11efe312714760275c75142b20de5c3146556c590541e110122a74daff6a277712823f5f13d10c9e20cfcda6eb43e00099f3191a7c9b5d4183767c07408f18792d0211f7d6b776461271c98e7fa73070f1b2e0194c8de3b1d5eb4cbfb74880b025014636872d579888a65b1da8f043e", "DATE": 16574, "PIN2": 8966, "PIN1": 8966, "SERVER_SECRET": "1d5538cd079d15ffc719846d546dcc4ea728aa46803de23e01354cba596849920a86725c2059c9f8e2983183ca139e99a4133432b88e0a50cdfe3282a5d2cfac20326dbaebef6164cf4f8e2b5b95c70154dee71b14a307843a46d1cd4fbb476d093e6f3db4c8b24119f893781df531ad0e1dc8310618d9a4da2b7ae63de47342", "SEC": "040411d5530e9af5f9807c50c964c1814108da746b9a6466536e36b84d1c80c949149f2f19391b88b7b1259692e67aa52576f3896e7776995bd23224f891e77809", "TP2": "0410f8f1816f8b93b465ce724c48f3742a1add38acee41271785e64e93952deb411f99871c976067d2c81e0df9b341699e298458aff7e71e1eb6d4b80d3dc827ed", "TP1": "040888ab611d77317034ea1788ef312485fc6d5007a6697a85b8061a1ee4578c620f1b9aec2b0fdf1d006da54727376dfc83e3c5c9285e420d1b395086a56cffaa", "CS1": "04084e45872289aa2567e3fe438ea9a64eadf42c956153331e40ab34dbcb1b0f8b087c8acdacc54e8c58c13edb4791fbb1b06c15974973a29a7677787aa29898fc", "CS2": "0405897a9bdb82bb9a72e474e70290bbc4f230c973ce91a6105df55165e34f43b104d10479463f2b094c404f05222f53cf981debdab81d6b360fe136f3afff2fca", "HASH_MPIN_ID_HEX": "28537c17f22db169ce4e26c51891ad2b5423de2244eebe3e8b349fe790e3b5ed", "TIME_PERMIT": "0414be024db2c7a1c6819a655830ef19f074ed4ff09589908dca2e94c5531f1f101d0797ff400478afbaf5fba98e78024bedf9c5a3a8c8ad8405ae2b18f9acf160", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34305a222c2022757365724944223a20223035633764356630333236353962663664363835326130663430643732613165406365727469766f782e636f6d222c202273616c74223a20223335626366336536646137303864636664323563303230383061383662376633227d", "TOKEN": "041f1a21e87fcd719c0aba93a76f322572a54df2111bf85cf037e307de9ab791fa186090f4210d2c5d4e9bf816be408b37b6747d07c60b7b85ac20beebab734482", "U": "04147718a47badbd0695701d19b2d1c3d91c5cdb97e2b8b27f03c6eff9c1d35afa1f80331f864540eee246a8313833b69a31e1604056fd63ce1331b1215c0660d3", "SERVER_OUTPUT": 0, "V": "040b7470769b6e5699e79450d46b808361f7339de8524359dbe1137c6e370ce66c064e21871e87a9b295ea8afc4c19c7da6c7988208d51e2b05e7080e18292c489", "Y": "03696268f9732a6b118a5227e29ddc9acf6f7f86da8b88c31a61dadd082de4c1", "X": "0adc1d878efb791336d2012b422e3d5a9f047a01efed2adde2bbabdfe12b70df", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:40Z\", \"userID\": \"05c7d5f032659bf6d6852a0f40d72a1e@certivox.com\", \"salt\": \"35bcf3e6da708dcfd25c02080a86b7f3\"}", "test_no": 67, "UT": "042141c6d18f1b1105a44c70828f5deed7be58938177cde1a3d28bae9eff3d5f710c0dcf9a90332aedcb5b7a414ba76962a677d7defb24ad942744450d04d10892", "MS2": "116aa8520b994a5145d1b989bacabb48cca6b5b0169243c2d324cd44a41a2a21", "MS1": "1a62be593b45c2ccf622a820734bb15d59d22ff4467952a8d2ca6e6853baa828", "CLIENT_SECRET": "040ad2dfdf4ca42bdb330d618dce1decada2b85b95ae02bffa65d7a7e7a96c866e1d3c31ac71437f89eb2b1b9284c2326c4b48c5c77c98c51d3584c4fcb42db891"}, {"SS1": "204bd6d3732be604794efbf1f31ec9236912149f6fc20087ad14fa8174910f8820e3ff6e6c91019859ab4aee87a90f03d4e6c2d2c477b2aa9a307f9c0491530822bc06135325422d3d1e5858de216ac7ad5cc588ca97585e675a8618f8255bff01f33eb6a733b8a375f83488413fd2cda487d270f8418712bb284b69091df1fb", "SS2": "23f6e58bab031a9dcc430d22d3aa4bd96c3592078d375b6740a1ba02ab39bfec072232ea8c13fbc07f10349b72cd1f7ab034f55c8d1759a4997196ae55d470621df9165074109dc3464d809f4729211c106ffd82706445cd88140334861a6f4a1895655377315d97367400d58b6e687f44de5d2f345d256e5eddebe931d4a5e8", "DATE": 16574, "PIN2": 5893, "PIN1": 5893, "SERVER_SECRET": "23cc86e35e6f6fdabf7273a30a2ba6a4513c3008a61685746fb2ff1b4f5ecb441848c384398ed43b540317b821ccde36ed8a2ce91b3a6b15aa557b55da03ab2e1575337d86c320f8eec56b386767c77d16623c31afc2324b5161aa3f76d0b2190ddec88bfbbb9ee05d036071ae04422f51f20311071034f28f635f0b6430793b", "SEC": "0422a8d092504720cbf6de7650cd80d3d66e5c90094d27c9cc7cc018c6d8a4fcdf135938eaab5e36d7fe879a1a977a43ee0c26074baea9e50540b9f664fdf4e49f", "TP2": "04115a5af992c88f429a189206a2c18be390ae8a8dbe200a86326ee5018d84f6ca0e1684cc768e83a4eaa87ba875a6037bb90f146ef0648b5e4f7abbd3ff2ebbbb", "TP1": "0407cebb6f0f7d21894cf65a5e39122e8eb7dbeb02fab277a6ed5d2dbe4db291380eec7a985b93800bbf099cbdd39595c369855853a3cab4ab54598b2ab09e955b", "CS1": "040a6070944ee1eb8452d82ff988fae3a4a5111caba81b2539765fc945dd41e28b1659e232bc8601f2ecc597c6a0f5ae6abb791e8b0353fa77248e3cc4616e0a3e", "CS2": "041e6f4259f0648da2332a1adaf0289b2b5aa582cba76c3d074e73856cd4c6cba716623205277d2db9e3f011f7b5ad0a68cb0c79f3679dffa2c26f7f657f10c730", "HASH_MPIN_ID_HEX": "abca69e8daabe88616ad19f224bae387137d3f527bfb4a03d20530a82b5f0261", "TIME_PERMIT": "0416d30c3ad582973c8463b46d800a6995d506d4793e0f79955ed2b551e5fe998a07849fa62cbd14053131e9addeefcd144d091d0f88edab5da229709a5a5576a8", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34305a222c2022757365724944223a20226432623736646365356434623633366536303837646430623961343830333365406365727469766f782e636f6d222c202273616c74223a20223635646365653063643132303139643965303561346335323934336632626164227d", "TOKEN": "041913751ad89e733374387ffb4668fc52f36eab572e7c2468a6873a7d3337c1e11f49a745be5dce7835dba9110f336b9304957777dbb365bd37366c970a82858f", "U": "040768cb1393625afbf9d4a8b2f4a4e7d6c9f6619bf3fa4c842550d51aba199ce51fe7f78c1f08a5a1b1f7010e3112f50b5756281fe1446792bcfb2bc16a879cb9", "SERVER_OUTPUT": 0, "V": "04070b10018dc43a6386d5646779ffc8a1232057fc5e098993594e75aaa7b133851f29673f2f557f3f2483dd32eb201dba7310ad931e90648d0313a5b0b32712c2", "Y": "20230abaf21a3c89f4b6aef7b2124ed8d9f7d6b5f80d5f1ca147e2b9ffa43208", "X": "02a848a5f9b4ba9b8aaf8bcc06592922adf9fc72039c1ebb496251e7b35d74ad", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:40Z\", \"userID\": \"d2b76dce5d4b636e6087dd0b9a48033e@certivox.com\", \"salt\": \"65dcee0cd12019d9e05a4c52943f2bad\"}", "test_no": 68, "UT": "04120a7126fdac5ed69e7b418f816ec3f9d5ceccc363e1015158a896877a7e0b7e1ed8e5b1e75c1a34751f472734ca241c1299e734fc77b23eeae15b643a499eab", "MS2": "05a465d9884764378f03cfd23d3ed5a53990b81a43565e08999381eea318e4c9", "MS1": "076011702a4d318f493c475a0169b75d8e170e85b7c49090b24b261812645e36", "CLIENT_SECRET": "041174e40adfa22638791680345790b575864838f860ce25e1df5cc2503617cf300b72f72f22c98dfeaa74ea9dbc99bdd251d32ecc2c6277374cbd651b1b59b1eb"}, {"SS1": "1d4dde0d5bd7dcfcee29ba50d4b9861619ee2c232e0a4f1642776d669b2bc14b0864608c865bc73af3d6efe08537f9e4626e849db38417c5ef3c7da5f103b1fb0dea106f6cfb1d01eeeef3f5c233336120ebd205e1554389338b8fa0b2d927ad0ba8b734f80b9ed107dc5e856fd46877807a96315329345c4cf1393ec4738eeb", "SS2": "09a206e33907751f06bafa3afb7d497e80c1ad8b4d870d06fea12438ebf2105b18c11138c50de0712510af7493cdb7f52e01e2b63cd39b48817de487d34915642005577f51bce85f4f49dd8431f6284a219f80c0f3246946cf04a332dfb4b2241e55586a4f9f4c6f95f17abe02c931e02a5eda9de3b786aa3dfe68dc9ea41dc3", "DATE": 16574, "PIN2": 6773, "PIN1": 6773, "SERVER_SECRET": "1a2cca121e8d787bcd3f3b541d81265bacd7ff4bee4b40b24414411540413efc175d92c140842ceb664ac14a200cde437c67a5ad9aa5339ebf626b2f3581e75f1855bc5030c509fcf9511adde68a4c874b5c0a4d56041c05331e0b5304a22a0420b70b692318bbed3d049fd7768101715b16ec36c321dfd56698cd2a94e42509", "SEC": "040339ffbbd5cb2cde91265261bc9ccb2a0b80c80e097a0062a93bdef01e7e43dc11de58c9e2c3e5148c43eca64f114141f96aa2324a802433cad677c41883ad09", "TP2": "0408fb394128989e758c57f50d9bde5ec3860906fc16e3e1d35970dd8376e295062185ed97eab576ed3ad4fdf2c82fdbf16f5ccb0ec3cf95b3aa268c1bd12e43a5", "TP1": "0409e25d195e57f2d70eedf24e12e5a39a44bf57dd77c55fc73052243df47ad21201b45bdf5645edf2fb2f8d872e93c5d4ff850fdd45011d81c7c3ede0df70fde7", "CS1": "04098381b1cae0f2e9f4316136fcea99d2eb2cc05b0e3713107434fa65899d1d54158f692ab0c375935dcef1f2d24463df84e6e487fccc47c2c7c1792463fab644", "CS2": "040cb897b943623607122c6269855a50415813267e39fb42bf34244886d2f3bf841b7c1654fd40bb1fd3a568e01cea415f52fcaad53d6107a476b78052fe1c47d2", "HASH_MPIN_ID_HEX": "03503fac344abeaec6884b9346298405573171773af2caa64c7b82aeb4db6c85", "TIME_PERMIT": "040e120d462348e8c36507506cbb1e1ac00ab2d063939b2e59f8a4bf01ea3bfd2a0f8aaca57b1110ba20ed22db84e7dbd3c2672f88ca54e2b7bfce87a797503a3c", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34305a222c2022757365724944223a20223833346337653434623061353939663335636633333430666563653164663836406365727469766f782e636f6d222c202273616c74223a20223236356336353834306564666334333238366230336165343062313339346633227d", "TOKEN": "042289479fd0c3ff1c01888d5b1c583978651836b9fe0c9b3e6e8caf1879e54b9313042656c6e9c750d3d925b45eda697051f214222ec8d0fd44e47f9d920fe483", "U": "040794aee464e8b09439fc5ab90fc784778bc2c03b8a4388843c172e2d3cbfc48502491252ab255cf62551b1ebe74468df369fd75eea179b38ac01006f790488d1", "SERVER_OUTPUT": 0, "V": "04150dde0a9cf4c7f7f5310110116edc3a202909f613731c2771d213d092a217e223ee72d4e4a2e8f309f93465ce0b13b3dee710a76f31d3dbc0c9a5ca1c1f4d7c", "Y": "053250c9ccd29dd61f11101fa457873bc69e8f9437ba824e52662c21841fb0f8", "X": "18ff9690fb82cd245c3646e679e32aead89b6a0565a53cc640ed6091fab34889", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:40Z\", \"userID\": \"834c7e44b0a599f35cf3340fece1df86@certivox.com\", \"salt\": \"265c65840edfc43286b03ae40b1394f3\"}", "test_no": 69, "UT": "041fe272f80651371e00cc23ff66935eed19f38c30cc2a7289878b83834eedde12148739a785b235d266fd6dc0db09c6f843282e50a8fcce06ce9a6056a913acb7", "MS2": "00af7c3a6c89d6fccf52101d7acb1672e397d68027eee47ef6208c33ca9d5a52", "MS1": "115000ac71d885c443e54b4d30b2c05601f9ff4d6c22aa79e4bbdb8a2972b0b7", "CLIENT_SECRET": "0400507f2cb2cb01ac088e02136d05f59ad0c2e9636eaad56f69d62cfb8eb5fa3900e74bc3001ce14bc993a48a3e780d0596888d15db44ce732ad95f8e34a45f62"}, {"SS1": "1872586fcac7f9ec2378179a6b94d87cd7dbc88df7bc5a076c2730b76580b1e20f35122b840f89574714f0a3820564288e0f4d066b1e214004017308da939dff20e7a363f7236802b60938a800ee9373ac9bb2d1fbfc3c875263ab5a35105fb91de53606b94679b3fca3d8bc43bf716e5dc732c89276bad3d5e8042e5f2faecb", "SS2": "0e2554f585242d0d25647ac93d29ea1a1ca6fc51f3c448fba21c8547df97d18f1b0838c0c639c5855489324867d59ba2b40d12490e1194bcb3cf95f41bd78a51052584f55303cf58f608d3d73bd982fbd159a0e064a51f1487b00265339c43e006c9b81c1fee8e61501411f3abcacf090b2b28b8eedcdeb03838d05ee879b094", "DATE": 16574, "PIN2": 2305, "PIN1": 2305, "SERVER_SECRET": "0baa4f6456ae33d64f34c7ac3063b5485e152ba7a326648a565ee5df493975371f5fff7adacc964306cc489aa78c63d94d24106f0629d29eaa466eec88d6012c08d9c5e7e37fb05fb5ea3e4d6f1355365423b5a4923e6aa8ad36d6d9e2ef5ee917dce3706b8443e3946bb25bb519b2374c6be07c8d3f5868ebb0c01cffe29df3", "SEC": "041c1d585a6069dd6c89433ddda4bc4353bd9bba5ef72f365942153943c3b3e2bd19b5859727bc78373bac329c8e81ef0e3c8bf8380e2304a2aba0496eb3e29b2e", "TP2": "0415a57e766e066ff841e4189e5a3eced08d188ca125fea68dd2cf47efb16be9f30f54092cf86a919596b1366eeeb426281dad25ceaf904acfa7d90712e48759f8", "TP1": "04040e0a73354295b5c21286f9d2f6f22f00670973b8dbaed54fcf65419f4fd3021935361735d5dbc2b11b1af5ce39ccde45b5cd8bc536e6e55d86dbd6d1aa6888", "CS1": "041e2d1a629653c43a6509963230b0f368d174bbccd79bb1c526abcb2e9b91d549029c9988224f7ab3df90c9523d02782940114276a1f9c094e70c64f89a96be19", "CS2": "042007df401493d50b777f78413dffde09e2552108d8b19bdc709280742b51ebd70c1a46897be2d51c91923059fcf964ec3be21ec8093102abc4e4d233506397c9", "HASH_MPIN_ID_HEX": "9971a420df8871ca2a468b3859e1a538e4aeedd9881d573683c49dab0e95a25d", "TIME_PERMIT": "040d206d0763c2786049d39ca0740134fd0278f7cb2ff26621a01accdfd072c2ae177e8913a3c21156a7b23af1f16a3f96c7b3447e9611608cb5cfdced8bef4ffb", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34305a222c2022757365724944223a20226538323462356337626162323930383531386366323339633133343833353135406365727469766f782e636f6d222c202273616c74223a20226238653762333434373166353964333335613235326437623333326336656435227d", "TOKEN": "0422ab5ce520c170db26de2fa571204dbd9e9dbbf9ecbb1b486a95d220d0ccd71a1e2d2aedc9bcf3929f9b739c341e8b2a5170e55b6b2e34e16d2594edda785da3", "U": "0404958625da6cd947c94f86fa3abd6c36d9814bafa09078dcf192ad6e93e5d2c500cb6d1455824d7c18cf1c7b52e75595068314e7a8f05c146237bdc9b950e891", "SERVER_OUTPUT": 0, "V": "04051236b5a847c0b4a9e0d04722768739ace2d322e7f00be7db7050afba5295421a21f58fb28ac3d82dcc999ba42cfcb7b8907754aeba91ad46492ed00b4c0fe2", "Y": "034b4329e182005e1da22da62147bab395c08099663652ed8a3076826c82333d", "X": "08796585e75b1e7f71a85dc4001f002039a43523b16e50344aea71b9a258b8ff", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:40Z\", \"userID\": \"e824b5c7bab2908518cf239c13483515@certivox.com\", \"salt\": \"b8e7b34471f59d335a252d7b332c6ed5\"}", "test_no": 70, "UT": "0401c3e7cd5d6a0d008da8a2d00cf2edb0052e447b9b5f700d4a25e4664811f55e1114cf880d033a236ba197c7ebf5184ea067fa73217db13d4a44db8bee88763f", "MS2": "155617c451dbe13e6bf3919a275724cf2162e11cbba2c14306135eb124fbc97f", "MS1": "2036eb5fe70a83d543be694b58ee3c143fadf9b0c1bb792aca99e420c715f66f", "CLIENT_SECRET": "040401eeb3752ef2395e719ced3f37fdc113c6ab6cbd87f73818251e729abc842c175951a1d7dab73a1bd8e4c5d664afb9f10083c6769a1a4c1ad02e03cfd5198b"}, {"SS1": "18bd00e26b5f6340ab7dee43b1bd54cea2958b40e2b9b9c9354be8eba33309a10241dd86a1e29bf561276139a78f57f4f62489529d6f1f4d0c124a9e73ea383a1993080220046ba8e7a082f34b241a065a5bcdc7da1be2d9209f66b75614ed7a04048207631faf3f28a1c90b019c34a38e8b36a2f8ab6e25a738888eb25364bb", "SS2": "1815205f091384a8ed8754474a0101770bcacddb1a36b66b0f8bd65b147af8ed1ef0661350899fd67c1ffa2ce3aecdf3d34ad88839bb6dccce16b6e24a65faa710b6023d7e4d039e23c40756d5dc7c4ee02682b022c207aa623c47e7bf3aecb00dab0e640a49831c3aed7b96b4093f7368a00e4464987ce0ba1adb762b6262df", "DATE": 16574, "PIN2": 9018, "PIN1": 9018, "SERVER_SECRET": "0484433b827728cd62e3b2f5d09675ea3167c5e16321a63c874b4e351a2721b90754827d145e4c4baf01337aca449c8d654d8ec6760c23fb5556cb09c2b9f37e1a498e9d6d344c4054c80bbd74d53522e557c5fc8a3820408b93fbbfe732b8f211bb369902687f87620246d06c85e0b43d9df7003534975ae7b26e6b7fcf038a", "SEC": "04111bcad54f9e08606252d02033da70a0f283086dbf27d6c76db16329f345f2f5045c8426d51dc31dd4055b22bf36bf17501043e8d6e01f9da808e605ec0ce1ba", "TP2": "0410134e79cc83cd6822b7a260d32a99397f1749868da9fa58b466e002d287aac3212ea602a26fda13e5c46b358ca35d8acbbd5fa4c2d8238571f6755d09643180", "TP1": "040e915f629e49a46257c09ca2d3ddb2f543592808cf57f3bcdadf6ae40cc6c2641d43b2fadac099c3af1df94d64b465bcaa54035d6b0f7e804f2752904fa1287f", "CS1": "041c1a64e76f1e0831cd4985112290efdac44d412da8efe94eacc16ae95170649209d8e9c964b56f5a45748ec1bb9946b4615b4fc35d88dc0212dc8e6f756470f7", "CS2": "04193ea07eb088ecf13bca78d9bc75e3f699d967baf126be4a2bf3fa6e8948b56921dbf3402c4aef0dc4e06d38e5bfe8460fe72ec8fa1dfe334f8105635bef27b9", "HASH_MPIN_ID_HEX": "c4d001c31805f7bc108230c75a04a8e1841b90090d4455532ddc544ce4f06f3a", "TIME_PERMIT": "0409c3bc85d16ed32b1e6e8aa82341d8ac8968b568fc2fbf9888d3faf49e4090cb08ddf70e89f2b272c5999e2a9a104b8f4de89d3ed2603e5bc36500541ab56e2a", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34305a222c2022757365724944223a20226138346261373539353962653664653631333733353261373534623263613666406365727469766f782e636f6d222c202273616c74223a20226566343735373038663862626463363865373063356163633166366535666564227d", "TOKEN": "041fdf1b1f65b0f159e08fe8172162ce9a09738491621bb44617e0cf420648c2750637bb9937d0b50dd1b09aa8e1ddebdac4421890c690c508c7f272f5f7039d9a", "U": "04231f6efff8db5bbed31ccb13d637ac8369af53fe8e9f5902cc3651976e6a83541a83d477ed194d903fd33db68b54043a9c9ed7883cd3f866c53cf4a445f42fdb", "SERVER_OUTPUT": 0, "V": "0411537c3b32d37e00568d994a6da190d867fcd18c3cfc1c63156503ff6fb02c4220628527d2ac987afd4fe90c8f62954557939ac83c911d9d5c3fc084858abfb7", "Y": "0e9c010cd2b152a74d89029b9e4c1c10457715f80b59a3498a6073e7a485850d", "X": "0c62d537c6cdfc129368781cd139ff36fb6056b7a557cd6d4309e1043cc89448", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:40Z\", \"userID\": \"a84ba75959be6de6137352a754b2ca6f@certivox.com\", \"salt\": \"ef475708f8bbdc68e70c5acc1f6e5fed\"}", "test_no": 71, "UT": "04169f17d8acec3a8e0638cdfe8f0f21fdf290d12dbb09cfc19d89007e13db4353236561116e198120b170959f2c36749e18f1e75c4ef17c7250b00bbf48e60490", "MS2": "1ab243df094f9b69b36ec8e2321f1e5b54add19c811523550b6985576ba1ad5e", "MS1": "1536bf0c344fb5ba1a81cda37d9a8ec02567cc5ecd87e65fea1cffed552f2af1", "CLIENT_SECRET": "040ee60898445c6c38340523a736a277b359cd0e755db39c6a42043e9cb95c58c421ff06eab75ea4306305f9c0246fe2035b1dd6b808a566e3aecb5860dc9fa880"}, {"SS1": "1d4df7dec5f716858e419c708f309b9c7db06006688df7a6bee2ef85b7cdd65d1443b4a9499fdd578f4a681acfc5424780467053c1a1b80d331b936abca1f9e609ccef7b0eeee98fa953160ce0d1ff594d49e8d626087c258d0e2a0f590840430bb21ec72cb2d1a68141c6c5d266aaa972439257c0adcf2080bd6c5e34f6704a", "SS2": "01b3a63690b40ee666f5f676d0ef05f7225db128409ac25726cc3295c9d21b791c7d1241223e0c1b6d22f869bc5881577adeaa3fcc5cb446bf4f617b21752c451e653072bafa5bcda802a86ab3e36289012fc5b186a135a0e7fab21088ce5162087f5d96d5d2c11fcdb30bc9d8437f4b321e3b97da5bd30bdff7051f042de873", "DATE": 16574, "PIN2": 2775, "PIN1": 2775, "SERVER_SECRET": "026aeff487587a29df38c4c467c08cf035c5b6a5f2c6028b0b175cc63d3cc02817ca0ce0c530f95d8a8c82e6dab8be1d88c46f48909bc17127a6de9882648a2f02ae29fa17d633ef4a107ea924616c1af83268ce1971b58867978e11fa7af319127cfbfa8e6d1ecc63a0655605d0e3f83e61deaf2088985b7930e9c7ab0e908b", "SEC": "040c695aa12da2642c87a0f7b8a86b2be08d6f03495a365aac0f900590deae8f6a025cb747ff5990ec2590e9818758a839b820224800aa1ce221c6903e347ebca3", "TP2": "04111e75f3d614b96ec4cef070d4a4ec4af75c2afae4213be98a6c2a30df4f695e06cd5c2765b91d46bbb8a9f435af82d0f5b13fca97c6d30314128f8980143d8b", "TP1": "0422d6240e601e4454a023867a004e957885ce5f3689506dcf8d69713b85aabd360711bad0bddb5de90cf274e82ea1b676cd66ecfe0c214c9d5ae410da46c8537d", "CS1": "04084dbab55abc58d9236ca702ff6bc7126ebd79f5d1503004d9aa041636989ae91bdb66c06026c0e39e25efaf0de94048cd1bcc42acd7e8fc4c2f98879a902de7", "CS2": "04227d91faa9c9e1d399a1193a27e8932ea5d1a37484ce8da4ec45da0346dd7e9f114274aad88858988d1f177ceb12a2400e473b8c694d397388705ee4014c2add", "HASH_MPIN_ID_HEX": "d23310d07ad63165b1693dc519e8f7fdcb7b72d2b0b7fdcf8102bfa2e6a19e46", "TIME_PERMIT": "041c65aa1d398a706db53f9d00b7b9a470965163cd1eba8ec4a89c16d5318e374011b94da889fed386b5946b4d55d436730ee23e123a5e9d4e7417338ebfc3b230", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34305a222c2022757365724944223a20223062653565323532386533643639333035613963363261313262623466646234406365727469766f782e636f6d222c202273616c74223a20226337313865366138373364346635353137376463663931356639326632353930227d", "TOKEN": "041c964f954538c353ad4e3698a3c084ff4a92c08b2b222973b0d5b039c9c796b6100d58ec7516e76317d037ac729494bf05dfa0138b2180256a1cf1e297f282d7", "U": "041d7039915ad1b7e3dedc5640755a36163d117a8b9b854e2cf010abe64128a5af0b07a0a32252a8882995b99844e524604df243f983819dd0e17e8a64ec596a6f", "SERVER_OUTPUT": 0, "V": "040b062d770f759634478235b7126255439d29fcc0b1b824070349f609ea795b3717e1074431ea03ada1f9d0b0ae78380825310bb0a1334bc99fd28ae148ee75aa", "Y": "10fc4c4e7f2c11baf60100084f51bab9971dff90bc5035363a0e07e0aad89001", "X": "03d8e99f32ac533770d3842b3b1349a0fe4a77d1b0e7507467561b2539acc5db", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:40Z\", \"userID\": \"0be5e2528e3d69305a9c62a12bb4fdb4@certivox.com\", \"salt\": \"c718e6a873d4f55177dcf915f92f2590\"}", "test_no": 72, "UT": "040e5cfc0792e3134daa63a5d7e140d146e29dc501eb65198d7588465de9f65eb00650980f02cae9e2950a5705b1c927fe9998690bd23e2675f9d7e8dec97719f1", "MS2": "06bd1e3d016de0a70f8d8e4197521c0ef461e3450abaaee9a93edc817975d895", "MS1": "04357c426000f69ae867881432ba8ae3d89fb3aa515788acb506a84d0425fc23", "CLIENT_SECRET": "0402c4fb0348f121c2c53c681afb8c2f141ffb736c4cacf8ab0c4d4c57d5e704f40586441bf50f7c85340edc198da5de521660215c9d867a0137b0cc1b9ee222c4"}, {"SS1": "15b36aeff406dd4b038924240461a758cfaa0228aebbbe90e583638b29a28a201e00e707b8188f0a5ae6f5e32efc65a382ec168ddde9daaf7c241a27ee4de6f508450e397f05ff478b37d7dfbce938868fc9968fcccd706ec920dba5193d2a5a074f0a51f534003c23dee02f0fca958bff70f168fc2ab27004fe0aaba61bf542", "SS2": "2268785f18ef8c8d9c2a57efcf95fd8f766da389aeaba115fe8a0b1368bd557b0bbd45974a59db401478e1305d731acbf49ee98a337486418c2d2bec775d678d18288c0cd1e0466339ddf10e8fd6ca7b65ed9a8389d402e15239e07ab604e07810d98c36b6c0011cc7b8a786f9f19276dfd240eb47463921ef0bfca729eeb071", "DATE": 16574, "PIN2": 3156, "PIN1": 3156, "SERVER_SECRET": "0a0d6b8d2a351daccbae438fb3175be07c2437ecec64eea7093199b156217ac713cca2795a649cc78c472d3138bddb4841515e77a81c118be7d62e89404a308f11b2b274a174977f5c7373c7938e118a02f379d8af8cfc00ebd78f5ec8260e7a129ff862c3d426d207ecf061d00220c9e27671ff56bdb7c82bc9bb9a681b846d", "SEC": "040eb7e188a3236e469eaa05fc7199afd5a9e93b8d488463d09319d88c23c9e1772091c0d2c2fddf55fa899c322a58f5eb6098870655b9d93145393b7794647f53", "TP2": "04066cd554b41fb9bc209afb1a6603c16124644c89da138b71d169e07b1a6dc75f11c010e493866f94c67db8fb414a43d9a5650138c4760627f2c24a876fc53ac2", "TP1": "0420ca64450f6f9eb96f75f54f9a6d0958717ed85b8f972293decb7c457c4d05eb06f5f597794265c360d37c09ba6dd438eabd7e220d6f7c544302b7264ac9527b", "CS1": "04192079d5ea361a12d571ea168dd7e47091b041a064c797fee3ed94400e493bf4228e7f3cfef638a805f8355c7a1a82f41f13e208f6d8985a11904094d9597caf", "CS2": "040a80cd423b73dd16c11ba2fa3ae434d833396c50047157ee461bfc3c8c6990b622c0fd616f17357237d7a34e7b80fa64ba2509f0cba7675aba98239d88a53324", "HASH_MPIN_ID_HEX": "d4d3916938174ec409297109174444b8a07f03322f571fe7b927c19b36183c31", "TIME_PERMIT": "04014f5e3ac4a06f3d01bd975acf0e90aabea7472ad66864a80ad7f7c47d2d5fdc06c980b880c18276a4b53e05ffdb5435f71d86c0a5eb3a5ae73175fa21744f10", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34305a222c2022757365724944223a20223032626634383239366565616663366664316235643439643235316461303130406365727469766f782e636f6d222c202273616c74223a20223561393137393134373835626633306663323334613561373362313136333334227d", "TOKEN": "040fbc9966e127cdad8a9661fcaf0abb41662b97e81f6442db7f0a77cfd61e247806f10fbcac3823cb6f5b02d9d0482ffdbf53a6bda32cb76d203fc97e0940e142", "U": "04171ffa5740a36f0352c1554fefd567ba4cfd94aa73ca0ccd24a7f636ffbf99c022f7a763796121d3c16a9dd929f5109bd718737ddf863a707ed54a3fa27295c2", "SERVER_OUTPUT": 0, "V": "0416b534d0a8d5e9a4b295fa11eb3e0ba9d8ca7371a4528f4e625b3c51535abef80566d0acc03b6967914557e26866487433f5284fa1005d4159bdddc1cbb72a07", "Y": "028ad379dc8d0c5c94d0959a3fd5adb40618e300793f1feda872dcea0a9fb11e", "X": "1cc99df8e06eac9ee13c0de7b1fd5f8f6ec15a3c1c2f8ff3b1671c702a502374", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:40Z\", \"userID\": \"02bf48296eeafc6fd1b5d49d251da010@certivox.com\", \"salt\": \"5a917914785bf30fc234a5a73b116334\"}", "test_no": 73, "UT": "04198b0254345ff567dda6eb6ddeb712135d6f6c99a6cbb3aa8febd0e4645b25fa1475bc64eb375b8ba8c20d75338504de08cd2fc64029864fad8ecce488b2f4c0", "MS2": "0a51ad670bc1bc75380d3ed74205899fbb3370fae6b2084aaa54855cc73aa7c2", "MS1": "0c9a54fb4e582a3a9e9264bef1975ec6878589a12691734335203ef2308773f8", "CLIENT_SECRET": "041ee79e8a36ea6dea8ec822764d29f11e54e37ef867b717629a2e2476e04d5e1c02725cf44807a8c47495e3e09a9da531c7f7fe5740219acd45ceb23df0579d7d"}, {"SS1": "101fe19150de2d09b9394fce651a8ae6d00b0c42602754b57ec4454d95981176091f1d4a6ca8ce5510ae5be23cdf88cc994f9ee8d41552f974f2d2bc28ff1f880491aced0b5be9af0e0e435e2ed5fc00f205f16c20f538dc857031dfaa5782a60c05afc82d5d1792302420e706f3ce4a13e2a9749386e3bb7db06bbe48182062", "SS2": "08b348c26e9d84bdff7e74f3ed9f5b301681b8a11a8b0ec4888b0d3b75afbb78208b95f153be9982a4e95f70fe4079fa1fca31dbd8f40e70cea6d18d16a172d10412feb5d10edbb70f00627e9c48f56bdbbcff4c851dbb98af2d13a8b6d8d6be22a4673f8906a2f4ff844eb467f8807e45eb07beb6cf1c2ac94a27e4f0defb06", "DATE": 16574, "PIN2": 6117, "PIN1": 6117, "SERVER_SECRET": "12b8fc4a9feb11bc2967ec336545ec3001c6e028281ca05f51b3324844c549dc0ea154b5663f017abbc402a0659ea8bfae5820cf99e3ba837a42be3e461926f61191c167df0c228caa8ce9ccd9ad7f1dca46da71e2204022c28338eab78c981212792f50fc9c800f65072626eca7219fea6951850c0c9af5ed70e15d82fc10a7", "SEC": "0401cb5f49c716bea6bef9e1c9c71812a7d0985d8a277036ba6918fdd651e3cd9e00079b30165763a76434bd6b925cc8f6a756f2b6aba70dfe175193a971554d6f", "TP2": "0414ea3d87d940f3b258c694e11ba864748b30978fbc8f3f6f11f2a71c79aafce5059e67631b6dd3976c3dd9ae69a8ec6da26c50ca73dead652fe50e29f436903c", "TP1": "04151456e952b14d5cb2edf4fbaf1866a13413a35d5f4ed4410d781ea937e2f65c0463a95182dfc6d0aae6c3b965fc122085352242c607177be7ae05afc66e98fe", "CS1": "0406a0d384fbbdf2e687b8be136a1a30ccd5c6b4cff8c400fbbf967af8a16342f0165b126a5df3e01d2d1ca6bb27b4cf177801c2f936afd81b159d21fd09462e81", "CS2": "041fb77daea54560fbc819da7dd4811475a310fd86f0cfa39ec224b27f8df766660ec093cec82dcfc361bb83838bdac5fc3d83ddfac1329f16137e7a5d8b6b0259", "HASH_MPIN_ID_HEX": "3b10b108f06201ef7730818466dee620fb6a6538c97f8b2005641c9d30df417b", "TIME_PERMIT": "041cad85b361151beb4748219b549b27bc403a37bf832b19d785e973df0dc4809c17fa956a90e5df4830dd069d711124e68c834223bc58ff03484f3599b7d9c5ea", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34305a222c2022757365724944223a20223833626366616362343337396666616537653833623538343362646139336566406365727469766f782e636f6d222c202273616c74223a20223238306633633739336331326338643637373030363038653538616162383034227d", "TOKEN": "0422340582d0b4617bb4c351ace0f8e6a0b204dfdfc21acbb321b94883ba29376207e1f713ceacd7e97c5e4f1bc7b83f4f2262f5d97604af84034a4bee493c86b3", "U": "040441c6351e1db32b7f4076333942618856cc5d3538677e332b3b08243031145211894bf43f2771f8c850e42cadac0c6150c2f036dfe23dadf4b372da5019c7db", "SERVER_OUTPUT": 0, "V": "041478a40b5c4daa70dbe5af8016fece68c401822c183a6395641410edfc7d55c321776602b6d41df15b46a89d080949c302509c6a01edc285d7b87552dcbd2114", "Y": "10664d6392b9dc63fc0bd42f6bd05fa538a69dcb10d5ecfbf4c496cf77728725", "X": "206c5478e3f78ef93737afefdfff1882d6c4a559e0d741755d78acb7bbd79e08", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:40Z\", \"userID\": \"83bcfacb4379ffae7e83b5843bda93ef@certivox.com\", \"salt\": \"280f3c793c12c8d67700608e58aab804\"}", "test_no": 74, "UT": "041a28396fccf8a5a1ca449ca28a43d20fa0f6daea9380a0de8cfb9226f1e081390f92b06fc9dd3275a07b77329d7eaf49b64f7ded137f5aade3e28fc2b2154034", "MS2": "1b9754f8566275ec47c592aa5c9b4bc646b95e0ac03d38572875b5368b600348", "MS1": "0b303e32c2c2fed6029942760b00fd25930a8c64e033ac76b04ab0048a95d5eb", "CLIENT_SECRET": "040d52d1918a1fbbd84c6212e9cb9f4d74dae07aba39ae5b314a268bd9904de2301ba3a76e91c427c2c1ec9607a69acde702699165ac14a3695ec5aa2e21c25b06"}, {"SS1": "226d61047ed6811089cff316caa59abf5f26dadda367b1fb4ffb294b6518b37d1499724ff08013a827c795551f8f86342a99259147689bea835983e41a50955e039dc34be01ef3f03c633d9d274144a9540dcedfe5f165e6b6023bf09d9129231decc21179c0a06f31be354181b0db0a732f8acdc17d3853688159d915da7802", "SS2": "141cde714386e227d8e46d994af363714ca5526a62f1d156847ceae29445c0211d843563aad4e4c4bda37cafd64e4af2d68b44d2b00fcb1754ab45ddb30e1e440620740738f41069b44f277355ee5284c09ea65521008a0694225227469f374517a47081740eace6af5c7faa87431cc812c44f7f3eeee62600f21f77597f6ad8", "DATE": 16574, "PIN2": 6793, "PIN1": 6793, "SERVER_SECRET": "0f938261758a22ce716f50d6c86a75aeccc53bde8ad0dc92b0a5b3f50e6c2e6d1b676015a8a68d464e487509fd9ddce62c0ccf1b0b5192d759e808eca167bd401a9af31ac456f14d99f75afbded3c760724d87669e1760e1c0803f8ac6ae02331ad0cfabda6384cb8b725ac75d21fdd6949f446d0602443cc5e268d01a8664c0", "SEC": "040fe18abb2e4a57ba2a3b4c64429f61ecd33f5892479766a6af98cc3475716f3f059ce95d3b469d009075d8f33a48811a3bee49b8b29a3b02abd71ad576210678", "TP2": "04085c140a46792d8f5c95f58e4727173afb423defbaa52622dd5cb43f8563d3b81fbed110bbac1a35b1d9f63a9c0a1ccf291240683977070aacaf6820aada1c5a", "TP1": "0420cc59016f6d73598d483145b3af2ca808f2f39ead4b7a637a6d96f866afbb99083e1179800392cdf5cbc1bc7b8f985ab306f383693e0d7012b313b6e3e26d83", "CS1": "04140ffec91a3d37a2bfb8567e2d04737162b0956bc6770f918c803eade2a3c4f71597613f4f59be66d7bc8ea7a46e61c7e8746c2aabd0b66f17c8ed9b0f4910f0", "CS2": "04064376cd43e17a15a4017eece02a66bd5c8dcc601224313671cbb1e1e35fb6fd011a0b7d80beb08b737ca3935af5be55a52aeaa0ddc2c2836b88008494d90195", "HASH_MPIN_ID_HEX": "0c4ea4f68d98454e1fb3b0ae7dda4c0e0175051f8714c13773c17e4fa5e4fe9e", "TIME_PERMIT": "0412f34e1578617ecad1372d0472ef3f6f491d8b925b6ec85a0db246d49f2bb54b164599274714a5720e59105e50a1679795176ec8679c8ee61d3fbae492e0bcf5", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34305a222c2022757365724944223a20223632656234343734353963646137376631616235326462383461356562303563406365727469766f782e636f6d222c202273616c74223a20223532336236613230353436393561396237656266323734333239353930306266227d", "TOKEN": "0412861f662d6a65879b1a14a492432e3081d501bda49adc9ec13d71115da564aa0416e2631bb8b8a6d4a710c2b0fe5368353b182e4ce7a9e68c5552eac72548f3", "U": "04098b53424d974b1903dc4f87fc5d5e14aee5bfbc184f6ee337b522667a29243c097a632546463558d4d685072bef84f4975bd93d9d915a9636fdd7cd4c7bf3c2", "SERVER_OUTPUT": 0, "V": "041e513f583fb7a8425b79a33fd911a061c21abb86cd0d44f686e9b2a7ccd567560776af6684f1c3fbf00ca578782ce70bb28f6b7b6445e6ace5bfeeec140622ee", "Y": "215ae7dd3b1b78f63cc6e5e9c5deabf9b1c7c1a5d66b9ab1780b902f152337ca", "X": "0efa21af9746e24ff05c5e3f5dff603ebfa5eabd1e3bb3290476769a384c74ee", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:40Z\", \"userID\": \"62eb447459cda77f1ab52db84a5eb05c@certivox.com\", \"salt\": \"523b6a2054695a9b7ebf2743295900bf\"}", "test_no": 75, "UT": "0403292c6d20f9d11c0ffd27e7b0bfa708e5cbd6abc6f2336914113ad3029a3cb71be6d25ce877781cb03fc4b44f827b709790aedf3b82bd32741a7a48930885de", "MS2": "14220e128fae3e2d8362a5e25f431ff3bfc68324ae2c2c18a6c6bcaa853ec9ed", "MS1": "029649662ff561a2c078bc8135e894f9bf95a0d727abdd7fc745f19acd37238c", "CLIENT_SECRET": "04228627c46aabe9e93607e0880249ee2575fa461c34843074688a1a6d69ee01ab1ca7c18cdcbc6d2a970f6271739da118cddac872b2fbd3e56aa5e640b0041ee3"}, {"SS1": "170147757cf74793b70b59067ecb4df28d2de03239302dcced09e00257cbb3d60a21a3e1f19c4857e988941570627058bad89c8cf63034b99fe1cd18dafbcf3d15f24243d5bacfffbe4ccf388b663cf268fbafc960330ed1057a951c4adb41a800f5c10e491b6ff472606e10a8388c678725c0f43c959a4c2d77781aa92b859e", "SS2": "219a29da9fd66027ee6053a902847df5c1f383945ceacf5aa76c8c29aaa322991c7f3792903f3ac4a81c6d5cfb39e76f52b6ba28c0b12013671659ac8d71cca922e2ef1761781480cd9836b7caf1972392912a2936cb4af380c3b5f23ce00fed0b5d2e7d71f3421b0f0be7e40480a9cb846b86143b81a2ee4299da8f31f8ce8f", "DATE": 16574, "PIN2": 1465, "PIN1": 1465, "SERVER_SECRET": "1ba7ca9fb84c8f034a31aad7c9202fbd484e4f7dc86bd1d995d110bb40a70baa07eae0bf76b3e3fbc00bbeba0ddc7b23b279b36f73b5c986678bf1fc37e797011290c9288f03e1eac03d04a74b527a78291d8f5357000310ddcfffdf7a365b750290e9cf078c7173aa099d07535d0b48620bead80377af0db2af9f95bbe6813f", "SEC": "040a1722b8da0aa51d8e2f36fd4cc18cc6eb2dd6b4f75dd455ee83231236e3006c17404de1036a23202f4860a3c53473ee8fe749531564c73e1c64edfddd5422a2", "TP2": "041b724efb07e12f4ab78f8e6e1622ce9f3c1d769f83916f563f81813e35ed57e904e42206d02700e65a7f05a873c3d968f1a063eb697c0e829c9fb84b7ef9072a", "TP1": "040ed250a1fb50b1a5c030c2fc581d4c58fec72f6db36582aa3abea61110f9170f1030cd2b9c1ecbee754171c1604010861ceb1e9371868f6d792917c0199eb93b", "CS1": "0402c14f58bd22c9b20a71c6f109daf497ad67e9735789a66ed4fba1ad918ea3651d675ff5e242f0e82335ad59728b5ea8564f570c977cfaa382d2ae15ef5b62bc", "CS2": "0421a934e6d999d9a0e7ff67dccc535e1db3ebb487dc338aa84c8125c41dfc22401150a7e21850efa24f599e8ea0ef7053cc41b87a64992408b8d2c81d07dc25bb", "HASH_MPIN_ID_HEX": "fabb66971385c63df357eee34944e3bd6bd60176e7d2d7ceddc380ef26572a5e", "TIME_PERMIT": "04176a10f77fe6659f96976e7e3ed033b03437b1622208bbd35a02a9495f38f1df1141b5462b0e02f18ff0052422641e4b3ab72c71511c2c57f1714320c8f66f7d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34315a222c2022757365724944223a20223638343361353635303733326366386464636565333836383136303934353639406365727469766f782e636f6d222c202273616c74223a20226365386636396565356637376234373836323636383164353033643364613764227d", "TOKEN": "04108aa181d56e471ebff7b01b07869064ee1311a448fe1b8851d9957a252a710a1d781279594b4a0353c4f372721f64d49a309ebdeb285597fc6e05229b39f9b2", "U": "042009cd27d5bf6d8f3ee4aaedd3a4f99aa79d1e6486836be203c96949371f4e4b1fbeadecebd5280d5056437cca302f0e1f838e3930a40f820485a58278cb9e69", "SERVER_OUTPUT": 0, "V": "041bd47c21e5409b1d76058589535cbb8bdd07ea7495f786bacbd2be22031d6dc511b81de4823100a236a8260f2716ed2940cecfcd380e6695118112e7983af3c3", "Y": "08f7cb3bdfd9d8dd325dd462ef63b976e715c4daf5b0bc1085f07735f67dc794", "X": "0dce166774310de7967c6f63842c3930ce6970b85bcf66729f65b7eba0744d7b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:41Z\", \"userID\": \"6843a5650732cf8ddcee386816094569@certivox.com\", \"salt\": \"ce8f69ee5f77b478626681d503d3da7d\"}", "test_no": 76, "UT": "0420cf053c43eca91f035b092483299427f7344a6b09aec6182ce62d2c9a728dda0a52dd563fde9a653e65feec4bfb7ae223ea63d6c9ee14ec0b23f815c66c9946", "MS2": "01437bf7b9b068456f6557a334c8e8c059edbb1c4bb6d6338a8ef5a0a221728f", "MS1": "1dadac6d97f09a39ff01abd53cfbbae7a20d97e42a59da4b582b3a5f4a205bea", "CLIENT_SECRET": "040272e317a96ff8ebc806192b29e83a0e8fb76ec2499959cdd9b40d6b0747d52819c7a900216b2d17c8696366eed9f70ad3007e9509548235b763a1a0f2f185f5"}, {"SS1": "1f097c8c65309174315a2898bd6390c264e1df974e6198d70eb7360befdb963a09dd3d8e7419537f8c17cc2acf768a050209b4a73bf424e7e50648e6be753bf7106727b4d8ee9a03c2215c1be4cb01d8ed46d1b7da81a1d7e7a804a92cb31c300a22c7b8b6f77c459a114a71030186fde697a18dc19dd44f13e29b2992ffe5df", "SS2": "02db319acf3de58b8d2bac54ed54d6d3744b6197b49679c8317266535b188ef91b1ab5fa3713aa4a7f257740c140448dd5987a75888c084cffe8cebd42fac050093b992c6d6e7faa565da5e88f2eb58f04ccb154ca8b810119ffe6798becc6a812bd7ec6117c50550a5b93f2605011a157da1f70e20b644fd8aad22bb0f5614f", "DATE": 16574, "PIN2": 4408, "PIN1": 4408, "SERVER_SECRET": "1a214e15115e5681df373f289c645f6f5f77ea9551dc1cba37812cdccf46494614b81f127925c4bd113241ab7c4fa385b3a318c35e9a6e3b2b5dbfcefcb3fd2d16b23d69f7fb46c931304523c4e9fea0654c57021bb8e17ff67dd4c4b889bc700f1d4a1a1696a40b24026ddcb86202e3b1e97e00365b2a4ed0a33959767c14ae", "SEC": "0415bdfbc98a659324cff337acfb4ed2d7992f7fd13e8cb0af1e74f7a5597dc19821ee05ae0d3b0e5cdfce3ee08e17f6b755f7cee1ce48ecfa2355371bb7960484", "TP2": "04197af006f93311c702bd2bc20c8f18b0fc1de2ea10fe1417447d5db7b65c4ffa12936523b37b93ba0362658525d979bbb751c39e110196dc38a0f1e86a297561", "TP1": "04005d534df3c8672942d081ec5308e2e3a97c54043fa93a9920ef96171d9f210f216c3daf2ff98b7e62935d82c2619c49886d82911cc7d9823d14502bf3298436", "CS1": "040fc9c7c32e80bd775c8de0e2eda495f71c8dfdc94b2e46592b19d4cb7d4e819e154033783350ecb8467b137b5236b2ea27eb35d5a98186f43f36206e0c5cb1a5", "CS2": "0421aa97c899a7fc4429d78819dfa58d7bb676bdcbbc2e5b2ed0eb235356984c7c136d8d310029dc7603aed92385d57daf555104ed1a7265190d8416c02764f275", "HASH_MPIN_ID_HEX": "7a84bc16c8edddeb4142a06f20d349c843adbe0e221447e3c068949f31dfa44d", "TIME_PERMIT": "040ed4adfdead7c38b137a0bba9c0f4085704d89a4d56de71bd25d751f0b002481164f4e2286309e1ac74043f553b0191d359a625eb414b9d5b87c518488097b75", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34315a222c2022757365724944223a20226165316232326666616437356462623062666463333933333330323966643065406365727469766f782e636f6d222c202273616c74223a20223033656430613439373338663139373061323831383666316637343830663538227d", "TOKEN": "0404969c30ea63042213bd18d429a870e7a0aee0cc7ef2acef18c1fdaa4fde95ca08fc985cbbcb8605d3061c72add8ea45013d32f4dda5e13966bf308d34eddfe4", "U": "041f19326ff5fc3b0d8055892d28ed5badf537b6c9d260ef95a05f1b3062c54dc203c4dabd30896a2b80dba4cfeac3e432999d592903164e6c485e9d0740111147", "SERVER_OUTPUT": 0, "V": "0419047d4b8ce9e0ce7cb0dfa716614bc373713e7125e2e7d35d213b50127d47201f21dbfbf3753cdc28a2d03dbaf0b14e6b7f26fd7faa781f50091f13897bb58e", "Y": "17f82fec7aa8cb3e66d6d049307cc385ab8ec1c972138791e7331c3f2cb39d0c", "X": "127b3891459ee824aa89b037084205dec1a6a30db1f684d802008ccf580a12f1", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:41Z\", \"userID\": \"ae1b22ffad75dbb0bfdc39333029fd0e@certivox.com\", \"salt\": \"03ed0a49738f1970a28186f1f7480f58\"}", "test_no": 77, "UT": "04188ca601f22cdf502010bd4f2efbadaf9033768fc209739696576c759113cb33055b315099702d80bfd0395cff59f851e29747ba7d9e4bc2153710ea3d4249da", "MS2": "0030a26ecba9c8d1cbbbb577b6da76490d91af26327d09a5d594e0fe573fd8ce", "MS1": "0a215f6ff9431ff0e5c8830a20d70d121561c9191b4cfff7eb6668a516ec0b46", "CLIENT_SECRET": "041178af3cc3ffd50ee8bab2aa5e115bbed9976ad5819564d8cc4b99bc6bad461d130d74bc10c47faaf0d37b43cc0de11b101ddd1dead75a4e0542ef352f19a29b"}, {"SS1": "15be2f85201b0d20c3d4705e6dce7434f94c191bd45863847e3beda2bf6ffba6140db35451e5858a9fcf290269b7ac51c36593c4f6de9846d5f094356f638ef1097f82573be54a2053580f5a28eedcb325e13f59afdd92033659f21eed18b98300afa7845bdc0083d07c014f075592f4bb7fa7c30f3f0a3e3c8bd03888327ef3", "SS2": "16a3baf019539c0315d7692d97b16a83efd3835b5e82104896a7917bdd883b420beda280541de80f6d6298b6b5d5fd339121f9df11af4648af6f575b93e45bfe03719ba4fe901dc8567998a3c617462af099f158d3a28bda998e8e3011598cdf1384db7309a568ab73b184aa300aa3988433d55e6dcc7ffdf31af64785a64f75", "DATE": 16574, "PIN2": 4622, "PIN1": 4622, "SERVER_SECRET": "0d1a81b236f782a3fdb3b1f324b3d3186ed0f7a421c96b356f32cfd36485b09e1b75c12ee0bd8f12ec2ef586557768624bb943bf22d4a2b46fccf867bbba1ae112afe9c30b2aa97aea3f160e7b5e379edfec817e2c17e3fc8c80c71028babfd520b19aaedac2581868441663f5ebb57b11317b7237a4a6a1d92312614de4a929", "SEC": "0402edde4e6922696941c3e27393bcb9c8d165c08e6b85bfedbd903edbed87f98512272d73ebce620505b95bdace1b162eb99ee72c7654e0a9078d6c66c2b055be", "TP2": "040d2afe33d847f77e1e697ff197761874235f0d5fd0cf4c4de165ccab273f846d0836321f823052178d54b2c64bd900c85f6d6276ed773ac29460cac4a337703b", "TP1": "0418a3958f56731b342d0264ac5244d33d3c047f815980e2bec61dfdb0039d33121371da7873f92a6ed65556bc95c060f5859416c7230050ac22efc25eaa72ec8b", "CS1": "040a23127f1c1ef9eae16e821b7e71cda653afd2cc6843f413f9f2cd0f8f86612f05d5d073cd4ef32825b6fd2fe65f6797f7cfcdd30c460c1193ba1f7529c79ca8", "CS2": "041460db2f38dc661e79bab2ef1fd58c230dfab81324684db126f1c3555fc884440a06103a9166a64bb1c3dbc3ff2c81c0fbce3ae3910dc73f2483e16b917fb55e", "HASH_MPIN_ID_HEX": "9a73eb1190bf311de49be4df153d23afcb1fd1dde9ee84c5e51b2a79ccc0e2b8", "TIME_PERMIT": "0411eb94501fca823362cc36a605d38206deaa3e3df831e29a916831933b8d2ef2164118deeb137a2dfd6ea14461f75105361a6445ae1c80f8ed2ab5e6fdfd248a", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34315a222c2022757365724944223a20223365336639303731373830326534643337343032383136313332656135343732406365727469766f782e636f6d222c202273616c74223a20226636636663383365373338323665323935353162366437373132346231633766227d", "TOKEN": "040024e12a3ca2d13675ed01e7b64864c8838b30509474663d12055b42b7aef61e183285a9c4a9fc143ba8652d0a1f10360fad244b3f2393e891206d7d57e7a23d", "U": "0423e640df49b697d1f39cf6a816df89400fe81ab887859fac1de9299e962c51fb155c6e5e91d00e3d00aeb3be079d2d86c39f3eeeb4a5849a9c881ce52f03dd95", "SERVER_OUTPUT": 0, "V": "0401d092d53393fd0700ffa3f205593a15752f4e252fc5fdcea0b1aec7c665bc5e17451168fece0f131c04453ac007d9639382e2389dc7276073a9f04c75d7e106", "Y": "0ec5b89b2f5b94e757807f0e700dc1e007ee5925a5f7d8e131defa0631a748f5", "X": "236a6dcb9f8d942f2a67af6de5f0733ee00896e7071e96cc918a84de171f14fa", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:41Z\", \"userID\": \"3e3f90717802e4d37402816132ea5472@certivox.com\", \"salt\": \"f6cfc83e73826e29551b6d77124b1c7f\"}", "test_no": 78, "UT": "040c176127de1e4120331994f7fc7b78e440d2932ab6c916009f08d8f2b4cd1c650a8b5b497363e59048b99a81b709fff51dafd93142f3d10be183e66c937e47c5", "MS2": "008794ef8d91ebf8f98169651879be71da42381a8916278a52c9e466bf677b47", "MS1": "076613fcc9ad9ca1370e2b1946691e78a484154ecdc02859b970034ce1ea930f", "CLIENT_SECRET": "0407a3117e24b5688f7e509a33421a2f41fdefb162a6c61a6045f84c0fde5dacd10e8a87a0ade99e5e37d20f8f2c9cb53636d355c5e8fea941f6924f3777b2e3b5"}, {"SS1": "19c2a5bca467207839eae1eb9e6ffa3cf940d90921fdfd3502bb5ef3c79dd9a922fb127feb4a48fab5f0d57d1d2376b240b25eed089612e8a5dc5f7d195b01fb0482ecc4778a029b98ac51c9013837dd42c824622d75f1885af330de3785d1b40a2b017143ba60ef8f037c0db5cf6f1573c14df6332d1645d5540e67f9677557", "SS2": "01ff55a792841bdaf02967e58b0142b597182e7db55b6ff811ca54265d71ac200422a3b86c7756f1a4f8ad8f5db935e40fec3d76a6bb89fadd4e6f390d72bcef075c3f68cebedba4de15af5fab3c80e87450eb9c354ae71378cb028d644768820860b2597344d8d67ce7b120fd12ee47aaa7a42bd45cf7c5ac89c8184f3642c0", "DATE": 16574, "PIN2": 4442, "PIN1": 4442, "SERVER_SECRET": "0e2d7effdffa7a8519a7ba122b20268ae1d2e2d59c87670f7e2a6ab3e19b02f5205821e79aa04cbbfd76675d81586f226c7fbfb60a286cb95969011b6fe66cfc1e8d6aa8da36974640c2e4942fb0002406edac903100e5d7c6e5f9a6e9be661b084d1a09d0036a11d7fc5db2bf15956b9435f1d5f784a67fa6be729c88480d32", "SEC": "040a024e929f300c0115c56379564a50917fadcdc4a96fe4a2ca519ad99c17ac661dc19bd8b019f2f76f8f8fdc79a555c1209150a1d9f43da8837d337af14a72b7", "TP2": "041d08b6e0c24809e94910ef1c532bcaaa867edb996b84798fb986100693a7f98e1d5a4b78bf16d09ed69b3d8eb584aea8302e7853bd97da8bebb48db8ac60ffa1", "TP1": "04083efe81e4b221f09730ac6dab7d98ee0f15c4cf7b8ac56358408b280a17fbb8083e7f7fca8123313ac8f2f47b9ede1ed5d1114515835e064781366c89114bce", "CS1": "041d6579f830557bcf1aaac7b3f3319cc6d8b2796b7faaf5be30b7404005e764042101518f6a0332fce7960153dc1240c53f5b8782a2ba08a36dcc5ba92096f4c7", "CS2": "041581cda3d3517838cf757ae7d24d4a7bd1e700cafa8a251aa30881131762eefb1515b9caa7e73e883777ddbb250fe2154fbbb459bb9a89288de6f7a854d09333", "HASH_MPIN_ID_HEX": "ebc1e6567da08600b5f9967f79b7adf2a27ea215e6c6e3b8442b6ec5f6569a45", "TIME_PERMIT": "041fe99e6e9b84a68bca3a065f92e119363cde9815b189aacde9d1eb66a96cdb840b9f79264af4ac05932aab45f9ff094fff5b4d02eba79ae5f23d97807c3e7d13", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34315a222c2022757365724944223a20226463663237313230616566336566316465313339346630636533313236353239406365727469766f782e636f6d222c202273616c74223a20223132333631616530326133643866616135323464626266646130626335353433227d", "TOKEN": "041775afbbc3f488c3a11c43820a089bb4f71b24606714a46b5691bb95dfebcadf176a0fbfe4360c3ece95de8f509f60ad02540635bc311a9cf61fb29c30c5ee6d", "U": "0418b2fca769dca4c179d3f3181cef7f770ffeef954c7632dc039caea273a00d5808f400331a1135bbcaed8e693ffa6355e93bc4334190a74d74f364ccc4e7326b", "SERVER_OUTPUT": 0, "V": "041f91baff6d2d9deb90cc983ae28989015e6fa92518ea402179acc5c0f81c84f40ee3681f5c0c3e34c66ed2780c9f55fbaf0891608c763e2e64ed56cd09fa5227", "Y": "01ea209b6bf28c3f3c7e3ea5e2d04f2e9d47a84e391f9f8adea5f68ac4058915", "X": "1959238e767013547e7f6c28c088f644c0dc044833ad7ab9ddf1f617d4e16c4c", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:41Z\", \"userID\": \"dcf27120aef3ef1de1394f0ce3126529@certivox.com\", \"salt\": \"12361ae02a3d8faa524dbbfda0bc5543\"}", "test_no": 79, "UT": "040e0a8c284fae697b4403bbea279f358e3fd3d6379dbd8a9e2c4cb5369cd33faa1c6022efedb6a4c5e6498b3b9130cecd857cec1c32e536c32f67e96acf41fcfa", "MS2": "151502b83657373acf353061704428ece44311d78a475a1a34ee9aacc694eaad", "MS1": "0008a48f695c6900afd3dc32ede652596ed68a5391b7598d55b71dd96620bfa2", "CLIENT_SECRET": "041d8d5c26e47b11fb6a9ba2f179b08e62401bf0caa17ac71fe522735c88937a5c041e223bbb4a2b0405fa00bff032128977ab9a8a253e6602a4aec1e1790956c6"}, {"SS1": "0f20e679d60df7c9beaa9342cd64f2a1c101544dd644c555c2bbce605ec763d7080c6ffc1fb62f2776f0216f26516b4b151093c5ba5bef4f766335f9a88f634f2283efc7d2ea850b4bf882e1043498be2552d35db2824d52cd4b080e852495921aca612d340d630745dc6f3db2c6083a71be04c4584e0cd33de7248d7b528538", "SS2": "1eaa84995511c5f2e6e4149cdbd0415c9ad458e6184655c00668fd0ea37d69780ac3ff74b3895c6259ec76448b6ba6ec2bd08775541000261605490ab24a4c2c03d65374c6b4d48474fca390c6cc357fb6715ed3bf9ebf2073b46751857696bf030f2649b2881c29cc46ec740aed46e2616fda83def10d99dc2ee9fd8875dff9", "DATE": 16574, "PIN2": 23, "PIN1": 23, "SERVER_SECRET": "17f61d38a668a73f130a301c14076d9edc30be2be7de42c7207d9cff93db863c049e4a2262912941b80ee1f575653f9912e242faae808a328e3b07d33ce366951bf2bcb45eae3fe09806a22edd7cd774816cd426d7bb3d7be891d971f26d8f9400ab1e7e0518fdd83a0048ea466c4fdbb1ea37e1d59d1b9ddda8eaa6514e5a09", "SEC": "0401a8e5659026e9e627a6609f417462e7ebe832a16938b48b093f2a0887d8977b08ce6207db7abb91749514cc65e95c2badf137870ed39aa52bf0fdcd4ad11d57", "TP2": "041f6f54e2460b31082fbf98f9457adccb420d1de95c1198aa2d72bca0a9fd8b291faf1b06e74790eb48a9aa40f78b844e2fef42a8190ebab61300cbdcf87d72f3", "TP1": "04087d65684b87b7d0d52543b68d1f76dbaa93ebc19bebbef5c2d907918ac65b0020228ec3e8ceacf27c65fde38e721ae51f7c8bd9525052a40e9a03687bc41b2e", "CS1": "040728f6b2831bfdbda67ee6332989d5d2e2d532c16ed242224a5f4de78ac0f9d1127d13ea8209a7d2e1684edffd06d1907a390a4e0e6d59ffec9500ddf478a93a", "CS2": "041c4e3f992aeb5393d173ab44742e2208bd73bb8c52b2f25399c6b81cdf6f01c61c91d34d04b5859683309d1f87ff9594be6ec08258ba72ad0cec084b873fed2a", "HASH_MPIN_ID_HEX": "12f0994434062a6d0d580b07c5467bffea14a7c9d04cfaf8d8dc020b0567ec43", "TIME_PERMIT": "04010e6abacf7aa7604c2fcd0a9f25ad8a3f563a04d7f3ab20cbee338d5bcd7b2b168dadb1320d4dd0afd0b6deb279363b8e4f9547308d89f627ce98bda52bb482", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34315a222c2022757365724944223a20223263613565613437636466653434626337306161643365663436613865656362406365727469766f782e636f6d222c202273616c74223a20223161616434643639633433376435396434363165323463336566653935346466227d", "TOKEN": "0420f55223d3c18ed678355d85cbd3ea1e316834049eacad12bf77e0d9fffa76d2147c217c4cae879fe06ef35a9fa3ede51558258241dc4e223690be7f9cba4198", "U": "0416cba9ceb82d657c28f291786daecc503af4f6d30fcaffcfb2ea91baf8f8150e21886732152de9570e4ab6de46e1cd53150fb26358364743743410bdab77a9c8", "SERVER_OUTPUT": 0, "V": "04014b36352b67823b21f79aff606da0c468b01a5a227a4068f07eb90c8e9f6af3239415d1986b3e45c14807379b5cabafc0c49dbb5cb78ac1166baa4b0d3b31c7", "Y": "20af008250abbb6ef856dfd78fd500cab5bc74ab3873206324dcfcc5f327200e", "X": "0afea84d843970329b05aef35e7fd40bd2382cda360ab3767f758df9703348e8", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:41Z\", \"userID\": \"2ca5ea47cdfe44bc70aad3ef46a8eecb@certivox.com\", \"salt\": \"1aad4d69c437d59d461e24c3efe954df\"}", "test_no": 80, "UT": "040a5eaf81be42cd3e42de79ac02d5c59e9edb439e0c451dbdf9eb609e0f2d17d21be43ee7f58d53268e35b954c5ac52fda57db4238a3c660f22f458466a5f35c0", "MS2": "0ae14be7bd65250f0fbfc0420ac52acd468ac77377555a8c418d9fd531c88fce", "MS1": "21a94d01b34275d87f8db7a44a6b2beffaf3d8b0439e71cf93537a51ee799ea2", "CLIENT_SECRET": "041224c1110ca468cf84e5d988bbea9c5e18175320c2da6dc4fa758dbc1fcc36de12d33edd9ac0712a51f9eb7250f5f3580189674bbb0d32fe037f709d3d67fb7c"}, {"SS1": "1ec443bf2e655d3897b19c9c11cd7f5d2a0d580a5d4e8807991694d52e5385bc1a8178e64bfbb11613473f19513c200078a3f9c6cf34378c328503a3e496495b1c4ed4ab72d55efbe4f358abb4d288afea25a20ba6e966011efcc1f3affba32201aca8005714c06fd702f5113f0ecc0470090ed98c94e285360c5b23af9fe0d3", "SS2": "1d675162cd7d2323a0e4714fcf5fa4020f050fa740e6ef5b6a921f60468112ab1b2b4458f744c891c42e5ad16ee7d4ae6098bbfe8cf265ef7df6e76a6fe932241b9d928f01ecb4b6c8ed98add7ea7c0425ee60da0b8d0bcdeffa3eaf6a37b0671423b2b96874bfe7d9364a62fa698945939382bbd496457033456b18c2623aac", "DATE": 16574, "PIN2": 5993, "PIN1": 5993, "SERVER_SECRET": "19ddeb5eba0705e7ecad54c03164a53e2f15ceb84252670aa210f83c9b40c48b07899647734d647ba87417e6aa78e92c17277a599cc1c4f7d8ab176749376b0507b0cb8d6cafeb23998bb945bfe7d21053d4df1430f0212fccbf00cc576c86551d6793b6131433982c401572ea415851c674b96664f741fe80be08870a92c81c", "SEC": "04023233aef05abfb8ee59ee31d4df3249ba04cdc5dc0a5a7702c7940e5d4693f80a55de057a626cdce0ea31182fde9ef5717e1f9c8b7084ca5d0d26c5156af7c2", "TP2": "040bd0e9ddb8387dc29c529951168a1a3415cec884f03807a0d4e595e9be6c88fc17e9b6be282d31dd5846cfd893ff8e48f6687ca68ffa6e4c509874600e32bc2a", "TP1": "04052f3ec1daaeb316739d4808205d4acbe62ed706e35ee36bea0c2ee49386404e173d4b7ec0bec7126201b5d55601feb260c330ce0b111376552be1d1ab565bbd", "CS1": "041fce97a56a08effde4e537996da7f132201fb2af58382c9c88dcc3925b05701b0b408e1427c389e3eded83f58cbcafddfe307c6d4d22f4cd5555fd167572d7eb", "CS2": "042225f2d1baff5f7b96ea689fa500eb82c6326be697da6004333aa7876077280614b3774e1be7d9406e208451e4b25baf159e5177cfd3617553827aa262a42579", "HASH_MPIN_ID_HEX": "a2716f8a63ec8c00a7a123491b5e9ee6458614b510919275f6822affc6bb934f", "TIME_PERMIT": "0403087fa9efb2bd5227d04fa4d27b47fe83065f1f17a4cbf3ae18f8df6a8e354f224c3f34fa90b900bd9c2f3ab7c110dd8536871fe25adac61456ba9a09ba3051", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34315a222c2022757365724944223a20223837313732326133303962383033393535653765326463336136356237636330406365727469766f782e636f6d222c202273616c74223a20223763623464373566353230333161663735343535623736323364613764323430227d", "TOKEN": "0408500bd2c6a29151895dc7f65aa4bb3ed3f9d5b7dfdd40c997b320efd19879de1a550d5c6aaacecf08f0624181c54279212d062f793c88106f5c7b5f8076980f", "U": "041a1225b80573a038bfa01472d1772e5ec5b3dc5dafe27e12ca6e7b3ab8c456562105d8f031d744de02e3755c375dbe86984f04a0defd79daf804685a3d78e870", "SERVER_OUTPUT": 0, "V": "040dc447be830a707cd147e4a4c1fffb94aaf66b5c0fa431f0833c9ed3a91d99871941973c8224c361d4895d4eda77aa6eb7cebf93ff61fdd015211bbed328a27c", "Y": "043628381882a89a91bf31576b2f0e9dbbf3e166a5b1c5a9787c6072b3fdd805", "X": "174694bc19309b54589e67553d480dff826c632152a35f877cd28b96bf594479", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:41Z\", \"userID\": \"871722a309b803955e7e2dc3a65b7cc0@certivox.com\", \"salt\": \"7cb4d75f52031af75455b7623da7d240\"}", "test_no": 81, "UT": "041ade874f9bf4fc1c1af465593fb1dbaa7551d679115179ec851c39f164a877a00d3aa7e3718376e17891c9a72ced5d9d9d71adfadc54619f10648c35ceabd14d", "MS2": "21714c7e38f6834860e6a6552f1d1bc2f786da8f066b5a6991013db9dc32f24d", "MS1": "1d580184fa53378e80cf23f6396a4f7909aad88e1c76f1da22d02dd73a29015e", "CLIENT_SECRET": "041a9e4616077e46e524b9d3b644bc17c5fcdc697ecb595dffb8d7ab170fee0e8a20d35168cf8c7c2e5c1a1ba5379d75706881908352eda3100a7cf6c3b38c70ac"}, {"SS1": "1f8889730642a1532821bc44612e63b33f8e6d4151d19a9b11b40ceb6d3906d910e220bed635efd725048c03c3a10f83d40793a778014260daebce800c76accf130f6114d61385b6950c204f25e3a18351f55a0e7508c04862866b4d5f570ecf11b911d202b9381bb48e1c26a99f5abf3b19b78585758dce6927628697880eee", "SS2": "0593500e95381eeb22053bd998e7021819b2709669b19c67ef7b41b40d6db8010b5e5609ce3aa1cdaf3a137164fa8b22d8bd9fbe888a6c2599d692733658b5360ffb11b24ced8900e7bc1e93b90e1b78b1bf8ca138f136eb97745d8d30662c6e1fd88b172f6dc36874e505913914fab81f4a9e1f91caa786a78ae1e63edb90b1", "DATE": 16574, "PIN2": 1620, "PIN1": 1620, "SERVER_SECRET": "0769211e3e2cf35834ebe6566e2b4ddb27ffcfc567f70b3c51a1f05d7b128d6318ea7b2237a558d1b68ab69969e0c1255c957ef90fb434383fbe3ba13725839608b89e4956d2fe2b4f8dfc8484401ce4d383829bf8be16cc250bc42997287f7a15d7a6ff3c3e9252f4343b7d1984283559db433a9f9a09bf9c589d29a371b994", "SEC": "0421d9b3f6f51e2ae44c52683449bcc063cbb8494d6f9bcc631bd0c52ad74f935318be45a50c9212607a49bd8f251f65b3e95a3605f2167e0e8fc3a3e2a1189363", "TP2": "0421ebb226b079e1e91d3033ea5763f82a4856345dc7e46bb89f8c09393e227629083a9f1bad0708c0e04740d0a9daa61bdd1652aa1744bfb5aec584219288a5b9", "TP1": "040eba02c81508e0ace62b273f851ca57a8d9edd9885712344c366636d17efd09e1b9617cbebd06eca3fbcb5dee22515b958c409c84c03b9d318ff7d86f3ae08e9", "CS1": "040c60f5f0f6918f718cc464caeb532edfd87dd56da5adfa2edc862b5e287f0878018a9bcdd7d4dec21b35f49c6039efe7efc876b0fb2584af901796d7f70bdae1", "CS2": "04008922872e18d28252b2d92138ce47622011470f433d3381d2662f12097e78e11990360c6fa27c5e8901cdb08723df897acd59a4bfbec82f5b1140700ac6f658", "HASH_MPIN_ID_HEX": "e2567996f829a0a577f84c200f4e42b6c0cb478208a5be7672bb19a528602f3d", "TIME_PERMIT": "04186b1b06c8b39e6388989356872db938b045a71609f46000a9d5066f8983edb808674416a9db61b23d3fae796649436645810eb54e23b99ac2cde7d5edcc7809", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34315a222c2022757365724944223a20226662383837326461653463653561356138396162356364616632323862613863406365727469766f782e636f6d222c202273616c74223a20223761356462613737626336623534363935656566636236653633626437313535227d", "TOKEN": "041b4323d3ce6136ad181446f6cce3709b55044ebd6c20ea2ee516388a9fda0dfe0b623bb55d7a4662d0c70ab4d4e6c88d1c4c295bba102e12b1fdb1a03b9aa9e9", "U": "04027d2b281b0cd19c8bee2e6c8724c432c6ea53f560902e5bd31eb5178d3d3cd316f1ed62049908df28fde6f2392b4d0bbc0f51f698ac73e60a5a5059ee71af09", "SERVER_OUTPUT": 0, "V": "040ec1ae6a765ac28b531bbdcad7321f834858a502680b76d099b75f37baeff5aa13777063eebffe1af0928a6dbe74e083cb2c42706f1bcdb6f6cc8247d8244759", "Y": "0a3ba6023e66c2e89441152c946b4d4f51823148487af0ee54518c254f484c75", "X": "19e29eb3ab4b4495b7217f49f9555e68793ad67048e5adea0b67e9234b10590a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:41Z\", \"userID\": \"fb8872dae4ce5a5a89ab5cdaf228ba8c@certivox.com\", \"salt\": \"7a5dba77bc6b54695eefcb6e63bd7155\"}", "test_no": 82, "UT": "041c40d4c2df35af18b632e8956ffaf48d6caba53025e9cbdaa9c170470665a1940d52b726d45ce908f1e23c522e77d3e890158db3e2a93c2c37dd4fabf7e0aec9", "MS2": "1f2e2d456a617fbe59e610ae72eed4dc91a3aa2f4f0de17cec7da135623a50e1", "MS1": "1871746c9369a4a26c5b92bb1ab48dde537cdf8f6700db208ce0ea6bf58a7c0d", "CLIENT_SECRET": "0412aa71f8fb4fc7731b8a047150de68d3ec0994336e54d3c2e356bf345054ad4c14fc9e164169b9a8235158dc4045ce0d16b83b17882eebc82f076d51426b47bb"}, {"SS1": "0ae60ea8957c6e022b94ad59e5b5d8682897af8dc4e0949758fddbcdb496cf1e1f61f7026293774fb153e577d8b31311de48ec247ad31d850d0d6c35a9d8c6e915cbaf0702c01cb45a8e7803189aa89437eaef558a28a5e1cd286af4544c434004abe93f23f6ec45c667cac0175d9da2767490de66bb8732a52def22833513e3", "SS2": "2113c16c6984d53bae2d48d38f616f9665a8c6f3e486116bcf80b0c55478cc8d162e8b9bd46faa967f7576d394c5260792173fed6b3ff7f3a0456013f6fc72a40b4e72bca6ee0bf27229e3701539e2f295e3de40d0a4a9bc07c8399d37a06e5520a7eb7fd7be10d57d793d0c3b44b5dbcd75f6dfd8eec7475f601183857beef1", "DATE": 16574, "PIN2": 2873, "PIN1": 2873, "SERVER_SECRET": "01f0d6e9bbc05967d35fa9d2d8f94c44ebdbc1eebf7a2fde8bf4e75e10b70c221206f1db48834491695159cf3fcce900e7aa8422a479199b672355cfc089573f1b371b8425af5b2b9d8f724512d519e993669ab9154671411de6ef267292db3407a24c8fd06e4a5f29defc52a38daeefd8c64aca397abebbe5925aec45795616", "SEC": "040cc08ca06db551fe4fd783304ef66f04c0ae6c1a39204e97a04a137b5e48d767166cc0fdb3190d5f171a986049f96b87709d79593708a7a7de3809eb4f22af41", "TP2": "041042aded55aaaa105b86d70915032883401cea09df6af47f553e7bb2926ea5141aabd9244d36becfed1994820936e4e20e149e2a32584cb588e332180c73547a", "TP1": "040566545564e51b5e799f1db8c84cb19bb7839a1e5b8b80fd7d90d1d4ce59770a12371db4956f1febaf639c38ce2c251dfd7ba07a7ad84fc248b999c486226714", "CS1": "0413abf837b3feaef0c4c3eec94c0aa74107a450565d6312be39e4a6a60647e21713799ab399b0ad0166d9f10cf079598c7eb62c68adb905edf089d5a5daaa33fd", "CS2": "042298a7463b69ac7899ebc857b4fc52773690f0d7d8090bebffe74a1a045a617723ebc021103c78834f05c2212f16a1af7ea44b58ea1f2a0e1b2547477a1df643", "HASH_MPIN_ID_HEX": "ecae268d1a238d4e7c4d28577ff82f3adcd74a72c7e837f4f2bf09c3b24b78b4", "TIME_PERMIT": "040cee22e56f6df8f2912e4a632b08b8cfad51874c9b48cf5cf043a931f363e3b623ab71bb297b05efbbe0b9befb8a70531c30489d123babd3c1f46a3f7c14dbe8", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34315a222c2022757365724944223a20226565353634643339353935316331356234353032653630383234313338306432406365727469766f782e636f6d222c202273616c74223a20223064343962663862633234666534393932386432306662323230666265343637227d", "TOKEN": "04110e325a92c50769fa37c0b4616a7de2af7bafa25a7984bca7dab82ddaa9dd9103695e35d6e1fbd5124fe5a078b001bc3f662e82619f0061d8f5de8333fbc98f", "U": "0410fa9ae18e411c164917c24ad0200ddd37c49586a8ad1763c63aecf2e5b5cafd01eb9d768ef6b182646f73ab88b9dd9cbc1a5e86e2f1f1e9b4c9c21a1c7a2197", "SERVER_OUTPUT": 0, "V": "04018c714757fc038eff3029d5e7c448ce1be727385e25c3c376743ea9d10e8916079a41a31ed4ad1fb7a3b42473c511082ead35939495dde4b5254aa2429a8758", "Y": "0bc69a74ad5a805679cf45b9b4e03c14a3c67a2a58583e226cf0aa33ab76d07b", "X": "0ce21ba24d2742a82aec722a80563400a6da096a4e791130500d5fc1f2389d81", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:41Z\", \"userID\": \"ee564d395951c15b4502e608241380d2@certivox.com\", \"salt\": \"0d49bf8bc24fe49928d20fb220fbe467\"}", "test_no": 83, "UT": "0406ac3ca14c0d8578636b6310d65ba6f0c0c6e89d0317e79d6a070ed3bf38f688106aa4e338f24185cc466e6329301024397d1e4f94f1908937183a4549776514", "MS2": "117d1464545659a692e0424db4ac07452304e9652d217de4008af5f2f16b6b1d", "MS1": "23effae4c67e7e3bb0f5cb6c37401710d5d132bc5798b55cb5706fe82c66e9e5", "CLIENT_SECRET": "040bb1db220ba19674509713228dfb6121575323eb1f2405381f176b2db8a04e1b1b4b97533be6da35979beea250305cd8fccf0ed354f9531c4eab31c5e446f324"}, {"SS1": "1e4f89dc6cfabdf987bb08a70d423603c9406c9ce969d855860c1e5a1e9695651518cb5c9f456bb2e00ca0eb3e7847c1dec34ebf1255bfe37fb063ac45dc46fd1a4a75e9aa266b5414f82eb978719560d5e05406e583fea9d43d47f86a7293090b86bfef700a5f1956b2d60b3f3c19a27bd574855ddaf49533338d0db8483fd6", "SS2": "17cef6d6cb81bcdd03fc96405459138d8ab96885f5d64ccd15569dbc7d78d27714a001e42d523bca7726d4b7b0585aaf49978ceb8b41e633aa3d61b9a2bff73c0d1aa651ebf0a61ae349f4ed048a54731f9ccad5adadca6fd58bbfb6be1842701b338731f6412f9637ace1077e610102d54c8793b1ae839be5017d6315d5fd66", "DATE": 16574, "PIN2": 6172, "PIN1": 6172, "SERVER_SECRET": "15e01d324c73be77009da990c757e2b8eb3310205c98ff6021c1d057e27719540f364b5a36bdd72f82be2987fefdd69a6bee518b4a6d82629a91c06340e7003701f8f2b2077c24c6806c5daf3ffa3c31daf8d3afdf4a8ef4c46b507050cf868d1034bc6c3823f071c935bb8872eecbe4d47ad42ba187fe9ee3f959ed379ab9f0", "SEC": "040f0eb2a923182ae1be4dade38fe08bacce551c1b793cdc117b09e1027a8b54b70d0ac21d65f6450de696df519fff23b083fde573db03aa1090d3840850b84929", "TP2": "0416f3cf0bc9546cfc3ecd93676113b7b206489e28fed485bc3e785e86fb82a8931049f07b46b737590f653ab2813ef29bf00d29351177e0f41e4701512e7f824d", "TP1": "041a1dd0e4ec5a04028ce2018e27b84805f00ee5bcbd4c2488dd9b2ba4fc8300dd14ffab2d4db96160b7b483c3e01f8c739ea8415d156fe024d532b8569617e554", "CS1": "040dc3a219a5cf3814015a54d36924459b6dd2f6b9afa35b95b617ced0ae8e3e0c2217322dad4eb08ff28c15db0be8f5a3b722cf60ab62ea383095bb986ab4c503", "CS2": "041f026509e87e05327c9e1a8eab3e9c3545d00f8a6010eca802ed1a82d10f438c145a5d5a4353102a3a35b92d5b99ed56ce3ae951dc0b697936db9768f03ecbfc", "HASH_MPIN_ID_HEX": "d4bc97745c37e7f83c23c2f78a64808b57b1ab067bdf7952c63210fcf5be7f41", "TIME_PERMIT": "0417d653a540efd7765948ea8f4eb3ac31f86628333a78ab8a7e341a3deb86644b181cf8618b5b2ddae3b1f9726d66ccd05098f023724291d4fdb29000d07a3aca", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34315a222c2022757365724944223a20223434643366336431633536356335306434373530613832613732366231663063406365727469766f782e636f6d222c202273616c74223a20223030366464643934336230363330363933313833666438613837656339363036227d", "TOKEN": "041901fc38ce2757e6eeb8d91c430ec38aa256200c72c2c9e5494828f3d76f6d051145e8fc979af80ae7ea0afa7d043a78b9ce793110c909d9f543e98699820b95", "U": "04093b42673fb147dfe682720d58f62104508b6631fdc8ad5dddbb9f1afda1e1312165a599dfe47aa5b36edc9a2edabb38864a0e742cc5e5d8dd1ae1b0ce69cb23", "SERVER_OUTPUT": 0, "V": "0419379339a4b26628285f88414e048df2c774ab8799d949d4d376abd809f0b3f707d052197a526caa5d7344257d5975bb3df048ab2111bbb5c60d2055b391f43e", "Y": "0129d676a1477ec0f98e3b9bbcce240506727c8b7694a0c95b4308bd8fe93fef", "X": "23fba0aa380d00d071320aed405d52ec3045fa6c988f55e279d872cda4abeba2", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:41Z\", \"userID\": \"44d3f3d1c565c50d4750a82a726b1f0c@certivox.com\", \"salt\": \"006ddd943b0630693183fd8a87ec9606\"}", "test_no": 84, "UT": "041b4bf15b5d9b23507dbee9df71f80b4476158a5d32cd82d49e72e3d7716c36621e1d66ed4c7e3ac7c6aa65f577a74dfc2a5215f7dcd783eb588c14a93cd61419", "MS2": "1ade1ada200b19432c5f488fb03ab69f874a32dc412961fad1f85684bf841eda", "MS1": "1474a9cdc4c10aa698b3133e95ac43ef29e1b46de68dac3bd59d1b3d2faab6cf", "CLIENT_SECRET": "040afa64681dc3d3eff11b2978bd4590332493bd8c816891fd236548254ce1868219100a9543d1d437d6af5912cac2cf01ac5abab457ec7dabe2922dc5b5f99fae"}, {"SS1": "05c6bb794f9f731153ce1ada5b8505ac042b9fad0e6e3ba1c78095b6c3b4662414911195650e7997636da29da0649e067edb6f37ed5fcf639ef14c95542ac416120a202993001d31d9ea667e34105a1a2900bb891644c6a2e9a1c0400ef53dc609b532b6614c02904e13fc8440357b917a8c1248d71631376794a92b3936ed0d", "SS2": "159e6aa7734a9e499a2c98e3778305ba4ec17c2e3c1a5216dd66611e1bcc52390041bffeca47173533b7d1f75097d183801e172d8f26219c7b61272ee9041b031799a12092b063f233170eb379a306ae3a46c2aa16c77fd014483a608988e42223ded036957e0f099535413ec29310a77510d614b9f1ac22ae399ebfcf3773ca", "DATE": 16574, "PIN2": 1972, "PIN1": 1972, "SERVER_SECRET": "1d3989cebe5db62efcae25430f8a019c6e6cd00392e43d3d03924f78815b77a60503b342a652f1c49237898327f2d39cbb1e22df789dbeb7d6a527c9499ead6e21a22ca045033bf0788aeeb6d6ae073944f6f70ee579aa2f61abac391349cafa08d84a7bd2c49c9bc3c2ce9ccd9d5b7adb655aef81c672abfa1160f5462e7022", "SEC": "041a776ac2bf109a5f5ca008b3f3e8d21b5d91e5e6c61fc915d683c2ab1067648d0377b8ba8c74ddd67aaabd0d67915071020e2d952306f41f19b642f4381e5514", "TP2": "041c9c1e8d0e7152ea1cc16fb2718c0b0af1f43bd154a075df0c2844efce3a7b9e08003c8bb86978c4918f3435579c5ded7ae333bc30d0ba37e70d18244a46d8f0", "TP1": "041daf5f24a75262414ee997e3db4e83a197fc31ca26ef9f364f2c50bacd8666c02295717d495fe1b4d57eb94d033e56c2e60e8c54548eaf629b4801a7e30da0ee", "CS1": "0417b587c94aa0a69a202d141bc01d4ffb32923352eddf950d4ce3822de64b4e52014fb2b1dff48f26e9f04e2d51365a4b80dad7c1eabf6ccc9e0c5f5c32c3e69a", "CS2": "0406a4c03c0de367aa797448c763c30ae698728f15225f0cd398ec8c657a96bfe422c4e8e047a631c7f183c601f7302b52dbd92a8e0ca0ccbe4260d7361947cfe3", "HASH_MPIN_ID_HEX": "9d5ce41b69a2b84e71c4701cdf5c1689beb937467701fa7d27f88ea1952ef31b", "TIME_PERMIT": "04141e694615735e97002dbbe42caf1d0f91feddad6cd4afa35fb1c73887fe25b4045b55ec71ae1a2fc2881149ceddf66daacf24691ac0506807d26752ea86b3d3", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34315a222c2022757365724944223a20226264386130663566333762366463373238626639386261323734666330363936406365727469766f782e636f6d222c202273616c74223a20226238353036303138303233633431376530663264396139313634366433313637227d", "TOKEN": "041165d27adc025aed2919dcb16aef10caba6a37bab8b7e113719608dcbf67a9d208d0c9daa9b4742ca44cffe6953e651815505500958274990bc645c2c1b5bd93", "U": "04063a80a56cb6e513e767513e4a6e10488b67ed46ff79a28157872fbbd59868b60bfed79ed7b9fa57e19f3be82b113ad9069474b680cd45b03c8c2f351794bf47", "SERVER_OUTPUT": 0, "V": "04194cfcb472f416784229735eaae023859431f53f29c3e7d866b021c8f663bc7c212fead382db9c8be2b46329149835e1fd7da24e9ac64d6a29a470813aad0386", "Y": "192fa62c72bd062b8258f655c436bbdb266d2b7111a7eba423af90e5c7203236", "X": "042b670088180ada9d931c812d7600de3bc7cf70d5c8b331a63f6ea23c863443", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:41Z\", \"userID\": \"bd8a0f5f37b6dc728bf98ba274fc0696@certivox.com\", \"salt\": \"b8506018023c417e0f2d9a91646d3167\"}", "test_no": 85, "UT": "040a3d158546903660bb6d681a1ba53579e327fe8ea7ef3bfa7c7f66d07839714a2255b8d63ee0ccf2cf108de258a3a1b976065d4144ab153eedda411b5f22dc08", "MS2": "01177a6a9081a37b1f52fe3e9d3713b146d5e8004729f5d43b6fdc54dbf65710", "MS1": "173ed4de9dfd1c7aa98bbe58645268b90283ed45d5b230e00a2783868927c950", "CLIENT_SECRET": "040234fa7b79e79381f7fb9d4d947e29ba33325b698aeaf5b9c079723d391343bf1ad2664cd4f4fee118de578fdc00833208c9ed1f466904eedd260ae837c967c1"}, {"SS1": "15a9b0476f93ed540b612b854fca4aa1e79342cb593fdd24160ff3583ce59339033b2c8561614bfb65067aff726df6ccaae10e6abbf86b4d4b15f42bd40d81e901b0b5891ecf6746f14038a2e23d10212d52adcea79985f1c05fdb650c1cf8f818c1b29934d2112f1cc9d1cd01e709f61100c3e58d7a33ef771aa8c228137483", "SS2": "12ae9569f0a37c524d181286ab3e7b43011a40b1966283afa78f403b1c2470a30d3010341616e6b9d4bfc75a859205d06c9991154f04de58d727b17b4702eece196b5506388ed2c43023a1223eb3ed7248c40f250c140a27a9bb96920e57ef8913c9d39eca93031f789f2fe967f5305e123f2f4e1efd4e2dd97576e3a4053b6b", "DATE": 16574, "PIN2": 1255, "PIN1": 1255, "SERVER_SECRET": "1028b09e98d7d337dd4e243d600ac6cc955a7953b6494445a78350929ec186cb0e3a61c953d355c799797ccf0bb725e80fdddbb607860b9a84729d7c0399f9dd0014ced30499f276d50eed8cfedde8799dbd4ac9b88d9001bae985cca955f0d11945006f16bd302a9e0d6891a060d927960462ec72b6a0d0179e96154e6c5830", "SEC": "0411bbfdcf8e67a19e20a5d4037d787c188cc1ee798ab6e4adffbf0c9700dad38a1beea0d545875fb4a960adc0d17a25ffe1ea7ffceb36d38203b57d296a784ee0", "TP2": "0420abde83176adfeec81527b1de6630523ce12d7a7ba74866543824f4f7ba51a90fcd1822c47f218bd3f717c76051bb466df1370bdf3f5263ccedb9ed63be1c4b", "TP1": "040bf781e92095fbf95b661e0d90bfb5a4111f61b87e1578d75eaf2dbbec35e40904fdd7a997454764e4c1a257bb08a32dd548b29558f15ef358a731b58f82b5a5", "CS1": "0415877f2d9f055c144812ab55222021c9de65adee3ad0d354f2d14eb6aeaf606d1af4c86276c2432e1426e3e80a6d6f4785a2d2139bea814d376a891eb1e1f251", "CS2": "041fd6aeabf565155e3f979f18babb4a341b07373e763438ffb3e94aa759f41a8c06a799664db9b7ab23753f8cbe1166bcef184d5c7298b807c79796571f6c2789", "HASH_MPIN_ID_HEX": "277a3479f6872328251823c9cd3126d9e0a43bfb919b39cb13bbc420103edc5f", "TIME_PERMIT": "040aa9827300d89f8973956d4489f431f3e36827c2dbd799fa2afded0473e50e8102eaa8216e3a4d5e6e5a9f4baa6eda8407a711d110e97419e18f2d103eb5a0e9", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34315a222c2022757365724944223a20226330326530643761356166396134653435666562616562633334663533663762406365727469766f782e636f6d222c202273616c74223a20226238356130323163616532643838663639623738653539376433663564376534227d", "TOKEN": "0413b151c03422cfa21e278e50a054e65be4f82dc05e9419155382108c889b3fdf0dced28589a129fc37fa08687368bc012f715d0ee4284cbc143f0295d1c354fc", "U": "0405df68a89d66f5fe99f7ed7d501394b478a5ee4db947380f1520614ba8e19758210c5ddf855aba41155277184a0cff69ebfa755ac4a7ea8b4786138645807a24", "SERVER_OUTPUT": 0, "V": "04003ab02ec0b139f361cf7e7e442fc808edc86266fac6c5dbf6c5acc267e6055d1e54e654704303d68d0c462e803cb6966a5f9fc592c593a3a853fc9d618cc504", "Y": "03203bbd9274284566f25b283456fd9bd5e085a68d732069327cbb669f572663", "X": "21637ba1006a794e75a104903cf3175c3358cb42d0c6dc0c203fc6876db71238", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:41Z\", \"userID\": \"c02e0d7a5af9a4e45febaebc34f53f7b@certivox.com\", \"salt\": \"b85a021cae2d88f69b78e597d3f5d7e4\"}", "test_no": 86, "UT": "04184ed877b5ef099d7564772b5b87d316d514619a90c3429531b24e1c000d96721afda95c4b53b809da05ff879b3c7d338ceb4cf8e160550caaef1f8c4f7a89c0", "MS2": "170086639278dc5dc9e9dda5d32bee64be6f38ab60bef05db946f2565231418b", "MS1": "2178223941d4fef253cb594128732388ba97b3ef97ee2e1e2df3c017be568799", "CLIENT_SECRET": "04156627d733796135c0320e567b8952b655d5c9fa5d2b8ac0dc8aa6d4a3536f04229b53e379871e153039c908c04d8c430d34b6bf0d42a2d1f316d8ce570575e4"}, {"SS1": "0a71fb759976aa6c4355fe59a5aa39dacc02d3104f5b5ce8ddbc3dd7d9b0a06a09a4f64edfdf89ff198a32e1e46b71de710b0d55624b754f9473ef252c863e7f1a78cf6773b28a1abbf7ca224588ce8d68b4cc607d8cb0a60d37296ece5ad02907b04b9a4765815daa704e2631bdc616f27ea36a37df1f1ec10008e3b9fb0e66", "SS2": "0ffb0f8f3e278c7ec9cea1f58c7c3276beeb6191dc72732c3c29fc92800c46a5224f51b57b39c9263c6699859b60cfb077d12b37ff81e904a03bce82f93e83ea15e134e5405498042f41057e84ecb586e9fd4cc1941518d147fdc82afb9141751604838e1655db56ad35ca00e3b37565405f6a3a42c9cd9a0849cdec75afdb14", "DATE": 16574, "PIN2": 5086, "PIN1": 5086, "SERVER_SECRET": "0c3e76da0c65d7b6d483d05b82403f46a398e904c73d493e973fa488dc7e02ef1ea6e4e486c025a5a15805ed05956575380834a6db29a581c0f756a02b8bc1041a0828e65320e271ec35604accdac0c1be3063d90c6b0fee0ec6960786fa64191275217108748fa185147404ee9baa6422d938f19daadf137e5616e84cf5ee5a", "SEC": "041ec9eaec0bcea4f3c97b2638c22deade34bd14966367a8e3ed625b8a38da30ed0098c25cb78e38dd29af8378408513cd2f1cdadf36ec5ac37176b711a5e2f52f", "TP2": "04211074f946a006176c18d9b36d9987a3dd1da84075b0c157714a1bc016c835eb15415b6ec13203b7abe744d288691023b1a459bf505218579c0821f599e28355", "TP1": "04140d41a42e00a33d84c26780cfeec3aeb273750294f3c2611bf042aec240dde80fe3691a2e3a6dd76dff0ada1f00a1d96b9f914dcb42bd7bd93e460d30db0ee3", "CS1": "040b40bfae29e5ac0d26470b3fb3d0343000d00e0d75af7294a2f7aa5aebac01851eeb33afde72b94b2ba8fd19ac2dd493f03a53634b10804798864ee3f1c06679", "CS2": "041d0fd3f1e0ebfbc35bb72b8952b1f4a82907947617e59cb6466738df77cea479074bf29294e18de2c6eda495acc915e72151836f1c3d625a703b92cd9d9465d8", "HASH_MPIN_ID_HEX": "adb6304121e26d8009fdbabcdf72dca795a1e24bc50bc14391f34bf974d519e1", "TIME_PERMIT": "0407e604b36849eed7914077876ec75ade4ebdf55e4986c056ba2ff62c707ecaec1fb59c09ad9cc9c03ab27996cd52fe9f4b3325ae9fc481ebce67abef7f09f924", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34325a222c2022757365724944223a20223563336566306335366533363039393734393732646636353439346534343835406365727469766f782e636f6d222c202273616c74223a20226134643537323739326136616639646263363262306436313333636134613237227d", "TOKEN": "040a92c221a99ed3cd1967ea02bb7a262496fadeaceb8d2c9705e2ad0ebc351f1a16eca8fe948693fb23b3feee2b351edefe45a6d6e2500be265bda83a6e3f4b7b", "U": "04180c6fe97b85423b847c697217d7e525d40641a95ba8b93849be5dc1d8332364042dbfcf586a1adbae23e56a4f28503a0fb3ca55e9b730787eb6c96f6848129b", "SERVER_OUTPUT": 0, "V": "0406cbdb31cda5f3f37f37872c4841459646dd622eca5765ab3c10a9645e64a8b80ab8f9526529b5b63e7d9cae5cd8ba9b5826c64efe3ef6baa2a28f4cececbf9f", "Y": "21866651d2ae554c1d8b9d07bb690e642471ed1f6772dd0f951c8068e1054e75", "X": "070115bd969f551e1cdf816898921ba69d6291b91a25fda8cfe0c14c3ba1fa16", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:42Z\", \"userID\": \"5c3ef0c56e3609974972df65494e4485@certivox.com\", \"salt\": \"a4d572792a6af9dbc62b0d6133ca4a27\"}", "test_no": 87, "UT": "0419a6a2965727105ab6c9adc621eb34e1f7c95383647ca044eb4b6b924383c2a108b9275dd265bfde9be11ecdedc110355016a744daaa944f233db54fd040396f", "MS2": "182f0304b00d57eb9ef202f1edc9148b8fda7d5baf34f40a8cbe8f41d95aec1a", "MS1": "061fd8a46a5285f2e2c1c22e0f4a1bbc72adc2daba67b2e3615fb8e33fe2599e", "CLIENT_SECRET": "041d98fbe0e18da73078f44434e9eb0038979af2220b13e75b40ee9cd34f8b0a711924c89543e31fd945f0613254e65796ef98404d05e6b6907377a3fe14f44555"}, {"SS1": "00dfd083edc1f1b217760585b9c0ea522343f8bee6c662c5f1371c3e9654c61b15322f664f9181fab1b381e76c43e5bc742c309266eaf0916e0f8d0c703f705c1d4f50246d1c6f41e29d7311fa406284ac4a3030f7a057e3c6168ab0384d73d513faf162294e3b161b593d514ecacb7ff79fc8a859d730c2e45e049c12f4145d", "SS2": "0c5e5b08242a82941a3b368315e728b3cc3e35fd93d267d75788bb814ca964900f47cab9273648cd86742acf570490ffbae445740d8b54cbfe43c9ca9d49792623e3dde36620f8efe21b8932b5041f5d8f2db768fd68031de8da700055d683bb068213f6e10c77cb566d20c6e36cdabca1097ffe1149aededfac491c432a2e65", "DATE": 16574, "PIN2": 4270, "PIN1": 4270, "SERVER_SECRET": "1879ddecbfa9f51f3940628a6e185340ce25211114e0695a1ff106ee368cea2212ea40ebfdddecdef8509de4ee1c548c8fce555c3fd15b07a3ca43020d9c733820eaa9ba1a2010714041f4f25a5fa2d1daf0cf973fef47d33285036c8ccea3a707e79312fa1692cd359f94ca6ec79841f952b883864fe7d0d1374eb942a56f48", "SEC": "04131d7ebbb9c6cf101b34daf12a0beb526778895acd4855861fe0f76522bb6786193ed045ab1957a42c5e4b24f9f9f934f24c05c8ef3d8b8f9c4191e0818d9722", "TP2": "041b2f1fe394695b1ef702c9831cd0e8d4cc30ae6d40cb785bd6eb576ad9c563eb1f0cd5543072d4c6fc9c712f82cd1d365617c8e772afb30af5d71e9931313236", "TP1": "0418da3a187de45d1bdd5211bab5512f20fafe0866e1915bbf81e0d6c6bd3f96e823ce0b4be07ed143eee083eea43a96c18b1dd224c5186ac03e10d9fc69dfb916", "CS1": "040c5282717c005f556fe8b0a66b4b981fa1b1f6bbed98c049c11756d49483ad84077072553701bad201b6b4681831e21f042e36a86d3098b2efbeadfd89a1e36b", "CS2": "04135183c0dc0ddc5f09c691557974de26ae6ac8b8a9523db6947dc78f6d288c66045bb1398d15a0d74967e5562dfbbf8cfd3b7f6ede518d42a97f29e41bcb19b0", "HASH_MPIN_ID_HEX": "c2880d829778be5cc9d2321f5018688e0c49f0dddb7854974523c5dcc5ba924d", "TIME_PERMIT": "0406cb6faad9eea91f58d15b5ca41a9118a99f98d2b38a7a8f68e98f93592d8c78085a5f435747d44646285b284803e950fca1df0a38b677bdbdde59cdcbdbc96e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34325a222c2022757365724944223a20223231343733623965653964386438666663303738346438396265316632666265406365727469766f782e636f6d222c202273616c74223a20226261343463613236633931336465326663636235353563333437633735656262227d", "TOKEN": "0409808bcd383f45049d881ca2f782193bcdbe150db88686e849ad068d14a6545d1b8800621241f0dcbe052d67c88b1c5ca0169428a63832a4e35842f193d4e470", "U": "0403acb48b996edb4ca18af50f54ff6d04221421ac73250c116f1b136fefe08bc404b98cbb1776fd505a5afcf094189d64329a262079376da1f5131715f46f9be7", "SERVER_OUTPUT": 0, "V": "041186c5fd817d27b4a57dfc9ff21aa3218ab478de8c6550d25c3c203e26ede8030d15a53a5ea38caf5ca356b667c21d9a50a85c07e11fbd39490009051dd0ec4b", "Y": "1cffd28bbf9a36e6502bfb23205e29ae0d9ca2e20a3362ab83e024277c0679a7", "X": "0bffd28119caa01e14b31b99bed485ea8bfda9f5322a9e59c5b732a3916d72ca", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:42Z\", \"userID\": \"21473b9ee9d8d8ffc0784d89be1f2fbe@certivox.com\", \"salt\": \"ba44ca26c913de2fccb555c347c75ebb\"}", "test_no": 88, "UT": "0403535b12cd2377ad948368c94bc5a9d10f18090fef844e1d9dc1e37638c5e2e911a4800fb9eea09b7de4e24a2aa262c1dce634480b0e46aa865347e59da883e9", "MS2": "116e605eaf66011d6865fc5cf466e97d479f8f85bcfc94759045db21d0d42098", "MS1": "00602db989419a861ab8246c5fca5680069c3c5eca104a4e670f60408db96f92", "CLIENT_SECRET": "041fe61b61001edaf2983a1637943d3973b14733b2224296afc5cbe07736af8adf1954e17fdc37169c52ca0cbaa2d936bf3b3b7d560de360ce2bb3ee036e21b144"}, {"SS1": "07a8d11d6fd68f93afc4164e9a31dd947b2cf941dcff2e833196d6524ffcfc7003824deb51fe3fef929758b01adea11db41a1c85a1516c62dd2163e7188e357116c16ea4e8b92ed5672b646cb2dff5a2f7872a9fb0d4af402f02bba666b6241c0d2fe5d5bcf1477e7fd4eed93de9ccaede0a2f00e34dc75f3aa4f4630e4884b5", "SS2": "1ccedf72c90f147ec602ce8c3e3bc8901970c7597f60a54f8a659071b06c26f71c9c47648da517ab0113fb475bf74598c015a23f64d31e471d60efa3af69792613e519a6257e46610c6b7c040af5757e9b0dee8e18334d9f6d5ffcfeb4ebf1140e2fc936b6f182b3d7db9de1c2402f033e04c77bec1989ba4f86f62fbd60e22f", "DATE": 16574, "PIN2": 8933, "PIN1": 8933, "SERVER_SECRET": "02a5e08c1df941747db736856395e9a40bb50fd61d82259f2cbb30551d6d20a817716ac337fe05707a471f2dae136a7a3c0c74f7bdd395a604e4f5cb6beed7af1fbf43f1d5d5739e8e21acfd44f3fecaedcd678e1d27c6d9b279007d807256651a768256817e859c208941ca536ba26b6a8d3a3c1683f1cf114b78caf865d885", "SEC": "040086bd71db49bb5e837f7a176e9ffdbdd33af21b683e9ad1c0ef0833ef60d31d1b5993316eec35e3e0bd5add787cb5fed77708c39fb711778708bf5f8bd7c869", "TP2": "040c2e09381a428571296625211788c467aecb6e4cafbd9eb28a1075a855bfbec51988df72354e6419c669fe217c02b00f11330e023d1c0e3692795201717e0290", "TP1": "0414f99a4a43af4cd5a1dbdb55851dc5e5ff50f55dbb90a48c951d604507f0eae71d283089d39329316ff148e8398a27269ae743fef57abb123f3a5a02086e3f86", "CS1": "041f91d33d7ca42a760084f0f7387b11620dab04d2653cf369eb3606f30ef4879501500997af6df45a94b32bea9a26ea39863696f1a869422db0659d3e0749b35e", "CS2": "041f15b2783f4884fe0497d6196a24f26147a7a32f7f4da8462451f121e5d78ae5219aae126f0278f3dfdbff516e6d44cd08a4adc1e25344d0b529ef2bb3d8c772", "HASH_MPIN_ID_HEX": "632b5388750fc04da59984fca361fae6473375c65efeac1bfa6f05ae92c982a2", "TIME_PERMIT": "041dff9695558ae9954f87e087185f8f14778a123a5322cb739c72a5dfc81ae0b6210fb7339ca4a72be58142513c713fad797d423f011d93e458426b29afd8317b", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34325a222c2022757365724944223a20226334383161373131633533303963643834303265393732333633386465356137406365727469766f782e636f6d222c202273616c74223a20226663633730396666613439656361383934666133343735643962326363623936227d", "TOKEN": "04151e2198fd58a3301533a94ce9a80de13309baa2c1e4ecb001e07fbf8ba8b3fd226374c9a4f98aa8746c5a374e22edd406558d41bba12ba83b1b7510cf05cfa4", "U": "041fe8f22c2ee20cf628186e7a160401de905c1d1c8010966e6a4b45a39c01f11a1fd8ae9c4e3233de9ff27b1fd1d6022ea71afafee5670cb8853b114359b2ee94", "SERVER_OUTPUT": 0, "V": "0403edbec87f67bd87364dfb1ea312ec704c3007fb60cb72dc5bb885a4d01464ba214ac10c870674d2a47ce912fd2feeab8be6a5be7bec21069518874e6273f206", "Y": "065d4fc4bc6f8255ab7959f2e7997271529aa2de2e295c8166cd7f0174aaea7a", "X": "122fbe30638bb58b8f6878b9323ff28661cd56258052d4f22452f5a3d3d6b7e4", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:42Z\", \"userID\": \"c481a711c5309cd8402e9723638de5a7@certivox.com\", \"salt\": \"fcc709ffa49eca894fa3475d9b2ccb96\"}", "test_no": 89, "UT": "04026fe1e10ae217f7f124316e0eb259a6545c34ca7c6438fe44ec4a0d574c77bd0cf81d9a78fceffa45538d94257d6c44fbd4d0b743ea8449cb403aa380a72450", "MS2": "2287f55eb2f99851cba65d12cf662bfe323d5dba9ba74188778f512c7c7acc5e", "MS1": "04650dc8332f75995c6ddb39cf6ab18323e967e49113c7248c043ae0847adf00", "CLIENT_SECRET": "040a08e1280f5094575c54b302012f9352f6e21610dd40aa1dc4e89e208141c497134aafd45e77984d0d1f6fb5b224dbf3466b7dee3b302fc48d2c2032af22b2c7"}, {"SS1": "2347312598b1e70f541a0c493b9d4bae1d294cdd525431cea41513293c0c62e801b14503a68f540f0556893ebe2e3b3ea6f6e46e76d5d7a4b8c52c348e2e9aca05548625be8d86970ad3f6e47f2a1d827defb5b23180d837a18a9290e38defe603aa252d3b441f446a94b6ceb7105d19c05175e8a7d83a1a38f09a036f347f0c", "SS2": "087658a6fd05123d6aafb64cf7adce797b37b70a4b6d88d0f857b9e847961174114da196bb4aad64f21ecbb163ae4184484a54b1bc68d2b2a0e0dd49ff6114cd11e0f299ffc0802b2f2c597c26874eac28145137eed9b7ac3ff3497221ec037c1a15304b88e2b7be55f7eeffb93c815431b424cd5f98af268ada87d2231a7f3c", "DATE": 16574, "PIN2": 8897, "PIN1": 8897, "SERVER_SECRET": "1c1ff4d520ddb6892dae7e7c0ee342383fba38da517eaf73b55a4e542efa133c1a55a110d35decaafd1c4f95c42416797870f40d9e73215934c4a8148cefa17104dd3d5041f9e65f3b47cba3f7ec07b3a3731f04e9b8afece88524f452ec35b4196974b9a98e6467a92233bbcc5e4441f312697d0a4c6287ec80bd022be42834", "SEC": "041e68e9b917a99f733ea980289251a20aef0cf8812bb97b9f2b9e9263a05f195313b29e606dbd8f48fc8daf16e4f40c930b172146e70e72da3a7f7ef40c028765", "TP2": "0413b069f1eeffe9442de46fa5bde4a3465884df8e24b444790587af97db4485cc13ff469bd010a95953fce7d47c4b92b5527e3c09389c84d253543916f3f36067", "TP1": "04232d64ede2229468c1e96a5359d270255faf965830a451b93255702e21adaacd10fc77851fa408b053f9c1dae0c62eae6508d57e1b93adebb3892dc71f25d382", "CS1": "0401064e8bc6627f2bc6612f00c9c7a0dee794681be35bfdb5e5052adcd58e989914e9d3ac430a073d912ade6b83fec767577116cd8c9b26575d1fc667b2d9bec9", "CS2": "041911666887de724e03d0f100a1d5dacc6be9d412da9e84acf027b50e0efd26ff1009bbf02201940fecfadb850c9b4c0bfb696d5bd4891d3c41519095ee5cc278", "HASH_MPIN_ID_HEX": "dfc46edfd82e264554762fa2afe97a682fae9610df4c0ecbf7a02abcfa363190", "TIME_PERMIT": "041bc380b0d8e33ba5da7b925e6cf899c98c1ce68256bfabdd1d3a34ae03aa702212f91bb48a2622c6d2a4b9de23073273af1a59ed4386c7ecab972e0fd1731ba9", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34325a222c2022757365724944223a20226365333434343533373530353432306238386239626438653036613733363735406365727469766f782e636f6d222c202273616c74223a20223064626265386233613237333965653736346534633436386138336533626239227d", "TOKEN": "0404fa97240e58b891cc662a47e0d8abc9e0d42f1a0ed8fe93bd821a8a6bf81c0808b61edbe74cf891715dfb95af0b301965c884c7bd001822490b13d335c1627e", "U": "0420fcc5094063d1ef1260301766b1fc04d73c1a7b46eeda68dc51f69ad70704201b8a2ba2b26d80ed334dd6ec7028edb1aba05cd9cfeb76584de1df2df4983aad", "SERVER_OUTPUT": 0, "V": "041036d0eb774c9cfcbf0a07edd51bff9f85733afbbc41013b5740cf0627382a2007cb3e3d833c16e86bd029f937e36ed52a61d79c3a76f6929910accd237b98e5", "Y": "1b280775648122e96d6528f36149cb6b99cbd4e90e1c74cd747d278cec1e2fec", "X": "08009286a9ffb5e0419b68a64ab5dc0040e8387d63687cfe948fc62ebedec530", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:42Z\", \"userID\": \"ce3444537505420b88b9bd8e06a73675@certivox.com\", \"salt\": \"0dbbe8b3a2739ee764e4c468a83e3bb9\"}", "test_no": 90, "UT": "0415d82022634c8469116d184c4f536b40751729a65a738a07d33d0f243ae084400ec427426a5e1c8459c5593f03e7ca9a1ce1cb5cb2c95912c759fbc1a5ca2dee", "MS2": "09d13ca428e89a7854e528cda041c46692e496b720166640e30d136695e7d705", "MS1": "114671dd75bc56e848ef604d7eb07f37f82a72a631e9cd2998bd6f3a01d02197", "CLIENT_SECRET": "040303705a4584359ad9c94f154185a0cadc735b5e498278782c6cef3f5d33c9c4220ba0a61cd38d11a23c4f32f4ffec829ed7e1b0e52ab5e8d57591d7b9c86ddb"}, {"SS1": "02d604c99dbe8ad96943d17b20601200d8e06b2876d9073162574705d3cfa93909a91c98a780f8ea58aa495e925a963246d7bc0569b2dcce4218886b3093ada4049373f3d980b817f96288090012a235787407cf16c261dffaa3a62a5604ccb6052467d373ac98c2aff97aac8ee9d35aa1fe80fdf727c33a926e5770d1c8466e", "SS2": "0ba8bb63f67b495a640c98076e6d0379dc9daaaab0b76d2a0e53a2d9a950f80503791b79e86cf499e1e84afdec977e25c5f8fb638b1c3377943df9a38c7cdf0f09abf2aed81249590d7268c0b9150728defb174e9e790e80486648aca4871c0a0608e143f8f2eba4951e587f96fe49fedd39a5f160356dfb32eec3001bf3e0e9", "DATE": 16574, "PIN2": 9935, "PIN1": 9935, "SERVER_SECRET": "180d66eac37fafea20d62690a492940044a151243d6ca791d39b7561a10678521367a954237b457d550697f4ad7b5aa074487fba9f6841a7a9745fbd9878842105690ef318de2f1948adfeb971844697c8fedb333e2ab68d458e16cce80f57ce16b522129dc4caa0bf335bcd31dc68746ce46407c93c02675266d9af52beacea", "SEC": "040ba4816166e8c21cc07a4b7dbab13faab9dd93d00a42bd46df45e3bc6b43cc1e081e738f7d8aadea1c4ad5fd368a0e69144af810b5688a83fdd4ac660a46c27a", "TP2": "041f6df10bba046b75f28333be95f6f494c0f4011629d48b2d751011a80411d70b1939436316e6d5920f4242a3cd4c43a7fae1f9b7d14b5398df2b014a7d525318", "TP1": "041ebdc2a27780f8555dcb6149a8ab6d050b81e86d876f0a188e456a47b6de436e0844419e61dfc77b3f36df72fade6235f7c22c9717e10e06c4723b4aa3bf950e", "CS1": "040d9fd1d3e4b50aa260a5b1407298a6ce4ba457412f32d06dfb1df7f84416f1721d6c0b319d35c266e167ee2cc47bcb226350c4e2638a91d8702ed11dc5999de8", "CS2": "040751b3085c081b5ab7c7a62d1708179a8c78d8568978c0145f3470607b126f830377b08876e78130b8838d73695a7937744254513287084a9add948b6e661070", "HASH_MPIN_ID_HEX": "eb5423a25e1526bb3eef42c042ca04685d25449257eb7f0f1ad0dd94e1ae375c", "TIME_PERMIT": "041286723cb8f1605c9ab36eb23cdbc2949d05f9be9550d848c7560fefa3e0da71009ca5f26019fa077d51b7ba2f78d2dacb1bd7a46c2ae31743b03a64f5dac832", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34325a222c2022757365724944223a20223732323539326461663466646433656162663834356466336365313562373664406365727469766f782e636f6d222c202273616c74223a20223932646631373432313266376234373662623161623830343532636230366433227d", "TOKEN": "0411237eac80f598ccc30272d6aaac3678fb61ed5bc8ee40bb75224ed3568173e518a3eabc5c3fe058e2240d50b3ad702f45e9b6459e8f9146a790ca994a80db93", "U": "04045e145cfe8bd4dc9ed0e3530cff7c459e5ba1866b26db043e33dd4fdab776c9187c91f1d763357ba2a8aa1fbbea2298a292944ff54da0e07f06944ed86e199e", "SERVER_OUTPUT": 0, "V": "040f0d67f4e37290a1ad7429ec153353b777a281b4355ab22acbb28e6638d1e14208e6d92a044239abb130217a786155ef457976df86761287390004ab3da36b00", "Y": "03a2d15c45b1353564ea42095af98ba7793c80f4d57c355e7ef7b4481641f95d", "X": "07852dae4e95ebf1659601182f7415be5ccf7b5f1783157365fed2c4aae7307d", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:42Z\", \"userID\": \"722592daf4fdd3eabf845df3ce15b76d@certivox.com\", \"salt\": \"92df174212f7b476bb1ab80452cb06d3\"}", "test_no": 91, "UT": "040d1d31858e34f3c7e0728b42ccd089100a5ee222fa75daf9e3a75d343d8e27d5202a1ec6648ec536b8a8d068836985d6f6c44da10b05cfbdfb657e2bb76f4a25", "MS2": "1982434156d888514628ff80e41c65f0e499dcdb295783bc017ead2955520272", "MS1": "1941454dd79e74480e94ab8fa48cddb341c8e9707338c94a1a6c145f2238e621", "CLIENT_SECRET": "042337024de7446447f0f0f2da7d09c29b9c597c5c62ae72cb878fb18bb9c783b014e00e5877796338d86430d36ffadc032a517d1cfe70e9b286772cc79fe8b0c2"}, {"SS1": "13c17a6b5aee88eb95d37077f20856eba3cd2df11961f914c5ac6fe51f3e79061f281eea12c7f8c143e4ead51fc269d8f3130e8a4dd9deb918133cbc326c7a58009ea6875f8d9bce8a17bf9a31beb6027862b851818d0f5901a0a28855614d930a52a5a0df9290442f30307b64dd652bf3d8b949a227fa1fc8f43d74df7b9950", "SS2": "0793a1ef51a581767ce5f47a1b5ae0722d48aec1c234ea3b4b0a884fb3ebe677187dacdfa211124e063145ce309c8880c0fcae60beeb1b5a56182baaa8c564580a9d5495cccb9f6f5a87ad8434c5a5117aac8fdff2255e6ff189d7b659be198912b2349f5f135a2411ea250af1c6bb174a10150f0729815e897bc07338ac486e", "DATE": 16574, "PIN2": 5150, "PIN1": 5150, "SERVER_SECRET": "13e10c6dfc0d673fad1e3e0dfb042ca0640483257100dda8b9c41770e39e776c0e8186bee193e58069192307d524b741b805360038280eadf9ed3e7879bea3992315f465f428fb2c3bf81710871dc555ca7fd787645049834e36a73025fc882d1d746ca2635a71b3abbe5b3ede6eab10cc86b3dbd65377f50fbe7fa131385b9b", "SEC": "04159974d191e2f0509566136631221f2efcc27da3bc591e4c7d2bfcc51275f8be0258e99713f9634cc33d2277016e4ca762f41bc878d412ff1b1a7b7e8eed4a3a", "TP2": "0407d18bc4c1d01989f2f0ae9bdb3fcbbd0e34814f48bfbdd1ea5c9c6e96e292661d9d47022cc3e9d5f7782780c94b0311fa1ef5cbf32704dc7d400bab40ca9352", "TP1": "0403df0bb9f09b6b8ae4b79f4b71d5ddba68dcecf72aa73d25a838cbd7248db4af1c7ae5812c8d478df6f95bcd0d915e64fb6181f61cb1e405467ac501471a23e8", "CS1": "0403968aed5eb30d20f6fc6d2cc782a780134e1c61295be77a50641f00c6c8683a02c1e993293abfd883e61c197582d12c00ea9bdd9f9efac91c4ecbdbc38e4618", "CS2": "0411d84338d067b6a915139409b5adf50ecb4fe65a852f8a6dfc8dd0f23c3f48ee1037c13f34c35114bb336e50cd957f433870ba442fd18f2d13d4b9cb9bfcba66", "HASH_MPIN_ID_HEX": "50396b01de71f2a5126bcfb46da71d3e04bacf255ebd05561d8ec2aa05398425", "TIME_PERMIT": "041cd33101119a915d6b93d79785855cfae91a772d7c484fa8265e023bef8fb0d22166f1b497bee3070ad304efeefd93f20288892bd257dbe84180be60caff301f", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34325a222c2022757365724944223a20223630643161316335363266326366393237353836393734643634623362333165406365727469766f782e636f6d222c202273616c74223a20223039346537656534666333316662333966393861643937356163616232343863227d", "TOKEN": "0403ca01b3c91e3be4ce7b1e36d2d00b4f82722e6a31cf4275d758783665b9eebe1825ac73e2db1842e756909513aaa56a8a879e9fd44a42b412e929e3e4138077", "U": "041cccff02fe369a404b4f3e7a09a189836213ccb9d0dfe5cacfb00311b06c2ea61772bd144092c5c92c140f4cd99d666f0132f6daf91a3efb06e40711fd172f32", "SERVER_OUTPUT": 0, "V": "041a32eef94abbdf040abd77568df3b19bd489732faaec0983874f886e0f7489761503c4358e352afc7bd8a84bb18f4076f0ec079e514cd5d96570523cee5d2244", "Y": "02f0f8b13b21fb8e9cfebbaf17e9deee35e993b725538ef11bc5694c634ee3cf", "X": "09f639c29bb3814d9b7ab5e0a856b8674f71cbce8a80b7768755ad180a96075a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:42Z\", \"userID\": \"60d1a1c562f2cf927586974d64b3b31e@certivox.com\", \"salt\": \"094e7ee4fc31fb39f98ad975acab248c\"}", "test_no": 92, "UT": "040d939b9e8ec69a8c1f846f86cdfb81bb68dbbff2698f723e1e184ee3ac9da8fa2368327979ece22e09120d44563b2cf57c9a8edc662a49504a9d165b0745c7ff", "MS2": "00d1c86efc3e9d19d8a8bc5c7869995ab72a2b76a4813a5f96afc09e2963476f", "MS1": "0cbc951ca4fd45af267ddf3413bdb9288ce72f39ab23114ea97f4d7d4d9191a0", "CLIENT_SECRET": "04193b5bba30803f9ac0191bd15eb291baddbb3aec31b5caf282cbb599d3e5f8b01f3d2909ec29f76b572b3c2e1ec00844042703b090646097dadd567b03c7da9b"}, {"SS1": "14f6dcc3e21c658deb97eab3c0f3c202928150cc305e0fe097bc32601fec11781e79d74000c83df5fb845012fb4b701045fed9d71fd0cde4de13d0d62453c0b60a9b0c0d1a52d076b62f5ec29e5413e43bb406c10464e3fe1518cbace544c74d1e2f605c53264181991e20e5d2889cf15173493a455ecea8e826400b2e8cbed1", "SS2": "0c712ce3af814d53cda7fcbb9dcaba1439310a6d3c03d74460a710b90d711381201556fee3c9b4103163e39b1cd56feaf9d5fd0fddf4943720fae0bdf95643ef06a4d04582acfc0fdb08e5ea10850d6dfd6cde867e78eef60105b6ba7b5751ec0075a718706acf01aecd7848fced969a334baf941c00ff2fd9863c6f3c1196f5", "DATE": 16574, "PIN2": 5140, "PIN1": 5140, "SERVER_SECRET": "1c1fd8e82eff74a36427f592e16d5152c9cc9b77c3876b4635d04eee006a68c923899fae9ea0bcb1f08e1a2851d651e2939c4eb64bac8a525c616dcd207f0b9223ae04afd0730d71d92539a3986a29263c5828fe84e952d16965db7e28aa6f6505af21d107a3cf2ccf42f895c22b99f2dfb0d11797cc80d2aa61b71e5563d083", "SEC": "0411c36b092fd6918a87b6f4f59c4f00d0b0570be5532c1776b625ba25c1ba4b8d1df3e8380c97e3054c61bd596866104194f3a61ead4b8cc23c0cb3e047db638f", "TP2": "04076886469564d7dcb54de89191eb36d7796d1b651e4851625ac7e34b116365a1131f82b1699425dccf0b53f3cea2120c730996d6a6f90dcdf468c28bdeaf55d1", "TP1": "041a58627128aadd789d4a0c1245cda2d84a706d0db163b5519f7957461a27b65420295c333ed98cd0f49134a2c7bee261d512de19dbfe031d68f7fc6c0f03df8c", "CS1": "040c7f380eb6a178cc1d3bc175dee567db56a6d41831ab81e9547586c7a7d93ed100286cf307fc2ef2b6a50c75782d9c2bb046048a6a6fb831c46c33766f07045b", "CS2": "0411cb09644d4b4795b38e2750df64800562aac4185ab82330d3236a286f6e06990bb74517b32d5f1a815066d18cacce4bb1fa2264369a75c4ac47c093693b5cd9", "HASH_MPIN_ID_HEX": "b88aec13eec2315a764effa6a9f1cd4e17afe0bea682d9efbade7a570ae5b8d6", "TIME_PERMIT": "04131d403abc80b61514dda3cc4e8d2b0949ca9b6fc2d887b27b89933bfeaa97b80ab8270a08b19866d5fa5cfa9561925f6849f22aadcebed2bd586a06230381ae", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34325a222c2022757365724944223a20226535343932363562616263353937633832383238633064356536356234633264406365727469766f782e636f6d222c202273616c74223a20226337343834343363356134316539633532396433373638333437306439333262227d", "TOKEN": "041d5cc6ad81906d8c001c89599997e4397d3fe1ecf93ae13982c44d661517d7c212461d3aadd5fc1c753856335932992c2404b81cc7b562f684dc661293532493", "U": "0406499b0fbc312796a166685aae88cba2904b8d41e3d9934b1945f97829b668c0057a0c230e03f4319a0a85cd7352e2893cd71bea307be407a22722daaa212eaa", "SERVER_OUTPUT": 0, "V": "040105e584712e5a24d8b579df4a6f49377c0148145abfd517ffe229da26cc2e510401e4278d47d2519377decaaca7dda9556da9901ac46d42a595ce3aaebe102d", "Y": "231f39e9ed8ad125f847380c80cc47be5740271db3f2cdc37ebe90df1b5a4824", "X": "232dd145396bf97f683bcabc3a062637cdab880fb6d4a227401adacc6fa8c2be", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:42Z\", \"userID\": \"e549265babc597c82828c0d5e65b4c2d@certivox.com\", \"salt\": \"c748443c5a41e9c529d37683470d932b\"}", "test_no": 93, "UT": "041e64fbbb0286d08a3529ede905d553507e2dbb7ec53917a5f4076bd87ae3ebe90f2fbcf27fb677d4d431a99108e22dc8a9a95838f7edceffa6d9117173182026", "MS2": "0770f5b2cfcb4bf662d767ab0b3a78525e454b411a53e83e26b27ec1e2a37912", "MS1": "08edaff61006ab87c4b2aaafc02cf89ac5543437a4cdc076103fee024933a7a6", "CLIENT_SECRET": "040768fe5cee4a5cf5f73a8b72b3303566a823a4a5074a727bb303313ec75c28b61a041b3c548bbcc1caee215e0635a57e32f2ab18c72e15181fe5486a9a7ec401"}, {"SS1": "07ae0f602308519bcfe9f958f1d7f0bc4d1b951182a1a619042ac5e4433b646f1c0dfda71aa4ffe3bbe4b25e1df94988f14d80b51eb42bbbb99618543fba3f110a569282857ab9b840ff3c0488e2104af22053f10887765668928369bc1c57e80e0b07bcd700399fe491bf0b081147c70c29bec122db8db7aae4e0ea1268c106", "SS2": "1a2f457a33de12d8c675d90bc788071db60373b98bb0fc533b0e7b4aed50823602c7be6faab03ddc0b97c1ffb91e7268193d5d9183cd473a09130cbbe97c8dff0b83052887d5602cb14195b9677d3ed7dcc24b98501b67cf27cc659e5eb9561600d52ad30583ea8a49310fcd73fa9a2bfe503aec39395745ea917cbca57eef66", "DATE": 16574, "PIN2": 4207, "PIN1": 4207, "SERVER_SECRET": "091486c09db4ee4bfba5ca2b4068e6f5bcfc010124f5f96b72fe5a5eb74094a619fe60bc5c7da22562d1589f274cec9b3b8049d805f63bbc5e6063c09916058e128707b5799d5ee98516a1d0cb7e738287e3c9633e383d6fe74b3bf1d70336fb0461977bdecb81e96f8731a8009f71c365bc4c6b276a66f45eaf7bd08b0e8205", "SEC": "041e342741de422033c3c1b3e95606b70995b8ab3410b96abd6670e5da9577453b0ca36b0f13f1dfdd1e390a289c85ec044492a25d4900f501816773cd9fa8b294", "TP2": "0406507696ba8cd2fe7081f21edd9c72053d080f35bc9adf26672a14f666c16a5f2149921dd6168d98952f64d5fb955e1619b5016ba1c09031de2ca08f24f13825", "TP1": "04136cdddd4bcd602181ff5594464b989c22b470c36dc7947db2bb6b03c39aa8f505f22817b39d9efb638f6401d56650c71eb23e3bb7b5094478b9558129b0ad5a", "CS1": "04134199a0d5b7fafde379f9f28e2df6f27d474fe4cf52f9387ba2d9e3b6bd71d901bd2bbd67cd75c1c062015e96b1e92f4b2208d2570709f71a5cc1f043a23e0f", "CS2": "041b67daad63d790d52b901b970535c9ab9831bae7a6ac17948bfda3cb4031e34b0d24ae518ef09f64cf1bee71030b211e8065f7e84c46afa101c69cbb208f094b", "HASH_MPIN_ID_HEX": "42c1f8155ce2f1d0f4e42afa185742cfa5aab343d73604ec3fd45703dce1a2ed", "TIME_PERMIT": "041eb9da7cf51221a23a24abd65865a1b36818428e1269b68a891be668e0f6383a16a5dec1ce57bf56cd412c814d727b8666d9b64da69afe79f00c2c3113cef46e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34325a222c2022757365724944223a20223964653763653134373637323035373465323033626263306434653566643263406365727469766f782e636f6d222c202273616c74223a20223836393666616365663065663766663937643534373130326433666631666665227d", "TOKEN": "0411d83a6c8a2e75e842cbef0fc8d5190bf5bcf504d3da0b64aee6f7d00c02b82a02e65ff843a33a74bbcc860785bd43a90fc729e85d2bd1d7bc8c5d63157550d4", "U": "040ceca0da69b4c4e49df306106e3ab2d0fbce862353a6c6e5af96b9e68fdf41860259db95697bd0d6429a070f9310d814675092086234188142c57435a0d7112f", "SERVER_OUTPUT": 0, "V": "040e0e573515242d285084e50cad2ace8c4bd6fe76f2e33188928a597484c652010c228b23b9abb69c20eea800eb9af9459ad54a31f9eeb233ff767e568019cbfa", "Y": "08ac7bdb02bb654aa5254c8f4dadb42fc5964dc5869c8bf8aadacb76c76260ac", "X": "19e9e77fc0b66b39ec3f094c1743060ecd82951043d66fc7176371f1b2ad4440", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:42Z\", \"userID\": \"9de7ce1476720574e203bbc0d4e5fd2c@certivox.com\", \"salt\": \"8696facef0ef7ff97d547102d3ff1ffe\"}", "test_no": 94, "UT": "040154cdcf5b2adcb286d17c95c905f251665e091510451333957df1ec5221fddc192c517a6e3d7004aa134fd388462634fb4bba42c0706ce9bf05d68760d897e5", "MS2": "20f672e0d167e5aa91d5aea7ed740ad8062cf6ac26b6c06d1fc719356264ba71", "MS1": "0bdef0aa6d92389ae4def2aca7cef69c327a534e001a5002464b039e04ddae46", "CLIENT_SECRET": "0409480df4f22090fff35075bcb6a232d437ee45cd04f633d0d44bc6b43c0111a41fc12c265354f4e0c919ed69d76ebf1d80fc09a1aa674b036b735b9698c22a07"}, {"SS1": "033bbc9c7263250fe4c057ea6bc2745905a19c80a90aad1da4749b1d6558138d205d1d1bf70e95598cf46e1d1343af8c2f262e74e5f4a279032f7bbe6aed4e1e1a331b8f7d0ab4acf5b8c8084b929506b39400511f894ff4ddba03e19c71704016658c8a8620587046c8493ff4564a7715f6a13d04fd11f938637c34ab73e355", "SS2": "024b3b4b2acffe70be2438ada0b83355d009362dc8f246e5ff200c018b7b1b320b7d44dd7c03e7f55a7e85abf910dc62dca6f1507dbfeb6a6743827daec76379124ac2c5593fe2102df95519a8a181eb6b1daf2779c23fb9b192b90fa1ef5315219046f05b6753461031501067c6891ab49f15972450b3961bf73262b850a9da", "DATE": 16574, "PIN2": 8448, "PIN1": 8448, "SERVER_SECRET": "1eb353b1874498946cfbb5f6e845f65b88b351587e193b21959c47a8c0dcbdf41c781496eaf139a09649279d5ad15e70b40f855f04655fb3281291148fa1279f1efa8f54620ee6e2712bcdfd29a6a6818d6a150e7a4e8765145feade19d88688024b3f6001877e9492f198b98b6aa0f1b9180cad5562eb62d8663a3f0f5ad593", "SEC": "041b1b6e7a4f20a40579a602c1470ac514b2b86b9604105518fb5705b3608aabd1124d975d4ecd691c0c9f677a11cf87d8485c6ea613b2f2bb7eea9c07e2cb29e8", "TP2": "04113c347d5cfe50d6631cf8367b66b4c8add52d55cc6eff2f12d8c5c62d6258551a7721401f2c64a893cae506f179ed83019715b5580fa6dc94c4215937077b8d", "TP1": "040b3809dfae74aefd5f340ddb75ff36dd00ad8db107bf7a84129236683297996e14a0b19b78641ba97e1b2fb45c2e18e4836c55b8c2bfb005f7ea85264dc6f058", "CS1": "0412bc1784dfe82c9b209987a78fcfeec4bdb584f30e03b45e65a30e998e655d4f154b0fbe386aba393079b445c2d61f7c3372959f67b027fd334cd01c55475db5", "CS2": "040df15f087cc64ac9d6adda8b51eb0fea283c6af62975dc55dd8d68330b2411de086468d452c9194772ac5ec153af8b17babad6ec22ac239af9e87d0fbfc689c1", "HASH_MPIN_ID_HEX": "b1eadc2680a6b952fb3acc73aff3afc5826258ecd88062f00fb9ebe98e0c914f", "TIME_PERMIT": "041e561a0e15127b94e7edd0937996ebb8d8fa16009e47d7ec551ed38f1048942b16afcd737117fa774eee215dab59abc43b11e6fea469a6d1bcace8f6a904e1fe", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34325a222c2022757365724944223a20226462363062643135353933633534306638666537346465633239666532316166406365727469766f782e636f6d222c202273616c74223a20223364636630356436323930306237326562653034373935373465376537386365227d", "TOKEN": "041a77c0804911d0a0265e156b95ecda06f0e1c2f15acc20a52081d05894d39cd304f0082422370292da36c755c7b4bcbe1970b6b787fbd9c174a4b7ba92b1e0bd", "U": "0406696a5a3b0b02aa7903130e5fe8a46bb45ee6d94c14eace072a2bb5b0df336613b366d59d53a00630369faf445b345b689b278be25f8acf756e4d258c012c6a", "SERVER_OUTPUT": 0, "V": "040376f9bb435608f61155c1e8354aaeadf859c3a5d59535d8568bdc80b944a1270c33dd301f955f07ea42e5586e1424f237aeeffd8fe6ec659c603d4155bbeb33", "Y": "23c047d8fe2774f1b3e3f37dd7e700a83e14888c94dd470462000adc6b370342", "X": "1d595b3770ad373fcc1453acc370ee8c08b24ed9eec47051cc74b354b6dbb589", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:42Z\", \"userID\": \"db60bd15593c540f8fe74dec29fe21af@certivox.com\", \"salt\": \"3dcf05d62900b72ebe0479574e7e78ce\"}", "test_no": 95, "UT": "041e58b99f57b550a019d78f5e0be862f1a477eeeb3ae5c588d5938de1da2b05a704b2e2baabc3064f2eb0b8327e80bbaed123d266a084e18d82613e21abd6f115", "MS2": "0faff5027c2821f57c29eb3c62d29daba279dac83de6d3882d64f9f2b16caca8", "MS1": "16847bb451ed584e57ac0cad81422611fd5bbd77b16589a513e3541853084cca", "CLIENT_SECRET": "042131a50a983994910ea0768e303b851bbd3c8ed876c3f093f22019de18e8705609624991e359829e0f9e930306ea947df12eaf574661ed36df5efacb67476ecb"}, {"SS1": "201da16e56171e757072d481bffa965ab5a0456f06134586aac1dc6097d6ca3323351990391073108253993c5ba0175d3b83f6d4636ce16e4dda494f55c09f8e1d011b56cae3d18f063ed37953f95a71c972324afb34d23f72f75cba789f5a9822d491fa9a3d9313a911c4fca5a7299f8fe9c66d9402bffd76b356b210a054dd", "SS2": "1642a0e24111176ec647a7ef937bc9fc5e96e60ca1590fe9075652733942c0a8180efa02234db1808d31ccbc9a7c45ecbd5f0b9ba3bd2ae4d39eb0091785e43205316367aa0888c220428eb6d96de44f84ea0e643f9ff99fa8090f9a168a9ea414b8a9747b4f8a182f46a90430e10f559a5a8eaa9375150739294fe5a0e36897", "DATE": 16574, "PIN2": 4655, "PIN1": 4655, "SERVER_SECRET": "2246ea9161a2e8e4e2fb619445d924f708f61578e68daa41c13194c0787a7a7d00b1eb1523ef52d3fcf62bcda8f2311975888b9d9fd0af5dcb17e574b6729aa01d5057dc9b27e2ca8cb938fb90fa61b21fed52adbf042167e43e07c228490cdc12b8e40191c8e68d19c6b3d44946b322d360413c153c8f44267c58da85db4d6f", "SEC": "04102a72cc12f5567cd01d3a735cd768034eac11cc1f8c2fc2c80e9d18e90805710ff92bb34bfeb05199536ddcc08c50cbc5d5a80a6d869a94f902a035998db497", "TP2": "0404f8a140f6b02fc05281e0c70c27af3617a8f6e69f05ebd63cd1c9827199e51b0d8d870ce7688404450658aef86e85403095e7f34532b55e2e35af2a3a4c113a", "TP1": "0411221ddb951115300b47746ce712084db1d59f22890069b798396eb4a6a3c427016342600e48011a62d6072247e6df0247fdc1c4d59b7b1523f4217a04fafaea", "CS1": "041fd1c651a6c6534af301f6934ff9b0f1bf904d2888e4c9453e97b887d0f2b14d12199e464d7f6b7255bbc0c31540dfd23ad237b9dd37863bffe6c879fdad013e", "CS2": "040af4610790aa958d284069b8ca72bbb84a29f6322b4bed65a953484174ff6f4d0489be7548106627e43106cf89d799c8d7bc79f591722da903c56182e1a9ae17", "HASH_MPIN_ID_HEX": "6199f7805403d537d61e01752a07140c66ee2baf4cc7d7aa4ea09cf78e3d546f", "TIME_PERMIT": "0405db9b2497caa5231bd7ed742c7bf67ff63eb5b1d9059f02b6921c965d4bb98e1cbc68c75db2912e983ae271263ad161d2519851949c1ec893fa9767b35ed030", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34325a222c2022757365724944223a20223238356430333230643031313937356362306364323136313732363736363333406365727469766f782e636f6d222c202273616c74223a20223463393131383561313231633266323163666335653635353664616333656632227d", "TOKEN": "04131ee62cbfcf807c406dce65b06b680f0128b951694fa4c3e9f4de32dcc4f48d0bcc63acb1492de70bfe9571586a1c554600c5393bc76aff9ee6e89abfe305d2", "U": "040e7fabf872cbee9ba7df044c6ba56b3aecda167e3c47277c9afa54e4d46e973e19283b622fb2b2adcf053634311d39e3481de5655ae13fec961439396c7842c7", "SERVER_OUTPUT": 0, "V": "040ec7664bd087696edb01c43b8f252e3612d14f1db9b7985b09b7de9f1003f1060948c289f414b777961174eed324818510a6944ef4cc95ee76a7223230d7afb7", "Y": "1d0dc6a5fc0c9cb8d0b63c05696f1d346571cb640e9321e7f9db95a53c4bdfb3", "X": "123777779b7fa7e6c098b1e4097f4c082e9ab7394d9a5d401d0de107288e48d6", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:42Z\", \"userID\": \"285d0320d011975cb0cd216172676633@certivox.com\", \"salt\": \"4c91185a121c2f21cfc5e6556dac3ef2\"}", "test_no": 96, "UT": "04069c7e5e5ad69a29b0c5bb73f2e930f09ed47fbea3242a88754289fbf0bd22f5109768953421e01e4a41aff2d4c30c9788d86405d40de26a3ad3c314938f424b", "MS2": "18c670e856d88b070948554e26e1d215ae9cc497c240e3e390ad6e384749a7e0", "MS1": "1d21597713d76016e720944efb930fe2238ddf9a4b465a76e10d62c481f5f48d", "CLIENT_SECRET": "04037aaddd360201dde7d63067f58961bbf2e27d2d6cc82025eaaa49586c03b7810c9fbe40ae9a37f6d797e29fbe1699e47458d43cf632dd7c03a16247cfa17bf6"}, {"SS1": "0a8ed05020a86e5c04d6be28d4d3095f4408c6740350c1c8f8eb534b835c547c005a53a804cf0ade904730318ceb54464e2cf6f6f18f997e639224094e30c6981590b833da4043975e64e5b07e9e8109c45438827b28be1fc60fc8ef0eedc38d03e27ceb99fcaac6bae028bf7d79a3aebaf9cd644824ea4864f23c716bcb0c95", "SS2": "15dd02de8f1f4bcee3b4d2d8113048168318e31b6469ef917f80d7dc886c19780d09ce597875a5b04757d35a15a4820e900ecfb58937a3e250cdb040599f1ff80cc6bc1c68a912ac5cd52de310131515d1d1c11bb471bba977a4b95220e0ee241656925c17cb86cbb3f2d97afcbad184ca314e2d92c4c933f845de47fd7952a4", "DATE": 16574, "PIN2": 3105, "PIN1": 3105, "SERVER_SECRET": "0d1041488e95a7f546d5192571e11bdce0c0be0b9710b27214e2755806b97f3320f0be4200ee90b1f0a008f64b51b8734bf0012ab2ea43a820d6b9656c04c0bf091354b65873e96faf113b2e63918f617b948c54e99f1d44b6ec6e27a284d0231cc135fcd4de66ffc43d81c6ae45b8edc007c74147daa0dca9dae802014423dd", "SEC": "0419302e7bd089b80e357015869bf6f7e87ed017292484200c2e254c7b8fa5c396117e980d4da50fd6bed0fd7c107bb2760ab1614daf8d69c81ebb2c45e2eddad3", "TP2": "040c43791cc2d5b693d92d34157d6078f3161cf6c8a8d09d73c7ae658ce46914021e6df9e3b524d3f474d3dbcd65b3e85a600723d02ca0dc3451084f65d9210324", "TP1": "0409572ea6384ac5d7de14638b2a2ebf5aebacf38c7004482b2110a07cadea92ad0bdfe63f3c05a96fbca70974dc7999376e15757b81f54f31e2b5db9eacef335f", "CS1": "0422646cbca2d42dd4aa8537b1ea2d6ef7593aec59411f2184790216f5f266513c1e2ca63faa9699700cc54e269a7ed651c441b42c319ff290130ffdccc2851280", "CS2": "040a00ce5ed672a7bbdb3c0dbc26663cb254253acac41b279b34f640b8f8ced7040297a333a5784bb466a0b6db1578b38b2821773edfe973930efd987e7c09b7b9", "HASH_MPIN_ID_HEX": "2d111fdda46279e4c6bcc5ee44e79f70819dee84ded3ebcef5e92666741782f2", "TIME_PERMIT": "04239b12ec89e163f4b2e6818bdc53f825452688f10cbd90ad50d9e28056826f6c1813dfa20e324a9213d18e04f1670f26ec790ea465568b9fc0cf56f17767568e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34325a222c2022757365724944223a20226437333334633638373530316561663830626465636437303833306638623635406365727469766f782e636f6d222c202273616c74223a20223461373933323736666565646435626130386439383137663834613735306161227d", "TOKEN": "0421af944b806e4e61a4f8d214f533e0788a29fd5bb06a56ae47177efa57b1a9020b2cf14df998bbbf18a4654383ab6415588ac1391a882408248bcdbb30d87b57", "U": "041018dea602bc55ccd7f2853d57d2785c9c089058500dfeec0725ae8ff0de83d11a45cbdc1d8020b0b878b57738b325fb9bbf7cf0bd3540ee4d3afe71cfe96277", "SERVER_OUTPUT": 0, "V": "040f92d76735bfd3bde7b894d0f2013225c4da1ae74196eaeab3419e263fab60330c9aabc92fab947c2d28b0496e530cacabfcbb01042d223d6d1eca06827f5e3b", "Y": "063c83ffaec3a5ae316854ded47df7c9a133583ba13bef4b2f533a2329585df0", "X": "15059291a21c03d2c51c00b278d5cf063b7b597b42f136417988ea760c1b5274", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:42Z\", \"userID\": \"d7334c687501eaf80bdecd70830f8b65@certivox.com\", \"salt\": \"4a793276feedd5ba08d9817f84a750aa\"}", "test_no": 97, "UT": "04129062df4710a83dc15b7d540f933a9332a7e6ce1eee134e0c653a42c9d1a380124a2e9a79d49e9acd8501269092ea2cfdcf26e51bad9badaa2146f7134aec4c", "MS2": "2011450dcb071d423590352231290ace98c4505706d44eca28bf697de74f6dd9", "MS1": "10afa2fe5051e1a11a613f4ae4b2358856c2f62b1422f11cda342b995ee52e6a", "CLIENT_SECRET": "040dfcfcfe8ad5fbe0e72b007ee608be9b23aad5ecebe252c1fc03f1cc1052fe0c015bc7f8b3a13c096fc63defc306cb0d044176bd94a1aa8a1f99be1c46085fcc"}, {"SS1": "0ef024ac36116414e2a72bdfc7aad26096bef9b6fd470be52a7b9d4167876cf01a724730dfb773425a342f69b0e45ec5266bbfbcf706a45d71a624869420f8480a8d438b04dd2688ad414d462fa765592b5247f051622383934b48fa5712a3e819fb1dc9c79cbd10f0cd21a2359d8d754b1abb2727fd2438893c7293afaf07df", "SS2": "00a8decf6198327e22a17819068d5e4427b09bf61c4e0cf4ec843d62acd50b9e0245047e5d8ebd25078476893bbfef0dc02ad4237467ba9325093479f18dffb81fd7a1d20c019df2b065e9a9b6a36b049b1405aa829926ae5272066521e54ed2008f953fe5a05fd0179bcdbd9967a77120d3e0d8bca4a702f01c8d218f798c4f", "DATE": 16574, "PIN2": 451, "PIN1": 451, "SERVER_SECRET": "0c40160a2b6617316c6230c0eeda0b3e1fa3296e865344e5b656bdf9ce7899e80e9cada544c99c67dc02f05eaf72350de64e357fcb0a5945ebffd5cf1ea4e6cc17b8ad8347cac7ddae0c2ed2613e5fa800b72251541bd47c6b84a83a1a5dc68e1179dad2361195873b47944cf1b53b259d95dffd1ea6a0ca9e9cf83182df605d", "SEC": "040ab8112c6758a6e87782adda13ca686a540cfb3c2a1e514cb8039c146d33739a0e6631f0d49cf578b9f78eff20d0e9395b00ae182d9d9ce3d38ace2496bf14c5", "TP2": "04210130df40ca766d67e7ab0eac69cc13b44f52c61f8996fb2970b3df9d49dc7e132ce62a5ba3c82eda99601eca4fea2314e67287bd4e911fec604edd033d6f5b", "TP1": "040ea646ca771f6c66a1c80d8e937971bae73c3cc73f660fbee59ad013cd9a103f118c1fb7e83ad8c2cd022cc1f6f2a5d839debe22ab3f7b41538da61116f212d8", "CS1": "041f2eece85cc5c2f55a84a475ca6e0379b0502a37d936cdbc56e8ff95a44caddd21d50982a43a706ae6e25c973d5062765eb6de3fac3af71b9bbac76cc8b53725", "CS2": "040d232e9cb689b19f8781866175020e699f571301dd5f796a018d26ebad5aa8941dae23eb56855f0a3bdeb34c3fea0e25be9dc47b87ddf02bc3486461b5aa0abe", "HASH_MPIN_ID_HEX": "3c74f601323f4d7c04d53e9c09c5c4a3aedb182470f88febe4fac51f1bee2dce", "TIME_PERMIT": "04228c8a8760a082d22e15e628c705bdbdc7033a590781f7d8fd9a62f036e2ff1d04c6dd825cb0bfac8b22ab9f733c5de160b56f42dddfbad519e964550c9db579", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34335a222c2022757365724944223a20226464623531396435386664643837613339363438333132313462656239306333406365727469766f782e636f6d222c202273616c74223a20223464316264333631363365393362353066316133323761306436383638353538227d", "TOKEN": "0413be681b96ed3aa6e36e1484d6a9346ff8f6db41c3ee3504c6f2b77c2f6e0010175ef6607a0441b6841e7b402117493d2f069db024b143c386d9c4e8960b1840", "U": "040c6b22a892b830051f144463104b23391b31256333ba692e16443a9e6b5cb48115ea02264e5f361ecc083259c49ba9d9a5a4d5d95cd1f121ce7c5547f725c049", "SERVER_OUTPUT": 0, "V": "0415057641bfec07cf7c79adbfef9c029d545d7a5b6be2b8ac7761e7d6d82af08501913a485de4329d91e80fa221defe91fc7157e160d052dcb76ef49c4a1169d0", "Y": "2062616df893a16ec5b91374e6bc20608e8f2c8e6dea4801aa59db1cad60b53e", "X": "04874c6ee8d356c65c9981d743d3aa92d06b049f755373e62dd937295539486f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:43Z\", \"userID\": \"ddb519d58fdd87a3964831214beb90c3@certivox.com\", \"salt\": \"4d1bd36163e93b50f1a327a0d6868558\"}", "test_no": 98, "UT": "04070e609bde8b432bf4c65694525ec836e7d009959d7e0f8758d5eaf035b925721aefb691f974eafb4d8eb3a6dd254ce2d090ff78822f5349d2dc4eb5fa349f29", "MS2": "1507e181184e973a40e579d6dc4ad337292f5c5b771f45a52f52fc936b4ea234", "MS1": "1bc9be49250969efb85a7fd48063f8b7d28a25c7f890c27840e3647887ec823b", "CLIENT_SECRET": "041e3af68baefa15e423b760d37cab0c2d84a7b5c3805442da6f31e8b5f482982c213b64b7552a3041ef914684d2e6336ac4bd6fc526afaf7bf00306c95b261e4c"}, {"SS1": "117979048a7f7b75f501cdf1a1aa98cf193314504bcfe2f9be9f8211877f9b1715561f0312fc90a18d5a1aa5719fb2ceb8c3b0114ece63426647802df7f530920932e25598d0f385a328e9936ddfd029416cee427065a126bec711c64224d0bb027069c6df0b246bd87f389a69311fc4db51c66843c1aa5d953f9e79e66caaf1", "SS2": "1253c87100d1a70b2c575154aff93ffd1e74e4aaf5270680170635eb2e57035309bc1006046b605b4601aceb3cfc18ac5d3e8941580bb2117e67f27f81a410ef03ba40088e93813fbec31e32e61fbb1f7eb72adab3fbc13dd11e026c4669f76f0b9c0b15afffed5d9850b344c1b2f03e92e4daf650be8a4e7a89895302ca6946", "DATE": 16574, "PIN2": 4471, "PIN1": 4471, "SERVER_SECRET": "117f63b05f8aa7626d3e396ccb46ef1deb179a13fd21cbf2f9d079a595c9dbdd0848a4ee0b198a47d8b1ef6f564b55420c140dd3eb00d81f65a0440e48f9b03016df5877c273cef3001e25deb234fabe63a13d32bda39a38205c618087f62db00fdd97fa31e373932c506ee3c10b9feed68aacd811af163c3330a82b872e1f44", "SEC": "0416281ece500ccf21daa16e42bb3b3355b30399e20d10d14250dbcdd85d04d1e80240deea7649a16da17414abede131491320bfd30f3e96537ebdf82f58997054", "TP2": "0410cf6b55739ad948aece6eb2591b10bc69a0e1b6631cad2ae4d036011bbcf9c2114754182858dfd964da39c46f9e9cda9a9a6834295e7f7dba66274d10654848", "TP1": "042186c8f49eba6547e171adf2f88cef4bcb1646f341f9e9d24cd943dfbf5f464505a3ee29020decb1d8348a6996fc6497954e6bd873117b49890a101790affd8f", "CS1": "0420e7a508d5759334af039beac00776c5802f14800fe260a1cd60e60f4c6f2caa0ff2603935431b999769da59f239e8ff49b8a653747a5ad7be9a2de6cb820fca", "CS2": "04210124c36850b0abde5b4a56f623948116af13c0d5dc0a50b15d3c49cbfb7a2b1d6cfd34a519edb62510c363f1c35e8261aca1d62d117eaa223fb7ec593c8b1a", "HASH_MPIN_ID_HEX": "cf32aeeef560bf9644254504d5e0fbb30036ef1e60fe39ced9746ba441bd2af2", "TIME_PERMIT": "040d429f69f43c7c6f6f67a6f2addce441a52c4960917dea666e34d1556074f4b30bf3368d8b7f990792055be91d98c3fd0c88ca64e8a015ee69ed742d909f8ea2", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34335a222c2022757365724944223a20223866663238393461343465626162323334346163623961303962303962323637406365727469766f782e636f6d222c202273616c74223a20223038656161616461656533356331353866313031623662316530346333306430227d", "TOKEN": "040c8285c2b91edb19b5f89f7c0e923aa59e2ab8d428dc08ad610c5ec361c4f1d5225a4f1c79f2e149dc65d8bc4423333b28e16066173e742e37bba1300c805e35", "U": "040e17b55650d9b2c2cb4a6e2b470287410940397156eb82c704f49c6576d63d9804738628364446696493e8e5074519779d8381957b5da4197b3ffd57f9416eef", "SERVER_OUTPUT": 0, "V": "041e59b02fffbf052cd0a2706d253af2daef39f7035913df02bd29715344ef2c3205ef14fbd726282b923bdbb08f466024ce30ea51c506e6309317f5e946eba26a", "Y": "15b2566680423303c458619762f73c04f174c484ff0cbbf3ec3a56c9829d39b5", "X": "1182be8a617bc1ffbf4f4199a0db39392ac3cb41111b4ae3cfd61f255b182d04", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:43Z\", \"userID\": \"8ff2894a44ebab2344acb9a09b09b267@certivox.com\", \"salt\": \"08eaaadaee35c158f101b6b1e04c30d0\"}", "test_no": 99, "UT": "04107d7dcc2d1c46ce7dfb714f2f8a04a1413c8159833e86c4772da2661d25d9eb11278b6bebac8ca6b2b4e98cbe7e5214cc3f05e0acaeaa356e5f5389c8525fd4", "MS2": "0bbbde2ab6f2bebe8739378fc893dc454e05e50bc57c11b248a3e02e6d3041a3", "MS1": "075f2932c5228ceb35210fd3415e2c062c9da203bde9569875b7d1796ce5e9a0", "CLIENT_SECRET": "0418b94b0e38dbb004e010ae1cc9b4ee9a722bc89ba6e983b5f76c0bd1dc3152a60a0f5c7eb641c2bb0d89af99001438de23d1f5b12e5fa9273ee3f6fcace899b4"}, {"SS1": "09d643a0bef4f43b01fd19cf97a6377b02b9ceef54cd3f01032edf65bcfa6ce2222fb1df7e4f6daba28bf796e4c34bb137bec2eedbf4bc8636272de17aaff568177939fe8a24bc1927303a95c04e1db6db3156516635a04deb7be0533513ecfb2387c083dd2fdc27c621f142f95ba7ef9ba24a087fc7d20026581d0a04c26b05", "SS2": "130437c0788185f59d25f6d82a5a13a63baf9ade12f9e2ab15b3ad67272960af17f79535d3c6eaa73ccdb41f024a75df44d13f8c43caf8ea0c86dd05c1b7657a08f3b1a2211d8097fb6e18218c123b27f758e3312453426853e3f72d234e80750b85de39bfa1353ac5266803ad341d0733231de0fd2dcce2787fada092de68d0", "DATE": 16574, "PIN2": 3975, "PIN1": 3976, "SERVER_SECRET": "16da3e60d4a9815ff7151659a6fb74772145c8d5039f363f21830d9ea34251ab154424c0c2de08073bbc2d7837bb502da21ca56e67fd5356c8182f5663975ea21362cea335228d286973076ed8078a5ad58b2aa51c823b59fafc9ba94a9b37501c468f6e3584dc8bd4386c4a3089009fc12584810ef412891600330818f5c490", "SEC": "040b943626b07cd3713894002282ffe567115a93e9c3d746cab8605dbc9f105113034b3407d5d559ecb1e6ad03fdbe18e1f4ef5d8d29c3caf218b0f3054e91494a", "TP2": "041c1006d7a7978db6f65f37faac2fa6cd6031456ad512168c1ca289324a7c8d251ccab1cfc62dfd6a5ccd6a3459513b8ffb1c93a0b6a607a2072355eedd044abc", "TP1": "04085a59f199c87abeae8cf1accc946e62cfb26a3f544bf1f663ec524094c4b7f70373a84c683895ca8abe3e4bcf51b9e085d169bf2fbf4f3d0054c4b530d08aa3", "CS1": "0422b473e2762c99eb4f53999d3ae7a5b6bdfc8154e32d88b77633505f26378bce191baca57ca1a8eb86028342ae3693bb9b384f4e364a51946e08f5c170cd32a9", "CS2": "04189be78e9534cefd89466d2795308569c35b809deea4a060a3d893e27120ba6c044d2357b4734c56d49468a5971b408d77e5c9239c960308a476651d3872df80", "HASH_MPIN_ID_HEX": "a59c4d255a362630e8ffdab5af2a830156e3d21dd43e9d53e3dbd9548d6c3181", "TIME_PERMIT": "040a1c9dd29d30c563af59613dc2064c1df3102b1517a17945db1e8bcdffd0e44f0bb601c5d16dad959bbd0f1f0e6d69281c4213783785363c9403d673e957bc5a", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34335a222c2022757365724944223a20223366386632633937656365303235363133306364316431316530613833383534406365727469766f782e636f6d222c202273616c74223a202236653738346361336238356563353833227d", "TOKEN": "0412ce0573a9ce924c920014cd27544b82276c805d2775045836c5351fe73e3dcd1b14a29ca1b97cabbbc122701630e6a06ed5d4f09bc3523d020a483ba4f49ac0", "U": "04030348ba0d7a28058c505b714053c1d32040c41cbc140750169448ecddc2ca0203ecddf3142d89d19ab0a3b3baeebe3605fe2c383605bba27d33a22b6da04844", "SERVER_OUTPUT": -19, "V": "04030214369f0216b3fa0743cef44ba7b1935dae13d4c952a24f079d36355ababb0b6d57b68983e36dd1ff8784c4c5ff4418737b19bbd2f2fe9be4d2989d0cfcc3", "Y": "04765cbabc5da009f9cbe45e1ce7f0c33bb1899a71cec70dac6c39a1ecf4c0ad", "X": "1ee6eeecbe3f670979d75722e06610d8fb6778ff3fd7ce9fde6377a437b0d939", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:43Z\", \"userID\": \"3f8f2c97ece0256130cd1d11e0a83854@certivox.com\", \"salt\": \"6e784ca3b85ec583\"}", "test_no": 100, "UT": "041202d7a13487afa9ab18a29dc5abd204b6f5bb8bbfc2d550eae3f8ba431096a01db7bc3a551994a172b7d8b78176a2bd8637d15ae57439878072714c400a8ff1", "MS2": "1db90f475befdd1bf0be340581415f700b79495a1156e95dee0e301eb09209e0", "MS1": "149534f42c7ec3e6d0a81f6ca2641ab82135d345dc28afe8292875b1c6739541", "CLIENT_SECRET": "0410f2c16e2d18ae0dc4f1f021f623de28b382e5ef3afb71d40b26a5cc717afe1a0d55da689fd4e50a4baf49ac82cd48e3f7f2782786e005ad29d7e6abd384dc44"}, {"SS1": "09520aaeb316a3189b93351fdc4b3046a9ab8730382af5799c839d0d7f0d9cd6049ed8db776411b24c9de280c0305c8e557ade3678dd0aac176e585261f4541e139fd34022674b2080cc2ddaeea94ee00d143b268e4dd00c7d74086c9a18bdf3206e785eb169052b5304a305fee5ea2ac5304c1d4f9f8f44bbe91b09b6473232", "SS2": "0466c2d5f88e0248d9ad132eb707ecc42d583d6d3ece870eba00250c3d3289620d86506642f2d0c208b3ab5491e3b4020379309ab5a53edd2327e93a44d8790f22791af5f63320239884d056b2b282f19fb639a58323986237a147e67f72a7912111a144a2385ff308b4f2102313ce071437598f2671b5d206619ef6d8ca777d", "DATE": 16574, "PIN2": 1395, "PIN1": 1396, "SERVER_SECRET": "18db2db8e5c6bdec70a1170167dad0bfc82f69309778a38aec1f3e050a15732a148b2862753493cf3716913a907cb8716a86083c6824f24e97ea58f1776424500222a94f2ec2b69c4fdfea5115667a4ff6cb820e5a3a37efcdd3f8293abdc561115dc81f815c32b181ee65035395432032f369c23ae76d164902459509bbcba9", "SEC": "04095387ea3c36e4e5f034bc068fedcf9e35023b5783330f1baa35131d34ce6aaf0f094cf6c8d18b3e275ae70d57006765df6d9b3abf578a9a3b9375bf8dfa6ef1", "TP2": "041029b8fc97f7c421f4c61bfb6dadae9d504101109947789c5b5951c9c993152a21ef129c9a121ae88665110ba73531ef0ef429a5c875ed254c5ac5b4394946f9", "TP1": "040964a9f33abed4680305428e88fd3c9d5f15403af9024e015601bcc1cd338aa21814a92d2a02c013309f647a5377c3019e0505226184304bd4d1397ef1b54064", "CS1": "0405d73a477825c1918166be2a82d1e7f327c4bd761ff73851947f5b8618a2059810f4cdd51b7c6df81a1acbbfc93efb5cf935081b5318539e3b6acf5d723b8c79", "CS2": "041258810c7ed76583d0e644c7a2e93790deba0ac0a6ced033beda6a9015af65af22a78229f96bd2ef45efbe64293e7f8f3541499772dd5d52faaf7e3e902b9425", "HASH_MPIN_ID_HEX": "2ca0302753c70da4feb8bb5b25787cbdf76f6b006a4beff6f8fba7bc6366dbda", "TIME_PERMIT": "0419ac7bac137f437783bab22d32b16987f672c287aab1ccc6a021267b39213822170f87ebb2e689ac7f3b5dc9be4a74cecf9e8b8a4cf549ba549fcaf4a8893a18", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34335a222c2022757365724944223a20226161363338383563373836643037653764376335373036653732653966613732406365727469766f782e636f6d222c202273616c74223a202236633333663536646264643837343961227d", "TOKEN": "04163c8692cf316aa63ef519c1c5d7099de4835af391b9d97f0bdc98ff9e8219d3044bb18a47cacd809e2decd80604da75e7c039ba0ff2f0b7bf96a16a25c009ee", "U": "041869602ef92ce91b70cddf81573a6e7bdee832efb024cc90858d0afc742bac21027fe71b283891842f36f285e0314bafe54722fff77f96af32e91d6a8891f0d1", "SERVER_OUTPUT": -19, "V": "04218ecd817b4561a7099a01adfa97a030e6d146d62f5f1c9fde38eb01beef46771c6274b1aafd1dd08fb67410ecdbf84fd3263259fd5b2014237dc670f05d65ee", "Y": "07b7890084dfdcf8be34c15e845d1ecd76e0c409932d262a7033fac45fe01caa", "X": "1e5d34d070f64d88383ca50727db0946653ce2a7c9c6d520120a08ed3c0f1184", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:43Z\", \"userID\": \"aa63885c786d07e7d7c5706e72e9fa72@certivox.com\", \"salt\": \"6c33f56dbdd8749a\"}", "test_no": 101, "UT": "041ecb6755d7375e750f9347f7e319a061014b3e964382d42cbea4a4a8af25df560dab56d080757e075734dc1f09518a1033c84e279c0b8639570c00da95d5be38", "MS2": "0bb0d85702ec39dd191a97e45ff0be87fd0b06ca5558a64da1fcc91845c8d2ca", "MS1": "1687b7cd7d87020703368518dfbe6e4c4fff9d3d3e6a26ce0745085a3d5e230f", "CLIENT_SECRET": "0401ad57bb50fe6e824d9ff8fa752d495df0804fe3164e7ea80a869cd5e504ad321ab55546c7d1d5d203546b8629914cfe7e00bced23311b7b25a88256cffd2192"}, {"SS1": "05e8afd51b9afafd205411d325ddefcfd98f084f09abb8ab0bd91982753b42b70f642329012ebc15e0926bca2afdc65105cae7fd69a89686e89ed75fc18da86909e89d49e58db1c4a57d6f69db28f3aac233915f5e528a68ab65ea4fd53f69af0d7e64d1c579f8d341b8602b45ded94de9d2bc407946916cc8fb4d00594621ed", "SS2": "2266a45832b219809178e3859ec68673b4dc50b32b2f96e89fbf969198d46e4c19ea7b0a73d47390236f14a6812e4f633dbd0ddb3991c767e1ef0de425bb08ab200df1677d9f6996269171f99b23f2ae70ef9d649858a69efab6466ca8be54741103b74c0c66ec71b42c92a05d90849b7d9903ebf301438e6a6233f52730f888", "DATE": 16574, "PIN2": 4293, "PIN1": 4294, "SERVER_SECRET": "219b859ec0c6068937894290bbbeba5b37589f9db0fc4a5ebedc81ba4fa732b70c70e4f08f7423b2056a2c30b6d5b77368c37c16d39194af6e0cb4f18eb1d12d1ea3ca7237d7098ed1e1f3d207809f450f2814458822652cb796d4287e2c62c101e18f90368125f9a53a7fdcd082983426c0f631e84f423dfbb23ce865001910", "SEC": "0422f9e523606e0083e44fc41c7ebff8b927a88f7dcb7c5215ba2185db8ca250d20622b53ace122b95216cb2d95737db2e1c5d6110e7bbc7207baa06e715ceb6d8", "TP2": "0418b582cdedc87d924a6a6e2041010babe4424c21c4cb2e1f393d5b96ebb395a91187e35b01a7a30514453a14cafb1533c3612bd1f382d0a2579591292f884f99", "TP1": "04233ac1d3584b4575133778de9d703a971edc1c550e6e8e64cd7c907f0fb57eb50e466f38c61437c9c5837e6a3b2eca9e600b36638ead48c38b13f840bc66c5d4", "CS1": "0406936ecdd6cd1f8bf3a5356ca9f8fae35cb8d7c46c94111db920f579256b0b06063a9b1438c6e22cc2a5844f400980839a28f96ebf396c853a73b3935ab7f813", "CS2": "041f00c8337d2dc0db20d480951463f1b6b11c21c7543119a0c0562983c33f1c46219f243260272912d7abe13fc38ff3135719a41c6408adeba6d9392ee03c644d", "HASH_MPIN_ID_HEX": "8bdaeb64d0b0a471578b99ae15ea93b617d5ef6eaa559b4fcf5a1cae05668e84", "TIME_PERMIT": "040b6db798b46f4a7b9f47b4cef292e3211247dc98c10c1aa7cfbb3ee72caee9a70fd17e7bdb9ccc3fd62218de73c59696fac3026db482d6411b885b2490cfb0db", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34335a222c2022757365724944223a20223833376564336366666164643234656131303933643033656637323666613063406365727469766f782e636f6d222c202273616c74223a202235623730663138303531633063663365227d", "TOKEN": "0404dc0fb2b08e02a549fe3e0715fe81397f6e7283f8f6fb9d947a824909ddf9690a3cd156ebfe0f4c19535be83d1b794fb4f3c57660878c03f237e63f21d44d3c", "U": "040e46b41bcbd4ee54fa26d6fb110fd0129f759bac297c0a9abac84170dcc7e94814c6a0d7c23fc78df6e4d3fbae4c7edb44dd3f011c14fa15fa1efdc8e82399bb", "SERVER_OUTPUT": -19, "V": "041ac9663e7850606f1904ba405e97cbe57d66c34e087ee764e392c34e9c3078c41c44ed7f9c1765cc6b78e9623e86890988cf847286fe0aacccce1aa4aa20270b", "Y": "1f5327a5bbf5f7312c4042504c4e05e21ffe1fa175d8eb0f51b31d9d6b59df00", "X": "1446a09cc89373e872afe81308b8f8317dd4ad9c7a96c8650f2a6f320bd85095", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:43Z\", \"userID\": \"837ed3cffadd24ea1093d03ef726fa0c@certivox.com\", \"salt\": \"5b70f18051c0cf3e\"}", "test_no": 102, "UT": "0411748533389bb9493a957c72aca25548f03765e46836d8084b2444a688d0bbbc2165337d0ce19ae5dbd5e2c5451d9d150c605f2149af2b79106a8ee7691ee9d1", "MS2": "0456625bc422c4c4933d185187365f368d1ffbb31b2c2381aeef9d982ae52665", "MS1": "16420f3a31a369916bbbe777b339ef83be81e5be19c4c51bb7cb56fb6ed3372c", "CLIENT_SECRET": "0409f65c9082687ee533da41fe2ff2ccf6e1d9b41787f50d0b1b8358b4c85af6771faed021bc847fb2eac9c30866e4304e8cae0575ebf5b811d1016ec7ee2aa30e"}, {"SS1": "123c932285624983c8c794828d4068bf4e0070d8728d38c4fe5059688c8874b70b81cfe080a83704477840b2dc0dda977d78d0348791898499defadd3f479aa61b6e1a84b064acbf2b9ecbdfdbe8215ccfe3cc0db772c8194636cda3c030cfe910096295edcb542addacf4636a22e8f927e57c605e454b4c764d028676a052e7", "SS2": "110ed8bffa90b0313b417f6cfb7325fdea576fa1042f99573ba1eb82cd95c9451302a8b444cb04044aadb5d620bcf62c1c555407670e6a0f3164c95198bf080d1193c6b85e3d53695e5fc94c208201c8f8fbd292d26b7693fff514b60ef31482223220879635ec88df53827028f63dcf71a0ef1ae781455c404008bce6df7e64", "DATE": 16574, "PIN2": 2408, "PIN1": 2409, "SERVER_SECRET": "083f581190b852d19955bd6bce0ea2ea69edf84e285fa12f053f54572c1c85330aa53d43c7f679f9322090a61950c0fa5567030550d4999727346acb4290531008c8a3797162f615fadf29951d5d7c33fb65062820daaa2824c4fe6bec38880d23cd81e1af929a2245f3e7ad093f9dc4ea7ee1d849efcd0aad614013de33339d", "SEC": "0402c2de4a99b302ddc45c9a6d2293cabd7e2ec5449a241b621d46c37d249ab9ff12e12519233b6895178911025b75c409ab722b19a99006ee5afe4760fac3f0f3", "TP2": "04000837cf49abf738480bb23ac78e4475fca4e3f95ce133ac2f877c94e2d3431607ab42ee57c8e975ba116bb2c26f60f031f342e1acdc111dd29605f7b55a40e5", "TP1": "04114cf6d213576464e1ba56e68bfda4810fa81fc4a3c53f4a41979a056aeb30d71f5a7cf24e1c05908efcbdfc1fe0f32be6efafe6be0861b7953054aa8f98a8af", "CS1": "041574c50ac297264a0d605a0e3129d8fcdf3150b1d8521315154b8e7ee56cde4d1eb3b31ccfc2e0e5214ac1b2784ab662b0c48396c3697b88d9c3173b89e4016c", "CS2": "0416f0f4c03c37c804c586ddf36c668dc7ac2434f9a5b56ff4a07a224b635252c809d19b58445c627240517ae1b22ea1816c6dfcf880940a82d23c72ec8d7f1a38", "HASH_MPIN_ID_HEX": "d02b361cf8ef872eb7a44351156b2569797d2f97b2a115cd8508ad6526fbb20e", "TIME_PERMIT": "0419ef96f3848b263ce44d3e5cdb8940c98806aeec41e4e8c58ed7df9872555927239644ef8e6678f4abf4add2054a6c525b7382e45420715cdfa67a61c6f64d2e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34335a222c2022757365724944223a20226433393864363464666135643361343133393061336662343738366538663935406365727469766f782e636f6d222c202273616c74223a202266613636306335643933323330343335227d", "TOKEN": "04201e341fd52ea53c95c7f2a7d6208571bf750aa1244a3ab40d61e325f45782a911d82a6d4a09d3dbfecd38427bec93608a69fa316f7edbe01bc2079dd2ce9134", "U": "040f3f76971a4e72da98e11b82560594d78faa8663598d68a7735653913ec7b1e815f8d7dd819717e86e1bf65cf2ceb630852a9c93aead6530ccd6c10bb4d9cc59", "SERVER_OUTPUT": -19, "V": "040f7dbe5ac47ce6a7958215eda2417b1becac26e7f646d34936a4b0b65ac6f8f203dd2652a61fba8d99be0ca758d96a3efe9cde66c97a760546e360e382889721", "Y": "0d0b943a796cece77f5fcbb3cdf29bd957b1cfbdaf4b1505fadcb91e789d0e68", "X": "137ef999c8e0879798432bebb9a1a04c2b8b6f826b98d3e63f6612be7f755331", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:43Z\", \"userID\": \"d398d64dfa5d3a41390a3fb4786e8f95@certivox.com\", \"salt\": \"fa660c5d93230435\"}", "test_no": 103, "UT": "040364375e9cd63213ef55a21ea7c38cdd1a813cef241fb47258ff4c2f79eda0ab0a282458adf728f7bc3e960260ea3435210b33f68d003fd26adfdd3defe65a3b", "MS2": "0de967177386be9297a4483e2bf688a4179229e48c8d2df4f49c96003eff7375", "MS1": "232cee7516f87222b8aab59de61eec339af20e4e44333baa1637f76a2bd6eeb3", "CLIENT_SECRET": "041e16ee1cc27f9c9875292b31520f9a7c20d68775b461c51bac9e20d1ad3405bb111c47607e00e4e4a33b39d7e7f7be3d6bedca967eb87fba38a914f8d52ed152"}, {"SS1": "118265878016442ddb346ce15e7028d8badfe0f7b28fcd753e44c330a0ce189621a04a911e9a8a22193c0748569bb47ce34d3aacef597bcda547cad492e5e1fd1d0d716c808a2b5fe37daba7acfccf5dece03238b9a09d7f6bed5bf2374321d0106c313b26563f9ec3aa1df5deb2173b45850ce77c1e0c5ccf2c3b117931f5e7", "SS2": "1d75c4f9a5f3e37a18fa8da73cf03cb0e776730e2e442551bcc7c58316ea1f5d08b7218bf188531c6d88a85db4a39a696a2ba1d510273b174c0f698d353928e8023f8b46b50c7f14b5fad20897e05a5cf564cc5a2ccdbb1eefa9b1933b02a2ee2209015fd5f64d64e9a997cd3e833d5b630ce68500f4e02e49e585c31952ce45", "DATE": 16574, "PIN2": 7907, "PIN1": 7908, "SERVER_SECRET": "066b4b03346328933b63a446b7a686e0a2ec53f779f6e8b4f1d1a7f717e21964084feb3671f414281c262dd1486a968c4cae0418fec4ed6a8e5eca561b2d0b6b1ef8bba819d144ad9e330d9ee872c89c827690e54d63849e78004fe108628bb80e1ea934b0ac25d374ce02ac31c5d89b1537b8f7ba371842f2d77aaf5514e00b", "SEC": "0411ce735782d9251dec7179b2c4e6dd617480422998d2cdd54cd5dd81d1d9ec0514b03862c07cc37b497f22d78160e01c644e162a5da97e927ee16b028d5ad939", "TP2": "040047b258aa171ab9d2b45113025f9bd90d6e58c9088b5cb8c19ae3733c1d6b741906f6db6a5571c0a5b184de9226a802ecfcb40475723f1411f4bf2d13e6babd", "TP1": "0423883dd6f2632ad0cb7773e2b3e122def96066626f87ae0f3a6c6e5e485854181c0b4af39ebeb240e4f0574f6d19a67fb5a82a02a47728f0b45c101ec0bef344", "CS1": "04034732532725f59ea6930f55d37dc6f9eeb97d96374973e979730af444d6e3a60735a74de4a3cbf2bb0eb0ebe2d78bfc2fd0e0bef37ef09448d0a613ed43fd94", "CS2": "0408fd7da382118b4406386b44bfb02978c53046b0952ab25cc0705bf0c1777b8b0db1510cc715ba1d2c8b24faa972568752e161159d4bce077f5c58f21656116d", "HASH_MPIN_ID_HEX": "d5d04f73cf77ef630fab6cf7b467189e8388374749dc8889cbbb764bf9adb52e", "TIME_PERMIT": "040b0c80a37f27e6b86e20d96e8a75fe7da42224c7d5d0e666df0941d962f6a4ea0868512df0b5dc5c08423b955ba960e05580262beb30fc2155f79a22fa4d9e04", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34335a222c2022757365724944223a20223032616465353236393631356133363131353334343538333234623365353339406365727469766f782e636f6d222c202273616c74223a202233373361613038346539653436623963227d", "TOKEN": "040a59cbd18e0215f28d2852a835f0e7686b8a2b53eba5c5b8596117fc18fb74030e0c66caf635a53e6cc84dd8f30b934232a1ead0a12255ace4c26c2611e15f09", "U": "04052d60a82da08dfd46e015487fb2500f31011b2f9bdabfa61930f9b67057c8651137d058741add7e3dce3afe848648b8e49fee95ff5065a836d5631171c363cf", "SERVER_OUTPUT": -19, "V": "0417dd02e69e3f154a2eed88550dd00e5659f89bf36d366db6a28365bc919d982115be759a5de32969c80f73fe0110baaaff0282389a394c8acbab205afac18ef8", "Y": "00b04b7cc30e69766435598405b34630fd57d9ce01ac5bb6f6ac7beab503a12a", "X": "0ea2a575d1d0a75985cf5d85350f5bbedf07b5086216acee48c29d4c02f66fa7", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:43Z\", \"userID\": \"02ade5269615a3611534458324b3e539@certivox.com\", \"salt\": \"373aa084e9e46b9c\"}", "test_no": 104, "UT": "0401f1756426c89ffa772c0bdd8e5e016ee39ea1bc89b19978a27facb0ad525d2e23f3c18c089918e14aab1e1f94037136f793b43bcd7fbcfa58626882aa22c849", "MS2": "198cf3c7751d199dfc2875485eaac7aedd25d771e55aaebf0a6321b8b977b2c1", "MS1": "0be8473700160ea28330aee1aed15abaa7e358b576fc7634f55e66189851ffa9", "CLIENT_SECRET": "041de1d21aea31964572976641f3cef0964e16804219b628b38720d12d10774258076a6f102140663413d4ac888b9008e6c08a70c35b9806a987d0d7b343eddece"}, {"SS1": "03a0ed68f4dd3726c25b0e9a1b254488d69d8acc377903f60c5884f249eb96071ac0da89e0f0a48fe1af607f4540e67ca64de3bba351169894774456dff9eb230bf9d32dec02bd422b202525ed2464234a5eef40758108399a50a749485541700b3a1dcc85447a17dd5166f212d87e9ff7dd8044fa15233a79563417176152af", "SS2": "13766f03d3dc109972bec68089eac82d150fb024cba43ef7982f3d8fda2c6fe11a69e4aafb3a2bc5c31718bfe3ebee22745a366676433fc343b411f4edd0e0dd0e3dd58c4e5a653dff0c179e90706ad873a9195f6872aee42d04658c231e791411e731092771182d8383a03e885e8dd2b5db502884efc3fcf9ffa78da67ccdf7", "DATE": 16574, "PIN2": 1895, "PIN1": 1896, "SERVER_SECRET": "1ac419792232ad18e437e65d618006b7a82c26a5058c42a6f0ab9e55211fab820599849a56d1433fa7884d639c46438865ea245ae7e93901752d8f367a006feb09f90d0fc2a361171b89974e91e7142e479e78fd84805bce1572a258ea2c663101ec484419905b1a711e552dae5a6f7ef6e27ce04ee5a49860ed94cd666c86fa", "SEC": "0417054ac072d6e5b026b28ac845dd62614c81f4467d7b1412dbdc260cf9ad702c1f4881be7928545d48a67895dff75e070dd6b8b3da378203aeea9ab83a1f6169", "TP2": "040b0f7712017b902f192b71d44cb46d51a519a8c0423019941104118664ad7d9a1c7c12283601480a2d2653c7d93341897234496f142c1060e64fd58d73a51846", "TP1": "0418021a9f5c1db7d742df24927d7a378bbdbcf9fe4b3079d97897fd36d3da1377158719c1c16ab47fa86d324c9f0c5a26ad7bc342fdc77ad4279ed4f9be4b35a1", "CS1": "041ad53a445b48f0c8a1c7ac97450431a73e7225866ec92091078d5f78dafb44042144b66cdb0f3c04b68871c2d1dfc4ba19ad7771bebc76dcccb3c762d5dc0a9f", "CS2": "0422477619f7add302d6f4ae3f7d91ddf0d7b7f785101a8f06021dce32c729a97f1dcba34354063d5c7e2cb65b19333261899c6f33a6ba2ff4b70ca1487a7ee8ba", "HASH_MPIN_ID_HEX": "1daaccbcc6209bf1861c3bbb0c5901f834ba4c5531f0d070de18918c5ecaa951", "TIME_PERMIT": "0401994cc372159b44d265ac763d238670b2ce406737668bcb184d0fd6bbea9e7a00d1bb603d4a395acc0a66bbf618e2150615332d2dd811d653289205235197c1", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34335a222c2022757365724944223a20223832376361336435333562643730613963636262306237616138343564643261406365727469766f782e636f6d222c202273616c74223a202236366339613531633634376134613635227d", "TOKEN": "0400aba9ae96fdb8baed51fac556762c7a25583a26fb6f07b5d95f51322e928ed00d8d8dd10c6dcc71d57952a5faf5ecc02904a25283ece3c910be9251ea2951ed", "U": "0407d740bae70207c86610178bbd006ce6fc72f4087f2310882bc5021df5872db21ff3227cb923b34408b065f7426a4d468008330f7f737f1f01f4cfa8c7953841", "SERVER_OUTPUT": -19, "V": "041515d0b1dc3c6c6a7601f8689896f282143a4fe1114d6338703df79d5033f53606a5aa3bb06b3fdf645f84b612b77c5d6fb07915432eb79c67ecff5a3955ab0e", "Y": "1873df3d6593a9e38da5a3c0c8ee43694586ad03a87906471b00a6f93d3d6d68", "X": "1f9c06871b00cc3d68219f08fae2444ea727286276a0dedc984917aae467d89d", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:43Z\", \"userID\": \"827ca3d535bd70a9ccbb0b7aa845dd2a@certivox.com\", \"salt\": \"66c9a51c647a4a65\"}", "test_no": 105, "UT": "041110d7bbde9fcc0f618ec9375b2e4fbeb30059027393a140d1c030f9a96e87c80486ab51afd372a086a59fb4ed7d32056a1de4eba8a6f7e78f80bcd14612345c", "MS2": "1fbd2bc08497100e61f81a6dd2207c991598cdf0de34e92cbeebba81a230542a", "MS1": "0578a58f0b0054a33acd271dc1506ea0a1ba8f22d38c03759e69d7dacd12ce98", "CLIENT_SECRET": "0420bad0485185402961a0907bdf01d63d5813b924e211b01a1f8c58045846a64b00c55e96cac27f830b26683b919c6cffe30fcd45330993d9ed0e66f6f5987888"}, {"SS1": "1fe25bed4dbf0252f7ba15133f4a19ce13ac29a47a28f152250f72b48e618c6e23c4bf92f819d9a086aa54b5b780c2f00e2a5b21de790f54ac2817aa6817ca891122c39a6bfd4133733060c2c22f2bace87ed2a9ec22eb1fa7d21c86ee4f44c01433fc339fc9dc61156dad9c51d340e225fd5ec6aa638c9d27b3d7a4f7a88629", "SS2": "18d8cf14042042e828d1764507dbcb65a382686e97369a3b9750bdffc0b4719f1cacf064ad5128d0e0177ce01f4b15e1139cba79305e08b10338e955eacdb7a503c3197a4d521e8f250e64a4663fba15091b6b64c152f85556709bd084d37f2d1b1d6e2994a78a08cc090788a4df4da2803b270de1981472ed83f42b02b223be", "DATE": 16574, "PIN2": 3899, "PIN1": 3900, "SERVER_SECRET": "1fcadbdc1572adf43e2e89a3478b3a55f77fb9802655465f09a1aa9ac94e17fb07abb43206aace71fa63d6f17ca773b1750ce42bf7260fe1e031ab35597b65491e34c5b8a72ad93f2276c53e44a790c6a97a5a00ed47efbfa7d779f9e0b7bc7f06cdba939f42ed51b9a41a87c8fa613b1a2e5279739ea03bd2e0893e53d9f15f", "SEC": "0423e4e79f61467e69c3ca7e87650b4eb15fd88d2d523f344c2f3579b2013be76e0d19d65315a2d1d2e45fcdf6ac3be12fa4b17f83f3c2b83f69fab48befc9e7e1", "TP2": "0413d6d848f11a72f41e759589fb3461a854b1a483f397eb4df807098225101ee123785f222df0ff925bf1946c6db4e0069a6a15748cd712a61741f419834c31e8", "TP1": "040e56f2a87c03425735664d1ed2cb0cbc2fdf0e6424769c7d9f904477c57f12201432de7f6d101c99352233d42472c069cd16398536e1118508523ae39743e2b2", "CS1": "0418fcd5d4f0c14c0a923d3200747849d4ce1e43ce88d4f6dcced1f4969b4054fe1c23a35bb506e392fe351be030a678ed2a777764d9d906887bc3ea9513c5e907", "CS2": "041ee89ba0618b9a1e1440856b03dd3ebc78732a1ae0a2e9ecbe766fa10db2b1901442486dddd9dfe27a6549b52b82eb2cc3440bb01fcaa820e6457ce8c4fe00b4", "HASH_MPIN_ID_HEX": "5654ae6593efad8d6122b1167780cd1c424b16777bd1c13bec6d65c97269a391", "TIME_PERMIT": "040520c57a74493414a9b7dfba533965623f15767ab6f5238898fde79c74227bd0133eae2b2e84419bb60df9eb86fffcb950c773fc0cfc05f0daf3c82cc860cfcd", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34335a222c2022757365724944223a20226562303164363664386364373363626663393835643333353633313764386136406365727469766f782e636f6d222c202273616c74223a202265373763633831633333356332383837227d", "TOKEN": "04223be6a39516deea4b6228e4bf73dab86f69278e7e9727e6bbfa8ac824467f4104a7298399b4c42b686f83433188d2e3bbb40ab24ceb594ef0bc442197266971", "U": "040908c026bc274b2737494d7f80387e64712dbeb16cd1669aebdd593bc7a1db7a18edd331ad779e803a17bf861b0cbe07868790188bf30486e4f0387bae1afff5", "SERVER_OUTPUT": -19, "V": "041d5f4938ace5a1f72a4c2ad0db7f7e4b7221ddddb860ad32215d3a6c80b5590c10a44d44e89bad25ca9b140b8d5b263c6e4cb91937014cb8d48b377227a764ae", "Y": "2193640131ff74d608055711242af420721d0c767871cc8be9b1439dbaaf90ac", "X": "02ec41c90ad8573303b06cf1a862d101e8d8d7c35552ebd779b5d8178ac33a47", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:43Z\", \"userID\": \"eb01d66d8cd73cbfc985d3356317d8a6@certivox.com\", \"salt\": \"e77cc81c335c2887\"}", "test_no": 106, "UT": "0419aca7b32614c1d64c05022e6b4043bf64fa46b64ca4519201ef7cc29618fa83192c2d7d5c473eaa93416706978c705c62b5e6ae2ab7691041208a8359d99c2d", "MS2": "03e1081cf37aaabb2b5abde86ca5bded1276efc7a3a9837089c642397be1d5f2", "MS1": "1d1399e291e6eea99b21553cbb0c3c4a5d00bbe11824cab429bda73f3b3ca6d9", "CLIENT_SECRET": "041a602c816cc2976c27e5dcb9316f932cfd3738b5c33046410a56f8fac8b7cf2f0cc71c31765d4a34734bad7fc18505d991f9845988dead97ced5ce814fc24879"}, {"SS1": "0f7a534d79678796f7ee4bb9acac406d7d1379cb7da78e2a927bea68e17526b4133957d48202299980b09a84ca2c3384b64078ed9fc0abe9c0e6b5cafabb4d950039fbf825e3089ddb52979fee155846befa5053903b76002f7f2af5d859d2a9202d653412b49b2c335442bc9f6c294eb2ba325d97753f5948c2801530392ad4", "SS2": "2130f702e727ae3216e60284fa71b3fa4f47cf77cdec89c635d20ead3ac955170bce9f8488aac25e1f01c91c1cd9d471cf0170e3d8911ee2d9adf69390fcdd3e1f63fce09e82136284298c5ddc5b0c631eac6ffa2887c2418604beb0512284de07ae57682695f0779dd2c1347dc4c9e29010e2a713cc63bf6864bcf86b2e76b5", "DATE": 16574, "PIN2": 2381, "PIN1": 2382, "SERVER_SECRET": "025febfc166733103f2e008bef4064a5659a838a616dfe203c99b2e2e7f603d6075bb539546a71c825f945b4899771241942b395e7bb65dea11a2953bd2905030be7cff589e1c12374616cf2f260b7e6763cd05f4aab7c480138a9186634d9650b359bf9aed34af0b378a2dcae7884bcb10463d8cb515900c59eca589f3595f0", "SEC": "0423553c58e6d3047328490d5b7ff8bddfa4153acff2e08c43e12a261d8859c6c70376fc775088db2b7977e05a9e8b185ed19f09f6907e14b925c72a5ae71ff41f", "TP2": "0409efb767aefb3f7955d841c3e02c3ec76b20a53c96c669f48ac8414b30da3b9801fa72d22c46d8b2b78c85cc053511dafa309eeb72a40f86c3322d62e13e1cec", "TP1": "0415f3cbaa43242525bfa9c2a91630103751021d26245cf6b150a724c96ec86e671ddebace92213f16a92604706d8d317710d8272a921c809076efd66cea833306", "CS1": "0413455f33d7b78ce0cfb3399e37efad6498fa708a250459385d719f506aa4a6dd1ab5a90aabf463973c4011f1156a81a24a18113fde7d347c1b17658fc2a35bd6", "CS2": "0416af833271eb2207002040adb3a165375d64884e212d3f402d043873e246c532068bff7c597d99fdbf260e2b28a8f2ac9f2b9f5f16572f8d35a3049153fc351e", "HASH_MPIN_ID_HEX": "5a0c65711fef44c13c1a15043f20742e26c7032eaf8e5bd3da8d99c5a7784ffa", "TIME_PERMIT": "041d80b972d0b8f483c81e27fba98631ab4d8e6bac18a6c9a16b65df4213d256e3059f6bcbba21bd3fe98cb6639a2b4e4265da9eb5cfe40db59dc6fcc2f8886d2c", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34335a222c2022757365724944223a20223735666363633930373265306664643433393966666435643230353261636236406365727469766f782e636f6d222c202273616c74223a202230663235393337316534626339343033227d", "TOKEN": "041c07c7af7a7b283ba6974c332a8a1766ef2a54c7191f688a3998f46791043e4708334266fd521ef09db10789aaf3a8e4834ce6656e06dde0d721078695ff29f2", "U": "040d5728c11b6b7de5111deefbb92c76fbdde13a8b12f9c200ef235b97e24d4eb20c96f14ce150622b4db87b403b9d257ef27b9a56ba2b7dea04146997a405f008", "SERVER_OUTPUT": -19, "V": "041017c51d230e10fd0bb23f052b37b5398e52054ec920f34694781440ecd4b2da0cbda3a8c6b7a266a35c58efa4ceb8b18b0e30360cd470fcb0505851d5e69000", "Y": "09d11d2221a0ddf534cccf63659167cc8bfcde534c9a3e0698d698fd98c3285a", "X": "1599da9d95b206a263b16230d99eca02f399b4e1fb79b01a719fbf6e321bea0f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:43Z\", \"userID\": \"75fccc9072e0fdd4399ffd5d2052acb6@certivox.com\", \"salt\": \"0f259371e4bc9403\"}", "test_no": 107, "UT": "040d59b13619e3d841768bf78c540089948ce2f00baeb01ea1b3f9814c27ccd4e61166e68398f08706184286ca268e67f90961e7b92e74aa5cbca28604dce926c1", "MS2": "1a762e4be078bc16ca76efe064a099b73de6a07367b887c1c321a82d5da4648a", "MS1": "14bddafbde8df8bbafcbd11ee388f1caba37022330cecc3cbc46fea5940c6bf6", "CLIENT_SECRET": "040a5a5b7cd96e56bfebed4fa4d2b2aa6356f04f5db7850a8ae589d63a4b6474540bd5b37d44eabe18c70409c2ea238d7d13eb6de87a0b76a00b38431dd750f436"}, {"SS1": "16985d0c19cf06eca6a8c1129f88554df9b04c8bdd3fc9bd94a0f91a76bd330921c05b10f83a213bbecbba5dbc412daaa11dad4d8db4525cf4c23686eaa1919e03832301010aeb3fcfafff87c27052b10724c82ffbcd5f8f1b9cfced67e27b010c33760f9fcadc06c8821d00571f153df7bedf8cb1174426ee7eb8e2e6da8b9d", "SS2": "0dcb257134bb481a23ff421936f211796e236fc65bf81f809ab9786c94aa52b80688e7edc63038f02ff332a9f708961bfdd1d4d350486a0d2b7865ca1c39e29d11323bb7693daf503b153c8fc0531699df0f83480078580f41f1103bc99709310623262766978d8daf73079b2e19df951d087c07f76ad7456a9a8d9e082fb941", "DATE": 16574, "PIN2": 3763, "PIN1": 3764, "SERVER_SECRET": "1db97c0049e07f03fd316bbdd8f4509cccc1726ef213d0ff8a206ea555c3d4ff22d81795721149164cb0aac669c3bc22c0a6ad88714bb30e1ef1af11a9cc5ff40a0c0ae9d6de5c29bbdb2ea229448ca9f44e7d89b3f5df716f386d1808651f71086736c3be48fc8696d960423e14de72e5fefcf669f95f50fbe9db02124518e0", "SEC": "04106e8562135feaca286c1981e3a3303ce2dc677a1012c24783c3741d99ca7b8e0fed7d39d64f0256be3c721ee40b8a1cdecf690525273c5d037d1f83c6d939d8", "TP2": "0423b61a097119d9ca95c2062be9f6736460cb3828b44125f2f8b5f86f3d9a7dd70023054de62479935874de336075f2f72790f051f24a60bfc0bdecf86a9549fd", "TP1": "040ab395b476d77ac711f2ff7bfbbd1e5af5de6f741e74f7adaa129544d30ed1b21a12a9cd7af36cb08b43b2169f739aee6cdfa6d96a343e69d9512c029900b2bd", "CS1": "0404679f5b388795b9c95268e97f62ec8eff637dab79eb97810d28e75cabb8817019b277149a42d8eda2730ad0c669b4fdf6a6fff8df268f998fc7ceb206b65788", "CS2": "0417957faea6ea669e0df26bb704e7b2788b65abfc49ff7e42493fc7da25d5f9481158075f87e0900569f710cc2987c5d5356bc5732251d388d9ed2fb5baf2e2c4", "HASH_MPIN_ID_HEX": "ce6f7c3e1fd098f05d6705414fca74483bd7ff511fe6f7a62853c363e4d0b435", "TIME_PERMIT": "040f90797b4519094b3c653a905fd44a1f34b952b91f853eeddee0950f64d8e62a1618d895e0b8701ec32448c142572078ef76682759f22b43750298ba532ff92a", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34335a222c2022757365724944223a20226666333530366262306262656634333433383934366439386331343534636439406365727469766f782e636f6d222c202273616c74223a202264353264353433343963666636643235227d", "TOKEN": "04208e93c366ed21baf67d99ed401568c12a4c423271b971fd40b18ed414de8ebb1d6cb55ae4fa72f539bdbdc7e6f06b311b1ee44236fa47c444e93c0b1ca8399d", "U": "0417350f434860818d1e8351654d4cc93645b14da64c4a599e4fbe026cbbe737d51fb4c95ed9a0fa0227ca355616e7dd39b6d5d0d4f09ab8c06b5bdc2c0f7a4996", "SERVER_OUTPUT": -19, "V": "040f27eef8c8e3e20226226c23c66a9265593c6b7e8acc20b6d2290c1acdd5691514f7857b8f17e07588198cb3fcc636c64d6a73be559ef1b9cbb3d541597da3dc", "Y": "11926e5a671740e6676d8b99a9f0fc36ff2d4c791ad11aeb263a45eaace08e9b", "X": "0ca30838b80b1609a17cbb4ba752a57538cfbce357a4e35e65e2978d7bfddb01", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:43Z\", \"userID\": \"ff3506bb0bbef43438946d98c1454cd9@certivox.com\", \"salt\": \"d52d54349cff6d25\"}", "test_no": 108, "UT": "040033455e9a99c74e9e2d8dfc8906469c83b660434b114e89642710cca4f92dff086e49a2e9b20b73b041e446bf71ea1b2c47754686a3386d0bcbe55836ed4819", "MS2": "0e71c192db72d6795e648632177538119522abc0a0c1a0a9aaee79f18ffea398", "MS1": "10acae93ac55c4858f8f1fe157ad8dae147e0de9adcd600b8615c57b6e093983", "CLIENT_SECRET": "04107c2954753ab822eeb008529608f0fc3351920ab68c20e155ad0392efc81e3c1cf9cf33e676effc2cc0b9edb657459a41e11f1bf61000f8296298a44466daaf"}, {"SS1": "04ef133d09c97c08ec2e4992a4abd0eef995dcb7831224115a79d9e2e7bef9bd15e0751faf0fc56a8be8432bf600858e9db7c607247fe5ae30e6552fe03b53321ef34bf7d1d23592db7aff1de8dcc6f3979ce3008f8408a0c125bcdf0c8b3e032391f218ab7ce4d19ced932e7ed0d37bd2834fd0f4a36b7e56ebc0a4b66a0026", "SS2": "024630d1003af45e97f73b6214a387112934c86b505ecd2139b996038ec20f3821b84c83179fa4252a7e0b865d4897dc7be4e69adde50d7972f4714db4d284920474ab278c89a4bd7a76d8e93ee065d15be7bd59c76bf9d686ef5008d2a8e0780b2b9e7ac3901a55de3a85b371c13fe08e0684d4e76d935be79162ca610b3739", "DATE": 16574, "PIN2": 1965, "PIN1": 1966, "SERVER_SECRET": "095acc9267b3ed15b03763679c23bb246d62aa4c56e1d4799fc5bb80e5c02b17013c1a0e81184060551da944cd23da4fbec7814eab0a010b7023ef7e53c9c9540bf56bf132875e791d27ed8b3c2502138d23974113a9653d555a28c7c0fc238b1119af116bfc5d5fe43ced7f7cfdf0507ccaf2d1846f5bf3fc6fd29461592606", "SEC": "0408ceee69b7763553e8283588751e9b6f99efdca0ddef145bf89e67c5b7c1ad40200081ebb0a3e0cd82bf1c18e8af38de714e5c5ea94c3a4cd70f5811ba05ba78", "TP2": "040e93d1709de0b115ea3a00aeec61ee9448fcbc00ad6a24b4fee5f0782fc63a9f03c80d1786b48a00bed720630a989baa23b8a4f0d388414cef44c01887e597c4", "TP1": "041d8072ee07b17ed6828e48632cc4310d06a167c1b4fe852090f64868994d30f602fe557d6164ba4e077334192233c16562aed3d274e54a18c5b9e2d4e56c2945", "CS1": "0411df3792239b69d1896b7b62897ce1116cbe1390f7c0320471595acc1f326ecc190bd8fdb597f3e3e8a61afc0ecd106a743ce99a603d5f54774d8555408a9dae", "CS2": "041729f94107222c4a49b53411c35db345b8a00b74344d73a4765c0f391a968ca70da35db513944bdf4f3918c3fe76f2cc422dc99933a1655b249a96a8968c39bf", "HASH_MPIN_ID_HEX": "b699f9d34d52e1edc989a617b1804f3ab319d5d3ef187619c3bcb91b55eb8e88", "TIME_PERMIT": "04159d8a550bb1130f9efd49b716df16adca660c6059b1703f85b1853d7680499b1df87b3d1f3b417f108bbcdaabb46251f0bb4eddcd938a11b6da0a655ea40bba", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34335a222c2022757365724944223a20223365363864633331353662303530336533656538616663396636323131653135406365727469766f782e636f6d222c202273616c74223a202236623566363834393738353362636361227d", "TOKEN": "04079625609428cd9f594c5ef9a657444ae2b76360a6e310799822348e10d573b50d9729b5365bc87b881c64264c70a6145fab73ba26e299f132c252acc3995f6c", "U": "041052d3835f06f06e5fb1eb781857f7cdc01041013869afa0501d031bd01cd38602811403acc03017a2d4a7bff820b95684c365e5af10e924fc0f87e7d9e73c0f", "SERVER_OUTPUT": -19, "V": "040bb916b093daaf1cb128162ec4749a57397297abdac40131caadc042abb57eb31a16e91450c1881b4ad1615c2de296696cdec400e842ea69d2d710d83aec5fb3", "Y": "0f5d00066194f2206a0eea3a13526273848136b686820a4ded28cc1c40d6b079", "X": "0b26933a5569bacd42b0fad9288caea07910e4266779a037b01f880f15aa2b23", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:43Z\", \"userID\": \"3e68dc3156b0503e3ee8afc9f6211e15@certivox.com\", \"salt\": \"6b5f68497853bcca\"}", "test_no": 109, "UT": "04214c90a02921f46cbe4053d081bcb0e18bd05b920e2651a84e15b90cd8c1ddaf160c618e24a57a905d7059418a2a88dc54898c2991c8baab74bec183729441fa", "MS2": "0619e9a7db82ba4d347c8cb2b960fce206866fff869d84a01b9858df3e83905d", "MS1": "15caa342f8d26ce9b0e79d6fad862c77db6eaa085a5fdfd6a528a288bb7baeeb", "CLIENT_SECRET": "041282a10d67c065d8e19af512bf90f449119523ab7146c74b417ca973054cdd270207360479674a48ada3e694a63d8ac9526071f2b50378aa403c4471e30a5c47"}, {"SS1": "1903eb58d72cb4fb61f71c9fd72daab797b19adad941f7c9b6f9e758b6d272c1085d194d96913c30d57dc77f67886a145661f2313ee6a05d4c3c3dd3f686025508fc9efdcd47847874d474fd8b9b0cd359eba93bf2c45f75873905436e2c16bf1ddfef28d28da382f2494cb2723b62020321cf88f187e35e61001dc5184b5b63", "SS2": "08292524e92f0128d4cc9330a6ef61c8e990bb6e149c19b10cfcbfc5ce37d4161158fe58de44fcf78ca584f483d7fe0c5d69f6f52ecbf7934a516eddb72398350cd6e10cfe158f9320747dc4d8961775e5d6c0e5cf1f28160a99c55598a9d10e0b8549b42d35509aa75413512cce6e5ffeb9d11e8b3ec0f2e7009fe565cfed9f", "DATE": 16574, "PIN2": 2262, "PIN1": 2263, "SERVER_SECRET": "1c6e4a04accb58de726d8b4883182cd61d0e36ca0e6bda93299df229be44f1331c3797a9922edfe4d150623c83801045785415aa612e0623157d280caf54655a1433569b8087a743ed1adbf023847c2265bcdf01cc793cdb7758217e882125bc0c191cde99c4e7fc0ff58c7f2ccf5c505e0f4979ca88c3c59cb5edf1c3e20939", "SEC": "0400c9a2af348df0b111644f81a705a4e9c90216b0aab599ae59170385e3995cc8194a578f162c99f4a57df5bac8bcc8d5c4596a289632d1cd958f4d63a738a2ca", "TP2": "04154ab5baea5855c1e647e94f36dc2f3a34f13507af34cb99acc89edab8e187440df6fda2eee71d2506f2df85a155fc2f3fd67fd71fd3a584a4b6fd76ec43875b", "TP1": "04222ab6a15fd3bcbe4693196e699e9fc458a22206986e1df499ab4063eb1a5dd71801ea78482d24354fa048dc8b320b93fd87be88d4555e38a4ee8e4f2446760a", "CS1": "040d2df2f66ad071728b6e76ffe5be7af0a431edc0e764235733c37bce41cf6bc421a0ef6b3688e5cfff35f0a3bb8c604081934f898c04ebd28144013b03e97ce6", "CS2": "04118927356b6af70c53c79bfcd0fb8dc83b8d26b59a37a9f312ebc964c4233dde1e0d6f3c98309c34bf6240eb5647ba5b6e15c11645a426aee0ac1275ee725db0", "HASH_MPIN_ID_HEX": "4f5a571d6af7d3e6cc390e1cbd944cfc03a2bfbe06869450709cc4e856e971b8", "TIME_PERMIT": "0408f391fa281a7eb6ea50621873183fd5ba870e4f9af929be2038957f394cccd004215c94971ff37eb89ee82ab43d90335509b1ce66bdfd9db337bed5607257ce", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34345a222c2022757365724944223a20223338333432306437643830613064346631313565626665373137396435333763406365727469766f782e636f6d222c202273616c74223a202239363065653631356639656133373535227d", "TOKEN": "041a0bc8de55372c51515ebfda994992ef850ab215d2e347103c5645a846c1811c13574674259921761e6646edcc5bb5e36183dd9c308dbda90a7c2ade02aa68bc", "U": "041404a4459dcf4883f9ba4a250b47008f9917d0a74a8eea49a5f5e26c9e07077604d119bb48cf5af319767ab5e4f958ee1ffbe6b6773ca381b17152ea344f82ef", "SERVER_OUTPUT": -19, "V": "040666ee148aaeac387d3c08536eedfaeef93c70d6397a734487a7389c05a3cb5501bad7188a9e541e2964477c19b0fd8f6b6c466e6a8d857030e2df889aad2840", "Y": "23d7d4be3fa8b49ba623f69d2a243c04d480faaaec6de1640a14c4b4cc167c80", "X": "0556e7df71edd9862f89c478ca6c0089f28f27eb25fde61045e6d1cb77d6ca04", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:44Z\", \"userID\": \"383420d7d80a0d4f115ebfe7179d537c@certivox.com\", \"salt\": \"960ee615f9ea3755\"}", "test_no": 110, "UT": "041bbaf5fc77c9aef5f86ee2f05d9773957a44e4da9bb2d88eba30f161b64035b81c237f9ae47752679906a52dd32085a53db81d4ac94691036a5b5837cf59fc86", "MS2": "040d65661f069c3e51727a5f25ef12e99c4df2051788842f1d752fac0399525c", "MS1": "22591e1ce28c74eac3583fe3cabfd564bab58f9d425a876aae70d5303b43fa71", "CLIENT_SECRET": "04150827142aae998c60c4b063ef3d06d27dc5bb283d311a748be885e7256666cc01ab06c30aa38f404a7beb8909bfe92e5d50a6707d6f22d4db8f01ef7a14c8a6"}, {"SS1": "14a0e6e158dee0d7099a5955d3c909aa42a222bc6b3b999d32401bbb2ae6d5ff17a0d1913e3e2f1aa64b40850e13f858935e0947d066abf0deabf2076b07991f1efc285f42aaa9150795282abfb3c071ab59a56ba63249b3e2790317039bc6430032eeadf5f06fa68a8427dc1b7b8a8f3883514d62ded71f3e2ee9fd6a7d7c25", "SS2": "0c3574777196bcb786f6722703743e2941ae892dd11ed285901db3a22db0c15516111af6bd03f2455da31c5db8aa9652116808297185c9fbd549ca075ec883150b9cd388c510ccd3278e9b31f28422aa5d9529f0b249a923be41b33e265d250f0b3fd846596ca90be80d8794b5d0e50d10dc8a9970904af44e5109376a5f63d8", "DATE": 16574, "PIN2": 3289, "PIN1": 3290, "SERVER_SECRET": "1ebe7f1e3e0058036ff6705a07b588473bb9584724e42d4820c6bbfea5d146501a52be7789efd34236f7fdedd9fdc131f6c979ab56448768041ea8b057220deb1b25d84982697be9dd055f9f9bafd1a8fbdb7429b70f278e9cfa9a4c397bf43a1cbd56971ecbdcb98279680d82e91fa309c75a0ded254a36716b20e50fb1acb1", "SEC": "041d13f8e7c4517eed2679703ef2f2bbfc418ad7bd00fd0808f56aeeaaa3376fd308f46cedeacec5ebe6b89b2acb7518af9af296250efa43db6e8bfbee98881b04", "TP2": "041a46404b2f1c7b762b172827ccea902d58037ba5e5bbaef0414f8a6ea7dfe9af0417b50e8a42cb234efac16a6b2494bbdfa5a24eb5f216473d44d9b1630c948c", "TP1": "04235b5b238d672ffd59abde4110ea1919904cca34478a0d3ef4c6fee4eca6c8512072b59c9bb7faa88bc5c06dcb9e58cc1ca3213434734856591a9b896991a14d", "CS1": "040c677a2877b5a5b332e0a604d0b422b99b165a3d8b468059d0aee58679e629110c3cbfcda3277f30ca542a7cd6a99862ee9f057d16185d2e32e97b153bb61f69", "CS2": "041711e89b116aa56177e049d8ee1f92bc4f36a959ce5a1c8991073a6f3af899ab01187bc113a18f1a5eb00211293b141dc4d72c9d583f1a036934922e186f4307", "HASH_MPIN_ID_HEX": "371303484f023367ce719d398881c1668f7a6637f2f9f19f095412bf0c6bec6b", "TIME_PERMIT": "04083ad0a29022b9ca783cc30d5906f5eea0dd8ff5bb7d9b965768c2ad70aadafe1741e216e6295ea32c0722cc3b97ccd0a485e9e1f36df14ef1985adaeea29e8f", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34345a222c2022757365724944223a20223761613039396637646137366465393232353865316162633666316363353536406365727469766f782e636f6d222c202273616c74223a202261623336316133346162653833343236227d", "TOKEN": "040d13f47d0c93e20c3bd110791c759205350fdd3a2a91e1da104d5673f4a827740028e80310ead932a040f02799a9b852d544faf75c426523aa8089658cde26f2", "U": "04037a02ed5c7cbd3e677df8b20532a15c51b73d451f34a3e852b6c067e74c2d8213e987d01cec7c6fb74fb5ec32d4c9bc4274362259453fa339543cde96f9c775", "SERVER_OUTPUT": -19, "V": "0410401af3e29347f204cc05ff727943c11541cf2756435c8e1306c5730ef5239a2189cad062fe46e31e4f8e8ebfba7146a180480ec72c8c64d7a0a126705166a8", "Y": "13005f496b1d391e1fce79750f303bc24dd161ad552b29b0b7177ef05b8fc0e7", "X": "0825363a6c6bdf9754a5a1ba2900434e8b7631943a529e587d3a2a28102b263a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:44Z\", \"userID\": \"7aa099f7da76de92258e1abc6f1cc556@certivox.com\", \"salt\": \"ab361a34abe83426\"}", "test_no": 111, "UT": "040b7287a88ad98202f12b1b76aa71abaf90827f2a5c682f4c53ff41c94b11150d0cff80d18106af5e6e669807112c99feb3a768b2ae1d379d0b554e34a72ed433", "MS2": "0d64f441906f137fcb399d36fce4ba10770790903e579743a4beb24bc1a0c4cf", "MS1": "054242cde188621955b4752a6b41977915e294dab090a1309cf37bed70a5ffaf", "CLIENT_SECRET": "0421155702ca40f15e0ca37b00d15fcc028e0e65b1de874f519f6fa9a67dc7084f0e0f76aa9f699ebd53b519f6e3c16c0b2498e2b7dfc714badddf1fe7ed1dd8b1"}, {"SS1": "0e0fbb8bea7d5ff953c46d70e95b71933de3972f9218841033933a1c1c2a1d9309fae4085f22fa843e82bb2ba6354c1e8f7e366cb584f308b05f33091cea82eb07cccfbc14fd5de6d660b70a8d190ef8c9e164f659bc5f27b24c5b3d99be5ccd0c77970425750fa1dccfe14238793e3e24b8ca148d482a99773ac20c68aad6c1", "SS2": "0b5e340a5e34176abb49852e5f6dbc01374515c237e8d8f04531c3095e2140de14adb133a038621fad10a2782092dbb813ed6d03b2e1b3aca62b8fc0b291d3f801b94e6428c60555ffe7724a3ade9bff26fa254a39da4a4197c17beb94f375c601b961cf1d2afb2fdce6d0241e0ec3f1ac2052695fbf109403602ae33b13e8ce", "DATE": 16574, "PIN2": 9054, "PIN1": 9055, "SERVER_SECRET": "18bed93901b13b13efdc1e91c7fe63775d6ecb4a54934344a98152e3c1b8154f0fe28347798b37611e6cb374901ac2f48eba672972f2bdfeb898eab7a254bc9e22a9957c974a05b9a0b66fd0ae36d239d645119ba02e4413da621792fb75e0121cbd5340e25472d508cfaada1ae9597f549d4366d85e4b508065fa98853519c5", "SEC": "04135a8c2600c1f4dd62ccf8aa97fb51cf2716c0c2304a84790faa679aabc9096f14872080d15337b44d7f5546dc34b6f6102d18128ebc87fb3faba58ca967af1e", "TP2": "0420fa53a0137b3e648ee84db9292c40149735f704d30d1a117e5f2fd8882f1f4119c1785850235966728d493df676aa49a90d7838af5e741e3e6cc9654a6f909f", "TP1": "0421c58326f8d04c87e4b2dfaaeef1b9875f342979ab794755d590f7af845585cb049e52cc252317923aff16c21b482b05b6efc184fb22ca9e36f3870d7095f4bb", "CS1": "041af3201f8ca56904c82e03230de961b74a23f91ccfa8773711d8deb277b8cfb409fb4a0a3a103ebc6abdb6ed2c9d3f1e0d1dc34696b2d9a1b835e0df643b3bc6", "CS2": "04065a3d330fc2339ab32118efdd226b4de4522c9208b7023e6b21ec7ac4eb638e18c0ae2b79683aef6ca74977f0eb78977c95b21bf41ba901f47450a333f97a17", "HASH_MPIN_ID_HEX": "80dd7252fdfe4d70e1652dec323e1121b589240f8eea52557f7ac8547663083b", "TIME_PERMIT": "041889483a35d694f2506dbda141356266e45d0ab8cd012128ae17eccd17be3e6b015b4267f3f5c9d28f6abfffca1656a96ec2ccb9d809fe40b91f606d41e9b770", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34345a222c2022757365724944223a20226538663738363534343464353339626564333330646665396335626637343535406365727469766f782e636f6d222c202273616c74223a202262666535646665653864613036633136227d", "TOKEN": "0423dbd8d7bf400e6b9c5ccbd5bec751beac35d9f78983b0801fcff790c5f074da032898ceab35133f52cd94c408d86e1cdc61e69ca458d2b81501c63e3cc6a8c4", "U": "0412ad59f8906822035b7aa4e2769cd8428c45d7ddc61880a64031aaac0eb868a70b9900b0a02a1bba16964c03e60f6be6bc23df307580535a8d8357d36c1d5db8", "SERVER_OUTPUT": -19, "V": "0414dd564c720c93f3ead633cf0e2480a2a5b957c59742aef2b90629506640332b21d11645620070c546cdaf08c457f4508d2c56007f36de6987d764bf483ee14c", "Y": "0becc3d11fff2f74cca7a99119e9f8bb004e029655c24842fb789a326f2768cf", "X": "055b0298df67f66a1bc13bc63f21f0beb9a38c60e00be95ccb5c7fa42ec8fde2", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:44Z\", \"userID\": \"e8f7865444d539bed330dfe9c5bf7455@certivox.com\", \"salt\": \"bfe5dfee8da06c16\"}", "test_no": 112, "UT": "040b484849a13fb4afd7cc3aee3b62342910ae6c16f2da0636edfb3e922483f41b220d3b581f2ba7d2dfbd50531893498c62cafa6a16263e3779558a4ccaf6bf00", "MS2": "0b2dd4dcde345c9886b884ba053edfd63f6e5388b8b91b82a8240d7825947910", "MS1": "1f142847222c8c4dab4f5af09a2766839c620edd242bed8240396aee3e721797", "CLIENT_SECRET": "04233a326ae526dc08c819e891147ebe335ec8c20f0dcc26f0d28e09006f60c4970d327d8b6f5b9b76475ccd92cb36af72209bd202684c29a456843c45e20d4659"}, {"SS1": "09feb76580a618e9f80bbc560cce915e9cb9dba0307e659d12a25a2aeb11e41414780a041754ec9485b0ae34f6425c4f191506f0811a63f3534053704f01f3e919962f8159729059eba8a3fe16ae164b44416b4d2a8b079a79c133c737cec9be0d06b2426171b1391097396c1753df6753c4836e690be9eab7e74266de02a4fc", "SS2": "21c0ee951a2d9fffd833c72272ff0fba032736efa38957d4c51b82dffc81ef1307f25050a349e5b05519251440c9b3a6fee801f02c73e9e2959a2ffc67ae489a07925be255bc173777b34b878e79f0565c4cb50a530d1478967da3e400bbf43b175ce1c028389b6263d6bda76274cce85c2985507ef90fee3bc3bb5f715c0263", "DATE": 16574, "PIN2": 3888, "PIN1": 3889, "SERVER_SECRET": "20f0e763eff231d013252ff0b5bf0c61722afd27ef7d7b61034505b3b8b63f5d20b5ecc5b71868267c16bc2a4760c6c71c70ca9b07c6550c08b6a3b05cc48b5116d44c3dca3883d60c10a3a70225862c6c948df50e1a86b1f03946d2747ce51d1db3ba09befdc99e362f4e398afc1e0924046c48853064a6454e1883f508287e", "SEC": "0423436ac445a628f576ee561faf9692abe1e1bbefee9cd03c77a715e44e2c6a4f0d09033fd2b3a2fc3aece384ce65318f8786c73fb891c18639d81af7239ce242", "TP2": "04131b1132ca78e33b29a5521b5cebc70f1716ca2c8d4c5b0093220677de12f06c1b7ecf2f5dd11b73a5c5890ecf46ca6cd7b5bc4fdbc32b0ebf1b7e613333479f", "TP1": "040109bc2ce8516d5bff320ca8a488bc896dc942cb2fc647dee6e8639ad49f58c30e89bfffb94f2c43571f17ea45c748196151f9c5dd698b1d2893841490fa897e", "CS1": "040d8f2b8cd4e0a146aaca11b0411893fc7e57da2e927b4d61b4226769a434711f0b153b0a5bb5e820c905c6e6df17f63e0046f7c09b3a78ceb4e8b529f68b1b27", "CS2": "04098ea8f7a8468182c263a4ea2a8ef9c56327f2b44490e07a7832afcb80ab87741954fd854006a19501d30237075a86422accac49d0d3a8b9849d3c531683b6f2", "HASH_MPIN_ID_HEX": "947bca635ca618b9b70716218004140491f87a61bf7731c30bad71a3c050e956", "TIME_PERMIT": "041815cb16ade3132281928f5b632c68356d621d65c60b913af5e96f2a2a567a3c15b50749410e71a6fdceb9c00725dd4af654e797a66d630882ca0997e136b48d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34345a222c2022757365724944223a20223232336339346265363432383939633131323061373639313764363430323731406365727469766f782e636f6d222c202273616c74223a202234336363626361656239303066653734227d", "TOKEN": "041b83faa1e3cf65143b28930944d5c5975af2a90b877f756f32c4fe92754a463f1382e6679e46428aadfb3821643402d5dfd413b205c7d762dff6be8f300e095e", "U": "0411717865f3a1a602368732481978403c08097300b55d7027c5f226242400f58a182435e8f94642d62ea25e4b21f166298e178affcb27a40e81d018a7a84f4d5f", "SERVER_OUTPUT": -19, "V": "04239afc5520c7e353ce8156c3961dd321a02df02d3af29b4ca7e822840bc6a1501cea7baac1b6406a8932fd6f42e26c987007186a78ba398a583e403c900dabb9", "Y": "2163b8587ac5d60843d766952a9a1eed559982dcdf260d917cc8bf05bcd4f64b", "X": "1605601dc37dd9dda8cd425788e8881a5ba73860851a7e683e33313ef42e3753", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:44Z\", \"userID\": \"223c94be642899c1120a76917d640271@certivox.com\", \"salt\": \"43ccbcaeb900fe74\"}", "test_no": 113, "UT": "04178976131fb4395e2ea090745da8ac87716286d9ffa6f97d97ffff02f924a5f123e424dfb0d7b1f8d45af0234827faa71ebe860bf9e559b02f9e043b3c31e0d5", "MS2": "1c0d96d843f934c88031359af28472ea0403d1e30ff961cf71151d5c937090df", "MS1": "23b4903d41053636f3bf59f521eeb8081c8bf5e067c0992b6a95dfec38989771", "CLIENT_SECRET": "040b92afb3eeb6026587bf32c7b9cf4fc31b05da4e8999f482c9aeefa89303c8791ddd75d6b015976fffbaa1cf999242c4bf14d244a5a3f7469171eb484708a6ce"}, {"SS1": "01dc340e7b6ab29ce4396a96f790175181be52e3481a5e76d735818deee90c171785b2e442ade721561530fe9261582cfa6e4dfe2722715c2a58a591c22c470d0eaa4aac727a4b62b81ce739cc91d28fc7d62450beb6c4cac67d937244a31f6e0b074679d6e50533414d8941b321d9ecd17ae8ed0230f3165b4913f2b0d402f5", "SS2": "0ecc3fad682c930e5a87a0510e0022ab0c265ec34048d44691b33c4767e3f4c420a8f0ec7784fd503d2b1287f5c95287aa7c281cbb0e2a8711c4b201d6eff7c31cc80d188192527d59e4d75f915fb7f0253446608a9d5acc0af2970fffc57d950251a35083d4dda323afbbe4b46a8305f9abed060540d0fc9d005395c5203d82", "DATE": 16574, "PIN2": 8289, "PIN1": 8290, "SERVER_SECRET": "02bd3610049ac089a23f49d25518711d54ab82cab4d324199dd40b6da6b5c3bd00c6e3bc21f352cd4a7f167f5998389217c64409b8304a57dce5fa3f3922f2791e9120fe17bbefb17638d89ae1f702022d4b27ad33bef7627a10f8aff20e86351e52d2307404e356ca87ea020130ed09617f7891107e4f6ea97a8dd42ca87969", "SEC": "0403f3fe8b0574c430e4ac0e3b4a1bda20e9c2f39f692ab237dc174f6b00cfd76d207964ef52cf8811010e7df3a926d74c38de697138d416f1095223d5e2698d13", "TP2": "04127801d48e1c52de565c50b0162b97e2f2cad9ea16c42f376881b1d609ad4f3803aaffdf6ea2d243884e7a405877f75560c6a6237261eac2748ec6c59c825784", "TP1": "041a79bc0ec2c7d973b52c83d7c9951cb480c64d0ab0c35322129b392a25ef1fc115475bc6c4303bdeca7e298dd05985e27bad8ceb2ca9e2e68cf1184589b09106", "CS1": "0406d870eac410bafabf74c589d5b25d94f1271e783394611742ceec1cb5e5a9b108c56958f7a36abe8bc85dadc02f5370933655cddd70da1c6d7363e372bce71e", "CS2": "0406ec369f2a66a455fe2fabfecb6bcbed0dc329c1f792d1eeda4b5fd53d228c1314da8bfbc4b82b5a74c01e81aa3f3fad728cb7d54ebbc54acc6d874bc10197c4", "HASH_MPIN_ID_HEX": "c65afd07db144423ae3822d2e695d6147c5645df34c1fca6fdf626495fdf3103", "TIME_PERMIT": "041155ec4e914bfd232b25a1a945077148a66d6b36563ff96e6f0b8f61a84577b713e38f1cd845767675dbd4f633ed032879f39a29fd59f54ce1f87ac4dfaadaa4", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34345a222c2022757365724944223a20223937646537306330616332366538653634613262313264363631356164663937406365727469766f782e636f6d222c202273616c74223a202238633065626133333134633031323537227d", "TOKEN": "040fffb31e5cfbccfef443d47bf20c900a14fd353d48f4e6510016179b711a80ae16f44edfd0a44a7bcb88a805ea91d9de2012ab8638fa2b7609173dbbbebfbd39", "U": "041e9879c841f81487519437df7d3ccc93500679785157801d9ee66220bffb93701ea78ab2f370695cdce77573ec8d3f3fb2eeefe655492c0dcae545fc121cd406", "SERVER_OUTPUT": -19, "V": "040d0ba48422b0abd5fda91154278ddee7f7df6e435f2d77d5018a50439cdbaecb0df1d9033dab90c0d74cf1f07977b2636bb0ada200530c89cf75b391390461ba", "Y": "22b73ffc88b0d4d69f792a18de2de9b3e07f10aa1e019e90ee1351dcf5a6e1a7", "X": "1ee5c1711581861b1bd0b3e5a32c696bb5d22151b65056dfe175ccc1705a34f2", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:44Z\", \"userID\": \"97de70c0ac26e8e64a2b12d6615adf97@certivox.com\", \"salt\": \"8c0eba3314c01257\"}", "test_no": 114, "UT": "041860b2d41d5849fcbf5e05af16177c28d06704c25cb2112f2fed2cb20dafdc9c082868e22dc50e603eb1301e0c697250e8966beb42aab3c4438dc9b17d263e67", "MS2": "0de016f22c119e22dc6d51886f3a12dd3626841a7301db5c0df8db401ba66317", "MS1": "1eba940066b3e2ca3650ad315e6ba13d89cbab164547767b9a5b76cbefea0754", "CLIENT_SECRET": "040269f2a402168f7d24b95b4a5dd9598fa897343116a7dabeeed0e9455361f56c0dad50099cb063aa0931ad0b0cffe0cb88b32e373c464cd7a2ffcba42df02fc9"}, {"SS1": "0c42a9670f8abf35a27cd9d8e191a42dca2dd56fffdfcfaff4a2b981e6ed3dbf076b0425750e889bd778e94c6937be9e00362efbb6907d637948cbc8d7f3c75f19dcd6c793ef0a33c61eb1d08274ba5171541c3ef59a10de7478190976b8dc4b0ee70e84744bf5331a10c130a3981a0caa76977a64a6c4b3da21ec95bf335665", "SS2": "0ad4bfa10120f94b1614c01df4ff80e014b57fe2ca0d1b9b8249b688f101362212eae04df7ff85547f35c94ea697a3e9d5c456f27a3e0a9d5ce8c062b3d0d5c41c28f1d614fb3b6483521d299f604ba5c27f5bfde655c41efe0facdddf7066e7066011624ad141cf87c99073d39ea4013eb6d5bb0df992aeadb0819913598641", "DATE": 16574, "PIN2": 4685, "PIN1": 4686, "SERVER_SECRET": "1c6b77f32c1ecefce5cf36e6ad84c08fd537773defa114f5c34a7514c36e1d1e0d2cc97916ec4ba1416619b7e3d82951501fc6f29e73fad51e132ecdcbcbfdfc1406344e1631a2c4c9f9ea9c0fc4be4abdbb569ab9ebe8bd212cc6f22911eed8143e78c10179d669a77055e6cafe5f9cd83b0a89741b0b5dbef55a8b15b26d3a", "SEC": "0407fa79b4b2a548b4b88fedac567b5fdad8837c35a2878056955517252e46b6e90eb331aef52bf4b7eac60b528fa99553c2ded34234165d148aa7051e8975a610", "TP2": "04191e1f5040593131d680c3f68b5e4aef0cc67de1f089968ca8f7c94d81b82bb61e3f599f7fc159295cc3de7cde14bc9a08e1eb33cfdd4bb99479cccbeda387d4", "TP1": "040fa2e6acdd5b823247101b16f5cafb7ce82be9c5cb0468e1e5acccad41365141198a43d0682a835fb0eaafa5caf5145b5bb4690cf3370a64bbb74504027d604d", "CS1": "04019661fb1e4cfdd47832eb7c6654af21127a93cfac67c9052833681dac3ece450fca5d47fa0dcc9c6463ef4ba78b2cbbde505b14a8bc407f855854a94917e61b", "CS2": "041e0dedce73b57e0e3a7c1299a8d14a893a895fbefa3cea8cf833ba1f4c0b67291e0417cdebe8445281e50a4d662f9f8f986c4a9ceb2fc787e6533904f1677258", "HASH_MPIN_ID_HEX": "61444ea41a0b2e2ce81392063e9fd39dffe6b20415f47364a313fca0e2baf4c5", "TIME_PERMIT": "040a689c3cdafc3484811688e57086a9171c33d4ebaae0bf1d3c2e3f4a50095651043ade12b588e7fb55185b973202749bf81a9e38dc366f36a598d60f6b635bf7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34345a222c2022757365724944223a20223566646266313734643635383639323134393639616139393739633736646562406365727469766f782e636f6d222c202273616c74223a202236343364346264636637653661646238227d", "TOKEN": "041b513938d7d09649f9d20ee4e0bbd99b608217b9f409e25825e81eb74b6318fc21c9e31b6b5758b3fdfd06605de8d171fa2a53c8a6b750f428d7a36276b70d3c", "U": "04109cf3a47658b146170164cc06122abb4375df882676c0e3071ae5b13f53e01405ef4be9e00ca22c6705a4189299eb7afa33da7ac54745a227e525c66f6a081a", "SERVER_OUTPUT": -19, "V": "04165b8befcfbebda086c6727fdcba4be5892bd50bbac8c64936fb44b51247d3c017de37b1afbfb4d9e9bd55207486f4aa6b2c4c4b6d0a4fdbcb3e51146d1afb7f", "Y": "0442631ce4156cb260e87330cc06b02b5655c0e5a974ad3ab80a47d0a0d913a1", "X": "162849c6088f5856da0f5abe448021e68932f34f941411e479f3b91ea9b80885", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:44Z\", \"userID\": \"5fdbf174d65869214969aa9979c76deb@certivox.com\", \"salt\": \"643d4bdcf7e6adb8\"}", "test_no": 115, "UT": "040b2052cfda5c01f1d6b23935aecbd977c72fef9eda8ae987bccf3e24e931756a14fe5657671a39a44845d5e9851d937ff9c7a3782f929d2c58b936aa8b9f8a07", "MS2": "01bfa525aa166d6436fcf936c2ccd35837ec4ee815668648ed30ccedef1c2eb1", "MS1": "1de45673ea0e917f189a4ea9038d7a5fb3edab79ff30e0a6b9aa4ac8c14d6e4a", "CLIENT_SECRET": "0411f7ef39e48dfab72300953a5b4bfba8845a2f3814dec76cafedab2fbd4c1ca502fd63bfe07fa3a379118faea4b6c4e186c3d3a79fb82f810502e77a7acc5178"}, {"SS1": "189cc991e005a33aa8e4aecaac061ab74f4f76903284968792115794c4239fde006d785a8db2aa3a4620dbd782adb85c013f9d6a379f368a9cc2aea0c37f7bfc0dbf8ffbd2c123465a0b3d00cb209035b9a2726a59444b8e176bf983e5136f070c7ee2149b4ac819077951fe22ef3e01ade1f49b420e1b19ef6bc76f3fefdd2e", "SS2": "13e71e90e5cd6d6e46e1a3ad2b5a71ea6474969f4e92d4e316843199aff5ddb80e57b68daea025d48f3bd0f9dd3dfd410397a549723e4280a8451eb9c8c166de1e2f8f27e0e1b5d20a453d8f9a6a7f26fc14364a23bcace7eb35c9c26181da8419f969725c4e3d9a41381d03bb8e540528063cc8ead3d1bd6f37914a911798c8", "DATE": 16574, "PIN2": 9628, "PIN1": 9629, "SERVER_SECRET": "125905a1d5490f52451aced7ad478da08b89267ef0f9715b2b3b9b0deda8ee31172d0e55b2d280cb0a5c0acabbed947fbf8edafe14437ccce7b04736c0efbe330bdcc5bce941a90510668569d2c97f3272feac2cce5e04a6ee5d9a2bb47099a909d23ee3a0b846836b175beed9271f0cfade6c0f1c847227e12d0413604264fc", "SEC": "0422f3a0df365ef1737d04d5b44d37aeb597f5e6c15c963aa990f7b95636b2cfa713936fe706d99d7feed59462b2ac35f42936a3515285cc5fe3bd61c9479bc2ed", "TP2": "0417a49e30e168124753e4a0cbcc9696c79a76401024c707fbdb21c1458158ff070bbfa0b2b58a95e5e2109b4d5844bb7b7c757e3032de1bd5f2d70a7cf5c2aea8", "TP1": "0415b0c8de7a2e386103440c86dfc631b21ee60da4b280d7be6356fe029af6c54022efe9170c4dddffa872a8ca314611979a673d985c32f74c3a7c64807f509fc0", "CS1": "0413944c1fa7a6e35362545c8b857aa44c659eabfbf4610b91a89b2310abff89ef0b78ebb15a71e529dfbb4057023e12a6cb7afd3159598fdd3a468f73bd7940da", "CS2": "0411eb92fd8c3d666949e5ce2654aa9402223072fac16d502b748ae518be37b1c1117f8f590c08b9e001c30b84953e92fd4979b885a7f2e2f16e20faa773bbe67d", "HASH_MPIN_ID_HEX": "24281fc3b99732d324a86686bfc052c669f9f83a84d6170bfd88c1126f07fce4", "TIME_PERMIT": "04225b84a707469ab61756b4ddbe90c5c04e64a7c44aee1752c5fee688ea0a10e019014fe4460f91bb90dbde9bd778fc5614e84c7a90aac0e1d6b44291d50bed10", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34345a222c2022757365724944223a20223762663631613934323561653036306363663332383565343864363235346436406365727469766f782e636f6d222c202273616c74223a202234343263623162326639326261326335227d", "TOKEN": "040705197c36ff49e2a509775f9e3f02364d5d1f46f57c0702e8fece5ec2a1a0280e06a1eba6dc0a5e03db35a326e3f241436d7d14e6abae804c141489c7fc8943", "U": "0401d060f1e540656723f8de13166e8e8fd37095f751467610dca953d66448e03b12fbc67c0c11e037d37bed4729eae078d975efa43baaf2ad6b2645f490413245", "SERVER_OUTPUT": -19, "V": "041988f53efac016c50032763da2deeaba3949960e70d4c72b506e6a7f685e28191ec8f3d14eb5a799e8650f7f902a7da0c3851b1f740eddfc1d4a7d706e48f15d", "Y": "01ed08ac88b7dc06fc18f500587407dbb9d0d76fb83a41a83364a3a79923eef7", "X": "06f61ad5eb5adba6c179eceac29df77a36f3a1f71699feec95d32a51e0d6ae81", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:44Z\", \"userID\": \"7bf61a9425ae060ccf3285e48d6254d6@certivox.com\", \"salt\": \"442cb1b2f92ba2c5\"}", "test_no": 116, "UT": "040f2182bee0cdea96427bc49982c39ff55922d076b9f907f113e1f9734b2a6abb0c99208879815288def73d3a82f974f2aed728d3fdd4e84c0aa0f3c0f868a732", "MS2": "1523e70ef34ee7a6c0c023422afcd5bfce945ed1a39a5fa6d440cd2781e89e8b", "MS1": "138701abe984e422eea160078ac22b6192565ec01416e78bcf8d3fcc9557469a", "CLIENT_SECRET": "0411cc5452d5b2d8bb6509c9069e63cf3a16c990362ee3c070d18f10626cab0e961f181e839a9d9472a1d11bebdb397f54641e85e2ad5cd3672f81b1706ed7b1fb"}, {"SS1": "1637527def64cb34a9a87321eca65d31a6e20061529d0cfcb5943f5ebe11306b0979cb66c2d55aad93a51c3c74a07f2f02be49010b18c8ea6f6eb8b214a0c177217a0641ee53c2f5f95552be260ca9b3cd79ed85147ee232e3b6e5fb73a9209f05ce14200c0a064f0066c073986dce297d810e9c20d2537cc6df30c80d0a4f51", "SS2": "1e276329b72748ebc87d548ad5f3b2330ce0dd7fab62193d59a8a126d47a16f9079574e9130c5587f5e125c4a6aebed6acc8e24bfd650e6bb3286885d351d60b0d997c948728b30e8001bbf1bacf4ea5c8ac949f77073c88822f8c0a0c04c2a201244f5dbcaa35c2205799d388f15df97bbdfbe1586c38c8c794d872a571ed04", "DATE": 16574, "PIN2": 2352, "PIN1": 2353, "SERVER_SECRET": "0dcf50e404b58fab77b9c22ba0e05080f58b726bfe84fc82fb7cfb26ab656c291c671ace6df3d2088d1a7458d7e992aee4da9b7a82371329b7636c3d98946d5808c6a9e013496624723255874c072ef29fd220d57a8fef4dee1fbf7d97a3394e050996cb56594e8ab3f402c12c0021f3103130bc50f6da99ca3bc157602e5325", "SEC": "0407f04299dbd0c4879eda8ffa64c8c819c3d7201eb7f3193bd056cbdea5526b7b1cb09403e02fb4e940af19e90ce6d65fa8620945107c83f68a676bb3684b4c29", "TP2": "04164e25c9ee8e06f480a7938cb7f6212096f12ad8415d47c637045a4f43185aaf0c0215b6908ceb333380425c081ee9e775b113717d0bfde3988091de816ce6d8", "TP1": "0418b9d767682b49a27ce85511625bd0bacc19d048a335867c91766dd215cd77171ec8ad578829d792da8f3d380876ad845e6df474438980f22a652c1a913098e9", "CS1": "04130b09f84809dc1df5db341e3fa5875e5bb34ad47c455d9a46e9b60897ef20cf044f1b9df4e4aaedc3a1fe8e82ccef40c39ed00e39a2bdef46ef8043fd6a0449", "CS2": "04193b0dd5b452e541bb084e50d257f58480bbb46e591b814c4af29370b949d34320c0b4e00d8612768dfbdb8a8a1a442241d4c7f57f50a8c957a84f45cb6e002f", "HASH_MPIN_ID_HEX": "0fbe08f2ec3a44230d8658e490c4d01a06b1ba9469154d14d9ec38cbeea7f811", "TIME_PERMIT": "04170a34bc85e311f7d70973513f1ec26e171a921e9a7190120fb0e3a81f1e1def0d21006171b12f08c282beb1250a6c7696ae9f38c3ebbd31d4e26d9aad8438e2", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34345a222c2022757365724944223a20223763366631656538333930343864393633393433393061353930356132666339406365727469766f782e636f6d222c202273616c74223a202238333639366636356164346132386332227d", "TOKEN": "040ed9ca6c39e39570698a6e6fcc34e0a67d8807c31d20644fd71d9286d57f3175049c1b322b03a66702635881cf86f2f2cabc164276799487090222a05de4e1be", "U": "041ee51b9556eec8e7d9e7d859c9391cd0a35a9cae4b5d7adddd42b5705210d7f611c17b599701a453e7485dcd4a95d9388f73f69102c215399cd77110eb0c48d9", "SERVER_OUTPUT": -19, "V": "04199cff2fda38777685e494fd7486e3fc16d6ef8d58d5e6784ebda23344d82983019792cde2901e9bac48bfc215b7a469dafe931402e8fc38d8f888ada01f5ee2", "Y": "0d241b6f2a20c81b6e5d949292d2001b59c2de06343d621eca8904bf800aacd7", "X": "0ccb77aaa5990e2251eddc9113d8d4ada239c4fbeff787864196ff8927afeafb", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:44Z\", \"userID\": \"7c6f1ee839048d96394390a5905a2fc9@certivox.com\", \"salt\": \"83696f65ad4a28c2\"}", "test_no": 117, "UT": "04185587d8cb837f908011da0b3c9ff71dc736816e095f3caa9725c769d151ca1b20fea747b2029c7d444dd01f7048bcfed4ad8e3a3f81fd03c5a94a52ddb0b805", "MS2": "23fde34a6587dfe4a31b65598f9f27570ac3905726aa7b4ebb5b439f3c7419cc", "MS1": "02c6dfafb6b6120b2431869965c2614e7299f9f91eb0bdb149a40c5473e19799", "CLIENT_SECRET": "04102c0ac983b480073392f22be27f243499f7a83bf6486fe42a0f197a7317d9c502db1cc1ef3d4d25b20556feafe33cf51cef44c04ee728d4ff4efa36afccdf76"}, {"SS1": "024a40e9cc53d8d6a9311419596fe341e08daeda6cf971ac623db0dfe254fb68200404fbefe5707c716c3bd4d6bb6a859ed990838cde4da3a4526d4f0d708423215d194599e5e691fe063bfe09c3ef670d343f2b475dcd97be5e3e269a9b42bb05697b6978d76e7df40240b7e94438399608a61191731a8d2111cb53c4011c23", "SS2": "168474caa72d38b12a403c2e7b649000361eb05f226b6a99c1ea60b84dee2f060419dcae8221619352418e74ba3ab93c8af170043c7b1df7e675554800f7426d11c329211aea7f8d590cb84ebb5bb154eeaccc4cb680d3ccca967d3d5f20d16820f3a14f0878242bb1dbb791315e5cc39a45d85539466792205334ca2b000a34", "DATE": 16574, "PIN2": 4960, "PIN1": 4961, "SERVER_SECRET": "02ae77488cf662259ee7a1a2deb737d0d5c23cd022e0c71cbe7c6ca37894f5ad1f32c3796531ac35428b8c5f22c565d5b74946987a0de738a46a369755b7aaa50454cfa39de9fdfbdfdb7a8ee53392e52fa78f81d620e646f92684618a348f6b0bb1668f277abcced20dd300d9babfeaab81393394e1c2b74b83c95f1d614e5c", "SEC": "041b9643160e1c881dbcd79b1f6ebd037d7f469819116207c22cfd7f0498d820e01abaedbfc477e6116f2c37c71ce9815c7bcbc37c7b939fa9e026ef7664a03647", "TP2": "04031b421c4503c2f17c580eb076b785c44e098e0fe0a74a6bc80331f3c8628cff0f7e4d351cba7a5b3abd262969a72cea23315efa0a14958fb0a66053d3ddcb91", "TP1": "040198b3c1f25ae5ef62476cbba300a94ebe93278e843b4b72746fe77a0d98af5d2089e419c5cebecfe738b41660ab7964dc9c9f9cca2de86585c377133c17d927", "CS1": "04159a5ed39228856a716bab3ddb8204ca898d9b2a7ec1d56157aea6ec3c757de91970992e95eab168d81c446bf9a1f15bfa0c45f2434be1ef6e63df31c20295bb", "CS2": "040923bf73c5a7063bb7eefb1e593f63ae4b0d9f2acf771e9e0da31ee1893b248f0a132e1361d3b4a9291098f5c66b317b77ca96fa24e6edbfc7de94de6f4c49ea", "HASH_MPIN_ID_HEX": "01d5cfcf89e9e69b0f961ebaad8d90a487b94104b71ef0b1c88d8560f0b24c28", "TIME_PERMIT": "04079bf681497c2bdc26fa87f741326fcc2c1769d9192cf6c831661b9c2ab6927e08d7cd02abf6a2553fcf062288089a15fde6e819f4b7eb6fbe117656f27d70db", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34345a222c2022757365724944223a20226436303537383864623237343135383137316236383863333335303234656165406365727469766f782e636f6d222c202273616c74223a202239363339616534343830303462353135227d", "TOKEN": "041145b420b7b5e0b166ae3fc40b9b291a300144bf84ba4793cf04cc9c0d715a0203f8c5d14957d9b01219a81906a72bbe466af6ccd53e6b37af6184bc26926965", "U": "040cb530c4eadbe910d1a75f001edcb566ed982d6551c9192f849919711350321605a7ee4b39f5647ec899450c31e5565c8c8216acc18ec58b8274c83edc82b6d2", "SERVER_OUTPUT": -19, "V": "040c96bd352228a4e62551be999141a11ecbc75e0dcb0780468f21b3ed303307570bbee55ab0ba4478017cb9a097f94a8e2d6bdbd423495df485986d96e582f524", "Y": "2282cfc2fa113d6e87f32325dcb827a5a67397c3703832191c3f2a3ee23cd4c6", "X": "1d73a56cbf92416693bd99b51f1d39b3363132b8c3165f4e96a500a0c1271f38", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:44Z\", \"userID\": \"d605788db274158171b688c335024eae@certivox.com\", \"salt\": \"9639ae448004b515\"}", "test_no": 118, "UT": "0419cf8120036dd1c3ecc618804db64323cbc626560dc6e931d3f11196d1fc633301d58819b7bef2dc588bb591baf00509e488ba488c93a9ddd56f337c25d1ebbd", "MS2": "0319dfcb1951fd50d8179dab703156ce1a0e2fd453868ca6ac31790ccb341c03", "MS1": "0140c5d153bc77b7697acaa07b95d5aeac15b8426261a4517197595c4dd6f27a", "CLIENT_SECRET": "0419c98b7471dd362d2d5b38977f13633aa7ed117d48c5df856ab746064c99f57e002018b748d8d41616a1bac624c45f669c26cf6826dfaf000df73a8052a8dbad"}, {"SS1": "04e8643a07a48920cd09a4df966f1d2ba6cb83a7d02a140a2a8fa9e322928c75237c7934614b1089d05be5d0a6c3d73b75f58656dc72265d67da797a9b034c4405e5dc0dbacdc0b9d29e281cf46412a63a9f0fb2e5f1cdd63e1184a6e5dcb7ee1358ae118fa484fd8127aca66640609786694557f2726cd61f9c6ff287841f00", "SS2": "0e7b067f98596e62caed1e44cbe4c8d9bedc016cdccaea1f7f337fa2fc40f5451e0143e61411467b498943971b7decd5a1ab32b1ba9c34f70096401fe909138d000392b4c97448728bcfeba768be7bf7d790cb881a5458e1eb1476ab1c3934330c075a37296ad89c266443a71c95f07fcab3bbcc64711c382bcfbc50e85e7a91", "DATE": 16574, "PIN2": 6431, "PIN1": 6432, "SERVER_SECRET": "0b0d12111c466867ac0fa60f2054022c992c1553feeadcd487c7f31bebff2839149d7c99768f1785d6076a9e3d4ca00dc88b3d4e0a948a3afd2862bf19579ed2009af1ad99d697e6379379b088fa1e3b0f31da82106653bf153edc00766dd18e1815bf0a1a747d572c8d3e6efdbd392e7223ce9f36c17d2a0238c8c710a0e140", "SEC": "041d5946af03a4cbe94e18eaa103b4b650346bddb54110e08dc4166b6bdb6bd1aa2299979f430d7294a10947be987cd27cbfd4c176583debd939ba85fdaf536f96", "TP2": "0414dded2a9d6f22baa7a0ce5cc63ecd36c19fc41f66679b58dc3ca9cfb2d6c26810cb8a8a2121ae2f767f59b4fafefddcba90fcd70d89bce4c621a421f657af53", "TP1": "0400f3b538f3ca240587e019876375fd07a76c20f510485a4d7498b2464b35092302e46ef268f11c1b2a6b285380e2a88b0072355f337440aa00d22ac8979db78c", "CS1": "0415f98dc8cf5a8c4571cc73cc568c418a010732d8d91deb395af1e874ece0bab402e3a6be1dad0393fb65b3894311925931a56581344f6e9084794c434177e66d", "CS2": "041e90bcb7eadc37341f7701f5baa0d2bb4a8431738bcd70aaa6af2c2f8893db7913867a53ea6776a15d1df4342961e80acea6ee6258a09b9a3397e5bc2d133b7c", "HASH_MPIN_ID_HEX": "31bcc32b6ef1dd290702af9a514fd5c41ec88b52f9d657f758867b80aacea700", "TIME_PERMIT": "0420c186d0a5e7e7042537f9ef31116a7dc0976e4cf5fe2da4b36567bb736f5eed0d4a1ee2c37b5db40bf8e8bb211e48d7e8e506a08efccfbf51157eae1afed10e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34345a222c2022757365724944223a20226137343733343363643833656432663933623236386536623331393761653566406365727469766f782e636f6d222c202273616c74223a202263643839383964663136646539303938227d", "TOKEN": "0416b22382b63032896e9f0d68cd1044dc620a84bd9a9a408ad5b9b8e58b9b487a18c3ada1a284b2b7b5164d31581a7273da7fab4da421a61e8559b7bd6fe975d1", "U": "0419ac1ad65fe3739ee6323d139a76c8e924f772ae9b9580ca3bcc4e1a65be75ee172497254956c71165567f456683912ec6cbac90580b6140a92ac21d6e13620b", "SERVER_OUTPUT": -19, "V": "041a791a10fa026bbdd27e6fa2fecf9cb73b5b0daf375e711510a252bf17c3c5da225a5612e216439e021407de1d70f89c314c7ca3265844a6ff2255a1f42357d3", "Y": "0670647ae3fe0a9beb3991bcbe44670ff91425f2b76301a2adee3615980044fd", "X": "0bbd3361bdeaaecfb07814a03b6db949eebc4d9e7b20ae38109812277addd815", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:44Z\", \"userID\": \"a747343cd83ed2f93b268e6b3197ae5f@certivox.com\", \"salt\": \"cd8989df16de9098\"}", "test_no": 119, "UT": "0422273b87a67c365bc1b6733ccb921ec5db39a61c55b9500d8b091e2c2a656ad8198369f75262558acb7e4e26873a97a49d42337369d5107b94b2fd2517821d75", "MS2": "11f15ead6901c2362c59ed162e03229c2176e429cf6aa570a5520a0ee953c926", "MS1": "0979ee5251ad623b265b74aa6551763df997b336d681bb6bce4fefc4957c60c3", "CLIENT_SECRET": "0404378794d905c4816aea2a63c57b3fa2e22473f8f1ad92855efe79dabf84034e0a87817e3897dee4f707ab7e1822d6bac06bd8888f93a62e4246d92cee35e2c2"}, {"SS1": "14746859f8444ac8f2edb399d86668ff122b91a220c00d7238c8e551919b89c7172a67d741f0c618958b5e2f30d06aaa25ad80f256a526459d33ad4dce25c19b16188df81f1187d081ddb7ccaf83073788cae9ea02cbbdb5da628c17cfe01ba7159eb0aef1b9abff8f40d747e586cda331840c9123fc816f45d3caf12a2bfc41", "SS2": "133853da7e1365d32da45e6c78284cf403c97fc7cba5949c87ec8d069ba0f7a302886d3aa4a654425295aec1f0e4991f63f79d1db1cc2141f79414eaaf6226e2074d6f6887e21f6f48d0ef75ff960276b5d966ffb44a77c85228aa48894e0dee1923d789791b251d50575a18a24230198710f6ac3de0c4b76fbe2082077dd48a", "DATE": 16574, "PIN2": 6094, "PIN1": 6095, "SERVER_SECRET": "02beee69e8cd6404c936796024e498ec7e817dabfd6e08e86146ac346f1161da1282c59ac30211024332dc1ef364bf75c7d14bc4864ee0ac55880c32f998cefd037888ac4f48103270cf64f8c10aa7fee6d01fb990458479d03f4a5c1e7f33790127749a80d3c35c70ea638988e191d670dff6a52c519f76766b4f141dd89ba7", "SEC": "04119886e61e4679684960138bb52a3da526dc42fda142969e24bb5e60566423cd0a5f5acb3ec485be90f977bb9f66b8dda42ebabf3d991da86b5f57db04f40ee7", "TP2": "04119580b6b74af28cde25d8e3b84257b22f2d8220f067a9b646de0688e53a650001d1a8b5026eeb1d035362b70fac5cdca96e009d606d604e1fd1307414446238", "TP1": "0417736cca0498d082a90e51f3f843bf3be34e95f3ff20cc578e9bbe638332825120bc3cf2faede99df1e9aad0b5fb3d842e187438437e24dff75397612734e034", "CS1": "040799e7f3e489ce75cc2e18ca51eb10d3cd461d48f50fcf5f8b3bed17460869a3100cde64a01f4d10806fffa16f0191369ef3c634f095139bce34cb1b2390c17d", "CS2": "041a0adb6a8ddfe930591e57cfef0118206721beee75177b41a4aa84ce894b711211d79018f47b908fc20099270cedd48b449b1d2097d6de0b331fd66db1a35ba7", "HASH_MPIN_ID_HEX": "bcb0509ae11cfa1234c2660ac5b7a96ba70f7a490b62f8a1477a654a84aed715", "TIME_PERMIT": "040aeade4227117c4ac396702f486ea5f8bbc469cd995fd14faec00f2addafd2c6008075c4f572dc4fe4032dd6b207ed4b1b48c25b5f4751a1233722c483d1a3f4", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34345a222c2022757365724944223a20223833393365346264633132633632356238663833313463636433313938363162406365727469766f782e636f6d222c202273616c74223a202266646361643834653037323033623963227d", "TOKEN": "042230a39bb8032023e9e8662ebb1ad6f9e8f6f13aca0eb9d609d1e61e1029613e1441308ef6b7c455ed39a3d9a74bebe0651728901a3a505051168a16759dd4b0", "U": "040e46abc4012b6533f83596f549e41c6a491c7ed0a2420f4addf227d293a87e6c00a4eec74532e6d55b68125c81642d3301f3fd988abf8ec68ef571f5e2609896", "SERVER_OUTPUT": -19, "V": "040cb6592dca13e04d23cbb14e42d652a1c1cb0ba67cd928fa118e126008239ac021b483f5ffbe7b25e598b8408796329aa19de383661e639e0f33bc739153c557", "Y": "059fc64e08a1e5dd02e26328210f83c76fd18b03981236f4ac2e9145447fa4b5", "X": "12b4dcd8d70c1fac4e37444e9e6f4bd409865f7dfacef497adf7cf1a492fd5a6", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:44Z\", \"userID\": \"8393e4bdc12c625b8f8314ccd319861b@certivox.com\", \"salt\": \"fdcad84e07203b9c\"}", "test_no": 120, "UT": "041605ce1b6b30343d20653d28ebff93e3089c21f6e85c7300ccd99d2788574d5d1dcedc2cc9afed9f05edb4d4c6e799bdf96a6a752702ef2aeb6678c1c4f3bd54", "MS2": "0ff88351c43cc599dd0cbc9e9d252c505562213b38e982b8aa41e2c9a833c355", "MS1": "1e301ce8942bceecebbfdd3e16623d86f11b9ae20b062b2dce59d854cc0b8093", "CLIENT_SECRET": "04071c084b8b685fe70d6af90629c4db75de9858e23b770f6d080c310d0140fd0d0546d0bb8ce338e4bef878e882eee1cebbe47ae1bcbb81536ade277b5e485ba0"}, {"SS1": "06671684aa3649b86c41177ed71106f4390305aec44ea33035ce711f00da61dc12803c098e2f8961439a8c345f37471c9f439a8beaa295ef09ab75e75e05946320dc36feac6d056df61300b89c00068770059bbea2d9c3040f13e0b118f5b2250e4dd6ae1ff90a88dfe433e7d7ced5665100810d1369c9fe9533478dd3151526", "SS2": "0f617d1076f48bbe60c5f579ec67cea9e0e99a1ec4d5a19bb3351515d1b4c7531071d1b14b1b52bc471e73388b80401575a2cbe39e1b6d14564d447bceade0da10828f0df61c449b7bb0b4d506b80c44c14939862c329b880f6aa039561b40f70f555bbb61cd5e6398ed7759553814b22c32e3f5f2d5286925ba32f379c38e8b", "DATE": 16574, "PIN2": 8623, "PIN1": 8624, "SERVER_SECRET": "10f6edf48c5d82a001f33fb15621d511e8cf642946e7c295d2ac33d7a0eaa6a017ac0ad3fc2c0e270d2c25ab5bed8ba04e1ebb69e66d642fdd213206682ba0b70117385d31cbf44e0812be68b78954dfb1aab637cbaead16c580b88cb209147f04abf5341cbd602b855a1be69bfc71d561dd98cd327701bb50b2844d8280557b", "SEC": "040eecdd0b9447b80ae8deea7403bbe770c571aab871331a1e013626a44c0a08a003edf38559b770dc87ace81b3ffbc3724b6b55a75c3ad217744d3f13d6f7479c", "TP2": "0406f6599e6908b4d4e8c79a5c5e79fa3dc04e8860ba3d25728b74ccfd5e9aea1505b09c54c78e5b7f1d685e01df247c963190cbced6ad934a599df47b408c196d", "TP1": "041535ca711881b058ad3e8554461f141020d5a29115b1456ca3184f6f02251753228f35ae0ffd11f023be878a076c691b5725b8be2f63ee6644b2d418e439c2fe", "CS1": "040601c3cb10a13860921f861018ee7eec2fa35d2a955fa3259f57ce60703d44420fab45fa95a1dea13abc828ce12628b2f8274c4e0d18fb8188a0d34381dec0cc", "CS2": "040a28edea1fd43435ac6d5cbc80a3d046882b27e19fb49e008ac4043affdc9c0f0d62b29126e9a40b02907b210a881460156c855ccd707d8fd87e96e94ba9213e", "HASH_MPIN_ID_HEX": "7df4c18cce04025eb20112b9456fbe5bc0539ba54c97fa40e553eaeecd1ee3eb", "TIME_PERMIT": "0423693df49549bf88c67945e093bdb0caf086fdd43146e9e84ca2e3eaf00a6a2f1e099428dc5ec05fb4d9846fa42fd5ffad4e9a42b02ec26ba76108c549dbe97b", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34355a222c2022757365724944223a20226135626334303933633166636630633432653435643334306531333134316339406365727469766f782e636f6d222c202273616c74223a202230316336376633353133356261396362227d", "TOKEN": "0412981281e288f397e98b7d7f8bf18fcd84cc9f1b5d8d37d275e9adcb841c27bd04bf19c35fbad5e012556a7b714dab2d90c0c61169b86a41cb385043e6bdcab4", "U": "041bd021b16a7816b42a9a01f7ccbb5cf3c054a63df983558f02030ad202197a0201dc4c8a9ac5f4759bf0cca693b2db293a110fd4ce1d4cd05ba3e91572d054ee", "SERVER_OUTPUT": -19, "V": "040e7413551cdfd027a35d669eb263b527775c8fcb07e34df0954564ec04da65010f800961c20b1c27b830b74ff5f53dd3b9986b50bc3af27f8a64d5b9bb2b7498", "Y": "020d2ba1962eb5ef02c892fa5a897da1d907c788d1552018755c32fba3e00e16", "X": "210bf7af2ea5ef1ec5380410d1780eb588359de851a78d279717bd2afac4fb94", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:45Z\", \"userID\": \"a5bc4093c1fcf0c42e45d340e13141c9@certivox.com\", \"salt\": \"01c67f35135ba9cb\"}", "test_no": 121, "UT": "04190cc93c7509cfbe982384e22f17691dc04d9468a923028c8bac0daa029d5ed507c74f39d5173ad22381ffec1ec19c2dc17f2954c96ef40f9213ee1a57cb7ee1", "MS2": "1bc1251e6f6192fd00fee1789473e3e53ef3b1888a260c74dfc20b0ec87583ba", "MS1": "009e9f021ad87e5948ecb208ceeb6e27beb5695bc206affc0702d2f2acee09ff", "CLIENT_SECRET": "041f44e435cd45e9dddde9a7fdc2dda35f9b2e6f2041df2865878e7ad0589d40360ea5c982b121a95e166a4b7234291b5f9e2bbbdb213044f8ab8a70e52bd7b45d"}, {"SS1": "163159c9d07284509feffe47d90a06a4570eef3ea8d5f7616e73c0f647a8742e059808445a61b65add1194a678d55ec03b9247a6b8645bf1de8258e9bce13dcc0a0cf4280fea785ab6ce20544444166a3b2969ab5cafe83ff7a068d84f7422310c9af55b6d473ed3b0cbaeb31164479d767bdcbd236dfe901c305301142642d4", "SS2": "1572c8e306328666fdcc6a7db657751aa311b59bf8eba99ee2f9e12b8acc77d4215190e312eb3aebb83590d7a09465387aada6e0e3706d6a9d02c3562721d8251a84ffdc0f4416fcb9861d51c09451d6bffe9c8af014a0a2fe35fe4c7ec547e003f14d714e3bfa25c03c13693c4c13946ced52ed483fec303e5f4f18edc36a55", "DATE": 16574, "PIN2": 6561, "PIN1": 6562, "SERVER_SECRET": "192ea56dfc86b965e05bf4382c9d50c530dceb9edbd260c745197245413967a901db5d5e0f0584c9ddcce3182e9234df483a2cf9f51c04e0e207faae8ab8135e13944cd58a0f79f8372de1c9117239b8dac3124258b93826a067d04d2af736ea1d28f2e158125782e588ec508db54886ddcb01d4a116ba4b0932d406562f3a02", "SEC": "04154de7d23c3827e76216acf6876de9b74f38f7a206309a2cb9ec156aab2144920edb4b16f8b8cb264640e53d7ce736789b7bfd1fac857f66e82a5fa1bff8e496", "TP2": "0423c19d02ee4a9993c73be568d6ef4feb337d414701f3d041b4c9425f6e3ef71f0859d28934611a0f3d0b9281de90eebf09d2c0a7fb6c85b7623049edb6ac5074", "TP1": "0411b4d7bd9a33c1c6d6d96ffffc984e57c829372d48d5bc2d37dd16ebfdb6a3e1113418c9da7fd9ae7adc321f16e8525499aa762ab62aa0073758afe63a1ccc83", "CS1": "041f6563f5c8467793f67a267d983041ed752952ab12ea1bea4bf7bf23f92738cf0536566dce0a7977ff2197debb940881f90f0ba8d87436df9bd8e62bd88d019a", "CS2": "041e064983741760fb6c6fed5344bcb26abf4177c29ff523e7c5a48d24f4b6efcd1f08264956b106e6e0f8ee21c7dac8691796713354fd5736666158fb70f6ba2b", "HASH_MPIN_ID_HEX": "8f67331205c9caebe571b7c9b54ca24a38d5a3ded6a591f43c6621d90cd222a7", "TIME_PERMIT": "041036b417ca9b011a1818c58a57aa2cbbd6cf73fade36eb28e86b9be488599b9c2355eabce0e69b8dda2aaa107fb7bf82559bc2fb9d1ed999df405b1af953636c", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34355a222c2022757365724944223a20223436326666346434366363343837306335336137346236396161323038303264406365727469766f782e636f6d222c202273616c74223a202264383932653537393638376463383632227d", "TOKEN": "040d85a4b913d0d97aafc8255b9d1cd1dcd91a360dfadab435bb187ea6c94278411e879127dd5f8f363cb6c6f3fc1472ead2f93e22c2ac34bbfec1ae2c0bc7b19a", "U": "04046310aaec07a436f6a14f3bed56b22c3d786d9071af70482a42480e6230b7b403465de111f56373f5c5be32312dda8c9c69213983b22c29b0abfffd90c86345", "SERVER_OUTPUT": -19, "V": "04223bd88a8ab01a24297d85035549e4919991ea294de5fe72c0150c73a04c56f811d0a5fad743787c26026a51e76e9331221e24c4749912099a0152dac93b7086", "Y": "165f2909a0889e9743774c8f8c77589f7d4ffeaf3804f5dc746e5b41147449b9", "X": "1b3dd4f54fe09f6623260d628d81b15de9e91f646cc497f527f66872f8acb2b1", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:45Z\", \"userID\": \"462ff4d46cc4870c53a74b69aa20802d@certivox.com\", \"salt\": \"d892e579687dc862\"}", "test_no": 122, "UT": "040a1eec9df73cb102f9e1401e66843af73ea8a304058d2c39e4292acd02ab5cd119c6e340d8b159eadd885cd020b46c05fd3b796848183a1a0a4f5108361e2dc5", "MS2": "0a2cc6fad2fa2f2f1eb5309502bbb09519e528b32fbf2f0afe8d5090862599c5", "MS1": "0944011f5a92584239a7fc84752fb6c12e8c83be85a3f79882871eb59fe5a1ea", "CLIENT_SECRET": "041c3193e51b41cfcfaa95782f3aedd1db3688643cc023150b6c8cd06a6aa14e7e0106cb84cf512d51707671766435064864c06afd220f05ebffdce3778b8d8aff"}, {"SS1": "229183d17d5f508055eb7cca16da16ef2026449f47747edcf9b9e74cbf9d1abe01cca485512805bb66215fd9bb0dd242501e376d113fe9839b7cf93de1e4500d009d27c36b43f41a3f56d35582da00288720c9d5f68762da669a5f34442b80360b03fc731bb672470c47ebffec31236eb3a357d27d95d31c31cbaf070e808fbc", "SS2": "1560850527de7e199ca654b760b66e9554f2ab870d0fcd0d3c7a9fc4835049fe03c993c30618ccaab275d62b849a4da6955d5f3fa52324563debfbf4ac94acb70d457a8a57a9fe67858d02119a0f0fe58378fb883945e3820d1af6a62a3981521d5c9ea33275aaa019503ac86791891e3e339857a2b0e37b6e305ca7a34f814c", "DATE": 16574, "PIN2": 9109, "PIN1": 9110, "SERVER_SECRET": "0c72ab81258f2b1b443049701c1701de185add36888941a453b2bdf943d6bb8f03de6712193727dd1db2c071b043545850311b32c1940ef0605f449dd86b847d16b11b8b35b98ab80ac35f25544f1eb3fc78a11d3eb3302974252a72764db3a112a9c00bd38ce3fbfefacf9c062520538b0e96f985e0a293c515060ede239f64", "SEC": "0411fa63bde422041d15274754edcf0a0e82d04a1393a523b6d2b4f6dc97d1786907f3b828c7ee9e9f241d707855aa1b206d9e78b91d49f0a935325ffb0ca6b0a7", "TP2": "041403e042997865acb89a509ecbac8baa4eb281359f7ea9bc4f8140ea780b6be7207e2058d447feaca629bd542ee97af3e7c4d13c4032260ae59406f16173271f", "TP1": "0400f10769c66f23b0f7e44bc7a9aba97cee4f50802521d084b31fdab8c5a22d3712f46b2367819a7bce47ad1e1cdc1334bc86fb67e5ea2414be7b7b21e95112e5", "CS1": "0409b41c80570a44edfe507c00b3667718c574e81d7969e9d4251d574ab30f0f990cd2ab96269cdccc1a4d7a1f7ad6cfff7cc48c5cd14e709ab791a9dcfa305adf", "CS2": "04033f57b811eb1015c475bbd3e1ebf703d614a1b7c103cc3910c400dc4dce93641326066856fec36af532a5e1ba1957cd1e6df025cdc210e13d4404121de51631", "HASH_MPIN_ID_HEX": "efb9ca86d4636bf87a50b82c56cb5fa306e814dba2a872898d8c1931f918f105", "TIME_PERMIT": "041af7bfe3ca494b36117dc239805a55a1b5630f5b7668eaee7cf1194ec83d794a2258513cd7824524153d6968dbf423a572cd3ffd53ed2c552d8a0a7ad10cbaa7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34355a222c2022757365724944223a20223031623036343537336130636665623563333137643537613530613634623761406365727469766f782e636f6d222c202273616c74223a202233326361316338353138373436656261227d", "TOKEN": "0421280131b1668939962bf1f1d51393d0ba9975caf61f4205e849d72e4f9f909913c00e24276f1c28dff6fa8aeb032a7fa3d9e437708c664738ac385acf3e11d4", "U": "042199077ea361e58e847d9d70c652f971bb98b6e4e6ec8d35e4256e2d63e5dc7612c7200c37eaa82733eb6d879cda1bb7344c2be3ba5508f437c4484891135591", "SERVER_OUTPUT": -19, "V": "0412c99bfdd11822f535557c295ee1a735673d4468896f99f4132280f96777e27318661086b417088a7826b3994f93c4de73ab850308b3fcbefb0c6784dc284c0f", "Y": "016d483d28b1e4f7b9d907a991926c2bf6719c06fe64904be0a24546666048be", "X": "13271ec72291598fa91107e21e7ad1d8193c4ad2303b2f14454e22a1accc5297", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:45Z\", \"userID\": \"01b064573a0cfeb5c317d57a50a64b7a@certivox.com\", \"salt\": \"32ca1c8518746eba\"}", "test_no": 123, "UT": "0420ba459847562fe65b9e381ca8374861d0d4df28757c4eb240307140ae7d425f008410144f5c7d779686b55fe9958a1637a7c8c89e70ab8c407ded53d899dd03", "MS2": "192a2310b259bc87504d88da7751716b16772598f34cf9c6bf9a9c346725c9c3", "MS1": "1fe915d02dfa39a10b56a4e59f5732dee3db09ebfe194dc03c7df21051d95e64", "CLIENT_SECRET": "040a7833b229929dc0d35203663ce54d7d9f8122dfb0288e200ed125b77dfe87b418214d6d771537669631b2aa46e09b06638e87fd011c2957775422a84c1ab1ea"}, {"SS1": "23d1be133a4b25386213ecb2e14ef30b1db190585dda8424e27cde9b1b4ea70e15b8e500d194fd70197b851f9c2f2b043739d44f7869381d256bc3d02051d831213a7520f276f4f5a225aa0a9820b2a0e5210e20f27e894fd1536ffd25cafbb10bbce1c67d4e5b54676c6f19d95a8e9f397085b607ec3e593c132d08cd0798b5", "SS2": "0898e49661491965713aebb5fa91d597e8255ae66897211142fca635e3cd6c9e22f445689042625a76c81f94e28d7903f8e429c5d290579853ac0d0c6957fc3a165bc2beae3c254d03180991a241f47ce25ad6adec503032ca27f19c43ef06ee028f79c5af74b2957df1effde797ba90662b4d4fd824287abb61c8280923ccb3", "DATE": 16574, "PIN2": 5397, "PIN1": 5398, "SERVER_SECRET": "0fa99bafefafa8eb191f4ffa8cd7225bde1da5fffb36836a3342e67bb7cdf3e410e586703ce0a4df0f93e850b98d503b2bb5f5620c124c3210810ab0f9d70c8b0f0e2930931afd478ce222aa3e2e5eb8871c4c00ab745580c09bb70eebe1a79702b7f0de9a629b2dc7377af16c121a2a4c607745f023e68ec8ecf6aab817894e", "SEC": "041b2ffedb28fb44136b94d3d7b1f79175aea00f01e9c4b405ce588b4a5c30800f062564448160a33dbf6cb629b8bde37b55603cb147e3cd1ce70747e35c37a387", "TP2": "0416930ec4d4b38f1cc7bea39ee61cfe5f3f130adade2fe1b57afbeeb78b592a03177810aa7b4adb62ce50966fc5499b7cf8a738491d2071a3744b3b464bd149a4", "TP1": "041982eaedc551dfab4c94f4aa83c96f6d30215fd0a1895664767910f45e10f34405fb53342f6cacfe2303fbf99a441f6f5464ef49dcff8399915b750e6a7f0549", "CS1": "0412f1272903e1d96197404b584c8027316751dc20c112b555557bacab2d8cf6ef0f9079c560542fac2071b6526ee3da2f48f52a115d817d9b18de83a9ceaef1ca", "CS2": "041bad7aebbbf253b7f6e40ac130916196684b5f7649cdd096614e702dc0cd9f8e232dfaa431291033111d7fb2e286fd5d369f5d192856cc60c2c954bf6c63db8b", "HASH_MPIN_ID_HEX": "f9ab9b14435921492bd0ae0b6b8ec31dd24ef50afb3f2b0e63b8534fdf2fa6cf", "TIME_PERMIT": "04098ba2b4c3ac5d6999a0780315e4a91493af75bfbab6687efb0c33e4a042389d006033919c4122b0f7446e510ac45ceb57a515436531331b6ad777165039324f", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34355a222c2022757365724944223a20223234353933616366396130616131636437343238353465313337633865626165406365727469766f782e636f6d222c202273616c74223a202261393339343866383430623662373263227d", "TOKEN": "040acc3ed8a6fa6fe9e08f0cdae12c806523767c867a18cdd4eee27365a13e0e7a13ef5ac55826b13d5e8d89243efcd5593c37fc61bfd45e8b05c0d6eaef3f5f24", "U": "0404d2eaec8d5b872e1375872bd8f53fa59f63483d851e2977eba0fd495ec0720f19ff4817824de7c775853a8be225376bab4b690d81b44cfa808ee52bfaaba451", "SERVER_OUTPUT": -19, "V": "040861978ed013ad7575a328b4cd8cad9c7a93ed32525b88344d062d9a173a2da820773bab1410d226afe1c879fcff837817f4db665d6bc85f5519e4a26a68f177", "Y": "0071ef4c8cb880594343ad2c1c580602670d60f0a0d6860ee41cf6eda26220db", "X": "20cf8d2ca8e74b41106dd42177041846204f604b035b412d2285689de637dfa4", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:45Z\", \"userID\": \"24593acf9a0aa1cd742854e137c8ebae@certivox.com\", \"salt\": \"a93948f840b6b72c\"}", "test_no": 124, "UT": "040befa116d4c4cc729d7346c886d7da607613a553b563acfaf6547b5acd1fc7e80edb99e17b1384cb0e103c6054ab9b296cd73bc50ad5b76787deadaa06e16038", "MS2": "014fd2ce8640d56a8018ee4929bc05a261cce55d53d78e51fdfcd627bfe5ee89", "MS1": "16a232d92aa71a6d4538623ba61f28e6c281cb8280ea863241909ff44aaec128", "CLIENT_SECRET": "040b196ad91f408269a2211663f3def702ea7052c609dff0aae366ea20fb21a29d0435035e7daf2875def94172b2fe7b77e57fd22f6ea6732fc7719cf66554617f"}, {"SS1": "11bc65bcddf46f3260fa4cdc02576e7f961ba36dd69491c75361a6ed3a0563a9084dcd5a814c92ab8c0f0dc46e33e6b4acf18987b89796775b258ac3ab2f49da19f3d879512776c75de26b55204a2c6792852152a19bf35b07e244ddf8acc138059641ec072fac23dc6cc080c9a083b84614c21c939d372af90c6dcbc3e53bc2", "SS2": "01d87c9274de1ff9845575ebd3c2225fd2105b2edc5981996ff35093c7f8e42609ca619da50a0478ab6b37ea1169daca488eece2485ff5f43933d21ed9328f331655afe6d4a4298b8bd7be9aee53a9f44a9aa8ff535927fca6868408549008181ccbed40317036d9274ca6bd64a1c171692696ef671045a6906431dc26176d8a", "DATE": 16574, "PIN2": 7460, "PIN1": 7461, "SERVER_SECRET": "1186dfadef3c252a91ab50d10b60e4b6b7f7b82cc90e8dd39e191c7040df522c1ab1d39fac391b18d347bad48ba0f486c510d82f5461d1237078668837788b2f0dd3bbda252ca7ee3041eb6da1386f6e04ba56e4171ec81adce4459a28f16f7111f0dbdfc1afaf261b48b19807d0cd4f7814448d2d2e954343d86706a738dba7", "SEC": "04202c6f6ee02ac663489f6c40d41114850b15869d84130fdf4c6511879843b5941c052168b2ca00f5b3c5b926f7d571f312ac62db3519ff7ab751534312853650", "TP2": "0418f3942c87395ebd021e7a5e89b6e62a0feb0389f94da73ad9b6294069c4ede01fc21ac91182779b5215b5f3c272814069dd0adf9ce0458f57782af233259c69", "TP1": "040035d424d501af479cc5cf870d6d3f36e7577b86e43a6c5f9d5046be5f3f2eb50bbc65d2801c3ad3691ab9863d0f7252253f1b01036a8a5e2cb03f6b1a2aa68b", "CS1": "0402f07a88c879375120185465780d916a8422107e9d89919f428055457c4cb3ac230b7ccba350ea707515e33b3f1c6d02dce633f119b98b53277ac8d2686cd3c1", "CS2": "040d96da138196e89db12ad697a4c0632703ecab0682852a19fdc3761d34ffa414119e93f0c53f1217f9f785c153a38fe14521ba6e9bdd55f6d115396c830236ff", "HASH_MPIN_ID_HEX": "f2404ccff43b8a04341d88ca00b9c6e4781e360f0e6b771bd710fea1f4fa4514", "TIME_PERMIT": "04151d3d382849e5572bd503bdd632e083acc846deff45fa17fcccb5f8f6fe4e0d0f2d8fafea9a98b20ee4aa3e3f60c73fcd7c716261324e44687ea7ef06c14421", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34355a222c2022757365724944223a20223439303562656233336561363333306262623931353266373263376336386465406365727469766f782e636f6d222c202273616c74223a202265343366653433333930623630656665227d", "TOKEN": "0413e8ab1f1283aee3f424820689d6dde0b3d598a921636ce07c41646fb753b8421be729d604adf5992f5f6fd8faffad3981c07b563d89a8721590028d21258432", "U": "040bf6c00330a865ea3b2238bda9366ae59683b984a7460eec3aa985287a0ab4461035430d66cdff43c7067f990d899c717fab0fc87fa744722cc9bbdc65f1b369", "SERVER_OUTPUT": -19, "V": "040c344d9786b982ead08deec9a6764ee0dad341a65a125c7b6469e243459d6f7c1222f3ede5e7d1d7984f6808862df272ff8e4e82e9a02e91e47ad40805602ada", "Y": "2250967d0aeb1e4fccf4f4ddf8fcfbaf1bc7066ff76346a5ea6fa3d5d1816b86", "X": "0fd636d8f1580f19ab22a63db92b194f1877584488ff03d5bd2e334d1bb78404", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:45Z\", \"userID\": \"4905beb33ea6330bbb9152f72c7c68de@certivox.com\", \"salt\": \"e43fe43390b60efe\"}", "test_no": 125, "UT": "041d5dbafe39e111cc6bad1a4cf1677eaf8a09d6eae61952122236c13f933d6bbe17f0a6fcd9fffab2a6ba08079017a1c448457c82e3757d9f004783f8da2ce49c", "MS2": "17c913a2ec90cdcc53de154dca24bc762f812e350ad2345b6f6c4059ce15a984", "MS1": "2258ef7945469c155a839adcbeedf6a4f61c07266df5a5bd46fa0d92815156d7", "CLIENT_SECRET": "0408aca54626f120138b3a1f4ff5d9fe74296e01174809a0ecb6942da3614d7ee0226c3491b4f355d89139a7e655b1f5779e7f78afbcb4e31ff19e36cc551c1154"}, {"SS1": "164d787a58b65416141cfdcaed23c145acb7e586667f6a7508b47a3c261945ea0acbff4d30a60e12efca3c8ffdab9442293d1c7b95680c90e605f53c235e2bdc1236cfceb60edd80c2511005addfeb58dd852624013692f4692ff4f1f4b6df7d0a4cd499ed8bb203204d14a8522f946aebf06c259619d13981eeef0e56c4d999", "SS2": "0cf947f6574668504a929bf01cebf03ee3c1d7299739009a252db0bfac7cd047224c906ea3781d43cac526da57499588e27a912d583cc51d960a535f968c0846220113c25b4dcfb57cb37f4870207080688bfb894ccc49e1e515c96a3e6feb7809e8426c65a2a76e884fda0fc6ac6f1dedc6e49787334111f7f50db86874d386", "DATE": 16574, "PIN2": 3481, "PIN1": 3482, "SERVER_SECRET": "2067a06e5492b2436ce1655ff6178b683b987f1706fc2d5e00687831077fb23c0a8d9d059fd757f61743fb2f12846317c4636905d065098de54c5347114371d71580ad4a5bbeb2b12071598d45a63ce9a0c1aba3e5577b8abe7a0f59a8211fc90a47b5fb44aa7751cde5b3c77d9262ec8c5d314c763a79c067562885923db496", "SEC": "042134620af92604ef36c828177bbab2700d4fb428d78f8d4475db1d95507c3f4923b36a8eeaa072f9e4d7ba16448ede297df6ec3e01790292dbc32f7ccebda6fb", "TP2": "04109597807bd8179ed3b671a0c5e84eac00313e525e1b87c86c2fac10ad7ba45f136a88d7763d66618e695521ece858f931de9db172ceb278130817f755aedd20", "TP1": "0402b15dc61a273681b68a98a517e165949338ac080cdfd85b2e60004aed972c081508f53b0cd70074249e32c19cd85121d4243df50c8b9402fccb310a1bd4de31", "CS1": "0413f5cdd151fc8ef152b845ec3f6efcc8db0946b555aa5b5ba1dd26fab75982640fd2dd5f76df1e77c8919355ec497965ab943ce048fb74d55d62de12d328fec2", "CS2": "040f261835bb7a395fa8cba9862ec9279dbc10bdc7909026bfe460fb0c18e81e6f1085321455637a84e048a7b53d158594154fcbb009d51086c3cbaf6fe1decd16", "HASH_MPIN_ID_HEX": "a83850fe1fbf72affa9a2d934610050ca0995d4ea7c9fd95b4a88c66303c50d4", "TIME_PERMIT": "040fc5ae788eb2487bdfde53ec675bad68ccf7b665e5182319ed44d8ed57489fa017659aab5b51c51293a6ed2bae2464260eae965d7f87f17868b60843ef08a3ff", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34355a222c2022757365724944223a20226536653932626630323662363764396565373638383132373935356563323131406365727469766f782e636f6d222c202273616c74223a202265313834346364356137343035643563227d", "TOKEN": "040a24977a2a7a2d9d51dbd382953e63d2d36f06c619fe0cd4247c26da4cae4c5322af02c64b3f67b64575420404a996b5412bb1bbfe325ffebe07c92f57a8b846", "U": "040b2ae921bb3f430a7464c544f9769110314478b69253bd9ba4e86a078f8d8f7913bace5cecc4b8f3867a9b869e2594d4a990b9ef1571f4f49778f6e4436f3602", "SERVER_OUTPUT": -19, "V": "04006dee90f43a604c922f59a3bfbd1cd2719d785fd08fce8a2c3fb18f83a693401d55cd724932890fcdf3e3271dca591c7e180da84db7df5ca488c4b12e48db41", "Y": "09f0634e477e56bcdd9e1112013c1977d4af48b5c712c45a51b652c86d39039c", "X": "136b47220c0793e12883eeff43c227c6a363c79ceeaccb18ad661ac5f3979503", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:45Z\", \"userID\": \"e6e92bf026b67d9ee7688127955ec211@certivox.com\", \"salt\": \"e1844cd5a7405d5c\"}", "test_no": 126, "UT": "040226292622574be51100bd2e104cace6b0a3eae0d9b7a899a02781df4dc9fe8c06aee81c3d2a9948db1de764f166cc39d6ecd2f1a64c58aa24499ccfb8ac5952", "MS2": "0a16143e3308bde74770cc116b9a7f8cee97ffef0d6b3a98390a657faee05d11", "MS1": "23526113861888f446fca8c864147d9757fa3ee37869f5021d28198e2c0e64a1", "CLIENT_SECRET": "041a68d0a178537d4d68038e1cf07a09c077b35210f8491bc50211176891ca4e1c038989ed2b6312a0283a82f38ac9e83b996c7dd957c34c28ce2a2bd578af262c"}, {"SS1": "1ee03bd25722b6a4234f76bb612d37c8b2908d98b5f75bbc06dee9c920e2606d1c8c0d4559c977a629dbd11d74934ac6d9910f9c24e83bdf4eb2272ee1f9b9900ca5db09b9738c838d07420de9f74a27f8065101ffc2cae19ae32e0586f1721408b9ea2e6d4b3d9dfede7e62aef203c9935b6cd8ab6d9d6d41bab5047fa0e094", "SS2": "11c0362c05b61150dbce0c5362766b8e4d6f19bf3975d9ec157c7143307503b80624dd54d701d6c9119439cb35eba553f06dc0f3f6c7e82b64b356fe932cef8102c195ec969667396b3efb5b4cef21a0bf89fd89a4f9892fef4ec0db8b783ed909bafd51f368af86f5cab3fd985f05ffb23053646c6b572ab314906a99197706", "DATE": 16574, "PIN2": 7551, "PIN1": 7552, "SERVER_SECRET": "14d57a61371a043be2ce1080f7299c66adc775803b58dfea0abfce885ce30c7820b56f6d7d7ef1489e6c245d11ad4a49e32c79423aa04dc355747e40dd6b049315e0b47f65b0ac4246cf9c04f93a08d53fde8c13230d127723e74b2edcb138db0e1b218c360a64b642cf2407f0b00330b1fc8e4d0a4da5eb239b35b83716a208", "SEC": "0417b24e6d05cca4d5360ee87e093bf74fa89b4bb3c541b3fa747495211f5dd24516b568b67c164cd977b598fdf3c84b33190fc6ea4925de207ed172f468a2899c", "TP2": "042286fc4bb481a8bf922318d862ebc6231f8bf2ccd83e5189d893bcafffe53c0c15a3dda40a55c30756dadd81cc51cdea4195e799a53db97efa93994e8ad8e835", "TP1": "040b2d34418bcf233035be780956ae5cead8b74da02f656a0b4efa6b9f4afbac2922cc00ee08c7a11587faa657010c58618464c8579b3efe0beb24e8f82830c994", "CS1": "041c5dbe9fa5705580a604ad6f7cda55ba1b1599134dfa05959835ab815ef809be1e92cef613d6de3fc70738c54c8f996988b3e9d30ab288b225bf653217fe05d5", "CS2": "040ce4b1a757e90889ec3e0efd1f1ff0a2170254c0e636ff9090716352e85af1791c2f93a11e3e97ed3dd811e6055edb37ee8d5c1230e29020fb4663e1a98d42d4", "HASH_MPIN_ID_HEX": "2073421533e4bb9506699c927d8f5d06a45c7c947df80ee7fc319cce9a37b84f", "TIME_PERMIT": "04168f7ecc515e82dae618dda52ae8c773153b47c011f32532fe50a4f12b43e558194e53003ff886d85f5710d1da7270d970058baf3c3c635dfc2a86163af0889d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34355a222c2022757365724944223a20226237353231663034343064386535313637643035383164333932353336616138406365727469766f782e636f6d222c202273616c74223a202264356366373964616334656663363939227d", "TOKEN": "0422ee3b90aafeb3d2baccc195e2f80fdf3baa5d0580bb305f1feefc618cbfc7e907b8aec6abdceeb3bd843af9a257ae3c7769abdc14e53460c30f82df37c19221", "U": "041b13e835aa0b59dd13c4c3a5ed7fbebf6b42d31a83c43c44b8b56beac0dec2141028211b385c0d8b8e2e0c8cb79d71057193d3605aa1877a1b2cb49dcfcd476c", "SERVER_OUTPUT": -19, "V": "041fb768899e2df7dd04ad2211a8cd3b594b2758140ed51eeed48760fce818163c0458fb76cf4a4ed052d13439f9d31ea49046a2fb3a8c906d49e8914f07120a4d", "Y": "0a5fa56c0074fc4b4a3c0048a8bce783e1f5caa02648c0dec08899a3f65b2403", "X": "1ae2a59888e4c043c87ec7f2959c0b4f74f315ebd95eb6ed1c38c782b81b02c2", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:45Z\", \"userID\": \"b7521f0440d8e5167d0581d392536aa8@certivox.com\", \"salt\": \"d5cf79dac4efc699\"}", "test_no": 127, "UT": "0416def3a6f817d7c816ccbc8b6689ebb3721e46872bdb15fb07e98eb0d133c06a1dca77b180d417e3de89466a70a8ef8d3a1b6fd29431e9ccc3fb85cb6e9dbe6b", "MS2": "13b545412d1375b85025e02e8dab6b430d0c2e9d71031e906fdca39b36f05d35", "MS1": "0aa23354c4fbc14f1fef61bf8f44bc891c560dfe83b22597f2046b0bba05b685", "CLIENT_SECRET": "04021232eab1da52667538d36ed619077e24c584e7752998c0fb508eb8364464f10cd00ecef2222e4c82dc82da0bd7ff0c582191ef95b2a21f68c23b077731f2c3"}, {"SS1": "16f703dc6c6076bc11827bf3c42d03eb5ecc4a90db859a49224111c2b646d8770cc2e88afc2c7c2d5dde46c14f926c61c29044948e430521947e0cfec235ac2307b8c2208f87adb1fcf8545e98a6955311467639f9868b18727b2f4cf26602cd0050572667864b921017bb585447a6bf3edf09474340f6c4610adc57d2d3067d", "SS2": "008da8157bc3c8eb2e69c38d51bd2a79dc45b0aa2cb616286ee32da39915771418e3d5270d086f1e22eeb0791a49f1ca9092f73e1f02a1901eeb52e3a841e6111f692af7a5ec3c86f949df7433520681426fb61392760f3c3fd6a05bc7e996a2232e443f06d9b15f65368dc320a6e82e608d51c550f4e7ced7de0b087849083a", "DATE": 16574, "PIN2": 8403, "PIN1": 8404, "SERVER_SECRET": "02ea26bc346bd3865ccc926df9cef998f8b3ea9d9a540b3a9ef20d648d426182162307f9e58e474cbbb5d7f0f09f75270240a1fa6fce450ace360563dd1427d618e86f197ad3591182c1c7c37b349d7a7d6570531a6558b2d0287a5faa9fac49127e0472bfa81220eb3e1d8bd4d496ebfe0e3fb7557e419b11e5c7e08ab6ced1", "SEC": "04189e7da45012fd8f786313d240f597b01ea15a133123dc4a03db44d0b6172470124e67c31199e8fe88e255261efab22ed1e34a91953811215ee01d5db1ac3b1b", "TP2": "0422ff150fabd29fc1555a313f46a3fb159a3e3347f7ac74e14e8163e146aa10430a8eca3b7ce355cff97fde163d6b12708beb71415beb32bef97379d590e0287a", "TP1": "04186ffd8ed0a0e22618dcaf8f7d6e76c07f40f6e354b06b866dce8db215a64fbd1f76055262e0e452ad584b9efc7560c68c7073dec637c5206ff07acccddf5e47", "CS1": "0412a4ab14063b4cbdd051df5dd0f4f5bf67e2b5d02b0ab916567402f51f5c266300c2c5ce71cfe79da1cc1cdffe19d13722380c183225eeff7935765960a5aade", "CS2": "040e8388fb2b4681ba6136276caf6c677eda346702c6dd4c8cdf89bb08eeb460571768e0c752953ec008f4c83dbc4c367f04a4b6dd7b65c6427eaf2bc7d3a71db5", "HASH_MPIN_ID_HEX": "7ae1d0021e60550764c1fd7e77b5618fcabf32dcf3e99be53fef94fe6315b9b3", "TIME_PERMIT": "041690555d23dbd80d8823d3cbfbd87f892920c9d0dd924db5d0e75d2f96e2784a083657dc05c02807c73dd4d82f5ade32dabd23c088d44593d2793d7f707bba9d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34355a222c2022757365724944223a20223339336237393137393061376230316434623061636238303264316366376333406365727469766f782e636f6d222c202273616c74223a202239653034323164356133373263623532227d", "TOKEN": "04051806d67eebb80fbfd0bb058980144063f718338e2fc1e1750b33ab0666e5a511abf65ecb993180fc2949529c61e9dde5194f76468eeb7afc47a07723947419", "U": "04083756bdf730238afb7379bdb0ce218b396d85023546e80e7425e0be15886a9a0ebfa182f8b52d3743609d8822efc194fc6ef2144549e99e33168973517081c8", "SERVER_OUTPUT": -19, "V": "0404b186718f88133019d30be9a8970b0295458a1402402179cd2b7af7acbfc98611610d0435c01569f53a101ba394e3174f21dc38c5238ebe7f9011de00ab7f65", "Y": "0e2ff05554b7a8594f1e1b0639ae792d1afa84ec74c5f800f53b2dc2a154d02f", "X": "08ad6b9d5e9917e08af08042534c5ccceafa212f1b182ca9fe7c428fba80405f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:45Z\", \"userID\": \"393b791790a7b01d4b0acb802d1cf7c3@certivox.com\", \"salt\": \"9e0421d5a372cb52\"}", "test_no": 128, "UT": "0404366199857bd40002037a4e55048f4ba565e7031bdc466268cbe5379f96d0461bd7e4fe6152cd35c58f2b995c650783162ca478716e134e01e6e5c6fc51b44b", "MS2": "1c0e278b1559288c0d7f7ee481be5d596fb1a001604eaaa4409053d06f2f67ca", "MS1": "090d1a32ec62ee6e513972a6604c2dc4dbe998516f1f5001b4ef673061c649fb", "CLIENT_SECRET": "040bd0b880deee0fed3715f020ffa58462a97d911992917cc7c3a1380b796284ab0f17a9bb16d39d6365a513e27b78b2a0167efa51a6640176b9f745386d25b1aa"}, {"SS1": "1cad25d2d71ece7d58465ab066dacf3100f9179e1b9cc78197efa8f893bd54292181b00fe884fe35f687d425bb669839e0fb0fcbe6d4346cbb48497f1dd7f9311d107cde4d1f788c0bb47c5fc7d3976eed0c0ae2dd081d51ba51c7c64af5099904a6027548f33ebbf35193e36088ad894985beed6ca3dd94e2f5a7a4261aa88b", "SS2": "17f4c4a9435b443ffbf24df3c976e20ef4069caa27fab11954e3473e0dcc8e361fb7b6b6d59d5436d059ff96d6dd2e98c6134059b7c85749ad2c92810d47806d1d9795c59be2ca05d5d10d20b0df39f64aab69776ae3914533e81596d2da5c8a1c0785d9e7d7862f18776dac4ff6adbe20feced3438c2858ada604c99f5460fe", "DATE": 16574, "PIN2": 5417, "PIN1": 5418, "SERVER_SECRET": "17d05af27ac4b104fb1e8583e8de78dd4679ce4fbcdc8ed7a6f9402595ec0f450698ecbe823c69f95c719e4ab1926e77c673af1a509dfa28c70a57d7ca21539e150d93fa78a85934469f938d6b9bc574ba9106b35c7263dc8fceaf4751b9007f1c91e381f6f6c4ab5dbb79f90f8326ec048d39a224deb597e76a8c1bbbe07a35", "SEC": "0403bd7e7e7a020f4f0f97b8a69b9f68d66290eccaa2f41d799fcd896b0ae864ae1764b714c2bdd77641cabe66b0a36a0b1e6c6b998fcc7c1fe0f78343d1e4a9c7", "TP2": "04089b70ecbf17a15c943e98c43085df90af47b4c85f62b83fb15cc912244ff93d02977149e7ea57a02b2e070fa799a093d92aad20c804350df2321327bcd0a0f1", "TP1": "0418b2a1a9302583f636828611dca6d85628f3672df3ed65f3c01f7a2639c51b9a1e34ec654901f43122c1d6ea009c32bc058469df5357e5e1021ea658dc2fee05", "CS1": "041bb09d7030e0fea3c633f5419e2ff84bcd5f1477ed8e56b89b68bd1ab7db1fcc024a3690525cec58e9e958304ae74d7ef0162a72e094e44f20edba6a194c34e1", "CS2": "040aa8ce959c0e846d85f89e46d8fe7f7b87c12b5845ec31e69387c4159d4dad0c11db5eb5a909a435013e6df38fcde951369536688389da31d3e28da89e09a49c", "HASH_MPIN_ID_HEX": "b9afe755cbf7753583bcbee03b75457e9a58efe3826b5c8956a0df9d1ffcd319", "TIME_PERMIT": "04065af2b0c88a6a4441c2a25ea8f4f6ec52e80adf7924f48956a9216bc026688a0169d36c344ec0887a201b1967d2525ae8c49bb5ead52404b4af827509102f61", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34355a222c2022757365724944223a20226430663135306336666665633634616239363134313463376264313064613665406365727469766f782e636f6d222c202273616c74223a202233383139343862376261626238373337227d", "TOKEN": "041a6345be5cb453de4353dee95fd9169bc13bb39f8d6406df47f1a7da34bf4ffe06434e74adffc15e9eee9c338318c26427778b598ed4fa82f31d5da53047c251", "U": "04043e581a39e8148c7af36e1d99dfc44d8de5ec20b596103603c745ca052a74901ae166b18909354017357888bddb426b8a7f4330d6776aa1fba0b6202080f0b5", "SERVER_OUTPUT": -19, "V": "0418a1d0ca29130649efcb197d284b347a5f26b935c798878f3170cc887f7cb6580b2965432ddfd569c695631890ce8eba4bc1fcb68333364b61b11d3d7f09dc07", "Y": "0ef424593e089c8b9d8fbed4d42bbe6f6a393bd3c05c44e53d9001b9a985bdfb", "X": "2369afbfffdef218bbaa68395c6d9e84511c72738064aabf0318f4540a3624b2", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:45Z\", \"userID\": \"d0f150c6ffec64ab961414c7bd10da6e@certivox.com\", \"salt\": \"381948b7babb8737\"}", "test_no": 129, "UT": "0401e81a50ec8635a010144e9fe3be6e7298d582d3fbb83c87588b0fad7ca1579914e97f8da189723d7015d800bd3c65043fd6f48e7cbcc30a4df428d6961342d0", "MS2": "0466a5f6fb9619b7dc2fa6b36a08731fb15884352b0c623dae84703677ac8fae", "MS1": "1a76ae2dad031a38e522c0b866c131445056cfde47a5e0d04181877e0cb4f52d", "CLIENT_SECRET": "040761c0aaccfad1c4c3ff39f62c8a9da993d49ed08d27465dc3882dc52c6b77a00e098b5d5f2acfa8053364bcfc0861b4ec69ef6349e64894a787c9c1ab1db85c"}, {"SS1": "22c564ab1092e7ea5645dfc677b9e3638fded92f6cd9a0af44dd0efa66a5674c13c73f4ac748b4301db19310a571512213d378c29913196d7592ea61302c4041055da40560689199128c82ed984c60d2c226ece53217a63e03158c06a12f84942285fac166b488929dd9260ca26d05942caaeb12473c20d42ab93c58fe5a46a0", "SS2": "1fa99c4f208dab85209323f9bc14dc725562d6533e0356236aefeb6ec5285dca1a1e899959105a671b5a563fdb8d43207c4b578f3082b6fc614169416b9be5c60d56235144686f2820499ec61c5a964eb8a306265cc944af132c21a5bd45f62c1abe38ca3aec1860a325b82bd4d1e35217a3ecb26eff90245305ee1eb79f8fe8", "DATE": 16574, "PIN2": 508, "PIN1": 509, "SERVER_SECRET": "1bb7b13e5e9ea11a78be76b51036be88552ff27b1a1069fc56e0119dbedd6cbb1214640d43abdcc4f3fb4b619c0017d4a423702b7490c0ea819342eb04c5185a01b8823e7e03229362100f5ee26f28e369957ca0008f9a6328318f596197551c181e367f36aaf63ece8d4cb754a5b51abe208a3ae3b32ab961d0c5331ca23257", "SEC": "041a2ff9802a9b9b8eef37058a891a459304fbd1fccf75f374389f3ed32b3b8e941d992fbcfac4b463dbf595232dfeff299f95b0b004628d0db3c30891b815257f", "TP2": "040c25f56b6fbbf83b45c27e1f3157848077d5608f18998ba443cdafb106bf4d9f00f0af0e732686084d39630be70ffe467757dbcf0add7dc349a2bdef438cc87e", "TP1": "04114cc669fc7cdd5a50d548cf1d95c6f09588f68a230156a1c92c181497fd1313093c1756941b141a02a4316fee9704e105d49ff12cd29f8ba925a08286d53e0f", "CS1": "04099da77a86533641520319a709b846b33729708a8ec4f9445800e866349eb4711135b7099d00ae69572a8233ab9279856453b7bb9563d9c4a29ca4439d1d716d", "CS2": "041e48a2cf74f8dfd4ead52e1da1bdd962819621a00be605bcda9ab494d3320c36126cd950d43188d5dee619afc1310bffb319a568c80441ad432d21958b97791a", "HASH_MPIN_ID_HEX": "c829e7065ca50afdee1ccbdba1c4ca16ba1223bc422171fdb4d03a9860a191ec", "TIME_PERMIT": "040aa869b0d6af4c0fc6661ed3a5c60c626da31a62abe41bf31d71ef9705f7fdef1534b7b8af5d1c680e4ac76a7d33354541324c4b22bfd525e567be27842a34cc", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34355a222c2022757365724944223a20223161353138666437636661656163393265303032316563653330626130386633406365727469766f782e636f6d222c202273616c74223a202237313630373463323435633865376261227d", "TOKEN": "041a83242c7317d6b06bbc8234bbe938d666c0e58242da1bc8e92e04648e0ccd6f1f4cdb280b3df8e49c148f4f7d24e00fef9f76dd8333b1ee6c8d0334abff3893", "U": "040d567fe59c7cead14448d4caa48e02fa323b03f70c78be6b78a41d55eea019290a3e610c059ea5b5c7452cfb1a7c738ac6b6937f7f71d05dcebf87ff514a675d", "SERVER_OUTPUT": -19, "V": "041d025ad9bfe24d5a45f14e40bd4b76acfd6b0206ec5b3c8a854a5d9ee2c66dfd02b7612385a3ac25afc3db822a2f0afb8bcfb3bf64af9ed50b1835a20ef96574", "Y": "0372f5236f234fb253dff8ab8af813fa05704e86c17bf75ed405ba7152d80f91", "X": "1a57cd4a32fb93013b2fe947c99343582590a93c7088eebd68df5cf92c7026c2", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:45Z\", \"userID\": \"1a518fd7cfaeac92e0021ece30ba08f3@certivox.com\", \"salt\": \"716074c245c8e7ba\"}", "test_no": 130, "UT": "041b02fba115b58ba2c227321600356a26da7078ba9c4c6c8f834d568c0d31fdc00fdbda5a7a95089b0d3d5cb391e44d6bac87137c54c7ad53ca43617388549acc", "MS2": "046aef08acab2f0f67ac419af77bfeeb0525420b935797083857878677ad9d88", "MS1": "1ce1f8ad6cedd688b485d06c6b7970d2fe42877af5a573fc5cf39f257c0b0e68", "CLIENT_SECRET": "040ca13f3fcf949d96701e1b0a70da07eb57cfa836c81a4b16b4da1ac9a45b4d581a81b9e48cb9b30b6dd977e0ca70e70770209f0244c18b48d68f9019f0ca8c93"}, {"SS1": "039edc06feea6adf26308183a48ae8b98107be8ac0e42f7f17c7103263f59d8b1294c97f7a0a80601ff5ceda68c9c14dc39b737c739d9cae45998d1d333ad4bf147369fb229a5438ad072d3b56f2b4a8dc0388fca57dfad36e700e1e90a6fe0d15c28e38a6fd8d9b34c3261d53c0bc54619e57878b39125c1cd2de99510ada5a", "SS2": "112f20a8f9501f7d228e36dfde55d48b60fae6aac3180202c71fb13cddd1bea608e4698ab086b610cf60b49cc9738221385f3c1f4fde8f4cda414b60f07bbee00921574baebd96cac466fc6095f8553405d4b19c9fad2aab9493df5f0aa55bc61bd83ab5d60bedbce62ce597501676b22d45373412ee0af46ba0ecbb3bbf4cde", "DATE": 16574, "PIN2": 2104, "PIN1": 2105, "SERVER_SECRET": "08efd5fa5f0741a114c1f17d54b82747a0324fddf0110cd6171d4a134fefc91e0976444d2dadde6e3bc5d0384998c8f1a0b7f4b3a5004964fe632a6204bfcd9d10d4c76edb1464706e3463547cb90920d2111ea3c1c016edd82d249f85ef99a418197f45daaf65ca15fd0b3fafe1862cc3cc988fc9ca0a41a7c72cf4d5c06b92", "SEC": "041084f101a2e3260fd22951fd1a9a6b335c1a36776ff848ba1e4bdefa90ff8bb40c8fdaf342c1fd76b9cda865c67464d5657134fe4e1cd596b81c283abec44f96", "TP2": "040bdee0492da1e84e96ed494a19a39c48eba3580263a53fd497318b2f7e16e751098b89609d91a9256e2b06de05277c0e8e951a13a9b7b1a72696eac006b27aba", "TP1": "04051bc56ae2c46ccd639053710b2ca028814902f76d7d84c3ecc44cf72aa782cd1f562cbe29f792a05491f948ef7be3dd355bbf37b46136ad818dc406cde915f6", "CS1": "040b489ef773a645463404c82d5218a5e7b3fed9eb25ab237334b4eb337572fb5b232025e21c9ca7ac67d635cf0f26d71004ac82785d2cfa57a17ff56390bd02a4", "CS2": "0413c587b5dfd3a40625388c1c5e31281f17d972e6a7f4a5fe12522eb8b3e41ca7047fe6cc51ed7421e706bf571396c21e2154a25117fc500d229926a9255e9e93", "HASH_MPIN_ID_HEX": "ea28280697431bfab50d9da240d1c3f890ca67ce866e0274bf08e3226e00ddbf", "TIME_PERMIT": "0405de7dc5116d4bf52e184f4e702074ea6119355bf2a80900317713eeda628e591f2d2ff29e0171060a0a482984c694694d0db9c32c7251c266b1274b37faddc9", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34355a222c2022757365724944223a20223466386665396434613335316263306365363036663537303434333032313036406365727469766f782e636f6d222c202273616c74223a202262353731666262323462623465313138227d", "TOKEN": "04093414fd088afb967c4e816a1528080d3bde110f96b2e9d8baebf4fbd95e6a670de3971db1490ca66cc2d13088f71c9154febaf1669db5c299e57b97b1c1040c", "U": "04106bdbd620ffadc84c4a82880244e6e91b9abd45a166eb4806ec601fd7f7560e1ab9e9fd9d527de9e418776ab2c68731f62d8ee9c18fe6f853fab2571b56637a", "SERVER_OUTPUT": -19, "V": "04107c3ec836594963132f49ce3c1e5f2fda3e2b4096982e7007ad2f944d133d5917e2c8d66b5907514bf9c7c1fb28d72c50ab3697ae02fe495d8c9c68b5ee7737", "Y": "0234b71d4b5e344296d12b99fb1f176dbdaa3f337af1ccd85234a127284d9f59", "X": "169290eca41a623bc19c53f136e42f74ed557f41df3148f66685f630bb75d135", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:45Z\", \"userID\": \"4f8fe9d4a351bc0ce606f57044302106@certivox.com\", \"salt\": \"b571fbb24bb4e118\"}", "test_no": 131, "UT": "040d2c308372cf1fba0f731120b7f2549402c0fb38e63dbcbbc5cc1d20d06fbbf40952ae7f21e520dd1848b4724244a8793c365b5da1f31d9b1e7b8931276ace5f", "MS2": "1eefbbea9a72c328e3a540608434a1a5341c1b74876fd6bb5b919200d5cf775a", "MS1": "03c27dfad89e53ac8a4e8e6d2be4b499513e7583bc80a7701f62cf0ff5ecf54c", "CLIENT_SECRET": "041c4037f00a487f46e53db7c6807a313148cfdf8433a1bcda67f1bc7e641a8a0c225a9befa1483d4ebcceb301870a16904f30e663a8ff198cb6de7490f02bca8f"}, {"SS1": "04f93356e8c5c55c08cb1e942edbf2ebf49c398ef5592b4b442899ef02ae10c421a872f0593e4d150d5f2a57d7d84dcd7d85cded858c1977e65d737c378ec4c6170731b8d5098e40fd0376902538524a02c6261b79a3149288c1908d1e2b17da1fa8218b7e2f6bd1f7a291d217960016f9c3f53cf14dd6b9b1f6618ee83618d2", "SS2": "1076791938ac7aec0fa24bcdecd6fb71b672260abae3760cc03e711baea2fe92143f8f2be497a5b488ed2d6260909361121b2e365bf376fb52d54e80d78e69ef1cba693e40fa54b8af2b411b8958f95e1098c109e478135917da9bd46f70208f1513cb5c4ffcf9b2898681348aacd66598b40502212f377ba866605f1698832d", "DATE": 16574, "PIN2": 2145, "PIN1": 2146, "SERVER_SECRET": "14de76f13823f0b97de97a0e7a3ef70f089ae2f49f5ca1d6b06dd5c6f5997e021506bbf85f9e5d0001c7a7e7c79f40719211b862798ec1b9b8cce72c16fa79e119b192b04da7f43d5b02e225c0d887164efe133215120cefe193b52fd8806a69171b58ac5d054cae854d66ee42371c1a38726efc88b5a5467a698b244de945fa", "SEC": "041cfcb970003a16f877db486f5a97c865f126d12dbd0fd0547a69427670838d1917103af0014324c2bca24ac8f63e42ce720854f1209aa528db4dc49d547abe83", "TP2": "040ab734001fb75b0ac5c3b19ef4b1f129e6b4a98e6cf0e2700d64e8a8f9f1853808597cf60a0e48b18da122fa4ad1fed8eedea49247e59353820f37377de4bdc3", "TP1": "041ff4448d56d791fe8c4ea46f5a44e926f240f8a0ae5715071112bebf59ac759600fe0586ca516b569f2cbe194f965f846f0b8b51d9a652e9104f5a92c522281a", "CS1": "04218a2074d82764d39e428ca0da5b69a3e60f7a26780fef7741481895b5e8ba47010157a50a27b08d56456c7d2d6c691470958c503b5f96954b459311c2602d41", "CS2": "0408717e9abbcab3f0d61a9f05e97722003f8e727a7c45be15c519b7226b8758c400f4ca56b581df813e71f68e33add032d85f4b55a1382e96e091519f0f717188", "HASH_MPIN_ID_HEX": "b06bcfb08b73bf2cc9cccea44cd93e96b4c2b6c9799def276f4d5cd8924e3d81", "TIME_PERMIT": "041ac5a01d6f2b21ed51eb014c2a327c8615bd2be6d8ff94e5303541bd176844680c1b062d745b288f59c3d92b02664d31ce5685e4d63bd728c82efdbb1af65e23", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34355a222c2022757365724944223a20223633613465666662396230636164613166623035656264363330353031623462406365727469766f782e636f6d222c202273616c74223a202239393831333438616137386538636136227d", "TOKEN": "0420e8b28f38563cc3203145ae3fc3867a544fdc49234d81f7ec180adcfb702e62170a75b0b0d1cd33396dfb2c70bedba3ef8fe3046cf700639344a3d10d00b63d", "U": "04123a17cb9e672d4163ba0480e42fcf00a581fd64c35c6af36c4d9a4d05d1b2d50979e1c9f331a6ac9e584b9a98979611b7d544f6975ed44a2af17c5a285c0726", "SERVER_OUTPUT": -19, "V": "041d216f5424ac27e93af8cb630cbfaa183d33ae94a26e82a1b62d08bf7a6d713806d83f2be2946c93f528f20742c5d6f180a5e21ac529c5de5c2d68ba24327ec5", "Y": "1061f6b2ccab251b0c4c4eade84226fb8eba098213307c0787b8b2db14b95c0e", "X": "1ff232dd1f691c320b6bc178e564668d5eed1db00ad65faf688fc44f84632b74", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:45Z\", \"userID\": \"63a4effb9b0cada1fb05ebd630501b4b@certivox.com\", \"salt\": \"9981348aa78e8ca6\"}", "test_no": 132, "UT": "040fde13f50934b68415912d279252b1bf355ab2dacb3545610a32c881f42d52851ba1af38f82a37db98bcc4c661464407f2a57017d6590480a9dd725e2d3a3f2b", "MS2": "21d65011effea424482a794ad0cefaf72e1e3b35c1e266200d4457c340ec9854", "MS1": "02b026ffa463c2fd4cbb11ab86623d89dbbbebab5977e11e1d2e95267f9d1b15", "CLIENT_SECRET": "041741228ff0b7eee93de64f07ea289cb77cb3ecf233d474b3fb7c9eab49f01d6d1c172cafa8662602523ccdb6c705fd60b05c79d6cef2cd403e5fee73c111b7b4"}, {"SS1": "0e11cdedd036b09bf718010d66cb73d2f9c7c2dfe4c8f975ae7a45c4cba093740866110d091953cb443d1eca8fe73a0685df114de33e280407e19fb024a18f9602dcf593867538419abdf9b74cb4537945050261204e7cd9533c33f80c97d31401b3e935cb75d5eec02bdb5c9bfbb19b4e26d1a192196a8352599398927d5e72", "SS2": "23c016151afea97981a8c8f26c84c39b344a18f0fb6142318f42ef6aea162374089eed6014a9e6995e8bf381dfb03a2b1c0d3e231539107a336dcc9411528d8d15d06a87d307393d387945b607aa897fd268962a8e7cdd649d020f33015576070ba7b817d4e4baf5f9dde8fd46290771a8b77db75c773a5b353ff770ea823958", "DATE": 16574, "PIN2": 17, "PIN1": 18, "SERVER_SECRET": "04b148cceaec38e853191f81cd868e4a8c0b99c3a1f51f3e2d6ef017617d668512530f86ca47ae1cd2305d6a0ce5e7bd114cad78aa6a5bb9e3acfac2a065840e185a402acd4426a3c00f6528e6b3afc57041693e65f0403b3a86e702ea1597cb1316494ef083b564e6189b3ff1fe38d5efed4d122d47ec55d6bb465acad4db89", "SEC": "041e60d95ec5e713ced0fb1981beafeb420bf02fef706fa1d659eddb370fa2d10f12fb6c506bb1158fa377abc4f0b88c8cf603fc389468847def1ce4ff722ebf4c", "TP2": "04116c2b9490d61135e586e153d034dfd148a7f14f620e34f46e808e2aa1587c5b1fb00a137292b890f8c2a7c4f3d2b8dfee516b2b453e3825f4d4b6573e9d8872", "TP1": "040810a63ad2f215fc631e20c465ac293a91862e68a4aff1c10c867179b34cd4311549fd9d7412fc23083b74b80c18197009905c20a110cca004766a9588b80999", "CS1": "04053f7266694e068765997032b260b4d0effaf72e7f99a44244931ea72e8db85b00dd8f2d33bafe84dca94081872d2b1c9298e600ecb950afe90746877d4db371", "CS2": "0407c55dc713cfb3b61cd75075c95252409ace2b566ab3af83c29820b13259d5a10cfc0e10b8160900a2cd25ab0d72a549bec4de1f205830e602e35613e39ce843", "HASH_MPIN_ID_HEX": "6894a098c98db36a6bbb3b7926209809b153788260b953ea0a9296567f7c9531", "TIME_PERMIT": "041ab9d1acf6fc0a3e76e9d5114a6068d491667298fe3eb325670ab09add781630211c4e19be27f07e25e4b3cd5d21a9722b3033b3c6bd93769e32296bb064f718", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34365a222c2022757365724944223a20223663373464383035316633646533623163626265636265353032366162363263406365727469766f782e636f6d222c202273616c74223a202235396132363361343866303530653532227d", "TOKEN": "0423dcc36076f36fcc8a5ea63fe046c0fe72213c76050227bba727bc6938513c1708673ad112034669ae15615f18ae27a13ad547b963199d91c6e63fe553fbda5b", "U": "0403b6fd51bd1ae04eeba8a109bb1f1ae249bdcd16bc7d78b1ab06ee82ab13d2f709edea7b4615e9c417796063b28e0c6a8345234f1f6b43b1641689f2b9ea90c0", "SERVER_OUTPUT": -19, "V": "041f49d28345236fb9ab5abeb06dc9e362029fe750d23ccaccebfc2ba2eea4209a028c1be60499620ca2ca904f004a1f11f2444e404b6b7b6d0408b8a0ed218e19", "Y": "006115e35cd43c2aa696c0ae4a73e46b320a1b34cba3132b6be5dc06c309f986", "X": "09e1e7050cce7229a2a343bd27d3e09df585ebc3a4c1c10cfdb4c462ea4d43b8", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:46Z\", \"userID\": \"6c74d8051f3de3b1cbbecbe5026ab62c@certivox.com\", \"salt\": \"59a263a48f050e52\"}", "test_no": 133, "UT": "04131fa8b234139a89d9be79f42951e8d3519541da5350fd7414cfb6e992a91b5214fd928a6bc7112021fea3fbc0ec3b8efb4466c8e1c6a071ab5e9f860c03e33d", "MS2": "0b787b71c88ec697c8baaa0f280b62550b546219f9c83bc9114edd61a83dee95", "MS1": "229fe54bd9e0dfd480ad1cfcb3ac8dea62ce2aeb20188c6a771954cea2f0953f", "CLIENT_SECRET": "040edc5e222de3617f4a3c555feabbd5791fa3d9b3f9739c440bac076499b689be154f15c14775766261ec834def4de4a2cafeb15c0fb5faaafa5da45f848ab9be"}, {"SS1": "0122ea93789dd8f0f432629c35eecdbeac3089938348ed475c5cba136298fa5e1b571cec6d8c081c414331460399a8dedb9b314dd7d8eec105d44ce9ab57bf751ed7c59fbc2a9fb3ef6373f6be003e5c44aaf96ba0310343cfaf0f9647fe505a1dbe2e8019580dfa7ea401e4e803fab2a8e9021eeec220b69ba489e256a8c4f7", "SS2": "21f9bb9f552fff1e2b174edf3e1a7eaffcd5c4cdc96ae7a1d4f639f8db4380991565081cb45d66c84ea2f49ce5a61bfd5d0a0678e71f31ba4f74987c58a4762c1ca32bf10236053777eff533ce9e3b13f7db2d57f10beb73d63389e151a6b3ca1639b8dc8654c4e5efd3707b0e3ee24dee80ea6bedb0dec6dc6de400cc217299", "DATE": 16574, "PIN2": 8292, "PIN1": 8293, "SERVER_SECRET": "0971eba0f2e9c325e0952920aaa0963f96c834e3da4e96d9cd063a89cab4c38f068fae5899433caa14e6ca05796ad41013b86eb067a02fcd400ca118427509e00169c77e1f8b4034bb790cc2f23c2847e9c8693c239d64acc7d20817821d263a1df1c3f4297b88fbe5011b9eeb45a4cbc3c7a59013fbefe522e680647f1ef8d1", "SEC": "041d35b090e6e48bfd3fc57222e2e55aee91abfef61dd3a4cabb02396d84f9a39103b6c34cff64a07776e27f05d7fb87bb7a87f63342d11e942f564c201677a2e5", "TP2": "040a6d571e32883906bdf7d07cea5f7ed75ce5d2b2a1f49083d37ff0065faf4f851b78a4b06918c6ec8f628b542ea64bf10955b7d6c302db9383078497db43eef3", "TP1": "04192087a7bc5e5551b882c3845be46329ce884660b03ea990f726938b54fbbcf81bb6930f24b89cdd1ada65ac7446a66f84812ea156282a2ea1bc840ecaeba0c3", "CS1": "040e2f5f9c44b0831a70ca34ddbf2309c326d0dd39868f196865e43e401fde92ee0e1ed9047d97222285e7256c72e0ead2e490131fb004ca39086b4518258d87f8", "CS2": "0411161dea6b654550ff19b1954ae3f373d7a835d837107b35551a193870e464fd22dcaa23f3b7326595034989ce82977b269a739c1c6af1b309ea5bbe9282e053", "HASH_MPIN_ID_HEX": "d343fc2a17968dfd5414611285cb311a5295f3ceb74d669a58c6bc353b3e22c6", "TIME_PERMIT": "040c5ac04debd0ac72f8bc9e8ad78323d13a7497beabedd0ed36ba39fe4fc507821cba83105a79c68d5ae48c3b476816fb6fea2e19b8de53c69403b60f6b1b8f94", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34365a222c2022757365724944223a20223030363637376630393732633730343264333330306632303332653062626336406365727469766f782e636f6d222c202273616c74223a202235313763333438653065663263393466227d", "TOKEN": "04093a81bcaf89c67768d9dbca694130478ff18cf5908d57e140d1255ebe2d3e6d034ee0ccddabdde6c1d0e4f51706bf36e81f800448b1ee318ee9164830778a98", "U": "0421074255b056f3f2fd076f4d53eeccd1d51396e849852c6e033055d8cf56fabf220d4114d5d00930db868e2cf4137eb296408205e4ade1839b9d9e8028eb7392", "SERVER_OUTPUT": -19, "V": "04018319394d0f51634048992f613ded2e377fe0351091489a66411bcf59bbf6050f4bba21e37d3bd4f5e2c3fd7b19f3971a25bd70adfa0404a8a95e62cdc8280a", "Y": "0697d2ed5539baf317d6c676cad62eebf20fb1fda7708222fb40f25d42753eb8", "X": "10ff7ea68137f97b370d6b1242362b0820c04fcec01215388668ce18611d031e", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:46Z\", \"userID\": \"006677f0972c7042d3300f2032e0bbc6@certivox.com\", \"salt\": \"517c348e0ef2c94f\"}", "test_no": 134, "UT": "0416ca9c5e872291af05f8a71bde0bd23e1063243124c709a6f589b118d0dc36e00711312b299b580ff0ad0c08f02e3b44c954bab9401a9585eaf6c274312f26d9", "MS2": "0f143323574162f03c24a64684895b26d92548a264d2a42c503928ca0e0b8a7f", "MS1": "106874d80282c0396be240d8928c4575dda14965ec7f7ab545beefd75d1cda6b", "CLIENT_SECRET": "0411fb8dfb56087595df15611450b0d4fc93d0a423474d83dbb374f49f279d700e11c0be884b7f3bf4dba86546b05aebf5f6585f1507b8e9ab25c18960dd6614b5"}, {"SS1": "065790d9b133992b98c711f5f27f139a59284a3b0a66219f96ce55a44c10460c23ed750721bd9b804a80c81ebb0867911ae4456b34474337585fbd0488cda486216af46817181fe46ac4f1705c04fc94cad9ce222bef9379b7d1a14a39a4baba08e4ee99dc78fe667218a5e037ccceea506cd289026a5a7daf803ec5b31bb38d", "SS2": "16ede5a298b0522dafe590bb8b6421b888657616c91530dac674143eb025a0710e0f34d2e825664cb4cdf5f7e39509527cb156fde1ceb9d6da4af80d21413b6b17c2b807004eb28b04c37f2adaee340030a04648740600e767cc8782b0faf94f02d13836f1515af6fd30fdc22da2ec99d5400ab0defec11ef47edf95ff645de5", "DATE": 16574, "PIN2": 8119, "PIN1": 8120, "SERVER_SECRET": "16cd74e2f1498ce36fded71f22d010df184ea841250cd93e200f620434281d440ee30e44cf37f6abe82443f6b4d11bf63ba46dc452ddda6ef81ef6552f68e74b00d9fbbf2c5508d7aac965666d96455f84c40ab843e606783e95b5b70f4acaff118d7d170b9f1b3d6a4e6b121874cebace757294522ad4b00c3fe303d2f3a81c", "SEC": "041b0c85056c055b375fc39218ba72965650b5432e3cc995d8037aea6f6564defd1545f40d8631de70b0ae0d65b124a47fbe22cab389607ab1695a20e820636b68", "TP2": "04108e79442fee0232dac1e39cb75e95aef5e1d94988e4acc7913550a8b4b175a90f57e180c850d7599130d7cd70c055f02967ec32149f07b7ef05c71ea4dabb1f", "TP1": "0413f37c746916b8d034154b596679d5195587467cc01664ceff88318b0cab79a602c01492af1dbaacb85ddf1aa91859b0dce7e6ddca908776801c6135205f3749", "CS1": "041696f910d20c542e29d5ae329b92070dbf723680b6649f21cb96056d6d57236a126aea9fc8f9d1dd3e4366f7e68549c65be59e97485dc5438d366c1b254602d5", "CS2": "0413956a78969b514d4ae1d268a365d3fdfc2d38eb10993e4acf4c33cc8030d88a00bf98f6394a9bd66e00c54443e5036726ea2c522b89d1cd8c7bbe6a8eaa5873", "HASH_MPIN_ID_HEX": "26d6172e2d03f37174cdf8ef466797590f1017638e968fcbcf6d0810e611fdee", "TIME_PERMIT": "0402cd6ee2e01e4c649f4e2ce16d6eb922732449c6094390a19255030fb5f5dea00128f0782aac9bca033c32781d5f2d09c9c4cc475578677f5e2c4a928ffe4a42", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34365a222c2022757365724944223a20226561393561343861343930343530623635326632663662363765386634313831406365727469766f782e636f6d222c202273616c74223a202239373538663433396433353831633565227d", "TOKEN": "04146921f265eea1806803cd4f335b15647a71e2a0fd2fe384ee97d5cd570ca4990a7c7b816111114457fcf10a2041e766e6890a8e1ead936ded20c941fbfd8cab", "U": "04089609f78604ee57c37cfdf733b53d504f50d730e7bddb7059dbd04dadade0a511605754468b9e4293589fde58e03022df7c36565db39c53ad8ec13d349f08f3", "SERVER_OUTPUT": -19, "V": "0405fdb03bdd3754a310192cd37d82a7cd4920be500dc69fd4f7ccdf581b311d2a0e8f941de2e962f0c71bc451899f40c88898adaa87138bc50223b336c0e48015", "Y": "06d79d0f1127745d94a68f872111917d47d6d9a29d4d9b0a9b706d54678cf328", "X": "0f6c7c8ff6d46f8783ac213f5438c02071ab05f0e7c800166491898008efc195", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:46Z\", \"userID\": \"ea95a48a490450b652f2f6b67e8f4181@certivox.com\", \"salt\": \"9758f439d3581c5e\"}", "test_no": 135, "UT": "04110d2f16c338934c8fabe90d3b43938dfde14cc794fad400fff0893101cb6e4f182fd20933e2b84b0f2778c27b2587ec72ad64e4eca8be086206f2523d3c1f24", "MS2": "15084e65fc0793c212d2d3678a6dc2e5fb3b0741fe765693e76f88a977ffbdf9", "MS1": "080c0d6f9b9c01f31f0fa084015ed5e6e563035ad0f636d464b8d441de8d267e", "CLIENT_SECRET": "04029fe9a24ac5bc930bfedbd059e5fdd1c6a39a36a5a05cafe2fd5401b62031e0205059f83980b11bdb229be260cc465e804d2f2c756b00f16f0470a5ac1dd48a"}, {"SS1": "20ec756f7bc8eb39a9f61cdc4ec9384423f0467def9c41714b451bb9dac60004187539ab03465a01f98ecebe56877bf476fd4b6770727d1bf8a5c9590b0bffdf0f2dc811817738291bdde5e2442f246225812a72e975e96ea1d3335279db88c410251fb47e6f7c7966b3183ae35ec02199d448c2fc50a4352465d3e6e7277204", "SS2": "019aa6ba0d517e8bd4ec2c039ef632bc5fc55d82e50168d561b2cbfdfde3a87c039e128595c10c28eb39a729e747f97607da50b332b550a84d9d9bb5c0b17bd0091e78f518c8435a9d1fb687cebebe3f8f9c8ddd39e7506490da4d0a096f413520b050bd59394abe3490a9463c718f191948031706d044c5aa33679c82f49e00", "DATE": 16574, "PIN2": 5235, "PIN1": 5236, "SERVER_SECRET": "04a402e80a88105f6a0edb8c4d97c85751699cde9ac30220070b345066acd1250487bcda2854a57a44d6e55cc7381e9ccd4f32fdbaf61a2401b27d464d94e7731596684e409b77b10e2e023178cc7037660bf6c9f1b3994ba6e768f83884622c032c01d1762b39441fb54920d95f2295cdd6e242ca165bc9323b0b87fdcb7a62", "SEC": "0415b5a45bd5021bab23eff41890b1928009c42520e66905cccc1f874869947e091183ce60a32e62816b595bbd55b0376dd0392ed7a43032e5e2ff30d928ff0bb7", "TP2": "040a78f96b42b98c89e2ef3eeb0ce463fe51ca4867386260e6c3d04b18331d13c710f1f5b3f55a2dffb6614f3a87db05bfa657a92a7ec4e8a0d7ac68c17267f2a2", "TP1": "0409abe0e32b3a91a0d794f16e9df87d02da1fea9d72f82bd05529229b22052f75186b5f6c42963270ae3969e43bb913dd12f6faa0dc35fe8c4b9a4e9896f7595e", "CS1": "04027d39b638f51a9b6a75631a27bada47033454d02519edee73f3fae7d0f08eb41e45b6e495f8036edb58c1ab1551f007caa158565346c16162da560f70ee5478", "CS2": "041f3adffa382799d0c3d757303a4b54dc7c183bfa96cc3c5624bd35c50004239e109ef1e9e4358c2afeb7c5a951ed360e1f6fe3a76885eb34e7522571dcf6e16f", "HASH_MPIN_ID_HEX": "dbbbb1822e1733e33e54e29d5b935e43badf36fd5ea2020077fdaa38eef263be", "TIME_PERMIT": "041578cc6b3022ca69638d4bc475935e717a5df31f35d27b4e4033173f5d5516a917f97d9921d1df2947964dced8aa64a31b2c27588f76bf3cc363db2eddd2fc79", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34365a222c2022757365724944223a20223735383965633631313066663938386138386234313537623863646165636331406365727469766f782e636f6d222c202273616c74223a202237313061636165373366313162303963227d", "TOKEN": "0402e007103748977cf1838c5efd5465752f8cc4a7f448b237542c155bfcc9d11f21b43e84bb88ddbcd4c854d5481517ae4920bdba58cdd75fe83f8ce46f70dd4d", "U": "0405ed1077ec4698b2819c499512abb76239235fef721250027d7814ab287154f01c3ea68decff56d012ec2c16bed33069954e651ccc369af88c7859bccee46667", "SERVER_OUTPUT": -19, "V": "040825298be7f237f5a99a6a9d92466598da49819f38113a59afa6923d8ae54f6e0d1c564045cceb62c50a3751faf0067e07917dd80edae77639d04208b480cb23", "Y": "0e9ed0f06d412a17e0a91d5f1c68d24d58a137f202e3de7cdaf72e4d587ad6ba", "X": "1546c98b8d019b94dc4d9498caff4c357ced5a9c2f23b7eb8ddb90b991c842af", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:46Z\", \"userID\": \"7589ec6110ff988a88b4157b8cdaecc1@certivox.com\", \"salt\": \"710acae73f11b09c\"}", "test_no": 136, "UT": "0413b86128cb1a8aedae68a62f66c4ed05039021f5273081968f988b2c8e8232880bb5326e425e2ebe020289a5f9d5d3480bccd1d57b3631dd1de77a6794be5cb7", "MS2": "0e7a7cbb4738dd632d0a8591b2dc5400ab79301b0253179a79a46249dcc0633d", "MS1": "1dfaf1f8fbc1e73ca268da2438779761011f2f323d4e2e0c2e7b7dfdfdc09d09", "CLIENT_SECRET": "0409dba5ada58542b35c6fa821aa7ee0dc662d632d6c048eea0fb276171d86863a14d683220f17c91b4684ff48095704ae1e36ca9b480ea0d2ca2effe19d22af9a"}, {"SS1": "11d04c6be664a9ee8900149c4bd176db72834f46f02925675523a3508325028f171c08a1d6b16ca792a5b8006c17a546b1d2502ae15e7bbdd25a5bd0a306859a208b56293f16dbccbb83781b12ba6158d87fe9992c6c84a5ad156866f6267a380b54fc766ba63ce73f8eacbe4a3d06414cb4b41b4515fa068d30ed0162f93feb", "SS2": "051235d7a207e299654db1d0405ce4bc5be729efcd78ff490cb999069784677f111e18cc268d3064cb4deec9715f9e2f7dc6c72fda4c9d0ee276f44bd06172c116122bd3db7d865cc22a7c33a67062b557f14419f7fc415556661f02f729d09d10897e87d598eab742f8bcc92b960538fd33ae033a7bd32982333bb474de8ffb", "DATE": 16574, "PIN2": 7073, "PIN1": 7074, "SERVER_SECRET": "0fdf53b9e291dca9d4d5f0e44d616e6de62c8c64f9a62fd04cd2a44d3cc67e5b190fd0f4d58d07db7efbbfde577a88d5968321a3761c1052f2cf300cdcedfc091513b708815e9d45b3c1b15b2d4cdac06c18b9a969eac4bc90c3d12d2eab1b291947c1d46cbb8d36485dbf4c3471b06455afe4ffda78b03c5e1a8785b8fabb74", "SEC": "04027a2fc23aa766976be3a2b8475cbe63569c5b2f4f9fcef585523f32e37f1cc02071a8cdd1e09655c36ea663dea1e2d09ee298c7259fbbdda13bc64f65c40347", "TP2": "040dfc8d2a955c1cb5ac104efe3fde67d3bc0bf6fdad88c73e5eba0c3b9cb144471334414a0ac2fb7cdefa122f7afb271e84378eb681bbb4586f5bdcfe74211cac", "TP1": "040a6fbb4d080ade2fe426bc29e53a5f7ba8a47bc974531d67f7a53d2a66cdaba619a8463b32b013c3aaee4085135cc528725b2a017187105c05b0836ff8393f83", "CS1": "0409248826e9213f693acabe93de066f5defffa3c3920733a115b2797093f8f4281bcd7a47492b84382307d1bd4eeb976c2886118ec2e68b273dbf9a8caac9396c", "CS2": "0422f8905740bedf9199ab63afc5053ceb27c66bd869d38ebf5bedbec661b661cd0f071a8930b3c3224fc275012178025ef251f4d9e90e48e03a5edcdf32319c87", "HASH_MPIN_ID_HEX": "8ebfa37a0a384b9d9a2f6ddd0f87a926aaf80ffeaf8f7a7dc10e09a52d27605a", "TIME_PERMIT": "0410780810827441bb3437e7809dcc19a23fdc87a9b731f48923729cca24ba473412a5a01cef4ac35bc679cee5516e2faf14bfb1c1fb09086d6c2df6ec16e93b66", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34365a222c2022757365724944223a20226436343330646131303966303835373033656665613839653435663766343035406365727469766f782e636f6d222c202273616c74223a202230633335376539623831656238386363227d", "TOKEN": "04221d4686d5057721d83318d27a22f4b6b0fad4627dea74a47ae8266b7cfcec241415a3c5ca39fc8546b1103e91d6aac7091d943b7231e906d0277cba1cbf6d8f", "U": "0400c7b46e53984b5c893285e9216c8c69fc17bd5b720c40a3934a43a6cd9de61312a9ed3eece4d1cff318570ea4508eb5f15d542f4fd09a91e5a5aef76e732455", "SERVER_OUTPUT": -19, "V": "041bf41001b7139ac98e56d8c9b12a2ceaa11e78c7b0df931db5939ad368dc12d612ab0b802cf38813d1c1cbc62378f5ff9c5903ffebe91bf9d1d3172a30b6a6d7", "Y": "120bf0906bdcde932377ed05a923a92868507fa7eaa08d28bb48b334251228ac", "X": "17405c8a71473a28dd95d365293f0a58cfcd9d0a961a626edb912dd6f17a75f8", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:46Z\", \"userID\": \"d6430da109f085703efea89e45f7f405@certivox.com\", \"salt\": \"0c357e9b81eb88cc\"}", "test_no": 137, "UT": "0412189c2a25408b085ef46addde9ade6141d8c46bbbe7ca68d9a3b538c7557c4a0fa3a73627d6ee67c16e2185a86e599a55bc41de86d13762dd2aef3ad5f69e53", "MS2": "2025888564f59bee3fd6e5ed942e3118537cab573791c4e3551b66fc500b3935", "MS1": "0d0b57a21386cd2ef8b8334abcac3349d9b0e5e159d0eea7d42ff45ca9da087e", "CLIENT_SECRET": "0401d8a7d3c198285eb35d4494b10c5ac334f24f19f500d5f3f847acb214ae8b63235f7352b3a11cbc5da0ee7bd0dcc717cac2c563787354d39cdfeaacbeae487c"}, {"SS1": "001815697ad18a849601b14f0449782517ca089a1372fa88029b6bdfa171eda415d64e7979b5d391beca8187f21699eac92a438b50ebfdf4aca4b9847ab16dd911036e4ecfd38f12dd89c29b5193ae401ceca280cffb86dca71512d03fe05adf0cf560a4af15add2c50d24e2369e70c01e98ea6d24cf193a4803dfcf9f240ccc", "SS2": "029d97a22bf974fdbcec6985e64a6de091f9954034eff2052e7aff563919cf612138331bafe2eac644d53e8a47ec677c86da391a517d9838a95c38b242da7e581b5cb11700197d49f4df8f8ff17faeac0be5a39c4d263e6ae116b10fc64d15ed19766c6136e424319c3a094bf1eec4cc7ccfd2703d61ef9fe5b569d59cea54da", "DATE": 16574, "PIN2": 8732, "PIN1": 8733, "SERVER_SECRET": "144a62e03bcc9ae5063e61995ecfdcfae1d1ff37bf7a83a87dc7e49fc4ee778102fee32afa09596e8421dbfa56e38b81823b771d8dbb82eb4cd5a7f8abdff8df0adde7c4ac0f5a970877c07a19123b7c786c08369e25fdb6697521219a0c53de13294286cff9c9d3559aa04585429249f722a0c6d5f1988acab24e880e9e88c8", "SEC": "040f93aad3558679a50806f02b0b8d80105d1d6ed281b708ea585a4b6a88bf3a4923d59d96613917e0ca61bd871538d7ac301ba3ac5f501ba833f170437e52ce22", "TP2": "041d37654876cf9a3e61ad90e553f2852b7f7b8491bc672690e829b32d62d79cf40b2d3eeadea509d4050fc623d1240b9d965c32ce85473a8f2da9db2d34b621ac", "TP1": "040c90ad656d9066c48f7f30f27fe30511d8d29f864680a2ac829b0bf95bea49911962e5b80ce6cb68f0267a824a9c34360a98c96f1ee6a03715e810ffc50d18ff", "CS1": "041ecf8eab7da8b9bcf9c55c4a925382cdbc175507421c62f66f2bf3a5bb19ac9b0a64de5e6ab052259ced8ef1feb39565b2684f79bc6c262b6cc789da375e4760", "CS2": "041e66e3a8bbfbbc80c0084daebe6144f4de9946787fb435c5c191654690adefb71c75a5e01461eee6b85cef0b5ce515a082b84f2e27b28721c1c8cfaa8767a13b", "HASH_MPIN_ID_HEX": "7290897e8ae4fdbf5b1088bd740a9a139900d473f26032e07595a5f30138e434", "TIME_PERMIT": "041e7e8315f1b6cd19043c61d0d2a8ebab405c0ad03e7d3a4cb7ec224fd13b335e1d2343068ce2eb28bb46b0347a7440d379231f49f1817e59622b4ba98644c976", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34365a222c2022757365724944223a20223361396261343130373435653638373563663662613938303237343062373764406365727469766f782e636f6d222c202273616c74223a202264643162313666646662313664336137227d", "TOKEN": "0420fd236e8142855eb443bfd9dd54f38932b2558b985fdba45ae4af1c4a9125871e9a20c168a35381c3f3eaeb370b2b004ca569979dd83da203d579939b6ffe8f", "U": "0413635302eb9b7430bc7dfd1ee00407a421bc9a2b538070055fa9c2bd756522061d281881807e0407d1f2ff30b6c29958ccb3a8eb4f11ebcf9b4e05aa722b195d", "SERVER_OUTPUT": -19, "V": "041127dfacd10909980ce3eb6c66140223e3367361aacc52b97c5c4bf27714c476127f3e3e344103b201ce71987b349fbc0d8a6a08a49f97f9d35dc875168fe65f", "Y": "118c8cb2c9cfc05c44058da2b6b9dd73067bce89c8fec003fcd42b4d823dca6a", "X": "226d00e6d09445ce18941f76bb3bd9b23096cb7f4779deb819a1106286dbd438", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:46Z\", \"userID\": \"3a9ba410745e6875cf6ba9802740b77d@certivox.com\", \"salt\": \"dd1b16fdfb16d3a7\"}", "test_no": 138, "UT": "0421b6381f30d4fdec46e39f6e418fe9b4988412ea1dc564f160ff94922415042e00cd7f9841b0c53d743ce767582e356dc8e96a0e915c2188f39010d30ed43e59", "MS2": "1edec98e9726b623b8178c2ef2e5a7c5055a01a8380abdcf6e50b54221309df0", "MS1": "08f27346ee5808a1b5d6a6af25cf1c1381e4c44c8a477a470f563a51563bc094", "CLIENT_SECRET": "041f5ee392116d769be319ba300ae3761825b4e44b2bfc6c2ac974b8cecce8d4ea16e82ce0430e0c1870174a66d41621ae9d1b6659c21069919b07f54c42486bb6"}, {"SS1": "1f4b63fe242d23e10243ec30ba246f2e56c82da3011bf7730b088bb8b7a4f3fa1bedc76e701d37d3d0c3b17af9a2ae5b264ff09a9bbb11d2699f58fc96c1ca140d7234272a566a982232b8a3e16e01e8e855aa39e7a8ee8a69d8a4f0ce1be60e0f54e8fccd6e39ec58735534dc753b1a4cabe877c24edc7b7794d52c8e984bf6", "SS2": "07e38070f13a00d3cfa1e7d3f64762da98e371f7caaa5672348a7730b770ad5119b4e5d1a714c1225069e33eaa224ef236e44a9a5ecf4541d9a8c326411db7c9085d4bc6466157a8d7742ffb3fe16d8bddd2923884e18e30ad3af258e82cd27119c3edeba03ee989d230cc2909e4d3415ec2c55ed9607265562e5dd210f8f5d3", "DATE": 16574, "PIN2": 1301, "PIN1": 1302, "SERVER_SECRET": "1ca4577bce00e37fb10eab32edb3e041b3f72dc65ae13cf7772e6894c750b1c804b938cff5e9d43ffb2dc5837cfb8f8677f740aecfc73c15da30f342e6c6b7160945d47b3249691da435414aa82fa8e3a7d4b4ce9dd2ceedb33ac2e864b754ce1a0b92a0ccba13e4cb0fd8acf7eeecdd71accc439ed6d67d0121d3fbefb2396a", "SEC": "0409308a1361de5393ddfe3c14e9a8957c077468aeb74710c09714ff00e3632409033892f9f1fd8b0da2db277ea830af2ba429ebc47cc1be7822f18e51580405f7", "TP2": "040331024e49ff53d4a593e266321b439672d8662f13abb4532f947de91c17363c1527c950e27ad1c66624fc81186cee585384570b62712c2d4437411fc0138c37", "TP1": "04187907080c23c75dc323a5337cc4e9fa59442fa20e619d2ba3ad796a7da280031cc4eb9407bdb6d5518ae596a890b59c55a4ddbbcd5ad5c9aaa12dad09b7191f", "CS1": "041ecd5e3c359b11721996b22c9d6ce5c3bc1088dd702abadab5fc263d93d441ec0477c0706539366512b8bfa998c8882ce88f1b61f282d55dd29e489f87738ea5", "CS2": "0406cf9836eb2ae5aed7adb21ef2687615accba27de863d49b5e3964a8ea20df112130f5349fc985c4fff2a6222ad2083cb145469129039272c1c859eebdc5ee2b", "HASH_MPIN_ID_HEX": "cb50ca75d22b01a800163bef423bdeeb73fc3f29bac374439bbe6898800dd1cb", "TIME_PERMIT": "040de18d993c024045cd7915f5370fee4d6e611adad137148351a15a6d47f777e91f7fa3f81bb35736a831f8b6cffcef88554e54e00d9a86342c735635fca8360d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34365a222c2022757365724944223a20226466386662613436616363313566383934616334613739366139376461346237406365727469766f782e636f6d222c202273616c74223a202232313230656461653731643664343362227d", "TOKEN": "0406a4d51602280911e5919878eedc2c55e74a37f3c98c1f1353b4a1f51cce426a19892519d8df9befc32ed501e68553035426a7a3ae770aeb7ff3488d7e2ce6f2", "U": "04188e161ae44527452a8622b7a9b11dcc72d946fe30a86ae728fb310b920afeba0c76e7022b7779c2005c1cccc36076f7736362f74241324de1a62cd6be92af3e", "SERVER_OUTPUT": -19, "V": "0409bbc27160051fd0e8c607eba682eae5ccb8749217ea23a3894fc3b6e17204d2143dd4c195df4f9f5476d41642debdb2680469ca7170715f08ad631704fb42b2", "Y": "14805ee73a46e0360c810e1d828797036dc0ef863fb564e210827118dc41f733", "X": "21c28fe77dbc09d3dd2fbaf87f29550505d0cda97996918d59c1a42be1ea48bb", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:46Z\", \"userID\": \"df8fba46acc15f894ac4a796a97da4b7@certivox.com\", \"salt\": \"2120edae71d6d43b\"}", "test_no": 139, "UT": "04233545c90056d506046383427248092266c0bf0c4cc9574c4c4dfabf63b1d4e518f428d07b914158f7f4f12df092748e9c98b1cfcbac5fe29522d0bb57337200", "MS2": "1fe541166971c6aac8a06a0d78873dbce91c9227760cb84ff1aae4748a9f3951", "MS1": "036fb4d528a513ceb7df591de8fe14b1acffe467acbe8d67221e8c1fe4822672", "CLIENT_SECRET": "0419c7065cdc081fbf046539ab41e06166a36ffcdab05561fed990c97ee67e81510efb31a0fc828662d225e42724b5c93a90e6977a5fe1e96d8f301116006b4141"}, {"SS1": "13ff24d0e36c61f79394eac52bcb304c8830a629268e3a4d48756cea9380192e0b858d0c2d65894e6eca16db0bdeba09a2c0b688492f16d602a4e14243da1f5523d53e25f9e0cc46a3dac8caeff0cd54a34688ab924ba50d7f4b0537b76388a21588249ef7cb3d6126ea7dd08a6c53265a86122546275dd02a4ee309c3dd087f", "SS2": "12bd8bbab3abf98ed266ee8742f19456264abcb120bd848a8a53e81dff19dbfb191f1211271a0413ffaf651ec0def512452978ea016826b435b0961b930b79d81a3c43df38dae132e1749e2debd9587c8a81dda480eb283d9784695f9d1a923a074fd41f506c61665b8f77ac54c6a52fa829256043c1ab6c8fd61e91c5e642c5", "DATE": 16574, "PIN2": 4523, "PIN1": 4524, "SERVER_SECRET": "08002f33fe347044ac884d5916c075f2cdd11106bfba33e32b025ff262ba7a8c0a197689c61d12cd7c2fdaf55f3c0e86bf6a6fb23a415add7a56ac58d440a42d228d64725bb8df30af54e1b830f9e27adb777600ef39c29caa62e273eef18f7001f45eb54ec90a3f814f159da990e3d27c3c80a6a24d7a5fdaa4e4da8507080c", "SEC": "0413d71f62c1a08fdd644a7b8a83b959bd4e2c850b768992ebb5859666aa5836dd0f46b1da3919653dfbb402ee15e71c0d2e346d20e51df0217e59b85e1a5c2fc1", "TP2": "041b55cf68dd4dc49e417719f178a9b6325f369e88e4839085597e85939f76057a1b91d785b6e5e50ce85b2df2abb8b0cc49ee36aa78118df33e2c9234bd8a50c7", "TP1": "040be5e0c8dec24bdec065684cb012f792038261258642207bef70a99b19f71deb0fa3e5d24710121ca2974d4a5533d44ae568928b77b2988136719adb75cba7c6", "CS1": "041b73de9198466a4b3595ac00a960fd1f11f43db13e2f9cc4410084b2bef18ce71ffb51ed5d080b823def4e6660746396ecc270f2319fbef5f0493f035e0f9f9e", "CS2": "040ec827576026e94c814fc96f7e14571d64f42cac25907d4815cddc821583138e0104dfa3d4ed8a509964640d842167db8a2d6a7f8274e2426e5ad444c641e5f2", "HASH_MPIN_ID_HEX": "eda39b143c3409f598c986476cdab215049f5554b766d8817232f812bf9acefb", "TIME_PERMIT": "040836f71a0a178cc7b4f9e5ae852f92b6a0e16468c0f5203187b96d0cf0a5aaf30b4b94ff0e98ccebbe0c11e6e7e2ab06a5fe04dd914f69555c890b3c05f288d4", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34365a222c2022757365724944223a20223631636436323734323333306330376432376230633466323064336463386231406365727469766f782e636f6d222c202273616c74223a202232363962343665653963336632313538227d", "TOKEN": "040f87ae8d9c73dad994b4dbc45eb70935400b06ed9fd897e6c9cae16eb0fb07d9125915afaeb0bada63c795de69a9c4375fa1dbf7f62e50b8e026b154e615f4e7", "U": "0416a025edf67a1713d940cbe4c20ce1806709473a2113116fbf06b1aa17a58f3907a2e75a54c344d50cb10fd0ea203d8ccef3bdc1e3844f5a4c4b6effbce33cc9", "SERVER_OUTPUT": -19, "V": "041b180fbda52bd5c51a4de65f79451c1c766344af4221cab6750c0d44879282241157ef7ba03b8d4d2b1da5842b9a3d62c8c5a7f97de7019c43d34ee7c90b964a", "Y": "07807684dcc905e1b33557da131f559109f839a0288aa5fb7b70178d7d1235e0", "X": "0872c7617772acb07351df79c27cb669fba80d72012f1c270902496bec9dabea", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:46Z\", \"userID\": \"61cd62742330c07d27b0c4f20d3dc8b1@certivox.com\", \"salt\": \"269b46ee9c3f2158\"}", "test_no": 140, "UT": "040577f2d1d1502699b7a43c29815c4aa5d90862986df6f57f697809e5f55464b5192d03086bb8e29da4d48f7444092ca288ea9e936abd41f5ad7aeb5c9a07e777", "MS2": "171e12c257544025ffcb835b15ce7172558dcb6d3505d2030ee13d682cd7f899", "MS1": "174eb2389a8a9f2b461ccbf3fb02e38ae649627f4946db22e331a8da5714c505", "CLIENT_SECRET": "0413eddf27f833f4eeb5a57e27834316176a90874f54e6a20d09e0b10ca7944ed400b8b7920cc8d4441fd1b3a712db9132d60bcfd8c0b89a5795488d39da03bc08"}, {"SS1": "0b8a8889b709319b3ab7aa0cfeebd801cddb0ee5418c2b928dd2130a797b4f1c03765310c3af65961f26b9010fc82c7dc16c59c71d19a0e571097e577fe9d3e90a770aa8dfbacf3f2d4280780962f898fa3abc60001d07c7514a3da6b6026be205872f43d8d9f769953730bb84d32f525f211cab28c0386ba51614d1df3cdb64", "SS2": "1fd311b47300ae92147a71194f5a1f0d43903b5e8cd2ff426b1fb7c2521ace1a0d70178af8556d0e75f0e1f8d058909627ae24de6db4fff47832f76d248c918e0c0f23aeee832a448de70b4097a5d5ed9e31a5e5d96d56965aed16e84e89ecff1f89edcd394c2c5f8bec60f0b9f52e9981cf0fa00f05357509f27545545772c1", "DATE": 16574, "PIN2": 5259, "PIN1": 5260, "SERVER_SECRET": "05aa0891492911224a0ddd121102e85206248014c0a91aadf5f97ab46815e4fc228425824020a31294529da63cdf7b56d538f741fc6500c1e507bcb4f04bacd40fcf784881e88cd9f9455bf01f8dd09268a62c18f3d1e4b48afde772e1859acf00561cdde2d8b14c56aeeff128b3de6f52a1b16a4628031633091eea5288225c", "SEC": "04034268f53bf0c5c8bacb7e5d7bd8f06e5b1c2b64ae76141b9b369d4b76468bf2223e917009e935c5c6d1e20c8ffde6cc03db0c85a0794656e4f5019d6cf5e5bd", "TP2": "04110369c6793eb1d4c54af76860999663afbf8999d4a2a29086944934309370cf0b0942069d1c075b18db904b3724740fd05903bd074ef06916f91cd4cc5d0c51", "TP1": "0421c8a39186573ce25dcebb2381ffc9200efc8a15c0c6e47de0aa10390401e18d09de4c1d4532f57d406508b4ab937ce9b75cb36945c46f3fbe7c49f6d13b2d6a", "CS1": "0405b659560713ebd57bb55a52f7f708c015971ea447f998c20365c22950052a1f13abe575b2394a71506172cadc33ac1b0b42cd61d321b5cd21b25cc8f465ab9b", "CS2": "040a4fabfae0dc4194259e595f7867d00a6bc56cefd084cb92caefca18a71ae81d1ce6d90051c77d269fad0273806741234a3b56f1badc73389ca933f171790cd4", "HASH_MPIN_ID_HEX": "b37c9c9a1f30a381179255892631c637aff13337589742838c1b9862f76269a7", "TIME_PERMIT": "040e85e60cd077189cc4b196be477f9ca9ecfb62ccef8f20a3bf4994f09852a70d11642baaaae25670d2e9241789b2e17e637284543e0a4409311d9e5bdc829f18", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34365a222c2022757365724944223a20223461643336663162613933336464346630383862363864353438613439303732406365727469766f782e636f6d222c202273616c74223a202262303965653238373434313363393239227d", "TOKEN": "0416606249ac024b709b635b8d15f587650e433cbefc9ca5cfc5ed80ce830bd14b163f569b4444e7f83fe436b421600cc6c0b54a16cdce10af477cb21e63245a46", "U": "0406b38c0f331f35880d5ef1da737fb33b207bdad99949f385f0c0d37dbcb1680a05c0c0a9099e66820edc6f8558c9718e36c3a5f561004e41f6006008f83d4bbb", "SERVER_OUTPUT": -19, "V": "0419929d9ed60bdcb51fb3766b3af32e4125da5c70b62da5575b74e1363d9a9e83009ecf40ac45016b9ea65592c3a614232c2d1c59db33052ade21771667e1b678", "Y": "1beae979d3cddd8c0a1f44b171818c459f4d507965b847c923ec7b4e578c88bc", "X": "1fc3f573048e10df74d7ceeadea6f32a96de9759058bae5933402892cc94a274", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:46Z\", \"userID\": \"4ad36f1ba933dd4f088b68d548a49072@certivox.com\", \"salt\": \"b09ee2874413c929\"}", "test_no": 141, "UT": "04212efa15234060ff0e291a4aac25bba7a0a20909887f39b08ce89553cf8c6a3c03b972c3de0995faeb587414a987776474392ba762eb4129e16a94f39d66f1ac", "MS2": "114819b14628e0eea18a2be339d0690a34272e6c9d38050afcd66f35eade2255", "MS1": "08fc6c6c0c412970d908eb06d85282de77898d314d5fe4f8b7f9a4c36f25fd13", "CLIENT_SECRET": "04130b52bfaa1cf36d48cc9c0744832dd8d94ea3c17e26fb929c1617a5288203d90aa0ee89a9002946da35f461adab5e5ddae57045bfdfe7862cac6f4632880151"}, {"SS1": "03b6e31f9ff848e51d5839255324e5f068ca5ec61e365482981b3833733071971ada21f03a0dd980931e2b98f08ab5f004992e7a07f57794007b6dcbdb65046a0c094fe61756fd35c3db046db0f82ad444d02af858fa5327e718ee1ae6cdba931b4bdfe5d91d05834e0e3d6125f7cda211fde4d46a76a8507307df7dad4ea9a1", "SS2": "1838c95e9add438846ec55d4918529b59dc147629d8d576d09fb4832ccc3bc321533245deafe599bf839780926ae262adbcd3bd9a2cce4c02fb7a2b9c15fb8b90e29d3753438c15134d7b282ed4312aca1b3245b07e04cad2afd3ed3fd4b15b00276703800a03536dd63a1c4f562f1660f47b6106c2d280732a88e80cba84ad5", "DATE": 16574, "PIN2": 3969, "PIN1": 3970, "SERVER_SECRET": "23466260c3e19611d2717ddc25c902bd62334a5018bd8b84abc58885461d93df1acf55ab6128f154c30ab06d91790a5d74801a1fb4fbae3ab7c87e83ead57fa50bef3b3c898f8737ff2c5bf72b9c2f07231dff2fed404126e675ea48c339a152121e243e7775cf52235fa92036ab20e111faa1e74c4c7492d5ba93bee9549653", "SEC": "0406101bd7bdd1ced0671e6e7693874dd12361896833fc565c6c6f358121a1f0301cf1ce23c456fde786a0aa6d90d9703e3b051d8e1e8ff70414f51a63ac490020", "TP2": "0406a56de46a22676663455d6281bc681a2b0ccae24726a1c9a2dee2fdc59fdb1620da3ede7e752e603fd4457c6d8f4b12db977fe86bc95b16de26085fbb9c87b0", "TP1": "0415bc185e77f77f8a582f6b44cc9eca53f56b0f4d3f50b92d3cdb8c97534bd0bc1f27675dad1e54db9b3a466e9a1356e6a91cda9c9d6f330d99f80b0ba272fcd0", "CS1": "0401197af2cb6d4a2471751d6fa2a7733e42f079886e991261932f055d3d955b8f2347395b00087fb3323e00ae54b9c653273cfe258f8892d045b9f04c264e11aa", "CS2": "041c429cf93d4361ddea0cb68c60edecbb205c45ae19b7b6305968532735c8a5d00f3ff9a4877bce87870de33807502a70878bfa5a5fb4dacc3a7ea12a30d8af41", "HASH_MPIN_ID_HEX": "31f12441e847adc8c836a7c51e4414feea47d904a92243c4996a87f7a9bf7dfa", "TIME_PERMIT": "0401ad066c0f0ac108cdbca1a00ba79ec94e217dc8a140145a34b4273ece3b2c2605868c4e4cefa1958bbb5e3fa22434838321191c3a2797f3ceefad2c13ad4bef", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34365a222c2022757365724944223a20226536343631613838363934663336383766663037646135323334363839616436406365727469766f782e636f6d222c202273616c74223a202231363833396262393465383338616362227d", "TOKEN": "04034a3d055029e3a3073532cfc5c5b6a45436c66f6c48997970e94b869f9de099208176bb789767fb829a58f9c43ad764439a4e635e2901ef5ce3afeb348f1256", "U": "0410dfafec91a0eca4dc8a0b5736b2ec244fef0aa555c500a68d7a1c2579b28dc701edfb5164681ee96c1ed6546dbe25a63c64442c9be1162c546f8d36f7c2cd33", "SERVER_OUTPUT": -19, "V": "0402e945b5c744f9e772ac6edced2dfda5ce065237849463ecc458d3e5c72e5e1509946a27066c28d401c01941e553a66140c2838b3075c1a7f1e1bacdc5135c1e", "Y": "062a90703272d06818403ae3b609f30f7005179bd8b39bbe892490ae62224d1e", "X": "0fb30669017b7f3b7fc7b434f80c5786fab2971d600159270a3ead611dfb2c8f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:46Z\", \"userID\": \"e6461a88694f3687ff07da5234689ad6@certivox.com\", \"salt\": \"16839bb94e838acb\"}", "test_no": 142, "UT": "04000fe52c03cc29fa1158cc1d06946025731decb9c4af9f2c9aca9db946ffa631094549f4f8c6552f99d31f02d3a2388072edd0ef4b284256fbd05b2b817aadd5", "MS2": "0454106091b5654e41e0668f6e6b9b184593b6ce97be87e55aa9d4e5ade595ba", "MS1": "15a848191bfb6b7840ace04e710f3597452f345b8f2fa2a02800b10c7543dddc", "CLIENT_SECRET": "0414d666e6867717d1b81f8475bb3c4466be33d2ef8372bdf4e4e7d452bbb4f5bf193fb33762622c8bfd500bf826c5f369b46c9ed14f059262e8c1717f2de2ae08"}, {"SS1": "03767fc9e4613c6f88c1de2cbc5c59676c79bbe4d729786b90864c600ebdb6270af0ac246a44a01cefcc8f6afda9f06237b48e8f62d8dce4a5425004ef87a6150ea5741bc7503a2d752fa4287541b76fa7edd4121552b9c8c3d1c838b9d8a23115bda66154e9dabbebe164e775aeebb07164c0ce6eb93947b7654e84cd60a9b7", "SS2": "1f3c06bf2ce9e55550cc24b1e56c686e71d59e611d9214532ca1047acc4a290120f83987922a1e706f6696797ece89c2964be251b3b4ad1d1d87d072dd99041b13fff6ea382424db3d845d219eaf4ee54cc554e69d68d187643ceb69b8c1d4e01d7e3565d5aa81e240d6ef89b19db18176320e542edce0e1101881af8035e26b", "DATE": 16574, "PIN2": 2279, "PIN1": 2280, "SERVER_SECRET": "1ae8c45ff5d8ba26970b348754dcdc283df20221f694c89f4573aa67c970e0ef11cbd53b92e405e0d604bac4b149de31a768460e9b85f339e67c93fe8ad17d7b01cb2555810a824754b51d71a46fe905b1c9e6adf7bd33f029c0617ef3e7ff2321bb12f43808198799e13a0697c5887686ea4a503a3decaba7492c20e321fece", "SEC": "0418f8d7806e61f759e90bd630a6960756e15424e7163e3c9b96b7f4ad9c7a13b220e585c68a758d9c31d8e77bbc82bbbde33ea01fdb34e902673dd3416aed03f4", "TP2": "04162b7713c670abd365641530c4244f740da0240e88072659c6cf33310d033df4054a2e74bde6f43813248324a0ab41a5227f763b17e9e96f6b3953078f2ec7fa", "TP1": "04019e9fd103e369a739ed84a811fdc1f648b4e751bf885864b50f504c10ae6de4096247b3e823936a18ea30185c9027176561478172f7f8802175fbb059396c70", "CS1": "04159ca487d4a32c3b0df52051ec85a07b81d744751767c5d79d8b1627a4b450f00d14fb787151453c1be65d1179af7feb7a7abfbcc7e3091185e081b4af96aea2", "CS2": "0410d532734bec683ecd3df7c52b7cfcf0224a99ba363fac76c13f9b5bbeda90b70263baa9f59132526d7655d83c643f1f3ae1264d335c273a81aa17b026400049", "HASH_MPIN_ID_HEX": "d00efc380e9606ffcb7efc4f475940a0613f4ab63211b6fa90ea5152eb39ce04", "TIME_PERMIT": "0415ac082e543ee064cbde541ba2354a45ae474b1d6cc3ec094da9f7492cce2891093166f9a3f0ed9e9f4f8bca0745cbdf9c5de578b5d3cc7c3d58ccae0b912f56", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34365a222c2022757365724944223a20223166303530313634633235666139353238333534376331653465323264616639406365727469766f782e636f6d222c202273616c74223a202237333861623862396463343966613435227d", "TOKEN": "0410e87dc805c9e78a5478de44ca6f0fc9eab0e046bbf176c13fff326f978409301492b1c9305557ee11e1d74349eae085ee4cd269ba974e9a28ef99933ced7dfc", "U": "041d77d5c5bc89402810678050ad7e1871460c57209ddf88c651f600cde2f84c7b0a419ebe9bc842ea059d3d4d8b96a0d45b1e2d1eb80804123823078072ca25ad", "SERVER_OUTPUT": -19, "V": "040fc2a33b3b4f513a9f8177639d4fbb8682e8ec23240d5ee052195ad20689f56914f5ab0334f1f5fbc461f7423deca4db1a6e54e465f7d4e2dd1431c9c8b2c616", "Y": "04568874e06e99bf53b4e940f2d96d7aae7c7e6ccdd1bef9791805171863280a", "X": "1756bb1962347cca26b6bfcfad5ffc128f195c2f526ff9e5f94e58428111f409", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:46Z\", \"userID\": \"1f050164c25fa95283547c1e4e22daf9@certivox.com\", \"salt\": \"738ab8b9dc49fa45\"}", "test_no": 143, "UT": "040dddbedb725f92372129fcb698f510c7288dd80d1a369ebd254092204ab6544d18c6c1cf7cdb18eb1315e59201ccf7cab209ab7fae8b150408cfcefd074dd013", "MS2": "1db27d29f876ed9347ccb2242fe4a84588c73085e1a3f8ef6acaed95d4787dc9", "MS1": "1a4dd771c8d4bb39caa7f8df5eefc271112e6e7113089f1ad341a7798b4024db", "CLIENT_SECRET": "040d12e8f3485c9c00202d7643349c62f1d4b4f355b676da3752d46bfbd3eec51b08b73851f0219adf775a92ce76f214100269dfe9c9fea8b138a0af0b878f6cd9"}, {"SS1": "17287bdff88fb38b3fbd68fba34eacfedff453df24e519ae63581f6a53f0c1f323ed858866b5b2a4167e297d6214dd6f9f7edd4d1f9dd3586589116afa7c9ed623cc2794240e07c227ea84925fd72d0b7fc5a70f5368400e9ef3273d2f207f4a20125b699f7ba86ed54b87d5bfda2eb1a6e76005518f95fcc15efcdda242a0c3", "SS2": "09962998eba6964c9ccb8f8337f54b9c2a47d912cdd8a9c9cf4fed9fc6a13f2804b36e9754c4ae4cce0855f472ae3cc00af82214e4b9ea527ca50d50943274bd044206349d1a61a658ddf9f67d814491fc2e283a3136473468d24aaf3b8c3fea066fc88a5cfcbb193faed580af358bcd34321ca2e36129597a5b4029e9f7c019", "DATE": 16574, "PIN2": 1545, "PIN1": 1546, "SERVER_SECRET": "1f947ce379d478f76f5a6d778633703bb812ee04503239d4adc696a28f4c5f1f00986246cd05e4535a1760187d2cfb426a2bd257a0331fe7053f8a57745e989111bd0f09f3c9f26a7fb7a00a6ec91965d4b5e9e78f12d3cf85c246f4d6d494aa057c92298b0e73911143a80ac17ac8f83f9a7b0ca6d47e1628a8ccee757e2804", "SEC": "04086d0e0c6fef3916ac8a6f7a4a13ff938f16fd9aa9fe9c7ce1dc661797ecde4b0f567f8f8f5f7e5f7e8add33804b313bb66e7ca0aa691e6f4b0d11ce7db31781", "TP2": "041d39d57e5f98d3dede033710fb93520dd3d7cb04fcb6e7069527f698daba83b31777fa1e61a68721f94d50b1b45c5b8357707b9193d4d586456312dfe2da68ea", "TP1": "040f07f0840eab5d9154e3d2301635530816bcf70241b4aca580418ca69133b980050c0a00ac4bd298dd399f4e08846c646bcca8a61df311ff4d60e8d6fb7a704c", "CS1": "0422574c40b4484f25a7b8ad6badf4d3fc908f0bce271a2ed4de718d89b3cea57a1071610cfd70122c468e1ddf3e5445eec583264a47c668a5ae575a1b652728c0", "CS2": "041188b7178fa61e56650ec310eecd6c724a2c12adbb1ae920d78ad9721094fb31127ef95b47c5ecc12bfe78bef2beb4c921840b16c3c078738a18aba27d22410d", "HASH_MPIN_ID_HEX": "caf545ed844bbf58a70725486c5583345831f357b062f7d3f9b30d69440674aa", "TIME_PERMIT": "040742457d9fce308c92b9adabcf79cf003a15496fdc37038e4965be40bd5c309d0728ea08246be9576eda4fa199b8875cf4220f64daf5dea0fd7b9ed2dfb37023", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34375a222c2022757365724944223a20226136623263393561633131313938303939363434616538623238343435393266406365727469766f782e636f6d222c202273616c74223a202237336136623764356336376539353434227d", "TOKEN": "041c66d1e423acce719e00f301598329be465866a48bebe13647f352db0cecde0f04a2dfbbc4dabd778d03e2b38caa72c9fd8185ed2da23c823c2bdd1eb0e5d966", "U": "0415596e0d13b3031b1eb6a9a5a400497d5233ab5763175b6abfde696d18337a820ccdf5c64ed50b98a4abd3ef4bc91b1ccf428e9bdaa382d1c628363607b51584", "SERVER_OUTPUT": -19, "V": "040ae6c29c49d2e9530f6bdf97464a07ec3a0fc0d45ebcfbb7897916b025fc155b145bded9d4b8f6f7c04494949e6f49e50bd4c7d0cb937b0c20c7ddc134cc7978", "Y": "21e1bc57fd84e529c51f287c55f0890fe6c1293362d57e917a05d705eee22733", "X": "053c24c97fd7f7970e7747f1b55342fb40608420e9c02250ed09e2edc47e4635", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:47Z\", \"userID\": \"a6b2c95ac11198099644ae8b2844592f@certivox.com\", \"salt\": \"73a6b7d5c67e9544\"}", "test_no": 144, "UT": "04124fd9c02d7b04ad378dc5d8a507735e8fe79cc6a1a05280ddb8b6865e1396340ceecd05057267535be304ca88d63cf552ace86e8ddda2a84e18f2eb9e551fc1", "MS2": "07a5e530bc2e2082bdfb2a583749a574a7371693381cee3dd5cc59c01016c021", "MS1": "04b04a9aa72545e432ee1e01721302344004c2c1c89b44d9cb3ac8cfe92e2be9", "CLIENT_SECRET": "0408277408ee6a55282102976b5966ae9bdb9d9cb6ee27f07946b38d4960b206630781a2b6b0e393759872714132ffd16b20aef45e4ef651d50704ab8e1177915e"}, {"SS1": "007f73c7bb1d661bdc8274131a349afe18d9ef8ad85736ae447b2cecadf7294b1e358342fff999154259edf18feab1f95816e3d697cf9fdbcf9fcfc5293a9d7b1631a706de327632c2bd30e4ffe41b94d4d361a4ced68519647ef4b9361726fa13b18832640b7c549a0263a5cd9cb4078a3a69286392980dc846d9cae9a87c70", "SS2": "162a475416ec3345fc6131611ad2bc8db2e5c0366f5c185adc94fef7901c42511831207f6d7bb3efc414df78b07eab0f376fd1864c4795aed72516eb83219154133c1db554e67d8b34f76f302497865707e304113e31b5a2335d4bd27f801ed509f7273b78c64a67c3cf95b21b63dac5cb05ebf390c0565fd4faeed466d1a60d", "DATE": 16574, "PIN2": 3478, "PIN1": 3479, "SERVER_SECRET": "08f5b07efeb49adbb4244ef5aea1ad4f0eff07271d764f64abb892eb328d6b4618ab92245280be6820fad90ffe2cc313b047b141c0433f515334231f9c46fb1e196ad112d2875fbcecb67adf605741db388727b59f14525a7bd4a383104470b80c2725740fd9dbbdef49afa547f7ce87716498749a95d8262d02f26c76aac655", "SEC": "04224ec62ea899749065b6a509e043b9b1426a7f6854ded73370ba535a81b498c21155f28e37c105dd5efc5f22df7e1ff5c70442a44ec7d38fe3e54f7e2dc3be7b", "TP2": "041af3d816fd92dbd2415378b8c85b0c37e395d05f4b8c779e457018ef9fe8490b105efe60e01e09979d45fd6bf0c14cb7dbb2afa031c1dcf1bf1d9492bffd77c7", "TP1": "04176d7f0cfb2bf3b484a756a6dfd88e6e237c85f250d41095301a0352fdcd84f914df66cdc6ee071ac0fbc0106823aeccf45f808d9f866cdc796abda210ba0dc4", "CS1": "041fc78b294ff1d2b709c17781b578c5321fd7ef388756480e4288befa4f2efb9b1ca308cdc09c1006be5d599bb08f396e3c0961c6e37908557bdcfb476f93bc3b", "CS2": "0407f68adb7d77447d2d00a033868664f26fccfb997735dc3cb8232ad5531bcaf7173c93c6671c6a3e119e85461536b2f350ab7fd13fd18e24ed511d6f5ec17195", "HASH_MPIN_ID_HEX": "2e8ff438a243c8b6892740c35418cc62abbc80dd67fa2e6ea07af9b7576883ce", "TIME_PERMIT": "04207e00151cf44c28c10553a49b581c8611781c28a3f464a16ba1de0d6af9a75a217d6dd57c6f16642858111dfbbf7542dd43204a1e57edff3e21a26bfbdc25e4", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34375a222c2022757365724944223a20223232653662653036313235636165383532626536336435663839363939343165406365727469766f782e636f6d222c202273616c74223a202230666432306338343935346361383836227d", "TOKEN": "04220137232b375751306026d38a6df81c9eaf05a290c5e873395e34fa5ca1941814915ad7331a5bbd1af5315e053e9081cbf95bb9ff09ce7bb44d2e2915963cc3", "U": "040541446c7a5a13df9e2f256db42e09709b6f98fb32f4a39ba802744e0f3e589e091b00f32aa03e0dc78af67a4042c99b8aea68598ec38f7274d888aa9e27139c", "SERVER_OUTPUT": -19, "V": "0414aa2107cbee7e35d2f7482f8a6780b35ab489079711fa8dca736107567efa620914a913ceb77a55d4c19a3bcfb21c0ae592c584b2652cdd477e54a33fd8da02", "Y": "00020f7cccb4170f8e18c88da9cf16f4514e934e0991f5584f4a418fed7264c9", "X": "1f5b8f9f4b5ac73f0cfd7c84de5e17e76cac8c6de3d6126843fff109acefa5ac", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:47Z\", \"userID\": \"22e6be06125cae852be63d5f8969941e@certivox.com\", \"salt\": \"0fd20c84954ca886\"}", "test_no": 145, "UT": "0408630f4a234c0612783725d792360af088b23ba7e72bfe46877716c1213c429f1e252eb65c3b673bc5196ec886e4b4aaf2f16702bb996cbb350f98417dd4a271", "MS2": "16077c0f9940d3e12b0cf1b7af51f58848ba40100280ad2b7bdfc7514651ec11", "MS1": "1485e4d30520270e76092c132b3f5c566f655d33f0b5ca53140ef9ccdbb599d8", "CLIENT_SECRET": "040874c028c68e6051713fcb86edc4b9a3d6cbe58a3b1a18c85b81ca6c52948e261790711006578bf93c3a0de10b4079069caddc12e08375385ffed04b882c5489"}, {"SS1": "196ff92fc5e46ee3c56a009fe03b977c69e8384135f7d5f807ed09e8c1ba973e21a44d947b24be1340524283b5f20d55db8b49c8cde11695f2396a36d367fb7c15c3378c1ba4373dca3c4e043ee153e25ac4f8090ce5f6beb2070a56fbd8ccbd05f7603a5e7ec2e6ef1a3b9dea57dd551a50af5fe39334dc1a31c556ef7f1028", "SS2": "1c8e41e4f05c7b7e8cca8278475d257ae45b7743254ba282697a51df8fdd8a881a1ebcb733f6cf8405489d07a7fe1fbbd37b62b6b40a3f7f1b2985798c7d19a3068cf0a2b42d76be5d71af618c21bcfb0071fe8e2575263ee72a55dbaf59f2e607697cd63f3e9daeb26fcdc4d3da26ec80c3340dd47eac3fe1b33e89de0d25a6", "DATE": 16574, "PIN2": 5393, "PIN1": 5394, "SERVER_SECRET": "165c50d385c9574d3c9702d973011e9ca8e85048f95fa839a678b0a7606620c91e5dbc0ce85674eb38533ecee47e3f3bd965e8ab5fc0e030b50c0b61a45881fd01eb25da8bb8f808dd2671232358639ef7101b389d2342a060daeecf02bb93d806b3ca16d765f5c84f391f8ef2231dcbeaa5d97234b99550969e04f13fa33645", "SEC": "0407347c815dec503d0bb1400f7a79eb68fb2866c79ccf4f3d15f0b2bf0ffc301f102d2c73f4c11974787600cd6674346a8459cd7f9440a2aa2986c5ff697c8a90", "TP2": "04032dc756a14df304e20a3853709159c383a10b99a9c331ba0a8054f6cf2a1e59172ddf76208deafbec8e50f606964b8ecb339d1418e1be6ebb94486f458e2dde", "TP1": "0414650baf38cfb58a8f33bd06c0bff4ee8b97555d750de0742ce87110a6df6bd004f9ad0e79bb7d2623a34402826f343e017158478ee6001ec82f5c86dafc3611", "CS1": "04174f731b058c507fc9b0d0d4327425c4943f9c53af94d278ca2f8526a91914ec2342e79a007bb87344b6d7a9ca1d4f01cc4b3439c063893f288b5d65ea1902ed", "CS2": "041eec178b44965a948eeb1b5e2c3c39de7418a7093ec9cd318c111c59a0dd4ed410bdae9ae660baaeba9cd9d2cebeea42ff67af375d205639ad2f44614ecaf5d5", "HASH_MPIN_ID_HEX": "19eb870286d2a93bd44bc95dd554c3f2eb386e9a8aed4b314b152cc662d46295", "TIME_PERMIT": "041a0140344e5bae6b9bd70526a4dcd39d812c50c9127371f2b3c5c46876efeda61c8420b4c2079da0436e7fd59181fdc8a69ed79a9d1246a12de90d6ecc2981db", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34375a222c2022757365724944223a20223936623236303038346330376639303838393833336430366439643336626131406365727469766f782e636f6d222c202273616c74223a202236373865386330323931353532646361227d", "TOKEN": "0409454ee990d049031ffd53f04f020ea2e1413c33b659a385c12176a2bf14df02036f9ccb369b8ba48c87e53d3ca4983b3ebe09a9b7893f4f29577d6bfdbff83a", "U": "0400359f2a76ed5c7aad5e8aa44f0440fef7fe57095399f9528941df24a4ee5bea1a939a83986de5b84380014b78d7cab710fe44ada016291235676b80fd7bb531", "SERVER_OUTPUT": -19, "V": "040fc624652e0e07c9b16e0de0376181103a5def457289d8d4ef99f20889bd85ee1808eb5f7130ea359bf756ffa8c7085845392d94dacd71b88db9ea4289549d37", "Y": "04107d7aac1afa0549ddf7bd241854ed77aab46b8ec6f0a6c39af649806e5641", "X": "05f21b76e2dd21c40b902a18924a39e995ed7f929ce79b063404dd8dbf26490b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:47Z\", \"userID\": \"96b260084c07f90889833d06d9d36ba1@certivox.com\", \"salt\": \"678e8c0291552dca\"}", "test_no": 146, "UT": "040b65f5c9193026e92bb921894a10acf1a2a04cb4b2d6582ccab807f1bed0b21c230b3e296a0d721d020bff537b5c86a453fa09ca85c6766c358c1954052ec3e2", "MS2": "1eb50e159c88987f01652136df671d1f7c3b208308d0f6c65efef6243c2560d9", "MS1": "12a7bbcb8de8efb05839fc6b01776cfc2f05520bc8cbe8678ffe2b9482646b54", "CLIENT_SECRET": "041fffba07cbd317c5501a06cb8edeb8baf60bed490707dc7d088b1cfc1fe7b29e02e49836e8e7ffd60eb7ba9d70651df4bb2fa4a903b6c5f898d7330bcba8b2c8"}, {"SS1": "1c6ff96052465b0fec193a96dd5417ac689563e4ba778ad54deaeba915dd52ad08c4e70b78af197eb8c865ae89f7d7d6cf22cd3eb50e95f0718a5618c56c7e4c21470abbebfcb9506fe06a3baa629124b18a3d0e45f7d1760aec53d7e6ceb1d71d03b216be452a95ea60e1abe51409ef9c4708c60075b37dadbcf7b7abc7cdee", "SS2": "0dbbd1e029f212a7b68b32a78fa21ffab6756aae5bf17c2aba8ca636ec4321f61f477c4c71f35ad2e809160baef5f5fafcd607099b728aa848649cc34d7035cc1b2a986a00fe7e8591ea01eee9906c54f342b038d9f66a77b4aba32d0570b0861895722bbadf06a9c94925f538881a64e8e03d74467e57dc2ff4373eb5368ab8", "DATE": 16574, "PIN2": 5560, "PIN1": 5561, "SERVER_SECRET": "0ac971fde7047c97ab728b37342f71d75867ca5d56c4b23126952a25e5650c1c02a53543f06cc4b7d2fff49c1a1910d35ebd04e4425debe0fa7d11d0de8ec8b423a227ad5448a92820f48c7a77126b86fd904cabd3ec43d452d404598487d3db1fea323f51f031b7ab33c8c48140e5fd58ea3e3ef809b78682207027cba7a8b7", "SEC": "041aa0ea01f19c8d12d3f810569d331b569bf6e97563694d5aa0b37f0fcbbc60a5232ceae85b18a26e660cf92c5fe8d626f7479ebb20d777b3bdd34e24dc9e9ffe", "TP2": "040f7d261699e11ab509ea56696258d62e043e402fcad87bdc77d2c2d827e1b84f107b24889b95d17eb39fd76d3cd8477cf8f0b1c6b85b1088f0e44d3894d7e92c", "TP1": "04037682b21924cc5fa6bb129ce79ad3b155900bfa9c6f7cb157c9c572cdc6f8b81c0cd439446ae07ac1b01d86e1fb54c0c25b5bf42a74c418608415879e00a1c0", "CS1": "0415a4894f62608635647b27a39e2172baf52eaf679a9a4cf0d296ccd257e0504d16ed6b45fcc20174868b153a6fd22cf6f867c980b55892efd7589286dc5e543e", "CS2": "04146b4cb82305d163898441b1053480adf08d3d13cd02942f61003f9a0a5d84670272d501df5bcd34c94bd901394a03a6feab82362eac8aabf5f910ba1b271ce9", "HASH_MPIN_ID_HEX": "93a888240a73176d666e5d2bca37289a68ff38bb11b69abe446b605e83c89642", "TIME_PERMIT": "041adb07bec4e2e42be66c49945955e8ca5e87de3861bd3238c1b17e92702ad0e70a1e1f1a8fae5d0beab76d5024b6f5e20a0372a3cb7f97a08fbb69ea5740a674", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34375a222c2022757365724944223a20223565393061313265323533656536643464636165363261616162653734353038406365727469766f782e636f6d222c202273616c74223a202233316666633134396366633832616332227d", "TOKEN": "040a62be0ed4f635099a14ea5b648ead53b2932b00a0c37c1090c671cf8259da43047e7416cab0aeeb032497e089917ad4ca46bd513326a80e0bd0cbebe0438025", "U": "0400cfe364478c635f27378b62fdd477eb6ad60d53e1c66085a1c82b9f07666d70209a4e38776dec36da3f41d66075209c18091f9c64e86ac867dd7f8d54feb2ca", "SERVER_OUTPUT": -19, "V": "040e18751919f66ee0e7f50b96e6d0649dcb6f82602fc78628773063d2303a50bb0ec8347d47339f7bd1712ca50a710442517a0df9638c440433770303679ab1f7", "Y": "1db52bba4444a6e298fe155c2ae576ad09064dd7b1b77a4c6ba2d10b3e3d8041", "X": "00a6b2419ac63dae66e06db68455f629c811ba07d9b4129ec3fc839f5135ffd0", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:47Z\", \"userID\": \"5e90a12e253ee6d4dcae62aaabe74508@certivox.com\", \"salt\": \"31ffc149cfc82ac2\"}", "test_no": 147, "UT": "0413b4014aaa3ab1a5a4f389cb69185fd833d542a166425f046d43577aaed03f771c3308afc004ef794d30cb28f62d6212f41fa602299a35cd5cda006ce9e9a56f", "MS2": "109681b3cfb064af9f13de097a7567e8820331f09f4c95f3f49cb8ea3d177835", "MS1": "07ddc0ce9368f68edbca560682be912d7be8c58f6db1176dc9cd882f75d84416", "CLIENT_SECRET": "0400f2c8f20f97dda31d954cb4820a08b8b181e0b61c55b18d831fd8b371b4aeb00cc6096fe67c126d2bbfdfcf98b4311b46ba26167c30c2636b4f123f21412044"}, {"SS1": "1a9457909e4bb6fed41b696da0377cda6b7803798ff7f0ee2e43e66e5fcf416d223c2d2c22d29ae4b898ab5bef39b6b67dfbf83f9f5c9ad01a9f2c6002c0ddb800d0d47214cc5df61f4a638b832ea764e191b555b5d0b64a754ffcbc96cb2ee5173fa22ed58619188aef0a8413cd6f06e3d4941968afa747d45b4839342cab05", "SS2": "0e6968249ac90e8d4cea2015656ce6ce23b0a662d505c7a3dbc64c411b2a4a791fdc6c50922dd1b2beb1eb58edc67b1dd0b4c6568eb47014c984de47b8c01430222df907bf7b5c9a4ad395d30790b80265c2e2d926cabd0d4cb3a49b305997231716975e02eceafc4d2ad0fadfaa55e8b7dc37c8015414aa921a9c539eed3fca", "DATE": 16574, "PIN2": 9741, "PIN1": 9742, "SERVER_SECRET": "0a62a5cd979aee03aa55552fa46f372db39cca0be509019579de6292efe2e16e2114a47ef31799e6b522b199dd1b7fae57c05421d86c6108aad6196ec1d37a6a22d9c19ad1f831a8cb3136737420596588d4e982045a9ddbf63a0d062c03614907ff69a3b4cc02ffd64be192b4480b56cb2096030bd6714421ff1ba40c3165ae", "SEC": "041db3d797b796dabbc73692f1f49ab8b92739f41c02b9e8d40bd0975bd216cae71620e5b4bed1781b847ad8861591295ca29d27ae845bf70c651daaca3d40f956", "TP2": "04106aaa420c8e170f2d1e602116b15c1d35dd986a3245771222310607cb13b1611fa9091ed82e5a6423e6e22cfa38ed9143cfb0931a736b1d65eea12f52574b85", "TP1": "040bc5c8dfa5d5662e743ac13fa9d1c58e3659a2c4051b9f653a9f67e3419718561768ca86803c445acd58cfb222d1d4f63209d2ba1671ed5aa9b324ecc8417f8d", "CS1": "041216db093e9e84cc1382f3c71438c97e870f139e4936214d6aa1379064b133d710d1fa65c0ea77a2f15d4516686f2ec81d83ec8a30800f07b755f6f4b1a9171c", "CS2": "04125a1fe9ebd6cafd3fd9d3d9188147effe39765ddd6b17ffb81c55c140e774060676511c9dee969f4e602dce6e82d585bca13051919c0cd5cfc80151e66f12a3", "HASH_MPIN_ID_HEX": "007e187afdd5168c6f43e42a3c6171b23eb2e18ae0fe8b48d7da0c6a87c18fbe", "TIME_PERMIT": "041bab8ea80751a601746df014dfb59b28c4b610f9e9a9edcd8dc46dbdc20e24b0227322deb11c3a71f7834d4de82d38063746547337d28a8699d303679785e9e3", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34375a222c2022757365724944223a20223936323039623636373433663265383638663536366539373631376337323037406365727469766f782e636f6d222c202273616c74223a202261346133636130383832313631643939227d", "TOKEN": "040445b984f0a7d11ae13d89087aecec126af5b2a2b68655e188ef7a99cda751ce1070f350e268c8fb7380003b9f9e7eb834986e3283f3703ab54d89f20449dece", "U": "04120b3d6fd1303a8adef222fdb9d14dc4857906cd1a6da26a8db8371b5d75e6420215d2e9ffa3bbc0cc08cd22d24badcf6fb776c1fa9d5bd86716e2ef1e552917", "SERVER_OUTPUT": -19, "V": "042294263a0d5022b7e2ca957e887272887f6d8ba58a84e5f7ed21f4a30cf295261e9259bf52a2749d31ebd992c9242098a12aba99ef8bdadc990347303798de69", "Y": "201a51cc46961302a369123ee31efcbdd556560a7a571dce70f4d59d80e4ea47", "X": "23d675447c2afff5681552eca025a4e389f7a693f13e3b64ea2e0195e0c13ccc", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:47Z\", \"userID\": \"96209b66743f2e868f566e97617c7207@certivox.com\", \"salt\": \"a4a3ca0882161d99\"}", "test_no": 148, "UT": "040e859aca052aba74a66cca945234fb6295d9c733911eef61a6927a17436ab5e4134b4c3f5351acceff51bf66332eb84f3b1a7c068b2ba90beedd5e86e0c2812d", "MS2": "1c30e51251fe38e824b08e5a797f0902b5063084b6c5ac18f16f90aa954e4863", "MS1": "213e9be40594dac90dd6084927b1a354443f832bf609408009dea88b6d6927e3", "CLIENT_SECRET": "0401f60882d09a6c6e6ed6f18d9b53051ec67122f14a09c5d931f8c427449fa2ca1cee2077fa7d25e0d7d0dd935f2fcbb8f02d7c4ab3aa9e44572b56b57840cd68"}, {"SS1": "201762f0317cf85d97a7af8efde13c8154334614158ab1b44053cd9d0af1dd48197ad9ecf80d978f39ebc920f9ac99bd88961c4ce78d501f249374445809825c169be29d814925fede59e7a1de3b1ea9774360cd68564461adcd61a55dcf89dc1da28312f614cfc63141c5ef752d2f7260fdfc88d98a914951ba4dddfd40bc38", "SS2": "019415ce2036692b258f12efa11a98a6a363a2760219976b249357e33c1a5756183636fe7bd46db7f586b0a7fed8fd4b6ce2db0d62b1677e2ded6290441cefac10c039057cbbcff220ff71dc436390dbf1f14af6ba07d2a23b5932484470b69a1d873dcf920643012c9e3c4dce2a6b913b2f6bedb519bcfd82b3fcfbae8c7a78", "DATE": 16574, "PIN2": 6350, "PIN1": 6351, "SERVER_SECRET": "15ee2cd0b86dc5699821b53f064bcf982af8b8405bae3e017df4b8511c9d18471814bcae714fd6532e45597c1e8a1161c20e90d93b73d0629ddb51c3fd7790181fddb874b1094e038f9341c93039358ac009a29d87cc01229286578b14a76f520895fa166de83be8dc14f56bfc81a0835bb7bb3fe99a586606016682fa3954db", "SEC": "041526aa75df54c6b3bc1282c772569dc691550550e91feced49751695262c199208e8cb9254708a4fced4e768edfcedb41e26dae837ae23b8c0fb9b0759dae926", "TP2": "04131131ea21fe7c1ae1c5074e384f2a2cfbffef1c7119b070f6fa605de204937f10c0e355d7db9ae38941b3d503ee7f3d1836711aa856b50766abc8e1ee47da59", "TP1": "042137412a02e8a6b3b24f254ff07d862b2707aee0f21501dfc117ba19cf4c094018eb860a1fdc0ffb1a0ed74d5417542870b1524a8946ae6a7f2914da6bebf7ed", "CS1": "040d7484edd9d82c8fccdf5a0e943c6c74122f978e2078654f18c60aa6420d5efe096b93069951576385a4ad4603fa5acda83361f6d849bc2a583a9933be7169ea", "CS2": "0410614abc7f1d6b9019b443e37bbd3f6cf198acf5f5329c40765071723d07c9f4026c26eccb3167518606a9794b1bcd5b8bef12d6e1313b57ff0fb0d62ceaf505", "HASH_MPIN_ID_HEX": "4cc568f117a4efdf59f24adc656b52b34e3cec6db2e85bb6684cd8401ddcf63e", "TIME_PERMIT": "041a5eb0b5105e53d3337961640be3ac37d262801f9b7fc300574c4b64445ec95501cce1ed3ede9b57af16bea149bde8f8955549b9e3bbeeab90e5a86f462c16bd", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34375a222c2022757365724944223a20226363313935353939326433626462343164393062343838386464373762343433406365727469766f782e636f6d222c202273616c74223a202237366534326234663039323638646335227d", "TOKEN": "0406acbe27d89121cbebff3214ed5a5a315707f901f5db03028372de057160cb8d0d0f98343f879f9b925d2d605e9db5712ff43b0eff374004938d1f9d0dd7a9b3", "U": "0417759898ddb3520fa797147e22e9f24966113750d9d79501da23d5f2728921f71f353dfaca0098aa1ef813895013318dac44b17e6dabf5510c0901a37c801089", "SERVER_OUTPUT": -19, "V": "040490bae2600ad6e6c16f16d169882c13a7eb399029714836c86619f0f32f6fbd1a4a21eab6e826e00e57559fb665493866b53e122b9be8f55082349bfbdacd7c", "Y": "1396c8368292a07a5ec1e944685fce57cc4f3879617c68a394b0c30da431d5f9", "X": "046b0ed474949c19388d02ed51820a9e66c709c35748a78b85abe54dc0734a4b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:47Z\", \"userID\": \"cc1955992d3bdb41d90b4888dd77b443@certivox.com\", \"salt\": \"76e42b4f09268dc5\"}", "test_no": 149, "UT": "040d28216fd86c4c00e1c453c08d0c5e4f3697a4538059ac6c2413cc8a6b2a1ec7052899c386e78de0e1692489f6d1e9f0b0254b484f19e8a67a9e39a495501379", "MS2": "122a1bb9e7edac5ab785d43cc833b6049caf3b88b9367943ed7ca60e6ed103ae", "MS1": "13b40959407d4ca3b03cc813ae4c4c77894437904bf791e869aa01094e64a447", "CLIENT_SECRET": "041f8b6633222d673382decbd87401826ff59a871f492e338bf82ea383e61d92b91687ad1df7bb33cdada8a39dc7ce9d91f063f7327301f86c24ec56c6c64de103"}, {"SS1": "23dcd8d0654388eb853395fe4aab17d53dc110d4566d596df454d64834a87fbc084c8ba880adbfe65f75351e96024ed7893dd8abbd047c4194fa2affc496016d027a2d6c6cfbcc9b6cab6dd892ea9f8b9ca260f6a104419fd5091942116606142366992c274d98b24848f0db78f74148145577009d7b75a5d8667e859a2a1330", "SS2": "18bb48534e46967160f8985f1a4381b5097f4691288732968bb715e6c04169c61ad38609dd4df8edecdb083e9599dcc330114d9ea8054acee8fd2f161bada28d02392109c1ba811cb9e4f60b370d82999a44dbffc9def41feded10e3b0d6073514faa3772174432583c0b19347559cf34ff795d7c46b5fec7788dc41a1203aa0", "DATE": 16574, "PIN2": 8857, "PIN1": 8858, "SERVER_SECRET": "049702ed0ad93b0217f506e059be3903efad0a1607eae833b5313a2811376f531c4a58d68f83a872b241e44edbc06a5cdf4bde2696129bd7b1951c1bab4469361b35b0aca1c79570afbe117927faeff81946caed6a254641b33c527b87b998d812849d8f98cdf3d32028a5bd15eec61301354989c6f42dc5018729306cda6397", "SEC": "040ca2208a482a8d77fe3931048891254a9d97555e04c9e40be655a81ff4db4c2621166e501c75515795f229cce936b7e42948a0aa5ae50dd4d597710560360c85", "TP2": "041701e2c54b8562579327a434c745aa00c691893eb6155decfe26fd766972a11209ec463b15b6d84dd38835700d3f274c6792d39931fb6940aa2ea4aee5bfd9f4", "TP1": "0414ed843660b29847dd619377f1c4a72983ff2020240f5b8e73b5f9df0c3ba9861fd758da9ad5c1b4c8bcef2486552da615f9d6d7eecaf082bf684e74936154f7", "CS1": "0421e212342c55c0691c3f57df3ae38ed7a98ba24f411bd9221aa79d244f75c30e0aee59f8f7d73ee26906daf92dc5d059a70d6c8d9e78e23f7f22d42826ffe422", "CS2": "04164794f322fd99effb18fcb076f81359606a3fb88dd28131422996ef4c55998509d7aca685d91006860cd0fad6adf060471500f51b9850c8ac9472c356162207", "HASH_MPIN_ID_HEX": "0227b58f21dec8a55dd751cebbf35554e642bf4e58894cae0613cd13792c474b", "TIME_PERMIT": "0417cf27b0a357bcb612de2d42108b0276b88c62bc3cb8181eb5c6a844723b0df4218b02fe6ffbb18591a1cdd6c16d85961f093d9b0257d8df887b3a517a3dad7d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34375a222c2022757365724944223a20226534333462303936356463663135393564616133303561633732333639363365406365727469766f782e636f6d222c202273616c74223a202230383732303133646166396464643231227d", "TOKEN": "0405ed45ce5f03dc9bee2874f487a85b887aa74e374f6ee881247bb1c5764d715613127cad871064a62eba46f144a5354a960bb808983c8333ac31109b8084f708", "U": "040095a79a4bdac91931adf68808d754ec1c32f394f84304d0fa825ae37ef9a4020501ebab53a3b6f8ac4ebc9b42d8bfd15a6976e157efbdc1857011bc93a5db92", "SERVER_OUTPUT": -19, "V": "040c31a2936126dd31b369bf5a79bb06e71d89772addcdc7f674b30bbee43b166712c3222f0ff4a9368c57f4a7d51d9e752917efa861a59127f584bd85b1ed0672", "Y": "08e729961ff00c99b2d8da1473cee8c031808aff9254885e588d458222f2b5d6", "X": "03ed50fa9501a5afcfde060f217306d8285140ccb0f05bd4c6e476bd3e9a6eb2", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:47Z\", \"userID\": \"e434b0965dcf1595daa305ac7236963e@certivox.com\", \"salt\": \"0872013daf9ddd21\"}", "test_no": 150, "UT": "0410aea41ffd9cb8ca3c04dcfd679c7a92934065cb41cda1fe6257c1794e3f221f0434ec656faf4614f7fca2661bc21ea4a677902dac38d00425e3a72ea5a4db4b", "MS2": "183633580177ebbca585d56b96dedc0cbde3ea874b76c85571b6107f72ff922b", "MS1": "140afd321b228d12d5be734e0841d5f9bd933002113e7a4990836a4f8aa873f7", "CLIENT_SECRET": "0420e26775029546d8aeb9a5fe1fea7c01cb673d2fd004211fcf9b3ff4af3b7dc803906292278c31e91669fc3028b9315de223f4b76c25567c95cda41604d31779"}, {"SS1": "01f7ce2fe2a6eda27f818b62827bf0d08bc5b5b8e077fae8a8d5831a8f26c0ec102cbf2ce26a5fc22bd4e972b49ec1776c8e29d79b3936f47c1c11c2b5adebb7099b666fd4b26f3bf586c04ec586f9459a312fea234db8b47ae8599a80f4e63d11ca0648974f82173fc397ac2f8ab0c0c64b77fce812b58b951caccc95c92fad", "SS2": "1abdd7cb66f87d9ddb5ebe6332f187e0f747f3f3f2db0cdb8b206290b66f90bf06a6f56c8cba9e45a7327b350b0d72c82089d547b20b2f6aa2a86a44838b024d054332d78aae737d291393c5d4744385f0b30c7d902bf772a5feb8b8ed750660194fa3748b5b9e74806deba9dc0862d6c8bb3ba3b002729f93643681e7ef0019", "DATE": 16574, "PIN2": 8986, "PIN1": 8987, "SERVER_SECRET": "05b4b55929355e0027122acea8755d54bb65194cc0e14efbca30a9583b5a712c1d66da4e7e428602d00225007df73cc664ccd3bf77d76052b05967a1ccde93e31b940df5481cb363217780e70a8708ee674eb5b3a8aa7e8de8e0762cdfeb77530bad2ccbae6d9bccbf703b24e4423cc96c39f6e26f5eed280784a3edc57ec892", "SEC": "040551e0c93fcf42e1997ca93663baa3f0f731955d5a0852d2840d62b5bdfcae160d7a9a1fa246d38a7a881c5265e94b4022958e93f95b53f9b524efef78286ac9", "TP2": "04073dbba21760c923de667531ebef4b5d36665c1679e512b86bebfaa1cb28e0891ed6b3517e2a11faa574c78a0a3a200209a9b8c248cf98d84bbede2e148583f4", "TP1": "041711a2c646a9c4ba76229ee75063c1b9d1c09216d2b44904e5a225c0fa29fd4509667f9d3cec50fdfe7c7d4842c098825024772d2c9e4a20b873953901b98d06", "CS1": "0409e72ecf0e35827c2f041c4eac18e6a2a9aa588af7407944907ff3abd9ba1ef8049a5a5eeb7246b3932cb5849b4766c4f9734c7749f610f015903234ecc9373c", "CS2": "0417d8cdf0b22ef19700f74b828b9bcefc6f48601111c136fff33123f5c994ac2c0d72891db424db7e32dca5bb00d3c088cf0706d32e08e1638a8faeb53361b5ee", "HASH_MPIN_ID_HEX": "3db59e427bc96d1a6d1b17e44e18e2d59de6e85d0bd0149c55cee96606beafdb", "TIME_PERMIT": "04024468132eec5e31ae89fb91f103a4f5ba700c016a8905796ad24d3f6feef72701f41fc763b4ac3fbda940fab298caf24bd038f2c3255ffb8ab7ee069fa9e525", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34375a222c2022757365724944223a20223030653331326531343663663966656335666466323037633539636265643139406365727469766f782e636f6d222c202273616c74223a202235623836626263373138616562333039227d", "TOKEN": "04026de35e0502f0485102667e3dc700d90b6fc60beec7cc1357f4969faaf495a823dc43d2e6a9f4b487d062963b112112d73e4d98b61b8dc6d897f7045b7ce6c5", "U": "04109d95e23b724bb56febce17c8f70ff1aeb3a8e9fdc2b922c198d1633d6fb6520294dde6ef2b1b7b90e58e2d438197243f794f25796a61e4fc31607ee0fd2321", "SERVER_OUTPUT": -19, "V": "040b7f09e1a8f4a52f81d0a2cdf3c9a3b73ffb1ac94cc31bd6b89143676221c7fa018ac01ad76bb8ad2ded61c41a5e464c43902ce04edc6bc41cb8cd635e2e1e0e", "Y": "0c0034c03543a0f76416f351761d48dc283a5fbdd48810e65e55d3c1aa748b18", "X": "17bfe60e15e2c554dee0c5b89b20c2f9a40d909cbd56be06b1e95949000d7e06", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:47Z\", \"userID\": \"00e312e146cf9fec5fdf207c59cbed19@certivox.com\", \"salt\": \"5b86bbc718aeb309\"}", "test_no": 151, "UT": "0413d8eb927eaa9f705eb54a08f9b373c6167284c152d84d9aed0ae646171ff1da1e7874c19b218ffa3f792298dc192674edc5f237d3426d297bc6c77b69462d4f", "MS2": "188ec3d33b6c8de0e8979d316d9b102e452e1a7de860f3f87c71c53637bc704e", "MS1": "0b411bd2801c80db3ee60ce4ad09f0322975070f053c6a390dc79bfc9fb0783e", "CLIENT_SECRET": "0403d6598bde80caf714cdfe2089991e7a700c9e58bf49747837d13589b70b0bc209d22617e0aa99bc91c82b1ba45d9185dc4c042289974a8d05cd9856c4edad70"}, {"SS1": "18e39d8f39dea8526753adfb500ab334dc2b31d00d3e292ed764e5ab494830d60a238561c58774f2ecf203e6d6192ddfc66cf8f3d286c47f3f8396ecf19ad7642280afd2ece120cbea9cb9f1b86b51937cfaea56076d8fb9a14a287100c9a1d81d81c35efb35d2180b7fb81517da535204ac775dfae111e7ae27b45d970cb304", "SS2": "0338e08648f81c6dda47e0513b28b9474dff0d6134ef395b6b1fd19c90c2ba6d1325831a9fcd59dbd6dae420f58317e3adb16a25e99372dbf3b36bfb2c2dc4a90c4f99e78c188130f3d3eddfc7aba1403dfa8a46180f299ebbd5e7d7a88a5fe2042718045091f34e488b37f0203af8097e4c2634ab7de9beb49495fff196ac5f", "DATE": 16574, "PIN2": 2587, "PIN1": 2588, "SERVER_SECRET": "0129af9f3fd3142c85bcf91847dbe6a7bde544125815528fd5caa6287432e78702bfcb343cf96e4f0958080e07cc9cc2f2c9e8c29fb5b12428b247a0f7b620f01c0f178d6812fa900e95f9eaa1c6a6939ff623646532df0eb154b56d59da2beb1c788a5b2605d5b99972bb17751c83abae935c756e1352f279ed0ab5ada3400d", "SEC": "04020ff5bb4a7086072d4c66de88e10267db3c3a0a0ce233de51d71224248611b21bda252dc552ee244fc470e8a5fce12bd7bfb62b236f779cd1aa005c71e84c85", "TP2": "0411f925e05e0d39eef13c2d7da0663c48276464523e7e8075f840f89fbbc820b321d7552c8095abce3e472a3a3ef56b635629df1f7e137b4fa2c90a7b213f002a", "TP1": "04097c92b51f0bffae433a331f75ce97e59295556b029891253baaaea7a606e75208f2710dd5745c27c8e050be43beb4180b013f8d5260bd4a027fd922b8dbfce4", "CS1": "040978b294c826c812ad6eadfc554bae2757c9f1b3a8aa6424ef18acd9a4946bf603f7ebb07e26cf91a44eb1d3aa0308b8e17ba10f44cc791735dcd8a7e27dcdef", "CS2": "04035203ed50397747315f90dbab89c835c9d42d7674855337670821e3d9b87d5d0d38893d06969b14f97a17aa6486228b412a3743d6de992333e7fbd66c9a1237", "HASH_MPIN_ID_HEX": "cfca3b74699510cb07fb528af442430ebebf95cd614ce28e8a61de78b619f531", "TIME_PERMIT": "0413e46d7167cce11cd118cc22ed6aeef576dc1e8cf5ee2c9b25375d37891b57d502976004ab8d725919e329c700bf987ab2baab08c809b0970cdc49c4b95176db", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34375a222c2022757365724944223a20226538616164383964633963626264396537396361353837326332633535626438406365727469766f782e636f6d222c202273616c74223a202264306566623630353834663965636161227d", "TOKEN": "04056da14440c7755318b354bd9e6ab05d57f45527d44499d6ac34e6ea42c217331047be3bc5ca6d2c312d5b203924c95ace2f3563ccfc52ac72f96d6f80456936", "U": "04116fd02e6461ecf9820100e27ff40c0a77fdef2f0a0fe87a9c3c207039e3bc041f10dbba3da56950dc1cab51a5e52249b5efe2ad8462865c7123795ca477ccdb", "SERVER_OUTPUT": -19, "V": "041d807becf63df6c489c855325e8b5b6af9ff40e0e6e08c731c319ce08f68521706f039d50d42e4f13a0dcd0e44ce7ee8de5f0c402d338199822988ba5c2721e8", "Y": "183679131dafcada1725d89570b63f77bc950cd61edde04cb9d9c5db3d0456c0", "X": "1cac0a8c0feb7cfb658c4120f4edc5cbabf3b97c1d08137442215eaff3d70b59", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:47Z\", \"userID\": \"e8aad89dc9cbbd9e79ca5872c2c55bd8@certivox.com\", \"salt\": \"d0efb60584f9ecaa\"}", "test_no": 152, "UT": "040b8253b61833914988dce08811ec5b700bc936feb39ecee9d1952648535ca11a1af1e0e8f1da1292b6d133a5ae999f0ab622a410c1bcfa2dbb8aa1e35b7d6fa3", "MS2": "1136a7d9084838c8ea16ce03af6f25f4bef0b51ea68424766d690bbd243465b2", "MS1": "06e9b7161799cb768eaf7cd11e349cadd2b3b5d1f1eaa237e12ec650a406efb9", "CLIENT_SECRET": "04031ce6263757a629de865818ff56ca52e10cb1566ffffaf9a2c4c6d27f89ce6a2268b6d3dfe24b94d55be41daf1460250f2bfe811850485753e84f060a65e975"}, {"SS1": "0cf71b6a727a0ae73e51d4d623a8e42b02797a5bd51aadb5dfddd236a99e9f8e1d75b42f6c3f53e39513feb2f5eed4df3be624871775be627a6bb6a3fba94b4c07409bcebb530fd162e10ed1acbf90f17476999e22f636e844ce6b65785bf0f40f37c8d5a91c0ecd49fabfaf3e41d4811944d02427763392055b80a252b53e89", "SS2": "1fbcede0aeeae8de4d3dd4ca42845bbdc42d1c073d37d2b1f6ae3e0214320c36232785523559669fdeb5004605d9d59a9612e96009cc2560dd98e387f549afae04279d2cfbec9eec72dee62faa8d9b0ab8bbaa949ff581e7e275392fe9a7573004ac119fa40c52952b3591f571909404b78dba91166a78fc5bb818f755b8cd89", "DATE": 16574, "PIN2": 4116, "PIN1": 4117, "SERVER_SECRET": "00167438b27ddf3026d448bab38671642ee41523e53755c4fca05fc9459e9daa1c9ce850de3f0b639b2cf7418bc1373f2fd806b8456d4f70a824f3c8344e781d1e13966fe209d226a73b24cfe50b1813b09ffa26dbc4376cab3f621f1cf258521e27dadcbaa40f150db85869956e206d01fec631430b888fe782f3f42c9c2777", "SEC": "041279daf2f1e246c42d56becd08930bfe5628f2f2894c09482b3ccf4648818e130fc291e5054d7c720881568b228efa95ae4bf436c91e1e9dd4299898075bcc8c", "TP2": "041ce691098d3ca3a237097ff95e4e9b3130d5885b756f35d0ae5470ff3b6ea7d8070fff716ab2781fe6e6a4a3f0312f356a760def311cb89fec5fbf18cb98584b", "TP1": "0412791183b27733c58b03254abcc5f3458d4951608e334f0a5565ddf0c6001acf11dc7a547eb7c8c5d5bf093b4bfe99185cd89998df27cd21e7f0988cc720bcbb", "CS1": "041a86c9b655745ebb8a5df5b7122eb3b3d9c3e0c83fa417a51abc21ae26164d880dafa6693b87d2730a2172832f6904f072a76a841cef83a2527005c3317d0fbe", "CS2": "041277213da928bd02a4a33c7443a5af33a901e8413a8cfbd306dd21d70277acc5153fca98695e28f334c2013440deabb728efa091b64682718bfab6988e306106", "HASH_MPIN_ID_HEX": "aaead7e50bef59990c7431f569225b68d40b1386dce956c502a6005948506cd6", "TIME_PERMIT": "0404326468118ac861b099eaef375b8bedae5e13498647c380c3d6db769671e19a1b5ff08347dbda0d0133e0cc660ee6ca93acc5886fc53f6e5ee75b3701e78c58", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34375a222c2022757365724944223a20223962663034376565396135656534353733666431663830383031626431383130406365727469766f782e636f6d222c202273616c74223a202232326334363664323362336634316462227d", "TOKEN": "04225a900ca37aac102373c8a0054c490a46f46b76d66d8d59608a85583b58518219b67cea0812fd510dd54e36cc371f18338c45a640ff33162d5a068dc84b425a", "U": "041c9924e83188fd6de41ea88340276da449e252549c0bc1e1f92b4ddcd9becdc30a4f399dbbd855dea3caa1e540823b5f02b24f46eef626a25b3492ddce1c2233", "SERVER_OUTPUT": -19, "V": "04086561ce3151541bb9a7b89e22ed796b89aaac69f6d512f0540dbe959b51b1dc03f8cc3f1cad5d79aa2c6c8df0ca8712e2b74e39516bb7f64642f8b2f11ef5ce", "Y": "0e2207b6ba67fb89af60c89ef739881d008eee725a5bb5d36164953367b62c72", "X": "0a930cc9f09d4ea20a1fa3f2cf2da0456c50578484e2560a5e9ac2f414105dd0", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:47Z\", \"userID\": \"9bf047ee9a5ee4573fd1f80801bd1810@certivox.com\", \"salt\": \"22c466d23b3f41db\"}", "test_no": 153, "UT": "0416f205d7fbf7f31896cdde5099d10e620285f7b5e13d1341065eb51d20af7d001693d9f01fadd286f46cf3a8c0361988105988ee3012a18fc79c7746a70dc6ee", "MS2": "20c736cb9712d4a5dda67a7a738c7a94d75d95f102b3d0132e89c2128697b123", "MS1": "08255c145299093f0e240574a3f05f778c14b61992aff60eff590c7d68541066", "CLIENT_SECRET": "04086d1771b9d66ce7d18eaed2b4860fabc7320a8da4f02b55a0f000d6ec90162d1113f2348da4173b2644cd4e0949c468fa37de4773f8681385435d635f7e63dd"}, {"SS1": "18c6540a5723ebf8becc3226793f8c489b718cb8de26e982661ed732d485c87d0b4059901facbe3a5123d6f4e90d8bb17e964c1e2071bb5ed8c198dd0e7bbec3224df35cb3ad0425470a0fd6a95a1c8f6f98a96d6a91f97dcc799c74a813112b185591e976e52d265f4a90debbb7cb22e1f754030669013e8dd45e635a5ce0a7", "SS2": "0d57bec8d734e20765a06f5cb040756532d0d911fb6725350ee781d50868ab8618d80a5cb38f2952efaaff2cc6b806dc623fd4512b8811a36808b91141e493dd06bfea90036ebac93c53fd0f46f7719818296b1c5187c3f7f0a2ebabc2f7ae600e560de1891a1ab0a3a779f8bf01e2be606fda03a2b35cc23d0609d1425c5a39", "DATE": 16574, "PIN2": 6000, "PIN1": 6001, "SERVER_SECRET": "1d1e4e62087529e840aeb5b61c47dd36064e33bee5acdf7a28d868521ce7210218591ac53ec9b16d5ce6982da282853692b663c7a5722da5fb9c30961989982718931db187d74b7d4a6efb8db7449fe686d2e99a7f390e1716450a4768d1300103af57945e49989d071106f4fcc19e93d5131a1330f6b06928e82aae4f018c5a", "SEC": "04236dfa085c58f071d6c40b431d4cc771486b6b879b021a15d7aa5b669381ca0d00899c78e765ae449ba5b0c1d51240601ba61ec9d8639328a7cd6e0dedb55a4d", "TP2": "041d28336610512c93997dd19d0b1bc9c3b4c401a178e79a09521e4d1bd29cf87018824e06e07ddb842e32fb0d8c2cddba3d7c404e2bd9e6382831c2c3114636f6", "TP1": "04116fe74c460acb4016d323858094e01b954ebf572c6f46b72658ab24f22db02703a106385adb095d59e663c84bb06b4a4d25006b365525c77d274e79a9b3ffe9", "CS1": "042198d6e9bd0f6d2318a402ac1c65c9aa4003e8fe373b27e0ec0f2e76733030680857bd8195733989c9451a7b00f161dab07f61a0fe2a1a7a7c6bfb8541c42c98", "CS2": "0418e66639520cc3938e95badb71e8118d9dd101e6c99acf527a692b733a9a90bc00ab8b6917383a77f910553343013d8fab7bfe0137c21c05ada79053b2349710", "HASH_MPIN_ID_HEX": "7e3f90a7d5191975c975c69990efde49467d08c4026ebab7b6cfa372fe38d7d1", "TIME_PERMIT": "04077780729e0f65ba2f8ee02aa6fda9ae8bcc99999bb0e512a7bb96eb3de24cd906b4f00abf606edbdba0c131143416cadef3e1c66fcceb12bc54e5790e2e04d3", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34375a222c2022757365724944223a20223065346235373466363434366532616366383764313566386337303538313933406365727469766f782e636f6d222c202273616c74223a202261663833663966333561633436303736227d", "TOKEN": "041fb41deaae8bc357b160f08bdef95e5b6f62649f5be012dbd443c4d88bfcb0bb213a6188719cfb47202491bb19c6667ad2133c3298faf78a7c077def7b31b93c", "U": "041408e04d7a576e75bd15696993fc4cd7438c5b28ed4e8f27f3ad2afbda3edabe1784b05c94452f801bb40c1398ca2bbcf919583dd20c3f2347eb2ac42ea26175", "SERVER_OUTPUT": -19, "V": "0402512bad5fbe0ef3542ff30bd3c96951f795351a38df420c06c59f5f241ef7b11c43d2b2df5fa1bb6843c6bd15695890d0e5a24668dfb641a2dd3fac54d6123a", "Y": "1b8b57ccea81a040287c8a154be573808aebf96fabfde8a48f81d56d52a6e966", "X": "1ed7982a69860282148d72f6292ac3e069f54e0f4814b2fdab216f425372136d", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:47Z\", \"userID\": \"0e4b574f6446e2acf87d15f8c7058193@certivox.com\", \"salt\": \"af83f9f35ac46076\"}", "test_no": 154, "UT": "04014f57da53cea28d38278307e25ca1966e9462900379cb94e78af05207734efa0c33dd3af01eb1ba2ca48ba41045b0f95c069ce6e3fa12f82861abd46d170da8", "MS2": "0b2352a7a5d411211129d36a5543fbd5aaadd59e6fdec780a2b5ae48847c2511", "MS1": "1eaf8021283bd5c85b9373d942fc1d96d766b7ecb8b8961a3ec66aa0d85052e2", "CLIENT_SECRET": "041caaa7e22344a95198be8d14f84313bdc4a0ddf8c9eff44322974926a0fe4bbc14237db5a2c8b317ac3ca8fdb2319aa192ac14da0784c55285fdfc30976abb97"}, {"SS1": "213c2085b68ec2b6c2d0c29593734c580fc6fc32d76442be307b4112dd23086d0442d81749e4dbc8bf34380066c299f90b5f1a35d4984e15ef3b3ee4ac11440800fe570f4372e7185142bdd1102e16389523323ba2b0608fb51d85edaecb9c0f11157b8a680d62313a94a3dff9076ee98f1c025d82303ce922f5d3e95f69311f", "SS2": "23e74a26bbb9d3ed669b22feed9a9c54e5fd1c5f22d58cb74e3ef9c9f425bb180b0b40e06679ef11a35c65f058283de3dafd3699535212fbd5f81d01acb644ed1c824a113d75a34d2d5cbc867c9a46758d1d6cd8f94b130cac7958eb70c05ccc0482206377832072ece118cb6103a5e844c230b830ff9a8c1be9afad0e63e389", "DATE": 16574, "PIN2": 4919, "PIN1": 4920, "SERVER_SECRET": "21bd7b74604df1c38564c817a0b6c6060ea435cb69cd551e405fc8a6493aea4318511029071047461925d26f52c586942b72cf66b79242ecec58c23656c7ff4013030d16250ee7a1e2864aacac06ab8885111a4b5b67f495b8712944d70ed2150990a1a2beb59feec9c173facc76e15f7742f9280a0399d574a1cf20276c2cf0", "SEC": "04021f55a6c5aba8529b3f4cee0344b1c6afb027eb2ef93b2a6de1e085cd548c0f09a1c6679e8695e00770d2c75b6bad7380646c17604ba63d405cd506e63d8fd0", "TP2": "0403d46c5c59a280481f8f220208e5d4bd1a6b6b89ddd3357a1ff0a8b89fd69e6f0dd803aa59ca68b193917d4e9c538648e868c636f427eb601c0499bfecac1e27", "TP1": "041e29ba0193a12745365dc4e8e08b72e007da05bf7bbc95f7f8cfd46b9fe2f5ba0f998a12704d83651e6f5078e1403543fae0823123f98110dd249d2ddc5d53f1", "CS1": "04115d86fa1c899aff1cf70ad2390307855df3014ba2eda371169de8e19f38a56b1739e0bf19b03a0f7ac5299089b27443ad370eaf4598e1a476aa0c6c30f6b117", "CS2": "0408459ce53302ff2eeef84bec69fe3acb87e06d84901f206890a5e888f8c1501e0582b306f108013012d6d266ccce508f36a50ae78b23183d785f04b6b1cfc4fd", "HASH_MPIN_ID_HEX": "e86d5c93445f231b7af6eb4a095b71ad077d3d4e89e1aba055fce0c7b20a562e", "TIME_PERMIT": "040572a7740cd13f1b568c3821a8288593ab26d8ebcf95962a2f2d4123ad76592214d9c8d08c2d8e510eda8e49f820d8ddf301b8fec50915d6f391a25380864cdb", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34385a222c2022757365724944223a20226461303961323438363136653339343834323566333032333466396131393832406365727469766f782e636f6d222c202273616c74223a202239663330373939393062306238646234227d", "TOKEN": "0415c348236b88891c92a4d2c8e411324086bf41a26b9127d3e8708da693c26d9b11435557e336cbbd9f1c12a52b65e37f11cd980d4bc807324144353da09fb72c", "U": "0402c9fdb4a4cf8404a317a01a60c3d37d8037d87aede9c4f53e4fa67a16617a3008a9a0016731d262f6aa7da32f81c9eb7ab99ca38ff11fe8688c1c19f3c28097", "SERVER_OUTPUT": -19, "V": "04025b5d0a96e19655b25f8c2e1f4b7859d5221491e4cb01b30a5846c19a37b9231f2c52a79fa5e74ba0b24b6204d1939f49cb6765fa7306c6907f9593f6a73365", "Y": "1740a7e1f08af5b74feb24710814b8d3957327cf6211566777dc3a2fd2113087", "X": "074b5f75481fa51fa964763cdcfe77130741dd7b04073c57a67b0f54cdb17e07", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:48Z\", \"userID\": \"da09a248616e3948425f30234f9a1982@certivox.com\", \"salt\": \"9f3079990b0b8db4\"}", "test_no": 155, "UT": "040aff8ebaa8e8bfc0f2c56daf64a453a2233bf7f670485c8a38ca842a9d33a47f1e1e66c3328d45111c9a83b99b92a2779d301d9a89176f4358e8867bb10d1ba2", "MS2": "00227d5aea56b6ea7388dd9a6aa5f7ef62c2f8630e42692777b87eb8406503a8", "MS1": "1e64352388c5e23564820dcd6ead5782c992ac7956bd5db827079f4df2d91256", "CLIENT_SECRET": "0406d2eb84194d16f6c56e739928f07e298a068b709b94da8c8292a2f92f32b979046d140afda50dbbf87121b6d0787b6f1ad36134babe9c4791e149ba36c67c69"}, {"SS1": "179062b800ce830d966ec0b0f9085e2f2f488e50a4dda7c648df6242cb6d0e831499e20be239d7695ea49e052cac6524b180bdc998fd2ffb652d7053409891910301958e8ee7bccd873b9fdfe5dd3e0e213a6bf22b5f1973e1f3fd2f2728e63e1a01b84d6f34e5127bc35d17f83db07dcfc1ae209f1eb4235e30f4295520386c", "SS2": "077139814959875fceedcf42ff4e4e17165cdb18d6781e95e25f0cc10e600f790e714974a2f06c173ef85cc289f5085c26d0a8398d17113be74abf822e52ca86053131bb14ef151997bbc290d7a3fafe317f7f41b6b9b6d04aaf32152b6ec7231c599935c6a4e1518b19f70c526a9827f475a294e439571edcfd8960c3538352", "DATE": 16574, "PIN2": 4445, "PIN1": 4446, "SERVER_SECRET": "166c46802f66b795bd248c625f7621a9b3a67225755fb2c7d34af67d172447d1040b126d85bb2e9215b109a7f92cb5674a30db39e18062e7df0e2c658146b2bc1fa6fe9d9a041ca8ec19a8f58c4cd446616dbea7903556d0b4e2beb431d19aea07cd6bba42b37d71b7e51b3e67a422bbef18023d62bf5b690c0b29a79defd88b", "SEC": "04085d0ac1a7b42ae968daec0618e2e4f92f8e39bb18755e5c683e1124088cc025098d6ac455707c5e7ca819c2c8c01716838e73935eddc07c8d8fa00cb500d5f0", "TP2": "0411d9436749f781defac5d90589e0909a64a12c3af4a66a751db6a080faea0b721280ed5ce4eddb4f9119974ffb2dc61ba94a76f4afdfaa8d7d0d855eb2a84d65", "TP1": "0408265a2d32cddadc626208701347809d12ce10c8b74265e3410714b01dd7542f02c85d6d08fb38af5a4814fe1335553aa5644931d746028e03dc80b9413bc57e", "CS1": "041863784f3d12389bb7e5c40201c0cdb05a013c8470c220f74a535521497c06cb12646d28c8aaea120fc3affd0198ab3d7b01dd942c96bfef9fe8d50aeaa7cf77", "CS2": "0411ca1da174388c683a9eb1e748e3cffe022ee5f78471694eb390c6e14a83cef10ead9ce7e793ea5755994e087c436c5edee972af5e7033342ae08e360e89f1c9", "HASH_MPIN_ID_HEX": "c53d927bf1e5d850cb87cbdb67e46ff8328d101b950ca8c4ea76a94038fb3950", "TIME_PERMIT": "040e4f4f336be8c8883537075601dd95ccd7fc58cd13e05b429c4069da8b7ba3cd1917d2698bfd9036d559bbd5d57c57544c3fb3ba06386253b428b9f6fd6e3319", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34385a222c2022757365724944223a20223566366131636566336338313166383730383566316563623265333336646265406365727469766f782e636f6d222c202273616c74223a202235663465353964343165373937306264227d", "TOKEN": "0420326ef03912ef844ec07df51c40df6e7ede93829c568bc7862fffc96326eed409b013bd753d177f2fc8301952d8680e0444ca3e93ded098c9a07689c1d82692", "U": "0415d6e1fafb89ba8262ed9c858c9ee32c017756ee413dbc563738f699b46d6e3b121da43f545e5ad15faed71a83d755d1c588f363d4ddc674dea08f1fd4608048", "SERVER_OUTPUT": -19, "V": "04196ce77c49332c3fadacc5bdfb1b4f314b825b313f600e7cef840b46117d48d40e9015bc1b4c3c7891c987c85938d505eefbb105e7b370b117afe068abd55075", "Y": "03b1e8c45e993815175fd38b6342a5c57ca24733945afc0ee813ae7aa3f2c09d", "X": "2066b91f4994025fc800921ad1a1798b4fad2fedb1cd0c82eadb9453e84cdad2", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:48Z\", \"userID\": \"5f6a1cef3c811f87085f1ecb2e336dbe@certivox.com\", \"salt\": \"5f4e59d41e7970bd\"}", "test_no": 156, "UT": "040385827d1609f5247f7e5df3463cdb075892a6a22cca80e57cd253a144098f560fdef5e7c873cd1667c233bc7fe867f92fd09abfdbb4d8d2a27be1801c84f208", "MS2": "17d7e5e462d943809ce4c217d87addc8b9022ba2ffaeb62002418dad67d565d9", "MS1": "1d16a28a0c5609e08c023d8926cce8631b7c09467530ff553a0608b82015e2e2", "CLIENT_SECRET": "0412622cb9db7ed90219c0c0ca0485ca2119eb35bf574c8dddac7f2b89559c1034046be6a1b8ea40135f568ecb33a72cfd362a755ae8c5ea868a8b272b3cf3e5d9"}, {"SS1": "0d9d3745d1bebeb0bce9c3a11beea6f7494308fdf37854a448c4d971a838575a1dd59aa211ec8181d60ad43c9bd94d28e1b64f8a1b0742c43b84c2ed94587c50110fb6a10fa4dcc6489d53ac2ef018d26c7e6d12669c8ceb8523548607a3b1140c005559395fb668fc75a846c50cba7635902d84ed83037158fdaf8b82e1a0f4", "SS2": "0fff2b257999495a1dee01947fdf30e77a42ff67a55e31caf6dea745856cffbc0febb812b305592ca52eac6ddc067bad5fec86880b008c0a1bcb81cbfcbc933615e6d9f9865461195c6774692cf2da1a230a0465f18195495227cc40535ef46b1b7bc31110d32d27525b07cd8e3b30e6331398a32be2b242b678a8276d588d7e", "DATE": 16574, "PIN2": 7124, "PIN1": 7125, "SERVER_SECRET": "0c20866f16f8fda0b648d01954cf65ac8d7b19cbb045a443257a018bceccd9a504bdc7afd919cea42afb75862880c8f801692f8e3c6fa948e8c315ae81f3d32622a7f5806af407fa21699ffda78015e9afea5d9d9c591ab8cb8059ac2ff44c5a093a53a799b552c4441a4b729a6ffeb982c37548950cd0e224818377fab1b685", "SEC": "04087f9edd825daac113b5cc52da367a7e338968872d477335b4e8ac9c578581642329daa8645661904a72c5ac5a8e5c5d321ce5af553371fb5062742869c1d42d", "TP2": "04189c8bf7fd1dea4a742b85cb23a0bc1e0b7506e87fa50113e7a4aca133e733bd14170882b62ecbe5f97fd0dc93abd2ae30287de7aa6474ed0f05b909c7dd44c9", "TP1": "040f0f3c3bb18046255d6b0b0b8f98fcaddbcf3257fa4d222bd65feff7dfa4ad6a18d872ff61b50977cf1468c757dc08508ac941cf3b92fbba5df9cfe8628e6554", "CS1": "041f6ef1af8c2a242eb66af071446171840c94250b97d3742e5db06730858e3ca003dee57b9ab11fb94f3923f64b2291896653c4f29509ece3dbb3333e5180aca1", "CS2": "041feef74f1c391293b0d25e73cc9d67e36fefd50a6e5f283f4d171287488335ad23781e431eb25b6ba2a4b585046c297e0890ae5ae40ea6ae5524679590721784", "HASH_MPIN_ID_HEX": "1b8eab856759b1c92c492f72685924c8d58a8a252181fbbd126f0591d259aa94", "TIME_PERMIT": "041d7cfbaa76df049529a1ae44907a00505532bfb6e01aa0d05015520cdf58a3f2074f13453a83ed6f012e6953f7b27b3913bfe11dd20b174b5759d1d05cc618d9", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34385a222c2022757365724944223a20223865613732353534613230343939623632623164376265343963643430323238406365727469766f782e636f6d222c202273616c74223a202239643765336233373239383531303136227d", "TOKEN": "040b72e33c17d28a7dfaefe29bdafb3604c2bc56f1ed309b35321db66883a53def017e7f3338c024b61da7d78a83e7944268c80e22408bb8851951bd5c76dbd64e", "U": "0417c527c86d8cafa4771bfdd82ee22fb86c59e4e4c910040ca4409539729f8f2d1a7cee04d4911cca5e4b09db82f6838f45b411f67b45970b9a00b5df2ecdddcd", "SERVER_OUTPUT": -19, "V": "0415788ae8b10f9834da9e062300579ac5d407b7fd5c3626ae4298377a01d657ad201f7d35069c39c6fe3ead9dcc32bed0025d37403ee2367ca9e9782ea3f1278f", "Y": "11e82d056ad66db48035cc5c47856d92bb0a40f7fe87ab0305dde3450960c77e", "X": "1aa46c52a1bdf4b43d1609e220d09d7cc4ad90daefb7887928d702af913b18ac", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:48Z\", \"userID\": \"8ea72554a20499b62b1d7be49cd40228@certivox.com\", \"salt\": \"9d7e3b3729851016\"}", "test_no": 157, "UT": "0403c88d52e17682df5d4561cf76bb7eed9eaedde55c937e2385aaddb79931da01031013167b3b22585faa8115a4a54a9b78402d965d7cf7e19b731da7f472d087", "MS2": "20f5020b0417cfbf8037c43c840a2e030ff7bc91d694f3e02ad4e892b82b7c5c", "MS1": "211f9b2b9564f490c08793c14fc4aa87810bdeeaee8d5624fb2e0f8bdb26618c", "CLIENT_SECRET": "042254bc9f1931c97db9e848312f5b25bea4df005ff47e68cd77c3e8e6c35ac2f60f1b3f05948db7ad828911640d97309bdef2bafe92f8539e13e1aa16dd9305f3"}, {"SS1": "108b4d1952a015a3996d130c430a3e1258aeb1a31dd3b894be0513d4121f1f94177dad514bf5017d9d0884f45380b2441d6181543840717740b4e775229ace421ff010ccd66a176d84f8e2441343ef3e38ff56aa3ef620c7bd81e34c3f17d5d70912ba4fcb2b9fa8f800f244c6165d4bcbcacdea119e821382b376e08825d0e6", "SS2": "02bf4f68b46ab7df8f977559f3a702991c9ed7c7a9c1f7915f1cd3dc20d3547f0ffe584dde5b33ed1a1093a60e404fe1e07a5098e9ec9cc0e5ea4e7c96be37b301c122ce2c7585c3b2c1122cf813f4cde52322944cfbb77112d38934f0d02fb1148d1767406398ce81d6a120d904b8f484de81f3e3758aa6a3c803fd5ea61c6d", "DATE": 16574, "PIN2": 3366, "PIN1": 3367, "SERVER_SECRET": "02deb44d797bee28481324665430cfa35f9eb236864d594879eff41c0bea39341f8208e8c9c0690788fe7d8de095b157a03f6d93986b265ce90d63f424962c4b0d0533d33514098d1a197f87a932d6a62115f7391b98b0c9eff140565b721cb21e72c591cf88d85843f870dd423f6199411375ff8339fbd29c2e60eeb2684e97", "SEC": "04073506f8f04fd4c793214daee02508d9317eeced206e3ffa9f72df75b887f53008c9746c3ec7be411036b89f3d8c01f855f68411bb060312eece978ad697a480", "TP2": "040d6808ca2c9b65dd14a4a7665340678fa28f2e3103e2b40973fe7cfc5ae2ee75052d6236dba9c7eda2473c2f911ea306d6a45f508628232a0941e531013d81ec", "TP1": "041415befd7fca9f0e1a2861ee990bd1686d09dec79b71498006ab2896033a7eb210d385a44d93fc12fce6b802c61c2ace3567e900d808da282b83055e8cf12c6d", "CS1": "0403e9fc9a29cd80789915f4124468a81a36e2bbddecb1d28407d5a325577ec06610e81d69c6ac3509fde857432b446694265d8fa2a954d75d28dc35292e7bb300", "CS2": "04011c4354e4c9fb06f552c204540f7ab2971b10537b4f0fbfdde88e42b77757db0abad1e4b889c1370ea36b9f0334c3af5a7e863fe28f302a6f6a9839fbc8def4", "HASH_MPIN_ID_HEX": "381a61f432f2693434b32789ff6b795de7d7430aed020e62e39ba14f7a0d7927", "TIME_PERMIT": "040ea4b3282c53450b0522fcf9ed08f0598c8ed5bb00c5ddfa05154d8cb33135981a71645ccba87b341772f806818b326b04d17536c0d899cd29bc82e74d8d99a5", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34385a222c2022757365724944223a20223463656233666338303264653736383461656332633436363738343836616238406365727469766f782e636f6d222c202273616c74223a202231636361303366326135323665663163227d", "TOKEN": "0410c37613e5d12213960368e073fc5c198351852f958349175f19865b5fc56a01070f617b8ec0827ffd1ceb5cad46689275b72b82281666e2657b01f3cef8fcad", "U": "041c8af58ccb74ea7a6f9014d5beebdfbbe5a9bbc8b30a53239e8e929d92148524165dd5e21839e4ca83be84712d1e5ee56c76e1a027f0c17fea2d122bddaad802", "SERVER_OUTPUT": -19, "V": "04082a5e6c1a4b29af75ababd6e206050ce9a00ece74761faed7037827471ca0af228f164f2158bf9900a2dd2f8147e3f08e52f1f5e92a973f6752e2dbc9d1d8d4", "Y": "1791792fd0e9aefbb5f0358e122195afffdd58dc790f6e8f4dbecade28ef4eca", "X": "123bc2f50e534d7de379e1e57039ed053c9e757f3b3372ccc3cbd34ee09a512e", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:48Z\", \"userID\": \"4ceb3fc802de7684aec2c46678486ab8@certivox.com\", \"salt\": \"1cca03f2a526ef1c\"}", "test_no": 158, "UT": "040fb937e43e7b522b2d43a1cb23c7c8b2221919053179f6e0142a789aeaf6956f1c4f89af10d00bed8b6f9453649c4fafbd4e53cf932955fc918361d077ec87fd", "MS2": "1d573d8ada351bc3d27f2faa4ef8e167a3b6103b9a65eded0f36b6e74c2b65a3", "MS1": "00e15b0132b49489aefba76f0a7344047fabf4632f8ddbaf77d3664166602e1f", "CLIENT_SECRET": "040705b96f9120bfe57ba89ff29dc125030307939c297da6e4b7d14255fc3d705c1c8b5415cbcacbee0cc1d6cf9dc11eed2aec2caa1920ef426e7c28bf1d17bd4e"}, {"SS1": "1b4d71fcf47e52d7fcec37c10f2132da959e364c408e13aed9c0a4012c10e4860b8d20371f003a97d5f189edc67469d8f45effc718b72ae909cc8756059547ab09c576a625c6fe597771a328645dd8a552599aea011ca08e6f291004c59163171895ed5e07e2b35c7ba51b055916756bd545b3191788fc663262a0c9d9f4c1f9", "SS2": "0605afd6f94e10e285c38e681bbb958b9db5a827615b56c75e5e53ecea40861f2011451a75ee370639bd2dccfeeaaf2c24dce0dc13b6ac18024045a3f9b848b9120a5901c9687fad4fd5d9040ece6389dff2c9c40e2e9743127d54f79cccc2e71ddbae35a3b85d067358c669a9d4087a1849880a0edc1516debc1491e36de01f", "DATE": 16574, "PIN2": 696, "PIN1": 697, "SERVER_SECRET": "15fc8883230c04b0d42b4bd5f806622a24266aa8c53a41f62978e80118ad5a4d1cca94a861acfcf5ea309da25c1601c2ff040b0b1a07429f56d0bef09578a079037ad014973a98da0eac64b65a14be51a5f8523516e7d25c2a84a7289b78105d0521e337b3d346a8df62d8126ff2fee48b677eda9d1e24c7cb73f8db5da8a6a2", "SEC": "040f5ae4b04068049d3e3486f2af44a7f509596a2f9bde6dd574e534aad2a0daa71c89138555f741ed0ec00ef93f6957a95bb5d1ecfc2dbd87ea4cbc66c6ee4fff", "TP2": "0422682c5e194ffee40f2d3d1bf7e287934db16b64f705fe73808650187bee3e0c06a3f42fe07c0bb1965391c999716c70b5c1c3ff1987dffe0f9ffaabd638e6ea", "TP1": "0412a1e7df91f6b2b2c0c2c8e85a6afe7d0ba3da54b35649eeb6f005bc8350868616ebdd19d5a4e305af27918e25b7c33cf8d4a408c7e96bcc83616a300ef0d77f", "CS1": "0411c24b950d028fb04dc752fa792bbe68f99b3cfb05f9bdf2736a495726dd867e16f6c90aacb5e0404ac3fe1f692213e91ed4e9661c49b91b1f21c5f73960d1ba", "CS2": "04119ecca6501befc03e0975d5b62e22e67cd0200181112861ceed4d3b2afd42f818a1bc3a3955940dd9e645809bc5f251a5c6d02511d2fde2a5ab89c70aa5a1af", "HASH_MPIN_ID_HEX": "9e2ee3c00fd49234f2c505ab0ca8ffc2566e4e527cb4b3cd48d4715565b884ab", "TIME_PERMIT": "040069581d0741784d6b5e403bf4d69ff6579cb564204fbb087e3bcefd25b53d791316f0097d113067ceffd62364d3b6e53a675cb9483267857e3961432a5ba304", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34385a222c2022757365724944223a20223436616539376230353730363830306333363235313765373965396463663834406365727469766f782e636f6d222c202273616c74223a202264303430656536373862393762366131227d", "TOKEN": "041be45c29551c70f59512b4111d78ccf1018387da6cad05da6643dc298f326b3c176205d2cb663bcc0760b18a09f37f4efcb71330081783f99db3bd8b9dbded51", "U": "040a1a933daccd61a4f3fc9a10ee2715b30761427cc6f4370f0ed05f653844933d000375774edcee69fee328a1400f42d8a4559e35f405ebf86fa33f9612037618", "SERVER_OUTPUT": -19, "V": "041ef312e173d02c59da7e04a694f35c195f5e75b4510ee1baa4f61fb1199d795220fe62026e6c014b4f913b837b41b649ef8fd2098cb8ae297e91cd283b8f8abb", "Y": "12564b92252fe1b67f9490f32f656e0fcb6b8b667dcbed2567072323cabdac46", "X": "16af7ae9b47c0918ad5651b9f752148e0d1fd8f3738c07353a94118404ff96a2", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:48Z\", \"userID\": \"46ae97b05706800c362517e79e9dcf84@certivox.com\", \"salt\": \"d040ee678b97b6a1\"}", "test_no": 159, "UT": "0411fcd029d178df61877f31ab143d91133329ad8bf62c2a5fc80d5bbe6ea74e6716e0adad98e97b0a1fdbeef4a2ba4041067c8fdb6e5925d6a4d24b041ccb0e9a", "MS2": "0809f2a7b44cbddaa264223f5dc58304116f9215a60d9391ee22936f6001eeeb", "MS1": "168b56a4f3a80ce27e8890304c73ebf953f64268e55d147bd2640cd35831ac10", "CLIENT_SECRET": "04072393518aef7711ad57fe3f221091e5a3452f465c75fb1d0fcc37011e67707306aab9b8a139c0ffe8db9d2f8bca91aca7824177aa079b6fac0496f474ba5db5"}, {"SS1": "1ead8aa33b6dabceb09549486f5b5c43f0ff2575f7ab5cde696f2ac3e1a81360107747e65c7154f0fef9d463e366c1e421e2afb371c2a5529f612547a5c694c11ae6388430f961adf3ec52e1df9d2b65b07c4ff45693f0f24bba439937aa606722908e57bef4aaf78061fcc1881d6e113294676f62456798d2fa095d6efbc630", "SS2": "228615126005ffda8111997a373486e215ace9ee3c44e802fb7df8049c131c710029afd4252826cdbbe04e74d192584e5131b51470fcc30031541d2be23e83711add45064da6a5e19b5c51e29da6bdf7e99928429a712dc19964b55fd7d719960204a56cc849c6e91479e1894890bdb69773b832c1b5ac08a48e573734e019fc", "DATE": 16574, "PIN2": 402, "PIN1": 403, "SERVER_SECRET": "0328c9e67f09343f4e78e7a38a60d19e3936e3ff2ab32e2adbd8f3727526b2c716b87bf6958a1515e5ea6d87709764057d3910841f521202cc7bb7550afb798010e82891811930dd0187d71d1eb23d1e968fba3948787e6bd5ef01b0919c4b7205d1c88c023ee9d4e6fbb64b80a8d317298ad2f776fdab5448504019a9b59445", "SEC": "0409f5299325be2a9ec0027601c78cefab55e91af17e4e1a8f7b14770917d3158e086908cfc16b4cd5dc9b58476a1e28fede7d4f76bababfff3d389d281d697760", "TP2": "0408bcf116085b252087ee052e29d649163a670e93d16628eb2ef4c8e1001db50f12a236c18d3736b0097199ab217dd73ebfad810d06fe9b36d746ed6ca98b1f85", "TP1": "0402edb622ba205c4568346350670ab22fa19cccc40886c92c5ab3d1f7bf6904291d6481c4e51c3c2d8628009bc25bb6cc801ab873562a4bcd5ee08778c2950b39", "CS1": "0409a885140ad0b11ed3dc31d23761ba83ff64eb4c40de1a52044f948917326d210bd4bba7465ce1d9bcb8956433cb795c0c0687d464e8c88d61be18f9c86decf4", "CS2": "04111a5fc3776177b5e0f6308f423011615fc4f8f0e78997936495258ab41f01b40bc699c83d2f95211216430c7f0628d2b0b2da665cea29f8d57819b4263bc2dc", "HASH_MPIN_ID_HEX": "31c30458ed0b0b897bb077f1e728b10ad7142978a17f03c5fbb2741fe00caf94", "TIME_PERMIT": "0416602b91b05903bda2a37adbd3bde40e2a1261f00749db82c43b73deee0fbe5309eb014a526c3a6bee4d1e579a5fd9fa482b951aa75f04d99be6e9ef179a0845", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34385a222c2022757365724944223a20223732323862323061323437613937353538656265393539633138333962343065406365727469766f782e636f6d222c202273616c74223a202262343935333233346663303230646536227d", "TOKEN": "040ef6263053f97c93c2465cb264c2ca7649cb6958a79a0bf1464458d4b4682ef5162de288b9edc5e918e7e3c6ed807a5990d9f16a725fcc56530bb1569836ce46", "U": "040c6eff266a4087169d15d1b1b04e99dcc52de404b95b94cd1e8b0f0e2642f1dd191588e388d40e5406aab7e81d4023e8efcfcef7e8892e98e2d53a3c27cde2dc", "SERVER_OUTPUT": -19, "V": "04092aaaaf86032505fb0bb679de6d9f79028b18a5e9f6e7ffe376299b6ec8e7c102b61608b96d15a862254c01da66e0a3fcf79994e262d5dcc4f109d732d0c93a", "Y": "00a7eca4f437d6479f4d2bb4c608200aaaddb7e3f383454c9da3a1b8cfbc3b96", "X": "02f1ea996195fafac09bc1f8b6eb74ad7df4199ddef87d5b155fce2855b43a54", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:48Z\", \"userID\": \"7228b20a247a97558ebe959c1839b40e@certivox.com\", \"salt\": \"b4953234fc020de6\"}", "test_no": 160, "UT": "04001902bd93420c1279664248482e8e13039c030bc299389673e455c866b66ea7192318961f8619aa10b25c88c04b37ea53de748f2e3544a088ea6247fcca777a", "MS2": "2364ded79c95d9abe928e2b35ed7814eac9f4e013a19bd752b1409378e6fb9c7", "MS1": "07fca892f3d5227644d551d75fd53d137e803987244054f7d0153a19f3f433f9", "CLIENT_SECRET": "04188dd74c5539211c726d46731417d8018415eaa1de71cf58b3161426fdcf5d0b1acea71a1cd61c667718d905517f3f97fe558638607f7ad2d774b5cd332fb443"}, {"SS1": "16cd3dfe0a1edcbedf0ae818ff08baa494a85ef1ce59e59c17c23cd77e0d5c50011df8a67ea41a41c0a305da19ba0a30884009541773454a0aa7768a9182fb6c22b724c4fa8cc644a3b836920d1722df719353eafe0c19300ce777e6f048cc9f1b8a33852583a52359d204d31087e23950f10d6e46b6580ed0db789356faa7ec", "SS2": "1d88e459f4032586c7771404bc851007e8956d39e44364a9c067e7000ccc2f7e13c1c42581888eda6d3de8c96b106390658dce70b3e91d7be0bb2efd6680e86e17bc380e4720a0e6a0832467cdddacfc47a16f3150230f725ab6588aa5ff883f06ad6ee4d05947721f8c0515eeefc665d08f8ac4a0fc3a0b8542bdf2f8bae568", "DATE": 16574, "PIN2": 1168, "PIN1": 1169, "SERVER_SECRET": "1f21ff9519fc7d4e06f4d2d64caaa49be592167eb412209effbbd66b908af06912fe5d58d6c581747c9973fefb6d91eeaf245f43b0436f98caf836aa0f07482921adf8bd83ab308be56c31a6cac3d939f0d47587bff1289665996faa52ff38a60b10ac0de89edb3c329aad53dcd8c86cd0758be062ccd94049cde6c8e9d13c7e", "SEC": "0422ec947ba14d3594b4d16ded29af225056892c3d60f1e290ff5c85532e88e36f13eebe93ba04d978525b6527b52f481c49bb7f15af1c3b659f0e2d06b6b7dd0c", "TP2": "0406f98ad95be3fe6baa743b485d5fb199f34d59e60436674cfb8594c98de6a85703642b98c72314223ea6ea2d439ef597a6925a4c36e7dbb5f1ef917d14b3373a", "TP1": "04019beede9f5a70df3966ab3ba72b5bc33384dca9df587a397bf0dd70b2537a5b0f6d1bad4aca9fd6c0d3d520e9492208fda419328e09f97bccd715116be14f49", "CS1": "040e8352c9b1a9f6dd07c6443db0acffd0fb1dd5420b442db40d97e7ffe7017a5121a065868177bea72c427ad73cf443d168579061ac80d179cc3a7466c3fd37d9", "CS2": "041e47102d6a7b5ae719d2f4841bf72aad911d35705610bc973402911c88f35ad8165bd81bf0ea1b4fda6a1e6362e2a750ca5cb276a9233e2eb8af6d96afd7715b", "HASH_MPIN_ID_HEX": "afc7ac5be05f98a0f5f84ed8920dfb80ed60f893ea23d746e198dc9de1c11a68", "TIME_PERMIT": "041fc728ff83017368788e74cc8b7e9c74e8124ad2d1efad24d645ddeba7231644029801508cb6f83e892618bb8e461b1b276d2fbf582465c0d1a1a7e1446d2550", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34385a222c2022757365724944223a20223131333131333332363337303732633436353031333631353965643739663164406365727469766f782e636f6d222c202273616c74223a202265333765626566653633313663393666227d", "TOKEN": "0422f3d115716ea4bf323fedee71ad6769a94ba8b028af69542a1c74920ae46e971f67089b072d706036291b115839b2cde7972d734bd35b7653693a13a4c7f12d", "U": "041ac3850c01ea29925abbaaaaad380d898abcee1a73547ff1f2eabe745dcaab2c100d32b6e75915eac1f394644fc5e64861fe38463f0809a63fc2a295d36b5d18", "SERVER_OUTPUT": -19, "V": "04033c187b370edcc9857699bb3fba67e90432db76c0c06969c2684a6c253ea949188a500620a96ee109d3bc5db0800a5f2cf5a4d30187f943d165849064da218a", "Y": "0093ca00521d7630c12ad06e765730d2e4512c76d3bd47395aead265520bace9", "X": "104c33a191b7bed311ce39c4339ca003ed95744e2a0af8bae6837361d8547277", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:48Z\", \"userID\": \"11311332637072c4650136159ed79f1d@certivox.com\", \"salt\": \"e37ebefe6316c96f\"}", "test_no": 161, "UT": "0401eebc69dfb3bd4a94ea6d1ce1748f9dc79549b76102f8756d988b1985f8b7120cc9646a3aa68c5551f027fd510c80c0966864ba773c5b5069c036554f86c144", "MS2": "071d912e963e505b91ff5c12a091e3b84837e2fc5030e1898eafbd43ba56e340", "MS1": "13eb40750bcc9e9a2933d871712ab62efca087407eb61c502caaecfec9ee611f", "CLIENT_SECRET": "0414c2d3af4eef9e8a8a3b20b126a7782e9d9535c3fd7d6b317fd702aa8f17db26053a0655a4bc998b4a5954126de954503b4f82fc3c347523195018d83fd46a14"}, {"SS1": "23f562bd1d78b552fb5fbcd84804cc0c50ab0b7a68faae5da9386611040981cf1f291a3bee35549e35338b25333ef12e2d0f797d6776d1c26f219f61e224216907feea2d013cd47a0eea0a3c0eb3dffeda997a98f263f13e84e702bd3bc2b2220b6295dae4d5e507bd32b45c6e39848e193eb0afa168c70051e8c7aa157341ed", "SS2": "051e4327f573d9712ee94f520ba92c3e0c07509caeaa803207730fbf407620c40de5f2dd21a5a4e909b2e6dade874bf3790397e1b410bb635f7d54fac362166b077f6398630005f0550b60f212e910971a8b1dd76c3204c803d92def7bab5f910e5d9a5ffc303c0dc5d00a2621d0e3c7b779da66269bb2bb32b6cee7c8d0f77f", "DATE": 16574, "PIN2": 5660, "PIN1": 5661, "SERVER_SECRET": "026f77999ca76dc488f3830cbb39ba7d8d0ebbebcf46399431c0df2636b4097f204241526951fa5c53dd188ce899e1c238d5ca7427542f1c4bb58c9755c10f2a155c058d81e65f7427cd4d73edb6e98135d68987589ba67784bfa1c6ec4d5c7e1729b03252ff2d0dc8b001b9400146b4fbc872e0156c33de4e52f02731de2841", "SEC": "0404cc397d346223108dfbafe9a8f963f76feef0f259588ba3f7b238e1f07f5a180dcede27be9d033d91af7df31af5c32fa4cb91038f7c9d099d498bf73a28a583", "TP2": "0422fb9301295b758efdc59f8cbc24c44e2e25596aa9c50dd785e6c6fcdf56c6d10f01d68aef5638fc9cfb5fe1541b5497a914b9dfa793d8a9cb91cae9cc28f850", "TP1": "04186c32fbcc15266f6c9d670eac47ef1bcd6ee96b5eac254274f91c5d8257b2c00e505f8863d8ae0aca65112f75394dff5e2981d565d9252e624b5dab1820bc87", "CS1": "04075f81a4bb470ee712edf1529b317e014c555506e7554e2f1501f6cdcb4657d208a6c24843caad2148eba1bf4ce4e0b68053026ae2eb0eeba4b6d19fc2703621", "CS2": "04065bfdcdabad7e6f249fd62efc196895b408af1d566fa7ea807ae815945488ba15a1f31fa1e5b4202f03589d6960451ef68c4f471f773b959633e947f687ed65", "HASH_MPIN_ID_HEX": "10552a28dc61b0856272b1c6374b7c6ee93acd7eb31874b87db94d62ca7ef366", "TIME_PERMIT": "0419f6a86ea2246e0268d9681a2063ec3d7050185a1f91076952a015409311594a10d8e259954b2fcd3038164b9084e9930d646c77065b528b2d3422ae7a2054da", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34385a222c2022757365724944223a20226461306365303435393937643366643631633935323863383835656261306161406365727469766f782e636f6d222c202273616c74223a202265363137383632356266613537366536227d", "TOKEN": "0404f4dc5bdceeac78c7a02a2bd56a94a337046748b676a2cf736367e5dfbdf0bd10246e01e80bddad1182983e37aff98fb3662c560b10ea2a977c1c03ef4cbf7d", "U": "0415b22dba7c26d6bb02a1860e1c0bfd3a68a179bfe976965258e1022e2257fcd816a85475133da01525b461c25b3f4a96ccbfa0375ae1f3417d660506911f75ff", "SERVER_OUTPUT": -19, "V": "04180bf8ddc9f4e19d39dc9bbe097440e2182d6b8a7f42317ac9fa279c46887ec01fd3df8477c5e205d13c55a4e2669a9b1de47ec9f7ec23131d0113e0c668722b", "Y": "0205a39ae324412da08b985563e030e72649cddebc2255055301ac898ef9b352", "X": "225f3c1e9f2cd41f8ed10030c96a3fc1b6e66d52d4adceccc1e60ca6b5dea49e", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:48Z\", \"userID\": \"da0ce045997d3fd61c9528c885eba0aa@certivox.com\", \"salt\": \"e6178625bfa576e6\"}", "test_no": 162, "UT": "040bdee3b6b629f20e3e75796b1d7278b182bfb40a083facbb0a8145eb7d2d3ae61018d973cc7e4e44372538181d5bc1e760a9b225563e6ecff31f5bea933663cc", "MS2": "216dc18f9cfdd5523df6c9bb30313efdbb2e9167d9f510590800d67fcb97f614", "MS1": "23469f3ec11e8f7eff460058d1ba345a192ea729d6ba93f12dfb5c13f7dffe5b", "CLIENT_SECRET": "041ebf8b1b2964f70151382122bbb2b7105aa287b0628f1ceb08ab992b21b39049195a99fad7b14a20701bb2ae630bc35ff25f5870214ae8d2e955e81bda6b479c"}, {"SS1": "12d1af365bb97ff4f4429d1cc70e4395879b1a05eec2b61f0517c42c6b08241f02b85c8235be3bbd6f76282aad9eb0d77d8bd84b2acf90e38af683420f4a4f44145a1e2348b8fccda04b89776ac5931f8d2f1823cfb7de8f5c210a8ef5533811226971d5b1919462acc3b06dc00f399d52812a23ae9594d1047c7d4034a95eac", "SS2": "19a2b8f92fdb9dd81c4fcef366b5f0c56f6d6ff00e6a50bc15cdf3d4bec133f00cb19491e9d8b5e80148b04c0af7612065bb21d238e792b46c8b00a65aab0bdb1b1fd362bc4b5dbe95d9a151722009e0060609f99891e8e143d2ade06ea26f3f0cdafc164aeed742e699aca35a8ed6f7242bb2bc8573aadc1fcee8c0c3429da2", "DATE": 16574, "PIN2": 7477, "PIN1": 7478, "SERVER_SECRET": "09769598dd507f1c906abc1ec2db928b5b0a7aa5c5bec3088467e377e8d6602e0b29d7e89dd4a870583ab10f8ad35545e490854f6026f6890cd1e45ececd4aa0213b6d0f09265d5dd4a4a1f8b1983902d356e12b1b2e3e4be7b09480d22a247d1ed7326e5edeb862440e16be43d704fbc3aa6ac0f5476669f8f9c8f4c20a772c", "SEC": "041dab0571eea132d16206872d4070c347d3fbd8f3fe489e40a4ae25fb7abea4ab1408ed8e49529890415aa47a39f8c2d50bba3be8b9089858576f2cc4d39d0253", "TP2": "040463c046fe62fb4942da92d8952cc4e55b1681e493f079dc1a26830985219a9d1ea09625f7e57a49eecf6efffe0d6cd186518da16c6f89486378fde652d73118", "TP1": "041bbfe0f77ec475e456ac45a5ada39831206b0b3222fbc73e240cecb38843b23d1cbc11ae4b000b75a5f8dba810dfb146a039d9c851337d81d535cd16398bc74d", "CS1": "04227a58a1762e9e4c8a4f2373480abaee4de74b6482ad785fcabea6cbe9cebfb503472a6adbe086e4f26f1b2c81a7637894b18c9ad6cc0cd7da74e9da35205bdd", "CS2": "040f4cb69ac20b7babe0d6974a3506920b280b96ad715eee3c91fee63185b2b27f0dcdfd01dda83339c97ead30e35311dbe7229f139fa96f731210989b19eb04ad", "HASH_MPIN_ID_HEX": "7b66049ca9fb9dbadfde3c9435f7e0bfee91b5e9b6e7d9b20989fe835d10b661", "TIME_PERMIT": "0413aa5c83009c1a21a025b969d0150947c0b67962ccf2e144703fb57b25f0c101078a59780a75c649642f6c2bae96998445d6bf3040a1841b6004eb81c20abd69", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34385a222c2022757365724944223a20223063393938383537386430366561373934643932356338656335323763303936406365727469766f782e636f6d222c202273616c74223a202236636533663133333436666437366239227d", "TOKEN": "04047cf7613a760b59ada762267f4ebec8d74850ab518e816b6e51b1538a83f03d05ed7a7b0742ca7fdc5c19b95bf31770b8ac40225b2ebc66631e44c6c5557c7b", "U": "040f77790e1de5cf6ecfae4b65c90a4bd7308868229632551a0456059aceaf427809379925aa08bd73cfac06ac022b617eb552e73b74a372e208f0b96d6c7e3c9b", "SERVER_OUTPUT": -19, "V": "041418dcde5a2014d1461895045da0df00ed3d4a647eaf650846f83d51ad1df50d0c8f7afd6002d670c3a474b1494d1923c599681c1c16a71655489626a396a64f", "Y": "00c6161e47e9f01809826279526df7e9892a3f6bdcba847501e15e1e9de1a7ea", "X": "0cc555607ef2fb06c2088cd508669a4f8ded06c36ae399543688c7e8f7fed292", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:48Z\", \"userID\": \"0c9988578d06ea794d925c8ec527c096@certivox.com\", \"salt\": \"6ce3f13346fd76b9\"}", "test_no": 163, "UT": "04223695407c4c10eabf435ce7120937a223421461066390830df7faef8acdd96a0c330b9a0171522e066cdbe123be69c33acd77e32fc1a7a07f09b90fd1a33d25", "MS2": "15341dc68769aae6f0d1f3c809a9feeb5129b6030eb8432416e7045963eb1fd1", "MS1": "101760e3efbafbf93bf72cf9fd47be6b62cc6dad77f4a0e73b2bea6303f713c9", "CLIENT_SECRET": "040728d08bd59198ea434488e89e212435c3386d9cfabe16cc240c91de9de2a8f70fe4da9b20a18098f00a2f734f70e885301b91a6a6bfa392817bdca3fbc17b35"}, {"SS1": "01e675a8603bc95eecd5a1cba136f5bbeafb9cd675808c04e8e848e5fa79c8e6102dbdb7581eeb09b43be32046e257e67928e7cb148d0e03799fe00e3f071228129c87735780d8d1b2e11a5d4206f354f613047226e962e18f11049fcc2b23520de700bf8bf685788243f05171808447f2dd1a55545f21089a78938ad1baf497", "SS2": "19b02c33ca37036145fd1e2bfe3170c87cb375cb4397020f1cfb17d6a65db626128a937845cfd0ddaee796e0975d22a0369e6e92641b209b0a75968fa94eb8a319af6fdc3ebc723f273ca1e14b503b08fd0c9dd62ce835fb7f4f467c6cd1ad9108052b0135990aafcff4885a482c76cf53f03d22af4af88d4ada9fdb9693aa03", "DATE": 16574, "PIN2": 4699, "PIN1": 4700, "SERVER_SECRET": "1764e6e4b1a98864ff78f38daa01fa3cfcfb7625e3ebbe857c6abac88d53d54d21943ee3be5e7ab9b2330cf1c5f42e996dd0c59d67bf5a0959d61cc970cf1b7604d86d1d1d040399273d5656507651a634647c86212fedac81629443abe636db17bafc94e24d0799c1eff7041b3896c1ab47beefd8c4f59f0b7129626cf0e1f1", "SEC": "040667534c08fb457b89174574735fffd99177c0f91785de90bf2e24c73ea60c0f01236d832c03b7ac87416afd91ea55a1c5a4ffdf5d6045432d4f2c72afdf1283", "TP2": "040108cfbc93006fcb87e428f2ed553d0a43fd3b614316152772324f0b194d1c011ea1f3a68886cb4d21b12ef657f86945df0362d2d713177cee39778951bb3704", "TP1": "040181f2dc11b2c6d61cde2366f2cda9fddc77bd43066f309ee73edd2e62bfff4e18a1a9089221f6b63dacc9c5f48b590fdec26f7a36c63958c694fabacd99e30f", "CS1": "040cbfe51dfec89afc25ac7d0a5f4da3c340d0e1048ffa9977545936c391aafad50a32d2e1ac6a040ff9f05c96838960b3e8c6c7de8a732aadbcf09230b5fe5937", "CS2": "04201363df997cb92cf2d040e2eddf2bd4ebaa4f2c1f52b7f8b2f5d975b8bfe89f17579ed211e9dc6550e1b9cd9098522f3e553110b306326fbedab0ffb665e24c", "HASH_MPIN_ID_HEX": "3b628ead6bf4931ceb296f2073c9c84edebbc870c3a020a4aa0284f197bfc7e2", "TIME_PERMIT": "0402a3ccd161490fd4c3f94cae81f9248f30e5f74e4fa20a885449c7e209f78454073962d195945b234102b652d31aa0a312556b3fbd9b51039f2a46b635592380", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34385a222c2022757365724944223a20223863396163366334626464316663373765336430386637303230353263393835406365727469766f782e636f6d222c202273616c74223a202266346334306266643639393230616661227d", "TOKEN": "040310cbda0f7b8f6e43855a254649cd1d527c6f0e27ebdde167f28bad357617330fe969683e5a7669a2ce4a8dd02e9db13f9d6ae0f9e497e59b29a381a6224a43", "U": "0415e3e9aef31fd4d79aa4d8a846c93aca4e2ad1a4fdbc340e2c4325eb4dc78fb90c1a6aacb4c0e7b9643197e3b551da40437e208180cb1acb511bec5f0fa35eb5", "SERVER_OUTPUT": -19, "V": "040fd01ce192f0d95a07f48d0d7f01dee8c39777e83ef39f16309fafaa05132c960cf325feddec04c522f9a2fd108e74153a63f82d5bbe507a8ba0147a16dd095e", "Y": "22cfa2e5ecbac04fcf73c968f81b3a3144fe640c713f10e7a5f9935d6344db6f", "X": "0272ad152379c8d274876e79b49dbe7a3d649f9e7eda9f9975279e80f50dbaaf", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:48Z\", \"userID\": \"8c9ac6c4bdd1fc77e3d08f702052c985@certivox.com\", \"salt\": \"f4c40bfd69920afa\"}", "test_no": 164, "UT": "0410de158504fc8657be6b441fdf2fdf007d042ce2398a6a64b23154093d00f3700a1fc768dfc4d838b527dd28bca9ee84c0170c5350acec07da24fc3e759b0f58", "MS2": "12e174dbb83093aca891ce13d328af02c087c4ac5fb775e38b890794a47f494a", "MS1": "1b4239f65c4bc694e04f5ff48a45a7042ecd2046c15b1d6eff4c628fd0444bf7", "CLIENT_SECRET": "041a7d3c06189988c3b7f3971bffe1fa735d3677b106d36ed3abd1148b839a94af19411a427849e24368059399f6500b604bad06575d3b842e007d289a1b67d119"}, {"SS1": "1b967bb7c3407e262760f8dea3b7dea643d606f25514b44de6ac0836b95e2e1d17efaf3b6d63d6b7d445196249080c6e3406c76d0f0c51b3a35f1308b177dc341977094ea71e05ddfac6846cb59d048dd39754dcaaf2b5434b13be63d29757d61c4b7d78aebc9b26ea7b5f06391b42eb3edaa7194f2296a5221911fb6eed15fd", "SS2": "17f6804d258d5cd729c69a6f5ed1d44fd05f17dd58fdecfe963967bc8584f650236c00152c271a4106b961df7bc7a2a528be8acf9b855d2d7500601155db83c70ced414bb4cd639c6abf99cf454f5ea50b507fcd45a7ce90248ea6d433b4f3260df6cf17c6fd29475229dd2fdcb26f55af9120dd525d184076b391863970adcd", "DATE": 16574, "PIN2": 563, "PIN1": 564, "SERVER_SECRET": "18a8617e44ae9de479239019107c115997ec1668e2a69ebe0bb44c7bfa0c7a0e0c98162af8190efda7d2f46336d85436d18ef017dbbbe824b68ddbb5395e92de0f295656c157b6fb4f89b44f5c367e68920abffb06aa4490aeca08aa25deb7a71554db841f8f08c2cdf8a35e7de4f8aa23991c16ede108738ae4ffac8ce9a70f", "SEC": "0412d75e48cf950009e61024b13b80e515413429a11a5b0efff61af0358a5e580014f826e216d73be0cca0cf044ec37011cce68599d104a7d6bd132b6b5e5f05c8", "TP2": "0404379966837fec9dde4307b1ec131be7fda5a80f901c8a6e5c308eb0ce91dbc7169f0f83627fd76d9582ddb541baee18f272c6692d956d21a9c64a972ff432e8", "TP1": "04020b57b63f8620191b1ed5284044375dff5bddb3095d5d6e2fa6d41baf714dda0d02d5af432f121a61b8529b6d532318d8fc35a9dc37047aad9eb15186a0395a", "CS1": "0409784e60841a489ca8ede30ea060db059963ebbc4984f7d437e6f6c5e8b183782115a93ba4533653ad89aec034a1be0a21af5c66ccfc0f2b27f113b089c1e777", "CS2": "040c851109eda626c031ea49be0285530bb7c16aea1e50f0376378d1e3b8d4acb314b6c15aad19e9621804b01459219f51f057bba1ce1f344104955c01426b88f7", "HASH_MPIN_ID_HEX": "d121a44d575716c965a0dd5bbe12408fec3729ffef06024760a5d06ddce20d32", "TIME_PERMIT": "0416cedd202dcc7d7feebaa28b09784e15d094bb73b078e693d6c6ce891636eecd0fe63c4c83ff3e92ff35baf839f5234dc5600ee3a29910d8b5c7336b480822e5", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34385a222c2022757365724944223a20223361613162633839306361343135356565636533656331643165393233336132406365727469766f782e636f6d222c202273616c74223a202261353938316639336532323333336136227d", "TOKEN": "042256b70f051ce0b60a848d2389ce7d4288f1f3d8b3fc1bd2adfdaee66ccbd70c0e6117528c069818f8c3968b0050ef4bccd2082b454ba5dd2a2c47f5a8f90cc4", "U": "0407715d830442781b39956b152fae89251d07590ef16798262e7a8da7b578265516a3218d697dd43df57832bc54907c74d940f1f7b72ef1f24549c3ac7bfc0ab3", "SERVER_OUTPUT": -19, "V": "040ec0b41653878ca5733535aff0c4ca8afda66d2891cfd5d3ba65a6df5d02b48506e3dcf4b28610f287df5ff74fbd70bc4393c2e0fb033ad0e81aeb5f3363ec48", "Y": "13a973f9ea71979044503f6ae13f582b04f67bdd216b1868b08df598a564fb3f", "X": "144150a542ca8230d105d613836fa7e8192706bf5f6bf1406d3296773cc76b85", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:48Z\", \"userID\": \"3aa1bc890ca4155eece3ec1d1e9233a2@certivox.com\", \"salt\": \"a5981f93e22333a6\"}", "test_no": 165, "UT": "041d02ab55e8a2b776676217b48ca0ee92634608e5a52968ef98c6118d93a7aa9710b05f4db35934bd42aa0e63f23df86f7a01db9f988c67f7a59d500cf349cc7d", "MS2": "114ace52798862b8825ddfd8f90fd69ef30c87c70e7c193a74e7a37d1af25d7a", "MS1": "1e1628db148d5ab75e41cdd4b8e6c72cb86d0a0042fcdf16b58b9d503505616d", "CLIENT_SECRET": "0400cd1751bd947eaea5a332cb128e2c79885c42b97e702b1b26d9394a992a76f40e2b4e6071bea8c9c09db05d548e34abd931d935e90d84551f839b39e59d0c1b"}, {"SS1": "13f95cc4eb285a26fe920fdd9e035df43548115f9f2dfea76bd01b0bd8dc241e208f355c1158ca46334c2d11767e7dfb3c0e5d4b38a9f74f7aedbd3b4b1ebd7b1fd7eae73da5a170c1e6aa121928393bf88e1be0a6bdd15a940e89955a32b0d109a225716869ce923ae7886ca1031bdc15eec1e313b90beff25776ff52e88de0", "SS2": "0ca6eaaf68d85586ef4efa1d2edd97d9b6ad61e69fe263b2d201220c1a7fe4fe04f27e5996692fed7729d48e00c78f54d82317781197560673e8df14c8de2c62019db735badc5aa95e50872f2c78bf273d539808d3f94082175f1d1ff971bcb70cc1ae5e10215aa4bd0074be33257c14e1d2f4c8ff24c2371192308c6a8e1ce5", "DATE": 16574, "PIN2": 47, "PIN1": 48, "SERVER_SECRET": "20e9c3d2db7b3677a6ae198a4125c1ad047cd3db012ada5973bd351ccfd663c9161865800146f52bc008e398811f5173952963f016b28db419b0b3e49acb4f8711eaf768e46a555f6b3705c99fa849d5d0208019a5ca75824587e879ba1d1af20c7f1f8577bebd99d732f45f9c8de359452389bb90ff4420ac8b137cb6073365", "SEC": "04006417a9ed5d4b617550a27647d4f2482c4a41e0570ba0ecbf02a26653082d9b13c047cf17432367163777d5de720a1b3de85f98258486b3ccc6b3e4b262bff5", "TP2": "0405bec87f1df9fa8acb23b40903e9311067b605548702d819047255fa9a6bbf4f1118af06f921df32edc9c1b185415fb0239b06f65957210cb840232b7971912d", "TP1": "040f940b4b85cf6daaa1fae16006d4b28aa303935fee27944d1fcb2820d99bcdad1761a25456659b2af4b12cc4c34b25df445f22ee19e72fd92598bbb027f96567", "CS1": "0403a130ea540b58d3698336eff3919986f12187e782bda8b5fe1600236645b49019210c97dddb6fe1e197c312160d90d905759926cefae6fb60619b449c57250e", "CS2": "0409f62764111006c33f2ff8caa3440c2223c560af8c2e13f7fb84077ee2f98ba41a185a150f3ce042215d4e902c65006790c76a5fd82e22c3f7dd16f4296a9f3e", "HASH_MPIN_ID_HEX": "210902e62825ca91d24fdf03e4895a0423b0b6981d1f57f54f0e9466d000c277", "TIME_PERMIT": "0421d2c33d010332a4190402138216e2470a9e98640c1a76d323f66d718372c28e01941ec7b93ad5572fd2786eafdc23856d9fd1782d1be6f946666127072ebff6", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34385a222c2022757365724944223a20226364303434633135303262393139363862633735323835646265376433303435406365727469766f782e636f6d222c202273616c74223a202266656263353665333562383931643434227d", "TOKEN": "0409059a2f15929e60502460d33d0018d1466a5e0e88e667a0ecc74688d4da6c0f1ce0b602721463703947a66ef119d868a694711ac91dd56434a9fa9fe6e56062", "U": "041229ff7c76be34cb90d9aca39eeb811afbc7a080d18e65f5fb0509b8b39ef1741df72f2fc859e71c5aba963acefbb24e9ab9e221216eb9a6f892fcb24389d62f", "SERVER_OUTPUT": -19, "V": "04196f334d9701d87304bd6c5971163a2acf74044c56c565b42853b2bb94d034e91e43301829320162778dc2440104a5c6ac08dd60ca8bc7387950f740eb05865c", "Y": "000bb926b714750e4ac5339d24a4430c6db53c45a3976e7cec5000796dd562ba", "X": "14c40ae8ed5571797123cb3d1cd6cb7982051a996cf65bc73927c18af3fdba49", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:48Z\", \"userID\": \"cd044c1502b91968bc75285dbe7d3045@certivox.com\", \"salt\": \"febc56e35b891d44\"}", "test_no": 166, "UT": "040f119a653f68be155e067b9eaf613e84cd0bf3fe29917652123674fae77a036d206db33c37b031a094f14b2b7ff7c75d4d8ad3470624e22f53f2a4e55ed9f8a4", "MS2": "194d1d40746991c4d9c9739ff20a69c15153c0ee6600eb76886b22e8d000904d", "MS1": "0b0a1305989a59d650dae9e4dcb114a64f09a40eb95460c3f86453acdb23a15c", "CLIENT_SECRET": "0418e98000a12a7bd4aa9c9b0b14a7c9087746a98b86ce703b49e720f3ba24d81910b122e75e5b6d1f17a90aad0228b0e63feb26f60b480de2356ce613b0781189"}, {"SS1": "0834316a5e1492cd833a5fe157384064967e1ede860d36ce73d6c7660f722197213deb8bd4e4cebbf67fd99a25aa659cafdae71e3e8f13c92b92608a4e3504070a8a1c66b168472d0ccbdf6c14228556ad9eeabdf8c0cd15f9854ff396297ac101f8bca43a9f0b16d900ef865c845b1c6f9d2dfa4b3a46b9a2f2ee8d28d11e74", "SS2": "17ae6aa631f5791edeccb328027fe13aba0c06538d2022c0f5573f71f2ab3dbc1658b53f506fb46a8305a7ae9298ca2fa11cfc15b510a5808d57baabeda3fbcc1601f833b3f2f2fd850428f2533e6827db987292449cbde7b830c9c26e7b68dc12a9504f5a0bba2fe19a29fbaf9695787acbf3d795c63eb810c18a1f7cda4863", "DATE": 16574, "PIN2": 1980, "PIN1": 1981, "SERVER_SECRET": "0f1135d12604682c5463f3ade13ca73316f6d034f39e29ba5d5eb2d833c0ec681da0a01a5bddd58b51e6fadaab5d33a7d23a83f2e7d4acad7703ace28f6d861800be73095f2af0f7904bc047c3672d1e99e8de315ff8df4fe364e4f9fe6f0d2e0f4f99a61a831fa109bb83a86e5364fe0cf0f5c52bca20117d19aaea75d362db", "SEC": "040832cf92ca5bac7166b111192f4e51446f64e7a547ae969396c0a168d4020bd90bcbc938594fb02d6a0ee294f82544da79a6de6b4699b464b2ec8dce68aae6d2", "TP2": "0400f16f4c9b4db1c6e0eee90b0d080a007ecf67126bd4db39cf65e8db04141d5f234d3cb0f8016c7ca915c43f11e0998b4d637b178fb4b8e7cefba928f9fb2a09", "TP1": "041e9c29ba076e700a6dc8f03206761d02f5e2146adffe8946d0ec42d0f4c208951bda0db753f4e7d3a77967be8d420621a0c76adf09812721f1038c4b4c9eb4d1", "CS1": "0405cd2775cae8238f3027b63dd2f0b618149319f2b23d4b5ccd57f92cfff56f131c2124bf7d3b45a0b43a304128708d2b8c3f7bbf150c4f130b95c5396efaeed5", "CS2": "0418cf3db62b492fc2cb36e047f69c741a01b29e32ff1d76ed9f5a54e0fa8916741f83a04371328d637da4b98450532093d23e295945f57ca2d0604fddbe83160c", "HASH_MPIN_ID_HEX": "906d724d060a2c03a5cc0de91e66d55a544572f7c51ea1e9fa10d9b81bac77e2", "TIME_PERMIT": "04199d687e47988d2e5d98223872511f292bb361d965524bf2b3a441e95b6687d61817caaa4c863b7ce3ff5691121c09044e1668bfb12c82e1727a4df02c92ed88", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34395a222c2022757365724944223a20223037633865666539663963656634636331313233663063393432313461353761406365727469766f782e636f6d222c202273616c74223a202266316333326166303966353663653865227d", "TOKEN": "042300a58c8c1cf95aefbaae861400c30d93ab9e8a915370a4950b41775772175f08279496bc4581b266e09e594fa3801dc187c2451547abfc18fd94e88fdeb0c0", "U": "04173c6ea97002c35ef51b15d3716551f789b26b10f51891d600765193303524941be606cd459162ba405ed3464b16952a8ec0a88a645f7d22cf671a8da726c2aa", "SERVER_OUTPUT": -19, "V": "0416bf5e423dd60fb98752e76490031d3a7cb521d46312156d7f07ec857ecdda422061d00e0b5fc77f3001e56217e00620c95a18a459908805eac546be4ed48ad3", "Y": "00372e8316d871f281b1ad4fa9521e71ae97c0d1fc71ea5d527422fb4adbcced", "X": "12a71c54ac67b9df1d9734495df174518603d4c86883d5d08f9bde3f4a6a236a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:49Z\", \"userID\": \"07c8efe9f9cef4cc1123f0c94214a57a@certivox.com\", \"salt\": \"f1c32af09f56ce8e\"}", "test_no": 167, "UT": "040d01fff2949780341920d7d38f6c54c61525cb16ad059a87fdac61a219447a3123a71162f8e8ae98802e53331fa19d397f7c1621e81dcbc2b882d78cb0ee0893", "MS2": "026c1ab95af931291cd266c9ba4c3733f03e140ef7d935ecd04fa6b2f96e65d7", "MS1": "1b77bd436a5d36e0928511c93cc5e975c46e4b5a42c83e1c201287f8dff5d21d", "CLIENT_SECRET": "041f052f47c465edb3a76429778328de81d07da7024d474fdeb2e3440f8bcaaed11b8667ce63a78f64fe4fd523b92a2149ce2b79000ba371ed72463885ab52e92b"}, {"SS1": "0f57968c5629afbd68b2864b8d1283eeaa986e790c72417bc881a9286c2fac74220f301637aba5cc7cc2eab66d3d4c5122f576f1fd34b396d5f55deae966a5e2012ff3203920a5f96124bf4fa28b02b2392623c2c9f6325fdd3e556c68de538b1f22008739ed25079a2ccbfaa0ff06fb1bafa68559a594f59d661ea21a1598cc", "SS2": "1a0c6300c88e583ea92a98b868021d09c75becf902895da26c70164a7a3cec5911de34aaefe4b7450cb64a90f5a06ba668a64264c077c84881a9339563e2c9410eab6529f9c6f667bfc6ede381e524bedd7bbbc0e5c380cc4d55e06f0c353cdf211981a2923114c406708de4a1b199f2b2f416857e829f8381422d790422a9e5", "DATE": 16574, "PIN2": 5463, "PIN1": 5464, "SERVER_SECRET": "0dc75be4b60d962e30721562d8a154dbbf0d7142fcd9d3bcf68924c32314af6720762db37ac46f0eae41469db066599c36c2badce2cab02ea895b7dd86a9bec2033e48ce52c145af99cb07ba185b44c8d88c08018fcf6f7b91ec29c9b567c24e202f860ae6fb874d2228fca180606b80e8c32cf5afdc47ac4c899f49a0ba02a3", "SEC": "0420c4b06e86abe23bb26d3aa4e8bbcda8912eb4b08b2a6815bef764fc8ebf297f07e8a5b6868dbb6ac8a156908948b47b0e1b6439a6756954f58761ffd711bbba", "TP2": "04010aa6881bb1af4a8e8081de6fd755aea4a91850b3602efdaef127f54bf355a720e156ead088efa698e3d705631ae17363bf9ad8823bdd15b92771a4c4a54b0d", "TP1": "0402fc3ff27da5cf1fca2bfd0225028d5d2c8b1911e4d88db76080272ed5ccbb521a822f1584cf943cd422ab807d84a7cdb74b3428d1aab09efe6a12283982af67", "CS1": "040dcb6357e10bc28fb46fdb0445ed89b95c8b56ba3c60df34539885a17dc33d8c04031766221e47e664d89981115e2c1e860ac3d31e4ce74651518c0c93037929", "CS2": "04201b8fde9ad030bdf031fb05dd91256725b5b202b0373290fac5953ea46fb95306b0df36b3579152cd624cc482a174554a637369f0f78bd900ac6a32c0b4b291", "HASH_MPIN_ID_HEX": "6b98500e9d5d544e09ad19d19726a8398c00e55089fd566c5bf9dd16a2a419be", "TIME_PERMIT": "041b4f7a84ab1104051bf3b0cc701630be66a6b94b9844c013fc1db0d522788ed6015ea6fa34d319f3d6cd59bfe5a5d9028138ca0a8c9b4b7e795ab473564cef1b", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34395a222c2022757365724944223a20226633623265366361386665633762616664643736623530396363326531666239406365727469766f782e636f6d222c202273616c74223a202235323563316464636235376536333832227d", "TOKEN": "0400fe192bd5fdc53a3ff9038e3e3f25a97bf94c889685779a01d93c3890cf99f01d48f977dee156853dda65b489f4dc2930395890c775a25d7feed52cd896fedd", "U": "041ba8da65958fb69b25ed5794c1b55e35a01697aad127dce5829a9d3e66020b001e8e625472ac3a3f7dc78ac88410d746905aa2cae9c1dbb0f58fb71f82b2fdb7", "SERVER_OUTPUT": -19, "V": "04060db9e3396e90367b7b0061c6547d50471dddcab624173686ef5719bc699f540272de6b069f77c5606f9d37f988a6a19f71a5876247a82a5814eac27e21e94d", "Y": "10661a67427b01789a83f58eefc2948af1e9b6ca67ef30e614760ec593b97fa3", "X": "0ade379c47fe2ccc777de9acad3c4077b4c219861cbe1d4568039afb1db8e14a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:49Z\", \"userID\": \"f3b2e6ca8fec7bafdd76b509cc2e1fb9@certivox.com\", \"salt\": \"525c1ddcb57e6382\"}", "test_no": 168, "UT": "041a096f39e98fafdf6b873c14f9bfedf72707b3bc954318b5cac3a95e9ca8fd3712a3a82f4db866efb15fb970855e4008bc629e8f9b0049378704460129d77ee0", "MS2": "194063f1a908a10967555872bf618f228d9b31c66d7f21bbcdfd0ce7b53a0ceb", "MS1": "0b93e11adcccec87eb160d100129d9e327a2ce3f98f9727b3e5782deed0bdf9a", "CLIENT_SECRET": "0423a0c63817ecec2938f3312eae23582a221eb6af089257560b88f387a6077e1f012ef346173968a173fb5942c25557808d7177afed7f5d3f456e956b1af5f423"}, {"SS1": "131203736e865ab5352652e47095b0061698bb350a9c98f00573c181e1834c6a1997aaab8a0ad8e427e89f9d548b6949f8a8bfb900b71d18673ef5525e34de531ee6330f81bcb3eedc5382e6efca6afabb605d00f8aff259010415de8e42128d1524a518b480508512c039d4c0d4af02f6209bd449826ed17df6f36325ad67de", "SS2": "1eee65e99e46452e21160cc7256f67abb1393d05f3bb45c48893dcb41137f909210e77ac81894ed4ed751cbef266809c505053e6992cf393106ec9656cacb5cc172ddd116cc42cc911b8531fef4fdc1c965f01808afb6a0c4bdf6ca03e85c8ca0c3f64a25e240e60e454fdf373a5df77052276ddda486f3758f855325ec1f777", "DATE": 16574, "PIN2": 4772, "PIN1": 4773, "SERVER_SECRET": "1fd6119ee3e35e63845e36696681e5914fbb9e88e3c9875ce31039a8cd1dae220ee8bb6267ff7632eaf66156be0ad8ceff8df559425877c958ee419c218f41730e2033c6d42eadbef863facac335d8caf8163c28e193e872bcb97466e79f79480672ebee9bfaf27e2de8aceb8588aabf2e00fc6ce2b4344f47b709b02c216d3b", "SEC": "040748b41097378da39a146d7b98ecbc155a833ef6bb9e3297d253983b490a73691452327e844a07e005dbcfff58c525803f14063abe58a7fd5de0f0d02e7b1de8", "TP2": "04168a99674d74b8d74850398a217de087c1513889498492c4f41d362175beceef0eefb9a0c430bc70cf1af112a636feee052eed162301437988c8e4957fa1d88b", "TP1": "04165096eba53d31ec8f9b2bf5882fcc696eb52db177232b0a52d892abbf03220922c0eaa2777068de63f2233fe9fa1a2a7ad2693c5c67f020ad231dd5d65d91de", "CS1": "04179f58b71fe3c40b5fa383e4dc610b4b2c0f255d51b1ad869645bd97aeff930005cfd0d3252c95e590c300effa793d1160a9bafc533d9643d0339e1359f51da1", "CS2": "0412d40b33f6a4399aec8512df8c630137cbf7036758db3717baa8c25e8b8698021e1bfec3d989acea4f2d669dd220442e41917dc6442feeec4e0980f4a8b2ca42", "HASH_MPIN_ID_HEX": "016b38d81dc2431a94147838d8fb5bafeff249f30498afe293ebea0d714cf62a", "TIME_PERMIT": "04139839132be04d4a13295af00c348da81a3d6353c382120f18f0da37c1eba0330d215c751855ec5f5ad69bfd60169f07361d0baf2c17b57904d61acbba3e6e39", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34395a222c2022757365724944223a20226262616431346636613338613435303733643535653339623135623563343636406365727469766f782e636f6d222c202273616c74223a202230353265343936393232613630656661227d", "TOKEN": "0423220700caabca27eade7b0c1544863ac7f8d94f3d62c39ddb3c50ad722e70ae04dfefc3eed65303d5d2ac44eb2f0ee7a34e61d28445ffe3831ca94349037116", "U": "041e892139d76329e4d436dde4a96e7c14f59f9067e3e7898fb60d704ad11992790269dd9d29f414bef224d32484b7fa571fb8735dc0bbf7d60de89d8eb75c962c", "SERVER_OUTPUT": -19, "V": "04052e1eda453248c3ab488c931f7c06d28aebeb72aaf24f4d3e8071f91cfc83c9178df5b46a876db5889d4d96787e4a4bc28b8c40217de3aa79c26e54a793ac82", "Y": "143613487c552624103455370de0f6150a8b554a20f4c4b09f56046f86f49aeb", "X": "073f216ee06d896c76fa22f96aec0c0a059508a41d000ff4cbb3264dab9f5b8f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:49Z\", \"userID\": \"bbad14f6a38a45073d55e39b15b5c466@certivox.com\", \"salt\": \"052e496922a60efa\"}", "test_no": 169, "UT": "041de93744beafa9f52fa1d6531dc6c86534e2c151c1ca3a49ee52b2af76e88ee015b1f5d37f9c090928101f996b69fea65e64fd64bb688bf8989a5ee058b9cfd5", "MS2": "1059952e07ca70e38304f254907f70595d1219faf520f7aa754b06a7517bf8ba", "MS1": "0f3e319234af1d6a6a09589888adbb2ab7092cb6ad68f4082eb8b1518b217cda", "CLIENT_SECRET": "04054b6611ad00c92a5c164dc9b2926edb87b91fffe2a0f1832d9c2ae9233fdaf81c7cb7d74fa09239fd127da809678272e2927db0490cb7a26b014b9c6ca2065e"}, {"SS1": "0964712306458d2f4ea53df2d3e96f04bb2bd4183629665dbde4e23273cd58b71e7197136e42468e75113259c8edd85df5dd6436d299a04fcc337a6bff9bc94d0c11b67d6c09d209e4b53fc684e3de9285daac7959d908ce049b6c00638f62f51ead9022d4a2a0bc5afdc7ee17051b884bea4dcc541796bf7a7ef053976c81ad", "SS2": "0f1dc99e7feae2382ecd90639b364838b29c73e10b6144be7c364f18029c16f712a0a7ae38fd32c31fbad0fe2cc838d0dbb2d97091fba2ccdbdb0191ad8c4fa812c0f6e5b07332e6f402bb5124adc8910cd012465eec8f3baded0bac26ad135006c375a56273343dd9d07611badbcde901b0b7d57146002cf3917020e786d78e", "DATE": 16574, "PIN2": 340, "PIN1": 341, "SERVER_SECRET": "138843b6378041cdc39f9a828d5298ce397facc1be6a9ddb27941d5b415435e51c57f858ea38b14603db6a9f5941b6997eaf672d0000970170de5f5d6da4218211f1b1953f6536190c7450f13068de5541a167f12b044dac6347ea643c1ec184014dcf3555662d9ef1a2166e048738e4e1a263a09412bf4c9e0b99585b72414d", "SEC": "04112765dfd98628675a09eab6cfb8fb8583f25676a4db9121afa5e0e159895cb40412b8c5ef86557bfb88c8a8b41ef7ac2609e03911c957e5b008c216338d5b7a", "TP2": "04014bcbdb769da17c0e780e5dd0feeb7b3b6280136ec32f0123e97f30b2d170dd1f0466692ca37c1685d6d779996c9021e7f95c6ac2453ed32b2a8c624e89324e", "TP1": "04037ae5e1b5750fe83d72c98f81d4dedabbfc5b2a261cf9996bb1a22641a50fd50b812f9107b7a703849ba63becef90ba19d6131dc08714c0c6713d5e393a8ba1", "CS1": "0404c266d30fe2c90c394808608e36099e7f14029b37a817cbfac13a87957b594c1bd4f914c2d16dbdf20b9f8a1f56c717cd840c147024c7987ef4091860ce802d", "CS2": "041341ab0e71290fde2c38f5a8ae114fab7391a9da1c8e2b14b0721e4834cb30b423605d7744fbc141a8c388f1066ac5ef371ef27de62e3f833b1f5971940a6a42", "HASH_MPIN_ID_HEX": "dc6c6b5b81d74bbbdaf6516fcb4623d4e833a3d635474a1718f0e10996bb7fbf", "TIME_PERMIT": "04009b1c38961919551f7e396e9b48788f30cc23665b8b18eff595f304ad415e0c2362bb5e58fcde3f292e7b1303219f13d37a31f94474aa675ec5beb4233d6e0e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34395a222c2022757365724944223a20223866323037376564343735653938616334323237316362663332393935343332406365727469766f782e636f6d222c202273616c74223a202234633966656136663134306637343663227d", "TOKEN": "0403c28d3f7b036b12ea15300d5285eed041f488cbac03845fae652e7d305c135d0816a67be0e0cd009ca3cf6242024ac4ed39bfee7123334d4f9ca78ad63e8320", "U": "041f3249cf98e979853de84618a2c7bf3bed64490424fd6c7fcb8afdff8b34f4dc1319f4e5452b4a17007e64e745f8c8358b7c4506b7e91387ad9ff04ea188eafc", "SERVER_OUTPUT": -19, "V": "040b20b440298ddf615c47576602fdce5b4efd587e9947793ffb02124f4c59075108a7a0dbd4e33c97786d957aa8a6b83ea2b05082f8debc91f3fddfbf0c411c4a", "Y": "0ab18100ad5d90186181170b2846c7e545089f1af6b4a435899eabb3d70f2b4b", "X": "024795927cdb21985c089577d8252add23cc29d6e695d49bcac7647454cf6156", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:49Z\", \"userID\": \"8f2077ed475e98ac42271cbf32995432@certivox.com\", \"salt\": \"4c9fea6f140f746c\"}", "test_no": 170, "UT": "040db845655a53b09324eaeab0d2e4e90f31451273b5226899439a6a3142cfa78c0489c9d1ab51eb826645ee17f3a4120737094764c4d3880b85f98e2d0c45927c", "MS2": "1ac22fb0d9068b97b7c467fe45751386f418d97fe2df1c8d77f60c84ec377c22", "MS1": "077c0ccd379c73bea7e674cd3f9dd59c88524ff4bb1b2692dacd488f2fe0fe30", "CLIENT_SECRET": "0407524545ae9652260a817f341001ae0c2cd07d2162ba3700f74d8f6cb32d69811967e3b95f70cc70c0d5b025484eddf9644d663434ee6006cf696e1440a08d93"}, {"SS1": "09d1386b2ce314acaab109718e0e7397ba76cfe07a32b31a5805a37cee5ab6262357d9c1eecc6c0d5ff752d27b1884c29046756d40982f1ac929ba8a77228816122f4aa1d41a196f6a4563cf90ef65497a4481e26d2b3702c39aff9b94fd81cb12aa900c83fed623bb591ed3e2a26bd98196ac448e62cde3508763cfea80c133", "SS2": "20b6723d7375fcd4494dbdf9e538a9e79a329d4ffe8aabe40d9cf506db6a496b014dc8e0c1457a6259971957cf1fce52e1a9b5a1446e00775f48f1556d5385870efd65432b5658681beafc6a881e930856232c965aed12fad25e6d6520f4d94407e8c63598c0c9388d1d415c41984355ac92f15ec2aa1a570546978a208c005e", "DATE": 16574, "PIN2": 4521, "PIN1": 4522, "SERVER_SECRET": "17514f2d574ecfb5c94168c460cbdb9e95467d6967fc18f3e8912949a8de0eaa20f800e79196a32b180a7afe4d70526206b15d7badc934e8837469237edeb2360cefa9befdf05c80ac1134899fef610adace6474c68d156af6f96552ce7c34420e554de877afff47b446e39fcd45033c16502c87f28893cd41a4f55510a4c8a9", "SEC": "041cc9cc832361c42ee871cd59ee740f5ee267715b690540c69dd78c786f68b9281bcfc8a21aee8e9704e330cf9e9dc777f299642fa9b940e4d6134e5bb3788ce4", "TP2": "040ed3833dfe56c2f100c2b12d2ba7dc28ee27e2c302c73f3eca5fe9fe17a9fba315187de752402cdd8bb713cd8a192405a6d10bab646cfc8d090036e1b72a3014", "TP1": "041e3780f2338d8f89bae52dc22dda1b52666a4752c3588f4b40613d8a894fdc0f163513a0037bdab90d22bd8795dc7e4472543dcf63caff31baffe517bb2ae3a4", "CS1": "041008e696cf7717a3a8174743a4438ec620b87a599ef082d9fd45ba6df7fbade02191f18a18f5b9c305768953a073af30ca988157c9b38c706c9d0641a15c561b", "CS2": "04107f958bcfcf5d8632185d1566fcebd068d1a95415084c47a9ee83c19a54a2712337989116a161ea49f56017fbf836c1ef130e71fa59a324987921f2eeecf8cb", "HASH_MPIN_ID_HEX": "f37b5498a5e321581fa924a594a81b151a1f80ad03947954ed6d8a8d05c23d39", "TIME_PERMIT": "040c4cbd1a8bfb6d9224687027bd358e2396d73729f8f47a0a39774176da4dff031ce34df98205e9515ac2d1740a8f5274375c37bf39f98927c514607b85329056", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34395a222c2022757365724944223a20223435316636336566333361653830613265653432633061303031383536363433406365727469766f782e636f6d222c202273616c74223a202238343666653338663137326264373639227d", "TOKEN": "04148a9b1f94eacda5b416d09be945f0bf957f9ff326449f11d11f66502d21409a1b90f861a93514a9d9223ff0eee6dcd3614215b04f1b8e598aafc012675782fe", "U": "040c03a41d14abea397fb17dd24e4aa035b8c36efad8763098f07289b7daf044ef08a5a69c07b0bfbb30a8eea51071dfb20cc968a7ead3c80c30686a1e60f21d83", "SERVER_OUTPUT": -19, "V": "0418073cb1570edd72490bb47b2e0335ce3694e42e130a417cd5786d413def24d7185950e98b7cacd30337cf42c7477ff1cc08402c19c6ed8130dc83f7120d30c0", "Y": "1e65251b58656528266d4d90be082575fb10fd9ecf579127fd8bc6f2542fd6de", "X": "1a42175ce5288fe46443aab38ba25eb0996c39e3f159bed59599e086993c09df", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:49Z\", \"userID\": \"451f63ef33ae80a2ee42c0a001856643@certivox.com\", \"salt\": \"846fe38f172bd769\"}", "test_no": 171, "UT": "041518849dc6b3263df942bbfd42c9464e907f369dae22fdc617c68431d82158c11064259e06d701aff4c26b97bf9dd0712a2b65348fe3c40114bba9d65d0421da", "MS2": "0e56f14984ca1197b1afc938d5a4dd1e85b910489b4c417f4e8fc472f2030455", "MS1": "13fc7595cbc9c659b88a32fce8d3958326cc77708c3905797ce5d77bc41bd9ed", "CLIENT_SECRET": "0402f8aa8c1b2670c0268bdcc96746477bd571e277e1953cdf35dc1c984c581910184f5dd04694a24c3fd7178134ad92b682cd7a42c4d3c21b09982ca8a8334374"}, {"SS1": "23f95fc87b1fe5e195627580566399bb8940be8a20260cc34ccf6ace6092d80c07da62370586ae739ec3893a85176e5cb705d9029f23cc052ebeba12582d1a4716cf405a5fb6cc6d3391a9fdf380d7c3ffb76f7583943cbc30989e206c77f34a04f608748350b2430d186c66a2ea03402ae72724f87c8df5c384e4f8f285866e", "SS2": "067188af2826cecc33ab16153675e2549e6f9bc9052ecaa958ed9d3d5f716bad2018f06175c056879e1eae3b7186d9075834416757ed8c8ddd362f36783d4a5c07259678f7ff7774e735b0f0cb27b4cad168b67e07f44a379c73d91305114b3e18712b20315f55ebafc4f7ffa74d012f8a8cd6186a313d7fd1c8ac85004e8acf", "DATE": 16574, "PIN2": 8725, "PIN1": 8726, "SERVER_SECRET": "21f81017df53b438a30866145b6bc62a341b26f71f9062ef2857eb790822abb42115652c77388d6195f5a1ffd847213c9b46af8801838d4f6d9118ce1eb95dc306c14525274c36f5d656ff6fbbb0f458864af147dddb472d406cf4bc1ea818d11a278e655359dff5d15f0e8de16b9f4b9faa6eac58f7a170e015f20a1bb3e251", "SEC": "041fe6b77e5ac2c5397a158cf7a46fcf78be2246397f945a5b98b2e8af68cbc56815d32d6ead42d2d31058a0af2c4b1c7493aa2ba57c4561524ca91e84435080cf", "TP2": "040a36be8b1b3fd4986c0765c7bfae42467e3637f8d941052adadf4bf293f21bee00959edc2204922b4a9b04a4dc5852d064bffe7eb5029e58d93c2512b37a6866", "TP1": "04178f0698b4144e36fe19c5f125cb94b05a9188ea878030b23ea1ddb9a58472d511fb377a4d04eff3813f4a6a0fddd4ad822d57dcdde6eb2e303789509d326523", "CS1": "0418732511c734c3497ad50ae53cd8da66034d243ece6a762c59b356662bafe7551437a27f69fabc66044eee4835165a88e9ab652cb0d278ab632c2cda6bf4c017", "CS2": "041098463d0c95578dbf1ef0a0d5325449701c4d42b85dc96ca8815117e5c25b5f0977b2e3ab4d692233ec609d5b19ffec32b517e4effd298d950c9d325af8e7cc", "HASH_MPIN_ID_HEX": "d26571fe11b72f86884481bc61e51a5b6c553e098a66f260d9007c13193b00e9", "TIME_PERMIT": "040cb7f0fc71cb0999ca978cd53e256537eae6b42a4336cd7bbcd0551fc505305f101118a25240c67f280e1d57a274716ee7dfb9af172cdf6472092394bac4f3e0", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34395a222c2022757365724944223a20223833396238656439663063303033653433646636666631663766393933313737406365727469766f782e636f6d222c202273616c74223a202236386265643239653830646561303136227d", "TOKEN": "0402c98dfb7515e797afa377d63fc67ea9ce4d899202197c44f6b3eb2dcaaee49301bf6052e3c31b201bc6ebeef7a1b56e92a897c9b27a59c64b8f3ca1052e5e62", "U": "0422d2a8dafa7e2d2cfb9e4c624a678a02f0cb4045e4d9591d10133bcb39ecc2c70ecee206126ae089e5282c2bf151f5b638be631d5899b82f27484b4629a6fecc", "SERVER_OUTPUT": -19, "V": "040c2a5fb6d18fbc10c5c92acf23e7d2869b5a16b71efe38394b79c2a9fd0e93950d35be6cf2cb8b922d835cfcd38fcef127ff0b5278b8d994761dae5c7509e641", "Y": "00440d3e63112f04d01d77b3a6d74887efb344520da6fae9ec4b0f96fb233583", "X": "1e2570d82f0fb017ac99b038d7139910bd250b80643075ac4ad99896455e2f87", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:49Z\", \"userID\": \"839b8ed9f0c003e43df6ff1f7f993177@certivox.com\", \"salt\": \"68bed29e80dea016\"}", "test_no": 172, "UT": "040b79d7d16bd99a0598eed8bf1fd0d575eab8f85350d4d96f3940ff665b90a1e40071f036f8913c8f83725fe5ecb65150a8ef803adc44e4c26077cd8b8b9b3f63", "MS2": "10e79848fc2b98791c0e6098f8b987fd0882d2bad7649e46675983f1b54134bc", "MS1": "12c58847bb28f20cf0c148f0d3d598c0b0af2fb9863025d5e2646a05c84cdc34", "CLIENT_SECRET": "0422b8eb1b30106fe2cfacd3a6adea70f3a088abef305556718bc1dae70981726f19dd66fbc3ddff1402fda10f4c35b9252bfad8174742521000f3eda5f4cb2b21"}, {"SS1": "22c4e20bc18920ed62e294bfa5564739ed8acd16c59c5a4545eae71e6bd35fab0339ddf90934fcdfc4db2fbaf896a9d05d604f98fff90056853e4bb1362b5c420cd86eafa2b90e3cc239e49a89d7a6a539466abfdbee8437d63eb96ca69435af197c094cf02d81f9ece56a03cddca229facd08b7f2a0c7c6422596bb08b08132", "SS2": "02576d557379de9d14f30e4a23dd87a0b1c875d59217b336065b9e005a7743210f2d617af86edcb4e055c1f8141da547eccf29c67664ec972a41b6aa6cbef52e1fad7518130a5bae5787610975820b0cae267760509c752e1c66221d8acf64dd10e830d1be4829c65014250f0b2a0e46a126c8162d9e3f02d238823ea6a3842d", "DATE": 16574, "PIN2": 7041, "PIN1": 7042, "SERVER_SECRET": "1ccba79fc12767c014e671479a41194143d24c9388352a2b292fbca72831b8a90d60b30a755270307ee04ccb08faf05e1f00a36610f37e2506c8185f6d26d89c03a9cc3106c9b80b6fff5b2cc96549092fd4fb19838c0cc2b463ad784aa8a68f1e567f3806ac3a42e250299c15207a01f23d4c01e7030826e1865183a3281d8d", "SEC": "04116a1125892089ebbb4a76c9f4955c48d7124ccfa85b569692a46a068eb402ed0d4090ff0b98b7b19c23f01ab8a464ad8d83b19b77e0cad58dcbaa5adba591a2", "TP2": "0405dac1f2ba879b7172621408de356c56a24b692e8f96c24115969bc38fa4e6f412b7f358da3239eb580d2137fad3f0fc81971d9aca9e39938dc77e21af510e14", "TP1": "041c425e6bea0160129bc74f7025235102e77e78c9fad0386a890e08a7af2c4d57074ec27d39fdb429a5fc3a18aa6d44e05bedc94c00b8fb88ba78a533ae9aab47", "CS1": "041f1cfab3c9b7492ef302c20249051e9f091b1095079a0ed4ce3b84294e8835d4006dbc7cfbfc2ccde453ae2aca51d1bdce5c7b7d152c3a7105abd0ff825b1f0e", "CS2": "041cf412aeb66161ae0de21cfbd8dc435a9f3c3ae0301cbb88bd6a3b350ae6f4341da4afe339d4e8c16c9460ab2934f4f97367ccc3d2922ade993926a2c061148f", "HASH_MPIN_ID_HEX": "e0a6f9455ec42a79e171fc9e27bb14130728ab823360f52ea0b026a7f603b50b", "TIME_PERMIT": "041879652a7c358f34a8b99351d5bef966088287d5b15616c9fa4d2967e051c71a18d7f5808fcf5be647c6089bbdd357a02e733bc87d539fc922d3656d9d425933", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34395a222c2022757365724944223a20223966393263643731623737346265343364633632393736663765613865386131406365727469766f782e636f6d222c202273616c74223a202234643330633530393135303537643066227d", "TOKEN": "04025a20b3c97185ea2163d13b99c938adfe40a498d52b62108d8402aa95f10c6a1b9b46e513e4353ff4dd1dd6a4411251285065571e3637de98ee1fd7c56a8959", "U": "04046c76e2dc1773a34f6416dbe02c5c58b47ccf8aea58e684c360faf37a10e5fc0b098cccd90bf94c55be052a70af28e3016d88f67894ec2ad50fab84253f833d", "SERVER_OUTPUT": -19, "V": "040863747a14430bfaaad4a4a76a547093d60a07880a98ab8771664862bf5e17be047bde202cc41718b0919d53ff4ac70abebae505ae609f719dd047b8aed99eda", "Y": "0a08e986b7741a4035a6a7748b8e71b36079ba589932dc54e22ccef960bfbfba", "X": "237b3de485ae0d3eeb3eac68fe13c50eb80ad6449daf9799358d04292bbb7983", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:49Z\", \"userID\": \"9f92cd71b774be43dc62976f7ea8e8a1@certivox.com\", \"salt\": \"4d30c50915057d0f\"}", "test_no": 173, "UT": "041655bfd0e4c387e86e252b4f14e4b873ceb29871e102f23d75c8fcfe9ff8f8bd18d86904206b992b9ae07236758a693e26acc778a38a6c0f5085e224d6ab834d", "MS2": "1e59c2b7e07010c5e4c384f191de3413f4fc1eb57e02d6397c89b1c2cd1d6ab6", "MS1": "07d69d0a3f330228d61f4bbdaeee7fb04190645665be4958de02cc2643ebdc9e", "CLIENT_SECRET": "0422daa4c33f2d7488ac513d10ea364bf9b68f58044287198a4e53ed5bb0a71c9d0014aa39866b130ab9ebe741af3a835949746f2dc34df9dea42e00793bbdce0f"}, {"SS1": "15f18def9c6b9fb81001a1fb7d531ad6d4edf097048ed071f6b6823238f507451fae13ccf518ce74ac71a875d11b27828b2d3008c786c7ca0ee0b7d93637bff3097a5aa44bb3faebd5e8a9ba2775df8b337f487dbc92fa5d760fee61a633ba1d065e6084bca29c7ee8aeeb48aa32ee10ea7f012c9b8464f2f891b5916d337c99", "SS2": "209d901366a2ab833717305dd50f08fd16668d8aa508906baf8fdb9baf5892e90116b71cf45b4e4742b99d26cd739e63845a4f7c3d9c656d5b2750fb7a0966210d3bf45dcaa3ff41fe1b702628bb6bffa2083f6a0c5ef3e0488b8c112c1426a607dcc4e2e4764afd79cfa0e9951615aaa74322e3e92eb2cc8f73a786688b1080", "DATE": 16574, "PIN2": 5123, "PIN1": 5124, "SERVER_SECRET": "165bee9d1c502b995d8b5074139b1b7826657bfb6e5f598d721322459e11e32d02485863e52c914a7c055940046d876d36285cf82bbc9ec786fbea654b1f460d11ebc9f88b7790b1846681973cb0548d5b247b89f6462bd82501dd472cca45641a209c9a282fa224ae088950ad3385539227f401bf3403547cbef456f334e26e", "SEC": "041ceeeffe736a7f625fc568b452cb8bcaa49d4247c2826ae3d6895dc6f77ba8390223d4a349b3226b2cb0d64253a7654a398a9dbf14d32e93df6fe77a25da4ac7", "TP2": "04068eb9e1a4051e5e51ea0b7f742b854458062d43267e370d3de2d60cfd737c3005a6eea305ccf5298f22a9778c551e4f1c11a6db5fec2cae3da58d3fb4942232", "TP1": "042174ff5b92244bdfea4d5c76c94c4347bcb407c89d22751afdc77c762334b4fa071c082eb61490a99c7934bc616cc99d094fb1cd4e2d7614a28af75890e41b22", "CS1": "040e6da60a0990597f2e21d1e25296da96043a99a005e0e15f64ab2515f0a202c806c98983234d7a2626eb6ab6cb4bc4a5bf78fb6ccaeb2eaca6032b242bc5faac", "CS2": "041b58b627ea86a5d3b8f695b87f843ee0928ee8de265c988b3147bf499c56080f1715024ffc708b49395b9e5d0bdce45b642ba627ba77e0ce81cf5ba6d9825bfb", "HASH_MPIN_ID_HEX": "5ae8061f7712afa45ba8fadd4d5501042e7e23962ce8a0d46406adc8c3ad7895", "TIME_PERMIT": "0400689f35b87bdf37b1c236c4871a52f07ea2279680bfb112480c47fb7dd4d7891d8ab3e65f8dfcfba3ecd555ff90c8c29e16ed0a6a24531e6f793bc1a89ef474", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34395a222c2022757365724944223a20223031386439373632646166356633653436353236613639373633623635666335406365727469766f782e636f6d222c202273616c74223a202266636134393466363363386232633339227d", "TOKEN": "0417f18876c7ccc7fc30d03bcd89b9077f71c4067462f498df66b9079c5172ab581342b23d88d5f4b6f47e48171d93635461f82b88bbf947ae3e3b799839358d59", "U": "041dc1d30551eca7b5fa0cda6796ffd99abf0844a712ed36d8ceb3f9a6a9188eba1528c8c976049eaa8bc79c86332ed9aecc76f34396f21abfc10d1dd15c38d281", "SERVER_OUTPUT": -19, "V": "040d26046a01058d73b5150f21ab7c4b3dfdbd23bd10c9e26e499a67910b8f2a92139d30fcba083db81512f36460178718dfd11631bc9c527205cc4f7f3732e1eb", "Y": "1cc89f566b456e11a7128857e37dbefa8b8789e0eee19e35037df8e4c2a81a84", "X": "1439eb962cd4c7830614a2906e41767933b7d48647e8e2a142f0cda61da356eb", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:49Z\", \"userID\": \"018d9762daf5f3e46526a69763b65fc5@certivox.com\", \"salt\": \"fca494f63c8b2c39\"}", "test_no": 174, "UT": "0411d3d3593265735526a9582cd043d9de9277954c8ffc2f5ce0eef9920945427c020e0bd443f42d851fab774ff72f4e51478e38de9e1e72ce70564e6d1d764c46", "MS2": "1d43682488dde672e8baabf1e45dfd18a916179b4e395d47d70d5ba6ffb0b1a4", "MS1": "0996015d7d2cf19091d3524e5c10dc7ad8016e04c92e9af70eaeb6937f330273", "CLIENT_SECRET": "04222d13b1cf35a03795731d8f70fbc0441591890b54f0773e2fe510365f9dfe141e8d6356fc73591625795d9a7e424bd351c5629bdc6b453c1b4fa3feff311e65"}, {"SS1": "19d593b8127d5a7050fd6d02c2eb2e09722c91003a92bc6054717c8e0a540d3711290e3b279b45cec7b9d1c9e25eb896ed5ff175fa407ae609711de43c8ab53e1512544bda825f84d8c11d136a9f7d7d1139860f3f760d8ce0c1f1a33fb4b8131fe18e6dca9bdba97b36cef318385ce314f5ca763ef4a12422b649a85e6e493d", "SS2": "1c37ee423f38ad6d0d32d5cd1c1d9b52c2e4f5bb3a56db4ea7f7f0a7e4b349c103319f6fec5e1075ed63c73c8450f185c9ae1d387e32232def8467995c7afe010d6e6f10db6b093577c15769d718eb7fd9f7c3a18d231da68f68d62813f60f891c8627930a874a3cf16c6a8e3c03b67efffab768df7367d7c9dacbad2f00bd3e", "DATE": 16574, "PIN2": 4133, "PIN1": 4134, "SERVER_SECRET": "11f45ce9c460ec08958919ee28c378653f96f9a1d0a5cec1c97a7e5e7ba0fc1c024921f7a05fec827a2183367e032746180e80745095973fd2163a5e970ccbb712faf3437617da9f65850472a24d3795c20d60d00edf041699843434188ee95c0899df5b9ef1dbfcbd617dd841c5edd42dab8bd56a02856db018c8fbb95fa9fb", "SEC": "04090cb390188ab16c83a49c1b41a4532f2a03c61c163586c5d4f1362f4e124b0709a2037dc8d1cb851220fbf89b2b8da521b7811d56b528863464d0f8c72a2b7a", "TP2": "041f69c07ae6131d0952cd26dfdba7e3b7b8aee45b26fcb1383850ea4f3b601f7c15540cdc04a060e5ef54a603a6ab6d163119a6a1a41b190f4b6f868ba0db8d8a", "TP1": "0422952ac08e21a1e036a00a9a3a42c862ac1047f7f8515f09876b0f0127497231098b17c440f47bbac349921a4208b2fd41ebf3a3e1736f58960e17aba3b64188", "CS1": "041202a41fd68ef900d3e3f961e27776a3d08bab1b2b5923308d3079ddc173e085115e213f420dc549909510c5b40e54fc1854ea8bc33ddf8dc303d7da48cd4477", "CS2": "040bd5899a4af099f16f8419e08cdcc69537082025ada5b2d2fd522eaea19e0d9700846928b1d6462f434c7be3e27e6e143b37379fac1ab02e351f6de3abcfadb0", "HASH_MPIN_ID_HEX": "53416fe54202104cc8e1aad00012c07b06b0a23cd3040205dd67f1fc512fe51b", "TIME_PERMIT": "04118db9857cc9b15f6f2b10058e4eea91297513f2879b75c7b540c890636c85501a0c75ab08be9688154f82a842ceb65b313255f5eca4a05776902acb0e0f7957", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34395a222c2022757365724944223a20226530666163343432666164613766643131386231613735363165373637616566406365727469766f782e636f6d222c202273616c74223a202238326335303466663861333762633937227d", "TOKEN": "040689451919f63ed2e16fe103a965c5b2f0cc2d9b4a64a4f61ae30b2d93da3dfc20e6ee530cb515ea5b4d486f72c02df7189e73b02a08697e92a75980514fff11", "U": "041e2fef9be4522dbda8b0ed3a4cfb18ad6484a674cec976f80a7580f8067eb39f1fbe22b0193660183ddac22e74aa6cb40ba0dc1b1bffb3441c59d094689c238b", "SERVER_OUTPUT": -19, "V": "0400f8aa1e727742fc827dc5e10ecda6c6d5f28d52d7659df25b0d884f089f39e7064753b2ce4aeffea5e0b7216c77d0b1cef1ff4564e2cc687931994bcc7bbf2b", "Y": "22db1592ebf6474480a6149946e87202ca834695ad7c0fca9996cda7de1f5b4f", "X": "176bba43f567b3e46f329a98f43829401aaad7f9fbb16fd0b2826c0cb5c3ca50", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:49Z\", \"userID\": \"e0fac442fada7fd118b1a7561e767aef@certivox.com\", \"salt\": \"82c504ff8a37bc97\"}", "test_no": 175, "UT": "04039c3de545e087b0cb426928f09932d126f1b9986d6532da51c3ea2255ad503c115b0ed6e9a28ed7f8b48b42d2df2023cf87d3e47cd0436201940591761acdda", "MS2": "0ef67569f1af42666966fe509035acf180c277149d191edc2a39092fad965b81", "MS1": "2360edd2c3c4760aca788879711f9a8c946172c4e3e824ccdd97e60458dbacea", "CLIENT_SECRET": "0409c7137cc113c452cd700a95726900bec31403e4c01a38c7b127d25711a32e3c23ad75f7c33d591dccd0fc2c35e2f6b508df4fe987304c9f0f9ec67dd44026b4"}, {"SS1": "21c2f6a47354515c343fa0dc4bc7b82d45dd21f8f65a5c880719b1fe4de9f1a315fbf255cd464a218e0db9e87869b1ca802a0212b6b45c1bdfd8038ce21fdb9f0d7461d379d17548e909f66aa79f641afc537225defd547c4f0c5382bf5368b61309c15666b52605264c3b3bdaf316f77f8c364441f2a5f4bfc5ece34df376d1", "SS2": "05247f126a474026f1b2ce94329b286bea07fa9c9356f6d2da36610f2773890c1faafb86adc1d063995cd5268d46db0074f174ca8bc3e2a0d507b39a8f7f609219fabdcef94d4160884c128a820bb14e6ab839d52d68d3eec451689c002637290a4fbafd160df31231425341bc4ffdfc650fc42b0d3ccb001d37324f30f53c9e", "DATE": 16574, "PIN2": 5924, "PIN1": 5925, "SERVER_SECRET": "1e737e5a538b829b16f32e1564b0bed0f418bc654f0b04dc30180a276e778e9c19bee37ee8776f64d4cc864bf4b97fabd97a4b3161beb3a61167d0e322bafc23193b6bd45d44ae3225929204f23302b0d7266249a1eeae2d9ad4feac6c5c2bbf1f6a19404ca7d9fbe423bced63f1d0f50581bc09abbb29438e9ae13d9b8828ac", "SEC": "040f92421096f25926ea594e37fb4f540dfc4a8f6d3f19cda7ff7f67c44ae6e2db22f9348f59274d9de893f88510c9afa2dd8c7de54619e18ce156b6456ee26ce5", "TP2": "041dee90f45afb604336b13a825f68ecd6f72dabc1c37feb69ebd69a6c47ef83b61ed2dc9cc0c9abd349989a34bc220e04c8f82062cc24cd7612f416b7728a5174", "TP1": "041fddac7f8000f588672ddc5ecf44ca483717512cbd6e1a7ab6448118f1768f4d19fd66a2936c04884141b6d3f42cc3d3a3ff8bc8fc254f6895e58be2ee6de3cb", "CS1": "040e135926bf6195078474f156668de6c003e1c1b29b32ac0f6c7440af9a24f5d51632764af8a1f0c43755991d607e5380597dc3e69d40909a0c315f8f93f48620", "CS2": "04007b63cc470bb1a0eeaf60a49b32b01b22782215d01cb6bdc1c2da6444486c2c2179b15eda26f0eb40b7b865aa98018f9619b329d70fc2f8000077f2999e5828", "HASH_MPIN_ID_HEX": "bf59f520d00199e0c6e032d8945b6111d2b1c8d001f26c00be25fea1fe0b3cb7", "TIME_PERMIT": "040de2b60885df8d6246cec8b3ae424053c4252da77b1bd359cf1ccb3a67d4fa02239f68fb4725007363268e25b1493c6cf59c350d481ee8d82dbb0bcb74631387", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34395a222c2022757365724944223a20223535396530333661636436663030396532306164383136326637373036303061406365727469766f782e636f6d222c202273616c74223a202237323661303635623330613535316663227d", "TOKEN": "0420747f2ec3587b752cccb1a679e26e7c9a4958d2ff1391c416d309967645f79a02332e26e63a68126974bbd329ffa7d4b620f47e550fa9e427ba89ebe9f8edaf", "U": "0409fb4edd6f032f85505be0438516bb1361492c74071242284408b0d83164b6281107dad66b7383ea3d92e4b6e87dde608ef549b5ec5e9f78e684b73a47ffb343", "SERVER_OUTPUT": -19, "V": "0403b4fba9ed12df5988d947ba15ee0b093223f50ccb1da4c838621c15acae88ea05bab66f7587ccf6947670366549c85f574a092e4293697256c0fa77b640e413", "Y": "084b8d10bc53fe0e1f37f1e032efcb7d406978d007320d3a65a52622017b31d0", "X": "224224ca9d0a0e3de806dcc48f9843c47c19bd69a8a0110275166ace0f6c573d", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:49Z\", \"userID\": \"559e036acd6f009e20ad8162f770600a@certivox.com\", \"salt\": \"726a065b30a551fc\"}", "test_no": 176, "UT": "040c71cda8b22724cbff7458ac87dfcb42a4fce4439df339acee4b600bb4edfc9623534b04aaaea138c79da56bd4f7f15483d954f1367f87020155ee93d95e46b4", "MS2": "0fd9759219b05fe6d6252773f759964f672394cf64457f66bafa18fd9edd4c75", "MS1": "1949ee298bba655e4159c266c7495c00e33eec1eb8d4f0d0b2a0b8d37f3a3a40", "CLIENT_SECRET": "04096037b41f1a42ab1d64e5705aea541ba8231dddd6a0c750f808cab29204b4d512decd4dfae9a2890424c37e4c3415507ce7716e3424cd15b5f321dc20804470"}, {"SS1": "0aa85ff4340d34ca668e65c885cd0a12a950ebdbe58631640e5542f2ce067a0d05a3e1015bc1dcc9eb6913c962663f1f33b161591b89bb9b6e009b01c3b4e5e10f7eb1cdc1ffd5f66ae1cf4b425e01b898bfb27b1ab17365d6bf54eecbe967bc1ec8562722ada6a32fd70d1e6fdda453dc557ee137abd650706ef646e7d1e829", "SS2": "14bf067f0fa0acc806c736d55d4bc875b10d419aa74efe2771831da24062958f16625277bf419dc49ef8095f827c0076e5f7ac5341863cfcdfe272509e20704c04c73c2f9b412e89e8b41dd6ffdf894da125e39f5c4bedcb72361cd033d9b4b421c76ded206758040e9320ad37b28fb4ec08310b4d4c87051cc29c4d7d4fd3c0", "DATE": 16574, "PIN2": 3870, "PIN1": 3871, "SERVER_SECRET": "19d2524879cb8670b3922a993a549bf217a7ee9939cf096da4af4b8e638eca5e0e4b6a6714ed9cd85cf4ea9ed9bfa80ffe031401d8bff1ef598ee634b67e7e5211e71b2792a7283b222ac4f7dd2452f5f6280b56004a6dd82ae2355925e0056a10e64371e1e506fdd12dc37ac65e10288db8315084f6d4f3d61d640988720fd4", "SEC": "0416c90436ff9a46214f509ee49cb8c3f6a62e67db34157560d52b1537fe4e4ad8003e62db961655b6d946c5daac6af11000c8129f67537e3afa8c697765051afa", "TP2": "04173c87ff4a5b3ded380c1c31990c472dae994a6264b90bc1d5bd67ea572ee20a004a73e30bd39a152fd5ef21f23ddbdeb35e00e0718cfc8006632c3d7a3e3c91", "TP1": "0423d8cef7501bbca3f7fc5739719a08b2671376eca63c0aefc271930be8f5dd751772f9359c72c2d49d926d0a2736aa7fea8c64a9dcdbead46fb76ce7431e9501", "CS1": "040b28fce6e8f5db5a655d68845b0451e6bdb9cc126ee49d2112e978bcbb972d2906a57134d3de2776e107522986398213033e7f9eca03cd5e5037b4d319c7c612", "CS2": "04082e90df17a51cb2b13cb967257d24bd3aad52c81799945bfbbf5ab12d619ca10351358b415a818c855121e93a9f003c2640d85cb682a18f15c949e58ad82f45", "HASH_MPIN_ID_HEX": "3d3da7b83a55c772dfe38067a86c5cc4b140578555aee077faae8e7fca3b467b", "TIME_PERMIT": "040ab7617aeeb39f843fa339aefb5be8f5a94fe78ca15a43ce222e52b58f79cc9b086f9264ae6619ab0dfb07e87a0c0f3b2a1fa6a1cdf2cff34acefa31c831359d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34395a222c2022757365724944223a20226633653064366433326661303133323266333663653435306537326437633663406365727469766f782e636f6d222c202273616c74223a202262373164663638326530643962343739227d", "TOKEN": "041882d8f1249915dbff2c73fcfa3d20c629e383acd58ae3b4011f8c20c421acbe0d8d55b641dca6ff6850a361e1f9e2c8e6376cd7ffce1718f73233db87b30b23", "U": "041de0bfec14a310d56912a04e67027348479917d66178ad4554d8d7105605e6c91a013668ad33ccc6643b7775a51a0ef1600d1578b7c9ecbfc525510da21ef945", "SERVER_OUTPUT": -19, "V": "040701d9d530212187ae882b7c0186fe30ed2ec6c2ef974958134610a28a943df811f123bd2da9e11e9324d4acc26f94d43a5a7275e6cca94229fd3ebe11fead3b", "Y": "11de93f562a8599397c6b62dd29163a489a1a1447f228b484a80976ba4b3d1fc", "X": "0c7e537a2bec19e5a0b0a16d5f79fae472e178f7c1730b7a18f89bf8e01e993a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:49Z\", \"userID\": \"f3e0d6d32fa01322f36ce450e72d7c6c@certivox.com\", \"salt\": \"b71df682e0d9b479\"}", "test_no": 177, "UT": "0407c28f84b6a56a2f9d12769ae8a942c5b9344b7eaef91846dc1971217641764800b5b6471fc0203693c19268f3a76807937e1faeab48cba9254501bc59e797c1", "MS2": "1ac1ce5256b037d8e02b08d3566aef529ba89fea72d8c70c693ff13935494db1", "MS1": "0deae51263f10508fe4d30d0a2358e3fc45d728e24ad21709fcbfb9025520143", "CLIENT_SECRET": "0412ad59b7496f5783ebdbeb2b37ea84d371dcc7c4e9342a7afdb139ac87e714770e4bf2d39ec20bdeeb936f2d63404563304d63ec0880ec385a91c445ededb384"}, {"SS1": "01a5bfeee6eef4942d3060f17f4946b32cc2101d03c0bee04ad8df7a5d8d6a1206f38d00ca35b345f8c8c582bf8ed25b60ff0c5b492b3c31c3f5f132b0609baf14ae309ba7bc25667718a1e6272df3a872305e78b271b9bd519c391244a2d6ca0bb38fee909e88b5c44107f2cb6866650baf91257c1facb2b969b44883c09ecb", "SS2": "0bb152c592918071972f786674ea59efc638e0a10c651d924071fffe44de2a980e49c150776b0e7998b501b3f433edffa28d2f3271b2c9724b241197b9b7a6f3101dfff717ded175a72572be1c3f5a41ccac421c81679df20f39232627af840c0e4599dbff49dd3229586b1a5f6fca02d47512b972e36d5752055d02266be7a7", "DATE": 16574, "PIN2": 8808, "PIN1": 8809, "SERVER_SECRET": "0f5e1dd745cf21aa18af4e1fa13373902f63660a2d70fe330e3659b6ae79d1be01577a5f0977b8bfa0b02065924cebdc6e47dfb0fc2cb3bf6d78cd8457869222016341f737038e08603828adf3c8bb370d96b97e436879cab35b84bb2248d3f1065ccd0eb778e48d306df592fac2d863d56aa37af144bbad69eb2c1ac22ce438", "SEC": "0414ae2b589cc4336807fe315566e0626a1099306acd046e3d169bd2ac44a9821c16af16fdd82f84de90de84cf1e4c3a33e4b044300f152c344af216c0627ebd65", "TP2": "0419d7bb91c1daf0bc9e4c19911d7e1106de99358da33405d3e09672b55a628ca30791c2aa8207100e4fd7d3d431429f74e0a9e3682f5b52c63243d8d710a881f0", "TP1": "040e704b1d70d1d14a70e0250ac9275a36bb431f19d54c47353646e0e1c6f2e448036c75a1fef4d08a32b3bd7549c1c2bf3f40697a85440854cfa88f891fbc23a6", "CS1": "0414ae4248be3b65ea3a2f13e502abf8a38171f763a5bff97dc07983911e77de1c0c5c6933f5e9d931c8824a953e78f950dfd69bd2510b0ca7046e90f7fc2c383e", "CS2": "041e857246bcdb80c2864b15356f4c5dfd49752deaaa0f596c4769710c764154fa030698330b33176b18513ddbef151418d3a9a8f00628fee6af471b6f32756dcd", "HASH_MPIN_ID_HEX": "3dcb1cddb86869c4cf84ee83a9d31597fbb55ef69e0a279e67660033c0773a1e", "TIME_PERMIT": "04150231916253d9c7bc74e289ecfbed77fadaab4c44acc7250aaf4f0c35e05b9f0be17ec1222422437a1fb1eceafcbdfbd2a229a25631e95756e592c02cbd042c", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a34395a222c2022757365724944223a20223331616364386562663935656664313363383933376662613036613234353739406365727469766f782e636f6d222c202273616c74223a202265373434333836646662333135323566227d", "TOKEN": "0414db2538c30ef918884ce198ed12dbd16b4e32c82f9d44434f8c243d6e6a951f215201b33f8b72468e0b2161229bef114503ca70154bd979d8ef7e650dfd1359", "U": "04157ef141ccc4eab3e6ad788885578dc94131cdafcc81345bc0d7ca79ddefbbbf14c3e5c53df0657d17e04d238c1909a186d014ad5d4ef828d0b6c8bb620cd782", "SERVER_OUTPUT": -19, "V": "0403f4b62e9572c6810bf6f7a0ce1765f0edc5055a8f75e9d5efcd9b35b146bfc610bb3975f0451c9e2b73cbb38efe9e800fed2fc9712489cec8294858634550ac", "Y": "103c80c4fc679520979e25d5d1ace1d2cf981e3bcfc0fc40e437d4268cfe9eb3", "X": "1572cada7c55cca3f36f63c86e28d666a071b592ae75a0ff546a232d92fb295f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:49Z\", \"userID\": \"31acd8ebf95efd13c8937fba06a24579@certivox.com\", \"salt\": \"e744386dfb31525f\"}", "test_no": 178, "UT": "040815fb4083cabbe6e632c13f85b45c987ba7e5d8ee7ff802d67ab1d973ebd98c0c7d6fde62b892a553b71f2f72ff10d13875460df4a2fe4e169eb09a5b4aa4e9", "MS2": "14f0787b0fcb933af936bc5e3d7f6db759b43a437b279f2c2b64c7bcf05ed175", "MS1": "136768bf62b17df6f33afa0b9bef8d5d642775f0e9576f7c32fce976c724087a", "CLIENT_SECRET": "0412c8fe0b9900129f3792dc9473790264b83eaabeecdd54e21ffe43e48315206f14b47df74f80db254ea4ee5ec5efb2d03ec3c43b03fa6414e900c1c7e95fc3d2"}, {"SS1": "070a65ec57dad0e971fea646acaedbf1448d1b4b91a78bf6e196614a7ddfd81e00fb7af6ac3245b56a38d07b94b3abc8fd8145f6079bbf2f46c06448af8fe60623a8dae98faca018bd594fc39ebefafeb44016a5b46f8dc9ae0ddfe8fe06b9531d83b3a9553b121109506b688b572dfc6322e02c1f4ef468ea0548e5ec978425", "SS2": "1f1e5e4c3a85ffd3bf6bcd35e33ad3832e6b53653df7ccc45e0be37069f548b5131d3f2048f3bbf9f95b2892b5c2a64c4bf474453dcdb3f5679be3136c3b6afb0aebb45a4588602976082243b701c1535b888e27e4f41bfa8d5c1aa67bbfdc4321807f53f7e76d19c472b8e1fee605f5083954f75a4bef69209991085623f799", "DATE": 16574, "PIN2": 182, "PIN1": 183, "SERVER_SECRET": "1b04eca08bc7cbdd7288644da2bd2db06f7f0b424bb52233707b0b421634e9350372855006797519ecf7805603de9792b60936547131ca1770076569551f1ea81561d31dd66373bf3b44883e1a35f1df380c7a0057087975ff9194823c8b95a902fd49ffab6fb024991c8f84d93dc1317d6f5a078bd4f49fc2d901e92a914451", "SEC": "041c9870e1a3e5613dfa548e29e2fa5a015c4ff31566e44446929d33b009fce10d024ebf0ff1daca6354be0a8e4fb515ca7dbdee7a52d44a3a81c28c3bffcc7c32", "TP2": "0417db6768ada5b9730ef65b020e71945c08dc2d6f50263973ff3e254836533f300b11507e73708ca4eee0b619f3e8d879e1cbabfd7750e40ab010ab50c7a90bb5", "TP1": "0410d37351b04dee709bf02303fc4fcc58f5bb60883349d9b6bb230c7a977a28a91719de632417fd692b743e453371a46c98b6c8cdcf971ce944f914d42d118d71", "CS1": "0411c91971f9a2301f69062db2099b2e2fe12eafb039bc590a7f6f06adb2e07ece04a53133ee90fa34f80c80503a1bb17bdf03742c06bc2a008d38109554f901e9", "CS2": "041177b5e0f42b55efd397de2c3e2883f5d389252cc066461bb51e6ab1de2da2be0c728dbc664b2cfa30216abe2c188c6a3e9126e9ffbc59f348728e32faff3c48", "HASH_MPIN_ID_HEX": "559051f00b835900c9ad57e8edf6818f06238734b1e3e2c201559929cf4c11d7", "TIME_PERMIT": "04167d77b46cf7af2bd8674af12db60167acd483d2553b0876194a75cf617f1e8b21e1cf09685329551a0af064026e19afbc40af6165617179f6d1b47bd51ba68f", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35305a222c2022757365724944223a20223237393433623366366335393466386434613162613066613566633539313439406365727469766f782e636f6d222c202273616c74223a202233343731363934323533643362656539227d", "TOKEN": "04006c11e92c7d5f7439ce51cde88f63119eb5fe32b1240e372de5346ba0ff820723174b0940bb86520cbcc4972dd17015c2e020b3591c2488d52fe681c200c6ec", "U": "040383f8854fbb0039b520d21e9093437943e4c831c2cc39a6b5195626a04ad92408cfec31bbae99f9db080740649ca2ec99d46a342828e82f10389197a9316358", "SERVER_OUTPUT": -19, "V": "041b57adb346048f9d3455e4401bd9eabc4cfac5cf7d0ae141bdf4a663b81c61c2056a43c4acd79ea7fb67b60af870ba480d207dbd00f1ef4962e470fb484c6e6c", "Y": "0291af284314bec5c3420cd76187c6243a4dc2c5867070e9eafb8bd68254270f", "X": "1e2354cf92feea5872690289e161264fa930adca19fe3bb7e85d22f319cb059e", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:50Z\", \"userID\": \"27943b3f6c594f8d4a1ba0fa5fc59149@certivox.com\", \"salt\": \"3471694253d3bee9\"}", "test_no": 179, "UT": "0408c7f88f31a487e94b49a704e6456c216d1efe8e919763e5f5d3b4beebe2aa460d92dc72014f3814f5151a5ac4e148a24b1bb462b59ee76cdeb7c8b87e2bafe5", "MS2": "23bb58820fbd08c08d389c493f8bd5c2791ba5578c4242917022b21c7300d62b", "MS1": "19ce5ab6ad6d0e465051919728bb6a89a647d3fb6c733af820cf2ec03c3d9691", "CLIENT_SECRET": "04073d9e192b399070f0c5a75d9630e6af0eb92c41680c79a259ff20bf55735fbc1f0db187fd366142f486ce76e386a157556de3ba7c926573088684bd4ac0aa46"}, {"SS1": "0c94d67edcf6a02d987ade2a84f95377c06046d482519c2d022d2d40a82ba280162fa418262b2a17b7d862c4ef3846858361bf6b45174f16c49454e551e76487222e7e3186b8ed4024b9a8db9f92961e8b708079d41800a92e282222de92e96004349e70ceca3007136760b6d34888df25eee760e82d72d50d7096d631b674b1", "SS2": "18a97b4a9b61c1d9bd4ab550fd67f9eb0586815130bf3fd74ae3abdd41eaa2141a9e0f4e88faee702704b345d9daec5caa592aa154bd029b989a6c2675116d9f13d92ac0ddc9100c57e9fd87e44eec61d6751f8092333c51e49faf2e1429bc9b23467fdc7db83186e44217df771bd9ecf2763c0d37517747930d13958b6a1704", "DATE": 16574, "PIN2": 2075, "PIN1": 2076, "SERVER_SECRET": "07f9288c32e6d9462486e3454eb4b331c6be9395fca5abaa42fbd66a4619da12067a9a51724db4132be6cb4af54001d70901b8283b9f4fe97e82a4b5fd7703670c93433122207ef2e74e1374f274374be21c2ecc50376abf33d5dcf4c00c9036045c958c3b31c18c66d512838296308fdfe4c06c7387a1ade4cd4dc21bf69af2", "SEC": "040b52eeb23556b5f034f989a2113c298547e89a2d955cb2f01ca848b1f9fa069211885fa2b5723d7c49df133faa7ac1a7e4fbea26948fc82586d859217f126447", "TP2": "0416e0e28cd24547c7f9ad7f40a5ba261c1428d42b1c159d28a0f408caaca26876162554842195fd65f6c74fb284c560b9fef3e9ad42c08f76b6ecccbdf5bea61d", "TP1": "04112efbe818d4c99cd3d35feb1937361cb099f7a970e9260c79171bc5ecc63dd70b5ececa15eeec6049332952d3d93131d089e0792c5887f25d6a880a767948e2", "CS1": "04110e166721fbb22f3d809d97e51b46c403bff6957f65d2e3722d18845067c83e0aff2bded6685669b36cb9e228047b5d14b588382d411dfd82d356654de7d953", "CS2": "04073bf0dcf37fc6e8604032af2ba131742b9c40aa0fdf417cf4a4373b18322e6b03d976ca29314d471bc50817462bbf3cf81bc303b72696e49dc94e984881ff33", "HASH_MPIN_ID_HEX": "c15b673e038197f3b187e1271dd783b70fad7295efaf44b76a1de25fa78c48c9", "TIME_PERMIT": "04002b6eb9bed31199592cda8e697562253b3480a98030a5528b5ed345b4851aeb1642662aaf8f74c5bea6710ec700a6dee9f82ded65b7ff2b08d874b48f01ae1a", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35305a222c2022757365724944223a20223164333838626333396131623934666561613266623634306637376466353062406365727469766f782e636f6d222c202273616c74223a202236633931393364643337643664383165227d", "TOKEN": "041051ef739916cde494b53fa3891f3233b820b9265ec051f810ad2f0cba8419bf1a6e174a3dc202158c93e6b2545aa5c3d827ca4dea67dcce0f2a9603e825c49d", "U": "0418e61d12001f679c56c3238fab0d2fa8d26e33670969d01bd6de193ec8d08b0a1355a4e3e56c2121a72827bcc0f4639780dda355b459df34aff23e65105ccc83", "SERVER_OUTPUT": -19, "V": "0418470ae1b6281c7dc59a0b9e1b4089ce28cb4852d86e8d9b91ef6fbb2489be780b78c2101e4a5ef05f402fdc87b8feba14f1a6c7da24174bc9fa1d58a3bc5418", "Y": "085d2bc557864d96461336bd81318e70a1203723edc53ccc31097412a8f21596", "X": "11048b386c77e82a67f8aed46584c29844f7e9ab8dc56d30657a10941340a5ab", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:50Z\", \"userID\": \"1d388bc39a1b94feaa2fb640f77df50b@certivox.com\", \"salt\": \"6c9193dd37d6d81e\"}", "test_no": 180, "UT": "040e9e4ba846eb4a14c3eb18b0ac5d52b335b3446d913d588448f8796dea05960700eb69a23fd9d37e9e14c4f0ae894ffd3df923c47c84fc76dbd0d88aee666dba", "MS2": "1d3b171cf94a80ca0886757f05daa706bed2798ef79dbde1c261d7145cfdcaf3", "MS1": "174e75a18068197f39ab8ccba347ec54351f3b72b75062d9ae76160f40b6728f", "CLIENT_SECRET": "040d98936081aae4eba3b0d98672b9e0e7cb146269a18c77de02d2147e770bd53f1a0bfe09d6b7f697d53fd64127f3ce7909715b153874fdd05f51771f472fc78e"}, {"SS1": "1ea049401f520c093b1a9625177b06a5e1d03eb1a319389b58026560291edb2517f725d69562ba5efe14d437787f8bb34d5fc165eb9006f72f6bed17689517fc2321baf96448caf24ab6717538d16adf4809dce8a3be5224de7dcae64314ba4a0f098fac90f7eadc5e5e6f5cdc5b960b08915bc1f061f645b8b8d85450dd9330", "SS2": "0610e705ce09ba2ef6c8f32dfb9aba895b489ff5dc9946c075ddddd4f7d9b5d8174c63dd5900108c05ff24b9e28d375088facb6f8a28a3a6b00f9512ae22b2a510def2d6ac65f1a5d4becc6e0cb5bde08787a7cf2f723176e2c0909053a424ed10a2fe006e02ec0865c6ae41f618d6249bf5e082311df66d60fde2d453c1c29e", "DATE": 16574, "PIN2": 5544, "PIN1": 5545, "SERVER_SECRET": "23589ad8a14697d9dcf5ac2a35cd2fd30708ab864cb25b28310429a815308e4b070d71e237614c59c485cf74a114b19d61513cf2430a6ea077b25f880d3a019b05758ed67560a82e0c3337d3a5ca61b9ca237165624b385e5c72ba3f1f8658ac06b96411d48e24c87110070ebad255f47177a440ba7e8d02512e51a9ba6a9140", "SEC": "04089d62f0056ee44fb7f694fec4474f9ee9aeb8ec8108c7d84a3f84d61cce872309d1ac4da218b4cb5c631436ebd399167487417756781d6c4ee0c5e340b08a9c", "TP2": "040b66d713305dd12f3be74971949f144a49554e44557c2c66ca2e9a0f4690950c0bacadc9ca49663c6f62a10b6e0b9c2c17c80d9efa7faf5434cfee4458d19024", "TP1": "0414239f86ea3043cd5448133122eeebdfbf9a367d6eed4825f085ec8697b56ec819d6066d0005c84f3850f46b228bb8907e5250edca9d4369a1acc91ec49c4c95", "CS1": "042180dcccecc736d1df53fe997bdb0dd394b72d1292c1342d1bb554be8f95b91908353460789b8099561dfcfd68237b6719ed3da285f484c0cb98c90de827aaee", "CS2": "041b55ab9cb9b0527f8ce78f5c7448b97cb82be2509abccd1a11e1613c0616fc9113818a9272a622a3af069daa431a227d8245b37ba03ed43056963d82bcef08c9", "HASH_MPIN_ID_HEX": "4f2ee14b2a86ad6640de41adb9eedd8bcddd3a281399d03924592727dbd9f3e5", "TIME_PERMIT": "041b2ebd733ad9a84770aad89493f4fd054f79a4d67eb03d5745509ffd38af0df9196ab254881290c548d0e18e4a4588d9df343f544b53c63a8d8b9efa45214a2a", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35305a222c2022757365724944223a20223137633562313333613364633738643166336238306464313931373361623662406365727469766f782e636f6d222c202273616c74223a202238663066306139356139643332376562227d", "TOKEN": "040d3e06fa085d4ca8fe6823c7474ad6b5280689342e1f975d16e7aae63e2bde0c009123dc91edfcb68fcf32a61eb5b521e687f35311290acf9e84f2db57cf085d", "U": "0407a5b908ab9a8be4e5c718ad6c2358bd2cdaec50ddc049b6d8c451fd6688eac1140288e9c0769d65bbee1d647eaf65650d6915395420022c15543343d13cd175", "SERVER_OUTPUT": -19, "V": "0407347a654c2cc0c8aac8940222304f951d7c2797a1426bdbd2cd2dbfb27da73f0c98151aa3613b150cfea9d4c571287a395fa394ca4c9cf13834770cfd5a68c8", "Y": "0fe1d5d781cecf59f32a7dfac7f9d17e083db37943b813eb569de05500ea2ea6", "X": "0261af3c24e0e2e097d30c7eade33dee0bd477e7e896cb739150361183e34e10", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:50Z\", \"userID\": \"17c5b133a3dc78d1f3b80dd19173ab6b@certivox.com\", \"salt\": \"8f0f0a95a9d327eb\"}", "test_no": 181, "UT": "040512715fd285626d4c9cd781b10a08f44312828ceaa032070179d2ec93944eff16d9c5dd6db644584b06b19e9c2ed5c38b3e6f79ebc95f11b115c2ce6e2db575", "MS2": "14afce7121aba38e3689cc9f7b067320263c8ef34908f37812291dfd2a22e0ac", "MS1": "045655bb5592dd55681848163ab24fa253473a5d3b352105550f4e72fcb5153c", "CLIENT_SECRET": "0416c6ba2157d7ae8467186a08f0097eb0f7aeef03f7deebba5a6b02f56df7e421135216eee8217aceaf247ab583ed214b3f5be50a2e0b8d08e4d24cb245773e0a"}, {"SS1": "1e15b777f65cba6a5c421790ad5b8369f290c288c49b8ff6025af3193ebca9f203aca8648fb9420c91ee2e6f8cd3dfa5bdbf00d38f1e87ee57fdde235b83aed71dc0452e42d463dd64e74204d2a8ef4f61aa8574c3daafe3b4290fa3065b0a6b20baf5bff41f593f1d4ca524145d560c249f79be83a638136e4891c0c2157552", "SS2": "0aeef93c2d48e17551828e77dea6c41a190b4a00cb81c6b92820e5a1cb246b951c3891397b2f0669f3634c770cc5850210d9fae42d2b9c3c8e126df16e53917513474a8f69bcad1522fe5aa92cd70e1f57b7c0daa58cf53e48190d04951ed7bd1af8a39e09d812fbb2f151e8b2d7935c2e368716639e987e5a5baf04603042cd", "DATE": 16574, "PIN2": 132, "PIN1": 133, "SERVER_SECRET": "0f25f65fc4b18d4401e6fb146e42d7a12fca22143a6617e51acb7d344d602da70e045f5d6757ed15de2a045a5c4bfd965123c00c2f83b02763ea78eac0ea852c1262310ebfe2036a5950b4070b48a9b90195ec28e1543680745a3131cbf2871909b9ea09bec298e8dce17771e400e508d793ff495c372fb026138eac16f1d1e6", "SEC": "040b70ea15a7b9cefd121dd7d3008bbde887b907d41844514905db2b0775b1e8542056343e2b5d63b2a7e6c759ce662828d71fb5d3e93f81fce60168bfae20e6a4", "TP2": "041aba8f6b910187dcc46ba589603db092758d754f7108c31a250e628444fc1dd809b0d263cfa273e1febf3b92bb9145808f285661ffdef0d6ee760c9025bf934f", "TP1": "0401a82cf2ec906952e4c0c7fd74b897dd5ccb01ab499fa35be53ec2fe602687fd0a48faa0b66e686aba5b6abbab6354abdfcd838b88d9f9eb9416dda006b7e175", "CS1": "0403fc1fa9183db21ea2cabbd74845cc0907514f94b892c6f4cc0182582d710a6e23103ae089de4d40a30d1c6dc3264e3e6853a7965c1c629dca8319c6231c87bb", "CS2": "041c83a6feed9623867aeca3dd13ba4b8b64d3b8b7ad5836581a4a34781bc24f4d2135c2cf2fb8cde2b8fe65c859331e6da254b8f03e512e7dd9f345a41fe78b82", "HASH_MPIN_ID_HEX": "bc5a98d8acd349674db40e84470577b77c87daacbd34c890c68a1de4003bffc5", "TIME_PERMIT": "041862d7c5b907c22d9a4b0519612c53e4721939c00be48f6f56ba80e427691c0512346a2edd18587d67b61246ca1cb7e9205c0e6945833ae84b5dd1532fc24434", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35305a222c2022757365724944223a20223562326463666637366265383932623961663030643864343035616365623836406365727469766f782e636f6d222c202273616c74223a202233336163366430633732623037656134227d", "TOKEN": "04234e6f46cbb68da59c878ab68e5a5758b0111c1239625ad25b51cafd8aca6e250d3cf747a91df67e2389daee5c0c8c9fe816c25b26fba1d3b589cfb906982e9e", "U": "041c9fa59635322cd011299a7204c7357607bba6962bb9ab0c7cba571de183140502f58eafc15d5116aa4c2dbc9fe565ab361307151a50d114fae3e40ff9c213a8", "SERVER_OUTPUT": -19, "V": "0407e099a81d4f3b53f16697d9d0930e7751774b9834113d0cd9a136578d44307510f46e46ad9cf84e035a0596224ff18200bf7ce82dd5473e56600b0c003e8fd7", "Y": "1ef85ecf58fc1472686cebae6bbcb7d5990c8b53dc2108804c4873b528915507", "X": "21eb5c8e3a41d4cf0360998b8bcc713e169cc64b1ac04c0e299a65be9db2c5d7", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:50Z\", \"userID\": \"5b2dcff76be892b9af00d8d405aceb86@certivox.com\", \"salt\": \"33ac6d0c72b07ea4\"}", "test_no": 182, "UT": "040e20b49a3a93bc6e1c958d9f5cdc2d5d80899df5004a5163defdeba8794e58c10387773cc0618e202f4bd287138f748e10fe73e77b6a2d3da91dfa983f31640e", "MS2": "0a534d2ed3db5f8a0b5e620a7f9c0a8e3ea080e9071edd599f1b2d3b46655d8b", "MS1": "0e9635c319c5c8f14e999ed12674bdc0f70e4541895a2b07b1231edfd43277bc", "CLIENT_SECRET": "04234bcdb1c96d3ebb24b2aa00875c32b9ab84a29141e3920f2df8c8e7621b3cc714195aaa5685d8e70058d99a9ffe6b3e2235b0c6340aaf32dacc23949c0ab722"}, {"SS1": "175fe43313c8c1c23dfbf0d686a9dd2adeb41c3c509109ebec3269856f4e7e112091b18fd628d2a06ac8ec7ca9eeb44760c8808c4ab042cbffe3c068d436c5311d8b87ae6d7661400d42bf6158ea123691c4529d4c7903b3793e4eb405a7afa412b1f3cf12ee97e931bd4b02d34cb491307b282336567b89366c216e04ddcb9b", "SS2": "0381d447842043acd15403f1a19c39a97c576b9f671927739a9533c4b39da51a0854ce3405619b1c93deccc2188bd51ea0eb36f73493330d8b0b743073ba2c9f18466b22fdf25cb6a098d1121ba513de06b45571c73d8a4418e869a5578f27e91c5b3aaa3c82b035490e58962e33fa85945aed619dc7aa0b8160e905f9f8f4c1", "DATE": 16574, "PIN2": 7275, "PIN1": 7276, "SERVER_SECRET": "1a6ac4b2afec9b918d5c7955b2c9e51460ec66a94587e917275416e62474ed4d18de7d723d3c3c02f4ddf4863f0a78973825000ee5a232b5ab3bb11270d1dcd32345f7f8ae1abc18226b149462d84f0591560348615908ce2ec603251c5aa591153d085b942a2e3b331306f833015c467e4d4ae3950947cabdba763c163f34fe", "SEC": "040e3f8519a24b029dc21d12f35fec9231261e01de4221b01db371bdf9d60b155c0021d57bab41c48cb696a9afded16019f0848a96c3f899f5ad9cf0f51ea053f8", "TP2": "04010b0622a7986d2388ce1f7fdc323c5b250c3e3a5b9e5b24d66c051499a1befd0c860a8efee40abee1c86bca50217386a81ad7571884842d9b3717871dfc2ea3", "TP1": "0408156bdd552c6d25ef7ef911f8d5dcf0fa2cacab8ebd716ca6157dd19fa211691a15225f54e605898c5f1e2c7bdecaac11c8a87d48725ddcc91623f9d75783f9", "CS1": "0414f9e4adfcf36678bab18de48ca85bd552ff7bb6df93a3ea6714e1eefb94ca3f22d286a19a09c20ced43100666a9897120691f9dd91dae94d83632d2bcb9c2c7", "CS2": "04113b7f002e1cd8b061eb43b17982a47576b2178a1434ae59e7c30c21847d0cb80edebde6a727d81fe31d6096815e9bab37e924505fee436ca2a119b5d8489459", "HASH_MPIN_ID_HEX": "dcb8713ff3d0dcf15e7ba4382832ba2aa8df54997948214088c0e473adfbdc27", "TIME_PERMIT": "0418a070a0f58d5d7471ad837c433823c218cb8cdcf66b93b02f5a00d43cdd37ae14f9e7e811d53b72870cd63451393ffbaf14200ea5edb2369b82b8ff47cd05e6", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35305a222c2022757365724944223a20226236613331353063663334313263356666633139666434636231373361626266406365727469766f782e636f6d222c202273616c74223a202233353934623535303438363561663136227d", "TOKEN": "04068f23ad282e6362708c1ed49f4311e8efe9772b3712f655cdfee42c348de6040fcae80743939c65cbd6a86a48e773038dbfce6d48f07da543f88ed313614840", "U": "040408acfeac17af2049444ce2be7ba9f0e9c586c6009ca889bea6a2e87d16986f17bdd3c38d74e5ebd136e313d7dbd7e3cffb412861b6086a876e884e275a3c3c", "SERVER_OUTPUT": -19, "V": "0411abb8221954839f9d8e6c895f4e3df81289af00b89d1f072fca3d3c28fcc97510a8fc968ee4e0552a6559afaa2e87f53a3a8268729351203b7ca8d25b89fc47", "Y": "0bcbef64a7fcc80f9e3869328525c67dfa2cfbfbee2ae8db40d881001001795f", "X": "21e408a05c6ebdff6722605b971611a12d995f14f94bde01c265c35eed792ded", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:50Z\", \"userID\": \"b6a3150cf3412c5ffc19fd4cb173abbf@certivox.com\", \"salt\": \"3594b5504865af16\"}", "test_no": 183, "UT": "041273fb0b378cd20aea45646317d412441ab8325c769a9e964e4afcf280204cff08687a5d004fd0a3f2fea291df87dc63e656220f0a6313daa282bc6ab6ea48f5", "MS2": "13ceb375f1a5c796d519a95755fc1d4fbb75158c2a75dbeea09aea8f4f498d79", "MS1": "01bd4dc8519db84fc068da48532e8972572bd5e3432fdedc74900d82ea02337a", "CLIENT_SECRET": "0422c2743ead3cf37cd95ba163705109c900c677cf516c26fbdf30d793e3f3f9f41a1793617d82ed93c98edaaf67999a0e84d8c871ad37e05816804dd8d064659b"}, {"SS1": "1bbe31dce412ba22411cbb1de224c2c6ea17070e0aaa10d1d6075a83170a8d161a3b93e11b98c58615f756bb2de076871c79b71bf4ba041724bc6f102e129a84019d494603b569e4d7270249a82cd09b4957847b33768b892f21094b0854d8f71401e896ae5a45c4fa0f73050fb060f7a1f3b417b48619f7c8e956cfe310533c", "SS2": "225fc2958f90e21bef01b46c2eea6ca5873b5318fbd552aa8173ee783e71a8dc0f3980c83046b9168b1f4dd94a61958f9fc5feb1819747e93da90529608a8e371e4d513a904ec018501c41a00fd1b84ef3dcd48b220efbe825ee2c1da38a12a00b0a0358d54872f218fa3ab09401e64f5c5b49dce0c7a8a7e7b94e894fb2144f", "DATE": 16574, "PIN2": 9491, "PIN1": 9492, "SERVER_SECRET": "1bb27d079ae63da23ac52d82f6544f01b3807430596cc1b90b73691b4ed68a0b067c85f35b12f077d851ae1106d9becc817794994c6ca6e0f795367c029dd5ba1740018503e926e9b3ebed54292a3bb9980da4d25767ef7465e6a4a1b83dd0e01fdd4af3ddd04d4e85691119002b31107045aa06269ead94a28c4f359055d719", "SEC": "041ee99d91053a433179976eaa0587b4fa2ec5501627153bf965eafed374cf6bbb1e55e8e3400645154eeb2d13e2cd122c3171675e46a8ab78b3a9d15dbfc3dbfc", "TP2": "0404a63102183c358c044810a0cd0fa443fb237e543fa6816aa0eb0a25ab3e50341ca6030faf6ae903711cf0c7bcdd8197893cc8891624170571ffa9a1a5df8ecf", "TP1": "0410e5d536bdb830859f0b2e4e463cf6b3f8ac6a77b5ce288108ac1253bb1cb1741b6a02e30bb8e958e340f001e8a9d1fe1fe043e96cc73b9b91f234b04299d459", "CS1": "041f3e2df7e4e27d1fb0717fd6192795fc6cc304599571bbb9a1a96098e54c387d1264d71d27e8bc4443695ecbe3fc72c7e5b40f27f120b50499599c3dbaeb60f4", "CS2": "041931ea67e53abba7714a198dc946e8d3c1f564109e8df0192fb02a73edb77f6d12bb207fe3bf7b7630d9771149799f2e30a6219d29231337b8feb9a03e2851b9", "HASH_MPIN_ID_HEX": "e453bee0e99d88ccae881a2591c3c2c8f39f16168af720acf2524eda34fa4543", "TIME_PERMIT": "0417f118e01e74dff1e7798609d5119e9bd141b9247fea57cb91a776c4e132dda70db66b1c6e24e2c746f11364d2124d30894a053f62cd54f16c3cfa7efe80ddb2", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35305a222c2022757365724944223a20226432336633636162626433646562393362356333373336313064383331303931406365727469766f782e636f6d222c202273616c74223a202236313735363161326263373738653361227d", "TOKEN": "0414761dbc9c658ac52a6664ea16e81e33371acf37e2552220a072c1728745c0a90d30bd1a722a961d8f35baca7795b91621944e5cd548243b88bea04f4ef9f576", "U": "041a7133662a0ba59eacdd3f9d4c76aa757f9159dc0663bf306fbdcd5540f4c1d30f77bb90b280e0e74e68f8870f800dd8939ab75ab10d5b42cd939a1d3caf6f29", "SERVER_OUTPUT": -19, "V": "040dd5716d09deea8dd30c66dad1ce93920e2432aa93c8399a1c96990d9bb6d1f61925ee34c9417114a47051c07988371be29c8e7bbd6fe97bb6e399f47f611a4f", "Y": "0d6914cae42c4593e6108cb917d901ab977a1bc466e85a54a1ff1dd4e032fae3", "X": "1784fa8c1d7caf3cfe3f2124012cd90d5bbc4c03683504988d147c5cf7d70c11", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:50Z\", \"userID\": \"d23f3cabbd3deb93b5c373610d831091@certivox.com\", \"salt\": \"617561a2bc778e3a\"}", "test_no": 184, "UT": "04159cfde3de1467f4b1e9a23bacd1f86d562815782130cd193cc77fbbf32ade2c13987ce195d7bc1090a11194244c00e3527f421d6c53be5655ecec8199030e6c", "MS2": "0d2947f57143efbd40a2c9486d7f27582310e7f33c6d7afaf7ac27ca7d80ae92", "MS1": "1994ac257afd958e66baf927bf80276d70bfd316de2280e011cbe5d1823e699c", "CLIENT_SECRET": "04024887744f01531cc4bc691f0d5675b72a8d49ca11de94f1a51d7a47be452c341f1398b090df7fe2897eabb7e64c218fa63d0184f06aec859021cf58fcec6169"}, {"SS1": "161f688d45c3b7426a3a14d3917d3c0039c7d85e4a56b41ca9ec33c35dc0af3b08da149bb043f85dc4cccf85e80469b12e6ac22a3397a3f77625ccaf7635fd6205338a36825cc67429591d49e70c9a665f6f75bf32faff39b61157dc63f23bb60b9ca6761e9a2d7987db425dc22c6c45191916b0a55a65edfc656e2f8a8004d9", "SS2": "0dc0fe8d0587dd1b81176e897ee25f8d8bfb5e844e92071c9f15a851fda9a41b00c22fd32268928d87e6c3dd5e79b3f6e69dfb69859c53b61cbe27254ff556630f9bd9f40cddf536674e362b8191497dd2b23877924ce7d8483a4e308c98bb75126d2c7f4cc1a9d5c43ca04905332fcf1042362d001a6a76378f28b2a9fbb90f", "DATE": 16574, "PIN2": 5351, "PIN1": 5352, "SERVER_SECRET": "01c8f0df3d61852fd834cecdc0d6a48872ca30784a5ccd1249bc3da85385ed1c0fb5f6a07476dccdd0de6030d98937ebf284b01f073ea74c99298ab6889043ad050ddafb02ae6e171b849d06e6c497f7cbaa872e501b200c2348a24c369069f623d1cef844b473a11e3683a93a6642567f8d38017db20575126c1627a7347826", "SEC": "040cdce8f295a4998e4287d07710c2ca8c6d86395ef2da1ea97b53f864ef43861f140264cb1b6cd9615472a6b81d931b3498d3713afb66ff0ff8ce0568e31b44fd", "TP2": "041af9c8168534f91971e5c98ea20706fb54a427729a3ce4bde22f2222a8fa3b68025a6fef4e72e3f58aa45703b94a4384e944c1781c198f3641804639d9db7c48", "TP1": "0423286618cacd1c910a1566bae284748f6052148846ed3e8b588f0930d38f1dc40141d595db4c592b436ee752fa3be9ccf6f1966add8b84767c4093b70eaf01da", "CS1": "040c37c86edb407bf624e40d56049bbb328d9c71f36a26a582f69206632b4dde370fb9ec5fd6005b888e4a9f495a765b7f8b01aaa3dd6c96377f4c258df5f3700e", "CS2": "0403400bf60e94332300bd0e2243e198aa5c9e339d2682a6fe099a868ad1618fdd0493deb0b99200fc0b51d7963235b3e38c9a2170881a72ced2b0229fd714c6c0", "HASH_MPIN_ID_HEX": "a889d2c36f3ba8dd4d5f8cb07a413521fa5f1ae323ea3e68d5388b7bd1f69bfd", "TIME_PERMIT": "040860f88bd97061de8ada760efcecee6b61541bde44f721345a54f71ee7b5bb10144f898745baaa84cc2eaeb61b80d85c68bf84e613e8bb458d488eec9310e821", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35305a222c2022757365724944223a20223531393634363766386533353763333637656236656565643631623839393935406365727469766f782e636f6d222c202273616c74223a202234643939643330363262643666333031227d", "TOKEN": "041405c1beb5a1b8488e20c25ef4667cdc1485771a678c63dcc79c33a18c9ad767041b56a205f876ecf4bfdb421536ded876a01ee45da765e59683f034efa0924f", "U": "040a6bae163d8d4283fe0f16fc9b911b7327861a589dfbc25e8001fe5f064718671b125537d0845c45c70265e424ceeefa38a5d0a3dde2c2a859863b3088298ed3", "SERVER_OUTPUT": -19, "V": "040653e7b45c2f03af884ec456bfdd48bee50cee72b5887738c227f7afcb15831a0110bead1e37a078001a0ef538444f75445c9cbdf500f8bee8b014a52c37bd7c", "Y": "0200d02cbea3ee53dc906fb436f2c53b49843aa965889e71b8552d3308eeb796", "X": "18cc26b106fdb2893869aaeb82aca0a81668c7c5a911a70d07f5c6bde9269d1e", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:50Z\", \"userID\": \"5196467f8e357c367eb6eeed61b89995@certivox.com\", \"salt\": \"4d99d3062bd6f301\"}", "test_no": 185, "UT": "04017942776de1bbecd1f09dadccc5336a63837117fc0fde9b75cdd8400817f1a51206b73479c47382997cd43f5e30480dcec38eec59468699249aa0f85c15b86a", "MS2": "0d47cf8da5c65cb0902b213a4700516832c094824453a05c0e5fdd4d5c7dab90", "MS1": "14c81f3f76bf36d5bc83d7b63cb7eed07b18fc7f62ed9a8ed8fb5dcf39a3508d", "CLIENT_SECRET": "041de3d781ae88886e54872a3da6d938a9c97ade3d02dde84eba9f1264876a2135226e44c2fa22443a188cf0d382d33006e7f095bef47d88f6c23b2f5c807f8563"}, {"SS1": "091eed0a01dae0b4243ac32196905c357957923c875d5e72696f062db2d3a6f7098df006c27326b90d5f8b5265d6b9431c897c224bcb8f4b974a65ab4d9f21000eacdceed480ac67da9aa3c04b8a610595f5e8e542b9dd18aa629cd41ae0cc851fd5d95708933bc72bf80aadc15f88d8563c003cd44ec65f2d30a3afdef6cdde", "SS2": "01922f0a37dba0a3bc27b36704dd96134b2ba9dc561675f246e4b0b2a18b98e306934f211a7335af955b9223bccd357aed21b70b7f79e3000a88916a4bb391e00eb290d4d684eea33b5334b7196f8df4631e9c8e72c420edffb467aae8a856d1089f2c4e521a3d28266939147b54ce131f3b837763c01e6cc2568198b0a9716a", "DATE": 16574, "PIN2": 5492, "PIN1": 5493, "SERVER_SECRET": "0bf3a06f168c50b4269c836cc0feef52eeacf14f343ba959a9f248dce4b33b591f25ff96191611c378d6ca413eaabff8457f64f55766d8d1bd7588add6cdfcaf0105d9b3744bdeddebccf86525a4a8e16574c5c456f59404c397eedee4f348a70b0788574b7275a9fb542cca610ff70164368173d4fa0bbbe02698d147c3442d", "SEC": "0419464006a6ebf8e95634ef8270f7f755b7b02d85ec5ea7c358b24fc5f15fce1f102ee9aab72f43583126118af793085445b1e775de939b87006239781308bbb3", "TP2": "0402110b01336eaa9a9e97a5c7322dd7a525cb9a41ae6dce08acb90747935892bb201ba540fcbff8a37a6d795adcb67548d0dc572a5c870b79c1fbddb7de0166bf", "TP1": "0406b6a0da152f8dee3a33332399fd38b58da4238856400600f0a1e67847a346b605426fa6cb0c9dc4e44b76e23fc9e8bc403c99264c7235f5c094b0e01730b47a", "CS1": "04001c741abdb81cc9b0e602b2c3ffb6506449ad5356b78ffa9a81efc8c55010f723473667ce0290d4a0373cfaeff420b81e09dc9c1464d28e36d1f46614e02b9f", "CS2": "0419ca28e5459c84a7cacebf29e800824f9ad0aa194074221c0d624a0db2a4a5160438764822f5a7f0977af78473350e51b1ca28cc89cb641c6e3ffe6b14b8baf8", "HASH_MPIN_ID_HEX": "8b96c8d449ad13958f54440a6ba852f847d5fd281b3519f21b7bd40dc3cb8c6f", "TIME_PERMIT": "0423b6d24435f1e9f8c62ec3f8a24772c9c39725a1867144f63281e27bd873fb742008d44218d7e9fcdf0fe90cf10570e93c5533068efe91e5834ca656e9b01eff", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35305a222c2022757365724944223a20223063623235643565386262346334373262313466316130386233323337613761406365727469766f782e636f6d222c202273616c74223a202263646631343035366331303364353663227d", "TOKEN": "0409b1411de4dd284e5f3d01167379d7b7c2b72b9bff2a4a05d98a313fee19bd9c024d57d5f3f248cbc25309069d4f7b5a1953ab685040ba7a414a2d61ee020dd6", "U": "0402dfcb52f5113281837a88681951321254f09fd9ab54cd6ebb52c61da633ab16076571d5c9d852c33c1971065960adc42217f2c9a0c083963b9e3b8843254908", "SERVER_OUTPUT": -19, "V": "041a37d360d15d5789094c328857870cf947af25de831e2560b30bf5d49c164f1105a1126ad2ea19653b66de91494ce9d711aa758c5871887a47becf6026c2eb6c", "Y": "11f2cd06b59bd60d28991c64b06ab6241d1b20cdb00908965f669b4903cdd3c9", "X": "1e54de4ca4b32f3f219e8ec181984e3c912f1bbf79c9272ae24043f287b26380", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:50Z\", \"userID\": \"0cb25d5e8bb4c472b14f1a08b3237a7a@certivox.com\", \"salt\": \"cdf14056c103d56c\"}", "test_no": 186, "UT": "040f8cb44eade988b1e200e74b93ab3a3ecb40642376e49a7641d65879918e4c5e14ab1094e562e9f0b8b57bf2e02ef12bca063812c5fbec8cc980335511130a32", "MS2": "038f1d92607fc272e056bdc1915c8b3e8977e9aa24dbfbca954c91a3de6fdc09", "MS1": "182f1361f7c05a00f326b1a5a5fb3fb96a2796b1a27b30482f908c5c9f9d6c3c", "CLIENT_SECRET": "040d3967d317828fddbc3f235989d94b70072f9c57197b1cd32b188563bd9b9c41016cddf63ed83883e0f2799996229384ca4bd511e89af8c12464b7430af0184a"}, {"SS1": "0322691ea6324ea9c4d3184b5770ed1e25e51d6af21c1a4582b0cb18424ff09516c7d4ca66959a794a6c90593973ca50dc60fce431c04ee812cfe816c0576cbf165d174b05be8a6698830f979c105f3a89776c86fef11e6930ff803b9453e01520524a765f39e4d29a4e50f61338e6d642a283f0a84ef8e57b54720f01e1cfc3", "SS2": "0cf4741d11585ef366f25d1e6d344d4f36d8a937865bbb7f751b4c941545efde0d37ca543426332fd852ddc9fbe845f3479ca809d77a7381bcf7b6eda480ae8e1168f5069ce624ac0233c71b1cad8cc8e542cd54c39050b52cfd363b81261d281904d7cd82c54f598bd292b86235967bf39c5de6c8f1ad0f58903ea66c0ded8e", "DATE": 16574, "PIN2": 2392, "PIN1": 2393, "SERVER_SECRET": "22d90a907c10cedd49ba5c3207633e2f6d0afd6cb80b2594b623f124e716311a16c7af8157695d01aadd4f57d4abc0b923341c4704238afa9b937f9fd30f6f081feda633b5feeba7fb81bd3a9c02171aa245a9900b3680e54e0c0f6ef132563a103f5ebff7cc5aecee471bd04956cfc7ca471a0d5c271b34587286eac8a71766", "SEC": "040e3a3a26284fe5e37c62896c137cbc35687687999b084a7cfdf01b54a2463bc504a88fdd1549649d90c124c1f277a637268b8504d0eec69683399f14c3a1b93c", "TP2": "0408058488ac1a666b39f71ae697b00a2e9f891c23a36b88abac61e2667c92ffb401eb08664f09f458d0bc873efda15a826431ee839be4d4f084d7a12db9034929", "TP1": "0422cafe84b427700b644c9c329cc717082e14979bf6b81251b9f9af2adc86be9210ec3c22eeab14efee82f3c9cf72cc18cf37dd1e9621ba592b42e82676b52c5c", "CS1": "040c44ca05e2397f290070faf32cb89e6dce2d042d0e6e7b39b1042e0cc0cade4a0aa1fc31a9299d6674e8125595ec7be376ee3c0bac4d4929f8ce616cff3061bc", "CS2": "041fbb6437a9c7eb15903ffb5106820fd46a180043bc29b3bb08fff552d2110062042e3c92f183eeaf57b45a07d169b79c3a8a8a319892e83f07436491e6916fdf", "HASH_MPIN_ID_HEX": "28a859d159b6a869549e0bc5a2a584a94d44c0bf5a9132df9a3899408d84710e", "TIME_PERMIT": "040b1af0fe4e92347bbf53688960dccbbdaa2ec44aaeeeb1b55dcddc00686a003d18c3e65bb70e1f3d7d4fba3570a97e66186352a26a86cf2ce2aabef256420780", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35305a222c2022757365724944223a20223061623264366233393262613433393765626138663036346565353362343565406365727469766f782e636f6d222c202273616c74223a202235646162353230633936336536616433227d", "TOKEN": "0419ebda18bc4e5ebf529379ee9af677ca0cda6c97c47a5866164ce58506b9fd4507d000be5a7f8a35400a2549e822a8a00027c2633f6d4c74a8c394efa831b8df", "U": "041cbb005f34f82ad8b5de92c3d4605b9a51bccc9a9efc4f7446998fb9d2eb41350fc97e26d1da998fce7fd7345c7de77d20555c83cffa8cf9c1533cc3efd44997", "SERVER_OUTPUT": -19, "V": "04147c97cf891ebae5f5ff45e115b524b84f7e92c8229cb9edec5aa5f225f09a9703173be3820e3de97c0c51ffb13010447fbb62a60a05bdb1ad3fd3d2c5be3b4c", "Y": "1b65540ea9ae711ee48988b4653bb6284a8b9acb0c6453f80fb6f2e68d8e80d5", "X": "0d46d1c717e3184d4d8898a35f3f698e5034a71ef9aa003fdd6b60e07a5b36d7", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:50Z\", \"userID\": \"0ab2d6b392ba4397eba8f064ee53b45e@certivox.com\", \"salt\": \"5dab520c963e6ad3\"}", "test_no": 187, "UT": "040ec64fc679965d79e0ae2fd9966465d383d1132959bbc39d176a6ddd3f6540ae0cbd0f2915bc83b351935f547aefd939319a3298f5d84013f01db273742869be", "MS2": "23a2bc3f9cfbcd816270392c137a9fa75402888252b02923edf9441b80844e28", "MS1": "1120b0b0f030bc0a9128feeba6ec621ef0b76962c2e35aac7843e5e19cf46928", "CLIENT_SECRET": "0420c5bb1f01dfec1260c644922e1c5363a3c46d72a298722902ad409c6e50ca60024fdc468b3dacb83a569d2774100dc4fd14cd28e69842c306d9188f4bb53d58"}, {"SS1": "0d3ec1057f7be3259513505931dcfc90074bbc608a45df55b68c43eceb91427015cf69bd12a4afb24f57b894a274efe5d0e204cc2d87ef03259b606fb47fdbf823a2584e26b6973eb819d17c2262cadd09bf2d862c2b9d38dfccab839f2d12441784792e8dd97d792bd0f25784b8acded90ea42c71efd068eb4c14ed5e1a5ea0", "SS2": "047b16df7a4d8ea0594d4072de90bdbbafe8a1172c537178dc048929857a419007a66106f9f4d290439590edbe5d24bc5367dda7e047ea0a9c996aa5de5e6f820a1c8be6ef107943a64d4cac39f77fe17bd622dc390788f43b210b98ffa34af821d4a4a90b89c90ce3a077937afda174dc94fa2001ef2f9cf3ee80ba89b8f2c7", "DATE": 16574, "PIN2": 6324, "PIN1": 6325, "SERVER_SECRET": "10c19ddf215d6dabc64682af320f9f136aa81ee0b08e8e4d6ad78cd938ef1846010c9ee237792b3f96fd56a4e6826e05d85a5cbef471d2697f265641b08cd093073d22ae006bb30e7008118f3bc97a7a841959458c9bfb5dec9c2f1e401d186d193e60913d4e61d39589fb6b76b1635c1e6795ea642287897309e822d4bcadef", "SEC": "040b12780ef8cc4b3aa4876ac4e52299e38d3937b05bf505d66fad7b451f2cc2571c5e58fff52d3b88a472e03dea56ad4f8094666b90bfa62687770342751464e6", "TP2": "040354c8d49fbadd2df00fb1bb7a568674adf2256bf0eafbf1d17c34cefd9663b610c9ed157e31dacf49a004847ce7a4b9b93f72c8c3a3c2d0f998c28bf598c63e", "TP1": "0421fee75f89acb0467abc00f0e393b6cb5b84c369b11bd28809585f962a94184212329db3553fce892fb0d884344eeab90cd753eb8a160c9373ae4d13aa48a87a", "CS1": "0405f1419e4598619d6d1c5d6821761f8013243b90f8c9c17cc23099df170c4c0b08e826a426ba38f868996a1f4c09fd4ad971be80d26f5fd7980d0ad1cd9d67a1", "CS2": "0409305d2a295bfd512b8e201859528adcbcb0e574b6647777da249ea27b5b9e740a23f5b55365129ed23f8fd17c69d74238123ee8a194872636045acbb43104c8", "HASH_MPIN_ID_HEX": "cdc074dc4e7a9d55f5c83ee371985a6c35f86ec19e7c6ff19506b30d7e62b110", "TIME_PERMIT": "0401d79c116390ceb05c1fd790a750aaf60175e8ec8324a997224a2a853d79730d08dc3ad4baf04b87461d330c232216ec820d067dee1ba4aa0ec6f851140796c7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35305a222c2022757365724944223a20226532376339613131663965336337323236303664323933326565316466653061406365727469766f782e636f6d222c202273616c74223a202237663836323461616665343665363862227d", "TOKEN": "04019ffaea0628fb6f6418a284eafdc4027b8b97effdb8fdf5b6600190ef9481c00bc7e079cad1126eda7b1e6a93d768faff8794d19e1608ea987e9343375cc23c", "U": "04208fe74e15db6fb85674b87158abc2a93a8a93fb3f81b63f7ef47bd6a1baed1b0c5a43dd661931b915c777340fd7fdf52e0ebc526cfecf4da1baac7d2291a80e", "SERVER_OUTPUT": -19, "V": "0411c9148f90da0c1e87fff319ccd698caabf7dd1bebd05ab285623a98cf37c727185a3f13649671561440c7b15f16b9c6fe7b2fe395fe54af3af82973bb4d4f8f", "Y": "05cf25973dac92ec3301d223008e16cac0eb59977bd5f28c73d35ab8d54ff10f", "X": "0a480294ae9f5e1f0d03d33b4a6b080dce96c5179876f00da5c61b5649929415", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:50Z\", \"userID\": \"e27c9a11f9e3c722606d2932ee1dfe0a@certivox.com\", \"salt\": \"7f8624aafe46e68b\"}", "test_no": 188, "UT": "041f19add7150c2cbacac77273447781ec836ad0772f33a7ee22fc7c3d8e212f971df2400df90865ff300b7a24796778010abdfb71b59d270be65beef9d7d13751", "MS2": "1466c0f9eae762442872683bd83c99b96567ae799449a0702451205ba264f343", "MS1": "2027d23c6fe37d111537110e23ebeceed548cd67e3c2b638c50247c45dae860e", "CLIENT_SECRET": "04134964aa7cda9497f21ad1495cfbd58e59946834a2e9f21919c496d2ebde3c6223468624260c36075c176b29282dbf6f6b78a7661cada5c02d3313e29994a1a1"}, {"SS1": "1790a10a2592548f11ba4b2661453c2852de3c8b40a60ca1187124b8233cc0b5213a04de756afe1530fadde5d9ea50184bba3833c4bfd9f4b9a9165398b5eaa51e1023a82a162ee4727063a3cd4f3fed1f769efb7ff2d7192c2729730639399c1b06fb72702741cc1887936acb52c426effbddbe751836acb5f7670c22cfcc44", "SS2": "058878402df7e8a108eee462285da27738977c1fe4909d994b2ec963c7a3371c07cb2ca1719ef4898e675153c823cbf92124d16e8efc9c091e62b4f05b4f5c1d0efd579d282d2e188f8c892b0c6d30b6b1e2943d87b1b4f21be0be62e2bb051b1d5486414f374fa717a661ce5f3bc3b537efaa26ec073a92562f08fba0fb4ae3", "DATE": 16574, "PIN2": 8934, "PIN1": 8935, "SERVER_SECRET": "04e41f8fe562d449bd45caa6ff328c03cf4422f9cf122a7f6cc0a89b5122587102c575ad057971b11f68f7a5be0158f7cb405270ec424d8de5488a206b96e5761cfbc76772e58109e80e872d34699fde023a5f332b1715c32eeef29fee62b7e720fb3d2ac97f0f45802043fe7f7123c2dab98b2e81feaf10232f4df51aec0fcc", "SEC": "042114f5d39d274a3badbf7103f1d7b4f2ad3eacbef817ad77161fa14bfdfb44ea07375cc2148fa69e13c26ae2a2c75bddbf101e836fb9f9615a8d4d79ce314dee", "TP2": "040d115297fd143b70955307c64084213098a3eb16228cf730496157dd00eb6c500c35444a5a1435cf6fe88b1969606035aa2384a8352762be696192086e192dc0", "TP1": "0422c30fbfa18372cf86c2c9cf4fe35e2dc1be59956ceff0f6441b904e45924fa512a29231f6c51b11bb270dbfe7a022fad84f4d54f7a13d4b7c4773461a00c637", "CS1": "040ad2fa2e919d531739afeb90bf13ff0c3804cf9ba0f147389d499dccf93c0e92170cd2265ab6f911f9966402489b334cbd9403dfff5ae6f0ee7e91d5fefbbf1a", "CS2": "04158fe4f7fdf0e0abf5f207ed9d5513d6c893c225144603552cd666cebb0877300b2e3c8bb33a835c114480bd0d616fd627c5e3fd3101a1a19d44e448a3c76644", "HASH_MPIN_ID_HEX": "9f6d088f15e112e52c1d8b4ebebbd62b723ed307be0b807a3dfeca86afb309b5", "TIME_PERMIT": "0420d24107ed0e2a1133d394f34cf47f603185e7625caff6ee429d1ac384d4e48003101fce70ff468bb938e23e165335000c7b37eae98b02a26abb9b0d182784c5", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35305a222c2022757365724944223a20223732336537363163323763363032376366643236363134613933323361303665406365727469766f782e636f6d222c202273616c74223a202261313261323663313461623335313538227d", "TOKEN": "040eebfe651963ba02c127d5c200245cc3d7db3977804025bf713f89c150be54660b59f6dc5ec28fb3108e6ca17260a1f7b027bd1dfbd5b1567400b319d4318a2a", "U": "04145462bf5873f407b63e9e2c55d0d59ecfc7ef8b2f2c5b63a92cb7c4ba02e7e612cbd88c189d1a3f1a812a44a4707db2f32ff9f2e12155441b568fdc1bf2e563", "SERVER_OUTPUT": -19, "V": "040ed1749be2722957a5cc8af6826873def3df3d1f687ab56af3fccdbf2cc5a1470ee95d030e79bcd2e5f0cd67ccbce914190a27a11e01b1da65680dd4b4db332b", "Y": "1b86681926bc75f784fe1b54adfd5dd7f507d8676740c54781c45fa470e050d3", "X": "20c925fa695b477ffaebf50dfc12f462cffcb445b8f634f3f4cf7f840c47ef6b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:50Z\", \"userID\": \"723e761c27c6027cfd26614a9323a06e@certivox.com\", \"salt\": \"a12a26c14ab35158\"}", "test_no": 189, "UT": "0403121fd56ce3e89f8754cdd95abc4d37fc03f361db40f5f472ce12b15fadd88a13c982b98fd9e0821e3df4f4dda957d3dd550f24e9c66c8df357efd5f5e39748", "MS2": "00251a473595f4362b916514a2ea911570aaf179ed1c127d6a63ff87bb09597d", "MS1": "014cbf28023ec52e939cbb1db06b040948cf0e7edd93dba953a88491baa3f6e3", "CLIENT_SECRET": "04194386449efb9168ca1c66134b30031262ea7905a9e48e5d103bcd805a5c20ce130372b66c4428257f7314c4031a6bc8f7949370ce3ebcec10ccebe2d89fb9e3"}, {"SS1": "0f1fddeec4b6fff791f23fcc51b0a42ee28eb2625ca21867aa16a4a66ee1512616c1d3d252507701cc34f43d5b7742380c9384f30e88b29cebc5a12ebb62be2b0f7c59078cf60a530e7b0a0666ceafbb3a749637ae0c0869f5b55a6d0eaf53bd099d627ff80024df19631e342dcd12740ae0061df2241257379e91547c6930c4", "SS2": "102c8d13c5ee89117e4edad4ced829f07364e4e1646f3c88a8ca3d0c707027ec2129c52fd6c647ebb1ae1d0cfa33a8753daecebcc78381cd708e46c64b6b278f23b3a67e076693c9d7385c0e789660b8cffef4ab9edc5de9b8d5b86f862bb75f228c8b54d7a77e3ceb9b82f6fd56efddf66aba79734d94694acc4601c30e612f", "DATE": 16574, "PIN2": 7723, "PIN1": 7724, "SERVER_SECRET": "018add7da9c80d053189bc9e0afd5269eb156aa6650fc942d3ded8560c21728e0e9cef4d01199189c507a4366f93ebfb77e1297b901cebdb5cdff9a783f74510017c3600e1c90a189873b69c651524feda9bb90cb473fbb45674c544dc1800a1176cce5e8ac51778db72ffc67498358db645ec1f9a330701d17084fde33913ae", "SEC": "0409068bdc3ad2c55356e40f971ba2866b233a184982d6170215dfebc455153ce004ebfa04c2e341e1af01fcd5a1992988d8307faed56b4cadfaa4bff0bdcf92a5", "TP2": "0415fe72ec708df4a282053a781e16b0b1948ab6696e0bb0db90b3e53e55f3ba5519b7021039efde0dc6afd898cf20b09d3c8c5884ec7e3cc7733f93a5329358da", "TP1": "0417d8e5b0f023849dd97ed9fc3e0c7c25bc0df35436b78f907374315f532f383822e283a74c29ecacb611e33099f076a0cb6db6f6146229b37aa8f83fc6bc5299", "CS1": "0418e6457cbab4dae7b5e6027ff4ed6f565435c5cfa9c9562a467eb5d5e0e377e3097330ba4d8253f915ec893f7308475134c562402d8021d1c01af9f9783ce63c", "CS2": "04078768a8d5554e2b781a12bd4a8d4baa52de1b2420ec0399c137d44989d75366068a2d35583d2e4ee576e6996ce6bc1e42580ffd63f8b09727809884b4d87846", "HASH_MPIN_ID_HEX": "15d501be59160bf10305943e7dd67f2b9232b177a4a346a7583f9c943b8739c3", "TIME_PERMIT": "040eb88298005c26a90408a88eb3f32cf286130f2c32df1a59ad8ad2cbc866e3a90b3cc9292bf0db45532060206f435ca53a656d0476aa994c208d0e78f6de5944", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223533383537663463383561316537393234303664656263323161353336313665406365727469766f782e636f6d222c202273616c74223a202237336530323939353836336565393962227d", "TOKEN": "041369ddd973911db7db6e7dbe59e626f52fe6618613f3814cad45348c012c2e37154c84fa8ee0a37e452b4e900a6709556ecbeecef9f6306feb1fbf339a3ccaf7", "U": "0412fd8b16347e0941d190c1925b077aecea6983b4c6712dff54ea6c9dd81de3091cab171f44329740e65b5d1e866f6d0924051f654e7c8b2ff8cbdfd0e21960e3", "SERVER_OUTPUT": -19, "V": "0401fe242b4e3e05e66d16f5713a83ac98047e6a98127dcebf2d549e617d2ba36d1ac07ff0cb2971619c1bf25b1c917c414e62dbd5868c3f14052d39730abc0703", "Y": "1c0ecdc0ca6aab63597f619af890ee2f87d7091de34656e678235ff963b513b0", "X": "20dc5e440655c92d5aca417e3ece0eb8c03520284a5d20e6a5fada45777eafb5", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"53857f4c85a1e792406debc21a53616e@certivox.com\", \"salt\": \"73e02995863ee99b\"}", "test_no": 190, "UT": "040cc7807c1b7408fd39129aa1c6bdf2364faec522413469d77b1b6b8ce7451f3401ed5af4236b46946f47b4ac198ef0e3392e4debf7b2c51f5907fd3d5b3746e2", "MS2": "1024d2689c125f809a37469f5ed1ed27e6105059c5100fd2adfe452caa18db93", "MS1": "14c3a542bce45d9ed3b2cd3586fb6c4a5ce99bc91a1d891a6fc4f9799a7cb353", "CLIENT_SECRET": "04038b9d3f946fdaf255342412e2aaf37f8b43c49b7bc2d55da6297e1d2f53143700f57528ca96c25349d78560e5e1c6e018aac52b148e1d2333ad16ce26a3c6d0"}, {"SS1": "1fec9aa7134b0d29d629932e1e08f9405d1f5079a514d9a5a30cd3bd21f7f40e15bbf18cbf6c56deb7545ff1ea2fd3686637aa6fb3297ada388a7a3b973570c90ee7c0ee21f99d730c7ed7d2b2d1162b3c410b9a00e18b2e9af9246e6a6406b60ef6796630620fc73990698a0226442f1f27fc371a75e015aa0464db372fd254", "SS2": "16529c8f74a128d41d1d06e363f0938a6322bd1e349b3c270c141eeda7ffd10120cef6e98d6462b118bf49de437e129180743c9049bf355e762a1384d1edeabc001f7abd92f5189bec740b205f2f5076849c21ccb44dadd371f26bf8259ea89c01c479df1b20cc7921241f392013dcfe1a981e2c3181b17ffe3a13c46a57bed3", "DATE": 16574, "PIN2": 3938, "PIN1": 3939, "SERVER_SECRET": "03a0c3a65d6e99158677b53eba4487d5930ca5e27bceca0f90ef2f26744db97d0216dc51b0b9f6635b189c01e829c92c910fde94619c02dbad91ee9370d165022343e9641ba0bd72e0ff0efa6af48c914499f8da9ff412207b68248f48ed335a0c36e68f460a2a383b4feb374cf2db285866e054f99edccfe42e6dac9da50e3f", "SEC": "04214b4b039005c386feb095da04b6d92bad07f334508590104cd2ce25e9c751220bedb582934312d92d8b5a3a6d6ec019ec1d6ba63a89ec9196d6dd0388fa3a32", "TP2": "04196977fa79252afe9c783e8845b2b7a42bfedc882628c5072d2cac0ddb21624413f31259a752df5cc5158a44fbe5b0d6b6cfeaf54db1add88f4d13221706e3e2", "TP1": "04077b35a1dfffff8bf8b92189ae51d1d42ab9d168c688346c1d1ef063595b2fb81114e779c2461b52c2cca255d80497efc58038a6d6e3999bd9d7222eeb5bf87f", "CS1": "0419bfb048e1be411f32a2adc95e9b5c29c371277fd1ba3cf639d0472d2867cdb31f6e7dabe1278b7692f1c4b8886de3042cdd22ec7c554e57f87e31adf63d0767", "CS2": "04191e53ce5640b56ff91500b3a5746149e920b75622af2c6dabfa20ecb073a2871d4f942cbfee598898964631d8cafd820f6afe35932717387eed7874bf1ab520", "HASH_MPIN_ID_HEX": "9178bb2a6b2054a8ee3cb2f49244db4f5b858e4ed116358683350d6f0d82b100", "TIME_PERMIT": "041eff172c7b33272fdf59e3760c5840ed46700cda9b72d290b8715810c28554a6002a92185d47e3a7e7680bc5439fc61332a937f856ba9419d94cb53543bd292b", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223966643631303938373932333436373061316137616165663766336564323961406365727469766f782e636f6d222c202273616c74223a202231666132393964623363386537353335227d", "TOKEN": "041293e646545fc631c20f8e47a49732d9bf5fdad882a9b603b2d4934b2160a4e414fe97570e1590f3c18d2f7f903f8ca0a416aab919e9347efb178b232af5b268", "U": "040ae5c460f228a1b796eaca17b079e36b8d3f0bd79d6ec0b95d449ba3dc5f91be009e3eb24a49d77843c155ec1167bc8df681f8c48be2b2e2d77cb55b20a2e41c", "SERVER_OUTPUT": -19, "V": "041f0ed38019e985fb08341678bd58ca33848f3da13d691e46bcf8be6f019fbd5822903d75a21b3aa6b2e1e21822835eb68fd7ee4a518f9e5bf0cc8d1248378294", "Y": "174115f023863819c0f2dad1b820926c8c73f6daeaf71b912976c82e5e2fa078", "X": "12a01af944fb7610ce194ace3abec30c5a97a600edf2c8d194c45ef37fd66f9e", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"9fd6109879234670a1a7aaef7f3ed29a@certivox.com\", \"salt\": \"1fa299db3c8e7535\"}", "test_no": 191, "UT": "040e17e1f7b06cc5a9d1995c86f8b91bcf4746f92892f6386c1fe19a78dc3e7aa8172411d9fc513f82a2270847a0822850600b52cbf086b6e1c3bb9562e255b5d7", "MS2": "18fcb05a4c30defb7039e897ff20f549a7b3ac6e62a4462057bad50bf25621a6", "MS1": "0069f43f0326244a7a75f7a25dc5273734c848f16547d81c9ef87fe628a95d01", "CLIENT_SECRET": "0406d76ea7ad41da622ad97316f0202250a7cde97c0b727bc7ec8bf9a58f53395f0e4cb6996e12a3a35532135043b76de4bcb66287ac1337dec159d5aa93f047e3"}, {"SS1": "1472b88a37b1479a4d13bb305616e10f073450cf5c5a8b6b1dc7f7efc6ef0638049558bd5055fe9cef48d673ab29e3353c3f2c1346398bf010c82affd4d3125a090d4bfbb0f4f0b3cc5f958011d66e9683baa464a836136df9b94f78f4277b27013223a749d3b19eaeb285df1379925b8fda8d2d09fb2b1ebb1e0c84ab33650a", "SS2": "0e690f5afd8f29c3f7d44555ba5ec9811bc353b4c7ee2b70b5575c3535bed99c108061568a896d08bd8855dd8858a98676a20d080ecc999da054c122c11bd41310ef87739f5b8562e350aad472def518c91fe4f0564378996d4aeb5b5af2b0e706b95a5d81d24664de0c6d79830e01556d7517c3327ac9d5b27b74df4c2053db", "DATE": 16574, "PIN2": 7123, "PIN1": 7124, "SERVER_SECRET": "1435a97d9d5b57a11cd3e3af06d1c3d599b5c8ba0a13a5abf94ca55e14dce3bb0cac0c573d20bd251294a202b48605801ed18aa037ab3c32102149a4cc0404f90edf7cb49fcaffd5c53320c475696d67551f5d83cee9c574aecf9b3c6644a66c10028a57d0e31c5d7c121d20c1116eb78ecb3641c3ba5bd4fb2987a1174f6724", "SEC": "041801acb4b274b2bab3873f74dbbe0edb39be34a10f3565fabbe458c37b96935e16fe77e2fa022dc0a7771fce010a82fb5a2d769a76cc50cd5cad22d2cfea32b6", "TP2": "042325cb4e97c1f5e8c137c52ebc71b1a7c690eadf3bc6d6b2f6ab468a9d9dee462360802b15016d0dcd8e1042eaeb7acbfcbcff57179c46dd5f09bdc8a31e789a", "TP1": "040c17d5ee1e56d145253a3287c5dff4296f043e657360ac6414431ac735579a1c1aa765c1d5e3e567f048d6632495f894d3b132f213ab028f3fc52e46f3f5d3e8", "CS1": "0400a892eeb6878bd0c78b2b7a098119a452a9f6db4e37484cc0aeca77cc3ddd560695d8c299f854074d9d62beb483613e932da48b69d859b8010081549a0224eb", "CS2": "0416e28545a66071cba72eccaff161f8c0a9b2b385c8d48c155787f6d92408ce8219a993f39c198f0ed95dda258475bc87d94460fb6a0e4b159916f4107ae0931b", "HASH_MPIN_ID_HEX": "5c9b0c8bc8772fd166bc5b0e9979ba9c35c6176f949cce2a030543d599ecb5aa", "TIME_PERMIT": "040728f38b441313fad16a130849bb1bf18026e814c562b288ca2b842667914c4b07d38d62fa7bba88a250372a41b41ba0d45610744b796274e30f83bacc847a91", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223731643762306531383733626461333164643130653539396433303964613634406365727469766f782e636f6d222c202273616c74223a202265383030316633366137333331626335227d", "TOKEN": "04079c5b917db8023e367000772fad99c8f7f3ff35e7b133a4a59805ba3891a6bd00e4c1319aca1aabd55dbf365610f796a64d64d79227a57947578c8f0052ce38", "U": "04149d012a197d484b3da848f89b94dc1db3c0b0139d3df85c85e2a94064e884b204e654cca7a91827c91276c75905795ae88fd8deaab52712da2049ca230b2fb1", "SERVER_OUTPUT": -19, "V": "04232f459c123a6e592460ebb0ab66444cb58ab8526a4161e5b6590d162a1eb68604bed43991b78d200297218ad4799547ffbef7c0d75da3452b642e39d4386b7e", "Y": "0b4533d7ef0c5da6ac13c3e5664d279302c2b986cbcd255053fd0f81b67b701d", "X": "0085dabc9914c5b8c05b6629a91deccd2c7d6327f1c613a20ae0c4900e9af0f2", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"71d7b0e1873bda31dd10e599d309da64@certivox.com\", \"salt\": \"e8001f36a7331bc5\"}", "test_no": 192, "UT": "0415ffc411f4366549e764e720bb3d3a44160a600face5a57f6f78b1e1695f47c912f6203b4ad5c640895d807dc83db8c0f5f825879f0d472c75b8850c3886d4f0", "MS2": "008d74957097895817d01f433e88cc9359b1c0ba16a1bcbaabe80adb6e0f2a35", "MS1": "1a2a7f786e8a54f00c052610d7eceb25301a9e0c45888748ed9440c385998cd5", "CLIENT_SECRET": "040f87fdc8fb2c34c1a1713d031a6efa8232aff63b82a405d5d6a321ef10575467029fc0cee578648a1fd17dd47ca27ecfe534ccd430802f1d3bf66bdd74bd043c"}, {"SS1": "1235580430a9129a2e12e1caba62da873b956bf6037cbcae6f714324911fb97318312151d20e8d3f8a9c0d980b390fcb00202e35ccf8ea7b4f40adc5461224e103e0ecb457192f7955442e02b19702099b3e9a22ee6660ada44cffbda61d61f1233f290fe6ba0f2976ed266fed91203658cfaa0d32c3425df2260bd327052f47", "SS2": "010f6ac2b5d7596d26b948d9245fb0a59038a4eb34f34a4ea327039af6730254072825e2444ba3426aed5c318ae454c1de388ce9ccb8784dae31a3a4669566811412677537561e3dc019c17568df073cdc520e1b2966a2c890bd611bacd4c57f0a46d6918b7a5bbecc976d9ec12ca3046bef44c53cb05270a197ed8ee8f3359d", "DATE": 16574, "PIN2": 5737, "PIN1": 5738, "SERVER_SECRET": "192ee014cef7e35f806d0bae16391a40e3c95869319ad3649bb96fe9d3e4eb511ec6890b02cc50488d5dc381c2d2fb275d0883f8de706f37df59f59a9c79fad200485c12df91f4ccd21766cd1c08ea6a0fb5f5899ef556f8768b8ff89067db381316d615d7aad158a596552a2b304f6a087a801f79a4b094b855c584a1442357", "SEC": "04213b7ac2b515bf00c246d350638a5001c8baf724ff16396a35c2e3ef547d97931b5d13da9eb44f958f41889082082c8a021e2bf9c277151833388b80972a51ab", "TP2": "040b3dd92a46c74ac642ff37114e6c1ddb761f02e58ea4da887be474628ecf6b3d08d78a63c6ca996687ade9097ce78d90f50b2727c4fc70cfcf550a34516bfccc", "TP1": "0407815cef43bd53da698941d2ef4f4bcd3eae4750e827fdcf070ff893176fab3b1970844f144a825a76d7a3f6380f76c6fe1bcb6cd1d1b8dc47075b459bd3d718", "CS1": "040673618752cfed57508969114e5944d92a8f1b9ad2668195104fc3768cc280f91847822002a55e8fd6156843c8b5e472a391b4f208e87eb6414096eb619467e8", "CS2": "04071eb3f288557f42fc06a18875f38a778cbdabb130e2440c6560398dfc1f60281a2ed406e79611bd453721e908d0f4795f749f969e98685a480969138fc5f8ee", "HASH_MPIN_ID_HEX": "c2ab680deb13dc6952075ea477a6d823c9bb66750c833f3baea6c9fdb90a7cd3", "TIME_PERMIT": "041588a02c072b80bec0ce4f9bdad082f43a0328180de30cc88737052aa3e36f1d213de7db52366fc8561e48fd5ccbe5bc56d5eea8b961b2636834a74564b20c99", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223833313663306164613065343037613038396230396136643239303263386239406365727469766f782e636f6d222c202273616c74223a202265656164633633333933643564636361227d", "TOKEN": "0421bd07fea32aae95ed357bcbc5028fcf69cecdd851f7f76a6285fe1ff2c1e2e3189be19a22bc383095533d72c2cfcbb0a9b930eb60fb4befb62058eac2149aae", "U": "0400766065de991445a6c68dec2f6674d876d6dcdd595e1ffe2ae9ab3d12ab1b5316cca96e0ae1a42d4eae6dde1f0e90fbbe887d3caecbb2038e630f7985652103", "SERVER_OUTPUT": -19, "V": "040338728b40cab1ed0483fd747271b992e6c40914071026fc3ae6d3d694c4e8391005b4ca54f1986d20844d9db14e686dac090669ce98b7f19da48b5f401bfbc3", "Y": "1fd4f4e6a973127c3940285018203d109ce7495ae329860ac8918ac2982cbb09", "X": "1b4589eabaf6277b78eb6a4a9dd476c63b3ef36064b9e6d50ca6e140ff6efebd", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"8316c0ada0e407a089b09a6d2902c8b9@certivox.com\", \"salt\": \"eeadc63393d5dcca\"}", "test_no": 193, "UT": "042098c5107d03aa8903656143650efd65b6554a7f14293e1cf2bc61fe99f1b76709ee18dbc2a05344844b4bfe131686389d7430e1c83d31524c016281e9e426f1", "MS2": "1d6ec125f6a75cea7e2d33b2b59415d9ab4e0eb2c1331cc08e3b767bf4a6c4a0", "MS1": "23b6dde59c8487255c5ee3ca6f654d8a9c65f442264f56f54f54b43f3d63492a", "CLIENT_SECRET": "0401c7acdf09eafed8cc26b74f18ef97ee387406a04cdd69dc1c3ad366f7600d18176fc540477475ee7152e682180da5e4451d4786ddb3d56b7700cebd75a01200"}, {"SS1": "00834ff80c7299960983cb63fa08cc4559cfebb03a424ef1bc21e3d01a778acd1ed705900025cde61e9e9ffea8171380b4d3102fca90c66e2e5529b43edd8932213d6596cf5befad91e4e7e5a60fa253dc3675617a9dec69e4b9ccbb1ca796021c4048fcf6c1fe6769ead4dab62bf42f78acfa5d02b7a324995461c2be3f4254", "SS2": "23d77c8f634eafac80c9f78d345e6bd0056b3d2ea23a6f1f236fa121c5f97c521ec3d385b77fd72af86d6e49a90d0f285a5e830106739f3facf86eb79ab14ca310ce67d8893f6d95092145a3056354af1df411f09f8d37be77b867395e87976b1a858590a283ae4829b97e86624aeaf0d7b744b80fa38010b0b5b1bd3c02ec03", "DATE": 16574, "PIN2": 5057, "PIN1": 5058, "SERVER_SECRET": "0dc9af9aee0b576523aaa2d73271b33afcd7844573ca58ec0098bf264b71972316e856f138de3874d824cfacf726d929b79623d4ebd2e247319e5fa74e6527021e58baecac45d0edac71187cbdd1e3c96376100264045de6d69c5891dd088d40054ade55e096ec7c7aee16600842933d83ee1e4cb7ad1301ff0922cca410a7ab", "SEC": "042049a737c46b9c853b1cf5201aa22250de6e027550bd527eb2a7d510422352dc04b57a68a0c3a64ba9d6aaecc1988adf51cc3d7645dd486397be2f3c0c601f7d", "TP2": "0412c413ba05bbd33c527fdf6725f28be8b239a8eadcf0fc06608c74edca47785c1086fdd39b3013edec3fdaf4355dcf270fab40ef1610815dc4653b1563010cac", "TP1": "04008bfea9c37c45c37d657c3ea01707862fe6274c536ddad3d679ad4d2da432d713d83dd789be452ad67afb5831f4afb2bf3f3b75512816380d8dc2e64c8e1748", "CS1": "0417eb723d2d4bb34ad68308a75ca6c2240143553239791ba37e2a3c55437b4ffd208ee13c0596ce2fa88101f2b7b97b6d8b30e3910f1f6626dfd28d41532c1754", "CS2": "0402712d9ab265361febaa5bccffa04f5c12c7c310057e3edfc96ac57f65360b9722c05a1e792d0eb62a4f39542700ff3b8c3b55ee9e526b9c17d67e86b7963650", "HASH_MPIN_ID_HEX": "3188ae1720eab5e69c9925765ff0bc401077244e1d10472f016c67af16757f7b", "TIME_PERMIT": "04105042a1df9d5358a32792a730ef3d2454d917e8673231557ce817f836ce25260d6911bdc619e705c3decf0b40580bee1afc072d3f69b89903fe28448ef3a840", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223066323363646233663764653931396435633062653232346330353136346564406365727469766f782e636f6d222c202273616c74223a202230653230323231633837373331343466227d", "TOKEN": "04046b1d8ec5d39410de223b49a8c9f4c8ddce3e53d15781ab17c3215c645e63f60ab85b293f644760034ce06b6168d80e80f9ccd2e8165716ff7fe89af1c9ce2f", "U": "041a71e43fe3d2b3bbbd6f881d339096f436a84b0eea53535f2de12c972705c5f01475b324bb2c7cb12a843a737a5d357a2cd348ea9756ac5a627e99f7f43e0af5", "SERVER_OUTPUT": -19, "V": "0420de0d2e2bc885935f43f7087881bd1a50d1fcbf8401cdee34c6dccbdb3716c90bb7f1b3c254df685832f4df0dd07b71d304b3ce17c2b2417ba45ea4be16680d", "Y": "196e92828cb2426d54ad28e674d7ee1c1ad0206e57c350db99bb0973d5ea7097", "X": "04bc27fc26e8c24b909bc0ac03b4ece426e104a96f755bcac44243dbe9c43843", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"0f23cdb3f7de919d5c0be224c05164ed@certivox.com\", \"salt\": \"0e20221c8773144f\"}", "test_no": 194, "UT": "04162397278b4fa7bf6a390f210300c7f6c4d2183c2f462ab2cd64e53bd7a3cd97058eb59fd50644566a5abe189047b4bcce714d304d9295aecd708f81c0f0c492", "MS2": "13a5641f18b5eb121739282b760974392dbaff039f7e984a71e9e986de92db65", "MS1": "18d9e781a67819f133300ae631d7ccc2d161407d2f3917c5d30b794e298d69d9", "CLIENT_SECRET": "040fd6f07561687903d1936bf492051baa53741cb964a1f28d221bbdddc3477bb21202045e2246c3cc381ad94febd1c58eca3ebdb1dec30abc76a483a709c0392b"}, {"SS1": "0a8c1bfcdbd8075183539dd2a054b08670e4168fc74e488e49f0fad09577551220181064a5f8aacafc30915e9d5290fba7a00a199a9b78f519fe99c1b94ae3140db17251ffa51dbbce5a7b4aa2850d27a7501d6921f5916e2fa937bfa0c272060a5f9b38b3361eedfd154b82e56c78b1d07b528033b2eaa3fc5b9710129dc214", "SS2": "0ff0304383049c67a7df6c0b95e3753be21e13a0fa4175394dee35eec2ea03fa1ca390300a0650a8c3ff3ac9597d5ad92a746def754610eb891a4913a0cf65ef1315d5b9c2ec1319d012863ca25df4b94071524c1d624b8830e1c562f9c7521c0eecc864fdecff5d3c0dd5c77ea7df39b74cd15996240c2f82f675b687d08318", "DATE": 16574, "PIN2": 2473, "PIN1": 2474, "SERVER_SECRET": "23aab3a29ef399db0a25bf748abe7ab31e475a362288d66cbf994d3edd8b857918d0def067f16461f608f697ce43e8270c470cb8db278d0d3b072af15e7b62d71eb386277c6580de9060de23757dbc42d3273e14ddd00d195848216a0116cbc202720ab52d0e70d8ff608ef0fdd842ec3854b47c469582a1b887c38b80cb87c5", "SEC": "0418408417a9888d76a78172181e8d8be75c7e3b37ad59652df2756e2b40cdb29903877b0cfbac677c29a0b3307effb5f0dfd3bf07aea159813f4bd146339dd181", "TP2": "0410e68dba5e9535e7e8ae0ee0eff52171446ed1c4bc0c2d590ad3f9c3226aab011934f8cf1b2e5f36875d88efab2666e6ab329aca8dc9070fbdbc372c02d4d43a", "TP1": "0400f06ea7f02730fae16125afb994e06f7db3a18db684e3de9e495838d28f22fe03cf81a7f8f4a931f7affc524b180975de02479a2f87fa3d771276e88e40d5f9", "CS1": "040238aa7b0c60b3abe8108585ad6c70356923f6fe22578eabb389183a4a2eaf2005083201a899958705afde5ade78f8217b3f9042b4f867532112420b01f77dd1", "CS2": "040d3cebe297af99b286145dc42e47911867ac2a7b18990d28df2de0a7fd6754c10ad2a585123f35d086f87ee5f69e863579823721a6592c5995e5ea299dfd2c4f", "HASH_MPIN_ID_HEX": "a62a372cf0112ad76bcf10b1b56002d98d0a9c1b2a28cd22aa6e07252dcd6dd2", "TIME_PERMIT": "041cba6dbf18814cb239ba032abbfa43825fd3c935732a1b43479811e088d3ab930860e60fa54b0b4bf0c2e91c98634fbbc9be8c0a714e69e7a5398f18120f794c", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223331633163623835643666303531393334653237663664656431323861663738406365727469766f782e636f6d222c202273616c74223a202233353036653466303966663838383835227d", "TOKEN": "0403bcbdf8931fc12ba3ae906360f9c4250c8feda81b2b1d85cd56aaba6cefb3770dddbd9a65942773a2a8ab16c534ab9a83701e051892c8dc583993d866ba48aa", "U": "040c1b65517be6653c1143816f8f71849db474160af0d7cc2648b705386a5237b622b15730cf80a74323903dd66739c34f01598bba9aad17ea24c774f017b1e041", "SERVER_OUTPUT": -19, "V": "0406a267ff4c1f2efec008fe416d71457a60148cc35ffa7ca59fcc7c5ec909391d03f7b7d5c67d83dd853c019c5ff6229857bd1c2e0ff1b71a00f3dd03c1cceb30", "Y": "035bdf66080d8acb9b6944751e9d23e7996fe4b74020f64118ff501586e52b7f", "X": "0423bc32ac18376c8ef1ea984d07f3dd0000c08bee5329cf51f8efca73de2fdb", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"31c1cb85d6f051934e27f6ded128af78@certivox.com\", \"salt\": \"3506e4f09ff88885\"}", "test_no": 195, "UT": "040c5c0761d225b11f5f1512d679fb5be478a57b2033e149a43721f4a1a86a79c71cd4580746310e88a8e51ddb09f477b971690d9135c500949aa41f40e7f14a05", "MS2": "227f7a3e1466c47a2bf743a075730772889e7b6713e14ce8976782a6aea758c5", "MS1": "0bc6dc7b99cb1fff614907d4c44dbe8694dc8e4b53af5373adb4890fac5f8fe0", "CLIENT_SECRET": "04151d03557c3cd034429cdeb85812ba1cdc27bec183687890c9f615464d2b62ba027f58f3093fb9f190da3becd747b25dcfae19bcc567dd0f2b5752f20b89f2b7"}, {"SS1": "1fb9d0825dd83998b21406c1b8a6e80b4890fcadebdad733f818f7e8a77d519208a5c2a22ecd6fd5f6763402d21d973eefef6c96f283c232d2d473f4cee62302161e4dfe1d593b5af40dc926c75793787c398f4e6153f2da4cdbeead06748c2d05ea6b516abf15c9c0bd50e177e1e1772f7d621ab66acd5f15db1d9c477d141b", "SS2": "121356d3cb3ea3287dde349182db8455703ba09ec0d6e2927ef402f16c90de2b202ff3373ca1631eaf5b41ac3a73c599311fa1e176231aa490ae5414f023cd0002cf490a8d44ed47af9305c87e42f32aca6b03ba7555db066464b573dc47e0481a0df083ceb88b159219796e14264e6d04477e1f97e5d637a106587ac214ef0e", "DATE": 16574, "PIN2": 1297, "PIN1": 1298, "SERVER_SECRET": "1f43cec5f7f9cd6f86ef7942ccd87b015ddfbc56dfed2760225391ee2451d96502b0ae2ee8b0221b165a29e2a6dcfc875c45a491780503390fadb163d164640a12c58f6f1d39467bcecbd87ee63a2033e1a8ef02e82de2a6dfbd1f0249be7c881d63dea92b383f3ffd91ff10b82c4f3fe3259a3b6ea61f55b4b29360f22d20e2", "SEC": "04003596ee1402a77dc249b4f3c5e3ddc45bd522e082faa39d2e81b8346861161d1f52416e8307cfaeb1a65bb7e224c489491c2810037ffb036af143c22bfb94cb", "TP2": "04214327e1d6fa6b1016cc8d0f5d553326224ceb9b9b380ae33c183f344cd2c46f0f470f40d35f363d480aac53fb59b21927fc59b6feda1bdcd77168bc5faac46e", "TP1": "0422a0c75d0939f6ece90e1d3480118f590ae80189c4c6be6d83955353b7223d59012c54dfaa9555781dab6e2b492b27b7b61eff6f9f2c2075f3811bf879561dc3", "CS1": "040b44ddda3a3e7f19ff8ee326eb21788ea48722aced7b1ca8445e8c0ac15b639f14ecb605bfc19740f0e972fecb22583e3d6423c7b56cda482e4f84e0bcf2722a", "CS2": "041b78f10465b035a616258e037e268993083397e92301d36e9979731b422739fa1625ad31f576dce0bc7c1583e69f25fe6685d786536cb32258adbf0025645560", "HASH_MPIN_ID_HEX": "3e185260c7d0b945ef5caa9b842d1efc71605ced1803c57ec22f0c457c96a645", "TIME_PERMIT": "0404f59855003e6e0b5bf992c01ba008b484494c287cb5b27fb1c1edc3a1f2b9f21995dfbee4cb80d9f93b755638430e55ba6e885c4020b4bee063fb6f4394469d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20226661313261336164633736353436636463633631366530323262306431336435406365727469766f782e636f6d222c202273616c74223a202232363666333364366231353861326266227d", "TOKEN": "04041af1d46f6a06386ee6d0723996e9a4b95704c9da59e99d11d6a233fff51fc9105f3d486197375d44ea241767bd6557dc41f7748dca437f8ff154feef1c7f92", "U": "041a76f792c56e28b867bec9ede90c14c1b9979cb773c47ea74809fc9cbad418c7160991cd5616580042b286912312d5744a8b5c1b1bc6c17c7ef8ba85b4457352", "SERVER_OUTPUT": -19, "V": "040f749a8e51efbd19467d9103c5d444afcf20db21b1caebabc571185df83a155d17ca590036cd3446804cfd3915809165bd69a5ceeeb79616300c0a4f265a2a4e", "Y": "005e809950d18d6ebc27967189e82cdac38a4d6190eed5f15c2724730653231d", "X": "19e9ce910909788b0821b30b7aef24eca4773a349f5d767d8577f0d9c4868b0b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"fa12a3adc76546cdcc616e022b0d13d5@certivox.com\", \"salt\": \"266f33d6b158a2bf\"}", "test_no": 196, "UT": "041934e20f15b4fe05c816aaf0570d6f3f7d371ba5369b5e157247b1322a95d17408493ac05e1083d42d824409fbc81046e515a20ae83df698162cb3b64fd0b46a", "MS2": "0ad69f23f66599248b4257a680b4289c581aa582ec3be7224430deb81d7798ee", "MS1": "216f6d1020873c0bf2dff17fc37075794d38971d69953ba09d349070b3ecb2a3", "CLIENT_SECRET": "0420cb8006ea4632350826de8043f41c387ec0c0f1eba7111c606d4c40c52d50ff0a9de9d913099575269cb7087fca92c20d94ecbfdb56393e140f9db9acf35bd4"}, {"SS1": "01d68d18902536b71a4e2afa5d796acca2c1fdd8d7441c678ff54434e64d83c71f847c0f3262fa62af30d9c60d2221d4e54558c189df7de31b4d73d17b1f6d921b111b2a279c897d22da5d654df9800cebfc69388ed9022738306f0fac3aa3f419bb2d8f5f6512c048d2ac6e1b8a9756f005840cf42738d5a53ab7b8302a78a3", "SS2": "1d1c0ba3d7d94460d5b817fa983ea203a85a4b163e380eb0b572e2ba34c90c61211e6860669b620aaaae85d8887d0d6e148bc3b1f961bbf28961ccaac29ced1b0b926f1365f6d7f95a5b6dcfe23fc9a00cd10c337e97f535018cfdc7d779295b179746a675d6fd142b4ae0f17562edda3bb8760ae911e9df658c5903494902d8", "DATE": 16574, "PIN2": 5854, "PIN1": 5855, "SERVER_SECRET": "19d92c9e12f8f0a0d9be0da4cb7b4c3ea8083eaa0e4692c94650629bb11e89a116df0a154a0211396b371d1a3a41c6b786163187c24f6963a8ca7bf7a6e9384b167f4b800ae828da6305fea07775c982f2951e29540338418d2b1864c3775bfa194d41e3cd1b66b796621000d7121c9bc05d29a7b194512788a600c17adbabe3", "SEC": "04203dd13e05913db8776f6cb8d1f784cef94c1ba8f30b64da8b9d187594bbd4d71aff81f9b311fba47da14938dd85c408eb931546be5e8074691dcc63be6d2589", "TP2": "04188842c96509a318fc9d8122f121cb63d7542b49793cf2829c51e43824aac0d500db5cb9c1b1f5e24253cfe6e3d2427f2181dea7cb54f4e01106d1e76750f0e2", "TP1": "0403233237d4cf9dfd54071847f04336a39dc6f5a819ccb6c6be3c08a54826ff9506a66f6b6fd45765ff868019dd607ada25cce5cf5239d046f3e3db445f9b38c5", "CS1": "04141cfddea22db370fe19a847dd512180aebd7d738526aef7f0780a519874cb271ad854a28aa4da68322f55138d119436e11d3a59910fcd43425eb81f80486a23", "CS2": "041df3d33cfe0a63e101f8e3fd33b334d79694fabcaed3c0042bef6c38c3a86896191f5804cd285bf9a0592651360fc30316ab943ee75598c85acee8574c735c80", "HASH_MPIN_ID_HEX": "bebe805f54fe3d0063975681ecb339cdfcd1af7b32d6a1261a6b6d27b5e07eba", "TIME_PERMIT": "040bc63f44f3bb9079e60975bdb41826a12e78c395c167037b0de03b476cc31b91031f321ca2228385993682ca6f89b29c0948f6ff0dfb519ef330701c15916533", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223235306139346436646637396237313230336561633337323530623862396130406365727469766f782e636f6d222c202273616c74223a202233313332306232383834323033383664227d", "TOKEN": "0418bcbb1f0bf2911ba40ba5c6576a34b5293b282602a129934769fc0b53ca7c3a1b837a2a69ba18690761ade4675be721c4051b04a1cc629e3b623e9ec6d305ca", "U": "04132b34eac1ffb372ec4479eb96e13973e72d713d76a8a67aaf6a429fc72cefe8062531e8f74316634fcf8ba945c93d09c6263d6c7bae189b3107a0eed524e290", "SERVER_OUTPUT": -19, "V": "040461de05c60571e48a413e4b8921e1a110fa2aaddeaf999dd0719b71f7f65f721b51353f2877e550a17ca9627bdb1b60edcd4087a2a092064a950c80d2ca0507", "Y": "131032f7fc9aed5a307fc196c3751a78cede784babb7cd7e8f8e8e780e4e726f", "X": "0c0b60f53c5ffb0d6c4b0c1880284e67767e79517523a7e3de6703ce107c6180", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"250a94d6df79b71203eac37250b8b9a0@certivox.com\", \"salt\": \"31320b288420386d\"}", "test_no": 197, "UT": "0411c344def7eb610284db341ab3e3a6ed773b8d70ce498f91283ed687ceb276720508e0adbfa154cd6824cccf3ebec6ae1794634e01af42f0baf1712f1b2f7d50", "MS2": "0233acd19f2e533c36c0be18e6b7c3f13ce865b6e60d3ec23fb18d52ffc7b72b", "MS1": "0a4185b2958277a911182ae7abdf4753f39db19a2f8b6640017f8f97c543de0b", "CLIENT_SECRET": "040cfc9bcdb7aa64f85c0e273500e6d6025f873710014e2684df68eb005b2a33eb03b7253ab48e0d43e66efe7d74ce498dd67ff4c49091e62875f4a0ed7979f743"}, {"SS1": "219d5cc0918cfe9847c3d032f0dda5a8ae9efd42cde082af24241b4313d4cea11d06b218a7e5ca0acf296a496ca9c3dfa17d8f9aff9a22ae7a8da206ffae9ec0123b8486ea40e4d955f07d9e317e0cd29dbd1e5dfdf8c4245aaaf13f63d74c55173d9000290becbfb108a33396a4638261a27e1790f0ed991b144be6c052b8f2", "SS2": "1df4545b87c96120c4d09b7d6303cf726bd047067d629a3db0a78a84fa99cdc114a767a9f6fe77b168d299d2cdbc68d4431219ec7ae359e7fe8d4de10bba9c931fc8e349d8a17c632caa91bedbd909ef17f3b8483ac20081604440935811c80819127f864fbba7881e4cf5b5c81150a87f6ac41a3c2ea916277fb5f0adba5280", "DATE": 16574, "PIN2": 140, "PIN1": 141, "SERVER_SECRET": "078855184bd9a66b1af9f12be0ead67b2866fdf8c6242ab0c36f61022eb9e08c2238f3598aa5c9d7529e37699a2c2e49e09d1aebfc4756ee6fc715b4e67f42831802d6e985a978819e19148ce2fac5112983a9636f899d63ff77b6c9764f49d01125266cca66242114d002fd3230030ff37a196860b794d95ea73a4865a94bbb", "SEC": "040627f922c2ae17131e1cce0bc3c7eff67b624cb54770c08125a0fb34b0e138a005393343a79a142bdaf2094c3538a5a6e127a2043666b84d80d2e764495a8dfb", "TP2": "04234609b0f84e7ce3f09f0d2f6e221466dd9619c52085107f0dd3464f2536f081053380a52f37c48a00292bb56b0fee8d95ca246f683b934a2d1375f53e5c03fd", "TP1": "0416c350776bc30b2aee7f51fbeb4a0bd4d4e45bdff925dad977f0535563228e0323b09a89e0c408c09548c41cf383ca25ca263b6f99de2daa593bae03240a37dc", "CS1": "041a838944e215b489062a13f7fef438edf0f8fd7d721129bcdab7fddb9f6e822d1f26408d492db5f45e03c337af774c13be4e61aa8d2fa0873282f74c8b171f3a", "CS2": "041b1b9d5753498c1b6fa673b7416447e81f68c3ca80b7f9413c3259d53ed7ee4017a4776345179691b8ea09c8b28467f9b9b6fb76754ef9547229657e7016efd0", "HASH_MPIN_ID_HEX": "30efad459e096f6472b8c2a28ee514d4654bd41798f439a7a4f576e89c4a8914", "TIME_PERMIT": "042272e772a8ccc0d9c2a9447bc75a85f16bc7ab5fb734c75e0cfedfa8eca6ee9f1bf45bd18347aff03cb4a57dc53ff0a9d5b62f2499560e2a10024eb494713528", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20226137646261366534316435343034313732376630666235613131306533613238406365727469766f782e636f6d222c202273616c74223a202234636234306166393763613735396361227d", "TOKEN": "041730054ba035f80df1648df1d791ff9e13bd09108f1267e222939fc4afc72edf1d28c55fac3f4b34f48765a881157f2e2c3906ec172f3ea5478315c7b9231287", "U": "041cd0a19fab397ca59d1262d3e5aca3f65587da08e85552d903f12dad4b26ac8c0d06b2d9e9b742958ea944ff175618da3c5b1742e8fb63f332bf22f6c23dde5c", "SERVER_OUTPUT": -19, "V": "040f7e239f6cac0584c8d8465a1d38d3d7e96f492719c94c7eccd4c6409baffa401a7c1770fdef0a93b25fe99ebf9e784cf83e911147e3b09046a79508381bcaa6", "Y": "2348514a2e0849de7f0cae94fa5cf74f639f6347b36d1fbfe1056a27c2bb6f7b", "X": "1762d533ef1a9a98ff31d3113e0d9882d2979e152d2ca6d3e3818d24a751bff5", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"a7dba6e41d54041727f0fb5a110e3a28@certivox.com\", \"salt\": \"4cb40af97ca759ca\"}", "test_no": 198, "UT": "040291f50ec613454f6e0e28b55e01c1380ff5de8cd189eab765f4d9bf937af1a0172af0b2734932d75379a274560df22dcdee20b11e3e3237487ef905792b5fd6", "MS2": "1185ace1f418553f1b876b4cc445597b0cecad0012049ea646c674c86a701c9f", "MS1": "208d1291443f0891efa640311758871b4aadb4ebabab0aec6d90f322b623a350", "CLIENT_SECRET": "040606133f002da89f57d0af999492660cb1ae6ff3d5950f580e11e65f3c2d7b0b0c55a0771c9e013af1dc1a74f6eabb291ed0cd0c0117b7f2f55dd39cd243e9e6"}, {"SS1": "10e4bf08f82385bda7f192d23af7f3b4a7b1042dc571ec874192b7f5cd29b0651a57ed84d44f23b64ae8fb88dc00c653d1fa2b9e0ff4563b3ed33740544c67b81ed88ef501e90c428a722fca3908ab7d05111a719455fb75b2414a9b2e50749c17a450d9fde16fa7b1edd6ca2c2012042bf9de6e89d3fd819e92c636d4b64926", "SS2": "073301c8672bdb786ce199703d6c4333250119e957e42c1f998763dece75764a08f2d0f2b11c016b7125971e5b9e5d35094258e90b0f90206ff2db066c5a9dd51d2ef5e4b9f196385ee3f732b6d3c262694dd71891b37e9a68b78e7779e9e7a0033e2bad10a774f5fab610170e4a59cd857a118408c8180693eadb4960384c78", "DATE": 16574, "PIN2": 4780, "PIN1": 4781, "SERVER_SECRET": "1f5d7bdd9e043c2a32466e66f311ff15dbbc5539dbd0c9c9909f25d98db8493c17484a69a937d3cc826d5a16dc063f848c55dbf6f3edd56d8f6bb4ae4b2f3dee2073766a0b8f4b6ad430c80d3c4e9053e506046f1808da035620516d9540e29015ec9ba385754f18c51398121505181004ddd3695118f012291c1629cc35bae7", "SEC": "042126f5f9c938b1eca59a6214406855dddb11898e42a6b1d220718412e483faf321af8de3245188048a3988fdadcb92a324a3aaad89695505f4a2526102408641", "TP2": "041137570c19f7f6e3a12e0fe569dee8f3fd90c74881b83ae15e4eebadeb0b06f6055d88040aca6c8eacb40a2952058da603c9b02dfccc70a74646048200bbe227", "TP1": "040292d3a4b288f947f4a779696c70235f389c1ea8ac45b9b9f5593eeaa0c5c40515c400f30368f918ce4171ed5a9da6ebb1047a5f7e69dab3a4566edeca9fc6d3", "CS1": "041816052a24104d29292ace5839fafc17d46140b41b5e2f89800ca5d13b307b2208964f36d00f5ed3f24bd73ac2434d805a199786f5564eac1f63c0bf9e86badf", "CS2": "0421879203aa7e64d5dd572f482319f4a843cacb000ccb8b1bd11b6ab985c7e3fc1194938b46eb482b992552fd95a9dc22e760cbfa475cc8846d4b20f6c0c09edc", "HASH_MPIN_ID_HEX": "55bf3bc47bf9e8ba162e46813b882c82fdd673be502911dc5598846ce32bb9cc", "TIME_PERMIT": "041a53f83cceb63476b2b6cc5286854a06c397b4ed262f069dc131d6e5537cea6e10264e170dc1f388a665ec55d789e18e1f4e703be99015127358ebc6020dd791", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20226239613336633263343037313334663161313430616534376365353531396666406365727469766f782e636f6d222c202273616c74223a202235306364656661343632323038643832227d", "TOKEN": "04161b9a1382fc7ccb004def91c5bf5105bb99510ce358f8e580a0c45b33694de216e091b13ed126b14f06c5070e1eac79b72b8078d1efc12b63c6ee263e2de888", "U": "04132c140a6ef81c2766523c7af2d9806cc83aa7976f57b027ea32517edfab0d2f0c550c4973692ffb62cae0f75249d5fac0ba201c1ee741b4d657f3353796c546", "SERVER_OUTPUT": -19, "V": "040e91031024f84796935877595f8d70a35cc7854275528f51c4ee06e1444217b21c161b5638d3be43cfd8c38bc8b2362ceb66dc018d2956f13876cb1e9bbf6fae", "Y": "097a08e146c7b1113f94429f41887b12f9b34485733a095f9b32b521b0b1149d", "X": "0c0a502e784bb6cb0992651e8138cfc8cae5434b55a65b2fedfff253d25fcc16", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"b9a36c2c407134f1a140ae47ce5519ff@certivox.com\", \"salt\": \"50cdefa462208d82\"}", "test_no": 199, "UT": "0422de13a846221a093b6fabdb77432f9a0c18688b94ec654f0e73e24aa5570710076987cacfdb600899f1f61c2b4622f0e8507725fdcdbc95dc5ceefc3f4524a1", "MS2": "1eedb4167ed170b2517b1777fd56b1763a802cb4e33d4fe0bae4b66caa13e55d", "MS1": "0dadaa713f962813933da3ab3ce3c931a4e4938a8dd50598d73735f5d52369d6", "CLIENT_SECRET": "042057f2bbd154cc843d653bd8d3269d726408d1780f37cb11f014454749d7572d1b32150ab7aca9773f1f9b6e164c55f7c8c1e9c29e4887b8ec1d796dcd757a67"}, {"SS1": "0d3bc7bc15fa085aa736ac443d783ab1c13fa4088c3eaa4082abd336cdaad43b14d575eabd16755314fe3381a0011f3e8bb3203363689347bdb54e44c38e9a3423e0f556c9ed21cc59021057aa965ca90d542b1ab6d6536e10f6a156aa830da3237aeb996786d15476171a3b5cab6bb83d000a4e7a676ba17e484d256a1f38c5", "SS2": "1df6da37ee19de444ea9ed91e5159713205f7b3cac31ad2d940015344c21460e05791fa813273a7a3a34bc50f451e25785b27d9f3dada5373d22a940291cdda70cae9b7554c7e8bdb0d4b6f804020faa17b952f642812ee9a112f797164aa6c81e4b9610c9e5c28b0ade1d447542a8e01c375ad9d066be0b59268beb3fa888be", "DATE": 16574, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0b6cd4bf911f880c322852e996bd2d213b6dc7472ccfef4e88c72ddcc1c098c52216cf095e5f995869994bb0e0b49814917472c9ef2ff91da73568c74a52af45171cf540d1863c984eb2f5b900f598d475c0c8dab3d797659e55099ad565213d130c582b576daa1da0ab4f1db6d25e934893cea02be9eabc055fc5c54f2e6d4a", "SEC": "040b9c711648addeac9d48337aca64bf5610d7ff02690eacb502cf53c29a0d619508ee4625ef396312c84e72380271fd1037468b6ec806184e339c7c1adf7b7f00", "TP2": "04014cef6a3197d62da2a4099b3e759917d5e67eded18773f880aae99997c508511a7d66700597c0601e1174091e2daf421c8752adea7a422e368c7af94ea026b8", "TP1": "040907f6213a33efd48f2533ac5bac18948677b2d37871502978a954d285b8b3b21305a5ed625d971acfed29cc00b986a50bf997622c94a1e413ba791694f10ef1", "CS1": "040e0a739b74bd255b9cdde11743d1b44ae77fdd403919a00dc5ae0cb7c662508b1ca3f2b5fbabdd7b1c259d0352bd66138e1ab3e8192e3dc4ccb7c076b7b56f3f", "CS2": "040cf8d7ea0d0da48e803b2558eb334d2a5df59d971cf4563c8466849f9b9e6a200996eae9d526628755227f1b919654c3fb4b7360c7a308e402f9fc2260ad583e", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041923d167da62a82de18bcea4e267124f334482d00538b4a3a8a42468c277552b1a81a00651b7971be8bd89b1b42b2a8d9f8bd2f06e8cb0d809e542ee07e67e0e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "04136d1008a88be0fe18fc87e22d0fccb5d1b5747f706e8cfde061a742f2a3819d2272fb24b9774cad1a31f3eadc28404e7ce04defba06fe770fc12621154b6673", "U": "0415b054facbc2472d9d12abe794801f3c054568a976fe59eed1262ac488c5f3e813af20b8c7e4b0554f8b5510c07da327c7dd2e300f22e5a30685353325ed3f5c", "SERVER_OUTPUT": 0, "V": "040a96cd0eaa154d1b090feca4b53bdac2ca774bd943ab49cd71b9bbee786fe1db21aa08819e8f8fa14b65eaf7a21fa7adba97545f6c71c9845292aca9551028b9", "Y": "05775053c52ddc36bcb0cf6555ed8ec67f552f1dc8e76040f386ed78a0fe1e28", "X": "1b879a9bea86499749a5fd18cc20dd477b918f861e6d7d2ea4bcbbbc7f39b28b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 200, "UT": "041ec334910761fc15c80bf5b1ea258a6398b10e1cecccf84d8862ab61934d1be905e8ab172626d95ab8964b098fa1a73aba3696e24c2186effe4ee65552684168", "MS2": "11d95d99b5f1ded62bd1b5177c9bad9ad1bf5905ed4f07fdfae4910c07c62278", "MS1": "0b46b8b0d209d66e494b5d7e8094666be50bac2c364e640702929339a861298e", "CLIENT_SECRET": "040d496eef8d1e4e2b1e60cfc90f4951682fef19fa4bdbb792b7ce93923c1797dc010356a43ccbe69180a4b04b76650a34b4439f4687cf7ca5c45f97f818a753ee"}, {"SS1": "21ccfde40a54f37693754d834ba8578016a104b19d7551586b82bc10c782955d08179d004e3be24ae8f55994288e0d4cdf806126e56972ee5f90b1560401b95c0f948f4117a4f2ce0115ed2d3be9162165b2918722fbc0f9bc4a55370b59046f09ff36f5a68f1e792b6fd5adaf9dd0f7a9080d97090bd1d49aa6dd4448d98bea", "SS2": "1a438f732dda3269dff9394c822b14d9391117acc90e2be16141744734ed5f4e06faf39874840440fa94a707e576b66d4bd0e434aade0b487e87af1f931cbeea2224da232c5a15d1261e9acb37742084c04bdb091dd228377e18b1027e0a8bc91630668c068ee40e73cfc5a368c0993c0bdf0c828fb77e8cc09e5f57b172a19c", "DATE": 16575, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "095eec7f81f15b711a5843035e9653e236ac01694f2bc3f368e1f26e375a7531190a2d93fb427361e6c8d19f776df5e007da0a72563312f6ced700a36cdd5954124703686020d1efb323c06311949c1b4db8b2732071814a129b20a1b114e60210f555bf6f64491c28d9ddce4f09aedcf055813def4c4c9b05fb265884af4878", "SEC": "041daf9ae4810e0915ec97dd2e7c0e01f9b14a2af11c5482b953b5de908804ed2f0cfeee59a39d8c75ae3f087daf42589bf6b255e9b4fa2b091b2ce0206c69b5e6", "TP2": "040ecad54d79cd2fd57e5b0e9c9f595a4533d70ec02bde64e662d7096753f496e312e1488dfc037ca749666e876c04bf4d67cd8185c169e11518675cb83b03e444", "TP1": "041527736d4d22dba1cc8849729c5f8a24c05411f2fa0962c8803a5a0cc6e9ffee2080977bcfb2e7b78dd1a1fd5992dffc9805ac983e4975db9b09d603ca719bba", "CS1": "04143ad89bfd9ffd72cf078f6161186b5615252266cfd3c8693a8dfd1cfc99e0a9031ae7c8cbd78eebca42664c9138ddac2dc5fbfc9cf50a364d03a171f5ee4b1d", "CS2": "0415999d2e22f98e0a7f88ad8a98a3e6b32fdf9e2554ca078d41c3ed86840b6e5517958b9880c9c4c589fdd708b934ef3e8f6a7ec1f82c1b5ca6581e3a9529018f", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04219992dad8a57973946f9a5578331efe7b7bcafe1e2024dcec5196cb545077c01e54b05b8af0d130e59e9c1f5b21d029ba3b44069e1afe86c8aa42227ca22d07", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "04111e44620acc14d4e72f767efcc49016a4431b96f81b1981dec0b62c85de986e0ceb3f60613e9ff6a63f32dc17d6e2e2a392d2485db565a0a40f46a2eb9d94d4", "U": "04220c79da33c4f892cc1a55897057cceabb7c5074ea9e17c0752f90210281c9621ad75b0b37a3342527b23fdd21e5a6e8c649782f02d17ad080c39b1b131a0347", "SERVER_OUTPUT": 0, "V": "04065190b513e2b01f32a053dc23cdb296a0d2a5c871ec08c45fe97fd1626a2e3d12aa7e98403056d0640d3cc1bda96beedebe5c60e8a863f0866be242d232137f", "Y": "0a457c68ad0b612f3c50d32a4192d60ab18e5e9bd0c580db26ccc235478dfc71", "X": "04de807515b20d2799cb1e3daf6cb84731bff85ad93e03dae80b53832e926ba6", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 201, "UT": "041b8029d247665330cfd595dddac2cd505b1e0cba7408e220c8ce5f4f7f1b9c0915cc67b092a6196addb42e99f14aec06c2a1af1ddb9186e0024284f452b38d93", "MS2": "171d0fa8a9471c85d5a1f3c6f9a70f2452c0ae1c9253f19b8e0b1d00e086e9e8", "MS1": "08aac6e25761b857d4e3c80a64843ace561b883413fc25e3a9b31daa015fa01f", "CLIENT_SECRET": "040da92e61077d8921daef1c705eecff120b17b03347c7509d885c45f32a37cb5f0bdd418f3f46a9cb0fbd8abf00d4074071e1b13767d6dc39a1be5bccaee8a0ea"}, {"SS1": "1ee873c2131fcf66b89b27f0fc15a20c6fa1d46bde0bb159b2f66e1b3b4d7a131f6a4e8548665cfa16a696a143c44de4c0e7f4ccdb59e6aee31a6262fdebe1da083c3b45d07b68bb92a8d27c62fa696d5f46b3f1f403708918c634e81bce93981856356fa45727ca36a3d34b1980a1e0610f98dbde4c6164e0583ae5fbd70b1b", "SS2": "0574e83357dfa91b45dfd3b185f8ef7d498ae700da2589ba4687ae99de6554ba1d6b705c02e27fdc77f1c693c0e1aabe5bcb8d84f78d8620b5c7d1afcaacb94c0a4c971c16075876ca2178b485312bb5f2adc1311a2f56483a230fdfcd567a6019c7ca9c6997afdc592889c8bc122a20f6832581ed646bb8ca4d927e2cd3f64d", "DATE": 16576, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "034185d67198c44c6b65b590f6867e2ed4a5fe08604f05a8e5f17c0201b2336910f124dda2e8bd137c3952700e245ef49589467425e8f8533a7de26c7cf527b815e417c04526d8a7615c42c6ef9daa9f8aef2f52146c01cb92eebd421881c0c00e2225c1754013d533538901b99070a8f64e8a7f283646c06dd026b5b1573dbc", "SEC": "0418ea97e0b12c0a6ce8d8e705bddb7a4d61609228e94430fdb518b208f1cd6cd509de16cd6b1da54d67e120bb4d0ef8f8ea6687c9af2bc9bb9ee4b1049ea2d217", "TP2": "0411d70bdbb13ba375822a520903586fc0fcc35c33826c50691179d473678aa04f1b79715a9cdcdad1bc378556086e1f7cc0b1ecf3817ff8bafd31f8891c3b1d61", "TP1": "04186223c79c92e5308d63e6da411f37cb5d0e2a3af1b852321dcbd5398c2b8e6513d5e09209f3f134813ccbef07ab933e20020b369856db4cf8a0958edb398e21", "CS1": "0412569be034eef60f4ffbdc15ec63fd0b8bf71b91e901017a6da1a41817e072af0f7eabebe18ca6f805f01f469cc318c1cbf66e9ffc931dd2b6f49656fc36cc4f", "CS2": "04022ea68c68c4630af58a641f54640dc6258cb14f98d052bf7f4d867504b031330920e6f6f107bed15df021949af9683e80547507b8939318bc07b30963fe6cc9", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "0416d75e723af14e7996b3c455f5a10ff80a8350be41d9c8d8f04b543db27a4721159181a99b4fb57cf4ff7ddf6815b8200d72e977984055afd010189a1e86a1c7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "041b2c1dfa73493240741d62fa80b776f1b1814082acb13af983e4af7452b76ca11097bcafb4401b010ef04fda18b1c6c484b0dba7aee26e90ae21190dd8f6605e", "U": "041e02230abb1aeabe7a585260cfe1375c49bcae1d048c1e72e68669469e9bf2f30037a007b8fb419ef677f255adc8c27816af14ac6a8ec104e3ddf88fefd8cb9b", "SERVER_OUTPUT": 0, "V": "040e01e16fcb6a7be5312dd0d6708b6295b25f33603559e2cd1986e3d3fbd3fefd10c788e94f492494fac0c414393e886f7b4bc4f2593f283c78a59d7e88be276e", "Y": "0fad2ebbfa02e3006d4ffc06fe903963dbfe7136be3da254c4e796167f791670", "X": "061bb88e1ab5379f12d48d9b23dba9a186f9813c6297e5172b7146edffb228cf", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 202, "UT": "0418e97e07f2a2d2d095bd957d3d3619cf9ab3e4dbd7c6325df3c584d706b1968507f320ef5519ef8f921a4b019ae16759760423d9954176840d2ed370bb32d12e", "MS2": "1b65a7a831577349f061b8f2345cb40b0f58721228bab5a1390b42a41c680b7a", "MS1": "07f9c64dba31aa6225f52997f6c1da139c3f5ffa31a94d6a5b9a69554a9bde3b", "CLIENT_SECRET": "04140e8da61b9b13c4901f8f90bb251559ae135f6a66be72989a914b4f5bcceb181b6dbf60ff54746e15aaeb13a1a3677acf061b3e34e10111c93c9fb5523d55ae"}, {"SS1": "099f01b53f0bb97dd17acd05ac8fd58e4cfe260a9c0f262a263d5268f0b6620114990992d82df7cddcadbf0321e8b67ea36aa04c42dc6bdfdb28cb2a41ff6adc1caeca22d83ed34d3f580ea4bfb26f7125ec5fc5b01196b0fa466907044ce9fa18fe7c216945691c9f2ef3b067b964656cb8d6d98905ce1b940f27c9c4583c33", "SS2": "12ac8a8574c8cab00d496e1e55e115a0c69eab56bb88eb1b40060efaa3243807228983223117e053d2360c6d799c592125bd7313d4c8d0305d2750aef3da33ae014f4f7ab3d09d7fa36ffde4ab80da47dd820ef6b5b5573237d3745a4a27b4fc17bfde09407400b446a99c6e16f755d14b1884592d8ac995dadfe3fba3baef51", "DATE": 16577, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "04bb94bbf76801cbc34f09740661e7b45c98f5016775b06f7f374ce9884926d50067a4d6c2fc86fd875513670c485d4f5a2b13cd524002a9c42331336e88c6d11b8e171caa54711a311cd1c7903adee972c5635a8b804ce74f429064785174ff064c23f737fdbfb6dfabebad383abf6b3f6a4a8f69b0a7a6fe2219c268fdc2d1", "SEC": "040164ff3ebeb4f8f8d327970b120b760f9d7c2f1970b80838c4e483bb1ef71b120a972b7e7ba0317265ed497afc9876742c351b00938417c0cc21cc896bfb9ae6", "TP2": "0400c407f449df18273aff0965a6ccdbabf179390032d0f5e855acb03ab912d232175a5749e2d77dd7c1ae6f5a9cf0e4b9a8f9bc5f6fa380f0276185b1279db47b", "TP1": "0418698c8d80b1e354deee1ce05c0e8d9d16cf8964e85ba1d62962b8df96ac24a001732381e99afd6ab60cdb4e364165266e9a73409f0d1b4e61f7aeaf227367f2", "CS1": "040c022f83d55eeb3e7b658640939c9b13e8d8b94db57a3579a05e970fdfec164901b801869e6d81d435973a100623b976cd82ba1cb338764693fa083d49ad3e71", "CS2": "041d7afdacff4b1f34db4e2143aecd56cae572af8a6e0b72a5dcd8512b4cecc2381d910f34ed772b13cf036de5ae2e6f094a0c7ffc96a31ea042b1eb1d65495c2f", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04110b4150d861866811ab5877ab5818e434de35b3e61d58308df9712c17f14b8d178d5a81be871c9359b2a33e13e512307a4e83aa759912c9c12be8fb126d66bd", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "041e878e140477849ba939e14d11dc6be76971e07f2126c69ac4e778f732726e2709e9ba51387db08282cb74db508109a0fce754d5869be6c3a5b6ced15fa46579", "U": "04080dfa4e1887c24e608aa36353e3418ffb9947d4cf274056fe63d23ee5008f840f53780ac4b232c3a7ba08e9bc6da6d710599a527ba80c7be1482cc459e4087d", "SERVER_OUTPUT": 0, "V": "0422667821769ab677b0da6008d50e7f3f815abefd7d796f034e521d9726c333b81e62a62cab0dbb4303e3469dcc5e5356e6292588bc0e4bff4b0f4b567d797a64", "Y": "17159b2f9e48822669481dcd0cbc6f367383586062a0a3a299bea0e6650b5215", "X": "1a302ecd8ec994b7b2f1176bb671a3393bd140a300dd85688a1ed2c92dd06b78", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 203, "UT": "04134ab0a251c82f4e30b0868347af3a186389ff7ccfc26671794bcd007030772904b0be719b5cdc2115f3aed342aea24b92a2ffd0fd475da3f8c91539a55afea2", "MS2": "16b9f63fe8e739d4bc0c8405a2164a5d31a0e4daffae29ec7185cf8c8b736470", "MS1": "00af6f75eaf2606339226361c841d873d7195a51058269b73a89432fbf287312", "CLIENT_SECRET": "041756aa8db396917a58a37be0c8446a855f0419b89966de53153067a772ee99a50a3c4c8383a173740c0e0776c15062b43ac253a56f8b89778f57be0e57765d4b"}, {"SS1": "1132dd8c14351efa5b3eb42a71065b626fa8cbb0856bb68a58dc1273e0a9561a1ef6582add944650602f95e7d4000513212da5bf51722e943e4341221e4543481f5db0b815f33fa427a1565745e1eb630ab2d7696f9088a4f9bc34d5fdaba56a0f051aded1985b14196001ceff417825cd2acfd033924d3a9c94b5b70b741f87", "SS2": "0e765da6685c5063fd141d632ad0dc95d21a04ebc2e7ce251468db2cadb9e5b61b65ab631afffe4516f76654cb2f286442afaa7bf721398f015c10c8666b5f7609b3bbdadc19b33f151c74d3fde67194afabb04b15c740c36a1ba94960d880370e89cc3313755bbdc81b5399d66b42ae0c1fd4443c304519f99bf85b9cca0a69", "DATE": 16578, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "083c60299845576f73cd73785cf63248aa4364f94675761de54e51e7cc2268d00c58046a51eebee7b3b9c485dbe6905ab88f01144962ab02e657b46239a8d1e81f66268da34cf6169a3d8a0f24e3c7f333e72596e07f4942d933cd19a73769951140b878848d06aac9e7792c8220b604bc976c87f5f9e395f82c5f185b5551c1", "SEC": "04139d14875e3c5bb8a6065862ba935ca930e0eb3cb6477bfc06a586bed9b8c174065d0cfd8a382caedc115d9f8d20c5db8f5d4428bf0a8ea09afc5e5eb760f86f", "TP2": "040e2df8581258ab062d7715fbd6bcce44583ec70c555eaa4860d4f64b2416238320d4446a6f68bc2c28975afe04fe9968f6123ccc2d7d64161c51c069718f3fd1", "TP1": "041badb763f92d74fb17d406abcffc78285758c5b8e3cf2ebc3f3a12a99ddc12ce001039885229a8f2e7a82c49565666cbb7c01bf2bdc9a998cf3b365b5acaf2bf", "CS1": "0412464537ff19c8b74b25c10e8258e6585a7608fcdbb43cce01365c01dd662c75081965b0811764f128a383305441338ad812b7e433bd1ae5a44fe537f9e60fba", "CS2": "04032dc8fbb694b4bce24b82ab42f056451f8253250c6c2b83e0a2fde3027f79fe22cb95571d0160377c3c4a5a3589e319af013ee3cbc3c0470e9fcd5072a7a5aa", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04123a3046285eb9b8889d3e2d580f3fab1fd7c10442e9ab5d6277843a9906cda403a3d4f4d38e5f1882eca2ae24b4138ba43eaf4bd63cba47af5d16d301ddbd1c", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "040241aa761962827ed47085c35ae737c7dd513f3f96ab96a005f22325e3a035791098f1d56e6c6e2a662a890e0418ad1c32441e33f3917c4b07b4bf71c99bc6d6", "U": "041ed46e6d027babc7fbbd4cc110121e91006c5fe3428d045263d6ab6fa4601fa3181d8216e43f4bd0802a8b9a67b82d85acf0b4c1707c6f572e74d6d5be4f31e2", "SERVER_OUTPUT": 0, "V": "0410b6f30ade2d097c72b6b93230f2f6dfa26cb8e06166b700fcd460985b435efc20dfb9a561907b0385e24c273de575acaf6362fb19be89613263565b2aeb066e", "Y": "0c332a77845753c1c5b845efd42d5de682d9d3e251af66a8be8d7f46bb2d643e", "X": "20d4123cbc0c892bb4580f2cb3bde97b560c260502d1e537a867658c70e1d71b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 204, "UT": "0402be75c0f934f72bfdc03285fd4dc5383b16c967f5bd736b49190b0ce2256aac03e612c195c3550d9b42982c8041b6d3f5e3fae51ac48b0974be082ba15ebff5", "MS2": "1b9e98d5bb59d209a9acf6ca18016a3972270c32df41e234abce3fd795550e05", "MS1": "18e543f8848a64ca5344d15250dccad9ff703377564860ec29162e4875c684b9", "CLIENT_SECRET": "040a61e9bf8cb430eee827cdca581bf4cf1285fb1ba672cb6f22087e9bad4d37b50b0b5e63199db95d01d1facb3ab74560f25aea69a4ebd98ccd9fb1ba29895421"}, {"SS1": "13f4546955df0ffb2cd02ce1bfbb5de89aa0061d4d4a9b494b6681fc14075faf1a31a775a6143bfe1ad1b950b754d87a9bb95c35d6bb15fe48b946a4a5137cb00a561d21f1d2ef3bc6de78c92f99de1adb4c1e9a3463135eb37df2e4e4bd2c1413aca22a28f830d9d2403ef55d7b381a126a8208516b444c29c5447bf7c48e2f", "SS2": "0a2fd502d7880621aa5c1dc64a367ac146f87c7ffdd94f5b6030d5bcef61c7f615d0a738bdfed64f3d1b2588de94e90e76d53c0d5912321a3d9a3a64d7f4285c19ccefad6bdbdc98c4a52a8ec0736e5f56f695ec16f45a33f6b2e3053c9a860a23418b77f5809e1ea6aaec5eb487e45108b4f872a1cebc31c958dc8d232d748e", "DATE": 16579, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0a03c3fc5207a829383ccea41f23a3bbc10c60da08e3b50dfcc3064e6f8d18a016b38d3727d8de29c7db945d10ed9eb83bd5bae3ad5a4db40b5c113fc87e77b601a3b3fad0d3c51e453058998403c2fa3ee57107de14ac6788b7da599aaab31b0f28c69bcf2b75cbbc1ccd0acb554a0865a84f126e94d53b2b83f9ef221b9c99", "SEC": "041814018a5469a4728e4c0532441ab09bdf10a26896a349424bc256d6db3de59b233de7b213097cbdcde05be36c42dd96f646f87afd1551311a4ddc193066f953", "TP2": "04124ca3ed47e9359e9dbc8952b0f5c25d43c08b1e3d514ad423f3e9d4b56fa9ac10d9f041cdbd8973bd66dce7f46da05a1fbb8d8c33cf9aea01e7084ccb390b2d", "TP1": "04080ba8e71e571118518f6080fc7b23765ac3f2089b2f803210110b25925c80fc16c1730f1d8d0daf909c4725081f9cb7af270281756c3d477f2648c631e87d7b", "CS1": "0407d047e046d63d7f13116b219870800518f76cc421d54e52d0635082398c4af31f988a68fd334358e02a50c7ebfb402e872f1d1f27d7c587577121671e8d52d1", "CS2": "040be4518da61bb3380a8af5548a7d1132e07be922501742bb48e4258d3aba4a97126f76e059a4ac804bd22a35a19553daad53e8dad25aedd0e720c8211559262a", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040e78e9d1df0d544da046abbb0888e5b40075328b92ca953ba7226aee99406a2623abbef1d483b7508a45f990811d8220c33ff72c5ac4e8d9a0e378abd48694d7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "040c83a1a878adae662afc9cd194ff921869f77080dffe5563417fbd0510f3da221742cd6f1fe27640f1088991935310e8f8dc7477e2a7836ccf9a03675692b7dc", "U": "0400643c370e19ac236d270985965d25082257edc3d3eb9dd94faec2f336e8996c15ca0888db5f218101f85e4da3ff9cee8b8297f78d7b0b9fb8dccdeba85eebf8", "SERVER_OUTPUT": 0, "V": "04021fa69fc96f4ff8931b3eb2cb83b8c56b8b5fc1c05abf47aab546d49b3a5db00fcb2426ace66578444cfc4570c56968f3298b0ad207209f575bed0ec38ac9e2", "Y": "07afb6d26589c9815ca51ffede6b1f180c50ccb81dd5d10b53a81ae3fb864f8d", "X": "1426ef6ba1858fc7db666e41b9da3f043dc2b7c2d22f4e0389734615bcec3a2f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 205, "UT": "040e2bebfafa45e379000e4244c1746858c2495f8a81c5728b5ddda94c0da86463125d3b643e0dfc0e8befd70d75bb4166b6aa71effbe1af3a900b57163df654f6", "MS2": "0bc74a0a61c8612f1ff25f725678e0a52aba95569cc85d512e3260a00e754729", "MS1": "2386bbed2fa614246d40ba2dc3d7f1c44a66011577f00d40c36dd75ae0111ca3", "CLIENT_SECRET": "04201d5fb2c7810886d6f3d01f730aa6008f90d44a9d91f6ca63ae88c623cd019717043ff4788d13107286b156a62430c11266f86b6d57c6b90173bfd569e9e320"}, {"SS1": "1f719fa821209496c47170865f91593b1e6a672fbea5a265402899b0aa07551e19cb7d7d8d5c2d1f6cb1ac7e2dffb8c982a9ce369e8d6424796ea44e5b911e69038101458ebd383e2acd588b529374605b04bf4e394e685be30c185eec4c45421177ba34a48db14fc99232d8017c87980b6b505c4869a5ff8cfa9691caf7ceea", "SS2": "1d611000c7215fd87105cf5a80cc8c881755cdaad6ba681a37f764ffa29c29670ceda8f89e42ddd32b7e5fbce28420abe9e4361e49ccca5724a3fb7fe25bf2e000017aa56e134c5c39411489783c97e51254e9f4de3151aa7987657c76740c8106125484e72029770b30f3fad75d78575832f36c655ca1c46e01f80d029787b7", "DATE": 16580, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "019e4a9ccebe61d4beb3c35a5a73fdc5f498ed7e897deff432a21ff9ae4175ec075f1bf8f03f770ce01fc449f5889f096a6394b69da19dedb126aeddb02dc72319c4ae96bfaef3c955fd26e4cc2223a793be4e6aeabb8d658ec2c8441c71c10106caf2b7e73c1f415678bda6f7829b64817588f34a22a1fc2f69c5a5ce790c07", "SEC": "040fcee6d0c30800fb066999d399671985c25a26a0b13a2b2add55475dc80eb5ed22952f71d7bb14af3076300ff5e39ee340000ace924b0bedbbb78e80d1f56844", "TP2": "041f6ede348de627dffa29e970894b8a9c3a9e6361ab0f775e0b207e31c1864297094006244d93654105af1f988bdd2682e90af09aa21302d699e1af9238d9b829", "TP1": "040597a0b06d012385d5737f663530573d3fe1876a50d63df33a92f40f320241d81faf38bf6da9b63d0b7b74b642b1b84e4576200e18005de2ed9f9cd637bd8138", "CS1": "0412519bd4ee30cca1c845251abc031d270e2af73ba90fc56207ac5aef2f4401cd1dee4f0f92e9ee2fa07a43857fcb6abc51c63f7697046657ed51a802142fcc8a", "CS2": "041c7f7d3333bd999a988580049be6a51eefc6d49e7a49537dd1b947b059c2f334082643460265fbd05d5ad91b758bfb95e8c3e054ff9d4d323758bee6e69f3769", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040604899ff4bf50b31ab061dbdedfd2ea6d44da454ea3f31c17b23dc300a3b688051083135832094fffd90894cb627d2512b9654a9012f33ae0603e2b0718054f", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "041a9c1d39acee8b84ae7b8ea456cd718fc4c95de04590f4f62f4f444f41ba0b7503a41ead3f5245be2045ac1de8c5d560237be9a76787f38faeef9fa286647984", "U": "0401c55fa7ae9b3dc62c5ba820eafc7935f5d488a8e99f293f5fa88e02c832d2111c26a539aac1fd6f589528ec42ff3570d21e8e075bc23e0689d36a9c0db701a9", "SERVER_OUTPUT": 0, "V": "0423c2b6f8d0aa23a4ec1287024af2481b1090c02f283ac736c1e1c27893074693058b445e40ff00e38551f5b40e30219614a7d35e7c7d95ae39e67bac725b9a8d", "Y": "08a5961a83abeaf8075602673972f3cb95b93c142d368341d834892b29aba0b8", "X": "094c97c24951b46c4ff3a1f6f11c3723cec7460b8b94a9b7164e19057b697d98", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 206, "UT": "041a265be0f6109e0db83518d9ad81e5c1e04b9c8e12598d1e8e27ae68457356a11fdb24da0d3bb21d26eefb0c9405c2b4a3ababedeba91e2e89a801cd96c8bfee", "MS2": "1fa383d70f3d329134d236795c685a3b0abbdf271412fba4c7fd14f902e64851", "MS1": "1fe204d02f9e8d6af6ecc31c3ffceec3333073db2d9b7c299b2560cab5628a28", "CLIENT_SECRET": "040ff5ee6746c60998a479918896d3ff7dd2ac29350af5fbf878adcb0e0e6defeb126f9da1ed0549835c798fe012fcd8671473f06457ff244aeda5319f850cd4fb"}, {"SS1": "18e071939040ecdaf7734e103a625ec829d7b9478c98c44fee1c877f5379e7a414df57892db312483782409754b48555f9473e0f7bceeee261d09afec05c3d0b1a434780a52db25ea7b3d4dff8031fe4efed3376e184a3eedbcb35001198239702965f841faf9c91e4267309196de92bc72969e28cba37e0fbcca541b8fee0a5", "SS2": "0b8f7905d84441377967cae470c64d94984f553b82d96f42861edca5546efc4b155c63f3ebec09c2c7b91cac4fe8cd22103b4dcf7130702db65162a0fc4a194a1b131895582743bbe640c2487764d6636d199d3ae318ba49238901c9f5eddc2609b967ee7b42486daa344d7e11bbf19dc9aed2bbbf6ce19a9425c8e9a21f7202", "DATE": 16581, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "07bafcf549dc97680d5d03d9142743b84fce222a54a949c3127edb3e47aa805e1c51109a6952bffd475c8a8bc10b5106993683e5f3fb194078b17c1e5875514a1922384aa5bb45b3f6b71fc5361f820b00f70c0a22dcd91a14f948559c48ff96128e392084c92149d338b779b733a08d42afe8df6e2b1562798c1323dcd4d40f", "SEC": "0412be3d760a9eb08981af690d630095c71a18e9134f3dbed6d375c5255d1e7c090900780ac2892962e7f7d9545373480e1cc5f4a46b07850cee0e8886b0deba8e", "TP2": "041dd9c72516d7189d5cf55c3efa5b0d923d2c3d7dd3207da4b339ff2352f3204305fced6c9cf4a0973fc1563f1ceff976c3611d2cb6958d49e5a38cbdc0e88534", "TP1": "0415df589e3211372847f3a3b05e445f1d3d1ce3931f6bebfca47411653e383359140969ac68f3eb8dc917a6578e80dec188e24269c02db073c0db227a2e10c552", "CS1": "040f791ed5030a3d5170dd9d67656b40fc27b843978f8ae1ea7f93c06f61ac61f50b93626b93e277c203d1da473bcd895a06027043dd2d72735550467f7d0d68c5", "CS2": "040c5f5eeb254f04ef8b02143a9a06cb414d2e7b63895cde445a4d83ac7703130522b2af86a4f5a571b92d3d9346bfce79bad4a5419027afe394f98b0b32e46c2f", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040aae717a278247b196fc486057e41db214a33d4a111099f378aee4ec3bffbeb604744fa4002820180aacbaa738892b4d07704c26dcc025011b83b8e50273073b", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0400f1b8394b851f028d72e0a43759b649d07a85decbf05a880f0e513ee5d8d17715344ac4a32e70427904c72339b534c7f5fb9af11a057442705d37c2712f7471", "U": "0406f3364a098c91aeb008bdfc8d7da742c51c22f30151b78d9773b84751f60c3e0ce7f879f66c9cca0ec6da20bec9cbd312111f9639065297873891dd3253632e", "SERVER_OUTPUT": 0, "V": "0411aa0bb26157774950c8c773ae3790675c5702ee65db33646a3043852599ec570350f3c29833b53ef297cbf48047c497287b4ffff110019228e01a33cc64feb3", "Y": "1a83349891bf65852439fe29e56ce3a87d25b4ce4a64347cb3c32ea198201492", "X": "228a9500bb4f4d2cb8a8220a1672b5a35d9f90b879f0339ac37846db01e3f581", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 207, "UT": "041e68b6fcbb517124bfab6cce9297049fc81fb7d9480153d97bda0c4ab9f9ab3e0baf1baee6d89a648b2cd4b5ee817eb29f142b4d21a04d77372c66bef3182bdd", "MS2": "1f0393bb02252f6bd4425c1c3613fddff20974dfcea02d8afd10c2d0f6d9a232", "MS1": "02c3a340ed4c93254a7021d62f6fc0b392499a728071d6ff13eb5dba8b48ac75", "CLIENT_SECRET": "041d8fcdc39cd27d37c3cb511edd74653c1c3db7e8683e7d6433f92e98e6a05a801539b5f4c89042aa37dadcd0ee1686489a7262e621ad83c9346695b920ae2450"}, {"SS1": "132ed8bab703dba834b53e3b79b59025ac3cea61558a67edcce52ee9d3c3c48006e852083474cbd5e8f4fc365a23ccf4a4fc7ede0bbdfce1d0b550fa28a97a441087abaa810a30bd901a3949ec3a500bf61a7ebc713ed555149e465c12b9303c14c8c689c749e4c9180c014b84a0b20d03a6b3bde710e9a42ba81791214f27d9", "SS2": "21b28d7ae470696ee2c26572fec1c14646236350d54748bfebc3f4d41ad327f910d242e6410c37370b10beabb5cd258d01aca3856b4fa2dd872ed2d49c99c73809b8911a84888de344f7aba31573f26ce204db64c83f0f6bdf8f7c9b6fe715b8213c691461ad7aea3f86cd61caf5a776bb1690ecf663f8af2f99000bcf86d898", "DATE": 16582, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1cb7b02b4e20586a544ff9c672182af8c8469db2adfe28a877f6a26058c033201cb770d7e8ee48c843701949163906532087efcd49c5956aab6d97aa58fde39a002367481487f78f045ed91b26f33eea1e3ac0a9433120c3efe6f8209b3808ce19d934a5b4fbbe8b5c99db46f901c32bfa966fb7f5016c6979c13ee3840d92bb", "SEC": "04077335ceae145482d8a26bc21671a99b84b5549714dae052f4747d71a2190d561b05d58650ae0f2b1b51cb1ae8499407cad2c720112b9c192b548dd1bccffb00", "TP2": "040a048ccf8bd0a2c09f6e2244f1b2ce453178fdfc402169eedec7697934a362350bdf2e1dd460438f49db9a0460cbddb9ace78be2be800c1de95cfbe7c340c3f6", "TP1": "04120df1e20ffcde1c33e08e8f930a6ccbe4bd596118044328a6119cd6c5abb0e2174a60dfe0815537fb59b833a85d7fe07bbc42e0694b1edf22db2cf8bd04ddd9", "CS1": "0406ce891b108a74baec4966494558da3c34d8ecc2437033da6db98d467e44334a04f5265cba1920d2b973c222112f2358f75e77a1291bf26d06ab3bd55851183d", "CS2": "041bbddf015ac92a8ce5fa144e9fd488a80c4e913d1b3832941030fce5936e8cea10efe7952130bca6efd1f3e2d1b282c4839c7bf083979862d929ac39891f895d", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041051813c96d169257d2f61e2f57de3d91bac044a0bd93c5db1ebd64d36281c6709e612c6d6b150f9c159114d1c1e8917e36eb718210849b252d4b137d120e25b", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "04052494fbbb002bde392437cc4e58181afec2beca8c3a10c509539a12947b68c104ba87c2361c5ead8c8133d9368f0066ba1b87a57a190aa80c8db9ffd23b9609", "U": "040c716f5daa8b647d14d6c0bbebe64ee496bb7618fd72a7731056cc5c680bd13f19cfaa0b3caed1d9de103e90f179bef4c95a9352b04a1a0f6656e3ca217c1333", "SERVER_OUTPUT": 0, "V": "040392b5eece61a3fdfb8e8992eb38a8bc6164f814c4d3f9e1ddc8b6f0c24451db038293c903d078bfec74a27c378f193133496e3b29f22958b6d0cc804ecb1326", "Y": "15f071d96957255620f415c2412179999bae9a1cf42b9612ab8e2591ae098bbc", "X": "149c20a5e66e23c4e34f0987817b2973e2cf95b12b2b482fde4ca84e63c18f03", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 208, "UT": "04094659ee651852945ac36bb5163cbf4f11815dfa8633aab93a8231671c7dc4fc15630eaa96dc2de4a9a2e21216396953f9f5c3e9c70b9bbea8614222b4993ffb", "MS2": "1022c2d3ec46dbdaaf66e4cb11fc94b0f297df661c4fbcd2a5f7d1de27ad8905", "MS1": "0e10eee9738fdd25fb32d6f6379bb91a3e68454fe55b352e91df4540ce72a2e8", "CLIENT_SECRET": "0410fa2fcb8071c7e7890125798d7471a554da65a5410feb827502c8faf40a7452057e918da9b5cb96b494d4ee77494ebed6a584091bfec60838e0af18dc743b95"}, {"SS1": "1e521b749fe9ea4c961f567c123da1bde81a6080130516dcc7697361a20ae70b020e586c1049082070edb48b7beb4e98172f44b9c234edf8662c8c11c810a61e219db29f06fddfb85ccb183514c4d021ad9b9bbf88343c3f9318062c323b6b0f0f739d414be1b582b28d6231aff2b24175065e5118901dcedab07ac30e4e56c8", "SS2": "009f6ee34597512147f10d83327b28d6660f128ee9ad22e71cc585c993e049760b533d6b32153d3f09d936477a41d7b0083cd17da538fbf05d6d4222f11433a403582d7f4b4f92e69e5be7ad6a2eb8658654d4b3f8d7a00edc6f20cb903d0c7a184ede34320c0584f4fb32e2cfc2103ba19da6d03ffaed6e4056213614ca57d2", "DATE": 16583, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1d28ee97dcd6b79b0ee9e57110e31c89d347afc7d4aeb9970bbdc69089a518af23168d2635bcda3a9458b776ce9b63d9dc87062036596418c1b3b98b7157384b10bd05b596f4dda9ea865bfb5b234b761ac0166c8a76ab00242ac6f77879650a033919b3e2cb80a84ac9d4092f073868fac52a8a61d1d69ff2391ecfdf9aae12", "SEC": "040fa1a1b593c48ca3ed43fe35ff7a9477cfa6b8798664ebdc8599864a97fe9e240ca89e44c626f4ca647be474addbcdf0550ce158a7a53dba522bf431535ebd79", "TP2": "04021f5630ab5d9508f97e40d4929139fab696719bf4abe24d84da87ce0a73fa0500ec49dcf062d1820b169eec4adf1546967802506df66b44b1f8aaa064a1d175", "TP1": "041eab09171c18b40b7f0b10a9864631ab9cdd01d1e8b3365ac9e2064a47bf10ad017296efbfdffcb5ac16af68f299e6fc6a629d60dc2d5856aba7960e6a644243", "CS1": "040efa53e84c899eb4ab2a556034d2de24e818d3ecc069e350a6938d7552ad079217fa9ffe1f3139326d7cc4c47b7ceabad12bd177319ec747ebc6c08c55848246", "CS2": "041ee7eb1c0fd42ea77bcb517064bf536435e1642e688c7fafe109780e7e9c9b470a37244d0184dd0204a855a790fff0440adfa5ccce745f109a97d774ea117c58", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04148300a659432175668e2cccc8ae24fc1a873265c86d43812b238e5c1d56750d0d4e4676408eab85679e75c82af451b34cdd27fb74745d25e70c3211edb2a6bb", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "04152d06c6104c68cee61f42f237735278a33f2b20f66adc847c719460d356a6a90820a3497b6b011a77a6ddde944ffe3c5d455cfd76d2441b7db489f9f5be528e", "U": "041a18aefd88086ab54ddc355766f7385d5a3276f30b4d66d7b39c9adf70b55f431123978830df093a8c0e7bda0eac59207f9615d35fe9214e8d8058b1fe70775e", "SERVER_OUTPUT": 0, "V": "0400507107cc806c5835185a737b8d0fb61fcb363d9ccd38a945e3d6bd243de773178fc2cc3d134d801e5bea74ec67911e6177382b17f3cb9ada494747217191f9", "Y": "1843f43e3b2b1ed1d2046880d756a81fd605c147d981036561dbbc36ba92fdd0", "X": "0979058ab0c1a7c43f4b745492a9def95f4741e13024c98bc46e2f9d9f20152f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 209, "UT": "04077dafd5613402cebe6b1ae420e1a436e3f7be6495c7616f21a3acb321764872232cad1b32844e0b2dec0d61e29a8b5e552bc611b001a6b91c49d521ef7f114e", "MS2": "1fd117c677dfc24494ef16bc58a382c02512448e36e71982e88bba1b25462bb3", "MS1": "07a4439b2488d6cb6e1a83c49a51741360d3b8a91752d8a1b2d53528753c4d96", "CLIENT_SECRET": "041617a5b9cc6f6337c7a86a4bbf765902d91c41ef7a279bafcf012b36de9aa40c0d6675ea79df6c239ba8673764ab0cf5420bcf41f469e7940b3f8638a0be6af6"}, {"SS1": "10e90c502f8cf7f8e60fbe788e12fe553c676bc21dc03e58cc5d79d2475e70720ae6bb2e8927751756e4484059c0d8b7ff5727c820eee9af6c728f2abb27a0461d06d28bb4ab8f480fe8b91f8399443766ba4b81e2f76ba92b358e75228fd0241a9da501ffabba6dc7b3d7beda473f94ae31e927067b6e6063a152e8a7df511c", "SS2": "17a75119c2450bc438b73e503eb97c67dd2d19d995050153f1587ab0c5560d420b8b28bc53b14306a25af29c05d7e890704a92d9bebd2294181d319364513dd31d987c469f2ff990b79e3cfd00abafe10fb159d3e06d6283eeb0732cbaaf0c030e1a9fb7d8f8518db3f7ab90368823953f99c67c9f6a3a4a13fbf4ef376ebbef", "DATE": 16584, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0b5081ceb7d3fed54f7625b1b2b4ee904b4e796fa5dd9c9262eaced71d9b4aad219968ad157818a9dee1cf8f6b6a36c049fb1cc8a4ff7ec0f6738b8d27534ff2057683f19c2cb8296f5a69df596c5e8177bdbc5fb23a6b8750be217f0ea1129007ded84d6eaee7fbcbc95ab5254b6436d149402bb1624a8fa4fe300ba9ca7a43", "SEC": "041b46a853426076bb147eef3a5d83f0aa2d0ab6343557215c40c5e0be0aaafd901732ad7445214dc36e687b78068ec8423ff09f14297b1ca68d938348d108351b", "TP2": "041e2ee5019f7f75eeaa779448740a3675225d0773b564c69ec1adade5b9aafa1c02e35ad8b4390b144851dabc81b293508f72db40ca84cfbf112cbe76d698ad46", "TP1": "04081878575c97930d624ddcaad7d5383f53d6a4c6ea8d8e68faa5ee9914e511401cbb5f070ba77f279e1a6b76fa131abdc24508a01f72647716788b11f9cca49d", "CS1": "0408f1121c6004d878d3e054dd02dfe24e8df50862f0a519c0f601922bb43379210cd8eda8d54034446d3db8251ed8bb17311080ecb2c2bb7a044d45e77bd97573", "CS2": "041e21792ad3d7f1aa64252a96a486a9a6d8d8762959474b12c7fa6cb175c7d0d301343fc43904eb0974487fce0a6a30983c14461d9654c72af1fa1531618f2847", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041619ddd0c48b4c5c253d6e4d7584d126145f1bedb583f6b848a247aab7e9c5331378ad6cf2cff29a62878ce39e227536a61d90ffb4b65c991cbd19481fb5f2d1", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "04079e56c91708d8dd70c5f1ea7d8a2bdee7dbbf708ee810be4387539df0ee72f220c68df84a3ab33f7f27c1656c754d4e915c0f362e0bd8ab19a21881b74a8b87", "U": "0410b35b06200427dc6d9b70d0b2d68dc8915d07d8e0085ace36f9c630c33d39a00a49751fa3801a8099c3b1e76fb28d81713fe6995657ef4efbe7f8888709fdf8", "SERVER_OUTPUT": 0, "V": "040631395a067373d883da294145857bb356ec75e43998f13e58e5e7106c9dbaf6019b928713ade4ba870868ada5dfca82f4ef17e63a1b8532ad363d79342db33a", "Y": "20f5b3b880b657c37980c1c14d442212ae42c44c899a8f9d6d729e47d20e1141", "X": "0a741c8c3e6b7456580f8f664e0525ea9cb105ed17223a4f9a769b8b2ed31402", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 210, "UT": "0414c2243d3265fc7797a71ceae38a88624307bfb67fd6227ba7d541eac0bc456c108449f04e5431934daedbbb2334fc391a1f4308bd2da5d31a462c9e9642eece", "MS2": "129e60202eb40fefc9c258ea02c3ae5ff4599a5e508464746c4f1581365c85be", "MS1": "0baa03a9f51b1e0d9c7df00cbae4c7c0bebdf98cf2c2400d93173db1b1f5470e", "CLIENT_SECRET": "04058346f67b0ba31df4dc352f6e4918567bc5926357be18adc3596b7c7c721cef0a2f107e47f539c9cf5f14880653d0d06949d05c9b6459b5ac03e91a7910db38"}, {"SS1": "2005a0015aacfd9eba77e0bc6ce5459e1af5631dcfb3bddbc7a8e698a8b0a39b1e665abf40df5a4522a36efad4576dc2f8f6542915cdbfb25b7865f33a40024f018739e4992e7c55d85458a2889dede8eb5ab0abb8a793e177faeb307e4e5438031aa1310f0ea43581bd47bda73ac03a9568d67a6dd4589235fc833486f8dfcb", "SS2": "1bc1823c38471c1f181cddbbc2b24db3a1ee43269f0e10d1cb54ed97ddf81e810ae07a9ee7a5ef6e111e19a801603b80eff1a59904d26e1bec9cb8347bba485e0385e9284c974c6618fe8727d45206cb83a734fc87a0ef9f04471f9a6c20fe3a126eed9cbb5a6d7329914f60d147fa4633f5d95f89fcb6bfdf2ce028e5817c03", "DATE": 16585, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0c10bfc96c3da7e7158294a25fb83ed1dfb21f60b89ff34fea437735faaaf2f41f5d78c03d478aa46f7c0bb5abc4a5c0fee41465807c25f34637dd1a86c1430902e0851bfdb69de34b90b495c9416b75e3e260106187c78d570f1f99bb30586f08a3b25a47f761cd954ce7a1ba5f9487340b1df60965be6f03a707cf2fc10aec", "SEC": "0401eb8780696e05e02b04a13b0b959294dfb56162c98436448d0149cbd4dcc66216ebb6e758722611f39d19075b3619cce9d53b711e72d39eb251d842fb737858", "TP2": "0404cf4e677a9bc9724cea272dea637b8a2d83a95a51ef247521bcfecec41f6dce23d8df49eef63ff31bb5c56754e8721639dd8bd6f571e06891767598605cc4bc", "TP1": "0413d2c2d7fc934352091e70b6e4eefb4436bad6217db64fb61fbb041b76d766a7218de4927d4953d42c1bcda8c20c30253e1d3bd717a06f63f4f69970e71d304f", "CS1": "0402178aaaf26e7a1f58d6464c4ec762b00d62a0ec23aa7437dc1a58b250e54f88233f6b6291866d12d02e1d3f98e710185c9ad0a6e49eb565c996409c88de1f07", "CS2": "0417584fc718db605ba5eb1c583d9b9289e4f211ae09c571779edd1f807e942f49104fa007be90ca933b594fc2438bc080e2c8920d18c1453d32990f16085e6a05", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "0410c1275b83da13ef21f5cf6cd895c5bf10852aaecb2ca06ddaa03111d76a974b1d9f1e234c054a389eb6a238e0c4bb884667f739bde148bde8e46b63d5dfbef7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "040eb9701cdbfd450fe9387f2d4163061c14d23eb6f3403af0dc6566ddd3cc353c1289722106bbc02bd73100eef44917229bce85c973cab4b05ff8fa4179bac53b", "U": "041260d3b5662e9df84fdb05e9ce52d42912ecbeff47f3f4f1cf5898a78d2855de0ca2eb3c736e5749b0b7231f9ce471040ed445de6f3f4de13ab95e640c293f2b", "SERVER_OUTPUT": 0, "V": "040017703dcef73984647e78c94e2e3f9c606fb3753dee4b5e2f2e3fd312cdeb8a04ee5d05ee9a66183aa47413e3de611ca7cae9ca43045f11ed24e1b41d427347", "Y": "0fda90a46a78d7bef09ef0d67a21ad270a66e50be63820df2aee3c0ef1c68dc6", "X": "20487802ac73cf03a621bd504fbf8d3c5adc98a43b6bbd73e35208ac1939b5ab", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 211, "UT": "0411975154ed3f3aacf72bd3d6a46064dec73bbcc8cf65af5727cc97a712c62c14053b946c327f3e2aa7b49a793f7cfa513d71599d95791d464d93c813813def9c", "MS2": "0fc56120da81f87dad9e541275191ff54b8882c8a89f001f199aa7216ebc8c4d", "MS1": "226e5316a221feb3bf980d21bdb9fa0be3a1a3d92ab2e19971e0e4f116a311a6", "CLIENT_SECRET": "040559c34e8531e0af93e0331cf22e160b9589d6a20e5c0f117dd7ee3368bdc71f090e0a023d5dcbb7012736072be1c8e9e2e21ec8dc48ff8e55a7b82dfd9efd8b"}, {"SS1": "1e91acb16340dc3c2e5eb084b59cdc13e6f8416db8326a12aaf05989b67d164603c00a27cd18ee32407bd054c171514e8d3db20446b4e5eaa738a40a3eef87ab0275d5918d784d1f9de66fffa2bd03106215a51a6d49dfbd14a3b8584515463f0e7cdaf371f279c79b5e61bb50e4335f0cca826bb60ed721219905b3b9237fd3", "SS2": "176fc48c6477acc413d1007f8901c3fe2a1c459ab24c8f10d5f12a8ead6dcb6d14c951b4c6053b2c08896e93523b89ee78594d7f58f9b6fe795642f18457a6111bd6c06303f2a679e765f217a6f6c23ff5884d632f14ae4285ee39a450f738be1c217faf5c42e1e1522d377985d449f18b7784811debe13166f705bf0c84f76c", "DATE": 16586, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1b3e7f62ab1bfd3ffe2697fb1cf2e43677cd55bbf55b250a2facd83988a5de96073c83f97b4e1a2a0fa7377e859cc604d15452b934654a5afd09c53bf9ca07a108718e8c3e377b23eeeb89354db972275d3c0af54e3542ff500f62dee21cc0cf1379ed5101d035cf0084a970f42f64c3936bf9243e92e7e847bb5247b9585498", "SEC": "040ee94c30d790a5297502c7ac6d454be147f6bd10804ba4fed02b45132a2a197e1c028957ce4230cc663a1f469953490a1b83ffaaba7fddfa110e2a943d743aef", "TP2": "041608709fc13c47614219bec0b254ce3c93ed21fa7219e9a21368e4653b840a8e1da6cad809b0326c806a1351ea3bccf045c809aa32a09a52af6fc958c88e2ae3", "TP1": "041e35948e9936b4ad0af9d4e2cd64bd8bf3665af5791e583e8dbc7c6a5028c2c402e567ba3c877e6d578e01a148833416e43ef7e7039f12e34366fefe1c9f015b", "CS1": "04198d77a0081ec86277b2c424124dfb31633ed83432c13d70b59397d5168d11df13d243e46cdcba1c84405c2ca4e220e18b1c36b6c1706117f1ea20e86c81d9c1", "CS2": "04149a55b3215e436a4bf501e987decd20b209e8bccf6502ab5d0e90fd67ece8d3221e9503a10918e7069817b6b9344fadcb22a23aa22306f4f611a0d25712544b", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "0405dc88512ffef7d86d6d0a23957bcd6d0e4d2bb01c3ec7f725b612be9b70129503765be557df6b231b3677b53ed4aaac0d8d2e1dc31644c003dff2a51c14b8d6", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0413a8ec4df142260627e57b7996378b0d68968d8ff76219f1d69aee30d163723c195c8e0b76d1a7d42091a8d88bbf1f675fbee430aa5b42dcae84f4fae892c961", "U": "0418a9fcf043161311f8c610624517d8070c9d9353cead51d65a3ac5f85f5d471a1b8be8ff787ed3cc020c7d7ecf5ac33e25f778afa62bb957541c261c16160d28", "SERVER_OUTPUT": 0, "V": "040e41641a2ac523d4e941b0c32ccdfb3cd60f2d7e3e342051b53baafa74f1e1f70249a7f1560eb3d3149e3327f244122fc7ebad842d796deb92ad212b63990957", "Y": "12b4cdc3f2781859dc67424945d45ebc3dbad7c094319e7da77e1a2671c5d4df", "X": "055c7050b735c3182b06b6b9e5a2d2d5c6bf17d5f7e910fbc41d52ebbd49c857", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 212, "UT": "04219dc129e45408549e8b6d5497efd3fccb0a0a95ef37ba57ea855576677217ee04cc8ff1c2c0eb3616a2526e57b3c6c176f3ff618476ade5bbb6106aff3d9f01", "MS2": "1f925d4cb81bf97148e10c39b76b7c51f042e7148ac9b602e12efd0fd9d6d176", "MS1": "02bea1c48ecc73916811e65eb3f567ac117aea340180306e36b47a4c86c19b28", "CLIENT_SECRET": "04153a5a3fe9ae83b14e4c33db264a5a28daa2191d51ef80e0dce4e00b4cba3b4a0b54b639784ca2068328de9818839a3202e9b3fbf7a611807fffbfeca26805e3"}, {"SS1": "20886af066b82aabcd2f3428bfbd8fcd6f70f9ef5efcdf54fe186bc89ab45cc31ebb889763af68a3a577d65cb4f6a1aecda13328283049785eb7e0e405a71d86131d2d59877f8745b3d4104f9f5a6e2308f974df5f7c559391bb0634e95320c01f3ffd185f330a7567de91cbdb3f9f2b89b319eeb5de75d91073f4b79074f475", "SS2": "14acfade1b6d7bed5b577ea8c73d3a0b9e9992c9ef03451445ed8eea13b8bf7707888c0f83d5fdd5b1ee7724375479fe6148d33ff1dcdf138bee46ba1493c17f0133429fac3fe924b05a825c8ba29d20808526f0b7bba5cbf6c063a821a6c72f0caba14aa2476935ea22478000324b9658042c57359be7f17c61e78595811174", "DATE": 16587, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0ce955470abd598ae5e5a7fca82ec6f3cfedbfcaacedc85aa536d814eacd35330f0f21268b19ec5c3f678890fe4aa99bff677ab07dcd4446deaa4ae857d374e220012f9e1f4f362720a83b1417eb2f6bba16612ce5c88bf9a443c984a976a1bf1cc2a99a5d91a4e258efb79de2389a4781a8135d571335158231944fc52f0eef", "SEC": "040cdf96320df72db60555fef85362e7d1c62e21d58b2e547f6eec9dd4f96d09ca0eafc8095de6105f617fa18fd0343f40d48cf6677a599c52d4b9c03e0ef14acf", "TP2": "041f2d7c929abbc4f42636baf99bc596228d6124529c71f6f9ce7fb1cdf9d3cef822f96c3ef9a1a9128aeec9dba430fd39c53e237423320121994408f46cb64f8f", "TP1": "04073a8b68bd65b3a940ccedeeedade8f2dc96b85ed866c1cd2f03b3a9667ce5a7092ac15a0e2ad8f950f999a051ecc5c0c08192e73cea2aec4b77c2b4a3df475d", "CS1": "042228d0363fc360931a90eaf60e40f325e0f4ad3911d63c5e54cadc658bf1aa120408502a927b9d449a68db482bcfa70c55b712fcd020f3c6d22117a5b8e53b44", "CS2": "0419b335a45b2a37ce2e3ef6ff0abf24742f444d7f97f207d451920c186d448462152642be94c099409cb4f8afecde4fa276630c3d6535c28c288cb2d9d50b2514", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041ee7474bbfb71ea3d9509c3b64727dc7113de2f8edbfabc407cdbd964f5783bd0199a63b0186267347f83d5659a405daf3922abe7d3d633d66e4540d7cbe6212", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "040179f550e43b8cbddc3495d07e44ddedc850364f1274b98bddc0454f75a2832523d48258d16ec6c8d3bc4fd781a0da385386bfff2cd0bee2ff9f198a95443063", "U": "041f6b6da34af6330921e1357b307ad6d17cb7762e0c00f1466a1c552a3927a70000f8c0ea59c334604d228eda695787a7b4a58543e2bb583d4f1a906356d49e8d", "SERVER_OUTPUT": 0, "V": "0406a8c357d8f18cbd2b74f9a77a007efc70953eb056ff9af09ddd239950a5083b001a2b28fc5756bb63ac11d4c7b928f7bf46c61afe1c3e2743984b1367259623", "Y": "05944b67556284b4fd8eaecfd8fad5de5fdfcefc0dc205c1ec83b55c8ed87861", "X": "00d4e78b7b9373430888be162af4d02b648e1d9627a8e7d59559310a2a73ef55", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 213, "UT": "04200da514bc73c2559e17bc631d3bbb954a9a9576eb7f54b9dd802bc8b3e388c00b8c29b25de2069bd1e28b5546552c1e8177f95bc3505a166b7df8883b3366a0", "MS2": "04eb8146027bd99a00a538672a51a593cb8c9882b309db59343309201acd4a3f", "MS1": "0ad97a89b3e270daade22b7ecfc42ab249153bb234f5a71cf453d91d1ee27ec2", "CLIENT_SECRET": "040b25ec60093cdb2efdeec350ea60143d2e8f53d8e0a292c3204d5815d2238cf8142f91054948f3d4ff6c51cc6ac2a6cbd6ca348ae1fe1674c6c671f300c7d8ab"}, {"SS1": "1a4826fc03e488286a4c67eb5166262f75761ea693c3465a63952004ddd7a6c706b5c60040887bed87a8eeef20700c6bd29758d6652177ef5b217bf2be0346cb05b0f344937896620cd5f38fb10256d9e3314884fd6bc429be4227c75c0ce78013587428dd2ccd9ae122f8f315ee96e29165a116e84e4eac4a7673c0c748301b", "SS2": "13c15214c18fb3111e3e72218172b7bd8ee4c4d2268df71f3d27b693829d7a7702ad00a8c42abacbe2f1f861322a0a9b34a53c82dae7463aa57e19b500b8917a0866aa94df11202afc3dae437b9bfa727691f82778e465444328062daf987e0112359d75d85e822a00792156ae0a15d0f4196430e9ef52e12be005c9fa0e605f", "DATE": 16588, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "00999b7ebdfa734ed659c8ad09ce5f3fce18f853f422ab65f5c728d877b37e9b13280bd0f21fd15706fb77e0b354ada81cbbffce1ab792f24d7cd1453922559320f88922cbb37ef26011222529367b4afc79414ea8c85d07b4f4bb911945cea30b910fb81b2676264a8c3c0c9012a1e7df58739aa4040648e890173af42c74fa", "SEC": "040f894aa55f6860352d42f899acb644fafdd3b799e51ca7ef9008d717f4482d4119185a4aab6de7c9c87155e32b6907d2ea2d6a691aca1611fcedd8501b10261b", "TP2": "04195b1fa1478295ec1ab5e0bbdbaedf2cd5ef670a380d918f195df014bef249040f523560226d1f28a60c695dc53f283da810cacace0492ba7b3473d3863697df", "TP1": "041d545c8409efcaa2e185d9ea7b19cb7dacb2772d13c707119611c7d7680560f317453758dc4c2e4a36ce87592be098bd62ae88ea87535d95058403abfebb0800", "CS1": "040c39eec5cb0c73083ad2e81d143fd7f28ab9b33a2b96c2d856e3654470b4571d162c1254b144c442b11a09cb31fa5a7294e0affcae3ae7a2ebda9154f4786db1", "CS2": "04233ca184a0f8c2374cb987d52c37e272c0d3a615cfc2932bff1a6ce836e71d69061c46bda42e860bcab25a8609a6c49edeaffd841707635baa324d1b5c75106d", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040cd442800fee834dd3bd0fffd8cc98beb6e48f94710ec7cc913ad9abf2317f420c1b18a7bb7ce7c06577dd49d262fdb5273563859d0c40c48521752f13ad7660", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "040099e3f3483c91531cc67b21394e8283d71cd82f884a69f2b1c664b85641bcb6174fb6364ccfb2568dfcbf9c463fc13f230960a7cc28b328458c7be911ddd789", "U": "0406cdbbf5e20d325f5e0b3fa90dfc07137ad3aff574f9d26f2501f8ea3c48df2e1523386c49265343a17748cee360d63f63c9a460e3af3e380110eed8eceae3c8", "SERVER_OUTPUT": 0, "V": "041c9b82def833264fba4a4f7152eb178815e5fe8b7f334095f83effd18d0ab32702220da45551b22013b22c2120e67bc2c3616c7e7cfc9d34c4878e31200d0b28", "Y": "228b34002502c5d692c40d9ee046f062dbb9dd6a7c5f7a692c93f4e2689d0a25", "X": "0b172aab887aceec935bc7ae4124785edc849d9500826fc15870076dbede4ca8", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 214, "UT": "0419a64cc11e036978603d0ff2f5544841ac60b9664d008589c750ffe8e7e995cb0453f88dcc59cb0f3136e3992de5321a62f755aa3d6d911cbec889592be9e516", "MS2": "07b841b46a8724bae78fed54a42e470f4bc654354abfbccd411a077071c7e74b", "MS1": "0fed8bdfae7b5ab136ef72e23934b7134e79e299ba545602673cf2d4c0db3214", "CLIENT_SECRET": "041399b5467c0a9a29de498c3a888ec195c4ec627c668c22d64e5d72751b3071d521446d80a4f0aab821ef80400e980982ca31db6450d9feccbff69cc8dd3dbd74"}, {"SS1": "11808609f12372a395669d8e2792c5c473910364736ee2311ee38fbb59a7cbc810a4d21fb9d6c0921c0e7ab1425788857589d6d2b828f1e1c957ef908075cb220addc8f4376ce0db2c0851c00570288261212cb4fc6a240c85e268c8d96587d014fed3ffd92fc093640700ed36a3608780f893047866c4471a095999278afd9c", "SS2": "1ddd9adf762c7fad8215940eb0d20f3c94b2bab92c5c17a308d4b24c1de9bdeb1e1f5357e31fcacdcde061b3e1a625968b8960e23aeae96a68bba2559e4fa08605d17ecdcd5a1d8f4b2fd70e5f2fe3a8dbba1ec47c8a34fdbe78f6e6311c623310563c9e783348e5a902ae5a88cdc4b50f7017d1bdb51f9d3cf4e5ddf952fede", "DATE": 16589, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0950d1af79d12380b36e0c2554c94124ac58423a509956910bcb69539895670e21fff8d42db3a50790b72d38afe16a7b400997328238c573ec70ecce94b846f913b7f56fee8c1238b1c461c9c2465ef7e93f86424e8fa27c685631d806640b300ffeac55eb21c10433bc2c86dc86b1a734b82b83459f949c89fa4994cb3e67f3", "SEC": "0417d1d5de4aa2f64c2a88f9edac7020686153b8bcc0e9089013669e305ff6a36e23910b27ca004a25bb509166fde00e5efebce52f7de3e2d26141d91ba5c4c3b2", "TP2": "0422c5467967572e6e2e4fe4230b6f04c1fa611c469a90d13e8515ac229fc6059500e1ccdf8e5eb222e3c1d61b649b243599e32a7c4dea4733cf57f3413323e335", "TP1": "0404456c9805c34ac08c94736809bdf2c5bdb0dd2d9e46a91ffa706db629bde2e6195642d5af6c3b7464548deb9a58e02515a3c4a8e28d04f110de9781d31db1e6", "CS1": "041f26060deb8ac72d4496dd227dbbcc211442523280161b45650d775503982c8d0d5355339a79fb2f964fd9b22723032cc10baca18bcc0722071a0e23b0e7a16f", "CS2": "0421be0838570ab258e470cc696d7b22a24bee1502a7e01d2a96777817a5128e4b2200e6e7d8fda239011fe94de2bf9a6615a30f7b01cc8f412701ca9344e3fef9", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040080075a4a17d37fb0368e8774bffb9719f0108bdac51b269994b9fa3bf40bb00d038dc12f486972941c0d2439f3bd3d316027c446566d6bedb3cc490166fff9", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "041b07943e162a87397b1a0bba4208848e25ac387337ffa2253b73924ee061c8011c500cc16c78d0817c630b5913abdc732c7f45103cf56b97d078fbb1a4103d53", "U": "041fa5c86f5a7fcd7dab6e985406445f251b562c0e63548b54af6a1e251a86b4141b18f9cae3c85e8b20f0878529c262c768a70cc93e9a9ca85cf4157c9bdc1b95", "SERVER_OUTPUT": 0, "V": "0400a87ee4cb4570996218bb4462b0ac3fbbe6bcfb870f58050db23b5d857909e01c130337327688d173fec3f3a54006b88a09b76cba21c6b5be00412708abe92b", "Y": "213832698ce469bf5e62438511fdf849ecb70278952b85d0ee5ba52770c857e6", "X": "0d8f640fbee3e7a6b7dc10c53094ee031e8074a0e61f29ad24b2af1c0a1e698f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 215, "UT": "0416950f50ddc7a850323e673741f1fac7cd03106701d3dd4f630b95692f8c5fdb07d571fa6731c47a9f4da54c75714b4499ae15ce2dd1ad7cafaed6cf8492226f", "MS2": "2180e5c7362ab5b861e3e4874548ea676669f6296b0970189857a5fa670b4dec", "MS1": "1b4207aa31dfadcacf89774c75072b974111b5a24293d633b70caef4d52b2a91", "CLIENT_SECRET": "0410983ea485d7bf99b1c7b395fb4db9cdc1c442679d7d91388b6a90d27dae36621b37b6c4466082bd6b6f99151947b07ff11195e5b7eafcae798b6871259082dd"}, {"SS1": "013cbe2b392281208f7bd132148374ae2e2633232bf6b7c3685bcf83ecac9ae31e0e0d8f76c03530195682a045d924d1475cc37e87e5ceca92a75c9577e12c02132a8aa327b1af6642c31f319473c37d15d0ddc2715085b38388c4be24ec6cae073b860e4339b759fbc3e87a1cdb3413a00276cb9abb91e835f39c0c3d7322b0", "SS2": "1555e5a9709d5793a856b601f4e52e1a21c20f27cb206f2006f0e1fa6329a49e2242debb66827c6f39c09e9952cf914b01ea7f3c2e49ebe7fa7f8c36166c122f1db888a84eccf5363ff36cb6d1ebef5b6e80ce597258dc9e9d67594ba6fcef1c21f7d693edbd7c9c24e3bc213ed37a306252ea65c2e42a23c59b580c8ebf6816", "DATE": 16590, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "171f790b0daf9dcccafc5d358a3b7e987b061b61b51573b96dc88d46ccac091e1c38c94f214414741cf99cb39ff357cc44d68e0ec7bf697bc83cfc3a0c4ad82e0840681b46c5a03b7d3b30ee8bac463042a9caf2e9d4bf0c8d821519bf47588b23e9450d8b9bab1032df4c17de2f10b78166ef82e01ac68665e43e0ba9f58067", "SEC": "041ae8396606f4be9c94380ba7da75a228db8731b9434e3a14bdede4fbc29cc6d31ddaffc0e93f66fc5d6f101460a0f0c2ff03fdaec08215cfcb3ea78b74b10d3d", "TP2": "0421948cb93e0efe0383d5ed1ffa3a31d4dabd0771c9328c24247e15ec0fb0c221059b32bc1bec06934f4fefa962900f794f72dce53115c1a4472cee3d66cd68a8", "TP1": "04179d04e17cc069c1155e622c7edb66726d3edab52027c34464c90264f6fc47ff165ff121a809bd945959f384f653c416d96d632b18b08efdaad4e5bc12bf6960", "CS1": "040048f729f262e5d59c06aa446b181ffdb4411c5f28b8afd8f2a0e2e83ecaef73175f7f3e16ae1ead1d886ba191d751917a933b3a4c946f2ad80632d5e08e5fb5", "CS2": "041b9269109ce557a187e4f744afc01496139c79d46df957f918f447aaaf0aab5b1c34a20030135a3f873822f42ce0f1bbec15ab96cbd73a04a0aa390e529195ad", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04008f0d5f44e57026d272dbd34771086898bbc848b3184a6d971f6b35072c643f134cd3d49fad87d833b3ce9565a9f2bb4ff3119c67e0cf9a7dd91373fd690441", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "040c601fe7d7d83bde49a7c957fe35d0d5ebb81320b90cced4e90a57422eff389c1f59c4de38bc9029b2e8e419e72c871e3eb377d61e0d003bcc5a88ec757f4a6b", "U": "040cdbc8b53a217500cef95b024d66171d754a15d8edaee6bcf236807590d47ab32104f969e2e1ca776e977a40c04724b9119c2c864d4119e0fc7672a63013ef92", "SERVER_OUTPUT": 0, "V": "0422fc2b13612962e28c3da8eb0b6474c4fa6a6229475f991c426a3b204cb2de491fe445496ed5e56f6875f115329fd79f36a69fbdd5cd91ff95a2640529720fe9", "Y": "108600f89d8bbc4fa4df7a6bf6a5360c1904fd9464bb96153c949bbae2b04d7d", "X": "176436a4b9637dd194841aafff5cf6b732dc5b3bc717b12ae3397fbc1a1672b6", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 216, "UT": "0414868ae4bacc54c0cb9ae12704f54c89e28fb74a52913bf83582286df02de98f13b0666ec74b1d0964ce709b1593718516452c223f39def457a553f483bbdaba", "MS2": "1e9de368d3e221b1c300b1113207bf8123163a2565f421868a65eff7489d4417", "MS1": "17ed07c9642819f5f8883a3ea2f2a56e96d1ce614c3977c8912d72cdb545d834", "CLIENT_SECRET": "0413d37a9c18e789d462bfc38b0814c45a947f3576125e82c18505c426788e6fd40221fc2f1993fb36f1562f39146ebe7145b2577ffd00914af44bc2c311dda111"}, {"SS1": "18b23f43b620d9c2e572577a379607dd6f1116593023828733e96699c56546f5143e508fa047823243ad5f993fb85ac7399248f754cbc6de0fa022daa3f17f112021f78f59fb3e546f5a4ec78840eb72c4a26e6573f543b0fdc3fe87875b441a186a954cc4a974643bddf7cf3a4d8c5463fc30ff265b5e660512e706b63b7d28", "SS2": "0015a159457939d64619a910b89aaee8e6a4dc2f15fe034b4f92153fe04708350fda5adb95189e86a28a278f01742471d6ace0d3704e1ea561bcf1e1692aface111eb2f40d67726dc56b4c5640a420f72daf0156eafb753d83b47feef518d157137f47caee50d226236b8736cbb755a45ee8e12d1e10481a569a7a2d4cd320c3", "DATE": 16591, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "11aa06e2b392079e78e63ca9615ce1a76d69da0f7f056a45e4e15f2972e001e10b9dd6060110da3392942bb8366077e5518cff65ab8bf8ec0ca16984aeff0e0e17cd9c0b0448cb0633d7b3bfedf1cdbd655c2a89dcfe232b9519392dc76ce75908d84c45ccdf75656f02da70f603aaa396e8f7f13523917f14fa30bd0e33ae7b", "SEC": "0419a14800d2f8f24ac02ac208694c145555c1e406f4bfbe3292a7bfed73a526b20a1493a36dc1b77e54a1ffdd3ee53ac7bd9929ac5ef1e7a1e8156a738f7e53b9", "TP2": "0410a807da6ce2c707b7fe56ed0a3c8622f41fd86c1c030adc57f126a17fc692220755ee3fdfb7451eda0b3c628e0a1753544509d6ae949c44ec8f2848e15bc783", "TP1": "0411501bdf13d6f3d720e0e96bca24a1febf7552f2cf815d314105e9f04a4903bb23944cf03671d7ade2047fb1cab0fa5ad2e065ca309a7053691dfc4d046b4cb5", "CS1": "04160e289cc19981b3c611b35326ec66aac10a4685738e492e24d0b5e5b766fa3803b44382120acc61a2e70e5f34cf930335423f61e48b3d48a7f15e9a5bfc4171", "CS2": "040cb10c31814ed4eb1626bb9a0a9be4a27f33a52137243fa7862f01ce53c9613914523afebc00da8831e42a233e5ae1b479694f8c963ef27d84805f9ddda33b9b", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040c6b09f76cea6122e6da5bfd3b75b877a8bfe8997d633919463ba2c909a3de350bf34532ae4051ada29b652193af238c759c1ff68a9861471535f9f67ab8565b", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "042169c19242fa0667e18be8d8e846a513aa7d11b2bd42f6ceb34ccd0ab3b5470c09c237f41d0137b5fb682884392dc2998ce89452fad42973e04fd755624cb8e5", "U": "0415f44818fa2a336c547344efa9f562aee9af8ea3921d8f6aec17a9643f46f7dd1070bccf88bb2e1611e492fe5859685f82ca2db2e32aa615c9efce16a548474e", "SERVER_OUTPUT": 0, "V": "04104b17957f74450fa2dfebb6ac8507d4af076d9e9e5c277734e9dfece629d3900909c7863546d59a3cec4dbe493a1c3af5c042a805f9e9f071ffad445f165dc8", "Y": "028d0da97c19221727d534e7301d5968157f204da336e8a690697b89a3b42f60", "X": "1815740afac59b6e823a04aaa3f41ae536ca3a709545a1df7e8558e7977115ca", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 217, "UT": "04028c48754feb8ecdbf3fb659e38246724e5fed2156df199a61fcad8fa6f892aa08236eea707346189e2ef5aad77cbdf5243db80187e4eaaa867ccd2a00dce114", "MS2": "1dfa7ec1d5481ff1cbc6d82c8162df70631664da7c522178cac881a99201a903", "MS1": "23f7b9b594a727c63d1c0445cc4c3fa53506c701db8c9811fcabd2bd75c61d84", "CLIENT_SECRET": "0404912624b5a7e1809332e8c033eaebc5e157aaf94a80f7a40582864261a30ffd16d5fdb01176eb946aad4dda0991bcb9c3ed11b30217b7e7706bca1af8b83c74"}, {"SS1": "150c32a5a03b863bc6f082c5050cad2fcc480b91c67677dd8594a2f81db900b4009d026f4ee37a31b69a2a28942cb1c71da127885af833c2310af182ffb7edca1b680964f499bbb55912b54aba776ccfca5bfb35ea400f701abfb47ad25e99f80cff71ae63ac6e28a7fb0db20f06275a04402228cd6eae8208dc0587b4a95029", "SS2": "16507ba35be6ba2fb0eb52ad12e3bbaebd959208e562dff70da6da9f732e0997081da8d23b6382621e77f9709996f33129db8df56f7216b9bd7f47cfbd869481126992102868d5564e8efab65493c89c27af4283d5904663e5f7f118d1caae8311e711d77ad61f68675fc629fa4c2d93f131091cbbee2811b0fb6635a5f8e5d4", "DATE": 16592, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1c65095fec23ffa39420bf0bdfdbaf749d72440d9f16f0fc8c31dc42b580bdc90bea323bd17e17e9ce0307b394f94068e3ebcd66e7a34b4456726a298e51ba181d539dce912c9d8c45894df3014af556f1889326b6e916433cdfb1d5c5801865115f184d3422df0032c1e69d49e6d1b4c61fe322382f47db112c225ee523cb86", "SEC": "040e4dd7539a02726c14d043223d20eb6705cccc99b3bbbee4d84f092d8f350d4b1652a039ca5f5f26d9604836ac9a08e5724357ccbbb1a4c191c4fa16ed05db17", "TP2": "040883129b6717d37d301302689bc25e757c06175263b9fde54780acdeb907f24f18dc015a41c072e41a74e92b2daecaeb26c6c025cfd1a8047e7c1b0cbb94831e", "TP1": "040fe3e93da022fafca0c22ef96e15f389f1aa7b4365ec8377dd291ec35641703e11b80af318425c9b437ecfe5895ccf0c0252629a227e3f7a241e1144532f5e84", "CS1": "04086dc06a281902c92e7e959986eccad430de7aa18c5502dcca575a021bb939b405d412c82722752079558444a6f5682c1eeb0c1c15781df816cbb6aa54f0f86e", "CS2": "04158017a469003195856ab23304504ae2f1ad2df9560f060f476a4084230428151fe35ef3812ca121e64e21f7cd1aea1dfa777833b3672c902efeab92130c2fb8", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04226859407d440d67a8032db723876c822f2dbf246689e7cc3cff8a9fb35e8018053992defccfd35d72b64facfeb55c2a819cc6871f28ebc323d041a2773fab82", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0405f51d3728e68c3a739eafa43d7b5c09ea4371c49f4e468427d4ff99acc76719097f1e43706de291f54a5f80cf97e247844e923185670f8348c9178d5489464a", "U": "04104e0ce79b5d4bcd8e45d01940b5a4e7c422aaeef74b21f8c75090cdedc18c0c2052e905fec75590cfb79d21cd35c9b25a9475daf9eb85b0dacfddbecb4271de", "SERVER_OUTPUT": 0, "V": "0423156ac51366a1309299d6b49dbb1be1db56196bdd687f0843bff21c10444e2700163612dd5519826902f501b9591085db434c06686bb174462d02b6c3809050", "Y": "096c2d76e5b1202ce5a4a1f989bea4cf632b30b03c612fb395e949819867a8b6", "X": "1090c966fbf1c91e33c8bd228d15eaafd036b60a4cfbcc6daa87a4abd2aa4779", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 218, "UT": "041f66a0ff2095b1d7b8f082995a9e523a522e95cd37a7f6f35f7e4ce69165ca5b232855d14272f537bcaf920e73648c18798c7a43dea63c25aa22106a049e6c8f", "MS2": "1236ce4a3fa70ae08d16602c4b79d638f6ccc272fe79c3c627631039f83f5f25", "MS1": "02f9b390ce28e464f04932c995b6cdf20873f70314168164141645671e0df017", "CLIENT_SECRET": "040c66cb8e0498b5b886c5dedf49c1db4b40c073f532e32bfb3d58bda78cc2b1b91fbbd363e69828f8fe9a9e658b2ae461a609ae65b9f0202cc1d4ee375a5988e9"}, {"SS1": "229513b7d6ac0af7a42e3ad393da88dbac95a7f7542694134c558f674200439b1af6b6421e33a19ad97cba3800d31ffc2371e115e477671639eabf818ca308ae1761c128c834365553802a5a302122e662446db36de74827d03f48550cb9cc680e953c5f92c75b4d0559b08f463b7fa24417efe9251fb1f30ba897b85119a34f", "SS2": "036b845c5a6d3a24bf2e2a8643e5675e741b672f22f9eb679264b5c649aaf66016a15a04edcf167e8d11a24ec28537b24992604c8eedc664b901fb277a00d689161b2894f136bd180ee19ba789b817b691db1672da6b50886c1defc5c121a8a51a8e31b9b678c54177d81d90e14c49d862a8cfeb909eea2b16798eb3c7355d02", "DATE": 16593, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "07c001bf7045b08dd0d68c036b10d9215263b959618dd80260f70aeb5dfef947061b63826860be1fa7e48d42ed1e81ae485e0cd347c9aae0a4accaed618d664f0e4e7fe761676be1d84c11c7bc56f635aab043570933135baccdc11625bbaf6b11026b47f8d1f849c68d76681c2f669d85afe0aa287d1019f6a6d17d6aada00c", "SEC": "04027f916b0d14a5fe15a59cbd47d5c99737fb9115efd23f29a9c0d1f0b0458bb10e2dacb24dc7c04479eed542bdd0022e94e82c29d58053214d9b8191e3c1ba77", "TP2": "041b391888c6232f23d66b7bc84324e13a9e566a6989010e99aeab9f53e8b71d311a9bd33a331f2e810878c7f4889a85e08d7dafdd2991049feffd513ae86b6de3", "TP1": "041b484b145efdc3d8a6838cbb2278c020c1b766a16bf41772b12a79e240d50ecb0cb65e49235b69522e83bc9205e2e6a414e1c2aa6843239f2c68ffb4eece942b", "CS1": "04119eaf7bf4fe9ec3c41ba16bf27ef016eb34d91c47f3274cfaaafe35acc6d1e81a6323385ef69722c0372a3b02fc02385c237edc8f77a13f392b3c0a2bc82410", "CS2": "042087086892b12bb0344891d94085797640db9a08b2523f77fe1f7b0ac9b9999120a263b7cc90c6a4a7b2b91d2cb18a56537be166c22cbd9c8f424102d08adc5e", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040fa9db0d099030fd8caa5d0cb5ee2de4f041187d958b60af0b98b8a23c49c8dd022584b0a946aba8b4b32ce4cbfd13e0c97d3608081993275baffade6b1b7416", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "040597900e9bc7514c5e7e34e8ea43aaf521b939178b7e7c610de3762c4410cb5c0a430d3b712bc523e7590ca9a1dfb25ac1d54a0f5398058e4cc3fc89288b6571", "U": "041a1d2f5b0d44db56a5583e71d1e2998e4d063da6d12434686cc2fc2ee3cc057d16570f275fc306f75769f134e1fc9107e2f61f9d9d79d26fe6dccef98cb4540e", "SERVER_OUTPUT": 0, "V": "04235fd92b1d0b3c763db04baac97f20893787a486c0451fc34dab3bd900133e14212afd671486e77787f6ce123f25ef7e188ebd65b4092ed706412bccb109a96d", "Y": "0ff3e1594e9bf2138b401abcc8fa93892c7a08610f02dd87703d874c35aaccd5", "X": "1324fdc2c6acc9901dde749123497eb2905b2aa9c334005fbf3026355cf23862", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 219, "UT": "041d94c9c54e53da0bc925c09cc6d1b1c2159691daca21bb8033081ec123e03e941e0b5ead2eb98b4a3a48bb44f927419efd48b555b464fdb4b2389bf493b87efd", "MS2": "1d253cafd050e4b955011d70dd06ea313994b3154ca427c4cb5f0ff365a0b9a7", "MS1": "111ae854c93be18a04172b9eb5e929d580273d590cd4144005cf4318434140bc", "CLIENT_SECRET": "0412b71da332dfc8a86f23ef0a5b1dd31be88aeaeb4b5a753a0aa1bc1532ece6ee1fefb4c2bd911f8cc8fc0c70bbc32c6f071d958edcd9e4b765078ac01d00d1a7"}, {"SS1": "10d2cd0e0da36bf32ec54eadc15cda99f87403e2f92e4acbd69d536c8dd320f10c09aa785de571206f0b95168d331b1037eac1802fce278d40a775f9f01308af05e0eaf64dc056ab11d141fea918c5215773a94708c02ea0e9873101556e333a2396c5de2847971a719727e9ac1742877ab117f90e20e1c658331dca1ceb8da4", "SS2": "0687d13c8b6646b8d7ee2dba33a857f5fc3df7566b4f0ad15aa1538ff8523ace1299396d0689f6746bae5ebb0c0fbf8db1195436944e1f583b03ed69c6fea6c6022367dec8cbde8faab9086aab65f448ac5930683afbbcc1aeba9b6c71fd2a2917551cb72500b8e85508afc2049218459abf938d14efde62b80584924822cc64", "DATE": 16594, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1de7b3074e1828898756648d9d580317f0fc666348d087631a1abc3c01bd71ad11364b1f771c9ca94166f900b7b13ecb3b28fc73d2e0a4c6e4eee6929bdb22580df4992747f144c6df2f26b277952784f0360e6090ad0438c566f85a85999df01f99d246ab6afc12554271e9ab0e633d99c9d8541552c023bab5a5d0d2000330", "SEC": "0419a4172856bea7f6c47269badb04783911721876b541eb798546ff3c5bcbb7321fe203e7a274c399f798892216f83b3975733eb27ce664cafecaa99e91344e80", "TP2": "04188fe27eb89a6ee8561c36e6496688317476c21d803e92b6a9eded295989bd9f0baccac37088aa5144e710aa2e314fced1dfb26ef0796d1cf5d8815c92cfe14f", "TP1": "041dcb093711272f2b654f66495fd499853b7a50fa7ebca175829f717a4a36a3211f620de177626393e96b717722e2922dcd3be953c7d90abea2996cff53bdefa3", "CS1": "040fe7ba80e8e92a3ee7c5166051e9d00fe6b40dccf73823b60ed8672f86dcdc85196fac3bbf26647ccf158dd21de489a36e0cb1d35ec65253ef94d679668f1b3d", "CS2": "04147b2639913196bc84f72fda36906cc2ecb8953ed9dda7ee6110da77518b0cfc08783d47d7d3dfea5ce9f903be1e1c576c5bf86296a707b2fd148018384a1de7", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "0402c37d9de36d2f305aebed340ee14c82080bd05ee64e25f3947c59bf0f75df2014254825246644f44c2382ca7218af6195d6e4416f557939836d6e9ee4c0c0c9", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "04124846e9e22563baa42770d05ca035d67de1c156fc23c13743a710840c48f9dd232ccc99fee96f436cd9a8935c7a8e7f4756534896094a818b34a524aadd212d", "U": "041e09981d1715b942f65b59ed8e3bad64d01e38269aa5c2b5960e9a35e047843006053763b1d8843ba4bb27b472103bc058ff5cb77a6bc03f13561bf36339c433", "SERVER_OUTPUT": 0, "V": "040547b265f677caecd84c686cb8087aeefbe1cac654e86a352f24d3af7bc506200f3583244a0b0df9e8a9ac9bc9c4148d6b7bd04dc58d9024c577278b99102cdb", "Y": "1fa1a65aa797a058a000c531505a3db87132dada69276f1a98ace80c4b7bb560", "X": "193dba3040f1eb3b2e786901835a4f8a38d84773b328e10d0e09d00a04ab677a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 220, "UT": "040aaf0c599c04b1ad3e949a351a699a62503eea388c1eb73ae0ea3fe321394db90c7e83818062c50f454467f57dc3cb845d269e5c33e770d65c29e29ddb7d60db", "MS2": "02939c4162e90054b972ce7d726ec3dbb89e15398a4df093cb078b12f3058e62", "MS1": "10c88fbf0f7b12e871fbdcf7a1ebaee235caf9817f946cf41a0a1f3158252d68", "CLIENT_SECRET": "041d6000d5adeb00b8528eb7edaf36403ff08732738e065214eec6e40717249fb523447e6e52120f774f5fd3d72c13b4b259a23a5fac729eb2c22bd0939c2d2eff"}, {"SS1": "14cd6fb9fc2ce4c55356d10ad5e5f64635574b358fcf7cad14c3d03142a9b9990bec85f70985aefe563aedaae011fc7b8285f21dd91a22e2605be9d9b9a120301100dc15c3a3ccc0c11b31964ebf5031c07df461ffba89db1bb949631d0e96ea21388d9f5615f2c1ba35eb12b5ea5ca22beaf069420299ea31ade3ed39a16676", "SS2": "0fa90fd619dce7b6c4fb87c30067089a207212e53ac353edc33c790aecf30be71dc95f3978eb86226c5769d713a1a6dddf4cc79750f073151e60a283ab39f3c41f14805354e250bf47c5bceab0e8311fe5d84840e9a3f077bc70d3aef28b9d110435d171d442c44f1955426aaecac5def1f32ad9533674c46cc4e52fa9b03dbd", "DATE": 16595, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "07bad817664bd82f8aa263b7b0dbb757062778d24827d4942ac29ed0603e091a0533f12ac69cd2a5cd78ebdf89524f10176645c993945ef3c56983b2c63b556e13c47fd7f32950002974013179b285af67a8b5ae0bd3f40daea5fb121e164917058826ba121771161e6f958da3ff145b6e2b46fb91390b2fe750cc71f08e5009", "SEC": "040554b4780eac63cdda6adf1058015aa936024ed1277aa023941f6b01d55b0fbd106c60b8f57e148d0262b7c5c739c392a8a37974e89f7032cc39df0e0c12a84e", "TP2": "041484bb0e0b8f3646708411b1c02afba7d27f296fbef16ecf1f04429025d242f523e42c9ee25d314ac32730a917c8eb45aaab47df091584e4b2a9b6af3034a48e", "TP1": "04040e443a88c902d42f2df1f06b4c99a83e23c3c94a9ed0dcd46ed756115049b80bc7d5be2fa61e65a588d3c0654ed12458ac61a670b7be54b9f3351f962e3bfc", "CS1": "041a467dcbba8b81602d92e03450bb6086d09e00168d34d762e5d5554256d2c819238044d97bcb9110374c562af3e5f3be1aff2ee80375396511f695fd787d8fd3", "CS2": "0410d19ea86d863979c3ab83fc70caeb67c4a1abe9a314beaa7f29d9dfd4f384c00aa310c751c40d97583be96c810d7aff3f7a06d855cde67d79944d150340af8c", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040bdfcd9559c130de8cbe14775b3dc38d6cbdb3a538332d5aefbc0cfd1b7412e20e458ee97cebae20eef50263ae8ebac6ba232831dff44a73c82d7c7f5521ec55", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "040ba049bebc604ef0c6c1b3ded5daa79741361b41f6ff01fdbf8975bf6c6ea1531348694577c215df5ecfea66955ae8d3a0f048ef8eac5004317750022cdf2d98", "U": "04034e5963c5adc1a5f6d4138532d6774c83642870ff7e0d831d0e40df55dfd9fb0ecfca67850cfb5017a04bf6dfa5568ae837cfdff2643aafb9d5c267bca6320c", "SERVER_OUTPUT": 0, "V": "040d9b211db2069d67260a411feb23cd8821d0fb8a6054fbc8a10cff407ed47b9111fbcb614ce73753beb5cc4bdbd8582990c42845075730df7ed60bd779f585f5", "Y": "07f77ca18e3f905b0cafb953f66c68b476aff4915532d027c9914ef7fb053327", "X": "082b71737ca18b4aa440d8be39903ab969e4182f940d1b62f5f9251462ab85d6", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 221, "UT": "04217c6b0e4f95687b5ff77fb10d78cd70053fc79b33dac435952dfd127c40f6df0b037016a27c7fa327464298b2d16dbc7b3bc1c85b34e6e37d66155cbfcf2630", "MS2": "1b12ada97ea7882fa2b72ce0552d8d0176697ae99d6c0df4ee0b4dff0f884738", "MS1": "1a48d211cd89564da0278f3ae02267b2721db90900d2b56b2d9d0c2e3ff8cdce", "CLIENT_SECRET": "04029659c163bbd1c33c50c85e4aca2053e80479a5a0d26f33638c90862a236f1d12e6b76aef2868ff9d263bb3283ab7c8c90dfde3ab174a9c40a091c8b39fd370"}, {"SS1": "04c3c4e694c86bc7c5cf6c060dc9ef2a14a6269e43a36ec21d9b1589899d9fcf1b66a83eb1683107931a36497380468c3f09d18971c3e615e81cf61d930adfe71d32d66742729aa64aa71c34b22bbdafc5b0771335a52f6ad8ab0c98256eeb2a07835c72d3c339777089d80ed29513456e167e32ee37c4a4173ff1469f2c85b7", "SS2": "0c19d6d36bca61deb4c398c701dccad602070de43e28d3de4df73524203156162106125277bd7133bbe8ce3daea19fbdcec44a34c0698ac12326b6cf328a4e8006792c382c64f56fbc32c868828f0677f8bdabf6d347f741fb0272db27ad61b40bddb7314575e1f8a22592c109eccb5f325ae5d13b935df6709b4cbbfe5de7a9", "DATE": 16596, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1b6f0009c4ab184fffe4c9967cef2d59c461009fca040f0c5355a1b32037793e048c0335c6d1cf6fb1c37fc38715929f964214567348ae241c133ca2f2810b381ec57d8dd798833249d825c41f6c2cf73e3bccc341ee718a1626bcefe7b54d8b17c232c0542aba378810e0e8797c6d7b1192227bca2a9b3925a8c8ca82caf7aa", "SEC": "040d40638736a2f07e7b5b752dc3d303b1f046334d93e4f59348d6003e1f8087b20927928f5b8a55e7ae51f954854c3df68632deb6877c98fbec846dac5bb2ea2a", "TP2": "04062cc5e8f13fe568897e2175e8db5b9a1985d90c32ca6d1e2f53cc34db1fe3741f16ab40dede6b23cadf33dd6343d02d682f5936c26dc83480c1a0d65bb56dec", "TP1": "0419a7206bda1cbe39120e0dd2de5966e66c166fb0d05535f07fbca85dca1078430a3a74f17dfe0576b4a74be9ca8360fa68ff5fe0cdcc103e42641122c1a751d8", "CS1": "041074e1e3167e0576aec62e82f3ca92a34afd0e301a00ec849b0f844f9cd1a9e21673a4b3115cde159f237a7ddcb5af1775d2b4fe4bd64b8d47839647f0d1fbe3", "CS2": "041ae43ec897deb10133c5aef27c2e970b63fb32c60e4946894cf824b7dea64fb70d0388601c614279252984db0fec34f50934dbeb9b60d35c3bcbe2fea187fbcd", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "0411403566ddb696386d61f4a851c03fa40d6534827a2988d7a0439277d99f1e851cd4f2920ecb64bd14e5a56856ffdd911337ec4826e341819587e584f90be440", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "041e59e03e0e5be147a86b1c975df45a5db0be286108f0d105f37da9d0b22201a71fb76b6d307c07e3f61ca1bd705f80a59d37fd38e52a495bf7ac9dadc643b98b", "U": "0414ced315795487861e7add872703b1a5c979f45fdca21b0772ff71a5878132a10969709f1395f11b820a6691f6e888dc884d3fe91a3ae5b2eaaf317da955da86", "SERVER_OUTPUT": 0, "V": "04195257401de28a5c27e4a506d83b66e9e6ce937ae035f9363507942bd9c5d49f1bd749efd6eb26dcc8104e97989570cdb81797b5ea7943a6d4bb371360cfccd9", "Y": "0202b8a4540624b96a81180fbcb1aedbe93ab38da38c6825dea0d54b64359f9d", "X": "0a0c03011cec93f9ddf3e7aad4dc0b72fd72730c50211dbc60a1c465d4806a30", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 222, "UT": "0412e6c9a4e0eceb170750422901648ca51061d181250bc7c6cad71d572efb046323792877aeaaa6e239f57121c85cc6fee9731a20a89cda490792fdb96054e24f", "MS2": "0a1354050822f402fb1abfd5ca8b4d860d39f3769d23a6374c8acb729a1cfc7d", "MS1": "1e3ccca9178c5de4982691e97be418fa2e6fd253723d30ec1fd2cdd9fa2cdbe4", "CLIENT_SECRET": "041087dd1ce5b8efe9cee3f9ea317e4ff311113cf9be3a2f790db7dae76e0195541adbc0f9b0a3bbe4ebfbeca0fd1e75d48850f8c1e5a3af396763c25d53951f7e"}, {"SS1": "09d6cdfd10d3667c71b6c1a634b529e794f9b73a548ec918687a4cc1e907630603534045cdad8a4e32fa946d4449ed3f3066f68cd1591bcd69727768781e1c1b0c3ba1a4fa3f8a29268b98b765ea7a8a1883192f2f9e7575681a87d6e642657511046ff4db3ca59447a70e1387097212394c8db0112b2c8cd06c77adcf2679d9", "SS2": "04a7214f4efe18039317203789bb572b5212ccf13aa904166f4d4df2317c4c4e0d640c4a879df9ac716ad6a37546b92dcfe87a15289f9465e004146d4d10c9381b5c22ff92cf47cd5b485c5c68eb3c94c0f65066ca76b4f8863769884d17d99e0f061c22f9a2e6f090e1bf5c4926ef1fc8723deacd3da8eba6b05c75b93b5c3d", "DATE": 16597, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1d68b980e1e65587ac7673670dcb33ebbcfd0f697ecacf46e58b83b5f91a912b00e0e1e537b12ac9a4c5caa964cff777db80e1a88dcac86949ed419e57cff49804f832e854f99c4bf833635426ada5907f4a431d003aa7c909ff68b79eb8a0cf118432a99bbdef84ab03eafa798f2080d914e1308a4fc16673e0256156f6a0d6", "SEC": "0401d82131783b33ed20ae4df80c928aaba69bcccb2453dbd249f8575843f5114a083ea3a5e11fac6f618c1cede88fc7f1c9b9d19909ed612a9e381156a1fbef5c", "TP2": "041541e3c1c1a92c6fb29a4179e2d4e8999925558c3c3a8448f6388c33cc26209b003d9e474af0028544cd254b512c7d8ea61e78aa2e92bb11651853783f49ece4", "TP1": "040ead73254890a20051fbe9d1f97d8220ac979bdf84d2aa06b47e291ae947cf79229ed55501a90626d6f1590a855b17192938b32bf5ea96d704370482f8aec855", "CS1": "0410f77b0fe8977635f2a189d83b6fc7654f4781b50266c116c2aa2dcf772036591e037f7aafb8c8e767ddb15ddf2d913a9730e4eceaf842f6e20079acd4b74af1", "CS2": "041f4af3f3dd64ec854aa701c0fd830fbd6e2358af640b342d242bc181946338220afaf405880fd9d012ad1030f8480745c2666f45f10f5f9fd3a9f7979c31cdfd", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "0400be30a34e224afdb2ba05ad1ef266dd4ab76aab247ef0541a561972c8ca92f22345f973548ff096e89d5675f232a844c6bbfbf201093bf069216887251269a5", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0401be47145f6495ccb4078a147d45c0650800e4cb33ac1d4cfd7c17d7225468d619bcf0dbd37bcc8ff93130201ee44569c7a339b1bfc28d6ee1f1f842d6f89a4a", "U": "04097e91778f09c6111632d1f3d6b9c60d9d2eedd5ba00caf9e31b7014023515c1100f5497fa5987a438b22cf43c69aac20435ec15b54c6c91389a8a0718c7b2ac", "SERVER_OUTPUT": 0, "V": "040e57ed3430abfdf44c55eacc1af849ab79fe34906a1394e9240b32d7ef758bdd1b342616e340981a60f63ebf1b05d1ac76cf6fa6f57c03eaa64d0e0af78ab696", "Y": "1a2776b3bba5a95b857971debee1b19bdfffb9dc266a0ac7514c8722dd64e5b6", "X": "20394d70b10347e33201e9a985be8e605102d16b07e452ed87f6602d3bc8ee20", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 223, "UT": "041554e50dbc75f378e00588e38e0a21bd61b4194dc445c8af6b9d9286d06f73aa21cab967a62e87d79fdfed0446dfbff0c3cb991d4905232f0cb02f86cee1305a", "MS2": "1fa167f0cc38bc960ef8b222dddfe14c21ef44a6eccc798745e42ab9b19aea13", "MS1": "05c1485b969db7236badd71aaceca9eb7da99474a3be4cc62bd56ddba3bb2173", "CLIENT_SECRET": "0409e4d39cb457ca0afa30a2b49a33d9f1292382dfd21dc69f6ddc6da603f737cb0356eaa455d5e7aafdf2dbceb6524c74719c652b69c6813a5bac3ec3195af8aa"}, {"SS1": "160486b1ee881458e523323b63366a7bd9ddcab286b887b51ae07f043a9656321e3bee49e4a85f721c8f65b34ec95428abe79f26ba6d963ae9e81f2e7207859c1c6496b3ec10e401cd3a8a114cb4e67aa39caa73533808a1410994e23820865b128dc77953b492c8aabf7361ddd67d776a3f7c193632818a68a9b8e61147b853", "SS2": "09c36f77fae403efb689f971df691782a4b0b37c473b303cef91c1be885ec3e409d1786d0aae3ea6054850ea1ef4d1bf63cf4082d085b504fce398b31b64adf0025b1d3ea98558f1ed793e49f178f7d229777626d08b6706a14d00e69ccfebd115c764ed3616bbcb1ce57c63394c314f43c70123bf16c284cf33397f69155b69", "DATE": 16598, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "040aa9f7248b870c365e545643e87ada716754de30e70c1254e90cdd48cec4fa0e51ab6efbcca2f305fd6ab80fc4df38bb80027c5aca06c789588f631a2c0e070fe671787b2b06766d344e9e5cdbf4beadf45b3c98adc58895935d3455d2d4d00e84d1105c7192ec673f17d38deb3c71e6597bdd6563fcc23cb1570713117296", "SEC": "041d3c6d7a764ead65a1c06938d635d5b081bc85c4330f77037429a3d2e5ec2784064f846d9f1b2634128a282e37dc6741b611a3f801d67d3340af3bdefc870620", "TP2": "041654f5a02cdb31f5d025e902510b25502716243e74536bf0e2d0daf395042bdc19c79a064ec1a72c644cbb3d18c4556b869fd941133caf0c4747874aa1fbc726", "TP1": "0404f529218c97c857b6cc006e3965fc73df3113be7a705e11375148dee24c439a0dcdf5c168ff9591dc29033b1ab19a60f68222a6b78de616afb0befb50913323", "CS1": "04056124df97361034b05948491665fc845e262cb4f83ef3e0d22d5b63d16a219e1803ce55a81f0699c8e82c341a3b778107fef77461b6aa800b459bb873f3359d", "CS2": "0402a3e8ee5b57287baddd85a2c7ddd27f19ab1abcfacf10608baa171bfe811e390fc4e55649eeb7368d3c0c38d75509d7393bafc1f5ca9ec246c4f8db8307a1df", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041cf245deab3d2d6cc4a42567ceb2c0c2c7d5d474b523ee2b17fa5566fbe714cb23e0fa46310d9d01d4f6155cc436742d2c272ca48cd59399e6ad6f9322785a5e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0407628e7baf3de7405d10ea1d5f8c36a131e3dfd09650a610b31a1e7271e798b6039c824f30b81c73418bcea264192b9fb43edff75410d2b3792b1b4ee47a3846", "U": "040ddcd8353f2af8a59e688ccc07e6c8dc0d5f0ed8c1492a78756a265cc3c0444a224ebf13b98130b40de6031911ebcdb2ad8ec49c9bcd1513ece2f406bb4578db", "SERVER_OUTPUT": 0, "V": "041903b539337db5c9452d447b5b78adb9e9d1ca3d0607a3b37f5b0fa7b611cb110204aa56f77cb0784b1bc47ed1b1cfa55d2fda59c67c2158d95bea0207e73322", "Y": "06642ab4acd20712d0d5b1b7133e1186b24209a25d92eee0b3fa3379f55a5ed4", "X": "22727770d0f03947fa0cc96c630e45703ef29e4ab3369561b184f7815afd9688", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 224, "UT": "0404fd52d3d707a1f10453c6bbbcaea6461b17039bb65be4bed095a8318864ef5609d0927e80512fd19f52a15449dcb830924937329b456022f8d0095f53369d74", "MS2": "1f0d1a958a750734cf7d8b95194607e22ca15a1d6649d43b467eac7c6e440daa", "MS1": "13ee895c56955ced33874a7815b2dfa178734f6c6fd0df122ad6458bf962789b", "CLIENT_SECRET": "04002998f95d646423135dbf9239e194ae7a7067226835b8b709b0ddf98f696f6a1f69cb41dde0856782bd11afb7c659142dbd7a47e9eec9e2dee93c8dc630c02e"}, {"SS1": "05aa6a8382abe89d469f2265a4ae675f0bbdac7bd848bc2b2ab5bc78e194a0bb0e89b7d4622892659985cbbf53d3fe9df723be2c1a3d2796b830315a00af8d210b053c01919c9029c4418c03a64d3e6c4005be7fee68edf87fb0d85bc39095c82066ca1f51f6b3d64933b5bde419066b37934b5484b27b123bf551dc9634b6ee", "SS2": "170df0d8820c182c8a50d525fb5a69992ab4d336ff77aa8855caa8c08b18f1240b7b9e4e2f1185e2110102c43934ad1fe5352f38d23767aa1231e265cad1a6fa09a88ca71d39825d728c1913d303b52ed3e26959cab2609f53585e7a02d0d4851cca16542a6681fa6dde5d7f0526ac9a61d8d8e99882448e4e17350c29d923b6", "DATE": 16599, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0abb9748c15680c79396d5387d2a4b7f24047bef38c17d8b16ba88ff83b453a80768c0cb3cc84b3cde09b6e4df49d8d85c298bc3a043094cc24b989c0363a5881cc9ed56a592b59d5b6392e7c319bf13987d2e36d245374d1f190f4c3567591919f1c7cfb0ad0e9f773cdeafe8e4d08af1b1ac3a5ec211072afd83fefe41fa63", "SEC": "0402c1cab95cbb51661eecb2826e864d374dfd7c3664fcf3241f01fc42616975e30c1ea2a6cff1271e87ec8c64bb0c8c93379bda8f98f9b67602ff574c25857cc4", "TP2": "040c31116506d46b66f0453c0f66964841044375538104977967afdc7f328e2b5207eb7503b73b4839acffa4b356af425d42825b6f6b567160744c8476ddfaac12", "TP1": "04034f0d1ff9187c8a87c54b9b1d1ec70128c7b135fd0dbdd46d8df9e78dee7f0c09838c575c8b870b2f78be71f7881dcd3b008b730f8832e9170e927e3da7e801", "CS1": "040080356217224e15add5205035474c1ec3bd6e9e75d6cbb83f31c40df45fcf3509b74fad7df5accad8784517f4b2d5fc60a7c51aee8395dbb625f90e88425ba6", "CS2": "0409a3ae1a7a0fa6494faacc342a246ec9200c9af94047371a3af06e268381f0401dc656c4d30ad84875cf6a233952511d795fe272ade4b46c3499b23b35ac1546", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04044662732e5ed0f7f4c2a191df8a8552fcbabc75757cfa75d82ed842ed42060905580b520936d7c80cb4dca9c52847262d3c720212ef9b928ad61f2e28f84597", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "041e8bebefaf65e0d7796ef57aa63967661795150d5e6d23b265d9b72325177fb616321e376647d9adf7694128780408dcb818838cfcdf526937f314d01549daa3", "U": "0405c3a751094d1da598560c0ca15f10cda808479df5d661142551a7ff86e74d4f16af6a5d5caadd2c781a0b109921de78d81868b9966668eccad8e77769fbe9a9", "SERVER_OUTPUT": 0, "V": "040edb2d873a46814c3af0eb64b28e967f3d799854d589adbd60092e626ea21bc0210cc3aaaf8d2a45861218c1cdf44be566e7c90b70b6e89b97ee01a2fca4a543", "Y": "144d30dbf1712ef0a4a9e1451ab324c24352a2b179742fa741b2e0107db36327", "X": "0b5c520742b222aa1f674fa790a305b4287b410eaa4d83078f6e3d4f43298a8a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 225, "UT": "041fc4ef037786169239df952bb6ca08c946b63b7433ec8a9f65f16d3c2424940011ee4bb7c03a8db94defc22719e7ef2a01d17058d98df855b5c4cbfc7ddd822d", "MS2": "0fe355fad4df5821318e0ab55aea1e8367ab7cadbdd0124e26538c424318710f", "MS1": "0e7a323344c73683d30d70d0b202bb5e20447e021a687bf0dea2f76738cfb072", "CLIENT_SECRET": "040c2d5d83c478fe751a2a25d48d9791e4f21ab585c86a6b50d026d51634e36ab503da591c51d113e16d67141fbe8502a73a4c6f896a709eccda75c67980235eb3"}, {"SS1": "0efefc7ec964a3703172ad3c04ca812b5eb9ecafe648ceb4ef8e837322b5a1b701293cf7fa6053a9592be6e03b80e2ca59233efb8f1c5dfd6ed85d62830ddef6119736441be501d72f843dd645338a9beaedb534e284679cf47fa77a1cb917b12022f7ca98806004fc2f9d48c5d948500f16351a6c9c2ba96430abf0773c5ff4", "SS2": "1d4e25f5e86096925baf764daa90584f9f38e7f63793fd61c3e6d55832fca9c3162df16001b563947b45ffde88ebcf9308c03e60abea8117d271e321115a54da0fcd42d514fad8661b663648636689e17d783d9946d855ad52ddae62a7d571e600191604416cdd239c675ee48b228ac20b63b0d9e32cbbe5d98e2569ed67b5ee", "DATE": 16600, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "16d7f9b201025e40e1aec98b1581db204e84481c266bb2c7e8dc786d4c4f67a41cc7dd2ce48d467b0ac464ded0b5e1eb01d99bde336a1e932c4cbda9091707410e9d7b79a63ee9e6d981a71cc26d555d00c0a9e6197b564b2f4194b5d551f9a41277f8dd02f78662e511178d6d829bfe2e854fb8c1fa49f08f9568a8afc229b9", "SEC": "04070f39c60d2f16be613b4984aae789596c5dda2306970162506586d2fb08077f14c93c3bca6a415e2d5a3b4c38484240f6a3353b8633015a289c59661237bd59", "TP2": "040f6585d22fab0128482d2cd12200487853abb84be42648d3c930b5ff4ab7430c05d5625f7e4edc047727f6c351c542783dcc29b0ed822b687a4fa017c9153aed", "TP1": "041570dfb31b6f62414244de5c04d2285cbaeb57ccb38c3331b4dd9e06448cbd040325c720e17de7cd964bf6bba98ef775965d2a3d977ccd1046e7fe30e710e78c", "CS1": "04036ff533f0d26eb1f3db656ce30fd70ca17b2cc2acc35ae50e068852ba629b240749189d62c477536456b73c27120214debcdb0e8262c51f5df028c13500f319", "CS2": "040a724be25e3cb8c476e3201a1a8b5feac5918c6e39a8ddf7ce37babf6b25add30da5fded3b870f6526e343fe8913c3600a47993330281cf3268465ebdc265e1c", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04024efa30856e35791c18a17e491e4135e13226c8de3c1a96a53f7354b0d47192087b167cb49949fa756be0ebf76c0634ca70c31129946762e0224324cacca47d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0420837812dd1be5e6551a2091d0c79ec118a1ad4e13073f9cd034b00116fdb2e004c2e8e4f2fec53de1e4dd39bdb01f59f6ad5aae227b3ec05bacd8b6a9d29b35", "U": "04075e79c24faa944bee0cbc0a857e5adbdcd6c97da9387238a9349772d8b18faf0e9f416f152b9a8acf447979c8805b6d2102e15228689375297726b51cd3b822", "SERVER_OUTPUT": 0, "V": "04141568dde58f4f849443b64a1aad5392ed84bb0aad59e88a0ffe98551277a7230fd02b5dc54cbe20e41676ee28bdf9b33b054102418a575ad160c8363adeb628", "Y": "078b3008fa1ef9bb6a6026dbc18f62313634425f3033e83e6f9cf119d9a0f5fc", "X": "1785e7d49853a8bf6cef438e7db8838154ada37743e25b56651112e12bec0392", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 226, "UT": "0408ec859833338c0bf18289738eded463c2eaabbacb95cadd4b2e7b9c2f7fcc0420bc770f9b165a6d4bc1f8182285a3b412c86792d7565e1a9cd636271a5dcceb", "MS2": "17510baf89fb35ebe8add5eb694cc2cd9aa726acfe7a51915844194df166be22", "MS1": "12fe201058c959e161382fdbf24516d50c78f0ee2e0ea20180018ba2de1a6fe2", "CLIENT_SECRET": "040d8e009eab7d706c67b157a5b7a474811a80b7322e55b03cd28a4a3d32f0ebac0bdc9c3499431037e5cf390b883a7e0956d4711f140b2a84e0bd065a5e28ecaf"}, {"SS1": "064677ccc24211362a1ba149628d5e9b50f0368f861990ace82ec1a5087cf9970fa2c50403722b76f25a509173de406109962fd0bb9675a93fd36d1fea507c040b5d8b080f9ac33611f09c12b0c7bb98158f7e0f28f790a3ef9119e147391b251719411df8eaf44afd70d48620ab94f782aaa62e1f2ad198eaaf184b8e602ed3", "SS2": "198391c082ab1f2bfa0516e55e3a6086b32058c3428a4869ca4a7be314a5d608015d630bc8cfd6809cfa4ce951a3a050a86ee7e2f82af509c895b736b365b8c200ffdac7e3260a47c00d03cae78357c475d132b412d0a3246ecb6b0d4ca7fe701a5be6d9eef8c678427e7bd90ad63ef8023624c178d2680504ab130c1803f594", "DATE": 16601, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "2302803d281e86d525777b5c84553de04724840f5fa38aaaf6ad99175065c1111a03470b5126bb344f37fa9d0fb34477580a07e1abd8d354570219e3b4e41d390a0bbfe4107c2e03a1ae073f8d9feec5c9eea388c9742e0537fea5a598fa4b35104ae907f583e10d971d732ae819261a0475e91d3793bfdaa1f47dea2662df32", "SEC": "0402a68cc3b3f6fd5ea76e47b85e4d752d51bfdd0e924d3bcd73168fd3f904e2df003e735e19038d725da84d88dc152b51c463f0e5a84259032c5b0c967683e8b0", "TP2": "040ee66545d7b94658c426ba6f8f0bd463aac9becdda4d7ac910583338a2944cf217b7de0259607438be60f313a3485b6a04f2797da6c610d3ba6593bf36473702", "TP1": "040fe02a63d7cd5c4f06f5aec8697d592216522b4fa98a60ec06b36f5d496784ea1aed2975b9e9a734a2d89c3f1c1b0920944ea11c50b3a1424456049701825467", "CS1": "042326e899427c3bfa2557b20f05dd5b3d07081bc48a167f858aef0f3ac66822d4151227fe0927125aa7e1d9bdde9cc1f45edd5730fd0cd94b869061164696220b", "CS2": "0409cc4bdc568d2b7dadae6c98b79acbf72e20a6e9ade61927081a19bcc6ea7c60061243c3d3d0c1056743da5d2c39e7c0344016b9e30bca580ea82bbcec591f5f", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04191ea6dc97f53a4c7bd04f644f3f75f272ac299a78e9ca39db3c54467bfa4e7b03efb3745b6c7d9737c9be70eed86df40520c1e34b24381d46219952ab59e071", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "04007acc143790559192e2faf433b75e5f008c355610f2e4c7e47cacbc831f45bc0faf7ebdc03d9257188277847549da03bc87c01c42e2d90c7896ca5c9d9a03d0", "U": "04123cb42aa831fbf17db5eb9c81a437fbb2dca155bf39f05179a36c9bd10353be032fc2ca3dfa9d8af58bf8ee924b3d711b6b3b93b042f7fadfdfa576bdfd35c7", "SERVER_OUTPUT": 0, "V": "042225359e858101afbf3d5b965eee8ceec663dbd9a42d3298e07461921d73ddec23bea0f36caf9ae232f7b0378da8f9b1ea76ba0a23a234240920e16994e4108a", "Y": "199dd6c303583db6115c9c0c78679b743d2b5ced92cc3edb2051d29b5bfed2a4", "X": "09dd194ce99e3d83f05ef123e20766fd1ab2b73e498550ef3e95d5ef33138ac6", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 227, "UT": "0420a7083a0e0537a018710801658aa8ce9bdae47ad2ed7046e4ab2a56d41b94bb0c73db3933ad47056f1a709b8b88361319a7c9a3c4dba85a426bf6e6c992ea98", "MS2": "1dfabd46cc2146b8a2bab39b23d3e46a7ddd05b359753ca95075c821f1ad3d41", "MS1": "02ac380202a3de8af61f0c3c4fee21b3d5c8d4153a957b0004d9ec5fdb249920", "CLIENT_SECRET": "0404b59a4421d2914f8dcaff4d158383f0243a3a5e45fcf17d99e32f116b985e0a2080d40295c4aaeeef3f3ed030a56f66a1c939fad5b8ffcbc09aa7e2853eb46e"}, {"SS1": "1c6ce3e0d4ff3956669b1f629e338bd6652657c8decce55769136270a56918560399645a1ac125ce6ece55bab1855f9d5979bf5e8ae8d11410ae17db46c3329a096e6b5c270465e0bbb9e40b2be9b3c2a79aab34a08f09ba9db8b2f4307767fd1cdae96c43de085e5dec73049e2e1bc378072201e8952b7ff48467a592d28269", "SS2": "08e335fdc103127119845c86741adb8dfa289dd0f1533d883ed246e68bcf54c60c025c83151e2e06ac9baed06a853b65d81ed1c82889dea88ce797241e21e6d41d4082ad94e3fb6b116d74a271c18f176f4598bcce6c8f5a09ae7e1019acc2510553bf66c8c719f33398b35033c7a507be3b7a909ea11b7c1f695b337b1828dc", "DATE": 16602, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "04fab77d576da917867fe82ed88d31509ff78f57a7a69ccb0bffac8a7f6c8cc92374a20cb6fc9b645d4419a42999f705fa94180f65fb1045617b002f0e8da7e00b161d3fc14cc9b27acdf3cdd8c451f3266dbc0b86e6d852a3edce480b6959880521bb692bf5370d758f5c4b4b94d5b234267933be49c48d152f1d95e88a0f8d", "SEC": "0410a70b012bd2754e309df9003c4bd1fcb4f75b99332242a903fee0d6404bad9b05a0942bb33c6da28f9879693b59672c5c9c3f85348d28411c71d309fb3e581d", "TP2": "041ffeef02c2fae572fde277748f83d65d9066a611724c4c471033baa239349a371d8aaeaed40ae5f1053c23439c0cbdffcdec3a0216c2e916ad686bf33089c892", "TP1": "0415c0bfcd60b448271374a927bcf557230fbaec6766d25d29e16ce8a788c4e89e0952d2b0cb3fc714bf8672fc12d9fc39adf0ad8171987c9c49d6d9ea9733b063", "CS1": "04200b316ed75439f789a4693cb2eda4fb0ad637d9540ae0b4153e1e5f31cd2971163b571007bfeda3478596220111ad88605708e2aac02aeb9de5f379bdbbf9c8", "CS2": "04050bbaf473fffe0162e268dbd0acffcf063cb1d6deea82ca856d9bad64eb281c08b6abb18cddc3afc368ac6b755ce074c82ce89137490b3c45e4e990438cfd1d", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041ecfbd71e590ad90a0c7f0a8ff25a3d44fe8d0a8df99bdbebb814d38c3d8970500bdce59e0d4dce412ee6031f2cb08c7d63f2779b1037dfd8996a6b3129b99f2", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0420149de0317db5d4953af72ad79face5f3d4f91ef2f39508323a917c6da2886a21808b3d07356a9bf09c046f94ccf349c346dd4a23d5b39effb3d867e6498e47", "U": "040c2fd7a074f0a2873f5aec0cbf50209687bcb313ccc75359dd0a2640ab54ddd31f7391fecc39c77158ab761fba19c4cf7bdea461c29800cba456d099da517c68", "SERVER_OUTPUT": 0, "V": "04119606ededb845176730e64c7c8d39ea226625c894037f28a867c27939986f3415cae04857d3ed3a426cc28a34496c298e2afbbb5ed23188126cfcf42b75e509", "Y": "213bf91fd365f5854a46ac6b86b8aae78680b0e5625362d5ee79c16068dd7ff4", "X": "0d7770fbcc21e1e058834329c326838c978b56f7cf61939a875f729fbddafc70", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 228, "UT": "0409dc95e3b808a144de39605f76490a975230605c812892f3887dc09a18072b82239d214dc6c1c2a0ea07da1fd6b48c2c6a1391fc6a5405db8b4053d869ff3c2d", "MS2": "0cd2c1651afdac33be8c015a3829fd0df7296e80dd76196c094180abbb5ab9c3", "MS1": "1c365c67c119133ce3b863dd2e9fdd559c3c76558f65a1d56c8b8fd3171b8a63", "CLIENT_SECRET": "04238a80df8cc3e071f484293bdd943c8cb1155fd41f8da40649a023f73c684d911d1743fb95322013a6b839727e21a30a7e1108d0e0ea19574c2f8c0e8aa66958"}, {"SS1": "0b053efbc7f25a40e1cebb149ff28dd063b8e6702c3697abb5c7923d621c2d9c1ce002e774f14b37458d0c6568476e08b6072ffa66f90beac81f75b1c5b3bd361a559728ce501896a617cbad6ccb32875166a6dd99b6b82d19e087841062589c186931de736ee29b4bf98f6a8fafda204b7a900669af7ad46aa44edba5013740", "SS2": "0d0add6178857d1e3f92aa7c941aa1e1d2c1686c459c77277a6c1221e247f3d814ca6af5082df2ea76c30ecda5608285bdb4f1d21ae1e6fa3d2fabdeb247d81b223a157a2ef4673d0cc69c4f047ad018f50207fa5029b320a2a4aa32015d569c01071f917ebaec3c2e44d5df4f714e424a84d6694d168de5395db831d0bfee61", "DATE": 16603, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "14e542c6127bc84fab651714c356773f5d6b621f02542841b49a2afdad99983f0b7e79ce5c14b693ee8ed5cb01bf3c48fb634d45409a6321ddaa99588e500e5b089d66512037abf62a6cd0ad85fcfc5ed3eb6bf0a4028ad1c5269623eda5c04d1912d900d705c8f85e582b89d2b10f4017a64dfe440e5d91e5b4f9621b933220", "SEC": "041f837d75cf48c0371c5c474871abe0c7cdd34b96f85051299fdc8a75868b7db409390092251d1539e16ed8312091112cb89103f1e78887df9247bc5a2abd21fd", "TP2": "04034e48c021a82888d49d96fbbb2a7ebcfe4bd6f84ffaef8fdf5191dfe48ebf0a17df98844430b174a274cabc03951e7208ce54d8faacf8e7963d31942627324a", "TP1": "04064a0020ee5f0d85a0e8f503b325d039c0d161f77758db231660a8b12f246bb71c0671de8b2d4e3539ecbf1bdfa07cef5f9f5a8f04414fa6dc135bb6c7363b7b", "CS1": "0410b6feea377df81c78ae6542982f97c24deb0f13de59923de3fadbde0fa7735f0cb1219c9e294786389a0d39e585a0e4845ca029e47beebb896a5a577f1b16c1", "CS2": "04189243d6fdaf65bb5b58761e5d6253192ce76fc3a22356664a5eb967f8a7456020f13f291d6f7fc647beadac3357bc5fa4927703ef5899886d8517db7f3159be", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041e3cf30ccd888f54b248af1aa7ee08cad299553fdfab3d4d356be18dcbd003a81b8caab9bc18c4af16be626da98fd9afc735b850661fc971c663ad819ada988c", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "040768a2a58eb0ea23a6e424e13e2eb06c4068740ebfd05ca6ec874afe3d84da2410730206a1910af00f6184acbfe1b68f8d9527444772749ca9b6c780ece69d26", "U": "0423910d20c678efb7c6b0ec57431d658188a3398d5c643ca5e152db98cb6f14d70a05186ce1b84efaa1f2ce2d9c695c6c0a177aecab00916389c7139281c7b5cc", "SERVER_OUTPUT": 0, "V": "0400fac4525f2bfd315e5f3aae377b6f0794366c1be60382b43fd1e1c66d0352730fdbeff92398fef64043088ef909f54cc0a50190b6158ff92b5ade87a958b4e4", "Y": "0fd94048999a93e849185d9fb1104dc1385c21e448eca5cd001d119615562b9f", "X": "1d9f88e929140e194c99d5ed8a62f9c3ab9ecc487dfb352bb50b4cc64e65df26", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 229, "UT": "04220527d92066a00891add49c734bc233e46076643f6429a22f918aaea10b5d98043d774d32fc87afe7fca95387e86eef62ce23d9abab9c10e5108391b5772a3a", "MS2": "0b7175ec4b46c0a7d134382c08150a7ecb58b67e00771271751f6531c916511a", "MS1": "0354cd6f9d7b86ec74ae7e3d274ffe1ca9cb51b516b8099fbd9d5754ed7ba3bd", "CLIENT_SECRET": "04200cec2bcdef43133c40271bf293f5719f48ec4f94fb36ba7ef40c8337116fd61262a2e5c13f55c66c295f3379fdd331930b94e77439a3e504e7be908412744e"}, {"SS1": "015457df5d19346f3894c9126426bc115746a098475e9eb4a6862ed26105c30117b344ffcf37fc1732a9c78a24d8321773b94a94c8dda92826b2d6997f15311417349fc32b9627a04d681033baab6026b8529fec09ad4d397f3d7d85c5f69f3718f10b1bdb498ce1a19439a64a62585f0281f4b9f55f97160ef877b71a1f8e6d", "SS2": "174d4392033067121f27777d3c055a70ba6347079e0b206bbbd6995196a26eb809ec286716a4603b279879612fa5016e61b270ed559e8e136af6f9d89d04495c0459668bf2dfa272f35d817fcd78f3f1114fbe388a4ba78b819a965b4430eba32227d67e5e7c7d4882503a5f3e1b25b3638fcbc1e4835c97448bb0d469cd4013", "DATE": 16604, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "08f074886a0ae63c95552bc5ed25bb7d49182f942ac2dae0664030002116e3932207eb27353433541b7874244f06c4e200958b399f8199db5d2a6eec167b0bb90bbbbd2b034c060c6d7e4042cf5f144d0796e67ec9f2a5731e4e71ec87f8e5f410f15c8ac58c2b8b1c5e71b410320ba9402830a62abad2eaf15c34ed9d432b64", "SEC": "0408d3bc60d6ae27c7ae5dce7b780988ecae94d356c4b0eef6d0214690f0e69830152c044f5358f4f2c3c71514719639eddb3ae80638d6bbb1a415bbaf9acbc447", "TP2": "0406df85880b6b362bfd323acc8fcd1af61a5da73613280cf023d41cf02b5842051a49b0461595dba6b7ad5e69ebfc001a8ae3e11d26f40437b587105dfa0dc476", "TP1": "040701c04cf800453d0c7c2e88922e0bf74cb54a535c866516f8198421251f57981a39bae8f03fed5752ce06389498689ecde097802501c1a39b73775f73e4f422", "CS1": "040ef138aa9d8f0c693578df9306b18b1fa82a294f7b3655afd89fdec27b95bd530b9ff46322946c1e9539623cd746ad12f049940f3bca0e830e9ddb5e81a62c30", "CS2": "040ff2834660d103bcce273a20174cdc4d24eaca1060aac347315088644e5074b81d616d8cd15c9dec1d319a4f070619666e4f8d39b0d4ce7fb8a2acfb9d12483a", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04032c38cc2f8ef2372c11ee43979221009ae732a6e98837cb8cf202f0d4298d3d1e03a8ab489f0a98bfeca6f4ba536f2c2d9449c2930e443573014ca6847fefb0", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "042268606e1ffcf9e779095156e692fab79b05036a7131d1b0b8992bf2621c877119f4b668294bd23681ce1b0a34b12215919826b95c26bf14bfa4a49b1fb01a8b", "U": "040a8fa2855ed3d2c4721f64234904b842975a7dec9467b19f258d1c859cd49b0f07b53a014e7a3414a8f1f15b021add45708105015883f305408a12ba80c5f33c", "SERVER_OUTPUT": 0, "V": "04094068d74f68604ae4859c47a1400f443ebc0371894f637f50cbebf3accaa05c142ae70071a6ff65dd4e5ee64d778c101514c80128b5dd0fcfbfb866a134251a", "Y": "05b562a55ce39faa1b773adf65be24dc487fa5d3cfb619d557c110e05ff9b784", "X": "202b5f856a6a590add5e439fb341864d591c7d5e76df689ee202536099354701", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 230, "UT": "040855e0acc31a2d500232701c0e2fae25e457e3cc8d785240c4f7ba56073d84de09b04a35ce9cb62c8ce63e2944b144ac31e449792b2be8179f03fcbee0f7796e", "MS2": "05dc4dbfdb48f171b043ae26b94c217c69faee85875a04db166911a697729964", "MS1": "1f50aefc420c3ca78ee741745f6895b57d29e0fef1d138811cc56f58fb597e42", "CLIENT_SECRET": "0417d5476ff12d3a2c98f8ec82ba6cea4fdc0a207f7e68323a7f9d25f2e1fa18cd0696902d5446c7178dd827516fd40ea9327bbe8e7f022db83fe64d79cb12c886"}, {"SS1": "00fee45fedec20ed4c40353378981aa4a2240c1d3dc65168c33d435e261b802520af2524eb4194329521b76a68739984f1994bd7a0ab392998dc0a73ebe321910502100e46a7178896c3a1b6955fa3a6474cf7b3d05d4010ff924172ead4fee72007381969f16f34daa26d57d843054e1779b99d27bba80a88c6d3a125949262", "SS2": "20efad83a556b38b5dee54adefffc8bee3167aacc29be36670dc9c6fd9efe84b1419e8545ed76668ec9b9072e1bda71c8110d7cf3c60a841fb5a8c31d1bc093510fd2cbb81b3c9139c5d37a3333e691005b317cbaedea4ed76ec53b321d1b5681ad4b2467f44a9343f1b1a650dadb19695e96e7613f6c1307ae32445a6b8a18e", "DATE": 16605, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1936ca596168e65c61464fcef28eed8150d7f8c929d896a93454287a4a25a0c910e8fcaaa39d6a931d6e255ac7a4771a3d2df10579ea62f7c7850a71d02ca9af0ccfe01ae75e9e2f9b097d7f5cd0d6eb5f9afaae30c2134beceb8ef88809f5021393e59bb6c3293931a54fce34a18ee9b995f653c61087a40618144d5a208e6b", "SEC": "041b2d3416f3c9b94e6e05dcf7fa1b19421cdfc3f9266f395efc8f5ea1866abc260b451d932134d530ddf1ce56fe276037b451f73eadae1a5229bb52cdd2cc4686", "TP2": "041f7a02b4b771dc5ac45c91bc0e4d637acc7156da5918e7398dd63b8170410a5519dd450456fda5348c0dbbf8213575b02ab4ca04069d87729465087d98b443c5", "TP1": "040eb20f18cbbe283d702b26fa64d0bb309b57c9936794e5c43352bdbce72cbbc421078b2351a5718d98c292e5e375bb39c76b51675e6559b4db528d1acdad0890", "CS1": "0400a3c0ff4b9235c3066d59e308cf7c3c11309b17c7d429f14f50363e5cc82d601c21f3fd92d4c3cc55f9572674cd51364c44a14988d2c15dd430123ed17d5ef4", "CS2": "04015db2865e56edc2e9b6fd184a77217645a1b7d03cf65e71654f3e14bc1d9ae61b9eab6184fdee1f7ad4a4603f9f236de7fb679507994334f81e67d0c237c02b", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040c29f810cc108f40a0546d0c0698a0752785b30a05249fe1d23f10fb2f4b442a0de5464eda2aaef227e9e50a773f14007703e4657dc913bed7cb5f5818cebdf6", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0421478fcd1e91b7fd59606d9f3be1ede98efd4b7dcc8401d314155a8ef33e63330ea73328e2fd881456f7661c461b15ae2b8cf4c3d2069c9fbbb226cef80d98b5", "U": "0422e30291e373228fa4695195b9ecc2c3e75f419236ab95e80998713a102a36b320c274da56ee07bd2c06e9744e43900966140df4ec7ec900572d6d6cf5d7b738", "SERVER_OUTPUT": 0, "V": "0418190c1944d4c0884e09a4cbc8afa4af148824274aa3b2a300d964f6809368090a6e20aa777e398ec62833690317d7f3aafe8b12f627323d5613b98dba75addb", "Y": "19a714dbc15f584f9c718b82e841d62f8d9bcc577da168b6d33c85a3503bffc8", "X": "0d82090195bd0f0101a9e1a5c5d43d05eafe51ce48b551676dd45a5367b705de", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 231, "UT": "0405c4a109b217b76cff2279e8bed764d30494d59c0b6201341c54656ffe83a3841d6e20cb45a7c1bfdc9ac9a0863705358c52965e6afc7f088cd5bb5df1ab1cdf", "MS2": "17c06f7d41008c109b67b6f9f6365b4aaa338fe92c258252ca317d4a8a40b888", "MS1": "054a337642b29ef73c57e091da1524125e2de7eb4b34d4bd84fc9574616b8c13", "CLIENT_SECRET": "041a4d2b2d240a94aca8443f14bda104bef4d663791bfd92a0a4e820993a5bdc63099b489dce3e7a65cb11300a562b8c2b87d170a46fb0debee4443b51f65cc9f9"}, {"SS1": "1c7f12bf4aea6a74bd40ce9b3ecaee8470f4f418de51a56b356e2723933e31d30de0a878481179136371dcfa7d5096d25abc84f86bf9e2562fd36d3df44c34a417b7088f4124dc85b5fd3d21156f46467a1dd28e2c67ce03978efe66042018871540f62154cccf1e1049d11e73f28e81b95bef2051c1bede611d07996576bacd", "SS2": "040b0428cecf9a9e37668b6dde69ab021b2f31905cdfc79c664437665a8619741540707cbf2d9249502477d27db8017371c13573597a1c9217f455497d8ae6fb2019941a3ad731c193309b14251fd7eb92aa6775e739a7fc2daccec0cf30c0a21b025338376d48f28d07cf8fd87caf27d527e1a4af387906dbb0bd6055eff082", "DATE": 16606, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "05836ca321ef1f9b2cc77cd027ad145ac3949333516ddf89e6e3c96f4cd48d8b1bd91a22ce993b22f3c65944f343d3f78094fecd00e07e0225e5ef666f14342a10f97f4e1343baf31a8d912501198fc4fe65186477b39c421667bd54c21ee64805dc062b2df74dcf0e9f0d164a9354f1afaedef7c7954b06ce43787fba6128b3", "SEC": "040adf431c080b53e8af90b69b9f2fddba27b8247a81605c8aea415eef9bbf42c20c98bd5204b28ed3e5343adc2b0ab3a80d86c048e41968d87535d2b018efd67c", "TP2": "040a3ff883bb73c535d1bc44e6c366d17471b21719f53035f739ba7e230e42e2c51f7f0d9bec1ef2e475a46c8492dcf972de3d777c41ad42d729db14821f5c88c4", "TP1": "04147bb739a6d9a47e057e5f5898afa2b1014f267c3bd59d350a7241b08e0f0ce004867552f818813720c5ab782f55cfda0e71b47800052e31d0084348b6130c6d", "CS1": "0401d9a51325f4d47fcfdb25db7a44e385801d72633d39c3d8d96de69a2f6d308816606fbe4a21e22a2a7bf46ba60216370ae78141e872393127ff1908ac84c644", "CS2": "041f03e9fe4c0a2c54fcb1df653481b6ee71dab39d5449fe4dde514d9b4fac3bfa0d96fceb579c113425071eddcdd390d30a32cb706aa2b3cc6ac0588d340f79c2", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041c1d5af783062560c63715211fcc583265f11c2997eb2143a8a8884d0550124c04dd07c3dab0636a9dcd6f00212b3802d7f3a9288ac887a44c396ccf9a3370d1", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0419c4b7eed16be1ab931858c50b0a69a296bdf1e02b3d6a6b97159ed18318b2bb124a2f01b6b067f9ebfa527e0b716cae502d22d19e18fc9dee9603563457c17d", "U": "0415f29ee01e74dab9aa0819d9b6f76a6e9a7f6a2603a222f1f2a0b0b7ec37c1c1009a23b91bd12a24d2a1ce6c99a069d7164015e77dad27beaafa7aca176a4554", "SERVER_OUTPUT": 0, "V": "04007f745a8e196a185ed41e145d6728d4ce231613a00775ac2fa55e3990a958b322db5d1ffac0178fbe35f1d9299f06bf89fa6fcf123c68e6f1bd9137a8e4eaea", "Y": "1ac1e1fa5caf1b0bc1d42b3db4d423772aa39464c123aaec27208b649425a9f0", "X": "18d0e79dfa2365a348072b6188e1b8221253e883e6a69e2bfad8ae72fc5c037c", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 232, "UT": "041b3a04841fbd8dd40a79784bfe62dc2838e8998707d3a5703fce2641bd46d2db12090741d3e1d4ef4a772773031d79c5a15c9900430cd57db7c0e482f84f7b34", "MS2": "0b0456ee5d27f35611ecca4abedf35221fe433654e6a9034aa5a1215ae62e89e", "MS1": "131108da081db3b313a2c668594470d0a5e3092fe0f857a00e7ac8de27965b36", "CLIENT_SECRET": "040e2358d1b1d4e4bdc107795e4f4952fb670aad41ec351c63aebaa75526de89bb169186e050f517256afffb179ac6686b21fda48f139c08b8fb6dcd31ef9ddbb6"}, {"SS1": "1685562d3273a8ed3ec36a36e8ddc39d319164797cfeb1ad78ffc6acdcf09ab210d390d4d812ea303693a27c70357e410483489a8e2368d0a75e1cb3c9435d911dc7460cad8eeeb3a5087393e451ad667dbed86e89bf18b2e1db3d9052c044ff1d41c3b09013e30f259c9fbcd076f669cfaabf7efab7545ef5482d5a1f43503d", "SS2": "0b6950b72d5ed2d0ef3b2194709e3043e03a801a957022f456c875392234ff2d0464e7a9bed84bdbcf5652b7600703f7c298a5ffcd2a852430ef4c7e90cba20f1b781049d7ffdc8db0cc35dd8816dadfc59e42aeda1b38716107cb72dfb2cda203bd196b76b4721f973096df273cf6510f1ade0add49572a2ea38c649cf580eb", "DATE": 16607, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "02d10d87a51771f4cf85fd5c6b73b2424b45083a1bcdfbc932df7fe19f7fd62c12158d1b655e2bffc5925ad96b1f04e517822eb104a94f1d619af560da9c26540e1bf7c04521f8647aa845d3e9b5d13fb2a55ba2bc5bb1eee27ede4adf604c7d047d031b50640b1aab20d99496fc226520e2f1e33cd056aae6acc5f1bb1cd7e7", "SEC": "041ca2427a96e35acddb96e1df74b5ac3bfaf221ea03a91d326db64169977b91c90600c8ff4130f02c5f2dc7f3367aac9a1d785500a2546c02485bf5378625085a", "TP2": "04060977fbbafdcc05eba5c0fb8f3011100684f749d238832cd24694bd6a80b02e22d92802911ff210197b41d91dbaf1769c98a5c56f41d7cd72495c92c12e9cd4", "TP1": "040e66be1815e1764f55310e1a15a39431ff06e5506e815101befd268dbdff90ba205c8706a979c53eff55b589b7aa402ec4ec0f0408fe161b206f883a5f7ec875", "CS1": "0418e330833c0499d712f8ec24b1707e3f8d69c6ed4b36a7d6179cf2d2e7bb95bd1bdcf4523e2654e9219ee9d110590d36f6b8f0cffb5104a89626cc8b55fff521", "CS2": "041cb789c0bb4b49215477e6362d8cc512d61d778d59e7508a54305b636820d3b21149356cd6ad14ca36e51d5154d06013caa4c408f7c39b9b5d32d50445f3023e", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "0409ab2a5c44b53a1e8f8cd54b45d05fa737c8458b55dd3b9ba0ff7a333d58715c1ee2f7b3521ca8729169511ce90b78467e705d7cdcd908e3f52ec0a7a5e42b75", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "040f93aced85cc676e8527ef5198bdd496035842c5a6d77b42f5a9b171f2a8174b1c366f2da8c4ca84079d161265ce7ba00001716ccfd460ae65424dfe3d7fcb77", "U": "0421e30152967bfd7234e8e55ac23ae2e327d1649bd4f0bc57348db779741b71c601627dd96cbf9b6b036043608f3d3fbecf8d5c7b2b6084c38e588be2ac93b701", "SERVER_OUTPUT": 0, "V": "040e80a70173e9b0972dfd9154761c68290e3b0fb32d882a70c3a5b3295f4944e10a3eeac0d053d381b1dc02e97c56fa8ae5a26f5037532daef31590f252c793bf", "Y": "0a2cefcca34ce473c93594e58458b1b36c8b2e5aa1a9d0a384b0c6182d4afadf", "X": "0a883903dee3705810cd060d9ac493bc3b79d21c5c363a91410e7e907b3385a7", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 233, "UT": "0401509c00eccdb229f9a29868dd8fae59bdb5c1bec7a8469f5f51bac8fbec570e1e6b66c1bf14d952bf98d83df87e42bf85c0184895665051df013960c5201759", "MS2": "1d5482d1975c326655c5be325f69f5e3e7c74d9027dca455a80704f6733159c5", "MS1": "11e8c88f26e853eab10f63fcf2d6384575f0ba2d8dab529a188ff4e7d2f2ed16", "CLIENT_SECRET": "040d9a75a48da2aca6518de442b398485e2b3a37559634768f683c2ee582244b2d21546501a3714f2612348fa8a24358737d1076e3d89dd0c2150461051e7953c9"}, {"SS1": "167f8beb4b39f7cc6373e4ef86ed10fa237effab001bc419f7feabb227592f130bae52e44c88a5dfd096fdb8983dec3dd0a069494351bb15e290fd1234dc1e4d06994e07ae01c87351b05bde57803bbc13821fe59eb43c8a20c444cb46bcfd9617919bc8019e42447878e576272a8db9d9fc0672ee5d2a73c533548d9275845f", "SS2": "071cd19abfbc02df9b6370dd230f297b1da2325d3e9598269635c2ed6ba21181071fa998097285c4d0d19a507b657891258bb678dad929ba29d26cbc9d525aa7200846a0cfc0c14c4cbf2609fb58108f8ba3f1916300fbc3c60cfddab349ed7a1da878d747e4e861a95eb9554b26334faaad5ce13b9aab234c92267140b456c6", "DATE": 16608, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "12f4ed7c7c71563e99c372afc52df40aef145dedd9f2d9631a6fa9216de9f2b805bf9a3ac0824f4adfa275ffa948d14dfbfc772c8013dc21abd9b5ffc6260e8d083c54ab4ecdf35595fb0bf8d5050ea89adca5b4af1812cfc32caf90c9b8ceee234b3cb8a6984c50ff25c0b7959d42993938c2a5b2004c6be76829ccbcea819a", "SEC": "041550dc3b3e023ca203a83843f3f028c5cf935c129a0eb6d1bc85871766b01740214c7536f7538fda579e096f9279c3547ee6009f955a60c73b4ff9af850fc177", "TP2": "041c34ebd589f6048c174f68b0051182f233deab2502c249586f7da3aa6262179b0eec5c58f22e1bc1bb186eee6a1d6c105c53d412162d8c1d174636425e3d42a9", "TP1": "04236a5592b00426cd56a36a3646681efda6994f21d6978314f25231c7cb8386550d9cd00223f1e4adb41c551b16e4e2e3f32f170438f0ef2173b973cfd9ebd71f", "CS1": "0412625ae8df83269c8900fe87a0771b85dbdd42fd5fbf9abe44aaf6b462fafcd805d919f418897e2632ff931a1da50ffe79f5363b9947e2dc2644dc394e3f4e1f", "CS2": "041d49796cb6891c974effae359e9802418c81954f81c1979813c9797dd2e3a3941b3a4b532801dbf9d0b20634c57bd1b5f83968cdd83dcc4ff7f3ab064c123714", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040eabfeb2cd163dfeb1598c10aa23cc83cb391d15605d3721780ead873914801d1e8e8053919d07b63624b3bb1f92cdb9942db1e1019bc3e50f1a9f5fc1da2bb8", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0411b123fd904a9ea6bc4925c8a0c920cfecfe0da43e73d8b60943f1437e34d7c10d03c996340f0f6b7d8d2939ce5f000784e17497e6f5699ad82350aaa648bcde", "U": "04236385ecc3244cfc6e7ffc0c6a35c373f0754513407977156080f06238090e4c06bc966e595466660e98c0e12b8a18e509a16a9b72d33c817a406e072a79378b", "SERVER_OUTPUT": 0, "V": "04225f9b8da680b982ebf86eca5f7847d07d21b68896a3f904b1c9e0a15c8184461d3788a618f95ac18771ef650e72ae39890ebc04a42288aa88a8b78424333cf7", "Y": "132b5d72ed853e4fce08129e83613619f1240ce7b34231c22b28bfcfe652d3af", "X": "1cb947f3bf6acceb7a04ab1c13b8220ecc4d1fd8942e362dcff2f99e454b174a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 234, "UT": "041f6a637753aaf18362a566ac462bcfc0f646ac7803c2101e1f72116ca5ad8a5f00460c0733bf5a6fc498a69f41d3822b6020ed3cbc4cfa4220533d3f7f5e40e2", "MS2": "01b3420ff49698b3aaf97ed50f14164080ade8c967f6b20ddf6990a258f89ddc", "MS1": "10bebd61d7f48db9fc8b6b41679110d50ea5576b5011466cf10884f327ae6465", "CLIENT_SECRET": "040e191641fd75a50185eca03f3e585d425db130a71eda0dd3b9244d4e9f316791009c02b21ac256afe0a94c742fbe0a41da7c5d0b576417315a571babfb1632c2"}, {"SS1": "1dcf027f136b9ee3b31e0c1dd6c9c7680860e66adc9bf34616672b84ffb95277234e26d7f20789f8a8e01bf27eeb3ebb6b420cf07ea66516125691fab58b857f0fae7854b4a251024c04ff20d9adcf02412de97450738a0e38d8d32cc9336c1b1bdb167763a9e158b1e835be82911b52e5ccf66fbcf1fca22ee05b170444393d", "SS2": "0fb6529de5d740f2cc15676b4d1d8893efe4d8667e1d70dacf01d78b7d0dbcbd1b9d3677a28f49cf10859d134e5b61d05d505670702219f152cf82273a1adece0b410d881cbc8938b81ae12ae36d87caff15be664e37313af9508c41bcb562e40d30dd9f994b506f9932dbb5098ed3b4f0953b9712e9ddd65cfa4dd186a6af61", "DATE": 16609, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0d5579035c58935ebc8955e4629e6fdc9fd8cdb3ef458c32946da1c0dc63afbe000a9b1463611e7bc64f6bec129964b96f00380a9f8bf41cffd586fd75e9c67f0f234dd8d02f588bd31d1f1f4cb0004527e8a6547065af90bc7d15b4927723c9047b5be1cbbcbb25f02e9d8adb6e0c0c971e89c798dda3b3ab07101cb8bbd647", "SEC": "0413c9db51bad83d356846b9a83a9930a5c15e051b81abbfc563fb0c81a7fa8c9712a3d1d070e2a2ea630a9e6912c4a83b3e564cf962c5052fa173accf235c6f75", "TP2": "041430def35ad1e9d4a88bbb441279034875ecb12e74b8dca3724f130e8ddcecc907c0fcd6bbefabd28eca730109faed887f854719dc38bc3a34c0c02e7da4bece", "TP1": "040adc04fa75d2c53c42f87890366109e6e30bdffae71d3db09f25763584a2cebe1f684e0bdfd3ded07c9dcd7d1224651a7de7abc57960d3ec3240c49edcae75e7", "CS1": "0410129557b6852611afa13f28677fbe09b4a0b0a65e7d5236ccced57a8131a2f10f58fe4665779a6de7c1988890f6ca15d29101e6ca5a12c896dadead8ffad742", "CS2": "040a2e532a8d390b03a76e5f782b29ccca0850c25034b374ad2219d41ea5a692f81b38d06c147cb8fc48ab04156a9bb02c4079d8caa847b1c959c2bbb72da6b7c5", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "042282cced10fbda3c7cea8a1fc87607e8df06eac3b4b1b27b132a42ad3285c43c0869d927c893e115e5468f1ca672d305816935b47536a153b0ced7dc790fc4ae", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0413987b0a9484750b7b7326695c840b52cc7e5a9bef58fef03006b2835d0827da03952cf22aef45a3e0d34d8cbc7cf47212eb04b8901c740cc5bb41148e7d8c09", "U": "040c61453bfe32fa93444de8f4c628d7f29d9fe7efc512ac1aa660e983e2c8b5e7234258d9da0043eb959ec24284b4e33f046e40cedb444ec21b3ae9f57b619f2f", "SERVER_OUTPUT": 0, "V": "0409cef6acc9349a7a047d4768fdd3fbabc95ed34be52634f18fe528cb0797df7e068adcb75ae08833c3af43f858338f7d767428a6d0cc240d0dde0bb3c90da124", "Y": "17d1a3fe2488c81fbbc66afafbf4dad223b5b6b0fd254b73f4f68183a59254f6", "X": "1699b2aebe6a0de6e33616d3970cc2efaf39a6ab11a3eced253414a04bbdd268", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 235, "UT": "04175d67163695e9e3ecfe9f715be1930a149fec043b40266b29fddeeb8e10bd9506a5b87aa014b8c2501df7249eccf97693844a98f9c6e9bbb545318029bd1769", "MS2": "01031a18c472c96b644019ace5fcef668c96d4095b342da1845eea3a0033bb36", "MS1": "1f513f526970eff9c9af1565886cb6506228032fedd9160b67849b97ac8f541a", "CLIENT_SECRET": "041391f8bdbee0606d3f065c7f7bc7147c127f5f6ba2851372a90944e69a01fe9311d0505f0950b2c697a70c191aa3343889e883f59561735aad6e3150ea0eac3c"}, {"SS1": "0882368db2214983a694e3f8f05a987c8b6d491369589ff9d7e9ab210232c9c1091e96a8e28616c4c3689bdf84634d1543759e5a84d8742601402ff9c91302c70b07b5a3e13272f1d8f0dcb419be58631b23c8b0ccd0da0a22ab501080a4fbab12236e6e71c0f2967cd221bdbe61419e99a5d7f8562493e6a91e33d202aa959e", "SS2": "02c7fa3fdd2013814d9504251c314b404129af433afbb87d5205a08e0377d8c51262a8b563f35169422a50dd7b820e93827e84256859670995a7896bbd4bdb8c1752a08de3871767ded50a45ec2c7b925ae77e5b4e0c8414b5a66f80df175b6c00f66e9b1eba3581a7306f548a760e40387a6617edfd0a2b9457dcfcdd11c0f8", "DATE": 16610, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1bb6df2d0049d67f53f64c351c583a9ae077d76e83997276becc7e6282200c1607e63fbf3f42049f774809c203a0e69e8f9e421d7ba54f6b3e282e99093a5d69186dc27d53c996fcaa2a409c67d357c4a7c7f4e1f607d53917048576e34bf3061319401b01ff97ca34e03989155fbfd58b93b67c861aabba6e29d2200ebcd6f6", "SEC": "041ad4c659307a9b3a4cfcd4b915f15d1f62290d73dda26e2d6ef4de77788e9e4016029a31009b39ec97aa97799152aa008dd3e9fe725f6279a89ec0688199dfee", "TP2": "0408202e9fad5e60359cba21a92a20f2c85922abc5161c7e33818a4e051e23ae970de9f8a05056ef2a446e7001482cecd86ce4b25c9656346997b127e1d38634f6", "TP1": "040784f1114670c43bf58db4ed19d72c0d6df7ed3ac513f6dc92fb78118b761d601f2b1b198f71394b430ab50adb6258a21df3b195456ed49da65535902d5c0e1f", "CS1": "04059a6264a670a815bb37265d12f96b5b62889b3a1ee96ad0c408199b682e09a701124ffc734d788d5fa3e5e19483cad0a02bafc94e5f32b50366a6c477a84a13", "CS2": "0405135ff851b44fe2c147e85daee2507bd2f05b9367df61aa7f2e9ead3fefb7ae073256ead669c086829659d685d323af8e30ee17eb118a0165fe794c1b9889fd", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041d04901cf068f6cc26ae18283f79f450a56ea1f48c013bc1a10376fb1fe3571420c81ca537db312c30abb469c5d558cf06fdc7602aae356d3d8f77c07659b943", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0414c526997f53c05c0a59ab9220a5435454e5d8197f5ba0cbf08c0ac932e377a81949dabf13d6141dde6f0fee2d5e35d9b73461915f2abd6d8572ae043e30b353", "U": "040110b8d10097679a91fae83d559ad438b1a160a8b8bab1e6b75e56918f2b25a70f43cefdcdcb1ed69f3bed6d37e7b1aa8868d630ea62d72dd58936677b1ef60b", "SERVER_OUTPUT": 0, "V": "04142f7a8152ac83137103d54434de0095099ac2df3a12073641e3deba145a4c930171dac45006fb674975c17a61578748f070d1762c5727ae135f4393249d0d00", "Y": "143e6615af1ed9df83d808a72b69f1cf85af384414199f26ee0ab74c1b4359fb", "X": "0547b179f19b8d99a0a3d64f0823656e7864df031bb926ed8ab09735efd32834", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 236, "UT": "0419668670bbd9e7edfbabd1805bc39e0e7ec6bdfc1223675b19300f37f47a853c0d2d0de04ad004b78fe6fe06f5135ddee6e31bea4c5f815065a26d3a2bdc20ff", "MS2": "0298eaf40bb41ac8a80a53b018795b6d51a318b420a6b9bd14c680ec10060e84", "MS1": "0c7499406fb1bdf5ec2ebe2cfffdae79dbbac9810a6fe9c9f376581164aeeab9", "CLIENT_SECRET": "04163ea9a36b3bfd2caf5f164eeac17a8d53eca90ea22c3a4627ec9d2f4f6e39f314932b668a2f1efeabdecf8a3c46b5211399ed77d0f3b82bc6ed967f4623d2f5"}, {"SS1": "1d10c177fbe5db861560547c8ad092fd95ead4a5cafc1d91df94e994cd99ae501173211a51e2abbd8e33f2beb633b58c2808d028445b5e9099c742d4b314563d0a596bac0da0e30aeb43a8fd14ed96cef799f3559f9193bf81918d1b58429a4810e9a0b27866505edba9858c050066ddaf7a9ad3443aa95cb84dcb2cd8b52e22", "SS2": "061b173e8acb99ba7dc4614dcb0e6f411658639dc32bc75fe5a7205a5f6689700ecc5935d1d2cd9b8d7eb7dc78cb216697dd1aafb1f796104db73ba96213f9b9084eda56459be196d18e8908abbd4f296108239410eb1e9dd8ab0facff01626919a38841c6934dd3c23261ed77dc6a4382b71e9056dd736887b5df72e2400650", "DATE": 16611, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "15fce984cd9202b53c7385e1faa1183d2a793a73abdf53d33f9fc74613e8803a1dc6247c73fe2919368d4a064bcb086b822e995791df0e3f2349e5122c8ba47f1814b098d30ad3f5c55f85121c18115616d7cd2e1dee50562711cbf6ecd1503e15d362e0fdb479e1a7bd52515cddab836eb66970d20ce6c2ed526f5f8ce64f8c", "SEC": "0416c9749d6aafbc116431fb239f58589a3afa7ad571b31c787ca4a74ee7a34fa009c4e87fd1287d76da7db1ea058fd2e078077f2e74c5529feb4b38400651e559", "TP2": "041995d5c8efc8580f2325a66258b6be90fd70a0ac66cb42ae4940ad23020df6b7091a6c769114db3afb2f78178529f145bb238325d11cefa5120257c1aad6e456", "TP1": "04029e48b19d17b41fdbc3f338e0519b7020e1b298da57b6e1236e3785c7487c882344027be8d4e71046edf7d7edd3f0356f5fc6bb6d85cfe4db5c5a1231171b68", "CS1": "0420eb98ecbd71bcc113cc570b855f48e213d4c6afcc895faa3a95cdc8fa2263ca020614e82f9bab654069753bd0f000a5033711f6d2a1bd026204399ec9854334", "CS2": "041c9f323f1d514ce006844c8dcf9ace5b36e870cf9d4c47d67804cb9004f9e9a214bfa2e2b2ba4c894a89fc10039cfd52f0d9199bf0acbda9c30166e8a0ab395d", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040c763c602190ec3f577bcec924ac77052a9a431f33684a33e7e292f6adc51ba6129357f3731354ae1446e072b2c134fe8e74d3d5f4699d257b470c9a68a8e8d7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0419c9df9a5eab5dadee50ec6ae8cf69abd32b43a02de5ad650c2b9e83a7f1a9120db71c65f4749ce682acb5ccd78893e2ad83f5216c1e4f980a8c18280f2e09da", "U": "041bbd7cbf5e4ea17c4f26a6662fdec2cce60b67360361b7f1ce1a082d167221e323deec50fdf698bd6310cba9c5c45c769e11cfd1aed33ba9c7516b221b193097", "SERVER_OUTPUT": 0, "V": "04215fd61c472209c3d47b152d1ee14e33be20129fa765afbd82d9de0a62ffe467164767e7c56a13f968e68660a77ca26d8b75ebedba63d8e99a5f1140402fd7a3", "Y": "0902fdb81bf6245abcd785ded1035ec0993b9be6c581ffa44bc5c9c1418105e1", "X": "1ac98e503dd0625aadea1887fa61efda88a31d698bace1f714bc7adda8d8a3b1", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 237, "UT": "040cfd736712b7583fef06ea9c216d4ac6c8462bf3dfd4076f042434a1ea584f7d1159540ff8c1ddfa0df4e1f0d36ea092d5e5bc22e42c144d0f57504cd4b066d0", "MS2": "1248d21088d7c7c31950f3b9e03678200b4478eede73b3e9ffbc186dc97bf9f2", "MS1": "12ec7693b752cc117119314a8c2a3e8d11475d6e611e197250324f9040f1ae0f", "CLIENT_SECRET": "041a2a01969107ae0db5ba20e2b59ab50094d80265f8e8b793880430f5d74222c918cb66e8af95930cc3184ad8922fffe4b922a7c1ab0794e5e8092eea9671a414"}, {"SS1": "0ab139b15780dcea0c80f370ed7a0dc0ac271d1a433c04db1e508b2c7935db611a0b8a14317a0efe858710ec4b1a694ef882e1efe8aa00591667fc5f1bbbeb9b217d95abd578a27c6f51bccee112de440b86f38e680f1e14288d1c62e89f7d861d208570ad8354859636b17202c361a63ca3924038b44f2d784964e84bdb0982", "SS2": "0e9db6803baa04f764857e15719f012492c31e1947aa0603d30dd3a890e1c3f71f24410dddb66ddf432646a976c370a5e924b4796cde61255a2099ef62101cb00237664652ab5386268fb98bccdea21be3aa79a21ddcefc2ab4ac5a3336c793c0b7bed45aa944ada0f5e7d39f9b3ec441ea5e772172f5d6656654100de15db77", "DATE": 16612, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1389aaeb9f3873b0c33eeec377374886764f54367b3da7dffb7d61c3cffb22d71845730e18344978a533f424ebcfd33f7425f8c003bdcadce26fc534bd32b27b14eeb48c31e690fefa76b22e630c3dc3cae9fea9a599495850c188ab7a91be9301e00331947c421da829b0686ffba6b54236f352c252f0cdd4f7015f326f3f2a", "SEC": "040715f68b99adab36d944aae428279d39a760e917a7306f0b8cea4b82503fcb4b111c032b1fa72f9aa5311619ce6d3b6a4b0a77000efe0c00dfbc3332b22d0928", "TP2": "040c338d5eca93c7f7e537ac0044936336b4420583259a9dabf4c01c5c16185e8211393a1926a795355314c29d129824dd714a0ca3839b14ded1f27c452904f579", "TP1": "040531c30076dcce8d6df04d04dd774e24a4249e37c873a0fdbd2580ef06b88ec61a03976a838378ce4e55e3c1a057edad2eae3c3cc1afe281a1debb4bf4f251da", "CS1": "042224f978bbb93226b730d3bb6c4babd876c486544149f7f1cae19f7b692719961a9470033750ba8332e63d8f2f15003a91003ab9fa9498c35aaffa5c49208aa4", "CS2": "0400c443bd24e58edeaf5a34c70b4bff8678b193cf668db0712436760f93778cef137dfa5968d00f380def5eac06c7f221b1f4518f00fe7f894b64af268d2cae62", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041192caf48e59682230007e12e45e8657520723a69cf1535d65f8a2316ed3002614508a7af7f0a86f8501ee8274e409b041d25ae0120ec945c92307183adbfc86", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "04229203375bf825b99e67db6a1db2dddb5b095d25e889406a409677bfe2afb669150d14151f3ca74a7602d5385341bef8b6d4a79d14e817f4805fc3ca1d303368", "U": "040625454cf64f3a230491058230c013566d9b8228c93a0a7ed5d1e7193ce0d0301d1c0de4aeb17d526bc982e4af486c377b1209a657921d12d5d5df02adaedd07", "SERVER_OUTPUT": 0, "V": "040169292e4a0cc34d6863df558167d2f655e0c58082e47d82529b9ffc0c5e35b410f52595ccfd36bd0d904b3e44b520419d76e886a0d947692417eccdf5fe382a", "Y": "1d19950fa923ece9e90f4de358671b79d452e14fedbb463d5d2786cd22a5b24a", "X": "226cfb94a3dccf7f3b991cfc96a5c9ae5b51a7ccbae9fdbe19ba59e8963766a5", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 238, "UT": "042296fba268ecc9ca7429a5ca60d2e56aaefc84b3b00e4b3d90edb0f1438c5ea81e0b3f6516cdd405ca25c2688d4a1323626e7f23fea554af9af5e6b4734328bd", "MS2": "0196d2db12b012bc8bbbc3ef89c3072b58e8f64f6693cce8debb9ede91e6e203", "MS1": "0c54aad6a52dfc9391827a8b7bc9817dc7b09e02c2b9d128498a77d36d2fc427", "CLIENT_SECRET": "041ef77f47b64a227a2c702edcc16f50c419c94373b7a74ffc4d7144eab6141a23085561b6dd5f322807565d1cd7672db2fe496835a97603e2c3fe65f57d320670"}, {"SS1": "0f4eb28392f7936c6aa50469b5317fa76de314c4749b852d320ff9ac118c890716a4cf04aa05e73bbd97161c21e99774c74e9d05eda9965ab04845bd16b23ed0062296f4c52bf670464696618f3d5dc1f4a4befd8882945ee1f27f097f8d945b133564eaf3251ce8c98ba9fa0a877e83cc502fabf99f32e42d7d1415b1658e7e", "SS2": "1781f9a5560d77ae7335b941d06f91e4590013a84792307b06ec8eceb8d5a7cc0d456affe26f05bea6d2cdd9b9fc4f8738b71bf67918632781f8c0893763da6d221da50ef476c1e6a65dc5653b5218237dfb1d94a9e2665a01568f1d187c826719bbd6ae05b9e95b94919035cc0377e48eca155cd3a435e32e4fbea0972793ab", "DATE": 16613, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "2000838728b9e4dd73c5308caa61559ddb34daf2ade314ada2bb24187bc1e00123460ed6b481336838aff7a64edb70c7fd0d60146aa400dc03bb0ab7c6211b4e1b230bb1409bea5c108e0c72f0746c6a490457c18f240d8d7513a6be002905fa0b93ab13d8c612a2c8dafd63df0b1cffa27f68a7c96b1d5d20ca585f382134e3", "SEC": "0407a20b5aab29e4a8366dc5c013a4e7ab5816c7a026d6f20e97576284e9a136b901019d6ac6ca8db4604be016d2c41bd4f4021588ee31fc7298415459e83941de", "TP2": "040eda0d4e50480cf12d4efbfc117fc9ef07472da33372a8e9c8fa34d32ee225f320833a5e96cf5acac507ae0bf0fe6edcaff74ebd1aa63bf49c440ed1bfaab666", "TP1": "04085d1db05c30cbdb07b809e0ab4b9bf0a53f3de2f3847fe20c270b540d0e2e060421366f21323e66465388c74935c02bfff63e6d1a4fb45f49fc6ef6c3d83d1d", "CS1": "040feb4e184a902faa25c8730ebd97e1eba5366efbece4620f24e64c4e5a3f5adc15490efa69e58a69cc85ace24c532f28508f2997f4eb15032c03b26b3304e32f", "CS2": "0400ee5701628b18006a9e9b76712253562b6f60de53a2f60fddda897cf14bba831234fb48797c07f9f5fabe273564104b02a3ffec0ae6678590a5041d7efa19ed", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "042039c6f7bfd7ac8573a8c5a72c3e2a7b5edc88ff8fedf1f5047c041d905b95e5212d0fa20e01e276f61173d2e54d04b22e9fd94cb105396ee6be364aec87fe78", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "04204b60637e0fad275ae4a792eecf7e3fe9020f6bb91ec2b40827a43dc237930a22bb2eab512654283ccd8ec5e7d8481341b9be03226ca5fa4468d407aa315689", "U": "04202a77e58181b9a995b575e04e9603dcea74c0388e092a0dc4c1934570275865146f70df79110b83e3f650eab971eab386e1dfbe18f2ce960ec3b4c4918e9625", "SERVER_OUTPUT": 0, "V": "041e809f5b2c5d9a568116da655168e4d12b175e15e4372ca781542f3b98181acb1207069e269163e4686b62fd7f5b38238d5282512f78f57c98594f9367199373", "Y": "0a35986aad319855fead7c4fedb6c6c76889fe99d225e46f354e9804bdddb766", "X": "0354a3efce2a17e22204ae800ff77a99265486c8f43bd908a171bf8ad7cd3796", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 239, "UT": "04152efc7906763e071f589aec9d85cf8e7fb9caaf2dc8ad305dd5f2b82860b91220f535113b2f2fedabf32ff481d4cbe96a673e1b1389f01c25900fa965b006bc", "MS2": "02d19236105a827233f03829bc495dc26efa2f17ae77ecfe3e2624b216ebed90", "MS1": "1c685cae5e2de229828930e54f2dae81a464698f326ddefcafd1e7e9f490ff49", "CLIENT_SECRET": "04164b6d346ebafe551d8fb1e56d038971c8291adb19118bafde85693354be411b23114ea465006689c5db6267af12d6399a805f106c667c93bcb804a27aeb84dc"}, {"SS1": "18d9873620b1b471b1ff24047b1295e44c14324cc624e61afed86061a6805a6411dfdff015f59585b999a4e4044277a14238fce5850b15fa0a39362536285169039c0b1bf92832a4a71f72212c503a26d15125d5962e16bd07cf5b19e537c0860b79f7913d096b28f9e3ae4a2ebfbb6e9657bb2d00fd90859d35b79f53b7e6a2", "SS2": "06053de7859dfc178b1953261d4b1b34fe586df86bbc5bc31c8896dabbd052890fb0878dbeb29e004c2ce577bc1422d37375bcf0e26e609e7879ecd02a9bbd2f117b10149be0b04c861b4853cbed5f6c9eedfbda009554049f5cb8d9deed959f1e888b7e4847eac035f355e616ddf589fa215d03c0d8c3471ed0765f167b864b", "DATE": 16614, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0bc0f25100f82748d1d1f6f94e0ce2421d5326bc42d7ad9804e40d222e99732e145c42f66d09d505680627071b81b703ae499513d19ef85bb66a2bf44279e6be15744b10a2d72950f432f74739b303c8ce320fc14ade2b34ceead1516690deab1e08500b6f51f5d2a95d39bfa07daf1fbdfa70b4624e5fd517c8234eec5436cd", "SEC": "040b53d1ab7058354d446eb29642671bb23da7fa7dcb5d56b1a0edca186c6df56a1ad3d8c1073cbea8714a2d4346cbfc321551efaefa51ff8e4ae801444712ab06", "TP2": "040f91e7253e9c5826854f68064bb6b8c29206fc870e52e0787440625b05ab3327007fc27860287a10b121a9e01ff1167327a26b2d9128e782985f514cbb87ccd3", "TP1": "0423783c35db5d4c256b6622c4dd1614278f7402a44bc0606e0edc32d11e9c63781f27c22610fb0c5e020f9315131689ca50c1f2cb21837643805c7d10a760eb8a", "CS1": "040c7ecf5001c0c84cef78a8df60a22366eced9d372bc21c758760c4d8ce595136153bb7df11f6a205ba8dc1d57eb18645a7286ed1b3644be14e046909489b8e21", "CS2": "040c7590bbfd806ec685c757e9b7b8afc344b1eeba4ccb2ae6ae70f3b3a745dbea0800f8b1ffaca3a0029f37e15ee5c7ac2e9a69a5c6d935ddd3d0d69b4b2453ed", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "0410b734cf147bbef9f48c783e52acfd854738a5e5062216dcf6013bc1bc69b89f1b2559c51067e84d0d2bcaf7a9ec6232c88d43c7b18c53fe87fa94870295b46b", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "04142f000a58dd96d59f5e57424ca76075c5a9bdbb0b559dc15dcafaeb17f2c72d223da411d0a28a84451bc71a6edede6db1c0e8afe73f475754e3266c72b54781", "U": "040288dda67af046a17743e252999b39253d7639581301b1e09afae76fef9468b822515c176093c2dff37ebf9b9b7d874ca5c5c3ec66c95a14ea4b0d35f6a60d9f", "SERVER_OUTPUT": 0, "V": "040402fe6a6d4a0e862ec6492a767c69fc6ec20a053d4c06e2e62dff609150d03f12b6bfe097cf0f022da6d999ca7cae02d2f91b91b0dee4c99d9f190d833c526f", "Y": "0dcd082a33e729b4a3ec512acbf3245172861e571b94104b680d9941419703be", "X": "049c65d7fd03aa44b070d0f127d8373b7adbb34dd2b02b931777b8a90ccfcc8b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 240, "UT": "040395396d6b52392133e5333c01319bd6e45eaaa26b7ef5ebb45f18aa07b094d506bd411f26450139b529fd5eb707a2a8e8298bb2eedfb997d9879a9e0c9583b6", "MS2": "004c43c8e36314249dab551808bc8d29072ff6434be6095b3d8da38ed7cd243a", "MS1": "218d1de773c2b6c6b593d4adb393919c5a5c11658ac280b32dfdc71fa8fd2733", "CLIENT_SECRET": "040f169bacf80d279f78b20b0b525c0c73f0fa22cc2da018ecd562ba7ff41b466503e3c809aaf24ce378fd290a244a4086d19f5fb72cdb49f5624771507921bb9e"}, {"SS1": "0b276b59e3ef979e442a49d8c76f7a1deb9409ab22bdad71628d8e52c5ff47dc0b78d60d766c1037ec479ee1df318cfb3349c8e27f4dd3b4c41648098668b4eb0af6b4c5a1c1bfc6cd0568b3436032df8c0a8650ebbcadb463e0b6a7363d44580a1672ece31693ade3386cbb29508196dcfcff3b64c8d833abbd9fcf47bb401e", "SS2": "1ab1d00ef6cdfb4d72026559d0ee51dc240f13910484b002542d2b4598ddf858056d31f185cc8416ef0f816ca88fc5a8a7ea757e17b9c3c66ba239021ff95c95109ee4f78ff45f5952eb705a8b6098bfed529fabf2a0ca46538960e1b54638cc184e22cb1bce5fcbd13c711e33a9d585813f538a3c2318f154768ded3ade93f4", "DATE": 16615, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1e4fe96785b573d32c80cc03e0970c7e90366e057afbc196765c960b04ef1fa606db9b4df89381e3643ccd8e1478a6356fd61b9e532ffd10f7253085376633541d9e350cf7a950c1e179e1398295a3890cf4561322cbfbab0b956c89a35b02ef14f6908831792a7898dfc5ec935bde6ae72ee9aabe3f274bbdc3f1035d8ed7b3", "SEC": "0402a7c248526fad88789e922a521fc04fc9068df042455e622254a34bd5ade7af1d52fd93a15cbc72a0be3fe31cbd193da2e21ca8d403bf923fcba25bd7944bf7", "TP2": "0414307d0dc9d571b4ae976f8874d82b9aff67c34252fc9aba5c292dfe10d05a9b1fe523cde80c2e6536457cc46018fcd86cb6ac288eb059e0c0c80a218cfc6a88", "TP1": "04233de844d6d26755f379a34a23d8a4dac284b81e75a3a32917598e8adbaaffb6144f07504b7980b47f956bc970368ada1df327139e3dc0a71d24997070263727", "CS1": "04070641a4970ef15def4cc5e64ec797d2d98d1b39d1bb895639aa2d4108c905f0031d046aeae84031f05fb6e584057710e3727dc4b49038e4a53e6e15b9826f08", "CS2": "041caa9df15f75eb3ed840387f61d1f917cba3ccac06d02257923d8933ccdc5acd131b67807972f3861710e153e53f0bb7e8e9bc01131f0412c7230b1de3b47475", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041198301586bead2a4ee2af83a4c1638a885b1349425097e86d06b726194fbcc0164b4cbae8272fdd515792b751383e56555819914ad709e71e693748cbc162ef", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0422b8bd877ae1ee725f103f64abe39c633e13c6c6268c98192316e2a13c9e56ad0e7eca66bd5fb91e1e923a2a3dfe71f489d166d4dca9eae21b3d1f79a0607688", "U": "04051f3609967c6c7e84dd7872ee812c5f420480d6f4fb76bb9b0e841455357f20171f45c42bb3d7ddc482d98b0173c81dab4b40e772c9239eb1de8887cd5efed3", "SERVER_OUTPUT": 0, "V": "0403fa06fea9a4a70b743f49ac3dcd69ca99319ffaea0dadf208cd80f81d51650813ec21fc3714325b796e37702d7aefa7eec10a6ece6572203c690eb1e5da327b", "Y": "211d03cfc23496727a551410c2a84a1755d688e4b557d6630bea84896cef90d3", "X": "06ab4bf3865cc8146cbad56a5a240961ebb7c176ec93916a518d9d3f6955cf18", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 241, "UT": "041cf2732f10ed023312ccecc111c77fe2d74148b09ff4f75d7ab284a381be519b0ad0e425868f5c015a732cf7657690fbdbaa18ff92c27407d0698da2363fe987", "MS2": "09bcf1d559f6d9e9bdeb61d1b442ae276fd41442514f86a3bee8ce9b9c3f74cd", "MS1": "0825dfe882cd9c34bc3fd9dca7d906ff9241e82883f9034a3d7db9d6e27c59e8", "CLIENT_SECRET": "0422b39b54e813a06a6f8fa642429a4debde4205033c3da91146a61ef5c60a259f01223203f2e940eaef84278aec975b1a714112b1bccac27bf51a208bc79d0d1a"}, {"SS1": "150827b5363eb02c2e148e08076055e42e36a0ceef945412c050ccb098832133031502af06b2f09fd82c2ab5e392a3b16edf49677ef3de56621aaefa2d33cccc0597afc5ee96672a33c75dd435f1e8fd0d126e55770122626341821c7a91e1de17ae543b6abd46bbab78c1dfc54e5d27092b8e419bb88e97f3539fafbbf16a3d", "SS2": "11d61aa5293417252875d1f4c174240a1e75025a02edddc41f2eb017c3fe29830c69d9fe52d0b17ff4556490c2f47b54df785fec09dd6c033c8107d2f71bac3612fd3ba247bcb48804d6cc0e46bd5f79c6ed856d76c2feb0d3ccc6c9b437f1ff1b6df82d84351ac3516630a68eacb5bce76a0b6db7ae6df2e448102d788e6fb6", "DATE": 16616, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "069dadb22aabdb3b38487cf955a7c09a740e4c827c33b1a0c070322710284d78043095c9f1ec24cfdb434f9c160e5403a1c4aca3d435638daa9772c435f032ca0254753f853bb2181597a9ad8c3c30e651793d035d4fce5c310807566b72ac060398145b14ee7809ddb7eac0e9069795b2576bb7a92a6dc422c67db1480c1fb6", "SEC": "040fadda782fb0affd0ec299969663e76bec1ec15f0459215040f22a0c2d332bb82019fcd46b5b8350e51c126afb085f928942643fd436a85bf270797d1c7c3408", "TP2": "0402001f0cdbf3eaa68ceb6d2c21a54448a4f802e1ae979014c21eaa58cc46d63401981ee2a6de952fe119c3eee77254f2283504a631ba15e9770ba842b4aaec84", "TP1": "04233e46afd751951f77ffe98d87b86ce89b423c9d709b969206436f9bc93e1da2195b159e21d165a7954b67701a2bf16428a0db7ed9a753cf86612b5f996512b7", "CS1": "0412d3f057026bf3536d8df23e4e4f224e45d53cc69ca112b9a26c598053972f500ff979765eee286365af610336310cc9a00fb67860f4dd75f64f6bac3473da20", "CS2": "040eda3547c4a04304938eb05b2b1b0a6ccc6203b5f04e77eeed11dde29b1b999a00cc9a31ae7afaab985f75b28b4a49897e5a1d5f031326b28152038ac273c12f", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "0422c2ada3e6f0411f85b22b29a82aa957692f0d785d06306ca65b5f24c3b6bde81c1962937716e3980c2ebd34502333d46a4dca499a19d0c4eeefbc22c0e5c81f", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0410bb93a3d654c1cf716a22ab474e959a38d5fe2bceff5b4bff9d07cb41fbdb3a05d5e6bf85ff40d94d71ea9fcd9df3ff8587d4374c9ed92f194a30cd10c06a84", "U": "0409f1d2f9e2d57f2e6cf4efcf9fda298c2da3dade4d5f6549e844554c94c237710b5f980b36f134a71f8e687596ef42a2dc7893772ac2baec2539664bfeaa7396", "SERVER_OUTPUT": 0, "V": "04231b0aeb98a0d2182b3fb92afdf12cf6719509319aa4217552f3f02932240b460a72a746d3aebbf3ad1711ad75913b1a83a737f40e2783e3f518fdeb303df329", "Y": "1e9c1e5e858ef0cb461550b213d46933da9920ee7991c6ab3269ece841e22a17", "X": "0208490e938efdc96977634a2529908010fac7563481f35a508f784aafc640aa", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 242, "UT": "041be484e8664a7711b576d9b5816abd929df5530c7faa828acb89ad97e9aa78000edf81ca73e61cf7dba358b2f78dde2707539ff38ea555297e5e3c06d762230d", "MS2": "05002c15ce11161773326569a575f6bc7ab159c1855a78b8634e8e8f666470e8", "MS1": "0a71ac1d49c6fb793510ca2b7e081cc599fa7bfc9467668626a629847ed4b59e", "CLIENT_SECRET": "0410b6b97423dafdf87100e5fcfa32611b11809307da5af3e8eb1c2a00ba966f6d1d6ba2c9cf8adde0f43a92b169ad1eb89e346e7c98d5d61d7cc75bc9d1c3c7b0"}, {"SS1": "2082ff96e8306d2ffe9960524304a9383d59a696a4ca4be567339f5b5a57502811f20aff8d165f1548cfc0a386444bee708c81dd1dae409cf1d9185558f7a54d1642e9317301492acc0e435ba1e8056445680b94b77b0e56d79c58243ee56262211f73ffcd78c55d6942197fdb069f6b9a56043736df2b0154c9c84ad1465b1b", "SS2": "0e7bd11fe5ded7da27aff73a13082adfbdd337891a5638d5ce4bb67c78ea55f60733e3efa74232938e5ed6ffb701a8f28877413bcf54c38da8840b090719e7fa00898919069dc6f566fa217439ce4d7fc3b7b3f2375c6ab7dea0ac84a3c355f71fa6c8b6ae7ca926ba40e76be60669aba2a4d21e9b3fecf5a04fa10b9c10846a", "DATE": 16617, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "013b46910dfef57ebb8c3308a266b70d4ac4bd6d5940128262e4a94a9ea651d822e1ae673ceb6108867aff7d5b4141c20b875b9574afec56525bea54a3b3656b1a7f9210fe9a7d20ee8aa75fb1bf485b863bf7e3921580caf7fd126dcd527f090bb5d0b7cda2ecdcec2dd07f36fcf62db443b328052375defcb05b0a29159a9c", "SEC": "04031ca6801cd084788b8c0f10eccc620ccc95d3c337fa810af6dec1817f33f2971b4b039164fd6b9c1ac7e295139e792fbe6e2b6a509e844395d657e2bb953aa6", "TP2": "041bdf850ad5b194bd0ec3afc00881a10a31a25b6864f3f46c44e657a884f70c2a09994788f5bd9262ba30697f5c4b0ceaf9319d28de2513132c109301f9dff7b7", "TP1": "04209ba7db45abb4437887ad86d4ae89892e6efa12a16c733d76939aea085acd80111e866eb07d961ac631d0a7b85970d7923553a132fa1949c3279c29a242513a", "CS1": "040b42889174373adc0054b0f2786ae7dbac66164f4a3a8da167b6bea5ce21af6d040b793c8229f32f682cd1e343b07e86f674263bf17760ddf7064a94d98b4101", "CS2": "0403922d8c7f53da9079a46e699f184c938cdaa1f450d3f7cb5b655e2e5e6102d70c08189ea0081afa5edc99537670622cd2a65d3e199c8e119ca7c653b4e0e715", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04053c83e514b53c634daade4a9fe5d1f85a7cb63d458258d23eada66db83c012a18ab987a7d455ff17e5b0a404b2a4770265035ae7026f8baf8a6da91121c6878", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "041a10ad6b8526d3f3569f1c28ef3beec7d7f481932bbf5603a5211a617196362505cc1887371a617fa5e2bc3d367516b263d3bc7cc9a0e7b6c5b22bd50bfe818f", "U": "040c5fe0c17ce60f1ea783140c6050472ebeef606bf5852a78faffc68f8ff2859803bfb90e7b961ebfb3bb63661e139295f95d1949ade311ff1ebcae92df55bbb6", "SERVER_OUTPUT": 0, "V": "04132b831a92d8ce73afb7df601093245d7e8312b24b3448b27ec7523040282bca0b5e78ecece158f8dd8b54210b259437cbbab07dd039196760ca8d96dfc01893", "Y": "11be6c1ab2261b08add78764f0dd7db2b1897d8c72080c0194dfde3e8957a4b6", "X": "0ffa390ee7ce608d8a87a6ffd5dd7be27a41dde1050a7f774a08ecea3ddcb1ee", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 243, "UT": "0416cdb9fd2b7565835c64114d654e3c61576d3c709cd36e64e249cbb13fa6d7d721b89927295c139fe9f11ab336dce39b88570924f479e8199ed13377a1857239", "MS2": "050be0f35cba9de14f7f891300c54169af00f9f21e3d36e1768abff4ea6de1dd", "MS1": "1f92f854bdc493cf7f176d6cb846f37438eefe34a52e54e8fac1209b37bcbad6", "CLIENT_SECRET": "04217c88f1898cd03430a411de33d3501bdbae6358476563e7061ee4c2d21a72791062a9a87cb8f9ca28f912396f3d55d6f7fa4de2bd453c94d2c0b2b13d65c800"}, {"SS1": "1d471d7523f3cd66ece800ff45d111f88f184fda86f649fc23758df9c3d09e9f0472a1340494d8ff682dfbeedcf5b491e58e1f18dbcdae6ade78b0712751ffb40741953c9764b0aaf3477d959b0be02079f60cf82b7b451a2794a8d450440de5135705867df0b5fe5001dc013846de9892868d7644e22b5ad4c377df2a62966b", "SS2": "14f4369d5383f7b5d3ac50f96d274eb0179f0dd62adf8a7f4c64350bacf1db9a14afe9b58584a289379c3b77b7779b5534906106b998c673ccfb1c3fbf24de0a16ff4f422ba24a186679e966b5f0ed128a1f67c39ae857e55ce03fb324c6c25709772f6e2e7c19acb4863f2c874d289b2c112b23e00c12bd7df5ac2e995ee0c5", "DATE": 16618, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "17d1fa3511e9d4b45e59e43ae051c71ac629a4a327b3c984180bb50ec0314b3f126d0c059e81a86338cf61412c2fff0253a821083c28b5a1838f46dc0c9d7df71c60d8250348446206f2189c33698aba680f477d2b62874dac91a9be97c943e911b091762013b97c812af72b5f45f799eaa3206f7db3d2172f88412adb79fbd0", "SEC": "04223d0abc381b608598b36ea78aabd0318bbd3c308242ecd11e8d7f66021916f217aaf8af3bbc598d64b3185d3bb955336c876a71736aa1f73ead116a35664807", "TP2": "040b7e36d791d001cf4348f9f34a883045918f78354a37c75e2089923a8f0f7d820af59565d3a529111220373f3d45713fbaab3eccf8b8ffa927e23d9af064f93d", "TP1": "042219184ece5917973d0f6c66cf8a1eba956f1943de58cda4cdfea7a2738a6cde0badad760f3aa2b03ac1a2be81a2f4207d602a51888f77bd9db0790fb9daaa21", "CS1": "0421bffc189baa05819c9c111c5b75b265efa5e9311d758caa55cbad1027c061df1e07e2b015c69f17413ec5f135c3b8041d125d2afa96189c099824f9f9aa4ac2", "CS2": "04141e274bb11faaed7bfb33978a629736650e2107b73a2e647ba51e29de8bd59018677bcc4601dd7565bcf91dfa68d87d8434de00e3cb18c7fccf03b7b9ff1ea2", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04202172aab712bfb24a35985a952136ff67bc5495783f508e7d87984ccfe8b76811de8eb88d4680e23479e45a091da77998b88e638c973d367ebc7d8b32e7e053", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0407c305c62c53950912bb19797a27d5a6aa63c50ea55c4abab6f95585da2e35391910eb01d4fc1eb8d05c7a9923c428376fd15fa2e03b5c9c5b85e1bc9159da40", "U": "040771e1f2993bc84568c1c2d3de1cc5c800362dd6fe239990e21f35f311758b7f182fc09b7bba64e3412ac2874bbf80af30a234b53d4878ae8d3677e2c1ccc7fe", "SERVER_OUTPUT": 0, "V": "041dd568a88607475b5e10422ccd2288f5c71a58a323e1f3ae09514ab370b3ac6210f587ee8c159d910aeccadfbd905bf153c9b83d51fc5555bcd12cfebbbfe84e", "Y": "1ded76079e9e8fb6fcba7384b92d4e1090dce6474776346b7ae13a3d2da68667", "X": "0838dce291915d91ba1602c1502496a9cc2ec602ebb015c66b3dec8d444d6ec2", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 244, "UT": "041bb0771d4266f7a1113485a95b5e28c85a06d932ca39847bc224ad6b2887b6cb0b53386f270fcc25457898414af00afb556b7375afb8e727bd94436876ee5886", "MS2": "1626d1d0f17022085794170e0691321cb379151db2422f603e2147431d03be65", "MS1": "1aa259e0b3aeccd2464a2af32e32c1730c7175609903fbfb8c354196716ec201", "CLIENT_SECRET": "040c0872d0cdfb9b3c0a2db0322ed1098fae286006cf4cf6aa33774b5bcec37b3e0c64493ceb7cb6279f515535f93326831e719ef1a8754ae2f6286ffc5a53d624"}, {"SS1": "0d023335f942690977a73e626c2049a4a3fffa015cc6c3c45c027360a6d41891005433ea3dc145a323c2fe866c97b26123cbb5c766746e137fb9abdd632376b608fc240d179d492e5de65d66024f88384aaeed0e87a67cd4644e23fa0c4cebcd1f0772ab0bc3cd70eb61f1fe3bd56d63d229e24810fb8d6a5b6e305e4500174b", "SS2": "094ce744fe0509a2b5457df8617f88190f6d3e9e1806bb7ed68e736c7b452c530e08539c763f735b8c7ec0865006237976688e816317b931466409695068b7380add100624ce1d5339aba0c71e4f30381b03daede1a4c4ece49bc1aa496c8d320ad022958f4ead641ad1768db693077d8a05fe600592e770e2d7b8e495125b73", "DATE": 16619, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0561b18d1519dc77a6a45f7f499cee7377f311f224097acbbb1597a05d46551204cd2a44d6e28b6dcf6c41df7703001e62bee56697e12f1e6dfffb3ba4a3e59602b12a8ca4c9fc22534e570ff8980f6b7148b8d33eccee74a03e9fb5333f4eb516c7287904c9d66cf0021238d9e2af6e21f5ae5432ae5e70743fdf6615f51412", "SEC": "0413326fd4a6eac98e78161636df46879ab2508591880aff6eb368fd4b86e3f8e008ef591141e7432feabef37a8091f56464799df811488bb013a29308dd46da98", "TP2": "0416837e8116e5bcb053b87e720ad787de5415eac5f59c9b5a1cf5aa475761217706997331f13e2dc7426a84ae37e4956817f88bb28258201dc68215f36df2dd2b", "TP1": "040138f05e8fac390b901ee40aadbe45c2b3772241517c18df22ff14f9ecaf80721a3baa40769daa2e2f17bdf00c14963ff31d529f616eef9632b075f1d8801e02", "CS1": "041a82a30558ebb54e14e193b1c80ceb55df84d5dd4f2f0d69ffd1a4bd3dde620715e681edf4518fe502f7c59ea51cd6e140274beca33baa9bac3fa3af83149802", "CS2": "041394bfee5c53ed348bf007657d70e6f9f7f937b8129e04d75e559a35ffa274d502e1a073a9975bc4a687f6862a2519bdbacdf21800f301fbc148c66204ffcb8e", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "0412e9b170ece824a450d38024b76c359e9625ac71975eff2f539183e65f0bd1bf0701e97a74b1e83089eb1928138a04a8cc988f747ea13b004269287549178e91", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0404a1fe9090ae1c803d5de75545887b08e523d3d7060c571f362b99a7d3f1027d18dca74b7dc087237a660386916dfc450bad88ef02e66292ec3da90514a75160", "U": "0416a14508d1c4a88529694d74a46daecb1bfe923cc5641db75a59766b7f9edfde11e879932077e9ae30eecce422b859049e893da3f63e7f72f72a6e64d9e762b8", "SERVER_OUTPUT": 0, "V": "041f57792ebfb0e0a36fe305e11e92f16bc790f29a44f3107fa370015934bea5e122310940ded00520b4ee3cf36bd4e3468d0e6572a490680d6289be8b23f4ad94", "Y": "032166ad772bf15e2af96eb6b12913927d8e025c28faef6d97a03990c725f8a4", "X": "1a0949edc3d2f2cb5c7d135ba2b7dc7c05c2cca3719343e65495eb52dd0c2d29", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 245, "UT": "04154692a71309fd6f1e4dc0e96b31c35351ff114020f2cd276af0e3cf98301c4b04e368adea8f361e22b489f48fe16cd3fe4db9ad814e11f944883fe72fb4e5d9", "MS2": "00310c3754bdf501f599ab6919e3e768ab6cb31f3cd194e38352d55c2e96006e", "MS1": "0bd92826d363c5af7d398883a78dd551a9f115cd4598e9c9f2ca17a626356f57", "CLIENT_SECRET": "040594b0ccfa07a9578aa4c0b307f9e2c87f89e21cb807c70c2100126fdae853d2206c5fbab335982c22e164353bd2774aeaf75d78370946cece2fcd6476283cf0"}, {"SS1": "1b656d3753a5de58e8c10671904461779d36bbeada3cbda8ddc2237d2d282978206b66ea9eec5804ae6d85b2b2de4da6f1880bbeb429ba4224494d05029e78971f071790f8c4daa62fae31aca286071e9e0ac42a0675fcb7252ae711c020996b1ab29cf457076b48e973e2c6f2bc5d832ebcc026748f0c45e7850606ee3b8f92", "SS2": "145a4e511f5dad7ad8c4c6d4792abd3a030be6225fdf684496fad654533556e50238cda16378eb24327470dc80a1ebca80e73dbcb906a3ea6ba5952af56839a02141d9c6a2981260a80e7e5b4f13f283971ea2580fcb01960cd2c3f21d5e341209b14b26455a5b5bbfe66a8d92fb9d4ebe9551b20b978a98d11f6baf94823e21", "DATE": 16620, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0c2d1331f637c669dc3556a87f2202e068257daae8504e2863e9d096f5891b80218bfa41eef2751042b639bf6999967dcce976d9b3391fa1033128c15b9fb7ce060953c1cbf53ccb364ceb9b963132d3bcfaafc9e0ee7d7f24c73677bef0fa0104aff9bde187d29fd120788c1a862ba41b915199ec13197b74393b58575a47cb", "SEC": "04106d0fd21b65155d01a7057681757cfc73f291b201f55fd506680142680fa18f0b9e8ed50e3fecc2730018d199581abbb1de31601cb76f340faf9e8e788658f5", "TP2": "0400a23cff040526bd873f70173e53c83219fbda97a7b23084ed9361d679cb375b1a9ff755a7cd43275dd3e26067a2247096a82e7983e89de8c1bc6e42efe4e7ad", "TP1": "041d1e39dc9be6c63bda7feb0fe88a7f414e2a1be106be103886e74f78a94dc39621b23a14cef35934d40b1afab30d04a5586c0a844918823a154a5d63ffaaa7f8", "CS1": "04025ccce989e265ad3d30ceb6e5d63e435005e4832ef06653fd44f3f42cee1ec50eed44c187c95f3bdaa1d4a1f4d0c475b2047e282b80a21aa84e0e65b79ef1fc", "CS2": "0423b67bdb2c45c9de36e66f1cbecafa72d3fddadceda6aa738e0d58762724cf32101135343d6d35848592a98714fd5df886f04aee39401c2ee578012db84471cd", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041f69e3fadcda91b5c4f6d0ab1a87020cea5e563e100937c797551769e00935c92357a9226e13fc7a6d684afb179e1cb17901bba1de350caed786cadb11b4de85", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "040ace6630d6362fc24c933329981b97103b91f973d5d79f4961609fdd00cc277e15b44419c20f1c3bfcec0da7f250d3e10e39c832987230b861585948c0a3cafc", "U": "041f752bbef2f6b8e9b1652d3cc4863dbaefc2df1899eb7c81bcb0617adcf8e3250d68a5191205096b84a2eeb22d2cb0a5cbebebf55b6a4501497e7f2ac3aef64d", "SERVER_OUTPUT": 0, "V": "041adcc3caca3b6f8de031d6f26ed332feb505b2f54520d18b6f1d8d55463687c7117c7378a88f300f72738975d083c030adfc0a9a1a284b256ee4171b969c213d", "Y": "0e820aee415b78a95e2cbb720951d04d4495951bed2183bfbfed9cb671d519ff", "X": "1064399408c4960db448eac1b0f6798a234e65f6e0c254baf0bac4c76399e3fe", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 246, "UT": "040491871f55cbdd45e74e3d9f0b5d1046b40deac67bf0e80a0d908f23224445e90e498b5e054b56f409513816c695499a0cd83b07dbab93ae192ee53b583115a1", "MS2": "22324cf52f0cf274396b31f40fe7dc6e85d6114a269ec5991327c6b35a30d888", "MS1": "1f169d0db5698553f50526395bbef7ecee0f48b71d573305cfaadef7bfecb69a", "CLIENT_SECRET": "04072e87dc3fb51279fe86f6d942d4176c73f2ac065594b2974e55013c18300d0f0eae5952593481cf50c931ea4fbcd18940f8f8383e98847fd979fd793539d953"}, {"SS1": "1e38761f98e4c162303958028d30e15a33d4a4b1afeeccd427f2fb2b8e15f8fb07cdb7bcb35e14c077f11bda06b580e35e1385eb48a78ff09b2654420bd8dd1505f65b4657c7172831ab86e0570c710610dd5d7a1e62d2b97521c794c30f853412b48390e3e7d036d174a05b72c062cc27b96d53bbfce84a749440002fd95ab5", "SS2": "1b8cecad90a685aacda81ced3f417e83c389afdb866b306d44db18db51a41a1b16806baae7153929f87813820930cd84741b7a0aecf6939df4cf1465eb8b879423faa6db0885e9bf0db3baaac5ed2ae3d098cac042e74c745ef52baba25771a52236789c1e9cca0564dc251dc8ed42736a581d5e6f762d5f6b2ed5fdc5e1d486", "DATE": 16621, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "236c6cc5122e5b13017b4bdf306d3ebb30d656460c14b965c08ecb8dd674d1380da6d674fe1a5444f67dba8c8d0720cd52f1b5ead4bd06df3289cf88efc680412378fd82cbedad305cfceaab11bba206d16086d7b23fc15d487bff52a89eabfe00349bedd160d9e2d7bc14cbe586dc59cf061af53ee203c9e7cda5ffae8f0d06", "SEC": "04104226502d2ae44cd05d3febc998f7f845209145ed0b046754633ed28265e3d717eff7c6d0ff41189d938b04fc2d6e61ff82404880c0df821837b48578623e71", "TP2": "04228918217fc41e914439f3fe496f510e3d1f690cf902bd4daa8408d2960713ee070cd57cbe9d722e30364727d8b996b1131b5618d4d44c17309dec90f34f0c6e", "TP1": "040a5c1840487ab0052bb82fbc4b45c4f644c7e4cf438f1baee99223e0d7bf01a219891851e5a36014652c9dbe20ea4b334fe39e979778bd2bafa19c7d027bd911", "CS1": "040326557fb42da103ccc21cfbcbac84a613362a12e438af416d59d3834e2d604319ce184729129bc959eeba4bec8b4ca1e3d2835ae4bb5faf48ac1707bdc51cb2", "CS2": "0411071ff58c49aced360ce883377e867089a9392df1758b7967964b3e1a9e02d20b8418c70614b64212ebd805dab644fa527563ebb72ceca70273c4c64dd97632", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "0409d290c7bac6d079e831e5742335620cdbd327b47d295296e4f80b6f33a19c5904f8cd45e519bb70c764052c1a5d45d195634627654b13f8fe80fb50ce9a83aa", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "04144d45d0d02d7c99b8df392951ad713883605ecfaa11bbf27355013a2ffb34f4051bc343705d2f059f334819c13476eac74fc72ea05fe00599022c7c7e39d885", "U": "0403b88661a889b2ceaee2d55fc7403bd95f9fd69e550a3198e48e5d3ec20f3fb3123470085474ce71d1860354c940a7cd771c647b0592dff159f2c3cc6da572a0", "SERVER_OUTPUT": 0, "V": "041d37e2c4090b8f8cbb011bb97ba1cb8df39f3ac854bd1b8a3575c9fb8ec6234716881f69fd8d75d28dd84c46beafeb87b5656f608cfd25d1ab706c54d2318c80", "Y": "00b425e0e907bf0c384f10168f9530279c540b7e81301ce3a98c2d9c06a385a8", "X": "064a0b9aba8f006c9dd4cbcdac8376ea39117d3a9238918c256d881bc6942fc6", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 247, "UT": "040f08148cb3e9068ff6f6c6d7d6224f745e2e31d286a51a4519b047878d4e8341086373c10f6f2dc61675f542527bcf3d319ce5b7d56e91d229ba574fb09cc63c", "MS2": "1a7d3fb0d4a150e9af3c25838f2114d592ed4d3df2c697df022ee69c341dbaad", "MS1": "0e1e5b96b433c1c2f3931c51a2663fb4a8c98647a69e09b28175f275b3c678a5", "CLIENT_SECRET": "041a6d06a0ff47843336717591ca68677461854f06b37ded519468c8501c8712882121d967f840a7d95764dbde9618096629a00e60aa88f840c519af96e1a82ce5"}, {"SS1": "1c94e05b371c97f74d953c5700c42af04bbec72b4ed77c6532bba9a549c4577d0b5488223832d0145f87502f2b47d6fcb3077a020c820bebc38c1a9312b7954514df1b47872ac1db00c063f1cab7a8e2cf20d92341e9bd754902509a79e359321e2ba4bd0e45523afd6bb31e6a64f76279ed6f504f05062c34e2147c9f448807", "SS2": "1b4040f54a16cd7721998e025d6cff66aa1c34862c156c0792d904e682061e8014840097788ddef42e7cdcf6068dbc4778125be3205f1783ccb09e75726e36dd1619716e3409497bc77b5c1727caf7da74d6363cac15d0df65901d7ae894cbb91bd6933d7f03f0f0ae1955ecdfe2cd064f5510cf574061259d83c97fafc43e10", "DATE": 16622, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1dbe70300b242d7c5b25f57b4caf01fd46b2ed4ad1f2553224fb709ff433d14718d9453c4686d62a4ce47e3f17a521cb6227091d401c7d7e515692c25987a0b10405bc29b715849d252c28cb8fbb68ade1508e35b442e76d65c09e6707fb0ceb111155b6b35589f5b9eb66ce6c1d0bb95d5f06383e06fa97240b275ab0c9cc14", "SEC": "0401b1ff0e9ddbd31f3a8fd8cf9bdd8d4eb6cafa5e9cc263e546a6181ba229dc4b162ae1a00dbf65fab976150d9a7e9fdeaff8a4f8dd8a94ad7eed420f0424112f", "TP2": "041b8c62e022a637a453dc79dbafe1ea939898958aa8e2646ae2f50dd64427b9c317996f2ae598362f2b10b3c9628cb87384ccef9872d4994bd763db7e0f10b141", "TP1": "0418d3007393a65b07e3028c69ebfe633d562967ea93d9b575ab2e713958dd071102a376edabaae9ca20e7ebce504c67b3db946277d23d3fa2791673f43a39751a", "CS1": "040fb93bc83d2b32db952548afb820328d50dcf810a694f3d25d88d4bbf75f90eb1e2a6a74272fd697390edf3bd20537ac96ee1b185e1ec2cf262d04193daace99", "CS2": "0419f7746b6f124056bca608e54309f4a736b9f572c6730f433c62b8043e72ce801107158c0e54affac001ec778e5bac809d4f8b80b98716998cab999f6f855ffb", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040829d7d49306094263ae7c6d4bfd73843983af12588805da3ca5f5fc49245b74231766b63ba12be58e139448b47a85ac757a621dc3b926602801e6129d9ffe81", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0412105777cfc2bc05e07789e4f0200b5e132a223e2e6e99cfb2f78f8e5adfd18e1c559e3fea9a1194199fde1300a85b22be8ec225d3acd0697266fc8bff3fe237", "U": "040b03e67e3c029efca4303cd9a9edcbfd858ce76fa2bbfd4996ccae1b9323800311bea1a15bf9dd6b2f470e50a9898f545fd4c9c11a31c2c0cd9622d95a114d61", "SERVER_OUTPUT": 0, "V": "04134432c350c51066fe42976c32578568cc5678e39324b82fc22266f61fab58671e7ec2345823d05d92a2a7e7f397f8c2da2b346ad6b07a5cccc1a1c4990c83de", "Y": "02542ab94834a3e9a2f1d1c9948f4b2b105be14f52d90b1f66a1933ae526414b", "X": "010b1c0162ed924605878e6ba7fcbe1a2a7bf82add37c12e83074779e0e97fb5", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 248, "UT": "04147ab0fea6f0258d883100e3bba7aa53a209737dab98e08291c967943a3a5715217536b419967d6db4c5f549a6aef574a1f672cd28e83993daee75efe75bef34", "MS2": "0953000aecc3618a0a7fd8dc8767e77645410bd0cc99a6f35b96e17575c362b3", "MS1": "0ccc99b80fe77dcb2fcc8a46fa24234dadc088777680b36e2e80f4f1864b51c8", "CLIENT_SECRET": "040a09526857fef668a4bd19dbc24f9d9a06a2d23098f831688fffb17243c1461c1b12d1437fb2d129e438204e30e2f2348fb17b74993db34e4175cbeee0c2dd42"}, {"SS1": "20e5205bfcfe59aa0065f8469681c17f8928687c49495aeff1a64c01e413801005fbcec6953965cfff564b900593d21f0c26beba48dd0516314ecf698255f54913f7fcd291b40c87d0f2603bf87b2f81f944ec528e20384a6826c5846bc440841478d48ecdf5f005f2cd8fea9161635c3248f7575f976b4c618fd769f5d15b7d", "SS2": "0ea82eadc8e7e5ca979325b737140d07c1e770573e9079f576b1dded6027a36713011d4461bdf504e6b33de253a8937f90043703d25c72e8efbeba85807457f722ac96496398da731bdc60ade5418ef286aaf381f16d4ce9c6208196c2eac24f23663865e7a5fbe576947eec2024509ed7045920d43649c59e5ba8ac13b7a655", "DATE": 16623, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "17dabf3e918b8437cbec8bf2ae6f4eb6dcfa50c522eae104f8aaf4ed9d292d461092c7c67099df721f6c04965969db69388c1b52e4c924c5ac874c224387d7ce087dedacc10f39eef4ff5160e72e30867256e4ed21dac8c7587b9d9d7ad7c04501cebd5711f43dc290940f1f9b959956ad02a8bc5df38a5a51a9fcc02b1dd1ed", "SEC": "040ea2bc737da52e3f49f423d959549fb79845f498dc462511f497bfd3a45ff3cc1dc0cdec6225efef71ff68ea97a12b61db809cb062b9a5ed2b61bd211e0e56de", "TP2": "04118ea31cc3d72d771899f187c1b61b09b9b00824ca1a5d631b0e5d6ee0d307e3051146395d51988cf7b7b46c66481eb71e6ae32a6598dac5ab19f2d1cc416241", "TP1": "041ad3bdbd19176a3c2e87cf3904ea14418ba2e64aba93b81dcd09cd297dcdad15150d1b59f5e60763226f1c02fea1392c2ec2936b2812458eebac6a7b1579fe49", "CS1": "04171662131f3dd6c4d10afbee66df0bece0615962ae89fbd3638fc96dbf3d1f1c02dbce1555c82379ec86991e9328b172cf31ab89ecf2dff3681a023bc4d1521e", "CS2": "0400358fe0b8e2f8c6a3871bb3b702c626013cb1da3339473edca74a730c96ca4c07d82b4094d84c862b2a3fb4be9f8023d5d0b00d87271c66a6624ff0f07da593", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04208d27d9deea0aa972bc6211341c7cc63f01016261f37dd6ca9f8f27602a629e12f3c5da7f0576c92188f3b3a0fd7d91d51ba66d3a6b8e8a31107b9fb304677b", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0411babb19a68d6d9e9e832b7bf8b8a0af8b514fdbc4a3b7310dcfe210ba0eb88b16a56fe9d244116e8349c3ca8f6da605590d023f2b175f189a6fc0d59edf63a3", "U": "041bafe2a92cd3e928c08d05dcc7d0a9b4e36c797768a36cc7f0c2848df310843f2313fc65200f44763266aa07ac7ead7abcd90de1e992e85d9a576f3312803262", "SERVER_OUTPUT": 0, "V": "041d5f2ec3ffa150f06c1af42ece85a0cc7d564c6687ecc322aa2ae7be578dbf942345ba76596025f61ff7bfaa3a97c3c05833485eddf66ca0ee933d2213d4a10f", "Y": "1a23d0725b7fa7c5977a66354593c2dc5b1e417d6869e60339310030927e41c3", "X": "1dcdad6bfb00a8a0ee2c6f97b01c28ccfae37208b43e0ce973eef1b04116e4b2", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 249, "UT": "041b51bc7e119a4118c2d5d314de1975666ad1440624a9af96d7cf55354d6367da13c937012388f61a283f1caa77609270aaf2565066040cc9400a61bdfc5e35b6", "MS2": "06e36386972a47d19812409fd6631296546339fc11149e2bbd0ce0b487ec7150", "MS1": "07d8f41f77e9e4d0f73324aea4e9d6df0c5280e8accdaa4ce1d30a7b24a3b621", "CLIENT_SECRET": "04082f6c4534b4316fc3974816ddc85f4587e3c82202b73d827f31f668e1f7202b000c608c1dc4dfcc8dc3ebdb0f5e7c48b3898790e0fb7fab67a056703158e4ed"}, {"SS1": "0515bb22f9bf19e76f232894007bcfcc3686033955ec541096c2e8c0ca8899841a3876400ca66e14052e8920f382d7a8d4d94db65716b9aebcaf7515d93fca7b0e3d665a78e8d4baba42fc6b9533a9cca594b9db707fb08fe34cdc45203c8964076c33c17fccf541ff94ad8c065f07493309614f00f50a91b88fb2802c4e7b92", "SS2": "198be276c46e70b9b285f25d636179bfffc07593a163ca267a0321a01e0ac7670a02e5a786c68e0848eb032592b3f3051a9cd490012499df90ab69add6edb49413816620617f44502ae4b76e9a303f41577998ec79ede89aba6866a66678f5b921881e06eb058bf3f360248b400e7a1aa3152bc95fcecf69d98fe8b98197d019", "DATE": 16624, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "023ada716d5b4f45d7bfc22d2e4d18a67f71ada3e0c0981b50e94907c6c8289c0eb0d0d2fc9fbc0b81371ea29a329ec375432496c0dfc218181dd48930d9a2a60891af05106a285f976e5506b3aeed2f7f394a09e6750ce8a7c607aaeb0765f30abcd93e3799eab716f3f8496bef2daa8bdcfce16da6eefcd5299a1a6caebf29", "SEC": "04239608d5e3e42bc01b9e147a6bd0f31e314c3868d035b21aac3121255db35a06026fab90951727a4376b4fd87e6df53b2b9a4a668447fca89ad5d0da11de12de", "TP2": "040134ca7be8317fd30824abc34f3b752296f28ff18eee3a9ccddfa6cdeec4fe5e186262ecbca5028d91ad33ca0be775d94ad8403efce60c8ea458e826e6768de6", "TP1": "040b1229562e129d28d78b580d2fd54bf551398fab1347598f0752d7c377186833165e0664b7ae9652fbd18475a52daa911ee16ba817d29074d31dfda3f9d79629", "CS1": "0418f4718b420a0369e61033ce3045dded201c83776bd8ae307fc1f437e595470b08f00bf6b318f117adc14fa10aaec27fdec03506d6ed9095bbcda78a398ec6b9", "CS2": "0423d3594dfbb06cc4a2c949d90bd7ace12f43d6fbcb0a46adcf23c7db102c381808975b7ae20c7b521e4f5d1977ed024cf33c2463e88fe25e24c08e6347aaf1a2", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "0404ab36d995914c3d7443b6137ad771c6cdcb4c52fbde79a9afe2e3b2294674c9211992fa762b34567043f1070079d0c0bbfad1215e364ab2723fb003d96a6d0e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "041a1c57adae6b7c1db81139bd2a3cae7fb84ba6d0fbf7bca91c9396526866b48914ea445b855c21c803697150822b9c4bf1d6611a11b5d9fa2a9fd87191305985", "U": "04102a6bc07e6c7c8221aa2f66b661ffff293fba977faee6e08f667120819a0e4321c548cca97b38dc6d2d10385c9a862644ded3fffbf45ecc74194a52aafd7178", "SERVER_OUTPUT": 0, "V": "04145d4967d74b2be02a2d890507c548db0184544c808a75e3e0473403b72daaef1c7cc97b4e0847b02c8cfc5ef6a8646fa36edee4bb7a1efaa2f98adcbf1ab513", "Y": "00aec19e3532d66bcf31718773ca26469c862fe2adaf9155b7df6bdaa1ccb214", "X": "1a782f81bd4067e5641e33b21d201db02ef55cd46e33cd1ce5ab50e3043db032", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 250, "UT": "0409f9456f900980e75fae81bd5663b512debc32c180e323656493a76e8cb89a0b1fe952fb9f3a84a7d5bc815fa399f486f5c4dc38d556db7b7ed000bea3b88699", "MS2": "1d58f919ea91a2b2ca913ef69863f99fc8efbcae62032ac3f307b5b7b3a33f81", "MS1": "191262421a5c92297155bdba02f9c210b7c62b0841751ca6d8608fc34cb1e68d", "CLIENT_SECRET": "040c4440791f4a1b543a9bf5296ef4c2575b1cbe156ca1eda5e67d3abe3c936b75078a9afb822f96d8aff225cd2bbd38d21ac366bf726525f1ae159962299b13d5"}, {"SS1": "1aa21e72d8f7c09c60eb22219176774665bfcc4e9b0e8d860fca679039001eb3097e2470bb93c1c62e9d05e55157545b3faa5cd8f12026d69d3b21288abbdfc70fd96fb85ef4de91d69396fbd81f0797a24d8d17a72d91ae79e1c7a790d2c81602fa9edfa0acc55e1b5728c725dcd5ceb5ad423a81d26b57906e63c49a64c5ec", "SS2": "0b8838696247a7c8cc7c064e93d44e7716718e22e73ed5183f3acd4dead15b3d07c3bebedb95be8b4f01835ca8e6ff1aab48c4450c708b94c374b61a1bf5e30a1e1f8f9be3b2bbc6927470aafc38425d183a4f30e8c271197f5a1bc9b8d9e0701092407848a3b6b45f6ff3b069a3acfc3e8a50feaaa0c56d4e4de9d664a3f755", "DATE": 16625, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1def8cc8bc982a28d29b00332ed8faa120c7e7c1ebffcc2e7224c15937c7889d209fdacfc4a61cc67863be9355db37d3f5fe13c96fb414251156b7404b85cf3f17bfc23ac2c9d8e9554d02ff73a748fc0a0aa06334c8852722bd93697db462ae193d5b203b94997209e1be75fcf9e707e92d7fc1b7c87846c44492f2cdb6d124", "SEC": "04054a067559d736548263c33cf276af004ab058d7d1927ae8dd1527e65f53c1291b5c6b2ecb8834801a906fa90567ac00670d7c75f50038f9cdddff3d403fac2e", "TP2": "0422a1a4a221b16428b14c21877da065a7750365dfa9786b357496dd883213b49505bf9c2094966cb323a1b00c353d3fa1ed542508e4c44b9d3c2623c09b12d397", "TP1": "0415531b2ccacab24e326844fd76c387207a94106dee60ce1d6176431d712ded2f2079e9f46884a4f060181bfb392e1ab72ecf98dfb1dc39b8398081b6881ffa14", "CS1": "040691e9a4c44d3ca89ba09a1bdc7aac8a9b0c1cd429c6c79cd56a4cab007e8d4f0c51a46f862bef2b7db2877f201afa68b0fce4fe1f4ac3f471f320141725420e", "CS2": "04165a3f4daea4a947e56468ad7960324000822a819ab35bab5c42ee8d7b0276b71b042a0eefeda3c582f1fd9f3f9ac432342c10eb37c239fadd55391fbebf1595", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040faf6102af2c3802782d497219a4cbc16483253239d77b4a714c7f6e20c33be31b7ea457b1bff41880eda6bda36036cf2a7671427367bd2c05176fea00d96e58", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "04124aef2613af167ec66679dbf8c6f91bf5f4f8a6dd7aa477b6ca27277ec4f0b7164f277c3c2f3d99844f969befd30013f4cd5e68bbc1ab65335278173584c2c2", "U": "041e19eb012632066890a4726149aac9912c12ede84ab3768370a1554a7a0e07f10dac659c57dec685104c6dffe7b3ee9c071dd0c1ad7414b0f4a709b7d2fd0bd2", "SERVER_OUTPUT": 0, "V": "040442ae1eade9be5d942c6cef98c417cf4b551c2159968e6e7f562eb74180245108a2b4587fe232fd033f9f9c7f133dfab690cf1d3d70ea1b4f9b5d0b6fe4a019", "Y": "0099564aab862139bdfa5ed6f57c0606d433a88056cc8d58474487896c77b1f4", "X": "01a5bacba47ea42d51fa2b1a015bced8bbaab94486247fdfaf3c1a2f514f715d", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 251, "UT": "04222682597e91c4f160b15df8313c365e652a75215ac4037b737ea275ee635bde14351124cc0dcbede1eff23dbb8b416d64101a346e598e07e84131214ce729fb", "MS2": "207506703c3b8d05f1df2ea35bb25c397b7cb43b70dbcb3b5f44e650483824e3", "MS1": "0b037232a57cb0221d9f3dacdcd64b8acf7fd5fa2333ed24c2afd6ee2b1788d5", "CLIENT_SECRET": "040b62769f50409c8a4f277fbb58bf7b58e4c77bced88afc99164d4e43c3b0ae19030a4f850af053aac5d32920ebae1b81cfc71956382dc8f77b430d8fe9df070b"}, {"SS1": "02324a7a8aab9d7d10ff899879c11675906d5e53c7dbb93385e90815227f08841b0fc08a0da35c4f7ac6ea4e9f730031945dec9f37c1b159560da4c30680aef90a0f0fdb06892eeed488d9f8a06b53736264903ec33bf9f8ab9cf8571b73e5bf22026fec5624658a993aecf8c65d4349adb5a58b17550f6a8197e77d0f81abf3", "SS2": "0ff9b5454fe7a6e792537d32a82b854c200aa9f1d0f2352811f54d59a888d518018f8cb6574045bcc50400a2f09a6ccf283b2e50cb44c989bd03b58f1d3494101ccc567f9f72f8f70a2720cf007a80fb1b7a45b7d14ba60739f924084ca85a001cf937cb0c42ba179703bda14f3446870006e3f3347ba8bec35d9125c7295b77", "DATE": 16626, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0101620b560b3f60506c930a817e23259fc37207bb33e8d1309aef966701e9210745d58aa5b0fcec2302fae536116a4bc277163af1152ea0e0a4e02f5b121fbe12e437224346cc8908db61fa91d26bc3692b5a14eae148a466620ef8e74b54ee0bdf079e6eb6d690dd673bf1822f985b91b02c30bb82db4c3f011fc9eac7fc59", "SEC": "0408d760e6db69faaeb42e2e8f590e2421acb75d72a1b20b1e6591a6b86f6da05c1f8606353f99f7f5d24d3d2d99e5516fc40649bc0603569de9ca26760220d9c8", "TP2": "040d670593290d5858aae76f98ce50abddf76b279954d742186e0329e0837ab40f1ecbc36db4d756f9ca2428dbc1fcd5dfd9948954fbe3ee9f40ca0dc16892c196", "TP1": "0400887d3998e8339e2e5dc7b3f446ffa212a6221fbd0707e0ec25f4f041b81f1f09721b52b865de5200d5f25b6672f00a0f5cffe1c1c993ba4c947db4d4d0055f", "CS1": "0417a051b05c798ca527981e7e592f6c6f3698de534e2a2ddacf0530fa3d2b71a8053f7f1f89379b6e3339f5bfddfb143b9f98eb8ad7e09e8472941d52d6df0ea1", "CS2": "040433504699e2dc47044f23154c9762208f2759b6e7c0665511d2340b5fe87159036da8c4f43874a5fc242894310897254d917a7d1cd5c5507f8253d9cd395799", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04153e0ac9e2803d0b4a42e17761dfc9cb800cc71c0f3ddf9c999d89f52b863f8314858fb2cf1bef0818a4bad28117b47cb5c3dec7ab59f6df05bb14814c55a492", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0418b2a47d09581ec7ed0d1bdaa8cbc8fd2bd6ff8e1b0674f7546c521cc6f507261d079805af9e7ae4b883c4292e3b5217837bdb5cda6897915348b741271b7c7c", "U": "041a0c7025c0064536fed86c4c835bda7482267dad558338a5e5907805241233bd0c11f2d86cb5ba2d77be82b6548c935893c29932e4103e0d17180cc886044516", "SERVER_OUTPUT": 0, "V": "040ffb527d73adf383abe24e40fb3fd729ff7c2718feaea8b23e28aa3d8b03dde701e943d6de134b8c2d6bbaad5964fedd5cb535091cd23f15a289bd054068b9cb", "Y": "051e8485c2bca5882607e9b0b2e2a6285b07b42905c99cc0b5b8e2c90f10e239", "X": "11852bb69fa263cd11d534fa36e2437f4330489043d6690c2a9a3017b4833c26", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 252, "UT": "040d8b6076646fa9fc2e7695d66f8b21ac6d7e1727e00c64ff3c5b19dd85678b5c1f6e11b098336c80432acbc0793b423e9c34d104e4cb04c86960c92ccfba28f0", "MS2": "14b0a73671bc222636c893d02beaaa9f51b8111d07df1c6a5bf6b95010ca8e6c", "MS1": "0130c009b050d38f4bac637ad3dae345d4299166d66b5e89ff8db66bf760417a", "CLIENT_SECRET": "040ddf304f3ef2450bb6f284e3888315deaf058e1a387eabe88d3208fd788adc95187efc15bc4670c1bec20ad25adb5878c0936c567700a4da994da4ac17180cd8"}, {"SS1": "05105fc21e8c4b6c4dd78c6bf3b8146e5c014b3e26dc9c656ed2b010c50e7baf02f9f834f5f853d1d637c13acf5d122376f6857563079ec776f71890cec736c319c3311e5534c9a7b79b4b80f2a127e3fcb9e4d808f3601959359219fa8f822c061df1ca8e8a33326eca379d72835b0c37a8b779747f916890471e405adc0c0d", "SS2": "1c8a4209b8c98ec473c3b7b5b8e6f5a046f8a1c10edc613a8072908d4d365e8e1c3f2cc562bbedd216f1ebfeec21f632b2e36431f7ac8205eaaaf0c261c9b51817ed2968beaa1965405acf2581c9d8525e732c102e1e6b33e75364bbc492dfa822cb472f9c4b12b92d61cd0c30c7f894513d24ccdfeffbc671b39ceae0d6f5fb", "DATE": 16627, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1b8dc253e73b4aac42285a0b78b9ad4a67cd475251fd498b8e4a48f8745c355e0fae96314e382994b88adf083bc98f90bec9642ce6ee9a818895b06dbbd3df0d010c086b7e4babcf40cb0bcfabc8b9efcd36de7dfffe0af0ecb7f1d4be1f411a1f90211381d70b8e6a15c3f601f5d9e7b754381c4b617e052b27c1679886bd20", "SEC": "041640249e241513d7b23c22cbd245fffc57b27671206385f52ebbaeec23fc1cfe00764976ebabe4ec121ba237ec376a36d45c1854c35c2bf8abb9ec9a08072ff0", "TP2": "04238b5235518029fe79ce35e0180ff7410acad5d2c6d8b7fb6e40f030ab9d48be1f0d699a8ca8d67df1ad035b9bad8b099d39cfdbfd81ed7e9f0347744ad4c189", "TP1": "041425e3dfb7b3d11e6686ea123ec6f62d6e8cc9ab698c585ef75c78d9ef56f250208c28e2b4250182477ab8226888102699992a3d4a0f072db5cc03a0d3ea1f69", "CS1": "040e2007eb16cd99aa495ab8830dee8ed7700d026d2944d114847cf570d7adcaae19f5b72e58917e808abf1a64fca23b358094fc3b49710d43c9b177dad6f25ea6", "CS2": "040a668c0ef2aa003103236351ff3ad1fca6905141ad90103f386c5b41b453fade17b83731ff74a0614df9273fb0fb226dbf235f41506bd9112f73e8894498695c", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "0413592b5b5d5d22f44f21f3d739c5c93d6a6c251225167dfe299d085f5102bfe8149fd64cb2ab52968d86a6c08761f37091d17c0c8c60aa34335a6a577cea4dac", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "040999d8ec1336a1aa088ac1fdc40d8acf9f3b41626db1b810a4bf3355fb66787b1292b1cb9343202d1ecf21e02e229b65c0edbd9857baf0744ec347236223fe46", "U": "040d3537cb460adc2afbd51077810b9cbb803a9887f29c18b559bfb5c06b23eb8b0f75dbb7345dbf560d7102059438cd0b9de7d3067d69e8be5c8a4bf7b31934bb", "SERVER_OUTPUT": 0, "V": "0408d9732675386d0f969e85d5dc147a7fc17e5855b792f4de7531db7f56362ecd1d5664438d82d06d24c1cd41e074550e726554337235a9d291a014067a3fa3ba", "Y": "0300f5e171f0a7db7e2e47dce5f3bc5ab09cf09366abf4b1f1c47566e8ccac13", "X": "22dfc63fd6718ff625a97589af9d75d7f51e229cdc8266ac0418398f35199618", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 253, "UT": "0421820e66ed6f77b4283fc863d4453168178335d2a453f33e3fb41ae996377ecb0eb296a64c75ae9ee99b313d5745b0f025020d5e3e80c6919729c5c011032128", "MS2": "0fba02ea55742e7f3f4c77e227c01bb3d3f660a365b9f74a1168c7a7a17f4949", "MS1": "0ae3593dccf6a4585a699494bf023f12c1c85ccaa4774d6d25d44497605f782e", "CLIENT_SECRET": "0403759f00439445734555a594a9a27e884514e233483207a5b54527f538b7bcd20d78be80406acf205c938899be1dd2dbe9b82474ec234dd40e7e18e206fe49fd"}, {"SS1": "0a1b1c1f198f3932ad89e41ea662a34c7b2cb3f099ba4a04e5e12e0f284fb0000ebf2fa2a59763947057d7008447a4e78184933621e7c127c6a253ea8dc6547c1eee905d68af218975297b5c7943862e0cd996baab07854b6e00918d7c84938909d3ffe752cc482c6b8e424b4fe167277527f288f5043dc52a0a705c9c8cdf37", "SS2": "006e1467a1a21d8ad257427b2b1e56a351fd16c7d2636df1d5fd3319634abc0e1c3271626126ac00ccaf6ca07291c58f2f95ede6e70ecb92f7e868bb19400f6701a119cd8876834a2755cdd93396130c7e8674b41668e3551b52993513fdb258147564aa373521563159e48e1cf738ff4d88d50fd6f954945046b922c8245acf", "DATE": 16628, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "05f47d8b3793264f7ef3618e42480ab0143db23638b0f17299c2d1b6f892d1c701d286b8308ea60586d90193706936fdb2667e3665cde0acef6b734a365ca5df1e839f951a2dfd40a1ede26f3789383b6950ef029efc24aab93f76ef874b9d6c037fc29008ca9c59d3947b8a4ef8c4aa21a9d93d2c8ba6842fca75c81ac5816b", "SEC": "040abffcd51f33981019e9e2ead70ba5a847a826a9fac5f1a7dd6b3681e008d85522f39af40b4b15a7afc9c72a18b5f3181f3feaa6fbcbdc5514c7d39bdbaa83c0", "TP2": "040e94453a48161ca32f9c3081c09601708b555c9633c207476204d13fafafc64511a756947a62d13c6a713fc4a2c03bd8f3bb8e803015ad28d946e6c30fc767ad", "TP1": "041ad15370d10d79e570465d34dc4ecd2b56f06c3da45ea5f0e4524c4c1ca0d4bd0eee4fff71503ee2159b5b56dd55ba8b18f98a2dadefe5d8756884d6165df308", "CS1": "0407d02d2cd1cf1f52f33dec473936ede641216d7d1b54db0431f1ae3f6680439f1f5800d4013b152611a90a5c5955c18920bf6025b9f685b9efd58992cfcf4673", "CS2": "0404fadab765cf35659abeac35160f00d86fabe153a81fa44dbeb52e2b5f9ab442184c22f27999c0cbd1a66138fa59f83bd73956546ec5bdd2e7d16226d6b456b4", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040f2be9f3218c33401db5fe9bdded4f3604c947548d1c1c1cc945e0e7e6b9363710a9e2aeec245946a8a434e21bdf87f894cb7e4759cf48c8934469d105cecd09", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "041739dbc7b3c2c8a9f4ed0a24d1e08b032191cb6d378c03526b58e07ea179f0d21cd0ae46866b675d1db9a81893615161c82b6ac44884e8e91a04c638b3d44d45", "U": "0401a8bef03d9e0642361110a62c53c00d9c86c372910c130da8e1211e37dfa9f905fc5628642d3a6975744f633f3daeb14b21bc2c7a3533707a0d2a0fd1eacbf6", "SERVER_OUTPUT": 0, "V": "040b064b05258aa7d4b2e0447f41e8071ddcd356c69964f8e7bf014940e2108a0b1c5b1f9eadd60b0d46b12b0da0e23cc641e4246161f7828faea5ff86231d39a0", "Y": "1552a74f265ee667d4a720541ac5e5798a51c915ab0ac4223b834179fcd000fb", "X": "14e30a6f6372119afe6e0f4b97da87ab6c7cde4803e02da431b7d34697c77bf9", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 254, "UT": "040e019b5dc7a8aa777eab6a1f5b91bbbe7ecdbd431a6bc6cef7e18ddbe5de039616756f82601d219f1dd8393b932e26feea02ad336501bce719b0c567e9278d87", "MS2": "15d62050e56c2ff2ddc4534e7462f63ef98e2d5c2f532511e54e2e124864373e", "MS1": "1dd95593d925c547a81efdb0d97d9178217fd98cf77c5e7e4b9f46830df8713c", "CLIENT_SECRET": "041102ab26bb80a13d49f32bb053c90d7103227430509185dd66c40301607f5e330f8263f6bf9003c357bf29b91d3e7d267898161e3a121cdfee3ac5ca90ae3df4"}, {"SS1": "1ae2c9e566cfc7cae2f8e070215bc0ee660eee4d28d28dc99cf11fe0656b4ef41bf7b5fa42e292567bd0b891bb24f8d947d91e4aee090902c5b98424cad6bc0e00d3b5157d5005244dacb8a1f94cc56f38e555876eb589537bef32175d1c5c0c2353f4ea4432cb55e4f7b2784c68aabf17b3989007fe7de3b7795ed24e8d57a5", "SS2": "160857abe88626bdfd2e08407f06cc806896cba969d70b213ccc65efbe1b1b191bd0376c69aa7081b291afa63a5666ea721edf3d39f0d84be5b486c592d79d8907412351f0968f074692759de37ba1e53b2917d37ca5d60d608d7726982f3b9907cc5ec4fdde1fe8943e291d8a222fc79e571d2726c2c001bf7cc14e8b5b6b1b", "DATE": 16629, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1853217d1d092814000469da1b26df1a9291471106fcc6cb72c2f09582cde2ea0b01a7017b38288be8b12023311c69dcfb962442746cc866497ab7e1e5756a8f034439f3f316e6e84bca2ff3712c03ca89ba569758e234469ac67b97e2e0d9e70d190ab1611c90ccb7bc7dff60092773670cd877188764dca94a083b9820325a", "SEC": "04095bdbdfae61ad23be0ce74a1bd1dac9e48167218a25cd5597ccc085730b680215942da6353d6e919ddaac27d07deed646358505544ac403eaa6a187d723ea75", "TP2": "0409b247dcd1e7c4418e371ff3ca2095aa9dbf99a45978731dcd85559f4a05bdf71e21534b1737c448f5f1a29e13a3c8cc68bd8adc4924cb002d2da7955b31d74f", "TP1": "0416a44c85d77cec54e462154bee39168cf7843a5f2fc729e4788ac80d57a3133f1c0a626ef562e7eac6182582e85bbd0de0c1a7d17ac7c392c86100b792f7c0a4", "CS1": "041e33c89dcec7ce5fe86552024defef8be7b487cc98d24a9985e039e54af63545226096efc09569143dc7ee1d042c04e6efaf9ee04b9d2acfd8efa3084f1b1c0f", "CS2": "041067c4425d30d20a7c1ef75718adbc8ff2043155b06995319d18153455aa38c106d03e3fb0fd38387c1f9a51c20b06ed3b7e1482a4fe4830b3efb6a70fb3ffed", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041bafc18e786eea7834ae4aa29f54d884a815019af869587f49cc8dd4da8b3da111491517b997eaeb4c5b3aff1b823a1586867ec8b59f4d570a23fdfeea0c9579", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "040678968d11a7de41692dfee7b1a478ce3f1cb995d5dbdc755444a3c58a7100781d7fd70e788513ec96d531132d1bc27af2373eb739018886c471d979f980f58a", "U": "040cf529942d7c6cb24cc883a3432dad1210cf4a25bf565982691ef43db0c8c9fd19990e1b45795dfe2915b7ea62f9c5b8de892689ae59de1b50c45f6fd9b39ad4", "SERVER_OUTPUT": 0, "V": "04118890edb8156467fb3a88b6889e22017238ab774b9bd3eda04b9837165cdc4f0b48d22a55932b2312b43fc1c80edecc8374ee6e5fff3b9d4b343036fb22f56b", "Y": "017c58072788d0203f6188fea6deca7b4e26fd08d65cdfc14f272af8720b3b31", "X": "07ddff094fe5196db97988936e7f0f84e55b5e3a0d2236290081b2bdde97b3f7", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 255, "UT": "041d54f4e914f1e60e5d2d88efb232c21e4d2e1588e7da405a4544524cd91500e11a6e623c01e1df8759080f924ed838fae3aed0c9c52bb529e2df9af02c3f1346", "MS2": "15f4d657eaa05ba72c617ed88312fb35f26f84ad34c7e418c1be3979ecf5edea", "MS1": "0029781829329d0c574c1c386713f752e06837d74d5755d7e15944b9132df58a", "CLIENT_SECRET": "041326f8c90835ae3893f8ea0a48b747c238376788939caf962b3d54fad99fdd56218da31fe1e3542bf0864f70a2b9d835de02632fbdaa612ff95018d5f85c2dda"}, {"SS1": "132bb880a45cfdad789bca411a8decb5e9349f71b3eed433641118f1353b30d50ec0fe4ef44b886982f65eafd97196ad64d943f24b113366f34ef0f19fd0c0a50c49759b7d36c043d351493de380cc33bc23e18dcd8b55c28cff4116381bdce817738761a897fe3cc411c824b1495f43faa30fbe5107bf60e7dc9aa31e9ce3c0", "SS2": "16595d4bdf299f3d196ba0f79198760259fd56c33f9eb6f4d4288b5092a2967a1c1b908997991d04f69bcac6f1ec1c716517714f9a9f1c3c7a7dcc2ecd8648950e50c9d861560928be1191bdade47653967ba29cca237043c343ce335bf6e46018eaac50234d860fdf16fbc509ec127af8d8e172d686bfd1e262feb1840e38a9", "DATE": 16630, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "069690a742621497e2918a0f927a9d2142810299fc3ddcc89c90b41817bd9ed81b70961503e175c3ebd0ff9b42257cd19b29d7f0d998cd061709e4065f2fba921f8c8d657f7f18667ddfc66b2ee191a3d2d3134c0b7aaab38018e75e43f208da0ff429994548c3eb34ac46371fd901c936e237f8fbe9f4f9ad55773305f8f00f", "SEC": "0413eebb5ab22779585b0a959947c27348d9d62e8f5d4172bb9d1d06a4e444ed521e4140c467542537738db63450d8fdf751fb79585ffcf75f43b7b48823b73c98", "TP2": "041f838a53135725a7e63f853162f4425928d325b37dc38e33eb08899b6022d52704f8f8569f70814b62b6a7a241c88b675950ca674c20361bcb71ab2eab18e7ca", "TP1": "0404fa4d33f9111c84083d9668cd58b1364951ee0af1498d6213e1f1c68662a4fe0ab6f455c9f2f8a10a80a26208545365c9a755ecb65f6b593d27b6b3ad7ae613", "CS1": "040434b74f0dc9dd5aec4eb0e6c18bbe983d01dcc58c107c60075dc98bcfa5ccd9075be83057da678167dbb87f2429d6db0f4609e08f10e940cc5f879e129d5702", "CS2": "0419c7db554c7ea9e15236d487f78e34ad94210b1137060e79c7faeafe06350c3500ef68c19b9688902dc9dc4aa6c01913dec952d259f916480b382cfeb9238c49", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040e872658e40f97c37ffd3982435385aa549bc71e5e54eea505c2da591249c50516d651ea6c166befc3402f2aa77591b978380dd9dddb13316540512aef8e20da", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0423e7f869be4596717ab90594e379385067ea6150070735292e035aac522a48ec19d5a41401dd8d090838de13ef2d6246f9466e8dcdcc597ae198e983caca8f42", "U": "04051e9cb1ab30f620a80871285b15ff51c795f27d2ac91f8b4a58e3800fe47c2e0dc0e95eb39ae790f682fc95e3bab9e829b170ea06001fd9a6780e2acb25547a", "SERVER_OUTPUT": 0, "V": "040fbc0cdf4068768b9f5b0ea5f64f39bb91ab8d7e6aa2680f3e6ac3cd0a55878d07b1cfa8a4677bcb334385f9ed62eeee48e1552866080c9c9624feca29f3d01a", "Y": "14d523a6208f47209f849c2a47d58aa421f45016f37de302b4f61b22c623a34b", "X": "08890153db44e548684e61783a61ca2f601e6b32e71143e0977473566a781257", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 256, "UT": "041bd144792020ea81fa7643d0bbd2ba13089d2411e10043473c94dffd013a72870b1244f07538c91b874b65fc593992e5f10025a3f0c6edfd93c97ca27d11bb2b", "MS2": "00c3fb4316d5dec99b7e5d96ce30fa9a857fb345da4ba57dc8cf358ef7a523a4", "MS1": "1950bce160d212614a172c0879bf034ca2dd43a929e1fedfd1c6626e4b3a369e", "CLIENT_SECRET": "040456ad6c927817e1bc62f3269b7e15717317e3f175fa0bb35195a07905bfd3520b5e5faa040a6169ea30381552ed11382e0be1617c4b82ca869d37a054b97441"}, {"SS1": "1bcb5ab7a64bae1f63aa80c0d59416dfde8115d8be034cdcecba84d40b4efda80d2ff12c37d9ad0cbb5e530c704448bd642f1cf2b6678fec7cb819d42fa126f7231cc897019abb9c65af9934600544e6cc811fa7162275bed8d70ea8085c2b6b199ccf446d9ff417c23c2593aea379a8eab2754cb67babaa507ba1891913e27e", "SS2": "1cd9fd33c7894af0810bab963a405838f95e0908bf47b41c1b932459aba2e00c160b7f682cd95e1f41df5cdec0a6ebc7d76b44e5e6ca037969927b40bfc613920952d00e0c6275ff98d0aafd9d29c4cc06f90a94c2bb88888c4586c85ae40a170e9c3a317069a4476e3d9f40306aad44ce1829f27b4e7124fccbb06ece4fd6d9", "DATE": 16631, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0f9898a0d4167dba72a78ca8ce24a6c313f53ca0f5cac18c49582419e95ec07102fec6ed7e95485a49ffe329bbccb7cf25d323425ec5e038a7e2f36318e99860232091468fc3c60e2f213b9e5791214d4528ec48fac20de84318d01e9abdc19318fafb3c7c4cc5763bec6ac8a360b7b7fb79a3601202252eb1a0d3fc72d22b1b", "SEC": "0410bcaf48bcdca17e935ad42a1a2416373ba63165dc45e80edec43272b233118f0de7128dd5600b0e95939ee0f7d873a999e7c5527ea35d34d06225801b4c12f1", "TP2": "04010648b3e1a3f344529e4eae3e7780f7ab416b6b41b601304fad0d68c4a2179700cd4de9aed842f527c01637019dc1627733fb4dacb0ad37f7140ff4aff4e9e7", "TP1": "040fc9cbc082e19d4ede9d2325b71f8c0b6ceaf06f850d94298842380f35943c4618659f65bb05b8ba5526a0ae0a5d4bf66033b308245ebefcfd0acea1e0b9613d", "CS1": "0412d8e08d6d60260f20faa004f3af1d8c3a7a5b13961ae7a41463630ffe90231b13d01875f9a42426313798ae7fe5829b0049dd2a1ff0fa5b179fb10d861fc5aa", "CS2": "0410425241c3f45e8af088cfafd614d4d8c41031aec5bc4a8a4ebece7ff0756d5f1e4ffa24d5d4759341c14001ebb5ab1d059e83bc56d8472c383116b2e25f320f", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041ec22eec00f388e181855e23eb17ffa4238598e146f2c5d5d2102feb331962fe0c8de3f529d9fcaf42d952ac1d415105268cab18482c33cab25c8c3dd56b3107", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0406f6ab99f9309375e529d90fd8dbcf0e7c0d2043487e7ca4357cff5be00f8b421b8b162921bb1eea389ccd2c8a0e8351db75a937a735f5f9c484f251cc783dd8", "U": "04108ceb88ebd584afff9e2851e728f109d6def827c4f7c735acf8971b2757786b15e7dece7e879b42255c449702bbf1001a8730652d8f78459b72ab35c3459556", "SERVER_OUTPUT": 0, "V": "040464bb308d6ed7a87b2601fc3e4f53387a87c7e9d6c6c5bc4106f5c7b9fa387d0606b26db492493afca928cb7056773d262daa90c6d7391c3a7cac938cad3d00", "Y": "1f35ed19bdd86d317022143ca3cd5f787b8df0cac1516f50b20af9fee751d955", "X": "175463828c1df019a85d436b1f085e0bc69e90019fc84f30d7299ddab3f5bb74", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 257, "UT": "041e448d2b56dbe8095df0965de5d779d43bd28e072c65678dae03535578c948bd08f82b77f51f753ba9f3d62933897dce01f281ba9cb5413b2251a11cca0106b2", "MS2": "1e9aa33115f873a3cef1356ae2ceb61aff69aa602a818f7b7d6de101b8feafce", "MS1": "03568beae5b3d7a80c4d40b3ec4d988342cb9f04342997809dc9472ab5f4a38e", "CLIENT_SECRET": "04207f45e3dcb3f92b1d66f3633eb6bc50c83e7142b9a31a656f3b148df19b4b6322cf40abc6f38e68763e6124f65daaf3f5d1833263b897c768fa57016cae1790"}, {"SS1": "189d7e2c184c6724ee1903066457440c2f8d54d7698b55381a9dfbe4a3a3700108d8b3a23b9b906742bce4011ff00c58377370590b35d6eedf43ec62e8be9eca2219f23c9cb0f6219cc055e52773cc61591f0e7faf8d0af3e7e0afdbbd8276660e82b425da160a8d59fbeaa2480258fe0d24d82e39ad90c2fe45a234a6a17bda", "SS2": "053b5a0aea3a0052c9101a41ca25cf633b4f0b0c5a16c749f5daa71fd72777df1ca690e2fba0af499ccef0bbb99629c4b84750eee8667fa6fb318692df7c80b61ad6bd8060be217c74ad1ea06886d6f7782e9ebd2054243346756a6ca8356c2c0ad86869932c4f87f20b4a86f45699a7faa85584ec608588156cb98723595810", "DATE": 16632, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1e193f24c9607072e3ff686fb88035910157b775d8cf18237df82acbcb42377002fb51984fda23dc24d119c1248f3a70bd497c031d468a600b772bb82a1a6d4322b8f045897b21421c5d12aada201b40877b1961dd233354f6f911bf49bed96f0404fa5351f75a8035301ac6ce00e5a9a39fa3a94cb8cfa94cf6dc2ddc15ee20", "SEC": "0423d61641449fa2bd74c9d7433796fa174f10ffe38c68f3c6f7ea0697c7ef519013b34b7837b13f0d2f992ba39b9598ce4eabd9962098eb002cd01c77a72767d8", "TP2": "0406249fe3df06f6d01fd56cd815a57f6e4c787a9a5971257648384170c968b63e0508019555d97429907eb6a687cbf0357048f02c1337a478f99cf2c2f247191a", "TP1": "0401a5be8242a2a0d7478c87c57c2296c04a8283c486a20829b9a1f320ab25e87311d55c387315b1c0e2abc38ff644726024e378d042d40eadbb71fdd4b04f94b5", "CS1": "04024b67e88fe5afa23b511df130ba02303058f335a470535b8e76cc4842c7cc050390f47a5f491a50dc6d835be11dc3610f7039867e80b4a9406c3d15d61a9343", "CS2": "0414847fe1e4e10c0b887328ac26e837eb27adf356f90feb50afb2390d4569c2b61b37e47e4480ff8d120c96058b711fc22fea1c7875ccaa3db1fef6206ff798ec", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04182cee117d2b5c30c71cfaa712ec2e12f9993197b6eee5bd93ad0e302860f1db226da67ee9ff490dbd0076310c4969706150f3609607a89c2d53327c4f706b53", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0421800717d0fc0cdc34c4c54471aa165349924cb3ab06e3cc922fbea777c795d805faf5aca39189e09710a43b8087b26d1fd57d414c69561f867beae3a138dd8c", "U": "0404971764878c1ed16c4d976a325f42c300d77399a24c7322db64cf6c934bb0e20e5b0c3721115fcabedb1f6f3681f8a83ed770f699c1f0ad744b45946c24f1b7", "SERVER_OUTPUT": 0, "V": "041264e9a447598424cfa75c7e4577a573fcf2960919aa4960079001eefa12318e0fdbe51e83badc1213f8dfacd7d7ca266ee48f30fe6775ef68b3e65885a4a09f", "Y": "1d5392bf78f82b96a9513f806411fdfc0bc85ecc96efea3207448a68308569a2", "X": "1b33cd163957cc982b847cac03de0867a52e5018a73cc6a8ad7c63cad4b6265f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 258, "UT": "04189b40968e44fd5bfe60be9e97332adadf3a2a195ca4f4c60d45456f74d3873e15409d9184c50d35295b40415558cdad8604b15669e3d0f7ed815e580507c36d", "MS2": "0c2a250ab02bf42d2ab08fbc0a040904bac2028fcbb23c5af2fab211a1d2da99", "MS1": "025b5c7a46315531b530fce15cfec1644cb7ff222f20efe199550b637caf1553", "CLIENT_SECRET": "040fc8d32cc079f4f14788e77a2aec7d008d29e5f8f4261ca00cf0fe42c7f585411daeeeb01421a3de9ea65dc50ca90e8e11bd86dc1b116ae61f4b30f7711e0b67"}, {"SS1": "12a726e720fe4b074c43b151039789a63a53147a89d3de02cae5644d4f2e93bb0e8972c4f093b0d469565228899712ecee29ff95346361269261a35b92812d0606383bcd28b9dab4188977bda03bf5a6f3775ea6c1889cdf7de09d20478b09e417d9021722037ab4aa788a4d559a7bff32f8385f49179f240c61f3e7c5497384", "SS2": "046b7bab33a81bde59fc540acd39c7f06d9a221ba5d42282eb289fbcf1ec122d1764a71381cff46e8c764eaadecb7d31dc1f55e5d1f4cae46d609ea60525a8061d901b22e185d594756066a001528fb3a2d1078fbd22cf1987127d4a8a9d0e3f09bb6e5fe6b4559270d993deb10c21085b6e57affe9bef8d2fc3f7d6e3616abc", "DATE": 16633, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "223cc9919fb31d19f062255eb30a4acaac3035006ff17e2779a518c3bd46833c16593c6bab2f251cb41e38f3312a89d552ee31c8d4c96b62d34eae3b7d67098916f5b214a5ae82ff5e28a09de052ab1deb51edbf44bea398f89382965c26703418d469dbc52b7ce89bc9e74f2565d4d33ccd336284c0b12588af164742e588d4", "SEC": "0408d7a4e19bb0ee49c7bf9f02905d22908968455f5d1649556be8ca8eaeaa0d032274daa0e384a3f24960500332361b83ab891551c65d43cd88f418fe4751ce1e", "TP2": "0404ca09cc804c4e93ed4f4e499ad3efdfb00fb4c776441a9c5de911ec9cd147470aa120ad6f7b7943cbae434e2dfcb8965383df5d94484fb5eb98f61ff3c1db0e", "TP1": "04048c05f85c64a5380280be90f7abc3f5779893a8286dae06371a59ed6400cdc30e1d4ed78d9f362e8a3161d977951346a9b5ca3c19ad3e1da437abc729c70305", "CS1": "04163c9418c6d1f034faf91b751e83796fc41579e7297806b1eb59f9526f81e45704c2649dd8f024b87adf32fa1f476fec1dd64e83aea6ea97f044c8ba0e10cdcb", "CS2": "0409cd9085fdbbe7152d7cce62b97c3d9748ed36b40e599d319809a97a008373031c45f6c1adf2a77cb9e3ab753e57680bcc5b4c9943b18db07f30c2b03a44d331", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041b1050173f98c0c6f6fa7d49e20563d4f5bee1357426db86d53c1a75c63a4d4413b2b7af779755015c32b9af40972a2fffb2d5cdef51ac0b4e482a3561877f35", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "041917cd9714a85e46565b3b92c0f83a79d20791f4d5a8a4fcc7670896da8243a302b8c65ef0e9d615dac0c267a03779fc4617f2fb5d514c2937f770984375190c", "U": "040f5742a23d4651736945b6ddca0c74dc57c55dec100d08a7f5db6011e8fa01f20aa1c192d4fbf0f79e46c0b9361a848537cae42071167e178519e1c3a9a7cb19", "SERVER_OUTPUT": 0, "V": "04166cc80c553a527052fcea3bcaf02d200e545b4653eaea2159f160d3f21e40be1a5b5a775ae474fe742c81a67b64a600080d4d2acf2646b653a2e4b205b2eab9", "Y": "003f6f0a547785e232da2ed233ddc94826b0cd2cf6cdf3974d9a2022784fa6b7", "X": "1f14751b03c1460aad03bc9303a6f0964ef78c3ae0bee69e871457e7bcf3ecc1", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 259, "UT": "0409d6214d580086bb7a129f2385aadfeb53d6cc90bbed9503ae6e00619bafbab81b023a124148864a1d9d41bebde775b6a352a4b8ec49c220894360729d9ce8a5", "MS2": "19bbeac61d22100c3a16107cc1cd726f8d45faaf212807dd3768e944e61096bb", "MS1": "036a16353d979cf113939bd97e6356a07735e7d898222b0c8ef5aac40cd867b3", "CLIENT_SECRET": "040e6266723895facd4f2d851acdc06b39d4d8a04dc074dc3c927fbf837ba58092055160b03adca2e6908ac2180f7b30ece80f68dc296af3bc12468845837874a7"}, {"SS1": "02bdfc51abebae8ca7fd18716f2390473b67ea03cbe62cbc53d847dbba84fec303327a54b7d078e25cc5984dac6ba0f848d604444e912b8b33fd1cbea1e016650ae0a106a3fe9225621650ae96d7564ab7b666bf648b905822597776d83b4e7f049ee0812d0bb3e3ea9cbdef4cd9c6cdc97583b7f7fe52408131be687855f42d", "SS2": "15d7811061cfdfe99fe43b3868775c05d32fdd07e0312c8073ecb2853bb2fc5212dd34f82565483239784ca63533db45878be035fef7143fa5c289e39a5d4ecb2160228c4c4aacc8d93db75966f0ef86889aedad1c67ff574744ba2575c9595206663d6dfc1b16ea21e59478b8e32c76e9b791e2557a7ecd438e1988e3dba117", "DATE": 16634, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "18abebc3360d0c182b1b612337efb406f4746b69a8a9a744e3c865c0610aaf0c1d7f6d7073a3a9318ced3fd7a854301b8a244a46db41ac9b05cce0ba04f81d8b2092789040cfa137e3ff6b3905f2d4cfa7506769f32a2857c45e46e2f1171a281f65e001e342a60085595bfaaeb6c7e3c3ee9d794169a5ed7fbea64219eb3597", "SEC": "040233516c1f5e37893df54ddbd244d5fc60cf02d74328c70ccdd35bf0481df4a411f0ac845d06aa61aeccd8c690bfa3d96f53a91d6af4eb7cf1307ede7ae2485b", "TP2": "0402f534f6995380c939bb4dfc4286c6cce1e07bf41f35ce0b7d82e115f4a471be11a944ee5d7867fae5f012a8b6064842742d94099242dd593895a65fade5d8f4", "TP1": "042012329dc8176383df916a74f17fcd1b013a18cbf87e0eb67f26422a4fa6a9fd0a35ef2bd8fa9b98a95098306feb7e9e1a46b791403a92e706cb4022ae814cc8", "CS1": "041889011c5110c952b33d3009f25fd88315c442ffd9a45d6c6afc46474fba692c0a6172acdcc67ce51f4db785016075a90bc342332d9690e43bed4ff8dc486afd", "CS2": "040b8e69bc1b4c227e7e6d5a23a2fc8e71c34f19aa388cc547ab0ead673ab308fa110bd38dfbebd2196a2b0778d711242d7b6ab379f091494fd93d760c1dca51c1", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "0409e51966af412a7c4f7ff203ebc8777e46e3947f068f52721ec6e271b7a9e0e0122565942710fa01684f011c199780113ae96c85b2eab0514a2905182d9cf2aa", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "04228bb53dd7a4ca424df72f4e8b85c6965baf7ef3954e9f4356217855ae35c13e0a5c8d5b2bdde74fc28600a36f464329eb03e006ebd5a977ea85f2bd85bdc76a", "U": "0406c38e31c93cc7494e07b02240ccfb407d752f9563ad5b5b7f748ccb82500d460b022f47e028c1207c67e21052de715ce3883938ec5bf9f9d677481e8225bc40", "SERVER_OUTPUT": 0, "V": "0421c6fca8efb3366f1e30e229f09874f064fa77918750ed8754ef421cb95f2749232a89ee50d650a9bc9cf9339aa1352575f7003f88eea25314186183a8ea0097", "Y": "03addf04e6ebcb3ac9cd1c2a977e29c25b65f772843d20a38a872187020ac215", "X": "19a0f4a47750e6740e96a3fc6711039d71ed36edc8ce4436857988001e95e6fc", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 260, "UT": "040e4ccfb08aad03b4f66a47806331bfecb6424ac237344cb86374325b8a0109f70244367044109beb85f68f1f20bc0d6cc041e2ecf079f212477363be6070890d", "MS2": "0b9a0d21ac377377d25252b3d4ea7d49d36e6f0397907ea02489fec661a56c59", "MS1": "00a8503e8dd53010a285e1b4f3ce86d8a50f56aff34039e0d13223213be83771", "CLIENT_SECRET": "0410cb352dfb20b4f36171e9dbf5646067d39fd40c7aad6f1d683e648487ca542218cddc2230987be412754a4d2fcc1d01e7a9c4781bcbb3dfeba284b7bb86c59f"}, {"SS1": "0081763a51d75ec65c0602eee2b215832cf15f88d20e02d837eba7321b1db11f04c7cf97e6e311d352c8c2b5f1a86aa189ea0ebd168128e5c1ecd27d19727d0e126637211b7c7afdbbe5b5b4fe00cbfb85389e205ca7552882dd121827166be821c90af857da7d287ec75422618c5da769efe4e0fd9d338fcbb2d11fae392239", "SS2": "154043da611726a4eff6ceeab83751e228230b7a8d29619039bfb4835088c31b14464c5429b51218b7d589a6a11b07daf1cd65ae6160cd0e9f411339f0d530551d59f185db47dc11a5c6f731f9eb6dae78eeed93245be78c1e5f64e208edf3bb0baaf2ca557dddcbb0fa9cb348816b990b87842e2c4ecedde0edeb25a45227c1", "DATE": 16635, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "2397df2db16e0e75d65d9aff370a87fcb60b552d7558c19340621ededa5f956f00eda2f22ae49d8b9c1af73863131a26293fcaa806cd571067bf0ee7dc7c7ba816103a9de022aa85780a819560b1c16f6e7e6f8f13ca7bde3a678d23b549240b23bfef3dc8598dcdd50f2c964d5d1afdde04b4865a0740d18f7d9bce4ab244c6", "SEC": "040e331bc6f3e5e662cd32d4a29dd998193213a4faef724fc8fa4754e2c43bf2b010e80dbe4bebb83852ef64bf83880f80ba3e816bf053308cbe98f8cf4122d436", "TP2": "04158c27b376240d34e54d23dd5705f372f03f8b40e63d5dbf2337bdd2c8180ef212d1b73a6672ae74a2ff1423cea54cb694016616968843332a7a6965d778c3af", "TP1": "040c210e7cf5263a60f248afc0532b6c3fde800903fbefd9e3960829fb554d479a0196a5b177456f3f331b4e7790efe5ed231b3cf6ec052e957237114ef4fb808d", "CS1": "0413c834f084294241e98f0c70ae6d608c360fafe8618a03a3e859f34f1781cfff1a2a8035a1367f26446a9f3dd4a06701733fc339135f0b3e0962f2dc8c20e023", "CS2": "041604817708c19ff0f4e01a6fd4c18c081577f0fbac0a2fc728de73f57abf8f2d127e6e1072bd22e4a3dbe41a76e1fdf562c8eb68629ac382d2c169ad8da279d8", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041c792affa4e1f631c8501a9ac07e6d398f4b08b5617de05b9286c334bcaf8846080e8e6ba260aebdb529e2b14323e1e36eb10eed74793d42cc7c0e982f54535d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "040890b4f6fbaa7ceed8d5bb1e857a67f91262e06ca60e8ba9aabe263c3464df7f229a85414d711aa3a61babae03ff10302cb78f58819a63183ccf57c2d44a71e8", "U": "0402eb95cc83c106f5c3d28af3070667adb4f4f01bb01424e2a60433fdf7e2016c17233651ce02a684550f15246e0cbcc65feacb75dd01b975ee4c4c70df0fbc76", "SERVER_OUTPUT": 0, "V": "041d199d6614eedc462d517ec5435cdc01e5b52fadce84a05edf93fb6cbc98be4303063b80b5212660a16353957ff0d49b488124c46a1bf667ad59108480e9f0bf", "Y": "2184d4fed5ab7c33ba6faf497ff4442ecc091c3503b1f2dc142944b590e2c1d4", "X": "02adffaac692b7b9a317029a823310ef43ad9b05acc406d97573559935cf29a3", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 261, "UT": "040391725e99fbce79754995546862f0548c2b7a1f856acf624b05ba7ad63f390408cb92de4fe9fe848c98adf9cdeacd805c837a0625dfdfe7957b8cf5c0d0e167", "MS2": "1a36e3382a5c034b0c0d82b5f1427faadb0a98d62c6db562034e10a6fcf923b6", "MS1": "029ba243f7639bfefe33013aa12e356520b88be51feef71def7499aa1252e93d", "CLIENT_SECRET": "041e0a210aae90cf0fd24acdae413e5bf90c4b5e73e9f25451cb619f84a63b855403fb6ef844d5032137f2572cd062c07c7da57f9d51f763b3fc0a915b37d00d62"}, {"SS1": "19e3d04c3dd2d56fb167b1fd7a0425e983fe6d7aa94f5ab0550b2e279f8c5a331a8d2d927fc36f5e7004773edbd7a4328b14ea64abf12ac7809ca1b4733c96fc19d3a6ca5e0061629de755bae70daf4a270d6a46922ed2d0d7c9027b8a4ef932113d623eb2b83434d6bcdabdfb1a7df813b06e3f4123f2b36549b5c317a3016f", "SS2": "06d9268827ee6f99cee2ee8c217e8f1d0d9747d2f1cc72fe2a73eec7995ed2660601519c19fb68c2751f538be27a5be2431968af468753ec6303e1ae17dc647a1c384737c5a030a62fb107143810249f6cb1ebc8e1bb2478670cf6ee26678bfb034cebcc63d32673376ce48f26214b94d5bebf2fa5a1fa6e5323331f7281ae8b", "DATE": 16636, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0c474804756ab74b38e5ecf2273464e3be7e726682686514ad926fce805e7c5e1675d8072a6981da1205c61304d6ac453e71b98f076eb36d6b7e509738a05467091f007725865b6586563463c261405f3a16637db8ce0c6c2d9a44cec670e3910bbb36665e1ed5e862d31f60c20a60a7ad16dcc0a350fd219007908962b1313b", "SEC": "041d8e56b9cdd7ea02d3cf7f77769628ef96df0d14ad9012f4e084a36b34c59dcc0420db6288ad4c53f24df91f76b6952df6e6f526fee90652087ce971b49c15ec", "TP2": "040b48577e45deb2be768d93a90fa30933777fddd8cef02d5b93ec901688edbc660e1e6ba8ab3724de8137347de8d437f6e88ac659f59872dfd636dc3edf2d4d2f", "TP1": "0422860bcdd6451349cb4986057be83c177251267dc89767b03bef43186eab6ca01ed1b83bf9cab4e59b70f79426e12c4bd7bfe33abf3b445556702caf9ae0d481", "CS1": "0420a351ae8aa923425fe1049885b0aba2c68c3dacb0b69e11c109b61648fa99c611161d3e130c30ec29d81ee4625ca07adfbec43175b1a470dd64a6ca4a5d9907", "CS2": "0423b184b271be93bf906b6f8878ec7404aa9d8bb1d0630033d8917d881c7d5479237810ed734c88167a92b9e23aee07a3e2ce668255e8ccb211c11592fe41b884", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04139e099760c40c194b1ef25473e1c7752d3ee1e6684bb84ac4d00f8599efb2cd1230351c6e7ecc44c455d0d5fbd579ccfe0e706768e8059057bceda4a8f48a2a", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0417ff8807010dd87fe7eeee8a61fab942665dfa254768a17797892a278fb3f58d08f33109a34b68fee911d558939864c60b7709e35bb39f70e178b41ca0559cc8", "U": "040463b37c8770358d01037f35a31b0265bc984b05d4391160eac0207464617a6d19c4003572138fcbe4ebe74033c69ff62a3adc61639d761fe0d529414a3e906a", "SERVER_OUTPUT": 0, "V": "0404288f5c43407449d90b383c81d22e58aeb03dc237cca7cb33988da34502258c18f4204238def73dedc6430e24a84e1c2b736a188fb6d932e84ab806c1c2e67e", "Y": "143fca21cb961cb0a1d15c9a89cbdd21e0549727f4dfa62e519afdac40e68677", "X": "1f5e033bda2cd45b19b928c3444ab1de92db33d40e444ca42ba6c4a415fd55ee", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 262, "UT": "040b0fb248bdf3f41589515814e57af6c249d1aecd5d01ff43e8a37a0e87490efc06689072ee4acc00073bb6eb95712a8bb4d7e2b5d7231faf5d43f72a3bd3b10d", "MS2": "1ef1f2aaa530165284f57889fdcccabfaa2371d74d7017876e498f9c7f32d15b", "MS1": "04d5db99ae8927a1a159d9b0e284dd9c33bd6433f9595c34a274d2ba01bac87c", "CLIENT_SECRET": "0407723aa77dbf1a1ce214a55ad3bfcdd1fdec9af57b4e5134af8073aafa9f6c4a0142dd650683e673cdeb07736ed335748adb36f0e186f61d05a6e866378bf29f"}, {"SS1": "00f2f11672c67da32fe0f68329a87168b5e72daddc38262020162534276542cd045b4521114b15da8f34e02323a4fd2e4b96a9b6542679314960bca114b3684314353b8c53e933acc9187939fbc3cf38df8b51e66d2f70fa230db80f8d2dd67913bbc65708db896b7f58a874592bbd4672aeb02b2b6bdbe79bd74bce60b02b38", "SS2": "1d531acda9a905eea8b22f652249cc0d8062bcbe7baa6fb6b45083ee036e56960ea20436d45e8a0cd61ba9c9fc3cb7855d20713496b9771639b0d978190bdebe177076daaad7e6c6f8657f79c5049697db687f294ce5216a11bdc9c8d8f25871194c482c707c2732aeb0e7b8e6f50eea68405717096d0cfb8d62e251f54e754f", "DATE": 16637, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0f88cc1a542034f3738ea83c52c65ccc18339c2a7f2d71283c151e3832c2d96e14fb721afe4e084702f0d5a2717ffc0d2e48bd55b6fc23e86a3942394588bb8d1a7774a045032e0d015918073b615aafe6f52136102fb65117fdfb30c746b94c0af1bcf1b0b460adecbaf71dfbb9944cb5a2c78499e8ab57e30a2f1d8da826ed", "SEC": "040554ddeb66379b243d49213616729b74e8a1dfb9e1faa74270046a7ca4a731c50755b1ab2127fd3f727d9fc482aa35d3a3796ab48c2dab74890c955e17b3c5d9", "TP2": "0414430695a0f816eb0bef8e54d4638657073b4849119562f0ddc5b0b8cd547a581afcb31bbf32c5fbaef3a129ec97e4008c2287dc9842e9a386e62c79637e3513", "TP1": "040b2c7c8c5696b1be2ebef3b36d132f5547fcd7b75b70b22b086fd30d5b5ab1d512174d8750ea0df00b615149ea38291eea0f39617a517954a9b6c276e0570480", "CS1": "0403c8da6169750b27cee46be36cf5564daeeddf3bd7f21e6cb16512487f3c6aa11640b9bd384f48c89701a327b2d26868e5d6e655f130b5e1ecc4659055f0919e", "CS2": "0415d9c78fd68fb74df13416000f4f02c9a43df2a06a7720338fb6ca34871a797d0945605cde247178ac83a17497645c6cf881f9504ced5548f13e3976cfadc64e", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04197c6b3356925c6879f5be66696f8fb0055435eedbb779ff8fa15434550aa7552013e36460f962790ece6688987097c0da1440f135a5d1d086f997e0b3355ec1", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "041a7ebcb83e594c5d02abbb3d352d0585ebb7579e167afd3b784c02a9706df2f60b765224504bf4223b04e46c657e5a103e66115b7e855f59bca425c12fae7078", "U": "040525cdfb1bb1e711ed9a0d79d4c24e7907f96d8bab4c8f075fc1ba05316ee02c171d45c40a248a0e5b38996c2f6f4aaca43aa69fa3270b0c4250cedc75ac87bd", "SERVER_OUTPUT": 0, "V": "0405058045895866a776886a1ae7592fd4188563c6f1e2972dbe46a6c01fc1ef0511a070bc2150d63e13b9cd0d13e4485a87f122d399a931fee9879a72acdcd12c", "Y": "1f7bf0428383637bbff92e8bfc6a28bdeda96aedb47e97560e0daf3fbae3d6d4", "X": "019f0a84edff48341a54e6a1c77f074fc1a6f438a479da3aab056a21bde00643", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 263, "UT": "040a9184152a47ce30964dec158a5efd3bb1b1c40a07cd00ddd55edea60a6d7f841e32ef75366e28e9d3ca7b934614af787c4a87ef483d3b8df474b7789c3462c9", "MS2": "0562ecd1e9af139bb7929aac40d37c6f1503d23189b8700ca7bd7512c28c55ae", "MS1": "038f40fe76dd8a7a6476485cad8470aec9118296e53d7c89ab38b0837663888a", "CLIENT_SECRET": "041052ba8e0599df3640303551b86e5e238c2d2cdad121007f56bd70cd06a6e1c121b10ec8953a952b7788e07cc4503b677572cda5e45cab72511b1f03c805f311"}, {"SS1": "23360ae3553c75cae1eb0b2fa6608ae033acaba9fc72068aa22850b9c73028db15ca28eaaeb6954aee3dc419b85187e7e0edd6a06c67a6199ae65e7884a38ae807161bd2334161a80f747d533b2bb980cd070d2aade2c63d43b6f6ba58c8645303d7fcde932d8c2e821de7256ca2dd3ede7c28b7de8b4fd1bb48969593b249c7", "SS2": "05ed08e61333695ea5675f137ce28d9e320491f0d3e795c89eac81b41b6b74771333e05ed4ca2cd2666290eb6aed0c38b4d52c693184a9d6a972e26b7abfab701038a9c019ad742b85c7b50726db7f986e9606d1b3f9e6d9ef712088ec88ce9004dcd0f4ad825e087f442cf12b92c783c3dbf7c6d03021b764ac86a26765f0f6", "DATE": 16638, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "010608e45b7a466fe30a13a40b209a9289424b389b860d141dd06999416834e80d6b44cd1f37f3efdace3d1d57eb4d5bb73b0df4ca2517a01de3ffc8840687751df102107be2f0f2d163fbac596cab4d4ba4b901a7411ac1f11ead3fa186256214e90b980a878f4e2d0b483b4f84d9a08802454946a251e38c60a948f87777ed", "SEC": "041262c50374cd069065a82767ac42ff5323c2215697ae9c848c98283a2657ad1408337311e41e461ac40254c1b446b3915998158bb3a037a3b724d31830546e50", "TP2": "042029e6f5c617229abc6b78ca3cc9614222618b221e38e801bfbf3777782c87fc117b41123c9de9eab42d713a799bfe4d889ef07a81295dedf2bdbe45c964524f", "TP1": "04125642d21168ab6f590efecc46a4d8f327fa5e7abe59a3e23847c22a758279ff0b224b2328cb71436f5e0619002a9bbb5083ee345ab66f5bcfbc1b6badb7bd4b", "CS1": "040d891f0bce4531659b0727f887d6c9d19d7bea6a944fba760b153991e195572b19e2610473920732201c800dc55a54877185b0cc459c947709bc259325a50248", "CS2": "0406285cdf4ab6514a2877c0c929037cf54c1f241b6104cf01567b3301522870a503023f606ef2c8b2ec2919ef8a1724c7b76377297a49bc9088fd391bb3b4eab9", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041d2fa9abdb2729288cb152f36b7966102de1a47d1d7f686a284cc1bf020cc2b914ba67f39fcd27dfb86ba5e91e2a6868e65e4a698a1eb2cf26f0009f82177f84", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0408202ab22f6f23e6f3a9302358ed5ecbeae6ed874828580f7c3f6b6497d371961033da7911d0e519cb35137d1b404c053c8b5c85ca5bf23fc81629381738d162", "U": "040d3ae2fee82329942561b44a5217c098ce4aa337e328197893afd7cfd5c7c5c7198e9498778e9654bb370a58856aae6d9529acd52b87acdc925824b017fd6369", "SERVER_OUTPUT": 0, "V": "0409519b418b6213f3ef5cf3f91e3f78d0638b0c8436d72de26378ab03084b6c7a1f17eef034ab25c039ff8e54de296458d3e8fcf7040ee55d4caf4767c66808fb", "Y": "23ea3f32b84ececfc695d8d36bff3d15ba7b28e17e1dd2dcf59621fc1b4d6800", "X": "033efd4d7e842a3223fb9f94282d6805e80c09946617099c9ea0920060085f28", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 264, "UT": "0411a6b3724fc806ec0481ce2af1e82f02e47cb55309851082954dc35dcb9a5b3420e7f587a3fddde9d6b8780d15397baefe84c589ce17e1cacaaa673e04736e12", "MS2": "1df1bb7496d1000b174eba9ac1bdb838b0c372227f7da8ec4282801a7ffa94c8", "MS1": "06e7f75775e7d26a800d328da74899b8f7de5bf4407ebd9c8e799e51b960da79", "CLIENT_SECRET": "0407036e7afc145141e18d10493fa2499fcccc72312f8f85880f7cfb67a63d69021ce6e3793260e52a3d84b935c4dcb1974d873d9df7bd1cf49738d86239fe64cd"}, {"SS1": "026f3cc26ce9ed0a7148553d5b6ce66cca470772773a351b92ae6c2ee6811016127ad9e4116b7e7d345d439922224757639230b6fb0bd2390882d2d07c180727225f92d0641fdc9a3af7b705cc7fbc1efeb2241f3ad1502c77763bf14801d4441c08adcfeae22b9ac118835ac73f8221cb8d4fd83599c75ec377766185cc1a5f", "SS2": "22cb115c1c21dc4c69115b68923e7b0af5c9f72afae7b7227b4bd004d4fbf725166942d2325fb5e69e27813dba80101d14b7aaa51177042fc2e92b98890e9d34214cb7fae171c65ec5f517ddd33f0ded3cd5c944f513dc1f09dc0aab6e0c09890003105485b186a9cdb88d0f7db37edea5a192122c0a99118bf9f47b9556f9d1", "DATE": 16639, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "15090b56d01971794b12264e9fa63546f0aacb7ab03678ef3c10adc29eef0dcb0e2192ae9443157ffc5ef4085f6e7f96d89edc630d680f568fb2fccab857f5021f982c16854cae84e50a16443b687463a5e87d1493feea9bc7420233c7bead6e17b06490bfbafa0e253976fe1637ab4118d18d7fbac29b9b9fea5660358c3afe", "SEC": "041ff2888b25f414e07c0f64a1a5fd9702f2c0af0bbf27d8c880905ceba291af190c06dc33fe4095688189552d81d4e5303ccdb0fbf37487039632947009d364fc", "TP2": "041a5791aa4d98cbdff784449257f77274b46788ac9b1f1e12049adc82d9476465009c7a1e41ac59bf116f3bcff7a2acc32b18f4926aee1effab876a911b585821", "TP1": "0407696ef9a682190784d2b4320435f4259e3d18570bbd1afca2df5b458fec078100fc971565b24f8139ad3453d4306a23f6c67ea42506342046b675ceb854bbdc", "CS1": "040446533e876742e617c01d4c49a68a2fe9302345c7cbb8379d557170d09982111a183e6df6e83ba6d7c02bf3c5b80ffc1927d2f83968f4066970129c26d1701c", "CS2": "0416af76159c0d5c7eb9141cc028ed2524b79c3c5b2c74d2450137f0f616c2c81f13c347e4eb873b6cbbb0191f1f3bf826a4bf5d268d5458ec92044b6972916e95", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041cbcb16d27ab8c010d386281713c728e229bfa593a8880952d7e477a49014a171776f0ca1be245fcf1ddf3b498927670863ae2732c6f2c82986d2515df01c17b", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "040522d6676b49b85aa1778e84392da8def956f8e13b6442d1b9017032f598520513f4294a9cb317127fa8dff97c2d14835b521b688d5cb9c12245037ea6d11965", "U": "040dbec3d36c9b6f1a0d0197c568c05ea170d80cab810a0c4f1e2ece534c3bfa2f1cdc208cfccd7941dc5b6171ed651e9e2cbd4f0960e2738247af88a7f748838a", "SERVER_OUTPUT": 0, "V": "040e6e7564f22e28ee62dfe59c3b8798d7f8e237d84e5d5897ad173a36d631d3601bd9bf99388ed63cd82f3270227184071846be771874ae6ce02f0895d73bec1e", "Y": "19bd3c40d210319a3b1f5ba94fcf6f1cadd67ca0b55ef7a494dde425452d12db", "X": "198fcde3db2d9a6aab196ae801c527e196575a830be5ceb066c8fa4f7a3db1da", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 265, "UT": "040a1a14588a81c150f0a9f692f2a58d30b942b93bf65152d267ac798bb68dba2d131cdb03dfb6e4c64de506cdfaa10e932fdf8b0906aaa2060563f0c292124821", "MS2": "141c4fbea6565c9f37b8a0c9092d4fb2f56822950ec59b8aabcc93cc71b635ba", "MS1": "10ba1b04367ed3e7d4abe2b648e61a9d4127599263a2ee5f1f087099ff124746", "CLIENT_SECRET": "04107c7aed9b583b4d9b1259b68fedcd7378befcbe474f8b75332351c93989a6e20801d3de2e070327aeb1ad32aecfb99e12679e2fe3e1101243fda62a188b6cd6"}, {"SS1": "0d9ca7b04bde026ffb4fee177762ef368abe8e512ff61a7e7e0052f9bec5d2f004c84f616d91fb0795645701250cba9cded8df750258d96afff1c30dafc5111507e29a0e9590adb1800ba713237ffa6ca191e4230c3624f8c781989a96fa242a0709e3ef363ffe4084e4639ec51c5973f6d4cbecc90973703e5bb762dd314f91", "SS2": "045098f45c730f77a58a860df14044ea30b46d2a2fbafd8a97725fbfe1623fb7088bcdc78dc97807c339844141bab43bc6fddf0de4eea43d495d2aa316d47db51cf7e4bcf49d1b2678b69bc579568f9273f615687bf1a020c29f3d84d237467c0920ee89340a4b207870ee404dadbb816b75777136ee17909c2fb1208535579b", "DATE": 16640, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1ba612eb79de5268b0be3b155cf03d43bb74b35c5af44a2cee782591629285930da7d1ec99f47c1ab5867ff7027038811f5c8715a8850c39c155302e402deda11c2730a716b669dd59844620a15ba10957932597d6b6dd0893f9d62d220ce3d41f0d5d4dc59771ad5c1d2f1a1fbfaefc1ee3f8aeed6183c725e9f0306114f4c2", "SEC": "040e5e8db3cc641f823fb69c787b0fd0dbcbbadda14ecd9ed549934b3b2774f52500b51801ac849ada1a9cb15e57a6786ddec0b42a52efa7f3e55d4992ca06c24e", "TP2": "040ea61bb37fe34ca45fd46683da7614bec8dd17d061379a526ef82bbc1dfa2e3a21bc582735e90a5dd7c656a760a6dbdb01f325aed3f3b04067d41a4d336f0334", "TP1": "0416c690854a789a4f6d2544b62c2bb4691e47cb2bf4681a6d30b5dec0f957bd921369e993644dc7e4d3db4a3b488f22ec7d4e0d161fd21c765074a4691120ffb4", "CS1": "0408d6a47061e33316ec778ce165debd4397144ce289626d3aa6f0aaf694fdb0c40a7e93e4cbef58cc596714aad51048a3aa1a01af417cc7a065d3a183777c0cf4", "CS2": "04011ef047badb2dafbf028ce962b796d7d05f7945f69bfd532ab65725398a82ca2234bab18c9697350c50fea380f6ab4e463f5474cf8b9381a8474177d88c93e3", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041cbf5886056fa84c3bb58401aa24f3d3af8e445687c919cdf4bf19d4c2ce1282192f9b88899ee3e121a94f95ba66810546489714ebe6f0db1f377a5523d16829", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "041de6a458afda4bcb91521588959dd578785636d40920d0b612f6947704ab25580c9ffb729a7bcf726198d07487eb83b0a4bf4c8e2a1bf989abdb88a15573b816", "U": "042306542342970180be5d58dc8560a1facb4653c020f69947c16eb3d4a717b3ea1288fdd473e1504ccb8297498cbf41028d553aee19b812dd24163fae4f5da731", "SERVER_OUTPUT": 0, "V": "0412219d37008b75dcc254bdb1ad9f409642393dc3f4943d8aba8a8cdc8020f4641632218c169b362aa8b0c1877b6ee280032d915eaa6882ec8ffec1ff8996cb11", "Y": "03ab3e4d8db4c3d1f03401752b13975dcae5e85d3006c029ea4a427bebe5fdc6", "X": "022bef1aade379aabfc10c2c33c1973fa2e5a981378d27dcc7b993f2de4ec1ca", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 266, "UT": "0404895ad7d5f83c02cd9418dbd1b1aa5269ab2355fb7abead73d6b93421ec74c2112606d6d3d595713cb52fcc9bdf06d42ae97ef7435e43414cc1a9d4f702d780", "MS2": "0934480752f17b638e8cec0ab15f895eb71f2711323ec98ad3196ced984cadb8", "MS1": "13f3374caf10631ea768af4925787a9200a061ae0d5ad11c887b1b8b2be231a5", "CLIENT_SECRET": "041364224726ac4238bbd03c50fe0804f6a4a4eabc5468c44c20385e18549f6d87078a13b3067cc65e0e35eb9c5572c8f86ac89c06002042956ed0e92b13f54017"}, {"SS1": "0917087388e450d96fef65bfe7c04f00a6397564213717e125e360eca64dfc0f0c22bf888704b2e52ece1424e0911a739b4f80d6213e371c8316054461c7dbcd0563bf3c6641b6477b50d31071ac4849e48cdabc9fb652be340594b584d3435011247731fb6a70ffb2c8fe2d77f8f2a419205d3f71f62ddf39a1aad6936fe4fa", "SS2": "1b5046685f4dffbf523a50e701f008ad6116162d1b33cca989d17bc56b3d83f217c90140661711861422c9c48b6dcc5a923f781c295d90dbeb79307b730c73ff1e2faaf48b1e68bdbed5dc989c09668cae5c7e83279fabea10a00ad0871de6d0071ab509d07dd6e4d349342504ac8b84ba9cc010ca89d4041ca6bb55dd0d1712", "DATE": 16641, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "02e4c3612ec965ff0f2746e234e4822be6606f13886a25dd23e922b72c31f71f1871c229ae4ae3fbe95b1ef9e621e1764f274f3886adb192276101d1cd63d5bc0555e08fe5672fa323a9281314c29dc0d76bfd1fcc3c84982ee47be7a090b52011e8a88a4fa07956501ad62b749fc97200cc5fdaa8f0d5316869f9c71ed9dbfb", "SEC": "040ad7e51172b504ac42506c5426c7b81b859124094c4af146005af692c7fbd9341a124522c192407048a3f3bcf590381b914299bd94cc3d7c7a5550885753be68", "TP2": "0401a8eac1872ed0c3aabeaf8f9c613b40b228c0520401637edd5332485440f16a069fa4d43f009dc84496c1ea9237afbe2ec98f135df82fb96f9debe7f433ebef", "TP1": "040e3b7d0cb994224387acde18957c0b6b9915aeb9f6a248d2efb8671ab4cea0f80b638314f82b7d72fcc19e042e69100d385c612abf31445cb86a6f9f9ee1d4c9", "CS1": "04057329ac5414d5ce9e0d508d0f81444aa1d52963ba6501687f5fe8063c9490551c5879f3e2a6d226b553fbb597b5e4a53ad861c8f7b9944673bbcade6c3b4cbf", "CS2": "0408797856d85691253ae12391ceda300f1ef2efd896898c3c9373f94027dc8c690aa52aebb7de9d6aa7807dad9dadbcf6831d3e5603e01378c1bfc87aa0119e3f", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04093fabfff7d5c951303866f20e151ab297b7c32ade7030cc97388db0213a0586137e678a91308878d2f0c38b01aabc4ab3fd562a41e0f60ce30c374a6e63fb82", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0407a42507fbafebaa76576c2846ffc49db691710378b8258658f6a1f0c0cf04e01a4aa605095363a1a9db280b3a7d1831bc8417e89c01f33fbe63463d1736ba2d", "U": "04070a5a3e325eb468a52495d79149f4080f13925c0bdaf3c0a3138ecb9719bee51f2eb3ff484f8dfa8392eed3797fb98e51a6ed0e7441d2d6db835f47ee81e6f0", "SERVER_OUTPUT": 0, "V": "0405e95a05661e8b6e90d4af87f956b0652dc620990fbbb30c9ae3431d4bcbe6d703dbd2d363cb0e28641e5badadb92aca0b71e378995c12707caabd0b1fe585c3", "Y": "0791563d9b7cbc6c90c6f7ad97f5b85251579b93bb0fb55b5579afd51be74ecd", "X": "07a10449fd16d40c1e42ecd7c5d500cd146722660cdd31c4210b75010c4d899f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 267, "UT": "041695f78fa43d035fa7be490c7cbb2e542a268946916fbaddc2641e9547418eff0fbc3ae52939b08e062db449a8c815f9b3d935d059706c9ffa03af362cb12ec1", "MS2": "08742670a706e79403c2421dec61ef795842f4c82c9ae32f30607c7e8c1461d0", "MS1": "080c499765146961da9ae7c5dd4dd35b9300f45aaf18dd5427b209ec8dee12fc", "CLIENT_SECRET": "041826dae59783f70459d8302debccf442542db12210b29527d4943eec5b4fd6cd21932957eb2ed34ea6344eb4d778264e526b32c87da98581598f08c43cf8ba83"}, {"SS1": "0bf2a37b641ee5ba10aa7967613ccbb674d887490941e40fcfaec21f8a11f7781917e56898ee7494dd1d65d79e237381ec053e008312a852b9181fe97e65f681101a7a183e5191bb155f6f58cb551449d3ad50ad2017f5d08bbf190372b38cc105175be2b25043432bf8a4b692297d381a9acf3d603494bcf4ac01a3ea93f6ca", "SS2": "0e2f45d4a8c830e03ceeb4ff75e394917fd3fe40641224a4aa3134f7f9e68c991f15abd375b0a1c340018dace393f2ee24dfc1668cba225c41b84721ca33c62a1c5a30ed87fe787d7b4c28e73719c7356023660f00fcd2a74da4a6a411ad5e1a0f57fb50a1005d15c40d2bf9846be2644bc1426c14dacde609045cafd2fdafed", "DATE": 16642, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0e086bda9e2bc88d02fcb4071718850a88d6d11c666c42e9f5f37780da4d31061ddf16f4c197f38ea1bc928b0ccb452edff58b1e7b5f3f0d08ce5a298cf4b35d136e93c948140a5b7a920c2403385bf9b2b76ea5776ab8451ecca37920cc98d31d6d372456062b213e1d6168ac8320a25a246cb82f7cc7de4064a49e9bc2fb5f", "SEC": "0419d14d45952b33eb29ed53c157a03267704d1028ee73cb774cf2f72ed52eff2417406ad29ee44d4bd390e06fed21d7c9d6ee185d8491fb203e27df279da8bc52", "TP2": "041bb6c6fd024b92658082c6eadbd7b5d6433a51f1b22c96ea4d76b49865d92adc1d6e7d290880d53c3687c6f8341aacae501dc6e55d5c729622c827bd5ed1afa1", "TP1": "0413437dcea84954c81391f53041a59ac9291b4a97be3bbaa94325da666719d76108e36090345eda913f3d2639afe527bbdff732d8b91c29390e55d0647b9a1108", "CS1": "04231ae2a54ae497b99891336f6bcd7729539f64a8a41b8e2df73b95de73b72dc704bef579c80770352db3c875fecbf287284380605ec0f547bd989610fb4f80ec", "CS2": "041214232a4115f16f4ddf0a7ab659ac67c8bbf1943e1ceb1826bf85333637f65f1d99ee12fa6416ae2326be44531a699c80ba94a0ab0f296b0a8570d66f1aeb65", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040736f84bac6ed48a817bf54804ddd6c34e8e0278d498bb234100cb4f7391554e03c1b9388e3af649ed8f6116d390f68b615034c3b2cda54e06950fa252acf290", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0419fe4644d109eef40f00789918fcadfceee1fa2077675dee53aeb33b62cb5d8d1f89173ae5478aff0c80949e017aa54da2f2806fbd3325f1b920f0dbd008074e", "U": "0423e6bd2a40203d3cb06357dbed6012989ccb2bbfae068260346f5799bb9791320670ad8cb94563572b53c4492721a4100ded26073a9c95afd9975a766ff534c9", "SERVER_OUTPUT": 0, "V": "042318c1bb078a6b72dec1bf74de86910b293c9d72ce31c99c8c8fc123b999397500e03ba85a60356c58df5974be129be67cdb1483df58730d670d6bf78f5e7b52", "Y": "1b5bfd2e92c31cedec12657268d90eb1a456d746480e377a51398945f18f132a", "X": "043154c1e4b8a4ad34c25ae8648bd04abdc7b7fa2e0442131b2d73917e7465ef", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 268, "UT": "0402182c8ac37d85b839f79fefc07caa99f90b79a97f3101ea5b0ef5e46397694107657dc227b4af14f617649b42fef3be294595228ef01f3b41918db8d0b241cc", "MS2": "212338e0070cc18018d405deb6fbdeb9477e6c65ffd2934fcef283e248f22374", "MS1": "1b85caa327751dc9c5fb454512dffe02a6a661a1d15c16836501d83a7c3812b3", "CLIENT_SECRET": "041f41821f0c8335414156e180dd6da3cb63482e41efc3c31dfa8736141d0362831dd3d641d3d34d09ee2788d6c7aa71ea643d28d45affa87d8fb9e4897fca848f"}, {"SS1": "1f955c8528c8c45018b17ebb1e0665600551871dac34694a1d961551883ed4571f806825d412e76b2ecaab68df148f28afe97d8749da5c87463ccf017f983c9f16c4e6da2b8f8fab9e79d3406764e23d48e96e653f2fb45a0a0a10ee2656c14018adc2a976eb8bf711983842fd81edb2ddc6cbc4a83370699bc8afa7701b78ca", "SS2": "18b5530a00a12ab1f4462bf7962fc7be04805093a35708edd5cbe749a4d456b51748b8eb734af7bd07aa7fa44c3da4719e705d15bf961125d1c0323e0f2aa5dc1cdc169e3747cea7d55a3ff8dfb2128dbf3f81af2e166d3557bda22e88bfa27b068d194a114319849535dc53d43b078704b153207aa78ef35df7d48a5067a2ab", "DATE": 16643, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "028719e4bf10071fe2d1d0ba36c6a529bb869d1c29d084c7c5653ea8012c8558134efb9b4e5c9cb64cdd7d10d43009824b6f40cbf92e69425e7c018a82270666097776ae1b5493a8d981db67e9b683d91db15b1b3868a6838c70a3ae150dc94206975ab4e580b721c2adbd3a7a937853378e9da9356e23ff440c3e328cb6cefc", "SEC": "040c4a78359605a70452f578ee17af7d94d60bc1ed878445935213c854ecb2a6f01c50dd8dbf05cb4f3820d9d4b3cc81d07869ccaee6071ec0c09d659ad127cbc2", "TP2": "040657aab24216d4ccdc23135ca341a8124a01893059f2f2e0273368069b765ecc20adac66ebdfd3e76a585f2dba1ae572e2a0956641d8e8b8ffb2585818b52d75", "TP1": "041d60d003fc33fb89679cb9435469ac4d2e0e9006ada85238fd3dafaa5a9f1fcb1bf87b8d9775f2a90913a0bea2d3600abc35b81444e300f53c518b91602d9668", "CS1": "040ebf5793e806a9d963c8f074a430b55e6c2dc171722fcf97c4e6a89fce729d250517a88c19012a761aa63684ec2ef23355acffba4ef9f60f37ee11aa6709839d", "CS2": "042251ed64d56a8b7f78b3a1a814718ef550a0f280db185d63e029e6faa9c5b4fd0e407d29a9c64b457dd6262b2bfabaf34e9b7a009b1b8a93b1513f6d623a694d", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "0416ddc14376f67f5509957436989a6e8373300fd23a55c04e00ea3e3bb0d125c70a2f7e16acae7a66a73738b990611878caf6ec3664a9cc8321a0290199bafec2", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "04192a57f1f504f16fb46808ed6981dbe7af889205e4404428d23a8b0946b76ef504155ae0501a28dd4bd5e3ea9a762c4796b3c902ee53aa16650de00dbd244042", "U": "040f946adb3cb3036c74731e088cf81ef9814133da894135adf89d9bcd82f3bd9f078e55b12a95e126a2b5924a097fbc01265825384115c05176c862a4b2ed07f2", "SERVER_OUTPUT": 0, "V": "0401f1e0e917a462abab259fa86579c516811c0e3b091a094433e7a262a32af3cb11ece6d82f9b074d9b5877e0e18036e7f6463ff21b5bc586e005d90134d83ac1", "Y": "03ae5b05ba0226511086c1901a461e5b3d50df6122fec53119af55da8f09c598", "X": "095a74aef38b76510b7198e98d152461462fe4f54a1bfe23971fb12399d3509e", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 269, "UT": "040d937b8fed79fe4953abbb364caa88f47ceb7cadec3777209cedf04f80cd97260c3f50097d0c08e25f7727709b20a75a2c282f095af45e9f1ee8efdc99898066", "MS2": "1f00cd2539fbd054f0dcb9eaf3c2206b6289035268b29b4bdea94cce0963c6cf", "MS1": "10e0a2beb310b3aa2124ec9b8b807cd6630ca6714337613db1f8ace91cfd409f", "CLIENT_SECRET": "040d66bc05bccbb1d62250f863c2d6ddd0b322ec476bdbaab194af7067c6a5723f03f20a5bc22dd77e1f4d965885652f5cb8e92f63fb40fba1269d1d15f1239887"}, {"SS1": "11eeaf656ff6f71e61dc1a32d9ebf52c062515433710eccebf940fd134d5412d0147afbfbfabe178daed378ffc7ed4061b4e065bb055f440025f684111e69f19166d44e78fa94fc11f5007db4119366a94e0944b321eaaf85c8eff8b5daeeee91b26fe3442c0f68b56904fa9f0cb412c70ed09aba3c33421ec7311239884b7c7", "SS2": "0124731e6076352f3c51801cbaa9e11e9c9686479d545e3d29251f925d8acddb012388a0f47b1da878c7023deb93531be95a72c058661ab35376b5d44e2579d10d477e9e31b60fd3259280d6949787a7e5419fb2755f4823426e70e5ee10d3fb20ead44f289028f2f6bdd172eddacd87c53bd154c809ba44a99d117c3ec277d6", "DATE": 16644, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "15c0204f57183d51a5b4b21bc09349f727e727177a754a1c05a2fac94e193d641343059a9fe8e41ad297cffe222ea9482d06f835c7d0d55a0a88cda727f1e98717d1c2df800ce2959f3a21aabb9ba7aae814d825442d5ddac1fe06c45f230ef5094b8f058ed1d4f5a258b84e8cf4e9b9fbfc259b8eea9f7c89aa843695ff33fd", "SEC": "0404edb3f01c5b8754537d0986ebc162ac9f18084b4261fcbedf8de78f4eed8de208f9c76e40bc656844f9ee053ccf40f7004815ab13702638f6f11cb675387bb6", "TP2": "04064d16ad2b62e5c9024bc6353eedc8425f23a79737d62b4f72ae137c31c282620c724b8d4dffa508837e3f30174a88df93236f4d486c8ed847a9e4650af86c92", "TP1": "041298754a0e04b13d6bb4563daf40b602743a3cc8a2c19e891c2b1436231bd88017a40c91cd8334a32d0366b7b0651c7c97dea552aa409ff0eb4eb7419a92a5ca", "CS1": "041daf3214dd78c4c8dca97fb7110967b74d1446dce25933fc47dc10fb2d1162940b956cd9db2005ca00b3d7b0307332f02205843097754490fadf755cfd0993ba", "CS2": "04197c893f9f3ed0582deead49daa5f7de2d7e3972805d7191555154824f7fa4ae2286e1e6b0a7b9283cf4e965ff14eb83bcffc53b886282af12bd5bb4b351e5a5", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "0404bb88d467633c3fd22ac2d09ea4438319479e53f0f60b38bdfed8d1ab7321c5147126be0d14e84a81c344ff88c437465387ee53c318e1e0a9cbadb37425d9ff", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "04121aa6e08ed193fdda4b56e6e53782f27ab7a81b490f7b134f8b833c1b0b7f5713226dd4cb4d83cdc2eda65f308517333db6ba60651f2595da51bc58f59ece8a", "U": "04117065b76c866c6f45ee35705e7ea7ca320129512142be9190c27a1f005fc4e41cddb5beeee0ef4f5076d7a00400adab15a6e04582779226a2e9b1280f361a5b", "SERVER_OUTPUT": 0, "V": "041bc8c3fb3b405d6210d643c667c915397bcf2a7caa3360db4d309fe26076dc211ecb19946d6ac75bccf79b7e7c9639260c0a3214fce70843c22c3efa20f732f4", "Y": "04979189b877ac997113f77459bd6bdfcaf4971caf86a1d37fc1acad1b2ab2c2", "X": "17894da52b9882a05e6684aae0277cc0f7ad180c9b171f8a26e833797c6a788f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 270, "UT": "041ca741d5140cdba48581e889bd8110e883f5a7053f73a4a27e42da51964f2afb1b861a3ed29c8993eaddc16d3f8cacd2c3cc0a4fe4fd44448705ca53295eccbe", "MS2": "123e7ff63f91510754185e128c96183aee73b3caca37164a7973b7d13004d574", "MS1": "07d54acad9883f137d60a237cc389452187d31000978be8316cf7ce2273ecb48", "CLIENT_SECRET": "041291de93a69f485ae7fcdfa20e71bf3d6a926d8a265adf51d51c7fac3eb56d9622ddd48488c44ae7765de08ea2316de0bd5f5207996bbc98a70d7e4e5825e41d"}, {"SS1": "038fead1417efc660243845772147c490030e9efc1765176379331360634bc2723b0419ffcace826f257f1a12f4f63acc9f9d23da357fbf1742d0e250fc520441fa05c0961051bddc69542217a608bb6bf16a66603924612096cdb287ccb7b330401bf4a901ed672a1c0faba7b175d630923de731674490947caa2cae4acd517", "SS2": "197b8578fbb3b5fede94500de8f6e1181004805b0cab1b313f4e3c9da25ecc50173494f8daeda4e7bfc19974fd8f7eb4a2770b767dee1d1176bc017b37762a3e21cb457e6b81a28b7d1df97b2aad74cf4958a9a8ce5e154daa56f1ba50dcf17322e1f726d7af9b083bb3b92d8a186253b4f39113e17c712cdd16be822ae24f22", "DATE": 16645, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "07c5922a063bb0b3bc67263b8ef5e1c28e59a02f6d422231013907da456fab091390d6d890e6d654ed32d2119b676ee52f224f3dcb56fd90b0df0d21b513af5401adb9393d54a7a0b3c7357e45d2350a7c042cdbee8565159003332c5733e28a148c04010a3daf09539723c18785b92da37c11040634d743830e2b6e5da521c2", "SEC": "0413aab3b897b83e5d694f5cd8249cedb5225f4cf6abfb2eb4beb317c56aecbd1512685af96cb4f171247064460bce45e202e0b4469d808fca586c63c3c9b77e52", "TP2": "04156d4965988af8bdaf82e9fa8d728b65794d095d64a8b3dc69b592afd1188e9b127ca29b54ed00fae2708476db644e3a6d8475afe7f4debf3065a64693489dce", "TP1": "042286e169740f5fee8d0ac4823f84509f7a0eb335a937e758f9f0b414653625ae2244bddfeae05ddb0306c0b60e1a2e6c646beed33f3fe9eaffe64093749d51e6", "CS1": "0404ee76d4bd756c68dc8ae576899561f7411c79f9af647034a5fde6304a2462a3193c83804f789d2614248b144743dec52643139aa82c072274fbdd53a081ed53", "CS2": "0402d1fccc55c30fa8e31d3fec632da209db0724449137c8fceac9705c068c9ba018f1240c4230bd22265d20d1677c9974033b99375cc9b90fec62f336fa154220", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04203810a9f7ecc60f2b6e134a28b600ebbaca36729db7222774261bdf2ca7ab0007b174f300b5fa372917095697d4350a07f4bffbbdab99b9bd5c283c19e114f1", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "04093c068369c9477f92bd4195297a4a444594149a4dd3531fe1dd07c5a72c5bbe0e6ff79dc553995e610ad922f26ed5a27cfa12568a33bba7c2db0dc54cb36a43", "U": "0408e93c44fc0cf96ec2be9b0dc5706c92dd81d3b254338d7af0289e0f538751aa171e1482c572afbf445f0c4224a860b61710f0deb00d3ae6e48813f6a8487a1e", "SERVER_OUTPUT": 0, "V": "041c757eb39e6954dd8e11a8c81a9ad540509352c87051d68f19a10c4325a69ae304707ef4b6fb5b069552c24e998cb1ab30ebdac0e7b8a886da29893892822511", "Y": "1d858c589abc686bd8c4b4e0eec45aa69db6f3655818b99ce59e0b61e8d03ecc", "X": "0b4f22867a4f144f9edbfef1bf632ff7d74c589c129459bc4576233bd45173ba", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 271, "UT": "041186885ed44720066f7bc6bee4db5590fa3cb02b3b606d3dde511b467f9d744b155215779ec5e34a23ec89cae4a946debc02b0cddaf5f7b15f9166c1086c089e", "MS2": "16c041895f7b5bcccbfac8c62b6fe0bab0008b7f74c80aaa5bfc3ddecc1f3850", "MS1": "0138cd7777acd936c95c1911fda09d18a7ab107e1c4975ae4912cb7bc9d9c38b", "CLIENT_SECRET": "041e085e7c98689d9109978066f5e2406df0f444042abea2572360748107a90c69151e1e3067d2cdb539c922a0317dc5faa97dab53671cc13fd5ad37c70a762bfd"}, {"SS1": "0aa8c3a9536560b775cecb9eff90e1ff4dfac9b61e2d2ab482f45c476329ad29028b59c3ce48c705fdadebb660d2bec5179e16a16b29ac7dc83ee51301e95e4d2050a97ff487bd0c427d40d79594999ff4182d6724883fa3179cf1571246174b08c3b5633fde6955b47c460ef3132aac7674216220fe1208ffd73c4bb7c7594a", "SS2": "0ade07b2fe1742a4b983a37dea1357d71f5954ced86977c400f01a2e15368e70239ea61e79795501ad73920cd9802e290e9f3212654dc6b119d77ec2f89e1d4b232db0ea36ab7fbe612c660cc47dcd70439fc2e3be4177b402dbc2f3d12dc8041b05356977521026989d1c8487a98ede06ecccc2cc6e12a5f84a39a25158c7bb", "DATE": 16646, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "22d8edbb857961c67e6c22ad8de98442a61644f4db48ee5f71e0ec48fd4661f9011f708ae68ee64b96714cadb5b473ef8ba860f195e863bc4e0a495a237ad6e305fe5ab19290b83ea4714315d7b0aa5b831ceb5302fe762cc3a8c1d0c2f426d316aa0c9cc1443ee7faad7721940e21ab9e48a7002d87bed6c7acac4e2e5312c4", "SEC": "0423f21b2835ef9c97f4b28da429e1984ee309f2838dc1e4d0b577f0856cc183552372aaf3afe4ef5ea9848d93409ba4320bc8ea8a8c05f7a1e86c8a912e580c42", "TP2": "040be13af1eacea6517ba0c2da3f120e63774ef0c77d2b890736a11883f9be49631ed2aa2102f76ca89aa6fa3ba5b295aa3b43e9fea8e57a453557569ee877a31d", "TP1": "041020948850752e9369cfd10060a4190be71295975dd4d750a462e4d48dc0a8821660b7274cecaf84e98984de0b3fa444be60e41f054fa2409203045317e91265", "CS1": "04163691a912b5a5d2918e5253258839ee77c0c7f8d6183b9913b9ac8c7dd9ceae078947c0a95594dd5a711db6666e2ef0149f586e68b6cd88f13873d77b4b924a", "CS2": "040799b59774751de13aefbb59ae0aa817a182cbf12c1457406d9bc8776847a4ef1ce3973c124d2a9db9be46003aa8406819c75f726907cda21413d56b2b2bfc7b", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04057cfc7bb9ba0b487615aaefad9c1ffb7782d3e1d5022478fb142a2abbbccda4178d74d9bc21489702dc8db8ce720ed73a21f621a9e2b3721f9543774dd2ff21", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "041d5072908325d1aed1417c5d659b6acbfc78468db13ea3040d000314e6824b8c046a527c4820efe162585bcbe5daaa4f22e497d663f19cf07866a8f66f6a14c8", "U": "0415213e644e683beb01f5447517df44f76acb1ec7fbd7f4ed7da90adbd5a68ba41ebaf0c35bd049faaa32216e893139acd4edf71d14c1250d6e615a50fcb981a6", "SERVER_OUTPUT": 0, "V": "041b4c39d16534b32cf43a02794567c8634f86a28603e1003d9722b31a76c9b4d8179e5192bc1340294102a21d66108b708db524154e0cf85d17370b4dab5a5061", "Y": "0f076c10f1d7d4273ebfe854cb0930dcc990185ee784de7f05a110d052ac2d83", "X": "09610a5eec7fdf2ea7d996328db8b229d3e30408c4045f5df72d238a4c6d9d46", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 272, "UT": "0421760cb258cbd13d99b69fae945aa1006343bf2d8f3696c661cc4e6a60e403020c88948f96dcca1e87648479dca508274767e18291ee55ab75265272b83edeca", "MS2": "10bb077c75e2c9a6ff99e004181d5168c5a616522af3ee6c7636a5c2c2463d67", "MS1": "1065608c3eaa1dc65390df0c1fa0367e88255d24f35eb6a3187e124e87e7395d", "CLIENT_SECRET": "0401ce3d4b2ba373c80551f7799d66d1d2e486d265ea231954e7531c0c32ebb4e9051829ebf887688b6e753a3fa0d587adac45234ba0f37569a826f3c6f403dfcd"}, {"SS1": "1296462dc0dc0dae7c5aa92a5e17ae26829dec89bcbebb47ce18ded0f28cbae3163bd9bd4d6231102528dbc3993f0eefd5327ec8dc145015482adf8cbc444e160de16efdfec03338ca0f159238ffd06e8765f7cb3d6c0461798f802932a606e40e4451eb12c89990428d8c500727b95b2cc2df6147fd16ca8305fd65523369a2", "SS2": "1bf90107383834ee2b8f36faf7bf855b7aaa2556b7ec56c2439bf1dd1909e2cd052718158f9ca2444491e6cd66590c35add24047d5a2c68567b24fd3ce865b0113e0ef65658677e4c7b3fc903b957e62d8f28c76b8c121271cb98fc64be0c3f218e4fa38538629cc6877d09b3e74fa24530f474b77f9092e89fb6e4ff6fd4de3", "DATE": 16647, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "08768850fc208ee823343be4e3f092d973b1d28e62392dfc21482181cd5b906f058bb17b148cdc313addeb195725905c9f1994e65be9b6957a87006ad7c594ab106d2b086b79caaf6557642dc002b692271e4afc32297dca02375b1106663b9813451ca1ec707cdebb9689d438b74e338b15b8cac7f3f8a2ecb6596495ff1967", "SEC": "040bbd6219c912de8519749d9c307e999ee0d3b69f8f43e92efebde70279fdad401ee3ce9293f6ea2eb5b872e7a387568df9fb2bd42eae899925774ded03f39558", "TP2": "041b9e15ef7c09ce2db62033c028cde77b7d3531f40d94250686751abd163c836b007f2dee0382fa061f4808ac53e177c3ec9cdd7077fd40c5661fb6a82666f533", "TP1": "040fdff2637560c2183d7ea35d613b5cc983449d306935ca7a2ea8df3efaca8a3f15530014d8dd2e8ff44a63efc6dbf74a5d72911432433434c762f670b5c1b019", "CS1": "040b2627c8c0029fa1be954585c84c7f7934677fe9048fa8bf2eb6ae78749ad2b2031470bcec55430452e744956a8e577d47712775aa91676d6288cee3bd249ab7", "CS2": "040c2eef076a2ed7fa94d846d11e572e1c99632314cbacef2d4435605cf4c595a60a5b04fe943d87caf925c34bb7bf1cd80ee354cb82bce3a62936b61f554d2287", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "0412a501cd3f222fc980cfee757e26becd7b2676628392bbeafa66d69a63c55d1303eeca9535a884ba07bf292067fc5ddeac5a72adb9d9071e08990fc71742ce42", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0401a93a11cb4bb6cef4e5e7e488f8f20fb785b16429f2604a06beefd09ff35a5a0b889e729e71dcc6dda73dbab6f0f1dd9a639b3ceffd14d561ba478f092ea7d6", "U": "041090d5778cf70f78f5515c69ee19840f4eba65c8dd58e69f29e66bf683353f6c15999c0ae0c7d09c0818466b7d6593ad48153e9ab7bf49119c6209e44fcfb821", "SERVER_OUTPUT": 0, "V": "042134ca52390233f49aed75ef4bcadf9b91c2fd6067a02df093bdaf567ef67fa80402d388c3fe9e4e90a788fbfec808cfeb87708c4b0f25242cbf4186b4a0441d", "Y": "1c8f5f96b5c5e3388426810a614ad72bce3de03319aa40ffc12c5a7034bf3639", "X": "0e3a2ca73dd20a0216817b9819f525fe85e38dcf53c35dcc65c031e84f9f2a9a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 273, "UT": "041679449685e297af7d8550b9eefd7d22af7a2d10f22ae587296cd7526fa0c0bb1fea55fd1d75c52b6533791c6ae7dacbfdc49dab3fde7a08011b634e3045ccf7", "MS2": "0870f2ba5024153a06b904291b92d68620a03246d056d7d5fa4862efb0b3c341", "MS1": "119c4590fa8d69c7f115635e7a7d84c0cb6580cfa8b89f3ba21855f891206b26", "CLIENT_SECRET": "041c23d4ed0d0afff907b41431cca6db965fa7abddf7744a2d915d89508051954a02159beb8b888a25dbbe2b9611452cf8788a86e538f84b10fce8173d2c37d655"}, {"SS1": "1e19cca9070b2d6d3ecc30217f2f958e5f38994ce72a69f16496af936c880a82231dc401092dd3af21467567b33f557ce439a84d5eb42d38658efe25e4c7930f17e17f82ac77998835cf1c7349ed5126e4771dcec04e0f704eb1a16250a8c83f2045306113620ab854a56cf5fc377400acdb4b0f8062c3f8f8635eaea906856b", "SS2": "0018b705a117e12b3c79eb538f0f3a9b2a1f2fd433835112f091cf18bb52cd1e174233ccc0e0b4548d3b902acf1427eb70f810a9feb236f41c86ba0bdcad2bd8226ad3364f31255ee1e7cb0254bac62cb86bbb4637c6f8d5cd075c443486cabe0fbc3e53e9324b41700f7815587aae971ea8ee4fb32d6650b2d8960f675e4e54", "DATE": 16648, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1691f6dd136aa1f0e456d8a591a58acc46a8e8ffb865a16d28f0e948746f3ced1d113da740bca46802748123f3b7bfb7c76b3bff180e4a9b4ab1c2d70608921d045fa0fa2dfe8f2c84cdde3dabc5c74355c38497a7097a09cb19f8c17190dd7d232bc4a852e82a66e2799d5d24932bfc272f7b0d3776336c767627b780611ddd", "SEC": "04235cd2218d55731e981a326003894d4cae84237046d67df35ea1bfebc07f321c00ebc32458f1d0ce58c4e9d89ca63bac558b5dbbdc0d1db0746dbb041a5d4012", "TP2": "0415bb48bc442df20e8283f74d176849d760351bc3e3d9689afb4702028a0dbd1706c19d86d4e91502f550ea22f2002121f4620155365b3d7e219757de2a2ad09a", "TP1": "0414a7eb33203adc23d43d584e03b781ad010e4958264755c2800cc028c380e21e00782e676f3a966e49fe5648b8ff9bc902720e268ef54e785a35027800bf35ff", "CS1": "0409356a17351c825ea0db87e722c5175b0f84b26a934d8d012b9478c8ac414fba20b61338f50b9c13b95c91a35ff01a58f98fa75a05d4559ca764410e3dbb4463", "CS2": "0416d185835230808e0af1a286f627caeb650883a8ff0d8faf9fd579a1d838a3801ab894054abda071d94d9686e51e4568f3d203051c9dcc5455cbb7e664f315f1", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "0420585eda564d019c450956079d3d2b8341f5eef626d12d135e9592afce76a8641ba632a2a33593519513a8e88fb9134476907d8ef1a957efec46fb545fbab852", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0412b91240c6458f6f0a2de06931a9363f45028ed2baa71b2b023209fbca7a0df208407fdd14ced4713ece2b4293e89a12adf3788851dd1d0b67f9110c794245a5", "U": "041478ac200b8c2ef5734fbf6a00a0dc3426a06e825ca127b74d4bbfa1998a2d9907f74dad3aecfdbf48f5118238aa7ae300d936bbeb27f0993600f07becfbd48a", "SERVER_OUTPUT": 0, "V": "04215947dfff79c8baea780d48a55ad955cebc576bfe1cbc436fdf6be421da2fda07a6e69ece3fd3105405b1367fc000cd8aab2124188ef02ef9e4e45b5b555a1b", "Y": "0c95202258590d5e729e2083905e8fc1eeca4425f682e407153c7daa26e22128", "X": "0fcd1d0e40b14d5c7048e78ddb90e52bd6cf86baf1fe499a637c83109fe30bde", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 274, "UT": "040ad4cfc2be246cb3d57c566bbb169f9a475d27afdd990322da369e78d2bb43aa0340665e8f60d851dd7fdf41b4b9887ea3bb2a6c9f0c00d93d9bf7bae0c1b364", "MS2": "0e9a16cf0025db87e81cf582670fff3259dab736fbb5b2c930f60059a6122a0b", "MS1": "237355128ead1a2574c4b58c7acab6c4dcd8e5657fe28cca90567e2687470ca8", "CLIENT_SECRET": "0409e32e02e256f1c596c01965f846c4dbbebf442b5b04f6d39739d83c7319f1790e96fe2a7734fb191411c882e5106ead807108fc3cf06ab0dbd90dd0e99315c8"}, {"SS1": "0e1b3d2e04e2a8fe1a1319dcc32d723d108f7ad1eb488fe20360bb18d32799f4161d8ea9f2164365247455f9a439c2d473c98588d2e66361e7fef5a2e00c182c0f44c1b4a10163a1aca7aecc69d5cddcdd88a715e1159339731e05bd68aa1cb92241f11348fb83190086e90d742c6253d50bb6bc285e2e262f64d22b6aa85363", "SS2": "1d4962f099a9dfde218bb21d0357f2fd4418332a5136fdc4e7e9d750c47d547b2172987666e09d3ea067c87834281509999802d8a60bc2c0a9ffa32817b46968193cd26772fb620d92f06ba7e19e2b7dde846d79f00fa1e21332460d6d4ca67218bfe4daca363d62ca656b9d9c430540bd9ad2737c7490874d948615a2a56a4a", "DATE": 16649, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "22b624edfe0c2c9251fa3f0a247b65025f38d7cac8797169c42e3588815efde11e87fb2599a6e0fc17929747b2a02e12197ff020410cbb79e47056f43b5c44bc22c594a01d2b12bb7075c60f9155524e8e82722104c6ecc3a25f7d8cbdb481da0017f8b666c1256af7db29efc1dd2800b19b3f992c8a02fb8265a40a77df743a", "SEC": "0410ca3f00eb5a08e686e6c4da95fa25b91633142bc26da30cf1492520de0758650c34c8128eb2d1fbf8ef450aef6710d051b6fb317fae0cb347930d7ca3403b77", "TP2": "041c5fdaa91eac4ca80261551b326a8ddb07d80b640d7415647e25716fe21d2bb61e6e30a1d1e621d3b0ed87425818cd677e0036572b325d2ff94769e49b4b8bc2", "TP1": "040874c2e505dda6ecca584e8f9023f229621c668cee961560d28266cb1cf0877d0191705638bb1062bbe8dad0e4f3bb8aae0e31bea865f7fe7009b1eec1b0aa0a", "CS1": "04090f88c28d378c019c7b04e3817da03bea34b0d0c55a1476ab56c711cbfa758306068d2f18090261302e97ee484df773c94a27cfc6ef5bd06b7ab88ea44f4c05", "CS2": "0405800436b1b3e6f55b11dfcd8b024da7e129b880e0b3e84453838a2feae81a551c202401775c2bc0eb5bbae696fa2007a0cd294b01ac9f3d77d38565803a5d97", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040776de83ce9d8b349b9fcbcd96d3e8b63892ddc887177308ac5a6910e4a3abbc0684711752126c48c717598994bfff5ca0137b27f56f859e6ce2bad0a36c3363", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "04213a99da3dd5dbfb6113caea649b88a74f52b2715dc1b10b503168d766d356e20d10a6a12f1e95b5d13c943186260d8518138969bf1add379c7ff62feb943680", "U": "041c7c42ac021c2a73a4d5cd33b6272f3c0f7db6c48c5fa1795512e7e2bea907e408fb28309a08885f685fcefe9def940a97c94945766fc7e092581f2fa77dfd92", "SERVER_OUTPUT": 0, "V": "04027b4a7325b60799bba7b01b25adcbd6c931faeda1d5bcc16ff62efe128d385e01c3f4286e0878e272d3a01a1da3a1a939e52bebd702abcf566170dd30747f6f", "Y": "1836d2d57ff4d1779e4d8ee25418568c4b4d479344d16b2628b515ffd3397e7a", "X": "0f9e6c6eb24ffd8717b24978d0148443ebe1e3be4f28b2b8d755c78306a02eca", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 275, "UT": "0405d678a36c6f43a3b434e6e0c424a1150e8385b29463bf45c7a6d30faa98907f18e24d616700595335f018765e0d535b16a4e77b3ea3676a829dfa11b3ee6c89", "MS2": "159608cdd789b98d8262852d704c71e7891773a8cbd576360c1871b148fbfac8", "MS1": "10f6f4ad53e280abcc77894de416bdf41cb9eed035d79ab72b4b3e8850439545", "CLIENT_SECRET": "040a9e84c497d39c75b15f6c1baf2c0af1bd063000cde48d76902b0166d0a11f41025b069ecd082cddc04bc330c91c1775cc0bef72bb479a9ee8f50d6304170680"}, {"SS1": "09d7fcc5c1f3791572c8f8f893f71e0b13e9866e274e6b5d7265755ab79278e90da5d211a1f0fc45d9003565d89ef248de556327bf000f8c6739271f5c66bb241d8d9a548323749797dc0cca8b9d8c5f133428256eeb4d271fb152137013c8b50c614902f8ef40a8a23f3d09ae5b3c61b2c78cf27c46d2c711ce44796a22a3b9", "SS2": "1aafe92f6b39db35389480fb76ef1c0867e420c34c1947d3a65c72f6367db60e0b974cfae0e3e60da45470b5d96a248a7bb1f38f9d906307f0aae3ead3d0ae3616da5dc24e312a3062cc16d8b5fbf2b10685deba12ad2d43fa610df8a5e517df1426e583a624fc159ad6cd06d28831f8d9215921742109a3d9c0c52f23e708cf", "DATE": 16650, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "05193afa85f11b1d7555fcad5d0a54341cc88837b797a5d118c65199c0fad9f116bd8dbf4151304fe1487f91be2005889e29fac346633d9def859ee78edbbc070cc637ec21cd44c3cfa59c7d399e405b8aad2a1408524037bccd629e02e6f16f221f0d9c751612b429d7f9062878fb718eb5061f4585e8ba4b6d6df4718e0949", "SEC": "04084ab7d3e9cdc0ccf25c7b6bbac1fabff0adc5b3e4a9b82b6e2c6440883d0d9205d0d523c8fdc692b7872ef061dc7afda4659e1202321a00de0b59c125cdee9e", "TP2": "0406e226bb1b0ec301900a77eb212b52d4cdc11a9d53bd9c64926d8a90fcabefba14824be2a964df8dc8e739066ff091231aba2617bc6e1a2573eafe015aa7779f", "TP1": "0412119a697aa1cb3ae791d277afe06c7b81a746b646aa16448ae1559110c16bc21f817bc60b139c44c19eb4e5efe6a7376ae14d9b9bb33f3a320020fd956a325b", "CS1": "040adf0a51de6e9946197fe0c66fc22d2b7fa4d7f30ab3c1c47256fd53a5b9735011f2fd51289fd3856e6cfb6eee9f730d55a9d89e3be72e6dda890c0588dca113", "CS2": "041acae269383c98d48f2014c60edfb8567ee6d121c8f4b77614f8fcd2698162e31367ee1a828c402ac97263dcfef81c5c2a2d5cd0f42fe79a0a7f8ac7b7e6072d", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040d230340dedd4b09c3a8f522c1851ffea4097462bc19e2ded1cf26aecc3e399c1c2004420b8ddb9f728f91dca292752c89e36db7a294a5d18a0041240afaa1ff", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0406467c79e604e7fd389b4183574a2ab6206cea5edc8414934ebe6ffb05adb01c050626a7a4dfdad984db39006f1e12408f105d374cc37991cb42188d3773c387", "U": "04028501fcb4d224ef52755b5db77da7719263b0b34df58293c5f474ecdbac5b431bf949db19bd7aaa3a7c33a900036bd7f6b07af32e42da853af81a38b7f5375b", "SERVER_OUTPUT": 0, "V": "041203ce3e903a42ca9bebb9a05f8bc8b5ed86f02e51ddfe136e72bb32caa39439167157a8724f006b4d3f0e25882f8c23897ea5e0367c80d6546e7083be5547d4", "Y": "112e7c3c2c7b5dcf7265f65e24f934b1e19f3c56a92051b8a078ddde6c962675", "X": "1a9b234aa1d9969aabd0f473c9697732b02cb54af9b53f0c433e2b91dc7654d4", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 276, "UT": "0423eec0cb97beea3322e1a99039c504591b887cba8e1fea6ccccdb303c5f4a3f821582f6356423346dc344716f69454837b96956d59ba777e3f0d35c544979e64", "MS2": "1d8599d24e88b857e2eb6a52862a45ad3afa81a51dd3dc1ba87cd015a41e4af0", "MS1": "204d838c50bcb19cdd064acc8709e84f807ff1cf14e4f1161c04bade390b75fc", "CLIENT_SECRET": "040efe5d83bed0ae06acbffa772519065a29ed108bf0827363bd6a697fc4de24f51401b54173a02bcc7437c73ea1b4b5732d4e44e9ef7899189a99a4da0b74d6f3"}, {"SS1": "1749cd04c879682918235708429be8f9f89371a9ade48fcbb1e96acb6009814d0767b9ea1c1213e5305038a4a41890ec86fbe955d2e31123b18c474a6e44886b101bfb4895baf0401e9f13ef1138189627fd76be50c7f078aab1bb1565f47b37204e09b31b6663a1068cde345b06be191ce4a5e9308391989571127d4a3f9553", "SS2": "187c1341f313c7b355a074eb71ad9b9d0bd93134e96d0b5a5940d9b3107d244700d9f41ea238c11b849b81cf5ad605b24bce4ab724551315388d93975032f95c045ce5333bad5d65a418da811d961837a36c98ddfe3e14196dfb32f828c0a3e30fe0e03af5adc12c9df073dd98a48e7e46daed6986ca0c5e7c146c2c6557fe1b", "DATE": 16651, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "035447f241cee3a2f4eb0c8bb5d2dc3804f1bfef491a85ea3105bc9d154b1f0a1ff4cb8e682e15abc003a548e000ea6a987a2653ea3d05d5c68105eb14bfb9490178179fa5caece863be8f99c4ddb68b95b2c8669a8d8018009c5e71ed785cfa1c6e6c718bc13820bb834a3d517c5493eec551d6109a577a2d1845501babab37", "SEC": "040c5944a82bf11bd730d66e99bdd0ec9918e8755a199daa84d43a9f4a26cf90881629a07095780d3d88ffa725a28056401b48a4fa3afb4c8bf3d005d06327d33d", "TP2": "04114ed05f8351da53edf14fdbd60c6d9ec45c2ab968e8ff019cb3e3c2d39668e60b5c53f4d5e7f0be25916f38d72741b75e51f1d0e19ff715b202892353a6b8cd", "TP1": "0415acff46102281f8db9948badd9e32475fc057bf41a329bf8c832177e31a472c1bb2fa86b0c44dae3e1ed790378f713c615eb1656713f5eb14c85332b5e94817", "CS1": "0402179b841526984d0d7fe36155ff5c2784d7f5158937dca9f43b99e21c3e47c921b0765596f2ba26d73f1cfa57edf90b723124ccd6ec175eea3f148b79310928", "CS2": "041398c3d21795aaecec0236ef1a5a88f215c01026dad0c6d5201794cf7fb7126b1d21d014af96b975bcc741d40e89209b7bbfc26f03b65e7af03a02c6ca6c6dbe", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041a2a268733c0f6d9951741c93b185d3270a9c21c92c595e78cc1a113519c3cc51496bbdc79b5ab9f0fd2448424c8ac1c0ae6f4448ea6de6dd0a8a837342e690a", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "041009222f008e48b6d234ab685e248941fc4e189f6fe9f24feba1f699346bf5b9235113d02d19319e4b91f136789eddddee200abf7d2d4772ad67c5be6d302191", "U": "0416f0d35bccfd27553e85620d3dfa55329b24fdc217c66ce8a142bff5d2ea4f42014e9d6a06014e0748256a32f1ef015deb36a3df04d76629fa3d31482b7bd7fa", "SERVER_OUTPUT": 0, "V": "0401434201401d46c82d8802fc0c7a2b7c20e33c765c6c873ed7d83d312853f8940595b585143469ddc19fddc1728adf28007da303a90a65c6815ae22bf25e4e94", "Y": "0a4c9541009e3e295eb1a26a8573dc9e36843451457d1ffe8c829586cd8992cd", "X": "171f2ae98aaa4ecd4c687fc88ada271c1962ce184e889ce56f852719fce52e68", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 277, "UT": "041599c39974b5aba8ba487d919e706ba59dae542d8bc334103cc80d2eb1e1855014772ac9754cab5642f984aa216ddebd9e4b74367b6919515041e86075a8735b", "MS2": "0f2a736a1b3e291e181e9735f398010a1c8f48b86d28fa44d8e83e868e0b88ea", "MS1": "01394d5cd97c78daba62979c5003b660fbfee931ad010e089f0ced46154dfdf7", "CLIENT_SECRET": "0413d7c252fe299b01d160249efe8fc38380c87595bca096be2fee68ffe92278c70d9e5f8a672c44cf39b21fc10d0eb075a9e095fbaa07a752b4656280c017964c"}, {"SS1": "17078de6485ed425b4d0c94a637c5ce6e705857edfba97a76d45731ce6d6246e23c3c2b66427b05cf197ed6e059fde0a698732333a1ddf9732464244d6752ee011731af883e5eaa07c6c82498b338650f5773c155432a6fbd51d6aed775eb01d190f55542b11b35a36f97d927436e0da4cd65873f0e1727ac0141c3c5023d580", "SS2": "1db110989ec07a5d42be687dc477a59b617f34ec6e40c3cf9da3e32a988f9bd41b33e01d9b29cf4116500b9a674689674c78a98280a74a034d79af55712d02e716b3de9a25cd41eb1cc1cb85840f4ae821a9d8a8c1c00bcf345efd9bb5f11ac50717739756a798e3bab67b2091171f2041d6a14f745c4148d96bcc81b58b5bbc", "DATE": 16652, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "09269a95dc08c4ee1b9204d9d4106a53c90bfd2d9789c528e43d8891122203c1198067c87b1b63d6eccd8a50dd26327b17a3bc20ddafe1822a8a8a72460e4cc213a39f4471609e6bb16b505c141117d2e0ef4581d6480b328a36a401cc10403811a377206188a051bb5b57960bfbb7980aa407ef71f2cc88a006b305a510f216", "SEC": "0412438f88c41ada988da8fd46afcd5963cf91e3c5c69cfba46a0e93ac53f9e4502275e7d842a48f1485fb6ee70ce6709c5684b64600f6cd80506c73d2f1a5c28f", "TP2": "040b2ddfbacf1fd38c190edfdfadf3a9c8d5b12fedcc4a6e7ee0acec6ac7d00ca0015271b5c34b5d1f5b8c1fb0c8e64a19a13f6451f08ba94b10c6d23503f3e8ee", "TP1": "0403cb3b8a36163a42faf8e14259f51a3f9c54c352c3452342ed79ac3576acf63a11ea70ca0eaa414a1a7d6a4e528157799f6e5f1fea6d98a84ce113ef260f024d", "CS1": "04124d54f8f4718668e27e54df38d93b85601500a5889f3d6c75661cbc549499be1796e0b572c3a417a249a505d666b530245d2e3344776c947cc8e3096a9ded51", "CS2": "0410da863f06f302bf543f61d5130815f97623047b7af03b600d612999714eaa4818a907d17a712b6d9e0ca87a32fddc05afa0145206f327c738f153646b4e2bbd", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040e25f003a39e0f5458cdc9ac6a000c6d4997b7be013b723e34c0ac2dd9dcca1f04e8786c2288bb2a2933b01515f4bf6d493ed4854b7617cd2fc377303b9e038e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "040c82b0531f8c5cccde820d4e6664ddabe08c799abcff44d7fbba5a64a01c80bb198d2211a38c2451a12aa7b5253240101b817018bbc4cec752b0ec9555fcf9be", "U": "04004700e9bcfa9071c9c8a2ea992fd47585af4f9f647216f71c300f0c0118160c1f53197c1f793ac8aa5facf05b4f63a25b6eafae1edb0cd751499864055feb06", "SERVER_OUTPUT": 0, "V": "0418338afda9621fbfae730c301b528f899e38f7572da1c84ac2ec87640aedf35806da1c5a7abaa9d5a5a3af17cb90820fd6ee08b05d38b32890fd559c104e145b", "Y": "1fec920b0ebc10c7bb56706d16552b292f29d3bd3fd61f37f6fea35e7d8637dd", "X": "09cd783b92e35155654be6517dadff712299c72f30eb0b030f47a7f176d5a9bb", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 278, "UT": "04001b584883a6986d001513a7b55aff3f96c896c85d65c984a5b674c3b8cbea9403ee8dd1389765c3835a1d7b544d09488942c3a534f8fc238606875bc16030ef", "MS2": "0a653748bad66205a4ad21dd53a48a2ec94d0d56052e17fca99aabf38c260e53", "MS1": "1d232e3b9f18506bdf9838c10d68d8f4a01158367b862b1931a1f949ae656bf8", "CLIENT_SECRET": "041564acaaa1e97eb2d13c872b07dbe0ed36fee51a7f3fef6f934b2aa81a1c1fe220895a0be6dac81de04e72c9aa4ed0fe437c0b38fd51cd6f304d42528c5678e5"}, {"SS1": "098a03f1017bde7b88071a28ec459db7b15358214f1abdbc02ec49d8b74f8bc920934c5c101480b053bde230b3994eeed43f3d227a4022110c987488be50e69f1fda062364b77aeefd2e69d99053c5ef4b89d4b61916366f91a1a7d8d347ede410ac6860194953e97b263f37ae477f24fb18af28d16592bad77101e9441d3d8c", "SS2": "03291400bc591c2052cc38d7912fd4f601924c29f3769a5b1600df339d1638c019a081a84ef56738bf0f2403cdd64b356163ad1f11879beca637d8d1f178eb4a011eb6f265028dfc5422a85b32483084b7d710d7be556206abb90304fd160a74227e0e1159ca8e48fbbb4ae1379af58e2fdbb9ef7d510dc7ca7153f0908999c2", "DATE": 16653, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1c241cd621e9e1b81d3b89811aebd96de22d511ffde7f0bcf83946e5c64d28d20d4546bf39c2103ce9bb6bd402c58ec9375c99138441d85ec0d30d4f0fb8e4df047687e4c7772d65dd90d8ce3e2cf226db53c64e6ac9f9b961c96c656cfa3b1a1d776b3e9d30d78459df1fc407842dcf86a07ffdf2c38b9e5bba7c02a30e08f7", "SEC": "04119cf430332acb7b65040bb3a79020b34cebe982d14cbf962a8eab905c963bd11b7f912875dc96d75ebecd07b13ecc06a8324a0cd3cd7515329864ae49d76281", "TP2": "0400ad65dce06066442afd7f5991ad0fc42b68b2757f2897073bc49920128226fc22c53d31c090654557ff129ca582d68c057a5251ba660e9623209e61d69c8074", "TP1": "041c6c247788aa8f22173bc750830de8b517dc98e273b6b10953c5d91164d8b67013e769108db9065c1a67ba9ba37f2a5281dd9e6be08721837d2073c016f41474", "CS1": "0415c8b2d01c0105c46a50b304ee027c6bac15d6b706c505de106c0447e8e9281318e8b575eb26f030f03cad023beb3de271b749e2e28fef97948f7bc10775270c", "CS2": "0423544e6361a3c4c4d8ebea67e574e31a80fe3236ed85128f52cf0e84bcf5ebc60729388097a4589798b08e625d73c5a17cad1882a71601a2f1933865501344a5", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040fa7f9164e3821c182f0b296dc3be66dc6f3ad6d6b1086fb5c6e88bc1f89772e22345d9e63aa6e10625aec6407d24da5cf0cdacac594739a3419b0b00d7736b2", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "040a49fdf8910c8b68da17090dcf496af8539c0575aff2adb0618ee1e4a58f015913b1ed90d595ab0acfd37aadff27f0bde3232dfa3ece3c445e8ed51dc95cfdc5", "U": "040e71fc236fd35d4a1fd230e96494c441a0283f69b960321e764f6b1f70077a5c05d1db02163a33bf4484b08e65ad100dbeb89d49cdefdec2d52a945b77a3d33d", "SERVER_OUTPUT": 0, "V": "040accbbddd47f32eee93008733ed96dc555a8992551af3941e9ddfc4c2c58e512076cdde3c5c2108749ff4c67939c74a1f1cc357960a8080b63c8005c2470891c", "Y": "0cf462af2b554e1b7a1fc779452d3b836c9d8ece8f38b7b5955fa68953383d93", "X": "13f40bf283a22c0030c200ce6b4b923ca877e25ed773ba91f2457727a23e50b9", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 279, "UT": "040b83a0705b82154ffe43a284aaee88d3fce2202f7a0280afbb07fc0586ea43da043a1f320850e0dd7f16651fdfde1e462a5119095fbb2ce22b9138c335b80a97", "MS2": "1b465ea4d6e2df89a30e53a784fefa6f046d904d4a647f944560abbd76f2f5b3", "MS1": "091ed7537c5e392ad61c46beb670ca73ddb1ed7f3d9e2c1d6ff1931685111022", "CLIENT_SECRET": "040a357bfa74b2eda1776beab2ef3704074e6fb360728a800a40a97053303ce53a12da9f824119327d778d0f87cf35446c82b12e123199b7d86becff43a69f4176"}, {"SS1": "027c43e30c027713fe709b8ef21d2fe223ed5a2452952332a2d7112f7b392c2b155cd46cb3ddded8642318ca680092e70182b8b30f1d847b33bdf514e4c99b19212a74e9ce21d9cb4db2aa91e2cb747b2554a2d828c8876c93fcc6985e47f3350fed5c470d38feda76c76958a7fa4a6b54b768a2bd5411ac18635f72b39b9f7a", "SS2": "12ef73a1ea9e19555a00c2d4af22fee88b08cc45b52a9c9bdf692a812cd52b93227dcd11a88b54764947ba412080bb1fe7f520fec39df06a48bc88df32e92efc05529fe07c3352391281b6079ed00306fd8a0c010ac5e7ee1cc7c52ada5cc98b1f79c38579d81297994dbecf9618e591f3f506b3e517d11ff070ef69fb1e33ad", "DATE": 16654, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1ccb5b11a2315ea07697329b0864558a3ac0b5bd152f6d06b4d69d6b202d6e8507cb559a4886d1ff765e5d4c8c59487636009a4af876363ef57fc3b9cd0de3fe03419d59dd77ff5f661bcabd647f7ae9cb31f64a18d0fb10681c23bc40d4e96f0bbcfdc25afda2374654866d4751401353db6df88dcf1c5890054c20100c1992", "SEC": "04239e5631be1c961cb2a3c7e80402af2789009d2cd1c106f5b899c918e74e3b99025960b1ba0e51535b04782ab1dd918ab06b4be1453014fe0938204b90913bef", "TP2": "0414f0119a494f4836c44c3e463c59b9d91ea96933a238ee167b7be7424f76af84056fd04e6f63bffd020f1cf7646d3fd6247b13ddbc33e2de5b0298ece9573f92", "TP1": "041c350641fc9358e5e7f5b91ff7d058938615c2314512ee5476d5426622f9c2d81eecafaaa4f4c71bb471082e41c9378af1d6859f556a18edd642c7ebf5fa2bbe", "CS1": "04092ca6ba46fe921e8c3f2ad376ace4e4fdb564457c4bb1831f183a55a4b307f919be61da87f940043acbb8dd040bb7fe8ddbebebd3747495900ed1376ab6bf0f", "CS2": "041c52df95bc279b6c6a8ac93674957c2c69c2a35b341221e58e66d74fe163b552091013060b30628edb83deda0c15d89cf60640caba5f94b51a26e37cceaa3629", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040d7fb083b3b09b8b5be14c65f9289cf71446eeb8446f311688c4425b6ee1145c1036057413f01365989e27a1c093be287c6420809997b8e1399709c6c2fc5d8b", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "04231a8bda180e6e32559e992ba7b2d261e66ad7f9f5363789d0e3e212a097f069131f288ff20b87c6200ba5cb2da8862c7a7606547fe8ed473b0d61d68e814b42", "U": "041e7912f2811f3f2640f12d5f3f9b52600b8472710f09cf236dffe67544e799dc0173f2fa0be7f1f127f451fec444e18fa48c866ad016b19b86230ff812cf966a", "SERVER_OUTPUT": 0, "V": "04139fe056c6138377cbc8309ad553253998b7e48b7ecfa9e9014a0e78343e014e0ab2949bea0914d60d8fe23288bfb04e78c9fad000624a7f0c8401512ffa63f9", "Y": "14b3a511dc2460c8a7bbfc9b3ab6acca62f59ee992bb9a3d54251a7f4a7277ab", "X": "1170d33738b47ac4ef7711d6bac9b55c87dc397daa71c7f9c49b10e587c12375", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 280, "UT": "041fdc223b537529e1fd2c51d7e9325e75d93ad9bd56acb85fbf6e317f69e4219416c685364ee7c062de3cb1b4d532fdd421794018ca9b7aa00307822e24365806", "MS2": "02d168199953ca551b4a3b24989ae2bb8b763aba59dc67a6c03e2311d345703e", "MS1": "132eb1a107faea680f137a8a5db84dd509aebe341f69d0f12e218eef3be75c27", "CLIENT_SECRET": "041aa486bd068670c84088b254ccc02c3a1997013e1340b6058a934cf1facd5f7313c80f5fd2bf1f29b1c8283e7c5e911efb333eec4a1f8e02c0dcff2b6d7cb55a"}, {"SS1": "1a72c166ec451a5f3d01f94c6d108a46e25cbe8b64ba4704b590d2e5da2d4ce311d7e4fdf5cf06bb7bb80690b55f4a32a914d27c50f0214fb18ee1d85f6fd97f14be0851d6a6b38654722bd52e19a6c0cd490f666e578a7e89ca68e78247b25b0b8b8a184daf8ceac660f0344d22df7269561bda3d876062d696e7e8ed91828e", "SS2": "15e549d0d53358b081d8e395a306da1f48b6e4c6c0c3ec95d987619e12c776a70d61853a52f4d1d2cbec8e130e2f9a8fb1c007acf635cc49d8557568174cf5011925e78bc436212956c4909eb04a61ee31d9ebfda3d43ff787ac46230274c44c05b30d79b7cbf27fc9e9570432f4bf9fdc368d49433bb3531f6f91620b1564f0", "DATE": 16655, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "07a3e0950c29aa0bfed2158cb85572ec522cb8eb4472ef915089812ebe58738b11824a3af0f23bb562258aec31025927dac19f51bcc11e5c71a351c20c8b5ef910f35108b219680494fa11e1b070b4aaee8502c0d46715118c79a31fa21b230e1b4eb8d6644312daf8f83feed2a5f34265b4e6bc4f1dc7b8d0d7fd50cde6218b", "SEC": "041a5b98e69a2c3103eb4b5cc22c003a1896d3bd0744ee404f381d5a7b5ba7d8f5234084750a0e5526abbafe3dfa8c0c9dca3db2bf595c4020698d76e10ca2a8fd", "TP2": "041cf706abd7f8bfc56375d63d7d74f1273b541074db4b54e74f7e7b4b2c96585200237837e18adb56abe5273e5b63751eff2c71a2343e0baff24ae9a907d69b32", "TP1": "0411e4dacd742a933229e91f30181d84c768e34cbcf43d486054dd7a7cb0dcb5c020890f66c27a03eb4b297a43735390f531cdfc2593799784bdfea59d374795da", "CS1": "0408e99088cb8a2517d2b3bd38ef6eb9566ec8e6061f11d5e97338ded73aae5bf70f2f2a50b8ec9d02a0cf3c8c7ffde9fd8131fc584676b9f11ad34fe85f93d0b9", "CS2": "04098a2dec07f50d7601c909723dd52f18af8f4adf58b2841dcb5cc28b19e66a770c0325459e1e40fd9079e3f8fe995d2f685edb8c420cd85edfe56736e2c915d2", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040b894bbadf7d5d15fdac812874d5acec5620d10fd051f8c568f293feb8cfe39b1b65ed9b88cf6216e06096e84fcc9d10ff845f94f06f397eb0019a2a2313f760", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "041a04f3594a43c22a4702f7ff8495eba65d0e32d6b4e222d7d75a2966fce60d900033892589251e8a546f2725fed668ec0b900298d236435a0d7d23d1242075d5", "U": "04070fcc7a20b6b1decfd9842441928f0f3796751a0589130b9faf9bdade5798d31e94264b4f699e7013ad384733bb2e05e15424caf8c435e3bc9a73c498195e50", "SERVER_OUTPUT": 0, "V": "0402c4663fea5a4f25d01813c4b25729e96e470dcc2ca62c8b5eb4ded1de241b2b037d25a8e5923b136f307882ff4b5c7c044cdaa0ed974c9ece6bb7eaa35c81b6", "Y": "040f562d67f8a6f8e115bcf75ed1b6deacddf240c14d691bafafa5a547caea69", "X": "22cc83c8dd42ae8ec89a70de50aff6cbb2589ff49cc220387088e03172f06525", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 281, "UT": "0404108378365dc2d088f5e4140b0391f5eb3c903a484dcf93e63505a9ec5c081c20716e9d8618cca2b1472f26d4fa9fef6dd3e3bbe1663591e3f369fe5daca5c2", "MS2": "008915804fcd144861af458bbbb17a44b7521cbeda7e551212b33d2001463ae6", "MS1": "1cac26e22ccfeb10dbe3f32531bf49f2f16bf77746648ee479ce0c4e5f77a5a5", "CLIENT_SECRET": "04116b969da64499f52b208c275c56d10e3727db819c2a2df8c2124203778a41a7111fbe8c3fa86c83936d056bdde65d4ae6771c016dea67d8b434677e7279c433"}, {"SS1": "1fa9e664e0f8bfe7cb2c8200f440589ac44e1b0c3f27d3fbda0dc32b6d3a114a12c4c83ec84541bda6c0f8294dfb0768485e96cdb7b2cea08d2561f4ef34242d05c6e6de4f4019406dc311c61c28077ce9356525a62251ba575b3af7b8e9871b014db761ac5ce26d5c2d3294ca2edf8eca0595fa21e45f70f1d3da4569e0b165", "SS2": "145e88b0079e7fc034468aadbd9d25bc9205c46419ac128fbf78e67eb05187ff10b3e90e975856554c3663898b7141b31f8884d1765ba89e7303af1284ee319b1124c335905faa0812bf43a3803f0af18e42587b040a51c13ff239f9f26509ca1e841ca7b907c6e86f72990e05be4cce132cde2b28690671a41769a7651492be", "DATE": 16656, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "00a72e18ed299222dfd50b3b3621dc1c290aa2ab2bc61398a75d368ae2b123eb1a07d0711a61cd8df63d3f2480bbeba14e1f43d6e06d54327fa880af735ad72d18252183782045c9cba479aa1c6b86cff37190f6891bd9ce6316d358afac1162134a2f1a8e2a2d6a8cdb9380eaeb6aacded5aacc2ef9f22c765d2ff670f0ae4e", "SEC": "040c119b76ac0ee225fa963fc6d9acace61d3f8181db9e6f6c205019ed87346a571ea618a0b607bb8e30263f8df10de0d60c01d66489ac8ef8873981a40afe3b5a", "TP2": "041cce3627242d56e72e3e469855156b4391a5f7c524a624c54fa31b0277d3037717ed7f9bd03abe335cc0452c185d22ea044fbb0a7647039d6d3d099a342e8a22", "TP1": "04101c2e0c1f397d5be2765e97be2a3b473b5b3087385f63d198b07a4e8ec201661957258ccfba1a79707847c8b6a6b1ed39ad1a913507de1d11a735ee372642f5", "CS1": "0414da33624cac0a6ca522cf4edbbc3b47fb6034df698d2a05851b4417b58da35b0f18beb314756826bce39d947c687789e0f79512b08c997bea71813a9890bfaa", "CS2": "0414bf0aa19173ea6e44b1ecaa25759f1305c0f033c7cc85d69eab2bad01d1e0340f73d20df7e4c9c6dac126b8b1ab48fab6366a07165f27a504c0be38d2bacf5a", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041dabf5e58b56e53eb3266ea06133876c2d0a829f9d2db11a7fd89cc2ae5717c300adde1dd5fe6732fb35aa85983cf79864bb5bea1a8f95ffe4c58159bfab8724", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0401360a1326a70d20c087cc7fe19264ab0cb0495b8b183a582d0c90cd37e61e5d1b59a6301c4057edad34755302b7ec5810ec1bd779a89ecc7cba779c29201990", "U": "0417d2853557b992f29be51e77e72ab04afd5972873c8f03cafdbbea286f0258951beb6a13c9dd3faa26bfed7d7f65774e692206b13204694fa36a2f14300df536", "SERVER_OUTPUT": 0, "V": "040a5eab6c1e4bcedde9358b40dec8dd6b9427491cab9a3e8184f450151cf9b5000e99218d84469b13f9ada4e14c22b7dc9568ead0ebaa58526bca993eeeafd3e6", "Y": "15b28343a6395536ecffbe331a50cdb6b53f38c4e5335e791cdfcf1c691286a9", "X": "02923d603efdd5f29a2a7bd4401baedb2d5b2fa7ae3178126672916086e08014", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 282, "UT": "0420f28a1d4001c257c55c86c95489f5fb85310d53a642032583687b600672c05d11a41977d947af5b9fb14d33cb9b8f5505743322f8fc8227d2318ff3dc36bd0d", "MS2": "0c3f8e907ac0ce3b64f0d29962945b481f8fa244d21adb5de3646567501a1630", "MS1": "17a0f999b89d533b8cb3659fd2aeab49b43e0a20b3bfa8f8def0c746bf0ed82a", "CLIENT_SECRET": "040649d76d1ceb0131e2a8bcb201b8b43fe8bf2bfc89fa654814b31c054562ae75074ec1b55f9f46311c6ae2cc11fc00cda2ad3cc2368813a856c4c1831557a082"}, {"SS1": "128e390086428ddd3c0941f9c317edc33d9cbcaea470b650661a41b3064deea40f1cfd8c6d18f82ca683f3e1b4d2bcf06c196605df74bd3efaee547109b8c6350aa74f9242dc2bd6deee308000247b565840884c379bddc745c6948b1b8902151b0d7c6cf5d421852500706cc259223fa91296a69f56a70cebb5ffae2d9e8182", "SS2": "175b63e36a324e7c3920d2e42707e251504f043268766ed13df74a8825595f2a154126f75560e4d89a153742977ba13caf3c798fba870b2bf0a69dc7e07167e91b3bb2036535cd85a7798177c10e86f176eb23ec54e4e0682d56ac73da1078b518ccb9b82ed8e97fbd66c7d9b9d243abff81da273957daffbe7eca864601a00a", "DATE": 16657, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0e48d302c9e7e1c71a9cc65ee7a4b8c905df7850c58c5e82c58562a6b2e922c51f55762ba7412ce0eaf6e2aacb886ed2149075d968f89d006cdf60f485d977831d0c85d5884176a2f9580ad43cb02fcb759adeac403dd816d5a9cee21bae67ce204a0803756e8f565bbc3d306d75f91efc04fb1be46813bd323a2116806b9b26", "SEC": "0412995c68357c0d11a42d3db09793704681c6224ef0d366184911cb4c6bd821fd19c2849204e633c75078cf4cfb6057850faf91f1f021a516719291f68b438332", "TP2": "040d45863019fe04fbc7eebbae9499f2e996f8271d2897b2f916c10b2ff601b12a05c254f3f127a36524e3d07b6be4dc45877fa5489b8b9f403908f42c68d5717c", "TP1": "040fcf9fbd4fdebd4eb7ced6e04cc7ab17457d51b54c5a72a57fcb4b684420ecfd0ead66bae4fd4d8dcfdfc0f8f609e7d146d58c21f19afc9dbe67c2fd0eda7ff9", "CS1": "0403c9fec4d96290833f4d2efb6f9f571ffaa50fdc55e0aa070c489a19e5a50b6f06893df4fa1b6a85113ea98652bfb6c93f7b3d9dcbb4f185ed3bdce61b085bcd", "CS2": "040b36bb17f8ac34ff4de838a309d938995d53667008055d1e3484a7e3a2853aa116ed6a20bdef0af9a43c2b2e900a479945e942b2c94f7649e73019f7f54f7bde", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040f27d6916812d4110722bd0010af769a339bd8b4e290a633725365ea2c7a32bb0db8351310d464b6a90b0e9be3804f4ffca438ee26ea8aad9f4c581c7bd707e3", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "041409664478ce6fe5e0b61d3c64e7232a24e14fa07084a18a9c9ba69f5471a0c50d900566dc3561fce8d0694372488593f8869edde3e88a66ee2157513dacb3ae", "U": "04082dfd5a0e11c47bf82658a50e33ff14ee606f3d63247d5596ed3cad56f50b521cf30b0a4ad08c4d818755ccc12b3a2c3297f9e81ab874eb99fd523cbdd2d8c0", "SERVER_OUTPUT": 0, "V": "04167e22c1f0670164f9ec2d793e280f3bcf9232962a032175015beffa1bf9d09a02022a33e85192935897ff9cfb0d6df8e97b7cacef0f17d00ee1a2cd4d0a0c2c", "Y": "0ecf96fe7de8f3c539bac51cf99ff641e6c2b4832899053acefa5e1cf0423022", "X": "177e60625ace94545e43ab10882c67ce27f9fc0a239ec4b1d9502d7d0038c451", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 283, "UT": "04237a6af3f931e39172f207e3d6efa14bfc313a7c4a908be583d054dd04d7c2cb1039f65c671dcee1164c07a70cfc3ec235c14bbe307a3cfdfb6f178b54a4b2e6", "MS2": "0cd9c1ca972933596cd476be0d48f70886af5d9e064e342ae9efa12150f74e20", "MS1": "0c3cc81fe8a2abfc69f3ea5cadcb89d9938dccf4b8114c4851e8bfd673ee52c9", "CLIENT_SECRET": "0418ade8af2331577ecd81a0462bed2a27eb8aa71e34e2e0854f959becabce941a10da98f7cade401e21e774abe09397ce6ec726e153f92a13612c692927dcc0b7"}, {"SS1": "1b9e8e9ca7acca9579059affb4aed997ee47345f7def7e47f1d410debcd477440b7c488dd98e5be3cba5ec90c65bc5ad974c03942fe4936c9378e37d6d9a418e1c9ff8240b3353dfde10851fd1fb41190b60860a8ffb30e7116272d6e6dc2bcf1d208a72a83c89e54e3928fee6b087d3f6c0fbb2b67057f7cadbcca1144b653a", "SS2": "024dc83de55b7ab9b21817b4b75972ea926017b1270976b5579b921727a0957602fe6351b2a430c66d91c9f8e7129ac3a77a59a1dbba8bc62e751d4c443aacce2155d7b7dc99d789bde23a104160b71d93fb236ca8c298f9d3e489f8dce8c02303dc383ef693db7a4c7407b096e0546a8f6bc964cd9c0f95f6f4ff44e54a6689", "DATE": 16658, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0a41d5c420878405365ddd080efc54c80a65a0b1da3d456b824769ebd52b7ad712383cde36df6ba79cecdbc7c6e4ceeb8d5ac266ab667b6fb58a716bd0c4291722fbafd944517f4b47437ed14fefaa8a3732dff4605cd2020d977955c5b6024a08c830858e8aefe8d3c502f6b661257f26e5189ab1af7444d0d73b68339034b7", "SEC": "04141da15bbc32a198b0528da088b86b86ef5c7b3d6d6c38539edeeb0a42c4d79415c96110d9c9d56c0099f9ab9edc67ae80157d8833ce10871a03bbda93e52303", "TP2": "0414fb8738b6b04dc3ddbb96dbdc40ded89d00a0541e4809c18443f73c78090f881cfeeb6fb008238c9817c5e42a47b26072d9ee8c77c445fa860da65338bdf55a", "TP1": "041dacd7ad268d3e17dcc88325387ebc1f320ef02da5a9683bedccad1475ba0cfe1c367d428fdf108e45be4a0551006523bc81e9934ee14c70e92de30be6626380", "CS1": "040a6d087b3dbf735e81ef30a3af5c00a87e447b900582987fad7250bf7beaa8c31cbce861907f73e7f90d06966a758f8b165df928d0f75f584a2090bff56dc602", "CS2": "0418f63591756a11ed0a8b7e75fd38fd772c5f3f1fcbf3184b78b3eae3ac77595415675a1adf02fe93d0a1c67defc342ca0b3f5d0a8daca7f678cd2af3704de831", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040ef187712046fda3b549dafb6b9621f499f1596297c7d8962afb738ba8b7cd4e2254cd78fe2da8672f68553c36b23df410156a2013418ff6008289a6b3449384", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0405f038ccc87402795cc0ff62d991a189035fc979a8c140740cb4de8d4235171602769dd31c977a40e59d9e1cafa066fd4db554e025a6753ac66aa09b93e90883", "U": "04208e48dc095ea0a6f54a5b3117f952a7adb14a52a4e989243628a1586460df4f1cb698425ec383d026eef9c7d71b8fb4f89deb6cb2b1293963286e740a64c814", "SERVER_OUTPUT": 0, "V": "041f8888d5e104460f0d391d4f5a4b7ee4168cd0447373fa4da468e93bbca50e5a010a412595f1836c214c881d6677001af04d2f29767d645ac0ceabf077bd14e5", "Y": "1c3f7862f83b65f39eefddade55af4903b899b4a37eada3413336d46b829cdfd", "X": "1291f2948c576bd8c6477381290e4fa2bb27d00de3d64921c9046824e38e5b43", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 284, "UT": "041514221aa2c7ac3efddc49006b693b63a7fa1bbea22dba5d2c6c285464e5c291057dd39440c8ffc71aa4ff1789cb57aa3ec6908e3326ed0d836efd129d1ce3dd", "MS2": "1f2523b7ea24e9599bd5cd8672897143af5356fa40c2a61ac7efe19d3b6cb10c", "MS1": "155506f543f0172f6e136a4dfeae6bfde0a7664b98c11ef44bbba7dccc243365", "CLIENT_SECRET": "041a29781721ef8a4b6d163604065ef1efc9d04766fbcdbebade423606b310303105083cd88e3f47c22870129fdbd7077af5072e6bcb51bb0d88b8a9599e743fdb"}, {"SS1": "1ea9cebc8aea00f1250e9b2128f61031e13d8d07058635d41c84023c5f98ca7c2056d2a182e43dda116da1f130da01a223cb621ed6de624217742bda6b4b84c1146c9439ebf96719d6ea96da50f9e9138c84ebc5e1789f62da04abbed21e318d185b270be4d8c57bfcb5b1b886b1645ff9f4005b1be9f0216f395676b6c6a60c", "SS2": "21edac7753eac7c193c3c69848c836717ce73a9d91bd42f1e8be8b56e6e718110068b2e5c4c630c62c677df0318e662c6683e3b8b29e8d4b5f95dd13e35fc8ea013856826bb28398a70efe4ffb8b35fdd08ceefd57412d299e1f5f1aaacd8cab0a1cc9c2103d9d570746ec18d094aa8515b97dd0c035005f270e0847a32ad051", "DATE": 16659, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0a73aaab486ca380f3ea653bd6ab1b1e49835ac9cead3074decf41ca387d4b1d0730ac45a323b82740cbce9dda73e16eff5edaaf5a6023a9bd7131800f00d5c71d8a97b09bc4fa5b4888524fdb253e0980c68e2f8bc49bfdf825484a8eaa34b91b08aa80b978fb3f6cf667fb27fa4d8cdc4dc6cc12933c5f6d95de6c9c3d65d1", "SEC": "0419f57e730ff9ee8b0dab1dcec098811d5678b6dfd32c35e481b5d21d24f7abf810fc2f17fd5a7d10a5a59fc1246a1b44cf8a544145f05509497560a2dfa7cd73", "TP2": "04092ed727974a283e68ee7b7b899cb2b569417eb5aca1e737a92f769573ead6e41fc88d60787c5511569a18b3a42d3deac0267c812cf84ea64c923f202ff587fe", "TP1": "041a43aaa321d6803b1324f6570eb42b3dfc85127da7b81d884749278e2d1f6d7a08f1389a168737e47b84ba2a7cbc90469663a36b33f70f70b1a8bc930727110b", "CS1": "040c5c8c7feeba060053dd414dfcf937c60d1ae0501ca684a001283b87604f4c74010cf8b7fe18bd61c16c9826509c554f4ead5769d5d499c196e08c46a5085870", "CS2": "041f6e5585745402c8c90a4b2a25aa348565249fa4bcec86c617153ffc2f38fc3a048de81b4d455ff6975c6a6aedf09363f888e800068732da282766ea3f14595a", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041bc8bd1ee9569619d3283fa755ea2201c130db494b19f6263e9286144f3e993806242af10daea3249ee94cf39458de62d103a19e0f7e807a6e6224b837a81c01", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "040fe8144801bec8b5b527cf5188ade15fb4ce3532eaf8ba43395a7ef0500b07e71d55f1c6c9b82cc08b0842620b8d0010a4bc2cc929f7fa2d7918882d67503231", "U": "0403325cf3fab04e2718a289b5d1fd69397cd52214616a09f19591c0a10fa16b681d2ab06e9bb681c52445096bb1f9b9da4374b738dbe8a3fa5ca29b1df7c1ae6f", "SERVER_OUTPUT": 0, "V": "0404f7dea1f5f582c1abbf06e1e72a386e5bfd835333abe6bc922d3ccfd6ba112309de248b3d5f322d4802b0ca44cd52f41939dfffc41a12d236e9d088fdbf6e61", "Y": "09e19cee68235653990f306d2c2e32320f58bfc6f11669aef915c02105d87399", "X": "0a839648193e05d21380cc6da88a77d437c4e108032aadf7f41785d94784a284", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 285, "UT": "04189bfc12cedc68af112dac5b45c5428e11b1bdfe4cca3759f7d9d79c0e9500c0172b0d86f619f473e974ff45bae34c64b010ae02fc38ce13cb8b788bf06942bb", "MS2": "176aac0b8c0b47e21d726b4fdaa8eef1ef5b3a6dd81d04fa3ef5515a4f6cef9a", "MS1": "13ef79a7ffcd9a601af4b8a70dc5c84be7f1168bdc7be770025b9741e8866655", "CLIENT_SECRET": "041c07ce1efd8b99cd57355096060061d10e3e3ed5d8894f0dbaf1acb25547d7c31f6f3b19cbf396327b6b8c0c42a0d376249c03fbc431144570816366bef40b90"}, {"SS1": "23fca396f80c61e746f6402265bf0709e29b62411e8867f90a71a11bb84657b50d7e815b31de6a8de8751813dbd2b69f90ea37122f3ab619c51e20b3556c4fa4058966c8f2dfa66048eb4df0de91044debc2ab5198b05665460d11f26de04d480cb466f90e72fb1b902b2f571ca7318793fe4364f523eaa89047760e247e284b", "SS2": "1c75ce5916d9bf56b53c69f5e1d12584cc677fad5b3604edd0393f6c31067ffa13038b3b11253f04db68b58f5d10918c2b4f964e93bd29493f55e34e72345a260e7bcbd3e2c569091eec6a07ede93dec3f60b00e2eb07f6e6f056f1ac1280a5321f9e7c96caeb41163cc6c88a393d93afa745e13453f5319b08f7274f7fe22d8", "DATE": 16660, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1129ac5ccbf43182aeded2c4627a101543ad4c42c2394e193f33207b58718160211e7f6d19d55196482296733de4bec82a0d998b275795aa2364586276ba89a721de23ec03d72fd47a4c71a753d6462aabcf233fd4920a78e06384c3ade84abf1b285f384eba79cf47ed1bc4110c5e5e9548fc13c6bb1c1cabdb85597c78091b", "SEC": "0414f81da21c1535b66ace37a1a472945da12ae30a5086c8e5ad85c9ef32c2d6b2029700eb99424b9e7e742e21c5561083829cc85459070e87fd3012fa693c72ee", "TP2": "0419a9e2110ab9267d6e00028ef4eba2f658e295f31c24fe2c19c7ab60c37c077b1fd0a5552e1d4c9af808d131142bec3cb7f54f1c93824fdf36fefaece8974e6e", "TP1": "04137c8751a9c2f2c769025cd7517542e940a3daba0bef4b765697e005b30ffd5c0f51621af4dab9a85f98a8ddb6c09ae00fca28841d5f929fb1fb56a83f390d80", "CS1": "040976e5abcfbde649f6dab00b2cc646f3a7dbf2c17d3ca1868215be1792105482131c89b64d7f5fb145448ebcadaa0b5fb17e16bf59543b33eeaf980f2628ff4b", "CS2": "04030e97baa72d884c571b55b772cb44b76069c303e50d806e1e12a2619b6fa08105e4f9851ebfdf93f04a97625f4ba6b179672a0f4f24d850ec62ec6289829504", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041f71410c4c6af36dad0a509be7be7608de23a5060ebfed18b2fa8f0de69b76420dc78ae4239064a07cf145dcc846c74a4e019144b06c35de7dedc6a4a774b70c", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "04078479f8ca2998d4df3a20689095f790bbb456284b73c0b39ed420e1b6938806075ae67a4de0dc12335666b69d31244793cc343e138b485a7d5c007a65cf6c36", "U": "041568c6dc9a3a2419e21204993056d2ae5a3745408eb4cf0ce6600eba6e043c6d1b00a07f2a9a124f35548ef3f145398562b1ead7655923402ca79ea8fa06ab24", "SERVER_OUTPUT": 0, "V": "0422214b809f310be752928eb3da8d8b4de20a6d91f068461fefd9e901656e50d413f00396de2b8b9f8ac27ea05125928355c625990008df0172acc394b352442d", "Y": "1450ddb74020ae9207dbbbcbf50a4f540dc497dbb0dd088ccb06ba87918da42e", "X": "09ff4e4a99ab7227039629d6b0c79a4e334d89239d71ca32da183e1b09c19e84", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 286, "UT": "0406a941bd98fa9f4d8da0cf047741a8f52e4ec76a825be4986b9e6e244fe961fe1b363dadcab160fda14b890d571663675f20eb002c5776b092fb05c85845d4f6", "MS2": "13f03e771f82826ecfeaf0e447e842194fba207c395d1fdc346670799768f9da", "MS1": "23a03fb6540f397616df60d4ce19fa58558c09171ed0a6af04deb38887f30564", "CLIENT_SECRET": "0414d5bac48c8d1d7c09752d16c64205bb27efa3bfd29ee794f73773edb40214ed007373aee80c2b1ca6c63c3660805006408df7f43c530b1e0879d8c6c8d45d93"}, {"SS1": "00afa811f5b8eb0184d6d3a94754e4f4bc1b8be9b8c66c2ffe91e48d1fc20b591113f338421506f4aa9f279dabe1362a5ade68794844a49d160065d25a3bbb4121131f901fbe9c3cc856caad1a665c8382e76c0e69450f34160c4c4b9f8f9d6414b9d2ccfa369c5e28352eaad4907596f10e20e4c10b0f0d3d1a1acb68dd01ee", "SS2": "121f0dbd682bc5c9e93ce428be6b2759d46fa3d8a93f6b1e09d4531438caf07e0570485d5a19d06e55a0b61f1c2ca81c182ce23863a957f4d7926faf53166c760ef6a0cf472e38b92ac886b4fe1571a47a703f4e01afe8e2c684f3f1927472cc05001b3264c9de21d557ac98dbbea81977d0a899c0eae1fd8e57c7c5ca1313a2", "DATE": 16661, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0d3c562d3c487321675f70061b9bc54a1e8c8d1a1d34a9c3045529a00ca7d59f002ec0ba18c311fef433e1540799e9211ee858377980fb868f574ff81b4b2ce519d4c0ac6ac213a8621e1e77b168a96acca6f43b72b778f3542f299b7f9d351c1ce7b6ccb4763f1218bf4c8ca46a306d93ea61d7be7ff0ad541e98420a01075f", "SEC": "040b6e430a2833753caf8d42013e18888bb452c434a072eefbb949f9f993a953260c22d034d0d78738e24d7141e417e9085d796846647777179675d35401e56f49", "TP2": "0401202407ca15b45c4ca21e711291ffcef8117f658032508bbac59d72fb52ebe30568fd884142f9b14c674211c840d614559234dcd920f6154fa35d710df8e2a5", "TP1": "040d5494e9b8593ba64b845808166c66c8c16d84fdfd579077bf72e54eb16059a904b98023796997130f4c0959069656ae7aadac91cc78334f6c25f00d37dcfbb7", "CS1": "0403c9e679a62b7369b19bd7c768963bac8a2fe95872caca0cce8dc36be897558a0bf120c6767052aa64a1cb3bd79377dd9523215ea171a1a3c2dffc8f643d5abe", "CS2": "041e9ba7129aa86fc0bfcc27ae1fae52ddf12b0d4632ca51521a1a9b30e9b7373e238ae4dca10b7345c3fdbf88a14dbfeb3760133eef3600e64d67211f120e777c", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041fa20ea07f632f635bfe8fe907920a59e50c913f3d13357d8bf9cb51aca8474c02f65948600096c8b72e54a2de2b6de044be2a7e4b32f7bf4b0a360e87a707db", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "041f6b450eec9d0d86f5295ca093bf9c115cce7f94a7930b7f577652bbea0f237e1a001e47dd0d1a2ea3cf83e45274ab90f65a49114b0f8c3019013270d2a95bc3", "U": "0414b4e7e05bb3999846934226d22e37b901e54ff5cba2a4dd0d11da6ff23c457a078edaf182ae10ee0fa0d567af772026624deeba9fcaa4eb37e2e3a4938d4067", "SERVER_OUTPUT": 0, "V": "042279a8e9bf47653f5e7744fc0c00b9ad018414f3734fa5ed437805f89de66b1d1d128be78f77ad62c8853436fbacfe5b9f70ddf576965378ca012d26feeecb96", "Y": "0ffc629472c776dc3ff7460476d608197666332035c3ccd598d3b16a169bcfe3", "X": "11a77cccf5a2c47913df7f96bdeac89b0421b442bb910f12597e95dceb6e4aad", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 287, "UT": "040be9a2450b1892cb5cf472f38c16804d06b99287c73bc1060e7c258e7ba88f5f20b2d59803bb062c655608fc0490e1149fdd1e4d6ca8d583e5b3841eaee55d24", "MS2": "0a790768b3af6d8a98c0b2eae691eb83a30a9bd2761668524d56405c033c15b0", "MS1": "0961539606949dabb236c094a2346a4ca815a7555c1019eeb542a9a1cc397eb0", "CLIENT_SECRET": "0412f6543801958829528ca97ec0654b1869c24f000f46dc79610e760d6f6f02fb061eb5b1d73aa3d40f119fa13e4a6ddd093fc2cc98139555874c34022c125d5b"}, {"SS1": "0e3525810435aa93c1041101aef225cd549a25102d462c1d286c588a4ca1985c1db5460273f04d923d78ab6f041a0b802385aba94e199cc2bb92dd861aeda9a61b8680b9ef324952339d82287cd6774141865797f53651afa6ac63deb28e7b8a0f81b25729669ace05e60eccdac4dd92ef7592158b210debc25c394d4fed967e", "SS2": "14cdfdd54ecc4c9f59eda836c71ecfbe687cb7f64190b7ded2540275ab9000c20dd4841c8cd147d58d682954afe710973d1cd1c0cbbc2e889720e25cc7afb8630386a9812084e3965048bdad4dfb025e2ac0a8cadf6c1b81584f4ca7fad65914202d3fabb533a7c025702e32050f0432fa1cc6aea7537ee679a50fedfb96dec9", "DATE": 16662, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "01531547a690d0b3948fe9384c9a6d1af1ec8b3790fa1d6ffd6a44ba285fe4280e69746343c9d408c9907ad9e6077f3abc1a6ed58b87ca5b57e914d554ede1db0ba85b173b93f14247731d24d28f733699e33aa67fb4773a8a0eca284a4c55fb14fc1c8535f3e1e7007bce8e44a48316da5b8b3b1cc276cacd3c7cd6fa91dc4c", "SEC": "040980871b3e8ed5867e094e2d168d3263be1a46f5b97a6fbfce487cb015b3fc1a1f622833dc9e68de65cb7cd18d15ed4593a3d2af27894b0feedd4f91facfb424", "TP2": "041626a71b5069dc7ef6de02826d866918c99d8e1bc38b07957a8b171f04590c571fdca440f4fd31b3ab9e964c7af4ae1b29b2eac12e6d32fd1438da828c922839", "TP1": "0419475277c8af9718227686d59ada816192cfd72ce7a0f491a046831dee80b9c00dd16353d87d681d0a23603a165e4c035cc270d73efc078bc5c6667762e3040b", "CS1": "041db6700c8c944a2c7a23f099fc5fc344a36bf81769a4d4eb78608103f1adb00212c110277e3b3c1956cc8e6c3a8172c7910a526fc7e8c388ae01798d2dfeb7ea", "CS2": "041798eebb5f5d2d3031c36318ead665ec47b924984e2b4d032906d1bc9223361d1e760d32b53a3690db3731f83529d021ac2af84351506780a8ac7ba83b4759b8", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04082b913683a0b0f750cd49904c6382233a6fcf2fc0d75952574bfdc23a4cd7cd1c6218bf7c716bd9783114e092fa3056af4c61a0a1f57cf346a2dc9ced3ce23d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "040d801c8242128ad7f191a58276cf166e67cd6cf6129b507a209f70f9cb02b1e40925ddecff89e04ce0558260ba124e9e5ebefdfc8b4e2bad1d8ac441da4f84ae", "U": "041c81fbc23807eb9632090c1b4273809ac8e0d289de70ed68da15b152e6ca7e150f7e9fe9561acca51414b76331c1d785ccce9d1d6d67085fd600ded871eba935", "SERVER_OUTPUT": 0, "V": "0408fcfdcef3f3b4f31cc0a5414bc8941a527a1b678fc52814d46122dc382ff7780f0d92412796612dd84f5621ee4fda26bcc3817497f445fd942ce71b7cb15968", "Y": "22335bbc1261842331dc0263256aa445170bc40ca98f2ec15d39f33bd1ac31cd", "X": "067a27bff5edd9071817e408d0f64324bf22f13fcd2a63075df2b21f0f79ca27", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 288, "UT": "042314e90e1bc3217d84184bdc85cc1a23054d81cc00f04bb2d819b25abf23e2520ba42d791f7beffb0cc4b3c59d90fb0ad5618e6d1b9da00c64ebd1a0c976c84d", "MS2": "006441acc5b2053aff9796f87cdb1e7d499312a0b02218b1fbbf61d76cbd73cd", "MS1": "1636e568ad75e4da92617551cf9c04fb59a33130d7f23e041296b5b78a66cc9a", "CLIENT_SECRET": "04054e0f81fb27e63a92c96bbe590edad11c7273917e97c88c0211dc14ebb33da807cf205e55cd4389ab00048adcf1ad20208300f352af9f9dedb2849104628c9f"}, {"SS1": "1e99b3e69329ef7c1741004a748f6398ce82db9bf9c6301e82714f59b27f56ba1dc9f85cc58d8d51a7b762ab4a1e34d971a27e4c7287e4b21a55c057293c8d040654239b9437c75e49649916d9b85d18d270c6702a620f22d3e7218234dcf332144664094af3b6f8e053c107c4a0272e7b64e84dff9c6018756b81b960bad4d6", "SS2": "17666be8ad767b7ed63512f9753e40084032dd5eeb8cb09726599babbffb921a03956f8dcbc1483cf30f0db6fd4d6426b024c792c77fd44ca4f7225564a7097917c823321e41820026f3f93249ffabd1e9d7a4d8f0f6354e3ba0ad68c978f21706f8543918946dfe14d6d75fbe064cfcbe9dbacc7a479b2b09d40469f4f4c419", "DATE": 16663, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0a0fe088a7c10e1070d5dc667ca01234ce43300b9f26bfe7ad7b87bcabcc56a412a349b81b9f3aee55e2d1415b8becef7ad60d4ee281fe0aca87a394f804c5ab06206823e167632f5f3654e66fe96f753aac395b78dbfd5bf87c25fab216d4d81111bfa85cd453e2482be0be08cafccdb5c6d31401075acbe0020802e39c1745", "SEC": "041906837b38fa85cbc25e6a020b9a8ea74fe67ab2e61c539fda81428d1e2fbb081e459c98a158e99bfbe613317282f93e783fe31f17825359f768dd680a698d66", "TP2": "041f5d097f5f096bfb9200cdbc5734349b71a1aae413c7b2edefcc0ecd10cd2cac1b267c43de85e8ab4f680e350441a9724f4e2d0c3f153c963242a43e92d63dce", "TP1": "040b234e1c4572ea724a8afd90ba4074596b12d8d143dd2c6c3d34e1e94fda808b1009ca6428503ef4effdd0e225627766481d67d0fd79d8c115b55d05d0a9cfa2", "CS1": "0403ad77932ee5990580ffe89566d501cb29ff674ad3d45374a588a16e0ccae3320c77522785b1b27afd09671507ece76e32a95f05f0aa1d56b266c8d6fc2fed47", "CS2": "04129ac53a95fae3e4c9bd6ec0c3b2cd383b0f528af9b48d2f4d556bcd5e761f2702c9ca5674e7a074ee2e8ac84918f74b6f0f88d5b3d9b26a13ef66b153b7e5c9", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040170ac92f7150ddfd8c62f43598ab2bb8dc795cf0a9c48b0904b4c1f4e500754055897ed02729b6b2589d9cdf1c089f5ec03f623dbc25b8e2b0f48ec1eabf54c", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "041a5ef86552b07615cbd64769f0e056db92b71d19fcfef3b31b83e1cc37ece5be22d8531c96142f287783ecf3ebd239843181d2fcdf2556fbd13aa9bac53ecb69", "U": "040494362fffd47e72512fcc14d5d909144093a7102ee9af5ab372c8507045b363088076159fb8aec75d5178b3c487fdd25a22770edcd2d5eb3107073fccb14535", "SERVER_OUTPUT": 0, "V": "0402bcb67c4407c0fa786a1e883ba167844c8f59f6651f3b10db5802a10d5ecf9215718de6d981f71da5c53c2b2e13d64ef0806a205fd40c2d8671c8db6475ef5c", "Y": "0aa55d1a01df1ebb5b3a6dd507681e4c5a4acfd0703ee765e8301c1dcbb39b17", "X": "028605d6f73161c648ccf8be3fadf918e00b682e11b0d10e592df9c21091cf3f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 289, "UT": "041e8908795d20c500752ea173a9a1e04d5fdb539525726649855b21259e4a679f171f88e9d7fb0461b0fde766ad06f8113fc89aa05876497091a5fb92d6ae508c", "MS2": "00e557db2b8c3b5736dcb1f4b750c754758a9815732fc67ffe6e9dcb7c6b7ff2", "MS1": "161e355aaf19cafe1519ee6825b0a7b92cbc3c648ad89d80d05ac02680570778", "CLIENT_SECRET": "041d133cf8193ef1a4f6f6edf28a018508f05a121b128606a33cc0cfd5edae2adb1e552ada4f0f3a13b6d5e908ac9d4367f5a088f3938e916e9f4dae492a6b297f"}, {"SS1": "125034ba66ab8767b7aa5c652142804862c2e88549f1fc7ccae74ee2ec364fb819012925b39d92d1e598c9102acfff940fcdc126687e5892ba2a26b6bcfb323e10392c5a13b444890645fbe7cdeb0704d34b98695038de790fb48573a39b18601e9cd8e787c71671e96be4bd38a031e6564e78437dc1caa3c2f5e4ac3418e2da", "SS2": "173749747d0698ed2a5ca349aa80b6206e714616cb2a97d6536fa944fdefff7a03050f0764408120bb3b69838c8de57dde57f9e29069fefada4a3874708e1ebf0c2db7f57801c32130d88073a5086c0139ea6fa5664571dece369ac0575b77811a0ac2b8e8540520f1229b874741c52bef4c75fb900a58d88e4965f4811f62b7", "DATE": 16664, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0cfd1401eac9836347497ca18173f0ba97e2f212d3b423650b20fefb143cd5b3011ed4d3f25641a5bd0b4cd263d42a5a2eb824a5160e7883632f73360a796d241130b07f78a709983b12fc971981b2cbf018101ce7e41ca4de32ae760d66a5dd1e42fe7ffaae26da65df2eeaefa93a82678497a5a0d1a20dbf0ed8683265736a", "SEC": "0421f88a77921f8fe0739401379834284d20825693532b3a8809d363305f495ab20508edd5451638fa9346fa294298130ad64f0ded007972fe06105ae8a4ba9e78", "TP2": "042355a73546ddfde74c8d724a4bc7d324f926a8d22420908fcfb94e39a41b9d5b0fe6ea1bef90576faf656a4e7abde38b0c921655aa6630a3bcc661afc8355f0a", "TP1": "04236eaa40d5c44f0c46ec60a23cd7e1ca6cd88c34078172a321e664a08a9e3c4022ecd70931412aa1708112b6a430281cceecdf4451a6fb3e50c5168385327b26", "CS1": "04024ab60e1c6b694df1e2e082f48d5ae75f7242cbe55c31a94c99878d091e4e820c8405da96721e71636889489fb1486b9aa02cba38efc33444848e7dc2c7a13b", "CS2": "04120e0db91499bd9474e4940d2dd3d93efa70d745d14abf4aa114630cdc95090e161ef2f626b7d6b5efb00fb359783f052caa7af5bfb8e295dff6653acb2de007", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04080852e87b0d024c94ce04f79a4e9efa173213410d643f5419d762b688bd17f90d7bc647bfe456a6a2c548002633bd08d9e96ef12afd2244cadc48b7f3e8b0a8", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0420c3aed01065cd7eb4e28edb50037a93094c70f66540d1aee0ff527cff92cb1320c6461ebe29cb0c48486b105dc6e2bf636f1f667cd8a6dc5260f706e9aaa261", "U": "0406a1d28169a90bafd4bfa6da8c0552e7f6a7015d650277379c73b581c367f58a2081184a945a8a9de360a0f366d23eb08a9af34605f7c530e11fc3cd626ce7f9", "SERVER_OUTPUT": 0, "V": "040c772e9fcb4ab94a51aa051ac7d0dc2b9108738327be9a34d786a489eeeeecfa21bf27c1f1e88cdd6e78569774f2fcd356cec324de7ef5b3409019de3521831e", "Y": "0ea9992812513a0a8ee41332da0581113682abd4d7190600038c1bbf75988412", "X": "1258da87135dcdf7407f5e5c96b27d8c65832f9c5af934bb900d02f795e4eaa0", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 290, "UT": "041aeed2df1f40d6ff1c468d7a2475fd4f60d27ef0affb5717e61556411baaf986090c07c4e4ebd39f2824892165032fd91fdd4804c5d7ba811ad8e153d4ef7bb0", "MS2": "212753aecfb03f0e9b986dc9291b6824d65ebd287076c5e0c15af1710c809c2b", "MS1": "187042a638cb8b02a4adbbbbcd72426acba38ebd3287f70636469159654a45b3", "CLIENT_SECRET": "0411b873c6ffcf083c25bc42bb24fa10e86f1794a179e93a45e9b97ed7ecc35cc507ed65573bad86693369e268b1b596f7a1ff01891ebcb1da3b0177b025e6298d"}, {"SS1": "1e68bf40946cfd4fc6925d630a566511584310437f139b2c831981eeb08779010976549682b00839d39479aee26f3a8f17b93093fe704b54b29bdfa257c15db515d1d2808527367c2e014525015237e15a0a4fa8c8b65bd39c313255f0ee6db9228be9b078f8782a9c121cb72ec65e1e5fbc1eccb7550f7b2712f6717e788f83", "SS2": "197bd189966601d37c64a31ebeb7a255664977f7278622046361e4b4594a0a6b0f47730f0abe09d74d2156c3cc51c0f82bac21aa3b91a6f6c0310619d269edd40feb7a5c0e014d5120bc918f2ad9da927be8dd037f3db7a3e0737c59803dfa451e096b2e1fbd92ba59b92581d820986a164e9159b1402af154b5d2ff89eb93a0", "DATE": 16665, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0f9d95e3d5375e51eaa18179d1f65b56dfb50fe42f9329300a5374338eacbaee0dbf30fd7038b7cd9387201672b3828127a46f452c2eb7b2637c35c0cdcdd8431f14a0cbc40fee7a05c0a3589359e28e471aba36b2bcc7ca26218b5ba596c041098edeb23f2ee004c90cf27fc6bd3fc6e65fdf9a1066250650935f05c2e2488d", "SEC": "04224267c778bdf389403b25441b302afb97fa5f1675825c2de47d4a935d72374f1b309ada5af2434b6978f69cbe9b9c625422c5502209a695e279cdf7b9a355bc", "TP2": "042194729af2a9b02af889904e40cf89895cad43cc35c8673820526eea33c7f1cd0de12c1a52f996304e642987da7ad85f9f20b9266a6b62fa57cbc9aa38124b05", "TP1": "041aa1daaecf1feea142b9fc7d9db3a6e98f95dba1bb63fe6839b7fb82334199ad096747a431b65661dac690e9dd949780d1e4c004de168e12dd89ede6cb5bad5b", "CS1": "0420ab395a395f1627542974157aab70c07f546e126ce8621080e0b994524b9f7f06e9ef506cfbbb0038b05042655d31c299c3648bbf7e31bb3192fbd5dc4249bf", "CS2": "04079a1acfa9b9e4fa5bc7c6c01269a48f14ec7c7934b3d9d78f3ee0490a3d0acb07f321108bf2ed50dbb95f48463f7b29cb47a3fb1f5569a93d12e050b2c47759", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04179ca22af5a54532a8fda056cc0fd8cf091bc881ac6aeb2b9440e07956d9f35c1cdb84640f4529b684f493e7cac9218322c68468bde575d5c966f82a1ecd1047", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0405da303a74870ef9843e6ecd60f9da44c67f409556ad67aeb77985f837b63e0b17ea7e27a3dea8e83cc779661853014670a02fb1a75186fc704af49b5a0137cb", "U": "0413153f7fb7af048e079e70e555a790a188a99ee93b3d5ec89c65eb896bab5ce30ed419edd596dee92a286aea3a7ffa09a2b7cce51a12c7ed8e6c2858b8179c50", "SERVER_OUTPUT": 0, "V": "041928b15480b1474b4e043025983c74ac81f650dff44c1ad6a7d5408d292fb6c61db2993947ee57ce2993cd1963ae922c696b04fde85a7ccfd8682c3fe7cd0e64", "Y": "0cc25f04703ce2b5b7abd2d0c39e2370fde13448e51cae1be6896b44cdb51b4d", "X": "0691be5654a33ee551b5ca8c4600974ecbfde54e243ce41bd8a56a021972c912", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 291, "UT": "04004c9c30ddb5dda0a0ef8f4639f24ee968def62c653d70497bf723c347f1d01a097ba6f16085235d2109b1e78e790e59f6aa3d7530a927d86ca64198c1556544", "MS2": "0cd40e6553d2ee0e58ea8a88a81e75713c0021ae464fc67d4feb5d83990af63c", "MS1": "0f979ff75bce4b1a32f1d2a7e31b78b4896e853528e52ee63cbc9935e4cc5d8d", "CLIENT_SECRET": "04004b164fa2dc610b53990631c869f1c03c9c901baf101c648b271f5e41bbba0d04fee657f7fb9b4a2ac045073fcacad73e6a95c355dd539628e335177e8bad1b"}, {"SS1": "05c5f84928d76f8b20dd8b1d8ce73c7ac785ab381f0b8b73af90b81cd70144661ebe2aa5847b0b2124fe9249f17f6272594c67483ed2e9df7005b4bff2930b7a0c44c6c170a3b765f208dc352701771ab5b072519527f8032702aefa547c76ec221071d16e2fbcc0cfe62a2840de319eb7c18d2df843eec86eb9b4cd0c0cce51", "SS2": "0947629f4dd55966d7809c2e02026e26de047007ca215faa13cf4ca79b01955d1bb2d41434b1b5d325dd1c0ce395ea35060542ec487c07af1f16814ae9442c861922270d45e0f031d47680d3531fcbd115c30ba4949f0810d0f341415086b95a05a4b8cac172ab041061c1f33f28d2c785baa45754cd4b8d7063e31ac06073c4", "DATE": 16666, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "07ac8fa3e29831f90ba328363b66e83b495eea004592d46a20a9b1f858f8071c168657181f6e00da3443f6541459b39c49a6940c9c4d0d13a9156e81662a2ab805d8448e0d75d72db447724f26c62dd1412face11903e219b9daa6d1cf2724702246dc050a36d53c43bd81194ef3569e99562540ba903adcdb4afdb8c4daf3e4", "SEC": "040f9c035b5b1251783309baa0c958849a29c8d72d0ba64b5675d6a6be05fe48bf1aa0aacaead2914e6ded64312d4a5c2efea7a219b896a1bd62795b9b684645d1", "TP2": "040157b729d5ab96555ee667ca877fae7c501218c7175d5dd7abffe4ea54574da70ce20570d18402a74a8d2bbed9495e5c7bf59ffc4972af40d110d62616feea06", "TP1": "04222eea611858986d20caca777353fc2150c27b57dc78afff7a7c1b18986d3096163734f26c23c327c1d28aaa0a67a1c37730464fbb0aa947bc28dfbca9d02b9c", "CS1": "0415cca87047ac89a5e79640107930f0d570ce139f83f7a604366691b335393d0a1581b169fa610e68070d5fbe38a44f84b7f36006849c997469f365ec8967cc73", "CS2": "0410b4a770911919e66240ca034d11fd10ffb5d385c0ad410e1fc3b853c0c508861ad63a0d54953fbb34c43331056ffc1951882f45baed5dbc6208ad9147695471", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041ff3946ccb23d1328f3b8427f456da70162378794e3576bbbea6e8f41464cf2b00465bc97920929c83e0b8a2f36fc2bc7a43a6d5b963b8ccbfc9dc2b65b2a3ed", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "04051abd9d7d9174c911639febc95f1488ca0d189ccb0c84ca830d16cd9095234d160f1c9591ed3f7b08618b3d0a6bc102c4bc6e4a266b4b0513c9a803d4cbf1ed", "U": "04024e56edb43fe2a8bb64055986314274531f37d91f7735ec06454ffedb807c2c22f91b34883cc9c4e1ccaec9e1214f65063d5d314d3cf3b977cccb61297070b9", "SERVER_OUTPUT": 0, "V": "040bd619dbdc894a9f0b91cadb0fc29a20074202b548733427ef86ce2fd5d6d20e11f4183472c0a56bfae1ff50b6865a4e1187bb8b784855b40eb2138d9f12555a", "Y": "1d28a3d5b3d6e816194a80299323d1432b15aca9002342998bb6eacabb0d9459", "X": "1e38f2ee2a07b994a734957fe8ba16114774334f54205568ce4c3d5e8c003b1f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 292, "UT": "040de2352819f050ac6e66444aaf5744510685755fb38b6965ff334adcfc0f125b1ab292ac45e96fcc37b086d6720056fb84b30e4b466a54bc9337df282b531860", "MS2": "13f4f1637c90cf55493ed0de78ba806c5013f4c09ac1bce598ae9b886782bb3d", "MS1": "0ecf4619dc7bc9b4709309aa9673bab31ea2f52f909488e6c6112fb4c2ea91f2", "CLIENT_SECRET": "041d4078ffbd6a0c5aa9537400ff96f2cf2ea4682707f61c21ba35a420fb13fe8502a987fe8d956c42c5ddc2eeeed29bca3fbc7d5cfc876234f32ffab697e2f1c0"}, {"SS1": "1b8445e2cd365a451b8bd39df1eded4b6707a11f909f189ff0163df9f6dd46cb214297d6fac4ddbe62f5a9224be817f501a21837c035418c9acb7fe09dad4382144c2385e120c8d3edd9cea2070f7a44672fdde5de7a11dcc03b7f954cd2f24c130674b283cfa3c0f702e3bfd8e55841ca00814f6691c3608b36d04dfd3b7887", "SS2": "152ca231086a6113e44ba51529eb0e0caed6c76d78ed83de1ab37b5e296c772606b163f2a7846f867551d1949b0cb6620b3f3424e0c8aa333589b385532beb27042308a01e6a7ebac38eaa82129580c3e4fa27292bc682d039c9b2c345e5c2c8216fa2724160b03ec52cab2992f4f61cc3853b995416751552a1a0e7a2cfbba5", "DATE": 16667, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "02629451711263b6565a433f7d05152a5ef214755a5dc57a8c827c0fba77d26e215e83a4ccbda5c3d4a9225a3e31f47e46580172b64ef92db27f441053d9fa0a0728a45612d7641882846bf19ab8a8a6226a3d53b86024e36b5d57ed5a070ec71d6dc91bb0dda15c93654461acb5deaa6f53b9bce33e2be41787aa462e2b930d", "SEC": "040ed70d2ca4144a258db6cb5d4456b810eb043d1dca897cf1bb1cbed52938a584105a7b456d7a4a58ac8dfa110121be23f3b7ac89d32dd4ced3b13b79f272e538", "TP2": "040c4c4a6bc5b573b01504b0e76f24836bacc87a4fd1eb8ab3c5a9aaa71c0bd6e50352095960da5823530395a387ed02ea9b7933c61c04c646428e49caaa61c757", "TP1": "04121048869b0be287208b7a5158576801e7dde7244b0f75ec74cdb7e65dc7042a1caad8f0a26a1d5f15958638ab576b0911a8056e320632f82da4b12d5a254fd8", "CS1": "040414385f15314279eeba921c4c1ab1fcea5f45b68ce9dbdd996435c649c9fdf81ad5f8cdf714f73276e09252ed8d11ef6c5650fd481802e6e8c49aec94f293e1", "CS2": "0400c1e25dad1ad9a5b8d08720bc70e7e98f2ae24bdbf7c1375b2c2ea41d3a657a04c57fb120f4eb4b9f2207cb583aa6022552a93a6312b60cf7b3cc0986ad504d", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041b041b0325bcfab33b7552e4189f3b289ac406012d74f346f37e6cb6cf7d9da3113c7c95d492098a2d7ff79558364d90f108616c6d75affe53711ecf12c789b7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "040c818701d2c0e19ae5c313dd5e927c32d45434802889bdb8eeec3db051fa63570bcc02ca4b6823afbdb574ae44ab5601f4b5e2120ce48c45dc2da589869fcb88", "U": "0405d9e24b927934bd1047435266bbffe7188f508e959ab3fc3c584c63e2c3e3040f498eb95580368f2012d8b16851a55860d95e5c219133b9326b3991c8ae020d", "SERVER_OUTPUT": 0, "V": "04217ed5a0ccc64601a10f3581389552799cb7973615b26f73070e77267675a7112111a746d8d7bb221c514d013afff35620210ad989580d8132df3cf55394da23", "Y": "01b3ebd04a4915a7b3e45cdddfad1017f58f92fd4a94b27916cf7acfd7dc002a", "X": "19a0f3768a6acee9f44972feecd23bf6e93e74a4bb22a93441a1e4951dee8ca1", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 293, "UT": "04188c3c79f19914431e419216533d0595d49b37b2f93dc988425007032ccb13e70ce2a3e08ea4f59d6b0d70c426597bd66cba309bcc3ac8b3b539986dbb553563", "MS2": "1dcae6cc5bc4d83df2db3d1fcf2fb1fc9f7602d6288cbbe7b0dc75804c076872", "MS1": "1d7f4b899fe4a5622153384a5860ec7ab7290d15ba07293adba9ed461b339788", "CLIENT_SECRET": "041826d7c6bc1426b0d3e8127bfc15a07f02363eb44d2a06128c0ce565d6bc19a519a2eaafa427c237f37baedf492fcf702a71cc1fcb70cd556b7593b5a9240a06"}, {"SS1": "0770ac38fa541579836059d0ee458b18b0a1fbd175ada17f1352dc4bfc9a6d0218e52b01acdab213fc1ed16aeeaf2edcb7e913efcf60c75fd9bbceee3960b12521969ebc595a8338aa54b302ec4824ff76ff1d28c8aad70f3d9d5697fe84e1e42171ad081b2bd654a22fc12b532b71993986d665df53bfac4946e9abfea0f495", "SS2": "0eed4d40169b8128eb4d93803acd9d164c72e73e64a85ae36f5fcc48b1292f0d17474fc76170bec3e96e28e1348589b7989d73afe4db27f683eb8036222bb34722b3782374fcfb515d4ceee49ab76f97fcf4a030e60d8573fa9f9d8802db8be71099c51b4096866bc7bd16b1ab95aea08424698f625e6921bb99c3943c686f1d", "DATE": 16668, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "209bfd9955d509563d746024c71b840831b57a8ab322b7480ee08728d396e01318f86bbe56f8304aed25f02377d48cd38b5deb0d74604ab6a12ff9901bfdd1b80f3dc7189a088503e253bf5fccf6147bf1d91639299a65530a53d093c26b92d212fab81c8f1443c4e80e7d1d31ce736c9f0a093a9300cf2590ea6e4688130466", "SEC": "0407e69badfa7af6fda3ad6dc944ab44a7fa124affeedbd900b41c28942917767516cd94259555307e9524f3c4cd155d0f7bee5081614de9b266c96812367f55ec", "TP2": "040e74db118a0a9e35b88abbc03dfda2ebb873053731d7c31a47695ac09000729005145f7e1e6c272ab38d14ee18e8efd92031f42d6003f905f073db00401c81c6", "TP1": "04207466714d1f21d0f2ea8de7c96c5cdc0c6b76e78fad93e9bbba1e89b176579510d60b41060d439c256f67c11b76c0ceb08f488d82a8c5b23e571f818b0d15cf", "CS1": "0419ebe0be83b4967e2bbccd0a8f811a5af29591e562b5cced97fcc244d6133c6a05376c5b35de0e584259335bc1eadf83730003699bc136be3f1f385c37f3bf05", "CS2": "041cfdb8615aa8a67a03f5c8773794fc173cd9b0457dfc3fb1c13535ca19c8875f0c2d410c5246b03c55c787b83289013ba237bb6e9c625de6e285d2af8f0321b9", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "040c497a774d0a12cddfa8064fd51f178f6bdafe2607bc45babc70a362947e92df1a146366b77c6aaa8ddc2320b42b6fc656cca1611dd2c70b653441df450df33a", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0421229fac062f57a6557da6c6f82435b70b6fcb3c51e72976f7074400c2149d091509be8a4a482e9fbea559645bd3632f54baeba38bd6034cc9da7a7fa961934f", "U": "0404a83cba5909a67efa57fec6b78b780827f8a94f26d47f705c804fa36bda7f73065900e176eb20909141e9be05fe7fdc21a7886d5e498ca806f9c100bb97c2c1", "SERVER_OUTPUT": 0, "V": "04071bc182d009b4315eb23a1769ae6e7320140909f6c0dd49ff84b0bfbf7a158a01b50b22f0926ffede45c05d9cae76c179f905d64cc9850b26a301cd6724712e", "Y": "018a58bab61786136c8c4254816b678e4b5da946f3d5af9b91768cf4ee9539fc", "X": "11662c714965409509909716427d95963a1c1330485d61ae3656886ce573ce93", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 294, "UT": "040150cf3906b9ea19e9d4ebeaae81f683670b324dc985482711eab3ae4b277fde025a24ee52fd1bb44a62573bf0295decffbeadb965e11a5d0fe2a38740518fa9", "MS2": "20aff62a65250b9b732f53a0b3461c2cdd6928d62be1fbcd226ac6070dd90f79", "MS1": "19e90cb4426c4edf5a8e3cd1819617d26a66f891df2c13cdcf5db3580d155a94", "CLIENT_SECRET": "041802b67352e2fa92f9527fbb1ed7e082eec2f184e712bea5a77b40c925c26eeb120ffb41b0d83c5e57765918a31a83da8957a97467c9f863ab98220a2c03c0bb"}, {"SS1": "1581943c2842d11d616b9941ee1150f348e952f1203602cd4e1b34860e0005861ec4f3f9a458e5d870ec41c23ff28b561c731c82b4f03fb4415b550c7cc9097810d14be86635aad30a2bcf8e086f4e5ecd4d357c79338a75f4e8cea2c7494b8a0300d8f875baa68ec097eb604c3fe7124af7be2f3daa4514531d27b91b8152ef", "SS2": "1e8bd13b938ccee10d4fdce79ae401592cf5d92763d99f0d50c02ad36d68dbf602ca8bc7c2eeb9d530c6a38e6d6e5a1326a0b69ec240938cf916b542b97d5d46088068039436b47d14cf1c2ba13698272a45c0f907cdf9c2b9c4cde516e11e2707a48ba3754a2f7067fb8a233690e8f08d57afb219d9fe38373d52510a4a00df", "DATE": 16669, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1f9c13cacab740ecd1fab67b13c1f98dbb23e25d619d1ad0d27b725250756abd0962bb4eabb11249d663f84039ec1a7b124cd69a47b7569a44dc5bba3eb2a069097dc319767877fcfde46638ef914fbe2695930183d340cecdfb29269e972e220db404a9c3462401f9df944d2c8a06ca54a4ef54869aebd20697edb2bccd3984", "SEC": "0421ddf4aefa172306e736c840dfd72ffb6f0df5bd57174418f73e93337433f277148148f55a1bf3834f20b6e7c60d87b6efd8c5e3df3b0963523e6169ffa829e9", "TP2": "0412709eb284517df7139a24e173aee147c8820bc26a0730adc9e4d39bd8cadcc415e677733761f6534fc65ba7d86a3a9b2361146c9ea4c3b1951cb295799b9695", "TP1": "041be84612e5f4cb2b27824529b784109c877f7f0854fce9f9e75294545630f4e3168ee66bac80527f297e53287130cbe4f5cf701b607da9d406c78c908029767d", "CS1": "04209784365d6f1ab3296042f536c26eef3a28024bbfb620e3d0c29e2ed0b51c6807ed40200791c7d569b92f9b86dc737f55d908ac928c35f945e4f959f81cb76a", "CS2": "0400e1c7982004268912cf2776f00c8b1b62a522466d0d8f19e1ac86adf5dddb0701ff38546b859ae78eacd07c8043651369f96b5a94f2ae01c10424b3b14930a1", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "04239d99a5b45d959688845f5e3ca7cd497f65c00062c109f075169f3eebdbba831990341a08c2e31277bfa4a59c4d440115879d3c349a58b53576ca493d469c81", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "041422cb0de79c4af903688d463b9753d9781279d95ec7d008038a82ceab43d6c5178e2c02f93a9ac5199ccf97bc68af77487c8e160b1dc849aa1077a917ef7144", "U": "0409c61bca875b3861953a3c2706532dcb41b0a3c653c2200aac62ba5320a8cbba22aeffe59706892a733c3f7b1091b84e04b5795530452a357ece2f404f668dd1", "SERVER_OUTPUT": 0, "V": "0411f6367525790e3f42bd6b1c44d5bac2264388555643adacf65e5625b1f553eb09cb75227e8ebb0d2d4d2d571df203e96f00d00580806753ea62be85b7b37576", "Y": "05806584e552414ffe2504f9a52f8cc07759b13c3d55cb2c4f832f312fa75b9d", "X": "0684763456edcff8e94687af417964c6bf7ee005692ac90002f386f92a39d43b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 295, "UT": "0411c218c380ecb580ed1fc704f70b268c8a46813c03ce2d2ddda19daab8b3742922966092f9bad2016ed8fa0beb88b0c4e04291c178e7d38928f14dfa300322bf", "MS2": "01257ceed993f5433dc1bead3c51334b68e74e193f4c2846a669cdf16972f83f", "MS1": "147fb6837d88e14a2ed717200d9e88e289826bf8087addc99ac7d72ad0ef2080", "CLIENT_SECRET": "04125164caee8a416c077769dda9bda4781d425efc1982b269793c1b56d31e1f5b1b01c99f921e60d3030526f3a84d9fe40e046db50b52702460e9d0a28a2f5624"}, {"SS1": "052361bcc3d74822575fd395356e6f6c355caddc579c8c23cb2813cb7ced97c71577415580dc02a1b650d3d6fd2d65a92a75a8eef5ec7b7efd1ee554ea84ce830e0c9d882e4fe54afbb756b199a26b7d094c32976f721388d4a92a3791f2f69002c784d8ac967f3dc87a593a290bd0c5c71914e6ea933e10d8bb2796c36aaa58", "SS2": "0bfd379cceb69d83d06ef20e12528188e2409acf95d826e7f422b82c072da85815e648fceecd680d54be49cc68bb567901149bd5981bab2f75c784547cde3ff31d43fbf4ef1974edc20a947c1a3c50afeb9df29abad41d7e99f2622655f2fac11af235c6f4bc945a2e9d036f9e9fbb099acf11e2261a11593d249d7133f3aa52", "DATE": 16670, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "0131db1801b5ed2debce2a3652a900d6fb42b13cce3326e0b3d2d810417b27a21b6ad331af8c0c7377a83fafabddfe2c35cfae57135477c3b34cd8944e8692e508b2ac3713e04f8408a62b0da3dc1838aba25a00c0c1fe31cda61f442e14a2ee1a15f9dfff189a268876b193276ff455c74daa630b1ba62220671d7dc637208e", "SEC": "04054938fd0e41fa10218ad58fce8960ecf9ef3e3515b2b6617b7d50e930669920031e3e99c80498b881688131efca09fab4d3e62087c84e50f4efd9e935e26fc5", "TP2": "0420d25e26ed4a7c190a9f78c7658059a9a9507edc47e13513f82a6a13242d68d0070b3b0b44211a0107ecdb06d5ead9269f8f604386dd9f8990d1e61b1c6dcdfd", "TP1": "0404a85a87239b1e4e7b8f80b90e70ddae06dc4c7806a1512818495d04a294b5fc09ee9030357a1bbd27efef9a424deaf83503dc8c2591a087d25abdaf6c249d5b", "CS1": "0422efa9e0d598324ab68597efc7d6011f9e15e3e8d8d52f3a2395557a81e708a112b118e238ce51441eb76800b68017225751b436c15eb1fe425539c7490e89df", "CS2": "0422de9fc1dca1de4254bd199f26ad823e11c580b9b709fd976efcddaa7cd200ea0099795ef1f353d2369c7053d41b260c5d4c283f600fe1e4204c2e6901982e19", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "0418218742244ee71c0b1e28ed464adcec00c764f9c06ade57119e2395779e4bd6131dc248cfc9de23de68db9f5c80bec253106992261e93a172ae2b616227f60f", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "042011f2ac0e14ccba5f6edb40ee8bae61ee173d4e0b661733aa3caa88f90ebdf603c383edd51d2de19d22f9458b08fddaf896c64f68a5c01f7a0ed9729bd96bdd", "U": "040a537c2a98f80ceacb277a2e4d32c3be2417368a0e3a3fabef43a7a1be50f03703f45e0776652cb660d8adda2207ed90d6ee427aa99da69ec53d41e709375845", "SERVER_OUTPUT": 0, "V": "041d99a5619a8c819214c94a79c61ded7b050fc08705b82c215e43947b7d947e4203c3f575439f53e3493055efaef5634760562343f398b3d373b7be1089164555", "Y": "1eb3e388e30a78e30a30ae00d1aa6e556a0c8abb2273988585d9eb325cb38cac", "X": "20992e687d4cb569ebb33a0e6a3f8ddba08f94b1086bfe1c9c3ec5045b857cd6", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 296, "UT": "04177e061f9d4d6e679331fcb4a88e76e2db439ec55bdb839d152dc9140944e7c50ab81092db5e7fbcfe53bf89b8954288ea456647a8cb5d2ad0e2dde53f8d74fa", "MS2": "15df4c12b2db2aaeede838c37d6c41fb5f8bfbb83cd451daf30cf0ba968d1d4c", "MS1": "0e466a484939d6f3ff97eda039fc6a5c6d69d895d6976aafce34514d1084352a", "CLIENT_SECRET": "0408e2c700d65f9947ff00826121474ca4fd2e0e9568625b9d735da5cf8425b3b2095d43071ffbb5e5231fbfbbac2aff0d69570c6068f4cf4932f5ae88f93fcc2a"}, {"SS1": "1a47d5db4bff0549c999dc46adfd7c853f9ddd51ffb4583d6c6160762c007697064b4a55b956764d977085ae39a6dbfc3bd1efa3e919a7cde30d84851beb09bf0ad0ede71de0acc0e9bfdaf86e01d393e993b2b1affd1e657708b8c852756a110674975eac3dd97634d9ea17661c912d1784731447727074aeaaaff8e5dfd1b7", "SS2": "157ef66639885f2e83437ddaeba727b9e2e6fe24f12efd37e8bd980284e9c8d113a08774c25b5f146432c90ee10d26d1ea35c3cf9401b248c7a8fdafccac18d7123a5759465ccc6a1d81b1df540424c8cff22b9e746f2910bb104b00f64c1d372079c07620b6ac0e61ebe4edc64f9e5d8f98b9d1b534e42446444f456fceb902", "DATE": 16671, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "1b665c4fde8a073792bc050e6e09e40f8f62f3f558600d0ece1b74651f18b18d16d4333bfe28852eec1a8fc94cdffd8e6d812bb2d4c45f978372250d978e1555143396c52af96eff5944c350deb3ed4b63dbb0561eac8535175da241fc4b944d1ef6c6f1479058973c461e326643f52a5dd7053b659ba111f42816c48df7b555", "SEC": "0423dbe82ff399cdacea6c3719eef726f6ee532b21628a2fade85656ac5ab28231234bfafcd503dd1b54d9dfa8bf36bf65ad012acb76e800d185beca4f0b08a3c8", "TP2": "040b870219c105d20fda704f7447f5a7da5da03d91f81935952671d2348d005111090961a9268300187659b91d366696b1efbf1b4b1e63826992ef7a690fec3036", "TP1": "041936cb81a5072b2e2fc0489ff3c45a2703770e12ce07bf1276a0e4af5f63f1c903e4c7bb3b961d3db67a8414639934975aeeb2f1167363d75f233e1892baf3e5", "CS1": "0416ab7d9308db1eb4f9bdba0ea19c2c560b724b05047647eddf06309e2c95c9f81894d5ff4953c26bd84e7a23f2b940e5bceda62c302998fa4f5b767ee6a11f35", "CS2": "04019a12ae9989a853794f2eb3f3b48aa9504c721ded001c6ed771ddf2b06ac63304bff1afff9014529096aecbd766686818cdf10ec514cc70f1228d8319d2d88b", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041b99b0b259463f9d7b123d5be7d4a0f3cf4f35e58064eda7d30396df36b5fb6d0591d3e11c7dd9f3ff66120df879bfd6daa3ef1ed71c1633d3dfe29cbec4e166", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "04220b7f11462ae00267a381900f5c07c7370363ccb094e68d71972b09b50c923211976e0e2dfaa7ccba4a0b4cb093e9c9ddb73ffe8e869a518941d5c6aad8740f", "U": "04069f9dd93c43a641215495a678c851aba88d929a2a1092d8b1f9e681916547e801bde8e74c5eca9e2fdeef228a2302ac5d8589f5cd57e15b270139d532dbeffc", "SERVER_OUTPUT": 0, "V": "040703eb6ce2a1a632c779752612e905f09554e60c35320bffd84075d0c5e4f3471c95e0c6f729594e659dcd733bd71374bcfafc5c37bed595ae5b3a7bb2f1de58", "Y": "111bd24363075fbbfb09bc82b22ee8a68cd4548511a15e18ab85b97a3e10017e", "X": "1b51a2a096c35b2e79f2a60241a2fdfea7d94b2c40ec38448cdde86c9ddb2159", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 297, "UT": "040defaab299b7d5efc2b7fcd06e95366fa2776a9d586ebb21215f4ca627ecbe051780e11d9460dcf7bdc3095a8eb8e4fb74a6d47b55cbc218aa1e7d8558fffc98", "MS2": "0e2571c48a2d63d249d254ff72c9fd3ff1aba86d9b93cca56cfbfa077ba5bea5", "MS1": "00d36cbbc097c7de0ac9a22186900409a6930a2667641816fc7ddb92a5f9f5ad", "CLIENT_SECRET": "040cf567b1928a603614af195cac7aff0af750c75f71a630e72ed21f42f6ba7a2810780d7bccc3d7dc2ea932b23a466fcc5f486aaa9023f3c4f9e22ae1cfb8a4de"}, {"SS1": "16d38b0f596a522ff7430485f246831ebbf5fd5c06668f95d729af924229156103e29887b24f4b89fb5fccdb930b411770254fb2e74bdcb59739d4d6fe48dad3114351b7cf2b4279e338a4aed1aac8286efb9ea18bc080067a57eac4ff996188021fa3e6c9662b63c18c4402310a5fb452bd74eb01a63b26a304c78284fec1bd", "SS2": "03475ea1bfb08c46fedb4e91afcbaded8c5c2aed55ae8599540805301ffa7be51ea08064905037235fb5a0c1b3d253053a179661710b52cf66b7e58919d0a7ab10281ff0709b48883e7d9f0332ee7f427f0483641db9ef989e25b4a4c4ef90b3130e1394534a971de83907c254d635d998bb907a0d7327f6ed5ddd04e91f7164", "DATE": 16672, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "17076b202aa25dd7a6eda5db8dee9b963796d33e9646b881c009426b7db42ef7234bb667f23a6dbb58616a7e546e5064753181b6df594bce0000a79ce4cac5f8130042767074bebab6c8aadfe783a933244d6928961ab4b687426b113531657605b77c2bc83d4d56a8d7c5ed81ff1a3538bc567acd1c3fb6e9480400f1d64c08", "SEC": "0415b310cc1e6ee1e5664387b94ff9714cc365298195e4bc964026f9cd450f8175113f849b9b274b5b640364c6eb21bcae4fdd5742b031f9b44f8e3fcd89fc89a6", "TP2": "041501c3737785502e2160c240340979c9db9a58516535e86a04c853c96859c8a208b9907a5691533b769ae3450c153b764cf3c556e0423640cdf63df1a0b60365", "TP1": "040519289a8fd2d262a5c7cc7c865a7837bb2519fba9bdd681cf856da4225d7db70b84d5227f2bfd9724ca799e17ce0d45d1bf2554df10b7dfd839440f97d6f651", "CS1": "0419889fe25abc410f8babd4a35930efb8636c95c666721aacd5cb74ba9587bbfd1f1c87c207c45fdd740c54ef3e1f7900c35ac0d6db5af1e823bc6067df69cb74", "CS2": "0422bb59171c0d2bd6da12e728f472043f0f62b16a8e092fbc124196bd6ceaf1ff0ed5eb12e612dc5102bf3ce19a70ad24cd9b281b8480a30793c4feebf795098f", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "0404976ddf3387de3e5fc84e490f73f9aba744057d34333da16b502be3dea31da011a0a1bc1433c31653cf4b1be2e4a286f1585a93735e9498c782d532c478bc93", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "04066e706c600094373f91d59e5182584ed8e767de5421ff4a9ccde42aa47528821659e053d8a50c26684678aa3372da8ec4ea972060c4604d513ecf116ee4b431", "U": "040fcfe65a438f44385cba190f14b7e944b7c611084b424475c949c0d56295031805bf48d1f3b14de9ad26793ee3cad3565eccd3ba244aae442dde87a9a5396d9b", "SERVER_OUTPUT": 0, "V": "0400aea73305c047102fe8aec0bf9962e6dafeea779ea0eea64a4ecfeb225649f4140a7343a03fadeb0f6c8e8868b2155f891b93263654be8236298bf9831bd2be", "Y": "1a926d82dca206c2ca62ff98dbd3bbbcede73d719022f53bd78816d9f1d7f0d2", "X": "0487b4663690458ee1f3983d9e4bec91078462f21100643480bb2a68bee251a4", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 298, "UT": "041deb7db2eccd7e43f03c7d42bbddd433579bb7fbda75f2953cfcca86dc70b90c0ca731e6c060d837d9a3a328a6172dfb61f9575158e350ab4fa2a3d212141b67", "MS2": "19a94e910cd0c7abcfc8257e9a9c187891ff487be6611c7d3a53067705487abe", "MS1": "0de1deac3c1c0c15d14f73a2da9c5abe39a14c68b02b95b0bf490a4432a8ca43", "CLIENT_SECRET": "0401543be9879806ef13c0ab86926fdd2e934d8ea3ea4c209d22bc78d78ab0892c22086f30509368cdd0602fc0198f1c07be9d68a24573a40444cfe268967f0d70"}, {"SS1": "0ac949052baaa16a5ce48188162d8eb54ea5ad49befa9a91587c23fb0d149ade1e9f8009e5ff418c6113449196be5b4ab1a6b965304e8c8a64aa9bec0c2d7eb9148c2f4412d1f01e73fcb7daa7472a396f4341bdbdfa7af6001a5c07b3688aa71dc81de4a93c2c2750813c6e48c0d7d57c61c8f8d7607752d9db527891e3598c", "SS2": "22bab02df35d87e1e4aa3d8aeb43b03d899bdcc4d4f3d29049fbfd63cdfeff27072604f0535c1993c6e947084486efc5e517cf3e856e832fbdac5fc93715563e1391335137d0400a1694990397e3f9568601d476240df87f059b1ab98f7aa8ea20eeae6e4c9d5fed962a20ef3587f1ae1cfad24b354bba7aac3ab25e7e8ef4be", "DATE": 16673, "PIN2": 2983, "PIN1": 2983, "SERVER_SECRET": "00c865fb5deefeb94f7f5739c6398faae085ff0d313fdeeeb44449c3642d5a3018e4a401758ab207179dcebcd4eaf4715928e4fe11b267b2b27ab4d561f0f5ce009fca2f626f1019dd648829fe124417f669906bc3e3d7f17a0c7ccd0e19e6031ba6ae949c5005a0f7741e1daec6ca83ae0ed84c2c17c0b73224bebd8c3a2ad7", "SEC": "041f10185dbcf27408b66a4856b06b6c78474b20571bdd63a041b88e9b3ab2996c05bd83136567c24cb92d7a17aa155c5adda60566fce56e234103db0dc1d2fd05", "TP2": "0405372884c32692546231c565e5f62c31c247597a2da57f564b7ac8a19cb44cb108a6ed69f6650eaae4123685a5f2400cc7a0fcf68162be1ae6920e0d3f04c611", "TP1": "040c32769a41f8f42d5e7e82b1f9c52ec9941e60b5bff6f8c266333ceca788f0b40432cbdcce613e20374c8eaad1813827c002032a4c318697333980c96c1dc8ba", "CS1": "041e3f37ffa04925030d625f2cca75560048a70b04219d529466037bb785f5a0f7164cc0427e255da00e4dfde37f9a6e3a194f6c3562e1539445cc2a1ebe2199bf", "CS2": "041c47e018a81d8a0a1e0ce407e72cae0a32417ecd08d6eb49f250071f6c3b600f014e85d2b1a4490dcbad813ba98ec03cac9b02e5b18e3c96038ca1b9bc0f49a1", "HASH_MPIN_ID_HEX": "21766f177ceabe95886228e24725aab9e8ee51d57311109b4cc5a9781bad1fa1", "TIME_PERMIT": "041402fd00bb813739ffe1c4d3751c6ae70ca03e2b73d155408cfa4dc92c4bd6ed195841224e60c47904923f53dc234039563f347c08a68b8726c518441b876f4d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30352d31395431363a31373a35315a222c2022757365724944223a20223362663565656135343239343832643630316263373038346333393463363432406365727469766f782e636f6d222c202273616c74223a202264313461363962393530333136643831227d", "TOKEN": "0423298fc60a7c65d4ef653908187ef2eba6c36aab473760f439ed2ef0d272fde71237e88d49dffeca82f896722d2d8d366ff7de5adbe5e45ef80381f4f9b25b2a", "U": "0421133bbcc33b3c8660382b293723b6c85b2a2cb4c992fee88cc2e3ff69b657441ef3e22ad89c7c2e35cfb709c68964b27e673627add236eb2b40fc15cdf3ed13", "SERVER_OUTPUT": 0, "V": "0402db0a293df55f62740e6c7674a388b1d8c1b998018e068d5f6cdd55403e76ba07ddaf1457e85e10197394d762a02763d7ca53c63a8eafd150e4050a5619f453", "Y": "102566e2e578b456d2045282504c569cd404b096b20c8fea3e44d59e26b80db8", "X": "068c64ee061ca41aea361337bf9768da72bc80bd0f32a8dd9bcea503ef24bac9", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-05-19T16:17:51Z\", \"userID\": \"3bf5eea5429482d601bc7084c394c642@certivox.com\", \"salt\": \"d14a69b950316d81\"}", "test_no": 299, "UT": "0405eccf39bf9e7154ec0ddaca122c4275a641a957c1c659cf2a9bf8083ce3bd561b31a742f5454a0ba765c4507c118b75a860a93e92fecd575c58013922f36db7", "MS2": "024eabed5f481aa665f50738a56c2a94bbd34588ed559ff64d6047c73efea2b1", "MS1": "1df837e6b86130e0f5c738aa921928e7cd65b25c34c8de04f54a374f90aa5f05", "CLIENT_SECRET": "0418e490904d9ebc940bd7373fafda8c40ac0beea15482d25af9506d92caf488ca18f7ef500a0f106d05cf8bd768f5db48348682daa6f9e15651b3a38ec994c977"}]
\ No newline at end of file
diff --git a/testVectors/mpin/BNCXOnePass.json b/testVectors/mpin/BNCXOnePass.json
deleted file mode 100644
index 4556b1c..0000000
--- a/testVectors/mpin/BNCXOnePass.json
+++ /dev/null
@@ -1 +0,0 @@
-[{"TimeValue": 1437055594, "SS1": "082fc0a0f340a1d18b51be28d0fc1c14210361ee9cd89e33bbfbaceaf91b0ef90d00773c9450f6db74a254f4bdcdb0bd501a30de15975b47c82e284d5bd42f1c23e5780693e63da58f50535b2c012f89392df1ed33b476e0b516e78489726edb0002284e932e4a13a0e6e838be28ab8973a5fa9a60760e5682a0d29a8b5dc6cf", "SS2": "2387f35da03b890e44669846486d5d55abb85eb13f6f2929a5f4d65d1953cb670b8eca87941c87a1bc9965b71b023a6bcc5af324c0824789c8b9b45ec38fda1604257638e754f2b7b6ca3b62e6b3478ac5dfc8854aed61366a52febbf4ec475a06ebc4c6b7fb6ef3d180cb8e11d2fde98af8ecec3b35eacb111b594a2cc66d59", "DATE": 16632, "PIN2": 4116, "PIN1": 4116, "SERVER_SECRET": "22a04aa155b9f4e5d5f401cf4a9853a48ebb338703713f8267ce752cfe7f3576209066e00046a2b55c341e2c54420cb57d33cff5e0b5a5ebf924be1210b6a1c808aacef1a6650b76ca10e3cfe7e36c2cdd095c908485da362bb0e82ca4215ca0039fe6f40de85ae2ac6748fe4146b3bedac423bdbfbbc8c496aed0c9fc48e713", "SEC": "0416cc105db6b649eeab5c55d900a7a4e7335b17b20a8ee2421aaaa00a572fa767072fab0d6a85b789bbe9ae2d53508ebb6c63611555926ebc7b63c074ceec5194", "TP2": "0423acc4d0fb3efe6c9083ee97fba7a28999f05b34988117615df402149cb20ea6078794313732ffd3d51b47e7b5f379f493226f643ea3a25d348fae094686e73a", "TP1": "0401404487efc64b49afad56d6ee7eaaf7990baffddcae300c6a0e93d3503175480858bb4d61bf5382598385a4f586b23490b2813ce8e5ab91dd7e44422b72adc3", "CS1": "041b0e0217960c6e3f764e2893ddd54e3f9742964bfb2ae0499a642500dad1101016980875b2b430c432de5201edd774b488800734da6801c9cdedab447bbe3bec", "CS2": "041c110579293baef562105420c760f4a27d85f5890c31483d7e792d4c6ad3b9c405b67d59b286a8645b5695b5d60683e5d2b315fba27b943ee4186f94935bfa17", "HASH_MPIN_ID_HEX": "b9b3d46398bf50c2f8fb451784aa2128de642cec70115b8a31d5e88a388cba4b", "TIME_PERMIT": "0414753542c15d5efcab38b4274252da121be0bc5da5e3f333d86a0a2d5002ce790051ecdbf492b8c5dc6aacd105d173e3e1473fd078cac83233ef01c361c0a5bb", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33345a222c2022757365724944223a20223164363764313438616266363765623934346133393566623434326138623366406365727469766f782e636f6d222c202273616c74223a20226137366465353036623735653539396664316462626363643061376666643035227d", "TOKEN": "041520a19f8a2d6c43a20443572ef2805f0cf21887c7f076b3f503e6ffc09cb21a09b0c5301d32c8726d9f739c358ae5d7dfb3f00b8a8cb4fee84942049d148963", "U": "041ad4e457fb582e4f6cadc63ec7f11ebd4a46e0a9fc695727bbc93de98414e928068540af45c968ec0601a85eb7c0f25ed5d52385558b6052a2fba0bd1f7edbaa", "SERVER_OUTPUT": 0, "Y": "2199a789cdced7bbebb55761cfb254c1979ce5e42fbae192cb2a8eb37899a2e8", "X": "206e3b2c3d64b357970320cead5aafe304c10b8739ad3804fe050c41bfc2c7ab", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:34Z\", \"userID\": \"1d67d148abf67eb944a395fb442a8b3f@certivox.com\", \"salt\": \"a76de506b75e599fd1dbbccd0a7ffd05\"}", "test_no": 0, "UT": "0419ecac47fcd2423252a449ccf49d1b255a150dd9db44ff42ef592510f2d898f5135d587204a8ec7eb49097ada47a2b1ee3d9d004521dff2f009443c6a841a680", "MS2": "17aabd87aedf8cc74004624696c4b9474cd4d0f8003718e3ed09b61cd75c9573", "MS1": "1aa7e48ba225ddb8d714ed9e8d9a1cba19d3d095d7f2ed05e6eed04e4ada9137", "CLIENT_SECRET": "0419b4248967e478922fbb00f66b32a48dc9ce45f2bd3755eac7a03e5b7ce1a5ef06e35f21137b719f3734c193910c8285633cc564e64e84e2606696ed3ed19a2d"}, {"TimeValue": 1437055594, "SS1": "1f0a6786b8453e8bde8df371da4440068931c4bf5c9d7be2e5d09ba7c7ef534e22669c9d3500ee41c7b92c0aa938cead8e467d317e4b27c9cd874c2ed9f58653075b5c163df3b20799ef8a2791eb6d828112ff260feb0fc39dbd0b711ae41ae40f1b689524ddc805cda3b95ee56de97e9d71941fd44da0b3f8993903e56e90a4", "SS2": "1720ca642eb9d2d00fa7c83bb49173015c6ae7c0b5efd879794862da852dd5900924b2daa97a89327f64502fd5427ca1ea41b5e5f44cfb054bfad11239f50f4314ddd241a76b2e6aab9900cf25e2b32bb0bc01e22eaacc496cea8ae7b25c8b7a14359713e43ad650d3b3766af31c1c2dc147d384b8c814a0345ff2695e992d4d", "DATE": 16632, "PIN2": 1535, "PIN1": 1535, "SERVER_SECRET": "1e9be19b9e35406176962ec8bc6e3139573c535579d172e5091ebb5809f9f76f03f4255d2ad17cc3ca16f027fbb89d1166d2ee1987a01e13411955e1237771a70f5cd77a058033890c454c4070f6008c21d637e994531e49161f5b11affcd50716b8f64f0e973f3a1a1491530c33cfb293df5d515d3406badc6cd922160c323a", "SEC": "040fd26f248ead0e35d09fe1c0fdcc7200de11633457d57dd0fbc4c8ddef7c173822d043acdbd252acc52c6b2823a382e0b96c3ba8493ffab4a871b98a0e0838a2", "TP2": "0416f543e42cb00afc875922ae6780cae35b9cf044fe16538bf294785501ddb2b3090e4327d1076d233d6006d39b63a4c8e72c7316613b7d5297537ff103a3ce6f", "TP1": "0407a3c2ceedb560cdeee862a86ce2783d4a0bf4bdf21a37b1de547bddf2cd213714551f555e01a388f4c2a2df07e0f1a53c41f1c096a0c830d50e2a0e4be2c857", "CS1": "0404891dfcd821f15298c948787fc6e94df28140134e9accb92aac9a07de99dbec166aadc9dac65e70f185950e975f7240c1dfd3865d256e5b0806215e13ee95c3", "CS2": "0403bc5f0a236271731e15554d3745498a6abb08a42bf0cf9fa844da1da2788267230eb2bb290c62e5c2ce533f930cccdd1baaa67da6ea5e729bfecce1f8b6d02c", "HASH_MPIN_ID_HEX": "6d3f66cea2c2765cdfea261c240b5fc80c39a4f784d8e35d757e2c2ccea4fb98", "TIME_PERMIT": "041756a2484f5a4c5e07915312580e638b89e83daa2b562b96cbab1872e396d4cd016eb2bb4206260e1764311914b161f6b61c5c115a171b556d8cf2c3cbdd114b", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33345a222c2022757365724944223a20223030666162643461613133643966333161323063363662343665343336626165406365727469766f782e636f6d222c202273616c74223a20223362636264653031623164336334333031363766346437613930623235613561227d", "TOKEN": "0418ba15d2768f38cf0bb1cd4dae432ef784f023f36f4ade3f490d2474cd003df400d491f3e313b4dc68d8773351a38b228a4ef298a42c76c6e629f5739fe00596", "U": "041f0ba9c7aaf9555de4eebcb016e597a75b9dbdbafb9a555565fa3ccb6f8cfec311919858f4586cde88292081617320472fde1f15ae3e29f86cc8c3efb35c5ac4", "SERVER_OUTPUT": 0, "Y": "0b2a71dfa1d0672d86647e29a21d99f9d13d8d6f9f29546c495322f0f13acd81", "X": "097cbbc27ed253d20851d132e7ef3cb223ebc2d42a7d767b765d0ef1f4201cf1", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:34Z\", \"userID\": \"00fabd4aa13d9f31a20c66b46e436bae@certivox.com\", \"salt\": \"3bcbde01b1d3c430167f4d7a90b25a5a\"}", "test_no": 1, "UT": "0406835bc8f692fb8d38e830625583fdc20c910973850a21d5be88d7c34277833b1e21ddfc587ee8d48a4c22723aefa11634aea4bced306ce0a80fef945519fbba", "MS2": "0bd0f9fc9d4c748b7b6da167269a64c3e48642a55176ff791d0343b4306b5cd3", "MS1": "0c7deb224423caf8a06965f2b9246bac63b186c6ec05a028dc6d449e6629f30e", "CLIENT_SECRET": "0402cf0505c978790bf5bc58c924951fcb49a3dc318527c91a4546fc53d5292ac21901d96353861029fa8da9dbd0dbc17e614a5485cc21e3fa71e2360838ee49a7"}, {"TimeValue": 1437055594, "SS1": "11d662c00d0d3f881404d2acfae22db878562936d941a374b54ea509605895e52317a9b55f74077365cf35e4cb543199c00b96437f610544c9c7dd88be2e89ac238b5b4c798fdc4164cdc1b3299178d0859455df40136d484da12517c858f1ac127f812070e326f34837d41d6fb13209ab2604e1365abb267073e5179e43ec40", "SS2": "13eb1f135f668afcc19c6fa675472452d5567fced6da896bf01d3365dbc097f400b3294d460fe49828f1a0377d2876c203ae5515e4d0aed54040b7150f8fe8860649a6f93a270aa7eeedc28777198f920270d74eecad990af949615d60b205fd21b819915ed7fcf77a15e390c4d7d8dccaf18fef2722c1b301995793d0ca8d02", "DATE": 16632, "PIN2": 843, "PIN1": 843, "SERVER_SECRET": "15061b323c65444caca65753324d843014fdadbdf9958ddf516679febb4f973e0eb5d3608dc32d0ed47ddf5c379bc2b724f0358ab8b968521d42ef1c22fc1a520a4e071d2bcb8240d63e3dd2d34646a3934336d126df77d344ac98004eb730a7036176b16db2c0bbd915ff95498ad0a1c98657ba41dfd2744be6942056f31e77", "SEC": "0400120e0d896c0fc3df240c1d87f9ce58b725ee008145f77f0f767fb836d7e3fa1125b87151e9b389255f4a1b85f32ac0ae3c62cb037f6f39fd4dbc8048380384", "TP2": "04237695dd784b268c7a03f11ada42ae65b200630f285876a0812df0f379d9f72b0cd5b68cc0abe0c20e2cbf2359a1a743cff27c79c0c655fd7f95d2820d759558", "TP1": "0407e04b24e6be31a1885f93424401b6a84614feec9dec0fc2ca28cfa962df7eb006a602e3a47b186fbfdde53e98fdd98c785d62a04e8e88dede489bb39ecaab83", "CS1": "04234a4d815221d901b0a37962bfba9bfed0658c55dd115387b1897bbbf63bd7bd17eab98d290564db64e3aa03b542c321760cb3354521ac991f1a24794505159c", "CS2": "041474f00ab39e397b3e7741a3beaa847ef604f819c481e04aee35e629924e008d1d5fd69687cbe1753a774ad27f206dda796064b42a36dabfb4aa4fa04dd3e85a", "HASH_MPIN_ID_HEX": "9b1969fb7539865c49463006891bd589b2bfec0afd10676df6fa942ad115222c", "TIME_PERMIT": "040979b536bd351f19c6feda495cce4705ffa80df29de789c37c9168887041e58e208cb5cd538ad4a1ab6a598112f7cc758159d165742697287a0c01ea216f4312", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33345a222c2022757365724944223a20223436343637353838323234313132336565383137386238373439306639653637406365727469766f782e636f6d222c202273616c74223a20226532383537656137326433373861383061323435653165626531363162343561227d", "TOKEN": "04178da1177afd7bc7787e77749b85714d60424319395c86b96d49b2fb02a4bba60702c87904b0aa6fc678d7dd7223deebac03674ca5367d2cfdd32b554f2af0dc", "U": "0405210ebf2e6f2ed2d4ab9f513d4dd154f93a2649ecbb591dd749b64220b6ed100387b9408a9abe4e7423b440b252447cf9d92bd04cec5288e894979807822f28", "SERVER_OUTPUT": 0, "Y": "141552e7c7d7f6e8e010326b047cdc37dafb5b1a89e20e1d069153571fa7c995", "X": "0a4e225eb772d11ff7453f98fadcedb69e458c66cdce08cb14ee5588edf757c3", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:34Z\", \"userID\": \"464675882241123ee8178b87490f9e67@certivox.com\", \"salt\": \"e2857ea72d378a80a245e1ebe161b45a\"}", "test_no": 2, "UT": "0417f25cacc62825b2ab114d689ab3d5b358c107b920f9405707d7f1a30025241f1c6055dc48c435048e868787bfcb6a4df000d94baf0764e0c4c60a76192b04ad", "MS2": "16bcff53023fc06ab79929a6a6e2ebb780c046868abcff7f17610a6b00ec124d", "MS1": "1066cb3cf8ceb0e0f71e369ba741f80e731b53207b1ce2dd2d3e8a6400bb4edd", "CLIENT_SECRET": "040edb7613c00cc632523466e9582afab0fba870c22793ebc47ec8d37ecbc538da03158232ad98096b902b2ca063da3b582f0b84d06d2afe1eecc2083dc18a55ef"}, {"TimeValue": 1437055594, "SS1": "096184dad48551fc6be718d6ac6cff22b2648c8647bf3e98d57d6b9bd63125751dc9a73d7690d0bf2e7fd158e7dc950ac24c08fc9cedd3cf24a56914037ade1819d97ff25c8461b13ede554e780a15c897a841fd15c49b4fcec3bdeedeb5bb92185d89f0ec9ae915000869f7c9f6aa689bc1dc14949acbae73c73f8daeac3ede", "SS2": "0397ff8864a8a437731f3f70bd2fe73eee5446a626922522691dfe4b8881bacb1e51acdd8ddc023be9f55fd8ed84f17e2d1cbfdc40806b36665ce8819037bd3a2307a22a575c96995011597414e99f3b6c54c7f92650190be2ea70371623fc401b5867fc94fba21916877f5b1611b6ac9cb62a5a223433d58be4c7c88eb1dd74", "DATE": 16632, "PIN2": 7972, "PIN1": 7972, "SERVER_SECRET": "07ecd98bb128b1929360e10fb988bcc4835f2805cf044e4651eb31b0740c9b2522a7f9a2b1e657b94338f52a6c3ae3fa82dd81449c34a2e5711f97885a0337430a171da6d485afbec18b3e3bc9edfb06db32ff83cf53062da9aec4e437bfc04b19765945045a7f6c9328864c67420a83b56730653ae3fa3660e0a9c07fdc05cb", "SEC": "041ff80c769451bf49ebf438834f3881834095a1e6530476eaef9838546a688b4c1826f5dd251bfcf4121bc10ce15ddaf5ac131dff57d09e697afe1f63dc8f234f", "TP2": "0404dd64f2e493cb2dd84094aa0718c4ef7a246d5655352dfe6bd1911466bf35fe1775e0708bb99717b784ca159298f7d69c3c1af4c5f978e8327308fce4023af0", "TP1": "040ef12020fbbd48cf4a6d044bc4cf0b5e5df1e5afacaf4d4ab97fb0e1110ccb521d5c6c2e33712b15df50a69517dbf6531cbb8582ac2cd83cdb442bdd496616c1", "CS1": "0407ec4413c24e35ff0be16a0a555278bd57e0815f351b9d8217cfae896c4f066e18a2b4774ddf99f1cea6b16961abb2a41b306c031dd6736a08df12734ff1dd38", "CS2": "0413b3a31e3bb327d001f5fb4b9a10333cf1f3c2a0676e9f41b78329e34153d0631fb07d132ad8359ef92035ceb43594fcf7c0c5d70bf99b1271fd70c5bcc03d33", "HASH_MPIN_ID_HEX": "723060d6d62776526a40cdcb0234a8ea0b447f54ee16c1bdee7a97f85359cd43", "TIME_PERMIT": "040f7b4da94cc4af4051863a4a27b0c90e09df6d455a25038e011607b7a88a95c904d57bea35811bf625facb56ee00e720fe8d5698dba0567c7a2bfe1e89187abb", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33345a222c2022757365724944223a20223464383335663032663136356436646263643062343339306633343937343930406365727469766f782e636f6d222c202273616c74223a20223066613432636461663133353033396434623335396632383038373934656239227d", "TOKEN": "041aea90e77d809204fc186e391181bee0f87e7a62f967555e0b6c8ec9cf3dac30004f6803588943907ef5ec93c07f1828aaa01453fa364f5a8b1d19f82f08321f", "U": "041ed3f1bac02f8bb2656b014ab5d798da097cea6a6a724b8774cfda0e3f49f5441aeaed71b3eb3d968b7e8f526de58b6eafa51f023a49016c0c706ebd3f537d50", "SERVER_OUTPUT": 0, "Y": "200bd00a38aa3f27fc7a67b344089863ae33ca25d61987f57621ba409139f9b2", "X": "18216cfe7274c2f260dde0d658566844d6feaf9bfb6455607f31b0d7d7defbfc", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:34Z\", \"userID\": \"4d835f02f165d6dbcd0b4390f3497490@certivox.com\", \"salt\": \"0fa42cdaf135039d4b359f2808794eb9\"}", "test_no": 3, "UT": "0419a60643e9d6e8fac87b6b1c6dbd2a2d17b715b098c4a4e362770dc2374fa38c17bdb659f6619b5ececc1a2634da44177df04c695e20ecb11c56c8859e2f1d1d", "MS2": "0bd581f3df3e1d4165ff9abb2609e7b235a2a7b3a871e4ad3d25a1ccd987d51b", "MS1": "22879582bf9698f145408977f6537092b299dfc8a9dc416370b3e27e7051816b", "CLIENT_SECRET": "040645f40aed8439c91174c7af6607927865d72bbe6594a04b5e5edd6e0393abb91ad240f06e2742ec5bef19c2f142435ac57dca003f8646211a80fb639720756f"}, {"TimeValue": 1437055594, "SS1": "0e8146d948b9d70b5572ad07aa8f51dc5d39d85679035ad20cb80cfaaac6ab4b040cb9baac13691e406dc1c321b354bf2c1d42fbe305715e54fa0e1e672b503f14b291275f8773416ea3337ef0b8a08e2f7f688d6a249d215715d7868496990d0866967bb777a97f1f9ea4e7d4f6c1f02f440d2916f78783f6ff51ceace6eaae", "SS2": "1b7fd428ac1b04f55da8832dab02996da7f43afc2947ea7131ff1a2911039fb805267daa99479588aebfe4973c1176f00c55a9c95c4387be2744f1e3e525ef78213d5b5ae859fc6a80963628e20f150f5a775a64e90880c89928b47ecaf067450986f5e2cdb1d7256dbc67f53bef50d1d5c03410589061adebd34595aa4f65a3", "DATE": 16632, "PIN2": 2095, "PIN1": 2095, "SERVER_SECRET": "21b7b1cd48fc25ec6ff595fba12da288a05018fe6bb029b7246509f8da4b777a1e85967ebf2d094cc682dd0528db93445f18f0152a3f4a8c0179dbb46deded0f1cad8fcbd074489bacf272168b5321e4a194682da5dd454e23ed64b37d237f2704f1dfb4e183c04f8b0afa3fbe35a4c629b62539c1dd92911d7fabc30505aa6c", "SEC": "041f7e3b61ea5cd8708f8ad231319f0917c68d313955fd7848e6752334b51dd6511c3d2e23f208ea0241bb3f1817b6d5b645b45ebe6b88e9b122b68cc439bb418e", "TP2": "04006fffdaf9375cd9b278d29c9c0abf39bf0c4a0effb1972bc7721e4977afcf461eeb095e7e3ae1597f51a39543af218af70f506387eb462360379d0cd2848904", "TP1": "04110f5163c1b7702ec14cf785f76aebdfa033a679a26dd0144977724d1c74d8f709780815f04f1d684b53c349e5bd89760352bb9b99a9343976314ca127c1a50a", "CS1": "0402d4c9a2bb32e0b79af40e704d4c2308564bcdf1fcb0a413aef5384966cef45d03b94909206a7b77c8ebe9933e180960dfb0c35925da3be774a08576e8c1d672", "CS2": "040946615a7ca6415e12272626a969352c14f9b27c89ff5c676fadeab625173adf0e7f66fb774c4326b2e9f91696a4e5dabe0aa9f472dccde05b316497fe6951be", "HASH_MPIN_ID_HEX": "d18f4c069b67ef01c59ab00ea108d313357a83a6c7c24245a43203d87189bff1", "TIME_PERMIT": "042105ee8fcf28921e3064bfe42b67742a656f29038cb1e848e077df11dbbb2e671df987b6399e75bad05e28127cadcdf9c0c8731569292407afcfd3d2c17ff947", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33345a222c2022757365724944223a20226262363164616262656262346635353761353635623965383239663762613638406365727469766f782e636f6d222c202273616c74223a20226135316234333239623639633661333739346137376330316630653966643539227d", "TOKEN": "040490b0c665b0fffb5f0deb68b353d527b22553f78ed2b411347f5746b95a437d171cbc02a442ca4ad04a967439f2b68428347d3711820b1a0d6a1bfe63baf1c6", "U": "040b770249bf14a784abb093b016aada2d51fc19fc24e2ebe81b26d387c39d5b1e0a8100b1637afc48f9e652983037a85eab3d7d1521d2fb1ca704d5336ea7b6b9", "SERVER_OUTPUT": 0, "Y": "0657e0e6c275fa357de7efd9da1b0d514a70bb5f433c3202bcf0eaee9efb3800", "X": "046609f66f3a0ed3731b585178396e3223485273fc86896ca4f211010f80c3d1", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:34Z\", \"userID\": \"bb61dabbebb4f557a565b9e829f7ba68@certivox.com\", \"salt\": \"a51b4329b69c6a3794a77c01f0e9fd59\"}", "test_no": 4, "UT": "0417aa87bd03835346b19dea1ec2f36bd1cc11889aa3bc531ebe9dbc16d70c385010ae0ef8893dd44f56d2886381b5e6aec8cc378644b376b7651f74b51943fff4", "MS2": "22c87d06f40485ab525783d3bdd711ddefcd867fbb2928e73568d8740f899783", "MS1": "0dddf02737cad83ab6ffed65fd90c869e019bc554504053da39a7b22d2196a3e", "CLIENT_SECRET": "0418e5906918a219a2fc340c39badc084bcdf3a56f06bc6f4be3cc5ee3365a2fa8046c0c52a140d03723f72469624531aa1c69f24c1fbfd040648880e68c8963ec"}, {"TimeValue": 1437055594, "SS1": "10a3adc1c8741b9ad13f4b076f9e1ac3bf5e8722079cba07c6e5bdf765b4646100b30929076fe47aaa60f9068edf51a513de543f48d20e3475a93e60070ab2910077d4224213c623467e55d15ca099273efcaf25c58130762feff3e4d35876d21224b7ac1cc461d4306e680e03b5a241a71108af57b2222ed27d373a30b3a786", "SS2": "13afc176e27670ad37770822255cf4f6c11f4294d42990448a33a20f7fdd64ff048431f72e300a8d276d60db5920901fbf25ad7a219a5ad1cdcf53540b0a07a907656a8ff8081154c70e3bbc95e0ac7d9b67370555419f061a7f86b1435e29a408eb946f33070d9dd10995e475f88e39525d1c710b169485782f3a2176371dfd", "DATE": 16632, "PIN2": 8078, "PIN1": 8078, "SERVER_SECRET": "00884ad099e601ebf3ec8f215421568d220fb184c873b9f207a0b88fe82760ec11e7d2c74dac247f7ed8c96a04081c2bbc1f1bbc0270fc960cdd1c54f06064c100f4bcfa3c9ee1ef74408bf3e6f91cc81ba0642b42277518069cc65e5803c96c0265a634fdb90aa97a85aa529a0bb48768c239713c041185d795c9975bd8e557", "SEC": "041d06bafb14d9af567985b4b4f8c0962f39bbfe1af8e659880f1aa673c3617a990c9c348c7a930f23ffc58761569fa274a34eaa42ffe5f53fefcb73f0e2cfffb2", "TP2": "04202748065930898ceb38bf60b3977a79a3d4545bed8702f587909acdd35a78bc1350dc58fc5bb5293dbe8be5d4c1062f0eb167e4c3abc14416260be73a5ad19a", "TP1": "0420d58ba4214c220457ecb2d3d074be1cace5fa7ed0417855e85ccf2f7ef98cea2093565db14cab29bf3a56915ad570329215ec6bf1491b48279ed9f6ceb6959f", "CS1": "04158933bd760bcf6e34da8051c8f42a82d6e66476ffcf7aafa594140d2a145e8d14a6765f7a4826e00796513ae46ef490447cdfba63be0e979924dc1e867848a6", "CS2": "042047915e66dcf1dfe0316578848a5c594b20d836a8425b65aad53432df3b668a190d40d269d926e812da35fd78f5953c85cddf9efbb2f856c9f3c8f1750c5188", "HASH_MPIN_ID_HEX": "fb3f7665ed8cbf079670fba05eb827a2d763cd486cb56aec90419d3e6291a868", "TIME_PERMIT": "040288790fafb7a98c9459147501eb077be6733863eb70f71a28b7f102b8319ed406c6bdde46253ac1c2a8772b25c2f67391f091a8d090885039eeb895b39b6ccf", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33345a222c2022757365724944223a20226639636163656331303335346635303836653731386436303538636139616561406365727469766f782e636f6d222c202273616c74223a20223735623266666337613739393839333534343730633438386364383432386339227d", "TOKEN": "040537801d02d60a83f7722fb24e8c0d9c9d12e2c9b013bdd1d2aeb62c6d118a3e1f432ca640d1047ad6e77ecb65fce80477aa1dec572cb9712d39035cebd2ef87", "U": "0400804b917f101a53a7d022ab6196c94a0c7841e085980af4c013b8366f4ca110232c8e1b45862d111ef5bbf8356774b9353571d205b6d36afdc4cf6054db6a06", "SERVER_OUTPUT": 0, "Y": "03ee9a72b9df62462599a9cc2693201543b21a47e9d4409af2669c4ccd2293f4", "X": "0ebe18c010fd571b9c6e07e70a75b0ed65bc8493cbd50dcb43d7ed4f18b51e91", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:34Z\", \"userID\": \"f9cacec10354f5086e718d6058ca9aea@certivox.com\", \"salt\": \"75b2ffc7a79989354470c488cd8428c9\"}", "test_no": 5, "UT": "040a6ae56ecb3db3eef308351e4a4ed31c89d336938f866b8fa4d1ec06ead94e4f19f6ca08e54d35a45a3029714bf72adeb6dc533ff9b3aa0530857a2374403987", "MS2": "0bc993a892c446df37412605ce25c6da06c3c437a4d9d750633f5ad9dd09111b", "MS1": "07b43fa17f0c70a4512c6f68d4707cc074e27ce760838bbc1b8ebb21520d72b0", "CLIENT_SECRET": "040266c959c3443ed20985b29313905d9bb2f04bbb9c8becafcea36643a3a1e2f21955cdc0b0e738898935d05e4e13db7e88e05e0c59716e4d07ca429f57590333"}, {"TimeValue": 1437055594, "SS1": "0f78b32b38ba387fd26ead5e6f4c432deac4690670d1d0f075424f66129cb2ce230fbbcbc83fb5f1c1b1f68556bf56328ee9b1af888ff0514f8c3ad218d24d990dd9c23da8587b973ebf37f6b264460fd2f94b7c33b50421c7a29c1e8191767e14271a3071a0d47119722a51b25b0369ad93e1b624c275126145519101b3795f", "SS2": "02d08830dd0005f363fdaab76e8d1ee272fd3422fb07aaa82f199cb0e76638ee0abb2931638b889e78cdde8c682d6839a439451d68f5f1bf6ca0def20bfc588912d3ba0d2e11b77be1cc002ce4f1005adf8cd3f67f75d00a76669d167782b72a0d5235a3f35c4df015063074bda3dd5d3bf8de5aa48100a94d053cf9576b0ad1", "DATE": 16632, "PIN2": 4279, "PIN1": 4279, "SERVER_SECRET": "00808d5dda133e05e941a1f8d008b570d46d880899177cf31fcd94c6ecaca28321944498857f37c52582961a24440675180374c9ffd06d77fde95e43cfc5d420153314a34813bf99f7bdc14e9725cbcfc6da1c7fe41b93a79e8c281e236df6f80f9f21ba91456fee210f63c7be9f836d6f18a66960eb11fe8125ee3dce9a3f8b", "SEC": "0416b67473f9566599323edf11979b4b76bf103729c451984abf7e4c3539cb67f5166876b1e8bce28027aaec38a79381e48d65fcea0c0c05ea0f4c7bbe5bc1b992", "TP2": "040f8fb9d70f76911319a347183879839b297bd8be0eaa8e3f75e01446513880d8000aa3d2cd9d8bdd8a4eb1a830ada0fbb9bf110d0d776d492b7043f25a4912b0", "TP1": "040fd9f0b5dd776b64ce58bf3ca58fead5b40d6f6cb79ba26f744a4d640f869fd2039b32c0daa0f6ae7e7624c2959ce51e7f333365ec6f45307fa65d3d1a4b029b", "CS1": "0402dd9f72640c50b6e9cd74303b43d90e566aed4bf72cea2e5054c409b6242d0b23f1cce3a1ca0d5db47218e370c8aae17d76fa6cb87d5a844fd36494b7bee915", "CS2": "0404317543e7e1f968d5c0831ea71f9cb928b78f0cefbf6ebd3172bb42381d8a8e160cc4556c1bbf587d92f53b6569c6a4924fb50bb12cf62a468507516697b6b2", "HASH_MPIN_ID_HEX": "54bfd095e20f198fe23a2fbd5eac675fe66b70d041568ab441c8e81edb03cf19", "TIME_PERMIT": "0423394325000be64a6d3f77037021307de7740b873e232689bfb75528f036cda41d33c9b8891eb24e4f389cbe6f9838a7bd301340056508ebd6523024cdb1e07c", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33345a222c2022757365724944223a20223964326437333338363163383864373337646436623039663461316430303330406365727469766f782e636f6d222c202273616c74223a20223137313262376239313532343363386637396566323232316363666662366439227d", "TOKEN": "041dd1ac80e615447d65bbfb0c2f58743be6a8b1fb9dd77bcdedf2f4028afb0ace07f358be0aec025b94e2839f865ab93d5b08f8a668659198718edb82b43de8d9", "U": "040dd5197c3d2713e06f4ed7d3ebb4a49df0b7642b270fff77b815c8ce0d39cdee1558346f5cd01c13acbab64d9bbc5d3b02b0188d75435e6a16b3a0f55cb653c6", "SERVER_OUTPUT": 0, "Y": "09c5df8d16a98f6feada6abc8d4be435176e1020456cd3763f6e71524688259e", "X": "093f87857bf06fa6e997adb38f997a9a0e96b56e541a4bff4bf89cf806422649", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:34Z\", \"userID\": \"9d2d733861c88d737dd6b09f4a1d0030@certivox.com\", \"salt\": \"1712b7b915243c8f79ef2221ccffb6d9\"}", "test_no": 6, "UT": "040c765d42a810f20b1c201169e867c2ca96699dd8bcd992b79736d38cd0a9ef0411844e878dadc48aedc8a2bd3c8f4cbb93f94c7df2a314bcd0846a342f1a0dda", "MS2": "0729216104cbb6bb3896c59f9b8592c9ec108c8e2859f0d6f5a6ca31a23e1049", "MS1": "05bba4fad041639a12dfb112b91ff152bdd3d48f91384474e703faae774ae303", "CLIENT_SECRET": "041cc63c1bfad23602b7a060996aff8e53f93128b4efffa724c5144a1a43c6c5fa0a66969c0c7e903f0c2008882a2840478eed6a8d83208fe576d9d627e41ba22d"}, {"TimeValue": 1437055594, "SS1": "21b6f31913fc69f324654dad9f88234fc2f4115a474d931e96c998871c9989ed0118f1a767072c15625ae67ee9b9dcfaca96b15fdca09f588248ac588964262d0dbd595ccbbea6520f30945537c80b4c118084c894244d979e824c322a1cd1620f88b875cdb1aa21f453bc87baf3b9886bccfa4cfd0ca95f7da84dd7379fe057", "SS2": "22586f28d7b03e1f3a3ba68fceb1ed27b3873ca2c5b998e16906a8fd99ac95221ffc2ddf57ccfead7a2660891787f9275145f4fe8177255eab6633f01ba59d0e18b9b07f51f4d0a3479f035fc94fe86fb005d2411cd2b4669cfefd7b6c238bc7129eab2670df19cfb297d884a8569ff4b24be28578e71300542770f9acd928e4", "DATE": 16632, "PIN2": 5746, "PIN1": 5746, "SERVER_SECRET": "0e87db97f7eceb032600bc40d6d2a84c6993220624d4efc46292e65008d31edc061c3866465985f129cba519e396263f6184ac5c0da5e69d41a3905cecd830a523ecdfb47ca9175a7c6728e5ca02ffb930a0ce5323e7b0c438cfb8fb9faff40d10ad917b37db62905008ed014d1bd2e0b47c1007b0b6e87b5a6c109e01d817e9", "SEC": "040cdf22125169f73aed4f857579d183e03db05d64ea168f55b0275bc57775f2cd06b262e4309ff803bf829ffd6774d04d52ef0786f1a3c41a321cd7a70330afc2", "TP2": "0416c43c08e70511669ce599a2a538be12d3abe3582cc9bbb6621411252f4b55620cf40aac5c8a91a247f3d9c19c4cc41d27b66b4edf7f0e69f806c4cde17f9c33", "TP1": "041c7fa68c05c3e594ad2d9d0e4fe6b6e4bbada23a907945d2818d02aec635158e0b6efe2f6bf1e2424d6df92714ba9a2d4e64a8243fb0a848eb6842a527cd2ae9", "CS1": "0405c2bf4e5c9adc83a276b75f13a905c151ef6ae6c9bb3d7cc0658b7c32dfe91f23afd7edd94a83e7810bf109e1d915047edc7121f758663a89b7d4123424d96b", "CS2": "04046cf112bc3fc901b3d76e54598c007d63db4303f6c06659a2b3772a320fc035233c50c2bb0349b2e9269b8a251874c2ee8909e92c42f3229ecf06b62d3170a1", "HASH_MPIN_ID_HEX": "206f4a9004b84070917957956889423641af811a1492e62ba605048f56fa5eb0", "TIME_PERMIT": "041d957b1f177871d7e6ee918f409c5b2aa1488550c0c102e15dae1f8ccf51d36f01038485126f678541329ba586abd0e9737597eece1021796f13006b894d40fb", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33345a222c2022757365724944223a20226264373731636335613832616433393766663230316463643739616432343066406365727469766f782e636f6d222c202273616c74223a20223132373661306331353562303466383861613139393530626238643734653331227d", "TOKEN": "040613b45b65347385faa4b8b748de0758c16e62f8c0d1c0aeff1153955c4e9f091f5d5a79be1b176c316d20772b6b7bf58091f2cc2e3b8503d47fb2acf87f1280", "U": "04079822951ad9acbb6987ce9658b98f85f0a1e508bc03771fd7ad913726a2fb1600f8e000ea67f1e7fabd7c2ab65a154baa45bf267a77431d73c4d1f79f2d973d", "SERVER_OUTPUT": 0, "Y": "22083153ce467aed9bea168eb47189832661c35ebde5b1408670c212d91b1d27", "X": "0fffbfc5255dfb3edf9acb19266582574be3cd332937db79cf3d4c90bddebb25", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:34Z\", \"userID\": \"bd771cc5a82ad397ff201dcd79ad240f@certivox.com\", \"salt\": \"1276a0c155b04f88aa19950bb8d74e31\"}", "test_no": 7, "UT": "04137640386e8542a5b1b21d70b69136ee38f15615e4f2c621559a544ad144d48802c7a8dd2b9624f430d5d1b804ef4a6407bb3844f6503f73bb5147070dd64be0", "MS2": "0583c820e45d89f38f5510516e8be013c64b81b17dac596589931a0956bc28e2", "MS1": "20d705c20f94e32d379c8bd296897b2ba3d8905bb2bef4536f359d59f32d1e08", "CLIENT_SECRET": "04137540232257b4a070bfad94eeafeb04b9beee811b7762ca389aec02757e4b2921aa0cb981584c00499328e01114970d2f9da4608c5954f681090931edce3834"}, {"TimeValue": 1437055594, "SS1": "20a60f2545d0335b128292a44ec19a0685de6e8e11a7f962a90b02ac3cf54ef5161bf52be280b96a66cca3bfe5d4bd259eaafb205b5ffb8bb1947426fbab40490f679d1a5bd8279cf482f1e58f2ef1b01ef8a2f276f40b5f236b791ba517d01a0c11df7e7bfda3226500dafcfa7b5ac625be94b3a34b85c784ac7f22bde58f20", "SS2": "13ad54fecb98e01a03bcdc960316b28605c4c857b47d0ae6f9ad0e81bb6be1d901c8a16831756e2de7677cdf9a879f6afeb8df5695610dfe3528a4bd9349e53f00268b0b7e3b9582a4c424e57e60ef9e0ec883fa3b39d6791559fbd60a64876c10f32e1464ccd70bd24cf7fae68db26e883c23aa1f728f0caaf3fc5ca9a59d59", "DATE": 16632, "PIN2": 3888, "PIN1": 3888, "SERVER_SECRET": "1559df9b1b6d8f7f920aa73f7ce7f6ec7532405185e962e63ed2ae12351381ca237efccd5acd68df2276e1e09bdb9a3fc30d38d86bac755d6deed0ff61f509282366658f4113a7de19d9646d9f6552b0aeb327a20473e9f1883fd0051739c0111640ab70cf4ed9456fd09529a016f36e98442156d2f7817c185ddbb61f3d2dde", "SEC": "040a051572b5b03aaf2c9f8492c22ede2d6df6511468954aab48375666ad6864e01e4eac5b5c25adc87a8b02884201c17466f2c6046f2fea51de98873c4f0fed24", "TP2": "04202284eeb4dd52548b3c812d6355d173a243cc8e54080b2658197fd36398cfd20083e25a1edd7570833cb4acdadd9747b149ff0ff0d4b8bfa3cb6a9acc302a79", "TP1": "0411b7463d6cfabb4363f66f5b69caf4715f54c6f58da20853bc6b27ab82fbebf31c41b9ce746e4b14c51ac1c0ad4cb95960ad758bf3acf76b0274e490dd25161a", "CS1": "040d6e106c1e31e0a1e43b641b35e62fd9e31b41c513bb7a736d7eddf51613c7830f16e3cad33f63541defc7b07dda7e5a0abf7bab2548798b838e68e0f705b60f", "CS2": "041d6d7163274892d3332e4cc38bbb7bfa8044b822fa766e51b292474719f0bc0508d25f620b4b774ce10edd25527c9ff42c959d6dc3ea835bd33f15032b99f169", "HASH_MPIN_ID_HEX": "366c1db0bcee4f5cf381137eabbef20459ddb79539fe0376164598ba1e83e3a7", "TIME_PERMIT": "041a0469ad551e2134f770b4a617124a5ef45007f84d0d8be133f9736adcf1a4b120ed4638c346c940d0447c4d1cdd251dfe7237ae2bed301ab2fa1123ebed5a5d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33345a222c2022757365724944223a20226333383535623531626539366566633335363565626261373338393334373838406365727469766f782e636f6d222c202273616c74223a20223265303034653133626563613630616465353639376339363238326230626439227d", "TOKEN": "04072981d4a182e4a97810fd7c5b127b271ddb25f642e5c73464452558e495b1ed190932c9dd1629c5f1f2c812b5b3554822bc18444d427f1f490192f47a6d8940", "U": "0402cb9f9df17368decb230ad2e1814d16a3c63dadeee1f0cf4a42e41049970bc821dc8de133ec69bb223d2087bff06f0f29c6053a0e1bbd990d3afdc37002b914", "SERVER_OUTPUT": 0, "Y": "13904ec0396c16e53b85eaffb95feb346911d840356231e2e1080523c2dbdcc2", "X": "1827f87c0832033e94c11021fb9521f41bdeb11e03badc34bcfa7d3c25646d88", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:34Z\", \"userID\": \"c3855b51be96efc3565ebba738934788@certivox.com\", \"salt\": \"2e004e13beca60ade5697c96282b0bd9\"}", "test_no": 8, "UT": "0416a964393c27d2ffdc9a7321ffce937d5928e87f912cd279e621d01a351da8a31a4089da68f56e8d678b6143fbea3ab0a4e521186272e984dc7157ae020ce719", "MS2": "069f5c42f679b13e16427fea489e1c2a8c514b64e0ab645c4ee9fbb2b91d9e88", "MS1": "133a893ca750b4d3a8ea2d8f60a1f1548eb6cb427cc2ee946a1d59c10b51ddd0", "CLIENT_SECRET": "040f8ba4c0b70e5bcf122f44ff03bfa2cead2afa4c9f6861311c021d0230835a090b565ae081547189b254113688ff0ee6a192e8c10150bbc0d80724a9d3ad43ca"}, {"TimeValue": 1437055594, "SS1": "15b45fbd93ddb2bd318f7bc487f92dfb8235d52208d1c830060bec546325ebe706a873544a271cd4c9d0bea6d0ecf6f16b0467280c5ab6f2ebc5040835afb0a61ebe5200737be76a1fc9bd391f34a7306086a4a6b2dcd0397303c29d13dfe1b00c58dabbcd320151fa44de1423c830926fd7fed46423b500c998abcf659f72e8", "SS2": "1dfce70e7c09807952eaef736cc997e4c4ee19b402da0db4378d784f4c3e7a1009d4d45a703792d9cd060948506d69136211cc19d635288c8e64d41470af5c8107e9b6e418c4b6b3bd859da608d691e62b7205df978443dc41ef1d5ac6bba36202f8e0d429f84872be9c1db38b1dfe4253eca8d4af7a3202ad931ed0692a3c9f", "DATE": 16632, "PIN2": 8616, "PIN1": 8616, "SERVER_SECRET": "0bd98bad2de5a88851e2814670e0b3c8e39732f147b333eef47c5361747bc13c16e7fb89d4f8ce663fa125982cacf7aee3a52434847f4c4b3df4edd56c0358480ed5367d49011f07d9542e8aff025352f63c5c90228e461c230f4668d0fd5da41e3ea29515138667be93a9392d7b4643349c907a98d4b97bdd35fbb76e58a12f", "SEC": "0416589fbab198df5b33aa40e0ffd9bca5ef1b8f631ef0e9ef5f6e91e8183762370890d2ce12d9f8eb1a4d6f9d50e25cf0f64c76ee4e43f19f04db56badcd9aff7", "TP2": "041d478719a1858f2be62033ad8b114a3b167d2492f5fd24ec7f0583b11e84903022d14127d8fff71d4eb30e7ab38308ed61d5f680c69342d1b967e97436f18677", "TP1": "0415b0a5f32aef0e790255025bde8c50c90b54ca77a88b8de89677df98148c329101c2541fc654c40b51be9cee188352f32faeab107888416b1dd2a9ebbadafe71", "CS1": "04068220d5205b39a4274be964b0195c9f66581d4bc963b9688a7a4d4b413513ac23bbc9475767a3482f1e50e3594389f8d9a32b718acce405a9485f7f55a89b21", "CS2": "040259c9cbe5e1062653d070ddcb9446b991f70c230a8436028a28668159bf9dbc1ece0f3c5fd56e129194a7147a273ecc415767afe801b2be85cb3ebf923a1088", "HASH_MPIN_ID_HEX": "fecf76c1416f129206e9e2a3fd3bf7230788c1130756e963183521dc2ceb3936", "TIME_PERMIT": "041fcd55a07d40cea6e676d248bd4601707543a721b91ddab9767e27bf2285cad40e63fff0540f193af36f520b9a79ebddf50ba70577b79da52c312f84e5d3a423", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33345a222c2022757365724944223a20226663326237613563393333623638323238386238353531393932333231656637406365727469766f782e636f6d222c202273616c74223a20223137316632613566643065343861303832373336393531313363306566666434227d", "TOKEN": "0416189809d726522f49c6c2775d676ce214724765b96f894214301cb93256d980186884fac7a60baccff492fd0916db5994ba9e1978cd6940df9e30d3b39b0c34", "U": "040e847e2e6a0395afd733602471e1eadf6dd0ccc87fcd6645ca7053869761da29067a5208c9414435ccd16f072660d1ac8070542bb266eee880e2814d08a4857b", "SERVER_OUTPUT": 0, "Y": "210f6f0628759207ccd4afd19008636ee83cec2779107eec7eaf596a29fd51c2", "X": "191bf4d04d0304dfae4ecc5e575e559382543ab85d307854af4587629f311d51", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:34Z\", \"userID\": \"fc2b7a5c933b682288b8551992321ef7@certivox.com\", \"salt\": \"171f2a5fd0e48a08273695113c0effd4\"}", "test_no": 9, "UT": "040df60d0990ed42d0db975d57c668d119f650eceefc9fd7fefb2d62c3b0d4104c0ab892d482172d6ad5a182ebbd430710c44bbdb35bfcaf87f25e075231525fb8", "MS2": "02064a58282ae0e61eea98a840a85babdd77ff3c3b915226ce67bf1076ad03a6", "MS1": "21d5f449b6e3b14728e75da20a2bc1784a5ea9a1d7e59dbc10b91abb7e3c88ab", "CLIENT_SECRET": "041adbb6ca2f4dbcc6a96f29af42bce12a512848d77a8059ca900a988e168a16060172da2257ea7e5b66bffcae658c27a2544d49d07260fe170ce1e9e9a6f22211"}, {"TimeValue": 1437055594, "SS1": "141e3e978728a2fb41e7dab57554a13bfb3b17114aeb68ac060d0a9af0b26ac915769ab2c077e92454dac5f66e202f6ca0ec9729752019de9a335722bd97a3f520bcaf94545b998bfc864cbb415a00adb569c6df1bb4f2f9246ce4a0fbaf745a1b98be2d7681ceaf40a6e691c4b8872a358fa5f8aa1c3e0112d9817d51a7cacd", "SS2": "1741c86e32dd113eb4467b4a78d9e15e60073a2b908d4eb9fb9104b3e8c24a9b1115675a9758a8c4dca4e1ff098ac437afb0d1940089fc4bf738f993cecc0b08135861e863beb76c984604284073801782b1ac9b912aa2d1391bb7323dc752ef21ac7ab855835ef9746f0248d6d8ee4a86b81db96e9c51fa79472a70a0acfe51", "DATE": 16632, "PIN2": 2348, "PIN1": 2348, "SERVER_SECRET": "20337bec3293902531c4444e8284f42d4eb51413918908df12da1d7600575545043ea2e161cfafef6312d7f2edef02bf582c773556d0c8f3501d356245b91e4f04935622d5bd3396aa41dc24e97729b2a4f383e33e265d9ca2d9ea981e63eb641fbd297e09f8e352f191a53f9bdcb074484d1e0a5093c95c9c9787825b153f44", "SEC": "0401fe01b7e74220521184fda7afa64fed847fbe8dd1496b58cbd7aba781555a39087d6dbceffda7a20f62202debf0c74c9bf9d12fadfb4022a8d64e8b78a549a6", "TP2": "041544b09fca7a847edad1b33489c4e3cdc8fe866db6721615fea747fc9fad0fac204a528e6b2e6f24bb0d637ece931a611c276b007b3cfa674e7ea56f2d1ff9da", "TP1": "040a0988593db59971da281052f574d9556c0ee6b793b163b086979b5c142e135802873d6d75a00ac88feced64b97ef0484a6e44a53235c6b9bea9344b0843f63a", "CS1": "0400df063860e4a1b9dda5d14be9310e4483446d6775399e22e934466b5f45aede0fa360ef1bb0d05b37a709a04a796694d05212083a636f858a22280ef4cc329f", "CS2": "040ac186615a7ef8ced8cbd18836b77221ba1399099f730a88ebeb22bb0384c68f1f3c132c629563ddba438e49c7bc2e77dbfd45ed2e372bb2905d1a16ab673f34", "HASH_MPIN_ID_HEX": "3fabf8f342d8349aa7ffde40020677a89327cf8f349b1823757dbf1f08387203", "TIME_PERMIT": "0404e9fec1d87783822a1045c6e6d8097cfeabd0e8c1d207b69d896c783a7cb0390bd98be06f0fbd02f0b992d74a467391df5489c3bf5c481333c3db4b2d736d4d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33345a222c2022757365724944223a20223833323937346433326332333332623232313931653265633562336164366166406365727469766f782e636f6d222c202273616c74223a20223535663234326630353530646533346663626663636638353565353431626664227d", "TOKEN": "040a2556fa51afce0a90f79d1d854d6cdcfb52fa2c438a7ea8945d9038aecdc4fa224bc02b68200b67261de2b19db4e18e04e654718333adadf8a1e5ac62b2e4ad", "U": "041a6e6cb6c049f7a92f571403cdd0b6928c98147ed4c5490a1aec0b6e7b573f4d222a3113af8ef0bbb2e710986cd8282b3a847de08eeb993a05fc9b3897f1b88c", "SERVER_OUTPUT": 0, "Y": "00c868a8618a1f163ab63f253bd9478b45dbeb1058e4ad02997f8fd086b44787", "X": "036c55d0c2e96e8aeebbecd55a614d9b9f52874e5ac8e9f8dc70c10b1c89c318", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:34Z\", \"userID\": \"832974d32c2332b22191e2ec5b3ad6af@certivox.com\", \"salt\": \"55f242f0550de34fcbfccf855e541bfd\"}", "test_no": 10, "UT": "04224c0d3ff73ca962bfb64517f74c66870981dc30fbd85afb88428e910c8a94b71ab4357f81f2d5deb2f06c2b0ed97e349658f986f929444558a157821d9784aa", "MS2": "1ff3d2a38232e47c4c7bc1587e36944c1b19b779104a4c7985a59e96f021e41d", "MS1": "21cd3ca8c4c180f30cd2993a3ce4b3bd21d40b19321aaad9d559054699de6749", "CLIENT_SECRET": "040bcc10475f2544c12f3a60a11b893436184042ee603fa79a02f5cb71c12476e70627ea5043bbcf7402ac8018c3e9450542ce6d7247a1212d4a4ea5533ee7417c"}, {"TimeValue": 1437055594, "SS1": "1efd294fc0c35364e0e6894f044b9e30f2c4c9280f2da012caf742f1336bb72408fc273edfc93cd5a8b150513708219407ca23c7698dc69c2ad9b9b4f169c2881fc59404803590555df0b349eb9d4cc2d2af6743cb1759a4186cdc5ae39ce6631c776911d7db0bde542ec5704d5703c95401bff481081a8f1ff8b6e33b736c77", "SS2": "1664d545c4d86aba5a6a58453a324cd864ffb4465c7b78a41da63f599fb95aea1dbcd23c420c5cc782b21c26126bb9b3d8fee9eb442290854ed3afd8b6f219720daa5c9bc736bd2dc0b157837e5a4f76a34da133aac20f7478119c8d610070701c7d87210bbee7585e80357de1493f76985b191c0886d183829a14f1ee0491ea", "DATE": 16632, "PIN2": 3764, "PIN1": 3764, "SERVER_SECRET": "0b658e649a31f1b2c89d7d9176605f0b252b7ceadf7a46141b3774611f8d778e2391f1dd2cf7d0c753468b6ac07524bffc1843e5c30977ccc746ee8749c1a19720cbc776acee8912ca77ae60f30183fa006c017e6895298e5555db342328376003f5451780568a1e1db743b34f9475e49c66978c3e40aaf6813a6f2c2149f4bd", "SEC": "0418d813ea5d40e21324ee28f99365f5cec138a70fa67413fa93e800e757daf96910379e8b44ea28fce00fdc4d969976eeb8ad288d81b81a492ab66a05b736ba1b", "TP2": "041de26abb8acf859ae9a3c6326e34bad0d1ecd0d3390bd511cca14fd548e1ca9e01c84bcfd7fcaf973c75621cae682085d724af493f76bb5e40befe74c6fbc830", "TP1": "0402c3025492f8c511d2beae8b5fad7bbf5fc5bb512c072a7ab2c61e93b0c27c6f0b3b9e22deebe02cda455f925a360e92546eff933784e91e3ea5196f6df19623", "CS1": "040a35cfc292cc4e5962ba59ca42d53d32947e4c32b621b540cf7c9345a69e4fd61cf29cf801716e2121a9399895ea15b168d622d39e3974699a54628fd9bc8d45", "CS2": "0420259e066fe78067e79e5c0fc6dccfa7796b6220e5c492486dec63bed72d2a3621e35bb562249a268d7f35d45c762e5cd613fc562c976784d2072e1fcd37683c", "HASH_MPIN_ID_HEX": "289ee3fa5a94034840db16087cf301cea714b03ba397b412b6c2d238eda7c9c8", "TIME_PERMIT": "040aaf1c8b0119389eccc9d55067c55fe4c7bc7c4df846f071c36b14e996a1b76206eec4a0734115df02d897053a2748eab9b855b89b2cfd97db279ed95125240d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33345a222c2022757365724944223a20223461383734353165373132386562383931633137323235666664616161333031406365727469766f782e636f6d222c202273616c74223a20226533383063326662613635306136383836323364303136356136613639383930227d", "TOKEN": "041d85d6567e0d54eedd1e422272034058aa1d8b9564eb300f03ce562a03c97e641e9be6092ab136ace2cee1970485f4d25f2bdd03df9c7b3df4e87d57e3184dc9", "U": "0410f7e14f66e78f685c0ca94fb43a6413f186aaee4e80280d02e1edbbd5df1cd30d59ef9b76c9a79e1e75b1d6681eb973e42b3fd8a581f8117054017efac205f5", "SERVER_OUTPUT": 0, "Y": "1313bef2e23b67339555b6636bc3d49d459ef3f160960dcf236ec1bdd5fe4ecc", "X": "1b62ed7d224b20fa452a5376b61693a5eb86a25fcb364f192937fbd901215091", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:34Z\", \"userID\": \"4a87451e7128eb891c17225ffdaaa301@certivox.com\", \"salt\": \"e380c2fba650a688623d0165a6a69890\"}", "test_no": 11, "UT": "0415b479e438845a8f9783496f58c3e0bbc170f5f88aac26ee7749ca40562d752f18880b97b5d5ac266d546c99037c20d397d6855210e54b434f6cf83e6416a438", "MS2": "0eafa15a9a8e4c7abef0545ada244f2cbcfc68cb60ae175fca9506abd4e55ef4", "MS1": "17d6e568724ef2c669b1bf0955d297feb04dce2ebcad5e0e293f312b7bc5eb75", "CLIENT_SECRET": "0411a0107ac787b157e005fb89a255364bd04bbf3ced17a9814128e5d91a54b02e090ed6d82f0e7e04cd4c3f0c166db4eaecb3062f54479145988fddd992fa4fc3"}, {"TimeValue": 1437055594, "SS1": "1f084fcd34b7141975d9be543b44c3112cad21e3727cbff236e05343f1ee2fa422086b6f3d50ddd3da8f7ee496245af4e482e54db6328f84c9cb7eb781cf92151404a2f6756c0989419e503f623c6af9d9ee0a05f83d3c793dfead7643a871b50a14504a13781f12942acc491c9f4bfa8ab7545dcc4d115374bffcb24d9c3273", "SS2": "14bdde43fb67578a7e140d5fdd25ea43b0240cfdb65c6ad1c0a62221f45134b902de451be9f09cf64df6f0778bcaa45f835ed4bfcc793aa28af6b1d774cdc85a1cad226f32ebb0f93e0e7f2a46fa53ece6f10c7ed739c68e0832c3fc5159c6c500ba45c28ff2bd415cc2a985277f42cfa36d9eaffebcda4329699010a01ed345", "DATE": 16632, "PIN2": 729, "PIN1": 729, "SERVER_SECRET": "10886faeb52c1e9537f160f45c59ad13c6cbef0298b424c0bbf208e61316b06521037ca12d451db290461dcb0fc2a451b7872d332bcec4b74e99c78a47a825e717ef5d303331f03bcd840bfb47b57f7c4ba91c072910a1db102a382b804ef9951140cd6d4b47316f0c8d4b60d6372edd7768b81e73dd6adfaf1801719de8f237", "SEC": "041ab7777be5e4ff6999c68b6a529dd7ac5a83771a775dd311ea58facb40d7f652165182ca902c450f268dd3e211f6ddffb432710f713860c5f2b66f56f0a0f9fb", "TP2": "04210a8a1f478d5580722213c7a298ab465ae54e9a3a1c5367a0f9758ddd898b9c0dcf36efd81b3fece50f5ff86d7644fac4e240e82281b1554ff279958701630c", "TP1": "04111a929dc7bd39e9b03a34556892a6a07979182ed75575e5d761a7142e4fae470891df49934011688e91f3ade100070974a4ca455ee5c7a44383536d09143e59", "CS1": "040226a6456a3cbc19c97dbecb7113a43076a97af96d7ce2ebf5c305bf03d054e507d8740a9392edd53a672914fe31d44d379c6d40f7bd65632478e15ddc3ed7a9", "CS2": "0423a6f7b78cc09da0bdc47ac51a1be4c9c40eb822ef0023c71d65f2bed5ff3bc3049167a462b7ec23ca9b2e98885ef631a9419b0742358f6b96f25a0a83604a01", "HASH_MPIN_ID_HEX": "9b1289ae13d277a7903bf91c39f7354b16e520058edbd1582b398bac6a4e5895", "TIME_PERMIT": "040292e7f0988ee3c2b27556133f66609c6cec0e840fef77eb7e8e3d91365bf7a7221043eba23d239ed94bcae8db9e4dfc9e48a110b6cbfa64d4de1920b3daee16", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33345a222c2022757365724944223a20223362623731366431393537323239626261306234323139643131333332623865406365727469766f782e636f6d222c202273616c74223a20223136653432306331306632333731636462323734313663646463396162303730227d", "TOKEN": "041cc54e7d33164efe713a6635e05147067e51c3895e6ccb45afd0f3bd6b9285981bdcf87ef710f2aac842a55a442a31e9baab1796a052ff90344d204c73ef9cde", "U": "041a8e01b282c075739404db6c88c30e839e28ee4caab457f42e678ec13254510d187d4f21d90a83ef986c99694847a758b46659fceeaadf788fb0b3b0bcb10f00", "SERVER_OUTPUT": 0, "Y": "1482a173e217118752fb0a85152834112811c19efef329d22728576dfb630ac6", "X": "10dc5afa64c0f21e055838571419b9bad8c5359ad33acb5f109150e15f81a228", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:34Z\", \"userID\": \"3bb716d1957229bba0b4219d11332b8e@certivox.com\", \"salt\": \"16e420c10f2371cdb27416cddc9ab070\"}", "test_no": 12, "UT": "04160428dcb8acc3ee9723a8b964433e29366172fa1a150d4929400df7be89bb511c31a5029d176c8568b73a0dbc73526064443b38a25e9563705f48de2e90a122", "MS2": "1870a12d9a058102ac5e6bb8b25efd92ee19ecc0bdac840ac2b052b8276bb858", "MS1": "129927756c27b518bda7684658ce9b238a7ae61081d4673363cb080231964ba4", "CLIENT_SECRET": "041a5e935fd79d7941a430752208f6f39a991954e8a8f989f017b1e079e5d146fa126d8ef4f8ecad862ebcda61ad79a8eeaf3b8df671e8969f1ddc0a4a11f5e107"}, {"TimeValue": 1437055595, "SS1": "02ab58c41ba82f7de410e2111eb3ea9e8d5c58efc2fa69abb4a74e2f99966fdd02c6cf185ddea52839c94e26ed7c516a35ae7994f23376c9c4880bead9cb8f7c09f5586f7307190e586e352481bc768d58bb173607017d7ef6a7e39ebbe05134186e74132682b785ace486080d34f4054d4aba9adb64605c0e49b59d12d26d6d", "SS2": "1a7bd72c0c88f97e6764caef54b615a869b81733dfcb7b61b261adb81cd88ce70a331d31721e1fef4c4ee87e24ba80a766d2d40abcf406e6599968d6d28039e11f5191b7307b749ac798ab130ce0e43db6943f3d986fb8ed82f22e52a05d1bb6013dea562ce83ccdec2f7af94f6336dcb28168f49247ed44ba4f45459d0d3b33", "DATE": 16632, "PIN2": 9410, "PIN1": 9410, "SERVER_SECRET": "047ca35946ee57111516f82d51605a1931146b4f351dc86e48f126c90e82a536048efca74438f46efe4659b8f5499abcf9a9918be660fee5587747005327a6ed01b0574b1e4e8698e14cced4657432e05b355117ead11a10fee742312b9fddb91e0c1a64d6da74afe6e4bc12cc47c81fc1d7ef2a01e184e6a172de2da23cc0b0", "SEC": "040e83641ef69e04b1c6ebd461633f5630d5f4918b4d98c82a067d71eb13d957de11cf1a1d917635af967bf7e1aa55881d15625fee69c33328777a9b0741a8c75d", "TP2": "0419f91052f79129cbcc0d8477e06a9f9e2ebaef5338b4c8205b621ed6ca680204217a180a1d223c12260a2ae46cafa6c2873015edf3406d4b5a17a46c4b3373b3", "TP1": "041feb1fede0801e06d694fb6f3957d805c77633ed34f3acd201bddb1c1ff66e8c1ab41301b261cb21245571f9fa1bd458cb507809cf117f212727ced872a8817a", "CS1": "0419545b0377a3a2e3c7a4075bb80330a1abb7b9b27f2f42e1bdae83a46e4fab84008b1dd9832ef635bb92d14d5a779271b18b2b361242d327fc299ea9dd0147ec", "CS2": "041670aca835aa6caca1490566522db9cb088868b19258207950580a33db96010a198d431324f7a52fc21944ef07d473d8fb9a076e319f6f1dc69c04ed35338bba", "HASH_MPIN_ID_HEX": "520253ee9b443098b498723b7cdce97f59a5b4e408193141790af7ae1094a502", "TIME_PERMIT": "04104c3b58d81b87d8ce6b426652626260b3673186ee7f1095cbe68070f7a0443600c748f473e203c0ad9127eab8024d270b646c6946cd985851ca9f6de567f062", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226266343065363033316266363836643562363665383965653465366263633933406365727469766f782e636f6d222c202273616c74223a20226532633533393430303561633863393562323038333334623030663530373836227d", "TOKEN": "041df9ce7195053809b2485775a9f9974ba1366ac4279210f901fffc3515bc5c801652c09676c5037bc08287c5aa5acae3426c73ff9a0fedfffec6624d64abaa5a", "U": "041c21a2c64dc170457cc25be48de8da0dc0afecd99745ec31f237d2d054e6da141e751690638405e6417a279e5b1452cb8040ec4d23593c6e34df54fc1abf1607", "SERVER_OUTPUT": 0, "Y": "1269ee0eef8c8273bbf338dc9be3ee3ab36e8111114c3500e2c107cefb736098", "X": "0151ef94138b5b19bd059b8cf1387ddf7d39a36a74b9b5dc9197eb984876dd04", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"bf40e6031bf686d5b66e89ee4e6bcc93@certivox.com\", \"salt\": \"e2c5394005ac8c95b208334b00f50786\"}", "test_no": 13, "UT": "040042d2b3678fe8bc99e0a19595f5d8b9b4f281e1be9ebfb11969d52d6a5707e81b9038a3c7b1bcad237a984bf2ba12583b059e1aafcd9268a91e46dc3a044ec9", "MS2": "0b396333cd482362b87006aee74762c5ee19971c1f07a2b60ae82390460a68c2", "MS1": "0d076f355ba119bc1b4ec43017ffe0c74dbc56cff41f838b80133dda04070b7e", "CLIENT_SECRET": "0412f4f95ba5441fb0a1e35093b75400bf61ec79bffdb6c34859f98ff43cd6e7801ee6e150e1546b12f4d68300cc8a59b9616c9b0390a6953911a270e1e3779250"}, {"TimeValue": 1437055595, "SS1": "1121461da0b381032d470ec98dc7058e40fd79ac326b001ef311f8e21383c65b13edee07a54b9b8b08ade1522486da58472d9f7f52d3469861de13c2feac3a8604d25c34e7a55536aab04fe961380fa5adaae77288ecec868a8e5adceb075fc60a5eb54a8af7318f66f59c6d5ed88914316213c8c539d197100451a31e043b26", "SS2": "1ee0191720fe5aa927ff15ebaf7ff0af186a265e7a7c19dc545b5f07dc5c7e1117af6959d16c667eec58910e3c91728058b79199002094a56d2bf0996749c04a14426d80134ddb41a2fb9007ad71263658fe19546f84526471779db5d6673e5b0d9126fe406efa3d69921685279f5f2aa0a369cb3477baa226f89f02c48074ef", "DATE": 16632, "PIN2": 4411, "PIN1": 4411, "SERVER_SECRET": "1bd93920323951c7719eba225527dc8cdcbd1127f2ebb16dd7bc0821f37dce371fbec3e9c47a65fdfbfa2e54cf8f53477b213af8e3cb9ad1f3d9c88a614bff42049f75799d64819e686cb971b76810f2d9e8aa8fa660a469fceb6daa33362a31126098b74967f92cc3c4052874b250a15881b0201a62eb0368bd3210c3cc70d5", "SEC": "04011b191e65c4a6c88a3c3d1dda3fd6bcf66ec47d348eb62e65a15fc391e14c0a18e5ec4efa692d85651c36c706fc31d738a112af0c1ba1b6e127b2250b86bf6c", "TP2": "040b5a7d2d8c4943db9b00f83730728b59c0eb2834fe6855acc9d026123adc93441ad84ae4127de8be49b71e00a06bc9f6e864cfcbff96b753863122d83ec52fdc", "TP1": "041a7ae7b493bbc82821c7e4716c194fef2d4035948bec707a465856e0b977b84d1d56d971b6100aa89bd8d0ae1a34537c173973281dbb5929690844a69283e88a", "CS1": "041a8424ebac47a3121e0130eb4db0db13c32de89a565ed16d6719b8cbe9725fbf1c81164d474cbde1e4130553694d5201c20b2ff347d46b6897122165bf428a42", "CS2": "041b2545e8f58cf20edce4347ebf914e5a730faafd78dcf65f8372b78af2ce38920587f9f22c6312bacd61657febf445d814666637a8f2d4abe02ab275508f0da3", "HASH_MPIN_ID_HEX": "16b140879f84bd5a1b8e08a2bcb67d15bc3d4710542244216d4b4dfdbbf5641b", "TIME_PERMIT": "0419f269e2bb7308fdab5a907bc5663ea2d3a00947d57c0c427e3691d97c644fd51559410bc6db6a23ab23aefd3b798c354992e10e4a16eee6ed80313b846581e0", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226461336163663561383662343438643934396165356530373261653565663365406365727469766f782e636f6d222c202273616c74223a20223634306139643435396662383339343662613032313464653430353937336632227d", "TOKEN": "0421d94f37813be32b3995135ade93f649b848edbf68ef064983c6ae6fda44bec71a358324a42be450d154946a8611f06b1870ce4aac15dea8015f9e2f2caa33f0", "U": "0420356c11c152057a16e963d3189bdcdd5814083a5165f65cf20670e2d81207bb1780cfa420f76c06cc1df963d388378d3a9350045b6888bc63d6986d287abd7f", "SERVER_OUTPUT": 0, "Y": "0eeb54be0a5265efd58dec5732f146f92209720e550fbcac0af0fdac50cdd609", "X": "1da8fdbba6e83c6d9f1a89f1fc7c0871b62d965c549c039287f816db9c958101", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"da3acf5a86b448d949ae5e072ae5ef3e@certivox.com\", \"salt\": \"640a9d459fb83946ba0214de405973f2\"}", "test_no": 14, "UT": "040ec352a6b673469d009d015247330d1c9110709095496f971af960fda520683f0d1b4692f9cdce4388190ed5d1f73ed4961986d3a4f9420f3ec904e6fcbebb19", "MS2": "029d7b3191bb5c3501fce6f3fac6e3f9802c799af86d6361ec687cfd5e4f956c", "MS1": "1f0cb6091f001cd40a00c9cf019ea238251685a49d363895fb2223077f617408", "CLIENT_SECRET": "04176eeeae545878791848f41b8764ed54def2fabff17d23a78091100aba053ab018bc977276adb19a1aaa1ae455d42290f926ec7fdc48319bfc45091da3d5b4a9"}, {"TimeValue": 1437055595, "SS1": "005ef11ade21d61ac0eadde02972e2de6d421275a37bfa48df685a74a2fdc70516a6cfae5e86bce0cad7ae18d9239e5b0e3e422872d915f2d251a4173e503a6b0d3156a84d8ddd03f0407d6a486408a7783875fb592d27845b39468b92ef2ccb10f80ab45210d73e0d28b5a310aba2be51543455f4340e89df721b41a56257aa", "SS2": "15302e6012a81ecc8d10bfee41cfbddb5d5caab43570f841833a4df2820fc9792285ff10aac04418dad2110659e439bfb067dc938a09c7cbd6f01bdc0858f73101f0220a23e9837a56f1140cc2335ebda85f51c92434e045bb21556d28acd3f11a32257c8b38bd7b45f1e4fc5b52c48d37676153ed5acf531c28d4699ae11e7c", "DATE": 16632, "PIN2": 1194, "PIN1": 1194, "SERVER_SECRET": "0c1f0a1d84f7ef2050822d0b7267c40ef224c181a1e153323f42c283068e01f105b6b997a6297b509331e09d539be6501da16e9398613790deb4c0bc59ff874622f7e037e9ce8b3c6d1156a7ef89e277dc203a9714f7126a1da793294daffde314baf0cca6df4e69077ef7854d84ee0662dc36ee1c83aad10aba863c0eacabac", "SEC": "0414c3964f2dc9baed7a0fe822da337837fccd71f047a787b4ebf43a1d6c87f67c180a760c788651362369cc05f8ca71e917bfc3083f22670b693f8c15c92a1962", "TP2": "040d5e5a4d5769e5d43c713dd4c1d13c72dd45c841c7bee5b447bd940012f467be01e2a81e6f300d40d5b19091cdef005dc5ea1004a6e80ad366450788503a2b3d", "TP1": "040929c8a9de6b460411a9bdee1fbb1f58770b5505da8742a5e409c262dc7187511d0a85389f9fc6507e1bf128bc84e16224068b17874c890de0c68beda4f55698", "CS1": "040ad6af61f568b0adb40ae1b77de62aaf28fba96d1f99d4da6502574f1e6a589e0b59234b7b67aaff5f74b3b1fd5b4b04ea19ef6068d416abf7896facd3289d98", "CS2": "04203ecff5912724a49ead970bafa49ee5f974905b1589e56ff10c035ddcc4342f12f063cef3ba0a21caffb27ca514d5cb4e6dde44a956635cf17003736eacddea", "HASH_MPIN_ID_HEX": "a4db348d6a3e12686220b7e892dc7a8c2d03369cdafb27c78211846384d74d39", "TIME_PERMIT": "040c000dfab56e9266f8ee90716e966ff5f478bea270afe2968fa3936a0f34f1a820fac6f963b6f7c65b318db7bc1cb883123ab0846f66497a54890b0a2eaddb2f", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226337313336353930643937363864313637353364363864326333343331303634406365727469766f782e636f6d222c202273616c74223a20223335366235316130323839336462353538303430363038363964363731623966227d", "TOKEN": "040929fe71e7d7a3814d3aeba40f9a786c33fbe3b2bccf86b9e83b8638bf16a69222ddd3cf5583476e502ec761311af5acc98e6eb3b4e15fd497ed43ec0df5a5a4", "U": "041f231e85cd33ead8f6f972939966b5b3f8c8a94ff8f573b56b9cce2d53ffd84c0fe624780c96d8454031dcf34bd3d994dbfda83f5aab2f5cce208af47c0123ee", "SERVER_OUTPUT": 0, "Y": "0cd7c161c49b6a196d77a23750d04cd63bd97ffcf4023915a1ac4ce354bd82a5", "X": "00422b928dd2e96614005ba84fc78741c706b2cdf1e6867e712d73d01aa17a21", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"c7136590d9768d16753d68d2c3431064@certivox.com\", \"salt\": \"356b51a02893db55804060869d671b9f\"}", "test_no": 15, "UT": "040c0cf30dcb53d590b1e4cf3a137b8890614ac6d4a13905feeacd41f3882137d120002dd8d2f6337bd910b999e7a199fc21ee49959bf7f775b209c7fdaee1e7b7", "MS2": "021ecb6fd22558fcae0387b205f80d7a029dffc18a0611c434ee2caa0cf90c04", "MS1": "0516497d2e0d85158c64bef07aab7363e919e9e4fd653633600a3018e004a347", "CLIENT_SECRET": "040035cdc25404fed0e2b5be105bcbc7226005dd176a48674d73fde18647649d161823310c66710662de295ff851c52ba63a75020fbe9b81c0b8fb2873c3ac533c"}, {"TimeValue": 1437055595, "SS1": "23dad6d7b3ed7e4cef930e8b3d011dfc6f1dd639bc1fae7fb2cad6827ea6b673170bbf3d94545632da5cc5aad16cb90daae8b710d07cc152f90243bae0fcb17b126c0780f165329d81558c67a99ba5b3c57374959fc5d068d791137a56a61ac41e7179156e2b819b89a9fb5b19c602ef114ae70304535eb05695fbb68bbf47b3", "SS2": "2151d6676be391aad04b74ad9169b1467a5891d93355393b007f3c1b8a3470da145803c0a48cd272ccc65c94e3efbc4a1e23e2d01e868cb9cd8afd4217426de4097ba55e12e54064a971140ca658aca66a09d015600b4d8781a732898b25f582003d71fd218cb4e1f28c61302da41adab06859df6b1d687f760b59e70b9c006f", "DATE": 16632, "PIN2": 3666, "PIN1": 3666, "SERVER_SECRET": "2354cc84b0be0d086235dd5106676f8693e3caf2571b96fff02737c0d7810c7f03db95e7716ff35c4eaf7f09ec2b56b20762605e77a1a86ec7495230cd5b6127114eed4e469f14b30c8d33987700b69212752777dc6d78ef33d40d6aeb275ce51b2b23061ea3d777149b1ec98623e20fcc732b107eba9324c7e7f394d5c33167", "SEC": "04087fd4db3bee68c16fa739fc8d1a483223d8566a188a6ed4e055aff46e78c957171cf4cd69dde39d94ee5a283a5ceb3ea0ad49e90a3ac02b51d6b2c4400cb0f0", "TP2": "040826228e1929139fea73f8637de9c15c609c38c6d9d658d3b12ce06a641995ca10772604069ec77a9bf62317b290fcdfbbdc098302eb12e074f6d273df7854fc", "TP1": "041ae5cb5b45dee4b542b8087191a774a42020f77e62bb409002f2c394137757e8171089a8215c86cef9950f85162848fed0ee06d6b91d537e94bd5b496f2764a1", "CS1": "040a40647d79427687f087efabde69566fe951a867144e282683bb8d42db4652c71371fda7796029e60c69181c9ee9fa209f2fbfef3d6749dff19bce53a9757a2e", "CS2": "0413665be94ad63b94a0deec4c4e90f320eed14ca79f65b134d30279617a3e537f1381fa0905472080863b7669b23b28dcdadc68cd56a8f135331dc80588859f83", "HASH_MPIN_ID_HEX": "9fb97d070dbcf9f02f43ce6c92819472f161cda42a3e573e92ae3139e64a866c", "TIME_PERMIT": "04113d67256d744acfe5dc848a6744dbcaf37c3a3cf403dad667a7f259e4b642e216c8683a8966965ccb76c89b3132bb225afb426fcf0a328b06f244f386cf52c9", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223863643361316134373638376662306636376561396532636431626666363262406365727469766f782e636f6d222c202273616c74223a20223539663466343065376632363031386266313661653434313661326336373862227d", "TOKEN": "0414d94c5363566bb7d58b1c262aa2eebd31b4c8c6a4708423b38f706d28df9159033b999178fcf7b6d010e906c9f24d36214e4c9f9bbae206efbffe8db39356d6", "U": "040ae2c3e19032733458d87778a894fee58bd17584b6c3c3016fe16a8e8fc8075c120becf699a5c842e590c2d416f76814ff620dc76b4bac78df1ea0350ef2c75f", "SERVER_OUTPUT": 0, "Y": "0f36cbf567ea62ef0fb17428388ba8c32e4c736f1435d725a63ad0e1bbcce48f", "X": "0fed17091ee2633e8ce34f753851becb2fb567050dc87140077136ae15caa1af", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"8cd3a1a47687fb0f67ea9e2cd1bff62b@certivox.com\", \"salt\": \"59f4f40e7f26018bf16ae4416a2c678b\"}", "test_no": 16, "UT": "040431d184823b62bd1d96124a67bc6767f763b664b23f279aa2a265e550130c951e00cd459fd3ff49fc77558962439ce0e6f1ddf340a87ccd0e2db6969b2d0cb5", "MS2": "19ce6cbc23b50bc0cf5300dda69b43008224194e1c75739a48017adc4784430d", "MS1": "1851b82bc5867efd663f4cb84f4d3122ccbcc4dcba715c34e44fdf6e6feac37b", "CLIENT_SECRET": "0400490fdcf249375e425bfa5a45016d25a3990b53a4b0beaccf7fe98d5874049322072b915fcf94c7ad8580c451ee2fade519424abeec83f123ab7092ca9e3d83"}, {"TimeValue": 1437055595, "SS1": "1465c8cfdbc267dba7c633b0bfe7bdf5abcb5f1c27590aac10f65105b9eddad21cf5e9a6d02fe5f13d03f00052f4d0b69401412d5653fdbe979fad22fb7a0f14047401bfbeae0501610dbe5ff148cdfa48dfd4f4888ae716353deeb7a5c5b4210bb2b0d0180f9006b8797b352dd721501fa28d81da2b672ffb7adb6b3cdca472", "SS2": "0040dae30b7302d80a3099a898ca47185dd8e189ef2a66b981e9602ee3acd7ed23eceea8b87da9ddb371743a127b21ded6da06ba8259f8673d29e283063d4dcd154f980bd5894bdef38d126097601e19297597707a87079d2389c34b11a2564b189152c688e555fa01500cd3a54d21540409d724556ea6a392d587873bd5256a", "DATE": 16632, "PIN2": 4703, "PIN1": 4703, "SERVER_SECRET": "184e0d80931ac074dd0497385f0eda5499ec7eb4467c1a71356fb5f70d5c8d0b0d8f5a6cd5ad6a4164f26a9041287eb62814ef254a12fac0928b907d4fb4720b025cd8f9b14ea04e3fd11345cc963d6c7a3e7437703e1171f7f6f908bd1c804f1e0ec758abb14f966a58865b4dc563477323c73060487c103ed93a044b0c54a0", "SEC": "0411d04d217ec0ab6aeed1385935e71a33aeeba74817e00d5886ba1226b5e3a851218272c144a2c160b90c4a2906c96d5724aacb017dd6b2c560589c1d951d2912", "TP2": "040dd9b30beec49d625d62910e5c56bd94e848a9922e21b77666ae17ffd471193e2090e2301febda70d27f40ffbebde9fe4776172b732218a4a40688ca6b5779e3", "TP1": "04152c631db2412096d8c363435b220a3f25fe5a2d24ec6c4baecc5555166b17c721de54b4513ed3f27c8dbe25f70e3c30cefe3391212d4f823f8cd0ca3ad23a33", "CS1": "040122e925d5f065abef086c1b63d7efb0cfcf43810c1dc926889b9d9be33d1bde23be99d18dc6d15e2a68f48a485a94173c6fc098bfab74b85af1024fa2792f86", "CS2": "040f023aad490c8b55be81353c58910e8ffc2e4b7f91231ecbd385456e0904fcb80ee1a1ce9b7c8e7064b1e0fc4510853bbd051f4b3638b9d4edef03b0718cd141", "HASH_MPIN_ID_HEX": "4b428e699fc9a420725a076d5413fcb71a747a4a2fbfd1cb7ebc90c08cfb6755", "TIME_PERMIT": "040882e822769978bfe5bf18e2ffc130664a2b4bf6920a2c9f2641db53e431063f1ff5fc746b87ca432aaa855ab24da576b611e6c83dcd7538e1851be64230567f", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223237363735643564333062303335633633373537616537616266306462626433406365727469766f782e636f6d222c202273616c74223a20223836646432333935613364303164303333366530633662323235653063616637227d", "TOKEN": "0419a378f241f8c1210f3619827406bfc4fcdd16832ce90d7997c00870bca47e8018fe17f16deb3d4d18c8a1dd5af16c40c327e235a5230dd0c188d13357613f14", "U": "0408301fe2746039f6d1b933cf136b54b33941642e6ae2ff933030b6b36805557d048b14057093ec9f841ff4ab130c13722849ddc7a23b1546489f2dc69f8442ae", "SERVER_OUTPUT": 0, "Y": "1c1f2cba76c40c464c385fdbc7df270f3dcce1387296ef592d8453ff1aa1c001", "X": "01273f0dee51cf0a7ab547d53f44f85bffb7fa33583a3a9428bfdb4e2d384777", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"27675d5d30b035c63757ae7abf0dbbd3@certivox.com\", \"salt\": \"86dd2395a3d01d0336e0c6b225e0caf7\"}", "test_no": 17, "UT": "040cc1452068bb696b9999f6be7e1b5e75f9cd94c98588fe5ec55e433039bdcb430ddcce810b8ea86ccd5db61e8b643a8b563f07c3a271de038a2d468f55954303", "MS2": "07e8493d8b0d000003928116bb37650b00cdc5b194152cb4c636526b47ed06a9", "MS1": "1a0adf7baebbe316e94ac64c5c86ac431d2f0b708f4f4ea856436fc6bde88975", "CLIENT_SECRET": "041125501e61ef5498d79f475b50318d0d6ffbd76bcb895bc8317631994b272c531dfbcbab019ff73c92fdf7cbade07f8f6e725a46ca27bbf0e00673b62bbaa468"}, {"TimeValue": 1437055595, "SS1": "0818708b4057a6b7b1246bc5c1ae71a84fa402961729edb72e69f3b366ab80e71e984e78ecd3c4dca114a4208a84a1b79e16c088cdadff0c8f60f2543301f1541ce918024251242f3761a3968592c7fd8b4190b91528ca7b278b35dd50bb64da062a96f1e1771cfd8d5f71790912aa39bbac50c229fa8d3948c3313babc98952", "SS2": "1c073c3a5aca34f59f43e1ee8639f402d08d5f31035b71bbc7fad1773c7c69cd0a4c60d1defc6c198da083ad9d6fb18ba9295019bf8999ebb49f4affc378393f0d9c595156090e85fcfba773878145c6d8c6c967375e27c0debc51255a7952581389f9014044f65a22fc8aaeb63696d69e4537e6d94dccbecdf41f677bc0f13e", "DATE": 16632, "PIN2": 5558, "PIN1": 5558, "SERVER_SECRET": "1b23361dc753294af3136729a5302ad7dacad4f4129c1f041870a6f93925273813aa2857b4eda7d70e2fa1e7b1baf87062de7ab8fde1b574c17255b0620ff9d922d2f48a7d49c7673413f36807ff5a78d614e7984f64e48788b54f5f4b69ce17219919647618e4984b22df832d7b29b62885761bc124a85e84621ed87fc3c5fb", "SEC": "041e17b37d06f123edf6931647cb891bc8fff89e3eea460e93f30c58fc84c39206148fc5cd39c2c404d90587bcffcae52c20d777756f5905d734e1387f555e9b19", "TP2": "040dcc09d755461b46cb2dec388815a694d8867a81ff1cfe7d8702d992f297b6bc1ad9b7a86c9f06455a514dc935bcc2d21fb9dac96678aacdbe0533904338afb5", "TP1": "04179065480dac54e4908018f9571d4751e5a41de122780c5fa0051e835d9f05a80969cbd01b13028fa129fb03cd318eb3c9cd0915d733163979108c876dadb401", "CS1": "041d4c7ec996ae43e13d276049a83a9c6ce9405198f8ae511586959533aef478cf1dd08605eca276acf4a94ca9bd66798c659f8ec6a477fc481bc90c2c348a17db", "CS2": "040eb81dd0505b75dd41900d9136515299b416947cd764c7bfa7ac19d109e7f9f9033154e1e5fd127a90139f920d0b9dbd3bbdec675e2b9c6c4faad48eafef519e", "HASH_MPIN_ID_HEX": "92e52fd7a598d3329558b15715cccf3fda6e24ba972197d26b06a67b7ce52091", "TIME_PERMIT": "0419865184919eba5b30638e28b6aec29aa531d52f436e8d4a3bdb14f2b2f1c6b8054f3a5d6dff6ab30f98cb9b37d826d226865a42bc40b539c6c576aa8b1d6035", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223462303438653962326565373530383233653633613931356631623436393566406365727469766f782e636f6d222c202273616c74223a20226564343532363861663161623062336139366531396534333632666365356561227d", "TOKEN": "0418484d420d5cf643aad539e9f52b7378ab8f4cdf8ef7bbe9d6ac9a6e8574201a192d203c66fc76e552d578aa5e5d8da6ab6017586927e43e70ef877766cd17fd", "U": "04214201e8f8cc2604db187df04bd48a50a2cc7a5aac0d6e098e9d44efbb315dcb205a66734278e4b357610f5736b38b82ec02a9fd4f0cbd9152cc2bbc17cbaea1", "SERVER_OUTPUT": 0, "Y": "0d2cc930460731529f003ff6b99a656193ff42acd219bcd9bcd197b35402a685", "X": "1e9c5a4c9440cdc3f5576c0b3569d84badf663ab1e1b9b8ab0999d1689faac3f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"4b048e9b2ee750823e63a915f1b4695f@certivox.com\", \"salt\": \"ed45268af1ab0b3a96e19e4362fce5ea\"}", "test_no": 18, "UT": "04123fb3fddeaffe5dfb2478cc0f1a2013c97e1c41c80a5daf876db9c924ffce1f00fb996f0f656502a28ed0888c5d68dd7afdcb25e43bb2ecee079f923141e9f9", "MS2": "217c13d95a6f57116c25bdd53ce905935b3e72f9e4f87e32b83714197c5a83f3", "MS1": "0809b9fe12a5f12dd625571b799e28dedb3876365258642711fb1c4773fb8418", "CLIENT_SECRET": "041da982bf4b92c79e12320974547dca93d32c32f1f2407936b3a4304f0fe9ad1e051f463ee406d90b2177a7be888418a70e9117ec704b2a356b48c4ccd02c1f60"}, {"TimeValue": 1437055595, "SS1": "2124d878bc05ae18bfd1c1b8fdf06f77189f98e3b2658452e9e29b8e144fc23502c5abb9977897f45480f487801f9a61b0372e42a2100762033a42d132c06c3309ce8f44d18486ed0f2cf36befe624b04cacf33036b001a62409682335a22cdf01312a4ce2a99072745acf80e6f9aa7897ef9e5d41d1f865c5ed5b045877209a", "SS2": "0144c1e5e23be6996ab5291bc5f5ab178d62459ad52fafcdbfa35b38641289d207af3ce235ec7b08f0dc36ddda2edc15fae60b1b4d9d8053242e4d0b839ce43723084451d891609033f5299cfb483a04beeeece181f862e6102fe42434263c5c1fed38dd6b6970c1e4b56e00c43ceb888768fa42dd63cd025480a9f8d4cbd581", "DATE": 16632, "PIN2": 8962, "PIN1": 8962, "SERVER_SECRET": "19e19ac0e2938b6d0789ea420bc80e440ddf6fa22bd494b8ad8c7760f4bed59f05f6819435e9be192adb5c540742c759137301da7ad2177dea93812ca592ae92121551dcdbc0841c9feedc712f78a7a6c96a2becb56b1e8a57bf24d18329aaa907c15539afb7e1f2b8e55ef4fb4608abf73404b2ceb5659b7cd14c83c264aa32", "SEC": "040697a45302c86abb805705faf9109c4ddfe09b0b8dcbd436c89f4b8741a6ba5215f2b5241045eb5fa5880dd4ef3e1b362eb28151e3ee0a1487590495662c1fd5", "TP2": "04195adc282df8e526e5fbc4c4266bb5f06647a59b8ac22c73c7fcae803abb9b9a0db18aa85edea9aa2fe25a7f1017c56fc34602ad6c38bdd9bb77fbae900486e6", "TP1": "04235bf05a09110757c3fdd994278e79bd49a22eeb581cf0856791442bdbaef2831e557b922c7f9a523c7305c797462864579f9a58b9c53fec4bd7cecc3cbfe0fc", "CS1": "041f743ccf91d3f774ecd3ba6014c4d686b860527e1ef0b415f4c69b9bf6031c1e0d9c797c091d3a950c64de89360556126b566466db4ac4a0cb87f2215b9eb465", "CS2": "04092d710891fae6905433a27d29f02c0d1512c34de55f67e2ba02cfc4c8cf71510a9070e17cfce6072a5455fea5b28b606a6f2b0517c3e41dcfa048994eef2d0a", "HASH_MPIN_ID_HEX": "2394aa62d7640ad3c8939742810e9edaa3d21be2262f41fc7eb92685a5a61c10", "TIME_PERMIT": "041db9b7dbca2b8dbb93b077b3f89799b82a07f4f4c090036f56f8fe2cea8d794e1369e5cae38ba6e122b478481037c6c576297e35f774ebbfa93da93f334ea568", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226633646432323764623830383462313965343563393539376538336366613161406365727469766f782e636f6d222c202273616c74223a20226664396633653435663064313638303934343063336661623232633532303166227d", "TOKEN": "0402eac396bdec8929485fd8b3982918e570e9dc99c21c195a105d8a77108497402098ec4824072f1c1b76e145bad6526b5d3099d9b85014193fbff9d9eafe3bc7", "U": "041d68b082675971f81a7b9e07a3e655d9468f68c9c81510072d5bce6d554bc11a1a52cfea598602ef1636e21bf4ec3dd706963fcffc067c1e1efffbe131439dac", "SERVER_OUTPUT": 0, "Y": "1d77eef22ca0c10bcf2c494263578727f331e761cf22022327b853c03ef0ae0b", "X": "069aea8e8552b85654fa45c5d861fad0d4ccfeca5fe882225c195f8ad95f6e21", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"f3dd227db8084b19e45c9597e83cfa1a@certivox.com\", \"salt\": \"fd9f3e45f0d16809440c3fab22c5201f\"}", "test_no": 19, "UT": "04166953130501ee5dfa056241ead9e5604bf8c21a3b6cf2be6120107cda23d1191d3acd2092e601fac897faaae777119fc7b6a04710410102d17bdeeba54eece6", "MS2": "1a96dcff0e5b2aed8a034cd367e1e62cb3f86072daa1eb114c027419ea2aa9f1", "MS1": "119fbde8dd4f5125ffae67b4e3fa8c7925d38522a53e74583ddddf1475cf11c9", "CLIENT_SECRET": "0410b3cc689ba1310aa8fbcdc5535d5c9b24407f9c88ef4a86c157350a21fd80d0018191b9d651fa1c16d423daf96a673db93dbae11c8c6dabdd767ad3324a9822"}, {"TimeValue": 1437055595, "SS1": "167e7c65c25f80a1dbb94dea64e396b34cfa47edeb3476d1f95eef3d050552bc087ce425beee13cd4d388252f3c6c93d4d193c8be52010f6c7c4246682f3e0221cf00340798caa4b01ed402cab0073efd315245c10eca7ef30e833918dcb129707b402ebd0505ee754413f68ea4678475c3705ec3741077216f92f2d4003b5ea", "SS2": "196cc5d90cfee46d847d857ce81d46eacf09cf2d3cab6e39ff94f53be5a1853b198895bc2ee6e0c9f36b21491b64c55e469ea9501f72ffa5fb005d17807230bc0eecf00cc46aee4f0f58edd135c0754da36b8f8a13d6bd64393b2284f73f1c5e018b3be32d1f42d609767c456085be0f9bbd76072b4642f85529e7eac7069d93", "DATE": 16632, "PIN2": 8915, "PIN1": 8915, "SERVER_SECRET": "179c28b95ab04a03311a4fc8e2e6a9a6235a7faa093de973eeecb5fbded1c5881ef8cb0b9dc0fab3ad8e64b668fe9b12dbbcf0761cf076531ebb501254559f750111b0bc82312eaf6ca06c425691bb6cee4908c990061779805c50a238ca1baa0c3f25ac169b043e13af12816512e03b1a16ae44585bb46228c7ff27131311d8", "SEC": "041ef43672c0e6a1212ec033b0bb71f24130b4aa6aad40bff7c50ebefe939fca64109ac419048d814442a1bfb0bf87fd1c3ea07b410fd9e33b7822bdf21c032253", "TP2": "041752454b4e15800bcda5581ae89584144257f03b615a93a04a5406dbb38f7ba112ad21f2e44a96fd4cc32e0688da46b5a34e2ee1a1045586c6d3016afb84a917", "TP1": "0404726736a3d64c7c8b2410b2b1932d2074067b329ee33421cd640abe16380bec1e8709f278eb05b6bf4a4597749c32c0850108697e89669644b8a8b1442e7026", "CS1": "041c2fb362a9d4ffb0afe4cc8cdcafd54304efd682449ebcdd05d4c5bc6f7bc6a1035d60a5351459dd682c86f77aefd37d65719fb54e0cd72c3c33621b0df6fcc9", "CS2": "0415129eff675097c289a3f83f16ad4af59337c927a5b3002aa170c251f1b3ceb007c8fa08b78badfda34f3301c9c937c7f339048939911803d761361aef202c72", "HASH_MPIN_ID_HEX": "4d1c63aef49f8b93d3255efbbab2436ead9177cbbdf72ab816bf2177c464c24c", "TIME_PERMIT": "04190542e10eb28527d27e15e7e7f99118cb73faec830f98d939db0cff66e9f3c61980a64c13e7981b249786178fc47d676c9e832aa4765aeb2065f8c923d866b5", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223763653435633934306636393433646236653731366432386235386538643538406365727469766f782e636f6d222c202273616c74223a20226565663866373434316633633637363766343037623739376262316636373533227d", "TOKEN": "040a94bdf3fd2e2fdccedf0a821a0a857919d3cffabe7e960223dd5ea2ebd9a27e02e6f1875e19cf327053ff39892339ef01024dd6d81e41086a19348ef3205f18", "U": "0406dd2bef46982c600cdf971027c39477efee27e047bbe2ae34d2185b521c66821c0ac4ba00feb7e10e654159e88156f36c584795f1703157a72855d5a64229d9", "SERVER_OUTPUT": 0, "Y": "12bb1d67e34d8cd81c9173240432103d875c19e2310f27009c8f6b868cf5729f", "X": "07d02706a63911757c5b00ae15398bdf24f8ccf487f4041e0ea6bb559e60f4bd", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"7ce45c940f6943db6e716d28b58e8d58@certivox.com\", \"salt\": \"eef8f7441f3c6767f407b797bb1f6753\"}", "test_no": 20, "UT": "040c85281fbb9708ac7fb2c5190274bf7087cf1332c38c2d5fe384f48de8e31b9a10fbb585027474a148a7166fdb5800f1cd07b4324ac6e1e7d75dcfd5f1257e37", "MS2": "174ed4eccf9407b2b36c29cc2b2b64424edb8a5073e7b3fceeb6cdcf666bf166", "MS1": "03112b5d22d677fa7ed698d875132cff1e3615f37664069b49bba3405ef8293f", "CLIENT_SECRET": "0420bedfd98e6e1b3afbba847190577886a84869491936c5eb6455cb60fa367a0d15b7d7b4672b1966b3ba3ab9772ae16ba4f120a723c379c969997dd47bb1bb99"}, {"TimeValue": 1437055595, "SS1": "1c2f71028200c7743973eb5b4cf992278523fddbd85795df04529adcb7dc721c1de51fb07e528562ad9a85afc5607eaf9222f17bd6d4b757a23c184ece0ae56e239cf45452afdd38b0944517e649d2e83ee0929e9c80b825c717e4ffb13904c71343c7afc2a1b67340adbde47c569b339daff386613a363a3d72783ee573d70c", "SS2": "18d90b9554809ddd6e5a848976ac047d3e4e8bfdb00fa303c316a6105d646cef181f8df4662c6cc65bfb2166b76f45188646428d8dbe238a999a75f149d6a2dd1fe1c057e7b14e5c4f0a89a04cccf7d6d6959a286cb517f0fd8a4638b7f1341d19459cd1393f70cc4546ea19dfb3b8063c5717a72bd4f607994d44e5338a1489", "DATE": 16632, "PIN2": 5133, "PIN1": 5133, "SERVER_SECRET": "11a02cf1ab17532996726afddaec1ba9583e17eb7e341504addaa59d3a8a1f4e0866d1847893cc0e492b2c63e88a9f0712dee8ad2fdcf413c5d381aff4aeacbc206d7a1ba8a3633b27f1a7e6f893f09471349b8f8886ce86e2e6df56c0fc147521891be43c631b0611a6d149b5aebee9f4165df4cd6adf27d4b4b3e73a6fa895", "SEC": "0423d9e7d837fdfb13508f39ea03e6931a287a2db022509b407f1209ac6c1bb33014da097913707d83f98686e16a47a8843be104d435f63a4e5b7a0511ee60d807", "TP2": "040105bc5aa447338e0ebea6e8ee1a211d5976aed2cebe1846c545aab2b7c2c4cd1fd9c5f031efdec25687a5ddeaba63229915fc3ae66e00f6cf453b8af89b660e", "TP1": "041379beffe90bf6abd693f8af3c70aae777a121d9fbb837c7da1bc9c1e46f8d20046f03d84c17aed6b6012c94d750af27431a0b6d7a649ad600625fda0fcc13dd", "CS1": "041d35e0e53a90a5ff9307b5b97eac04f4cc6598c280acfb5e19087578bb19d5690cae97ff08e2ddfb3a6e19e13dea1c4a2561bc5067c551250e75c3af85a94162", "CS2": "0414a98b6414877ccefb2ca01b672793db9bc915f4794c8d8a73997e829a380afa1887af1f82e2a1714f0a429d799c129713b89bd7b248bc596ffa5880e7a81243", "HASH_MPIN_ID_HEX": "b003096956cd013eac152ae591bca7c054de788b12c43844c79bef9c76113feb", "TIME_PERMIT": "04167a375c83ab8313938384fefe040b3e2f0aa84cbfba0de7648c22197909fc4a0002114b8209a202925507f5ce1c29157418fef7bd87a33b12166044b1be068b", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223561636463376364313764333537376539326461313332616663346534643638406365727469766f782e636f6d222c202273616c74223a20226564623066363336373461313138313963613134653863376230323939626536227d", "TOKEN": "040aa221e9ee39482dd4b41829a31ec43d884da68199a47f47e59c7f8f4f0e9de61c0a5ff802a752eff1d20446b3c31c8994a2274124d94991033814ab7c380cbd", "U": "041d0793cfa683f2b0a2c68622a3f640cf03760b64d0000f84cb7168641393369309e4ba2fa79fbede4255ecf98aa230d6af79ecba6feeda92284133f63effa1cb", "SERVER_OUTPUT": 0, "Y": "07eff2cb21516f8dab028f07c58c4ba2bb1b477635e6bf9df092178855376d8e", "X": "1ce985372265305a72bce0de62e8d89a6528abe875831f553122d4ba80f6838f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"5acdc7cd17d3577e92da132afc4e4d68@certivox.com\", \"salt\": \"edb0f63674a11819ca14e8c7b0299be6\"}", "test_no": 21, "UT": "0416a5f626609a868610e80fd604195b5161a0901929e8f020b0f952fbee287e020ee611ed055a8f7a4040ad4cf6f8984143abffdff6ac73f9fc3c069bd28a79c5", "MS2": "1d2861a78f1aaeff63d6ea6d8ab029dfba3b5c8fde372a35119a2de53bedd114", "MS1": "11ebf8baa2668df5b16e84095bcbec5f37361887f49434a9ac4bcea2e698e927", "CLIENT_SECRET": "040ce22cca8d2b5cc695e5bf8257faf56ac4b0185326fb2ce03917abf94e7e498d0483e5b336a2d4642e738f95fc0f99e582f77e1de2856ee25fede0224b49874c"}, {"TimeValue": 1437055595, "SS1": "0de2e6df1abd97a21d971e8c23c136f4696f5d76f874988d9d9333890f1b882a12e1475fbec6f7937c216a6e9e2d17ac0cdccb5b781176651600098f2860ffab16cc48d6f5ee290628e75b325ee4b9a8b2daa85ddb29cf9c7a20de9e919f510d23dfef10e5d8ee8cd7c3df1bb7e300f2c4e03aff86f4d2072c66110d139c9c7c", "SS2": "0537ed4c3553b874dbcbd3cf7dada742f32beb9a1f16456d9f875b5e192dc66420fc831947aef46207325d040bbbc1ad60eb12a8c622f3458ee502f0a6538e0922d7aa479e1d28fe5976bd70cc7043763db42bb49c2889869267c85eb8217b56202c0e756ade871a1715632045c3af1057403ce8d98b7812b3748150c64f94c3", "DATE": 16632, "PIN2": 5337, "PIN1": 5337, "SERVER_SECRET": "1e167c030bed8123f52715dc647979c777d5d1399e59dface8de353eb64061d02216ddbb6a926a4db272f2dc08304d32e4dbaa188694875d31531c90f1a13eb617fa2a5bf45430215f329527bc812da1ac46802be880f14c6d48410c860423c821fa166e6d1049259a5f4613c214a231f8a99753c09615a8474b7920a9f2c84e", "SEC": "04061e2d17b4c0e38713618bfb164e312525d4854efa314a22e328e27d559b6f291c1551a4469ba33b990e9303f212da7ccc21dc0bf53830a09c51c3d0daa3e8ab", "TP2": "040d1383c528d29ce6ab256696cc1c32485e96498d4b4c2740693cb20ca033e5fd1727d9b82df82aac69bae640d1660e196ed838f623f12ebb21cd9c7ca9ea0b5c", "TP1": "041874088d4210e3d4af1df0ecef90bdf7b78c37cb6ed682834b3654a0ba7bcad204f335edeefefe1cbc1fd5a6c119f333a0e4ef06febaf07645dff425a31e8f2c", "CS1": "040964897b71b4ee4b8115b839ffaab80c803d767e74c25c1fb76e7183b8219802043618edd91839ef1577b02916cb46c3484204ff012b58527c4d0543ec9294cf", "CS2": "0401a402a9b99429e9b988c14d1e700143c5ca9f253c6c3ae7fdd23f2af1c9886023b23159ed6c657b90885a87647a9ea7c436190a899c9cac70ae16d40adcdb25", "HASH_MPIN_ID_HEX": "810ddaea04c5c1d33f99cd2ca20738147f2618688908c6add5e8377b8354960b", "TIME_PERMIT": "04165d8518383c59296b87c59162fcd8d8018dc770f9ca59ba7a29ef86ef3b1497098c7533296fe76d06944a0146927bd2541bef8b4e5124e623530de32c0af4d7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226166636535343831313065323563303762343262313464313033623736303464406365727469766f782e636f6d222c202273616c74223a20223432663433663332643763653166633935616537303830366237396663623733227d", "TOKEN": "041b08b4d707a900b0ab9212218e8ff782232bcb67d0ad7af0b60d4c639e5d6cf81b97bd65d88f275271f9f0d6828224f7a9a4684247675c88918d74690a3ca51c", "U": "0421e95b832350e86b14a172fb8a692b8bef7a7720e0b28750dec10bfc7db6d968055e183b3e59234c2ecb39833ca58bc2ed9c38343aaeb7735d4f581edbe4aff0", "SERVER_OUTPUT": 0, "Y": "132a35942ae1f78f44b94f3b1679c0be95a885f1230b1189a395bb10e9b48cfd", "X": "16a9570fa23c138241b87c46f694b2b55d7db4330fc276cb30d44ed6828ab801", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"afce548110e25c07b42b14d103b7604d@certivox.com\", \"salt\": \"42f43f32d7ce1fc95ae70806b79fcb73\"}", "test_no": 22, "UT": "0400c108ec2ed1de79cc0cfcddef3e4382626877e1937ccf58798076dc5c6d43b902b67f5941711b5918a6176cab2709b7242bffa9a7bec56293f23130704e1130", "MS2": "059f060052ae587ed62932069bbf449d7aaafab1375353285ce084e6517fb02a", "MS1": "0ffa1676bee9ff7663186aa1ef66cb1fe09ca840bd2ddeb2fc9d06d7c3099f1b", "CLIENT_SECRET": "042093e8117bee91529caed016f9b7d4050ac26ce99a53b17ebda521ae230209b921f193b1352c023ceae47ed49b44a6632778b76e62aedcc68f245906bd2af90f"}, {"TimeValue": 1437055595, "SS1": "074e620a47c53adf4859d4df96bd5ba278f399f2c4434b73d2e5a711cda653e31c5e77295b91bbe8dc942ebf36f04e3c7c853c467cbbb9736061875867d84ffd06169ded374489a178adfbed46345efc5c3f1f2554799487aee929b526c1d5c81d6e76739578069c988516e27ebc2961bef6d24ead425fd720891e1b2f393f6a", "SS2": "0b412345b0ab86801c256a273cb8674d8340dd8c45fb920e09ae90676674d2d40684f28225cc206bb1883b89b378052be06097e2a1519f0f70c63b7f79fd0fa40fa865f48ce4b44e290e7a2a6ff2c3f29b6f81bafc8d23b5e3a61bbea63c15ee1aed6f9e2e3b34130388a869c2d624f683c2f671b34c403e8cd5be025ec8daf1", "DATE": 16632, "PIN2": 4924, "PIN1": 4924, "SERVER_SECRET": "10e6a2722cb79bb2a5542efa260d6a6078f605f58af34f6ae3e468e4c13d779501fd4dd0a767a12e82d2332fa99fca6884182b961b9c0015bb9c2de56aabd4db0710deb201c7af12a0cba3f1d85f544a8d6107f2bb71c16953868f9256cf27c000327d421f01cd561605435a59d06ef6fb2687df759200d1d56aaa68fbc570ad", "SEC": "04066cfb2a767984ce8de6169fe82f1778419015265d3ad7cc7db3058f9358884c1f5bbee103c9d7c0020a6dd484c231d83c3f1dae47807fdf45ea5fbe2ac07f17", "TP2": "040aa39e00812efab4d3754ad6e803166050fb849aae49f62c782449dfd0d1db5a1f7f61a513f5405c4083a1e5b4cabb0923042316754f94e95c05b7a2cb594bee", "TP1": "0407ddc4f87fac6689e93aef04b0a8262f088c28b264e4530172522db87efc1234216abe06d1cc8bdf91824a65167becd839f479d411966de354e290f07f49ac0f", "CS1": "041f6b62915debf363ddb2d61c54f1516f0a88fa01d2af46c81d3488c479eb82d719bf549cee6c84363d038a7242d68310bdb9bd184787fb45cb90609a169e9225", "CS2": "040fde7a3b1a8b7aae6d5a8ae72582363f606957707886a524a0976737b1e03b0810d2ab22e0b9b783c9357b0fe3abb26b3556ef0fb7eb3739cd92a0675fbd6fbb", "HASH_MPIN_ID_HEX": "7ac79a48b5f116cf3eae5cd1e9df9219ba17c32a0ce94913a7d0c7c1d0dc6eb9", "TIME_PERMIT": "040a28f1bfe51615f2a5cea19acf50771868d5bf8fcf90681c515ad75b169ff41617786c0185fdb4b3c00201d47e596c7244df4f2ec559f571d4bdc4734297ebb2", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226464353533306436363965633034386364306664626532373264633266666165406365727469766f782e636f6d222c202273616c74223a20223562623762616434376132636236363233333764333261613538643235393136227d", "TOKEN": "0414493ec8b984218d949ecccb715116a381cc04a6c8cfc6b41000f778130b49f4099d6cf0f1463297c68eeed7d56fe114ae937d6bc78d80111956528ccce18b3f", "U": "0420396f639a5c7d58fecbb68c13c2396c54aaf8c08e00e48b49c137477f4f1cda230ac40cfbf7fcba53f5f9e5548c453444acd3833b1e57240740cf5f7a0c8c7e", "SERVER_OUTPUT": 0, "Y": "225cf1573bd4eee607670d6b79090e174f6ed0939c3733964602db7090a32e71", "X": "1cdc04dfb5d0d9b320de97876c0c75a573b23e4ad3b3178b9ef2148360505a79", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"dd5530d669ec048cd0fdbe272dc2ffae@certivox.com\", \"salt\": \"5bb7bad47a2cb662337d32aa58d25916\"}", "test_no": 23, "UT": "0406261cf77da914a8812d2e75225df0e22fe4b378be2fea32ed9403b7d4dee2fa131363d78d5950d98445c7bed5d6724a88974361fe8b5e0ab60c819ee108f1d6", "MS2": "19737df08839b2c6bda04053818779c8f104363e0a49767896c7ea96bbf5986e", "MS1": "160b764cb78405619e1c0f6f12e1228e21483fb683b130db6210027900e6023b", "CLIENT_SECRET": "04015ac9e6ec0988d052342e425f6c3ebbcd284d7c72c7de38ad3e318282b5cc201738e53120b6b164334c18ec806af4e6060461af6682d2007bd1c74851026cf8"}, {"TimeValue": 1437055595, "SS1": "1dfff407a998e1ae42ba63e9d7468dbd0f3affd46eeb06e71b849e9b7da69f8a0ce1edad5779719277d96676c7d865b669f094f3bebb6426545ff27a02890fe10635dfad2f0c8438ba6743c21e62c87d7827dc00f81ae8feba72d57d85ece5c003a1b4f9d1401a292fe7ca46a9bab5a6709b6b4261ef5e318f1093efdbe3d92e", "SS2": "06a99f6fb31611e48df8511b84191a88dda865608d555a21c2b33542309253180f88dd3f84d1650835bac39a472453cf7595662c780f755892422c959d6b2d9301f0204978248a893f2bcebdaf96923da5494f804694885c3873f228322b58291b48da61c416db1f2681982dcb864a655f1fcf5a32e8a725386d306564e5fac8", "DATE": 16632, "PIN2": 9815, "PIN1": 9815, "SERVER_SECRET": "160d008919bf09dd8b8c5bec1e59cc93af87ca012f94229a77feb6c0dfb4a185233a2fadb561f9fde70ab47e11131c7f54286dedfeb117df6866cf08eab8d1d91ba45c7bc3374caa693c30c5faa32240b36b03f0bf4b865cd5d99d69d0b0d72206a0db6d9fe55e29b8a5c1d8e5e6b31683edd94b3139979c59d74ba368a400f2", "SEC": "04040c58835d1674a02d57438bc34c75904d9c9106f197e10e05687cda0e9c7c9f151933eda2de623126f461a7ba4931afd0f6d7935b591ab15205986fa46e255d", "TP2": "0408853cc6a9fcdc7932eb3ae647e6868adc10dd2e9601e63425d469e4e45daf9c11745425807b8b782158d3730cd8f03777be0f751148f9498d2d9449c3e9c87e", "TP1": "041c9b3a7c918a93893807ed6f82a12e5e586fd709350cee72a4d770c50cc777970d9f5527511bc366ad15493673042cdc0c3515396bd45282eabde97b5828a5d1", "CS1": "0417b32b90fb099fece26252d8ff88256a6bdc27300cc3761f828081730d09860d21b119e5dd11bf4435e6e706b830b68d8b4c60d2a57784a4896f46e5cc22d226", "CS2": "04108fe3a901d83e5b25e9f6350f096ba7b48de4279cb9d37e79d3cdca69e81f9a04dcaa9e0f00f9023fad0d8b1d8aa43474d10435c508f4dd90f01127846be5f2", "HASH_MPIN_ID_HEX": "048f0125345fd1da3cc4d35fd809ea9fdbbbd9d06dcfe4ccfa868d6dcf4cdbf0", "TIME_PERMIT": "04130c52a3796f04670b4b05cc94b0ee1de128fe709eb45210c86ddda7cd13c49a20efc52884cfcb2ab6590fb4f3e733f82cab78109da9374677ae6aadfd2eb84c", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223534363038396336353030336237626438383835353866663232626462656265406365727469766f782e636f6d222c202273616c74223a20223061363066363733616263646539303664666165366466393331633966623339227d", "TOKEN": "041ddf4e0f7be612572c79ab5818d0bd9e0d3538e39b0e566bc0f38f84d101f8ae02c53dec288ccdb536af7dcca995cea60bb88ac319dadc18ecd2246eccaf13f6", "U": "041839b3d5dd0528fe6ebb4b8fe0ca2d82de0d77acee6e2653e22a98937c39d23c0824f604c1a90eaa7a7e5b48ef97495b1d6f17ab99f6081c5851de0d4e022939", "SERVER_OUTPUT": 0, "Y": "0125859bb5998d5d21053a0a32f4149e0ecf0ec2b996997d6506cf09d6acfb4c", "X": "049503ba3a07b667a049ffb092393cb3da468502ef4681fd9dc6bc82b09fcfea", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"546089c65003b7bd888558ff22bdbebe@certivox.com\", \"salt\": \"0a60f673abcde906dfae6df931c9fb39\"}", "test_no": 24, "UT": "0406240ec243897b2817de929e5c29bee7b83f8032b6963086045955aa1f9035a10cb5e09a277daccf493a3b41104e3168bc2b5059259142ae308e05e05fc92a04", "MS2": "18ae401f3f87f35f32a83607ad3d67ba237e62d3f0d6ac5ced86f68bfc2cec9e", "MS1": "12af4d3cbae01080f71957366897cf2ca849604b50dba156e8955a2eef1bf512", "CLIENT_SECRET": "0405510122ce97d8591538ca33435d94aa0a264df45c2cd1b982ff8b43282bd85219e1266c15049d1ff0e2cbb7d0ce94e3b691eb5ff5687b53be531dba9a94b97a"}, {"TimeValue": 1437055595, "SS1": "151ebaa9f4d3850f67200fba397a0e66c6cfbb36b02a11b4a369853ad88ffb800aa782447cb2761c9e2f2045c38a70bbade12aac474cf2b918959e9dd68c22f709d56fcd55a557e83e669e77e2805ff218c7aed19de0038dd14c768d2251fb831dfaf4e9723199e35d4589d80e8502004b1a34da4dead7464c2efcf361ecb5fd", "SS2": "213f546044d639dfa60a24fe91c407d81ced9224ad542283ab2c1740beb5ab7214100dde7ab37e41be05f8d74d0b5ef6a42992b947173ec4fd285f4d38a047700908afac6dbe55512f5aa6417c7648aff1e56b9eba3ea61d3c1500c6a84c0800228824b381be3290cccede00f9c1ba6a4386a0b1cd9ae6454006841345c601c6", "DATE": 16632, "PIN2": 1580, "PIN1": 1580, "SERVER_SECRET": "1809f67bb6b94e6d382adfe85875475d34029a3096e604eac302754ae3af565e0256df4eb52058c5d25daa53a0c021b582065b6ab11ca2124f2895c03ac4130d03db5a46b26f3ff3922275ec33f99e737f3a65ae0b8561d359a7f2ffe8a0cf520af528509690ef2241175e2168c1be52944ff487b708297448d0d79f19549d54", "SEC": "04077364091300f87cda1d16a1ed8d35512639a87fb0e20942c43b71b3e3d90fb2118e893219720f55bd5a906d0122c2e25937e7045370a29c30393133b45b0a41", "TP2": "040b0253a183d292d9bde76392a0bbbcc9cacb978d7c64b5f0a8d55a452fa926c80e50679e27dcb38a87bfe730bfc7c6f94f2676a526c7778bf0c16ad084822cea", "TP1": "0406563cd9d62aa692495965ef7e6a15de10d0882d594d0dbef04b4563914753311814a84493ff21cdd211722b958673f1119bfcbfe30f31cb522a359e08877fcd", "CS1": "040be1c34540b42ce63ce86c8f9bd4d541c5e5b699efb2286685a8ec88169e10c1203d97ff1e4ee1c5b3dabdf48cd6875a2e3f5aac2adc0a73715c83afb3a254de", "CS2": "04133ba77bda07477831747d1986414e9ea4b84ee97fb58c56d0f0d82d34ad84ff0c1d93fc2ea816a69e3c3468bde3fd71bd12a0a8c106b2d388b7f3f06871f25c", "HASH_MPIN_ID_HEX": "18c824e55cd98a799340f188ac38b3364174a1dcf015a5884b3f10a97384d7bd", "TIME_PERMIT": "0400652e779915e7000ce7e584926f4df9af98d93f2c68878f3738d1d13eaf87b01ec26720a9855bdeb48236dc67d1763523f9f17206c045d5524afa9c42725f35", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223037623833363365613330333738383464366539303134373465373435643661406365727469766f782e636f6d222c202273616c74223a20223466326234333631623961626364653564653161643561613633346664646666227d", "TOKEN": "041e5d268cd58583567f3b2f244c30b01f2f646c6d8aafad79330f10a333e2e4af17ef2b1fe4a2f27576ad4ca2092d1d7520d6c3bf70b3c64f179125944d82eff9", "U": "0417d114eb7d1f511ee663cde5c399504b1fa61c410c3b23bf8ceb9af8ac93178004414438a05a6992aa21ed0cb6acbaecddf5185ef02f383192aeb8a707f49f77", "SERVER_OUTPUT": 0, "Y": "0617e2f50a7b1cb0626ecfa797b24900f8d35f3bd97ac978a67bcd59f3ab7536", "X": "2291fa3d3dca7fa8364953daa645072837e5bf239f02323a76a6e4396e2730c4", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"07b8363ea3037884d6e901474e745d6a@certivox.com\", \"salt\": \"4f2b4361b9abcde5de1ad5aa634fddff\"}", "test_no": 25, "UT": "0421729c46379b414cffd7260b9a260dc6d7f796594b411be45db8787ee72ec18608e720ead5711be6e4d8398ccfd5889c840adbcf412cbdca437224d88bf9b1ad", "MS2": "1619d904f1fd6b791a0e81d8a53d35230938605dc79df72c1e064b425fa22882", "MS1": "04a8aaf65175a71ab4bfb39f53d30d29107a3e3bb16319ad4fb5741f31cf5c67", "CLIENT_SECRET": "041d423eedb4e2e0269817014f3a12ff25d28fcb23c54eeb4c86ea77a7dfd3f53a0748f9847d077b45815aa98cf146abb94d6b44eccef833244cc0fc388e8aaeda"}, {"TimeValue": 1437055595, "SS1": "12a09577eb6f6f30595486fad7ebc3a1341162302ef9e433e1d001a9fea78d2b1e594e3678a081e7a07bc38b4fda4951b49756a0357a03e4f7abfa0bf6123b550039c1a85f511491e0f95086dcfbc796378760072bd2a8dd8d7ad8d5ee99b2fd07c9e5a511dee03edca572f6c55924e43965dda4a8fe086c84687796dbb44684", "SS2": "0aadd27990079cda4ae471ff46eea6892fd50a0a8887d5ea3f10921fdedb720419ab7e99af9079b144f4fb09b3f3fb63f0c76c677d1b56705c86df22a6fe760c006c35406106f3fffd0bd663ba1b0d23b89c1355e37f04db4df3e2fb87567fbb11abb1b261f976e2a5bbc00b861c90a9c4005dbd6f4c7c16ba63c077e747386c", "DATE": 16632, "PIN2": 5314, "PIN1": 5314, "SERVER_SECRET": "1104be4d66e7b41da565d7a950a86706f26f67bd7d387776f0bdce4d8207c8c420f1f771998f7fc73d2285401e37c083b1e1e2288e9b3922a8a4982056fee894149e0ec0f477a19c7900bc4626c61825be0c8e0bae19b6bf48a48ddb6d6e095a19612622d9dcfc627697e70d1ed56a2f5a2ba3fa541b00f2c640103c6358b8c9", "SEC": "04074f9aabca040e4c071321575583b917f498b40ad678bedd647e022573a12348003d0bb414033f3ce449f94904af23fdfde2a7d0d338bb79326d5ecb25334048", "TP2": "04076926a1869d6b8cffaf314b5f33acaad4ebdc0d032512ea53224d83606befbe1eecbc6299fd57a7a69ff36e6ccf38d361c3ad2c42466442612e6d6c60d1551d", "TP1": "04208fcc0ac70af091fcc1f11db34cc63d89440f193d652010b1c6a616d0098f341710f5ae655bc9411aec445348207796a029b757df761989eb3f535952c688fd", "CS1": "0406fe805766ea5b737fe5a2d53b6538733636843dbef935e27ea08f0942d10569146777aae7b40997e78e7dff12a2f5dcf64fb941b485e00301012355a9f844ef", "CS2": "040f8cbf8cebbf209ebdca9622819fb3b897cd2bc6474a3badec15cba6bbb2e240218c09039b8f119932320fcf783095c792915d9ee8349dad598587596a35ecb3", "HASH_MPIN_ID_HEX": "5d3cc05c6c82ecdbc5f32478fc0bbd3d29712af25ca03de3ccbf482507826f83", "TIME_PERMIT": "04219c5d61386561f326e77f2e74960bd28e5c399b209eb196ae561a15f2291dbb1f9fb9b4d0669980307ce16871bbebfc03fe2337464651728ce7bf83bfce5f26", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223137383930393265313161616237323635313034386230653661333330323237406365727469766f782e636f6d222c202273616c74223a20226164306261666337343835353363356363306534393530353866376331333162227d", "TOKEN": "041ad8094f5dc854325eb5fb4bdce9a7a700d540d85155a7ab8571615390d62b730dbf614820a78ab36b959e24995fca0882c2fe3aacf1b9527da85fbd1f2d8c52", "U": "042227a1192f9e8880a3b8f207771bf8d6b906e2be97a137dd8b1686d72f5a9f93040e35c101958b467485f57a2253a2857dc18597eba8f66a78b3f21efe9711ec", "SERVER_OUTPUT": 0, "Y": "21fd7d4c993d61a9692b89cf37111744f5fd0c8db752cc7cf487a2a5f83dfdd0", "X": "09e317ac3f6c8bd859d237da5375f29df5a5fc7d2bba61b14c61f79ac409af13", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"1789092e11aab72651048b0e6a330227@certivox.com\", \"salt\": \"ad0bafc748553c5cc0e495058f7c131b\"}", "test_no": 26, "UT": "0407efee2974f26fc61d22d22921f8fde39d38ed3d22fef2c719d56e7d9b19bfc61d6ba818f5118cce77ae4134d408511f9ab26abcd1f3472df8ab0ef54df1610c", "MS2": "149838282463244a61c727b463efccd995c134a0eb7027b41ec0c2fdfdd92981", "MS1": "18058af144c7ca55128252e66a7d6240b08049141b7da23318e3766dc8382b10", "CLIENT_SECRET": "04007862f4ae6ad3b1e2e6d9c8f95e79e30b5cea864e41940e34c4fb08a902a7680c5de89410f45ba2238debb0902c101607ff5dc81104fc4e1aea65b45f573e27"}, {"TimeValue": 1437055595, "SS1": "08b32d422e2e40bbdfd19f615ff8baee2e699bdea2b58dc13e46c6c888f9d3a80e1eae357df01fcb97db7768852a8b423e0fe790378c9f68a1915cfced5bc8ea1b8de66e5eb4a04e3791079a535e10796c9e79cb37743ecf0d26efc6585a418600e79e43953866bf7bbf20648213793ae3ab8d6d1d8a2c08b0d2c4f0bcf0027a", "SS2": "225553cc1c05a2486965787b11c4d0e78995aceb71041eb7008d4c0c8c5eac7c100d30f460de9e518c8bf7c1eb9ce571ef338b16c8e7f3e056856fbaa522dfef07fced161834cea6efdfc7937071196733e2f2f72b0473468e7236f720b1ce381b53bc9b959a697ef92b430fdcba8cd4f4e0abe63901ab022c333ba5400e405f", "DATE": 16632, "PIN2": 8419, "PIN1": 8419, "SERVER_SECRET": "20324c15c492ee1ce313d8f42b17e0cda1b9d3b189932ad02d8183d33ca492e30ad43be29b00bb788b210d12baadce9f56b83a5bc582abf4cd8fcf6767aea78505eac294374643f64cec0dd993be144c7c6d68665f0e9f3d5b21bc73454aa50806d5e77eeb5a762b1371ae4dddf5bacbc0d19b8237d505016d5398c89fa0289e", "SEC": "041d799dc7f51d86dbd34f149157812592b08df03249ee253c5f6a998018bebc6423138bce980eb0eae79a5dac073a352d8742b5d3f8cec422fd163a9ab3e13c30", "TP2": "040befffc5c5ea575766c45a69945640cea75e92006e494037998660e04bf6af93082b6632020cf131e4fa619654f1a1031afb7eeafa9cb1a8b697ba0a4ccc1a0c", "TP1": "0418a17b2bbd9e84ec76abae150a724002a5289dfb9ac30b0f8059eaa018c502a116b576f68defe9dd73a512c3e4e12c1eeb225d484f336ec966360c77c19e4a2a", "CS1": "04103aa39f9f3ef8f6734e51371457bf7479b19f3ad0f412b8cd7a272964c4fd521feebd75306f8389c37cfa606b31a34d2dbbd009e387b7284eba24cc0ab0f134", "CS2": "04047761df0beb8bba110d7ee61a963c6b7746491c914837f5a7ce6aa5f0d08a7f0ba7d6a57745033725b93ad0948d4022779b6237bc1d63611288afe6dc18327b", "HASH_MPIN_ID_HEX": "48761a549a27198d7fcfefe27e94ce74a1df5ba6e1537c28e1bb295142b9a541", "TIME_PERMIT": "0404c0f1d1a1cceb30639101aafcc2bb8735f360aafa6876639feea93c7bc9856c1c95822ed3527d6a2b895169a70dcc859f2bbd2dad1b46d75d3cd8b23d37d844", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223433326463326463366564616632336330323133623063613931653363303233406365727469766f782e636f6d222c202273616c74223a20223530333765376431316436646261656161633566373438356135376561623864227d", "TOKEN": "04064f5671a834234062ec24de3dbe95025e16215db0607d2ed8cfbc09597ab305159148b31c836e5b4c7a6ef5c29e3fddddf62a8c5401bc98bdec26a990ee32e5", "U": "04221cc66d53b647f408f56d14c4a717c4a88675998c012d33b5fc8b092e5e0bc502d77df274d3440d2364ef15a01d3e42c00dbcbf965334d512a4e5d2460e3161", "SERVER_OUTPUT": 0, "Y": "1fbc0962ed01a8ca5d821efa454f8c1af25618445968a9b0fde2552c346868fc", "X": "0936eae62246f5a05b8f4a76b242f9fd08a2355f31a39011046229e9e53a7bb2", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"432dc2dc6edaf23c0213b0ca91e3c023@certivox.com\", \"salt\": \"5037e7d11d6dbaeaac5f7485a57eab8d\"}", "test_no": 27, "UT": "0400dad3324d2e1e2e9ae15c1da7245333b494b024d1027d767147df95e0ed8f8320b4552eca8abb8a8be2c810855b5715ae418ec703d88f2c31e78ec3a97df1f8", "MS2": "17413bd4a1534dc12c8dc16c16d288a6afabf0ecdda2e6083755dea06f08eba1", "MS1": "07c8059aa6255c53001858032d666252c8d16eb0a77a001dea868e83b02f39b4", "CLIENT_SECRET": "0411e7b9411cd38427e2b5f334cf47a3d91e18fa48b76025c8d460750d1bba09c418e425fb3cecb4a3f6027f7b0c9658cf3e2207fbbe5ba161d72a49ba2dc5e9f6"}, {"TimeValue": 1437055595, "SS1": "0c60a9cb7df0b4f865f71cea39809ae806acfe8dcf0a290c739c8ae231de19c518f937161cd674453e8aed3afff37f65d22deab42087934bf8c7c129fa32746e08445f1c91054661adcfe573e65e84ec4a4851274fc2a4fc4818fcead9e2faca161c34ffd8feaab61420decee9fe4f0bca1ebd04026475d4f25e449b58d542d4", "SS2": "1b98684ba8d6d319d4f66ceabd5aa73293b34669465460141569cc8c2756f01e15aafbb7e5812f9a0be1ef09e4cc0daff4ce7462eff8052e2f01cec5a76c8221140c125aabec9dc889ff072578bebb090ec32a870134b046808fd716eb45ffb81a670fe0eb2660fe4e47da08d301c8cd839ba24c0acaff5844a6864069d599c2", "DATE": 16632, "PIN2": 9999, "PIN1": 9999, "SERVER_SECRET": "22284d465e0c67d5c2fbc9612b9db44125b71dc75290fb278045c582cb404b31149b544773ba37c57af18b20b37d73d4f372abc3ad5fa7852013c60172a5af6e052362962bd7d8b7419475d207ed11400f705794fbcc63f60a2f365745eef9e92389b1f198bd4ab6e34f62651d3f95194082e94f4d526df75d5f7b3974898ab6", "SEC": "0423888d3efc6843a013696a3a0240ef6008350cb2b1185582bed5529e8d6704f11f0a02d276e1b7d376a0e15b1728a621eae7bcd7b2e508fe319a7437b39559d7", "TP2": "041507a514a639d5ec7fa05c9a273cac40d299c4482390a078b9a61ad411d3229b097998e8d65c19cf92ab9f84081ec6215e698240c93e0acce14e460b7ca676e5", "TP1": "0404db51d8875f2a7440a87ce6c35d7dfef5fd333a728bfc0693db901a7ffe715b07f37b54980edde7bc9b177e9b9f491227a7eb07b96d97c1d44bbb5257637258", "CS1": "041b01c2446f184624eccab4ff5eb4c98615cfecdff803b5ecf1a8dcbbf424a9d710f063dae5b046628e9cb07dc7c283030512bd4d71c5c30c5f2dd4714041ed39", "CS2": "0407d70e9b9dc9de09b9712db2055f87b8111eb9e632ff897065b651ce9e87deff03c29038c71597d421dbae0403a17999a24327077458c4d75d4661fa48734a82", "HASH_MPIN_ID_HEX": "477636927c711839a9c19de5ae0463c70194ba8f56113b25d0171f82e3b866ee", "TIME_PERMIT": "04056d99e09e7f093197f51b7bef18836b929fb63d5a86ca7dde40fefb904fd518099ca2aaa0c1fac71d76996f068fd64f175d5b51ca4d441e3d645b29957afced", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226139356239373065396636653230303938363934623537306265653439653262406365727469766f782e636f6d222c202273616c74223a20226239313339323137333431353363656464653831623463333766396663343538227d", "TOKEN": "040dd0c1fbc431b40e1484ace8ce4aadbc77e85af4b1f73af696c1dfde8d519dd1147668a78bdfd167f3719ef501a6db2dff033ba498da98b4c54c0d7b5b0c9920", "U": "040823cb8af323b908c5f0bc97d212b5e20949552b826dc661e40c86c3b226410c02174f0690dcad785528805b78c7ef07d4ac729d2f0193175fe181cf28408d25", "SERVER_OUTPUT": 0, "Y": "146c565f46d383254cbe15678da45a78d905571a39950d0a30607fba96064500", "X": "1f058ca4cfe2f7e5390717c26157ef294e6019dd5b9b7b7d62c42ae1bc782bb0", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"a95b970e9f6e20098694b570bee49e2b@certivox.com\", \"salt\": \"b913921734153cedde81b4c37f9fc458\"}", "test_no": 28, "UT": "040013f7d9333f751d44df9133729d84d8730a67a0af0234a4bf7da2651162decf10f48868b43a6e9b855364183169c69a4617ed17608698c245bfbc53e7c251b5", "MS2": "21d16c7b703746f2851b536fa753068b0fbd9c990497a24911fb8c9ed6454352", "MS1": "13e20d1384d089d5d41a9a47408e2a06a73018b7207933259aa414f09c418065", "CLIENT_SECRET": "0407d8169eb02def78f94e4ea04bc8ce69949eb887d4563bb745232956465fd7f1079b5a3d74dd0c993f96463983a2b151944c40b657f1b20bbe73bbb07f04d3e2"}, {"TimeValue": 1437055595, "SS1": "127e5fb5ac44b7c9c1cfe30f900b8204b82561ae33240e76325cded4c32e01981382718ea69409135524dcf45257013626a2128851d6c999d350e197bd2050c60045cde45adc1a750d4fa947e2a2e1ea4b189e2d5198101702fe2e0e9606901306f3ce254b3894313b75202ad2c5720e02a80e68117ae40af0902e587e374eeb", "SS2": "11c9e6507c0db4e449dd406e1c6c38681439f074afc2869c8c05ab64f3f48bda069c405f65d9f79dc15567bb9fb457bc82bbf5243042d089fafb548bc4274c84142d6815345ca1cea11c699fa92edd3c4ead371a4db63f504651fa97556e8658123040913c21509c47258a13228d32f9aca4d39c7548a3213617efb5d7b1be8c", "DATE": 16632, "PIN2": 8311, "PIN1": 8311, "SERVER_SECRET": "00290168f33cbf40f80eaeb5f89abd1271589af492e1be13d6ae422da44462d1005848bf853561e02d130a092b88350dc0c6f12dc83c07f0149a3ede46d8de740f6459cdf65cec8f6059d5c3fe44848b7bb18232d75b29c73c53bf1a5b9e248d1091629582787adbc837ee2cf364e4a77e1aa46e64a8361056f578cf8f315471", "SEC": "041ac4e606ce830766d2f4e342c51f11c80a38c2907fc5a40014b6bc250e18c9031158967e393fc318e91eac3a17d0b7d0b9a5f4d439eae602f2852558c6e01960", "TP2": "0419d8a91f343e09fba77d137451094604dd259c6ca9815b39e9a45f3274202abd1c2b7bb662411557cff66393e598a571c4e7fb39e2db532b171e61fab1a6e69f", "TP1": "0407ba13ed18be3c0a2510044a8df6c932546eea91ce377b728e4f89c09fb33010202deddae7290a9ddf003a931135797887c7ba3cd404b5a2ac62765a8c58fb74", "CS1": "040415fecc150196388a478efce9fe28a45ef0c034d78dba3529a0ec0c15de4196175ed6c6cadb8470c74922e983a3b5baadf32ffab278fee6a35588e1ab802267", "CS2": "04152bb3264fe3a767ac6d507a388df4933f5a0bf56a4d568f1f9ec6b1057c32421e57e00cbdb60f55adaf65ed7eaff3977db388575e02026e2d0103f879f4903d", "HASH_MPIN_ID_HEX": "e84df2833ffb5c966812a5af384740c867be7c9e4f8bd239c8464efec49194d1", "TIME_PERMIT": "040439b0a07544d5b8456eda60d517f34dbfd0f6b1b67d33d14737a586f5a1b44f0d8d7e83ca56eee6304e607c5cf58dc4aa76ea5cb8dd8319bbddf114636eb09e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226438393363323638363136333834386234643735653231633431303639656338406365727469766f782e636f6d222c202273616c74223a20226532356665623362623633326266363862656431346636313233633366396665227d", "TOKEN": "041e8dcb34db6b34b1811cbe9ddb62370e44bd585439128ebb7fea09dd4868d1980fb206b82b1c4a1eec442fda8c060c014e9d776d69d86a7212c94ed8e0063cea", "U": "04014f675010eaf17b22e1e73734ecf028cbd7c0fb5ca06d0cd36b2e6e651d14042021dbda580e5a42dcdfa471f080c7caa235fcdddbe3ddb71052292d33a211a5", "SERVER_OUTPUT": 0, "Y": "0a4c957d5dcc154b41c7a4689f7876825e2957805051354ee34fd733296d7049", "X": "0d4fce3817bebb8a8f167c1032880d02678d38071806ccc02a61cadcb77d7c71", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"d893c2686163848b4d75e21c41069ec8@certivox.com\", \"salt\": \"e25feb3bb632bf68bed14f6123c3f9fe\"}", "test_no": 29, "UT": "040ffa5fc99b2bdc2960d26a1b0759ead70c0494f9fcef4fea913ef10c34df99bf0b3ccc1edfdbbfa5ccb60aa8e432fc528c520a7be0c871f2c010eefbc70f3251", "MS2": "008be08694642734b2700fa1cbf49e10c1bf392c9e7b720c2387f753ad2141cc", "MS1": "0485526651e8c4636c87c16b617f9e8b85129b0b997cdaedac45accc92279ff7", "CLIENT_SECRET": "0410d3419ce709d5628ea431eb60c22fb1a0d335f10793c270b766d5b3b4e5d686083cd3bba94de579678621c24d4eefdbec904b4a007b56fca69e7187097302b8"}, {"TimeValue": 1437055595, "SS1": "1f33bbcb414e773bb083c4d9b3be80e00a644518d0aacf4cc6328093941c2f5b12b66983b94465b0a9a10a5a13879263f0b4a8623bcd4d964d974feaf4ecab250fc71e5242165392bded8be171866025456b204dc45fb55682ebfd15cd17adfc13064e2350967cf203b13d7e5d2436049aebede3ee43b662b01e80b2a5dc18f8", "SS2": "0a256f9da6f1d8adab39777d0fc22d70eaeb3373067bc236fa993512eac21de41ecccf4da447e84b745a2bd9a49868e488c817f86d195a61cde11879af7901271610cbc56ccba88d24b00a406ac595804ff6c0ca89e593de013e3e7446f4e2bf1bea8278e7ca861c0fed8384d1058967f6ea291c7346105b99e18c0f28849344", "DATE": 16632, "PIN2": 4724, "PIN1": 4724, "SERVER_SECRET": "06bc05897c6c9ba2be85e5105ca58a8f360a89d99fc8554fdb5e0e2d89a4e94f225aef6c30467bcbcd686d826e76822569323d1085543bee3f03bde4df6a2b370e08680f1d3316cb2053a921eaecfb5e076393c094aa2d346526f954015918800b0f7495265bba6126d0f3465eff5cccdb0164822f7f49dfbaa470ecb0a6d9b2", "SEC": "0422c2131d8c3ec4d5a29e536087a74ea6d001741a7a1bb8eabfbc26cd390620131f48d38e701d62a76ab52f8865a28c7af3f6cf88a54f669c0df253d6ee0f3220", "TP2": "041f2e80500d837bf81341f8e0f93fec799173d88d1fd9fd182fe107c61ae08ec609f02c71151c84fdc3f3df2d7b7be56ae1663cff90a367ec488b5e7dc612be45", "TP1": "0403f4e8efa0dd7e1c805c7fa75c7ac28ab9595ab61f9a95b671a34a100a7d45362199ae25a88a438666bd04f66859c40b72dc2e7e48cfb96eb0c7d94c431bb31b", "CS1": "041962f1a28de48a608d2036e3e22837fa79b1d0e1839856850f21f87c51570e9000db6180d79481131c5a7fbe659d2cc5399dbaa6c7cacf80b9342b2bd82118ce", "CS2": "040fc328129e1321573e116aae4161fc8bde71cc0073f38311809e0d4a51d2ed051c8061436ca7861ba6e0f5e77dd2fb3add0d0a42b67a35286683d966e30b5845", "HASH_MPIN_ID_HEX": "e9218268dc397fc035b6261a7b8bf52268754315ed6e411547835a1b3da0d803", "TIME_PERMIT": "0414bd6faf1ea9966d8adc86543105c698e7795557a417de6a626db5b3790ce8f92288e057fe1221e97654930852a290f07c69677911a0fa5a46ebe7d25ffd364d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223266643839303863663964646534646263316163633132376135356161316431406365727469766f782e636f6d222c202273616c74223a20223639343563396435333637386234373861633635626439393830623237343932227d", "TOKEN": "042088251bb3a5121d94a199185af5f116adfb72b3c925a889ec4ae058cb583dfa1f623ee3413c929b5aaa1ef7e63f34b98fbd296ef44b28e43de8391646473c0c", "U": "0412c53b9659e7ad533d55b43e54c9e3e6b512962ac8a0af48155e751945599b4301f3c65398932c871f41bc8a52312092ffa7db0cb0037dbc5c70147259f7df64", "SERVER_OUTPUT": 0, "Y": "1bbaaee3f9887d6cb3768139c111c087f99b11fd5fa75fe2da1024ed89b625a9", "X": "03104e488bd2779880f6540eacc06b5da3df0bc85dc954421e83571ad56270cf", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"2fd8908cf9dde4dbc1acc127a55aa1d1@certivox.com\", \"salt\": \"6945c9d53678b478ac65bd9980b27492\"}", "test_no": 30, "UT": "0410a70452a425f195ab4c59d95acf37d50d092d4943588396de625f2210e4104220d15a55ade2216c99e0e688d2a01e627a31610e0954e08ded8662de05768d91", "MS2": "0f9eab17fac6c67c5949ef9409a72578ce875d44a588184075d14d10be2d6b6e", "MS1": "201e0d647978e697f50f22a02155e6008d75f8af32f35f0f95f020574e16b951", "CLIENT_SECRET": "04036320eb698fa593e2ce7fbef881822d72bebc249d53b20fad4fdec14b8217d614717aff86705a83e7b76f391896288b02cdbc8843a130cb3c486d0865509e8d"}, {"TimeValue": 1437055595, "SS1": "1d465309f394ae8011f9d21ad37e08551af11a074b97df141c3704e6e6772c7a172505ccb9833f2b271bf861dd0d2bfc133d77b741d5e589bc9b8efd497e7a57177ad6b4c494f90ce96918763b0217ccdd4524e4105b096f85509e46805ef7ac08c5921f88b9646040bb47b5477ac0030e0d4839d0dcc28561780f492500b978", "SS2": "0da6b1e10f8873d93734a7167c47aeb2f3189c09f4cb5e95d737fcadb649f9c80e08209e75740db4e7dbbfd826aad116521271e003354d5e147a0fe808d944be10f59d565fe0bd82785dec84ba0d83047a7821a12d7fe72252e3a0a478a14fcf1d31388c6dd0f3cd08f9359e538b0c558e3b433660f6a942ecd2f5166268e437", "DATE": 16632, "PIN2": 3162, "PIN1": 3162, "SERVER_SECRET": "125fbd3665f7877caded92937d83bb2f9d090776d0aedd7ae7caa17586294a4604808a61aef3a69d523ef3cb7f0997c8f22d9c8270d66a2d692c7661010905571daea9730a06acedd23e1ccfd215541a3a377b55121abf38b7f95ebbc52eb63e1fada2cb352e7a74a3feeb3aac1daadc6c09b00585700b2b48bd1773fdcc906f", "SEC": "040765abb8b1ba09ac6f5471352d9552a925b8f7e1f18ecff5976341392ee7fcda0c83369261a05b95a7f4908ee7d09663c9c141f03e78a92ccba1855862444581", "TP2": "0410398c4d44be77708533a49e3d6a9a07efab3d22af5a6eb5ec9dda8b22f9546f22ba8b9972958b3e96fb5b9761305255fe9f1169add033ee3e67c335ec3ad749", "TP1": "040ce715dec0f779d1c4fb3f98c7d8ce271c3a9e0fcf22bb43ed67472d07aa2356207b157b52cffcceb326d9fa74a8ffc8f1a68fc049266db461da05d4d4719030", "CS1": "040bcc8a2d463fb79c8300787a62e5e9a0cd0ec20769e5ad90d5b3327a4183689719fdf1bc8461b51e8096f1aa38cd5c284a6952f482bffd1392535ed4ef5929dd", "CS2": "040f189e7ffa6b9345de3ecf0703f7568c7df3abf2b60471ce7d3efc89b0173efc0723ee4b0360d1eff0d9b381a46867e1fefad2875e3caa96f1ada10019ace54f", "HASH_MPIN_ID_HEX": "ee593c7d013e417bab619b9e343122acc348b7c18b93849451fc7a9d1cfd37bb", "TIME_PERMIT": "040a90035339c9a7515f265376a0ace51303532a7c401ab0a951388f557dc5868f1c458d7dcf32f96f8f861a3e1595468d518ba1e4bae7afb59507256a5beefb0d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223362633763636436393239323136663063316535653936653537356262633135406365727469766f782e636f6d222c202273616c74223a20223131633166663761323631353633393732316630343433356165656636323163227d", "TOKEN": "0414a7a25b19179bc9320368ef9c94b70597f509bd1852e3801258a30442d897be079bd558763c69061cfc43c2c4206dedd7a2d65edffe3be4a667a54ebbbb2153", "U": "040e2cdfbae98e9eaabe9882f4624f033d07c776e469245aa89f79aa70df6a7a5806ce162a5cae518aa1cbd0efe7561277356dc91eff5c0478c60c715e11a4cae7", "SERVER_OUTPUT": 0, "Y": "117b28eb91b886cd4bb7b02901c286b099234f901cc986ddadf2e51d7ea249c7", "X": "167f09cf1c2ae3c2048325b6d42e1c4d35a2bb68fa0cf327ab70bb3fe4d947ba", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"3bc7ccd6929216f0c1e5e96e575bbc15@certivox.com\", \"salt\": \"11c1ff7a2615639721f04435aeef621c\"}", "test_no": 31, "UT": "04197626a5c2688d498afaf2169c460741f7d6fae7f9bbbb5c3099678ae823d7b60f15deaa952be03cb440709fb937b2f343706257cc615c3841bdbf3b99f120dd", "MS2": "01ae92ce900defc0722364434077e78f84414825fe822750c7665c37d7099cfc", "MS1": "164eb23ed7c4e6225f4bb198469b4f5e00a22aaaf885dc8a347782f4242d788d", "CLIENT_SECRET": "040fc73d1f448f443b13303e3ec36d1e8dbd554110e4ce20bac7be53d9eb651156146706261c93d7918486e6015ab2695538121c8e9b12c82cdfb92604af1f2f9e"}, {"TimeValue": 1437055595, "SS1": "1f49d6ca4412372e1ab4e0768421e4f6bb249006bcdfb189179964d60ac8c61717900d0fdb5f79dd19c26e74b6ffc38bf719be8437f8a7f3656e6f4565084c5e0534e742040d2e75f230aeb8c9b9d788d6a6e42fde3fb1a801fa2df5a4fbb9081286fd56380ee1d274d4fa49349432fa8a8b4c748f0dd582e72e403d7b5472c8", "SS2": "22127c026c20b259ac7e51753fe76224adfabe829b9db899ecc7768a4cc900381e36fea902207938f4b131be8e0165d641ef543b33574cede95d656c1522631208cbd760e590336eceb7fbe925d6c6f30b25ada89464d80050da82fb6408ee742371da36bc57b081dd30e6b37038160a7be92b695aa4f834f40a5aa14138fd62", "DATE": 16632, "PIN2": 4050, "PIN1": 4050, "SERVER_SECRET": "126670c368a06296b366907da0096196313f67c5570e3d26f65167cc8d5bc6b418d088da207c3207fe9f4070b0840b31eea2b641265520c0a434d46f1698ab5004d2b8b28155346fbfa0be21b1b7bd7a6f132563e1c20e79e65ccfdf624723f50f5fc499347eacd30505236c2bdcc2a5f4810ca8afe7a9d82a90a852bf9c5964", "SEC": "040c114c842aaff729e6879d4fd6e50a8972ac1c46cb6e19843cfb3e94951a816423bf01335210b47e6a6017224a7557bd36063a6c09910d307d844fedc00dd274", "TP2": "0403d7dda152be9c72444b95992b1fbdf24921c36ab95b4cfe3a202983122a9fd01674f41a8c29866dad90a3be995208eaa0526f1d2f9739eb9026e46875bf4a3f", "TP1": "040bec9964c9148170d4fea199485f2d84a6db06f06b7dfba8f24125fc6bf576d10f267040c00f6bad7c2c8d041015ea936314aff5269ae0bf94ef1ce0ddf41ef8", "CS1": "041c5bd20c107bb436ba1b3423e891f45137e2f7995ab3101d012480b0c06db4731c6a4950e37a3b4e01f792a6b0bb0381542502fa367fac726e0f8852f1f68ee4", "CS2": "04214d371f45973b107469e907c9bba6b47bc8c74e7a4928d604e97fc1e8353ace0fe820dbb5fcc304c52d3623f60659d64f24b21467261fe4ee37daf8010b93d8", "HASH_MPIN_ID_HEX": "b2cafd2fae498b8129e646d70f3c323c8c200562d2fb4b53c2addd0ccf5ef1f3", "TIME_PERMIT": "0421e190df16a8e19f606ff1d8d437e04b5b94c4ad3e2e3457d5554e74b9bb83ac21895bcb79545b301c0287d335b3b4e2add8035abcc8e40920f1b501ccad8b5d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226364386234636637386136363663393331356632356338343333663037613639406365727469766f782e636f6d222c202273616c74223a20223066616563646232333264383265326465313264313636393137616537646632227d", "TOKEN": "04040c2e3ff4a984c0a9f0fcdc735c1561d67aed6fa9dd97cb5dd3f972cb80028203e8ccd234ef2e9a0cf9c771ab320d2af7a1cd19c062a4922965362c8b7c433b", "U": "041c08df1a0fb109b390d4491dc64553cd7ddef241d508c7bf50ad0e8f90fedba1128bdbef167bb7705ba44245536d355d308bfbd5b31c0ac3329df7071de75cfa", "SERVER_OUTPUT": 0, "Y": "232c1568a94f777027de0632aa6d79e41f0d10bc7c13cabf4a45ae76861c6a41", "X": "01e17c5856f8ffed235932086b2d406f291a031bbef952bd42a21b6e807a5eea", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"cd8b4cf78a666c9315f25c8433f07a69@certivox.com\", \"salt\": \"0faecdb232d82e2de12d166917ae7df2\"}", "test_no": 32, "UT": "0410c045f9b28e3a05581ca989bd2a42ddd93eb2dc28825eeb400b6887d50d3b031c6caa8aea6031fc6197d15d1eca57609acc46976707a78eff6f705bc61e553e", "MS2": "0f7c6fe63f28c503b12e52a52ecc97d303af20eed2a6e69671757ede2dfc33d8", "MS1": "0d8411e67711eb34d57ad88545d676cb92bd7ee22ed566697037d5c9a009b0a2", "CLIENT_SECRET": "041b543657beded90381c37ea0c05c7f1dd0d94e7999041a6b6d1c9496ff4d9f6511bcb24d1965dbb3ad863b10dd90aee61bfbfdd89667a2bf97bb119dccd73dad"}, {"TimeValue": 1437055595, "SS1": "0104099a3a013a32b07394273a927f16188149f5d20e4a791a2eb7939405bcb30b0c0526bc8b5d16cff4cd4fc74d536fad7f562477fa10cabbd5774c515a15b2185dabbd6956db03823f4ce9861c07e95e58caa4a249bd6ef4ee085bea56f9730605132e3bbd5dc847b3564632fbc75f56a784c73a3862fd944fb62014e98538", "SS2": "1374aac889b689ee3fef322c973e4f209c49824cf10d49803cafd4fd1692f8f301dcb42c13a0dfa8e115a41269db2e66974847ee20554a3f54e10db8ac8fe3421e5ba611b86d55076024fdffb3ef93a2999faebee1f9a038a08478fbfdd6d2e50380bb420ce77dbd29280cc84bd6fc5b3bb31c266279143523e0d3a4890d5759", "DATE": 16632, "PIN2": 9257, "PIN1": 9257, "SERVER_SECRET": "224afd7c356bbd6e5e288551a316996b280174758963f78f5845e4e494cc5eb8011c2ee9269d97f2f602de59361b1b699b1789f8b1c572ff24ad5c54d6633ca70b7c51a113acec31a6d559d0a9c9b2c17457bb2842d9e4e1bfccf7f29faa332818ceca79f5b634388185a56f9c3deb1beb95bf7adc258c1af34567ebd42080c5", "SEC": "0413e53b644fdf41dae31ca3d39fbee78675a5d36a71fcda9bed8a74728eb66d1402fffe7e144265e9cacc53f7ed54dcd8694ee05e3490b72b789547f93c479e39", "TP2": "0416c2f41baae755f02913a1e14b84920f2577f70f84da3c0181169d927aefc380208a23dd62d5c273bed925e5430b1edbefa9d4bf77ae5428bdcc137b8f39110f", "TP1": "040234826c2adaa11faf0a3e93bb25192216cde533deb6f3bebe1ab6596c0f508f17d416ec5864ca56814b7799b065351188d48554f96a8569d9b9d9dad3b91a74", "CS1": "04036e52fd7164584d9844dade01da4cc6e16963d9cf383fcf79ab8a1c81a74dca014cd670495d1092b756e39086a67a644e95f479d2942234fa9cc66fef58fe37", "CS2": "041b62214af43f92bf80c3ef6855199f156db27ea13b4b9c9eeadff1a5d7a8d1b40f8da715a924097eae7907dac1b7e6cfb83c0bc423f18d88122346dc0185c9de", "HASH_MPIN_ID_HEX": "44b21c062f02e107843f7321681e8bb99bd6a3ec5aec65b939be68105cfb6984", "TIME_PERMIT": "0418a27b71c4ee3582c82de00d651f4ce1c384b40ddb02954d70d079eac6e8f68a238507ae64b75c58aebf7fdd36cfe1fba3320c62c7f415186b355bba27525736", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223833383633313530646235356266393462363835663332646662666639653762406365727469766f782e636f6d222c202273616c74223a20226565383532306364383437666536656439313434653066303664663265613964227d", "TOKEN": "042180d2418dd3ec7c5308784b748968b9bb19d659ae32193465b0e17fa00127c41202c146605f7c1b8e14d9fcdd6744ae9d69443036543088365588df2bffcab7", "U": "040ed115f2206b828b1a5b05c8b47e1012aebf6af603d04e7c3368cc82477966a61b6bc66e2f91ab8c9314ef49e8c6ac2f8960720ed4c6b06d676c1eab329c1e59", "SERVER_OUTPUT": 0, "Y": "1840e7e3dc9e79f78bb56a774c1195bb3311d2d4b2248bafa377ecfb91a17988", "X": "1faed519160a762c11a0613ecb1514b0a4012ddabcc09590df385b064bf9f476", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"83863150db55bf94b685f32dfbff9e7b@certivox.com\", \"salt\": \"ee8520cd847fe6ed9144e0f06df2ea9d\"}", "test_no": 33, "UT": "0410adee6d44bb88d51cdeb5487ae038937bcbd4958958c36c5a2733766d18d535235e6e197dd6f1789338cb2f58edbb5b25c53006fe3b9224d1694ba71f89e8e0", "MS2": "189ebe018f7c17c3520fa1870ab82e7c246fd47cecf603c64dfd656fa0f658ff", "MS1": "151ffdebdfe5911190174b161be327d94d605d13009b85f265ba6a93cae24c42", "CLIENT_SECRET": "040234de22991a9faef574aa7c7d242934f8ef5686a50f278f792512f99ec838bb1486c35116b091e9064789e26d938580031d36a28adaf6442e8406874e56bef2"}, {"TimeValue": 1437055595, "SS1": "0a7587e71438e51da53121404efbb3ef0d50d5084d8fa3f05e85fb5b2fa434df1e260f257baf78a55c137064c36479b3927908b45d9960a6da3bb88103fbc3b011e13b175c63fdc3f715aee515ef04eddcf81512e7d483f77481368751982c63125bac7581ed907fa534b40d803cf282d94c0525e3f3dee51f07f9d3904ec8bf", "SS2": "107bde1c6acf16fcf6ca1626690a0ac63df782ce4595b7b6d05e3b211ef21e671d8d4d601e67c520e7d4234fbeeb5bdb47afbcb4912802a1a4f08667ce952ab40df1d0ca4113904338e6a33c160f2cc9f7e70fe24b8e13151587dff532b7c4860e90f97690c44fb9952fd3758bfe3c2711f48afa9af68393d58b5d3d02c1601b", "DATE": 16632, "PIN2": 2443, "PIN1": 2443, "SERVER_SECRET": "07c48f55f24d15f581191f22f317c493bb28d62a761d7ed80e5dce084683c4010473895448057faac094848c5bf8ec3e70b01263aac9adf085a19336835428321cff860957d7a0a84b577149427dc18ac923fdf069e2adb05e2d28871456cf8f0849378a7bc41f9683df8169eec25a72e0e63669f093d91ba7945894d0b8d1bd", "SEC": "04050a7277655beb1e98a8ab369690c20352a149e0a2986d3cd87f31e1f2362ab000da83f64c2a6c888c23cd373d89f4b7569c04a19b6f8faf777a1008e7fc316d", "TP2": "041cbd2f4ef659b4d3123cb41e0de2fa1895f1ac9c60d45ad4b6ba5d1447490a6607085982f3b36029a7833ffc14f48024f8fc9dc6b0c1336aeca6fb3bf505b2e7", "TP1": "04081434a3e85a806bd5c90969aefab024cc79025bfd066185a7facb9a5129e95a150390b4aab18e7c3cfe80e6aecc17e7b2e039d68f72f601c865b3e1f020af22", "CS1": "041690c5335704eaa8e36f6d64f5b25e67a6b71aa1a7c130737e2ffba03e6d120201dd3695025e34b2ca45e7f400c7db74ec1115c984a20beb1ab1a45b71820173", "CS2": "0417606154f62696e29b7b306125b981c8a8ad40b91eddec4b46341a981eb94a4f0549b65362b5b60c459fe3de7f892cd8e76dd9c77509f8e1c824d69e710f38b3", "HASH_MPIN_ID_HEX": "a3d84d1241f8dc40b9c2bf8a9644a05fa22fab7300940166fdcaa01b72c86cb8", "TIME_PERMIT": "0418661624295f7a48471bd9d116b3da90d1781d3196b2039988bf100f7e6ca25518d15b6121590aa7b5615878057338849fd00517962a49e2ae96d47b6d4104b5", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223361663338613437353762633937613136633536343833643866626338636638406365727469766f782e636f6d222c202273616c74223a20223030313765353766353866323364333633646130313234306264323538646133227d", "TOKEN": "04150786064468ab6913dfadc8c7aed87341de5887ea74793ac0ddfb4e1c386cea2032d899fe3d7f4c840ec0554ba170d4362f674656fb951ad3b16009f5f6e4dc", "U": "0406d15a3ed840bcb4a1363fb4874255efa5014c19fb7b6944691311906882dc311b2b1350ffef85d5d75aa60f340bb33f03c10bd9cc31e3ad971e6e63b8cf65b5", "SERVER_OUTPUT": 0, "Y": "12ddd4dd0d4202ef9ee0e7289c91db6ac17dbae4753f1cf0239513961217f0bb", "X": "2360c9958da5a46ced9bc6db0cce94ec3d8afc5a950cbc034ecd891b35281adf", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"3af38a4757bc97a16c56483d8fbc8cf8@certivox.com\", \"salt\": \"0017e57f58f23d363da01240bd258da3\"}", "test_no": 34, "UT": "042311957b7e3c15b8cccbb0b9945a23f61011ab1c70268a0fa4cf2839c77f2ddd1a749e8493fcbb38ee3c9d2c53cbfb31724a252b911b4b03379850982d679efb", "MS2": "2287d15fa1e9fd4a300f3dda4c748bdbbe06df393ffb020211368429a3a75dd7", "MS1": "12543a55ecf65a26854ea0123ac1a3653101ebf071b4aab99cf77e87bc0df77f", "CLIENT_SECRET": "0414d3f124169444f6cae50f996126d57a52e48606f3a0fa7c0121df89c93ca96d0dc0d1a43312c16b9e2b8fa430298b380a9a9d9cdc17c3796489961cb52ebc75"}, {"TimeValue": 1437055595, "SS1": "1cbb9e004144c61dd69f3951c1eb1c576c4ce9d9cc19aefa2f94d6febbf72e990223b510552b2312406725e8a5358ebddd01500e0f393c45ae04c5dd8c79d28d10ff53f30543c0cff4f53a4cef2e7ef6394022a3f217add8eebaf796c6b9fcaa155fcb502dfd9fbda63770ec11e795871fbf6780674d2baad248dfc960fb9c90", "SS2": "13f2582ec3ebd31841f5bb2e407e4b3458fc249b02c31bf6c088d36723ae0b650e9f3ed29172aa172085f98dcff235a71aa3f521bf3c70a74ecbd444c4de755e06471095b6423c319e6c2ce3911e59af7e89b47c0a3116c6826f23c364086f05217fc02bb550cb56fe4979b830f560c8e695ac641a20f3d151aea2e486dd3b74", "DATE": 16632, "PIN2": 9699, "PIN1": 9699, "SERVER_SECRET": "09831989c528340d8e93009f98c8ad06e25cf06ea0d37b4588bf986aba4a09c30cf1884228f835765c3aef1ce5469e7dda549d8a3ecc37fa5221f63a64df1ebd014dc48c3b788486d755623979b59bbea42d0c814cdd367d190d5054d19df3f619801b14009b00c8beecc54dd371de74d47753aa94f630f65f2fbff6a8df7aba", "SEC": "040fbbb722ef00d0fa9e4ab11a54a2541c7e25eb2430f72e3b1698c410c67064a520974f16e447ab881d8194ded2f57d18c9ed17cb97b0d967c22ae796e5d62e28", "TP2": "041697bf514aee344b218bcde90f8e7424ea74d5e563265b3190aa1bc3a71c2c211822372a6dcfa66e38699b342187537e8da98453db8728dbf925220f731ea902", "TP1": "0419e5f212f4d67fd7fbf9f3921399c398fffb3f5b555424621f82a51035b8067d1be44b5d6d44bf6f82fdc429d5c50a7111928b8df274386788d76a9d1347698f", "CS1": "0423be594e69b1a1b7b99ad75ce840f54bf7307b480cf1c4c18f9597e072195a8a2078cd475a4ef41b91217ccd2d94ac254b52c2e06cce443671f9bfffa17f8e1a", "CS2": "0414fe870ac362c5fdac9ef6ae458ca0cf8501094e6d2beb1d48767ef516bf3236195e680f37c1029cbbfa5b22e52cb08488b63150122484df3b2a732c48a627ee", "HASH_MPIN_ID_HEX": "dad30f1f780ee6f18261170daf67957f1d24152c85cee380e7020f0fd4414718", "TIME_PERMIT": "040bae0d3e44ff3fd8d8cfb8469726bc2cacec9e0b34e449155c37a23d482debef14d39a720775737e79f77d507d75b842a6b59897ac5fc9ab0c56a4bef44bd44d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223030333737396432626136396632363431613064663030363530393331333536406365727469766f782e636f6d222c202273616c74223a20223438346430306634663965633465613930653639323563396132613232343930227d", "TOKEN": "041a87f9ffc62a392d6b2aca2894e42c9e289385a410f5b57a7a033c00b9f2c3d70d681e70e06a88da7b7718da14be170e724f919ca28c05b4cc46e3f3307c0a00", "U": "04144298e2a1cbb3f1ccfdde4b858c0660f82c6fd324a9a27264b223a9c71068a320d1830e826a64a8ce72707a2bd6940349fc8a74db3b8441459de9c78189923a", "SERVER_OUTPUT": 0, "Y": "20dfd4ba1d2e887e05c0631d3a8f67a13cc59f4af082d5b23bf7b5312c708e92", "X": "1212e1e0b33d19d72cc72c6d5d0ad9c106850becbbf804a1b0f7d164e0e84289", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"003779d2ba69f2641a0df00650931356@certivox.com\", \"salt\": \"484d00f4f9ec4ea90e6925c9a2a22490\"}", "test_no": 35, "UT": "041fbcd0ac69dbf9899d4f4b9e0244d330830bb3d99b19f0e964bf71af0db6f1dd1c8b1ff6fcf1aeb3818e5529306375f76c21a51cd5656f6029fc5b88d5f6db27", "MS2": "08659eda01947a51add11fc595c19e67a5f8e4c9b4e360d6f8e76d30f87bda77", "MS1": "1bb37c9c7283e3fb6dbfb5ce8a7870533e45b982e129873e11a9b1efcd139066", "CLIENT_SECRET": "04185f288c4de40d4854c1b32d89ff16afdb566ca6e415c36f57dc2ac8f14e181e1920fa2ef9b1db475fe5f772190882875563b650cb0fe036e677bd4efc07ad6f"}, {"TimeValue": 1437055595, "SS1": "1968171cbf42dde6c5095654f64d0f53f8c48ac09a43b9455c91b5ec7623c05b119923aad63fab1cbb4496097698421be05a120b11abe88f2cf326cb5b2cda68100351319e52a1d52225855ab28d9fa323966115f902b10ad3bafd105beef1de12c585f4f70dea47a64953abb158edc86678231a7793c760859a7216de040acd", "SS2": "15e0db0e136c9080efcab81c245b7d2c40c88971e4756e75bdb7ebbce6551fa6116900fe4719b0687bf327c3ff08bb00152d943559778a2776fea0f685171241176302fcd00d8709036600334722bdc1ec81a9bc4705ee7c1d2608717e4d3f741f5d936a853479580ef2f224de0e7c9aeb173034dbe1e33d8ff4d0d73cd8f776", "DATE": 16632, "PIN2": 7941, "PIN1": 7941, "SERVER_SECRET": "0cf1c89289589acb3f9fdef9d017fe0aaf4a789b7a8cd9c92baff759a8e8b18b21870e77a59d3308f6bdd31fcceb5d2af3341095b4bbb7c4985fc86137a03534093f856aeb0ae690efbba2ca8adcf1f90a19e90c688c80e79036552694e4529f0db81462f85c56b7834627e674c836e202cbc4413f02e6f088345cdb38483652", "SEC": "040d2fa1443c068b896e3e05f383e475ee3e24a1fd5f6478a9988d42a23ebfa74a1965f924772a7834aae918d0408e0c442b31a587d2b92cb826992ffdc0b05a69", "TP2": "04239358bf2c90209bffe1f53ffbb4ecab5b2ad0aa9fb52622ef53f4dd4260362708194f851fdca990fa6e12c1c12a9fc1510e199dc97b0c4b06edb795dc15a242", "TP1": "041078f235ce79f72196849c5d17aa3c980eeeea91e4ceade2c72e9a33fcc0f22e15d98e09a1a369ee9c758b9275e9f098fbf30764ffc83d0709fad6b88fb15864", "CS1": "040ccbd6597d34c6a4f86ea93fbc4d47db48fa97c7d4c9797a078ca5506375fa5f057921cda38d562a932b796a5621ac4889a9363b996a73260deef2d5d5181378", "CS2": "042053255a7c220f620aa13e43abb22a54e370b3b1d457ed5993d2156d5a45c9760fa8361e3f95b5bac303b7731df004051b669f0d72b7c0457de149a42d44125b", "HASH_MPIN_ID_HEX": "7733a29c9bb62fd424cbb0fb8179d19ed13bdecd0edd59b4ca56c9dc2395948d", "TIME_PERMIT": "040538fb4ed8c583cbe478aab1f2429b1aeb22b9be06008fe2811a85962706837b02dae13452a20ed0d19646ac44c5a36c6c1827a2afbc650700bccc654a87a552", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226238313934613937323365613161633932343833313461323336336162303636406365727469766f782e636f6d222c202273616c74223a20223461353737363361333734383034346364323334623435373039393534303830227d", "TOKEN": "040d7118fc13e24285f00197225e172c8fd32685d90f2e2e140b3d0c916574d509052aef5cec8453de1f303640f383226295e9378c1882439c6fbab86025f723fc", "U": "0412cf4c17f1b7fe80d6d4e1f802ea75d9f39dc03eeed5c746ae99b1095268b52d0be03fb696d38ebd9c05c43b14cf4952dce2a53571f2dbbc2297770a633b07e2", "SERVER_OUTPUT": 0, "Y": "024974feeef5935483ef1afaddb0d283e8c9c2bbc9ab17b66b54dc114f6fe31e", "X": "07fe24b4c634d6a31ce5b7b847d78135e98ccb02d16ab0ab1eef606d0eef0e51", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"b8194a9723ea1ac9248314a2363ab066@certivox.com\", \"salt\": \"4a57763a3748044cd234b45709954080\"}", "test_no": 36, "UT": "0415c28417b53b0a9a8d644aa2dd9fa13874e9a415caabaf6b16f2047571908e900e1316e63c83bf8b42e978caafdb35057fbdc02cb041eac7ceee7636122ac176", "MS2": "10d3ba2f217edf52f172d164f1c5446f5f30cd4fc1a1e3423759e52651facc3e", "MS1": "05d27d4fdb6399cfcb8dd3049afdfc824c8ad51cd939bf524387a341cebef512", "CLIENT_SECRET": "041319c01090a89cebcb94bd65b142e4e0b389a68e28090590c98dbf3ad21d0e25055e4572428b39b256dd49e21f4d058e988fb615dfdbc0194e003f131a888631"}, {"TimeValue": 1437055595, "SS1": "10b32d10fc4df62c303b99ceb50538dad93f4c235333bfab0748464981505d1912b8e954b5ed54b9e487041c8b19cdfb382c3715184cf8c37c518ba671891f3004b30ede5590c7da7d1bbd7a87406fdf470acc12bbafb5445ed529995fcc8e6204150b338def7e28a295c670dcbe22e0fa83715f21f291c27ef5d2ca70afb7ec", "SS2": "2074022b0ae6adbb8c6d410c1eed4df8484e4dc473013a873cecf13a2df707ad134f4e59b5e90b85365d8f8aa3aa60c10562bbfdbee281cfa8425e0425856051029dac1c25a7f1bffb84804908b9521678d399188b0a6cc5ca6e877caad3dd7b201842dd9f615c56634de3e5e951c2fc644407c9f8601aac0ff0c494a34b3e57", "DATE": 16632, "PIN2": 5123, "PIN1": 5123, "SERVER_SECRET": "157fddf51850b1f37cb616cdce74cd3ef8ccc38cee24cf51e29de76f278891031a2a98ebdbee9a5cda928c322ff4fb61f1e2e990f4d56ce702a57fe8ce979b44029a876c09cb81dbad5aae5734674971c2e78b5ce572c69c31e8f99b3ca5f84c0ba213a366fe685e771467649e15a83cb0fd5d4669f30a80bb7a7e4bf08051a9", "SEC": "040709587d3f3c364b2fb64f2c142ebb22ca41a5bdf4ed20d5ece76b5d9b16559c12292e8cdfd470174fbde0ddf57a16a9e6f0051a937b58c6029eaa1055ef984d", "TP2": "04156c927410349fcb6d3cf85fc588bad165c0f617e9b32735de562b16307af0b900421e6e92f5e8542341cf2e751dcc75be70c5130a0c295c7279f071b568191c", "TP1": "040cd01458da6c1c4062207c3111f311183e7e05c046c39a89ea61a7f1861445c4078519ebbd44089a43264fd22659f913061cd0c325dccb8ffb8bff82851c9d21", "CS1": "040e53bec726ecf161fabec2fd0733a70ccab53a664261addadbe7251ed5159a6e0ea6009da23cb932bbe31c88e85f3c348ca2ec3e0025198756ec4a193cb6174a", "CS2": "04087c66465e5b79613f20cc31a5e585633c5d4c32da9ad8659935f6017b9f548a0554ae69af6b7b5361dec667b7ee64c9e06fb76f0d202103e67f52b33bdb067b", "HASH_MPIN_ID_HEX": "4b6f91941338c28a5e29b0715fb24aac0dcaacfc9612a34e86ce258c0b5adda1", "TIME_PERMIT": "0403f6aed072cd74e17dfa79b3a988cf16b13c9082a84ac9b94e2d90a7dd7710c219f2eb6393bc09fe4745e39a186bcac0ed76863f38ad8eb9a01ba570c526eea0", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223635623466393961656339646565303031656665393566653434363131396663406365727469766f782e636f6d222c202273616c74223a20226166653563303763313137333936326236343734383165623037616165373335227d", "TOKEN": "0412c207b268114f583bbbefce86c72936a31cbe81e1e9a8feb00a83655ae3341214a54e81d26c07ac1ca04ecd5d683303a9d281d916d7d1fa092ada3e7e64c363", "U": "04014abbc90317ae53c427dc519c964137d591c5a532dbdceb5d0ac30ab613f54d201de833ac28af8325e56a75365ad6d65f8be1827fa17ae6b386e91be9fe9922", "SERVER_OUTPUT": 0, "Y": "191667a74ff0b84f33ecd9daa17d445023cff498623756404130cb508b286c84", "X": "18ffa1fbb3b0a6602ba4baf35edbe574c8558c9266f102bb95ecfd7443974bb6", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"65b4f99aec9dee001efe95fe446119fc@certivox.com\", \"salt\": \"afe5c07c1173962b647481eb07aae735\"}", "test_no": 37, "UT": "04187a7c0f99fba112252a686d47b5eaf007323053ea7e429c1eb89e4de8d4349413d8dab20694527585095f08bdf8fef422e8b624b7862eccb39605bdb2f448eb", "MS2": "0213de3c4e03528cd6b9170955e35509e7d5ae2244a8f6762448d46e00ec546a", "MS1": "16e249ce1b2b2d47a1dbed905b7027eed91248537a91a985a3775d266c60aad9", "CLIENT_SECRET": "040e77350a02b780ca3b722dcd0ed12dcfbf20a6909e746fa8f4ceecf0511965af1d68a248c93156f8ebb0b8d46856b0e73b331ee27d4a87feb04fe2be4e5db6e2"}, {"TimeValue": 1437055595, "SS1": "13596507058f46f5da4cccade56f561fdb4ce38791e81cfa9c825c39e40ecd4d1bf948b2b78f53cca66f723463cc17d36d0dbacb6b64fc1cfb6ff1f9e9fe254c1cdaf63ea31fa8f61a3f23723c472a8b2880cfeabdd88157288fe110d97551d500ac4fdf989dc8d42d1dc74a3c6583192fb61ad0bc690586d10320aa4b6b541b", "SS2": "0e92ac9986b50ec25aca1582c71cf25bab90bc78ff26d0804e315beb4f65486a0323fcbfbc03db2ec0cf365b80babe361ca24a5b1089fcd5e61f516549bab1231053a667279cd9437619b559f6b75b5206070d816b3797e953a953c509a5b90b0ec97145de264acce630db0fb6f57cb08ac6decf772bfb5980fe7e5391cbd50a", "DATE": 16632, "PIN2": 1957, "PIN1": 1957, "SERVER_SECRET": "0ec9929b046b6f41991bfab562f76b00be8c4ecf1a965e46e50f4ddf6501db3121954a0f9be1a00c19b35587076e202a89d5d372abf99b8891a8c17d0a15dc7d01b4a24b5d9890041fe8323d425b98ce7c31e9facf1cd58b893291912cba57ff00bd03dde7d8d6cc9e4c4e49d0ec55a1ed729dc50a370dc6348b589683727f73", "SEC": "041313b79f58d4250af361cb9ab6e93160521c4a62f24f20e7b7bdbdcab59d793208124023203c18a5dccbde9a3c98afdbac776b23282a8737bc6c9f1e299bb250", "TP2": "040ec239fb8fc496c2f41e0f62b904d9dba04ab18f67c89bba1214d26092599d860190cf545a40dc19702ce19e2ceaa15558b39b4d185faa83f37f50f108e259c7", "TP1": "040b46bc2682c8ca9ada0a2f57591397d90dd492a59b063d9f598ea248bfce9ae10afea35063cea9edf33a41551d936bfff70a1ad3512ff7434b54bcb42eb6f503", "CS1": "0415ae3002b1bf3963df072d474b79d772109399fe8992b716fe3d374ec8181eda1e201750ea65454b5923a17e7ee0879abff53f83fc94dc58646f6f23c860c366", "CS2": "041ac5dedbeb18663ce62fd307cdca94fce2cc4a0d5d33af079a292f715de4b4510b5fe7b4135fc7c274ea19be339184e1b13c453cd5b6454ae8d8056b2ac0ded4", "HASH_MPIN_ID_HEX": "bbd7b2c6dba19331dc76b041c8ab465d80b8c2194e337fb05973e8539a8018ab", "TIME_PERMIT": "04087dd53d7dcdbe8f861729ebf387a01e9da937335ca6ba570fe3ba851f0e918b0a021cb7084db2dc69b2c524105334b98e3816e4687057bb18930f48b3b3dadc", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226366303534613130623537323438313637633837336466343231363962346336406365727469766f782e636f6d222c202273616c74223a20226362303163376439366635316466646238313662393134336133346561326533227d", "TOKEN": "040c518a500e49fb6f260ab32737d7aa0a49ee1eb4318cc1465e6ebf9e7d72dd1614c48d470304844b34920977696d14a5b4276472280b5a046efd4507cdd14315", "U": "04194c3409ac17bf6295679360e49083bdcc9cf36fb23c016f1cb37b8dcd5a9ba607fd2b3b95fc1a88df72bdc27ad39796708269f9499d1632943577f203c989b8", "SERVER_OUTPUT": 0, "Y": "03b9695ab81f1e4c294c17794c691d0e7953b2e9722944809cf2a40c2bfe6c4b", "X": "08a6df8914e474860a441aaf4b814a86bf3c117ab1a089e9cebb82abdd07a089", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"cf054a10b57248167c873df42169b4c6@certivox.com\", \"salt\": \"cb01c7d96f51dfdb816b9143a34ea2e3\"}", "test_no": 38, "UT": "04105e10ba067fa738bf5c58140657fc5c85a093f8209a94994a898916114d1c551ba505eca9cda3f38f53d69f07c063349d3b42affcb86e4cc51ad8d0374cb13f", "MS2": "00f0aefca3928724f86939fce271cac9c250539a2eff7588cdba83667401b901", "MS1": "03f6d87c2de822fb2334c9745f71a930090378399a3df7512f521f65a9eeb804", "CLIENT_SECRET": "041afc2989a7fe73fdd63297005841c6f7d0bb5d50dd642fdb45d3ba2d2e7242b50f88d422184ef146ff208ee8bcb790558b3b29ba5f73adf808c586cb44257ba8"}, {"TimeValue": 1437055595, "SS1": "08a2a6404689db88e357ace47c8cf9a5539c3628fee88231dfbd3b410d1abdee05ec217867391b99ddd1af1a81d1aa44b0b67c37d6123ca212b57e794c3ead461cf4f33f2f3badffe99851a603aaf91fc9aef5efd28d0022ea9cf7101f7458722087e39325a67e1fb19458f195ac46f24f348b1c38af2c1fd510ee2c55746596", "SS2": "0b232e1c26f0be42a545df0184dff1f36f720d453eed831ea239db4f22f476c8006d4495950b8c176fb0ef0f5519f74402d6bcccf03cf85158e94da423ed368b01144f41e0e64c681fa39664b82fa4f823786d8422ab6b23aa7e1aa424c25086028c1e51fbaac6228d9c5bbc1bb6d5fb8827ba3cd025b6b517a9770379336e92", "DATE": 16632, "PIN2": 5486, "PIN1": 5486, "SERVER_SECRET": "0aa0e371e54939b5d5dd273c7daaffec4fcb3a064bf5156168e2624afb5c25c21b44efb82b3be76cb6751b3ed844e6bf4dcee29d160f5f60c27e8f67ec1bda390036700d0e6ee90fe7cee3280fb57b32b00772ddecc0a7415beb452278a7191517fdd158ff903b42754c6a25b098ca665b1ef1d54cbc653b0c3792d6ad2c9c91", "SEC": "0416dc19427f26cfca296dbdafabfb4aeb12a95cba5086a23c82e9d5e086acf647067ad1c253ee087965d27e2240b2a3f5d6560a81cc30fc70973036f39b6c8b91", "TP2": "04225b9cc4d88be43b852fcef193ca07469f64f75ded58ac28d0eb2c71f40ff9500fdb80fc9c9552c12d31a9119a61b229a956dc7013bb294a023b298d4415cac9", "TP1": "0423fbe89b8c7a2d5f83a4cfc97685e070781665f2c1228143baf39dd842f12f052162d9c5adb3acb5723b539a6c88fa81b6bfbf8e3fe5371bb3dc46e8ab39272d", "CS1": "041c904b5e9a475d4bd996d601f6f0fcf7841b5b28cd2a8bef1d44a4f1ee4648ef015f56d31bd198019a5826417720d635ad69819ed1f6c6a01fbb41c6d7c72983", "CS2": "040aba13ad3f6832030ad2361eb94d266a34f3eb3bb1475f38e594ee39b8d6091e18cb9a997e7a2598013f970b4e901309475df4602670a18223295dc07a8b399b", "HASH_MPIN_ID_HEX": "cd968159425422e0115d74d7e508cc1bea4d2968a6dbaa4bfa6598d5b4815797", "TIME_PERMIT": "041032ea9e65f57d799b9b10a70e290fb4824d4f12cef0c4f585df2eab11fe741008c739adae59d00e7564b88c4be357b7329d08df29fb7bd9192c709010b23126", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226534323463383562613437313738633732643031656433316164373666333739406365727469766f782e636f6d222c202273616c74223a20223366303333653730666561326664376139363264613333323663643265666335227d", "TOKEN": "040388b80e46b7d314d864c7be25d35829764082f0727b86d9b81931a089af1ed8236339c1b5e5eb62a15177e6f64c88fbd13e63015c06d81ce026623a8527351e", "U": "041cf31ab0ef173d34b3443d87c1eba5b751c39d77c4832a8f31e9a4827186842a1bcbb6ec9c5c62f544d9dc37a13e1981483c436c26e2df3229b38778909feb77", "SERVER_OUTPUT": 0, "Y": "04ba899f164095bf64814b428f81b920c2bd333b7c440220a49d2cdcedd6d895", "X": "127d39010725d4645ac79232562f9149d17c4bab46f8165cb08747d07a95bec5", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"e424c85ba47178c72d01ed31ad76f379@certivox.com\", \"salt\": \"3f033e70fea2fd7a962da3326cd2efc5\"}", "test_no": 39, "UT": "040cc936ca58944749c26d4b90ed9fc38d0395e09fae48741154ec5a9e47e295851cf4bc33634f1994244475a8e8a6ec1ab0dd44cdac8d17455b6661a4b102e52f", "MS2": "192286397170671d5b100b8164f4e2cdf45fb4a1f7dfa2b7289a3c5c4af1bcc5", "MS1": "14ba1f9a28221b2e03f5f707ced565c5cee39268e463075e6310470b37ea89d0", "CLIENT_SECRET": "0418f71d78ba57c2a74b9096c7a79ee643a57996908d6f02446edd71559d8e6b7f014437196915d8bfe207759c3a71bbf1b9868bfcf31706c5b132b174dd87339e"}, {"TimeValue": 1437055595, "SS1": "016a0325a594083fff0f3bd40288c6294a8c0f226570a3ab42dd1ed6173bb6f4074c5fa46d38cf601de264e2b6ce7a8a379c44f5096c22c8a45db6712f3e39141aee2820c43c982381c77d23f2a52cf38b4fe91c6101ba1290e75b64cfa524770382da0fb5a14a7e0bcb4c2f59f1804d76777fdbd938f9b64f608b7501e9e0b1", "SS2": "1bf676a0a310b4b6e1db46c397d185a0bb08f72892ab7511c40261b015397c1605974a6a7b9ebceff14c318a1ba879a341a47bed0697af4cc918ced50c01e895079f6a28a2af7a50e409580777e64a892b387b3b10a6ca16d36dfa5f4dc31adf025fcc03da14d6d4b65302b17f6ca39e16f78f188d0dbdcbc9a0ca8d9e4d2c1b", "DATE": 16632, "PIN2": 393, "PIN1": 393, "SERVER_SECRET": "0fa3f54b6c96a8fec36aa2c36598b129ffcf575ff22fd861d6799a9ba96adc011eec688b4f792046aec1d7709a0bdd07e80be7678a6a3145ed8b674d74de5e06062c7a72b586af9c64993dc9118beeb85ad4db7baf81fb1d8d9015ff614ac74c222b5f51ef0accb1a43e8338e4917d29b6450853d050874c9801a3aee03349e4", "SEC": "041295b0be7356cd80880eeeefeeae4c935cebc450e505fdf13d294734303b6f931edf1481bbd9f521b72833ea5d4f111473ffacff0f3284cb4b23030d70fab193", "TP2": "040872bbb02ec8620e46c31584e8f149ff1709747647c5af6092ee05388a40bc850d12a9b4be4b3feb498d49e8b59a249bb9dd7b9ce75c7b2f15bdfe80e466ae66", "TP1": "0407be899ee57ce53ce6038e130ea2713975f06e76c1f4d1d8a009841986bbea38074de99192845254cc3b5d0cf3b8cc3142cf3b85d66f5f1d95c71a15ef8ffa35", "CS1": "0416e0b21637e1b58014adfc061c2f815d4a62ba33fa43042e9d9e7dac100ae255019e9eda994a00620a098b547880925c08e1467defff7085cd083046b1bc2bec", "CS2": "04212160a152c13b0b7ffd9b084783340abc3ef230e0e260da1159e7008e387ae10a75de1fcf7acaf3759b55d2cd94b1251c61f333d22a92e9e3de2805e6617a3c", "HASH_MPIN_ID_HEX": "44fba9946c555eec7e42545fb29b0d0f0915f9b48dd5bfc3bfda5ae5033f7aa3", "TIME_PERMIT": "040737e503d6298b9da718c9ac0673439b580b4e28165bac64237c55b759a51ac41b855610f6b003898a4b9ea1761eed5a9d3c143269281980281e528abc2f515d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223462326464613639393736316234353130343333346335383364336236633832406365727469766f782e636f6d222c202273616c74223a20226233656138363830613832333636656465363463336333373966643265376566227d", "TOKEN": "0410336ea9e2d854f54c8875609de4a3861010cbd22e03f7557a6effde6fc64788061f3be87e0ce7684f5f75e6d46d72282ad8b54dc50ee18c008afc01b4cd5d2d", "U": "040380962b3f886409680e8706aee7e3f9251bf18e76b5b730ec64cedb9511183202f21ad5319653ce468f034999b08c078bc601de776228e797f280f251d0238f", "SERVER_OUTPUT": 0, "Y": "0893829eace8914262d1075a3b00162eb9f76b3b4e8ee619629dce5b5dc15c56", "X": "10159208f18fd3d16087841146e43eefc98e2da6b3cfaa7ea8598f2ee18a75f9", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"4b2dda699761b45104334c583d3b6c82@certivox.com\", \"salt\": \"b3ea8680a82366ede64c3c379fd2e7ef\"}", "test_no": 40, "UT": "04102690fcb4a6ac969a401bbfc6b47ceb90c23ca359e442a3fcd7b93e46ec97940ce7872281bbe0dfba00f9d2e3bab5e4333edee748bbcffc122d68c369bcb8ac", "MS2": "017ceb3d6e52e40596c7bff315f129aa08e3ab21d268ef860a9d531809f029a6", "MS1": "028b6d45ead8a197487542bb601930d4b2c6e53f88481c7d0e329eb2e2e4917e", "CLIENT_SECRET": "040d8d7a6f7dca5385086bc6094d836d36becd2a2a099c2dc6208130017e4904530082c0a5b782c9c624dcb7b9412ea588eafce0ec536aab9a17ca68b71cd726f4"}, {"TimeValue": 1437055595, "SS1": "07949815ce4517b6c4d167abbb322b03ca26fc6540d67eb13c86500b5e78cf50202a8be7b834e1e39950c9a5fa3d228b53195f65cdcfde5b1094fb288fcca037104b5eebfe9714d13d1301cb97d186b0d1b15d175c19af8aedb7d9141a9231970e8c81ef99ad3efc29c230779a2dde39044568f17cbe453e2cc5d5d30cd2cb8b", "SS2": "20b657d70512f73849b96e75e62a6b2b46687fa8cdcb0369f6ea59ba505118192103ecda8564fa4ea8db0897fcddced4d671969852c7ffcecf58fdca71b4af9d0dba37fc0cbf76d0833d8ebd86ddbb64c60651165047be9c2dfb98018c0aca7d0651bf56b8f6e26ff603f4e6cd7aee9c5fecafb58527bcc0aafcf3eba5e8369e", "DATE": 16632, "PIN2": 3858, "PIN1": 3858, "SERVER_SECRET": "14436b903c7943f7a3125371eae76bb0c1d27112398912b02d5f2a2e39ccd277175fc46ca18bf0e9c1380153b76b9996a49cc5f8cb717b99763a54c74aaaacaa12fb502c3d78704410ad937874d74a7f67110850dc88784521a307ae27e20a690134554ded346418e0339e36c048a2d0eef1fa1c1d14dcf82310153724542075", "SEC": "04185690480db61260283410100c4813d442989b93ee9d6f5b640ea4f4221d31b00dd49f1a711f38408d7b62107e78fd72922f2088cca80b798931a99354c7c4c1", "TP2": "040f9ba5f010d6478f1010cfe3a61c0a98e62ea4bb0d7c1965e98d8bfb0943804001b3503f57df31c1cdec14f160319e45f6c3564ec6dbee293d98ac69ff9f7d8a", "TP1": "0401d15b9f984cdd58f17429c6160a0b7495e3f3531ba07fc77d5a8cfc0b3c04ab08ac717a4dbd44d6a4f31c3e154056255b00986dc69cdf568545b21bc00aaf94", "CS1": "04233d8567d7b5cc0d030fec7c495a728df895369dda9ed87d2b3798a44743ca180dd65c5e695da7a622e4d6cbcefda640b99d533069955c3f5f4a678cdedb3a88", "CS2": "0405d99aa0efa6e6b5ca6ff57c146f358f0030a738012215a9a8cf48994d0c5ad70823adb30b214392dae0614d99db12f2178da7038338ca18ab15a7db6cdf9d49", "HASH_MPIN_ID_HEX": "942e5136eb5cc410bd29503023408fdb9d6ac94bb86d1e42b5e7415ffee69bd9", "TIME_PERMIT": "04018180ccbbf5ea3f0181e57e00be5fddf6c9a2866447253b4450e499b6883d1f1361b8a0c715663fe4f030b370c2d4b7a19ac103602c1f3a3c6735fcee9ff9a6", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226236633639396636336636616164326136353833626232613637633763626235406365727469766f782e636f6d222c202273616c74223a20223236323830303139643666616334643563356433363065616362383036323130227d", "TOKEN": "04181cd4dbb3e5763fc41bbf0df549f61ae475b2cda88c6f7254a61fbaea1aaa1e0401dca7c3939679c926640ba8cf712dc19020ed44460466fe7bee1c9e05eddf", "U": "0404bde0073743f28a77089d67c4d57c19e23922cdcf17007c7455ccab8509198110ea02a020cc27a8e19072ac52b599019ff063ae60dbee3585ed16cddd538907", "SERVER_OUTPUT": 0, "Y": "143e6cea01c6537db9f20c16761e547e69913544b1196e65d05d0edc762b8b4d", "X": "04011571b5c66abfb9968284cc6ffebf3b7d9d6f06b5d570dac7d8016aa10d29", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"b6c699f63f6aad2a6583bb2a67c7cbb5@certivox.com\", \"salt\": \"26280019d6fac4d5c5d360eacb806210\"}", "test_no": 41, "UT": "040f6d2456ea2c96ace4b00a2d15d48c8fad5d8322f9f8d8de0fb2b67b92cdcf3c08cd2e981c7b236651a235370aafb1e261ea7a81c46d4516c645872483230c48", "MS2": "0828454fa97e8043867be4ca09eb6dfd7f3e3524bce0ebb8148aa2fb9b88f97d", "MS1": "15fcd026cb971668537af02582787f95f487b2c09d181cc9198b888d7c617924", "CLIENT_SECRET": "0417ee622a001d3837c4f58a1597beae097e88ad0553b9344d478dd8b3160195a2032d0599febab54c87480a8d3203f47ce532a0f5a9db6516d5fe7683aa1f2021"}, {"TimeValue": 1437055595, "SS1": "0039a25e755654857677f8cadc5efac6f919ce5176952853ac5a601f5b8e920a1b07c589429e83969e8e7ce384ea39eb7a7355e119cfaa45751a61cbc7aef6ff1d4b903fb23d034f3c7e110dee1f1635b999af3c8e8a9769e2e63d919b66212a098901c1309a4e3dd50625fb06b81fcbf7e66eb2aa7b4dfb0ec88341f04dd25b", "SS2": "10d376f3659b74757f9a40573c457e892bb1444f83d7e70d5d0bf696a1c2208b08bdf796f60252bf73d30eb605f79bed865460849de449b0f51f5bf34fefdbf6038fd882f05dc314ba2dfa32ef85353f2858ed07dc2aaa7ca8fa467a217a57200dd33e74e3e0b1ab3d65f59875f6c2d1d82c79ae1e0a2872195aa134745fa4dd", "DATE": 16632, "PIN2": 9718, "PIN1": 9718, "SERVER_SECRET": "163cb63279b2a0ad42cdf63e74e7be832be430c3eb4920b0d8f2f9faec3f7909069bf4d364d6aa60d27469efd51081ea720e6b884c338646975b1773ac2add2d1cf8efd45f014b8cd673abed497cea221df41e1e27734e59fb16fc022cea76cc12a48168d6aba3425747b7f82b144c21c819e4b00e1bf2733181b00c099754c7", "SEC": "040b18de2066a251318413651e24835736e4763fd529189abd21b0f2342f2780c601952edc03d7ca27228785b936ab450776d7f11b47b5c1a30672dda958b02b6b", "TP2": "041bb1139111bf8dafa43dbf515fa3ddb75b34c7086d4f8416314fc66f8c484dc610cd69678861e92642f4a285229d8d1cc8ec97b14400123fe4281dfdbad32b8e", "TP1": "041cfa8a6b41eeac318f9b80379de2df68eded45915e37335e36abdec5e3b27cab231d8a7aff8fa02e6e9c45f4c63979313df47387e7baa500307bfdb9961cba9f", "CS1": "041d103a7acb7a216ec918b220398d915d5b49c8154a02df693d24e1c0f08869ff0fc11e9323aef2347d6c82c7025a93b603ae937b89c7a773068da02519718fe4", "CS2": "0414cad0e6de68f8c10906ef2935b22cdadccb3376af9587afe8fd9f0660dec0001bb931e11d042156ac0e895af3d90c31b3794fe80ed0f5796ccb9e5aa2fb7967", "HASH_MPIN_ID_HEX": "85755d523879077fe77780fa0341166a38e7fd72ddba2deb482156b163c9a9b2", "TIME_PERMIT": "040b65c54e6b0caeb52844ee313ec71e1e78783ecf67f1e71d72dc632174b82e7a171d101f2be5c44f9f6e920d65b05df653c5e585d36c6ee228fe8ebc9a1834e4", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223266363937623433636234336539303731643135666664386133656332616434406365727469766f782e636f6d222c202273616c74223a20226235393064316337663562646161333830643363343033366437313737646631227d", "TOKEN": "0409673c08fe06e22df49187dc94d8299512d2d496fefd83e0d82f41d0d43c786b1e8d56b29eb4feaea6eda738347cff3f62ab55c99d871329c45fafe3321fd34d", "U": "040e0d25a0feeec9b2f0719eca553a6de892e7dcf5c96c1f3f056f2b09065d8c3c01912aadd58975924ec8586c54672fb03b4380b9599ba28112b89d41142c4e04", "SERVER_OUTPUT": 0, "Y": "190a06338e696988240a7729cae04bd20664987605b8b39b5fb35ab024934f1d", "X": "020ea81fbe7d9af7549d17039ed1cd34400f130d089609fabf227e772046988a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"2f697b43cb43e9071d15ffd8a3ec2ad4@certivox.com\", \"salt\": \"b590d1c7f5bdaa380d3c4036d7177df1\"}", "test_no": 42, "UT": "0421e42341617dbc320612f34dcd696346f41774a9bee85c4f38353389468a5b2c1d0d8a526b750157653bf0dde0bf41102f3724dcb271fea331d6fc3a296265be", "MS2": "0e44a1a41b8e6205c180e6da203c7859ae231dba7a175e3f106e40f3a28199bd", "MS1": "036eb5fb8af902d128405084d4f543fb758c01f0d87d712c2dbb238e762c5dcb", "CLIENT_SECRET": "0400ed326d905b35f796b17c67fef8f3582b4a82f60a913f839b17c8e4f2f62f6f0269c2d175e09a1dbe7df4cbb3e2154f8e42a0b67c91cbb038ca2fdddd9cb378"}, {"TimeValue": 1437055595, "SS1": "13d420d9e50cef94b80a6c4ca6a800db93719fd478ded8496e94082b221e3a1303ec48f72af5bbfa54ba73ebc8238cc2f6e903446c269a1b0399b63c1fa176d51b70c5da1ad7c79202bc2a12be8ae46dc3bb771488681357a52bc28758103f0c1788165604b987749ac6f899ff6d3fc1c46d416106457df4a4ae15474d2b34a7", "SS2": "1da2c022eda9530f66e6c85feddcebbdc29b7c84ca107d679bedee0aa08ebb9f08d16490b2e754a51a60d68f42dbb1383f2dce829c0a39b12a5bcc67f56c4ea215872e339f301f1b2d37ef3838382f4779ea51516082f36ed45e2b8d4a3b135e1e7ad3c87faf427634bded904fe4557c9d1f2d1266706274e30c3224700a3fa5", "DATE": 16632, "PIN2": 7476, "PIN1": 7476, "SERVER_SECRET": "16135e7df94696b892d1e9b9d37c53d20963e262c7b895bf9810394a95794c981878b4f190e9259ca8571a378cad9bbfa19fa42bf1960d4e43467c3d5872b53c1b7b49f212c4cf0ed477c072b4e2ad873e10bfd1e4cb6c7fd4971e76376323160d592bd16ce73971b4bba25b11ac101b8db8584a52be6ada07726d3fdfac59e1", "SEC": "042160babdeea0c1aac893a69144577bbc8bc1c0658d76f54f4c9a2ea1782d786e22c33307dec2789be912394950e6c2694afadae15df044eb2814485acbcdb463", "TP2": "0420c9a7149f81a06680eaf0b913c396972ac86f977ad4a7df07aa8c012f4d67ed20f0cc23dd31350222384dd297200d5184cd6220ef88b4dc0cd918022900d50f", "TP1": "04179a0272cd4cad8a5a60408fdb672e9292e57520fbd298f391f4db8d36487abd20987821a2a4995aa25b10077b127165e345374612f99c5fb5b7fcc96f3fff35", "CS1": "0406b6fbef891b9d08d279c40cf87c091dd466d52fd47057c0e197af2771a4e1c91040a484337429b25903161ac0d4af57b5346c7e0afc589ecbf1f9d88861c1b4", "CS2": "0400940d58340a4bf29bd74849c9b18446334a641661c5939875f9a5b6df3c6dd1018f74d94907bf0362f67a1af0995017a1a15da86674c2f9d8f4b91595a451fc", "HASH_MPIN_ID_HEX": "9766ed66ccb2828f2266b08c97eb6f51a9046ec75448697b8e9ef35f851b399d", "TIME_PERMIT": "040e9f4646af87d24ddd45f11681a9c906a93fc84b8fb180008ada4c600c7a3f151045b2c16f170bf87b4cec81a30b0b5c9f21ab28043963fd0f838f476ae2fc8a", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223137643365633633336133643437363236303338343830323763396535396132406365727469766f782e636f6d222c202273616c74223a20226566623134353530643038323630666235303632323530613633333061303363227d", "TOKEN": "0414b172cf69c9b3d8752aa3eeae99edfd534d8fc086fc6e5856c91284154702d20a774911deee2702556ad6d3f372489213aca503f0fa9c3a42fc588b57eb142e", "U": "040974cdba49fd29cbc532b5e2501eabdbc856814bdbd72990b2f055132634615209204b789c4eee562deed3834e7d060d755472efb63a2bfaf736e79d2b60177c", "SERVER_OUTPUT": 0, "Y": "023b8d0c8ae2ddea911f42ff0735b97355c36dadd2f8e2fe7995fe7e952faa2e", "X": "0880160c50fbcce3d99f7778da64800918bae52170912b5104958409a2ab86d6", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"17d3ec633a3d4762603848027c9e59a2@certivox.com\", \"salt\": \"efb14550d08260fb5062250a6330a03c\"}", "test_no": 43, "UT": "04143904983ebaa86ba30740f55bf51c6d3a552369522ac174cc0cc323e04d789901901fc44fc88fc76708534f8063df980729905cd6fe13ca16a23056f1d2486c", "MS2": "083f377284ce6219fcd4418cd31e999929eae1e71f70f7d12b7a9f2880d623fb", "MS1": "02de258563c3af4446bcd64ad3b8c8d8338fed6834ce5cd09542bd9ca4fe95d8", "CLIENT_SECRET": "041ac75378eb6ffc239ede8b9fda0bcc7238c962295486c0e9e4c5ba737df2301f0e54fe7525fe8bbac90fc66ebd5f0f3d06d4be0fff5acc9115ef5ebb2f5facd0"}, {"TimeValue": 1437055595, "SS1": "0ae862263da548d48446aef875ee238450231ab813556eaaa600f999d28768f807b5360cd6a3b04414c97933ea932eb1782ebe8431054d0eb8682da5b07dd90e09fb18e0276a0e155e2d6b8ade70041068555e1a969fb51e3472702e1f512b261aa6fa07ea2e308449979fb79e661046182d16010d84f3f62e3a796c6f2cac32", "SS2": "06cee61c9634b11a41572886a88395c9cebb8b4436672d323ee96e4c5800e73006c9e90b52d6982232287470603a5ed079080b682aafc69e2972eb8eecb9a4bf0ee4fbf785fff38b823e6a3a013095603f08f094218e3eaaa8c5d47a83a112a422633ce96f52c6ea9bebfc23bb3343447d93345e7773787af09b3bcd2fa8345b", "DATE": 16632, "PIN2": 5472, "PIN1": 5472, "SERVER_SECRET": "1fac23962953e0f8a97bab81f655d4ac1518501b693a69b1fe15e32b939ce8e30f678438308c66f565d2331b31d5136405df51606e773761119a52d355aa834d1e53719e33f0e9e29f771089889bb2c6ec3faf110016064929cf1cdfb389f0bf12bf0ce2dc8fc4a18bbfaaed28aadb54dfbacc0cc0edc649337431e8da83dd09", "SEC": "04037ca2bbe6c5ddcbd30db95a66c77d7227807003cf03320820e3386b0a21ba2300c88fe53b77223b90abe7b11ce05f90131cf418a33589d0842ab7f7b9bf8c88", "TP2": "040cefd0c173e094b7d03e2e86dc3f7d33d1601ad40841c0303422de309a19f93b04edf489db58879561e12b6217b8677b970c6fc491366b277ee9e4135521d42e", "TP1": "040f678c19a0f97954f0426cff275ed425fae54d21ea25193f472e47c5fe581b06047b4b8579fc010bf2f4a555d481f055cb05e6cab2ce7fa20e457652e3e4c9c3", "CS1": "0410e704fefff8208ac0a790ecc08a600e5ed8625094496dbbc007a3c847ca47ed15d7d54a850857103ad308ee0f984539456bcfe5096bca871ab04bb2fcb17f6d", "CS2": "0408f5dd770a747a3ba43eee4f91170dfb3dbb43bdaa1fb951fb16ccc78debcb93033a800e64face919a7a8f15a3742f5fd395d53290c77deeb50ddd582dbab51e", "HASH_MPIN_ID_HEX": "6536b8071510419f51fa60e3dc8451a5d73d7def8ed088ac8604916c09278a07", "TIME_PERMIT": "041aa437b723a5be7d0ad9c39f82bfadb9c067d46720cd2575d944f4e354f1b8ae18a834e03758f9bd9debc9ba32def7c6edf4cee7342c4053bb985f8c8474f8a4", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223535386539316162626233353063393039386366326264366262346236646639406365727469766f782e636f6d222c202273616c74223a20223734333531653435626238316664363962333636343334303364353231643537227d", "TOKEN": "041e4a404deb0367d909f996f40a109105ff3c1919f59a0b84e181a2acce00b7e0059c0db40bf50f4e1ffaf88ac81a7f6a377a426bf564b938b5f7a7eee5e0393a", "U": "0406b0c472427c43d842774ee9b8243677b6d590046cd9556a9e6d115ed2632d0d162b8c30ef910c2c7338995e025ee9064d666c98a7decbadd8b91235806b36ba", "SERVER_OUTPUT": 0, "Y": "05203f97565dbc7de088dab8d52d9da9ad59074d16612372e30bb13cb6fdd6fb", "X": "1c3422cfdf9b2435e656580a333ded17cffab506ac7625dc2983b3cb2cae5eed", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"558e91abbb350c9098cf2bd6bb4b6df9@certivox.com\", \"salt\": \"74351e45bb81fd69b36643403d521d57\"}", "test_no": 44, "UT": "04159c68aac959721927854fc6bd46e7cd27db02526b26663c3fae27084ba6ae3e0240c994ed104a4f3ca9b5b96629167137b41cefb833f672c870ea25e9ba553c", "MS2": "170672044b0d70801cef84e96e7c3c0c415476f7d95cb96848e8ba4fab049f4d", "MS1": "0725082dcaeb31a90703b4971c890ccfae359e55db822d2e4020165711a09cc6", "CLIENT_SECRET": "04168474603f85ddd274b68dc5d768d566c8b067a0d5029b338be7314b8e4f484e1b0072aace8d9edce09ac632d5bc25b549667be465c61592bf08e5cc5295a9ac"}, {"TimeValue": 1437055595, "SS1": "032f8cf55108c94d029bdac360146085caa34bff95770ce9bf098daed0aeb006171bf5c0da0cd531a5fdbc67d9990f6a6f75a21c52c7d4802744be6ccb1e46df06038769ba452425e21901d5facafce97f9b04fead1a5e155955244b63f9fc280e3a3548885ed6e42dd77edd962b07e618ef03d0972577c4d19eb8f08c8a6e38", "SS2": "05e6e7e9167aa8414f66b8c13abf62d767a253a68578fff84a2276d166db4e0f1e2955769a15faf85fbbc4c3a1c1943f7a0848b454f55a3719b83b7226b082be00b6f7642d2f81c3a8f6e8f63c9eb5f631b46bb5f8d3f2d08ccbd610595473cd00788a48d63c11bbf5de756e8a1ff20b4423a7845799cca1f57799ef2b5bc0af", "DATE": 16632, "PIN2": 8998, "PIN1": 8998, "SERVER_SECRET": "062a14cedeca1071e528c1ced8c458c88c444c07229fceb796cc157ca10d2930238ee9670bd7a0410e5ad0988dc6efd38404fe2e4e65911e1d5811115f51975e0ef5d3d4b41b0d30a1b0157effc96651c078d21ea571d7cbc94aad0fab0260ab1b0c9015327bb48ff52fd801906dc52c2c7e654964f170047f84be20492da3da", "SEC": "0409e2c21a20da9b22a825a88bee39c9e654c4d4eb848bea54df83e948224a1f2d1dde27a98e723301ca584e37cb8b9cf805b3cd20bbcc4fad556fe0148e270d17", "TP2": "04164afd7b5609bf1d397bc60a3e9cc5719cdb4670857537e8b802aadbeec6ce4d1afe942a1d3d0f82c45683be192a1032704c6f8ec1750ff91ab85361d7b2b2c1", "TP1": "041a2f173a7bccb877d95c849cf34ff3b523957e2fd933f3914989a08713d3f7200f0116d398f62d323c28925ca6f66913d11deeca143586815ea9376f2d5e4990", "CS1": "0407af048941981aa14ca89810aee75bc9901dbbb2c5f02ecaa9c50ae97e75ddd820e279d25a98f7e198191f08f745901d7da0005d345edcc3d699edcab4f79aae", "CS2": "0405161e997206919cdb134d5949365e21c7944176968bac0a25f59fd1e33da61d00e1fce4cf05cb33b10b9659739494e8033673f96642087d458c56a4217c95f1", "HASH_MPIN_ID_HEX": "9704b88c8e4ad153322e38cce677b3559aff9031ddfb69f0b105854b49ae9d6a", "TIME_PERMIT": "040083c13c94365a5102f61c9820959cc95ca01b2c40fe8e936ed775736e21b0730876c19a0f03a571c19f956b4bbee7258e651dcebd04fb98cdac747b0a1404dd", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223431373365653261356438636563643366393039636465346262373565656162406365727469766f782e636f6d222c202273616c74223a20226536363032396465643561383964613234303664386563393438613064633261227d", "TOKEN": "040c7446c3f8c5e70373a5503fd72cbe8a8253f05b853fa1285a80c25528cff5c123279973ae643e503bf475e347b04381667833e0ad88ccd4a9b071bed93d6b6e", "U": "041df809abd5c6b44a47d9527d6dab78403c954de3e3f70d15ad4b7f6805e114701354194527d72d4e758d8040682ed4e3b7561f7f69518f11278618fa682df6b6", "SERVER_OUTPUT": 0, "Y": "086b020649a3086cbe0e27331169ab59c75156ac1a32e376f23db71b6d729878", "X": "13b2ab0476a4d1803608ad26491824f1f53cd6ed2fae6a8d6e2ad84af598d2e2", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"4173ee2a5d8cecd3f909cde4bb75eeab@certivox.com\", \"salt\": \"e66029ded5a89da2406d8ec948a0dc2a\"}", "test_no": 45, "UT": "040bf7c8c41f1b7cfbc15b79c0797d873c9b97a3e0ad5280ffcef3ec52024903211e1d50f88852b3678cb2f1b311f6f7a3ebb5d46ca3890256b10f808380b14d5e", "MS2": "1040a03347171590ecf0ff868bed5a3fa412b1486cbcb44fdac5ff8430f8c93c", "MS1": "1c367ec29745ade8dfc637c27135e85ac6e2dd68fa1c379e5ef65d2cc7ece707", "CLIENT_SECRET": "040a3b3c7c7bf06579fcf797668465d9ae2e65b2aeb290440323910f98a4585b90020792551abfe791b2a7383f6e971122f4e0faa452f6ee9dadde022d27387508"}, {"TimeValue": 1437055595, "SS1": "03e5ac5714d8282be779ad8ef76774ed61f4a7922018bbc3e4049ee7d64f71c302112eefb427cd7c7c0c45b45d923f2d094c5ea70e274671e6d0e05e993575c417989db67a60ff0f56ed7d2d329c353816dc8b0ceb8599c5fb638db09f05a89d197156feb420aa5a14eb322c38355b61a5044b3666e36514ccb36751173e78b1", "SS2": "20acab7c0eb1351fa461337927685d345d354d87bf4dd4ac63a2f03689027d3e040897b5ef6723bb6818ccb7991fdabfb65b564103cf455a299095ece8d69b44025ce42306a5f305bb0511140541d98937e403cb4d1d460dda591a7430030c701fcea14cd0a0302a2d246daa209cd1cb0be1c347e047a76ac29d1b0cd8c4e452", "DATE": 16632, "PIN2": 1684, "PIN1": 1684, "SERVER_SECRET": "01cf8f57e0bc0c54e8195ac56cfdfc83e27bfd12ed2432de8cbed55f7d27f6a309060cced85dc107b0d6d6fc2108d13b94a4407a2a24794dd68112ac7d24146d21070fe086eb9ef858007ec53a9f472433d76eaa07c7cf43ae302cfd7cdfbe930929713e7b9a547cd005e9b79cb9666b0d299ec1adb1d567ecbc21ef02886b00", "SEC": "0411a5a60b0b29825bc0f4af9a40dfd44c7fd8d1f72409996796c19568ebb1358d0cafccc656e61048d0be5b63a1e007ed92ce1582763893309d15837ff7f925b4", "TP2": "0413b279b7195ed503f666a54e11badb31c0c9e91f86b7033c1330412f7d907d3104c40a3374275b6de97597330ce9b08d640b2d15984df1680543c55210fe96da", "TP1": "0408bb9314c4c539245b224b12652d95433593dba9c7caabc586ae51aa4362670a0ba65f7eea1d5160accc0652d60592e7e0045bc7434eb3972bd3ac54dc1f9eaf", "CS1": "04189d2bbb060cdbd9618ffac4f5bbf32d87b972081c9ab57780e7a0c6f68567fc10bdf8b4517791be121263c07c6771a10fb3f09bc6c3592f7fd8e35fe8092346", "CS2": "041fa15482880ab3f78d4c1b339ab842fb3b5d03b49441c47d7f6d11453c8b15fa054b19de45399aedc22ed62a85c00565bda0e1d33641a8cd8158253d9c59e5c7", "HASH_MPIN_ID_HEX": "b316b9c1f804a58e3584cb5e36d40a6d578366cfe574d527af2967e1b7d9c869", "TIME_PERMIT": "040cb66b7e879c0187905d547033a745170eeb9788d8312c623091cd6183b36f49103fff3c1d8f0c4bdddef17f500863f6ef43ac12f411667b2423a0cf93992a6b", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226639666262353536353433316234653630346237353334666663333938383738406365727469766f782e636f6d222c202273616c74223a20223962636133376437383733396165373666643765383766383931323432383262227d", "TOKEN": "041f4b6b8c3211b81f678a8e812ebee1b3cfe02c901d77123ab8f22dcee545cd1e01c4d100c17a6b3cdc69756bde421a723011fffa1ee74dd9804ff656e1719482", "U": "041a7736f724a601bec8919e9b6421971649f458bc9ac62dcaf64c1cb06f1435121f2dfa5ce02c7d5c3a6f8b4f578a19e05d220fc0f835566ba51569e95720b7f7", "SERVER_OUTPUT": 0, "Y": "2306c0a87e331b6fddd1729356a2aa74df004ad20ccd582c4a19c2a5b5fcad9a", "X": "0c02f5300afe5d434d0e32b55bb2137cdfe131114e1556df06b71c5a87c63298", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"f9fbb5565431b4e604b7534ffc398878@certivox.com\", \"salt\": \"9bca37d78739ae76fd7e87f89124282b\"}", "test_no": 46, "UT": "04131f7585fc79c96edec4198e8bb317d54cdf208c206dc2f0970df7b0b320e62d03afb38a499d74c1e0015f95bc0c08dfc9d31facb2d52f9f780b746a1ef0235c", "MS2": "0bcd282f92719497c0413ecb53e58b0ea4a2c0be7cf63b8eb2f3c7ee61c5dee7", "MS1": "1897daae656d585f48e744e21432b8325ff57c31e256805cf95eb26d9550b6e7", "CLIENT_SECRET": "041d4c5a523b7f6e257bbf4f344bc71584ad8601e3dafb07a2c3d19665c75dc7df19d21569d60a4e116bf13548ded66d56dc5b4634ae312819544fd39715734b20"}, {"TimeValue": 1437055595, "SS1": "1ce8383fb3ca3ce06b5fd482a0d5ff94c9b632def612db3059b3ef2c9ad8c9771a086216e00bcaff130fba408a936891e9ac3c4028ee83ad2d8b3f1c775b35660b50451e75c4b950d325a19503203709779f92e113b33660c6a7dae69d073cc700e9043bb2013e9707ae9983e10e651fbca26d23a928c0b4096d2af54d733dd9", "SS2": "0114f194ac4b3394ff3da25789fea0176a86e41c89d7f187e2db6549fb2f7a390481f6e1e736602f1cc6b9fc2861dec1528f3ef4c6a59729f5e018db3ed9848c1e6ceb3cfd6973d54e8e124e03279c59173d21acaa477c60dd87af98421dc7dc016f74bb5e188eb70c2e24990b6b251ce11b67cbf150cfc20328b7945d14e9b5", "DATE": 16632, "PIN2": 7965, "PIN1": 7965, "SERVER_SECRET": "0a13af573b31d38189e03c4742f40d0679c04826015cdf54689aa6d04701111b08c3cf8253baec42840c903198f58b85286026830fa8ee7178ac12fa988b93df1802701e96c4253e1df08036f807b6d0098f290e810d084807bbb1e4d0673cdc13fe9d773bebee8e5967e8622d27a51921166389fc751af21c4a50f25ad98fb9", "SEC": "0404037dcf879769608a4b6272f2f87efdceaa7816089b5f02e660946352ea746f07daacd5396fa6a9695e6b969aa879c4d80438470fdcdb53ca67f345ac574e25", "TP2": "0400a5bd25c83bbf7489a12ca17a967d0ba2f0201b5687c9c704f24a8cdd4d63a10040eab090a27c20dfc1517fe0e23661550787df7280e65e53291c9d32b345b2", "TP1": "041f18a100ede0307dc3391ef5ba05ad3884dc26c2396ca99a3d1ec795364464540c8a83cd174ffae220afefc10ed8ac1b4126961e63efe49522cf2c9ac7c622bc", "CS1": "0415d83088bcd108903af26d8c05d1d948a6ba45eb05db697121044767bb6e31ca23cf634d67fb0b0b9a0419fac022147542384d6243bba38eb26c7a2fe905d539", "CS2": "040594ea3d4f78b70e2cdfeb612b1af6ab483d5fd52dc7d84ca024816f3e9f5ffe06f15c2de7662a99c8b0fae0306f02fb4e93d417fade52cf738f05c5d9f5da1c", "HASH_MPIN_ID_HEX": "55acc93ce106b09564b138e81a177d1c7e2fb4c06febe5dea18189aeaefb41f3", "TIME_PERMIT": "040f46bcffde073c8f6fde8acf90deb8c60ce6bc1766321a3f02582810a8a0cd500eab991d265a3e7aecef906adb672c2a8541096e611a2b1d5eb7706e7f3e1277", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223964363734353933336235646132363061306535643635396637336532356132406365727469766f782e636f6d222c202273616c74223a20226634636365623035386534643131376561346330633839313364643039643533227d", "TOKEN": "040b25e56f4592d80a52835ca48faeebbe0669eede0abf0e84ad63e4a2c7ad95ff1d7f37592c102179cecd0a81d224f40c4ce2ce82f074cbc41e0367fa59b31a8d", "U": "041657b685ef4afee91c08a3ec952810f8b9a428bf5e87908669bff5e8d287adf0068d38248999366922ef66d06fe836378d44d20d17abf7dbe41b6ecf9376708c", "SERVER_OUTPUT": 0, "Y": "014445a26b30ce7944283865448306aa6b8ad890a60d14794fb72df2cb1f0607", "X": "0c3227b629dc9d8d3e70f36e5f7e80d68787845d86ce477bc629fa6a1fd90a3a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"9d6745933b5da260a0e5d659f73e25a2@certivox.com\", \"salt\": \"f4cceb058e4d117ea4c0c8913dd09d53\"}", "test_no": 47, "UT": "0420d354cd04f946660a61db3dc33013690737ff73307a5964080bc0c37aa26a7e1a674adc4d87cb1737ba5b4e92d66fd9fec6a389691b997821a6051a2b92fa49", "MS2": "044b3c287c8e1824380d7c996414de31d922cf3c7580bc4354a9a136d1e31658", "MS1": "1862505f3ab5a70224ad9cd370632bcc2001983b6d83083e423adc8e5b6a9a81", "CLIENT_SECRET": "041190cccc5315498827157c590fdd9fd0d2e9ccf3987e243ec2b411dfc4defab91c0a734a686980debdb7d00d03662fd08e470837075302951c5a4d84ffb7f64d"}, {"TimeValue": 1437055595, "SS1": "1a0e52a95392b15cdc2cc9ea9bb858a014d9993d11b62d9558e93fc8a9bea54404468987ea2e4dbc1bc76c40ab2e617c8ca82bd573acc8debe1583fc86664d361828f75ca5573038b3183d74a1c89193ac828574b5d2a3f5db15e51dc49c69a210183b7c864ae5a16ce33086c35f41089122b5777fb75a3b0612974393a92daa", "SS2": "095171d320e7911433074cf869f4ec519f48b3416ef01ef519b30b42baa0157519f9a3909c86cb81e436e7529b0d12a66ff0105635d0a460a8c5552f36d44ade073f5febc149d8edc28e71b59097b1ccd9189c95281a6dde19b90b4dec205a001ed0568e10f54558667ec67afef3b251464ec0abc5f69f1c2faf5ec313cb54d5", "DATE": 16632, "PIN2": 818, "PIN1": 818, "SERVER_SECRET": "149293b7561374255d19109dd9aec44ca225c8975063ad0128dbcb8fcc000df5193934180b42dc17c012d7e8c4f893872a35533799080c8b6ed837a8380de1fd040cf69bf3407849684e23c821a3a139f83883adcf24ce462c82da41bc3010581b6d938f98315582d33a9e16794cc2f5741803d1ffc94e83f993730842e91764", "SEC": "041f1a7af8cf6605c1e22f17eb390199e41b0a3b90fd3aefa83a6807ed8b68fa31083d33d322344e7b0000c9578938112e70ce5fb3331d3d6680a59517daceabbc", "TP2": "04021b33bacd24f826d4c8ee8cf95736060e429d51fb753be1a08533c73089bbd716bbaaea921eb5adfbd3f91b6750188111a57f2027ff4c73f7327f5b7d575432", "TP1": "040cac9c79536b844864d04853b3e3f7ac8c6095f9b208a4f378f60671577b3e0d1d36d0c5d88f592a24b92270f9e4a85308f6ca17f20a20a085573bca951be1ad", "CS1": "041f2b955568ba48f5d72022a3d0f23f9f69bf08169cafb841583f689f8ad99df31427dd7e687453550a58d246ffe6c754eb00c2e40475f4bf3cd9e88249adf439", "CS2": "041f06649b2b2fb0f3bc430f58b72460484fbdd5e489d2fc40aa62041b4aab6cdb17d7b6448c6e9cecb96e35c07dce4a395ccd51a7ce7b8c526aac174193125e57", "HASH_MPIN_ID_HEX": "d7fb1932b4a44d1d449611a2b3862d36abc01a196fdd6989aa4661e5abb503b5", "TIME_PERMIT": "04195a58ed3b0291f4645f250d7355cabd2586b1a1e387e1a05194fbf69c0676821257e73cb2b66a55f47777af2ce3626393b6755b536595cedbac413b71c362f9", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226366626535356239653938666130613336636161626233333531666562373563406365727469766f782e636f6d222c202273616c74223a20226165363331373862306561383937363930336531613835396330613663363035227d", "TOKEN": "041e9fe5fd9a4927ed2e4df4a1d6c7dd121bb26a0070b4f16c98c094075315122523deaf9e65e7a866c9de8fe454d1c1e5ffc3c1404d155ea69fffcbe4c49ada46", "U": "041744b3dc824e434a2ad4d9973134ed2ef8e18e543db9c82ca7a124b8c25f1e6c23b8148e140156933599bf9a8905db3e256610ff943a2465048f541d6a7a68b7", "SERVER_OUTPUT": 0, "Y": "07baaccd9d1dba7eba8fc30159eb49a43014975c5def13fcf07f74ae383d3d39", "X": "1b18c30b259bd2c3928e8dfbef0c2d17ecfe160f39fff0bf25e2504949f90e33", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"cfbe55b9e98fa0a36caabb3351feb75c@certivox.com\", \"salt\": \"ae63178b0ea8976903e1a859c0a6c605\"}", "test_no": 48, "UT": "0416217874dfe7496c70e262c32d9e93a0c448783f1756dbd6c787f2346102a00c0f0f5f6131c653857aa3b92b50fbe68dafd626b10c7fcadb551c97ec735d4895", "MS2": "1d1c9c515fd2a8d50ebb5c20d50c2974e8a7d2c52745ab29e405e5fcb28ab43e", "MS1": "129e361aeec89eb9517ac4c9c6f4fc12572ed2d05b1b7f16e8ed9560c1ec8bc1", "CLIENT_SECRET": "042343b8484bdd7af78a29cb139ba48a992ee8b9d8e16e5ba0c8291a77a8c9624b1bbbcc421fb5ba352baf21eddeef5b6f1ba99b0d4043967e61daf779e1c43b4d"}, {"TimeValue": 1437055595, "SS1": "1b0ac502abcc81c126be1ed026b7c016eb740a3e53edab553767c4d555abb60c185ed41f61008d5e1bd5d973130accd453cc4b38fad451fa28c5739fdd4ce52d01b6fbbdef572dcbd0a77e7772d1a086fd8ea858a0e095af9aed55faed0e5d6c0722a0669a43ae484795fb4d8eae82099e7753384d2131b49f1c85780cf96741", "SS2": "1c5caeb7bb7c1af5613047b5223ed68164741e850fc5395ce4b42c1611faa03009e7fce3786e02271c8383d939508722cfbeb6166f3fb09d0e4d362ddf83c0a8169e600a833055aaa2d45f04f3124aa10b5e9e6454b8fcd342cf684c7e4d550a23d9acc1cb721c451ebdcee7f2ac980114a848df96d8f125a314e771bbd6c295", "DATE": 16632, "PIN2": 4568, "PIN1": 4568, "SERVER_SECRET": "0f39734b764e7ec283d7f609d32a673d1dd864876b11259e72d312c3c226cf01233976289b7d7a8258e289f2d79fb205068d88195a14a198249eb89954a39063023db885d9dbc91f4dffb66ab5481adc6348485cee1ed66e87e7e1854f9f747100f7c9a8cd83e1d08b5b6b7cd93663164cd977633f1e850bf2cb56883bf0d7c4", "SEC": "041e6518054514eecef0efdd41c4c07d1195a24788212f4b16e785063c0e9c375d0d007bae09cb36ab5f4461a19c42f92d0523e1a9b631468b63ddaa74a790ff1a", "TP2": "040c33d3a623e85036ec9b3053aaba431eb18bce32f1d26ad1b47237d83c707da61abdb09cf2a18e02a0d6fdff1aad09e97410e890ab6dddc57e5e0381f0bd1a3f", "TP1": "041ed9ec574d158cddd97c6d814bb22990dc4a8f2966160efd73ae5c282012163204b65fb12b90daaf66290a1ee7b53729f02b1c995c419e057d6d829541330a54", "CS1": "04054bc714a093870c3920f41e8034dba3c8c429acbc390f571a84f834ed522c0d0539547088848720f60039491652c981579713dd2c866acbdd2f5f73dda31247", "CS2": "041864957d7b32f01f29f85af3cf065ac127c98359817d930a59f1fd62fc820ecf0ebb93194d971d7c743944c352bb9bbabb469a39b969dbc1447c84631de043a9", "HASH_MPIN_ID_HEX": "f1d230636993995c75c7b8a5ab566bec6a1d803816d607a403f7f09d4887b3fb", "TIME_PERMIT": "0414a05f284cb6b1004c14622821676edafee00a00009053ed233423ccc65778a20f62c615199523e8bd3bfca1a1f48a6a90a7b232de70cd6840094da7e55cab50", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226335643132653464616636303535356632373462653634346164626333353766406365727469766f782e636f6d222c202273616c74223a20226463313737393935363565663236313037313837613865303966353237383931227d", "TOKEN": "0421fcf94d8ef882726c93f2b3bf9d53221008e1ca9f2e66b10a7eb982a9f156711cdf4108024a6d275ebf925ba8811237635e587d80ac624e7d02f976b3cdff82", "U": "040e0aaf19add42cf022a7ac8fa7b222d787e6780088b9f5f7d70adf18fa8603fa196010235e340d0c76aa4a5be3c716b7c4feb04e39cb0f24b7d5e5c664adec13", "SERVER_OUTPUT": 0, "Y": "09f477ed3614a9bd3fdc9d8b4a73d954b797be01bb6537cee9f2de6170d9834b", "X": "079f5bef37f2db027bc95da9e7362b5d87061eb8c6e984f132dd2fbba4db8aed", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"c5d12e4daf60555f274be644adbc357f@certivox.com\", \"salt\": \"dc17799565ef26107187a8e09f527891\"}", "test_no": 49, "UT": "0403dc5a148843af36d0104ebad867c83732173ffac94666e9f2ab7f49c1a1d057056f828a7b29422722c74718cc24db43f2ff475120cdcdb6ce91e0e7c0397954", "MS2": "1891f0a7aad7e461819a2c32c5118b5e2da7d28e58874486019a361fe4df449d", "MS1": "14cab478a56794a1a18538ab375f36960f356fbf3d9550e4ce29dbd557ffc4ae", "CLIENT_SECRET": "040fd394e12e1b9e5d8701fc7f8dd4f125f877ba0d13f453c037bcde91062b2d5618f49850da75b9ba0420637b931a22cac6d5018229b39e1de0e91ce4adc19d93"}, {"TimeValue": 1437055595, "SS1": "0cac071b74d2229562693d0ef827ea972b4ec38ad3245c4aed23afa72cea2062222b2f9536a679721b2b6f1ec56fddc90413acaeb9d544ed5f1eb4c3e4fef5670d9257b136a0c8c932617d306fe163019a018b2f7a4103d064911abdc8b57b720a5006a894f5c649d8bcaafb89ae82d73be554c683471c0106418f95062f4c42", "SS2": "0b352a81eb839c0b55f2674ff4ea1668508304fe71152826077978b98e1d4c5e05b7f32a1a4809bccc3c910e15077a644fca90a9d0f7f72e249380f3051904ac10b2b35a2ddccb973865de31c838facac04a9eac318458f5195026c52268f75f1c898e1d44acbdd1cec893b09740abda310211b569dc01099634ee1d23a4a695", "DATE": 16632, "PIN2": 4107, "PIN1": 4107, "SERVER_SECRET": "14f10c9228d16402414af8da911514c7df22a57ee6702f0636dee869de51d1b21a1b8ffba3b7c5f6a31379a16f2bf8b8302779cfe8550096821c26ad048314bd0b10d83923a322317d41e12ba1099c0702a8f2bc2944d19e423e335fbe0cf76b065719399a18ab6eaa909ddfa8a15d1e4c01d424293351c6dc7d245350bdf1df", "SEC": "041ce3d0fb890d10fd609041469ea9d1e59ab40513a9e7c5ce017349dde20a7c021d352840994ace6ccf929c121a5889609038c7192ab33fe205f8fbb12f84c439", "TP2": "04134823427268b9ebe717d7ca3b658aeea06c9b8f43a894e8c825c72641a8575d01fd0e9b9457e7b728fdb2d57ae9f4bdccd5045172b292b6b998696bebfdc355", "TP1": "0406baae61ed9e843ea13aa8f103ff71cf1e538dad6b378297f68f1f1081945096123df9319e51b8b3a7d562537d931e3191fba09a3558a784320b3fdc13553a22", "CS1": "040436370b23bdff9e3e2eddc365bbbfcaab7c9b0c9025c478f2fec3a1ce9b5f370570eedba49d5508e1d4268e861aad2add3d5d1a5611c7c49e050dce048904cd", "CS2": "041ee27413033c067f12313e56cb62f8e3e7dca147dce6074b3809fe9b7ed97500106f245557b964e6889af8eac176175f3e9856e45b7858fe9f9a28ed2431a9e1", "HASH_MPIN_ID_HEX": "a04afc5f5c7c11008c049de884aff802f491331cf7cb2a9b3f638cfe452d4b32", "TIME_PERMIT": "0415ce24c50fa7c8fc3bb7891ba65dc3b24c52134e1479484e6fc92ff0922ea8191c962c094154dfac263ffb2de60c743026cef929a071f444134ef9506391f87f", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223830633938666132633061396138623764363733346639663964376235313131406365727469766f782e636f6d222c202273616c74223a20223338373266383666643431376438396634623933323261393965366361623232227d", "TOKEN": "0416bf9169519ab90e0fad9aa8efa507feb6194042df19941b70e83794014afb13091451121ba423508d89376127248cc35d68091213907d8f819fa0d9f9244aed", "U": "04238a9d75f9fd65163072dfbbf26447e3405bd7f183cc7bfc387e8a40815d8a7a1906264346f748a31c348ecee991a65523c9f80d3a27f8e652ff86d68a2e5101", "SERVER_OUTPUT": 0, "Y": "13a6838d2aa6b257a3313b49331b62c9523d27f6d34bcf42b9eaabd56542f8d5", "X": "1cd9a541a4949ef144a7bd29a83c15344e5c49b01a8689b3c30cc4cfa3911302", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"80c98fa2c0a9a8b7d6734f9f9d7b5111@certivox.com\", \"salt\": \"3872f86fd417d89f4b9322a99e6cab22\"}", "test_no": 50, "UT": "040a08edf00b2cf1100b82687fba579de09985572b0b57a51a9e93e4d9d74ac003059323bfdac5fb1b58b1d1d90d469fb1f04880340fa927397bdd9d892fb2fd88", "MS2": "1b4a74867e904b1b8268e858a5a756e2cc94ccafa6bb07ff0d067a84f5e71944", "MS1": "0d76fd99fabc1cc0be493231628884709aa32fdf228b22c318baf65bd27a02a2", "CLIENT_SECRET": "040a559ec4dd7f9a415faa953a384bca55a4a2b0b011bfd97ec73fe0527cdc15e4024504ca9dcddece61d6d5f879c6d02c90fe55abe91301af75da83fbde4922fa"}, {"TimeValue": 1437055595, "SS1": "08af7251b54d5d1840cea9e906d130e32c33f2d3c86b9e96904130852a6f232e07ea57f0a6ae89e65511672c1929ae9fba84c6e3f148291f13454cc5f7405c89232e96e15f2bf47f6ce3786ce2d3fd6971923e78c017de7cbc88c20a371ea7f1122ffb5aea14803a58bd503b07c83478b5806c05295135fc36d93c844ff0c070", "SS2": "043775fef84f691d4ffa6f7b8ee3e1a7f5fe41641edee5eee10a68f890969fdf160c321227e937811e1a1c26c0664eafb3bdb078a7d9ab02887d53119926c8ae01d2a86600ce61ed8545215e30138c82eecc325950c14568d4baed4dd7f1d2a50616e9ed2dd225855dd65264be85c7731cb91031054a76ae8a2ee1c9bac4c74e", "DATE": 16632, "PIN2": 1886, "PIN1": 1886, "SERVER_SECRET": "1c92ccac62910b9e9fd04cd32391ab180dd5126ba9dc3db9610cc202ee861e720cb88d7a71ac15428f64b5c989d56f10ae34190a5a4a4539649d6a99098a2bb1149f2e6ae96bb262df633271f121ae6b07fb8e097819a3eee340105f7311775910de16e550c926c7411f96168e3c817993ab7a78486f520d0240a8e42a639d67", "SEC": "041b37902a5711600ec78adfce99bbef67106f9381411d48486eb0bd76ea3fbd3d004808fa529efff9f9fe5ecab3b61e7788bca07f56f2030310a31a2cf3244f33", "TP2": "04037106d93e1bd6dc4d8a090fddbdeeed92a22a3588a25d18297b315aa209630e1c241b559c89f98cda1ff005a1bf650ea646e11fbc081a7958f7e7e447f3ef08", "TP1": "0423291acbae5a556ad5ab167644247423792418e2640f8111678dc1671c8bb20f1a5491a8d4f354db52d4f966171f7615e8f623cf7be474ebda2b748706c28db5", "CS1": "0411e285f373975d312042c79230b4a44769ed197db4003cbb91fd957a75e6eacf04667789439d4aeebfe6f6291a56a483ad402e3becbf8ea246d842c00400a3f6", "CS2": "04149745a63eddb34851387fcb06af0e0de6d025b7ec23dd1c288c698830417baf22f37c4f16eb2a8e0530e6af61b5f2c21b41961d9f96475ed5f8c228c295d1ee", "HASH_MPIN_ID_HEX": "c5e6887bd897c93a6cf9829c3319de4e0eea7ec57bd1be2ddb3347bf33638514", "TIME_PERMIT": "04084b46151faa4e0305458d38e0ddd0b9bb97b09026b70f0ccc29f77d8bb0ad621381b05b06b0499d46216a06c2f2f3c72363de02e4ddf76208227f24d18e128b", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226132393331323437303831333663353534303635303562336361666663343864406365727469766f782e636f6d222c202273616c74223a20223262376666356332626630666338646365393134653538363961356239376563227d", "TOKEN": "041358cbf3fec42d9d00290f0829be551d765d4c0bb14e69d36a89f3b59250d1370a753bfa5a60cfd6a84703f6aefa7c93ee516a6c6c64a5f46ecc4e60ed691f9d", "U": "0419bc78eb5bb24fbda8039aa6a686ccf2dede3d101cc1ac10d4891baf72d025ea1ffb24af1b80d5cdf586ed695a6613cdb8506465c692c0ffb00c595a1d89c7d4", "SERVER_OUTPUT": 0, "Y": "12f2e88db93071703ef15c080e49aee43eaff24e68773b256f02a7c90ab05a0a", "X": "112dddbc2b25a48a74e6a3c12873b36a0df042ecce50eb3949a8bd124b73d4d8", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"a293124708136c55406505b3caffc48d@certivox.com\", \"salt\": \"2b7ff5c2bf0fc8dce914e5869a5b97ec\"}", "test_no": 51, "UT": "04154e0be07ac17fb2a693775aa589b782e21b2d6b86b6957c97920242b37558f204abb24cb0050b1378a87baef155e48ca58e87ab9c5ea5d2275b6fadecba2b02", "MS2": "204475e335f1fe8605244a4e580f9e0a7ddd18a04f7fc153bd0c757212452558", "MS1": "1ea50b08750853f6e6fc739e66c8c54ef311da1904d7c4d559384c2967fd2694", "CLIENT_SECRET": "0402b0648bb15fc96987a0c759f5a2dcec6c29a4b4215316cc9ea1400b54d2e87707c99b425040a473acac66535f6bbe4f98fc9fc048c828312efca0b6a40ceab8"}, {"TimeValue": 1437055595, "SS1": "1a24cd2399446f18fcf21c5c75a221645d2f20934678c71fbbc2d35c69440dc11bb5b2636214222977b54ad9aca2b995dd9638c46fa6b04c906add2b63ab051814e486a7ee5a7ef3971b709011973b0367f2de9e3195b3d5da4404f5928e0e3b1db1ebd101f850aadc9fcf2b0d3fc9af0578b760544337db3106da72d527b256", "SS2": "07bf3aa287eaa5e286f883af1aac9308506cdd66dd0cd6b59afaacfcd9b62a430ba5f98322f6b67cdc70db9f1ac93b60320aec3de9470ea4fd16b955100cd8fc14b8e0880e5b6b305227b20647d60e8a24d8546bfa3624d0c974445ec46af277048870a5462a43f23cc5c228ad94c3f7a71cec0d2cad0c205a0733af7847e9c3", "DATE": 16632, "PIN2": 392, "PIN1": 392, "SERVER_SECRET": "141029971c1a7e430995c56fbcc0a6d66374f6078264e8511242c1f2550c211213da720d64a360e4d18870096b26de324d7c57e3aed277c549948a1cad60ca0202a2e7163ebf9dc8f7edb7aa07131305068d01a939058b6f357b2770bd062b70000cba4f171de13c741e84775ee0bfad8306c69fa8bc3428082acd1aa069bf6f", "SEC": "041b87b699db67bf35bd2f7e0690192faa8c9d5cfa0fcd5ce197ef8e6f5183911d16256ec71d50255a4ad4a7661f87579999096fc5734230f9baf05b03be2a4375", "TP2": "040d67081f86532a1276f9e3b774a4e20a39f22a1c293902e3f52e99f23f5f04db028eb68eb9637c73698f337ebb4082adda54ef69e3ad0b00e9971f9cee01c948", "TP1": "0412f160ae416da66967678f90f40f841c5d12d4735e2afcb5aa1dfcaafc74680616b9c52594d27085a8cec758fcc9f102a4e95afcb8efe4912d18633563adf517", "CS1": "0421910edf7e943d5ec57e64e99bcd5cbcf6ffb308e5beb42c495becbb1834e5191fd0707b86dba79400ea333dcd51cdb0dafb69f6c514ca7cd2f864d20e65aeb6", "CS2": "040a1e1bb05e0bed9cf78274e696b7fec949fb3022b8092ecff46cc78789df82a11f04f9635ff33603c2939ac78c20f4f393bb2a947de5e2ddbff1c7a08b3c5d4c", "HASH_MPIN_ID_HEX": "df8811395b874dcf274140d9315aadf622f153cac743e642a648592b6ee118be", "TIME_PERMIT": "042327712e188929196c74c6725dadcb6afba3f60b6319c6f223fabfc7f52b267511596f9adbaf82e02da98222adec5db8436a0e078ade02be9bab5a3e6f9ff2b7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223438346664653565333139343839393330363439613266366161656330653234406365727469766f782e636f6d222c202273616c74223a20226563633062323333366339646564626331613634633866303165303137363561227d", "TOKEN": "0401d24a64c68e5b954191c6b00fced59366c5eb0694a7f680c67e462815653d2e0a30932d9d3425811f635720fa8c6c4d4369922b903f05dbb20edce5040015f4", "U": "04151c56dec6b4135ace2676c7ab0940e8bfa7086f41b71572d7193e70852934c90047644e52e721348c0ca0a867664b16c92c55e62c728aeb75948fae030e11ac", "SERVER_OUTPUT": 0, "Y": "00ace6f2fbae88dede2823e0945f777896f26c01d01d96a2d88357476d142759", "X": "031f9a25687201ee4d1303900b603faae4fef3d7bf7c306ac92e9d76cd141eec", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"484fde5e319489930649a2f6aaec0e24@certivox.com\", \"salt\": \"ecc0b2336c9dedbc1a64c8f01e01765a\"}", "test_no": 52, "UT": "04113c79936bfabf5623a983c11ba27d981d6ef28b485220531eb9a402e84cd72f0fcf2cc65b6c94201594e9e37e03613e314e558c4adcb16917ef98fc58179ce7", "MS2": "214549067652ffff2bbb24831b2e5bbd4e55ba32052f00ffadb014914c66d6f0", "MS1": "216ed7042c90704b4cb0a66780917dbf25dbea6f679988cc050b3b58804eb691", "CLIENT_SECRET": "04125a6757618a220a3d9e07b31eb549b72b9bf4a5b4576f690a8b72f9fe1252760c2d68718a423f8cc648c65a1128a74a2dc7ddff580e2dea3abd14162552ba6e"}, {"TimeValue": 1437055595, "SS1": "0794aff04b6901013d7bdba94c0f84fb76357d54a90ce7333d9e77b5050d7d5608ac8d3f9571c8d09891af7dab5e2142b3d1f8a052da13e4b1951416af825bb70cd5dfd431c345e7b1535537b061b0ded3ef2dc7fccbdca5aa504e41f315e0e21052134a91f35dfd7b832a69f1a40d765e563b1ec4549de388be58607ce493dc", "SS2": "2050f1cc96d297e16582d56569bc7173b857c94d0c7fda7e41ca4e31d747c072201b1ea61ae645114974d2fcdd182ff4abf6b01c78ee760b63896b7d7f2e178023e4cb2a3909a54d49cdad0b0e16aa95cd7ed4f2ae967b4d4dc0fc4d71789a7e1f8cab3518784a6669418eb3a91635d993bc77dc7f362b67398a566a48323017", "DATE": 16632, "PIN2": 9044, "PIN1": 9044, "SERVER_SECRET": "0244ba8ba6dc67a32c1f9048fdb327dde3bbce4a82d04d823cdb642db460555317f605920647a9b7cd5bca996cf339743ad8c1ba3f84f5f38aea15d6454fa69005ffde0c2a4005543383314bfa5599fb871246101307c74d2c042cbe971fee2323bd21535f0482b1235b79e19c98183f48cb4fc7a2a033ad703f200b7c37ff64", "SEC": "040e51f2328285d0b7a317f25f4ae11c47e6eb5dac55003476d4263d1a0e17a19520f01eec130b45ad382e7edf990ef13b60486ac94341cb5e078994b138688c39", "TP2": "041aacc6a99dbf8575874c7f44f0871ee1d4b2354e5a1c2404740f40e82f45dd351a9a5eaaded95f064aaca3f58516b11f319afee9646135d75bf4b6840ff80b9b", "TP1": "0415fe9c82a0e0b5978cd90f833af4ef4a773848ce4d481693ea320eb90e902b6f1e385ffddae6ed79fd9e2dcf9fabf03d9b1bca659f30a735094d8c7bc95635b6", "CS1": "04226aa253b54ac0ab9947a06a7c72d80ee615ab94caeed7b69d0e95ba341b178d182f047a46322ea1346b1410dac8534278bcd3cce46b99175edecf012c00d500", "CS2": "0403c9a8e09da0721e975ff94f0e581c7c5bcabac215f6fd7530162be8b3348e371bcde0556452e0bfecf00eeb507da9309f9e146cb989a6a087ecdd50888b1314", "HASH_MPIN_ID_HEX": "7650f0772c444ff29cdb509a23025ef095671e3a11bbcb67359a657da6e32588", "TIME_PERMIT": "0419789998e7baa955dab60fbebaf25701caaaf3be8805613fdcd17845a0411c2214efbeb301175222bb9da0fa1bef1cc9198d70fa100ae9f42ead51e1a1dc8810", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223735313737356163663634383264326464393763366561326364343537666465406365727469766f782e636f6d222c202273616c74223a20223034636635633063366237613931623161376531666662623565643030306436227d", "TOKEN": "040f42e7d223e353264540de31fed544c643ac65421e3ea2635563fcaf3b72f8c8150d6225550e449eaf06ccaddb0495e3d65af026ed752e3c0077f8cff0776d60", "U": "040732bf77497fa903b34e7486f69f0bb8baea67e768f747780b0f960d494044601d47020d112dcd663463612f72e63a13d8e09a5d41ffdc75dd887a1b9843a66a", "SERVER_OUTPUT": 0, "Y": "1343042a356f8af60f18864609534d51ab785443c2b9f62242d0df9e2169e1cb", "X": "190f88100da62eaba80e55726b505018df1f4047a81775a9ef16c7951755d758", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"751775acf6482d2dd97c6ea2cd457fde@certivox.com\", \"salt\": \"04cf5c0c6b7a91b1a7e1ffbb5ed000d6\"}", "test_no": 53, "UT": "040f9b48b5ad159ad7716d24b297fd5dea405ccc2a7c51df68fffe716027d0874f0b54b0173ddf017ae8b7a207a8fd2201baa09c0d37bd086651bc12ac2d41b9a6", "MS2": "06f17921c863079f38817c566ca6d5fcb1461420fa9a7558b8399d58f604b05d", "MS1": "1a00758170263f900efa358d8e32476a531eedcc981adef80f969dcbc200e873", "CLIENT_SECRET": "041c7acb2fc0e1da533715bd39adb164caee2b29f16a5fbd5dd399aff4252d197d08c7e46773ec63845c3f21c3facc52f42dafe25385bbb0c8abcaceb08b6cafee"}, {"TimeValue": 1437055595, "SS1": "009ca5986b76d54ff1a5cbcb68f1dbc42b103be776b19f0eed3fd7da3fceec401716fbba0d347c634af913c68134e3b4f59de4d819ff7f3e1bc79d76dfe87f3f04330a7038fce787d5f4b088b1dc86a40895e635119317735738b08d5be9b024149e201d8516c1800e9e6d9554ff630f34cf34d508198471e9c5a73a8bf8e38d", "SS2": "05ad3fe437eaed1023364667422203ef0fc6daac79678002f28a927b27d2ba3912cca357b2718698617b679db67709ffe68c1a2371bcfcebb86dff840acbcc9516ec0bc79150773fee4e997374ae8cf425339546a5bc8948ab6dea94a0e2d1cb0c83e2021f1ae8bf0a22c043686f1ef4f0f5fa6d2a625f12a5f2d15a8272e02b", "DATE": 16632, "PIN2": 9073, "PIN1": 9073, "SERVER_SECRET": "21151b259c59bd802ec5a5e4a06c38c2fde88f03e2ee8a9190257796777db3670425c785b2bcdecd2275c660c10d527cc8e4591178c4b738eee5d9784ba42cf8116499ccb903e331517002a6bd1f3717f710ee62665bed3f5a9fd4583e8eaf3c1c4ff3773d075a263705a9deda08f9b06b772fa21d0f843f54a123cc18a85128", "SEC": "040e660c31345ba38bf9a59c594b86e1920b5a88025e3088e6b6030d638474dce20c723b7ec50787c7bc8d64560c81b3b845f5cf8815c3c9a6338e6e650b054cb4", "TP2": "04227e37cc08db7dfd48767929390702c19866d11cd661400f1ad7137e643f35a102c713cc0a0c0fcf46f1928eac85ab86f64abfbaa841d4c7162b8137a388e5ac", "TP1": "0423c8f6824fd78cad96658fbb46831d74efbd965a57dd2eca01052bd5db8995241b1aae6b9d943c9741939833a4d78ffbe5016649fc526a14bbf50a2a4725fbe6", "CS1": "0420fb50cc753686815b715ae224816cc88c7e9ce30dad6ad3ecd5fc905a4637d61ce2e07f36425d188fcac001c885fdcca0d292b85f34ef6a9f5a7d7d4054d459", "CS2": "04171f0cbeff5d74ea5acc141ecef5359acb2d64d98e9e7438ddd543917f297ade0b7a4f473d92836d6dfd5faf3a38dcd089c326c1ac1b649257ecf5b953175d79", "HASH_MPIN_ID_HEX": "a82547840cc3a2112e3a59053b31b91205528f663fe6a8a903140aff527e9ad1", "TIME_PERMIT": "0409d69b0cb1b15edfa20aa584cb1ad3b9bbde3f88fb588e4367e5ad82d1006698099f88c9669e2cde7dde347674c55b1747d020bd188db1ed645d9343e6139538", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223566643432613233636232643632373566663836323236613761383930626235406365727469766f782e636f6d222c202273616c74223a20226137353938633963306163343535616230656563636339653934653562663861227d", "TOKEN": "0422b6bd324c12c7a4f152c9d9e9473cf83a725fa59fc8a1876c2b67ef8752ac64035595de7febab2a2602546c9478b5b639f6df05e6739aa35cc550cad9e3acdf", "U": "041046bf9c989bfa479b62c458a623495899228ad3cc68abca683e80618463764b021a866ac7433af9529af4b3d54f687c92709b49edcf70347b408105392597b6", "SERVER_OUTPUT": 0, "Y": "227ec4867ed05b4cf131732a8538670ca0ffc60a54045e9bae06d9e140fb666b", "X": "15d7e79acfb7e24007e8e014e2186334f2ab93f7731131bbfb5cc6d5eaf9267c", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"5fd42a23cb2d6275ff86226a7a890bb5@certivox.com\", \"salt\": \"a7598c9c0ac455ab0eeccc9e94e5bf8a\"}", "test_no": 54, "UT": "0408add6dd7df85ed2c9c2ab221cfbe0943ff11aaf50a25f8a0b209a8e6240b537206ba25dfe5c4ebc4ba3fb52f364593a1e36ec18420b589469a1d1bc18732775", "MS2": "23519eb84d43ca58471a823c9afdd425316929dcb3695f78d7953b946d00c403", "MS1": "0222fc3d41f2afb09f821165b3b2a1fe810884a0462a23969970dcc1a9c4b38e", "CLIENT_SECRET": "040cf3bc1299323a748ee4b5ea7501acbdc2fd653aecaa845f49a76ec2f6131c4221be0efbd92fb7cc48074e31369429dac31114772216ea804633624df2ef6e31"}, {"TimeValue": 1437055595, "SS1": "202b17048efadf59f049fa10dc46479f50abdc1755294458991614786d237f0602437f76d94e877f12d0fcf11931df0cac97e33f5bc4c7675172eeb1c07f3fcc15fe966ffbc535226f865986d3b2340e2ce294bcdd661a2ab457083f185e0a1907c85e2dd611f687b9689e7d1389df307c60714eb32ff4285427360ccf01387a", "SS2": "169abbf768d7d45d82d241b5189ef39ece5ef352f18d67f942739b881d38a8f10a0962ac673deb1abe135845e0b5ddd0595601307022659257b14198d835e9a7084e03c13c75e8667a4ee025edcdbcf31d7e34de9facbfb8bd8190fd665b1d1d1e0d62c70b70de4bbe30bd4967e2404774e8cd7245ed809bc677e4555bb9267d", "DATE": 16632, "PIN2": 8730, "PIN1": 8730, "SERVER_SECRET": "0129f9d6d0b0438fdec69ca3d240706d3307df9aab40e89ec4b3c5eb42890d0e165d14ce243ab0cd45689bd84f94e14829b43fd741d6c00784b4fe7dfa5a2e7a2205fd93490d2d799eccd0443115cad69d5125e3e01bd49cc2839c64dcbd1a34089c323bcf62197549309144fd9e826ef82214137ba1757e149d28372cf41e61", "SEC": "041f6a2d109a461ca05f6a98867239e6c5f79a70942e61fe96675dd1ab9788f68a1b78da4e61cfd0e3684c9f2e841246b00aa5c934ae31ab57961acb2ce81ff59a", "TP2": "040f621f545a715c6c8581e143b322c4c43b40f36bad3ad14c212cef1cff0ed1370fd4e917a28b39723516ab1298b37a34b24984fa6263c1aa9428e2ea539ac13a", "TP1": "0403eb79be636f0ade7d81042ec0fda0a798e304cd46af29ca7dcdd91b79a5eebb10a3abf0b0a26d86ba0ce3ffafd5048debd2cd74b50de6fef21fd11e355e4e27", "CS1": "041d24da08355e4a5f7db9f4b849999592b3e790d47f8827eac0cbcb12951c747a21a4981395908ac0f01a8765571390321b9f17963f88af7c9b93a56c35ad5507", "CS2": "040fd6a87965f4b70684342f4ed9d346013346f880c52001abd8e5d4883744205702a8fd438d0d68abc78eac5137d39cf9955e546010f7786f799cef04e8dbef51", "HASH_MPIN_ID_HEX": "598c7d85dd051b50e68afd0a36230b6db8c6989b7fa7ad40bcc4bcbcd9a4d2fc", "TIME_PERMIT": "041a1ebf161e68be07765abcb307ca3571ce441265b963b024449400b4ac8ff3af224444c6050438c3ef718162d46cd6e46977fc15e0db1bbf350a4fd238f98ba5", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226534336338663263313735373639366163353536363736343237393336643833406365727469766f782e636f6d222c202273616c74223a20223232396633366164323239356337303033376531656334323839343735666136227d", "TOKEN": "0423785e89774dc0c9e6dbab8c6be2ff03367ac02fe3e07f415afc44a59716368f04bdbb397900d5f99d1a24d6e02a6d8752bca7b72d74aa38201bb0ed80ce69a8", "U": "0415e89a2ef8f0e4af142964cc2c175be0246a274c23beb269fbac1eee2e50427c0a0688245afc0b5bf590380caa589e4ae351df4faf0a7b15beb4a0e539f26ce4", "SERVER_OUTPUT": 0, "Y": "143bae531fd7fc53faaaba83e3a9108e859ad8391f8d8de7077ffd1f87f81b22", "X": "15456fd91919bf4218f693f266e7b7107b03553442f257339ec31c267058a0ff", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"e43c8f2c1757696ac556676427936d83@certivox.com\", \"salt\": \"229f36ad2295c70037e1ec4289475fa6\"}", "test_no": 55, "UT": "04171a4a9fd3bcbfc8f999d7f3a96695160cef7e949175a72bdc82049922e979b6118ce3b95ebaa5e8a7dcccaeb547a2af7c01b3d2f152e4a0439fcd1eafae7fb8", "MS2": "04c16815ae9763786a538dc9e89c4acdff83813c7067eab9d04fb066e14da939", "MS1": "1a719f953904e5be222e3bfe388928bdb1cac2ba1f177e53e7e95827bb8c422b", "CLIENT_SECRET": "0413d5467b724f3dca411f3e682ed2b014e1612086033e720c35bb09fd35359d64059ce87dd48af2fb2a45888e21d134c8f645c4036f007ffb9d8d9cde942d4ee6"}, {"TimeValue": 1437055595, "SS1": "06eb96c8f009dadd0d97cb9a86ab89cdb950af18c41bf020db3cf0a6f22100de182591f847c419b31de68b81440bb7009d800296786703461ca7a77516ffdf2d0ebeaae1b5534c7abd971bcfddd46e3e19f84fedc1c67270155800895b1c598c1b89188c4074fd5608dc9ccaa4f56b04bd2611f14cdc0de3b7fc4beb78afd739", "SS2": "0528d0a273012887bc42ad9933770cd666607ee5f3886d54d1bd6ddeba9680b21ce13de4d43004c13399506880f72ef44a3f18f160e2beac63d6f2d280f88f4b0ef6aa451e6e311717962abbc3a189547ba7660c845eb1bbe2c5dc1e7de7129220495f2ede8dc68adb6dd860dd360f1f8ecb7d59d5736b9b4cd849f600d30875", "DATE": 16632, "PIN2": 8432, "PIN1": 8432, "SERVER_SECRET": "09fd13b47e770ffad0dd3317829fb6ac85cd10d669381b20c8a762e6c965149f147c29da02abd77906d91b3eee59e1372652c4cad43ce298fafbd06e2bb31cdd236b1d0eec913825ab8ac94e831e078ae47ab32097a62098a4451ea7d61337e7180a447207258ebcbac49acd2e40f1a71eaffc22725d2c4d95dd8e9f1a2a524f", "SEC": "04022071513512f7d2ca3fec369841978d4e3a681d446bf9f6c1fad9083e09f6480d6198f2875e528b204cb82d15cd437bea2793b193fed6c8f6afddfef72f73bb", "TP2": "041c501abbf624f58d093d41fc5a7a611e1c021e603248891cee9e2fa7a060c11a0bea821f4f46651e80a70914896014502cd90bf19afb321f43d48ab45b6299f0", "TP1": "040db8283f95f41bdba220148fc0e86377b7d0fc3e111ebfeb0dd32d8ebd32c3ad1f2c181e769a878e88b18001043a33eb6299cca4401967fde45bb00c2c199ff3", "CS1": "0407c4c0ee0c066fbb7b3b14f010c670ca56d51ce2b865417b698a90ea8ce7e9b2196a095f1bee2c825ef1ab373b1a3fe3062115cdd36d45f2fb997bf21d7b9f7d", "CS2": "0418421371ecefd4137f6a8b3bbee44bcd2a61ee09ef1fe93e3c48da957c8c99181caccb6345e149802762701aaf2b3647496d29515997a6220eb934d54bbf00fa", "HASH_MPIN_ID_HEX": "1774eef7f335d8ee0d6dd07dc01f98c2ecd7d45d02adfc3b4bbf7f31ffe2994a", "TIME_PERMIT": "0415204648c11b2ce239d58ceefd4fd95c378dc2eeac57c879999860a5040cc08807e3aeb59c2b0417530855bf6678b379cc723a8fe7cebe7bfffe9b504a145e5a", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226231303464316466663532643238623766343736623537386234636132343064406365727469766f782e636f6d222c202273616c74223a20223830393862306665353530366236623531623236333330356639343133353737227d", "TOKEN": "041e4da912401839de2722becb5efe35ba067d1443401ec9a44dfbf1bd07422a7e0c1e4ba8f4662e466c8eb4034dd9c44b46450964361d9d3d7b151e925902f32b", "U": "04220e3c44dc3e76a6af590cbc7fe4b285b31f378a36b41bafa4af3ff81b1e5c881e6f661d052a86f91e43a68910063b43abec4a27adb1eaadf3da9efb5f2e6d40", "SERVER_OUTPUT": 0, "Y": "22aca0fd0c0fb7fd9051c48307958b172217d12554ae6b7bc2157163db06640d", "X": "1a6e5dd260e343c12c61c4deddd1c5bdf6444089d2c3af45e029ac2fb44e15a3", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"b104d1dff52d28b7f476b578b4ca240d@certivox.com\", \"salt\": \"8098b0fe5506b6b51b263305f9413577\"}", "test_no": 56, "UT": "040ac7bc847a6d4023e5271d5c778d1b2c1700c3112aee1cd82b82df9983e85d271522cd571173209c18d0d14ec922292dce93b044ee53ff3bea0c171d6f63fc6b", "MS2": "16ffb4f7bb2bbe08b146e3f936b88ff80fb5c6055144a928f054dfa7f7dce975", "MS1": "1465ba59b8cd8fed33775c9d9fe3b4e2a1db93bb48418252e64a90cc8f698d6c", "CLIENT_SECRET": "040d8c2e642eecb76528ed979d034e9770f6827afd6566ee31003bc71ff71d789912ae2c1c0890f82bfce812463c2574f262e3b04210256c503b91589ff95b2dc5"}, {"TimeValue": 1437055595, "SS1": "1a9a76648ccd25c39980d7de318039c8fe77c650a79a96f4a38bd2850d09ed35110b6cf400151dbef49e06dce4743bb707d0bd0c8a393e1e18c0909f81881f8418ea2a1c7aa91b59187940ba2b1c953ee20dca2f5fc2fac5b75f57f67771a59722155cc8b85938d1d2f4cee795088ff6cb61fd7a313bc7cc675a482839e5dcb0", "SS2": "1193e9d1805fb6cc0ccf11d2ed79ea22ac516fe34e9c9203e2f12132b66edf30075a20a071e5df88374eacf42dc6fb9093e8aebc0b9bb6e90bf1462532cc86e50241b5b5e17c2a8db8b264d198ec3a053a0a35dd2f3a4fbbeef66c28ef8cc93d023064a166ba7b123c343b1254ec589b674ed1135cdb086ba73bc462cd2a9e1b", "DATE": 16632, "PIN2": 3984, "PIN1": 3984, "SERVER_SECRET": "07cd0e913d854fe3eea785402fb69eb6646ddce8277846a1e67c9b14b7b32b3e114e59a3ce2409272e97553efde5bff148c000af481d01b8e8af53a069a9d5b009a96aa67843c7b7e317671cd02d24ac3d55e71f426d4ab12dc1f8c9b03616ed1092929827c3feecac7207d007d3ecaf3b1d6f2f4ffffb42aca3961e2e94ee29", "SEC": "0413e8b4059932ff05c33c8a400b60ccde7f268ef3c217e6aa4d5a17560f399ede0fee4cbb8ef39cdd6528e1ee937b695694fb20adc0bacc38d39b0ac2d1620528", "TP2": "04127d8a069b21e230e4bf216b49d5bedf56567d83ba5efc25ae09ebc62cd70ff408c8eaaaf9816d4ab3ad4ab928111e82fc1b797d4b0b7a8607e34805565cfb99", "TP1": "04177334a7dd36a99fe85901e0f7bd36f3db6a09955f85a5d37f729e5a12d4a1431032913ae19da0a8a7635b36ed2dc952b5d78ae3d76e36292a8bb8e380b6b398", "CS1": "0408da568d8d5dd1e0cf4ee2fe22b60c62cbe0b088a7d306e88da7562eb2e92483049684eb8ba5d992a5be4813eb998dfef87f10d94ad4836ca34cd37217f335a2", "CS2": "04231811af1927fa4c6c4c41ebef2c7e298f1a1b6bf4c93ab065519cb4235edeab02ffdc8c772cd055fd9776c26adc73c3e092864edf585e1755d26741e92ee8aa", "HASH_MPIN_ID_HEX": "3152779d5168eb2b11a77d42e107a20f98164c2c0dd03421789ce12d0d494fec", "TIME_PERMIT": "0415e3a0dffe8e5491f57be38893644fef0fd2ccb8967aae09c2c9ff90323837cf03c1af5b1533dcd883888746e4b6b8e429a270d90f9272bc2051696fc756eb54", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226665326231356637393465333133313432303661626263663862666135393866406365727469766f782e636f6d222c202273616c74223a20223865343466623536323661623663363762616131396434633664613734306465227d", "TOKEN": "041e4aea60927e2fde85df68c987756260fd47a9047dc666a35097c370b19f7a810cf1f2ea8cfe0b5862aaf48f87096c076de52039391185b66f8e1f9d8d36b65e", "U": "04170422cc2568932adf12860d6342699c18f237500832375f4bab68e31af8e9a20ec26f487a4820f9be8f92b16695e153d35e1b11a6c091a76c8adec24f55f12e", "SERVER_OUTPUT": 0, "Y": "0c0c22578d22c47fccfb0d7fcb90ef5a2c29daee4683391216bb20affbd59d61", "X": "0cfc0e43f54ae35a58c3608748787ab7666db1f777b5b1b947381824da35b89c", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"fe2b15f794e31314206abbcf8bfa598f@certivox.com\", \"salt\": \"8e44fb5626ab6c67baa19d4c6da740de\"}", "test_no": 57, "UT": "0400f5f21b3c547be43a035d6047c826263c8bfbdd879c999516d8385ef288333e10961d809dd4f46ba47d5a26c099de3f6d4aea1f38daf5591961dc301ac23d41", "MS2": "1bfe10302a2da4204f9b3fd53410ee2428b2874b0bb81200edab267629d2c8f7", "MS1": "0ceb4310e15241a0d0041b2de316eca6eaeda7eb6b07ccb742da2850fb15dc93", "CLIENT_SECRET": "04100c42d317470b3e5377804b5d05af91c0b7b57f24d699c7fd6fb0907391562611691eb1316caa36800e2ee112bc0483bf2deba407bc136f90ef75b8d65b50a7"}, {"TimeValue": 1437055595, "SS1": "21fab3d41a492a9fd180f473e91e5fba8281cfacb02fb10800efad9b64db6f0c0c096971fa5bf2ce9f56d96db76857f82042bf93b3f59d54942c59c96d36fea713ea775d8fc0fa33e04c980c918a39849cec3810b83e0690624e8d80f04f1a6709589ffb26d140cd8a9028e792cbaec7580ba759cab6c86c9977899df64294df", "SS2": "158fe442535834da0104a2778aa67228044f2c4fb080e8e5ddcbd63d53947bf807cc38b747975bf851ed048192870fee1eec0c6276f2ba9b7679fc9e737dfa0c091af25e5fb22fb6b77af190ea8f09de33827d75989f2ddbf866ef8cf0e2b1c809986501ddb9d75878f8cdfe6ee32b39bb4d6e9916547e089f8af454ece99944", "DATE": 16632, "PIN2": 8691, "PIN1": 8691, "SERVER_SECRET": "22832ca0c09eaba0305bd2fc38892892c829b9dd85126d7c0cd83d49311c0f4a15a052351b822c9dcc03c8c032821078201e36729b428381db46e015815acc4118b08f36b4d21085f04983ea971b1c5faacec0f7a86459bb1fc914c2022df2410f4eb149ee9033b05d3a74521b27c4204b46a6d88789a3692c5818b42bbbab8e", "SEC": "040ce6b717c9ee271af7940d34f6c125874d2ea057de2829afd1de71b6de14fed000f4fec9f90bbceb0170740b3437111cacca283422da1b3d973222145b69f200", "TP2": "041f6cad39bd38e8f7562c8c5963b879fc84caacf5efc8eb3384bf985f50bc6f9714eb1d9feda183fc7c1b9d1a5340966e89650a6bda644e9cc6f83ebea5f4693a", "TP1": "041d13e5661ad84671521a407d83f5b4a96753ba3e711b10616f1da3d93a72bf4b23c701c556eb062a3b427bc8f07182cb5841c2dc9f48b805002be4076fee5de0", "CS1": "041912c4194ee31fac6249f89f4f09511c13d7a3ef73180bf63cf09ebbef7268cf1b2b721fb4f34ce24f13aa6912e8c78905464e924fbdfaedf49fe61e8f6f638c", "CS2": "041986f5f4b49afc86161603c3a86cacd80dcde93804dd7ff49deb2b4c3bfbc75012d80372a85d7a7ee7ee0f7b7c33eb0104495881d4833bd0ef942911ccef956e", "HASH_MPIN_ID_HEX": "c7cc1e221b6f22be688ed83ee88a2dde16f5b66c2f18fc7e0517b08c606a1494", "TIME_PERMIT": "0419c34b9ab91cdd7df53a557a5e218e5558c9180573182942d56fbf1cc51e5631213d9eeff6ed05aa2b9d33a3f945d77111464f5c515dc1a2af9c9fd176543947", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223834353065323833636537336433666136383466656637663837613038303064406365727469766f782e636f6d222c202273616c74223a20226238386366356466666364363665663236396630396564303035366261393565227d", "TOKEN": "0409c123b55f8f9d744b68f1bede0cb6f2e5b9e5d09f6430d83842271d4f6900000a2ac834054806425b55d434a4723eab9b3988cc3765fce9371c9530c9c9ecc6", "U": "0403dec88b66b791888e141bc992be6661e242be3cbf331e637406040a580117521df426b73dceb7aedbf2c0f077b483d8ef565308b18be73d25f7586ee74a2aac", "SERVER_OUTPUT": 0, "Y": "22030d96d291c03c613e233d3c09df4b4ea69bc72a09e31dd564d61b42e69ce5", "X": "0d0dec9824dc989c376bf8029f6aa14c68990b9bc77dbfd3751d23fc775f8dbe", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"8450e283ce73d3fa684fef7f87a0800d@certivox.com\", \"salt\": \"b88cf5dffcd66ef269f09ed0056ba95e\"}", "test_no": 58, "UT": "0416f6514e7bdc6ee649285248f25c4d83c514df4fbe16bfaa5cd1d11c12e6bbc60f0b238a6a64c51bb26a34d9547d1506d099a0dfa0c45527d4372176ba800fac", "MS2": "067dd772bac34f166d9e0e4e51b77d6e4d8a58ae53db574d585f4fcb92fa9de5", "MS1": "1a9c2d3a423fe5e00f078233ec39804f32ebfcd8657f53d8a8f93e922ebab6dc", "CLIENT_SECRET": "040eea5646da20dbead2f4ef6046cb80dd078c9b98acbbbd649a9a3afebc13ddf01ed5de3e35634bb13b0adfbf726d4bb7c48c9b0b749e3d0699bdd1a5cc1c9a7d"}, {"TimeValue": 1437055595, "SS1": "031248af7a2b0204e2da10ad1f1b5288042f4606d870494f9fe835f0380a5f0f0f9ca634f8dc7960f94313c0e60f5cb8b1254a6ef690b6fbfdd693fcbe8b3f661756b059a2fb99bfa663adf5b06a2423184227eee97772e415827d85d6bbdd8c1b0c83ff3f2435ee7e61f83132bd9d3bdfe3882fdf729e6c4a080947fc75b201", "SS2": "05ac734a890c2e3cb95f37ee81934b20afb5c78803acf5563075cdfbc0615004164410a1930e89309d0cab37ba8b33fb4ae306c9e0138b2e8860eef6c54e0d550befd8e087a39053573afa247bf50ae7218e3b3dec1954a1d99c67408e046b6917a5899bde64781ce8d23128ad2d8d199886f7153aad1059c368b1f8029eba7f", "DATE": 16632, "PIN2": 3193, "PIN1": 3193, "SERVER_SECRET": "1df3aa672261833cf9aab89b962a8026ddbaf452ea9f584ab6a12bbf19427eb2148960dff04492a222fda40e32b9be3acbda902198fb7b5c39125b686ccd0026233afb696dfa5e00b744823d8d9aa451cf17dbb1f13c36d67b9117bad36bc9070cc9992bb0499e77b21259a0b6326faaa5e19ccd41b1c1a56a8a6d66287eba13", "SEC": "040f6cb25a2e7e3d9e12189b0a7db9dd66f9dbcce05ac3c050473c41b29aa1452c0f7e3a090e1b3eb50422f1872aadb3f2785ab616033ae3042ea2cda5226e9901", "TP2": "04079578f7e5c2df147acafa6e90b35de81df95de27a2a91baae2aff991beb7c5917f2fef74b323954cd58fa7c205e5380f4adf998eb00da50374e516fa15e7ae3", "TP1": "0421d85c2ecd984db746e3925ee67f96b8826a95c0ae664857e788e5b2ba2d0d8607ace95983d9f7325c49ea1e5847a459daf34f57ad4a7b65f4d46b38a0c809c7", "CS1": "04174f779d7f79c62c97350a1b4d45bc62214192c11d794616a8ac41226a92d2121d54ff1b8742ec51beacff46e06451544288fff213de1dbcda3b4380f7fdfec7", "CS2": "041fc67928d9389e38725970ca56f6353378031955b45a40ba157cf4a7a41e363207c35e9b9466fc7fb61b98a932f2156269ef69cb436bd20357b67d8a91087b57", "HASH_MPIN_ID_HEX": "a7c2f5dab59798bf2fbf2b78573f00c6732af0f6b0414163c9e6481eeb6fccaa", "TIME_PERMIT": "040ad8af67ddd9da3a686be923a369df6e62895d77670ef89ce2ebcf1bf8ec2089211bdeb2c510f7296838fd285cfc75cbb693a938477274ea695dc9b5eca2797c", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226466306162373063396438333638343663366136326636376337356534313237406365727469766f782e636f6d222c202273616c74223a20223262323133376436353762393961363135306664326666626461306563656137227d", "TOKEN": "0405203673da2ccd428b51fffb0d73eb2bfa9a3893deed4926b5b8e7ed45d36bb0144397eec1dc2ea2a563d57b2151b83058ee11bada12678eb97fcb4261a5e057", "U": "04023b484d948dedd489047669d1af7c23cf6f370ec8d7da722140142028cd462e0610b0a4caefd11c49e0e177cd9ede08e347a47d0c597c0acab04031c92cdb96", "SERVER_OUTPUT": 0, "Y": "1333a2793004749cecd4905161c6262296a24349fc4312234e07cd7bd4b80dad", "X": "02e4306b3e7669df2bec9d477837fe884a55a050e8778e6e764b729a3e468d89", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"df0ab70c9d836846c6a62f67c75e4127@certivox.com\", \"salt\": \"2b2137d657b99a6150fd2ffbda0ecea7\"}", "test_no": 59, "UT": "0418ae530d9326ffe3735f19e9aeaa750499f44ed41f6b4dbcd7e538c5174cc4a518360a832418c3fcf949be9c4daa487b3f0e5d8804654647f26daa207bac90a4", "MS2": "211b850db5272175866b588c5fa7d5595842b49c90bb62f84b645c74a4a4f432", "MS1": "076658e393f5f519c00b9eaf37cd20edebb838ef02bf0f4b04aee9150396a510", "CLIENT_SECRET": "041874afbacdc9dc3025a805dab53e999670e2ccbc1945e2f205f16a5d8cba19900d94adce24de1127fe2cd771e5ed503ddd0fd8e140b78aa912d549fa27d4f766"}, {"TimeValue": 1437055595, "SS1": "0831de9c79b3ec90ba9727049f1da874c9bf99f8d8d154316ad846f43d0af14f0c885bba59aace5068418a9ea5019c517daf9048bea09b0d278ae8942a2862c8039f16840db47ac38786b1d56edc260b1d245f8d234b4689ac3ccc543ad7be9906ead179a3ca255e6c2748d145122b3e78d1eced326720e15c9d9d3bc95382d7", "SS2": "138b86433347524386bb0d678aa8d98675cd287df75bbb66cf4d6b68a1060057187c0ddc902e064ef5711f9d89b44fcc4476aa3bfa6ad48f6988066fc9013ae81f2d7294291e12c93b3270fd74de78def655e9da49e46f27a519afeafae88b230fd8354a567eec3e0c01346dcab5f1dd910c97d97978f707c75964713950434e", "DATE": 16632, "PIN2": 9159, "PIN1": 9159, "SERVER_SECRET": "1165932bb9e867f0e121b3de730f9939976f843bd0b7592fa6bb2cf66a5293ad15a36cd4b67efeb39057652f5ad5f6b090b2e7ceaa12fba6118802fac74327970fbeb5e927a3933dcc1acc5f9e886e1cd6a27f191454236b3ae3720d64f2267d15c382e17fc37674b448e2266149b6823efebdff6ff62a3445e0c2e5dbdda23c", "SEC": "04121f47230450de0c1d5a33261b609df260c5c7f7f27a4ddbbb5b2f560c809d8d03fe04ae9be30c9e3e5a70befb2ded5029f55fb01b128cddbe948c8f8b2900af", "TP2": "04117a967dc47003f7d9236785553b6b2df7999b0e91ebb2475e0707c11b4d23090e4c109b6708c7029ca26362add4492f8f93407773623f5e86e4a6cb77649e83", "TP1": "0418ba902ac8b78fff69c6d09a1fde4116ec0ec77c7521577bd3e07676fa27c6df1c1eba6ad90bd71a710b1779864f0f960641338fd790e40a2f85698880e54f99", "CS1": "041800183a86e2d41cc8d472abcf2eb463b9cef27e6d93c79997e3022372811ab4164145bc32eb0dc0742c8a8072792b323358ef7cc7aab70ae466a5d2c4c2bc84", "CS2": "04108a018c7f585f490e43dc6ba6259422866107dc619c363ed5d51f5ea983d3f400eab3721c381b66977177700d13ce78c63331c61973ffd5bb84ce4f6085006f", "HASH_MPIN_ID_HEX": "8a809bfc466ee211e694250dca9653b4f96b6db6fec5299fefbef4c608907117", "TIME_PERMIT": "041828a34a38464d1f9140b2ab081f66e42bf7a2bee01063ab1ad0fabbb615370f2218f21e3ae6c381d125159080bcbf9b34e62f83c33f4fe3088ab9cf0da3451a", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226439663361343264366638313863616662633834376565636463303230346439406365727469766f782e636f6d222c202273616c74223a20223035633536363261613039653736643832333734363630663336306136313031227d", "TOKEN": "040ba24cb72b5b21967cb4583b25792d99c0039ff2ce70a457a56c1e237f67afc40bdcf5f91620d8e2437cf6bfaa9b7a7ddcaa9464c92167048d7434a5c03f081c", "U": "04164ba856f646dd188be176f28791b3be849a72cc3fd62ff57584d5e7b83763861500dc54458607107eb69935f017d285ca70f1703508ca590c67a07c19eba573", "SERVER_OUTPUT": 0, "Y": "22635e51b0c573b8c7eb6999b000f2c839231f6a05e0b1346daf91844ce971e6", "X": "1c34e1657f52b15ddf71723ddaddbd199b4e3ecc516643e37360374f187aabf1", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"d9f3a42d6f818cafbc847eecdc0204d9@certivox.com\", \"salt\": \"05c5662aa09e76d82374660f360a6101\"}", "test_no": 60, "UT": "040252d84b0f56e9574f05cc9cd6ce98500d31efa4fe9e1fecf3322e594142cb5c0121c57b2bd80e8cc9bf00dd8899f2b523c1d81a05c53652c6f441489e13f6cd", "MS2": "18317df3d7846882d7b677619d414539a7b15d3dd4731b697869de7722d08929", "MS1": "114aae07d3f4b95367d82e4cf72cc161e80c53aa08c6813da21754db091a1969", "CLIENT_SECRET": "0423a2867ef236c655ae4bd9235ccf607a06331d16a340401850a6e7ee0ef84af01474e38262be1239996743f37fb6a074eaf4e49888f203bf729bec679d1e4805"}, {"TimeValue": 1437055595, "SS1": "14a65efc465ce3269d66fc546bb7d0a51bff09436af6ae8752292f01f65e18c110564b1605eb58cf4652be41af0286bbbf27422dd7d48555f64615c1dabb447b0606b9188b1a04c36f7a0e1364be47a4ee94a080d6632058b45140034b81233e0487392830cf3ee7304dd0a61e6d18b51f02737e31f19ade5470dcec1e21874b", "SS2": "155f6d087d0d1b21c0dc36a92c35621269e060861dadd1895fc5dc0201de70b101d201a443c16f1ac530c6905943f62f176a16a267e1c541dfc40f681fbd9f4113a5774669838a2bed18332eaa6b38ca2f72a53fe17ae482238bc3df10b2022b0f11168fc56cccd2c75a2f5c36788512f85cb239486585494a1a1aec9b92baa7", "DATE": 16632, "PIN2": 4348, "PIN1": 4348, "SERVER_SECRET": "1339177331bcb6353d94cbb62552e4629bd8310484414886dcda58684258ef63177932b60f43a79f17a902a53c064c2095a85bc303b7a1714b670539768bad4702efec2c15b2fdf9e3a0cc4480b93ba12425651ede0bb332943901830839f2f82008e57028063a636a294b2e0936824c1d093fc4e5795645a8006bfc99c01bac", "SEC": "040221d5d32b4f486a44afbf34203a906f5daa5635d8ac15e13e07d3e70d1876390f1fbd3edac1f85e0fec1e243707784617541caff1cb70b1fff1f62ea0edb015", "TP2": "0403cfc59d83de737ec13c80c2ce6d033c92ae8aea05d03e0ed0e80dd78c2b7b901e81449d1c4dc785adb04da86230ea4b26e0ed4f1bde312bb5f70e52be964553", "TP1": "0413ff1e05bcdb4a1fdd583d18f3fb1b612d770f43db5186de703abf1cc48e306204995042e224412dea3553fe37fe928a69a4f3e78490f6a480f19c6a61489f00", "CS1": "041d26172c08d81e4df73b4ccbdba0fd92baa08421a6672d0c9c0d6db81e4c50f802342c2d51e82953ce093826f0db3ba2c8678443adf323202d2b5da86d5abe9f", "CS2": "0418f293e8265061674806ac7b437b85579892138efc2325a0837aa6ba7c161ec3031b775386154d514422037331c405a0fa6b44c4104262157a9e4b7373e544af", "HASH_MPIN_ID_HEX": "57b66875c3920ee281f5f3eaf9835e4f0306e7f88b1086c6a97233ff995a4bdd", "TIME_PERMIT": "040ba1273beda3f54ff1f3928868bdaed9170fa0440b164dcfa2d84bd7fc060e140bfab3d7bd4e8fd14b45534318ae47b9fc69a1186be6344deeec495ae1c36768", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223131623834376566313235663933613266666136656364653538653334666565406365727469766f782e636f6d222c202273616c74223a20223639663533333633356339636239386661346432316637333130616433363665227d", "TOKEN": "042306952ec7d954ba6997dec7a0f5c18ab7cc75da49bd81af5e533c01d11ff84b1048f8b150b453db4c37f881b009cb8534f13c6d82db57b0a8335d3648f22893", "U": "04235657a884ad4981f9ff32d3487b9d4269994a6d71716e2b6a0ebddcf4fd4d4c151a2b13baea9999ec0420b26bb340d4350ad7ef12f4967ff2f522162f6ce007", "SERVER_OUTPUT": 0, "Y": "0d2c407ec845f5248e525abcb2055901b842ab0ac36f8da0837bffd4e4de1469", "X": "17915451fd088e3584ebdb03b26454beefef8095c6850b96c0ef04c1eb771155", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"11b847ef125f93a2ffa6ecde58e34fee@certivox.com\", \"salt\": \"69f533635c9cb98fa4d21f7310ad366e\"}", "test_no": 61, "UT": "040b8e881328f2fe5d67bfb21f5377ae074097a85625fb7264eabc018f9222251615e769cc8427b087d57dfb9e6077ebe58b987ba12db98b80de0eff89efde7cab", "MS2": "0b50ebfe5ba999dc58e9c2476be7e48c9ed6dfed8f14162c708b5b12cab61603", "MS1": "1e6fe24c11d8e731818e45926201d38c4e34c17aaade3704be1a5446cee1de99", "CLIENT_SECRET": "042229c2ea3885895d30d8493a7d1b292bc4494eeb049a7ef769e962569d17d8dd155c41ac77da5799688dd49ace0bc6215b230abd98a92f37992fcecba757013d"}, {"TimeValue": 1437055595, "SS1": "0d377f323fe58fe4c4011d14427e4f13430719f6faabec744933a7095ad8c9d11a5e6e636113f1ff2d62b10f5718ba7ab8e2f1089031e6fb1dfdcc4bd0a4824c0dcf962064d15e54c052ef816689637bf2beba54955a32a25d3abf4798633863100fd6b4d5e4653611da8aa7215dead6539491892c38dbc70de2e28951cbb726", "SS2": "1759a1e0672c8fde62f31f44941e0fc99cb8edde14208e974a962d289a81d4030a479b1bb05a4a7a5a9876d19877bce0aeb0aedadbec52a6c8c42d9df6ff988b095c52b603cf65c49f8921e3be39019f9b85f1944f5dee05f4d56c2d2bb875711f890c2fa1cc120012c79fd5ddac7c98303b359a56f958a96fd4e675ea2c8d89", "DATE": 16632, "PIN2": 9856, "PIN1": 9856, "SERVER_SECRET": "095be00b18a7402271174887808b6b0c5557acc2d66bf51889ee9d125023336209e872026cf8f7f3e95de214b567b4c0393734af3cd3151476ce0ff9b52ea14a08cdc4029866cf7944cbcf5456eabd450db3f841af587e72a3916b4f2a1437e3010b7759661543e6bb7374ae6e9765d711833f3fa097062fcc4d378666d30415", "SEC": "04031cc2592e9d6be99c58e5d0806519a81ac1d20e003ab1c7c6ff2bd497d29d840865d5fbcf3c9db8d85f769c6c4e6e8834ebfd3b631a0b1a6cde92ad457c76ff", "TP2": "042004cd2193226554471f81f65146fe761cc5f59b6cec805177741518db218939210d805e812e348ccb9df339085195ca9e7798cca6b2ea2b33467ff040d23e5d", "TP1": "040ebe1c5ede55865c1c8eea525191fd2e492b63e583191177ffd9ff20df83c52b0c7160a4e9d2c1e7106c52c95e7a48e32f0789933bc3c884595239f12169c834", "CS1": "040dd09131226bdaeded814c47958b4b4ccc479c91443a1ad5efb850bea720f70f0478788dfd898686ea100c6f793d504ee25417b1e4707cc7a4368201659d0854", "CS2": "041eb48624ca1e2d738aed0ba3d1b332da31f053b50ac24b33532bd660465f72b71af317f06662002c7b5757bbeaa8bdf6772dc5dfdcabe17ead87593361ff0884", "HASH_MPIN_ID_HEX": "d26b10e04af07f8afd5542eed4a2d1c2c557d434586e5266129038211c573282", "TIME_PERMIT": "040fa807169a27916a2eda5af6ff99dca9a1603aaaa624538e3febbf362ae101cd23b36151e383aee7bdfa619a691ed866bf459394616630fe9bcf50aef7064d98", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223832353463343564653733336637326532353564366138333464303239356563406365727469766f782e636f6d222c202273616c74223a20223634643338333532323931313961643065316439353732313335613338303639227d", "TOKEN": "0402636e0464aa35734a98ab4999a21a177695c8d8b7ada9c5de827b65b436fe6a140df6357ee55462fb311be4f7a041457ccb584ba96050a716c20c5532da06ce", "U": "0410c334ee40664d1ff6ff2094b97941bed27897f17b4d34c601d4730e828f1a63090adeb829ebcd8260d8d3c379490e54029fd457d9f87f3c50b9c91fb8eed717", "SERVER_OUTPUT": 0, "Y": "21caf573385a564e4befbecf36bc65dce94aff4e8442d1ee8216e005551c7cd4", "X": "23d2c90e12ca9593d2e8fd0a6a3d94b07ccc1c90d44573d4d9144a9b62b2a922", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"8254c45de733f72e255d6a834d0295ec@certivox.com\", \"salt\": \"64d3835229119ad0e1d9572135a38069\"}", "test_no": 62, "UT": "041a59ffa9dced6486f500dd6a273226d1647891d7cdeca3ff9943ea8da69f4f650f3549a4566664d0c77eb3b999039c95eaadcea657b9bbfc8218501a552f8149", "MS2": "07baae8094512e07902027612c54a9be1810645986d9be47ad70687bb49f01fc", "MS1": "1f06027aa5b37780ce6a72a2a233da776ff7899e0c72ed1464edce7986fa5792", "CLIENT_SECRET": "0411b179ce20c188b28ca6b70721894b9627976c52b9a4c5c001e511086cc798520928d1b5d3ff46846e5f4fa7c125016262a573705e5ebd90f6cb5a345ed76af9"}, {"TimeValue": 1437055595, "SS1": "0b7e54870de25e30efe2af3c14e86b00380140893ea57206fc026179d06681dd07d4117e8e2eda0ddce86ce4db199e910b67a27ece68387401cf33c5319ce0e023e3ccb5861815af225bad03fe49b837c6fc7b7374fc353f663bab44a953b44f121792a05f99d303843024fcd2f5c37a5858e32890d6ecb3fd27199dbd705f47", "SS2": "148df58cb56aa046feeb61f459598c4292bbe8f07dfb2a05966725623bf6a41917ce76af6425b8b9d7cd7406b755c53707e8c5f90bb9611daee86b7d4aa7494a08f1750fc99954c5d98783caf7a936e885636869048c1fe2c47124813243760c01498384a6ef4dad2e3a2980d286726a8979c048ff69372bed93c045df4fe533", "DATE": 16632, "PIN2": 3848, "PIN1": 3848, "SERVER_SECRET": "0a8b9b9a300bd648cae6274ec2a02f46eb8ad0783b35ff7057cd041370c30a6c218384ee2063d313c9c2ee690f3301eeb38ca25e614bbff9e237f827ba3c68491cc481cd33b2125cfee81b8b5fa643fd19c419ac0817b599e3d03ffad8385dbc1e3630479eec1435d21925b1c7f0fe6441d068e91ca368612fa58a2664d7e7aa", "SEC": "040210c03081f76ffdabb12011f6db4ca27de749b66fdf69e3a36e53abb7c0cd1c21a65055cdd86da81949e3421b9a880a29ee9356d1943fdba0d3da7d010849c3", "TP2": "042140d00242edfeb454681c758db3e98aac0397eeb869aa7e862748ddad871f65133d7503e551e010c43af36f72e7ec3e4a96d0a4aa1b7547bbca5f0a462f0b01", "TP1": "0408610b0f97db9473272c734b1f95afcaa84ea4d50798bd87a3c278e95d5bb5c818104d6362226e42d25adcc94ac45792f43af279ee9583dc4c6a146e112f981e", "CS1": "0407157f7030c0d8f2b67612f305836f575b33799ced0f4939722706cde092d674123a7699c437eb82eb50168f5bdb69ed5cbdbe19bc73653cfba3e2a24e4aba5c", "CS2": "0404efb538814d1fdb55d5efedb4461c24bbe21249ed68368d365f5de9ac46712a0d34a95caa066fbd8a05d74d124a1550af7dc6e93e33525763fca0524faa59a1", "HASH_MPIN_ID_HEX": "b93483a64396a751e50f59a0b0ba071eb72df1f0d9b8a44796630edce2fd1765", "TIME_PERMIT": "04195292e9df27d4e7bf8fac4a6bd6ff845bd3dc2fe8f422cd5b5d2b2e9fbc4b7f1d4041219b08763cafaded0e7f9cd170fe625044882688a3325dd7116ae79593", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223534343738356239643162366633383836623665343339313737333838323330406365727469766f782e636f6d222c202273616c74223a20226438646133626462303736343436323866363964666338653562313430393239227d", "TOKEN": "040e6fe5e11cb8a0f115747e463aec73a8ff5404dab7dcf23dee930833badfa8db02acb8d5c2b39659c57aafd69d4e89782ae92e331eeca98e008ae5da5653cbe7", "U": "041da937d11a11e1daeaa9ff22050aae514398cc3c30308ef22c615c1a247e747506eb4e8cf3b47c52e4f052bc020e16485ed009e262977d63c7bbc3483002ad69", "SERVER_OUTPUT": 0, "Y": "14dffa2f4483090a35f3a3ad4eebd2e4415de6c1486ca996ad449bdf1ece0b3d", "X": "2239b9e3e407b9f99e9dcad616577a988572786cfe23b6cfec54fbda771b7e7d", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"544785b9d1b6f3886b6e439177388230@certivox.com\", \"salt\": \"d8da3bdb07644628f69dfc8e5b140929\"}", "test_no": 63, "UT": "0409a710d307dfa16565348bbe3e4d1eeaf693fc106e4f9953ca62b9d3e612f7d81a3037d022fa9f5405824d8c29e8859753b7f9448c7bf2446d50e1969c4e7308", "MS2": "1c14a3914fa11ea0236704dbe73fd4348ca579140168785a97c42b1340201367", "MS1": "1a7299f40b6a4c4cacf40719fbb41527fca1967b331d052b27e0fdec1e929039", "CLIENT_SECRET": "04091496a4765501447cee44284a9ee5e901db385a31d2511fc982f461e9013cbd18e6b50e38402db76cb8384caef4be647c11a11bd0316908aca306d3e6cf2d6c"}, {"TimeValue": 1437055595, "SS1": "13bf607f416e4b196314d57e94994e2cc41001bb33fd61c9e470522a9de20c37110907118f4622945cbf2ccdcc8a005303e4c5b7d653377c69fb2ab259238815162854b5a35fe78600c210c4678bdfdcb9523316d403b51cc4292bc450216bfb074bff4822aff57ff20e6ac44bf6b10a63633ba5cb1edfa2c65341618b98e1fc", "SS2": "1a7ea9f3dbbbab6eaf701a032313145f19d1d1a257af12eacab05aa780d06a9322ceebace02f25ac26a8cf7b702c83a224cf71406179ce80f064b94d477ab0411acf2a88c541a84940da79b0fb1a8c56ee10befb3c97ced769d17591f0228d5701f8a78e0e63fc1090667fdd97b6a43203a2d677a35f1f13c499d70b62eaa29b", "DATE": 16632, "PIN2": 9840, "PIN1": 9840, "SERVER_SECRET": "22b6720c8ce0ca15c31e6322f562052e084f9608bac50f3f2f5b04069e78df0f073b98d95f17d664b25b64a9c343e0eb575d8079274fa9bd605ad4658b4e74e01120b9bb2c0069c26fa6ed458d557a098c4e79a48e85de701d5c27d65acaa33a1e6c8024b64b11fee2f6df62e71977be046d7ed14c387a85435f684ab93b7b2c", "SEC": "041583e8cca5c0da0e96d472807c126abb0d0b3d8c87d5fcd2d2a66607790f5a7005275f9ab5236558f230dd649467fc2004977a9a141219f337e5e8460f6bb976", "TP2": "0412512f56474a4b2dba8eeba796a4a166df94cb181ef8e1a74233c767cc3f330e0f2243e20b5ae645a3da9e94db7b69dfafd9f8d11a982f4b9d168179a27381ec", "TP1": "0422228f69c1ca9a60195760c711be929b8eae79e6e9860fdeb894d05cc9387379095268f4ff6126d6739f4db190f09ff9532f61391498cfdd8dd85fe52c3773dd", "CS1": "040e4112d8ea8ebf20b9e0f5122d039e4457eda245aa937d6f550af9124998ce1f02b6fbeee6d168fae7a449441ca09cf5d4bf4f5ace932c2bf9290d5a8db45b8e", "CS2": "04051ce54b38f9661e265dde6e3d6d0c8ec158ec17dbd1b93523591d62bd37a3261906e3de8e04dea88ed6f638fd170c808093aafc39a2ac556e48527b49ea3647", "HASH_MPIN_ID_HEX": "f049ade308814d878744b832a46175b4d6ce77b56f948be97f924bb1a4c0b13c", "TIME_PERMIT": "040457cbf9b0cdc6db4bba007e0db20e4be518ee4061f019fb9cb3f45d6a23254f0d3f0118108b671a39a40f3c6e78c923bb1a655982e298f316c45ed33d44ebd6", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226436616233653836303539663065643134333437366263386330326363616335406365727469766f782e636f6d222c202273616c74223a20223063363939656235326637316364386638313634616361643738343532373337227d", "TOKEN": "0403fb1ac2fa9296e5c3cfaf484665e9220b763ddc431befff793419ac94d2e7c5138f9d035836e2b513efdbdc40469a86b212b5c9f7ef6d7be6d2e4693c0fed1d", "U": "040557ee4f9f6a6b64880caec8b63b1c781d18b381b3dc48b2edc06fa3ba96bda1138109fb3f32d3255f530d2b8dc44bf9fdbf84ca347cd0e55f14942b59454e8f", "SERVER_OUTPUT": 0, "Y": "1cfc85770474d5caa4ddd0bd44b8ff759e88df5b6800fca79d21a4f1a0097450", "X": "1a742d46d555cd11450448b2fbe7c9c2db074b4c86342be1cbc5bd36964e03a0", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"d6ab3e86059f0ed143476bc8c02ccac5@certivox.com\", \"salt\": \"0c699eb52f71cd8f8164acad78452737\"}", "test_no": 64, "UT": "0411e44886a3829daf9595d61023d4d0291d928bb6df16ff58699c36d5645a43c51030430040c0b2273ddda2559db56e6ad932de93db85403b83cc77fade5eb408", "MS2": "192156d3d9027c76d0c879f32f479eed8e6ec030bba1747c7f36785790dace16", "MS1": "0d432bb1a1dfc11cd810cddb4d0eef78164a95234a58bf770b53dfe9a8571253", "CLIENT_SECRET": "0423081f4e5ae7028010a379d6d08ce23c6ed8179a8f31c6171180e99f63ff507518e52659b1985035ecf642644fecdaf28d47359d1c5b8bdf693f2f1f01e54106"}, {"TimeValue": 1437055595, "SS1": "070cf85fa0d89545dec9a3008d6a0439bca8492f67fac8123a80ddc8b798844509e8825d375467008a5587529508a92deec18b131834c08f845c4ec1d890ac89198d21142179f3b5aa65853bc9ba6bacfb6ced2c650b1cac86651828b49fca3302f0020c770a732ef136e126ac15aaca0bc0dda4638a1d69d19300fc30948f80", "SS2": "120f4fcb2a4d270257117685b66ecaeb592efbf0c39cef94885d68869c9a138c03ca344bb0629a286b69a166804a72f2a99750368f9fcc3c5b0ea5ba8093c9191e5b29f576a9d0757db3ac8ae80787a189e51e896de5dc41c3eac3a64ab423ce23c013b6388c38705c4e2a50997e195153a079f88f19ed238ee9284d07d75a75", "DATE": 16632, "PIN2": 5236, "PIN1": 5236, "SERVER_SECRET": "14e6f1129b4288f3ae0cbf9262b79bb4f01a2a62e3185b0895c971376817c0961432576f21135dc6b515945e7764e549bd3358a0b0c4a9f7165ae2ce1ebfeae91928b9c7513db87173afa3936b264eb44e648f524d22566c3a3bfc669d5c2b27224e7721b9db418052a6e402935ed6867ab0f8177b12cebe356e516e55d882a3", "SEC": "040243bd58c69d4dfe5c23618315935646aa00359025cedd7a32448619d2e0b95b16b99c05d148e29af0e0e72d177bec2a44b9435f47f754a3507d654a0cc5b164", "TP2": "0400114176548f54c0493833bdb0dc8dd359bde589076492cf14f46a65ce671edc1d0be9e505a1bc5d25f1beb0dc1e0bace941eaa8dc09819513e889ec4da27ee3", "TP1": "0407206d8d8709c3f06f167582a1d89fd07c48ecfd140794d32f2ca13db5e85f950381451e405dce977dc0f97066f6a8e761b2ea80a7b6d6824d55fff61f56bc6d", "CS1": "041bff39ee8f42023cace5c99a7ff52cda5e4499440ab8fb36bab95b0c86064ba01883ac30aeb561ba9a6eecc1899f2e58a6a73bcf76d85f43efa00f995c77d82c", "CS2": "0419c6f5f411daf047db1360aa67c247745da2902b490c39d8f503bb47652c75c916466e9f6df596914c8993c5328b403c5647283e8357aa59954cf8dad4c5cd7e", "HASH_MPIN_ID_HEX": "dbfa6db9db662e067412fcf3969f088de30cfac7bbc9e8a6202040ca57b86f70", "TIME_PERMIT": "0418cd22ba9a0ac195297a2cfe897b260486d3340737c6a7deac7815170d17212e0e5f87d3c0d8b55ebe1a1c57329487d60deb9cd76598407c8562559ccfc25486", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223363656133396538396138356236373539386335633134376135363738646362406365727469766f782e636f6d222c202273616c74223a20223762643438316434333162656531346139646636343433313931303131363639227d", "TOKEN": "041cb451dd2bc4f05d8dcc90239acd575dd54d54d12a4b7fbf3b46094084c2974201022d1b4a322bc2d6b8066cc01286c68b998cda5c1eae855b746ebda7159f4e", "U": "0412b9b2317334799803d60db6211daf06718f18c625b2e873012a19d6faa28b7712eeaf27301817f6a11b2f959f1ebbd7f82c8fb4a793fee3ae51cafe8bebc9a4", "SERVER_OUTPUT": 0, "Y": "132da633fa6b06aa8b4611cde0c8e1786db9cbddf5195ce25c61caa400597e1c", "X": "0ac7f75abc61f3e22b93521470929e9d4b573286fba323b21363834b400b2085", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"3cea39e89a85b67598c5c147a5678dcb@certivox.com\", \"salt\": \"7bd481d431bee14a9df6443191011669\"}", "test_no": 65, "UT": "0412da9964c83e5dba6e562e7213e279515ecf107aa432d566adc4e643bdd99b9e203050a7a025d7b1d22937740fd922b10501ce408caa597e90f34670faa058e2", "MS2": "10f951258152ba97bd1cac42ec35cd1abd55977a95376697432f1b71a27c5707", "MS1": "04022e8e44d71a223d9b131fbd210382837e30e36338a100efed0e5e7e0df57f", "CLIENT_SECRET": "04157f27f73a5b0b13e2d1d5dc52acb327be01c19ee47e0af2e73129f4b6db20682291e0f8b25fb541884ed827d3c5aef38aed53d9151789d0fdae5381acec9e85"}, {"TimeValue": 1437055595, "SS1": "05ffda640b1d05f4cfb2494b5b2ee2fdad85002a9a19a2b8c639b5e810e683e10b69bfea265cdba8d34c821aa84611707b36e0825b73748a29167a9cbeef74ca0eef173e538230ae7b2dce0e0bdb1f4c9e90ad84a112170f39c9f6b0616b15f72032f6db8aed5a08b698b78e051c640433f048ef3fa520ef7226a221d7495927", "SS2": "0681edcf2291f1b551302792d78b1a0db07f6ff9ba4a3d57b83a8010a27272a921b301f7034880941a95f19a1109a27af018d3a9510082a8271df25dbf6aabe407438c75768fb92fb1fc1d5f47f8fbb1f53f8b176799de82845fee879a3ce77919b6e5ef5f37e71d02d18bfd5bfc814b503b63c7b82860de73f0eb9e317aefe2", "DATE": 16632, "PIN2": 8503, "PIN1": 8503, "SERVER_SECRET": "16474aefe3132c63973ca7365596cfcee7ff83852c6b9951461899803dae5e6c0d863abaaa1221b3aa15f59e5ee3647bdf8cbf4ce6728d64a85964d74851976c0ee98091a01e610b5ced7ed785354e7ce3f780a3c8a55fb91df91d480e5cd2860f49e7da50b2dd29efdddb4ffcaf16c7b81c6c326b615ef0ded4695d8ae93aa0", "SEC": "04148c5e00053f0f0794b8b36811e4f369244c80e90c452a4e5eeecd9be5bc83b20e3dec8c33cd46226af7a83e5ae2ad14ba2383b59327b96feaf8744f668d9c5f", "TP2": "040f8f4f9c6698c602b271f0265dda9a3006ff6b564ef78418ec4130f96797464c1bd9f185c26a05d56ddd3def4ebe3d497a380a5952ec39aeec166fb67b132dc6", "TP1": "0409c30167955b35290784fc8b7175e8a9e4ca79cc0ed4557d5d8154c80918d0831df9c3e6bb883d039b3254a1f54e8c849f46c4f146e513a360c232fa9476be1c", "CS1": "0409aff2571b9e890ce64b21f98b5d53456987707bbb001b53f4d539e7b67099672361397362cefa694b10db4694728d76a1407403e1fa711c37d11d5a57a2d42e", "CS2": "040fef9c3b30dc526fee755387ced24d960879b0f20c230a7af0591d098da65da910fc613f4c26e82a7a171dda589ef42cd0c2f41a2ba758f39ae7b76ebec05741", "HASH_MPIN_ID_HEX": "c2643e1ae9726a227212d2f6c33f1511fda558ef727150f8ec44a56827ebbbd0", "TIME_PERMIT": "0404320135fec04898f461cb51df983e6271fab4045d37b87a31225df56a328e0c030fa9e89d7f81fd37fcc6febf817b51b5b29c4b636cb103e4fefbca3aafa2c7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223961633534613232396264393962333961666666613264323531356165386564406365727469766f782e636f6d222c202273616c74223a20223836613862333761393335346234613432613464633938333037386338393734227d", "TOKEN": "040b09f9d7c5b4f272e855413462e80c355b1e13e0ea34a597b4bcc0c9330a9cdc1ebca2435274275df355798325b47bc7a0ee72253b5e60ad32ce85954b955274", "U": "041882282d0207aa3202376d63c21d4629ef9a84e99ade446c38a91ece063633ca0c09245d7e97b05098f74ca7556d4cc76326f38ce902055e06c89e18ff9f07b0", "SERVER_OUTPUT": 0, "Y": "0494c49569844a3052c950419599074ab0d9a1bde7f2b20b710b1d3be4386a93", "X": "1c1a3bbe56cdfdbf9af0cef9faec1c6e9489f642101e3ddb1ce691ac918a6fb1", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"9ac54a229bd99b39afffa2d2515ae8ed@certivox.com\", \"salt\": \"86a8b37a9354b4a42a4dc983078c8974\"}", "test_no": 66, "UT": "0418b391d41ba0ecbb26666fea3810f80d2255cc1eb7267d16467bcf05bda565d805f8508f5bebd0ad71b664865243524d71d788012da9a67a023b59a6bf14d1df", "MS2": "0d55fbc392d91a82f02406c5d37654088152b953dd78c455791625deb220a211", "MS1": "053615fc945085b395b9ad8c41096f7b4acf10c540df938533d1c99f385c4207", "CLIENT_SECRET": "041228459f99fe30da1233b95a91150df9f067a8e923ceb2fd8a25e0fbeebb556e19a5b50a0f740a7a16cb8ba94f3eb288ee5a96d95e68409b644c58a388d73a60"}, {"TimeValue": 1437055595, "SS1": "0641a7a9282c99cab1773424a9cf731f735d09c084f30d6fc520620778b924e317a8692bb1da8a9066dc812469eb643b1b89b8ac69400af6fe5947c61bc201c60c608b8d7981d7fac47c2857fa15c810a2cbd9d2dcf61a3630deb590d00e76101d79ce88c68dbb495285969197ffce04813b49f2b3091f8bd52742b557794352", "SS2": "1b3a7b9ab7ccdd22b34e781bcb43cae343767438cc9e3d3f72350f33153d246b1d1191973d3535c2ff3cf02b5c8f6f51bc89cd8e48db78b91a27ac3a75497fa50728e8885134c8746947ab054824676c3e362a04f6cf3f48eb5c385462cabd08020bb53ec669ba3e30847b3714a26ef801711da7ced78a3a8729dc91152a3b23", "DATE": 16632, "PIN2": 879, "PIN1": 879, "SERVER_SECRET": "039f246ddf7de21d752daec90d2e2b75948c038491018fa7f9098669fd67f2600044ec890af8216424564bc8f41b14b7a89fec64411bd16ee3ac389827b27972094b24cf5cfdeebe0e1622d19800b9233c94049f35c0dc9230d0e72cb1f4f2c90252a50e4bb2613d483bdcfaeb657937c0a6304842d779d31edc2911a5500877", "SEC": "041738b400a0b63125adaf78056b4988ba207e056591a3da4ffc0cba7512a445bb0fb62f24ad9361747b2fe1825dae137de9c6e5a5daf3c6f001cb2f6b032887ce", "TP2": "040659d9b2dc06f8705e4bc27c84704e8665055f6a40f65f880d171439acb67f450e4c1766dd7dcf6573456ff55088bd6cf090760bcd5af42b31355e4997074386", "TP1": "04210fe8b689e5cdd5d8b957b8aba16346e98afa322026835a450539491ebda7fa1ce4f01636c0f51419832c2da99cdf01865c74495eafa26e640dd954abc96862", "CS1": "0420f65a70696f7b6ea9ba3c1bfa1e7871b908aff4beb18c78cb6983a4d2c4c50407bb27718da9dc032b54fbebc5bd6af6e365d1381a595b9e4abfb37433a20d97", "CS2": "0410be94bd141431d80150bb4b26c6c3ab8b13a16887f7b3bc031c223081b195eb14ecb142b712b5edf92690cdf65ab050f22f9e3b14b1af1f21c370fd68994a04", "HASH_MPIN_ID_HEX": "0bd6111a0d694461b14bfb9b3a68decdca1985e4315ad50106d65c0657867cd6", "TIME_PERMIT": "04013ed1a4786f72479ed260f912a1704a6cc9ad4feea11028c834d284626fe4360655df0d39403900e02bbdc4168d84bdf74f44ffcd498d796617ee399512d366", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223264323330646434333562336262656437323233303065393532383839363338406365727469766f782e636f6d222c202273616c74223a20226164303532623566383232346462666536353838383065643232313664346338227d", "TOKEN": "0418db4417846857cfd41ce36ed7741c1fcc66d13bf242647651266fb01d6ffcb813eed8dfea3e917e310d78f83c3657d1370064c8e9cc1ffcacaead4517bc3bc1", "U": "041bbe2d39f6e1b4cdb84144c65af5b01dfcaadf6f17a6611fe3aa8d37c45385cf02dc80fd7a4e211a9fec57733a5c92a2d192201f7b16f03782e6528d3d952c3b", "SERVER_OUTPUT": 0, "Y": "0c4fa4b6ed7f90a4699721a86de2075e76691f6809ea4b7f203a69108545b9db", "X": "03dd42e2facb5577f9ec20c3b70333b1a1dfc027b3895c59aa95766d017b8d58", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"2d230dd435b3bbed722300e952889638@certivox.com\", \"salt\": \"ad052b5f8224dbfe658880ed2216d4c8\"}", "test_no": 67, "UT": "040714067cfcc44f65cebce4b9031621110c8b74705b50d09d9963f0d6ef302c530b452e4870b2490bea030917f751c13bbd4d7d5a690c0c6886a25072225b69d2", "MS2": "116b105495ab1bd510dd33b2d52a9e66b10a0165877267987132b95f012bc7e6", "MS1": "1e2a82de27f2c4ee26be22250eb7f2f7c3d94b353da6a94be52731f2c172ff44", "CLIENT_SECRET": "04164a46ce49c1e8db2ffcadfc7e0cbe94480538b00b6095dcc5f0f6e3c20e8f070e4d1f6fb80e4d4c6ec728fbaac3d78da8f6db23661b9064091f4b9a29bf57a5"}, {"TimeValue": 1437055595, "SS1": "193036f341e3f4b8e292e0d06282dac204eb75508f0bb646e3545fe712c45020001ecd91d479c95e341327a147dd92068ac3a52e1041974846e60c5dd02f2ffd13ed66bb227248d5762a6abf3698edc76dc5eeeb3536f7680207264733a87a5500d5b5162f861d271a08c4d84a37a362a9b750d9524b1203d59dd234d82952f6", "SS2": "0af4a0de3b8dc9ec7575f68736551fca841ba3e0a06743ae1ea250bc37b653700bf0560a3d602a0743fc0dba7ff167e6fb7b0dcbbd3ba12b04531449f7442935016045de11d62ff2d3a464e3ef87a0c63ae4ba77e30eb5782fc1384fd475f92f070cc6b80a8609bb105a942ad17ccfa6daae20d19fff7d1322ba5abc0718a6cf", "DATE": 16632, "PIN2": 4240, "PIN1": 4240, "SERVER_SECRET": "19b9c8eff655f4bf3aa4a91711cb8e906b0d30c966c94e2d7cdba743d03bd86d0ac6b1bc2302b15f164d6cb3832c0ee4a60dfdff97733d79e24631101877f25d01b30fe71569a4735bb1ec916b9f7710b82ff903cd57aa31f93b10a21559989100a6ff2c8b965089c64502e943aa21766853672aa90fec73fd871e7e25f12eea", "SEC": "0412c8fe176f9cc23f52b1a508900175e3e9111ae950ccf2b946aa450cbb151c2106e681844eb5ee98e05f174975014b1122805cfdc04c6feeacc8af7ff1c84f1b", "TP2": "040eb034f170301b1e5bd886918101a729f9d1f0439567a70ab362933d42586e9a0f945a1179d68b192abcbd19fec561d022b3c52aaa3282cec96f1191fe4249ba", "TP1": "040f64d4e520056a6e003c51e248f7159992e11e50a2f1156e2d0893fdba82dc672118d2a80302982d5fb45f03b13b5856495d694848febf751ba2c8f3478e8f89", "CS1": "0419d750e8744831c45e4cf2de6bf6f680c38787af616787fd62a7eecbbfcbeb67017e634ac5d10b903e6e571e58992f4658620eb79e71c31f68375be7441fbaee", "CS2": "0412740f4a5bdb4db3ca6f7ac61a81298eca47011196e0c78176d76419834efc7b1e31ec143352e3687c1501770c3d1c1e25af56d87d6ea46ef8a0608af0975259", "HASH_MPIN_ID_HEX": "33f03db9575e4a1e9bec68c725e9dd671a64586cd1ebdd3b48cd0ae05a7b8ed5", "TIME_PERMIT": "040380bc1106ab5d6514b7925d0ff6202af4c0f951f05f80111b41445d4aa42e490bb2e1efb57a0b1114f81c4f77cd658d8ff40f9d071ce02350168486472b25a5", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223439383031346361366630376464386166356163616235356130643162666664406365727469766f782e636f6d222c202273616c74223a20223966646362353336646137353162653739353239653263323239336333616663227d", "TOKEN": "040baf79944e8df04673f9246761cadf26a673aaa3dbcb6012ac46c519163858a723ec522540df3f4472e067f15279003edf7eebf176cdd9cceda410ec40eeff57", "U": "0422fa41bb241ad6d69ad7a30aad127f6b4e4234a06e35f57862ac392c100ca4040cc2c39de2fed9f20bf8edb5b08817872dba7504f231e24693764d6b3ba836cc", "SERVER_OUTPUT": 0, "Y": "085e07675628313e28c71d031325cae1b4f6cc3f9bd3d6b05f670fd4a41b5cdf", "X": "103f6beee094d9056afe23435e9dac4aa20d26e289bdbf407e202fdceba02e40", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"498014ca6f07dd8af5acab55a0d1bffd@certivox.com\", \"salt\": \"9fdcb536da751be79529e2c2293c3afc\"}", "test_no": 68, "UT": "0421a3e14d8b466e1428d3c9a436757df53db2a31874df19eedfc69fcfd67002b506ac330074a1d8c112be16fd71e39dd0d18642a93fda7718e2bb76ef4d80a867", "MS2": "1c9085b520e4f1504e6a9ed93bd907c28a1abc3fc09327ef0fc09db08c30616f", "MS1": "007b1e50d2d67a4cad69b097b1f1ed7d062affe837f70c8983fe7efec390867c", "CLIENT_SECRET": "04217ab17a3b78f31e7b6638b2dafae7a329dd9d0316cdbf66b07b28599de80bfd1b7e6eae97dfab60828dab421eec5b7bd86d3701e2dc320505fb14af07d15e96"}, {"TimeValue": 1437055595, "SS1": "0189807352039396bf746e832e132e5a3b10eb99f91455d871506baa7eb4be7512f307ba36b015d49ab241639797e244cac595edcc29395e6483ab27a011966403875df8475148af66466f5afa44ba66f6aad281414907357b05c79b155c687e0945bb3f0baa8a0545311e6a452224ca024636d42adad4208e19f3c56d5a73d3", "SS2": "1f95d0077f7390850b234dfef8962b91ac8c88d4d406fbe87287e86a521a03fd075a18a4c71f3d32eafd3e41baffc62eb02bfc0166ac2e188b5f76dd4fc1b7de01655cf36d40d83c5c2eece5e3662520f0b69eac52a13f8c93f9bdc61c66ba1d0b1f0a59e35a0fb9164594425c3c46b1a1b27b7054ce3dcfc25f53900f549849", "DATE": 16632, "PIN2": 5646, "PIN1": 5646, "SERVER_SECRET": "11b9ee643b49d43161eebcdb9398b72de6ab638f5258429477b8583a76af372c091f33d4064cda1cacabc31070da8c44790c32723d768040d89ac8ca67a2345f0c969e95ba4e1e5235d093ba0bf0a196aceae1c3ae9fb881afb30d223b3cd5d421776dc7d27d1e9514c95a12066979f2d92c44a05562e10a5d159251297b6f5f", "SEC": "041c6ae9ab05356c9a060420e315d5b85616f69b2d763c7e61e1ea12f9b3467c93074e604f17655e2e2fe73101930a1ce2a962138392ab33e786727b14d4429158", "TP2": "041c963402ce36b3d6aa3a1a11d9011860873a6f661fbec8d4865261c9485929bf052eb7cf403c2f323e607a73078766a1d85fbaf1294cd01bcda0a530de62095e", "TP1": "0413ff9b9b650c41d9b74b9fc77de684fd2df518c55cd6acf6fe1852c10f1f1a31044a35bc84051049e4997bc9c02c59c72f07f5997bd1b5a0839526077147682e", "CS1": "042096cf5deeeedf4193ce7ba178deb8e2c12492cbcb0fa775edfdbd3687257ae51768c4c6f8b6b785a555129360c63e33653036b5af73660b8778caace2f1cd26", "CS2": "040d5364b789bfd9015498412bcf659ee710cf934e4e33ca6bf68899fc6d665b2b1397fac74678820543343ed00bb99da1ffac2f46712343bd5ce6c33be91e90be", "HASH_MPIN_ID_HEX": "6688f89c990fba85fec8cb353d0555a4046147810cfed22b9d764967ba5b105e", "TIME_PERMIT": "0406c5fff12ed831922f1e44300e2d964afd0b591d28c3a6720ac2a6799f05a60b0c21cbb5506433a6567735687f59bf30426923b8ca9db988aa5e97a0e1012d83", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223061653430613135616563306537666466366534353564313966633634663133406365727469766f782e636f6d222c202273616c74223a20223963383937626133353530633864366165343133356166613337343231653862227d", "TOKEN": "041831a75e76cdfbffa6c4af5723e56e2d31ad80fe7201a11ad4c6da540b8164b303399dfd1275bda5a1f1680113b73c6a6fe5c4d80eb63baad3f4ce14396715bb", "U": "041b2adb0edfcd2675faaa4efdea25efb00bf177bcfece356565207a653bd71c59226bed7c1481175088de48e1071c58ea39668177035f4ec20dd8173aca06c564", "SERVER_OUTPUT": 0, "Y": "22818ca61f8fbaeb8369936e37ab5800c30edc5a0f84ab4b0ed0e6316e335a15", "X": "182ce9b9cf77b47859ac4c8f322430298b9cfd323811bedd2309b89028a8c283", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"0ae40a15aec0e7fdf6e455d19fc64f13@certivox.com\", \"salt\": \"9c897ba3550c8d6ae4135afa37421e8b\"}", "test_no": 69, "UT": "041cf49acd37983dce2723cac665b2bfeab0dd76a80febb770773dd5856bcc33b007c0811991020dd0db4be2ee6e6aefb1f2cc6be6aee4a5b9f00900781813d6f4", "MS2": "1ea665822f723cd62c46c7612985622b01a6a94988873ea67c0426327c08cb93", "MS1": "09ed7ff1127d9532856749b95a1c379e18502c3b0d860af2a15498e5f6fc16dc", "CLIENT_SECRET": "04035eda11e9c15bf4d509f4ffcbb76090b7eb9d9cd62121dc76aacfaec562178c0869699f04565c3d299572e5768759e0ed57b256ac37f0042df3ed4f83cc5070"}, {"TimeValue": 1437055595, "SS1": "1dc69d600865e29fdc80043b71485752f03da1cf7de284e0dee501c40fab9a82189553cdf36c7ef5f763bcf132f7f8808ff1d373516181b77c5ff009a5ac99ed1c12ed49c0bb004f7b99173d9396866db0c123bf3a73819a6a1701eafbc2056a11c326668a4b2cb1b725173151cd10d2895f79399b2cea8ea470eec1d3241d79", "SS2": "1f533f8308665da45dbd09d5d5c0dc61bebcb6de6c5dcd39a7c5b22adf3ea3ef15719afe96dfee4e11d47f317348854436940751ce2228e6634228d44fac61280c5b82b4127132c9d6889a948d0d989f16a7aa834f4746384f2ed38ccaee8e7800799d6038d3702949c90bb2cdfcb6908cc3c60dd3b30c4c22a72b1e123de0a8", "DATE": 16632, "PIN2": 7928, "PIN1": 7928, "SERVER_SECRET": "0c3661f52525de99a9c4cbb102681983e831100db268b7a7367023449076587311b4dd64288bafc937ace2fdf30ef4b1d7c731023920bfce3262dedf778fd91f09a4ae1f6c5d616eb62bd575aba8e6a3ebd8e53682773913be6b2454a55649e41b45e13733060a97b1b79edcbd74c0f1abc03453d6a74bafda77315885a0a53f", "SEC": "040403f7dee4f646826b02edbcd622d373d60ebee6a9007450d086d6b8a6da84a6019af96348abec81ff0f1648a92d930f2a7a866b2b410ee1609e3c328934254b", "TP2": "0406b30c5402e878f2a30533ff93b73aa33492fbb8ca702b20f6cc1ac5ff844d451540734e0bebd604b677d93e2cd020d3fc1179c7485ec119c79adfb2508db5a0", "TP1": "041ebd94d0ce070afa2b5fbe9a20c8473a59b445a11f6a1ff0e1d355ea9cedefc80e09bda676857652168ed0c585bbb88d5fef0b8179c68be5b16f523d19b640ce", "CS1": "041e9a8fc1bac79645d503fe40bb76f5762bce24f5fb88d7734d64ed3b9ce123f012816148a82ee0e1cfbadcee56ec9da6fdf2f75b525a458a43a1f303a49439a8", "CS2": "04212b0a57568830e6a2de3ca1993f58ac12a7fd59b4dbd48078ae829502f2c8fc2077e4d189fe099a5d9efcf531eebe17d8a0a756b76911c78d42cc6eae1b0286", "HASH_MPIN_ID_HEX": "c4e457663ef7be36e408722c1ac4d6b48f1a1c578962d129527872c7a68aa862", "TIME_PERMIT": "042225fd0d5ae53f228782b6b344baafd916f72196d91dfa7340f650a6db3483400f2823294a53e3c8d1e271192540430661a56dc7647232384bcaeeaf7c923689", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223236333732383032383566303837336265653435383734633064313938656235406365727469766f782e636f6d222c202273616c74223a20223432613635333136633062393939383065346138366437386332316662363734227d", "TOKEN": "041d67817e83b7818d70f5048c34fa90ebfcf74038b8dbade2c1690dd1a96fd8fe0bdee83d1939f95e6865efd3ebb67a891696c066bf5a449335e989a82ff2b954", "U": "04046a33eb3ac68eb72235948c4f949126b1f66e6a917f141a3f3d181eca84c9281939212814ac2e256dacb163ba3e66a18abdf150e33358e25afe0380ef5e77e1", "SERVER_OUTPUT": 0, "Y": "0bfa52e68e0f5111119a2ae02bb50b1a112522eb9c3c4b76fc057324d86ee759", "X": "11e1844119c80fe4f08c53bac24e22946ec4b9061866ff8d964195347aed319b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"2637280285f0873bee45874c0d198eb5@certivox.com\", \"salt\": \"42a65316c0b99980e4a86d78c21fb674\"}", "test_no": 70, "UT": "041d45355d6e81cb954f42211daba806fb3b834966f0614c3b2c3c3b8aa99071bb0de39950d26672fa0a5f8b6b27ca142a957eeb60c2cb4121dabdccba06466136", "MS2": "213ade5784a343964d93d60ac12b0be3f75d833e855e50858b3ebeb44ead75d1", "MS1": "04b2c6d3b98eba4cccc0524ef4d68c985382c0aa2f0d5bf6cd25de032739fde1", "CLIENT_SECRET": "0415488b7e0b6ea6013e85ff94a7c0f65917dbcc0db4f1344b35caf518e109b02f19a6596f58ed4cb426f06c4e3ea08630b81a727c839b25cb16015ee0a7c4de46"}, {"TimeValue": 1437055595, "SS1": "0bc7637e2c8b0d57a67b9112f09f5e4a6d08974a2fd07e352aab0e391ecb7ccf0d3d083936b5fc9dbb147ee65d76ca9686508d4227f9573665e36fbf9192ddd20b2dae65ae6891b2b62930f409ea9533703de66984f8d281a051d9589ad950060dfb0b022972f9abf07f6f5a89cd3b9f635c7fafb83082417a7b96997de844f1", "SS2": "09801c1221a9f3b18953b59c8cd8bc1999461249b3eb1533bee5c01e14fc946d08ecea4210e1870de7b36101d36284d512e5ac144cccaaf63cde763b29c83f9e1039ba4d748ddad8d7658fc8b6dc6e4bbce118c179bf035bcba682921ad7c30c12820d8acba830b8d36410deb13c1d99579b6d0451e449a91c88446245a799f4", "DATE": 16632, "PIN2": 4781, "PIN1": 4781, "SERVER_SECRET": "047430ac2d9064471eb251fdc3c26e7ec900e16026c0c09760c72abadf86ae601a12558fe287a09b48a087999b0447596aa4e2cb39e97015e07e72e9d75ca3410375294e52f6907556ee91bf5f81752c8ef2379394a55fe2687347ac5d524569203dba279b08061abb6db08b9efcc42f3fe85eeec0186ca0cef119b2b15bcb0d", "SEC": "040894f0ba10aa734342764f39e8daa634fb19f3e35d7ea74b24c3dca85b58502721d358a3fedcac0c15c2c273024e9797465568db51ce229d17eab4597df688d5", "TP2": "04170a37f20fd2edd03cf488c8de82a007a3a7a404ae853a2c566b5e0b6e444a4a02bc17e4c25a99b033ddd40f063bad38706bf39eee08d805fa9b8f757e7d6d0f", "TP1": "0416e7b5cc4f87d16c064694c4a1e79583ab0385e019f75fee1cd33631c2d9784216fb3f687b3dfb5bc20dca41cf5219720708164d8aff517d98035f994206dd35", "CS1": "0404834a7ea86b8887bec3673edc40c059b27ce0449a16460070422e40988c6d2c107cacd9402855b919068ca9b3ba59feea2c485042474cfd939d1b57fef4312f", "CS2": "041372c6f36846fe530d4f6f21e502757662feffc2f17ff96816b126acbb35922e17e46f0a148d51dc0ea3e17f9750ab8e8d5b91387b7579964190feeabbb5d84f", "HASH_MPIN_ID_HEX": "66b878eb26032e7b4e77c60afbf468d2eb930745a9f19b5d857acfac7a4fc679", "TIME_PERMIT": "04217eb24220731200ce84f8b0584b615b5de14046c35fe42b0a106827d7b6ecfd123bc0e6efecdbf6128c2b1ade581ec237c5cab9118254b4422e38e7324ae1dc", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223832633936626533333232633137646565666662633364646330353264616437406365727469766f782e636f6d222c202273616c74223a20223531373632373339336565613738653561623535636262393539626132623964227d", "TOKEN": "04092131b1d87fa614718a2a97a31623382d7afcca7c1e9b263c0829daa25b558723af3d7bf38b79ae728332d6d97251a386a0b9433c1ae9b698eca7fd92070a33", "U": "041a715d94d3606f44acfad7d2ec438a0cc647639b727a45a8ea338f134e47ad1c05bbdd445226c252e460fc950862e78bb7f3f03b89da8ff42cccaa4993cc0527", "SERVER_OUTPUT": 0, "Y": "1dbdb46190f1f0d8be9aac74b7bdc9a208fa4aefaa0fea0f1b28b96a5541605a", "X": "0bf48c6f508be743bb7e4d593c04efb3584702b605ce12967f181674aae75f20", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"82c96be3322c17deeffbc3ddc052dad7@certivox.com\", \"salt\": \"517627393eea78e5ab55cbb959ba2b9d\"}", "test_no": 71, "UT": "0409957528dabdce9b233af294ed80c5725792370e130829ba6392133cfa7c8fdb109b5d3f2ace43a07a2eb4216a9dc3167dbb4c529ccd30cb5efc8371246a248c", "MS2": "20b271ddc4a6cb5050b36370b439211dd0d4c46a5e28c47f81a9cd9bbb51e509", "MS1": "0a030dd0471e7c1879ee6339f3aea4d263e5da759c4614027e42002cf2073c1d", "CLIENT_SECRET": "0414bcdf88d9192814a081b2ee3bebe01f07c1e4541bca15428d725156f9d438421aef5a320d77664984237b598dd577e7184733a2feebe8bb858ac77f7a5ab39e"}, {"TimeValue": 1437055595, "SS1": "1f1cd01287134e7d76b276089b2eceaa8c8cc594e3cb8217ae75fa5a4107cda922050904cdbcdf4be725bcf2f18f0f4866276ca28f0fbe37f93bc23966b82d2b12cf5208e2e0a8b715a9961569263ad2144b96c1e3a269ce5a8695937ce75d0d03158dd92a470f6879467bab830c5f8bc813ecf78f1485d74e2564809a8a4a58", "SS2": "0530588a083bf57ab10913a81e4a90a610986b01a5806876404a44d2069960560906e027e1a14e3564ecf2adea33c75e6190b72d781e452a4744ac8f81ef354b0373b1611b4114e617189c1236ba66161fef064a25f1397a4df87adce92c47b80887c64b7c7647a8b532a508df47ace4186d954dce104956dc572ff47be8ea3d", "DATE": 16632, "PIN2": 9385, "PIN1": 9385, "SERVER_SECRET": "0759bdc1f4476b725829901f5cd56358ba7b3b1e51d5859d98a4e1daee86b30923fc8e5c5ca5d1e1abf335d20e7c3d7183e3ebc92b42a18681c08f528854bacb044ae46780b50e6017920ea76aadeaaea10668c6a3000dc97d131a7687ca664e0936798a224f3a3a98b22579eec384cf6dd143da31f1e84fef172bce9a720901", "SEC": "040ef29a9a968ebcb6e78840207aa13f3f1f0ca47bb4634d5fd8833b8a9ddf2e22230e80b98c15e21c3d6d1c667c849efeff70cb2baf0548a9038fc73b264aaccb", "TP2": "041ce54b5be92380e9d283787e387fb724c138ca18ba8092c9126527c318d845eb0b56ccbe20451c2803b19172d505c83cad81692683dd61209c8d76091c034a9f", "TP1": "04126443ba246230faaf71151c6fd6ee4984e89d6dbf06c2e505c42e34d52d1e8615cec1e54ab7c7b5c20858ec37383bb5de6654919d9805b7b2b1534d2891771e", "CS1": "04213ff60dc656c26582c97083393867ef9171cf3bb01e6b84788afabc55146c48175cf8c527126d3288e3bd8c3480eaae8f7559cad44eecf1bbf0676751ec19be", "CS2": "04112558f378412e47329d9fe606cbd2aed63b4ebdb8d0711519c223c82fca37cf1423eaccd4145876d78120634dcb47c693da94b0ebfaa92a903f5d624d5acd5f", "HASH_MPIN_ID_HEX": "75bd9a09558e13fcf51cd41e95340c29600cb574c014515c403b958d658cab26", "TIME_PERMIT": "04145a8d0cf2d5b481d294fecc6fdfbde71b582833abe8c46ba101823bd7a338f50a07653a6d4c4fc17d504127db84125a67edb9f1bf53d0439589f2d60bee94cb", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223730613630376639333736613234656233613335366139646362313764356438406365727469766f782e636f6d222c202273616c74223a20226231356362653934336631323439343030356330386364636132353830383034227d", "TOKEN": "04067ee83c866882467813f92db6c1c468a8e0900d6baf06c256e9f24ce1fe36f90a2873c1971102e647921bc31e274967c82add5a760efe8c624386960429c0df", "U": "04087a70ceaadbdd9c2d1a41ac58473a0396c8e216f487d62d5cee429ff156446f1ea92e3bbeaf81495cf254339f6bca67c26192c18e9303329b01a3714a074403", "SERVER_OUTPUT": 0, "Y": "161d3a3f83afc35f8c227ff96822c28aa920dfad0249e8988e769f932ee9d98e", "X": "13311bcb72914e359be8865e536a5a4e7d8dd9b5867eb8351caa3c70fb53819c", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"70a607f9376a24eb3a356a9dcb17d5d8@certivox.com\", \"salt\": \"b15cbe943f12494005c08cdca2580804\"}", "test_no": 72, "UT": "040981296b66b2777e46141ca7cee2f13acedb0dc086271042f3e09fd871355fbb1f1c91abc4b577d7782bb723394eaceb53f4d59a22f472e531b2315ce1337c70", "MS2": "1405b3e8c5e5070db608f449ccc7039dd8fe13db90f50f0ad21234f26c72d2fe", "MS1": "1257d346a11a1ce02fea2ea4c4f0940994e42fd5f6b4ce0193bf1d5f81d2f4ee", "CLIENT_SECRET": "0400fbcedf0e1ea818189b27926b3a5ca2937e365fa30febbfd491c55fd8096dcc229f4b15209aefaa3799e0bbd8adf230b10d212e81d6a02f88503f3478f03021"}, {"TimeValue": 1437055595, "SS1": "176a6be271e9d4eab197763d86a5edfb02c8949002d7ec088777372e3efc53dd067b52045f8456d1cbe717bedf6c14f3a551c57019d2af0f0472fa31dfffa62a08584e6ca878836b4dffb2490c245131623633b2f494617311c40a7fcb3c1d521ed6eb3eaf8d0302a46e6b5e8bc7b702c7956a73092dfa58e6afc7ae3e0f6469", "SS2": "00d5c532cfb0628655e6af9a3e27ac787c68021ff96c46dfc0ce76b4daa14212064cc2c087110be6174dbf330da3d55476fe56156e49d1725be36713fe8b433813172b6e91a72b5942e56b15dc4c2099e61dfc714a02971715c482a47c4a70fc1532e72414fbe1dfff3306fa5784b4981107f4f9e5044b20eb39400862fd9036", "DATE": 16632, "PIN2": 2941, "PIN1": 2941, "SERVER_SECRET": "1ed6898dbda7fb42c292a488cb3b3b2900f22a7cf476bb438e2b7d76aa28ec3305b9e6962a63aff2c9bbb1ad166b95f2cae9ca2b01e58c7577fd7c6d101f1dd70a7fc002b414c29a72c076194e26cac8ed43267ecb60a9baa7ee977ad3fde66002d6cc285a5264ddcc678d6209029670b67ef093197a5ace49a32090bd35f68d", "SEC": "0408074438446265b292770070cfb03dd7c31c87888698412cf60ee0ad73629b7421e9870f5f85c91f7878cbd450fa0352f39de6bd3ad06dc3cf50198a81238302", "TP2": "041c1bf05a7713dd1e4c2fb76da584f7d9f7be8dd86f903be9122b3c90d32a241306e851c3032a2e100f7aa90e415b2fa6e93680c397c39f79eb64da34f7fd8692", "TP1": "0405f90879618d1de4f4f453b7fb002ebddf3ef4603dfaf7c4b1e0c7b29eacac9a2094ab7ebc0f687745b5f642afe8b7f735f633e87bad2af4e3d32f353d9001c0", "CS1": "041d5cae883ca2309434dbcad14b6f9fa98d747ba1b0eb855c58ccffcfc7ce25320483aa573f2efa4b29de945ba517f5dde45359102c70e31afb8fa5d0b1e12b8b", "CS2": "0402a996e5170b9898ffbe67f85b35fa87a5b6967e4f4afc34b033e7fdb9db785616338dc75a1a5ba893955abaf9038835f7ca14ace70c40e33c77a841875e5037", "HASH_MPIN_ID_HEX": "3a76e3aaa88ae4f7feb14fcfff6913bd3e908df2d15dea69d158f6b04dc434c8", "TIME_PERMIT": "040016193ee5773084eb154dbb85da27acf77681acc21bc6195e11cd7e4f94f56a1055575ea041bcf1a268e89f8a89ee1467188094145ed35393844fdc22e63b6d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226638326438346330376366636333653638643963343463663561386532383833406365727469766f782e636f6d222c202273616c74223a20223937323064353031336534303239613435363933353764636432623133626465227d", "TOKEN": "040a2cdbea9a1dcd92044552598aa5c14359d9c63daf0f2fe9e984313a77eae4db00bf12c4bde6908c4f56cb916c96e967a93e8f2f5b04cf5088fe31b4818ba693", "U": "040cc2ee4cf4d1f3721481da2d2ef20fee019b5929cf320fbd72662c4be80191bd0314e27bd3637bad041e87f507abbc0aa40c90a0bb64d291d061abb677737d54", "SERVER_OUTPUT": 0, "Y": "077edd5d112df898f9a1bdd8c9cd8c552785dbd9cdeb4fdd4c7a39536883edbe", "X": "1cdf0c7d96b2661765061a8ae5819b80c989630db704cfa990b865f3f788829b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"f82d84c07cfcc3e68d9c44cf5a8e2883@certivox.com\", \"salt\": \"9720d5013e4029a4569357dcd2b13bde\"}", "test_no": 73, "UT": "041831fa58ff9e996ad80c6e3bdd3adc7b2a3f3228875d625f1dc4b0ab7c56c533051fef8cfa01360e00ba87ab3176635ecdbc834c3822289914fda17ed2b601fe", "MS2": "2277a05523445c3a4173952b62471c25e04e12cb563449f3d655b3d00ece2b0b", "MS1": "19f9d2dc0b42f595f8e07224ca91efd537785bae939c828e4b9329929fb0e0ce", "CLIENT_SECRET": "04225235a9864868a20e1f69fb398c48ec3f32276a83cde9a7d29c919eeb9fbecd0e26887fabcbfe812d1af8c49a859311da772d029de40c23da6e0a0df7ee4505"}, {"TimeValue": 1437055595, "SS1": "0582f7fc41b3e00ce2ea0c1ad29dfe42eed782b77703a28e9e032f57c27f14d200b5b2cc2cd1f3f705c5f0a2bdd160ef3184319c6017861a30bf060ed459742b1c59fc46655aec2daede7c7531c0661b91a199215911abd2b69683c726d933fc098729500c9e627e7d3351472267b09a2878f2e5cc24355272e7c6de8924ab8b", "SS2": "0e3155b45c95900722c64bd36e2d3a597acabb5c1ca56dd5d64c9f4a37db5f771da8c2a229363ab0190319727482826b6ded3493fcd6f9946a6c0fbac345dd260d925cf29e0f14b97b08c1357753b8ebb9035ea4da61fe95235441115be572d21a7ccab66835c622ead6ef0d2cd97c1d7ccd0152cbc2a3b9a6faac9eb9263dc3", "DATE": 16632, "PIN2": 3637, "PIN1": 3637, "SERVER_SECRET": "0084b883c49b8de7ffbdfd82dc2c474c0ddfa906ccf7d9edf516ccdadaddd7e512c1667fb1c81574408a5a514f47bee9d09407155a14efb5b9d401f39325e4a621c9554f39dccf45479ff8029e465fde80cda18873acf2a6268e2494f993dd8a22799ad4aea999a1d0f38f1e6ce244440d1d12965d409cb973704d1b0eaccbed", "SEC": "0403954b96092825b6bc2872efc1ab8b7510713903579e2b94ee3836bc8910d716068febd09c8d878f2e6402244763f8af4328dae61d08e524ca11b069741043e4", "TP2": "0405d546eb80f4a08462daf1f97df2469ed03e409c89e2fd6c5201afe6c03de8e413e44675ac3404233901057a218638a5f749034c298fad3a9d0958689ee73d33", "TP1": "0417065f0f6ab39c4b2cddfc6c499efdce1a5376cc6d06966d897a63d3839c546b04bbc12350bf31118318ac923baad7d972b970c0d5b91fa83df47a814c034258", "CS1": "0423a20043403ef8e03e03fa9a659c59fb1989680393b9f34fcdc494926a71196e22bc2a83a95eb458573cc9ea965694013dfa0a16a0518a4da21af573cc2bd3ba", "CS2": "04193130c30411f57e07752117530bca614de8d68e759b740999bb62f08859cedc0c5ab149da92a259c41e62a059d7aadea824382f9c28f58ff54e6bb16f2a5dac", "HASH_MPIN_ID_HEX": "c02c1a63880fbb79fc9b61dbcb0b34efa828a2c7f1563dc0f05fb4cdd13a6af6", "TIME_PERMIT": "040d1feb2a7d613fdf0f4a92b924617d1bc386ac92b145c230229d9b2660ea4d1e1434206a2b384dca54f5acd6c5a5f6f2c11552d14271000d804062e569ca8645", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223365386235393439613133323133343037383534643535613966653961396538406365727469766f782e636f6d222c202273616c74223a20223030616539396363343664333731616264313936633232393266393933633231227d", "TOKEN": "0404483ca89c9eb6db4862f556005ae8247d38b6ef8a873247a27cc635a4fce580220ce7ed6b0b6db1b62ba368a7ba19db3b0e2ab02ec500eeff1f4b6ebd616b2b", "U": "041a44cd1ac49ba2423ce2bb4745754a9e932f1dc0c4993bff036ae5888524cec3123686836ee371e444ebe9fcb774f3a6028d03e3def8ed289472f84735a99ac4", "SERVER_OUTPUT": 0, "Y": "1d7222988c370a467caa0bd4ba24e18582216b6525dab4b9777e7a411d2ef492", "X": "0ce41eb8f59503ea58385f46c5c3878485e2421220c50bcb6963606fbdcb085c", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"3e8b5949a13213407854d55a9fe9a9e8@certivox.com\", \"salt\": \"00ae99cc46d371abd196c2292f993c21\"}", "test_no": 74, "UT": "0402cbaac158da514e50e516c8c3672b732a1615f03bf5eaf1119cfa2c6075529d0a900f18fb37d7e2bfd6ddc41b1b57c25b17d25b299e76670eebfcb6e3265d05", "MS2": "1ca7d4517f3148d88b8fbeaf223e98bd3d11b9e4d3cd87af778b9c8c3a02cd05", "MS1": "0491120046f61898b984d65c56112db16318289375a94c5a347482493ee90502", "CLIENT_SECRET": "041d1a3296b45895f5dfe7cf36654eee86f8e5aeec38c2969ec693b23b715c6e620d601e169d61dc2b66ae1c8247ff812cff1c48518fed61cd6b9d0bbc55ce11a9"}, {"TimeValue": 1437055595, "SS1": "03665ee3daa01016e738640357e4207049498a53c8e545f8c8f8c6cb5fc3a2fa22869fcd9a4bab7df57b2c9d41b5b2d6c0bdbd176b47d937295761f074cb80330d3971e74ae10ddaefe4d4887993a0cc68305866c660d3641b99a2f27761eb3c039326f043df8b912e48bfb63c9fd1cd2189fe3b41ccb41ec212e9b02845dae1", "SS2": "04d4a3e1b916a1eecc2298c6cbbd22fe225f3bd7f182b99d9618fd7346f4f6c11e6d5a125935c6f49297c06d1dcbd9adb6ee53ed47a5dee2b3569f593ec139500df92fd6d3bfab9e137f0c1d3a744dc44a1b43dfe425cb1dd03ffbd1ff7ddf590faa75d43b4b115bff23b6c6610c996355e087557c89699727e165cbd374aef2", "DATE": 16632, "PIN2": 8914, "PIN1": 8914, "SERVER_SECRET": "18263cb384bfc389e3e0ff87174aca2fdcea70109ac85ef3f6dc4c8e32d2a6df0bef98d120c04698b9f23b03feefa4dbeb742e380310eeafe25cc844b2540e52176e2610902578c079966a1b34a6329d813b6ea10fe53dd53882a7deb7b3614222cca520d428f7584c023d4693551b9f487e7cae25f016dca8bd0a45698badd6", "SEC": "040f3aaafccdd4bf593c5ac7b97f29347f09bac808ee042c8544d2a9d3bdcdf53d05ee64b682beabade539ec6fbff75eeab20a45e255ee0627f5b1fac82637acd1", "TP2": "0416595dca24ffb33b9a2983f655e1ae18c155ededc0631285927623910617f77f0711bedaa78fd3d28f541ce9c613b7cb41fb9937a9400fb810c2f40213105948", "TP1": "040ee34c74b93eb2224af3c20631ab4bef33266917bd4a83f6f096f0ac1b5270a71d1d95ffaafee0b7f8dcb01986dfc2c81fb73d2e4a04110279b19d7000fe3a6d", "CS1": "041c0ad777636108ca862f01beea3126dd5ae7333e77bceeaa7c7847a0ade4816b1dded9d76e766cd99b7e0b01a886985563d8d43338ba1b74951f58999732d91e", "CS2": "04080376de837307c96c97890d1ae4330a6e3e02407ab8c85e1654cf70aa30a1cb22f105c5b08f952b80e0e032ba04fa377e987a0e78c310dc8f88d4d907a7ca0e", "HASH_MPIN_ID_HEX": "ab3fa339c4f68be267a069f57b03e428a09d1501b99c40a9857d566aa21faa3e", "TIME_PERMIT": "041fa91d4831cd8bfe665c246280a191850205b91aff117d2ec0dd75239b523dbd12cd92aad4810197b48c9b94567890763f00c76a6b9ebb429278f78530d052ba", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226631373636333736636261303835396630396235646462623339343162306639406365727469766f782e636f6d222c202273616c74223a20223963663266346431306536643832363963366433366636346236313039363131227d", "TOKEN": "04122d2523f2ae2dbb55ec5adb1d243105dbc530c5bf97de0698e3165d2535546b200b75287edfb2a7d32a99d0a878bfdd0c0b6405cdb1de0f5dbba2fea38e1630", "U": "04035fb2a237771e7d8cb5963870497d1d4580932d9c7de72fe17cc1bc6c6569c8063bc16b21edf46af840db9ebcf6224c794ecdd09ddd932d55523ffe464e177c", "SERVER_OUTPUT": 0, "Y": "20821766c597f1c814c7ebcf3736f552da6a9dbcf1aeae6fccb881de34bfbcf7", "X": "12be3251f475ae30d5598cccde5956978a11e21e579b2fbbdb488c5e5295f852", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"f1766376cba0859f09b5ddbb3941b0f9@certivox.com\", \"salt\": \"9cf2f4d10e6d8269c6d36f64b6109611\"}", "test_no": 75, "UT": "040f871f5f7ffb812b593a68915e462394b9cc0457e8c58c746a0822143848287a1d1f1436a43ed975a106f9a0affff707a2c3497201d02a5a9e64a8641199c512", "MS2": "130b50c14ca6f3428ad31e23c374534d9b41011767f3189942a4fd5a91a783a7", "MS1": "1cfe19f418fa9128ba45f7c8aaa0ecfb8db9fc4b5f7c03c51288d02bcd103f00", "CLIENT_SECRET": "041243f5efdd24faa380edaca2a9f36b2e5f00935e06d11e735c442106d2f54e57034854231bd0c9eb1a701a892e61cb7fb8ed19a7d6b9abfcbb831d4d63bcfb4f"}, {"TimeValue": 1437055595, "SS1": "014bef385f3ae9c1c1bd3be2288d86e4559057f1ffceea7054eeb2d0f785f9081dfe56f3241e4dcd5ec04a39f062536d82306567be7b85ccc5644086062550640950b3a356c59c3cab66418d1bedd3ff3a0bea6badf92e7f366b9a4adcf53fd3111fb257ca510a7eb66b5ca7895566c0f49506dd3d335281afb865c3493aad5b", "SS2": "09af691fd20a904972a761379b21343766285d931b59a426a67a19562fd288c4239674d172f655a0c9b3782f7b5e3d6adcefd96b9f33ddcffceb8f775c42079a105ce6bd8a77fe204f5cee2649df7810a7fca37a69b547ef059b9fde706677bd0a1ede725d31c42814968946318c3cc6d489848771a7bd0ab915f90fbed75252", "DATE": 16632, "PIN2": 448, "PIN1": 448, "SERVER_SECRET": "01f63bb8f2fd887ae9e5fa8d7adb549c2725ecb9f040b8cff658be29bfd70e5c0f9bc9ba89d261f4a0fc20b7533a5187bfa3ac84df40422be1e86e28859010b2058e947f3c2667e7f0092aa5ae7802a3246c5449ba67ae3afef2166de64886e708f8968994e63af581c8d8498668961d8c27ba9285973cc36abd77dae82ed5d3", "SEC": "041ae7bf73d3637331097661a5c93cf248bcbd8a1ac9b1fee23e8f1df56f69e92d021b758418c95e7f76e6f61cbe440807200659caf26ae6d30a904a30f33564a9", "TP2": "040b7fe1aada81727f65bc8de2fb1af8abc3b0651fa86c934ba0154bf063e4d3d91637223d37c715da7a045ce9121cdeb85569215cee28bd16baaf25a8114d7e7b", "TP1": "040c0d1469332b6900b9a5a1b454b339e0aadbabd0ecf2bd92fc28ded187cc83b604161d6d14c1ae79df6345b5f135b0dd38697104ad3bf0b56d32259cd38e390d", "CS1": "0400a01ebe1d4912d4e9aa511437ca0db8eecd1288b37f9852424801373802b95f208b763763047dac326ff8007b92028d4efdd3eefad4c10e24572f158b39cbf5", "CS2": "040e66914d24ee502e83902336184f92b13fcbe08cfa1f7b7248e998a4f838af2507024d3b531c632167b0172a5a006247931cf94a6f3415d587cab55d46aa72f2", "HASH_MPIN_ID_HEX": "aed840057bbb09e67770cc1cf0b00a94a0774f2c9a7b6a93fecaf3361c4c62ad", "TIME_PERMIT": "041e91a8195b5d45ba20a1297dd9f48902f67f887317abe6f7ca3a45e9ad229ef5231499e820b554ad7a20195378261fe2582554e96b51cae7a2cb3aecb4b4ac61", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223339363936356633393736663338633932646131313061333961356266376337406365727469766f782e636f6d222c202273616c74223a20223039646564393035323162306466383631303431653365303733373562333332227d", "TOKEN": "04184dbc1bbb7e637f852d6e80e292176591311bec72f44b40e5540f06387b43d11d7c88d1af87dcfbd9ccc88e7c5fb5dfc01dcc61c121b6432eb196ddb96c0066", "U": "041f49173392575d069ed2060739e792bd8b4005d1597ca7426d35bb02ebe722610345ee70427cacc8ebb95f96a6581794ac1b344f352bef16137eb5220535c219", "SERVER_OUTPUT": 0, "Y": "1cdcf3ad34d7afcf7f36843e84d8237a0895ae9e30b0bb03930eb209022c60dd", "X": "179a10244ed2c2433da4cb1cc3c9f1017c72f1d9552167adcd3a4101a7758bfc", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"396965f3976f38c92da110a39a5bf7c7@certivox.com\", \"salt\": \"09ded90521b0df861041e3e07375b332\"}", "test_no": 76, "UT": "0416ecb70c38d47dc7acd1238e3f468dabb7d9c7337f8dcf53d61b3eb64179403510b55441c3630f4ff1d2344bc59662a63dcca0a20e0cc31adf1ba5459d37dec8", "MS2": "0f74432d783451c7ed650c666c5a0477da22bd884421d350c763d40d8049a9e0", "MS1": "0a33b025de142da4c87c27ea95b9a92cd60fa515dc0bc6dfd3933d0cf314e627", "CLIENT_SECRET": "04143b262267230f6b0dfe9c652b2bb9d929eaba0324f30cde8abd76ddab821397182607dcb2aa4cd8bd5dbd8f88b60193dd046527b796814845e0ff31e7eca018"}, {"TimeValue": 1437055595, "SS1": "18750f4f7eeee1fe0408664ea8120b4d41b75b3dfa9f74ef62c9b52c80bbaa7721b5a4b9074cbae0e38b97945905cbd06a00744e8ba0fc08e2cdeb7cd2cec6e4037f97e3e19afe0d2d7a40fc6c70f2f706036de7aff9330f0747ad0896778884166bd2e8bb62f3a9f3340179cdaec1acc25728601ccf92e61c0825e1d07cd7ca", "SS2": "1715ac3a39b8d134c87ddff3494d7cd70795e622903ac15773eb52ddf8cec9421e29b0aa99c679f77ffc363389eff908e425991ffbf1e8e9fd6181679721b6532255295cbd71bf1d0e579a1e0affd225385feed7b6fdea9bf45f19dac13a479b00761bf0e08d3f208d520d8e834b2dc1ade7da9d93de5a5e4acc7f2f206a4dc2", "DATE": 16632, "PIN2": 9772, "PIN1": 9772, "SERVER_SECRET": "0eb8c2256b02695f294e9bb8d39cdf5d68ca6d971ccdaa8010844de7979b848e19f2d8a78d1b35f0211b6db579fa21f7f24c1d2e9ab1ed998b10c50697bc12f0172f74f1d972aa61df1a1851b2ae4773822476db8685287bf8f3cd7c6d456e861b8d16097b4d6d4a62b7d6b6ed7a4aa6bd0d5525247125d42d376a73f0bf8a6c", "SEC": "0421b4a9166467b6c2beadf2973d588c9c8f9c84a9fa0ae826f31f380cf966541f099b0c49d44d23dc4225897e9ec8c21153b01f193ca6e4298cc50ca0a13adb1d", "TP2": "0406ab38c659f1f232e4c72dcfe79772dfbf4bebfdddfdbee265e093247a251a6e1936e25dff91318cedbb4a584a73574e9dd110d14c4d8c8c003663078f224552", "TP1": "041d83b4b3930872df424fddd8161f1037e5d4723021ce5dc2e42a112473ad9a3b0f5ebbcce1cf7fc20d30436583ee22651b97ad8e6b05a81aceea7841e417259d", "CS1": "040b76fafd1c4323f3d296851db008cfc8b48e7e4cd638be472ff43c3d757c952b20e7b5a16d7451e28651a21fdf31bc8fc7a43e6ccf51e0075d10b38c182df1c3", "CS2": "041c51e184be9de9f06940cf3e4c13ac83787b46fe84444277567c6966002a54a10e29c10083acb33abeb179f6f56790bc02caa649085fc0ca71216393716aece1", "HASH_MPIN_ID_HEX": "379e49c5d667d34e267b394a4ac2456c7c7b3dbb8084e476386d4b665c614023", "TIME_PERMIT": "0418ca2bb86fadc730c3d80b70d8f207a1c810685ce9370e19f3008c72198e37d9083670dcc92ce303c045b97ea2eddc6eb58c392e2b9a4098ca60a78539894063", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226466623765393566623834663764616334393763316233396536633163663539406365727469766f782e636f6d222c202273616c74223a20223534663366323064356363353132343937306239663566333639386265353830227d", "TOKEN": "04235ab40f0b9b4fe11aa2bd5cb49dfa14db5a496ee8091630f4dea9f323fb83610831b7c2341215fc0b3998a4541977ba3acd660a9199a0bb211c3b78e668b4aa", "U": "040f0e1674d8549330db161727267c7685686f3ea2110c5303728d812326b2870b1d1e8b5849f3bd86eb9db27ef21cbe0b56b7e4619efd8a3dffbee943d27025b4", "SERVER_OUTPUT": 0, "Y": "08b2f2e79cb6f78f87ea027091ecf00e152e99231319495908900c4207128dc3", "X": "053460bace17b39355aef09f882ce2839bfe42d1de10c1792f4de02e4feb183e", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"dfb7e95fb84f7dac497c1b39e6c1cf59@certivox.com\", \"salt\": \"54f3f20d5cc5124970b9f5f3698be580\"}", "test_no": 77, "UT": "040aaac7af6fd82339302618b9557372fd4e1c96e7468997474c87706f57672a1b07904627ea485401eb844dbdf1b3941f9927116d7de111f01ba283ec3db69282", "MS2": "03163e72baa5d8a46037e9fd1ce8fd9fc264a4429996e5c10e933f5c77043342", "MS1": "0040f0c81bdfb514425218367a2235ca4f327da814891da632f09186e6bee69a", "CLIENT_SECRET": "04056cbb49eeedadecc10a5cb4ecab4f0a53541920a15c8d6f2218cd4d18da6bad1669140d1b01be6b65cfd579fe3f03471dc180076f3ded3468f7985d08461719"}, {"TimeValue": 1437055595, "SS1": "1f288c258a6adcb96bf1386145f748943b5a05e121bc59114039b85c1dff125f1c95b8d7a897d0019842e67e170d36ab6de8414c931c564f517251fe7cbc39551fbe29186b4306b7f5008764ba4eb769637c0160c6abbedc8005855112eb9ca00861fdad42d2a7a623ec6915d0678e4c8839d0ace883d80fc2d1658e086f1063", "SS2": "06765712c78b9e21ac8d19e9a95831615aec8bebf64a556aacaa32ddfaf9ed70089c19042a1fef2b324dfff22192bac6fc4da043e4d50d3972b85db4e8492b0c10f7165e706a58be584b934a3bb007e21b4730c45c1e3b03ee538a7fb82fc8fd090ff8205f221c20ae1cb6808f18a7c517456df1a6e7b5cb6bfbdb8f0d5b4d77", "DATE": 16632, "PIN2": 4233, "PIN1": 4233, "SERVER_SECRET": "228db6ceba466510c046b26819606f499b2d8811d09ca6e9e8eab98b3ad3419f063ad107d71c077490a927f1dc8c970e071211bb4dc88d2b036125eae6b7454714f0c0f9041ba49df7a2005a37668356fb6c43aee476d07d2c046ff429a62d4918a2c249ae3a7eb43bf24c23a97408f91b60c738fb7ceb54ee4a866f85bd8991", "SEC": "0408903d8476365cf731d49a14322f8984abe79bbff5a8ee4310543e620af1eee30f0ac82c2189ee67605bef4974505ef6136da638f15efbc2856ba9b7c3de353a", "TP2": "0402b958f57676dbdb90368bc710de3b83da7352547da8af6716e441af59bcd80304c637c3dced78a9c05d8573d33745e77a6f73945c68c6d5da715f1f2d7bb7e5", "TP1": "0410f9448e49b6749a694647bb7c839f819a6e6872294ea31c458c71f3da0258ab076dfa7708f045fa0b217322e79c14369d8e6d54d1f647f3ce49b59c8a9fb455", "CS1": "041fc878793a357902262baacc671c3d42ef4e165531cda6b92b62d027123dc92a0ccbc2f8cab86260868599e1c25dc60d182e8167b5359aa873caed59477a240c", "CS2": "0416147d51a8c776b122f09ea652edf84d0c593d9227bcb2d488b147e945ae011321aac1ff6afb9b242984bbfab32bf835cb06893041f45a404803fce9493262c1", "HASH_MPIN_ID_HEX": "a880193bcf5d5cb7e39434353155258524531523abc6f9e69179a804ed3ff7c6", "TIME_PERMIT": "04010f0c3cff43fcff4a99b3204135de51b55fd81bff1a30a61db91fd9c50987c113ede68c7259886d5de297a135982eb1e2f2f2ab3071d7ab8dd8da621d0460c3", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223231323939353132383832663835623730313435383563656665613366353665406365727469766f782e636f6d222c202273616c74223a20226338383263323538316235633939336632366363306335613339663861343763227d", "TOKEN": "04209e774b69d606183d6c7c3aa496ad9e8f800b5e036ad444ebb035ac3f6b1ede014694283bba694974d77bb86125b7f3437b67e1f4044a034d7d0fcb34972576", "U": "0405889868a22c3bbaa3b3fd9f32e1ccf00ea572eed9026f555f6ab681fa6d7da0071ae0414d0f8935957e21fa722b048a5252dc92f48a9a5fb6d228137d9038d0", "SERVER_OUTPUT": 0, "Y": "0391d4f0986fc72b0e584b40c71735366f413bb5a89f1ef672a13e717bf2b175", "X": "12d607fa84faba7edc8599b8a9eec4cd50f20ca500485dc015c4527bca9a11cb", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"21299512882f85b7014585cefea3f56e@certivox.com\", \"salt\": \"c882c2581b5c993f26cc0c5a39f8a47c\"}", "test_no": 78, "UT": "0420a1422e0b1d18efa57f736c436451738553342c2ab994d3b7277fb7212b4d532114a769d0d06eebdc22cde865488d91f44323a1e343309c9d95865b7f4b95d7", "MS2": "0fbfedfcb4ed0765cbf76bd4b89b1a13a3837e592700229ab72f2e8615403189", "MS1": "0a5dd2e5a5e4d61cf8108092058e433a0af6bd530d5bb6129a51cd2e591a0c78", "CLIENT_SECRET": "040dc20047f0defa2aaa74e0a8361167826c13a4a587355c2b761dd567c92f0f51035d29306e87e70727c63766b5af5a004b54e1dac83e3b42f372e998e6e89ea8"}, {"TimeValue": 1437055595, "SS1": "13577405ca599e37a28228ed2484eda1000468aede65a709e53cc334aaba258617353706b4f31bdabc2c09b11d9fc67511ccd83fe7f6f04e29a6a79c027756250cc138f0f13319475e775638f51a3c7fa8c461c0626326d04016fd668f7bccd807fe34c35fb0d30de389eb90a8b6d0c12956909846577c7fff49cacdf79473a4", "SS2": "09ed33ace5745905668e2f14c5eae11e5cfc5a073337c19914d5ddbb9a3838fb16e07378df55186fe65288fca6245246777486697e2187e6aa0625d154b22e7c0212f0f9bce451a4e1fe17ccd983138636e732653a9efd9c73b55c1f5af34a2119c3e506015e84d30567bc8ef750eb161514613916d259ecfdf7ea38228e2082", "DATE": 16632, "PIN2": 2174, "PIN1": 2174, "SERVER_SECRET": "13dba1589935f997862c286d943214cb3fe98cf24ff4c50007abbcb8f09e473c0e1dc65fa3cb6d0b77464086ffe53fd425747aa30819a80db4f2dfa224cf3fd0040bba1da7217a0fab40d9393ce5699355860faba5bc9d91c5877b4524f810a315b7dac32e996cbe4804f79b2b9159d2c52a1dc3149915d777d517b7e127a383", "SEC": "0402cade8260fbfe98d5132572e1bae79aa519de5e208e28a075dbc451f9a4e59e0a9227fbbb9692fa38881808c35202a21a7a3802ef42b6a7b932aa54f049cc33", "TP2": "04058f027383ef93e7d8279d08845007e62cdee8fa48a5976571fb18b60bc38e8e04751514bb496c65ecf2fe1a62f502310c6f8df53d27e287b80db874b8fcb5b0", "TP1": "041838f5552c88020f707abc63ba78cc8cc044770bdb141f4cf000ec6f21b3646c10de623c4130eb1f5aa2d89b1e874c1268c4d6295b2168f4e8de2c41acd7e360", "CS1": "040c93f531bad93f6d55dc7de296eef07675a25df5bc7f3d28d5c26411408213e606ef5b513b1c7f6eb595a27a2d6bf34e24e4febaad995955a69e744b5e101a89", "CS2": "04036ba43a387d7ec7ff7d810849d55ede70262c5873d3b7e8b455a8e8ee6df5fe02373d54d5080f18b2a82ae5bc2a03c501264e555d3359ee4813564b579058f7", "HASH_MPIN_ID_HEX": "4f897b532a509331144495de0d645f848a114d0ba88363ce9557390be9df159e", "TIME_PERMIT": "040815c7461867ab0dcc6dd3b8da4837631cf759148f4c3d1f06246346e83f69610be044c7bde1c6cb66a4fc032e63633b7a36f4e33c1175cfab787de8e952746e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20226430663664386232343037356132363535643430623636366366373035356565406365727469766f782e636f6d222c202273616c74223a20223364323132306161393133623833616233383832366235353336646662653964227d", "TOKEN": "0400cc68af0e4ebde168ccc404e251a1284f327c4c529d0d32730b14e249207fc71fe09d91d74e8398f977be79d22b52fe485734cbdab193302be857614dcbbab6", "U": "04091393f28ca834073db01ab5e9c3ec0652884f6974cc74ef337ed4b9f36258971886f4cd3346c3adc71eec3884732f509239074a50d1611aa8192763b39c4ecf", "SERVER_OUTPUT": 0, "Y": "02d54ce9e66152af30aaaf18a44b1adcc2b950149f5deaf055884e5167e43997", "X": "0a10501b227e36afe7960d842583a8e9ea5f5c8813ef4b3542554f831771ac46", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"d0f6d8b24075a2655d40b666cf7055ee@certivox.com\", \"salt\": \"3d2120aa913b83ab38826b5536dfbe9d\"}", "test_no": 79, "UT": "04092068c7798aae3d55b4c83cfe03fd2fe6efee733221f3b41ac0d4afc68b8a901817d1557cca8accf6b718c9179d4bd25fe3c8d92d4153bb42934ee14807ccee", "MS2": "0ee60b09cbdd4b538621c75ef042ba3bbe33ac54ab8485d0ca84c006bfa4b704", "MS1": "088ed2b8a9b2bc763fd8515c3076315693fbe0ddc7e0aeb13e4815bfa6ab3aff", "CLIENT_SECRET": "04077768e9026a73b418471ce9df7940d37fc1c747bd38e15be23db8e5827e2e9a0325cebd4606ecf44a4985c09df4909c0608c92042e2f7c5f78a5659d274e23c"}, {"TimeValue": 1437055595, "SS1": "0cdc019567564746951f565c96bd03790bbdca28bf3030b85382a11bd5a274462193147279d912d978a2140be9f1303ef60276d445d54c516a089fa28162322015d7bad226dbea06b9b16e4dc80cfda19c5412d2583d3938e98e19292c334ee8066c39763296238f3a384f77f54df6efcd2327486a7f43f5231464cbf7cfb497", "SS2": "143f950e63a472ae28b848e844fc56292c03a9eb73fdfc4c2c4596c13817c63e030314f053e8cbdfddcfe637d2068b6145e4700377ce147a6f5abb2556994657095ada771be7f682d6c7af6fc044baf71da9793bfa45a7c313916b840690cc821faa10dbd63713a4f1e3da1bb6c594b48bc80af7509339d987aafcea48a610a6", "DATE": 16632, "PIN2": 8887, "PIN1": 8887, "SERVER_SECRET": "00a5c5ee3bdcf0b911ba02adfbd946d6c652299a65b2b1d14ae1c4e70153631023bc79a201380387b4fb8758c0116cc3262111c9ebc30b1997a9ea6860b2a8fc0c705a4a9a57e26fcf2fdc3be8c8a48f7c927693a95b92c931dd7ea1f2fe621c0345595c382379673d9313750a0f444ebe9bd0c37f097eb9d570fba5d58296fd", "SEC": "042302827ecb1c091de4091c90e249003d374529cb3fe4e63cfc873b5469fd150005f3dbbf7fbbdb81f651be8ecbc0aabcf17ebb4629497889e962b398f6d0966a", "TP2": "040bcba2b34ff60484d9f377c7f15f5c92d4b52f90cb1e337a8d28402a28fba177182c0c74418ad9a7a445fd437d2b9313451a09d5d111af992b5149a41bb68f93", "TP1": "040ad2efa9bd69f333f3ddf52171f0ff0f8fe320b8b2aa9186859946c6dc4d721b1d40bce66d903f1720b2b0c8e0ceaa6ec29ec0d25ea2f63b589ee74833731b1b", "CS1": "0406d1ec50c7372c44dfb82731b991e9f17ca0205a7d4362ffaad4692d0f8841780c0b6fc2bb07a94b0c00d46a9ac1e57469833a91acb3a14f8d1b7b507f2a1518", "CS2": "0419a9bd04a0e15822594bcaddc649a24847a9fc448d84b0526fc2ab3050a12f621e86dc5d5d971065c8c570dba333d554373a8cdf245920065956db44acef82ca", "HASH_MPIN_ID_HEX": "77258941bca2c5268ba13b4ef2da76965638eb0d725f1ac51e771ac3e9460c23", "TIME_PERMIT": "041310789f6291d6d459cd8173c298fcbca822ac7e1d2ef6f58311d2a4793c35710a498b030f72a82bf67b7b44bcad00a68d6115be82f5681d70690851021d740b", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223033336465326363343531393666396364666130396639373933646666343935406365727469766f782e636f6d222c202273616c74223a20223336376239303030626330643933366462323232326236343537303166313933227d", "TOKEN": "040246d0ebbf1ef1fbcc770dcff5d9ed14677421a570cc036322f04b40a6b832611ca77ce17193ffeb485121fe05e1118ce815edba305ff7cdc26ddd1b01204075", "U": "040ffc38649b30643dd7c1040b29f69e6775388afeb670356e65c9bf9db2a090de0072e1b3bef3eb33cc08d9873e3a3da631c9ed04272ec547f7fcfac8e7bc4c03", "SERVER_OUTPUT": 0, "Y": "10c6c5b9b60e91e67a12a936c185fe1f9cc4e576e69cfdaee25b5bdbef62fc00", "X": "013fba0d25b8e02bc6ba1885f0762b4b2e9247b3dcbb9472d5192038d6ae3909", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"033de2cc45196f9cdfa09f9793dff495@certivox.com\", \"salt\": \"367b9000bc0d936db2222b645701f193\"}", "test_no": 80, "UT": "0401b9cee474f968a182e1c9e3b60d6cb3ffa278e83e778af2f144e25a69771a780b5d87ccaed34affb084beeb3fd34088f1983f3ce6d27852ffda0a9d6ecbfc2f", "MS2": "1757b38bcda53b5a4dfff11a8ba0767ca549fc75fc8df82e1228dcffc7a0ef7e", "MS1": "22e5f18a90e684a1b5c55def357d3280d91b1f7627d1e681e0e5ae42662e84ee", "CLIENT_SECRET": "041034fa32296ce93844b021c250d6c9d56c9bf7b3eb4d418276ecc469527d811b1072b5f3f2cfe77ecbca4d9997405b686f2fea5e42f11da15573025eadc9f508"}, {"TimeValue": 1437055595, "SS1": "13ca345207ddec9a8cb8645c34cbd532aa9f32dd44ec6b6180f18e294257acc20d17909a87e918d345fb7b8951ce5509696f65e0eb287ab3adaea016e1b8951e20ddc1d4b490b957c3bb6bef42e314b3a50427635919815e683e16c81571dda5126d35cdca5e1a6d678741c373dd5e491961cdcf83323fa3757da9daa06811dc", "SS2": "049b72729f32894462722da3f7c34cd3d26606240005599620fe5949cbe23d3e0b4980b98259bc5521620a43971bc6af9d07b6f0db30bf9992588460115523fc05764fbee60a6871d09e0db3c24aafbaa1ee73dd597f8560a1af8d53c5b052bf006aba53ddcb634ebf987d89762f3f4dee535f134e2e6ccc9c0c9959f78ef604", "DATE": 16632, "PIN2": 6690, "PIN1": 6690, "SERVER_SECRET": "07c38aae06a77e28b1cbc4fcc5529765e16e246333ec074c74fc1f791da653c6225e10a9e8a34ae13003d76c820ab9f19e46f0679bb04c2efd9432d2b2d52fa71a5c3fbcfbf0be42941812378d7e3b80c7f56bb71e7bb038a8519c74d59bb554132a18e169b0e27c64c75b808368c9115b09eb9f811d68a6e33f2189a20d07fc", "SEC": "040944b67ab40fc9d750542d6012a1781c4296bb819d491eb324f9aca500e904080d333145df8f3aa1542c9ac479211c08056cae16055f37a2c94c899984432235", "TP2": "0417cdfb0ce476f91d499caad5105d9390b5f393d3bb319095c40936dd25fe53860ee6bf64c1a39c0eb024c8230be02b520fe720a5c5d2af1c61304b60e84aded8", "TP1": "041048c91292f19469f6b4706576aa38c31cd68e169f2701dd5eebc31ea3a94e7014063d2cfc0ca76ce8eaf0f7099e00948f57dc6acabba9072d74bf488f21db4a", "CS1": "040d6a7789a1d2ba778e1746425d29d76e00b2e6de08b2d175899ff638fec480ff0ae8e26a5585d3d4dc695be5194009d7bf71a1f113710f23291576e664fdb29d", "CS2": "040134414542b9d7357c4571aedae20babd160dcd8c69ea14799e5c59edef59c0e038dcd7fbf8ee1e579173c7a978960e7ae2bc293313549646103c9b337e9ad94", "HASH_MPIN_ID_HEX": "ef72d6a8006508c3483b21f96f35df00146aea66aaa96b11c11ea980d18b49af", "TIME_PERMIT": "0411cc44492ff758e8067b352531b07fc57c5e51f585c7abfef4e79dbaae2db78f1a5bf25e62493ee21a011a1437464f6b207c07111092239abbfb95fbda6905b5", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223831323337626665626163333966653235656637383933396661386264626662406365727469766f782e636f6d222c202273616c74223a20226438303766616230303632636335356461333934623437626138366136383363227d", "TOKEN": "04231a2deb3f54482e9a893ede79acb11a9bdea22169448ac455bff2ad36bf26771731d0535e5fd018ae7b2a6b6b1ccc47543b99d58e0932514b4e42ec5bc85b3c", "U": "0415f6d77ae9a14e217bce860ee819d6c2c255c399daa898facf846199b51d44c71a86dc7a3b62d1004e225955eada33b5a370bc66ad0fd49bdb06e8aad9b2ee82", "SERVER_OUTPUT": 0, "Y": "03c841d08f734872def0b90e5ec1b57571648024599c554d26eb8509b7b490d9", "X": "151c4cd2f0016a8b0494ac3151e90b2f859a6f6f0f03e5b188eea1e0056f6f2a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"81237bfebac39fe25ef78939fa8bdbfb@certivox.com\", \"salt\": \"d807fab0062cc55da394b47ba86a683c\"}", "test_no": 81, "UT": "040651b70881e6272380bc52367d6ecd178acdb685c3fb1b30ca00c8e8064db52c08339cb3ba487adea0131c9e54d54015ba1c60e5a7de5be0dd46be89568bcd20", "MS2": "11a395a3fcb5c25064221caa960e8b723195df2d92f3e999ed6536ee02a42a77", "MS1": "168ef35aa5c33167f5c1686dc899f7ece78de3d1540a72c269bc67a5f4540d55", "CLIENT_SECRET": "0413358654d74483cb4018a332903a19576f22088c6c755c68f2a9e8dfc59ef9b707d9296c4953d68bfce7ecbd56defd11611c43f51e0ea754fd92b05969ed14e0"}, {"TimeValue": 1437055595, "SS1": "038e16e89c02d9e87e60c0b907cf5ab5c9f54bce0f5d92de5b9e4980253a2ed10181bbb6a58c47b4936b38a07a00220ca1013f2d74863704331485e174e4a6ed1602c55c1341b9d51922799ecc6ec7dd3daac66a4efccd4c3fc76d2b53bf203c1ffd4acbfee9508366b0f9b6e6aaf2f05738506be2545b0f88e691949b58f49d", "SS2": "051a6b13f08068c9c4921a2a1c138c43c6da88faf65c1a94f7ed43e158d6a2ed069d867120e990b1ef7dcc15dfda6589e97cb16fb972735bd7b0f55b95eb983916868f0ed20e3cfc116f8c76737faf47c4e440c0adc50f7ab97eb1f42d14d8f4220aa91fb8bf3b0f88e9bcc944289737d59f1c5f42ec646164a67d785a4edf58", "DATE": 16632, "PIN2": 4110, "PIN1": 4110, "SERVER_SECRET": "0a2fa9f1b1de7b65c907c596fde01c2792cd48a3fb1d35d4d1956209c9feddde0bf0fcd5c4516446290c4eb8ef73e45f72e92d573cf3e54c4345388431d6d56a0a0cf880c8ef1d4d080078ab9df390cc159392e25de58a64a28569e4d10b56360722f09a5e33a62538f0a0cdb7c284cf3788cf62254f3f76674b6fa9150a7f8f", "SEC": "0403c2898733bcf4ed652f30fb812d88f9d211318f9d29d60769115483f84a9b191e29f3b7955324863596020bf335764f1d77233096eabcfaf779862ef0c41cbd", "TP2": "040cb0600abf445eef373538f70f9a5a76031f5bb88478a1b52c147bc851f15f17053b35be8c1eaf5147c2a59a9c4aee7c4ad19c819af99de096ab4cd49cd0a97b", "TP1": "041a78a1cff2e12ceec3ed24f4985b5fad501f4cdd0a11a080c4b7f9890b09acbc1143fd7a37ce7a61022b0176a1b5a7c3c0d7bbc7b1639ce810f630ca8a3a3c01", "CS1": "041d0c4af82a85183bc5d4452bac3e932b1cf2b30ca7bb0f91c0bacfa20ded2b8821f01fe1e34edc647608d04f9ac78f6e2f2906a1e5e84a6c0474b70b4494e1e6", "CS2": "042143974ef6532b76ef285121d47f039aeecd5dec888e2c37890275715b6c950514e5ae22e375355dada1c948be7bf44e2694b0d4c29a02e04c1b6b1703f11f05", "HASH_MPIN_ID_HEX": "db9fc81a176dabce8484f7f2fdb3a1b00b743af1ea2c70d9d9dd463f46c9df13", "TIME_PERMIT": "041bd61112ce778120a934caeb01239dc9813be43ec5a0b7245e5a8ec05172475b06c1847e9c109d6e3fe747c6890552f5c0a823374ec4ff4bdd17906d3939bb08", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223734383365336163643035396435356634356161393236346365343031356362406365727469766f782e636f6d222c202273616c74223a20226161363631623735616264303630303564623063623164356332313232366339227d", "TOKEN": "0417415f3ad8ecb0d00f7998a4fb25fe3d87439b56d766749941320d8a4717174d0f9d7432fe41bca083eecc32e9b3e5aecccff2d25e766cee07722295b8125f4d", "U": "040e96c015353c9ca209052ae533dca5c96f580afbffc1f1f196f1e1160ddc352a21aebd5115ebc29dd962b546e086cc862c02fc6eb802432b5ec797251f6699d3", "SERVER_OUTPUT": 0, "Y": "1cba7505700ec15d6f8b116c6d5025b4c0a8ee45abef0d887ffd71afff9738ce", "X": "0a456eca508b447877ed41dfa66a11db4c9cb1203462580d8f784f6cc34a6251", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"7483e3acd059d55f45aa9264ce4015cb@certivox.com\", \"salt\": \"aa661b75abd06005db0cb1d5c21226c9\"}", "test_no": 82, "UT": "04038bd9e0190c7f2abb4fcc4804485750c994f426a71bbce19149d7df7f23633a1ef7420fa3f5e06808d56e178c72f64bb5af2e1ccee25d186e31bcbba86073e3", "MS2": "1325f41756156aaba548096b7c8822bddd1788ddfc9e36acf77333d45194cdcf", "MS1": "123c3af8fdaabec161583cd7689f315127aa3b60f1a97edcb640e76acbedbc50", "CLIENT_SECRET": "0414354942e1379dbb9397524f67ceff52266f58eeaa1dd4202d2fe172726e11da06613ab186dece97635b1d9c66f671f0354d1b0eab9ad2a74f1654cc58931909"}, {"TimeValue": 1437055595, "SS1": "15eb14655f55715abdccbec0d07b1f659f2c9dae236c294944c67c9c821f76c20d1ba1597bc0c17ae80b03a74f193d5f2d5b49286d10e8c67af6286d79013e361e8ccb79bd5897de99830374ee8f30a62141ed49775fa4d011851c4ea6b19a9520cd968d748794d4a34d9dfbab43e4601c1e8ea1beebdae6ddc908ff546bbeda", "SS2": "1329ce1b3781d7c86ade297ac22392ec44af9a6df94e212b71f69ed3135bd4dd1c71037cb7caf59f86ffaf1f41ae33815d1285ff32161ab509af87e28d5b482f21fa749abb7577db8869652c2a235a99cd0745851bd193b3c51a3e695d7f491821037dcc750689a02425a00c7decbea18bc1a922654054fd3758406f07158ca0", "DATE": 16632, "PIN2": 2452, "PIN1": 2452, "SERVER_SECRET": "16b46e62d5e1909817b0b4a2df83836cd2b58117f8567865c87735bfef578b7d195f3431dab03975c42c806e28cb9972f95dcf9f5c40ea2af2b026e6fe2bf87411bb04adbc1f67c1eb19f38c6b991e0b049169d651af051df8de7e76cdfc45f31055e837303a2add4fd1a99fae088b7176056cbbb44796f0aa2d66af3f484ee9", "SEC": "04103f39f5d6ed237146759b20a91d73f2763cfd86bd1284d1916a4f0e6b582bb60639053380ae697c4f3013020f2c8eeeaa55a69728e024a18ce4952ab2e2745a", "TP2": "04025f4fcd0d828307add741389bf3fa9fa6b3c73594a64dd53b9f70de6fbc039b04fe6596e5635fe352ed934ffac0aa2887c4bc6ecf8c7986d5e20295d8526616", "TP1": "0419ddda7589d8eb849e5a5c19eded2649ee91af8e37198d41dc9b9150e3a4057812991d7a4f916175da85d3d83d71b426a1823d03b4cb9127ffb8843939ad7abd", "CS1": "0423f97691fc70e900d1ae1acfc46122b4d4adeafb9466733b4448435d2294fc761051a4b5c0ed5c580c14827d3bf0b8e722a81c9d1c50ffd3f6e005e00c02b093", "CS2": "0403afa0890b6ce4fdef4e068aca89f378bb7d0be9534695978b1c3f8475306b941ac2e89b8c934a7ff18e8af6aa65586a3a7cbcf086d5b75a97f6b2ccbf0ff4a0", "HASH_MPIN_ID_HEX": "5b5c390dfb545c1eb365c05f545603be11328b40a7cc1d3ae56a791f83b173f0", "TIME_PERMIT": "0420129dd2f2d917fe2032975e7da0aa69ecb085a77da50e4027df86ecd693edf211f00db4c293a859ab45b8e36f897b9150c30873753c0df282a7b25cb96f05de", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223432366134333665633531393233646330333762353963366661323038393063406365727469766f782e636f6d222c202273616c74223a20223266376239336262363133363762363739616330376536363932396664616539227d", "TOKEN": "041cd0ab29ef22623a6a1f600c4803ca1cd4c78bcb74d6461cac54487b6d394a8d20d712bea473a77e0c10c5928d285b75ce5fe9801709e09d70c35b3d630d233a", "U": "040a7aa4662b508e5dbcf3992cb275bfed80efa49b75135fefee2d2865c96b6d1906ae2f2c0d36c39eda9938db6b4e67d9ab9f46fe25c425bd9fd4dfe688a525aa", "SERVER_OUTPUT": 0, "Y": "1c5fa46a0a666f7be48e17fa667aca3d38d08c48340082f4137dca4542792231", "X": "1457bbb76c72b01319958ddaa013fce69c3a00f4e814383ceb50d7b5d0ffb347", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"426a436ec51923dc037b59c6fa20890c@certivox.com\", \"salt\": \"2f7b93bb61367b679ac07e66929fdae9\"}", "test_no": 83, "UT": "041fbd04220ed06354eb67a7bfdbc6cfd95fca0c61c06f70ee84bb27b35ad5c7c90294131a8e9cb678e0dcaf6713f172a0056e39c6d96f133d932a2e676c8514a5", "MS2": "221d05c9e83a8fb508f9946e55240112e157eccf9942b7eea683ae139f1252e8", "MS1": "016f05b68848e591c883eb7caa6b612cd244c1149908bc08ce434ef998cea16b", "CLIENT_SECRET": "0419c534e30b50146ff819dd5d331dadc75e57fa6431d3ae236159e48f4cb02f47014aed0efd295b82f00931c525836f38a43a38cc75dcb9bde166f9420297181b"}, {"TimeValue": 1437055596, "SS1": "0257d052951c3d55893aba56b6d8723a973c5e48361dc2a5e16100137d7e17741a053da4495a05693db60f88ba886142350ce7b7436c8d7c47adf00fc8eb93a0176dc0512b65b093f9c767e334c5a48b48184e6296ee1f5741a631dc1dac0ce90e610aa87ae5c7aaf7a1030b0155d9303101e2a2b9931b981a8ba01c09f28008", "SS2": "236031465af503389e33e881ae32fa767076b23dd5c6aa949369fcd59a299ac11f1ff708f39cb15faa42a25e60dd0f8f36560ad0f4729e0f436fb5f8fbae72a8233df55b5e55ca67b3239e5fdc3a7fb293d41c497cae5c5449e797758ad3e4ae1ba90168517b4470b259a46bd4f21d48288bbd64e2af3f59c28dc07f1252b639", "DATE": 16632, "PIN2": 1879, "PIN1": 1879, "SERVER_SECRET": "1c0fcd9eecc73a17e75956e9bf6b1580d15e1fb7cdde278c5abdd9fcf158d4ea03ef5bb7743e84d28b62472cea71b0a8c29979a5c4e3e46067ac2a08562cd18f14db0bf50cb7f61ca9830d428653ba7cfef71c4f630352d9e164d225e3d15dfe0a9490f971202043dc5444411f088df4cf8ced6727da720fce338dac4dfa92bd", "SEC": "040931603b2b9fe16c9de6fc134e0df43e798dffc193c0f0157d0434d6e662c91b1ff109f8a2dc73a62c15fabffff43b32627ee624b54a4f33955a9f9fd3731bc4", "TP2": "040eda076c7706cd0cb06eb14179b57ddee66aca6992676e1637b00e2173087cd316d124ce67a4589b759658c9e6fcbf1652e81f7d9b953780093b583d5d0e009e", "TP1": "040d49e4ce5e05adc5abc83b5750141947d0a650a2bae106255fd59d93748adcc618809b6b618e5c0e77089265a83aefa6057040a36096c46b5c8e88bac9f88b82", "CS1": "0423666a9ad6259487e18ab7f5e094160528bb5ad790f7f655172aa7e0fa66889603b9e199c181c9e2d47e75eb6a0e2e382e973bfb9e27a42b3cf50d0d7148e149", "CS2": "041935568d89b83aa8b7a77e22cae785633aed1936554fbd1e4169d2168017ac6d22db7a40a2cf98f6fe1b41d93e37c4fe7c37da739e434a34900c4d5fb71b4f88", "HASH_MPIN_ID_HEX": "7c899e9dea578c81a10ccb5d93541836dae4f7ce95cab9bef482083ef3bec13b", "TIME_PERMIT": "0416818c4b65e5b43f90d1c6fd95c242bb93d0d38c5fa81aa43a786f3a397717c60d40e1347777908d30d9f26b6e07f699739378c9d2e9df1e49401fb21aa8c9e5", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33355a222c2022757365724944223a20223361393137323037376361636638363861636566356436653731383036343230406365727469766f782e636f6d222c202273616c74223a20223465626566663761633334383932306262373065623461356134326436653562227d", "TOKEN": "0415b5279b65e4157cb7d01e40d4c3fe2127441cdb3e5985ecbc23d389b83dc0810fad2b2f6f790ccf94236cb667e7ae8161b314495a97b4eba13fd8f75565d6b2", "U": "0418285fd826c3bae6b9a0602804e275694a0d6b2f5ea9035ef34f1b46df302b8f1aad417ef130c97a273b46204144d6e0b15d6f264e3b66b34a3384a695bb37df", "SERVER_OUTPUT": 0, "Y": "1af453f8c2a8b26f6fd24c8764eddf13706e1a7058f8c61eea6844571d1bf365", "X": "04e483382535a89c1a7c06df3463c1ddb23822101d794571c1b4138beccbda04", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:35Z\", \"userID\": \"3a9172077cacf868acef5d6e71806420@certivox.com\", \"salt\": \"4ebeff7ac348920bb70eb4a5a42d6e5b\"}", "test_no": 84, "UT": "041be33114798663ae9a44a10c94a84f2a147fb2463fb0ddef5c64807f402593c60150828fc1c081248d249e7b7ee962cef376743f5feaad71823bfdf57487c670", "MS2": "010f0506d148210c280595dce5fdb76aa8cb6f38511ac35c2fc2ab0f3ce8c221", "MS1": "0c98c6bb81793ab5b9ad67f71e9f7fe4fdc9a4c6c1ea5a0d42723d35c07ca4fa", "CLIENT_SECRET": "040bf1b096802489caade680bbb6c8b50f9b69d2117c00157fe7dc1829c715612b22fff56ebba7f13e8484968e93704fb22a3d0fbffa2bc39971b7af09c480ea8b"}, {"TimeValue": 1437055596, "SS1": "06d29fdbcda974e6e3f1d745fef10d0ebf82d06c977290d20632e94ce0ffb2d515524b80f7d58442e5e4c4dc7358cbea7c21f36247fbb9f198119cfe0402310a02113591b5a642c6b4c28ec9c900489c125d0537020807aa7e942098656d3bbc23f476a636a7a2f9b123a5eecc53e03f39a4758f8eb101f8ea11127a2a59bff1", "SS2": "12875b352b0e4bda1d44046cb0a355ee5f5a7f068b74623ec7de91a258d6a01101d50378d3f81f9dee608f3c21d12edc9d2eb1223c8041d94bfe0c35337c14f2111baf7d24ed0d53646d792609126cedf9ade308dd1b8f2e54337cee23b52cbe028d15b90cf525ff80641201e5f0c928e030ead39c90891f441c4a0bf1cf448a", "DATE": 16632, "PIN2": 6702, "PIN1": 6702, "SERVER_SECRET": "1f38c646ef08c5d54af774e6231c6cbd463646705ce29af0d2f93a7b1fc366f31ae042ac6f4d73f09557ab8e246c425bbfe905d888f4c95d49b6d69b81cf5f881a461490a2a0cdcc353491462a42c7903f559b91856372ed0b50e7a628b4151218945bd5d2150a817c582b85720ed6ada3f41e47e53a7929fcc38b736538daa7", "SEC": "04034084e94ae7a5576f9e14da406a399aee0e077578356740ddb1a792cf6a29ac1b87c92cba5c313a9a7fd484139e183c2e7fa5eb4d7e7005bce3e8183a646a5d", "TP2": "04034354f0a3b1406c404a45420c5291912cad0d067819246e84687e7a56a16b9b12a04c516e048b75e1696486542f89a28cb0115557b1992af5234e9fdb25b07f", "TP1": "040adf69961221b08bcf6381a0e66d1b410a21bd9d5323da0051147ec2300f5ce01fda545f1e36decf711bcca4c686283c25c4592639b043f4f2ab510c72a2ab21", "CS1": "0415d1bba89bb6227819091c9dcf45c94f4156c0dd3b7ca1d0a7f0fb92039b4bef1cdcfd06011853c549f5fc7bf525e22a889b45c8e375a5dfaf7d4af28e2e866b", "CS2": "0403bd880bbfaf49ff6a3a8474070502c089a5e740dd8a7f90f9fffc903b6b9de1213c38ae08bc1b7c96f69a71cfad4673895fbb7c9357cc3fc843c36ad83d88a1", "HASH_MPIN_ID_HEX": "2f75bf7efe13b3c965d73ade4dce6bb31dddd85d68ecd7553f96547469be7fb3", "TIME_PERMIT": "040bca050f5c9475b49800392aeff2c74b2212010074a054e4992f828d773a7f1a0526368ef08ca7d76364c0b03898a4dd488725e68a5169eb2a789c961758d046", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223663376261363464646262383032363433306633306562666263383739396361406365727469766f782e636f6d222c202273616c74223a20223030666165323034613432383764343536666362636235316536626138323066227d", "TOKEN": "0416f185046c219295b34ed631d4bc793ada0501c26d7e5ae22df09773df8a2b3a18c6081a8c8e34cf3111ffc91bd8f67f2958f785f5f755e863a568fd1b873ef5", "U": "041e79e93463a48afbd37ec65e05bc63e257f5f36ed1ac62e745b6715bcff72a3b16dddbe48bee190633747e1106d5524b411649dc4a22bab795bc4278819bb775", "SERVER_OUTPUT": 0, "Y": "1b495418ec7b854513443c7f7b6cca9773a8cc04b4146d9954e983311f9c0664", "X": "0e0e1919fa69aeb924af316cad4d53518ac84eb9639469b56c293d045d48dbce", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"6c7ba64ddbb8026430f30ebfbc8799ca@certivox.com\", \"salt\": \"00fae204a4287d456fcbcb51e6ba820f\"}", "test_no": 85, "UT": "0401f6f36fb7950e23131e6a3acebb9e2ad2e1e30f032142dc69d9eec213fa098216e0ffa3f588c3f046fb7f8a2dd3e6c9666c281b5fb978c27b30f5fe6b1b5335", "MS2": "13842e276f21cb334f9dceceffc4c99665f7ea355b7c8a48adb09118e549a90b", "MS1": "11098797b81aa45566e0e862f37bb6b7400b2ff2a4563826c902fa097a783d93", "CLIENT_SECRET": "0408a274aa2ec0863198f7397c1684c6320000bb307efd92ede420c9cc26a1cd3a141a6077509c4bc09930722bb0de19900d1a6944339d9812def1f3b1662cb3de"}, {"TimeValue": 1437055596, "SS1": "19f16b6483722d77cbc002e9c49a415fd2e01792c3f45480ff526031bf08e6470bf679b6ae274cbe749941bde5179031db46e0382cb90e87c7401dd7c413bd1d023125ad5095499c407dfa527995a87fa7e1fd3a1be61ddfb921269e55fcc78616f16b816ab7cf0d481b055208e22478f14f266a61b1dbf090a7f1a8b4140e75", "SS2": "230cb549d47b76a39b0628851606ed373bb50ac37c6d846386868f7b01b6516c03c635c2f671e94c3b5fcc95d78a774e6c788a79e74f4cc1737ea9db6a1615e5235dced0fd47d5816c5a5217e6f16f79318cd75f969e8d7c151b2046f724d6fb1fb42b58f02f8df0540d25bfc3e6c0ce39e37a4d8042ecd311d21278712d77d2", "DATE": 16632, "PIN2": 5189, "PIN1": 5189, "SERVER_SECRET": "22489b355e9da3493c8278e2cda9b55b883f2db23463d48b34d599a36522c01b090656c06c53cd66f434cf1f997855d101ef1bf2533db7f675c255900543bf5214e84dee6a99c507716bf41da164c863649c40b36eb96d33024a723e16b01e9101064ab52d517a01e6edcfe385b53d318e4fb066febabf9491cee8cbef441f2f", "SEC": "041215587d000485101037349dc3bf64d62d2546025cb19002a3145ec259bdf06a0604d0444ae64db6775ada19f74339a181c3804e788c1c132a20f7ecd56b0af9", "TP2": "0400047f4defefc8baed56f30cee2fa742347bbbdd88feaa0cf8056171da916c3f1462a91761fddbaf5e0c7669865ae007638ae55a821e7473b6e771a435ee14af", "TP1": "040713c49aa96ab4172a8ef20efe5f9508d9ca440aadedff869bc0295e71cc9b440b3d95d55ff9b3ebde957e286f562c00e57d2ec2bbde104772c68ebe9d8b1a50", "CS1": "040273cb33e885433a5533f258921a5824a6b9c4ea55f85f253d954f2c01e730f202cbdc689495fba3ecb20bf8b86c6b0927ec5a3899dc8db0f5b91c9218b531bf", "CS2": "0416f20471ef105c0c8dadaf79d1414f24b35aca82a46218466fb96587bf23c77e0b8eb63440204e38736af00d5fd967c20b5e9a7946ab879ec44b9e5fe0647455", "HASH_MPIN_ID_HEX": "ca1ba9aea2fdd203eb37c55593db0f6682a254c8b265cb58626b50da531ada53", "TIME_PERMIT": "04237caa62583655ee7c7bd1098ccfc58f73c463c4eb2350916e3fd71c878a66491d1d4c057d1f8ff374e729465bc1ae6f0faf7746695c0a9ea1dff8504c102e83", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223337393666313832646566656632356263626666393166653863623834643266406365727469766f782e636f6d222c202273616c74223a20223761346237343863393632643431623537363333623666626435376234666630227d", "TOKEN": "041d679876b431ff74079c739bef6acc67fe5331228a7cf58bb3b93668a30049190846cc6b3c6c7c96b2ff4f245e4a9362d9be47f20dc879bbb2f116c91a354b46", "U": "041b03a357f3c6c340ba63c4ef65c0fc34a77bd47608e08277d4c7e40dcf879a7709de89691ad35aeb326061247f31bca352ed3e16494b35208c370c2f6ede67b3", "SERVER_OUTPUT": 0, "Y": "1e59897045d73a76719292eea817c81ae0ab256f564995cbc4cd7bc119b5013f", "X": "1139109cf6dcf873238be3e814a8d9ab4a7ea90b4bec27788589b2295262e8de", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"3796f182defef25bcbff91fe8cb84d2f@certivox.com\", \"salt\": \"7a4b748c962d41b57633b6fbd57b4ff0\"}", "test_no": 86, "UT": "0404d139f3f5dcd02f953255424f85c980ac06f6dc9414adc069ce8072f2330b42074c266659b2ed16f69b0332c708338e0b43cc049185412949b464a99bbdf0b4", "MS2": "12e014f0d720296e6949816c0807b184f0c823b597ea560f576b308f0f28adbe", "MS1": "013a350f4a37c7b0b0636e74671992df99fe0cf7f5a71951fb89ea1b31142b36", "CLIENT_SECRET": "040637a877ae778971f3dbe0fe32b5274a9a7350f2809aec266040401944533fc01c7d2a14d2731fde56356c58cc754ae629ef9ff1ac21f939d5b98fefd92a0769"}, {"TimeValue": 1437055596, "SS1": "1af716976c8a862131075b0dee0a510668b39abc747f7efe8f95bf26f1e99c2e1e8f3501166c64d82dbaeeaf6492d663017f4e7bcef3c6dd278847b05685629d07e4959a2ae190d4aa11a67110bcd6de4823151c88d2c6ea8e7d02a32b174f5c18843201d4c8bc4d72eac8debc71ad3cc85b34a0fa580f928cb56cc7879f3431", "SS2": "204067ef329b482dbd70b2003aaf434a6510260492b8508b291e9018fc8414e60910d1109b0b2e26b7c1bde2c23b8aa2b263c1f1c04adf7c1fd2b2e4df1f91b41ae95b1da612bb29284b1e6da79627448109b1fbba7c86359bd3eb32fee7c2b50e8b3bc731ca49d64d52528162be2d7100732e67ebc200b01846cf0d21aa5b22", "DATE": 16632, "PIN2": 478, "PIN1": 478, "SERVER_SECRET": "05f38ce4cbb30fa7332a44ccdfea42df5d47259a4ae12accd05edf3c672c77b906b8967b72acb9c1c31d99d9f0f78cece7eeffe8509fd839ed582165b655be9119b66419cb989b5fdeae09a1420aab42c638d6075cd9826d3a177063f21b220709d399430157650815c9672c8a54c4d9cef8eb2f9e4d0d2d844526b7d1c02247", "SEC": "040d5191c472d0b9af10ff7ec7f5d90366355b7c9ddfc823d2c84dcbb3b9f8596411683499c5a73b15f687431806498bb9af21f197308a8abbb615804e04126709", "TP2": "041593ba996fc0cd9ed58faff93e2d5ac954a7b6075b994b247072348d76d7206203c2bcd8f033d90efe35821fdef886896e7f2c8801f67788cb09af15080c206b", "TP1": "040b30420a1974500ff1cf01af9d81af01a2e34a8d01f5f30b60dc40ec6bfbcfec1b5f674067dddb7233f742bc31a3f13f34ffd7e96ff5232e15f2ff8b7f53d73f", "CS1": "040695e52cb89392ada8563f5a9ddcb31c11a29e82ab748a2b8dd1bff1c070d4b31c3709c07a842f7ee6df7cedaf63437b82ac64cc3c678c03ddce8c1dfc2138bb", "CS2": "040a9d9459684ac0f94767430585172880013510a7c22c99353d871898ece163410ebfbe0bfe438807e80530958adda3905ae457b0ca0b130ba2c1615017da3eec", "HASH_MPIN_ID_HEX": "6db6f73e735ab0f2d42634da42fedd72b2c98e0ffc73880b996144a7ef77a59c", "TIME_PERMIT": "0408eea858e60c1c506bd74d6584c6efcbbc8e087f26fc44a2267fb89dcbbd14ee230518e5bbe27127d951498327478c661357adba12dc0f436edb57db2b6b7bf7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20226561373036353662316665383862663537663832356434393434383832623866406365727469766f782e636f6d222c202273616c74223a20226466386337323839333933313166623366326437643762623861383033326463227d", "TOKEN": "0401229cbdf3d0a20b588fc68c89f74e33218700285a2f6bc813f857c78ac3757116325f9bd00d8200d182a6d1b5aaacfaef2e0a35605559d89f01aa4e65a6c472", "U": "0412b02edeee3d96481bf5fa089e7924fe855c00d53403d6ec91fddb6428f7759d02fe11658ad00af6e2f647e432081ef0daab5401191e637ecfbe01b5894f4789", "SERVER_OUTPUT": 0, "Y": "0f2117dff59b69123aff2b6ca7a46fc361d3e1a76aaa879c0a2869f4bdd9d451", "X": "23d32e9733f29980400bf6e872d3a6b69b5c60ff1f2c8253cb77610d2998440c", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"ea70656b1fe88bf57f825d4944882b8f@certivox.com\", \"salt\": \"df8c728939311fb3f2d7d7bb8a8032dc\"}", "test_no": 87, "UT": "040aa4a20b53e86ee47f62d0b157ea6decb54c3ba7108e269f037001a18cb858820307b066c43ce12cb8f60df88e714996080e7daf68eb5bd738151f654ede056a", "MS2": "02c51b0630539ed2a0cc7818f7a7645cccde6df8730f038d4bc17ccb60d3d91d", "MS1": "187f38596e55e0ea8fcb067ff4ee7c205685e2ca37156d2208b185ca0324c7ae", "CLIENT_SECRET": "04101a02ab2cadbae6cdbd15d1441b508fa131647240c91657dc00abd7426c3dbb069fbc48db93151ab399090e0fe08e1cf51f6cfc7979db4b70ad51494bfb7d18"}, {"TimeValue": 1437055596, "SS1": "0227d08bea581a90d17b53039f53367c5159b4f9ed57efefc6d1a7f8d63c050a1e6e5720fef1b76f83b5054ca058ca70fd88a0ebb314522ecc7f9628684e75d90f6c70b98a46a1bfd88d0e98031644513efc2ef4228123dbaa812b98d93055560d61a73a0f1b2883d9ae2add025a4f6db0c87190fcfa40f40102890484190cef", "SS2": "147bfe601ffb8fdebdb1a7f8ec86890cbb695815d0f29fb581317c6da06a1350032e836e5128b5a85e9c6721ccfc9f26b771de05b46b15ead301acdb0998736e0b7117ae21cff6398605d35ded665a23bfaedc6c0f8a0bc1990d42445dab25b0109e85a2bdfd8e96a6d71b2a36ffbdb6b8f393168d7eba9fdf349dbcf4901850", "DATE": 16632, "PIN2": 3037, "PIN1": 3037, "SERVER_SECRET": "22e2cfff645bb45e00c65fe5ed89fb47c23e838f2eca3a1abbdb18f771d16f601a5f5c2c5e55053490718e68806a6f9d37bab1de4990c8e090f2197a43bfe42d169fd11cbefcd1ac5a7317c96725dae8c3f6ba42b1fa36271abc8ae25c0b2f3b09a0bae0668dea92caac980d9cb442546e5086bbc08211b8e31b73d5ec8af9c2", "SEC": "04069fdc2bd8f4723c81887aa9ae0fb7f40eeca08412c990e21ec6d76d2f2c9a491d6b9c48e0cea7d196a11265981e50077467086544f2201ea30eb342826bd57f", "TP2": "040e2080f51dfe416aee7e835f7e269d7ec3d20537d4970422874bcb77fe29553f1e7d0eb0cc68ceec12ecd9ce037a5863f5b29d83dbe35abbbe711ac84f834010", "TP1": "041cea02f8cb2df510093630fb9ee43a5e4e347403249027e4312c5edca35c290f21d61e3eb3f88faea20e78179d478b984125696a395d5023dab9e2260ceb36dc", "CS1": "041b90ee70919a4f7876ef809573b709a7eeaffc66c779ce31c9350d3efbe4bce2194348e7a2eaf95291cd77a63abfd7483cbfc5227c8d0905c5927ba5990f3ff3", "CS2": "0400d928615e36796f5d5059c4ea0647be95251526f14e49316ee62652825ec5d016005ab2c977f99b09497867f6dbd1664e53c389422428dcecbf351d48ed198a", "HASH_MPIN_ID_HEX": "61921da344d9c5a481be2f8cf1a8a2efa8f44b820d27cdfa34aa4f9b1d9bc2db", "TIME_PERMIT": "040b2f926f3c4ede026ca6d3bcfce3bc0618f0c79917db689790b667ac7047a9602314a2d4850c9b2bfa000f1cd8f5a98a81c5f0a0510ae66dfbd81b6efbffae08", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20226232643337343934653863633835663337663230366434346130363939366361406365727469766f782e636f6d222c202273616c74223a20226339666538656137306531383332396664306135396436313837656639306435227d", "TOKEN": "040f968aa98921abdad33eea6adb2c957d5e356190f0e01a4a9647a1f1a8e141d515ace5a5e1d4a338e43ab1ba03440d7275acb5744b8110b14b400dd4a67accbc", "U": "0403c9a342b783bbe8843ca2ccbc6a1ae99fbfbdd28e1b169cc3b4839b8dd1ae5404e85aaa15310de903f3ce7406a15125bfa0e309998f5d06e328fcd879c74094", "SERVER_OUTPUT": 0, "Y": "18c04b4565530e2199bfb14afddd8a4c774139095b37ed00f5eb3e624d4d2a07", "X": "1e464a65b1aca6ca21e012156a5ef2fbcfd3c00bc6624a3ed353598eb80f14c1", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"b2d37494e8cc85f37f206d44a06996ca@certivox.com\", \"salt\": \"c9fe8ea70e18329fd0a59d6187ef90d5\"}", "test_no": 88, "UT": "041d1049abd1b7d1a98cbc969e2a258aa8758732091074eea3363b10f9280ba5d9041c9282292f7925460b2d23f44782a97439379bbaa231a124a4b946ad9aff64", "MS2": "16817f03b7a53160d0d1d16cf396c7d5bccf4fe7665d63488dc13fdf2b9a81b0", "MS1": "0a35d7e3b92e77859743cf660a7a87ce018a9bebf14676aaf275ecce3e37a804", "CLIENT_SECRET": "0405a61b54202a5c85486e5fcbeebd113784779fd3bf591d66627052d844d9c6871675c659135db7d81c38f0ddabb0837162e48783c32147b97a1732a3bfc7d06e"}, {"TimeValue": 1437055596, "SS1": "0bdf1f88a14de07132a7d582cb4f3d518e7917da46a084e6e5d035bdbab933b8157ab40129fd7ac6b34b6242c8bdfc5a7fae8d31793eb50316f0c2ffd3c23ff922dc6333bd54bf441603c3ddbcdb7a68d68c44b109df446ec0262fba117108e40b34b796f736e094539d59165a50b73cf6e72246b8a6d1079b3098ae88c2c71e", "SS2": "1b063121582946256baec54409ef82d7b03a919d6c308d41e1d01646ec0617681caefa1640159ebb10c08c6b214d703d5ec456cf4dda46998e8790cb230dd57d215b47dee24962ad9c6a02fb2be27ca84eecacf91a8371eba3c07b68ec762fe10934167a47485f2bbe548f6c4d29a429471c475d29a321532c3cee8cbe828ff3", "DATE": 16632, "PIN2": 9773, "PIN1": 9773, "SERVER_SECRET": "14ef204b08f4d9cf1618d2c84b6114aed8065b35354ce837004849527159293e1bcccb4fe8f05062ad9095a845b853e28a338e4e207729d1a0ce55a8ff0f0f4a16158651f42b51fa73653c22f068054df49b8463c39ad2587f58552c1139cc531128352fe118b270a07e5e944d152ac91a06e22c4fb1760de5262bb004714f24", "SEC": "0400e3c08e55a869cb30b29e2eb27e4e29dec5c6ce41913cfe3ce65b857d3c39e11b033a99cd8d034336ea71067c530a9a49e76dc33c07a7bf3df93df21d572a7f", "TP2": "0420dc73d91a639eba64acb2eeda8749753a0e81934f7ed603a4c136302416b8d009f12feb7e33d433e2dac50e9fa63ea042041bdf618f83079d89aa138efe056c", "TP1": "0411dc7d38acedbc0f2decfa7df0ab66e37dfb76b3e30b695d3e2c9f981cc788fe1c40759ce29be2b7d0627d1f35180c42df0b18a7feb9ea45d74380e5ab3dc35b", "CS1": "0412dee57601a75f1355e4fd9d0e76775e61f200ae3cfd1c72b2a2c27fd8627a3d121ae5a42c822762503b55b342d1e035886ca35348e59a740a13c3d7391f12fa", "CS2": "04124eae3d95195d90ba961729a5cbb33bc525edc65fba4602fdcfe0a169e9509914a4b23be8bb1b1af743c61a42f18310f68504f9774dd4675a4849858607b025", "HASH_MPIN_ID_HEX": "22f77d051b530d14b603483eb2b0cd1c309fa9148bce58a4a28914c347832ec9", "TIME_PERMIT": "040f1bf904e8f3587fa7d922f7b427cb64c6f7ba9ec46e9a049a07522d5ed6dc7c19861791629355871a85b08bf36bbb012f1812ac48a131d117203cfe3fe97a73", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223032633433336330363836306165303262353330663263303236643661383266406365727469766f782e636f6d222c202273616c74223a20223633613536323831636630386166623139383238356131306535623736656137227d", "TOKEN": "0421404e579662dd46ccb0742fda4cc225bfc884a6db91fe67576ec167f40579841cce296aa697bbfa7736d7f838d87a9fe2532c9fe043e5ecd047246a6f14b63a", "U": "04003d5bf162e451ca5e4b2695214f0297439f94d1a69796556d59766c56de076d1b9d1ce0bb0154342fb4bab770236bdd8d2689e2c39044736ed60b5a5a49a4ef", "SERVER_OUTPUT": 0, "Y": "09264ed22adae1dcdc83bb65b67dda4621c7aba53707dd1e73c6454d94354b63", "X": "08d32a555208be390f96e7d34e660313efd66b1c81a0410f38c0305d2cbeac4b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"02c433c06860ae02b530f2c026d6a82f@certivox.com\", \"salt\": \"63a56281cf08afb198285a10e5b76ea7\"}", "test_no": 89, "UT": "0410cce976eaaa5ba36d91046b5381feeee0f53d98bb0cf24793e4c12f86c3ba4a23c5855f7f8b78c9c97c884d38c6f04f4e14c97813344d3774fefda4621fe28a", "MS2": "0d1c1163483528ad00e8feb30b6c033a2a7ff0ee2ef72201277bd636617c8732", "MS1": "1900a8d5d0f2447c33cd83653d0f1a734a0d99d96547f6965646959d5a31cfbc", "CLIENT_SECRET": "0412c1e66db20b4be510a7a86d236f926bf6fd58d8174ebfe930b40f209c9bc7a02010d30fa2a09fbb5cb7e8158fe8e0d1701d4974c6d1001fcaadba83e503482c"}, {"TimeValue": 1437055596, "SS1": "21be87bb72bc8fe66384537f85b635979030b35bd21eacf0bc123452014706c107ecd53d30dcab031a0efa6e387c8f85ca7d4fc39774366690f402b39d506c330bb1a649f27f57d773078996a6b76f396d5636b19fb64ab75e23be80efa4bd1c08db50da7550d0ed8351be08e252e961c8439c2430d685f03106140670f2f760", "SS2": "091eb45cda41dece55800ca1b6df9ec44bbf697fa7cf36e9ca84eb18cb2f0c98089262d2d6a2a2af27b848ed78887d4895909e9d94e2e43a6d2ceec61b45dcff0445dda567e1df244c5f89fc4f7bbe4c5dc1346d181e46d1a2d37984322cf5b2109f122cc5ccfc1c892989ab295d2dfd3367745853c4205d5a3fc14e939bcfc7", "DATE": 16632, "PIN2": 2864, "PIN1": 2864, "SERVER_SECRET": "2008580c231ebdaca4cda148e3b1fc24c8f920820af41cdc17ebc35ddb0605910dc89303cdab25cdf0296f64d3385c5ce21bf83bbfe04600ed682d714f26f3921c42c4f5abc587e7935606538e983097b1a446af3b3055d24bd7e1660a76bfaf050e34c8b425964ef4f2c2e717a2ae6f07bd704f9f0268fea3d5a7cbd7a406e5", "SEC": "0418b0d0560ef4eb5964fe40d4fe092c969ff418f46607cb6dfd569a45e095b9fd043fa4f56719763a6beb5b3801baafa7f7e124f9c4a1bd32e7a1cb821fc07554", "TP2": "041a79bb1aa3acca0d623c265f71cb633c55a4b0ea0c9a3db238be65830dd87b830d757eaa00da2ff97496b755ffbb6eee806ad055138c3c93f8c09865cb18e299", "TP1": "0416da32a3963e8000a0d54fb2190c29a01a8e87e54c8b9504a9b35b4e8bf6ed15221ae04582ec484caf00cadafd8fa20a578ae0ccf2215784c46a6bd942258424", "CS1": "040ad3e4d548d7ce5c4e79828e91168478ca1a4ff09980be079bd305191ac315c71f22444618b3cefc994e08094e13409e95da4de087aa7fb639729fcd10338884", "CS2": "0411df83d95c894688cff1cf1fa562860592e6ed3fd8b1a4fe62757831c3d325202090077de87102fb6928d3b8e1381ea9feeaf985469f8562d3c2b234230453bd", "HASH_MPIN_ID_HEX": "efb105f920f916ffffe4c79aee60cf535ab171888a8a7d3fcfab25c7ab68cc74", "TIME_PERMIT": "0408e33e6a5405e3c05b66e9d08e629aa9689142a06b62c07c95cdd93558e8d6390513816b6ed2021f1d5d386ad4c1ff3a2daa25fbba35a31bf0ff8b400a52983d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223731326333376531353030393766303434653062636233393361383539653331406365727469766f782e636f6d222c202273616c74223a20223965336663333131653330343662646137376665313466666438346565376138227d", "TOKEN": "04138a4fc973ac44c254a19e1dff73309f79fb7533bbd90fb3e9aa1e6656825e6512e175a6a5fe336910803fdbf99c287cef440589062e4c735e990decfbd0ee0e", "U": "040d9d53f8ce584cfa9eaa8c30eb50b7458a57c4ecb53999011becab33a9421dd9032724d008b5274d5a3ad70c5b8fee32f89681b84c642cc636bf6de4a349b8b7", "SERVER_OUTPUT": 0, "Y": "03178f4a995d4f425274504e9f1987c28b41d4e4ca5556276eb732990ce56931", "X": "18be8b89731830fbde61e811db30bab996075eb264dea2383c53896b96f0d2c5", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"712c37e150097f044e0bcb393a859e31@certivox.com\", \"salt\": \"9e3fc311e3046bda77fe14ffd84ee7a8\"}", "test_no": 90, "UT": "040539c236e034908c0dd2cfa0738abd68f6a092c30171c7e8c37f0bbff603601c16fd7f09d2ffa50a1f7802500189537993b9cb4cb2988a56d75a5f990724f1ec", "MS2": "169dc4e502846e14c31e1af7e417f4fb2ad3326031678e8859dbfda864b182c5", "MS1": "11d9316f23270c4d850cc18d666b484245b2e505fa5e90853e7a649d3a6754e0", "CLIENT_SECRET": "0412f98e1f41fb8cc27e43eca679c2a90a7624acb14a6c5011183cb9d4b2db92bd1db9775d7b6559625a8a564c85f570ee54a73e68093e146db2735957f0d7b687"}, {"TimeValue": 1437055596, "SS1": "0e331ca81fc9fc682c5857bb8a3ce7166b8a06ce612cf609bc63dd0fafce9cc4094b6e80b356ec90cb523fb45783c3a41f5c1338a4545723cac1240c7b3160770a2c8cb851ac7f2b42c2bb7bcd83ad452a71c261699bae57db3318d0efdc91cb02d50f3b08dcc3075162044cad033d1745629c73ac48e9dc7cc431c89e15b4f5", "SS2": "010521f2dd837cda4292785f348f2c50e9d17520b58b9de4f45d5b2aaa69760d19107d3f4c8a67acd65be6ceab5012bdcd5a8d3ef75ad02480c178553994b06d0e2cab081300e0d59b76b14689fa1382bb94ad83e9f5f4f75bde3b0111aba49d0c11a6005f4a87448c1f5e620a09d84c6da9f28b1bf2375ed1e54674f2954818", "DATE": 16632, "PIN2": 4988, "PIN1": 4988, "SERVER_SECRET": "0c475a6492090efbe317ac0e44484c335f43d201be4008f4da57076950cd5bec0b34cb9f1cc47dc8914fbcb1a4c30844a03d06f2471ec3caa911c9cc0011b3321358f73b6c3155223831901d9c95a58e881b3d58fc84936ecbbb41c404ca316e15a261aa1fb3d605f6e54b96f996688f52162b49e31ba89141f8e4162d9133d7", "SEC": "042132d3c9ac6ef79f535041d1f76cd14478531ac319903c55e2d6afd718d15daf055946aafb888e791aacb75de318479865f0a9d0b8734477de62b26f42a70914", "TP2": "04029f0e7b3d4c40c71ec90b78d436b3830b1d41820f60906017e0c03fa9770dea0b7940f6640513f5724475f7ead72c8c92f3387b44768e5d418c699746f05632", "TP1": "0419be869003bf44de02e146edeafeb399a2af8a52820a5e57ab8a308cf154091e18d9e5c95bbfb7e35951c6845b323a7d5c7afcd021e31e06c26e914ce6fa233a", "CS1": "0416a213d567c9b5a3738f675f692ae268a6d3a15de1eacc835fee40ba35c58df90971978cc0873c09ca2306fdb21545e9d213214b8d03f791cfa0b0cf4fcac2d7", "CS2": "04221bd48e779ae5671bb438e4428d7ed03e11429d08f9cee4172d6aae09fd545909dc451c935bd43dbb1d625c03b912e1fc4026c0b4e7061f688a14dd610428ee", "HASH_MPIN_ID_HEX": "7ae193782e92fb3021070597e146640b0e4f8bf0790089cfedec1ecfc39bd2e9", "TIME_PERMIT": "040e128bab689c918cf41fc8a263bbeafa4574d6b478d9771843210d3c40c1405e0807d14079a51538d3e76987946fac9ba9cc9fa33242bce0d8bb7261a9dcbfc9", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20226463383530633636306664343165636562316530323833383161633430336439406365727469766f782e636f6d222c202273616c74223a20223431643632383032323334666238353637346566616331316463373262303765227d", "TOKEN": "0406ed584ea0610226fecc6e7d270525b1c0a128558c5bf4d640c19615ce0254a508d71b2bfe1e1f2d13f22c714e43a7b400017140b33c35130b2ddbe5d5ce436b", "U": "041854c8a1fc1e0a87d992fa85f77cad0c999ba84cce6bd39ad9b40742e030df2715e98a8e64ba69f0e8c1ee26e594b9cba0985cfaec706d03e381d8dc7728e848", "SERVER_OUTPUT": 0, "Y": "10ffb3d007921d3e96d3723e104074a527acc40c5760679488f88a7c2cc286b3", "X": "18bf87e1767e4dcc2818470e72daa2053647ee38a019490f26d1bddb12c10cc7", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"dc850c660fd41eceb1e028381ac403d9@certivox.com\", \"salt\": \"41d62802234fb85674efac11dc72b07e\"}", "test_no": 91, "UT": "040aff841e365744625ba64549dd26181a685706add98d3f639aa9ad731d73bdd7178787b8b8a0fcde4d8ab5227bf5e3735680bb70713f1113acebd29dfb52c8a1", "MS2": "07f25f38f79379041b0dc3e87b0f29a6e8fd9544c4360ab78970b904315c5352", "MS1": "0aa0b003569cc2699585877083a3c38711ad1a1cd9dedb4a841904d097381974", "CLIENT_SECRET": "041de1eb3b5cb2035bafb561788898b62e3d473b0e9bf3ea748abbbbce9b55e326182640ac8510443d9651b5a0aa36bd7cdf084d3aceba8b7bf7d6a45e8213c33c"}, {"TimeValue": 1437055596, "SS1": "07775195ff82445fa5fde6b31c45e74b8fea11568ee8a92dea9eafdc959e379c02fcd05f39000b085ebc34ef8ebc58b68916fd2adb1e5dc4fa0b9ceae9ddf52a025ab9a1fddcac5a7d58fef4fe83d2baf12c8f9253f197728fe71e373e64c49e22ea0cd45eddbbfbaf8ebf8f18d46b340d5aebf99d02fffb45ad1848b6fafc17", "SS2": "1c9c1fec3f19dd3f38db6eb6e201c48d9163391cf1a5936a79f149161940d19c06ecaf8a8cbcb9b64b2af065ed13c50c518de60625051ae25897a798a22ab9780aa970e0dbad979d265f0e67c1fd67cf5e8974a2242b4105f492c1dfadcebbc40db810bdadac196b4be44b78d0239babe9dfeefaa4dea67b24c1017e2fe7423e", "DATE": 16632, "PIN2": 1258, "PIN1": 1258, "SERVER_SECRET": "0a36b789fda4753071ed42e5cad23a22f268072961cd4fa0ada92b97abe4184e02035340d5b62c97e5d479bdd2ccc6af5d3f4a634de89bc94fbf891b9fc0cf2b1e88395ad17b2b49b3cc35fa73bce3691673fa70a6138c0000c0fbda2c71105d1e5182cf045e532344feea683bf72daee526d8b1e480930bcc2414eb5923a439", "SEC": "0410ded5ca637761642be821813cc32c5d7acb3c763ae1d7e802e9938f0dc0495a1236198f91ac1c8472f1a50c0c9632b215db7505030f86caf3c8cb1490351949", "TP2": "0419afd41bb9bc978c71127d8c2a1d9a40c68b8977eb1aa89857fb47c30e7d9e6e066d1578fde875153a3e45ef03283074cd8c9b77af10d0491d3e5b0741dfd7e4", "TP1": "040b23388d49eae5c474d962f7d4a260fbe832780455d923f23fc3945bc619f44804c930679366484b564aef5c697c7bd7a578aded88eb5d3a4115f6c42b299049", "CS1": "0410114f319fb4b0dfc1f19d2587454e8a6d4220f7b8f7f013f8e5eda175b3aee522a48585af3d1e4e0d6b1b3663e048e68e3a8eb1a40542eaefe7c6c761e6a0af", "CS2": "040935ea7d9621f5d3d133923e761dd3b281c5bd02a40b2ac2dee61c622041e7a41eb2073b89738a085207ed178f0d21ad5b4c95146b7dae8c21a640c0eb1d393a", "HASH_MPIN_ID_HEX": "eb44ee7deb087c407e0959e98253a5934905e3bcc02f57676e04e0a3c26be95f", "TIME_PERMIT": "040aec918f2179aca4b0faa6510bd8e386684fee5489c210b92dc2395507f48ed907604b60d31f13bd282b93bca7363e41267cbe3029887bda055b51be6a3734c2", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223630386565306566353035313336353565303333396331343835323034663135406365727469766f782e636f6d222c202273616c74223a20223938666637613938393436323637383531333335343063393933333632393965227d", "TOKEN": "0418e55c0e822803dab01721ff14f8671b599a07328747f98441284b46ee68ef860165a91b6c9e30869178e4ee7399e1306d4283303df4d80cf75de21a6ebc78c6", "U": "04233305a50efe38b233c161184d75ff5aba85ac14300793b4b79abc621e06a5aa1f9fe1cd39590788c9a85d9eb97d131c8599211f7cf96a555fc3f56469402a8d", "SERVER_OUTPUT": 0, "Y": "119406d3f9b6f71ae5b3b4045b0b8b185f0d286219a554dc96205c83445d8997", "X": "03fe6d7c5ecfca58dfe42d14d5a8968fbcbe70aee9b05dc99cdb7f1e6bff7d0c", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"608ee0ef50513655e0339c1485204f15@certivox.com\", \"salt\": \"98ff7a9894626785133540c99336299e\"}", "test_no": 92, "UT": "041b337e777cce6792af25a8e1fc67f84c097983ec91f251d81e1b412b21ab35c414bb41a83b7e2a71410e0c8141932585e9192920e1dbe703a728cfaba1db1f49", "MS2": "11cd74cb60254fbb470085d03bb23921cfc0e950178bf9a046c70c881c4cb122", "MS1": "0ed5414e75ee06decac9bcb7c6866c4377e06305b34dfb18187277ef4bbe0b42", "CLIENT_SECRET": "0410898dcf874c74f3a123335c1100ad9622015db843802903ebbc44c461b92967159fc52b3f744164b35ef7e8d0a154e7a0391d6387c4545dc3cec08edd15b198"}, {"TimeValue": 1437055596, "SS1": "12e0a6e9f87d3c3ee5037363577cded5b955b7e38704cbf660c874b09b62921011a24a9292c8e12269a9df3c4a6d641d32116f43818bdf80a3763b7378ec8caa14e9ae2f943bea9f6ad6ffc639db39e538278cdbbc5b5f3fda905807bf5696e31e1cf2fca1fc5c54a7af8d890c3f848fa52634d33df5251a2e8342a9ca6cbcfb", "SS2": "10e63ecc9ae8a8c19f373507a43c8c2255bb9b9a2c269a3b5fb579b1e4822012077d4239d7f43c2104a0e96283c198800d0b1b08b9af768184ca62803976486c038ad10310fb9eaa4640f2fc96c2d53ae3f7d755fb6eb194f042b5e47695d5880e616cd32151f5ea28750b870f8228aafe9cb8d138e878ff3082c32255ac5619", "DATE": 16632, "PIN2": 7885, "PIN1": 7885, "SERVER_SECRET": "10f465853a25883f12cb96f491cba612119180424ec3163aa019bc3de39272bf05f19200f8434d39db174e8aeb67d2aa54800b628b9fdaad5c476dec58e5542f062ded6aab7081d17592b92f1ff33898f58edac3902ac5460dcbb192f4fd77c10e400849061d970b4937ac1053a65dd9432ce89ee263a8023520b385d6ba705b", "SEC": "0413bcb2e0a445b9ad55d2e35388c6a3dee490bb3aaa61825d290191e4beabd4bb0c460c2943c79beb1eb35ce99098479698c8ef366f124e2dbfa3352b957cea3f", "TP2": "040cc81d0f04ca07d8855119d6449a174724626a565ac61f719e0815b35005509d1d34e32257bd69e8f02ba348f4382faca2200c7c1ec70f95aed26993991d02e6", "TP1": "041bc25892ae2fc145e9e30e066887b60439189ab54c868d822c75439a4692aea222478137fb66a65ffa28dcf97955a99635f8543d1ee6923b3e48afd53d50db42", "CS1": "0406164d085def04524dd8666fe8893fb42a8681fa2e1ebfad172972c2e26d455321dfb4a2e4f45992bebfccd9de3e1d41898331c93fb546941d963d468e1f9115", "CS2": "0418eea5102a09912a8910a5189d7721d7047dd4d016fa7340a7e262b3ccea35fa0050cef2665f78aa3f1d9b5d8975e3d5aaf250c65960af60c1a03ce0186109d9", "HASH_MPIN_ID_HEX": "30cdddf6beeb7f4d669cbe5d8424be67a58baf9ec74bb7bec49a575c8bbd96ba", "TIME_PERMIT": "040d24bdc37ca89e81e807a7fb66501902228422812d5bd47fdf28210765baf8cb0806be78bfbcfd6515f0e23275377673d3c630c97aade0f3fe023df9f0c6a366", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223663386165633362346334393935353238343334396535343339383230383538406365727469766f782e636f6d222c202273616c74223a20223362356266613932366133656563643564646566646664393432326230303535227d", "TOKEN": "041a061127ae2d3a78f1f390ce4f1b4d36c92d78e0be73a193d3faf86bb61e1f3b01e1c8275a0934d3b522dab699ac376baa9e6125697cdd8d2167ac561c2f8d8a", "U": "040e8ea8a3f92741f34e354e3dba119549f24f22eed9b760833dbb174cfbb2f1b0141a7d91f2095f48a65d3c17dba6f17b42f1a30e996d32cfb8fde5f712340a57", "SERVER_OUTPUT": 0, "Y": "03f73d0ede5cbafef072258fd2c8f71df4b3dbe7948fc14bc33a210dc7683eb5", "X": "09feee9778734f65a5da8b9c2882a7228325820c36573e5f56ca87580be31069", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"6c8aec3b4c49955284349e5439820858@certivox.com\", \"salt\": \"3b5bfa926a3eecd5ddefdfd9422b0055\"}", "test_no": 93, "UT": "040e4c1d8e9abe5e7480ec36cbe894bdfcc5b9b925670278678b3ccebe50747a3007ca2c46f819fbe17efe8e8884528392675e14058896f4a22c136c14af1f24ff", "MS2": "0f9e2249dfb746238a929414451ca99726fe49e0ec5b09ae249d97e793d8c892", "MS1": "05b713d68901f2df89c997da46c6744a665a98ac93abe82f3e3a702b2ffee7bd", "CLIENT_SECRET": "041c902252c7a4c3f286faec720c20195a2146ce86e8cbeefac2e0ff8e6d498f011579845365bf334185977bb3a96b132fba437c30ad0d60d2ba5ea9bf9f79b307"}, {"TimeValue": 1437055596, "SS1": "0fbcc4da6bf439d5f95c139e8e07cd107ba12d4413ca2b8e0a2eba2dd4fe4eb71e87d561b8e35cfd6a729b6a900241a80396a66072271c4fcd546d1f670586a60b0bb50129f7030ba54fc6a336edf8913546d21edd9a48a34d5ae975f7a9ae620a31fd37fb761fd81c308e74be8dc92aba7fc9fdc1c92b6431e8c985f4754450", "SS2": "04d78e2e2a0b356d0775ecc8031ee976fcfbbf78d3a03ef8416067dabe10ff0d22ce90ae30e391c7e74713d6e649f8893075033e27a9a7280d4d1f35c5c0d35d0c0e603cab52cdb37f1647b11ad194a42292d0fa69622693bc6a14056cba18e0152b332d545542befaf27ec63216b3bb56dae563798ef5ace7397249f4f29129", "DATE": 16632, "PIN2": 1845, "PIN1": 1845, "SERVER_SECRET": "1a4f93e8bbff8e61b8d28f6a63351e251d59472d5cec550609e7a835bf88c66416933c1ae7cfd1f50963d2efeae36254aa6e1884a29c215defe03f970d04b77610a6e03c4ca0c84f8a338a445808598628f84803119ecf708b68e099b987908503be3f90d5b9f9f58a52c2ed2e013331c86c0bd32dc6b596d75f0a41dc10b296", "SEC": "0400e65de3e5f97623406d6cc6baccb16f1c042f9d8f5c1d0ea20d65bf5b89e23d1f1886b27f58fd5d9262b673d3b2f4fd1618e7832c3a9139c7034562044241bb", "TP2": "040df909947a47f6175b89a79aeedd7071021ce6b2512d0c9f3192d40f1260084f11bfde30aa2a12896614647de3846b9c065203a63549db004514aab87ca6ae5b", "TP1": "04218a9595f78a712af38ff477f6831cf258c14208f6ca91434648c3989793b00f217f3288dbbd9b2aa1e742f8f4a69e476fd7ec437741b0cafc5848a96c3dffb6", "CS1": "040e0c5c36402524f7a3e07d3f0e0fec09d7fee7aaa6fec76f710b44e8dd1ac9c11626557e072d7ea338eb8a744983c043bb670aafadf6c278d0d02fb81a8da4f8", "CS2": "041b3f6ad496a22c17c6288f0362450da27aa3a68c59bdce635290044772f765cb03ed0e04b218188d64b5ee4aa88b8ea31216d7bf978eb4362f615ced48079bf0", "HASH_MPIN_ID_HEX": "91647bf89230fdce7f550ef5efba5bec39e78c2e292a22e7c705f5e378d3201d", "TIME_PERMIT": "0420eb4dc6847cd410edd3398681b51477d2abaeb972f0bc4ae95c9e3e7c73b30f191bddef0904be3404baa3b4e5c7b514d7a3520fc70c3894255daf89f7bb669e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223665343432633761326364393130326661653765303139366537653065653133406365727469766f782e636f6d222c202273616c74223a20223531306361316631643030376638396263323766326139346236393565386331227d", "TOKEN": "040056183a6b018940b523c084805bc92ca9d2535d22cf604aee16663bbb23927617fb211614b15ae7773d448a389ce382ac219bb61fbb6866e3b4d835727a83a0", "U": "040fe740829d0f13a3a2abe25e96608be559981b23b4d52222c4b99d019b8b532a223d9f681c3ab49237d737de0e9580d85746c0dd9701a3e6aad71ee80213572b", "SERVER_OUTPUT": 0, "Y": "0dce23519e0326996979509873c6edc1b81f6937d18d4909989a7f3e3bb9e151", "X": "0bd93d99d758d171d2ff8534a8fb6832a43adbbac491850a8fcfae2acd1f1b16", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"6e442c7a2cd9102fae7e0196e7e0ee13@certivox.com\", \"salt\": \"510ca1f1d007f89bc27f2a94b695e8c1\"}", "test_no": 94, "UT": "040b07be6f0028feff7b29eed0a397b6bd8798279443146d58d54e1f87a955477a1aabf2e34631a62799c306b4a5335ebbfdb83e3b1f97983559b3ac44e21ce77c", "MS2": "00c7e7a33fb03964dbb5141aeff6c5f1131a1da1a93456b4403a7752cd8cd14c", "MS1": "05990b9d894fdcef972ba17763e3b8ba67b81d38454a82c25a53736f85132054", "CLIENT_SECRET": "0420753390fb186e00f66996e0f1b440b5ba8d1467e8a214b0185f9a73fae2692e0878a5aede8d88a79b90f6aee0486e8c1876e0c219ad6ef66a0dea4e17df9815"}, {"TimeValue": 1437055596, "SS1": "08f8d49ff457dc7cb3310343ad8bd2127790087cec61dff564514de872c22ce6209a6f9179778e57bde653d994ba30b1100fb6c11a535b01d0c1b3adbd0c0e7c0f712a3531ceeef0e956624494b2b0f6510f74620ecc487ac511061244d8ad251512c1ece8cad487dbafeb959d7facbf93091adeea6d5710fcae2b0723aa55c9", "SS2": "1c76cf7b5bdcf0979e45f35e9969589a5df1a28b39f15765b35549f02b0d252005706ba6c37e1d19e5fc1204d8ba6213a5bf9a990892f730954b083fefb0c817061b4c6e4d72513bca2a4f7efec0fed1cc5ec2119fb3919b32c01256827f1cdd028eea91ffc8685c9461fa091041e5786f1a954593a46ac5ca1e0995eac6327e", "DATE": 16632, "PIN2": 3446, "PIN1": 3446, "SERVER_SECRET": "05033508e4f57537c1991db0717f1dc6942e3d91c63d74155ed51d75a47283e31db2e21190e11c1e8b61a767764fc693b72efe15c5bbd01f3a1efa9bb901fd2113d0d8294d2041196a905d092dcc1310d955260fc041e27882a83c47ee0885b71b7b05354502a82d29c4d69136954aaabcacd39400665e91c5a61f351172eb59", "SEC": "04153181d3344953b2a68e1770aa9ddf6ed249fa6128364ed4417c2a49aa06ab0108cd7ef622ecf694ecc0a84f4d96703b673baf63e27926049c25ccdb578949fe", "TP2": "0405968bec2ba5b9d4f47769c21bc477d29e62b8c4d1a10a21c64a7ed40c536f76111ba0c1fb95e4ad898cd073f3a0898facee2243aadf875fb89564d65fa33f36", "TP1": "040f34f94e6fa6b50af6dba6fee69646ce39c3ed5cb88b7d15e6f86568434d0e9812a7d0e769e99e34ca8d2ebee52bd21dbeb4aec43e7d1bf9df2def9ef8b272ff", "CS1": "0402d7788fefabcead6ee422855681fa0c652fea39cbb3f38fafbc3c146fc251571918a2dfe2e6a1fad19daaac05aa29bc801910b5648f8b35412525954da103bc", "CS2": "040451ee3567f2f77aaf7c8130f9e33be023703d53aaec087511a8d287c1ad73330ebeb4b3dec5b56e7471ddcaa80de8472f3c550599d4b6263ea8f5b64b740d92", "HASH_MPIN_ID_HEX": "296836f8e07b586a75fd7e783f7eec082bb419f81fe31930b84081e6514634a1", "TIME_PERMIT": "040843b3b5bb297b3651fa0e4ada45f1ce29c62de1d0c2b7eaf0d9d23937101f290bf4fae870e271d083ce0094026a40030369d403f29074f95fad3ca3929ebea2", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223530653562663032323234663661373136333237373230663866633664363037406365727469766f782e636f6d222c202273616c74223a20223464663530366137636435303463383239306534363938666362346662653534227d", "TOKEN": "041fea2fa38d343d56a232dfd3139eddf515eec9a906e842bcfaaedf9dca549d3104b192438a5244450f8e22e71138ba4ccd231c63f7a0402ea3cf545b5255bbff", "U": "04109f98ec8b3fd842651429d09aea32f95b2a440cfc229f8495acfd37f731145903aa29da1a55d0546e30f2204ba8d03f08c04fb29201c8d6ffd2a8ef4651b053", "SERVER_OUTPUT": 0, "Y": "1f713517d66ffe0438d4f01dc07cd130277dd56e68ee0a3be0562f45cec8f8b4", "X": "0a1afab2ee3239a8d44d292d8eed33d62f1a595c0efcd33b7f1fd7fa0c6da620", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"50e5bf02224f6a716327720f8fc6d607@certivox.com\", \"salt\": \"4df506a7cd504c8290e4698fcb4fbe54\"}", "test_no": 95, "UT": "0411c32adb0c09ab89efa0909e4c655d3a561a028e04209dbb5b488eaec07c30110166711570e2ff3dc510ce7e2afce867b25774d5669ed59c799faa7a5bc59458", "MS2": "1b39721d2d49c2b9ecfd6975eb396bd0e390fde3dc13f7d7016b25627af42297", "MS1": "0ba4a0a3ca2c66817791016ba7c87a987c8da59d5167dd1dcf06d344546c3ba4", "CLIENT_SECRET": "041a4353f3aee8cee9135360858f1605232243f5957daf242a93427c139369677a1ed230c97636b22497b41fa5350e2fa4ceb8e3d60dcd5f2b2fdcf0bd2dec2535"}, {"TimeValue": 1437055596, "SS1": "2375704040c42c0fa19613c0e023f073e919c6c2566811a59e572c7fe193d3560dd70780fb30db1e965c26d06000ffea429da0fca4a9d194a3b101dec47b87a2008b0f87eb35e0f5ffa31288db5aed7fd7ebfbf69755b951f4bc44ba5ec3b98a000f62b291ce2fdb093d711316c7633362b1b4a719da64ebb9d29c97648ebfc4", "SS2": "0b6d3e005bfb7ad4d77c1886e5c5fc342fef3c42d99091f44b49b3636596374304439718bfac78e989535aaba7306b0230a08727c5b80241765edafa2e3d983213028058b4a136647a9cb0540a4a2686b9a211347d458dbaf790212a9314d80802ed46ec090d11adbe473ae8600a1d52150c66f019b77bfeb835234b42c24955", "DATE": 16632, "PIN2": 1269, "PIN1": 1269, "SERVER_SECRET": "1babb18ce759212361c9d65509c473149476b41c1cbd582a06113b2a759624300d4ff678085e5969ca5f3ea6ee3d0387bc3447f8e0c06e98b0f8788b314e17e90891d2f09ad626bb944d8a9430aee1c35e3d992a6d6680b4ca77a2e8fafe2aa60ef0e90996a174197a973512351d502640a77a5afc43161dedbb0f6380c0acbd", "SEC": "0420ab751b7b268897c6a2fb88331499862a42d43aac06cf888fa4e054eed7be410e9f684224f1e36ac7555e6552b64ff72be6fa1eb358cd8f8603551e14119abd", "TP2": "04205dfb0dab70abe40be2b08a82524e295c707e489c7d79100cc6ae1f0e02ac9d2126f3e984c10ba53f16ad87f58df9550bebfaa968da749dd8f2d79328a24154", "TP1": "0420815c7398499208e77ef5c4d1e5fb3c4f1b8a770fe9d98a3be85ded790d219f1fec187ad397d67f16e06d8e367a60d1b5870e7248c770e58db010a7ec8bafaf", "CS1": "041a0df94439aee880751dddb63a4f5e7dbe23f7e0ffdf6a497f527e829be935141b7e1a67c4fa454084a5e60eb85e17687fc339fd81a60d9e80e50b0e08e57877", "CS2": "0415181e3f47abad54ebf66a327f64b75705ee7fdca7599f02d7bcbcba5deff4aa22010bb29dd0dc5bf21f2402ab341a60ed3f2a14d1fe32d2fa57272dc7809d02", "HASH_MPIN_ID_HEX": "a132835a6c92889002d508d6005b4ddc755e65fa2ebf26835ce3887c8a81b69e", "TIME_PERMIT": "04078d251f51673e2efaea258f553b7f8295b0bfeb546b69e8d3d59b67fb4131411bbaeb4928754323207e6826e8ebaa76c490087e8abcba0e1ddbc9107817d2a2", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223533666664376262653465353663363166653730313764333266346666356465406365727469766f782e636f6d222c202273616c74223a20223263366231636265313637316438356462313437333430313366623466323530227d", "TOKEN": "041fc92813eb8a4c26be2c5be8029007bad4d762f91c1b4260db2973a56f96a3061e11aaf3be59f65b801427daebd077dd905bf730d2e8749e1bc3d7b7cebdb316", "U": "040b0d7055aeb57b25da0d459609bec14281c0752afaec904c80d0325b97e9a10014d0aa981a916a8eadb52c7165b16d771cc54716008dc6f45fe401138f3b4305", "SERVER_OUTPUT": 0, "Y": "054c6cdbf8e3a1bded4b0a1930ebf21657fcfa1069afdc2bc865b569d1d4907f", "X": "21a44c0333fd3ddaee812ef8fb6ae4529c19c58dcb4c7250fe73b55f384a219e", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"53ffd7bbe4e56c61fe7017d32f4ff5de@certivox.com\", \"salt\": \"2c6b1cbe1671d85db14734013fb4f250\"}", "test_no": 96, "UT": "040fdcedd1c8323e57682b8c1e119b33d22af8395e4bd637a43d831d8c640a82f419d8292c58731365b5153b691ac054bbcdfd3e8e3b4e8608aa3197d768126ad3", "MS2": "22390a2ff4a68024721827334b61464d48dd49d9ee98c0505ab5e227d9bdf458", "MS1": "0ded5d569cb573066bb399b8a5161e16a987d3694ab6695ba8eb7af0215b1272", "CLIENT_SECRET": "040c22308036c04c1a2b32919ba90465f2e4a7e9a84ff944746bd54251162e857c10f8106c064f87b76c95eac6cb59034a94a566bb6ae5a57c66a36ed0133b7b0b"}, {"TimeValue": 1437055596, "SS1": "0cf8c7032ffd61cb4669bea4e5d6299370c5350ae4d2b6ad91b1b0ad6bd1a10a15e241870377970fecf163f1ee994f44efc2e4f9f9c90f842a7f1320edaecf51206c45665d5ad2adcf5f070dbd9e7557e523cb2c75e7217de4882a697d27847f100476dc5ecb069e75d948b8e5ec2c4039b30fe431d5ca420759d9f1ea9f8756", "SS2": "1dda3fb581ff70aeaae6cce8d2a682c549f01344ba2d4d8842322c47846cbbaf05675b44fd58ebd19a698c45a0e449a6560362498b604266f7286b1687cae56e0b63f615a06a4c8f6a6a3b2aaad39358e55ec65a3f340f6c37c70f765efe5ba1072974b4e95809fdaf690c8edb626ac930b442a2b186fcbeb0795609ef4f66bd", "DATE": 16632, "PIN2": 8118, "PIN1": 8118, "SERVER_SECRET": "211f44dcab3d47125c2444601839b3941e93b4949321875a16956483544cfeb80b67c63957e4223c71a404f7ac3ca853bdf3706dabdb07f4497dd7dec70277040c0b58785c939918d646a6e2235736aeab1882c0f564788150652e7341e3b73d168c588cf68799214f9b1c583c5395b88a3f9219cd26aac064a2993afc9dc0cf", "SEC": "0417983991ec61b61d3ba6f5b0ec7645548c1b27334fea6fd4ce2e122fe7f13030220b13014dc6a752b1a6d7693a4ce5bf63af1016a182918c4a41c56ff86d6c07", "TP2": "0415eef6b1c841a11c5cffeea694ea8e13c4d2a636bbd61d5fd44dcbc4214b1ebe164474c974f416b35bc4e964e52252515db58e1a9d10bd7e256c378d649c9e02", "TP1": "0405d0d4c2a61c9789093a859c78d9e2bcdd4fabe25178bed483b0714513d67e0702a0b3611b4e6fd9dfe5e15407b3c7b054b31075fa8a72fc36eacc987b23ef33", "CS1": "0412d2af75aa20421cf4d95cb00a3e527bb684c38fbac4156897e6fe90090c1f860c9751eacbe7e8595ca555bbc23de5014b9669b28e45379055634e3ec016fb6e", "CS2": "0404c00a9edd002bc41c2f2b910419ecfd72297921ccf734d00cf777d73bedc1192267b72c46936a19163a7173f69cc514893997ace82aa029d9f771adb972e19e", "HASH_MPIN_ID_HEX": "58088d5c9c1ab8f4c4b692963eb37e66cdff4e585774673b66088c04820ff41e", "TIME_PERMIT": "041de835d1d026f0e82e6169254b7f655ff1aafad49042d702acda467462f129d311ef9af09bbf216edc12b775862b6c113409c7b3e684265bd6ecc57d720a8a4c", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20226431373131326236363938303461343737303135626132356434323832613332406365727469766f782e636f6d222c202273616c74223a20223432366132653764323039613361623061326664353834373063613830333062227d", "TOKEN": "04049dfcc4067b66699a448091ef15fc0b803e6ac2488d309a1f1a9627edac727d01925d9fd5c46d487f2d2fd468e006125eebf6873ab275d409395f04c81e2fb5", "U": "04086be4a061a04f6c1e232613f7c3758bf2780e7599b3c15508f403a32d3b95b80854b04d3f6f97f42814114c9e0b5a08447d6158f7c9d6217d2cd7d29137aac4", "SERVER_OUTPUT": 0, "Y": "07c40a48b0fd79a4280f6cfce9a9eb7982de8163d8b6c5cae276d93943dd51a0", "X": "20d9fb3dcda97095ea2353abc04ea1b63bf2947bb64848edaff70590770fe1a6", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"d17112b669804a477015ba25d4282a32@certivox.com\", \"salt\": \"426a2e7d209a3ab0a2fd58470ca8030b\"}", "test_no": 97, "UT": "0415c8a546c8ed072a455e9a793e37372c1c1c4636442eec29db2bde04fb032e14158a7ce8e1592109452e4072216ef2694499ebdf450de8886305969b3ca37819", "MS2": "0027c139902e81c45d98cc62feb1fae4de1857467885dd38cd1ccaa17c09a0ae", "MS1": "17e402e839a4f736b3760ec3ea8cadd7c9689fabc381da57ea20b2e4a33dc7ed", "CLIENT_SECRET": "0409df58e18a5b4f04e8388a82254f5b60cf00f21391df20e7a3ae1d3ad1f43caa02affbc281532b7233ec6817dc87cf4641e7f9a933923f81b49086971c20fde7"}, {"TimeValue": 1437055596, "SS1": "0b004f6da2a3a75c6a5da2d63a1233512e70391e7a54ca8cd08402e6b76a03fa0d35da14c9a6cd8fc9a259a2f70839248aee9b5b831b0e431a526eb29883f4fc03c5401011f2dd12c09b1726dec5a7386452a997c45d896e3f107c90b1689bcb1538a11cf9c1dd7c1c8fcddba62cae11d1afddf29374d0f903bb7673e0e6c910", "SS2": "084447cafda97dadd4b2217a58f944fd95d0024968345fec707d402814aaa7d2201c79f5ec34cf14ba224391a9d2efe9ca03735088cae1662f76fa5ff86c9eee1f6e66b8e7d11d66f50126728d2c350eeded968bb1561c9f85320c235c87da01116a269a3b80e6bf7ccf66e7c2c4da04a8d9d0e260d0d4ed9d1ad66d679ab04c", "DATE": 16632, "PIN2": 2706, "PIN1": 2706, "SERVER_SECRET": "0f4a9785a16627bd90f113bc71279417e2ec352634829f72c07e63e9e968606f23c2c5614795f97aab3851c9900f75887ad39fa3d5d9d12eb6f6f132a5e7f3e11c8d95344494cb58a431503fbf84e528ec117c924b8f1452dc89a8ef479e9dd4102249ca37e29c315fc0ef335cbe5c679da9b9c0e084f7a631e06896581b542c", "SEC": "0421f660638e521615bba5bcb7e4732451d045b2c0c879b44077c350c65887ce80105fba784a47ebe856dd08bc7591ba9921c03566a1972498ebdd6d53c91e3223", "TP2": "040c1b2aa9116178231b505c5bce386737a18c0c62e302662e90288ac1ebbe9c28181ed908f722c00b510d63e5dc52946a5e6f07cb40bc3a2471ccc8fe4ec61d58", "TP1": "040565bc8686b55279f2772380cbeb15b61bffd5b911b51c16aa840721861438440567ca011bd164509459fac958d5ea18c3dca0812e42d8402beb98893802336f", "CS1": "041ea79bc1a3edb9beca5325342e9e04b29c17c94591fe28a557e691266ec1060f23f4b177704a6904f5d97c21c7c5f7a2c565462a579c811483cd9aa243bc9182", "CS2": "0423b5dc4832368a3ccf9b560b9128977bf69a642ec613a623a639d0415be247560b9ba6ce26a0d6b7bc2a87490141d58c58e36328825d0e007bbe579c4b8d6604", "HASH_MPIN_ID_HEX": "b4964dc32f59dfb9c386321f7d580874565e0f4c6d729a1bffa3283f37c672e3", "TIME_PERMIT": "040489f6e839aed756d31d90d36458c732da325770a290f9c9519aaa2fe5d1d5b10652b23cd079252a93964c0f33958fa2c733cfbfebbea4f3d2c0bfe5dd97ffd6", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223336303433323262656135393533373934356133333463373638313538333064406365727469766f782e636f6d222c202273616c74223a20223632346266646561343362326466323236626538356537366330333739646136227d", "TOKEN": "0417ec1dbe46dbd90c62a53e68913e915166758daea7366a8cd3a835f19dfd479e048df368d023446c6e4bbf3c0baab74a54e80e104968e10bd82f95e28b0633e4", "U": "04009f96f0a83cdcfd17127abb5320e0c7e7cac92b0622fb8c38210871008a75b4085700a7886ef975fee4b5be8177b863a0fbacf550405478a5391c51e4bfb2a5", "SERVER_OUTPUT": 0, "Y": "1f5fc56ab270858cdc9b7d8e1546d6502d806c32044fc3249cd92642f5f4bf15", "X": "1223df883e5069c6851baf59cfe8d3bea1f67b506fa755970c29530b38a00d58", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"3604322bea59537945a334c76815830d@certivox.com\", \"salt\": \"624bfdea43b2df226be85e76c0379da6\"}", "test_no": 98, "UT": "041218de86b8c0aacc9b23b0cfb70efa40762573e48bcfd01b94ae9a23b6fb2b3d027b7a3dff3767fdf64df87aaaba037deda3c742ef1cb0b9c3cc98d2840ed662", "MS2": "0b6658cbe289a163159ac0883b32e0fcda1983199c92c433e1c15a7e20f8f02c", "MS1": "164522d646665c306996dd231c0868aad57fd07fdf28fd406a255846fc7e500c", "CLIENT_SECRET": "04089dac53f8c2e9a424c8bbab1cdcd7fac084bb49189e9e0dc1eaa5fb60cbb85a0411d2bdc00683ccc71029bbfdf14f1879e621aa8a0c94cc9a2680b2a8a0db15"}, {"TimeValue": 1437055596, "SS1": "232ca589c5917561a3c7b8c45c8093aa9f54eedeaf99a44651638bc736b714b316325ae8d4f1ab84269db55447ee90969c8026b485cd6365e1a5ff7edd475b00130aaa7018a73308283c394b6ee4e543576b93905315570b87732f00c159720213511643fafc781973c6e768b857ceb352e436aeda65d9fb8d95abb67d55801a", "SS2": "11789018ca0cea35d72f0549d2e23a5c5267e56f50f29ec418fbc0ec450fcd7f0ef874998f5ecf40ddc36feadfae6c4ad179f62a80098e91fcc07731f2185f580175fe0ac1aa99a50e7ded5417c2bdb94eab7c0493e24d0c0985184c26c97c3e028740ecc8a8dd788bcff3f82c8fe2e97d75810981d1fb5a5f43b21a5a980dc8", "DATE": 16632, "PIN2": 4632, "PIN1": 4632, "SERVER_SECRET": "1f5fd0ff194945dfe731045552513b2abb669a41f0d2cf02da22d3d0091ffcc72051dd35df3b8dc9e5c92e4b204ffd4c9bb3b0c612bc34f4b4ecc3019882cd8d1798e305ac911898f79ef2ccbe7c4e46ec25e8312e6741c6c0de3a10df30bb451d956cd1774ad9dc138e459ef39ed507ae333bfa2d085c85eff6426528d02257", "SEC": "041cad2b78c2b5e156c260b4bf4853e70077b738a252424c4dcb3f7cbd36e2047f0433daf3cf8e89cf9ab5ae03493a0d9898e857ed1831a43d19ace023b7b97a7b", "TP2": "041014e259e153c0d25ec2244bbf26e5caa1bc4990ebc2d99639f0d6fa7c4203c917b33850797a0d808b2a9d2709dc40e8cb235beea9e273bfd87bab2177bfb3f4", "TP1": "04222fbf092a36c9dfd4a9298a9ab4917c40c1fcb9d5600750a2c10618347592c3225062ccc12d09c3100f749f777d2492ee5182612a57bf6b48a66ce61b174bf7", "CS1": "042235a103c0683917a934d76bbe9621a46e68d09b819181f16ba77186cbaf76c9073e3cc9b8d2f02734afb15b731cb2c3cc55c4cb5ae7a2747a6b08045253bb5c", "CS2": "0406f17743cbf823c8e9afb825f2b5b583b9822ecf5711b9c05d15ee9b83a11e01040d17aa16101e8fb8464649e0182b4e097b154453974cd43c16f1e5c575946a", "HASH_MPIN_ID_HEX": "7940ee8598fde4b3298fdae68a68fd854b5a24e0229d64e094ed9088ff6b71ee", "TIME_PERMIT": "041f870e7310459a3e48abc651e20307401780c625dce0ab7cd1c6ec6eb07e0244100a0d539e5c6b39947db89cce8bb0edd37a143e16f7951ff7eaf97dad0334eb", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223934303863666366643761333231386438633436376331386365393432653832406365727469766f782e636f6d222c202273616c74223a20223037383965303961333963643966356238633563393466373839633839653935227d", "TOKEN": "040270d946f220f442131ebec67d56f4e3c1039feaa3752faf2f7fbf8ae8c9500e0d67138f439321fae1419616492148f2013477c8fd02b6f848f2ccd511e5a3a4", "U": "0418b3aa7069b548b21cc29345922c9c3f40a057f1df6f34b7338d21842ef0bee41f70ea5ffce2f52e36687e1fea11eaa77905282378e22342f91641300b599143", "SERVER_OUTPUT": 0, "Y": "1c0fb063648c878a0e470bfb32b002e3f964f58c1571847e94db69a5bb5666a4", "X": "07c34f1d1c9c4b012a0af12de0af3ebc543b6adfba672d854b8bc213a9ea905a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"9408cfcfd7a3218d8c467c18ce942e82@certivox.com\", \"salt\": \"0789e09a39cd9f5b8c5c94f789c89e95\"}", "test_no": 99, "UT": "040abbb093a0bcfdd575de98797284b95328c2b72ca4492393d1fb509cb423e20214c833a6e2567f374c8f94946d3c1ee10b5c139bada048f062a6b4911ef5658d", "MS2": "17ee8cc15b0dd1ac742c93a16ae2f8c4ae5306384f3814106bded7d3f2d2fa89", "MS1": "1d52c0d144b0ec072f2dc4518144c50c7a066bff88aeed17231378f234e8bf3c", "CLIENT_SECRET": "040b77e32b0b502d3469c7ab7f1bf9432830fc70a2dbee79d1daf1048f0b500cdf1c3d2b869ea0944ffb38ae58d7d3c324da1f09b3b183ec21be3b0adeb5647c7c"}, {"TimeValue": 1437055596, "SS1": "12e06a4620e48f0baef1547c0fabd27e434645135b890f5f33da67ae2d5a3d0507492ab8eb515b9091b094ec850c7a5160866ad94e45c5f9a25da5e91b025d8d1aba0fd74e73dbd01b04fa3b9b07ea6e75d653d89fa6f4875d5b37dafc5648590208260dc9ea2c2f7f10da2016430fcc177e2d22183976450c37e79581bab3b9", "SS2": "1c69654b6dac115954dbe80ed87008653a0127b3adfe320bf585fac2078460f820d54c622be2a03f086671f0a9c3069de679be7db8ac320fedd80a6c924cd0851d0e0819d0721b3c31d12ecfe316fa9ea012d02403b6a79c7381a108a6aca23f142c33455c011641d68b78a24f4b1049b41963be85b48cff76c9aac3668ad6fe", "DATE": 16632, "PIN2": 2863, "PIN1": 2864, "SERVER_SECRET": "07628bbf10df97f554fb254035966db75f45d2b4d897635eff60a80d29e2b46007063d5a2aaf337b43d520c982004ec9524034075e07e573e14536ea0625fac70ae6edb1659129177688d5ef97c7e729c404ac11bb2fa66715da62838d6b1ef207dbb1e1db7497fb156627184e5498d369823e3f17efc3cc864e1e5212332ec5", "SEC": "0404a8cbec5a645713cee832aeef9b67aebb6a0cec45f0b9ee56a916be996c24d7059ec2b8af58e50198d9834eab539b3d5eaa534dc91d394dd5ba6d45c9d95795", "TP2": "04144e53b7aa91706fea3e54b170b5ebb1432744eae237e648844d8e27f7cd6696013dc4f3adb44a0a79ea9f53a22822ddd59d73f4d2b937b695c7a17b90ec8c5b", "TP1": "04051afa407ff2cb9c10a54ec0903aecc87c685b05bee97a2bbd496d7eebb01dde0dea7657c157533a127117327ad2a6da56294410c4db7e209d214769681e3555", "CS1": "0412718d4a2108fa3cecb937ac8ef967bafb7d0776d10ce723d27480edad482ba40e067ca9e1f212740585cb4e8821adf2909a0ab15ff00b57ac00fc942d6be81d", "CS2": "04063af749c5e9c336671c9e40540704361dd1e454d783711d8bf76ec502c3de1403b1cd98e383dba92f5b7a413cadbdbe65d7d6bc79b1c4eb58a80705a669cec0", "HASH_MPIN_ID_HEX": "90d1b22f534377dce6772dcafaa1f2968616a91d1381bee21810c0a2fcc71c5a", "TIME_PERMIT": "041298d659e3a38cf4d81c9e1d4acbe64df6e50b91269558c5b465d6f7313417e41edd5e6890306ff6af8b92debaed252185b62ec7c1811c7f46b676bc274c0519", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223661373134666161653761333963333361323764326566633336643661313831406365727469766f782e636f6d222c202273616c74223a202263373761306236363333663038373564227d", "TOKEN": "040104704da99c46bc7111886832b75db894279111a94b1f2118595b6f3d7eb9b11536fc03dfbf23dfa36247148c3b39a53fd0ebfa61b2d9e64157b0daf2a723ea", "U": "04065adda797146615e03bfdc45838a07378a4a606d0041c5802b489f3d271819f1baa30b9bdd78ea97924a34a344cf57e4425eb04e6a22213a31ff791b2d8ec2c", "SERVER_OUTPUT": -19, "Y": "1e378776f4c465a30d593cde3afc3dac0b61e4c7fb791adbf9340613c8aa4696", "X": "025fd1c1a7147c7f087c012798f2a96727e19bde91d48bb3e8144f45ab75c7c9", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"6a714faae7a39c33a27d2efc36d6a181@certivox.com\", \"salt\": \"c77a0b6633f0875d\"}", "test_no": 100, "UT": "040fe23e93adfcfde9cc8e232be44e6e10ae0a3a6472c037c41ee9542ac370aa6a034429f671ac6b8064fe42391b77d2a2f68493a84ff93297ccbc65e96e4d0166", "MS2": "03b84665449b9ba46f8bd021de4a0d62937f026845d16ed89d1a93db30ef377c", "MS1": "167b3a5e6cf4cc967b613fb46988af9332da80b5c73737bad340886495f6c52c", "CLIENT_SECRET": "0404c95c1b2a01e3ac8a292daf375680c693a27adbd0c32eca1e39c4baab0c6caf1fd7f54217f564c4369d11cd6aa348d90f93a2b608d219d5c3552b36b67a3a84"}, {"TimeValue": 1437055596, "SS1": "2021f58d665e73beebaddacf5886e425f7507794dc1d78b2fdacdb37c187c9361284481e7154a4f16b10355ee2471c2b64dc4b23f6540370dc1714a9d98b838a04a8e8cb955857386a92d72eef907f388ef4a0737f74131e80863f74fd38a8b3018ccfe952ea1221fceb932a75411b37d6b8ea296d4eac5309fd13805836d382", "SS2": "00170282b27e391b8cbc505ffb895013d0e8bf33423a36c6e531d4748cac7cf40e7bf6b233074c97630fdabb5f230b6f98e7efa85bb9756d3a83c983b979f19c185b14e02a54adf1e974c1a6b4b6924c0c29f648e66a83be63d1958d8c4a5d6d1639c97ab8d57f53e22712a77e32eda4239a2db9e4991b2b33e7c1d81f39da94", "DATE": 16632, "PIN2": 6782, "PIN1": 6783, "SERVER_SECRET": "0b1c4edc44ca301d00f6e2efa1459722a10c53aefb914e6b5f81b37f8321f59606f8a7d7351fba67da419671558273410ae162fd1074bfd8c3a3c51e3e602faf087bcfdcddb529bdee9ccc47027600a4bcfabc7f34f2f6f23ef64f1b08cc769510d2dd41b6274e87a99d059d85381824415a1208cb7c5f1d75b61f575a2e213b", "SEC": "040566c74f74ab966cd154969a081398c994677c9397acd1e509021cf4ce50090911745450526c9be7581e929f798ea4d71b4be53cfa6e8619093462c889ae3582", "TP2": "041c24bb34d742ab6b1284498d106f13f5a9bba2ec6e9f0f9b11dcfeec1db3bd5d02a4e6ffb5cf9e3cd258b27cb4651c17d369b6fd0021d6de6965be863e879b6a", "TP1": "041283f583a4c314e437eb70a37fb0da8e4edb0f57a260ab4c945c056568c1cd52159ba2f4ecb877c18009df3cfb180ea4d1df2ae2d03619441b09d4e5c26aa545", "CS1": "041480507b811a2b85fe5d3658dc686393c874c8ac827e0c9cc3f53bf2198df18723c8876326e3fd1852efcce72a24d537614e23a234a3fbbd45544f0fef2b96ed", "CS2": "04121c8360fc39a49040e12abf78c50bdc5946d351088772b3ec7289849e0647341f373c9570b1cba9195ad8d6da011a40a70d3292c4d4e8ce542bfe4ba1e9ce2e", "HASH_MPIN_ID_HEX": "f021a566d9fba1d909823659e5e839d38da072a52c27746519647390d8ac87fc", "TIME_PERMIT": "04183044865c0ff7380a918cc1605ecf7adb6cb802679d87ff41e17f31efd12e7d0d9ab14a4b5ac6ee2439f0c184b43381ace1b7b619a2cb7091b0b369cb5fa350", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223765343239636333396136333833393562393434363266373265383630663131406365727469766f782e636f6d222c202273616c74223a202239613932306637636335623262396564227d", "TOKEN": "040d9cb2ca84c6abc14e52dace8d6e537ed44b474ef186d6e7074844e16b0046ad0970229e4e9d3615d9bb71eeb02b1faada16abbe555c1185799458f93343e69e", "U": "04188be260fbe9ec3a900aa14c83d4db61690d62c876c9bf7b8aebbd8706099edd183d383e0cf62de73279c3273a9c210836c7ac9c7d32e1f89765f1a0d344e10d", "SERVER_OUTPUT": -19, "Y": "00bba3fa3728400a934cb1eb6874bba5644242ab4006caead5e491ba30f6843e", "X": "1dc25f4a7f97badcea5c9a057d13f12780bef4229567e936fedee4b733adc48c", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"7e429cc39a638395b94462f72e860f11@certivox.com\", \"salt\": \"9a920f7cc5b2b9ed\"}", "test_no": 101, "UT": "041b15412bfdff52d2f50799eb826ae902fbd1a9a6df46f42bbb2664c1cb2507d91166047d064748c7729013cb3b620776c6fb23243447e67f8def96ae00134d3c", "MS2": "11f9c28f4c90347e523a71f5011213a5ea89c1c98be571bc248aa990dd63485d", "MS1": "22b60f7cac13dba6943b766b86fe52041cb3564914bb0224660bda52a0354a4b", "CLIENT_SECRET": "0421752491644b979916ce14db63717edd9987f13fefa52b6b424f5ff3327e3ec30eb4dac3ec68acc5ae8609036a2188f171df7b0e81a2ca9200bf2d26c5be3dc5"}, {"TimeValue": 1437055596, "SS1": "225670f9c55c6e55ba9e9358992f4397b96efdecd67c51b5b289c9b451804f8f1dd3795f39815924fa52c5ab1195e7e91508450df7a5bbb04de6c73f5b9e2b2902e03e4f5bb753c80897f0b32979bc2ad70efb38c22e70d92e876b634757acee03762c4817855b625fac6ce7dafe66475795b5f826ac6f6ec3ef3e0615a8e67e", "SS2": "1fb75b8ce91f648df2fe7c22eea8ab1d79c2ee930e177009e18a11a7c5666d991d6bd3504200f9e5585f3b64027f1208976d31380b98b063a532dab65c45f40711eb02f555080b32b043f5813972208121fc2d0dfd89e5d30ba9b022db49601c223bbc193c886b48cdd9a58b3fa5be54bd3d1e0e2d6b368eb61bf05171af45ef", "DATE": 16632, "PIN2": 6882, "PIN1": 6883, "SERVER_SECRET": "19d7894de44d412ecd700cf592a074988d0612df7e7dd05822943cb013d4394a060938059b0c40371c75687d5b4d7c080c77a1aba5f1464f5fb73bb140d2e299076315a0c19f6fb9221a323dc54c63cf94e98acfe38b531c056bd322a5f8ccea1297e3ef089697ba3f6c301070df0813f0138fcfaeeb1d5f65455403c2fab221", "SEC": "04147a79cbe1c02c7615996e74af8eebafc16caffe038896e056a399b77d9636a21825db1d5911de38dfde0605f24d1062f82bc4a0821129247d5a5afc8786e04b", "TP2": "041c40524901230ee740c7de191ea07622bd1136c9ecede84709d3e4b18cef9cab117946900bfb44f808ac6dbcb51e95daf600a5271fc6e435af4d03d501f6aa44", "TP1": "0418a35e5f91850657b642b73ea6e71bb3869f67ce3262d09cd3391aafddc5563b17bcb4be976388940e40bf5cd55f4337776b7da79143c87806392d2a87079863", "CS1": "0419812dc345f58cdf0e1c4d13a60005c49d09b2dd920badbead726083e29c6d410b1496114166e9e4d8360bdd7c08e36752eb368b1f93590130c169c92021a290", "CS2": "040895c37f84bc732711e3248ba1da9e54dcb98acab11e1ea2945adaefeb0fbf9d07e1e3cde7cce521ad5afdea9e893004afa15b96fad5d94ca6401316a059c17a", "HASH_MPIN_ID_HEX": "4ac1c07c92cb51535dbe06d8544a0296235136d3b953c1242b5a4000944d9ef2", "TIME_PERMIT": "04118bd0b76c96f73a001fb5b995a1513237fb533060a1b3a800d4741021f05767099298fe24625eb688047d46e292cf8b0138b71f97e2ec7c56205d411806a9d2", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223634373565663239353162373165343061626663653065373562393963373832406365727469766f782e636f6d222c202273616c74223a202265336663363763343039353265346263227d", "TOKEN": "040043a5074bc9faf84193b81462f2eaea7bb0541ace65ce3456a630c7ab2cc82900e46461c4f67769b7f834f3c3826976f0c73ef83980add8677933e1588365e8", "U": "04235594f10c694307eb89a61927d0cebe749d60a9a1f89ad51e37312e109f3ea31fc880a828da0a5fe3c210f4c3e2676f25921ba6d1876d16adfb680e6258df25", "SERVER_OUTPUT": -19, "Y": "0035da307ac15174c5b0e3999665dee8ace46e67fb91565e509c6c7f2ac2a99c", "X": "156a975f94e696d0fc8f09ce3fd17fda1fb60c6aa758046c1a316846508f1006", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"6475ef2951b71e40abfce0e75b99c782@certivox.com\", \"salt\": \"e3fc67c40952e4bc\"}", "test_no": 102, "UT": "041befea37fc0fd5ae12e979d4175ad0d07644881ccbe956a07c2548c23bafb7ac064c28d40892c29c50a17c286f72d2b8366c3f8cf04342365e2d476b8ffc1882", "MS2": "03d74d1c42d0b7777f7b38afde4d403b431d58c8e13f15ab17113f467e9b917f", "MS1": "0ec2d88a1c826fb572a5f35a99bb6e2012da29fb6eb848c6bbc023f164931b3a", "CLIENT_SECRET": "0407f5569ff61e37a0f10c0ee215979565ffe4a1b23c3413540e2c100057c652d4077ac6695fa9c813be8594602e42be407e48b309e5bc4876290fd7d678a17dba"}, {"TimeValue": 1437055596, "SS1": "04b184b38d20ccbd0d2a839d710abca720e3313a3bf44db57a3d74ff436c7db70c4e6bca4835a44156e9f9efbe2c3dd0f2e23a1e19bfedc6735907ada30867aa121b5f9466aa73a6ecacd9fc569a36e10fc603033971daa0668ca853ac48b3bc16cf92f40b475ab0af31a1410188a2da7269911314453e61e6b77c68e3555f45", "SS2": "1035a8d512011b9c683359b33588273bb07ceb6107894b99c50985b1dd69108a17b6d8d50f895684e1eaf566629692f60c9edb1d31d3f1e31a999553d0c803e601f04adcb6869717a5d2996cd0b791b7e06f9254c9961474709d9a258e89f43618b71a46277d481b90d15a31097da69d3f36f6df769aeec04e81181e59666546", "DATE": 16632, "PIN2": 6267, "PIN1": 6268, "SERVER_SECRET": "1c44d71e2722fcc54bf3c88bcea2185f8ebcf2c1f527e35972b0186e1707b99e0702d7e20c4b6e2d6a4184f1fd52bd6b2146e3935111e880573fdd017931f8330a9827bced09fcbecc2ea8b11bad4d17dc00874ee1f102c991d80013fb6c85eb0d0d30e0b023256e7dbee036b5150905d1a90b3ce11efbf4b2ed4586454ce8b6", "SEC": "0421e61c792e8ed953ee0f028a28da41c42bac199d374b30978722d7b19d13100a1d56e4a24cb6977ea2373ffb472743988c29c478d0465d65d51c291c82796785", "TP2": "041117f41cd1c69aef11e3cd96e6202bd593544e4ba240158af5860917d82c03d904321a4e813d5e9265310521f5274665714c50f123c1b9053543756bfdac0a43", "TP1": "04005ed388d94a691f8cd571ef924ba457b2b0db57c454abfd31b7fab1d2de3add03b89988e6f510a3663d8e1aee310cfb0e2aa531fa312fe2ce61f90f1c379fca", "CS1": "04234e11f172e346d02b26d2062da3cd74605e4fbc97223dbfe23fab3f70516421160056ac9fb66be03531c708c9b4d4c586b6ce7b5b5a5b678d7b9f160f46dc4f", "CS2": "0421f0812a828d0d2372516593a5eca85e0d3c21366a3dce515c0e119d44fb2007035659e27214a5e9a31bb2d3444dcf7722be9a8755439eeb2fae629f330a1e2b", "HASH_MPIN_ID_HEX": "f45457c22c9443b5d667e52fc19b002fe8d6edeb9004b78930427adf67cb4a5f", "TIME_PERMIT": "0403bff786d963d99405193445e1e42d3c172aa81890215700126e7fcc0c72961b1566af0ad67512db6dbb43bf8fcdc86d5373de1869000732c7b4ffac7584c986", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223966666531646430643935623837653734633036306137626435356261356666406365727469766f782e636f6d222c202273616c74223a202261616336663033653963313466643665227d", "TOKEN": "0403ee5e87fb674ead4d8b90f7b3824ed0dbebc55ec7359a4917f20f9dc092376e1947511f15f2dfc241c3a080c9581fa14bc69b659707ff4fd595ce7c5d8573e9", "U": "0409889217416c4de08f62fc021c53e32997dbe0bd3f29b13aef94987871d5396219a953297537940594baf63183761acf995692ca21a264e34a0ef711c2429bca", "SERVER_OUTPUT": -19, "Y": "06752f8ac43cc5340c791a9a0487129a2d2a8f83310cc09519c009cd35dc4275", "X": "106a51363b0783f3d2dd3485ee1f5d863dbe538f643e7247794927ddb6b2bf1c", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"9ffe1dd0d95b87e74c060a7bd55ba5ff@certivox.com\", \"salt\": \"aac6f03e9c14fd6e\"}", "test_no": 103, "UT": "0406617995923ded5215c89838c151191f7010f19ade01adcc13543e4d5ed36762168bc61bbddc4d5d4fd36e6326a41a37881bf4241045c55f4403d1eb5326f2dd", "MS2": "027295f21dc85e27cbb63f31219daf8bcd4286cebfabadd026abbc899f16ff77", "MS1": "1b59ee246497899a30a7cb1a2dac3232eb62cc81a692b3eb47055e28879b1b78", "CLIENT_SECRET": "041507364ab4438cd4f56d2c35ebcf50a6d35f2879064c77201aeaa61473509b3a1de46b862702937e1909c30ed2488524b511960704ebcd7e493a2e9e468f823a"}, {"TimeValue": 1437055596, "SS1": "06b4136da83250d985f73821998e2d8573a395041eca273d4729e4115ef259b501d96f68bada94a65e7210f27ef92c31ceffa567b695898ffb13fdbc776509fe1e9142d2ff7ce10eea365ea9f8c5df207b7e4c272ca8b41d0009bc794e8c10a81c77bd4453d2ef24e34057513896e9a9a9582c3fc71899e740e3843ac0d96116", "SS2": "09ca8a03f051b5eddd91849a5c447cb74c2eb9823a63009e38a63d32aa2ca4ad0aeb9f77018ecdc9f3ba343ad0abf4f03289437a8fec44e5f87a11c682c4dd5f138d4ac81e449ce5cc80709fcc476282ae1710519884ae0b86cb75bfb0ead5661c0f3eb9f63f2d846c7fcdee32d8eec159129ad57f0c7a676c2ed32baa1b206b", "DATE": 16632, "PIN2": 5285, "PIN1": 5286, "SERVER_SECRET": "1d7c59d0b18e853e50601fd1677814558fc09484977dc411901a745851488efb199671bb55e6eed28c4c6f77e28ebe3665678757de7e3752c76c78270c9905bb148ba5548875a5fc2caaa2850de1edd87554684146b890795a65e37a291726790c41669a81753bd068957558d4a19e02a8b8af3104469c4937003a3f04677d9e", "SEC": "040a529604eeffd1bba2f7fa89ba71d9fe40b01e2001ea0429790edf8497160ea81a438efd084b631c315c5bb1b380df6f7c963d2e94b5dd01fa51c44da1b3dcc6", "TP2": "0420ba988f3755d31f44153d4d191a99b3c7e28a15b4b883359ff17f94be9745570ea83cfd0dc6fd09d735d2b0e40736e72847864139338620792e7a548d1a0ea8", "TP1": "04145e69f1375a8d567fdf1620a7b87383c83386996ccf52c99a0e468873c458bc03a8e2eae20cbf6c1fa7ec424a109a9b4083cd959b39b48fa2a2887201e8dbe4", "CS1": "04147a0c6a4b3084b4724effd42344fcb88b83004dbaa6b40c5f8af6c039eb860a222de136847da557032e4299173229fa27cd6bea6e65c56fd97d9b710f45979a", "CS2": "041801b5cd72cbeecd3cb8d836594b74468e8750b838b41a4fa865b3ed42c448a31a4682d5983be6052b576c863654880bfc1e9b9343521d5e3e10db6d099762e7", "HASH_MPIN_ID_HEX": "eb850a58d158eec807f216222880c1246c17040db48081eb93860f4a9bb54843", "TIME_PERMIT": "040c0855e3d89af364af12b96018f2468e9ee7efcf2161d930178bfdbe6e45263f1487de86d0bb6b5351d891072ff05f5e484b6db0fcbbdb4883c8d1dc9fe348b5", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223663323462653034383938616330356538363765633439623130343839616639406365727469766f782e636f6d222c202273616c74223a202233613233306333633566653237313039227d", "TOKEN": "04010ba3ebbe39994c0c61e0cd439e962ce59293161c44ab8a3f2c160d0318edd60006972f0e1676a2c59b790196377c2cd53d14c4148f061cd220be4caf32c47c", "U": "0400fe4c635e884fdcc4c77314d27f9b362bea55a5d2385930b89258846e56003c11af72e5257dcf0a9ee7c91c25bb2c9d8003b19d390d46688bec8b6a5a79eefa", "SERVER_OUTPUT": -19, "Y": "133de13a673dbc1e356c0e3ea5aff2acd66b48505b9827badc8a92ea950c670f", "X": "02369823393a62d4e1d258f14eeaaac2133f95599ea61e870c2df6ce049629f7", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"6c24be04898ac05e867ec49b10489af9@certivox.com\", \"salt\": \"3a230c3c5fe27109\"}", "test_no": 104, "UT": "0411ff91bc8f38c928d0e4b2bf9a933cd5e7d94ccd784f27e5473140ef2b879d7c1af71bbc84c59770795fb1a4a91f9f3b264067c2dacee1485cc17700062df47c", "MS2": "014ff2756b035b7d53b5099045e227c800ae6c89092aa5491d661ae5a7a1601f", "MS1": "1de078f3f7100d1733e752b63fa065c982a663134b0d8b18c2c82b6f1e634e67", "CLIENT_SECRET": "040daad48dfd9e99a6ebc736f3faf99999a217a2d8e6d13b0b221714132dc5035d05e2de33fd664906fde819ab2886f18a2772937b7d4f9e6d939c0345cab9afd7"}, {"TimeValue": 1437055596, "SS1": "0182e7e894682fa24bf4a2a279783c70044aa60509dbbeb89376a60dedca737e1e771c48360ed41949762adc29c1485dd965f77cc80293cd9d60b16750262088091513ae18b3c3a6a63678c15aa0366c6c5f673bc91e7b51a292a0179a32fd5605a997233e689e1bed37e76a7826e4087cb3ecf7a3c33f3007ae25217aa20807", "SS2": "0615e8bf677c7d53d95690511939007efc0755fac8fd208e5a002c147ae6ee8f1be170b61a12158028e60955e4f3a3437a9d21d833fcaae56b944421fd6f6cf8181a6a11c80e87f8fa2be5eaca93175dd0efe3ba9bb0a75eb014da1c0af444990d0b09eccd21cec2f40998ad7841a72721620ead0c52c8279774cc9f6f543af6", "DATE": 16632, "PIN2": 7647, "PIN1": 7648, "SERVER_SECRET": "016542b22ec8bf016264dde9348a7d003a5d7480b5fadac57e87988fffec230f0d9a10249fa2d813be947f8164da54d38decf48e6bd646b9c1ed480303d2e09c0c664cd55832b6f371f3535b86e2fb765b10268105cd716600821d34406fe23f0fdfaac6a5e81bdd3da61a6a9d1a34695381640368dec8d517f340a0ed0d7a71", "SEC": "041dc36a16a63c55bd62db23e45f6e59cd2a5907faaa6a5b6a6099baccecf4852c0ba44ea7beedef58ad41fe9abf856718bfbd0d04fee18c0064fc17720d133dc5", "TP2": "0414bfa74cd952e38a8f2723870e4fa59c4f69d6ed2b92051a883cdc0917e444fb1e9752b0f306512afc6b8320c4305b765d208b7f497b4b0f244becc23f0044bd", "TP1": "040a26ef66abc170b3b9e6ad4f3b4aea41187ea0030c85a88ce872db0e89e39c1114835a8531467446b6e3637efba29e2f9b6675b0ce4b82afab90aac115727ce2", "CS1": "04079a1e33d1b7b93103d8c4475c74b929d8a36b4d02f0a25079c62ae07b69e05a034e5229c370569477166d2c530ea4da723b2e8da7c5114dc8d66fe472e94fcd", "CS2": "04095c9b1792c0d8397fd2b56af158e6afd701e795a0ff892f809df854260c8e470426dfa58ab44237dc0f18d5a3797c24b3e96eb75c1a54ca772bad4f1f2843e7", "HASH_MPIN_ID_HEX": "113834ff5a57f29ca273ce104ef2ef9ac1d3df62c168e93dd52ddb551fdaa185", "TIME_PERMIT": "040e990d958f2d6ba7d1491b4985244072a710daf432de1e99f58e675ee0c0498812e694856e618274b8004e902797686e5843e5a2a93ba6c34c167bd342c20f9e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223165646638323036643239663837396233636233353238316266323433646166406365727469766f782e636f6d222c202273616c74223a202237333163363866376162386339343933227d", "TOKEN": "040469ad313be29da619c3eb33e75fe68fb5950347e987c289917906286837fad111cc29bacb4696c7aebc054698d5a897699c557cd5ce1cd9d15409fa178e4483", "U": "040530095e32d52eaea70ed45d5a0e15f80816dec33329f9b6ca76112a1506cf6b2169eadf10adcb9600368dc1fbd659c2972b9682f85d12d000a444e33e9df8a5", "SERVER_OUTPUT": -19, "Y": "14a9294d442551cbf7be4d6f32f3df0bcc40313c59e679b5b9a272294cf277dc", "X": "23e19434748695c0ccef7fc9496dcf2582eae7970414f26978e4a662e31591ca", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"1edf8206d29f879b3cb35281bf243daf@certivox.com\", \"salt\": \"731c68f7ab8c9493\"}", "test_no": 105, "UT": "0420ad010d53a32d6caf2661454ebadb30ade8f81d9594c6a22365c96f83b69a970d07ccfe4f70f4a4c7b5e9bc964a3ccba0646d4df6abc1c93a537132feb7c7ca", "MS2": "160a2d932ae72834984c30f856207615abf6a4699c9f1f08186a0d876cdcfb98", "MS1": "0fdf3453cafe2a40eac515d2b620e675e5ee8353a51cc84c1835ffcee40cd4da", "CLIENT_SECRET": "0421a7175e261a8897a16af8a90c028aa7b6e76400483bb8d28d6d031c12bd11061988862e1b7725bec961babc4bf904781705cd229f3320e3ee97dd9e43d5334d"}, {"TimeValue": 1437055596, "SS1": "231c28453011fb5189159368cd299d5eab7c39a4c8b3e8f587df9dec6048b0e013848bb643b23bab9aff88dcf82b296cbc03078fec65cd024caf1288f6ef72c10b3ba88d3ac129881868a0aa91978c6bdc2a4c8b0dcc3c5be2a37bc09f3cad5604cce7466ee6dcc803f1f2eb10cf2533cee317d4b4fe8b3c75c8157251fe29cb", "SS2": "18e7ee96617fa7ebfb3332ef6b80ffaa9be7b263cd3730701224510711bd1cb406c78044fc129a0f52a30fd95df41e1e7af8cb57c3d66792034f2f4923be39e61b90d7059af823f794c1792a25c4dd7ab412aa65136a86cd0e4fba8049cc3b6e0550fe361a90ca8b5818bce79d65dd104ca0d601af22fc09e2277bac2cc02bb3", "DATE": 16632, "PIN2": 3817, "PIN1": 3818, "SERVER_SECRET": "02cc9b5e05d4d2b5b8229d21b7d48d957055f7c17cc0e5b179951102c15fc98b014afaa0ffbcb080370fd9da18e37983e762b47a9badae80cfcef84c4c44028b0f31f801a68302d73279271a6c7b1665a805ddb6e241490ff0a96d7d54069e351c8ababfd5dfaee1459ae3d177b263c37d584fa6545a749dd27117fa9e6e824a", "SEC": "0421abaca8927be4d33b66c3fcb2d346421c924e74cdb0a4abfc32814c0cd8854922bb1fd9bc685d607f4ce5aeaaff18427e19872b405b7497a4b4793fd3b0f9df", "TP2": "0405f42f2f69517a73f31a49842f4c17f84cbd8a2af7fabfeb5d519b06328c266f0a1565acb59420a7df03d587267c04acdf68a70e515c0569b2271216e5ccd83e", "TP1": "04109a3b2b658715db46ec956778e15932dfba4063ce24d98635955881c411c33107f7e11a87c5a821843db5a9c4d077eff6e89f9a0edf87d82ea6c29270360599", "CS1": "041bf24c29962fc451a3e540571cbdd9c57e446769d95f5b5182dc711c32aa5bbd0febf7b286dfed5d187f98686075299337b1c1da3d4be04a48ed6339ad3ba27e", "CS2": "041c930ab5cdfa5d4213b8b283cad97161bc983e303c1dbfeb6b6f7e5017f321870e7642070ca3780f30ed9866553f3abf641cb424f600f1a7fc53ec665ab3b18d", "HASH_MPIN_ID_HEX": "0637640b8610e41d40a658bda97dc9a3b9d6851bec4b72e4c54a848172412990", "TIME_PERMIT": "041b497d5556b927b59190251d35ad2cb12c7b7f66b0126577661e2898fb4c1d651582495bf44e9ccad34e83a2e7ce3a59d8d3f64895cbb2a274a5bf08dd14c986", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20226130376533353734653739633465383137313762306462343866303536366230406365727469766f782e636f6d222c202273616c74223a202237346664343065373465323936333635227d", "TOKEN": "042151cf3cb8a6bbfef31d6ae3f97709c568a320a3ec0a55fa7959707ff164997821bf8cfa5bbb0d7e7a2bc16d8d45417f305f5c9195b93d394f58cbc84dae9a35", "U": "04079cb9d121d62876b0454f90f372ac2ddde8a1e17c7c66a680cba8160df15d07026fdecd94fc0f9f86ea3ab919ca980b7eb1fa93e38cde0cf15428bb09065615", "SERVER_OUTPUT": -19, "Y": "143a08402d60168a45d532b1b719515e4173b46d9d8a37e606dfee58d4f9d01c", "X": "148e9c2f66c03de1d12a7698d3cc328494f14a00e0600362de2440db379299ad", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"a07e3574e79c4e81717b0db48f0566b0@certivox.com\", \"salt\": \"74fd40e74e296365\"}", "test_no": 106, "UT": "041e9176041b4fe36d964f07ac5aee0cb46dd66ee586508006e37962dd54fcb35b2004e70a6bdb212c085899a55e774bede455420e816fc7bd9e18d665d50fce35", "MS2": "20132c835f800f71b6b17499fe91c9273bc092a4620a80b172644ebddcac550c", "MS1": "160fba953d2e5c27c996c003c6e74d3334a26355e7edbd91d81e8ec9076d35b7", "CLIENT_SECRET": "0417bcd66abf493a347e7a8d8e242685e139d91c53aa1bf88970cdc567894cadc105b4f0d8368213c6a9fae9dd6ac9d80b5ab04f37ae2ec6d6544b54449ad0f735"}, {"TimeValue": 1437055596, "SS1": "0a3ef6ac8f56c91cd0c7a027c2b70bf1cd46ba73391c43de87756fdc47464c08232698ec26707479f0f6df547cb18cbd32f5fb13b64d6db8b9982c399eb9646a206e4656aa092a9bedbdc82e9db2aa43d43d5ed4c692f981a4cee346ac46efbc1c28c3b01bf8019459e0614915b4b499d5845bb43bce6002baedbd582a59e859", "SS2": "2380239b4eb3b745b08d78b237c0fd1ab55385865795b15beafdd1845ad9b80902ac0f1ee4cf0b040bfca7a0e9c912a1650a578f312c5a6b58af966240bf4adb0e93d4bf91f738d04a2b65a6bb3b0b01d24ee6a482e63e89fad16c63fc09966f15d844793f195fa4fc5e7936e2fc12b489b258fc282abbccbccb8ef0cfed7ed1", "DATE": 16632, "PIN2": 5884, "PIN1": 5885, "SERVER_SECRET": "2252d60bf332a5f966e0f987080ee9607fb3e62b880657425da376c5c21b0bba077b7fcf3a041a21003141283156798872e3d4aaaa72764daf3c0d7b5d76aedb217019ae27bf20e51dbf2840eac24209ef3f79357c27599202c4acc8f5e3754a183373d686b898af72aedb728a5ae5614b95f33391db52b695ba7711ca4abe1b", "SEC": "040a54450fe0d30b9784cb861798fead13fdbc272077ee8b64cc11d520112508760c2c972a2abd36d2f55cb98bcde463ac1fed130f5be3e8b4509eb82c1f1bb6ce", "TP2": "041d379553ebf8c0bd0e583c0b0f208eb3c03e0260f99c897fb5dca59d37b8683711f13de3adbcf7c6180e355c74a6a95aa917ebe9b82ac2ad0e0b2dc3ea24b885", "TP1": "0413e82c1bb73bacf86dab105b247c6d39a3198e852388386542ce4b910859c7cc02d93f170bad95e227248fbd0ea8b07da45090e5654eab8d46b6e9d3f6a3d243", "CS1": "041fd1ce64b2f09e5bdce82658a8c1e99cf43b7a397237d8f62a1cce7b4e0c8805132be2a3f60038549d751b3f970564cadfd7284b0623f8ab9e37b0c45d2dfb50", "CS2": "04170135613d625d4847a29542f909db633bbaf692216d278e6ebfb2ef88a2ad4d001d3bcc13cb5089418033a11188ca0392e02bcb080f8865eca2a94f6789fced", "HASH_MPIN_ID_HEX": "06f1e00461d733e74b523883483a38e99a1b5249f2837a8edfe7f1d2d7ef75a6", "TIME_PERMIT": "041bcd889b6cae9677633ef462ca6e6e39c7e0d28ecf9b97645436db8ae1c63f6a13ca4630fdac7242abfc595e1e04a9947c72769c2b7eac2592cdd5cfb4f99463", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20226164313664626461323365656634633933633937626436343165663631313563406365727469766f782e636f6d222c202273616c74223a202266386466653964633031663666313438227d", "TOKEN": "042354cbb8e1f8a7e18f19c79dcc77f400e5b1241f5609f099366613c67d528c7d139072e35e6f0cd6744026202485730df56b10c1673fe0734b0995048306ca93", "U": "04095ee15fd09a2c74a0379058c476edc37a207298a1cc4389703349dee1a5b803019095049b49b932edded339575a4b207a40b566494be7eab89d9fc90e47619f", "SERVER_OUTPUT": -19, "Y": "18aa819fc33f8c1cdf049414c8106d7a8ba97c5e35988f8e772f37eef7cc9f4b", "X": "12984746c742eb493e5b13b33403879f38b0bfc9d593ff340e0a0200ebf568e2", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"ad16dbda23eef4c93c97bd641ef6115c@certivox.com\", \"salt\": \"f8dfe9dc01f6f148\"}", "test_no": 107, "UT": "0407196a356991ac2725bc32eb483d2272d084d0b5c4859a5b0852888697edc1ad103061f635c4ae0750876b9f924e61757c141037e43e48987be4b78cd0f37b97", "MS2": "0c5da236e47ab07a5f48e24accbd0428fb0c2071ecca705a761eb0da06358390", "MS1": "205b1a9baa97ab6b23bd9e858c7f04d566e7ccb126174218ed14395c0ccf2a71", "CLIENT_SECRET": "040fc3cea5f1aa2eba07b6b0bdd02786777c229b618569ea70ba72ffe4628fc5580f67c605053bd1f59fce8a06f889ddb00c3c3ce16573cca1d6d7cffa11a70cc4"}, {"TimeValue": 1437055596, "SS1": "05156b6a71ed40159861cc42679dd2d673a4b9c7ab5aa2a82d83db815f690ec312d5438a646cf523c6611c33c7c8ecf839fca30de5a510cc333608d455b1d9250b8a42b4cb1a6c70b8374faeb976de07b057d45f70fe16dbec7b5cceb42d63121b5b22514ef27f8a0879f6c17dfdc0acb63ce09d676cb5307eaddf518b60caab", "SS2": "08d6f4a61b64d1ec5e284f47214c3512044f128b8b900e49f577503ad32a13ac0b54e0fecc5a94750848ec09c11442ceac8fdd97b39c5b5231dd986b837178870c77ef56f40f2442078e65d52fa0e484e740a78f1b7c472e88f331800b1f0cc91e1048998f30981fb8dfacdcb4262bd6f9c183f363fc61b5f6eef5e542bebefc", "DATE": 16632, "PIN2": 4490, "PIN1": 4491, "SERVER_SECRET": "1571b7d9f10d4dc4e70c099875e883792608d8028a986f926ffa8731f62bc511227fc7770a994bb202f798762e5c5ee7f28551f7e4ae0efc400880bf7eb8e1b8101045ebee38bc74025139cd2dc41cd70eb9906a33f1d4133e34e54b37f71571235e75531784eeeac1585492a09cf83f1499ef88f22283967f7a19d97524e05b", "SEC": "04193f0805117013d92edf7dff1c71f527e6f958edacba019d6a3028d488e07e7e0e15b270dbbf3c8c5604f7458569d46e1a965e1a748f5e3f8a5ab0ea56b9db6a", "TP2": "0413984da8f2fba69db247f26ff6cccbedb53de9f31eda10d8d2df88e4a80aa07c129dc9642606b1ca6a2c83e1c69bbbca967b04a748163afa2605aadf9332fe15", "TP1": "0405436cb4828ef0c4453b8aff0ed24922fbb1a0ed70cf561a43a71eb9c782599d094a9dc0f13e4d8c387ba34d934e6495b0bae970ca3d8d42ffa0eace467dcaa5", "CS1": "040f8311ce1d97ad0fa1da56f4f1088c13623e51fc9a69ef242f09914e8635da270223ead337542a75b9d83723ba1e320c8852463a05f24c3edacf823104f6c573", "CS2": "041e81def61c19cee1d49a32c37e7b3e513e44e13dc69dfe16c7b5e92d1460612d0943115e5642e5e1abab7140e51c15e0a3e0a95e1d187c443b81c87e627d11c4", "HASH_MPIN_ID_HEX": "dbf0ac63a7d05f316cffb18bc0ccbbd53aca5af4a6d20ac106c6487079d4cec6", "TIME_PERMIT": "0402cfbb915268fcff232fd6dfa515ff9b015d17fb29587c14cf4ffb64a208b50012f947f205734626831841848f935b58e86f78d616f57b438e80f37b43cba1c8", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20226665316138373964303630363833653861656161656563653337656661356536406365727469766f782e636f6d222c202273616c74223a202264373135623664623835613861393633227d", "TOKEN": "041c6893c325095161574fa48156223f148a6e56e583d3e36c8c3a8f018495feff14d7a00a54589c887cbc416f7d85fa3c774bc59dc513311cdec7f7db0eed6cfd", "U": "040630c335e611b19143c3815d26d5648a16f35133370e07d836d040d7f2ccff3e167faf8074cc68cb3a8c2ef2981afb6b8ab8bddd7a91ff0a5ef632910d1cd305", "SERVER_OUTPUT": -19, "Y": "1eee4d3903f4f2d1cd315e6db9f1ba004b1e0b17f3d28c8d00c3141f1d8ee6ef", "X": "0ee1be994984d2359cd891f9642660c7307025af01c828d0777120566e6352d0", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"fe1a879d060683e8aeaaeece37efa5e6@certivox.com\", \"salt\": \"d715b6db85a8a963\"}", "test_no": 108, "UT": "040153386d9ccc2bbdd486cf5e0533a9953504c4f8091cbec07761b7309fd1548c20923c1d8a73a68e5db475f58710aa779d1ce68e87dc759c9687a598c93bc1d5", "MS2": "1dcee98a8a6b3f5eb89e5142611d339c4d2c537cdf992e5fb81fb626008f5e73", "MS1": "17f66731761da4e4eebe60940f1547dd348ce38ca9ab1aa7a65377ba2bdbed84", "CLIENT_SECRET": "040a54a9bb59bb6247a16bcda26b52d634e7cecd630c30d93e25e3acb2d12487c90a9d4955a45f22482d54d1b30a6c3d6d61eed41d332ac59cbcb952a797c85b89"}, {"TimeValue": 1437055596, "SS1": "1294c03b56e5666f4f8524025b2be2fc103e1b47a137a8fe411b2984d2b9d029092bb81223a0eaf244cf09d9f2315f57f8ae22dcd8f6899fee9e1c91246dcdcb07220aa16b029e99a05e22ebb85c26a12f0bd1d9214dba23dff81125388e986617d806f9d5a8568f14c2cf16db97d6a61278c7825f80090452e1c8795b5d5503", "SS2": "08f740cd42874055a7df10a13be538bd5fe4f7b9c19b6245875a6cc6331c5b15169a2c773e24b97fea3789e248080443fc34af4f73d54e3ec08f2678624c7dbc1e5b941fc183c03c0dec5e6df1d921ffc49386bde2aaee2145b6e6cc1a3f69f91f5e64422207c84cc15e6b033b9a962b4efa3e7c9f25ae8217ab3d9a73a00cf2", "DATE": 16632, "PIN2": 949, "PIN1": 950, "SERVER_SECRET": "23c5cfce81dd8bfe510de27379fa0e6f223c1507b77242047e29f20af0ccbab220b104c51c2fb3ba8aae87675a345779592ec1fb8708160321f6e280fd40d8240d983e8d57898d2cf271ce57e7cb0cfb9d14bb97fb5f4196d39e4f10082d6bd91dd29e6a16d4997c326b306e4727675f2f299848df001b90ad744f6929c2fac2", "SEC": "04046f980a39409a59c622032937c1762900f8877abe23da48e6057ac4eba4eba30163d6f02e4014350a9283592be08a213259b5e51f4c709ad06df83e83e09f4e", "TP2": "0405172e8670909654eb4b19c554ee47e46011fdbf28c1cfdafdf8f66a5873ddf01e1c6c7118a5c0a4504997c010f2e678e5f047393ae05efc6368eb38bbbef08d", "TP1": "0411e05df64736acde1c945b71c1c5372ae69e620491148315817ea9e1bac509d6168aa8c33fe667d76a20d395b41c5d0b3659b0e71da691a427f07a4b396503c4", "CS1": "0420d72f203c86a02f6cd678f4b65fafe8d399c12d1ccd310fd5874b13f614a596215bf3e320ed08109d526b240d6b9e5613a69ecfb19ab9dc6f27118eea903e90", "CS2": "040147ac1527d4d766ead2c9849951c149df59b41d38169c2d8bb2744e2101a21b0797d2a10b30cb0ba3a5c8db0bfb36b43d23329b3f5e67b98d795d3d8c3b910e", "HASH_MPIN_ID_HEX": "f28156ad8e58038466c893205a0bb0dac67c97fea75dd7c5ce03fd3149d254ae", "TIME_PERMIT": "040b401af43b8ba56669db5777e8348ac90dec4522831a6a9ebe41bce879cd1722167706073e415c7aa4fa0b249d4daa630e60cdce0990fdc3fa1925afc33a36d2", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20226536656362333361373264613638333661336135636261303237383832656533406365727469766f782e636f6d222c202273616c74223a202236633063623766366562616336393031227d", "TOKEN": "040f34b221d7dcdcf29893a43a43001e6f777eca455d7a6f9f145c0b4db039c801196aea7f14cd4b47efbaec65247815ad490ad9c4a425bdc8cb4df45b136096a3", "U": "0415b539ee7c9bb2798cbf06edbab49e6ffc69a8bc448c2fa06c334a5e95f83bfb07634a2f4478452bc9d6a2c9e853fe16339e4f368d4f7186282d1010ca3838b5", "SERVER_OUTPUT": -19, "Y": "18afcf03858ff1dad9d45a61d1c9f0541674b6581d08cf43160694fef4369343", "X": "0d1ee1ac7abbe24cab288d625eb130be98bc41b3628015bdc033742ce84a2d52", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"e6ecb33a72da6836a3a5cba027882ee3@certivox.com\", \"salt\": \"6c0cb7f6ebac6901\"}", "test_no": 109, "UT": "040c057ff9af284be936da8492a8e3374cdf731d0b8749fbf85e1b73e14502b48e019ea06412ed838aa76a58a9b07dec855669d81d2412c9d8b30feed98a585575", "MS2": "15fe0226fd8e5ef83a984bfc812f38f5d69c5f225fe16e4d0986bb6c2cf88983", "MS1": "15dc01b0006b945adac0656d344456a887e5c65aff31b9222e1e072d2f162959", "CLIENT_SECRET": "041a31601f8132044e58392f15328a565201fafaa48d970aa8329beb68ddcddcf5037dc5baf15d052dc169ac747e59d1b40ce0fb6b31adbd5a514822a863bc3439"}, {"TimeValue": 1437055596, "SS1": "12095baea80d8535eaf5c2ce6ada586252b25c69ba6dae39a53f66fc32cb6ebe066cf9add46a3818046a17c81370c09a4ab60587d80f19f026fcdecd11e5602b1d18e785c31fe8e51c0c1151cc8dc7ad37ada66ceb54c85884ea0896f46eb6c9208ba585337281990ef26e55963dd9a5066cccc35ed7462a320fee9917c437d8", "SS2": "147d4aad1dcee44973f1031d30a899aa4189119303631856dc4c9c32a16d9a681a47b6b62896f58c074e6c2e1b2f7b911105022dea3e9515eedbd081595cbc6d13042ae7792c8750869f11c9e40c9419d9e9ed323c3adf097e7accbc394a1a3903e21c15db71d7267bfad9a8e6966dc3e6a52d2c757234b623a971459da045b4", "DATE": 16632, "PIN2": 9442, "PIN1": 9443, "SERVER_SECRET": "0e044af549a1faf5e6601b4ba14fef2dc2c82b756f28d3b2d9ad6f88ee5b9b5207c9d137634732170256b848f8aeaf7b4390ec91f448ee8c49b98a62d0cab6de09ba81f634b12b2904ed4ca543e7e05ead7e9ab934c71ebb20347fae3d044ad7197f6ff7ae5d3ef46377dc160949baf7c38cee5d7069539b59d076c617758751", "SEC": "0405e11da4df3b43b3abd1ee2f4edfb2bc31a507a5cb12952578cf29bad77bbcab1ca2d472287f2a3a350da02f71d98f7d80c68db95a1f852bd1942499d3894b3c", "TP2": "04158a7ca8d903883a42c35859a7f07abf62a46480da329a43a2870c09b9b97a2f17fe36a28fcb093220621b0ca2e4621cd5aff1efcc0500893c540557fa8dd65a", "TP1": "041063d958c5b95f6777e725cefcc33c90773bdb1fb8d18415f990dd2a831bae0a17bcfd7b92cfc6fc8e8ab0ccca1887ebf7e0e476c20dced8cf2c428eff35d3f8", "CS1": "0406f4ec06ce86f63fae785efacc5d82f533180bb55b648e41f37a660462587ca41da817c3646041163e56352b7fe6dad729c4bf6915525ce72e44eade8e3e8407", "CS2": "0404e4f755166eaf694f8133a01f6a2731e158e0e775e14faf3732722985fc1a49160c85759a24d197856427eb06329245892c317de659bf82e71d9fe193e260f6", "HASH_MPIN_ID_HEX": "5cdfc7c93298e3d4c5179a5361e78cc06466e298d4b26770f82e67f4b681de98", "TIME_PERMIT": "040ed0231df960b82a2bf193be9a90c254ccb8ae038d0d9ae7d60e9315374aeb5a20d32efb49fd37bcc1e0bef631cf0a90fabc71ed597fe0d55793bb403dd709f6", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223961373930356464313231366532653162313966636535613933373361373731406365727469766f782e636f6d222c202273616c74223a202265643637363161343731646464393638227d", "TOKEN": "0416f146ee14601c029cac62d06a810c2c44e9c4850e59ec05c39d53737a0ebb85052568f53d1a897e1e927a25ffeca971bdb23520628da85cf289cdd8b5f6f9ad", "U": "040d2c623b43f9dfde785a8c63a87fcce8bee804a4752ef63e6a6dca5c0011d3c60813fd4ffad348c4baa3f7f36fc6744a52431828aaa4f8cf24007a40b8ddcb1d", "SERVER_OUTPUT": -19, "Y": "07592fb0c693cd5916266e352f519a1a53a64e4d302387f013926c4a8d3000c4", "X": "043a5626157b6d0bc8c1ae8873afcaf77ff15f6131cec50e84529904a4a2184a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"9a7905dd1216e2e1b19fce5a9373a771@certivox.com\", \"salt\": \"ed6761a471ddd968\"}", "test_no": 110, "UT": "04179182ad06823173377a49118176dd694212f182c59cd6b92ef772e70d654eb906eaac3dc839582b90c4550704a1a34a919b877e4df265d3c308708e0af30232", "MS2": "1652c4b08f9813654936e30013bfd24b37570ed9bee3d8482febdce53cb31877", "MS1": "0f9a25a1c2c96b904d6c77d1edb8f610b7094915d34715c8544758389855e6af", "CLIENT_SECRET": "041f85b60274c68533d9863a4b0764ee3e341998c722dde9958798ed751d1b1c3c0326ef05a37846687332ded368b22eeab0297f1e3697edda144eef9a9f40ea3b"}, {"TimeValue": 1437055596, "SS1": "0fd7c297e4bf551ffe991a4a00ba1f0551cafef3d87169399d7c058b4833a92e198b36204687455895b2dfc479bf810e8da119cc6e5a422ff56ed13dc6d121230552068b9b6e9a6a992118b844f3a391e3d4e2a097c3ee55175e094919d7975210242300d0eae76d4a11098f95115c24eb5b82eda23d6f7b7d6b35200d2d7ca3", "SS2": "02d5e884a2ac75170027c8e38dfa595575a41e0aaf5b5d8c2c3dcdd364af84611b563d5ab4e81460e78e7b4107ffceece57f0bae196c588a194d9ef6c86694161489b5d74dc482539f26d857890d29fcd3c9dfe85a25ef7aa205967154bd317f19b2b815dbfb68d8d81deea6d8d4366145e1fdd20fe1ee250d2bc0a6455085a2", "DATE": 16632, "PIN2": 7708, "PIN1": 7709, "SERVER_SECRET": "19ad3963c4dc91fc5ac96b64c96acae4766c6755f01b94e4a2c792bd5fa91eb3225b82298d8ad119128cf7ba53c6846853b3ead26cb275e982e56c0876ff44c8093d8d447cd2156ce717fea7c588a5d6b8c63c57db9a6a2533173723c1dd8b960f2bc04514180b6531c3f18b97666554240c72684bbab3cb697645743c3ff473", "SEC": "041586dd1fbe4fe82b51d0921ad56ea3395288f44d9316b9d4f6a4e423940bfa8e0421252fcf8e406f86b5a1fc3ef2ff235581a5707897a166e05966a98b553048", "TP2": "04225dd8dfd75cd6ce9cfc5a14d65d004275f4e078e39e7306ccc9ed0724f935b10553398de412ee0260c92251fd4f9a62c560d101205f8da21aa63ffe11981ba1", "TP1": "041432c904e93fbaff643af9ae9f9a0f516329afe66a357f9cef02c1480a66898b01df28fd732a8861d9063797b5251e7bd84b1d3a34854cb708850712fb7d2ac0", "CS1": "04150c38cea729c900b5d92d0eb50293f45311c425ec11fd4fc7c0b1de7f30be38116022a6ef339c5247c0f856f306a5ebc244624dfb6719900a8267fa2d23b830", "CS2": "0423406ea49df87c46f066e5e7424251f010c8a19beb22988fa9b68ee6230e88fc0f1051e0aee8053c2d8a27d6bfcb81483790a74cd950a1470f346845374952dd", "HASH_MPIN_ID_HEX": "21a48d32f5e5a237c3700950cc91a93badc59c13e342e7bfb66b6f243543938d", "TIME_PERMIT": "041407431d55ba249e6ab255810340fc52ea3f9e72aa370ea3eed28bb05fc30cef21967b4405e5df4b80f42557d12dfed6a8168ae228646c2119021002e891870d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20226136646235316539376639356433653232333132663632323430323338663630406365727469766f782e636f6d222c202273616c74223a202238333464643332613738333036316339227d", "TOKEN": "041ef0bf9c21ca748916be19f22829e09e41fd8f9859748ed8bfce31132f304da8128e3050577e40adf2f0d28dab788653bbabecc3f314cf1007ac848e53f54a12", "U": "0413bad0a29b645fda48bd35fa942d77818db96a30b54289e133f87cdc5703d3e10660957dbfe688d6e596b829ebf1425d946131f7fd1a6a6a54eac8dbb7046125", "SERVER_OUTPUT": -19, "Y": "181262c25ed8667f173a23f254857cd39614a7508dd8ff8ebabc162f126bb819", "X": "13aa464656804f642bf60f6fca2dd508932e6a5d19e86f025522cdf4384d75b4", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"a6db51e97f95d3e22312f62240238f60@certivox.com\", \"salt\": \"834dd32a783061c9\"}", "test_no": 111, "UT": "04182cbf5fc1ca27a3cd974f118473f838d146e912320b0f5e9ff478cdc8f032c31e1ad79300f4458de30ebe8cd42c3a694a4130a9b120b6cd980a5f423de5cf07", "MS2": "179ee9d8417137ce6f71508d57126221931d7ad15223c2cc7d61b9fe7eefbd61", "MS1": "018f7a7d853cd65b5954df6657d10b8d2e4fb0173ad2eca876ae88b4d29fc50c", "CLIENT_SECRET": "0422f88ca9f58845f22fc86d98ccd63e44045a355b2d50f133c0458b6ea3b0601803deb2cc1c0f7c69b50dcda84a3e59d9b7122c6016be53311ec74e7e78d8ccc3"}, {"TimeValue": 1437055596, "SS1": "0629fcd214466a17865b22a2ab30545e197cbcebd54ec4c6565062d0390436bc0e93d3f6fab5d22ad2c94438eb952fdd3498d931f7ac90d44c00f444675f48be0d8a013da508e6101323c8bd3b96cb537654cd026f044965a4b1a7f632073d46235863675d7a80a1757422025b55352704729fa06a7e990f0ab8bc8d00378b4c", "SS2": "05c5939fac44310da07f529478efa0ca27003abcad5e5e14749407d544728c3b208793f0b593ba04ce71aef31f6ac5a4e18d3c2ddd44bf425bc53022fdd98a0615a3eb47464dd4613396161b57adc31932d17960fc0c857da728cde2766366331524979690af8978a6f606929017b1f69351fbf5d49016230136802e80210bc2", "DATE": 16632, "PIN2": 7197, "PIN1": 7198, "SERVER_SECRET": "0b46f020d382329fc4fa8d59c2f845a311471c5e0a07ab624c58caa7cfa4d9f908ab87a00715ab4fb996910bb4d0cf8b13e8555cef158cdf873d7f377fe289f60a3c74686e255001e9859600dceaa10e0b183cae22c1c69a24f408ec859810e3046a3d3e8454289af67c557840bc09774515c58ff8f1ff5bbde8ec95eab14c86", "SEC": "0412e7bf9749180d234da58fade747739b89ee8e73a4b22fbc3e2f2a7a3ff0177d0bb83e069a308cc848bebc4b9aa23de0299f5e2d12f05ab37c8bc6fd1b6a95b6", "TP2": "04023b019804fa0867c04083cf2b7df1366a46b3d009d418e94466bc74a0610c371a36a8b446a10fcf6a2ac310cf43c3074821a4e9303c6f93bf9e494a4e4d8a42", "TP1": "0412ea34e83947bd3284d3ea00e842faca223c5b0f74d2d19218ef09f6e278c21b16c9019f48675d943273e10296b48c3f1524565df17203388bd70758f495dc78", "CS1": "041a91c0c324b5b486a5aec1a0563d5ff0101124dd1cc4bd6c4d4fcb2e74d7c3191009eb81d9d35c4bbe4e2307ba0bf81f2aa53cff34d7bfa393f3e5f30695735a", "CS2": "04167c2241ec7b6078d71dfee7d82eb7b32dd3290ef813a739dc34086d63edc362181eb52c2bdc46c0eac8982e332608ebbc713add12d2e95efafddd1506f4ad5b", "HASH_MPIN_ID_HEX": "3e7e0aeb88dda225dfab34b7c65f13887bcf63ebb302108f664de62d115ee477", "TIME_PERMIT": "041dc4a6cf1663e3710f307cfe3f1bad69fab9c7bad1554a11b4efc36323d61f9b03fa203f14ca91b4f7b7d2d1f2e8113d46edd71b4d276d661528b884227a29fd", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223061316437346139643833366434323466643539383837663637663337623063406365727469766f782e636f6d222c202273616c74223a202239333862376661336332346362316533227d", "TOKEN": "040c91754feabddb24726fb81d18c51028c198b9c464e1371deeffa2908aab2eb8074fd3106b46acb7f33db05f353b1b9280b26e86cb007b456219e6f08e091e26", "U": "0410cdee86ce21167d8804d8c40bc90cd3ced0b6b151431122814bf28e40608b2f0edaac84ceee9339d0c2340bfc7404f9104a4d14c4285f90f620fec0f3381bdb", "SERVER_OUTPUT": -19, "Y": "02b02e93276a4fd327fe243f61f085b6daeae75707a4f5cce1b65d7222dda1f0", "X": "0839dcbd8f3c99bd73121af0edc10686d5f72164192daded89b45a1723c4749b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"0a1d74a9d836d424fd59887f67f37b0c@certivox.com\", \"salt\": \"938b7fa3c24cb1e3\"}", "test_no": 112, "UT": "040e42a402abb6028b2f16c48c64a5a780db4530af57dabd9167222e17d29fbf92127ee3aeed050209fa1328eb356eed72e6bac6ff6dbacb14ff0dd80b7f7f77e2", "MS2": "07151248b45625b40f6c50a6187205fea160f014d139597f645180b6d2bce8cc", "MS1": "0f4399e7efb262f8dfdabd09515ee56fe30ed0f1ef4d3d8ea32e1a271f5726e0", "CLIENT_SECRET": "0408944c935453a134c8dfa717b62f804745916011a2462883ca60d64b47038f500657b00eac001f5224048067c7473532a03c6e9b93b402975e706bb9f0d8462c"}, {"TimeValue": 1437055596, "SS1": "20086914d74de8697969447783782782612fcfef12e300c770a9d5ef04ccab4a23e7da35310a01a02137696b35e0e425bd197d0f2a7339301090168b8de666580d3bcbb90d6af371fe96683f17909928cb54a4892febeef06715f761851edc1c0ec284e575c862a30a37530be64dad47e05a8694f189c142b9635f7a9eda6fda", "SS2": "07dedb6769a9c7bf18ac10c0926395a2368cfa6d86cf123c48f793399afd6403186bf60a5cdc5a6947fc82082ee8a7da0b6b1d7539dacb78d5f22ec8478883aa0429f6d574e7331c6769f5196515631288b350f20604fbc0dc65890ff40991581ea9212961b2dcdcd72ba0f9c3ddc9a6305603dfa49350901b8ce5d2dd20381b", "DATE": 16632, "PIN2": 1327, "PIN1": 1328, "SERVER_SECRET": "1b51913858834c948f03c49e8a084cf6d1479da51c55325c65fd2ccd849365a60835a7f63a382c61165303e4be96e8c2599c758456e49bde5edffe94dd5e3515212729086652424589ed53e208f2bd1bddfc33898425f03a8a0efaf84db4a37d185d6e4155e820b1ec9802a593982a3bf531514609235009d8650600fbce7194", "SEC": "042365bfc2cfb71414d9e8e743ea82f6437578476ef94fc3d682af6880746864731b50dd9f80f32dd125626797ca10d33172c0dff1be3bb982725d5e177a9c2db7", "TP2": "041f98bea24ac4e2bf64acfeb2308fdb272c635fd01a0d29b7ace0a1fb1168fe6e02d627536d55292eb902cb44ae58540c80fa884c47f17c7686cb988c965657d9", "TP1": "04090af7defbf2f71a09861289bc5e8a778e633da06c2005748d6bda1d45946030145314d57b458ee566891a6017981c5f137f37fc1f259615a7e9b8027848c574", "CS1": "0418d6b993ca3f03be3208989062446f08180a9a0e5789575be1c984af9f95ad9916669332fb3cf851d1d26ba3fd78499b99e5a388a207695b981067c600592994", "CS2": "040fe90923622aadb435031bf7f3efc4176af6f701854f100673231123bd92362f0899666bcf46992074c6bd6047405b16f4848706706d7531b69433923708cacb", "HASH_MPIN_ID_HEX": "08e81dd3a2c38746757bf40539893ccc8b2ffea6dba13c0464e286055e60d5c1", "TIME_PERMIT": "040d9892e9248c6faf040d6e5f6860e06bcab83bc761943998eab6706cfd4d672d11ac058d67fe1f6926d0781f2ee6a10d2c785e60652c3b9e657815ac441853f7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20226134376565303433646663383561633434373736323037643034316439663939406365727469766f782e636f6d222c202273616c74223a202262326133306233323838316637373566227d", "TOKEN": "0409169a2a16dd97d8705bbb1e211f54d0308b81e46155c73db1733dad7c5d8eea07feb5f6b733642a53b048de6e45a40b1f1fa7c4b03e4b710082d62fd883f077", "U": "041b8e84eeb8c43bf1f4625fe1ddfb3331b4c10aecd21edc32943251c2e86e7054034d51d13870e55ab097d13b21e772f733a0fa4ba7f8e7ecf9651aeca61d9cd1", "SERVER_OUTPUT": -19, "Y": "12fc51b817fadaebb8b6f07f4d9567495405d0a8cc9656cbb55ea64613f6acfe", "X": "175bb18d330e63d7ccde524116777c6a2a58c4b6a5ae4740f3677a5391d12d59", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"a47ee043dfc85ac44776207d041d9f99@certivox.com\", \"salt\": \"b2a30b32881f775f\"}", "test_no": 113, "UT": "0402035ccaf811e411eb12c9d592830849e733fbb001f790b65d620cee3e45ade8048d1c12a9d71f817ce5cf1cea17cb6a4f9d7273c547e701715b74d875aa5713", "MS2": "1c1f23eb966a0b21825a02a3f8afbcadab19b30c5110a10ec63b43e4b68234f8", "MS1": "1c4a0ecf115fc0285085808fb7a1cfb8ae0339b4a9c9025abe63238362fd4b84", "CLIENT_SECRET": "04023672af7d3d98e8faf2d9160497d7e9d513751268055e0ecc25cd56d2ccf4e104211ed5de0e50de1e3d25673b2b92380919a0af3e63c0ff3e7048d6244588e0"}, {"TimeValue": 1437055596, "SS1": "14272f2843bffaeb312a015d21e9f04c11606036544c33a1cc4a59b9215ab6ee0d342bd962cee75db43c90d53a4df54ffddd127455bb8c9ce97d3d8db834eee70661572e62c3d830a21f3105ebee4d02855c76732e37256cfefd3c223c5304ea22bd4d3adda7d03bea352dbeb97980aac816e4774d9c5072a9df861a90e937fd", "SS2": "079b80ef83f01177bbd165660b9b527a9d5744625e07d37bb9fa2e69d9032885033ea088eef5bd831fd06f2129b5b0d1ca2f1365bacf674bdac44a0aafe963ab1fa96008f9b3ddc88e3f355f339a6a1de227f06a5be0155c81ed623ee6237211103cb26f0fe24aabaf2fe99e4ff892c0acf77370fa71b093b9eb5bfc86f3d1b6", "DATE": 16632, "PIN2": 2077, "PIN1": 2078, "SERVER_SECRET": "109ca99606fff8b1d55097ca462097ecf1b2297fd3fb075499901345b1297b4e12299a1b3f1262663076db67c0f255ed9c5f11b927da312b382e9a1cf837a8b410686dd46951aa6e6b7ff51a48784758b06967ad5a6bc772fcf1a31ab1bcccbb0fc6491b7d6d180ca14bafec995c275feda1adf954c55c451c4916443e8e259e", "SEC": "041e8b908040b99618e4df6637ac9fc79e3a62f4ea9fb7b6fe04f76b8db6b0a2121feeb940887ef22b2c5dabd2893cfb95884fc091f230faf4c4358edaca5ccaec", "TP2": "040cad3b1ae4cb0d825ad0ae4c10fe6fd648570f16960ea906be45039a476d7dfc07d97f20df379f2cbf88789357faf6cee21422b553cdb91b72969ef1b1032444", "TP1": "041083b80ed2a3fa0ad70680fd006c29c0a27fff8f3a4000e36ebdee1ac66637a309e9da89282e587e4ff5733fe72bade2ec778e75fb33c4d4bec255e014ccd118", "CS1": "041ba2a1d56d41a4411addba4d88e952d0e02012ea056ee4dbb4a9b572e1068e8620862b6fcb383d48a7942327b4b0783db4fe5941198bfffa165baa4b52852439", "CS2": "0407f93094f84cf549a785c26c0f2ab3a3bb7b8240affcb2c93ba2da91159dae1805d6ad6c47d8a127a0aa4b1f71dbf5692ac4d2129cf7769bf10aaf7d101bde29", "HASH_MPIN_ID_HEX": "db17cb003d4accc1be25eae5dc4962071a8897a3b7a434cbde71e7324f7459e7", "TIME_PERMIT": "041b2f99efd02d6383542af941070b6a0199aaec7021fff9d38d4b175f13800fad14717beee8dc3f1c25f421334535c7bf64b4f8fdeb63b6d4c950ee7c47346619", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223935303561343865636138356532333137346639663564353139303265313233406365727469766f782e636f6d222c202273616c74223a202233366364383933633132326364383861227d", "TOKEN": "0412c5e8265c17c57a63c48f02787fa7a3e8787f34d052b262139e45b4fc992383089f6aed6c1404aa13d3d26ece69864ef6e3387598990ce7a9226b6f8ff45cf1", "U": "04223ca0460ba6616f3fec286e85243ac39dd3b17ba501f957f4f164ef76d9c9be1f2f807c0077828e87f5ee202627c7ed370f210da31fa02de36dcfefd3563b41", "SERVER_OUTPUT": -19, "Y": "1c3bd236b505b7e6bd6fb927aea2125078babaf567a0ebf13cb3b3aeb726547c", "X": "159bd24390cc48c5557803268964efee832970613ca1bebe1f97562902b901b1", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"9505a48eca85e23174f9f5d51902e123@certivox.com\", \"salt\": \"36cd893c122cd88a\"}", "test_no": 114, "UT": "040c2c52423979bd60bb101acf9c2e4c28e45e6acd28f379c756788caea367f5fc0859863b24324f2dca7ba3f20e83cbc9e11ee8b6abe66f0ba3f92c2e5381a9ef", "MS2": "1f883381f6b590305d67ac110b9cd06fa17c2b99e4667e8aa50c17c46abe69ef", "MS1": "18f1b2bda7eaf6b4691986604a8cbfdd74bed3018b698108b50340b19315c8e9", "CLIENT_SECRET": "040db4d70146b129e022c3cb01cd24ec578bfcaa0f752e5bee34c972ef210e08f310c8bf8a590e5fb666ce54100d22f489f2fe23132810cc6800d346f300698a9f"}, {"TimeValue": 1437055596, "SS1": "0053ca3829035a7b5f7de33077bc55a26745000f23f083d8c3745b1fddd7810d1e0fb0d3fa774f98c1580fe1d39817673e2f7175f775a699fa421143a9582613041ef92433c9eb41b9e4b4c9738b844afb6a9a5da9e8736ceb9e7ff75c74e7b51c30fe4ae3f7ae552ea396ef26dab6a3a81207b557cd6448e10dea4c57a359ca", "SS2": "1bd76e2a44c852d4c5ae49feb8ade43944644e22cfd444b171c1df42357e298010d41ab501e85389272c0963d8f48ed90a76b4116a046301ffcb5459e7e29c932193df3be4d626bad1fc523c085f78b504f4b7d39c0ca3e34426ea272e659e5422f804ea2d3bd569504a64b3f0897642e34d5b036e8c9aab2622f5b01dde62f4", "DATE": 16632, "PIN2": 3334, "PIN1": 3335, "SERVER_SECRET": "13e709bc359c4b8615172c458224bfd918b9783f112639402daa874cf051770f1b0fc08e67df9306b80a590ca7ea3d34beabb5fd23fc2d296ad2bcaf869983c71654ff542b9c81a73c519e18a742cd5de2a8277cb3d5d91ed02a14f65230de2d21df85098f9c1dcbfa999d1ea6abbf456e25602eeff43631adb474f9c1c76817", "SEC": "0414f62f5d1a9d7c66fcb126cdf1f76a388c401208ad1fbf9eeba70dc1a8c9835115cfcf6d6b6e382556ded18063e6ac36960d07011693bd46f1b1ffadbb65557c", "TP2": "0405abc9d0da8daa1628f024a8706d0bc580dc864c6244af0a941aaead01b3121410b888bfa92f37a16b664cdb02b70fad72060fac6afb5ac837806b99f7083f2e", "TP1": "040fd3f57a13cea9e3abe4f78d047e49cc6a7e6495502f6dc5df39c22ba3eb833d1edfc59bae17bc88fa5e627d010de7deb1bdd4424676730832309e38de693e69", "CS1": "040369dd91af322f6d02906c761b0b8fe4916bcdb0c200e5b20ff913395957ee9b20ef153bd175a648d1d739efa981c7058776cbd211255623df25f60603432666", "CS2": "04057019b921244e94f3e02e19a22dad3dd9d7c9c0a1e22dfa583c4cb0d70ad9870b2ab1b962426a759123ee588e2990cc76696dfd264fc0e6a8410d4509810b0d", "HASH_MPIN_ID_HEX": "4fb4121d4ae5b63a5d9c2e146648ecba8eee52c3b76be8555c84d08fa1eb03ea", "TIME_PERMIT": "041a7d0619e90cab7b8198d72e16431c723bcd6fa0b0178bfc8be0dbb7de1b6e2f197c74636e1d8df8dee176928efa18121098eebaa30acc8fa6c85f802b31bc25", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223930656665303064613337653736656434616561326464316561333961323764406365727469766f782e636f6d222c202273616c74223a202230366561666133666265363631363331227d", "TOKEN": "0414799c22c8d57699ebd5edccdfd05828ae25bd6d6367b80cbea83f25cb62aad0133d7ac71a970cb4228049f958b005c08752cb5b305cf79584dc7de310550b25", "U": "041bb0e2e4a04e7ec78eaf83779060690482f3c7fb0d3700cc0a6f8d13cf78282111b170c23121f6d5af922c22293633546369a5d1c44f6da113dd8f3405a09d1b", "SERVER_OUTPUT": -19, "Y": "19d4b258a8ed494c8977ea59710b0154894418f8d3d377127f7b6f2a9edbfbf8", "X": "148fecf5d9d870665d50be980c8523ff1014ff8d57128e5f1c9b37792caa486b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"90efe00da37e76ed4aea2dd1ea39a27d@certivox.com\", \"salt\": \"06eafa3fbe661631\"}", "test_no": 115, "UT": "040d30ae7d4b887b8704c7c4853d6c5614a2e2de4488d68e580eeeb38ce73dd429189d540e8508499fc4986d358e4fc9457ed102651095d437c7afe1e84a6ec7fc", "MS2": "10ea147627701571d7cde7b47a0eac18a20ba9f257c9546d2a5a5edc2487711c", "MS1": "026024ec983da0acd02aba012375aec0b29e7c16103eff2e398d920e289a72dd", "CLIENT_SECRET": "041e382b092b911addff062b9e26c801f3b5a6250b4b9f6bd6075e0613f235bd9b164d04044c883c79fe3a5e605aaf4264c4c3970e0bcc0df57aa5d21720f8b32f"}, {"TimeValue": 1437055596, "SS1": "09458444b39b36ca6a525893a80535aa53e20357937ab476abfea4b5f4f27a900fb00243ca0cd46951ab94a26183955300dd923a596a01a40245e9e9a229fff40e0a5d2a50fb2994a6bf51ea34af8346462d9a5a40eb640b7a22e59f8110d3f3004476b0bba12bd13922de29fa847b4b852536eb87a50934854845a0a6818001", "SS2": "1600f77518de2729d723a988c693663c97253c358a0a617609587cc2fd30dde11fe1631c6cd854fc90a84fb8adb071441b97576f1b1b9281d1f47d54ef36113e1507e531c463d5a2f200e71434a1ae6002300a336a3906001bd106c618c1053b230acb4a57064d571885931518140e3b3b9d593f7d010557fd4a7f817876ebcc", "DATE": 16632, "PIN2": 8849, "PIN1": 8850, "SERVER_SECRET": "1e6d9389388fbdb49f1980600fe5cec741c8cca85e2656654954768dbf31aa9b0f88865e6aeb98c0f492624cd1ae9c0ee45661b4c5d2ff9adb566c350e57448b0fdf5f6618386261356f5cfb2fdc24d810fc097e3648e367910b9ef4a27b52781793251980d49546eb075f16222fa881a9eb26c56d8bc6aa7e88baf99d89e3ae", "SEC": "0421ca46887b24e6b5596496aa0223bb89d3882f827ab82f717017fa23be3720ea1ce46e93ac305712c4014f84b72f533e7e43ec194881cea9c01532d9908ed149", "TP2": "040d72eeb89edbb1b45042bb5d5bc78f66b2fd6257cea8b8a26291f319d86a448c179faf4d2dd374dc5c929ae73c5d6ad5d3323680adcf08f23ce7ed1ce5a50cfc", "TP1": "040649a1f2090bcaaa4f178ecbd8cffc3bf80b35580546d9c993ce87aea742365402c8be9d001f3efff0320eb9f534f867c4c53abdcef5f6dcc2fdac03a8fcfea5", "CS1": "040f3d3bb14e5f8b487f46fbf2e2006629316734e7c997fcb23fcfdbdef944030e0e516fab0a3f323b7b9264ab588ca55085a8993b0f424429c68088afd3fcbb78", "CS2": "042233731abdebb2050bab06d596f88f01f758f891fa1cebf624a6d9b0927482e600a1504d47c0adfcd36d98e7044e5866696498c3d5dca591930cb42c380d7589", "HASH_MPIN_ID_HEX": "ca1c03997c03145027c70ad695d478e6c6f582860d81864b4c53504dab38e419", "TIME_PERMIT": "04192a7d80712083c0435d5742052408d77e460aba6863311e35f92807264b10861945cffe515047c36c8b151514002702e4483ab33b4d6ea61a4819e8f4efceef", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223563326135393566326532343565646336303731336230323635646238626461406365727469766f782e636f6d222c202273616c74223a202232383031383636333665643035663334227d", "TOKEN": "041f2ea6a2e50727103923695cc9c302306994f10a77601b313e437b30cb2e682914bbb3ab4a63c7b42214f911220ee33cf8c5aa826893fe9ce9bc4c4764c15c69", "U": "040c573964473308a1028588a73b921b8b80987cc43cfabea8088d75f3bb44eb751644f3ef2d975fbf27d6fdaed2a9a1f428bdeade5bfbd3c34afe37f5cfd95177", "SERVER_OUTPUT": -19, "Y": "0963dd9027e74e53ba76f28e97b124f11445ea629d64b75534e9580ab37c7a5a", "X": "073dac142bc4de46f44c7515e4a5b340e94de5447bd5824686484e3d9ea09eea", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"5c2a595f2e245edc60713b0265db8bda@certivox.com\", \"salt\": \"280186636ed05f34\"}", "test_no": 116, "UT": "040fecbe0777d6eb118be3b7abe520f180d36738a13f6a09eca2e5f425c91aed7600284f55bb64c4091faf81b0c5508975b95672736e7761767d4825a3697a9a2f", "MS2": "16d0b9b486703e3df5c5d02b2b8440d097cd034be355065b909db01a9473e3a0", "MS1": "04797c0219262c78d7dc7f4b24a1a3e1b4078ba6971e2890007d1cfe069a6113", "CLIENT_SECRET": "041261e4f90043eab8bc64fa1e2e9bb91c15240bc7199fb95044c56b742b65596300b7b53a1366ee74fc83aa05056d79e65eb3aede4868a8a3ab9d5b87e150bb1d"}, {"TimeValue": 1437055596, "SS1": "1eb39d133a8284b98dd6a28b17dfb187685b821fd2132ec1ef6658a9301e5bc80a12f5c79509d0dc89d39c11de8a234c23f99de6b322b0a6c9c211ac604ee46b0a97948e036727f5f9e1462956285b7f05eb8a7b19aeba00496b85061ab13d5015760ba236a6990ac76002a7e83f84a4e4e6d38f5255e9251bf4e52a80cfbb40", "SS2": "090af47234ce4d484cc0d582a4b4b99e3cdff16a106f768d373480a1bd0de3de011e4256c11dd00188a49243da6594d0e1b7e5e0ea4bb31b9305d32eb82d81cb22445636ca33a2d7e7e1e4b1295efdad449458bffaccc8fe2cef0d011e82f65a0b01a23538933a9b166d03350829fba23cc931c3ab18c59f382e4daa568be5d2", "DATE": 16632, "PIN2": 6233, "PIN1": 6234, "SERVER_SECRET": "07f7a92b5ccc06a80b57099bdd47d8ae3f3886e33904fbbb7b99387e04ed738f01aef71eae3df4d41e9945ce07c8ebff945c2ebed834d0300a240bae3d7fee5500090f4086ac0e8504524e6cf93e845fe12f00abceade9c57920c01209a17535207cb40b1744656a24af81d96504e42d791beb9599ed3de595439befb97985c5", "SEC": "040ffbfd4506fe6ebee5d21f5d36b9bebfa85f2ef799837ad4a19df5b8c61d1b1a1fde8d948f6863b9ca83b0e61b0befd15f04a6ccbe81292af02f503dcdb26c18", "TP2": "0415531ab6727a0578e08b657d9b70a9e6ad7aca87b1ce2a94715efd9502fbcf4a1d723a193348b5d82ed3b86ce1d3d269451a747f5dd6537b4dfd8398ecbc6c6a", "TP1": "04233facb1b14562b79ad8b3e2bbfd84ef34ab93bb9a425fdf82684a969523ab11141cb2d41d5484a078ca0d9f77031e311eea07f1c32b0fd19b6bf98a43a61542", "CS1": "041c0c519642bd83889ea66c469893b7672aa0521122a37a2b62ed354d149384010c3fa8402e3df419d7c99202fa0310032d7068d701bb56f6817480c1fc093326", "CS2": "0418fdd1c3e54b68bf6db168cae28ebaebe3582c7fe3406fc1181dbf4347e7ef5521fc09e17b499d2ce16eff8b0d7917d46bffcf71576fc19dcd72d75c7b741f63", "HASH_MPIN_ID_HEX": "05348b83ca223b5a79389f69dd3934bb3f6ed2483e9e2c12d946111bf4e1f61e", "TIME_PERMIT": "0417cb213f986fa98457a8eb3ad0c905a6553eee4c82196c530684ca035b49be2507b94ca45bf3c8744b857425e5c3c5aede2a9f5c5a45bd5b1565165e7507f8b7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223633393331326134313636313236313131343835386430663835383631386136406365727469766f782e636f6d222c202273616c74223a202263643238663231363034366566616637227d", "TOKEN": "0420baf989c5c469ff13ae61954e74d74f148dd74a94d6bb65f0b293f36ced12010a2acde2d7345f42d1dc8c2f6b0ab6f3f972bde48350ea977475e2752e8dab6b", "U": "04147d701d0c5a9c7b1cf4d1edb38875210c2de08cbb2a197de53f9b491747dd7c101e67516511a6a33d43a59faeae4f99b09f86a1043435644da6dcc7acb66014", "SERVER_OUTPUT": -19, "Y": "011830ba187f3ad2d5e75a8d714b0d81e26c8f6c5881ce329719b19e00a38056", "X": "13885769a9c666b1337e975f540a6eaf7a8ac38339ce38f426ae57dfae25e5bd", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"639312a41661261114858d0f858618a6@certivox.com\", \"salt\": \"cd28f216046efaf7\"}", "test_no": 117, "UT": "041054b0c35847c89513f2efb76f270e8834ae4bdadbf91cde255a9e2f10d925ef0b32e221da7a837339c135e6277a1f719661e9938f74e12ca6ceecd637e963c4", "MS2": "135bdc971797ea32cc43331dc9ad6b0323336621855fe026be1d3a4a81383476", "MS1": "13bc6ed122d44f5f5598045509215b9fb0d4aa1a3711792cb121530a1953f1e1", "CLIENT_SECRET": "04145147a94910ec5eef791e42672e254db7efd0464df94861a662d3abd64905a91cd2889efc893467591c5a1f03971e18d28c6b7b68c5184b83eb34d9481020d5"}, {"TimeValue": 1437055596, "SS1": "202e3fecb7ec4d6e0eff8fd2da3b5cef2d051b7cb321da9491723a6017d818051b6c6c6baa11a67782c216095a95ea992c35e012d1657a055e73c2eebb815dc70ffcddc8372fc3713fa4baf87970df962c2e759b80d53be581b759cc7b227182084ece3a8ce84a787f446330b3bcf54e0740d79acc71fc7f3ed1b5b35f507dbd", "SS2": "14a585d23ba4eb51e7cc077e785442c54f8b304c636fa574403d751f982cf73310992319c31705946dab86e3b12a6d5dd1dc643cf4b60ef60a5b6b68aa97c03b133fd815d79bdaec5cbbb5aac7beadeca2b8807a26706057890599953aa9e5c41ebd8083d8e86d68b8eca7bdaf8d5a00aa28027af97d1630ebb466303c1e799d", "DATE": 16632, "PIN2": 2096, "PIN1": 2097, "SERVER_SECRET": "1702da708cbdecd64a3febf99b9385ffdb252000276254bc7ed8e0b5e8eebf2b0dc394231ce4165af7544ce5d7ce7461fa0570aa28bf2098836d4d3ddf1c4b8b112e7da84e129c666b43ea6e53e2efeb6fb1e8fd8545e0a399d91fe1ba443af103dcf8a1b25004b050b131a36bc4cc9a8594af393354b3bb565e1de58f6c4541", "SEC": "040229dae1589e2f073748993e70c05ffc4e990eb5db27ec2a73dc0d55fa5bb7aa073a84018cea62c4cf3e3d4418ffa003df58fface1d01e8dedb2eccfb5799329", "TP2": "0416884705279c3ee95f7f5e9bc65eb14c0e37c9935d5f2bc80af5e376ab3084200b1cd7577840431a0b10451add22da0191a275327fc9cf68f84ec120e64f32d1", "TP1": "04015d9a1e60f9cdf66fbd1f6debc51aa083d7ed50778df3c3ab0060da2c3c494819444beee4e7c4213cabe66fd0dc7f042bfeb41ea05356260f35a53ee2fbc61a", "CS1": "04151cab4968ada1bd2e32689f253b69f3f9fdce6f260ad36189961d2e2727bcac21278d8a4f272f18343d4ab4393edef471abb80e5ca2515e66b07e534323f3d0", "CS2": "040697128a83c6e5fcb8422b6c0d8c438cc8c08086b548ad2164e943be9481ca87008fe70ba851da614b8617e5dc3db4a8098b553e0a25fa199d450e34181fb0d6", "HASH_MPIN_ID_HEX": "5662d3e474451df2c82be520c4cc028da42e488e0543ab2ad3af4c5117690806", "TIME_PERMIT": "0407b30190e3c455c3f5f55204af5f7c140efd08e9a7cc3fda86dd9e57f8c46b631d896853f71406da6d21dcdd4238f46a33c40976e5eec3ffa51b784d95a631cc", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20226537373333386436373766313662326537323363383532663534363530383665406365727469766f782e636f6d222c202273616c74223a202265323136663761633234333231643664227d", "TOKEN": "040474e10908cc718e946547b4e2e58bea09b9ff16345113750a6ad92efee5f0cc026b413952df0feab10d0a3902e7b5d2e6a31e7873dadf86ded12166f9135ef6", "U": "0405252867ce84ee8af23ee05df886a8bb84aa400755daa13b755b6e8091a92c70124aebe87280fda84d2ff3e0a80aa94d69d728729c866a1e5421d471fc6f7033", "SERVER_OUTPUT": -19, "Y": "07fcabfb8df10bc698f79db00faf93dfa86c940d46aeee8d6cd9a47fd4e3f03c", "X": "182c27f4596013d091b09ee3a438ec239fcc0c1a0ea91d00dd58ec30aaf82868", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"e77338d677f16b2e723c852f5465086e@certivox.com\", \"salt\": \"e216f7ac24321d6d\"}", "test_no": 118, "UT": "04225feaff166d72237dc2df79ca2b1c2787f6c92652d8ebd9a52baa0890638daa22fb1e5750cc162b5273c9e8002d318f2476e61a136f1e2d21015bd6d67ceae9", "MS2": "040fba7bd591e5469d4c3b804c51f83d52c2577ca0d3d99342e74664953f8cf8", "MS1": "1547ba8262fafdb0528fecfb73e24ef2d31bf2f1f5c38f48e9c7fdc1a20e1f33", "CLIENT_SECRET": "0415c12dcd0f8003233a37e52245af85a2947eaf543586df03d36f61161e9d22d91970a90f0826f7d522b281458b1ad4b39c5e6402bbf3a027ef4732a69d9700db"}, {"TimeValue": 1437055596, "SS1": "0a15f4914b26841fbb86ccefd9e29a9621fe5e5dd1331ef621765251bd60c8f10960b4a8e58ee4b734b6c8cd268c9a63539bfb1bfe79eb249fc4ba9a538aaa851ffd4f981f1c0c99ba1590c553ab1b6de3acb377032e060ff2fcaad24b14eb54049ed808552b1a69e0910999e56916426bb89945bb9daecd85554963a09653aa", "SS2": "1e0eb97117d9ebaa8a2596b9a1a5b4ad52f2da91bb58ded7d7c44ea8f843dbf011df09e347089291501a5022fe693ed7b8dee2e268e686395f6264975ea75c552324664c2d5b81a7653dc68c971d4c6f73343c58427b69ad654de65bc24f01bc113b7dd6ace1ab3ae4426142d624ac12af23173406f892baae76865967a02a9a", "DATE": 16632, "PIN2": 8165, "PIN1": 8166, "SERVER_SECRET": "0c008ddb999e4a4335d528e89407c90b7d63c0acff0550ff5e4fc9f594d1781313f91ee9b127983b78779deac5588ffc8c9f4a374fe09ce2dbc55af3e95807c01bf5a1c827ca2d7abf432ea9cac94f0cc510e68d3f145145050ea45cd220185f0000256bc926b1cc8f8f90e6723dc2a65f547e9154944ea93dc59f2f7cc0a02d", "SEC": "040daa7d15e18f420e517ba79b908b2a317bdaf3d16f931e05cf709ce4d46676bd074fedc28eb4dc2357fb2779f0c028083d8c376466db07a72922040e0ac794c1", "TP2": "04041c7f9133c9c99171a5561a80e7b00333313863c6b95c8367f5b133a461b5f00b9a4f7c687307217055ff687a36df0d48165d4c8d624fd7cabcb4b67b726282", "TP1": "0421e24914375a0866ace11689c54b750b2ea3903f96de3e5262bd142bd4592b9f06bc46ea3e454637c8e9ded11c29078e8122ac86abbd668c44a887a02c075c85", "CS1": "0416be055eb727264cabf0eac7266fb9362bc46811e56a584d69affbff4e86ee272178408a02a26df9bc3b90edf6ea493d05bc27914d7b8a88d601dc336310f541", "CS2": "04007da2f5aa32ed3a970449b99bf5ea3b9f901e6d71484b924e6b71196e094d5613f61219a03522034d94a13271378606c7f4b054f8a9fc5ce251dbc0037fe5ef", "HASH_MPIN_ID_HEX": "7775474775edc1ada71c2f5b7d13cefe74dfdb16a4bdb7cbea1f9ba3ce11eb19", "TIME_PERMIT": "040bc9ec56ad9d56feb4775a15809630f5dcd0bb4a647a472dfb6f3c96b27297471d1cdc6e02bbef416de50e4f7e456d4aaaddf04f413cdd00bdabefd618dd1e86", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223135646562353964393666303739393864626635373966323264333462656630406365727469766f782e636f6d222c202273616c74223a202233363235353836396532383537653937227d", "TOKEN": "0418fa8f724d3e7e690099152ee490fba5607a88792eaa555a54e29d1ba6bdd20207098cd99f00ef52240ac6d080dbe49418a0d2a0faa6824a9c98b7f5cd187da6", "U": "041f5079932e65f33712ab7fb2883272ed72a917c2f2600d96b8190d40d0663ea12369b8eef078f0ce2bfc2cfd912c152c4fb882ca3911f33fa1fb6bcd53c45984", "SERVER_OUTPUT": -19, "Y": "1ca95fd364f6cc5803f2918aae9ebefe0f2b7089f52f0bffbd8e13759ec040a7", "X": "1df45f672e29a7ec92b3df60dd6ecaa46319a9bd0b890ad1c42b481632a68c50", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"15deb59d96f07998dbf579f22d34bef0@certivox.com\", \"salt\": \"36255869e2857e97\"}", "test_no": 119, "UT": "041b043c234825f320815c14641c25b13eac7867d81b52c1256788308db7fa3d2c0bcd312a568397e952571240bbbb543448f13de83aa8e2376238e51781ed0d4a", "MS2": "0f22ff1dce98874b3334e0c1d2d5995f8905946935d145fe7fbc5cfbe776f0cb", "MS1": "1145daba97cb82c95e7a6102431861f8a8bc49cec7dacaf21e1ba3259d4d4369", "CLIENT_SECRET": "04129862fbb7fb5e783b342c71c3800d17412d24e41b4f97a523ffca4f4f540f820bb8b34938636a2e65a6088bb13e399fde215e435bccd527b075a5618d26cfd5"}, {"TimeValue": 1437055596, "SS1": "22037c6c69b42c82304baf147c401df060e09f5d5e830f818e1b703abbfac5790ee34cd96c84b9817b1bf971f9aae0d2f9cbb1d295ef55dd96f58dae7f7e68161806d3bbd5b7c84324410c800d3edc18f2ed1cf7e95e7449264a05e2d95d9d2b16a682b2ee6f46619b39536bcb6072a2b4f06825af6a9b092e6f65cd5de3fc4c", "SS2": "1d75b1fe6e1da2969d728036b4586a710ab908d0ba7e2245b9dbc32e184fc1230426f5a604fd26c2953a54381ecf46128c942efa4a867cffd6f61c7a9472ee4f0aa7c5cf16228cb4ac837ad871c3a744e8af665a8b242fd8fa6de2df5c34ab491a928adf87dd1fcab317576f1359bf7eb98323747d265d04c95b9e2f28b0118d", "DATE": 16632, "PIN2": 4979, "PIN1": 4980, "SERVER_SECRET": "0d501a2c189e3962acc8ca8f0dcfa564ad03223f9f67ae01307ca974ef65b32b1b7da892880dd6860b21a7ec1c13a161e8b021ce1b0e9c958132ff1a5abda32811c197e57208132f671bf736e36f043ecbbcfe464ceaba83b609e36febcfc7c92067a8ee54e4e901be73e94a1cd78a10e1dd94ed5006208a6ed6e1a4b52a76c5", "SEC": "041edc9daeb8e0f3a6f2fff344e617b5dbc18a06d2ff583183dd8c52e6941d1a2207b678b31d168f24b436ba8d86e39017c8722c9afef8fc5701b21438fbd5da49", "TP2": "04179996a335e4fa309dc7d7942cc36401be9be08969da647943ec405d27f6ea4c1d911306eede08194d505eab8c7e9016e6ff99888a5dbf68465841e54cbfebb2", "TP1": "040c51f518576723b42a52a5ec32229282bed88fa758be22f310776dd469760c71092b25f980f531a855318167273653cc692bf641d3303a22b23e1f89b5d737cb", "CS1": "04114180651115fd82c8738a9c546c177709d2d5dcf809a13e974b1c3229dbed831be4a8ed1329648731230a615891eba7c4ab99093a1f7e1be6f0cbc909309aa5", "CS2": "040c3255e24dde4c72296b4aaa5b3c293815b2a0524b6a827e97488102c2ce5047230a25d62b3aa47e67db35cc6e69a6bb88cd8cfdaa7e3b5d7e7cdd2d659c565b", "HASH_MPIN_ID_HEX": "d09834cf4dda3e0dbc867486426db3a12ba46e1694f89cdf56851ba3333bc93d", "TIME_PERMIT": "04120790f4c600c9d97196bfba5d240fbab2ba27327118587aa4af9c98c5f441ee1372d43d6e272f839b92ab188e8f079637fbc2ecefd77428dadc92177f323a3f", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223166633834336432323136363962333065333235303438636238663966616365406365727469766f782e636f6d222c202273616c74223a202237323134346365633933616634316363227d", "TOKEN": "0411a67cb4a228d908d87d88937601067d20f6fcafc2eceac38a5d2562d0f386ff1274c54af803a65dafb150bca7f16925f94ef809036ddfc7d557dbde11c7c6be", "U": "0403bbc39da870c5d946bf74d2ea9c8adbd98b1fe85c45aced6f661ef752b5b448139bd3d69dcd9343cf5d5d08f5047954ce0d2f7451ba291abb16e304b04263cc", "SERVER_OUTPUT": -19, "Y": "16be4b9b2f5619dd911175999b9b0fea1c7138d3333bc0af3a3b012e667626e6", "X": "06e1700c56a2738b9610c238c6856b4b1a8b36f0f55fb8ea68db182650a7c5be", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"1fc843d221669b30e325048cb8f9face@certivox.com\", \"salt\": \"72144cec93af41cc\"}", "test_no": 120, "UT": "0409fa49e0e810ac318165dcf7523a3aea559a49a8bda7db0eed493790c888bd232279e000c68255912d5cd5aed7a4263b3a2f66eb7418f365d98dddb4c495b5bb", "MS2": "0ceaa7f0a9d8d57620a7166d2c1d8f1c4feabb527ee9ac00d59d3cff0f97d828", "MS1": "069bf1ad23c3769a89983f7e997d85810a2b948c677a504e49d0b65a177507dc", "CLIENT_SECRET": "040c20bab5ec0b3bc309e9e29d0ca128da9f9f3d42b1302acd2b8c0110bbec8cff10151277e46ba3a450e42fffb38dceebebbb31797a4a35f649f9db993033e6fa"}, {"TimeValue": 1437055596, "SS1": "1d0b45b6fdd9582368922c8f1b0964ef0aab482aefe18df6f6735e2f8805324015a5d870168e3e1082d58f7bdfb6ea829f53c4510563c35d54e993c6c0b0419b0b91a460fda9aefe92a6633f4e18dbbef476019e7c8bb5e8e21ba627438f8df01acacda6af077dea85780b3bd7df0065358f3c1e61e77ab0905c7a651e36a351", "SS2": "1320c91419bdd98a4f2ca3b36ae3e7eeffffbd4f009e04e0945a87eef8223dba0519332583a7763b7bd81c2db643eef2ecdaaab187a728bfa09cc3ffe572b2731758bcb9b1715e811c1e798236f6d7e7bcb7c852fd9fc2b32f77fb8a2d8ebcd816e5d9b9fc2c438cb6ac671a364a18d3bce932943b243aaf8d96a0460d0b1e7c", "DATE": 16632, "PIN2": 7421, "PIN1": 7422, "SERVER_SECRET": "1c532c92efa196014c741a52e32bbedff5bc129c90e0adea06465eeccb1d59442015937603e399a2f23f47936d70996ce9f714a15c39193a426f157122f449200147e8a97c7da0330e311c7385485cbb91c024fab3e63aa4435550c92036cc8d0c4066a1b338aaef2da91a2400f563962ef6884a7229e295394a34634f12f2f7", "SEC": "0422f291505276eab80cfdc9d601811245e209ccadf1b08c0662089bf5693af92612ba3acbc0365837fd284635dd26499d2fd97878ddfde22db857e3c6f5cb153a", "TP2": "040eb22148ed57b4a0321ec54df242491cf05e39921f47c83a9241f6a0dc97e9bb1167020fbdb13a8d2d5b0865953a7897820b52f32fc2d3b4e93be27890766a8c", "TP1": "040c594782849e7498bd72cea6cba155bbcff17f1495bcd56ad46689ae93cdd4ac223be994f2c7d28e276ba4b6be157b5c90e902d98fb5bac5cc43e9f1c0b30f1d", "CS1": "040628eeb1edd0ca3848efd182a3e3322047fbb16af887a2a53cdde029305271b008032a1b2a8ad3f9c959f48a8bffcfac4c717954eb3e7605fd7cb7f63d1158af", "CS2": "0408c7e2a89485f6a28c9c5c8d3c5f7f9cdeee773c722796d60d5e34b01bebc0f61fdba196197266160767c6a02d388e708d19abdf0d36ea54e67c831290b57720", "HASH_MPIN_ID_HEX": "54f6633777292cf06ab7a1530c1e7c209a035daefe78d655aec182adb13a89fe", "TIME_PERMIT": "04120ac7ff90bd6fe27edcad5ed74fe5429d47f8baca7fbd1ee34740d399401d5201deed8c07675ac039abeffa2cabf85789ce3bdac91e8533c3bcabbadaa41564", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20226634343137313736303761383265636363633430336366353532373035343339406365727469766f782e636f6d222c202273616c74223a202230633736353135636362383438386465227d", "TOKEN": "0407cb6b362822005b150ef40edb975d6549adb71633cef4be4d4f68ed46102ea90ac53e277ba7fcdf77d6ee4b8a96949a0956066ab3ce95b7bf1b8ea0805e065e", "U": "04227a439b09db1317603014fa480e30a54ebb84b12509313853f73ddc07c836c31c09462f9f2ca9d42aa34ae4d240b67f5a6d8fe9f0033709acae1dc50e2a4bee", "SERVER_OUTPUT": -19, "Y": "03da60d542fc7b07c1e9fd4299999b0436fb036653f6e215982b903a50e4077a", "X": "0aa629b4d621c87b5d808771b142808d87e65767ff24f694aa2fddaba50ca500", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"f441717607a82ecccc403cf552705439@certivox.com\", \"salt\": \"0c76515ccb8488de\"}", "test_no": 121, "UT": "0400ab99d014f73b2d2adf23e9bef97d4c1bbf8ed95d0f7e4727a30720763d59fa0648b6e554e35be019bf64dc15fdc15191f9dfe58075f0cdcf41a6e424929fc7", "MS2": "1a417e81d2f3eaf1e32dca27c99b6333ae22e883220237a509a7997fb534a2c1", "MS1": "1b8546b7d38cec1ac8821852570235e8d531d8a1a9f0fd2f949c0b7a5d0a0d58", "CLIENT_SECRET": "0407930c78efe96ed6f97aecd52069cdad2eb49a878c28164a70d06cc99f8765001638a76e175877424abe3253c000c59cc19034ccedec022b18a85a3112d37185"}, {"TimeValue": 1437055596, "SS1": "0e33f7e6e974e6f39661e6c0c1e8860d31e370be0223faf768e87e4f804f98f60ba76b5fa373a021416ce3a955f34ee8eac5b88623e63ce30006d51a04a6200c09003262d1fde078bd9bec6a680032a9dfbb22970ed1c9d8ce56423b6107b78a157739a4bd8d9474140e3ab82a2b045af2a99fbdad8d56f532ef0b9b98285d6c", "SS2": "0d00b496394e216dfec4253977c58454e7d5457757f91271cf3a3ab2476e6d9b0248eb70dda0b4992f748e78ec4d547fab50d711bdac72a3f347fa05722ed8f51f13cc1db9a9b79620c093a56690e5cff2421583475b16e2fe5babbbca5ada3113f95631c8a53f37c16dca894ecc52ac06bd5d84b536349cca23b24959122a8b", "DATE": 16632, "PIN2": 4596, "PIN1": 4597, "SERVER_SECRET": "095c30782d2b51a5c8e9f8751409c1265a033d18ed13cac2c86880ac3230e7821f5b649b65d707c4235babc584726def1868a8e8271960a58430b1b1b087a3c311aba082b445c06b8a26f8c08cc4e7269a7822eaf0b9dbb430de3ae09bdb34ec126bf168989dda5af0069b9eabe39a2f5dfdeefde9bd030661959df640447b4e", "SEC": "041ebc84f3d71a4d868959dd23c1a519385fade0f4452754cd769870081ee068ba1539380f2f2c33d1af47f32534b6026402137e7b1fe3b6d0340f28998d5e8d3b", "TP2": "0408f035c676669d21281f02959289c12c5fd828eb8468a8013cb05133d9cb26b9050398666b9ff66f80a0d939bbe81eaa9373d375b15e9b14610b8accb88e73d0", "TP1": "0401ba7cf51a60d34ce88acd9ede0beadf402d431b87066d466dcda8637889f96e168cf35d823fcbfb8648f9d076d0bdd1c0101c4451930e7dc021fdc826ff5ec8", "CS1": "040042f29791ec2a832fba2dde8d074006309e6f06296aa4c9283d9c16534e60fd1795c21f07cfd5954ce93510a01c315a06ffbc9b0c0742b9998cd07a0e477363", "CS2": "041365dfafdc8032f0b99547983a37b87c39062e5a92d238047d63ce5ba53d68a72347f296936ed6a141a5e09b650cadbaf4a69d218de9719e12a4219261d79874", "HASH_MPIN_ID_HEX": "7a73b6127018bf5be655139ec538f5c36b6217de2babf311f589f890d679d174", "TIME_PERMIT": "040c670f93e4e355ee048d11ea10bd3b76ef452e7eeda7a87958fc5329e505dd581e1bf3a9aaacd79f89baffad9cc8d66356abc33e8bdc0884e6a707538f69181f", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20226633633164623865366532336163393834636336306466316430653762623166406365727469766f782e636f6d222c202273616c74223a202237343837346162336634383835626533227d", "TOKEN": "0419e752cdfa39d41e7e354ec59004771193a668494b74681c3fa7c03b972a598b0a581a60409e27668fe4bf3d4eb1b303170955e64bb2e6fd05bf082c6ee71647", "U": "04118a4971e789bd3f02d8f87ab9f0bdc262f504219396bbd18b50061806643e1f014ff9665ae7ff84db3b0ce7b9f7f7f8161f650930300f9fd43dd366b6ab6298", "SERVER_OUTPUT": -19, "Y": "1063aebc073feea70ec94b72867f082aec4369de0a6ef5822201fd6af179005e", "X": "0aa849fb7881253fb4e613617e4f0b4e7661902c5c77f9326c5ac1771ed4e5b3", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"f3c1db8e6e23ac984cc60df1d0e7bb1f@certivox.com\", \"salt\": \"74874ab3f4885be3\"}", "test_no": 122, "UT": "0410f8709247e5285576b268abef50514dccb2e887114a3f1070e146e0b420a7c716afd2c23727b4a84a64b92a811732ab484d0952e51831fb067b0b66b5e67b85", "MS2": "1e920e0d0d1a3acfc8a6a0509853b27902d5fc24296aa203c8be822e56d8a0a4", "MS1": "1da089dd64d71e13b68234949abd1a9073fc00bf76ff4b7791cfd89df642d98d", "CLIENT_SECRET": "040f203584e1fd6c996238bc0e252e0eb908f565a4fa4233531bb9b0d91a08e4131d7416b707b8e8e88d4ba0c2c34eac26e3eb233890298446458c70f56abb48c3"}, {"TimeValue": 1437055596, "SS1": "1d9c276b2c582dbf8d8fafe6c6c93dbf494cbd576bf0559b606a9b87c4da3b5810949cfa11d4ca44c1b30e27f06c50da74b25c66006c8100432f9aa9dfe450bd0b2f9d51d68298873a980743426809d331bcb6ab33d5beb3f288b1ca976e8df2138c7a48e19e32cdfc06107211e121f0e4d187e542c8541fa7d75d58065866a2", "SS2": "017f4586429ea363e5f434b929dc7ba6a5f2e4e81dddda0c1495f170518b55be04dd8f38ab8474457a68afe127adeec462a5f8b3b71bdb25b7a20042e851bc5e175d8bab7d5557ed6a467c10132106b812ec45b5f9bfa89cc88042a401d36eb505f7e90df32bdaa7ce72e90f5b9d52bd44bb3a147a939fed601cb1919ccee0c0", "DATE": 16632, "PIN2": 3000, "PIN1": 3001, "SERVER_SECRET": "152467057551c6d31c148c590e68a42e7c0aef3eee2a420603cb6e73cc1310640d152cf83ad2c070766e13dbd5855e9066b2fc4d23cf5657b8daf70313f096b1110ea73888da5e53f6732539262903eb50cbf8aa6c54a7384af34a5efd374a4619bde1b9a8c5ad2e6976ef0fdac5b398ebd2058724cba22f037c90dfebb956c2", "SEC": "04014d1cca472b284623d46e8b7c4a0d8c4a1c8a110bc959be0bd62cbf8e20d76a0e17e7864bbd7d5d9e61e7bfffc42bd509b2f5281ef06fe95e81aa12fdf0ac15", "TP2": "0413b29770bd44e423b4981131081161e31f0ac555b697306894fcac250f8cf4641257494fce343093dc8f2fb29e0664061678d5ba4068210310b660b3df9e9746", "TP1": "04022d42d58c226147ff7297240f5ffe534a153e692052044366fac5031a1ec2f91dbceb047c0270a03250a295ac6e35ff66c53af5f941f525e4548d18858ebdf3", "CS1": "041b6618b11c0a05d46bd3cab9849b41b7198e3d4b13e10016b80f86ff289d15d821c5b212d7f942d43fbce24ecd183051635dcf1903196128e38520178e22bd3c", "CS2": "04121f04662270bc9f17b89f614e580390460a85c4bd0693b8d52b7b9fee49bf341ee3eab40f58acdc15f7fa0c90639a9f8e9c5a41d90d348f7f2edd8328dea3df", "HASH_MPIN_ID_HEX": "192a075b039c0cd9e872927035761666d2e702c049f813fd91c757123f87656f", "TIME_PERMIT": "041bf4aa631389073a9ec56fb731ad141cf5cdd804d4df8a2ffbd30bb1537f63ee0ac264ef8487c3c8d6a9370db1a708070541cf8cc96ecffa8b17291e536b9d97", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223038656561663961623265353137666661336437396636323530613935323362406365727469766f782e636f6d222c202273616c74223a202236376635383835373030643639313136227d", "TOKEN": "04119daa0c4658543e4b464a08f21e2c0ad2f033ea6d24034440c6cadbcb4dcd6902ea7615ccdbccd3c29146f74479b10bebbf671bd37bdeee7edb4190511b106f", "U": "040d6f7393c9c15dbb4524bbd0c4ed3920c193234cb817fd252e8ba3e20924bde71990c9469e92b27d75949a200872ba543a359adb287560d1aae515d26f707e47", "SERVER_OUTPUT": -19, "Y": "1015c2c812707b6f3d4f76f86994aa34fe279ef6569cf187da11cad2bd88ea8e", "X": "11fe07509d145bbb09d4d2986dd6f24044c5893ec09e56ea7406543a91d1ef74", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"08eeaf9ab2e517ffa3d79f6250a9523b@certivox.com\", \"salt\": \"67f5885700d69116\"}", "test_no": 123, "UT": "040f5dc70fe57711605e925ce4045dc7a42010585507757d7f1b1b6fe5f596a76e2044d1e980de535b2edda2d41c435f6168de69826080cab11537ce6526d06893", "MS2": "17ff2024651cd30d8583a8b91d047844166496fb35cfaf9a973c4e6943c75887", "MS1": "078b33124e766a05ad6f652275ad543af48832ebdaf9ff846cac764b91912f8c", "CLIENT_SECRET": "040affffb64d18ac02715f54534e91fe54b6fc2387904cd47c2785fbaed889248d0e299d960a0a72d5765c07a123ed6a3a946fe97c9f6a7b18ec9a42e5b033dd37"}, {"TimeValue": 1437055596, "SS1": "160589d88c35d49886f12206f3d937eab08042c1584e17a33588970b6d6bdff704f72fffe240bed291b1af8d94072bf3652e6cfc16dce609423eab339aac06191b8a764834b3a67893c1a2249dc8acf8f2c76874f37c2fd53fbc7a33e6f5b0d210574b5e572c16ea2fb935a62d6f391202937e4ffe58aa9e6b6802902f8ddcf4", "SS2": "1ab0b63e6f892c7d41171cb07d2471cf24ee0ca9b4c1ed5720ba94858083da710c0520f65bc7f518c8717bb20a45c5c5e9827baa98170aceadadc56a67747b070825da7036974a1a6e15ea74fb2bf8a45810c17b91167edc5e3c148e01becd7414c105a4cbf766f0ff1897cd428495e2e471619fae340802caba8f8b2831e338", "DATE": 16632, "PIN2": 3937, "PIN1": 3938, "SERVER_SECRET": "1f2a7fecff305aae4f7c923a42b0991afeeb4d84f6e9f6449c2a1ac6f71009991ad1dd90e3eed34a81a95cbd1a620599fd7938e9c518bac426b0765bc9f412450d96605522386678d357bafa05cbbdcfe623de8f20cd66f191dc7edb7acd7c7206a6b980f7f499a4e641d3ffe217605a55a0b9363792513a0457f3e667324ccb", "SEC": "041804b95d713a8c551c2d2b4a617e9cbc73b70c9ecd9bfdf9a919ca8b581df0f41ac749c762c5f0d56dde6fb71847830a75221d6e5dc2d57bac62a16a52b47ac9", "TP2": "040d96c9573b1bbbf7edffda0d012b08ed9f4806a8fa08c4fa4614d57a8b012185044060bc1b035294f7edc30f1ee29d2c57fb193df91d2a35329a7045e4c21ce0", "TP1": "041bc746a5309b31288c30ee26c6ae97c57fe912eb75d939782e15f2a49093b5cd14cf8d3ff5a609ba9dc8272379a08703f1002022527bfe7d2efe51b643fce76d", "CS1": "04167ae05e4b7d70dbd8ca0b966814330603ce293ac33ac954279658a4b8205bba13ab86454a7b0a8bf224c51eff081b2aefaae512f42073ed8957375fa5524fbf", "CS2": "04030357efd9c848c9484d6a41ebb16ff3de1556208d4e9bf26fb03ce0135461cc0403b7513e7fb8e15c03707d8ec0a33f9bbb963ac397be4500ff8842998af18b", "HASH_MPIN_ID_HEX": "580418e67b1806fd7c0392d0ad83928b29bcac5518efbfc4e94c17bfb459889d", "TIME_PERMIT": "04172212ab03f5695c39563d1a69b1990a4689605dc070e35a59ff82c0e26ed6a61568695621ed133f0f8071b695d77e560a84f3ceb953ae460326a1ecdb7773ff", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223934653963613564663362393039633065363865653262633435336132383131406365727469766f782e636f6d222c202273616c74223a202262613035633733656637663466653039227d", "TOKEN": "0419eef5eb1bdc7b924200213984e6491dcaa957a5f76736442f1232f960b884e00576c1d8776626e6b3dd41324f141f516d8145579b6b0dcd8b153c65fe47d278", "U": "040cbd59f1e887b79ccc6f938b665f84598fab7dc596f99ff77be4ec7524454613194560cc6027d8bc15c7a847a684f96f8097624ab5eb16af414901962c5c9cfd", "SERVER_OUTPUT": -19, "Y": "00aa78fe681a8728a87eb11d4078b2ed426c4ed91302ec5865b5fa6a12b78c1d", "X": "0df0a2ea7e2dde086f027ef0e30e5a6c66d9f80ffe599a86edb362330bdebeed", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"94e9ca5df3b909c0e68ee2bc453a2811@certivox.com\", \"salt\": \"ba05c73ef7f4fe09\"}", "test_no": 124, "UT": "0420dba4a1e10b4d0a339c854030d8b9fdb7014d50b6f89bd0ebe4f592de1b7f4c1c0b5c47bb0d1110282a25466cb60fec1a9a0d48bcbd33bae798d96acb767055", "MS2": "1e9c5024e1bd7c9230652a19ae5c33c300b628bdd028e658bfdcbe7e23c94ecc", "MS1": "09ca23c31dc0a1d96aefff7cd478bc0fdfd5d5b40718a8b70eb31cfed353e786", "CLIENT_SECRET": "040a0c564b4735bc2dff6940fad2180399efa3e5877de6a8f80ae19b2dce260bd01b282bb017ad308f81c1f6a693f19139de51648ace1ad2c042fca6410e861ff9"}, {"TimeValue": 1437055596, "SS1": "1eaa9ddd88023d691895900d8b275f8ebaba9081ecec5b44d019cd0dd1e34d291c0ff2c151b293d72355b4cd764279c348c6a24112574a8fb57e81e19fa0d38c02b32970c613f649ae8c424dd96ffb268c70e25c74deed78fcefa6ac5f37eaa8058e2c457ca09598d4542826bfba25c220e3e906687dbdca605cd37d275419d8", "SS2": "07b80bf10f1e7f8a65bb5a8e41ec1144cf33e5f9f83813dde3ede7e3b78dd2ad16b47483158a9f515728cd2d4db8cc623d6687c85b5f333f9d78212cba462bec0b2b385ef34a18ff3838a3eb54240c31246620fc4a9e36719f4ceea907c9206f0e0789c58d035ece82aec2123c458d29b070db9ba9ba71e42bab79b524aee146", "DATE": 16632, "PIN2": 9673, "PIN1": 9674, "SERVER_SECRET": "15ea18c713be245999317401d6b88e370a6db740e1b95a03a3093b076ed516ed235942b894364152576fb310fe7cc452ed8526a2e25f1eae9c8e7337cf03e616037b84e2246083bd0a17e2938da5f649d97cfae53cc48ef3ab345c63f945980a09d1ec7975c58f132a4578fee4bac4c78741855466536a1b2a4b832856307fb6", "SEC": "040e7f13f002940096ed243a810928e7f66f0fff8d6bfb86c64d72265e3db91e311aae2dc75cd9946356ccd772122a314d85ae8a2cf072214a918b6f8787f42026", "TP2": "04070f594455405651ee98163d38ce42eca79c8b3bac44b14061e76cb9687941ba1c3a3d33a43248f152007860f52ca2fabce392a40dfbc218043881d7a0411a2b", "TP1": "041415424b058d14bf8212ccb96881fb8e8e8746b6cc018cb53f83e649cbe61a6a107297a2fe987baecc208d5e9e1278ed8902add03268511e24e7eb394d1b854f", "CS1": "040e7dbfedd63e4e8063432a45f95da8cee3bf793582dce8cdcac39e3f2cee403e0842e64cf584077394a1f5038f5fa8e70b82e00cf63b0876e2c02f86b3263708", "CS2": "04134f4a3bb51196c56f0debc0770f773335f69c77a4519693375ba88d1c46fd3b15d8ce3bdfd61392060291c136b1d34cbc6d3fadf7934b4b7ce8001451bb61b4", "HASH_MPIN_ID_HEX": "a360e862eceb734856801633fedab0f904e853271df4cfb5fd913dc8d157adde", "TIME_PERMIT": "0421ad8188ceeba263c22fb10c9be6aa496735ec97a9503eb5836f7a90278ef8be0ccd3ed95a55252108923805ff8eee985b29f3138bfce7417a565f8d14b0c3a9", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20226638353430333830363535366237346438323031623235393639643335653139406365727469766f782e636f6d222c202273616c74223a202262366331643838626239386664666162227d", "TOKEN": "041b36741f372f875ec5743355acc89bedb5758cd4562c1800586114505a85523a0fa3de450a42ead5d7a960d7a2131e6e0795c1c577e22a54e02de19b714d648a", "U": "041c4443431837a11a6222deb40f658ae137260723e4968005d8079dcad2da34990054d83866b3ce4042f2cf607ffc3beb30a1a6a96d4612a9f01d65a5fe2e27e5", "SERVER_OUTPUT": -19, "Y": "23148e1d3550135e2b4ecfdbcaca4e9c017277c1e77d547fa98ad77cf299e16e", "X": "20c4f42c4400e0671b66cd55f8f2553f99efd805f8fa16c2348842378a42bb8f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"f85403806556b74d8201b25969d35e19@certivox.com\", \"salt\": \"b6c1d88bb98fdfab\"}", "test_no": 125, "UT": "040984f82bcb7b913b9e4b0e4ae3c297687a3fc19e6496921789d823f344f3c2f51dcbbc5d376096e184c0f30da40d856970f1b039a644c135d07af3c77d1bed18", "MS2": "14cf616ef9d7f286bee5e41918f30a881942a25fa90a3982360071938f1d6b67", "MS1": "0930e9e27853951349f3d898e290931b79bb17ca89d651319fb0b9b7c4a3690e", "CLIENT_SECRET": "041a8350a701eab4261ac2a9fc1c914a8f2723ff32778dfa817f8af8d84a3057591e2f41dc2100c40b2262d1751555a04b8b55a38f97808b7e14a5b7997bdd8c93"}, {"TimeValue": 1437055596, "SS1": "1b842454534e5fe75a7131d1ad376f14cd5a11dab5342f4f02cb1e165fd1925f09d4c507bc4e4ab0eecd7a279895eba1e9a383f85ad3012d143ea1e422e2ff91104c1c2b2148cb316e987e80969ebfa2b93cf1ae0008d04918ab3524eb6916791295f5ca6ad78e0395f3dc042953148af3eb83342185b2cc3e8d5949a8ad6328", "SS2": "1690d324416788306c9e933e91550004a4e45185f6d950bfeededaec22c52a370944a7ef9022d6dea51f0690cbf925f788fe3d40fdec694847285e565d365b150eee8b405266687d3d3ea565e8a11b3de2f60f6b8f042adcf40212cc584bc8d71bad38a1a71d489c7a6213910b8051703359014efecbc450f235bcdd1419afda", "DATE": 16632, "PIN2": 4986, "PIN1": 4987, "SERVER_SECRET": "009b724199855f6c492648a60c7b6e08c2fb4264f718b45d78fa31aa62845bc21956d565634228045cd71e51a05b7a85a7a16a2cea343b1f4544b25a3cce9b471136e02ad9a79aa4d47f6098244abe058d0702526709fb2262dbde96d624fb1a06382107e9e172aec9e5502e395905ca0b75bf75ee58c198adc3d3ae1997810e", "SEC": "0412e2769617e157d667456bde4d0b1fe6bbad7cd928b11263da82e3ed0bd9eb9617496e848d4f3a26aee95c38ab3bb9c39283ecf803a78939eccf670a773a9078", "TP2": "040d8f98e5e8820a6f9a8db717395f7c9ccb30abb94888d63277bc1b863d28629f23fa0d79f62007f10813171716669dae793cbc977aab320bfc6a795088ac840c", "TP1": "04168a3a514b705878a44335c45b37430a9100e5f07e5e9a408cb5da9c50333ee11a3320c4ebd10a17ecf007454c5e0ab6a3c2431aedc125f12c44809ae2fb7dd4", "CS1": "040e19050dff4538cef86c0802d7fd1a9e9b56552d99bedb8c9a52c7ea1de834f40383b2394105259c2744b70a698576ab2daf2be3409c54f8017b0974bd5d8db4", "CS2": "040afbc9047cad6ebc29b8e68ce25510b9bd1d5730664c25c4aafdbe287d3e2f951be2b3fa166771f0be154012d90def36e42df01b8028ae065dc4e96f0447b132", "HASH_MPIN_ID_HEX": "5f0b7baffc2f4c62c39cff723fdcff82b245853b840654f0cb85c313b3bb86d5", "TIME_PERMIT": "041ed5d46ec2739ff674cfdccae0c2a694dcaf1d4ced7e0aed63bd6390458187cf1c1703b4dd9cdcadb85a101d9be7d02c3d17c9a3a1e8353397877baed8d5ad39", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223536666564343738376632613638623762366331303638366461303263373230406365727469766f782e636f6d222c202273616c74223a202238323232396462633766363862626433227d", "TOKEN": "041c0c1e0baf81088292ae3999258e31b00abfb0f430da121daacc0a5f824512690570a726114913b3d5ff11a3ab159895bd69679ae7aff27337b31a35286c9145", "U": "040149b2fdb642d6752dd2f7495c1ee43f1ef88829b750ebbe6284262fe1e1c50d18795c7300c1437694ec4439784ac88aabb68c3927aab37716fa875f926a4a0d", "SERVER_OUTPUT": -19, "Y": "04c578ee20259d0dce69606c6b1756671589ad4dd33ee4920f42749f9bc3c1ea", "X": "18ab4a26c7b0f1d19a33d494068034b9c25a0d9c90a44b7a9a3975e01862203c", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"56fed4787f2a68b7b6c10686da02c720@certivox.com\", \"salt\": \"82229dbc7f68bbd3\"}", "test_no": 126, "UT": "041770597c88d09d67b6b5e1ee97f9c5fc97ce7860e938b3e58065cb8545c6537303c70f5d21761a22301462333b6327bcd83587034b20f26f2c0670ff7c8477ff", "MS2": "190520c461c166535abb701f99c87645655855a7dd12d8ea3fca038f6c1ec2ca", "MS1": "059c8022364d3a300f4b66a4622fbd923b80c32cdd8498371820089fbb8884d7", "CLIENT_SECRET": "0414e9bd1fe55b8b9844c3d5632aa076ad0588590fcf1627610eb9505a04cc45af0c17750f351cf385ecffe30739e10f1cb8ac70bdc2ec188d9ecb34b76c64396d"}, {"TimeValue": 1437055596, "SS1": "0d9ee897c7440f4e3e33a6e849b15f9f7ff8711f47a12f3407a8953bbadc5aa31fd54f248b75fe8074c9c2504b7d9a3417c41ecd304a78c424d364d26ec8e11812cbd6e452c64912bf5cded24ade92dfc7a90efb057ed0d81ad59e195f23b98e03fcf59fc8f4854a1f759ac72efbb8133ad80fe4d975d07eb1d32b42de952eed", "SS2": "21928c90fd6021e3f735e6806853eb33b3dd0c97aabb8379fc023095ccf4f11f1266ae0434cbb41c94fc4acf33b567e963af08c368afc86665118c6c054c888219532ae52657dd2d28dac87edd7899e1163c93b9bcdeeb516e8c6178e2e357d51bfaad528a3b002e95c7f2fa4293c4534015c75362a38854cb371c2ca5bc15d7", "DATE": 16632, "PIN2": 1236, "PIN1": 1237, "SERVER_SECRET": "1099b3b7d7a57510b68194b32426247fcdb34caff60a95eebb41fc142760183d0fe2acd485893d8fe6354b5818b73422213af83d8e670631fa07ba95bb4d424823936bde8b6e973f5751619a42fa8b3da1f9b782c03c1b0ff7b864a96c206e390f8ed57b3b6b9955e731238d2b0016db68a4d72c717f4a26ee8a6865e0751673", "SEC": "0422485b71a27c1515f7fcae7b9df60d1b6e1795369fb1e8eaffc56cd65c5192220acbc5b58c7750e6ea92cbbb4517d8553a5fd56b151c15be38b88b8b974e589a", "TP2": "0400c4a5c12f1e273c3395df1a69b078ab35fb86884b23d2ddd2b6d550f1d2851b19faea972e9a5e7f89110e6a98a7fba5741d3847091cc2a96a77fb3c866f7039", "TP1": "04152940a7e521aabc8e2c46a6ddc8ec5fe29981c83bc1f0d6ad21eaece288888d169df192b5ba3a4c0a4d1a654e38136bf71b23fd8b8391d6166f6ff5f051028b", "CS1": "041f043371a43c37087a539afd338b052ff2bf0b34c8eaec8c3d07190fa5c767360c021141f8d2f75459a433ce85a3db8cf5897cd8c9991aaab2dfc888ce429784", "CS2": "04211a364ce52b9cab55e0d98afe242fa50878a1bb14400d47cc811ca73457e6fc0a45afcb72d29cdb6d65f77f00fc0dcd3bafac78dbccd4953f08df962100b981", "HASH_MPIN_ID_HEX": "c65b2e843262513ee6a99766a760832fca68a9151f2765388893d444771e16ed", "TIME_PERMIT": "04063ad2375da124dbb8b5b719f71297175ce7923b4ce399ed862d78e1a305a119225d9e7f8b76c470e258b3f96e85d57966ed6245eda8beb3d9c04c9735762124", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223433323164306530326438306638333065613131303434646664353065356365406365727469766f782e636f6d222c202273616c74223a202232366465616432343233666131353463227d", "TOKEN": "04203f4b20c729c94a36268ffd747d22fd9d1a2993eaa3b62b3f6c506d1f0f21170ba18dbf274914c9c9532c9f7ca7b7d2731378532ef597ec355407b3ce8e106c", "U": "041309c8e7cec4b853de15c4b37d673659619bceec1f798f72e93a87fdcc10e0f511c87eda0460840a705e0028ec98b7f2df68c4b633c47c1f99bbf204e516ddc8", "SERVER_OUTPUT": -19, "Y": "1382473c84fb8d7820586fccebfa22895e4ecb97a4fc97569519db6cefe2611c", "X": "1fb0bd6044b84edfa87e40b43c5d41dc6431fdc7c30830cee8211407a4c011a7", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"4321d0e02d80f830ea11044dfd50e5ce@certivox.com\", \"salt\": \"26dead2423fa154c\"}", "test_no": 127, "UT": "04143df5a05f26efcce6b97aec17d2ca4febd0786359a4e4b04e2fb36bb252d2e00d7b889b69b537e47598bf559c4edc7b7475fb42d04054305bf94b1580fc70cb", "MS2": "1bc90185680d58cc1b924dd2ea0a792324b623ee3d03c4c5b03812257f673372", "MS1": "2146df6b20a177484a541b76a64d18681193cf55cfea11384372d7e353b4fcdb", "CLIENT_SECRET": "041e4291d11bfe3d40b98573d2e23ae333a72d412b8973d57295daa1d52423eed31d6ca51f56bf539572d7224b18998c6dc548525b5cff96ca293a37b53bccb1bc"}, {"TimeValue": 1437055596, "SS1": "1fe03b5870e947ac498d8501ffcedc9775417241ff7e26382c9dc980588787b311a57ac03e04fc0c2f711c654dca4fe7cdde207c30f24884df6c23951141b058169e191bae12e2dd3bc0707b047a6e95f2bd1a0d31cd077bea25932d80adb141082a5c404a60f3d610f67bbd767158f0b659ba7ce05d2c500759543402b4de09", "SS2": "0cd9d588030180c90da7c0f4c3baf396f1c277f27505c34a0c51b8eaa2ea177319a3b5fd0dee55e5e72d661572fa04e849198e643b12a54d8a6c03ab7006895a0b6a8ecc57fe23d017008db5d8424c4c887d26065447a79611d3932abf61ddcc06c9eb78d4c7e5aba26cb2606406a325874ff8c43a9158d3c6566215d091aad7", "DATE": 16632, "PIN2": 55, "PIN1": 56, "SERVER_SECRET": "1040209c4f29d46b2ae9871280c45da5b96cce3a74fa13716486de8c802e52d51fedeba55d39b379fa9441bf26c7bf0257b9d0112402a374d4d21c46be99668f143eb80a7e7615365e2347a5b22a970126e0c364e357914e9e67eb688a8a47f70d06315b80f9928f3a2303499e70e72361a11af9421b7f2f56304b77a0b0d3fd", "SEC": "0405b5c1628e24a1a96c9814fec2f577993b9914aa62fca3a51edb24c4786d31471db7ecebeb6086719b7226c26d82d53e85ff98cd8b90f4733bcc492cd1935dc9", "TP2": "04038a85a924206c145700b3264f847c7ca2adbcfa4129e7f116d79b5945b70b6901e2d9bfda09f52041b1fe901c055c27cceb73e9b1578742cf8d651265369b55", "TP1": "041a0c3435f79edc84df147f8134b100df974710ebd936320b2f15e0ec2eba3e641e96147bfd7c64a6417cb0df4cf4560fe54e1acf6593d4a45ee72bfb61534325", "CS1": "0423b602a1ef46dfad05182d4011999123a9435110bcbf6d11194c75cb11ed8da514da78a1618377d88d3be5b12fae36be12528d444f2ea2100e4bf4c424ebb0e9", "CS2": "0403f13fab0a604554e9120c35e59e0498a12ca904cabd87a633ec9049ea201656133a525a9a750f1e70f6562d0fa7f01aab11833c6302b20c4947aa88a7e461f1", "HASH_MPIN_ID_HEX": "eb91131d1c22106bf452d00fb09b841adf5d4234ab4b89f02ce0e1028bba8a02", "TIME_PERMIT": "0414dfd4f85da8272f6a1281bdcf04775e23255f462dd2885684561849308f4f3f2366c23eded7abc538edefe9471fb48b850c13d3bd7b658ab42540bf296e8513", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223133373466316434393534323532633430646666313539666330373935626366406365727469766f782e636f6d222c202273616c74223a202266393439643436396339373866393536227d", "TOKEN": "040534bf82631f2d4f5bd8a3e5b791ef571cbe7cf08562121db8d590b5e1ffbd740cfbb27f86b213ad510227bc7c5fa94ccf1e565d60f0df753e333a36b6ea30ff", "U": "0411d2f1d33866fc69c01e7a4a12eed8f0aa5e6b045ec8491475c25b34df3b299f029b2c26217c128fb1d702dd311bac2db091add49bd175fb7f2a779ecf54ed61", "SERVER_OUTPUT": -19, "Y": "1981cc81f15b383b5d2e3e44d639e3b340d037ce64ceaf0ed84e54b6fc8d6297", "X": "1aeb6981043d3a2a8e1be7ad19e01ed9641a219f4b2781440d4e782140081973", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"1374f1d4954252c40dff159fc0795bcf@certivox.com\", \"salt\": \"f949d469c978f956\"}", "test_no": 128, "UT": "041da33bb00a5189488691469724698a7a57f3db53399cb4b7d100d647421ff7d6230b1c1aa3ce3df70eacdcbd70c6d23cdb962dfddd433870e196ff5e9d5fbc1c", "MS2": "1883f65289af52139578990e2619f71e62cbe8577961a127e22b867d2223be2f", "MS1": "1939bc7491bde9cf1a5d1a5faf7510b720d7868854e23c648d1971d363b47dbc", "CLIENT_SECRET": "040db8019dc7ca503f2af8e8424b7fd8dc2d5f3c92b9ed85c163808919fa8f0cec0d290e9af46e37dc72514ffbf78fe6f9a985f3296182c5d60ec0277e022a0c47"}, {"TimeValue": 1437055596, "SS1": "1cf3f75331df885fc0a9533ed1d918b25c338819f37651e5127aafb11c9d52e20a639f86e9208e05a2a2ec4bfcc8b28cab5b0e607d57a64bfed724bebdab95462375473d9c1ed2d1810e0418a7fdc23f0a2d7d66aea844adec778c877b5142930022fad882fada25812b850b10c86afeb9d8677a237cccdeeb8a1532457b2c4f", "SS2": "0cbe29bafbfc4d1e65623ca3f59e19db1dab48d01af7519fda7aefbe7f63f524159c2edf38bd7153554e03aa3fdd0ae9657ef23d1cf0024e6d05c827c8432e670a7faf18326f10c8eac5fffcfbdedf1c1c80aa778513d54f7d8ea8142ea14dc31b3c091326cc28e66e3aae7398398af268200da798bd6d20c0303b06f6f279de", "DATE": 16632, "PIN2": 1543, "PIN1": 1544, "SERVER_SECRET": "1d0c2f1c188069023594100163913e8ba5ebbac0e0e6f22687eff1280bbb45af14d90343bbf0d7f0c4201e4532a46c16dd2a09162d490f3034bd79801c41ceb405905b97d929e01e21e2107ea2fbec97a3faecd32a0ac4b2448f073741c4efb51022132c6bdc4c669a99d0013140a197a1f18a47d5503858f8c2da26ee919a4b", "SEC": "0400da1e69cc3f47e1a9131effa6e34c91e1425f22409c8a2383e1fe1600775644031d5c3ac7b5aa7770bce3e5583eb047b7f4c64be32269d2a388cafaded02ec6", "TP2": "0421ad1612956ff63d4a77a4a35c46f7abf7dccf98df96e954470c1bf78585fca7215dfe1f7672f2da624ea3d8328c82dc6ef6f27f280966bcd0c5c837df74caac", "TP1": "040aa1a143c660bb4e545fc14f61fe69e8eeabf6e011517ee5f0c141cd472fc37c222d98d98b21712b750ed4457533a6a525017082d7814acbd0c02c6463ef8ec9", "CS1": "040d3bf89687ebe181cdf45286210219c57d6befabb7f488e69e58d9e061088127006fe7ace725edbfa751154fa1fcb839f73eba3b6000f3b308a03841bc3c2fc1", "CS2": "040511bd548071d0feac1a66294d5cd51ab842991c8d1276deedfd3bbcd0fcec920a2e0dc71c3d74553de7963c26830bc041289f8db99dc3297933f6086c3bbd5a", "HASH_MPIN_ID_HEX": "e5dccfeaf7b35a1d5a85ad3bbd7c2af83b5763f933ec817984ea57efcd5c7a2e", "TIME_PERMIT": "0400b3e2e5a9d4614b27731f6b06dfc2166ba2f9cfca722985e4f356c6775c21be04722441f3fdc1d5dafa60e71acae29c1cebc2811e8ec1620cb87550fd5d938a", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20226466623936353138323533623564366466353265366538313361326634326461406365727469766f782e636f6d222c202273616c74223a202230356266303961373432663830633636227d", "TOKEN": "040513efb84bf9376ac1996e9c1ba30dc7d4129a72a99803691205d1d4f2735e0809dd2e7dda8e9bf5275b6928efd7247798d31fe9bfffe2b8de3b30a2bf96af09", "U": "040355f54e64c80c013906397d42f929f559271a1a8a77f70317cf343f503147dd2286423ce20d09058247b23db1bd19efd61f57675fa50967c485bcdab43f243d", "SERVER_OUTPUT": -19, "Y": "1ce63f331d2d92acc7f3b81753e971683c09faaf7dd23f4349246dd374c2d48c", "X": "0127dd845f12dbe8384ae1787aea1cdea8ce28e55753ecda4e7e8cb3cb5f6d6c", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"dfb96518253b5d6df52e6e813a2f42da@certivox.com\", \"salt\": \"05bf09a742f80c66\"}", "test_no": 129, "UT": "0416f67c7cbdd7cb012d4e2f38766008df134c6b3e9b35409b7d974c07b1946ac819ce297e8e1a67f6c3779f2e61425457c5f13ffa630188c3de199fc1218bb1d6", "MS2": "20abcea82b121a7a04717d7c38d1111a3b27be2eecc4d269f56d99e5a7022bdc", "MS1": "1e972a7fc32aaf19a1c0b46dace4d0d694680ebd51f11f2f1eecc8065b92bfe4", "CLIENT_SECRET": "0418a6369e24a6645bc49a9caff064c3077f9fb7f1d976b3450dfb8d15baee7db4083a0950d958843c4d1832f6a8ecd4148ad711e9481b52bf02cd40b66d3787e0"}, {"TimeValue": 1437055596, "SS1": "1f25079e5441bb78c66cbc61433888f51953aeca712dd20390b3c8c379fcf16810e6e17b0854c36f0a45396ecdb7210ee6e5da5ba9aa3157096197282042d4e019385d3f5e3700522241a3201a54082cdaef326f2de0da61ad107eafe24916161f684ffbb87a92bc07ed76650d4031475813498bc1c0eba06b32cdd6131cb74b", "SS2": "1ec134f763c7d5de9f1d7d8e16289ff2cffbd8b0a5fe5218407cf442ffeb190b0f48810b2bc36d69bd84b45238a62fed90bc90fd0ace49d87f19ff7b960f41b410ff49c53724280b1c14b66655e23b18a42d75783bd2fee541480ecd7d55358217c7d024c4db5f909444be8698d1ce34d83c69f9c1c13f8ba7e6282f8c6cd9db", "DATE": 16632, "PIN2": 9578, "PIN1": 9579, "SERVER_SECRET": "1395cab47b7e500eccc36f61c6cba5e83bbd322b1f5f8f39fdb0033df49c9c26042cc912ec6623ae58880d14523c0c3bb3a41d1099324e5992641d2ac2cee3861b3c641eb636c36eb030161afc2c32cbd3404acc8ae94929049fe7d314f70a38109b8f57a51f44138bb263cd571fc31a81a5ba9339abae182065186f8600d777", "SEC": "04085dc0e887619774d67af8c029c1c3534432b18ca7da018621cbaa31c1138d211625d4cddd4a4f2d914045f344dbc0430680bf47c6716f6f9f87e1232978f53e", "TP2": "04106da07b46c3187001aae52c859ae228eefafdf08b48a1a141d5f168c26e3477170f70ff621d4d875a8d5c34840265cd05c865dde86d77d0bf38c936a539de9c", "TP1": "041cb05af677526e755bd48d0bf3817e0b4b97b63dbfab27ed83f7bdc08ba7cb1418f41ce4395e39176748b70cf77308f31d15a4572397ae9368b660b2551f7139", "CS1": "042234ee27e88f292503f78c9b5329ab6ba85453f0c2a5dd2fac0a6a87831a59851ae8e8f177539138e01de643a88fb21862c05bd087b80a9efd7d099cc6104f4f", "CS2": "0417e8f59b8e02778747ae2e2977c8573de79795ceac78615f3470c43d70ae71720d11da4674bdbc2a660a5a9d6c6684904b1ed274885b482b62f42806b87df8c1", "HASH_MPIN_ID_HEX": "cbb4e12e24119c0c16b6007979d5fdf08b7eab47bbc4638bc69057d2ce8c12ff", "TIME_PERMIT": "041a412f1d3b0151cdace6a543dd9cc1c09a666f3fa51ff88b9a9fd2468ebca2bd0735a2c9e0d9f08c73eef80e48e5a8dcda263332de006f1de7cb191c538d6247", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223366623333646366666533333836383035613337316335306334333934663631406365727469766f782e636f6d222c202273616c74223a202262373134343361616539623366363136227d", "TOKEN": "040ad9e57a0d0bb11debd13ea958b161e3bb151edab8e5faf96b9b5da9e7e09b620a1e74717364a1cd6b957fd0ba28437c6bb59134d569d39a74aa463a0f9e167d", "U": "04102a98d8f717cfd6978a731694a5c6c192bb439262ca66fbae313ab6a186e5d713b1eba50804e227a15a45902a4509c8324293c5d873fe4307fa662d146187c6", "SERVER_OUTPUT": -19, "Y": "196df456ff62a104e161ed1c4d71896fb299278cdfd7acebc63f4745b53126c9", "X": "0119bea99ba3cea76964e2faea34045a1d75f3ee514dfaf242433a49700b55d9", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"3fb33dcffe3386805a371c50c4394f61@certivox.com\", \"salt\": \"b71443aae9b3f616\"}", "test_no": 130, "UT": "04006ecf6110ec27f87707b4b68af34830ce8191f7f1e354989379100a0c2726ca03fcf06c764d3d1ce472bbae60575a1c072777ed9c081b53a2af99e3fa5c3988", "MS2": "1e9c3935a24f2bee033f489aa94652234a4d7fa2185ac59c5e98c90d7627383b", "MS1": "0a30ebf12ed3434ec57a2c28939b031c42818e28ade4cc6c34fef25a9afce6f9", "CLIENT_SECRET": "041318cb4b93c264aeb0791878bf85a3d852debaa42c4d1d63594da3f1b525a249052643919484fde9b8335dc932832cebf04feca379cf0200bcaf6edb392bff4c"}, {"TimeValue": 1437055596, "SS1": "10bbb2b018c35ac53f856c9412f735251011b38060655456218f45f6e91f4cb8021a1748f19e74113168601eb17e88de49f4a2a88ddf94a9b2f0c1c70cf7cd2d0932aafffdc6b123a70d37283e1b1553d27f9ba86a64ef11de3562df94a5d3951745e58cfd2cbf117a0885bff45194b1981a5fcd0cfab2515e9714434857235a", "SS2": "0f1c172351ec30d875b323f5221982479d500ae7f098b7f0fa18d7225422eed8118955e38cff4a200e85046d801ae25585d0e3f249e2be6d8557d902af9c800d20d6c92f309a3f73044323c241b25ad0df085d6bdbc49e7a240403d3c650994e139e469e51fd0f4c2b7c6412ed9ece4c26ea5d651c0947d1df24e3036b61a1d5", "DATE": 16632, "PIN2": 7556, "PIN1": 7557, "SERVER_SECRET": "19a4b4a116b49ea674ae2a2cc4d20aa0346548a355e8ecf0f795492c5f3dcbf221ff3d204b6d138bcbe97535f3f275eb8113a21b19f259ff993cfc1c99747ec60f421914c8edfd590959f53be62331cd6cb7be0a3009003c046d69d0b97c0eb7011da36c591bd0e3a92011437fd9b7b01e58f11d2bea365006389eca6fa9d748", "SEC": "041fd16bc0397a67728fac5429e0de2aecbf5c5fe7fdfd448a7f629ab85d22f952163dec08314499dd95f10a785fff3447dc2173ae95c2955b1b1b824ef79c0c4f", "TP2": "0401fccf9b2a51b460f6c8740397c213b9ae95d781277f4431753f170749dd88231c0a3f9ff507e06138b752d036bfe0a9e63a659ba0b295097e95d50d5e111c09", "TP1": "0404754711af8c0cfe05f67e98f89bdb76c9909a7beae835de166f71afc0355d622212ddb78ecee639ead4f6bf3d8c462bf007dd2cade9f8067bb7ca706d6ecb0b", "CS1": "0412693ae702dea1c656d5bf0a75abd2edf79195adaefd4ce434e2010e0f5afeea1c47fae73f138c668775c0121a8bda50c9cf02d1f23a05bdd780ad93e7a55457", "CS2": "040188a92c0a8bba32536d77083ddefeb2c295758f5545f258f6e96841060ab995010918dde0c49c0c4e3aeddf4df981defa0ad4859a34dd36e99220ba57871c86", "HASH_MPIN_ID_HEX": "0705cce71f06ab34d1752cf66e1f034fd23368b3b38312c62064fdb935069766", "TIME_PERMIT": "041720f95c6bccc00cac06ce4b12c9d342432f51da4986e2bfbd4bd68641d3e5ec108b0db7617334a662be58aafec882ee33bb7bdddd47aee0cdf0cc42027ab910", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223763313730623734633964383665376531353364623135393837393761313735406365727469766f782e636f6d222c202273616c74223a202230626138663161643231653630336163227d", "TOKEN": "040390497b24dd244399b9a0d53bba98d4bb283072150e96fefe7ba43524a2555e12568a9b2bbbb3745b8edbf1add4c738d43a36e5e4aaf2bd704dd7361d746c6e", "U": "04145677bd7077a4badee44757ee0da4d3ba2c21f9ab8866f1b159ccdc14200cbb206ad01185a104580b18892f7270258301a0a5d16737595d7e882676f58c9f30", "SERVER_OUTPUT": -19, "Y": "1ee086e8a556a0c5db6c49c163853bead139226fc2570c5bd0216ba6279f008d", "X": "144562e1603d24343d7e4773a4cb31c46c03eeb6190719d4fa902fd1da11d493", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"7c170b74c9d86e7e153db1598797a175@certivox.com\", \"salt\": \"0ba8f1ad21e603ac\"}", "test_no": 131, "UT": "040424e9ff98eb8ffce620a7081ec345b8e3862c77651209d55c0da7f8e722f6e4004003920045a895ed0df26f26d3d84ba76d36151411bdbaca4fe4e469694499", "MS2": "1dd459edfaae29836bf7d0a1e2555c87e366b35919595c9879137e9f3f93151a", "MS1": "21147f08e437baa1091e98a6e7c773019c10524db2c944befb34d4b962bbe732", "CLIENT_SECRET": "04184aecd1aa94845b709d4868ebcc54b94be09e96f4cd317bd319c156e2ec23a91e5d7abc21151d415594e6c13f214a477518a28e9eb2f83c174b76975ffcc48d"}, {"TimeValue": 1437055596, "SS1": "17351f926d3642cdd5c206023a588d4a0debb48d8a936a9a0474c23d3960bce9083088401743f56dced4dedd7dd6bbb72d79b5665901392e388acc7bd859483e04eb9da3c4bf4b183a3f5e1a625cb9c4f81bb98a1e34a76c735947670376dae620ad938490265d309a3c62eed7023eb9be7a54098872e9d7c87679bc308d9520", "SS2": "207a7a2320b54668120cff5942895e9613b44e698d370f268bf4ba6592c707c610119f85412e50a108db5cf00ffd351aa1d4bfbfa84893769e2733d64b504c871b28ccd3956320211c179d07cbc4bd265e6b2aaeffb3852efd2d9aa1f055e6151a1394dbf94a9632fd40437255cd9abc5a88ee115cfc57af431848fed50b8e35", "DATE": 16632, "PIN2": 3856, "PIN1": 3857, "SERVER_SECRET": "20b56e03c827caf78b7f0082ca0197740adfd7def6ec7159b68d8c5e70311e03132e759ec30ed71628af3f038bb1ae13dd1a68aa65c05f5fae35f7ad86fba19305194b7d713fa77c158533d03a26ddded8971a70a14eb5f15915c26b061b86c31cf2e37ff757cb74358d0f6103463e3fbd0f49fa4ebe55841b1a2ed7237a822e", "SEC": "0411486e52d37dfeb72172abf42a44b8f0d6ec099c84480969181312eab9908a0712c3ae6893ee1336a6cda84520903f4988d017eb8b4993eca73aec30d381889d", "TP2": "041579565ba491e87564993e7fd16641871a255e98fac3d65903fb232e57db56b615150a64d07ab45c4266a4f5da9218f550f13479b671a7b4b3ad8d9dca07420d", "TP1": "0405f71d35f9891392f79df4576b74048d824e535699582e2b02434cc339ff9d96146a36110129ca917443997e2c48d73a64374ed6cd18323ac24896be82373065", "CS1": "040404564b1130488d1b2ca1a60e305f847fcc93d7482baf7ac65dbbc2e76985a8215fb7c26f2d42f608ddea38f300b3e23e182cd1dfbc75b4cf5099ba7446feba", "CS2": "0406efc6e497e143871a4fdf684ea991e6fb2480195788bcac7dddf04c3374d08d219af0dc1eaa5d59edffeac26aba47ac8328d1232f5dd5e88ec6805712e977dc", "HASH_MPIN_ID_HEX": "2319471c4e5f61675e19eac04aa4ac1fde62186e841ad7f1d4525fad7de63847", "TIME_PERMIT": "040648a98be966c0eef4c84aa4e5c3848107c69feb5a36400c6db17a3024a3e16707d2142df9c5f459f7cf2d8bc90d45a91f4afad94083493af15b84cc078bd9f8", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20226565326530326435396436643039366432303962323762356337623761356437406365727469766f782e636f6d222c202273616c74223a202235316636386237336561376166306637227d", "TOKEN": "040d430a6496a695d879c88dd96f50eb7f5a51c78da049f18c743bdfd14e37958b06f69d688e3a75e41882f027590dc3f6ffcbf2c17aa9d1e6e5c5971efec17ef9", "U": "04209fe9133f924f3b7e00d8e228b284489dc43f56a39b757f05c3cfcbb0c7fe27054891a192d257d2bcd022e26e368002ad287ea2b8327d698d15dba4cfe46135", "SERVER_OUTPUT": -19, "Y": "20aa779980d2878820e4bde760fd90b673e94c8550e896717e9c0aeba63c437e", "X": "0642c6a6c4c33761fc13c03b5b6bf6d38b8b341c4fdd35c4e0837a743f834763", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"ee2e02d59d6d096d209b27b5c7b7a5d7@certivox.com\", \"salt\": \"51f68b73ea7af0f7\"}", "test_no": 132, "UT": "04169e0b5732f20d417f2d273b7eb533565fcf88f9fc991a4e180b8ce42a7b7e5c1d07573661e746c3337b2e91c6aa5261a87cbe3e624390ab76f3d3a5570e30dc", "MS2": "0745409497fc9fa74ce409d1facdd55b63b976f92329c65892404b7e1ce37296", "MS1": "22d391b1eb38057a1a7b80bfc8eee41ed01d00f992a92650ddd74ad48714c06a", "CLIENT_SECRET": "0401fc4c0871012ccba9f92bd2794027cc3745db56a66976875ad87bf9d501f42803cfec755a33fa851411bb1d11b65994a133822c069f5d1fb32e5fd275c2df65"}, {"TimeValue": 1437055596, "SS1": "225f926d09082525a0ca031e164e335b1391f60525756ae4942b9402c58d3ffc0f8e972cfa8a36b96402656dd941220360252017a9f8968f32198fb5f7408f00078ee9b898a75d5f6a5fcd5d40d54f04d0dfe0ccbac69af4e8e5c70d714352a400455cdb1eb689f6b950263688aae048610dd8eac566d151605c0b271ca4a107", "SS2": "0e66e11c3227996871b24546b63e7275be52702f558dcbe67c137c54ed9cfbce0ebca46099e0a0218a05abd6a83c173cc1ac420e04a7a59bb5e07d73159570160d7b2e1165bc7245010fcac43541c808986fed205ae32de5e766dfa1a68c1e95087ffd84b2c4de6df6cf491cf822ac80176377c08d755f0179bff902e1c4031e", "DATE": 16632, "PIN2": 6990, "PIN1": 6991, "SERVER_SECRET": "0b4e5b1c2269951bc04b1620709e4f5ff49ea07ebe7454cb422297fabea2f6a2052d3c921d8977738e2cac7200962c27050b6e7c2d12adec5b7d08ca5964eb1f12fe87a0c3c6608ac7e89a2715d1ee8580f9630b9dc1418d390753c786de2a1e019d793c6f0e8309724fcf5d63098b3fdbcb6a5ea2e98130f891670e4d6d2c97", "SEC": "041756b21117681e4814fc7fcfb557b16c345f91f331eaf6177f76fa9eef67af7e20cfa332ff447337c747659164f8259d90564631b003e6985bc8f3adc6bea082", "TP2": "04011a5826d05bad778f6b7e2b81e8cb212ef39eee44a6493fdfabfa20e64de01d1f7b566d8a715a9c9ade84193b8c6eac056f162964c45f6b8cefc1403f4deddf", "TP1": "04051bd9d1022569c4bdb86346b5abd549740cea640d169c2bc7b4e76a74fbc6fc0fdaf6ce8877603a4e8c29781eb761553f4e042b65061bd50b91ae9514647909", "CS1": "040740eba333c5887e0b6570933aaa2b7e075e3fa5ca8bdb97e6abc6c4fd0bfb430adb5fa8cbc152abb7f41d85aed3c45af134703cd52d518fd780a1ceff0a9b9b", "CS2": "0406e2bcf37c019a9b324166db3bc0ffc7b8b5a190d71cb03c9fc806ea34873373064a23456cd98919d46edcc40d409006f22c1baac33accf0cc2206b14d56e419", "HASH_MPIN_ID_HEX": "4c4da2190a642dc3f880e36e44d45f6ce71f134b96048479d205e40081835693", "TIME_PERMIT": "04157e6c52c8994bd2d33b4ae80d781fdd2b9678bdf177cb576687b658a86f46450c04c78d2002da55baa74023db4f8875978287581e06f51668c363786dceae4c", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223265643334356335383362656137303966373933316531303864396662643530406365727469766f782e636f6d222c202273616c74223a202230356234353132353935643530323132227d", "TOKEN": "0419412d250fe985aa466837abdb190de46575e6d67cebee662e8fbd9d74545f941b013a32cb1b1a1b3f9ca5e045848ad50032487289a3fae4a3bd4f3ef8d70934", "U": "041014dfc9364384b8ad40fb3ccd49b72810c3e41617eeaafd6179ff9d72ebfbc022b2cb01935a7ad9a8e637c280d162107a407981b50bc4ec34fa9d3cf1e4ce3b", "SERVER_OUTPUT": -19, "Y": "199c70a2753c5b4e536ce28d9c921fd78ea4756c95bfc0683ae99657f82f3529", "X": "01dfaf115e3578120be69f6f95d24b8495aff02e11e75cf3dd2327b8f740814a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"2ed345c583bea709f7931e108d9fbd50@certivox.com\", \"salt\": \"05b4512595d50212\"}", "test_no": 133, "UT": "0420f7147ecbedc641cd66f4b97f78d06795aa0948a0dd0afbb5b7625da5a5b8f0220a7cd33a08e35eb9005c3a40be084325bd2b9ae71c68a3794fc704012d6d85", "MS2": "221071e6425762e63cad9acee2c092599c6a72ee75f830d3b4c270286b02efb4", "MS1": "04b11a81cc023301be80174cf42a111d7a8e1ff2218c14bed4a8c1cef572ca04", "CLIENT_SECRET": "041ff909f624740299de7c33d922d80f69391272e0e08596a680becdc766b94e0a04d5a8a1641f47e7992ea6842822998ffa445f7f543a7685c5c712f54567a7c3"}, {"TimeValue": 1437055596, "SS1": "147be61b6cb9fe9fe8af58b52431b3f48be6b9bd26a9c755a42f3837cc09078722d48e2a4ac8496e02d043a5d93c86664947dd8e0c4e221517d5707cea2681b2233c49f3d0ad3786a7398be96484d20f3923b7cedaacff2845d7131385f6f69917a937047d323aacd87d6dde30c385fb1ead10f49236af3d2364e572541997eb", "SS2": "0518e96b1aa704521e2a5cb73a3d92c6ec481d7b1665b7c2b1eb455197268e93110e0c88f7982ff17b402847260bdbf19adb736937d2656e83afc1ba5ea740b504ed041431cebdd98d90986ec440c78d74f951b76f46d1238916df4f621cbc90060ac811e2b475cddbd8f4b3ab10742456763f872364dd41ef69008cb5f740af", "DATE": 16632, "PIN2": 3342, "PIN1": 3343, "SERVER_SECRET": "0c7ff8e2a412c9c2a740ddd30dd7010f56d74a49abc5d6b549ace9b08008621002f2e89a14723a11231096050868245ff59f4db4a2b73838a361fec85c5c70b51f9b4f5df0493a976273939942d49b6f7257a954ddc1162c394f2c24c3e09b1a2064f2533ba5a4b87501161c0d5c619574b5ae93bfbb2cbecf714f990636599a", "SEC": "040f12200b1810b33dee355348f5cac41b3ac2e093aa5fbf51324ca172698499630f4d52ed6bd269fc7ade71006411828f2718602ac33bf9f9ea56520a138628de", "TP2": "0405b3ecbdcc61153d30caca3ed5fa07aa4add4bc5b16a9d72ccbebcdef536e415029265af7d3f672d129b5b436c760b260452b36500da8038fa44820c2a993a43", "TP1": "0415faf92fa81ebcecc30e1f39e2dad1af07e8b1f2408d9aa4369202ccbcded81b200ae729bf39e66c3de680a26cb8fa07ddb0fa11a0f8fa3e37035670f3c20227", "CS1": "040858f473029c7db76196e92bcdf4a608e5b8549d6398f514630b81e1a56e0e9a1906039b849cbb6a0876b0671154306856cf6cd76ab00282806dad11215a52da", "CS2": "0406a2a3f8edd50bc41b6ff9c66dc818fc09629f0e1824add499de5fd65bad166f0962d8b063efc14c7e20c1f3d3229bca86ac72b5ac851e3a62623f1389ed152c", "HASH_MPIN_ID_HEX": "e90bcc87803308da38c75fb471776da121851387d640573744913eb58435a088", "TIME_PERMIT": "0406589a8875dfa505b3ba5282bebba852ffc3bdcf39fd5cee7811f69d7b57c32b00fa4d3cfd116d8ec1787b30d00e82d3c55e1d4f2e82eb0a139685e7dce18acc", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20226431643766343137613362323138633739303438386664313937323433353835406365727469766f782e636f6d222c202273616c74223a202261373336366139633539303666626536227d", "TOKEN": "040daf8369ea70091792cef13e20a950c51df2233da11508c5cc819d2ea0b57b10238b6ed8941dc265a6bc98c40afe7db46a638034aa4f017809ce664cd10f8711", "U": "040f7683000e2993e709748e1a0e1166ff4df080d41d24b4bbbbcc24ae4e022d3c22abc47aecc9d3a8cde860daaf52bf171c9bf2d23e1af818ee01af812679946e", "SERVER_OUTPUT": -19, "Y": "17967d0527beb9f5a81fd0fc35a1e0bf088b1c8844c2fa0f990ee98c7c8caa03", "X": "1623fdf20c4f32076221724f229228fe7a763f12ac52dfcb9266249799af973e", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"d1d7f417a3b218c790488fd197243585@certivox.com\", \"salt\": \"a7366a9c5906fbe6\"}", "test_no": 134, "UT": "0417cbe6f2b0cbb4d009b67b23d5bbe80503c7dc10ce3810bba2390d6d242d678b17a6ff441068a4dc0d21d4b2cd2387f48959c62b7be7219f67b874bb723adbbc", "MS2": "1ccf040ba9f4bb9222da8719827c1e292a21a7793b18cea137481915f5f2dd15", "MS1": "022fbcef0a021411c5cdcd7030ed9e7eea4182f77f6621028c6f7acfd308ed94", "CLIENT_SECRET": "04006433be0bf708bf332df8e966ca6fca85382d92d4a8304148d4640d297aac2e0273bf6d91f2a493bf0c58ce6ab3fadb867929bef73c8a1dfeca4751362bca87"}, {"TimeValue": 1437055596, "SS1": "212951fbf4ba971e2d24f7902a40786c46211b3108540bbd53273b193aa03e1a222d4e841128b7ea387e2003c5570e9981e1543d587bb03c023b7675bd40b23715d18c64239e5abfbb5afd48b859e6cdb0f94ca81294d504f2e26cd72253a00a02185fcd8c95fa40e868f5813cb6f51e2315db0480b37c762e25818d7c668fba", "SS2": "08ce3bc369de4cabb8e42c2921139eb8ea4237b824a4d94429c8e4e4d7e969991298d457931b7d6941ba91fc6ec344923ed0d93372e70eef602c9b8da78e6d89100cc7b05401752dca6c578cae716e86ec08b98f36d3d011dfdd53ae3df54be203243f64badf2e75c36cfcfb4d1b7445c45572ad0e4e76dea60026cfc460aeaf", "DATE": 16632, "PIN2": 7524, "PIN1": 7525, "SERVER_SECRET": "0783899e9b08c3069001b73c786584bdc5bff302288b5c06a25c122f59fdb6af13c5f2476f1740be9198bef6c8bb38d503f1c0a0c34ee357ca37dde4c3d9422001e0c2f180e87ae1c804e97ade849fbca591d4322b85678663172994cdcd93c5198944528b83641ea93e377f82ece582dc54432aae645071670f91371015b14c", "SEC": "040a3e5998431313bcce80908e26c36596cccc1b7aa7203d6c177f6f0a6f5588821863059e73818ec73a6263bdcf6b9c1e92b306c205079fb02ad6a58fa5feef7a", "TP2": "0415700d562282e6ad787266438ad54f487cd60816c53ae3d62061eb9bc92e3ae301e3c211dc64c788b4f4b82b490d2d9621a84bcd45fea338c3875c4927725610", "TP1": "0421ac0cf5fdadcfafeea005d0b792419076ee20318462641b88af9914c6e659bc0762c198f9bd2679c3c7c3a3dddd0ad46ef392210acdc1cb11c57395b10d0325", "CS1": "042284a290fce37857370b3b7f1aeecb6b2520714d6705dfc08c137dcef57db49d0be3e5e2a501db96659b536f77601a3ea608aaf00849200efaa1beb499483c6c", "CS2": "0419e647fb4a5061391b1ebe617457ba507327419c9a9bd96390a01de4e88871f517f5029b66432743d7079ccdf95d6492f2ce9ace27a7c36c7f6f1e2524741db9", "HASH_MPIN_ID_HEX": "ad0ded9abff8aa6b6f1aeb6360d6e0861ae3ccc39d411303706d30bd5ef8ae23", "TIME_PERMIT": "040fce5c369086a54bec2b954b4cc0dcdab17fffa8516f8501d3a7fb51611c513b18b3d6372e913925482462fd6bae822e6b4cfa596953be5e40207475ea221c6d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223239646261376339313136386665623165323664616635393531366363343434406365727469766f782e636f6d222c202273616c74223a202239396464303962303734363337316464227d", "TOKEN": "041fe738a786d72266e375a87e17a8a55f2ba098dbbbc8bd7512426185e50a2811096baad24fbeb0b959ee47a43e1fb751d7a3b08e0b06e8567785f28daed8f60e", "U": "040037d4c7f026ed4ec80e96795d594e58120dc2fc54a514f186e52fd7c343a29b157f35ee91b57bbcfd17c184d5c180b6c98a065a954f6512b63a54b4d0b05a71", "SERVER_OUTPUT": -19, "Y": "0cfeb2edb8b4cd304d8b371861ba658897c50c7c5fc9cca0612848a910b63593", "X": "1e0b4e5bb9a0af8e92944bd5711ec3fe0ae105ab56e7788929df59332c437070", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"29dba7c91168feb1e26daf59516cc444@certivox.com\", \"salt\": \"99dd09b0746371dd\"}", "test_no": 135, "UT": "0411d1dc8028c86f22c04f10334d182c7b99bf957847a75835264450c2d93468e517b13054b559410c86dd81e7ef354723e4b8e04144f39d86b44a4a2a7e325a4e", "MS2": "139abcab8cf88911af19eb16422aa89f5aa65e5dd547ba1d3e8efa1079d4e28c", "MS1": "124d28c78cdce10610d99a0c64c2299d3c73e17ee9b8a7602523b5550a1aaf8a", "CLIENT_SECRET": "041517c8d93cdbc293ddc09b96485f5793ea1e4c21fe3e585532e76978a400f5340a49e85331d1c28687e9ace7e8d4a74883e857b68a8f2af2114be9add983c657"}, {"TimeValue": 1437055596, "SS1": "1cbb09629d10b909dd2fee44b34f2a6cdbb01bcb1fc7610bd92ec020721709b60a70f5a26516b9f705cd4fd62534aa5d1e3f9e9d6aaf9bd819ca5b0d430dcfb62201fcf30ac5a570a4816cf022fd67b17ef521ba093e06317c9f424b30a2ce7615cf32c6e3d651e2c0160bdd171725b1cefd29702aa9770f2ad097680a1c2dff", "SS2": "09782b6e04f0b33327f8a4a7ca7e0635005b9623129858ed8798c339d0cb0b381314df242599fc46c3f239d7291a714d46c68c641e933ddef5d2572daa9b0f4811521042bb790f8d5115aaf5472b4b79d28bcbbbb654c5f45371b9896c9394d316e37188df862a2bfd07529e1bca04bd2d5ab9177f937a243a31ae698d696d84", "DATE": 16632, "PIN2": 4109, "PIN1": 4110, "SERVER_SECRET": "0cf25682440cf033e9f6058c2f8cbd6f7601a9f32e12142078d9178751e9a1541ea01e1c36fcf5606c31eaacbe2be3e3340e5739ad36dff45a3d18175c6399800f485076d8e5f61afac7007a538a066d4b3d50f7e7709e7225c858c495a3d9c0013c4ad69b29af11645cc3dfa1e4d5b26367cc40e889fb620ad0537735497e6a", "SEC": "041104f476ec525f9d0936535755aab4b1485cbd401b06f0c35c352a0821e33e6700e42dfbc1aacbe9ef7dd524a561e4856d549154f7355b20b3d1da3b94a44f94", "TP2": "0408e010fc086373344a3b95900e63d9fe30bb353f2fa4027f18809d7dbfde9de220548d6c20d677e2bcdbcaf3527236ce8315b24fb2d4903fb3d7adcda18660f6", "TP1": "041f639b6af059ad93e76027b4a287b0b398b9107d3b262b69fc7b29a980656870129ca702f0cd91d7289e3eedffb744a798e7218acb6eb818481d9ed3ab407847", "CS1": "0412eda48028b73c0fe7ec7926151fa2505ad417680fd05ea08f3de74091c468260b406b239a57e1d647daaf2f73751ed3ff5640841fd0c61b54806649151d6c3c", "CS2": "0404d8195d7d2162c6e790aabe2a7c866149513e3a708da887f8c10ebe3e33299e12232dd81cc57a4e7160aa8a410791e7e116a1f3c67baddac4553c13e378a7e9", "HASH_MPIN_ID_HEX": "ad58663f3d999959a293e63553ce382089d375c27db76ba6774f466be19223b1", "TIME_PERMIT": "0415b687c791c919f17d5ab48d1665ead56b16eed140453a4b2fc71747b90cded21d700bd450bf112653fe25ddf8b1ded53281f221db95f8b2e986c8919de2b104", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223832363237656536396561383764376232316533363465353330333530366139406365727469766f782e636f6d222c202273616c74223a202265323130316530666633393661316638227d", "TOKEN": "041da27e28a90743d51572704a0d2cc6cb0c2fbf22fa050ca25819382f45d1694b204e1ad1c81278b887c21ebe19fe3dba0d76da4a1ca43d090d942ed7bd211fb7", "U": "040bd02b2bc76ef35a0616e3c4c31be91a11ea52a7911b839091e24d715b0e90a002ca5d2645e93305c20bf9718b5b1e7aa31a2a46b51228d1cccf42dbdb4cad6a", "SERVER_OUTPUT": -19, "Y": "0eb1f3d70bd58af1dee210a038a78ff74c3e3a7bfb5c35e5956d13f707426d55", "X": "0c1747b4b10fe8b29a798284124f3e34cc53ad95f3d899f35b130657157eb0f7", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"82627ee69ea87d7b21e364e5303506a9@certivox.com\", \"salt\": \"e2101e0ff396a1f8\"}", "test_no": 136, "UT": "041fc3116ce4bfb058353577126e25af4427d7f0c1edd05fd0bfdbe79fcc3059010fa794933fc19fe4a09b49631c9eae720759646b59edebc308e76b6bac80336b", "MS2": "07fb9cd4fb227418c1a486848b04b41fb3c96712a0297ea617a9dba9979cd8c0", "MS1": "0e9cb04ffe836bef974dc8681fbea1c61f50e9aa43e9a803a2f79a35e7e16ee3", "CLIENT_SECRET": "040a54dda7b5d1be39f9574f2ca13463410845b8c5bb798d8d1b814f3381b1cddb18073fe828786c0a4e8f8419faae5a99b1ff34815f4a8b4c129e487f371dda5b"}, {"TimeValue": 1437055596, "SS1": "16d985475b42d39d97c5a59160083bbd73ff0bf377f33bc4d8dcab11a84164ea02c5de7292ae3c541fc9add41652740ba67707171b52269f1da2a95155c0a353049036e2ede01b4a06f3647077a9134ba0b7acb16193198528abcd29f9067d9808071a1df1bf71a28cd79e6216548774add261d07c34a7875e8d68c765537b3b", "SS2": "1531070f13c0dd4eb33f55dffc1c304c8169ad474eef356692b1f3a4600087210731ff2b3d20392e69812ac6b0d2848a87ddb723096e728af1484dc4006def401c361de2e730dadb92acbe44079de93e29f3baf2963b1af62507a271ed95698311e1cafea24530ee273880347c32db23413ee7d323a0455fb0650bac5af10a05", "DATE": 16632, "PIN2": 9391, "PIN1": 9392, "SERVER_SECRET": "2038f70e2a0b2da625c044ce39bbf45b6ab213410dc1d1896d7143467b47486a20b47ad1a5132891b5c70c1e843ac616ec825da3ebdc8d6b42bbe596397651d01bcf45d6b16c62e2139b045a73d3be0fb96fa5ec2d5b857754dbd86c122b13660dbb226ba87b009768bf2dc39528323e1a8067b28deca84f5d6a74d9d7b9ff10", "SEC": "0415f5566faab272850ecb361eeb3939b80b3132b3045e408d9ce02da2fc3de2571dc7fb6086250aaa06534360606478b9a63303687b17553807b6e4164d7b01b7", "TP2": "0406e98a6a3a2b8b1799c919274cb7ccdaf7d188bbbd3b96352b57c9207ebc1dac18c5e19dccd901c25fb8b5084fe213ca4ab755d3363786ca74032f1a5505602b", "TP1": "040e672a2a8155d6dec71f72a61da2d82c4e9fa7f0ced27218707111eb54ff9b3a23677b9518f8fd0135f695bef3dd77cd277c67ec2b965a6cee989a927db63f8b", "CS1": "0404c41ff45283786f3677e0ca6207022e9742e0a8af18f18c1ca648e1db79451f011707dc3b3e3c664c95dc9809887c8a5f3072388863633b2858d25cb4a1eb6a", "CS2": "040ccc55c8b0377a637801e68bffa1d1a6852a4b652b9f1adb6d9b55c1f34d0e5722067f932d312a5ba95f14bb67b67392e82eee2b8b4c4140d51d6d397f5ff9c2", "HASH_MPIN_ID_HEX": "7a482142570ee366c5b1fe93a1423dfe94c6546e2be10e76ebd0aa3eca7db967", "TIME_PERMIT": "04198e6f6abc7fedaa37a0f2217b04b97fcdd60ca7ade12aa7bba0eb0e4ea8c6780ba6493f8c68ba9226d7272fa0edc8bb25a46156eca85a1ad42b56b4a93a0df7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20226562336235363437386362313130373366633566353734393162316432663533406365727469766f782e636f6d222c202273616c74223a202236663662343035323361346662383866227d", "TOKEN": "04057ed04672e7b5624ffc4dde2d4d59d97760090a2d7776817b15c24b962ed72a0e4a4b1c6f8786f86523df7a183edee6627e93d93a0962eb2031969a4649fa46", "U": "042146838fe90adf177692f2bc42df309e4ff75954f897fa8b10a6ac142840751e1984d905bfdc0191fb983b5ca16c6c6f9ba7c616446bf3eea50d777352049216", "SERVER_OUTPUT": -19, "Y": "10c6bf640f71c2dd4a1d7e0433c79dbb499688cc5f1970368d71e111bdbb2b36", "X": "167ca46abd5ddf6ed63fab1b663b5c35f8c65afe42704ed5c90c5b81c07937c3", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"eb3b56478cb11073fc5f57491b1d2f53@certivox.com\", \"salt\": \"6f6b40523a4fb88f\"}", "test_no": 137, "UT": "0413a450b353ce8551385ef33f601b4f3599c10dde68025a440280a995684f53c100284a7c0a1aa6b2fcdbef5429281586efedc8af9eeb1023d6dba2ec14734a83", "MS2": "03247cc1401b0ed818a8504bc3aada0e8be887f690814e0be665af29425c4a12", "MS1": "098ceb8755581a8e837b9be92e140f362d83ac83f15e1742ed869b0708668c9c", "CLIENT_SECRET": "0412507684cb18efd66053711bc891e3046cb5cbc75a8e125291b56aecf12967f819ecd7a8dda226f229fbc08c127d29f57ad8b7b1c8580f4bf76c22403050f2a6"}, {"TimeValue": 1437055596, "SS1": "1c58ad31e5d6a61715699edba01323b1ec60cb9cb69725cd99aec61a1bafddaf1a0df7808ca7ea977a86267afaafd7533c2bcb3ee3ba5c407e584a0eb89fa28a08579aad7e31c3c67f1af1eb23a01c76b27a034994cd76b8a8075597af541f5f0fd1882e62d5385c066985117531cfd392bf678840006ca364cc52502728dbaa", "SS2": "1c7dbfb3c234ccd2c7b137ad253b0e6c4604f8432afb2a540eb3bf7f30a856780f8c109a080f3402f81b9dbd06778e59b2f15514eaac357c5b595d2b6e4ab7f504b2f19db3b0f35fd3c438ec6ea5508c879bf7bbc6d98b118c296f7a362813dd138816842382a8717f6bfc813d9b0ecdef780a83ae9fb8fc2cdc4645732f140b", "DATE": 16632, "PIN2": 9340, "PIN1": 9341, "SERVER_SECRET": "0f747782b81ffe1da49114d6c4e6b417fad4e9783105b537d5bb427641e889701a4c8a7972b41d6b6a5ea2d2fb3302b4aaebc24edcefb358a800652fb0124f1f1b8ff9b9683d67ba5fcecc43d2728801562d3819cd3607ec9da438ce3a42278a1c26166eafacffd8132b8f7eaed7c04f53a5eec032695faa329fd401758ee4b8", "SEC": "0409a2c9414c010027fcd6220272c3c7bab6a67cf81d9380ebdda35e7cfcbd7b291e72ac92f22c529c7c7cb4afab4767a9c9d7b0e666dbaec70e5ece6696737f15", "TP2": "041c69ff33e0306044cf8a149744199d827218c54a8ad7f49faa1d752b6aa20e1d1d27cce2858763943a0d3fe4337ac220ecdf18a363f98bee085766d108e9b812", "TP1": "0407b639e0ac574ed0cdeef9cf81d46117ea9761d629ae02693d2ac6d2463ad70910c56b796922439927a65ca08d69e6e3debdd5db90c8281cb136bb952956cec1", "CS1": "04122c38b33fa0b78fa868f03716c7fa10747aea89903b3af08cf2080b436512381aa01b931b14bc66f4a11ac8077d4e96e9c2b3a1c457b8d8bb6b6813cef8cedf", "CS2": "040210f3f060903854c5d9070107b4a54c3febd008853498bcbbd6c4390861a6331c5a72656dffc49ae51f0e8ebdd78a9d3d5bea0d729502b7cb643033d0360ff2", "HASH_MPIN_ID_HEX": "9caaf642aa085039dffdcd613f9b95eaebb1efb9a6b92868263a6dc7270cb9cd", "TIME_PERMIT": "0410f3724325d304b18100c6eb2c39e55a8d5393638f040af018dadbb0dc80481a2333cd979d732d597e9ebe4de75fe50908a84cb44a28805e3adbc1d7491f2ac4", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20226230343565386535336637393131343233613464666265376535636630363164406365727469766f782e636f6d222c202273616c74223a202235346462303636616134666564323131227d", "TOKEN": "040c729a3c2b4734c0a6cf84d02cf1bad16dff20a318cde194aed13ee2ec6f25ce117c164839e34d2d0102f337b84496c410f51acc687ccfd4a998184045b153af", "U": "040b5e3ff259f3167623c543e2790cb1a1a4f753877058397e6bbdf6d09d11ba71181acbf35c3e51038d18eff4f17ae800334eb288670104bc90441416518a2dd9", "SERVER_OUTPUT": -19, "Y": "0da0be5f4c9676b6724900026bc4aa66a319c9ec0e016ed331179eb073590a43", "X": "05dc3d1437d1df2607b2c7e5c342678b063b3db60427e8ffa8e255a78206e075", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"b045e8e53f7911423a4dfbe7e5cf061d@certivox.com\", \"salt\": \"54db066aa4fed211\"}", "test_no": 138, "UT": "04117267beb32d1a059cbcfed6cb998413ae9ff9343e396e44d7a8904a9020a113024680aeeddbd195fb7cb0e8f309aebfbe97b84af4dad8ab2813ede8b0a35e8f", "MS2": "02a73b00bed65e5b3491031183c9916890efd7c7e32f50b0aada6ef3ef0144b1", "MS1": "18f709f3ce55f585486fd633d60ddd131b038763f430c069cbd8207e0fb59969", "CLIENT_SECRET": "04048acc7846a137f8af06190b5750b34dd0b0efa652ea4c0b379d382f5830ef6612ed7759b2723b278cd452d1564e7ca23369f7badaff2c041b9d1ce506ad17e0"}, {"TimeValue": 1437055596, "SS1": "1fbc8c193abf87c37ff79467a2d473429f4d65cca9b716abc1ad884bf4b8c4191b99275f87a98808bec3d305352e1db8a9d10495bf152a4ffa588976638278e109c463f96c282aa379ebcdb6890ef7f82fcdc69be28f9882509a5bf4d602df7521265a6db23dc544d80a1f7f305ea9c0714b0a30584382c5b563cbc97716a8b0", "SS2": "1862aae6a7695b12f958e44cae458461a70bdf9249902c74e51d6291361f6dcd1e24fb42c1bdf8c1ede42f13220167d81071a604122f8082fef10efdd010ca97196087a6fd8775f17369617f71e2837fa4fa8621d1aab6019348789d6c28ce7e0ebf1a82be2d160163973e011817e95ab31b5d18da0d1463d5aaf8f27489079b", "DATE": 16632, "PIN2": 4269, "PIN1": 4270, "SERVER_SECRET": "1d57665bde8a7e87c23d10dacbe36b4bef913f357bb2cc3c2382c3fd5930f3d204d2e15f62e0bce64f207c82443e8f4cb611a5de5a59e3e157366d36c849f392003a8164990546bbfa32266716f7e3feda8b355e5660189af84df735f59a2ba7047d3af0d9b59467d7f20f72f355d6d06b8f5ae4eb5ee16dc88380a60055c5d0", "SEC": "0419809c7dc06fd525e32fc1ab821752511c270f4f8e87b0cc38b33c885aa5055d178c86779dcccf0c07939b833715ba9337f2c5f8fd4b1b4dae35d2d053d8469d", "TP2": "0407985555bfc311d41ebf920f6ec22e7c6a459dc8b9add30b99ac91aaf4bde3c414583c0c51be4f56b1aac0789342a0c40ad2602afff221e68241797b8080cd04", "TP1": "041c2bfe70eb7cc2817e35d6c2a05c8601ad859c76070578978fd3a3cb04471b9422cea662ac1df553ee07aa72441242eb4926ecfedf37c43cfa778b813ce81770", "CS1": "041b3364e0b72b0c73cc51ff73506070ef2fca6d08359f9ff4db35394e24e5c21c1fe2c8562776d97edea51fba07d0ee2bf8e7baf01c4cde4f1b507abfc8e54bbb", "CS2": "0408f0de87bf3f602e1bd9f14508e43f9aeb5fedfe2538c49d582c1b55cbdff54b14326e7967a00c4c7a6e6a0cff370e70e2429678d9354e2ae7d4e6fa7c2ce8df", "HASH_MPIN_ID_HEX": "94e3f02198c18b6cd6bea3c71ad6e4ea615aaf1d0f948777b0d8e2711e22e4a2", "TIME_PERMIT": "040ad63113f9e92634b8d063844b5ebed2c95ebbb8d626e7ced53cdc619244d1d60f1ef894d4b72c69e7ad1710188267760604bd61d14520f289942912d4ad691a", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223461323532303762613139633730616335303465393231343066613630366666406365727469766f782e636f6d222c202273616c74223a202234323439303061333863666364363063227d", "TOKEN": "040917c5ffba0ac21860094fdba3948c8325ce0820a0d4db4b28cbb4625387630b197662fbbf46b1f6ce31bc69ab98a6a54792fd7167acb61f1b8b673a6b2a5d51", "U": "040154002d034a47b56526e063c64c2630a96e171558570c41653be539071e4dc6162e53aa78589139e3b7e4ee8ecae8213c2c19990c1687857abbfd37f927f474", "SERVER_OUTPUT": -19, "Y": "0a2b3640530b3d84c3b3b189bd52dfda5b41c1a108a1495cf73c0be0fdb0dbf4", "X": "1715550a390561ec9ebe8b0ec2a60005f2da21d8a8d55bbd674c725ece91b377", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"4a25207ba19c70ac504e92140fa606ff@certivox.com\", \"salt\": \"424900a38cfcd60c\"}", "test_no": 139, "UT": "040caba80dca136eba2cdf7ae94059e9959e967d9ccbb5c85baf7062afb337eab10eea628d95fd2debba916d6ba2e22981277916a8a0dae6aef8e7dc9badd9b049", "MS2": "0669f6c9866973ddad40211897f8f6808faef7ad4b97f933ed3740e678384c76", "MS1": "12deb9fa6b1cf00b96b41e7d7bccd8c7ae5ffbcff956ba5affa935bb3a8f5bde", "CLIENT_SECRET": "0410803563bf7baae27e37321285cefcdb6a84885f4e3f48cea6988090aa25b0130faf30f5019f0de8543866615066cc7b5819537b794e3cd5ba00593f457774dc"}, {"TimeValue": 1437055596, "SS1": "1c438a2cf1311a06efa3839b024745b19e6a74235dba9911dcb40c33384b7887147a7dd4318556f04558ba4b5bf24fa44c708c08370458857b0e95bca6b4e91b0663011bb0cf3cedcb92cc6f02390ed603eaf98ecdd07ceaa59faca42e7574151f1b3afca4c9f21bd713f23b066eb98460896ed821aa555f507a1e24912ec130", "SS2": "16902c324be3a4d8f683a1b6a03d433f3dadb49954c8a3792838d3d4c800a8f6211c0d36264f229dad3cace431a32d1e0aba88ca6babd1bb473bf017187cb4ce19c0eca38c3e4b93ddd4065df32bf755324aebd389001d9f12b6cb31f155936a04893433a04feb141442ca7e13c364dd1b5054a1d7b71b66b03010a2a2dd53c1", "DATE": 16632, "PIN2": 6106, "PIN1": 6107, "SERVER_SECRET": "018061807bd1dad8e214571c0688d4a8a842c20d66ddece1389b9f68b4d88aad0fd4ce1aaf93eddaede0ee08879768420c139b697c282260bf4344dfe717e6c619b3ec70d2b55258f7baa89a04ac3179a69bf6a1483d0a2ac7cace39eb71e54e0e7b25bf5938fd85ffedff352eda3236dda5c6ac893089542777761fea3f4e1c", "SEC": "04157190eb56f3d90acca1a2f7ffa235937156ff8cdec0ab7a1a1713d87a2df2d51f0e4d14090f64f99cd783607a77ff4982663851cc6c1b156b2b7aaede2b5e90", "TP2": "0411d7b8d5c9bd837f9617ad71ebe04187bed47b4f76d4c461ec681dac2d4bb4001f772698069fcbde2cceac946fb1dfd5a5ed0293546feeaab8efd5fc55786971", "TP1": "040a87e2f85e8acfef97f17f3631715ee2aa8b7e93b1c2e66ef33f4ca33db16fdb23305c508ccaf9384b3cba89adf4b1bc02558ba052a5633e522bb8cb6f9a4c25", "CS1": "040331a647393b7be5f0f2a3df1c7dd07e82d308452083ed9be97fa7b6154eda0803fd48ea4fc61759794b15e3f3b6db0051e24f7631a78558ef49d2a7003adb71", "CS2": "041a052aff4fbc492729a2610ed3b129fa783a0eebd5ff5eaef4454186286e98df13c21fb290eca3f53d295f803b2cd200f101cf8f5c63233c0930fd4f7e9473e7", "HASH_MPIN_ID_HEX": "1f9de43aa86c9e4966ee70ef6665714354db66fc62cc71383b5c8e570057aca0", "TIME_PERMIT": "0412bd9ec39d4a9c6c8972c6a9e3089255924a0d58d973e81300ef916c6ff6a66f12975b10ab8bd0daf4ea3f56d4c29c33bb85d1fc637d25ce1a863db27ed5c1b4", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223536653462616532653365393833373439616634346461646436346566623131406365727469766f782e636f6d222c202273616c74223a202262386330343261643633343062333164227d", "TOKEN": "0409e82acca278ea1cbe497d412efd48a7ab74fb5019f0941d4ec2af04c7b6b992004ad644ceb35be108945b5ce4894df34e2fcc8f874c38a8d8b11ff8f655678d", "U": "04032691e5f6fc2a7eee265eedd78282e1ac75c8b7573d03e0a9f3b93565ea3b6f1f37f211a18a04a3dd28d3a57f73546891383b9e917aac869a11453b6569b622", "SERVER_OUTPUT": -19, "Y": "1282e9ba104fdf8266616e6045c4842455cf8f8aa6184b5d83fba446262715aa", "X": "1eee2c881a2f703ef0c8abd467e47e2e13fae98ca0d83dd678524451bd77ba41", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"56e4bae2e3e983749af44dadd64efb11@certivox.com\", \"salt\": \"b8c042ad6340b31d\"}", "test_no": 140, "UT": "04159e5d55fb7c4bede88b15382db4885fcd6e1618611805540b4615bc3609ec090cacf80364c60eeb5d761c697ddca8fad1bfb85caa563f072a4398256feba739", "MS2": "071d1e9f339f135573a05c512cde801f56f809aa7cfb3cbfa7737050f8139000", "MS1": "1e32c1c633f33371c0cea894346814038cac37a6a33ff738bed49cc37327b4f8", "CLIENT_SECRET": "0411964c851fcf91d1057872cf0b663d4a85978011c5f61ab1d3a00e3e6556e0e01877cc29239fbfa929126e7da23c0274dc7fab2221af341f43bbdd41816df584"}, {"TimeValue": 1437055596, "SS1": "0919dc15900cc1a9cfe245a93e9a06c173b69663fbd4bb3706c712d32b03789f089f51e4b387ccbbe2ed8c13f354765c32f16f1b5045a7a6acb593f0f51adf7002a16edd29592336471178ffd5aaf991d6a77af6284c460132f3f6e107177d8d1f8f77b5a6a4ba7ba7ed9eb7f68a87a9205c9de44912025957d937159462b494", "SS2": "02ae1b845f2a4e59b368c4993ffd7fcddedb40f801e4f8f75b7f123adb38560b0944c62c916f8bd0181bcf796e18d4a679564289b3ff07701b108e4b10c426eb0606653f2b2721305320509e9dfdb9463893f958d28500156d8c094c09ad14d1209dc2526c2962ef584c2f386e3bc4da6775078765c67ba2a725045ce17ca2d3", "DATE": 16632, "PIN2": 8710, "PIN1": 8711, "SERVER_SECRET": "21ac5e6369283094d4082d44c52f74ff59e7669164bb996c42a8cc7c48fb426623a1a40e020eccd7b3908814147fbca0a7b52bc3229f312189f5bc0cf6f22aca1d1ce01d62083fd993fbc34a9212cf6e12aef47bfdc8c8278996a644a3a4cd220cac6deaa2f35287e70dd9ebd95960572fa96f9c5ee49146125fbd68ddc65aee", "SEC": "0416e662f12076ce986a539cbd70562e6a230b58c99f437115d42dce28f77179ee112788416cdae666ce493afca86e45327ee9ca8dadc30721b5e8cea018720861", "TP2": "040837094f69c7cf51dcbe75b34e54ad4bd3d84122778aa7d355721df875754e141e152fa7f98e6570fa3c39faf94bb61c5286e1a4d671cf2482eecdd3a8c77d1b", "TP1": "0404d6821e0023047db46fbe9e894e4ad4a3168164762f2985f94679dae522e7540c375e2bd70291391995a4a26fb0419252dd8250c3743cdf65739eea1661df1a", "CS1": "0423ff497f6f8f28d63d1266217a0a6596e631dd2bee8772ab51dec8b03765ff5a211af7d126beb99a1e014bad6f60108752949981786062cd8e2eab914cc30bbf", "CS2": "04003fc38dfaecb66c5555ec2de0ab027cfe202840bf2f1ff815de3fe19a7f1b8b06aa0497ab2ce716936721c71cf330cd8ebbdeaa7718363e416d6d2e2b14c438", "HASH_MPIN_ID_HEX": "7deef0b4345ac06473b313aaa12182f39c158eb1b03931c8dcbb0cf954f94748", "TIME_PERMIT": "041de014b0527188fa6a1abe70875f1f30a43573ac24e9098ac8ce4334b155fb7f00779792a439422829b71cfc8036f1c1754956ff54741e7af288bbabc63d7906", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20226239353161393539303761373334323065353961616666633265393439336331406365727469766f782e636f6d222c202273616c74223a202234623935376639636334623634386437227d", "TOKEN": "041b8a4b2ac89975be6495e8f687607319444d6bd1c86ebddc4e337e5cb82cfde71d59182af0361a3ab2e08cd993d180e39d457d97d4b188b0be16fde2b83f229a", "U": "040cc2ed25a839a1e5f7e7823ad115269ccc28aa535c129504a88e0e7f339772e8191f65b4274e9d935efcd57a800b491a06fc43e66c857480f4860fd139c98958", "SERVER_OUTPUT": -19, "Y": "0929d219692cc654ebf4ddd0f01ff02457cc906696ae7278487e11d9fa39fb0b", "X": "22c20d56952fe7482021a027a91c449fd29dde09577ba91652018d5e48e80e2e", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"b951a95907a73420e59aaffc2e9493c1@certivox.com\", \"salt\": \"4b957f9cc4b648d7\"}", "test_no": 141, "UT": "040ddd609fc1f516724d7ec703f146b653b434108c7b446657273a83d3b22200f515733d02b9deb1ff66107f2ca0603de401e2fdde1c0c10f0f917af29a2540af4", "MS2": "1bb16167a310859535d91beb6fa761bf316065d9327336c7f76097997de0dcfa", "MS1": "0a365890facc7cbc18d510708854c73c82de86d8389cddeb54fc59ff4f4e54e9", "CLIENT_SECRET": "04153c8f816781ee8c1241120d74ce92170590860f9671fe448f629267a63531c81ddb9b95548d47151f5a660a4449c887d628616145dfdd9ae1b6d25feeb9dd98"}, {"TimeValue": 1437055596, "SS1": "10925475198d51c75588ff8d7acde3a719959203e75596fc4820da819a0520ff0dc02126fc233a7d99647f499d8cb816a8f9e131c7c26ddf27f70c8dfcd3b71009d952f15ccbf4a3238fa7ac31de1d47adc7acd4fd85344a7cf050e8dc0fb551085922557c6dd49e04cf50a746bbfd6eb339be714acecf34dfa8bee6e7482417", "SS2": "19ad43ffb5c4bc32a7f86bc7a98953c77258df2677ae4f2766613fae95be5adb03ca6334aa3a987447ea14fdc99d256191f0159814f8b02f4fd6b66aa453222a17d98063936a3a40805514f1769f1e334fcb91ca5d584781d4f29b6e1aaf085c23685a45483c48e96b5cc6e729b2a72b68337df99068dc075e59e9de97ba6122", "DATE": 16632, "PIN2": 4377, "PIN1": 4378, "SERVER_SECRET": "02f4ec371283c247bfce0dd4b28d29e18a1918443a37418ff1a139b978e0e0a122cf704921daaf119bac70dc3a62088fc17d15d9e9c1bd1d98d79fba8b1326c0212c1ec924a9824ca043e5f59db70879e6841cab2b1d29dba1a53e42404de2651b4ac35e35510bf1ab71642d30e79aac843b900fc430ad751da3e1c24a657c84", "SEC": "041dceb98d7bd250d0c4851a7760f620bb21a430295cbd26b301926631ea9f599703ca12320dd74908ee474ffca5966154bdd7eb80e1d41c148cf4541595347710", "TP2": "040074d0ddde1a9889ac12ab81ad4978c6861e60d3c8d8653f2affa7786bb622671459fa0e9f07fef03608c627482de2a8c0269b717857ee4e5489b29db544f5d7", "TP1": "040d99e887f4f3493042a5a50cae3d10624066dc1a6d82769c0846919fd477bba41fa1193fffe8f14db0a826139cdf2a604eb2f903efa90f8c36f298c82ffd2d18", "CS1": "0416bbfcc1da3dd7dc7a54feb5fcaeb761c21519182fd9b386ed357479a6a330760566d952b4630dd02a661f21fa716064b9e6aa98dd8b8119de9b2a5bc5c854c7", "CS2": "040ec9ac6006055d6f43af4142ec0fdb5b51c57777de2eb29a0936adf9fe8dcb77211b6851190adcf6fc936fe192d179bc2c262c0f63a4303ca9c0a4442c742b26", "HASH_MPIN_ID_HEX": "fed8b530a7108c98d897a86647bc3253863b84df35c656a2d44b66b2eb888ea5", "TIME_PERMIT": "041dc190e59b76906dd0c3de5ecb5dc6620b8ad3529ca33bfa8c03ed5129dc07231af5a3328c84cfed4c9b1569eec1d2f93408551c369feaf751c6720f9d9a1041", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223835356135623765373735363634373838656533373732393334343066666162406365727469766f782e636f6d222c202273616c74223a202263373563376633353363643234373164227d", "TOKEN": "04119bc197dbd362525c169761465267a4a8234a888ebb7f19dcfd3f9d72bc04dd0e7e9b6b390e8d99256517faff9b389a8dec1deef3ca5148d78103194669fc65", "U": "0402a402cd428b38dca7b533864734c718fa4b77d9abc2c38d26e1b7c7324f5c271d57c5547c4256d3124b0d80ef7151b1180d45ead85def66291384c3624e97a9", "SERVER_OUTPUT": -19, "Y": "026ef6e293bac07eaf81bb058a1f706f3202b75209354113f821ef4de49a3582", "X": "16dde8e14875a39c0499a0eadeed2e6fff6c52a2e3538c175f3373f4d719c891", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"855a5b7e775664788ee377293440ffab@certivox.com\", \"salt\": \"c75c7f353cd2471d\"}", "test_no": 142, "UT": "0417392f502a517972b656a4dcbbcca3f684833551720e403961d677d45acee663011ee58e54bbeb642f39bea1bedf40509b241715dd989e0056bfcbe5cabd00fb", "MS2": "03510ef755cc1457395d11453eca5416f52f65b5afb41cbd59dd6655a4755cc4", "MS1": "1a1d1805ed547ccd47429468161abc0d9f8549044d542befc198eaebf6b1c7c4", "CLIENT_SECRET": "04141cc864504c7bda3b5fde724f86149fa9edd0fac16b894246bf00b13d62838e15315dc5de63fc077d4c7844330270ae462bff8c99fb558860659b229095bb4d"}, {"TimeValue": 1437055596, "SS1": "0f137361251c82abcc5e92688cd9c3ebfe0557636606f735d7115e105654e3750c3aebaa9c98718c2b0bd3e8824803608ee2d67ac160a7c7170561eb113cd30a1fbc5d077fc39b8b862027f0c0f04ab67464c5a78f624999f50ffd5cf36fa5ef20f1b0f46e39b76044b15db33944f8cffe89102c8dca844807fd16f691cff2e0", "SS2": "04b3f13aea2f3a49cb0278e84715d151d64f82b2f2b84a7ba88b3d177641587101d96b6ab14c965c4fc88d4109f5f518901a4802514d30500d1ee1a6122a171916efb1b1db46a59175b361468a6333e74b4da011a1fc94f8c1942bb599d13c9515acbae6559018fddbd4dc1943ac01d23d554d1ff10853c44cd8cbb3ea8625e0", "DATE": 16632, "PIN2": 3315, "PIN1": 3316, "SERVER_SECRET": "1d8560be032c1f606161eeb56f1ed07516ed1a9dc8f7a6d592a16c9ce62b0f05207797228ad20f3355d9ef5a16eb8d16a81f7022557a060804217e12b9e5361c2180c524705769d99fd503aff4734351faa26b0e43195c80bb2ae0014756474219d848670f18baa68fc121785d59d4b5b45cc89720de48bfd7c64648d39e306b", "SEC": "041afe4a6ec2d956a67550f0da3c9a31582ec5da4d67529e23e05622c55f2edc9b0ba655ef699bad4a7831d9eff1578e4d5d68103ccb34822d4727604f527445e9", "TP2": "04219d437c5655b57bfb14d90aa33ea49131dc351d6bcdfe6e1c1630f4c3c4a36700d55dda776b40b2cc311a7215a7a1d5cf3155fded0765201e9c526e493f6c5f", "TP1": "040e2ccd846a0350165f90cb3949b267be5f11adf14fed5ea6de12dffb3bde3203131ef5a8c0c0f720ae8655063acddc6db87133a9bb558e4f3cacb3cd76c6a53c", "CS1": "04161af46b63ccd50d40cebcc978da3af313a018634ea28b9762cba6d4d59d64e721c7caa009691944b35b3c54fdd257aa796ed79fee454dc8a37de3bc0fd5c3e9", "CS2": "04017c18038b2454d6441487941f120d0518b1701cfd6a3faa54769dd8c41316770660907ffe6148250dc99e08ec088c17bd8fbc607a452b3635cce7c6cc1c4551", "HASH_MPIN_ID_HEX": "48fe147303b6036b2cc5f187ee620912a81d844757f8f831c27d7b189b66ef3d", "TIME_PERMIT": "041a6b87aa47926ca6bd6534437ee95f11e6248336554a8c539a81ce4f8078658f0170fcac57e64f270655b440bc086e5a8fec10b3d99021fa1b963640d33f10fd", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20223964346531316134373665616135303865333337316437373231616332653262406365727469766f782e636f6d222c202273616c74223a202264386338356532356435313931666338227d", "TOKEN": "040b7cd4a00d964d2058cadf51ac762b83c33f40dfe6a8f4eb204a73b9357909a50263023d91e63cbebaacb904c17b9ce0ce869b28c7576907dff3438a7edd0189", "U": "0412bf3d8e163ac79706ae2013ac0a31aa6266c1940ac6f4a3622b71c6263b718511af62c828bdf97c0e24cbbb6fdad57cfc0e6e675e15abf95b7f7b08a688877e", "SERVER_OUTPUT": -19, "Y": "067cfb56ccf65ba581a74584a6584110a4f261af0b81a45bc7f713ffe79f7966", "X": "09fe51f9fb70379d8679b2ce29e50ce60cd9eb3751caa678d37e5e6c0c1ad8fc", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"9d4e11a476eaa508e3371d7721ac2e2b@certivox.com\", \"salt\": \"d8c85e25d5191fc8\"}", "test_no": 143, "UT": "041924731c354980f0e3b827a7a0dc09cb050e03df3732de2eee56c09cef0cd6400dbc13a4a3a4b2d5dcc3e4b386a5e2e70ff9fb3c59d18a0f3eae7940ffdf255e", "MS2": "1d52524c38e2d15400421eeddf929300ad57625828ec926aff43986b17ad057d", "MS1": "1d09c0179cb2c409e003317a93a912921d667773123a586bf4776075955f3cb4", "CLIENT_SECRET": "0407838b09b80fa763329cc4b4b34fba3e8c08ee3880d0ab3243ef48b698246b2911be6ab64f1104f7aa9104d71f0359af63a73d988b15550f24f28db71aa6e2cf"}, {"TimeValue": 1437055596, "SS1": "1115df9816dd88e70e4eaa634da6c863a214e8fb4d5af7eab1a9858f1dc67f5c0cc8af81db39fb0742c09af2823a7263c143fd543aa5128ef4b1f139c24f9b64180ae4cefb4c12b3cd0dd6beb67ea8bb58fdf0644008732857afcaad936bf1000c84203b3884c091e5b9f80d6a346402b2edd5144f71235d3afa4837d711a964", "SS2": "0ff16bb44a0ae5e3b0bf93d7421bdf586a5520a7462716a187a0a3c82266ca021f2c8fc9c6ad92f4e86efdd5e7506e5c3fa5ae80876a49e4fb6a833a6928bd330b67af2f4198afce538bdd36567c339e5876be988ff4522eff15229d92f731810a0186a23ba61f656f7fd339dcd7b46076db1206a70b0389a3b601437be6fc3d", "DATE": 16632, "PIN2": 7640, "PIN1": 7641, "SERVER_SECRET": "2060736f063492eec25303837bafccc6a9375fe157c4f5257a5316e7c37f37f019822ad949f5047887afcc8332be6a0c4cecc7a14547a9ea93cfe01e857924530783a0e9d8daea7efeb8957e336a14d0cd2d324db28b2e9efed3a2271ad4ffd50581ac4fd0efe74950ac62e47698a87f929df16f56307418994b2454563b67c8", "SEC": "0419de6fd42e8550f8b44c1f9ec1c1daed8bd59fed47089d5b4f84f83448f34ef9132137142f3e2a70de9a7a365ad2e0a12797e86ea92fbb5c03745b711aef3669", "TP2": "04021fe5a96d4023d4ba4ef18d9d9ad426290ea815d7df4d64b3ffdb045eaa75b11d7b491fd97950311d469c281be1ddab74b246164ce7aafb675dc9fc770c917d", "TP1": "04043639abe0bc9418adc79b1caffca8119f829e3dd31428efc90120eb4d22bb36131b61378661586581364dc28418459290e6194b0675f88d5800230763f50600", "CS1": "04035234742c2abda2e8cc2e2ae62c209ac2fb4ced18c64a6de4ba47cf86cb7ed215999f7dd6dd3843e323de55c46f921e69cd46962f199173972f430b0cb953be", "CS2": "040be751c4d535a7111606c46e74227ab7b5581de56458ecb217f6099ea3638dbb202b8199e0f2f42c2dc4f9db50cb9125d39a1ac9a3f1992aa51ef6f2f452630c", "HASH_MPIN_ID_HEX": "03e8485922a0a68b33667d86e2f6c51010df4812a18520d8e2611e262c1903c4", "TIME_PERMIT": "040beebb6a0686ebdaab3bfe6f0b8f1e743124ccff7bee70a95b08e0038932f0380bfed79cb60c16ce61e05b8dbd07fd1814931dc7661655ae4e29710f750d1b83", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33365a222c2022757365724944223a20226231666536353935303232313934633935613139306139633463316535326564406365727469766f782e636f6d222c202273616c74223a202232366465373832373633636333623363227d", "TOKEN": "041c00bd24982adc1596a17a9eee4af1c481e1772beb6e22d06e06a1f189496fb908da985418a3db5eafa7deaee13e4e2174df1d88acbfc4caf8963044a2d9bdda", "U": "040539a501be7d9f1ff9b1e1e6fd1f10f072c107a506693f5926762ca822f267610bcdedfc284b393e569167fbc6b0b5d046367487825ebd0d724c04ea2b4be1aa", "SERVER_OUTPUT": -19, "Y": "10d1f66cbaa4dd738dbffa39513690bdb620ae4d08c5eca07f53dd457893e674", "X": "1a0fdfbc88f1a6bd346f883e8354d40239c13358bc5c73320e9d956d25eea853", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:36Z\", \"userID\": \"b1fe6595022194c95a190a9c4c1e52ed@certivox.com\", \"salt\": \"26de782763cc3b3c\"}", "test_no": 144, "UT": "04106e120fade48db94a97bf4e55ab9a7b8fafe6e88dae80593d69f9864981c3141a3bf631246513452dbb3a88124392066cf175dde427290b553e798935d67b98", "MS2": "143892e69563584b77a1bd1cf3ecb56c126dd88e1d316bd6418972307d8a00aa", "MS1": "02b7c9759ba2f8b2dd2137565a6d1541a96c3c5f623ce364e2fa99e839439740", "CLIENT_SECRET": "040b06a57e83109ac8694c35ab23c9f9b49a621e11763b5eee0579c6d0b43df7e205c77c61d78ce5b9e626170b386275d33a39d75f7fa66bd3416d1859a0a0faa2"}, {"TimeValue": 1437055597, "SS1": "0e982d5fb680baae5cf0e435c11deb286e49bd9a348b10c8b27f61a0d244b46c1f44d26bf5dd0e09dfa89c488d23fc0a0ec0cd31111a4cc5b3f3e88b918c178e07e385304ee7e5168e2362c53f79bedf57e2cc6febbef874ed1d44be2e4e9aa904ec0c9602d10ed3bec670aab21f0973736e2e3b1bae733ced148785bca10aa1", "SS2": "0cd2ce566589e1fd4bc726489900c1621b35b5bc018f8899d246f6c1ae05b162174710c5913ac729b44746e023d0dffe0593ee8f263d7dcd984520e2cdb4c84206f21b52599f32f40c02bceaf8650d6aaca56864a76732d1895136ed77ee67d21daa9f7bba6d8a9a17aa269dc000be2778163d1ae2ea8a4993280e192c6dd158", "DATE": 16632, "PIN2": 6324, "PIN1": 6325, "SERVER_SECRET": "141622ce13a2ea3b2f7facd1877831fd0b37dc3e1827fad44e84ba017431cfaf1e1b1a3656b0664378ee668d02ee74c521b8ed1087f52c17f622e0717c96beb01570b24a2fa5aa3d1ef849edc423447c382eef7bd3977d8a7e8780b84726a4380e9a4a7e29a8775a9d7f4e37138cd2fe6694da5470a102d74bdf5bca8330b5ab", "SEC": "041586647dd817b79eb289a1725ccf12dea094dff6b5ff53793407596b59e1d8ab1230f4030cfed2a15db077fcd0bb87f050841e1d7ccfc61b6a56c5405efe3e97", "TP2": "040126772b5019fe4aae4cdbfbe6c6c8ff5723219dc492fb1b0135225f2b1bee660a768dfa52796b1abd8f42bdc36be9142e4c0554750a6d5672f01177d1478245", "TP1": "040c26c2f23e05e50651e6b8e3903e06359afde3564bd84f6347993aa2b60a024f23cac0617f3d11d5a48183c0747b6094166912f2c2582a9669a24fc87437afeb", "CS1": "0409a925151d2017004a0c30b2ae0dad24d8bd9b75a5f633673faa94ae8cff05c92043e4dc114c68e61920ee6968c184535c0a7cebb5c889c3d25ad71927d0116f", "CS2": "041ba523cc36c92a65c3f03acb444e8491b826f502940ca16d5078f577804439221f3c41b0c7c5508efdbb882f5ba7c6c85636bea91d8b017a9b5b9ad7e60dd15e", "HASH_MPIN_ID_HEX": "8a1e542e254240fd41abf19c5f2e58b164dd8fcd5be667e2eb1395a4f44e334a", "TIME_PERMIT": "0419bd110eed78164336d87c31ccc5bb5517e718fa727dce4a8a52b3e039b29b5b221fc49041d3e840ed49a5e43abd850d2db430ddbb17ad2d417515961ea7c714", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20226136613230303137613734623738306364346363303736613130643530303434406365727469766f782e636f6d222c202273616c74223a202231636139383330626536336434616232227d", "TOKEN": "04157c58ce3f8311767dd07afcc50706c6491afcb5aed40e718fcec81dfc164cf7025a4733256a12fc5ad08f7ce7ec647a4f438aedfd75be0a5adedd4c0b1d4b00", "U": "0422daef39791f98462fad80dbc28d83fcf8a5aa30d06b91027ab78303697bb0b10ab663f0bfc2cbb2ccaa65fe5631c5206e20bfee1ea177115790447cb1876474", "SERVER_OUTPUT": -19, "Y": "058f58427539152100ac58a24df37f59ba3929e1431b8c53be06f5a6299a62c5", "X": "206808ca92746f8c82207146abe0c002a0258f24fd2333122706092b376201ca", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"a6a20017a74b780cd4cc076a10d50044@certivox.com\", \"salt\": \"1ca9830be63d4ab2\"}", "test_no": 145, "UT": "040a37fd0f7485f3fe192ee2153f02b1cf5939eaa62d8cc3c12cf055c9c096441f0f6197d936ed406357f8bcd086443c6a9b39348a00cf7b3d7584e023c93b7500", "MS2": "20a2e6816996064adc7729e935761f736fe6090b04eca42fcb6fdb62a253aff9", "MS1": "1482196e4ab530f77e9b8d65226b09b69e9049e18f82009df74d8aa115fdb384", "CLIENT_SECRET": "0402f27d887fc4416e9a5c7a598efdd4e8969d01d81c48f6c451671b22b8bf859f10b392ed044476752dce9e65457b8a60a86e506d43784472966617cddd28c544"}, {"TimeValue": 1437055597, "SS1": "16c9cff94058abe7cb7e085894f147be7666ce3b221d05234b3ca7241b463284075039d65faf1ab7b602bded402b0721fbbaa2f4016c227b0ce223632d5e612a0bf386d5fd4ce86f7f37948652dcb013de549dd74bce746059da472c72d868761fe984deae3370ff238e82039b45514bd833509f52f55fa9323003ff75a3c18f", "SS2": "0b1702558c9173e64537019976409f22a1d69a81c9b705ed4dd65d161bc1a0390ef6b4a91831239243367324ad82a02fd2ab3e16013fbe2cf286956069b2019e09aca7a0c34801f76596ecc11a631666dc596670005b33ba8ba28ff34cc7f4431e9845a9de909b11ff8580ba766cc687221faad1e667da390f7865480a517296", "DATE": 16632, "PIN2": 9556, "PIN1": 9557, "SERVER_SECRET": "122ebb7560370447b105930a818b345240a725007261ec446fb07ea1bcb6510a0b3a3bd489f41f8cc9e26fce347facc574b62f90da1b1b50abccdfcedb02074b1ce0004be969089450e942fb1aaf760107e646cd560b61f46c3a1383987edcf5007854e40376caaea37c86b4747f9828a6b009076fab9f3fdebf15ecc0411dab", "SEC": "041f9f83eb8fa70d95922b69605c1a9e11c42d85a306b3bdec36578cfe7ea2c52a02710e996fcce2900d032d7248ae2e808ba2c9e858a0c04508d329a386fad802", "TP2": "040e7ca51263022ff42a7702c5acfb5d99c39e04e08f77df1216c25ca052c47a8304854e4e6319cdfe1e89ff5ef6fdb35e6e12abf27aa8cb2c4d515b932d32bb75", "TP1": "041f2647c6dee5dbbe53936fa1cad7563f09178a4e4fa547623f639a8d1b1f9d6d0928c8be58e93cc66eeb70956101fe6ab91420952228ed05d2913a9c36e0cf52", "CS1": "0400dbbf19abe5a67e80790f55dc22fe4eb8759ae5f4a060707b57a101db9b10731e5c384241365f130ffbd2ad8e257936a9b8994848c1bb5a3eeb83d61abcb8e1", "CS2": "040130cea3559401213231463f08e06fbd83ff379d0562c78440b9a7b5137d126a1c725048c7be9621eeb9aa678cb2b105de31f843b3f4c10a612f2c5587ec485d", "HASH_MPIN_ID_HEX": "00f0fd5f6a78aef02985f125c16c4084687b62b55886444b16151c050dbe7b8e", "TIME_PERMIT": "0411a086231347ee9b8f18aa54fe0a9ff5236b063c13e87d73bb76ecb15eef18650f1a4605723b60ceb59c2c821254f50ef8c450e73c8a1bf7c5ee0843e87470fa", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223638623831633965363430393266303438643663663237353130653131633339406365727469766f782e636f6d222c202273616c74223a202233393336326539323735353038663862227d", "TOKEN": "040ecf54ed61bf265347e63914b176dbf6a547722f0421ba8c3429d6e0454913b704cacb77d21da918fe3d93d485d2d27eb3f4d7dec839bde801b5c44d2509335c", "U": "040b003ef3e8945a6387e5063bb79c91778a527b8054da85c95f80437411e9f5f20e2f4229a1434b8902953efaf71ac4af82a6b8f65efb24db51d559fcdb65eac1", "SERVER_OUTPUT": -19, "Y": "1b74729857367bef65086f272d068435d0b1cb555fdf3144e012b260a977db83", "X": "125856f369f6a17ed4726e1733b42184cb211bcc5c48b2cf9dfcda7c7ee34816", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"68b81c9e64092f048d6cf27510e11c39@certivox.com\", \"salt\": \"39362e9275508f8b\"}", "test_no": 146, "UT": "041bf11398b9fb3c5128d6c469a03902f02b63dc922fe5f717ea2092cd70fa02811b5325f0d1c7779fc1fc5ebde7226f9ed992d2a10a3fd707c9d91a51b7ef737e", "MS2": "12828d2012b5b37cfe75753acb4097d5d8ca73d7515f86d3ac1a97be9b2e8634", "MS1": "1b9d386944d7d8b8a7eb8391570a29e20c06e74a39dd14f2e05e2b846d82e09e", "CLIENT_SECRET": "040a53b4bd374ce9242ce252fc7b76d090114c9858fc5378e232a9aea920c0470622a5265b0f0b018b5315e32beb6fa76c7e94d6e8d9934e57466940b08088d402"}, {"TimeValue": 1437055597, "SS1": "22eaf2daf03919afd51993f6dde485c961915bfb5aa00bf2a5edfd118eb0768d0694992e8f545a5764e0085e6180e436bcc50211f97545287570f6057c5817ff00e2fc984123635e0941500461b1373e6aa195fcd003fb3fad55d2ee92cb903920b0ebac9cdc9b2075345f63ae49feba1cc7e665905a319665160b94c2793192", "SS2": "1d5a9949d0a7e8e70e65bde6260acb597fe3ec46b46d7568a4b3b1a52f934425092dc4b5a7813a739b18f858b35b5453996bf9dd2246650761e02f0e0f01e75d1ee0a2ccea902e16875c3a2a4bcccb206cebb4fa46a55cd8f1e592a1863757f905e58cdba2986160ff196e9d17355711edc22778d9dc73e544645bb10085e4c7", "DATE": 16632, "PIN2": 8037, "PIN1": 8038, "SERVER_SECRET": "00d5867d875422145b0dff65ca725263bc9c77ded1b8b2941c338d23fc3c35620826bd205557ce210ef96a05d2444436e39e7e0805c43ccb60f5f7096eb2d03b10feb7e3ad2c6fddaf95964966c8e0eb5923118ca4430957042662d7caca9b1d08344e954b5e08548de4af2088a2236ef1942467b74e7b47bd5d73a0370e8d52", "SEC": "040fc96ffa9f2ba2ddcb9bad2febb86961974cc8959e1f04e45654fdf3fc5506430bf5cae59215bfddf86dfeb5e6eede78f596fd20fb562bba1f37eba8802aebb7", "TP2": "041e352dfedc89f26d013627d4245027941a651c0cf787005e0f7fbcade3e8fe4e1e0efa4daa3f9d38c91ac1fde8b48509cf80eb379c6cbdc83113483031c7b540", "TP1": "040113daeca40631a4595d6290d1ea90317835cd255d69a90b4bfcf984fcc896fd23418f413ff348795dc20affefcfe128938ceaf1ae6b82d9367ce75d814f376a", "CS1": "040d16db1c128fcfda5edf063b43541c3a7f4f75e30ba33cb68973fa0c8b9a8ea4026a3166f7610c5c750054bd1aa5071939c48332199ecd6b41f4fbf257ba2b48", "CS2": "040bd79349be6c7cab17acda26286b637e80426f0597fc2ca4f3ed761c9a09ec590a1de6aed0c1e39e107c1a0ebb7531166e0ba527d6856dfbfcce3d1579f4dcfe", "HASH_MPIN_ID_HEX": "98d35437347fa19c4c55e107e27d388b6a4f75bb888303315865bffcef02b073", "TIME_PERMIT": "041574fec3a705a4331a1eb71c9a9306f61e228914482218b4d5064bbf76bc193d19985ab439c59300fa3bce4d1ddd3347a1f138b06f6275e3d0cef4e26810156e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223234643666396261333061303938333534316462313231656261343630636166406365727469766f782e636f6d222c202273616c74223a202232613162613937323038396362346664227d", "TOKEN": "04044388115c9f7931cd7fd7c8a4b829a584df441c888947492ade862e0a33468202a46542300ca3caa9abca8e535187907470d0a50f92f839dda71ecdd0ca947f", "U": "04028c658c392c4c748653b8ddffbfc2c040b6fd7eb74a6d02cea4c3300d397b011eac01fc49e87c297570275d638dd8055cc5ca98f67f1b287dbf8c89ab9a494f", "SERVER_OUTPUT": -19, "Y": "0869df41de93d26f29a7d57befdd499b356244c01794ef531bdc72c6324a6f1a", "X": "17b8245bda407ea4eb3b8d5f83bf39d92fce8240ccc9f69ba457066dd8dde464", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"24d6f9ba30a0983541db121eba460caf@certivox.com\", \"salt\": \"2a1ba972089cb4fd\"}", "test_no": 147, "UT": "040234fb35908825769b1ed3266a82cc833194f2cb9337f4378b142e39d263dbe705d1aad23bedf39f1673dd5e5819982b215f624151da58716c7187d6176fa06b", "MS2": "00e0bfce9ffe5c6ef8af3832490833b6d924eca4ab5e528a84c1333f05307ae6", "MS1": "0b191dced79effdde8a701538cf3395f56fa17788779437632b68deab3e6d497", "CLIENT_SECRET": "0401d2ffcee21109b677a00f69057f80ed0a025800b1268d0a023cc0a4cfadb93c10fd49127aac2f0fcdb61723f30af883ff79538764c2a2c9a2d81d600a0b304f"}, {"TimeValue": 1437055597, "SS1": "159b1f97a761e004c8a1f30760ad20a2c114aa310a0e5f9e72fa21e27d64bc0f125eb596cba6150166b8aaa216ee207cf6f9fd3713b847886d07692fb85f09a423c74efeec7de6a7d38de8b3c436285a1a5df056dd46d1401990947a9ce418eb1c4b0ec7308a9534ff6a1be276a73f2e3e418fb06cdedc30cf87a56f45df79fb", "SS2": "12fb8de9e3dfc95f4eecd4833721539c82e11811578cc0b922b42626ff1c15d910c4ea43ed86acdc6da7c9cbda8ac04edc52a7dafc70de3753c00717d7413a300fb3a8a87a4ce3aac8a1e34dc6817438a34434bdc4e270062441ae9ef862018016a825ffdb7110263a33eb109a819904db8b4d29fb47dc8c8110d622130ba4f3", "DATE": 16632, "PIN2": 9644, "PIN1": 9645, "SERVER_SECRET": "19b031aab12aa8086c06dd0b71445ad1df0d362d339da9a570a26bb74da6f63d2394e82c9182bfb32fae1587bdcadde68b5b15c57e3d088ff64c9ca258b61ff7222cd61825e39233efda530beda295acc8301bb8440141638df54eb2eef5c0b71582fdd5da4cc0ba55b775ad640e52b2da059169ee25d98b0ba1c6a6d6a25f26", "SEC": "0406f1d83f15dc57cf3efebdc454216f351ea65a9a85b14f9eccc803f59237a6cc031f4b7fb186be3bc6964cea644ebe84299f61180672b7f03062d50a3dfa9094", "TP2": "041feb8a882740cba2f664781f919bf4e1ff713f0f81cc20154d1d89a7a0e7e2811812cdab5df4449a568bea37b0a8b4a8852edc42feee187b221657aed0fc945d", "TP1": "0410686faf1e88995ec1d5883601690c64bd7db49d5d16ad1adb620c294ca124a51298e11e394d1340f2f00b19dfdff7fd744870fe9200f512011d87a56f5bc1d6", "CS1": "0418e868f58b911d4243903ad52980e36d62ca432d4458a4e9da3c72260bedbb410287d4c35c448e633a87560b2f6cbdfed5eca7bd4ce95c9a090dba66cfb66613", "CS2": "04220be0e5b1ecb447e3832daea493f8366fd88062b6b66beba3aea9915a05f2b60be37933953648437ac2ccee9a1c00ce2b8c0bdbe702ba08063d94c9f29fc542", "HASH_MPIN_ID_HEX": "bc45e823db7c075ed1e68048eb970a01b40ed8ea3b0b495215212d4e4ea5fb89", "TIME_PERMIT": "04184336094a7b3858a06ad5fb51bd1414cbd191c0485504c31d72d2c75b31120c11d85c83075d6516633ff066ce80280ae9e1b8352bf6321844c4305c525b6135", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223539663432663032616139373965323335383133363536373230383637626263406365727469766f782e636f6d222c202273616c74223a202238393335646536393637336266616535227d", "TOKEN": "0400770633ec68ff1e4066cdb5baac9c82603911882ac5fd867afd09bb959ab565109db8eadcacbc80e684e0b01a806fe86f2692176ce33c12f1ae98fbe1c7e794", "U": "040b1f824166a16cc0b13ebd88fff42fabf93ba8ebb94d8dbcdce062bf0c15488422463564395d3bc4fe55a47fd888ae52a96b114c7b8aafe381e2f5ddbd6c7cbf", "SERVER_OUTPUT": -19, "Y": "11603f519d7eae765b449a92c4ffec0c9d01a790c4c58da437ccccd61e61a658", "X": "0cad07ea8b2a758890a4c7afeb8757b215e5d1ec4cfaf9067ccabb80b742348b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"59f42f02aa979e235813656720867bbc@certivox.com\", \"salt\": \"8935de69673bfae5\"}", "test_no": 148, "UT": "0421064645c5183b239ac243c88eceeea78cc6c3826747818cd822ce53f7aa154a10d6536faf56951b9eea39bd8f887725546487a6729625903c9119ee6f38921d", "MS2": "1c7ec1a00d40f5ca513843d681aedffd69da33f7f250d354cfd8f2c9cf81cceb", "MS1": "2022fe9d1daafb05d3e25e703f04c68700cae22c623a6077797c7967a3171ed9", "CLIENT_SECRET": "041ab4c598d46b4f51c5e0e27b69a7015520d324e1eabbaa840627357a8f6f3df41af72088e92879162c97649c48a562fdb49aa2fcf292ac20c0061da4b82b0b96"}, {"TimeValue": 1437055597, "SS1": "23dd9d4d940f2ab4b87e8d54f7a3dd462b01f48c008cb6f4d7f659417cee80511f678cd419e3e0a278f5e0d75caa1613ec1bb96648715b9c655af919234974d40bcf659d988051fe078b777a01dd0c0e4ada1c522a4528e8bdaa518d5311f9c502187ec663bf9e47ac24201a90440ff2c1239001bdbd66c40a47f9b344e64765", "SS2": "20ffc5dc4a4daca27bc2b63a3bc2822a7e71497cffb37ea2285aff57de9427971c0956aba610bb9df9dde4b0f03a6279bdad67abc60b5377182806a4911a9ba11ef6d0dd262659279389266f9fca199b4198b6a408be1678fbf168e2f9b058f7118d3da04eaa797fc5d7e7cefb206f8d3eaa5087c7b31cf183a731469e3662f0", "DATE": 16632, "PIN2": 3963, "PIN1": 3964, "SERVER_SECRET": "0d7a4224d0a2e11c140c131199e830be682853b5197ae0996ca01972eb26281d0bc36b44a3672069946a23bb2517fc0d2bd37db86878ea11b4945a118667a1ef0b5c55ef289787b5b4eb7598412391f81b611e73186b8a112221637ab988fb6405d6c03ab08605c4eb71c88c0af57c8706c500507091192e955388b89d719f5a", "SEC": "0403dc76185f31037bad84649e561019faf43a02425486719a2b811837e42b4a900a65cf7e40f9d7396b6388f90edfce0cb801654ed0e6703af7e3148cd45bf6fd", "TP2": "041c27be24cdc050264d37139faf663e117cd575feb14faaa18d9db4087fd4bf6b0710b87f83d41fe97a1c2da6dbf3582ee9dac29d46b70dc9b04dd9a4dfa62c05", "TP1": "04196670145e76839b7a5cfe460a8fe9b571c2fd1140d2e7f675ae808708a25026004afe8b48014f5cb4be2a5aa694a0d6de77060801e2c5809fae6cb85f3a63d4", "CS1": "041b3022c1125af049c57e9c61aadbb8f23bd2fbbc58caa7372410d8ba04dcf3cd0736d33bc0d3c2bd859f7e05bb4a1f7f6ae86147fd6b1a832fbd19f373488f8e", "CS2": "0414846837643c93c884dd5b95cf18537001260abb58da1eac82e1743e6e6f40d0046ad8f03cab4149edfe2f72af3a1410b1b3031d6c40ae299602dd314293a589", "HASH_MPIN_ID_HEX": "478ef8725dac8c8c3d8a4e0a31dbf48157388cd98f00da50a9eafa6b2a0dc306", "TIME_PERMIT": "041cceb39e3464308e2daedae54c9d5f6ac1f269739ac36083a65cc587e8322fc211077c9f7d56c2ba1e2a83c84adb0d6c47e13ec09a301f144c53285a3e19bdc9", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223130626661633336653437613232663833653432636639323865323962363433406365727469766f782e636f6d222c202273616c74223a202235626139383039313361323065626266227d", "TOKEN": "040bf87b03665a8d40d9c7cb886178cb180fa2bda3356deacf1697fcb5672d44f5112f696d3772925ecab59f6161dffc5c68c0f7cd68190170ed86aa65fbcb5448", "U": "0407b199ed39b126cb55b699ddc1c9134643420fb49b53247d0de11ee0459d133e1432276ebbdb0d731a342bab0c09d3d760ce10c00a30465a7207fd933e51fd6a", "SERVER_OUTPUT": -19, "Y": "1ebdd7c9820950e1ca1e0249d55c4e1dd85aa6b8a4350d49654f45d4625e5dc5", "X": "0859b59eecfdc366fcbaf8e67472750aaca89b6e4c3f05e8f815067ac74affb3", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"10bfac36e47a22f83e42cf928e29b643@certivox.com\", \"salt\": \"5ba980913a20ebbf\"}", "test_no": 149, "UT": "040a7b87eb193eb38b625166bacac615d180fcecb3d29b00a7640295f5443e122b0ce57cc5169a298411eef9ccdf224c889d8553cf5f1d29733c57b1e8560107a6", "MS2": "0b2e4bbc07f0f6aab93c5e1159ed97eb5633190afcb5922e7579d270f1ed352d", "MS1": "0c82c7a322000dc2e036ec98b392a708b865d874d0cb8108ca909d7f865827f9", "CLIENT_SECRET": "040a1199631863e336c1951eeeb9c5bd5ecf5515bef234da3ec3682a488ba7904a1ce17f1e32178cf557b76d3b66c17773f0cd404638dc6da06ef19f68ab29b13b"}, {"TimeValue": 1437055597, "SS1": "22556d17e5372285c894185ad14995c46bed17975829247a3efddf3dc67428850888f5dc5b7708bc4eeb57dd3ec08631fe1084242ee89afeb51567778a90976402ab7a3dfc9ad25c82ce9d73e33af5eb1a92d145c43a70037fbe55165a4ae1d61358cbcdb4627d1071477084419821c702810f4786749c43a91f774bcc66dbd9", "SS2": "0948b03ad2f1340c33e7dd3ee6ded8d1701dd44b905a02e4a3f4f501b64e57700e1ee63905a8afd571f0e1ee2c90639afbe894e5523c3a580be6e85eeda9009902b450df3846d034be3b34bf3237532ad4e4f01179c9c8efb44658be1a3b57d600691207eb991ba5e0b46852686bb36f6345484f5127a0e9652905e5a3a9d4d1", "DATE": 16632, "PIN2": 2467, "PIN1": 2468, "SERVER_SECRET": "211b03d65539d917b405318c7501097c553a3cec160b1e84ed64e6802e97ff58021b998a9b0879bf73223e9dc3005be0446635a195adf4535a17acb2d999f77a1fff21ff6ea53de9e295b95d049739c9086070f66713ba34477f0634ab1afb1e051bf4c0f0635f6514a35c4d5c8b89e35b3a97111f803071bee8b5426cb9897e", "SEC": "0415be516561b96c7e3d02ef1c519597add1f5a5e983a8c8c36e2b190a6974668b07d16896e4de0a2aa3dfd342081d9f5fb251ca29d2d0023b024830805b5d12a5", "TP2": "040ec8135fa4f62079140c2a6fb8e0a4e0f9742f1df8c75b387f430d861fe89e0004a3164052f81ec1336ce7769b9734c85f43c8cebf0a79b1e5a8a048ad3825b0", "TP1": "0415a23964bec98a80e420fc8db0786ab9fca04baf3189456cd78e57313d8c06341baa93de1ecaee0c57fb8177c14b2256bceb6b8458c6010bff3c861db59e6da1", "CS1": "041ca6b81003c0085dc2f1884d0d7913f5b7d5d82bc0c34c06fae1b9c60443ce73218650b59213f4ef7d215268f46e1dc3646ed721b291c286ef0ffbadff84c57b", "CS2": "041a73f63d89b3864c8f1397b4512b3ca0b6648f4c104ed86db3789eb3c8954ffc0525382c313d1ce61faacb20520b2894dbe8c288ac0b246f44474a7b578975a7", "HASH_MPIN_ID_HEX": "c45f8f8bba8af3346ce15fbb37c66886e36ab9bcc49999a0f704b609f75bfeb8", "TIME_PERMIT": "040efdaa97a1569a72485f5a85d6922fb20d7a9d8ebafa7896c2e53e5f891613961d987daaa3281490114bfa611314b6f61fe8e4ba233a003b69d7fa41bd6596c7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223935306465646435646136333166386634346530353437396232333039313734406365727469766f782e636f6d222c202273616c74223a202239653135633237383634323339373761227d", "TOKEN": "04175f0f88e9d6c12488ebb43ea1264d27c739207ffab1e0a2b1c09499891761db0f7e7e516f2e0ed2af8bae5ed202be68266e3e8572bf976ee74d3c70f14b683c", "U": "0415bbd819e0994fbb29067c948e4d1144af8626c549dfe14955c62a598fcfc78d1f5644180e7367221c057e909227340d930d550e7d88bd574e941b855663bc35", "SERVER_OUTPUT": -19, "Y": "1e64dd4ec922b6c5a0bc4cbdcbe51e642c4b8469c4e7cef1de6cd346bb818409", "X": "04e9065760e26e1575a5548055e16746cea0c829933cfcea4647946f1b4b20cb", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"950dedd5da631f8f44e05479b2309174@certivox.com\", \"salt\": \"9e15c2786423977a\"}", "test_no": 150, "UT": "0414874a52aa940848fda3f616e5e42cb8f3e1f5d67305cf9ec8f525f9d2bed44c01920560cbc94f80877f3a9fa3a09e743d0bb3d8eafc9bb40fc9cc41817f28f7", "MS2": "1ec2d6c0b7a7b394d724655183c8dd8eec9c6874f942ab059ff281842d9c1614", "MS1": "026599716b2461608634490bdf4d9489d6a868301e39e96203f4b191ac311183", "CLIENT_SECRET": "041cb27a434840cd0d1dc06c761bdf285ede522baf65446c2c67eec57b2529094518f48d724538981417445e2883aba474728e416a624eab2ea700435ef4c0efe3"}, {"TimeValue": 1437055597, "SS1": "029193671dd24f314d7d64ec3e858e3930a903369ff9e674c1a6250fcf4b51e41b6abc4eac11efe55b3f7980138b6614647751173129f80a61e7b51107f300cc02837e916bea61215379d25a76451d1e752c5d89e6ecc6255405985097b8ff75148b80aa7885dd114ca50814f8d6ea390c6c68ce8e8b04c02a820dcdc74e2e83", "SS2": "04e207e128f1bf5db63aa4bf67a8543008f1265213c4feed7fd2757d8dd14a1f02474d96ff027239b7c98a81722e806292e600c996d46e111320b05ed12806a01d9fd1b269bdd530e970b19fe038b7b2cb93142ac38f98e78900ed7587f3e2ed173d5027dab61fe0379fbe02a1ba3cb7ad3a8ac4ff52bd7f7abd558084354350", "DATE": 16632, "PIN2": 3953, "PIN1": 3954, "SERVER_SECRET": "02421470569df47fd453ded3f368902047ccf1c59ac81919fc626c8fdaeb3459121b3f1481de65fb58a027582f2d97bd456619a7ab47f6a7e9efd77238ceb22015a19ed0e1e0f7205fd08608c527b7969ae3ebac44da33b6e5a40fb9473a12ab14926cde87730930ecfa94a9e054dd0b2b2bcbc43fd3569ddaed17ee27adcd22", "SEC": "041eba98774b435ee77f36953bdc3acbee57135e6e67e4a4911276056a7d66ab54224f2c202b5c034f2a8edc0c29a0e84ca868cd21560919b87a61fc78dd935de2", "TP2": "04209f86d4c32dd44d2cfe51905aef614e22e097a137cbfec2767826a456347df91c29e2b4e40be428393e721aeff1b5938a1b36f6bd10508b676c41206a03ae03", "TP1": "0410048632348ecdecdc4a1b2f5e9072671dabe499cc0aba2671602edac1d40ba0119c1d1adeaa878ff7441b5c30f53f0f26f73a6c740fcf54a1abcbd311ce4da9", "CS1": "041ff4180935f66f3f5404c6e156b101d659c6a5363b6cc90546f77ecac8d2c1080727e25dcb5cdfe4ba0a090f4aa0d93fe4954b92c1d7acf7ecd457afffabb5d4", "CS2": "040b3c8f549f233141e8797dd970498b3d1bdb3813acc81589d8beceba0921874e2102c1378274559e1ff2ba8dec18e97cd4f3a56e7a04bde24535448dae52caf8", "HASH_MPIN_ID_HEX": "51c579c6539b204325eb23805912a1b1c5c42452548b92e38bccce5865d656ac", "TIME_PERMIT": "0411d024ac5beaf7f3952f0aa6c1003cc1e0664b0e4a0a574f14b2f1a6b38f244c0716014f3dd4a15ba377da4ef3531c0461e469189b248b87a863d4331ace55e7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223062396238363032343866386162626164363964333836323636303366623466406365727469766f782e636f6d222c202273616c74223a202239386436323962643465656131386664227d", "TOKEN": "040c9f456164d9740a3b7857e11eff813b27d3a81cd4d05f073e781fa5ba018fd41db0779dc7ead3adac87821ff4d0c377c239e883676b4896ab21fb3a9b36cf80", "U": "040d39012e770ac15f13b7c0adc0def57b81a4d75120c75c12d1396722a794b1fb1f1743ae7600b25d2b2d61c790b07ff1949b79e45fe321ec5ac816c266b2a31c", "SERVER_OUTPUT": -19, "Y": "1387dec4e0a1eca784bc0d66131aa7abd8a812bcd4bcb65ba0feb1562aded855", "X": "11b80444130c4534b108021ab70d6e8bbdb86a7346433c2003327d8daa38f0a4", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"0b9b860248f8abbad69d38626603fb4f@certivox.com\", \"salt\": \"98d629bd4eea18fd\"}", "test_no": 151, "UT": "0420a42e7a312d83bc6f2b9754b48f7e4e5b7235ec553a8637cce92be8b5766e0c084851abd6d0ec063dcb90c6b42ba3235db5fd3c55e9b7f1a51a03ed343d5bf1", "MS2": "1e63e643d1fb0d9247843c238dbdc4be2151b162c84a616eea962d1fa2172d62", "MS1": "0aca2b6e01a0be13891d9fda4c17b4c191d5688307ff1600ffaf42dafef4f19b", "CLIENT_SECRET": "04173f3d4590491f0585fe2e34ae8199e72b89b0426a89ba644df0874e856a2c9e08a4b605d213d12ecfde4851bf8ec6ca246ad4b7232fd549640109c8a745d970"}, {"TimeValue": 1437055597, "SS1": "10c3d21cb925a219fc239ec6b73ea9c21ec2315d60a200912d279d435dbf94e61e9e51ec7834f237de1b37cf0cfe14dc3f256e144e63b0ebaba79b97f0eaf377154dbdf7ef38587cdc257464b34bf0a0989c15aa5cbe871a860a064cfbf20aae0bf90dbaaf39ea46aa8537301d327ffb25cadd6993ba0d1595a0edfa630b3d3e", "SS2": "039ee70efa588e10d985b5783e5767737a8264431ef7d1afb5a0a8634c60d19a17d95274af40d53f76d2d03264f11984f9501da3300de7461098ef6df056e3d00e8982f61eaabef6f7066ddc79c7fbad5355081ffbf9b8fcaa17074fc852394f0cd4ee4782dd5e5fc49fb945a71d81133a4e9bdf63259ba9db57b36600d6cefa", "DATE": 16632, "PIN2": 2768, "PIN1": 2769, "SERVER_SECRET": "1b096c1af817d930dc5bff116e77643e84008a2bf148a6698135621593d58b811c1a73abd478606e3affce3206317dfbfe63665f42090310b77db921321bb5ba08b0dc101598eb9db7aee1f7cf0ef157e881ee8c6f57441cf82ff2120f96bc7d1796d172f4c82f8d144fcca7df7f039a28fa5f4087fedff47553b3502b2edb0a", "SEC": "040088ac868785b6340b6866867f3240b15e75039067437befbc5b784131c54a171bdac25fbdb9719aad1c45f6c83ae19f040365c52870bdf1ec5a9fca29fa4990", "TP2": "040bb1afc7952d6e3c3efa4db5e5c19d08d5e6fbdd7f428612b62bce990dadde4f203ebe00d3c707b7fdf5ff62263c26b352b43f9eb7184ae4fef78a42712b06e7", "TP1": "040511e3d56fa06608f4f5eccee37affe87d3e2c6ee95035c10e7e65dd12243fbb1e58248b4ecaabe1b01e157c227fe92e940152778eceb97d282962ff8aaf98ff", "CS1": "0423034827d315f9d97b34bed4b0ff695a18b26dd0d5129e4df872d0427f9a9e980523a8e35d4c837ce56760e169c20b96a1997bf355748d4904f8a79132e9bc0d", "CS2": "042114d29b1441a6f8eba14384925cc56b1d23a49f0f43f83bad5aca05973e78b20e6e268777c1eba98802ca76978a560dd9b777935fdad5d75f0e9cad8f7663e1", "HASH_MPIN_ID_HEX": "f567f344ad6b19506acc411ecd6d1b3bf5985bab6ac3bc268a2be3bc995972d9", "TIME_PERMIT": "040cd4edad2f955ff9b0535796c09a8f9d526cf5984901633fce1860e17cdf6a291e3a7d61d644155fc283c255bd7702d625c743ecb31c332639b9bb6b18aa2b63", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20226639393838316436386636633761363639306661633938653434343064323664406365727469766f782e636f6d222c202273616c74223a202265343339333738636163316330633734227d", "TOKEN": "0407b1dea7e0d0f1664e0ab60124869645cd298c3b6217122495d07fefa538cfc11c2a74283f1f9f47295a0c66f81b4a7a1883a7d623c2c8be25df99f15478266b", "U": "040d99fa074106815664ecd0058cde78f1ab94b3ab0232db434f7f4dd25f271e270eabd422380e1fdc3a78199753c81476b9ec15531d4e39901b2c0afba4f7da84", "SERVER_OUTPUT": -19, "Y": "0f6e980890e172ebddb704453f5db2b53e98c6c6b62098a40805ddda99c8c997", "X": "1221fedb9668714da937e0a17b10d6ece39e6e3b5fa21dd071a5b9666589d84b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"f99881d68f6c7a6690fac98e4440d26d@certivox.com\", \"salt\": \"e439378cac1c0c74\"}", "test_no": 152, "UT": "0419a6e5f738a6fcc301ddca180c3445f8cd288f217c2bb7f170246b3960fea878040da6f016520043b62d6e386ba7b0fa1b2c99145caae481b0c1d214797bee79", "MS2": "0ee2676f73f9a693dde6cee22274292d82fa95b16f0f447fbf898e19d488a2a1", "MS1": "099c330d23246f74b2955f630a5f6280b1b8b5ca37e5ed1459e7932978913de5", "CLIENT_SECRET": "04153e5ca7000672e30590f66471327acea351d249bdc0ecb7941ce3c4d2c70f85207ba6dc80b06426da404a9d19fcc3648e9191e3cf993ef774861d087e0646c8"}, {"TimeValue": 1437055597, "SS1": "064f564c2479234ca45b1b59ff589a7849b69ffd08357553cf2879a7802f923e16f862813a7e57c1a4159595f159d5d4b73a8f372ab1a48943173beda0605b441129a2498d634e4da99072facdd46245c3a4d87f93dabcc6d04e1b96edbe6e6519c74aff0f3cdcc9c357b4aaef155e7376a8aa0fa27255e63cc3accc2d7f57d0", "SS2": "0ed890524547849119fad27f1d86ab68ecd96136a556cb1a29fc3150d8aa6e321f92f9bfb731008e99cec35b4346233e61db03c1864371040d06bd8fefd24a3f0c8f2185ee019cf280fa1558d978db5e863a296e084f787930c721ce988aa126108278f71795cb965c264f2c3bc1a404e1ccda424e2e0a14a8e824dd0530d481", "DATE": 16632, "PIN2": 8693, "PIN1": 8694, "SERVER_SECRET": "18bee110f3d6cfaaf161b981cd7ad7f50564290efebd2aead22bb8d661bc11c521fc990efd95dea1290eb6c5ebbcf7431444fbba97c7ace6cde27e3e643cf9240aa9c6550e8917b6f5ee675246145656510b0b2046910c8d923cbc0d5c3590e90c63aff61ee9e2792fd10d0bdedfd6985839a02b9e9f02380fabb15d7a676a78", "SEC": "0405f54e5da022ac1a535b86620ae0bc3f49b007947d8d1a25943e0baf7fe207b811d450418792e560ee8b6bb336661bdd67b66d783c12fab9f8fa37533d9a13b8", "TP2": "04132b6e411b447bf023081829485d064f0fb1afc12568af121f45222fda7aec0101f5e0c05ef4c0801a87606ec40fd8214f7bd0f40fdc889f5eb39552d1bd7476", "TP1": "04237856abfa82a5f584106ced01ca00eaf8cdc4c3e98d1fb34f6d030b95e56772187011d027b444d79b786e1b131d19cef3ddb0018c2778e7d0c526d3e009b508", "CS1": "0419d0f404fcf24c6c4d18f7fa4a9f7f3ebe0b29107e5af5a89e2add58ff35a47e0f06db285f1aafae1a7f1f5872a385d90bd8faf23f53d8bd93ba2ef863bf31b7", "CS2": "041470e2a01dc5c0e4ac22de6bdee6864885592a44d86c373209ef61122185b5ca1e47497b8c1519f69764b9feaacd9493b84f9965706dafe57d97852284ed0749", "HASH_MPIN_ID_HEX": "121d216b59de7b8ee85b826ab68d3c2077841498e97f9bdd9cd85cbec9bb5eac", "TIME_PERMIT": "040294b6e3a76ca0202573263291481b0de41fb324e45070a23820cc03d918c97009480edceb9374ccc59a97f98262e8b90a24be458a2c43f069da86889da31c6b", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223034373833303536333762346463313066333531326436643833656237376238406365727469766f782e636f6d222c202273616c74223a202230383261396330383633613736633266227d", "TOKEN": "040c0984a006182d23e941f57751feb196c94927de5621ebcd3d0e88e9db8a1f9e11e7f98467e702e1b34f262ad8ce306724cf8f98d790be6cb5b0fa6a2334ffee", "U": "0403bc19d7ceaa8bbb11f89cb7e4217100994f31a1133708786b50c3bac40d2c62126f7098ef04a28fc8d10d3db7123208465b047ae8ef1529104658d47f55b1f0", "SERVER_OUTPUT": -19, "Y": "07eb7a8eb187cc756f9e0bd9711a63d2f75b1a93c24fa4a82a1b435c1add3e7a", "X": "190ac894c24037221774b2ae1d7186f7abd38147818cd36c81926b84fa917e62", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"0478305637b4dc10f3512d6d83eb77b8@certivox.com\", \"salt\": \"082a9c0863a76c2f\"}", "test_no": 153, "UT": "040045bdbd44c1e6ed4e89ebbf10dc5c9677ce017a82538924e59a2c9aa7f291830ee1b2cbd7f16abf30c8d081524d1ef035e6461f5c6d4ca2bf66348fb4df466a", "MS2": "107b165b9dba2b718f0d258f64fd09b6ab515a478f5802bc1e7df22b69ed8d1c", "MS1": "0fd9bbba6f669f94e37a56e4871fbdb5b05e40af8564a7957492a1d454cd50bb", "CLIENT_SECRET": "0413d9e039cbd29e2fc22d61965e17283d9802912dc28308a1044095a40647aa671f1935a2a7aff0e6468cd8534544c262adbe648becde13fa86d5b7f9e420c994"}, {"TimeValue": 1437055597, "SS1": "1fd68bfcca6a9894daf329727369a8037ffea968d1fb53f5e71569f2abc7e91d1db282fa71c040422176ddf2e92e89ee8823f3f653d8d86b207407583514463303e81f2f8764ef2d0816e37d4bdd4970fe2cc5770a9a56359668e6de098240f3057191099655a1147b641ce39e47b87fe6127d54d4fd68bdcc09883e69cdcd0d", "SS2": "13d6136dd6bb50358150f7073cbe39345e455a12b0108bbf052a2ca9673661ef20a53fbc0ba0eaa865c61bd78d8ecad13b0d4b01559dcf3cbcdf9cf920c7a50604a417518e6a3741ccd88eea73922303f100769f656ce165c58484c84818c8671a1a669438c5958982fba0b70b61386f6ad0de0c976ea13c48db9573b04a9723", "DATE": 16632, "PIN2": 3947, "PIN1": 3948, "SERVER_SECRET": "1453f086fc685a44bb5e1d7cda422bf9a39e4ef7ddf0f6362e48132b3c0f82c80314e0493be4e4026ce3b2a4110b6c423924a77189283b5e26353cc23a7869de160dead8cca33ac7c817f5fe7213056dc624fcf3ad602e076629254ba1f27ad617f678df8a7f72b31e297d2185df5cc7b1c5c3df47b16c02adec788b63331f55", "SEC": "041b93dfbc73a41573df27eb6e50cf84b3ace6bffdddf7bdf9703d78e899b3734c1ff08d26bdfd3fd6a6187dfe56d3f75142244547b69c74044117d0c26e030347", "TP2": "0400e7d82dfa6299bb2b21708ebcb2f0e102a25eb7bf0d276f1bc7a793f8e284b810d878415c5641fae3d8969a7812035455c13563b0feff071d45476f619bb328", "TP1": "040d383072f3a9817226ddfe80910d8bf9ab1c02c2daf3d2bf6800735ee48d44131bbba41812d952eb4370b1a6a432ac76488b97d03219c6659b9ce4cca5610680", "CS1": "04036a769cbc4b233d86b38491eac273501253a514f2f58a1503078fc32f81e06322d0589af72be19075ab9f35f92ab724534978626270397dced0557957a1aad5", "CS2": "0420cf7f12cf769b5d50612258e0e184011e05d0683b4666e502822b57148538560d7cd3a0322000341af095f4c50146c518ab939d7df8e62913c884851863bd35", "HASH_MPIN_ID_HEX": "4329d9dcce1415f393907c0a1bf41be82f81a635d81ecea4c97e134a43810de7", "TIME_PERMIT": "041d5b6d57ce992b6d56a4bda118c526e199ed36a3753220f1f502923a5a3715c6062db63a9d37e1cd9d26ad074ca7698eef01d2b6f22f5ac45db4bb5d0b4f2cbe", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223938343732343563323361333239366465323138343739616366333933333365406365727469766f782e636f6d222c202273616c74223a202232333234316435343563323338303664227d", "TOKEN": "041f953de855c3b8511bff288f440eb2f38525e9a7eb7de84b07ffd8c7171eb29e08f2b93cf95d1927ff85a3bf95e61d2be42c51c3f5f303660ea3bf33f705d19d", "U": "0405833e8a379fb4b7cc09ac6abdefdb6edfb621dd853ca331d13e8fc2551fa27b05540e907d28d93b2042e5f5e25fa0018baeadaa14cb1c0f0ca68aa162308e82", "SERVER_OUTPUT": -19, "Y": "19986189a6a830855e86658628748c9a84a6b8953c1c380ac31430aa8ab0b8e5", "X": "09033225472be74848d82a39eeb70c5407adb0c2cf260c826ef37859b945a96e", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"9847245c23a3296de218479acf39333e@certivox.com\", \"salt\": \"23241d545c23806d\"}", "test_no": 154, "UT": "041530e55043734fe0c91d376320925045b0db6031fd5d80def103b647c2f86fbf11b74781ec1809630737d5218dbb5f2230bc943dc0cfc9df2d271f6490f1f70a", "MS2": "045b2cc795e306232b84eff0f4f4e6df52a5e699d002267719b416c8e8c08489", "MS1": "0012f8d7b65a85db24163e75bc49198f7ed16a9e603eef2b29c38d9a8061c84a", "CLIENT_SECRET": "0401686c6a81fa13b056af37cc82f8f7cf430de7906b761353667706bab9a2987715e2c34ffb248b8946cccc7d7a96542d29aa4dac2b06aadd38fcbc8ebfe10e26"}, {"TimeValue": 1437055597, "SS1": "1bce70c94af28bc71eeea5bc753a3d2b7986bf84b226cc024e0235b0e09deff41759871e54df63e9de8f99415844c78922921ef1d9fd054469b32e51510840b919637af776fbfc7d03472a289cfe0d5e264d22dff7a7159b3c4662e9380e25d911c2f9b2af0752ef7022f5ff50fb18f525ab944803b4403b632eb38288b0dc26", "SS2": "08aaaa97ada53809f0ca76dbba9e1b0c479a5b4bbadf773be846e50dc8c00f0a10007aeb67cedca06d3e12a2706656a88f061b9e41c1ce778f4f9c94f93765e619ec71197fe79700477831cd35d0f22d87cc033a6de193e957861003e46c8e0d0077086aa7cb9aa2d1a62d540ce835adcb0e247ac5383bfc55eac92f6a4b3aec", "DATE": 16632, "PIN2": 8521, "PIN1": 8522, "SERVER_SECRET": "01a554db1a8bbc15c8d60dd9f791e78fc4da429a0bbe4fd55641ae19d56b8757088596558ea508825528a43053d637d70dcdffcf6ff8d12d800fd27226eed2c31b8f7a853eb08dc4941bb2d91a2b75b9c134bb6ebd6d7c6d7b8e7fd4050c21c61367a33d799bb74853bc17e31f84e3f7a07d5244960df10533862f0a02e93f74", "SEC": "0407412746d1685eef41253b8d9d32387321519d2931c4f0e55370597297b7c5380d00b4e2d21777e68bc52cceffc169c2e21606aa7c37d112b61a8a5d66152e2c", "TP2": "040e2c08fdd26a248100dc8518cfd47867fce5397f7cf53262cb17a47ddaed4c5e1b2c2b2a5bf9a0b65776173b2dd7efac02ff15aec0495adc8df004360daa1bd0", "TP1": "04028e2c48855f5d81bdee85afb60523aa6e842def6d1a7fae34676c0144b4f6f52180b6b3e603620b2300769677a24d65a15020acd4fc8d0d93f9b587b95f90f8", "CS1": "041c453433bdf297bc82cd6b74d5d5e0e9c1f49501594b032ed71768e266eaaa7b02322322471c640cd461896f6d2108e057b2fe8f5a379d3036d0b519f9a59ef4", "CS2": "04029ee3456385afe505cdd2934166ce5c546d5656447c67650f0f80f26e973e1208ebde83cb76325c3c1840542c717344bd71014e2a23214fab7c08ba3d3d514f", "HASH_MPIN_ID_HEX": "b3fc4918434fb851107f58cbc06399ca300de1999e5a93fa2c6baeb37eaa87ff", "TIME_PERMIT": "0419361f9302dd62e76779134a71c23cc8fc6368c8e1dc6434ae6eb89393c014b51cafc6e3fc02c0682a4a27c17c42c4272cc3c4cc3bcb8e2df06941099aa3e399", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20226630356263393337643938356430363862393938366166373765323431363232406365727469766f782e636f6d222c202273616c74223a202265633638323338643833333165663065227d", "TOKEN": "0416cc60925b5a06cd6b29013ffa138307f95346c494cbd72bdf268eb7a42ee587153e36333c98b1598203afae53bd3b96d5a4a6de49cc6f6724a5f26f721c97f2", "U": "0404a7f36d6a7b8fb35b5672b8f2c924d0ff4ecb55d670ead9473a4867c0b8968d2103363f4239e4bf5edb80146ca2127741888094b93594a929a2f795047a899d", "SERVER_OUTPUT": -19, "Y": "230306216cfd0a1587943a758a9d5ed25dfc6221f4ef8e81f96fd6b95dd53015", "X": "1ef2c28732ecad8e32e3043a937e06e43422a2dcb1020767413cbbcce5a858aa", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"f05bc937d985d068b9986af77e241622@certivox.com\", \"salt\": \"ec68238d8331ef0e\"}", "test_no": 155, "UT": "041f9d73a8208923c2c15b4fb1b49d4cfd820749414ea27dea7d3e9c36a160ed20162e6113ec70c1c9ec9ba871d68ac800c529083f5045ed4b6b0dd98422e418a4", "MS2": "0347da7892f18d9d94a339c3ae6e81e2ed5e1c080fad249fac132ec08dbc704c", "MS1": "031bb2295dd4080d07aea89c71129d7d9f7b93ecfc5f2b40204d4fd7041320c2", "CLIENT_SECRET": "041ac9cb69696c4a18541475aee613ec6e81dd40b66d802da6361b3e7835481bb113a4071e3fe175e63ab0056ef7910dc41fc857f4685cc999c396d37bc9dacc03"}, {"TimeValue": 1437055597, "SS1": "21bc4292e0baf9500c4257605552a67459898d4f8ba3f3e115821c9a2f23f9d318028c45a6babdcf91f4b077b278f94a9d3d60f3afe664e68eda75a78822caee1505d8c8bdfabc41d3a286449cfe69d9b9e5d0a34ca06357ff57f4e27d1de27b1476b68560ec0e3b89e6c1a9ad04eb520560fb2e4fc41c5a393399409351a70b", "SS2": "0c0c7fea2b0e755f0002e4e28b54388899ee4829b325d61ac1b162b87e70d95610651c30a51447d4a8d1b1290ed7f34bf898fd911eb84e68f34fce149ea202ec0dd1acdb2cdb00f90475eda6e771fb0c1946fbf40d513d434fab58c7d3fffef70ec7ef891af498c0fb4c7eeb90bb05a7c6ffc9e16a56af881459b5f3ef2e78ad", "DATE": 16632, "PIN2": 2072, "PIN1": 2073, "SERVER_SECRET": "014571a8337862d72ad139723c83f56524e504cfc6445a7c09d0303d31973457034dfd2e8cf4736034617f160cf0914e1b5b7b2948fe422a25505a8ab872bc9e1896309d49772598dd527d9c8babfb2adb3f1ea1330b015bbba2e9206b81bc0a112bb95409afb05d981ccd4112da2b8dd3f9d6e06030b1a97885ff439db7d378", "SEC": "041d873fb866db88f6bc759349f147d90e79cd01aa0b742d299b3a65c51313a15b0a4c31ddaee324271c12affc88da99b49ef19cef1dbea6266fc2e6cbfc2fa778", "TP2": "041b42715a9798c229d4f037cdfac1696230711446706a842f8e6a6efd3651f8cf1eb8d870925383f333ea7689493c00b97a1f80bc843bea639e03f40975fcec4b", "TP1": "0408214fc2f3e194cb1fb4f99bc527b163c3afd951f019038ee7e3ea1e070ea47f02c335cd8601f77c85d53fc73af7f6ce5fd999f73aa2957501a501689cfb1e30", "CS1": "040fea54d5c6777a872e64085ec62f0eac59994aa0e68642b49b1ba27377118dfb042772a22f6468712b4541d914b067bf8422e5286b94d32acbf20036d9b3b7d2", "CS2": "04089ac75c662cddc8625ce9d6626847d25a0a26e86989d2f4081c7cb76f4254930123241dc421980c6a7ecf803456bde7c7a8b542dbc7a6c040ed196474c5da92", "HASH_MPIN_ID_HEX": "2455e617a67088153730baacd2cac683a9cdf44c7dce224cad3713f74ec46fa0", "TIME_PERMIT": "0412c8eb8a78d4dbbfa7f3b831eae5c7cccd19bc590fe319015d8ec06db4e9e65f024d6bec9d0cc3eda91faa4d9c82b6498af710dc90f9c7acc94e99230b053a21", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20226432343439633439313130366234366231326632383561346264643237303164406365727469766f782e636f6d222c202273616c74223a202239343936326634346663366133656637227d", "TOKEN": "04021a27bafc43234917bffce0ee2816ede64f180bd7b1f84833f5139b0978d3d916c45f341520c90cd7a6c1b812ded6655796894ce81e3a492d86697927b22e81", "U": "040ead1d23b70325feb5ba89d3998f05e2c0300004ff895dcb20d0f406cf5bc36604fd71b56263ee7b67039e4b3e67c75fe39dafde7e042081291e665a226023c4", "SERVER_OUTPUT": -19, "Y": "16dfca521b09b26b02867455f179d54c49869314fff6645d1ecfcc342d1a4da7", "X": "0130351cedb53a20efea5c6f90a179cea9fd6f605ea64cfa2132fc279f6d7da6", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"d2449c491106b46b12f285a4bdd2701d@certivox.com\", \"salt\": \"94962f44fc6a3ef7\"}", "test_no": 156, "UT": "04219c3d602623c0b3db9abebb2bf5a02cce901e1ca211f4c09b2cabb24593f8962003de81a05d283a24f5dc2f8cd72d78e82a436850c476ba5b9a1464cc65d9b4", "MS2": "192dfe2a9a145663d1dbec247f946ea185b2efc6cc5c9b235aa5388218461069", "MS1": "18356983440f8ecd85b9a62bab90d0e7a1560d98a9041d9e97b4abd42b854479", "CLIENT_SECRET": "0421b235829daab7afeac167dd92498a9fca627ec65ee0ec8ec6c14d750a831a3012906eb13c3840e63780bb73b5a709cfdf6afb48872f6994fc0aa5e4fea7d957"}, {"TimeValue": 1437055597, "SS1": "01d8a82071434ef470c7d4030c9cb80cca50ed5479bc812cc1b5993aa98a299d23e52b70ed14a3423a40a15d1e84158e87d3929cc61d94391746725b988b6e2f0b96d54b2dee0aff8beca663d5c26616910d186a0e5bc0bb4f08dea5fe328fed0a3f85c13a9512674225f1a99cd1fb58ccb91d9378f44c3961e116c31e068eee", "SS2": "0946d409ea78b8e11ddeff2227155dab6c69b05fe6476a05a51140d86627971d10a40158df0da03cbc730f9baf005a6f1698012e3906bd91339cbc63e6a192101e9637d5ad5e892c6b9d687d83cce54510d744fa643673fb5d39db2e466fcc71227e6931cee267e74a9495b50a6b1d9d09fa6f98547ad6ec0f18977c50341b61", "DATE": 16632, "PIN2": 8722, "PIN1": 8723, "SERVER_SECRET": "09ff570922ab01c330aaeacea626fd07ed909118eb76ad4f5b1e764f0e040a881769aa4c5fff37178deace03cbd1e19f52d10770abff8305e0b6d69fd5cc18c316d30ea79e726fcda5ca5457e37ee409934832e3660794a09d9fa54093ab93db0fa3eb0cf057ec0101efb827ec8e25bb83592163607c11289cff6a0239ec0c87", "SEC": "0402751d221c8988cc403b97684eb0c51082d6c63b313d56194f5928738325407f0e6fe95865d02fbc39703e747d19cc9f8892122f4a8b0e6871deb378a9187588", "TP2": "040b7d4f0e73d30bfe08e6a42b4d2dc1e8c1cf28478d9bcdb8e84f15eb025b35cf134ef7959b70844b9a571f21a140eb415254326d1c0718153c912b6efa89419d", "TP1": "0416758deed85c4fb143f65c4f3912458e5f336dc724f892701792f33f64eca8d00e577f6a5627c45f9b0755a6a238e8ccb8d61f433d83c60d39865a6c484ccf25", "CS1": "04166ed2a64c5f83a8f313354a0346379807baa713ced1b67b88eb810983cf7e8f215c77acae85892ceaadbaf1e791945bd79585f5d82963b88ee54d9b3135ffb3", "CS2": "041da0036407d6416ab9a26539b6bdf3d64e5a183cf468e7eab552d3c53593cf7e0559e8b4dc17de8119d5dfdd293b742c5696545b7fdf037c5d7915d29f3f2609", "HASH_MPIN_ID_HEX": "152e263bb831b7c2412f669accf07ecfe86d3776eda40095993bccea813a28c9", "TIME_PERMIT": "040a43877bee96e3e7ee3c9ebbcf29691bdb9f7b4241df2bcc92ef2f37c14df86b0c24ef67017915ff34f34714e52705d1140e7ead571189a0a0c53fbe52554233", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223764333930653734343263373936313539616139613133616438373963646265406365727469766f782e636f6d222c202273616c74223a202232633936653435643966383131643337227d", "TOKEN": "041b1e2bbcbacadd5d61dfc6bef804008d037121b43a5204ff63e6dd37eceeaf830627ce3349e414261aa7218b433b0ad3ed8b69e70d407b96ec1f213645a05141", "U": "041982403ac1bacb83e25fbba6e267a33a0ab66ca7c4f3f9a9fff8ddec2de947aa1cc68dfd6864a692c1b8b9eef68f97075b3b7f8579d094a2cdfdeb37a711905c", "SERVER_OUTPUT": -19, "Y": "08225e8f30f629159be3cb280a0c8eb4140c506f2132332d6a41194815e34f7c", "X": "1bd6e0a127258dcf43bbf7db324b1fd0e281992b916d6f5aa4ebbfc724cc0024", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"7d390e7442c796159aa9a13ad879cdbe@certivox.com\", \"salt\": \"2c96e45d9f811d37\"}", "test_no": 157, "UT": "0401e4ab61df267a1f2caa414fa97b3d248d00e942ee4f0ba0a01d3f2b1f494c8418c57b3eba6117454167f1fd790d9cb3d01d99dc1cb88011e4be62570b00f475", "MS2": "19a4e1a8929f750e95b04f771f4d1c7e7a596d4be9616e31218590d40599e898", "MS1": "19e6d48af1e73fba880caa4ed8286673768fa83abdf91a62f35dba10343619cb", "CLIENT_SECRET": "0407f78326e32506db05aac7777bfb3fd2877ba37ab39ec8b30039080fd1d8ae1f20266bf3c9d3055aa6b31827b26af0c47ddc2e1fcfc94bb30044b8bbbf00de99"}, {"TimeValue": 1437055597, "SS1": "0927cb2c772937b8b37d3fa7ab5cc54864ce770844ab5275d9fde09953abee3509fd773d5c408c21499bebdd5b039d71e3d3144b96b21fe5c2155af1edbbfde70e7a74341d161be34303dcb591ab1b3dab549426696115381af4c8c104213ffe13073aaef0873d65544ec071d44c5b95f59aa2be332fe25edc20d87364cc03d9", "SS2": "1349304d9d2c8322255903814c70c3d395d7edd3f932e061c423073a2ff06e9300a61cd46dca582424d2f44d6566abc57bfe038650813c72aaf0c69cd8747d1e1e22c6f1576d6a3168402ad70674b66d44d0a6be1e36b014c7991ec218fb12f7183bd25633e3e24082b8e422b8138a2abfcacf7b4d48aa1c69861295c4e7b833", "DATE": 16632, "PIN2": 4894, "PIN1": 4895, "SERVER_SECRET": "0a124046aa8a727891ab6a9f7e7f174ee6e553ebf4fe7003b7bedf1a0eeea9ca0bcf2ae577d08c227abe678ce7851d9a62abb6ec8de97197beffe9091b3b5e5f00105677ce6d0690fc2637810b21f4c36db5b3585bd51f9bc2943383a2d64e8516475ce60ee264025c210c7142a6e60f539afd1bc1e62e7e08b9f66c791d8e91", "SEC": "04034033108945cbfd0a4f828484a2b12e25900d46e85bf99757131e56964e568300532b4dbef2bc774e102f0c5c9204521b6bcb03b0203692380d7cf8e4d237d7", "TP2": "04066d669229468351df19b56500796119c972d6a491ac619c7e5c57b0e707f38d04811ecab4f3fbc73bad882488613f4019328493ccc1974cbd01454cd9e6b028", "TP1": "0400854a22c8cc0496dba13e7656e9e3354beb0259bb86cc5bd91e64b1f2e0dd47027dd1650d8c2478acc08285f7b0c9f651ccd448f546478f542c34bf9d08aa38", "CS1": "0409733063af1481af8384f6f9f9a5c4fdaa34595151d1e444b26c88d5f01d191c1a31475fc1646338e3d9ebecc3dfdbe6059c855cae3e5cacd1bac2cbb191c830", "CS2": "0408806ff6abdf12cec3097fcba8d058b2daae566493d186dc23e3d856edb9b67919a3f834b2936756250fa0940a2b119496b35823c1dc08ab473645bf3418c089", "HASH_MPIN_ID_HEX": "76e228da1b96dba4458858562405319ca7704012e0485bc651641556407cd0cb", "TIME_PERMIT": "041929c1639d8713f1eacaaa4e81b44f356b7164fc2a2e0f180f8bbe2ec8b679af07cb8e42d75f50acf456a6d6bcb169fed4d1a87ff3052091f82cd93fd71188aa", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223061343930663866316231633161353639333031653961366232363932353365406365727469766f782e636f6d222c202273616c74223a202265366366623337363636343061623837227d", "TOKEN": "04158cafd1a8fa6c820f61410e3cc6126bef48e49be3e0b6e6963fdc9c02569c5e22fa7dacf9ce204fa40b95bc1c7932027520680280f00a97e48b0f77110bff81", "U": "04195fe9e8f71f0ce5b4d8ba74a4316e1ba6f8642ceb93c1860f8c76b8268bb7ba07ce76862666031178f02cf07dce914222d247b3dd7618114fe4985fdbdf9068", "SERVER_OUTPUT": -19, "Y": "1e76fa4c5d11e1ecda56fd8c978214d5f72e85c1669e501861be966c8b0c4b96", "X": "0883b17cd3acd57c174ba8a71051aaf6d5c2642f6cf1fe6a2c8888c9c028c720", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"0a490f8f1b1c1a569301e9a6b269253e@certivox.com\", \"salt\": \"e6cfb3766640ab87\"}", "test_no": 158, "UT": "0423635d41fe0fb862c7e19c831a3609529c6077ef491292c07c6351557c1e62e50be874aa3eb2fe1bc15320ed4eab18e9ab9586bf768aa7f2c8d124164d745d18", "MS2": "20629696309bae7b167b9eb74c8a19aa13c8eaa3e8fc282aa050b2c04b6bbc5b", "MS1": "2113d1171248d821ee846e32b5ceb636e6bd7f94a7b4c3ff2f988f247a94363a", "CLIENT_SECRET": "040d254390ef862d5a59a3371bfbb27ae795130114c77b42a3bfb58209312c44780a4bd17f1296175d76d7e423f0a3264b986d36adf03165ab46df23a5f328e2c7"}, {"TimeValue": 1437055597, "SS1": "0e2d09df4daa3e5fd57a983d04291f1cc813a1496500e263a06012569ac28031106a80320aeeeab42ed1805f2247960b501e47fae7d26f4ee664c4a75a4dbdc71d4679cdfa20327d0d6ded7b1a62c05b16ee09a98d3910a7a50e032b479e4c43123300919ba4d4e0352f5c577862270277c208fb1d6d92cf790ab04d740427b9", "SS2": "191c001ac8ea9892b39e97d5b5beceb5ee86a5295588f7041f3a08dfd9082736189df929bd4221e84887cbece9673896952c2f6b0a1b42331a220ce323aec2081126bda53802041e8b82160e41fe9e003b6ad07c2452c4fa65aa442da64d0dbb0e485ca10cb17e2e25d8925ec19fd75df9482c43cbfbe39690d350333a7b9e17", "DATE": 16632, "PIN2": 6440, "PIN1": 6441, "SERVER_SECRET": "12a947def1f5687ab5757bb5b3e9d083ca72072423c154283ba7db459b55145b079c5345ccdfa7510f92bcc64a2b8337cf303f62cd1346d352c11b37c682f79d0468cd89c5126e605259780b7532a07f7cf79b259d8cd6a313e8145bcff560a2212f5b152234a74a23aad6b8278f35573d6173b2dae0f480357bdfea8f94690d", "SEC": "041d26c7d1baae5a321607c551855eb884e195e5b7c9db8a8d49435413425b5b6a0abdaabc613ca8c85d5043ddb20393081589fea5e464206a1ad2aac69d084d16", "TP2": "041f3ef655080cb9d669660a8f37a78ffac454cc286d8e7ffe715556d85c9b5f7d0346f22bc7a7b16ca0848611b2016ed5b03eacf4d7898afed0f4b458e211cb70", "TP1": "0422fde12d4f39279191ee0cd7c0aee935239daca5ceb051b2ed972f1dda8dd66a101d695b3cb8a654042ad238be5be5c09de726c977a908d7b0bdc3b4eefa8adc", "CS1": "040158a8ab90832a3424ac6a4be3b6189e33a6ea40b6dcc9b0502e858ebaceff4a0cdbd5aac82e8c504117636233a39a72673565834799082dfd3be4a773f1fd3b", "CS2": "041f31becc7dc502fc22e428733fcc99c69b98e893d5e60eab2854a73aacd61887027643a64d75f2a8415916495e3839748f923ac4fc70c411f659297c5a3d7424", "HASH_MPIN_ID_HEX": "1f54a3c0d9ef3a627cfa566098130e9d0331b5c267a859f3553cc1d9fc4d507b", "TIME_PERMIT": "041523b9a65da889dca6ea663bf2c7e449f863b3ef1643feb87df2585c7aa0fda817f29fc87ea6f52544b5e5e9c1aad4d8d5d78ceba673373e679abfa94d85f6af", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223431313264613536623561303037336335343033626664623563373862376162406365727469766f782e636f6d222c202273616c74223a202238643834393637656232303964353365227d", "TOKEN": "041ea683ae8b42dee883c85985f9ec6009c6945060b2c6e925167907e22311839607fa8f89ee55613c5b994adfa3a94c531934adbd232a6b7205f7e8d8ee9b563d", "U": "04008ed86127baed7ea23a3055d319fa83051924156dbf886d23cf9a7c75fef1860c5deef1c02d28056419a15418d310260d4b0e0ea73011523c3175fdf4860e80", "SERVER_OUTPUT": -19, "Y": "0e96b25ca43334eae9808896ded35f3fe18d3ff136d4a6222d5652475e766a92", "X": "11d238fd1709c68aa17def158771172b9c15448b2527bf3583d77fd54de8ac45", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"4112da56b5a0073c5403bfdb5c78b7ab@certivox.com\", \"salt\": \"8d84967eb209d53e\"}", "test_no": 159, "UT": "04165883450283ce105b532596369797f0fa5205c82e36bde54135bc7844afa52b00d4f37996aaded2e721c67128ece9e428b5238502248ef6f1f52b98f48ce673", "MS2": "1fce678f7727db4098caedffafb8cff4e87a0350f3886fcc1cb7fef5aa69302b", "MS1": "10488305b71a538509cff08dd11f0bd1d2967d7a8e16e3aa29b9dac73a249027", "CLIENT_SECRET": "040a96dae657ce6844de86f2c2aa114a3ce2598d64dedb70d508af065fc8b0c50517007c91a0f834e6034a99a3a1b4507bc96173d19e8c96e361e81a0021cb5a5f"}, {"TimeValue": 1437055597, "SS1": "0222b0ae70344d2fcfdbdf3f745fcd6f13ca6e204de3dadfa0f0d4a6def4b20114e7dee3aa82c730ba33d594bfdb2abfbf8052f4be0df2402f173bfaabb5b9bd1c4eeecb227efba53deb14415218105f4bfc6a990357fd60fb48c7dd84b6d115209e17e4d6191ee9dd4de11ab22e9fc9ec0aa39f476c2f2d9d8c6b0e714306cc", "SS2": "207d66fd017ad008d7281d5894a7da2d48fb87385c99c76da318b68ece1971160fcf0eda29603576a00de30d0ea4b79fceb494259167404a7fe5b806b730227a18a42c34b6099e92ebf0fc00836a972b70d57a72203251572797ce954200b69f07f90178f10e87e7811eeba700c6a2dd13085dd1921f51c53f0da1ddf4fbb532", "DATE": 16632, "PIN2": 3163, "PIN1": 3164, "SERVER_SECRET": "1c54ece9408511c3d7a4ea79c267700ab3838064abe837347f5e3b1dba9a6e4a1935dccf9ea725dc27da161d1c97391be60bdeb7c7284e7545acaf548c6c189723f1a4c5e5097ba7a514b418fca98f0d44ba0aa643b9af226494d900fbef7fe51ba9a07694aed64f87b36bf51d66dc377000d9f4c63d2251de596184b4a1cf55", "SEC": "0422eec87fe0d530e2298d6396400e00ca8900451c5a5578c030989120bacf202f0784fff626f21724a64d79cd2c6fc5edc1cff1b9881769178bac268826b9a400", "TP2": "0400acff93d415773a726813bd6c3229bd9cebcc00c4d17cf643ce2af82fe1237a02b3c92e604e4b080017fa2fccb9d4aa8fca2b1481e7fbe197b4fcf93c5b0c21", "TP1": "0422050316eb026fd2227822e517d7f9fa70644d0ce15a811dc8aa0443e174e76d10585bb15aa0c2801ee3242031ec2bcec2ab305ce48baa3ca3927e946aa9c7fc", "CS1": "040ca1c6b620d6d3701b95d93e0f8eb7887f0b814e660f5bfebd8bad1dfd688a5915f43fd0af3a5c4786fecd461a27a70617d7608ba612d2578eda46fc59c631c7", "CS2": "04216d347c1050bd4fb13fb260994ddcfb7ee6da27b2dddf0ec04a36c72e9d32f70f1811551d0ea439418f2120227c57087c824e2826cf971914a014c4de32a62f", "HASH_MPIN_ID_HEX": "cc8ef56cd8575779cc0ac29969273c1bcf0111260881bd37c685271b0d098fed", "TIME_PERMIT": "0416f471d1773ab60ada73c44ab3a9c873f2cd39af478234e700a5575d61e1666b17449fd9445cb28f725b3a440a38622f90206fcaa4ecbe064f46626c521f7386", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223539613332346236636334633135313166623431393239646266303363333637406365727469766f782e636f6d222c202273616c74223a202266346434626136623933663739643836227d", "TOKEN": "0404b7edf04af982baa60f481c9f9ea8e56cef6ba08efa2891eb3d11ad08b3fa40017922e6ea55c000d398284a54ceb345d6296a34da677c306bbe02201efe1479", "U": "041d11169b897e82a1fa10672a8e6269dcbcda756dd0301872124f1e188b3344910b986cde1f943a2ad0580de77bd03e606fbd2d63d1c400246013e0c7d1efacc4", "SERVER_OUTPUT": -19, "Y": "00c96c929e9335aaa3b05b91e62bc5c62a84061d73210e9a94e9d2aa3503d61f", "X": "087b6245c1b171d90c281435fa6b952b7e695e1cd74b8e3425d9341552f6661e", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"59a324b6cc4c1511fb41929dbf03c367@certivox.com\", \"salt\": \"f4d4ba6b93f79d86\"}", "test_no": 160, "UT": "0423beee2c551787015b24bd2b4027d307453078c0882c07d60cd6e76d693c080e224ecdd3b91ea80879a8377877db34d85e037c870a33a55f51c9580cb983265f", "MS2": "00b5c0d97c86ae3e5aaf4cee7aa41e3e1b343034ecf624021eb8ec8b95d9f84f", "MS1": "17cbd3d6b91915ba1ce8ac516f177a89e31fe66c787fe6e81a5f21faef8263a4", "CLIENT_SECRET": "0401305516916a196cde881fecb49789416d18dfc6fc37ccc735bbfa5de748322e0cb62da7081728df0efb242de031cebb312826de916e56152d92f10272877dd0"}, {"TimeValue": 1437055597, "SS1": "1a928bebc12cb1c0f088339a4d23952e0be0b0c2edc6f9b62293c6658eec7c4d04ff8b96e6c9a62f9e9c61337a7bff3ed4b18bc137a0a84b9deff448f3e4278e0c473532945b08e0de03c9f0c39726f88b3574adf10d7c2c39b5903cd55445e612aa323f548d69a02748374a3aafc2d794f0609ea9e8d4146bd8674d4c102fd6", "SS2": "141a14e8653aa33d894e6a238290e6011df5af9b2cb6e6f80c5970dc13dd7e1d07610de414866a042316bf87f86172c7527b0c1fbacce6be48155a112041d4041dda59aec6c6d9fe6df53581766845c0b6477c7cfa514d59a8559f4ae078fd9e15511160fa618a26c6c3c1f8ff1febf7b0fbdbb154f9a91f2e21a8ac74447d2d", "DATE": 16632, "PIN2": 2367, "PIN1": 2368, "SERVER_SECRET": "17e8e9235db0b6e6e392eb0ab380ae85ffffef226c335eada09f6edebd2fa63d01908b44db7edb77866f1e482abaa5f138d305a6162d855e8b40cbf8ba10453c22cd876e34ccfe91738f5e1e712d8a9fb2f173e40fa2a934acc30cb850182fdf0d43782b7f45818b049750a251f144340f2b291e2803e939bb468e3b9085c241", "SEC": "0405b141796eeb3365baa90290efcae18ba3df9c09844fd1fd7cee614bd34db51e143ec1ea84333572575d2569f71d4ecf3742164cdbb851e47bfc453220e0dc0e", "TP2": "041785b6f7df3e33645caa4cd2736427f622a0cf104cd3d37f6b6ad9b79ce7b43805098f923eb38eed50927b3e235c86c777c82a484f482627092a3710f072f2f9", "TP1": "04113f83303f3abc1369f47d3946705aa6adf3fb39121b6913716f3892ae2ee86f1a11b2bade64161b5b93a190a97b94e6e6f1234c0475e06bcd0143d72a1fef8f", "CS1": "0404abec23ac29d3bc177a464d27113d283234493607928ad0e358bc81fcef7405171256d2020d920e02a69c94a35395bef377bb56635f8a973e722d8b0b099f6a", "CS2": "040c20c9493ee71791f76da324eba2850e3598c276f21534b57cec59087ce27b4502bccdc1698c73ba5b7004afe5faa463745a17a45b4b313639adf7cca218736c", "HASH_MPIN_ID_HEX": "e4a83dc66bfe1f865a5ebfae2094068d145122e4b59b90f62efaec3a61e86afd", "TIME_PERMIT": "0414c5221f702585ec3e2ae1dd4e0349477b8016aa2d318c92d311571a07d3c84300b5a7044c19245ba0d99aa8634baa1fc922eab61bc23fdd441b52304669593d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223962353265323235663630386534396435616364613139393637363065663530406365727469766f782e636f6d222c202273616c74223a202262633235393863373637656265323461227d", "TOKEN": "040b982d92816ba90aad852c3050f8c2b68265509f6bc8d65a7782c5cf0212bf96210fb8bff069e39f76cc0610ed4cd7e04468384c655ab4cfae61ce0124cbe5d1", "U": "04238630bdc39160f09112a91efd3c427b15bdbd94b70fed76170a9267447bbbf00c1a8bffabd6248a8045c4340aa49000048dd55c687952f7add8bd1afb52bf19", "SERVER_OUTPUT": -19, "Y": "2103a08ac0b89607f545dd65992b6037c57ef522fa98939ca33104f560eafb24", "X": "011fd58742f6730d472c4c969bfb554091644857b825757b2fe5561d886b2b5a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"9b52e225f608e49d5acda1996760ef50@certivox.com\", \"salt\": \"bc2598c767ebe24a\"}", "test_no": 161, "UT": "0407d72646b50f385f4cb6e5fc4e70b8be9baf2d46efd9a5a9edf03d9241c277d708ff8609d3005619662a5ee4d297e150f51738d69825f86aded7e80b20da657c", "MS2": "1dcd5af374633d24ac2aa051549c4207cd51e4e752ea002c1bf565da2e78cc8a", "MS1": "1dd815be75a2bcc96fda34eb14f65470ba665dad9a69fd3abe64862e793eb321", "CLIENT_SECRET": "04123e884575327751c9821e1d511707323a96eaeff670d7ea4a7215167900e1b51ffe1725ad9737db2e38c1df4c0439f3f3879ed4dade3fcf51f47dfce34fe556"}, {"TimeValue": 1437055597, "SS1": "0844a95419a74e3e1031b351f2998ff3f252f4b6c435cf13217b4fa52ba48deb104ec9edea27e9ebaa1a490069748d75ae33dd8d4935cae4e80a87e9e6c8893218bd97674af0b4e4aa251fab2054700e7638fad16a1e70d8c91faacd6c73f71a0947169e826aa70c260e7143b7c96566ce5e52ea945d94b1d8ee3a775d370458", "SS2": "1b10b9c697d9b5df19e77b56562266c97817cfbcde65bea031438855052761b621867ddf787ee238a5f8fe5185e5825afd7bf70ce102e53ddb02d8a1018a25bc0f471079eed2dad2754baec74eb8e59394e180cfd032d96bdfafd8dd5e2cae30078b3c407fb5cb4ced6af4d8a2c1159e8c111d5dde1fec09a07c28bdd235e982", "DATE": 16632, "PIN2": 5563, "PIN1": 5564, "SERVER_SECRET": "0ab4c90b12f2464ee6920f85bb9fb68c9559795edaef1702a897a11fe73a276b23891e29f0e27ad4accd53b4eaa7d42372b8f2b453aef36a82a9663fdfeba95e0a5165b24c69c0c89293dce2d9bb05e1e44595e3f09936d8945b76c896430f34139db6f214b2f58bb6907ec08bb0c39f5c93c877760e463362fd87ab1bfdd04d", "SEC": "0402570c28e874bc409ec2ff882173e2670ed1e07d2b37b1adc3a722637dc9737105fecf0e946971fb28440b5ad3d121f2a2924fb41d4ffef7f2ff6581d1fdfbbc", "TP2": "0406d505595c3522978fb6d47986bec918d1de5d8de17440b71bf1821a8f086cef2236eb091cefbc8a2efbd03f3f09d37ae839c1a91f23ea587b6213306c4bf431", "TP1": "0406098fc78dddffc2acd45322bd48ddcd22f3d2e895b82f3df74afb78d9ab54ea0d613e4595a147c415f4c3b28896fa0b1c7341197fdac814e8eba186889433e9", "CS1": "04216f73ae4dc50cc4ccf0dc1108fed9ac51de2a5372fa793e4f6056b72a2a21ae23d64023600f1233b6d4c7e2a93d9e52bf448cd92ce6e68ae6e05d5586314194", "CS2": "042092ffbb1472317132345b99386d8e1c341fde0f8b45ce9cbe873c7f0ddc56531a42227514edec8e2af1d67d275b8870cbaac8ea0658b53a212e8324010a4f3c", "HASH_MPIN_ID_HEX": "1bd1d785db0237849ec4e7e9d374e3e62ed3c88db90552fc6a0e78d3e92f7a97", "TIME_PERMIT": "040ac54df072d82cc71ca974288e703796e18cacf4ec094738a867595e031037dc0d1cb4a46edf2a35c635c282e30706681690de735658780f3b4f32260f975ec1", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223536613762366463313937333436623762613464656430636262373561666536406365727469766f782e636f6d222c202273616c74223a202266646165623236626564316163373734227d", "TOKEN": "04020bce64e0f3828c3982d7748627822a67a19b2f2472b08aaeda52ba2c843ad804c7f412a5cad2cb2c48b84262e6879bb159913282260cfe41c33e7369422436", "U": "0418aedac09266d0ed6d335864c1f23fb2b9c87d13f18c16bdcd5d2eeae611a23e20d2f5f8768a74a354f3f5c85034be0fe9775a7e822a80adb711b46cb963080f", "SERVER_OUTPUT": -19, "Y": "200b3ba2085df810c398c49f7dddf76d832a0c1eb41ada6f1aeb08353ace98d6", "X": "02767e158395d3bb685dbb51a492e09d16de1ecb46abb21ffbc2babcb2de2306", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"56a7b6dc197346b7ba4ded0cbb75afe6@certivox.com\", \"salt\": \"fdaeb26bed1ac774\"}", "test_no": 162, "UT": "041e4f3054535f124e18fa69ed43f7d46a31abd0a0dff9126a8f29c07c3fdffc10005118c9b21c75825610b90525bf186c4a96413040f120b61bb239bd01a12ee7", "MS2": "04ad1dd96d942a4a5e9db1c04f3796ba113aeff893e3450047373ef0058ee17a", "MS1": "0d931b2b10d61071b71edb3987c8658143aac6b86f51df2a7c66b589c9cec16f", "CLIENT_SECRET": "040032a7d7d059d2ce2a0a95060aa58b2975599ee23721a69fe24f3fa1fadd2581184c79ebe5debd27c00a4239fa21a54645d7c4645394ab34e67ab2da0d35ad39"}, {"TimeValue": 1437055597, "SS1": "05249c8c78f9c43eb2f89d0efeeffde6ece70e72e20e13419500bb6f7835f9e01562d5b1fd96fccba745114dad7cc786455c91c60cbdf22d76bf379610c80c281a7e4bded4f96f599783274be7a3a43100a89b0fbd37a1ae7b3bd5e8c2a8e59d0a6aa7917ccc1aa040923096930b79ed65b7d2fe007a934300eb6da675427df2", "SS2": "161eaea0c427b11881956952a45d1e2680ca644e7be336f42c14ae26d9c9dd7c11ef144e1ee2816d6d8ba17d767e3c4ac04e861041689d920afc334cee41202a07a9b38079d4530d4bd91642a9a8e92b351ca96109f97941a961f5a7b903e78e160eb5a166fbbe636b0667e664273bfa7f439ab5f183e498caa0b47cb71ed1c0", "DATE": 16632, "PIN2": 8939, "PIN1": 8940, "SERVER_SECRET": "016712e5188b099ff9ce077676fbff5911d7ccd9ffebac9cdd3c35ba3eb9195c0e35fb72ec11d3231440649bc568a0e2cd411c63ee3f1dc028c0a39ea61a2dcf1f38ed0bb5ef9a23c8cfc2f492a74845ed0596a1b396f3d6dc4a27efebf27ef5031bd714981a7cf09ebb881f03fc36b99506ce81325ac40320dc111a63347f97", "SEC": "041c7276bacf8cdfbd937ec1f58e437392f3dcf8ac324d888b13ce1cae2e5af3fa1a4b6b9e018f4c3dfd0280daa7de2df0bc9297976a167205ff3b2b3355338cb5", "TP2": "0414b243446f64125886e9da8e7b19fc35065133a583e3f4ffceeb659298ae982113bae748b6de635c2331318074b3972ecf17e27a28afb269e873c4cb8c291356", "TP1": "04055b6a23898a9627037addbaf3db48100d5834e63122f8476b32dfc7c2001fcd0426737f621e41d760f1cbed38046ca5ab3ce7e29f0579e27ee8f2f06d7a077e", "CS1": "04219379a7123c6a1cf5884c23ed7d799d507dad64279cfc0d58edbe74d4cfd0ab23344c0b79cb4c37fdf992890828be29dc0f1e85a040c88b0f70ec51400c0f1f", "CS2": "041be7d7b47b0f1d4ca60f82bfa613cdb930549cd14c181aec036089fb6e4c711c21fdb88371826e48d8bf766c35f02c126684d7b49a17484748aeac5ecbbdaffb", "HASH_MPIN_ID_HEX": "70b1a3bf5af045b7d8d62d4feeecbc099e8044adc0398a7b99d209348bc8de2e", "TIME_PERMIT": "04014ef477a18c62c5a2275b47ba83ff4d68a66580e567b9b7b1efbf25a56fb90922b57504fe899fcee02eed8320781e778d7b12ca902d0438f824502ae78967c5", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20226163346165306364343932636661313834303534333333613336356266346337406365727469766f782e636f6d222c202273616c74223a202232333836343563643662613366386461227d", "TOKEN": "0423939d3a0ec693d682c8a88cf138fd6b8952aef0726c118d6ca43d20b25538350809eea19cdb98a7d456b705ca821c066bf01bf49edae42d1c1618c3bffa6fa8", "U": "04054ad80aa5837926efeb7f7c90dd50606fa15eec5da7fb48329e1eb4bddca3a91463a66f277f7966d41cff75e175a3a0e96bf2fa092ceb720d141a481031ad65", "SERVER_OUTPUT": -19, "Y": "22bee87f6d102b428a5409ee6afa20f47c878753853d630a900be647c5780942", "X": "12c796c9fe061d1184ace72910edfd10e2661b9dedf64d45d6ce776d667c9ea4", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"ac4ae0cd492cfa184054333a365bf4c7@certivox.com\", \"salt\": \"238645cd6ba3f8da\"}", "test_no": 163, "UT": "040b9f50c4733da6fc5f134af21da729d4d00d26344b7d7f5c542d88b5c873b0a703c0261ae824cc51dd40fc5c86ee914704580aa41fa3d1fc96f4f6dd0db65bf6", "MS2": "1beeb5353aa33e327c0e8c73c493d3a59ae0ad78d78416ce0da11273464fbdb8", "MS1": "1a553b43d6c11ee235beb52fc21d7e1ee0ec2d8c0a89d41e3f80e5ebfb8363d2", "CLIENT_SECRET": "041f0f2f7501c4081ca48b71d57b62a40520f7de92c92a55b2d9eb15b6180292540a5d911d1f727dc9f75ded2e738a2b2847414e8cc6187a6a50faaecd245ef7b9"}, {"TimeValue": 1437055597, "SS1": "0f9dbab6e0f26f9aa60bbb085fef54b8f416984f864027c7c0665b9b696c233f02439371e39d8c93fa94ce754e83cf750cc93856110281d520c71e558bb37d30060083d6322721bb550446006d2e09c62b83351defe61f2077ebbce623c4a8080cb9507598928798cfaf8e3e4b9102fffa158ab713c7017b8e24e97afba1c754", "SS2": "0eb7206945a67c0767266e40b1d055d1d2281bec19aaa75bfe4ca0d4d506253d1ca5e3c4cb2dc27ee1e697c50828fc24d92d3ed24d22131ef936ccfabfa47f9502dc3e2062dd4462b6fef5f12d1c60f0a637b91a9f948b506d5b41ed3b2e4afa0e009adf9353a9fd535b8652b4ac546cde0bb6bd0d6e1eba4b2b3f9da4ed4094", "DATE": 16632, "PIN2": 7457, "PIN1": 7458, "SERVER_SECRET": "1e458ddac40b67e471d596990744d3be22c2aa6a9a98763370aac366637eb6de22d3049e1c3c343f12afb236c6565e4da548e5d6f64d1d701abf99feb5ea2f6e0808f4ce7f89a0036cc6d381c463a9ff0013eb50f87d75b136b9b985c353cde81e82a741207ec465c3da66fc9c49b05d5913210772533eda29be6007731b0972", "SEC": "040a8915226ca4f3a0b463228c939b43155f2e8d440b7e9155bf78668eda1faf870a656a355af90609cefb7dabda556752e4c863f47b1028cc7161e2d824b2454c", "TP2": "04197e806061223f017bf4fd3cb3c7a02770a395fb2979600d5df29f9886639b290af1b551c93f14383f869441c81bfa10b4644a1698b3a79da515d6c05cd32825", "TP1": "04185d29113187ff91bd4fc0d379015a6f818485d12f440433a16aecc9bc6fbe190a1ed6266cda6eaa94bf2966f59de14971d948865852d3d902e1f8a4d6675935", "CS1": "04144b899e3e8e0c977940a3d0e912d1fd5cad7c8738d02f134786aa067efcc41f180389798ca53ee3f2430ea5f7c784488ae19972946181e3f719a5eec2488d9a", "CS2": "040fe3226756cf21a792e9d18b29bbc70634476444409b46abb783ecc807f1d60d1160d908fc69c679928028ae8b5251a34dc9d6610e3ea313cf11c5753b81f120", "HASH_MPIN_ID_HEX": "f4d1fbb59cd2c6bfffdfe3a5783abb7ea02670857eff702917aac032fd3294f4", "TIME_PERMIT": "0417cba401db4f9591778b3db8c6a9dfe65df4236f6018cc8688a1cdd613eda68421bc703c54357fbe138e5aad53e2d5d45481bc87d59d27b95a7e303e8c192bf7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223334623135613538396434653561303432353566393465323063353464373338406365727469766f782e636f6d222c202273616c74223a202232316462326138316439633039323339227d", "TOKEN": "0419e6f224048ab45a7bbbd1e4552ab0c3393bdc3ca9807963a9da9eb27a7576b421f820df36560219ac524376c25c2fc737cc61f28b3c7432f34e759a5ff8d32d", "U": "04106c633807973aa142a88872733078aba222ec40eaff3b53a772d67c2d3191b70ced05216bb93fcbdbc830b8b649c3e56e02562cab2605f362cbb3e1760747ba", "SERVER_OUTPUT": -19, "Y": "1ba4ba39db3bb9009ea9e277fe72bc324c9ac5fb6c047c5c81a2ae959e851e4c", "X": "0962094ad35f6a2d7691f435482125ca2c7ac6637863632881eb6a8bc9d413ea", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"34b15a589d4e5a04255f94e20c54d738@certivox.com\", \"salt\": \"21db2a81d9c09239\"}", "test_no": 164, "UT": "041ee9595320367ea5db8b9484bee9ea79a76438036c738ee249a210fb00601eaf05ddf89a4f35564e51cae55dfdd66c617953350151529c4bda22e6de60a80310", "MS2": "07f36e36dbc187a771c17f7f156c404feb4d34ba8002cd4cc5683701a19f3ff9", "MS1": "0ad56e09e0f80286c08459dcc1d3c1991f0928751a7e24f1527df2c2da74cf0a", "CLIENT_SECRET": "0406e2096b084adde86f1ceac40f882af1e503b6bcb739a6adf73de558434087bb14665b1529ac2b9ec06de04794bcf26599bf571fd808f3300a0c2f2598a59771"}, {"TimeValue": 1437055597, "SS1": "11e1bdb6e0766c0e29e99ca8b377d92434ba3c5ec63c9307924993648e18568f032a091246f2496b9abe3f952be9d71173c378a0e901f5b656e3879e5d95fe14059959cbc3b321a0043ce70102007e70e666364e683e961ce8ce1edc8fe8bc7a1930e7afc0d4cf54380b9d1bb73208cf9ee3cba8cdc98cdc9fcbdf4eaec9d84f", "SS2": "0460e02e9186fd97f9dcc5b80d48735b04531f1ca01e3e9b5af8d7ae2427459011ef40d70e08f07c3ec7b3f1aaabb9d306de449c50124fc05f8fe50ef1e184d70dcc542d52fedd313a5387a7d3f17bbfdb57550a5702f524392091de7ea9ff5215c7047a7995194e5f2702e0163cd1cf92a1372a314b6912cccd8fadfb3f9866", "DATE": 16632, "PIN2": 8274, "PIN1": 8275, "SERVER_SECRET": "0a624d933b60cabe833ed8d8ffe6ca16ad3d711e8e3ee606bd51b97490544c8d1faffedd6fb9e737be666f28d7b88ccdceda0ea1131ef403fb7e7aeccbd880980cdb36b11e8f84d639b3e56daa1f89ff9fb3e7705671d2a66a26a7e2f0891bf31cd1c0e6ce86ea022d02177fae806c8d9f167eb029557763f7965831c1998e39", "SEC": "04169da81530640acc16c713d50b890a99f59e9d18714a133d7308e88e9b8284e119b14844b7afa4d4111fed078cba5404d24401fa833e5af2b7c6778203f0fd01", "TP2": "04154e30528260e16622ae485427a15b22cfe6d3e1e56db2e9d7672b2b2c0b116712ea850be09672677b1db0801d27717c3a75e80881e48ec0416506c62410f86f", "TP1": "04074ade39c2d6b9c31ced290ef5568983dd43eb7a54b480a6394897f1d892a0b60e9e93be7b20f49b51efb703d1544711b00b1a23f0fc8d5d1e24414615d69b7f", "CS1": "0403e695af488a5cf885e4ec9d6ac51337cb9f3d6f27e45b51e016cbbd436a6d2d1535d3a7b7a71b3cdbf08a5eba3a5fb4f4770d2d85a03a8e0db7d464ba4e2b88", "CS2": "041586b94124a61476953d3b4e029d8b86dc44636c586241b0ab7702b4d794b29903cd3ca9dc7b33442e8439af3d7a346c59ba81af21ec6e363bfff8fca9485acb", "HASH_MPIN_ID_HEX": "6c37f9c074984990e6f0256ea9b4cbb1c3f1199bcd5be2c24a8f67b7461c5663", "TIME_PERMIT": "04173b356543eff7cb97d7710d67f12b73b3087b9b6d4268506a0d1b464cfeb90322ed72424b34ca295d58d8d54c28daf847d0c5801caa8471a8fd2d925480af08", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223536383465343961353137633639666161626561653230373034366438363330406365727469766f782e636f6d222c202273616c74223a202266346665623463643938366333623761227d", "TOKEN": "040c031102fbff1dcb28e3895933492fcf6677bd0b75d01533ce6f3b1fbc81d0dc22657cdc4e2c9820ac45d254ebbc2e7afabc76fa372cde278350e8b6475d7cab", "U": "04015243bc626d0edfcffd9afd46fb43fdf0b5456cd7b622d9ecd0ee51f70dd1971a78e69f190ff246a82d5d3571b1d6b73d73fd49d4811d1ed35cc771e0f61342", "SERVER_OUTPUT": -19, "Y": "00df3123132f164cdad6e68d73a27a8618f703b05ab04109f68db7cfb3c139c5", "X": "0450519d58ffb79d5092fffc9a994fbdd1f805c5610302478fc768d1d1acc20a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"5684e49a517c69faabeae207046d8630@certivox.com\", \"salt\": \"f4feb4cd986c3b7a\"}", "test_no": 165, "UT": "0423e5a6ddd401e76a16f6c16cefff2d82430aec1f13a49ae78fd7bf81e6fcfcfc0a20086a7d17b118ca7a5cc12cee4c1373479221a52fa775f3c8c6d79d5f1e1b", "MS2": "01799e62fecebb023dc93091309983a61aad953d23ab4ac6769dc91ff6ed3d5c", "MS1": "12f412466d75c1f9cbc10b3f9b4d23c9e12f761f4b421fd590a934bc2f860fd9", "CLIENT_SECRET": "0413fca66e5404fb269bcdbd773618cd9d1036ede0ee1a10520ba1473ce534fb8402d89e399e0f5a8d476d5df82528ce7aa86a6528e890683731ccd3afb496ba38"}, {"TimeValue": 1437055597, "SS1": "20ef91a225835349d422378096d272c096fb5c91feed80ff330d20277989d4170fbd121aca6831baad353598936b586b93929138e77102e2d9306ef51f854fcc07ee168f0a60c4306c896f726ada9566c6214e1ed5813d21ad8a0e6b3d3ca3c90b15e5e2098cbbcd40a33665545e35fd42e42f07973a535131c8b0f883d873f6", "SS2": "06480d1452ac19068c2d1152c24a40be1c93810393f00c5f62ff7f3be6a03e1505a9064876ebca434eb91ab5db415fe8f68dd201744fef2bdfaba9c439ecdd6b05d5a6724e53b66c609cbea74235f25ab9eb4c6855c00424de7b739cc4e9a8150d8841c3c969d8a2f454d07c5d3a5948074434d0dee00c1d0fd6c3075cbe26ca", "DATE": 16632, "PIN2": 8400, "PIN1": 8401, "SERVER_SECRET": "2348fdb5986423fb2a103665122c3c5092c7b79e24c69faa45b2f15fc1891d2420f774d1ec328602b44abac2670f3f1679c030ea74e085848457a0272ec516a70e4f0ca02f919d2b6444d3e403718bcba38a048c19a3a77b3498a014d8b15974216394bf1b3b0f6597045553c3388acf21c8cc242df4fd6026bdb2675a9aaf19", "SEC": "04169af15775cefb98d282f76b30db1dc980977837bf0817379912e2c77a6ebc751cbd866cab9968be0fcdf8790cf0a1d2313f091c10eb81201288fa3487f552dd", "TP2": "040557fc96e2e324f61162d290812544570c666d2cc571ad2ec90fa01fa7f86f4a1bf2c1f02fbe1f056249ebde4cc31a7883296b9bd20482067fed5090eb3171f2", "TP1": "04184f8e9f86afc7c33e8c55e908e58e1f0a686b2f8e6cdab0a3760c172a2254f61def6ec784110b4f90c368e7d7df2bfa280d447ac9ded5700029e3fcf41fcd67", "CS1": "041e55194800ac1719e32d2f5bdd4aa0e5ba6715f1d9037d275ffb3b55f5bac99623098dfdee517ff1a0fda760e0be2e2714ab87dc2c0bcb0bf065aa7566ef7c17", "CS2": "041aa1d08ae14cd0cf2232b969839e70e2a292fa56cab12d18597ab0c34bad44540da17ce715d15eb65bf359d1b897a53a6eb0501ae4dbf019aae5a4a31090ab3f", "HASH_MPIN_ID_HEX": "74d5f06e7e9b9395fda107c9f77b14dbad826dfccf3c145ab5925b54e36d701e", "TIME_PERMIT": "0422ac00361e3246c87d683a9bba9b6a31403a608610d49c94043cd7d11963786417a3a3fa224f4217eea2bd7a8087baf191c0b1b39cba0cdda579ea45a753526b", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20226264633161616230326335653864346238383534303061646536313132333431406365727469766f782e636f6d222c202273616c74223a202266303465616161366165316364343137227d", "TOKEN": "0422468559846b8fb538a2d0b965f1cab374e314d6d52b87ec0b12a44cf219dcd909ac679dbfc8509c9f5cbd2319cf3fb6b0292d52b9738bda73614e7c7aa0d741", "U": "04207f5f1d15ff8c8c2bf4a91c712d24f46212e2fa732d5a2eb95f33b3d798e3010bc7536c0cb46880812c16aed586ded8f19ebc852a1e2f857a3eb5a99d1c0b03", "SERVER_OUTPUT": -19, "Y": "22b61609319b60d1c3b88d9ed6ff3c3e5c4eed6955ca51e4b6e1be817d554867", "X": "0aba13b222cf8161022957d5f98b8a62f37ed1debe556640f14a2adbf84bbc6d", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"bdc1aab02c5e8d4b885400ade6112341@certivox.com\", \"salt\": \"f04eaaa6ae1cd417\"}", "test_no": 166, "UT": "04031e991d5b6e52e0b2acce983a183c53d1c134c1557bc195854f40f647c3770a1b9fb73cfd26a2cec2634c068700ec32ae210afc523eec55f1e85035f342407d", "MS2": "00190d2b2e223d420b50a1b36384b7393ec8cbcb9236bce62825e2dc3047d551", "MS1": "0731bcfd8dbd211b0d78c5be9f7d1af92bf48c62018437c8ea32322cc6aaf295", "CLIENT_SECRET": "040654548e20f1aa309c7c04078bf1f7e2299f214f2f617df69dc3be897a5a6c4c20b4c5f27bac67687bd3f3e4ec441810067ace01c170e42776d7e7d4d91a03bf"}, {"TimeValue": 1437055597, "SS1": "226a60fbf5142ae33168d43b91f9b794df5a9bf39272fd981ca7e9e41c9d03a20700dd9531ba6e2c37e0bb4c5f4ec9d87a366b0969745613b5d51b46bf4b48ae02bdd7b9d62303c74c6443b89f25264d87679f1840ebea813f6e2cddedd3476f1be33dd6c758fc61911bbaf7be620bb447e4577078da0f9dc7fa7c6274820858", "SS2": "01da5f47e51825a3df46700f7e0e431b372cab590b146082170180e9e4cb1ace16bc1c68b54814bc07baf030f83f037fbc9051e01c9b097dd9dd44ff8fae9cb71ac741bf752887d8d71f41caddbec9aee3fecb5687970bcf3008abb2e53757bb20f1a527fdebe12969b0f77f737a9e0f9d3315bfe9111368a3817aec46a58de7", "DATE": 16632, "PIN2": 3131, "PIN1": 3132, "SERVER_SECRET": "21090da3a48a7fd7678b5c9632ce0f080e7eee8f3e676bb514887d1ebf5ac7af0e252a1da721c3d10feee67f2f9f835e1db1bb8bd4ca112007f74dd71669ffd909ae1238c0b620c488f7b442756e03b426d92f1409738f9a48f9b11d1e6f7a3f031a2287c56973227b296d0d21faac0aad4b38fee1c96b3e1fc57b684f822d0f", "SEC": "041e534e3d91ae3aac4d50048172c541d96b24be7f99271fce34ccb07bf06adc07099fabe6c3042d11deb7cfffbc60013d4513b835d34de0baff4273097e3a4a90", "TP2": "0406bd06f342c04bbf09bd8043394a35621a33c182c1b75f102578a850826fd9a8024b836118b45f1ee15a3534ce0a2bd9e3630e5987cf4d27be434f6fc4332e71", "TP1": "040e1073c63f5d237ebbffbc94ae21645e7a1f1e48e4eaaf9f409a9af8014d09070ac3d9a79197b3d591483c86eefc09b126da39ec0b70cd21406872327dd99b96", "CS1": "041110e4e7f2813021370652b2035b225a90bdf0adbbac21213711a0a4752c2b2809d6e292f12e2ae88c5121acaa0463c3c7feede64a8db71f5d765c4df07e4697", "CS2": "040adb0bb6bb285dc28d5ecdb62c943686e9ed658c47916874a184fafcabbedeb61e28d0d8deb7b4d4f1b36c838572d69e2aa1e43cbee8f68e0d15048ff65e20c7", "HASH_MPIN_ID_HEX": "d2d435217a862738cd5a2df1f647f7bf6fe45de0608098577457573ea08693a9", "TIME_PERMIT": "041c83b1d0eeed3a4d866f857fb74a82fdcbeb6f879e9772befef859bfda33c44023f29125a5869a38b1067de2901bdccee6d375c85c8e5374db58e8d451d8061c", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20226538646334373136373239366565643130316363336562393939613164316231406365727469766f782e636f6d222c202273616c74223a202230353535313939636130336231646562227d", "TOKEN": "04017c91ce13770ca33de5202ab1fccbdb1abace116db56cad922e5926690785ef01fc2c01899d3b62d59115afdf849c289ddc1e7c398fa72da4ef123c3e9b534a", "U": "04185ff31e3d732b2787555fc6fa1bc4938aa038adca6df8a071755b2ae5959c8f1b43aa7df5263aec5236ef5da4fb26e1e7cb020cba4ea9f9c1ef9d06031d90bc", "SERVER_OUTPUT": -19, "Y": "233edd5ee030481db760db064fecc38bcf5b7fdb812be9d088f9300d11aa793c", "X": "1543b18bd59d52e585a7bd5981eb1cdfa2339baa28e84fb8c98f6543599a7556", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"e8dc47167296eed101cc3eb999a1d1b1@certivox.com\", \"salt\": \"0555199ca03b1deb\"}", "test_no": 167, "UT": "041859248d127b08140d03b95673772f13a80bd17938214d9baf433478f635fb7c049a6859aab04ed4a9d896b0cd04e645f65bc1db04efe9c58344ef7c3e0d55dd", "MS2": "018c6965fa83ba286ca0c4a960857639d9d9597a60ce9a8fbb9dcb53089a5bab", "MS1": "06974d4e644b9fbd8af4e5dc9439b614f20183913a37e1c61398d173b70814ac", "CLIENT_SECRET": "041c01ae727007d758de21c5dbe035f6f4a962dc26b078af3e32ae2f6d5334cd491e22a9070c678d653657d181129f32fe9c73694ad6659f823318c0e4060f5d19"}, {"TimeValue": 1437055597, "SS1": "0eb0eefbb1c6bdf385ab181d969bb170a74356f895c11b28ce1bdb74abc2faab1fdef9026c39b70a198f27c2bdc4f53140e28b34e7c9b404941ceb31624499f01e25ecff5a6410cebdedbeeab5e68726f5fea62564ba988d758d4d16bc23ad940ca930ed130772e9b51166b289c74b8d28b6de617dcc23c54a477364b1d24e86", "SS2": "0ac1117dba931d85467355ad9ab177e9a2f49f9ca1f013e7557804e07ee3cd2f07147330e83ef4b62947c7d7b44c9050d5e97cbad8329ebe5251396109c4ce81191ddfb2fb21fa88754f5f8e119fa2a16bcee21bf44cabeeaf8d638e47c7ce770df3a8df8833f627a7a345b67a3a7b7e667c49b49964204f9fe1c21de1e820dc", "DATE": 16632, "PIN2": 5795, "PIN1": 5796, "SERVER_SECRET": "03383c77f51b71a38efe1e1115c48fe9aecc0128e0b93c2fec8123b6653fdd6d15e9d0d95caa3c3faeb20c828d48e32d43fd0dac9c22015f0677c2db6feeec6f04343e1423d6ab6d019becba6340580edee7fb75f2d9a491f9bd5b1030adafe217d053c2f3a7d02ddd890c95d3773026cac494793e591edb135177fae4deb13f", "SEC": "0414fe7f8b6fddb7342ae5211b316cd021fff49616b7d990a75eca4ddb3532a9b510d7ec34c30130a5f016809176fee3407fee928df6a3b89941ea4eee6a5a87f4", "TP2": "041f0a5dc89bb4cfbda75d528edbf7aab5408f5e0866d00380d1faa944c1ec41b713c11193b082aecee81749366601d8a20cb9293f842a0e12976105d46587a7c7", "TP1": "041cd1ff9cc59c6071c051ebb3e60b0950ee14d8402f9c9ce71353c406f5b5d094014b993cd15cf11cb8d11fa92094fdcfcf831c237072d94569d9fc939de8860a", "CS1": "04131d842b9b85c0a56e46878cc78d253e6ef6a4792c596796ea87488a4af73afa07866b815edcdb219e2adcf8348f89ce76f49895bcadd224d157434ea2a49092", "CS2": "041cd0da51d0353fe964eb5f3abaf3eb190191c5e3f22f770a1226c085481f52ad06c83750d877b4ac16e2175defe23a007e69a082758df0627555ec5a1e01f9ce", "HASH_MPIN_ID_HEX": "85857cc4263cb6de97facdb351b713da0fdbbce9de61b506d2bf6ca1d55d7a55", "TIME_PERMIT": "04135fe7a0f992e9a032e9bfff940336a92425ddc36e8a243d38c32c4b2410a6500944ea420de5272da6be1e116f109f067b0fc22edb0782ac78f306ae316c1415", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20226663633134666366346564313465626632623330396366393136626639356230406365727469766f782e636f6d222c202273616c74223a202237336363666139396134386237393630227d", "TOKEN": "040e4e18a8968f35b7f820e57466dfecb27e037fef63892f2c97e63032e9ce7874016c567a729034a3ba6ad6e04c06d81cb8154855a7f688ce2bc7979116f8887d", "U": "04193c8a0a301f9a1a6388ad4f909286f7802f70fbed57a0fa5878a7fb1d1e5fe215028b822dbee415d8597664aec10ea466deb85c3588e6c4d25e3632a08312f4", "SERVER_OUTPUT": -19, "Y": "21e042eebe4b47ce18391089b58223a3e0da9addb4ff51a6540742af6394fd87", "X": "23721058dd8128429f0efba42d9abe6b701b68cc916031bc082302d226a24185", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"fcc14fcf4ed14ebf2b309cf916bf95b0@certivox.com\", \"salt\": \"73ccfa99a48b7960\"}", "test_no": 168, "UT": "040a8c6a6aab4cf2ee6b7526e78be75dc6ae3f338424b39b8ed560d262f64b3c1a11af104e6bebfb362557d2e31e027bf7611e44b0d892b5e69eb53de6a366fa13", "MS2": "0487069986b462bfb2bdfdbbbc6aae20a41b678a02f99a3695e0110801693223", "MS1": "0cdffdf8a8cf3464f220b16c67436a56b2583d59edd6422bb450925a0a69cc9c", "CLIENT_SECRET": "0418649816f53bcb659ffc2c15b251ec82f16d43d969063241605c3dbac3d6db46015add566207b4270be028ca5268174abfe34894468b0117cebf2147bff210dd"}, {"TimeValue": 1437055597, "SS1": "05fe8b2714ec68943535aa710d3d79ab0e428bdd303cf4fbabd07cf1d788375f1ae0d96bb25ebcd0f7063dc7f0452ec2f94adcd387333d28dfd3d250f93a110209fc7e71cb1245c0f62089a344c464a596ae7b6d44da6eafc07cbd3e4ab492d3043b019ad361902b22f4a27c7599cac92c674c88f16782efee74c8ac6f230c99", "SS2": "14330b27f596b20d138175b5d9b9d7de36689d565c0e6a578d365a072d289b5720b28e3acd43e4a769d275b424e3ffb5ef8133d82e6dc67bf5d7bd4bfb362a751ef0e78292f88c2231e367b8a86a6e0c56f12b44b4ddceca58cbeaa481173bb42294feaef3fc20f88af3567b58b73c313529bf42fdd5ea3ce13356dc830b2383", "DATE": 16632, "PIN2": 3215, "PIN1": 3216, "SERVER_SECRET": "096e344cc58b421a6a7c714afff017ce5e7273bf9ea2acc08ddf91258cf8e5c908eb93f2f84bef8a6d07682ab49f3903a835cddf1283a635c8707c4b188937180c429436b1c224faff01aad6545d8ae0d864cd608e3c7f5305a2e39e08a9f076044ad7981389103e590932c70a107b61194aa9982f0632fb2bca4a11f8528c84", "SEC": "04178676e73ca5c932f340d1e4b98ea4e160de926f785416a0bc8faa17a78b5e5009010b710de0c5ccbfd92f9cb73b9f9d9298fd0f7105c50f0cfa42094f462a37", "TP2": "0418dde7415279f8ba3ea2570ecb5df6d0f6ec6fe8763336e98946e059941109a6021c1165f774281cc6d87f65ef78136e1ad4db3221accaf5c0919a910dc6d156", "TP1": "042034baf42396b9ffa9068f06d53dd746800023a35a29ef264b83a88e245c30bd1cd2b3d5057f861a6528926bb4b578bebebc16cf71af31fcee1cc9bbceb4efaa", "CS1": "0408def084ab23d7783e3473bf411320d100a91f7b0dbd98cb94c9393cfaaa7aab1b9b595d4bb4a87f61529d6ea939658a7e78381efda51f7b932febbec27693a6", "CS2": "0406f1383e1b9fa073ba34195936f1dfc68c30c5f2065c49968aca035b0b91648e06f0bf4a41c6c54eaf30f5464edba0466a8b87d517146cebd642cc5c0e95df2d", "HASH_MPIN_ID_HEX": "a64b78ba99acbb9a6b4dcde22ebceadec8779435ec55446b39ead553f4e7d56d", "TIME_PERMIT": "041a06c32e7e9e859e5230786da50d915a9a2f99495f3e880df12bd00fe25ef9e20942e70d950530aad823f1d5bce1f17ee9b92a3f5e276e6d9db7ea6b56e3f4dc", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223662353463336635326662303631336236306163663435633161373336343933406365727469766f782e636f6d222c202273616c74223a202266663862653333396531646163313363227d", "TOKEN": "041c075056d29bee4da64c69e80c0f1c3e35fa4ac18845a7d82bdcbf0c6c51aae4105943999661b3cfb66d513254ebf344a2cca79e1ea007deb9fb9674a92e4cfb", "U": "042113ab3fb7e8b0781495052b5035e86d49c6029f223a1e0f4ab009a7477e44c20efa93b0e133dee6d6385657fc517dabbe63ed95fe1ca072a74d6fc50625f196", "SERVER_OUTPUT": -19, "Y": "10437e519bc519016650ccd1a84aca901cb32ef7b41dd883b67ba814e45f06f9", "X": "1ac5f4781835d86d1b2c9ca3883f3ca6fe5f9c189625c9b72304f13babb9116b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"6b54c3f52fb0613b60acf45c1a736493@certivox.com\", \"salt\": \"ff8be339e1dac13c\"}", "test_no": 169, "UT": "04070aa670ccd675e1fd23254592d2ff43f7a69d13473c3feaab787857aa6cb2c5109199d05ad3274bbd3cd6cdcf97b76025eb18c75a8828ca8bb857932f6f7ae4", "MS2": "0f380dc40a223ae7a376a783756563109a7b0e86494c9c4e6d2cb9325cc508ec", "MS1": "048c60d0a6c015adb15387ababd94270f680c57ecd1c10c8f68a70324e3d4783", "CLIENT_SECRET": "041e4dceb804785c01fde8e65e7ccff64c5bbe3eb19acf8b0af15d5b535e5e032f04c83f0bb39f400efbb47e52cedb77764d5abd4803b10cf7b1e9b8c4517b1d00"}, {"TimeValue": 1437055597, "SS1": "00a52c4e8391b76105655c9769386b80242c55642a6e45221c9539ed6ea8b90d0cfaa2ef288a4719f8b91dc5a18a31234b0d5a204ee61b467d03e11f6a9d956623d8c775f4889a96c8d84c6b456449868053b1e96139778c59dd3b53f05295651ada7e9bd9ce4d22ce0ee8229126a0c1704d2b7d825c25da92249a721ae3e98d", "SS2": "15fc85a9a352dfefc968d504e0375593d92c2b65537df8ad9b88889f4b7c046703453cc78c22a4001223f113044e8878f4e88c4e96e89b4a232d0cbaa8a4ed80012c1c3e496a22d07b075ff34edb47f81960f73d6146972707acce6c8e7a8109102c6a2b7562bd7cfb8ab8b1715f8e24bbdb926f9903383fde1e0b01f14619f6", "DATE": 16632, "PIN2": 1452, "PIN1": 1453, "SERVER_SECRET": "2135e18dae6f56634e5856ab90d05f548f51154ed16adcea93a38f5aa044be1c0a008a983b63c92d854617c7c5b502cdbca13e637a10f5b86fe08d0b148549cb0acbe180400f2f893c278ce5eea4d52f70f9ba7b2e73d0f8f5f093b506ea74ca0a5ba4a4d4b615f3ddc254b31811091f9eb6544e9aeb6d63699243fb6b4ebcd1", "SEC": "0411540b0b4eef5633e3fdff4ca31805c3d1bfbb8a48168a01e36263f51e4775d304226836bd0adb4f303f0fcbcb99ee19a86228f8b4c1e3b28195b804b74a3c6a", "TP2": "041d763d326eff91289b545f0ef9c55cdb5ca5ec46339c9a389dea94b32f3d0a6d1ac84d05b47da8d65856c190e03b613b7fa5ccaeebd25e2ca84314abe48bd22b", "TP1": "0414bf186f8d77eec564c74403b66a8f1222ab55ce98e89937e8349292bc7a3d8a1e13ebc186a05f124a87d0ceb1c69bc5592a01071c7b5dcb1febc151427d85db", "CS1": "0406dc1e4d11c296c9897013ed047798e7470c4500680b40131d42c45b89666a2219e5751385789e9cd1a4a4f3db847cd0fb88c02d973b7d39199fbea08597418c", "CS2": "041b615af622561b20f25e42eec9705feda703b09a352e5e6b309427a251479b811a7f401490c341a3ca9197879c53774df33a7b62caeb7d583077430050d2c96d", "HASH_MPIN_ID_HEX": "ef7442e9fbd496d51f32dafe55475f1468ec340bdcefcf64a68efba62eb9c5da", "TIME_PERMIT": "04009a548db4fcd25b39aca88bc55904e4258606d4d4824a7226d26491fbde2c4e0a5f5566e0bdac5d2182b1634f4e42c70dea90da7a9ef2a3c96692655b69a772", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20226662326130316465383664626563633834613232393633623835363861663661406365727469766f782e636f6d222c202273616c74223a202230616138303261306237303334656161227d", "TOKEN": "04000549236e4326217722eaf6d8911175218037b2150b5c242586bd4466443b691d8568a880b98a09184a2a242f4216d2f9ac2b672f95657f1739962c1e5189b1", "U": "04065cdfeedb058f418aeda9d7f721e334f82ad0a6bcb77af07cbf14dc03c4fecc0cbf76318b84d176dd8c5e921effe536bf01c58ba689429311822158856e6748", "SERVER_OUTPUT": -19, "Y": "1731367d255a2177313c5afeccf2c27506ca39574bcd58927c657ed1b4dc6eac", "X": "18764d68dc71e44bb41f1dc67ba0542be50d431c3d746c996add00135b2ead8e", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"fb2a01de86dbecc84a22963b8568af6a@certivox.com\", \"salt\": \"0aa802a0b7034eaa\"}", "test_no": 170, "UT": "040086e4e746ccea89ffe508726cc0e5206c77b7c2cbea5a578951b092baabfedb004ba1acae45f28afc21006fd77d1d9da66917d68f2fdfd48b86040b859f1406", "MS2": "2062c1125aef80576dc2ae73a44e69c71ea9c0a8e3c219cc1068e84d14c9c440", "MS1": "0f76ce3b91d1f2323a24b94bb9bb6179efade3d2d59c6c5a60b9e2fe92816157", "CLIENT_SECRET": "0416e4d82b741774cc73ebb9d0bffa86a37fba0296e6f3b9665821b0fcaa9c9ac120c87a9865a9021a5912f8cc99ef5a368c98bcbdbfb6d28a6346439910f4da23"}, {"TimeValue": 1437055597, "SS1": "18b96d96ee29a31e286c56fc862092d8275532591d22f399420b7e93b883534607e7b4a15719afe11c4ced83486769f54653debc48217abc63ef49d9f6ed5a7c1855f22b0d46e5084dd637ae10448032519a74e034c84fa234e92bb84e64f14a0e37ea604090a868806549f02b419071e7b60eff982c954c7ac04aca04c1ad4c", "SS2": "026e4a7e30f38249355cd1c8db7d4759ad1886080c8e18245d5a9508e5c8abde01a2115f1b922bb1658808ad9ac27b67641f925c3d076dbbb263108764caf9b9202b68c024f5ae3220ab62fff5cb36a349033df1f49d3c11102f1f006bf1c4560b4286566ad1e4afcb05502267ba07fd1e52a2c100764339ceaf6b24c3f7c925", "DATE": 16632, "PIN2": 466, "PIN1": 467, "SERVER_SECRET": "1dba55e5a7a3a8d4c91c9448b4d232975e5b8f31070266d1f5321005e15cc2ad009d3a3d7f28283aa8e712c45357d2782ec4900200460a8e3f01a1b9abc3413016354e6c799dd03116c79030f68f11f1d5baf6a1d07c755834812a3a9b901cb01bf42c650687056b69eca4e7b57951e5dcb5aabc5d8f7b8f0d49250914d1199e", "SEC": "041d218bd24eb9579123f6d07e83883b1378dbb03734c58e4f7df1c9363e91f53720fe867f87b6a780920d1f6ec69ef7cc16e0d458dd5c459673d63918955b81ac", "TP2": "040aab950183b7f6487d0332fccb40876612e1c801a27e7c87806e867e0e85be2220cfaac2e15e825e6c356464e155a06e94f00974acd787f8c7fc222425dbd1a8", "TP1": "040a0aee66c9de0fdd973f72b16bfeb72f8346220a910d9a71918ee8db898e97771b8ded862e22f0141e2d7594ad41d2e55c43fe3fdcb6de7b2b0c32f1cfcb2174", "CS1": "0419f5d2771dbbf7c79d10752c93db37fb09350891a6fe667831ce63fd698e0ab40d669b11ff77856f8bc7d96b88ed0028a4d3d527445c8f07f32dcd9b2549dc6f", "CS2": "0422a995d2a64a6ad1cced9cc7e4bd20f6c6d7d61f4a41a4132973497cdf6004a4104860d08c39c23b2a7cca964f70f55c7b2034dd55d38df42f095648cc1c33d3", "HASH_MPIN_ID_HEX": "4c1429594d9772eeced099f952363dbf8fc161a2be35cabb111569f2f390a6b8", "TIME_PERMIT": "0402df09a420097545faa889263ee675f05563a050facbdd255b5dbd9c49616e9023645ed35f5b8ed988732bd740f39baa9060ba049780428a3299f6e06621f330", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20226631376362363036616561323735623530333938343539636431346264356666406365727469766f782e636f6d222c202273616c74223a202265346632353365316361343862623564227d", "TOKEN": "042071b8f32de9cddd1b7db263f4ced8a4b8b33bcab23f5c4925b25f45e29f34c319c8a73d8bd70416b877dbe92fe0a8281cd6b9a1cb408300cd493180abda0023", "U": "04069230a15b61e1e22deafcd5272d89984bfbe4f879b76006c1dcfdcae822a42013942efa5b9fe8cd6f4222c1ad24a78fe5214946ab3eb3a65906c3e5666d11e1", "SERVER_OUTPUT": -19, "Y": "1e753a6ca0543d90fb8bca13244cdf7839b3e8775774de54ac8aab4d8e628ada", "X": "09d9bb027338d4ffbdd461c845325387ddd0dcae9cdc8e73cb2f04d501986b55", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"f17cb606aea275b50398459cd14bd5ff@certivox.com\", \"salt\": \"e4f253e1ca48bb5d\"}", "test_no": 171, "UT": "040e5f0dd133f997a7095c4cf3c844a1ac01223d9f7009d42d6191db2f162799221e82b81e248657aed55f6528c35994fdffd27dc8243eabf13990e7355ab16f9a", "MS2": "0911e408e476b00151d69bc78a6ce105cc364d5a39abd38367ae8fad0b4c4b00", "MS1": "169f68cdf48ae7d5b762222d379292881b05ffda9939fc1131b22e4071419e64", "CLIENT_SECRET": "040d732b8ac866a744e54ddb323c877515e064f990ff4893f8534b7ad6ec7835ef12a646120d57187b47ca514296055ae48f450ae6649d160f6bba4a00f4692780"}, {"TimeValue": 1437055597, "SS1": "05cb948c2729e3ec1487afce2d65dcaad42f2ae1c051d46424403e82bc7502401d82ed107fcaef5ee3e8eef4bedd53404c3f715d6aacee02122aa53f0dc364a622032cb07d43a70a7e6408222e7fc69ca1c8570e4eb57f03209b1bf3df8ffe5c18ad1a9342246333b045a8e13745499d363c3f4092a79e9d6fac266803810015", "SS2": "02de229a71cdff69f572fed01de00fb082d5298aad078ba71db1009ed301f66a0cfccd8e0b4794811e5e59c5788e6a195ea4cd8f82c4fb61b039d1a66db07ada051abaca65864feb6b8cd6974b327ef44e08c24080492363bf4a9152a23f1ccb032c447ee69001f8c8cd3f629b77ce2201be0254f68f436f4b156702ecfbbe4f", "DATE": 16632, "PIN2": 4390, "PIN1": 4391, "SERVER_SECRET": "1c181903337e25150d0d7f0f476e711f3e0a68f9f0ddad83df4435cb8be5236618c944d9a2e87e9892e3da8a18ca3e129272d6c2ed027b9ec7d9666b78cb9f9d193291118afce7649f8019231b1c7ef9b5ad61642dce15091a640c2ea93cfa0c0615b351b92064044c38ef6fa9bea8e6e5ccd29fc0ebb951e15d66707dc6a5c4", "SEC": "040ca2301eb7d56f02a7a92bbbef1b4752e1210ecd05a13a72edd28a825f9e07e309605d53e9958801576f2bceeb99ed3e8afd300ea06c1e013d516607f0173662", "TP2": "04193b120c35f475cbbe4c27d153b7aa7b8077dcc67df7c018807bd58cc818564112e2c2294c337c32af81117a9a59875c9b44da637ce048e11ba8d6e9c813d93a", "TP1": "0408317944143e6d66302fb64d1e8d0f00c1c812181f3e18825a949e8dc04d18af140d3b6f4b0f2dcd79305951b8531522f05d82546d3699a87d5d486f80f93074", "CS1": "041a3a82dbff50495b62a9a8e1bd76526d9baf18e6f0f4cecbcfa7fe4155b6005c0fb14f0c449360e2c36f4d8c214e48124eeccdb9bcddca66df2a79a1c715e2f9", "CS2": "0408b0c78afa91e7ddfee0ac7bb9140531f67e201853d831c8db23da826485c7442033e073f6b9ca5744ca1669b63435a8a2ed975e485753f455d6ebe167aa3d0b", "HASH_MPIN_ID_HEX": "c86cbc977ce747df9f5fb16c9be01f35160a726a0717afa407f5d5569e2ee00f", "TIME_PERMIT": "040b77ddd29e654ae2d83942162640fa8f191763573b94573a518f8ed65b6f6be2073d3743e9bce459c4d6c79b1742c1dd8eac59464a9729ffa094cdcbedc36a0c", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223938656637663438626239643434333162666639623034643739363865646634406365727469766f782e636f6d222c202273616c74223a202237646164306635343364333537613461227d", "TOKEN": "04122b0a97869d5eea2a9547c3a91e3d0db2febe73bd12fa20c05f28d1b4909b9c0e6bd814d2411052ce2aa632bee3d367bcf62d59f4bfce64519f77fabc5363eb", "U": "0401a0fe79635985afa5c396c1e202f71284c35cbe2d02329210b808d0edda767b0505bb93a3daa549f3eaac4869da993d01fc5908dd7b97b974f417fd1d2f8e22", "SERVER_OUTPUT": -19, "Y": "11d8872a7a3023329d4745fefb2e3ed1237599d8cef758fe99d5df42841ea873", "X": "14bb7d01c7e38e0089c10c0acac082cec3c305635cd6e8abee9a1a2401a52303", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"98ef7f48bb9d4431bff9b04d7968edf4@certivox.com\", \"salt\": \"7dad0f543d357a4a\"}", "test_no": 172, "UT": "0420941f3a742ce8bdf4e6e1573e6a020041b1a996fdbc30ab1da9bea6e290ce2a018d6f61bc4d4b17ea7675fef61d926b110250f33241a936cb7037dbd1ed50a1", "MS2": "13caacfbe7fcfb1a06ba1a5e1289ee4e6a923a487d3a9667944e79f03b414e83", "MS1": "0666103858e9f931881b472ba871001c1528e2dfb4aa9668dd79a88c9fc3232b", "CLIENT_SECRET": "040d53b3288732758cbc99ab5913f7e10dc65f314acee873506ea73ba859f9bef11cc1ecf923f128939f5a2d956dda7cbbfecbd434f8c87f450133921ba70db347"}, {"TimeValue": 1437055597, "SS1": "0583fcfaa25d486011bbf117da1d8b798cd6624bee8bff2c692e15da11c0128205f0352a26a5546a2f86b2912c19302c8ab9e81acf9aba0d29eb63bb93e21f24173f25755ba9e95d6c39b088c5251a7ef4df58ba3df35feddef51c1e2c3cf166057cebef9aa1a4ca076ee810cffd9b158adafbfa45ad890023c823e1e3b343c8", "SS2": "0ed7aa021c2b0713fa9333a40d56911c9e4a06769ca4811698a15fae05d8ba2a0233e99413fac25c0f614123167839c9eef4d414b7442c0420d1dbabdaf1fb730ec960ac279fe379a709a55aab3856779c4ec90e621305a04c88d3feb69a05b106ce9998217cdb24fec335b062f441aaa57aaa98f4e6293bc8188e3df33675dc", "DATE": 16632, "PIN2": 8304, "PIN1": 8305, "SERVER_SECRET": "1bad0e12e1f054456540209ccc2acf9261802a7aed6e4aac9dd16a247db26bc317629c39103fb2b3fca522bc4cbc6059e6c2d2963bbc7619c97b9250495e884c14763383e30081045e081340c2bc8fba72430e295439a4e256e56539e1276f3a0344e45f7d8fcad7449a3cb6b549396087fbba0c6ac9692ef9b3e268889c4d63", "SEC": "0401e7f1c8c51a45892bf1de919dbcc5e5a786b86b78c4b33c4290176bfe6ec82f1420416eee6714f144d6e9ad627bef93662b057a92bfcdd4ab91a5a6f81fec54", "TP2": "041b0160040497ba77aca59aaba1b49d0354284999b1cb6787cb264d28069787101378aa980811bdee39ee6ec10ba371b8c52c0fdb007e75f9a96e1d9c1e87e798", "TP1": "040ee058a80959851ec85cf6ea599bdab983f9cf6e551e32caf5fd0448dd13cb5d1337b2a0d1d282dc9190715f4f6b7eaa021c110424df483b61ee3dea3c46a76a", "CS1": "040203187750ea0722e82072fbabc11bcab74bc1fa6266682f9b05ec6c311950462170829667d6106130028101b102742348a8f387df4e3e42e155c984c028c931", "CS2": "0407a205c837db0d2f19ed0eeb900f873488e513872da5ee3668e46b2e4b3bd3d823a766266138237844a4c0ca526e1f307b38b913617dfdb12dd280ea77199f9b", "HASH_MPIN_ID_HEX": "2d225c96dc711a358c2a158a41305090cb747ef84a0bc7037bfc4437b239523f", "TIME_PERMIT": "041db5649423feeef6d0f7641fc8644613379a35ec30e4f88929373cb2a32a16080cc5fbfe945f6c47368bef4ae0ce887e17782002b38afdc1d96454bf3a1157e5", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223161373366666164333532646334383563636138633865363131353034636432406365727469766f782e636f6d222c202273616c74223a202230613366313639366131643664393636227d", "TOKEN": "041b4318dd16dacb7154524b64a5cb040e4196ac24897110c96ba5d76996885c1e1ce061d669ae09d3c1e0596d5c212380d443fe0da34938b9cf89d906bfda3e8e", "U": "0406a627d713cc4eacd44826034b38cdf9d6d05d8149c423cf2dc749acfe84795812d28e58bad1e1681c9edbcca07648a793d4b9f16e07529f0d97cad9103170e0", "SERVER_OUTPUT": -19, "Y": "04608a3bf4919cf226dcc1a95f96094c948978df3ab3186a0931c665b2c8f9fb", "X": "1992797c465f3a734479bad8a1aa9aeb31e05ec288ae8318d447e0d374581dcb", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"1a73ffad352dc485cca8c8e611504cd2@certivox.com\", \"salt\": \"0a3f1696a1d6d966\"}", "test_no": 173, "UT": "041f30c94bc0d721a5526cb15dafebd8561203ba0d3686cb9b79230b460737ea3b121e3ea4d2af78369e8da941001d0ffda71e16c1b4027e9341e5b899bcd9f8e5", "MS2": "039532ad512c405be8932660d128c50fab9e711038f009a92e33cd3f3c55b1a8", "MS1": "1d7ccf412535a9b558cdc897aa59bbb3000a10fd96741e1c054458bfda67abdc", "CLIENT_SECRET": "0409fb572c9e30bdd95c2b16a2cf3f31f69d38192f1180ee82d5c50e0c6165c83c0d5ccefb18ca02bf9200fe0b3650f1ca75b02dc8f0e5e60647255ae78ac73fae"}, {"TimeValue": 1437055597, "SS1": "21bdcf464326555976fa2ed7c5b4f203a3f3b56f3fc29283c538ef08e7a2fa2718f322e888bf79cd575f16e1267e8b2bbe38af18c675b9ac6e1d4102f88f656a148361b7e3d52ef4e0c990ae26a623e149e5a002655711ea9dbcd0651e1c8c09042cfe0126ed79658ec08977d387e49aefcb43bceb0243cfb6783d00e1faf6e9", "SS2": "125c7c40a4c987a1ee42e557f08dde67ea71ff71b119556526ea5aad029b5b40191f50655ee1e232abbe52193dd82a56ae779355558c2ace4d119aeef42de3a52257801ac43da748eb4f761001ab2f0ee222e3e1f63a47f0893ace415d4a44841f658f607049b269993fc845130afbdfaac09d5104fda858f1174c8d9507c3ab", "DATE": 16632, "PIN2": 8347, "PIN1": 8348, "SERVER_SECRET": "15bbd91d3595368c27959687e80ddee6868d88269703b1869b4dc6ba9853e0700bc640bf4432f9b1b7e2261d7141a32a3535a7f10cfed792241d01e4750ee11f16facc821dacc310ccb02d65adf09e72acb84b8d6be154da854edc93bc55781809246087119988c7692580043ba93d442c76de8766371179868b3741d9349d84", "SEC": "0403d07ded21f22481028e70496c5febadbd82790631bf5e6a6e6ae4f46b01a5dc216bbb947cd9b66545ab03e55a9b54bea2164164ebe604becb7d68c1289432cf", "TP2": "0408453b55aa273b38886cfadcdb6bedd8f7c61ccd6bbcd28c18772fa9a760dad50e01e807b7ba2347d921cb176a46dd63380884695fea8069831c8b873dbe3fbb", "TP1": "040931734ce22ce07da1b4a0b9d1d396d1975af8a2730d0b93cfd488a55899e5a6005ade89d87f6340144aa52853575a583c086523d4daac9289c8b15097104bf8", "CS1": "041cab4cb614395937d1fbf2ab2eed23b4f24b0dc78300b38042186d7f604ffb38001798caaf56b22d03ce2c728c96083ac83b1ddc5ed316b3525db292a3889bfd", "CS2": "040a19ef1ac5373550c4bc62561e7ed61d4b781bca40f69887bde0f7e8287bc06f11369b2baa4ca64db80ce1065bcbeb582ca5cdcf5a971ebacaff1684309158c3", "HASH_MPIN_ID_HEX": "0af5c7064c43ef069a2f3d52c5495b83b428adb2b7f956024510181001e4f2e2", "TIME_PERMIT": "0420081725c2cba24c39afe02bf0ca833428c8dbdb00b1facc7669fa916bcf29e20ea3ab88bab52d1603f581a2a78979449a7d7a550ab92318d4efbe62a74c4ce6", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223433363334326664326531303932383639343866656162323932353730613765406365727469766f782e636f6d222c202273616c74223a202236313732366531666139396637323465227d", "TOKEN": "040549cbb33ba917d218709092eb2137906a0005051a31e0d1a1266babed06f5eb1ca3d71c90c900310efa2edf6b7eef2bf39aa4667724d7996b858e36ca2433d2", "U": "0402ded680fcace6f352e7aa126cd5de23d0c5f61a09b0de175fecd729348037fe0661ff181e4257f3d52be53eeaec822bdd38380c877c8db7c3d0f6f5e2f9aa74", "SERVER_OUTPUT": -19, "Y": "204a64ffa1a40c6fa097abe6fede16f708bbe629974a5167a105b5b9740119b6", "X": "05ef5cd5011b92e77941719f75ed8c9ddbf3f5de1aa9571fc417a3fb3f9ef3af", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"436342fd2e109286948feab292570a7e@certivox.com\", \"salt\": \"61726e1fa99f724e\"}", "test_no": 174, "UT": "040b0127a21354063530f875bb51c6fdc2351cb62bf0bed26a9872bbec4a9dae2b0413783e919cb13590e9115a8e329249850dd7f0b5d753e7f92e704085ac8168", "MS2": "1541ffc1a40138ab8aeffd963ec052cd350d9f6094e113af2ca061a0762c1feb", "MS1": "17aa4cb6564ea061f84299749b9989adcee6250f979994b876870ee9b6d8d5d7", "CLIENT_SECRET": "040f5fcb875db7199506f8e38ca32f3c5e31265b5476a2c26994b51309421f715b11f54d7529560a7518975587b77f9c345ecfbe41fb7a87732da0876ff4d6c5d2"}, {"TimeValue": 1437055597, "SS1": "129911c60d1688b81b56bcaca6ef8fcbf2e05efc153de97bbf565c9ea0ddcfc71fc0857c0e00e300ee3e922911097df1f9910934225dc98d3ed007bdf56f982614a75328074b53eed527cbf2c0089a30f867cdd0d9b8e4429719d8b46abf30c3221580974c3849b8879e6f47545a3a2b05331e38ed901b6c10c9bf19434c5d7e", "SS2": "233b92eeef2329ba4d7f1dd205af5d4568b94aa7e207ddba6b1bf1a035b5079005e4ac48ff9503b34464233172c6da2b9ff4edb34fd7df2ccb0410f70e23e8f91910135d078f203eb42c6d2a4b0c59f6a3e979658e7140a56f753e531925ba1a0e08064590875c2c694715c7053467da258c9b458265536d6d37d125f3605d31", "DATE": 16632, "PIN2": 7101, "PIN1": 7102, "SERVER_SECRET": "165274865f82f94f6aa987a02b5f32fd86467fb68f46c6090ffc0f2b9b51ef6802108996ce459ec80d9cf5f966924067c657f2b069fb2d44c906cc2eebb714ec0e1dd81a868bbee12adbe61b28e7128263307f5fc0baca0a991bad5769094f1923d6124f92f10df4deb25bd8181a8e78bf37f2469fa1784fa3be608ea3cad517", "SEC": "04233a8b437e34a1d756a970277cf0f16d7c159fbc8f7924c1c1d00bfd049e8eb318f2490a52ad8313032d76016bf51fc71d966097c4c87a49d65716dbb9799a5d", "TP2": "04060c66e5d956f527640a9d3392c2362ad2ded104af97a5abf5fe0ea252c70ebc21cdbb5156683f203b9870fed532023846c7495746cac3b7673d59c9a4f1417d", "TP1": "0412a10b601f306ec5e710ff8698eecc22f06c664435df2d045abf9be0508b042c1baa61d79f0cdfe8fef10d112553c6b9892201ebc1ec97abee1addb30f83d41a", "CS1": "0414292a044162ea556504536896659f8a8b008721dbb415dc963018ec71297ded0394f22200b0ebb4feba0ce8c05882adee5da8694f47c1d044257d02f78c5461", "CS2": "0423793e3002df68e9e7283baece6210da7fed8d110cbf7762ef2f2b4d1459b0d70def95cf2210b46dfac6af5e01bd4acd01976fb280484230b28ec89d18b61aa4", "HASH_MPIN_ID_HEX": "c916a8db3e1a247f9dc99f78fef9b88761a17ae3061cdeb76fffecddbf6a820f", "TIME_PERMIT": "0400cddb8d60dd8d0afdd28592ce9e89b9ab3c6b6f5d58de3577868eca16366c2207999d2fc6bbb1c22edae2b42f446ffa12157e6ad5d5c0a90c705e486419c9dc", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223235323536643465323038643933316534376532393062326533633331373566406365727469766f782e636f6d222c202273616c74223a202264316565326531363261663330356532227d", "TOKEN": "040bdb5758e86f0a8502a7ae47dc4af4fdcbf0c65d4411b8df760c6a0e3f9d085209e3bfa410f08b22053e5c7d5c2f34e0aedff699bae70317d0ccc6c72ce55a6b", "U": "0409fb3e7eba58edf241e5487cb19da82b13b5b39ca5117309f689cb3433275a0702d1b0b22a9b87004482e1809203e2b163877d6a1da5fedc35f6d3e1b3f496af", "SERVER_OUTPUT": -19, "Y": "006589194b2124b246efa3eb7118d62fbc8b5b22013b564e7285ce54cecd728d", "X": "167ecbd7a4b557f2ac7f5f68cbcd9e0a637a828ecc643a6adf9b94079bec3bcf", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"25256d4e208d931e47e290b2e3c3175f@certivox.com\", \"salt\": \"d1ee2e162af305e2\"}", "test_no": 175, "UT": "040cfacc5e139ef0d0915c5326fcc4445b7fa29753f982f1133de6d2201d1252081ba2f24ef970cc572e95ff88d732be4ea9c9330c7d4d319f92eb0820e81ec8bf", "MS2": "059101b1f5659a3ea1d3a9b0e6e05ee638f5810df84410c90f6d75dc661c8663", "MS1": "03a2eb62b0fc77c8f04a53614249f171205750e0524de9abc31a902b370ed17b", "CLIENT_SECRET": "0400b0145d1895d9b6705defdcef1132afda17aa9c0fcdbc62a1213c1ff6858d4f1b82c4e9e2e437c2d40faccfb5de669262c47fd1acf93e1b65a88a397792f320"}, {"TimeValue": 1437055597, "SS1": "0e449e07e715acee46352f8ae8ed8bcae481421f9fd9700f5fb37dc0a3efeedc14869dd2dcc301b56babe9f4d10bcab30b3f943351e1a631be26e0ae42617e0b07d4d9b6ad9e2e23f705794fa5cd72d6e78cc67d2ebb7c6f72381bd2f0e4ce5d1e02d457d83c61f89f78de8ba9ab44899cb5a5e26cbfcadb91bf4a29f81ed4dd", "SS2": "218281d81996005c20480c0421840e63456151098ae4c1b562d5b299d938be4d113249f8ac726a4d61bb78b14fe639278b3a62bf78ea66eb8f59f0051205cddf1e45d9a2f1e2889744d0ee66f84de90e31c46cd7d49ff4ae88fb3e5808414ef107d8cb52e59f1998013b399f7a0e0a00356a3e4b72937a8a871eea3eac836b91", "DATE": 16632, "PIN2": 1499, "PIN1": 1500, "SERVER_SECRET": "1d7fd7118ef4ea295693d36872f956d58d80921e7adfcc7c1d264c9b1d03ee9e0d80f8e89bf223db5a1595538e56e1eef5ebac0a76073ca9f363e89dbbbefe53209b79870e64b45bb8aa643fa6f88378d6e6bbe506802c8b5388d9ecd74afd9e001f38463cf25910f09550850c6d631d1d6af324c6a78a73940ae5435d094896", "SEC": "041e7a42098e9767f05086e28e1d1e8df5e2aa120562063caf6ea1dec4b8196bc31d6756c553c2ddaa58d5a8a612d6ba48bf88673cb454e61238a46c8fd37fd69d", "TP2": "041b19d5f00dbcac5f84507d72bc4450559e21e87a9be138de4f1bdc4e797d1bfc115ace3c4034d05c10c22d27d08dbd9306900e515c8d77897aec5de2feecc5b1", "TP1": "041f4e3c45d92bf9602e49a8afaea02dc07cc822ee9bedd36dd028ced0494f26890558cf4a05b3182165aed289b3088eddc74bc9792335847ac0d77a204bdedd84", "CS1": "0402826a435d3e0683a9b0ef977bba352ba14722038cd9770d81bb3bacfc6c737700ce2d5f027ad07fb4c779c3cc56f4453df51bce0473e23b243d249c145b27bd", "CS2": "040eb4a3f5dcb05b11cc1f23136563568b923079edb3282941f5b72bfe78ff62261b3f6a337d0cff475f530ed4176a063b5495b3e2b2c213e375debe7603905b15", "HASH_MPIN_ID_HEX": "7e396c0d6f712dc9bc33bc39796a53552e3d94fadb3a4ba56d0ebbf02bcade76", "TIME_PERMIT": "0408f0a26893147d2c746157c3936729bf0e5c95594beb70d75088f1e3e151efe31a205bb73c9b2a0a99c6236013998764410f9cf033c7b0e2581a4ccb60362b71", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223664383364333130643965366433656561326566623938306335616234353230406365727469766f782e636f6d222c202273616c74223a202265373132623462633332653731313336227d", "TOKEN": "040f610ed9e3d0029fcd4a7c9936eaefec4bfac1ddf891c610413a0af1758de28e17b3b9ef6684b15424bc771e066e595795d4d2a75ffcfb472d61d025cd87a051", "U": "0420ee098bfdc69ff5cbbbb0cd168acc563a19dfc608dd68f41f823f89bd77b83f0dac459d0d4d95b066efda07c59e661d42a73151c89a6941511efc16c887432d", "SERVER_OUTPUT": -19, "Y": "23feb9ec1cc8ec4c41cd2b4173dc4c6397ca4a62d5faef5328e894b50c831163", "X": "21b9f658565376d6811395fd0b384ea32b378353aa3b50cb8a1685275529adb0", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"6d83d310d9e6d3eea2efb980c5ab4520@certivox.com\", \"salt\": \"e712b4bc32e71136\"}", "test_no": 176, "UT": "040e5778060be1feddcfc2422ac1136852178accfdba4c5f10ed5888d249b083df086d57538ac489f35459c3e3016ea1fd8382a80745f5afe8f80480cb53bbf86c", "MS2": "150d85f81cd38f48870b8547a8ca275e40b2c0ff906ebb392456bf9e65bbbe75", "MS1": "0a4307cbb4e9a30d50a6f6055db89a3b05eda54ce5de7d2eab9cbceb820a2aaa", "CLIENT_SECRET": "04104ed91c3ee99bd2cfa95cd621d799d2c89a1d967dc8806beeefd6b4bc280125071d45f4867b6461ed16b8be41edfb4fdefbebf87c79d8fd7ccf811cbdd3cf56"}, {"TimeValue": 1437055597, "SS1": "102cd06fab632e2704c06610148cd5ff66a9d9ccbc388dde73f1981c32dfc09c0116cda5421ab0c058ba1f08d41089d1652f99eced2aea31b9e93c6ec4ff98b90f127e93d8631136aa2e1a748a6a690c72525f0edaf41608b6d7c402384394c001f14ec72525fde157fc003cce77e930abc504fdead86915b4c5f13053bd297e", "SS2": "026ebff0848602f45bf94d7fd10e676a08b2bfef8d64e9a05393754f59db32de02273e8c045bf8580fcb2c2da4b77dcba5d1a4e1ca88f108059b2b30c9dc387212cba8c705512b599d3a59187f828aac05fdf36826fd87ca10e1ea03a7951b4313fd34bb0f00651727f116abdde2172116a8f66d0775cb630a816026005c6daf", "DATE": 16632, "PIN2": 3235, "PIN1": 3236, "SERVER_SECRET": "011a9b5c30fea6e43bb1f19f09b20a69f7ce1785537663d9251167e54e9384a2033c8faa896261d9baf7d1bcfb85c04a843c0c2046248dfc53ac7fd3f4f6b39008b4b9e4a4d20878d708dc86792c67ab9c5a99fe9ca7d9ad03eb6f717704cd970ffe9e26cc77bd1152703798c9d0bc8351c00034bb9fc805bc18debb354d99e7", "SEC": "0415d28925fb6cc8d8c337dd1e3fb2dfe943681313a0c9ba664e8ecb2d1df31b260c255be26013320931f8ca995cac070c082a67287be84db5f0170f4d34e93680", "TP2": "040e0268167492a7f376e6cdf566f9577d6ab3a260e1737bdd4fa8606a44273ace15e27db846e0195bb7316ea25debfaab4491f8f95d16c05b39fbaae2526d12a3", "TP1": "041f51305912b9d150466c0392e0761e8cea0028604b81e44c93badabc003fcbc917c71593a2114180343e31f7d63d0cc337e234f787ad98e08df482027c320e83", "CS1": "04229817df41ef060e3e4ad5e710b82635ef713d1f42f10be6f630ab4ca124a8040ee72dee1e81cf7e357877609e10d42aaeb3f4fe142003374ea9c8d91ea8758f", "CS2": "0410d34c44e7ad32ed2c1bdb81b2ad1235c464e1fcc8c1e3e4b3b6980c771f62700a474202ef4f83532e8d99c7a31d64620a9fb5a7bbce89d478d18cdb2a3afb1d", "HASH_MPIN_ID_HEX": "ef24052188b1eb7d1b43d8bc048f2b1ec5f42df7f4b03b3c3f295fdfc2b93b3c", "TIME_PERMIT": "040d644974c898c23dfbcd4dd2599508e06828ec645491749ea114922ba306fcd1166090212be75f9c4513e254c7d218f1d44665641332780c0db41ce063bc2085", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223535386161333266353966393435643063343861376164656335613563633333406365727469766f782e636f6d222c202273616c74223a202237623866373266343761353235303739227d", "TOKEN": "0405e8339ef6ec823a8031de44209756af9c4ac5a9979fa417bf089fda22680daf20b62d2000d5c22fe2f6d944b3fe830def8b515e65116e3475509441d40945e4", "U": "040b44459373d88d851e5b420d9eec6904f2ca8f328f1787766b9c117827ae565a1e125172b5e9ea00b0bd4ff677157418819b8fa3b4f7198fde37ef7b142b7967", "SERVER_OUTPUT": -19, "Y": "1562f2062eaf1e36ff799d4a8a185f78bb1f8808c60f359b394b6792db441910", "X": "0c166f836ac2c0be56ba5bfb561ce1bf512563401b5cca69088d969d7ce1a42f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"558aa32f59f945d0c48a7adec5a5cc33@certivox.com\", \"salt\": \"7b8f72f47a525079\"}", "test_no": 177, "UT": "0421e4d9f2dabf7ae913dde1a3062883fe0742789094685ec69e08a99f31303a901072d65680a9a2ee67297221a022f78a9fe4999890eb90b04d1aae180f5ac7fe", "MS2": "108c6578e5979f92e61e72e0efb5ae0eb0af37e2fe0cb4065dac6a19d90b5f0e", "MS1": "1cc0a81d94b2a757c93baa12aebf54bf4ccb8163c9b8fc2bda03a2bb26784e94", "CLIENT_SECRET": "0404c20dcbf5617f726b5c6a13cf266684aa924afe01d604d27ff1eb360510d6c019394182dd805ccbb948a39c365d54df9ad991aa40611ce6c762eb21d29933a2"}, {"TimeValue": 1437055597, "SS1": "1df0099b68130528d8c1f173b9c87799ce44642742bb5a13747d439aa425adc01dc07202fb7bf8c35f08883e936139eef3fbfdefa6d6535c56dbbb2541e9d2aa0e1f6834e9ca202b444115b422b1603d362dee3e31f6318cbb9977a6c4110239137a263994e1ecf5c69dfa6dde2748934282a6c4d74e894511ecaf52acccce36", "SS2": "0f582047e37d392520b6cd2a2d6391d39f1809c0330b9d4959de0f2369ec9bb1231d06f748d8a32944373a5ca6943357902e6c99acdae50058f5c15fca4836780f15a0285100e80669a9055a7fc365c8c0bc681b0a25db460d1e44e50163f99307ad47ef74ea9057d246e8b5ce38e7d9df4a8db03e11ab9f5fd262dbe7050ad2", "DATE": 16632, "PIN2": 2361, "PIN1": 2362, "SERVER_SECRET": "0942f98f5c9988bb70aeffeafa117e4bb37b07444709047b64095b190322196523ca3502261afb3bc473d5c3ae6efe9aa30df55c2c4390971a051472f096a90014a7d10447585c6937dc65daee5ffe5178056cfeaa08b07edd08c3e107958dc803d39659d62637862f2ca6bafd715dc35a4e4ecf6140ea5b1b588fa0252c1563", "SEC": "0423704019ea154c4fa4a678952459fd4e70149e45826b6c4621c3dea1c9cdfc4d15826b931c5515dd8eb9d4adf29c9ae12300813cdf907d6412b60c3c191a7140", "TP2": "04118ba834dad9f02f75179916ba167f8a4067f706b3a1aa46f8d0e6b7c43f1a001c63087620308ebd170778519a9c44386e8827fbae27aeb483c6885e153c9c38", "TP1": "0404a91c07116fadd1160369b0c11bb516fc0c6b27611d798c5a90e21499274bde1a52c352a864d57b68f02436e69a45c2d6a75dd4ffa2b0e4d7a6a92ce793d89a", "CS1": "041208f597dafb7513804cc847724c43ebfba987b29b982f2216cd7dd8d60bda7d0c185d2616c2c014011c148cac43d6a8bb30630150b110984c9249e1775ac4cb", "CS2": "0419c82f6d29fb6dfd8efe3f8090cd963638e7d4402b2cd96dacbd637c1e3c224614c0fc593f240f4c2c7552032f2f75a153c4486beef0985f80fe7714ccad4be5", "HASH_MPIN_ID_HEX": "614c02c83083b3ac37bf50980827eaeb838347d1869a305fc397073abb6299cf", "TIME_PERMIT": "040a32250286a631f9103e0701d5cb19e6af179cd2a645a4e5f190d8fda045577c0fa1d6d404ec9cc6e588d997e427bc06a4b901d67f7014c93c8a24131232990f", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20226562643931313530623239326633616439663834303037333863656564343738406365727469766f782e636f6d222c202273616c74223a202232636631656565356330623332306336227d", "TOKEN": "0420ae9c6a1ff4fcd7d84feb1bf68b59601ac712b5eed1ca892785263e32a5c96819607f8817b2c7457fb3a4b6156729623d3d6966176888a26c359e1ecd84ad5e", "U": "04231522de2f1acdc759d9f654f639730f3e1855599e648399b4778336d25769c12377bbf5f41689d77a5cb2e70abd9cda168ee559e8cb4e3960b8835de0cd8480", "SERVER_OUTPUT": -19, "Y": "135a457fca91fdce9ebec016d50524b38a2f00272fc631d5bc23fbe78a805e54", "X": "14ac8ecb24abcb66468bb894ee4c71c47e9775d8e08e1433f43667a799929af6", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"ebd91150b292f3ad9f8400738ceed478@certivox.com\", \"salt\": \"2cf1eee5c0b320c6\"}", "test_no": 178, "UT": "0419d48c4f607f45b06001a0de2013d123cdc5a2dd89a6fbcc76083056e3030f33188ec7427ce26ecf4321f81ebbaa49cc5008230ad7c1861f1fd788bf6c490d26", "MS2": "18a9fe1d8ebf202dd8784f9fce0ea4fc287d1865afbf20b7fd69ce52a00c6416", "MS1": "13ae2763c03ecc505c3bd1ea90b1ab62af7f58f1a61bec8ad4bca24642424bd9", "CLIENT_SECRET": "040089388290d433f2aee155a8026909033e1239de0ea699a3889173ae63d26a0709361cc49cb4fb3c6d91d1d196dfc66b9ed1a5dfc57500c20643d5722791a86b"}, {"TimeValue": 1437055597, "SS1": "032aaa10b5cc95ebe464d7445b9716507f9ec41a1c1814c0cc945521e35a2d65042cfab806276480401cc46a850a7a946b519116cef3b2e3e291300f960f3a1b08f70cf4d6f0c03b27cc30f73b743c6229406c41ab664788fb3510acf0d3782d0e979b37dffda3719bfa04a1ad86e7eb02029a28a113657806d7f3bb77c6c19c", "SS2": "05603e781f2f3e3e9b8016a0518a4de0b939cdf285c2d4890787ef2e15db55ac108166b29d7e8689608f0be64555e198cdb4875aaf2bd80ec0f2bb4102e407ab0ca5d747954d1411815430caf18bab2ba68fea03c89e3e65bb58e3f7911c9749073a7d67bf6178a22209795f414de225f714566c40ebf13d55bf78b271bdd1d3", "DATE": 16632, "PIN2": 3732, "PIN1": 3733, "SERVER_SECRET": "071229b134b88c37238526a0cfa0a343a01a966f7c44b73b9eea7c41167fdcae1430aab791404202ccf30f21b4723b1314033d2d92061357b52a696e0d8b8fee17ac462532fed1885c3624958acc18a3189d53ffa69d4efa84a0958d1cde21441055124913cc8787d9a3ed6794a218b8c79ca321f0e65b970644a775078a0fbe", "SEC": "04096cd7750cbbec6bc358d3d1c93d1ba4057b9d6cb5ae44d8f9fc9e9394d23c1f11a2e12fd6435f66714eee5ac927b6877cac01ddd4280540b79e251d158ed1ad", "TP2": "0420e047fa492b8a636be878aa994cc96f14f3d3fd49d3c5b8d59a51c850a5aa322154ffd94444fa91a3c01b66cae6c52ad3b3915b7bff9b6910f52f60c0ece4ff", "TP1": "0405bec4e695256af17258cbabd6730fd5a40e3d831cc2d2e749c54ad15de9f8e213eebe78b6e130d5465995acebba7bc4cce451a6788e110ecde27e92889c9dc2", "CS1": "0408055d73b45a1252b9ac85e1d9a3743d70b2a6cc1a9baad92bc200d123cfc7451497485b52955595157854916c35bdde524a685624740dbb48ee0984bc9aeae8", "CS2": "041d9e4da83148611bbe8e6cb8ba441519ad5d02427677913d3a65041f1f4d64e109437368fff97eb189567722649d8ab48cd179206690fcbae6fae6fede97a91a", "HASH_MPIN_ID_HEX": "a4968fe75a0d90437f6cd8b63eb6d6a0f25913fca6f83902a9ecda741a54ea60", "TIME_PERMIT": "04036035079c1d43ef1f29da30b7046c5f027966ed36e9ffba45a36e518f73f16b0b89a9a28e6c4d57340228c0dd1f99f483a0122e6da047b069775d2b842076f5", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223136346237313766333532303038393939393832646133326564623761613965406365727469766f782e636f6d222c202273616c74223a202264356364383361643761643038346631227d", "TOKEN": "0418a8f100fc4ade7a6fe6d8340850f0ad54ee2c9249d40f64a3748eca158e1edc04ba7878f84775739b01b39af22979935f606fe1dbb035dd1ad8a73bccb1abb6", "U": "041cab7cec8c1b36fc51526d7b35d2b42b2905a9e821a992e49f7a70e96240220e0d924b041c186723b6a4ffecb59a2605d2bd23eaf540351b67c0d0fe6c3d7435", "SERVER_OUTPUT": -19, "Y": "0f25616bc7505679ab8d6328296683eade9f2fe099c3cb310c720ccdd837ab1c", "X": "1014f9ce5a1529b7adad9895c3cf8610b8a2e12efd7287159cd97e89dbffbc4c", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"164b717f352008999982da32edb7aa9e@certivox.com\", \"salt\": \"d5cd83ad7ad084f1\"}", "test_no": 179, "UT": "040daba1fa19aef057018beb3319227b5157fd2e46ae45c1f31458899c9a6a94121bd86f7634a633c42c569fe47ab2a81b671977be9d16f5d507a1bdb31fdea6b5", "MS2": "0f54ab5adb5b2bfe0f8d2c68158e4835a6125dda55aa6be4f9a319fbc67cec8b", "MS1": "071e20bf1eb666a057ce7bb909f6b8df10447e1abea11ac7de86c8555e5502ec", "CLIENT_SECRET": "040e9f7422c69adf944d37dfe7c031c02146ab298dffb90b1a2538f50df2ba1ecd0f465e3789a4d987afacd686648a435fc63420a8cb03ae3fb8d7d1a48d492eab"}, {"TimeValue": 1437055597, "SS1": "057d576f6c0f4005a00f147d87e8fb696abc88160fb960b4a8d1548d4707e17f01f58f588e88835692b168e4b6f67d27e0b2afc55da99df9fee6349d4b8f6082036176c60ab2870d324e1e1af0610799f2f5968fb79581003f2ded2424f0925a182bd9133592f3ddd3b31752d8401d1c0dbbb27fcaa705507f14f19be1dc967a", "SS2": "0af6dd30067d284407db3b90952321d21b4c8b5d263024570559380279dbdc00111917f26e6b76833370437200dedbdd09817c14ca6ee4539ae1cb06cdc5a83405516aaed137fd6d46397273c462e11577756a1b04968e1fb15568d26db6fe5420a089cec1f8589dad7b8d270793dbf95ffd9915f7d07c950ab48db2eab44a72", "DATE": 16632, "PIN2": 6740, "PIN1": 6741, "SERVER_SECRET": "207c3198bdfabd45860fd91fd8166208204aac325ad0b705b48b4e69618ce407218f259e931262a8171d6b78959168cfd64b0f9a3f399e4919d4bd37a3cd7dba1f387fb58ab44f9256a3792f1e82a60f99c5e87a57b9c22cb4b986b3bede41260e9845d42e0ca8caa2c51db11f1ecc49f04e28e2e7ef0d5eee5a5cb6292d64ea", "SEC": "041074dbdda8f55ebd0bdcc3edb3ee2d33b8910b06c9d4f537ebd19be3b40d8c6c1e9d5deb0db6cf812a341f8c561f8e1a630a6e42f39887c571e2791238734d5c", "TP2": "0418bb175e562bfc520ac760a5d1663ccd37527b37c6db9435b5b331379548d38f0426ad0bc6c39a7762594f0f95111e6d336639ee72e4a3836f8f14465edd28b8", "TP1": "0407cec3ed29dd4fbd8016c830e69dbcc728fc57e4ca088094f1baf612e216043113f34951af5ec0ace334ef49c3c130ab6daed070418d43d1ab938863e83d4219", "CS1": "040cf9e97386053bdf4e5cc48dc412a3023b6a591b9f0485fe353e972f14c5e916070f8920e74485680a7dbe6254748ca04f2a399b172e04ba329a0482431cd13b", "CS2": "0423fab28fdffc3c244f2dff452febd9afc2932e910a40649f0e75146c7790de370f1401da48b92a786c3ed2e148f588849d8b7b7e8fa0c098b4fe2714503f195e", "HASH_MPIN_ID_HEX": "314f852b1cee0b2605472aab0616a4e56c8959bbb3bebe94fa927750b4d68e2f", "TIME_PERMIT": "04120a8735484bab742aa2ef45eb3f9b8468eef9dd4455ea33b2952ba4b060203e07c7b0efab8754d8e4b4b7c385d5402e6699bfb7d458a873f0e0774c8d37a58f", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20226361336436643535366365626236386362373338613233353362646330663133406365727469766f782e636f6d222c202273616c74223a202234323737663239323664636339626636227d", "TOKEN": "040602ca6212bc9d2157a19b6b24e821c424493b253ba719ca8fb506e036a0104010e50b022bb1e80e2f7ad6baf452c483e91d472571d5cb4ac9b010756bc9f6f6", "U": "0415f6799c0f00b2052cf82d1aafb53dad6e826f71930bb939d4ccf78ce3ac4ca608bd0796fc735f69e73c7e70f00fac87f35050d5055dfd18ac33a4913ab9414f", "SERVER_OUTPUT": -19, "Y": "0e09c629bb0716f517efd4fdc454c84b38893d8d877b56d231761e1abecab293", "X": "0b89b359f77cc164e31c1dc31102a28902b7437f418e502f9a6aef8c03769b3f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"ca3d6d556cebb68cb738a2353bdc0f13@certivox.com\", \"salt\": \"4277f2926dcc9bf6\"}", "test_no": 180, "UT": "040dab2a8395903e706ac5fc6a1993fcb88921bd1b12a3a931e1dc7596f55f319f0143d8598a966bd6b7cfa97ca371ec774e3bec50c6455fd833565365c2356e5e", "MS2": "160ec8118a02dcb140c95d839e0dab5ee17babbe20e84403c41f926b71985784", "MS1": "0f948f9d0727207ef0e03f3b1f28a1222b00f3deb6aba328044f7f62e6090fdb", "CLIENT_SECRET": "040d175d6917b607a321c9a3809e0a74c1ab21b08d0dcab8a36a97c0292ac340d819baa02caa7f01b838d3a6464dc8732cb3bbc4308ae2bcc735daea8ea2bbb5fa"}, {"TimeValue": 1437055597, "SS1": "1a352ba52bac950ae4ad19c864746016fc6e34dc492e135d7f74890afb7f9c79209122d5f20cb4b386a3fb56fb202d5c3e2e1a4f6b0d9b2bad1204c6f1c6b205030010af07afc8ee8d926dc25fa25fc2e3b352a09ddf2a3246e142a946924da20419e2ca52d44d564d6dfc561c9c4608d105846db6c2cbf82785364f913f8e06", "SS2": "10461f6dfa0e876bf61e44698c3875b4753acb0c140c01affba3ed5815f852ae0560cd1f2ba3d476296a65a7d2f3324acdae7692afbe4828f1c01fa26497de431ed5f7d92f74523f2e835a0924784678e6b70ab98e20d8c2717e8b01c6f61f950e68661a1e10a51adb888fc562387bea642a90d0456619a60a67b2a6f3476a83", "DATE": 16632, "PIN2": 8999, "PIN1": 9000, "SERVER_SECRET": "1e8f3b1c658e512f4f70509fc151084e990029c7271fbf5a4d4768c05a20953214c7d9143ad9f7267bdd1f0cf723f4d5e5382d9360ea646c94173b354478096b0b0eefeaf351edb5fca3f1bf9a9f22bf9112322d7db69252892a7431e40c9d7b15f1b816f3174689d4d253bf2bb139cbaf1c07fb39515daf141b50f9790a2804", "SEC": "0409173120e8b594b1e58fdb5bf50f9f3cc4d76c5435c4127d4d6c4d66aa6fe7cd02b00741cab03678390203bf355b76e6c3283e49f13304edac13e6a568ad1239", "TP2": "0417156724e523b4da3ff9c91f382a041a5219a58604e73beafb388d696823e7a40c535bd3ca6b6737ee63e396b63087cc7a0be0dd876af092cafd1e9bc93fa5b0", "TP1": "041d7af3fe647f8096753d0601a61ea31019757cf2e67f68f86e9dd4c0a0dd7e41092516d4b5c79c34e828926605a7670aa2044c67e6ec5d6372330b06cab802fd", "CS1": "041889a71f37402c438eaa809c12930e66cd5f6f0d1db76dff1abb9aa77710d5ee21fce9355009c6455eba9c59a17cd306f7f10021ed1de2630a434d2effde95d7", "CS2": "040ec524e7d02a286d006008ae588958383b119ebeae12ba728097bc2e2f9faad9054df6ef1f00a448e96c017e1f5f246b616eb242b89e3364eed275067488360c", "HASH_MPIN_ID_HEX": "83d325882a4409118306c91e06d0a382ae248ea8cea1ac14ed1fa2b4f926d6a7", "TIME_PERMIT": "041212393b2bd7de4c24ceb7e818d58c394327845717bd1799d3cadd23b3cdae3214204b3c63eb9c6f68f459c8bd10cf37d9dc364c59cef33bc57ebfd29bfe82ac", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20226133326235343733386639633330663734646263643966396666373230613362406365727469766f782e636f6d222c202273616c74223a202235643364303663623236373162383036227d", "TOKEN": "0411b01f415a208f92f8c1ed4e12b0d91233b30ddc73d441a2a3ebc06a58f73ac5005a105ea14d79e93e700b5f33da1f8d3404c4e6b364676b7c24ea151cbd8c09", "U": "04017377c90d62dc72fa7df63cb7216534cbf0354fefd2a4bc7bd79233d0308d180ad624e0a18b46227116daf7acef8d48b388ce371c196ab09546059b0e3fd056", "SERVER_OUTPUT": -19, "Y": "01ccf34129b9db549b7fa129398bea0b331833b4ae890ef0691110b38d3cf252", "X": "1ae13446e5b21f107d8171f9cc4aec420955f47eca34695f008c858ddcbf5216", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"a32b54738f9c30f74dbcd9f9ff720a3b@certivox.com\", \"salt\": \"5d3d06cb2671b806\"}", "test_no": 181, "UT": "041edaccf820d6b877560c1be7e2385e1a310a24070cdc240313a28c5dc449e96c1be8869fd202880bdde6dcdcf0a2e76f89464a50bc9824dd3c849bdaedbb91cf", "MS2": "0c111c619883e805ad1a98b9ac8691e54f0c86f2d7d5c6b6b68875e2fa58f738", "MS1": "011391e726986df37a7db7cfd195cb37cb4f984d76e02a4f5871d48eceec6449", "CLIENT_SECRET": "040f2a23a4a3675ccef9f105fa51404936ffd30ca575e62152c9ce2df34d14eb280289a745dfe8fbb492e0e5317dd97133fceabdcbce751c94830e4cd646ac46f2"}, {"TimeValue": 1437055597, "SS1": "036403d6cb6c979f28db11d14d12c915c07d5d339466888dd7c69ef47c3b57cc0fd77ec3ce01674a8235fb101ece0fd00f5b16dee91dd0f64fb0a0f9e0a3392804b703d1e1dd2ae57812ab274305a775185a990653777bca732335989312db26077392445b9d0cc15d9ab624a0fe9d48d7522c49f58f4f7692113613085f49b3", "SS2": "01ded965da9ac193925c7da2b84e0463f6e7f18b42110993dc3295ea15ff924c1c8b3ad38676ae371e445acb3c1dd027cdbaf34ef7d26fbd023591fd039ab21c21ec57608e8ffa23a50899fe40f70baed8f3da90eb10d1ccd593261d9b4db5420ace89cab47d4f770e3525950957c9e3778874f176a87510bb5d1dca228727e7", "DATE": 16632, "PIN2": 4622, "PIN1": 4623, "SERVER_SECRET": "08fb34774657afc7bb446ae16e09eba1f7fa27d3cf361cbb4ba9ad4b911c721418df3145adf98823a0a34a05fb308fc25061385c3adabce2e062c56bba43a285083d19fff51c9feffd51fd064b667332dc0b6b7b2cd01482e146d115983703ee10e601303518395d9f0c2404804b0728583cd95fb2fc365759becc6eec145509", "SEC": "040c738e64c3406ee72e3164106821ecfa5f29f99bf4bb8b6fd45511a1e680b69509c24d5c9cd4af6fe6c50dae80f8c208d90a0b6c666fef837b3d276147e0317b", "TP2": "04008af42c308e2e2ec99bf191bc849f21719f326dc3ad969b050bd2444284aded01603e7bf50c52e0f688f48e7037edf46c8e4ea79436d09b5ce6a035c694e1af", "TP1": "0415855b50fe887eec4254c0d9ec8a87015de882ada7fd3749781cbe6c0b841b18083e375cbe8712a488d457453d836056c44fa73fa97be3fbab64b37b8d318eca", "CS1": "0423d3f5f85b29abce7d803a493de2b6e25d2372723a5262524f96e0594d88a3e10a0856a9ad181fefbe1ecd3507aca52855d0af935993ca238952f77afddf2843", "CS2": "0400de5a3cc53bdff85a6a65a06fead4bee65ad4a19bfbd9905011970fe25424280308fda122e88ba945159a3e1c3843c7b61504032519c59438ef6df83fe88af6", "HASH_MPIN_ID_HEX": "8eaffba0a310cc4f704b36a94623d52db166b30260f7b8ed7ae6c6a1b7b3dc1d", "TIME_PERMIT": "0409e99c8055275ffe8158523cdb8ef2daf08baf67616d195b2138a90109ca1f39060dcc323aad79db2ae1381f58998f3b99dd26a5bc026dd93c2fdcf2a4807b80", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223234343263306138376434323537613362666136376439616131656134353736406365727469766f782e636f6d222c202273616c74223a202231326465656535393165633966373863227d", "TOKEN": "0423cf1bfb374091bae0487af9559be7ef2cf9916ecda7985039ce958a9a0ac47e1a04271aae510a733a92e0cc6e132934eae1b78a939b1b4efcf5c209d4a28dd3", "U": "042161a9ef8d953cb12ba09226699520dcb62b042d9a2181a9216b0a23fdabc1a9044b757553773cfa6565715c72a7e3dba8e80dd9f507c248f85d4790ea13af3d", "SERVER_OUTPUT": -19, "Y": "15856fd3888e4d3ce5cfe0d0d2388f091379c39f1d24d8bee03492373fc25425", "X": "20f8662d49d2dcbd7baf1586df898ea9877364afcebea9a4a81a377d94cd1f85", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"2442c0a87d4257a3bfa67d9aa1ea4576@certivox.com\", \"salt\": \"12deee591ec9f78c\"}", "test_no": 182, "UT": "0423b6435711878a60929f6821b9bdba16b631a399c46118d4c97888fcba8186bd12cf0dc281388e8210d6ff521a061e83713b73844ec5fd41c55bff758b41b4df", "MS2": "045772696a76fc17a384326d36f93c697d80b3153781107efb4b6b5aab884fed", "MS1": "21d4110bb77f49995fc84a9ca02925af778ea2a69b2db773a123f0c460ea4492", "CLIENT_SECRET": "040bb2aa157e1f8101df3d00e9bef0f6d3519b908ef2ce547b63e95e8310f27b160775711948a9d586dec889a7b87c11ad31acdd8ebc90ef82dbfd00a6c772ee88"}, {"TimeValue": 1437055597, "SS1": "17f3128fc08e069094876ba762cae963665098cbbe9ff858393874ce930c27c70e2874567bdff7936ed5e0d070521abe6a5ffd12de89781555ac50be84de54cd22389fc731f56358bff233ac54cd6d920bc8ce5f4c35e5908e622d0f55f217c2049f8de5a507d33d6659ae3b93f4375fb14890e58828f4f9ace866bf4945cc8c", "SS2": "07b2620a5eb1e78d77b18a828c3b8563a3f6ea2e22df37a3484fba0cdb763a281ae1f693309ac6b2996e7574bab394edc78a4b080773415018ab7937de501c2113c420f515969868e9c324dc371049e99a4fc320cb28e82ce198f741da524e6b1c83599d59fd557fc26ec8ee3f86993f6a48cc1cd1f791f099a95b81ba771e6c", "DATE": 16632, "PIN2": 3156, "PIN1": 3157, "SERVER_SECRET": "0b7bf347aa3a31b4f4e0b094a532d7c3b5d794d82860c38e7463632acd00d71607bd6a2a98df02b9b4ace65eb08e78f31a4475fe3b70df235171a8f10a4b09a213041590646f0f89f718ffff4e52edf156912d548ab28b0b2e48e8c6172ab0e715d89e9774a99a002c8b635c7c09c7531e2a95b99b12724cff6d34bb961fd214", "SEC": "041d5ee53db17fccdcdc9c1a6ae90c767079ee60e44c156b93a527a05432f0463300d4b397688ce01295d41c3fa7bd3b7f89026571a0e461ed2a7dbfafd8f17acb", "TP2": "0412e5732b5dc86a4bf0ddd8655fe07b076291ac85791c05ae9d5214ff315a1023181e2274b5c64cddbf413b7905b30cc8f4152482fddcbb646e98285ade620466", "TP1": "04047be104a83a391399c1e76c097112ef18f996ff0609a126c10c9f9a922809f70200c7988ff85e2c42e8a2f89346e426ffc6d312e72c87ceb6e54b362cff24ab", "CS1": "0420c636dd8cd462efff77d1f9c6e5261180e0f7bad8db7e8be7ecbd8c8f8465ca0a3b7b123397021035c84a5d6164019bd1dcd9cbae16faf5110d066a155301ac", "CS2": "040bf1f9268463603b597358e897b9b296ab769112a7e4cff6a623636ac2e62be011cf620bc229785d5dd1c1148308f7f750fdef27409c0ecb839f3fc4135e8498", "HASH_MPIN_ID_HEX": "36a33ae9ed9a24acde28c29a18feda9eb8b8419640bba618d1f14311924129e4", "TIME_PERMIT": "04223be50a4cd3a91ac436b97cdce7b586db889253b76f9e769fc4d23e5bcd6b7215fe523df6e0d0c590a293f9dffa8445b69c7cc77821cdbf7b8b3cbc87d0ae29", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20226164343030373863393166656365636465643236313166316665666432663462406365727469766f782e636f6d222c202273616c74223a202238653932373539623664336435666663227d", "TOKEN": "0423c1c18d322f27aededc3e3c12a9a7ec117671afb7366b57737907c000d26483009656683cb4ac503ddf8bdf418c2f41870834bf2cff8967ad4f5cb258fcfbb7", "U": "040800c3619f58aa9df36158025c1b87f3d9bfe1bc7d2e953cb675f0f64b10eb4008a276c154f34c5c36a4a478eb10e707c741921f31bcba033aec020391fb152a", "SERVER_OUTPUT": -19, "Y": "02da1ece5474b9c683106ca86170b1c364976f201306f841a60104fc0291991e", "X": "010d819710a3ba67621b0d3647eb412f7791c386eab862dbcd51803d7aa2b21f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"ad40078c91fececded2611f1fefd2f4b@certivox.com\", \"salt\": \"8e92759b6d3d5ffc\"}", "test_no": 183, "UT": "040a4bce4df04c275d20e2c8af5ec669f244d2041587ce2242280ba4b84e4955aa0f1f371b4761230f897389baef3b1029ca5f132498110da839d0e55276845738", "MS2": "18722ba7f6e0863ee6fd0e3602abf6bcb845261ae697af9c898c7834c40e1dd9", "MS1": "0985617bc68872deee1c5fca48e0106f5000fa940d964baed31503dde76f698a", "CLIENT_SECRET": "0407058c3897037a6bc5d38776cd809fe56c938995e38221c291b4954e4aa0ddc9041c7882bcce54a71747649076d9210550035ad93137cbf942b8153e8f852c60"}, {"TimeValue": 1437055597, "SS1": "0d02bb246531b388a7d076dca96b8581e33a3171eec305a407172a0b262ed16620f0780eec87819faadcaa5209d870f743bc0b59fb315de4148e7e8d1e4749b718786400af0f77c324f8c7a59badb2dd312a7c09a8b53ceb7805e8193a10eed61080c63c030c90fceb30afbc24abd9c78bf223ab328726975adf348dfa98244e", "SS2": "0e5aeb0d6710dd9072ce0855096fc252991229b4c4262671cae0672eb180132c00a4ae72419bc5891afa9e21ba24724cc457f4dfd9de22e3c0bd41d17d94dda215d492fac8b93d8b1073da94fe350d76fae46d51af15a5b93c3e7f8e9e961475036cf819a7538f0563fa67199af33b01be794e75855f60b4f1c58c218763e154", "DATE": 16632, "PIN2": 1488, "PIN1": 1489, "SERVER_SECRET": "21d4ca21fb9694ed13ddd17cef2eb5959b97eb7d7f114ef0084a2500a742a2ac12f8b495e3c46e73906c76baf151d0ea2b85144cbb0cda5b4b9d8c28665d50b40aa7cdeda65068ea1065373661af59a5f7c0210fe9acee4474940efa8e5c36380256bcd35e3857923f58b029f6be4c97c0640347fe340a4729c75f4c71ae48cb", "SEC": "0410542af53a01c3a9c474d96882766fc4e70873f86b7f91f322e11fb2f404978a00340961f93becf160dc98402d3057e7674c21c87246c94cbf09a5b7527ecac1", "TP2": "04127d870ecbccb02f3d016e021383c16d79660250c620851c3502ddfe93bef62e13f075875f1dc185622d9705c4f758ea1445fc96b1546f4fa7a91824573ce5b7", "TP1": "040595308b61d2ab55c2db4f99a64fc3d848fcecbe0a17c995aa4633fbfcacdcc50af2f0e546630c1678b970713fcc0eb742cad81640364653f387e75c53852127", "CS1": "040c34cf50b95b1095b319de73164dd4ab4dff0ad818f153c391edb2f1fcc684c60346909641bbed242b0d1f0c469a48ca8decf4478957b6da44f64a7a056cc35d", "CS2": "040ca4a481b9aad401a7e3edb30c831052ea240866ee0e886a7c5ea8b26dc4ec1420becf3764b6512a6bb6112fa70303240e913a958dc1fe71811dea60e983b6e4", "HASH_MPIN_ID_HEX": "24ab9fe92f83f5f6ce33917d65940449984223c9e7bd499a73c1b9cb31bde1fb", "TIME_PERMIT": "0420a3a32701ea37b3e4132c61a57ae6d221df0645348a70bd17d6d3a94def54571cc2e64ad75b17c4c410cd226fc7f86a98266166405dc120a55a4dd374a252f0", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20226364376239353232653361326239353930623530343737363834646366323963406365727469766f782e636f6d222c202273616c74223a202232333434376235313835326261353466227d", "TOKEN": "04123c353ae2618b0037cc1e8418b60c60e54cb7c04f90c0806ea8000ce29e9baa0dbcc488b99fcb03246069e800ed2c912782cb3cc73ac1e09c4f5a3db9f234bf", "U": "041faca872c782bcdcd40ab2809caa1a54a7a2f651f4093e38c3860a04d4e1185000181ad8f47bec09be2390fdadcbc42e7d7dad754168342c3f0cbcd1d96dd7c5", "SERVER_OUTPUT": -19, "Y": "1ca0b94c10403a4dd7f465675d2dbf9769969b2e9901bc440948fbf6d6c1a4a3", "X": "1918b977f970d93ab4ea16b71962ae7c42f306bf0eddc9cd8bf14dca42e2f5be", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"cd7b9522e3a2b9590b50477684dcf29c@certivox.com\", \"salt\": \"23447b51852ba54f\"}", "test_no": 184, "UT": "0415a9b131ebc60688b7be95f33bc4696a46cf8be26211a99a49d5a2291b719d3b1eaf6b1eadc4adf4b4032ae80772c2b86d73f56030eabd39bbeeaaf8d8655088", "MS2": "04f0db11bfda842a6e2ef3e9ffeb830c092111131e789e876ea17255542a0726", "MS1": "0220e60dff5f92e482773235e6f7d7dca3b130a2343ea57513b506ba80da4998", "CLIENT_SECRET": "0407d9d97d74e76a87748bf5ada82ac2ee9a44164170d300d48a7f899ef2df54e1209129b73409ce0662fd193db425eb05cd74587551e2116fde4910b23665a8b8"}, {"TimeValue": 1437055597, "SS1": "0ec8b99c8e51426ea0ce73c8ac614a9f612c75b01c043ce6b755916b37c7a7fb050ceec55a6f5704f5b973c7728ab8b998e26366e33ba838af27986ca96a348311b1753682881c3bcd13a54d6ca34b8acf9535faf1a9e3dc9671867ed80cf57d1631e72656f85a7e464682035505fd9f523cad73181d55b1dd91950d28789a9e", "SS2": "054d463cb6f400d07abe32038b3e2056c52b938d854e3199e1620d394324024e186eaad8228f129bfe00c84a501bb7951d747d70dd20af12678fb0ea652d9ea4167cdd2506796df0e48da5060f33c5865ba9d75cd32ae3f6d76b911bf30e786110e359e96043e8f67bf962159588dd74319571e9be1311a17ad84d502edb7cd6", "DATE": 16632, "PIN2": 9893, "PIN1": 9894, "SERVER_SECRET": "0a509dcd50b77b25826565dd209d3e033d1bb514283ae6d7c61372ca4fda886012a0365439d18d228c5157c55a77c95f84e059fc31292ca3bede27adc0593a141408e779fb17790b0caad090c5d77b862e629377a193110ab150715af733123818b3bb2ed33bb251ba19eea399cfd664052620d214206ac7007c7000be01283c", "SEC": "0420a4bd1e8623531a86506b8f7446965d170cf96976589ee2ed6fa16cf6197ea323162804f9cf522cecca8044d8298d183b8f1c9f5d81150d1282bb5cfba5aa8b", "TP2": "0403ddeb0199e7dd1e9ec71542ba11b708a6cd9d5c7913e154c03704d85c801b511e73849b331bee7af35d9e0265a9432da8386d4f234e9f00785de00e1d77ad5b", "TP1": "0412599350c652e924787d086ea2ee3b33560dd9f1eacddd14a2589ea502dd10640548838cb1261e998408efa88e005a35d2e91a873315ff5a997848e92a210ca1", "CS1": "0407690d810ccd137cd75d60cf85a0f2ee031a970c506414131ff25ab62e2ad6de21d0a47e81ef2a3c4103f3b35c4714056611b8985f7d60aa3cd1f4f4644b8a2e", "CS2": "0407041738814d1fabf8ece6272df17cffd89bb0cbea24ad17eaed501a7f60fd7016b52d709ab2e99806a98f427bcff035c533dd2f8cd99bcae0d2b54d605dc5eb", "HASH_MPIN_ID_HEX": "27625a972d937fbf4f1f9e7c12b9e1543b5bbb434a06e74289a85dced292c677", "TIME_PERMIT": "041c31a8f7eeeda7f6dc73e3ba0381b1af8b60fd439a56954246342360c929430c08f573c0fb317e1c34511a1e52ab6e079d8420800e20c471a393ee9d77d846a0", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223264333666643631633161393530646161313666323762393932616530303631406365727469766f782e636f6d222c202273616c74223a202232306535303533366465666638346134227d", "TOKEN": "0405d27fbfc308d9d938951fd5c8c2ebed1eadaff078c6b680a8bc29ae051b69d60b6900e8859762eaf1f5397d47136a9dfad6a98e0b1e9e42c720c7b8745ba414", "U": "0402a4978378acfef89a9b9c726e33900d48b07e7b2976e884d0557c364a5b3d3716d340ba941bcc2c119c2c82e75ee764e4618187e60f5bee343b09454e87632b", "SERVER_OUTPUT": -19, "Y": "1bdae999a23b993daab6952e2e152be875d39a02714460e710bc925af11b9542", "X": "0510e28c714222d76f43da50bce1fda2f7139ebf0e0b00e8bdee91ed9c0e5588", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"2d36fd61c1a950daa16f27b992ae0061@certivox.com\", \"salt\": \"20e50536deff84a4\"}", "test_no": 185, "UT": "041fee641e9840c5a3b4d191e2a3fa6c0a5f0c090f10c98eb2d7017f4e7c6f624e19998639e21a22e045ba5cde0069aff4776e94a08da39d410306bf9eabafef64", "MS2": "17fea29347d1093bafa1c80a0c4eb29ae93141a3fcde0b4ce9307c422722e82d", "MS1": "237bb959466d396c8e483671ed62f920df4a6b33769e97fcccbc57c2fe1ffc3e", "CLIENT_SECRET": "0408e86e842f81d851d12283f1a41505ec82b29cc22ce03de252609fc69232c7ae1dca2d62d4167b685f7ef523ec1cbc37e4575b338af12f44f008cb360ea0a33e"}, {"TimeValue": 1437055597, "SS1": "180f9af758066614991ce3a4e83f3191cfcc8294599ac8eb360921b340d373fb1b864b657bba1cdbe3e370c3dc7388540bc7825294ebbaf21a261b843969e3931275d8c9c21e9cb0f7d7ee69c065cc3129eaa30de351aebf8d889cc9c4a79fe1214f4b852d8b09571260c8236d9ff4eabece633bda1c3716698a31dbc761bc19", "SS2": "059b899b7acb651d9b8e3e8fcaf3577a92f63f6c550879c49381145702e85ead14a13d42c8af1251d20f266ca3f3d7d9c21bb2556474950d6f9995e31ac7ab751063dd7ceac7a4c5a3ca2a36277642b41408eb66a701025c565bc3df2639afca233ff66c559131e2fb7853adbfc742de068c5f313133addfb703d7bb1adeddbc", "DATE": 16632, "PIN2": 8329, "PIN1": 8330, "SERVER_SECRET": "05ca15dea155e079dd51c45b502a796bb80ed1b79c8e8fb4c1e22480c56a3fdb1000b87feef9c3756482e648987525cd6bb3eda4ad17cde776d21b0f6ee191c22103a065adbac95a36861671690337106c4557f3f8a5f7b7c1f5d9ca856cb5d910d117ddf3deb985be79f66c49f4f7043bd9552cf25d8a12486f43ba86e38b94", "SEC": "041fca148d19641472106e6263903dcbe81fa863f52161a473a36bed118b31f2d1208d1ea3525451fab0369f13fcc911415f92fbaeeeef8a3421863818cffe0568", "TP2": "040e469b7b90c7ac6a27a34c65fac83989fb34b53bc1ea706e496305113fce71a803279c097dd2b57817c24d06a1a43c5014c4a66fcb13fb1c5c04b7b54ccb2167", "TP1": "040930b9dbff61e21a63dc4940221322296eac3ed33e66d5e4b5f829c3f7c83a4d05dcf4131294651daefa88f29abda223de4ffe0a79640eb867105a0f3762e1f2", "CS1": "04050bcc73ea187817a88d79d21710120571e73dd719aa9bc1fedf58295b862531053dae1753820ed7ed35dc54475f21f37ba33e5b2edb77f85f7e0a2fdebd691a", "CS2": "040b1e5c69b23128dc8c84749b5c0ca129977f9fb872b21a216eed8f1ea853faed1b7cac801de1ab4eaa688b14a4af3fd5ec0ef0bf38d5ef7700b14eec8ecbad99", "HASH_MPIN_ID_HEX": "f661abc8a93361acee54a4c333c31bc29f105ac18d43ece2c991a1380c99980d", "TIME_PERMIT": "04215bdda5bb7fc400f6973162642ed55d707db77c85b78892d2e3c18b00a4a0931ec86af64aeabd7dc5d6daad48310badd32c0499b354c5e42f5167ab5fe959fe", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223534303736306231663638613062326133373835306637333035666262303438406365727469766f782e636f6d222c202273616c74223a202264333937326462666361643135613035227d", "TOKEN": "041b308f7c12ff63d7f1ac50b6eccc23ade9b4ba603c240997eda22b70b4b75d0d1ad8460b6624e2a712bd26e8d6994679fc15e5cd09ae8935f9dd06fdb4bb4c7a", "U": "040de119fa4d52b8fb4dfb940fa0f64a0ec03f875701253a0911817a7bf24d8fdc1cbb12232aa4fcd4eb8e64feb73c1ae168b6473b06972571ea2f56a6ffaf7d8d", "SERVER_OUTPUT": -19, "Y": "2350235f167d8776fa085ee2fd096724374194012993c681862d1ac9966ca235", "X": "1ba82298cd047c8b542dea302b17c4e477d39d372946bace272c1f5e11535225", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"540760b1f68a0b2a37850f7305fbb048@certivox.com\", \"salt\": \"d3972dbfcad15a05\"}", "test_no": 186, "UT": "041a86b3363b1326b343cb4d77a6f4615b9b7670f18cf818f5668a500fe5f01a6d20d87ed4ca1e616d8835b0edb8aa6d10466b55a90c4bd66dd691de35d6cc1f28", "MS2": "01a8ba47b7b897a9c885f187a49ce96838a117f950b5a54903c92edd684fceba", "MS1": "045181cb05a6568ee9743eb87c7bfe1c579be4333417573aa7f96be4ac48b4aa", "CLIENT_SECRET": "04068f25f65ce22fb7343fe6c7f19ebb8f5bb4756d6b6750d3179616152d2cadc818769884e09aeef01c12710eacd482a16816f12512c36b78e72d1c2774306154"}, {"TimeValue": 1437055597, "SS1": "192c87450eacf126b2dae716aa4b166cff41906e285db17a56f152e7f9dcd2831bb806c201d9f4c3c757ef8b47bb3fa16f6cf808504aaf7bc6b395dd979b277422896fef96379fd0b10aa2c89bda70de2ea3cc1dc24b9220de9d065abce1c4030fbc7177e3195c3276a5e8464cd08e1ff2fad9762a2ad5c829af2abf871f5727", "SS2": "055a430773becc2ad78863282af0fb698325b483ea16e0efdfc0f78d980c47fa114dea90082387d50c381768134fad7fae24d68db4a8c2c7362c2e0248d23e9501ffa599b9dd7c474072601f1f7f88da9ed9c72fcd83ed476f47f0a33c782bd319c3190d8672784f541205aafd9049bdbd7b86c7e38e846e5564386e83d3fdcb", "DATE": 16632, "PIN2": 7273, "PIN1": 7274, "SERVER_SECRET": "0bfdebc160884650fcbba5439e13400ed6940d503a6ece8e3251d93a711e3985163a300d3632f2ee508d8f0e4e1b993baf3e716bc596c50028f42929def267b207eb0dffbf7b09ecf3ee83193d156bacb2b91a553808edbcfeff3c94a541e5351d1fb42d6111b935ebc4d847fe6a1ac9bfda3cf19bbe13775d428276829b58c4", "SEC": "040dc844e7b5cc125466152800ce6602e1ede3e0346f894443027efec3e44091e721125a677f0a39c8846ef979bc8cf3a92025177ea5cb586d47f2a7117a0e3128", "TP2": "0420ad5e1c089a2f55872679492e46eb84705b643aba7b38fc1f469ed822ef2fae22f27f526a48a02d1e07f03a1e983b36bfb74c92ccee842ea86ef7a9eb239b12", "TP1": "041cc737dd7c9698ee646d2654b2934fed05934cfae566a3df6417fc1c31231a12164095b34348b5e62a8278f7db79ef5693485e044e0a42ef88c8b98bbb1b98d3", "CS1": "042143e43bad7ae55663c80e57eaf8a96386c4b7a6ffaf5756a29d8b87d3f5af7b06e8b4e0d616c559ebfd745c97f303d0379be284b26975e9ce0195cc26e00da6", "CS2": "04065bf9bd39ebeda32dba275fe979651355065235e805a6091645192972875a59194bca14ddbbbdb1a272ccaeb92da9c7b44ac1c1a5481fc8ed81b8020be65e0d", "HASH_MPIN_ID_HEX": "4951e939ea92b95871734630a5b88bee7fc490b6c19948b4e4533f050c2bdb36", "TIME_PERMIT": "0410a766c798f11b1ad3382f6fc7279ae6336d1a2896d8dd3e7ae2d2e9409aa6dc236d306f108fb03e5e3df4c53e98971d17e275a3d9045a675e8108bc4882907e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223265656566623762323730376234386537383963313734373532613164316332406365727469766f782e636f6d222c202273616c74223a202237653637623831653239623936643032227d", "TOKEN": "040cce06e0e38dfc22d95530997005b745672363bc4876eef3e638060f728ae6b212fb4277aeca42ebe1e7581bb999bcb053ed73529555278331c173382e919961", "U": "0400c9e23da20712858f205c79cd9ba0cc6cd91084e818a6b4f600eb0f59369b1c0d19d85f99dd1e66f6290d7392d0302141e4e67b02a980acdb5f09916ee20391", "SERVER_OUTPUT": -19, "Y": "173e77b6a7a8409e32dcae98410fbf71db84dc864367bad9bbf50873e948530a", "X": "21e65d8c10b414741e243f2c4d145c8320cb9127f178953bca3bfeadf729d008", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"2eeefb7b2707b48e789c174752a1d1c2@certivox.com\", \"salt\": \"7e67b81e29b96d02\"}", "test_no": 187, "UT": "040e11e66b59f16f07d683dcf21b2a5bf64899bc602fc793046109cc4e7c4edd6f12f73ca3e24f799af51545f7d190fdfdefa48f0dce032a862d0a7360282fbab0", "MS2": "056fd46ff421a8d71e92bb40f8b876702f31f352d42fcbe800d29743bd0a7320", "MS1": "174cfc48a9119e41207d5205512035cf0a68c8205251a989b62da9edfa17c179", "CLIENT_SECRET": "041525cce7dd0187611bed41b53eb75ecde74e7124de4190e880d6648a50323d9d0af9ef6caaf2b9a6b7ce223c5ba4b62c32c93a7a218befc414e0de3bb5b400b9"}, {"TimeValue": 1437055597, "SS1": "003c20f6c309ec447865ec1fbdbfa1dc3fe995ae423f50655af8e45ead35c28b128f8b3ca739d03d841afd23ead5c7fbbcfe188fa3607b7fbe4c4e1c99975aab1af7bb718d8216ed32ad7d5c0799c54e667f885916d319276f13e0dc08334cc01f5cdaa54aec3ee154c26e17102cc39ab302753e94cd681933c5aa179b12b3e7", "SS2": "23ff2a3d95e10f753c0842599b688f30ca2f5784539c29f644e2c5bb48bbaa8217888539dc855b9c1112665bb1d88e0224a6b2d298a874060da435ee94d9e9281016bb9d8de52120b8242dbbfaaee864c6d7a16f3f329dbaf7b84613f19af15b1d7addc32a63793e4386b2bd96f4031a4090ccd9d2546ad9afa630bb89be1416", "DATE": 16632, "PIN2": 6548, "PIN1": 6549, "SERVER_SECRET": "0b309cf7671cd067e313b44733bf932dd871a806933bea8b5a14bd5943d4182c0c4f4029a58182f690e3103d45bab4943b9df62f39f323115b2fdca7368b164b1e70b6c5b450cdd2f14343cf1b7c3a484dd1b83891d20cb94acc0faa80d4da390024aae181b9e80c58bef6bd7cadeedf85e79e6d2a7bf06a696370d84d5a0c6e", "SEC": "04125e1decbf42a2cba5473fec75f446fd4e5368bba1a6b60dff8d07e8d3b466b00e3b4228a9a8b5afd5033bf0a4a4b636af4469b7c706b136093cdf8066fc9036", "TP2": "0415ab6e0048f40273814b8a699381970a6325540a435e06e0324966e65cc416a61793c12d0da3549eeb5174b8bea8d13a8f4e0e51281c4efe117e50f6d59385c0", "TP1": "04109b53ad41c36a34f54d4efaa123257994c25abd2c90f01025cfce941fd08f4d11d67488aa58199755123c32b6c88ddcbaa7214eb2675913441ff62eb60ac7da", "CS1": "0411fd329c1d8a10cc4d30d08851a61b6b315bf09880fe6dc64b432c9463e3b9e30dc641ff1e9f9703b8033e4f2513641724e40446e0669a973fe5ab634ee3e89f", "CS2": "04057c898a7ed4626aace2f59a31020382dfaa88c73548daf9d603852e5e3ef25a021fc17e372b8eb32cc5cdbc49022f500bd5c44f7243573c80b745648283f598", "HASH_MPIN_ID_HEX": "85d7af71b68dc5a26f61be74ac54e22b93cf2d53734f4454059f3040bba9c10e", "TIME_PERMIT": "04216d3e11887d5f834ca5f996d80a0e67992a28fe9038f7e4a34772e50346792518cb680b7ed90342966d9b314fb37f06d0f8490f3595bb3a7c6092044b89e426", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20226164363365616463633633303762333833393365656465303033333938333036406365727469766f782e636f6d222c202273616c74223a202235313436336261323837306136613862227d", "TOKEN": "040dc0a5ef81bb6ac682e2918d4c5703bc79e59511a6c31cd56421eca39cdcf214049effcabfe75aad8e9b95f9d2a6a000d1f4a8c2fce36ad442d193ac882c9deb", "U": "041bd451ea275a30b0027d465dbbf48b84367b63c40442fd560ef79eb6c629e42a21efe778d8a785a40eb54d088b070b410a0335e974537985b7a0133611ec641f", "SERVER_OUTPUT": -19, "Y": "0bbcb7b8db318bf00f526fc5f1d8c08dc401c2ba9560167c7ce8f25ad102b4b3", "X": "187416d46265f601e2028d1284bd832ec02ea48420f74cc15f6c246fa0ce2c85", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"ad63eadcc6307b38393eede003398306@certivox.com\", \"salt\": \"51463ba2870a6a8b\"}", "test_no": 188, "UT": "0417e3c25ad834e9fb54509e2a86623e7395ac5e56e3d843d911ee546db3a7d6f00e59814f3b1a6329df2a8fdfab21270b1440aba49a3a40b93fd3146dd0440a92", "MS2": "1ffb70c5ee14598f43d540782abf64651bf3d60278467f2c7d21c1a2a45f9abb", "MS1": "14635767c56e1c3922ccaafd91e52e80f4b941b30b4e9cd9370006aee0443b54", "CLIENT_SECRET": "041e89d00310a6059c52d1736d7b3108877dca4fe2c47cc7aac3ef94081582007f1e16f8d511b0e15dff9691134f7ecba4aaed9e2cab6c8f0af070f5bfb859c870"}, {"TimeValue": 1437055597, "SS1": "1eefc7a8e2ad6e615c517a875b26c6e852c83417fcffebdc7714760f117d15db032aa98648d4a0676b9e890f101d4a9937c6ea356ae6eff80958e784bb3a35ac1f89489f621c795c56e29f11ff77b6f67522050c439800ae9cad0fce89257402009f6580030c8e140f0b609cce539b1b6fe3f55f3efdb4339ec35188a3e3e917", "SS2": "01de5ec976d95f730ba390899caa0c21ce1261f811bd322e39c851f7b515ed690b8384e152761c3c31d812c244aad4256163a91bb4e77f4a75d0525fd257ec1d1a0045884ca736370a476fbe0c13a4f5ff494ce02e84d0fbff930d58644a4b5510b188a2414767617fb9761f58c9727d4e61e45c8486ac635102b79bd519f528", "DATE": 16632, "PIN2": 2894, "PIN1": 2895, "SERVER_SECRET": "11dc375c1a7e6f8196d79d75c6df3bde20025d86706d5ef3af22df24b55fc73901b26ea96c3b27243d8d640bb695652d36656d72b8d0af4173885a2c7ae93ab007b9f968d89c393494f945e4a14266a59dc76e3a46fff324563dcf735fd5e3b8124558599b93e89f862f153ef36cd922619e5e6c4a320d383ee5ae2f77cde9cf", "SEC": "040d71047124fe432f36b29e269f5f01872568379fb6690b579fe1ee68a8b2a46d0ee4433347ab90bb200ad22854165a64f994b53adfec512fe987d31ce7323553", "TP2": "041f59dba539a237f2c1fc7a7c13842236c487bba9a3fd77ea4261d571842ebadc1197281c903e267856ebab36054273c64940aa643534ffb65fe985ebf241163c", "TP1": "0400edaced839f0db7984866792232efd902f914e7e9ec3d4c4f750e970b7466ca199d872ccb6e5f0d75108a9f2242d4e49a6e271a5d8fd0e8c097c160bf4a2d49", "CS1": "040d36ab25b2db821a0386cc23c82676177dc341cc4957f89b7607dcc4d874396503381593cac4f340b17a0b4e4762af6b5663df2ffd82160d3c7dbda7a8933b5f", "CS2": "04039a71bfab64343cbc08747af5d244b23b52e3a7b43c41ba4fab900c5c0eb1710987734afa20879e1881a0f2c628d8cd8b6497985d2020780db63052028018c8", "HASH_MPIN_ID_HEX": "997cda29e5a1ae694437ee08e2c5b0dadd10b71e6de7537df38872527c5f8a60", "TIME_PERMIT": "041936564ac239b90b2428b2fbb1063798c9a00d455febe383fa01d641663a03e02270a2282b69eaaf035e15a75bde3f3472a5137fa4836696741b553051f8336f", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20226430393433316161393130316561386634393862373135643062373331383232406365727469766f782e636f6d222c202273616c74223a202263376662646461396637636538366638227d", "TOKEN": "0405979d7e41a65acc6d06be67bf9846f295efd6e6ba666f838b12372478dbf2ae0b49bc5d5ec7f0f7e4bcb2e6d58c79adb02e021b28694b4f964e4c8f88c7160e", "U": "0416a8600505c851117b42c082e79c5c204b5d8f9d7201053a2f419f8cc1400c940d1505ade60cf2ba49db5bc5d350d96d0e9fc297f96a7f7dc67257ae8d7f988c", "SERVER_OUTPUT": -19, "Y": "0076736a77a49d90292c9113961a069e56a785026c97658e7c954677aea15063", "X": "0845f810a4c652061c479890ec786711addbcc19c70fbd482e180e1a3d7c98d6", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"d09431aa9101ea8f498b715d0b731822@certivox.com\", \"salt\": \"c7fbdda9f7ce86f8\"}", "test_no": 189, "UT": "040886bb29161b0192cc8989b73e3f308fa01a6c29d1d8086eb86742263b670c201dd0fd5371290345bd59d1571eeae6fda52c894958d920ac52b17d55d053d224", "MS2": "11964d73b03c98383998a63062cdde9b1a4c255ae3611ac55d6b2767d1169c03", "MS1": "1df9ab1406f8c2e3726136c8fb56bcaf010e19e94f16d49a48845b42a38e28e0", "CLIENT_SECRET": "0411005e210fbdbb50b39329473e2aab36e7035a8ed75dcb06626d918f9f62981f1eb886450ae4d1cbac7e931eaa5b68f19eec3566d87eb61208c7e51fd2385245"}, {"TimeValue": 1437055597, "SS1": "02c0bcfc32f0840de5ddbc1d5aec20731a16041d4be3820838a22590d5bfbfaa1813945d7637e606c4b9e811a01a481412a78e5cd09e5aa158f51bcd65e840a50d71d1d497245d19194b80fb5eb924258fe5a276f2bd1582ea5bb404093876e9014e4168fca8c792146683ed0572f608c3f203651ef2717f4b827edc6127ebde", "SS2": "1347b73220c2b23e4276eae257fb7743386f0905e9243da500929104d3964376176e320fe347cb6c0c888b7642b435b7c2d0c4dd3f7e032bf98c122d5ac0c3ff016e85703f120a744b8a3f8008e8b720b438ae6a9eead7bb2f97147fec6d86e307bfb7227c4d754e71e1d77e747b73ac7edf8efb3f95552b40535c6d0df6c367", "DATE": 16632, "PIN2": 1475, "PIN1": 1476, "SERVER_SECRET": "1eb656f60427c42c849a1d0581e5ba5b33ca730d7ba5ad041bdc9b9239749cfb00bfbbf641be58f3d276edfb2718e2f2a47ddba467d745ba2b848fdbb2af9a93185bdbcf9d24b8c19f409dba79d5489616dac86160cd654123409c4e047cb6191ccf7d6babde5cb3a3dcb73c954baa10f9e312714a90d0ccaa47354f35474315", "SEC": "040655122e6eb9b875a4343e08dbaecc68a83fc797e64dd23b478f39d209729b201a8a6b3a307d7007b19d3839d3131a91fd1e28dbce4d0e3d3a610a8134894d93", "TP2": "040d3f0f9965ca016cc727893fde54370f999016b737aabc53a084eb521bfe4b810d38fba17271a240847d3232455d5da26f66381907e75d49924d694cdcfbf670", "TP1": "0422eccc4165fe334d42bc5ca0d8bef15408bca1821c07f189536484f7bca3d6a4049bd3df08c4e4820d81119f60a4649188934d66630c1c80f6abfb688b5e97d8", "CS1": "0415b701522c727c2fa40a22de57eaf263941861a7c3b42f68e9a3c5345a9957e816be27756fa3360b6e9e946f986596fb9d10452c5c75d8a3ae15c3d1576dacea", "CS2": "04207e92f90c19a50347388feadebd964d694003db6afc68cd3a9c1cee2de714770924cae30620931f6b4c949aa8e961abe65b9ecd0fc495986689b58966172210", "HASH_MPIN_ID_HEX": "13eab167f67b796f484ccef3c79c6c4bd9bd99b4461145d47c721a28cbd4d851", "TIME_PERMIT": "04184ee9cc5b977f2ad73f3d3031c254f270a98f207f0062c6153afdf5fe733137039c6061cf9e7fa03386e5bfb91e1c8a05dafa1c2dd8d8c4b2ce983f737ce39a", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223833323562373064323630323539666637633863653937306663363937383536406365727469766f782e636f6d222c202273616c74223a202230323439303963376235626436383366227d", "TOKEN": "0411424888238a2e981b353a43342acdc15422ec31356334a80f1dcc1b47b3d2341897ea7618427310501f9634d23e90f42fcd6047b019e8d4cfadb864edc3c852", "U": "04155ba0b309e9a983010847a4f87e3261e52708fb491e314fba3557becac51ea50e92c3181ae65e1e85fcba20901a91fa3cbf2a9cc0b4f0f1690249f593ee1d80", "SERVER_OUTPUT": -19, "Y": "2184be604111030be78b6423b7c03879c9420a7e3d618eccadf8bfb2e2a2f9f6", "X": "186472981d3521d9a821355de93b8a8d6bfd107a8d1ef4f6c1df59d3f923d29e", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"8325b70d260259ff7c8ce970fc697856@certivox.com\", \"salt\": \"024909c7b5bd683f\"}", "test_no": 190, "UT": "04069352f70dcaa134868fde73b4fdf909b1766858aecdbba8096250ffda0eb6631d8ec232e3ef1c10f0f54d2f145acd7f92950f3796e61a0ccd58fb814917332a", "MS2": "091ebfaa542265af9b179b9077974da1d74d39182a5929195fe40ef0d88d17c4", "MS1": "1c21127ea6d24ce1e2b030cf3119bd54a185db0cafa39c9d83369d73e8c63e78", "CLIENT_SECRET": "040c5db105a47888796f8849abdfff26e5fc573b5843bdffaaaaeaa2196903c90b1ad9225a89671705ea4cc093f827ed1f1d0e896296ef4cb565a2fb7ec6b43018"}, {"TimeValue": 1437055597, "SS1": "0bcdb5671827105a1e90c4ed11f5f3f25fd9ee9448f5c92a8ead8afbed14990b04b3e546d42dcc148ca24c085bcfa19b11612734794389575f386cf0f6a9ac0214b9661e2b0ea4c3c5364ccba62370757029b5e217ca4bd100dc3731c794de2708b3a382029d8a3d4a97b508920f8e0f5419230662bf3b603c2ac2d594f0c1ad", "SS2": "0a897a575168807f36af70accea5ff77c355c5c885c1f5dc5dd4c75a60a18a3506c1d39cd81089c7bf80be25eaa5399bc8ccddef005bf33407692d9cdc764d9823148867c9b9f57eb675faf82b117a7c5cbedd2c65475fcedba868d3d455641c06cb1746727335252333f6a6a0c0e401038264cba248648d521a82817bfb7943", "DATE": 16632, "PIN2": 8183, "PIN1": 8184, "SERVER_SECRET": "09c687c35f50adbcb7e6b43d0b41178f5e829a4ea179490548249d6768e52c3103616770997f5139b387517a31739f01625993c35fcca6956cee85fca8c6b6c516365c8a4c3d4e0e69dd6b782eea439309e7f262aeae11e16b9b1d1c4fb226be1dbe9e1de86a51cc19a09091003f73f8084c5338cb87615f9dadea0e2435a473", "SEC": "0413b2a8021b21a31224ea8b86a84ac0670f43121f95e5d680fd5270374dcaa9520497d85bec9459c8a089e4deedf3244d60c52118cd255a2d0fd9d9b8640c508f", "TP2": "04169e32a13f0271d9c42c4fc030bd3d36cf655bbd656ebba23dd59045a72b2eaf049bda76b6d06c0c692df925de48575493974f0e2edfcea0704f6c1b830c217b", "TP1": "041688db30665e7525fe51fa9bbb64bc90955ba92813c56f2808b47fc872681c641b1f13eea8d502f4cd686464f00cd9f5e6eadee3db32d5cc9380385d0e4454f7", "CS1": "040c2b0bb49ca6b4a6abe64e321ea65d0a78ef2345a99e4723023058933edd09d00d59b6cfadfd8127fd0dc8d08be46439119950434ec372dad4bab2a762578d49", "CS2": "04228b6d375a55a03b76d422ac5df54aac92c881a24d5933028133913ba6a239011a15f65ef467bf1c3059bcf72061675b4d330ed054040b709ad92bf9cd327ad7", "HASH_MPIN_ID_HEX": "426d572c1456cc4a7c68d85acc96c52786cbe8161cf6154ad7b1e4979c1528b4", "TIME_PERMIT": "041b329f1f86029917efc9a2c41cb9fb30f30b92e718cd25f6fdda754ff9f514bf015565f74b60b55b06779bede63e1d01348a98f45b2f01e4a514ba7ee8160137", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223532373636323465376432633033316634613739643131306232626666336233406365727469766f782e636f6d222c202273616c74223a202235366639383930373633616330623437227d", "TOKEN": "040f7a8cd01d139c9d89ea23f2936dd5973d07f7ef010a239539f0f85452bd753e1011ee1b68ca1948a3b7248a35f9563c74ecd8bffc746eb2b9eaafd423dcd508", "U": "040879d09baf918aefb822626e1a70b5976d47469d6b256c228d32f728df435dee0979bc4bb86ef3153294bff8157ea22ae7ce4593c02002a49391602c02e82ee1", "SERVER_OUTPUT": -19, "Y": "000f74a05b66d01cff2c3e6fb5d6260dfaabe5029816bd93b79cb3aaa2354051", "X": "007e6f360a8c1e5a69b0eaf5edb6f15c48b961a0e0fb313db29725bdafdce34e", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"5276624e7d2c031f4a79d110b2bff3b3@certivox.com\", \"salt\": \"56f9890763ac0b47\"}", "test_no": 191, "UT": "0412dca32319720126ef1a4d537656ceb9a1f64ce304aaf01b148fd1be7789cc7418314ce3860e174cb7783418c118c567c52fdd279bec4283012beb404f6775b2", "MS2": "182db01d23eb2bcfc90c52f1491d13f8288b2f4289f738823cbbce3341c7b99a", "MS1": "1e447c98b1aa8c2f6ab292e98d0159a37cea034a9ee52c1ed9a350a0e013b76f", "CLIENT_SECRET": "04068a9a7a5f8ff039dc2d2cb382637682958b7af20ddbb10c4154c9dadb873ac806439c4a5317f966220490a69050b0310bc77f4f15044fa2a834f2057059f93e"}, {"TimeValue": 1437055597, "SS1": "140e9aea7ee6e60f564b9db3f04ec26e3ce1a6a8dd8577a4af70bdf98bf98f1200aa51c43b89081b7f851d9fa984d97a50d2c58d1a127a6a1d7baa414497436f1003b7385a44fe88aecd7d7d463d818d1b888c5654d14a917bda5db0adcfd09b1faf0b255ad62fd6fc3e3b5a07f65e5ce27f69f561f3b084b2119c3cf2065e4d", "SS2": "0d52f2b7c775302af47b01f279b04dfe29aa4e165d8681b3873e20473e4a6d4f221a0bf9d4fcb233a7858bd396b2e3ebd47a2f2335ef3bf7e94496a9c8bbd02400d45cffd2053c151692dc21f367c87f88c33ff27eb9990280cdd3bd88f2378806d1a643005b75aeb6f8814c796df98db1d0e57aa212f02cd719fb98db5c4bbf", "DATE": 16632, "PIN2": 4011, "PIN1": 4012, "SERVER_SECRET": "23549c4571bb919814f0c7b947ec0992dde51074ee8106e488584254bcd898fe1a401a3e1020fa04d296a921b6766b983f7bf50e0e9be21e853f8c8113f178911084e01f2d4a16c8d58d73652a1e7b65da95ce4a7c11f27aa98468dee0ace1151eec346a584ae69e220cb9e1ef9e21e23dee3ab3b9be0ff12db1e294d6b954c4", "SEC": "0411d44378630aaef06ac2a2b2d5c6b2f72db842b75e91a0311d0b0ad5796c5bde0cdb173e4c0442318778a201a2de6b56ecdba776fa0a0bb503dcb0e84cc28e22", "TP2": "04219ab43595f909e456ab7af26cb25e78734b5c0cf88b4bca4a4fe1c0aea933cd04cdf55acf943cb70378e101028714a06c719d75192e30bd2a6670bfb338af4e", "TP1": "0410a876f824082a3fc81c786ca7c005304424bd9cb676fc3c0a7f0aa3c30df1990be49be1cf3557bc385aee6ba0200df98807888fe5e213097ea1d8a0f282239b", "CS1": "0413cf18e251659f576eca595102baeda3e2e9d0a263170664cec152f34d3facbb0924d91046629a4a942fbb8d75352f94eec1d4c90e59f4d18e6942a582217994", "CS2": "0410df510ca85ac26b2f746832a4c3b99b4e4e466d98a62788e8821f13f1b5616c1364047f8988f7cbdb164820b0bc06a4797b81c188c9be66bd8bc424e36e02f4", "HASH_MPIN_ID_HEX": "946017c2cd6467568ee959cc33f98755e7342d25739b34da6e858ff408d00279", "TIME_PERMIT": "040487ead8f037fd7e0041c62497fa292997e4aa4d8bd46130db0cb3ccf424916a2154d1cdb1062712a0576ce3b514a384093631522a2deb5f640e43e5f5041d2e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223635343335663935303139343635623630393261623231623635313464353964406365727469766f782e636f6d222c202273616c74223a202230316239646230396631393238383339227d", "TOKEN": "0422d9d7f5540b58993f251a83ad26d415aea47cbea9b96a3a38e71c4e3f2b3c0720c302584742a0d172e05ff5cfc64a03b6ec30d9d3ae74a3fd2b8dfd273f52b2", "U": "040be36f9c88ead0edde9e0e6c5139742f189f37f7e8362ecfbf69c37666bc2104002b5952a72becefb7c740c166e199dff9c94b96dbfc2989a3f82a0676d9ffeb", "SERVER_OUTPUT": -19, "Y": "1282934e9d0694fa516e48c07457773b9d0dd3da7d550f5b5ea021c5de6bbb7c", "X": "140d1f58e882b9660524eb626aa0ab8da8c427cf437144ef670cdbcaf8e020b9", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"65435f95019465b6092ab21b6514d59d@certivox.com\", \"salt\": \"01b9db09f1928839\"}", "test_no": 192, "UT": "040560b70f3b01291489b537fc003d65a27df0309c7dc84b08b5d3257e65980eb601a29d2071d373b4a796e3292baec8a45ffe00cf99a86b22ebaae5b240407eb6", "MS2": "1258f7a5a96f7e603492be6f15c20e75b43ba76e95a8da1eecd6662528ab673a", "MS1": "0061fb0ab5140f42c0a5d378cd403d86fb845d93044c5605c79fb99ee45dd25e", "CLIENT_SECRET": "041398508ebf52bb06560025c607a74b47523be30bdadf2d44fb4107ef6aaee3b11e6e72c8ebe358cf7fa4d32e3aeb6b8bb0e83ddf9526f3821863f42584961e8f"}, {"TimeValue": 1437055597, "SS1": "09233c511d0a3615211da99ecca80bf02bd70cee7cee67a407ff8cae08e7b3c212df43f50ac1ebfc3e56d8b00a6359198cfbf309c5b3a47d3374145f8d7cbce1236365edb76d5ed73772950cfa19e695132216ae5bc40e67459218fa6b14144b0e00deb2a9850519ab4d9eb3fe0591289c106e3c8332fb171945f331f5e88b91", "SS2": "1a8b06b4e6f5011f753dcc308b3a0e8d3f7767b9e551587e432e0e1dc81e4dcf16cc3a19bb04e9d2909dd56f2ea17dcf638eb10abc8d183a4bdccd5f8d5c414d007ca15c0f293a1543917f5ea7538256305827db1d4e6053ddcf99077ec93d9c0d31497272782f17007a519d378228c612f3738c83a03e2acd872710f6fe1e08", "DATE": 16632, "PIN2": 7275, "PIN1": 7276, "SERVER_SECRET": "12c3972bea74d5d941a0826fd357eb933fec672496e1c6ce97b1e47dd31055311a3cef0bc62bec36f7429ba0ab6702a066e1ec88b341351b9f78c511e5d162a71e3feea337736c129ce663ef2e8f33e0a793a433eee0882b6a43d7232a7c347f027d18e083de4d93f4e1ad4d1141d27f1801183d8580196ac6f86619aba431db", "SEC": "040198fb3a322187a19a03aab7af401b40bd8b18ddc065a993c8df6705abc978190b68e8a8997a52f73cbf4e11115dfc8935f3f8b0a8ee35b13d8b4b9da561e1a7", "TP2": "040e6a896d6533df792d3157d294b085d59d6cc82dac39fab1dc88724c6237fa83027060e405af00e46a4cac82ded6db34e737da842fe28ed39ece20f0c3845fb2", "TP1": "040d40f5b0098793b5e62c7c4babd0856c8cc5e358c720feebb733233a34b9c4c51abf4385322e34cd7b6dfd658becc43142bf98774ab8268ef99cdacde0eeef32", "CS1": "040fa6fcbddc1d34a29ecd8d260b8ed1b75dc755d02ea8fc23586c7964a177da0802c60e840ce6cc6654d80ed6b3a034cc54a4322837d444d697b61295a4e3ec80", "CS2": "0412018d0e02aa3491a9785f0cc1dd42cfc9b84b707c01517f02f8f1162bc183422086f8c74bcbde9e887597401d7c8c891ea5811aa356ee1439b3651ef264dc5a", "HASH_MPIN_ID_HEX": "a689209964190381648429d3b780ceb603e41e1903c60ce575aa06e4661c7960", "TIME_PERMIT": "04097806919b5c4365cae91030e36e0d9c34e4498f683b1049cb11626282f59a2a23b74ab554fff7f2425440505447f4818b89c28a007a7cdbe26907a5f33e5955", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20226132326163346162303466623938653635393139356466633865613234333930406365727469766f782e636f6d222c202273616c74223a202233343636383738306339343263323966227d", "TOKEN": "0413f5f2368ac8596c5418b03c37affdbb620439ceacad122fc0a219b819381fa111a9e68073fd08e147af42feb44252b958836d4f42d18ab38e3aa2a7833e1c63", "U": "0423dda66ce30882c6fddaf79747cb79113a9c5302157ac05cbdf162f8d0d398ac115a601cc45011fe88a507332cbb1545affa01f492d20fc1beef3d9984a085ce", "SERVER_OUTPUT": -19, "Y": "074532ae010c63123a8e2f4748a8e4611abbc865a06a1042ec1e3a41d381b48a", "X": "051746f6224f87c36d43e39d9fefcbac9949ac726d790117e63c50dab970cb98", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"a22ac4ab04fb98e659195dfc8ea24390@certivox.com\", \"salt\": \"34668780c942c29f\"}", "test_no": 193, "UT": "0405db0c5b545eedafd2dcd9225db6df064f6470f5d10e6caf38a25cb615ad2c1f04a96b9e4fd8331407c24bd0c215a873ebc45a44d8ebcbb88289160c929271f0", "MS2": "22904109a592344c443fe0466683b5a34d6a313e7eb85edb18d62ba6eb770229", "MS1": "04f40ad58531b2d612fbb265d88bd0c5a1367bc896cb5950c3df45906271e86e", "CLIENT_SECRET": "0402f05e96abb98f122379927dd623271f716edf5df057c2133da2333d7d0564a4023c17b2427531a5768b81061952f88e804b377f4264de2ced61c011f6309904"}, {"TimeValue": 1437055597, "SS1": "1e5ea096f1f1b94f2558a541b5b6dd6ba646baac29f88526a99b0b84f5fd8b0e073585e5cd9013cfb49beac588003088b104ca97dc8d2a86be742bbd5b0afcab093f7f40e36d2aadddefc3c05ba8b0d8ff8795f0954f13d28a699507672e85161d72f5c8a886ed087850011d798deb35c22b7a8621692939b9260162a451fe67", "SS2": "09a049072085872986fa743cbfecbfdae6f3b6b1331a851034f5203b7078cde8067dcd7c3f7ae3e25f7ba01f27e15f0294d39f6c284e8e2c329fef2960ea1c9a0092a9a96ef3a0af3cd46d98b16fb10c29392d613da462a761fdf51935fd6c9222e758ba024c2e1cdcc79233d7e4e6df940dfd160332025054574ff6adce8acf", "DATE": 16632, "PIN2": 7745, "PIN1": 7746, "SERVER_SECRET": "0b2ce45291ff77fbe9ab900df5ba54cefe3296f325b37d8fdadd2d1015d63a001f17d405cb9dcc316465c1c40a0df4d18bac020fddccff19f591a91d7bd15bf507a7b80de215b678bbf9b4e7208760f6c2a681e85b3d004e6437a9182661496a233b426d497066fa9158a8701528e8f8a52c40509ba92bb1bd68150bd0b3c331", "SEC": "0408c47460c7a9fce952ea4261054456c0d2e2fe595009445d463eddad4d62eb0a16dddfcc1661e8c2b2b8ac29e1380f5c4cbffcbd1c779d459341d691c17160bc", "TP2": "040b080f02a6ba8b9b422133148b7fdd9e22085c28ee7529d6f77524c9ee6c0ce5221790f289d920ec63b4028242343ec91daf1a018bec8f62fd6c48c6e3a9b23f", "TP1": "040d22b6da6e376362ba7d2b91f18f428400c3a6cd5c1378bd794570ba2261bd0e0d61825d297448d02289498d3d4379ba0312cde36c3ed6daeb34b39b8e4c3b1d", "CS1": "040a7ccc1b5ff76133981162f2ef923584aca63e54196d9e2b5413b22d7adb6ec809b703aee050d4f338cb957459a7abe292ad9b83009339dcbaaa8c05621fd0be", "CS2": "040480efb24679a987f64f3eab0dc602361b86cda26a3cd98f707c63e2c7539f4202420a0ce0a34057de2cb8980eff537c6a1c4758ce5f5dc5d5938712a008afc8", "HASH_MPIN_ID_HEX": "3b6e3dda375fb8712291f3212b86d39ff0ed46ff15176b91c6c4089be09cb3a9", "TIME_PERMIT": "040e245cc53653c7273eaac75c663991ccd07a3e76f4127a8033387a1e2294b77f1d9af3d1c962a21187e8e42e7631c16ae78c25bff6454527108b12ac94cc3118", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223630616230353265666663373161653961646532656265386532386431316638406365727469766f782e636f6d222c202273616c74223a202233316166363166313331363539323561227d", "TOKEN": "041a44ac859c85af85b932e5bbabc5cd4c62e4e2d42a356f4f6fea907a536654f30d05b7455a57751127a08cb4ce3c6c4fce741bfa603a2070928b5d225fcd6961", "U": "041c6ca0c426a170ba9fec6533845fb76171cf126811d16425531220c48257d6c11a662c08e9647980f7515553da7a13859d65b8f82df761ea923f7a0f466bcb86", "SERVER_OUTPUT": -19, "Y": "0ca59c911c58fe9273f62f0c10d1cc1baca6be3432ad603f407c709115bca7e5", "X": "014d23ffffb93d7a9dec05b94bfd533918e38607269c5e8c9cc39cc2824186f7", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"60ab052effc71ae9ade2ebe8e28d11f8@certivox.com\", \"salt\": \"31af61f13165925a\"}", "test_no": 194, "UT": "041232fe4c439d4ab83f85bee3e79c7f51635797e7cf08c1b36cb3e55bc50c3b2408f6700a56e914e53137e04fc4d0a734f3d6b7cbb2f7e00a5bfe27855673e8b2", "MS2": "1265e214395ce9f3b0a97faf43ffaebcfa6c3957039342bbf8f73bae505b96db", "MS1": "02e9bd3c8fa9d8f47d674e3c304f5140d11b870992b6a0db32a74de9e5d3e5a6", "CLIENT_SECRET": "041946495c8d6f446156dd7ca43ee5ef062aec4649e0062c74030621bddf2810021d4e74c58d6dbef787ec2fdf34e9de9696739bb81ce3add39a421ee5b1a4f0ac"}, {"TimeValue": 1437055597, "SS1": "0ada0ab924c48675c91c1bbda8a2a9b04cffd84a8cf7c46a5d8b1c33877f5120062b1518d97f9bf52b55ea7848867f9cc62c367bd0a921c214de79d7286d86fe0a0c522ce95afeb7a25bc579f90d29eaf91ea23f2f1d5972c474a550818bb98220bff411f8c2235c1d207c0e44bed6f6665d7d0c393ff59b6567e6382434b049", "SS2": "1e8942c1c425fa00ab8e185081af640f86b62bc1b8ef1e0a641516fbb1666b600d9ba0a323faed1a6fef0afd3c07225a0dfe9ccd5e8a5158a94edcc6bf519f980da243751044f63fef2d68389b7cdc924a2e9f8e9b4d10d54b890ba3da9606250ab1982843257b235e5ff3d95b3f7fae3a1ada7303ab933ed618554543c06aa2", "DATE": 16632, "PIN2": 2925, "PIN1": 2926, "SERVER_SECRET": "0b4de9c5d0d3178b454808bab59391d6f57d22752735b5afa44e8ef09735ffeb13d2a7600e7ca806184ac64f4f1352dee0dd6aecabbfe77766852fe01a1cc70b12e70c82af7c2df2553bb2c38b1070da7895b9e556148d7e943568bfcae1a87e1ad641a854c35cf4b9b7a7a29808248d5df7b4fba2e3ee66c78651497ae32f18", "SEC": "04112e38e32943756c92b56c7a05dba4ced67b26c947395124d6b74ec36b19b6d207aedf340134157d861262ded2fe7fbce45e554ce1584f1f8f9e1f2ef24021af", "TP2": "041b75cc39ddb70ac94c5e8f2202b9c5d8a7c5bfa9d8457e8037d03c17eb8552de07d75be9fd5e802cb31f6b3c7a1958eb1a6d3df470b5ee406cd541ea40e48b3f", "TP1": "040204d2e0f9488cb3f45c33a4027febe83cac89efe9ebd42b786ddebeea5588131d24d26033f740a72842622098a6033f5dc87ab2b1ddc47e6341ee009b9a9fc3", "CS1": "04156ec88b685071d89ec6fb4fba8b354fcd21a56d77a3f1e7b19e4ac7c5a8ad671fe57cfaab39bc333fb033260cc96e5a420178c7b26f3192719847cf80471679", "CS2": "040a372b23a9606ebb8b3b00e72cc1edb1f759d38f33b38d108098557fce21cd610394d241a752c6b419593fbe293ead56f1abdf41d7c1f044a8a0c9ad6b919847", "HASH_MPIN_ID_HEX": "2fd18ecdf7ee7c591984455b56e4cf79e25a4adebe7885605285a079e4f1ca31", "TIME_PERMIT": "04139a2d53dda8735657adc6ee09e7d778327e072585a66483e0130d3fa039f8590842853c3e87c56de9d2c05fd42100e6a479b7e935ed5f2ff64b46535e50a6be", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223166323764646634343535653965643065316638336136346332643361383363406365727469766f782e636f6d222c202273616c74223a202237623231363534336663333030626538227d", "TOKEN": "040711a7b84aa33156b1e85bcbe31978ea5b56abbe5a372a171e8118fc99587a661bea08a24079619a598285254aac1f6717802dd3a9f07b64eef4a483258ab44c", "U": "0422b3fef5b6cee4e76fb41b4936513f40167e1ccde7516decc422877ede12f0b414a672168f964a20d8b9a19ec4f780e77ee2baaebc0ec4cfb9b42481a7a4e8bd", "SERVER_OUTPUT": -19, "Y": "205a4efad8232aec1e8a14156fcc7848f55de1fe609d3a3b671aeea32fb6dd5c", "X": "0b748853f8275ce5694fbc25ad8002055c6d437d8bed4f7186b6801b5d5e4ec5", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"1f27ddf4455e9ed0e1f83a64c2d3a83c@certivox.com\", \"salt\": \"7b216543fc300be8\"}", "test_no": 195, "UT": "040573ab29cf8c204b9d6e5935313ec9a78bc368d3cf239ab0fa94b446064562de0b093872eb6bf2ada3d39cbfeffa8e1efe20068b23e78d8ebb1af41b84db1c17", "MS2": "0a78b090acbb523b7bd8e5abf58817ad1e5bb61379a3ec534f5ae8b077e59627", "MS1": "2365abee5ce19da1e9eb34719a7cb8535a34b21dfc167b1de879bec4dde2b6c5", "CLIENT_SECRET": "04237e3b5bc1f61bed3470afbceda91625dc4b0c862acc75c1d507a01a6f72d47116933e80faeb7908f0a8361e1d49657eab46819d46e4ed7610736fdf337b11ae"}, {"TimeValue": 1437055597, "SS1": "1c9a985c819c91dfcb64e7fa0deb8b2427e5460008e22f538f4434b4a0ed9a2110774894d78354a8879ceb81ef34ff2db3ef0f95715f5b0102b8f4cacce7c35e007578b1bac39e805c2f86a261d620dae3368484bfba3ad04f293187539a6b3c013d65a0cffdfd726b231b4700060e72665d66ce68131d72a818584444073f53", "SS2": "0f33b2836581ab5e23fc83942f060905dbea44e019646a192f30854a7ba7b2fe16c869fee0ffe8e9723f545ef6fdb23c7eaf85e0214c20199486875ce25d00b71cbd4a08c5352eda5a3585d4c2ad5191f9d27afba502cd7c01a68f4f5145f7d4089cc6d537d42b3ad3e05e5314d582a58d4d17f13dde535dd54d05f2d675ba35", "DATE": 16632, "PIN2": 3010, "PIN1": 3011, "SERVER_SECRET": "0ca6ec48f57028b21d9d6a69c756ee5d05b9f9122ba82e75847fc557ad990f491ec53e9ab2b07cc7b7a715dc33729c61fb6cb7160d18277fc66c2fb984a9f7580c6859a490611a67b0ba44223c6d085e9877bee9f1af816ecaeb34126eec6bed0480de123f7899116c9b6fa9502c3d5e1b90b74d21e50ba994acfd7c91fdad27", "SEC": "041f54f3b6141b7367d0e822dad15757ca6c5e212373a430da495750095e438cc51c97c463fd05f4a21115808fb2c878bc23a95e91a3c5dbbcdb5c943a8b120834", "TP2": "040caff671bc62cb8a082f5935936516033078897e38cae7d860f2416ecdc0be9306c78b76156935d344676c3d95a7c0d16e3a944e68111bc481eac98661b6f657", "TP1": "0422e5d8042c4b7061d867d3fca23b9df9a9a26b6c9c80d3f2d432871ea620ee281b41699c9fbcd68d61b6f57f2f8590e0b4b0945d5c7beed1c2040c7b69a94020", "CS1": "04027423b56fbf1e10d713c260a30e7d2f7884ba4db7cab6804644f6a2445b5bbc0049820f23175807d481095828c96d764eb95f9d632b253da14f3d5131aeef24", "CS2": "04184cd96405cd1160fd2acbecdc83770c31b243e0d8b3f96f2ff2efbf651e3bf71ac992f403521cb89817e68538a48d3b656c7c8d367f534198d4c6de764dfb8a", "HASH_MPIN_ID_HEX": "241ed4f022020662d9e407903c7be70550975cd57edbf4e19c7e88f856582f0e", "TIME_PERMIT": "041129afcdd7c7c5b1c7949725f779fc124c0c99cb9eaf57212de133aeb8a3a1ff153e4b50dac4877a30ddeb60b9ecdc43a861ea8d2fc7bf968c0c1822e90da32a", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223363343735666534636533383839383133666438303164393034303966616166406365727469766f782e636f6d222c202273616c74223a202230396562396535313465626635666133227d", "TOKEN": "041763aa37c8eb5b041eacac81b97bcfe1d6e0d290e4fa1993dcb41c808cc56feb113c27656447f4f8b5a6406e031d88b21e4aa3f5c4cf940b39a4993c9437632f", "U": "0404b426b59dbdd5cada5529373973caa2c46f3840f6ce54540329dad335a924bd0d3a01a368d7d6d83ed63fdf5d195386efb7eb89543b5bd347f2024a6ec9264d", "SERVER_OUTPUT": -19, "Y": "17f9514aa67e1d041255b60fe006559e4ce9c925c08931021f791da9070ef944", "X": "15d393ea0f03b2ebb366eb38936995ada296ee191d7c64f49028abd783c8b1c5", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"3c475fe4ce3889813fd801d90409faaf@certivox.com\", \"salt\": \"09eb9e514ebf5fa3\"}", "test_no": 196, "UT": "041b9385336eff03b72d8448c0ff662e54c68c83fb3bda06bc2dca773a2c73a59410c37ba653b04d05da96cbc5fed8510212dcad625b9ad71ec4a0d42f2266562a", "MS2": "0b6db675091934eeec6b387fa985ff2d0382c38b9fdfeae8199bb91b6b0dd4d3", "MS1": "1fe8ca49c7233adbeec0c56920777655dff217b75d970789ac7300e5071152c4", "CLIENT_SECRET": "041e48852f69fd0f57afb345d5f29d3446b9f8a3e597d74f4134e4cd5bac5803980d8e32b85598022e514bbc6b4ca702d82abbe45d8ff4032f840408e3a897b52b"}, {"TimeValue": 1437055597, "SS1": "1d9984eba57d17aef43a8cb9e9758238392b395d57b5d4194d77b378d732f88c03a17b9fbdbe67c4da2b5c5d15552d20d55167ad09c24b2906edb902e917210c196630601bcb35985fd35c5a42d0d5f8a77275aa9d91769c6633239f2ca650fb010a746c568183fa040ab546dff7ea9896f1e28bb89fc13dbfa61d2b51826709", "SS2": "010c8df37a14aea87ad8dc0b514c4380e1c37e599dff41c04f21c8bd92485f250ff9fde77d54bdd7bebcf62a8d08320fa43b4d8853cb22e114858ba83a8764f91d59103bace4d251e210fb4e12947c1fbff0ffdab8739018ede6b25138d59e791920d0643cd9fdee74736c4c6ccd7f354ea6438ed194d99a8f3a43a701f6af40", "DATE": 16632, "PIN2": 166, "PIN1": 167, "SERVER_SECRET": "1a19aede2a68d3550bbced5440436d284ea0beee114c58bcbab026bd88521fe81a0e937ee221eefa3dbe26679e11436ced366f1bd3f8ae98993c24694a225c82211e058acdd506a8a5e46bc500e6aa354e24840f2b5699183d63c7a18e26b8ed1811633b53f4e0a56c01c7555d57a0674c752728c6670342824f86248d8585be", "SEC": "04181c57ee941ca4916ff4164c4a0dc5b98e5cff64aac4f2289800f57b42f3ccf0154f8594a12353091db11f01764ea994bd708d09d87590d1700fef691a4282cf", "TP2": "040e15bb9125ff2044694a14316728cd1caf9a6a936b76d411a1285beb921c11771799c3efc9d2ec76a2e928cc1f4771a13f2accaab8ee1902e74ea46220d6ba90", "TP1": "04053ffb362227893f2aa6dad419b32c48c75c71b7f0b8a030aacc0fd17c6ec21f067d6b73f234cc8b5c410c59298bb84fec1439619ed3aab61cc29f19059a0927", "CS1": "04137bd61ae33170f2c3892c245147ff6fa36e734beb3851d7113a8b74d4313b611fc1071ff58653190b3b70c86274eb7741f64ab4cfd04ea7e72be88516e8e6b2", "CS2": "0412840b027edc274b4596baf9caa342b03c15076d4840e36950bbee0ad034d53b00f117dcc515365a8caa68bf40e49b28a81f1a637813dd6faa45a5d9255f654c", "HASH_MPIN_ID_HEX": "8ca9e07cb48be9cad5478c25172366b3541a9339faf185098bb9a58ed991ac41", "TIME_PERMIT": "04238f0d78523953a493adb89bea7c99f0ef11ba2ce580cd1d12b12d9405ae853c1d03ac1694f27f7e87a1c4c2a052ebe14afb7d3671f73fb45f3b21294ee67727", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20223935333236336537613334376262386432653838306638316339356135383466406365727469766f782e636f6d222c202273616c74223a202261326135636537343834343034323031227d", "TOKEN": "0410ef24c0dd0992a0aed757d9d97ff2d65137708b0725d03937b1d4b83ac7ce1b0ba02b5ad086787bc8f5fcd5e03a8bd694129f6938d549c636d02cf543e2952a", "U": "042226300b38a8cf29dc4b9aa08879e1cd38370124aae2024f93fb9ebc0a35f4ae08abf0487845de655a3bf51ecbd81bac645edd1295db002a61cffa4038db27aa", "SERVER_OUTPUT": -19, "Y": "0a5c24d9897bdbffb26b719033b1d26e7f33951e89614ce21d84d9b199ca0232", "X": "08370e5519274c2388d876c8810412ae64cea2c7ca0d8975926959513f7f21cd", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"953263e7a347bb8d2e880f81c95a584f@certivox.com\", \"salt\": \"a2a5ce7484404201\"}", "test_no": 197, "UT": "041a2e93aa80e76e3e97d45712a0c6f324e7f25f2d20bf1dcbc70dd984afb04d16058f303d8d039054373979ae87dfbae7d0a17af6e90b83d59f4fcc1d688dc48b", "MS2": "1ea7b9e3e9ab975bce380934d1202073e6f66aad08c49a221987526f8088a4ef", "MS1": "0649a0b8ab6cc059fe9c3ce6e4f92eba69c9600e2c37d439eb5eed0ec95e9b19", "CLIENT_SECRET": "041549c78e482dd2daad2aea957eebe2dbfff947ffb112161857c76faaae49a53d12a1e92f3860d5909c8bec922bb489097693181a47b73c7a2b7f9cf47363f485"}, {"TimeValue": 1437055598, "SS1": "1f25c8338c866d720227553518226625c3952a90e940ac29114b00bbf2cc49d21c5e6e5d281b5151a889495ceaf450ce775004307e1c0c037a75b125222ed2621c55411f8a28d5892d2d1da8a263f249e579caf2f1502500b79ce279ab20892123a20e8b4ea98346772aa59355c860123da247cf1e2747cec5df5cdb37fca87a", "SS2": "2004ee6a7de853cbbbebf59bd26caa2ba1d988bb000a84eeaf81b3a036cec2950be922cc3c1247b754ce25c41b46da940733c1cff3c4cbcd25fd3c88748580fb09085b3a4dd4022d46d02e4de18055a6b1408c217b36b4333f05d5d63a8771711331a25e218de5a8a5fc8845c94ec5580c03eaef0bf848a570d81b13b027684c", "DATE": 16632, "PIN2": 5740, "PIN1": 5741, "SERVER_SECRET": "20c20cb366f466a231603a33eb8b33583e5d627ae66c5bc65e0167c2e0e40b49200fee007fa604a60888a3eb1ecbd354318ffcc96a9ae6a2c3b17533c7dbc2920fb56fd443fae3322d796f01990f169198becec83590d1d9219fb2c06f795d4b1336eb71845b0cf07b0e13278804bc9d87c718f564b18cb96e9b118d081866a3", "SEC": "040bc65344cbbc2e75654cbf97823d16c15617222b88e7305b141317f7943222560b8b5636e0dee70c482d41b9b774faaefcbf17f5eabc81a2a023e68ae6af818c", "TP2": "041c0076dbe4a4d671910457bcba6fe889d74f6a947ce56351c050ccfae49a4ec80e68883d2cfa7680598bb2feb1450c49fb8a23e5258f5af416a73f1f891a5850", "TP1": "0414bcf2b319bbb65efc7b90ca2f06ddc49c3b617b32c7992019760acf111791db16cf7358773953b40e03faa9a760911413c474dcf8ae97775e6fa0b7b61b19bd", "CS1": "040371949a76166fb3f0e18c49d41a99f3ed5b70b0e6f6d4e38c92714bd5fbdf671e8e92167ccf5c263cfebdd04593b15efd27317f237db498f0a079034d4fa9aa", "CS2": "041cf0231bdeb35f5cdb6e32b741607a50a6920f76b673cd713ed9e1ce216e82ba0df28750d31f4103261966590e28246a1c4d545779dd72179530c6572ee00880", "HASH_MPIN_ID_HEX": "6eef0931129b1e09183cac1939f3e9f2eaf99485dc3e07fb27d9d5e2a7f01066", "TIME_PERMIT": "04021154003ccb6479411ccfb88f36c9d7dfbfb280b7b70b9bd91eaf01e78cb1e21efccc3a7e843ad1fa701b3c28d3d628f2481deca6ba9d28bdc0ec19f77eab61", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33375a222c2022757365724944223a20226638326334303238313130383239306164656263386564333363393162623336406365727469766f782e636f6d222c202273616c74223a202231313865633361306533396536313636227d", "TOKEN": "04024504f12f2bd5c446e2e4d4ca4b926b3f04a0f2bf2e0e5db419e59ac8c8e26e14095b592c321ebf59a2d4f54ae51bb9d1d87568b79282939f958d392ee70d52", "U": "0415ece13e50a88a68ceb840a0edc010fd02da93f3bd695a7a5ec3c7552c0c417c231c140e749d2286faf68910ade1b444a68ec3ac71b9ef37cece33cc6074b8d9", "SERVER_OUTPUT": -19, "Y": "01e9b80e9f43ffcf7bf98e1f770ed67a914b6e5cb6c98d5ac2703041c257fa68", "X": "203c5a3bb4516d69acc8dfff86b8bfd48e88b7f0919bf38779529dfc672e71c4", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:37Z\", \"userID\": \"f82c40281108290adebc8ed33c91bb36@certivox.com\", \"salt\": \"118ec3a0e39e6166\"}", "test_no": 198, "UT": "040de4bcb6a2e91b45e7fda12c1ecc976b56741af3d8db1f85b18178750ec6af2214f66306e7d3eb64ca9a9f9d9f42d6bf2fb9afc0186df36819d6ae517171739d", "MS2": "0bcc23f5b3765d70e5fb954b4e0274a063a2ded11f5d22056a6799975cae543d", "MS1": "0b419eb4c0f5ef725dee440ff65e1fc9ce977002368d47d6e435ca3249d3a0d0", "CLIENT_SECRET": "041be1e5945edc2562c8a2c9f6bcbac7fac68bcbc15878abedbccbb27b4a8ba76a1ac10752912c5cf7a0f896b65b1bbc98785e3137638f9d5bad0ae6140cfaedf6"}, {"TimeValue": 1437055598, "SS1": "0f0b6d11d51c5c4876835390b9bec380f930aaba421388db56af38f9c6ebbac917708ad8cfe55d437a83ec22b7e95e61a43388e34606a9e5c7f3c50fc67a375523d46ef3184004c19d9bf814730e4cc7ce313b72f87439ee424a125d8ae054781df85f9c9b3d3a0e8276314c3bd6dda98d7a323130fd1f81cc7321833ec0a184", "SS2": "056b9daaaa2bd16581fda51b1cff8ffc01171b59fa6f363419615e29f4639bea0368b3fb47610c2d4acce676212df95711e39b361ef970bb7913a359b6d35c2e077bd155a102bb619f2c57fd0a491f00329db0376879914f4714e1be7290345c003f1f1a20e220ff1a4b03312660582ec78c3f662c97b18a056944f166506ca6", "DATE": 16632, "PIN2": 4013, "PIN1": 4014, "SERVER_SECRET": "1e37ad39e3e97a6286b6cf87845c781232c6c1ac99f5bd72160ee0eae1297af816d58da7c5965a3580fe85fd55e4b2e4284e6b6ac19509d2ff8746cf7e3d136e03d9cc30835e32b0c8436575e435be51eb45eb031722d93be7b6b5bd69015bff0e793159e5b7aa777b1e74c27d520e5c69685e166091cd29bdc666d8e4cff393", "SEC": "040b567f94e0335c8c2d6c8167a3d95868a48fd3d07038df196a35c46acc76b62e04ee8904629b1031b7a409366b3e821e0383b0f5726fe4e43cd057477abf21c3", "TP2": "041e43e9495921d3885ed698bfba248f5a34723edf5c15df79f28abaafbf8cfb001ec5c364c1d91a863a5891f1d5e902318d1d3257727d70fdcf2fe57508515f1a", "TP1": "04009a7163b6c095579215b3a2aa02b6e705eaa1876c7cee3c383c564ed837edad0bf2d4b9ac04192586022b0e55f338952fe826c9913930a459dd55cbe49efbd7", "CS1": "0405cce6dd8fb3ebb10a0452bcc5c72bfd085f961875890774dee9d5209347b5cf045a9cf0d7060cb32b2ee11eef3c88630d8c7736c1ae9a28af725aadd05db80a", "CS2": "040897c9cf4ed37f415ce60fb947fae44e435428deb2df0dfd0ca4710c8cf742261fd1bb8d08a4e7bc545bb8cb0bed12e2111f18e8db6b59b6f872d096944daa3f", "HASH_MPIN_ID_HEX": "38b9239886a67326e8cb46dea1d53e1079e689e411e28fa9b16be74fa80211c5", "TIME_PERMIT": "04109d7f0cec776c4781b4adb72ced0b56a86cc6092af2d219511a825ab87eaa8a1c06147a169bf3bff72031a281b6b1b1c8587ccc4ae296781ccd302645576955", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20226636633462313065303932323438386235623834653133383636393361623437406365727469766f782e636f6d222c202273616c74223a202234396432623139663536653130313730227d", "TOKEN": "040bd88bdddc487117107bf03c3cddff0e5bc857ed1d6460b8d78dc1c0e1360a241681600856d3fb6f4692cdcfeb3ab92ba8e38e386360cf817392723070cca616", "U": "0410fb560c630dde4fe5d67b666dbc5f48b058b969a746ea48994c13fff4568be113ef0a3704334e7868a1969a878c3a0b242512faa10c440dfe5e4b18af0e4dcb", "SERVER_OUTPUT": -19, "Y": "0fbd5a46654f1845cb81aebd163b3a68ae51ca505ecfc6de28be47d417e514a2", "X": "1005ab71024a16fde49b4bdddd9fdf211198b2d27e0f2c230c1ee179d0648539", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"f6c4b10e0922488b5b84e1386693ab47@certivox.com\", \"salt\": \"49d2b19f56e10170\"}", "test_no": 199, "UT": "04069f827737845d1701f772feb9c9a3933855cd0bbba55d6a79f44a54afa751021bbe9bafab2729c6c14340a5ca0ebc52c8da67fbdbbca26cec3c238340c22f7c", "MS2": "09f02297d15f60761df58ec9adf6cffb331461ae4d605254a9493aa812d27cc9", "MS1": "1e4c31850f72d3079c2a830f60546d6f975011bd0888da0087133a7a32d11350", "CLIENT_SECRET": "040921c08bea40a4571d1c2c6db0c9bcadd570a539a6c183e7e9554dffb6d7a3f301a7ab653f3f71ebb5dbc5d301e7c59b2bf98fe8233b2102ce4d3ed95b98a530"}, {"TimeValue": 1437055598, "SS1": "0a2e23694b86e8ba3f0046dcedd29ac66bf223427ee74152be81fe10578139b80c819a2bab8ea60de4b9b57faeb03281067bb73cafda0e14c43997eb3a2a6c1622171fd14113b7a2abf3ca280e8ef1304d03d22bb96a7e376e7c56646ab3178102b7849cd5fa99e015d7f284965b0adaab1acbdfe536389bf636ed56316f1253", "SS2": "1fc758c5c9b09ace93ad20ebc1b57c162ff4c28b26dbfa70fad4088a12b6b6901a0069b19e7a0f97fe0116b5308ae5c508d9d58fd7d776e4dace002f3255f4d407efebfd44bb53a9f412706661c5c1fd013556d7a1a1701144bf1ff85d28c000142adbaa7d48bd1c599ffa6b5daba18a4c973d409b050179f8e2de351515f066", "DATE": 16632, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "005def4e415d23a65a94b7c70c3000c9e9c5d5416ab17837bca30e307c6c2c730c9308c844bc8ad2c49ceffad6f2f5098b50ffc6bbdacadf0d4756e91783c70621f72a88df7808ca787520101a6aa61d5600fe3671a26be6ab28c44c6411406916bb9b3d9833dce38903b85c13864fe60e9536fb0aae8c93845087698ddac09e", "SEC": "040b99fb0da53103272dad03f6b49afde100916823b88e44479aa739c35bd0863f0b207c53d68c043fb9e9f7a5bb1b6e170ba970da21d0e67384fc5a85a6c8340d", "TP2": "04087bc0bcd6875cf040c7d7146bfc59689459403eec9a868ce76bf31e5b0b807716b4865a1d8e0a45630acf9cf6bb5cc29e64d8f4359b3c2db30c826b9ef92532", "TP1": "0401cd35f9b276e0a69f27a61ada4daa93bead3294ead790c088633c91782e197c2346b9a588c0fda36ef00fa012980e50ec7fa27a7a54b6822f4f6777714a0e3b", "CS1": "04177d71e2971cf99ab82fa8a53f5f27950681d6d976faff28975d5bd4582e6728177519c54823c81dbb6739b0c3566b80f422a9ef4a081a0acbf4413ed80cb10e", "CS2": "04020e9eed5f0db761e23553374c7fa52186754dfa23f5a7bf29fbca68fde62409029d269e5d3a21fd8c85e8eca3a28470f2886706afa25ca432cf716f9c958240", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0403e0e884ec6a01853a68b363c77806d26b300881a9cbc79c60e7a0f75ddb29fc046cd632310ca77ca55f0bbd7a9f2f3715f6ee8b71021fd7be1e8209d3e81dc3", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "041229e8022cb0af23edddd68d7d6abc049ab9b97376c7c7ab45a0cadaf4cbbacf1d9c1fc92ced80e5c4c4d7f72c4f3bb69a8e38a26513f5c6656392786e8a4c6a", "U": "04213d577584e869b4467487729e71edb518f674e7bbda5c82d87cb5fde8e3ae95209d010b0d352d5a0963f18a5f885a587aac4ac6b1c3723ecdf15684489ce547", "SERVER_OUTPUT": 0, "Y": "0ef5b18c22254d77195f721965c7f037fac0ae754378ed94cf777162c1a7913c", "X": "1896d6eb45cac618abaad13809503609d458dc0bdf00b2c7c129809e21f868bf", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 200, "UT": "041e45f2986425d43601948eb766b51bbc79f4bbc6a5db68024e1056cc243d53da07b2a4ba3f04b9d6b9f360cf7ed0b686281e9ed57d19f7d91b271a8c80d5675d", "MS2": "16a1a6f885a9218f708da31945150071f59f8c4cbac009ea0fb1e8708a79d48f", "MS1": "1b8d228b45aece74b399b230e8c801475f3c95b47bd55d448e52fe075de1cc0a", "CLIENT_SECRET": "041a429e32396a3beedaca9a81767b3adb966bb559317d5a7d4ee5d0d96e7dd5c71f1b753f86f2b1944059c7147cb381b13f6b4fb58d6c4577cd97b9f756f18f97"}, {"TimeValue": 1437055598, "SS1": "11a30c2e1a14a29ef895839e915fbb1289a73ebe22313a88811dc944e73dba8f0f8c390d6cf592bfb5624aeffb121a07135908ead0afebe54e508f5a5fa84a6612a701347c4c50ee62bc7c3b72b5ec4a0b44dd2a5131460032f19021d5a8c3931e2a5a78a62998916d158dd05dd91367926842cd6dfc2d91fe2513032409d19f", "SS2": "22463956475ee5dcc3f52722f0717c6c199bf48909c89e081fd4526b13cb59581e8257b74f24398108d20c265c41292f858626099e800cea364e898818dd90ca19d24d36544ed19c59c3cc4a0ec9594fd0478c21bb55cd991565924ed1524f690fce6b7f669fcdb0458719f92bc26819035f45f8ca508961c0154d3bb2f61120", "DATE": 16633, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "179b6190eda32d4ee0b2a7ccd726babc468a5a69080769cc712b4c7d64b2e50e19e60f1b68e0ee3d8deaaf298d4da6a2dfa55d524bcee32ba8fc2457367961d91b4831c7b50a0ed65abcda742b41f69035a297a04566f6784b6423f6ce9f72ba23cea00162e181b78bc3d8921977e377213b8c9c429ed9712bd2e8f51051ba22", "SEC": "0421679ab70ba8bf311ff2aa2ecdc3c5fc8b71040cbd5caf71ce674e25dc070106069ff6b28142a746eef64d04fba95bda65ce950b516240f3a562a78fe48d8d6f", "TP2": "0421ec345eee6a6c1cc11f8a04672298ccc024124417ee42cc1bbea494c82c25f51de0015dac4b9341a00b2283c1d94096df7bf32eee90ac57b6d2ddbe81c621c2", "TP1": "0400b26ce37f9f17bc3d46f6c0c77e91daf0e85c26bf45a720cad2d748104f49c40e91f2c5ed7659cb8d87ad9e847c3112d504d4a6fb15b446d269657bc35c327a", "CS1": "040b001a727eeaa443b7b49a9e01d387fefc0eae1e40c962b6f2e9c1fe730e0f92199ca7f36525c1eae07836757a0dc9af845e633954dc1baf164e9e83c3bd64ce", "CS2": "042129f2ae45c396486d08bfbf1e76a7f803a7968d6dd0275ddd4460192e0fedea158d63053bf1d3fca7d3be49d5cba540b69fa03dc27cc7988a3aee048671ecf6", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0415b45c18842597f6da96f214d01bd58f87c82713140b2b5865b3c4b4890963b103cca7fbb04626689797d9ad0f4e4e87e36d938b9a45b0a2904aeb45c102eedf", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040a8f09fde0c1e7a6a75fd8ffb1c1eda7a8f75608cf2515458e4579ae5536fe271db53826aa1124f1227fa7235c697144d83a33cf4f42bd2635f35b6bf571f363", "U": "041ba82a3a2be68ebf209986f4159b39d6aee6bb7ba65a4732edaa4c89de5d69d3047f0d3f32ea1032d30e78a9a59a7bbc61bbda19d5f7b6c80add4e626d02f296", "SERVER_OUTPUT": 0, "Y": "2230f2f912231c766b27b09dc0a463c611919b0dbd0fdc1adeb5187c711a07d2", "X": "0a595d21afd1957adbd2355c9effffb67b70d331584369c1b6af42baf34c4126", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 201, "UT": "041eca95a22ebb5aca0d9b8a51c97e1916d3c1348f7b35d323751076f933c5ae2e1f017935931349dee6052cfcca4542581d34c93d85bde5f6124c052c5c30ca2f", "MS2": "16852b403d226a811f66139ce681aef9c8a2c917e3d4ab26a48a8b935c854f6d", "MS1": "17a11402557cfac207fd037cc8090a812316e9bc45ca9b9f6883f42f8cc45291", "CLIENT_SECRET": "040fca6ba70f9cf6dadb13b4007b729dd55ad6c19c982e01a79eb815dc04302c59232ce186f93b23efa3549d1891bfec40e670917d8c4924856993974a32bd892d"}, {"TimeValue": 1437055598, "SS1": "09f804faddda16248a130da27c819240d084700a2cd1390d1a9eae91e15b1dd21846751043f37cd1b5327c2ca2abd4b86bc5c709295e5dcff3c6a78ba6ed3b83150f2dc0dd25bb1c5ac130d8e8878410fa2754ea1266ff93045df61f5fcfb3200f6653ac44dbfe99a5b3507fafe1f51e8d9d9e6c05ec76395f84ea9fae808d49", "SS2": "17671a41105be83be56ffdfbf3600c276bf42bb0ead1ed32e9ccea4f1f94db2f1e3ff04d7125a0c0791966269fd97c70299755f66e934edaa29f38c7b0be2bfa1abfc7f40e8318de0a47339304067b101d159e03c90c0c96f22fc71eac45541318201e929a4bb6ed0beeab8e739fa4141322d08034ceff2ce42ee8788c676123", "DATE": 16634, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "14aca23922ad8638ef504985db7e046d9332d22dd37c06c3073d2471aab9f29e1cbeb3e2eb73abb79dd978a50e6f5d61bcff5e232c06af026b0fabae27c5a99a09e8477c4e3e619c7a5bac052ccc1cf25699af6402f8a48d9cdfd1dfe7e661d520b5bcbf8583466aca7016c282ff79d6746b76c1041116e97110dc7572d5a443", "SEC": "040ac4323e0e87fa10498bd5ae912c885facacc669ac80c54e4fbaff5c089a1d1b0b67ba407dc4818cf07a25254095a5b28b9986df515cef8d3d960e76cdc35339", "TP2": "041426934768b4a2fbeeea733d4fa30494c8ced78574ce2d5ea3ae0e4e306ab04b208dd84f1198ae5bfdc7b7557e477d8a25912ef2de0472999566b3eb20d90cfb", "TP1": "040dde7b616d32bbd6a903e4b43034c2ee94d1b2e83ac72b5461204e7e8af8381c1f20c309273bf80451ba724219c29d6ae895a2f44b178c4a612fccf61dd4a5ec", "CS1": "040b8551740e078655d6c30289386bc4c3296746e3ba7142a3b0ccfcb4ec32f6c500dcf82862842190a79dc0bb6d52e7fff1ce7cf560655daf473db4a99a446c32", "CS2": "0404be9775543d42a6547b570dfb4c204be77bbc3276cac7345a13b907ce0a6ac409948ebded78ec903cd8208bfde14528ef0e5cf6a65f4d8a0d8ddcb6da14227a", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0400dd8c67e115e896ac6ec267b5cbf840676a0d8f4943b62e1ef72be36e89570e0f09cdf19e523ec30192906a767929b87f04fd0130782e96197b9c6e349c48df", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040289b430d5194d6a3f8362a469d5c23eaf0770a7e2e66e296a4634d7cc084a240a0b3ff40e7574a0cae5e503880aaebb937d8a1bf0de5b6bebf8375785916b2f", "U": "041cef086748237f35c26a9587d84f7a53cde7566bea03184840afec114f8a58f00572809f223f36691bc0b2692b8a288ec61432ec6c16ba0660fcbeffc8a40ed2", "SERVER_OUTPUT": 0, "Y": "22849bdae8eff0fb8f894da90f16103eaf70841512f5676e7b7807ba4a7d2608", "X": "151aee4e317fd8662d2ab4aef45532642e477628fe05d46805acc4228ea606ec", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 202, "UT": "040816b357a3262a7717cb16354a8e622dc2545d8fb91bfa3f61b8bfc3a376acd91aa227dc3f1fb378aa3478554af6166c369097b06f5d4923deac1cc61567446c", "MS2": "1c990b48839ffb487ec245e70c475bd1cd1e8257af3b89b1e2658d445ea2166d", "MS1": "0ce6ae28754d5b1adb97f87f8ffc3631b0e989d0e1db861a308b1536f7c3502b", "CLIENT_SECRET": "0412a9bff76e9fe3ab0029703ae6f0f6aebc6d31ddce765f956147610f07d9dbc60866d39698712f67835cdbca78923795d02a9e6c6da8866ea8a386069a0c838f"}, {"TimeValue": 1437055598, "SS1": "1610f0ee45faf5874dbbb7f102ae3a107a1d869f57c0d47196794e1e13bec5c41d5d0e119e1a69995e82f31d480d93f94ebba27ee786cb8d6325f13ab96014e000f1c1d57d7cc78637c1133f6bbc3fc27e034cc8fb5a58004c9b10c6eed59fa50d2bf231cb162c224deff2b26d60f194b7927662b948f114d41620068e9f98ed", "SS2": "18b34be804faaaed5e20e7c5e366569c60d264a427fda0d505243660500fc33c02691b3dd36ad3c7db9d0ed4c2c5a588cc3e01c49216b6bae5c91d6993cd7adb0bb0ee21529c33d8da846eee5250d1ffa8d2ee464b16b2fdcac3e0f20b363ac50f88dd78b21d200a68e053b94380a302f7f8797eb7a9d0409a3a9594c91bf98b", "DATE": 16635, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "22b859281f8ed0d7e970143b1b38bf1da7450e5e9e413c6391a4239060a64864094c11ff1577925a7feb5249a90acadf883608bf2ce2b3b9a9a38db06660c63c175f7e701679d1adb7a8771d62a8fa5de4e00f208711fa0b8eb5ba78fc023a8306f52f61e6922c24326332a1fd18aa78a85dacdfde405866086327aacd29cc19", "SEC": "040de583b1604c35265c3594654ebc32a118f8e0f9d69b8b114e57127836408ddc131719d1fe8b43db72a65864a24168abaa977e437b717985f44900f454fb13a1", "TP2": "0417b244d04cf24096d126616c2c637bb676fbad2ffcb31f13281710e22ea3fd5219acd170069a870f69e09a3e8bdf6acae32e83e31c2cb9bc6ff4d5337fed91ec", "TP1": "0408f36f4518023bc3a36a6af9c71de89297fa3f6d7d8f9ce217ea2a4c4d9e64e723ce97e0f65a6d61e7d01baa9f27899e4c6ba8b20e9c05117c75f7796be71eda", "CS1": "041bdf0e43cbb4f39f0ca2ad73e2f2d70730bf286c03f7afe6fe186be2156c1b060e5bae7ac80cb7a06e2e6475d93eaaca567b7a35f5bc03f490d8d1a4d0c7573d", "CS2": "0414710bd00c7b115a6c60a23f1e794e581a7fafd52c65e272bef69a3cdae7e4350a6befaa42723cc4cf2a561945110bb59c2c4604d627bffe111a9f27c67aa3d6", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0406fa768d90259361bf20c96695bf239946ae817c99aacda77ccbb669266d6b21017193d312553462a929f69e910a5ade04c6af3c32ce592792f7f76a57a2a6c7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040129e7f4269a5817cffe067448d57268a0942dcd2b715d1e658bc6cc13994e4d17314cbbc411ce59e70519921f821507ae4d044036d024fe0da43a98ad18126e", "U": "04099b347389404d2ae54ee8c5e67fb29e2b058b137c7bb5511c62daaaf264d15001f2f58acbac7fe6ec0476b4fcbca185649b42f0ad377aab9ef920f195c541c4", "SERVER_OUTPUT": 0, "Y": "13698400a4795561e7c8d84e800944af734856efa6dac378f4a5e42764b7d3c2", "X": "14ad53738a0508066096f55f1f714cd9495331866883966409034749bc3cab0f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 203, "UT": "040a13497f7e7b0cc920d843296f48517ce99c9759a0f7596b2cffbd6fa1e241fb21b3315ff2e123e0ab69a363402841941d83889e70de73878ea77bd1ab3d1171", "MS2": "0aa1e684b661ca882f54b9ae570468799508aaee750b580adf7c3db99269d77d", "MS1": "02c2136e1f18314adb7c41f79ab85e6a9fd59289b4d90df15203c7a1f8f94561", "CLIENT_SECRET": "040569dd6e56ec02f67a7241982dd820798c4e6a62409d83e1668b8adb3b40358d13f4d7eba5ad8ba1f00e3159561028f3631de06f2f52ad40a80dfca62911d571"}, {"TimeValue": 1437055598, "SS1": "1f7b4daac07bf420937943ffe0ae8ef7d3ffa5b3e2dbfdae6361901f01c124fd1450d217aaa4ae8ce464b50a4d33bbed54a89777cf9b7bee35e6b70497e648d50319c2955f6942382f8bea73a46a131ea0a01d14168ea70931b1c7be036f08c90a5e27845f50f2277cdd07d8a2781762e73510288e9a97248a9b34a60143ba04", "SS2": "0611ae2bc5df032b7c6f6776347e3d9a810f745c6eaf688fb8d3e0f2dcf8104112435db849fc3848b871bee1b8e7c5fc09fab0847dc296c6f0edd7761e03a655198046c7ec28222d94f10b12db59ab458fd26aac764557ebdba58e4fc1f82fa8021b861a2ce7141c69f2ced978a2fb82fa6ed47cbfd866537386c75ee645845b", "DATE": 16636, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "0df01621ec587171cd670858a8d4778aff66da87cf80a684adc03b9e20e9ada020bd3bb5051156ffd616064a6b79ea9931b9071f95331dac494af20d98bf03301f60da36c98fe40939047892d72c97035833a254620f634f20b1a67dd27aab9212bd0fd66f0ec963fa089c33d3ef5abdb087a9ea332cfb31594f0521ea678297", "SEC": "041aa55b955e533989324b952f8e4292ee587d9ed58786c1269163e2d69d15b48e12b9133a07247d26c5f7d27c4c10ae31328d0f40236ebdcd9ac470e884375891", "TP2": "040a552bb9730506bed2b44252b435273b89385462c8639408ff9fead59b4de14819d2c29dfbbd5fa052c6351dab1b5e50e87dfa7b514c1ca766bbe30fa5157c17", "TP1": "040990d9422cd9b0e2fa0adf25f4bcac7060d851828e0dbf1030bf35f915cd928819b94fc9df149d413cba5e56e2ec9e09d380f02c05fe8af29b08dcc086a67efd", "CS1": "0410eac9d5a0a7fb9f48a18c318d9d2fe9f02b58085afc99d58a3935ff05ae2de51cc04a95d984e3c579e1e4c951f9045ef4021b3379dee55769d4ad55dea07e8f", "CS2": "040f7a0f7391e8310397af0c93e67091af63f1f4f081f7b3b5412b9efcf13ad4a2219d167f07e22497a9e2aa93c29505846a69ce64dfcb89c4831c5014de246f12", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "041370972075eab58467d77537b0544d9ac76bb2b033287b24cac8f1d88a1f2bee19c2ef94879cab9cdaf605d6a403e4ab050d88261fd78909d6718a4903ea34eb", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040d0df086691bc0347664e2bfb82f5c4ee72785f5cd3bb04bcf40f2e8b8f16a570fea6a5d2262a6bbbabebf61f3eb5ed0e7756e7dfd0dd495739e5df911a74a4d", "U": "0420dbdb1bb205efd2b97fcfa0095e759d45b5dab980c9408bce72f4e1d0654b6b0df08662e82a6ddbb159b39eaf25c27f3ed28387442afe3d8c062624c99c34e8", "SERVER_OUTPUT": 0, "Y": "1011307e2e980e21b6c9fa368d5cfb5478c686f04ed6d25cd8436edb6fab89e2", "X": "079a0b01f2e1f6b670467f85395919df2c0e096655ee7dd6af5d91674c9c456b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 204, "UT": "040c9721f1fe58fb22f5b96c9163196135104a1150adfef354304830551d6701330de86ca6c86d7cc5b4be284c591fe2e9986150133e87dd99cc72693b2ae3522d", "MS2": "11e934733051b383816725e6f8a9794c023c912976c212cd341649c8ad9efe7e", "MS1": "04cd02a0e13319f4eaa735fc7388e34f4d61d2957c89f8fff63a0d1b3f5ce40b", "CLIENT_SECRET": "041ab1642937308299d945986cc5c3e9703b91873e7eed56d0b94661b47f46df320185ee8b57f994688efc021c6c0d0a9a7d4f755cfbd2a888a01bf75ff0e02fd4"}, {"TimeValue": 1437055598, "SS1": "1cf3f2db888f84146fb2df0272414a59fcccd1c89b6cdd1092254c1ba293401205d86703451491c314e64dcbdae5d13e1b8eb6ce3cb25bc8472d583262081b5214414fb698223af49872043c6159348a9ac3e615ae196398ada1ddcb6f56f58a1bc330405d834dad608aa670c7efb564e0f15ff8eda65943b8673402870ff3f6", "SS2": "0a8b77b370fff4023f6e6511adc95c799062ca00114517c21a7b739e140ea3af0259cd7dcce2dac33816b4c45e4c0ec4869b6e39da56dd097335934099efbb0b00703ae79b01c892b87d81405ed249bdc64958a93bb2670f30ea467de3131b75100fccf3f5d996150f396811bacf3f92ab9e366b974c5b110fff910e1bb4a400", "DATE": 16637, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "0899f0277aa74f663e3ff9860425f9300b806f72c4f25193c7102a549227b768057a17a9d21e0f704871eed3aa2168e786086946b8ab546df1356846e5e2a72b0dbc4b379cc096cd8b1607246392648c53ed0e462a816c6a90fde0041fddc7b01d143f2d2444da3fa71c51799a78b960b7ab61afdad0cd9c6dd40dc2af702a4c", "SEC": "04132702066cdad05ed7ccd2f992baa87f2f40ce865ce8c9ab13975825b81be56c0edc4bee6d3b6034f57a758c17ff208ceb61740472ff6b1a3ca1b01bc9173345", "TP2": "042199be248888203f4e9f781724dafe3a8405a8b3e2b8b28016583e5d7344c8db0038951f41999c66daa410c3cb2a4188c9ca1aa8baa81d5cc4adc99f6d1f7717", "TP1": "040f05900ecf736845dcbb0636b850c8167d3106a73389f67eca0a8f77caa54ae521b0cf54fb15255e1c4fc6f983ec8dd6608847ac67313f7a274b869f0a18e1ae", "CS1": "04222d3839a6f2dad05e91186be959113b97774bf9ef8294fbdbcb9d977ca5eecd00e61968ecfdf881538577fb6a9e7c89c6648d6f53afab6f8c98e523dac8720b", "CS2": "04022481e483e64e6273f19f24286012a23eb6c319368afc96bcc4bb22766b10651598a96cd6cd8c637490de06529bb1829ddfed4c8cd5e56211cfb5269b6d79c6", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04049dfbc5646187c0591e751b5977f40cd4bf7f0931c6da528994cf757998aab404cf47759cd2d5ce746c6e1d8034f4b0c4333f94884bf03a3c371a471bec5550", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040932f5f42cce19b7caa5eaf1f94556c4a30959cf55cd2d8a37a2e9b496195f0a16c673a8441500c3447497205a6de47da0fb4c3587d601e4d19800673b31a69f", "U": "040364258447402db9fd21e51c448dd93164c50de2a5428c279105f69eaf5ac4cc149bb8add547902e434e94c3c86dcc4763c832df0d9062b73eac3d4dbc470c49", "SERVER_OUTPUT": 0, "Y": "0920110d2781820a25bf8cd32fcaed5db6e0b77502303bc3fca3239c338714e9", "X": "0a574aa17eb0caec6d5ce7902c9e788c452cc12dbaf441c9cc6fcb3befca48c2", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 205, "UT": "041908f58cdfc38b595e270583169e8a82d8dc4949383e625b7e02b014ad827b3d194cdd5e72d8ccccd800a3eae9e5da23550c2735eee1c010136b8e83741d1cab", "MS2": "1f05bacf85e80000e0eb550a6e41d7408735bcd66c569fd3377554634649c1e9", "MS1": "16053fcec64fe50bcc0d6f7fd522f9ba70053d1f525cbd413c1c4c0c197e9ebc", "CLIENT_SECRET": "041b82943bbde4cc96ae042093e460f990d1cd3f2bdc8a6789ad0f70058330e45b08a4d3cae8033126eaef732a7760c0423872dae2c8179ee5b3083f8800bc7781"}, {"TimeValue": 1437055598, "SS1": "112c134d421cd76eac04c9d917cc334653b0a7f7badd0e08c48beb8665f14a9717ed0bef423b14bd4770e78389f9bac4cc36da91b2cb7a63cf6dd2ef3d3984ad061c975ccdc49bf45754ecf349c2ca1881437dd409cb453eb7c5555eb7adf84a094502feafdb43b336f77e85776952ffe31c0a140d6ad20c2869eead132456aa", "SS2": "0b8dc8e3b5dfca7f1d7edc91a0210bbb25929637baa72ef1cb98282a2e3b1a2322e6ac96a7351492f37c737fb426af8a0150fae89acea22ca15545385337dc2703daf3c5602aac5e678756484ffe845909306a71e263a5eb1661e18b48f9731312e2f6bb983e948601e79069ff90cecf73e31b315712de11d01132d2e16cdf97", "DATE": 16638, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "21d354176c3eb38fde06b65d467749c5d8fb9bc2cb647d9b854a4d1237e09e2706e4a48c2617d386c65c50aeeb2ce79e7f73595160fbcee54a1b98c7dc606738192f333543477f4305aab77a58bd1df9a76a74553179411a62ab1a6a3dd207f20270dbfdfd536ec723099c9cd0110cd245e60a65f02cb4b989c92a2b3204b0a0", "SEC": "04148a451d9b07298e8f594c0a6f18bd6d8667d81adef7fd4b060bd349991f1de221dfa2382b767a899f2ec9758a2b3c5ba615d0989efcb4bab68728b1aea38a81", "TP2": "0402eb387dde82462a2f32729cbd16fd5faba4533c62a2cd5da63b406f1265df9220fec0e7a7de8e08d7fab5b7825ac7a879163bbb7df2f23853912c160c9ab483", "TP1": "0411350dbe97eeca12a6644c756dfad9cb20090c506232d42caf0638acda3a1cd21c1ee79acff3a493fb750f66f7f771424eb82dad2eee62c342597840fd06c0fb", "CS1": "0407aa63d742f5f426daa908b535f14d02a837c568ced5d2933e6071d87d68aab20796541c1b749f752c32a9c95e17099dfc0ae5521293ed56c13ed074222ebcbb", "CS2": "04001c1072ea069fe4bfaa5c111feef52a614773567762578d66f18d45ba47a673103c120e3718dd7637e58442b4aa6968f353cf149ee8a2f62f9ed7bed682c2af", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0404d47edf5e9cd5498520e7160d78959a6af64e13268e57d182ad7c550fed7f00063508606b2c568fbcafdb192e0c1ae0606c339904d417c23e3ab4d5027aded9", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "04133c0ef467105f66a9e9623fc1a8ffae284ab5785bae796c06cf871f0a03287c0566d15a7c79ee78838251df9d9730f1ae02b5f7bdce8d7ce896818d300f60fa", "U": "040a49e6c06c2e9e70b920178af53f116a83c2a57cfdcca03d667e2ea6aa8a92e015787932fb631db1347a32141a22b0b4c2d810326b65a57690e79b93be7b212f", "SERVER_OUTPUT": 0, "Y": "0111a281b780ef56661c25bbf61f9253ce3f8a126f971455c3bb845eb80425df", "X": "075e3105819940785b8f8ef70da101780a47a510a6a3f9dd63ee0b529d574070", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 206, "UT": "040c211ea354618b4f8c74ee928118cee32128b8f387f09dde651007904dc1a2d00b0da5d2ba8158ae7c1b2de5293103e10f7261dbeaed12964401b016328f5b4a", "MS2": "22a9af4944eac209b764a8ba0f641b1f736eedc5675da6928b1483b8f28e6d4f", "MS1": "02672673d816994d7f37ce4e0a97c3a09020db021c2b9b863d3eb104fe5ee86d", "CLIENT_SECRET": "0421cf9cc6b61bffef9861d43b8be432b9272c59d24eef03620322225699b7f18c134246dcfb7f8cb5a614401a5895004b8df077da30125cc783affee9a1e2e378"}, {"TimeValue": 1437055598, "SS1": "0c2dfcc879c417a3331b227a220320becef1dd20bc7cbe6c99bc929faca321fc21cee37facc846d778ce8d449351f1cf46e24e3bc6787a98a8d710086e17dd261e653bda7dc9c98807340ff1bdbc3af24d37339fd97e6443134bc9893098785a1d3608e715c3df0d004b304b82f5962eee94704e850e7d7581a3544f19676c30", "SS2": "01b6003df5e64480e716e2c4988a4dbbfe3a005fb8dfdd8b54dbf57ca82a47b023ad9f9f6a4a02245023c4a518906e485799100cbc13da711ac467f788f9a140229b51f09640ab7d4e9608edc1b3de8f12c46a320e542a1859b00cff19f8b6080686a1d623062da3e6fa6920fd109da878863b4155aabe5c197b9c0353515d29", "DATE": 16639, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "0db395d33f6ad65f0ca7c6ff6b757910ba0a7106785cc021a844e3d76523313f192c32a0ca0c3096b1cb70dbac1d22e7f147511accfae49e04d944f3d8cd42c1071c2c9dc119d8e271d854302969f80b8b716def168994dcfc8b79bb1ee0cdf6151ac149eeb6a77769436a24b783fe04e5ebb72b777bb279755c825aafb4c9ea", "SEC": "04170c78ff50364407a175dbe97b6e50162744bd8ff77e10bdf10bf35349975d8423571f947ea02bada9109ec92276d6e539fea7ed1d852f145512ea6aed8cbaa2", "TP2": "040519cd445b06142dd342ff6ab416bfc5ecc7cf97d9da78702eae55008ef646cc158a0800d28dea8eb971c20d687acc7906ecce3766b0baaa8368187ebaa66402", "TP1": "0415af0eebd821a5942e20c986661be332c93a58d6c7617dcb9c98613d3151506e0d02576c9d625a091506431b0fdf197687fb580fa5636d60c8236baf49492e33", "CS1": "04206fa7bbf7dbb5b0bb290272dd0bb943b4f2b4d0a21f6b1684468591bb244cb01300c28b8edc47ff2b8bd40a9677474e33e5d9d4e53ca2ca54c87f599261b244", "CS2": "040ef0d08bd6cb7d39cc07e7cc38f45f886836290f3122b4df3004946e1eac6fe023bc5f8c20a418f2f3a4b055d3eebd08642417e417da32454566b0d94db9e5ca", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0402c5b21df96dec0d1deec8de23d6333025bc8baa94050857b327c07df0f3730420142132a8c84cf58268802a161dcf6d968d84ed1f76a5af9a9a2cbfb696a8bd", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "04106db9ea3505f2424f793735bbf96fb02c85ffa6e63cd6fd6f72fa3e988df74b0c99eabb1f1347668a3da47a821a58b80c5aefab9f2c526861d31c91746599fb", "U": "04090ca78a15058eceb00dccd7432c55b204e291b7063cb214c5e3596dbf686f9d2175e17f6a26e9eae12c0e14e751f25edc83dc8f8604552ee3fa76944aed7e75", "SERVER_OUTPUT": 0, "Y": "1e78e32cce43c6bae8795d2a2ad730916afc252a8445dd6b887fbd55e826c169", "X": "01216328811ea0b97672d520084786fbfe7e1e771f96e8836a0c2d5fd55a0e92", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 207, "UT": "040b6da48b2019ee3fb376f71aebe810453a9c533983d3c119e9c9986d7f71b8bf0a632e3c4e1b528439449e92d329cccc053ac8e49491c030ecf71261cbfdfa14", "MS2": "19e7874aa0bf353f77cd1207e6a7e0081ebca34e965d10f8ea53aba1eff3bb69", "MS1": "047a35c476cd500bc648cac4b8c15e48e5b0e833c27afa56560bc71461a62a2d", "CLIENT_SECRET": "0404c211c5f092c26b1c95fef2a559a4cb46a4eb0ebd0b1c5d37833e699c0a3e651e76d9b66def747683a20264de41db150b2f6092bec00353f4d09553b35a337b"}, {"TimeValue": 1437055598, "SS1": "0b036a6a0d6531950b3d72a2a0278e11682a466a357d9d139ab30978bcd8cfd11b8c5de8a61b58941448885161cc5a608e015f1dc4ec9e10daf0e1048965c2fd1d7411aef8960d5e0131b07477fdc50cfeb01d8f1477e327fcfd8e517d918bf81d98bafb07f5ea2210da0f4486c2a1e25d9ea5a790f6dadb0b6a8bd6f55fa917", "SS2": "13c337278ddb115cb5fffc1938f1734bace38644d6166b82c8df3ef947543d0e090694e317c594a7093f8019e6595a3286eba3cc9339eb4f8ff3dc82343c81f1225b32dccab49e32c88366ad38952d8ed8793f3fd396734415295a214a3181a30d5807e8e94ead8131dba1cdc5f2c52031e2c60ccea86ad52c1ad7ad98732d42", "DATE": 16640, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "18971ffad15df4f352397794c2fe075ab998b07094440e3a1fbb2407bd49b48223ce88de88257de6a2fa87d0741355724a58d0607a94dcdbb3295e010daee3e41deb80935852183b64deb30cc5b75c96bcd3510fc8fac408f3cc058903af4b221c209840919998c10e45eb56cb63543413defc4efa34a6c8dd16c2d91bfb0c5f", "SEC": "040b702eedb60a9a4a0996e002b6d59a3b963d2c78b60eba1e546693eb99f0cc8e107f186390b82691eada719dfc570cdbc2a532a219f09db6f852b268ff8303ad", "TP2": "0420c0a69e58a6fa615eadcf3f89c28298902b8c56f3f17693edc1f86edf539665112dd66843ad4e11d297e0e78d8df306bea793c9de404843ae1a6ee71296d928", "TP1": "04035267471120d32d3a47f81845564f812e99e5db0ad80d81af9446404c070d630602e374839211f9826e8c78d063094d56faf3bb8603e210ef014487cd4b5ead", "CS1": "041f3221027edbcff26710d81cffa01c28167e04fac1d75d3c0e34115d82c13120136543a638bba5ee24d7bce618d9870938eb75c820dacab443f7e1adb47d6b68", "CS2": "0404d12982ebc0fc59d98700c543ed6545eeb01f7295ad0ad517f9280005e84f13223de2a207e1cc90b0b43ac47366b773e818cdc8465a536cb65dc82e2e192ad7", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04229bd6608411773e77b51bdf20e976dab7b2333cbfaa761e946230eb97ee969b1e237f1023e8ed64ebe65f853b81ef10e9bf7dc8622990568a81d5b22a67a848", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0422bb8199883d4186b2a62c17cb87105bf52ca84567b849b0013633c61e600fca217fb3a9b90f3ae26b64a556a5dcfb39f161158f0f9b5dee56fd37f89512c81a", "U": "0400fdcc0e8516b85f4333331bf8d412482352bbbb76d93c6244de86fba9c6351a1377f7768bcfcb1e8eeb158c6f9379dda05b86bbf834f8a09588255f583aef09", "SERVER_OUTPUT": 0, "Y": "030280d22a052f5c158e16e5a955beb22d3a495fc5fd649467bd108b47974979", "X": "119a92b990d729bcf3ad39e346f9221320df88d733ea191b5ca6bd77e506261a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 208, "UT": "041f1e76c925f226baa16caa6c58c0af540dad6562019922e3ba54fb11966bcf38159ae98a7e39abee05660de07b7af55e24224691412a10aed64fd983e3a3b3c8", "MS2": "13c2093e53f1405729f6bd0ee549897bd93b54f108799b252a2616ac73c885b8", "MS1": "04ec2454c5f51f5929d3493f5c0275f8ced97a4f4e3ae70114b7b7ee5b715a03", "CLIENT_SECRET": "040d546a85884eb5ce598339386a118c930a37d1ad15760f9718429a5d06fd07372069c0d3c6e15ab9d8f6c0453232579217b09457afe68d730ff4590895b89d36"}, {"TimeValue": 1437055598, "SS1": "16a62bbdec450329406ff57428573cd185a3c055e4e51aa235a1c9ae494c3c9b1251c08a3d7ab48a47fd428bd5e2246b2484aa983ecab944ca7cfbba6304e2d807cf7ac382a87036e5922d81cb83282b6f18de9f0e32b34e34e5e51deb08055c183bdeaa491cdd5e98f7521ec079597959645276c0888d0af3c5bad933884c17", "SS2": "0aeab61741dcda87a52a3a0487ddf9450f1eff56ecfc9b4dd7a744bd5a6c45571fa623ce489b9cf8ab5cb9e9c89455344d698540c84c6887bde55d35c880470201d251ccdf60e319590388e60d908a1af4f3599dd5c05264eea8e9be0996dd6a1b09190d86d9a668ca89b642a0b71712b993a4be1de59f43028009b867886002", "DATE": 16641, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "0eb308f65b58a557859bd16fc961e533c2fd734722a53130379fd29590e33c7a05c38169ce0fa161c00df555331a5b0af8f0c2a6f545e4fdc5044113c23f9b0122af88ea3b0da3cc9e4d8c1b797149b10923c94beab5ed63d15395ef43fcca6a06fe5e35f08a5ae39929682c92c07f7f08144488037cdcce9a2f9d162c4739e0", "SEC": "04059bf0bde3a601746bcb86644b83273b417a05f0c6cc80ca8d14f42715429dee10c5e170ba417fc9ee5418ab4a8dc05350389fd7541f2582b8054c62d177f7ae", "TP2": "041b8ef0c4b8455dacb750184c698b0ea4221dcb0a3a13557e47226d36858ab7361cb644d0f1ec50c94eb35618fe621cf71eb11a124aa6611ac3b2c657ef144542", "TP1": "04172b9352c87c10bb958f1ac068a2b6898ba268907adca2c7088be48b2ca40c101b2be62c480c9e0132fa539def15afa32be1dec818ccecab51ae31f11cb73e9d", "CS1": "0423a2917328a53239cfb8942e803a5e2cd771e607c022ae1fbab3ca8990b4aaed1371f7fa067d4bb440aab647099401bf2d42900aa1c1d12a52d80a7491a60821", "CS2": "040bc0c1691e82b10e162535e7177b91db91b06609e4f540b58f1e7a0ba42c37320401ee53b453179697d88e4f412dddaf244f20b74d156f316d29a41b5b3d20e2", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0401b3d0ba601300b3f6687a3e9f03eeb1ff980fa30c39cd5fb72b974076f694cb0491a7de0b55949a1dda51f4c9521e684a39529f4e7685fe7c5b0e8612f36651", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "041e99da53eb9415faf3a01c50b6ccb126dfe1d4d07204f6c04d7086719a625b1e137845333a7fb6a11681b4be62c231f8523cf6634bb30f6c0cbc16e150e4e41d", "U": "0400f0859a36ed5c0d34895b21baa9d9bfbb5ecec43d1ac04eedecf0a409a381ce02065509eeb6930f61f057b43279c5b6a6e7ff8670adb5d3d93368a35b9e43af", "SERVER_OUTPUT": 0, "Y": "1366b9a76c88bdeb34cebc419019ba1781f0e9fb431e7f8b23c7bedd611b52a4", "X": "0b598d46d307255ac5e8f2d1a9739a0e491898ac603784775e17762cfbd40034", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 209, "UT": "0412450b4d0db2813fd4aa8221eb9dd6338098fead3d436e823fdf15e839ac41f40d552dbfbe7998299634d9f7b728afb08b1ffbcd3bcfc8fa43a60658c3e85782", "MS2": "21b8fa44cc9c300fa5ed685130218372bbd7953ede25d9ceaa84632712c7c74f", "MS1": "0d799a540cb64ce943a46c00ade5a0198998c70ef635e5d293ec71505ed70137", "CLIENT_SECRET": "0409bcfe6a2fad0703dc6049da37f61d016947e107e2c3090a42ba63352629876709b8d9dcfb6b8b85802de5ca8f6ab6d30f31ed76562acb9e6cb79c0729aeee24"}, {"TimeValue": 1437055598, "SS1": "22a7b3a723d2fa3000f645fa6bae9c009f6c837bffe26e7de0707ebf66a1b2241b5355c3cf52580cda6e93f51b93e7c105480ab98396866e5328b53052e75eaa01b368a58ee0950979981b6776a675e8758f9eb4cdc50920748d8300214c00930b05e87494f6a781aff974a5202898c39d126132d0fa9d38f04f1231f22ddb63", "SS2": "12a87f67302b50023199d3feba2ad889aca6d5fd811dbe247003f1fcf9e64d941de3dbe1b0b6ca00e746683f2c9f56a877c314cb0b7d0ea65ec20f52746796a31bfc1058c2b5c39058786060cd63575e3352a4ee2dddca56ab1362b8249b8e4f1ffa4c6e4d9f5954e28904174ee1bfce9c07648682292be730e19178f3d0b898", "DATE": 16642, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "001f5a4f86243e652fca4e0985d1207f1ded97769fb1e7e524c8a081c963b40c083cdf1b74af4a7a411ae9dd416320da9536f08fce11a06a4e7c6f0b44c0aed30bdf99c89171cbd1e4ea93c974a53767489b2fb06c5ff6c21a84012e98bb84361c60f1c84338c3b90029fcffd2021a0ca4325cbffb56e49e131fcf4f4a080248", "SEC": "0408437dc272f5c0b14dcd7c2d8353820b7dcdbee1138afcf901000eaeb671c1b501724817d970aedec8bc26e7508003594b794c61814e87366703c4cae049d1cc", "TP2": "0415a74418098e318a199a4763d0b5676d522d69c8f12221120ae5ecc48e2069251eda8c783035b82857e9a67bf217263f362ea50e8ec614ed775314abeb4ce715", "TP1": "04043813860e5817d1ab0da1f17a24f81992c26d127e7ac7ed3eecf0adde3168c012f58d50cdf47a1d88f038304a4fc571337de3c2d32ab8b9dbf21bb3bcc8ac50", "CS1": "040058871d61e6e289690eeb820a13a0aaa1dafe8a1ed40977c9a6831be010c277213ae17727a6d3467c4701200c47ed76ec536679db9f797194434221380921e6", "CS2": "0405258d16835d298b53f4543d6a1555f96bde7594399430d4d50f1f9eef46ea5f19f9e214c0a7437f65434ba8fef0f932bb28470c0c7b4f17bff7618989511544", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0421177211d5dadececc17441cd6115ec117322f4ae342fa73df3edd88d7f611fd13c1678821fdc5e98d6dd6d51c0d1f081eb560923a4eb95e0971feaf23052c25", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "04086f796e309ef7a1ee4f22c5ac73c6594b019bab9bce198c02838bb6aa527ded196c7e15899914875b0ae964ff3570db3c443211d957745d8e5847a6cabfd06d", "U": "041888202fa015c2d03a99a9b1a098f968e2f9eb6272501d3631d2fd77b970e7eb02f5e4dd060ab95efce931b695204829b814f261ee0f0841ba64911beefe9b7a", "SERVER_OUTPUT": 0, "Y": "0d3efc40f79135d25975cff25c1482672f133949fa298bcc5e06ce6a5cb04577", "X": "17eee45c6cb1fe96e93204073bc4d26cd763c23254fdc2917720515074a6d9f8", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 210, "UT": "041425a805bead8021dfdf918a29e50e95d4002b58a85f70bd97ea9f5a5855efce1fbe3ce483dc50ceaa80298ed28f72e64545e336234dcec0c9ca28fd0f7858ec", "MS2": "1a5f359e62832ab46215c88abc9644814157573f1448435a5936fb2559f53c34", "MS1": "23d37e18efa2ca3cbcd1a393ad747c15ab65ded61e76681f05ee016e585125ae", "CLIENT_SECRET": "040d175813be1febe5ba6cb8f5031c01a23532bf56b136430bf556962f8d3bfdae0ec3102ac13d067af07b81942f5afbeccd2a4a6b7bbd098ef0db0ba92060c50c"}, {"TimeValue": 1437055598, "SS1": "1585b8b62103577a69cd89070543eb5b427a30ec3f07c4c0c64d308324837f8e08d46b3c105a4ab4e9ee30caa539057d1ea149ef92e4c8e80a6d59f0e41816f514f31f5df9ae2e6037c1775737d0cac3de9010708082d4cbee3c6522de502ddc096104cdd4254ab7f7f1a0740b90e255d45fe48be13610a493f01d39731c42d7", "SS2": "001c7deb089f4fb189cc4b4fc78d8c44a3a88441067ac0d9bcd5ddc945f01dd81509715bd5efad50e4c248917c7ccf29e3bd4dfc52577a2d344466b19a6509d11d002367e39cd7cca440cc458a9b73bf1b3ccafb192dd79828b3e369243d083a23707c83d47ebc0aa447995ccd4d6e5e664647e904865941fdd597ac27e86477", "DATE": 16643, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "1a65f8c1f7fcb31c242fa4be4f644a8b46beb866969bb7198cd510b8a8ac09c5081cd0f01c8010e0af2691f389476ae3ba0febd95b2d3185515c39f927e52af4128aa5d719ffa87a35715ddeb6b55c3a1bfac0773795b6da50200d3e77af2eaf143567289973beac5210f5251da0afbf10b9e601d33b77160c472d4d72f2319c", "SEC": "0418006bc67935b0158122fb1076dd4554ed57a1ed7a9595f4a5ba2553f73143e915f51e00ef10aad38aa3d5cdb41d5e3a2e06482d145196879a40b60f0be0d672", "TP2": "04136f0a08c803bd16b3992d99f3aedea0cc0daefcc924d72355cbdb09edac9b6b0ceeae1ce183fb333be8f56e7c9c63fc9b66bc40043de7c9c28f126278b6ab05", "TP1": "041023b4afa540da01f23816a04ef898aaade2e630c80d2c399e4db8f8b372c2c01c92d8dfb6d745566d67d5f2f6e7103b1b8bf994126d593f2180cd5972863077", "CS1": "042385868e5fb5cbc893f7f1a96f36b79bc49f85ae70ebc1de9997110bd9b8bedf0d8ffa8e6067933cb0d48f28e1d9d1e5f62ef1030123842126d08310d390fa87", "CS2": "04001dacc79add94ed6ebe2378a7ca779f92d80b31e563eca809ce22d67fd613210a29221ac2485e8bd0ff90637c7d1978dd9d6d7d4ede873ca502c2903e3730fe", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "040808c3915a508edaf36f8a6cc8f197b1b95da293b118ebfa8944d018790d6a630973a757590c4794bcb751314e878db0a786e878771bde67f73a0ca89e7dce9e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "041f66f03330022557ee8d85a602ab4a14c45afa07284158a3fcb6585efcc914230ab9957f395823970ce58e81d9797d99b2b9d70ea421a3203c5de459196f68cb", "U": "041e930bd5becdfd0f358942b00ada8c9f1d38f47a602e7d407dfe10a4969dc455173867a674c9cb976174ef884a3fe8e01094ac00b115460b9749e46a12f82612", "SERVER_OUTPUT": 0, "Y": "15b1626f02665c6f8e24efbd8256ac90eb8abf5add5217d89a6f1c307359c49c", "X": "00a68b76f3b121d4c94b81cb24fc5302e17d20798b975e54f12c7a88f671b465", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 211, "UT": "041f8b76168f352aa5d4d4d17d42b96ba6319ef904f6ae8e178c99451e24e3580c22bc5923fd348b11acd9edb662d10d8f281ab16098f9c3f9f05b84abe4d9ebc0", "MS2": "0772a8c4a415403e64412766a1dddf8c8abf396fc6c615e9a001b35909c3e581", "MS1": "171ca4fc3e268644901bcb9bbab801f83b2db5d5bd6b1a763c472050f8569a41", "CLIENT_SECRET": "040d3e4719752beb9dfb6b97b0ee0b2e13407cfdf7ae7818da3b96fed8e59976d913da9675e81514cc6c67ebbe331ccf7268fb9cf032607b70032d5a3662f90fa3"}, {"TimeValue": 1437055598, "SS1": "106ed8189340b884c37259c731a700378af91b12de5f3715020df38cb7dea1000448cbeb5748db62395a437dc8c706156db42d3e8dafe7015d00a6bcf78c1e73152a71dab8ca77f7eec77da429da9a05b61940d984e5073842bb7962b5329ec41babc72820725f8a01a42566d0ba0969c72e8706680988efbb1753c986b2e234", "SS2": "0b0a6ff1dd5dd7e54c350ecdd2a99a191aef0cada4b5a2468eb2eaf7c67903bf227752e9d75d8b5c903840cebac639d9d70186e8f6a53fb9ac7bed891e0ce7e52089659ae7c1d2400641513342a92feaaa731c189decaea8c4b87750c03bcdc21ec98d165f4cb5ff5b5adff234b85dca7c753d74bb3f7de70182b391e9b48a06", "DATE": 16644, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "147256f0d8b7db1b0dfb9f6a0b9b204aa5f6dc34edc71c864b2579d0fc5eacf214a132583c0b324b77bcc3122d845690a178ee7ba99a0c807860403d9fed136c12c1c1884704eac093e12887fe9569c4caa169c519061721d1f86540fd8ee08908aa940f49d1fdb3bac5f8cecdd8d46b7a370b2f413121bfb40044b3c390e37b", "SEC": "042046529cec6030e49fd978fd72c1f94076c5ea1164486b344eb402cbcd50b283033919541bcc7a066b9307da50527e13af9675ffdec94f4466ef9e1aba5f47d4", "TP2": "04232909ebe507feeaee12a30f89dcff3fe0c4e07cac55dcf45ad54facb12ca77b02361de1850933571e87097d01d962a5e5e23c9bbf30a818b165043ca5aef57b", "TP1": "04009ce59139883b991a806666c54e9fe2f184a37ca0b5f7918733c0e13abb2c521d08b98fdf41f826a0979d46cb527b492dee21d3c1256dcadc6643f6e0f6f42f", "CS1": "040e236e1f55adada27be45910fb87a35babeee9cfa6f9c80547cf37606a9bdeb1236b7e4edcaad0a6b929a1e799c0bb436468030b2abea75a828dc5568c969d92", "CS2": "040a57a7dd55d2ed4414d8e2c98432c3bb6d45748b76ad05e1dccf4312573d28aa0600ea54a0ee468f73ff1904fe7ef7b70e3024441434217f5659cfe577dd8423", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0403e8b6f8eb5af8a4547abe99adbf613e986d502f626d229a3469af5184ce54e91358a613e279a0d3cf30d3f8e9724a1f9eac9c2682142f6e347a012b349a0d2e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0401e0b5e62ddc992d9fa923252c6eff7a8558a2ed21cd782bc4d375560bd646550bc3f1183495d070b5179c20bd15afb711f257a19137e4e9255c5c1d69c315c0", "U": "04077d546aa8552ed1f3fd67444b986fe36b34b1088bc76b4fa41985300d5be81916d76feb159c2d5ca67567a4a0b1e0f387eb5261d83c592d6c56c9a81ee44e45", "SERVER_OUTPUT": 0, "Y": "0e8ae0d8b9ef938a178d0a8aee91515f735abe6b8c25d5c9902d53f3c0fe0203", "X": "16271e873057e69ee80d8652e454ae279b4fcfc1f632e5376a1bd4d573ce4fcf", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 212, "UT": "04029302486729eec515b87137ef0c077168167687448082f37ede06d5c60a785417efbad3888de1640e952edca4d4b4659c94bb28730e43d25d68c533e8f34c99", "MS2": "086234ff9b9ed934a535be7fbc5cde613f696880db1ce684077877806641d19b", "MS1": "110588e7b90b6ec2da71ca0869cf296655fb2cb1cb428469a27fb08078a74696", "CLIENT_SECRET": "0417137e330aa79e629830e3d68639500a103e2a965de4ee4fd5fd684fb1ad01911340c6a3a9cd3d448788b323397c938679f1b11a58a180e568b303b07fa063f6"}, {"TimeValue": 1437055598, "SS1": "08652738cee1b741d630bf2af34ee55624261441a44b7f02f8b8e924cad632b90c94af10d1070ec73190c67ef5e05d792045a1bcab1c75f5ded786efb1ef41e915cf5379e13c9e75275b544cadd2a80a0e104570c50e636d21ec6004ed0a2d8e1b595ea00645fda6babf428f99023e175bb0de662a8aa216af06f2be6be86375", "SS2": "04ab46102fe67057e5b4c2ee2fe213a8d2042598ec82cf9ce06fc34d3fd9e7ca03903748848e03065fcddae79cc9e7a98c8843c0202eff9d12a67482dc88a72723eaef4995dbbf9ea6acede4897adbe358f215bcf0227905ab23c2068fc10eac1ad037b9ba7a76bcd0f2082c20ca5db67654b99c7421d345ecbc8bf990a138e2", "DATE": 16645, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "1919e577fbbc8b301346c04530a976d7eeaf5ad2ae26d8e06e1701411c95360c1678587babf098fa1f8e8af1420db5e60a7cb51f1d51858f2491712996126d6b069b5b9b73f4c4e4c9a7fc5308d7d7f5ab7750b8bce65d7233a5ad4b2262bbb61eab6c2483adf159b6c7f642cc4265697ab36b24e0391aa258b93527ca9acdeb", "SEC": "0401c57844629968bf724079f374cacc190c33db69b843cf63b3661a6c20accb0c189ddb9c1bb38f71e41401aabd72509cfb5ded77618651a0b94af446fb297746", "TP2": "0421f2755429ca690c4d830ea4d10bec06bdde198bd52935a437c884fb11e27d840404fbf50558dfc1ff474ac5b19b318df756acd76c1ffaf1ba21379eaefe5285", "TP1": "0409fbc066c8c4b93bef9e33a3ac3090845c175660a83029d09e2b60e77862bdf80f84b5ce26fa0bb42b07204ac7ee805610ac27edc1b0c5878df658f6aa173126", "CS1": "040615f9d1e00830d5d51bbe9f77d80b7ee95ae82b205682bf86665928b7ba9a39014aa9962653f3b80c47655f7ac58d03a279b2268cbdee477611b282f89b6faf", "CS2": "040ce6bb1f4d4c87c1812085cb816afd6c9f514b049fb08271e8e09eb60ab20a0801dfc56a8887b547ffd66973e50ddddc2de029b14a2d9c3b6d774885d514ab29", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0417ffcf8b32577874dbd24d35a05a84caf2bd82312abd5240f1485ce1319719f3196584002926ba776d6bebec9beeb70186ef806a013ef58ffbe776d052bc16a5", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "04120c46ccfb0ea8c554deccab28fd329ba3ef248f0cd2d89fda1792bc2588ed2e05fad3d01c8f7a64ffaece4bfcc46318aa9b6b567aed79911b1b3c0f2abf046c", "U": "041bd50072652d01a50c45361e7c692579f295ee2006a38087bfdd9849b88281f318e0c35e546bcdcb305edcdea379d33ea30438eeb143e9d4221a650ce7075a79", "SERVER_OUTPUT": 0, "Y": "035b40f6b124ce9adcd7306450f2acfc1e045f39859c78f04371e0bf6befddf7", "X": "00f1fc1c2cfc7b8849ed3f60d511de902840adcaac9a33302d3bb0a36177c487", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 213, "UT": "040eafd3f7e012277658b6b1dd24daaf6c7e2e34b8b3272ada1df7219a20767d0c147e3d9cc4eac273ede385f50fc1b367c6c9d1946d7741788bccc88b78c4e968", "MS2": "014e6a988ae91f421335c6acfd3083be0f7aaa77ef2226a82255229493236b2d", "MS1": "0f1b31920fd07bb60aa7987095bd1028cf346816cebfa0ae2a0bed399096e569", "CLIENT_SECRET": "0414cbf80241005248524399968293451e9f940712eb86ea901a5235f28d9dbf951f425e24932b3e871fb2fe0fd5ec1adebdac4411d3215dcc82e2389ff71755a7"}, {"TimeValue": 1437055598, "SS1": "13155f722ace543a8367d41913b8dae0fda494e4bd2c121d8899254cd72969140ee5c40649e3f4f5dface0386a6d1714232d742bc0aa20039ef401fba0f9db4306b75301073612a83b54826f0bf0f52c2e7138850dda5fda66f7e08fb9b346d919e087419e58c9093350dcf12c04d0de8cc2f420b9a065fe9b9079e9ace1c86d", "SS2": "07448275015c68c58155fb140d054908bb83bb5db613cca2515a4201f89a18781c1c7206dc07220d9d5b5c744274ae23da6dd3895d292b5e8cfbd2bb30aca39e120e42bd2ea93c8b28df6e983676bdee7011efef9f9328eda970c0421ad7ad0000ede955ec5959253f74d0597ca7029be2ce7714951485e46ba80e691c82be1f", "DATE": 16646, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "00c09fb82b284a72f82269fcec6ee8fe0119b3a4a6a391ccea3b4ff7ecd8afbb09080bddb2b8298591c100d1f64982404bab383f3c7b886082dd3e19e6fbcc091e1f1a81abcc3ede2176a1cc71b9a0fff17de93c8ac4b9633c80c37226d7a8951415084262211669e79a766192aebca1023461c45780bd3aeefeccd3bf6a8634", "SEC": "041032fa436d77c0454cc27d220490306d5b1f39b85b07fd35158e548794086c5e1148cbc253f8b11e35c583ab4bd861bf12ad01768ae010540c00e923996b3239", "TP2": "0405a9e4d094152bf54d194e8c3e862ae7bb84d968914e61f101f4b5f7e12aaf8b12c989e3ad9d97b5ba0591e94053175f0d3eab0ef6873041111d5a68512c7838", "TP1": "040c2160aaf1d3f26433bc27c08488629c654be84871359dd47926e2cf16049a241829555cc396ec2417fed8349b3c2dbc5e90e0bce80770202c67e9d08c126795", "CS1": "041d65cb5e88c4c477e4e24ff715970282c45f678e3a1f4f4321d97a2eea67b76717c4139258e226fc4f3f0833a4be42184f02d61c318b939c80bec1a4c89a1209", "CS2": "040b41a197bb9e3187cd294da2aea43180d2e04ec4d15d4b5f19163d2b3650cadc1be0d269b463f08d2a40bc4e874fc5adfd16809a79f57424131e7d62dddbb0b4", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0405e5d2a4d7855c5a76ec8dd65b70fead3379327d41b1623cfc3b43d9d15652040dc80fcc7257f4cbbb830a92e158d555c78d554be5c4461841e85002b03f492f", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "04126235d474b9a77cb5c56c915cb48a4a9da465539cb6804577638b30c5058424197c98be07233dbee461b753c3476dc05221a6abbc573ff88c4abcfa47ed4e64", "U": "041872a1546792b5530f74923f04deac2bf0156caf1e30f88d7e864d87329439861195180868b6422314c24aafb44e990963209a9def113ce7e9a3fb8e96f49376", "SERVER_OUTPUT": 0, "Y": "18b8d7e1e60ab6702345830145b467e91c1fe53c75322b7d3f1b0bbc0193b1f4", "X": "1feeb808bda2dd83beb6c3b87e7970118976974fd074553f86ae2668538b9f1b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 214, "UT": "04194a7e713bfa2bd4cac10a23e20aebe22189652f918e1141f515027daeb92e1c095b0e429c8ee2a563634bb13b321127c7947e5e1ef04911ea49a007cfad9700", "MS2": "04ed475266fea0c296ee18ae21c0f188a919173a1d9e17ba6241788fe05bf274", "MS1": "192802a31f684fe8121b689f5e6b16aaedde745c5786628c4ee47d2ae3b64f94", "CLIENT_SECRET": "041024ac0beaecacb2d3311e62f4e52e1b70dc5798c06294d72e617010680690d21b5a3fe79cc5c77af332276693d9be56cb99377d2af9f11106539fc875cd9a02"}, {"TimeValue": 1437055598, "SS1": "07bff558d39dc947fe917c6570caed9a6a1aa5f8e3136e6322a7070811255d6e1e19bdd06a9dcf1b244cf0e1acebd3bc784e812ef7b77730e504c4bb9be31573009b8414e021851fc7a2f92af1226cb7352c23e60910e425b1297a105844cac5178bd77622e857a90e0f08925dc3f15808a154ef76a3ed9a1562522ce9cefdd9", "SS2": "14ebc4ac162288f751519d984894594decfae2f0820b92a8176430412330bd4f14c7ccc0c6d06db72e8e0bcad6bbc05bbcf7f2df41099fe1d1f50ada6d605b7e078d2fe345656dd04d92c16483d7ad97b1a270e6778995c8e9c8e6e56254859e0ae811fccb7002336e06178cd2f9669dd2eb57292f9c13a100b97808388128df", "DATE": 16647, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "1adcb038b702ccabfc6eb3e1eaf1c1768a8c7482c1f2d9a8b66e1345392885bb06510e0c0338605d1f45001e938d043cd92623354c6059765c29c014aa177987102a413f6210b846073416b6830ca6b4a69ec3b45a2c6c51340ebe8d28022c831f5930defab5e13b6810c252488242853a91a9fb856d7e9d4a623baedc82f6d6", "SEC": "04061b94bbb1de9fe30324748545a9ca927aa46927abdf156e70d0236a8a557ce323febb03c701e2eb40b5d50d4335068f9f71da78b0f2df033871d70b34cc43a8", "TP2": "04060d06aa68f6e216177a8e45a20cebcc2b5204724a25b7c97e0650e0c92914d90454a8e1f0876bcf13ba6041fcd4a0d3de639f4c79a656a67b4be879265b8270", "TP1": "0423ae04073adb9ae46ee731e165dd37378d71f1889356c560c0632a577419cf3f1d588804641b7e752f82ac2a43e5e374ce3266ce7da9743eb78d367a601faf8c", "CS1": "0410e4dcaf53d7b9a7a6a3d8123a7908cef742f44b4a8b63e92643fc4b4125c668140c83a1f1dff4f5bebc2cd7596393023f66c18af0d81dd669ef24fcc352bd7c", "CS2": "040bc47accec4852feafb185976161474c6a58774f818298ddf0944d97172c5efc0936a48bc3881fa2a34ac1545f4556c8ebbcfd27aec5cf4b1aeabf24c79f00e7", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "040c2e0fa8ee59daf0d7b7ffeaacb64fda5ed08b6bf94c5b06726d12e7b4ddfdd01534679e42db7bd4f3fd8e3e83504a231647d709da082e1ef8a574f05d45547f", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040154f6742a7359f59f444174adbff0eab5c09f8e1700cb675ffa27b536a7672a10e38f97a622efa00b4e8f156e286875b71e99171f29dcbe046455861806cff3", "U": "04148883a6d564438c6d94f287755b68275fb942eea134c414b12def9b59d093920b5c9aeb25fa4c8664815b8a4c7130240fb1fd9096108aca540d2757ef6bb39c", "SERVER_OUTPUT": 0, "Y": "0dd24f6e34d3332aa2f410052e91247ee16a99fb8017022cecdc932d764c371c", "X": "03874593e2ffa7a54358e88793e95699b2d320741c0579d48f46d587ee0d772c", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 215, "UT": "04213fb2d3837082b21277f39de271abfde01d459a503fa7e361ac319cf82a34ba1b201710061fe0091c8ee289d2cfb4a72693b6325647ace786debf2547d22454", "MS2": "0fb24e7de55c379154fd7ebe68ec856ae903f2fc1c238f4fe6710d0becf044b1", "MS1": "10d09fc7001290673b57b3cb40cb99857d7595ccbcf57e36fef312cbb3fc10d5", "CLIENT_SECRET": "04192e2018221efa72b4940e48c1d28f1637b54de8d1fd2f97ea58a9bf37003b942270ea8837fb898062ceaf84554a4c0c15fca7bebbaff67c4063de4d15af667a"}, {"TimeValue": 1437055598, "SS1": "174a407e6eeae21cbd5dde81d011592d9722b2d5b89887bd1a4c39117b96c4ed1a9f6a05a90d862a09c1f075c9116ba35c06ab48dbc16d42e23ce74231a359d612a26367ce653cca4bf17355e3dadecbfd5c417662b4b83564dcb0fb51350daf1041e3dca7c2ce3f8e958b39b627d563cd43cdd08461ceffe5ea678209006cef", "SS2": "1440568426c42bb64c950d438882533fabc1ffa9664b091d7c52064bb3c78ee60b99d8de0113b1bf1209e9b3add89ff3d502af7e318265101c018051e761f22f05f19a5e150497d05b7075ad1781f06fe028abb132b7aed961bd6bc06e31ba670e486ffd19ade36904623f288c1dfcffc035cf5984223907d81b4e6ad9de5808", "DATE": 16648, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "1a32b8a2c625e9dc5be40f0164b513a40a0731990ccd89416303a2f4b7b87eba23ca8c4d8126dabef4fac01b616652d9bebe9cef0d005fff2796dd1fdbc4617e10b6bb698dd3bd5050e84b57da9d79a3a6679dcf7ecbc46ec72b4236fc86309b203d31d6b99c438335110275c7ea29049f0e348a9b911812ae58a29c73f5a823", "SEC": "0407b39c70be8568b72cb03421c33214bbcd80691f4959655cd5323f76f31b9a13068497b3f060246879ffca7e6bc3b2f84b64d749d5d8247a677e91a7f4b86841", "TP2": "0422b316ffca9c513dc2b72f94afde1390199b64cc927fcf18d5ebc359147ca8d903f3c742cdf66d7d90faeed80331e169afa33819dbce961924cbe61dc60b49e0", "TP1": "041cdf2403cceff74ccf8027b6dcf54965ecfc6f08b8e964b2b2db613c7bef094b184687a1df6095d9d69b567c4baf1bbf2b3b88c1d1440ebd12031101972c358f", "CS1": "0421267ae7783cfbdf84df49a33390d275d68d80b2364f63682e4a8d21a08f24191a4d0b655d5b460d9592d3d013b177e9f77ffb2a6de6416300abc2feafdea0b0", "CS2": "040af81bf34cf5d93ec03471871915defb50cd8d52c75bec628baa95bb275738450149eee66fb08e168fa020ef0d50f9153ee54c8089d7e4123d3e334ce89ca428", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04140a42bc16bbde18519d8b97477a762491894608000779369cd3eaa37e8515bb1703e3697f62e3a2c2ef63073d49277342cc9ae59408b1c031511db354222765", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040c4f8a37a13900007063c29964e62e3ed3f6a1dd8a6b6b19806f59e5d6108c48103eac6ce635fd8b6e8da57115b527ae864bc20ad2426d851e33a348c8b295a3", "U": "04005fafda6a1a70ce4c3d70af015a3af4bb1e91b0d424da4078b9f6ad4174f657225b13e4c8da6810e5ffe2bbc03ac2eed794ed0b5141c93ae8a39f7467a7abd7", "SERVER_OUTPUT": 0, "Y": "1a7e2b877e17ebf6d1a4180f3daa0d0e90bf2b561b4439800529d5e2de715f60", "X": "13453b13255ad2453e2f8a6b897fe777bdccbc3ca07541e109c59a124246e1a9", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 216, "UT": "0412e5a8dbe6e39d19ae530ed8a98117c20e30a88c67d27be81236490b5547c6890930cc13d67eb2e7fa5ea1d9f0ef36a168e5b57b82971949e17ad527cea8025d", "MS2": "1780ec1f26d0dc29f7f5f1e09c9a233022b7805b125b3bcb569b2a9e5c9ad777", "MS1": "078dd7eaa7a947191a0749c140ee0b4dd900d52b74efcbb064567596b2c5af07", "CLIENT_SECRET": "0421035c0b4e4cfa907681003d0e8f5dec22012161b193fa5dd839599efa9bc7a8075a1b98fc03602c542d59e630dada53f6c29a4356a7bea0002624409a279891"}, {"TimeValue": 1437055598, "SS1": "17f6d88797f63cb47406ea6896f24f8559725f442af44b30397b771ca1245d3701cfb6d66170e6f7932ed708ba188e8d684481f0bf4e7133ad7d5188e5d51e0e0196f12c80f5bbafdb1709499f1729fd31471aecd1d3957d659c0892c85765a31104d66fb0a8abdda6c27b575a3922506e1e232e4c4e926f3b9ff297aed5a867", "SS2": "1602a96bb4f1bdd48bb2dc10561ca5d5ebefe06d2ec3c694c48a2fcf57793e0411d51993243bb2b42d46e616dde3609879bb4c69f0e4d1c18239e1a7ca103c7a23c8ccce1bf7058fbb2a49fbdc588c5d6fddf04ef2b184e847b9b3a6d6b25127177d6fa3d385e75f220afd6067f160b1d0721e3977705f5e0380f5efc1701106", "DATE": 16649, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "2098626ec3ab32247646c44d0743c225f6cdc7a0d50db6d89b10d52e7a41c1990171223d43b493f7cd8fbcf2f9219889590bf225d9ae6d67b835504747cb25a9005e57e2d4db56bdf4f7d9041bfdb7d3a66a7eea769c971ae8143f1b47d01c001ad6292455cfd34f327339f2e4d5689fcb4757e799e02fe321589b776029bcfd", "SEC": "0404cc822588a024f39c1a2d9ead1fdf2e19318cb4823ca3c75610cfdb6b766b9d00e157f6eda21d7c79fd2171195657b76a764b95d8820feaab327218e1897e46", "TP2": "040b5fbb46b2f4737ed29c0890910d593adbcba656903e5b5319ab93c7c17bbb13093268a75b0f01db8854d03915ca205af5fc6b4b3a93f8cd3af410a80a5d25d2", "TP1": "04110d95dcdea8f8865eeafabc9261e3b0e823fa5412d16f4bcd4fb1379b8f2c1a1a4cccdf6a49803f0507f2cb1eb9b909245c186c48b0ee1a32e7c5a79b6db199", "CS1": "041bfcbece9da1b171f0f250d2686e1c80c73e24c9fbdac61a22ac554ca06d2b6b0193241eb78fd7e037414b0c61c49e840522a9ee0c21c129212862d1df345d67", "CS2": "040ec69a164a0969a5e22cce6f682d1fc8f2cf5c384fd0699ed72b33053c9014c51c06d8c67de932849fdd73c504c971ab2822ac564b8287f41a63c1d785531654", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "040099f4f63d04b9f6de7b42c6b671cadedcd19e0e4caa55c2aae2ae21108d377416bab4ac65ef0acae933f0b2ec3cc9df9dbd6d7739eb112b40876100c431a455", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "04176f476961b1f07447939991fd6220feb8010c3bf0a827fcc5a99f1b765ca70c0b655b1d512af4d5988b3666df5f0275ccf3d7c086f367f4935545b3775a689c", "U": "040af15b38276c9aec2defb48780933ad0c220da46789c59a2ef88344a77fb945b14c37e353c1201fec259f2224aacbccea3f24698bc96c0ee6ff9837ee18725ae", "SERVER_OUTPUT": 0, "Y": "050456cec087964126ac8e83833e87ea60119ffbe0bdbf451ef47f88045f22ac", "X": "1c07730a32983ca3c673c02fef9b724c481fc1390f59a60334306ab264537d9d", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 217, "UT": "04138b8e2765352e11a77c621d40d027b350640ecd76711e477be58fd4b7d4af832329103e3d4515191996418ddb8f7fba12c5fb75db81df4a6d9981413a785a5d", "MS2": "002156f0bf1ea7bad468ace72fa21f5ae8aadd7e1d27b204f5915e3a286c611d", "MS1": "03a50b805b8dd326e7ac716e2ae6124d9cdf18b8c2d5f59b625bb82e3788480e", "CLIENT_SECRET": "0401bd0800030df92d16888418614beeb380c60f6f0eaaad8bfd3279b4e8258dd91a0d23c90df58c7ef437f16776a04163089decfb1a5cfbd942dfd41d6264fc97"}, {"TimeValue": 1437055598, "SS1": "1deb17abcecb51419643f68e0701c62ae84f78ad743a89648140a05f903864ca1bc05fd11a88bdd0c908f2728860caadadf5b046dd9fbc98cf920b5752a34c4b1a4f189ea547383d1f641ee168cc8670ab41da389c11cc04e8981ab4e5a97787180bf9bf1f3899c6673475f13542f903580e9393bdecc19ba54fcd52526ddb0b", "SS2": "0cc03d2eafc5db494c421e49c34bf3a87f0db93de6c455d61e8d5577f617c0c801976479c8c6b8792f4f35324eaf9c6cafe981740d1f038ed8bb4979a78da693033795caf2e30f66037b3a5cf3f17ea58c5387e65e7fab96156404d0e67ff7351ec873a06d6b6c339ce6c441e921dae74cabb18f2325fac31c7c4b805d8053b7", "DATE": 16650, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "1b13aee2632fff849d9d54dfe16e59512c897fee966af71a455cc214bc6d90e4156ebf4d0e87a5b62f54b96985c994c06d3066a22f3e4a71eaffe310036ac3801a49a16e5e58c8464e1cb1ad606f22b3b5f51d1ec89e89c24f1a7d6084ce1d9e055f8631c61fb8822bec63f447b6d96bcca7726e1b4ea6c9fdd5bda3f98d4961", "SEC": "0421aaf4e5f8823bde0f27a831af6284636bda3b7db03217420861b098b9aac1af132aee16d9a9e9484540fb366717ea3e5cf4a08364120d5bddb28d8766e0ce81", "TP2": "0409c85d0b71d154dc0015d3d3c0fa3ce75a501637db41197f56fcbed64f1f14941e79810983458971e232c10d774f2a44ef43d37e03ca9b18da943a6daf572585", "TP1": "04224ef9134044837edc6bd998ba18f8796415e2003304fa4693e5926dcfeb9dee11119d4b989bc1af978ba3f91de7dcaa4847acfd0b99856b4c7e4a27d5ad81c1", "CS1": "04226f22b379813d102734cc1a03cd9e4626d40190f1523e6ef8ce655f25f68c6d1c4a6eb7be412838109112ff3842110252a462d67dc273c0b262e660386cf638", "CS2": "040974851be271d71a807e9e13617415382fc7846a1e51c9b304ef7fe21176392912d4f1f9a0c159900843dfaf70c1269ffbab38e06caf0779d3997aa7c5da86a6", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04083f47a9a793baae730f8a6bfda99ba92549bac0ab89d08715dbe00b42e53d7813197f151913f136278fdc228be97d9a3625d70b14b22c4cefdde3815d0effb7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "041ccb77f20fa46eb08b0ecd680e7ae39135a35b8a3dcca4d1cd9f887a6489990520732bea979e6508edc6bc1585ceef367c5ca3d7a83bff08f42f50367e5c879c", "U": "041646ab9f346d50035b8d58e1055722e707fff46c943abf961ad07867eb48957a15b4d1e3924030e7b5d640fa6f886f1815ac07b96e8b0690ff2ad63a63ced059", "SERVER_OUTPUT": 0, "Y": "0c31f00a56f1ad3edeaec1757543d9c34ff36ac1e583cab6c3879f57dc3a8b1f", "X": "193752bcb87338f68ddc9fae7d8f19404d44c1d7f7b76b7668fc182c23d7abb7", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 218, "UT": "040261fa9df7729c7f74ced6d1dddd7b344f75b8abc485d988c0d3215aa5941c6820b453035852b353853ef52b4bb15c01b1b2dbe16f1340d89747430671225923", "MS2": "09bd727128aa434ba711d5f9a1476912693ba5c6c33baba27fa923e213f32409", "MS1": "1ac84ee7189b8e12b756e634e3e991dbc4b0dd21dd875bf170ca19e60b976142", "CLIENT_SECRET": "040a91e79d318513986c17b512a242720654d91399734266a79069af17a3bf09ec0d52b9c68d17adc75096fecec483384aced49bddcd492d2a9141ab267c64ca58"}, {"TimeValue": 1437055598, "SS1": "1c9f989091fc1d463d2039a87f9981873614000a531223f3b2497db76fdf807c12c216f86091586f665d6d92929e2c66c27b86e8f5ca084f6aa93220c7fb743d119c779a0f2758b9583025ac577fce89f04c672e70bceaa23222299e9cc9ca0e0345de475155a3beb7b3759676d31ca48402e91e885826408f0b40fa722ca40f", "SS2": "164a65deb9e33283399dd4f315f2fcbf5b0c4d86b8cb8447cf903b2408b8844518987d05d6585287d618e13de6fc19726a0bf964cc02948e0a0f1ff8a9f204be11c83a949b23c2e8ec99c6147f9e59df8700800c6ac62517a4178ca75ac0a32b0ace7e5cff251740b16d8a748758078ad967e8b9f4fd68a026eff9c6ee8064ce", "DATE": 16651, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "12720103e6b15f19f4d5fbfda23e9942027373a89c6745d65ffcd350b4ef86461258017a3463ecb36149e7a3d44bbc3deaad073a26f3c13325ea4a02dfe9ad101b158c2fdc92bc2a0096dd2ea9b6bf6c081ceff6b5005258817ca763fbd4940309682b1b4197fec8cd846a3a6d67e77295a27094bfee711220a8eb4d4cc94063", "SEC": "040e29322b035ce515fd756724900dfbc3073564d87ddad85e91bd0535dff0df1322a137d9b5f06f66eee31386c659540b18dcf3948fed8ace45b40d8de7386fa8", "TP2": "040d140dc1a3ee83baaca802a8c907bbb847d997a3161a1e2c78bff036864233031f77b62ad1f4f57b39d9567c4b574d213dd3aefee39686853aaca8075603bcbf", "TP1": "040a0676de83ba85fe00b886ccd044634e20219dfd19784139c840855d375496391eb53d10a40bcaebe5e404c9869ef96ceb6fa19dde398cfff15bf4cdefea395e", "CS1": "0407d394bf6af25bdc9a8db6649489cdca7717b27c3af6033420ea8d1aa0f8d67f03df9978d1e42fdeaddf65e44e8922db370b944e785e6a53edc91d55e62ca974", "CS2": "0406fd63aa4fcd0a9ea3c1001a05fe4a76a6e02f68be26e6569bdf9df8d1d388c823ea85e577bce461209533bf108c08ffed87b1f37d8c3da03ef3506bbb870029", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "040a161349fb69408e61c91beb142ede712db06d3a77c657f7267862bd1203238c0d55e7a8c68c1a4186d90edd5c8121e3190dcc5eb669feca83062ce96f8b060f", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0406e61bc958a95eacbbdb13c88fa61b723c7671b7784e63b6e5bbef05c32b07640dd23335e2c8632496395017b3c8cef1a38d327e2545939746fb09c3acd82614", "U": "0413b6c5d93bf6b1197d41f828546a7181cb75e9c6b81756a4f3948793e47b9e6505159ca918d91979b77baf548d70cab100d2291da7ae483e2d7372bb638b6b61", "SERVER_OUTPUT": 0, "Y": "0c1ec8cb2fb2620ab020471d19c9f6c2e1f855c1a5f40db8c4d309baf59d4933", "X": "0ec2b2fb224f71e6cb335dd88a1e5e1759c244cc404f023bbd20e509dfa068e9", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 219, "UT": "0402fc70c2ee579a6e78ed8fac8c8102c4cb9879689bb22f4c78beea56e492e1910719ab9186de17a06b105647c55c0c6abac08cc1a199f1e2d5b6bfe6b3905dff", "MS2": "1e36f99def827d6f0d9dd94796fe706b3e76f061a57e78d2d563452de2e0e115", "MS1": "198cdf7c4deacd4a31c29e89d635e3c484f1e0740bd92e20f80b59865d29535c", "CLIENT_SECRET": "040a4acbc334978a97d21483144ae714e01c2be40dfc731c7205bee0eea14b43b50aa97f6dbc98c0043e5a575ccc96a6f60fe9bb5b52d52134be6eb73641c0a616"}, {"TimeValue": 1437055598, "SS1": "1d56633e29111200f91e1c4992e3a731609adcca0ad9833d5d11cfe04b05b5591f8353058f7b8fb62a2971235d56dd1db8e6494d69a5fa16ea790f3177f64c26176fab58f1a62f1574c45710cd87aa48a1af6617797cf656f70290a1b6e96faa07f2cc8194ff32cadb45821bf347b2466767896d5c28fb182ac36098614a9d47", "SS2": "0ca80f19aae6b2a490e7579060a90ba60ac730203caac37c28b450617af01faf00e66342ee7693c26c1d38e7713e8afa7aae0918e13a9a09e25a3838d68677ea22739cf69b4fd6fb00d4d73a2471639fd2cae9059aa36426ad97f4531cd206e404e0d4e3a33ab081dc5d6659152c3d389da6f314482a9477cd644ab84e3f5a68", "DATE": 16652, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "00e78b78811f67a43e2e237dde2ca38608828bc4219bc3f31521d2bc98b250250d2fd30f25e205563bd862d4d2ab6d284277e30ff29c35b41adc2533f995f8240ba1b878cb74978c982921d2b1f759c0ebeade62b19baa70def7cae274b7ce7d18f4fd631f4399323c5fde8461bb7528b55f2472660abd3acec9d0581cf23708", "SEC": "040ea940924922dc0b3603e3e2cc6ec52306cdac7551a1faa8e807f9a8bb4eec9322bbe84081a31b8aedba85dbc89523d496d1704f5bbd5756158832dc0715d944", "TP2": "040a6b60c1251416d563353a9baae6473424ff7fb807bd90d33f2483bd38ab23431fe4f42b4bbf734df312d4967fa0142af3eb767602a39f86e0e81aed2482a90c", "TP1": "04011cdeb4bc39e876b3e22f16aa0afade085a885767088e1767da0673a2d6fcfc018b09c7dd3b99eeac8f755ce8cbfdedd90190ff4e1f6e0f97ad39a5305eb214", "CS1": "04041c41c7d15a9a4bb721b5738587524e4dba82de8cff9403a730fd829faea0a119f4c14c44a3283ab8e838cdf75cfa67fa8620c40ac8c3088c8514ba3573b7f5", "CS2": "0406e40f87d66163b1fd9697d6558c0a743a6d4853af13c6f86ac32b2f6fb7a4070e7270447c216e6b248ae1343cfefd8afc05002272bc8f24c516d373ff197fb9", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0419b57b7c2798b83b7ef7987d3685743afc169d2db895a42bd194821384f251ee02691b67dbdb5c7828fd46e9d5b034fc16f1297ecf854468cc10edc178d22bcb", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0406aa32d3397f4a0872373939df9ac911de1463e38eaa1badcf76ee2adf6a913a19c890aa78fa6c14f0c72a7e8336b9969fe7f40eb10f06b9a4249bbfd7cfc8e2", "U": "04219ab32298c0fa7be50f56086a6cc6de424824eb6c31ca971fb37d28300e2cc9100f7a2ff65b716144b369602942a2f20317ecb9ed0ee2f993132e017ce6825a", "SERVER_OUTPUT": 0, "Y": "1f8f10dbf6a0869116a7702f3a9dbd228bfd0710f1e8fc8020b0c4ab41cd5368", "X": "0775428b7780c376c10d24a99ef0315b20721e17691a032c20d492e9efa4d66e", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 220, "UT": "0418503730da0a718b59742ad8a76a8297c1746b126329c8a0e6eb8538291eb11622902503ce3d4d23bb4c080b899ed62d28804cd0a4902588f2e5eafcf29c35b5", "MS2": "1b4a52d2fbd40861ba3966ef8f65921c8e272f92581025422468fb50426421e9", "MS1": "229ab5d3114ca4b6c85960610fae9e3c54a391625f32f09bbb005218bc04bece", "CLIENT_SECRET": "041f0a2fbfc1dab2a2b00ab1e11370a268319c823b4f6eb393fe420872b27b0980076fc9b566fb12fda578d0ed4622aff4cb92961cdf5d71c233008bde8b57459e"}, {"TimeValue": 1437055598, "SS1": "058cddabb80af768243cdb5b06a6761e1bb29ec8cca2e8d90afb8e129933c5261424ff2e132e135f50f9077eff0d760b0cc0668e80d2496c78f99163e608d0540916d35247dc99792dbcebd9fbb44389d43c4978faca5199214f168f591a003d222becb3f1039cbe345725ec70cf76a48fa7c04df2c7aa924a158a4b7c44f52a", "SS2": "02374e826b97f9f29941a2752bb7789737be84f3367ba07bc07ef9297688e277194042821333010d442941938f7434b01a6ea3290f87ecb9d549482a9fa5735a14c6fb8e2e5f5456e10375502e59793cdc0538ddba215fbc4a115715b4dd986500e16f014c89347ec6c3d48423f84450f63682359aedd925bb53c4f50af559c1", "DATE": 16653, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "054530664efd8b6ca2f2c94b8dd4e03db55a4690dcae4f39a05e4942699a146b0cf9703a8fa65d4458f431ea8e73d8d17aedc37b873e5ea0f2280d1589f8ab3d0ae471094b2feba6e2661a6d23af8069adf0de950797e6744feb71df30a816c40ad7673716804e7f3e2509e696c4a0ff028e827a3df689adb6b7bc96ab1f03d8", "SEC": "04208a7f1195aa2e9c99143c7739edbaedbd7eb259405e0030de41179e5dac0fe71984193fbe98c7f2c732dfffe6c0dd1eb516aea52899e279fd3e1a159e0cdb99", "TP2": "0400cb86a08f2fcf5e385e0d8796395be2b30a549a30869fd38b0e7b92bb15c5c400eae0aa8912f1232bc297d90c2e9947502a3b04df2d53bad60a5ea8231fefbd", "TP1": "040efcc168acbc5283a809e0053e31b50aadbfb12b35f3fcf2f0e11bc0eb05b990020daf7b387e4676c8ebae5619860195dcb729950bea8c247169be7f06b3c003", "CS1": "042389f37589e4af2f217f0d024833e537add6397678c8a8f32d41d5bdbbf7d40311bfb947f1dc161b1acd5b1f0612225e346c27bc986519e8d2255c0a9a43b413", "CS2": "0408823e7a9f3443f5b022c231648ce7bab60f5287115de11b0f21400502a4f2af0a82890cf22ed1a06d04f52b9c1807b29511cebf97947b761c8b2e7e8bd13f30", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "041661e95d3f4b266a817f589e0a656ee915456e41f2a964b4fb8a93023c6d069e11e1361494d4c2d7b27504469ab15b7bd00cb5a2b32a0b1b6852429c310a5f10", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0406122e10f77e6445b4f98590ab1ef38ceaf5c8f68d5d38a6f5a2329f21c47f9b14680d6403ff28989284029afe8c21bc70e9756fde8b3570e413f5ad85f8a455", "U": "040b30806030868764aec93a477555e2549dcf3ae9caff710f619f0131ade47ea41ef23325ec8d0ef3bd357baef3a5c1f5fe954b9508e26ec25e485601e624a8ad", "SERVER_OUTPUT": 0, "Y": "221fd8caf4e718e515c455ba1f0c61642b98cf213a51fdc7ca61d236f76adff0", "X": "06bbe7ca31c985255006ebbe692df373d7a59959f62273f79e2767ba5405b2df", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 221, "UT": "0422700dfdbd35eec4561dd90ef0f0e6e78261446ac5082867f2ec2b9853043ea918133d65e3a2a99d3c8c19ae289c0a49132c6e31ba8deaf5e75abf353334b516", "MS2": "1694f0534c4e196315364cf53b8da6c97c511989708592700176153a1c77c437", "MS1": "0303978a580bfacadc976820126c144d59d4784b67d37fbe65f21cfce7943a8a", "CLIENT_SECRET": "041b2e430a7f8f5c549f8cbbe2cb144dcee109d9ea692ce115d82f2a385a0e18971eae777214b605c6c9cf04dc029657620b97b21659654d9bfd53ee48b8e20ea0"}, {"TimeValue": 1437055598, "SS1": "06cf93d729f8ea31ddaeed25bb818340e3d36b54fa0ddb2f082e43b2c124626123545033a9434dcb9f036d1cd50897faed0f93179a98a36f3bb8ce4f842759c723f41560b561aed14ecc860cec7a0c5f36dbc4266dbd9da1a14d08798c3cea252220db7985b0a6e84c32af5f290fc9e16cf9d7d64fae7e034fe5a5904091aba9", "SS2": "0fb85c9bda12532e4647d7fce4d6aeacbc528829a5199e56010dfc7f7a02bf400578f86169557d04f8b58171f62e5f2f7015e52278befd606a17a1e2173dde05147057423a8e67816a677af9c4a9b909cd7fa99f03d594df82da96374a27508d0b6e91e74eb90d29cc0bff42070de504efbde19a4a84710bb2a8e00e95adce62", "DATE": 16654, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "22ca016a1da28aec09fd2c0ff445ec0ce92e95d2aef9a493447dd0603b08bd700ec8177a28d8627529df3ef06571db758a8c7c1a221ccf7f18c88711ec4837ef1b72c1c126132c15b1e5e26d2142299877177dcb7d66a4ca942d5d6b268a418b2102e5297980ff6a00d5ed7d3cb87079956e8e4bdc9fdf4b2ac447d5ec0f59ce", "SEC": "0422dafa66fc35b1dcb1579ed961b55883306d6b0615fb8d01e52cb9e2ea38b301033e3f106d9c8efa236d57d35b0d62511ec05da895c81838d9920799ac40b3ce", "TP2": "0414524a7dffc202677fba175378cc9e7e0a4f679c762153c434f9d5bacd75930a0dd98ea224f4549238680b425c2a4a0c95d0bd5283764bdc7c2743bb549f7e69", "TP1": "0407e6ca11343b50ea066766ab26030a3237acbb81447d92a7924914660b0d600c1066d36794741b08fbbf3e9ec073e09928418e5587792d99dadecfb16c2456dd", "CS1": "041ffd4fadbf20fd33ee26b2ef5cd408ac132277b3404cb0df70e4d8059ddbb75701d88d75152b728c8a52f8fd88bf47019bc43c540bcb5789ef86633dac7e574b", "CS2": "0414acc9da587f50fa17e1c2318bbebbae619b9646ae6bd2ccac7039a9e802164e22cc4fcf74aea64fde8422cfecd276485881f86a2839b2e6a96f2bf992d01680", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0403335166022fbc9974df15d888dd34fe9e47542977a28bbe48ed2d483f10351f172ad815a40694e1efbf98a3ef595624227e274964d8f15351f28207e1007c0d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "041912e1a757b8d8cd04b49c8f8df8c420a03227f7ee6173571673fedee7d57d0a05ef3ef23f23b1ea4f0947bb5e350471da51d6ae2a88b41def85ba839f497a67", "U": "0415af6330bdd55eb8e54121e75b375257cec122430b6f1a4a170d4f4e7015cc691a2e5c58ea0797f1ca3bf3d34e8248e0d0b51772807209dc335efcf65578505f", "SERVER_OUTPUT": 0, "Y": "141ddf63343cb13a607f685db4a7bb49fc718570c5c09bd3cec0310e9e228c98", "X": "02137256a77a447b0749db17f801ebc551b7a25b8a8813f3f0c528b9a9471b70", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 222, "UT": "04065919e0e40ffc634109b2a48d859fbc1111f0af810f09b630988088d3af4d5515f3d4b58e27f827de85e041723383a7bf42c0350c6a4d6094b304508b356d28", "MS2": "151960a0f1173aa9f5b2fca4d1103b0c89279588ba8dc19117bdc508b2ff3ae2", "MS1": "193d80b08da455e05b254096b5711f0b0406607cd47380f95220103713c7cfc5", "CLIENT_SECRET": "0420a8c12003c197a0f79372084763d7d4c358e0104aa85ff0cd46a850a3df047017ceb9cb0fef473a04d697bc02dc4ca52ca4569330a4a65f78f22ed2d54bc700"}, {"TimeValue": 1437055598, "SS1": "2029a58d0dea53ee3c05627b3b151e849ea7e3816b2b595d7ded9302626645781d75a780791b8a59cb1ef205167273a54906ab26a644dc609c421746c5421b4f232024d8bc4620bd9d42cdd926d6c476a8bfbf91fe5c38c36e469b7bbbaf84f50ccf7e56e7ca49b7dda4b5acebbe5d3e0d01a1aaf87bc463ef03abc8ba91de87", "SS2": "039ab5b7bbc6aa8f40a9f79932c5d0c6d05dc7d0bc82d9d753305c62dac1b03104822761e127903baa5391af0228babde94fc827e7ad0c0a9c64f4ea6c61affa13f833597ad1a48c053c06ef4691d2bd7a609b37d2e6fc235bca24f9f50b23661ee74f28d8f77d10ad31ddf1aa9eb5c040af56241cbb411286942e81a07d7662", "DATE": 16655, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "2239be842a7f8cba6bf2e426e6b4f8de0b93592e002a0278e5eb464b12bebc1a0ac5d9b66936c605b0447f46b8b3ef4a903034583253b8d8cc23f4f60dd9e28904bd8f164908e585203c5783358f084168f6100f0de80dfc31cc62f4cdaff8081c03efe70d0b36edd81ece6fcdd1e8808a03a96834cd1f9772d50550519d608b", "SEC": "04101a09037271c3827d102ac5eced12b3d1ed4b14fff2031c0edff3b4c3f1220119644c5f3c7d5e7e272bcba0ce82cea76e0867356169a75ce55a3cecee1d60cc", "TP2": "041d028f5a3233162c1af39bd6e1b023366d65e5f860ac6a3549b72253414c03620c0264fa0e4645ee4e5fd7fb9ef2ab17cb0d0e3adf91e4a6fd636e70ee3f458d", "TP1": "04214cc7464e17265614aa7ad87a38c6b0b32b094fbbde5c00d2ca46d6da8d28a51e76e4daec3521978d6c5425a6cdf79e6ab67b86c2f5e302341f8ef7bceb1d7d", "CS1": "041cc3230509fe8524eef3132f1b5b750280fca269d440352c310a10b14aa6e6ac0d37adc4e239ac41f11f22905ae0e289b433cf6722b8a9aa880151b9ff569c3c", "CS2": "040720bcf0171c4bf09f3a306687ba9a6a61bc70821a84f44f14b63a23c34700ff0adde45cc778e79dca2cabf89d9e50eee3c07db8c9b579c074fc7cf2763441ea", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "042196f62dab41fc82ebb40eca3efd5ca6ddb19dff295b727f6c8ff62d6058eadb19d1c92647e181f8575ccb81b2792034bf4fd7bd1743ac60cc9d808be081f3d1", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040be398282a4087ddee0702f58320be93b83945377aad1912759c1d77a02a774019e8b882c39c57e0a30883e552278387537d98a7c381a245a8111212aae4ac6d", "U": "04083b808a46bcd984e8a96cb1c56d93c74f7665477945e5096348150e4a3143f11ca5630670e0949bc98a50e27c387ef706b73bc4226d0174b5624d35addf38a3", "SERVER_OUTPUT": 0, "Y": "1dee85a792b9a3406e2e0f24903dded97877c83aaa33eba0e3afbc0591a6d098", "X": "053a00a3e01bc9575d15680830a15e0078b91d0c72f7c2b3ac98a5c1fc662b0c", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 223, "UT": "0417d8da00124065af34c55bee7da6c166f2bfb8cab1e8dcc424fe87d2b82dea7803fae98438d3b44ea91f8464bc736739ae87b75d5508b5f6ce593cbb73e993bb", "MS2": "134122c67372a17a1905fb72c865048ab10e14865d87c546c71ca5d7bb1eb7c8", "MS1": "0806b6bcda84c8336b09041ecff46e10cc4d842b49ecca8664ea056e1c53789d", "CLIENT_SECRET": "041ec9bcc86bcba54592eb14c8d5d204384cd0b7c060768cf6de7faa9b58652c990385dd8aad559edcbb5c8bfc5de78e35b9b7ec3384c94607e10de545691cc9b7"}, {"TimeValue": 1437055598, "SS1": "19ab2925ccf7d0671600c12eb6dc5994add3fe59ee75f8d86379b66fc70a03331f5d83e9afb6ce78c726fbcd0a8899d608ff5825c8317bd7aca84113bf1212fb043906ef5d98cd5e1ab7c710e92f1a5e7b60f29bd74ae9ec6bbbeb5e720b455a1e93dc33d7a6259eea1272c8c55e80e6a7587b066125baa473b19914489ad9a3", "SS2": "1e77585348eba9e777c60a3a3c6ae28bd9038d3cd9c935064dd868aecb6fe7f91efefd57a021ec8b31e8a57cfd56436e1c8235c54c5425b89567273ff0ee8bab1d2eef862ab6b12be0936e29679c3efb4a21957f09b066abd111a62f7c4b5fd911e43eb7d06346c3acc00d44c4609c9c7bfa23fcf9dc48cc66d7571a1d3eb84e", "DATE": 16656, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "1d99e6169159aa77b3356a3fd88a55adf7f760a088964caf8417906828faedd216180e48a3e426d2c42cd5cfc36bd0c27a40e64d73cbdba15dae6a98752eb5c40e63cb6941508da171a9d710543078aa97f1f6005d027a59f047604121b4d129005a22230f9359ce8a7e4488282cc7bf61d0d1293ce7a36ccef7f5338b9fb2dd", "SEC": "04008add4db44abbeed14c86a2fff3d32c5d06a10e23faa9eb4e799d0f43f0ae7f20bc58faee20e0bcf8d058a49c69275ea3fca7735d35408e8cb28f232b31ca4e", "TP2": "0414a7d206621f41780999d7fc80a62ebd471ee7d2664f5c4afb44c4f4ec1d953f227277d3ff3cf98561344ef305eb05c2f8c33dffa7f75e7970853a7b0709a473", "TP1": "040ebd82a90071a54d8e730f0e6a3ab82dcbe15d104696bb4516fad28cdff4c8951b80db6daff64bf5ec828173247bde2f3285e58877d8b456a3e5d9d6ad0b69bb", "CS1": "041b56a4d672fc7c48425e547d4336d72b1b221e5776e5385b20a202614bcb105618073779a6edcf5ecda1458ea2f97938fe18ab63001967ccac6814f8a551b03b", "CS2": "04228599595a6a98ed80d44af883a6442d3d3ce774e3a302a3883d6590c64f40ec1ff13be71dbb0b429cc85eab8cb912c384ae478f4b31ec8c3d53b69e0c3658df", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04209454bdc12c6facf0ddef3468b74cee4ee65027629f3d6e7248bc6693923e3310b2c83a1ec65d3f2883b0ec3eaede19401d698b01c06e4d919c704dde081ded", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040e3952944e5b14602ee0cb3a03e3f0313f51026377e352589c044f9425a6fa5a0d6cd35cfae8b0307665fe078e0dae151424d7de7b388557292a0e0cfb607745", "U": "0412b61aa9df93e6023fbf4ffe28d313b7fd9497f0f06a1d755c30a68cefa5e4f1209912a96208d7d005961d262c9989e75209b609c35ab106dcd62183a31bda63", "SERVER_OUTPUT": 0, "Y": "011b0780f72ad82e2f8f166b09ccb141a5a149e449f513f032071fd1ed615c7f", "X": "0d55b71349b595e892751e88288b3d0d194899b8fc893e4b1be3b7e73a2a774d", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 224, "UT": "040d46e985f6c8c59a948912da54974f87578b5fe0929e091c16aecbd0ab38b74e20dfd09cbfd47498a3d1254119a60f9b7d34558a94c1af0b1e3f008b2a7cf677", "MS2": "08fab4bea65c82681521fe2259aadf385343500cb38a2daf8c4f16352acb71ef", "MS1": "1fb3bf791dc70b5fb05993a98657c5d3aa20ba0c92804cb1ddfcfd4ed353b285", "CLIENT_SECRET": "0401a50cdb8f5b427d0bbe1139d3544a86a5944669ee5e22fe386b7582d6a01b6618ab6d1552d3fcde3f0e53b784af7e2036b5c7aaae8d10f0ab137dfdffddfef1"}, {"TimeValue": 1437055598, "SS1": "0055c6150d5598a194277605ee2467a81148ee16b68aee6fb738b2aa92cc6b390eaf301571421420f066c5597a8e14c5f17579f1e23421dba00dc0fea12a07da141450804d6a367da841e22e456871c68a1a9dfe850b6807bbabb1d0fe21bb670e1697f8bc77e5b711b09fec4e9b06c89fd612e4efa4bd5daf558d012dbfdb34", "SS2": "13aa24918ad9f02a2105958af58dd08c9c9951c50aa36d7dc557755f8c3f5aa51698fe8ff53df196013c4ab887d14a62f28837576f467cb385a4bd30763f8e260842f34da423477c51cb3d2fe4b25896f023bcd3aee439d9f2a58acbe720831904fdfbeec4e7c0a440ce2b5b567d8e243f7f4f6e88c6b825938b9ba4c2bfe493", "DATE": 16657, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "09cc5b2321c3b7c039c981e6c02855172e50758f6adec63cf79542e65278a2d400c5f708f53008a5a32023c0edc222175edbc78750cf065c7ed2ac051cbb3aed238ee3edab49622de577763e6e2cc2d709a6ccd6eeb6741b66ecae26b2729f7513da75988a1307a0e67d847e3abd412abb95c26532d867026cfe1dd40abe792c", "SEC": "0402f3d2a532a876e50b5e040a8c033ffea7aad1ab7d579fa1720a9d038164a27601eabacac8faccc43ae1273160ac684e317cb76335e67bc3125ac292f1f7da08", "TP2": "040be6964621b9cd0a0da865baccb02b28478fd2f629dd358ba894fe2ed19ffc0a0b469d877676241332770169e1c610729cc38b8932e390c9efd38732911d1ab3", "TP1": "0404e880d3a95325e412ebdb0fcbd5763dcfa7d04649c6b0de48cce1b61001d26c1196c5b4f6252d512ea66cbe7acc41834a342c9380646f5eb439bc385b6701d2", "CS1": "0413c61df00ffd1bb50ee401e556a8a3384fdca12149f2d46448babb2cdf0f6443006909ce61499e16eaf1ceb51600931daf864485989bfabcb4058287cb52d637", "CS2": "041c5dddb68939edb6e26cd25271867c74267c6a111064d157823a3e75df2e43db01c8189fa5d39cf4dec0bfe5d81d75ff341fe38afff82ba589098040b41d04e0", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04221441aa312644ec829e27aaac221b8b848e98d767db3cfd10c64198b8617e3c21235788f017ef04b1a8a13c04d6fe44d69ed83649a64539782aec92b11af7d7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0401e54735f017445f57052457f530eff4d01ce275cf00a778becdef3df83a5970236942c645711a135d393e8cc31c6f7248b5ed54e147b669da72934b7f87ed85", "U": "041be3fd2d0adf0f58f8e8e033634ae0687c471704cc510368d3e063429dbfa56f169a4fec631bdb79619ed313d074881fc1a38fa4a17cc6c40de62ded3d63517b", "SERVER_OUTPUT": 0, "Y": "009546b531e7d1857982d06c2afb4b1d35344efeb9c2b30fb77b3f475735a2f8", "X": "0b432bd3a649ddd55aecdfd67a0623089011de4011506ced7b974a4ae6ba6c4f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 225, "UT": "041321a283b14ece94e8f4645480c1c4f885494d4bad0ce75fa6b5baaa7cc4b0f1073ae580338f91650cc8a5a76dd0fa8a9db8a95fb66742f47ca8ef9ae179d20c", "MS2": "13fc58bf70bd7b289237733ff26e1f9a2063498553c11a1962581fe240c7ba2a", "MS1": "03cf91401f062804950f1f267d9a466ae5b3f6214d530c06926be0d1929fae44", "CLIENT_SECRET": "0416b0eefebaa6aa9f6a370d60426897a9ddc06006f4d5805ee6e2150d38b04f3a040545077b45e6f5943db5c8f1b8da252babc0f07a9eb0af850bcfb33ebf13a2"}, {"TimeValue": 1437055598, "SS1": "056574a7e420e12d021fd409dbd47d32726ad5ad57393e58bcd0d15de57f570d06ae67385f60ba8cf3759433b40fee8061b642d96278cd1591a8e0ae13916bf70cd7bf59384c143a857285223a4960e90b7e2791e26ed9befd27f2127f5305c811a7d7d2a7555d35fd753b1fb9a174735bfa340938ed98ba972e58aadc03186f", "SS2": "0d4ee55a339b9c0a85add759176b98602bf57d7836edf6df28310005f6e80e56215323575e7615cab46e9dff2ff72098be670b163a6f9ff3dc8515b31c672f5618d8a939787bfeb39db569787faef5e3e1792e190352759136af93db4bb2739212f44258de61dde2b8df04b2e5ab2db98be6299d4991bb1882967f55b77fdfaf", "DATE": 16658, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "0f7dbb851e530a8616f61832665520451d587f10abbf76e08964f979bb33c09007801f92d16ef15311d522e0452520f3ff8f248c78a3c44d592bf9814d5901610113d8df0aa243200485ea8ee03a840ba893df23e53e51f5764f75600894a75f1fb5eaeb4c3813fc461d3d7bd9637d804b63873b94ec000aedb70e33d03a1c0c", "SEC": "041201c0a6b5ac0ee1c4347decfcfa92e13e30e7b00fc3f70792f7b6c35829c261176ca6f9a7c18557c483f86a78d7299409a594fd99ae6673b1ee12e9b875b987", "TP2": "0419c0a64b59d29cbe9e3926a6c3caaf1148680375783304580bc1542dce77c20612084bc0d5cbbc1fe2773ef9cec758c4c991a3af02fc4de3f46596cd1afe88b0", "TP1": "0409448564b27e572c8e82b0a175e611dcc9bc2ec87d0783cf4e048033b107fa271685352838146783ecf77ea27f8e74bf03abff0781ac11720c8e99a56c2ccc8d", "CS1": "0410b0bb941225e8c3412cd9b9e9f8788297923fee95187178f37ab6457417f52a0a79a18d68b72d5de3f688ffe893991703dbd88bd273c4064c635dcb926b41bb", "CS2": "0402d8b1a1bd8a767d350fdb0583186a8e89928fc7ebbb333443fbce8fcc53335618f7171ecdcc4962c30378daf8ef5319af8f5e8f4e6d5b66ee5341c01a1902d8", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04068218b3f87f74447b65c8004c9774214b18c52883440bba190e63720f2f8bd506e65a78f165630ec2718b608d793a92a2dd6678d3ec603c61bfe5fb6de18cf2", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040e20517b19f17f2df5153b423a870fae7a7fbec0396e9b6a3472c05f48ec81440c8ab0a28979ab64d285838f262e283183ac0b80a1897fd5bc0764d491a500d7", "U": "04014b07dc82d822bcffdf2e0713546a973e1a8b63e3b612bcaf81d9534ec93aab1f313c78fce789c76600dbe08aac9b10020b69a9989f7e367bc3825f77885250", "SERVER_OUTPUT": 0, "Y": "162c68c72dda9cddbf911d256e8706bd714f9c4e1ad4d036863b6c5272919820", "X": "107112ba7b750d8ad7da882601b92ccb4fb84b099885c589bccd3734ecab4120", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 226, "UT": "040ec0bfbeb72bb4a1c5b5da4377ff74b19e3bf1122664e4136cfb95a24ae6917d1a6dbb073738a10934e4f8ef1495957aeaa1e587a76299d1efc7873f8a15fea7", "MS2": "075e8f47ce2b51bd7ccb8280e5b1479ed839d5710d996cee4c7e6c82c1b726e5", "MS1": "10735e3953dd0ca1f58a226be677e916ab1a7e825e6fab3e56832b99f3f4315e", "CLIENT_SECRET": "040507cfadbf55bc671ffed1b37968d786cbc5646d435bf4ca67d215212cfcf80722fddadb6fc94f050bf856bb830d7ca3f97bfb50142c2fa2b77a548cffd05ee4"}, {"TimeValue": 1437055598, "SS1": "01cbf0e1c0b3bfb3b5e5b0d330d5f608c5bd61841c8c0e62f008ac9c45a3e4b612a04670f7fff4b5c48f7c6178c537c76a7d9063010b8eb471789670f8c962dc1e051f2ae04b59de6295d4386eeed7c190b423035ce61288d281f99c53924cad1bd4da0535153a4fc777439f7818cb82e41d3f4bdc8d552022b21ed0bbfedf51", "SS2": "1012651ce6b6f71a64884be5cba5cf256417f28add68818d70d9ee1f2d0d40ac1cc0ffa96fff26308dc9fb6257deeb037107d6afc9cc86707caf7da15060d9400efe9203595808034b492f38f7aada4b34496b55eb53e69a38b590c52df674bc1bf508acac077ef2a33199faa0ae4cfbf5d7f00b47c2e950e90d3da15983608a", "DATE": 16659, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "1d7ccd8125e6c89ad0f36bc2fafb03e02d8d200f57ff90cc909cee244d60adab07716ac0ecda6fdc56ab3039cc8f24d06a2e6ad79559b2f2ac8c2898ad50ce9d2201579a58e32347b4f1eb2532f9c9e9d3891ad3938030b6411cc53191e9065e111a1168448098578144a8c2c261b268b06f0e14dede05d3606c87e835261020", "SEC": "0400a8b5224d0fe1511fe3ff38c733c79ad09c0b188879adf741347517cb4170980692fed17a3a8cf3f121f54e241d1cd9d898f4e192dcaecce19d6ca61b61b391", "TP2": "041a32a5ac6a285978715d730dd7551e8a36f8598d80d521dda33651c8c46d3bb81e724c62f1f0e99c08ff4ce1a068633080ac77f25d90154dc19cba810cb80f86", "TP1": "0411759afaf2ace70c3bb96260f9085b71eb017edceac94df5ba19b41de63b0bea01d1cbc2fd829e5a248173df810afce22b85ca6d4fad8dc05ffee97f373bee33", "CS1": "040217999a4675e735513fa131e9a6ca48c3eeb2a01945d1b77f933ec70a9f5b680d6bc60913431d5fb0424dc82d15087f9221c829d815b83c45fd4625acca148d", "CS2": "0418d158119ddd1c6a20a4ff0511aeb72f53b8bf070523c5c4d54301752553135d0386f24b6d598068a23532214ddfa14530fa01bebebd259c77fbe4ade5fbfafd", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04143de1ae0bed8c96e003598cd708ee0f2751aa2a6658fb462e3e50959612d5a105a9029a40856c0661306f84a7d3e5962dee3c138c79f687824aab2ff7de499d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0421b55a76582dfc2962a1f0322c83b6653afb803056fcce3bc47618f80acf65ee14ebeef662b6c4faf75d34f55942beb3e1b11b193438759143c5e32052971905", "U": "04188926462754474f9fd654df0c697157ecb9f3d708f7d9ed7696fcf81396724b23628f8dec3429efc1b232b6f1d6462172245843b3f9eb30641a44edb84936ec", "SERVER_OUTPUT": 0, "Y": "0d42c21b3271d571afebbadd8c454ad36d72158a187771ee65ad3e858de10b78", "X": "0ae05b22ed4479ae9c22008f85a7d325640d49a8f49c737e0600b653dc25340d", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 227, "UT": "04157dabf15c40fe1c79e4b3190768d7f6e81582ec24d6ad15405f96b2000cc6120ee0fbf2b6b5feb78c9df2dd1d411364d820a2d1013779cdcbab0fcd6fc9f1fd", "MS2": "08cc4c80d01b719b43d133298ff9b6af0bd26496fbb4269bb322c162aba0c247", "MS1": "1f7ebf22417e823044e3a5420a52585316881d8519b3a4d82b459dff8e3026e2", "CLIENT_SECRET": "04232ec0b7950947b2343a8e001d45735f7cf9592c1ea5e5f9b1e4a484e4eb9d291f0609edcdedbbf6354f153db8226fedb33cd2cfe760b6eaf8e82f342f79ab04"}, {"TimeValue": 1437055598, "SS1": "061199f905f149fe6c3e85c6bd0fab33ae9031a19aa8d62af7f6cf5100c720da1efc32b573cdf6cbd924becf83ee36fc4806f5ac62876f2e7fd91abe51a8dc55026a8b12a6609ca13188a7649ec08e2e8faff8081c562e62daab7f49a96d888202250b73de7c51e9d02a8df3d3666978c19b6991c7cdad7318855065263075c4", "SS2": "1ec0651831e5f5e1e6d4bda9a7f255698d5f59f0ee12647c27e5e4f61523861902151d32b1f6166d08049f1849e7b040f38b8e4fa26ddd055bb7a86b4a9162ca06a4ac0648375f59bb288d1482df0b14ad4c4a915203557a5185b1f2b2ea52971b53241a11197aa20f53bf5465f620fa1c3be429adeffe6005a88ebdacddcd21", "DATE": 16660, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "046db33937a6c489d264929a59ca3380c415b5b57da60c18953b50ad2d18866e1baf8827e3cfdd143504ff1b037203e9a06d60e96563728be00af1f4bb31106800328a1cf0b709750af6daf01a0b5e6508d002860c95c6c9b8229a3e285670de085d0636feebe185cc349955046970970769267b601ca4c6326f358cd061107d", "SEC": "04175c9703363437d860437a2302fd4704e826edd94fa52e083d779eafad5d15c5205dbcac4e5b623699999e7dd067ab7748a28417507f63544146ba68f87bfb52", "TP2": "040a0bdbd62838913a448e0b50fcea2212a35ed0a05970daae69901e7eb840df85106edf8dba86021e145646359b84f5770971f66bf4eac0fe569ea250cf3004ce", "TP1": "041d6b754d6e5175cc0789c1daeb784feba1c6bbf4ccccd630f61bedbd5a3c7fb20af506ab8c6d042b4160f8a07670c4545e2c5ae99022db6b1b31de3e9367b27a", "CS1": "040b4ca17b4c1fc60cb07a9e07c90827a0dc6c12fb98b1f37a4231ddb6e202ec9505e8de61b2c9094b69b255c1cfb6d25572cd009d099205acae86636936db073f", "CS2": "0414282da9dde7f62ac3e38e83e1d3ef420181d405778500481344ac7be37417361ec25ebb344acc6b04b36b39667fdb06315160710b0e4e3318c86371ab0230db", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "041d6c6951251033498f68884bb1defd112feb24b210c0d8a18398402b57117e5515f423c89d02fa893ed175b236cbe38620b986023a7f858b5e3e18b5b944d928", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0412f25ca56c332b977b1000cfe1248b3462e84fbba15c93c0b6afec7e6c957570142efc7fe7116a04f15484f18ed208cc8b8872900d1ea9394b7d3b36d5c85c9d", "U": "041127a1298d56bb7e9fe6b03f05a29d60630915b5b34a4ffd63bb77365e5a644d092c318e77ae3ff8f0b06316331659cb22d7e2d7f388bcd1b334bded0b0b0165", "SERVER_OUTPUT": 0, "Y": "009a9639cd8ad8cb728dcc8aa450c80f5715b1532f92f0548c2ca1d7140a130a", "X": "062b0a097fb7a27a655247cab63dbeffab71be5fb02d9a296ac8a8dff4a9e45c", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 228, "UT": "0413e5479517f828a968c71a6d77fd9ab7e2b62a92f87ec31802941e093b82f3ae0c420c56589efdb159de2ec69df312315339f73de72c2a35ee725a9f268f4323", "MS2": "12dbbf928876546366e7d23439dc2ec0b9cae8eac6d5e66ad6d320c65594d525", "MS1": "017d062a983ac2d519f3899a4e5cec6be252927a65ef24bc04405c99f67bf6dd", "CLIENT_SECRET": "040e113bed15a1d417735f4d202955be215ec8f7f8224eac24bc1592f7ea1fc56d19cdd5391fc1c3ff82c1722b4b931842f78406e29d2324d29051444c9a9927d9"}, {"TimeValue": 1437055598, "SS1": "1a15118ba946d2161dc0b2ab44786f4bc62421a3e0e08e676e586e1eb326a4e21d9291cc138526ab5a035d51fe7eb7a719a9450e7638dee613cca2e4e2985fe12343fa2670f35a86df8df157c4d5060bfb822d6065fad9075fef8838620e314a16a4a8868d7d2e9096a45e72b149e5caac046da028124573f77722cc0dd619ca", "SS2": "02f1781807e575b8828f3e57b528b2370c27ea65c5c45b64b25b52db35e444cb21cecf83ce045dc468df798ae9b0314c98fae2bce9ed78d529d468fa92c99f821cfb4771f865fd7b037313fb76233c17f1e4905409524716adc93389b8b7803d01b1929cf42f727e971615106f5e874a1c2f8a576f6779f5f8dca1b15b5009a2", "DATE": 16661, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "161597b173f38cd54b45ae78857696c35ac0cc22d1d959cd795809e37def5ee82054f735388f891bed8658e7c796480d1d62b1e230b0966665a85ca9970c5e940f33cb5e10287b24ddc747e86333a45006def37becf4189c3388e75d5dadb0b103769194eb4925fb47cd62a6612cb2ed6cbb8f317d5e83cc2ef6e14d2559bfe6", "SEC": "0421b2ee8de964e28119e0c044a9623a5a9ffc08ae429eb3e25f382a9a39b2df12142f453f8460e138983e8b17f4df7e40c149a15c309be3b5215bbebae3b09889", "TP2": "040fb971118fa51c28b28764263daaf22b99e9c785ca772964419fa585ce2f150421aa4ea45664795b5e2c419c4cac3dcc57992db9049780694c8d556924879454", "TP1": "041e05a62120e9397de6e6961fc76641c4c2fd6f569048d83f9d2d71e07f70f1e60c253f925221cde3affd7243824048500741e5ce97787a01226be5825c47cadb", "CS1": "04105184b739883e6b282fbdcd747f4501f45436a2c952808042a78dd385e3a9e500dc216ac6e7e6921a49054946602bb41b2678ee86b5c0e20f7aaf198d83044b", "CS2": "04173df305867245cb91a030a8d9e078b87d74414665b5bd56446def815b0ec64223f96fe9ca2b56139a3ad635e0d0e24c13234667c4a6625609b9a14bd8b623c8", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "042257bced1f3be627630658029e303f5397f7a206f084e1ba13fec349d6a37dc2136e45d9034671275b7f76e87caaad3ca8a4442149e4c7e1b8ec6a2f60d66dd7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "041c3ec0a1f27ef852fd851a1b3d93760ef4efd10535864fad45345d6c4c4dab090fbf59966c7eeac7cf43b3b77a1738977d9eadcd4e3e95edf1f52bd3891f55fd", "U": "041af2380d49b6db11c60227d009322505bb101a5e83b42e8c022a1461ce122603070b9786beb9f12a7c2577e756a29ebdf0745ddff9891b6c6c5c634f8092d4a0", "SERVER_OUTPUT": 0, "Y": "0a113d76bd55b3a6a4ae43f42cd6d3a6513791466af9d71f7ae7fd26e7c0b1b6", "X": "15fa2ca89ddab0ae8f2d2fc755d1dc0b81aba58d0f2b9042d6e8a62ba7bcfb06", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 229, "UT": "0404ae93e5012000d82a5c3734a0ab2b7a50bcf6a94feacc94f16c28eb08117d3005a6e640f330cd70d0c0dc46b912e69b35bbfa991d4508a5e0238d4c5ba480a1", "MS2": "0f1ac0084612f2cab1cfd2f5d25867bb933cb7015185688d42599210f368d7a5", "MS1": "216a4d7a43e4da280196fcc69e8867e8a0ff56062b34d15d44914c1567f5e744", "CLIENT_SECRET": "040775430f1e90eac4c0e3f7783ff6e0f1fe990007fd688cd8fea6c739374ba9272272dab74e5a92da628e7e5865e5a39d6f13d9b9463b418c14a3f0991e74fa4e"}, {"TimeValue": 1437055598, "SS1": "153b12e6365ea4ecb24e969cb533cd45db618c0bfd2509898e91d33c8ec81d9e05d6ad419e0e42947c85a75ea076e3087ee993c085828fdb1479c07acde9297b1a66b4bbca8b05fe4a0f6297b88f8f4b1d51d1c4378699f1c3720550545455320e1663a0fac019eaa39c966222ac234fe3cdca333dac098afc98b0a9cbbc56a7", "SS2": "077e058d40be0e5393411e870a04e12fcc0f11162087c2b70d206f7a0e2f52f00b208ebfb9806477e35aabc7dc010a0e4fd63fa17b193ab1c5cfabe94396ce76085fef2ce3d1e10a9e3c309a8c87e9b1c48f05dd8d057e23a249782adae7a569052ad690f4757994a4dd20da4df25fe67cc55f4d44e67e61767bc22126de431b", "DATE": 16662, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "2351aab3372987731ae807903bc767320e9f2ef01f198a4da6fef0df8916ce6b0420c814e575cd7c45653f386c0dc3f87d58fee5911df508aaebf4f7f588f0321b485f2e38bbb3e36b1706c4d72e03a7e93da9c8a233d2cd600a2b2353598f211cec17255102a8a50810ed015ad1c7d91a9bc9ef8f75e8c43c17280c2856d7d4", "SEC": "040dc9ab92abc9cf3557f9763606ca6d9c701cf33a45b39c248d42972e86fa02b90d5a9eae9dee647e65ee61cb6f26698501d4e70f82d0a4ed8515b47ec7ca9a73", "TP2": "0407d95e0fc0de19aa7038b3f273b45eaeb17449f25e634904ac2417f9a8ec49c50ee6944fba2795f5182732e2b14992d9e46e404713cfdd690b9e66817b68d69b", "TP1": "0406a0121fd0b1dfe7a94b6c9a31da60deb5da027586ebc0522440d4e0580177a8229c8dce3f2979a090757282353692c3794e62b1a561e50de18520cf48c2da6e", "CS1": "04164b1050496ad310c1f4ce6f10570efbe005d84a01126eb9661f8cfe9fbc6e3a09f8ec72336739dc4f13d0a5ac351889b67cba9fa7dd4240beeb81b3413a74a8", "CS2": "0400d9b817c6fd1a2bc2d6ed6a79ae19e41bcc0de8d6b63da21cdf7c077a1d5e2f0bb2a752ef5c52929e2e86a5a5115baca82a51be03babf676fee6db944b9347b", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04119af10569ac24a86ecf5469f12dd8b2a03d10deac3adedd520beb679a0e27781559ccff6180c08e1236e60a957fe4376888ab2b48c9177fae8702d3e25464ab", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "042043247c7863346cf7e54480e37cdbb2218e0b5ec0032c0ca9a3576a7cbe9e98011d55e646eed9ddd16f42122faeab78b3075db2f28b67e7530a3241008958a6", "U": "0403de3fee61e81a28208e6da505279cd198b52511405ae44785a82d742671b6a51f7a79e03d6289613d557776cf331dcd648996d99e1d970273ed5721bc2374fa", "SERVER_OUTPUT": 0, "Y": "00d16fb1ac081ef4402fa5b140bda9f622f1912b30e1785bf7a0a31e56b4d3b5", "X": "1a1ddd05535e578ca05773ae405bd4ceec9b3ce6b361de47eba7b460105e933a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 230, "UT": "041b871e47b75519b375dc71f76856c6b405964aa6b9385a27074b704f8914bc7c0e80a98799fcd9a005ae92f735745021a3ac30afc5bce1ac369e0ac0374ad9b0", "MS2": "1f11226fc7621f0fb4e0197444f566fb3fea2427c211ad9ec3c39c685c66b12c", "MS1": "194f3ac28e84a02422f8a020fbd6d4140a7a04f91d670c92b82a3449602524f7", "CLIENT_SECRET": "040c22d4a53ef9c05032fee35c46e76a7da47697349bfa4d903291e277482311c500a619ef3a884d5fc79dbb2d6b13fc995902471a0087e7f53e56cbc21056bce8"}, {"TimeValue": 1437055598, "SS1": "14afe3e44ea9cacee6bd1f6cf6c80bc001a11965bac01f70317823f0fe643d4513c2f7ce8a3d8141e1ca3498b32ed343019fd1b6b4d6f8fe7884a92cbc86676c1b7a0e03db5a7a98024b0332d804b4542ffb1699b5637c867310261714cf198112582f4ef6cd6b3d1c140a8ba6b46b32f997d411ac9280586abf986c5dd15a3c", "SS2": "0136345a63aa430b78653887e43fa0b16bf68fdf40cf95eecaae1950de7d99e41329d4bfff3e32c896614a06f92d4145f996d3ae34f88379233245bce1f3419f21ad89a6223976d88c0a51dec9da0c13da7396c7158501cf3df8befa02126669209ddd7ae09f17f913761b8e85f2533e34d88434a3d9bac1dc0b6276db04dc50", "DATE": 16663, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "197039721a023ee6c15d2eea3b63a274d0d84ec6f8f454c7dcde303629ffb5e010300f14c2368bddd9025d63e98fa7d4a571adf49381d9164a96ad506539348a1fa169349d9d9907e270ae725b72b3a268705e0d8c22e13615db66d3462eeed01ba3291e5caf73eaf7460092dd28845690d57aed8d885d07935a00096398b73f", "SEC": "041c72827ceee0c1e58ffeded05fac2341f51605002fb0abffa7383e03885ebbaf18a3d161f498d1351bec861854a74a844f0c1084d230832d518b02b215f1fbc9", "TP2": "041d098f9d50611e0964bb59150f2d6ed45cbf5b3b418dfb3139935159740a98e51474ecd1b8da2badc5a2adfe3c9655bd0e8d3c9e721be32daa281ae54529c274", "TP1": "0403bd79f6386946dff468a947caf7caf9e3aa90e06680a7ee4eec54e213d7428011fb8b63e053de036496ebb543aeb4ec5297121e3f73a1a19068fc07b0307599", "CS1": "0403a5d65086814619e6517f21c393b763a4a4ae296f34ba476a71632b5bdac2f615dc12cc979ee82cf7a46e55e3629fb8d676027dcb29856b11344b8bd64698c2", "CS2": "04227b276785578489afe065a0306deac6bf35266c9c86494da369e9d7b91a980303f7f31cef674b56e517cc74a8618f4b11f019889d34416579be1ff9d58fc699", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "040a5d9b3c61ba36cecd98cc7127e2873688fe9c6fa361c5c90b907de689e0de0e217e9a7858a91dc0e855e9fe8787fda4ebd3bfdc057d8a8504b82f4e8332b40c", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0417b9db8e0c881d67aca8435ab8574568b648cc814bf827174f63f26503adc3df1894e8947ea972ce1fa03c95d580b301dafadccfc5a424d9ae774472fbf4f575", "U": "04215ab730bfa0ffda476edce89899ed6b6b9ec73522e21980ba593f8eaa89ca9a0165d6365d3b2cd4612fbf22212718e4ee3a337f2d4a0f4ffa2f56693411c92e", "SERVER_OUTPUT": 0, "Y": "148b7cfab7cee7d047681231d2a1df3b356c2e2c749e5f16f2dd5d5bee1366e9", "X": "18b053ec571854cab5916d9c11538eeeb8d089c8d1b639ffa50d0bb4a986176d", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 231, "UT": "04193f9184f5351515c4419efc6e078cb1d73d728c001d29b8c679bc8c4587ef89010419f4368d71f320aef4db19df67bde7a72b6d40296953875ac00a26cfcbef", "MS2": "22343eba37ad77d595423a756b14dabe82a75cb84ee53635c8cb9e89b940e408", "MS1": "04b655441fef8ba27595109d2c863a9a13fcfad1b2ae6ba7b3d9bf17b97a7779", "CLIENT_SECRET": "041e393424f7c79d13dd4afd410afe1c5401bb7a330cdf525012c9479c3ca40c720188679196f4296c1846758b9b97719ba3e6dbbdc1934dfdd2c14356d675f480"}, {"TimeValue": 1437055598, "SS1": "16d6863ca482786a6af208c8b3d257e277e592c6c3bb21be4554cef498e4e4db056276c7e68358731e73ff9e3f73973feff5e5dbc451027921f4f9e31e7f5cf7055c873af125231e4072242f15fdabbf0ef1fdc38742cbb4b8eea60afc712049232a428d0a1403f5b6e3851234ec306a1c4114d2b7e155ec71a59d895ee1c692", "SS2": "0011a0ed452609c8013b20cfa6be5a47029785944ddea25c7e7deae612df18ad1afc782b9d68502fc1363e44d8a8a1eedff11ef613d48c12977f2f5f18e291cc07c181037556a494dfb8ab9a1733529cc468a79f49c57e287f88b92de34b57fc1b51754cb613968b664454868e2a333cb40c214552461e9acb7e46bc229ed097", "DATE": 16664, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "0b2f3ee93627d3c18b01295f30a6476058ade925462933370ea397be406fac391e897abf75c91514bd17784abf814361f72cd76a163828faade716e7c264b1020da8811e25d8aa19ab323b55e63f08d6e5a37c3149425577d51c4c281d1ef9b405ed599a3c7c6533ea34654f1d5b796206f43c09e008bdf1ee351dc3798e6801", "SEC": "0411ce1a2638f6b6ec1dbf82420130761e6609f697d5177a64d8b518f30936823423c10c1400107d33b1b17de0a25e7e07edcd18bff57a6ac14b9c7ef087f541ba", "TP2": "04120b107a742ac340487ae6af6ae42ebefb65296e83a28398659f60b76e10c6ee002535daf7ac0ab88f43038784f83f424985fd76c44a691dbe02dd3e94109c4c", "TP1": "0406d4481c65ddb0614959f7cabd48030e8a3252453986c656a25eaf456b41c6dc05d50e955eb5afc6226baa640872930016d3a59917cfb92625f985a14e41af6c", "CS1": "041f7f5468aa0b0bd039d1e773e875d20fc44af3ba043e240a2f8543a3282fd67703553611c52217a10d14ee6b3398631fd11985be0c04a60bec29233e33b26d9c", "CS2": "0415b06a8bd6290f8c01de3da9664b6b1cafcc5afe7562a2da470191cdb94ecacc0d00dbd7f6e78a061e21e132d6a347047a58d5a8d5c8430a6e548c9d0d73d1c7", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04152a6da07d28b2911c497f5d023558286cb5f9731c5f3954b4ae02605de5dc121e3822310b7936a3074602fab91c57c3aabe463d0f6a61976560849aaa48f34e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0418e02904f0aec182bc04f979ef2781380eccb9b610806750942f84e0fbe25be523d700a4fe8e0a4c9542ae7558b10ae018009e7317ee6ed4c07a079f1a5b68e7", "U": "0401fd7d10f1be8501319392086a7b29df9e6d36ac24ed9e857f978a4d8f67f77112d37ea412e685de2f5cf1c9d35b4b27ea8b776404689118e89dcb181bf35e38", "SERVER_OUTPUT": 0, "Y": "140adb04adf666aeeaac589210267fba0f9818db96bd59edb0ee0c732d0e58d5", "X": "0ae6ed0e8639cf37e71e31a508baa4ecb369e4dd070c794c0a6cda7464110358", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 232, "UT": "040e66ad8c3724b0a2d5f6c5f6388ef8a392b9eb798985fca3428e604fc46ccda41320a183c52385eb7974f1914035f18a497e6777e0c9a3740d00c48b66105f16", "MS2": "0027ecba05f6d5fdde8f52a20425b2140637843d247012a36215d43be8500616", "MS1": "1be3092c5e4d0425eb96bf91323721afd5731e2fabcdee00981b03d9472de23f", "CLIENT_SECRET": "04106e1ddf5eb583f7f63c3be9fcc182e5ad4bef6c4abfd6f0ddd765c41cf14375198423112512733622d329c8de35bd603c3c07f7bf86a3114e1812935a27e994"}, {"TimeValue": 1437055598, "SS1": "123221dac36d47e028836d859e5df2d9fe6b3b14d5906915c4f77346e1394caf1fd9b16f9e4a4fe7e155a0f4442ddd908a0a5999053b73e386fb26982aad7a550a91f8887783c3985fc09b3bef9b6b31231ea5bcda31f7be2020ef2c5415e92f1724eac815c66ec2910f9d6a4dc6f29219fa186773fda85a8023900857d9b1d3", "SS2": "1d96e969ceef5f00601967da0e6b87f0089e2d30d427c94306ceac9a3af1a8b317f96591d952e00e57477933b68f9475f7e4980902e7a2c4eb5749cac4da0d96039fc44753dd478d1517584d39717cc0250132d7992f13ae703ecc00b967664c146f2a4387f71aa6ec3e0e18541ef66266fa75194faa11b4df7ba87ece6373a6", "DATE": 16665, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "09f84f7896e6eecfd81c7d20bc535f468e25041beb9f01e2b1116e92cf58874b23be686becc34347eded60a9648cfba37c36afa3b062c1aa34b7a013fcf042f11446ecb9bcc95ce4b717c3ac4b16eba493ea1556eeb27a8a10e058fb4ffb4ce10fb8ddd6044e36950203447ac7a846d0c108de4d1fb7fc4814b8106e3cd2e1e2", "SEC": "0415d996e13416eda19f62c6fe3cd7e306a5be1c428bd5a33b886e33462cca8f840071e775035fe124b30ce15cdd1e1b59b1bceed84c672e48984ddcea26ad0116", "TP2": "040e85aed6630f277806bb00d867fc769e4d9d91b52040608e5cf3ca10f49689ab0eb35e6f1d1d3c461b42ec2f75ac7bee4d6d4fbeb870b20ff6fa1d0746db0c06", "TP1": "040e9910cfac682674e413bf4fc104df3d7c39117b53c8848278995903007de4f21a82a742c818a8e7b5a7f8ae528c370a6e97fd7d84cb34259a8583a73672d43e", "CS1": "0411a66d52bb3114469e33986aaa42aca991e78cc07a018d04fec71048b9fac8c40cc75402b38e64fe662949a4bee68948eb638345edfcd5492a883c7a2b5aa23c", "CS2": "041c0bf19cf2e97b0f123ff1662cc21185deb1426da3726bc037164d840824c7441f2cc92ad6d363561fef76044ce56e3c06ebc5467721e5b9f0cc2dca0c3d9af7", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04101486831de17317552a2ad7b6b7c3dcc89c8ec8552c68baaa539e2075e66d660de2d6f62f13161e06014dc7ac356ce60e94ddc12c4431da620591e567a77e7d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "042032ffc4e82ac0b4a0fcb469944b6c029b68a716c8ff8258477dc8e3fb4523bb18420aa4ce467ee40969073d633b91991acf9be6466222ed8ea27d4749dfaab6", "U": "0409c6e439e26d89f7f06eb77a1c7c06aef367c6114e240984547d54c13204f69d05af8af5856ba3356be47b8e7237cc1b835bf843661cb7cfb9a62bc0c8a92f1b", "SERVER_OUTPUT": 0, "Y": "188d4f5156de9a4c89508559fee085f90d0b25c20176433a0d9a490a34f832c8", "X": "1bf059e150d85229eda664e675dec6f13ffee255f93cf47084521981158ae563", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 233, "UT": "0409be31b172757d358e1428bb9c9ffbeeb97ef9edb99e1b6ef7778c1a34d906481cbfa9a12d596e06b8f361b64e2ff6e47f0c8626a72ccbfa662dd4b793e96474", "MS2": "070ba20b8a2f4cfca56232b70c3bb4bdc0fe75dae156e8f94686ceeddda8c374", "MS1": "10502633a0beefb6f248a71840171c45b7a5f311f840caae35932b0bd4f49619", "CLIENT_SECRET": "04029bab8b8ace02fb8aa884795f6630e00b24b6d8da818ed17a1164efcade302b1fd0bdb9acff59d94b4d9f6b253de570184407cb19713ec1b9c8c056c940c49e"}, {"TimeValue": 1437055598, "SS1": "19e160f21806e6cd66ffc0676b8bdbc42d2f544f59ffe3f9bfbb6425b78747df08c9a011e5fbd8f12f476ec075121c4e2049200c1482de10ee8afad3532f78471b055981e274f5a2d1da2a38d566962a6d75b75e065e6f23ee886fa8825907541f0b32d4d943192a09500a874efccee39c8fbc3f7605d47ca9962acad59f4607", "SS2": "0e26674fb15bafd8699916e461947750cdf860effd8b7a713160aadc38d9785a0105a48837cf73f37fe7fab63b26228d5ac82a9e6c67495118bf557673338d4207cbc9a331f3161998e3300c00353a5927a7c3ffe7b44c727e94dd9f59d3843b19fbfc173ef9b8f84af3ed5814f4e173d2818e7f815e6810a4eacb263c741e4a", "DATE": 16666, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "0e78c55b15af18efa63b76b596bc131f357d7607cd246cf5048ee7b42d28d10119068709e37b1e8925e4f21c71c6840ae05bf5e5267c59628ebd407b32b3becf16fc63a4744592edd60be21cb862998902df1a5e42ca3b5a923bd6f43174d8030b4dbb1aa94e82e4879cff3b6abf5b5a7ab0f0673d2fdbd5387e5f6a61779331", "SEC": "040558ffea65a35780c801858cb5f183f52458d8b249938ae2e29d9d22e119670a103a3d60c1bf1e5c07246aafd01a2dc9c4d19d38a46db267c92c3f4886b39602", "TP2": "0403a781b10611d59901d2dcf1a7df51deb85233ca45b52f0911a0de1204af86de175acf2d08b64e8c6564e5c1a580875cc5b021eb399e0a02b49829448e2ecc45", "TP1": "040d61a90c0104f712528fb6a93e4c39db8f3d1fde97cfecb4890d6fb8dfc50f801db7ed09c903d093f5f36568058d227c25001ad684dfa1ed715b7a7d20bba0e2", "CS1": "0420f72ff4205732bf1dfec6ffd7b49d774fec1671301c1be074b989d6ad612c7e168451fa198cd944de349a145c8f3894ab3a2128cb171650fd445a009d3acac0", "CS2": "0419d7025502178f7a16822c64535d6e63479e2d309c99cc4d5f02d79fe35f04ba140510e13d4db289d6feef84eeac4f637e04627d47ab4c06e6ca33336b1b37ce", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04122c4818faaabe174e5657dddb43f0b5f7ac7c843dc6df6c03c9684d50e8c07a0909d9a08c25a51990990bbfe4145975571749f5fb63881a83d0d36b7f4eb24f", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "041446db800132883f475823fd7384e52db9f736ba3e45ca93a667fd2f87ab8e9b13f5656754ffca6f106570263161a1a7940b135ebabb71e57d61ed1d60784684", "U": "0410073330dc8dcced985e5751bb7341dd910d172cc5f7ff0bdce377230d2262f801220607f06ac6bc2c3a2d9a4de008e5a75a40ab9e10b167cec064c7e6972514", "SERVER_OUTPUT": 0, "Y": "21342eed5aaf1177112417d37dd1321ad297e892f80767ea36fb751ec6bdce4f", "X": "0e39326e034bf2ed24de45925417bfb1a5ae3b23a5d7aa667726873e4fefe5cb", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 234, "UT": "040b01b0606b0beb940c6ac9bed3394ad0a0888b408b372386512096223f99aa6020a990a32d67c01860ec66d861bf377ef2de99a3c847a0ae9742a490fae5ba13", "MS2": "114b22eb07d78825568100ef8cff3d2dee8be4cc5fa604d44198f140a1d646d4", "MS1": "090fe78cc965cbc854096237c63a78e55309f9ca39e994bfcd038df6928b5b97", "CLIENT_SECRET": "040e5d4e5dff5a7e26527b7bd5b9ee3ffb5cf17ab4e758223ebb76a218ba7ad2140e6408c7894a2643635f8138fc0465f9736e4d5c70cf10651f8b1ba4eaa3f9b4"}, {"TimeValue": 1437055598, "SS1": "012ed60a1415934f305430b405c9f9aead7983a9332e581491a9225690fe3684095632802b8b35f768885b6cb7681816056369bb4b8ece3138aaf49d46d8519b05f36a93cf51baa7444a77967dfb6d5a8e7d49c4e816efebd648dbb2d718aa841d04e9f0429ccd1074a33b711af173828056cc44b2244ed841e2c2fa723a6f5d", "SS2": "107156ab21fc92a5f9c43c919a8affb6fa15ede4f0fb81d41cd8a0b08eb85ecc0ac14a1419c6b36eb28b3c60750a52ac343067ca8c29c1904b5cd63a946f8f0f137e675c911252d6ec365a38097b606e0fb7abaca6eb8a0bea436cd776adee630430b1754185b620b36f6b52d4b3065dbb81c9feb8f1633e88c1f6d80158be02", "DATE": 16667, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "1c314316d3e059ae676c01191012365dc2850fc59e318ae8f229705068e83c9c1fb9451a6a1673c25caf746c4c9b26184d2823b9d0683b4aba1443b08a3065ba218482e254abb6d5d9a8e5ef53fdf80187b735c678691e4a0f4f69ee6019e7d409ba8cd5e329ef13dd826490b8124838526189a259a0e64879f6a9706d47854f", "SEC": "040ad74cd1247a99f24428d02d5e6725443bfdbc2d2be2780696c36f913634b58e0959e6839ba999e3975636922d6c06224deda57f5cf665c81d52ec22f0d28a54", "TP2": "040cf133a15147b2404b8db187f2d394a08a9f15d37ddc9894a8dde979344a00ec0d5e7b0c84c76e592304e4596a7ef70dcd493ed14a0438d34817191a8f36db8f", "TP1": "040ab18a9b4cea26f4fa24d992baf055e662517ed15ce599e483eb469fb314245c15c4031ff93b367beadf55fda2adec75695f164364ec669262943f0e3fb88dd4", "CS1": "0402fb46731e85ff94eff6c5982235f2acf5860b16e4a755f65df9a6b6500d12450ed791cabd0943b026b7c1fb60a067f3c64abb0e26441a0a9b1a3fff0c5ce077", "CS2": "0422e5ef6534818727c1bdd1371105de5103c3c4194f73d73aee51974d4c1deecd1143ed59d2f621a9b771557745732e0811ecaab62e089343f6d180ae01b606f0", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04022e147c08e81eff7178a550e09ee757f98d6cc24299362c942363cea0cd5ef51406858985eab73165c85ffee5945ce97412257fb0a404598d0f7b8ff39bcc09", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040043aed7c9df208c7ef9b2a0c6eb0d92bbb2aad5bf4b4c28d4556cf045d1125c17bdf33f94ee35f3ed4899ab476fd227f8071573c2925b66a144d4a21aaf8e6d", "U": "040db9b9c56b162cd0dd82b39fcad77f782679b4bd01ea5a32c11a8bccd0ccb09c22e6615099a90e935fc021ecd514c36d5f36186019f83c52e7102ad1b951a610", "SERVER_OUTPUT": 0, "Y": "00a09c8c7f2cc0ce9ca6290b7f52abc5ee3b1995d744324c57a45817d15c35bd", "X": "0973546109e2efedbaf65b28b5085b01c58a6489003eaa9bf3abd060d3fd5344", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 235, "UT": "04136648209231dff0f3d1aa46abb06ba7703b6ec76e1582fafc5a9c92d0a296ac126cd18b7b1786fbea615fc437640cc5ff9478058f860c67e56bd78354ac3e3f", "MS2": "22a2981dee712bee4754862c451021c4a95eaedfbae24d12a046bf0e66586a97", "MS1": "1626bb9782598371706a94786760db73025cc5536d4aea55877c1e5e1a9b3877", "CLIENT_SECRET": "04071e6b202439c5a15a812411cfae931238b14156be36517d11628351d0238251160e0592dcabb756c07c066f3e6a16eb485f5831d2bf6c2bbc82e98a21ee9ffa"}, {"TimeValue": 1437055598, "SS1": "1f13adcdc5bdb6395581b416e5f0182d5adea77df8760da54e005d8ac688910f2160124dddf994ab3d8927da0db8e3d866a1024c712e0b48e3980a0964efbe621336c843ec966c1bf6adc5b8ec47a2bda4b8f1053f7f40055031bf8e0e92dccd15a6aba3e1e8aa9d2a88f750ebeea021bb5aaf0a41812855a0f782ef779d0e70", "SS2": "20406742f08d25b12893d141ed7867f22f23b2829e32ccbf73b79ad0e684bc520438b81e97e37cd81c3de02a0f9a9e8fdde18b36477eb1ab2cd7b2e8de653ebc1fa3266e5ab4c553e34bc26a066621b3cf280386099dda937dea76a2f7d768f403c2a2da71c48d3408a9c498d9a1ad6bad38f3a38ef9ef4f2c8ba7d462c491e7", "DATE": 16668, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "020fc336441402d419e75ef7a3ea2c54ad0ed5b3b47d7ab897b71c542d47163c2146ac62409f85cb020ca4c0747f202abab28c63ed8748e87f7fb8ffb6483f9d0f40bd9051f68b7509f62c80c1e8f449f1708eb05e0973f65fe9f8487f1cee720fbc53e5a02802e0ff39525254163ea4eb5c59334c1fc253852ce10679be3d26", "SEC": "041a47b9a0e776f1af1e27db37adc04e7e7cf76db9a04ca3060c3d1ff1c8e8bf3c1d2282a447fe5ea269b7f1e1b3dabd686794c41f84e1fbc64df5eb3c62537d6e", "TP2": "040308085708eb184bd0a4f9f993865a0fc4380d300fb642370b1ed62e54384fe6056be338e0def7550b5c40297ec79ab914230e0b9d4039435db3234c5ee6b1d5", "TP1": "041a35d96dab0708c6d99326fea9ec3a78de7b2aa724354931a945d798153180352001bba0fb8f3faed2bc6fc71b926cabff1343816fa83b39f2b7fe547a93d15e", "CS1": "0416fd59312f1b59a38911615490be7d8357b256fa33185f12cfd402ef78cbef1c00739e74704fcd405999c063c064899d90749cdf86c8ce78c87c65524a2aedf5", "CS2": "04074dfd0a3a094a3878f3a4a320794fd9e9da3322bcfbec72eb80f071e858321d182f551b30e73b357cda591ab0a7f6d81dd924d8eb22b6d26a8cc1c2f2d9c733", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0410159ae50de7ea3c9920b8a7ce6119f0d97a153573d5b4fc51be16674d8bf5e01d5cd077cc3dcaa9143ab84b3a4c287d5bdd8eb75629e1619af8b3c664fe9fb6", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0416cad56937c560e746397c987fd87596b32e659bf7ff82c22cc87d90cf4480231b093e14a082ccf81ea3d9f98c6c4eead7128808c884cd255392b00dfa15a5b5", "U": "0421f0e024ca1503a064ce9afae1c1513e64c76ecd6e9be72779db648bfa90344c117fb144195349deec71fb1e8718abbe4f296a2f156b0834784e69db71b522cb", "SERVER_OUTPUT": 0, "Y": "0dd341097114ea99a9ee03ba19ae1f58af30efab67a8a3cc79e10bff30127f59", "X": "06195bb6717ec3a9aa7aa682b5b83f694c63202fa5a28eda150130601ff9df98", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 236, "UT": "0421248c0c2989038a04bfdfcda32d28315a45b07db84c0a42f551783f001869a81ac3f82a8b1842177396677242268b09c634c007edbca366b745bfd03ca1bcae", "MS2": "203062cb263455f49a3a67f93c01b3955d8f7603993b2efd5f50b9c0e7dddbc9", "MS1": "07faa2684953ebd79904a7f271d424cc84501a507c18aa4a72ed762fbde79df0", "CLIENT_SECRET": "040eca2bdf861f4954f6bfc1ffc2567a58f38e43f3c40bced5479df732725162490e35e0b991d462e10c36f24d0f9ade763d94af3e15057b69edaf5a4d7a36c322"}, {"TimeValue": 1437055598, "SS1": "0f25d78765d3cf9c0c1c35b2402c412f7b6913e16ab32a6ca997f454d14223701bac614aa78117c3e360411946054f9045d1be0dd68cc352979b3c74202be2f40ddf611945e7b59daa3155cb1437401b25496e598243bf6e2f51fa0e9d5c86af1d225745125d2baa909fca48d01e6b3eedbe9726aadf032cc54e196c5ccced0a", "SS2": "10ee4bd38ff6ea95e99c7b7e5fa467152b43b76bea2a5c4cb1333453d186e5fd1f2e8316a58f3d4e27be39cf13235df07210bbf1b34c9e2bf6064cae4a674b191b441366e8bd09152ec4c62cb6158ef5fc0ad3f4a58b793880074285c9b8d1c211eee153d959a567ae499bebcd12be6fa1da47c130d37fc37e8c09069c9184be", "DATE": 16669, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "14495ef8fdb5fd0e13868696ea14372e01d32b1eaf80deaa65683d46cbba26dd061fe8830477a786ac36a2d0e631bc3033b230eee52bf831aa05e0806456169621d00f89114bd8519fee74d66da078b744c598ed2efe0eefed15f98f7361aafe047116570f0e9e34481796518f9a28cf9ee14d378d18075266d213062060a98c", "SEC": "0406fd23315b83f0317f480e27691a859c59e97ced3d0ef88c62d3994379c71dc81c150ab4da7c02f27112dc2f45234b62c9a3e7e0eeb69e867342e740e9b4c419", "TP2": "040913a3002966345e0826a17ed895f055103cb7fa7d99dd2a6b7613520512dd5d238850851d8678c37fd36f33712f5e2ec745d95ffa8e79797e2670710c1dcd10", "TP1": "0403379e9afc547b2d3cb42499e054be604dadf09f58ead852444faafe6e01cbc21e38dddeef24ed17e61542bfded9a0e69364a4465cdcba5dfacfb0f259fce126", "CS1": "041ad5951071cca09e8ade2c6cb86b545af499b31646f086de4005aff8491971481f893576dcf0281b02f8576c37286ae6f7603809473d06ffada49ae4e0deffce", "CS2": "0418c950b8e3533f50d21f6d3f2d4c258a65c6799439ea7474f3d1f05eb66ff12e04f185063de3e487b893bb0008aefae5959c06a38178271b5b4c323e3bcdb712", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "040d48749ddf3599fc64ce22f29914271f8cdba969f9c0c4ac9d910bb2ff319a0716893fb49f219c682dc9bcbfc6b1eb8506f299070331787a46b41f39ec61833b", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "04209b84718c9956379aa98f5e8560da81db3b9b914ee6592f697ba26d987de9b102313b926d3e287a6071aa35567b7bcc74ce4079aacdf8525854ad75d2af3c88", "U": "041ce7faea606377ac9a4c056f2d536f25c66279423958036f60138e2aa01d99501703fbf267f38c6f369c99a330f5a4442920fd360b8646e609ec8069aecdbfbf", "SERVER_OUTPUT": 0, "Y": "0ee6c740b79c25c24aebefc67ef12c58beba3e710f250a44d9c839516ffa8db7", "X": "14274030e85a8b8ffb0914d3f0ecab3e5ac7a433146623df252e42be7e73ee54", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 237, "UT": "0408afb6a520e89d5ae4b98245d0f497ecce6a77e7a65a7610f8aab42e58b36535160c17a8117c991252c08e05e2e400cb064c62d5fd60aa530162f2d007093b3b", "MS2": "1d85905910a26b7e1b4966e878dc72914eca95ac09d388f81b1266146d46169f", "MS1": "18879310d93dfe2228f88d54d742fc629ecd84f78d654a951926ac12b7381030", "CLIENT_SECRET": "0416287ae6d86c10a5baf14859c86505f880a4743648c3344ed2ccacf47113c46821fe579679b96e3e5b450472bf84fac18797221478676164178df80d83dcbceb"}, {"TimeValue": 1437055598, "SS1": "207c5818d161db9abb97af8ba18c31a5dc9d60383f0e0e5ccacefbb146842b77238ff30bb47cead9af004f8af6efdc0c1aa2e2b1f423419a0d1ea2fe807a510b23ab4ab84ac75d2027b611c5933811604e35b5d298a9bb37121245a5f0818faf013a636877ace661d67f51c8ebf4e7c4987351263efaa6edbd12ddbd3db874a0", "SS2": "18be97237e517bbe9c1de9b35b50539dc8f6016dfeafc926b7be5f314849ab4f0809228decc9c9a35105f6c32f91989c07247e55771579981024d3c14ec984e9172efac508cbda3958179752cfc32522181d9d8a804606db4445f2313b7deca41d4fa19d94d8dfaa3a040af583827cfde757e41d1f465cf2bde516b00074dc9e", "DATE": 16670, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "0c2fa810c9ada206a93c75e759b58f0ad93e5252320b9034f0175c45261dfa6e06f0f4e9f7005a0728cab9fc9086fca713e258864afee3fc28c70c9c3b1ef0280b4ffe89557fa53fcc606a436e672d9700b024ad49a367d68c8855258e6f61a90e4c46d66de62e4b7c65cb9dd94f131f992ab4fbfcd8e8459df99ed916343abd", "SEC": "0401d26dd8410e6082ef4274899dc50579c5b8016f4100e0137b1cf26990fb2f32232a8efdd5bc87469749aaadd94c99563b70cb545e71b07e1cc3a2cd0be6af4d", "TP2": "041989f7396e80c4535f3e67e65b8d0163f26d2b875a2ae072347f9e78989c76b707f258c3a79a7c67cb481319134763d709b0bc33abd79baadeb9d3921bfc5310", "TP1": "04211c0f9fa5beb9bf21d99b1ca74913cccaf1f0c9a170776024455327c6d6c2420f13cbcc9fed288fa61f69805fc25d6e4a294652fc3a2e12e8cf1fb86bb5d97f", "CS1": "0407942b87784e951b3b8f57973c152dcc2cdfd2e191059a60df21dfbf409b285805ebee4c4b0d83d448fcb482d38f8f4a3a613ecfeb37c23ffe5847490cbcbac9", "CS2": "041f569c027eb7a994d796aa259e575b3f0c83c9bdb8314a55f563429000a5e7bf1a120397ac1cbdded7dafcdcaac010fcfe2b455a31d16f23ab2d0d578e8dbca8", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0411682b3a0e0787594f4a439ffef6678f2704436b9f1067dcbcc0c34706189aa30cbb04a62e4b6c52e20b1e41f68068c4807ff0b400ed456a7a35da748220e114", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0409bd53ee6fa337527c5258034eacf0ce814d491378f25e67194344231b0559bb13089f9c315927cb109372e12bf79d4e523a0dbf802f17ff52fd0969914ac4f6", "U": "04119eab782b1dd1df7c3163d12ef4530538981e358822562790ee4608a781540d05d8e83bd68aa21b12a93a9fa1fa58034b6e30544b9a84a122858c8ce1eda7a0", "SERVER_OUTPUT": 0, "Y": "08789de55cbdb1014f9bdda102435d47fa96ae05e9e1cb28b33550d08a8cb479", "X": "14b7d91302c6c18e0bc374d84b32cd0993ccca1101ee9580048ba34d5be8f03d", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 238, "UT": "0416f46422b0829170a6955cff47bc6522d968d5e861fb96d480e12566fdae5508062cf1d12f63a7572377443b0ce41961637a25fc0965ebbe34717cf0c10e3425", "MS2": "1f8371261e6ff378b4018f0d696564e645bd3329036a134087a143de625e4c92", "MS1": "1c05e7d437adc24fd6131f10cbb7d023268fa175db1412d81137b1d198ce2725", "CLIENT_SECRET": "042093139d503ef51cf0b6d343d118bce35a71da8f9d5ab6cc4badaedec1b89ad40124ea02cc66bdbf406be523a2b39b87622b934523cd9e1a2a692682a2063911"}, {"TimeValue": 1437055598, "SS1": "0505604916f86cf8f76e3a8576ac3587e4d3a0797d2be7a59e12d2084fcfecad1e105cab295ab5b106de27c52d504a80def18dbdb2003703ce8e4888ef85df402233112fd1fb721805c056f075f8234400f7814dfa2fb6effb26e01a12d9172f0d0fa5f60c355d4cbaa7902c66dce14cb8bfd4ff17b787199279602e3ad197fb", "SS2": "23286ed51b265dce67d5dbcbfa2f59c35575b0f8c6a6c886a157d908ca2ad8ce03ee5c0f6207c68b88959e18649969e5f45b6b6e633836a871dad15918a7674c1f9e49ebbaea48f7641a446d891ed78ee3c8884422f56e27e174490edcf81c3d22d57ac81c7e5bf8d0845c94da758ffc92f2ef3863fa49a179e3b6ab2422d456", "DATE": 16671, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "0beecfda8aaec14bf50ba100d5fa777848152643d8ea2c8a872717141aa9dbf0087be3efa41dde4b603274c803600a6c32c32c84072116fd8769b1ef95e725f91ede287212b424a6d3bc8cde52c30067d710b3663da52172cc1f9fc171a4183100ba7513778064da328692f126f484771ef2902e3140d2ab771c72116862b3d1", "SEC": "0410f963a131e9a91a65a6e2026d008a1c16d57c8b1d7c97042a8fe30e099e2ad51ba276583b579c1fd3604f2ed6c1b8d17185e912876bc8bc7dba923bd22ecdcd", "TP2": "0422bfd0a3d282cf3c9a66de1f50257f26bf3114cc8420aadd2e6472c6d38c1e931f6fd681ab91df157d25bf9330b4f7f160a9cf0b592259224bf0cab2c82c699b", "TP1": "04043e74a873fb673f55ab1d3d974c193878268b2aaf5dd9756555f66c29e211f90208d2a308d52c18647df60fd4cf49d7d12499107089aa439ddb6a7615200643", "CS1": "041c9221dc84f28f0f546bf36d88b841c71dc2d23bf62d13b8f7e1ddb56b627e2b09d9fc9baadce799a06bb121914c9aee1831d60ea2dbb6d09c22d657bfc562c1", "CS2": "0416f17207481f48f30fa21a7288421ce68cc25de9fdc67315bfbeb427797d85d819ffaa2a121791f07529a15b8c8c17142fa57a12be5818f897183cf0a1bc9a22", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04129f76c06396b408484faf387730c87bdc9f89d062a1f8f30ceb8e66923a17b816bd59903962d675008d7f24105959d1855d4179e857b4d6224afa1502b1dc82", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040720a205b043e4d9245b167046a2afec01da472cdbbcab7566e3fa89cbadc0c02205dd149893d1b5db77bcaa1c4b97d20647fac4d4ceaea1ed27371f05b50e66", "U": "0420bf2a9b0d4be3fdc542a6717dbc3797ae259c1f2b1176d288848f4d58824b0b09b15d8f1b9453c36094c0bc9f9088f2b336f621ecdaeeb902914c45b27e4e6f", "SERVER_OUTPUT": 0, "Y": "1403c0727cf134a2613f7f7a51b1132a1ce27e153de293b60ed393aca4ddcd7a", "X": "18f47c5324177b90d5dbe92e190253077eeb99b3e7fd464f2a94a4c7b6395b1a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 239, "UT": "0403daba16919b86390ef61d8f7ff753951f7c0555b0b9f62fa6412da47175b0131e25e93e458f675600d26193da538a5706850d6f44b3c91979630dfb5309ea2f", "MS2": "12dfccf20a17a3c16f78bc9d5559474bd90a51e3c28df177798be64ef33e53b8", "MS1": "0ff82166f474806f6be576dd8a6c119530717204e6b975fa69ee09f63acd1c32", "CLIENT_SECRET": "0410ac50a5db67a6d2715ef1866bee6c72a430012ffe91f1fb0f4fa8b9ef9b909f17725122eb1db4aa6a88f0c7b22ed45cc35462557a6dbe8ab7bd3cf5bdb6b341"}, {"TimeValue": 1437055598, "SS1": "0b3a1a386d250bdd686a9b886bdcf032fb9346baa5a45072ff6b7cae5a94a72e0eedaad099d1d866bb5e0a2e7631764d035c9cce356bae021e99648b9e38af550e69860ff734f0ee0d04db669d4d130917cec0c3ed70d627d261df4dd05b21c722b9720164ccf3b20f853d485343bf9a4d7155e6617ac6b934f335758c6bac0a", "SS2": "218116dee1e196dfa1e7511a4ca196f97dab498a244bd2a9bc3a333a1de191790112a6a96287aed302ffbf3499c1a9987865cbe8aa4a7e283dd19d55be91e6e916b76513788031ea620b23f4bf1476e9c82e9ceacac2a2ab4e5527428b72883020fbe5c321d9752efd839e4be0d9097c6d34ea620b048ce8a0a49b804b83f876", "DATE": 16672, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "149f39c946e8e5f6d17562edc83486550c6ba264a956b5d6451c4fc2dc41d3451d425da5440cf4015475eb17098f0660f1a72e3c9c1998c20b89b90efe2051300f5516f7834d303913383ef5970e093c9b9e9b18fe44b6939d01b508b4df67880ebf2d7dfb312e42e2876f8ed40540713113da464d9933af2c2f479acc5ea251", "SEC": "04028aef80e749a0b79a7474afa20357c7e411fa76f8c614bc080deb5313f343df09499fe6c2a78bcd843d8e84d6dd50be86f0f30ef2a51c306b2e2b9ff709f437", "TP2": "0406d0fe8232ff23425114b02e554a6e164249d7a2fc118e1649d234d9e344e47a13ea23bfa2f3cb2449c4e9832f1313c4d2fd68e706b36f1f83938d5aed60edf9", "TP1": "04165e77f784b204ee727d7b0fc5f778426d0a434a9e20e22e28ecfbebebd78f382127bd77232e204aafb0c786b1427fed6e9e0276fe5a0c6f52773aba33cb6a4c", "CS1": "041f061670c1f9e3676a55c7454910770572540506a1e0b64d977d808997de234a20de15fd9686b7513cc8dc5524295ff8b2f9d2fa9d1f02c4eed8d7f272b663cd", "CS2": "0402b449308d9248d412a6f36831131cfe3d235a219b83288a14c68a46679d7f8611d1aac70c3cb34ca07ad1e06020be253e72e459d2707befb4e3f8c2a6d4d5c6", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04154ccfcc618652f9be9f8f897c4a3a037d8d9b4176a2a26416bb9908ac144ba51a174ae7546613cd140c3176cd72fb918d28920f373781e28257625b25640766", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0407f08d8b00985658321b6f6cb50a1c6c8bafde9362ee5a4e098e37176b1d5eb21784268a1af8c6ee71bc4551ea6b726d2333bbd16c5470800078b687208687f7", "U": "041220e84139f4033969769914a48111aad0915c56b58fb117501e53b3127152fe1f74d502622dedbcf92418c77770e21c69e19e94e33a91feb656208bf787954b", "SERVER_OUTPUT": 0, "Y": "229a5687272e08462a02b2f420cfdaf8ebfe27f473a3dc0f858eba46f93039c6", "X": "1801ba0472343894b312528017c3e3f772e3954abf4e0976cbce6ef00ec72582", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 240, "UT": "040f05ff17c18819164c793a400d0bc32f395cc664d8db503de463193f9028fc59160c42dd87f2252d4a959f8643892243d6590fea09d0d86cc532b8dbb7e0b8c3", "MS2": "067ac0276b1e83e70eb1480d06fbdde835f0349117b44fd9039852cf5d198cb9", "MS1": "0f741b6c3e57c809dbce2c436da9f6cb5b7c108aefcb64d158828c9cdfb25755", "CLIENT_SECRET": "0419642189535d29b431640fd930a716fae749293eb6143f1db10476a2b08352c91591b2977bb9a2fd4e8ee58bc41631850333fdc4c8d5d89ed4d2de5a16ca2d72"}, {"TimeValue": 1437055598, "SS1": "17852f6895c0fda988e2f30a6afa9cd4805f1155e3bd329c30c3e5f3873bd89e1256bf1805493347a1dd0374a16c3d14dcf055a4ebd7fe0066254b29072fc39f04ad976de849d674c455af01b3edbfb188ed8886da7df70cb6e4376e7db250c807f18c52ceaa0f187b3f0daf1e0cc12151ab6aaeb56b7f78a933e6a0d442cab7", "SS2": "1be9e2611c9c754045d9cb48dcbdd1e612dc4c78e9e51c626e04d79a8b8d584b1fd7a7b7a4bfe7e79a140c7f998d855ae8ea629a55810e4c89b5bdb6dfa960020540929b7ba56e65092d4d76bf0e79f863614d38244a76c4652bc7b28447478605a01828d8cbdf61c31a40ac6582b1530ae0ec504e1295f63c7f0c4422ee95c2", "DATE": 16673, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "083f79b7e3fe31401007a7e64a95e54f1c66f2a78eb1061dc5682d11ed8d808d1c8fec7492d73c97dc9ef4d6d3e0986494160ff76b62264214a2f8cb9b89ad2c08e4861e7d4ef1d42ca1775a04e02cc7e9436a05ee1cdbd788d125f80fe8306505d0c90c11e6e13c11136f7a54d15e3a30209dc728df52d6bea1c3202e5dbfd0", "SEC": "040c6218263dc286e7a057a2df69495e91bed4331bc868d55ca5981549baf0ba66105be5d598d42f722ce05e3c50302a54e55b24821d2ab592f50999f22c22f94b", "TP2": "0421a45ccd4bca71809e24fde8877d71fcdbd8bf16b6a1d95a93b28a3295a5d2e823291832a9f68b23c2c2dd760fd10a3a106317ff6125347c35a6b2cf05ebb639", "TP1": "04074e58bcb63d1ef29d50dda0224bd44f5fa309a6f230c9b9836f5375fbe5da371e64931790ac8db3e80add68fafcf82fdf320dffceb6705069d71bb5df1ea0c2", "CS1": "040089883d1b9c0282641ed21adef4c48adca1f23dca476a12b73fef56ec29ab060c7920b6b7b1ddad14e28791671d6f5abe4decfe66eb6e03a9ae9b969d77cda5", "CS2": "042015a249d18a2af2f4f0729f28e5100374a2663ca6e489391a2edb19e84f05671b4be53ae288c7fcd42ad4b519fd454997a34d3b9cff83103c22c0d2c1d7c026", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0423f08071e451d60dc0929c8531143a142428b85362493c5aa1f870ef7f780a7b0ea88342449af0a3aff3124a16101cd0fcad78835d1346d9df303dea2da08f1e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "04098a11d61d9fb181885d04922bd88dd042cc3d5f1f0cc35cb252e1664081ed1923c38155f68a74979152cb737f99613b98722472870522002d3c81acedd6a705", "U": "040e3c5fd53c46f9ffaf3f44162d47d768a6abf3b164bd59f984530d2408d9cf2f01986522484311bfd7e19887a02685232d21c08dbaf4aaa89b058edd51695195", "SERVER_OUTPUT": 0, "Y": "16c98996110a5b19d0a4c743565720f4018033f74be347c81b5949eb0de765c9", "X": "0216ad773559432d4f7939764c808f4aa305b474ed37414ea9619aa6c04787ad", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 241, "UT": "04061049e1b33450f8b3084fe6dc9ee38623f06bee00de12fc361a5369cb9ad1341ef1b1fe094c2bd42d9b03b785372e945d36da2f847fd5652115d3a00f1eb430", "MS2": "069cacf11ce2d9e572bb49375c8953b6a4f15edceb59739ceb6a6967dcd23097", "MS1": "1103c4353fb921ff4be8d1eb22bbd134954969015ed722290ff794222b409616", "CLIENT_SECRET": "04146851eaf5e6de600c5f0854fe96e404894bf2701ef1d2bda7deef8cb1ebcb271dc968c829e2a5124d8442cfb62d5a40964d17ff8685e0240704e9d25fbad127"}, {"TimeValue": 1437055598, "SS1": "1a68391f7c5240f82c48f197fbd682ec6006f0eccb418ba5fa38c9797dd2f3dd057e362bfe908be5dc39acc8822e1098d92d20e16501715d9e18974ef151a6950007a2a5bf9a4ae1849d8672d146be7da4f8604435e2fdfc97f56cd717118ddd04fc1abd351679485511287b4c1742252706103bdaa6d32b2277f0cb7290f1b1", "SS2": "1b4d89ea0b2ef5cf577839be55acf75d68830c798959e6c9a65ca4c3d859a6a314b141b26423b1325fb2f0f6078ad565c2ffbdb809a2c983afe7648e69da12da0cc52fb31ff9f03621c0687e2ae64a0d77292121de41cc801a2ca870a40e9592143f47115e79580b310504ad91ade86df8b2ea055e4e568862eaa89880c21f15", "DATE": 16674, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "143a8a6acd2a4b7019ef35981434867c74ee4d1232691be0cf397d93eaf41ed81637e0f391d2e2addc8a5e200ca8ff8f7503917143ec24485e167d57a8e75180198e7ae7f7146ab2b50ac246332c9cdb0fd5952e2356847a6c045443bffca74c04250f74fa48d817617b2a569a727ddad0bb9db8d72441459773983adab072fd", "SEC": "0422bcffb481c6449e0dc63ab54cf17ea5098c1048c1969bf55ba451da1d0a0ddb218d173be0cea556e23859e49742545b26fd153e0f4c9e3131f2d1bf25c72052", "TP2": "041922a48c724b5848ac989e812e6ac7c4efb1c44a9691f13736e7f920f1ba1ea31015da0aa14cc346008ea68aaff07c6efe8fb41cd68ef9c9ead75b4818b1c5cf", "TP1": "041cb302102d41f13f48a4ea9bfa590dad7cba7e24c00bf5d6ee2224ea69769a191435fd12ebc58d7b6fb6392e29959e900dad808a03912301a89e2b301e0842c8", "CS1": "041c38dc29848754222eeaedaa1e0da49721b0b38a0d70de2bd18d465f9cfe398e138cf1330291f2372778a1965445182d43217494e27fdcd5668498b13ee26b05", "CS2": "0405a6355eac2a41a138e957fde8cb7da67cc18b6e799244fd13b1b38b798ae34f03508bc1a55d773d1fd5db537207a7cddab4c3fb3b7fab6fc4add100aac0def2", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0414267d0107944e0be08a63f02033f61f45adac8b680dd0fe25fd6b1d719e246b0436b6109cd1a526cb2938937cc3bc4d7221af4c23853e4d4914fe4720479b58", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040903bc896c6a76b3456fe3b2d0202ca7b0342d598495dbe56662481690c6d79c1c9944b3e5843b3c6ba6f214a7569c2200cfa04d66eb8d14fbcd10af27f67975", "U": "040d39527cf68a6c69ac90a9a07299e2778a938363b9800417554c880268a596ae0c87aee8fbf19ab8bea8bac2628259583afa8a40b0d39da78aec03758d033eaf", "SERVER_OUTPUT": 0, "Y": "0c30e847ec2ea1abfe7e84af121c19080257d9fb17d87cfd2ef8f02dab3d5327", "X": "211694302722aa0ec8dccd6e4a1130590becfe1353ef30de205302253eb34009", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 242, "UT": "0406c8ff67ca391ae1a65be96bd4ec9a58829ad8cdcb2568667d10eaef5eb517f00ebba2cde11b371d0c6cfb0d1a47c6fdfd34eabac5920db66c5c31f56192596a", "MS2": "1ed163b6f521df4802ae1ea2604b3b3bd09e50233c8fa0b46478419a9340eeca", "MS1": "1dbd17a575e9a4d8470a674082201a69b12eae2ec313952a657631738b6fa27f", "CLIENT_SECRET": "040c79263f71890763ff15c91a5e8f52f7dab061eeba987aa6f20ec4cca59f66251b36c460444a1089a46ad53d90523249290f837140aaa6d9235d0f59994fcb50"}, {"TimeValue": 1437055598, "SS1": "13b382dd3da188f2102507ec4130fb3ed497e5a2e803ffe42d9b0e70b52cd4ca052510b6e15b8b92e5cf1525af63fc0554e02b7a3d9a1610f25e10c254a2e5ad05f7294f9d9f3129b0b96b4eb6ef16512b4fd044ed23b8486786234310f1d87b12008650fff9ae7a2eb9c608c061e03e2032c45a5a786f85cfe1edeb5a7b9e2c", "SS2": "03df176f98bf95081c2ac0820f5dec445ebff7d344d2cee18a86255499013e390f9f741adc353ce89a067352d8092a50336bbb27a7469cb130285c7d3adf1b6600dad41619e26de1b552ade12203afdda68079b410437af353b8e75c457ae5ef1d1962788b28952d82c588eeb37ba6332778d05569b89beb220001c6eef86a7f", "DATE": 16675, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "096b5bffbeb274659b185fd7cae267a4d991280d1bd7775b799f62928289276e1c458e481ad560a93436f7e4de33a55f92b63a8cfce98d56b2657bbf2f6e0c8510b91df4ab38a1c123bfd6f7ca1245d161b8357e85516ed4e8d3f302b37424da15402a1f6b0b60a942f995a0849c3dbfe72778e3be12406c361e62b00f43c0cf", "SEC": "04226ba0203b59424d8a0e62cb8ebb3b76239fc75072af3f245f7c4f3172656afc00a9346908a30b5c79c1dd1a24449817d46d7d28e2138678033ef2122cb27313", "TP2": "040a97f617c6e8c386c0d01a36978f896abea002762b274240fb6b29611073adf921cdbf2ad1f6180fade3ec36d6fbe9a6969bdf58ef696346fdb37db67a35d45f", "TP1": "040aa034d93006012a100036ecab08f689916d5c4604582bcc6eae9878401587c008f8a88401d587f109a4456a8ab5214e7c4fe0888764790016b4627cb94bf626", "CS1": "041b25da87f1d8c1a0e340516dc8e94e27d23eff1552992ac0b79584f90dfe1c4a1981a9a60827f8de5c377b2715efe788a7d1cf9fca4ad064ee6ee704609e5ec3", "CS2": "0419854c903b8bec472031809899b6e69b4bd08e1820fda6122911373e4e6cf457143d83658a0644a6a458ddbf44bb1441c6198098297917deeaccdbea493916e2", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0414ea8e5a4945b065303dba51ede79be4dcb8a209f8f663b6e483da70135b744922df37415cad7ba2f3f50f530441db7444aeb3962cf490353a52a38fc1c1fb44", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0417c5f0082704d40e52fecfe3d3a897f3a9dafe32cdc3d3be6b6c18495867c0f218ea420ad9b21ad06e2821d59882a89c2a179ff2dbde6d0c4cc8db666061e60b", "U": "0402cb7f01af1aeda9b4ad88964e1b39c50a637cdf371d0334a78bef3843fe5501025eb3c053ff8e1d02183d2d6a8786d8a856f308135b795da8ccbc0b9b55ccab", "SERVER_OUTPUT": 0, "Y": "210667b182152b606923b1e0868e452f9ed3c7334248edceb440bad7ed0cb6e4", "X": "1a5cf3e4e72b9a000bdb31bf5e710dae85fc34a57e56c4a9d584b6809ffa7715", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 243, "UT": "040aaaa02e3d3347b8a8428028bbc1673e89106815852dc3eb588dd5ef77dce4e91a3c23dca0d31e4c6d1d5dd073814c89769472b1515a304b67fcd77a648c9a8f", "MS2": "0368f3dc00b45d867b2c4900d4006b049874c2ae2f656653e4b24bf70f392bec", "MS1": "047c8fb532400ff0731e6bc00062d82025e3ddc59de3a23cd0595ff5052eac60", "CLIENT_SECRET": "0407287b16309385ad6238613af0dba4cf0251c03cca957c573524d669a3ecb8da1954ea1708e64332d6f9f03671163b3b966442ed3ee1576d44584044267d0cda"}, {"TimeValue": 1437055598, "SS1": "08ab2879efe7ed83f42320cee5a67ed789f313a68f3345361b038f6c201153771f56cc6c79922284de3a62dc5eb24965a62ab10055f6edfd5c55ed7c6df3c85603bfe1446090034bf9489ec1359dc17b80eeee669449046cde3bf0997c7f09a90c3628a3eb45d90c8956c6dbff084324f4067fde5c91da2578de9c19191a7878", "SS2": "18d324d51f63e6b69b670cb37026e3ab02db4d0bc22645e4ce1277bfcbbd2b7311b76548720656430ded7af2acb048c16afed90a94ccc43cb5e7dfe65d564f680fe49ec077593887b5deb2f887faa465fae364b783836572c9a746d7547d868418a3af7a77a55c3ae6eb66dafe203c14280f10fa4bb7407b7628852aed7e3d05", "DATE": 16676, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "16e23e47ecc7b2ba27ca82d1795b3cfba8caeac6b6aaa610692b30c66568ff5901ebac775d8a194d38c99772a439987c476b3f96e7624b8a66657098429373db23db5171ca83366420b9c9184c6c74bb5ccece82319b17ad11cee39b6d68f51a0192e6cb0a66320049d5348e249cfd9e56d6859211dd1c521c253c34e935c4a0", "SEC": "040f225832346a4f6ed00acf3df31c7fb80cfc7fd7e0ae72d9560d29286ad25f5e0021ecff5902d3e1979c6d3c9039ffc9c91694c1c7b42886c301104b0b151583", "TP2": "040e6f27724f81557842a3d648c392a1702172b935525072547775c19e8ecfda2d00e9d0fcb54746498b778dad2184ba9567fd00a7f3c9e63793b322c69cd08ff7", "TP1": "041eb6e68faf6ba209cdd751efc287214a7642af1405fdc2c5147a19e2f41883fb159e8ae92b4ef18a460b4f3bfd2ef17c73e685e92372918f512c89ed29570114", "CS1": "04111287c46dac0d86632a2c0e23369c26abfc8f8cb8e7b5573493be3f7754f80c1ab51bd346d72e2a7599a8d76f566dcd7e1b07e7013ade36e01fc4ee976bdc4c", "CS2": "041923e0a2b62f01375193bda9ee8de338421fcc21caab593897d40d5d8271ae5d224264a16940593ac3c5d0b22c72bce8960f606bd1ce1ca09ee3467d12d1ca0b", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0413e3cfbcbc7715d52cc5d744df76211220db94753248223e838e3b3c3d4fa6f416a2c9571f1fc3e6f70332ad3066481713a6084952b6210237be5ac3124ab08c", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0402a6aab74616bc087d58563d7b8c0621b6bd760e50ebc5425238e55162436be900ab06ea50fafd151b7034bffa7ca1849e180680bec0d7e13eb01b460508e13b", "U": "04048256c518a9b27eb7db0aceab77bf4827cafafaaa0d913e54d544a760bdc32206bf67ff4fb74ade66596e004648a58f1700818d631923bc6c2dddda5a7f791e", "SERVER_OUTPUT": 0, "Y": "1d3b8660df1f999b8b12a20c5e45be95a3aa7f28aca92c1d077127e9e1422dbc", "X": "11cec882ae9146e01e66d6c8a1f6d1e17f8d5b2bd2186458a426d979f34beb3f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 244, "UT": "040ff589d2c19313768ed3682411e2b4915e6cbc62a3a02d32edfd78ea6b9a422a1a8eebaba91068efb1292930f08f02cf2d8d56a3e0213821c555afdfaa3cd344", "MS2": "1c67a03df7b29b7e05310add98b19b5b4126ee5f47eee2933ce604daf93a0783", "MS1": "109bb3da4dc684eac54f5404ff40e3c24bfa22c80cb314fe3a1db6ce41ecf2bf", "CLIENT_SECRET": "0413f574679a8d4f82d9041a876b79bed8e197247e83e26ca7a0785af67460c9db0f311f9a7a8c2344bfee7f79e8c9e6180a21c6d44a9c0026e6882f6e6a24f541"}, {"TimeValue": 1437055598, "SS1": "166785573e8c70ae58566a47c1969e4832b90d79164bb1abf70aa2586530181601e5a8c7d7b0f9b29b936d58f6ba374fcb5be66499a83d57a8f3c4eb6f79730519f05c3a0042522df2d82eb407d0b66f9a6d0a357513442663fd64deece6f56f0bf6735a4ec14a07d74cbc49162fe40d887526e5c69d0261c0ed96fb41f50802", "SS2": "0c9791d610684500a766de3f34c3f1976d2e2e35307185a5b325050986cc0b91054e0ab24adc129db204601fd7dae9d25f70dc6878e775bac9a1f9fa7fc6b95404fe9769bf1a69b1317664d39f0b6237d684fc22b5586579e7dfc91f174b97bf0923078050d70b51d7c80381cd2c2f9ea046296d2eba6e63c38fea450e6d5704", "DATE": 16677, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "02aeb77d782000e4986c93e44f66bf1c65711011f62fb27770d62651936b86f70eeb2a9c2f26b0867e32323dcd0c66a0205ad14a90d3ed5573492ff695b6fa9f1f7c52c242eec062985f519c725e80826f10c54de17d149fbdeeebdc7f7d480f031c0eb5195eba0f6de1591af1ef5db2dac14c5b972bf6e55ffa72eda40300e8", "SEC": "04060ceac1bd6bf27317e39a97d8dd7bdfcf570f6bc84641611b624f0143e2bd700aa8bcdcd1195b21bc61dccd2e2a56e1b2ff6750a5290755ffea13d4726467ee", "TP2": "040239c090b258d463b4edcf2d5a67a5d5367071b492816dd280cb7ef5419c65c51a1ff960e069edd9409b4469f1fc58f74956d907dc89e6ccb2849be2728b2f2b", "TP1": "041b178cf757cf8f30254454551ffa16e1cc3fba7004cb4e3b7270f771fb71f83f1fbb6f7654aaa36e399c7fe6b397be06a05b3cf30937fff5eec99863ff6e8908", "CS1": "041c66b7084874cc260862a3073d45cea3efc9678ecf62c082c8a73a577c596a900228a816320faf7940b369503bf75a3a6028269406d5ac5c6680537523d79e00", "CS2": "04024d679e7c3515eba60e118986f75c4a1f655203ade09c30ee37269f4dbbb3031b34d59f8a8ec749422fb0816f74a90f7cd404b7c61d9024b82aa382f2129db2", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "041330594012e0a4eb84319c116b7d866d5a5972f753b2d21b4c928c07709ca6831a049ac3f762d165969d9a716c742ad82a8a7fe0907b1d91ed379f1ec9d322e1", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0407c8213be770533f2b794b24ad2d85598761c4ba96477fb1dbb0b3e2f01f40bc0c616cc8733ea21372aae473882987d77c7fcc3fb7dd899dd6e33e3627de6bf2", "U": "0420ebb61057131bd2f3e446a70581c30e2ec7a0ea3b9d86a19227b0263843e44e0ef4331d9ff143999761af08bd9abe9358df08856257613059d0caa694bd92f4", "SERVER_OUTPUT": 0, "Y": "1feaed6fb8d80c0601226c784cb2555b5fa5e7a066d4cdf7eb627c7d50d6eab3", "X": "02f82dbad9b53a707b63ef40a252595c51364cb6413d0dba8149ed9f82eb2548", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 245, "UT": "04223c41bc54f1211c0c9ac9cf8410abb03a4f291b8c6348f96a058bb98db5d0921898b2bf1bd4730b83843b5d7e4bff3bad761f1c1d5270429b9c38d075cdbc42", "MS2": "205e6897231c6bdff6803c73755d67f0f1f07e2646bcca04ab3548ca9c8b3816", "MS1": "044890d832e6c2044da0a45f36f7817d6466f9cf4c56b440cb233f7afb2a4d44", "CLIENT_SECRET": "04203083b3232659e49d90af154e5701556d42196e35756b4cbc97e75faf00dea9067f32b5ad73a39310f4c687ec16f71a0451713e86a89a1ba7390b99ba627f95"}, {"TimeValue": 1437055598, "SS1": "04a76e404d8e4a8f238d26eec0662d6bec8b861f2bef24f00bcb702b7652c6071e6519faa0f2e9605be3a1645549089887454268b5d480a299a25ceaefc018e60eb44e87ea7bd57af191663bbdd097e86b1d8df77228c128fd1d45d6099e954a174bebac65becdd2d2ce5919ddd5e6737050a8ea3ae2ad21979ca3c8df0457f8", "SS2": "08e11b1b1cff8df26932325478458c89b40ca87388c264dcad58f93c30d5a9660ddf23c25d494b025164ac21a2e3ce95ed8f9fe6c980fbf43a51db1cb3d6df831bae57b1e11569139fd550f66e554a9b960da63be955cf7c449f00b46a49f0d50b51236980eb6700bb57b8cb26452114e5a110fb2e40566adf05e5894fc8cdcb", "DATE": 16678, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "17edddf977b6dfa97d7d633358ac4b40c9a5b8c8d34aaf0cabb2ecea9a5a737c0d2bb77461f34a80e9dc90e79ade65783e34cf3917ab1a241dc2b130fae1076b144f924b4966fe810f89988865f1d4544382b3b0d4f842b9dc9b7f15487e2bc91a596de07249e6ef632fd09a68f1a1678bb5765a7d94d75b69fe570501dd43ac", "SEC": "0403edbf05f72107739806c616bba6a02238d4d917c4dc35c8e53dd4f24f49ad710f44ae11faa590ce960829eb17e1ea54d63409c66a9f9ffb39218872779bf11e", "TP2": "04239070419d870ee1ee57a960476ec17c1673c42d7ccfaac069f6457034b51d301ab81f5b2468b744888aeb6b473d2a3db9a6d3a3ffeb11af7c9903524df94249", "TP1": "0406c9e6e87ca293bbf78dead61151dc684da6803bf8cf1fe25028749153e945451599d68e964e4c2d691ad98b95da9b65642c615cf2233c94a457b5084759420a", "CS1": "040e8aaf238458aaac4d68322710ded3d0b3ce8b6c971fcb970ef5a05076770ec60108b217d3236ab12b703857760d7780a64de019f6c7a94b800bcc97aaa9a979", "CS2": "041dacd97df15d91cdac1f8739529dc32510819f1abee42523209bb690b4ca0c4802a66173ad1a2cfa50ab5b981056e602857bdba42df9471edc6c8ddaae975422", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0418931f685ce02b15b6404df92af34be01803913e4da37ef4dc43ae116d4d98471300c6ed6f37c61dfdc149b90a584d4dc607a288b43947081ae4e22875ca5ffd", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040b6dc8831864d3ae5c3366db23bd43808e4356e5ade902cbbf5684dd591748b72192e21fab11c4f47fae06734c36c4e64b6739520e9cf3e9ee18c31f7485eaa9", "U": "0400641282eae991e5b7d1fd3f943e0757acbb441571b970723262dd0d1f37f13f20de59f943b6102d1197cfac65a391b5fcd0ca1f64ba4ff9495fadf001550775", "SERVER_OUTPUT": 0, "Y": "1afedd87f1eea542f57e442c4ac1a672fc5884c6d664137ad731eb6dec3398e0", "X": "0dc91cbfe8d916e1c7bafaf874ca6ebff0eca340dc301f22d35f98042824d3db", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 246, "UT": "0409fd3af95dc9f137b610b62391d3f52c41c3f2986c4f93c04eda9f6a3724d47214826cfe56b8d40804caa7f7f21039751fd235e72522eb5303d841fc89939ef0", "MS2": "1bae8530a3376cfcfb5baf25ccf8ff225420118073acb4b586aa123fc0e23a4d", "MS1": "08e7abbd862c51d1d55450a80c863468ba94bb6c51f7c9c2dadad4cfb7791b9b", "CLIENT_SECRET": "0410b0f918cf0d9ebd2c959b8b838325cefcac453a882903c975d6c726adccffd110328332fc6abd4ff95115258030af7c21bf57116882863e32325f31abe1da95"}, {"TimeValue": 1437055598, "SS1": "196653bc155d9f5e57659fe713d408557715ea0e23f5ad12dcf06899b609809205ab27062e4b2b95867eaab559c10216652721e2d5ca5d1db8a77168c021e3e81552c9887bdcaeaad48be89f708bf2ebd8c38aa4a3c9f633c889610bf5c16ec51c84f0d6f9a846213b679bacad6e16c1b7b4895d1a7483036cf489076957ba65", "SS2": "0cef62f2bb3947c9d037ef3efedf6061f86bfc0025722978ef1197ba05cc064911b7223c40ae953fd09186bad75ddc37a4d509b6dbea8532da58cf170304a43f211418ca5ebc09895454f286c3eb69f4b777b18411942df3e700385b353e65472332f569daeffce90efa5c5cf1fa113621c48f92d8760de1f42be1d5153b48ff", "DATE": 16679, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "10654236486d2c4dacedf4d0132af3befc635437629d056df9f5f029a761583616624f898c0055c4697683e05e414ed5bf132db49ddd4f28f943685a5c1fc6ba0d607eb1e20898caaf0af0a676e2b2efaa4f6bc733c3dc9504484dcbe76afdfb07a823f175b61cbce05c155273c560e0f27b13911bcb069607b124fb93a248cf", "SEC": "0402466f951a5ec592c2bb792e01b460abe6ce1515e179da7288df7fb83d22b1571ada64e475b4b964664c7bdfda095013ccaffeb1ed441025ab69d6571bfbbbfd", "TP2": "0408802bb89e6d387d21f9aecc7843b7b9eb4d5195b3318e914d1e2baddf015a6004d5df332da66e4295513e9bbd5f48dac1c7ca87aa0909dfecb5b9a7d9238b5b", "TP1": "0403932438ff5f634d654c368a47d10be85990130a0f7b93f8339d42e30f24624b1695e78de20cb478365f13d729fce5d16d17f2201d1e795daff47dd96dc59e8c", "CS1": "040db39c6a87e884ede954c8cc570e5161057c8ea6642477b01a6e29165e7f6743149943df5e4d6b4ec8abfbc4bb9229bc091961979bacd2e56610958ed61a553b", "CS2": "040a0b41e04421c7aa49a9023dc00777c94271dcf9332f43b0f1a04ddd8429c2951aeb14c4d885b2eafc842c724b98b342d9d8d288ee7fd5f739c1be990f563e4b", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0406a1cb6a4291241fb674079356c4bbc74675f11ceff9fffe5e72c6021fa675b10df84c9d0979ea8f9ea9b53a5753c532c98869a613819bb18be032fb29a216a4", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "041f0fad35c40738eb26dae8fc3898d8a302d7ef22ebfba2c9f8f5f13a73001d99212872f6cf299cfbf1629f9435ac89f330cf619e29da8cb9532077dbf85a7baa", "U": "041ca8ddeb1f4d4faa3b8e92c6475b08bb153f7a9e432d5d64d5aab613bfbfdaf104dd5122c23c571aab946ab84dbc974ef3392dbf3d59cf2cbc1d2c416974243f", "SERVER_OUTPUT": 0, "Y": "0419b7c74fddf418ed336348d81db4affb9c63ec4470140c27f6d02e8cec00c5", "X": "1c182493c3d6241b1686ba44100be37af08d0f74b27f3b136a46bfb66f11c92b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 247, "UT": "040d1836d4f942adcbe771ce155cd601a82d4a6566bb481670859a2e7efd42b68e143b29b1cbbd0a8e19438dbec1d3c1fda3e37da9e35925e7f58858c447205ee1", "MS2": "14a34bdf3cf25f760879c4e2970b47218d2be0f3f2a22306b3064ed441b1ad82", "MS1": "1ceb53eb8f64d9e6eeb652c692b6b0cf3ebb14fe9179545a1d3fe31942be2bdd", "CLIENT_SECRET": "040d638072e5ae1e13590f8037ce517472bdffa2ec6ff39c9600a2ba6add718d4e0d37a4ed492bb7a57bc19128fbcd4c39b2ea6ee8e54e4b3e91e36e11beb733c3"}, {"TimeValue": 1437055598, "SS1": "1ad0eb511695be8199fdb57519b8f8249432cd9229e001492d130dce7c11382b21117a79fd5a146d72e5bda7f085cc0b86638515dda0ce83e62341aa9a8c75ba027b8fbd13f65dd43b39b348895b4e65a23328495e88d64ddbc395f1e921e30d1090c5f6722fc2921394a600850c6e7345ad95b4bda15bcfcd5458cf9de8d3d8", "SS2": "1abef475d78361b670f1e8ca11481af3cc3e67bfd913ae51ed7e58eca16e782000156c951fc1de4741e062c55280fe3e92e67c0fcc6ee861d1a8abb02d978ffd1d10fa94df693c5aa3850401479ad27207c09acc3178f9b5d7b8ccadd7b28e3c1619e4ee1c75b67dc46dcee1f9c6fb18ddd6c6c20117a20307d1574005a60607", "DATE": 16680, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "0c344a8416bb2da7c9bf82ebd448c3cdde10fc6b1df26f493fd8ca8db4f975af1edb29ce28db04185e0a5ed405d57cedf9702edb8c5f7acd6a1d69af8a017a8e1371094095ad0f50046bf4431f2ee1b7a64811199521bae16c1a2df76cad226d004093d9c342f38e8be2eebb6c31c44fbae50c31c878d3827b2aae98b97be07c", "SEC": "0405976d1d326b02fd31e7b11edb09eaad740db19b5d80ecdc08dd5005eb6991e921d1a2834ec2a95032314a61dead697206f4af3553c6dc2f9b470fbec4edb290", "TP2": "040a34f7d80ee629dfbf35bd8987a8cc0be304b76610e091ae69c345f5db28581c22f266a32a281f65deb1e2e12cfe37e589dcd7c92a919cd266151fa3eab4415f", "TP1": "04003b5472ca5a8e10c5c52a5e2f7830270250626cb078a7b9f53a36f9f87cb08a02f2f530065188729f1fdcda9e666bf3f9cf0c77d24d6592c66530b54047dbe7", "CS1": "0404780d0b7abbdbc0d6b7c4858b329365f77a8f82120befa99f3789bd45b473a60ccdbf15df106a106bcbdcb0c50994ea3246c482ea87f12db1e15ec339e75536", "CS2": "040a9c96696e008ef5971bcd1995644465b865234bea611f28d836b38a62efafa018966ce0ff29281869f2e8973738c87fc443f8856905460767b09933380ccee9", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "042198f986a36dd8c7bf5e33a5711c5c14bd04d7374a3bd450c058f2245738b42a08d5b166363dc4132a0f0a2ebbf25d44d237b67ed7665c3ab4a120b639b6d50d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040a7feae76897f94976ac8e7470f730a63572d6b87048acfa6d81eca9b8bc532e0ccc63787c8262e11ece8453dbb24fcaab70119a3fda0f5a51808cd8940dc21b", "U": "040eea1ac12db97f06cb5f4d7d40055defcea56a16b0262c064a205b82f467b05b1f44ad364cc8a82dccd4e15601f5d75c64d7d874383bda40e2cf8a1642090800", "SERVER_OUTPUT": 0, "Y": "024ec018df07ce2a869ad7422eef6d572b96d447397c44a6cebb52c228b9a6ca", "X": "118440c931d753ab832d7abd9947a028f891ad1394457d5ee4bf1a1e15fd29ad", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 248, "UT": "041d57c8f5987152d953e7ddc9cf759bf83d6770f42cd7ae81d7a25e0d7f44d84d1b9cac11fadc3aa07f7297d924736a4ce8632252208fd0ab5873d40754c932f1", "MS2": "1766bee1ef609cb74ffaebc93fb3dca4861b89470d5465d2727a6215b521edbe", "MS1": "1ca0a1233f3d097c83711cea4532b4cf5045b76a88a1f265ee19f7a5aeb4c58e", "CLIENT_SECRET": "0400cf937ed072b4a25baa962c0218ad6edd14366af8ee98bdd7bf308cb0cf547b1b77fd2a2ec688942b25311ca535ffc31576f9859d1c7ca378c525ab4a25a798"}, {"TimeValue": 1437055598, "SS1": "0fd8e7adb2556c3a4ff14917a6a185a8f802af912bb019f408f85156d452bd191bbf8ccc36ffa472a3c18246625b9232bc2ab3568d5eaa94f57deb4dcb79972d1fd3b441b861a875dcdf9c497798d46d2e8c80299e93376e4da4364d971e2b280365c7e9ef8697837edd1b123d6cce8c1ea16c7c5e8afd674ed55f08cd338618", "SS2": "1c31e4819e05b9b7e6a50e0486b691fcc9f769a329d9b42312fb278c45a82a4f14b378d2872a651fc59faee38b8a9876b7c735b8691b8f5537e6e7cb3d65ff8504d08709e3ca930758cd24277cc99450c737f0919b9035173db6e97e71708f7819e2c3fcdf93688480e82364754542182ec1a248bdec7b0e020af6c3c584242a", "DATE": 16681, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "05a8534272ad8dadfc06cc43b15a94b1dae92d2c9e73bd04b7e8a298f9c356d510b7c7d21dbe3af1631e406e0cc3ceef55df65048844378be1ee982768fb487919890626469225df40ae7b3e09b7d1120ecf4e51a180078b458b96954689a67f0f420f53d55315d0d5201f18f187797d04d38a6edf84df2badd350db185abaf0", "SEC": "042023b3cd6c8384c4458825aeb06b319249ee9f3ca231052614efe1ef1cff07521b674f89c9babe994fe74946ecb20db47fb7556ce213e031d9188fb32b36ed95", "TP2": "041901eea9a082253fbf05ee88f0dddfce1ea11ccc401f77b77ed4e5a5b64477030da5f83cad681aa0d526d698aa029aebf3babcd62fe0f2271a2cb9304a3e5cbd", "TP1": "040c0b1ba8b147a4d36e3d239a008b040a7daa742e7703a5ab11e54ba61cdb7a78157116f6dbdd46704919b9e56ebffb42f1d6d86a20c88db22dd63ecb41eaa43c", "CS1": "04036c0ac30b9a8bf9e7394eaec0a4286b74d74e8d4b23dbf41b22e40691b43d3103ba7501aa04f5bceeff366ffbe75e3b6b0358cd87ce985d8e405ca34dd49131", "CS2": "041cd11e37191ac6f4674a2b65a8799106725e071e07db71ae643c884ad95e601c1bab3c83bfcd114f35428ef9fec7aa3164754ef5d60dac8a130a05b7b8db5a77", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "041c413cfead3d57766eb02ff8498c857c251bf16412b14dee161db913613cbae91dc74246e3c2349388fbda6e29cfbf390e6ce09719357f558d758f8fe3c66ae8", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0415ec9c220b0a3a7bfc0f8f09d5e41c76f8f575229c68538872b89d9c72f523a203652b517ce2c00d29f66c818454e5aea6939c64ca73b105439abf40d905cf63", "U": "04151c31a6d5bcb0cf4bde9c071671fe099a7399b0ae6a9dc2a7e14093d2893deb01ce767c93fefef9b4f8dd46f7a63a9fcc83a0d53b575f7c3eb2b47c1e465464", "SERVER_OUTPUT": 0, "Y": "1e855ee24d49b54a9c64122044942c655e6f5aeb4382859906691a6886a6c02d", "X": "135c9ff7c20a8c1bebb1fab27df5486813eea8a7f2ad16f8538f1d1f85a5e8cf", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 249, "UT": "0414a443f31d4039e002bc108f51c7a6e8fe62b0d8e78a4a804536abc48ad2a7df143dc91c41a7b352e001372a038bf6dd4917e232bfba08ef3babf6d046e84805", "MS2": "15b303ad984c3b756ba916b5fc6a44ff0e8a8fcd7d38ec7f95efb09bac255a32", "MS1": "1addb41575d4aa27f4c23ac86cd167345e84a2624736b8bf79f61614265bf876", "CLIENT_SECRET": "042242dffa5830b13b2907c408b75ac53cf1050466339a58dcc8cb01fa81248e3e1a2308da7e83f21f799b9c3bfba8fd5ea54de07157c3de9bcdb4e1794a658f48"}, {"TimeValue": 1437055598, "SS1": "123245a55c22190778ff4415c159b18d74927cc59250e9b76b08fd0d94d0166819728ccceac01c62f0d1759c7e24a02087ef571804d8e64c71c680834a2ca85b0c360f5ac4fc4ec0cab573c584d1268e6bbef225cac1336ca49661d8adafbaf41e8c2213f93138201b97210b59c90d98dc593f337ff332572e05154b99d5fa5e", "SS2": "16c824e60c1196d5d8b41b64df8fed2518ff042a56021877137da2ff43a10ac61b5ed6930505ec6477d97d995bf885c3d5d039a196e3ba56e7cdcf6d1d36f07c137cfa8380a5ef9544180884b7dc6bd7e1607105ade4a56d70593501593585511bc7368cc66b666c29e20f408babdb68e992b135d7f5745e90984f20ecc6b49c", "DATE": 16682, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "1d7f7e51d3b1e6c3a100e81b8baa513b0e017ae2fcf842708e9fb2b9fb54ac62120580faa221bd92b133bb0f955505323db7b7bd0dc2087aa0bc0222420f51b1060c9531fccf27ecb8111fd55c33d5fb855edc9305ce3861bd596be52e6de6211fdace9348656c10b5bb6206853f48fbb8536926cd61cf10ff14666e306162f0", "SEC": "040445277a7bec3b755bfa4a1d11859d1bd0ff0595926fd486247260bee23973270497a123a86efcb12b3053a9528ecd4eafc9574eb22ed7edb1b8b90c6d0b7062", "TP2": "041a09f1ae35abe814562dadf43b2dbd9e34f73135532048864b069c1aef9ca32a20c3b57faf57578bfa8c7c69eea38e2617083b3ace8f2f1876a5b1c5525a61df", "TP1": "0409f471f9a714ce2092962701ef3601ad82364eedcc95740f29e41ce316ecfba512589d90be471db49832491378c6699a9091bf9d6343795f597b714f62932a86", "CS1": "0408d0edd194dc7e5924c172a7185118970c469fef2114dd3c21e2bd227096eeb70e906d7162929ba8b970bc1250b993ea8bfe5639759d25ea7beb4941d7950b4f", "CS2": "04003850cb7d8424e938b7047bfe48a01d1ba0b7a28a17167ce343b1640920ab6420b8decc6c3e0961e54bdb5c146d06f0bd4a66697a7b390a7e7dadeb50494bb1", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04156af90f95083b31b23a5d57e02c57327cb8c08f3feffa687f5a17eb9d0cd2b817cb93d2fefcfd24bf4e9fd7e1cd6f333031ad1421cb7556da12dbeb383dec27", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "04226400583cb132db788840ac3d47796a24e1a749f357189451e28fd93ac4b102046446e0cf34862ae484044022e80884526878442fbfb43c2c4adb05e6bb2ff4", "U": "0416f31346151962a3ea76a405957f586058be940cf6b35461c2c59a63fd8ad3e4029e88f6e85147da749d5d6e00d4c8e35339c6408b9dde6dea9661b190b01884", "SERVER_OUTPUT": 0, "Y": "0b552e1f385c6520b778b311ca2b5bd797f87e2bec1a7230f06e2e8c2bdcd372", "X": "145921c66f7feec9cacf08aff99244af73a326cd894c791539354e9a0a86c51a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 250, "UT": "0401e1e2fbf9cf3501fe95424ef86e382a731af5539abb8c432a6b931ce48035180baed2da23fbfce757358f6fe856a24ba34b6c2e1f027da813fc373a00156e95", "MS2": "0e1da8a62bb0657806fbad1852f1cc1626e03b581c5e1d75129edf3f857948c8", "MS1": "208f11c77bd8b2efd3a7e36fdc84f9df2b0b9d9c890a0a27ed85829f9a912a6b", "CLIENT_SECRET": "040426d4895f21414c5fbe00367ebeb8aad110512c7b84a723534c6d052aa29b6f1c2f944825fe945980c542b59af32e7d31cca45b63939ba805c5d3ed19e28c6e"}, {"TimeValue": 1437055598, "SS1": "0181b597ab297ad50f2f78812fde9e857e5abaf17b8fba127f846b31b7203dc4214a14986c6faa8b10f00cd17f01986299c3ac6ab2144d179092dc0fa6b0ba1b15cc95dbeb93047cbec53e6ef694461d239a54eaa376ec99de5ae5f529f4d39218c268b3e0755df2c4e217ec9e020fc997a26c4c405b826f33ecd71728994a7d", "SS2": "15fcbab680b1f403a2475d00a0a72ddd4dff2a5347a3fffa5b3b094e627e32130f7b03b0527b4c96b1de6e1d1e6beb2de6ef3d55aa0f6cf939ada92474716ce40edbea82a1a89a6c91862c723ca39eeea19a432d0ea9c9dd83e3125db06246ca0c8ca0b3376834073f4581162930a3783d7a84791b4167ae692c5b3e1576db9c", "DATE": 16683, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "03acbf6052aa636510a7a72a5bb47dcd83f5d976bd1782ae0652b5de60103bc912ead0931e89a6a132cb376969aa2de5d5fb33a43e9662a7e904a227e43c1f68098b804a1a72b1742b9def5ad1ec0f8aedc144a6f294567189218aa1143da82d07502cc994810c8de4f5d0aaaccf3dce54cd4801d95427d806ec1a307da9487d", "SEC": "04103560a1d61d35000b0c9620b55d7197df18c0636a3b698adbceb73ab5637fdf198e453cc7e834383488dbc0b629f20150882d5755f9df305d92f51298b70dff", "TP2": "0408d51e947e89d09c01a6874858f4bf3ec487cc4343a7f54b9a9974c439bacbc603652ed64f1a2f5f27ab1b7daffbd1b7382cff1f4331da3fc55bc30dc30f8eb9", "TP1": "040511f2e767ceb364b37fd7c7423d6338d684442aee773b1670421689a8310261056ed151b24bc2f5e6161b2298f969ba662508ee2b9720af6c4002a24d594cc7", "CS1": "040546f23ea6095513d2a99eddbee1a74074f0a3ad61e0ff1458ab28d59ec5f4b1232e71e06e6645bacef0064d5703b7a0b3c4553c91157a7504c2e08f53458cc1", "CS2": "041a0f0fb1b0904a2449042da0dda5b8e2b1b451d76ddf1b00594d86dd10637e2b0e42d8f36d7aa78d209a62b7a72898b8fb50f4239c2e6e62946a7603f84dc63b", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04085cd9cb343b3bbaf85ac3a502284caf85c86f0e76169dc6db1bfd601ea7620318f3770cd72f3f3896f9726d949b425ef26cacde7ef410dba39070e3d13d238f", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040e3e0e41a47092b3329fcabdba2d7c0e8ebe8827665c07e580d9f60e58ea9cd11133f17eb4d84747f845130e6c7d9d4baa30d4d28c218fd8d082a211530332a5", "U": "04148e3e746d4f207fa5c29b79799df8e7d5e0df6f3209ec2bafa4fa0d77cef71614b7e46d59d375cacdb410c501b7399394928ca772f5b50588598dd5e1c8691f", "SERVER_OUTPUT": 0, "Y": "05c71070427891840e6a61b9aadbc72f8053db4d47b559bbb36cb61431720f20", "X": "1bc83ecfdffc1f9c81bee0a7fea2c08586423de2ebf211710a2bac91a9a0f81c", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 251, "UT": "0414b2db90dbf95244eef85e93fc8e08a0b42d6cc07b36f35fc5529d5801e15ac10acf2454f9cc93205d28b39864686298483237d1dcde2d7c2dff861f8a183774", "MS2": "0d6ad64e1a34f6f2c12f056b01322bc62b89b509a8337ac847b4359567058936", "MS1": "0b634cb0e1984b4e0048de167fe51ca8db2460488dd50ef8f9950e21c6b7d9b2", "CLIENT_SECRET": "04127e7bcc48ba0108cfc2db0e976683556bfb2bdc8c714af44debc16b66addf5e0f12aa3f505f7b4f112aaf54bfdab91658f9fe97454538e0323f43588bbeb203"}, {"TimeValue": 1437055598, "SS1": "01c7719d68df865fef363eadfa1920c862fb636c46886bfa2bac1234eb36181c00faf3bb40ab3319866ac04ea8a509d9c18d501e002d10a31de2383743a3c74516e90759aa96bda1e51dcd67f7e4d2ceffaef96423eaf6b14e68a521c21d06ab237e2f6c3a7ee79d966efbcbb44849585a6dd725ff4c9b980db5e658c0609ded", "SS2": "2210bbf78b53aa683237edb0681b5fe97651390cd64b50c2ca41660c0c86a0e70e279e9c3ac08abac668e324709aeeac3463ec0bdd15946af360fe1718ff8948079a802af12f6d8cc161367b345f2f1dd80a440f14de0ce3bedbcd8254691dd81beafa8a6c22fb9a80ae5794559a24bd4ad6894790a302cc8828ca8e2c003248", "DATE": 16684, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "03ce32e6d2614ac9a18904d959f3373905aadc4fcf7c55fc6daedbb8ef9af17f218a400537a42373ce27ae816c0e747da129ed3681cf0f01a6bf9853fc45d54c1e9cc2cd8e3c3c84732848f3691d65afdc991fc1d6c5a1a98ca6e8d37a7a553717fa349282dea6fd3e26143f00b109d41ad75f33c1c371ec620e55006fb9ade3", "SEC": "04097d99662d9d5dc0fa5096696f1e202cfb14002052b6509a2595481f47ed40d212aba0cb5170d005e64f520d9d4cdf1011660acf05f728530801e02d600556c4", "TP2": "041210557cca3464c8fd8d555c713a90c8d920fbf3d556a1940efd274c83c0169c028c2759b211e0f7c289dfb6b5052a95d84d62d2c6373855ce107c155cdbbbad", "TP1": "0415bc119a7feea8e4e2673c5fc8df4be28cd622aa7af3ae64d5e6c31551f88c051ae1e473442e02217b5578c0625506a3549b15bcbeeeafe36d7eda3e3a1018b1", "CS1": "04105c9e7b4e0e440a76e57dd6f39a276f71bdd7b4b72512f66fa45d97d8d75524029472a2806fd43b72fc999ce4a740a3837cc3ca9ace1dd37e86d38d40895fcb", "CS2": "041cd095d2713b434cc7a6fb84cd01aecc6c39bed0cd9938acf62dd78c27bec81410cab1ef0e496f97d1b202c19c33352bdcdbabdb467e6ca07b4bdb220d3836fa", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "041beda639dfbe6b2f0ed04a251dd8d0c1637ecd45e86b3759613f4cd8defe51680bb4f636ccd9466102cddc883c4228db0d5ec420752d131cb01103adf0c5dc78", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "041c352c93aa33824eaa71d4336472a3f5db8686d5747a8b398076644a8d62f56708697b211c785618bd365ae49870492cc79e2fe6f1f038a30ea74887c10f4490", "U": "040c9653e8681f182a9387254c0c5510b5a6041b1684ac6c79e9fc3a314427c49d0ae912f78a1f7f1f9eff51ecc4d8ba3de831f3c930e4ceb5db81f67f020ad604", "SERVER_OUTPUT": 0, "Y": "09df9dd50babe11a4c32f683cd492eceda77a4dcd96ab2353cc59d0776cb4cdb", "X": "087567188f92072b92a35cead7d19949027cc207cf7808c30874a69c9c8677de", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 252, "UT": "041e62f7cf130be02ee2dafe8a3e5ffe8fdb998ac1f21c79c617ecab93fa39d419097d3788435a055acbca69e9ef106673dada888e10688ec68c35873b80aceb64", "MS2": "03955d539b87382e3935a252c7e6be908b4899fc878c4b2923b47b9e16584822", "MS1": "110d5f5f3aa54ecc98a077f7d3a834bb1344601547383a419474d697914a3fa9", "CLIENT_SECRET": "041f8df27c139c15720b1d9143fbe85962583abfeac34fe70eb5db874494a0df5801456e88e9fa3d49cf0180e80fa0aeb610f5aeb9dfbc9c4a5e25f4f3e7b95f7f"}, {"TimeValue": 1437055598, "SS1": "1fdbe2701eec12ed9e08349f0570cdb4f164d5fcc5cf3f4e3ca16bf07e3324990d35c8a10e29be7f8abec49696bfc4942824017e34a689f697818ac937ef85fb0ef383ebb05a1baf88be5212052929319eb495d73a4b6e278fb384d0bd4b0dc20e893e52864d4e7936a72f42b755902d632e1308d03695d824a31dfb0589db98", "SS2": "0b00e15b8f70924b2a35db569a27600358844959108acab0ea8c2c5f24c327de132fdf77d322922e3e9f2ac07c97ff23ae07376991d27a4405b3f49bbacba6821caaf41eda84aa20ba5769081fa65c7a7872e75b408c82a5eb235a9bfb4399371a5ca11a34426e62b5a99c322a7be4590e2f27ea3e8dc054f543b057d9cde9a3", "DATE": 16685, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "1e413093ca4263cdc5df4662e8195ab9de84c6c6db798bcb3f873347b8f16d420a7178724f5b4aa0c247512de31a64c877dbb014fa7f8fce3a5959e670cb99a4138ebda2b1834d8e228544b6599f270335a5478edcec8610d68e9850e2ffb97816ba9d888cb8ed75a1ba8fa4a350a8fe50a7e126bc0c34431f585164f8b3ea18", "SEC": "040e01e0680d1e28e9746dac692cdc650a86ca8f7af88e31a0492a96dddfde298a1f18745c42c4e0618d7d2924858f7ab065b318a60851245028039be3657dbbc5", "TP2": "04218387f2f946c15d3334a09fd5b5af09fb2c1ceb2028e2249702c1d5bc991ae519f8f1fe6a3e0fc4033b6fec4a6233bf26e290fc14b3e28f8cb9cc5fab4d9ddb", "TP1": "04059a04625361b934e3fa3e596a9342f892fa0ac566a653b7647a4c30af6bc9b20653ada40a7ced2a0e4f2b5698acc205e2b66109e0d11cf456e0bf5479386f1b", "CS1": "0423dd86f509116a72465e0582c160bc47dd789cdc5b4d4741e9ad2a979ba9a275017452ffd3cb97564157a0eee9957add0aa9a92c55a5d4f1cf6b2f17b4621fc2", "CS2": "040d14013a5a902b95935e40465d895aa5de9fbb9bb3c21b86b712528964e91d931090e4d284c6ee3329b2f9e8d644ea9ab62466f3b0997e3841cbda4d6c717d34", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "041a110306af3caf808ee04468ee6f1501635251563effb880b00b2093283c772f084da3d29cd6d9d8d237802a3f7823b43583dc1810ac93bb39f7e9f48645868e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "04073431a9ae6bd7049530cc64b773183a3893c5642d57fa650378d660c4e073e409b9f0ea827b8e4f44a5a9482e9f4605c205156bd90bff6a955c3e19f1fefe2f", "U": "04140a23d473e57032ea9ec6f7d89417d8072bf35f877deb1d0165e50b10a5ddd003a97d31db3d0f5f55cbc76c77274e5ef19dfa9937e84b8d9487799d4b318a79", "SERVER_OUTPUT": 0, "Y": "0247349ab5cf3072893e80cb1a46814a407c7044ab8519f78390d961f8788929", "X": "05449f3b78ff06b31447ccbc30fa00eff4402a4373bdaa7a55a2aaedfe36e4ba", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 253, "UT": "0402388dcb889b87664949ca4c4eeab5a4d87cbc8c8056f59182f7f47f1d004e9f0af939fac8f292c6114d1fad51df1a78cb885efdd70c403f31a9f8d1603ca5c1", "MS2": "017c1787cbdd3f97ecb541c696e1aa8a72c8c22ae54908697a83df904143f208", "MS1": "10ae4b3e2f49fb7772763a360186c633d17cdec483cbbfe7036dc05fc9d22248", "CLIENT_SECRET": "0412283994ee915dc73adcb9af1845fdb7920e6ff73cb8d61789f809c149af9d551ce23043f7fd2056022e1130eed0b99dd99360bd677556f11888623b626c269e"}, {"TimeValue": 1437055598, "SS1": "2222999e42c84958badb1b4d76e3cdf8ac5d51a68744090129cc35714ff17c2d22ba2a62606b524d9508a39ce9749e8bde3e28381f020df075a796413bbeb0dc0de36eb7110bbd77fa687211e1d5d3ce9d1804520c10cfc5264716cfa6cf6f200319b87d616d6c3f99eeec76e0794a795b16487ec2d1eb59143d6694477c4a44", "SS2": "0f63451d3ce0c76f716ca10ab0bdee168dfa1de01479e038e9a466031b102cd9026aafecfa1526c984e66b5480807e4245a05e8c57bc53eb2b3c76682a2979110b0e0af7aa9d6c971d53e9783978af042806d1d34bec2b4153d0bab9b73d26380b95412dc260bc7ab9869fc13a98075f5cb0a8a2ae1b9a7fb48e092efb682dde", "DATE": 16686, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "01eda67338e071cb4b87c6573f4efb7921362eb2eb1ff0ec88dd675390bfe6fd0f4e715d5dcbe0713299da2b3a34fb482b344e0be559caf483a303b0f576e571102ab8db34118e923dd29c5c8b8476816c3447a522cc24e836865b30af6f58950b841f080ee2fb401a6437e54d65ef065bd5d4b596e5fee484e16603aac6a354", "SEC": "041e7fca9152b6d63cfaa8f527037e484bdc7493de8cc2ad515b0ee1c2d480c6fc1ac86afb322ed0feb810d02af2b2ae46b4df84d49f3fa02d69aaad0d14fb9168", "TP2": "0416061c58f91db51c819fcac870ea931f32bdc9e0a0ea32f69544853d7bb12c731d90b8869a0179e02a889bd5398e9e16e950c22f5be004c6910e7062e52dd44b", "TP1": "0420a92a8795d86f8e16611884acafa95e440ac3498b39018e4574cd4b5e7e8e8a156d437041db9970ab065908b8bf28807d78f216304fc45b0e874fd45a516b0e", "CS1": "04016a4c4a15334a824203ab6eec6a954e296e3767bf0c1c51b0f3da3ae3c8f6ec0b640d1e40a1e55a3e075583d25ef72cdb5b2e75cacc041b57210d5ce5092bb2", "CS2": "041e3063a78983fdae1c2fc6154bd910636fd1ff1a65fe0a6657d346d6a2970b3410aa7828e8717d47f60ba46621985d8aed8197d5a14141b17ea23b3565136673", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "040f870d21a98e8b37c860aeb2c385eb1d2bf980c282b5bde1334a53c97065c513164e142e5f46d99e019344e13be885fde6b7a04a2306226d8dff812ae6ac39d1", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "041d05b28e6388fbe4e4b6e6eb930318344914be42110e497ca1a81e503a401d9a0bbd01d2c3277eff3eb0cb58b59258c1e9d9ef9973162dd50135dde854ad42d5", "U": "040001529fb6fa55825033b127ca6f3cb5f0bb1c2b9da14a31f85ba880c3919139090e8cf2ed3b34f532d6cba2fccb9a05f50489f3d0de91b559f303cd7eac1d22", "SERVER_OUTPUT": 0, "Y": "0e4227bff58036157c0b65e935d0c0bae242e21952edb40e695ca95694f17a0c", "X": "00b9b60b92ab7f9f6ff84c89073404ca19080cc900e552842889875b711baf56", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 254, "UT": "040656ee4c4ea4e6a04456fb5896e20ac83387de9cf2c49319af5dc9bf91cd43960f5ebbe55ab155100f6f56b7aadc64136968cb2d15cb2d2a0fd99c7285eebd63", "MS2": "1802ccf05485d95dc32ec73f452350408f0e5cdef4dde11f5b4f61b3a6215018", "MS1": "0ef77c44ccb44a84d551db84c8ed69d655e805a9657e1ecd99a61f33cc0c5069", "CLIENT_SECRET": "041bd233a0c9732ba9247c93a97b4eb9c57132fd33d091040a3226093183389eed0d1a76843a7c0b154bcb7d45149508045f1e468e55cb9f93425617b1dd02b958"}, {"TimeValue": 1437055598, "SS1": "0032618667be87e8faa2524a74f1d15009d7ea462a99e24769e25c786b20a42d0c223095bd471bee5f81dbe889d8285286b1321b17847575954b4fb7c521313104f7a5c9d4ab318dcc02a9c96c830874f09da91fc888a42d08025226403e1287165ac0210103afc6c8e09ea45e75732cdd1851c9a492a8cb89e3e764d7164f55", "SS2": "0bbfa2778da785919563383b5b1a2967e0009994de9de14fa6c54ed47caf0ccd0493d6cf04b159bdce78af526aec43dbb2338e0b280c1d20dd145d4da0b8e0020fb6d213f0bfc922716419e7096cfffbb44f39ffe36cf837ac2c443716ccf7f511b60390145a3c18c0096bc41105e52344d2e0398f9d3aff57bf05d2a659eb97", "DATE": 16687, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "20fe31d488f6b10a55bc04649e24ccf0aae29ec4797a50e0e8fb68ad92e47e2c0e2ad9a4714ce0f429e6f09c30599d3530dc99b2a72ed60c3761273f91535dcb12236e2d4edf9c5f571d18ba28a9b26f2ce5653a1e6a641cedf6cbc457badae705a5b4bf2beb5c71d342c2d1448a6cecaf11da14d65b92f7fd39bf1691f45b83", "SEC": "040c01db9cefca5ed1a0158ba1ef152a09802346a0f92c0b68f8ec47ed3522407f12b8948ca8a5388099bcab560353dc2afc7fcddfa682b18c7396576f041b2e9c", "TP2": "0407b30ef7b319342273dbfc48208f7bb7cf11d360282d7bb41c902db3b3d64a610b4cebcb08439becf25e5ecdc644aed0aad1ae5d04f1439e492163a081691974", "TP1": "0422e42a37e72d393de9efc238c18463c8b0ec39b43080c6fd9adcb7e6c8c121971dfc815d12fa915046790eeb28279d22d7971b8f6ce70c8aa27794cc689ade4c", "CS1": "0418283597aea64f6d36bfd88fb61f23fab57d80671a5e5785ca3a22275fa6b81808a1a9da7a8ace21af90a34ff579d5d73eeb0ee5bde250d9814634eb3918d14b", "CS2": "042143b0d69a98623ffb3120de08e0cd71b782393d8c37e312949f8ffb1151f03401cd940c2da065659de286def983125d1e5d5793c2f39833472c708b3279fe82", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04137b3d9195743d1a81e98e46d179d65acbc7bfac8aee1965efff93bbe93cd52e16039bbc6d15d7870f1cf8b44616a7870fa2a31ea945f2f21b95d5c1522c6ad8", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0405014f22646328b1d2622e23f7c4a2fc984fd05ce3d990cdac3e1f5d1a9a2b830c803435c575eaf1e11d0bae9d3a07007d4a9ed9e15143ac72090b353f22f79d", "U": "040d41021bf707d5b3c8a708c1d785a42ccfdaa8a719c80b8d3ed0bfffaf43924e1af0992de7d42b68126eb3ff6c9929fa8330fc92b5deba0704b3b13085e52ac2", "SERVER_OUTPUT": 0, "Y": "1d69f49583642d4ca861bd234bd678c71c9137704e9e55410b11543bab34ea49", "X": "1a9cce56f7ced517c68890377d0013dd99b1e96c5c775174bb8980b1e78af57e", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 255, "UT": "0415f14daec40327512f479ea754e3a3d7ab625eac545636f07a3a6e88f629fa8b0a7ced99ea92b768c3095ed3e8175972a59dd38977fb17dceeea798d8ca8fbe1", "MS2": "090c0e9b1042b178bd59a4abd933cdf7f554a80f25e23ee7e9e8c76f08fb903e", "MS1": "0b74a067cab2c2dd382d964a0db5987bf7ecc103db83e863554d7f608b2bd8d5", "CLIENT_SECRET": "0401f09b18c1267662db97b8e0b68cd03e8ff5e1277176da78570952a0c90a8f050619e81afec14ede9f9d8a3ff41a3fa9bfc7244f685cc6e94cab7bbcf68bd866"}, {"TimeValue": 1437055598, "SS1": "147deb56a546f01587582f0afcf8f7eae2cee9837fc57322d229989fd79f32141cd5244b345eee6add3e65c3d81fc1236ec3961ef3d93873429ce4d596675d8a23bf2579a414da566552de585e3feeae576f5f6a26e81dad379db18feb2c6a6a1b59f7d2e06b95794e40112137ad029df901188167d198b92e95da13acb389c7", "SS2": "236e33ad72b9e1e0192701e6fe267ca7a088ad200f70eb458bfb1bd6d83b9b7c23f5d14f8efbc134072f62a3f0213b210aeb7970dfec6b3911a5b6bdbbccce2f06ea811367b75d1c1907987e6c30b31967bf75518e4a8eab397a3c7ac6e04db2148e840f0bb2307d6f9b4a9af0d101e53024f6560d433ad97518ac5ebdd2b2b3", "DATE": 16688, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "020807c41528cd4058c30f14e7b5c761cb50a51d88c5958988b98be64f37651e1201c8ba0729f379053c3175c0343bb6790c696883bf8a4a497339c55164467002dde27cbee9afde4e0199c02b600822507c13186c2163ff33f8de623eea00a90a70902f274485a3ecf30f73114bd707eb56b2777c34c57710553a53db3bdab9", "SEC": "041f723588583b88bad52190b7cbc2fdda131bf1a038b7bb6bb11b36d1e6ab3564203dc118685d6a5cde363a499453d035d95802ba6e515c5dff9fc370cc0133d4", "TP2": "041d3345d03452417f85e7a0da3f8011f41e40ad755c97d0645e88964e34367ee10a8da226817b88e5beb4d94c2442bb3f47a9976604160be778865015a3dad112", "TP1": "04020965f7d876e5c45f808b0c67a01bcadf4c56c3dd7f79b3e566c3b2ef92e4da12e82d16ed4b1f9d20d719c0ca505969484d2d9b693b724381c16e235f036189", "CS1": "0400a2cee99f86dfc8ae73cf1eb32f3a939e4dacfe48264863da70d15e7363ccee2364cf71c0bbee0524325120a36d6a8d0d0d9fa3c6659cbb9be3531584b74f51", "CS2": "04085a883ae3a4d379a36b4ba759c6fd3b5e0f77ff9b17f0d432b4fd811aaed5f8165621c3d6692e4e3db158bc160535e9baef42acd329283c840d9845a548f225", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04155beeb38b126803c76f10267aca5e2af480f1e9a31bdf1bf89b56a2099d82f80847aac131a22ab69f2d7fd6857aef14ff578a7abc59c9d289f3891fa8468c65", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0414bd84e8d698ff7b1897d5fe46932226e67bbf9d4280881a1d1a9cabbdf8abf9123ac4d0fbfa6af57e8e2aac32ea0c1cfec7125d3194de0c23b082e1f4c6ba5e", "U": "041871c7c72bb6bd8eb1be8f0bd993b20aa26e18e0cc5967a5d42a2f29c7d08d0e0dbfb6953d8e8a53294e5478e92c40fb253e57908cb6e998ebddf9a9d28bcfd1", "SERVER_OUTPUT": 0, "Y": "005524b75428e0ef84ad06288575f9a81bbeadd020582bec392555d47bc2696c", "X": "0bcfa4d9e432b6cf7ed17ea8806d93963d780824738907f96ec507360402b518", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 256, "UT": "0422206cb1857d60698515342aa145eb31dd9b26062daf07ad264485b175d53876042e01d658d748372b06320deabb267bab77e8a92b30ad60e466c68b52c14e8e", "MS2": "15b2f71efab9f570866658e93f75e056f34526091c309444f911ad905f219b66", "MS1": "0ad22bf718144de9a879148b22ea1d9938b4ea735be81d8a916560812e6501f5", "CLIENT_SECRET": "04066a028db83207c3eb88d44798c146163681586a1c434b40320f245e8dd470cd01b063e7461a107802c71d41c0c5e003063727fc068f096d01e47a0e7ebed675"}, {"TimeValue": 1437055598, "SS1": "099db012411b8b1c9d5fee92b3a08f94b5b37e079d9ea51d256aebf801aff62e0abf092a47cf6bdf9229eb6a7aba3ad599974d7e0b1666969be7699d96fa9f9b072d4116771e8a24652ff3eabe70dee896b10118e69e8f549d5fab24b44f8acb1c2b80e5fbb668a58b560ae4eecfd46eab18d6643358b0b23ade7ce2b3df9cf8", "SS2": "20e8f4d57a25570015b56c265f9e205e5f388d01a9a4cc12852b1cfd0a0eedbc0040dd4a1df83f5f67a2120fb5afe70016d0dc7fb7e389247a7fd91e3ec678b01cab3d6878b2e2225b96c70449cb0205b46c472af774fd7d921aaedf9a0a15f008035babd6fa3b078b42ad13dc02a29b7e0c5ce8875706ab64e95939981dfb34", "DATE": 16689, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "0fc45d1202662f3065d8b37773f79fcc7919807a085456e738514e2efca4090c026d6aa89b6a59fad26ddf80ef917e14da14ef0be6fe52780d733148e9abb1d8067efaee7394aefcd69ed740afa020f0cae820399096b6860d0682668f72900b043167a70a838cf440493753df59326f5346bc9d617adea8c761ef95779af7e3", "SEC": "0411143a10da87db2c883a8606798c7fb7303d3aa4f1aa179890ee2d4f5c14af411bc6b010316ee7581aa8db4713f4279fb53e01707e92e38bdce20b5e98dfa199", "TP2": "041f03d31837739488d033a121fee195903c980782c78c396aa20c1775dcce788d0524e2a3cfc0a3657202dbb3014fbc73227ef969c15aa749b7c308b4895c7089", "TP1": "041677e40fabba0296e5bfa2401b7d3c04bcc263a3c4503c65354743fe7fa11bad1eb92745e1a9644f529b949faa4d09fd5bfcb7f6333b7dbb02b82843e0db6fdc", "CS1": "0410cc5dc49a82ff51ea1b7c60ef6a77eb7b0b962f9c113404f84dfcf7bcf6f393002e77aad6de7e18f200befcc0c9c0a4344414197673e3db646ff9bcc1676ba5", "CS2": "041ec5c5443578f52690cfd1afe75ef3b118cff4e2b62962ea657c720e6e1e9a542038fab73c102e39b8a34e8a9a5efcb96a3d6dc4b09edd0309a650af001dba9f", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "041dc15467f7c75cec9d50c8f6d7562d8b76921f762d831a78a9ec625376abb5d10d850707549ed777ea52a4c7d0093efdf10e03b5529c055ca6495a7c591ebfcd", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0418a29f850074cf6d743e2c34386aba7737d1113c36cef11b77ca179333614079090271b34656f6bb1a0e784edd305de37b29e20d8c6049b8331952eee3a39fb5", "U": "0418a4a9971f764ad072c87593b80e80df9f09b0564dbdc0a35e93f6523e6d31a715d5925742f06763c2f3f50f0d318bee426056fbeab45fc2e232105207d8aef2", "SERVER_OUTPUT": 0, "Y": "19f437985d5df72812945b2a0d235b33d24221b92be001bc7b065a75b770041d", "X": "1693532fad5aca84d0068d157c0c881ebada11961269c84f2870426c7050ec59", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 257, "UT": "0418ec8a68e1367fa31f9c5d28bffa454b286067e72f495ad4164f8c1e885c47d40f1c3e181ff8bc27aeefb53168bd53b03be2a96f7abba2331fbe1cbe0b14ab8c", "MS2": "086d3bca4c8bb15436967d350ba1532cbee323f2b56ad3b405d8ef9c9714c1fa", "MS1": "059f73160ff923c873747d85bef91b0925a4d37da4ff300ae63021bf952e1176", "CLIENT_SECRET": "0419b8982406934d33ab871561f9f08f71cebf22b63cde43d56e9ef988a5fe68ba0c15071410892be18a951b7a4090d0b0622a0f967af530d0b07af25312cf6f15"}, {"TimeValue": 1437055598, "SS1": "03025fffcdc27dd36f42eecda87b6396945c121b7597927aba10b5fc426dd4fb0d23ee5708a7f2b5a2f9983f9ea6f8915a7b64dc41acab23dd36874ad7ba8bf91af06a04b8563aec34fd8a5bdbbd6924bf95c1f88441dd87ddbcbf5dca6f5ea82076c09482bec43f2eb0934fad85b22f532384ee68a853f7934118e8721a9d89", "SS2": "1d196a31fd7905d40fddfdba0e482901f9188b8638b9e5bcf240ac45993de4e508961dffe8b019e051bdc1fbee76beba7b4b179d90ecebfe6a99b1bde65da388224197809f68b988c74e545d6eb5d87e8c4b6065896a348392b9d4652c784073163e87bcf107e9206e36c8bbef0fedf900eb2f50a50c4d5c5f258e78f5e47d16", "DATE": 16690, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "18fdd72f36cfd89f71202cab261894d2dc7a1d6ed477b7eb03ad854c09d3ddd91a7c654f70c8633f510bb8c29bf0e05485a98b60d73c799fa7ca0347a1c0ffee03048954e1caedb76e3d078028d81a763b1b5e92fc652a14ef24e29c2afe9640115fa4e581f2189304a3e0a8f2c9bb3209fb5b9db42c84a1b06ff64b108b5edf", "SEC": "041f53c2d0ebb942d78b66f88efbf4104297946a8706ee7f64999514c18dbfcd11075fb103a2b16bbb63d5bacdac15c72d100cfb5516886a969816c759cb1a0705", "TP2": "04150bb4d613393d0167130ddbe4fda632f0863d6c41f570394270e2ec91e06fa11ef74bc788dfd1a39589cb4f7e2b3fc9ad9f21cabfcc4eadc42c1c384ddcbbce", "TP1": "040afa952db382d58aafbbb1700b35b5a68f63d2686860ec9d1dd6f715f4ccd806095ff0318495cf220dedf175f692f098deba025e917e54203ebcf0fc3d28b1e3", "CS1": "04182aa66c817557f805d3945e07ff3ac5a281cac16e340d25b167a4f39334cb1f15fc1ce8dd378f838741b73140d36d83865adf2bfbaf8c19feb64bb77437b05c", "CS2": "0409116fa292f1267d39189ab48586d9f9a6f68ee1446d95c349a1948c1c50adf50964ee9a71bbead548eb4bd20a72c73f800f463b85fcfaad78b257ff4e61f8b6", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "040bb0aec13ea2799cdc07d88de6de15232f45f291e5358a92990742ac305fec651d851adf9a7c8977fda9d638dec9be2f4b6e59bfdfddbf879a1dc2068f01a1c5", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0404e8babc6eac97d48604833a3b4e0e1653541022ec1ea0606a732e575b66e33a1c84e5f7f697eb6c5183bf828e0c731ad87d41790276f385a6523753c975c14d", "U": "041036bdfca6d83a7ce6b80eadec39badcce6833cda0c9c8fac634228c2894cf970b05486864e6e6804dfceef9fdb8820c1c510bac5ab93a3d3cf5ec39cdfc21ae", "SERVER_OUTPUT": 0, "Y": "02fad975a9daaa4090d11d92d2921f9bd9540f75a7d8cbabdbcbf98a55ae0a67", "X": "0d7be1bca404d3f61f4d7652ff1b4d84196019f943bd9d2a69ee5ffe3f6ee86b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 258, "UT": "04003480cd1616e69740d4731e4ee7b216f91255961c12a4d8c8da10ad2c3a588f08bb1e21b0fa71fa3116f8b4fb82fd648054d184ccbef4278ba5fafb0126f17e", "MS2": "10287078650c8678d86319e65065e9e196ae81c8b3c7c86832109fb363aae4b0", "MS1": "1c6237b5cfcf9e84c31814ead37cbb7422bcf401ddfb51cf2342dad72409648f", "CLIENT_SECRET": "0413edb37ca1101837655fb53ae4318917b004b52c811bcc0f9d20d6ac00b1f00c0200cfb683ad303d10783dedbf284cd298841d226ed57e69eeb5bbcb23f7c37e"}, {"TimeValue": 1437055598, "SS1": "078b0698d346135a7605b73fdfad54c6a690fac3b6be3e1136007c57cc9b70ac21f66879be7474daf32f3911d90d9a03c9be72b848738c19a56b249c62e58481047d77408dd79bc575fe92a0052fd8958bf345bea833dee6deba8452dce829f61c384053db59e8f1f991df63ee7435e4b0c90319b5d6d5d693dd7de35494596a", "SS2": "024fae47d0d3b14dc4e95d16eea7a27430695e83b4ea48de9c2f41c3f19bca140aa29dd077df10b6be711f560741c10c0e4903fb969c345d06a84cf419974951179bab49f9eaa27a1dcb5f77a4f1aca2dfdbe3c60090c44ba20813ce8739bae307a089f1bd733d05339706bec4e687471dbb24fc8932a876ba5e21e96f060b23", "DATE": 16691, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "1e7d7d70d400bcec5a852a0d4b5cf057f34bcc61ac565fd08779905a4fa658e6056947256140f1067ea42d54064340606936e5892ff4765187871786bc34ebb50710f1b1ddfba671e34288538f4050670fd46b45ae169c2ed7d54cc701da4fa90f7d9e91544a6eb79200d0d3a9d816d43a4710cdcf9d798f244a06c2dac4fcf7", "SEC": "040e9b038f30948323679903ae9f4c289d22c5152dc3e3cf9308979a35af7b20970e7dbb5b39d31d9d15f7b48be1f08657a671a9f4eb62093589ee772cebf72378", "TP2": "040cae2f481c369e2c98d9d19ad40471e5aa1f1f415693f0ad45ae6a1e1f995ff6130b88ecaa03529faa37629087f8b1317c8525b82623fbc5a433e80ea16965d8", "TP1": "0405e051da910d09796e59bb984952907feb8a5238fad024c30a2cea1b4709ad9406a7de29f092b6f51a10e420fd34cd22f5656a2994d9ce5a6c8bd396d90fc5e5", "CS1": "04096f04f850c13bb100e61f0eebc0402eab4b6158c05f76771c2de444ee21adbb04eafe25c31bc8d73ba46c60dc732218b81ff0ffef820127d31df4a6b01dae13", "CS2": "0406e64c0ef5ef5b19648b28d4c80742ab58dd6ba6e88852e35b6d837a3f6c93fd05a5dd25cb5fd57ccc557c17d3aacf09e29ed42a491012f4b5be87121648716b", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "041550933b4da8153508ce39bd88c696bb2c1a0b5f67ba28c1e35377d8f782b3861365a71ed54c8a2589b4905fe327c69b3089b90bed2e91074d64f43ab5186688", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0411ef3ec7874b7e1d4214779442a5ed2cdaecd64c3d8c756b11d5093488ae68e7057468d8c7d657401b48a0af6171dbf12c7b0c5242df36b486fa83bf9152d3b5", "U": "040d64850bdaa8f7578f950803a846eeff2d93a6ad2d7c37df93b61be86e955160168f7e92957ff6b97107b2931df44b81f2ccd456772cbe34a23e6cda5427832a", "SERVER_OUTPUT": 0, "Y": "1ade2d757ff5377395a7360a8466fe2c59c528a91c8594d437d8581704ddfab7", "X": "0c5579627ea81928799a615091494cab9db99b25685b68d44254d0bc77fe8e8e", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 259, "UT": "04210de07ff07079878dcd98f94a7066b4a54c24f80dc02adb4bf0bf518c3523f119e9e9a2b87aaf41dd69fcfd06d16e1cec86a2ae8fa1e1a06acd92b0541f3c73", "MS2": "037a489d4fbc4ee9331d416fde347062e3d738d2033963022e79c940f60dd736", "MS1": "221ae1920fbff9d1887d74cea3e82267871bad4d4c962f9f66f9530bb452d17a", "CLIENT_SECRET": "040a2e38379d06cbec038e2ebc03e11d91fd71d4beefbaadfcb0821df5d39c42f7046dc2ed03a4832177303572e5a98001b6c30c3cb346f20c3caab7d3d5574754"}, {"TimeValue": 1437055598, "SS1": "0fc2ecbd4d390a0ba26119a38a27e936bf04443d32f7152e4fb553be0e3a6ab10be730e4bd5f7e993078cc098f1a90307412b74db5899b32474fe9a6630655e60b9ffd98b560d028b34e5e22ed9011ae552f892c76b73e37a6318fb2180350c91762bcf1d99d404863463fac9b9310ddad1b5cf2abf815db227202ac7f2cdab8", "SS2": "206590b585f37dc40047a511393ed5babbd038f46ad94f6c7cad55532b7577db219a9837245e2506e5bca0b921d8aaf6d9413314de50889b531b96f2572e27cf1659c50107e5e54014bebd27c8c65eba7aeaac5b821631f827bf1963f44b5a6e0d3a95ccd27019b0cf25786cf3eaf1d2b9bdf05296165184a92a8f83ca2012cf", "DATE": 16692, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "1ceffb0a66f72d468ac4312241867bd9c7efc2fca1055a5e0c3c35bd28c9956f1246d0b9d2a06cc3b0840e46ee2c9e3a3026a7cc9c88316092660f8d15da088b1e0904f3dfd9224b95529b214581c36fedc0c320fc2f2e36210fde28be2416340152ee2f21cf06be897db0241cb14463da2b49fa88b3a124f9c01b02f23d629a", "SEC": "040a089a5af5a57f3d1c3b13db3b15ebd313e4d6be44495f6f603aee896b86e3001afecfd4515d2ac7df46a18b9b6caba3f03bbb6696041c82868a87b0b7beff59", "TP2": "0412be541e0ce43be39f2b0aa48a1e99f4c0009e6551686c266dd91cda6240b3751bdb7f896fa23498a1505783cf2e809dfe33cef397abd932586a684341aaa1c3", "TP1": "04097b6ebe8f3c6f6da1073166edfda1d7f6ec330088ee49b9f3f08c4466fa3ee007475b61957557ed3fb82b2d9af7387508f4a5aacabde845ca6b372e2d006ae3", "CS1": "0406ea6162043e62fe47c92b70edc37f3f2d3543624b47af6fd7ec0bf1aff445cf1189b48c9132ee60b705d2727e9b4f311627d91dec3a7ea0f8b1c1e62a42a962", "CS2": "0415c6c184cdaf053f37a36e3f08d7fe536926680e5324bc100527d362059ba519212f79d2038d463aa4edd87158b65318211dc78d8c2e7ff74fd588c90e25b4fe", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "040531a67334eb8c82ac3978978eb7e9105f3aeb00bbc63b9f40b05b01c90014251403d59a4c5b6ea18e9dedc9f9a9a680167edbaedcc759bbf2465d673e7a6938", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0420bc43c32229599578ab572b2fee399eff8bb360f5f0299148d696df81028ca821247a8490832a20e8b533942980c56ea631a1c7d9228b62b20255954bd02868", "U": "040fa70839d185507365e395f2db5f3fd1d6d76c254f9b7a772f4186c7b44333e8135d292598ff6a55ae4e3dadc5bdb8426db9ebb040d3e6d9937e5570003707e0", "SERVER_OUTPUT": 0, "Y": "0b9d7414e755c6ea33e05200bc132d4c29f82ccb94df119d01a5114266da5bc8", "X": "1380a5a6e781cfe80f77ebee04c6ba7e0376fbdd1c02f2e3ece0b64cf41cdee8", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 260, "UT": "040fc148900d6afdf7890bd74549437af39f8fb52e12a656079c441833a1866aa218b6788a500cdf7c370a5128df877303a4d99a26cb723786a1141f1dd8243cf5", "MS2": "0ff960d9dd3ed04cb900c2a86d890a460c09d107ad809b7309b1780d02c08487", "MS1": "0d46dd456c1957420e48b55f87a2d8adbeaa101f7d47523216173209c7e32b1a", "CLIENT_SECRET": "041cb6429aed1775ebb9a81e2f6ace43165551f981ef08a9909cd84f89040b8a3f23335b91a8bf6338a58b116b74afb60734511c90de6160f9484bf93308ee2006"}, {"TimeValue": 1437055598, "SS1": "16bd9c128293bf9495aef7406a52372aa4a7e24c85a2b51a9c93bd2d9cb4c90b1fba4ba190c252ee706c3c016f3ff9abb2789105a56d0e7ce3f7b50473ff37fa0ccce2a57864fc039e6c5ebba6149d861df1c7a20ce4ad915b3b46a3768237fe157f06ab5315be47f1b58a5b6e8da52a7613cdbfea2540a612df622165b46cd2", "SS2": "1d1b93baf686edd0a5d43a23b9b8b2571e44fb34ddfc2360e1b0eb9f4e2c7b011ddf85cfef9c740220140a9f5a98baca1f4045c6e56c9543e9c30fc0650b83e0132c78e06b1810517595d2306bd14f45bf77a13b3128e06415e110f3fd2fc054028335c0916e814d8ebe08f6431258cff527b17246c906054dcb569c6611c888", "DATE": 16693, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "0f7523ec62b7df85cfb08e8c193e1403e740da679c6c16a2c2b44697092d630c0dc3a389be0b83e113ee5f49f4a73ab72f1f08ae3d08527a873da82773205f6111edc6855aa0569d4897e37c7dc16a881c9ec36ba3c3e3f18652bf928be1a97418716a8ce96d7c5c0f904e835d0f6fa50e4d89d7e7a010d7e51867a211f9c136", "SEC": "0410c4736c63d30b24354a4fa27b7a5c9183c146b37c60ecb798c137af554988281c474c0f8a37c46c86c250cfccc272e8e1fcd2e14d36d822bdc1ca1f41293ff2", "TP2": "041210a19ad11f6f2f00eecd904177dbc21b555b67393a577e202ec4a7403d10da2077719570230166a2d15315b0549dfb140d0ff2f2b2fb9ef9d1dd60914ae304", "TP1": "0403be2a0a46787724677bd748ebe0f9a06525e3245c5ce926d6bebc324440b08a18f34a415876bc5d598ec0cff5e4dd845c986b82b1a6d1020e206a46c7577f36", "CS1": "040dc257d1c4eba599bdb162ed85640f9f0f0048f0cf9ce6e5269592b6fb817f4603e1126028b39bc25baed7891e584a2b1d86ab67cdc62279ad2853e2b938e3ad", "CS2": "04034027fdb30db9875866be4deb969084e7a6f937c4345ed3213d5bd7a2d3b732069b9848d63fd4375b726cc21ca544c61a61da94ad8d6c1e4ab5ae4599c5c7ce", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0413977ed86d2c05ce305d2b21198a8f9cfafc93e974c7ff7b1b5d4f791ea4eacd22dd0bfe11dcbd218e0f1d8a288e10e74902f8816e73d93a50b955eb8147ab87", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0404588d58e967bb8be65c533256123bad42b2b234b19b8f10520c3d42d95bda0f01f48cbf58e1a80cb0721bb2694a0962e4235e927337faf06e6699fd5ddc2d40", "U": "0419b69e00466a3da8105fcef29bd2f329860fbe34c0f5daf94398748269afa5990118f6939f79217374f0fc9c75baa8c892b87e6fcf2879b3fb51920cf22aa763", "SERVER_OUTPUT": 0, "Y": "1ee4cf43265e753ef64deb3204e2bad5b4e344c281bcea6240e9428d6ac0d79d", "X": "00491e82bbb4eeaafa154b7760c32382321d534df23c9180e74f27a9e2675749", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 261, "UT": "04163b9dd9e8c72a00eaf22c7a50d8bab9a59f1814fd23c5bde9aaf0db2c4221c01bdbcc7fa5db310dfc70f51555e162b9f3adb7d4760fb40ae6f1dd75f7eea54a", "MS2": "1ecf19b805d39951be58f3013442bb602fdc0dccff761bc3d8f1ccaff3b37f6a", "MS1": "0c8da0ebedac0f8c882efc6e6e9382aacff166b0ac375505708b2ce92329be4e", "CLIENT_SECRET": "0406cef4e32dc9460bd173f360b61c9b2f9e2a875c65d2fd3ed16c7659f2e78ea1170286e744586ce35317f122b7fb8f927afe013deba70d75a081c06e9f7ca4d3"}, {"TimeValue": 1437055598, "SS1": "1d0f377a2129dd18c503474f075f974adae5469c66a1e5c54fa10e97141e294402f0ee81ea22b7dc618fa3a5a347bff68ea44c3e6598529d86bc5d602278a8ba164defe5a3e1708d3e9dac66809135f202b498076c789ffc3b3a26dda23c5dd41bc53b7fd20bd8946c5f1d0e6ea4685961d7ac85400cefda9c85a272b4db99ea", "SS2": "12a4a67c238dc1e600802a7df307c1442ec59530d215ab512ad0b60b40ec71d0148d2840903186e986135b8ffda27d13e03abd34c97a5605c800b7f5f89e728c0e34320d94496cf6c1c2496dae2c36893edda669c2793be95edf294e288a5d280cc1ec22a023909328b90a859ac968844383b03e77f10b78e4f27005f7d0d298", "DATE": 16694, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "01a8c96330180f128bc22f101c703ec4d466133ae081b9d6f006863f65748cfb06783f863c5dcfd4830a19b6015937b169d2b09eff1ed1c11baae4e7758128a50ff59ea90708e3badbe483bcd93087cf4316cba5610eeae925eca3b20a3b5dd91969cdc1832a2dfbfa2a2155c27f20a5d273277984f8e975b08935612d2350fe", "SEC": "0418ac3c8a7e042d3094714b181d554a5adad327269ac829787a4a26d1122116a006d2794c987e269c7116a78adc79c8507b3695d66f618f4e40849b6457e99cd1", "TP2": "0413064b2e82263bb8e2f445b4c7a84067c42050f847bfe0512441206005d56a021fa5ec37cf04204ce59e7aefb6b544faab6aa5220edad262c0d799336362d8d0", "TP1": "04186360c249c38fff72293772d7e9949d716c4c3f2b161a5793bbd10e6224b2aa2338c438a49dd4935b912cfb1ce39cbf2263f0b626c817127c03bd855f925a8f", "CS1": "040eae1c2ce000783ecfb75eddf1e021df985f07cfc7eacee7d54642721252b8d61916a2992e932cf366f4e0dec2141e688ed15d4da9ccf6ba592bd8741a1b9df8", "CS2": "040c8e83074128d4efa922d8fe9acb9064787c5c2d1ef2ddeaaa0b64dbc6e0c39b0e7775a23f794eb5b07374503cbc0b48bbf6fa77f56fd59e2e4f8436d755f756", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0406cc4d487e0f97487d44dfddbad6162df49487590ead32e834d745a81cba00d5047e907f36a763cd05054738a491f598c44052c2fc3d66f7c665961fe781f9b1", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040cca67ed39413243165b85e740721269f97972ba73d5fd640169e964db7768a821045142dc6408d3461dfd58a3a6892bce62006ca784166444c7740043d17374", "U": "04195736a4dee1db2b78932ce0056c477fd481a1618629b7b152135b959b13f0e2053f7246d49f738ff4c946f14d25fd536a3ce4fd05b69a60772dfdaba79e8dbe", "SERVER_OUTPUT": 0, "Y": "06ab3e2d39cb22dc9270df8edcc41ea1939636411c0e445296972f3ebd414dd0", "X": "0c765fbecd68bc3d6160044c7158c90b15d6c102e57cc7a8f28906f45626422a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 262, "UT": "041c386377e2fe4000150793f3e13f946826d99b77ef10428421857fc362e8bc91086e72f9adafff979566c98dd6a90ca2c475e3b56b1320d57d8b92f352088106", "MS2": "06d4c0a5c32c474d7bc6bd5ffbed13f9640161034af3366d1f49d5c85ae2f0f9", "MS1": "0b4c8397328a8ca5ebbb4144c937bcb622dd341e03d7c220128dc87632947a6d", "CLIENT_SECRET": "0406fbc2a1eb2f7ac5b5012ea63a6e272e763ddb3ab9b4f395cfd598ac3c08578519ed713b973544a8a36502e3759261fe0ccff7062ac20297f0d472d252c38c5c"}, {"TimeValue": 1437055598, "SS1": "1ed06b192416f17c979bbe90f3debe040ce631db97d8be6828b1c2a3896ee1730801c01408ccecfe9acf8ab92d6697e65ba949b5e89808a827432e91eb82eef102de3ba1b3023167c0c55604fb31dcc09dde4cb364d1a397df15872e2e21ff181dd152e3a42bbdf5df22a50d7a31fba760dd2a19ed03d0728dc0851f0ddf027c", "SS2": "0981e944356f86a72a6d65fbc215e52a9dcd9bc7c5f22e41e35f636c3d6d513615e6df13c27897c0d58693ffe9771a5542567b6d1601f31172e5739dbb4ce94d22c39e0f6e0d7fcfeee231f2453819ace4a1c53b12ef5646846e922c89e38a4a0e84e09892b76069c58edfff9546b5b2ee99e4453bd4dc027586a49426e0e12a", "DATE": 16695, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "0351efd9d8161a6917e00a2b89fdd3ed221c3c28768894549ced35fe12de879406e3173e737b1e94df899a735a9f3ec043fb50e5a9666b147f877f3a4923db1115c66a64b8f412a5b0f0490c4fbd076e9976f11a85e6149a85a97209f0b6a0ea040f1e2161d151a330b9209812ededb6fa11b57e5021f29039623839e252e73f", "SEC": "040e6da21c618c28663b9207c289b0ff29827242e6c29ec5bc9e63d081109714e31e55dc5bca1c5869642cf640a4019c509827244f8132247384eca254ad55ec69", "TP2": "040013fbe12e6c3d52a40664414daf24761f3db0a6ac41bb0b34747f48edb36d7c0e38b1d830fd99b0a98a064045281789823254f0b74e9fcbbc4294db0d7bf975", "TP1": "04052098dce0fea2b9f52a7d04b5cce077c8e4dd9ff6c88ed1136163ab6f431abb0803c6a75438e0b93d36911841de6ff1fcc90cb6566c7e270c2758c5e882586c", "CS1": "041718ddd80ec140aa7623f1f454a7aa2b78cd908e5d506de0350deb66cdd7940a1c8a96aac7ab9e361fd3ec9f0c3fa8695ac4fc03bcb18b073c834dd8a45d2cbd", "CS2": "041b3b22f4e446fcd4f0de0f255534450ab173f186ecb8f2e1d7dde38f1f56c785141c94517913899913950722818e139cbd1f0d17a2f57cf9f7ca85df1deb0da1", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04102a7b2c43ca6bc02eab39cf1a3358cfc547e1341996d5f9b205ed4d58ee696517025d9a3cc1455d035c40fecb1993822b5b856e1ae1254f7c93b0bcabc554cd", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040ff56030912e29fc796764e2e6f2c0999422166d6442d75f5b49b0ac051e1d5408e5f9f025e0cb23d35f14f4317a7502250126d4ed96d7361eaf21a203cf3a07", "U": "041b5e821d346d8b0a1296116b0defed040ec25cb4ec91ee5622193f50ab689db918d0ea7079048b30c0187638123d31e40983c59158e488e214f4b0cd89ff2fe9", "SERVER_OUTPUT": 0, "Y": "018d5f45b8b31516150bb2352e714e792bf60af829d00aa15bf9acf331a4cd8c", "X": "02cd760245f3bae7b34835dd23c170a293ab93637da4a7a05ab85b27ad8a438b", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 263, "UT": "040f700613d4012ac024e3eb6cf00f015d57a4c55116d387f9c1e36a0a4546dc2f13796f0f3f37d1dc6e4d30c6c7d9736bdd5f6ff7c88dabef9fafb9cdbf056ca8", "MS2": "13f4d24e5d5e4bb0279daabdfe69b1fcb61ccab6a4b9de6ca0feb616b38f9c1e", "MS1": "0b0290e167281256fb781133649161cefe51e8ed1b0ffa23756c0c73bd796460", "CLIENT_SECRET": "0416451783e5a052ffa6199e90a931028e7d0aef0986da8fcbeef0e1a9a179570f2174de3f4811655d256ce265a99e7d1cc016d58f229391bea19a285b3f852ef7"}, {"TimeValue": 1437055598, "SS1": "15530eebf435f16dabcab1492bd29a4a3c550f598e6dba6f1a4260c0f93b4a6d23046066265422bb95d0106db0207d5de778bb7208ee68fef6c8520daa59a8f90d6a411e883ebd1f48a0a9ebfca7a1420bfc5a9699b25db759fe8ef581c861320443a45731acc3f886b8f93c1816c5fd1dec6137b22441cfbaac268e817af214", "SS2": "01da9c35cdd3a5c2af06b14b5b15b214415c1555b4ef97385493da79c224a67b10c21ec7f2fb51234fa3828df25ed2122362ef0d174ca92f03472424473b0e5505f938e538a86553746058208dbbd0f7ab2afc3d4bf4833df2b73a0bfd74118800c873599bc5063431b4e0e7ffba3bbddc58a5ba8df9995358d108cc6fb2b697", "DATE": 16696, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "1cebee9ff8846f82ab4d3f1b279908fa952b7156828565f8e73af7fc9c20210722e5e6451e887471f1d358a506539af56a61bed971470d5ba690346a871de2950818676f1af514996467f89651039cbc2cff2971d2a54336b1c2c39a3e97597d1f219f7e229443834ba79f6fa6805102143404378789c942164faabc09086e25", "SEC": "0405e6e686934ba40227345041470a4059916febf015cf53aa9c3eea092b8d700023b2050fd5ad0e629c8b9a6fb193d1b19ed5c2c57de794a30d0fb66167fe5976", "TP2": "04227334198cff5f0640c79e29f096ad5407917235c04a9650bbd23219874fa5ec1ba72612e8449aab7f9547c7823599d780640721666fdad4027ce644474acf1f", "TP1": "0411f9e38515401986a4cd8491307a9f9f5fba318df189f221fb9761eeb993a6a402d8f3ea67031b9507cd42c50b144292d2a775ebde21ac9996d1d89ab6576f7b", "CS1": "0406df056e89afa3129f2f276c658d1b5f6e411d544f3a14c04e63a0bac8abfc5108e7b6870bb7e30401222ad48d7eb294a539cedd77ba006e5a17da268e825f45", "CS2": "0415f27984c7faea6c436934eac2d60cf9d5b46b27dd951cc700cecef77098c0980f4b265c960231721421025a7cc62880c9410bca565da8bc6c8094a9dcacf313", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0412a6cfdb936c409e21e20959e38e4b0b1aa0a66f6b42d6551189867d47d02c900f186f522c5066a72490dd3e6b10a200f1c24e774c6eed2660ffa2a091a353ef", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040a93fa15c48681500ec455ad246926dcf26a90e7440ce2a339ae83ddf746c490187f286c904f46ff6c2482975b64cceb306a42950755bd9690054f675a488db7", "U": "040e1c093af6f80f1328f5ee409d2b0ef1a36b2c2bb73de9bb661d094c3d3149720be9d078feedf9e19bd23d7a1b49460a2f19b71375286ef1d000a2a01ab3fba1", "SERVER_OUTPUT": 0, "Y": "01537ebfdfa1a9fb1297df8fa1dd3efed05e8748418554d9a2a0d69b0a26c200", "X": "186a4370116e156ff78728906d150a7e7501228db85e51e2baac8f5ae7cae388", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 264, "UT": "04054bf7da84f06e339e2ae0d6bc973e6ae0b30b102a3abe6fd749634aee6ad76705216883a6f442ae429cff07d53123ed022625fbd963724c4c3f485785ec0de7", "MS2": "1d08ea84e9f1f4e758ce82e98450a1b501bf16a9d3e505c952c23666f6fd0b38", "MS1": "0c8a078138b7eac25816c7d96e4dcb9277820f2c6cebfee2e34b0e4879546cce", "CLIENT_SECRET": "0417ffbe57acf5c2e90b9e8cfd4e85e9819f45b730fbf56e3a13a863be70a0041a19e0af06030f9678d8bf7d37b8f56f0ac6ddf7accd6436621a7dedffd88a5eea"}, {"TimeValue": 1437055598, "SS1": "1db081b8564fff642a1510392452fc8c1cc156214cebb3498e4a558d1018910119a49c88cac82f7464802c5e207b6618e3b05617bb5da65ff22d498fb57571c20a9c9ef5ef9288a61a2e8c0e957d65aea599bd3bdc6b0d00b162b561a1253d320b87994ad1bd39edf12d3ebea622ccbed7b136d3843f9a33c60f45fb4d69f155", "SS2": "2140c038586022d84713689556b8525b98e4d9f9820fd8458130bb26dd4f8c2c226b565a92f65243500551dbc46fa3ea656d4ec29297fc316013e283430d9f5b0d91867a586e39e07d5f0d4f345dfac15e24efbe5abe7cb0c20e3bfa19acd62202a40eaa1a997252ed1935cfa484dce1ace38ba448f2d32890de5db83aa58b13", "DATE": 16697, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "072412f16aafe74e17697337ea9f19581d3aa477c98e85d4740a5295c284b22a16bab5f464f19973207a62846eca7fb2bb95f2017e9ec6588cd568c07b20c8bb1a062e2caab9600dfd6ed451ab4a207d7c44efc4d4585211a72ec67f0da6caf20b2855618a82161c91425970125478956ddfa2af7b7001d0c9f7ca957eef8793", "SEC": "040a210bec1fa4c0ae6816ea2173ebad7bda8a034ef8f9f519a9b54746cb2af0c412ecc8e672e26299af616d1fcaa209e29e4abef17b5b367ab7a5ab6f9dc69135", "TP2": "040ade8ac992daca6c1f459a07e311784a0e5cb7d9da4490bebcbffaecb8544dc306653aa76bb78981fa5ff36b43ee83c264c15ae1cbc05d4dbdca97c3a30e9a2e", "TP1": "0419c527fe2ef063568f5eb4553dfffc1c813b78c20431262f35ad964cecaab6260aa55121f27d2b182b8ba5c4d42360ff52ae1b44a1715318545a17a85b4c3836", "CS1": "04111aa9b1f024c198adda2b40a178b42089cd879279d7ac320083ffe1a0f2cea10f547d2a6062ff6d8df50a94e51e93231863db25e391902aeb9d1179a2da340f", "CS2": "0419e5e93637398eae0ce4f729f7f804071846bb9b1eefc1323e6521aeff9c14e21fe7bc05abde1294e43eb785e58ec569e66f920e1b8bafab7dca3bbe3de40c0e", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04084259d8b41dd7f12cfc8cd78e6e379ad7f347737fed128ac86a6d111112c42111a0bcce196713a13baf9c537e9e834e4fd10e275b1e45b0464cdb6caacb9f88", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "04070399376f9d1134fc593bf6808afbcaf73990bb0a8c3d7f9a1a09c0bc75eabd0ae3ff8e33e4121376a830ae7e112933097c36b0d90f4d53cbc2a0da943596a3", "U": "041bfc3d6439f75e700eaf4582a9ac8b9eea98612dc38f3f69b3138ff30925bc661882bc85078a689dfda18b6b9fb1d8c77cfe9f45f34edb1040a3f60adcf0a8d9", "SERVER_OUTPUT": 0, "Y": "02a297916924c4a967731d1b7ede586560e414704227b55ee5274966847c572b", "X": "150881a0a011bda9e53824501ddf19f1237d828ba9d29cddd5f1f61f777f4ba3", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 265, "UT": "041b586f5681c231cf0160cc2cc2ab30fbf8c304ec2763434532a943818bec72091d9ad0a4c0764bcc1d0d9fe3c269f9ab178df36da6648d833891bfacb41ef782", "MS2": "117df6b89be72a954aeb4b81a384809ea35c76f54e7b2187d4761a069f87426c", "MS1": "0a74f3131798ec67dfdd8e7708b0bb9dfee0c70e01f5dab991e7d7c397b5efa5", "CLIENT_SECRET": "040ca4ee0763746b1fb35bc9540ec84e3b826b6780a8b3ce091c345dba9208071f135b903fd5ae2ab8fca468d61397358f4ad5ce9521cea90a2bb108771455c7b5"}, {"TimeValue": 1437055598, "SS1": "23da239df785e49d838a40d576a95e602da621109d8f8fe35bcb547467318f4f1d25ed18cbb4a2cf62d6c5aa5f24adfcfe9fe86288644e7ed61faa8e85e0c997005962b95d1ce1717ada32fd157fa68f128384a51b351884ec9e6c979934aeec0e8b1ab50f23e18871e555f280ae22ffc1330d80c23c655be676c1ae9a656415", "SS2": "10b64df8fa65cdc14eafe56baec8ee7f1b62d72156c9313bd63fbffe7e70a94406c58e0bdffab4493c84d0c8a9d7d0e52b40af820e76d3f4216e4330d15aceaa0ba16ca9f5cae16515386d073d2b36023b630a05262ff39eebbc7d58a93b65851816cee2d50a1107c92458a5097c68162b370217fcf13b2794988fba6bf40089", "DATE": 16698, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "01488a75acdba5b21e52f57487abfceb4c8b740a182d3d48ddc978d62696511d1a21f45b6c9d3ddf29d5ec62c8cab1a923b12adc298cb0dee353c8cfecb0ea950a3966962e9d2fea97892223568967bf73bb13f680e860ae7684aef8bffc70a90f703bf54f2361698619c700e04440e1cb2c8e6996e892c885fabe2a521fbf8b", "SEC": "040eb9bc2f0b159c10f4782d311f2379ea2f8b960e59c7968897a708fb46fa1d76051a1dfb3c1beb2598e0c46fc16581d4d0dab584900cb1ef264fcdbe2073574f", "TP2": "0422d3fece24bb10bdae04f3e36b47c062ca0685e9f6d29ec4d0ddcdcc311e9f8f1d3870e817e12eed379901a7cc4a3fd63190e71b5c5a6e9a855550784fc881a2", "TP1": "040a5f1277a4548884963beb89943d37c77fa4de90ac543c3410f1fc1958623175202b7d8b680181d814ad121730ec11d9806077f9d4733cf2a811cfc247d9971c", "CS1": "040f6847d05847c404957519a2fffa72f4f3f40f91db9185110b890e1fb27db28e088deccb73b97a1e99e4f96025327d94814db7326afacb84413447356c5fb2a3", "CS2": "041deabbdb4c8db611503100ec12a8a9d300578e67ff28e41b96b900212dc29b5b0c06d68792e68ba34b8d520f05be45b520042d6626791f5ac0801caf5869911d", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04090fb5e6aa7292c22d78d1d4ea40155bd397353311ea2f6cb3fe34fc275566e3036ae1bb8ff480707f11cc1c9afc2a7644187116cc239d2a0764e54053c98366", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "04033804f5d94828131a50aa5c98c408183f469bfdf50f0fe9bc2f6da25b67df5a0028c3114bddf2a9c7f3022b23521554d85d8d52a052992e1f90d1ed075c12b5", "U": "0414a46401efd6fe8b26bdc01aa5d828b0b4d25dbcb8e0da74705b942db8505151135d7a35ceb1d71daf98fda775a9ce794e049b4d2e93932e6a87cbc6b94dbb91", "SERVER_OUTPUT": 0, "Y": "0af7e62e8890175fc1ac808a34a160cd8a0928e92e7186d797edb87ebe8b29e2", "X": "20b8fabde6542ccae1f76e19497172c7b5d9cc3cf433bb7ded54b457a1555f5c", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 266, "UT": "0405dcf95480b6815d63933d48e073c36b205948f866e2ad20bd9faf9e0628c77a16c58d6fb15f01c03ddccfb670a82fd52f75a63d0018517db03b325de87aaf4c", "MS2": "09eb1e35d89cb3a8e0ce5bd16f69c1968a3401b1acf5dd955ac40259fe5c1632", "MS1": "18906602a4d156d507714fc03735186700e650b40cdb085ce129f698f36128b7", "CLIENT_SECRET": "0403ba1365824efc10c1c71ab80a99f83feb6443a22881c5a2af07886dff7e237b0be49cfd173493a16f852358361e6fd3e5959ab65d68e973feb51d2667fa6b22"}, {"TimeValue": 1437055598, "SS1": "0b24c5b807482673ecd1b5fe554bc163217419074ecc14bf86187a1798dae93b1edf477bd72bc568c9905072d73590acfdc3b6ea68b1e3603b692fe9121795800526de0f10c5eb9a9344f0b66ce0434d30eb881161261060ff3e98a5625003a009bda20a67b3192ea1c5ed50617a205a53c34e4b40b1d2aefdeb62cf7c3d06f5", "SS2": "0b49ba128d56b84a57ff415f69585c5258007d6a31c6046ef9a664ebe78de28207f4659f8a0611796b27a7a7ecc77f3bfb0d905fdc52dffaf3153b76be3dd68e0b1fa58d0302ea77ad0c558072b068129a27b6dab93ac4ad0896f0f117c6b1a80292b687129a4d7400a54de62ede2fd9662db36a28730557215a469da3dc305b", "DATE": 16699, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "21d67b7cc662156ac7babe85e9c15e40d69546ca0c0540b10e8f7f5a162e2ddd11b903f2c758244e0d9279c25d49e8fc6a81d3a4717f02b9d546e6bdcaec31ce1a78d5504ad22e415bf4703c001ed65e871e5499d737c3d57a73cd9980327238012d3e07e3398eaf11f9289b5d417a92ee91486211bedcefd3218b95da7aec8b", "SEC": "041bfe4914a4bd526a2884ddb9022f7208a5ebafdd18b93b4f26579519cd7bdcf5227bec09b7a935a3063dd00f924044b9be426861b1dc08beb490b0ad79eb2a36", "TP2": "041855b61070f7d39d89d32329f0e156a137551b29dc5208d44b0418154393dddc068f4e543c642d6d99fa29a7091f4fc560efb5a85285b2040e6e4c5b6579f426", "TP1": "040da24fdb09c54dbf8364be4690306cbf7a6ff92590897c715aa98c77747ea0e523cb8a0e45b70a4d521d3aeb357fbd9785cbaed53c97546f320cb81e5a830ce8", "CS1": "0413cce03da3a2c54859eff484f0ebec19dfd5fc4cba0477504dd8f645f8816d17072804a7b49e11dbf788f500f2a6cb4ab8230228d663010508b61940c3449c5d", "CS2": "041d17919e2c009bfecf567d84087f913db77b4b50fbdf50ddcdb3d60095284f4e1a9f8a132872eacf07dc60725a028b79194b0538935162fa83a6de6b5002763f", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "040cb3a8ff36ea266179c5e64b7aaf1337c6189103c20f7360d4c988b0f4bb7ea10a2a24d6a15d38e92d450f897664f73a4925c53a02b7c81616111478fb485edc", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "04049769a731566986d6b017738f052d3142d77bc21cfb4e822ea1ccda22d9e7f20f02506d02a0a36b2d655aa357f6f50dc6229b6331ac283ef31b8a835cb1cb1a", "U": "0404eef6aadf8b650ed81d7da2e11579ec77b81049d6df63775b9e8137c5fc0b1721fdf8ecec3458a253bea946cffdd9d1ba9d83a85fb5d990f9aab96aad2b0a61", "SERVER_OUTPUT": 0, "Y": "22f5f284a5f81ffea465956833e36363e87e50e610e32fdf3d5167ebc8cf8462", "X": "10875415c02c32f4479bc3a618d5c12c5c599272eb5306131444eb97ae2ea309", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 267, "UT": "041564c98a945e8729d331669c7ea5ef0940308d1409301181f44337b70e2291e71613080c64ac25eac4712470d710d3105e1c09c84a368122df1d4d9000caac85", "MS2": "174cb9e6df38eb2900db986333ca01809693dadba96c1396749858120f2ab78f", "MS1": "1543c1c27cf14eb88b7009d41e71b30a83b3c4b83805bfde7429697257ab0626", "CLIENT_SECRET": "04028750770c9782a18af97615312229a6256b9d14f36dde9eab0c069ca98531130422c94a79a715ace1b49b38a83a73bccb27c4aa832664b63bded93525fa0117"}, {"TimeValue": 1437055598, "SS1": "0ebd69a58da99d6f37395431da17bd128d6da1272086b26823c33ffa4ece1f790fb1045f969824e44724a2c1b28af3fcf9f7c47ca65e93af130bdfd5c771030804fac99eaa60b0e845424ff961d2381f1730087d33ef093e6d8856c68feaf01313270c265214aac2303bf9fe84e27e892aa7048ec73d888ebfc5a73d93fc8804", "SS2": "12a3c83c26334b5f3859e8d40427e6e618b08fb120414b7db7a089da7dba93e61ed57b0aa5154aa15b40bd1f4c69d5e1e864ef451c3cbbfb3aa0275302ebb02008a3b9878d721e52e0e55d7c3f3cce645745f2334dc7643d414c07b28cc957ae019711fb817a2de79a4180672c35516f0473e81c75d08a9e309ef43dd86c7adc", "DATE": 16700, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "0064fcc7f6df2a53ca79d415463aef8657e2d63d1117d422d411a3dffee0adfc17705d2a88d1248dac253a8a7a50f996e243d05de6e4318d2e6725a1f047b6ad1ae01d18d431b25d77c8e92a92061d59940a795c4bd329e3e8b0eb30f71c896d024d10ba34545a0e6553475bf2e2473219c7cecb54809791234b2d19ea0d712e", "SEC": "0415b262818ced784ce811bf881897be12f09bfdff41a33109db9fc81ead8992c301a76ceadee182cba8c6c2f080df4dda5b15c743fbb2cbddf26c5fc64166714b", "TP2": "0418292de29f18ff1acfe92c4705c28fa67a385869c4d9de134aa407b556e8cf3f1668b279b9294a16ae54e663be3279334f2a426223fca34f6ee277eb64696cd4", "TP1": "04123a63267a5baf13e416e004f80777e0c6d70c4dd65b7f2e3ed9c9f9f74920b61d472e47d68fdbcc0acc45fd09bbb415d195007e69daf1555480701142797a84", "CS1": "0417312954d0d41f5907d62099fffa4f609e30dfc8f36a10dd36e6b4a68356ad1d23aeda1b55d9f50405e0fc83a29534d9c9eb0c87b524accd44c6adc5656dca86", "CS2": "04231d703ca404cd92aca6cc1bb4d45130821210a254c2cd0f9ce0cad8e6bc5a6c17cc5e98d51333660679bed60945722996c763e0b56b99d3bf520f5a1b4224af", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04018d37666f0eb1e77e60c17ed8b3dd6e7b4d6487db006cbf9aa2f3546712b42a1dc791461f7518bcf3c0cd2f5588aaf5fca64d789617aabd8c038254383ffa02", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "04061db5bfda6fa90fea37bf6b186afd2dc5ae477c72f1c4ab87feb5fa997d68fb18b854496d593e1a8a742edc440987757ac476669a76c32001ff684e442cc5bd", "U": "04066c076274fb85370612ba97c27ca899a04b7be8c7bfc2567e565d089d0f69600147bf9cec2a38f3023f8b927dfbfe994d2d5472e917d0b16574e6428cc3eb64", "SERVER_OUTPUT": 0, "Y": "0fe6222fe13268dda629830a2b6de9b75d52f5e84d7464c147968a348c2f5d65", "X": "10b4fbdf6f42cf1fa9ed9bae73f4aad581d9214fb5a23bfb1dd7593286d31003", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 268, "UT": "04094eba6f0d6d3ab0bc6a1d14f6ecb2ee531e3e146e14da6b1a1f3b5c4082b3a222195b44b0a8bac0008fbfed448f52914e913c3b3a29afe074cbac5fcce56529", "MS2": "01b6b0bc4705a7cf63ffc61280cfd84e847ceaac82aaf73ce704120a9647fcf1", "MS1": "06fb33583beb28b68b1438b685d64bc5a7e2610e3d25dd4d3619824f3e92f4fe", "CLIENT_SECRET": "0404585aad83c30d658be2d9e8d1cd5683f689235f19a1cb2c195e7a1b4b43ed8d0c4480f67c006aba0fb248139bc30afd881641e387a76c140c4ba9d9c072f232"}, {"TimeValue": 1437055599, "SS1": "0c419436637fac26066fb4b0b4fbed59ff7cbcd282c87d01f6408556f6674b4105d095246ce76c1d2e9da43790a42e13d2fbfe3ccad22c451d3d077b7237ebd712977959e833ee1e51d8529c8daf112b959a968149274dfa4495e460d05ba7040e9a4650ac6ae309b674ac10990197459d56a6d6bce7cba4d11d5e705ced9faa", "SS2": "0a0b2716502ab2b85ee7ffbc62018c2d80f3737d67db7239a2ca54279f5e596f1a0cf837a2f7740cd64ef7ebb205fc6342acc1fd3c3348b7edb824193e95c1951d3ac91c76a3b46529d6b55cbd12fbd6bbbb9cae4348ac00d67e6f3bbb2692492174abe6e38721403720a0bb5352ac2825d27ee7820b43e4f2e9b09c6db243c3", "DATE": 16701, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "1df08b04a699f92bf2c4c77e6959507d34c465c8633a46a215f5f64b6d87828a1ed66c683e485e101d536208a87985f34fb979e85f5f4f182f416e9cebc36309036b5e2ceaedf843bca55a20fde294a806ef781fb4b5fd41415871566359853309f3982b97eadcd8957d17f9180f60eee837b34d991c7a6bcac59ff95f7232d2", "SEC": "0416f090deb6d7cb2a869e36e3af0a35df32f772dc93883ef21e5252c64982d57f171d26c8bb7a709d785aebaeaf98389bbe5ff742f2ad8d50eccd93554793b1bd", "TP2": "04149683dc9615d0a61ff08808afce6ea73930948dfe3fb6e6e1a984c6493ceb65229c750385f6158c58a2d78d115dd132ca594917efc535b3b510eb31e7222380", "TP1": "04012480ab2cce1cc4029c7b4ff8a1005ecc5113aacc1343ea27a9e0a62dc48cf507b16bf7850f96f5a718017e3fd7f47f9e67bf0628d34b16d05f17d9919acce4", "CS1": "041ddc974bceade1f8bffe7b5a35244916a01c477e51cc6a675c5407d4b24ccfdd1b6c46b1547d0d07ffaf596fc47a2a6e1158dcb43aed4ab1372a8976901f232c", "CS2": "041548420e033d7be3b30230f95fec9276b48af7e28b02f9f54b5cbca730be21440731dffbc723ac3c92806a302fbc9a0fc2a06ef89d03eeb98e213b3c295671e9", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0408941dd0eb47a7e9ce77d70ab334a76a901cebcb81d5d63a845cad6ee176e1c3056ba0b8ae901280947467e4b99d22713c5f86517191c8df3644a8490efbd1ed", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0402b8cfe89b42f74c73a701d6b61d797f0a45d444b40644b7f4542072976f83380e6c04eb69913eb987b284ed8ccabf46f57bb87945d6383a7f4559ce641bd563", "U": "040450665e1c09c79c4f95cebf31e8da0ffd4411e1fc4de1664725d0192aa4b0b51202a87946de916c1ff4797fe963f248ea487dc60da24ce13ba24248e64e783b", "SERVER_OUTPUT": 0, "Y": "1bbbed610703bf40eced499d47a85463a5ff487d9cc3683bad91cde84e0d3b32", "X": "1610401bd44e582877f68402a42d49b31eb00f239982dae997079e41b1d0a8b6", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 269, "UT": "040e133db6299f185f77a6ae3e743fe19354bf91349de91ef7968073879e1b684e189dfb05b888e80110238d16f7787c2f1285eefc552b4c9239095f5157077476", "MS2": "15df438537280e6e68f1ebfecba24f48553493942e6e4975bef5a3744bdf53d1", "MS1": "0f1ce4643ffaea362bb317fadf609c4b41f440d09fd0cbfc70307a6569e4b023", "CLIENT_SECRET": "040c14b139054d06034a892044342eedca1ec96c0527d7d7a0b15568e3e6c453a113d6a52b466096f152c43e523260d05310ee0125619ff6bcdd78bb932c3e4b53"}, {"TimeValue": 1437055599, "SS1": "01847e5c3f809edde2edc0078c8bcd40801ec20f3d67a581f2f4e8c6774545d30287159f1bada0294092e6d6a0deaf17ead9cb4d740b479873b4c9647d259d1c0a7e4706cb011ba48cda3cb5d79596cf2207f737b5eb3afdb5457b05720db2b720c07018c53f23b0adc7e189dfa4c98d9733ac42545735cbc82611941c164b64", "SS2": "0ef101942f049eddbd1b902ca3b58d62041d5c0d8ab325a17d74c6db8eced27c11da115211c678893646a7dd0e3e64c4513fae2f0610ef6b3ecad389162d4a8e21104f6bc7979304d859d338db4c32979bd73a20e91d33f5a9d67eafba943bd71a574ca4b5eb640146de45653e530268c27eef63d58968e064d47d1e707619d2", "DATE": 16702, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "1f92d9ee3c76f099b435758bb39815c19028754433bc541fe11b8759286fd04520f485d89620c22c9ae7d90028e675782b5392af344d0f9405e75f0208d023e515ca6a03676045266527238794570fd8027b9c8c4db767695ab16da94ce1159704826213a66445087857d5803769a7b1dda453aa2a0ef3c836e4e642d5206479", "SEC": "04186565dfc0a75157352710b8ac1e8146e362ee316193778fd71e9bb277f4d7ae16bed9cc89eb3b2283480f8ff7d748f7c47dc983798dff0296c569fe7a280f06", "TP2": "04035b6afe69fde9e695b78b823d238a76555a34061a9118d77c1c7e9637c8930b007268cedc3d66747002c725b06b1a0cd86b340320a05bfe8a2149bfc385e096", "TP1": "0412bcb65df18a2db5c3fb48b5c9d51d8e92b40dfd8e143eb1511d7b524ac57f721d3715adc61af2eeb50f66a0ae549893d82f3d6e105d3cb70d963242fdf92690", "CS1": "04002885a1639b08198c7ce79ced79bc4fabb71cce6944fd60a6d256d40ce3ac5b20d790e6476497880240303470fb17c60c261d7f7668c4596b687cb29bc74b44", "CS2": "0403e6b56e86fe6f622d8dcd9036a6356bd85ce3a2c1cec21b414c1d5ff64184a616ca86f2d76dda6113b82dd514af51d2d7114c13149b42f541e38e745430fd0c", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0413219aca232acbc5eedd46774527f2ee7c8f9d7dea358dcdb693621006cfe9a1195c48afed529d30bcbfa56281fb7b94640bbb9875ac215ef696e6ccc60b45ba", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0402380d2246099c7c4340b911dd3bd5d254955dffc32a3612a53a78e681d0ca4c0bbef0fa3f15b987af963ce9b38b4cb5a9eabaa9369174f770d11e7b542d53f9", "U": "04148ce1cb0d3e309d065c25927b69b82e8be29a1b645033f2e6b2c7c0f34e4cf90e44491c49f079fd6746acb24a4576ba7f7a11f397aa259239386eed1bb2a840", "SERVER_OUTPUT": 0, "Y": "026c684d25d0efc6356a186a20a8deee3bd092303519ce0be0bd22bfd5ad5913", "X": "08b9f82ccd70cdf2eeffeeff0b14d64df53faea51d2d086d9dc864b7f7c8b3a5", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 270, "UT": "0416f7b02bd164d507fd879bd12c0b0e48e5cf26cc113ee70f95b73ea1af0a181113589a8cb38b2742a77b2f488498a07d220332434d384798633d0a25e5c50475", "MS2": "183df1e039803e09fea032f88c4d38614b78aa77b19cc5ebe6e3261103e5f3c3", "MS1": "07b1d3d7d19b4ad49052fbf9338f0ad9b975bf7ae70a5b8515421011b12321f9", "CLIENT_SECRET": "040f79d9f877919e4ebe928f43558fc9b4e48260a21b26b4281ed55c3c211c7eac06dc8abfb939c482d28c2c8a60cb331a7ce45e00174675f32102e2c61bf994be"}, {"TimeValue": 1437055599, "SS1": "19327f44042d22424856dda7f0435f532d617c1f68daefbb516b0588fa81a6f921cfa5ca0cf79652f2b3156a3120e3302333352870f5a2ce68abf256ee61ac410508f6c78055373f78cceec381478483ea9700467a042c907309209bddf5bed61b0eef960e225901c2c48711602dcd899fa8e0c08333b517ee066f80b75ef824", "SS2": "18a0599b3297b97636e8d8199b5e3bc850235eb1ac785df5baefecea19d29b69119970c1ad4c5500bfd5f2041509b762d6baa51ebb4d63fcf2b54205b3355f5005c14e9bb00a7a907bb13f8c61f820e7bb825ea19d875cbc757e00bd22ac13dd151044741cd7b8344e985c2aa19d44dad0091e1cdc8c6f132ac9f90422d3319b", "DATE": 16703, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "11f50e6910faa09e638f4ac3c4850dadf2e9affae2b28c8cf1b7537e6c43eb290622b860f6268c797ac6ed570801c231b8fee0ae01df4818439519a3c9babe2c0feb636d6aa1c07d317ea7a6b077e06424ebd2d3e53f44f7fbcae5f94831a235009b12d0f190a715b1c10070a0b54f17f9fc2ad2527f76b2806c0759c05af704", "SEC": "041620587a3e9b634f6a45bd175c8382a89742ac47948a2ba0cc1bb5f24eb437ca10b50e5c1a0a4f40b1c2314f7377976d2e2221ea66cf0f7f0053bb100aa6cba2", "TP2": "040fa8ab1c515a1762a1582454b02fb3286c95c6bb96e22ed8d953a7419e5ed9d614b8715fc14d47c171f91a42507955702f8a4565fcebc324cd0586315a16186b", "TP1": "040e4e4d608a611ca36c05c9863a34334bd76d780aff12835f09cda76285f8ec0d093af050c1ec13adf9aec4f27a7d1f7a38e6459a6acf28e251391b88770cb201", "CS1": "0415af2affa73b9137cf6b15b7b6b9b62c567a6809a2b255bcbf82c19d850cae7d1dc49ead70b1a943dce17987ad60cdeeca9846ffb9df26000c79046e61e11787", "CS2": "041c66442614397c0921574b01e72d5db31e414fc43b6d37232c77ea55492d20100bd33a5b29ea1051b89aecba11484c2e80aae88c74063fe2469f083794d8c289", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "040026ad4dd753c73a21f7b6c3763b30896a118f79f4ef609c58586b294515501d1ae446441466722c152835776dbedf04bb6279ae055e273852edeb6e24050b1e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "041336d5f9bb4b937471639f7d3187e493617d5e3a6b495bb7e52522a80f5cb2f310a7f73f8d773db5cd39a5d8c9796d41918f49588f0221fea3dc8e00e44d65ae", "U": "040f08096b1b703361d58941bd98184b85cec77701fe535db0ea0dcd775b99ebec2318f4c76106be22fc34775743610f392a6098286105660d9613c68d516b4a5e", "SERVER_OUTPUT": 0, "Y": "00e71b5b9288e123f06a7c75b4c6944cb7235beb942bb3cca9443a23ae254ea2", "X": "0288d534caed66828008f0bb209970d80612c82cc2e2cc4168401cc5fc9a1945", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 271, "UT": "0402a90413ef25d34160485c74df762357d15efce5d64ca6fb98d136d202a4b8e4005c88ca541861b091df2b18bd280235292b3808b05b7190b666c913bb5cdabb", "MS2": "17ca7af9c1b688f8dd66381f89b479326300e7586eb64fd99e441797ad68084d", "MS1": "05c1054876e97b3c29392a264dbf657d63774b71a243652008d22987a64eb67d", "CLIENT_SECRET": "04075fd3e269dec6d19ca9c15aa0596a86197cd58b66b243c90f728d0626e2a1ed20569a3103714ae421c9a988befd637609b05bbfd20f7d1b7419d830ef230cc8"}, {"TimeValue": 1437055599, "SS1": "07799781cd3291ddb7b389409f0930bf4fee5a2f7104afa7711d7389abc67a350a12cee3ea5640ca22d45d11a04544ca75d3c9539293237efb420f9d3abe14961c02e0ba82038349b9af048f67f219e4b26a4cbef7c19ecebfe5ab6df047f835231a8f7695511355e8f003fb5ab7a94fd3121ae952248f3e3aed5df6d2663bce", "SS2": "116b032de446f349ff6cf729bf14f594edceb12d364e5626c3a32c98c510c32a1e7e8ac8a72a1501b3be0a76666ae7c99b5348ed574bdff623397c17a0f8d9d00d25adfed2d5be8cdd15d2c6526c24859e4322534ce8e89e9e3977a1dd02428311e390bfeacd22fb3428470bc36e9b8adb3109ff5ee856068121b47de197ce3b", "DATE": 16704, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "0c59492c5eb38b5f9b4e723b075d8105e8390e77fc7af651895283a41727672e008ecf00de18eb398f90c36af76c41d025c4c3f5e297145962cbb0facf6fffa0196f768bd4c765eaef8f68fa1e83e0a1d99b85a637e60676caf5bdae27597f170005a11f294bfdb958d805d9f3b05c11cd91e38c1871e4c9b0906aea8df22b75", "SEC": "040ca0486df89068c1e26a64d697e570f43c22076da130ccfcd4d00adc3232aabc06abb2bb86c33d307b99b65f0b2256e93a8a087d8b6c63731cd1029df25e4ff3", "TP2": "0406cc18545c69aac58aa883373973ddf290609da14201d2a26b84b63e1c64de911f37404dd024c3860364a80bed4cc985646ac3c48a07a7166dbd2c7a45bc2ca1", "TP1": "0423c39dd52073f64e01691f55c3f0c91985df322efa8531591b8b6f01cee3665f222b5628b7732b22af2edce66736ca7ed1672cba28f18d2a85b9ae5b33d4b31f", "CS1": "040226974fb0e2c4b8a9c37297aeaad50a184c472c829791f5d125e48c6532d1cb2173190ba6b7264744b86becb262de35ea9b381f42fdaa63e85f86bb916ea934", "CS2": "0400f4c354fd190966dd00cfb196cb4da44d5d6089937d0584ae86f63ff86a47e205a46b73b22a20a225af91f04e41ca0c86c50ea0287a0875f99961d6689889f8", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0416e4fcd0ccf9ff75f5ee9c1fcc7a3c734a1da0468ed6628d78d21f6227fd297e14d9cea427ecb139aa766ceb271ce81e435ea4c59bd9bd9e6819d7226280f23c", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0402fcedbc18f273ef0c8ae3d723d1001c5ddd3de41e8b642f4b51e42761e994cf004a4501f119a6c82f33bdbbb4fee4d1f669782b02bfccc2f323c069c40b10b3", "U": "0402e262d31bddc7204f287514f1660400d35abfb3aeb3426403eb4bf2f2e47894058d0828cfa073e28a1347492a6dcf1ce68c62faa06436c066761be38771b078", "SERVER_OUTPUT": 0, "Y": "0c670ee2d115ad404dbb8c9c7d399ac088cd1458df8c998bc9d53d3f4771a4d8", "X": "1c6a14cf90cbba639181185dd47548c9a506a723c818eece373f52dc13a1e9d3", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 272, "UT": "04101f88d9d9416c35611d660a07513a612ee9ab3e0cbac50ba0aece57b17b99e60b769b74075e4d33d161822ac272198298f2f513290847279ff5173e885d0e4e", "MS2": "17682ff8c5fb60e811e2449aadf940aa760a5965933e7306b9c144ce599c31ed", "MS1": "1cab27cc84ac4a8d627cd3a50222366e9685c70a33d574c1042ca059d32dc3db", "CLIENT_SECRET": "040d982fa68b748c84e5e0cd33bf56318665f18ca5ae8c1177e40690398971b7760f4a8b71c8eeffe478c463209c4b4b24aaade96a277b466f46d78efdf9544214"}, {"TimeValue": 1437055599, "SS1": "1522d79f411120ea6943194ab37c03f8590d1f319950d60a4f393f7d4a03b94c21e9163291898312437b7f6418e314a88f517f969158e3e3487e50641716ce9b17d7a1dfe04397b80798bceb76f91f2039a63d064804fb05ccefd3800df0ac581d48482b3a0197e7a7c363289d68ae3ed440046164e64187a80e3a7cce5b3fc0", "SS2": "20f447a6f16f50f8eefbdebbd91d09caf376cf0e05e8ed09b897d2ba8e5804f61ffa57b8fce01f17acc9d7f043d16cb98e81b12cb90672e5c3a65728d697c217114565fc5fece849dc28c640d0dde4a968334053ead919c0c92c2647c0b1598c20bf443e4b24105ab853e7d2f3474566454af02356a936b68c45ef15dd87ce3c", "DATE": 16705, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "137f016693d5e3e165b29d67bb5eff56b996810067815cb2b2845e379ede982a00cee0d5e101724baa59ce9a1525e92e1ecdb742df1645785f70d8874678198b07e5c1c1164921a8d11345a746e5cc74a6becf42efe302c7917688541cc16df605a204ebf90b551c122d0c888b792c9242ec12c4c0ae2c654a8490f6bb987f78", "SEC": "040c68529025e8600a03f0ef54699f2df69deb72b29ef52e8a30aedfc49c6d5be004be9b15cd96f1095903a6b03835bd2a026fbfecc41f2413a36df8ec110d5cf4", "TP2": "040df49ee0c577ab05ee985a11ef6b96896faba7d0e2a447b8d44fd3974a0f8b620eabb0fa24534d4ae9f2bd21cc98a8130ad217f9d13c63a50e1eaad951f159f1", "TP1": "0407b30b563c99fdc78af51caa1ab74de982d0cd1d8c5e868d101aab3f2c794f6806392720202e867184e22a3fc38f4aa057572246faa12d31fc686c174496d897", "CS1": "0413fdf33dab991fbc3f9b20b6e6e8bed9062830b077c1d42371101792c8e70e5222a455548a0e34862be60aa41fb4beaa49ac119912f0a1f454068c352689c5c9", "CS2": "041430cc8972ba838c33d01132f07bec827614445f4db9f8bce08df37ac39c29ef142a1ca121d85be7007f7ad74dfc34ee3cf94b6c39a37e78da7fb4d9f1809ab3", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0423b1f4a3149a4eda89b9950705693a5810e9c235442c14f9bef06f17fd33bc1508c0751ffb67717bd0d232617099b0fb9886b1c5b977652827783ed2e15a7cc6", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "04208cb582df7771a7946470fb3f0707082bcde342dc0b6b53adaf628d4ba724911301a78d0d99bb27e111c2b439f2bf169a9b671587969f91351ace582d22d3ab", "U": "04056d98c1535feea52351d5ca55003102c6676ec84edbf05c07525b037df9292013a3680451aa85bfe719f2a1e1b58c61893cdfd86c6e673981e02dd441a36782", "SERVER_OUTPUT": 0, "Y": "0a63ea62db943e7e56109a191f152680f96e40c292ce2c8a70fc20227ff9e946", "X": "124ee274ca8845bc2047694e6c8cc92c06c4dc2916f4fddcfb60fc82cef115f7", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 273, "UT": "040b25c9299bee07ab6c4fc40d5d3feaa7993339929d718a16a30a9aa94f44461103b10e67f18e475d0ba98fe0229f9899e8fed4ca2e710e587f3e62ba036997dd", "MS2": "156aa4f8aca43383dca9599373dfa94cb225b03ce3af538c682968422800da1e", "MS1": "0d323b71f5f5bc4091a7b0c8374b67530eaab38137206cb154611fd0e2b62478", "CLIENT_SECRET": "04087ce410b883f816e61a5d3cc7ec86962d7a91a11a4f1f61e0aa7f30ebb652281313e0116d6fc9574e72c792c26860ed6222f6b178c6eff1bee2c4d7a69f3be6"}, {"TimeValue": 1437055599, "SS1": "15f974ed20b52cfcbb983169e593bf7266980036009af202fb8c0ed716daf1260e206eed245553c9a8734b6fbe058bdb61b58e6f03cd4f2ab8a1d9094784aa0106e57b5eb72685ea5356c6e6e46161dccb0886398fb2e6a8667bc7c49f04fdd10dcf68bcbed5702d06ac12a392183619b6385550cf491765e59681758f66eb97", "SS2": "00475040235869af9b9513019ac1f8a4627609d69ceb5c69fee561e5c79af25001daff4b7c838fcff9e2bb4132e458d58524ef3ae67f36a2f954cdfa989a985e217dadc5be3160a2be394957c5e3fdf4b838ae8e4cf1bac088ecd0b260864c2c118417de188fbee046dbbdb71d3ed83e0a0eaf8c2b6c0f0d593ba05898f91c08", "DATE": 16706, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "12727862d0e358a5a49f48903ec856b164e74d393a0b7152c525463a59a39b6812cab8da4955f59529f08bc967d5c207f29518c30da41aa46c0b347fcc70888a1d504c671557402e8244a60aa29a64c829193634a6bcf777484005d2acc2c0f50b8bcd01cf8552b17ebab432a7f851c7d6441c33b4238717f85f98948cccabc9", "SEC": "0404ef3a9360b6bdf861c30fe4dab5e0809f5af043ef9675f0782009eea72751be2230b44364da546b8bf404e16d6fd61acb460dec076d48c781452dce7731f78b", "TP2": "04127402b6333e8531ba4a23cdba030e69362ab5b2da69295307c4b39044cd7596193ebd350670492e6552896b71a09ea6810b0a701771087dd0a217380488eddf", "TP1": "04074d957c94b7ea21c5e0bf890ab78ac4dcf919e7c7d73b72c4e5e148d45853101555d8383235fbfec2cbb7fc1a8bdcfe3b931b9071313123a1bd4cad0a616a25", "CS1": "041557ba606434eecfbbc60c8127a92e3d8f6f432d07435a8cd21c0f2ddd2f400b00f2d625137c4be31cba0b6dbb3dc4d2cc249707efeec101118697d8ba5cabc9", "CS2": "04042d27cd0b17bd200a19325356e18ef7d7a2e599a431bdd3b744e463551e87bc1e2297b2568937984ffbe18a0a6711a8c73b136f89c6210221b57b03f0d8e63e", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "041718abba421f5b12e61d7b4a741a140cf2f66f007daad0d89481fde9f70e059a1ed4249615c94ff5fca6b4287b4fad43803cb03137b2f0282c38dd286eb0258d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "041c0af93a53998181d1e966131bb1bae2c2ada017f284bf9dcc3f2ef05275d3ad15158b2aadf458cbc51ba785f0ea1a11f50a54f4214eb9c1e08e4e7bb028e339", "U": "0420b940b8d247b1277c06eb7888b6453ff9d53e19a47412d20b32533ec3280f1721b30fe9e8086d49ad61322c85855b15aee719fd30e641a61b62a95e85272376", "SERVER_OUTPUT": 0, "Y": "0227ca02ab504201c0954680bda4d1f45dd39a38d81a9901c173c9877f2266af", "X": "0decee8c483d57d24cf24ab76a8a93edab5056791bd9a25d05da44defebbdc9f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 274, "UT": "0410558511019b75f95da52515470d9ff3c4533eb30243c184ef2f7284660205c3005d2bcff28a6fbf3f96624e6c4535101496fa9fc2ec042ccf70a35085ae2c7a", "MS2": "13bcc835d4c514cb657cc0f5483c82a1602f2be5992287c908bd05057912d8da", "MS1": "0230cc4837e4f1fa390f825346566319fd41b2fd90690a963f2974fd56ec072b", "CLIENT_SECRET": "04033d4bd5d08e5f0c9e5bebe638e2058258dcfdf891dd159e6945c01f823432db05dd838dcc2b784c8a49fec3d363be5c6428a29085d7782be73464679052139d"}, {"TimeValue": 1437055599, "SS1": "0bbe132aca41537fc1efb63ce9f438aeb8f13bed7e83f2b96a976a56f144b3fa1cab3f7a04f4fb4cdf955a97b78076bab7b905c3acc431d1b45b1e3187e311eb005983c5127bd9b39050c24e3b29380e92dde2987e05cd935f81852131f820f902e18c66a2ae525ad3e74a9cc5bf45398317055830a3051e8cbd3af2e94648b2", "SS2": "18ed8ddb7212d37ce2bc98ec7905f4d0025aea8948d9862afe877f86b2b59a0b1bb236c9a435c9e5833ffbaa714c49b00e7bb7c507a09bdf3162984778d19734074d265df8a7f6eaf9083c09c43999b6e80b22db91840f4f92f50130851e83d2067c74d72f96e8956979cdeaed25aa895b47ba69ec4d406caf28d0e01de8febe", "DATE": 16707, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "0b65d6b93cf31ea7b653b1caa7ebeac038081acfb92048d91e440acd80d89d4d01a0d8a3447e3fd1b52a2978f7ce14905f463518430244a09073156b085068851bb81707aa7014697eee28c3083975f0d5ab75eb826a4f896769846c7bf9572f170c1c6a9647396814436626206c1ebfefaafd011322b16b8a5356a65b0c4840", "SEC": "042295226946cc92c41181dc7753dc32f28fa4a81f8118c6fc2c7a35f3accd57ad1113f203f12aa8d0b4ab73915d2f3d9213f86f6a038479cbbceb5593a37c8374", "TP2": "040837d20adbaaecec37a9ff538a93cc1cdd00173e729e05279239d1e4e70fc442012e42803f29c9418981317a64a2d0a6c4dc8af4b079d3887bd6a3b844e6dd81", "TP1": "0405edf31fcbec97fce62ed982a5baefd1deedfebcab79f0108843df6f50477dfb23c7b5362b78b27780cca76ce654af54ffd9630762584b9fbabef4e548653743", "CS1": "04170801d41bd87be637a46354aaab1dc74d4411c8fad73748420fcd33dab4f37a0c5ad04bef3827fd478a25af57ac43603062fb8a9736fe2c05a1ebc584837988", "CS2": "041727294611cb2e1afb1fbeb249a8b04ea88b2c61bb4a5dc27621d8488cf66434148f005288182e4b28c2b3b9a0f3658607d5dbc73c1606299501e2fce421627d", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0410b625bb4ebd484d1a273006d64aaf5846cd7bd2c0cbbc62e0f21af3fc079a0d0c7e84be97fdf88c9fba450f4344955ba8cec99ca4ab41042e5c84c2b5c5cc88", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "04019eef30a103a693793a661d727ff378e5011bc23dfb94b54e0ec849999bfc0903c052fd41782c22388cea13af4a85838af5c9bef2dd1dfc5f0c5237d3f3f521", "U": "040549326f9a711e447d73631132439810b601526df33e2df73ad2958f1cccaccc1761996a792c821006f92478dbe6f44a5c5a20e79d7f0664a986096b83f8f81a", "SERVER_OUTPUT": 0, "Y": "0852ecdb2791a7e879f58590ee01fbc8639548bd2683f3042b78f21e33e74d24", "X": "0eb11c77c815e420767237e6361cf39f67d432e28e7034750322746f0fc7adc5", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 275, "UT": "0403b6a14df1f89265744e5f62ee66b11ec5b951a1fa50f98af8dc3b590a337acb0a5c28e4c653f5058ed54f0b3932a67ace1321765a4cddc5542f298ef7e25859", "MS2": "203719adc2dd6a5d3011b47adfb27b2cbd6f84c8d5be71bc465f64e14c609acc", "MS1": "10ac6953ac96d86d0258d385924172f2b311d0db5e92120b6e4b2b365e5256c7", "CLIENT_SECRET": "0413ec00084f2e148ba34ea2d73441b5bcc2b034722f016c59d50f807a596276791b6ffb7c7a29f6cc19f4400998e1b8b3e75ccafe27f6a7977003d2372eeebb68"}, {"TimeValue": 1437055599, "SS1": "048d8fd1bbaaff9887f7ea04f3e00e91a06e6c8ae35efd16874d91f2678ac61305dc5cce0cfb65999f62c85944f888c372f89f5534eb21391074fd1e9a6bac8e22995b59cbdf6bc39ecaa34b57f20327609570c71dcf513f88a6b29bb31093381fe5a173b0c6243804afb1e7436466cc3e211ff46253f1b7183c3b7f3d86c66c", "SS2": "19d158323eedb8a431f60e3d914dc6f50cd06d77f2af56cce8e4c83c2450d2830032679f4b11977777f2ebd41c9101a635074a0ca895e8b8b53e7433d5ed74da0c98ba15fe03f3e398c973a5f48dede7222025e7efe8b8024c497dda5002fd7e053e39f499bac374387caf3af1d7177d9f3a5229896565b7a39e8b37183db924", "DATE": 16708, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "02bbc0882a44ca2610a0b1d202036eac20e89e80d4e1b34cf8b62335adc9b97d0ce8672f29e53e6b49c8a12f2e7398dd1ad00b3ba18bad04d1b240e3a02faca405c947c96e1d69c7c6bb6ead9b142f73c628ff7d672a28e86de7a2c7124da54d2217d6f23781a4fe245556a6aec034c98d52c468475b9a6ba310e67b461acabf", "SEC": "04051e25b7780c6aab5d9e941c1220f9ba691c807b7563f8bc85f7fbd937c1e8e60f2534bb7f221869c3cd4c60dda65d32a2493a0c985a48165b4b8a86842bf9ae", "TP2": "0400216263865b6d3102b0f7e8cecffc6e70d2627adac4aec668244b0343eec70d1159bcd4dcc868d726d2e039e0ff5363e01d8e5cca8723fa592246f1ee110640", "TP1": "041eaab429fe02f070c12d05cbacbd8dfc6f5d56da68c21a153f77e1632b5d057f059984402b31e732328c1224003bec0135d3ec63f660652abea3fe8b207ddbc9", "CS1": "040f3014c0f54dd629964ffff34a411dd959d69b269da49ac98cc0d9448c54763604766f6503ebf764aa4962a529e09b86c3f6168fbd80c46394f64e8cb78496e3", "CS2": "041facbb0e077a488d353002e6fe556e591d34c021c374a7735616fd22df9e8a7a10cfabb0f7a1870e773af80eae0dac5d1eff6c8d1ea81ce2becb94fef227d35f", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "040b0975a73d7eb75cb9c5c90d3fe974f66f1e903739bf811584896b6639eb2bd806caec44b7754f2854b89517f595691e70d9d7187a6a0b0e9f6fd617a15138f2", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040c46a02d187296d0c05941fb6cb4ad5a5eb04aa8675ee58ba8c63c9c22bad2151d3c1826905871999b5f01ebf9c7dc421349262d5f69f1ec8be8f20d4b984246", "U": "040f57d9337a078b33a269cb802ea9792f4e8cbd099f20d5eb78916997798b1e2e20edcd4c98cb5b4a5a9778af1f5896e213e837e6fbd3925b307e93dd33e0537b", "SERVER_OUTPUT": 0, "Y": "0fe5c385228d21041e886fcdb6650bd5649084ce204746ca5d4bd7b3b5a53048", "X": "11653fb17262e31cebbd333a9b0b2ea0e27c77a53d4e3b7c89dd2c7c9e716c63", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 276, "UT": "0415f046a880e5a6c3b2ca4b83528c81788970ef9dee1eeb8e9f84c37458a1421c1ff5c4ec988c1cb4a07ca8ca3eb2b76194c9fa4f9b18c89755d77b3f4c1dd755", "MS2": "17f307f43889691cff3814269b78af38cf0ecd3c4afd588156d91beadf1c4694", "MS1": "05cd2774f34f7a5b52aa6f15bcf265d09f6071947684cca146ff7fd3617d062f", "CLIENT_SECRET": "040c7314bc6c1879e534e5ab592683cdaa72130d2bd95b10281f30eabc17649a37130a353d53f0ac530889b1058bd937013d911f743ec70caf1b25e19f12236d7b"}, {"TimeValue": 1437055599, "SS1": "156234dfa0111d95465033e515fa2a5eb51df754e16ab049afbec52ccf2dc6c40af74d13b770ba317cc611cac77d3805ffa6c153f2f30c64d0d860137139b8c022e505022e15d228e1f7d1701d345d7053df6e2462a22fa1b9756a3f0fdf4a6a002737603f5fbb98ad371f9de5a76bc2a39643bdfd1fb513aa567c4cfb3017ea", "SS2": "0a472095e76ae4596de509a4f391bac192ac9043795b0a3ab855e6874151fdd000f91a1b5d9cf0dc5bf0c2d2459453098c36d6cc2ec9c5a79902c9e31a3679b40c19ef131b7d86b5e93c46b3c0df887443140a169280cd7fa541d00d4f0f42750707b4bad4c3d47bfe3478bb62602cfde0046d683e822df679902fffc1c55298", "DATE": 16709, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "115a0c848f998c1f48de9c389db0026b5ebb196f693d5faad943c76d54aa987e12a17ce6de2dc0951340fa454528ca27bb8a13c9925cc57296c636f78a71e8ee1365f62b0a656656d7af33cd4b7b0d5333ec6e73a7ab79e612f3728fd48dba92001ec68b9436f7d63c597cf1900a12ef52431eb246eb3303cdacdfc1f2a43897", "SEC": "041dd7f56386cff7c35a405aade20ff388aafcc06e4878ae3c427ccb2c56443e50008791e9fea8f7a5a785bd18b4bb104f39ab22530abb7734aeca5e5ba61ab8dc", "TP2": "0411140f14e88646659d670c260a8001935fe64119aa5c161f79e40c49ad3c9fd304539a9f5818797bd01810568cdb03bfa32d0d94e9451e2726cb7f16065204a5", "TP1": "0417b113eccb94d87b8eeb8a52b7085e9b246ac0f77822ddc5480070394cf9c14e1a1ff05a5811cf33cc21794d965298da34863c1edc81f95296236a83b54497c9", "CS1": "04066625cbe6e3bfeec65e3c7b237da50ac52e040009f07b8a22651910bc3a30250a58cca19784fc934bc079809c4d00668586de0d9a614eb0e781b7618a900860", "CS2": "04222994260a1be510102dff877f89f1f01b5b1441d29789899f275a2ffd6c62c409020e005878ad0c798f9f0b00d70303268896c187579946f4c46e1a0f18e0a8", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0418c86c2fcc81a719aa5e43f7f2037dcb0c358b5927dedb591b1e122c275cbf511c434260adf04eeda095eae3b4d92d2bdb33e345ddd07c1f56b5083c8cf774de", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "041bc7e2ee2933b6a409ff88f910c3862bd1f00345ba8c40a9d65a81952706279e1ae9b87d8d7c4e5371aefe0e26253524cdc1c7144611f6940bc59ee5417a1785", "U": "040d3aab7010fdcadd5fc58794b7f23dcfbeb8f6ef78275825ec24c261f5f6452301705dae63d07f074ce21d3fc3d3c17039fb4a4f3883090c08de99601bfcc1be", "SERVER_OUTPUT": 0, "Y": "0888f6c94150690fbc23643bfd6c156d7f4a7702b49885b807b82e817b87d8d0", "X": "1ddc57862c68f309a1dac3ea69fb067be75168e72049b17b2fa33e819b285a09", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 277, "UT": "041e0c62382c1b48f64fec740ad7c5dc62335294fdc7a011057ac5d308dcf3064622b62dba0fbef9be29a590b2addc89e0e324ad0fd0f9036814522604d8918f6c", "MS2": "074634e1552f0545537ba5904f40c497e4e33d1ebc32a088fb5c8fedb4e19bbe", "MS1": "1dd273153d1fc22a4a89c8f0af3d55625402ce913ebdb19fa51d1c47f1bfb58c", "CLIENT_SECRET": "0402e1cd060fc0f843b38b47ce6c2db99b20e0232042e9b86f8601162ecc8f187c10b06c5a2672841509e4bd303d2403252bd58a7ff98d01b2459c425f84ba869f"}, {"TimeValue": 1437055599, "SS1": "11e5f77e4e61b217bc5d6099c9af922dd5cdc325ef56e0bd95a1f47021a4321015f9e2b4d526c62557e5c43236d9be5f7a4ac0aadeaf8e80b836a5d13f22b7041a25af8b8ad7189c2cb08c292b3d2bcc77631944ba1b2cceaa15ec4067f91c9921dcf1a0623a360c1d55adba0b9b5cb0a69740935905dea908b92ca6d1d29e1f", "SS2": "097b87a433bf081851df26670f3f0ab38612b01e23e5dfb3968b4fdd9a0fde8923e9110acf1d619c827ace3722f4c372a4c2768664e2dbed6edb299ee037d633129941276454698235eaa8a2c9cf260e1e81f35438bb6489e13462cdf74af09708c4006caef411eb49b9529c49fbf0abe3d11e50be09e2c07b67cdb8ee9597b6", "DATE": 16710, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "15ff2ca1ac8d2b63fa0fc8359e723526b529363aba2303f95bae18368927f4240630423a75f2ab4feba8441b7ab9a074e98610e55d3b3d5f08a155313da9bb08096e158bdd04a587880f346ac89e41166260cd2b38260c443bb227d53194630b141f39186d3c6b29f3c965cf9293dee8fa8fa0ab79c2872c5976a2c52fe2d528", "SEC": "041b033048a166e8d3e6746ce7c9f0d7fb54a6803482b64061aa7ba419b2048760044ad6113613e6a82b63638637a75a72aca2d580f1da2a3734a3dff2737a391a", "TP2": "040aca72c8834ad0781a1c830411c5fbb6875ce5a3427821d25ff7782be581eb3e13766cc85a074948502323166aeb5b13320858409325881360af487419ea93e9", "TP1": "040b5faa0f45735ecc8a6b36de341946e4e3de3c487d5207b8be077f810a4d7f4618ef3f2cb35140697c8ab4d58f9b42e4d44bbb85cfbbebf8f8696bdf247f3d10", "CS1": "040196eaa216433e55f9adee56535730fa986e170252b02f99736f7ad2707b2aa61a411574d83fb5a878b0c45d8d34ece54d8eefb12baf304e1d79185116da4553", "CS2": "040a6c9f9f3a3c3cbc67a422de12c3b2f25ac943249d4deb30b0d709083210a27e138eb0e69d5889431de6ec59bbfc789ac598f4e4f087ca51c0da6b251d657571", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "040e75c997f9cb28a2a39663b00372a0f68b88fd04c8a6c2b7b5e4c15f5d714f4417144d7379765cdb5fbc6b3fbb1b9482d3c388eae225e5e0a7a6caa716738f46", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "04123ea83332920afa883fd5ba9049cbf7bcdcd5fb5b1862d3bbb4480ef350f0d20b77e5ff634be533838561d3a66318f1bb2cf2910b97a157cc1fbc293ff72bef", "U": "0414cffd2490fde16477e23e71e597cb9a5b2f73cc2cc9bf3cd5107830f3f55f540c0226c1fdf13113ae08d1bf8d8002a630d76f2e3458bd083869dc582c1e2caf", "SERVER_OUTPUT": 0, "Y": "0ccd74c3d73521ad7d2025935e49ebc0792e7a48ef63c4c3d11e20a8294965cf", "X": "1736aae7e19a3972268c937753f7847e861a4a87afce6b4076a4dc62e509dc5a", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 278, "UT": "041f815dfeadf071a83e57dfeaadfff73b0938e877afbd1498ae8f7576990c98b3232494f88046ba6993f560266eb9ff1be939e97d1ce8d7ab174f925a5ebd1d7b", "MS2": "1061a9ff30327dd55ee20e3b04080897da0cd2e7d58bf31bd41afb6b79e3ba1e", "MS1": "1cfb3326bc84821a1228ec328090e8fd6a58536ed4d020253110d327ce9a5dc2", "CLIENT_SECRET": "0404d4c5029d1976c73f02978a85a670fe315914c09868bf4e713a02d6f832d69118d781532fb1cadbcdbd580d93d57351f76535d818903f492c33bbf3a72dd863"}, {"TimeValue": 1437055599, "SS1": "0061f273c4ee058facf420bfbfd858bcd0ac50c26cb76cae8a1761b66cb7ae79203d3917214562d2b5a45e6f1083a5a3c7573408d647699371e1d8727de9fec32062e28d257c2ba043d4bb92123764cf8c4be25e74f1f179f4759f8f2cda1f26212388cd0aa0f21b768a822e7fd4b4d69e457991a60741213e0f0e09a67beec7", "SS2": "17766a6f5604dbf490bbf92aff202da8dd3e7baa04f81421e00b649ab7bd09f112de9f305b6681d647cef2c4ce608a07d97d5a27a068fe058cde7938f50d7c2413a0f15f71bc7d06e6a115dec2c7ded721762619542f875270b691a107deedb1137274db72ab93f463f429a6b6907f4fe757765b14cb8065cf820c9380be5eb8", "DATE": 16711, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "0b2834e2097d3abb8e85f68f34d6210046790c0fd7b0d01050bb35d39ab0d9061d08b4e27e275eec567859c45c4a5455ee7eccd34fad4a45ae3e9e41d9e0ac5f0f6792b91f6ba26057bf2f1e3c80391d2fde7529a4a5ad706f64194098847dc01b7152ca772703508cf75a1ba6f2fd9bd80e80c1e08b46bbbaeb8a34fe169156", "SEC": "040eb0567d1640093ccdb90f474fb1343fe0b87b0ab8972e5563a955b759760a2a21276e7615267532f5733fc27810c0e228ab8849cb09f3aee9247868a24bda4f", "TP2": "0409bd8fefd1d2a535ff5d7b4a53a64e20a042b66e7be3964ee8f6ab9c591b5a59225870334759fedd56b0a37b1d20d87978f61fda8dadca801194babbe1266e34", "TP1": "0406312c42e5a4f1221b1460b406bcd30fd12b657808ea0e7fbdaab01f6012f2930354117be859abe7c256c8379193b6a2c3fb7422398e90a9672cc58168a65eec", "CS1": "040f0065d77fe6e852949a8bcc5cd21c78f1d83cffbab71b1e6e2fe884c55b388c1369a0ce57ea709edf023e149faca0eb7607b2d04eced3c5291cd948b26f9fc2", "CS2": "041fcb56cfece86ffdb6c4561e1899343cea6539b6ef4c85b2b3edc96df35bda4b0b0064209b593b473514c594081fe15e949a3d9cc99135ff91b36a00ac543284", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0406010fba53e51475846e1e93723323ddb3885a17363d41c5d38fecd2fefe0ba9019fc9d83a093de1eeb4263848f1655aa2a665dac1eac7099085ba491ddb5b8e", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040da709bbeaea879321dce098f0e81b1e241270162b2c8c516e4173d410b5a8bf0613ae021c0fecc515eb2c0c9d9a9d579582dd234f2be9286d96c017d5ef47f6", "U": "0406a9d53b07c465e4958e3e190df9036232506e0c42f37da02d6a85c2fb1ae6131bcd270d1e8e8f9dea82f8c8090e408d821bc087767dab83418a69702f6bf61b", "SERVER_OUTPUT": 0, "Y": "052ab0533196f03a8eb5cd2fdadaf08f2526b34e931a9c79de704d7fe7f1f6c5", "X": "209f95cfe82300b5d07f65524a3ecf14d28a3ff3d9899ebdf2fce5c24f14b19e", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 279, "UT": "0402037e5eb62bb3423eb6a938a0cc718d458add0414e53f6eff411bac1eba0c3e0d953114352744f4fadecfe95f5651bb3c1bf6ba0fc294db948f5691e3d90955", "MS2": "0658537383c78a0c1306802559347214327cd52bfd886be208e23db0f510703d", "MS1": "2233802847dbbbab583bf8317d1f50f84d8a6982b4dfe5ffb216c7b959a26c78", "CLIENT_SECRET": "04153107f29ff12b159a4b68c9cf72cac69fa8697040cca3de712231178d5996031edc3e23f5fc8f024917ce7e899bdf9d6036a45e426872ee49aa7b8b11bc80c4"}, {"TimeValue": 1437055599, "SS1": "123afe92e22a9f34456d0e21645abbc74ec064916cbb7342b800b8b2e392f8b401e38915b20f559d1ef3a091f7e1374e726053726029ab9f5b9f650abe454a910c2ac1595357281abc99932cc039ebf23c47f1ef4ce3bdcc4373b28d8ad02b8d0157ea3fb30dbe4491e08e4e6b185fd0f797194be00602b49e0562c4ec54b71c", "SS2": "1af7ea77832aab7a5165c79f7645abb47c8b7722ab6f6fe6b88ec5f2bfeb3c201f56853e0454f249199db6e7cd0aa16992816aef3115ed0e864639c621e5b54222238ac2546332551d33f7b57353e3f69344b671fcdac5adc4e2b595ed273dae059b2d56d1a50fa209d7ab82832dde7089e9d7e536057b6f676cfa32700aa462", "DATE": 16712, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "16b0685d89060749b67acabf17cfb8bf1f7ae085edc4b1b29e67f816e5cb30190d12c78cee182b7ffa6fa747c4e19f0cfe343ec97c982eb0365cd6964b67ff04105b14c7f9445c96a34f7590b6726d786bcfa01afd02d990df0b3267a2f0ed4905bf4fd408d327f6f22351b8d4fe1f99c81d5f1378d20c758b98c9001b6561c8", "SEC": "040a646ccdbabdd99a76fc34553f12b94a2ca1e5a154ee72e16a4879f28736c6c715bf7b33bc96afd6de75b343f83df3d754b533e52d2b53a5a1814099e39ce33c", "TP2": "041636c2d712feed0c8243e87452843a770c25c9c97956faa511728e8d71ba04952223c17b878d5b7d2152b13e64fe9dd7a1dcf873e849985eebc858bc3b4a73c5", "TP1": "04183a89e9c8985c0ddeec3516742209e6b560de373fdd482e955d55135544d1ac136ae5b4fea6f567233d0d3dc58103daa3376b37be7dd38d0e67d78929dbf81c", "CS1": "041c824ec5f0d56c2ba8deec09f51b8e8e0da1940f23f047104c789219db03809611f20a0cb34fcf71830fc3a2f50740dcab6d753881ae86d9c1c72af7082411a6", "CS2": "041478a84d00eb78f046c656d1188efe1f1699f14283a75d4151542500e065528e111071f07d1f9e593cec0339f9361fe2eb10ef9b2aa1b106b8ffbe1aae779da0", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0414fe6f5d04a92b6b4a7e99c00c0109fb5b2fbaf71769f4492786c90aec7d1e2713e3f5de832e70197e25d077ba4b76e49b9bcace2f2f8f5f923418be627a5773", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0417280bba82223d0dfeda9b790f7b1894f3ced0a93870250250cb353db9bfcdeb21a056881ebdedfef4082c9bbe349955b57678d5cf82092025fbec31443a0e8a", "U": "0416c59d3a9c182f9a3414cc228aacc6d1fddbd23008c3fd84e619f2e9897f8d451af72edcd27e7ff27b4c1c6f2f12f1fcf3f366242497aa27342bd38d5b01eeee", "SERVER_OUTPUT": 0, "Y": "1a8be2b14aea4a8f2909b702c9efdfbbedfe49fef7106c1d68e653acb1b49897", "X": "22a4ffe23e103aceada9d9513e7ff6c411e0a61ee726b27aac069654c6ffe41f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 280, "UT": "04198c729d9bbc56b8c4b2c20b89515dd20f21ebbbe8e7f34b9827c8f6d8d0b9b52128ac3545f7c1615a216fdd8ddca096f7c7122d63d0ee380da614c50978980c", "MS2": "1a299fdedd86474145e2af5fe02026db802c33bf18f558306e70ea176b5d810e", "MS1": "1ce4f43c0e72439b550978bd29077822af36521cdf0e56b2eb9056ceb744edf2", "CLIENT_SECRET": "040d645123a4506b8498da84f557e2686033b458787d9de6b82bcd0ab3e9fdd6a81f9fa16cc8f466cd81b7f7e02ecdf8c0101c5013c69352f53b7f659a5ffd18bb"}, {"TimeValue": 1437055599, "SS1": "06d633ef0b985b11e4824d55e77b9554bdd4d238b6315e72073a4fbfdc3d715023f57296a8243f42bb4ea4da8f36561c554414acafa801a5ab81232a9caf1c19063c292f805f9fd69f5f25e8aa162473ba8ca5845137d0da642d02209346a01a20b27731f4ccd1568e3c2c4686d939e8c3f762c04e9967a2a19f276a4e0697c0", "SS2": "0a59701b249d04af9af7365f3329b65638a8620ca52bbcf0d008b9ffc9e4155021034fe613ce0c4e10709e1fbb11610435339daf55ba37a8b5939740318ba4de1bef383197c37d0b1bfa8ab5d5864454cbf41627cfdaef9d102d2099523166e51052e34481cd14ca167bb630b0bd32cbdf26449ef24ea1f3eac6806c0d5b3d94", "DATE": 16713, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "16ccad281474d4a324e6fd99819b067721cc454a683582b9cb64e16da397d6e206424d0a78b046eda20fb71e83afd70da756b53d23c6918c209b83478bcd0683035b54d3b9a50eb0261f46348f56830fb314f20ee291415aaf47bc45e6b4d3851cd7abaa740359deb984956ae3994bd64edacd672859b64e2cbab962473f6ed0", "SEC": "042121a3c51c46b90f7dbf8a501438a3fd8b5b0192c2835012320f947dd81fa10b15c91405e4205d5cfe2f1cb81dd235caaff12018869d28f13eedbcb345c8af46", "TP2": "0416fe2f1674fbf5118c4f8a580db40928bc98eeaf5b5b6d6932e43b1d926a5d910a5ba8400aa3106a76b9d0f29c24edad07fcdb05e32c900d06c0991509384e07", "TP1": "04231313048dc9bea81065fb02f0ddfd3b2e93464d000ec5d6ea3717507f6157620703e84969beac6b871f7f6558592e995c58dde177a4efc2aa1bd5671f0ee8ad", "CS1": "040d6c20365b9ec29e9b6119ccc43d70b427d0ece084cad69bf24dc6af5d1b72c919de65852b0abc18e8e1b895616d57c68ab35f260692f687bf624937be41648f", "CS2": "040100032d198dd05a0268e87fadbf65ab214e5fb0e0b24750dfe2e0361d8e197f1e44d0ce36722aed3d6b85061af82da9ebc26f7b83db809aa48522856ff0fecd", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0408334a677a48e09189af2c37f6612e1400781771a8c03429a9cd7e2ec0055a981edfc5a4120f881890c0c1ff430a2a8e483b71cc106d8b350d72ac93e505eaaa", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "04001fbdffa04ed2e1772ff57f6b287e988d20df072bd0b811f4fa4134d1787cff0e95ee797dcefe7be3d2d84a50f9524fd6592e7858f1347870403c01ab7caa8a", "U": "04019061a5edf17c86b1f323a4f680ae8b6fbd254369fbbf7f388210ccb89561770b440fdc12dcbb9360e2110a733386484c8407eeedb192c01b3fcff0d41818ea", "SERVER_OUTPUT": 0, "Y": "17884bf064aed90147fe8fca6c566e839da39570bab133e464741e3174867734", "X": "22bc61a1f37e58b6b24d676a3814372ded6339f1a6a869659142ced3d827c497", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 281, "UT": "0409f5784cf99b71d1608e175126531dd5c69b3259adb6c1b45f6c6fe6edae673918ca06a4d6b4188a5be731620c845fd6fd1badb7e1b01552e2c848b63af101de", "MS2": "142271ff20828e5f810adb40edbd46572372d97ebd3f748bc07d120873b8382a", "MS1": "02b21f3a8449579a4e93e205a15539cc41f6d36eced7db57a5225373c7a8b586", "CLIENT_SECRET": "040e55491a89fd9192c55e83b8d5f9892cd5e1fe2e41d187fe0f3e96404610ef6010ac18e3302ee55c7f07c5f4731f0b368ad0930e0920354dc95a033d60ac9dab"}, {"TimeValue": 1437055599, "SS1": "1464d36f4308780fd768a52c92f60b5f0e52c404418144a91af25f38577a08d618fc7105ff75401dc16d571e4ea99283e3e06015cf8518ce13480a415759bb67183ce2c70692e911c6deb40076a914690e14dfba25ffdfab9b4751806fb52df81cde9ecb78de79a53f63453bd89f686ec11c711411593856bbf2480f0340820e", "SS2": "1815b3e4651e454d9daa0c9f0fd096cbb75846244c1ec802a485d8b19f901cc50d3adb8007275996f04f4160075e90dd6a7a0f726250ed5544ae70b8c04810670b9dce7e84fc922c5c42b1bea4b47eba85667962277e07a4d7aa35d13f455ce703a70e6756cbc9a5c657203b7353c58f82be0a1a9fa3dfe86bd6fcdcfefe7dd3", "DATE": 16714, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "138c9cf8849ca61b2d7ab0820a648f8427f2efd3ba32973daaa625127aa569db05e62de6c246497fcb04f7015bf7d3deef0b50b11348399292c23c4c562ac77016bb0bf5550ba8fc2c0afe724c8e4beec7d254cb54bdcb904b95f15417bba5b41b91714e6ee6ecb04d564c420abe6319db696c5ae8a0561f241e45f964d1a59d", "SEC": "041a7b79a4668b6fe306871b71016043622ca352c83bb6e9a641e217e1ff3c5ffd09e2bf4e31ea501cd74065fdf45e5b6789a60a434fb4625ef3c0f58f8fec1d75", "TP2": "0403fb6cf956851fcfbded04975b9ea403af8b9c065c382b41090862a6797b5754220f68e343a4a6e76d41dbda14c22024d16f2fda683520c32c80b041bc1ecbfa", "TP1": "04170554704673e436aaeaf89d83eae425b0e730b1a5816c40eb5021e4f8727fed022f13a3b895900a81b1fb263da654d08a5b708e6d396a5c26bac459cad4d8ef", "CS1": "0405bb3705ab446a5fb568ca0c66491425452f0cb1c01bb85b2fc610ff6408d9801e48776a31c0dc274ff2772fa767ff9b873937875082a9029f75cbe48383e8cd", "CS2": "0409eaaa949a48fc846787ac76d94748f557300ac519dc248956ca8bb2bfd99eb501bc482fff8663d7787d5ad79a26378e04b01f486cc8765ec4ff2034da3bd48a", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "040d3645c3096e23adf73a3d1c131dea3d9520e20e8816ded2ff30728c74c67acd1b8623e06719e01b91c598efb0280427c20fdce91e8ad14e14f765ba5da07cc8", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040d08de26b8cebbcfdb4fea31c29d5a8732d0806cc727a7ed1307d13a8e64c105171eb96110bac9c7111ae93eb3a512b7c018493b7cc2ca985077a2464117d95f", "U": "041af31b2aaa35a8aa3ec4dff9d5302e1272555561dd22933c55e79ad0bb1fb68516ab691094312ebd6530b648a1c4ed7b8701b746e2232e0127434f47e6c7f201", "SERVER_OUTPUT": 0, "Y": "03f651fe4446ff1a3f1eaa05d859049d4e164530970ecc8f0d20577ef2378378", "X": "0cbf92be21bf6c3cea3c074f57200d25ef87adad6e11f84d696123b01af75496", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 282, "UT": "040227a4be8adfd4a647d00ca517553f921a347b03152ef6c9f653212800ccd17e0cbd629caa69b871661452f28df898b91ddd7353ad4db46d0c4996359159ed5c", "MS2": "161f028098941ca6f5239de3e569d254755745058e24b8f64e9be4079f7fb4df", "MS1": "0e64804caced3dcf7e1b105b8486f70157c5bec35df7490711930003e95e553c", "CLIENT_SECRET": "041f28bfac353a1b06f50533cbfd39ab7ff2f40ee6b4d46fdc9cff2645a25cf4710c73ff4040e8c1363e2cdf61e9e7cfe2a8861c6584861cf483f03c3fefb9b30c"}, {"TimeValue": 1437055599, "SS1": "1dafb0881644f27d9e798e100ec98a2a69b869eaec93c5e7509d64b4343d421c0ac27f6c90bae355abd7460af0d5c818d63cd2e38d2d7e8df837502b5a7759591d688f2fdf76dfee863f8647a9a5a1dc137f70feab9a37c36ed27dedf359f00b135531a565e99abf3b23bab1120ac1c65e29ad53dd844d86b9ba13d4b87e635f", "SS2": "07aceef537675d2ff8aa640d102b8609f77ee129e2e54096254414220fca1146070086a0e73a7d062224d6c836ed264a46d5d6e272c079c04227ad11b6a9a7e3211739c3490d3658f8c8255603be6388ef9fc47f0f21807336eac5d4bdaafde2044170c0cc72c7621813cc45ad4f37572296adb6fcac2201485097dac8436785", "DATE": 16715, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "0d34b16138148df5099705473e19a28ca27136e80619150b0ea5d488a29ea2a522a610ee4363784c0b4b412742a53430a5384ff771abb8bd732ee10a03698cb608cda0ba2d9bf3d3d40e3497545a3162ecb6e9943143c4aa00ea283c84bb31d22124d44a7427c6303c12fbfca69873aaad918f8dd4e97646ad2f8ca60ab558f6", "SEC": "0422715fe3b4806d0ba8fe557cc9b23c9701192a5a04a0ef001e4967ba1d8e51f2060cf4006374b2d080e53088ffa28c808c5ca1d007078ab1c09d8ee4c977a6f9", "TP2": "041aab2e23374afbb547c69c57e1f7a589e679d26541c4032dd86afd3a4e2819792080e1d86aa4a482c254d63b1ca89ce94ee1adc7411f95f3e12f35d1519b6c44", "TP1": "040d5e1b68e5cb157da89583079c142644c40d5ecca9728c07d2fb8d9a541ec9be14564c64427f31cbacb080be1e4595d92c1d140e099576979b1845bde52b8beb", "CS1": "0409cf45ec67163fe2b6c9d08a2b503eeb436695ffb10c86f713c4abbec8db9b910ac07c9e3a47de4cb8c5322c5e01f1a0e6616e33704d4cf5254b56cb2fead14d", "CS2": "040a7f9ff8039cf6bd80583b2b1bd2a46501a38a1f026d2dff84d9fc44487c0a2816e618b9655004f213f9c91d1e8317c9e8ae719a509a225a8199fd875f5a2634", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "041ef99ed4be63660f1c17823b5b09cb357ee29e3fadbc451a4f7859b29c63554320a56de59902ae12dbd093b418a1aacd556b02654fc40aaef17a5c796cd7b930", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0422ead4474b091e429de91e60200f34986925b2b61460e67968008e1c1251d3220dced08fac2f914691c6a7a7f74fd7fee45d2ff0384e4655638d0dacd8caac11", "U": "0402938e90aac27796bf2882e12aa62cb26487c803699f1b1ec4be02d03e842ae41b6193f5a1150c1ab330b29b629d3ee401ef9e21bc4b4413f7805e6935d2d09d", "SERVER_OUTPUT": 0, "Y": "1f92ab5d79e09234bd2558bcf7619204ff38ec085f6ba70944b3ba1297643517", "X": "1128ad25aa7e00f7786529aa1ffc886f0879bce38b3ddf4936a12fd5dcd6093f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 283, "UT": "04221b89a52313ada647b2e1129b74d433ce8fc876a290af294b708f4774d66282067df4afbe3f8af3ab8ae9d5a08d5a98070ebe40fb25c92a48d67df52833cb6f", "MS2": "0d62b82ebddf8fbb4ace9ed73ed2e259fdfaaf393896417a684472f4efc1839f", "MS1": "00e65c94124a1d578d563c7247dc10a02422d608ef5c90973934f0a20965ee1d", "CLIENT_SECRET": "041a0969dad94e8e5ead108984d050b023b9c1ebaaa29320ecc59d63c47529478912d750af77f971b3311c6ad369d7ba27a747dd51732a6dd22af30e26f0006310"}, {"TimeValue": 1437055599, "SS1": "1af52ea42013efce43deadba22111b155c44eb244701f99dbe477f04c68f920f0f241763b690ff262cf9395aa1195b77355dcb086b0aa6c0dde2d15787386f9c22222bc19f4a9d55a36a383791f212934161d3e17b905dda921629d5f2db47c11f8558b9a1fb07e172aac3aee4b97fb5532aa2c85b78a260a2ee2f1c7fa5d42b", "SS2": "06c9d4074d99a09438f2a85fbc6e4e36dab68ffe27ee9c08e44ca4c61868685c08e3bc849956df604f05f9e121f1b5d9e7907836a83c8b3adc66ec09b34cc88b1ed8f0c3a3c27c3a384dd3be8d4145450a1af878a6571c9a0bd505b6a6cbafc516a21b2ee15d315780943d3bbac6e3f269871ed279547f32074549251edad052", "DATE": 16716, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "0c66d65d844ebdd81e5ed37f4301a92415dd589d2b8ec920c922dca1e617496413bbb525da146a23881b72d8e483511786d706aeeed22ddf25da7619d97231f507d534851936a7bc43229aec2a234a6fb0b87ddc83744229115c4748efbfa27a1e53faf6f1095ccaee6754fdcf5cba0b59d1917c870d0c716d0899db6e428f84", "SEC": "042341d33447648f0602295f544b6e229c1de5ed67ddb38d598c40ffb7bee147cb07dbd5b47a2b8575b5f472d6785d35e5458df8d638e53576ae850dce132a91b9", "TP2": "040d7e69229a4127c15a57573ebf1ffb367996346c2eda0ce5c643887020717e0a1d49a4fb14d4cbd3d090f4a5f17b5d934c8f216b4365cfd10311d0d8d4034e8a", "TP1": "0402b106e0586f7ad3afbdc068294029f2d01a30bd901d95a7ebce803387cdcf412023d0dfbe35b74b7cac7c16fdb53950dc2ffc95a721515db4de1af3870a9f45", "CS1": "040ba36ca369b4637dd45e040c4bfce178d9cc8cc1eaedc335cf2b4f2594ee2cd822c5343d6374451f68e3599d1427bb1eed56aad9969829346082f261b84f35e7", "CS2": "041c814e128d3aef6e1d1b09b4cb9012be8541cf5b743307f47b6bf05733870aed07aa674f160f0d9f91eac7f8594c6d79605fbbf1ec244980ddfd39fc958e8278", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "040f2d715b242ec221a353e5374ecea85e58da1c6d7fd923b1c74d23d706eee5d21aec0582fcc24f728ff41ea5f1a9a2425a160aa73523c7c4370388c88e708a4b", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "041dff13c9bb6d4679903145623a177696a2afa59101db364d437b931d2fe79bbf0f6a4c1c505108f34b8d037c435bcbdd06946eeff29a28de17fa56080a4d6b93", "U": "040e5216ffaec04aa182520aeb5a9c8e79c8da6dea62bba0bd88d8034ecaae9ded05865707be541ef6fc25f18a82e8711e2aafab72591f742621965888761e13c9", "SERVER_OUTPUT": 0, "Y": "156cc772621bc30255114838ff2f8bb5f39ba0169946d154c4c3ccbb772ecb70", "X": "22ec95da2b46800e23921f0f38ee4d39d0a4636e57d9958831623ecf0441573f", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 284, "UT": "040ada19138a3d1254bc55aec1325b6f08c9d72cad558dfe02bbdb41cc5a0e00950b6d516d8111570b3fe8ded9aeb35e57f6ed6a0e01ab6a442a2e8ae635e299ad", "MS2": "22d1e68a9c4d118376569315ff1d6f8a53faaf319f3338ebe3eafcae305018aa", "MS1": "0badccad11c7fd0863b4a6eee16f279607e808f28ea80d8190bcf62c435b9f30", "CLIENT_SECRET": "0404a45ba6d574d9bc3854d780f0fabb91edd961a51a1d1127d9d097baa86ddd3d0751820e042ac060a19643a53cd8cf40e3cd63b5969a5fc99e131c35c0891347"}, {"TimeValue": 1437055599, "SS1": "0bf5670a55cb15908c197725f4a73a77c82cd0fb9f719061cbe1cf7b2361ec7211b53f7117155f1e97e043e67ce7618bed697efaaa5cda3831b1b41f699cddc910e69d0e64e1519817622600bfbfc21e5768e0751bcee358e28865b1052e450d1ec0755915d67136aa85d39d7db052b1917310c27e01d575b447033186d14a36", "SS2": "029ee705642d52b66ef77b21192905013e270a37428c9af0d4610f3dcd2d128a070d031b5b633a5cd7df2d88d846e4f78822af5c32f4f05bf10cb71480df43660ce7dabe14663faae3a4c0ca1a879481f60591ab7be44c6a5ca7045b61f07e7b22425d8b2c081ead0b56ce51f539d9a32b3c1e9116890f0f16c96c6f461359e0", "DATE": 16717, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "00f148ce8400f5c71835056080a0b2e67df611301cfce61d4a6eba81487c2cec103dc71d45584999202e3775cbeae60539182c6a3a36c0c0c26b16f043689b731cb555ccb7dd507ef4e1e6c117eec338d9cc54fc97310272c39d0302a0f3573e0780961565fd93385decf340b4f6c40106e2067d70069727c1a48e536bd97086", "SEC": "042355efcbabe0b9a8f8d157f9f28ae0960ed1d860129276cf82927708a926b1740669f743f3259c9f6d27c2737d070b91b8f0d0af7b0ed33d3f94a89bde582343", "TP2": "041316f52f022d4b7f16c7a8570e0b3512425dbb997688ae3b9b0f93a36f19e8d81d277ccfc97ee595e440e7cffe50f1d14318c7e7d7c5ece0c42ef7e6cf4f7db8", "TP1": "04031eb5af1eaf8c6ee4f1179aafc834d7b75979736a7045bd5f738b09cbfba2b3066061799ea43b7f5f0983b674508a12f1d24e6eaab9ab7f394174bd728e5b06", "CS1": "041c358ba88406d8a407aebf39d51276a5ac6478eabaa925be1c112e3bef3237eb117dc6a650d0caf58d022c44ae89a5c889d4a4594d2fae1fca637cb2c944025b", "CS2": "0401b5ae5865a9afbcbb47237c3e92132a0503f2e430097afa8a455510cc43e68b093a460cde9aac627015c5e242c215f9d6b88ab7e780a2ec1e99b684948466fd", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "040c9d42518cbe504e706509854ad50b33f8c004d4cbce6df9bc10964bb735cdc41499a43f37027bcb5f80abedf369a7dbc11886f37148d92340c009c81e6d4fc7", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "040d678c1fc88752be09f95fb7485201c1550073336495dd0eb146e53fb51e586a06313cc63e36302c3904c0aee29e589fc79b25ceb7ea3830f6e30752b6b790a7", "U": "0405a6919f348824c92634f30317c0e59acaa26e94e7ec539bdd75bb6fe0dfc72e13a8627803c7f37c42b8127306d3bf7495e0f5985f39afdfc8dac0dde9ff8beb", "SERVER_OUTPUT": 0, "Y": "03bdbdb36e90acc8a4473c2d6d7bc2c9eb353bf2e7254657219ffe549de0e4f6", "X": "0f83339d9b1cd9857ca12fa866eacbe6edd5c57738e2ae6fee826ee9d3e3c026", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 285, "UT": "040df739c09778b8836d50fd323cde4a3b020e72d97f5916c3373e107542155c301ac57ea9ecddf012d6e37e7502e80dd0fe6c41080fbf1be99a8f662fb21ced2c", "MS2": "0a590f973122c685c2b429a515e1215ac3c8fddd9976158c44c328c14e58e7a5", "MS1": "107f588ebb83906788f061b740a57d51bbf2f63aa858c647add007ce1355a36e", "CLIENT_SECRET": "0419622f54671738647c50fc3498f82d2a7af496fd79a90b2dd0b52d53c770c4ae19de284a1c496a48c88bddeb7f57f32d063438f5a5bd56adf97495d56fc4dfc3"}, {"TimeValue": 1437055599, "SS1": "1b31b2d80642933a1991317450aaff712b7583fe196b9ad57d70f47801425dcb0385fca30f5e5ff6e861a85007adc1654376301d95fcd13d2431c02ee9f92c611ee6b41e3bb320f08a645815324c7c36bd84680ddef889651299cdbb67cfd65a237a32638ccc2aac9da47f4434b4ccbf49af448cca5c9a5f208a5bf6bde9e703", "SS2": "1a26fe020ec65267c2d2d6cf49e168f0024fe754aaa4a83ee683ae5632ef844b1e707f0d3e2668e8e492c2b5efe15769f7f6b27e4bfc7a0863184d043563a8c721a4db70155d22389b42380a08d449b54636f2c45deb5587601863858248cb89102702336e3d698e1ae1951e258b0913769f0cbe5be33419006e28d6a4947b8c", "DATE": 16718, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "23bd0c04e4bb013331eb149546d910f08ee6ef8bbfd6a228e278be756e083f6e12452e65681ded2b8634046f2c916d802b2508b51b48abfd3ac5575844bdecab130ac7227756b91225bfaa21a9cc0787c192af540a2109176f43afd2204e3ba91df84b49baf4abe742a46b84808fc293c3f9db31dba72be29af590b2accbbfd9", "SEC": "040da330bae3bf6e004403db16c80f8b7c632ef4a3016fcbedd77ef1b03869ab59105ef2dbe57750981d8c49307bb2b51fe029ba37316a36502c60c27353887ee1", "TP2": "041766bf4b5e4d6b9e6f9dd39fbc82ec252ec5322f2793b2f1bf23d282469e7439116411dd6086312c2c32b53e014124071d7c3bf98c276c08606d35cf7b0749da", "TP1": "040d608b6bc90358c0defa7e139572a92f462535f4d2a6b0c48cc8b98573f87f2e04df4c889e193ff4c1580defb93ff525958df141b452936bc4e5b2432cfa3867", "CS1": "0403703518c7463e20be5100982c7b07810c7a9c108c19b8b96f61b3960d6bdb530039b5bb241687777bc050fc64b8ad5dd3a7be5be07d535fca109dbe1b37d524", "CS2": "040ec8016ea02b615007fbf47e0d3e560e953957a8a2bbb05fe6e29d893de2b8471049da9b850feede6d8e3c4ec3ac5c396d203cbfbba8361b625f72f2bfef603a", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0407613fdb62bc5c42fee0236dff7e9519ef9db0548e53679ac298c15cff98ee570bdb4e8f5b95145f783446d0f40fa9bade8130ad8a84aa8a619a238455bc4837", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "04160765f6588e3b15fa35fb2ee5de2729c0a14467b54cc59c5b97bfaeed29288500d061e308ad0a7ca63b30326411b902fb11dd6f1f1b5a5f990a2584423cca60", "U": "04167a10d2456888fdd4f2938b62a5eb2753eeb5ab88f483acdf7bba8b2f7d1c3202b6b132ae1cc2050e09d55de458c97f68ed50643024c8bbb140d37654540034", "SERVER_OUTPUT": 0, "Y": "120bd9ecb811d912aa91295ff333fff93bb843fb96b5d3230081a82acef59f53", "X": "1dcae075674e9babb6805210099a3aba1cddfbbac3747092ea5a08059c8ac1a9", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 286, "UT": "040b40a48a70f03177897109a218ab70894318a86cfa8abab25e932b14abe8fab7218b2e5f1578229377584a32267d5c873accb2b1965afd1152327fc775d14388", "MS2": "16d4be27521cbe1a39974f73f96c92d8df504dfdceb93468f5fd8b99e5603625", "MS1": "0145065bf5b14db0a7bbe253a0fb8e1ccb5358d260ac77b49ce4aedb36c91e9d", "CLIENT_SECRET": "040f44edb931e5540bb0932e1e2a557d0254d524ebc4bb10e333da69a2a00e5659020aebacc357b0979bf797a91c63293f93853d3652dc002fb48308316c5f6992"}, {"TimeValue": 1437055599, "SS1": "12778f2c23ea7ea52a613197c3a8f33a4b4ba4e829102e7ae053baa3832be6d2022ee0a0fb94190e4cf804e54c718a5570854ab5fbe7e5d2fc036a097f122ef818ead5b6ccef9822bd548e3f627c1b559e591e692e68e9109e4223992fa23a170587db9c5260691da6dbf7997c8402c4c18ba0f99e16b657c00d5de38636f515", "SS2": "23a306f61b897989a677d24451da91e976172501a5796c0c602f9069b4363e1e01bf258ea4460e7844e4c6f75458076652cf903b6621d08b59818205eee4e3f602e5ae9751d8a13e067d0ec0e07b959d97ff06b194317ca6ac4fd11adba2bb1415e4584aa8495846f1c209d6a056dac325e5b29e6e8dc4b4cfe5d119a1eea818", "DATE": 16719, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "192893aaf7d46ad49bd4b60432cb2e6df15b374961cd6a359a52afca95412a690cc4161ee16f3255191cab564be229ef098d57dd2e242458e136238b2a97505211a48903c478683736e627f4f214cec33098a5301d81eeacc71a936e35e6be3b0ac6472f466df1360b64c147ad9f141c8d57e46ba1a06c9f45a156f076a411f5", "SEC": "041e48511b25a8b93ec7ed16e5131bd9516c6845202683aa6907e17cad5526ead814bfd03d76617a402eab948ddcdce26c354a98997474c6c0f090db43990e9b03", "TP2": "0404e2f52744a695138e316f7b2e13b66e8a2891e9aaf34c309061f05204954caf05e7c0878483347da201dbe5e11be8b69529bc7ec1ba210a1dc6fda2a9c09726", "TP1": "04088d6b9bb10f507ed073660425303f508cd79a7cbf56d1014785614c3816f84a1c67d88bf04729d7b31ff19bfebe06258a796147d250c4885a634e52e2944ce5", "CS1": "0403b6d02dcefcd2a4370e4addca1542049034a6daf28a684edec312c24d58a8d11a92df9748e63aef89d13bf35cf654985d831da2b20c5a79b4c2aef5675d2b2e", "CS2": "04082732aa6688843c6354027228e8c311021eeb4d0fb1924a8f875343f42305b103a2afb2da97e4368e20e1307852bbe2e4e66c20fb2020fea02b75645300a8a5", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "040b41b95ef7cd5f1793e17af47818ba7218bf0a71b1e31655f80b67f0c2580371006a4360e2ab116253d0e2858cc4524a97fc67d8ff9bdeafc95a3dc4c6ccfbf9", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "041c2bfcee1f374884779d95b766a6514f03637de44795053dbb8ca0247fdb6459098a5d32ba68fc7b5ee082cdc859a937b4cd1576ff57410195165b84ca382e3b", "U": "04201d1a768fb22c849e3fa51cac3fce5db83aa02ca06089f65ba1863b14287cdc004e738c27042cc19655a4e256b7a5ebc6f68682e5a76528d0bbb6c9326a05d9", "SERVER_OUTPUT": 0, "Y": "00375affc82cfd8531703f3c62faf8d41e6d083298bc03d70d82bfd0ad3bc891", "X": "07d9e537f28192e8a533bc65f2c32770393da1d30c4817e390d6ace95ea4cc7d", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 287, "UT": "040ccf71dac08148456c92b854b06eaaf6b5df2e369af7adfae66d2467935ef56a1678351e9a2b8d59e5193874e80b1345389b229be11b98f559487f7ffc4c8de6", "MS2": "173fcb7e36e7e2980b54c82ec3b25cd5fed99d60da2b62203606418fa722a726", "MS1": "0321753f01e14b5dfdce9ad81944b570c592d302870242ea7ed82bcae3619aaa", "CLIENT_SECRET": "040e387e3e5770ebaf558abac62747f9a49d4c3889f2920b6f0e4e4d61e1e15b5811ac72ee96403d3973be5e987693803b1f36a4b095f3ae734f32b94a23cabce9"}, {"TimeValue": 1437055599, "SS1": "046dbe9a034c101b83c20ccbaa0aa6b3248078824f03a33b1cdc76c518e0e5e111ada2181cb557841ec4b0b438551ec0c5426c41b098e3c5fed6e6fb78f08112215756ebd249dbbc8b72e5b42ab285e5738a5dbb5173aa66683da2ee482fbe8a05e50bed54e165d2d3613c2ca875989cba8ff615f4bc4bc3cca9e502e4591d23", "SS2": "1f0cdfb8d7291c45a91fd78d1ec54b2b0fe328e933c2fd9fc1d2fdf593ec5d840e57a4ace831b094f8cfa0b09ef5547b31123fef43e6923261883ec49d5df23b20a6e6ebe52d57bb20c1565e67c7532f6c6218d55396d6ed0df004d7e2831a1207e92947a17f49b98be4df2d25bc5c2c74295b3fae9eb1810e57e0394b3dcdac", "DATE": 16720, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "2384afdd8f0507f1f74b876ef9694fde624bf61423ea6662d6c9b8082300fdff0a25233ac8dcbb4be2db0c8e0577f1707708353bb787e05ca55dfa9fff78acc1022bdd97ce42eb4517fb161469851b5516ea00568f7db6cba501da075c6fbafa0023921ed193444ee4e791ca46861cfeaafba4d423b1f513b44ddab8ebde3aa5", "SEC": "0404a2d2ac07923626c2a098f4e27b6204d996151baca86e10989b93dbc995bcdf04e2b49b498539c125e5abe89325b062eb3db0a2d0d6b7be9a7180fdc2210c3c", "TP2": "041b0a90d0bb57a35bb3a6ab9575be07028ac5f2d30d265c9257243071ab55aaf70b136cdbe54c7e75a2f1bdf24a53ce2b33faa51779c276e8720088f28661118d", "TP1": "04105fa1508b4bf8e5d8a729686a50f3f15b2fa0c2b81116823931a7d2c5091bd0132defaa75681a56a61850c747b77a453c235be6438c0ef00612df64ee829510", "CS1": "0419b39641738c875b1133ea9d4a67ae916fff8c538cd9d4c0c532d2c6f1d511ab1daad988fb1ffbfeffd15fc3bb0fe95934a88c982925d40ebc77160aab44d4ae", "CS2": "041c309ca0d65f079e58963327676f352a4b729a53e978713773a4b89e5f617c9b140e6ffb9e4f736c9946115eaf94fc858f7b158a606d6dc5d032d2cff96c8bc9", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "041d1970ec5b3dfe50eba4034d14db65ac4c428c6fc5cef9bfab4eeffa78025b93201072f07161501e171a08debd2bc6c5308df6cc9d499c183ec1dee8f25b00de", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0404907df24769e0f9d54df022014a4360a1134fb52073fd357e16dc75010456fe049c579a4795685c2aeb3faf024f7109026689eec9c5a7aba2f1de3127009c2a", "U": "041b4a9acc535600cbe935240cf7ca67ef66fb9590a6e3528bb84ec2255e3e4f190599b50c84bf8d5d3889a4865e6b23af6061a3ffcae9027ce7347e9f5b61c60b", "SERVER_OUTPUT": 0, "Y": "1dfcf47666844e411dddfedb2695377bfe7cce13bbd17db6733de2171ada371c", "X": "03bf1cd40f868c2709ead872829276ef1e8cfdf006de3028e62dfed9b3895065", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 288, "UT": "0405e19272bfa2f93aad7f9448feadb88a09a8317bda8a655c168e36b49f3290d819c9c7f917ba8f28b820abc279892293590a719880b33277a415e8f59a707513", "MS2": "00a408576739492af2975e2db2937f191534b36bd41b26d8b519a35574e48017", "MS1": "0da2a87a499ff9662b5d3725581bf1100ec0ce9137a7f8ff4880da151c8050d0", "CLIENT_SECRET": "042096820b2e2f8a4279b23f530cc1f1a10f9c9ef5009ab220293fa55ca26408fb0ce5adb3e435883368f55f4a55ae9bc85c96eada72c21969fb1c1c1d85d5a208"}, {"TimeValue": 1437055599, "SS1": "018c48447ef2f8b495891feed86bd872543af803407a4d6c700cf2931140161e044ef27f474facc608af42d6f0b559b6038f7e6c28469b931eba96fcf140b32d05e581e4ac2b85a307b8cc13079eebca896b7a2112e2918e5ddadda4319fd1df0fd6156bc638ff73672deff14adc41c8309200d7d16fc32416fcb93577110d57", "SS2": "18f0593d8fdcab0244f73ce333f30166897df6f6d37ff29f9dd99d6aa071c86d05430a678df0b02325358cf4d96f341c4f9365a1d7d9639b1b6b66b63876bd641ca69c827a99d3cc372ab243dd3a5081ad1953eb4fb16cb2e4047fde110d294c1b14736aa446597ce1efdf91d887306a66773a0d6cff2ce226d2f3c1806870f7", "DATE": 16721, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "1c958e11ab5d32facb7f62bea075283097a397cd8ea118d23bc260a55508ca2c0d5a9463ff57823a00e402740b363914e19f05fade5754dd8a1c65b331f6dc3a1ea1b9595f9f02177e64da0411cc7167ab09a26ee8d7ebec2febc46cc1138811208f68f5ea8a3a149e17ca1113af95cbc3397992ab35024a20751d05b315ebce", "SEC": "041b9a44c4839048730ec79cf2d724a97f3f481336c5e82ec51e1726a897f11fcf0c5d98b4069ae23c872af3879f3e9699cedbe70485bb4ae32688a8733f5c29a7", "TP2": "0421cf8c46c91165627ed35d8dea422d2c3e1ca7e2bbfe99c4ac925c6e8620443f225061c61b994571dbcd5094304708bcfd5933f90feb5b319aea464f58de926e", "TP1": "0415d251aa413408f81d0b3c569048746daa84f01e01ab9fe4c6c9e0c42c611ac41ec3710c9401f1e7b8da7ed7abeb3f01ce20d5421521d13dd6a2729381bc7c77", "CS1": "0421fa0aac1ad0d2b999edc60c18e3191956c561f89c32d55a6a4a56635bb08e1c09e9169d8f5e2c4311423247e11736c4aa9560072b41dfcc3fda669132d4f608", "CS2": "0414bdc6045bd16aa2ff1d7b9c62c40fff8212fe3d0113b24b3fea7bca2e9aec960d8e63893ea565a147fba83fed71874ebed65925d7fb29d3880948aad5e7e401", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04087926eba9966fa404fcab00d54663c42ab0338c5214a00e07cd2f9fa3bbd57f00d11c9d61270e71aabe353f3a441209149844b76d935da41b28c513cb26f5d3", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0402f069285a8ca697cbae7eb208a0aeb26b26ad6e3a500220d5c977ea35cbe0d60580fc502f43b14474ba181497206da7a13eb4966f086b3e1d2d91f74087f74b", "U": "041beb1bbd629861191ec40d0888c20131ee35a6ee8326f5b7c035fc86e4c41a27079b9a3d1690ca08c767721a7b772f6ae22ca1b8293b0d78b8b7be2944975d3f", "SERVER_OUTPUT": 0, "Y": "11db1d196d566f7d0800e4400fe38d5656866922d546dac6ae16780d339d9b80", "X": "05504cd9965e6bc71f352e2111806b2e9d31088c83240edd5eb4b58f58100350", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 289, "UT": "04147aafeadc535e672b03246a2d2dd9efbf2344ea22d90f140fa70ae495c1061314a8e56f5d3562d8f010d7a245a45e715f6539ebf77d868a94e300f0d446d184", "MS2": "1e0d35617bf5dd5452926de4bc2bb7306201af22ea6d60e07b882030fad3cb0c", "MS1": "1e4390ef9be1fbed4255f5a40f9ddda9e69bb0186e5309793c23416a9725971c", "CLIENT_SECRET": "041d3b2902b898a1e2d6bb4bdc5c47901966e2fb18a161fc1a74f955c4472f60ef06027de53a55257ff5895295db9fb7d408663c824cc7c30fbae6302bac01f2a1"}, {"TimeValue": 1437055599, "SS1": "1800caa31953f77312bf53e4555e412dade63287821c941effa03642679c20211a3309231c3666c7652afe41c72a185ce4b4ce31485e573a50562d44b2c7c0ef19afdd5c985092c539bcc86acb2614ab402c825e55d20b0d45eec2bb2ad291421feb86bf4d4bb64da04a132a96908e1e84a6ac5090d14f096237b1e2e561e6fe", "SS2": "097fcdc42e6d6e1c34a1476f3f452068dc6a04fbaf66db3573c37f0b404525571b7aee8788ebc7e5e3d57c981e520662fb4362542f1c9ec6e57c7a5b7460345005389df6b2e908cfe5e19bbe1d618df20449e9e7099180974c3fba92484033881980f99cb62f87aae6d46757722bee2e79407c4f4746bfeee6a04e2d8586a221", "DATE": 16722, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "0b7b936c05dfe639dd22c920c0c415cac7116940703c6dfabbbcea574c1a427b1146d5c330dabb8d6d6ef6e9da7f17a3eb9ad4a06022c2079dbbcd72ce3ff7760b71f9d4b3488ccc926c7ade84296ece2659dc2fd2aae208e56b16a0a2050f070d71006ee0a57aa79910be6180acbd0aee06f2a09cf5be7b0ee8c6fd109261c0", "SEC": "04186d97fdd565fb1052ccdbfb3d2bd5b987a3870e046eab2dd2f6fcbf5cd28f9c01c92780edfce6fd648ccb9b1ee65ca7652e61020fa4944f149c0a977de4dc17", "TP2": "04143e96b8762486f0ba3edf24efe862318a83865242fdeca4f283e114b1d8b59610d87a724c71d76d773e11fb1cbb4190221dcad81e0e5d0ad6287cd8c63fa950", "TP1": "040ffba6c8e9734a2c53ccd8444bc444884109d3acf5404e95743c2c3e967832d819fb10f378da3260d1b6a4a897cbb38b5cc2f444bf2d72dca035a51c64cd859c", "CS1": "04149a036f38a7ec8050754f8a69753fc720dab9d5e11a850f2852e8e9086e521013a4508c0e619402bd03e9ece054a2d64b30dd46f3c884c1bdf4f3b797b53471", "CS2": "041019bd7d4914522c6be1d12d5ae9983d38503980798cdf97750c3f4243f0f8db1607e63bf0c5a8d500bd780da513a74322929ff6bd1cd371ef4d528e0c8800df", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "041470d6bab35926fd33edb5a2781569e4c2e248b4907cc7a62625b10cf26b647c14881b67772a8c99e2e43003ca6b74cfccbddd504331443815cd4d3c23360139", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "041b8b3baad6b5918cf47cac228c61e33b0a2772a21b8f78aff56549e7f99b9a0200c836b9d9940366f8dc6452fa53b5a9da58e315398c2c1411b62b41ba127c5d", "U": "0411836947fd14b928c3028756575d6c726e91a20e2926973dfdea6124bd801c00098f26e02fbfaea2b6b709a7cdb3f363d7692f74858327c35592b6a0a1e069af", "SERVER_OUTPUT": 0, "Y": "12dde030d7ec11141cf2fee7511b5ef153032276df40cbfe8638f0848e123057", "X": "0b4039d05cefd07973b9c90f41e36ccd5299d1de9d58ffb49ba5a7015738084d", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 290, "UT": "04218e9300dadae0bb5f11275bfc1f008af8af21c22af89f1d2e527b289377d6dc2064a821eb1e99ae3bef6a19e6a9fcfbf23c2f0b9f85a63b5ad23bd033359b9d", "MS2": "1c1d88a35bd5d8dd582ce4304099aa5b7ee9991dff40ae0e16e343d4c6e1dc17", "MS1": "18cdfc7ad7a0b11dbf429dc2e2dcc88f234b5c5825321cd6391784aae84ace6d", "CLIENT_SECRET": "0416444fa37f0cfa2c43cf553c0b80b8a7f6a682d12153de243c5e389aa6d6bf6c1a32862ce0f0458a72f5e5a04a362980d6cb90d78bcea31349e9632d98202136"}, {"TimeValue": 1437055599, "SS1": "06db0f6017447eae3da91131c485c4dee7aac5659ff9fd525e218c64d416784e04167d49437e2d14054627cef9448ea25c9f6ce37960ea3564b016069e367fb00a2dff150129d05d37cba5f714c8ea22b7616d2a5509537f3ca493818212452b0828caf1ca46b733440e5d6910d039da729408c7292882840ab8e6a39ca149e2", "SS2": "0644d4feec0d0908059696c54768addf3444617d147741e998f17f0f20d4358a066a46427c3568f2325d1ba64f1c6d265202fc781916c1b53d2bc73e4b6771f91273541c71d8baa905def50025be6637c9d5c364b71fca30f35efcf02aca245521f80098bdb992936f5eae408f1a7edf2313d62fbd80f8094c130768782a506a", "DATE": 16723, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "15dbaea249f39aaa5843f6a6260d6e5131bcd626f355b94f8053c30749ae6ab2216d88f2007e9b2ef0efbe03dc914e1864e178f03e57e72cd0212570a09c264511848c292f72621044ddacc53b73351c0ee8cc150166bb35c8da4633cdec419b0fce4b9be168d52d6f3f68170b82cad5daf88ef5cf0781e36a4361119600f840", "SEC": "0408ed58be5cd5e6fc73dd89b95fd1dc3812c4bcf1a323e3b2869861e9c7e7ed960dcdabe50e77f241ea1ee3cd9acdf09e1b4274a0b33a4a660af916a3bef3326c", "TP2": "0413e845fd1dc20ac5b3cf82c06cb14e1691ee938d60bdd8f48f4d6511b9f77f0010510fae6c9c8f5d275e4900d05003f58f840eecbef1845ee4f852d9bedf9fb1", "TP1": "0418f49189bc66fd7e99fec1fd910f2322a7e69727d1317cd59bf6e151cf97a6da1d6a54294a274c2b6aa3f5a4d66c662efe03c4af0c4a0723b6f57d8f3d7d6d6e", "CS1": "041f81c135e0ec4ac5b8c2a226736dbad3e38b31313c296ea2d4487df8160d3e10229bbfbb4e5e8daf037dae9fcde6f45a3954c1be1d2e5fd36c528901f59bdd6a", "CS2": "04024639f6bedf6d5901a523ce763c70279db6b06706911d373eee22157012bc010ebbf234a065d992cc5a833e9e67c8cecdb749fd957f4ac16376de3945e4f171", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0407276b2112285832a59d0452a5c1067bd0bf95f84775642fc2479155fd6d7be90ad1587ba290bfd1d872b77f96a9be5b9ed09b867e29821715427531172945bc", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "041545fe0bdcfc435a920bf4482c920cd6928df9b802bfb3d116d06f704dd72cb81c351e1192c7be164dc93672e4bb08afbae03f7324b6842848b59d0c79eb577c", "U": "041e6f088f4a9fde0b782c4b0684b27de336771c7562408c11c2b195f3d73745d402e5819701ebf25ae4ec558506ed7fd057b3e3ebabcf262dddfd8fa874384cb8", "SERVER_OUTPUT": 0, "Y": "183cc7c53b01c7378829c1734a413861c4b4423e09e9a767bd0701299822daa5", "X": "0917139e1b47ef68f965583ea00c801c26b09313e33194bd0b9954a81b50ffa7", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 291, "UT": "04081be7e9adfa0e3662d4d52ce1dbc59362a1df49baafe096e792aadf6d27497716d131cd78cccfe0db7959e2674cb2750faeeeb309e8853d3dc2675193a2293d", "MS2": "14ae20b52e491e609c694153cf668bcb06ff9a198712e5f6ef23dc1404dc0b20", "MS1": "09040e21eab5455dbecedd91e3e5341d4727191ce0be7c9dd80617aa81d97953", "CLIENT_SECRET": "041ffd49e01279d825fa1afeb85a3510b10f388b48389b50c491ecc3649ba1b22003d34190fb10532f4e71d5e526c44942fca2afbeadf53076aa9bf1fa089cf1d1"}, {"TimeValue": 1437055599, "SS1": "1d4bb5aa3d38f7e29d1958a570b7ff0ea2aa4d09ac3c2a0a5c0174da0322fcbf043dabe41ec13f05110c2bc5cda7b60d92978670e349c23a8f8e31ddfa46959015761f61a29f86e1bb5e48a881e7cc46928bd2f0f6df39f661d5e91cf4247b561dd72fe8b373792a9a88e20ffc658e2d7fe8061ee349b716ac1407f654c8fb2a", "SS2": "217365f90a6335b1dcf962629186e7719da00e975ecd5c08dc726f80433912910eae04d4c32949575377491a20296ef841cff8e8ff09a2279449c7a977db5b131e4008332226362dd3153d3b67dc251d85639553ba52319bc28edbaee1c4097a03087f990ecbc26ff179e9f9f8d24df6b788f084232008fdca8a483fe52e9974", "DATE": 16724, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "0399d6a542065d61705d479715189d8b558a0f0e9381cf4429c0ed9f588b8efe0609c8a5114b5320a82cb62c6e447e58a9473873841136c2486f85d67a49f1811614369fe3c4274aba7ccb34fa4f13ee1173e2c33fe3ced4a4d5e3f2a7d56d4c1700318a7cecbabc648d0f0bf24b3ca0bfc63c5691671bc158e6d9fcd78dc96a", "SEC": "040d98d7c2438b77e04a3c85cefba72c8196b15006dd46b6930f93533980bc0a6f02504b2ffbfc921d27042022174e7ebf842a79201b1c854c5ed8047f90bed495", "TP2": "04186b7b6001168886831ee668b6fc4698a86838f97595277d8298a78f890c7f3e1b8321d6f958558007a9a7f7ac332f10a11e5fea40030f8ec953e9c3fe21e169", "TP1": "040eeebd93a7e3946f7724f4e40ee96f67ca93111eb47efc35989d06df1971245f156cb96d1a4aeb5e41318b21c594bb64863d9bf58d84e4771f4e0810be3f041c", "CS1": "041ccf1ef1d1476004644e9ee9ba78a71f49d0a68d6fb06d15218bb67f529005121a68bf6ef0fb9aa87a86141c0d054e8e4da6e40c35a786789c49a0249f688d89", "CS2": "041a934db3626cb9b61fb1314ece327e3d21a4dabcdc2c37f5f572fd463cdf915810d08fded210929b22c34fb4bbc5eb372f58bca6ab39e66654bb9e5a0b2edc33", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "040b552293f15907fb84bd9f220b69523c6d14d141bfecc62489351fe45f6bfcc017fd513674f52530e60812c29039cd46ebbc7339cf2127d6011edb7f360fe6f0", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "04031359dd810041f1a3f3927d11647a09f305d46441005240a494583fbb6a870a0105be1d614fa45234098f3f1a21aacddacf1f4e772863e36589573f24938ea0", "U": "04054bce1c7bcb5367b9f593bbdd845c14185bd234abbc7e9160f63f98834940c419bed3272ffec84f99c4f41fb293a765d3ad7cd28cffc9f7ada11ff39710a92f", "SERVER_OUTPUT": 0, "Y": "023a9e62c815440efb738440b3051c719ac9028b950946062957ef2498be807a", "X": "2305cf7ae544e2fb9d4383fc15f11fce03272010e8424228cb01766b21392781", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 292, "UT": "041a686d4ef486357b143d14123783ca92b8aa0dac6cc7c9a57238476b3519a1c2230fd8f77b32ec714c11fd99b0f5e7545b91b129b5443a8d8d9047e77346767c", "MS2": "15eb8fb5d5141ca975310dd576787ec734dd5c860891d5bf3c390e7cebcbadba", "MS1": "0c9155c2d74797a89fb901d923ba1205b08510e59facaba3bbe6e212b54a8508", "CLIENT_SECRET": "041e7b324914259ba2dad7eaae72ea9fb7ec352e1f7b69a159e391f827ed4536ca0dd6fbbce3345fda06962cdf03324cc1c46ffc5ce8b46f54f1bc3c198553053c"}, {"TimeValue": 1437055599, "SS1": "0c47367ae1afc8ea5e1118e2cc151da7692634bce4079e3c1ca936324ec068570c10b135871b5a2260f9697fa1196a8593df11d9be41a5acd21f0f99d61637f418c32055d54d66de546e3a6db5c0320a74a182f785b98b52294462746c546e9c08e519a996c9980ed812d030841efeaed09a681b8dbf45b8bf45bee9eb8f8232", "SS2": "093c78d7eccfc1eebcd36e4c7ce42047445666bd88dceb1ee91a1584a4c2094b05cbbbfd7aa872cfade33da96275aac1a09e2c7e1a0d97b2f2d6416368c1258e0cc1ee8b92e2b60fc201ba8e56ee357969f449b5d73df4e22b4b4db3fc2f23ab07ec030e59420c427c5418655173ea6ca05f5f8500f28e64b1c3345132a19640", "DATE": 16725, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "15ba9c72ab7e82fadfcc3a5f0cec91997f3572e5cdf5b52de4779954da65a61023074fd29cd2917c230d9d00e2ff098aaed5463dc9ab0e307ab9cb0bebdd2e4a06f3ca8e8dda3981c49084b67dd8f827f751496792b680a12729bfa2c564dffa14ebd49d1a7384902964812771dea8e421902766c005901fd03bd68e1fd64a5c", "SEC": "040f8cec49ff67a1ff6a896f7a1b3913ee6226b7c43d17a7f11c7e95a628e9fb0f1a05e84f9cd7a50c5b16bda6019c7f1d8dc05995be1d7d6994390cb78acc4654", "TP2": "0400606c7add82e6f8e2d20d247f656a3445423d50496eae4eb071c2ae48cd4a4d0383da275087d833a6da525d12765b68d92747985ca3e493edd289fd412d5d41", "TP1": "0416085e0df25fabcff2a0adfc2c73362c8917734ea4c7663310db7bc384c4183c0c4697456f19bb3962930a7005651fbb446aeb3ca7cb0cb3f12c46e57d17a376", "CS1": "04022db81060608f14dcf5d39a7fdf8e2d9b9c7141f1dd3b618b5bd7ec3d34f0671a6136195d453e78542ebff9651d702cef1b789cb0eef5ddf75fde0bb3296b39", "CS2": "0406f21efa5608a4e5a61ca20e1ee3f103b8fe7c49df39e41eccdbaa891a6e41ac1ef895c65e7268b46600b7c44bb5ab1a3ae63c640c5bbb28abcf9726f3b9f9e5", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "040f21083e8510041ca6a05fbe0ecf1cd1c62c0e1d7a7adf200e2ea17f64a4d7f60c009c2ee788fe3858a3307dcfa31c724e845089def34a671dbec638f8a389ec", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0411dcde2676cbd5fb8f54a53419b2299f72c2542487811c3cab8ccab22625c68f1cce11c1c340171093aecabcecf7c8d6d09927155f97a8f14c6c0cfc58b2ac77", "U": "04006eb8cf84307fce4ed7afd93b2050fb278172a65e44bc745c65849215a4b0fd07e6e263fd47d700405a61c3c131db33a76039d091c57ea854e04853f4b1c4cf", "SERVER_OUTPUT": 0, "Y": "0b481c6a95061c8dced68d3a85e2cca3b59fb742b88315fe80801d2c0d7a3ba8", "X": "22e3dcc96b6df9a5cc1fd090d1ba976350797c4bf2719079c2a5c5aeee4a23d8", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 293, "UT": "04204fa38848662d3277fa35335cbd65207287abc9356869574de56cbfff9934b70415ef6bbbf4159081f84376d93622de1e691d79524c76473b641eb4ac72dac3", "MS2": "22e6c37031e4bc13023675b17a2879c4c464e883797ad1f699e41590450ce994", "MS1": "12fb3c742bacfad537c7950ab5c236c8a6b7128d78a23e261b9184fa1a324437", "CLIENT_SECRET": "04169bedf02d2feef6769928ca7f17d2beba609066d86404369a870520ef4ee5801fb741a2227778c6e2112b6b78eb7906ca163aa3b61a48f3f0ae4480edfa94ec"}, {"TimeValue": 1437055599, "SS1": "0d0f48f6fd8cd0631d53272770048eb9c32e6261a3f2845d7bbf0e2368f786c7115e59d2c95e2186a467236da93b903489647c931dcb9c280743bc7b93496762106ae0cd8febaa0e39d1b24d21fc2e5f4393a23e514f4bbe487824ee27a76e6915e8b30c3a012cf2891b880aafeb2d6ac9974657bc76aa57d5617be27680934d", "SS2": "20a20bf7f7eda923a5b05cb3ccdf58777143466f451416e841e2dfb6b2f223ca0d81098bab66de58620c01597cc3b415c346975e636d5653772d591b0cc824da01182d9d965d3f0bc9f2bfa4db8824c080a5da3664f5fa0fa6ebdee55fd6915c0482ab97e29ade48b3e78f45e088b4f244d0857e2dabe00ca88309f29f689f00", "DATE": 16726, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "1550debcde21e86e2fead6040fc85783bbf537f7983f4f18cbd4c184644540fd104c4ff528ce7b64da23651acbb4c32fea5a3188c317bdf61ad002d1b99f3f871922a253196f28f99d0b6ff900499c58763bea3215f181e35b865eb8e650a8ba203e9fb3a8411b979c5f82a4a6abf4816dd582e49e5806a7ce8999af4899cd9f", "SEC": "04024bde19424220160073e952b6d5e34d2a6ea459b37efd03af6448fef135f51b039c5382813f9df6bc0a11225b4334fc7b5ad1c59087056f316e271c7b43a7dc", "TP2": "042094522e057fa8cf8ac3dd46f4cb1305b97a3d0c9b6958069dd90aba01da43a70df848db2442ade21be0d39fe79df7a7c3ba1bdf4ff7f1b5af7e9629ce9344af", "TP1": "040e711658ffc69a8efac36bd2411bc4d5af6df5eb6ee5e4dda308af1c2eaee07d0c35ae6d00fd91d093c51f77856e06cd91cef7fb12b27347b3ce133efd81ef6d", "CS1": "041bcd1d4573faf347aab7ef03e39f23e95a558f90ef414c48eb1ca1bda011f55305e02f9e5c6d31c709fbf2086062fc08de45a506ba06a4f62ed4eef9972388b4", "CS2": "040dcee2f6cf16a7a942a98eab074e9ead0dffc3b1472c8a23a1b9e06ab3162fda10f2b516f8e5f43e8c448cace02014e26830d31891ef13424afab6cc2b41b441", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04027c50fc28febc2d5a05a07a13d2324ad6ef36ca4056f7ca5d25b5575fd1059a0071c0a2722f813fd8cf861d5f540cac8b5148e42af3363e5d3f2629005c778a", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "04179f161d7d8217208d2042575b39365265dd12a1caeaedd6a71f7130938257d01cc84b1427fe6d661e8cf5499b653ce284ebd1e7a9215bd2fd2ad048f61ed50e", "U": "0405b5117f41fa50ab2c5a2e0c1d3195e5db4ca25d2dd745ddd9c528db7d4b177901edb33a1a6a57c1d437f8598652b888a084af000c01e97e127a77151530a4fd", "SERVER_OUTPUT": 0, "Y": "0a7fb8e7fb2e3428b39078497ca32837134dbf110df42a75e03cccc6046480ec", "X": "0b24f7ea3d6c7167bbe8df0ab436f36a8d9bd797651487fe6e953896b406fb5d", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 294, "UT": "04177c739343e7bac779527de41b0eb82f7862b9bf5f3225c715f5a288247ed5ae23127e11df83a896ca2bad63035ed818fa3f5830e263f076b828dd3dd6b5a169", "MS2": "0a17b1f1230d4acbc213b8eb9586116cf03753c6d49c2da45288a433e0bac306", "MS1": "201bec6edcbbea75ef394f9d090a99ab44c8ede3cbd01a6bc83b5b65f146dcd4", "CLIENT_SECRET": "041bc800b6f2a0ad0e0ce9d9f5a1770797a335c601e8d38873ef38fdf4ce8ddae000694ca074cef5045c89ede665d048cffe1c91e205e7b3439674fb152e32948a"}, {"TimeValue": 1437055599, "SS1": "0edcf5fe6281fe6543510e3bf746028f9e4ce1b57f2e8bc4fc53fd016901cb4f15439c51f55c8438dc74763c12a1ffd0cdf683b0d49b5359bd65bce45e7a28ab167e2e6ac45578e1f31e62d881feed38d3ef48f4b5d455c566e549036d9178511f7dc6bdc485ca907f447bb5f340abe9245aef2a0a89e29c6eef7097ff69e229", "SS2": "0bc9cacddeddac2f29fe07127b2411705d82512e531553c8916c5baa17339ca40acb7454f850f079caca97c543ce1c6c06f709173bd43e2a24531b80f006f4971dc13b1ffc03c55d640e0d64fa0b8416e097959e6687acec9bce68f6c0836fdd1831145aaf2d13a459db80a1ee6c01e284a101f6d65ba119fbe8c557d60869cf", "DATE": 16727, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "022c2ec34704ce35138adc3976e9bdf3d6f77376fbacc85c34694a546229108b11a02b2a57daa46a05103dfedc26697b6fca221cfac7b8834239f8689bce29d6025fcda0c0d972fcfee56c932e6f8bfd3584b7d985cc7402a5326d16f20c955a0f4e5a01629c5ea9fa9ea14858accb3b1fd776c9761daf88538f6cd36b177973", "SEC": "04038da2fb04c55ddcc5d60ce7d48d03586c882402fd97f5ed2d27c31d965cdaf20eb8a0f90c509f78a9f0cf26960b45b3715cdba01537a3ed3e8fe599933671ea", "TP2": "041293633ef2e3e3455f4f1b99cc67b2c6c1f574c1222d46de1e91e3e0dcef674621cbbb61457649850745b0039ef215e529fd434b2e5ef6a2c39aad38d6a9bfef", "TP1": "041f292b1fdf0f6e89db618a2ffd6954fcbea6e452ad6f07a6d75ea3d408fae33016008e2425c4a47142ca18574f7fc32de5bae580f8e3ac293f9bdac04383e8d9", "CS1": "041e508bfb51d8c825c61de7ac0166d8799f57dd0cd88bc32360554c01e7eae8001d0ad2cabb020752bdf964f109c105b553d6154ea29d4049034875bc0ca2f77f", "CS2": "04171eb06598bac089c17e9d8f57322a81e9d51386b2a64cb2212172a007bb895c1d7b8777790723cfde7ff10865dc8be6d7ecb05b368d921b013aa477be3d83d3", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "040f653272e6f706f8d99ed4ef5649b48de61abe80df52d8c6ae37690d8c93ee4715cb2f00c4d0f32437873949ae755d62a65c475cc93dc1f1ec3fd30c64b8ba7d", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0407aa341c7d90e588a3cd39450a120d51d8dfe23ec7be3e3e9bf73b372b35310c22545439505ab74dcca8b26b0df21bc3b9be3a00e3125d13f74c21d6356cec9f", "U": "040979195804c7bc75936f5e200ba8163b6437df159fce9720e695aad6434b4ad50b4a4991ad066842f0f68ed9eb9c90f42a7fd163648a255dcd9b8a79de434a6c", "SERVER_OUTPUT": 0, "Y": "204c9a9088bd422fa25b65b339946d1811623dc436df657f31f8862d2b682c95", "X": "047a1cba4dc20eedff0e0a409466c678d637d19e43e0903ac295db8f6adb90e5", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 295, "UT": "041bb27f75bc7d4eae44c06a50ddbc56b3bff5ae2898e23f6097fa2692976b0260163e60511e2c948fd7aa19c231cd4eb4be78979a6bff57a9e913e441f3f8c48d", "MS2": "1c9070df56f53df9e6e4793e80e932375b9018ebade0b34a361b6888fdf37362", "MS1": "1629c419479a0f4599cff79f8ae4660a9ff7abedc172d6a085dcf7b7111f8427", "CLIENT_SECRET": "041d67766d6c1a83ce3143f007aed50418981aeb1da39221bdeab50c7777593fc121c64de75c9afd53c90c2ef21ee836f07ff5154811ad40ef611e5d80b6cd8a0f"}, {"TimeValue": 1437055599, "SS1": "1bffdabfc7b124b565b63c68cd7d729d58731de2efeeef6c0d2ff990079d801e072cf1de9a7241288e2493bb56a58302bc93c051d5b6fbc2d2759fb200729df4043d21c3d4b1b924a76cebcfe291a216bbde558528a4dc1bf39a887c8cf505b0124b561bc0f2981e68a99c9f1d928f5786d623a1243155550d9efdd06ac3b2e5", "SS2": "045cc0441fb3b8445de7f3bad3b1ea052b345755a6be34ef4202e772430da71a0a8231939951f8bd4fa0c3b90150eae122493a355bc002e2bd84d64d0293c49707f1dce15592a0b619b658bd2c0114ab9b3fec031a5fdcebcdccfb0a361bba5d0b49b34088b5da55b64b4ea02960510c3264337f244a0a810c602d203272ee61", "DATE": 16728, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "13c9e266dec853d55771a206a2173048a5e338199f8960e170769541d79ab8c82365cfbb8e3526dfddd1db92247ae5d04ae59d2fe69d0dad5580df1543b1b9b21d9d9a86d60634a85035912a480a7de262de96f19b02777c6cff09975e71e652235b1bd87cef05a1451ad7ca246d4d04d49eeeb6f69b87337b2f22944f58bde3", "SEC": "040b99a1f5bd70ba3273537d45ae1cd54963ef9647535963d6cc31b5eb958a4fa61aee9e6a5210b5923ec710d8bc0e08d8e6357c13e5e6cc0ef6e8bfe0b759f4af", "TP2": "0412c26ae4d4f1fd4a83479582d57b35e6a170e721e19117b3c6cbf094bc5be0d521238d5a0b12f3c7fd96bf95f7427d16c309b04b348c242e9785ca0dd3ba821e", "TP1": "0419e5e632c5bef67e09220310cb2669e44f22003657b8d30bc97b241419b7857f1fab984824cb47f6b0b7b6890a1f93d646163184ef93358d60693d3e83b80577", "CS1": "04074a6fbc697e4a963927872fa2c829ebd1e538ce0b8bc11ccfbf39025e3623201173e3eb1ddf4ebead2dc36c22995f28258c28ae798db47497a63351958f30f1", "CS2": "04220fb08d38b101f09764fa302e28ea1d8d2105a729a2933cdbb508012ea7d3ea1e0604cc5f2e49b2ce1389b4931ae7177eb396abeb252b2ec6216441b9d36849", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "040357a71293ad35fd57a1bb13c81d9f2f0da146586ceaf9ccb43bcf0309636c631672b865056404678def84ac6c9962683622eda24ff8365602e4f1c9426e2bb1", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0412bbdc364eab5f1f633739f790d2e05205e3d621de8fc3decea436891a481bfd04380212197ec5010e264597f12892bad082c8bb2d10ca2d83208663d8c79ce0", "U": "040a6cf11160ff167d644c08802c9196dbc93abc9727e3d8bb3ae8ce9d03af47ed1470f190b35b36da421627c24fa019085532e639dd07ee476a8043afd4b5126e", "SERVER_OUTPUT": 0, "Y": "142ce655deabd8b75e6ace6eb421bdd6a8b1f2f3849a418e269543bdeb47dc4d", "X": "199bf825945fc2f03f25cc23740ca688df3c24fb0ec6f48ef71bef65cf260583", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 296, "UT": "041f4c977efdd77552a1fc534abbc46a2dcafcd8a7d3b94326367684670fe056520306c5c4e8fd5b118b69dbf577b2743f503325e0e132433ff904e1e9cec20fcb", "MS2": "23f1d03d5605cdba987afa073a08196fc693d1d2f52d4e3b0ae04d77cab57b89", "MS1": "19971f1fc24e4ab0a7c1964e9cc364ab6dba4a33e522abf9fb989c8319d4ce7d", "CLIENT_SECRET": "04115947fb92b8fcc745dda580775d94d09ada2b502cd2a80aaa2c666d18fbb5e9179c3c474c3192550eabdb3e48980e5db8807596620ed528599251099a0680e4"}, {"TimeValue": 1437055599, "SS1": "13e6be7a8b27caffb62e30ce4a09c142201b6681864ea90b67b9772e230857ea1a1fede53c25c6fa1bbd95624201e1b589fa872b0b2db57cd91ed72360b767480ab2e27088eb26f475b5c26b72b21eee400ee3748ab8e41b7eceb86781e95d630ef83d45b8ddf24c2a3a778f2a44c76d6975874b3c44acf744bacb4c0b4300b4", "SS2": "11bbcd2b0744e3b2c6dd9c24f27231190488201d2e2e323c7d947908b18b1b680192191fa7354fb60d5e6e58fa2b1d7df1ab9f335f0759b548ca39472e05c77f022cc8db0deb573ae288f36c6969244b7e836d2df8f245a469ce87f9ec8b979d1fe2d982803d8fc62735e4a1fd8e37e0f6538443f3b6555ed31daffa0100d746", "DATE": 16729, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "15e65dcba90c7ec484e8a440596da81c0371f1d936efd9b32939f12db6637fba0bebcbf0a0d413586656246cba7c0f9cdd0e31a53fc9d97e8551c2ba3cf83de81b404060a00058ba36497175a6be198fd870bab16719a74245fb03722979e16d17b3ef6960df82c09377b96e57d6c6130047304118c0eadf2c4a027a050df53e", "SEC": "04183d8bae963d4848ebb67e20798935a99e9e21b13be3327e388b40b191d0ad8d23bd218fbac4d3ac725c547305e9f89d0738c51fe2136b2762ffffc8e0392095", "TP2": "04035b3462cc4802a2ea54e5de36bc75b6523d68f2aeb8f79fdfef0d93b718661910ccb8fa5d754282c00fc3ba123f09f9af8ef5f17f29dbaac528d8ea046e5fa4", "TP1": "040ee419c93c3e080e2ea6d30c14c7785802c706c03fe5bbfcf9cbf3ab28f70a9e15eeec76dd765d7531381cab7e28cbfa996052b6de74622c4625a477ae8eb139", "CS1": "04135d0b1a26af91ff9f66e771ba534ef07149dcf076a7f9a82167478303b5a2eb0ff7671d8d9a73c5639327d042e9370cdfaaeef0436ce0758d1e469340add52c", "CS2": "0420abdcc62397e80afee44b0233f3538c95e6f92a8ce4b6d88a355f37fe5000c80bffd21219df5e1c7d733d85611b65e0522033084df2f148646dd28246fe3f89", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04048c166d27a41cbafc9f5000739efae130ac1ad81273057b8151d7f7cf8953c219adbee5848c84136050e9846090bf0ba79e8eb8e36532ab24c16432ee709609", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0403a7ad8f6de6e76cda38934afd68717a56086e9c4d363b698901a023cd4e1ab60204410d8071b4b4a5bb5f5d149d77bd8d87dd159310456e0dc9d7c0c25cae31", "U": "04103fa56dfec35d6082a29b442d14e2471f80c175762fbf49af4e95719e45679b2249b2bc5b81d2dae828988cca4ae6a1e81dbb5631b26e4a1c8e240d41a0c805", "SERVER_OUTPUT": 0, "Y": "0512449e491edbdd455b46affb331566acd2e15b1bd4427cab899237962a5444", "X": "112e8901cec278b59f5bc6cc4e7f6415c19ea8dfda8e0b76e97d342ac0dd7d04", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 297, "UT": "04209d4d222411602e0ab95685052117f422ad8c68708ecdc6a5df1c89fe545eff1429496160e3fe49096383d55339d65037b842bda7b377d0f0377c11d765141e", "MS2": "21d9195a1ae6687f79609a35f4c9107680f81df918c6e33b9a118cf81c08da16", "MS1": "0d5a51beff31d1a54e9d8d3b0a95835e9e3da964801053acaf4f89a4da1e7f60", "CLIENT_SECRET": "0414a2f3584aa0bfbf305826c4183c7de266dbed7fdc434ac424a9c12407505e99042e793456b8d5612cc05e3da0a981769cc3da8ecc9f39e784a0ef0c414b699e"}, {"TimeValue": 1437055599, "SS1": "208c6171b8d9ecca1dbf9b241e10bcf91dfb1fba536cbe2c6af8fb18fe761a270007b51d902e041dee53b8bec96cc5ee9a537f9e9d95f42de2aaded9ae148ac7071641ead08ea82ab473b28a1a1e8a64b3bedc0d195398a30fd39b35089cef71224d9054e71fddcf157e2d2ce3a285a276c4310fe485f34563072cd99d37b9f1", "SS2": "2375c770b2bdd8c189bd88a7ed9d2699a5915e64651c226711a0c09e56ed489c1d589d875082422315a38074cb679f981e99f7c75eccda6fb75b3bdf72484b0d0d90d69384c09357c5a4677a091ffc0713067e44e8c494efece27941f4c955750655f1c17ee9aa782f19a9edcf6bd92b986aac1a52f3c1fd4ddaf03a1d65e695", "DATE": 16730, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "0264b6e8039a8889398c1d4ca9fc31c1690631e8f14135d250da3c65ef76458f0683b580ec3f216022003e1e581a78bcbce7f723d333255d2a41c5d12d6b547c126539fbc6340a3469d0bcff2e5c62a25aeca401d59898933640a13a8cde25c10788baf7298de01e0d23f3d56fc42f37dd7914448f183b355b301825947e9e65", "SEC": "0403a241fec0988dd5649e9426b439de2864b5fb35c80e18e2f2eab07197a1bde503aacb392e9f1a2294af2fdee0ea652340c1fc8411eb97a493d3c2532e519c7b", "TP2": "040e429d090bcc43698f15a677dc3478e11f45fedc6d45cc149f9a7d6c77c256a4180fdf865e2359fa31076d4a564e85e98b844a1cacc7333d268b554f03d09cd2", "TP1": "0420beacb0b75c9bf385bdaf1ceaf67902c3591c0350acb1ea332c5de3155e0303177845d11ba0c80aa39df2845b83bf73638916997352b4f8a87b839ed7391c28", "CS1": "040d3adc4bc70505c2b11e8ed6341d8b1cdafed0d261029de21647de25c51e962507cc157b1fd06dd098e171f46862e1205e49975497235c43e3b0e2609af997d8", "CS2": "04228ee9171b85ed3a41cd68ba34e235ebdc2b1ce7c021efcb017fd696997fd57d04bdd188be8b3abc9b8dbc8916018205358299275450e21be720fe20f49761b1", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "0415f5d852594337504e774ee98178325c18e0ae0dff2554250350d767ed7c4c2a0f6a14bca94d1919caebaa10f82da2ea809e892c7cb2b2ee6f40091bc40797fe", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "041c94ce80164abc42e2dab4786ec7ce4e19fb01a4f71d694b391112ac670944b0220ee94102704428a030d02e4084435cbeb94104aaca84cbf8d747fe456717d5", "U": "0423c388e02d0571b3f7d436e2e57709f89beef80566681caba80189d44d76879f1014ea59fa343d7a9b6c14be9f1eab2f0a2cb0bff88e617ee97d6ada41ae3326", "SERVER_OUTPUT": 0, "Y": "0ee73012d3c452e58d4595195f9acba47f124b0003bdf14c64d0b0aad2565977", "X": "0d4e12d3fee376c63a570939cac53bb0740a75bdb075b41ed08b74b3b974f5af", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 298, "UT": "0403442ca5119f39c70031ae5fd7131ca981be42b60e7141136e58d37c838060be0c1f3cace932d4c881a81b0f9e580ab799fdc8c999f24c84d6f374c7fe0d90ea", "MS2": "1e3f7f3b083d53aee701de7c3079f29af639ffa1a5fe781102a1125be4e7270c", "MS1": "13d749ea9797c1af393a3c47ab7e17a32b33790be8a1b2d2bd4c86755dac5fdc", "CLIENT_SECRET": "0408fe63a20c8469456ca8cde0736710cb40db5e71923d23713045dfca69f99a881b0a04ed4c4c95947e7b88ef8bf259071160b73e474084f106b07f3d4559a592"}, {"TimeValue": 1437055599, "SS1": "189b380f7a912de8c3360d929c8412b286c0be1a7e101646c56e0616941408f3185d8801325011c31404268a39a8c8efd014e161fd39f701a68a9866a3f4eea20efe26dc1360584a3e7ca98ef5c3a6255b9a881e68eb2bbf8e33aa2f7d68cf291e8104d88337c62d7a7049e758e646d123c956ab68042f80d202ef6af9d68064", "SS2": "227fb8bbd6d530666cc12fb9a1b2f1deb84ac029db87c8d5b6d31c4342af6f1519bdfb7c135f122d5ac6cea431e56f96c0c236ac541fdfcabbf6745262ef555315ebee85f38564baa0a2388ce807025ec035c5b91b7136352413c22472a5496612ccff59d69f544cc522d586efdddac12ecf38fd812bccc10ae8b2a4f99728ee", "DATE": 16731, "PIN2": 6070, "PIN1": 6070, "SERVER_SECRET": "239c29371918bf1a4bee6692da73f69cbf3a90b92472feb7d4ed173155e9a31a209579cd2459d68cc68fba9ee1953a7fae81c45a2f5ff2890b6e0ead69714dc3146e5d621eef6d9bbd5fe330bb3fb229c10ea1e466b9ff5e68796a6abb1d22dd1a2ad2093cf5a6e6a7bcfb61950ab60dd80b3d3bb32e3ff73e9c73c160357864", "SEC": "0417334b3497b96006077a42cb3a240b2a60a0e1aaea4bf33244d2c59d4ba750121452e2b0140939052412597111207dff2369b2a0d654a5fa019cf50af846f03b", "TP2": "04000b3a8a8134021fcdda806c0b42172aef10f64b954cbcbb4856d170b3e592ee176dddb6255be23bd52b22a9743155fd699c580b934612fc9bc0ea604df19064", "TP1": "04103a0faa1075c5cabbc2dff9f9f30cad0f032cdd5d449e6f929c38a4258b45370a83c1a926696fd3a5a9b98b51a4b99f6b8cfdd08706e86cc4bcdb8a7c61b017", "CS1": "0416e57ab4973e7e11b7828a70653ffc94b38695f71bcbef9a53b18dabee680cb107b4f7f8b866c478196cdc1956ffc4bbe7e99246621cae1d0bf94a25cc06fa42", "CS2": "040fa5aa89178a8bc651777972f660f9a5d0a2ecbc95f6ec9760e42172537dec66147bd8e3d537317980fd636818688ab9b3280ca46a52e004c6a2f25c074a2a8a", "HASH_MPIN_ID_HEX": "8cd5c6ea9c25a6bda0698b8a2fdb6674ae05725a8c97c2084284468a1e799425", "TIME_PERMIT": "04119076f8054f9d4703756fc5fa41e8877a5fbbfae2034c3d6b02a6b474dfafe1168d6b6a8de5209d5447c6d26967c7e27b6c192a05017e4041bd7065d668dd93", "MPIN_ID_HEX": "7b226d6f62696c65223a20312c2022697373756564223a2022323031352d30372d31365431343a30363a33385a222c2022757365724944223a20223830636464663430663930626435626238336339393635366338333466366534406365727469766f782e636f6d222c202273616c74223a202235623139313236373464653363346561227d", "TOKEN": "0412942be63c7281a8ca64cd18590977cf936c7c1013d66137695d77a14ff147b71e96b32eee9fcf8010b22511413508c27284f14f136898948d7f114a0d3a2c03", "U": "04010a0eeaea17b3dd890a78b0ba667a82253065ac184833ea41cfe49b966101781aee0d0e2d58ef027b745cce95f73b4d426a3907aa3dd6017c8ed0de9fe70b68", "SERVER_OUTPUT": 0, "Y": "23f11458aadadedcaa8e6d7de4c393ca239b4419c9c24ca245a425ae8c60555d", "X": "22f3de9dc2bbbfbf15fc5559cd56950dfe06a8b2d26393ac9d2f62958bc36dc4", "mpin_id": "{\"mobile\": 1, \"issued\": \"2015-07-16T14:06:38Z\", \"userID\": \"80cddf40f90bd5bb83c99656c834f6e4@certivox.com\", \"salt\": \"5b1912674de3c4ea\"}", "test_no": 299, "UT": "04182893c0d34aa7813dab39233de98e31b49f407f70f540143b09aa1f3c86632a165720e339431a20151589e238b0d6fbc43e27d10556d194e67d82bfeffe971e", "MS2": "0cfe5e3726423f7bbf18a3060afc402cb179d0a993eed30ab92474432159e425", "MS1": "02d118e5ce70145d74c91b2b3b1f2ad384589d8b3788c16bedf0dd06531434fc", "CLIENT_SECRET": "0415e3a660ec8cd98875d30186c474f1dadcd332742225e3fec0aed078fad549550d44bc055807767c03e78cb10853a7ad5f9d4eebd5e8046574cc9759d0e02ce2"}]
\ No newline at end of file
diff --git a/version22/amcl22.pdf b/version22/amcl22.pdf
new file mode 100644
index 0000000..b5ba27f
--- /dev/null
+++ b/version22/amcl22.pdf
Binary files differ
diff --git a/version22/bigtobig.cpp b/version22/bigtobig.cpp
new file mode 100644
index 0000000..fbc89ea
--- /dev/null
+++ b/version22/bigtobig.cpp
@@ -0,0 +1,292 @@
+/*
+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.
+*/
+
+//
+// Program to convert from Big to AMCL BIG format
+// cl /O2 bigtobig.cpp big.cpp miracl.lib
+// g++ -O2 bigtobig.cpp big.cpp miracl.a -o bigtobig
+//
+//
+
+#include <iostream>
+#include "zzn.h"
+
+using namespace std;
+
+Miracl precision=100;
+
+// Code to parse formula in command line
+// This code isn't mine, but its public domain
+// Shamefully I forget the source
+//
+// NOTE: It may be necessary on some platforms to change the operators * and #
+//
+
+#if defined(unix)
+#define TIMES '.'
+#define RAISE '^'
+#else
+#define TIMES '*'
+#define RAISE '#'
+#endif
+
+Big tt;
+static char *ss;
+
+void eval_power (Big& oldn,Big& n,char op)
+{
+        if (op) n=pow(oldn,toint(n));    // power(oldn,size(n),n,n);
+}
+
+void eval_product (Big& oldn,Big& n,char op)
+{
+        switch (op)
+        {
+        case TIMES:
+                n*=oldn; 
+                break;
+        case '/':
+                n=oldn/n;
+                break;
+        case '%':
+                n=oldn%n;
+        }
+}
+
+void eval_sum (Big& oldn,Big& n,char op)
+{
+        switch (op)
+        {
+        case '+':
+                n+=oldn;
+                break;
+        case '-':
+                n=oldn-n;
+        }
+}
+
+void eval (void)
+{
+        Big oldn[3];
+        Big n;
+        int i;
+        char oldop[3];
+        char op;
+        char minus;
+        for (i=0;i<3;i++)
+        {
+            oldop[i]=0;
+        }
+LOOP:
+        while (*ss==' ')
+        ss++;
+        if (*ss=='-')    /* Unary minus */
+        {
+        ss++;
+        minus=1;
+        }
+        else
+        minus=0;
+        while (*ss==' ')
+        ss++;
+        if (*ss=='(' || *ss=='[' || *ss=='{')    /* Number is subexpression */
+        {
+        ss++;
+        eval ();
+        n=tt;
+        }
+        else            /* Number is decimal value */
+        {
+        for (i=0;ss[i]>='0' && ss[i]<='9';i++)
+                ;
+        if (!i)         /* No digits found */
+        {
+                cout <<  "Error - invalid number" << endl;
+                exit (20);
+        }
+        op=ss[i];
+        ss[i]=0;
+        n=atoi(ss);
+        ss+=i;
+        *ss=op;
+        }
+        if (minus) n=-n;
+        do
+        op=*ss++;
+        while (op==' ');
+        if (op==0 || op==')' || op==']' || op=='}')
+        {
+        eval_power (oldn[2],n,oldop[2]);
+        eval_product (oldn[1],n,oldop[1]);
+        eval_sum (oldn[0],n,oldop[0]);
+        tt=n;
+        return;
+        }
+        else
+        {
+        if (op==RAISE)
+        {
+                eval_power (oldn[2],n,oldop[2]);
+                oldn[2]=n;
+                oldop[2]=RAISE;
+        }
+        else
+        {
+                if (op==TIMES || op=='/' || op=='%')
+                {
+                eval_power (oldn[2],n,oldop[2]);
+                oldop[2]=0;
+                eval_product (oldn[1],n,oldop[1]);
+                oldn[1]=n;
+                oldop[1]=op;
+                }
+                else
+                {
+                if (op=='+' || op=='-')
+                {
+                        eval_power (oldn[2],n,oldop[2]);
+                        oldop[2]=0;
+                        eval_product (oldn[1],n,oldop[1]);
+                        oldop[1]=0;
+                        eval_sum (oldn[0],n,oldop[0]);
+                        oldn[0]=n;
+                        oldop[0]=op;
+                }
+                else    /* Error - invalid operator */
+                {
+                        cout <<  "Error - invalid operator" << endl;
+                        exit (20);
+                }
+                }
+        }
+        }
+        goto LOOP;
+}
+
+void output(int w,Big t,Big m)
+{
+	Big y=t;
+
+	for (int i=0;i<w;i++)
+	{
+		cout << "0x" << y%m ;
+		if (i<w-1) cout << ",";
+		y/=m;
+	}
+	cout << endl;
+}
+
+int main(int argc, char **argv)
+{
+    int i,ip,chunk,basebits;
+    Big n,m;
+    BOOL gotP,gotA,gotB;
+    int Base;
+    miracl *mip=&precision;
+    argv++; argc--;
+    if (argc<1)
+    {
+        cout << "Program converts from Big to BIG" << endl;
+        cout << "bigtobig <big number> <chunk>> <basebits>" << endl;
+        cout << "OR" << endl;
+        cout << "bigtobig <formula for big number> <chunk>> <basebits>" << endl;
+#if defined(unix)
+        cout << "e.g. bigtobig -f 2^255-19 32 29" << endl;
+#else
+        cout << "e.g. bigtobig -f 2#255-19 32 29" << endl;
+#endif
+        cout << "To input Big number in Hex, precede with -h" << endl;
+        return 0;
+    }
+
+    ip=0;
+    gprime(1000);
+    gotP=gotA=gotB=FALSE;
+    n=0;
+    Base=10;
+    while (ip<argc)
+    { 
+        if (!gotP && strcmp(argv[ip],"-f")==0)
+        {
+            ip++;
+            if (!gotP && ip<argc)
+            {
+
+                ss=argv[ip++];
+                tt=0;
+                eval();
+                n=tt;
+                gotP=TRUE;
+                continue;
+            }
+            else
+            {
+                cout << "Error in command line" << endl;
+                return 0;
+            }
+        }
+ 
+
+        if (strcmp(argv[ip],"-h")==0)
+        {
+            ip++;
+            Base=16;
+            continue;
+        }
+   
+        if (!gotP)
+        {
+            mip->IOBASE=Base;
+            n=argv[ip++];
+            mip->IOBASE=10;
+            gotP=TRUE;
+            continue;
+        }
+        if (!gotA) 
+        {
+            mip->IOBASE=Base;
+            chunk=atoi(argv[ip++]);
+            gotA=TRUE;
+            continue;
+        }
+        if (!gotB) 
+        {
+            mip->IOBASE=Base;
+            basebits=atoi(argv[ip++]);
+            gotB=TRUE;
+            continue;
+        }
+        cout << "Error in command line" << endl;
+        return 0;
+    }
+    if (!gotP || !gotA || !gotB)
+    {
+        cout << "Error in command line" << endl;
+        return 0;
+    }
+
+	mip->IOBASE=16;
+
+	m=pow((Big)2,basebits);
+
+	output(1+bits(n)/basebits,n,m);
+
+    return 0;
+}
+
diff --git a/version22/blsgen.cpp b/version22/blsgen.cpp
new file mode 100644
index 0000000..9b08b7c
--- /dev/null
+++ b/version22/blsgen.cpp
@@ -0,0 +1,194 @@
+/*
+Copyright 2015 CertiVox UK Ltd
+
+This file is part of The CertiVox MIRACL IOT Crypto SDK (MiotCL)
+
+MiotCL is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+MiotCL is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with MiotCL.  If not, see <http://www.gnu.org/licenses/>.
+
+You can be released from the requirements of the license by purchasing 
+a commercial license.
+*/
+
+/* BLSGEN - Helper MIRACL program to generate constants for BlS curves 
+
+(MINGW build)
+
+g++ -O3 blsgen.cpp big.cpp zzn.cpp ecn.cpp zzn2.cpp ecn2.cpp miracl.a -o blsgen.exe
+
+This ONLY works for D-type curves of the form y^2=x^3+1, with a positive x parameter
+
+*/
+
+#include <iostream>
+#include "big.h"
+#include "ecn.h"
+#include "zzn2.h"
+#include "ecn2.h"
+
+using namespace std;
+
+Miracl precision(20,0);
+
+Big output(int chunk,int w,Big t,Big m)
+{
+	Big last,y=t;
+
+	cout << "{";
+	for (int i=0;i<w;i++)
+	{
+		last=y%m;
+		cout << "0x" << last;
+		y/=m;
+		if (i==w-1) break;
+		if (chunk==64) cout << "L,";
+		else cout << ",";
+	}
+
+	if (chunk==64) cout << "L}";
+	else cout << "}";
+	return last;
+}
+
+void set_frobenius_constant(ZZn2 &X)
+{
+    Big p=get_modulus();
+    switch (get_mip()->pmod8)
+    {
+    case 5:
+         X.set((Big)0,(Big)1); // = (sqrt(-2)^(p-1)/2     
+         break;
+    case 3:                    // = (1+sqrt(-1))^(p-1)/2                                
+         X.set((Big)1,(Big)1);      
+         break;
+   case 7: 
+         X.set((Big)2,(Big)1); // = (2+sqrt(-1))^(p-1)/2
+    default: break;
+    }
+    X=pow(X,(p-1)/6);
+}
+
+/* Fill in this bit yourself.... */
+
+#define CHUNK 64   /* processor word size */
+#define MBITS 455  /* Modulus size in bits */
+
+/* This next from output of check.cpp program */
+#define BASEBITS 60
+
+#define MODTYPE  NOT_SPECIAL
+#define CURVETYPE WEIERSTRASS
+#define CURVE_A 0  // like A parameter in CURVE: y^2=x^3+Ax+B
+
+/* .....to here */
+
+#define WORDS (1+((MBITS-1)/BASEBITS))
+
+int main()
+{
+	miracl *mip=&precision;
+	Big p,q,R,Beta;
+	Big m,x,y,w,t,c,n,r,a,b,gx,gy,B,xa,xb,ya,yb,cof;
+	Big np,PP,TT,FF;
+	ZZn cru;
+	ZZn2 X;
+	ECn P;
+	ECn2 Q;
+	ZZn2 Xa,Ya;
+	int i,j;
+
+	mip->IOBASE=16;
+
+/* Set BLS value x which determines curve  */
+
+	x= (char *)"10002000002000010007";   
+	B=1;
+	x= (char *)"10000000000004100100";
+	B=7;
+	x= (char *)"10000020000080000800";
+	B=10;
+/* ... to here */
+
+	p=(pow(x,6)-2*pow(x,5)+2*pow(x,3)+x+1)/3;
+    ecurve((Big)0,B,p,MR_AFFINE);
+    mip->TWIST=MR_SEXTIC_D;
+	t=x+1;
+    q=pow(x,4)-x*x+1;
+	cof=(p+1-t)/q;
+
+//	cout << "cof= " << (p+1-t)/q << endl;
+
+	gx=-1; gy=3;
+	if (!P.set(gx,gy))
+	{
+		cout << "Failed - try another x " << endl;
+		return 0;
+	}
+
+//	while (!P.set(gx) || (cof*P).iszero()) gx=gx+1;
+
+	P*=cof;
+	P.get(gx,gy);
+
+	cout << "MOD8 " << p%8 << endl;
+
+	m=pow((Big)2,BASEBITS);
+		
+	cout << "MConst=0x" << inverse(m-p%m,m) << ";" << endl;	
+
+	cout << "Modulus="; output(CHUNK,WORDS,p,m); cout << ";" << endl;
+	
+	cout << "CURVE_Order="; output(CHUNK,WORDS,q,m); cout << ";" << endl;
+	cout << "CURVE_Cof="; output(CHUNK,WORDS,cof,m); cout << ";" << endl;
+	cout << "CURVE_B= "; output(CHUNK,WORDS,B,m); cout << ";" << endl;
+	cout << "CURVE_Gx="; output(CHUNK,WORDS,gx,m); cout << ";" << endl;
+	cout << "CURVE_Gy="; output(CHUNK,WORDS,gy,m); cout << ";" << endl;
+	cout << endl;
+	cout << "CURVE_Bnx="; output(CHUNK,WORDS,x,m); cout << ";" << endl;
+
+	modulo(p);
+
+	cru=pow((ZZn)2,(p-1)/3);
+	cru*=cru;   // right cube root of unity
+
+	cout << "CURVE_Cru="; output(CHUNK,WORDS,(Big)cru,m); cout << ";" << endl;
+
+	set_frobenius_constant(X);
+	X.get(a,b);
+	cout << "CURVE_Fra="; output(CHUNK,WORDS,a,m); cout << ";" << endl;
+	cout << "CURVE_Frb="; output(CHUNK,WORDS,b,m); cout << ";" << endl;
+
+	while (!Q.set(randn2())) ;
+
+	TT=t*t-2*p;
+	PP=p*p;
+	FF=sqrt((4*PP-TT*TT)/3);
+	np=PP+1-(-3*FF+TT)/2;  // 2 possibilities...
+
+	Q=(np/q)*Q;
+
+	Q.get(Xa,Ya);
+	Xa.get(a,b);
+	cout << "CURVE_Pxa="; output(CHUNK,WORDS,a,m); cout << ";" << endl;
+	cout << "CURVE_Pxb="; output(CHUNK,WORDS,b,m); cout << ";" << endl;
+	Ya.get(a,b);
+	cout << "CURVE_Pya="; output(CHUNK,WORDS,a,m); cout << ";" << endl;
+	cout << "CURVE_Pyb="; output(CHUNK,WORDS,b,m); cout << ";" << endl;
+
+	Q*=q;
+	if (!Q.iszero())
+	{
+		cout << "**** Failed ****" << endl;
+		cout << "\nQ= " << Q << endl << endl;
+	}
+}
diff --git a/version22/bngen.cpp b/version22/bngen.cpp
new file mode 100644
index 0000000..da4c10c
--- /dev/null
+++ b/version22/bngen.cpp
@@ -0,0 +1,251 @@
+/*
+Copyright 2015 CertiVox UK Ltd
+
+This file is part of The CertiVox MIRACL IOT Crypto SDK (MiotCL)
+
+MiotCL is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+MiotCL is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with MiotCL.  If not, see <http://www.gnu.org/licenses/>.
+
+You can be released from the requirements of the license by purchasing 
+a commercial license.
+*/
+
+/* BNGEN - Helper MIRACL program to generate constants for BN curve 
+
+(MINGW build)
+
+g++ -O3 bngen.cpp big.cpp zzn.cpp zzn2.cpp ecn2.cpp miracl.a -o bngen.exe
+
+This ONLY works for D-type curves of the form y^2=x^3+2, with a negative x parameter, and x=3 mod 4
+
+*/
+
+#include <iostream>
+#include "big.h"
+#include "zzn2.h"
+#include "ecn2.h"
+
+using namespace std;
+
+Miracl precision(20,0);
+
+Big output(int chunk,int w,Big t,Big m)
+{
+	Big last,y=t;
+
+	cout << "{";
+	for (int i=0;i<w;i++)
+	{
+		last=y%m;
+		cout << "0x" << last;
+		y/=m;
+		if (i==w-1) break;
+		if (chunk==64) cout << "L,";
+		else cout << ",";
+	}
+
+	if (chunk==64) cout << "L}";
+	else cout << "}";
+	return last;
+}
+
+void q_power_frobenius(ECn2 &A,ZZn2 &F)
+{ 
+// Fast multiplication of A by q (for Trace-Zero group members only)
+    ZZn2 x,y,z,w,r;
+
+    A.get(x,y);
+
+	w=F*F;
+	r=F;
+
+	if (get_mip()->TWIST==MR_SEXTIC_M) r=inverse(F);  // could be precalculated
+	if (get_mip()->TWIST==MR_SEXTIC_D) r=F;
+
+	w=r*r;
+	x=w*conj(x);
+	y=r*w*conj(y);
+
+    A.set(x,y);
+}
+
+//
+// Faster Hashing to G2 - Fuentes-Castaneda, Knapp and Rodriguez-Henriquez
+//
+
+void cofactor(ECn2& S,ZZn2 &F,Big& x)
+{
+	ECn2 T,K;
+	T=S;
+	T*=-x;
+	T.norm();
+	K=(T+T)+T;
+	K.norm();
+	q_power_frobenius(K,F);
+	q_power_frobenius(S,F); q_power_frobenius(S,F); q_power_frobenius(S,F); 
+	S+=T; S+=K;
+	q_power_frobenius(T,F); q_power_frobenius(T,F);
+	S+=T;
+	S.norm();
+}
+
+void set_frobenius_constant(ZZn2 &X)
+{
+    Big p=get_modulus();
+    switch (get_mip()->pmod8)
+    {
+    case 5:
+         X.set((Big)0,(Big)1); // = (sqrt(-2)^(p-1)/2     
+         break;
+    case 3:                    // = (1+sqrt(-1))^(p-1)/2                                
+         X.set((Big)1,(Big)1);      
+         break;
+   case 7: 
+         X.set((Big)2,(Big)1); // = (2+sqrt(-1))^(p-1)/2
+    default: break;
+    }
+    X=pow(X,(p-1)/6);
+}
+
+/* Fill in this bit yourself.... */
+
+#define CHUNK 64   /* processor word size */
+#define MBITS 454  /* Modulus size in bits */
+
+/* This next from output of check.cpp program */
+#define BASEBITS 60
+
+#define MODTYPE  NOT_SPECIAL
+#define CURVETYPE WEIERSTRASS
+#define CURVE_A 0  // like A parameter in CURVE: y^2=x^3+Ax+B
+
+/* .....to here */
+
+#define WORDS (1+((MBITS-1)/BASEBITS))
+
+int main()
+{
+	miracl *mip=&precision;
+	Big p,q,R,cru;
+	Big m,x,y,w,t,c,n,r,a,b,gx,gy,B,xa,xb,ya,yb,cof;
+	ZZn2 X;
+	ECn2 Q;
+	ZZn2 Xa,Ya;
+	int i;
+
+	mip->IOBASE=16;
+
+/* Set BN value x which determines curve - note that x is assumed to be negative */
+
+//  x=(char *)"6000000000101041";    // for full 256-bit GT_STRONG parameter
+//	x=(char *)"4080000000000001";    // Fast but not not GT_STRONG parameter
+
+//	x=(char *)"4000020100608205"; // G2 and GT-Strong parameter
+//	x=(char *)"4000000003C012B1";    // CertiVox's GT_STRONG parameter
+//	x=(char *)"10000000000000000000004000000000000001001";
+//	x=(char *)"4000806000004081";    // Best GT_STRONG parameter
+
+/* Fill in this bit yourself... */
+
+//	x=(char *)"4080000000000001";    // Nogami's fast parameter
+	x=(char *)"10000010000000000000100000001";
+//	x=(char *)"10000000000000000000004000000000000001001";
+
+/* ... to here */
+
+	p=36*pow(x,4)-36*pow(x,3)+24*x*x-6*x+1;
+    ecurve((Big)0,(Big)2,p,MR_AFFINE);
+    mip->TWIST=MR_SEXTIC_D;
+	t=6*x*x+1;
+	q=p+1-t;
+	cof=1;
+	B=2;
+	gx=p-1;
+	gy=1;
+
+	cout << "MOD8 " << p%8 << endl;
+
+	m=pow((Big)2,BASEBITS);
+		
+	cout << "MConst=0x" << inverse(m-p%m,m) << ";" << endl;	
+
+	cout << "Modulus="; output(CHUNK,WORDS,p,m); cout << ";" << endl;
+	
+	cout << "CURVE_Order="; output(CHUNK,WORDS,q,m); cout << ";" << endl;
+	cout << "CURVE_Cof="; output(CHUNK,WORDS,cof,m); cout << ";" << endl;
+	cout << "CURVE_B= "; output(CHUNK,WORDS,B,m); cout << ";" << endl;
+	cout << "CURVE_Gx="; output(CHUNK,WORDS,gx,m); cout << ";" << endl;
+	cout << "CURVE_Gy="; output(CHUNK,WORDS,gy,m); cout << ";" << endl;
+	cout << endl;
+	cout << "CURVE_Bnx="; output(CHUNK,WORDS,x,m); cout << ";" << endl;
+
+	cru=(18*pow(x,3)-18*x*x+9*x-2);
+	cout << "CURVE_Cru="; output(CHUNK,WORDS,cru,m); cout << ";" << endl;
+
+	set_frobenius_constant(X);
+	X.get(a,b);
+	cout << "CURVE_Fra="; output(CHUNK,WORDS,a,m); cout << ";" << endl;
+	cout << "CURVE_Frb="; output(CHUNK,WORDS,b,m); cout << ";" << endl;
+
+	Xa.set((ZZn)0,(ZZn)-1);
+	Ya.set((ZZn)1,ZZn(0));
+	Q.set(Xa,Ya);
+
+//		cofactor(Q,X,x);
+
+	Q=(p-1+t)*Q;
+
+	Q.get(Xa,Ya);
+	Xa.get(a,b);
+	cout << "CURVE_Pxa="; output(CHUNK,WORDS,a,m); cout << ";" << endl;
+	cout << "CURVE_Pxb="; output(CHUNK,WORDS,b,m); cout << ";" << endl;
+	Ya.get(a,b);
+	cout << "CURVE_Pya="; output(CHUNK,WORDS,a,m); cout << ";" << endl;
+	cout << "CURVE_Pyb="; output(CHUNK,WORDS,b,m); cout << ";" << endl;
+
+//		Q*=q;
+//		cout << "Q= " << Q << endl;
+
+
+	cout << "CURVE_W[2]={"; output(CHUNK,WORDS,6*x*x-4*x+1,m);cout << ","; output(CHUNK,WORDS,(2*x-1),m); cout << "};" << endl;
+	cout << "CURVE_SB[2][2]={"; cout << "{"; output(CHUNK,WORDS,6*x*x-2*x,m); cout << ","; output(CHUNK,WORDS,(2*x-1),m); cout << "}";cout << ","; cout << "{"; output(CHUNK,WORDS,(2*x-1),m); cout << ","; output(CHUNK,WORDS,q-(6*x*x-4*x+1),m); cout << "}"; cout << "};" << endl;
+
+	cout << "CURVE_WB[4]={"; output(CHUNK,WORDS,2*x*x-3*x+1,m); cout << ","; output(CHUNK,WORDS,12*x*x*x-8*x*x+x,m); 
+	cout << ","; output(CHUNK,WORDS,6*x*x*x-4*x*x+x,m); cout << ","; output(CHUNK,WORDS,2*x*x-x,m); cout << "};" << endl;
+	
+	cout << "CURVE_BB[4][4]={"; 
+	cout << "{";
+	output(CHUNK,WORDS,q-x+1,m); 
+	cout << ","; output(CHUNK,WORDS,q-x,m); 
+	cout << ","; output(CHUNK,WORDS,q-x,m); 
+	cout << ","; output(CHUNK,WORDS,2*x,m); 
+	cout << "}";
+
+	cout << ","; cout << "{";output(CHUNK,WORDS,2*x-1,m); 
+	cout << ","; output(CHUNK,WORDS,q-x,m); 
+	cout << ","; output(CHUNK,WORDS,q-x+1,m); 
+	cout << ","; output(CHUNK,WORDS,q-x,m); 
+	cout << "}";
+	cout << ","; cout << "{"; output(CHUNK,WORDS,2*x,m); 
+	cout << ","; output(CHUNK,WORDS,2*x-1,m); 
+	cout << ","; output(CHUNK,WORDS,2*x-1,m); 
+	cout << ","; output(CHUNK,WORDS,2*x-1,m); 
+	cout << "}";
+
+	cout << ","; cout << "{"; output(CHUNK,WORDS,x+1,m); 
+	cout << ","; output(CHUNK,WORDS,4*x-2,m); 
+	cout << ","; output(CHUNK,WORDS,q-2*x-1,m); 
+	cout << ","; output(CHUNK,WORDS,x+1,m); 
+	cout << "}";
+	cout << "};" << endl;
+}
diff --git a/version22/c/CARSK.pem b/version22/c/CARSK.pem
new file mode 100644
index 0000000..743aead
--- /dev/null
+++ b/version22/c/CARSK.pem
@@ -0,0 +1,54 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-256-CBC,E7A447797FE65D8D1309B743D8BA74B7
+
+G+ZhtxB+W4fKo11fAzggY0OOOB1RAwwSZFZ0DhlYEl76BLMUlXUfiziGQvpKcKdW
+aKcCPqmWw0TFkgwdwRB1NPu2tX786tNF3tIQa33TEuaY1ekyP9DpQdGksNHEIZ5N
+fCW22KJ+7lcm5/0G8IJXXUAAXiE65o+X+6vlmT9nzSPlCKOZvb0ITtahuphzg6l3
+QmXHYYtflKoqv9mFo63IGIp2EXjAlJUlVs+8f1NG+8b4J0KrHXx5MmvNBn+86GEV
+8lyryqgVFRxfbcvDI2s7GGLW4KZCDCRxRrG3GTtXRjJaVjw7VutL1teUfHKOegpA
+iFa0HNpILpqu6K99DBcteJaFxW3gOr3PdaylC046G+P059AnBA86lsJedKjbJ3WW
+DXtOawuBIQ3iIrGJ/q5vMK7cbAG785HOaqMQth0YPB/VFklsjAd/RW2CKr94ggB9
+wU1/IUcJ25pz/ph/7h7KDjoxIa1OEx5EHzzrFc88jGAmEBSfx6J5tU2GtruJhoqr
+SpiW36KQt+xFydfjywxO32BQ9YPae1yeQQwrX67YBNUkQhQpff7KxqqQJt7wqAVL
+vD4jthqRHOutco/It0cuqyO8dK01UDB6UIZdRlJuJ83HmqI+3YDtd2MOUIteSXMb
+4wAhMf1XFB6FQUuzB9Nc85wXWa5a7qyP63VMoPgiqgh7g5Is52hlcFcIBz6GE+h6
+Oz8FnaVX5K7Co2XojTJ3f99t5oEvF3aMPbCnG6izFQYNH+o8XTxRrldpb7hvoU6t
+z3lh4i8p2lq/DO1F8C9jKX0nJiSK311beuqkb0pA4VBPYNYBvx+UP3zBdcE82sab
+2flx1m6/OrJnyDMAOZAUFdbarU4AFJgLrBWbDjouCDHlQLZjY6ubBlvmslzY9QdR
+A1ssy1+wi39bM6ZSnrS1310/JDQPdIrd6Srh6e+54xiJHpjcvqE77uBeeje9ilHB
+pXdKi6Hv873yrI5T/F5zonKoFc1OO4cOrc8MLaQs0kJTcjXdg9uNk3AYKDYyq5JV
+gvJU2c/W/Z4pq0ve2ekETXjaoz2DSzbg1LGgzy/AOdPukmNgADn9qRyNtgwr30ix
+kDRjEG9bt5unkskXjdqtwl6mKiYvtM2SPfncdyCW3tqW++a7GvlA1TLecgzw9t40
++m0gKcIBj/vy6VFiLluQy7J59+MD6BNVxSeFvR2gMsj1sIxsIrq4lxPyG4knp3RA
+JeKTDes5DrquboJ1usl2ra8v5njJB8phHDVss4rBtlWuw5zBagaTN2PU8GLzmte6
+6PeagGDYNl2zoTMVOtTQ1BYDE08IS6ZNqSftrkGx4ypDnI5EHqoAl+ksSenGq2eg
+0/vW768hHSmQXIZHsV6YuI2nqYoM+SDAAFg38hnrtoIYEf0XYhHhr3hasL1ckWxG
+Q/fAlZynbxKL98KKB47eXXky0CHeJ77zICD1sotXIJJN4yMeDW14HIFCV/G9l+RI
+NYHCYzlnoaz244TTidsyYt02GYbR3zshhUw1CNn4THHQl9p4o7jYO/gFZtelc3+V
+SeVOKCXiSnJPhPiFVbnhlpJ7+4GhdpZRi84a6aLRinOUZf0WjYspOKhEaPOP5e1m
+ZKgC6vqqWawN+NQhHNG/S8Opu/TAt0hNE5fCYUUdWCL3MmuJPSsJ0orEtV3TAqLz
+q4znU2fzh3nuTKVWxeHbiVJ8dW50JhhixDYW4KrW8U/KHpqIRc3CztZllFrH/5ly
+al1FqhsNt4DgJwgqz34MMtKFOWw5K9/DPB/Dy0s9BrxkE5B6dxwj5S9RcVMkkkw/
+xVF2qt7ApLcPl84iQtP+Dz+bGWCL7LeeO5JG42Al4M3buO5b+34N4CpRHZh5E6AW
+uRbFuY/RiiqOxG+PQmWRdnEReBf4ORgocr5Kv3PAjp2LUf4aeSBsmml2CV7lgJue
+BOPJuiHL9YTfBchABi1dkMTjXUshtbtxLmBVJmkFsaTsMZsKKKRuIk+O80yYOncd
+uF+vKn1+F1hMV84ejIjLjreq+yTSDvVlmQn5v4jbDLtlpYBFoaMPq1GBqt0ZYSrK
+/sy/sy+jzneESlb520jOtSd2sryXL3jJOxJauZltALmJ5ZqImJ1NXZ8vTTwLmMaA
+DG3PqtZprI8oOj/iPXCcMPXkaLWJ+lVIfIqfxXYSMwj9ZVYoRBaYmym33v7pZtkn
+/8zLXv8J19LSoG+Ykfaf7Sf8fi0FzRmrj7jjXc2Sf5m1PhS2Ss17J8YydXeulKER
+M1TPOcfrkvdHZzt+ECNkqDxbbskaUTm9HdZ5HTdybnLryQalEzR9jzC02QobDOiI
+eQ6j0MjEpK4KQ9HY+deZiFysKQopvBjD7uSoq8gTBtLD4gpYVveD7Y5tlwVknrhl
+iFhdRCAgC6XLE+N7PkQm+nyI9T/IERSP9zDQyTguJKP4sq3Hl6hCkjuuogD6nLmP
+pKL4z+u0pqEakNExFxsDL/hf2G3KnFEJHhtT4/JlxuuJhdKs1uCO7zzWratwbFM1
+EQ9euYxLutt/5sNOaU+uabmk4R4ziRsdFYDOHBQR3IhoUJ9L4UhPvMZTo+ZSHpWC
+ellUk5UspPR3pzcd+lnQQGNTkwzMWayhSFfFJ6sdvfd1TTNflYpFhLHOD+ZSx4go
+/VrkSOkoXZtdr8a6cqOI1wOQIoeYjama4h+R+XW1jrc52GHchhrx7ZPjWGllYN5g
+ypzWl9gFbGGfx1gmIt6OCfCIcGxOMS7o5taCUpjiqU75Ts4Ri+/c6RJcI3CqBBT6
+mJ+nSfTZ7hMTaCmmmkYbvcCcAVZ9W/IxyVMj/p7pI7sH65vz3mNC7E/veF7rlSSZ
+EvgSjv12FgmD5rGtW5b0bbbylOvRygo1BpgCWSp91R22Yw+pjZilSvy0kWEMq2yx
+d6sLdkjZgLtp2NPMCM51OpuO0Hidd7KwdaJoB5rJwGs1+JWKtv/Xr4cSBXzpgDWl
+LxaGwC0KcDVoGRqvJldGuCpdN56yC46njzgZmQBq2QXthrJ1wveMiwpyFd/fu4KJ
+gu+OlNzMvZRz9zJkfHdswnx/P/E+FR/yv+W1ZKKhb6hBHoW7HOuJecjmbZpD562Y
+snzQ+Ehc3H88Mykzcc/iHZabNbP+M2TcPQ5eLvd2oPKsSFZw7EHU1B6XFpzk6r8x
+-----END RSA PRIVATE KEY-----
diff --git a/version22/c/aes.c b/version22/c/aes.c
new file mode 100644
index 0000000..f876c51
--- /dev/null
+++ b/version22/c/aes.c
@@ -0,0 +1,702 @@
+/*
+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.
+*/
+
+
+/*
+ * Implementation of the NIST Advanced Ecryption Standard
+ *
+ * SU=m, SU is Stack Usage
+ */
+
+#include <stdlib.h>
+#include "arch.h"
+#include "amcl.h"
+
+/* this is fixed */
+#define NB 4
+
+/* Rotates 32-bit word left by 1, 2 or 3 byte  */
+
+#define ROTL8(x) (((x)<<8)|((x)>>24))
+#define ROTL16(x) (((x)<<16)|((x)>>16))
+#define ROTL24(x) (((x)<<24)|((x)>>8))
+
+static const uchar InCo[4]= {0xB,0xD,0x9,0xE}; /* Inverse Coefficients */
+
+static const uchar ptab[]=
+{
+    1,3,5,15,17,51,85,255,26,46,114,150,161,248,19,53,
+    95,225,56,72,216,115,149,164,247,2,6,10,30,34,102,170,
+    229,52,92,228,55,89,235,38,106,190,217,112,144,171,230,49,
+    83,245,4,12,20,60,68,204,79,209,104,184,211,110,178,205,
+    76,212,103,169,224,59,77,215,98,166,241,8,24,40,120,136,
+    131,158,185,208,107,189,220,127,129,152,179,206,73,219,118,154,
+    181,196,87,249,16,48,80,240,11,29,39,105,187,214,97,163,
+    254,25,43,125,135,146,173,236,47,113,147,174,233,32,96,160,
+    251,22,58,78,210,109,183,194,93,231,50,86,250,21,63,65,
+    195,94,226,61,71,201,64,192,91,237,44,116,156,191,218,117,
+    159,186,213,100,172,239,42,126,130,157,188,223,122,142,137,128,
+    155,182,193,88,232,35,101,175,234,37,111,177,200,67,197,84,
+    252,31,33,99,165,244,7,9,27,45,119,153,176,203,70,202,
+    69,207,74,222,121,139,134,145,168,227,62,66,198,81,243,14,
+    18,54,90,238,41,123,141,140,143,138,133,148,167,242,13,23,
+    57,75,221,124,132,151,162,253,28,36,108,180,199,82,246,1
+};
+
+static const uchar ltab[]=
+{
+    0,255,25,1,50,2,26,198,75,199,27,104,51,238,223,3,
+    100,4,224,14,52,141,129,239,76,113,8,200,248,105,28,193,
+    125,194,29,181,249,185,39,106,77,228,166,114,154,201,9,120,
+    101,47,138,5,33,15,225,36,18,240,130,69,53,147,218,142,
+    150,143,219,189,54,208,206,148,19,92,210,241,64,70,131,56,
+    102,221,253,48,191,6,139,98,179,37,226,152,34,136,145,16,
+    126,110,72,195,163,182,30,66,58,107,40,84,250,133,61,186,
+    43,121,10,21,155,159,94,202,78,212,172,229,243,115,167,87,
+    175,88,168,80,244,234,214,116,79,174,233,213,231,230,173,232,
+    44,215,117,122,235,22,11,245,89,203,95,176,156,169,81,160,
+    127,12,246,111,23,196,73,236,216,67,31,45,164,118,123,183,
+    204,187,62,90,251,96,177,134,59,82,161,108,170,85,41,157,
+    151,178,135,144,97,190,220,252,188,149,207,205,55,63,91,209,
+    83,57,132,60,65,162,109,71,20,42,158,93,86,242,211,171,
+    68,17,146,217,35,32,46,137,180,124,184,38,119,153,227,165,
+    103,74,237,222,197,49,254,24,13,99,140,128,192,247,112,7
+};
+
+static const uchar fbsub[]=
+{
+    99,124,119,123,242,107,111,197,48,1,103,43,254,215,171,118,
+    202,130,201,125,250,89,71,240,173,212,162,175,156,164,114,192,
+    183,253,147,38,54,63,247,204,52,165,229,241,113,216,49,21,
+    4,199,35,195,24,150,5,154,7,18,128,226,235,39,178,117,
+    9,131,44,26,27,110,90,160,82,59,214,179,41,227,47,132,
+    83,209,0,237,32,252,177,91,106,203,190,57,74,76,88,207,
+    208,239,170,251,67,77,51,133,69,249,2,127,80,60,159,168,
+    81,163,64,143,146,157,56,245,188,182,218,33,16,255,243,210,
+    205,12,19,236,95,151,68,23,196,167,126,61,100,93,25,115,
+    96,129,79,220,34,42,144,136,70,238,184,20,222,94,11,219,
+    224,50,58,10,73,6,36,92,194,211,172,98,145,149,228,121,
+    231,200,55,109,141,213,78,169,108,86,244,234,101,122,174,8,
+    186,120,37,46,28,166,180,198,232,221,116,31,75,189,139,138,
+    112,62,181,102,72,3,246,14,97,53,87,185,134,193,29,158,
+    225,248,152,17,105,217,142,148,155,30,135,233,206,85,40,223,
+    140,161,137,13,191,230,66,104,65,153,45,15,176,84,187,22
+};
+
+static const uchar rbsub[]=
+{
+    82,9,106,213,48,54,165,56,191,64,163,158,129,243,215,251,
+    124,227,57,130,155,47,255,135,52,142,67,68,196,222,233,203,
+    84,123,148,50,166,194,35,61,238,76,149,11,66,250,195,78,
+    8,46,161,102,40,217,36,178,118,91,162,73,109,139,209,37,
+    114,248,246,100,134,104,152,22,212,164,92,204,93,101,182,146,
+    108,112,72,80,253,237,185,218,94,21,70,87,167,141,157,132,
+    144,216,171,0,140,188,211,10,247,228,88,5,184,179,69,6,
+    208,44,30,143,202,63,15,2,193,175,189,3,1,19,138,107,
+    58,145,17,65,79,103,220,234,151,242,207,206,240,180,230,115,
+    150,172,116,34,231,173,53,133,226,249,55,232,28,117,223,110,
+    71,241,26,113,29,41,197,137,111,183,98,14,170,24,190,27,
+    252,86,62,75,198,210,121,32,154,219,192,254,120,205,90,244,
+    31,221,168,51,136,7,199,49,177,18,16,89,39,128,236,95,
+    96,81,127,169,25,181,74,13,45,229,122,159,147,201,156,239,
+    160,224,59,77,174,42,245,176,200,235,187,60,131,83,153,97,
+    23,43,4,126,186,119,214,38,225,105,20,99,85,33,12,125
+};
+
+static const unsign32 rco[]=
+{1,2,4,8,16,32,64,128,27,54,108,216,171,77,154,47};
+
+static const unsign32 ftable[]=
+{
+    0xa56363c6,0x847c7cf8,0x997777ee,0x8d7b7bf6,0xdf2f2ff,0xbd6b6bd6,
+    0xb16f6fde,0x54c5c591,0x50303060,0x3010102,0xa96767ce,0x7d2b2b56,
+    0x19fefee7,0x62d7d7b5,0xe6abab4d,0x9a7676ec,0x45caca8f,0x9d82821f,
+    0x40c9c989,0x877d7dfa,0x15fafaef,0xeb5959b2,0xc947478e,0xbf0f0fb,
+    0xecadad41,0x67d4d4b3,0xfda2a25f,0xeaafaf45,0xbf9c9c23,0xf7a4a453,
+    0x967272e4,0x5bc0c09b,0xc2b7b775,0x1cfdfde1,0xae93933d,0x6a26264c,
+    0x5a36366c,0x413f3f7e,0x2f7f7f5,0x4fcccc83,0x5c343468,0xf4a5a551,
+    0x34e5e5d1,0x8f1f1f9,0x937171e2,0x73d8d8ab,0x53313162,0x3f15152a,
+    0xc040408,0x52c7c795,0x65232346,0x5ec3c39d,0x28181830,0xa1969637,
+    0xf05050a,0xb59a9a2f,0x907070e,0x36121224,0x9b80801b,0x3de2e2df,
+    0x26ebebcd,0x6927274e,0xcdb2b27f,0x9f7575ea,0x1b090912,0x9e83831d,
+    0x742c2c58,0x2e1a1a34,0x2d1b1b36,0xb26e6edc,0xee5a5ab4,0xfba0a05b,
+    0xf65252a4,0x4d3b3b76,0x61d6d6b7,0xceb3b37d,0x7b292952,0x3ee3e3dd,
+    0x712f2f5e,0x97848413,0xf55353a6,0x68d1d1b9,0x0,0x2cededc1,
+    0x60202040,0x1ffcfce3,0xc8b1b179,0xed5b5bb6,0xbe6a6ad4,0x46cbcb8d,
+    0xd9bebe67,0x4b393972,0xde4a4a94,0xd44c4c98,0xe85858b0,0x4acfcf85,
+    0x6bd0d0bb,0x2aefefc5,0xe5aaaa4f,0x16fbfbed,0xc5434386,0xd74d4d9a,
+    0x55333366,0x94858511,0xcf45458a,0x10f9f9e9,0x6020204,0x817f7ffe,
+    0xf05050a0,0x443c3c78,0xba9f9f25,0xe3a8a84b,0xf35151a2,0xfea3a35d,
+    0xc0404080,0x8a8f8f05,0xad92923f,0xbc9d9d21,0x48383870,0x4f5f5f1,
+    0xdfbcbc63,0xc1b6b677,0x75dadaaf,0x63212142,0x30101020,0x1affffe5,
+    0xef3f3fd,0x6dd2d2bf,0x4ccdcd81,0x140c0c18,0x35131326,0x2fececc3,
+    0xe15f5fbe,0xa2979735,0xcc444488,0x3917172e,0x57c4c493,0xf2a7a755,
+    0x827e7efc,0x473d3d7a,0xac6464c8,0xe75d5dba,0x2b191932,0x957373e6,
+    0xa06060c0,0x98818119,0xd14f4f9e,0x7fdcdca3,0x66222244,0x7e2a2a54,
+    0xab90903b,0x8388880b,0xca46468c,0x29eeeec7,0xd3b8b86b,0x3c141428,
+    0x79dedea7,0xe25e5ebc,0x1d0b0b16,0x76dbdbad,0x3be0e0db,0x56323264,
+    0x4e3a3a74,0x1e0a0a14,0xdb494992,0xa06060c,0x6c242448,0xe45c5cb8,
+    0x5dc2c29f,0x6ed3d3bd,0xefacac43,0xa66262c4,0xa8919139,0xa4959531,
+    0x37e4e4d3,0x8b7979f2,0x32e7e7d5,0x43c8c88b,0x5937376e,0xb76d6dda,
+    0x8c8d8d01,0x64d5d5b1,0xd24e4e9c,0xe0a9a949,0xb46c6cd8,0xfa5656ac,
+    0x7f4f4f3,0x25eaeacf,0xaf6565ca,0x8e7a7af4,0xe9aeae47,0x18080810,
+    0xd5baba6f,0x887878f0,0x6f25254a,0x722e2e5c,0x241c1c38,0xf1a6a657,
+    0xc7b4b473,0x51c6c697,0x23e8e8cb,0x7cdddda1,0x9c7474e8,0x211f1f3e,
+    0xdd4b4b96,0xdcbdbd61,0x868b8b0d,0x858a8a0f,0x907070e0,0x423e3e7c,
+    0xc4b5b571,0xaa6666cc,0xd8484890,0x5030306,0x1f6f6f7,0x120e0e1c,
+    0xa36161c2,0x5f35356a,0xf95757ae,0xd0b9b969,0x91868617,0x58c1c199,
+    0x271d1d3a,0xb99e9e27,0x38e1e1d9,0x13f8f8eb,0xb398982b,0x33111122,
+    0xbb6969d2,0x70d9d9a9,0x898e8e07,0xa7949433,0xb69b9b2d,0x221e1e3c,
+    0x92878715,0x20e9e9c9,0x49cece87,0xff5555aa,0x78282850,0x7adfdfa5,
+    0x8f8c8c03,0xf8a1a159,0x80898909,0x170d0d1a,0xdabfbf65,0x31e6e6d7,
+    0xc6424284,0xb86868d0,0xc3414182,0xb0999929,0x772d2d5a,0x110f0f1e,
+    0xcbb0b07b,0xfc5454a8,0xd6bbbb6d,0x3a16162c
+};
+
+static const unsign32 rtable[]=
+{
+    0x50a7f451,0x5365417e,0xc3a4171a,0x965e273a,0xcb6bab3b,0xf1459d1f,
+    0xab58faac,0x9303e34b,0x55fa3020,0xf66d76ad,0x9176cc88,0x254c02f5,
+    0xfcd7e54f,0xd7cb2ac5,0x80443526,0x8fa362b5,0x495ab1de,0x671bba25,
+    0x980eea45,0xe1c0fe5d,0x2752fc3,0x12f04c81,0xa397468d,0xc6f9d36b,
+    0xe75f8f03,0x959c9215,0xeb7a6dbf,0xda595295,0x2d83bed4,0xd3217458,
+    0x2969e049,0x44c8c98e,0x6a89c275,0x78798ef4,0x6b3e5899,0xdd71b927,
+    0xb64fe1be,0x17ad88f0,0x66ac20c9,0xb43ace7d,0x184adf63,0x82311ae5,
+    0x60335197,0x457f5362,0xe07764b1,0x84ae6bbb,0x1ca081fe,0x942b08f9,
+    0x58684870,0x19fd458f,0x876cde94,0xb7f87b52,0x23d373ab,0xe2024b72,
+    0x578f1fe3,0x2aab5566,0x728ebb2,0x3c2b52f,0x9a7bc586,0xa50837d3,
+    0xf2872830,0xb2a5bf23,0xba6a0302,0x5c8216ed,0x2b1ccf8a,0x92b479a7,
+    0xf0f207f3,0xa1e2694e,0xcdf4da65,0xd5be0506,0x1f6234d1,0x8afea6c4,
+    0x9d532e34,0xa055f3a2,0x32e18a05,0x75ebf6a4,0x39ec830b,0xaaef6040,
+    0x69f715e,0x51106ebd,0xf98a213e,0x3d06dd96,0xae053edd,0x46bde64d,
+    0xb58d5491,0x55dc471,0x6fd40604,0xff155060,0x24fb9819,0x97e9bdd6,
+    0xcc434089,0x779ed967,0xbd42e8b0,0x888b8907,0x385b19e7,0xdbeec879,
+    0x470a7ca1,0xe90f427c,0xc91e84f8,0x0,0x83868009,0x48ed2b32,
+    0xac70111e,0x4e725a6c,0xfbff0efd,0x5638850f,0x1ed5ae3d,0x27392d36,
+    0x64d90f0a,0x21a65c68,0xd1545b9b,0x3a2e3624,0xb1670a0c,0xfe75793,
+    0xd296eeb4,0x9e919b1b,0x4fc5c080,0xa220dc61,0x694b775a,0x161a121c,
+    0xaba93e2,0xe52aa0c0,0x43e0223c,0x1d171b12,0xb0d090e,0xadc78bf2,
+    0xb9a8b62d,0xc8a91e14,0x8519f157,0x4c0775af,0xbbdd99ee,0xfd607fa3,
+    0x9f2601f7,0xbcf5725c,0xc53b6644,0x347efb5b,0x7629438b,0xdcc623cb,
+    0x68fcedb6,0x63f1e4b8,0xcadc31d7,0x10856342,0x40229713,0x2011c684,
+    0x7d244a85,0xf83dbbd2,0x1132f9ae,0x6da129c7,0x4b2f9e1d,0xf330b2dc,
+    0xec52860d,0xd0e3c177,0x6c16b32b,0x99b970a9,0xfa489411,0x2264e947,
+    0xc48cfca8,0x1a3ff0a0,0xd82c7d56,0xef903322,0xc74e4987,0xc1d138d9,
+    0xfea2ca8c,0x360bd498,0xcf81f5a6,0x28de7aa5,0x268eb7da,0xa4bfad3f,
+    0xe49d3a2c,0xd927850,0x9bcc5f6a,0x62467e54,0xc2138df6,0xe8b8d890,
+    0x5ef7392e,0xf5afc382,0xbe805d9f,0x7c93d069,0xa92dd56f,0xb31225cf,
+    0x3b99acc8,0xa77d1810,0x6e639ce8,0x7bbb3bdb,0x97826cd,0xf418596e,
+    0x1b79aec,0xa89a4f83,0x656e95e6,0x7ee6ffaa,0x8cfbc21,0xe6e815ef,
+    0xd99be7ba,0xce366f4a,0xd4099fea,0xd67cb029,0xafb2a431,0x31233f2a,
+    0x3094a5c6,0xc066a235,0x37bc4e74,0xa6ca82fc,0xb0d090e0,0x15d8a733,
+    0x4a9804f1,0xf7daec41,0xe50cd7f,0x2ff69117,0x8dd64d76,0x4db0ef43,
+    0x544daacc,0xdf0496e4,0xe3b5d19e,0x1b886a4c,0xb81f2cc1,0x7f516546,
+    0x4ea5e9d,0x5d358c01,0x737487fa,0x2e410bfb,0x5a1d67b3,0x52d2db92,
+    0x335610e9,0x1347d66d,0x8c61d79a,0x7a0ca137,0x8e14f859,0x893c13eb,
+    0xee27a9ce,0x35c961b7,0xede51ce1,0x3cb1477a,0x59dfd29c,0x3f73f255,
+    0x79ce1418,0xbf37c773,0xeacdf753,0x5baafd5f,0x146f3ddf,0x86db4478,
+    0x81f3afca,0x3ec468b9,0x2c342438,0x5f40a3c2,0x72c31d16,0xc25e2bc,
+    0x8b493c28,0x41950dff,0x7101a839,0xdeb30c08,0x9ce4b4d8,0x90c15664,
+    0x6184cb7b,0x70b632d5,0x745c6c48,0x4257b8d0
+};
+
+#define MR_TOBYTE(x) ((uchar)((x)))
+
+static unsign32 pack(const uchar *b)
+{
+    /* pack bytes into a 32-bit Word */
+    return ((unsign32)b[3]<<24)|((unsign32)b[2]<<16)|((unsign32)b[1]<<8)|(unsign32)b[0];
+}
+
+static void unpack(unsign32 a,uchar *b)
+{
+    /* unpack bytes from a word */
+    b[0]=MR_TOBYTE(a);
+    b[1]=MR_TOBYTE(a>>8);
+    b[2]=MR_TOBYTE(a>>16);
+    b[3]=MR_TOBYTE(a>>24);
+}
+
+/* SU= 8 */
+static uchar bmul(uchar x,uchar y)
+{
+    /* x.y= AntiLog(Log(x) + Log(y)) */
+    if (x && y) return ptab[(ltab[x]+ltab[y])%255];
+    else return 0;
+}
+
+static unsign32 SubByte(unsign32 a)
+{
+    uchar b[4];
+    unpack(a,b);
+    b[0]=fbsub[b[0]];
+    b[1]=fbsub[b[1]];
+    b[2]=fbsub[b[2]];
+    b[3]=fbsub[b[3]];
+    return pack(b);
+}
+
+/* SU= 16 */
+static uchar product(unsign32 x,unsign32 y)
+{
+    /* dot product of two 4-byte arrays */
+    uchar xb[4],yb[4];
+    unpack(x,xb);
+    unpack(y,yb);
+    return bmul(xb[0],yb[0])^bmul(xb[1],yb[1])^bmul(xb[2],yb[2])^bmul(xb[3],yb[3]);
+}
+
+static unsign32 InvMixCol(unsign32 x)
+{
+    /* matrix Multiplication */
+    unsign32 y,m;
+    uchar b[4];
+
+    m=pack(InCo);
+    b[3]=product(m,x);
+    m=ROTL24(m);
+    b[2]=product(m,x);
+    m=ROTL24(m);
+    b[1]=product(m,x);
+    m=ROTL24(m);
+    b[0]=product(m,x);
+    y=pack(b);
+    return y;
+}
+
+/* SU= 8 */
+/* reset cipher */
+void AES_reset(amcl_aes *a,int mode,char *iv)
+{
+    /* reset mode, or reset iv */
+    int i;
+    a->mode=mode;
+    for (i=0; i<4*NB; i++)
+        a->f[i]=0;
+    if (mode!=ECB && iv!=NULL)
+    {
+        for (i=0; i<4*NB; i++)
+            a->f[i]=iv[i];
+    }
+}
+
+void AES_getreg(amcl_aes *a,char *ir)
+{
+    int i;
+    for (i=0; i<4*NB; i++) ir[i]=a->f[i];
+}
+
+/* SU= 72 */
+/* Initialise cipher */
+int AES_init(amcl_aes* a,int mode,int nk,char *key,char *iv)
+{
+    /* Key length Nk=16, 24 or 32 bytes */
+    /* Key Scheduler. Create expanded encryption key */
+    int i,j,k,N,nr;
+    unsign32 CipherKey[8];
+
+    nk/=4;
+
+    if (nk!=4 && nk!=6 && nk!=8) return 0;
+
+    nr=6+nk;
+
+    a->Nk=nk;
+    a->Nr=nr;
+
+    AES_reset(a,mode,iv);
+
+    N=NB*(nr+1);
+
+    for (i=j=0; i<nk; i++,j+=4)
+    {
+        CipherKey[i]=pack((uchar *)&key[j]);
+    }
+    for (i=0; i<nk; i++) a->fkey[i]=CipherKey[i];
+    for (j=nk,k=0; j<N; j+=nk,k++)
+    {
+        a->fkey[j]=a->fkey[j-nk]^SubByte(ROTL24(a->fkey[j-1]))^rco[k];
+        if (nk<=6)
+        {
+            for (i=1; i<nk && (i+j)<N; i++)
+                a->fkey[i+j]=a->fkey[i+j-nk]^a->fkey[i+j-1];
+        }
+        else
+        {
+            for (i=1; i<4 && (i+j)<N; i++)
+                a->fkey[i+j]=a->fkey[i+j-nk]^a->fkey[i+j-1];
+            if ((j+4)<N) a->fkey[j+4]=a->fkey[j+4-nk]^SubByte(a->fkey[j+3]);
+            for (i=5; i<nk && (i+j)<N; i++)
+                a->fkey[i+j]=a->fkey[i+j-nk]^a->fkey[i+j-1];
+        }
+
+    }
+    /* now for the expanded decrypt key in reverse order */
+
+    for (j=0; j<NB; j++) a->rkey[j+N-NB]=a->fkey[j];
+    for (i=NB; i<N-NB; i+=NB)
+    {
+        k=N-NB-i;
+        for (j=0; j<NB; j++) a->rkey[k+j]=InvMixCol(a->fkey[i+j]);
+    }
+    for (j=N-NB; j<N; j++) a->rkey[j-N+NB]=a->fkey[j];
+    return 1;
+}
+
+/* SU= 80 */
+/* Encrypt a single block */
+void AES_ecb_encrypt(amcl_aes *a,uchar *buff)
+{
+    int i,j,k;
+    unsign32 p[4],q[4],*x,*y,*t;
+
+    for (i=j=0; i<NB; i++,j+=4)
+    {
+        p[i]=pack((uchar *)&buff[j]);
+        p[i]^=a->fkey[i];
+    }
+
+    k=NB;
+    x=p;
+    y=q;
+
+    /* State alternates between x and y */
+    for (i=1; i<a->Nr; i++)
+    {
+
+        y[0]=a->fkey[k]^ftable[MR_TOBYTE(x[0])]^
+             ROTL8(ftable[MR_TOBYTE(x[1]>>8)])^
+             ROTL16(ftable[MR_TOBYTE(x[2]>>16)])^
+             ROTL24(ftable[x[3]>>24]);
+        y[1]=a->fkey[k+1]^ftable[MR_TOBYTE(x[1])]^
+             ROTL8(ftable[MR_TOBYTE(x[2]>>8)])^
+             ROTL16(ftable[MR_TOBYTE(x[3]>>16)])^
+             ROTL24(ftable[x[0]>>24]);
+        y[2]=a->fkey[k+2]^ftable[MR_TOBYTE(x[2])]^
+             ROTL8(ftable[MR_TOBYTE(x[3]>>8)])^
+             ROTL16(ftable[MR_TOBYTE(x[0]>>16)])^
+             ROTL24(ftable[x[1]>>24]);
+        y[3]=a->fkey[k+3]^ftable[MR_TOBYTE(x[3])]^
+             ROTL8(ftable[MR_TOBYTE(x[0]>>8)])^
+             ROTL16(ftable[MR_TOBYTE(x[1]>>16)])^
+             ROTL24(ftable[x[2]>>24]);
+
+        k+=4;
+        t=x;
+        x=y;
+        y=t;      /* swap pointers */
+    }
+
+    /* Last Round */
+
+    y[0]=a->fkey[k]^(unsign32)fbsub[MR_TOBYTE(x[0])]^
+         ROTL8((unsign32)fbsub[MR_TOBYTE(x[1]>>8)])^
+         ROTL16((unsign32)fbsub[MR_TOBYTE(x[2]>>16)])^
+         ROTL24((unsign32)fbsub[x[3]>>24]);
+    y[1]=a->fkey[k+1]^(unsign32)fbsub[MR_TOBYTE(x[1])]^
+         ROTL8((unsign32)fbsub[MR_TOBYTE(x[2]>>8)])^
+         ROTL16((unsign32)fbsub[MR_TOBYTE(x[3]>>16)])^
+         ROTL24((unsign32)fbsub[x[0]>>24]);
+    y[2]=a->fkey[k+2]^(unsign32)fbsub[MR_TOBYTE(x[2])]^
+         ROTL8((unsign32)fbsub[MR_TOBYTE(x[3]>>8)])^
+         ROTL16((unsign32)fbsub[MR_TOBYTE(x[0]>>16)])^
+         ROTL24((unsign32)fbsub[x[1]>>24]);
+    y[3]=a->fkey[k+3]^(unsign32)fbsub[MR_TOBYTE(x[3])]^
+         ROTL8((unsign32)fbsub[MR_TOBYTE(x[0]>>8)])^
+         ROTL16((unsign32)fbsub[MR_TOBYTE(x[1]>>16)])^
+         ROTL24((unsign32)fbsub[x[2]>>24]);
+
+    for (i=j=0; i<NB; i++,j+=4)
+    {
+        unpack(y[i],(uchar *)&buff[j]);
+        x[i]=y[i]=0;   /* clean up stack */
+    }
+}
+
+/* SU= 80 */
+/* Decrypt a single block */
+void AES_ecb_decrypt(amcl_aes *a,uchar *buff)
+{
+    int i,j,k;
+    unsign32 p[4],q[4],*x,*y,*t;
+
+    for (i=j=0; i<NB; i++,j+=4)
+    {
+        p[i]=pack((uchar *)&buff[j]);
+        p[i]^=a->rkey[i];
+    }
+
+    k=NB;
+    x=p;
+    y=q;
+
+    /* State alternates between x and y */
+    for (i=1; i<a->Nr; i++)
+    {
+        /* Nr is number of rounds. May be odd. */
+
+        y[0]=a->rkey[k]^rtable[MR_TOBYTE(x[0])]^
+             ROTL8(rtable[MR_TOBYTE(x[3]>>8)])^
+             ROTL16(rtable[MR_TOBYTE(x[2]>>16)])^
+             ROTL24(rtable[x[1]>>24]);
+        y[1]=a->rkey[k+1]^rtable[MR_TOBYTE(x[1])]^
+             ROTL8(rtable[MR_TOBYTE(x[0]>>8)])^
+             ROTL16(rtable[MR_TOBYTE(x[3]>>16)])^
+             ROTL24(rtable[x[2]>>24]);
+        y[2]=a->rkey[k+2]^rtable[MR_TOBYTE(x[2])]^
+             ROTL8(rtable[MR_TOBYTE(x[1]>>8)])^
+             ROTL16(rtable[MR_TOBYTE(x[0]>>16)])^
+             ROTL24(rtable[x[3]>>24]);
+        y[3]=a->rkey[k+3]^rtable[MR_TOBYTE(x[3])]^
+             ROTL8(rtable[MR_TOBYTE(x[2]>>8)])^
+             ROTL16(rtable[MR_TOBYTE(x[1]>>16)])^
+             ROTL24(rtable[x[0]>>24]);
+
+        k+=4;
+        t=x;
+        x=y;
+        y=t;      /* swap pointers */
+    }
+
+
+    /* Last Round */
+    y[0]=a->rkey[k]^(unsign32)rbsub[MR_TOBYTE(x[0])]^
+         ROTL8((unsign32)rbsub[MR_TOBYTE(x[3]>>8)])^
+         ROTL16((unsign32)rbsub[MR_TOBYTE(x[2]>>16)])^
+         ROTL24((unsign32)rbsub[x[1]>>24]);
+    y[1]=a->rkey[k+1]^(unsign32)rbsub[MR_TOBYTE(x[1])]^
+         ROTL8((unsign32)rbsub[MR_TOBYTE(x[0]>>8)])^
+         ROTL16((unsign32)rbsub[MR_TOBYTE(x[3]>>16)])^
+         ROTL24((unsign32)rbsub[x[2]>>24]);
+    y[2]=a->rkey[k+2]^(unsign32)rbsub[MR_TOBYTE(x[2])]^
+         ROTL8((unsign32)rbsub[MR_TOBYTE(x[1]>>8)])^
+         ROTL16((unsign32)rbsub[MR_TOBYTE(x[0]>>16)])^
+         ROTL24((unsign32)rbsub[x[3]>>24]);
+    y[3]=a->rkey[k+3]^(unsign32)rbsub[MR_TOBYTE(x[3])]^
+         ROTL8((unsign32)rbsub[MR_TOBYTE(x[2]>>8)])^
+         ROTL16((unsign32)rbsub[MR_TOBYTE(x[1]>>16)])^
+         ROTL24((unsign32)rbsub[x[0]>>24]);
+
+    for (i=j=0; i<NB; i++,j+=4)
+    {
+        unpack(y[i],(uchar *)&buff[j]);
+        x[i]=y[i]=0;   /* clean up stack */
+    }
+
+}
+
+/* simple default increment function */
+static void increment(char *f)
+{
+    int i;
+    for (i=0; i<16; i++)
+    {
+        f[i]++;
+        if (f[i]!=0) break;
+    }
+}
+
+/* SU= 40 */
+/* Encrypt using selected mode of operation */
+unsign32 AES_encrypt(amcl_aes* a,char *buff)
+{
+    int j,bytes;
+    char st[16];
+    unsign32 fell_off;
+
+    /* Supported Modes of Operation */
+
+    fell_off=0;
+    switch (a->mode)
+    {
+    case ECB:
+        AES_ecb_encrypt(a,(uchar *)buff);
+        return 0;
+    case CBC:
+        for (j=0; j<4*NB; j++) buff[j]^=a->f[j];
+        AES_ecb_encrypt(a,(uchar *)buff);
+        for (j=0; j<4*NB; j++) a->f[j]=buff[j];
+        return 0;
+
+    case CFB1:
+    case CFB2:
+    case CFB4:
+        bytes=a->mode-CFB1+1;
+        for (j=0; j<bytes; j++) fell_off=(fell_off<<8)|a->f[j];
+        for (j=0; j<4*NB; j++) st[j]=a->f[j];
+        for (j=bytes; j<4*NB; j++) a->f[j-bytes]=a->f[j];
+        AES_ecb_encrypt(a,(uchar *)st);
+        for (j=0; j<bytes; j++)
+        {
+            buff[j]^=st[j];
+            a->f[16-bytes+j]=buff[j];
+        }
+        return fell_off;
+
+    case OFB1:
+    case OFB2:
+    case OFB4:
+    case OFB8:
+    case OFB16:
+
+        bytes=a->mode-OFB1+1;
+        AES_ecb_encrypt(a,(uchar *)(a->f));
+        for (j=0; j<bytes; j++) buff[j]^=a->f[j];
+        return 0;
+
+    case CTR1:
+    case CTR2:
+    case CTR4:
+    case CTR8:
+    case CTR16:
+
+        bytes=a->mode-CTR1+1;
+        for (j=0; j<4*NB; j++) st[j]=a->f[j];
+        AES_ecb_encrypt(a,(uchar *)st);
+        for (j=0; j<bytes; j++) buff[j]^=st[j];
+        increment(a->f);
+
+    default:
+        return 0;
+    }
+}
+
+/* SU= 40 */
+/* Decrypt using selected mode of operation */
+unsign32 AES_decrypt(amcl_aes *a,char *buff)
+{
+    int j,bytes;
+    char st[16];
+    unsign32 fell_off;
+
+    /* Supported modes of operation */
+    fell_off=0;
+    switch (a->mode)
+    {
+    case ECB:
+        AES_ecb_decrypt(a,(uchar *)buff);
+        return 0;
+    case CBC:
+        for (j=0; j<4*NB; j++)
+        {
+            st[j]=a->f[j];
+            a->f[j]=buff[j];
+        }
+        AES_ecb_decrypt(a,(uchar *)buff);
+        for (j=0; j<4*NB; j++)
+        {
+            buff[j]^=st[j];
+            st[j]=0;
+        }
+        return 0;
+    case CFB1:
+    case CFB2:
+    case CFB4:
+        bytes=a->mode-CFB1+1;
+        for (j=0; j<bytes; j++) fell_off=(fell_off<<8)|a->f[j];
+        for (j=0; j<4*NB; j++) st[j]=a->f[j];
+        for (j=bytes; j<4*NB; j++) a->f[j-bytes]=a->f[j];
+        AES_ecb_encrypt(a,(uchar *)st);
+        for (j=0; j<bytes; j++)
+        {
+            a->f[16-bytes+j]=buff[j];
+            buff[j]^=st[j];
+        }
+        return fell_off;
+    case OFB1:
+    case OFB2:
+    case OFB4:
+    case OFB8:
+    case OFB16:
+        bytes=a->mode-OFB1+1;
+        AES_ecb_encrypt(a,(uchar *)(a->f));
+        for (j=0; j<bytes; j++) buff[j]^=a->f[j];
+        return 0;
+
+    case CTR1:
+    case CTR2:
+    case CTR4:
+    case CTR8:
+    case CTR16:
+
+        bytes=a->mode-CTR1+1;
+        for (j=0; j<4*NB; j++) st[j]=a->f[j];
+        AES_ecb_encrypt(a,(uchar *)st);
+        for (j=0; j<bytes; j++) buff[j]^=st[j];
+        increment(a->f);
+
+    default:
+        return 0;
+    }
+}
+
+/* Clean up and delete left-overs */
+void AES_end(amcl_aes *a)
+{
+    /* clean up */
+    int i;
+    for (i=0; i<NB*(a->Nr+1); i++)
+        a->fkey[i]=a->rkey[i]=0;
+    for (i=0; i<4*NB; i++)
+        a->f[i]=0;
+}
+
+
+/*
+#include <stdio.h>
+
+#define KK 32
+
+int main()
+{
+    int i;
+    amcl_aes a;
+	unsign32 t;
+	uchar x,y;
+
+    char key[KK];
+    char block[16];
+    char iv[16];
+    for (i=0;i<KK;i++) key[i]=5;
+    key[0]=1;
+    for (i=0;i<16;i++) iv[i]=i;
+    for (i=0;i<16;i++) block[i]=i;
+
+    AES_init(&a,CTR16,KK,key,iv);
+
+    printf("Plain=   ");
+    for (i=0;i<16;i++) printf("%02x",block[i]);
+    printf("\n");
+    AES_encrypt(&a,block);
+    printf("Encrypt= ");
+    for (i=0;i<16;i++) printf("%02x",(uchar)block[i]);
+    printf("\n");
+    AES_reset(&a,CTR16,iv);
+    AES_decrypt(&a,block);
+    printf("Decrypt= ");
+    for (i=0;i<16;i++) printf("%02x",(uchar)block[i]);
+    printf("\n");
+
+    AES_end(&a);
+
+    return 0;
+}
+
+*/
+
diff --git a/version22/c/amcl.h b/version22/c/amcl.h
new file mode 100644
index 0000000..26a74c3
--- /dev/null
+++ b/version22/c/amcl.h
@@ -0,0 +1,2935 @@
+/*
+	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.
+*/
+
+/* AMCL header file */
+/* Designed for AES-128/192/256 security, 254-521 bit elliptic curves and BN curves for pairings */
+/* Each "limb" of a big number occupies at most (n-3) bits of an n-bit computer word. The most significant word must have at least 4 extra unused bits */
+
+/**
+ * @file amcl.h
+ * @author Mike Scott and Kealan McCusker
+ * @date 19th May 2015
+ * @brief Main Header File
+ *
+ * Allows some user configuration
+ * defines structures
+ * declares functions
+ *
+ */
+
+/* NOTE: There is only one user configurable section in this header - see below */
+
+#ifndef AMCL_H
+#define AMCL_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include "arch.h"
+
+#ifdef CMAKE
+#define AMCL_VERSION_MAJOR @AMCL_VERSION_MAJOR@ /**< Major version of the library */
+#define AMCL_VERSION_MINOR @AMCL_VERSION_MINOR@ /**< Minor version of the library */
+#define AMCL_VERSION_PATCH @AMCL_VERSION_PATCH@ /**< Patch version of the library */
+#define OS "@OS@"                               /**< Operative system */
+#cmakedefine USE_PATENTS   /**< Use Patents */
+#cmakedefine USE_ANONYMOUS /**< Use Anonymous Configuration in MPin */
+#endif
+
+/* Curve types */
+
+#define WEIERSTRASS 0 /**< Short Weierstrass form curve  */
+#define EDWARDS 1     /**< Edwards or Twisted Edwards curve  */
+#define MONTGOMERY 2  /**< Montgomery form curve  */
+
+/* Elliptic curves are defined over prime fields */
+/* Here are some popular EC prime fields for which we have prepared standard curves. Feel free to specify your own. */
+
+#define NIST256 0    /**< For the NIST 256-bit standard curve - WEIERSTRASS only */
+#define C25519 1     /**< Bernstein's Modulus 2^255-19 - EDWARDS or MONTGOMERY only */
+#define BRAINPOOL 2  /**< For Brainpool 256-bit curve - WEIERSTRASS only */
+#define ANSSI 3      /**< For French 256-bit standard curve - WEIERSTRASS only */
+#define MF254 4      /**< For NUMS curves from Bos et al - 254-bit Montgomery friendly modulus - WEIERSTRASS or EDWARDS or MONTGOMERY */
+#define MS255 5      /**< For NUMS curve - 255-bit pseudo-mersenne modulus - WEIERSTRASS or EDWARDS or MONTGOMERY */
+#define MF256 6      /**< For NUMS curve - 256-bit Montgomery friendly modulus - WEIERSTRASS or EDWARDS or MONTGOMERY */
+#define MS256 7      /**< For NUMS curve - 256-bit pseudo-merseene modulus - WEIERSTRASS or EDWARDS or MONTGOMERY */
+#define HIFIVE 8     /**< My 336-bit pseudo-mersenne modulus - EDWARDS only */
+#define GOLDILOCKS 9 /**< Goldilocks generalized-mersenne modulus - EDWARDS only */
+#define NIST384 10   /**< For the NIST 384-bit standard curve - WEIERSTRASS only */
+#define C41417 11    /**< Bernstein et al Curve41417 2^414-17 - EDWARDS only */
+#define NIST521 12   /**< For the NIST 521-bit standard curve - WEIERSTRASS only */
+
+/* BN Curves */
+#define BN_CURVES 100 /**< Barreto-Naehrig curves */
+#define BN454 100     /**< New AES-128 security BN curve - Modulus built from -0x10000010000000000000100000001  - WEIERSTRASS only */
+#define BN646 101     /**< AES-192 security BN curve -  Modulus built from t=-0x10000000000000000000004000000000000001001 - WEIERSTRASS only */
+
+/* A few 254-bit alternative BN curves */
+#define BN254 102 /**< Standard Nogami BN curve - fastest. Modulus built from  t=-0x4080000000000001 - WEIERSTRASS only */
+
+/* GT_STRONG curves */
+#define BN254_CX 103 /**< Our CertiVox BN curve. Modulus built from t=-0x4000000003C012B1 - WEIERSTRASS only */
+#define BN254_T 104  /**< GT_Strong BN curve. Modulus built from t=-0x4000806000004081 - WEIERSTRASS only */
+#define BN254_T2 105 /**< G2 and GT-Strong BN curve.  Modulus built from t=-0x4000020100608205 - WEIERSTRASS only */
+
+/* BLS-12 Curves */
+#define BLS_CURVES 200 /**< Barreto-Lynn-Scott curves */
+#define BLS455 200     /**< New AES-128 security BLS curve - Modulus built from -0x10002000002000010007  - WEIERSTRASS only */
+#define BLS383 201     /**< New AES-128 security BLS curve - Modulus built from -0x1101000000040110  - WEIERSTRASS only */
+
+
+/*** START OF USER CONFIGURABLE SECTION - set architecture and choose modulus and curve  ***/
+
+#ifdef CMAKE
+#define CHOICE @AMCL_CHOICE@ /**< Current choice of Field */
+#else
+#define CHOICE BN254_CX	     /**< Current choice of Field */
+#endif
+
+/* For some moduli only one parameterisation of curve may supported. For others there is a choice of WEIERSTRASS, EDWARDS or MONTGOMERY curves. See above. */
+#ifdef CMAKE
+#define CURVETYPE @AMCL_CURVETYPE@ /**< Note that not all curve types are supported - see above */
+#else
+#define CURVETYPE WEIERSTRASS	   /**< Note that not all curve types are supported - see above */
+#endif
+
+
+/* Actual curve parameters associated with these choices can be found in rom.c */
+
+/* These next options only apply for pairings */
+#ifdef USE_PATENTS
+#define USE_GLV	  /**< Note this method is patented (GLV), so maybe you want to comment this out */
+#define USE_GS_G2 /**< Well we didn't patent it :) But may be covered by GLV patent :( */
+#endif
+#define USE_GS_GT /**< Not patented, so probably safe to always use this */
+
+/* Finite field support - for RSA, DH etc. */
+#ifdef CMAKE
+#define FFLEN @AMCL_FFLEN@ /**< 2^n multiplier of BIGBITS to specify supported Finite Field size, e.g 2048=256*2^3 where BIGBITS=256 */
+#else
+#define FFLEN 8 /**< 2^n multiplier of BIGBITS to specify supported Finite Field size, e.g 2048=256*2^3 where BIGBITS=256 */
+#endif
+
+
+
+/* For debugging Only.*/
+#ifdef CMAKE
+#cmakedefine DEBUG_REDUCE /**< Print debug message for field reduction */
+#cmakedefine DEBUG_NORM   /**< Detect digit overflow */
+#cmakedefine GET_STATS    /**< Debug statistics - use with debugger */
+#else
+//#define DEBUG_REDUCE
+//#define DEBUG_NORM
+//#define GET_STATS
+#endif
+
+
+// #define UNWOUND
+
+/*** END OF USER CONFIGURABLE SECTION ***/
+
+
+
+
+
+
+
+
+#define NLEN (1+((MBITS-1)/BASEBITS)) /**< Number of words in BIG. */
+#define MODBYTES (1+(MBITS-1)/8)      /**< Number of bytes in Modulus */
+#define BIGBITS (MODBYTES*8)	      /**< Number of bits representable in a BIG */
+#define FF_BITS (BIGBITS*FFLEN)	      /**< Finite Field Size in bits - must be BIGBITS.2^n */
+
+/* modulus types */
+
+#define NOT_SPECIAL 0	       /**< Modulus of no exploitable form */
+#define PSEUDO_MERSENNE 1      /**< Pseudo-mersenne modulus of form $2^n-c$  */
+#define MONTGOMERY_FRIENDLY 3  /**< Montgomery Friendly modulus of form $2^a(2^b-c)-1$  */
+#define GENERALISED_MERSENNE 2 /**< Generalised-mersenne modulus of form $2^n-2^m-1$, GOLDILOCKS only */
+
+/* Built-in curves defined here */
+/* MIRACL check.cpp utility used to determine optimal choice for BASEBITS */
+
+/* Define AES_S if the desired AES-equivalent security is significantly less than the group order */
+
+
+#if CHOICE==NIST256
+#define MBITS 256	             /**< Number of bits in Modulus */
+#define MOD8 7	                     /**< Modulus mod 8  */
+#define MODTYPE  NOT_SPECIAL         /**< Modulus type */
+#if CURVETYPE!=WEIERSTRASS
+#error Not supported
+#else
+#if CHUNK==16
+#define BASEBITS 13                  /**< Numbers represented to base 2*BASEBITS */
+#endif
+#if CHUNK == 32
+#define BASEBITS 29                  /**< Numbers represented to base 2*BASEBITS */
+#endif
+#if CHUNK == 64
+#define BASEBITS 56                  /**< Numbers represented to base 2*BASEBITS */
+#endif
+#endif
+#endif
+
+#if CHOICE==C25519
+#define MBITS 255	             /**< Number of bits in Modulus */
+#define MOD8 5		             /**< Modulus mod 8  */
+#define MODTYPE PSEUDO_MERSENNE      /**< Modulus type */
+#if CURVETYPE==WEIERSTRASS
+#error Not supported
+#else
+#if CHUNK==16
+#if CURVETYPE==MONTGOMERY
+#error Not supported
+#else
+#define BASEBITS 13		     /**< Numbers represented to base 2*BASEBITS */
+#endif
+#endif
+#if CHUNK == 32
+#define BASEBITS 29		     /**< Numbers represented to base 2*BASEBITS */
+#endif
+#if CHUNK == 64
+#define BASEBITS 56		     /**< Numbers represented to base 2*BASEBITS */
+#endif
+#endif
+#endif
+
+#if CHOICE==BRAINPOOL
+#define MBITS 256                    /**< Number of bits in Modulus */
+#define MOD8 7                       /**< Modulus mod 8  */
+#define MODTYPE  NOT_SPECIAL         /**< Modulus type */
+#if CURVETYPE!=WEIERSTRASS
+#error Not supported
+#else
+#if CHUNK==16
+#define BASEBITS 13                  /**< Numbers represented to base 2*BASEBITS */
+#endif
+#if CHUNK == 32
+#define BASEBITS 29                  /**< Numbers represented to base 2*BASEBITS */
+#endif
+#if CHUNK == 64
+#define BASEBITS 56                  /**< Numbers represented to base 2*BASEBITS */
+#endif
+#endif
+#endif
+
+#if CHOICE==ANSSI
+#define MBITS 256	             /**< Number of bits in Modulus */
+#define MOD8 3		             /**< Modulus mod 8  */
+#define MODTYPE  NOT_SPECIAL         /**< Modulus type */
+#if CURVETYPE!=WEIERSTRASS
+#error Not supported
+#else
+#if CHUNK==16
+#define BASEBITS 13                  /**< Numbers represented to base 2*BASEBITS */
+#endif
+#if CHUNK == 32
+#define BASEBITS 29                  /**< Numbers represented to base 2*BASEBITS */
+#endif
+#if CHUNK == 64
+#define BASEBITS 56                  /**< Numbers represented to base 2*BASEBITS */
+#endif
+#endif
+#endif
+
+/**< NUMS curve from Bos et al. paper */
+
+#if CHOICE==MF254
+#define MBITS 254                    /**< Number of bits in Modulus */
+#define MOD8 7                       /**< Modulus mod 8  */
+#define MODTYPE MONTGOMERY_FRIENDLY  /**< Modulus type */
+#if CHUNK==16
+#error Not Supported
+#endif
+#if CHUNK == 32
+#define BASEBITS 29                  /**< Numbers represented to base 2*BASEBITS */
+#endif
+#if CHUNK == 64
+#define BASEBITS 56                  /**< Numbers represented to base 2*BASEBITS */
+#endif
+#endif
+
+#if CHOICE==MF256
+#define MBITS 256                    /**< Number of bits in Modulus */
+#define MOD8 7                       /**< Modulus mod 8  */
+#define MODTYPE MONTGOMERY_FRIENDLY  /**< Modulus type */
+#if CHUNK==16
+#error Not Supported
+#endif
+#if CHUNK == 32
+#define BASEBITS 29                  /**< Numbers represented to base 2*BASEBITS */
+#endif
+#if CHUNK == 64
+#define BASEBITS 56                  /**< Numbers represented to base 2*BASEBITS */
+#endif
+#endif
+
+#if CHOICE==MS255
+#define MBITS 255	             /**< Number of bits in Modulus */
+#define MOD8 3		             /**< Modulus mod 8  */
+#define MODTYPE PSEUDO_MERSENNE      /**< Modulus type */
+#if CHUNK==16
+#define BASEBITS 13                  /**< Numbers represented to base 2*BASEBITS */
+#endif
+#if CHUNK == 32
+#define BASEBITS 29                  /**< Numbers represented to base 2*BASEBITS */
+#endif
+#if CHUNK == 64
+#define BASEBITS 56                  /**< Numbers represented to base 2*BASEBITS */
+#endif
+#endif
+
+#if CHOICE==MS256
+#define MBITS 256	             /**< Number of bits in Modulus */
+#define MOD8 3		             /**< Modulus mod 8  */
+#define MODTYPE PSEUDO_MERSENNE      /**< Modulus type */
+#if CHUNK==16
+#define BASEBITS 13	             /**< Numbers represented to base 2*BASEBITS */
+#endif
+#if CHUNK == 32
+#define BASEBITS 29		     /**< Numbers represented to base 2*BASEBITS */
+#endif
+#if CHUNK == 64
+#define BASEBITS 56		     /**< Numbers represented to base 2*BASEBITS */
+#endif
+#endif
+
+#if CHOICE==HIFIVE
+#define MBITS 336	             /**< Number of bits in Modulus */
+#define MOD8 5		             /**< Modulus mod 8  */
+#define MODTYPE PSEUDO_MERSENNE      /**< Modulus type */
+#define AES_S 128                    /**< Desired AES equivalent strength */
+#if CURVETYPE!=EDWARDS
+#error Not supported
+#else
+#if CHUNK==16
+#error Not Supported
+#endif
+#if CHUNK == 32
+#define BASEBITS 29		     /**< Numbers represented to base 2*BASEBITS */
+#endif
+#if CHUNK == 64
+#define BASEBITS 60		     /**< Numbers represented to base 2*BASEBITS */
+#endif
+#endif
+#endif
+
+#if CHOICE==GOLDILOCKS
+#define MBITS 448	             /**< Number of bits in Modulus */
+#define MOD8 7		             /**< Modulus mod 8  */
+#define MODTYPE GENERALISED_MERSENNE /**< Modulus type */
+#if CURVETYPE!=EDWARDS
+#error Not supported
+#else
+#if CHUNK==16
+#error Not Supported
+#endif
+#if CHUNK == 32
+#define BASEBITS 29		     /**< Numbers represented to base 2*BASEBITS */
+#endif
+#if CHUNK == 64
+#define BASEBITS 60		     /**< Numbers represented to base 2*BASEBITS */
+#endif
+#endif
+#endif
+
+#if CHOICE==NIST384
+#define MBITS 384	             /**< Number of bits in Modulus */
+#define MOD8 7		             /**< Modulus mod 8  */
+#define MODTYPE  NOT_SPECIAL         /**< Modulus type */
+#if CURVETYPE!=WEIERSTRASS
+#error Not supported
+#else
+#if CHUNK==16
+#error Not supported
+#endif
+#if CHUNK == 32
+#define BASEBITS 28		     /**< Numbers represented to base 2*BASEBITS */
+#endif
+#if CHUNK == 64
+#define BASEBITS 56		     /**< Numbers represented to base 2*BASEBITS */
+#endif
+#endif
+#endif
+
+#if CHOICE==C41417
+#define MBITS 414	             /**< Number of bits in Modulus */
+#define MOD8 7		             /**< Modulus mod 8  */
+#define MODTYPE  PSEUDO_MERSENNE     /**< Modulus type */
+#if CURVETYPE!=EDWARDS
+#error Not supported
+#else
+#if CHUNK==16
+#error Not supported
+#endif
+#if CHUNK == 32
+#define BASEBITS 29		     /**< Numbers represented to base 2*BASEBITS */
+#endif
+#if CHUNK == 64
+#define BASEBITS 60		     /**< Numbers represented to base 2*BASEBITS */
+#endif
+#endif
+#endif
+
+#if CHOICE==NIST521
+#define MBITS 521	             /**< Number of bits in Modulus */
+#define MOD8 7		             /**< Modulus mod 8  */
+#define MODTYPE  PSEUDO_MERSENNE     /**< Modulus type */
+#if CURVETYPE!=WEIERSTRASS
+#error Not supported
+#else
+#if CHUNK==16
+#error Not supported
+#endif
+#if CHUNK == 32
+#define BASEBITS 28		     /**< Numbers represented to base 2*BASEBITS */
+#endif
+#if CHUNK == 64
+#define BASEBITS 60		     /**< Numbers represented to base 2*BASEBITS */
+#endif
+#endif
+#endif
+
+/* New BN curve to be used for AES-128 security as response to new DL developments - see Kim & Barbulescu ePrint Archive: Report 2015/1027 */
+
+#if CHOICE==BN454
+#define MBITS 454	             /**< Number of bits in Modulus */
+#define MOD8 3		             /**< Modulus mod 8  */
+#define MODTYPE  NOT_SPECIAL         /**< Modulus type */
+#define AES_S 128                    /**< Desired AES equivalent strength */
+#if CURVETYPE!=WEIERSTRASS
+#error Not supported
+#else
+#if CHUNK==16
+#error Not supported
+#endif
+#if CHUNK == 32
+#define BASEBITS 29		     /**< Numbers represented to base 2*BASEBITS */
+#endif
+#if CHUNK == 64
+#define BASEBITS 60		     /**< Numbers represented to base 2*BASEBITS */
+#endif
+#endif
+#endif
+
+/* New BLS curve to be used for AES-128 security as response to new DL developments - see Kim & Barbulescu ePrint Archive: Report 2015/1027 */
+
+#if CHOICE==BLS455
+#define MBITS 455	             /**< Number of bits in Modulus */
+#define MOD8 3		             /**< Modulus mod 8  */
+#define MODTYPE  NOT_SPECIAL         /**< Modulus type */
+#define AES_S 128                    /**< Desired AES equivalent strength */
+#if CURVETYPE!=WEIERSTRASS
+#error Not supported
+#else
+#if CHUNK==16
+#error Not supported
+#endif
+#if CHUNK == 32
+#define BASEBITS 29		     /**< Numbers represented to base 2*BASEBITS */
+#endif
+#if CHUNK == 64
+#define BASEBITS 60		     /**< Numbers represented to base 2*BASEBITS */
+#endif
+#endif
+#endif
+
+
+#if CHOICE==BLS383
+#define MBITS 383	             /**< Number of bits in Modulus */
+#define MOD8 3		             /**< Modulus mod 8  */
+#define MODTYPE  NOT_SPECIAL         /**< Modulus type */
+#if CURVETYPE!=WEIERSTRASS
+#error Not supported
+#else
+#if CHUNK==16
+#error Not supported
+#endif
+#if CHUNK == 32
+#define BASEBITS 28		     /**< Numbers represented to base 2*BASEBITS */
+#endif
+#if CHUNK == 64
+#define BASEBITS 56		     /**< Numbers represented to base 2*BASEBITS */
+#endif
+#endif
+#endif
+
+#if CHOICE==BN646
+#define MBITS 646	             /**< Number of bits in Modulus */
+#define MOD8 3		             /**< Modulus mod 8  */
+#define MODTYPE  NOT_SPECIAL         /**< Modulus type */
+#define AES_S 192                    /**< Desired AES equivalent strength */
+#if CURVETYPE!=WEIERSTRASS
+#error Not supported
+#else
+#if CHUNK==16
+#error Not supported
+#endif
+#if CHUNK == 32
+#define BASEBITS 29		     /**< Numbers represented to base 2*BASEBITS */
+#endif
+#if CHUNK == 64
+#define BASEBITS 60		     /**< Numbers represented to base 2*BASEBITS */
+#endif
+#endif
+#endif
+
+#if CHOICE<BLS_CURVES
+
+#if CHOICE>=BN254                    /* Its a BN curve */
+#define MBITS 254	             /**< Number of bits in Modulus */
+#define MOD8 3		             /**< Modulus mod 8  */
+#define MODTYPE  NOT_SPECIAL         /**< Modulus type */
+#if CURVETYPE!=WEIERSTRASS
+#error Not supported
+#else
+#if CHUNK==16
+#define BASEBITS 13		     /**< Numbers represented to base 2*BASEBITS */
+#endif
+#if CHUNK == 32
+#define BASEBITS 29		     /**< Numbers represented to base 2*BASEBITS */
+#endif
+#if CHUNK == 64
+#define BASEBITS 56		     /**< Numbers represented to base 2*BASEBITS */
+#endif
+#endif
+#endif
+
+
+#if CHOICE>BN254
+#define GT_STRONG /**< Using a GT-Strong 254-bit BN curve */
+#endif
+#endif
+
+
+/* Don't mess with anything below this line */
+
+#ifdef GET_STATS
+extern int tsqr,rsqr,tmul,rmul;
+extern int tadd,radd,tneg,rneg;
+extern int tdadd,rdadd,tdneg,rdneg;
+#endif
+
+#define DCHUNK 2*CHUNK	/**< Number of bits in double-length type */
+#define DNLEN 2*NLEN	/**< double length required for products of BIGs */
+#define HFLEN (FFLEN/2) /**< Useful for half-size RSA private key operations */
+
+#define CHUNK_BITS 8*sizeof(chunk) /**< Number of bits in a chunk */
+
+#ifdef DEBUG_NORM  /* Add an extra location to track chunk extension */
+typedef chunk BIG[NLEN+1];   /**< Define type BIG as array of chunks */
+typedef chunk DBIG[DNLEN+1]; /**< Define type DBIG as array of chunks */
+#else
+typedef chunk BIG[NLEN];     /**< Define type BIG as array of chunks */
+typedef chunk DBIG[DNLEN];   /**< Define type DBIG as array of chunks */
+#endif
+
+#define HBITS (BASEBITS/2)      /**< Number of bits in number base divided by 2 */
+#define HBITS1 ((BASEBITS+1)/2) /**< Number of bits in number base plus 1 divided by 2 */
+#define HDIFF (HBITS1-HBITS)    /**< Will be either 0 or 1, depending if number of bits in number base is even or odd */
+
+#define BMASK (((chunk)1<<BASEBITS)-1) /**< Mask = 2^BASEBITS-1 */
+#define HMASK (((chunk)1<<HBITS)-1)    /**< Mask = 2^HBITS-1 */
+#define HMASK1 (((chunk)1<<HBITS1)-1)  /**< Mask = 2^HBITS1-1 */
+
+#define MODBITS MBITS                             /**< Number of bits in Modulus for selected curve */
+#define TBITS (MBITS%BASEBITS)                    /**< Number of active bits in top word */
+#define TMASK (((chunk)1<<TBITS)-1)               /**< Mask for active bits in top word */
+#define NEXCESS (1<<(CHUNK-BASEBITS-1))           /**< 2^(CHUNK-BASEBITS-1) - digit cannot be multiplied by more than this before normalisation */
+#define FEXCESS ((chunk)1<<(BASEBITS*NLEN-MBITS)) /**< 2^(BASEBITS*NLEN-MODBITS) - normalised BIG can be multiplied by more than this before reduction */
+#define OMASK (-((chunk)(1)<<TBITS))              /**<  for masking out overflow bits */
+
+/* catch field excesses */
+#define EXCESS(a) ((a[NLEN-1]&OMASK)>>(TBITS)) /**< Field Excess */
+
+
+#define P_MBITS (MODBYTES*8)
+#define P_TBITS (P_MBITS%BASEBITS)
+#define P_EXCESS(a) ((a[NLEN-1])>>(P_TBITS))
+#define P_FEXCESS ((chunk)1<<(BASEBITS*NLEN-P_MBITS))
+
+
+
+/* Field Params - see rom.c */
+extern const BIG Modulus;  /**< Actual Modulus set in rom.c */
+extern const chunk MConst; /**< Montgomery only - 1/p mod 2^BASEBITS */
+
+/* Curve Params - see rom.c */
+extern const int CURVE_A;     /**< Elliptic curve A parameter */
+extern const BIG CURVE_B;     /**< Elliptic curve B parameter */
+extern const BIG CURVE_Order; /**< Elliptic curve group order */
+extern const BIG CURVE_Cof;   /**< Elliptic curve cofactor */
+
+/* Generator point on G1 */
+extern const BIG CURVE_Gx; /**< x-coordinate of generator point in group G1  */
+extern const BIG CURVE_Gy; /**< y-coordinate of generator point in group G1  */
+
+/* For Pairings only */
+
+/* Generator point on G2 */
+extern const BIG CURVE_Pxa; /**< real part of x-coordinate of generator point in group G2 */
+extern const BIG CURVE_Pxb; /**< imaginary part of x-coordinate of generator point in group G2 */
+extern const BIG CURVE_Pya; /**< real part of y-coordinate of generator point in group G2 */
+extern const BIG CURVE_Pyb; /**< imaginary part of y-coordinate of generator point in group G2 */
+
+extern const BIG CURVE_Bnx; /**< BN curve x parameter */
+
+extern const BIG CURVE_Cru; /**< BN curve Cube Root of Unity */
+
+extern const BIG CURVE_Fra; /**< real part of BN curve Frobenius Constant */
+extern const BIG CURVE_Frb; /**< imaginary part of BN curve Frobenius Constant */
+
+
+extern const BIG CURVE_W[2];	 /**< BN curve constant for GLV decomposition */
+extern const BIG CURVE_SB[2][2]; /**< BN curve constant for GLV decomposition */
+extern const BIG CURVE_WB[4];	 /**< BN curve constant for GS decomposition */
+extern const BIG CURVE_BB[4][4]; /**< BN curve constant for GS decomposition */
+
+/* Structures */
+
+/**
+	@brief ECP structure - Elliptic Curve Point over base field
+*/
+
+typedef struct
+{
+#if CURVETYPE!=EDWARDS
+    int inf; /**< Infinity Flag - not needed for Edwards representation */
+#endif
+    BIG x; /**< x-coordinate of point */
+#if CURVETYPE!=MONTGOMERY
+    BIG y; /**< y-coordinate of point. Not needed for Montgomery representation */
+#endif
+    BIG z;/**< z-coordinate of point */
+} ECP;
+
+/**
+	@brief FP2 Structure - quadratic extension field
+*/
+
+typedef struct
+{
+    BIG a; /**< real part of FP2 */
+    BIG b; /**< imaginary part of FP2 */
+} FP2;
+
+/**
+	@brief FP4 Structure - towered over two FP2
+*/
+
+typedef struct
+{
+    FP2 a; /**< real part of FP4 */
+    FP2 b; /**< imaginary part of FP4 */
+} FP4;
+
+/**
+	@brief FP12 Structure - towered over three FP4
+*/
+
+typedef struct
+{
+    FP4 a; /**< first part of FP12 */
+    FP4 b; /**< second part of FP12 */
+    FP4 c; /**< third part of FP12 */
+} FP12;
+
+/**
+	@brief ECP2 Structure - Elliptic Curve Point over quadratic extension field
+*/
+
+typedef struct
+{
+    int inf; /**< Infinity Flag */
+    FP2 x;   /**< x-coordinate of point */
+    FP2 y;   /**< y-coordinate of point */
+    FP2 z;   /**< z-coordinate of point */
+} ECP2;
+
+/**
+ * @brief SHA256 hash function instance */
+typedef struct
+{
+    unsign32 length[2]; /**< 64-bit input length */
+    unsign32 h[8];      /**< Internal state */
+    unsign32 w[80];	/**< Internal state */
+    int hlen;		/**< Hash length in bytes */
+} hash256;
+
+/**
+ * @brief SHA384-512 hash function instance */
+typedef struct
+{
+    unsign64 length[2]; /**< 64-bit input length */
+    unsign64 h[8];      /**< Internal state */
+    unsign64 w[80];	/**< Internal state */
+    int hlen;           /**< Hash length in bytes */
+} hash512;
+
+/**
+ * @brief SHA384 hash function instance */
+typedef hash512 hash384;
+
+#define SHA256 32 /**< SHA-256 hashing */
+#define SHA384 48 /**< SHA-384 hashing */
+#define SHA512 64 /**< SHA-512 hashing */
+
+/* Symmetric Encryption AES structure */
+
+#define ECB   0  /**< Electronic Code Book */
+#define CBC   1  /**< Cipher Block Chaining */
+#define CFB1  2  /**< Cipher Feedback - 1 byte */
+#define CFB2  3  /**< Cipher Feedback - 2 bytes */
+#define CFB4  5  /**< Cipher Feedback - 4 bytes */
+#define OFB1  14 /**< Output Feedback - 1 byte */
+#define OFB2  15 /**< Output Feedback - 2 bytes */
+#define OFB4  17 /**< Output Feedback - 4 bytes */
+#define OFB8  21 /**< Output Feedback - 8 bytes */
+#define OFB16 29 /**< Output Feedback - 16 bytes */
+#define CTR1  30 /**< Counter Mode - 1 byte */
+#define CTR2  31 /**< Counter Mode - 2 bytes */
+#define CTR4  33 /**< Counter Mode - 4 bytes */
+#define CTR8  37 /**< Counter Mode - 8 bytes */
+#define CTR16 45 /**< Counter Mode - 16 bytes */
+
+#define uchar unsigned char  /**<  Unsigned char */
+
+/**
+	@brief AES instance
+*/
+
+
+typedef struct
+{
+    int Nk;            /**< AES Key Length */
+    int Nr;            /**< AES Number of rounds */
+    int mode;          /**< AES mode of operation */
+    unsign32 fkey[60]; /**< subkeys for encrypton */
+    unsign32 rkey[60]; /**< subkeys for decrypton */
+    char f[16];        /**< buffer for chaining vector */
+} amcl_aes;
+
+/* AES-GCM suppport.  */
+
+#define GCM_ACCEPTING_HEADER 0   /**< GCM status */
+#define GCM_ACCEPTING_CIPHER 1   /**< GCM status */
+#define GCM_NOT_ACCEPTING_MORE 2 /**< GCM status */
+#define GCM_FINISHED 3           /**< GCM status */
+#define GCM_ENCRYPTING 0         /**< GCM mode */
+#define GCM_DECRYPTING 1         /**< GCM mode */
+
+
+/**
+	@brief GCM mode instance, using AES internally
+*/
+
+typedef struct
+{
+    unsign32 table[128][4]; /**< 2k byte table */
+    uchar stateX[16];	    /**< GCM Internal State */
+    uchar Y_0[16];	    /**< GCM Internal State */
+    unsign32 lenA[2];	    /**< GCM 64-bit length of header */
+    unsign32 lenC[2];	    /**< GCM 64-bit length of ciphertext */
+    int status;		    /**< GCM Status */
+    amcl_aes a;		    /**< Internal Instance of AMCL_AES cipher */
+} gcm;
+
+/* Marsaglia & Zaman Random number generator constants */
+
+#define NK   21 /**< PRNG constant */
+#define NJ   6  /**< PRNG constant */
+#define NV   8  /**< PRNG constant */
+
+
+/**
+	@brief Cryptographically secure pseudo-random number generator instance
+*/
+
+typedef struct
+{
+    unsign32 ira[NK]; /**< random number array   */
+    int      rndptr;  /**< pointer into array */
+    unsign32 borrow;  /**<  borrow as a result of subtraction */
+    int pool_ptr;     /**< pointer into random pool */
+    char pool[32];    /**< random pool */
+} csprng;
+
+
+/**
+	@brief Portable representation of a big positive number
+*/
+
+typedef struct
+{
+    int len;   /**< length in bytes  */
+    int max;   /**< max length allowed - enforce truncation  */
+    char *val; /**< byte array  */
+} octet;
+
+/**
+	@brief Integer Factorisation Public Key
+*/
+
+typedef struct
+{
+    sign32 e;     /**< RSA exponent (typically 65537) */
+    BIG n[FFLEN]; /**< An array of BIGs to store public key */
+} rsa_public_key;
+
+/**
+	@brief Integer Factorisation Private Key
+*/
+
+typedef struct
+{
+    BIG p[FFLEN/2];  /**< secret prime p  */
+    BIG q[FFLEN/2];  /**< secret prime q  */
+    BIG dp[FFLEN/2]; /**< decrypting exponent mod (p-1)  */
+    BIG dq[FFLEN/2]; /**< decrypting exponent mod (q-1)  */
+    BIG c[FFLEN/2];  /**< 1/p mod q */
+} rsa_private_key;
+
+/*
+
+Note that a normalised BIG consists of digits mod 2^BASEBITS
+However BIG digits may be "extended" up to 2^(WORDLENGTH-1).
+
+BIGs in extended form may need to be normalised before certain
+operations.
+
+A BIG may be "reduced" to be less that the Modulus, or it
+may be "unreduced" and allowed to grow greater than the
+Modulus.
+
+Normalisation is quite fast. Reduction involves conditional branches,
+which can be regarded as significant "speed bumps". We try to
+delay reductions as much as possible. Reductions may also involve
+side channel leakage, so delaying and batching them
+hopefully disguises internal operations.
+
+*/
+
+/* BIG number prototypes */
+
+/**	@brief Calculates a*b+c+*d
+ *
+	Calculate partial product of a.b, add in carry c, and add total to d
+	@param a multiplier
+	@param b multiplicand
+	@param c carry
+	@param d pointer to accumulated bottom half of result
+	@return top half of result
+ */
+extern chunk muladd(chunk a,chunk b,chunk c,chunk *d);
+/**	@brief Tests for BIG equal to zero
+ *
+	@param x a BIG number
+	@return 1 if zero, else returns 0
+ */
+extern int BIG_iszilch(BIG x);
+/**	@brief Tests for DBIG equal to zero
+ *
+	@param x a DBIG number
+	@return 1 if zero, else returns 0
+ */
+extern int BIG_diszilch(DBIG x);
+/**	@brief Outputs a BIG number to the console
+ *
+	@param x a BIG number
+ */
+extern void BIG_output(BIG x);
+/**	@brief Outputs a BIG number to the console in raw form (for debugging)
+ *
+	@param x a BIG number
+ */
+extern void BIG_rawoutput(BIG x);
+/**	@brief Conditional constant time swap of two BIG numbers
+ *
+	Conditionally swaps parameters in constant time (without branching)
+	@param x a BIG number
+	@param y another BIG number
+	@param s swap takes place if not equal to 0
+ */
+extern void BIG_cswap(BIG x,BIG y,int s);
+/**	@brief Conditional copy of BIG number
+ *
+	Conditionally copies second parameter to the first (without branching)
+	@param x a BIG number
+	@param y another BIG number
+	@param s copy takes place if not equal to 0
+ */
+extern void BIG_cmove(BIG x,BIG y,int s);
+/**	@brief Conditional copy of DBIG number
+ *
+	Conditionally copies second parameter to the first (without branching)
+	@param x a DBIG number
+	@param y another DBIG number
+	@param s copy takes place if not equal to 0
+ */
+extern void BIG_dcmove(BIG x,BIG y,int s);
+/**	@brief Convert from BIG number to byte array
+ *
+	@param a byte array
+	@param x BIG number
+ */
+extern void BIG_toBytes(char *a,BIG x);
+/**	@brief Convert to BIG number from byte array
+ *
+	@param x BIG number
+	@param a byte array
+ */
+extern void BIG_fromBytes(BIG x,char *a);
+/**	@brief Convert to BIG number from byte array of given length
+ *
+	@param x BIG number
+	@param a byte array
+	@param s byte array length
+ */
+extern void BIG_fromBytesLen(BIG x,char *a,int s);
+/**@brief Convert to DBIG number from byte array of given length
+ *
+   @param x DBIG number
+   @param a byte array
+   @param s byte array length
+ */
+extern void BIG_dfromBytesLen(DBIG x,char *a,int s);
+/**	@brief Outputs a DBIG number to the console
+ *
+	@param x a DBIG number
+ */
+extern void BIG_doutput(DBIG x);
+/**	@brief Copy BIG from Read-Only Memory to a BIG
+ *
+	@param x BIG number
+	@param y BIG number in ROM
+ */
+extern void BIG_rcopy(BIG x,const BIG y);
+/**	@brief Copy BIG to another BIG
+ *
+	@param x BIG number
+	@param y BIG number to be copied
+ */
+extern void BIG_copy(BIG x,BIG y);
+/**	@brief Copy DBIG to another DBIG
+ *
+	@param x DBIG number
+	@param y DBIG number to be copied
+ */
+extern void BIG_dcopy(DBIG x,DBIG y);
+/**	@brief Copy BIG to upper half of DBIG
+ *
+	@param x DBIG number
+	@param y BIG number to be copied
+ */
+extern void BIG_dsucopy(DBIG x,BIG y);
+/**	@brief Copy BIG to lower half of DBIG
+ *
+	@param x DBIG number
+	@param y BIG number to be copied
+ */
+extern void BIG_dscopy(DBIG x,BIG y);
+/**	@brief Copy lower half of DBIG to a BIG
+ *
+	@param x BIG number
+	@param y DBIG number to be copied
+ */
+extern void BIG_sdcopy(BIG x,DBIG y);
+/**	@brief Copy upper half of DBIG to a BIG
+ *
+	@param x BIG number
+	@param y DBIG number to be copied
+ */
+extern void BIG_sducopy(BIG x,DBIG y);
+/**	@brief Set BIG to zero
+ *
+	@param x BIG number to be set to zero
+ */
+extern void BIG_zero(BIG x);
+/**	@brief Set DBIG to zero
+ *
+	@param x DBIG number to be set to zero
+ */
+extern void BIG_dzero(DBIG x);
+/**	@brief Set BIG to one (unity)
+ *
+	@param x BIG number to be set to one.
+ */
+extern void BIG_one(BIG x);
+/**	@brief Set BIG to inverse mod 2^256
+ *
+	@param x BIG number to be inverted
+ */
+extern void BIG_invmod2m(BIG x);
+/**	@brief Set BIG to sum of two BIGs - output not normalised
+ *
+	@param x BIG number, sum of other two
+	@param y BIG number
+	@param z BIG number
+ */
+extern void BIG_add(BIG x,BIG y,BIG z);
+/**	@brief Increment BIG by a small integer - output not normalised
+ *
+	@param x BIG number to be incremented
+	@param i integer
+ */
+extern void BIG_inc(BIG x,int i);
+/**	@brief Set BIG to difference of two BIGs
+ *
+	@param x BIG number, difference of other two - output not normalised
+	@param y BIG number
+	@param z BIG number
+ */
+extern void BIG_sub(BIG x,BIG y,BIG z);
+/**	@brief Decrement BIG by a small integer - output not normalised
+ *
+	@param x BIG number to be decremented
+	@param i integer
+ */
+extern void BIG_dec(BIG x,int i);
+/**	@brief Set DBIG to difference of two DBIGs
+ *
+	@param x DBIG number, difference of other two - output not normalised
+	@param y DBIG number
+	@param z DBIG number
+ */
+extern void BIG_dsub(DBIG x,DBIG y,DBIG z);
+/**	@brief Multiply BIG by a small integer - output not normalised
+ *
+	@param x BIG number, product of other two
+	@param y BIG number
+	@param i small integer
+ */
+extern void BIG_imul(BIG x,BIG y,int i);
+/**	@brief Multiply BIG by not-so-small small integer - output normalised
+ *
+	@param x BIG number, product of other two
+	@param y BIG number
+	@param i small integer
+	@return Overflowing bits
+ */
+extern chunk BIG_pmul(BIG x,BIG y,int i);
+/**	@brief Divide BIG by 3 - output normalised
+ *
+	@param x BIG number
+	@return Remainder
+ */
+extern int BIG_div3(BIG x);
+/**	@brief Multiply BIG by even bigger small integer resulting in a DBIG - output normalised
+ *
+	@param x DBIG number, product of other two
+	@param y BIG number
+	@param i small integer
+ */
+extern void BIG_pxmul(DBIG x,BIG y,int i);
+/**	@brief Multiply BIG by another BIG resulting in DBIG - inputs normalised and output normalised
+ *
+	@param x DBIG number, product of other two
+	@param y BIG number
+	@param z BIG number
+ */
+extern void BIG_mul(DBIG x,BIG y,BIG z);
+/**	@brief Multiply BIG by another BIG resulting in another BIG - inputs normalised and output normalised
+ *
+	Note that the product must fit into a BIG, and x must be distinct from y and z
+	@param x BIG number, product of other two
+	@param y BIG number
+	@param z BIG number
+ */
+extern void BIG_smul(BIG x,BIG y,BIG z);
+/**	@brief Square BIG resulting in a DBIG - input normalised and output normalised
+ *
+	@param x DBIG number, square of a BIG
+	@param y BIG number to be squared
+ */
+extern void BIG_sqr(DBIG x,BIG y);
+
+/**	@brief Montgomery reduction of a DBIG to a BIG  - input normalised and output normalised
+ *
+	@param a BIG number, reduction of a BIG
+	@param md BIG number, the modulus
+	@param MC the Montgomery Constant
+	@param d DBIG number to be reduced
+ */
+extern void BIG_monty(BIG a,BIG md,chunk MC,DBIG d);
+
+/**	@brief Shifts a BIG left by any number of bits - input must be normalised, output normalised
+ *
+	@param x BIG number to be shifted
+	@param s Number of bits to shift
+ */
+extern void BIG_shl(BIG x,int s);
+/**	@brief Fast shifts a BIG left by a small number of bits - input must be normalised, output will be normalised
+ *
+	The number of bits to be shifted must be less than BASEBITS
+	@param x BIG number to be shifted
+	@param s Number of bits to shift
+	@return Overflow bits
+ */
+extern int BIG_fshl(BIG x,int s);
+/**	@brief Shifts a DBIG left by any number of bits - input must be normalised, output normalised
+ *
+	@param x DBIG number to be shifted
+	@param s Number of bits to shift
+ */
+extern void BIG_dshl(DBIG x,int s);
+/**	@brief Shifts a BIG right by any number of bits - input must be normalised, output normalised
+ *
+	@param x BIG number to be shifted
+	@param s Number of bits to shift
+ */
+extern void BIG_shr(BIG x,int s);
+/**	@brief Fast shifts a BIG right by a small number of bits - input must be normalised, output will be normalised
+ *
+	The number of bits to be shifted must be less than BASEBITS
+	@param x BIG number to be shifted
+	@param s Number of bits to shift
+	@return Shifted out bits
+ */
+extern int BIG_fshr(BIG x,int s);
+/**	@brief Shifts a DBIG right by any number of bits - input must be normalised, output normalised
+ *
+	@param x DBIG number to be shifted
+	@param s Number of bits to shift
+ */
+extern void BIG_dshr(DBIG x,int s);
+/**	@brief Splits a DBIG into two BIGs - input must be normalised, outputs normalised
+ *
+	Internal function. The value of s must be approximately in the middle of the DBIG.
+	Typically used to extract z mod 2^MODBITS and z/2^MODBITS
+	@param x BIG number, top half of z
+	@param y BIG number, bottom half of z
+	@param z DBIG number to be split in two.
+	@param s Bit position at which to split
+	@return carry-out from top half
+ */
+extern chunk BIG_split(BIG x,BIG y,DBIG z,int s);
+/**	@brief Normalizes a BIG number - output normalised
+ *
+	All digits of the input BIG are reduced mod 2^BASEBITS
+	@param x BIG number to be normalised
+ */
+extern chunk BIG_norm(BIG x);
+/**	@brief Normalizes a DBIG number - output normalised
+ *
+	All digits of the input DBIG are reduced mod 2^BASEBITS
+	@param x DBIG number to be normalised
+ */
+extern void BIG_dnorm(DBIG x);
+/**	@brief Compares two BIG numbers. Inputs must be normalised externally
+ *
+	@param x first BIG number to be compared
+	@param y second BIG number to be compared
+	@return -1 is x<y, 0 if x=y, 1 if x>y
+ */
+extern int BIG_comp(BIG x,BIG y);
+/**	@brief Compares two DBIG numbers. Inputs must be normalised externally
+ *
+	@param x first DBIG number to be compared
+	@param y second DBIG number to be compared
+	@return -1 is x<y, 0 if x=y, 1 if x>y
+ */
+extern int BIG_dcomp(DBIG x,DBIG y);
+/**	@brief Calculate number of bits in a BIG - output normalised
+ *
+	@param x BIG number
+	@return Number of bits in x
+ */
+extern int BIG_nbits(BIG x);
+/**	@brief Calculate number of bits in a DBIG - output normalised
+ *
+	@param x DBIG number
+	@return Number of bits in x
+ */
+extern int BIG_dnbits(DBIG x);
+/**	@brief Reduce x mod n - input and output normalised
+ *
+	Slow but rarely used
+	@param x BIG number to be reduced mod n
+	@param n The modulus
+ */
+extern void BIG_mod(BIG x,BIG n);
+/**	@brief Divide x by n - output normalised
+ *
+	Slow but rarely used
+	@param x BIG number to be divided by n
+	@param n The Divisor
+ */
+extern void BIG_sdiv(BIG x,BIG n);
+/**	@brief  x=y mod n - output normalised
+ *
+	Slow but rarely used. y is destroyed.
+	@param x BIG number, on exit = y mod n
+	@param y DBIG number
+	@param n Modulus
+ */
+extern void BIG_dmod(BIG x,DBIG y,BIG n);
+/**	@brief  x=y/n - output normalised
+ *
+	Slow but rarely used. y is destroyed.
+	@param x BIG number, on exit = y/n
+	@param y DBIG number
+	@param n Modulus
+ */
+extern void BIG_ddiv(BIG x,DBIG y,BIG n);
+/**	@brief  return parity of BIG, that is the least significant bit
+ *
+	@param x BIG number
+	@return 0 or 1
+ */
+extern int BIG_parity(BIG x);
+/**	@brief  return i-th of BIG
+ *
+	@param x BIG number
+	@param i the bit of x to be returned
+	@return 0 or 1
+ */
+extern int BIG_bit(BIG x,int i);
+/**	@brief  return least significant bits of a BIG
+ *
+	@param x BIG number
+	@param n number of bits to return. Assumed to be less than BASEBITS.
+	@return least significant n bits as an integer
+ */
+extern int BIG_lastbits(BIG x,int n);
+/**	@brief  Create a random BIG from a random number generator
+ *
+	Assumes that the random number generator has been suitably initialised
+	@param x BIG number, on exit a random number
+	@param r A pointer to a Cryptographically Secure Random Number Generator
+ */
+extern void BIG_random(BIG x,csprng *r);
+/**	@brief  Create an unbiased random BIG from a random number generator, reduced with respect to a modulus
+ *
+	Assumes that the random number generator has been suitably initialised
+	@param x BIG number, on exit a random number
+	@param n The modulus
+	@param r A pointer to a Cryptographically Secure Random Number Generator
+ */
+extern void BIG_randomnum(BIG x,BIG n,csprng *r);
+/**	brief  return NAF (Non-Adjacent-Form) value as +/- 1, 3 or 5, inputs must be normalised
+ *
+	Given x and 3*x extracts NAF value from given bit position, and returns number of bits processed, and number of trailing zeros detected if any
+	param x BIG number
+	param x3 BIG number, three times x
+	param i bit position
+	param nbs pointer to integer returning number of bits processed
+	param nzs pointer to integer returning number of trailing 0s
+	return + or - 1, 3 or 5
+*/
+//extern int BIG_nafbits(BIG x,BIG x3,int i,int *nbs,int *nzs);
+
+/**	@brief  Calculate x=y*z mod n
+ *
+	Slow method for modular multiplication
+	@param x BIG number, on exit = y*z mod n
+	@param y BIG number
+	@param z BIG number
+	@param n The BIG Modulus
+ */
+extern void BIG_modmul(BIG x,BIG y,BIG z,BIG n);
+/**	@brief  Calculate x=y/z mod n
+ *
+	Slow method for modular division
+	@param x BIG number, on exit = y/z mod n
+	@param y BIG number
+	@param z BIG number
+	@param n The BIG Modulus
+ */
+extern void BIG_moddiv(BIG x,BIG y,BIG z,BIG n);
+/**	@brief  Calculate x=y^2 mod n
+ *
+	Slow method for modular squaring
+	@param x BIG number, on exit = y^2 mod n
+	@param y BIG number
+	@param n The BIG Modulus
+ */
+extern void BIG_modsqr(BIG x,BIG y,BIG n);
+/**	@brief  Calculate x=-y mod n
+ *
+	Modular negation
+	@param x BIG number, on exit = -y mod n
+	@param y BIG number
+	@param n The BIG Modulus
+ */
+extern void BIG_modneg(BIG x,BIG y,BIG n);
+/**	@brief  Calculate jacobi Symbol (x/y)
+ *
+	@param x BIG number
+	@param y BIG number
+	@return Jacobi symbol, -1,0 or 1
+ */
+extern int BIG_jacobi(BIG x,BIG y);
+/**	@brief  Calculate x=1/y mod n
+ *
+	Modular Inversion - This is slow. Uses binary method.
+	@param x BIG number, on exit = 1/y mod n
+	@param y BIG number
+	@param n The BIG Modulus
+ */
+extern void BIG_invmodp(BIG x,BIG y,BIG n);
+/** @brief Calculate x=x mod 2^m
+ *
+	Truncation
+	@param x BIG number, on reduced mod 2^m
+	@param m new truncated size
+*/
+extern void BIG_mod2m(BIG x,int m);
+
+
+
+/* FP prototypes */
+
+/**	@brief Tests for BIG equal to zero mod Modulus
+ *
+	@param x BIG number to be tested
+	@return 1 if zero, else returns 0
+ */
+extern int FP_iszilch(BIG x);
+/**	@brief Converts from BIG integer to n-residue form mod Modulus
+ *
+	@param x BIG number to be converted
+ */
+extern void FP_nres(BIG x);
+/**	@brief Converts from n-residue form back to BIG integer form
+ *
+	@param x BIG number to be converted
+ */
+extern void FP_redc(BIG x);
+/**	@brief Sets BIG to representation of unity in n-residue form
+ *
+	@param x BIG number to be set equal to unity.
+ */
+extern void FP_one(BIG x);
+/**	@brief Reduces DBIG to BIG exploiting special form of the modulus
+ *
+	This function comes in different flavours depending on the form of Modulus that is currently in use.
+	@param r BIG number, on exit = d mod Modulus
+	@param d DBIG number to be reduced
+ */
+extern void FP_mod(BIG r,DBIG d);
+/**	@brief Fast Modular multiplication of two BIGs in n-residue form, mod Modulus
+ *
+	Uses appropriate fast modular reduction method
+	@param x BIG number, on exit the modular product = y*z mod Modulus
+	@param y BIG number, the multiplicand
+	@param z BIG number, the multiplier
+ */
+extern void FP_mul(BIG x,BIG y,BIG z);
+/**	@brief Fast Modular multiplication of a BIG in n-residue form, by a small integer, mod Modulus
+ *
+	@param x BIG number, on exit the modular product = y*i mod Modulus
+	@param y BIG number, the multiplicand
+	@param i a small number, the multiplier
+ */
+extern void FP_imul(BIG x,BIG y,int i);
+/**	@brief Fast Modular squaring of a BIG in n-residue form, mod Modulus
+ *
+	Uses appropriate fast modular reduction method
+	@param x BIG number, on exit the modular product = y^2 mod Modulus
+	@param y BIG number, the number to be squared
+
+ */
+extern void FP_sqr(BIG x,BIG y);
+/**	@brief Modular addition of two BIGs in n-residue form, mod Modulus
+ *
+	@param x BIG number, on exit the modular sum = y+z mod Modulus
+	@param y BIG number
+	@param z BIG number
+ */
+extern void FP_add(BIG x,BIG y,BIG z);
+/**	@brief Modular subtraction of two BIGs in n-residue form, mod Modulus
+ *
+	@param x BIG number, on exit the modular difference = y-z mod Modulus
+	@param y BIG number
+	@param z BIG number
+ */
+extern void FP_sub(BIG x,BIG y,BIG z);
+/**	@brief Modular division by 2 of a BIG in n-residue form, mod Modulus
+ *
+	@param x BIG number, on exit =y/2 mod Modulus
+	@param y BIG number
+ */
+extern void FP_div2(BIG x,BIG y);
+/**	@brief Fast Modular exponentiation of a BIG in n-residue form, to the power of a BIG, mod Modulus
+ *
+	@param x BIG number, on exit  = y^z mod Modulus
+	@param y BIG number
+	@param z Big number exponent
+ */
+extern void FP_pow(BIG x,BIG y,BIG z);
+/**	@brief Fast Modular square root of a BIG in n-residue form, mod Modulus
+ *
+	@param x BIG number, on exit  = sqrt(y) mod Modulus
+	@param y BIG number, the number whose square root is calculated
+
+ */
+extern void FP_sqrt(BIG x,BIG y);
+/**	@brief Modular negation of a BIG in n-residue form, mod Modulus
+ *
+	@param x BIG number, on exit = -y mod Modulus
+	@param y BIG number
+ */
+extern void FP_neg(BIG x,BIG y);
+/**	@brief Outputs a BIG number that is in n-residue form to the console
+ *
+	Converts from n-residue form before output
+	@param x a BIG number
+ */
+extern void FP_output(BIG x);
+/**	@brief Outputs a BIG number that is in n-residue form to the console, in raw form
+ *
+	Converts from n-residue form before output
+	@param x a BIG number
+ */
+extern void FP_rawoutput(BIG x);
+/**	@brief Reduces possibly unreduced BIG mod Modulus
+ *
+	@param x BIG number, on exit reduced mod Modulus
+ */
+extern void FP_reduce(BIG x);
+/**	@brief Tests for BIG a quadratic residue mod Modulus
+ *
+	@param x BIG number to be tested
+	@return 1 if quadratic residue, else returns 0 if quadratic non-residue
+ */
+extern int FP_qr(BIG x);
+/**	@brief Modular inverse of a BIG in n-residue form, mod Modulus
+ *
+	@param x BIG number, on exit = 1/y mod Modulus
+	@param y BIG number
+ */
+extern void FP_inv(BIG x,BIG y);
+
+
+/* FP2 prototypes */
+
+/**	@brief Tests for FP2 equal to zero
+ *
+	@param x FP2 number to be tested
+	@return 1 if zero, else returns 0
+ */
+extern int FP2_iszilch(FP2 *x);
+/**	@brief Conditional copy of FP2 number
+ *
+	Conditionally copies second parameter to the first (without branching)
+	@param x FP2 instance, set to y if s!=0
+	@param y another FP2 instance
+	@param s copy only takes place if not equal to 0
+ */
+extern void FP2_cmove(FP2 *x,FP2 *y,int s);
+/**	@brief Tests for FP2 equal to one
+ *
+	@param x FP2 instance to be tested
+	@return 1 if x=1, else returns 0
+ */
+extern int FP2_isunity(FP2 *x);
+/**	@brief Tests for equality of two FP2s
+ *
+	@param x FP2 instance to be compared
+	@param y FP2 instance to be compared
+	@return 1 if x=y, else returns 0
+ */
+extern int FP2_equals(FP2 *x,FP2 *y);
+/**	@brief Initialise FP2 from two BIGs in n-residue form
+ *
+	@param x FP2 instance to be initialised
+	@param a BIG to form real part of FP2
+	@param b BIG to form imaginary part of FP2
+ */
+extern void FP2_from_FPs(FP2 *x,BIG a,BIG b);
+/**	@brief Initialise FP2 from two BIG integers
+ *
+	@param x FP2 instance to be initialised
+	@param a BIG to form real part of FP2
+	@param b BIG to form imaginary part of FP2
+ */
+extern void FP2_from_BIGs(FP2 *x,BIG a,BIG b);
+/**	@brief Initialise FP2 from single BIG in n-residue form
+ *
+	Imaginary part is set to zero
+	@param x FP2 instance to be initialised
+	@param a BIG to form real part of FP2
+ */
+extern void FP2_from_FP(FP2 *x,BIG a);
+/**	@brief Initialise FP2 from single BIG
+ *
+	Imaginary part is set to zero
+	@param x FP2 instance to be initialised
+	@param a BIG to form real part of FP2
+ */
+extern void FP2_from_BIG(FP2 *x,BIG a);
+/**	@brief Copy FP2 to another FP2
+ *
+	@param x FP2 instance, on exit = y
+	@param y FP2 instance to be copied
+ */
+extern void FP2_copy(FP2 *x,FP2 *y);
+/**	@brief Set FP2 to zero
+ *
+	@param x FP2 instance to be set to zero
+ */
+extern void FP2_zero(FP2 *x);
+/**	@brief Set FP2 to unity
+ *
+	@param x FP2 instance to be set to one
+ */
+extern void FP2_one(FP2 *x);
+/**	@brief Negation of FP2
+ *
+	@param x FP2 instance, on exit = -y
+	@param y FP2 instance
+ */
+extern void FP2_neg(FP2 *x,FP2 *y);
+/**	@brief Conjugation of FP2
+ *
+	If y=(a,b) on exit x=(a,-b)
+	@param x FP2 instance, on exit = conj(y)
+	@param y FP2 instance
+ */
+extern void FP2_conj(FP2 *x,FP2 *y);
+/**	@brief addition of two FP2s
+ *
+	@param x FP2 instance, on exit = y+z
+	@param y FP2 instance
+	@param z FP2 instance
+ */
+extern void FP2_add(FP2 *x,FP2 *y,FP2 *z);
+/**	@brief subtraction of two FP2s
+ *
+	@param x FP2 instance, on exit = y-z
+	@param y FP2 instance
+	@param z FP2 instance
+ */
+extern void FP2_sub(FP2 *x,FP2 *y,FP2 *z);
+/**	@brief Multiplication of an FP2 by an n-residue
+ *
+	@param x FP2 instance, on exit = y*b
+	@param y FP2 instance
+	@param b BIG n-residue
+ */
+extern void FP2_pmul(FP2 *x,FP2 *y,BIG b);
+/**	@brief Multiplication of an FP2 by a small integer
+ *
+	@param x FP2 instance, on exit = y*i
+	@param y FP2 instance
+	@param i an integer
+ */
+extern void FP2_imul(FP2 *x,FP2 *y,int i);
+/**	@brief Squaring an FP2
+ *
+	@param x FP2 instance, on exit = y^2
+	@param y FP2 instance
+ */
+extern void FP2_sqr(FP2 *x,FP2 *y);
+/**	@brief Multiplication of two FP2s
+ *
+	@param x FP2 instance, on exit = y*z
+	@param y FP2 instance
+	@param z FP2 instance
+ */
+extern void FP2_mul(FP2 *x,FP2 *y,FP2 *z);
+/**	@brief Formats and outputs an FP2 to the console
+ *
+	@param x FP2 instance
+ */
+extern void FP2_output(FP2 *x);
+/**	@brief Formats and outputs an FP2 to the console in raw form (for debugging)
+ *
+	@param x FP2 instance
+ */
+extern void FP2_rawoutput(FP2 *x);
+/**	@brief Inverting an FP2
+ *
+	@param x FP2 instance, on exit = 1/y
+	@param y FP2 instance
+ */
+extern void FP2_inv(FP2 *x,FP2 *y);
+/**	@brief Divide an FP2 by 2
+ *
+	@param x FP2 instance, on exit = y/2
+	@param y FP2 instance
+ */
+extern void FP2_div2(FP2 *x,FP2 *y);
+/**	@brief Multiply an FP2 by (1+sqrt(-1))
+ *
+	Note that (1+sqrt(-1)) is irreducible for FP4
+	@param x FP2 instance, on exit = x*(1+sqrt(-1))
+ */
+extern void FP2_mul_ip(FP2 *x);
+/**	@brief Divide an FP2 by (1+sqrt(-1))
+ *
+	Note that (1+sqrt(-1)) is irreducible for FP4
+	@param x FP2 instance, on exit = x/(1+sqrt(-1))
+ */
+extern void FP2_div_ip(FP2 *x);
+/**	@brief Normalises the components of an FP2
+ *
+	@param x FP2 instance to be normalised
+ */
+extern void FP2_norm(FP2 *x);
+/**	@brief Reduces all components of possibly unreduced FP2 mod Modulus
+ *
+	@param x FP2 instance, on exit reduced mod Modulus
+ */
+extern void FP2_reduce(FP2 *x);
+/**	@brief Raises an FP2 to the power of a BIG
+ *
+	@param x FP2 instance, on exit = y^b
+	@param y FP2 instance
+	@param b BIG number
+ */
+extern void FP2_pow(FP2 *x,FP2 *y,BIG b);
+/**	@brief Square root of an FP2
+ *
+	@param x FP2 instance, on exit = sqrt(y)
+	@param y FP2 instance
+ */
+extern int FP2_sqrt(FP2 *x,FP2 *y);
+
+
+
+/* ECP E(Fp) prototypes */
+/**	@brief Tests for ECP point equal to infinity
+ *
+	@param P ECP point to be tested
+	@return 1 if infinity, else returns 0
+ */
+extern int ECP_isinf(ECP *P);
+/**	@brief Tests for equality of two ECPs
+ *
+	@param P ECP instance to be compared
+	@param Q ECP instance to be compared
+	@return 1 if P=Q, else returns 0
+ */
+extern int ECP_equals(ECP *P,ECP *Q);
+/**	@brief Copy ECP point to another ECP point
+ *
+	@param P ECP instance, on exit = Q
+	@param Q ECP instance to be copied
+ */
+extern void ECP_copy(ECP *P,ECP *Q);
+/**	@brief Negation of an ECP point
+ *
+	@param P ECP instance, on exit = -P
+ */
+extern void ECP_neg(ECP *P);
+/**	@brief Set ECP to point-at-infinity
+ *
+	@param P ECP instance to be set to infinity
+ */
+extern void ECP_inf(ECP *P);
+/**	@brief Calculate Right Hand Side of curve equation y^2=f(x)
+ *
+	Function f(x) depends on form of elliptic curve, Weierstrass, Edwards or Montgomery.
+	Used internally.
+	@param r BIG n-residue value of f(x)
+	@param x BIG n-residue x
+ */
+extern void ECP_rhs(BIG r,BIG x);
+/**	@brief Set ECP to point(x,y) given just x and sign of y
+ *
+	Point P set to infinity if no such point on the curve. If x is on the curve then y is calculated from the curve equation.
+	The correct y value (plus or minus) is selected given its sign s.
+	@param P ECP instance to be set (x,[y])
+	@param x BIG x coordinate of point
+	@param s an integer representing the "sign" of y, in fact its least significant bit.
+ */
+extern int ECP_setx(ECP *P,BIG x,int s);
+
+#if CURVETYPE==MONTGOMERY
+/**	@brief Set ECP to point(x,[y]) given x
+ *
+	Point P set to infinity if no such point on the curve. Note that y coordinate is not needed.
+	@param P ECP instance to be set (x,[y])
+	@param x BIG x coordinate of point
+	@return 1 if point exists, else 0
+ */
+extern int ECP_set(ECP *P,BIG x);
+/**	@brief Extract x coordinate of an ECP point P
+ *
+	@param x BIG on exit = x coordinate of point
+	@param P ECP instance (x,[y])
+	@return -1 if P is point-at-infinity, else 0
+ */
+extern int ECP_get(BIG x,ECP *P);
+/**	@brief Adds ECP instance Q to ECP instance P, given difference D=P-Q
+ *
+	Differential addition of points on a Montgomery curve
+	@param P ECP instance, on exit =P+Q
+	@param Q ECP instance to be added to P
+	@param D Difference between P and Q
+ */
+extern void ECP_add(ECP *P,ECP *Q,ECP *D);
+#else
+/**	@brief Set ECP to point(x,y) given x and y
+ *
+	Point P set to infinity if no such point on the curve.
+	@param P ECP instance to be set (x,y)
+	@param x BIG x coordinate of point
+	@param y BIG y coordinate of point
+	@return 1 if point exists, else 0
+ */
+extern int ECP_set(ECP *P,BIG x,BIG y);
+/**	@brief Extract x and y coordinates of an ECP point P
+ *
+	If x=y, returns only x
+	@param x BIG on exit = x coordinate of point
+	@param y BIG on exit = y coordinate of point (unless x=y)
+	@param P ECP instance (x,y)
+	@return sign of y, or -1 if P is point-at-infinity
+ */
+extern int ECP_get(BIG x,BIG y,ECP *P);
+/**	@brief Adds ECP instance Q to ECP instance P
+ *
+	@param P ECP instance, on exit =P+Q
+	@param Q ECP instance to be added to P
+ */
+extern void ECP_add(ECP *P,ECP *Q);
+/**	@brief Subtracts ECP instance Q from ECP instance P
+ *
+	@param P ECP instance, on exit =P-Q
+	@param Q ECP instance to be subtracted from P
+ */
+extern void ECP_sub(ECP *P,ECP *Q);
+#endif
+/**	@brief Converts an ECP point from Projective (x,y,z) coordinates to affine (x,y) coordinates
+ *
+	@param P ECP instance to be converted to affine form
+ */
+extern void ECP_affine(ECP *P);
+/**	@brief Formats and outputs an ECP point to the console, in projective coordinates
+ *
+	@param P ECP instance to be printed
+ */
+extern void ECP_outputxyz(ECP *P);
+/**	@brief Formats and outputs an ECP point to the console, converted to affine coordinates
+ *
+	@param P ECP instance to be printed
+ */
+extern void ECP_output(ECP * P);
+/**	@brief Formats and outputs an ECP point to an octet string
+ *
+	The octet string is created in the standard form 04|x|y, except for Montgomery curve in which case it is 06|x
+	Here x (and y) are the x and y coordinates in big-endian base 256 form.
+	@param S output octet string
+	@param P ECP instance to be converted to an octet string
+ */
+extern void ECP_toOctet(octet *S,ECP *P);
+/**	@brief Creates an ECP point from an octet string
+ *
+	The octet string is in the standard form 0x04|x|y, except for Montgomery curve in which case it is 0x06|x
+	Here x (and y) are the x and y coordinates in left justified big-endian base 256 form.
+	@param P ECP instance to be created from the octet string
+	@param S input octet string
+	return 1 if octet string corresponds to a point on the curve, else 0
+ */
+extern int ECP_fromOctet(ECP *P,octet *S);
+/**	@brief Doubles an ECP instance P
+ *
+	@param P ECP instance, on exit =2*P
+ */
+extern void ECP_dbl(ECP *P);
+/**	@brief Multiplies an ECP instance P by a small integer, side-channel resistant
+ *
+	@param P ECP instance, on exit =i*P
+	@param i small integer multiplier
+	@param b maximum number of bits in multiplier
+ */
+extern void ECP_pinmul(ECP *P,int i,int b);
+/**	@brief Multiplies an ECP instance P by a BIG, side-channel resistant
+ *
+	Uses Montgomery ladder for Montgomery curves, otherwise fixed sized windows.
+	@param P ECP instance, on exit =b*P
+	@param b BIG number multiplier
+
+ */
+extern void ECP_mul(ECP *P,BIG b);
+/**	@brief Calculates double multiplication P=e*P+f*Q, side-channel resistant
+ *
+	@param P ECP instance, on exit =e*P+f*Q
+	@param Q ECP instance
+	@param e BIG number multiplier
+	@param f BIG number multiplier
+ */
+extern void ECP_mul2(ECP *P,ECP *Q,BIG e,BIG f);
+
+
+
+/* ECP2 E(Fp2) prototypes */
+/**	@brief Tests for ECP2 point equal to infinity
+ *
+	@param P ECP2 point to be tested
+	@return 1 if infinity, else returns 0
+ */
+extern int ECP2_isinf(ECP2 *P);
+/**	@brief Copy ECP2 point to another ECP2 point
+ *
+	@param P ECP2 instance, on exit = Q
+	@param Q ECP2 instance to be copied
+ */
+extern void ECP2_copy(ECP2 *P,ECP2 *Q);
+/**	@brief Set ECP2 to point-at-infinity
+ *
+	@param P ECP2 instance to be set to infinity
+ */
+extern void ECP2_inf(ECP2 *P);
+/**	@brief Tests for equality of two ECP2s
+ *
+	@param P ECP2 instance to be compared
+	@param Q ECP2 instance to be compared
+	@return 1 if P=Q, else returns 0
+ */
+extern int ECP2_equals(ECP2 *P,ECP2 *Q);
+/**	@brief Converts an ECP2 point from Projective (x,y,z) coordinates to affine (x,y) coordinates
+ *
+	@param P ECP2 instance to be converted to affine form
+ */
+extern void ECP2_affine(ECP2 *P);
+/**	@brief Extract x and y coordinates of an ECP2 point P
+ *
+	If x=y, returns only x
+	@param x FP2 on exit = x coordinate of point
+	@param y FP2 on exit = y coordinate of point (unless x=y)
+	@param P ECP2 instance (x,y)
+	@return -1 if P is point-at-infinity, else 0
+ */
+extern int ECP2_get(FP2 *x,FP2 *y,ECP2 *P);
+/**	@brief Formats and outputs an ECP2 point to the console, converted to affine coordinates
+ *
+	@param P ECP2 instance to be printed
+ */
+extern void ECP2_output(ECP2 *P);
+/**	@brief Formats and outputs an ECP2 point to the console, in projective coordinates
+ *
+	@param P ECP2 instance to be printed
+ */
+extern void ECP2_outputxyz(ECP2 *P);
+/**	@brief Formats and outputs an ECP2 point to an octet string
+ *
+	The octet string is created in the form x|y.
+	Convert the real and imaginary parts of the x and y coordinates to big-endian base 256 form.
+	@param S output octet string
+	@param P ECP2 instance to be converted to an octet string
+ */
+extern void ECP2_toOctet(octet *S,ECP2 *P);
+/**	@brief Creates an ECP2 point from an octet string
+ *
+	The octet string is in the form x|y
+	The real and imaginary parts of the x and y coordinates are in big-endian base 256 form.
+	@param P ECP2 instance to be created from the octet string
+	@param S input octet string
+	return 1 if octet string corresponds to a point on the curve, else 0
+ */
+extern int ECP2_fromOctet(ECP2 *P,octet *S);
+/**	@brief Calculate Right Hand Side of curve equation y^2=f(x)
+ *
+	Function f(x)=x^3+Ax+B
+	Used internally.
+	@param r FP2 value of f(x)
+	@param x FP2 instance
+ */
+extern void ECP2_rhs(FP2 *r,FP2 *x);
+/**	@brief Set ECP2 to point(x,y) given x and y
+ *
+	Point P set to infinity if no such point on the curve.
+	@param P ECP2 instance to be set (x,y)
+	@param x FP2 x coordinate of point
+	@param y FP2 y coordinate of point
+	@return 1 if point exists, else 0
+ */
+extern int ECP2_set(ECP2 *P,FP2 *x,FP2 *y);
+/**	@brief Set ECP to point(x,[y]) given x
+ *
+	Point P set to infinity if no such point on the curve. Otherwise y coordinate is calculated from x.
+	@param P ECP instance to be set (x,[y])
+	@param x BIG x coordinate of point
+	@return 1 if point exists, else 0
+ */
+extern int ECP2_setx(ECP2 *P,FP2 *x);
+/**	@brief Negation of an ECP2 point
+ *
+	@param P ECP2 instance, on exit = -P
+ */
+extern void ECP2_neg(ECP2 *P);
+/**	@brief Doubles an ECP2 instance P
+ *
+	@param P ECP2 instance, on exit =2*P
+ */
+extern int ECP2_dbl(ECP2 *P);
+/**	@brief Adds ECP2 instance Q to ECP2 instance P
+ *
+	@param P ECP2 instance, on exit =P+Q
+	@param Q ECP2 instance to be added to P
+ */
+extern int ECP2_add(ECP2 *P,ECP2 *Q);
+/**	@brief Subtracts ECP instance Q from ECP2 instance P
+ *
+	@param P ECP2 instance, on exit =P-Q
+	@param Q ECP2 instance to be subtracted from P
+ */
+extern void ECP2_sub(ECP2 *P,ECP2 *Q);
+/**	@brief Multiplies an ECP2 instance P by a BIG, side-channel resistant
+ *
+	Uses fixed sized windows.
+	@param P ECP2 instance, on exit =b*P
+	@param b BIG number multiplier
+
+ */
+extern void ECP2_mul(ECP2 *P,BIG b);
+/**	@brief Multiplies an ECP2 instance P by the internal modulus p, using precalculated Frobenius constant f
+ *
+	Fast point multiplication using Frobenius
+	@param P ECP2 instance, on exit = p*P
+	@param f FP2 precalculated Frobenius constant
+
+ */
+extern void ECP2_frob(ECP2 *P,FP2 *f);
+/**	@brief Calculates P=b[0]*Q[0]+b[1]*Q[1]+b[2]*Q[2]+b[3]*Q[3]
+ *
+	@param P ECP2 instance, on exit = b[0]*Q[0]+b[1]*Q[1]+b[2]*Q[2]+b[3]*Q[3]
+	@param Q ECP2 array of 4 points
+	@param b BIG array of 4 multipliers
+ */
+extern void ECP2_mul4(ECP2 *P,ECP2 *Q,BIG *b);
+
+
+
+/* FP4 prototypes */
+/**	@brief Tests for FP4 equal to zero
+ *
+	@param x FP4 number to be tested
+	@return 1 if zero, else returns 0
+ */
+extern int FP4_iszilch(FP4 *x);
+/**	@brief Tests for FP4 equal to unity
+ *
+	@param x FP4 number to be tested
+	@return 1 if unity, else returns 0
+ */
+extern int FP4_isunity(FP4 *x);
+/**	@brief Tests for equality of two FP4s
+ *
+	@param x FP4 instance to be compared
+	@param y FP4 instance to be compared
+	@return 1 if x=y, else returns 0
+ */
+extern int FP4_equals(FP4 *x,FP4 *y);
+/**	@brief Tests for FP4 having only a real part and no imaginary part
+ *
+	@param x FP4 number to be tested
+	@return 1 if real, else returns 0
+ */
+extern int FP4_isreal(FP4 *x);
+/**	@brief Initialise FP4 from two FP2s
+ *
+	@param x FP4 instance to be initialised
+	@param a FP2 to form real part of FP4
+	@param b FP2 to form imaginary part of FP4
+ */
+extern void FP4_from_FP2s(FP4 *x,FP2 *a,FP2 *b);
+/**	@brief Initialise FP4 from single FP2
+ *
+	Imaginary part is set to zero
+	@param x FP4 instance to be initialised
+	@param a FP2 to form real part of FP4
+ */
+extern void FP4_from_FP2(FP4 *x,FP2 *a);
+/**	@brief Copy FP4 to another FP4
+ *
+	@param x FP4 instance, on exit = y
+	@param y FP4 instance to be copied
+ */
+extern void FP4_copy(FP4 *x,FP4 *y);
+/**	@brief Set FP4 to zero
+ *
+	@param x FP4 instance to be set to zero
+ */
+extern void FP4_zero(FP4 *x);
+/**	@brief Set FP4 to unity
+ *
+	@param x FP4 instance to be set to one
+ */
+extern void FP4_one(FP4 *x);
+/**	@brief Negation of FP4
+ *
+	@param x FP4 instance, on exit = -y
+	@param y FP4 instance
+ */
+extern void FP4_neg(FP4 *x,FP4 *y);
+/**	@brief Conjugation of FP4
+ *
+	If y=(a,b) on exit x=(a,-b)
+	@param x FP4 instance, on exit = conj(y)
+	@param y FP4 instance
+ */
+extern void FP4_conj(FP4 *x,FP4 *y);
+/**	@brief Negative conjugation of FP4
+ *
+	If y=(a,b) on exit x=(-a,b)
+	@param x FP4 instance, on exit = -conj(y)
+	@param y FP4 instance
+ */
+extern void FP4_nconj(FP4 *x,FP4 *y);
+/**	@brief addition of two FP4s
+ *
+	@param x FP4 instance, on exit = y+z
+	@param y FP4 instance
+	@param z FP4 instance
+ */
+extern void FP4_add(FP4 *x,FP4 *y,FP4 *z);
+/**	@brief subtraction of two FP4s
+ *
+	@param x FP4 instance, on exit = y-z
+	@param y FP4 instance
+	@param z FP4 instance
+ */
+extern void FP4_sub(FP4 *x,FP4 *y,FP4 *z);
+/**	@brief Multiplication of an FP4 by an FP2
+ *
+	@param x FP4 instance, on exit = y*a
+	@param y FP4 instance
+	@param a FP2 multiplier
+ */
+extern void FP4_pmul(FP4 *x,FP4 *y,FP2 *a);
+/**	@brief Multiplication of an FP4 by a small integer
+ *
+	@param x FP4 instance, on exit = y*i
+	@param y FP4 instance
+	@param i an integer
+ */
+extern void FP4_imul(FP4 *x,FP4 *y,int i);
+/**	@brief Squaring an FP4
+ *
+	@param x FP4 instance, on exit = y^2
+	@param y FP4 instance
+ */
+extern void FP4_sqr(FP4 *x,FP4 *y);
+/**	@brief Multiplication of two FP4s
+ *
+	@param x FP4 instance, on exit = y*z
+	@param y FP4 instance
+	@param z FP4 instance
+ */
+extern void FP4_mul(FP4 *x,FP4 *y,FP4 *z);
+/**	@brief Inverting an FP4
+ *
+	@param x FP4 instance, on exit = 1/y
+	@param y FP4 instance
+ */
+extern void FP4_inv(FP4 *x,FP4 *y);
+/**	@brief Formats and outputs an FP4 to the console
+ *
+	@param x FP4 instance to be printed
+ */
+extern void FP4_output(FP4 *x);
+/**	@brief Formats and outputs an FP4 to the console in raw form (for debugging)
+ *
+	@param x FP4 instance to be printed
+ */
+extern void FP4_rawoutput(FP4 *x);
+/**	@brief multiplies an FP4 instance by irreducible polynomial sqrt(1+sqrt(-1))
+ *
+	@param x FP4 instance, on exit = sqrt(1+sqrt(-1)*x
+ */
+extern void FP4_times_i(FP4 *x);
+/**	@brief Normalises the components of an FP4
+ *
+	@param x FP4 instance to be normalised
+ */
+extern void FP4_norm(FP4 *x);
+/**	@brief Reduces all components of possibly unreduced FP4 mod Modulus
+ *
+	@param x FP4 instance, on exit reduced mod Modulus
+ */
+extern void FP4_reduce(FP4 *x);
+/**	@brief Raises an FP4 to the power of a BIG
+ *
+	@param x FP4 instance, on exit = y^b
+	@param y FP4 instance
+	@param b BIG number
+ */
+extern void FP4_pow(FP4 *x,FP4 *y,BIG b);
+/**	@brief Raises an FP4 to the power of the internal modulus p, using the Frobenius
+ *
+	@param x FP4 instance, on exit = x^p
+	@param f FP2 precalculated Frobenius constant
+ */
+extern void FP4_frob(FP4 *x,FP2 *f);
+/**	@brief Calculates the XTR addition function r=w*x-conj(x)*y+z
+ *
+	@param r FP4 instance, on exit = w*x-conj(x)*y+z
+	@param w FP4 instance
+	@param x FP4 instance
+	@param y FP4 instance
+	@param z FP4 instance
+ */
+extern void FP4_xtr_A(FP4 *r,FP4 *w,FP4 *x,FP4 *y,FP4 *z);
+/**	@brief Calculates the XTR doubling function r=x^2-2*conj(x)
+ *
+	@param r FP4 instance, on exit = x^2-2*conj(x)
+	@param x FP4 instance
+ */
+extern void FP4_xtr_D(FP4 *r,FP4 *x);
+/**	@brief Calculates FP4 trace of an FP12 raised to the power of a BIG number
+ *
+	XTR single exponentiation
+	@param r FP4 instance, on exit = trace(w^b)
+	@param x FP4 instance, trace of an FP12 w
+	@param b BIG number
+ */
+extern void FP4_xtr_pow(FP4 *r,FP4 *x,BIG b);
+/**	@brief Calculates FP4 trace of c^a.d^b, where c and d are derived from FP4 traces of FP12s
+ *
+	XTR double exponentiation
+	Assumes c=tr(x^m), d=tr(x^n), e=tr(x^(m-n)), f=tr(x^(m-2n))
+	@param r FP4 instance, on exit = trace(c^a.d^b)
+	@param c FP4 instance, trace of an FP12
+	@param d FP4 instance, trace of an FP12
+	@param e FP4 instance, trace of an FP12
+	@param f FP4 instance, trace of an FP12
+	@param a BIG number
+	@param b BIG number
+ */
+extern void FP4_xtr_pow2(FP4 *r,FP4 *c,FP4 *d,FP4 *e,FP4 *f,BIG a,BIG b);
+
+
+
+/* FP12 prototypes */
+/**	@brief Tests for FP12 equal to zero
+ *
+	@param x FP12 number to be tested
+	@return 1 if zero, else returns 0
+ */
+extern int FP12_iszilch(FP12 *x);
+/**	@brief Tests for FP12 equal to unity
+ *
+	@param x FP12 number to be tested
+	@return 1 if unity, else returns 0
+ */
+extern int FP12_isunity(FP12 *x);
+/**	@brief Copy FP12 to another FP12
+ *
+	@param x FP12 instance, on exit = y
+	@param y FP12 instance to be copied
+ */
+extern void FP12_copy(FP12 *x,FP12 *y);
+/**	@brief Set FP12 to unity
+ *
+	@param x FP12 instance to be set to one
+ */
+extern void FP12_one(FP12 *x);
+/**	@brief Tests for equality of two FP12s
+ *
+	@param x FP12 instance to be compared
+	@param y FP12 instance to be compared
+	@return 1 if x=y, else returns 0
+ */
+extern int FP12_equals(FP12 *x,FP12 *y);
+/**	@brief Conjugation of FP12
+ *
+	If y=(a,b,c) (where a,b,c are its three FP4 components) on exit x=(conj(a),-conj(b),conj(c))
+	@param x FP12 instance, on exit = conj(y)
+	@param y FP12 instance
+ */
+extern void FP12_conj(FP12 *x,FP12 *y);
+/**	@brief Initialise FP12 from single FP4
+ *
+	Sets first FP4 component of an FP12, other components set to zero
+	@param x FP12 instance to be initialised
+	@param a FP4 to form first part of FP4
+ */
+extern void FP12_from_FP4(FP12 *x,FP4 *a);
+/**	@brief Initialise FP12 from three FP4s
+ *
+	@param x FP12 instance to be initialised
+	@param a FP4 to form first part of FP12
+	@param b FP4 to form second part of FP12
+	@param c FP4 to form third part of FP12
+ */
+extern void FP12_from_FP4s(FP12 *x,FP4 *a,FP4* b,FP4 *c);
+/**	@brief Fast Squaring of an FP12 in "unitary" form
+ *
+	@param x FP12 instance, on exit = y^2
+	@param y FP4 instance, must be unitary
+ */
+extern void FP12_usqr(FP12 *x,FP12 *y);
+/**	@brief Squaring an FP12
+ *
+	@param x FP12 instance, on exit = y^2
+	@param y FP12 instance
+ */
+extern void FP12_sqr(FP12 *x,FP12 *y);
+/**	@brief Fast multiplication of an FP12 by an FP12 that arises from an ATE pairing line function
+ *
+	Here the multiplier has a special form that can be exploited
+	@param x FP12 instance, on exit = x*y
+	@param y FP12 instance, of special form
+ */
+extern void FP12_smul(FP12 *x,FP12 *y);
+/**	@brief Multiplication of two FP12s
+ *
+	@param x FP12 instance, on exit = x*y
+	@param y FP12 instance, the multiplier
+ */
+extern void FP12_mul(FP12 *x,FP12 *y);
+/**	@brief Inverting an FP12
+ *
+	@param x FP12 instance, on exit = 1/y
+	@param y FP12 instance
+ */
+extern void FP12_inv(FP12 *x,FP12 *y);
+/**	@brief Raises an FP12 to the power of a BIG
+ *
+	@param r FP12 instance, on exit = y^b
+	@param x FP12 instance
+	@param b BIG number
+ */
+extern void FP12_pow(FP12 *r,FP12 *x,BIG b);
+/**	@brief Raises an FP12 instance x to a small integer power, side-channel resistant
+ *
+	@param x ECP instance, on exit = x^i
+	@param i small integer exponent
+	@param b maximum number of bits in exponent
+ */
+extern void FP12_pinpow(FP12 *x,int i,int b);
+/**	@brief Calculate x[0]^b[0].x[1]^b[1].x[2]^b[2].x[3]^b[3], side-channel resistant
+ *
+	@param r ECP instance, on exit = x[0]^b[0].x[1]^b[1].x[2]^b[2].x[3]^b[3]
+	@param x FP12 array with 4 FP12s
+	@param b BIG array of 4 exponents
+ */
+extern void FP12_pow4(FP12 *r,FP12 *x,BIG *b);
+/**	@brief Raises an FP12 to the power of the internal modulus p, using the Frobenius
+ *
+	@param x FP12 instance, on exit = x^p
+	@param f FP2 precalculated Frobenius constant
+ */
+extern void FP12_frob(FP12 *x,FP2 *f);
+/**	@brief Reduces all components of possibly unreduced FP12 mod Modulus
+ *
+	@param x FP12 instance, on exit reduced mod Modulus
+ */
+extern void FP12_reduce(FP12 *x);
+/**	@brief Normalises the components of an FP12
+ *
+	@param x FP12 instance to be normalised
+ */
+extern void FP12_norm(FP12 *x);
+/**	@brief Formats and outputs an FP12 to the console
+ *
+	@param x FP12 instance to be printed
+ */
+extern void FP12_output(FP12 *x);
+/**	@brief Formats and outputs an FP12 instance to an octet string
+ *
+	Serializes the components of an FP12 to big-endian base 256 form.
+	@param S output octet string
+	@param x FP12 instance to be converted to an octet string
+ */
+extern void FP12_toOctet(octet *S,FP12 *x);
+/**	@brief Creates an FP12 instance from an octet string
+ *
+	De-serializes the components of an FP12 to create an FP12 from big-endian base 256 components.
+	@param x FP12 instance to be created from an octet string
+	@param S input octet string
+
+ */
+extern void FP12_fromOctet(FP12 *x,octet *S);
+/**	@brief Calculate the trace of an FP12
+ *
+	@param t FP4 trace of x, on exit = tr(x)
+	@param x FP12 instance
+
+ */
+extern void FP12_trace(FP4 *t,FP12 *x);
+
+
+
+/* Pairing function prototypes */
+/**	@brief Calculate Miller loop for Optimal ATE pairing e(P,Q)
+ *
+	@param r FP12 result of the pairing calculation e(P,Q)
+	@param P ECP2 instance, an element of G2
+	@param Q ECP instance, an element of G1
+
+ */
+extern void PAIR_ate(FP12 *r,ECP2 *P,ECP *Q);
+/**	@brief Calculate Miller loop for Optimal ATE double-pairing e(P,Q).e(R,S)
+ *
+	Faster than calculating two separate pairings
+	@param r FP12 result of the pairing calculation e(P,Q).e(R,S), an element of GT
+	@param P ECP2 instance, an element of G2
+	@param Q ECP instance, an element of G1
+	@param R ECP2 instance, an element of G2
+	@param S ECP instance, an element of G1
+ */
+extern void PAIR_double_ate(FP12 *r,ECP2 *P,ECP *Q,ECP2 *R,ECP *S);
+/**	@brief Final exponentiation of pairing, converts output of Miller loop to element in GT
+ *
+	Here p is the internal modulus, and r is the group order
+	@param x FP12, on exit = x^((p^12-1)/r)
+ */
+extern void PAIR_fexp(FP12 *x);
+/**	@brief Fast point multiplication of a member of the group G1 by a BIG number
+ *
+	May exploit endomorphism for speed.
+	@param Q ECP member of G1.
+	@param b BIG multiplier
+
+ */
+extern void PAIR_G1mul(ECP *Q,BIG b);
+/**	@brief Fast point multiplication of a member of the group G2 by a BIG number
+ *
+	May exploit endomorphism for speed.
+	@param P ECP2 member of G1.
+	@param b BIG multiplier
+
+ */
+extern void PAIR_G2mul(ECP2 *P,BIG b);
+/**	@brief Fast raising of a member of GT to a BIG power
+ *
+	May exploit endomorphism for speed.
+	@param x FP12 member of GT.
+	@param b BIG exponent
+
+ */
+extern void PAIR_GTpow(FP12 *x,BIG b);
+/**	@brief Tests FP12 for membership of GT
+ *
+	@param x FP12 instance
+	@return 1 if x is in GT, else return 0
+
+ */
+extern int PAIR_GTmember(FP12 *x);
+
+
+
+/* Finite Field Prototypes */
+/**	@brief Copy one FF element of given length to another
+ *
+	@param x FF instance to be copied to, on exit = y
+	@param y FF instance to be copied from
+	@param n size of FF in BIGs
+
+ */
+extern void FF_copy(BIG *x,BIG *y,int n);
+/**	@brief Initialize an FF element of given length from a 32-bit integer m
+ *
+	@param x FF instance to be copied to, on exit = m
+	@param m integer
+	@param n size of FF in BIGs
+ */
+extern void FF_init(BIG *x,sign32 m,int n);
+/**	@brief Set FF element of given size to zero
+ *
+	@param x FF instance to be set to zero
+	@param n size of FF in BIGs
+ */
+extern void FF_zero(BIG *x,int n);
+/**	@brief Tests for FF element equal to zero
+ *
+	@param x FF number to be tested
+	@param n size of FF in BIGs
+	@return 1 if zero, else returns 0
+ */
+extern int FF_iszilch(BIG *x,int n);
+/**	@brief  return parity of an FF, that is the least significant bit
+ *
+	@param x FF number
+	@return 0 or 1
+ */
+extern int FF_parity(BIG *x);
+/**	@brief  return least significant m bits of an FF
+ *
+	@param x FF number
+	@param m number of bits to return. Assumed to be less than BASEBITS.
+	@return least significant n bits as an integer
+ */
+extern int FF_lastbits(BIG *x,int m);
+/**	@brief Set FF element of given size to unity
+ *
+	@param x FF instance to be set to unity
+	@param n size of FF in BIGs
+ */
+extern void FF_one(BIG *x,int n);
+/**	@brief Compares two FF numbers. Inputs must be normalised externally
+ *
+	@param x first FF number to be compared
+	@param y second FF number to be compared
+	@param n size of FF in BIGs
+	@return -1 is x<y, 0 if x=y, 1 if x>y
+ */
+extern int FF_comp(BIG *x,BIG *y,int n);
+/**	@brief addition of two FFs
+ *
+	@param x FF instance, on exit = y+z
+	@param y FF instance
+	@param z FF instance
+	@param n size of FF in BIGs
+ */
+extern void FF_add(BIG *x,BIG *y,BIG *z,int n);
+/**	@brief subtraction of two FFs
+ *
+	@param x FF instance, on exit = y-z
+	@param y FF instance
+	@param z FF instance
+	@param n size of FF in BIGs
+ */
+extern void FF_sub(BIG *x,BIG *y,BIG *z,int n);
+/**	@brief increment an FF by an integer,and normalise
+ *
+	@param x FF instance, on exit = x+m
+	@param m an integer to be added to x
+	@param n size of FF in BIGs
+ */
+extern void FF_inc(BIG *x,int m,int n);
+/**	@brief Decrement an FF by an integer,and normalise
+ *
+	@param x FF instance, on exit = x-m
+	@param m an integer to be subtracted from x
+	@param n size of FF in BIGs
+ */
+extern void FF_dec(BIG *x,int m,int n);
+/**	@brief Normalises the components of an FF
+ *
+	@param x FF instance to be normalised
+	@param n size of FF in BIGs
+ */
+extern void FF_norm(BIG *x,int n);
+/**	@brief Shift left an FF by 1 bit
+ *
+	@param x FF instance to be shifted left
+	@param n size of FF in BIGs
+ */
+extern void FF_shl(BIG *x,int n);
+/**	@brief Shift right an FF by 1 bit
+ *
+	@param x FF instance to be shifted right
+	@param n size of FF in BIGs
+ */
+extern void FF_shr(BIG *x,int n);
+/**	@brief Formats and outputs an FF to the console
+ *
+	@param x FF instance to be printed
+	@param n size of FF in BIGs
+ */
+extern void FF_output(BIG *x,int n);
+/**	@brief Formats and outputs an FF to the console, in raw form
+ *
+ 	@param x FF instance to be printed
+ 	@param n size of FF in BIGs
+ */
+extern void FF_rawoutput(BIG *x,int n);
+/**	@brief Formats and outputs an FF instance to an octet string
+ *
+	Converts an FF to big-endian base 256 form.
+	@param S output octet string
+	@param x FF instance to be converted to an octet string
+	@param n size of FF in BIGs
+ */
+extern void FF_toOctet(octet *S,BIG *x,int n);
+/**	@brief Populates an FF instance from an octet string
+ *
+	Creates FF from big-endian base 256 form.
+	@param x FF instance to be created from an octet string
+	@param S input octet string
+	@param n size of FF in BIGs
+ */
+extern void FF_fromOctet(BIG *x,octet *S,int n);
+/**	@brief Multiplication of two FFs
+ *
+	Uses Karatsuba method internally
+	@param x FF instance, on exit = y*z
+	@param y FF instance
+	@param z FF instance
+	@param n size of FF in BIGs
+ */
+extern void FF_mul(BIG *x,BIG *y,BIG *z,int n);
+/**	@brief Reduce FF mod a modulus
+ *
+	This is slow
+	@param x FF instance to be reduced mod m - on exit = x mod m
+	@param m FF modulus
+	@param n size of FF in BIGs
+ */
+extern void FF_mod(BIG *x,BIG *m,int n);
+/**	@brief Square an FF
+ *
+	Uses Karatsuba method internally
+	@param x FF instance, on exit = y^2
+	@param y FF instance to be squared
+	@param n size of FF in BIGs
+ */
+extern void FF_sqr(BIG *x,BIG *y,int n);
+/**	@brief Reduces a double-length FF with respect to a given modulus
+ *
+	This is slow
+	@param x FF instance, on exit = y mod z
+	@param y FF instance, of double length 2*n
+	@param z FF modulus
+	@param n size of FF in BIGs
+ */
+extern void FF_dmod(BIG *x,BIG *y,BIG *z,int n);
+/**	@brief Invert an FF mod a prime modulus
+ *
+	@param x FF instance, on exit = 1/y mod z
+	@param y FF instance
+	@param z FF prime modulus
+	@param n size of FF in BIGs
+ */
+extern void FF_invmodp(BIG *x,BIG *y,BIG *z,int n);
+/**	@brief Create an FF from a random number generator
+ *
+	@param x FF instance, on exit x is a random number of length n BIGs with most significant bit a 1
+	@param R an instance of a Cryptographically Secure Random Number Generator
+	@param n size of FF in BIGs
+ */
+extern void FF_random(BIG *x,csprng *R,int n);
+/**	@brief Create a random FF less than a given modulus from a random number generator
+ *
+	@param x FF instance, on exit x is a random number < y
+	@param y FF instance, the modulus
+	@param R an instance of a Cryptographically Secure Random Number Generator
+	@param n size of FF in BIGs
+ */
+extern void FF_randomnum(BIG *x,BIG *y,csprng *R,int n);
+/**	@brief Calculate r=x^e mod m, side channel resistant
+ *
+	@param r FF instance, on exit = x^e mod p
+	@param x FF instance
+	@param e FF exponent
+	@param m FF modulus
+	@param n size of FF in BIGs
+ */
+extern void FF_skpow(BIG *r,BIG *x,BIG * e,BIG *m,int n);
+/**	@brief Calculate r=x^e mod m, side channel resistant
+ *
+	For short BIG exponent
+	@param r FF instance, on exit = x^e mod p
+	@param x FF instance
+	@param e BIG exponent
+	@param m FF modulus
+	@param n size of FF in BIGs
+ */
+extern void FF_skspow(BIG *r,BIG *x,BIG e,BIG *m,int n);
+/**	@brief Calculate r=x^e mod m
+ *
+	For very short integer exponent
+	@param r FF instance, on exit = x^e mod p
+	@param x FF instance
+	@param e integer exponent
+	@param m FF modulus
+	@param n size of FF in BIGs
+ */
+extern void FF_power(BIG *r,BIG *x,int e,BIG *m,int n);
+/**	@brief Calculate r=x^e mod m
+ *
+	@param r FF instance, on exit = x^e mod p
+	@param x FF instance
+	@param e FF exponent
+	@param m FF modulus
+	@param n size of FF in BIGs
+ */
+extern void FF_pow(BIG *r,BIG *x,BIG *e,BIG *m,int n);
+/**	@brief Test if an FF has factor in common with integer s
+ *
+	@param x FF instance to be tested
+	@param s the supplied integer
+	@param n size of FF in BIGs
+	@return 1 if gcd(x,s)!=1, else return 0
+ */
+extern int FF_cfactor(BIG *x,sign32 s,int n);
+/**	@brief Test if an FF is prime
+ *
+	Uses Miller-Rabin Method
+	@param x FF instance to be tested
+	@param R an instance of a Cryptographically Secure Random Number Generator
+	@param n size of FF in BIGs
+	@return 1 if x is (almost certainly) prime, else return 0
+ */
+extern int FF_prime(BIG *x,csprng *R,int n);
+/**	@brief Calculate r=x^e.y^f mod m
+ *
+	@param r FF instance, on exit = x^e.y^f mod p
+	@param x FF instance
+	@param e BIG exponent
+	@param y FF instance
+	@param f BIG exponent
+	@param m FF modulus
+	@param n size of FF in BIGs
+ */
+extern void FF_pow2(BIG *r,BIG *x,BIG e,BIG *y,BIG f,BIG *m,int n);
+
+
+/* Octet string handlers */
+/**	@brief Formats and outputs an octet to the console in hex
+ *
+	@param O Octet to be output
+ */
+extern void OCT_output(octet *O);
+/**	@brief Formats and outputs an octet to the console as a character string
+ *
+	@param O Octet to be output
+ */
+extern void OCT_output_string(octet *O);
+/**	@brief Wipe clean an octet
+ *
+	@param O Octet to be cleaned
+ */
+extern void OCT_clear(octet *O);
+/**	@brief Compare two octets
+ *
+	@param O first Octet to be compared
+	@param P second Octet to be compared
+	@return 1 if equal, else 0
+ */
+extern int  OCT_comp(octet *O,octet *P);
+/**	@brief Compare first n bytes of two octets
+ *
+	@param O first Octet to be compared
+	@param P second Octet to be compared
+	@param n number of bytes to compare
+	@return 1 if equal, else 0
+ */
+extern int  OCT_ncomp(octet *O,octet *P,int n);
+/**	@brief Join from a C string to end of an octet
+ *
+	Truncates if there is no room
+	@param O Octet to be written to
+	@param s zero terminated string to be joined to octet
+ */
+extern void OCT_jstring(octet *O,char *s);
+/**	@brief Join bytes to end of an octet
+ *
+	Truncates if there is no room
+	@param O Octet to be written to
+	@param s bytes to be joined to end of octet
+	@param n number of bytes to join
+ */
+extern void OCT_jbytes(octet *O,char *s,int n);
+/**	@brief Join single byte to end of an octet, repeated n times
+ *
+	Truncates if there is no room
+	@param O Octet to be written to
+	@param b byte to be joined to end of octet
+	@param n number of times b is to be joined
+ */
+extern void OCT_jbyte(octet *O,int b,int n);
+/**	@brief Join one octet to the end of another
+ *
+	Truncates if there is no room
+	@param O Octet to be written to
+	@param P Octet to be joined to the end of O
+ */
+extern void OCT_joctet(octet *O,octet *P);
+/**	@brief XOR common bytes of a pair of Octets
+ *
+	@param O Octet - on exit = O xor P
+	@param P Octet to be xored into O
+ */
+extern void OCT_xor(octet *O,octet *P);
+/**	@brief reset Octet to zero length
+ *
+	@param O Octet to be emptied
+ */
+extern void OCT_empty(octet *O);
+/**	@brief Pad out an Octet to the given length
+ *
+	Padding is done by inserting leading zeros, so abcd becomes 00abcd
+	@param O Octet to be padded
+	@param n new length of Octet
+ */
+extern int OCT_pad(octet *O,int n);
+/**	@brief Convert an Octet to printable base64 number
+ *
+	@param b zero terminated byte array to take base64 conversion
+	@param O Octet to be converted
+ */
+extern void OCT_tobase64(char *b,octet *O);
+/**	@brief Populate an Octet from base64 number
+ *
+ 	@param O Octet to be populated
+	@param b zero terminated base64 string
+
+ */
+extern void OCT_frombase64(octet *O,char *b);
+/**	@brief Copy one Octet into another
+ *
+ 	@param O Octet to be copied to
+	@param P Octet to be copied from
+
+ */
+extern void OCT_copy(octet *O,octet *P);
+/**	@brief XOR every byte of an octet with input m
+ *
+ 	@param O Octet
+	@param m byte to be XORed with every byte of O
+
+ */
+extern void OCT_xorbyte(octet *O,int m);
+/**	@brief Chops Octet into two, leaving first n bytes in O, moving the rest to P
+ *
+ 	@param O Octet to be chopped
+	@param P new Octet to be created
+	@param n number of bytes to chop off O
+
+ */
+extern void OCT_chop(octet *O,octet *P,int n);
+/**	@brief Join n bytes of integer m to end of Octet O (big endian)
+ *
+	Typically n is 4 for a 32-bit integer
+ 	@param O Octet to be appended to
+	@param m integer to be appended to O
+	@param n number of bytes in m
+
+ */
+extern void OCT_jint(octet *O,int m,int n);
+/**	@brief Create an Octet from bytes taken from a random number generator
+ *
+	Truncates if there is no room
+ 	@param O Octet to be populated
+	@param R an instance of a Cryptographically Secure Random Number Generator
+	@param n number of bytes to extracted from R
+
+ */
+extern void OCT_rand(octet *O,csprng *R,int n);
+/**	@brief Shifts Octet left by n bytes
+ *
+	Leftmost bytes disappear
+ 	@param O Octet to be shifted
+	@param n number of bytes to shift
+
+ */
+extern void OCT_shl(octet *O,int n);
+/**	@brief Convert a hex number to an Octet
+ *
+	@param dst Octet
+	@param src Hex string to be converted
+ */
+extern void OCT_fromHex(octet *dst,char *src);
+/**	@brief Convert an Octet to printable hex number
+ *
+	@param dst hex value
+	@param src Octet to be converted
+ */
+extern void OCT_toHex(octet *src,char *dst);
+/**	@brief Convert an Octet to string
+ *
+	@param dst string value
+	@param src Octet to be converted
+ */
+extern void OCT_toStr(octet *src,char *dst);
+
+
+
+/* Hash function */
+/**	@brief Initialise an instance of SHA256
+ *
+	@param H an instance SHA256
+ */
+extern void HASH256_init(hash256 *H);
+/**	@brief Add a byte to the hash
+ *
+	@param H an instance SHA256
+	@param b byte to be included in hash
+ */
+extern void HASH256_process(hash256 *H,int b);
+/**	@brief Generate 32-byte hash
+ *
+	@param H an instance SHA256
+	@param h is the output 32-byte hash
+ */
+extern void HASH256_hash(hash256 *H,char *h);
+
+
+/**	@brief Initialise an instance of SHA384
+ *
+	@param H an instance SHA384
+ */
+extern void HASH384_init(hash384 *H);
+/**	@brief Add a byte to the hash
+ *
+	@param H an instance SHA384
+	@param b byte to be included in hash
+ */
+extern void HASH384_process(hash384 *H,int b);
+/**	@brief Generate 48-byte hash
+ *
+	@param H an instance SHA384
+	@param h is the output 48-byte hash
+ */
+extern void HASH384_hash(hash384 *H,char *h);
+
+
+/**	@brief Initialise an instance of SHA512
+ *
+	@param H an instance SHA512
+ */
+extern void HASH512_init(hash512 *H);
+/**	@brief Add a byte to the hash
+ *
+	@param H an instance SHA512
+	@param b byte to be included in hash
+ */
+extern void HASH512_process(hash512 *H,int b);
+/**	@brief Generate 64-byte hash
+ *
+	@param H an instance SHA512
+	@param h is the output 64-byte hash
+ */
+extern void HASH512_hash(hash512 *H,char *h);
+
+
+/* AES functions */
+/**	@brief Reset AES mode or IV
+ *
+	@param A an instance of the AMCL_AES
+	@param m is the new active mode of operation (ECB, CBC, OFB, CFB etc)
+	@param iv the new Initialisation Vector
+ */
+extern void AES_reset(amcl_aes *A,int m,char *iv);
+/**	@brief Extract chaining vector from AMCL_AES instance
+ *
+	@param A an instance of the AMCL_AES
+	@param f the extracted chaining vector
+ */
+extern void AES_getreg(amcl_aes *A,char * f);
+/**	@brief Initialise an instance of AMCL_AES and its mode of operation
+ *
+	@param A an instance AMCL_AES
+	@param m is the active mode of operation (ECB, CBC, OFB, CFB etc)
+	@param n is the key length in bytes, 16, 24 or 32
+	@param k the AES key as an array of 16 bytes
+	@param iv the Initialisation Vector
+	@return 0 for invalid n
+ */
+extern int AES_init(amcl_aes *A,int m,int n,char *k,char *iv);
+/**	@brief Encrypt a single 16 byte block in ECB mode
+ *
+	@param A an instance of the AMCL_AES
+	@param b is an array of 16 plaintext bytes, on exit becomes ciphertext
+ */
+extern void AES_ecb_encrypt(amcl_aes *A,uchar * b);
+/**	@brief Decrypt a single 16 byte block in ECB mode
+ *
+	@param A an instance of the AMCL_AES
+	@param b is an array of 16 cipherext bytes, on exit becomes plaintext
+ */
+extern void AES_ecb_decrypt(amcl_aes *A,uchar * b);
+/**	@brief Encrypt a single 16 byte block in active mode
+ *
+	@param A an instance of the AMCL_AES
+	@param b is an array of 16 plaintext bytes, on exit becomes ciphertext
+	@return 0, or overflow bytes from CFB mode
+ */
+extern unsign32 AES_encrypt(amcl_aes *A,char *b );
+/**	@brief Decrypt a single 16 byte block in active mode
+ *
+	@param A an instance of the AMCL_AES
+	@param b is an array of 16 ciphertext bytes, on exit becomes plaintext
+	@return 0, or overflow bytes from CFB mode
+ */
+extern unsign32 AES_decrypt(amcl_aes *A,char *b);
+/**	@brief Clean up after application of AES
+ *
+	@param A an instance of the AMCL_AES
+ */
+extern void AES_end(amcl_aes *A);
+
+
+/* AES-GCM functions */
+/**	@brief Initialise an instance of AES-GCM mode
+ *
+	@param G an instance AES-GCM
+	@param nk is the key length in bytes, 16, 24 or 32
+	@param k the AES key as an array of 16 bytes
+	@param n the number of bytes in the Initialisation Vector (IV)
+	@param iv the IV
+ */
+extern void GCM_init(gcm *G,int nk,char *k,int n,char *iv);
+/**	@brief Add header (material to be authenticated but not encrypted)
+ *
+	Note that this function can be called any number of times with n a multiple of 16, and then one last time with any value for n
+	@param G an instance AES-GCM
+	@param b is the header material to be added
+	@param n the number of bytes in the header
+ */
+extern int GCM_add_header(gcm *G,char *b,int n);
+/**	@brief Add plaintext and extract ciphertext
+ *
+	Note that this function can be called any number of times with n a multiple of 16, and then one last time with any value for n
+	@param G an instance AES-GCM
+	@param c is the ciphertext generated
+	@param p is the plaintext material to be added
+	@param n the number of bytes in the plaintext
+ */
+extern int GCM_add_plain(gcm *G,char *c,char *p,int n);
+/**	@brief Add ciphertext and extract plaintext
+ *
+	Note that this function can be called any number of times with n a multiple of 16, and then one last time with any value for n
+	@param G an instance AES-GCM
+	@param p is the plaintext generated
+	@param c is the ciphertext material to be added
+	@param n the number of bytes in the ciphertext
+ */
+extern int GCM_add_cipher(gcm *G,char *p,char *c,int n);
+/**	@brief Finish off and extract authentication tag (HMAC)
+ *
+	@param G is an active instance AES-GCM
+	@param t is the output 16 byte authentication tag
+ */
+extern void GCM_finish(gcm *G,char *t);
+
+
+
+/* random numbers */
+/**	@brief Seed a random number generator from an array of bytes
+ *
+	The provided seed should be truly random
+	@param R an instance of a Cryptographically Secure Random Number Generator
+	@param n the number of seed bytes provided
+	@param b an array of seed bytes
+
+ */
+extern void RAND_seed(csprng *R,int n,char *b);
+/**	@brief Delete all internal state of a random number generator
+ *
+	@param R an instance of a Cryptographically Secure Random Number Generator
+ */
+extern void RAND_clean(csprng *R);
+/**	@brief Return a random byte from a random number generator
+ *
+	@param R an instance of a Cryptographically Secure Random Number Generator
+	@return a random byte
+ */
+extern int RAND_byte(csprng *R);
+
+/**
+ * @brief Convert to DBIG number from byte array of given length
+ *
+ * Convert to DBIG number from byte array of given length.
+ *
+ * @param x DBIG number
+ * @param a byte array
+ * @param s byte array length
+ */
+extern void BIG_dfromBytesLen(DBIG x,char *a,int s);
+
+#endif
diff --git a/version22/c/arch.h b/version22/c/arch.h
new file mode 100644
index 0000000..21753bd
--- /dev/null
+++ b/version22/c/arch.h
@@ -0,0 +1,119 @@
+/*
+	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.
+*/
+
+/* Architecture definition header file */
+
+/**
+ * @file arch.h
+ * @author Mike Scott
+ * @date 23rd February 2016
+ * @brief Architecture Header File
+ *
+ * Specify Processor Architecture
+ *
+ */
+
+/* NOTE: There is only one user configurable section in this header - see below */
+
+#ifndef ARCH_H
+#define ARCH_H
+
+
+
+
+/*** START OF USER CONFIGURABLE SECTION - set architecture ***/
+
+#ifdef CMAKE
+#define CHUNK @AMCL_CHUNK@  /**< size of chunk in bits = wordlength of computer = 16, 32 or 64. Note not all curve options are supported on 16-bit processors - see rom.c */
+#else
+#define CHUNK 32		/**< size of chunk in bits = wordlength of computer = 16, 32 or 64. Note not all curve options are supported on 16-bit processors - see rom.c */
+#endif
+
+/*** END OF USER CONFIGURABLE SECTION ***/
+
+
+
+/* Create Integer types */
+/* Support for C99?  Note for GCC need to explicitly include -std=c99 in command line */
+
+#if __STDC_VERSION__ >= 199901L
+/* C99 code */
+#define C99
+#else
+/* Not C99 code */
+#endif
+
+#ifndef C99  /* You are on your own! These are for Microsoft C */
+#define sign32 __int32			/**< 32-bit signed integer */
+#define sign8 signed char		/**< 8-bit signed integer */
+#define unsign32 unsigned __int32 /**< 32-bit unsigned integer */
+#define unsign64 unsigned long long  /**< 64-bit unsigned integer */
+#else
+#include <stdint.h>
+#define sign8 int8_t			/**< 8-bit signed integer */
+#define sign32 int32_t			/**< 32-bit signed integer */
+#define unsign32 uint32_t		/**< 32-bit unsigned integer */
+#define unsign64 uint64_t		/**< 64-bit unsigned integer */
+#endif
+
+#define uchar unsigned char  /**<  Unsigned char */
+
+/* Don't mess with anything below this line unless you know what you are doing */
+/* This next is probably OK, but may need changing for non-C99-standard environments */
+
+/* This next is probably OK, but may need changing for non-C99-standard environments */
+
+#if CHUNK==16
+#ifndef C99
+#define chunk __int16		/**< C type corresponding to word length */
+#define dchunk __int32		/**< Always define double length chunk type if available */
+#else
+#define chunk int16_t		/**< C type corresponding to word length */
+#define dchunk int32_t		/**< Always define double length chunk type if available */
+#endif
+#endif
+
+#if CHUNK == 32
+#ifndef C99
+#define chunk __int32		/**< C type corresponding to word length */
+#define dchunk __int64		/**< Always define double length chunk type if available */
+#else
+#define chunk int32_t		/**< C type corresponding to word length */
+#define dchunk int64_t		/**< Always define double length chunk type if available */
+#endif
+#endif
+
+#if CHUNK == 64
+
+#ifndef C99
+#define chunk __int64		/**< C type corresponding to word length */
+/**< Note - no 128-bit type available    */
+#else
+#define chunk int64_t		/**< C type corresponding to word length */
+#ifdef __GNUC__
+#define dchunk __int128		/**< Always define double length chunk type if available - GCC supports 128 bit type  ??? */
+#endif
+#endif
+#endif
+
+#ifdef dchunk
+#define COMBA      /**< Use COMBA method for faster BN muls, sqrs and reductions */
+#endif
+
+#endif
diff --git a/version22/c/benchtest_ec.c b/version22/c/benchtest_ec.c
new file mode 100644
index 0000000..5929d0b
--- /dev/null
+++ b/version22/c/benchtest_ec.c
@@ -0,0 +1,212 @@
+/* Test and benchmark elliptic curve and RSA functions
+	First build amcl.a from build_ec batch file
+	gcc -O3 benchtest_ec.c amcl.a -o benchtest_ec.exe
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "amcl.h"
+#include "rsa.h"
+
+#define MIN_TIME 10.0
+#define MIN_ITERS 10 
+
+int main()
+{
+    csprng RNG;
+	BIG s,r,x,y;
+	ECP P,G;
+	FP12 g;
+    int i,iterations;
+    clock_t start;
+    double elapsed;
+	char pr[10];
+	unsigned long ran;
+    rsa_public_key pub;
+    rsa_private_key priv;
+    char m[RFS],d[RFS],c[RFS];
+    octet M= {0,sizeof(m),m};
+    octet D= {0,sizeof(d),d};
+    octet C= {0,sizeof(c),c};
+
+#if CHOICE==NIST256 
+	printf("NIST256 Curve\n");
+#endif
+#if CHOICE==C25519 
+	printf("C25519 Curve\n");
+#endif
+#if CHOICE==BRAINPOOL
+	printf("BRAINPOOL Curve\n");
+#endif
+#if CHOICE==ANSSI
+	printf("ANSSI Curve\n");
+#endif
+#if CHOICE==MF254
+	printf("MF254 Curve\n");
+#endif
+#if CHOICE==MS255
+	printf("MS255 Curve\n");
+#endif
+#if CHOICE==MF256
+	printf("MF256 Curve\n");
+#endif
+#if CHOICE==MS256
+	printf("MS256 Curve\n");
+#endif
+#if CHOICE==HIFIVE
+	printf("HIFIVE Curve\n");
+#endif
+#if CHOICE==GOLDILOCKS
+	printf("GOLDILOCKS Curve\n");
+#endif
+#if CHOICE==NIST384
+	printf("NIST384 Curve\n");
+#endif
+#if CHOICE==C41417
+	printf("C41417 Curve\n");
+#endif
+#if CHOICE==NIST521
+	printf("NIST521 Curve\n");
+#endif
+
+#if CHOICE==BN254
+	printf("BN254 Curve\n");
+#endif
+#if CHOICE==BN454
+	printf("BN454 Curve\n");	
+#endif
+#if CHOICE==BN646
+	printf("BN646 Curve\n");	
+#endif
+
+#if CHOICE==BN254_CX 
+	printf("BN254_CX Curve\n");	
+#endif
+#if CHOICE==BN254_T
+	printf("BN254_T Curve\n");	
+#endif	
+#if CHOICE==BN254_T2 
+	printf("BN254_T2 Curve\n");	
+#endif
+#if CHOICE==BLS455 
+	printf("BLS455 Curve\n");	
+#endif
+#if CHOICE==BLS383 
+	printf("BLS383 Curve\n");	
+#endif
+
+#if CURVETYPE==WEIERSTRASS
+	printf("Weierstrass parameterization\n");
+#endif
+#if CURVETYPE==EDWARDS
+	printf("Edwards parameterization\n");
+#endif
+#if CURVETYPE==MONTGOMERY
+	printf("Montgomery parameterization\n");
+#endif
+
+#if CHUNK==16
+	printf("16-bit Build\n");
+#endif
+#if CHUNK==32
+	printf("32-bit Build\n");
+#endif
+#if CHUNK==64
+	printf("64-bit Build\n");
+#endif
+
+	time((time_t *)&ran);
+	pr[0]=ran;
+	pr[1]=ran>>8;
+	pr[2]=ran>>16;
+	pr[3]=ran>>24;
+	for (i=4;i<10;i++) pr[i]=i;
+    RAND_seed(&RNG,10,pr);
+
+	BIG_rcopy(x,CURVE_Gx);
+#if CURVETYPE!=MONTGOMERY
+	BIG_rcopy(y,CURVE_Gy);
+    ECP_set(&G,x,y);
+#else
+    ECP_set(&G,x);
+#endif
+	
+	BIG_rcopy(r,CURVE_Order);
+	BIG_randomnum(s,r,&RNG);
+	ECP_copy(&P,&G);
+    ECP_mul(&P,r);
+
+	if (!ECP_isinf(&P))
+	{
+		printf("FAILURE - rG!=O\n");
+		return 0;
+	}
+
+	iterations=0;
+    start=clock();
+    do {
+		ECP_copy(&P,&G);
+		ECP_mul(&P,s);
+
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("EC  mul - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+	
+	printf("Generating %d-bit RSA public/private key pair\n",FFLEN*BIGBITS);
+
+	iterations=0;
+    start=clock();
+    do {
+      RSA_KEY_PAIR(&RNG,65537,&priv,&pub,NULL,NULL);
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("RSA gen - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+    //FF_randomnum(plain,pub.n,&RNG,FFLEN);
+
+	M.len=RFS;
+	for (i=0;i<RFS;i++) M.val[i]=i%128;
+
+	iterations=0;
+    start=clock();
+    do {
+		RSA_ENCRYPT(&pub,&M,&C);
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("RSA enc - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	iterations=0;
+    start=clock();
+    do {
+		RSA_DECRYPT(&priv,&C,&D);
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("RSA dec - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	for (i=0;i<RFS;i++)
+	{
+		if (M.val[i]!=D.val[i])
+		{
+			printf("FAILURE - RSA decryption\n");
+			return 0;
+		}
+	}
+
+	printf("All tests pass\n");
+
+	return 0;
+}
diff --git a/version22/c/benchtest_pair.c b/version22/c/benchtest_pair.c
new file mode 100644
index 0000000..c9dcf38
--- /dev/null
+++ b/version22/c/benchtest_pair.c
@@ -0,0 +1,257 @@
+/* Test and benchmark pairing functions
+	First build amcl.a from build_pair batch file
+	gcc -O3 benchtest_pair.c amcl.a -o benchtest_pair.exe
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "amcl.h" /* Make sure and select a pairing-friendly curve in here! */
+
+#define MIN_TIME 10.0
+#define MIN_ITERS 10 
+
+int main()
+{
+    csprng RNG;
+	BIG q,s,r,x,y,a,b,m;
+	ECP P,G;
+	FP2 wx,wy,f; 
+	FP4 c,cp,cpm1,cpm2,cr;
+    ECP2 Q,W;
+	FP12 g,w;
+	unsigned long ran;
+
+    int i,iterations;
+    clock_t start;
+    double elapsed;
+	char pr[10];
+
+#if CHOICE==BN254
+	printf("BN254 Curve\n");
+#endif
+#if CHOICE==BN454
+	printf("BN454 Curve\n");	
+#endif
+#if CHOICE==BN646
+	printf("BN646 Curve\n");	
+#endif
+
+#if CHOICE==BN254_CX 
+	printf("BN254_CX Curve\n");	
+#endif
+#if CHOICE==BN254_T
+	printf("BN254_T Curve\n");	
+#endif	
+#if CHOICE==BN254_T2 
+	printf("BN254_T2 Curve\n");	
+#endif
+#if CHOICE==BLS455 
+	printf("BLS455 Curve\n");	
+#endif
+#if CHOICE==BLS383 
+	printf("BLS383 Curve\n");	
+#endif
+
+#if CHUNK==16
+	printf("16-bit Build\n");
+#endif
+#if CHUNK==32
+	printf("32-bit Build\n");
+#endif
+#if CHUNK==64
+	printf("64-bit Build\n");
+#endif
+
+	time((time_t *)&ran);
+	pr[0]=ran;
+	pr[1]=ran>>8;
+	pr[2]=ran>>16;
+	pr[3]=ran>>24;
+	for (i=4;i<10;i++) pr[i]=i;
+
+    RAND_seed(&RNG,10,pr);
+
+	BIG_rcopy(x,CURVE_Gx);
+
+	BIG_rcopy(y,CURVE_Gy);
+    ECP_set(&G,x,y);
+
+	
+	BIG_rcopy(r,CURVE_Order);
+	BIG_randomnum(s,r,&RNG);
+	ECP_copy(&P,&G);
+    PAIR_G1mul(&P,r);
+
+	if (!ECP_isinf(&P))
+	{
+		printf("FAILURE - rG!=O\n");
+		return 0;
+	}
+	
+	iterations=0;
+    start=clock();
+    do {
+		ECP_copy(&P,&G);
+		PAIR_G1mul(&P,s);
+
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("G1 mul              - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+    
+    BIG_rcopy(wx.a,CURVE_Pxa); FP_nres(wx.a);
+    BIG_rcopy(wx.b,CURVE_Pxb); FP_nres(wx.b);
+    BIG_rcopy(wy.a,CURVE_Pya); FP_nres(wy.a);
+    BIG_rcopy(wy.b,CURVE_Pyb); FP_nres(wy.b);    
+	ECP2_set(&W,&wx,&wy);
+
+	ECP2_copy(&Q,&W);
+    ECP2_mul(&Q,r);
+
+	if (!ECP2_isinf(&Q))
+	{
+		printf("FAILURE - rQ!=O\n");
+		return 0;
+	}
+
+	iterations=0;
+    start=clock();
+    do {
+		ECP2_copy(&Q,&W);
+		PAIR_G2mul(&Q,s);
+
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("G2 mul              - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	PAIR_ate(&w,&Q,&P);
+	PAIR_fexp(&w);
+
+	FP12_copy(&g,&w);
+
+	PAIR_GTpow(&g,r);
+
+	if (!FP12_isunity(&g))
+	{
+		printf("FAILURE - g^r!=1\n");
+		return 0;
+	}
+
+	iterations=0;
+    start=clock();
+    do {
+		FP12_copy(&g,&w);
+		PAIR_GTpow(&g,s);
+
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("GT pow              - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	BIG_rcopy(a,CURVE_Fra);
+	BIG_rcopy(b,CURVE_Frb);
+	FP2_from_BIGs(&f,a,b);
+
+	BIG_rcopy(q,Modulus);
+
+	BIG_copy(m,q);
+	BIG_mod(m,r);
+
+	BIG_copy(a,s);
+	BIG_mod(a,m);
+
+	BIG_copy(b,s);
+	BIG_sdiv(b,m);
+
+	FP12_copy(&g,&w);
+	FP12_trace(&c,&g);
+
+	FP12_frob(&g,&f);
+	FP12_trace(&cp,&g);
+
+	FP12_conj(&w,&w);
+	FP12_mul(&g,&w);
+
+	FP12_trace(&cpm1,&g);
+	FP12_mul(&g,&w);
+	FP12_trace(&cpm2,&g);
+
+	iterations=0;
+    start=clock();
+    do {
+		FP4_xtr_pow2(&cr,&cp,&c,&cpm1,&cpm2,a,b);
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("GT pow (compressed) - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	iterations=0;
+    start=clock();
+    do {
+		PAIR_ate(&w,&Q,&P);
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("PAIRing ATE         - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	iterations=0;
+    start=clock();
+    do {
+		FP12_copy(&g,&w);
+		PAIR_fexp(&g);
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("PAIRing FEXP        - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	ECP_copy(&P,&G);	
+	ECP2_copy(&Q,&W);
+
+	PAIR_G1mul(&P,s);
+	PAIR_ate(&g,&Q,&P);
+	PAIR_fexp(&g);
+
+	ECP_copy(&P,&G);
+
+	PAIR_G2mul(&Q,s);
+	PAIR_ate(&w,&Q,&P);
+	PAIR_fexp(&w);
+
+	if (!FP12_equals(&g,&w))
+	{
+		printf("FAILURE - e(sQ,p)!=e(Q,sP) \n");
+		return 0;
+	}
+
+	ECP2_copy(&Q,&W);
+	PAIR_ate(&g,&Q,&P);
+	PAIR_fexp(&g);
+
+	PAIR_GTpow(&g,s);
+
+	if (!FP12_equals(&g,&w))
+	{
+		printf("FAILURE - e(sQ,p)!=e(Q,P)^s \n");
+		return 0;
+	}
+
+	printf("All tests pass\n");
+
+	return 0;
+}
diff --git a/version22/c/big.c b/version22/c/big.c
new file mode 100644
index 0000000..1fe6259
--- /dev/null
+++ b/version22/c/big.c
@@ -0,0 +1,1525 @@
+/*
+	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.
+*/
+
+/* AMCL basic functions for BIG type */
+/* SU=m, SU is Stack Usage */
+
+#include "amcl.h"
+
+/* Calculates x*y+c+*r */
+
+#ifdef dchunk
+
+/* Method required to calculate x*y+c+r, bottom half in r, top half returned */
+chunk muladd(chunk x,chunk y,chunk c,chunk *r)
+{
+    dchunk prod=(dchunk)x*y+c+*r;
+    *r=(chunk)prod&BMASK;
+    return (chunk)(prod>>BASEBITS);
+}
+
+#else
+
+/* No integer type available that can store double the wordlength */
+/* accumulate partial products */
+
+chunk muladd(chunk x,chunk y,chunk c,chunk *r)
+{
+    chunk x0,x1,y0,y1;
+    chunk bot,top,mid,carry;
+    x0=x&HMASK;
+    x1=(x>>HBITS);
+    y0=y&HMASK;
+    y1=(y>>HBITS);
+    bot=x0*y0;
+    top=x1*y1;
+    mid=x0*y1+x1*y0;
+    x0=mid&HMASK1;
+    x1=(mid>>HBITS1);
+    bot+=x0<<HBITS;
+    bot+=*r;
+    bot+=c;
+
+#if HDIFF==1
+    bot+=(top&HDIFF)<<(BASEBITS-1);
+    top>>=HDIFF;
+#endif
+
+    top+=x1;
+    carry=bot>>BASEBITS;
+    bot&=BMASK;
+    top+=carry;
+
+    *r=bot;
+    return top;
+}
+
+#endif
+
+/*
+
+// Alternative non Standard Solution required if no type available that can store double the wordlength
+// The use of compiler intrinsics is permitted
+
+
+#if CHUNK==64
+#ifdef _WIN64
+#include <intrin.h>
+
+static INLINE chunk muladd(chunk x,chunk y,chunk c,chunk *r)
+{
+	chunk t,e;
+	uchunk b;
+	b=_mul128(x,y,&t);
+	e=c+*r;
+	b+=e;
+// make correction for possible carry to top half
+	if (e<0)
+		t-=(b>e);
+	else
+		t+=(b<e);
+
+	*r=b&MASK;
+	return (chunk)((t<<(CHUNK-BASEBITS)) | (b>>BASEBITS));
+}
+
+#endif
+#endif
+
+*/
+
+/* test a=0? */
+int BIG_iszilch(BIG a)
+{
+    int i;
+    for (i=0; i<NLEN; i++)
+        if (a[i]!=0) return 0;
+    return 1;
+}
+
+/* test a=0? */
+int BIG_diszilch(DBIG a)
+{
+    int i;
+    for (i=0; i<DNLEN; i++)
+        if (a[i]!=0) return 0;
+    return 1;
+}
+
+/* SU= 56 */
+/* output a */
+void BIG_output(BIG a)
+{
+    BIG b;
+    int i,len;
+    len=BIG_nbits(a);
+    if (len%4==0) len/=4;
+    else
+    {
+        len/=4;
+        len++;
+    }
+    if (len<MODBYTES*2) len=MODBYTES*2;
+
+    for (i=len-1; i>=0; i--)
+    {
+        BIG_copy(b,a);
+        BIG_shr(b,i*4);
+        printf("%01x",(unsigned int) b[0]&15);
+    }
+}
+
+/* SU= 16 */
+void BIG_rawoutput(BIG a)
+{
+    int i;
+    printf("(");
+    for (i=0; i<NLEN-1; i++)
+#if CHUNK==64
+        printf("%"PRIxMAX",",(uint64_t) a[i]);
+    printf("%"PRIxMAX")",(uint64_t) a[NLEN-1]);
+#else
+        printf("%x,",(unsigned int) a[i]);
+    printf("%x)",(unsigned int) a[NLEN-1]);
+#endif
+}
+/*
+void BIG_rawdoutput(DBIG a)
+{
+	int i;
+	printf("(");
+	for (i=0;i<DNLEN-1;i++)
+#if CHUNK==64
+	  printf("%llx,",(long long unsigned int) a[i]);
+	printf("%llx)",(long long unsigned int) a[DNLEN-1]);
+#else
+	  printf("%x,",(unsigned int) a[i]);
+	printf("%x)",(unsigned int) a[NLEN-1]);
+#endif
+}
+*/
+/* Swap a and b if d=1 */
+void BIG_cswap(BIG a,BIG b,int d)
+{
+    int i;
+    chunk t,c=d;
+    c=~(c-1);
+#ifdef DEBUG_NORM
+    for (i=0; i<=NLEN; i++)
+#else
+    for (i=0; i<NLEN; i++)
+#endif
+    {
+        t=c&(a[i]^b[i]);
+        a[i]^=t;
+        b[i]^=t;
+    }
+}
+
+/* Move b to a if d=1 */
+void BIG_cmove(BIG f,BIG g,int d)
+{
+    int i;
+    chunk b=(chunk)-d;
+#ifdef DEBUG_NORM
+    for (i=0; i<=NLEN; i++)
+#else
+    for (i=0; i<NLEN; i++)
+#endif
+    {
+        f[i]^=(f[i]^g[i])&b;
+    }
+}
+
+/* Move g to f if d=1 */
+void BIG_dcmove(DBIG f,DBIG g,int d)
+{
+    int i;
+    chunk b=(chunk)-d;
+#ifdef DEBUG_NORM
+    for (i=0; i<=DNLEN; i++)
+#else
+    for (i=0; i<DNLEN; i++)
+#endif
+    {
+        f[i]^=(f[i]^g[i])&b;
+    }
+}
+
+/* convert BIG to/from bytes */
+/* SU= 64 */
+void BIG_toBytes(char *b,BIG a)
+{
+    int i;
+    BIG c;
+    BIG_norm(a);
+    BIG_copy(c,a);
+    for (i=MODBYTES-1; i>=0; i--)
+    {
+        b[i]=c[0]&0xff;
+        BIG_fshr(c,8);
+    }
+}
+
+/* SU= 16 */
+void BIG_fromBytes(BIG a,char *b)
+{
+    int i;
+    BIG_zero(a);
+    for (i=0; i<MODBYTES; i++)
+    {
+        BIG_fshl(a,8);
+        a[0]+=(int)(unsigned char)b[i];
+        //BIG_inc(a,(int)(unsigned char)b[i]); BIG_norm(a);
+    }
+#ifdef DEBUG_NORM
+    a[NLEN]=0;
+#endif
+}
+
+void BIG_fromBytesLen(BIG a,char *b,int s)
+{
+    int i,len=s;
+    BIG_zero(a);
+
+    if (s>MODBYTES) s=MODBYTES;
+    for (i=0; i<len; i++)
+    {
+        BIG_fshl(a,8);
+        a[0]+=(int)(unsigned char)b[i];
+    }
+#ifdef DEBUG_NORM
+    a[NLEN]=0;
+#endif
+}
+
+
+
+/* SU= 88 */
+void BIG_doutput(DBIG a)
+{
+    DBIG b;
+    int i,len;
+    BIG_dnorm(a);
+    len=BIG_dnbits(a);
+    if (len%4==0) len/=4;
+    else
+    {
+        len/=4;
+        len++;
+    }
+
+    for (i=len-1; i>=0; i--)
+    {
+        BIG_dcopy(b,a);
+        BIG_dshr(b,i*4);
+        printf("%01x",(unsigned int) b[0]&15);
+    }
+}
+
+/* Copy b=a */
+void BIG_copy(BIG b,BIG a)
+{
+    int i;
+    for (i=0; i<NLEN; i++)
+        b[i]=a[i];
+#ifdef DEBUG_NORM
+    b[NLEN]=a[NLEN];
+#endif
+}
+
+/* Copy from ROM b=a */
+void BIG_rcopy(BIG b,const BIG a)
+{
+    int i;
+    for (i=0; i<NLEN; i++)
+        b[i]=a[i];
+#ifdef DEBUG_NORM
+    b[NLEN]=0;
+#endif
+}
+
+/* double length DBIG copy b=a */
+void BIG_dcopy(DBIG b,DBIG a)
+{
+    int i;
+    for (i=0; i<DNLEN; i++)
+        b[i]=a[i];
+#ifdef DEBUG_NORM
+    b[DNLEN]=a[DNLEN];
+#endif
+}
+
+/* Copy BIG to bottom half of DBIG */
+void BIG_dscopy(DBIG b,BIG a)
+{
+    int i;
+    for (i=0; i<NLEN-1; i++)
+        b[i]=a[i];
+
+    b[NLEN-1]=a[NLEN-1]&BMASK; /* top word normalized */
+    b[NLEN]=a[NLEN-1]>>BASEBITS;
+
+    for (i=NLEN+1; i<DNLEN; i++) b[i]=0;
+#ifdef DEBUG_NORM
+    b[DNLEN]=a[NLEN];
+#endif
+}
+
+/* Copy BIG to top half of DBIG */
+void BIG_dsucopy(DBIG b,BIG a)
+{
+    int i;
+    for (i=0; i<NLEN; i++)
+        b[i]=0;
+    for (i=NLEN; i<DNLEN; i++)
+        b[i]=a[i-NLEN];
+#ifdef DEBUG_NORM
+    b[DNLEN]=a[NLEN];
+#endif
+}
+
+/* Copy bottom half of DBIG to BIG */
+void BIG_sdcopy(BIG b,DBIG a)
+{
+    int i;
+    for (i=0; i<NLEN; i++)
+        b[i]=a[i];
+#ifdef DEBUG_NORM
+    b[NLEN]=a[DNLEN];
+#endif
+}
+
+/* Copy top half of DBIG to BIG */
+void BIG_sducopy(BIG b,DBIG a)
+{
+    int i;
+    for (i=0; i<NLEN; i++)
+        b[i]=a[i+NLEN];
+#ifdef DEBUG_NORM
+    b[NLEN]=a[DNLEN];
+#endif
+}
+
+/* Set a=0 */
+void BIG_zero(BIG a)
+{
+    int i;
+    for (i=0; i<NLEN; i++)
+        a[i]=0;
+#ifdef DEBUG_NORM
+    a[NLEN]=0;
+#endif
+}
+
+void BIG_dzero(DBIG a)
+{
+    int i;
+    for (i=0; i<DNLEN; i++)
+        a[i]=0;
+#ifdef DEBUG_NORM
+    a[DNLEN]=0;
+#endif
+}
+
+/* set a=1 */
+void BIG_one(BIG a)
+{
+    int i;
+    a[0]=1;
+    for (i=1; i<NLEN; i++)
+        a[i]=0;
+#ifdef DEBUG_NORM
+    a[NLEN]=0;
+#endif
+}
+
+
+
+/* Set c=a+b */
+/* SU= 8 */
+void BIG_add(BIG c,BIG a,BIG b)
+{
+    int i;
+    for (i=0; i<NLEN; i++)
+        c[i]=a[i]+b[i];
+#ifdef DEBUG_NORM
+    c[NLEN]=a[NLEN]+b[NLEN]+1;
+    if (c[NLEN]>=NEXCESS) printf("add problem - digit overflow %d\n",c[NLEN]);
+#endif
+}
+
+/* Set c=c+d */
+void BIG_inc(BIG c,int d)
+{
+    BIG_norm(c);
+    c[0]+=(chunk)d;
+#ifdef DEBUG_NORM
+    c[NLEN]=1;
+#endif
+}
+
+/* Set c=a-b */
+/* SU= 8 */
+void BIG_sub(BIG c,BIG a,BIG b)
+{
+    int i;
+    for (i=0; i<NLEN; i++)
+        c[i]=a[i]-b[i];
+#ifdef DEBUG_NORM
+    c[NLEN]=a[NLEN]+b[NLEN]+1;
+    if (c[NLEN]>=NEXCESS) printf("sub problem - digit overflow %d\n",c[NLEN]);
+#endif
+}
+
+/* SU= 8 */
+
+void BIG_dsub(DBIG c,DBIG a,DBIG b)
+{
+    int i;
+    for (i=0; i<DNLEN; i++)
+        c[i]=a[i]-b[i];
+#ifdef DEBUG_NORM
+    c[DNLEN]=a[DNLEN]+b[DNLEN]+1;
+    if (c[DNLEN]>=NEXCESS) printf("sub problem - digit overflow %d\n",c[DNLEN]);
+#endif
+}
+
+
+/* Set c=c-1 */
+void BIG_dec(BIG c,int d)
+{
+    BIG_norm(c);
+    c[0]-=(chunk)d;
+#ifdef DEBUG_NORM
+    c[NLEN]=1;
+#endif
+}
+
+/* multiplication r=a*c by c<=NEXCESS */
+void BIG_imul(BIG r,BIG a,int c)
+{
+    int i;
+    for (i=0; i<NLEN; i++) r[i]=a[i]*c;
+#ifdef DEBUG_NORM
+    r[NLEN]=(a[NLEN]+1)*c-1;
+    if (r[NLEN]>=NEXCESS) printf("int mul problem - digit overflow %d\n",r[NLEN]);
+#endif
+}
+
+/* multiplication r=a*c by larger integer - c<=FEXCESS */
+/* SU= 24 */
+chunk BIG_pmul(BIG r,BIG a,int c)
+{
+    int i;
+    chunk ak,carry=0;
+    BIG_norm(a);
+    for (i=0; i<NLEN; i++)
+    {
+        ak=a[i];
+        r[i]=0;
+        carry=muladd(ak,(chunk)c,carry,&r[i]);
+    }
+#ifdef DEBUG_NORM
+    r[NLEN]=0;
+#endif
+    return carry;
+}
+
+/* r/=3 */
+/* SU= 16 */
+int BIG_div3(BIG r)
+{
+    int i;
+    chunk ak,base,carry=0;
+    BIG_norm(r);
+    base=((chunk)1<<BASEBITS);
+    for (i=NLEN-1; i>=0; i--)
+    {
+        ak=(carry*base+r[i]);
+        r[i]=ak/3;
+        carry=ak%3;
+    }
+    return (int)carry;
+}
+
+/* multiplication c=a*b by even larger integer b>FEXCESS, resulting in DBIG */
+/* SU= 24 */
+void BIG_pxmul(DBIG c,BIG a,int b)
+{
+    int j;
+    chunk carry;
+    BIG_dzero(c);
+    carry=0;
+    for (j=0; j<NLEN; j++)
+        carry=muladd(a[j],(chunk)b,carry,&c[j]);
+    c[NLEN]=carry;
+#ifdef DEBUG_NORM
+    c[DNLEN]=0;
+#endif
+}
+
+/* .. if you know the result will fit in a BIG, c must be distinct from a and b */
+/* SU= 40 */
+void BIG_smul(BIG c,BIG a,BIG b)
+{
+    int i,j;
+    chunk carry;
+    BIG_norm(a);
+    BIG_norm(b);
+
+    BIG_zero(c);
+    for (i=0; i<NLEN; i++)
+    {
+        carry=0;
+        for (j=0; j<NLEN; j++)
+        {
+            if (i+j<NLEN)
+                carry=muladd(a[i],b[j],carry,&c[i+j]);
+        }
+    }
+#ifdef DEBUG_NORM
+    c[NLEN]=0;
+#endif
+}
+
+/* Set c=a*b */
+/* SU= 72 */
+void BIG_mul(DBIG c,BIG a,BIG b)
+{
+    int i;
+#ifdef dchunk
+    dchunk t,co;
+    dchunk s;
+    dchunk d[NLEN];
+    int k;
+#endif
+
+    /* change here - a and b MUST be normed on input */
+
+//	BIG_norm(a);  /* needed here to prevent overflow from addition of partial products */
+//	BIG_norm(b);
+
+    /* Faster to Combafy it.. Let the compiler unroll the loops! */
+
+#ifdef COMBA
+
+    /* faster psuedo-Karatsuba method */
+#ifdef UNWOUND
+
+    /* Insert output of faster.c here */
+
+#else
+    for (i=0; i<NLEN; i++)
+        d[i]=(dchunk)a[i]*b[i];
+
+    s=d[0];
+    t=s;
+    c[0]=(chunk)t&BMASK;
+    co=t>>BASEBITS;
+
+    for (k=1; k<NLEN; k++)
+    {
+        s+=d[k];
+        t=co+s;
+        for (i=k; i>=1+k/2; i--) t+=(dchunk)(a[i]-a[k-i])*(b[k-i]-b[i]);
+        c[k]=(chunk)t&BMASK;
+        co=t>>BASEBITS;
+    }
+    for (k=NLEN; k<2*NLEN-1; k++)
+    {
+        s-=d[k-NLEN];
+        t=co+s;
+        for (i=NLEN-1; i>=1+k/2; i--) t+=(dchunk)(a[i]-a[k-i])*(b[k-i]-b[i]);
+        c[k]=(chunk)t&BMASK;
+        co=t>>BASEBITS;
+    }
+    c[2*NLEN-1]=(chunk)co;
+
+#endif
+
+#else
+    int j;
+    chunk carry;
+    BIG_dzero(c);
+    for (i=0; i<NLEN; i++)
+    {
+        carry=0;
+        for (j=0; j<NLEN; j++)
+            carry=muladd(a[i],b[j],carry,&c[i+j]);
+
+        c[NLEN+i]=carry;
+    }
+
+#endif
+
+#ifdef DEBUG_NORM
+    c[DNLEN]=0;
+#endif
+}
+
+/* Set c=a*a */
+/* SU= 80 */
+void BIG_sqr(DBIG c,BIG a)
+{
+    int i,j,last;
+#ifdef dchunk
+    dchunk t,co;
+#endif
+
+    /* change here - a MUST be normed on input */
+//	BIG_norm(a);
+
+    /* Note 2*a[i] in loop below and extra addition */
+
+#ifdef COMBA
+
+#ifdef UNWOUND
+
+    /* Insert output of faster.c here */
+
+#else
+
+    t=(dchunk)a[0]*a[0];
+    c[0]=(chunk)t&BMASK;
+    co=t>>BASEBITS;
+    t=(dchunk)a[1]*a[0];
+    t+=t;
+    t+=co;
+    c[1]=(chunk)t&BMASK;
+    co=t>>BASEBITS;
+
+    last=NLEN-NLEN%2;
+    for (j=2; j<last; j+=2)
+    {
+        t=(dchunk)a[j]*a[0];
+        for (i=1; i<(j+1)/2; i++) t+=(dchunk)a[j-i]*a[i];
+        t+=t;
+        t+=co;
+        t+=(dchunk)a[j/2]*a[j/2];
+        c[j]=(chunk)t&BMASK;
+        co=t>>BASEBITS;
+        t=(dchunk)a[j+1]*a[0];
+        for (i=1; i<(j+2)/2; i++) t+=(dchunk)a[j+1-i]*a[i];
+        t+=t;
+        t+=co;
+        c[j+1]=(chunk)t&BMASK;
+        co=t>>BASEBITS;
+    }
+    j=last;
+#if NLEN%2==1
+    t=(dchunk)a[j]*a[0];
+    for (i=1; i<(j+1)/2; i++) t+=(dchunk)a[j-i]*a[i];
+    t+=t;
+    t+=co;
+    t+=(dchunk)a[j/2]*a[j/2];
+    c[j]=(chunk)t&BMASK;
+    co=t>>BASEBITS;
+    j++;
+    t=(dchunk)a[NLEN-1]*a[j-NLEN+1];
+    for (i=j-NLEN+2; i<(j+1)/2; i++) t+=(dchunk)a[j-i]*a[i];
+    t+=t;
+    t+=co;
+    c[j]=(chunk)t&BMASK;
+    co=t>>BASEBITS;
+    j++;
+#endif
+    for (; j<DNLEN-2; j+=2)
+    {
+        t=(dchunk)a[NLEN-1]*a[j-NLEN+1];
+        for (i=j-NLEN+2; i<(j+1)/2; i++) t+=(dchunk)a[j-i]*a[i];
+        t+=t;
+        t+=co;
+        t+=(dchunk)a[j/2]*a[j/2];
+        c[j]=(chunk)t&BMASK;
+        co=t>>BASEBITS;
+        t=(dchunk)a[NLEN-1]*a[j-NLEN+2];
+        for (i=j-NLEN+3; i<(j+2)/2; i++) t+=(dchunk)a[j+1-i]*a[i];
+        t+=t;
+        t+=co;
+        c[j+1]=(chunk)t&BMASK;
+        co=t>>BASEBITS;
+    }
+
+    t=(dchunk)a[NLEN-1]*a[NLEN-1]+co;
+    c[DNLEN-2]=(chunk)t&BMASK;
+    co=t>>BASEBITS;
+    c[DNLEN-1]=(chunk)co;
+#endif
+
+#else
+    chunk carry;
+    BIG_dzero(c);
+    for (i=0; i<NLEN; i++)
+    {
+        carry=0;
+        for (j=i+1; j<NLEN; j++)
+            carry=muladd(a[i],a[j],carry,&c[i+j]);
+        c[NLEN+i]=carry;
+    }
+
+    for (i=0; i<DNLEN; i++) c[i]*=2;
+
+    for (i=0; i<NLEN; i++)
+        c[2*i+1]+=muladd(a[i],a[i],0,&c[2*i]);
+
+    BIG_dnorm(c);
+#endif
+
+
+#ifdef DEBUG_NORM
+    c[DNLEN]=0;
+#endif
+
+}
+
+/* Montgomery reduction */
+void BIG_monty(BIG a,BIG md,chunk MC,DBIG d)
+{
+    int i,k;
+
+#ifdef dchunk
+    dchunk t,c,s;
+    dchunk dd[NLEN];
+    chunk v[NLEN];
+#endif
+
+#ifdef COMBA
+
+#ifdef UNWOUND
+
+    /* Insert output of faster.c here */
+
+#else
+
+    t=d[0];
+    v[0]=((chunk)t*MC)&BMASK;
+    t+=(dchunk)v[0]*md[0];
+    c=(t>>BASEBITS)+d[1];
+    s=0;
+
+    for (k=1; k<NLEN; k++)
+    {
+        t=c+s+(dchunk)v[0]*md[k];
+        for (i=k-1; i>k/2; i--) t+=(dchunk)(v[k-i]-v[i])*(md[i]-md[k-i]);
+        v[k]=((chunk)t*MC)&BMASK;
+        t+=(dchunk)v[k]*md[0];
+        c=(t>>BASEBITS)+d[k+1];
+        dd[k]=(dchunk)v[k]*md[k];
+        s+=dd[k];
+    }
+    for (k=NLEN; k<2*NLEN-1; k++)
+    {
+        t=c+s;
+        for (i=NLEN-1; i>=1+k/2; i--) t+=(dchunk)(v[k-i]-v[i])*(md[i]-md[k-i]);
+        a[k-NLEN]=(chunk)t&BMASK;
+        c=(t>>BASEBITS)+d[k+1];
+        s-=dd[k-NLEN+1];
+    }
+    a[NLEN-1]=(chunk)c&BMASK;
+
+#endif
+
+#ifdef DEBUG_NORM
+    a[NLEN]=0;
+#endif
+
+#else
+    int j;
+    chunk m,carry;
+    for (i=0; i<NLEN; i++)
+    {
+        if (MC==-1) m=(-d[i])&BMASK;
+        else
+        {
+            if (MC==1) m=d[i];
+            else m=(MC*d[i])&BMASK;
+        }
+        carry=0;
+        for (j=0; j<NLEN; j++)
+            carry=muladd(m,md[j],carry,&d[i+j]);
+        d[NLEN+i]+=carry;
+    }
+    BIG_sducopy(a,d);
+    BIG_norm(a);
+
+#endif
+}
+
+/* General shift left of a by n bits */
+/* a MUST be normalised */
+/* SU= 32 */
+void BIG_shl(BIG a,int k)
+{
+    int i;
+    int n=k%BASEBITS;
+    int m=k/BASEBITS;
+
+//	a[NLEN-1]=((a[NLEN-1-m]<<n))|(a[NLEN-m-2]>>(BASEBITS-n));
+
+    a[NLEN-1]=((a[NLEN-1-m]<<n));
+    if (NLEN>=m+2) a[NLEN-1]|=(a[NLEN-m-2]>>(BASEBITS-n));
+
+    for (i=NLEN-2; i>m; i--)
+        a[i]=((a[i-m]<<n)&BMASK)|(a[i-m-1]>>(BASEBITS-n));
+    a[m]=(a[0]<<n)&BMASK;
+    for (i=0; i<m; i++) a[i]=0;
+
+}
+
+/* Fast shift left of a by n bits, where n less than a word, Return excess (but store it as well) */
+/* a MUST be normalised */
+/* SU= 16 */
+int BIG_fshl(BIG a,int n)
+{
+    int i;
+
+    a[NLEN-1]=((a[NLEN-1]<<n))|(a[NLEN-2]>>(BASEBITS-n)); /* top word not masked */
+    for (i=NLEN-2; i>0; i--)
+        a[i]=((a[i]<<n)&BMASK)|(a[i-1]>>(BASEBITS-n));
+    a[0]=(a[0]<<n)&BMASK;
+
+    return (int)(a[NLEN-1]>>((8*MODBYTES)%BASEBITS)); /* return excess - only used in ff.c */
+}
+
+/* double length left shift of a by k bits - k can be > BASEBITS , a MUST be normalised */
+/* SU= 32 */
+void BIG_dshl(DBIG a,int k)
+{
+    int i;
+    int n=k%BASEBITS;
+    int m=k/BASEBITS;
+
+    a[DNLEN-1]=((a[DNLEN-1-m]<<n))|(a[DNLEN-m-2]>>(BASEBITS-n));
+
+    for (i=DNLEN-2; i>m; i--)
+        a[i]=((a[i-m]<<n)&BMASK)|(a[i-m-1]>>(BASEBITS-n));
+    a[m]=(a[0]<<n)&BMASK;
+    for (i=0; i<m; i++) a[i]=0;
+
+}
+
+/* General shift rightof a by k bits */
+/* a MUST be normalised */
+/* SU= 32 */
+void BIG_shr(BIG a,int k)
+{
+    int i;
+    int n=k%BASEBITS;
+    int m=k/BASEBITS;
+    for (i=0; i<NLEN-m-1; i++)
+        a[i]=(a[m+i]>>n)|((a[m+i+1]<<(BASEBITS-n))&BMASK);
+    if (NLEN>m)  a[NLEN-m-1]=a[NLEN-1]>>n;
+    for (i=NLEN-m; i<NLEN; i++) a[i]=0;
+
+}
+
+/* Faster shift right of a by k bits. Return shifted out part */
+/* a MUST be normalised */
+/* SU= 16 */
+int BIG_fshr(BIG a,int k)
+{
+    int i;
+    chunk r=a[0]&(((chunk)1<<k)-1); /* shifted out part */
+    for (i=0; i<NLEN-1; i++)
+        a[i]=(a[i]>>k)|((a[i+1]<<(BASEBITS-k))&BMASK);
+    a[NLEN-1]=a[NLEN-1]>>k;
+    return (int)r;
+}
+
+/* double length right shift of a by k bits - can be > BASEBITS */
+/* SU= 32 */
+void BIG_dshr(DBIG a,int k)
+{
+    int i;
+    int n=k%BASEBITS;
+    int m=k/BASEBITS;
+    for (i=0; i<DNLEN-m-1; i++)
+        a[i]=(a[m+i]>>n)|((a[m+i+1]<<(BASEBITS-n))&BMASK);
+    a[DNLEN-m-1]=a[DNLEN-1]>>n;
+    for (i=DNLEN-m; i<DNLEN; i++ ) a[i]=0;
+}
+
+/* Split DBIG d into two BIGs t|b. Split happens at n bits, where n falls into NLEN word */
+/* d MUST be normalised */
+/* SU= 24 */
+chunk BIG_split(BIG t,BIG b,DBIG d,int n)
+{
+    int i;
+    chunk nw,carry=0;
+    int m=n%BASEBITS;
+//	BIG_dnorm(d);
+
+    if (m==0)
+    {
+        for (i=0; i<NLEN; i++) b[i]=d[i];
+        if (t!=b)
+        {
+            for (i=NLEN; i<2*NLEN; i++) t[i-NLEN]=d[i];
+            carry=t[NLEN-1]>>BASEBITS;
+            t[NLEN-1]=t[NLEN-1]&BMASK; /* top word normalized */
+        }
+        return carry;
+    }
+
+    for (i=0; i<NLEN-1; i++) b[i]=d[i];
+
+    b[NLEN-1]=d[NLEN-1]&(((chunk)1<<m)-1);
+
+    if (t!=b)
+    {
+        carry=(d[DNLEN-1]<<(BASEBITS-m));
+        for (i=DNLEN-2; i>=NLEN-1; i--)
+        {
+            nw=(d[i]>>m)|carry;
+            carry=(d[i]<<(BASEBITS-m))&BMASK;
+            t[i-NLEN+1]=nw;
+        }
+    }
+#ifdef DEBUG_NORM
+    t[NLEN]=0;
+    b[NLEN]=0;
+#endif
+    return carry;
+}
+
+/* you gotta keep the sign of carry! Look - no branching! */
+/* Note that sign bit is needed to disambiguate between +ve and -ve values */
+/* normalise BIG - force all digits < 2^BASEBITS */
+chunk BIG_norm(BIG a)
+{
+    int i;
+    chunk d,carry=0;
+    for (i=0; i<NLEN-1; i++)
+    {
+        d=a[i]+carry;
+        a[i]=d&BMASK;
+        carry=d>>BASEBITS;
+    }
+    a[NLEN-1]=(a[NLEN-1]+carry);
+
+#ifdef DEBUG_NORM
+    a[NLEN]=0;
+#endif
+    return (a[NLEN-1]>>((8*MODBYTES)%BASEBITS));  /* only used in ff.c */
+}
+
+void BIG_dnorm(DBIG a)
+{
+    int i;
+    chunk d,carry=0;
+    for (i=0; i<DNLEN-1; i++)
+    {
+        d=a[i]+carry;
+        a[i]=d&BMASK;
+        carry=d>>BASEBITS;
+    }
+    a[DNLEN-1]=(a[DNLEN-1]+carry);
+#ifdef DEBUG_NORM
+    a[DNLEN]=0;
+#endif
+}
+
+/* Compare a and b. Return 1 for a>b, -1 for a<b, 0 for a==b */
+/* a and b MUST be normalised before call */
+int BIG_comp(BIG a,BIG b)
+{
+    int i;
+    for (i=NLEN-1; i>=0; i--)
+    {
+        if (a[i]==b[i]) continue;
+        if (a[i]>b[i]) return 1;
+        else  return -1;
+    }
+    return 0;
+}
+
+int BIG_dcomp(DBIG a,DBIG b)
+{
+    int i;
+    for (i=DNLEN-1; i>=0; i--)
+    {
+        if (a[i]==b[i]) continue;
+        if (a[i]>b[i]) return 1;
+        else  return -1;
+    }
+    return 0;
+}
+
+/* return number of bits in a */
+/* SU= 8 */
+int BIG_nbits(BIG a)
+{
+    int bts,k=NLEN-1;
+    chunk c;
+    BIG_norm(a);
+    while (k>=0 && a[k]==0) k--;
+    if (k<0) return 0;
+    bts=BASEBITS*k;
+    c=a[k];
+    while (c!=0)
+    {
+        c/=2;
+        bts++;
+    }
+    return bts;
+}
+
+/* SU= 8, Calculate number of bits in a DBIG - output normalised */
+int BIG_dnbits(DBIG a)
+{
+    int bts,k=DNLEN-1;
+    chunk c;
+    BIG_dnorm(a);
+    while (k>=0 && a[k]==0) k--;
+    if (k<0) return 0;
+    bts=BASEBITS*k;
+    c=a[k];
+    while (c!=0)
+    {
+        c/=2;
+        bts++;
+    }
+    return bts;
+}
+
+
+/* Set b=b mod c */
+/* SU= 16 */
+void BIG_mod(BIG b,BIG c)
+{
+    int k=0;
+    BIG r; /**/
+
+    BIG_norm(b);
+    if (BIG_comp(b,c)<0)
+        return;
+    do
+    {
+        BIG_fshl(c,1);
+        k++;
+    }
+    while (BIG_comp(b,c)>=0);
+
+    while (k>0)
+    {
+        BIG_fshr(c,1);
+
+// constant time...
+        BIG_sub(r,b,c);
+        BIG_norm(r);
+        BIG_cmove(b,r,1-((r[NLEN-1]>>(CHUNK-1))&1));
+        /*
+                if (BIG_comp(b,c)>=0)
+                {
+                    BIG_sub(b,b,c);
+                    BIG_norm(b);
+                }
+        */
+        k--;
+    }
+}
+
+/* Set a=b mod c, b is destroyed. Slow but rarely used. */
+/* SU= 96 */
+void BIG_dmod(BIG a,DBIG b,BIG c)
+{
+    int k=0;
+    DBIG m,r;
+    BIG_dnorm(b);
+    BIG_dscopy(m,c);
+
+    if (BIG_dcomp(b,m)<0)
+    {
+        BIG_sdcopy(a,b);
+        return;
+    }
+
+    do
+    {
+        BIG_dshl(m,1);
+        k++;
+    }
+    while (BIG_dcomp(b,m)>=0);
+
+    while (k>0)
+    {
+        BIG_dshr(m,1);
+// constant time...
+        BIG_dsub(r,b,m);
+        BIG_dnorm(r);
+        BIG_dcmove(b,r,1-((r[DNLEN-1]>>(CHUNK-1))&1));
+        /*
+                if (BIG_dcomp(b,m)>=0)
+                {
+                    BIG_dsub(b,b,m);
+                    BIG_dnorm(b);
+                }
+        */
+        k--;
+    }
+    BIG_sdcopy(a,b);
+}
+
+/* Set a=b/c,  b is destroyed. Slow but rarely used. */
+/* SU= 136 */
+
+void BIG_ddiv(BIG a,DBIG b,BIG c)
+{
+    int d,k=0;
+    DBIG m,dr;
+    BIG e,r;
+    BIG_dnorm(b);
+    BIG_dscopy(m,c);
+
+    BIG_zero(a);
+    BIG_zero(e);
+    BIG_inc(e,1);
+
+    while (BIG_dcomp(b,m)>=0)
+    {
+        BIG_fshl(e,1);
+        BIG_dshl(m,1);
+        k++;
+    }
+
+    while (k>0)
+    {
+        BIG_dshr(m,1);
+        BIG_fshr(e,1);
+
+        BIG_dsub(dr,b,m);
+        BIG_dnorm(dr);
+        d=1-((dr[DNLEN-1]>>(CHUNK-1))&1);
+        BIG_dcmove(b,dr,d);
+
+        BIG_add(r,a,e);
+        BIG_norm(r);
+        BIG_cmove(a,r,d);
+        /*
+        		if (BIG_dcomp(b,m)>=0)
+        		{
+        			BIG_add(a,a,e);
+        			BIG_norm(a);
+        			BIG_dsub(b,b,m);
+        			BIG_dnorm(b);
+        		} */
+        k--;
+    }
+}
+
+/* SU= 136 */
+
+void BIG_sdiv(BIG a,BIG c)
+{
+    int d,k=0;
+    BIG m,e,b,r;
+    BIG_norm(a);
+    BIG_copy(b,a);
+    BIG_copy(m,c);
+
+    BIG_zero(a);
+    BIG_zero(e);
+    BIG_inc(e,1);
+
+    while (BIG_comp(b,m)>=0)
+    {
+        BIG_fshl(e,1);
+        BIG_fshl(m,1);
+        k++;
+    }
+
+    while (k>0)
+    {
+        BIG_fshr(m,1);
+        BIG_fshr(e,1);
+
+        BIG_sub(r,b,m);
+        BIG_norm(r);
+        d=1-((r[NLEN-1]>>(CHUNK-1))&1);
+        BIG_cmove(b,r,d);
+
+        BIG_add(r,a,e);
+        BIG_norm(r);
+        BIG_cmove(a,r,d);
+        /*
+        		if (BIG_comp(b,m)>=0)
+        		{
+        			BIG_sub(b,b,m);
+        			BIG_norm(b);
+        			BIG_add(a,a,e);
+        			BIG_norm(a);
+        		} */
+        k--;
+    }
+}
+
+/* return LSB of a */
+int BIG_parity(BIG a)
+{
+    return a[0]%2;
+}
+
+/* return n-th bit of a */
+/* SU= 16 */
+int BIG_bit(BIG a,int n)
+{
+    if (a[n/BASEBITS]&((chunk)1<<(n%BASEBITS))) return 1;
+    else return 0;
+}
+
+/* return NAF value as +/- 1, 3 or 5. x and x3 should be normed.
+nbs is number of bits processed, and nzs is number of trailing 0s detected */
+/* SU= 32 */
+/*
+int BIG_nafbits(BIG x,BIG x3,int i,int *nbs,int *nzs)
+{
+	int j,r,nb;
+
+	nb=BIG_bit(x3,i)-BIG_bit(x,i);
+	*nbs=1;
+	*nzs=0;
+	if (nb==0) return 0;
+	if (i==0) return nb;
+
+    if (nb>0) r=1;
+    else      r=(-1);
+
+    for (j=i-1;j>0;j--)
+    {
+        (*nbs)++;
+        r*=2;
+        nb=BIG_bit(x3,j)-BIG_bit(x,j);
+        if (nb>0) r+=1;
+        if (nb<0) r-=1;
+        if (abs(r)>5) break;
+    }
+
+	if (r%2!=0 && j!=0)
+    { // backtrack
+        if (nb>0) r=(r-1)/2;
+        if (nb<0) r=(r+1)/2;
+        (*nbs)--;
+    }
+
+    while (r%2==0)
+    { // remove trailing zeros
+        r/=2;
+        (*nzs)++;
+        (*nbs)--;
+    }
+    return r;
+}
+*/
+
+/* return last n bits of a, where n is small < BASEBITS */
+/* SU= 16 */
+int BIG_lastbits(BIG a,int n)
+{
+    int msk=(1<<n)-1;
+    BIG_norm(a);
+    return ((int)a[0])&msk;
+}
+
+/* get 8*MODBYTES size random number */
+void BIG_random(BIG m,csprng *rng)
+{
+    int i,b,j=0,r=0;
+    int len=8*MODBYTES;
+
+    BIG_zero(m);
+    /* generate random BIG */
+    for (i=0; i<len; i++)
+    {
+        if (j==0) r=RAND_byte(rng);
+        else r>>=1;
+        b=r&1;
+        BIG_shl(m,1);
+        m[0]+=b;
+        j++;
+        j&=7;
+    }
+
+#ifdef DEBUG_NORM
+    m[NLEN]=0;
+#endif
+}
+
+/* get random BIG from rng, modulo q. Done one bit at a time, so its portable */
+
+void BIG_randomnum(BIG m,BIG q,csprng *rng)
+{
+    int i,b,j=0,r=0;
+    DBIG d;
+    BIG_dzero(d);
+    /* generate random DBIG */
+    for (i=0; i<2*MODBITS; i++)
+    {
+        if (j==0) r=RAND_byte(rng);
+        else r>>=1;
+        b=r&1;
+        BIG_dshl(d,1);
+        d[0]+=b;
+        j++;
+        j&=7;
+    }
+    /* reduce modulo a BIG. Removes bias */
+    BIG_dmod(m,d,q);
+#ifdef DEBUG_NORM
+    m[NLEN]=0;
+#endif
+}
+
+/* Set r=a*b mod m */
+/* SU= 96 */
+void BIG_modmul(BIG r,BIG a,BIG b,BIG m)
+{
+    DBIG d;
+    BIG_mod(a,m);
+    BIG_mod(b,m);
+//BIG_norm(a); BIG_norm(b);
+    BIG_mul(d,a,b);
+    BIG_dmod(r,d,m);
+}
+
+/* Set a=a*a mod m */
+/* SU= 88 */
+void BIG_modsqr(BIG r,BIG a,BIG m)
+{
+    DBIG d;
+    BIG_mod(a,m);
+//BIG_norm(a);
+    BIG_sqr(d,a);
+    BIG_dmod(r,d,m);
+}
+
+/* Set r=-a mod m */
+/* SU= 16 */
+void BIG_modneg(BIG r,BIG a,BIG m)
+{
+    BIG_mod(a,m);
+    BIG_sub(r,m,a);
+    BIG_mod(r,m);
+}
+
+/* Set a=a/b mod m */
+/* SU= 136 */
+void BIG_moddiv(BIG r,BIG a,BIG b,BIG m)
+{
+    DBIG d;
+    BIG z;
+    BIG_mod(a,m);
+    BIG_invmodp(z,b,m);
+//BIG_norm(a); BIG_norm(z);
+    BIG_mul(d,a,z);
+    BIG_dmod(r,d,m);
+}
+
+/* Get jacobi Symbol (a/p). Returns 0, 1 or -1 */
+/* SU= 216 */
+int BIG_jacobi(BIG a,BIG p)
+{
+    int n8,k,m=0;
+    BIG t,x,n,zilch,one;
+    BIG_one(one);
+    BIG_zero(zilch);
+    if (BIG_parity(p)==0 || BIG_comp(a,zilch)==0 || BIG_comp(p,one)<=0) return 0;
+    BIG_norm(a);
+    BIG_copy(x,a);
+    BIG_copy(n,p);
+    BIG_mod(x,p);
+
+    while (BIG_comp(n,one)>0)
+    {
+        if (BIG_comp(x,zilch)==0) return 0;
+        n8=BIG_lastbits(n,3);
+        k=0;
+        while (BIG_parity(x)==0)
+        {
+            k++;
+            BIG_shr(x,1);
+        }
+        if (k%2==1) m+=(n8*n8-1)/8;
+        m+=(n8-1)*(BIG_lastbits(x,2)-1)/4;
+        BIG_copy(t,n);
+
+        BIG_mod(t,x);
+        BIG_copy(n,x);
+        BIG_copy(x,t);
+        m%=2;
+
+    }
+    if (m==0) return 1;
+    else return -1;
+}
+
+/* Set r=1/a mod p. Binary method */
+/* SU= 240 */
+void BIG_invmodp(BIG r,BIG a,BIG p)
+{
+    BIG u,v,x1,x2,t,one;
+    BIG_mod(a,p);
+    BIG_copy(u,a);
+    BIG_copy(v,p);
+    BIG_one(one);
+    BIG_copy(x1,one);
+    BIG_zero(x2);
+
+    while (BIG_comp(u,one)!=0 && BIG_comp(v,one)!=0)
+    {
+        while (BIG_parity(u)==0)
+        {
+            BIG_shr(u,1);
+            if (BIG_parity(x1)!=0)
+            {
+                BIG_add(x1,p,x1);
+                BIG_norm(x1);
+            }
+            BIG_shr(x1,1);
+        }
+        while (BIG_parity(v)==0)
+        {
+            BIG_shr(v,1);
+            if (BIG_parity(x2)!=0)
+            {
+                BIG_add(x2,p,x2);
+                BIG_norm(x2);
+            }
+            BIG_shr(x2,1);
+        }
+        if (BIG_comp(u,v)>=0)
+        {
+            BIG_sub(u,u,v);
+            BIG_norm(u);
+            if (BIG_comp(x1,x2)>=0) BIG_sub(x1,x1,x2);
+            else
+            {
+                BIG_sub(t,p,x2);
+                BIG_add(x1,x1,t);
+            }
+            BIG_norm(x1);
+        }
+        else
+        {
+            BIG_sub(v,v,u);
+            BIG_norm(v);
+            if (BIG_comp(x2,x1)>=0) BIG_sub(x2,x2,x1);
+            else
+            {
+                BIG_sub(t,p,x1);
+                BIG_add(x2,x2,t);
+            }
+            BIG_norm(x2);
+        }
+    }
+    if (BIG_comp(u,one)==0)
+        BIG_copy(r,x1);
+    else
+        BIG_copy(r,x2);
+}
+
+/* set x = x mod 2^m */
+void BIG_mod2m(BIG x,int m)
+{
+    int i,wd,bt;
+    chunk msk;
+//	if (m>=MODBITS) return;
+    wd=m/BASEBITS;
+    bt=m%BASEBITS;
+    msk=((chunk)1<<bt)-1;
+    x[wd]&=msk;
+    for (i=wd+1; i<NLEN; i++) x[i]=0;
+}
+
+// new
+/* Convert to DBIG number from byte array of given length */
+void BIG_dfromBytesLen(DBIG a,char *b,int s)
+{
+    int i,len=s;
+    BIG_dzero(a);
+
+    for (i=0; i<len; i++)
+    {
+        BIG_dshl(a,8);
+        a[0]+=(int)(unsigned char)b[i];
+    }
+#ifdef DEBUG_NORM
+    a[NLEN]=0;
+#endif
+}
diff --git a/version22/c/build_ec b/version22/c/build_ec
new file mode 100644
index 0000000..b5dc735
--- /dev/null
+++ b/version22/c/build_ec
@@ -0,0 +1,22 @@
+
+gcc -std=c99 -c -O3 big.c
+gcc -std=c99 -c -O3 fp.c
+gcc -std=c99 -c -O3 ecp.c
+gcc -std=c99 -c -O3 hash.c
+gcc -std=c99 -c -O3 rand.c
+gcc -std=c99 -c -O3 aes.c
+gcc -std=c99 -c -O3 gcm.c
+gcc -std=c99 -c -O3 oct.c
+gcc -std=c99 -c -O3 rom.c
+
+gcc -std=c99 -c -O3 ff.c
+
+rm amcl.a
+ar rc amcl.a big.o fp.o ecp.o hash.o ff.o
+ar r amcl.a rand.o aes.o gcm.o oct.o rom.o
+
+gcc -std=c99 -O3 testecdh.c ecdh.c randapi.c amcl.a -o testecdh
+gcc -std=c99 -O3 testrsa.c rsa.c randapi.c amcl.a -o testrsa
+gcc -std=c99 -O3 benchtest_ec.c rsa.c amcl.a -o benchtest_ec
+
+rm *.o
diff --git a/version22/c/build_ec.bat b/version22/c/build_ec.bat
new file mode 100644
index 0000000..a49fc25
--- /dev/null
+++ b/version22/c/build_ec.bat
@@ -0,0 +1,22 @@
+
+gcc -std=c99 -c -O3 big.c
+gcc -std=c99 -c -O3 fp.c
+gcc -std=c99 -c -O3 ecp.c
+gcc -std=c99 -c -O3 hash.c
+gcc -std=c99 -c -O3 rand.c
+gcc -std=c99 -c -O3 aes.c
+gcc -std=c99 -c -O3 gcm.c
+gcc -std=c99 -c -O3 oct.c
+gcc -std=c99 -c -O3 rom.c
+
+gcc -std=c99 -c -O3 ff.c
+
+del amcl.a
+ar rc amcl.a big.o fp.o ecp.o hash.o ff.o
+ar r amcl.a rand.o aes.o gcm.o oct.o rom.o
+
+gcc -std=c99 -O3 testecdh.c ecdh.c randapi.c amcl.a -o testecdh.exe
+gcc -std=c99 -O3 testrsa.c rsa.c randapi.c amcl.a -o testrsa.exe
+gcc -std=c99 -O3 benchtest_ec.c rsa.c amcl.a -o benchtest_ec.exe
+
+del *.o
diff --git a/version22/c/build_pair b/version22/c/build_pair
new file mode 100644
index 0000000..6b6bae2
--- /dev/null
+++ b/version22/c/build_pair
@@ -0,0 +1,27 @@
+
+gcc -std=c99 -c -O3 big.c
+gcc -std=c99 -c -O3 fp.c
+gcc -std=c99 -c -O3 ecp.c
+gcc -std=c99 -c -O3 hash.c
+gcc -std=c99 -c -O3 rand.c
+gcc -std=c99 -c -O3 aes.c
+gcc -std=c99 -c -O3 gcm.c
+gcc -std=c99 -c -O3 oct.c
+gcc -std=c99 -c -O3 rom.c
+
+gcc -std=c99 -c -O3 fp2.c
+gcc -std=c99 -c -O3 ecp2.c
+gcc -std=c99 -c -O3 fp4.c
+gcc -std=c99 -c -O3 fp12.c
+gcc -std=c99 -c -O3 pair.c
+
+rm amcl.a
+ar rc amcl.a big.o fp.o ecp.o hash.o
+ar r amcl.a rand.o aes.o gcm.o oct.o rom.o
+
+ar r amcl.a pair.o fp2.o ecp2.o fp4.o fp12.o
+
+gcc -std=c99 -O3 testmpin.c mpin.c randapi.c amcl.a -o testmpin
+gcc -std=c99 -O3 benchtest_pair.c amcl.a -o benchtest_pair
+
+rm *.o
diff --git a/version22/c/build_pair.bat b/version22/c/build_pair.bat
new file mode 100644
index 0000000..88b5daf
--- /dev/null
+++ b/version22/c/build_pair.bat
@@ -0,0 +1,27 @@
+
+gcc -std=c99 -c -O3 big.c
+gcc -std=c99 -c -O3 fp.c
+gcc -std=c99 -c -O3 ecp.c
+gcc -std=c99 -c -O3 hash.c
+gcc -std=c99 -c -O3 rand.c
+gcc -std=c99 -c -O3 aes.c
+gcc -std=c99 -c -O3 gcm.c
+gcc -std=c99 -c -O3 oct.c
+gcc -std=c99 -c -O3 rom.c
+
+gcc -std=c99 -c -O3 fp2.c
+gcc -std=c99 -c -O3 ecp2.c
+gcc -std=c99 -c -O3 fp4.c
+gcc -std=c99 -c -O3 fp12.c
+gcc -std=c99 -c -O3 pair.c
+
+del amcl.a
+ar rc amcl.a big.o fp.o ecp.o hash.o
+ar r amcl.a rand.o aes.o gcm.o oct.o rom.o
+
+ar r amcl.a pair.o fp2.o ecp2.o fp4.o fp12.o
+
+gcc -std=c99 -O3 testmpin.c mpin.c randapi.c amcl.a -o testmpin.exe
+gcc -std=c99 -O3 benchtest_pair.c amcl.a -o benchtest_pair.exe
+
+del *.o
diff --git a/version22/c/ca.crt b/version22/c/ca.crt
new file mode 100644
index 0000000..e3ad02f
--- /dev/null
+++ b/version22/c/ca.crt
@@ -0,0 +1,23 @@
+-----BEGIN CERTIFICATE-----
+MIID6zCCAtOgAwIBAgIJALJxywTGMUA7MA0GCSqGSIb3DQEBCwUAMIGLMQswCQYD
+VQQGEwJJRTEQMA4GA1UECAwHSXJlbGFuZDEPMA0GA1UEBwwGRHVibGluMQ8wDQYD
+VQQKDAZNSVJBQ0wxDTALBgNVBAsMBGxhYnMxEzARBgNVBAMMCk1pa2UgU2NvdHQx
+JDAiBgkqhkiG9w0BCQEWFW1pa2Uuc2NvdHRAbWlyYWNsLmNvbTAeFw0xNjA2MzAx
+NzQyNDFaFw0yMTA2MzAxNzQyNDFaMIGLMQswCQYDVQQGEwJJRTEQMA4GA1UECAwH
+SXJlbGFuZDEPMA0GA1UEBwwGRHVibGluMQ8wDQYDVQQKDAZNSVJBQ0wxDTALBgNV
+BAsMBGxhYnMxEzARBgNVBAMMCk1pa2UgU2NvdHQxJDAiBgkqhkiG9w0BCQEWFW1p
+a2Uuc2NvdHRAbWlyYWNsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAPCTPcPWgiI0ka5Czd0ZzW+gTaMEe9QW7FGu5+9fS6ALrCpdbxdwDX8+OQXZ
+uQJpLYEAIq1pDh3fVQguH/jUM9gQQrS2Lmz3KhXC/J3yv85FRotCGv13ztapMedT
+y2IxzbtPvoQQc+IAlUPX6DtD8JqBoAstrlQUnkMChKztMGR2OERdjNzXmXm+KMMP
+lZzk+EvRwCornVA+SB5QAWj7y/3ISFo0y1WG8ewoQEx3HQYrjXbQP1VTdiLW7dHP
+QP86XKoTMtTBEYWuFhKB9ClCeu4Qqqxqa9UPIVfdro7SoZScCt+OX4KhzLnOCFup
+oLxE+yTDhDpYcCcmI1yglCv9DpMCAwEAAaNQME4wHQYDVR0OBBYEFFH18YEMoxms
+7121N/nQ+Wm3b5smMB8GA1UdIwQYMBaAFFH18YEMoxms7121N/nQ+Wm3b5smMAwG
+A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBALCUob0y2O4DSzsqG76yrtCx
+XWxDdgjSkHKzwFK62BzZK5EuCDJrVgCyoLX0SvYvoT9x0wtS+bxJ7TNEGn7Rkp5/
+iSQCUSF7sVRoHqzErk70xVKKDy5FS+zre8k08nJrtRg2u1PmY95NO1SE96BtUVLs
++8rQuqEX283tqlmqE/SF2+lxOb0WaVrya4oCJfj/XT83pRTcd5w9i7huWltMbKba
+gkmlQ/5q9Ayp/Jh1lLXmxr+/xEbZ2xEop/y+mgVF0vLxap7R5toBA0Yk7vvirlYv
+0hZGqGi5lBc9VeUqm1H/7XCi5xRU3AtJ4QRk4Z1xUa4qAPKfiqlPKd1dVe3Ah3w=
+-----END CERTIFICATE-----
diff --git a/version22/c/eccert.pem b/version22/c/eccert.pem
new file mode 100644
index 0000000..b9dfca5
--- /dev/null
+++ b/version22/c/eccert.pem
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICqjCCAZICCQCk9jKdJYtnjDANBgkqhkiG9w0BAQsFADCBizELMAkGA1UEBhMC
+SUUxEDAOBgNVBAgMB0lyZWxhbmQxDzANBgNVBAcMBkR1YmxpbjEPMA0GA1UECgwG
+TUlSQUNMMQ0wCwYDVQQLDARsYWJzMRMwEQYDVQQDDApNaWtlIFNjb3R0MSQwIgYJ
+KoZIhvcNAQkBFhVtaWtlLnNjb3R0QG1pcmFjbC5jb20wHhcNMTYwNjMwMTc0NjQ4
+WhcNMTYwNzMwMTc0NjQ4WjCBjDELMAkGA1UEBhMCSUUxEDAOBgNVBAgMB0lyZWxh
+bmQxDzANBgNVBAcMBkR1YmxpbjEPMA0GA1UECgwGTUlSQUNMMQ0wCwYDVQQLDARs
+YWJzMRgwFgYDVQQDDA9LZWFsYW4gTWNDdXNrZXIxIDAeBgkqhkiG9w0BCQEWEWtl
+YWxhbkBtaXJhY2wuY29tMDkwFAYHKoZIzj0CAQYJKwYBBAHaRw8BAyEASiRQmhO9
+PP+SqodOhXYrnSlcyAOog63E6a4KLDFvAzEwDQYJKoZIhvcNAQELBQADggEBALBy
+fCM/EhdqWBrEnDHtH2/U8xr1eSylHdcfnDSDR+X6KXH5rIJ/397lZQMHB6QSsEiV
+rWzfFDFPPjDN3xEDsZw09ZTT+L8Wi5P3UKR1gtawQCx3ciKEywAU1CU2dV05gvye
+bqIsbFUyH7jOlj6/1hIx9zaiLcoEex6D55MYQuWo664HF3CNdJFk1k4HF+fclRhy
+l4iryp0F9p0Wl5vyn96kg0NwaBZG860oCWDHZsjRq1JeSSaRf9CKNXWbQwjByeEc
+DphpprqmoVcI60cC0TvZZm1x4y7vjCXLD6uCDw3P7fnSp40yce64+IKUr8/cS+QY
+us58KHdLaLXsojZHL3c=
+-----END CERTIFICATE-----
diff --git a/version22/c/ecdh.c b/version22/c/ecdh.c
new file mode 100644
index 0000000..74694f7
--- /dev/null
+++ b/version22/c/ecdh.c
@@ -0,0 +1,751 @@
+/*
+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.
+*/
+
+/* ECDH/ECIES/ECDSA Functions - see main program below */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "ecdh.h"
+
+#define ROUNDUP(a,b) ((a)-1)/(b)+1
+
+/* general purpose hash function w=hash(p|n|x|y) */
+/* pad or truncate ouput to length pad if pad!=0 */
+static void hashit(int sha,octet *p,int n,octet *x,octet *w,int pad)
+{
+    int i,c[4],hlen;
+    hash256 sha256;
+    hash512 sha512;
+    char hh[64];
+
+    switch (sha)
+    {
+    case SHA256:
+        HASH256_init(&sha256);
+        break;
+    case SHA384:
+        HASH384_init(&sha512);
+        break;
+    case SHA512:
+        HASH512_init(&sha512);
+        break;
+    }
+
+    hlen=sha;
+
+    for (i=0; i<p->len; i++)
+    {
+        switch(sha)
+        {
+        case SHA256:
+            HASH256_process(&sha256,p->val[i]);
+            break;
+        case SHA384:
+            HASH384_process(&sha512,p->val[i]);
+            break;
+        case SHA512:
+            HASH512_process(&sha512,p->val[i]);
+            break;
+        }
+    }
+    if (n>0)
+    {
+        c[0]=(n>>24)&0xff;
+        c[1]=(n>>16)&0xff;
+        c[2]=(n>>8)&0xff;
+        c[3]=(n)&0xff;
+        for (i=0; i<4; i++)
+        {
+            switch(sha)
+            {
+            case SHA256:
+                HASH256_process(&sha256,c[i]);
+                break;
+            case SHA384:
+                HASH384_process(&sha512,c[i]);
+                break;
+            case SHA512:
+                HASH512_process(&sha512,c[i]);
+                break;
+            }
+        }
+    }
+    if (x!=NULL) for (i=0; i<x->len; i++)
+        {
+            switch(sha)
+            {
+            case SHA256:
+                HASH256_process(&sha256,x->val[i]);
+                break;
+            case SHA384:
+                HASH384_process(&sha512,x->val[i]);
+                break;
+            case SHA512:
+                HASH512_process(&sha512,x->val[i]);
+                break;
+            }
+        }
+
+    switch (sha)
+    {
+    case SHA256:
+        HASH256_hash(&sha256,hh);
+        break;
+    case SHA384:
+        HASH384_hash(&sha512,hh);
+        break;
+    case SHA512:
+        HASH512_hash(&sha512,hh);
+        break;
+    }
+
+    OCT_empty(w);
+    if (!pad)
+        OCT_jbytes(w,hh,hlen);
+    else
+    {
+        if (pad<=hlen)
+            OCT_jbytes(w,hh,pad);
+        else
+        {
+            OCT_jbytes(w,hh,hlen);
+            OCT_jbyte(w,0,pad-hlen);
+        }
+    }
+    return;
+}
+
+/* Hash octet p to octet w */
+void HASH(int sha,octet *p,octet *w)
+{
+    hashit(sha,p,-1,NULL,w,0);
+}
+
+/* Calculate HMAC of m using key k. HMAC is tag of length olen */
+int HMAC(int sha,octet *m,octet *k,int olen,octet *tag)
+{
+    /* Input is from an octet m        *
+     * olen is requested output length in bytes. k is the key  *
+     * The output is the calculated tag */
+    int hlen,b;
+    char h[128],k0[128];
+    octet H= {0,sizeof(h),h};
+    octet K0= {0,sizeof(k0),k0};
+
+    hlen=sha;
+    if (hlen>32) b=128;
+    else b=64;
+
+    if (olen<4 /*|| olen>hlen*/) return 0;
+
+    if (k->len > b) hashit(sha,k,-1,NULL,&K0,0);
+    else            OCT_copy(&K0,k);
+
+    OCT_jbyte(&K0,0,b-K0.len);
+
+    OCT_xorbyte(&K0,0x36);
+
+    hashit(sha,&K0,-1,m,&H,0);
+
+    OCT_xorbyte(&K0,0x6a);   /* 0x6a = 0x36 ^ 0x5c */
+    hashit(sha,&K0,-1,&H,&H,olen);
+
+    OCT_empty(tag);
+
+    OCT_jbytes(tag,H.val,olen);
+
+    return 1;
+}
+
+/* Key Derivation Functions */
+/* Input octet z */
+/* Output key of length olen */
+/*
+void KDF1(octet *z,int olen,octet *key)
+{
+    char h[32];
+	octet H={0,sizeof(h),h};
+    int counter,cthreshold;
+    int hlen=32;
+
+    OCT_empty(key);
+
+    cthreshold=ROUNDUP(olen,hlen);
+
+    for (counter=0;counter<cthreshold;counter++)
+    {
+        hashit(z,counter,NULL,NULL,&H);
+        if (key->len+hlen>olen) OCT_jbytes(key,H.val,olen%hlen);
+        else                    OCT_joctet(key,&H);
+    }
+}
+*/
+void KDF2(int sha,octet *z,octet *p,int olen,octet *key)
+{
+    /* NOTE: the parameter olen is the length of the output k in bytes */
+    char h[64];
+    octet H= {0,sizeof(h),h};
+    int counter,cthreshold;
+    int hlen=sha;
+
+    OCT_empty(key);
+
+    cthreshold=ROUNDUP(olen,hlen);
+
+    for (counter=1; counter<=cthreshold; counter++)
+    {
+        hashit(sha,z,counter,p,&H,0);
+        if (key->len+hlen>olen)  OCT_jbytes(key,H.val,olen%hlen);
+        else                     OCT_joctet(key,&H);
+    }
+
+}
+
+/* Password based Key Derivation Function */
+/* Input password p, salt s, and repeat count */
+/* Output key of length olen */
+void PBKDF2(int sha,octet *p,octet *s,int rep,int olen,octet *key)
+{
+    int i,j,len,d=ROUNDUP(olen,sha);
+    char f[64],u[64];   /*****/
+    octet F= {0,sizeof(f),f};
+    octet U= {0,sizeof(u),u};
+    OCT_empty(key);
+
+    for (i=1; i<=d; i++)
+    {
+        len=s->len;
+        OCT_jint(s,i,4);
+
+        HMAC(sha,s,p,sha,&F);  /* sha not EFS */
+
+        s->len=len;
+        OCT_copy(&U,&F);
+        for (j=2; j<=rep; j++)
+        {
+            HMAC(sha,&U,p,sha,&U); /* sha not EFS */
+            OCT_xor(&F,&U);
+        }
+
+        OCT_joctet(key,&F);
+    }
+
+    OCT_chop(key,NULL,olen);
+}
+
+/* AES encryption/decryption. Encrypt byte array M using key K and returns ciphertext */
+void AES_CBC_IV0_ENCRYPT(octet *k,octet *m,octet *c)
+{
+    /* AES CBC encryption, with Null IV and key k */
+    /* Input is from an octet string m, output is to an octet string c */
+    /* Input is padded as necessary to make up a full final block */
+    amcl_aes a;
+    int fin;
+    int i,j,ipt,opt;
+    char buff[16];
+    int padlen;
+
+    OCT_clear(c);
+    if (m->len==0) return;
+    AES_init(&a,CBC,k->len,k->val,NULL);
+
+    ipt=opt=0;
+    fin=0;
+    for(;;)
+    {
+        for (i=0; i<16; i++)
+        {
+            if (ipt<m->len) buff[i]=m->val[ipt++];
+            else
+            {
+                fin=1;
+                break;
+            }
+        }
+        if (fin) break;
+        AES_encrypt(&a,buff);
+        for (i=0; i<16; i++)
+            if (opt<c->max) c->val[opt++]=buff[i];
+    }
+
+    /* last block, filled up to i-th index */
+
+    padlen=16-i;
+    for (j=i; j<16; j++) buff[j]=padlen;
+    AES_encrypt(&a,buff);
+    for (i=0; i<16; i++)
+        if (opt<c->max) c->val[opt++]=buff[i];
+    AES_end(&a);
+    c->len=opt;
+}
+
+/* decrypts and returns TRUE if all consistent, else returns FALSE */
+int AES_CBC_IV0_DECRYPT(octet *k,octet *c,octet *m)
+{
+    /* padding is removed */
+    amcl_aes a;
+    int i,ipt,opt,ch;
+    char buff[16];
+    int fin,bad;
+    int padlen;
+    ipt=opt=0;
+
+    OCT_clear(m);
+    if (c->len==0) return 1;
+    ch=c->val[ipt++];
+
+    AES_init(&a,CBC,k->len,k->val,NULL);
+    fin=0;
+
+    for(;;)
+    {
+        for (i=0; i<16; i++)
+        {
+            buff[i]=ch;
+            if (ipt>=c->len)
+            {
+                fin=1;
+                break;
+            }
+            else ch=c->val[ipt++];
+        }
+        AES_decrypt(&a,buff);
+        if (fin) break;
+        for (i=0; i<16; i++)
+            if (opt<m->max) m->val[opt++]=buff[i];
+    }
+    AES_end(&a);
+    bad=0;
+    padlen=buff[15];
+    if (i!=15 || padlen<1 || padlen>16) bad=1;
+    if (padlen>=2 && padlen<=16)
+        for (i=16-padlen; i<16; i++) if (buff[i]!=padlen) bad=1;
+
+    if (!bad) for (i=0; i<16-padlen; i++)
+            if (opt<m->max) m->val[opt++]=buff[i];
+
+    m->len=opt;
+    if (bad) return 0;
+    return 1;
+}
+
+/* Calculate a public/private EC GF(p) key pair. W=S.G mod EC(p),
+ * where S is the secret key and W is the public key
+ * and G is fixed generator.
+ * If RNG is NULL then the private key is provided externally in S
+ * otherwise it is generated randomly internally */
+int ECP_KEY_PAIR_GENERATE(csprng *RNG,octet* S,octet *W)
+{
+    BIG r,gx,s;
+    ECP G;
+    int res=0;
+    BIG_rcopy(gx,CURVE_Gx);
+
+#if CURVETYPE!=MONTGOMERY
+    BIG gy;
+    BIG_rcopy(gy,CURVE_Gy);
+    ECP_set(&G,gx,gy);
+#else
+    ECP_set(&G,gx);
+#endif
+
+    BIG_rcopy(r,CURVE_Order);
+    if (RNG!=NULL)
+    {
+        BIG_randomnum(s,r,RNG);
+    }
+    else
+    {
+        BIG_fromBytes(s,S->val);
+        BIG_mod(s,r);
+    }
+
+#ifdef AES_S
+    BIG_mod2m(s,2*AES_S);
+//	BIG_toBytes(S->val,s);
+#endif
+
+    ECP_mul(&G,s);
+#if CURVETYPE!=MONTGOMERY
+    ECP_get(gx,gy,&G);
+#else
+    ECP_get(gx,&G);
+    /*
+    	ECP_rhs(gy,gx);
+    	FP_sqrt(gy,gy);
+    	FP_neg(gy,gy);
+    	FP_inv(gy,gy);
+    	FP_mul(r,gx,gy);
+    	FP_reduce(r);
+
+        BIG_zero(gy);
+    	BIG_inc(gy,486664);
+    	FP_neg(gy,gy);
+    	FP_sqrt(gy,gy);
+    	FP_reduce(gy);
+    	FP_mul(r,r,gy);
+    	FP_reduce(r);
+
+    	printf("x= "); BIG_output(r); printf("\n");
+
+    	BIG_copy(r,gx);
+    	BIG_dec(r,1);
+    	BIG_copy(gy,gx);
+    	BIG_inc(gy,1);
+    	FP_inv(gy,gy);
+    	FP_mul(r,r,gy);
+    	FP_reduce(r);
+
+    	printf("y= "); BIG_output(r); printf("\n");
+
+    	BIG_zero(r);
+    	BIG_inc(r,121665);
+    	BIG_zero(gy);
+    	BIG_inc(gy,121666);
+    	FP_inv(gy,gy);
+    	FP_mul(r,r,gy);
+    	FP_neg(r,r);
+    	FP_reduce(r);
+
+    	printf("d= "); BIG_output(r); printf("\n");
+    */
+
+#endif
+
+    S->len=EGS;
+    BIG_toBytes(S->val,s);
+
+#if CURVETYPE!=MONTGOMERY
+    W->len=2*EFS+1;
+    W->val[0]=4;
+    BIG_toBytes(&(W->val[1]),gx);
+    BIG_toBytes(&(W->val[EFS+1]),gy);
+#else
+    W->len=EFS+1;
+    W->val[0]=2;
+    BIG_toBytes(&(W->val[1]),gx);
+#endif
+
+    return res;
+}
+
+/* validate public key. Set full=true for fuller check */
+int ECP_PUBLIC_KEY_VALIDATE(int full,octet *W)
+{
+    BIG q,r,wx;
+    ECP WP;
+    int valid;
+    int res=0;
+
+    BIG_rcopy(q,Modulus);
+    BIG_rcopy(r,CURVE_Order);
+
+    BIG_fromBytes(wx,&(W->val[1]));
+    if (BIG_comp(wx,q)>=0) res=ECDH_INVALID_PUBLIC_KEY;
+#if CURVETYPE!=MONTGOMERY
+    BIG wy;
+    BIG_fromBytes(wy,&(W->val[EFS+1]));
+    if (BIG_comp(wy,q)>=0) res=ECDH_INVALID_PUBLIC_KEY;
+#endif
+    if (res==0)
+    {
+
+#if CURVETYPE!=MONTGOMERY
+        valid=ECP_set(&WP,wx,wy);
+#else
+        valid=ECP_set(&WP,wx);
+#endif
+        if (!valid || ECP_isinf(&WP)) res=ECDH_INVALID_PUBLIC_KEY;
+        if (res==0 && full)
+        {
+
+            ECP_mul(&WP,r);
+            if (!ECP_isinf(&WP)) res=ECDH_INVALID_PUBLIC_KEY;
+        }
+    }
+
+    return res;
+}
+
+/* IEEE-1363 Diffie-Hellman online calculation Z=S.WD */
+int ECPSVDP_DH(octet *S,octet *WD,octet *Z)
+{
+    BIG r,s,wx;
+    int valid;
+    ECP W;
+    int res=0;
+
+    BIG_fromBytes(s,S->val);
+
+    BIG_fromBytes(wx,&(WD->val[1]));
+#if CURVETYPE!=MONTGOMERY
+    BIG wy;
+    BIG_fromBytes(wy,&(WD->val[EFS+1]));
+    valid=ECP_set(&W,wx,wy);
+#else
+    valid=ECP_set(&W,wx);
+#endif
+    if (!valid) res=ECDH_ERROR;
+    if (res==0)
+    {
+        BIG_rcopy(r,CURVE_Order);
+        BIG_mod(s,r);
+
+        ECP_mul(&W,s);
+        if (ECP_isinf(&W)) res=ECDH_ERROR;
+        else
+        {
+#if CURVETYPE!=MONTGOMERY
+            ECP_get(wx,wx,&W);
+#else
+            ECP_get(wx,&W);
+#endif
+            Z->len=MODBYTES;
+            BIG_toBytes(Z->val,wx);
+        }
+    }
+    return res;
+}
+
+#if CURVETYPE!=MONTGOMERY
+
+/* IEEE ECDSA Signature, C and D are signature on F using private key S */
+int ECPSP_DSA(int sha,csprng *RNG,octet *K,octet *S,octet *F,octet *C,octet *D)
+{
+    char h[128];
+    octet H= {0,sizeof(h),h};
+
+    BIG gx,gy,r,s,f,c,d,u,vx,w;
+    ECP G,V;
+
+    hashit(sha,F,-1,NULL,&H,sha);
+    BIG_rcopy(gx,CURVE_Gx);
+    BIG_rcopy(gy,CURVE_Gy);
+    BIG_rcopy(r,CURVE_Order);
+
+    BIG_fromBytes(s,S->val);
+
+    int hlen=H.len;
+    if (H.len>MODBYTES) hlen=MODBYTES;
+    BIG_fromBytesLen(f,H.val,hlen);
+
+    ECP_set(&G,gx,gy);
+
+    do
+    {
+        if (RNG!=NULL)
+        {
+            BIG_randomnum(u,r,RNG);
+            BIG_randomnum(w,r,RNG); /* randomize calculation */
+        }
+        else
+        {
+            BIG_fromBytes(u,K->val);
+            BIG_mod(u,r);
+        }
+
+#ifdef AES_S
+        BIG_mod2m(u,2*AES_S);
+#endif
+        ECP_copy(&V,&G);
+        ECP_mul(&V,u);
+
+        ECP_get(vx,vx,&V);
+
+        BIG_copy(c,vx);
+        BIG_mod(c,r);
+        if (BIG_iszilch(c)) continue;
+        if (RNG!=NULL)
+        {
+            BIG_modmul(u,u,w,r);
+        }
+
+        BIG_invmodp(u,u,r);
+        BIG_modmul(d,s,c,r);
+
+        BIG_add(d,f,d);
+        if (RNG!=NULL)
+        {
+            BIG_modmul(d,d,w,r);
+        }
+
+        BIG_modmul(d,u,d,r);
+
+    }
+    while (BIG_iszilch(d));
+
+    C->len=D->len=EGS;
+
+    BIG_toBytes(C->val,c);
+    BIG_toBytes(D->val,d);
+
+    return 0;
+}
+
+/* IEEE1363 ECDSA Signature Verification. Signature C and D on F is verified using public key W */
+int ECPVP_DSA(int sha,octet *W,octet *F, octet *C,octet *D)
+{
+    char h[128];
+    octet H= {0,sizeof(h),h};
+
+    BIG r,gx,gy,wx,wy,f,c,d,h2;
+    int res=0;
+    ECP G,WP;
+    int valid;
+
+    hashit(sha,F,-1,NULL,&H,sha);
+    BIG_rcopy(gx,CURVE_Gx);
+    BIG_rcopy(gy,CURVE_Gy);
+    BIG_rcopy(r,CURVE_Order);
+
+    OCT_shl(C,C->len-MODBYTES);
+    OCT_shl(D,D->len-MODBYTES);
+
+    BIG_fromBytes(c,C->val);
+    BIG_fromBytes(d,D->val);
+
+    int hlen=H.len;
+    if (hlen>MODBYTES) hlen=MODBYTES;
+
+    BIG_fromBytesLen(f,H.val,hlen);
+
+    //BIG_fromBytes(f,H.val);
+
+    if (BIG_iszilch(c) || BIG_comp(c,r)>=0 || BIG_iszilch(d) || BIG_comp(d,r)>=0)
+        res=ECDH_INVALID;
+
+    if (res==0)
+    {
+        BIG_invmodp(d,d,r);
+        BIG_modmul(f,f,d,r);
+        BIG_modmul(h2,c,d,r);
+
+        ECP_set(&G,gx,gy);
+
+        BIG_fromBytes(wx,&(W->val[1]));
+        BIG_fromBytes(wy,&(W->val[EFS+1]));
+
+        valid=ECP_set(&WP,wx,wy);
+
+        if (!valid) res=ECDH_ERROR;
+        else
+        {
+            ECP_mul2(&WP,&G,h2,f);
+
+            if (ECP_isinf(&WP)) res=ECDH_INVALID;
+            else
+            {
+                ECP_get(d,d,&WP);
+                BIG_mod(d,r);
+                if (BIG_comp(d,c)!=0) res=ECDH_INVALID;
+            }
+        }
+    }
+
+    return res;
+}
+
+/* IEEE1363 ECIES encryption. Encryption of plaintext M uses public key W and produces ciphertext V,C,T */
+void ECP_ECIES_ENCRYPT(int sha,octet *P1,octet *P2,csprng *RNG,octet *W,octet *M,int tlen,octet *V,octet *C,octet *T)
+{
+
+    int i,len;
+    char z[EFS],vz[3*EFS+1],k[2*EAS],k1[EAS],k2[EAS],l2[8],u[EFS];
+    octet Z= {0,sizeof(z),z};
+    octet VZ= {0,sizeof(vz),vz};
+    octet K= {0,sizeof(k),k};
+    octet K1= {0,sizeof(k1),k1};
+    octet K2= {0,sizeof(k2),k2};
+    octet L2= {0,sizeof(l2),l2};
+    octet U= {0,sizeof(u),u};
+
+    if (ECP_KEY_PAIR_GENERATE(RNG,&U,V)!=0) return;
+    if (ECPSVDP_DH(&U,W,&Z)!=0) return;
+
+    OCT_copy(&VZ,V);
+    OCT_joctet(&VZ,&Z);
+
+    KDF2(sha,&VZ,P1,2*EAS,&K);
+
+    K1.len=K2.len=EAS;
+    for (i=0; i<EAS; i++)
+    {
+        K1.val[i]=K.val[i];
+        K2.val[i]=K.val[EAS+i];
+    }
+
+    AES_CBC_IV0_ENCRYPT(&K1,M,C);
+
+    OCT_jint(&L2,P2->len,8);
+
+    len=C->len;
+    OCT_joctet(C,P2);
+    OCT_joctet(C,&L2);
+    HMAC(sha,C,&K2,tlen,T);
+    C->len=len;
+}
+
+/* IEEE1363 ECIES decryption. Decryption of ciphertext V,C,T using private key U outputs plaintext M */
+int ECP_ECIES_DECRYPT(int sha,octet *P1,octet *P2,octet *V,octet *C,octet *T,octet *U,octet *M)
+{
+
+    int i,len;
+    char z[EFS],vz[3*EFS+1],k[2*EAS],k1[EAS],k2[EAS],l2[8],tag[32];
+    octet Z= {0,sizeof(z),z};
+    octet VZ= {0,sizeof(vz),vz};
+    octet K= {0,sizeof(k),k};
+    octet K1= {0,sizeof(k1),k1};
+    octet K2= {0,sizeof(k2),k2};
+    octet L2= {0,sizeof(l2),l2};
+    octet TAG= {0,sizeof(tag),tag};
+
+    if (ECPSVDP_DH(U,V,&Z)!=0) return 0;
+
+    OCT_copy(&VZ,V);
+    OCT_joctet(&VZ,&Z);
+
+    KDF2(sha,&VZ,P1,EFS,&K);
+
+    K1.len=K2.len=EAS;
+    for (i=0; i<EAS; i++)
+    {
+        K1.val[i]=K.val[i];
+        K2.val[i]=K.val[EAS+i];
+    }
+
+    if (!AES_CBC_IV0_DECRYPT(&K1,C,M)) return 0;
+
+    OCT_jint(&L2,P2->len,8);
+
+    len=C->len;
+    OCT_joctet(C,P2);
+    OCT_joctet(C,&L2);
+    HMAC(sha,C,&K2,T->len,&TAG);
+    C->len=len;
+
+    if (!OCT_comp(T,&TAG)) return 0;
+
+    return 1;
+
+}
+
+#endif
diff --git a/version22/c/ecdh.h b/version22/c/ecdh.h
new file mode 100644
index 0000000..7d0536b
--- /dev/null
+++ b/version22/c/ecdh.h
@@ -0,0 +1,206 @@
+/*
+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.
+*/
+
+/**
+ * @file ecdh.h
+ * @author Mike Scott and Kealan McCusker
+ * @date 2nd June 2015
+ * @brief ECDH Header file for implementation of standard EC protocols
+ *
+ * declares functions
+ *
+ */
+
+#ifndef ECDH_H
+#define ECDH_H
+
+#include "amcl.h"
+
+#define EAS 16 /**< Symmetric Key size - 128 bits */
+#define EGS MODBYTES  /**< ECC Group Size in bytes */
+#define EFS MODBYTES  /**< ECC Field Size in bytes */
+
+#define HASH_TYPE_ECC SHA256  /**< Hash type */
+
+#define ECDH_OK                     0     /**< Function completed without error */
+/*#define ECDH_DOMAIN_ERROR          -1*/
+#define ECDH_INVALID_PUBLIC_KEY    -2	/**< Public Key is Invalid */
+#define ECDH_ERROR                 -3	/**< ECDH Internal Error */
+#define ECDH_INVALID               -4	/**< ECDH Internal Error */
+/*#define ECDH_DOMAIN_NOT_FOUND      -5
+#define ECDH_OUT_OF_MEMORY         -6
+#define ECDH_DIV_BY_ZERO           -7
+#define ECDH_BAD_ASSUMPTION        -8*/
+
+/* ECDH Auxiliary Functions */
+
+
+/**	@brief hash an octet into another octet
+ *
+ 	@param h is the hash type
+	@param I input octet
+	@param O output octet - H(I)
+ */
+extern void HASH(int h,octet *I,octet *O);
+/**	@brief HMAC of message M using key K to create tag of length len in octet tag
+ *
+	IEEE-1363 MAC1 function. Uses SHA256 internally.
+	@param h is the hash type
+	@param M input message octet
+	@param K input encryption key
+	@param len is output desired length of HMAC tag
+	@param tag is the output HMAC
+	@return 0 for bad parameters, else 1
+ */
+extern int HMAC(int h,octet *M,octet *K,int len,octet *tag);
+
+/*extern void KDF1(octet *,int,octet *);*/
+
+/**	@brief Key Derivation Function - generates key K from inputs Z and P
+ *
+	IEEE-1363 KDF2 Key Derivation Function. Uses SHA256 internally.
+	@param h is the hash type
+	@param Z input octet
+	@param P input key derivation parameters - can be NULL
+	@param len is output desired length of key
+	@param K is the derived key
+ */
+extern void KDF2(int h,octet *Z,octet *P,int len,octet *K);
+/**	@brief Password Based Key Derivation Function - generates key K from password, salt and repeat counter
+ *
+	PBKDF2 Password Based Key Derivation Function. Uses SHA256 internally.
+	@param h is the hash type
+	@param P input password
+	@param S input salt
+	@param rep Number of times to be iterated.
+	@param len is output desired length
+	@param K is the derived key
+ */
+extern void PBKDF2(int h,octet *P,octet *S,int rep,int len,octet *K);
+/**	@brief AES encrypts a plaintext to a ciphtertext
+ *
+	IEEE-1363 AES_CBC_IV0_ENCRYPT function. Encrypts in CBC mode with a zero IV, padding as necessary to create a full final block.
+	@param K AES key
+	@param P input plaintext octet
+	@param C output ciphertext octet
+ */
+extern void AES_CBC_IV0_ENCRYPT(octet *K,octet *P,octet *C);
+/**	@brief AES encrypts a plaintext to a ciphtertext
+ *
+	IEEE-1363 AES_CBC_IV0_DECRYPT function. Decrypts in CBC mode with a zero IV.
+	@param K AES key
+	@param C input ciphertext octet
+	@param P output plaintext octet
+	@return 0 if bad input, else 1
+ */
+extern int AES_CBC_IV0_DECRYPT(octet *K,octet *C,octet *P);
+
+/* ECDH primitives - support functions */
+/**	@brief Generate an ECC public/private key pair
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param s the private key, an output internally randomly generated if R!=NULL, otherwise must be provided as an input
+	@param W the output public key, which is s.G, where G is a fixed generator
+	@return 0 or an error code
+ */
+extern int  ECP_KEY_PAIR_GENERATE(csprng *R,octet *s,octet *W);
+/**	@brief Validate an ECC public key
+ *
+	@param f if = 0 just does some simple checks, else tests that W is of the correct order
+	@param W the input public key to be validated
+	@return 0 if public key is OK, or an error code
+ */
+extern int  ECP_PUBLIC_KEY_VALIDATE(int f,octet *W);
+
+/* ECDH primitives */
+
+/**	@brief Generate Diffie-Hellman shared key
+ *
+	IEEE-1363 Diffie-Hellman shared secret calculation
+	@param s is the input private key,
+	@param W the input public key of the other party
+	@param K the output shared key, in fact the x-coordinate of s.W
+	@return 0 or an error code
+ */
+extern int ECPSVDP_DH(octet *s,octet *W,octet *K);
+/*extern int ECPSVDP_DHC(octet *,octet *,int,octet *);*/
+
+/*#if CURVETYPE!=MONTGOMERY */
+/* ECIES functions */
+/*#if CURVETYPE!=MONTGOMERY */
+/* ECIES functions */
+/**	@brief ECIES Encryption
+ *
+	IEEE-1363 ECIES Encryption
+	@param h is the hash type
+	@param P1 input Key Derivation parameters
+	@param P2 input Encoding parameters
+	@param R is a pointer to a cryptographically secure random number generator
+	@param W the input public key of the recieving party
+	@param M is the plaintext message to be encrypted
+	@param len the length of the HMAC tag
+	@param V component of the output ciphertext
+	@param C the output ciphertext
+	@param T the output HMAC tag, part of the ciphertext
+ */
+extern void ECP_ECIES_ENCRYPT(int h,octet *P1,octet *P2,csprng *R,octet *W,octet *M,int len,octet *V,octet *C,octet *T);
+/**	@brief ECIES Decryption
+ *
+	IEEE-1363 ECIES Decryption
+	@param h is the hash type
+	@param P1 input Key Derivation parameters
+	@param P2 input Encoding parameters
+	@param V component of the input ciphertext
+	@param C the input ciphertext
+	@param T the input HMAC tag, part of the ciphertext
+	@param U the input private key for decryption
+	@param M the output plaintext message
+	@return 1 if successful, else 0
+ */
+extern int ECP_ECIES_DECRYPT(int h,octet *P1,octet *P2,octet *V,octet *C,octet *T,octet *U,octet *M);
+
+/* ECDSA functions */
+/**	@brief ECDSA Signature
+ *
+	IEEE-1363 ECDSA Signature
+	@param h is the hash type
+	@param R is a pointer to a cryptographically secure random number generator
+        @param k Ephemeral key. This value is used when R=NULL
+	@param s the input private signing key
+	@param M the input message to be signed
+	@param c component of the output signature
+	@param d component of the output signature
+
+ */
+extern int ECPSP_DSA(int h,csprng *R,octet *k,octet *s,octet *M,octet *c,octet *d);
+/**	@brief ECDSA Signature Verification
+ *
+	IEEE-1363 ECDSA Signature Verification
+	@param h is the hash type
+	@param W the input public key
+	@param M the input message
+	@param c component of the input signature
+	@param d component of the input signature
+	@return 0 or an error code
+ */
+extern int ECPVP_DSA(int h,octet *W,octet *M,octet *c,octet *d);
+/*#endif*/
+
+#endif
+
diff --git a/version22/c/ecp.c b/version22/c/ecp.c
new file mode 100644
index 0000000..a6dcfad
--- /dev/null
+++ b/version22/c/ecp.c
@@ -0,0 +1,1176 @@
+/*
+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.
+*/
+
+/* AMCL Elliptic Curve Functions */
+/* SU=m, SU is Stack Usage (Weierstrass Curves) */
+
+//#define HAS_MAIN
+
+#include "amcl.h"
+
+/* test for P=O point-at-infinity */
+int ECP_isinf(ECP *P)
+{
+#if CURVETYPE==EDWARDS
+    FP_reduce(P->x);
+    FP_reduce(P->y);
+    FP_reduce(P->z);
+    return (BIG_iszilch(P->x) && BIG_comp(P->y,P->z)==0);
+#else
+    return P->inf;
+#endif
+}
+
+/* Conditional swap of P and Q dependant on d */
+static void ECP_cswap(ECP *P,ECP *Q,int d)
+{
+    BIG_cswap(P->x,Q->x,d);
+#if CURVETYPE!=MONTGOMERY
+    BIG_cswap(P->y,Q->y,d);
+#endif
+    BIG_cswap(P->z,Q->z,d);
+#if CURVETYPE!=EDWARDS
+    d=~(d-1);
+    d=d&(P->inf^Q->inf);
+    P->inf^=d;
+    Q->inf^=d;
+#endif
+}
+
+#if CURVETYPE!=MONTGOMERY
+/* Conditional move Q to P dependant on d */
+static void ECP_cmove(ECP *P,ECP *Q,int d)
+{
+    BIG_cmove(P->x,Q->x,d);
+#if CURVETYPE!=MONTGOMERY
+    BIG_cmove(P->y,Q->y,d);
+#endif
+    BIG_cmove(P->z,Q->z,d);
+#if CURVETYPE!=EDWARDS
+    d=~(d-1);
+    P->inf^=(P->inf^Q->inf)&d;
+#endif
+}
+
+/* return 1 if b==c, no branching */
+static int teq(sign32 b,sign32 c)
+{
+    sign32 x=b^c;
+    x-=1;  // if x=0, x now -1
+    return (int)((x>>31)&1);
+}
+#endif // CURVETYPE!=MONTGOMERY
+
+#if CURVETYPE!=MONTGOMERY
+/* Constant time select from pre-computed table */
+static void ECP_select(ECP *P,ECP W[],sign32 b)
+{
+    ECP MP;
+    sign32 m=b>>31;
+    sign32 babs=(b^m)-m;
+
+    babs=(babs-1)/2;
+
+    ECP_cmove(P,&W[0],teq(babs,0));  // conditional move
+    ECP_cmove(P,&W[1],teq(babs,1));
+    ECP_cmove(P,&W[2],teq(babs,2));
+    ECP_cmove(P,&W[3],teq(babs,3));
+    ECP_cmove(P,&W[4],teq(babs,4));
+    ECP_cmove(P,&W[5],teq(babs,5));
+    ECP_cmove(P,&W[6],teq(babs,6));
+    ECP_cmove(P,&W[7],teq(babs,7));
+
+    ECP_copy(&MP,P);
+    ECP_neg(&MP);  // minus P
+    ECP_cmove(P,&MP,(int)(m&1));
+}
+#endif
+
+/* Test P == Q */
+/* SU=168 */
+int ECP_equals(ECP *P,ECP *Q)
+{
+#if CURVETYPE==WEIERSTRASS
+    BIG pz2,qz2,a,b;
+    if (ECP_isinf(P) && ECP_isinf(Q)) return 1;
+    if (ECP_isinf(P) || ECP_isinf(Q)) return 0;
+
+    FP_sqr(pz2,P->z);
+    FP_sqr(qz2,Q->z);
+
+    FP_mul(a,P->x,qz2);
+    FP_mul(b,Q->x,pz2);
+    FP_reduce(a);
+    FP_reduce(b);
+    if (BIG_comp(a,b)!=0) return 0;
+
+    FP_mul(a,P->y,qz2);
+    FP_mul(a,a,Q->z);
+    FP_mul(b,Q->y,pz2);
+    FP_mul(b,b,P->z);
+    FP_reduce(a);
+    FP_reduce(b);
+    if (BIG_comp(a,b)!=0) return 0;
+    return 1;
+#else
+    BIG a,b;
+    if (ECP_isinf(P) && ECP_isinf(Q)) return 1;
+    if (ECP_isinf(P) || ECP_isinf(Q)) return 0;
+
+    FP_mul(a,P->x,Q->z);
+    FP_mul(b,Q->x,P->z);
+    FP_reduce(a);
+    FP_reduce(b);
+    if (BIG_comp(a,b)!=0) return 0;
+
+#if CURVETYPE==EDWARDS
+    FP_mul(a,P->y,Q->z);
+    FP_mul(b,Q->y,P->z);
+    FP_reduce(a);
+    FP_reduce(b);
+    if (BIG_comp(a,b)!=0) return 0;
+#endif
+
+    return 1;
+#endif
+}
+
+/* Set P=Q */
+/* SU=16 */
+void ECP_copy(ECP *P,ECP *Q)
+{
+#if CURVETYPE!=EDWARDS
+    P->inf=Q->inf;
+#endif
+    BIG_copy(P->x,Q->x);
+#if CURVETYPE!=MONTGOMERY
+    BIG_copy(P->y,Q->y);
+#endif
+    BIG_copy(P->z,Q->z);
+}
+
+/* Set P=-Q */
+#if CURVETYPE!=MONTGOMERY
+/* SU=8 */
+void ECP_neg(ECP *P)
+{
+    if (ECP_isinf(P)) return;
+#if CURVETYPE==WEIERSTRASS
+    FP_neg(P->y,P->y);
+    BIG_norm(P->y);
+#else
+    FP_neg(P->x,P->x);
+    BIG_norm(P->x);
+#endif
+
+}
+#endif
+
+/* Set P=O */
+void ECP_inf(ECP *P)
+{
+#if CURVETYPE==EDWARDS
+    BIG_zero(P->x);
+    FP_one(P->y);
+    FP_one(P->z);
+#else
+    P->inf=1;
+#endif
+}
+
+/* Calculate right Hand Side of curve equation y^2=RHS */
+/* SU=56 */
+void ECP_rhs(BIG v,BIG x)
+{
+#if CURVETYPE==WEIERSTRASS
+    /* x^3+Ax+B */
+    BIG t;
+    FP_sqr(t,x);
+    FP_mul(t,t,x);
+
+    if (CURVE_A==-3)
+    {
+        FP_neg(v,x);
+        BIG_norm(v);
+        BIG_imul(v,v,-CURVE_A);
+        BIG_norm(v);
+        FP_add(v,t,v);
+    }
+    else BIG_copy(v,t);
+
+    BIG_rcopy(t,CURVE_B);
+    FP_nres(t);
+    FP_add(v,t,v);
+    FP_reduce(v);
+#endif
+
+#if CURVETYPE==EDWARDS
+    /* (Ax^2-1)/(Bx^2-1) */
+    BIG t,m,one;
+    BIG_rcopy(m,Modulus);
+    FP_sqr(v,x);
+    FP_one(one);
+    BIG_rcopy(t,CURVE_B);
+    FP_nres(t);
+    FP_mul(t,v,t);
+    FP_sub(t,t,one);
+    if (CURVE_A==1) FP_sub(v,v,one);
+
+    if (CURVE_A==-1)
+    {
+        FP_add(v,v,one);
+        FP_neg(v,v);
+    }
+    FP_redc(v);
+    FP_redc(t);
+    BIG_moddiv(v,v,t,m);
+    FP_nres(v);
+#endif
+
+#if CURVETYPE==MONTGOMERY
+    /* x^3+Ax^2+x */
+    BIG x2,x3;
+    FP_sqr(x2,x);
+    FP_mul(x3,x2,x);
+    BIG_copy(v,x);
+    FP_imul(x2,x2,CURVE_A);
+    FP_add(v,v,x2);
+    FP_add(v,v,x3);
+    FP_reduce(v);
+#endif
+}
+
+/* Set P=(x,y) */
+
+#if CURVETYPE==MONTGOMERY
+
+/* Set P=(x,{y}) */
+
+int ECP_set(ECP *P,BIG x)
+{
+    BIG m,rhs;
+    BIG_rcopy(m,Modulus);
+    BIG_copy(rhs,x);
+    FP_nres(rhs);
+    ECP_rhs(rhs,rhs);
+    FP_redc(rhs);
+
+    if (BIG_jacobi(rhs,m)!=1)
+    {
+        ECP_inf(P);
+        return 0;
+    }
+    P->inf=0;
+    BIG_copy(P->x,x);
+    FP_nres(P->x);
+    FP_one(P->z);
+    return 1;
+}
+
+/* Extract x coordinate as BIG */
+int ECP_get(BIG x,ECP *P)
+{
+    if (ECP_isinf(P)) return -1;
+    ECP_affine(P);
+    BIG_copy(x,P->x);
+    FP_redc(x);
+    return 0;
+}
+
+
+#else
+/* Extract (x,y) and return sign of y. If x and y are the same return only x */
+/* SU=16 */
+int ECP_get(BIG x,BIG y,ECP *P)
+{
+    int s;
+#if CURVETYPE!=EDWARDS
+    if (ECP_isinf(P)) return -1;
+#endif
+    ECP_affine(P);
+
+    BIG_copy(y,P->y);
+    FP_redc(y);
+
+    s=BIG_parity(y);
+
+    BIG_copy(x,P->x);
+    FP_redc(x);
+
+    return s;
+}
+
+/* Set P=(x,{y}) */
+/* SU=96 */
+int ECP_set(ECP *P,BIG x,BIG y)
+{
+    BIG rhs,y2;
+    BIG_copy(y2,y);
+
+    FP_nres(y2);
+    FP_sqr(y2,y2);
+    FP_reduce(y2);
+
+
+
+    BIG_copy(rhs,x);
+    FP_nres(rhs);
+
+    ECP_rhs(rhs,rhs);
+
+    if (BIG_comp(y2,rhs)!=0)
+    {
+        ECP_inf(P);
+        return 0;
+    }
+#if CURVETYPE==WEIERSTRASS
+    P->inf=0;
+#endif
+    BIG_copy(P->x,x);
+    FP_nres(P->x);
+    BIG_copy(P->y,y);
+    FP_nres(P->y);
+    FP_one(P->z);
+    return 1;
+}
+
+/* Set P=(x,y), where y is calculated from x with sign s */
+/* SU=136 */
+int ECP_setx(ECP *P,BIG x,int s)
+{
+    BIG t,rhs,m;
+    BIG_rcopy(m,Modulus);
+
+    BIG_copy(rhs,x);
+    FP_nres(rhs);
+    ECP_rhs(rhs,rhs);
+    BIG_copy(t,rhs);
+    FP_redc(t);
+    if (BIG_jacobi(t,m)!=1)
+    {
+        ECP_inf(P);
+        return 0;
+    }
+#if CURVETYPE==WEIERSTRASS
+    P->inf=0;
+#endif
+    BIG_copy(P->x,x);
+    FP_nres(P->x);
+
+    FP_sqrt(P->y,rhs);
+    BIG_copy(rhs,P->y);
+    FP_redc(rhs);
+    if (BIG_parity(rhs)!=s)
+        FP_neg(P->y,P->y);
+    FP_reduce(P->y);
+    FP_one(P->z);
+    return 1;
+}
+
+#endif
+
+/* Convert P to Affine, from (x,y,z) to (x,y) */
+/* SU=160 */
+void ECP_affine(ECP *P)
+{
+    BIG one,iz,m;
+#if CURVETYPE==WEIERSTRASS
+    BIG izn;
+    if (ECP_isinf(P)) return;
+    FP_one(one);
+    if (BIG_comp(P->z,one)==0) return;
+    BIG_rcopy(m,Modulus);
+
+    FP_redc(P->z);
+    BIG_invmodp(iz,P->z,m);
+    FP_nres(iz);
+
+    FP_sqr(izn,iz);
+    FP_mul(P->x,P->x,izn);
+    FP_mul(izn,izn,iz);
+    FP_mul(P->y,P->y,izn);
+    FP_reduce(P->y);
+
+#endif
+#if CURVETYPE==EDWARDS
+    FP_one(one);
+    if (BIG_comp(P->z,one)==0) return;
+    BIG_rcopy(m,Modulus);
+
+    FP_redc(P->z);
+    BIG_invmodp(iz,P->z,m);
+    FP_nres(iz);
+
+    FP_mul(P->x,P->x,iz);
+    FP_mul(P->y,P->y,iz);
+    FP_reduce(P->y);
+
+#endif
+#if CURVETYPE==MONTGOMERY
+    if (ECP_isinf(P)) return;
+    FP_one(one);
+    if (BIG_comp(P->z,one)==0) return;
+
+    BIG_rcopy(m,Modulus);
+
+    FP_redc(P->z);
+    BIG_invmodp(iz,P->z,m);
+    FP_nres(iz);
+
+    FP_mul(P->x,P->x,iz);
+
+#endif
+    FP_reduce(P->x);
+    BIG_copy(P->z,one);
+}
+
+/* SU=120 */
+void ECP_outputxyz(ECP *P)
+{
+    BIG x,z;
+    if (ECP_isinf(P))
+    {
+        printf("Infinity\n");
+        return;
+    }
+    BIG_copy(x,P->x);
+    FP_reduce(x);
+    FP_redc(x);
+    BIG_copy(z,P->z);
+    FP_reduce(z);
+    FP_redc(z);
+
+#if CURVETYPE!=MONTGOMERY
+    BIG y;
+    BIG_copy(y,P->y);
+    FP_reduce(y);
+    FP_redc(y);
+    printf("(");
+    BIG_output(x);
+    printf(",");
+    BIG_output(y);
+    printf(",");
+    BIG_output(z);
+    printf(")\n");
+
+#else
+    printf("(");
+    BIG_output(x);
+    printf(",");
+    BIG_output(z);
+    printf(")\n");
+#endif
+}
+
+/* SU=16 */
+/* Output point P */
+void ECP_output(ECP *P)
+{
+    if (ECP_isinf(P))
+    {
+        printf("Infinity\n");
+        return;
+    }
+    ECP_affine(P);
+#if CURVETYPE!=MONTGOMERY
+    FP_redc(P->x);
+    FP_redc(P->y);
+    printf("(");
+    BIG_output(P->x);
+    printf(",");
+    BIG_output(P->y);
+    printf(")\n");
+    FP_nres(P->x);
+    FP_nres(P->y);
+#else
+    FP_redc(P->x);
+    printf("(");
+    BIG_output(P->x);
+    printf(")\n");
+    FP_nres(P->x);
+#endif
+}
+
+
+/* SU=88 */
+/* Convert P to octet string */
+void ECP_toOctet(octet *W,ECP *P)
+{
+#if CURVETYPE==MONTGOMERY
+    BIG x;
+    ECP_get(x,P);
+    W->len=MODBYTES+1;
+    W->val[0]=6;
+    BIG_toBytes(&(W->val[1]),x);
+#else
+    BIG x,y;
+    ECP_get(x,y,P);
+    W->len=2*MODBYTES+1;
+    W->val[0]=4;
+    BIG_toBytes(&(W->val[1]),x);
+    BIG_toBytes(&(W->val[MODBYTES+1]),y);
+#endif
+}
+
+/* SU=88 */
+/* Restore P from octet string */
+int ECP_fromOctet(ECP *P,octet *W)
+{
+#if CURVETYPE==MONTGOMERY
+    BIG x;
+    BIG_fromBytes(x,&(W->val[1]));
+    if (ECP_set(P,x)) return 1;
+    return 0;
+#else
+    BIG x,y;
+    BIG_fromBytes(x,&(W->val[1]));
+    BIG_fromBytes(y,&(W->val[MODBYTES+1]));
+    if (ECP_set(P,x,y)) return 1;
+    return 0;
+#endif
+}
+
+
+/* Set P=2P */
+/* SU=272 */
+void ECP_dbl(ECP *P)
+{
+#if CURVETYPE==WEIERSTRASS
+    BIG one;
+    BIG w1,w7,w8,w2,w3,w6;
+    if (ECP_isinf(P)) return;
+
+    if (BIG_iszilch(P->y))
+    {
+        P->inf=1;
+        return;
+    }
+    FP_one(one);
+    BIG_zero(w6);
+
+    if (CURVE_A==-3)
+    {
+        if (BIG_comp(P->z,one)==0) BIG_copy(w6,one);
+        else FP_sqr(w6,P->z);
+        FP_neg(w1,w6);
+        FP_add(w3,P->x,w1);
+        FP_add(w8,P->x,w6);
+        FP_mul(w3,w3,w8);
+        BIG_imul(w8,w3,3);
+    }
+    else
+    {
+        /* assuming A=0 */
+        FP_sqr(w1,P->x);
+        BIG_imul(w8,w1,3);
+    }
+
+    FP_sqr(w2,P->y);
+    FP_mul(w3,P->x,w2);
+
+    BIG_imul(w3,w3,4);
+    FP_neg(w1,w3);
+
+    BIG_norm(w1);
+
+    FP_sqr(P->x,w8);
+    FP_add(P->x,P->x,w1);
+    FP_add(P->x,P->x,w1);
+
+    BIG_norm(P->x);
+
+    if (BIG_comp(P->z,one)==0) BIG_copy(P->z,P->y);
+    else FP_mul(P->z,P->z,P->y);
+    FP_add(P->z,P->z,P->z);
+
+
+    FP_add(w7,w2,w2);
+    FP_sqr(w2,w7);
+
+    FP_add(w2,w2,w2);
+    FP_sub(w3,w3,P->x);
+    FP_mul(P->y,w8,w3);
+
+    FP_sub(P->y,P->y,w2);
+
+    BIG_norm(P->y);
+    BIG_norm(P->z);
+
+#endif
+
+#if CURVETYPE==EDWARDS
+    /* Not using square for multiplication swap, as (1) it needs more adds, and (2) it triggers more reductions */
+    BIG B,C,D,E,F,H,J;
+
+    FP_mul(B,P->x,P->y);
+    FP_add(B,B,B);
+    FP_sqr(C,P->x);
+    FP_sqr(D,P->y);
+    if (CURVE_A==1) BIG_copy(E,C);
+    if (CURVE_A==-1) FP_neg(E,C);
+    FP_add(F,E,D);
+
+    BIG_norm(F);
+
+    FP_sqr(H,P->z);
+    FP_add(H,H,H);
+    FP_sub(J,F,H);
+    FP_mul(P->x,B,J);
+    FP_sub(E,E,D);
+    FP_mul(P->y,F,E);
+    FP_mul(P->z,F,J);
+
+    BIG_norm(P->x);
+    BIG_norm(P->y);
+    BIG_norm(P->z);
+
+#endif
+
+#if CURVETYPE==MONTGOMERY
+    BIG A,B,AA,BB,C;
+    if (ECP_isinf(P)) return;
+
+    FP_add(A,P->x,P->z);
+    FP_sqr(AA,A);
+    FP_sub(B,P->x,P->z);
+    FP_sqr(BB,B);
+    FP_sub(C,AA,BB);
+
+    FP_mul(P->x,AA,BB);
+    FP_imul(A,C,(CURVE_A+2)/4);
+    FP_add(BB,BB,A);
+    FP_mul(P->z,BB,C);
+
+    BIG_norm(P->x);
+    BIG_norm(P->z);
+#endif
+}
+
+#if CURVETYPE==MONTGOMERY
+
+/* Set P+=Q. W is difference between P and Q and is affine */
+void ECP_add(ECP *P,ECP *Q,ECP *W)
+{
+    BIG A,B,C,D,DA,CB;
+
+    FP_add(A,P->x,P->z);
+    FP_sub(B,P->x,P->z);
+
+    FP_add(C,Q->x,Q->z);
+    FP_sub(D,Q->x,Q->z);
+
+    FP_mul(DA,D,A);
+    FP_mul(CB,C,B);
+
+    FP_add(A,DA,CB);
+    FP_sqr(A,A);
+    FP_sub(B,DA,CB);
+    FP_sqr(B,B);
+
+    BIG_copy(P->x,A);
+    FP_mul(P->z,W->x,B);
+
+    FP_reduce(P->z);
+    if (BIG_iszilch(P->z)) P->inf=1;
+    else P->inf=0;
+
+    BIG_norm(P->x);
+}
+
+
+#else
+
+/* Set P+=Q */
+/* SU=248 */
+void ECP_add(ECP *P,ECP *Q)
+{
+#if CURVETYPE==WEIERSTRASS
+    int aff;
+    BIG one,B,D,E,C,A;
+    if (ECP_isinf(Q)) return;
+    if (ECP_isinf(P))
+    {
+        ECP_copy(P,Q);
+        return;
+    }
+
+    FP_one(one);
+    aff=1;
+    if (BIG_comp(Q->z,one)!=0) aff=0;
+
+    if (!aff)
+    {
+        FP_sqr(A,Q->z);
+        FP_mul(C,A,Q->z);
+
+        FP_sqr(B,P->z);
+        FP_mul(D,B,P->z);
+
+        FP_mul(A,P->x,A);
+        FP_mul(C,P->y,C);
+    }
+    else
+    {
+        BIG_copy(A,P->x);
+        BIG_copy(C,P->y);
+
+        FP_sqr(B,P->z);
+        FP_mul(D,B,P->z);
+    }
+
+    FP_mul(B,Q->x,B);
+    FP_sub(B,B,A); /* B=Qx.z^2-x.Qz^2 */
+    FP_mul(D,Q->y,D);
+    FP_sub(D,D,C); /* D=Qy.z^3-y.Qz^3 */
+
+    FP_reduce(B);
+    if (BIG_iszilch(B))
+    {
+        FP_reduce(D);
+        if (BIG_iszilch(D))
+        {
+            ECP_dbl(P);
+            return;
+        }
+        else
+        {
+            ECP_inf(P);
+            return;
+        }
+    }
+    if (!aff) FP_mul(P->z,P->z,Q->z);
+    FP_mul(P->z,P->z,B);
+
+    FP_sqr(E,B);
+    FP_mul(B,B,E);
+    FP_mul(A,A,E);
+
+    FP_add(E,A,A);
+    FP_add(E,E,B);
+
+    FP_sqr(P->x,D);
+    FP_sub(P->x,P->x,E);
+
+    FP_sub(A,A,P->x);
+    FP_mul(P->y,A,D);
+    FP_mul(C,C,B);
+    FP_sub(P->y,P->y,C);
+
+    BIG_norm(P->x);
+    BIG_norm(P->y);
+    BIG_norm(P->z);
+
+#else
+    BIG b,A,B,C,D,E,F,G;
+
+    BIG_rcopy(b,CURVE_B);
+    FP_nres(b);
+    FP_mul(A,P->z,Q->z);
+
+    FP_sqr(B,A);
+    FP_mul(C,P->x,Q->x);
+    FP_mul(D,P->y,Q->y);
+    FP_mul(E,C,D);
+    FP_mul(E,E,b);
+
+    FP_sub(F,B,E);
+    FP_add(G,B,E);
+
+    if (CURVE_A==1) FP_sub(E,D,C);
+    FP_add(C,C,D);
+
+    FP_add(B,P->x,P->y);
+    FP_add(D,Q->x,Q->y);
+    FP_mul(B,B,D);
+    FP_sub(B,B,C);
+    FP_mul(B,B,F);
+    FP_mul(P->x,A,B);
+
+
+    if (CURVE_A==1) FP_mul(C,E,G);
+    if (CURVE_A==-1)FP_mul(C,C,G);
+
+    FP_mul(P->y,A,C);
+    FP_mul(P->z,F,G);
+
+    BIG_norm(P->x);
+    BIG_norm(P->y);
+    BIG_norm(P->z);
+
+#endif
+}
+
+/* Set P-=Q */
+/* SU=16 */
+void  ECP_sub(ECP *P,ECP *Q)
+{
+    ECP_neg(Q);
+    ECP_add(P,Q);
+    ECP_neg(Q);
+}
+
+#endif
+
+
+#if CURVETYPE==WEIERSTRASS
+/* normalises array of points. Assumes P[0] is normalised already */
+
+static void ECP_multiaffine(int m,ECP P[],BIG work[])
+{
+    int i;
+    BIG t1,t2;
+
+    FP_one(work[0]);
+    BIG_copy(work[1],P[0].z);
+    for (i=2; i<m; i++)
+        FP_mul(work[i],work[i-1],P[i-1].z);
+
+    FP_mul(t1,work[m-1],P[m-1].z);
+    FP_inv(t1,t1);
+
+    BIG_copy(t2,P[m-1].z);
+    FP_mul(work[m-1],work[m-1],t1);
+
+    for (i=m-2;; i--)
+    {
+        if (i==0)
+        {
+            FP_mul(work[0],t1,t2);
+            break;
+        }
+        FP_mul(work[i],work[i],t2);
+        FP_mul(work[i],work[i],t1);
+        FP_mul(t2,P[i].z,t2);
+    }
+    /* now work[] contains inverses of all Z coordinates */
+
+    for (i=0; i<m; i++)
+    {
+        FP_one(P[i].z);
+        FP_sqr(t1,work[i]);
+        FP_mul(P[i].x,P[i].x,t1);
+        FP_mul(t1,work[i],t1);
+        FP_mul(P[i].y,P[i].y,t1);
+    }
+}
+
+#endif
+
+#if CURVETYPE!=MONTGOMERY
+/* constant time multiply by small integer of length bts - use ladder */
+void ECP_pinmul(ECP *P,int e,int bts)
+{
+    int i,b;
+    ECP R0,R1;
+
+    ECP_affine(P);
+    ECP_inf(&R0);
+    ECP_copy(&R1,P);
+
+    for (i=bts-1; i>=0; i--)
+    {
+        b=(e>>i)&1;
+        ECP_copy(P,&R1);
+        ECP_add(P,&R0);
+        ECP_cswap(&R0,&R1,b);
+        ECP_copy(&R1,P);
+        ECP_dbl(&R0);
+        ECP_cswap(&R0,&R1,b);
+    }
+    ECP_copy(P,&R0);
+    ECP_affine(P);
+}
+#endif
+
+/* Set P=r*P */
+/* SU=424 */
+void ECP_mul(ECP *P,BIG e)
+{
+#if CURVETYPE==MONTGOMERY
+    /* Montgomery ladder */
+    int nb,i,b;
+    ECP R0,R1,D;
+    if (ECP_isinf(P)) return;
+    if (BIG_iszilch(e))
+    {
+        ECP_inf(P);
+        return;
+    }
+    ECP_affine(P);
+
+    ECP_copy(&R0,P);
+    ECP_copy(&R1,P);
+    ECP_dbl(&R1);
+    ECP_copy(&D,P);
+
+    nb=BIG_nbits(e);
+    for (i=nb-2; i>=0; i--)
+    {
+        b=BIG_bit(e,i);
+        ECP_copy(P,&R1);
+        ECP_add(P,&R0,&D);
+        ECP_cswap(&R0,&R1,b);
+        ECP_copy(&R1,P);
+        ECP_dbl(&R0);
+        ECP_cswap(&R0,&R1,b);
+    }
+    ECP_copy(P,&R0);
+
+#else
+    /* fixed size windows */
+    int i,nb,s,ns;
+    BIG mt,t;
+    ECP Q,W[8],C;
+    sign8 w[1+(NLEN*BASEBITS+3)/4];
+#if CURVETYPE==WEIERSTRASS
+    BIG work[8];
+#endif
+    if (ECP_isinf(P)) return;
+    if (BIG_iszilch(e))
+    {
+        ECP_inf(P);
+        return;
+    }
+
+    ECP_affine(P);
+
+    /* precompute table */
+
+    ECP_copy(&Q,P);
+    ECP_dbl(&Q);
+
+//printf("Q= ");ECP_output(&Q); printf("\n");
+
+    ECP_copy(&W[0],P);
+
+    for (i=1; i<8; i++)
+    {
+        ECP_copy(&W[i],&W[i-1]);
+        ECP_add(&W[i],&Q);
+    }
+
+//printf("W[1]= ");ECP_output(&W[1]); printf("\n");
+
+    /* convert the table to affine */
+#if CURVETYPE==WEIERSTRASS
+    ECP_multiaffine(8,W,work);
+#endif
+
+    /* make exponent odd - add 2P if even, P if odd */
+    BIG_copy(t,e);
+    s=BIG_parity(t);
+    BIG_inc(t,1);
+    BIG_norm(t);
+    ns=BIG_parity(t);
+    BIG_copy(mt,t);
+    BIG_inc(mt,1);
+    BIG_norm(mt);
+    BIG_cmove(t,mt,s);
+    ECP_cmove(&Q,P,ns);
+    ECP_copy(&C,&Q);
+
+    nb=1+(BIG_nbits(t)+3)/4;
+
+    /* convert exponent to signed 4-bit window */
+    for (i=0; i<nb; i++)
+    {
+        w[i]=BIG_lastbits(t,5)-16;
+        BIG_dec(t,w[i]);
+        BIG_norm(t);
+        BIG_fshr(t,4);
+    }
+    w[nb]=BIG_lastbits(t,5);
+
+    ECP_copy(P,&W[(w[nb]-1)/2]);
+    for (i=nb-1; i>=0; i--)
+    {
+        ECP_select(&Q,W,w[i]);
+        ECP_dbl(P);
+        ECP_dbl(P);
+        ECP_dbl(P);
+        ECP_dbl(P);
+        ECP_add(P,&Q);
+    }
+    ECP_sub(P,&C); /* apply correction */
+#endif
+    ECP_affine(P);
+}
+
+#if CURVETYPE!=MONTGOMERY
+/* Set P=eP+fQ double multiplication */
+/* constant time - as useful for GLV method in pairings */
+/* SU=456 */
+
+void ECP_mul2(ECP *P,ECP *Q,BIG e,BIG f)
+{
+    BIG te,tf,mt;
+    ECP S,T,W[8],C;
+    sign8 w[1+(NLEN*BASEBITS+1)/2];
+    int i,a,b,s,ns,nb;
+#if CURVETYPE==WEIERSTRASS
+    BIG work[8];
+#endif
+
+    ECP_affine(P);
+    ECP_affine(Q);
+
+    BIG_copy(te,e);
+    BIG_copy(tf,f);
+
+    /* precompute table */
+    ECP_copy(&W[1],P);
+    ECP_sub(&W[1],Q);  /* P+Q */
+    ECP_copy(&W[2],P);
+    ECP_add(&W[2],Q);  /* P-Q */
+    ECP_copy(&S,Q);
+    ECP_dbl(&S);  /* S=2Q */
+    ECP_copy(&W[0],&W[1]);
+    ECP_sub(&W[0],&S);
+    ECP_copy(&W[3],&W[2]);
+    ECP_add(&W[3],&S);
+    ECP_copy(&T,P);
+    ECP_dbl(&T); /* T=2P */
+    ECP_copy(&W[5],&W[1]);
+    ECP_add(&W[5],&T);
+    ECP_copy(&W[6],&W[2]);
+    ECP_add(&W[6],&T);
+    ECP_copy(&W[4],&W[5]);
+    ECP_sub(&W[4],&S);
+    ECP_copy(&W[7],&W[6]);
+    ECP_add(&W[7],&S);
+
+#if CURVETYPE==WEIERSTRASS
+    ECP_multiaffine(8,W,work);
+#endif
+
+    /* if multiplier is odd, add 2, else add 1 to multiplier, and add 2P or P to correction */
+
+    s=BIG_parity(te);
+    BIG_inc(te,1);
+    BIG_norm(te);
+    ns=BIG_parity(te);
+    BIG_copy(mt,te);
+    BIG_inc(mt,1);
+    BIG_norm(mt);
+    BIG_cmove(te,mt,s);
+    ECP_cmove(&T,P,ns);
+    ECP_copy(&C,&T);
+
+    s=BIG_parity(tf);
+    BIG_inc(tf,1);
+    BIG_norm(tf);
+    ns=BIG_parity(tf);
+    BIG_copy(mt,tf);
+    BIG_inc(mt,1);
+    BIG_norm(mt);
+    BIG_cmove(tf,mt,s);
+    ECP_cmove(&S,Q,ns);
+    ECP_add(&C,&S);
+
+    BIG_add(mt,te,tf);
+    BIG_norm(mt);
+    nb=1+(BIG_nbits(mt)+1)/2;
+
+    /* convert exponent to signed 2-bit window */
+    for (i=0; i<nb; i++)
+    {
+        a=BIG_lastbits(te,3)-4;
+        BIG_dec(te,a);
+        BIG_norm(te);
+        BIG_fshr(te,2);
+        b=BIG_lastbits(tf,3)-4;
+        BIG_dec(tf,b);
+        BIG_norm(tf);
+        BIG_fshr(tf,2);
+        w[i]=4*a+b;
+    }
+    w[nb]=(4*BIG_lastbits(te,3)+BIG_lastbits(tf,3));
+
+    ECP_copy(P,&W[(w[nb]-1)/2]);
+    for (i=nb-1; i>=0; i--)
+    {
+        ECP_select(&T,W,w[i]);
+        ECP_dbl(P);
+        ECP_dbl(P);
+        ECP_add(P,&T);
+    }
+    ECP_sub(P,&C); /* apply correction */
+    ECP_affine(P);
+}
+
+#endif
+
+
+#ifdef HAS_MAIN
+
+int main()
+{
+    int i;
+    ECP G,P;
+    csprng RNG;
+    BIG r,s,x,y,b,m,w,q;
+    BIG_rcopy(x,CURVE_Gx);
+#if CURVETYPE!=MONTGOMERY
+    BIG_rcopy(y,CURVE_Gy);
+#endif
+    BIG_rcopy(m,Modulus);
+
+    printf("x= ");
+    BIG_output(x);
+    printf("\n");
+#if CURVETYPE!=MONTGOMERY
+    printf("y= ");
+    BIG_output(y);
+    printf("\n");
+#endif
+    RNG_seed(&RNG,3,"abc");
+
+#if CURVETYPE!=MONTGOMERY
+    ECP_set(&G,x,y);
+#else
+    ECP_set(&G,x);
+#endif
+    if (ECP_isinf(&G)) printf("Failed to set - point not on curve\n");
+    else printf("set success\n");
+
+    ECP_output(&G);
+
+    BIG_rcopy(r,CURVE_Order); //BIG_dec(r,7);
+    printf("r= ");
+    BIG_output(r);
+    printf("\n");
+
+    ECP_copy(&P,&G);
+
+    ECP_mul(&P,r);
+
+    ECP_output(&P);
+//exit(0);
+    BIG_randomnum(w,&RNG);
+    BIG_mod(w,r);
+
+    ECP_copy(&P,&G);
+    ECP_mul(&P,w);
+
+    ECP_output(&P);
+
+    return 0;
+}
+
+#endif
diff --git a/version22/c/ecp2.c b/version22/c/ecp2.c
new file mode 100644
index 0000000..4808569
--- /dev/null
+++ b/version22/c/ecp2.c
@@ -0,0 +1,696 @@
+/*
+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.
+*/
+
+/* AMCL Weierstrass elliptic curve functions over FP2 */
+/* SU=m, m is Stack Usage */
+
+#include "amcl.h"
+
+int ECP2_isinf(ECP2 *P)
+{
+    return P->inf;
+}
+
+/* Set P=Q */
+/* SU= 16 */
+void ECP2_copy(ECP2 *P,ECP2 *Q)
+{
+    P->inf=Q->inf;
+    FP2_copy(&(P->x),&(Q->x));
+    FP2_copy(&(P->y),&(Q->y));
+    FP2_copy(&(P->z),&(Q->z));
+}
+
+/* set P to Infinity */
+/* SU= 8 */
+void ECP2_inf(ECP2 *P)
+{
+    P->inf=1;
+    FP2_zero(&(P->x));
+    FP2_zero(&(P->y));
+    FP2_zero(&(P->z));
+}
+
+/* Conditional move Q to P dependant on d */
+static void ECP2_cmove(ECP2 *P,ECP2 *Q,int d)
+{
+    FP2_cmove(&(P->x),&(Q->x),d);
+    FP2_cmove(&(P->y),&(Q->y),d);
+    FP2_cmove(&(P->z),&(Q->z),d);
+    d=~(d-1);
+    P->inf^=(P->inf^Q->inf)&d;
+}
+
+/* return 1 if b==c, no branching */
+static int teq(sign32 b,sign32 c)
+{
+    sign32 x=b^c;
+    x-=1;  // if x=0, x now -1
+    return (int)((x>>31)&1);
+}
+
+/* Constant time select from pre-computed table */
+static void ECP2_select(ECP2 *P,ECP2 W[],sign32 b)
+{
+    ECP2 MP;
+    sign32 m=b>>31;
+    sign32 babs=(b^m)-m;
+
+    babs=(babs-1)/2;
+
+    ECP2_cmove(P,&W[0],teq(babs,0));  // conditional move
+    ECP2_cmove(P,&W[1],teq(babs,1));
+    ECP2_cmove(P,&W[2],teq(babs,2));
+    ECP2_cmove(P,&W[3],teq(babs,3));
+    ECP2_cmove(P,&W[4],teq(babs,4));
+    ECP2_cmove(P,&W[5],teq(babs,5));
+    ECP2_cmove(P,&W[6],teq(babs,6));
+    ECP2_cmove(P,&W[7],teq(babs,7));
+
+    ECP2_copy(&MP,P);
+    ECP2_neg(&MP);  // minus P
+    ECP2_cmove(P,&MP,(int)(m&1));
+}
+
+/* return 1 if P==Q, else 0 */
+/* SU= 312 */
+int ECP2_equals(ECP2 *P,ECP2 *Q)
+{
+    FP2 pz2,qz2,a,b;
+    if (P->inf && Q->inf) return 1;
+    if (P->inf || Q->inf) return 0;
+
+    FP2_sqr(&pz2,&(P->z));
+    FP2_sqr(&qz2,&(Q->z));
+
+    FP2_mul(&a,&(P->x),&qz2);
+    FP2_mul(&b,&(Q->x),&pz2);
+    if (!FP2_equals(&a,&b)) return 0;
+
+    FP2_mul(&a,&(P->y),&qz2);
+    FP2_mul(&a,&a,&(Q->z));
+    FP2_mul(&b,&(Q->y),&pz2);
+    FP2_mul(&b,&b,&(P->z));
+    if (!FP2_equals(&a,&b)) return 0;
+    return 1;
+}
+
+/* Make P affine (so z=1) */
+/* SU= 232 */
+void ECP2_affine(ECP2 *P)
+{
+    FP2 one,iz,izn;
+    if (P->inf) return;
+
+    FP2_one(&one);
+    if (FP2_isunity(&(P->z)))
+    {
+        FP2_reduce(&(P->x));
+        FP2_reduce(&(P->y));
+        return;
+    }
+
+    FP2_inv(&iz,&(P->z));
+    FP2_sqr(&izn,&iz);
+    FP2_mul(&(P->x),&(P->x),&izn);
+    FP2_mul(&izn,&izn,&iz);
+    FP2_mul(&(P->y),&(P->y),&izn);
+
+    FP2_reduce(&(P->x));
+    FP2_reduce(&(P->y));
+    FP2_copy(&(P->z),&one);
+}
+
+/* extract x, y from point P */
+/* SU= 16 */
+int ECP2_get(FP2 *x,FP2 *y,ECP2 *P)
+{
+    if (P->inf) return -1;
+    ECP2_affine(P);
+    FP2_copy(y,&(P->y));
+    FP2_copy(x,&(P->x));
+    return 0;
+}
+
+/* SU= 152 */
+/* Output point P */
+void ECP2_output(ECP2 *P)
+{
+    FP2 x,y;
+    if (P->inf)
+    {
+        printf("Infinity\n");
+        return;
+    }
+    ECP2_get(&x,&y,P);
+    printf("(");
+    FP2_output(&x);
+    printf(",");
+    FP2_output(&y);
+    printf(")\n");
+}
+
+/* SU= 232 */
+void ECP2_outputxyz(ECP2 *P)
+{
+    ECP2 Q;
+    if (P->inf)
+    {
+        printf("Infinity\n");
+        return;
+    }
+    ECP2_copy(&Q,P);
+    printf("(");
+    FP2_output(&(Q.x));
+    printf(",");
+    FP2_output(&(Q.y));
+    printf(",");
+    FP2_output(&(Q.z));
+    printf(")\n");
+}
+
+/* SU= 168 */
+/* Convert Q to octet string */
+void ECP2_toOctet(octet *W,ECP2 *Q)
+{
+    FP2 qx,qy;
+    ECP2_get(&qx,&qy,Q);
+    FP_redc(qx.a);
+    FP_redc(qx.b);
+    FP_redc(qy.a);
+    FP_redc(qy.b);
+    W->len=4*MODBYTES;
+
+    BIG_toBytes(&(W->val[0]),qx.a);
+    BIG_toBytes(&(W->val[MODBYTES]),qx.b);
+    BIG_toBytes(&(W->val[2*MODBYTES]),qy.a);
+    BIG_toBytes(&(W->val[3*MODBYTES]),qy.b);
+}
+
+/* SU= 176 */
+/* restore Q from octet string */
+int ECP2_fromOctet(ECP2 *Q,octet *W)
+{
+    FP2 qx,qy;
+    BIG_fromBytes(qx.a,&(W->val[0]));
+    BIG_fromBytes(qx.b,&(W->val[MODBYTES]));
+    BIG_fromBytes(qy.a,&(W->val[2*MODBYTES]));
+    BIG_fromBytes(qy.b,&(W->val[3*MODBYTES]));
+    FP_nres(qx.a);
+    FP_nres(qx.b);
+    FP_nres(qy.a);
+    FP_nres(qy.b);
+
+    if (ECP2_set(Q,&qx,&qy)) return 1;
+    return 0;
+}
+
+/* SU= 128 */
+/* Calculate RHS of twisted curve equation x^3+B/i */
+void ECP2_rhs(FP2 *rhs,FP2 *x)
+{
+    /* calculate RHS of elliptic curve equation */
+    FP2 t;
+    BIG b;
+    FP2_sqr(&t,x);
+
+    FP2_mul(rhs,&t,x);
+
+    /* Assuming CURVE_A=0 */
+
+    BIG_rcopy(b,CURVE_B);
+
+    FP2_from_BIG(&t,b);
+
+    FP2_div_ip(&t);   /* IMPORTANT - here we use the SEXTIC twist of the curve */
+
+    FP2_add(rhs,&t,rhs);
+    FP2_reduce(rhs);
+}
+
+
+/* Set P=(x,y). Return 1 if (x,y) is on the curve, else return 0*/
+/* SU= 232 */
+int ECP2_set(ECP2 *P,FP2 *x,FP2 *y)
+{
+    FP2 one,rhs,y2;
+    FP2_copy(&y2,y);
+
+    FP2_sqr(&y2,&y2);
+    ECP2_rhs(&rhs,x);
+
+    if (!FP2_equals(&y2,&rhs))
+    {
+
+        P->inf=1;
+        return 0;
+    }
+
+    P->inf=0;
+    FP2_copy(&(P->x),x);
+    FP2_copy(&(P->y),y);
+
+    FP2_one(&one);
+    FP2_copy(&(P->z),&one);
+    return 1;
+}
+
+/* Set P=(x,y). Return 1 if (x,.) is on the curve, else return 0 */
+/* SU= 232 */
+int ECP2_setx(ECP2 *P,FP2 *x)
+{
+    FP2 y;
+    ECP2_rhs(&y,x);
+
+    if (!FP2_sqrt(&y,&y))
+    {
+        P->inf=1;
+        return 0;
+    }
+
+    P->inf=0;
+    FP2_copy(&(P->x),x);
+    FP2_copy(&(P->y),&y);
+    FP2_one(&(P->z));
+    return 1;
+}
+
+/* Set P=-P */
+/* SU= 8 */
+void ECP2_neg(ECP2 *P)
+{
+    FP2_neg(&(P->y),&(P->y));
+    FP2_norm(&(P->y));
+}
+
+/* R+=R */
+/* return -1 for Infinity, 0 for addition, 1 for doubling */
+/* SU= 448 */
+int ECP2_dbl(ECP2 *P)
+{
+    FP2 w1,w7,w8,w2,w3;
+    if (P->inf) return -1;
+
+    if (FP2_iszilch(&(P->y)))
+    {
+        P->inf=1;
+        return -1;
+    }
+
+    /* Assuming A=0 */
+    FP2_sqr(&w1,&(P->x));
+    FP2_imul(&w8,&w1,3);
+
+    FP2_sqr(&w2,&(P->y));
+    FP2_mul(&w3,&(P->x),&w2);
+    FP2_imul(&w3,&w3,4);
+
+    FP2_neg(&w1,&w3);
+
+    FP2_norm(&w1);
+
+    FP2_sqr(&(P->x),&w8);
+    FP2_add(&(P->x),&(P->x),&w1);
+    FP2_add(&(P->x),&(P->x),&w1);
+
+    FP2_norm(&(P->x));
+
+    if (FP2_isunity(&(P->z))) FP2_copy(&(P->z),&(P->y));
+    else FP2_mul(&(P->z),&(P->z),&(P->y));
+    FP2_add(&(P->z),&(P->z),&(P->z));
+
+    FP2_add(&w7,&w2,&w2);
+    FP2_sqr(&w2,&w7);
+
+    FP2_add(&w2,&w2,&w2);
+    FP2_sub(&w3,&w3,&(P->x));
+    FP2_mul(&(P->y),&w8,&w3);
+    FP2_sub(&(P->y),&(P->y),&w2);
+
+
+    FP2_norm(&(P->y));
+    FP2_norm(&(P->z));
+
+    return 1;
+}
+
+/* Set P+=Q */
+/* SU= 400 */
+int ECP2_add(ECP2 *P,ECP2 *Q)
+{
+    int aff;
+    FP2 B,D,E,C,A;
+    if (Q->inf) return 0;
+    if (P->inf)
+    {
+        ECP2_copy(P,Q);
+        return 0;
+    }
+
+    aff=1;
+    if (!FP2_isunity(&(Q->z))) aff=0;
+
+    if (!aff)
+    {
+        FP2_sqr(&A,&(Q->z));
+        FP2_mul(&C,&A,&(Q->z));
+
+        FP2_sqr(&B,&(P->z));
+        FP2_mul(&D,&B,&(P->z));
+
+        FP2_mul(&A,&(P->x),&A);
+        FP2_mul(&C,&(P->y),&C);
+    }
+    else
+    {
+        FP2_copy(&A,&(P->x));
+        FP2_copy(&C,&(P->y));
+
+        FP2_sqr(&B,&(P->z));
+        FP2_mul(&D,&B,&(P->z));
+    }
+
+    FP2_mul(&B,&(Q->x),&B);
+    FP2_sub(&B,&B,&A); /* B=Qx.z^2-x.Qz^2 */
+    FP2_mul(&D,&(Q->y),&D);
+    FP2_sub(&D,&D,&C); /* D=Qy.z^3-y.Qz^3 */
+
+    if (FP2_iszilch(&B))
+    {
+        if (FP2_iszilch(&D))
+        {
+            ECP2_dbl(P);
+            return 1;
+        }
+        else
+        {
+            ECP2_inf(P);
+            return -1;
+        }
+    }
+    if (!aff) FP2_mul(&(P->z),&(P->z),&(Q->z));
+    FP2_mul(&(P->z),&(P->z),&B);
+
+    FP2_sqr(&E,&B);
+    FP2_mul(&B,&B,&E);
+    FP2_mul(&A,&A,&E);
+
+    FP2_add(&E,&A,&A);
+    FP2_add(&E,&E,&B);
+
+    FP2_sqr(&(P->x),&D);
+    FP2_sub(&(P->x),&(P->x),&E);
+
+    FP2_sub(&A,&A,&(P->x));
+    FP2_mul(&(P->y),&A,&D);
+    FP2_mul(&C,&C,&B);
+    FP2_sub(&(P->y),&(P->y),&C);
+
+    FP2_norm(&(P->x));
+    FP2_norm(&(P->y));
+    FP2_norm(&(P->z));
+
+    return 0;
+}
+
+/* Set P-=Q */
+/* SU= 16 */
+void ECP2_sub(ECP2 *P,ECP2 *Q)
+{
+    ECP2_neg(Q);
+    ECP2_add(P,Q);
+    ECP2_neg(Q);
+}
+
+/* normalises m-array of ECP2 points. Requires work vector of m FP2s */
+/* SU= 200 */
+static void ECP2_multiaffine(int m,ECP2 *P,FP2 *work)
+{
+    int i;
+    FP2 t1,t2;
+
+    FP2_one(&work[0]);
+    FP2_copy(&work[1],&(P[0].z));
+    for (i=2; i<m; i++)
+        FP2_mul(&work[i],&work[i-1],&(P[i-1].z));
+    FP2_mul(&t1,&work[m-1],&(P[m-1].z));
+
+    FP2_inv(&t1,&t1);
+
+    FP2_copy(&t2,&(P[m-1].z));
+    FP2_mul(&work[m-1],&work[m-1],&t1);
+
+    for (i=m-2;; i--)
+    {
+        if (i==0)
+        {
+            FP2_mul(&work[0],&t1,&t2);
+            break;
+        }
+        FP2_mul(&work[i],&work[i],&t2);
+        FP2_mul(&work[i],&work[i],&t1);
+        FP2_mul(&t2,&(P[i].z),&t2);
+    }
+    /* now work[] contains inverses of all Z coordinates */
+
+    for (i=0; i<m; i++)
+    {
+        FP2_one(&(P[i].z));
+        FP2_sqr(&t1,&work[i]);
+        FP2_mul(&(P[i].x),&(P[i].x),&t1);
+        FP2_mul(&t1,&work[i],&t1);
+        FP2_mul(&(P[i].y),&(P[i].y),&t1);
+    }
+}
+
+/* P*=e */
+/* SU= 280 */
+void ECP2_mul(ECP2 *P,BIG e)
+{
+    /* fixed size windows */
+    int i,nb,s,ns;
+    BIG mt,t;
+    ECP2 Q,W[8],C;
+    sign8 w[1+(NLEN*BASEBITS+3)/4];
+    FP2 work[8];
+
+    if (ECP2_isinf(P)) return;
+    ECP2_affine(P);
+
+
+    /* precompute table */
+
+    ECP2_copy(&Q,P);
+    ECP2_dbl(&Q);
+    ECP2_copy(&W[0],P);
+
+    for (i=1; i<8; i++)
+    {
+        ECP2_copy(&W[i],&W[i-1]);
+        ECP2_add(&W[i],&Q);
+    }
+
+    /* convert the table to affine */
+
+    ECP2_multiaffine(8,W,work);
+
+    /* make exponent odd - add 2P if even, P if odd */
+    BIG_copy(t,e);
+    s=BIG_parity(t);
+    BIG_inc(t,1);
+    BIG_norm(t);
+    ns=BIG_parity(t);
+    BIG_copy(mt,t);
+    BIG_inc(mt,1);
+    BIG_norm(mt);
+    BIG_cmove(t,mt,s);
+    ECP2_cmove(&Q,P,ns);
+    ECP2_copy(&C,&Q);
+
+    nb=1+(BIG_nbits(t)+3)/4;
+
+    /* convert exponent to signed 4-bit window */
+    for (i=0; i<nb; i++)
+    {
+        w[i]=BIG_lastbits(t,5)-16;
+        BIG_dec(t,w[i]);
+        BIG_norm(t);
+        BIG_fshr(t,4);
+    }
+    w[nb]=BIG_lastbits(t,5);
+
+    ECP2_copy(P,&W[(w[nb]-1)/2]);
+    for (i=nb-1; i>=0; i--)
+    {
+        ECP2_select(&Q,W,w[i]);
+        ECP2_dbl(P);
+        ECP2_dbl(P);
+        ECP2_dbl(P);
+        ECP2_dbl(P);
+        ECP2_add(P,&Q);
+    }
+    ECP2_sub(P,&C); /* apply correction */
+    ECP2_affine(P);
+}
+
+/* Calculates q.P using Frobenius constant X */
+/* SU= 96 */
+void ECP2_frob(ECP2 *P,FP2 *X)
+{
+    FP2 X2;
+    if (P->inf) return;
+    FP2_sqr(&X2,X);
+    FP2_conj(&(P->x),&(P->x));
+    FP2_conj(&(P->y),&(P->y));
+    FP2_conj(&(P->z),&(P->z));
+    FP2_reduce(&(P->z));
+
+    FP2_mul(&(P->x),&X2,&(P->x));
+    FP2_mul(&(P->y),&X2,&(P->y));
+    FP2_mul(&(P->y),X,&(P->y));
+}
+
+void ECP2_mul4(ECP2 *P,ECP2 Q[4],BIG u[4])
+{
+    int i,j,a[4],nb;
+    ECP2 W[8],T,C;
+    BIG mt,t[4];
+    FP2 work[8];
+    sign8 w[NLEN*BASEBITS+1];
+
+    for (i=0; i<4; i++)
+    {
+        BIG_copy(t[i],u[i]);
+        ECP2_affine(&Q[i]);
+    }
+
+    /* precompute table */
+
+    ECP2_copy(&W[0],&Q[0]);
+    ECP2_sub(&W[0],&Q[1]);  /* P-Q */
+    ECP2_copy(&W[1],&W[0]);
+    ECP2_copy(&W[2],&W[0]);
+    ECP2_copy(&W[3],&W[0]);
+    ECP2_copy(&W[4],&Q[0]);
+    ECP2_add(&W[4],&Q[1]);  /* P+Q */
+    ECP2_copy(&W[5],&W[4]);
+    ECP2_copy(&W[6],&W[4]);
+    ECP2_copy(&W[7],&W[4]);
+
+    ECP2_copy(&T,&Q[2]);
+    ECP2_sub(&T,&Q[3]);       /* R-S */
+    ECP2_sub(&W[1],&T);
+    ECP2_add(&W[2],&T);
+    ECP2_sub(&W[5],&T);
+    ECP2_add(&W[6],&T);
+    ECP2_copy(&T,&Q[2]);
+    ECP2_add(&T,&Q[3]);      /* R+S */
+    ECP2_sub(&W[0],&T);
+    ECP2_add(&W[3],&T);
+    ECP2_sub(&W[4],&T);
+    ECP2_add(&W[7],&T);
+
+    ECP2_multiaffine(8,W,work);
+
+    /* if multiplier is even add 1 to multiplier, and add P to correction */
+    ECP2_inf(&C);
+
+    BIG_zero(mt);
+    for (i=0; i<4; i++)
+    {
+        if (BIG_parity(t[i])==0)
+        {
+            BIG_inc(t[i],1);
+            BIG_norm(t[i]);
+            ECP2_add(&C,&Q[i]);
+        }
+        BIG_add(mt,mt,t[i]);
+        BIG_norm(mt);
+    }
+
+    nb=1+BIG_nbits(mt);
+
+    /* convert exponent to signed 1-bit window */
+    for (j=0; j<nb; j++)
+    {
+        for (i=0; i<4; i++)
+        {
+            a[i]=BIG_lastbits(t[i],2)-2;
+            BIG_dec(t[i],a[i]);
+            BIG_norm(t[i]);
+            BIG_fshr(t[i],1);
+        }
+        w[j]=8*a[0]+4*a[1]+2*a[2]+a[3];
+    }
+    w[nb]=8*BIG_lastbits(t[0],2)+4*BIG_lastbits(t[1],2)+2*BIG_lastbits(t[2],2)+BIG_lastbits(t[3],2);
+
+    ECP2_copy(P,&W[(w[nb]-1)/2]);
+    for (i=nb-1; i>=0; i--)
+    {
+        ECP2_select(&T,W,w[i]);
+        ECP2_dbl(P);
+        ECP2_add(P,&T);
+    }
+    ECP2_sub(P,&C); /* apply correction */
+
+    ECP2_affine(P);
+}
+
+/*
+
+int main()
+{
+	int i;
+	ECP2 G,P;
+	ECP2 *W;
+	FP2 x,y,w,z,f;
+	BIG r,xa,xb,ya,yb;
+
+	BIG_rcopy(xa,CURVE_Pxa);
+	BIG_rcopy(xb,CURVE_Pxb);
+	BIG_rcopy(ya,CURVE_Pya);
+	BIG_rcopy(yb,CURVE_Pyb);
+
+	FP2_from_BIGs(&x,xa,xb);
+	FP2_from_BIGs(&y,ya,yb);
+	ECP2_set(&G,&x,&y);
+	if (G.inf) printf("Failed to set - point not on curve\n");
+	else printf("set success\n");
+
+	ECP2_output(&G);
+
+//	BIG_copy(r,CURVE_Order);
+	BIG_rcopy(r,Modulus);
+
+	ECP2_copy(&P,&G);
+
+	ECP2_mul(&P,r);
+
+	ECP2_output(&P);
+
+	FP2_gfc(&f,12);
+
+	ECP2_frob(&G,&f);
+
+	ECP2_output(&G);
+
+	return 0;
+}
+
+*/
diff --git a/version22/c/faster.c b/version22/c/faster.c
new file mode 100644
index 0000000..7786880
--- /dev/null
+++ b/version22/c/faster.c
@@ -0,0 +1,98 @@
+
+#include <stdio.h>
+#include "amcl.h"
+
+#ifdef COMBA
+
+int main()
+{
+	int i,j,k,N;
+
+	N=NLEN;
+
+
+	printf("Insert this code in BIG_mul() in file big.c between #define UNWOUND and #else \n\n");
+
+	for (i=0;i<N;i++)
+		printf("\td[%d]=(dchunk)a[%d]*b[%d];\n",i,i,i);
+
+	printf("\n\ts=d[0];\n\tt = s; c[0]=(chunk)t&BMASK; co=t>>BASEBITS;\n");
+
+	for (k=1;k<N;k++)
+	{
+		printf("\ts+=d[%d]; t=co+s ",k);
+		for (i=k;i>=1+k/2;i--)
+			printf("+(dchunk)(a[%d]-a[%d])*(b[%d]-b[%d])",i,k-i,k-i,i);
+		printf("; c[%d]=(chunk)t&BMASK; co=t>>BASEBITS; \n",k);
+	}
+	printf("\n");
+	for (k=N;k<2*N-1;k++)
+	{
+		printf("\ts-=d[%d]; t=co+s ",k-N);
+		for (i=N-1;i>=1+k/2;i--)
+			printf("+(dchunk)(a[%d]-a[%d])*(b[%d]-b[%d])",i,k-i,k-i,i);
+		printf("; c[%d]=(chunk)t&BMASK; co=t>>BASEBITS; \n",k);
+	}
+	printf("\tc[%d]=(chunk)co;\n",2*N-1);
+
+
+
+	printf("\nInsert this code in BIG_sqr() in file big.c between #define UNWOUND and #else \n\n");
+
+	printf("\n\tt=(dchunk)a[0]*a[0]; c[0]=(chunk)t&BMASK; co=t>>BASEBITS;\n");
+
+	for (k=1;k<N;k++)
+	{
+		printf("\tt= ",k);
+		for (i=k;i>=1+k/2;i--)
+			printf("+(dchunk)a[%d]*a[%d]",i,k-i);
+		printf("; t+=t; t+=co;");
+		if (k%2==0) printf(" t+=(dchunk)a[%d]*a[%d];",k/2,k/2);
+		printf(" c[%d]=(chunk)t&BMASK; co=t>>BASEBITS; \n", k);
+	}
+	printf("\n");
+
+	for (k=N;k<2*N-2;k++)
+	{
+		printf("\tt= ",k-N);
+		for (i=N-1;i>=1+k/2;i--)
+			printf("+(dchunk)a[%d]*a[%d]",i,k-i);
+		printf("; t+=t; t+=co;");
+		if (k%2==0) printf(" t+=(dchunk)a[%d]*a[%d];",k/2,k/2);
+		printf(" c[%d]=(chunk)t&BMASK; co=t>>BASEBITS; \n", k);
+	}
+	printf("\tt=co; t+=(dchunk)a[%d]*a[%d]; c[%d]=(chunk)t&BMASK; co=t>>BASEBITS; \n ",N-1,N-1,2*N-2);
+
+	printf("\tc[%d]=(chunk)co;\n",2*N-1);
+
+
+#if MODTYPE == NOT_SPECIAL
+
+	printf("\nInsert this code in BIG_monty() in file big.c between #define UNWOUND and #else \n\n");
+
+	printf("\tt=d[0]; v[0]=((chunk)t*MC)&BMASK; t+=(dchunk)v[0]*md[0];  s=0; c=(t>>BASEBITS);\n\n");
+
+	for (k=1;k<N;k++)
+	{
+		printf("\tt=d[%d]+c+s+(dchunk)v[0]*md[%d]",k,k);
+		for (i=k-1;i>k/2;i--) printf("+(dchunk)(v[%d]-v[%d])*(md[%d]-md[%d])",k-i,i,i,k-i);
+		printf("; v[%d]=((chunk)t*MC)&BMASK; t+=(dchunk)v[%d]*md[0]; ",k,k);
+		printf(" dd[%d]=(dchunk)v[%d]*md[%d]; s+=dd[%d]; c=(t>>BASEBITS); \n",k,k,k,k);
+	}
+	printf("\n");
+	for (k=N;k<2*N-1;k++)
+	{
+		printf("\tt=d[%d]+c+s",k);
+		for (i=N-1;i>=1+k/2;i--) printf("+(dchunk)(v[%d]-v[%d])*(md[%d]-md[%d])",k-i,i,i,k-i);
+		printf("; a[%d]=(chunk)t&BMASK;  s-=dd[%d]; c=(t>>BASEBITS); \n",k-N,k-N+1);
+	}
+	printf("\ta[%d]=d[%d]+(chunk)c&BMASK;\n",N-1,2*N-1);	
+
+
+#endif
+
+}
+
+#endif
+
+
diff --git a/version22/c/faster.txt b/version22/c/faster.txt
new file mode 100644
index 0000000..6995eab
--- /dev/null
+++ b/version22/c/faster.txt
@@ -0,0 +1,25 @@
+We assume than optimizing compilers will unwind loops at every opportunity. 
+
+But sometimes they don't. So time-critical code will run faster if we step
+in and unwind complex loops for the compiler.
+
+Once the architecture and ECC/RSA support is decided upon (that is amcl.h 
+and arch.h are settled), then compile and execute the program faster.c like 
+this (using MinGW port of GCC as an example), in the same directory as 
+arch.h and amcl.h
+
+gcc -O2 -std=c99 faster.c -o faster.exe
+faster > t.txt
+
+Now extract the code fragments from t.txt and insert them where indicated
+into big.c
+
+Finally make sure that
+
+#define UNWOUND
+
+appears somewhere in amcl.h
+
+Finally build the library as normal, and maybe get a 50% speed-up!
+If there is no significant improvement, don't use this method!
+
diff --git a/version22/c/ff.c b/version22/c/ff.c
new file mode 100644
index 0000000..3ae7029
--- /dev/null
+++ b/version22/c/ff.c
@@ -0,0 +1,1150 @@
+/*
+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.
+*/
+
+/* AMCL basic functions for Large Finite Field support */
+
+#include "amcl.h"
+
+/* Arazi and Qi inversion mod 256 */
+static int invmod256(int a)
+{
+    int U,t1,t2,b,c;
+    t1=0;
+    c=(a>>1)&1;
+    t1+=c;
+    t1&=1;
+    t1=2-t1;
+    t1<<=1;
+    U=t1+1;
+
+// i=2
+    b=a&3;
+    t1=U*b;
+    t1>>=2;
+    c=(a>>2)&3;
+    t2=(U*c)&3;
+    t1+=t2;
+    t1*=U;
+    t1&=3;
+    t1=4-t1;
+    t1<<=2;
+    U+=t1;
+
+// i=4
+    b=a&15;
+    t1=U*b;
+    t1>>=4;
+    c=(a>>4)&15;
+    t2=(U*c)&15;
+    t1+=t2;
+    t1*=U;
+    t1&=15;
+    t1=16-t1;
+    t1<<=4;
+    U+=t1;
+
+    return U;
+}
+
+/* a=1/a mod 2^BIGBITS. This is very fast! */
+void BIG_invmod2m(BIG a)
+{
+    int i;
+    BIG U,t1,b,c;
+    BIG_zero(U);
+    BIG_inc(U,invmod256(BIG_lastbits(a,8)));
+    for (i=8; i<BIGBITS; i<<=1)
+    {
+        BIG_copy(b,a);
+        BIG_mod2m(b,i);   // bottom i bits of a
+
+        BIG_smul(t1,U,b);
+        BIG_shr(t1,i); // top i bits of U*b
+
+        BIG_copy(c,a);
+        BIG_shr(c,i);
+        BIG_mod2m(c,i); // top i bits of a
+
+        BIG_smul(b,U,c);
+        BIG_mod2m(b,i);  // bottom i bits of U*c
+
+        BIG_add(t1,t1,b);
+        BIG_smul(b,t1,U);
+        BIG_copy(t1,b);  // (t1+b)*U
+        BIG_mod2m(t1,i);				// bottom i bits of (t1+b)*U
+
+        BIG_one(b);
+        BIG_shl(b,i);
+        BIG_sub(t1,b,t1);
+        BIG_norm(t1);
+
+        BIG_shl(t1,i);
+
+        BIG_add(U,U,t1);
+    }
+    BIG_copy(a,U);
+    BIG_norm(a);
+    BIG_mod2m(a,BIGBITS);
+}
+
+/*
+void FF_rcopy(BIG x[],const BIG y[],int n)
+{
+	int i;
+	for (i=0;i<n;i++)
+		BIG_rcopy(x[i],y[i]);
+}
+*/
+
+/* x=y */
+void FF_copy(BIG x[],BIG y[],int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+        BIG_copy(x[i],y[i]);
+}
+
+/* x=y<<n */
+static void FF_dsucopy(BIG x[],BIG y[],int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+    {
+        BIG_copy(x[n+i],y[i]);
+        BIG_zero(x[i]);
+    }
+}
+
+/* x=y */
+static void FF_dscopy(BIG x[],BIG y[],int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+    {
+        BIG_copy(x[i],y[i]);
+        BIG_zero(x[n+i]);
+    }
+}
+
+/* x=y>>n */
+static void FF_sducopy(BIG x[],BIG y[],int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+        BIG_copy(x[i],y[n+i]);
+}
+
+/* set to zero */
+void FF_zero(BIG x[],int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+        BIG_zero(x[i]);
+}
+
+/* test equals 0 */
+int FF_iszilch(BIG x[],int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+        if (!BIG_iszilch(x[i])) return 0;
+    return 1;
+}
+
+/* shift right by BIGBITS-bit words */
+static void FF_shrw(BIG a[],int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+    {
+        BIG_copy(a[i],a[i+n]);
+        BIG_zero(a[i+n]);
+    }
+}
+
+/* shift left by BIGBITS-bit words */
+static void FF_shlw(BIG a[],int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+    {
+        BIG_copy(a[i+n],a[i]);
+        BIG_zero(a[i]);
+    }
+}
+
+/* extract last bit */
+int FF_parity(BIG x[])
+{
+    return BIG_parity(x[0]);
+}
+
+/* extract last m bits */
+int FF_lastbits(BIG x[],int m)
+{
+    return BIG_lastbits(x[0],m);
+}
+
+/* x=1 */
+void FF_one(BIG x[],int n)
+{
+    int i;
+    BIG_one(x[0]);
+    for (i=1; i<n; i++)
+        BIG_zero(x[i]);
+}
+
+/* x=m, where m is 32-bit int */
+void FF_init(BIG x[],sign32 m,int n)
+{
+    int i;
+    BIG_zero(x[0]);
+#if CHUNK<64
+    x[0][0]=(chunk)(m&BMASK);
+    x[0][1]=(chunk)(m>>BASEBITS);
+#else
+    x[0][0]=(chunk)m;
+#endif
+    for (i=1; i<n; i++)
+        BIG_zero(x[i]);
+}
+
+/* compare x and y - must be normalised */
+int FF_comp(BIG x[],BIG y[],int n)
+{
+    int i,j;
+    for (i=n-1; i>=0; i--)
+    {
+        j=BIG_comp(x[i],y[i]);
+        if (j!=0) return j;
+    }
+    return 0;
+}
+
+/* recursive add */
+static void FF_radd(BIG z[],int zp,BIG x[],int xp,BIG y[],int yp,int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+        BIG_add(z[zp+i],x[xp+i],y[yp+i]);
+}
+
+/* recursive inc */
+static void FF_rinc(BIG z[],int zp,BIG y[],int yp,int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+        BIG_add(z[zp+i],z[zp+i],y[yp+i]);
+}
+
+/* recursive sub */
+/*
+static void FF_rsub(BIG z[],int zp,BIG x[],int xp,BIG y[],int yp,int n)
+{
+	int i;
+	for (i=0;i<n;i++)
+		BIG_sub(z[zp+i],x[xp+i],y[yp+i]);
+}
+*/
+
+/* recursive dec */
+static void FF_rdec(BIG z[],int zp,BIG y[],int yp,int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+        BIG_sub(z[zp+i],z[zp+i],y[yp+i]);
+}
+
+/* simple add */
+void FF_add(BIG z[],BIG x[],BIG y[],int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+        BIG_add(z[i],x[i],y[i]);
+}
+
+/* simple sub */
+void FF_sub(BIG z[],BIG x[],BIG y[],int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+        BIG_sub(z[i],x[i],y[i]);
+}
+
+/* increment/decrement by a small integer */
+void FF_inc(BIG x[],int m,int n)
+{
+    BIG_inc(x[0],m);
+    FF_norm(x,n);
+}
+
+void FF_dec(BIG x[],int m,int n)
+{
+    BIG_dec(x[0],m);
+    FF_norm(x,n);
+}
+
+/* normalise - but hold any overflow in top part unless n<0 */
+static void FF_rnorm(BIG z[],int zp,int n)
+{
+    int i,trunc=0;
+    chunk carry;
+    if (n<0)
+    {
+        /* -v n signals to do truncation */
+        n=-n;
+        trunc=1;
+    }
+    for (i=0; i<n-1; i++)
+    {
+        carry=BIG_norm(z[zp+i]);
+
+        z[zp+i][NLEN-1]^=carry<<P_TBITS; /* remove it */
+        z[zp+i+1][0]+=carry;
+    }
+    carry=BIG_norm(z[zp+n-1]);
+    if (trunc) z[zp+n-1][NLEN-1]^=carry<<P_TBITS;
+}
+
+void FF_norm(BIG z[],int n)
+{
+    FF_rnorm(z,0,n);
+}
+
+/* shift left by one bit */
+void FF_shl(BIG x[],int n)
+{
+    int i;
+    int carry,delay_carry=0;
+    for (i=0; i<n-1; i++)
+    {
+        carry=BIG_fshl(x[i],1);
+        x[i][0]|=delay_carry;
+        x[i][NLEN-1]^=(chunk)carry<<P_TBITS;
+        delay_carry=carry;
+    }
+    BIG_fshl(x[n-1],1);
+    x[n-1][0]|=delay_carry;
+}
+
+/* shift right by one bit */
+void FF_shr(BIG x[],int n)
+{
+    int i;
+    int carry;
+    for (i=n-1; i>0; i--)
+    {
+        carry=BIG_fshr(x[i],1);
+        x[i-1][NLEN-1]|=(chunk)carry<<P_TBITS;
+    }
+    BIG_fshr(x[0],1);
+}
+
+void FF_output(BIG x[],int n)
+{
+    int i;
+    FF_norm(x,n);
+    for (i=n-1; i>=0; i--)
+    {
+        BIG_output(x[i]);
+        printf(" ");
+    }
+}
+
+void FF_rawoutput(BIG x[],int n)
+{
+    int i;
+    for (i=n-1; i>=0; i--)
+    {
+        BIG_rawoutput(x[i]);
+        printf(" ");
+    }
+}
+
+/* Convert FFs to/from octet strings */
+void FF_toOctet(octet *w,BIG x[],int n)
+{
+    int i;
+    w->len=n*MODBYTES;
+    for (i=0; i<n; i++)
+    {
+        BIG_toBytes(&(w->val[(n-i-1)*MODBYTES]),x[i]);
+    }
+}
+
+void FF_fromOctet(BIG x[],octet *w,int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+    {
+        BIG_fromBytes(x[i],&(w->val[(n-i-1)*MODBYTES]));
+    }
+}
+
+/* in-place swapping using xor - side channel resistant */
+static void FF_cswap(BIG a[],BIG b[],int d,int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+        BIG_cswap(a[i],b[i],d);
+    return;
+}
+
+/* z=x*y, t is workspace */
+static void FF_karmul(BIG z[],int zp,BIG x[],int xp,BIG y[],int yp,BIG t[],int tp,int n)
+{
+    int nd2;
+    if (n==1)
+    {
+        BIG_mul(t[tp],x[xp],y[yp]);
+        BIG_split(z[zp+1],z[zp],t[tp],BIGBITS);
+        return;
+    }
+
+    nd2=n/2;
+    FF_radd(z,zp,x,xp,x,xp+nd2,nd2);
+    FF_rnorm(z,zp,nd2);  /* needs this if recursion level too deep */
+
+    FF_radd(z,zp+nd2,y,yp,y,yp+nd2,nd2);
+    FF_rnorm(z,zp+nd2,nd2);
+    FF_karmul(t,tp,z,zp,z,zp+nd2,t,tp+n,nd2);
+    FF_karmul(z,zp,x,xp,y,yp,t,tp+n,nd2);
+    FF_karmul(z,zp+n,x,xp+nd2,y,yp+nd2,t,tp+n,nd2);
+    FF_rdec(t,tp,z,zp,n);
+    FF_rdec(t,tp,z,zp+n,n);
+    FF_rinc(z,zp+nd2,t,tp,n);
+    FF_rnorm(z,zp,2*n);
+}
+
+static void FF_karsqr(BIG z[],int zp,BIG x[],int xp,BIG t[],int tp,int n)
+{
+    int nd2;
+    if (n==1)
+    {
+        BIG_sqr(t[tp],x[xp]);
+        BIG_split(z[zp+1],z[zp],t[tp],BIGBITS);
+        return;
+    }
+    nd2=n/2;
+    FF_karsqr(z,zp,x,xp,t,tp+n,nd2);
+    FF_karsqr(z,zp+n,x,xp+nd2,t,tp+n,nd2);
+    FF_karmul(t,tp,x,xp,x,xp+nd2,t,tp+n,nd2);
+    FF_rinc(z,zp+nd2,t,tp,n);
+    FF_rinc(z,zp+nd2,t,tp,n);
+
+    FF_rnorm(z,zp+nd2,n);  /* was FF_rnorm(z,zp,2*n)  */
+}
+
+static void FF_karmul_lower(BIG z[],int zp,BIG x[],int xp,BIG y[],int yp,BIG t[],int tp,int n)
+{
+    /* Calculates Least Significant bottom half of x*y */
+    int nd2;
+    if (n==1)
+    {
+        /* only calculate bottom half of product */
+        BIG_smul(z[zp],x[xp],y[yp]);
+        return;
+    }
+    nd2=n/2;
+    FF_karmul(z,zp,x,xp,y,yp,t,tp+n,nd2);
+    FF_karmul_lower(t,tp,x,xp+nd2,y,yp,t,tp+n,nd2);
+    FF_rinc(z,zp+nd2,t,tp,nd2);
+    FF_karmul_lower(t,tp,x,xp,y,yp+nd2,t,tp+n,nd2);
+    FF_rinc(z,zp+nd2,t,tp,nd2);
+    FF_rnorm(z,zp+nd2,-nd2);  /* truncate it */
+}
+
+static void FF_karmul_upper(BIG z[],BIG x[],BIG y[],BIG t[],int n)
+{
+    /* Calculates Most Significant upper half of x*y, given lower part */
+    int nd2;
+
+    nd2=n/2;
+    FF_radd(z,n,x,0,x,nd2,nd2);
+    FF_radd(z,n+nd2,y,0,y,nd2,nd2);
+    FF_rnorm(z,n,nd2);
+    FF_rnorm(z,n+nd2,nd2);
+
+    FF_karmul(t,0,z,n+nd2,z,n,t,n,nd2);  /* t = (a0+a1)(b0+b1) */
+    FF_karmul(z,n,x,nd2,y,nd2,t,n,nd2); /* z[n]= a1*b1 */
+    /* z[0-nd2]=l(a0b0) z[nd2-n]= h(a0b0)+l(t)-l(a0b0)-l(a1b1) */
+    FF_rdec(t,0,z,n,n);              /* t=t-a1b1  */
+    FF_rinc(z,nd2,z,0,nd2);   /* z[nd2-n]+=l(a0b0) = h(a0b0)+l(t)-l(a1b1)  */
+    FF_rdec(z,nd2,t,0,nd2);   /* z[nd2-n]=h(a0b0)+l(t)-l(a1b1)-l(t-a1b1)=h(a0b0) */
+    FF_rnorm(z,0,-n);					/* a0b0 now in z - truncate it */
+    FF_rdec(t,0,z,0,n);         /* (a0+a1)(b0+b1) - a0b0 */
+    FF_rinc(z,nd2,t,0,n);
+
+    FF_rnorm(z,nd2,n);
+}
+
+/* z=x*y */
+void FF_mul(BIG z[],BIG x[],BIG y[],int n)
+{
+#ifndef C99
+    BIG t[2*FFLEN];
+#else
+    BIG t[2*n];
+#endif
+//	FF_norm(x,n); /* change here */
+//	FF_norm(y,n); /* change here */
+    FF_karmul(z,0,x,0,y,0,t,0,n);
+}
+
+/* return low part of product */
+static void FF_lmul(BIG z[],BIG x[],BIG y[],int n)
+{
+#ifndef C99
+    BIG t[2*FFLEN];
+#else
+    BIG t[2*n];
+#endif
+//	FF_norm(x,n); /* change here */
+//	FF_norm(y,n); /* change here */
+    FF_karmul_lower(z,0,x,0,y,0,t,0,n);
+}
+
+/* Set b=b mod c */
+void FF_mod(BIG b[],BIG c[],int n)
+{
+    int k=0;
+
+    FF_norm(b,n);
+    if (FF_comp(b,c,n)<0)
+        return;
+    do
+    {
+        FF_shl(c,n);
+        k++;
+    }
+    while (FF_comp(b,c,n)>=0);
+
+    while (k>0)
+    {
+        FF_shr(c,n);
+        if (FF_comp(b,c,n)>=0)
+        {
+            FF_sub(b,b,c,n);
+            FF_norm(b,n);
+        }
+        k--;
+    }
+}
+
+/* z=x^2 */
+void FF_sqr(BIG z[],BIG x[],int n)
+{
+#ifndef C99
+    BIG t[2*FFLEN];
+#else
+    BIG t[2*n];
+#endif
+//	FF_norm(x,n); /* change here */
+    FF_karsqr(z,0,x,0,t,0,n);
+}
+
+/* r=t mod modulus, N is modulus, ND is Montgomery Constant */
+static void FF_reduce(BIG r[],BIG T[],BIG N[],BIG ND[],int n)
+{
+    /* fast karatsuba Montgomery reduction */
+#ifndef C99
+    BIG t[2*FFLEN];
+    BIG m[FFLEN];
+#else
+    BIG t[2*n];
+    BIG m[n];
+#endif
+    FF_sducopy(r,T,n);  /* keep top half of T */
+    //FF_norm(T,n); /* change here */
+    FF_karmul_lower(m,0,T,0,ND,0,t,0,n);  /* m=T.(1/N) mod R */
+
+    //FF_norm(N,n);  /* change here */
+    FF_karmul_upper(T,N,m,t,n);  /* T=mN */
+    FF_sducopy(m,T,n);
+
+    FF_add(r,r,N,n);
+    FF_sub(r,r,m,n);
+    FF_norm(r,n);
+}
+
+
+/* Set r=a mod b */
+/* a is of length - 2*n */
+/* r,b is of length - n */
+void FF_dmod(BIG r[],BIG a[],BIG b[],int n)
+{
+    int k;
+#ifndef C99
+    BIG m[2*FFLEN];
+    BIG x[2*FFLEN];
+#else
+    BIG m[2*n];
+    BIG x[2*n];
+#endif
+    FF_copy(x,a,2*n);
+    FF_norm(x,2*n);
+    FF_dsucopy(m,b,n);
+    k=BIGBITS*n;
+
+    while (FF_comp(x,m,2*n)>=0)
+    {
+        FF_sub(x,x,m,2*n);
+        FF_norm(x,2*n);
+    }
+
+    while (k>0)
+    {
+        FF_shr(m,2*n);
+
+        if (FF_comp(x,m,2*n)>=0)
+        {
+            FF_sub(x,x,m,2*n);
+            FF_norm(x,2*n);
+        }
+
+        k--;
+    }
+    FF_copy(r,x,n);
+    FF_mod(r,b,n);
+}
+
+/* Set r=1/a mod p. Binary method - a<p on entry */
+
+void FF_invmodp(BIG r[],BIG a[],BIG p[],int n)
+{
+#ifndef C99
+    BIG u[FFLEN],v[FFLEN],x1[FFLEN],x2[FFLEN],t[FFLEN],one[FFLEN];
+#else
+    BIG u[n],v[n],x1[n],x2[n],t[n],one[n];
+#endif
+    FF_copy(u,a,n);
+    FF_copy(v,p,n);
+    FF_one(one,n);
+    FF_copy(x1,one,n);
+    FF_zero(x2,n);
+
+// reduce n in here as well!
+    while (FF_comp(u,one,n)!=0 && FF_comp(v,one,n)!=0)
+    {
+        while (FF_parity(u)==0)
+        {
+            FF_shr(u,n);
+            if (FF_parity(x1)!=0)
+            {
+                FF_add(x1,p,x1,n);
+                FF_norm(x1,n);
+            }
+            FF_shr(x1,n);
+        }
+        while (FF_parity(v)==0)
+        {
+            FF_shr(v,n);
+            if (FF_parity(x2)!=0)
+            {
+                FF_add(x2,p,x2,n);
+                FF_norm(x2,n);
+            }
+            FF_shr(x2,n);
+        }
+        if (FF_comp(u,v,n)>=0)
+        {
+
+            FF_sub(u,u,v,n);
+            FF_norm(u,n);
+            if (FF_comp(x1,x2,n)>=0) FF_sub(x1,x1,x2,n);
+            else
+            {
+                FF_sub(t,p,x2,n);
+                FF_add(x1,x1,t,n);
+            }
+            FF_norm(x1,n);
+        }
+        else
+        {
+            FF_sub(v,v,u,n);
+            FF_norm(v,n);
+            if (FF_comp(x2,x1,n)>=0) FF_sub(x2,x2,x1,n);
+            else
+            {
+                FF_sub(t,p,x1,n);
+                FF_add(x2,x2,t,n);
+            }
+            FF_norm(x2,n);
+        }
+    }
+    if (FF_comp(u,one,n)==0)
+        FF_copy(r,x1,n);
+    else
+        FF_copy(r,x2,n);
+}
+
+/* nesidue mod m */
+static void FF_nres(BIG a[],BIG m[],int n)
+{
+#ifndef C99
+    BIG d[2*FFLEN];
+#else
+    BIG d[2*n];
+#endif
+
+	if (n==1)
+	{
+		BIG_dscopy(d[0],a[0]);
+		BIG_dshl(d[0],NLEN*BASEBITS);
+		BIG_dmod(a[0],d[0],m[0]);
+	}
+	else
+	{ 
+		FF_dsucopy(d,a,n);
+		FF_dmod(a,d,m,n);
+	}
+}
+
+static void FF_redc(BIG a[],BIG m[],BIG ND[],int n)
+{
+#ifndef C99
+    BIG d[2*FFLEN];
+#else
+    BIG d[2*n];
+#endif
+	if (n==1)
+	{
+		BIG_dzero(d[0]);
+		BIG_dscopy(d[0],a[0]);
+		BIG_monty(a[0],m[0],((chunk)1<<BASEBITS)-ND[0][0],d[0]);		
+	}
+	else
+	{
+		FF_mod(a,m,n);
+		FF_dscopy(d,a,n);
+		FF_reduce(a,d,m,ND,n);
+		FF_mod(a,m,n);
+	}
+}
+
+/* U=1/a mod 2^m - Arazi & Qi */
+static void FF_invmod2m(BIG U[],BIG a[],int n)
+{
+    int i;
+#ifndef C99
+    BIG t1[FFLEN],b[FFLEN],c[FFLEN];
+#else
+    BIG t1[2*n],b[n],c[n];
+#endif
+
+    FF_zero(U,n);
+    FF_zero(b,n);
+    FF_zero(c,n);
+    FF_zero(t1,2*n);
+
+    BIG_copy(U[0],a[0]);
+    BIG_invmod2m(U[0]);
+    for (i=1; i<n; i<<=1)
+    {
+        FF_copy(b,a,i);
+        FF_mul(t1,U,b,i);
+        FF_shrw(t1,i); // top half to bottom half, top half=0
+
+        FF_copy(c,a,2*i);
+        FF_shrw(c,i); // top half of c
+        FF_lmul(b,U,c,i); // should set top half of b=0
+        FF_add(t1,t1,b,i);
+        FF_norm(t1,2*i);
+        FF_lmul(b,t1,U,i);
+        FF_copy(t1,b,i);
+        FF_one(b,i);
+        FF_shlw(b,i);
+        FF_sub(t1,b,t1,2*i);
+        FF_norm(t1,2*i);
+        FF_shlw(t1,i);
+        FF_add(U,U,t1,2*i);
+    }
+
+    FF_norm(U,n);
+}
+
+void FF_random(BIG x[],csprng *rng,int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+    {
+        BIG_random(x[i],rng);
+    }
+    /* make sure top bit is 1 */
+    while (BIG_nbits(x[n-1])<MODBYTES*8) BIG_random(x[n-1],rng);
+}
+
+/* generate random x mod p */
+void FF_randomnum(BIG x[],BIG p[],csprng *rng,int n)
+{
+    int i;
+#ifndef C99
+    BIG d[2*FFLEN];
+#else
+    BIG d[2*n];
+#endif
+    for (i=0; i<2*n; i++)
+    {
+        BIG_random(d[i],rng);
+    }
+    FF_dmod(x,d,p,n);
+}
+
+static void FF_modmul(BIG z[],BIG x[],BIG y[],BIG p[],BIG ND[],int n)
+{
+#ifndef C99
+    BIG d[2*FFLEN];
+#else
+    BIG d[2*n];
+#endif
+    chunk ex=P_EXCESS(x[n-1]);
+    chunk ey=P_EXCESS(y[n-1]);
+#ifdef dchunk
+    if ((dchunk)(ex+1)*(ey+1)>(dchunk)P_FEXCESS)
+#else
+    if ((ex+1)>P_FEXCESS/(ey+1))
+#endif
+    {
+#ifdef DEBUG_REDUCE
+        printf("Product too large - reducing it %d %d\n",ex,ey);
+#endif
+        FF_mod(x,p,n);
+    }
+
+	if (n==1)
+	{
+		BIG_mul(d[0],x[0],y[0]);
+		BIG_monty(z[0],p[0],((chunk)1<<BASEBITS)-ND[0][0],d[0]);
+	}
+	else
+	{
+		FF_mul(d,x,y,n);
+		FF_reduce(z,d,p,ND,n);
+	}
+}
+
+static void FF_modsqr(BIG z[],BIG x[],BIG p[],BIG ND[],int n)
+{
+#ifndef C99
+    BIG d[2*FFLEN];
+#else
+    BIG d[2*n];
+#endif
+    chunk ex=P_EXCESS(x[n-1]);
+#ifdef dchunk
+    if ((dchunk)(ex+1)*(ex+1)>(dchunk)P_FEXCESS)
+#else
+    if ((ex+1)>P_FEXCESS/(ex+1))
+#endif
+    {
+#ifdef DEBUG_REDUCE
+        printf("Product too large - reducing it %d\n",ex);
+#endif
+        FF_mod(x,p,n);
+    }
+
+	if (n==1)
+	{
+		BIG_sqr(d[0],x[0]);
+		BIG_monty(z[0],p[0],((chunk)1<<BASEBITS)-ND[0][0],d[0]);
+	}
+	else
+	{
+		FF_sqr(d,x,n);
+		FF_reduce(z,d,p,ND,n);
+	}
+}
+
+/* r=x^e mod p using side-channel resistant Montgomery Ladder, for large e */
+void FF_skpow(BIG r[],BIG x[],BIG e[],BIG p[],int n)
+{
+    int i,b;
+#ifndef C99
+    BIG R0[FFLEN],R1[FFLEN],ND[FFLEN];
+#else
+    BIG R0[n],R1[n],ND[n];
+#endif
+    FF_invmod2m(ND,p,n);
+
+    FF_one(R0,n);
+    FF_copy(R1,x,n);
+    FF_nres(R0,p,n);
+    FF_nres(R1,p,n);
+
+    for (i=8*MODBYTES*n-1; i>=0; i--)
+    {
+        b=BIG_bit(e[i/BIGBITS],i%BIGBITS);
+        FF_modmul(r,R0,R1,p,ND,n);
+
+        FF_cswap(R0,R1,b,n);
+        FF_modsqr(R0,R0,p,ND,n);
+
+        FF_copy(R1,r,n);
+        FF_cswap(R0,R1,b,n);
+    }
+    FF_copy(r,R0,n);
+    FF_redc(r,p,ND,n);
+}
+
+/* r=x^e mod p using side-channel resistant Montgomery Ladder, for short e */
+void FF_skspow(BIG r[],BIG x[],BIG e,BIG p[],int n)
+{
+    int i,b;
+#ifndef C99
+    BIG R0[FFLEN],R1[FFLEN],ND[FFLEN];
+#else
+    BIG R0[n],R1[n],ND[n];
+#endif
+    FF_invmod2m(ND,p,n);
+    FF_one(R0,n);
+    FF_copy(R1,x,n);
+    FF_nres(R0,p,n);
+    FF_nres(R1,p,n);
+    for (i=8*MODBYTES-1; i>=0; i--)
+    {
+        b=BIG_bit(e,i);
+        FF_modmul(r,R0,R1,p,ND,n);
+        FF_cswap(R0,R1,b,n);
+        FF_modsqr(R0,R0,p,ND,n);
+        FF_copy(R1,r,n);
+        FF_cswap(R0,R1,b,n);
+    }
+    FF_copy(r,R0,n);
+    FF_redc(r,p,ND,n);
+}
+
+/* raise to an integer power - right-to-left method */
+void FF_power(BIG r[],BIG x[],int e,BIG p[],int n)
+{
+    int f=1;
+#ifndef C99
+    BIG w[FFLEN],ND[FFLEN];
+#else
+    BIG w[n],ND[n];
+#endif
+    FF_invmod2m(ND,p,n);
+
+    FF_copy(w,x,n);
+    FF_nres(w,p,n);
+
+    if (e==2)
+    {
+        FF_modsqr(r,w,p,ND,n);
+    }
+    else for (;;)
+        {
+            if (e%2==1)
+            {
+                if (f) FF_copy(r,w,n);
+                else FF_modmul(r,r,w,p,ND,n);
+                f=0;
+            }
+            e>>=1;
+            if (e==0) break;
+            FF_modsqr(w,w,p,ND,n);
+        }
+
+    FF_redc(r,p,ND,n);
+}
+
+/* r=x^e mod p, faster but not side channel resistant */
+void FF_pow(BIG r[],BIG x[],BIG e[],BIG p[],int n)
+{
+    int i,b;
+#ifndef C99
+    BIG w[FFLEN],ND[FFLEN];
+#else
+    BIG w[n],ND[n];
+#endif
+    FF_invmod2m(ND,p,n);
+
+    FF_copy(w,x,n);
+    FF_one(r,n);
+    FF_nres(r,p,n);
+    FF_nres(w,p,n);
+
+    for (i=8*MODBYTES*n-1; i>=0; i--)
+    {
+        FF_modsqr(r,r,p,ND,n);
+        b=BIG_bit(e[i/BIGBITS],i%BIGBITS);
+        if (b==1) FF_modmul(r,r,w,p,ND,n);
+    }
+    FF_redc(r,p,ND,n);
+}
+
+/* double exponentiation r=x^e.y^f mod p */
+void FF_pow2(BIG r[],BIG x[],BIG e,BIG y[],BIG f,BIG p[],int n)
+{
+    int i,eb,fb;
+#ifndef C99
+    BIG xn[FFLEN],yn[FFLEN],xy[FFLEN],ND[FFLEN];
+#else
+    BIG xn[n],yn[n],xy[n],ND[n];
+#endif
+
+    FF_invmod2m(ND,p,n);
+
+    FF_copy(xn,x,n);
+    FF_copy(yn,y,n);
+    FF_nres(xn,p,n);
+    FF_nres(yn,p,n);
+    FF_modmul(xy,xn,yn,p,ND,n);
+    FF_one(r,n);
+    FF_nres(r,p,n);
+
+    for (i=8*MODBYTES-1; i>=0; i--)
+    {
+        eb=BIG_bit(e,i);
+        fb=BIG_bit(f,i);
+        FF_modsqr(r,r,p,ND,n);
+        if (eb==1)
+        {
+            if (fb==1) FF_modmul(r,r,xy,p,ND,n);
+            else FF_modmul(r,r,xn,p,ND,n);
+        }
+        else
+        {
+            if (fb==1) FF_modmul(r,r,yn,p,ND,n);
+        }
+    }
+    FF_redc(r,p,ND,n);
+}
+
+static sign32 igcd(sign32 x,sign32 y)
+{
+    /* integer GCD, returns GCD of x and y */
+    sign32 r;
+    if (y==0) return x;
+    while ((r=x%y)!=0)
+        x=y,y=r;
+    return y;
+}
+
+/* quick and dirty check for common factor with s */
+int FF_cfactor(BIG w[],sign32 s,int n)
+{
+    int r;
+    sign32 g;
+#ifndef C99
+    BIG x[FFLEN],y[FFLEN];
+#else
+    BIG x[n],y[n];
+#endif
+    FF_init(y,s,n);
+    FF_copy(x,w,n);
+    FF_norm(x,n);
+
+//	if (FF_parity(x)==0) return 1;
+    do
+    {
+        FF_sub(x,x,y,n);
+        FF_norm(x,n);
+        while (!FF_iszilch(x,n) && FF_parity(x)==0) FF_shr(x,n);
+    }
+    while (FF_comp(x,y,n)>0);
+#if CHUNK<32
+    g=x[0][0]+((sign32)(x[0][1])<<BASEBITS);
+#else
+    g=(sign32)x[0][0];
+#endif
+    r=igcd(s,g);
+    if (r>1) return 1;
+    return 0;
+}
+
+/* Miller-Rabin test for primality. Slow. */
+int FF_prime(BIG p[],csprng *rng,int n)
+{
+    int i,j,loop,s=0;
+#ifndef C99
+    BIG d[FFLEN],x[FFLEN],unity[FFLEN],nm1[FFLEN];
+#else
+    BIG d[n],x[n],unity[n],nm1[n];
+#endif
+    sign32 sf=4849845;/* 3*5*.. *19 */
+
+    FF_norm(p,n);
+
+    if (FF_cfactor(p,sf,n)) return 0;
+
+    FF_one(unity,n);
+    FF_sub(nm1,p,unity,n);
+    FF_norm(nm1,n);
+    FF_copy(d,nm1,n);
+    while (FF_parity(d)==0)
+    {
+        FF_shr(d,n);
+        s++;
+    }
+    if (s==0) return 0;
+
+    for (i=0; i<10; i++)
+    {
+        FF_randomnum(x,p,rng,n);
+        FF_pow(x,x,d,p,n);
+        if (FF_comp(x,unity,n)==0 || FF_comp(x,nm1,n)==0) continue;
+        loop=0;
+        for (j=1; j<s; j++)
+        {
+            FF_power(x,x,2,p,n);
+            if (FF_comp(x,unity,n)==0) return 0;
+            if (FF_comp(x,nm1,n)==0 )
+            {
+                loop=1;
+                break;
+            }
+        }
+        if (loop) continue;
+        return 0;
+    }
+
+    return 1;
+}
+
+/*
+BIG P[4]= {{0x1670957,0x1568CD3C,0x2595E5,0xEED4F38,0x1FC9A971,0x14EF7E62,0xA503883,0x9E1E05E,0xBF59E3},{0x1844C908,0x1B44A798,0x3A0B1E7,0xD1B5B4E,0x1836046F,0x87E94F9,0x1D34C537,0xF7183B0,0x46D07},{0x17813331,0x19E28A90,0x1473A4D6,0x1CACD01F,0x1EEA8838,0xAF2AE29,0x1F85292A,0x1632585E,0xD945E5},{0x919F5EF,0x1567B39F,0x19F6AD11,0x16CE47CF,0x9B36EB1,0x35B7D3,0x483B28C,0xCBEFA27,0xB5FC21}};
+
+int main()
+{
+	int i;
+	BIG p[4],e[4],x[4],r[4];
+	csprng rng;
+	char raw[100];
+	for (i=0;i<100;i++) raw[i]=i;
+    RAND_seed(&rng,100,raw);
+
+
+	FF_init(x,3,4);
+
+	FF_copy(p,P,4);
+	FF_copy(e,p,4);
+	FF_dec(e,1,4);
+	FF_norm(e,4);
+
+
+
+	printf("p= ");FF_output(p,4); printf("\n");
+	if (FF_prime(p,&rng,4)) printf("p is a prime\n");
+	printf("e= ");FF_output(e,4); printf("\n");
+
+	FF_skpow(r,x,e,p,4);
+	printf("r= ");FF_output(r,4); printf("\n");
+}
+
+*/
diff --git a/version22/c/fp.c b/version22/c/fp.c
new file mode 100644
index 0000000..5d48f1c
--- /dev/null
+++ b/version22/c/fp.c
@@ -0,0 +1,608 @@
+/*
+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.
+*/
+
+/* AMCL mod p functions */
+/* Small Finite Field arithmetic */
+/* SU=m, SU is Stack Usage (NOT_SPECIAL Modulus) */
+
+#include "amcl.h"
+
+/* Fast Modular Reduction Methods */
+
+/* r=d mod m */
+/* d MUST be normalised */
+/* Products must be less than pR in all cases !!! */
+/* So when multiplying two numbers, their product *must* be less than MODBITS+BASEBITS*NLEN */
+/* Results *may* be one bit bigger than MODBITS */
+
+#if MODTYPE == PSEUDO_MERSENNE
+/* r=d mod m */
+
+/* Converts from BIG integer to n-residue form mod Modulus */
+void FP_nres(BIG a)
+{
+    BIG tmp;
+    BIG_rcopy(tmp,a);
+}
+
+/* Converts from n-residue form back to BIG integer form */
+void FP_redc(BIG a)
+{
+    BIG tmp;
+    BIG_rcopy(tmp,a);
+}
+
+/* reduce a DBIG to a BIG exploiting the special form of the modulus */
+void FP_mod(BIG r,DBIG d)
+{
+    BIG t,b;
+    chunk v,tw;
+    BIG_split(t,b,d,MODBITS);
+
+    /* Note that all of the excess gets pushed into t. So if squaring a value with a 4-bit excess, this results in
+       t getting all 8 bits of the excess product! So products must be less than pR which is Montgomery compatible */
+
+    if (MConst < NEXCESS)
+    {
+        BIG_imul(t,t,MConst);
+
+        BIG_norm(t);
+        tw=t[NLEN-1];
+        t[NLEN-1]&=TMASK;
+        t[0]+=MConst*((tw>>TBITS));
+    }
+    else
+    {
+        v=BIG_pmul(t,t,MConst);
+        tw=t[NLEN-1];
+        t[NLEN-1]&=TMASK;
+#if CHUNK == 16
+        t[1]+=muladd(MConst,((tw>>TBITS)+(v<<(BASEBITS-TBITS))),0,&t[0]);
+#else
+        t[0]+=MConst*((tw>>TBITS)+(v<<(BASEBITS-TBITS)));
+#endif
+    }
+    BIG_add(r,t,b);
+    BIG_norm(r);
+}
+#endif
+
+/* This only applies to Curve C448, so specialised (for now) */
+#if MODTYPE == GENERALISED_MERSENNE
+
+/* Converts from BIG integer to n-residue form mod Modulus */
+void FP_nres(BIG a)
+{
+    BIG tmp;
+    BIG_rcopy(tmp,a);
+}
+
+/* Converts from n-residue form back to BIG integer form */
+void FP_redc(BIG a)
+{
+    BIG tmp;
+    BIG_rcopy(tmp,a);
+}
+
+/* reduce a DBIG to a BIG exploiting the special form of the modulus */
+void FP_mod(BIG r,DBIG d)
+{
+    BIG t,b;
+    chunk carry;
+    BIG_split(t,b,d,MBITS);
+
+    BIG_add(r,t,b);
+
+    BIG_dscopy(d,t);
+    BIG_dshl(d,MBITS/2);
+
+    BIG_split(t,b,d,MBITS);
+
+    BIG_add(r,r,t);
+    BIG_add(r,r,b);
+    BIG_norm(r);
+    BIG_shl(t,MBITS/2);
+
+    BIG_add(r,r,t);
+
+    carry=r[NLEN-1]>>TBITS;
+
+    r[NLEN-1]&=TMASK;
+    r[0]+=carry;
+
+    r[224/BASEBITS]+=carry<<(224%BASEBITS); /* need to check that this falls mid-word */
+    BIG_norm(r);
+
+}
+
+#endif
+
+#if MODTYPE == MONTGOMERY_FRIENDLY
+
+/* convert to Montgomery n-residue form */
+void FP_nres(BIG a)
+{
+    DBIG d;
+    BIG m;
+    BIG_rcopy(m,Modulus);
+    BIG_dscopy(d,a);
+    BIG_dshl(d,NLEN*BASEBITS);
+    BIG_dmod(a,d,m);
+}
+
+/* convert back to regular form */
+void FP_redc(BIG a)
+{
+    DBIG d;
+    BIG_dzero(d);
+    BIG_dscopy(d,a);
+    FP_mod(a,d);
+}
+
+/* fast modular reduction from DBIG to BIG exploiting special form of the modulus */
+void FP_mod(BIG a,DBIG d)
+{
+    int i;
+
+    for (i=0; i<NLEN; i++)
+        d[NLEN+i]+=muladd(d[i],MConst-1,d[i],&d[NLEN+i-1]);
+
+    BIG_sducopy(a,d);
+    BIG_norm(a);
+}
+
+#endif
+
+#if MODTYPE == NOT_SPECIAL
+
+/* convert BIG a to Montgomery n-residue form */
+/* SU= 120 */
+void FP_nres(BIG a)
+{
+    DBIG d;
+    BIG m;
+    BIG_rcopy(m,Modulus);
+    BIG_dscopy(d,a);
+    BIG_dshl(d,NLEN*BASEBITS);
+    BIG_dmod(a,d,m);
+}
+
+/* SU= 80 */
+/* convert back to regular form */
+void FP_redc(BIG a)
+{
+    DBIG d;
+    BIG_dzero(d);
+    BIG_dscopy(d,a);
+    FP_mod(a,d);
+}
+
+/* reduce a DBIG to a BIG using Montgomery's no trial division method */
+/* d is expected to be dnormed before entry */
+/* SU= 112 */
+void FP_mod(BIG a,DBIG d)
+{
+	BIG mdls;
+    BIG_rcopy(mdls,Modulus);
+	BIG_monty(a,mdls,MConst,d);
+}
+
+#endif
+
+/* test x==0 ? */
+/* SU= 48 */
+int FP_iszilch(BIG x)
+{
+    BIG m;
+    BIG_rcopy(m,Modulus);
+    BIG_mod(x,m);
+    return BIG_iszilch(x);
+}
+
+/* output FP */
+/* SU= 48 */
+void FP_output(BIG r)
+{
+    BIG c;
+    BIG_copy(c,r);
+    FP_redc(c);
+    BIG_output(c);
+}
+
+void FP_rawoutput(BIG r)
+{
+    BIG_rawoutput(r);
+}
+
+#ifdef GET_STATS
+int tsqr=0,rsqr=0,tmul=0,rmul=0;
+int tadd=0,radd=0,tneg=0,rneg=0;
+int tdadd=0,rdadd=0,tdneg=0,rdneg=0;
+#endif
+
+/* r=a*b mod Modulus */
+/* product must be less that p.R - and we need to know this in advance! */
+/* SU= 88 */
+void FP_mul(BIG r,BIG a,BIG b)
+{
+    DBIG d;
+    chunk ea,eb;
+    BIG_norm(a);
+    BIG_norm(b);
+    ea=EXCESS(a);
+    eb=EXCESS(b);
+
+#ifdef dchunk
+    if ((dchunk)(ea+1)*(eb+1)>(dchunk)FEXCESS)
+#else
+    if ((ea+1)>FEXCESS/(eb+1))
+#endif
+    {
+#ifdef DEBUG_REDUCE
+        printf("Product too large - reducing it %d %d %d\n",ea,eb,FEXCESS);
+#endif
+        FP_reduce(a);  /* it is sufficient to fully reduce just one of them < p */
+#ifdef GET_STATS
+        rmul++;
+    }
+
+    tmul++;
+#else
+    }
+#endif
+
+    BIG_mul(d,a,b);
+    FP_mod(r,d);
+}
+
+/* multiplication by an integer, r=a*c */
+/* SU= 136 */
+void FP_imul(BIG r,BIG a,int c)
+{
+    DBIG d;
+    BIG m;
+    int s=0;
+    chunk afx;
+    BIG_norm(a);
+    if (c<0)
+    {
+        c=-c;
+        s=1;
+    }
+    afx=(EXCESS(a)+1)*(c+1)+1;
+    if (c<NEXCESS && afx<FEXCESS)
+        BIG_imul(r,a,c);
+    else
+    {
+        if (afx<FEXCESS)
+        {
+            BIG_pmul(r,a,c);
+        }
+        else
+        {
+            BIG_rcopy(m,Modulus);
+            BIG_pxmul(d,a,c);
+            BIG_dmod(r,d,m);
+        }
+    }
+    if (s) FP_neg(r,r);
+    BIG_norm(r);
+}
+
+/* Set r=a^2 mod m */
+/* SU= 88 */
+void FP_sqr(BIG r,BIG a)
+{
+    DBIG d;
+    chunk ea;
+    BIG_norm(a);
+    ea=EXCESS(a);
+#ifdef dchunk
+    if ((dchunk)(ea+1)*(ea+1)>(dchunk)FEXCESS)
+#else
+    if ((ea+1)>FEXCESS/(ea+1))
+#endif
+    {
+#ifdef DEBUG_REDUCE
+        printf("Product too large - reducing it %d\n",ea);
+#endif
+        FP_reduce(a);
+#ifdef GET_STATS
+        rsqr++;
+    }
+    tsqr++;
+#else
+    }
+#endif
+
+    BIG_sqr(d,a);
+    FP_mod(r,d);
+}
+
+/* SU= 16 */
+/* Set r=a+b */
+void FP_add(BIG r,BIG a,BIG b)
+{
+    BIG_add(r,a,b);
+    if (EXCESS(r)+2>=FEXCESS)  /* +2 because a and b not normalised */
+    {
+#ifdef DEBUG_REDUCE
+        printf("Sum too large - reducing it %d\n",EXCESS(r));
+#endif
+        FP_reduce(r);
+#ifdef GET_STATS
+        radd++;
+    }
+    tadd++;
+#else
+    }
+#endif
+}
+
+/* Set r=a-b mod m */
+/* SU= 56 */
+void FP_sub(BIG r,BIG a,BIG b)
+{
+    BIG n;
+    FP_neg(n,b);
+    FP_add(r,a,n);
+}
+
+/* SU= 48 */
+/* Fully reduce a mod Modulus */
+void FP_reduce(BIG a)
+{
+    BIG m;
+    BIG_rcopy(m,Modulus);
+    BIG_mod(a,m);
+}
+
+// https://graphics.stanford.edu/~seander/bithacks.html
+// constant time log to base 2 (or number of bits in)
+
+static int logb2(unsign32 v)
+{
+    int r;
+    v |= v >> 1;
+    v |= v >> 2;
+    v |= v >> 4;
+    v |= v >> 8;
+    v |= v >> 16;
+
+    v = v - ((v >> 1) & 0x55555555);
+    v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
+    r = (((v + (v >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24;
+    return r+1;
+}
+
+/* Set r=-a mod Modulus */
+/* SU= 64 */
+void FP_neg(BIG r,BIG a)
+{
+    int sb;
+//    chunk ov;
+    BIG m;
+
+    BIG_rcopy(m,Modulus);
+    BIG_norm(a);
+
+    sb=logb2((unsign32)EXCESS(a));
+    /*
+        ov=EXCESS(a);
+        sb=1;
+        while(ov!=0)
+        {
+            sb++;    // only unpredictable branch
+            ov>>=1;
+        }
+    */
+    BIG_fshl(m,sb);
+    BIG_sub(r,m,a);
+
+    if (EXCESS(r)>=FEXCESS)
+    {
+#ifdef DEBUG_REDUCE
+        printf("Negation too large -  reducing it %d\n",EXCESS(r));
+#endif
+        FP_reduce(r);
+#ifdef GET_STATS
+        rneg++;
+    }
+    tneg++;
+#else
+    }
+#endif
+
+}
+
+/* Set r=a/2. */
+/* SU= 56 */
+void FP_div2(BIG r,BIG a)
+{
+    BIG m;
+    BIG_rcopy(m,Modulus);
+    BIG_norm(a);
+    if (BIG_parity(a)==0)
+    {
+        BIG_copy(r,a);
+        BIG_fshr(r,1);
+    }
+    else
+    {
+        BIG_add(r,a,m);
+        BIG_norm(r);
+        BIG_fshr(r,1);
+    }
+}
+
+/* set w=1/x */
+void FP_inv(BIG w,BIG x)
+{
+    BIG m;
+    BIG_rcopy(m,Modulus);
+    BIG_copy(w,x);
+    FP_redc(w);
+
+    BIG_invmodp(w,w,m);
+    FP_nres(w);
+}
+
+/* SU=8 */
+/* set n=1 */
+void FP_one(BIG n)
+{
+    BIG_one(n);
+    FP_nres(n);
+}
+
+/* Set r=a^b mod Modulus */
+/* SU= 136 */
+void FP_pow(BIG r,BIG a,BIG b)
+{
+    BIG w,z,zilch;
+    int bt;
+    BIG_zero(zilch);
+
+    BIG_norm(b);
+    BIG_copy(z,b);
+    BIG_copy(w,a);
+    FP_one(r);
+    while(1)
+    {
+        bt=BIG_parity(z);
+        BIG_fshr(z,1);
+        if (bt) FP_mul(r,r,w);
+        if (BIG_comp(z,zilch)==0) break;
+        FP_sqr(w,w);
+    }
+    FP_reduce(r);
+}
+
+/* is r a QR? */
+int FP_qr(BIG r)
+{
+    int j;
+    BIG m;
+    BIG_rcopy(m,Modulus);
+    FP_redc(r);
+    j=BIG_jacobi(r,m);
+    FP_nres(r);
+    if (j==1) return 1;
+    return 0;
+
+}
+
+/* Set a=sqrt(b) mod Modulus */
+/* SU= 160 */
+void FP_sqrt(BIG r,BIG a)
+{
+    BIG v,i,b;
+    BIG m;
+    BIG_rcopy(m,Modulus);
+    BIG_mod(a,m);
+    BIG_copy(b,m);
+    if (MOD8==5)
+    {
+        BIG_dec(b,5);
+        BIG_norm(b);
+        BIG_fshr(b,3); /* (p-5)/8 */
+        BIG_copy(i,a);
+        BIG_fshl(i,1);
+        FP_pow(v,i,b);
+        FP_mul(i,i,v);
+        FP_mul(i,i,v);
+        BIG_dec(i,1);
+        FP_mul(r,a,v);
+        FP_mul(r,r,i);
+        BIG_mod(r,m);
+    }
+    if (MOD8==3 || MOD8==7)
+    {
+        BIG_inc(b,1);
+        BIG_norm(b);
+        BIG_fshr(b,2); /* (p+1)/4 */
+        FP_pow(r,a,b);
+    }
+}
+
+/*
+int main()
+{
+
+	BIG r;
+
+	FP_one(r);
+	FP_sqr(r,r);
+
+	BIG_output(r);
+
+	int i,carry;
+	DBIG c={0,0,0,0,0,0,0,0};
+	BIG a={1,2,3,4};
+	BIG b={3,4,5,6};
+	BIG r={11,12,13,14};
+	BIG s={23,24,25,15};
+	BIG w;
+
+//	printf("NEXCESS= %d\n",NEXCESS);
+//	printf("MConst= %d\n",MConst);
+
+	BIG_copy(b,Modulus);
+	BIG_dec(b,1);
+	BIG_norm(b);
+
+	BIG_randomnum(r); BIG_norm(r); BIG_mod(r,Modulus);
+//	BIG_randomnum(s); norm(s); BIG_mod(s,Modulus);
+
+//	BIG_output(r);
+//	BIG_output(s);
+
+	BIG_output(r);
+	FP_nres(r);
+	BIG_output(r);
+	BIG_copy(a,r);
+	FP_redc(r);
+	BIG_output(r);
+	BIG_dscopy(c,a);
+	FP_mod(r,c);
+	BIG_output(r);
+
+
+//	exit(0);
+
+//	copy(r,a);
+	printf("r=   "); BIG_output(r);
+	BIG_modsqr(r,r,Modulus);
+	printf("r^2= "); BIG_output(r);
+
+	FP_nres(r);
+	FP_sqrt(r,r);
+	FP_redc(r);
+	printf("r=   "); BIG_output(r);
+	BIG_modsqr(r,r,Modulus);
+	printf("r^2= "); BIG_output(r);
+
+
+//	for (i=0;i<100000;i++) FP_sqr(r,r);
+//	for (i=0;i<100000;i++)
+		FP_sqrt(r,r);
+
+	BIG_output(r);
+}
+*/
diff --git a/version22/c/fp12.c b/version22/c/fp12.c
new file mode 100644
index 0000000..f7d9815
--- /dev/null
+++ b/version22/c/fp12.c
@@ -0,0 +1,727 @@
+/*
+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.
+*/
+
+/* AMCL Fp^12 functions */
+/* SU=m, m is Stack Usage (no lazy )*/
+/* FP12 elements are of the form a+i.b+i^2.c */
+
+#include "amcl.h"
+
+/* test x==0 ? */
+/* SU= 8 */
+int FP12_iszilch(FP12 *x)
+{
+    if (FP4_iszilch(&(x->a)) && FP4_iszilch(&(x->b)) && FP4_iszilch(&(x->c))) return 1;
+    return 0;
+}
+
+/* test x==1 ? */
+/* SU= 8 */
+int FP12_isunity(FP12 *x)
+{
+    if (FP4_isunity(&(x->a)) && FP4_iszilch(&(x->b)) && FP4_iszilch(&(x->c))) return 1;
+    return 0;
+}
+
+/* FP12 copy w=x */
+/* SU= 16 */
+void FP12_copy(FP12 *w,FP12 *x)
+{
+    if (x==w) return;
+    FP4_copy(&(w->a),&(x->a));
+    FP4_copy(&(w->b),&(x->b));
+    FP4_copy(&(w->c),&(x->c));
+}
+
+/* FP12 w=1 */
+/* SU= 8 */
+void FP12_one(FP12 *w)
+{
+    FP4_one(&(w->a));
+    FP4_zero(&(w->b));
+    FP4_zero(&(w->c));
+}
+
+/* return 1 if x==y, else 0 */
+/* SU= 16 */
+int FP12_equals(FP12 *x,FP12 *y)
+{
+    if (FP4_equals(&(x->a),&(y->a)) && FP4_equals(&(x->b),&(y->b)) && FP4_equals(&(x->b),&(y->b)))
+        return 1;
+    return 0;
+}
+
+/* Set w=conj(x) */
+/* SU= 8 */
+void FP12_conj(FP12 *w,FP12 *x)
+{
+    FP12_copy(w,x);
+    FP4_conj(&(w->a),&(w->a));
+    FP4_nconj(&(w->b),&(w->b));
+    FP4_conj(&(w->c),&(w->c));
+}
+
+/* Create FP12 from FP4 */
+/* SU= 8 */
+void FP12_from_FP4(FP12 *w,FP4 *a)
+{
+    FP4_copy(&(w->a),a);
+    FP4_zero(&(w->b));
+    FP4_zero(&(w->c));
+}
+
+/* Create FP12 from 3 FP4's */
+/* SU= 16 */
+void FP12_from_FP4s(FP12 *w,FP4 *a,FP4 *b,FP4 *c)
+{
+    FP4_copy(&(w->a),a);
+    FP4_copy(&(w->b),b);
+    FP4_copy(&(w->c),c);
+}
+
+/* Granger-Scott Unitary Squaring. This does not benefit from lazy reduction */
+/* SU= 600 */
+void FP12_usqr(FP12 *w,FP12 *x)
+{
+    FP4 A,B,C,D;
+
+    FP4_copy(&A,&(x->a));
+
+    FP4_sqr(&(w->a),&(x->a));
+    FP4_add(&D,&(w->a),&(w->a));
+    FP4_add(&(w->a),&D,&(w->a));
+
+    FP4_norm(&(w->a));
+    FP4_nconj(&A,&A);
+
+    FP4_add(&A,&A,&A);
+    FP4_add(&(w->a),&(w->a),&A);
+    FP4_sqr(&B,&(x->c));
+    FP4_times_i(&B);
+
+    FP4_add(&D,&B,&B);
+    FP4_add(&B,&B,&D);
+    FP4_norm(&B);
+
+    FP4_sqr(&C,&(x->b));
+
+    FP4_add(&D,&C,&C);
+    FP4_add(&C,&C,&D);
+
+    FP4_norm(&C);
+    FP4_conj(&(w->b),&(x->b));
+    FP4_add(&(w->b),&(w->b),&(w->b));
+    FP4_nconj(&(w->c),&(x->c));
+
+    FP4_add(&(w->c),&(w->c),&(w->c));
+    FP4_add(&(w->b),&B,&(w->b));
+    FP4_add(&(w->c),&C,&(w->c));
+    FP12_reduce(w);	    /* reduce here as in pow function repeated squarings would trigger multiple reductions */
+
+}
+
+/* FP12 squaring w=x^2 */
+/* SU= 600 */
+void FP12_sqr(FP12 *w,FP12 *x)
+{
+    /* Use Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
+
+    FP4 A,B,C,D;
+
+    FP4_sqr(&A,&(x->a));
+    FP4_mul(&B,&(x->b),&(x->c));
+    FP4_add(&B,&B,&B);
+    FP4_sqr(&C,&(x->c));
+    FP4_mul(&D,&(x->a),&(x->b));
+    FP4_add(&D,&D,&D);
+    FP4_add(&(w->c),&(x->a),&(x->c));
+    FP4_add(&(w->c),&(x->b),&(w->c));
+
+    FP4_sqr(&(w->c),&(w->c));
+
+    FP4_copy(&(w->a),&A);
+
+    FP4_add(&A,&A,&B);
+
+    FP4_norm(&A);
+
+    FP4_add(&A,&A,&C);
+    FP4_add(&A,&A,&D);
+
+    FP4_norm(&A);
+
+    FP4_neg(&A,&A);
+    FP4_times_i(&B);
+    FP4_times_i(&C);
+
+    FP4_add(&(w->a),&(w->a),&B);
+    FP4_add(&(w->b),&C,&D);
+    FP4_add(&(w->c),&(w->c),&A);
+
+    FP12_norm(w);
+}
+
+/* FP12 full multiplication w=w*y */
+
+
+/* SU= 896 */
+/* FP12 full multiplication w=w*y */
+void FP12_mul(FP12 *w,FP12 *y)
+{
+    FP4 z0,z1,z2,z3,t0,t1;
+
+    FP4_mul(&z0,&(w->a),&(y->a));
+    FP4_mul(&z2,&(w->b),&(y->b));  //
+
+    FP4_add(&t0,&(w->a),&(w->b));
+    FP4_add(&t1,&(y->a),&(y->b));  //
+    FP4_mul(&z1,&t0,&t1);
+    FP4_add(&t0,&(w->b),&(w->c));
+
+    FP4_add(&t1,&(y->b),&(y->c));  //
+    FP4_mul(&z3,&t0,&t1);
+
+    FP4_neg(&t0,&z0);
+    FP4_neg(&t1,&z2);
+
+    FP4_add(&z1,&z1,&t0);   // z1=z1-z0
+
+    FP4_norm(&z1);
+
+    FP4_add(&(w->b),&z1,&t1);
+// z1=z1-z2
+    FP4_add(&z3,&z3,&t1);        // z3=z3-z2
+    FP4_add(&z2,&z2,&t0);        // z2=z2-z0
+
+    FP4_add(&t0,&(w->a),&(w->c));
+
+    FP4_add(&t1,&(y->a),&(y->c));
+    FP4_mul(&t0,&t1,&t0);
+    FP4_add(&z2,&z2,&t0);
+
+    FP4_mul(&t0,&(w->c),&(y->c));
+    FP4_neg(&t1,&t0);
+
+    FP4_norm(&z2);
+    FP4_norm(&z3);
+    FP4_norm(&(w->b));
+
+    FP4_add(&(w->c),&z2,&t1);
+    FP4_add(&z3,&z3,&t1);
+    FP4_times_i(&t0);
+    FP4_add(&(w->b),&(w->b),&t0);
+
+    FP4_times_i(&z3);
+    FP4_add(&(w->a),&z0,&z3);
+
+    FP12_norm(w);
+}
+
+/* FP12 multiplication w=w*y */
+/* SU= 744 */
+/* catering for special case that arises from special form of ATE pairing line function */
+void FP12_smul(FP12 *w,FP12 *y)
+{
+    FP4 z0,z2,z3,t0,t1;
+
+    FP4_copy(&z3,&(w->b));
+    FP4_mul(&z0,&(w->a),&(y->a));
+    FP4_pmul(&z2,&(w->b),&(y->b).a);
+    FP4_add(&(w->b),&(w->a),&(w->b));
+    FP4_copy(&t1,&(y->a));
+    FP2_add(&t1.a,&t1.a,&(y->b).a);
+
+    FP4_mul(&(w->b),&(w->b),&t1);
+    FP4_add(&z3,&z3,&(w->c));
+    FP4_pmul(&z3,&z3,&(y->b).a);
+    FP4_neg(&t0,&z0);
+    FP4_neg(&t1,&z2);
+
+    FP4_add(&(w->b),&(w->b),&t0);   // z1=z1-z0
+
+    FP4_norm(&(w->b));
+
+    FP4_add(&(w->b),&(w->b),&t1);   // z1=z1-z2
+
+    FP4_add(&z3,&z3,&t1);        // z3=z3-z2
+    FP4_add(&z2,&z2,&t0);        // z2=z2-z0
+
+    FP4_add(&t0,&(w->a),&(w->c));
+
+    FP4_mul(&t0,&(y->a),&t0);
+    FP4_add(&(w->c),&z2,&t0);
+
+    FP4_times_i(&z3);
+    FP4_add(&(w->a),&z0,&z3);
+
+    FP12_norm(w);
+}
+
+/* Set w=1/x */
+/* SU= 600 */
+void FP12_inv(FP12 *w,FP12 *x)
+{
+    FP4 f0,f1,f2,f3;
+    FP12_norm(x);
+
+    FP4_sqr(&f0,&(x->a));
+    FP4_mul(&f1,&(x->b),&(x->c));
+    FP4_times_i(&f1);
+    FP4_sub(&f0,&f0,&f1);  /* y.a */
+
+    FP4_sqr(&f1,&(x->c));
+    FP4_times_i(&f1);
+    FP4_mul(&f2,&(x->a),&(x->b));
+    FP4_sub(&f1,&f1,&f2);  /* y.b */
+
+    FP4_sqr(&f2,&(x->b));
+    FP4_mul(&f3,&(x->a),&(x->c));
+    FP4_sub(&f2,&f2,&f3);  /* y.c */
+
+    FP4_mul(&f3,&(x->b),&f2);
+    FP4_times_i(&f3);
+    FP4_mul(&(w->a),&f0,&(x->a));
+    FP4_add(&f3,&(w->a),&f3);
+    FP4_mul(&(w->c),&f1,&(x->c));
+    FP4_times_i(&(w->c));
+
+    FP4_add(&f3,&(w->c),&f3);
+    FP4_inv(&f3,&f3);
+
+    FP4_mul(&(w->a),&f0,&f3);
+    FP4_mul(&(w->b),&f1,&f3);
+    FP4_mul(&(w->c),&f2,&f3);
+
+}
+
+/* constant time powering by small integer of max length bts */
+
+void FP12_pinpow(FP12 *r,int e,int bts)
+{
+    int i,b;
+    FP12 R[2];
+
+    FP12_one(&R[0]);
+    FP12_copy(&R[1],r);
+
+    for (i=bts-1; i>=0; i--)
+    {
+        b=(e>>i)&1;
+        FP12_mul(&R[1-b],&R[b]);
+        FP12_usqr(&R[b],&R[b]);
+    }
+    FP12_copy(r,&R[0]);
+}
+
+/* SU= 528 */
+/* set r=a^b */
+/* Note this is simple square and multiply, so not side-channel safe */
+
+void FP12_pow(FP12 *r,FP12 *a,BIG b)
+{
+    FP12 w;
+    BIG z,zilch;
+    int bt;
+    BIG_zero(zilch);
+    BIG_norm(b);
+    BIG_copy(z,b);
+    FP12_copy(&w,a);
+    FP12_one(r);
+
+    while(1)
+    {
+        bt=BIG_parity(z);
+        BIG_shr(z,1);
+        if (bt)
+            FP12_mul(r,&w);
+        if (BIG_comp(z,zilch)==0) break;
+        FP12_usqr(&w,&w);
+    }
+
+    FP12_reduce(r);
+}
+
+/* p=q0^u0.q1^u1.q2^u2.q3^u3 */
+/* Timing attack secure, but not cache attack secure */
+
+void FP12_pow4(FP12 *p,FP12 *q,BIG u[4])
+{
+    int i,j,a[4],nb,m;
+    FP12 g[8],c,s[2];
+    BIG t[4],mt;
+    sign8 w[NLEN*BASEBITS+1];
+
+    for (i=0; i<4; i++)
+        BIG_copy(t[i],u[i]);
+
+    FP12_copy(&g[0],&q[0]);
+    FP12_conj(&s[0],&q[1]);
+    FP12_mul(&g[0],&s[0]);  /* P/Q */
+    FP12_copy(&g[1],&g[0]);
+    FP12_copy(&g[2],&g[0]);
+    FP12_copy(&g[3],&g[0]);
+    FP12_copy(&g[4],&q[0]);
+    FP12_mul(&g[4],&q[1]);  /* P*Q */
+    FP12_copy(&g[5],&g[4]);
+    FP12_copy(&g[6],&g[4]);
+    FP12_copy(&g[7],&g[4]);
+
+    FP12_copy(&s[1],&q[2]);
+    FP12_conj(&s[0],&q[3]);
+    FP12_mul(&s[1],&s[0]);       /* R/S */
+    FP12_conj(&s[0],&s[1]);
+    FP12_mul(&g[1],&s[0]);
+    FP12_mul(&g[2],&s[1]);
+    FP12_mul(&g[5],&s[0]);
+    FP12_mul(&g[6],&s[1]);
+    FP12_copy(&s[1],&q[2]);
+    FP12_mul(&s[1],&q[3]);      /* R*S */
+    FP12_conj(&s[0],&s[1]);
+    FP12_mul(&g[0],&s[0]);
+    FP12_mul(&g[3],&s[1]);
+    FP12_mul(&g[4],&s[0]);
+    FP12_mul(&g[7],&s[1]);
+
+    /* if power is even add 1 to power, and add q to correction */
+    FP12_one(&c);
+
+    BIG_zero(mt);
+    for (i=0; i<4; i++)
+    {
+        if (BIG_parity(t[i])==0)
+        {
+            BIG_inc(t[i],1);
+            BIG_norm(t[i]);
+            FP12_mul(&c,&q[i]);
+        }
+        BIG_add(mt,mt,t[i]);
+        BIG_norm(mt);
+    }
+
+    FP12_conj(&c,&c);
+    nb=1+BIG_nbits(mt);
+
+    /* convert exponent to signed 1-bit window */
+    for (j=0; j<nb; j++)
+    {
+        for (i=0; i<4; i++)
+        {
+            a[i]=BIG_lastbits(t[i],2)-2;
+            BIG_dec(t[i],a[i]);
+            BIG_norm(t[i]);
+            BIG_fshr(t[i],1);
+        }
+        w[j]=8*a[0]+4*a[1]+2*a[2]+a[3];
+    }
+    w[nb]=8*BIG_lastbits(t[0],2)+4*BIG_lastbits(t[1],2)+2*BIG_lastbits(t[2],2)+BIG_lastbits(t[3],2);
+    FP12_copy(p,&g[(w[nb]-1)/2]);
+
+    for (i=nb-1; i>=0; i--)
+    {
+        m=w[i]>>7;
+        j=(w[i]^m)-m;  /* j=abs(w[i]) */
+        j=(j-1)/2;
+        FP12_copy(&s[0],&g[j]);
+        FP12_conj(&s[1],&g[j]);
+        FP12_usqr(p,p);
+        FP12_mul(p,&s[m&1]);
+    }
+    FP12_mul(p,&c); /* apply correction */
+    FP12_reduce(p);
+}
+
+/* Set w=w^p using Frobenius */
+/* SU= 160 */
+void FP12_frob(FP12 *w,FP2 *f)
+{
+    FP2 f2,f3;
+    FP2_sqr(&f2,f);     /* f2=f^2 */
+    FP2_mul(&f3,&f2,f); /* f3=f^3 */
+
+    FP4_frob(&(w->a),&f3);
+    FP4_frob(&(w->b),&f3);
+    FP4_frob(&(w->c),&f3);
+
+    FP4_pmul(&(w->b),&(w->b),f);
+    FP4_pmul(&(w->c),&(w->c),&f2);
+}
+
+/* SU= 8 */
+/* normalise all components of w */
+void FP12_norm(FP12 *w)
+{
+    FP4_norm(&(w->a));
+    FP4_norm(&(w->b));
+    FP4_norm(&(w->c));
+}
+
+/* SU= 8 */
+/* reduce all components of w */
+void FP12_reduce(FP12 *w)
+{
+    FP4_reduce(&(w->a));
+    FP4_reduce(&(w->b));
+    FP4_reduce(&(w->c));
+}
+
+/* trace function w=trace(x) */
+/* SU= 8 */
+void FP12_trace(FP4 *w,FP12 *x)
+{
+    FP4_imul(w,&(x->a),3);
+    FP4_reduce(w);
+}
+
+/* SU= 8 */
+/* Output w in hex */
+void FP12_output(FP12 *w)
+{
+    printf("[");
+    FP4_output(&(w->a));
+    printf(",");
+    FP4_output(&(w->b));
+    printf(",");
+    FP4_output(&(w->c));
+    printf("]");
+}
+
+/* SU= 64 */
+/* Convert g to octet string w */
+void FP12_toOctet(octet *W,FP12 *g)
+{
+    BIG a;
+    W->len=12*MODBYTES;
+
+    BIG_copy(a,(*g).a.a.a);
+    FP_redc(a);
+    BIG_toBytes(&(W->val[0]),a);
+    BIG_copy(a,(*g).a.a.b);
+    FP_redc(a);
+    BIG_toBytes(&(W->val[MODBYTES]),a);
+    BIG_copy(a,(*g).a.b.a);
+    FP_redc(a);
+    BIG_toBytes(&(W->val[2*MODBYTES]),a);
+    BIG_copy(a,(*g).a.b.b);
+    FP_redc(a);
+    BIG_toBytes(&(W->val[3*MODBYTES]),a);
+    BIG_copy(a,(*g).b.a.a);
+    FP_redc(a);
+    BIG_toBytes(&(W->val[4*MODBYTES]),a);
+    BIG_copy(a,(*g).b.a.b);
+    FP_redc(a);
+    BIG_toBytes(&(W->val[5*MODBYTES]),a);
+    BIG_copy(a,(*g).b.b.a);
+    FP_redc(a);
+    BIG_toBytes(&(W->val[6*MODBYTES]),a);
+    BIG_copy(a,(*g).b.b.b);
+    FP_redc(a);
+    BIG_toBytes(&(W->val[7*MODBYTES]),a);
+    BIG_copy(a,(*g).c.a.a);
+    FP_redc(a);
+    BIG_toBytes(&(W->val[8*MODBYTES]),a);
+    BIG_copy(a,(*g).c.a.b);
+    FP_redc(a);
+    BIG_toBytes(&(W->val[9*MODBYTES]),a);
+    BIG_copy(a,(*g).c.b.a);
+    FP_redc(a);
+    BIG_toBytes(&(W->val[10*MODBYTES]),a);
+    BIG_copy(a,(*g).c.b.b);
+    FP_redc(a);
+    BIG_toBytes(&(W->val[11*MODBYTES]),a);
+}
+
+/* SU= 24 */
+/* Restore g from octet string w */
+void FP12_fromOctet(FP12 *g,octet *W)
+{
+    BIG_fromBytes((*g).a.a.a,&W->val[0]);
+    FP_nres((*g).a.a.a);
+    BIG_fromBytes((*g).a.a.b,&W->val[MODBYTES]);
+    FP_nres((*g).a.a.b);
+    BIG_fromBytes((*g).a.b.a,&W->val[2*MODBYTES]);
+    FP_nres((*g).a.b.a);
+    BIG_fromBytes((*g).a.b.b,&W->val[3*MODBYTES]);
+    FP_nres((*g).a.b.b);
+    BIG_fromBytes((*g).b.a.a,&W->val[4*MODBYTES]);
+    FP_nres((*g).b.a.a);
+    BIG_fromBytes((*g).b.a.b,&W->val[5*MODBYTES]);
+    FP_nres((*g).b.a.b);
+    BIG_fromBytes((*g).b.b.a,&W->val[6*MODBYTES]);
+    FP_nres((*g).b.b.a);
+    BIG_fromBytes((*g).b.b.b,&W->val[7*MODBYTES]);
+    FP_nres((*g).b.b.b);
+    BIG_fromBytes((*g).c.a.a,&W->val[8*MODBYTES]);
+    FP_nres((*g).c.a.a);
+    BIG_fromBytes((*g).c.a.b,&W->val[9*MODBYTES]);
+    FP_nres((*g).c.a.b);
+    BIG_fromBytes((*g).c.b.a,&W->val[10*MODBYTES]);
+    FP_nres((*g).c.b.a);
+    BIG_fromBytes((*g).c.b.b,&W->val[11*MODBYTES]);
+    FP_nres((*g).c.b.b);
+}
+
+/*
+int main(){
+		FP2 f,w0,w1;
+		FP4 t0,t1,t2;
+		FP12 w,t,lv;
+		BIG a,b;
+		BIG p;
+
+		//Test w^(P^4) = w mod p^2
+//		BIG_randomnum(a);
+//		BIG_randomnum(b);
+//		BIG_mod(a,Modulus); BIG_mod(b,Modulus);
+	BIG_zero(a); BIG_zero(b); BIG_inc(a,1); BIG_inc(b,2); FP_nres(a); FP_nres(b);
+		FP2_from_zps(&w0,a,b);
+
+//		BIG_randomnum(a); BIG_randomnum(b);
+//		BIG_mod(a,Modulus); BIG_mod(b,Modulus);
+	BIG_zero(a); BIG_zero(b); BIG_inc(a,3); BIG_inc(b,4); FP_nres(a); FP_nres(b);
+		FP2_from_zps(&w1,a,b);
+
+		FP4_from_FP2s(&t0,&w0,&w1);
+		FP4_reduce(&t0);
+
+//		BIG_randomnum(a);
+//		BIG_randomnum(b);
+//		BIG_mod(a,Modulus); BIG_mod(b,Modulus);
+		BIG_zero(a); BIG_zero(b); BIG_inc(a,5); BIG_inc(b,6); FP_nres(a); FP_nres(b);
+		FP2_from_zps(&w0,a,b);
+
+//		BIG_randomnum(a); BIG_randomnum(b);
+//		BIG_mod(a,Modulus); BIG_mod(b,Modulus);
+
+		BIG_zero(a); BIG_zero(b); BIG_inc(a,7); BIG_inc(b,8); FP_nres(a); FP_nres(b);
+		FP2_from_zps(&w1,a,b);
+
+		FP4_from_FP2s(&t1,&w0,&w1);
+		FP4_reduce(&t1);
+
+//		BIG_randomnum(a);
+//		BIG_randomnum(b);
+//		BIG_mod(a,Modulus); BIG_mod(b,Modulus);
+		BIG_zero(a); BIG_zero(b); BIG_inc(a,9); BIG_inc(b,10); FP_nres(a); FP_nres(b);
+		FP2_from_zps(&w0,a,b);
+
+//		BIG_randomnum(a); BIG_randomnum(b);
+//		BIG_mod(a,Modulus); BIG_mod(b,Modulus);
+		BIG_zero(a); BIG_zero(b); BIG_inc(a,11); BIG_inc(b,12); FP_nres(a); FP_nres(b);
+		FP2_from_zps(&w1,a,b);
+
+		FP4_from_FP2s(&t2,&w0,&w1);
+		FP4_reduce(&t2);
+
+		FP12_from_FP4s(&w,&t0,&t1,&t2);
+
+		FP12_copy(&t,&w);
+
+		printf("w= ");
+		FP12_output(&w);
+		printf("\n");
+
+		BIG_rcopy(p,Modulus);
+		//BIG_zero(p); BIG_inc(p,7);
+
+		FP12_pow(&w,&w,p);
+
+		printf("w^p= ");
+		FP12_output(&w);
+		printf("\n");
+
+		FP2_gfc(&f,12);
+		FP12_frob(&t,&f);
+		printf("w^p= ");
+		FP12_output(&t);
+		printf("\n");
+
+//exit(0);
+
+		FP12_pow(&w,&w,p);
+		//printf("w^p^2= ");
+		//FP12_output(&w);
+		//printf("\n");
+		FP12_pow(&w,&w,p);
+		//printf("w^p^3= ");
+		//FP12_output(&w);
+		//printf("\n");
+		FP12_pow(&w,&w,p);
+		FP12_pow(&w,&w,p);
+		FP12_pow(&w,&w,p);
+		printf("w^p^6= ");
+		FP12_output(&w);
+		printf("\n");
+		FP12_pow(&w,&w,p);
+		FP12_pow(&w,&w,p);
+		printf("w^p^8= ");
+		FP12_output(&w);
+		printf("\n");
+		FP12_pow(&w,&w,p);
+		FP12_pow(&w,&w,p);
+		FP12_pow(&w,&w,p);
+		printf("w^p^11= ");
+		FP12_output(&w);
+		printf("\n");
+
+	//	BIG_zero(p); BIG_inc(p,7); BIG_norm(p);
+		FP12_pow(&w,&w,p);
+
+		printf("w^p12= ");
+		FP12_output(&w);
+		printf("\n");
+//exit(0);
+
+		FP12_inv(&t,&w);
+		printf("1/w mod p^4 = ");
+		FP12_output(&t);
+		printf("\n");
+
+		FP12_inv(&w,&t);
+		printf("1/(1/w) mod p^4 = ");
+		FP12_output(&w);
+		printf("\n");
+
+
+
+	FP12_inv(&lv,&w);
+//printf("w= "); FP12_output(&w); printf("\n");
+	FP12_conj(&w,&w);
+//printf("w= "); FP12_output(&w); printf("\n");
+//exit(0);
+	FP12_mul(&w,&w,&lv);
+//printf("w= "); FP12_output(&w); printf("\n");
+	FP12_copy(&lv,&w);
+	FP12_frob(&w,&f);
+	FP12_frob(&w,&f);
+	FP12_mul(&w,&w,&lv);
+
+//printf("w= "); FP12_output(&w); printf("\n");
+//exit(0);
+
+w.unitary=0;
+FP12_conj(&lv,&w);
+	printf("rx= "); FP12_output(&lv); printf("\n");
+FP12_inv(&lv,&w);
+	printf("ry= "); FP12_output(&lv); printf("\n");
+
+
+		return 0;
+}
+
+*/
diff --git a/version22/c/fp2.c b/version22/c/fp2.c
new file mode 100644
index 0000000..93aa31e
--- /dev/null
+++ b/version22/c/fp2.c
@@ -0,0 +1,435 @@
+/*
+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.
+*/
+
+/* AMCL Fp^2 functions */
+/* SU=m, m is Stack Usage (no lazy )*/
+
+/* FP2 elements are of the form a+ib, where i is sqrt(-1) */
+
+#include "amcl.h"
+
+/* test x==0 ? */
+/* SU= 8 */
+int FP2_iszilch(FP2 *x)
+{
+    FP2_reduce(x);
+    if (BIG_iszilch(x->a) && BIG_iszilch(x->b)) return 1;
+    return 0;
+}
+
+/* Move b to a if d=1 */
+void FP2_cmove(FP2 *f,FP2 *g,int d)
+{
+    BIG_cmove(f->a,g->a,d);
+    BIG_cmove(f->b,g->b,d);
+}
+
+/* test x==1 ? */
+/* SU= 48 */
+int FP2_isunity(FP2 *x)
+{
+    BIG one;
+    FP_one(one);
+    FP2_reduce(x);
+    if (BIG_comp(x->a,one)==0 && BIG_iszilch(x->b)) return 1;
+    return 0;
+}
+
+/* SU= 8 */
+/* Fully reduce a and b mod Modulus */
+void FP2_reduce(FP2 *w)
+{
+    FP_reduce(w->a);
+    FP_reduce(w->b);
+}
+
+/* return 1 if x==y, else 0 */
+/* SU= 16 */
+int FP2_equals(FP2 *x,FP2 *y)
+{
+    FP2_reduce(x);
+    FP2_reduce(y);
+    if (BIG_comp(x->a,y->a)==0 && BIG_comp(x->b,y->b)==0)
+        return 1;
+    return 0;
+}
+
+/* Create FP2 from two FPs */
+/* SU= 16 */
+void FP2_from_FPs(FP2 *w,BIG x,BIG y)
+{
+    BIG_copy(w->a,x);
+    BIG_copy(w->b,y);
+}
+
+/* Create FP2 from two BIGS */
+/* SU= 16 */
+void FP2_from_BIGs(FP2 *w,BIG x,BIG y)
+{
+    BIG_copy(w->a,x);
+    BIG_copy(w->b,y);
+    FP_nres(w->a);
+    FP_nres(w->b);
+}
+
+/* Create FP2 from FP */
+/* SU= 8 */
+void FP2_from_FP(FP2 *w,BIG x)
+{
+    BIG_copy(w->a,x);
+    BIG_zero(w->b);
+}
+
+/* Create FP2 from BIG */
+/* SU= 8 */
+void FP2_from_BIG(FP2 *w,BIG x)
+{
+    BIG_copy(w->a,x);
+    FP_nres(w->a);
+    BIG_zero(w->b);
+}
+
+/* FP2 copy w=x */
+/* SU= 16 */
+void FP2_copy(FP2 *w,FP2 *x)
+{
+    if (w==x) return;
+    BIG_copy(w->a,x->a);
+    BIG_copy(w->b,x->b);
+}
+
+/* FP2 set w=0 */
+/* SU= 8 */
+void FP2_zero(FP2 *w)
+{
+    BIG_zero(w->a);
+    BIG_zero(w->b);
+}
+
+/* FP2 set w=1 */
+/* SU= 48 */
+void FP2_one(FP2 *w)
+{
+    BIG one;
+    FP_one(one);
+    FP2_from_FP(w,one);
+}
+
+/* Set w=-x */
+/* SU= 88 */
+void FP2_neg(FP2 *w,FP2 *x)
+{
+    /* Just one neg! */
+    BIG m,t;
+    FP2_norm(x);
+    FP_add(m,x->a,x->b);
+    FP_neg(m,m);
+    BIG_norm(m);
+    FP_add(t,m,x->b);
+    FP_add(w->b,m,x->a);
+    BIG_copy(w->a,t);
+}
+
+/* Set w=conj(x) */
+/* SU= 16 */
+void FP2_conj(FP2 *w,FP2 *x)
+{
+    BIG_copy(w->a,x->a);
+    FP_neg(w->b,x->b);
+}
+
+/* Set w=x+y */
+/* SU= 16 */
+void FP2_add(FP2 *w,FP2 *x,FP2 *y)
+{
+    FP_add(w->a,x->a,y->a);
+    FP_add(w->b,x->b,y->b);
+}
+
+/* Set w=x-y */
+/* SU= 16 */
+void FP2_sub(FP2 *w,FP2 *x,FP2 *y)
+{
+    FP2 m;
+    FP2_neg(&m,y);
+    FP2_add(w,x,&m);
+}
+
+/* Set w=s*x, where s is FP */
+/* SU= 16 */
+void FP2_pmul(FP2 *w,FP2 *x,BIG s)
+{
+    FP_mul(w->a,x->a,s);
+    FP_mul(w->b,x->b,s);
+}
+
+/* SU= 16 */
+/* Set w=s*x, where s is int */
+void FP2_imul(FP2 *w,FP2 *x,int s)
+{
+    FP_imul(w->a,x->a,s);
+    FP_imul(w->b,x->b,s);
+}
+
+/* Set w=x^2 */
+/* SU= 128 */
+void FP2_sqr(FP2 *w,FP2 *x)
+{
+    BIG w1,w3,mb;
+
+    FP_mul(w3,x->a,x->b); /* norms x */
+    FP_add(w1,x->a,x->b); /* w1#2 w1=2 */
+    FP_neg(mb,x->b);      /* mb#2 mb=1 */
+    FP_add(w->a,x->a,mb);   /* w2#3 w2=3 */
+    FP_mul(w->a,w1,w->a);     /* w->a#2 w->a=1 w1&w2=6 w1*w2=2 */
+
+    FP_add(w->b,w3,w3); /* w->b#4 w->b=2 */
+
+    FP2_norm(w);
+
+}
+
+
+/* Set w=x*y */
+/* SU= 168 */
+void FP2_mul(FP2 *w,FP2 *x,FP2 *y)
+{
+    BIG w1,w2,w5,mw;
+
+    FP_mul(w1,x->a,y->a);  /* norms x  */
+    FP_mul(w2,x->b,y->b);  /* and y */
+
+    FP_add(w5,x->a,x->b);
+
+    FP_add(w->b,y->a,y->b);
+
+    FP_mul(w->b,w->b,w5);
+    FP_add(mw,w1,w2);
+    FP_neg(mw,mw);
+
+    FP_add(w->b,w->b,mw);
+    FP_add(mw,w1,mw);
+    FP_add(w->a,w1,mw);
+
+    FP2_norm(w);
+
+}
+
+/* output FP2 in hex format [a,b] */
+/* SU= 16 */
+void FP2_output(FP2 *w)
+{
+    FP2_reduce(w);
+    FP_redc(w->a);
+    FP_redc(w->b);
+    printf("[");
+    BIG_output(w->a);
+    printf(",");
+    BIG_output(w->b);
+    printf("]");
+    FP_nres(w->a);
+    FP_nres(w->b);
+}
+
+/* SU= 8 */
+void FP2_rawoutput(FP2 *w)
+{
+    printf("[");
+    BIG_rawoutput(w->a);
+    printf(",");
+    BIG_rawoutput(w->b);
+    printf("]");
+}
+
+
+/* Set w=1/x */
+/* SU= 128 */
+void FP2_inv(FP2 *w,FP2 *x)
+{
+    BIG m,w1,w2;
+    BIG_rcopy(m,Modulus);
+    FP2_norm(x);
+    FP_sqr(w1,x->a);
+    FP_sqr(w2,x->b);
+    FP_add(w1,w1,w2);
+
+    FP_redc(w1);
+    BIG_invmodp(w1,w1,m);
+    FP_nres(w1);
+    FP_mul(w->a,x->a,w1);
+    FP_neg(w1,w1);
+    FP_mul(w->b,x->b,w1);
+//	FP2_norm(w);
+}
+
+
+/* Set w=x/2 */
+/* SU= 16 */
+void FP2_div2(FP2 *w,FP2 *x)
+{
+    FP_div2(w->a,x->a);
+    FP_div2(w->b,x->b);
+}
+
+/* Set w*=(1+sqrt(-1)) */
+/* where X^2-(1+sqrt(-1)) is irreducible for FP4, assumes p=3 mod 8 */
+
+/* SU= 128 */
+void FP2_mul_ip(FP2 *w)
+{
+    FP2 t;
+    BIG z;
+
+    FP2_norm(w);
+    FP2_copy(&t,w);
+
+    BIG_copy(z,w->a);
+    FP_neg(w->a,w->b);
+    BIG_copy(w->b,z);
+
+    FP2_add(w,&t,w);
+    FP2_norm(w);
+}
+
+/* Set w/=(1+sqrt(-1)) */
+/* SU= 88 */
+void FP2_div_ip(FP2 *w)
+{
+    FP2 t;
+    FP2_norm(w);
+    FP_add(t.a,w->a,w->b);
+    FP_sub(t.b,w->b,w->a);
+    FP2_div2(w,&t);
+}
+
+/* SU= 8 */
+/* normalise a and b components of w */
+void FP2_norm(FP2 *w)
+{
+    BIG_norm(w->a);
+    BIG_norm(w->b);
+}
+
+/* Set w=a^b mod m */
+/* SU= 208 */
+void FP2_pow(FP2 *r,FP2* a,BIG b)
+{
+    FP2 w;
+    BIG z,one,zilch;
+    int bt;
+
+    BIG_norm(b);
+    BIG_copy(z,b);
+    FP2_copy(&w,a);
+    FP_one(one);
+    BIG_zero(zilch);
+    FP2_from_FP(r,one);
+    while(1)
+    {
+        bt=BIG_parity(z);
+        BIG_shr(z,1);
+        if (bt) FP2_mul(r,r,&w);
+        if (BIG_comp(z,zilch)==0) break;
+        FP2_sqr(&w,&w);
+    }
+    FP2_reduce(r);
+}
+
+/* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */
+/* returns true if u is QR */
+
+int FP2_sqrt(FP2 *w,FP2 *u)
+{
+    BIG w1,w2,q;
+    FP2_copy(w,u);
+    if (FP2_iszilch(w)) return 1;
+
+    BIG_rcopy(q,Modulus);
+    FP_sqr(w1,w->b);
+    FP_sqr(w2,w->a);
+    FP_add(w1,w1,w2);
+    if (!FP_qr(w1))
+    {
+        FP2_zero(w);
+        return 0;
+    }
+    FP_sqrt(w1,w1);
+    FP_add(w2,w->a,w1);
+    FP_div2(w2,w2);
+    if (!FP_qr(w2))
+    {
+        FP_sub(w2,w->a,w1);
+        FP_div2(w2,w2);
+        if (!FP_qr(w2))
+        {
+            FP2_zero(w);
+            return 0;
+        }
+    }
+    FP_sqrt(w2,w2);
+    BIG_copy(w->a,w2);
+    FP_add(w2,w2,w2);
+    FP_redc(w2);
+    BIG_invmodp(w2,w2,q);
+    FP_nres(w2);
+    FP_mul(w->b,w->b,w2);
+    return 1;
+}
+
+/*
+int main()
+{
+	int i;
+	FP2 w,z;
+	BIG a,b,e;
+	BIG pp1,pm1;
+	BIG_unity(a); BIG_unity(b);
+	FP2_from_BIGs(&w,a,b);
+//	for (i=0;i<100;i++)
+//	{
+//		BIG_randomnum(a); BIG_randomnum(b);
+//		BIG_mod(a,Modulus); BIG_mod(b,Modulus);
+//		FP2_from_FPs(&w,a,b);
+//		FP2_output(&w);
+//		FP2_inv(&z,&w);
+//				FP2_output(&z);
+//		FP2_inv(&z,&z);
+//				FP2_output(&z);
+//				FP2_output(&w);
+//		if (FP2_comp(&w,&z)!=1) printf("error \n");
+//		else printf("OK \n");
+//	}
+//exit(0);
+	printf("w= "); FP2_output(&w); printf("\n");
+	BIG_zero(e); BIG_inc(e,27);
+	FP2_pow(&w,&w,e);
+	FP2_output(&w);
+exit(0);
+	BIG_rcopy(pp1,Modulus);
+	BIG_rcopy(pm1,Modulus);
+	BIG_inc(pp1,1);
+	BIG_dec(pm1,1);
+	BIG_norm(pp1);
+	BIG_norm(pm1);
+	FP2_pow(&w,&w,pp1);
+	FP2_pow(&w,&w,pm1);
+	FP2_output(&w);
+}
+
+*/
diff --git a/version22/c/fp4.c b/version22/c/fp4.c
new file mode 100644
index 0000000..f61811f
--- /dev/null
+++ b/version22/c/fp4.c
@@ -0,0 +1,651 @@
+/*
+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.
+*/
+
+/* AMCL Fp^4 functions */
+/* SU=m, m is Stack Usage (no lazy )*/
+
+/* FP4 elements are of the form a+ib, where i is sqrt(-1+sqrt(-1)) */
+
+#include "amcl.h"
+
+/* test x==0 ? */
+/* SU= 8 */
+int FP4_iszilch(FP4 *x)
+{
+    if (FP2_iszilch(&(x->a)) && FP2_iszilch(&(x->b))) return 1;
+    return 0;
+}
+
+/* test x==1 ? */
+/* SU= 8 */
+int FP4_isunity(FP4 *x)
+{
+    if (FP2_isunity(&(x->a)) && FP2_iszilch(&(x->b))) return 1;
+    return 0;
+}
+
+/* test is w real? That is in a+ib test b is zero */
+int FP4_isreal(FP4 *w)
+{
+    return FP2_iszilch(&(w->b));
+}
+
+/* return 1 if x==y, else 0 */
+/* SU= 16 */
+int FP4_equals(FP4 *x,FP4 *y)
+{
+    if (FP2_equals(&(x->a),&(y->a)) && FP2_equals(&(x->b),&(y->b)))
+        return 1;
+    return 0;
+}
+
+/* set FP4 from two FP2s */
+/* SU= 16 */
+void FP4_from_FP2s(FP4 *w,FP2 * x,FP2* y)
+{
+    FP2_copy(&(w->a), x);
+    FP2_copy(&(w->b), y);
+}
+
+/* set FP4 from FP2 */
+/* SU= 8 */
+void FP4_from_FP2(FP4 *w,FP2 *x)
+{
+    FP2_copy(&(w->a), x);
+    FP2_zero(&(w->b));
+}
+
+/* FP4 copy w=x */
+/* SU= 16 */
+void FP4_copy(FP4 *w,FP4 *x)
+{
+    if (w==x) return;
+    FP2_copy(&(w->a), &(x->a));
+    FP2_copy(&(w->b), &(x->b));
+}
+
+/* FP4 w=0 */
+/* SU= 8 */
+void FP4_zero(FP4 *w)
+{
+    FP2_zero(&(w->a));
+    FP2_zero(&(w->b));
+}
+
+/* FP4 w=1 */
+/* SU= 8 */
+void FP4_one(FP4 *w)
+{
+    FP2_one(&(w->a));
+    FP2_zero(&(w->b));
+}
+
+/* Set w=-x */
+/* SU= 160 */
+void FP4_neg(FP4 *w,FP4 *x)
+{
+    /* Just one field neg */
+    FP2 m,t;
+    FP2_add(&m,&(x->a),&(x->b));
+    FP2_neg(&m,&m);
+    FP2_norm(&m);
+    FP2_add(&t,&m,&(x->b));
+    FP2_add(&(w->b),&m,&(x->a));
+    FP2_copy(&(w->a),&t);
+}
+
+/* Set w=conj(x) */
+/* SU= 16 */
+void FP4_conj(FP4 *w,FP4 *x)
+{
+    FP2_copy(&(w->a), &(x->a));
+    FP2_neg(&(w->b), &(x->b));
+    FP2_norm(&(w->b));
+}
+
+/* Set w=-conj(x) */
+/* SU= 16 */
+void FP4_nconj(FP4 *w,FP4 *x)
+{
+    FP2_copy(&(w->b),&(x->b));
+    FP2_neg(&(w->a), &(x->a));
+    FP2_norm(&(w->a));
+}
+
+/* Set w=x+y */
+/* SU= 16 */
+void FP4_add(FP4 *w,FP4 *x,FP4 *y)
+{
+    FP2_add(&(w->a), &(x->a), &(y->a));
+    FP2_add(&(w->b), &(x->b), &(y->b));
+}
+
+/* Set w=x-y */
+/* SU= 160 */
+void FP4_sub(FP4 *w,FP4 *x,FP4 *y)
+{
+    FP4 my;
+    FP4_neg(&my, y);
+    FP4_add(w, x, &my);
+
+}
+/* SU= 8 */
+/* reduce all components of w mod Modulus */
+void FP4_reduce(FP4 *w)
+{
+    FP2_reduce(&(w->a));
+    FP2_reduce(&(w->b));
+}
+
+/* SU= 8 */
+/* normalise all elements of w */
+void FP4_norm(FP4 *w)
+{
+    FP2_norm(&(w->a));
+    FP2_norm(&(w->b));
+}
+
+/* Set w=s*x, where s is FP2 */
+/* SU= 16 */
+void FP4_pmul(FP4 *w,FP4 *x,FP2 *s)
+{
+    FP2_mul(&(w->a),&(x->a),s);
+    FP2_mul(&(w->b),&(x->b),s);
+}
+
+/* SU= 16 */
+/* Set w=s*x, where s is int */
+void FP4_imul(FP4 *w,FP4 *x,int s)
+{
+    FP2_imul(&(w->a),&(x->a),s);
+    FP2_imul(&(w->b),&(x->b),s);
+}
+
+/* Set w=x^2 */
+/* SU= 232 */
+void FP4_sqr(FP4 *w,FP4 *x)
+{
+    FP2 t1,t2,t3;
+
+    FP2_mul(&t3,&(x->a),&(x->b)); /* norms x */
+    FP2_copy(&t2,&(x->b));
+    FP2_add(&t1,&(x->a),&(x->b));
+    FP2_mul_ip(&t2);
+
+    FP2_add(&t2,&(x->a),&t2);
+
+    FP2_mul(&(w->a),&t1,&t2);
+
+    FP2_copy(&t2,&t3);
+    FP2_mul_ip(&t2);
+
+    FP2_add(&t2,&t2,&t3);
+
+    FP2_neg(&t2,&t2);
+    FP2_add(&(w->a),&(w->a),&t2);  /* a=(a+b)(a+i^2.b)-i^2.ab-ab = a*a+ib*ib */
+    FP2_add(&(w->b),&t3,&t3);  /* b=2ab */
+
+    FP4_norm(w);
+}
+
+/* Set w=x*y */
+/* SU= 312 */
+void FP4_mul(FP4 *w,FP4 *x,FP4 *y)
+{
+
+    FP2 t1,t2,t3,t4;
+    FP2_mul(&t1,&(x->a),&(y->a)); /* norms x */
+    FP2_mul(&t2,&(x->b),&(y->b)); /* and y */
+    FP2_add(&t3,&(y->b),&(y->a));
+    FP2_add(&t4,&(x->b),&(x->a));
+
+
+    FP2_mul(&t4,&t4,&t3); /* (xa+xb)(ya+yb) */
+    FP2_sub(&t4,&t4,&t1);
+    FP2_norm(&t4);
+
+    FP2_sub(&(w->b),&t4,&t2);
+    FP2_mul_ip(&t2);
+    FP2_add(&(w->a),&t2,&t1);
+
+    FP4_norm(w);
+}
+
+/* output FP4 in format [a,b] */
+/* SU= 8 */
+void FP4_output(FP4 *w)
+{
+    printf("[");
+    FP2_output(&(w->a));
+    printf(",");
+    FP2_output(&(w->b));
+    printf("]");
+}
+
+/* SU= 8 */
+void FP4_rawoutput(FP4 *w)
+{
+    printf("[");
+    FP2_rawoutput(&(w->a));
+    printf(",");
+    FP2_rawoutput(&(w->b));
+    printf("]");
+}
+
+/* Set w=1/x */
+/* SU= 160 */
+void FP4_inv(FP4 *w,FP4 *x)
+{
+    FP2 t1,t2;
+    FP2_sqr(&t1,&(x->a));
+    FP2_sqr(&t2,&(x->b));
+    FP2_mul_ip(&t2);
+    FP2_sub(&t1,&t1,&t2);
+    FP2_inv(&t1,&t1);
+    FP2_mul(&(w->a),&t1,&(x->a));
+    FP2_neg(&t1,&t1);
+    FP2_mul(&(w->b),&t1,&(x->b));
+}
+
+/* w*=i where i = sqrt(-1+sqrt(-1)) */
+/* SU= 200 */
+void FP4_times_i(FP4 *w)
+{
+    BIG z;
+    FP2 s,t;
+
+    FP4_norm(w);
+    FP2_copy(&t,&(w->b));
+
+    FP2_copy(&s,&t);
+
+    BIG_copy(z,s.a);
+    FP_neg(s.a,s.b);
+    BIG_copy(s.b,z);
+
+    FP2_add(&t,&t,&s);
+    FP2_norm(&t);
+
+    FP2_copy(&(w->b),&(w->a));
+    FP2_copy(&(w->a),&t);
+}
+
+/* Set w=w^p using Frobenius */
+/* SU= 16 */
+void FP4_frob(FP4 *w,FP2 *f)
+{
+    FP2_conj(&(w->a),&(w->a));
+    FP2_conj(&(w->b),&(w->b));
+    FP2_mul( &(w->b),f,&(w->b));
+}
+
+/* Set r=a^b mod m */
+/* SU= 240 */
+void FP4_pow(FP4 *r,FP4* a,BIG b)
+{
+    FP4 w;
+    BIG z,zilch;
+    int bt;
+
+    BIG_zero(zilch);
+    BIG_norm(b);
+    BIG_copy(z,b);
+    FP4_copy(&w,a);
+    FP4_one(r);
+
+    while(1)
+    {
+        bt=BIG_parity(z);
+        BIG_shr(z,1);
+        if (bt) FP4_mul(r,r,&w);
+        if (BIG_comp(z,zilch)==0) break;
+        FP4_sqr(&w,&w);
+    }
+    FP4_reduce(r);
+}
+
+/* SU= 304 */
+/* XTR xtr_a function */
+void FP4_xtr_A(FP4 *r,FP4 *w,FP4 *x,FP4 *y,FP4 *z)
+{
+    FP4 t1,t2;
+
+    FP4_copy(r,x);
+
+    FP4_sub(&t1,w,y);
+
+    FP4_pmul(&t1,&t1,&(r->a));
+    FP4_add(&t2,w,y);
+    FP4_pmul(&t2,&t2,&(r->b));
+    FP4_times_i(&t2);
+
+    FP4_add(r,&t1,&t2);
+    FP4_add(r,r,z);
+
+    FP4_norm(r);
+}
+
+/* SU= 152 */
+/* XTR xtr_d function */
+void FP4_xtr_D(FP4 *r,FP4 *x)
+{
+    FP4 w;
+    FP4_copy(r,x);
+    FP4_conj(&w,r);
+    FP4_add(&w,&w,&w);
+    FP4_sqr(r,r);
+    FP4_sub(r,r,&w);
+    FP4_reduce(r);    /* reduce here as multiple calls trigger automatic reductions */
+}
+
+/* SU= 728 */
+/* r=x^n using XTR method on traces of FP12s */
+void FP4_xtr_pow(FP4 *r,FP4 *x,BIG n)
+{
+    int i,par,nb;
+    BIG v;
+    FP2 w;
+    FP4 t,a,b,c;
+
+    BIG_zero(v);
+    BIG_inc(v,3);
+    FP2_from_BIG(&w,v);
+    FP4_from_FP2(&a,&w);
+    FP4_copy(&b,x);
+    FP4_xtr_D(&c,x);
+
+    BIG_norm(n);
+    par=BIG_parity(n);
+    BIG_copy(v,n);
+    BIG_shr(v,1);
+    if (par==0)
+    {
+        BIG_dec(v,1);
+        BIG_norm(v);
+    }
+
+    nb=BIG_nbits(v);
+
+    for (i=nb-1; i>=0; i--)
+    {
+        if (!BIG_bit(v,i))
+        {
+            FP4_copy(&t,&b);
+            FP4_conj(x,x);
+            FP4_conj(&c,&c);
+            FP4_xtr_A(&b,&a,&b,x,&c);
+            FP4_conj(x,x);
+            FP4_xtr_D(&c,&t);
+            FP4_xtr_D(&a,&a);
+        }
+        else
+        {
+            FP4_conj(&t,&a);
+            FP4_xtr_D(&a,&b);
+            FP4_xtr_A(&b,&c,&b,x,&t);
+            FP4_xtr_D(&c,&c);
+        }
+    }
+    if (par==0) FP4_copy(r,&c);
+    else FP4_copy(r,&b);
+    FP4_reduce(r);
+}
+
+/* SU= 872 */
+/* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */
+void FP4_xtr_pow2(FP4 *r,FP4 *ck,FP4 *cl,FP4 *ckml,FP4 *ckm2l,BIG a,BIG b)
+{
+    int i,f2;
+    BIG d,e,w;
+    FP4 t,cu,cv,cumv,cum2v;
+
+    BIG_norm(a);
+    BIG_norm(b);
+    BIG_copy(e,a);
+    BIG_copy(d,b);
+    FP4_copy(&cu,ck);
+    FP4_copy(&cv,cl);
+    FP4_copy(&cumv,ckml);
+    FP4_copy(&cum2v,ckm2l);
+
+    f2=0;
+    while (BIG_parity(d)==0 && BIG_parity(e)==0)
+    {
+        BIG_shr(d,1);
+        BIG_shr(e,1);
+        f2++;
+    }
+    while (BIG_comp(d,e)!=0)
+    {
+        if (BIG_comp(d,e)>0)
+        {
+            BIG_imul(w,e,4);
+            BIG_norm(w);
+            if (BIG_comp(d,w)<=0)
+            {
+                BIG_copy(w,d);
+                BIG_copy(d,e);
+                BIG_sub(e,w,e);
+                BIG_norm(e);
+                FP4_xtr_A(&t,&cu,&cv,&cumv,&cum2v);
+                FP4_conj(&cum2v,&cumv);
+                FP4_copy(&cumv,&cv);
+                FP4_copy(&cv,&cu);
+                FP4_copy(&cu,&t);
+            }
+            else if (BIG_parity(d)==0)
+            {
+                BIG_shr(d,1);
+                FP4_conj(r,&cum2v);
+                FP4_xtr_A(&t,&cu,&cumv,&cv,r);
+                FP4_xtr_D(&cum2v,&cumv);
+                FP4_copy(&cumv,&t);
+                FP4_xtr_D(&cu,&cu);
+            }
+            else if (BIG_parity(e)==1)
+            {
+                BIG_sub(d,d,e);
+                BIG_norm(d);
+                BIG_shr(d,1);
+                FP4_xtr_A(&t,&cu,&cv,&cumv,&cum2v);
+                FP4_xtr_D(&cu,&cu);
+                FP4_xtr_D(&cum2v,&cv);
+                FP4_conj(&cum2v,&cum2v);
+                FP4_copy(&cv,&t);
+            }
+            else
+            {
+                BIG_copy(w,d);
+                BIG_copy(d,e);
+                BIG_shr(d,1);
+                BIG_copy(e,w);
+                FP4_xtr_D(&t,&cumv);
+                FP4_conj(&cumv,&cum2v);
+                FP4_conj(&cum2v,&t);
+                FP4_xtr_D(&t,&cv);
+                FP4_copy(&cv,&cu);
+                FP4_copy(&cu,&t);
+            }
+        }
+        if (BIG_comp(d,e)<0)
+        {
+            BIG_imul(w,d,4);
+            BIG_norm(w);
+            if (BIG_comp(e,w)<=0)
+            {
+                BIG_sub(e,e,d);
+                BIG_norm(e);
+                FP4_xtr_A(&t,&cu,&cv,&cumv,&cum2v);
+                FP4_copy(&cum2v,&cumv);
+                FP4_copy(&cumv,&cu);
+                FP4_copy(&cu,&t);
+            }
+            else if (BIG_parity(e)==0)
+            {
+                BIG_copy(w,d);
+                BIG_copy(d,e);
+                BIG_shr(d,1);
+                BIG_copy(e,w);
+                FP4_xtr_D(&t,&cumv);
+                FP4_conj(&cumv,&cum2v);
+                FP4_conj(&cum2v,&t);
+                FP4_xtr_D(&t,&cv);
+                FP4_copy(&cv,&cu);
+                FP4_copy(&cu,&t);
+            }
+            else if (BIG_parity(d)==1)
+            {
+                BIG_copy(w,e);
+                BIG_copy(e,d);
+                BIG_sub(w,w,d);
+                BIG_norm(w);
+                BIG_copy(d,w);
+                BIG_shr(d,1);
+                FP4_xtr_A(&t,&cu,&cv,&cumv,&cum2v);
+                FP4_conj(&cumv,&cumv);
+                FP4_xtr_D(&cum2v,&cu);
+                FP4_conj(&cum2v,&cum2v);
+                FP4_xtr_D(&cu,&cv);
+                FP4_copy(&cv,&t);
+            }
+            else
+            {
+                BIG_shr(d,1);
+                FP4_conj(r,&cum2v);
+                FP4_xtr_A(&t,&cu,&cumv,&cv,r);
+                FP4_xtr_D(&cum2v,&cumv);
+                FP4_copy(&cumv,&t);
+                FP4_xtr_D(&cu,&cu);
+            }
+        }
+    }
+    FP4_xtr_A(r,&cu,&cv,&cumv,&cum2v);
+    for (i=0; i<f2; i++)	FP4_xtr_D(r,r);
+    FP4_xtr_pow(r,r,d);
+}
+/*
+int main(){
+		FP2 w0,w1,f;
+		FP4 w,t;
+		FP4 c1,c2,c3,c4,cr;
+		BIG a,b;
+		BIG e,e1,e2;
+		BIG p,md;
+
+
+		BIG_rcopy(md,Modulus);
+		//Test w^(P^4) = w mod p^2
+		BIG_zero(a); BIG_inc(a,27);
+		BIG_zero(b); BIG_inc(b,45);
+		FP2_from_BIGs(&w0,a,b);
+
+		BIG_zero(a); BIG_inc(a,33);
+		BIG_zero(b); BIG_inc(b,54);
+		FP2_from_BIGs(&w1,a,b);
+
+		FP4_from_FP2s(&w,&w0,&w1);
+		FP4_reduce(&w);
+
+		printf("w= ");
+		FP4_output(&w);
+		printf("\n");
+
+
+		FP4_copy(&t,&w);
+
+
+		BIG_copy(p,md);
+		FP4_pow(&w,&w,p);
+
+		printf("w^p= ");
+		FP4_output(&w);
+		printf("\n");
+//exit(0);
+
+		BIG_rcopy(a,CURVE_Fra);
+		BIG_rcopy(b,CURVE_Frb);
+		FP2_from_BIGs(&f,a,b);
+
+		FP4_frob(&t,&f);
+		printf("w^p= ");
+		FP4_output(&t);
+		printf("\n");
+
+		FP4_pow(&w,&w,p);
+		FP4_pow(&w,&w,p);
+		FP4_pow(&w,&w,p);
+		printf("w^p4= ");
+		FP4_output(&w);
+		printf("\n");
+
+// Test 1/(1/x) = x mod p^4
+		FP4_from_FP2s(&w,&w0,&w1);
+		printf("Test Inversion \nw= ");
+		FP4_output(&w);
+		printf("\n");
+
+		FP4_inv(&w,&w);
+		printf("1/w mod p^4 = ");
+		FP4_output(&w);
+		printf("\n");
+
+		FP4_inv(&w,&w);
+		printf("1/(1/w) mod p^4 = ");
+		FP4_output(&w);
+		printf("\n");
+
+		BIG_zero(e); BIG_inc(e,12);
+
+
+
+	//	FP4_xtr_A(&w,&t,&w,&t,&t);
+		FP4_xtr_pow(&w,&w,e);
+
+		printf("w^e= ");
+		FP4_output(&w);
+		printf("\n");
+
+
+		BIG_zero(a); BIG_inc(a,37);
+		BIG_zero(b); BIG_inc(b,17);
+		FP2_from_BIGs(&w0,a,b);
+
+		BIG_zero(a); BIG_inc(a,49);
+		BIG_zero(b); BIG_inc(b,31);
+		FP2_from_BIGs(&w1,a,b);
+
+		FP4_from_FP2s(&c1,&w0,&w1);
+		FP4_from_FP2s(&c2,&w0,&w1);
+		FP4_from_FP2s(&c3,&w0,&w1);
+		FP4_from_FP2s(&c4,&w0,&w1);
+
+		BIG_zero(e1); BIG_inc(e1,3331);
+		BIG_zero(e2); BIG_inc(e2,3372);
+
+		FP4_xtr_pow2(&w,&c1,&w,&c2,&c3,e1,e2);
+
+		printf("c^e= ");
+		FP4_output(&w);
+		printf("\n");
+
+
+		return 0;
+}
+*/
+
diff --git a/version22/c/gcm.c b/version22/c/gcm.c
new file mode 100644
index 0000000..3bd9b8d
--- /dev/null
+++ b/version22/c/gcm.c
@@ -0,0 +1,411 @@
+/*
+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.
+*/
+
+/*
+ * Implementation of the AES-GCM Encryption/Authentication
+ *
+ * Some restrictions..
+ * 1. Only for use with AES
+ * 2. Returned tag is always 128-bits. Truncate at your own risk.
+ * 3. The order of function calls must follow some rules
+ *
+ * Typical sequence of calls..
+ * 1. call GCM_init
+ * 2. call GCM_add_header any number of times, as long as length of header is multiple of 16 bytes (block size)
+ * 3. call GCM_add_header one last time with any length of header
+ * 4. call GCM_add_cipher any number of times, as long as length of cipher/plaintext is multiple of 16 bytes
+ * 5. call GCM_add_cipher one last time with any length of cipher/plaintext
+ * 6. call GCM_finish to extract the tag.
+ *
+ * See http://www.mindspring.com/~dmcgrew/gcm-nist-6.pdf
+ */
+/* SU=m, m is Stack Usage */
+
+#include <stdlib.h>
+#include <string.h>
+#include "arch.h"
+#include "amcl.h"
+
+#define NB 4
+#define MR_TOBYTE(x) ((uchar)((x)))
+
+static unsign32 pack(const uchar *b)
+{
+    /* pack bytes into a 32-bit Word */
+    return ((unsign32)b[0]<<24)|((unsign32)b[1]<<16)|((unsign32)b[2]<<8)|(unsign32)b[3];
+}
+
+static void unpack(unsign32 a,uchar *b)
+{
+    /* unpack bytes from a word */
+    b[3]=MR_TOBYTE(a);
+    b[2]=MR_TOBYTE(a>>8);
+    b[1]=MR_TOBYTE(a>>16);
+    b[0]=MR_TOBYTE(a>>24);
+}
+
+static void precompute(gcm *g,uchar *H)
+{
+    /* precompute small 2k bytes gf2m table of x^n.H */
+    int i,j;
+    unsign32 *last,*next,b;
+
+    for (i=j=0; i<NB; i++,j+=4) g->table[0][i]=pack((uchar *)&H[j]);
+
+    for (i=1; i<128; i++)
+    {
+        next=g->table[i];
+        last=g->table[i-1];
+        b=0;
+        for (j=0; j<NB; j++)
+        {
+            next[j]=b|(last[j])>>1;
+            b=last[j]<<31;
+        }
+        if (b) next[0]^=0xE1000000; /* irreducible polynomial */
+    }
+}
+
+/* SU= 32 */
+static void gf2mul(gcm *g)
+{
+    /* gf2m mul - Z=H*X mod 2^128 */
+    int i,j,m,k;
+    unsign32 P[4];
+    unsign32 b;
+
+    P[0]=P[1]=P[2]=P[3]=0;
+    j=8;
+    m=0;
+    for (i=0; i<128; i++)
+    {
+        b=(unsign32)(g->stateX[m]>>(--j))&1;
+        b=~b+1;
+        for (k=0; k<NB; k++) P[k]^=(g->table[i][k]&b);
+        if (j==0)
+        {
+            j=8;
+            m++;
+            if (m==16) break;
+        }
+    }
+    for (i=j=0; i<NB; i++,j+=4) unpack(P[i],(uchar *)&g->stateX[j]);
+}
+
+/* SU= 32 */
+static void GCM_wrap(gcm *g)
+{
+    /* Finish off GHASH */
+    int i,j;
+    unsign32 F[4];
+    uchar L[16];
+
+    /* convert lengths from bytes to bits */
+    F[0]=(g->lenA[0]<<3)|(g->lenA[1]&0xE0000000)>>29;
+    F[1]=g->lenA[1]<<3;
+    F[2]=(g->lenC[0]<<3)|(g->lenC[1]&0xE0000000)>>29;
+    F[3]=g->lenC[1]<<3;
+    for (i=j=0; i<NB; i++,j+=4) unpack(F[i],(uchar *)&L[j]);
+
+    for (i=0; i<16; i++) g->stateX[i]^=L[i];
+    gf2mul(g);
+}
+
+static int GCM_ghash(gcm *g,char *plain,int len)
+{
+    int i,j=0;
+    if (g->status==GCM_ACCEPTING_HEADER) g->status=GCM_ACCEPTING_CIPHER;
+    if (g->status!=GCM_ACCEPTING_CIPHER) return 0;
+
+    while (j<len)
+    {
+        for (i=0; i<16 && j<len; i++)
+        {
+            g->stateX[i]^=plain[j++];
+            g->lenC[1]++;
+            if (g->lenC[1]==0) g->lenC[0]++;
+        }
+        gf2mul(g);
+    }
+    if (len%16!=0) g->status=GCM_NOT_ACCEPTING_MORE;
+    return 1;
+}
+
+/* SU= 48 */
+/* Initialize GCM mode */
+void GCM_init(gcm* g,int nk,char *key,int niv,char *iv)
+{
+    /* iv size niv is usually 12 bytes (96 bits). AES key size nk can be 16,24 or 32 bytes */
+    int i;
+    uchar H[16];
+    for (i=0; i<16; i++)
+    {
+        H[i]=0;
+        g->stateX[i]=0;
+    }
+
+    AES_init(&(g->a),ECB,nk,key,iv);
+    AES_ecb_encrypt(&(g->a),H);     /* E(K,0) */
+    precompute(g,H);
+
+    g->lenA[0]=g->lenC[0]=g->lenA[1]=g->lenC[1]=0;
+    if (niv==12)
+    {
+        for (i=0; i<12; i++) g->a.f[i]=iv[i];
+        unpack((unsign32)1,(uchar *)&(g->a.f[12]));  /* initialise IV */
+        for (i=0; i<16; i++) g->Y_0[i]=g->a.f[i];
+    }
+    else
+    {
+        g->status=GCM_ACCEPTING_CIPHER;
+        GCM_ghash(g,iv,niv); /* GHASH(H,0,IV) */
+        GCM_wrap(g);
+        for (i=0; i<16; i++)
+        {
+            g->a.f[i]=g->stateX[i];
+            g->Y_0[i]=g->a.f[i];
+            g->stateX[i]=0;
+        }
+        g->lenA[0]=g->lenC[0]=g->lenA[1]=g->lenC[1]=0;
+    }
+    g->status=GCM_ACCEPTING_HEADER;
+}
+
+/* SU= 24 */
+/* Add Header data - included but not encrypted */
+int GCM_add_header(gcm* g,char *header,int len)
+{
+    /* Add some header. Won't be encrypted, but will be authenticated. len is length of header */
+    int i,j=0;
+    if (g->status!=GCM_ACCEPTING_HEADER) return 0;
+
+    while (j<len)
+    {
+        for (i=0; i<16 && j<len; i++)
+        {
+            g->stateX[i]^=header[j++];
+            g->lenA[1]++;
+            if (g->lenA[1]==0) g->lenA[0]++;
+        }
+        gf2mul(g);
+    }
+    if (len%16!=0) g->status=GCM_ACCEPTING_CIPHER;
+    return 1;
+}
+
+/* SU= 48 */
+/* Add Plaintext - included and encrypted */
+int GCM_add_plain(gcm *g,char *cipher,char *plain,int len)
+{
+    /* Add plaintext to extract ciphertext, len is length of plaintext.  */
+    int i,j=0;
+    unsign32 counter;
+    uchar B[16];
+    if (g->status==GCM_ACCEPTING_HEADER) g->status=GCM_ACCEPTING_CIPHER;
+    if (g->status!=GCM_ACCEPTING_CIPHER) return 0;
+
+    while (j<len)
+    {
+        counter=pack((uchar *)&(g->a.f[12]));
+        counter++;
+        unpack(counter,(uchar *)&(g->a.f[12]));  /* increment counter */
+        for (i=0; i<16; i++) B[i]=g->a.f[i];
+        AES_ecb_encrypt(&(g->a),B);        /* encrypt it  */
+
+        for (i=0; i<16 && j<len; i++)
+        {
+            cipher[j]=plain[j]^B[i];
+            g->stateX[i]^=cipher[j++];
+            g->lenC[1]++;
+            if (g->lenC[1]==0) g->lenC[0]++;
+        }
+        gf2mul(g);
+    }
+    if (len%16!=0) g->status=GCM_NOT_ACCEPTING_MORE;
+    return 1;
+}
+
+/* SU= 48 */
+/* Add Ciphertext - decrypts to plaintext */
+int GCM_add_cipher(gcm *g,char *plain,char *cipher,int len)
+{
+    /* Add ciphertext to extract plaintext, len is length of ciphertext. */
+    int i,j=0;
+    unsign32 counter;
+    char oc;
+    uchar B[16];
+    if (g->status==GCM_ACCEPTING_HEADER) g->status=GCM_ACCEPTING_CIPHER;
+    if (g->status!=GCM_ACCEPTING_CIPHER) return 0;
+
+    while (j<len)
+    {
+        counter=pack((uchar *)&(g->a.f[12]));
+        counter++;
+        unpack(counter,(uchar *)&(g->a.f[12]));  /* increment counter */
+        for (i=0; i<16; i++) B[i]=g->a.f[i];
+        AES_ecb_encrypt(&(g->a),B);        /* encrypt it  */
+        for (i=0; i<16 && j<len; i++)
+        {
+            oc=cipher[j];
+            plain[j]=cipher[j]^B[i];
+            g->stateX[i]^=oc;
+            j++;
+            g->lenC[1]++;
+            if (g->lenC[1]==0) g->lenC[0]++;
+        }
+        gf2mul(g);
+    }
+    if (len%16!=0) g->status=GCM_NOT_ACCEPTING_MORE;
+    return 1;
+}
+
+/* SU= 16 */
+/* Finish and extract Tag */
+void GCM_finish(gcm *g,char *tag)
+{
+    /* Finish off GHASH and extract tag (MAC) */
+    int i;
+
+    GCM_wrap(g);
+
+    /* extract tag */
+    if (tag!=NULL)
+    {
+        AES_ecb_encrypt(&(g->a),g->Y_0);        /* E(K,Y0) */
+        for (i=0; i<16; i++) g->Y_0[i]^=g->stateX[i];
+        for (i=0; i<16; i++)
+        {
+            tag[i]=g->Y_0[i];
+            g->Y_0[i]=g->stateX[i]=0;
+        }
+    }
+    g->status=GCM_FINISHED;
+    AES_end(&(g->a));
+}
+
+
+// Compile with
+// gcc -O2 gcm.c aes.c -o gcm.exe
+/* SU= 16
+*/
+
+/* static void hex2bytes(char *hex,char *bin) */
+/* { */
+/* 	int i; */
+/* 	char v; */
+/* 	int len=strlen(hex); */
+/* 	for (i = 0; i < len/2; i++) { */
+/*         char c = hex[2*i]; */
+/*         if (c >= '0' && c <= '9') { */
+/*             v = c - '0'; */
+/*         } else if (c >= 'A' && c <= 'F') { */
+/*             v = c - 'A' + 10; */
+/*         } else if (c >= 'a' && c <= 'f') { */
+/*             v = c - 'a' + 10; */
+/*         } else { */
+/*             v = 0; */
+/*         } */
+/*         v <<= 4; */
+/*         c = hex[2*i + 1]; */
+/*         if (c >= '0' && c <= '9') { */
+/*             v += c - '0'; */
+/*         } else if (c >= 'A' && c <= 'F') { */
+/*             v += c - 'A' + 10; */
+/*         } else if (c >= 'a' && c <= 'f') { */
+/*             v += c - 'a' + 10; */
+/*         } else { */
+/*             v = 0; */
+/*         } */
+/*         bin[i] = v; */
+/*     } */
+/* } */
+
+/*
+int main()
+{
+	int i;
+
+//	char* KT="feffe9928665731c6d6a8f9467308308";
+//	char* MT="d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39";
+//	char* HT="feedfacedeadbeeffeedfacedeadbeefabaddad2";
+//	char* NT="cafebabefacedbaddecaf888";
+// Tag should be 5bc94fbc3221a5db94fae95ae7121a47
+//	char* NT="9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b";
+// Tag should be 619cc5aefffe0bfa462af43c1699d050
+
+  char* KT="6dfb5dc68af6ae2f3242e9184f100918";
+  char* MT="47809d16c2c6ec685962c90e53fe1bba";
+  char* HT="dd0fa6e494031139d71ee45f00d56fa4";
+  char* NT="37d36f5c54d53479d4745dd1";
+
+
+	int len=strlen(MT)/2;
+	int lenH=strlen(HT)/2;
+	int lenK=strlen(KT)/2;
+	int lenIV=strlen(NT)/2;
+
+	char T[16];   // Tag
+	char K[16];   // AES Key
+	char H[64];   // Header - to be included in Authentication, but not encrypted
+	char N[100];   // IV - Initialisation vector
+	char M[100];  // Plaintext to be encrypted/authenticated
+	char C[100];  // Ciphertext
+	char P[100];  // Recovered Plaintext
+
+	gcm g;
+
+    hex2bytes(MT, M);
+    hex2bytes(HT, H);
+    hex2bytes(NT, N);
+	hex2bytes(KT, K);
+
+	printf("lenK= %d\n",lenK);
+
+ 	printf("Plaintext=\n");
+	for (i=0;i<len;i++) printf("%02x",(unsigned char)M[i]);
+	printf("\n");
+
+	GCM_init(&g,16,K,lenIV,N);
+	GCM_add_header(&g,H,lenH);
+	GCM_add_plain(&g,C,M,len);
+	GCM_finish(&g,T);
+
+	printf("Ciphertext=\n");
+	for (i=0;i<len;i++) printf("%02x",(unsigned char)C[i]);
+	printf("\n");
+
+	printf("Tag=\n");
+	for (i=0;i<16;i++) printf("%02x",(unsigned char)T[i]);
+	printf("\n");
+
+	GCM_init(&g,16,K,lenIV,N);
+	GCM_add_header(&g,H,lenH);
+	GCM_add_cipher(&g,P,C,len);
+	GCM_finish(&g,T);
+
+ 	printf("Plaintext=\n");
+	for (i=0;i<len;i++) printf("%02x",(unsigned char)P[i]);
+	printf("\n");
+
+	printf("Tag=\n");
+	for (i=0;i<16;i++) printf("%02x",(unsigned char)T[i]);
+	printf("\n");
+}
+
+*/
diff --git a/version22/c/hash.c b/version22/c/hash.c
new file mode 100644
index 0000000..6e6192d
--- /dev/null
+++ b/version22/c/hash.c
@@ -0,0 +1,422 @@
+/*
+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.
+*/
+
+/*
+ * Implementation of the Secure Hashing Algorithm (SHA-256/384/512)
+ *
+ * Generates a 256/384/512 bit message digest. It should be impossible to come
+ * come up with two messages that hash to the same value ("collision free").
+ *
+ * For use with byte-oriented messages only. Could/Should be speeded
+ * up by unwinding loops in HASH_transform(), and assembly patches.
+ */
+
+#include "arch.h"
+#include "amcl.h"
+
+
+#define H0_256 0x6A09E667L
+#define H1_256 0xBB67AE85L
+#define H2_256 0x3C6EF372L
+#define H3_256 0xA54FF53AL
+#define H4_256 0x510E527FL
+#define H5_256 0x9B05688CL
+#define H6_256 0x1F83D9ABL
+#define H7_256 0x5BE0CD19L
+
+static const unsign32 K_256[64]=
+{
+    0x428a2f98L,0x71374491L,0xb5c0fbcfL,0xe9b5dba5L,0x3956c25bL,0x59f111f1L,0x923f82a4L,0xab1c5ed5L,
+    0xd807aa98L,0x12835b01L,0x243185beL,0x550c7dc3L,0x72be5d74L,0x80deb1feL,0x9bdc06a7L,0xc19bf174L,
+    0xe49b69c1L,0xefbe4786L,0x0fc19dc6L,0x240ca1ccL,0x2de92c6fL,0x4a7484aaL,0x5cb0a9dcL,0x76f988daL,
+    0x983e5152L,0xa831c66dL,0xb00327c8L,0xbf597fc7L,0xc6e00bf3L,0xd5a79147L,0x06ca6351L,0x14292967L,
+    0x27b70a85L,0x2e1b2138L,0x4d2c6dfcL,0x53380d13L,0x650a7354L,0x766a0abbL,0x81c2c92eL,0x92722c85L,
+    0xa2bfe8a1L,0xa81a664bL,0xc24b8b70L,0xc76c51a3L,0xd192e819L,0xd6990624L,0xf40e3585L,0x106aa070L,
+    0x19a4c116L,0x1e376c08L,0x2748774cL,0x34b0bcb5L,0x391c0cb3L,0x4ed8aa4aL,0x5b9cca4fL,0x682e6ff3L,
+    0x748f82eeL,0x78a5636fL,0x84c87814L,0x8cc70208L,0x90befffaL,0xa4506cebL,0xbef9a3f7L,0xc67178f2L
+};
+
+#define PAD  0x80
+#define ZERO 0
+
+/* functions */
+
+#define S(m,n,x) (((x)>>n) | ((x)<<(m-n)))
+#define R(n,x) ((x)>>n)
+
+#define Ch(x,y,z)  ((x&y)^(~(x)&z))
+#define Maj(x,y,z) ((x&y)^(x&z)^(y&z))
+#define Sig0_256(x)    (S(32,2,x)^S(32,13,x)^S(32,22,x))
+#define Sig1_256(x)    (S(32,6,x)^S(32,11,x)^S(32,25,x))
+#define theta0_256(x)  (S(32,7,x)^S(32,18,x)^R(3,x))
+#define theta1_256(x)  (S(32,17,x)^S(32,19,x)^R(10,x))
+
+#define Sig0_512(x)    (S(64,28,x)^S(64,34,x)^S(64,39,x))
+#define Sig1_512(x)    (S(64,14,x)^S(64,18,x)^S(64,41,x))
+#define theta0_512(x)  (S(64,1,x)^S(64,8,x)^R(7,x))
+#define theta1_512(x)  (S(64,19,x)^S(64,61,x)^R(6,x))
+
+
+/* SU= 72 */
+static void HASH256_transform(hash256 *sh)
+{
+    /* basic transformation step */
+    unsign32 a,b,c,d,e,f,g,h,t1,t2;
+    int j;
+    for (j=16; j<64; j++)
+        sh->w[j]=theta1_256(sh->w[j-2])+sh->w[j-7]+theta0_256(sh->w[j-15])+sh->w[j-16];
+
+    a=sh->h[0];
+    b=sh->h[1];
+    c=sh->h[2];
+    d=sh->h[3];
+    e=sh->h[4];
+    f=sh->h[5];
+    g=sh->h[6];
+    h=sh->h[7];
+
+    for (j=0; j<64; j++)
+    {
+        /* 64 times - mush it up */
+        t1=h+Sig1_256(e)+Ch(e,f,g)+K_256[j]+sh->w[j];
+        t2=Sig0_256(a)+Maj(a,b,c);
+        h=g;
+        g=f;
+        f=e;
+        e=d+t1;
+        d=c;
+        c=b;
+        b=a;
+        a=t1+t2;
+    }
+
+    sh->h[0]+=a;
+    sh->h[1]+=b;
+    sh->h[2]+=c;
+    sh->h[3]+=d;
+    sh->h[4]+=e;
+    sh->h[5]+=f;
+    sh->h[6]+=g;
+    sh->h[7]+=h;
+}
+
+/* Initialise Hash function */
+void HASH256_init(hash256 *sh)
+{
+    /* re-initialise */
+    int i;
+    for (i=0; i<64; i++) sh->w[i]=0L;
+    sh->length[0]=sh->length[1]=0L;
+    sh->h[0]=H0_256;
+    sh->h[1]=H1_256;
+    sh->h[2]=H2_256;
+    sh->h[3]=H3_256;
+    sh->h[4]=H4_256;
+    sh->h[5]=H5_256;
+    sh->h[6]=H6_256;
+    sh->h[7]=H7_256;
+
+    sh->hlen=32;
+}
+
+/* process a single byte */
+void HASH256_process(hash256 *sh,int byte)
+{
+    /* process the next message byte */
+    int cnt;
+//printf("byt= %x\n",byte);
+    cnt=(int)((sh->length[0]/32)%16);
+
+    sh->w[cnt]<<=8;
+    sh->w[cnt]|=(unsign32)(byte&0xFF);
+
+    sh->length[0]+=8;
+    if (sh->length[0]==0L)
+    {
+        sh->length[1]++;
+        sh->length[0]=0L;
+    }
+    if ((sh->length[0]%512)==0) HASH256_transform(sh);
+}
+
+/* SU= 24 */
+/* Generate 32-byte Hash */
+void HASH256_hash(hash256 *sh,char *digest)
+{
+    /* pad message and finish - supply digest */
+    int i;
+    unsign32 len0,len1;
+    len0=sh->length[0];
+    len1=sh->length[1];
+    HASH256_process(sh,PAD);
+    while ((sh->length[0]%512)!=448) HASH256_process(sh,ZERO);
+    sh->w[14]=len1;
+    sh->w[15]=len0;
+    HASH256_transform(sh);
+    for (i=0; i<sh->hlen; i++)
+    {
+        /* convert to bytes */
+        digest[i]=(char)((sh->h[i/4]>>(8*(3-i%4))) & 0xffL);
+    }
+    HASH256_init(sh);
+}
+
+
+#define H0_512 0x6a09e667f3bcc908
+#define H1_512 0xbb67ae8584caa73b
+#define H2_512 0x3c6ef372fe94f82b
+#define H3_512 0xa54ff53a5f1d36f1
+#define H4_512 0x510e527fade682d1
+#define H5_512 0x9b05688c2b3e6c1f
+#define H6_512 0x1f83d9abfb41bd6b
+#define H7_512 0x5be0cd19137e2179
+
+#define H8_512 0xcbbb9d5dc1059ed8
+#define H9_512 0x629a292a367cd507
+#define HA_512 0x9159015a3070dd17
+#define HB_512 0x152fecd8f70e5939
+#define HC_512 0x67332667ffc00b31
+#define HD_512 0x8eb44a8768581511
+#define HE_512 0xdb0c2e0d64f98fa7
+#define HF_512 0x47b5481dbefa4fa4
+
+/* */
+
+static const unsign64 K_512[80]=
+{
+    0x428a2f98d728ae22 ,0x7137449123ef65cd ,0xb5c0fbcfec4d3b2f ,0xe9b5dba58189dbbc ,
+    0x3956c25bf348b538 ,0x59f111f1b605d019 ,0x923f82a4af194f9b ,0xab1c5ed5da6d8118 ,
+    0xd807aa98a3030242 ,0x12835b0145706fbe ,0x243185be4ee4b28c ,0x550c7dc3d5ffb4e2 ,
+    0x72be5d74f27b896f ,0x80deb1fe3b1696b1 ,0x9bdc06a725c71235 ,0xc19bf174cf692694 ,
+    0xe49b69c19ef14ad2 ,0xefbe4786384f25e3 ,0x0fc19dc68b8cd5b5 ,0x240ca1cc77ac9c65 ,
+    0x2de92c6f592b0275 ,0x4a7484aa6ea6e483 ,0x5cb0a9dcbd41fbd4 ,0x76f988da831153b5 ,
+    0x983e5152ee66dfab ,0xa831c66d2db43210 ,0xb00327c898fb213f ,0xbf597fc7beef0ee4 ,
+    0xc6e00bf33da88fc2 ,0xd5a79147930aa725 ,0x06ca6351e003826f ,0x142929670a0e6e70 ,
+    0x27b70a8546d22ffc ,0x2e1b21385c26c926 ,0x4d2c6dfc5ac42aed ,0x53380d139d95b3df ,
+    0x650a73548baf63de ,0x766a0abb3c77b2a8 ,0x81c2c92e47edaee6 ,0x92722c851482353b ,
+    0xa2bfe8a14cf10364 ,0xa81a664bbc423001 ,0xc24b8b70d0f89791 ,0xc76c51a30654be30 ,
+    0xd192e819d6ef5218 ,0xd69906245565a910 ,0xf40e35855771202a ,0x106aa07032bbd1b8 ,
+    0x19a4c116b8d2d0c8 ,0x1e376c085141ab53 ,0x2748774cdf8eeb99 ,0x34b0bcb5e19b48a8 ,
+    0x391c0cb3c5c95a63 ,0x4ed8aa4ae3418acb ,0x5b9cca4f7763e373 ,0x682e6ff3d6b2b8a3 ,
+    0x748f82ee5defb2fc ,0x78a5636f43172f60 ,0x84c87814a1f0ab72 ,0x8cc702081a6439ec ,
+    0x90befffa23631e28 ,0xa4506cebde82bde9 ,0xbef9a3f7b2c67915 ,0xc67178f2e372532b ,
+    0xca273eceea26619c ,0xd186b8c721c0c207 ,0xeada7dd6cde0eb1e ,0xf57d4f7fee6ed178 ,
+    0x06f067aa72176fba ,0x0a637dc5a2c898a6 ,0x113f9804bef90dae ,0x1b710b35131c471b ,
+    0x28db77f523047d84 ,0x32caab7b40c72493 ,0x3c9ebe0a15c9bebc ,0x431d67c49c100d4c ,
+    0x4cc5d4becb3e42b6 ,0x597f299cfc657e2a ,0x5fcb6fab3ad6faec ,0x6c44198c4a475817
+};
+
+
+static void HASH512_transform(hash512 *sh)
+{
+    /* basic transformation step */
+    unsign64 a,b,c,d,e,f,g,h,t1,t2;
+    int j;
+    for (j=16; j<80; j++)
+        sh->w[j]=theta1_512(sh->w[j-2])+sh->w[j-7]+theta0_512(sh->w[j-15])+sh->w[j-16];
+
+    a=sh->h[0];
+    b=sh->h[1];
+    c=sh->h[2];
+    d=sh->h[3];
+    e=sh->h[4];
+    f=sh->h[5];
+    g=sh->h[6];
+    h=sh->h[7];
+
+    for (j=0; j<80; j++)
+    {
+        /* 80 times - mush it up */
+        t1=h+Sig1_512(e)+Ch(e,f,g)+K_512[j]+sh->w[j];
+        t2=Sig0_512(a)+Maj(a,b,c);
+        h=g;
+        g=f;
+        f=e;
+        e=d+t1;
+        d=c;
+        c=b;
+        b=a;
+        a=t1+t2;
+    }
+    sh->h[0]+=a;
+    sh->h[1]+=b;
+    sh->h[2]+=c;
+    sh->h[3]+=d;
+    sh->h[4]+=e;
+    sh->h[5]+=f;
+    sh->h[6]+=g;
+    sh->h[7]+=h;
+}
+
+void HASH384_init(hash384 *sh)
+{
+    /* re-initialise */
+    int i;
+    for (i=0; i<80; i++) sh->w[i]=0;
+    sh->length[0]=sh->length[1]=0;
+    sh->h[0]=H8_512;
+    sh->h[1]=H9_512;
+    sh->h[2]=HA_512;
+    sh->h[3]=HB_512;
+    sh->h[4]=HC_512;
+    sh->h[5]=HD_512;
+    sh->h[6]=HE_512;
+    sh->h[7]=HF_512;
+
+    sh->hlen=48;
+
+}
+
+void HASH384_process(hash384 *sh,int byte)
+{
+    /* process the next message byte */
+    HASH512_process(sh,byte);
+}
+
+void HASH384_hash(hash384 *sh,char *hash)
+{
+    /* pad message and finish - supply digest */
+    HASH512_hash(sh,hash);
+}
+
+void HASH512_init(hash512 *sh)
+{
+    /* re-initialise */
+    int i;
+
+    for (i=0; i<80; i++) sh->w[i]=0;
+    sh->length[0]=sh->length[1]=0;
+    sh->h[0]=H0_512;
+    sh->h[1]=H1_512;
+    sh->h[2]=H2_512;
+    sh->h[3]=H3_512;
+    sh->h[4]=H4_512;
+    sh->h[5]=H5_512;
+    sh->h[6]=H6_512;
+    sh->h[7]=H7_512;
+
+    sh->hlen=64;
+}
+
+void HASH512_process(hash512 *sh,int byte)
+{
+    /* process the next message byte */
+    int cnt;
+
+    cnt=(int)((sh->length[0]/64)%16);
+
+    sh->w[cnt]<<=8;
+    sh->w[cnt]|=(unsign64)(byte&0xFF);
+
+    sh->length[0]+=8;
+    if (sh->length[0]==0L)
+    {
+        sh->length[1]++;
+        sh->length[0]=0L;
+    }
+    if ((sh->length[0]%1024)==0) HASH512_transform(sh);
+}
+
+void HASH512_hash(hash512 *sh,char *hash)
+{
+    /* pad message and finish - supply digest */
+    int i;
+    unsign64 len0,len1;
+    len0=sh->length[0];
+    len1=sh->length[1];
+    HASH512_process(sh,PAD);
+    while ((sh->length[0]%1024)!=896) HASH512_process(sh,ZERO);
+    sh->w[14]=len1;
+    sh->w[15]=len0;
+    HASH512_transform(sh);
+    for (i=0; i<sh->hlen; i++)
+    {
+        /* convert to bytes */
+        hash[i]=(char)((sh->h[i/8]>>(8*(7-i%8))) & 0xffL);
+    }
+    HASH512_init(sh);
+}
+
+
+/* test program: should produce digest
+
+160 bit
+
+84983e44 1c3bd26e baae4aa1 f95129e5 e54670f1
+
+256 bit
+
+248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1
+
+512 bit
+
+8e959b75dae313da 8cf4f72814fc143f 8f7779c6eb9f7fa1 7299aeadb6889018
+501d289e4900f7e4 331b99dec4b5433a c7d329eeb6dd2654 5e96e55b874be909
+
+384 bit
+
+09330c33f71147e8 3d192fc782cd1b47 53111b173b3b05d2 2fa08086e3b0f712
+fcc7c71a557e2db9 66c3e9fa91746039
+*/
+/*
+#include <stdio.h>
+#include "aracrypt.h"
+
+char test160[]="abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
+char test256[]="abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
+char test512[]="abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu";
+
+int main()
+{
+    char digest[64];
+    int i;
+	hash160 sh160;
+    hash256 sh256;
+	hash384 sh384;
+	hash512 sh512;
+
+    HASH160_init(&sh160);
+    for (i=0;test256[i]!=0;i++) HASH160_process(&sh160,test160[i]);
+    HASH160_hash(&sh160,digest);
+    for (i=0;i<20;i++) printf("%02x",(unsigned char)digest[i]);
+    printf("\n");
+
+    HASH256_init(&sh256);
+    for (i=0;test256[i]!=0;i++) HASH256_process(&sh256,test256[i]);
+    HASH256_hash(&sh256,digest);
+    for (i=0;i<32;i++) printf("%02x",(unsigned char)digest[i]);
+    printf("\n");
+
+    HASH384_init(&sh384);
+    for (i=0;test512[i]!=0;i++) HASH384_process(&sh384,test512[i]);
+    HASH384_hash(&sh384,digest);
+    for (i=0;i<48;i++) printf("%02x",(unsigned char)digest[i]);
+    printf("\n");
+
+    HASH512_init(&sh512);
+    for (i=0;test512[i]!=0;i++) HASH512_process(&sh512,test512[i]);
+    HASH512_hash(&sh512,digest);
+    for (i=0;i<64;i++) printf("%02x",(unsigned char)digest[i]);
+    printf("\n");
+
+
+    return 0;
+}
+
+*/
diff --git a/version22/c/maxstack.c b/version22/c/maxstack.c
new file mode 100644
index 0000000..77b2062
--- /dev/null
+++ b/version22/c/maxstack.c
@@ -0,0 +1,62 @@
+/*
+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.
+*/
+
+/*
+	How to determine maximum stack usage
+	1. Compile this file *with no optimization*, for example gcc -c maxstack.c
+	2. Rename your main() function to mymain()
+	3. Compile with normal level of optimization, linking to maxstack.o for example gcc maxstack.o -O3 myprogram.c -o myprogam
+	4. Execute myprogram
+	5. Program runs, at end prints out maximum stack usage
+
+	Caveat Code!
+	Mike Scott October 2014
+*/
+
+#include <stdio.h>
+
+#define MAXSTACK 65536  /* greater than likely stack requirement */
+
+extern void mymain();
+
+void start()
+{
+    char stack[MAXSTACK];
+    int i;
+    for (i=0; i<MAXSTACK; i++) stack[i]=0x55;
+}
+
+void finish()
+{
+    char stack[MAXSTACK];
+    int i;
+    for (i=0; i<MAXSTACK; i++)
+        if (stack[i]!=0x55) break;
+    printf("Max Stack usage = %d\n",MAXSTACK-i);
+}
+
+int main()
+{
+    start();
+
+    mymain();
+
+    finish();
+    return 0;
+}
diff --git a/version22/c/mpin.c b/version22/c/mpin.c
new file mode 100644
index 0000000..5086ad5
--- /dev/null
+++ b/version22/c/mpin.c
@@ -0,0 +1,1212 @@
+/*
+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.
+*/
+
+/* MPIN Functions */
+
+/* Version 3.0 - supports Time Permits */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "mpin.h"
+
+#define ROUNDUP(a,b) ((a)-1)/(b)+1
+
+/* Special mpin hashing */
+static void mpin_hash(int sha,FP4 *f, ECP *P,octet *w)
+{
+    int i;
+    BIG x,y;
+    char h[64];
+    hash256 sha256;
+    hash512 sha512;
+    char t[6*MODBYTES];  // to hold 6 BIGs
+    int hlen=sha;
+    BIG_copy(x,f->a.a);
+    FP_redc(x);
+    BIG_toBytes(&t[0],x);
+    BIG_copy(x,f->a.b);
+    FP_redc(x);
+    BIG_toBytes(&t[MODBYTES],x);
+    BIG_copy(x,f->b.a);
+    FP_redc(x);
+    BIG_toBytes(&t[2*MODBYTES],x);
+    BIG_copy(x,f->b.b);
+    FP_redc(x);
+    BIG_toBytes(&t[3*MODBYTES],x);
+    ECP_get(x,y,P);
+    BIG_toBytes(&t[4*MODBYTES],x);
+    BIG_toBytes(&t[5*MODBYTES],y);
+
+    OCT_empty(w);
+    switch (sha)
+    {
+    case SHA256:
+        HASH256_init(&sha256);
+        for (i=0; i<6*MODBYTES; i++) HASH256_process(&sha256,t[i]);
+        HASH256_hash(&sha256,h);
+        break;
+    case SHA384:
+        HASH384_init(&sha512);
+        for (i=0; i<6*MODBYTES; i++) HASH384_process(&sha512,t[i]);
+        HASH384_hash(&sha512,h);
+        break;
+    case SHA512:
+        HASH512_init(&sha512);
+        for (i=0; i<6*MODBYTES; i++) HASH512_process(&sha512,t[i]);
+        HASH512_hash(&sha512,h);
+        break;
+    }
+
+    OCT_jbytes(w,h,PAS);
+    for (i=0; i<hlen; i++) h[i]=0;
+}
+
+/* these next two functions help to implement elligator squared - http://eprint.iacr.org/2014/043 */
+/* maps a random u to a point on the curve */
+static void map(ECP *P,BIG u,int cb)
+{
+    BIG x,q;
+
+    BIG_rcopy(q,Modulus);
+    BIG_copy(x,u);
+    BIG_mod(x,q);
+
+    while (!ECP_setx(P,x,cb))
+        BIG_inc(x,1);
+}
+
+/* returns u derived from P. Random value in range 1 to return value should then be added to u */
+static int unmap(BIG u,int *cb,ECP *P)
+{
+    int s,r=0;
+    BIG x;
+
+    s=ECP_get(x,x,P);
+    BIG_copy(u,x);
+    do
+    {
+        BIG_dec(u,1);
+        r++;
+    }
+    while (!ECP_setx(P,u,s));
+    ECP_setx(P,x,s);
+
+    *cb=s;
+
+    return r;
+}
+
+/* map octet string containing hash to point on curve of correct order */
+static void mapit(octet *h,ECP *P)
+{
+    BIG q,x,c;
+    BIG_fromBytes(x,h->val);
+    BIG_rcopy(q,Modulus);
+    BIG_mod(x,q);
+
+    while (!ECP_setx(P,x,0))
+        BIG_inc(x,1);
+
+    BIG_rcopy(c,CURVE_Cof);
+    ECP_mul(P,c);
+}
+
+/* needed for SOK */
+/* static void mapit2(octet *h,ECP2 *Q) */
+/* { */
+/* 	BIG q,one,Fx,Fy,x,hv; */
+/* 	FP2 X; */
+/* 	ECP2 T,K; */
+/* 	BIG_fromBytes(hv,h->val); */
+/* 	BIG_rcopy(q,Modulus); */
+/* 	BIG_one(one); */
+/* 	BIG_mod(hv,q); */
+
+/* 	for (;;) */
+/* 	{ */
+/* 		FP2_from_BIGs(&X,one,hv); */
+/* 		if (ECP2_setx(Q,&X)) break; */
+/* 		BIG_inc(hv,1);  */
+/* 	} */
+
+/* /\* Fast Hashing to G2 - Fuentes-Castaneda, Knapp and Rodriguez-Henriquez *\/ */
+/* 	BIG_rcopy(Fx,CURVE_Fra); */
+/* 	BIG_rcopy(Fy,CURVE_Frb); */
+/* 	FP2_from_BIGs(&X,Fx,Fy); */
+/* 	BIG_rcopy(x,CURVE_Bnx); */
+
+/* 	ECP2_copy(&T,Q); */
+/* 	ECP2_mul(&T,x); */
+/* 	ECP2_neg(&T);  /\* our x is negative *\/ */
+/* 	ECP2_copy(&K,&T); */
+/* 	ECP2_dbl(&K); */
+/* 	ECP2_add(&K,&T); */
+/* 	ECP2_affine(&K); */
+
+/* 	ECP2_frob(&K,&X); */
+/* 	ECP2_frob(Q,&X); ECP2_frob(Q,&X); ECP2_frob(Q,&X);  */
+/* 	ECP2_add(Q,&T); */
+/* 	ECP2_add(Q,&K); */
+/* 	ECP2_frob(&T,&X); ECP2_frob(&T,&X); */
+/* 	ECP2_add(Q,&T); */
+/* 	ECP2_affine(Q); */
+/* } */
+
+
+
+/* general purpose hash function w=hash(p|n|x|y) */
+static void hashit(int sha,int n,octet *x,octet *w)
+{
+    int i,c[4],hlen;
+    hash256 sha256;
+    hash512 sha512;
+    char hh[64];
+
+    switch (sha)
+    {
+    case SHA256:
+        HASH256_init(&sha256);
+        break;
+    case SHA384:
+        HASH384_init(&sha512);
+        break;
+    case SHA512:
+        HASH512_init(&sha512);
+        break;
+    }
+
+    hlen=sha;
+
+    if (n>0)
+    {
+        c[0]=(n>>24)&0xff;
+        c[1]=(n>>16)&0xff;
+        c[2]=(n>>8)&0xff;
+        c[3]=(n)&0xff;
+        for (i=0; i<4; i++)
+        {
+            switch(sha)
+            {
+            case SHA256:
+                HASH256_process(&sha256,c[i]);
+                break;
+            case SHA384:
+                HASH384_process(&sha512,c[i]);
+                break;
+            case SHA512:
+                HASH512_process(&sha512,c[i]);
+                break;
+            }
+        }
+    }
+    if (x!=NULL) for (i=0; i<x->len; i++)
+        {
+            switch(sha)
+            {
+            case SHA256:
+                HASH256_process(&sha256,x->val[i]);
+                break;
+            case SHA384:
+                HASH384_process(&sha512,x->val[i]);
+                break;
+            case SHA512:
+                HASH512_process(&sha512,x->val[i]);
+                break;
+            }
+        }
+
+    for (i=0; i<hlen; i++) hh[i]=0;
+    switch (sha)
+    {
+    case SHA256:
+        HASH256_hash(&sha256,hh);
+        break;
+    case SHA384:
+        HASH384_hash(&sha512,hh);
+        break;
+    case SHA512:
+        HASH512_hash(&sha512,hh);
+        break;
+    }
+
+    OCT_empty(w);
+
+    if (hlen>=MODBYTES)
+        OCT_jbytes(w,hh,MODBYTES);
+    else
+    {
+        OCT_jbytes(w,hh,hlen);
+        OCT_jbyte(w,0,MODBYTES-hlen);
+    }
+}
+
+unsign32 MPIN_today(void)
+{
+    /* return time in slots since epoch */
+    unsign32 ti=(unsign32)time(NULL);
+    return (uint32_t)(ti/(60*TIME_SLOT_MINUTES));
+}
+
+/* Hash the M-Pin transcript - new */
+
+void MPIN_HASH_ALL(int sha,octet *HID,octet *xID,octet *xCID,octet *SEC,octet *Y,octet *R,octet *W,octet *H)
+{
+    char t[10*MODBYTES+4];
+    octet T= {0,sizeof(t),t};
+
+    OCT_joctet(&T,HID);
+    if (xCID!=NULL) OCT_joctet(&T,xCID);
+    else OCT_joctet(&T,xID);
+    OCT_joctet(&T,SEC);
+    OCT_joctet(&T,Y);
+    OCT_joctet(&T,R);
+    OCT_joctet(&T,W);
+
+    hashit(sha,0,&T,H);
+}
+
+void MPIN_HASH_ID(int sha,octet *ID,octet *HID)
+{
+    hashit(sha,0,ID,HID);
+}
+
+/* these next two functions implement elligator squared - http://eprint.iacr.org/2014/043 */
+/* Elliptic curve point E in format (0x04,x,y} is converted to form {0x0-,u,v} */
+/* Note that u and v are indistinguisible from random strings */
+int MPIN_ENCODING(csprng *RNG,octet *E)
+{
+    int rn,m,su,sv,res=0;
+
+    BIG q,u,v;
+    ECP P,W;
+
+    if (!ECP_fromOctet(&P,E)) res=MPIN_INVALID_POINT;
+
+    if (res==0)
+    {
+        BIG_rcopy(q,Modulus);
+
+        BIG_randomnum(u,q,RNG);
+
+        su=RAND_byte(RNG);
+        if (su<0) su=-su;
+        su%=2;
+        map(&W,u,su);
+        ECP_sub(&P,&W);
+
+        rn=unmap(v,&sv,&P);
+        m=RAND_byte(RNG);
+        if (m<0) m=-m;
+        m%=rn;
+        BIG_inc(v,m+1);
+        E->val[0]=su+2*sv;
+        BIG_toBytes(&(E->val[1]),u);
+        BIG_toBytes(&(E->val[PFS+1]),v);
+    }
+
+    return res;
+}
+
+int MPIN_DECODING(octet *D)
+{
+    int su,sv;
+    BIG u,v;
+    ECP P,W;
+    int res=0;
+
+    if ((D->val[0]&0x04)!=0) res=MPIN_INVALID_POINT;
+    if (res==0)
+    {
+
+        BIG_fromBytes(u,&(D->val[1]));
+        BIG_fromBytes(v,&(D->val[PFS+1]));
+
+        su=D->val[0]&1;
+        sv=(D->val[0]>>1)&1;
+
+        map(&W,u,su);
+        map(&P,v,sv);
+
+        ECP_add(&P,&W);
+        ECP_toOctet(D,&P);
+    }
+    return res;
+}
+
+/* R=R1+R2 in group G1 */
+int MPIN_RECOMBINE_G1(octet *R1,octet *R2,octet *R)
+{
+    ECP P,T;
+    int res=0;
+    if (res==0)
+    {
+        if (!ECP_fromOctet(&P,R1)) res=MPIN_INVALID_POINT;
+        if (!ECP_fromOctet(&T,R2)) res=MPIN_INVALID_POINT;
+    }
+    if (res==0)
+    {
+        ECP_add(&P,&T);
+        ECP_toOctet(R,&P);
+    }
+    return res;
+}
+
+/* W=W1+W2 in group G2 */
+int MPIN_RECOMBINE_G2(octet *W1,octet *W2,octet *W)
+{
+    ECP2 Q,T;
+    int res=0;
+    if (!ECP2_fromOctet(&Q,W1)) res=MPIN_INVALID_POINT;
+    if (!ECP2_fromOctet(&T,W2)) res=MPIN_INVALID_POINT;
+    if (res==0)
+    {
+        ECP2_add(&Q,&T);
+        ECP2_toOctet(W,&Q);
+    }
+    return res;
+}
+
+/* create random secret S */
+int MPIN_RANDOM_GENERATE(csprng *RNG,octet* S)
+{
+    BIG r,s;
+
+    BIG_rcopy(r,CURVE_Order);
+    BIG_randomnum(s,r,RNG);
+#ifdef AES_S
+    BIG_mod2m(s,2*AES_S);
+#endif
+    BIG_toBytes(S->val,s);
+    S->len=MODBYTES;
+    return 0;
+}
+
+/* Extract PIN from TOKEN for identity CID */
+int MPIN_EXTRACT_PIN(int sha,octet *CID,int pin,octet *TOKEN)
+{
+    ECP P,R;
+    int res=0;
+    char h[MODBYTES];
+    octet H= {0,sizeof(h),h};
+
+    if (!ECP_fromOctet(&P,TOKEN))  res=MPIN_INVALID_POINT;
+    if (res==0)
+    {
+        hashit(sha,-1,CID,&H);
+        mapit(&H,&R);
+
+        pin%=MAXPIN;
+
+        ECP_pinmul(&R,pin,PBLEN);
+        ECP_sub(&P,&R);
+
+        ECP_toOctet(TOKEN,&P);
+    }
+    return res;
+}
+
+/* Implement step 2 on client side of MPin protocol - SEC=-(x+y)*SEC */
+int MPIN_CLIENT_2(octet *X,octet *Y,octet *SEC)
+{
+    BIG px,py,r;
+    ECP P;
+    int res=0;
+    BIG_rcopy(r,CURVE_Order);
+    if (!ECP_fromOctet(&P,SEC)) res=MPIN_INVALID_POINT;
+    if (res==0)
+    {
+        BIG_fromBytes(px,X->val);
+        BIG_fromBytes(py,Y->val);
+        BIG_add(px,px,py);
+        BIG_mod(px,r);
+        //	BIG_sub(px,r,px);
+        PAIR_G1mul(&P,px);
+        ECP_neg(&P);
+        ECP_toOctet(SEC,&P);
+    }
+    return res;
+}
+
+/*
+ W=x*H(G);
+ if RNG == NULL then X is passed in
+ if RNG != NULL the X is passed out
+ if type=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve
+*/
+
+int MPIN_GET_G1_MULTIPLE(csprng *RNG,int type,octet *X,octet *G,octet *W)
+{
+    ECP P;
+    BIG r,x;
+    int res=0;
+    if (RNG!=NULL)
+    {
+        BIG_rcopy(r,CURVE_Order);
+        BIG_randomnum(x,r,RNG);
+#ifdef AES_S
+        BIG_mod2m(x,2*AES_S);
+#endif
+        X->len=MODBYTES;
+        BIG_toBytes(X->val,x);
+    }
+    else
+        BIG_fromBytes(x,X->val);
+
+    if (type==0)
+    {
+        if (!ECP_fromOctet(&P,G)) res=MPIN_INVALID_POINT;
+    }
+    else mapit(G,&P);
+
+    if (res==0)
+    {
+        PAIR_G1mul(&P,x);
+        ECP_toOctet(W,&P);
+    }
+    return res;
+}
+
+/*
+ if RNG == NULL then X is passed in
+ if RNG != NULL the X is passed out
+ W=x*G where G is point on the curve
+ if type==1 W=(x^-1)G
+*/
+
+int MPIN_GET_G2_MULTIPLE(csprng *RNG,int type,octet *X,octet *G,octet *W)
+{
+    ECP2 P;
+    BIG r,x;
+    int res=0;
+    BIG_rcopy(r,CURVE_Order);
+    if (RNG!=NULL)
+    {
+        BIG_randomnum(x,r,RNG);
+#ifdef AES_S
+        BIG_mod2m(x,2*AES_S);
+#endif
+        X->len=MODBYTES;
+        BIG_toBytes(X->val,x);
+    }
+    else
+    {
+        BIG_fromBytes(x,X->val);
+        if (type==1) BIG_invmodp(x,x,r);
+    }
+
+    if (!ECP2_fromOctet(&P,G)) res=MPIN_INVALID_POINT;
+
+    if (res==0)
+    {
+        PAIR_G2mul(&P,x);
+        ECP2_toOctet(W,&P);
+    }
+    return res;
+}
+
+
+
+/* Client secret CST=s*H(CID) where CID is client ID and s is master secret */
+/* CID is hashed externally */
+int MPIN_GET_CLIENT_SECRET(octet *S,octet *CID,octet *CST)
+{
+    return MPIN_GET_G1_MULTIPLE(NULL,1,S,CID,CST);
+}
+
+/* Implement step 1 on client side of MPin protocol */
+int MPIN_CLIENT_1(int sha,int date,octet *CLIENT_ID,csprng *RNG,octet *X,int pin,octet *TOKEN,octet *SEC,octet *xID,octet *xCID,octet *PERMIT)
+{
+    BIG r,x;
+    ECP P,T,W;
+    int res=0;
+    char h[MODBYTES];
+    octet H= {0,sizeof(h),h};
+
+    BIG_rcopy(r,CURVE_Order);
+    if (RNG!=NULL)
+    {
+        BIG_randomnum(x,r,RNG);
+#ifdef AES_S
+        BIG_mod2m(x,2*AES_S);
+#endif
+        X->len=MODBYTES;
+        BIG_toBytes(X->val,x);
+    }
+    else
+        BIG_fromBytes(x,X->val);
+
+    hashit(sha,-1,CLIENT_ID,&H);
+    mapit(&H,&P);
+
+    if (!ECP_fromOctet(&T,TOKEN)) res=MPIN_INVALID_POINT;
+
+    if (res==0)
+    {
+        pin%=MAXPIN;
+
+        ECP_copy(&W,&P);				// W=H(ID)
+        ECP_pinmul(&W,pin,PBLEN);			// W=alpha.H(ID)
+        ECP_add(&T,&W);					// T=Token+alpha.H(ID) = s.H(ID)
+
+        if (date)
+        {
+            if (PERMIT!=NULL)
+            {
+                if (!ECP_fromOctet(&W,PERMIT)) res=MPIN_INVALID_POINT;
+                ECP_add(&T,&W);					// SEC=s.H(ID)+s.H(T|ID)
+            }
+            hashit(sha,date,&H,&H);
+            mapit(&H,&W);
+            if (xID!=NULL)
+            {
+                PAIR_G1mul(&P,x);				// P=x.H(ID)
+                ECP_toOctet(xID,&P);  // xID
+                PAIR_G1mul(&W,x);               // W=x.H(T|ID)
+                ECP_add(&P,&W);
+            }
+            else
+            {
+                ECP_add(&P,&W);
+                PAIR_G1mul(&P,x);
+            }
+            if (xCID!=NULL) ECP_toOctet(xCID,&P);  // U
+        }
+        else
+        {
+            if (xID!=NULL)
+            {
+                PAIR_G1mul(&P,x);				// P=x.H(ID)
+                ECP_toOctet(xID,&P);  // xID
+            }
+        }
+    }
+
+    if (res==0)
+        ECP_toOctet(SEC,&T);  // V
+
+    return res;
+}
+
+/* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */
+int MPIN_GET_SERVER_SECRET(octet *S,octet *SST)
+{
+    BIG r,s;
+    FP2 qx,qy;
+    ECP2 Q;
+    int res=0;
+
+    BIG_rcopy(r,CURVE_Order);
+    BIG_rcopy(qx.a,CURVE_Pxa);
+    FP_nres(qx.a);
+    BIG_rcopy(qx.b,CURVE_Pxb);
+    FP_nres(qx.b);
+    BIG_rcopy(qy.a,CURVE_Pya);
+    FP_nres(qy.a);
+    BIG_rcopy(qy.b,CURVE_Pyb);
+    FP_nres(qy.b);
+    ECP2_set(&Q,&qx,&qy);
+
+    if (res==0)
+    {
+        BIG_fromBytes(s,S->val);
+        PAIR_G2mul(&Q,s);
+        ECP2_toOctet(SST,&Q);
+    }
+
+    return res;
+}
+
+
+/* Time Permit CTT=s*H(date|H(CID)) where s is master secret */
+int MPIN_GET_CLIENT_PERMIT(int sha,int date,octet *S,octet *CID,octet *CTT)
+{
+    BIG s;
+    ECP P;
+    char h[MODBYTES];
+    octet H= {0,sizeof(h),h};
+
+    hashit(sha,date,CID,&H);
+
+    mapit(&H,&P);
+    BIG_fromBytes(s,S->val);
+    PAIR_G1mul(&P,s);
+
+    ECP_toOctet(CTT,&P);
+    return 0;
+}
+
+// if date=0 only use HID, set HCID=NULL
+// if date and PE, use HID and HCID
+
+/* Outputs H(CID) and H(CID)+H(T|H(CID)) for time permits. If no time permits set HTID=NULL */
+void MPIN_SERVER_1(int sha,int date,octet *CID,octet *HID,octet *HTID)
+{
+    char h[MODBYTES];
+    octet H= {0,sizeof(h),h};
+    ECP P,R;
+
+#ifdef USE_ANONYMOUS
+    mapit(CID,&P);
+#else
+    hashit(sha,-1,CID,&H);
+    mapit(&H,&P);
+#endif
+
+    ECP_toOctet(HID,&P);  // new
+
+    if (date)
+    {
+        //	if (HID!=NULL) ECP_toOctet(HID,&P);
+#ifdef USE_ANONYMOUS
+        hashit(sha,date,CID,&H);
+#else
+        hashit(sha,date,&H,&H);
+#endif
+        mapit(&H,&R);
+        ECP_add(&P,&R);
+        ECP_toOctet(HTID,&P);
+    }
+    //else ECP_toOctet(HID,&P);
+
+}
+
+/* Implement M-Pin on server side */
+int MPIN_SERVER_2(int date,octet *HID,octet *HTID,octet *Y,octet *SST,octet *xID,octet *xCID,octet *mSEC,octet *E,octet *F)
+{
+    BIG px,py,y;
+    FP2 qx,qy;
+    FP12 g;
+    ECP2 Q,sQ;
+    ECP P,R;
+    int res=0;
+
+    BIG_rcopy(qx.a,CURVE_Pxa);
+    FP_nres(qx.a);
+    BIG_rcopy(qx.b,CURVE_Pxb);
+    FP_nres(qx.b);
+    BIG_rcopy(qy.a,CURVE_Pya);
+    FP_nres(qy.a);
+    BIG_rcopy(qy.b,CURVE_Pyb);
+    FP_nres(qy.b);
+
+    if (!ECP2_set(&Q,&qx,&qy)) res=MPIN_INVALID_POINT;
+
+    if (res==0)
+    {
+        if (!ECP2_fromOctet(&sQ,SST)) res=MPIN_INVALID_POINT;
+    }
+
+    if (res==0)
+    {
+        if (date)
+        {
+            BIG_fromBytes(px,&(xCID->val[1]));
+            BIG_fromBytes(py,&(xCID->val[PFS+1]));
+        }
+        else
+        {
+            BIG_fromBytes(px,&(xID->val[1]));
+            BIG_fromBytes(py,&(xID->val[PFS+1]));
+        }
+        if (!ECP_set(&R,px,py)) res=MPIN_INVALID_POINT; // x(A+AT)
+    }
+    if (res==0)
+    {
+        BIG_fromBytes(y,Y->val);
+        if (date)
+        {
+            if (!ECP_fromOctet(&P,HTID))  res=MPIN_INVALID_POINT;
+        }
+        else
+        {
+            if (!ECP_fromOctet(&P,HID))  res=MPIN_INVALID_POINT;
+        }
+    }
+    if (res==0)
+    {
+        PAIR_G1mul(&P,y);  // y(A+AT)
+        ECP_add(&P,&R); // x(A+AT)+y(A+T)
+        if (!ECP_fromOctet(&R,mSEC))  res=MPIN_INVALID_POINT; // V
+    }
+    if (res==0)
+    {
+        PAIR_double_ate(&g,&Q,&R,&sQ,&P);
+        PAIR_fexp(&g);
+
+        if (!FP12_isunity(&g))
+        {
+            if (HID!=NULL && xID!=NULL && E!=NULL && F !=NULL)
+            {
+                /* xID is set to NULL if there is no way to calculate PIN error */
+                FP12_toOctet(E,&g);
+
+                /* Note error is in the PIN, not in the time permit! Hence the need to exclude Time Permit from this check */
+
+                if (date)
+                {
+                    if (!ECP_fromOctet(&P,HID)) res=MPIN_INVALID_POINT;
+                    if (!ECP_fromOctet(&R,xID)) res=MPIN_INVALID_POINT; // U
+
+                    if (res==0)
+                    {
+                        PAIR_G1mul(&P,y);  // yA
+                        ECP_add(&P,&R); // yA+xA
+                    }
+                }
+                if (res==0)
+                {
+                    PAIR_ate(&g,&Q,&P);
+                    PAIR_fexp(&g);
+                    FP12_toOctet(F,&g);
+                }
+            }
+            res=MPIN_BAD_PIN;
+        }
+    }
+
+    return res;
+}
+
+#if MAXPIN==10000
+#define MR_TS 10  /* 2^10/10 approx = sqrt(MAXPIN) */
+#define TRAP 200  /* 2*sqrt(MAXPIN) */
+#endif
+
+#if MAXPIN==1000000
+#define MR_TS 14
+#define TRAP 2000
+#endif
+
+/* Pollards kangaroos used to return PIN error */
+int MPIN_KANGAROO(octet *E,octet *F)
+{
+    int i,j,m,s,dn,dm,steps;
+    int distance[MR_TS];
+    FP12 ge,gf,t,table[MR_TS];
+    int res=0;
+    // BIG w;
+
+    FP12_fromOctet(&ge,E);
+    FP12_fromOctet(&gf,F);
+
+    FP12_copy(&t,&gf);
+
+    for (s=1,m=0; m<MR_TS; m++)
+    {
+        distance[m]=s;
+        FP12_copy(&table[m],&t);
+        s*=2;
+        FP12_usqr(&t,&t);
+        FP12_reduce(&t);
+    }
+
+    FP12_one(&t);
+
+    for (dn=0,j=0; j<TRAP; j++)
+    {
+
+        //BIG_copy(w,t.a.a.a);
+        //FP_redc(w);
+        //i=BIG_lastbits(w,20)%MR_TS;
+
+        i=t.a.a.a[0]%MR_TS;
+
+        FP12_mul(&t,&table[i]);
+        FP12_reduce(&t);
+        dn+=distance[i];
+    }
+
+    FP12_conj(&gf,&t);
+    steps=0;
+    dm=0;
+    while (dm-dn<MAXPIN)
+    {
+        steps++;
+        if (steps>4*TRAP) break;
+
+        //BIG_copy(w,ge.a.a.a);
+        //FP_redc(w);
+        //i=BIG_lastbits(w,20)%MR_TS;
+
+        i=ge.a.a.a[0]%MR_TS;
+
+        FP12_mul(&ge,&table[i]);
+        FP12_reduce(&ge);
+        dm+=distance[i];
+        if (FP12_equals(&ge,&t))
+        {
+            res=dm-dn;
+            break;
+        }
+        if (FP12_equals(&ge,&gf))
+        {
+            res=dn-dm;
+            break;
+        }
+    }
+    if (steps>4*TRAP || dm-dn>=MAXPIN)
+    {
+        res=0;    /* Trap Failed  - probable invalid token */
+    }
+
+    return res;
+}
+
+/* Functions to support M-Pin Full */
+
+int MPIN_PRECOMPUTE(octet *TOKEN,octet *CID,octet *CP,octet *G1,octet *G2)
+{
+    ECP P,T;
+    ECP2 Q;
+    FP2 qx,qy;
+    FP12 g;
+    int res=0;
+
+    if (!ECP_fromOctet(&T,TOKEN)) res=MPIN_INVALID_POINT;
+
+    if (res==0)
+    {
+        mapit(CID,&P);
+        if (CP!=NULL)
+        {
+            if (!ECP2_fromOctet(&Q,CP)) res=MPIN_INVALID_POINT;
+        }
+        else
+        {
+            BIG_rcopy(qx.a,CURVE_Pxa);
+            FP_nres(qx.a);
+            BIG_rcopy(qx.b,CURVE_Pxb);
+            FP_nres(qx.b);
+            BIG_rcopy(qy.a,CURVE_Pya);
+            FP_nres(qy.a);
+            BIG_rcopy(qy.b,CURVE_Pyb);
+            FP_nres(qy.b);
+            if (!ECP2_set(&Q,&qx,&qy)) res=MPIN_INVALID_POINT;
+        }
+    }
+    if (res==0)
+    {
+        PAIR_ate(&g,&Q,&T);
+        PAIR_fexp(&g);
+
+        FP12_toOctet(G1,&g);
+        if (G2!=NULL)
+        {
+            PAIR_ate(&g,&Q,&P);
+            PAIR_fexp(&g);
+            FP12_toOctet(G2,&g);
+        }
+    }
+    return res;
+}
+
+/* calculate common key on client side */
+/* wCID = w.(A+AT) */
+int MPIN_CLIENT_KEY(int sha,octet *G1,octet *G2,int pin,octet *R,octet *X,octet *H,octet *wCID,octet *CK)
+{
+    FP12 g1,g2;
+    FP4 c,cp,cpm1,cpm2;
+    FP2 f;
+    ECP W;
+    int res=0;
+    BIG r,z,x,q,m,a,b,h;
+
+    FP12_fromOctet(&g1,G1);
+    FP12_fromOctet(&g2,G2);
+    BIG_fromBytes(z,R->val);
+    BIG_fromBytes(x,X->val);
+    BIG_fromBytes(h,H->val);
+
+    if (!ECP_fromOctet(&W,wCID)) res=MPIN_INVALID_POINT;
+
+    if (res==0)
+    {
+        BIG_rcopy(r,CURVE_Order);
+        BIG_add(z,z,h);    // new
+        BIG_mod(z,r);
+
+        PAIR_G1mul(&W,x);
+
+        BIG_rcopy(a,CURVE_Fra);
+        BIG_rcopy(b,CURVE_Frb);
+        FP2_from_BIGs(&f,a,b);
+
+        BIG_rcopy(q,Modulus);
+        BIG_copy(m,q);
+        BIG_mod(m,r);
+
+        BIG_copy(a,z);
+        BIG_mod(a,m);
+
+        BIG_copy(b,z);
+        BIG_sdiv(b,m);
+
+        FP12_pinpow(&g2,pin,PBLEN);
+        FP12_mul(&g1,&g2);
+
+        FP12_trace(&c,&g1);
+
+        FP12_copy(&g2,&g1);
+        FP12_frob(&g2,&f);
+        FP12_trace(&cp,&g2);
+
+        FP12_conj(&g1,&g1);
+        FP12_mul(&g2,&g1);
+        FP12_trace(&cpm1,&g2);
+        FP12_mul(&g2,&g1);
+        FP12_trace(&cpm2,&g2);
+
+        FP4_xtr_pow2(&c,&cp,&c,&cpm1,&cpm2,a,b);
+        mpin_hash(sha,&c,&W,CK);
+
+    }
+    return res;
+}
+
+/* calculate common key on server side */
+/* Z=r.A - no time permits involved */
+
+int MPIN_SERVER_KEY(int sha,octet *Z,octet *SST,octet *W,octet *H,octet *HID,octet *xID,octet *xCID,octet *SK)
+{
+    int res=0;
+    FP12 g;
+    FP4 c;
+    ECP R,U,A;
+    ECP2 sQ;
+    BIG w,h;
+
+    if (!ECP2_fromOctet(&sQ,SST)) res=MPIN_INVALID_POINT;
+    if (!ECP_fromOctet(&R,Z)) res=MPIN_INVALID_POINT;
+
+
+    if (!ECP_fromOctet(&A,HID)) res=MPIN_INVALID_POINT;
+
+    // new
+    if (xCID!=NULL)
+    {
+        if (!ECP_fromOctet(&U,xCID)) res=MPIN_INVALID_POINT;
+    }
+    else
+    {
+        if (!ECP_fromOctet(&U,xID)) res=MPIN_INVALID_POINT;
+    }
+    BIG_fromBytes(w,W->val);
+    BIG_fromBytes(h,H->val);
+
+
+    PAIR_ate(&g,&sQ,&A);
+    PAIR_fexp(&g);
+
+    if (res==0)
+    {
+        PAIR_G1mul(&A,h);
+        ECP_add(&R,&A);  // new
+        PAIR_ate(&g,&sQ,&R);
+        PAIR_fexp(&g);
+        PAIR_G1mul(&U,w);
+        FP12_trace(&c,&g);
+        mpin_hash(sha,&c,&U,SK);
+    }
+    return res;
+}
+
+unsign32 MPIN_GET_TIME(void)
+{
+    return (unsign32)time(NULL);
+}
+
+/* Generate Y = H(TimeValue, xCID/xID) */
+void MPIN_GET_Y(int sha,int TimeValue,octet *xCID,octet *Y)
+{
+    BIG q,y;
+    char h[MODBYTES];
+    octet H= {0,sizeof(h),h};
+
+    hashit(sha,TimeValue,xCID,&H);
+    BIG_fromBytes(y,H.val);
+    BIG_rcopy(q,CURVE_Order);
+    BIG_mod(y,q);
+    BIG_toBytes(Y->val,y);
+    Y->len=PGS;
+}
+
+/* One pass MPIN Client */
+int MPIN_CLIENT(int sha,int date,octet *ID,csprng *RNG,octet *X,int pin,octet *TOKEN,octet *V,octet *U,octet *UT,octet *TP,octet *MESSAGE,int TimeValue,octet *Y)
+{
+    int rtn=0;
+    char m[M_SIZE];
+    octet M= {0,sizeof(m),m};
+
+    octet *pID;
+    if (date == 0)
+        pID = U;
+    else
+        pID = UT;
+
+    rtn = MPIN_CLIENT_1(sha,date,ID,RNG,X,pin,TOKEN,V,U,UT,TP);
+    if (rtn != 0)
+        return rtn;
+
+    OCT_joctet(&M,pID);
+    if (MESSAGE!=NULL)
+    {
+        OCT_joctet(&M,MESSAGE);
+    }
+
+    MPIN_GET_Y(sha,TimeValue,&M,Y);
+
+    rtn = MPIN_CLIENT_2(X,Y,V);
+    if (rtn != 0)
+        return rtn;
+
+    return 0;
+}
+
+/* One pass MPIN Server */
+int MPIN_SERVER(int sha,int date,octet *HID,octet *HTID,octet *Y,octet *sQ,octet *U,octet *UT,octet *V,octet *E,octet *F,octet *ID,octet *MESSAGE,int TimeValue)
+{
+    int rtn=0;
+    char m[M_SIZE];
+    octet M= {0,sizeof(m),m};
+
+    octet *pU;
+    if (date == 0)
+        pU = U;
+    else
+        pU = UT;
+
+    MPIN_SERVER_1(sha,date,ID,HID,HTID);
+
+    OCT_joctet(&M,pU);
+    if (MESSAGE!=NULL)
+    {
+        OCT_joctet(&M,MESSAGE);
+    }
+
+    MPIN_GET_Y(sha,TimeValue,&M,Y);
+
+    rtn = MPIN_SERVER_2(date,HID,HTID,Y,sQ,U,UT,V,E,F);
+    if (rtn != 0)
+        return rtn;
+
+    return 0;
+}
+
+/* AES-GCM Encryption of octets, K is key, H is header,
+   P is plaintext, C is ciphertext, T is authentication tag */
+void MPIN_AES_GCM_ENCRYPT(octet *K,octet *IV,octet *H,octet *P,octet *C,octet *T)
+{
+    gcm g;
+    GCM_init(&g,K->len,K->val,IV->len,IV->val);
+    GCM_add_header(&g,H->val,H->len);
+    GCM_add_plain(&g,C->val,P->val,P->len);
+    C->len=P->len;
+    GCM_finish(&g,T->val);
+    T->len=16;
+}
+
+/* AES-GCM Decryption of octets, K is key, H is header,
+   P is plaintext, C is ciphertext, T is authentication tag */
+void MPIN_AES_GCM_DECRYPT(octet *K,octet *IV,octet *H,octet *C,octet *P,octet *T)
+{
+    gcm g;
+    GCM_init(&g,K->len,K->val,IV->len,IV->val);
+    GCM_add_header(&g,H->val,H->len);
+    GCM_add_cipher(&g,P->val,C->val,C->len);
+    P->len=C->len;
+    GCM_finish(&g,T->val);
+    T->len=16;
+}
+
+/* Return the Field size */
+int MPIN_FS()
+{
+    return PFS;
+}
+
+/* Return the Group size */
+int MPIN_GS()
+{
+    return PGS;
+}
+
+/*
+int MPIN_TEST_PAIRING(octet *CID,octet *R)
+{
+    BIG b,px;
+	FP2 qx,qy;
+	FP12 g;
+    ECP2 Q;
+	ECP P;
+    int res=0;
+
+	hashit(-1,CID,&P);
+	BIG_rcopy(qx.a,CURVE_Pxa); FP_nres(qx.a);
+	BIG_rcopy(qx.b,CURVE_Pxb); FP_nres(qx.b);
+	BIG_rcopy(qy.a,CURVE_Pya); FP_nres(qy.a);
+	BIG_rcopy(qy.b,CURVE_Pyb); FP_nres(qy.b);
+
+	if (!ECP2_set(&Q,&qx,&qy))  res=MPIN_INVALID_POINT;
+
+	if (res==0)
+	{
+		PAIR_ate(&g,&Q,&P);
+        PAIR_fexp(&g);
+		FP12_trace(&(g.a),&g);
+
+		BIG_copy(b,g.a.a.a); FP_redc(b); printf("trace pairing= "); BIG_output(b); printf("\n");
+		BIG_copy(b,g.a.a.b); FP_redc(b); printf("trace pairing= "); BIG_output(b); printf("\n");
+		BIG_copy(b,g.a.b.a); FP_redc(b); printf("trace pairing= "); BIG_output(b); printf("\n");
+		BIG_copy(b,g.a.b.b); FP_redc(b); printf("trace pairing= "); BIG_output(b); printf("\n");
+
+	}
+
+    return res;
+}
+*/
+
+/*
+int main()
+{
+	ECP2 X;
+	FP2 x,y,rhs;
+	BIG r;
+	char hcid[HASH_BYTES],client_id[100];
+	octet HCID={0,sizeof(hcid),hcid};
+	octet CLIENT_ID={0,sizeof(client_id),client_id};
+
+	OCT_jstring(&CLIENT_ID,"testUser@certivox.com");
+	MPIN_HASH_ID(&CLIENT_ID,&HCID);
+
+	printf("Client ID= "); OCT_output_string(&CLIENT_ID); printf("\n");
+
+	mapit2(&HCID,&X);
+
+	ECP2_output(&X);
+
+	BIG_rcopy(r,CURVE_Order);
+
+	ECP2_mul(&X,r);
+
+	ECP2_output(&X);
+
+}
+*/
diff --git a/version22/c/mpin.h b/version22/c/mpin.h
new file mode 100644
index 0000000..9627eb8
--- /dev/null
+++ b/version22/c/mpin.h
@@ -0,0 +1,408 @@
+/*
+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.
+*/
+
+/**
+ * @file mpin.h
+ * @author Mike Scott and Kealan McCusker
+ * @date 2nd June 2015
+ * @brief M-Pin Header file
+ *
+ * Allows some user configuration
+ * defines structures
+ * declares functions
+ *
+ */
+
+#ifndef MPIN_H
+#define MPIN_H
+
+#include "amcl.h"
+
+/* Field size is assumed to be greater than or equal to group size */
+
+#define PGS MODBYTES  /**< MPIN Group Size */
+#define PFS MODBYTES  /**< MPIN Field Size */
+#define PAS 16        /**< MPIN Symmetric Key Size */
+
+#define MPIN_OK             0   /**< Function completed without error */
+#define MPIN_INVALID_POINT  -14	/**< Point is NOT on the curve */
+#define MPIN_BAD_PIN        -19 /**< Bad PIN number entered */
+
+
+/* Configure your PIN here */
+
+#ifdef CMAKE
+#define MAXPIN @AMCL_MAXPIN@ /**< max PIN */
+#define PBLEN @AMCL_PBLEN@   /**< max length of PIN in bits */
+#else
+#define MAXPIN 10000         /**< max PIN */
+#define PBLEN 14             /**< max length of PIN in bits */
+#endif
+
+#define TIME_SLOT_MINUTES 1440  /**< Time Slot = 1 day */
+#define HASH_TYPE_MPIN SHA256   /**< Choose Hash function */
+
+#define MESSAGE_SIZE 256  /**< Signature message size  */
+#define M_SIZE (MESSAGE_SIZE+2*PFS+1)   /**< Signature message size and G1 size */
+
+/* MPIN support functions */
+
+/* MPIN primitives */
+
+/**	@brief Hash an M-Pin Identity to an octet string
+ *
+ 	@param h is the hash type
+	@param ID an octet containing the identity
+	@param HID an octet containing the hashed identity
+ */
+void MPIN_HASH_ID(int h,octet *ID,octet *HID);
+/**	@brief Get epoch time as unsigned integer
+ *
+	@return current epoch time in seconds
+ */
+unsign32 MPIN_GET_TIME(void);
+/**	@brief Generate Y=H(s,O), where s is epoch time, O is an octet, and H(.) is a hash function
+ *
+  	@param h is the hash type
+	@param t is epoch time in seconds
+	@param O is an input octet
+	@param Y is the output octet
+ */
+void MPIN_GET_Y(int h,int t,octet *O,octet *Y);
+/**	@brief Extract a PIN number from a client secret
+ *
+  	@param h is the hash type
+	@param ID is the input client identity
+	@param pin is an input PIN number
+	@param CS is the client secret from which the PIN is to be extracted
+	@return 0 or an error code
+ */
+int MPIN_EXTRACT_PIN(int h,octet *ID,int pin,octet *CS);
+/**	@brief Perform client side of the one-pass version of the M-Pin protocol
+ *
+	If Time Permits are disabled, set d = 0, and UT is not generated and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is OFF, U is not generated and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is ON, U and UT are both generated.
+ 	@param h is the hash type
+	@param d is input date, in days since the epoch. Set to 0 if Time permits disabled
+	@param ID is the input client identity
+	@param R is a pointer to a cryptographically secure random number generator
+	@param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input
+	@param pin is the input PIN number
+	@param T is the input M-Pin token (the client secret with PIN portion removed)
+	@param V is output = -(x+y)(CS+TP), where CS is the reconstructed client secret, and TP is the time permit
+	@param U is output = x.H(ID)
+	@param UT is output = x.(H(ID)+H(d|H(ID)))
+	@param TP is the input time permit
+	@param MESSAGE is the message to be signed
+	@param t is input epoch time in seconds - a timestamp
+	@param y is output H(t|U) or H(t|UT) if Time Permits enabled
+	@return 0 or an error code
+ */
+int MPIN_CLIENT(int h,int d,octet *ID,csprng *R,octet *x,int pin,octet *T,octet *V,octet *U,octet *UT,octet *TP, octet* MESSAGE, int t, octet *y);
+/**	@brief Perform first pass of the client side of the 3-pass version of the M-Pin protocol
+ *
+	If Time Permits are disabled, set d = 0, and UT is not generated and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is OFF, U is not generated and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is ON, U and UT are both generated.
+ 	@param h is the hash type
+	@param d is input date, in days since the epoch. Set to 0 if Time permits disabled
+	@param ID is the input client identity
+	@param R is a pointer to a cryptographically secure random number generator
+	@param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input
+	@param pin is the input PIN number
+	@param T is the input M-Pin token (the client secret with PIN portion removed)
+	@param S is output = CS+TP, where CS=is the reconstructed client secret, and TP is the time permit
+	@param U is output = x.H(ID)
+	@param UT is output = x.(H(ID)+H(d|H(ID)))
+	@param TP is the input time permit
+	@return 0 or an error code
+ */
+int MPIN_CLIENT_1(int h,int d,octet *ID,csprng *R,octet *x,int pin,octet *T,octet *S,octet *U,octet *UT,octet *TP);
+/**	@brief Generate a random group element
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param S is the output random octet
+	@return 0 or an error code
+ */
+int MPIN_RANDOM_GENERATE(csprng *R,octet *S);
+/**	@brief Perform second pass of the client side of the 3-pass version of the M-Pin protocol
+ *
+	@param x an input, a locally generated random number
+	@param y an input random challenge from the server
+	@param V on output = -(x+y).V
+	@return 0 or an error code
+ */
+int MPIN_CLIENT_2(octet *x,octet *y,octet *V);
+/**	@brief Perform server side of the one-pass version of the M-Pin protocol
+ *
+	If Time Permits are disabled, set d = 0, and UT and HTID are not generated and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is OFF, U and HID are not needed and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is ON, U, UT, HID and HTID are all required.
+ 	@param h is the hash type
+	@param d is input date, in days since the epoch. Set to 0 if Time permits disabled
+	@param HID is output H(ID), a hash of the client ID
+	@param HTID is output H(ID)+H(d|H(ID))
+	@param y is output H(t|U) or H(t|UT) if Time Permits enabled
+	@param SS is the input server secret
+	@param U is input from the client = x.H(ID)
+	@param UT is input from the client= x.(H(ID)+H(d|H(ID)))
+	@param V is an input from the client
+	@param E is an output to help the Kangaroos to find the PIN error, or NULL if not required
+	@param F is an output to help the Kangaroos to find the PIN error, or NULL if not required
+	@param ID is the input claimed client identity
+	@param MESSAGE is the message to be signed
+	@param t is input epoch time in seconds - a timestamp
+	@return 0 or an error code
+ */
+int MPIN_SERVER(int h,int d,octet *HID,octet *HTID,octet *y,octet *SS,octet *U,octet *UT,octet *V,octet *E,octet *F,octet *ID,octet *MESSAGE, int t);
+/**	@brief Perform first pass of the server side of the 3-pass version of the M-Pin protocol
+ *
+ 	@param h is the hash type
+	@param d is input date, in days since the epoch. Set to 0 if Time permits disabled
+	@param ID is the input claimed client identity
+	@param HID is output H(ID), a hash of the client ID
+	@param HTID is output H(ID)+H(d|H(ID))
+	@return 0 or an error code
+ */
+void MPIN_SERVER_1(int h,int d,octet *ID,octet *HID,octet *HTID);
+/**	@brief Perform third pass on the server side of the 3-pass version of the M-Pin protocol
+ *
+	If Time Permits are disabled, set d = 0, and UT and HTID are not needed and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is OFF, U and HID are not needed and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is ON, U, UT, HID and HTID are all required.
+	@param d is input date, in days since the epoch. Set to 0 if Time permits disabled
+	@param HID is input H(ID), a hash of the client ID
+	@param HTID is input H(ID)+H(d|H(ID))
+	@param y is the input server's randomly generated challenge
+	@param SS is the input server secret
+	@param U is input from the client = x.H(ID)
+	@param UT is input from the client= x.(H(ID)+H(d|H(ID)))
+	@param V is an input from the client
+	@param E is an output to help the Kangaroos to find the PIN error, or NULL if not required
+	@param F is an output to help the Kangaroos to find the PIN error, or NULL if not required
+	@return 0 or an error code
+ */
+int MPIN_SERVER_2(int d,octet *HID,octet *HTID,octet *y,octet *SS,octet *U,octet *UT,octet *V,octet *E,octet *F);
+/**	@brief Add two members from the group G1
+ *
+	@param Q1 an input member of G1
+	@param Q2 an input member of G1
+	@param Q an output member of G1 = Q1+Q2
+	@return 0 or an error code
+ */
+int MPIN_RECOMBINE_G1(octet *Q1,octet *Q2,octet *Q);
+/**	@brief Add two members from the group G2
+ *
+	@param P1 an input member of G2
+	@param P2 an input member of G2
+	@param P an output member of G2 = P1+P2
+	@return 0 or an error code
+ */
+int MPIN_RECOMBINE_G2(octet *P1,octet *P2,octet *P);
+/**	@brief Use Kangaroos to find PIN error
+ *
+	@param E a member of the group GT
+	@param F a member of the group GT =  E^e
+	@return 0 if Kangaroos failed, or the PIN error e
+ */
+int MPIN_KANGAROO(octet *E,octet *F);
+/**	@brief Encoding of a Time Permit to make it indistinguishable from a random string
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param TP is the input time permit, obfuscated on output
+	@return 0 or an error code
+ */
+int MPIN_ENCODING(csprng *R,octet *TP);
+/**	@brief Encoding of an obfuscated Time Permit
+ *
+	@param TP is the input obfuscated time permit, restored on output
+	@return 0 or an error code
+ */
+int MPIN_DECODING(octet *TP);
+/**	@brief Supply today's date as days from the epoch
+ *
+	@return today's date, as number of days elapsed since the epoch
+ */
+unsign32 MPIN_today(void);
+
+/**	@brief Find a random multiple of a point in G1
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param type determines type of action to be taken
+	@param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input
+	@param G if type=0 a point in G1, else an octet to be mapped to G1
+	@param W the output =x.G or x.M(G), where M(.) is a mapping
+	@return 0 or an error code
+ */
+int MPIN_GET_G1_MULTIPLE(csprng *R,int type,octet *x,octet *G,octet *W);
+/**	@brief Find a random multiple of a point in G1
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param type determines type of action to betaken
+	@param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input
+	@param G a point in G2
+	@param W the output =x.G or (1/x).G
+	@return 0 or an error code
+ */
+int MPIN_GET_G2_MULTIPLE(csprng *R,int type,octet *x,octet *G,octet *W);
+/** @brief Hash the session transcript
+ 	@param h is the hash type
+	@param I is the hashed input client ID = H(ID)
+	@param U is the client output = x.H(ID)
+	@param CU is the client output = x.(H(ID)+H(T|H(ID)))
+	@param Y is the server challenge
+	@param V is the client part response
+	@param R is the client part response
+	@param W is the server part response
+	@param H the output is the hash of all of the above that apply
+*/
+void MPIN_HASH_ALL(int h,octet *I,octet *U,octet *CU,octet *Y,octet *V,octet *R,octet *W,octet *H);
+/**	@brief Create a client secret in G1 from a master secret and the client ID
+ *
+	@param S is an input master secret
+	@param ID is the input client identity
+	@param CS is the full client secret = s.H(ID)
+	@return 0 or an error code
+ */
+int MPIN_GET_CLIENT_SECRET(octet *S,octet *ID,octet *CS);
+/**	@brief Create a Time Permit in G1 from a master secret and the client ID
+ *
+  	@param h is the hash type
+	@param d is input date, in days since the epoch.
+	@param S is an input master secret
+	@param ID is the input client identity
+	@param TP is a Time Permit for the given date = s.H(d|H(ID))
+	@return 0 or an error code
+ */
+int MPIN_GET_CLIENT_PERMIT(int h,int d,octet *S,octet *ID,octet *TP);
+/**	@brief Create a server secret in G2 from a master secret
+ *
+	@param S is an input master secret
+	@param SS is the server secret = s.Q where Q is a fixed generator of G2
+	@return 0 or an error code
+ */
+int MPIN_GET_SERVER_SECRET(octet *S,octet *SS);
+/* int MPIN_TEST_PAIRING(octet *,octet *); */
+
+/* For M-Pin Full */
+/**	@brief Precompute values for use by the client side of M-Pin Full
+ *
+	@param T is the input M-Pin token (the client secret with PIN portion removed)
+	@param ID is the input client identity
+	@param CP is Public Key (or NULL)
+	@param g1 precomputed output
+	@param g2 precomputed output
+	@return 0 or an error code
+ */
+int MPIN_PRECOMPUTE(octet *T,octet *ID,octet *CP,octet *g1,octet *g2);
+/**	@brief Calculate Key on Server side for M-Pin Full
+ *
+	Uses UT internally for the key calculation, unless not available in which case U is used
+ 	@param h is the hash type
+	@param Z is the input Client-side Diffie-Hellman component
+	@param SS is the input server secret
+	@param w is an input random number generated by the server
+	@param p is an input, hash of the protocol transcript
+	@param I is the hashed input client ID = H(ID)
+	@param U is input from the client = x.H(ID)
+	@param UT is input from the client= x.(H(ID)+H(d|H(ID)))
+	@param K is the output calculated shared key
+	@return 0 or an error code
+ */
+int MPIN_SERVER_KEY(int h,octet *Z,octet *SS,octet *w,octet *p,octet *I,octet *U,octet *UT,octet *K);
+/**	@brief Calculate Key on Client side for M-Pin Full
+ *
+  	@param h is the hash type
+	@param g1 precomputed input
+	@param g2 precomputed input
+	@param pin is the input PIN number
+	@param r is an input, a locally generated random number
+	@param x is an input, a locally generated random number
+	@param p is an input, hash of the protocol transcript
+	@param T is the input Server-side Diffie-Hellman component
+	@param K is the output calculated shared key
+	@return 0 or an error code
+ */
+int MPIN_CLIENT_KEY(int h,octet *g1,octet *g2,int pin,octet *r,octet *x,octet *p,octet *T,octet *K);
+
+/**	@brief AES-GCM Encryption
+ *
+	@param K  AES key
+	@param IV Initialization vector
+	@param H Header
+	@param P Plaintext
+	@param C Ciphertext
+	@param T Checksum
+ */
+void MPIN_AES_GCM_ENCRYPT(octet *K,octet *IV,octet *H,octet *P,octet *C,octet *T);
+
+/**	@brief AES-GCM Decryption
+ *
+	@param K  AES key
+	@param IV Initialization vector
+	@param H Header
+	@param P Plaintext
+	@param C Ciphertext
+	@param T Checksum
+ */
+void MPIN_AES_GCM_DECRYPT(octet *K,octet *IV,octet *H,octet *C,octet *P,octet *T);
+
+/**
+ * @brief Return the field size
+ *
+ * Return the field size.
+ *
+ * @return Field size
+ */
+int MPIN_FS();
+
+/**
+ * @brief Return the group size
+ *
+ * Return the group size.
+ *
+ * @return Group size
+ */
+int MPIN_GS();
+
+/**	@brief HMAC of message M using key K to create tag of length len in octet tag
+ *
+	IEEE-1363 MAC1 function. Uses SHA256 internally.
+	@param M input message octet
+	@param K input encryption key
+	@param len is output desired length of HMAC tag
+	@param tag is the output HMAC
+	@return 0 for bad parameters, else 1
+ */
+//int HMAC(octet *M,octet *K,int len,octet *tag);
+
+/**	@brief Password Based Key Derivation Function - generates key K from password, salt and repeat counter
+ *
+	PBKDF2 Password Based Key Derivation Function. Uses SHA256 internally.
+	@param P input password
+	@param S input salt
+	@param rep Number of times to be iterated.
+	@param len is output desired length of key
+	@param K is the derived key
+ */
+//void PBKDF2(octet *P,octet *S,int rep,int len,octet *K);
+
+#endif
+
diff --git a/version22/c/oct.c b/version22/c/oct.c
new file mode 100644
index 0000000..8d5bdb2
--- /dev/null
+++ b/version22/c/oct.c
@@ -0,0 +1,428 @@
+/*
+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.
+*/
+
+/*** Basic Octet string maintainance routines  ***/
+/* SU=m, m is Stack Usage */
+
+#include <string.h>
+#include "amcl.h"
+
+/* Output an octet string (Debug Only) */
+
+/* SU= 16 */
+/* output octet */
+void OCT_output(octet *w)
+{
+    int i;
+    unsigned char ch;
+    for (i=0; i<w->len; i++)
+    {
+        ch=w->val[i];
+        printf("%02x",ch);
+    }
+    printf("\n");
+}
+
+/* SU= 16 */
+void OCT_output_string(octet *w)
+{
+    int i;
+    unsigned char ch;
+    for (i=0; i<w->len; i++)
+    {
+        ch=w->val[i];
+        printf("%c",ch);
+    }
+    /*  printf("\n"); */
+}
+
+/* Convert C string to octet format - truncates if no room  */
+void OCT_jstring(octet *y,char *s)
+{
+    int i,j;
+    i=y->len;
+    j=0;
+    while (s[j]!=0 && i<y->max)
+    {
+        y->val[i]=s[j];
+        y->len++;
+        i++;
+        j++;
+    }
+}
+
+/* compare 2 octet strings.
+ * If x==y return TRUE, else return FALSE */
+/* SU= 8 */
+int OCT_comp(octet *x,octet *y)
+{
+    int i;
+    if (x->len>y->len) return 0;
+    if (x->len<y->len) return 0;
+    for (i=0; i<x->len; i++)
+    {
+        if (x->val[i]!=y->val[i]) return 0;
+    }
+    return 1;
+}
+
+/* check are first n bytes the same */
+
+int OCT_ncomp(octet *x,octet *y,int n)
+{
+    int i;
+    if (n>y->len || n>x->len) return 0;
+    for (i=0; i<n; i++)
+    {
+        if (x->val[i]!=y->val[i]) return 0;
+    }
+    return 1;
+}
+
+/* Shift octet to the left by n bytes. Leftmost bytes disappear  */
+void OCT_shl(octet *x,int n)
+{
+    int i;
+    if (n>=x->len)
+    {
+        x->len=0;
+        return;
+    }
+    x->len-=n;
+    for (i=0; i<x->len; i++)
+        x->val[i]=x->val[i+n];
+}
+
+/* Append binary string to octet - truncates if no room */
+/* SU= 12 */
+void OCT_jbytes(octet *y,char *b,int len)
+{
+    int i,j;
+    i=y->len;
+    for (j=0; j<len && i<y->max; j++)
+    {
+        y->val[i]=b[j];
+        y->len++;
+        i++;
+    }
+}
+
+/* Concatenates two octet strings */
+/* SU= 8 */
+void OCT_joctet(octet *y,octet *x)
+{
+    /* y=y || x */
+    int i,j;
+    if (x==NULL) return;
+
+    for (i=0; i<x->len; i++)
+    {
+        j=y->len+i;
+        if (j>=y->max)
+        {
+            y->len=y->max;
+            return;
+        }
+        y->val[j]=x->val[i];
+    }
+    y->len+=x->len;
+}
+
+/* Append byte to octet rep times */
+/* SU= 8 */
+void OCT_jbyte(octet *y,int ch,int rep)
+{
+    int i,j;
+    i=y->len;
+    for (j=0; j<rep && i<y->max; j++)
+    {
+        y->val[i]=ch;
+        y->len++;
+        i++;
+    }
+}
+
+/* XOR common bytes of x with y */
+/* SU= 8 */
+void OCT_xor(octet *y,octet *x)
+{
+    /* xor first x->len bytes of y */
+
+    int i;
+    for (i=0; i<x->len && i<y->len; i++)
+    {
+        y->val[i]^=x->val[i];
+    }
+}
+
+/* clear an octet */
+void OCT_empty(octet *w)
+{
+    w->len=0;
+}
+
+/* Kill an octet string - Zeroise it for security */
+void OCT_clear(octet *w)
+{
+    int i;
+    for (i=0; i<w->max; i++) w->val[i]=0;
+    w->len=0;
+}
+
+/* appends int x of length len bytes to OCTET string */
+/* SU= 8 */
+void OCT_jint(octet *y,int x,int len)
+{
+    int i,n;
+    n=y->len+len;
+    if (n>y->max || len<=0) return;
+    for (i=y->len; i<n; i++) y->val[i]=0;
+    y->len=n;
+
+    i=y->len;
+    while (x>0 && i>0)
+    {
+        i--;
+        y->val[i]=x%256;
+        x/=256;
+    }
+}
+
+/* Pad an octet to a given length */
+/* SU= 8 */
+int OCT_pad(octet *w,int n)
+{
+    int i,d;
+    if (w->len>n || n>w->max) return 0;
+    if (n==w->len) return 1;
+    d=n-w->len;
+    for (i=n-1; i>=d; i--)
+        w->val[i]=w->val[i-d];
+    for (i=d-1; i>=0; i--)
+        w->val[i]=0;
+    w->len=n;
+    return 1;
+}
+
+
+/* Convert an octet string to base64 string */
+/* SU= 56 */
+void OCT_tobase64(char *b,octet *w)
+{
+    int i,j,k,rem,last;
+    int c,ch[4];
+    unsigned char ptr[3];
+    rem=w->len%3;
+    j=k=0;
+    last=4;
+    while (j<w->len)
+    {
+        for (i=0; i<3; i++)
+        {
+            if (j<w->len) ptr[i]=w->val[j++];
+            else
+            {
+                ptr[i]=0;
+                last--;
+            }
+        }
+        ch[0]=(ptr[0]>>2)&0x3f;
+        ch[1]=((ptr[0]<<4)|(ptr[1]>>4))&0x3f;
+        ch[2]=((ptr[1]<<2)|(ptr[2]>>6))&0x3f;
+        ch[3]=ptr[2]&0x3f;
+        for (i=0; i<last; i++)
+        {
+            c=ch[i];
+            if (c<26) c+=65;
+            if (c>=26 && c<52) c+=71;
+            if (c>=52 && c<62) c-=4;
+            if (c==62) c='+';
+            if (c==63) c='/';
+            b[k++]=c;
+        }
+    }
+    if (rem>0) for (i=rem; i<3; i++) b[k++]='=';
+    b[k]='\0';  /* dangerous! */
+}
+
+/* SU= 56 */
+void OCT_frombase64(octet *w,char *b)
+{
+    int i,j,k,pads,len=(int)strlen(b);
+    int c,ch[4],ptr[3];
+    /* int lead=1; */
+    j=k=0;
+    while (j<len && k<w->max)
+    {
+        pads=0;
+        for (i=0; i<4; i++)
+        {
+            c=80+b[j++];
+            if (c<=112) continue; /* ignore white space */
+            if (c>144 && c<171) c-=145;
+            if (c>176 && c<203) c-=151;
+            if (c>127 && c<138) c-=76;
+            if (c==123) c=62;
+            if (c==127) c=63;
+            if (c==141)
+            {
+                pads++;    /* ignore pads '=' */
+                continue;
+            }
+            ch[i]=c;
+        }
+        ptr[0]=(ch[0]<<2)|(ch[1]>>4);
+        ptr[1]=(ch[1]<<4)|(ch[2]>>2);
+        ptr[2]=(ch[2]<<6)|ch[3];
+        for (i=0; i<3-pads && k<w->max; i++)
+        {
+            /* don't put in leading zeros */
+            /* if (lead && ptr[i]==0) continue; */
+            w->val[k++]=ptr[i];
+            /* lead=0; */
+        }
+
+    }
+    w->len=k;
+}
+
+/* copy an octet string - truncates if no room */
+/* SU= 16 */
+void OCT_copy(octet *y,octet *x)
+{
+    int i;
+    OCT_clear(y);
+    y->len=x->len;
+    if (y->len>y->max) y->len=y->max;
+
+    for (i=0; i<y->len; i++)
+        y->val[i]=x->val[i];
+}
+
+/* XOR m with all of x */
+void OCT_xorbyte(octet *x,int m)
+{
+    int i;
+    for (i=0; i<x->len; i++) x->val[i]^=m;
+}
+
+/* truncates x to n bytes and places the rest in y (if y is not NULL) */
+/* SU= 8 */
+void OCT_chop(octet *x,octet *y,int n)
+{
+    int i;
+    if (n>=x->len)
+    {
+        if (y!=NULL) y->len=0;
+        return;
+    }
+    if (y!=NULL) y->len=x->len-n;
+    x->len=n;
+
+    if (y!=NULL)
+    {
+        for (i=0; i<y->len && i<y->max; i++) y->val[i]=x->val[i+n];
+    }
+}
+
+/* set x to len random bytes */
+void OCT_rand(octet *x,csprng *RNG,int len)
+{
+    int i;
+    if (len>x->max) len=x->max;
+    x->len=len;
+
+    for (i=0; i<len; i++) x->val[i]=RAND_byte(RNG);
+}
+
+/* Convert an octet to a hex string */
+void OCT_toHex(octet *src,char *dst)
+{
+    int i;
+    unsigned char ch;
+    for (i=0; i<src->len; i++)
+    {
+        ch=src->val[i];
+        sprintf(&dst[i*2],"%02x", ch);
+    }
+}
+
+static int char2int(char input)
+{
+    if(input >= '0' && input <= '9')
+        return input - '0';
+    if(input >= 'A' && input <= 'F')
+        return input - 'A' + 10;
+    if(input >= 'a' && input <= 'f')
+        return input - 'a' + 10;
+    return 0;
+}
+
+/* Convert from a hex string */
+void OCT_fromHex(octet *dst,char *src)
+{
+    int i=0;
+    int j=0;
+    OCT_clear(dst);
+
+    while(src[j]!=0)
+    {
+        dst->val[i++] = char2int(src[j])*16 + char2int(src[j+1]);
+        j += 2;
+    }
+    dst->len=i;
+}
+
+
+/* Convert an octet to a string */
+void OCT_toStr(octet *src,char *dst)
+{
+    int i;
+    unsigned char ch;
+    for (i=0; i<src->len; i++)
+    {
+        ch=src->val[i];
+        sprintf(&dst[i],"%c", ch);
+    }
+}
+
+/* Test program
+#include <stdio.h>
+#include "amcl.h"
+
+char test[]="abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
+
+int main()
+{
+	char gm[100],gn[100],t[100];
+    octet m={0,sizeof(gm),gm};
+    octet n={0,sizeof(gn),gn};
+
+	OCT_jbytes(&m,test,strlen(test));
+	OCT_output(&m);
+
+	OCT_tobase64(t,&m);
+	printf(t); printf("\n");
+
+	OCT_frombase64(&n,t);
+	OCT_output(&n);
+
+    return 0;
+}
+*/
diff --git a/version22/c/pair.c b/version22/c/pair.c
new file mode 100644
index 0000000..5b4e987
--- /dev/null
+++ b/version22/c/pair.c
@@ -0,0 +1,828 @@
+/*
+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.
+*/
+
+/* AMCL BN Curve pairing functions */
+
+//#define HAS_MAIN
+
+#include "amcl.h"
+
+/* Line function */
+static void PAIR_line(FP12 *v,ECP2 *A,ECP2 *B,BIG Qx,BIG Qy)
+{
+    ECP2 P;
+    FP2 Z3,X,Y,ZZ,T,NY;
+    FP4 a,b,c;
+    int D;
+    ECP2_copy(&P,A);
+    if (A==B)
+        D=ECP2_dbl(A);  // check these return numbers...
+    else
+        D=ECP2_add(A,B);
+    if (D<0)
+    {
+        /* Infinity */
+        FP12_one(v);
+        return;
+    }
+
+    FP2_copy(&Z3,&(A->z));
+    FP4_zero(&c);
+    FP2_sqr(&ZZ,&(P.z));    /* ZZ=Z^2 */
+    if (D==0)
+    {
+        /* addition */
+        ECP2_get(&X,&Y,B);
+        FP2_mul(&T,&(P.z),&Y);  /* T=Z*Y2 */
+
+        FP2_mul(&ZZ,&ZZ,&T);
+
+        FP2_neg(&NY,&(P.y));
+        FP2_add(&ZZ,&ZZ,&NY); /* ZZ=Z^3*Y2-Y (slope numerator) */
+        FP2_pmul(&Z3,&Z3,Qy);    /* Z3*Qy */
+        FP2_mul(&T,&T,&(P.x));
+        FP2_mul(&X,&X,&NY);
+        FP2_add(&T,&T,&X);       /* Z*Y2*X-X2*Y */
+        FP4_from_FP2s(&a,&Z3,&T); /* a=[Z3*Qy,Z*Y2*X-X2*Y] */
+        FP2_neg(&ZZ,&ZZ);
+        FP2_pmul(&ZZ,&ZZ,Qx);
+        FP4_from_FP2(&b,&ZZ);    /* b=-slope*Qx */
+    }
+    else
+    {
+        /* doubling */
+        FP2_sqr(&T,&(P.x));
+        FP2_imul(&T,&T,3);   /* T=3X^2 (slope numerator) */
+        FP2_sqr(&Y,&(P.y));
+
+        FP2_add(&Y,&Y,&Y);   /* Y=2Y^2 */
+        FP2_mul(&Z3,&Z3,&ZZ);   /* Z3=Z3*ZZ */
+        FP2_pmul(&Z3,&Z3,Qy);   /* Z3=Z3*ZZ*Qy */
+
+        FP2_mul(&X,&(P.x),&T);
+        FP2_sub(&X,&X,&Y);      /* X=X*slope-2Y^2 */
+        FP4_from_FP2s(&a,&Z3,&X); /* a=[Z3*ZZ*Qy , X*slope-2Y^2] */
+        FP2_neg(&T,&T);
+        FP2_mul(&ZZ,&ZZ,&T);
+        FP2_pmul(&ZZ,&ZZ,Qx);
+        FP4_from_FP2(&b,&ZZ);    /* b=-slope*ZZ*Qx */
+    }
+
+    FP12_from_FP4s(v,&a,&b,&c);
+}
+
+/* Optimal R-ate pairing r=e(P,Q) */
+void PAIR_ate(FP12 *r,ECP2 *P,ECP *Q)
+{
+    FP2 X;
+    BIG x,n,Qx,Qy;
+    int i,nb;
+    ECP2 A;
+    FP12 lv;
+#if CHOICE<BLS_CURVES
+    ECP2 KA;
+#endif
+
+    BIG_rcopy(Qx,CURVE_Fra);
+    BIG_rcopy(Qy,CURVE_Frb);
+    FP2_from_BIGs(&X,Qx,Qy);
+
+    BIG_rcopy(x,CURVE_Bnx);
+
+#if CHOICE<BLS_CURVES
+    BIG_pmul(n,x,6);
+    BIG_dec(n,2);
+#else
+    BIG_copy(n,x);
+#endif
+
+    BIG_norm(n);
+
+    ECP2_affine(P);
+    ECP_affine(Q);
+
+    BIG_copy(Qx,Q->x);
+    BIG_copy(Qy,Q->y);
+
+    ECP2_copy(&A,P);
+    FP12_one(r);
+    nb=BIG_nbits(n);
+
+    /* Main Miller Loop */
+    for (i=nb-2; i>=1; i--)
+    {
+        PAIR_line(&lv,&A,&A,Qx,Qy);
+        FP12_smul(r,&lv);
+        if (BIG_bit(n,i))
+        {
+
+            PAIR_line(&lv,&A,P,Qx,Qy);
+            FP12_smul(r,&lv);
+        }
+        FP12_sqr(r,r);
+    }
+
+    PAIR_line(&lv,&A,&A,Qx,Qy);
+    FP12_smul(r,&lv);
+
+    if (BIG_parity(n))
+    {
+        PAIR_line(&lv,&A,P,Qx,Qy);
+        FP12_smul(r,&lv);
+    }
+
+    /* R-ate fixup required for BN curves */
+#if CHOICE<BLS_CURVES
+    ECP2_copy(&KA,P);
+    ECP2_frob(&KA,&X);
+
+    ECP2_neg(&A);
+    FP12_conj(r,r);
+
+    PAIR_line(&lv,&A,&KA,Qx,Qy);
+    FP12_smul(r,&lv);
+    ECP2_frob(&KA,&X);
+    ECP2_neg(&KA);
+    PAIR_line(&lv,&A,&KA,Qx,Qy);
+    FP12_smul(r,&lv);
+#endif
+}
+
+/* Optimal R-ate double pairing e(P,Q).e(R,S) */
+void PAIR_double_ate(FP12 *r,ECP2 *P,ECP *Q,ECP2 *R,ECP *S)
+{
+    FP2 X;
+    BIG x,n,Qx,Qy,Sx,Sy;
+    int i,nb;
+    ECP2 A,B;
+    FP12 lv;
+#if CHOICE<BLS_CURVES
+    ECP2 K;
+#endif
+    BIG_rcopy(Qx,CURVE_Fra);
+    BIG_rcopy(Qy,CURVE_Frb);
+    FP2_from_BIGs(&X,Qx,Qy);
+
+    BIG_rcopy(x,CURVE_Bnx);
+
+#if CHOICE<BLS_CURVES
+    BIG_pmul(n,x,6);
+    BIG_dec(n,2);
+#else
+    BIG_copy(n,x);
+#endif
+
+    BIG_norm(n);
+
+    ECP2_affine(P);
+    ECP_affine(Q);
+
+    ECP2_affine(R);
+    ECP_affine(S);
+
+    BIG_copy(Qx,Q->x);
+    BIG_copy(Qy,Q->y);
+
+    BIG_copy(Sx,S->x);
+    BIG_copy(Sy,S->y);
+
+    ECP2_copy(&A,P);
+    ECP2_copy(&B,R);
+    FP12_one(r);
+    nb=BIG_nbits(n);
+
+    /* Main Miller Loop */
+    for (i=nb-2; i>=1; i--)
+    {
+        PAIR_line(&lv,&A,&A,Qx,Qy);
+        FP12_smul(r,&lv);
+        PAIR_line(&lv,&B,&B,Sx,Sy);
+        FP12_smul(r,&lv);
+
+        if (BIG_bit(n,i))
+        {
+            PAIR_line(&lv,&A,P,Qx,Qy);
+            FP12_smul(r,&lv);
+
+            PAIR_line(&lv,&B,R,Sx,Sy);
+            FP12_smul(r,&lv);
+        }
+        FP12_sqr(r,r);
+    }
+
+    PAIR_line(&lv,&A,&A,Qx,Qy);
+    FP12_smul(r,&lv);
+
+    PAIR_line(&lv,&B,&B,Sx,Sy);
+    FP12_smul(r,&lv);
+
+    if (BIG_parity(n))
+    {
+        PAIR_line(&lv,&A,P,Qx,Qy);
+        FP12_smul(r,&lv);
+
+        PAIR_line(&lv,&B,R,Sx,Sy);
+        FP12_smul(r,&lv);
+    }
+
+    /* R-ate fixup required for BN curves */
+#if CHOICE<BLS_CURVES
+    FP12_conj(r,r);
+
+    ECP2_copy(&K,P);
+    ECP2_frob(&K,&X);
+    ECP2_neg(&A);
+    PAIR_line(&lv,&A,&K,Qx,Qy);
+    FP12_smul(r,&lv);
+    ECP2_frob(&K,&X);
+    ECP2_neg(&K);
+    PAIR_line(&lv,&A,&K,Qx,Qy);
+    FP12_smul(r,&lv);
+
+    ECP2_copy(&K,R);
+    ECP2_frob(&K,&X);
+    ECP2_neg(&B);
+    PAIR_line(&lv,&B,&K,Sx,Sy);
+    FP12_smul(r,&lv);
+    ECP2_frob(&K,&X);
+    ECP2_neg(&K);
+    PAIR_line(&lv,&B,&K,Sx,Sy);
+    FP12_smul(r,&lv);
+#endif
+}
+
+/* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */
+void PAIR_fexp(FP12 *r)
+{
+    FP2 X;
+    BIG x,a,b;
+    FP12 t0,y0,y1,y2,y3;
+
+    BIG_rcopy(x,CURVE_Bnx);
+    BIG_rcopy(a,CURVE_Fra);
+    BIG_rcopy(b,CURVE_Frb);
+    FP2_from_BIGs(&X,a,b);
+
+    /* Easy part of final exp */
+
+    FP12_inv(&t0,r);
+    FP12_conj(r,r);
+
+    FP12_mul(r,&t0);
+    FP12_copy(&t0,r);
+
+    FP12_frob(r,&X);
+    FP12_frob(r,&X);
+    FP12_mul(r,&t0);
+
+    /* Hard part of final exp - see Duquesne & Ghamman eprint 2015/192.pdf */
+#if CHOICE<BLS_CURVES
+    FP12_pow(&t0,r,x); // t0=f^-u
+    FP12_usqr(&y3,&t0); // y3=t0^2
+    FP12_copy(&y0,&t0);
+    FP12_mul(&y0,&y3); // y0=t0*y3
+    FP12_copy(&y2,&y3);
+    FP12_frob(&y2,&X); // y2=y3^p
+    FP12_mul(&y2,&y3); //y2=y2*y3
+    FP12_usqr(&y2,&y2); //y2=y2^2
+    FP12_mul(&y2,&y3); // y2=y2*y3
+
+    FP12_pow(&t0,&y0,x);  //t0=y0^-u
+    FP12_conj(&y0,r);     //y0=~r
+    FP12_copy(&y1,&t0);
+    FP12_frob(&y1,&X);
+    FP12_frob(&y1,&X); //y1=t0^p^2
+    FP12_mul(&y1,&y0); // y1=y0*y1
+    FP12_conj(&t0,&t0); // t0=~t0
+    FP12_copy(&y3,&t0);
+    FP12_frob(&y3,&X); //y3=t0^p
+    FP12_mul(&y3,&t0); // y3=t0*y3
+    FP12_usqr(&t0,&t0); // t0=t0^2
+    FP12_mul(&y1,&t0); // y1=t0*y1
+
+    FP12_pow(&t0,&y3,x); // t0=y3^-u
+    FP12_usqr(&t0,&t0); //t0=t0^2
+    FP12_conj(&t0,&t0); //t0=~t0
+    FP12_mul(&y3,&t0); // y3=t0*y3
+
+    FP12_frob(r,&X);
+    FP12_copy(&y0,r);
+    FP12_frob(r,&X);
+    FP12_mul(&y0,r);
+    FP12_frob(r,&X);
+    FP12_mul(&y0,r);
+
+    FP12_usqr(r,&y3);  //r=y3^2
+    FP12_mul(r,&y2);   //r=y2*r
+    FP12_copy(&y3,r);
+    FP12_mul(&y3,&y0); // y3=r*y0
+    FP12_mul(r,&y1); // r=r*y1
+    FP12_usqr(r,r); // r=r^2
+    FP12_mul(r,&y3); // r=r*y3
+    FP12_reduce(r);
+#else
+// Ghamman & Fouotsa Method
+
+    FP12_usqr(&y0,r);
+    FP12_pow(&y1,&y0,x);
+    BIG_fshr(x,1);
+    FP12_pow(&y2,&y1,x);
+    BIG_fshl(x,1); // x must be even
+    FP12_conj(&y3,r);
+    FP12_mul(&y1,&y3);
+
+    FP12_conj(&y1,&y1);
+    FP12_mul(&y1,&y2);
+
+    FP12_pow(&y2,&y1,x);
+
+    FP12_pow(&y3,&y2,x);
+    FP12_conj(&y1,&y1);
+    FP12_mul(&y3,&y1);
+
+    FP12_conj(&y1,&y1);
+    FP12_frob(&y1,&X);
+    FP12_frob(&y1,&X);
+    FP12_frob(&y1,&X);
+    FP12_frob(&y2,&X);
+    FP12_frob(&y2,&X);
+    FP12_mul(&y1,&y2);
+
+    FP12_pow(&y2,&y3,x);
+    FP12_mul(&y2,&y0);
+    FP12_mul(&y2,r);
+
+    FP12_mul(&y1,&y2);
+    FP12_copy(&y2,&y3);
+    FP12_frob(&y2,&X);
+    FP12_mul(&y1,&y2);
+    FP12_copy(r,&y1);
+    FP12_reduce(r);
+
+// Aranha et al method as described by Ghamman & Fouotsa
+    /*
+    	FP12_usqr(&y0,r);  // t0=f^2
+    	FP12_conj(&y3,&y0); // t0=f^-2
+    	FP12_pow(&t0,r,x); // t5=f^u
+    	FP12_usqr(&y1,&t0); // t1=t5^2
+    	FP12_mul(&y3,&t0); // t3=t0*t5
+
+    	FP12_pow(&y0,&y3,x);
+
+    	FP12_pow(&y2,&y0,x);
+
+    	FP12_pow(&y4,&y2,x);
+
+    	FP12_mul(&y4,&y1);
+    	FP12_pow(&y1,&y4,x);
+    	FP12_conj(&y3,&y3);
+    	FP12_mul(&y1,&y3);
+    	FP12_mul(&y1,r);
+
+    	FP12_conj(&y3,r);
+    	FP12_mul(&y0,r);
+    	FP12_frob(&y0,&X); FP12_frob(&y0,&X); FP12_frob(&y0,&X);
+
+    	FP12_mul(&y4,&y3);
+    	FP12_frob(&y4,&X);
+
+    	FP12_mul(&t0,&y2);
+    	FP12_frob(&t0,&X); FP12_frob(&t0,&X);
+
+    	FP12_mul(&t0,&y0);
+    	FP12_mul(&t0,&y4);
+    	FP12_mul(&t0,&y1);
+    	FP12_copy(r,&t0);
+    	FP12_reduce(r);*/
+
+//-----------------------------------
+    /*
+    	FP12_copy(&y0,r);						// y0=r;
+    	FP12_copy(&y1,r);						// y1=r;
+    	FP12_copy(&t0,r); FP12_frob(&t0,&X);	// t0=Frobenius(r,X,1);
+    	FP12_conj(&y3,&t0); FP12_mul(&y1,&y3);	// y1*=inverse(t0);
+    	FP12_frob(&t0,&X); FP12_frob(&t0,&X);	// t0=Frobenius(t0,X,2);
+    	FP12_mul(&y1,&t0);						// y1*=t0;
+
+    	FP12_pow(r,r,x);						// r=pow(r,x);
+    	FP12_conj(&y3,r); FP12_mul(&y1,&y3);	// y1*=inverse(r);
+    	FP12_copy(&t0,r); FP12_frob(&t0,&X);	// t0=Frobenius(r,X,1);
+    	FP12_mul(&y0,&t0);						// y0*=t0;
+    	FP12_frob(&t0,&X);						// t0=Frobenius(t0,X,1);
+    	FP12_mul(&y1,&t0);						// y1*=t0;
+    	FP12_frob(&t0,&X);						// t0=Frobenius(t0,X,1);
+    	FP12_conj(&y3,&t0); FP12_mul(&y0,&y3);	// y0*=inverse(t0);
+
+    	FP12_pow(r,r,x);						// r=pow(r,x);
+    	FP12_mul(&y0,r);						// y0*=r;
+    	FP12_copy(&t0,r); FP12_frob(&t0,&X); FP12_frob(&t0,&X); // t0=Frobenius(r,X,2);
+    	FP12_conj(&y3,&t0); FP12_mul(&y0,&y3);	// y0*=inverse(t0);
+    	FP12_frob(&t0,&X);						// t0=Frobenius(t0,X,1);
+    	FP12_mul(&y1,&t0);						// y1*=t0;
+
+    	FP12_pow(r,r,x);						// r=pow(r,x);			// r^x3
+    	FP12_copy(&t0,r); FP12_frob(&t0,&X);	// t0=Frobenius(r,X,1);
+    	FP12_conj(&y3,&t0); FP12_mul(&y0,&y3);	// y0*=inverse(t0);
+    	FP12_frob(&t0,&X);						// t0=Frobenius(t0,X,1);
+    	FP12_mul(&y1,&t0);						// y1*=t0;
+
+    	FP12_pow(r,r,x);						// r=pow(r,x);			// r^x4
+    	FP12_conj(&y3,r); FP12_mul(&y0,&y3);	// y0*=inverse(r);
+    	FP12_copy(&t0,r); FP12_frob(&t0,&X);	// t0=Frobenius(r,X,1);
+    	FP12_mul(&y1,&t0);						//y1*=t0;
+
+    	FP12_pow(r,r,x);						// r=pow(r,x);			// r^x5
+    	FP12_mul(&y1,r);						// y1*=r;
+
+    	FP12_usqr(&y0,&y0);						// r=y0*y0*y1;
+    	FP12_mul(&y0,&y1);
+    	FP12_copy(r,&y0);
+    	FP12_reduce(r); */
+#endif
+}
+
+#ifdef USE_GLV
+/* GLV method */
+static void glv(BIG u[2],BIG e)
+{
+#if CHOICE<BLS_CURVES
+    int i,j;
+    BIG v[2],t,q;
+    DBIG d;
+    BIG_rcopy(q,CURVE_Order);
+    for (i=0; i<2; i++)
+    {
+        BIG_rcopy(t,CURVE_W[i]);
+//BIG_norm(t); BIG_norm(e);
+        BIG_mul(d,t,e);
+        BIG_ddiv(v[i],d,q);
+        BIG_zero(u[i]);
+    }
+    BIG_copy(u[0],e);
+    for (i=0; i<2; i++)
+        for (j=0; j<2; j++)
+        {
+            BIG_rcopy(t,CURVE_SB[j][i]);
+            BIG_modmul(t,v[j],t,q);
+            BIG_add(u[i],u[i],q);
+            BIG_sub(u[i],u[i],t);
+            BIG_mod(u[i],q);
+        }
+
+#else
+// -(x^2).P = (Beta.x,y)
+
+    BIG x,x2,q;
+    BIG_rcopy(x,CURVE_Bnx);
+    BIG_smul(x2,x,x);
+    BIG_copy(u[0],e);
+    BIG_mod(u[0],x2);
+    BIG_copy(u[1],e);
+    BIG_sdiv(u[1],x2);
+
+    BIG_rcopy(q,CURVE_Order);
+    BIG_sub(u[1],q,u[1]);
+
+#endif
+
+    return;
+}
+#endif // USE_GLV
+
+/* Galbraith & Scott Method */
+static void gs(BIG u[4],BIG e)
+{
+    int i;
+#if CHOICE<BLS_CURVES
+    int j;
+    BIG v[4],t,q;
+    DBIG d;
+    BIG_rcopy(q,CURVE_Order);
+    for (i=0; i<4; i++)
+    {
+        BIG_rcopy(t,CURVE_WB[i]);
+//BIG_norm(t); BIG_norm(e);
+        BIG_mul(d,t,e);
+        BIG_ddiv(v[i],d,q);
+        BIG_zero(u[i]);
+    }
+
+    BIG_copy(u[0],e);
+    for (i=0; i<4; i++)
+        for (j=0; j<4; j++)
+        {
+            BIG_rcopy(t,CURVE_BB[j][i]);
+            BIG_modmul(t,v[j],t,q);
+            BIG_add(u[i],u[i],q);
+            BIG_sub(u[i],u[i],t);
+            BIG_mod(u[i],q);
+        }
+
+#else
+
+    BIG x,w;
+    BIG_rcopy(x,CURVE_Bnx);
+    BIG_copy(w,e);
+
+    for (i=0; i<4; i++)
+    {
+        BIG_copy(u[i],w);
+        BIG_mod(u[i],x);
+        BIG_sdiv(w,x);
+    }
+
+#endif
+    return;
+}
+
+/* Multiply P by e in group G1 */
+void PAIR_G1mul(ECP *P,BIG e)
+{
+#ifdef USE_GLV   /* Note this method is patented */
+    int np,nn;
+    ECP Q;
+    BIG cru,t,q;
+    BIG u[2];
+
+    BIG_rcopy(q,CURVE_Order);
+    glv(u,e);
+
+    ECP_affine(P);
+    ECP_copy(&Q,P);
+    BIG_rcopy(cru,CURVE_Cru);
+    FP_nres(cru);
+    FP_mul(Q.x,Q.x,cru);
+
+    /* note that -a.B = a.(-B). Use a or -a depending on which is smaller */
+
+    np=BIG_nbits(u[0]);
+    BIG_modneg(t,u[0],q);
+    nn=BIG_nbits(t);
+    if (nn<np)
+    {
+        BIG_copy(u[0],t);
+        ECP_neg(P);
+    }
+
+    np=BIG_nbits(u[1]);
+    BIG_modneg(t,u[1],q);
+    nn=BIG_nbits(t);
+    if (nn<np)
+    {
+        BIG_copy(u[1],t);
+        ECP_neg(&Q);
+    }
+
+    ECP_mul2(P,&Q,u[0],u[1]);
+
+#else
+    ECP_mul(P,e);
+#endif
+}
+
+/* Multiply P by e in group G2 */
+void PAIR_G2mul(ECP2 *P,BIG e)
+{
+#ifdef USE_GS_G2   /* Well I didn't patent it :) */
+    int i,np,nn;
+    ECP2 Q[4];
+    FP2 X;
+    BIG x,y;
+    BIG u[4];
+
+    BIG_rcopy(x,CURVE_Fra);
+    BIG_rcopy(y,CURVE_Frb);
+    FP2_from_BIGs(&X,x,y);
+
+    BIG_rcopy(y,CURVE_Order);
+    gs(u,e);
+
+
+    ECP2_affine(P);
+
+    ECP2_copy(&Q[0],P);
+    for (i=1; i<4; i++)
+    {
+        ECP2_copy(&Q[i],&Q[i-1]);
+        ECP2_frob(&Q[i],&X);
+    }
+
+    for (i=0; i<4; i++)
+    {
+        np=BIG_nbits(u[i]);
+        BIG_modneg(x,u[i],y);
+        nn=BIG_nbits(x);
+        if (nn<np)
+        {
+            BIG_copy(u[i],x);
+            ECP2_neg(&Q[i]);
+        }
+    }
+
+    ECP2_mul4(P,Q,u);
+
+#else
+    ECP2_mul(P,e);
+#endif
+}
+
+/* f=f^e */
+void PAIR_GTpow(FP12 *f,BIG e)
+{
+#ifdef USE_GS_GT   /* Note that this option requires a lot of RAM! Maybe better to use compressed XTR method, see fp4.c */
+    int i,np,nn;
+    FP12 g[4];
+    FP2 X;
+    BIG t,q,x,y;
+    BIG u[4];
+
+    BIG_rcopy(x,CURVE_Fra);
+    BIG_rcopy(y,CURVE_Frb);
+    FP2_from_BIGs(&X,x,y);
+
+    BIG_rcopy(q,CURVE_Order);
+    gs(u,e);
+
+    FP12_copy(&g[0],f);
+    for (i=1; i<4; i++)
+    {
+        FP12_copy(&g[i],&g[i-1]);
+        FP12_frob(&g[i],&X);
+    }
+
+    for (i=0; i<4; i++)
+    {
+        np=BIG_nbits(u[i]);
+        BIG_modneg(t,u[i],q);
+        nn=BIG_nbits(t);
+        if (nn<np)
+        {
+            BIG_copy(u[i],t);
+            FP12_conj(&g[i],&g[i]);
+        }
+    }
+    FP12_pow4(f,g,u);
+
+#else
+    FP12_pow(f,f,e);
+#endif
+}
+
+/* test group membership test - no longer needed */
+/* with GT-Strong curve, now only check that m!=1, conj(m)*m==1, and m.m^{p^4}=m^{p^2} */
+
+/*
+int PAIR_GTmember(FP12 *m)
+{
+	BIG a,b;
+	FP2 X;
+	FP12 r,w;
+	if (FP12_isunity(m)) return 0;
+	FP12_conj(&r,m);
+	FP12_mul(&r,m);
+	if (!FP12_isunity(&r)) return 0;
+
+	BIG_rcopy(a,CURVE_Fra);
+	BIG_rcopy(b,CURVE_Frb);
+	FP2_from_BIGs(&X,a,b);
+
+
+	FP12_copy(&r,m); FP12_frob(&r,&X); FP12_frob(&r,&X);
+	FP12_copy(&w,&r); FP12_frob(&w,&X); FP12_frob(&w,&X);
+	FP12_mul(&w,m);
+
+
+#ifndef GT_STRONG
+	if (!FP12_equals(&w,&r)) return 0;
+
+	BIG_rcopy(a,CURVE_Bnx);
+
+	FP12_copy(&r,m); FP12_pow(&w,&r,a); FP12_pow(&w,&w,a);
+	FP12_sqr(&r,&w); FP12_mul(&r,&w); FP12_sqr(&r,&r);
+
+	FP12_copy(&w,m); FP12_frob(&w,&X);
+ #endif
+
+	return FP12_equals(&w,&r);
+}
+
+*/
+
+
+#ifdef HAS_MAIN
+/*
+#if CHOICE==BN254_T
+
+const BIG TEST_Gx={0x18AFF11A,0xF2EF406,0xAF68220,0x171F2E27,0x6BA0959,0x124C50E0,0x450BE27,0x7003EA8,0x8A914};
+const BIG TEST_Gy={0x6E010F4,0xA71D07E,0x7ECADA8,0x8260E8E,0x1F79C328,0x17A09412,0xBFAE690,0x1C57CBD1,0x17DF54};
+
+const BIG TEST_Pxa={0x1047D566,0xD83CD71,0x10322E9D,0x991FA93,0xA282C48,0x18AEBEC8,0xCB05850,0x13B4F669,0x21794A};
+const BIG TEST_Pxb={0x1E305936,0x16885BF1,0x327060,0xE26F794,0x1547D870,0x1963E5B2,0x1BEBB96C,0x988A33C,0x1A9B47};
+const BIG TEST_Pya={0x20FF876,0x4427E67,0x18732211,0xE88E45E,0x174D1A7E,0x17D877ED,0x343AB37,0x97EB453,0xB00D5};
+const BIG TEST_Pyb={0x1D746B7B,0x732F4C2,0x122A49B0,0x16267985,0x235DF56,0x10B1E4D,0x14D8F210,0x17A05C3E,0x5ECF8};
+
+#endif
+
+#if CHOICE==BN254_T2
+
+const BIG TEST_Gx={0x15488765,0x46790D7,0xD9900A,0x1DFB43F,0x9F2D307,0xC4724E8,0x5678E51,0x15C3E3A7,0x1BEC8E};
+const BIG TEST_Gy={0x3D3273C,0x1AFA5FF,0x1880A139,0xACD34DF,0x17493067,0x10FA4103,0x1D4C9766,0x1A73F3DB,0x2D148};
+
+const BIG TEST_Pxa={0xF8DC275,0xAC27FA,0x11815151,0x152691C8,0x5CDEBF1,0x7D5A965,0x1BF70CE3,0x679A1C8,0xD62CF};
+const BIG TEST_Pxb={0x1D17D7A8,0x6B28DF4,0x174A0389,0xFE67E5F,0x1FA97A3C,0x7F5F473,0xFFB5146,0x4BC19A5,0x227010};
+const BIG TEST_Pya={0x16CC1F90,0x5284627,0x171B91AB,0x11F843B9,0x1D468755,0x67E279C,0x19FE0EF8,0x1A0CAA6B,0x1CC6CB};
+const BIG TEST_Pyb={0x1FF0CF2A,0xBC83255,0x6DD6EE8,0xB8B752F,0x13E484EC,0x1809BE81,0x1A648AA1,0x8CEF3F3,0x86EE};
+
+
+#endif
+
+#if CHOICE==BN254
+
+const BIG TEST_Gx={0x14BEC4670E4EB7,0xEA2973860F6861,0x35C14B2FC3C28F,0x4402A0B63B9473,0x2074A81D};
+const BIG TEST_Gy={0xC284846631CBEB,0x34A6E8D871B3B,0x89FB94A82B2006,0x87B20038771FC,0x6A41108};
+
+const BIG TEST_Pxa={0xE4A00F52183C77,0x554E02DF4F8354,0xB65EB5CF1C2F89,0x8B71A87BFCFC9,0x49EEDB1};
+const BIG TEST_Pxb={0xCFB8FA9AA8845D,0x8A9CC76D966697,0x185BA05BF5EC08,0x76140E87D97226,0x1FB93AB6};
+const BIG TEST_Pya={0x3644CC1EDF208A,0xA637FB3FF8E257,0x4453DA2BB9E686,0xD14AD3CDF6A1FE,0xCD04A1E};
+const BIG TEST_Pyb={0x71BD7630A43C14,0x1CAA9F14EA264E,0x3C3C2DFC765DEF,0xCF59D1A1A7D6EE,0x11FF7795};
+
+
+#endif
+*/
+int main()
+{
+    int i;
+    char byt[32];
+    csprng rng;
+    BIG xa,xb,ya,yb,w,a,b,t1,q,u[2],v[4],m,r;
+    ECP2 P,G;
+    ECP Q,R;
+    FP12 g,gp;
+    FP4 t,c,cp,cpm1,cpm2;
+    FP2 x,y,X;
+
+
+    BIG_rcopy(a,CURVE_Fra);
+    BIG_rcopy(b,CURVE_Frb);
+    FP2_from_BIGs(&X,a,b);
+
+    BIG_rcopy(xa,CURVE_Gx);
+    BIG_rcopy(ya,CURVE_Gy);
+
+    ECP_set(&Q,xa,ya);
+    if (Q.inf) printf("Failed to set - point not on curve\n");
+    else printf("G1 set success\n");
+
+    printf("Q= ");
+    ECP_output(&Q);
+    printf("\n");
+
+//	BIG_rcopy(r,CURVE_Order); BIG_dec(r,7); BIG_norm(r);
+    BIG_rcopy(xa,CURVE_Pxa);
+    BIG_rcopy(xb,CURVE_Pxb);
+    BIG_rcopy(ya,CURVE_Pya);
+    BIG_rcopy(yb,CURVE_Pyb);
+
+    FP2_from_BIGs(&x,xa,xb);
+    FP2_from_BIGs(&y,ya,yb);
+
+    ECP2_set(&P,&x,&y);
+    if (P.inf) printf("Failed to set - point not on curve\n");
+    else printf("G2 set success\n");
+
+    printf("P= ");
+    ECP2_output(&P);
+    printf("\n");
+
+    for (i=0; i<1000; i++ )
+    {
+
+        PAIR_ate(&g,&P,&Q);
+        PAIR_fexp(&g);
+
+//	PAIR_GTpow(&g,xa);
+
+    }
+    printf("g= ");
+    FP12_output(&g);
+    printf("\n");
+
+}
+
+#endif
diff --git a/version22/c/rand.c b/version22/c/rand.c
new file mode 100644
index 0000000..4a2cd0a
--- /dev/null
+++ b/version22/c/rand.c
@@ -0,0 +1,172 @@
+/*
+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.
+*/
+
+/*
+ *   Cryptographic strong random number generator
+ *
+ *   Unguessable seed -> SHA -> PRNG internal state -> SHA -> random numbers
+ *   Slow - but secure
+ *
+ *   See ftp://ftp.rsasecurity.com/pub/pdfs/bull-1.pdf for a justification
+ */
+/* SU=m, m is Stack Usage */
+
+#include "amcl.h"
+
+/* SU= 20 */
+static unsign32 sbrand(csprng *rng)
+{
+    /* Marsaglia & Zaman random number generator */
+    int i,k;
+    unsign32 pdiff,t;
+    rng->rndptr++;
+    if (rng->rndptr<NK) return rng->ira[rng->rndptr];
+    rng->rndptr=0;
+    for (i=0,k=NK-NJ; i<NK; i++,k++)
+    {
+        /* calculate next NK values */
+        if (k==NK) k=0;
+        t=rng->ira[k];
+        pdiff=t - rng->ira[i] - rng->borrow;
+
+        if (pdiff<t) rng->borrow=0;
+        if (pdiff>t) rng->borrow=1;
+        rng->ira[i]=pdiff;
+    }
+    return rng->ira[0];
+}
+
+/* SU= 20 */
+static void sirand(csprng* rng,unsign32 seed)
+{
+    /* initialise random number system */
+    /* modified so that a subsequent call "stirs" in another seed value */
+    /* in this way as many seed bits as desired may be used */
+    int i,in;
+    unsign32 t,m=1;
+    rng->borrow=0L;
+    rng->rndptr=0;
+    rng->ira[0]^=seed;
+    for (i=1; i<NK; i++)
+    {
+        /* fill initialisation vector */
+        in=(NV*i)%NK;
+        rng->ira[in]^=m;      /* note XOR */
+        t=m;
+        m=seed-m;
+        seed=t;
+    }
+    for (i=0; i<10000; i++) sbrand(rng ); /* "warm-up" & stir the generator */
+}
+
+/* SU= 312 */
+static void fill_pool(csprng *rng)
+{
+    /* hash down output of RNG to re-fill the pool */
+    int i;
+    hash256 sh;
+    HASH256_init(&sh);
+    for (i=0; i<128; i++) HASH256_process(&sh,sbrand(rng));
+    HASH256_hash(&sh,rng->pool);
+    rng->pool_ptr=0;
+}
+
+static unsign32 pack(const uchar *b)
+{
+    /* pack bytes into a 32-bit Word */
+    return ((unsign32)b[3]<<24)|((unsign32)b[2]<<16)|((unsign32)b[1]<<8)|(unsign32)b[0];
+}
+
+/* SU= 360 */
+/* Initialize RNG with some real entropy from some external source */
+void RAND_seed(csprng *rng,int rawlen,char *raw)
+{
+    /* initialise from at least 128 byte string of raw  *
+     * random (keyboard?) input, and 32-bit time-of-day */
+    int i;
+    char digest[32];
+    uchar b[4];
+    hash256 sh;
+    rng->pool_ptr=0;
+    for (i=0; i<NK; i++) rng->ira[i]=0;
+    if (rawlen>0)
+    {
+        HASH256_init(&sh);
+        for (i=0; i<rawlen; i++)
+            HASH256_process(&sh,raw[i]);
+        HASH256_hash(&sh,digest);
+
+        /* initialise PRNG from distilled randomness */
+
+        for (i=0; i<8; i++)
+        {
+            b[0]=digest[4*i];
+            b[1]=digest[4*i+1];
+            b[2]=digest[4*i+2];
+            b[3]=digest[4*i+3];
+            //	printf("%08x\n",pack(b));
+            sirand(rng,pack(b));
+        }
+    }
+    fill_pool(rng);
+}
+
+/* Terminate and clean up */
+void RAND_clean(csprng *rng)
+{
+    /* kill internal state */
+    int i;
+    rng->pool_ptr=rng->rndptr=0;
+    for (i=0; i<32; i++) rng->pool[i]=0;
+    for (i=0; i<NK; i++) rng->ira[i]=0;
+    rng->borrow=0;
+}
+
+/* get random byte */
+/* SU= 8 */
+int RAND_byte(csprng *rng)
+{
+    int r;
+    r=rng->pool[rng->pool_ptr++];
+    if (rng->pool_ptr>=32) fill_pool(rng);
+    return (r&0xff);
+}
+
+/* test main program */
+/*
+#include <stdio.h>
+#include <string.h>
+
+void main()
+{
+    int i;
+    char raw[256];
+    csprng rng;
+
+	RAND_clean(&rng);
+
+
+	for (i=0;i<256;i++) raw[i]=(char)i;
+    RAND_seed(&rng,256,raw);
+
+	for (i=0;i<1000;i++)
+		printf("%02x ",(unsigned char)RAND_byte(&rng));
+}
+
+*/
diff --git a/version22/c/randapi.c b/version22/c/randapi.c
new file mode 100644
index 0000000..9b32efb
--- /dev/null
+++ b/version22/c/randapi.c
@@ -0,0 +1,15 @@
+#include "randapi.h"
+
+/* Initialise a Cryptographically Strong Random Number Generator from
+   an octet of raw random data */
+
+void CREATE_CSPRNG(csprng *RNG,octet *RAW)
+{
+    RAND_seed(RNG,RAW->len,RAW->val);
+}
+
+void KILL_CSPRNG(csprng *RNG)
+{
+    RAND_clean(RNG);
+}
+
diff --git a/version22/c/randapi.h b/version22/c/randapi.h
new file mode 100644
index 0000000..631499d
--- /dev/null
+++ b/version22/c/randapi.h
@@ -0,0 +1,20 @@
+#ifndef RANDOM_H
+#define RANDOM_H
+
+#include "amcl.h"
+
+/**	@brief Initialise a random number generator
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param S is an input truly random seed value
+ */
+extern void CREATE_CSPRNG(csprng *R,octet *S);
+/**	@brief Kill a random number generator
+ *
+	Deletes all internal state
+	@param R is a pointer to a cryptographically secure random number generator
+ */
+extern void KILL_CSPRNG(csprng *R);
+
+#endif
+
diff --git a/version22/c/readme.txt b/version22/c/readme.txt
new file mode 100644
index 0000000..278770a
--- /dev/null
+++ b/version22/c/readme.txt
@@ -0,0 +1,77 @@
+AMCL is very simple to build.
+
+The examples here are for GCC under Linux and Windows (using MINGW).
+
+First indicate your computer/compiler architecture by setting the wordlength 
+in arch.h
+
+Next - decide what you want to do. Edit amcl.h - note there is only
+one area where USER CONFIGURABLE input is requested.
+
+Here choose your curve.
+
+Once this is done, build the library, and compile and link your program 
+with an API file and the ROM file rom.c that contains curve constants.
+
+Three example API files are provided, mpin.c which supports our M-Pin 
+(tm) protocol, ecdh.c which supports standard elliptic 
+curve key exchange, digital signature and public key crypto, and rsa.c 
+which supports the RSA method. The first 
+can be tested using the testmpin.c driver programs, the second can 
+be tested using testecdh.c, and the third can be tested using
+testrsa.c
+
+In the ROM file you must provide the curve constants. Several examples
+are provided there, and if you are willing to use one of these, simply
+select your curve of CHOICE in amcl.h
+
+Example (1), in amcl.h choose
+
+#define CHOICE BN254
+
+and
+
+#define CURVETYPE WEIERSTRASS
+
+Under windows run the batch file build_pair.bat to build the amcl.a library
+and the testmpin.exe applications.
+
+For linux execute "bash build_pair"
+
+Example (2), in amcl.h choose
+
+#define CHOICE C25519
+
+and
+
+#define CURVETYPE EDWARDS
+
+to select the Edwards curve ed25519.
+
+Under Windows run the batch file build_ec.bat to build the amcl.a library and
+the testecdh.exe application.
+
+For Linux execute "bash build_ec"
+
+
+To help generate the ROM constants for your own curve some MIRACL helper 
+programs are included. The programs bngen.cpp and blsgen.cpp generate ROM 
+data for a BN and BLS pairing friendly curves, and the program ecgen.cpp 
+generates ROM data for regular EC curves.
+
+The MIRACL based program check.cpp helps choose the best number base for
+big number representation, given the word-length and the size of the modulus.
+
+The program bigtobig.cpp converts a big number to the AMCL 
+BIG format.
+
+
+For quick jumpstart:-
+
+(Linux)
+bash build_pair
+./testmpin
+
+(Windows + MingW)
+build_pair
+testmpin
diff --git a/version22/c/rom.c b/version22/c/rom.c
new file mode 100644
index 0000000..9fada44
--- /dev/null
+++ b/version22/c/rom.c
@@ -0,0 +1,1206 @@
+/*
+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.
+*/
+
+/* AMCL - ROM file */
+
+#include "amcl.h"
+
+/* Field and Curve Details */
+
+#if CHOICE==BN254
+
+/* Nogami's fast curve */
+
+const int CURVE_A=0;
+#if CHUNK==16
+
+const chunk MConst=0x15E5;
+const BIG Modulus= {0x13,0x0,0x0,0x0,0x1A70,0x9,0x0,0x0,0x100,0x309,0x2,0x0,0x1800,0x1A26,0x6E8,0x0,0x0,0x412,0x8D9,0x4A};
+const BIG CURVE_Order= {0xD,0x0,0x0,0x0,0xA10,0x8,0x0,0x0,0x1F80,0x1FFC,0x1,0x0,0x1800,0x1A26,0x6E8,0x0,0x0,0x412,0x8D9,0x4A};
+const BIG CURVE_Cof= {0x1};
+const BIG CURVE_B= {0x2};
+const BIG CURVE_Bnx= {0x1,0x0,0x0,0x0,0x408};
+const BIG CURVE_Cru= {0x7,0x0,0x0,0x0,0xCD8,0x3,0x0,0x0,0x900,0x1248,0x0,0x0,0x400,0x19B1,0x126};
+const BIG CURVE_Fra= {0xDE9,0x1953,0x101B,0x1BCD,0xE17,0x1BE1,0x14FD,0x1249,0x974,0x1C28,0x54F,0x108D,0x150A,0x4CD,0x12D9,0xF91,0x12E,0x10C9,0xDDD,0x36};
+const BIG CURVE_Frb= {0x122A,0x6AC,0xFE4,0x432,0xC58,0x428,0xB02,0xDB6,0x178B,0x6E0,0x1AB2,0xF72,0x2F5,0x1559,0x140F,0x106E,0x1ED1,0x1348,0x1AFB,0x13};
+//const BIG CURVE_Pxa={0xCB4,0xFE8,0x1E4D,0x1658,0x2BA,0x2BE,0x13F3,0x33C,0x5E3,0x182D,0x1D8E,0xDBE,0x124F,0xFDB,0x8CD,0x14FD,0x155E,0x6A7,0x16C1,0x12};
+//const BIG CURVE_Pxb={0x455,0x4B1,0x1E4,0xFA,0x38A,0x152F,0x149E,0x17C7,0xD86,0x1CEB,0x11FC,0xAE,0x189E,0x15F,0x1275,0x8F6,0x83,0x53E,0x1536,0xB};
+//const BIG CURVE_Pya={0x46C,0x1045,0x1A1E,0x1B9C,0x1F9A,0xC8,0x629,0x61D,0x82B,0xB48,0xC7C,0xF09,0x4C3,0x168E,0x1E85,0x627,0x5E5,0x15F9,0xFCA,0x15};
+//const BIG CURVE_Pyb={0x6EC,0xF98,0x1501,0x1F11,0xE6D,0x9D0,0xB74,0xED,0x482,0x12E0,0x75A,0xF03,0x11E4,0x313,0x16CE,0x1B57,0x679,0x143F,0x1DA6,0x30};
+const BIG CURVE_Pxa= {0x1B2B,0x1F,0x932,0x1C84,0x191E,0x1F86,0x262,0x1769,0x48B,0x1523,0x1B6D,0x18C3,0x7E8,0x6C6,0x1FAE,0x16C5,0x119E,0x5DA,0x684,0xC};
+const BIG CURVE_Pxb= {0xCF3,0x1EAA,0x1079,0x1869,0x10D8,0x25B,0x18DE,0xD75,0xD74,0x18FA,0xA96,0x1305,0x18C5,0x553,0xCC4,0xF06,0x1A73,0x17CD,0x5AA,0xA};
+const BIG CURVE_Pya= {0xB9A,0xE69,0x1E24,0x1C0,0x119F,0x4DE,0x16F8,0x1CD7,0x1D0A,0x194D,0x88,0x1319,0x966,0x870,0xE6A,0x1268,0xBAF,0x1D03,0x625,0x4};
+const BIG CURVE_Pyb= {0xE9B,0x19D6,0x1B1A,0x1A35,0x18A2,0x4AB,0x1CE7,0x1FFA,0x1006,0x1D84,0x34D,0xBE7,0x56F,0x16A2,0x1A3D,0x2A4,0x1C8B,0x1873,0xECA,0x1D};
+const BIG CURVE_Gx= {0x12,0x0,0x0,0x0,0x1A70,0x9,0x0,0x0,0x100,0x309,0x2,0x0,0x1800,0x1A26,0x6E8,0x0,0x0,0x412,0x8D9,0x4A};
+const BIG CURVE_Gy= {0x1};
+const BIG CURVE_W[2]= {{0x3,0x0,0x0,0x0,0x40,0x1,0x0,0x0,0x180,0x30C},{0x1,0x0,0x0,0x0,0x810}};
+const BIG CURVE_SB[2][2]= {{{0x4,0x0,0x0,0x0,0x850,0x1,0x0,0x0,0x180,0x30C},{0x1,0x0,0x0,0x0,0x810}},{{0x1,0x0,0x0,0x0,0x810},{0xA,0x0,0x0,0x0,0x9D0,0x7,0x0,0x0,0x1E00,0x1CF0,0x1,0x0,0x1800,0x1A26,0x6E8,0x0,0x0,0x412,0x8D9,0x4A}}};
+const BIG CURVE_WB[4]= {{0x0,0x0,0x0,0x0,0x408,0x0,0x0,0x0,0x80,0x104},{0x5,0x0,0x0,0x0,0x14A8,0x2,0x0,0x0,0x700,0xE38,0x0,0x0,0x1800,0x1120,0xC4},{0x3,0x0,0x0,0x0,0xC58,0x1,0x0,0x0,0x380,0x71C,0x0,0x0,0xC00,0x890,0x62},{0x1,0x0,0x0,0x0,0xC18,0x0,0x0,0x0,0x80,0x104}};
+const BIG CURVE_BB[4][4]= {{{0xD,0x0,0x0,0x0,0x608,0x8,0x0,0x0,0x1F80,0x1FFC,0x1,0x0,0x1800,0x1A26,0x6E8,0x0,0x0,0x412,0x8D9,0x4A},{0xC,0x0,0x0,0x0,0x608,0x8,0x0,0x0,0x1F80,0x1FFC,0x1,0x0,0x1800,0x1A26,0x6E8,0x0,0x0,0x412,0x8D9,0x4A},{0xC,0x0,0x0,0x0,0x608,0x8,0x0,0x0,0x1F80,0x1FFC,0x1,0x0,0x1800,0x1A26,0x6E8,0x0,0x0,0x412,0x8D9,0x4A},{0x2,0x0,0x0,0x0,0x810}},{{0x1,0x0,0x0,0x0,0x810},{0xC,0x0,0x0,0x0,0x608,0x8,0x0,0x0,0x1F80,0x1FFC,0x1,0x0,0x1800,0x1A26,0x6E8,0x0,0x0,0x412,0x8D9,0x4A},{0xD,0x0,0x0,0x0,0x608,0x8,0x0,0x0,0x1F80,0x1FFC,0x1,0x0,0x1800,0x1A26,0x6E8,0x0,0x0,0x412,0x8D9,0x4A},{0xC,0x0,0x0,0x0,0x608,0x8,0x0,0x0,0x1F80,0x1FFC,0x1,0x0,0x1800,0x1A26,0x6E8,0x0,0x0,0x412,0x8D9,0x4A}},{{0x2,0x0,0x0,0x0,0x810},{0x1,0x0,0x0,0x0,0x810},{0x1,0x0,0x0,0x0,0x810},{0x1,0x0,0x0,0x0,0x810}},{{0x2,0x0,0x0,0x0,0x408},{0x2,0x0,0x0,0x0,0x1020},{0xA,0x0,0x0,0x0,0x200,0x8,0x0,0x0,0x1F80,0x1FFC,0x1,0x0,0x1800,0x1A26,0x6E8,0x0,0x0,0x412,0x8D9,0x4A},{0x2,0x0,0x0,0x0,0x408}}};
+#endif
+
+#if CHUNK==32
+
+const chunk MConst=0x179435E5;
+const BIG Modulus= {0x13,0x18000000,0x4E9,0x2000000,0x8612,0x6C00000,0x6E8D1,0x10480000,0x252364};
+const BIG CURVE_Order= {0xD,0x8000000,0x428,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364};
+const BIG CURVE_Cof= {0x1};
+const BIG CURVE_B= {0x2};
+const BIG CURVE_Bnx= {0x1,0x4000000,0x10};
+const BIG CURVE_Cru= {0x7,0xC000000,0x1B3,0x12000000,0x2490,0x11200000,0x126CD};
+const BIG CURVE_Fra= {0xF2A6DE9,0xBEF3603,0xFDDF0B8,0x12E9249A,0x953F850,0xDA85423,0x1232D926,0x32425CF,0x1B3776};
+const BIG CURVE_Frb= {0x10D5922A,0xC10C9FC,0x10221431,0xF16DB65,0x16AC8DC1,0x1917ABDC,0xDD40FAA,0xD23DA30,0x9EBEE};
+//const BIG CURVE_Pxa={0x15FD0CB4,0x1D5963C9,0x1F315F0A,0xBC633C9,0x1763B05A,0x1B927B6F,0x1FA8CD7E,0x1A9EABD4,0x95B04};
+//const BIG CURVE_Pxb={0x10962455,0x503E83C,0x9EA978E,0x1B0D7C7A,0x147F39D6,0x1FC4F02B,0x1ED2750A,0x14F81068,0x5D4D8};
+//const BIG CURVE_Pya={0x1A08A46C,0xD6E7343,0x290647E,0x105661D3,0xB1F1690,0xE261BC2,0x4FE85B4,0x17E4BCA6,0xABF2A};
+//const BIG CURVE_Pyb={0x5F306EC,0x16FC46A0,0x1744E839,0x9040ED5,0x19D6A5C0,0x138F23C0,0xAF6CE18,0x10FCCF3B,0x18769A};
+const BIG CURVE_Pxa= {0x803FB2B,0xF721126,0x62FC364,0x9177691,0x1EDB6A46,0x63F4630,0x18BFAE36,0x176A33D6,0x61A10};
+const BIG CURVE_Pxb= {0x7D54CF3,0xC61A60F,0xDE12DC3,0x1AE8D75C,0xAA5B1F4,0x13C62CC1,0xCCC42A,0x1F374E6F,0x516AA};
+const BIG CURVE_Pya= {0x11CD2B9A,0xF8703C4,0xF826F46,0x1A15CD7B,0x822329B,0x104B34C6,0xD0E6A43,0x140D75F2,0x21897};
+const BIG CURVE_Pyb= {0xB3ACE9B,0x1168D763,0xE7255E2,0xDFFAE,0x18D37B09,0x22B7AF9,0x149A3DB5,0x1CF9162,0xEBB2B};
+const BIG CURVE_Gx= {0x12,0x18000000,0x4E9,0x2000000,0x8612,0x6C00000,0x6E8D1,0x10480000,0x252364};
+const BIG CURVE_Gy= {0x1};
+const BIG CURVE_W[2]= {{0x3,0x0,0x81,0x3000000,0x618},{0x1,0x8000000,0x20}};
+const BIG CURVE_SB[2][2]= {{{0x4,0x8000000,0xA1,0x3000000,0x618},{0x1,0x8000000,0x20}},{{0x1,0x8000000,0x20},{0xA,0x8000000,0x3A7,0x1C000000,0x79E1,0x6C00000,0x6E8D1,0x10480000,0x252364}}};
+const BIG CURVE_WB[4]= {{0x0,0x4000000,0x10,0x1000000,0x208},{0x5,0x14000000,0x152,0xE000000,0x1C70,0xC00000,0xC489},{0x3,0xC000000,0xB1,0x7000000,0xE38,0x10600000,0x6244},{0x1,0xC000000,0x30,0x1000000,0x208}};
+const BIG CURVE_BB[4][4]= {{{0xD,0x4000000,0x418,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364},{0xC,0x4000000,0x418,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364},{0xC,0x4000000,0x418,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364},{0x2,0x8000000,0x20}},{{0x1,0x8000000,0x20},{0xC,0x4000000,0x418,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364},{0xD,0x4000000,0x418,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364},{0xC,0x4000000,0x418,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364}},{{0x2,0x8000000,0x20},{0x1,0x8000000,0x20},{0x1,0x8000000,0x20},{0x1,0x8000000,0x20}},{{0x2,0x4000000,0x10},{0x2,0x10000000,0x40},{0xA,0x0,0x408,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364},{0x2,0x4000000,0x10}}};
+#endif
+
+#if CHUNK==64
+
+const chunk MConst=0x435E50D79435E5;
+const BIG Modulus= {0x13,0x13A7,0x80000000086121,0x40000001BA344D,0x25236482};
+const BIG CURVE_Order= {0xD,0x800000000010A1,0x8000000007FF9F,0x40000001BA344D,0x25236482};
+const BIG CURVE_Cof= {0x1};
+const BIG CURVE_B= {0x2};
+const BIG CURVE_Bnx= {0x80000000000001,0x40};
+const BIG CURVE_Cru= {0x80000000000007,0x6CD,0x40000000024909,0x49B362};
+const BIG CURVE_Fra= {0x7DE6C06F2A6DE9,0x74924D3F77C2E1,0x50A846953F8509,0x212E7C8CB6499B,0x1B377619};
+const BIG CURVE_Frb= {0x82193F90D5922A,0x8B6DB2C08850C5,0x2F57B96AC8DC17,0x1ED1837503EAB2,0x9EBEE69};
+//const BIG CURVE_Pxa={0xAB2C7935FD0CB4,0xE319E4FCC57C2B,0x24F6DF763B05A5,0xF55EA7EA335FB7,0x95B04D4};
+//const BIG CURVE_Pxb={0xA07D0790962455,0x86BE3D27AA5E38,0x89E05747F39D6D,0xC08347B49D42BF,0x5D4D8A7};
+//const BIG CURVE_Pya={0xADCE687A08A46C,0x2B30E98A4191F9,0x4C3784B1F16908,0x25E5313FA16D1C,0xABF2ABF};
+//const BIG CURVE_Pyb={0xDF88D405F306EC,0x82076ADD13A0E6,0x1E47819D6A5C04,0xE679DABDB38627,0x18769A87};
+const BIG CURVE_Pxa= {0xEE4224C803FB2B,0x8BBB4898BF0D91,0x7E8C61EDB6A464,0x519EB62FEB8D8C,0x61A10BB};
+const BIG CURVE_Pxb= {0x8C34C1E7D54CF3,0x746BAE3784B70D,0x8C5982AA5B1F4D,0xBA737833310AA7,0x516AAF9};
+const BIG CURVE_Pya= {0xF0E07891CD2B9A,0xAE6BDBE09BD19,0x96698C822329BD,0x6BAF93439A90E0,0x21897A0};
+const BIG CURVE_Pyb= {0x2D1AEC6B3ACE9B,0x6FFD739C9578A,0x56F5F38D37B090,0x7C8B15268F6D44,0xEBB2B0E};
+
+const BIG CURVE_Gx= {0x12,0x13A7,0x80000000086121,0x40000001BA344D,0x25236482};
+const BIG CURVE_Gy= {0x1};
+const BIG CURVE_W[2]= {{0x3,0x80000000000204,0x6181},{0x1,0x81}};
+const BIG CURVE_SB[2][2]= {{{0x4,0x80000000000285,0x6181},{0x1,0x81}},{{0x1,0x81},{0xA,0xE9D,0x80000000079E1E,0x40000001BA344D,0x25236482}}};
+const BIG CURVE_WB[4]= {{0x80000000000000,0x80000000000040,0x2080},{0x80000000000005,0x54A,0x8000000001C707,0x312241},{0x80000000000003,0x800000000002C5,0xC000000000E383,0x189120},{0x80000000000001,0x800000000000C1,0x2080}};
+const BIG CURVE_BB[4][4]= {{{0x8000000000000D,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482},{0x8000000000000C,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482},{0x8000000000000C,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482},{0x2,0x81}},{{0x1,0x81},{0x8000000000000C,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482},{0x8000000000000D,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482},{0x8000000000000C,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482}},{{0x2,0x81},{0x1,0x81},{0x1,0x81},{0x1,0x81}},{{0x80000000000002,0x40},{0x2,0x102},{0xA,0x80000000001020,0x8000000007FF9F,0x40000001BA344D,0x25236482},{0x80000000000002,0x40}}};
+#endif
+
+#endif
+
+#if CHOICE==BN254_T
+
+/* GT-Strong BN curve */
+
+const int CURVE_A=0;
+#if CHUNK==16
+
+const chunk MConst=0x4E5;
+const BIG Modulus= {0x713,0x15A5,0x1FBB,0x1B77,0xBE9,0x125D,0x13D1,0xAC2,0xA55,0x374,0x157C,0xDF1,0x1369,0x5D5,0x1BE8,0x29,0x517,0x6DB,0x48,0x48};
+const BIG CURVE_Order= {0x10D,0x981,0x1FA3,0xAEE,0x3A7,0x59B,0xACB,0x692,0x8D4,0x74,0x157C,0xDF1,0x1369,0x5D5,0x1BE8,0x29,0x517,0x6DB,0x48,0x48};
+const BIG CURVE_Cof= {0x1};
+const BIG CURVE_B= {0x2};
+const BIG CURVE_Bnx= {0x81,0x2,0x1800,0x100,0x400};
+const BIG CURVE_Cru= {0xD87,0x1A7E,0x156A,0x16A7,0x1ADE,0x188F,0xAEA,0x14BE,0xC82,0xBB2,0x132,0xA2A,0x1476,0xD8,0x120};
+const BIG CURVE_Fra= {0x22,0xE40,0x13AB,0xBA2,0x159F,0x671,0x1BEB,0x9A,0xC49,0xDF3,0xC84,0x142,0x1F19,0x1284,0x53D,0x1887,0x9BB,0x1496,0xA28,0x26};
+const BIG CURVE_Frb= {0x6F1,0x765,0xC10,0xFD5,0x164A,0xBEB,0x17E6,0xA27,0x1E0C,0x1580,0x8F7,0xCAF,0x1450,0x1350,0x16AA,0x7A2,0x1B5B,0x1244,0x161F,0x21};
+const BIG CURVE_Pxa= {0x5BB,0x473,0x188A,0x130F,0x1BE8,0x1189,0x12A9,0x15A3,0xC00,0x1BE6,0x1522,0x82,0x1325,0x2A,0x1AF3,0x673,0x4C1,0x1E68,0x120F,0x28};
+const BIG CURVE_Pxb= {0x2C0,0x6DF,0x202,0xF11,0x13A6,0x1A42,0x78,0x1C3F,0x157F,0xBDC,0x146D,0x634,0x10A6,0x1FE2,0xB68,0x1860,0x184E,0x1599,0x1FD1,0x10};
+const BIG CURVE_Pya= {0xA1D,0x106,0x11F8,0x58,0x16C2,0xCF9,0x1A0E,0x2CF,0xCB4,0x164A,0x7DC,0xA87,0x1C6E,0x1634,0x1D28,0x17A,0x102B,0x14E0,0x1A30,0x29};
+const BIG CURVE_Pyb= {0x8F2,0xB31,0x1F1C,0x1086,0x6BD,0x1BEE,0x1EF2,0x1C2C,0xA27,0xE8,0x1C9A,0x18EA,0xA82,0x160C,0x7B7,0x97A,0x245,0x1523,0xBF8,0x2F};
+const BIG CURVE_Gx= {0x712,0x15A5,0x1FBB,0x1B77,0xBE9,0x125D,0x13D1,0xAC2,0xA55,0x374,0x157C,0xDF1,0x1369,0x5D5,0x1BE8,0x29,0x517,0x6DB,0x48,0x48};
+const BIG CURVE_Gy= {0x1};
+const BIG CURVE_W[2]= {{0x403,0xC1C,0x18,0xC86,0x1842,0xCC1,0x906,0x430,0x181,0x300},{0x101,0x4,0x1000,0x201,0x800}};
+const BIG CURVE_SB[2][2]= {{{0x504,0xC20,0x1018,0xE87,0x42,0xCC2,0x906,0x430,0x181,0x300},{0x101,0x4,0x1000,0x201,0x800}},{{0x101,0x4,0x1000,0x201,0x800},{0x1D0A,0x1D64,0x1F8A,0x1E68,0xB64,0x18D9,0x1C4,0x262,0x753,0x1D74,0x157B,0xDF1,0x1369,0x5D5,0x1BE8,0x29,0x517,0x6DB,0x48,0x48}}};
+const BIG CURVE_WB[4]= {{0x80,0x406,0x1808,0x280,0xC16,0x440,0x302,0xC10,0x80,0x100},{0xA85,0x462,0x102,0xA72,0x36B,0xE36,0xD4B,0x5F4,0x1EAD,0x1476,0x1621,0x6C6,0xDA4,0x90,0xC0},{0x583,0x232,0xC81,0x15B9,0x3B5,0x171B,0x6A5,0x12FA,0xF56,0x1A3B,0xB10,0x363,0x6D2,0x48,0x60},{0x181,0x40A,0x808,0x482,0x1416,0x440,0x302,0xC10,0x80,0x100}};
+const BIG CURVE_BB[4][4]= {{{0x8D,0x97F,0x7A3,0x9EE,0x1FA7,0x59A,0xACB,0x692,0x8D4,0x74,0x157C,0xDF1,0x1369,0x5D5,0x1BE8,0x29,0x517,0x6DB,0x48,0x48},{0x8C,0x97F,0x7A3,0x9EE,0x1FA7,0x59A,0xACB,0x692,0x8D4,0x74,0x157C,0xDF1,0x1369,0x5D5,0x1BE8,0x29,0x517,0x6DB,0x48,0x48},{0x8C,0x97F,0x7A3,0x9EE,0x1FA7,0x59A,0xACB,0x692,0x8D4,0x74,0x157C,0xDF1,0x1369,0x5D5,0x1BE8,0x29,0x517,0x6DB,0x48,0x48},{0x102,0x4,0x1000,0x201,0x800}},{{0x101,0x4,0x1000,0x201,0x800},{0x8C,0x97F,0x7A3,0x9EE,0x1FA7,0x59A,0xACB,0x692,0x8D4,0x74,0x157C,0xDF1,0x1369,0x5D5,0x1BE8,0x29,0x517,0x6DB,0x48,0x48},{0x8D,0x97F,0x7A3,0x9EE,0x1FA7,0x59A,0xACB,0x692,0x8D4,0x74,0x157C,0xDF1,0x1369,0x5D5,0x1BE8,0x29,0x517,0x6DB,0x48,0x48},{0x8C,0x97F,0x7A3,0x9EE,0x1FA7,0x59A,0xACB,0x692,0x8D4,0x74,0x157C,0xDF1,0x1369,0x5D5,0x1BE8,0x29,0x517,0x6DB,0x48,0x48}},{{0x102,0x4,0x1000,0x201,0x800},{0x101,0x4,0x1000,0x201,0x800},{0x101,0x4,0x1000,0x201,0x800},{0x101,0x4,0x1000,0x201,0x800}},{{0x82,0x2,0x1800,0x100,0x400},{0x202,0x8,0x0,0x403,0x1000},{0xA,0x97D,0xFA3,0x8ED,0x1BA7,0x59A,0xACB,0x692,0x8D4,0x74,0x157C,0xDF1,0x1369,0x5D5,0x1BE8,0x29,0x517,0x6DB,0x48,0x48},{0x82,0x2,0x1800,0x100,0x400}}};
+#endif
+
+#if CHUNK==32
+
+const chunk MConst=0x1914C4E5;
+const BIG Modulus= {0xEB4A713,0x14EDDFF7,0x1D192EAF,0x14AAAC29,0xD5F06E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120};
+const BIG CURVE_Order= {0xD30210D,0x13ABBBF4,0xCB2CD8E,0x11A86925,0xD5F00E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120};
+const BIG CURVE_Cof= {0x1};
+const BIG CURVE_B= {0x2};
+const BIG CURVE_Bnx= {0x4081,0x40300,0x10};
+const BIG CURVE_Cru= {0xB4FCD87,0xF5A9EAD,0xEAC47EB,0x19054BE5,0x104C9764,0x18A3B28A,0x12006};
+const BIG CURVE_Fra= {0xDC80022,0xFAE8A75,0x1EB338D6,0x189209AD,0x13211BE6,0x4F8C850,0x10E53D94,0x12593778,0x1328A2};
+const BIG CURVE_Frb= {0xECA6F1,0x53F5582,0x1E65F5D9,0x1C18A27B,0x1A3DEB01,0x10A2832B,0x1456AA9A,0x9136B67,0x10D87E};
+const BIG CURVE_Pxa= {0x88E65BB,0x144C3F11,0xA98C4EF,0x18015A39,0x1548B7CC,0xA992820,0xE7AF301,0x19A09826,0x14483F};
+const BIG CURVE_Pxb= {0x8DBE2C0,0x133C4440,0x78D214E,0xAFFC3F0,0x51B57B9,0x285318D,0xC0B68FF,0x166709D8,0x87F46};
+const BIG CURVE_Pya= {0x20CA1D,0x101623F,0xE67CDB,0x19682CFD,0x19F72C94,0x14E372A1,0xF5D28B1,0x13820561,0x14E8C2};
+const BIG CURVE_Pyb= {0x116628F2,0x1EC21BE3,0xF2DF71A,0x144FC2CF,0x172681D0,0xC54163A,0xF47B7B0,0x148C48A9,0x17AFE2};
+const BIG CURVE_Gx= {0xEB4A712,0x14EDDFF7,0x1D192EAF,0x14AAAC29,0xD5F06E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120};
+const BIG CURVE_Gy= {0x1};
+const BIG CURVE_W[2]= {{0x1838403,0x1321803,0x106660E1,0x3024304,0x600},{0x8101,0x80600,0x20}};
+const BIG CURVE_SB[2][2]= {{{0x1840504,0x13A1E03,0x10666101,0x3024304,0x600},{0x8101,0x80600,0x20}},{{0x8101,0x80600,0x20},{0xBAC9D0A,0x1279A3F1,0x1C4C6CAD,0xEA62620,0xD5EFAE8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120}}};
+const BIG CURVE_WB[4]= {{0x80C080,0xB0A0301,0x10222030,0x100C101,0x200},{0x88C4A85,0x15A9C820,0x14B71B0D,0x1D5A5F46,0x158868ED,0x106D21B1,0xC004},{0x4464583,0x1AD6E590,0xA5B8D8E,0x1EAD2FA3,0x1AC43476,0x83690D8,0x6002},{0x814181,0xB120901,0x10222050,0x100C101,0x200}};
+const BIG CURVE_BB[4][4]= {{{0xD2FE08D,0x13A7B8F4,0xCB2CD7E,0x11A86925,0xD5F00E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120},{0xD2FE08C,0x13A7B8F4,0xCB2CD7E,0x11A86925,0xD5F00E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120},{0xD2FE08C,0x13A7B8F4,0xCB2CD7E,0x11A86925,0xD5F00E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120},{0x8102,0x80600,0x20}},{{0x8101,0x80600,0x20},{0xD2FE08C,0x13A7B8F4,0xCB2CD7E,0x11A86925,0xD5F00E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120},{0xD2FE08D,0x13A7B8F4,0xCB2CD7E,0x11A86925,0xD5F00E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120},{0xD2FE08C,0x13A7B8F4,0xCB2CD7E,0x11A86925,0xD5F00E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120}},{{0x8102,0x80600,0x20},{0x8101,0x80600,0x20},{0x8101,0x80600,0x20},{0x8101,0x80600,0x20}},{{0x4082,0x40300,0x10},{0x10202,0x100C00,0x40},{0xD2FA00A,0x13A3B5F4,0xCB2CD6E,0x11A86925,0xD5F00E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120},{0x4082,0x40300,0x10}}};
+#endif
+
+#if CHUNK==64
+
+const chunk MConst=0xC5A872D914C4E5;
+const BIG Modulus= {0x9DBBFEEEB4A713,0x555614F464BABE,0x3696F8D5F06E8A,0x6517014EFA0BAB,0x240120DB};
+const BIG CURVE_Order= {0x75777E8D30210D,0xD43492B2CB363A,0x3696F8D5F00E88,0x6517014EFA0BAB,0x240120DB};
+const BIG CURVE_Cof= {0x1};
+const BIG CURVE_B= {0x2};
+const BIG CURVE_Bnx= {0x806000004081,0x40};
+const BIG CURVE_Cru= {0xEB53D5AB4FCD87,0x82A5F2BAB11FAD,0x47651504C9764C,0x4801B1};
+const BIG CURVE_Fra= {0xF5D14EADC80022,0x4904D6FACCE359,0xF190A13211BE6C,0xC9BBC4394F6509,0x1328A292};
+const BIG CURVE_Frb= {0xA7EAB040ECA6F1,0xC513DF997D764,0x450657A3DEB01E,0x9B5B3D15AAA6A1,0x10D87E48};
+const BIG CURVE_Pxa= {0x8987E2288E65BB,0xAD1CAA6313BE,0x325041548B7CCC,0x4C1339EBCC055,0x14483FCD};
+const BIG CURVE_Pxb= {0x67888808DBE2C0,0x7FE1F81E34853A,0xA631A51B57B95,0x384EC302DA3FC5,0x87F46B3};
+const BIG CURVE_Pya= {0x202C47E020CA1D,0xB4167E8399F36C,0xC6E5439F72C94C,0x102B0BD74A2C69,0x14E8C29C};
+const BIG CURVE_Pyb= {0xD8437C716628F2,0x27E167BCB7DC6B,0xA82C7572681D0A,0x62454BD1EDEC18,0x17AFE2A4};
+const BIG CURVE_Gx= {0x9DBBFEEEB4A712,0x555614F464BABE,0x3696F8D5F06E8A,0x6517014EFA0BAB,0x240120DB};
+const BIG CURVE_Gy= {0x1};
+const BIG CURVE_W[2]= {{0x26430061838403,0x81218241998384,0x6001},{0x100C000008101,0x80}};
+const BIG CURVE_SB[2][2]= {{{0x2743C061840504,0x81218241998404,0x6001},{0x100C000008101,0x80}},{{0x100C000008101,0x80},{0x4F347E2BAC9D0A,0x5313107131B2B6,0x3696F8D5EFAE87,0x6517014EFA0BAB,0x240120DB}}};
+const BIG CURVE_WB[4]= {{0x6140602080C080,0x806080C08880C1,0x2000},{0xB53904088C4A85,0xAD2FA352DC6C36,0xDA436358868EDE,0x300120},{0x5ADCB204464583,0x5697D1A96E363B,0x6D21B1AC43476F,0x180090},{0x62412020814181,0x806080C0888141,0x2000}};
+const BIG CURVE_BB[4][4]= {{{0x74F71E8D2FE08D,0xD43492B2CB35FA,0x3696F8D5F00E88,0x6517014EFA0BAB,0x240120DB},{0x74F71E8D2FE08C,0xD43492B2CB35FA,0x3696F8D5F00E88,0x6517014EFA0BAB,0x240120DB},{0x74F71E8D2FE08C,0xD43492B2CB35FA,0x3696F8D5F00E88,0x6517014EFA0BAB,0x240120DB},{0x100C000008102,0x80}},{{0x100C000008101,0x80},{0x74F71E8D2FE08C,0xD43492B2CB35FA,0x3696F8D5F00E88,0x6517014EFA0BAB,0x240120DB},{0x74F71E8D2FE08D,0xD43492B2CB35FA,0x3696F8D5F00E88,0x6517014EFA0BAB,0x240120DB},{0x74F71E8D2FE08C,0xD43492B2CB35FA,0x3696F8D5F00E88,0x6517014EFA0BAB,0x240120DB}},{{0x100C000008102,0x80},{0x100C000008101,0x80},{0x100C000008101,0x80},{0x100C000008101,0x80}},{{0x806000004082,0x40},{0x2018000010202,0x100},{0x7476BE8D2FA00A,0xD43492B2CB35BA,0x3696F8D5F00E88,0x6517014EFA0BAB,0x240120DB},{0x806000004082,0x40}}};
+#endif
+
+#endif
+
+#if CHOICE==BN254_T2
+
+const int CURVE_A=0;
+#if CHUNK==16
+
+const chunk MConst=0x1CDD;
+const BIG Modulus= {0x48B,0x305,0xAED,0x5B8,0x1E8B,0xB28,0x3C3,0x1C85,0xF93,0x40E,0x1400,0x1713,0xF3,0x710,0x16DD,0xB55,0x10F,0x412,0x1,0x48};
+const BIG CURVE_Order= {0xBF5,0xD51,0x944,0x16E3,0x1D7F,0x1C19,0x1EDC,0x1C24,0xF8D,0x10E,0x1400,0x1713,0xF3,0x710,0x16DD,0xB55,0x10F,0x412,0x1,0x48};
+const BIG CURVE_Cof= {0x1};
+const BIG CURVE_B= {0x2};
+const BIG CURVE_Bnx= {0x205,0x304,0x40,0x4,0x400};
+const BIG CURVE_Cru= {0x1D33,0x335,0x1112,0x4E,0xFB5,0x387,0x59,0xEE6,0x155B,0x11B3,0x1B3C,0x2F7,0xC36,0x3,0x120};
+const BIG CURVE_Fra= {0x1062,0x1D77,0x125C,0x4D1,0x92B,0x1E72,0xF0E,0x1366,0x1CC6,0xADD,0x1FC6,0x1F46,0x1F67,0x520,0x1AF4,0x1956,0x9E8,0x1C69,0x1382,0x24};
+const BIG CURVE_Frb= {0x1429,0x58D,0x1890,0xE6,0x1560,0xCB6,0x14B4,0x91E,0x12CD,0x1930,0x1439,0x17CC,0x18B,0x1EF,0x1BE9,0x11FE,0x1726,0x7A8,0xC7E,0x23};
+const BIG CURVE_Pxa= {0x3C8,0x1A05,0xE67,0x1924,0x4AC,0x8BC,0x598,0x149D,0x15CD,0x359,0x185C,0xAD2,0x17B0,0x1CEB,0x609,0x18C6,0x1693,0x1E7C,0x1F05,0x2D};
+const BIG CURVE_Pxb= {0x1540,0x2A4,0x2B6,0xAF5,0x105,0x883,0x1BD9,0xF7C,0x1B6F,0x8BE,0xA57,0x120F,0x565,0xC4,0x272,0xEB2,0x1D59,0x805,0xD6D,0x3D};
+const BIG CURVE_Pya= {0x513,0x110,0x1145,0x17D9,0x1147,0x19BD,0x1839,0xF10,0x44A,0x934,0xD7C,0x1072,0x51B,0x6FD,0xA75,0x455,0x1614,0x4C3,0x3B9,0x3D};
+const BIG CURVE_Pyb= {0x78E,0x1BE7,0x3D5,0x1265,0x1FB,0x12BC,0x9BE,0x8DC,0x1EB7,0x713,0x7EE,0x1B78,0xA93,0xEBB,0xE8A,0x77B,0x1AE3,0x66D,0x13BD,0x47};
+const BIG CURVE_Gx= {0x48A,0x305,0xAED,0x5B8,0x1E8B,0xB28,0x3C3,0x1C85,0xF93,0x40E,0x1400,0x1713,0xF3,0x710,0x16DD,0xB55,0x10F,0x412,0x1,0x48};
+const BIG CURVE_Gy= {0x1};
+const BIG CURVE_W[2]= {{0x1083,0x9A3,0xA8,0xEC5,0x110B,0xF0E,0x4E6,0x60,0x6,0x300},{0x409,0x608,0x80,0x8,0x800}};
+const BIG CURVE_SB[2][2]= {{{0x148C,0xFAB,0x128,0xECD,0x190B,0xF0E,0x4E6,0x60,0x6,0x300},{0x409,0x608,0x80,0x8,0x800}},{{0x409,0x608,0x80,0x8,0x800},{0x1B72,0x3AD,0x89C,0x81E,0xC74,0xD0B,0x19F6,0x1BC4,0xF87,0x1E0E,0x13FF,0x1713,0xF3,0x710,0x16DD,0xB55,0x10F,0x412,0x1,0x48}}};
+const BIG CURVE_WB[4]= {{0x224,0x1385,0x1522,0x4E5,0x1459,0x504,0x1A2,0x20,0x2,0x100},{0xF19,0x187,0xB3C,0x14AE,0x1D5,0x1B9,0x18D5,0xA2E,0x396,0xDCD,0x1228,0x1FA,0x824,0x2,0xC0},{0x188F,0x245,0x5BE,0x1A59,0x12EA,0x10DC,0xC6A,0x517,0x11CB,0x6E6,0x914,0xFD,0x412,0x1,0x60},{0x62D,0x198D,0x15A2,0x4ED,0x1C59,0x504,0x1A2,0x20,0x2,0x100}};
+const BIG CURVE_BB[4][4]= {{{0x9F1,0xA4D,0x904,0x16DF,0x197F,0x1C19,0x1EDC,0x1C24,0xF8D,0x10E,0x1400,0x1713,0xF3,0x710,0x16DD,0xB55,0x10F,0x412,0x1,0x48},{0x9F0,0xA4D,0x904,0x16DF,0x197F,0x1C19,0x1EDC,0x1C24,0xF8D,0x10E,0x1400,0x1713,0xF3,0x710,0x16DD,0xB55,0x10F,0x412,0x1,0x48},{0x9F0,0xA4D,0x904,0x16DF,0x197F,0x1C19,0x1EDC,0x1C24,0xF8D,0x10E,0x1400,0x1713,0xF3,0x710,0x16DD,0xB55,0x10F,0x412,0x1,0x48},{0x40A,0x608,0x80,0x8,0x800}},{{0x409,0x608,0x80,0x8,0x800},{0x9F0,0xA4D,0x904,0x16DF,0x197F,0x1C19,0x1EDC,0x1C24,0xF8D,0x10E,0x1400,0x1713,0xF3,0x710,0x16DD,0xB55,0x10F,0x412,0x1,0x48},{0x9F1,0xA4D,0x904,0x16DF,0x197F,0x1C19,0x1EDC,0x1C24,0xF8D,0x10E,0x1400,0x1713,0xF3,0x710,0x16DD,0xB55,0x10F,0x412,0x1,0x48},{0x9F0,0xA4D,0x904,0x16DF,0x197F,0x1C19,0x1EDC,0x1C24,0xF8D,0x10E,0x1400,0x1713,0xF3,0x710,0x16DD,0xB55,0x10F,0x412,0x1,0x48}},{{0x40A,0x608,0x80,0x8,0x800},{0x409,0x608,0x80,0x8,0x800},{0x409,0x608,0x80,0x8,0x800},{0x409,0x608,0x80,0x8,0x800}},{{0x206,0x304,0x40,0x4,0x400},{0x812,0xC10,0x100,0x10,0x1000},{0x7EA,0x749,0x8C4,0x16DB,0x157F,0x1C19,0x1EDC,0x1C24,0xF8D,0x10E,0x1400,0x1713,0xF3,0x710,0x16DD,0xB55,0x10F,0x412,0x1,0x48},{0x206,0x304,0x40,0x4,0x400}}};
+#endif
+
+#if CHUNK==32
+
+const chunk MConst=0x6505CDD;
+const BIG Modulus= {0x1460A48B,0x596E15D,0x1C35947A,0x1F27C851,0x1D00081C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004};
+const BIG CURVE_Order= {0x11AA2BF5,0x1FDB8D28,0xDCE0CF5,0x1F1BC24F,0x1D00021C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004};
+const BIG CURVE_Cof= {0x1};
+const BIG CURVE_B= {0x2};
+const BIG CURVE_Bnx= {0x608205,0x1008,0x10};
+const BIG CURVE_Cru= {0x866BD33,0x1A813A22,0x591C3BE,0xAB6EE60,0x1ECF2367,0x361B0BD,0x12000};
+const BIG CURVE_Fra= {0x13AEF062,0x1593464B,0x10EF3924,0x198D3667,0x17F195BB,0xFB3FD1,0xADAF429,0x11A53D19,0x124E0B};
+const BIG CURVE_Frb= {0xB1B429,0x10039B12,0xB465B55,0x59A91EA,0x50E7261,0xF0C5DF3,0x1FDBE90F,0x1EA2E4D1,0x11B1F8};
+const BIG CURVE_Pxa= {0x1F40A3C8,0x166491CC,0x19845E12,0xB9B49D2,0x161706B3,0xBBD82B4,0x18C609E7,0x19F2D278,0x16FC17};
+const BIG CURVE_Pxb= {0x18549540,0x2ABD456,0x1D944184,0x16DEF7CD,0x1A95D17D,0x42B2C83,0x16427206,0x17AB2E,0x1EB5B5};
+const BIG CURVE_Pya= {0x14220513,0x3DF6628,0x39CDEC5,0x894F10C,0x135F1268,0x1D28DC1C,0xAAA7537,0x130EC284,0x1E8EE4};
+const BIG CURVE_Pyb= {0x177CE78E,0x1DC9947A,0x1BE95E07,0x1D6E8DC4,0x1FB8E27,0x1B549EDE,0xF6E8A75,0x19B75C67,0x23CEF4};
+const BIG CURVE_Gx= {0x1460A48A,0x596E15D,0x1C35947A,0x1F27C851,0x1D00081C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004};
+const BIG CURVE_Gy= {0x1};
+const BIG CURVE_W[2]= {{0x1347083,0x5BB1415,0xE678744,0xC0602,0x600},{0xC10409,0x2010,0x20}};
+const BIG CURVE_SB[2][2]= {{{0x1F5748C,0x5BB3425,0xE678764,0xC0602,0x600},{0xC10409,0x2010,0x20}},{{0xC10409,0x2010,0x20},{0x1075BB72,0x1A207913,0x1F6685B1,0x1F0FBC4C,0x1CFFFC1C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004}}};
+const BIG CURVE_WB[4]= {{0xA70A224,0xC9396A4,0x1A228251,0x40200,0x200},{0x1030EF19,0xAD2B967,0xD50DC87,0x72CA2EC,0x148A1B9A,0x241207E,0xC000},{0x1848B88F,0x156964B7,0x6A86E4B,0x3965176,0xA450DCD,0x120903F,0x6000},{0xB31A62D,0xC93B6B4,0x1A228271,0x40200,0x200}};
+const BIG CURVE_BB[4][4]= {{{0x1149A9F1,0x1FDB7D20,0xDCE0CE5,0x1F1BC24F,0x1D00021C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004},{0x1149A9F0,0x1FDB7D20,0xDCE0CE5,0x1F1BC24F,0x1D00021C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004},{0x1149A9F0,0x1FDB7D20,0xDCE0CE5,0x1F1BC24F,0x1D00021C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004},{0xC1040A,0x2010,0x20}},{{0xC10409,0x2010,0x20},{0x1149A9F0,0x1FDB7D20,0xDCE0CE5,0x1F1BC24F,0x1D00021C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004},{0x1149A9F1,0x1FDB7D20,0xDCE0CE5,0x1F1BC24F,0x1D00021C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004},{0x1149A9F0,0x1FDB7D20,0xDCE0CE5,0x1F1BC24F,0x1D00021C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004}},{{0xC1040A,0x2010,0x20},{0xC10409,0x2010,0x20},{0xC10409,0x2010,0x20},{0xC10409,0x2010,0x20}},{{0x608206,0x1008,0x10},{0x1820812,0x4020,0x40},{0x10E927EA,0x1FDB6D18,0xDCE0CD5,0x1F1BC24F,0x1D00021C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004},{0x608206,0x1008,0x10}}};
+#endif
+
+#if CHUNK==64
+
+const chunk MConst=0xFE6A47A6505CDD;
+const BIG Modulus= {0xB2DC2BB460A48B,0x93E428F0D651E8,0xF3B89D00081CF,0x410F5AADB74E20,0x24000482};
+const BIG CURVE_Order= {0xFB71A511AA2BF5,0x8DE127B73833D7,0xF3B89D00021CF,0x410F5AADB74E20,0x24000482};
+const BIG CURVE_Cof= {0x1};
+const BIG CURVE_B= {0x2};
+const BIG CURVE_Bnx= {0x20100608205,0x40};
+const BIG CURVE_Cru= {0x5027444866BD33,0x5B773016470EFB,0xC3617BECF23675,0x480006};
+const BIG CURVE_Fra= {0xB268C973AEF062,0xC69B33C3BCE492,0xF67FA37F195BBC,0x29E8CAB6BD0A41,0x124E0B8D};
+const BIG CURVE_Frb= {0x736240B1B429,0xCD48F52D196D56,0x18BBE650E72612,0x17268FF6FA43DE,0x11B1F8F5};
+const BIG CURVE_Pxa= {0xCC92399F40A3C8,0xCDA4E96611784A,0x7B056961706B35,0x9693C6318279D7,0x16FC17CF};
+const BIG CURVE_Pxb= {0x557A8AD8549540,0x6F7BE6F6510610,0x565907A95D17DB,0xBD5975909C8188,0x1EB5B500};
+const BIG CURVE_Pya= {0x7BECC514220513,0x4A78860E737B14,0x51B83935F12684,0x761422AA9D4DFA,0x1E8EE498};
+const BIG CURVE_Pyb= {0xB9328F577CE78E,0xB746E26FA5781F,0xA93DBC1FB8E27E,0xBAE33BDBA29D76,0x23CEF4CD};
+const BIG CURVE_Gx= {0xB2DC2BB460A48A,0x93E428F0D651E8,0xF3B89D00081CF,0x410F5AADB74E20,0x24000482};
+const BIG CURVE_Gy= {0x1};
+const BIG CURVE_W[2]= {{0xB76282A1347083,0x60301399E1D10,0x6000},{0x40200C10409,0x80}};
+const BIG CURVE_SB[2][2]= {{{0xB76684A1F5748C,0x60301399E1D90,0x6000},{0x40200C10409,0x80}},{{0x40200C10409,0x80},{0x440F227075BB72,0x87DE267D9A16C7,0xF3B89CFFFC1CF,0x410F5AADB74E20,0x24000482}}};
+const BIG CURVE_WB[4]= {{0x9272D48A70A224,0x20100688A0945,0x2000},{0x5A572CF030EF19,0x9651763543721D,0x8240FD48A1B9A3,0x300004},{0xAD2C96F848B88F,0xCB28BB1AA1B92E,0x41207EA450DCD1,0x180002},{0x9276D68B31A62D,0x20100688A09C5,0x2000}};
+const BIG CURVE_BB[4][4]= {{{0xFB6FA41149A9F1,0x8DE127B7383397,0xF3B89D00021CF,0x410F5AADB74E20,0x24000482},{0xFB6FA41149A9F0,0x8DE127B7383397,0xF3B89D00021CF,0x410F5AADB74E20,0x24000482},{0xFB6FA41149A9F0,0x8DE127B7383397,0xF3B89D00021CF,0x410F5AADB74E20,0x24000482},{0x40200C1040A,0x80}},{{0x40200C10409,0x80},{0xFB6FA41149A9F0,0x8DE127B7383397,0xF3B89D00021CF,0x410F5AADB74E20,0x24000482},{0xFB6FA41149A9F1,0x8DE127B7383397,0xF3B89D00021CF,0x410F5AADB74E20,0x24000482},{0xFB6FA41149A9F0,0x8DE127B7383397,0xF3B89D00021CF,0x410F5AADB74E20,0x24000482}},{{0x40200C1040A,0x80},{0x40200C10409,0x80},{0x40200C10409,0x80},{0x40200C10409,0x80}},{{0x20100608206,0x40},{0x80401820812,0x100},{0xFB6DA310E927EA,0x8DE127B7383357,0xF3B89D00021CF,0x410F5AADB74E20,0x24000482},{0x20100608206,0x40}}};
+#endif
+
+
+#endif
+
+#if CHOICE==BN254_CX
+
+/* CertiVox BN Curve */
+
+const int CURVE_A=0;
+#if CHUNK==16
+
+const chunk MConst=0x1E85;
+const BIG Modulus= {0x15B3,0xDA,0x1BD7,0xC47,0x1BE6,0x1F70,0x24,0x1DC3,0x1FD6,0x1921,0x19B4,0x14C6,0x1647,0x1EEF,0x16C2,0x541,0x870,0x0,0x0,0x48};
+const BIG CURVE_Order= {0x1F6D,0x1758,0x98D,0x381,0xBE1,0x367,0x1324,0x1DC1,0x1FD6,0x1621,0x19B4,0x14C6,0x1647,0x1EEF,0x16C2,0x541,0x870,0x0,0x0,0x48};
+const BIG CURVE_Cof= {0x1};
+const BIG CURVE_B= {0x2};
+const BIG CURVE_Bnx= {0x12B1,0x1E00,0x0,0x0,0x400};
+const BIG CURVE_Cru= {0x1C97,0x11A,0x5E5,0x126,0x31E,0x3AB,0x7BE,0xC8E,0x1DDF,0x205,0xFC5,0x1950,0x0,0x0,0x120};
+const BIG CURVE_Fra= {0xEA3,0xE40,0xCD5,0x1210,0x15BD,0x1C10,0x5CF,0x4DE,0x773,0x343,0x626,0x194E,0x18AA,0x10C5,0x12BF,0x2C,0x63A,0x17D,0x1642,0x26};
+const BIG CURVE_Frb= {0x710,0x129A,0xF01,0x1A37,0x628,0x360,0x1A55,0x18E4,0x1863,0x15DE,0x138E,0x1B78,0x1D9C,0xE29,0x403,0x515,0x236,0x1E83,0x9BD,0x21};
+const BIG CURVE_Pxa= {0xC74,0x697,0x1BB9,0xA39,0xC08,0x1393,0xF8,0x17F4,0x1C85,0x1C83,0x12EE,0xB86,0x100F,0x592,0x18D6,0x164A,0x1053,0x963,0x1A0B,0x32};
+const BIG CURVE_Pxb= {0xFE1,0x114E,0x2CB,0xB1D,0x147A,0x187,0x827,0x1618,0x1B97,0x1FC0,0x5D0,0x11D3,0x137A,0x8E4,0xA80,0x1EC9,0x1E19,0xF61,0x19AE,0x28};
+const BIG CURVE_Pya= {0x9F,0x185F,0x1AF3,0x17F9,0x10CF,0xD9,0x11FB,0x7B0,0x1B3,0xB1B,0x1882,0x1B5D,0x157,0xF11,0x1760,0x571,0x1233,0xECB,0x1E7B,0x14};
+const BIG CURVE_Pyb= {0xE9D,0x4C7,0x8A2,0x96,0x1ED9,0x16F5,0x74B,0x14AD,0x64E,0xE14,0xD18,0x1B1A,0x512,0x372,0xD7,0x1812,0xCC4,0x1CF,0x583,0xC};
+const BIG CURVE_Gx= {0x15B2,0xDA,0x1BD7,0xC47,0x1BE6,0x1F70,0x24,0x1DC3,0x1FD6,0x1921,0x19B4,0x14C6,0x1647,0x1EEF,0x16C2,0x541,0x870,0x0,0x0,0x48};
+const BIG CURVE_Gy= {0x1};
+const BIG CURVE_W[2]= {{0xB83,0x117F,0x1245,0x8C6,0x5,0x1C09,0xD00,0x1,0x0,0x300},{0x561,0x1C01,0x1,0x0,0x800}};
+const BIG CURVE_SB[2][2]= {{{0x10E4,0xD80,0x1247,0x8C6,0x805,0x1C09,0xD00,0x1,0x0,0x300},{0x561,0x1C01,0x1,0x0,0x800}},{{0x561,0x1C01,0x1,0x0,0x800},{0x13EA,0x5D9,0x1748,0x1ABA,0xBDB,0x75E,0x623,0x1DC0,0x1FD6,0x1321,0x19B4,0x14C6,0x1647,0x1EEF,0x16C2,0x541,0x870,0x0,0x0,0x48}}};
+const BIG CURVE_WB[4]= {{0x4B0,0x13D4,0x615,0x1842,0x401,0x958,0xF00,0x0,0x0,0x100},{0x475,0x1110,0x56F,0x1BF3,0x36C,0x1FCD,0x329,0x1DB5,0x1E94,0xE03,0xA83,0x10E0,0x0,0x0,0xC0},{0xB93,0x788,0x12B8,0xDF9,0x13B6,0x1FE6,0x1194,0xEDA,0x1F4A,0x1701,0x541,0x870,0x0,0x0,0x60},{0xA11,0xFD5,0x617,0x1842,0xC01,0x958,0xF00,0x0,0x0,0x100}};
+const BIG CURVE_BB[4][4]= {{{0xCBD,0x1958,0x98C,0x381,0x7E1,0x367,0x1324,0x1DC1,0x1FD6,0x1621,0x19B4,0x14C6,0x1647,0x1EEF,0x16C2,0x541,0x870,0x0,0x0,0x48},{0xCBC,0x1958,0x98C,0x381,0x7E1,0x367,0x1324,0x1DC1,0x1FD6,0x1621,0x19B4,0x14C6,0x1647,0x1EEF,0x16C2,0x541,0x870,0x0,0x0,0x48},{0xCBC,0x1958,0x98C,0x381,0x7E1,0x367,0x1324,0x1DC1,0x1FD6,0x1621,0x19B4,0x14C6,0x1647,0x1EEF,0x16C2,0x541,0x870,0x0,0x0,0x48},{0x562,0x1C01,0x1,0x0,0x800}},{{0x561,0x1C01,0x1,0x0,0x800},{0xCBC,0x1958,0x98C,0x381,0x7E1,0x367,0x1324,0x1DC1,0x1FD6,0x1621,0x19B4,0x14C6,0x1647,0x1EEF,0x16C2,0x541,0x870,0x0,0x0,0x48},{0xCBD,0x1958,0x98C,0x381,0x7E1,0x367,0x1324,0x1DC1,0x1FD6,0x1621,0x19B4,0x14C6,0x1647,0x1EEF,0x16C2,0x541,0x870,0x0,0x0,0x48},{0xCBC,0x1958,0x98C,0x381,0x7E1,0x367,0x1324,0x1DC1,0x1FD6,0x1621,0x19B4,0x14C6,0x1647,0x1EEF,0x16C2,0x541,0x870,0x0,0x0,0x48}},{{0x562,0x1C01,0x1,0x0,0x800},{0x561,0x1C01,0x1,0x0,0x800},{0x561,0x1C01,0x1,0x0,0x800},{0x561,0x1C01,0x1,0x0,0x800}},{{0x12B2,0x1E00,0x0,0x0,0x400},{0xAC2,0x1802,0x3,0x0,0x1000},{0x1A0A,0x1B57,0x98B,0x381,0x3E1,0x367,0x1324,0x1DC1,0x1FD6,0x1621,0x19B4,0x14C6,0x1647,0x1EEF,0x16C2,0x541,0x870,0x0,0x0,0x48},{0x12B2,0x1E00,0x0,0x0,0x400}}};
+#endif
+
+#if CHUNK==32
+
+const chunk MConst=0x19789E85;
+const BIG Modulus= {0x1C1B55B3,0x13311F7A,0x24FB86F,0x1FADDC30,0x166D3243,0xFB23D31,0x836C2F7,0x10E05,0x240000};
+const BIG CURVE_Order= {0x16EB1F6D,0x108E0531,0x1241B3AF,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000};
+const BIG CURVE_Cof= {0x1};
+const BIG CURVE_B= {0x2};
+const BIG CURVE_Bnx= {0x3C012B1,0x0,0x10};
+const BIG CURVE_Cru= {0x14235C97,0xF0498BC,0x1BE1D58C,0x1BBEC8E3,0x3F1440B,0x654,0x12000};
+const BIG CURVE_Fra= {0x15C80EA3,0x1EC8419A,0x1CFE0856,0xEE64DE2,0x11898686,0x5C55653,0x592BF86,0x5F4C740,0x135908};
+const BIG CURVE_Frb= {0x6534710,0x1468DDE0,0x551B018,0x10C78E4D,0x4E3ABBD,0x9ECE6DE,0x2A40371,0x1A0C46C5,0x10A6F7};
+const BIG CURVE_Pxa= {0x4D2EC74,0x428E777,0xF89C9B0,0x190B7F40,0x14BBB907,0x12807AE1,0x958D62C,0x58E0A76,0x19682D};
+const BIG CURVE_Pxb= {0xE29CFE1,0x1D2C7459,0x270C3D1,0x172F6184,0x19743F81,0x49BD474,0x192A8047,0x1D87C33E,0x1466B9};
+const BIG CURVE_Pya= {0xF0BE09F,0x7DFE75E,0x1FB06CC3,0x3667B08,0xE209636,0x110ABED7,0xE376078,0x1B2E4665,0xA79ED};
+const BIG CURVE_Pyb= {0x898EE9D,0xC825914,0x14BB7AFB,0xC9D4AD3,0x13461C28,0x122896C6,0x240D71B,0x73D9898,0x6160C};
+const BIG CURVE_Gx= {0x1C1B55B2,0x13311F7A,0x24FB86F,0x1FADDC30,0x166D3243,0xFB23D31,0x836C2F7,0x10E05,0x240000};
+const BIG CURVE_Gy= {0x1};
+const BIG CURVE_W[2]= {{0x162FEB83,0x2A31A48,0x100E0480,0x16,0x600},{0x7802561,0x0,0x20}};
+const BIG CURVE_SB[2][2]= {{{0x1DB010E4,0x2A31A48,0x100E04A0,0x16,0x600},{0x7802561,0x0,0x20}},{{0x7802561,0x0,0x20},{0xBB33EA,0xDEAEAE9,0x233AF2F,0x1FADDC03,0x166D2643,0xFB23D31,0x836C2F7,0x10E05,0x240000}}};
+const BIG CURVE_WB[4]= {{0x167A84B0,0xE108C2,0x1004AC10,0x7,0x200},{0x1E220475,0x166FCCAD,0x129FE68D,0x1D29DB51,0x2A0DC07,0x438,0xC000},{0xF10B93,0x1B37E657,0x194FF34E,0x1E94EDA8,0x1506E03,0x21C,0x6000},{0x1DFAAA11,0xE108C2,0x1004AC30,0x7,0x200}};
+const BIG CURVE_BB[4][4]= {{{0x132B0CBD,0x108E0531,0x1241B39F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000},{0x132B0CBC,0x108E0531,0x1241B39F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000},{0x132B0CBC,0x108E0531,0x1241B39F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000},{0x7802562,0x0,0x20}},{{0x7802561,0x0,0x20},{0x132B0CBC,0x108E0531,0x1241B39F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000},{0x132B0CBD,0x108E0531,0x1241B39F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000},{0x132B0CBC,0x108E0531,0x1241B39F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000}},{{0x7802562,0x0,0x20},{0x7802561,0x0,0x20},{0x7802561,0x0,0x20},{0x7802561,0x0,0x20}},{{0x3C012B2,0x0,0x10},{0xF004AC2,0x0,0x40},{0xF6AFA0A,0x108E0531,0x1241B38F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000},{0x3C012B2,0x0,0x10}}};
+#endif
+
+#if CHUNK==64
+
+const chunk MConst=0x4E205BF9789E85;
+const BIG Modulus= {0x6623EF5C1B55B3,0xD6EE18093EE1BE,0x647A6366D3243F,0x8702A0DB0BDDF,0x24000000};
+const BIG CURVE_Order= {0x11C0A636EB1F6D,0xD6EE0CC906CEBE,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000};
+const BIG CURVE_Cof= {0x1};
+const BIG CURVE_B= {0x2};
+const BIG CURVE_Bnx= {0x3C012B1,0x40};
+const BIG CURVE_Cru= {0xE0931794235C97,0xDF6471EF875631,0xCA83F1440BD,0x480000};
+const BIG CURVE_Fra= {0xD9083355C80EA3,0x7326F173F8215B,0x8AACA718986867,0xA63A0164AFE18B,0x1359082F};
+const BIG CURVE_Frb= {0x8D1BBC06534710,0x63C7269546C062,0xD9CDBC4E3ABBD8,0x623628A900DC53,0x10A6F7D0};
+const BIG CURVE_Pxa= {0x851CEEE4D2EC74,0x85BFA03E2726C0,0xF5C34BBB907C,0x7053B256358B25,0x19682D2C};
+const BIG CURVE_Pxb= {0xA58E8B2E29CFE1,0x97B0C209C30F47,0x37A8E99743F81B,0x3E19F64AA011C9,0x1466B9EC};
+const BIG CURVE_Pya= {0xFBFCEBCF0BE09F,0xB33D847EC1B30C,0x157DAEE2096361,0x72332B8DD81E22,0xA79EDD9};
+const BIG CURVE_Pyb= {0x904B228898EE9D,0x4EA569D2EDEBED,0x512D8D3461C286,0xECC4C09035C6E4,0x6160C39};
+const BIG CURVE_Gx= {0x6623EF5C1B55B2,0xD6EE18093EE1BE,0x647A6366D3243F,0x8702A0DB0BDDF,0x24000000};
+const BIG CURVE_Gy= {0x1};
+const BIG CURVE_W[2]= {{0x546349162FEB83,0xB40381200,0x6000},{0x7802561,0x80}};
+const BIG CURVE_SB[2][2]= {{{0x5463491DB010E4,0xB40381280,0x6000},{0x7802561,0x80}},{{0x7802561,0x80},{0xBD5D5D20BB33EA,0xD6EE0188CEBCBD,0x647A6366D2643F,0x8702A0DB0BDDF,0x24000000}}};
+const BIG CURVE_WB[4]= {{0x1C2118567A84B0,0x3C012B040,0x2000},{0xCDF995BE220475,0x94EDA8CA7F9A36,0x8702A0DC07E,0x300000},{0x66FCCAE0F10B93,0x4A76D4653FCD3B,0x4381506E03F,0x180000},{0x1C21185DFAAA11,0x3C012B0C0,0x2000}};
+const BIG CURVE_BB[4][4]= {{{0x11C0A6332B0CBD,0xD6EE0CC906CE7E,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000},{0x11C0A6332B0CBC,0xD6EE0CC906CE7E,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000},{0x11C0A6332B0CBC,0xD6EE0CC906CE7E,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000},{0x7802562,0x80}},{{0x7802561,0x80},{0x11C0A6332B0CBC,0xD6EE0CC906CE7E,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000},{0x11C0A6332B0CBD,0xD6EE0CC906CE7E,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000},{0x11C0A6332B0CBC,0xD6EE0CC906CE7E,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000}},{{0x7802562,0x80},{0x7802561,0x80},{0x7802561,0x80},{0x7802561,0x80}},{{0x3C012B2,0x40},{0xF004AC2,0x100},{0x11C0A62F6AFA0A,0xD6EE0CC906CE3E,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000},{0x3C012B2,0x40}}};
+#endif
+
+#endif
+
+#if CHOICE==NIST256
+
+/* Standard NIST-256 Curve */
+
+const int CURVE_A= -3;
+const chunk MConst=1;
+
+#if CHUNK==16
+
+const BIG Modulus= {0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1F,0x0,0x0,0x0,0x0,0x0,0x0,0x400,0x0,0x0,0x1FF8,0x1FFF,0x1FF};
+const BIG CURVE_B= {0x4B,0x1E93,0xF89,0x1C78,0x3BC,0x187B,0x114E,0x1619,0x1D06,0x328,0x1AF,0xD31,0x1557,0x15DE,0x1ECF,0x127C,0xA3A,0xEC5,0x118D,0xB5};
+const BIG CURVE_Order= {0x551,0x319,0x10BF,0x1395,0xF3B,0xF42,0x1C5E,0x15B4,0x6FA,0x1DE7,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x3FF,0x0,0x0,0x1FF8,0x1FFF,0x1FF};
+const BIG CURVE_Gx= {0x296,0x4C6,0x1176,0x272,0xF4A,0x19D0,0x17AC,0x1025,0x37D,0x13B8,0x103C,0x748,0xE56,0x1E73,0x1FE2,0x848,0x12C,0xF97,0x5F4,0xD6};
+const BIG CURVE_Gy= {0x11F5,0x1DFA,0x1A0D,0xC80,0xCBB,0xF67,0xCC5,0xAED,0xE33,0x115E,0x785,0x181F,0x14A7,0x13F5,0xE3B,0xFF3,0x1E1A,0x1717,0x18D0,0x9F};
+
+#endif
+
+#if CHUNK==32
+
+const BIG Modulus= {0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FF,0x0,0x0,0x40000,0x1FE00000,0xFFFFFF};
+const BIG CURVE_B= {0x7D2604B,0x1E71E1F1,0x14EC3D8E,0x1A0D6198,0x86BC651,0x1EAABB4C,0xF9ECFAE,0x1B154752,0x5AC635};
+const BIG CURVE_Order= {0x1C632551,0x1DCE5617,0x5E7A13C,0xDF55B4E,0x1FFFFBCE,0x1FFFFFFF,0x3FFFF,0x1FE00000,0xFFFFFF};
+const BIG CURVE_Gx= {0x1898C296,0x509CA2E,0x1ACCE83D,0x6FB025B,0x40F2770,0x1372B1D2,0x91FE2F3,0x1E5C2588,0x6B17D1};
+const BIG CURVE_Gy= {0x17BF51F5,0x1DB20341,0xC57B3B2,0x1C66AED6,0x19E162BC,0x15A53E07,0x1E6E3B9F,0x1C5FC34F,0x4FE342};
+
+#endif
+
+#if CHUNK==64
+
+const BIG Modulus= {0xFFFFFFFFFFFFFF,0xFFFFFFFFFF,0x0,0x1000000,0xFFFFFFFF};
+const BIG CURVE_B= {0xCE3C3E27D2604B,0x6B0CC53B0F63B,0x55769886BC651D,0xAA3A93E7B3EBBD,0x5AC635D8};
+const BIG CURVE_Order= {0xB9CAC2FC632551,0xFAADA7179E84F3,0xFFFFFFFFFFBCE6,0xFFFFFF,0xFFFFFFFF};
+const BIG CURVE_Gx= {0xA13945D898C296,0x7D812DEB33A0F4,0xE563A440F27703,0xE12C4247F8BCE6,0x6B17D1F2};
+const BIG CURVE_Gy= {0xB6406837BF51F5,0x33576B315ECECB,0x4A7C0F9E162BCE,0xFE1A7F9B8EE7EB,0x4FE342E2};
+
+#endif
+
+#endif
+
+#if CHOICE==MF254
+
+/* Montgomery-Friendly NUMS curves http://eprint.iacr.org/2014/130 */
+
+/* p=k.2^n-1 where n is multiple of BASEBITS - but k can be adjusted. */
+/* Here p=2^240(2^14-127)-1 = 2^232(2^22-256.127)-1 where 8*29=232 and (2^22-256.127)=0x3F8100 */
+/* or = 2^224(2^30-65536.127)-1 where 4*56=224 and (2^30-65536.127) = 0x3F810000 */
+
+#if CHUNK==32
+
+const BIG Modulus= {0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3F80FF};
+const chunk MConst=0x3F8100;
+
+#if CURVETYPE==WEIERSTRASS
+const int CURVE_A= -3;
+const BIG CURVE_Order= {0xF8DF83F,0x1D20CE25,0x8DD701B,0x317D41B,0x1FFFFEB8,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3F80FF};
+const BIG CURVE_B= {0x1FFFD08D,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3F80FF};
+const BIG CURVE_Gx= {0x2};
+const BIG CURVE_Gy= {0x190D4EBC,0xB2EF9BF,0x14464C6B,0xE71C7F0,0x18AEBDFB,0xD3ADEBB,0x18052B85,0x1A6765CA,0x140E3F};
+#endif
+
+#if CURVETYPE==EDWARDS
+const int CURVE_A= -1;
+const BIG CURVE_Order= {0x46E98C7,0x179E9FF6,0x158BEC3A,0xA60D917,0x1FFFFEB9,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFE03F};
+const BIG CURVE_B= {0x367B};
+const BIG CURVE_Gx= {0x1};
+const BIG CURVE_Gy= {0xF2701E5,0x29687ED,0xC84861F,0x535081C,0x3F4E363,0x6A811B,0xCD65474,0x121AD498,0x19F0E6};
+#endif
+
+#if CURVETYPE==MONTGOMERY
+
+const int CURVE_A=-55790;
+const BIG CURVE_Order= {0x46E98C7,0x179E9FF6,0x158BEC3A,0xA60D917,0x1FFFFEB9,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFE03F};
+const BIG CURVE_Gx= {0x3};
+
+#endif
+
+#endif
+
+#if CHUNK==64
+
+const BIG Modulus= {0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0x3F80FFFF};
+const chunk MConst=0x3F810000;
+
+
+#if CURVETYPE==WEIERSTRASS
+const int CURVE_A= -3;
+const BIG CURVE_Order= {0xA419C4AF8DF83F,0x8BEA0DA375C06F,0xFFFFFFFFFFEB81,0xFFFFFFFFFFFFFF,0x3F80FFFF};
+const BIG CURVE_B= {0xFFFFFFFFFFD08D,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0x3F80FFFF};
+const BIG CURVE_Gx= {0x2};
+const BIG CURVE_Gy= {0x65DF37F90D4EBC,0x38E3F8511931AD,0x75BD778AEBDFB7,0x3B2E56014AE15A,0x140E3FD3};
+#endif
+
+#if CURVETYPE==EDWARDS
+const int CURVE_A= -1;
+const BIG CURVE_Order= {0xF3D3FEC46E98C7,0x306C8BD62FB0EA,0xFFFFFFFFFFEB95,0xFFFFFFFFFFFFFF,0xFE03FFF};
+const BIG CURVE_B= {0x367B};
+const BIG CURVE_Gx= {0x1};
+const BIG CURVE_Gy= {0x52D0FDAF2701E5,0x9A840E3212187C,0xD502363F4E3632,0xD6A4C335951D00,0x19F0E690};
+#endif
+
+#if CURVETYPE==MONTGOMERY
+const int CURVE_A=-55790;
+const BIG CURVE_Order= {0xF3D3FEC46E98C7,0x306C8BD62FB0EA,0xFFFFFFFFFFEB95,0xFFFFFFFFFFFFFF,0xFE03FFF};
+const BIG CURVE_Gx= {0x3};
+#endif
+
+#endif
+
+#endif
+
+
+
+
+#if CHOICE==MF256
+
+/* Montgomery-Friendly NUMS curves http://eprint.iacr.org/2014/130 */
+
+#if CHUNK==32
+
+const BIG Modulus= {0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFFA7FF};
+const chunk MConst=0xFFA800;
+
+#if CURVETYPE==WEIERSTRASS
+const int CURVE_A= -3;
+const BIG CURVE_Order= {0x79857EB,0x8862F0D,0x1941D2E7,0x2EA27CD,0x1FFFFFC5,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFFA7FF};
+const BIG CURVE_B= {0x14E6A};
+const BIG CURVE_Gx= {0x1};
+const BIG CURVE_Gy= {0xB724D2A,0x3CAA61,0x5371984,0x128FD71B,0x1AE28956,0x1D13091E,0x339EEAE,0x10F7C301,0x20887C};
+#endif
+
+#if CURVETYPE==EDWARDS
+const int CURVE_A= -1;
+const BIG CURVE_Order= {0x18EC7BAB,0x16C976F6,0x19CCF259,0x9775F70,0x1FFFFB15,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3FE9FF};
+const BIG CURVE_B= {0x350A};
+const BIG CURVE_Gx= {0x1};
+const BIG CURVE_Gy= {0x12F3C908,0xF553917,0x1FA9A35F,0xBCC91B,0x1AACA0C,0x1779ED96,0x156BABAF,0x1F1F1989,0xDAD8D4};
+#endif
+
+#if CURVETYPE==MONTGOMERY
+
+const int CURVE_A=-54314;
+const BIG CURVE_Order= {0x18EC7BAB,0x16C976F6,0x19CCF259,0x9775F70,0x1FFFFB15,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3FE9FF};
+const BIG CURVE_Gx= {0x8};
+
+#endif
+
+#endif
+
+#if CHUNK==64
+
+const BIG Modulus= {0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFA7FFFF};
+const chunk MConst=0xFFA80000;
+
+
+#if CURVETYPE==WEIERSTRASS
+const int CURVE_A= -3;
+const BIG CURVE_Order= {0x10C5E1A79857EB,0x7513E6E5074B9D,0xFFFFFFFFFFFC51,0xFFFFFFFFFFFFFF,0xFFA7FFFF};
+const BIG CURVE_B= {0x14E6A};
+const BIG CURVE_Gx= {0x1};
+const BIG CURVE_Gy= {0x7954C2B724D2A,0x47EB8D94DC6610,0x26123DAE289569,0xBE1808CE7BABBA,0x20887C87};
+#endif
+
+#if CURVETYPE==EDWARDS
+const int CURVE_A= -1;
+const BIG CURVE_Order= {0xD92EDED8EC7BAB,0xBBAFB86733C966,0xFFFFFFFFFFB154,0xFFFFFFFFFFFFFF,0x3FE9FFFF};
+const BIG CURVE_B= {0x350A};
+const BIG CURVE_Gx= {0x1};
+const BIG CURVE_Gy= {0xEAA722F2F3C908,0x5E648DFEA68D7D,0xF3DB2C1AACA0C0,0xF8CC4D5AEAEBEE,0xDAD8D4F8};
+#endif
+
+#if CURVETYPE==MONTGOMERY
+const int CURVE_A=-54314;
+const BIG CURVE_Order= {0xD92EDED8EC7BAB,0xBBAFB86733C966,0xFFFFFFFFFFB154,0xFFFFFFFFFFFFFF,0x3FE9FFFF};
+const BIG CURVE_Gx= {0x8};
+#endif
+
+#endif
+
+#endif
+
+
+
+
+#if CHOICE==MS255
+/* Pseudo-Mersenne NUMS curves http://eprint.iacr.org/2014/130 */
+
+#if CHUNK==16
+const BIG Modulus= {0x1D03,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0xFF};
+const chunk MConst=0x2FD;
+
+#if CURVETYPE==WEIERSTRASS
+const int CURVE_A=-3;
+const BIG CURVE_Order= {0xAEB,0x2CA,0x60F,0x1F59,0x1AB8,0x19EF,0xB4A,0x507,0xA38,0x1C32,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0xFF};
+const BIG CURVE_B= {0xB46,0x1FFD,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0xFF};
+const BIG CURVE_Gx= {0x1};
+const BIG CURVE_Gy= {0x4BA,0xE5A,0x19DA,0x7FE,0x1173,0x1306,0x17F6,0x119B,0x16C7,0x1BED,0x1F45,0x5FE,0x1F9B,0xF5F,0xE48,0xF06,0xDBA,0x1607,0x1E9A,0xDE};
+#endif
+
+#if CURVETYPE==EDWARDS
+const int CURVE_A=-1;
+const BIG CURVE_Order= {0xB75,0x1B7,0x1B41,0x13A3,0xAC4,0x197,0x169A,0x10BD,0x11A7,0x1EE7,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x3F};
+const BIG CURVE_B= {0xA97,0x7};
+const BIG CURVE_Gx= {0x4};
+const BIG CURVE_Gy= {0x16A0,0x439,0x16F4,0x144A,0x1BA2,0xD22,0x1511,0x115D,0x114B,0xA94,0x11F9,0x1C18,0xDD8,0x12A6,0x17B0,0x16A8,0xA7B,0x29A,0x12DE,0x4D};
+#endif
+
+#endif
+
+#if CHUNK==32
+const BIG Modulus= {0x1FFFFD03,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFFF};
+const chunk MConst=0x2FD;
+
+#if CURVETYPE==WEIERSTRASS
+const int CURVE_A=-3;
+const BIG CURVE_Order= {0x1C594AEB,0x1C7D64C1,0x14ACF7EA,0x14705075,0x1FFFF864,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFFF};
+const BIG CURVE_B= {0x1FFFAB46,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFFF};
+const BIG CURVE_Gx= {0x1};
+const BIG CURVE_Gy= {0x9CB44BA,0x199FFB3B,0x1F698345,0xD8F19BB,0x17D177DB,0x1FFCD97F,0xCE487A,0x181DB74F,0x6F7A6A};
+#endif
+
+#if CURVETYPE==EDWARDS
+const int CURVE_A=-1;
+const BIG CURVE_Order= {0x436EB75,0x24E8F68,0x9A0CBAB,0x34F0BDB,0x1FFFFDCF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFF};
+const BIG CURVE_B= {0xEA97};
+const BIG CURVE_Gx= {0x4};
+const BIG CURVE_Gy= {0x108736A0,0x11512ADE,0x1116916E,0x29715DA,0x47E5529,0x66EC706,0x1517B095,0xA694F76,0x26CB78};
+#endif
+
+#if CURVETYPE==MONTGOMERY
+const int CURVE_A=-240222;
+const BIG CURVE_Order= {0x436EB75,0x24E8F68,0x9A0CBAB,0x34F0BDB,0x1FFFFDCF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFF};
+const BIG CURVE_Gx= {0x4};
+#endif
+
+
+#endif
+
+#if CHUNK==64
+const BIG Modulus= {0xFFFFFFFFFFFD03,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0x7FFFFFFF};
+const chunk MConst=0x2FD;
+
+#if CURVETYPE==WEIERSTRASS
+const int CURVE_A=-3;
+const BIG CURVE_Order= {0x8FAC983C594AEB,0x38283AD2B3DFAB,0xFFFFFFFFFF864A,0xFFFFFFFFFFFFFF,0x7FFFFFFF};
+const BIG CURVE_B= {0xFFFFFFFFFFAB46,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0x7FFFFFFF};
+const BIG CURVE_Gx= {0x1};
+const BIG CURVE_Gy= {0x33FF6769CB44BA,0xC78CDDFDA60D17,0xF9B2FF7D177DB6,0xEDBA7833921EBF,0x6F7A6AC0};
+#endif
+
+#if CURVETYPE==EDWARDS
+const int CURVE_A=-1;
+const BIG CURVE_Order= {0x49D1ED0436EB75,0xA785EDA6832EAC,0xFFFFFFFFFFDCF1,0xFFFFFFFFFFFFFF,0x1FFFFFFF};
+const BIG CURVE_B= {0xEA97};
+const BIG CURVE_Gx= {0x4};
+const BIG CURVE_Gy= {0x2A255BD08736A0,0x4B8AED445A45BA,0xDD8E0C47E55291,0x4A7BB545EC254C,0x26CB7853};
+#endif
+
+#if CURVETYPE==MONTGOMERY
+const int CURVE_A=-240222;
+const BIG CURVE_Order= {0x49D1ED0436EB75,0xA785EDA6832EAC,0xFFFFFFFFFFDCF1,0xFFFFFFFFFFFFFF,0x1FFFFFFF};
+const BIG CURVE_Gx= {0x4};
+#endif
+
+#endif
+
+#endif
+
+
+
+#if CHOICE==MS256
+/* Pseudo-Mersenne NUMS curves http://eprint.iacr.org/2014/130 */
+
+#if CHUNK==16
+const BIG Modulus= {0x1F43,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FF};
+const chunk MConst=0xBD;
+
+#if CURVETYPE==WEIERSTRASS
+const int CURVE_A=-3;
+const BIG CURVE_Order= {0x825,0x1A8D,0xA51,0x1640,0x20A,0xE30,0x899,0xEBD,0x1C82,0x1F21,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FF};
+const BIG CURVE_B= {0x1581,0x12};
+const BIG CURVE_Gx= {0x1};
+const BIG CURVE_Gy= {0xC77,0x15AB,0x1B0,0x8C6,0x10BF,0x760,0x1625,0x126E,0xC2F,0x1E81,0x175A,0x1DDD,0x16CC,0x164,0x1FF2,0xCDA,0x1E4,0x29E,0x1BC6,0xD2};
+#endif
+
+#if CURVETYPE==EDWARDS
+const int CURVE_A=-1;
+const BIG CURVE_Order= {0x14AD,0x915,0x1BC4,0x109C,0xE5B,0x1E32,0x29A,0xB5A,0xAA5,0x1DF3,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x7F};
+const BIG CURVE_B= {0x1BEE,0x1};
+const BIG CURVE_Gx= {0xd};
+const BIG CURVE_Gy= {0xDBA,0x18E5,0xD4C,0x1EDF,0x1707,0x181F,0x934,0xC70,0xA6D,0x1DF1,0x11AF,0x1F40,0xB39,0x998,0xE8F,0xEDB,0xA12,0xF1,0x2AD,0xFA};
+#endif
+
+#endif
+
+#if CHUNK==32
+const BIG Modulus= {0x1FFFFF43,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFFFFFF};
+const chunk MConst=0xBD;
+
+#if CURVETYPE==WEIERSTRASS
+const int CURVE_A=-3;
+const BIG CURVE_Order= {0x751A825,0x559014A,0x9971808,0x1904EBD4,0x1FFFFE43,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFFFFFF};
+const BIG CURVE_B= {0x25581};
+const BIG CURVE_Gx= {0x1};
+const BIG CURVE_Gy= {0x2B56C77,0x1FA31836,0x253B042,0x185F26EB,0xDD6BD02,0x4B66777,0x1B5FF20B,0xA783C8C,0x696F18};
+#endif
+
+#if CURVETYPE==EDWARDS
+const int CURVE_A=-1;
+const BIG CURVE_Order= {0x1122B4AD,0xDC27378,0x9AF1939,0x154AB5A1,0x1FFFFBE6,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3FFFFF};
+const BIG CURVE_B= {0x3BEE};
+const BIG CURVE_Gx= {0xd};
+const BIG CURVE_Gy= {0x131CADBA,0x3FB7DA9,0x134C0FDC,0x14DAC704,0x46BFBE2,0x1859CFD0,0x1B6E8F4C,0x3C5424E,0x7D0AB4};
+#endif
+
+#if CURVETYPE==MONTGOMERY
+const int CURVE_A=-61370;
+const BIG CURVE_Order= {0x1122B4AD,0xDC27378,0x9AF1939,0x154AB5A1,0x1FFFFBE6,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3FFFFF};
+const BIG CURVE_Gx= {0xb};
+#endif
+
+
+#endif
+
+#if CHUNK==64
+const BIG Modulus= {0xFFFFFFFFFFFF43,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFF};
+const chunk MConst=0xBD;
+
+#if CURVETYPE==WEIERSTRASS
+const int CURVE_A=-3;
+const BIG CURVE_Order= {0xAB20294751A825,0x8275EA265C6020,0xFFFFFFFFFFE43C,0xFFFFFFFFFFFFFF,0xFFFFFFFF};
+const BIG CURVE_B= {0x25581};
+const BIG CURVE_Gx= {0x1};
+const BIG CURVE_Gy= {0xF46306C2B56C77,0x2F9375894EC10B,0x6CCEEEDD6BD02C,0xC1E466D7FC82C9,0x696F1853};
+#endif
+
+#if CURVETYPE==EDWARDS
+const int CURVE_A=-1;
+const BIG CURVE_Order= {0xB84E6F1122B4AD,0xA55AD0A6BC64E5,0xFFFFFFFFFFBE6A,0xFFFFFFFFFFFFFF,0x3FFFFFFF};
+const BIG CURVE_B= {0x3BEE};
+const BIG CURVE_Gx= {0xd};
+const BIG CURVE_Gy= {0x7F6FB5331CADBA,0x6D63824D303F70,0xB39FA046BFBE2A,0x2A1276DBA3D330,0x7D0AB41E};
+#endif
+
+#if CURVETYPE==MONTGOMERY
+const int CURVE_A=-61370;
+const BIG CURVE_Order= {0xB84E6F1122B4AD,0xA55AD0A6BC64E5,0xFFFFFFFFFFBE6A,0xFFFFFFFFFFFFFF,0x3FFFFFFF};
+const BIG CURVE_Gx= {0xb};
+#endif
+
+#endif
+
+#endif
+
+
+
+
+#if CHOICE==C25519
+
+/* Modulus p = 2^MODBITS-MConst*/
+/* Three Curves for the price of one..*/
+
+#if CHUNK==16
+
+const chunk MConst=19;
+const BIG Modulus= {0x1FED,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0xFF};
+
+#if CURVETYPE==WEIERSTRASS
+/* Curve I generated myself */
+const int CURVE_A=-3;
+const BIG CURVE_B= {0x28};
+const BIG CURVE_Order= {0xCA1,0x1945,0x1865,0x19C8,0x16D1,0x11B9,0xD0E,0x1C96,0x1E0F,0x2EA,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x100};
+const BIG CURVE_Gx= {0x61F,0x6C1,0x1DD,0xEA7,0x4C4,0x124C,0x1BE3,0x1560,0x74E,0x7CD,0x6F4,0x14B,0x13DE,0x133A,0xFB4,0x106,0x15F,0x909,0x18FD,0xCF};
+const BIG CURVE_Gy= {0xF38,0xEF7,0x11F8,0xC65,0x1574,0x10E3,0x4,0x12E7,0xB2B,0xA6,0x17A8,0x1C8B,0x1CD4,0xFA,0x1D79,0xBB2,0x1E68,0x1640,0x1A15,0x6};
+
+#endif
+
+#if CURVETYPE==EDWARDS
+/* Ed25519 Curve */
+const int CURVE_A=-1;
+const BIG CURVE_B= {0x18A3,0x1ACB,0x1284,0x169B,0x175E,0xC55,0x507,0x9A8,0x100A,0x3,0x1A26,0xEF3,0x797,0x3A0,0xE33,0x1FCE,0xB6F,0x771,0xDB,0xA4};
+const BIG CURVE_Order= {0x13ED,0x7AE,0x697,0x4C6,0x581,0xE6B,0xBDE,0x1BD4,0x1EF9,0xA6,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20};
+const BIG CURVE_Gx= {0x151A,0x192E,0x1823,0xC5A,0xC95,0x13D9,0x1496,0xC12,0xCC7,0x349,0x1717,0x1BAD,0x31F,0x1271,0x1B02,0xA7F,0xD6E,0x169E,0x1A4D,0x42};
+const BIG CURVE_Gy= {0x658,0x1333,0x1999,0xCCC,0x666,0x1333,0x1999,0xCCC,0x666,0x1333,0x1999,0xCCC,0x666,0x1333,0x1999,0xCCC,0x666,0x1333,0x1999,0xCC};
+
+#endif
+
+/*
+#if CURVETYPE==MONTGOMERY
+const int CURVE_A=486662;  // Not Working as A too big for 16-bit int
+const BIG CURVE_Order={0x13ED,0x7AE,0x697,0x4C6,0x581,0xE6B,0xBDE,0x1BD4,0x1EF9,0xA6,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20};
+const BIG CURVE_Gx={0x9};
+#endif
+*/
+
+#endif
+
+
+#if CHUNK==32
+
+const chunk MConst=19;
+const BIG Modulus= {0x1FFFFFED,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFFF};
+
+#if CURVETYPE==WEIERSTRASS
+const int CURVE_A=-3;
+const BIG CURVE_B= {0x28};
+const BIG CURVE_Order= {0x1728ACA1,0x8E7230C,0x10E8DCDB,0x1C1FC966,0x5D5,0x0,0x0,0x0,0x800000};
+const BIG CURVE_Gx= {0x14D8261F,0x23A9C3B,0x1E392613,0xE9D560D,0x19BD0F9A,0x1A9EF052,0xCFB499,0x4242BE1,0x67E3F5};
+const BIG CURVE_Gy= {0x1DEEF38,0x1A31963F,0x4871D5,0x16572E70,0x1DEA014C,0x1AE6A722,0x165D7907,0x1903CD0B,0x36856};
+
+#endif
+
+#if CURVETYPE==EDWARDS
+const int CURVE_A=-1;
+const BIG CURVE_B= {0x135978A3,0xF5A6E50,0x10762ADD,0x149A82,0x1E898007,0x3CBBBC,0x19CE331D,0x1DC56DFF,0x52036C};
+const BIG CURVE_Order= {0x1CF5D3ED,0x9318D2,0x1DE73596,0x1DF3BD45,0x14D,0x0,0x0,0x0,0x100000};
+const BIG CURVE_Gx= {0xF25D51A,0xAB16B04,0x969ECB2,0x198EC12A,0xDC5C692,0x1118FEEB,0xFFB0293,0x1A79ADCA,0x216936};
+const BIG CURVE_Gy= {0x6666658,0x13333333,0x19999999,0xCCCCCCC,0x6666666,0x13333333,0x19999999,0xCCCCCCC,0x666666};
+
+#endif
+
+#if CURVETYPE==MONTGOMERY
+
+const int CURVE_A=486662;
+const BIG CURVE_Order= {0x1CF5D3ED,0x9318D2,0x1DE73596,0x1DF3BD45,0x14D,0x0,0x0,0x0,0x100000};
+const BIG CURVE_Gx= {0x9};
+
+#endif
+
+#endif
+
+#if CHUNK==64
+
+const chunk MConst=19;
+const BIG Modulus= {0xFFFFFFFFFFFFED,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0x7FFFFFFF};
+
+#if CURVETYPE==WEIERSTRASS
+const int CURVE_A=-3;
+const BIG CURVE_B= {0x28};
+const BIG CURVE_Order= {0x1CE4619728ACA1,0xFE4B343A3736D,0x5D5E,0x0,0x80000000};
+const BIG CURVE_Gx= {0x47538774D8261F,0x4EAB06F8E4984C,0x3DE0A59BD0F9A7,0x215F0833ED2675,0x67E3F521};
+const BIG CURVE_Gy= {0x4632C7E1DEEF38,0x2B97380121C757,0xCD4E45DEA014CB,0x1E685D975E41F5,0x36856C8};
+
+#endif
+
+#if CURVETYPE==EDWARDS
+const int CURVE_A=-1;
+const BIG CURVE_B= {0xEB4DCA135978A3,0xA4D4141D8AB75,0x797779E8980070,0x2B6FFE738CC740,0x52036CEE};
+const BIG CURVE_Order= {0x12631A5CF5D3ED,0xF9DEA2F79CD658,0x14DE,0x0,0x10000000};
+const BIG CURVE_Gx= {0x562D608F25D51A,0xC7609525A7B2C9,0x31FDD6DC5C692C,0xCD6E53FEC0A4E2,0x216936D3};
+const BIG CURVE_Gy= {0x66666666666658,0x66666666666666,0x66666666666666,0x66666666666666,0x66666666};
+
+#endif
+
+#if CURVETYPE==MONTGOMERY
+
+const int CURVE_A=486662;
+const BIG CURVE_Order= {0x12631A5CF5D3ED,0xF9DEA2F79CD658,0x14DE,0x0,0x10000000};
+const BIG CURVE_Gx= {0x9};
+
+#endif
+
+#endif
+
+#endif
+
+
+#if CHOICE==BRAINPOOL
+
+const int CURVE_A=-3;
+#if CHUNK==16
+
+const BIG Modulus= {0x1377,0x1B72,0x747,0x690,0x201,0x1014,0x1498,0x47A,0x1BF6,0x1371,0x35C,0x1B07,0x909,0x1305,0x10F9,0x1537,0x1EE,0x1EDD,0x1ED5,0x153};
+const chunk MConst=0x9B9;
+const BIG CURVE_Order= {0x16A7,0x1A42,0xA5,0x1C1D,0x1901,0x137B,0x1586,0x1476,0x197A,0xC61,0x35C,0x1B07,0x909,0x1305,0x10F9,0x1537,0x1EE,0x1EDD,0x1ED5,0x153};
+const BIG CURVE_B= {0xB04,0x1749,0x7F,0xB02,0x16AE,0x492,0x1CBD,0x1895,0x13EB,0x1DFC,0x1DAD,0x1A16,0x1733,0x1353,0x13F9,0x9D4,0x10D8,0xE21,0xB18,0xCC};
+const BIG CURVE_Gx= {0x5F4,0x1098,0x158B,0x322,0x179A,0x1E15,0xABE,0x188F,0x142,0xD7D,0x1852,0x14CA,0x1B23,0x1109,0x1DCC,0x1CF6,0x1CF,0x19E6,0x1A3A,0x147};
+const BIG CURVE_Gy= {0x9BE,0x192E,0x1CD6,0x17D1,0x1DA,0x1380,0x740,0x1BC7,0x1CB6,0x134D,0x105F,0xC88,0xE14,0x1D91,0x15FD,0x18AD,0x1439,0x411,0x65B,0x5B};
+#endif
+
+#if CHUNK==32
+
+const BIG Modulus= {0x1F6E5377,0x9A40E8,0x9880A08,0x17EC47AA,0x18D726E3,0x5484EC1,0x6F0F998,0x1B743DD5,0xA9FB57};
+const chunk MConst=0xEFD89B9;
+const BIG CURVE_Order= {0x174856A7,0xF07414,0x1869BDE4,0x12F5476A,0x18D718C3,0x5484EC1,0x6F0F998,0x1B743DD5,0xA9FB57};
+const BIG CURVE_B= {0x1EE92B04,0x172C080F,0xBD2495A,0x7D7895E,0x176B7BF9,0x13B99E85,0x1A93F99A,0x18861B09,0x662C61};
+const BIG CURVE_Gx= {0xE1305F4,0xD0C8AB1,0xBEF0ADE,0x28588F5,0x16149AFA,0x9D91D32,0x1EDDCC88,0x79839FC,0xA3E8EB};
+const BIG CURVE_Gy= {0x1B25C9BE,0xD5F479A,0x1409C007,0x196DBC73,0x417E69B,0x1170A322,0x15B5FDEC,0x10468738,0x2D996C};
+#endif
+
+#if CHUNK==64
+
+const BIG Modulus= {0x13481D1F6E5377,0xF623D526202820,0x909D838D726E3B,0xA1EEA9BC3E660A,0xA9FB57DB};
+const chunk MConst=0xA75590CEFD89B9;
+const BIG CURVE_Order= {0x1E0E82974856A7,0x7AA3B561A6F790,0x909D838D718C39,0xA1EEA9BC3E660A,0xA9FB57DB};
+const BIG CURVE_B= {0xE58101FEE92B04,0xEBC4AF2F49256A,0x733D0B76B7BF93,0x30D84EA4FE66A7,0x662C61C4};
+const BIG CURVE_Gx= {0xA191562E1305F4,0x42C47AAFBC2B79,0xB23A656149AFA1,0xC1CFE7B7732213,0xA3E8EB3C};
+const BIG CURVE_Gy= {0xABE8F35B25C9BE,0xB6DE39D027001D,0xE14644417E69BC,0x3439C56D7F7B22,0x2D996C82};
+#endif
+
+#endif
+
+
+#if CHOICE==ANSSI
+
+const int CURVE_A=-3;
+#if CHUNK==16
+
+const BIG Modulus= {0x1C03,0x374,0x14F6,0x19E6,0x1E8F,0x536,0xF23,0x1795,0x1AD,0x19CB,0x10D6,0x1C84,0x1E8C,0x936,0x1C40,0x1AB1,0xB3A,0x1C60,0x1F45,0x1E3};
+const chunk MConst=0x1155;
+const BIG CURVE_Order= {0x15E1,0x16B2,0x1671,0x1BA8,0x1FF,0x1FCA,0x34A,0x1C28,0x1C67,0x1A9E,0x10D6,0x1C84,0x1E8C,0x936,0x1C40,0x1AB1,0xB3A,0x1C60,0x1F45,0x1E3};
+const BIG CURVE_B= {0x173F,0x1BDD,0x59E,0xBDB,0x307,0x10C0,0x12C6,0x135C,0xC0C,0x1EFF,0x1003,0x1489,0x754,0x55D,0x35,0x1526,0x1428,0x1E52,0xD4F,0x1DC};
+const BIG CURVE_Gx= {0x1CFF,0xC7A,0xB76,0x12F4,0x164C,0x1B80,0x1E62,0x1B95,0x7D2,0xC61,0x8E5,0x13A8,0x1474,0xC1E,0xCC4,0x73D,0x16C1,0x61A,0xCF5,0x16D};
+const BIG CURVE_Gy= {0xCFB,0x31,0x555,0x2B4,0x1831,0x4F0,0x393,0xFD,0x1C3,0x138,0x1BE3,0x7D9,0x1F0F,0x938,0x47E,0x92,0x8B2,0x7BE,0x10B8,0xC2};
+#endif
+
+#if CHUNK==32
+
+const BIG Modulus= {0x186E9C03,0x7E79A9E,0x12329B7A,0x35B7957,0x435B396,0x16F46721,0x163C4049,0x1181675A,0xF1FD17};
+const chunk MConst=0x164E1155;
+const BIG CURVE_Order= {0x6D655E1,0x1FEEA2CE,0x14AFE507,0x18CFC281,0x435B53D,0x16F46721,0x163C4049,0x1181675A,0xF1FD17};
+const BIG CURVE_B= {0x1B7BB73F,0x3AF6CB3,0xC68600C,0x181935C9,0xC00FDFE,0x1D3AA522,0x4C0352A,0x194A8515,0xEE353F};
+const BIG CURVE_Gx= {0x198F5CFF,0x64BD16E,0x62DC059,0xFA5B95F,0x23958C2,0x1EA3A4EA,0x7ACC460,0x186AD827,0xB6B3D4};
+const BIG CURVE_Gy= {0x14062CFB,0x188AD0AA,0x19327860,0x3860FD1,0xEF8C270,0x18F879F6,0x12447E49,0x1EF91640,0x6142E0};
+#endif
+
+#if CHUNK==64
+
+const BIG Modulus= {0xFCF353D86E9C03,0xADBCABC8CA6DE8,0xE8CE42435B3961,0xB3AD58F10126D,0xF1FD178C};
+const chunk MConst=0x97483A164E1155;
+const BIG CURVE_Order= {0xFDD459C6D655E1,0x67E140D2BF941F,0xE8CE42435B53DC,0xB3AD58F10126D,0xF1FD178C};
+const BIG CURVE_B= {0x75ED967B7BB73F,0xC9AE4B1A18030,0x754A44C00FDFEC,0x5428A9300D4ABA,0xEE353FCA};
+const BIG CURVE_Gx= {0xC97A2DD98F5CFF,0xD2DCAF98B70164,0x4749D423958C27,0x56C139EB31183D,0xB6B3D4C3};
+const BIG CURVE_Gy= {0x115A1554062CFB,0xC307E8E4C9E183,0xF0F3ECEF8C2701,0xC8B204911F9271,0x6142E0F7};
+#endif
+
+#endif
+
+
+#if CHOICE==HIFIVE
+
+const int CURVE_A=1;
+#if CHUNK==32
+const BIG Modulus= {0x1FFFFFFD,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFF};
+const chunk MConst=0x3;
+const BIG CURVE_Order= {0x1E9FA805,0x197CACB9,0x1E4EEA9E,0x17AD70F,0x1FA9850C,0x38A0A,0x0,0x0,0x0,0x0,0x0,0x4000};
+const BIG CURVE_B= {0x2B67};
+const BIG CURVE_Gx= {0xC};
+const BIG CURVE_Gy= {0x5FE8632,0x15F63428,0xD976C4,0x1AACA194,0x35B6DB5,0x8E3F7A,0x52D1B0E,0xF0A7A36,0x1C161D00,0x8170C70,0x1185AD59,0x181B};
+#endif
+
+#if CHUNK==64
+const BIG Modulus= {0xFFFFFFFFFFFFFFD,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFF};
+const chunk MConst=0x3;
+const BIG CURVE_Order= {0xB2F95973E9FA805,0xC0BD6B87F93BAA7,0x71415FA9850,0x0,0x0,0x200000000};
+const BIG CURVE_B= {0x2B67};
+const BIG CURVE_Gx= {0xC};
+const BIG CURVE_Gy= {0x2BEC68505FE8632,0x5D5650CA0365DB1,0x3811C7EF435B6DB,0x7853D1B14B46C,0x56502E18E1C161D,0xC0DC616B};
+#endif
+#endif
+
+
+#if CHOICE==GOLDILOCKS
+
+const int CURVE_A=1;
+#if CHUNK==32
+
+const BIG Modulus= {0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FDFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFF};
+const chunk MConst=0x1;
+const BIG CURVE_Order= {0xB5844F3,0x1BC61495,0x1163D548,0x1984E51B,0x3690216,0xDA4D76B,0xFA7113B,0x1FEF9944,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FF};
+const BIG CURVE_B= {0x1FFF6756,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FDFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFF};
+const BIG CURVE_Gx= {0x15555555,0xAAAAAAA,0x15555555,0xAAAAAAA,0x15555555,0xAAAAAAA,0x15555555,0x152AAAAA,0xAAAAAAA,0x15555555,0xAAAAAAA,0x15555555,0xAAAAAAA,0x15555555,0xAAAAAAA,0x1555};
+const BIG CURVE_Gy= {0xA9386ED,0x1757DE6F,0x13681AF6,0x19657DA3,0x3098BBB,0x12C19D15,0x12E03595,0xE515B18,0x17B7E36D,0x1AC426E,0xDBB5E8,0x10D8560,0x159D6205,0xB8246D9,0x17A58D2B,0x15C0};
+#endif
+
+#if CHUNK==64
+
+const BIG Modulus= {0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFEFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFF};
+const chunk MConst=0x1;
+const BIG CURVE_Order= {0x378C292AB5844F3,0x6CC2728DC58F552,0xEDB49AED6369021,0xFFFF7CCA23E9C44,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0x3FFFFFF};
+const BIG CURVE_B= {0xFFFFFFFFFFF6756,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFEFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFF};
+const BIG CURVE_Gx= {0x555555555555555,0x555555555555555,0x555555555555555,0xAAA955555555555,0xAAAAAAAAAAAAAAA,0xAAAAAAAAAAAAAAA,0xAAAAAAAAAAAAAAA,0xAAAAAAA};
+const BIG CURVE_Gy= {0xAEAFBCDEA9386ED,0xBCB2BED1CDA06BD,0x565833A2A3098BB,0x6D728AD8C4B80D6,0x7A035884DD7B7E3,0x205086C2B0036ED,0x34AD7048DB359D6,0xAE05E96};
+#endif
+#endif
+
+#if CHOICE==NIST384
+
+const int CURVE_A=-3;
+#if CHUNK==32
+
+const BIG Modulus= {0xFFFFFFF,0xF,0x0,0xFFFF000,0xFFEFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFF};
+const chunk MConst=0x1;
+const BIG CURVE_Order= {0xCC52973,0xEC196AC,0xA77AEC,0xDB248B,0xDDF581A,0x81F4372,0xFC7634D,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFF};
+const BIG CURVE_B= {0x3EC2AEF,0x85C8EDD,0xED19D2A,0x398D8A2,0x75AC656,0x8F50138,0x2031408,0xFE81411,0x81D9C6E,0xF82D191,0xE056BE3,0xE7E4988,0xFA7E23E,0xB3312};
+const BIG CURVE_Gx= {0x2760AB7,0x545E387,0x5296C3A,0xF25DBF5,0xA385502,0xE082542,0x859F741,0x8BA79B9,0xE1D3B62,0x20AD746,0x1C71EF3,0x5378EB,0xA22BE8B,0xAA87C};
+const BIG CURVE_Gy= {0xEA0E5F,0x431D7C9,0xE819D7A,0xB1CE1D7,0x8C00A60,0x13B5F0B,0xCE9DA31,0x289A147,0x8F41DBD,0x92DC29F,0xE98BF92,0x2C6F5D9,0xE4A9626,0x3617D};
+#endif
+
+#if CHUNK==64
+
+const BIG Modulus= {0xFFFFFFFF,0xFFFF0000000000,0xFFFFFFFFFEFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFF};
+const chunk MConst=0x100000001;
+const BIG CURVE_Order= {0xEC196ACCC52973,0xDB248B0A77AEC,0x81F4372DDF581A,0xFFFFFFFFC7634D,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFF};
+const BIG CURVE_B= {0x85C8EDD3EC2AEF,0x398D8A2ED19D2A,0x8F5013875AC656,0xFE814112031408,0xF82D19181D9C6E,0xE7E4988E056BE3,0xB3312FA7E23E};
+const BIG CURVE_Gx= {0x545E3872760AB7,0xF25DBF55296C3A,0xE082542A385502,0x8BA79B9859F741,0x20AD746E1D3B62,0x5378EB1C71EF3,0xAA87CA22BE8B};
+const BIG CURVE_Gy= {0x431D7C90EA0E5F,0xB1CE1D7E819D7A,0x13B5F0B8C00A60,0x289A147CE9DA31,0x92DC29F8F41DBD,0x2C6F5D9E98BF92,0x3617DE4A9626};
+#endif
+#endif
+
+#if CHOICE==C41417
+
+const int CURVE_A=1;
+#if CHUNK==32
+
+const BIG Modulus= {0x1FFFFFEF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFF};
+const chunk MConst=0x11;
+const BIG CURVE_Order= {0x106AF79,0x18738D2F,0x18F3C606,0x1806715A,0x22B36F1,0xA67B830,0xCF32490,0x1FFFFFFD,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1F};
+const BIG CURVE_B= {0xE21};
+const BIG CURVE_Gx= {0x13CBC595,0x7E9C097,0x14DF1931,0x14E7F550,0x1A111301,0x15A6B6B5,0xD526292,0x18FEAFFE,0x1F44C03E,0x1E6A31B4,0x70C9B97,0x43180C6,0x1443300,0x19A4828A,0x68};
+const BIG CURVE_Gy= {0x22};
+#endif
+
+#if CHUNK==64
+const BIG Modulus= {0xFFFFFFFFFFFFFEF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0x3FFFFFFFFFFFFF};
+const chunk MConst=0x11;
+const BIG CURVE_Order= {0xB0E71A5E106AF79,0x1C0338AD63CF181,0x414CF706022B36F,0xFFFFFFFFEB3CC92,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0x7FFFFFFFFFFFF};
+const BIG CURVE_B= {0xE21};
+const BIG CURVE_Gx= {0x4FD3812F3CBC595,0x1A73FAA8537C64C,0x4AB4D6D6BA11130,0x3EC7F57FF35498A,0xE5FCD46369F44C0,0x300218C0631C326,0x1A334905141443};
+const BIG CURVE_Gy= {0x22};
+#endif
+#endif
+
+
+#if CHOICE==NIST521
+
+const int CURVE_A=-3;
+#if CHUNK==32
+
+const BIG Modulus= {0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0x1FFFF};
+const chunk MConst=0x1;
+const BIG CURVE_Order= {0x1386409,0x6FB71E9,0xC47AEBB,0xC9B8899,0x5D03BB5,0x48F709A,0xB7FCC01,0xBF2F966,0x1868783,0xFFFFFA5,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0x1FFFF};
+const BIG CURVE_B= {0xB503F00,0x451FD46,0xC34F1EF,0xDF883D2,0xF073573,0xBD3BB1B,0xB1652C0,0xEC7E937,0x6193951,0xF109E15,0x489918E,0x15F3B8B,0x25B99B3,0xEEA2DA7,0xB68540,0x929A21A,0xE1C9A1F,0x3EB9618,0x5195};
+const BIG CURVE_Gx= {0x2E5BD66,0x7E7E31C,0xA429BF9,0xB3C1856,0x8DE3348,0x27A2FFA,0x8FE1DC1,0xEFE7592,0x14B5E77,0x4D3DBAA,0x8AF606B,0xB521F82,0x139053F,0x429C648,0x62395B4,0x9E3ECB6,0x404E9CD,0x8E06B70,0xC685};
+const BIG CURVE_Gy= {0xFD16650,0xBE94769,0x2C24088,0x7086A27,0x761353C,0x13FAD0,0xC550B9,0x5EF4264,0x7EE7299,0x3E662C9,0xFBD1727,0x446817A,0x449579B,0xD998F54,0x42C7D1B,0x5C8A5FB,0xA3BC004,0x296A789,0x11839};
+#endif
+
+#if CHUNK==64
+
+const BIG Modulus= {0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0x1FFFFFFFFFF};
+const chunk MConst=0x1;
+const BIG CURVE_Order= {0xB6FB71E91386409,0xB5C9B8899C47AEB,0xC0148F709A5D03B,0x8783BF2F966B7FC,0xFFFFFFFFFFA5186,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0x1FFFFFFFFFF};
+const BIG CURVE_B= {0xF451FD46B503F00,0x73DF883D2C34F1E,0x2C0BD3BB1BF0735,0x3951EC7E937B165,0x9918EF109E15619,0x5B99B315F3B8B48,0xB68540EEA2DA72,0x8E1C9A1F929A21A,0x51953EB961};
+const BIG CURVE_Gx= {0x97E7E31C2E5BD66,0x48B3C1856A429BF,0xDC127A2FFA8DE33,0x5E77EFE75928FE1,0xF606B4D3DBAA14B,0x39053FB521F828A,0x62395B4429C6481,0x404E9CD9E3ECB6,0xC6858E06B7};
+const BIG CURVE_Gy= {0x8BE94769FD16650,0x3C7086A272C2408,0xB9013FAD076135,0x72995EF42640C55,0xD17273E662C97EE,0x49579B446817AFB,0x42C7D1BD998F544,0x9A3BC0045C8A5FB,0x11839296A78};
+#endif
+#endif
+
+#if CHOICE==BN646
+
+const int CURVE_A=0;
+
+#if CHUNK==32
+
+const chunk MConst=0x15F615E5;
+const BIG Modulus= {0x404E013,0x1203604,0x4E0000,0x80A2084,0x2,0xC90420,0x4051078,0x3600001,0xA20660,0x36,0x5100900,0x10288468,0xD,0x2881200,0x1B0,0x0,0x6C0D80,0x48,0x0,0x480,0x0,0x0,0x90};
+const BIG CURVE_Order= {0x1E04200D,0x1203603,0x420000,0x80A207E,0x2,0xC303F0,0x4051075,0x3600001,0xA20630,0x36,0x5100900,0x1028845C,0xD,0x2881200,0x1B0,0x0,0x6C0D80,0x48,0x0,0x480,0x0,0x0,0x90};
+const BIG CURVE_Cof= {0x1};
+const BIG CURVE_B= {0x2};
+const BIG CURVE_Bnx= {0x1001,0x0,0x10000,0x0,0x0,0x8000};
+const BIG CURVE_Cru= {0x401B007,0x901,0x1B0000,0x1B024,0x0,0x288120,0xD812,0x900000,0x1B0120,0x0,0xD80000,0x6C048,0x0,0x6C0000,0x0,0x0,0x120000};
+const BIG CURVE_Fra= {0x4929A14,0x3B756CA,0x4337DD0,0xFC1417C,0x193166BB,0x1DC54515,0x1C0DF653,0x19BF8961,0x155980E,0x1983CB14,0x4D76309,0x1DEAB1A4,0xF9C3CF5,0x128FEC2D,0x867E339,0xDA0548A,0x1A480AF,0xA3CBCD2,0x116DA6E0,0x2A546E9,0x789577C,0x1F9459D2,0x27};
+const BIG CURVE_Frb= {0x1F7245FF,0x1D68DF39,0x1C1A822F,0x1848DF07,0x6CE9946,0x303BF0A,0x7F71A24,0x9A0769F,0x1F4C6E51,0x67C3521,0x38A5F6,0x123DD2C4,0x1063C317,0xFF825D2,0x17981E76,0x125FAB75,0x1EC78CD0,0x15C34375,0xE92591F,0x1D5ABD96,0x1876A883,0x6BA62D,0x68};
+const BIG CURVE_Pxa= {0x1CCC5E10,0x119F939,0xC6C7FE9,0x81022FF,0x6486AA6,0x1CBC560B,0x1F707429,0xC82F7B9,0x1A7F5CDA,0x14C0EB47,0x11412373,0x13DAF21E,0x126BE416,0x166744A7,0x506E81,0x1048FFA3,0x13A6B0C9,0x1A90979A,0xE78C338,0x1722C561,0xBFFF9A1,0xC1AF83C,0x3F};
+const BIG CURVE_Pxb= {0x67F4BC0,0x1BFC3C9,0x1E9DC3B6,0x87E2B03,0xB820274,0x1DD03B1E,0x517C463,0x1EFCBBC9,0x19F786A8,0x5572E90,0xD0BA5E0,0x16E8A40A,0x1013CF3B,0x11A7F82B,0x1C27B302,0x15E7CD12,0xB79A6DF,0x1EC6895B,0x5775A7E,0xBB28D24,0x416A171,0x127D284E,0x5D};
+const BIG CURVE_Pya= {0xC3FB414,0x2B868EE,0xD858793,0x157FCFE,0x16C849AD,0x1D17B0A4,0x1353CFEA,0x940A061,0x1CEF834E,0x7BE766A,0x4584C1C,0xE2397E9,0x418E9D4,0x8F53B8,0x53B37E0,0x11CA29D9,0xE425654,0x9EFF9AF,0x18CF27A1,0x17755A26,0x3F5481A,0x6C531BC,0x1E};
+const BIG CURVE_Pyb= {0x133908AD,0x17F1F1ED,0x14196532,0x19A85214,0x173EC3F7,0x1021EC2C,0xD798A3E,0x18F4C857,0x82EE2FA,0x11B5296D,0x1831D9C6,0x4463DB5,0x11B4812C,0xF93B884,0xC72653,0xEC6F6ED,0x916CFFF,0x1E81ED0A,0x1103518E,0x1E478B01,0x6B01074,0xC46CCAA,0x48};
+const BIG CURVE_Gx= {0x404E012,0x1203604,0x4E0000,0x80A2084,0x2,0xC90420,0x4051078,0x3600001,0xA20660,0x36,0x5100900,0x10288468,0xD,0x2881200,0x1B0,0x0,0x6C0D80,0x48,0x0,0x480,0x0,0x0,0x90};
+const BIG CURVE_Gy= {0x1};
+const BIG CURVE_W[2]= {{0x6008003,0x0,0x80000,0x6,0x0,0x40030,0x3,0x0,0x30,0x0,0x0,0xC},{0x2001,0x0,0x20000,0x0,0x0,0x10000}};
+const BIG CURVE_SB[2][2]= {{{0x600A004,0x0,0xA0000,0x6,0x0,0x50030,0x3,0x0,0x30,0x0,0x0,0xC},{0x2001,0x0,0x20000,0x0,0x0,0x10000}},{{0x2001,0x0,0x20000,0x0,0x0,0x10000},{0x1803A00A,0x1203603,0x3A0000,0x80A2078,0x2,0xBF03C0,0x4051072,0x3600001,0xA20600,0x36,0x5100900,0x10288450,0xD,0x2881200,0x1B0,0x0,0x6C0D80,0x48,0x0,0x480,0x0,0x0,0x90}}};
+const BIG CURVE_WB[4]= {{0x2001000,0x0,0x10000,0x2,0x0,0x8010,0x1,0x0,0x10,0x0,0x0,0x4},{0x1C015005,0x600,0x150000,0x1201C,0x0,0x1C80E0,0x900E,0x600000,0x1200E0,0x0,0x900000,0x48038,0x0,0x480000,0x0,0x0,0xC0000},{0xE00B003,0x300,0xB0000,0x900E,0x0,0xE8070,0x4807,0x300000,0x90070,0x0,0x480000,0x2401C,0x0,0x240000,0x0,0x0,0x60000},{0x2003001,0x0,0x30000,0x2,0x0,0x18010,0x1,0x0,0x10,0x0,0x0,0x4}};
+const BIG CURVE_BB[4][4]= {{{0x1E04100D,0x1203603,0x410000,0x80A207E,0x2,0xC283F0,0x4051075,0x3600001,0xA20630,0x36,0x5100900,0x1028845C,0xD,0x2881200,0x1B0,0x0,0x6C0D80,0x48,0x0,0x480,0x0,0x0,0x90},{0x1E04100C,0x1203603,0x410000,0x80A207E,0x2,0xC283F0,0x4051075,0x3600001,0xA20630,0x36,0x5100900,0x1028845C,0xD,0x2881200,0x1B0,0x0,0x6C0D80,0x48,0x0,0x480,0x0,0x0,0x90},{0x1E04100C,0x1203603,0x410000,0x80A207E,0x2,0xC283F0,0x4051075,0x3600001,0xA20630,0x36,0x5100900,0x1028845C,0xD,0x2881200,0x1B0,0x0,0x6C0D80,0x48,0x0,0x480,0x0,0x0,0x90},{0x2002,0x0,0x20000,0x0,0x0,0x10000}},{{0x2001,0x0,0x20000,0x0,0x0,0x10000},{0x1E04100C,0x1203603,0x410000,0x80A207E,0x2,0xC283F0,0x4051075,0x3600001,0xA20630,0x36,0x5100900,0x1028845C,0xD,0x2881200,0x1B0,0x0,0x6C0D80,0x48,0x0,0x480,0x0,0x0,0x90},{0x1E04100D,0x1203603,0x410000,0x80A207E,0x2,0xC283F0,0x4051075,0x3600001,0xA20630,0x36,0x5100900,0x1028845C,0xD,0x2881200,0x1B0,0x0,0x6C0D80,0x48,0x0,0x480,0x0,0x0,0x90},{0x1E04100C,0x1203603,0x410000,0x80A207E,0x2,0xC283F0,0x4051075,0x3600001,0xA20630,0x36,0x5100900,0x1028845C,0xD,0x2881200,0x1B0,0x0,0x6C0D80,0x48,0x0,0x480,0x0,0x0,0x90}},{{0x2002,0x0,0x20000,0x0,0x0,0x10000},{0x2001,0x0,0x20000,0x0,0x0,0x10000},{0x2001,0x0,0x20000,0x0,0x0,0x10000},{0x2001,0x0,0x20000,0x0,0x0,0x10000}},{{0x1002,0x0,0x10000,0x0,0x0,0x8000},{0x4002,0x0,0x40000,0x0,0x0,0x20000},{0x1E04000A,0x1203603,0x400000,0x80A207E,0x2,0xC203F0,0x4051075,0x3600001,0xA20630,0x36,0x5100900,0x1028845C,0xD,0x2881200,0x1B0,0x0,0x6C0D80,0x48,0x0,0x480,0x0,0x0,0x90},{0x1002,0x0,0x10000,0x0,0x0,0x8000}}};
+#endif
+
+#if CHUNK==64
+
+const chunk MConst=0xCE50F5CF5F615E5;
+const BIG Modulus= {0x2406C08404E013,0x240510420138000,0xE01920840000000,0x601B00000901441,0x400000006C0A206,0xD814423414402,0x6C051024000000,0xD8000000000000,0x9006C,0x240000,0x240000000000};
+const BIG CURVE_Order= {0x2406C07E04200D,0x2405103F0108000,0xD418607E0000000,0x301B00000901441,0x400000006C0A206,0xD814422E14402,0x6C051024000000,0xD8000000000000,0x9006C,0x240000,0x240000000000};
+const BIG CURVE_Cof= {0x1};
+const BIG CURVE_B= {0x2};
+const BIG CURVE_Bnx= {0x1001,0x4000,0x10000000000};
+const BIG CURVE_Cru= {0x1202401B007,0xD812006C000,0x480510240000000,0x200480000000360,0x1B01,0x3602403600,0xD800000000,0x0,0x12};
+const BIG CURVE_Fra= {0x76EAD944929A14,0xB7E0A0BE10CDF74,0x4FB8A8A2B93166B,0xECDFC4B0F037D9,0xC27307962815598,0xCF5EF558D2135D8,0x8CE651FD85AF9C3,0x80AF6D02A45219F,0x69B8147979A41A4,0x9577C152A374C5B,0x9FF28B3A478};
+const BIG CURVE_Frb= {0xFAD1BE73F7245FF,0x6C246F83F06A08B,0x906077E146CE994,0x514D03B4F9FDC68,0x7D8CF86A43F4C6E,0x31791EE96200E29,0x79D9FF04BA5063C,0x8CD092FD5BADE60,0x9647EB8686EBEC7,0x6A883EAD5ECB3A4,0x1A00D74C5B87};
+const BIG CURVE_Pxa= {0x4233F273CCC5E10,0x6408117FB1B1FFA,0xA7978AC166486AA,0xDA6417BDCFDC1D0,0xDCE981D68FA7F5C,0x4169ED790F45048,0xBA06CCE894F26BE,0xB0C98247FD18141,0x30CE35212F353A6,0xFF9A1B9162B0B9E,0xFD835F078BF};
+const BIG CURVE_Pxb= {0x837F879267F4BC0,0x443F1581FA770ED,0x8FBA0763CB82027,0xA8F7E5DE4945F11,0x780AAE5D219F786,0xF3BB745205342E9,0xCC0A34FF057013C,0xA6DFAF3E689709E,0xD69FBD8D12B6B79,0x6A1715D9469215D,0x1764FA509C41};
+const BIG CURVE_Pya= {0xC570D1DCC3FB414,0xD0ABFE7F36161E4,0xABA2F61496C849A,0x4E4A05030CD4F3F,0x70F7CECD5CEF83,0x9D4711CBF491613,0xDF8011EA770418E,0x56548E514EC94EC,0xC9E853DFF35EE42,0x5481ABBAAD13633,0x78D8A63783F};
+const BIG CURVE_Pyb= {0xAFE3E3DB33908AD,0x7CD4290A506594C,0xFA043D85973EC3F,0xFAC7A642BB5E628,0x71A36A52DA82EE2,0x12C2231EDAE0C76,0x994DF2771091B48,0xCFFF7637B76831C,0xD463BD03DA14916,0x1074F23C580C40,0x12188D99546B};
+const BIG CURVE_Gx= {0x2406C08404E012,0x240510420138000,0xE01920840000000,0x601B00000901441,0x400000006C0A206,0xD814423414402,0x6C051024000000,0xD8000000000000,0x9006C,0x240000,0x240000000000};
+const BIG CURVE_Gy= {0x1};
+const BIG CURVE_W[2]= {{0x6008003,0x30020000,0xC0080060000000,0x300000000000000,0x0,0x600000},{0x2001,0x8000,0x20000000000}};
+const BIG CURVE_SB[2][2]= {{{0x600A004,0x30028000,0xC00A0060000000,0x300000000000000,0x0,0x600000},{0x2001,0x8000,0x20000000000}},{{0x2001,0x8000,0x20000000000},{0x2406C07803A00A,0x2405103C00E8000,0xC817E0780000000,0x1B00000901441,0x400000006C0A206,0xD814422814402,0x6C051024000000,0xD8000000000000,0x9006C,0x240000,0x240000000000}}};
+const BIG CURVE_WB[4]= {{0x2001000,0x10004000,0x40010020000000,0x100000000000000,0x0,0x200000},{0xC01C015005,0x900E0054000,0x3803901C0000000,0xE00300000000240,0x1200,0x2401C02400,0x9000000000,0x0,0xC},{0x600E00B003,0x4807002C000,0x1C01D00E0000000,0x700180000000120,0x900,0x1200E01200,0x4800000000,0x0,0x6},{0x2003001,0x1000C000,0x40030020000000,0x100000000000000,0x0,0x200000}};
+const BIG CURVE_BB[4][4]= {{{0x2406C07E04100D,0x2405103F0104000,0xD418507E0000000,0x301B00000901441,0x400000006C0A206,0xD814422E14402,0x6C051024000000,0xD8000000000000,0x9006C,0x240000,0x240000000000},{0x2406C07E04100C,0x2405103F0104000,0xD418507E0000000,0x301B00000901441,0x400000006C0A206,0xD814422E14402,0x6C051024000000,0xD8000000000000,0x9006C,0x240000,0x240000000000},{0x2406C07E04100C,0x2405103F0104000,0xD418507E0000000,0x301B00000901441,0x400000006C0A206,0xD814422E14402,0x6C051024000000,0xD8000000000000,0x9006C,0x240000,0x240000000000},{0x2002,0x8000,0x20000000000}},{{0x2001,0x8000,0x20000000000},{0x2406C07E04100C,0x2405103F0104000,0xD418507E0000000,0x301B00000901441,0x400000006C0A206,0xD814422E14402,0x6C051024000000,0xD8000000000000,0x9006C,0x240000,0x240000000000},{0x2406C07E04100D,0x2405103F0104000,0xD418507E0000000,0x301B00000901441,0x400000006C0A206,0xD814422E14402,0x6C051024000000,0xD8000000000000,0x9006C,0x240000,0x240000000000},{0x2406C07E04100C,0x2405103F0104000,0xD418507E0000000,0x301B00000901441,0x400000006C0A206,0xD814422E14402,0x6C051024000000,0xD8000000000000,0x9006C,0x240000,0x240000000000}},{{0x2002,0x8000,0x20000000000},{0x2001,0x8000,0x20000000000},{0x2001,0x8000,0x20000000000},{0x2001,0x8000,0x20000000000}},{{0x1002,0x4000,0x10000000000},{0x4002,0x10000,0x40000000000},{0x2406C07E04000A,0x2405103F0100000,0xD418407E0000000,0x301B00000901441,0x400000006C0A206,0xD814422E14402,0x6C051024000000,0xD8000000000000,0x9006C,0x240000,0x240000000000},{0x1002,0x4000,0x10000000000}}};
+#endif
+
+#endif
+
+#if CHOICE==BN454
+
+const int CURVE_A=0;
+
+#if CHUNK==32
+
+const chunk MConst=0x179435E5;
+const BIG Modulus= {0x13,0x270,0x2100,0x1C00D89C,0x25084,0xA284,0x24720,0x10803AA1,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000};
+const BIG CURVE_Order= {0xD,0x210,0x1F80,0x400D884,0x24FC4,0xA27E,0x10024708,0xFC03A9F,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000};
+const BIG CURVE_Cof= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_B= {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Gx= {0x12,0x270,0x2100,0x1C00D89C,0x25084,0xA284,0x24720,0x10803AA1,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000};
+const BIG CURVE_Gy= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+
+const BIG CURVE_Bnx= {0x1,0x8,0x0,0x2000002,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Cru= {0x7,0xD8,0x900,0x16002436,0x481,0x1B24,0x168,0x48006C9,0x1600006C,0x10000091,0xD80000D,0x240000,0x0,0x0,0x0,0x0};
+const BIG CURVE_Fra= {0x1573B0EC,0x1816E4FE,0xA42E6E0,0x15DDCD87,0x2B17EC7,0x35B9A50,0x15AA1F74,0x1B7B2AC5,0x1CB5A200,0x9937657,0x17389A4A,0x738BADB,0xD92B321,0x3F5F0E6,0x1B1C9E9A,0x25CF3};
+const BIG CURVE_Frb= {0xA8C4F27,0x7E91D71,0x15BD3A1F,0x6230B14,0x1D50D1BD,0x1CA50833,0xA5827AB,0x15050FDB,0x74B3887,0x166C9A92,0x19C78A3C,0x199F4886,0x1B6D4F39,0x80A0F61,0x7236169,0x2230C};
+const BIG CURVE_Pxa= {0xF02B14,0x1DD1DD61,0x330AEC7,0x178617DE,0x1CEFFF36,0x116D35AF,0x1F879FBF,0x105DBF83,0x8345436,0x13664BCA,0x12EE86B5,0x776BB31,0x14AAFE16,0x41B3478,0x13E03554,0x2807A};
+const BIG CURVE_Pxb= {0x45BF266,0xE036876,0x8F0DBA,0xCB5976F,0x10DBC523,0x1723123C,0xBDDA7F4,0x10077CDE,0x11971DE0,0x14F1554A,0x195995EE,0x82E6FD7,0x40D5258,0x1400A58F,0x15A7850B,0x2B2A5};
+const BIG CURVE_Pya= {0x1E1B15C7,0x9CD5B5D,0x1571B2D2,0x1E4C048A,0x1474FB5D,0x18E2328C,0x11775519,0x144EF51F,0xF2FAABA,0x438F741,0x1930EAC0,0x144DC38,0x1287A0FE,0x36D8962,0x10011EAF,0x3ACF4};
+const BIG CURVE_Pyb= {0x571D60,0x8737DB,0xC4A363B,0x124E308F,0x13A65C7E,0x1387693A,0x10CDDA2F,0x184C096E,0x385175,0x5A34088,0xF17A93C,0x1E194915,0x1903ED91,0x4D6FA9F,0x8D8210B,0x12EDC};
+const BIG CURVE_W[2]= {{0x3,0x40,0x180,0x10000010,0xC0,0x6,0x10000018,0xC00001,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+const BIG CURVE_SB[2][2]= {{{0x4,0x50,0x180,0x14000014,0xC0,0x6,0x10000018,0xC00001,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x1,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xA,0x1D0,0x1E00,0x1400D874,0x24F03,0xA278,0x246F0,0xF003A9E,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000}}};
+const BIG CURVE_WB[4]= {{0x0,0x8,0x80,0x2000002,0x40,0x2,0x10000008,0x400000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x5,0xA8,0x700,0xA00182A,0x381,0x121C,0x100,0x3800487,0x4000048,0x61,0x9000009,0x180000,0x0,0x0,0x0,0x0},{0x3,0x58,0x380,0x16000C16,0x1C0,0x90E,0x10000080,0x1C00243,0x12000024,0x10000030,0x4800004,0xC0000,0x0,0x0,0x0,0x0},{0x1,0x18,0x80,0x6000006,0x40,0x2,0x10000008,0x400000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+const BIG CURVE_BB[4][4]= {{{0xD,0x208,0x1F80,0x200D882,0x24FC4,0xA27E,0x10024708,0xFC03A9F,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000},{0xC,0x208,0x1F80,0x200D882,0x24FC4,0xA27E,0x10024708,0xFC03A9F,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000},{0xC,0x208,0x1F80,0x200D882,0x24FC4,0xA27E,0x10024708,0xFC03A9F,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000},{0x2,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x1,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xC,0x208,0x1F80,0x200D882,0x24FC4,0xA27E,0x10024708,0xFC03A9F,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000},{0xD,0x208,0x1F80,0x200D882,0x24FC4,0xA27E,0x10024708,0xFC03A9F,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000},{0xC,0x208,0x1F80,0x200D882,0x24FC4,0xA27E,0x10024708,0xFC03A9F,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000}},{{0x2,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x2,0x8,0x0,0x2000002,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x2,0x20,0x0,0x8000008,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xA,0x200,0x1F80,0xD880,0x24FC4,0xA27E,0x10024708,0xFC03A9F,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000},{0x2,0x8,0x0,0x2000002,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+
+#endif
+
+#if CHUNK==64
+
+const chunk MConst=0xF33C46ED79435E5L;
+const BIG Modulus= {0x4E00000013L,0x4E006C4E0000840L,0x800014508002508L,0x888401D5080091CL,0x21C00021D4400DAL,0x25B06C01B144009L,0xD80000909000L,0x240000900L};
+const BIG CURVE_Order= {0x420000000DL,0x42006C4200007E0L,0x2000144FC0024FCL,0x887E01D4FC0091CL,0x21C00021D4400DAL,0x25B06C01B144009L,0xD80000909000L,0x240000900L};
+const BIG CURVE_Cof= {0x1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG CURVE_B= {0x2L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG CURVE_Gx= {0x4E00000012L,0x4E006C4E0000840L,0x800014508002508L,0x888401D5080091CL,0x21C00021D4400DAL,0x25B06C01B144009L,0xD80000909000L,0x240000900L};
+const BIG CURVE_Gy= {0x1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+
+const BIG CURVE_Bnx= {0x100000001L,0x10000010000000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG CURVE_Cru= {0x1B00000007L,0x1B00121B0000240L,0xA00003648000048L,0x6C2400364800005L,0x36000012360000L,0x12000036000L,0x0L,0x0L};
+const BIG CURVE_Fra= {0x302DC9FD573B0ECL,0x7AEEE6C3A90B9B8L,0xD06B734A02B17ECL,0xDBD9562D6A87DL,0x929326ECAFCB5A2L,0x32139C5D6DDCE26L,0x7A687EBE1CCD92BL,0x12E79EC72L};
+const BIG CURVE_Frb= {0xCFD23AE2A8C4F27L,0xD311858A56F4E87L,0xAF94A1067D50D1BL,0x87A8287EDA9609EL,0x8F2CD9352474B38L,0xF39CCFA443671E2L,0x85A50141EC3B6D4L,0x111861C8DL};
+const BIG CURVE_Pxa= {0xFBA3BAC20F02B14L,0x6BC30BEF0CC2BB1L,0xFE2DA6B5FCEFFF3L,0x3682EDFC1FE1E7EL,0xAD66CC979483454L,0xE163BB5D98CBBA1L,0xD55083668F14AAFL,0x1403D4F80L};
+const BIG CURVE_Pxb= {0x9C06D0EC45BF266L,0x365ACBB7823C36EL,0xD2E4624790DBC52L,0xE0803BE6F2F769FL,0x7BA9E2AA951971DL,0x25841737EBE5665L,0x142E8014B1E40D5L,0x15952D69EL};
+const BIG CURVE_Pya= {0x939AB6BBE1B15C7L,0xDF26024555C6CB4L,0x671C46519474FB5L,0xBAA277A8FC5DD54L,0xB00871EE82F2FAAL,0xFE0A26E1C64C3AL,0x7ABC6DB12C5287AL,0x1D67A4004L};
+const BIG CURVE_Pyb= {0xC10E6FB60571D60L,0xE9271847B128D8EL,0xBE70ED2753A65C7L,0x75C2604B7433768L,0x4F0B46811003851L,0xD91F0CA48ABC5EAL,0x842C9ADF53F903EL,0x976E2360L};
+const BIG CURVE_W[2]= {{0x800000003L,0x80000080000060L,0x60000000C00000CL,0x600000C00000L,0x0L,0x0L,0x0L,0x0L},{0x200000001L,0x20000020000000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}};
+const BIG CURVE_SB[2][2]= {{{0xA00000004L,0xA00000A0000060L,0x60000000C00000CL,0x600000C00000L,0x0L,0x0L,0x0L,0x0L},{0x200000001L,0x20000020000000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x200000001L,0x20000020000000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x3A0000000AL,0x3A006C3A0000780L,0xC000144F00024F0L,0x887801D4F00091BL,0x21C00021D4400DAL,0x25B06C01B144009L,0xD80000909000L,0x240000900L}}};
+const BIG CURVE_WB[4]= {{0x100000000L,0x10000010000020L,0x200000004000004L,0x200000400000L,0x0L,0x0L,0x0L,0x0L},{0x1500000005L,0x15000C1500001C0L,0x2438000038L,0x481C00243800004L,0x2400000C240000L,0xC000024000L,0x0L,0x0L},{0xB00000003L,0xB00060B00000E0L,0x121C00001CL,0x240E00121C00002L,0x12000006120000L,0x6000012000L,0x0L,0x0L},{0x300000001L,0x30000030000020L,0x200000004000004L,0x200000400000L,0x0L,0x0L,0x0L,0x0L}};
+const BIG CURVE_BB[4][4]= {{{0x410000000DL,0x41006C4100007E0L,0x2000144FC0024FCL,0x887E01D4FC0091CL,0x21C00021D4400DAL,0x25B06C01B144009L,0xD80000909000L,0x240000900L},{0x410000000CL,0x41006C4100007E0L,0x2000144FC0024FCL,0x887E01D4FC0091CL,0x21C00021D4400DAL,0x25B06C01B144009L,0xD80000909000L,0x240000900L},{0x410000000CL,0x41006C4100007E0L,0x2000144FC0024FCL,0x887E01D4FC0091CL,0x21C00021D4400DAL,0x25B06C01B144009L,0xD80000909000L,0x240000900L},{0x200000002L,0x20000020000000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x200000001L,0x20000020000000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x410000000CL,0x41006C4100007E0L,0x2000144FC0024FCL,0x887E01D4FC0091CL,0x21C00021D4400DAL,0x25B06C01B144009L,0xD80000909000L,0x240000900L},{0x410000000DL,0x41006C4100007E0L,0x2000144FC0024FCL,0x887E01D4FC0091CL,0x21C00021D4400DAL,0x25B06C01B144009L,0xD80000909000L,0x240000900L},{0x410000000CL,0x41006C4100007E0L,0x2000144FC0024FCL,0x887E01D4FC0091CL,0x21C00021D4400DAL,0x25B06C01B144009L,0xD80000909000L,0x240000900L}},{{0x200000002L,0x20000020000000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x200000001L,0x20000020000000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x200000001L,0x20000020000000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x200000001L,0x20000020000000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x100000002L,0x10000010000000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x400000002L,0x40000040000000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x400000000AL,0x40006C4000007E0L,0x2000144FC0024FCL,0x887E01D4FC0091CL,0x21C00021D4400DAL,0x25B06C01B144009L,0xD80000909000L,0x240000900L},{0x100000002L,0x10000010000000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}}};
+
+
+#endif
+
+#endif
+
+
+#if CHOICE==BLS455
+
+const int CURVE_A=0;
+
+#if CHUNK==32
+
+const chunk MConst=0x1F4017FD;
+const BIG Modulus= {0x2AB,0x1500000C,0xAAA55AA,0xB12AAD6,0x6D1BA6C,0xCCA5674,0x12E2CF6E,0xA9F9662,0x34BD939,0x12D8EAB1,0xFD9978E,0x9240600,0xE0F95B,0xAAB9550,0x55555E5,0xAAAAB};
+const BIG CURVE_Order= {0x1FC00001,0x3FFF,0x10000070,0x1400000,0x1D100,0xF0003A8,0x13C0009,0x1E200,0x180002E0,0x400001,0x4000,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Cof= {0xABFFAAB,0x14AABFFD,0xD52AADA,0x1562AAAB,0x15556AAA,0x2A,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_B= {0xA,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Gx= {0x1DFCEDD1,0x16A62EEF,0xE80D3ED,0xB8DE876,0x179C7253,0x182DAB52,0x46CC85F,0x1E571D9C,0x1E8392B1,0x1A155867,0x19E6527C,0x23DC64E,0xABEDA59,0xF20662B,0x17CECC01,0x310A};
+const BIG CURVE_Gy= {0x6619B9B,0x27EBCD,0x1BE80A19,0x13B014BA,0x191A4936,0x13911916,0x107A5A3B,0x1DCB0863,0x1F5FB1,0xDE44A9C,0x18E23B2A,0x1FA81FD3,0xB0D6DFA,0xC2FE1EF,0xDDFA7E2,0x3351B};
+
+const BIG CURVE_Bnx= {0x800,0x1000004,0x40000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Cru= {0xAA9,0x9017FE0,0x128DD8AA,0x1F4A321E,0x148FEC90,0x195CDEEA,0xE961AA2,0x168D3B66,0xAFD99D7,0xB989AA6,0x1F9A5724,0x91A05FF,0xE0EF5B,0xAAB9548,0x55555E5,0xAAAAB};
+const BIG CURVE_Fra= {0xA2EBF21,0x4E67DEE,0xCDE6590,0xE5EA94E,0x15454985,0x140CFC43,0x7E14D1C,0x1778395A,0x1944F022,0x166BEA1A,0xC3DEEA0,0x9F031A0,0x16A7459,0x1F1D6E00,0x125CFB72,0x72FD4};
+const BIG CURVE_Frb= {0x15D1438A,0x1019821D,0x1DCBF01A,0x1CB40187,0x118C70E6,0x18BD5A30,0xB018251,0x13275D08,0xA06E916,0x1C6D0096,0x39BA8ED,0x1F33D460,0x1F768501,0xB8E274F,0x12F85A72,0x37AD6};
+const BIG CURVE_Pxa= {0x10C1F542,0x23AF907,0x159F840,0xBAC0E1F,0x133D7766,0x1C034C5D,0x14C5C875,0x1ED0BDA2,0x16A49C71,0x1E9FF62D,0x14F3ACC0,0x1E0C9FEA,0xC4638DE,0x74D18DA,0xBEA0030,0x5D962};
+const BIG CURVE_Pxb= {0x749F03D,0xC843773,0xB17BCBA,0x1134AB4B,0x8EA016E,0x1A0D766C,0x58F819E,0x48A1FCC,0xE296F62,0x83370E4,0xC9BA1D5,0x1E43290E,0xEE59A80,0x1FDD85F5,0x1F3819B6,0x1D9F};
+const BIG CURVE_Pya= {0x181A77F4,0x191AD22,0x1E9F842A,0x1E1E6CF6,0xD55B9D9,0x1D062533,0x15BB1323,0x7ECBC1,0x1A9EC2EF,0x1EE14CE0,0x1E96B271,0xA794439,0x1C544324,0xE6AD5DC,0x16429B0F,0x448E3};
+const BIG CURVE_Pyb= {0x1E1FDBA2,0x1A09DB6C,0xF680D5B,0xFCC6122,0xC488E2A,0x1E489ECD,0x1005617E,0x1CF9EC36,0x1C89ED72,0x16C00D90,0x1563E595,0x1243DDC0,0x8698F9E,0x1BD81E7E,0xF2A0F4A,0x66A0};
+
+#endif
+
+#if CHUNK==64
+
+const chunk MConst=0xB3EF8137F4017FDL;
+const BIG Modulus= {0xAA00001800002ABL,0xC589556B2AA956AL,0xB9994ACE86D1BA6L,0x3954FCB314B8B3DL,0xE3A5B1D56234BD9L,0x95B49203003F665L,0x57955572AA00E0FL,0x555559555L};
+const BIG CURVE_Order= {0x7FFFFC00001L,0xA00000400001CL,0x25E000750001D10L,0xE0000F10004F000L,0x80000380002L,0x10L,0x0L,0x0L};
+const BIG CURVE_Cof= {0xA9557FFAABFFAABL,0xAAB15555B54AAB6L,0x555556AAL,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG CURVE_B= {0xAL,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG CURVE_Gx= {0x6D4C5DDFDFCEDD1L,0x35C6F43B3A034FBL,0x7F05B56A579C725L,0xB1F2B8ECE11B321L,0x9F342AB0CFE8392L,0xA5911EE32767994L,0x3005E40CC56ABEDL,0x18855F3BL};
+const BIG CURVE_Gy= {0x404FD79A6619B9BL,0x69D80A5D6FA0286L,0xEE722322D91A493L,0xB1EE58431C1E968L,0xCA9BC8953801F5FL,0xDFAFD40FE9E388EL,0x9F8985FC3DEB0D6L,0x19A8DB77EL};
+
+const BIG CURVE_Bnx= {0x20000080000800L,0x10000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG CURVE_Cru= {0x9202FFC00000AA9L,0xFA5190F4A3762AL,0x8B2B9BDD548FEC9L,0xD7B469DB33A586AL,0xC91731354CAFD99L,0xF5B48D02FFFE695L,0x57955572A900E0EL,0x555559555L};
+const BIG CURVE_Fra= {0x9CCFBDCA2EBF21L,0x572F54A73379964L,0x72819F887545498L,0x22BBC1CAD1F8534L,0xA82CD7D435944F0L,0x4594F818D030F7BL,0xEDCBE3ADC0016A7L,0x397EA4973L};
+const BIG CURVE_Frb= {0xA033043B5D1438AL,0x6E5A00C3F72FC06L,0x4717AB46118C70EL,0x16993AE842C0609L,0x3B78DA012CA06E9L,0x501F99EA300E6EAL,0x69C971C4E9FF768L,0x1BD6B4BE1L};
+const BIG CURVE_Pxa= {0x475F20F0C1F542L,0x65D6070F8567E10L,0xD780698BB33D776L,0x71F685ED1531721L,0x303D3FEC5B6A49CL,0x8DEF064FF553CEBL,0xC0E9A31B4C463L,0x2ECB12FA8L};
+const BIG CURVE_Pxb= {0x99086EE6749F03DL,0xE89A55A5AC5EF2EL,0x7B41AECD88EA016L,0x622450FE6163E06L,0x755066E1C8E296FL,0xA80F219487326E8L,0x66DBFBB0BEAEE59L,0xECFFCE0L};
+const BIG CURVE_Pya= {0x83235A4581A77F4L,0x9F0F367B7A7E10AL,0x8FA0C4A66D55B9DL,0xEF03F65E0D6EC4CL,0x9C7DC299C1A9EC2L,0x32453CA21CFA5ACL,0x6C3DCD5ABB9C544L,0x22471D90AL};
+const BIG CURVE_Pyb= {0xF413B6D9E1FDBA2L,0xA7E630913DA0356L,0xFBC913D9AC488E2L,0x72E7CF61B401585L,0x656D801B21C89EDL,0xF9E921EEE0558F9L,0x3D2B7B03CFC8698L,0x33503CA8L};
+
+#endif
+
+
+#endif
+
+
+#if CHOICE==BLS383
+
+const int CURVE_A=0;
+
+#if CHUNK==32
+
+const chunk MConst=0x123D0BD;
+const BIG Modulus= {0xAAD556B,0xACAAB52,0x5F75D7A,0x1BB0147,0xD5D7520,0xCF73083,0xF99EB16,0x531820,0xA68EA32,0x2C01355,0x552A785,0x5C6105C,0x80A9F7,0x7AC52};
+const BIG CURVE_Order= {0xFFF001,0xFFF8000,0xFE7800,0xBFDE007,0xC5EDF1C,0x3000049,0x910007A,0xC40007F,0x641004C,0x14,0x0,0x0,0x0,0x0};
+const BIG CURVE_Cof= {0x52B,0x2A00,0xAAB2CA0,0x5560AAA,0x6055,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_B= {0x9,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Gx= {0xD10786B,0xD59B348,0x3F54AD0,0x3477C0E,0x4578B9B,0xBF25B73,0x7BB6F65,0x4F6AC00,0xFF57E9C,0xEFD5830,0xFB6EC02,0xADB9F88,0xEE4BC98,0xB08C};
+const BIG CURVE_Gy= {0xD145DDB,0x5DA023,0x5FEF7CC,0x13F518C,0x2B2A66F,0x56EC346,0xC7A925F,0x96F3019,0x981223E,0x9061047,0x8F5BE59,0x4810AD,0x9337671,0x1F390};
+
+const BIG CURVE_Bnx= {0x40,0x100,0x110,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Cru= {0xDA155A9,0xA3AAC4E,0x61E5E3D,0xDF2FE87,0xE632625,0xBCDFAAD,0xD3035A6,0x5123128,0xBEAD683,0xDBF3A2B,0x424190,0x5C5FAB2,0x80A9F7,0x7AC52};
+const BIG CURVE_Fra= {0x2B4508B,0x2BA59A9,0x6EEF343,0x63DB7A0,0x1DFBC74,0x40341CB,0x32D55D3,0x1639E9D,0x5CC36D4,0xB19B3F0,0xD86AB98,0xF323EE4,0xB198672,0x5A5F};
+const BIG CURVE_Frb= {0x7F904E0,0x81051A9,0xF086A37,0xB7D49A6,0xB7DB8AB,0x8F3EEB8,0xC6C9543,0xEEF7983,0x49CB35D,0x7A65F65,0x7CBFBEC,0x693D177,0x5672384,0x751F2};
+const BIG CURVE_Pxa= {0xBAC9472,0x6059885,0xE2DC36D,0x7C4D31D,0x8C88A7,0xBDC90C3,0x1C688FC,0x29F0197,0xC43F167,0x3693539,0x61EB8BF,0xD81E5A5,0x22B56BF,0x4D507};
+const BIG CURVE_Pxb= {0x272AB23,0x9B4BD7A,0xF44DCE8,0x7AF19D4,0x3206A34,0x3F6F7B9,0x2A819FB,0x571DD3E,0x635D7EE,0x3A2BA3B,0xC1A126,0xAC28C78,0x17C3E5B,0xEE36};
+const BIG CURVE_Pya= {0x77BD4FD,0x81D2309,0xDFDFC6,0xB66072,0xC89A0C,0x41FC959,0x878287A,0x2E1FBCF,0x14EEE65,0x11C230,0x6BB325E,0x2887881,0x859A05C,0x8F40};
+const BIG CURVE_Pyb= {0x52C4CE6,0xA5E20A2,0xAFF40C8,0x5907A74,0x2448EF3,0x41760A4,0xFDA199,0xFFEF82B,0x8D4EA49,0xA0F29A1,0x6E4997B,0xAC7F7B8,0xBA88C12,0x1DCAB};
+
+#endif
+
+#if CHUNK==64
+
+const chunk MConst=0xA59AB3B123D0BDL;
+const BIG Modulus= {0xACAAB52AAD556BL,0x1BB01475F75D7AL,0xCF73083D5D7520L,0x531820F99EB16L,0x2C01355A68EA32L,0x5C6105C552A785L,0x7AC52080A9F7L};
+const BIG CURVE_Order= {0xFFF80000FFF001L,0xBFDE0070FE7800L,0x3000049C5EDF1CL,0xC40007F910007AL,0x14641004CL,0x0L,0x0L};
+const BIG CURVE_Cof= {0x2A00000052BL,0x5560AAAAAB2CA0L,0x6055L,0x0L,0x0L,0x0L,0x0L};
+const BIG CURVE_B= {0x9L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG CURVE_Gx= {0xD59B348D10786BL,0x3477C0E3F54AD0L,0xBF25B734578B9BL,0x4F6AC007BB6F65L,0xEFD5830FF57E9CL,0xADB9F88FB6EC02L,0xB08CEE4BC98L};
+const BIG CURVE_Gy= {0x5DA023D145DDBL,0x13F518C5FEF7CCL,0x56EC3462B2A66FL,0x96F3019C7A925FL,0x9061047981223EL,0x4810AD8F5BE59L,0x1F3909337671L};
+
+const BIG CURVE_Bnx= {0x1000000040L,0x110L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG CURVE_Cru= {0xA3AAC4EDA155A9L,0xDF2FE8761E5E3DL,0xBCDFAADE632625L,0x5123128D3035A6L,0xDBF3A2BBEAD683L,0x5C5FAB20424190L,0x7AC52080A9F7L};
+const BIG CURVE_Fra= {0x2BA59A92B4508BL,0x63DB7A06EEF343L,0x40341CB1DFBC74L,0x1639E9D32D55D3L,0xB19B3F05CC36D4L,0xF323EE4D86AB98L,0x5A5FB198672L};
+const BIG CURVE_Frb= {0x81051A97F904E0L,0xB7D49A6F086A37L,0x8F3EEB8B7DB8ABL,0xEEF7983C6C9543L,0x7A65F6549CB35DL,0x693D1777CBFBECL,0x751F25672384L};
+const BIG CURVE_Pxa= {0x6059885BAC9472L,0x7C4D31DE2DC36DL,0xBDC90C308C88A7L,0x29F01971C688FCL,0x3693539C43F167L,0xD81E5A561EB8BFL,0x4D50722B56BFL};
+const BIG CURVE_Pxb= {0x9B4BD7A272AB23L,0x7AF19D4F44DCE8L,0x3F6F7B93206A34L,0x571DD3E2A819FBL,0x3A2BA3B635D7EEL,0xAC28C780C1A126L,0xEE3617C3E5BL};
+const BIG CURVE_Pya= {0x81D230977BD4FDL,0xB660720DFDFC6L,0x41FC9590C89A0CL,0x2E1FBCF878287AL,0x11C23014EEE65L,0x28878816BB325EL,0x8F40859A05CL};
+const BIG CURVE_Pyb= {0xA5E20A252C4CE6L,0x5907A74AFF40C8L,0x41760A42448EF3L,0xFFEF82B0FDA199L,0xA0F29A18D4EA49L,0xAC7F7B86E4997BL,0x1DCABBA88C12L};
+
+#endif
+
+
+#endif
diff --git a/version22/c/rsa.c b/version22/c/rsa.c
new file mode 100644
index 0000000..d5898bd
--- /dev/null
+++ b/version22/c/rsa.c
@@ -0,0 +1,394 @@
+/*
+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.
+*/
+
+/* RSA Functions - see main program below */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "rsa.h"
+
+#define ROUNDUP(a,b) ((a)-1)/(b)+1
+
+/* general purpose hash function w=hash(p|n|x|y) */
+static int hashit(int sha,octet *p,int n,octet *w)
+{
+    int i,c[4],hlen;
+    hash256 sha256;
+    hash512 sha512;
+    char hh[64];
+
+    switch (sha)
+    {
+    case SHA256:
+        HASH256_init(&sha256);
+        break;
+    case SHA384:
+        HASH384_init(&sha512);
+        break;
+    case SHA512:
+        HASH512_init(&sha512);
+        break;
+    }
+
+    hlen=sha;
+
+    if (p!=NULL) for (i=0; i<p->len; i++)
+        {
+            switch(sha)
+            {
+            case SHA256:
+                HASH256_process(&sha256,p->val[i]);
+                break;
+            case SHA384:
+                HASH384_process(&sha512,p->val[i]);
+                break;
+            case SHA512:
+                HASH512_process(&sha512,p->val[i]);
+                break;
+            }
+        }
+    if (n>=0)
+    {
+        c[0]=(n>>24)&0xff;
+        c[1]=(n>>16)&0xff;
+        c[2]=(n>>8)&0xff;
+        c[3]=(n)&0xff;
+        for (i=0; i<4; i++)
+        {
+            switch(sha)
+            {
+            case SHA256:
+                HASH256_process(&sha256,c[i]);
+                break;
+            case SHA384:
+                HASH384_process(&sha512,c[i]);
+                break;
+            case SHA512:
+                HASH512_process(&sha512,c[i]);
+                break;
+            }
+        }
+    }
+
+    switch (sha)
+    {
+    case SHA256:
+        HASH256_hash(&sha256,hh);
+        break;
+    case SHA384:
+        HASH384_hash(&sha512,hh);
+        break;
+    case SHA512:
+        HASH512_hash(&sha512,hh);
+        break;
+    }
+
+    OCT_empty(w);
+    OCT_jbytes(w,hh,hlen);
+    for (i=0; i<hlen; i++) hh[i]=0;
+
+    return hlen;
+}
+
+/* generate an RSA key pair */
+void RSA_KEY_PAIR(csprng *RNG,sign32 e,rsa_private_key *PRIV,rsa_public_key *PUB,octet *P, octet* Q)
+{
+    /* IEEE1363 A16.11/A16.12 more or less */
+    BIG t[HFLEN],p1[HFLEN],q1[HFLEN];
+
+    if (RNG!=NULL)
+    {
+
+        for (;;)
+        {
+
+            FF_random(PRIV->p,RNG,HFLEN);
+            while (FF_lastbits(PRIV->p,2)!=3) FF_inc(PRIV->p,1,HFLEN);
+            while (!FF_prime(PRIV->p,RNG,HFLEN))
+                FF_inc(PRIV->p,4,HFLEN);
+
+            FF_copy(p1,PRIV->p,HFLEN);
+            FF_dec(p1,1,HFLEN);
+
+            if (FF_cfactor(p1,e,HFLEN)) continue;
+            break;
+        }
+
+        for (;;)
+        {
+            FF_random(PRIV->q,RNG,HFLEN);
+            while (FF_lastbits(PRIV->q,2)!=3) FF_inc(PRIV->q,1,HFLEN);
+            while (!FF_prime(PRIV->q,RNG,HFLEN))
+                FF_inc(PRIV->q,4,HFLEN);
+
+            FF_copy(q1,PRIV->q,HFLEN);
+            FF_dec(q1,1,HFLEN);
+            if (FF_cfactor(q1,e,HFLEN)) continue;
+
+            break;
+        }
+
+    }
+    else
+    {
+        FF_fromOctet(PRIV->p,P,HFLEN);
+        FF_fromOctet(PRIV->q,Q,HFLEN);
+
+        FF_copy(p1,PRIV->p,HFLEN);
+        FF_dec(p1,1,HFLEN);
+
+        FF_copy(q1,PRIV->q,HFLEN);
+        FF_dec(q1,1,HFLEN);
+    }
+
+    FF_mul(PUB->n,PRIV->p,PRIV->q,HFLEN);
+    PUB->e=e;
+
+    FF_copy(t,p1,HFLEN);
+    FF_shr(t,HFLEN);
+    FF_init(PRIV->dp,e,HFLEN);
+    FF_invmodp(PRIV->dp,PRIV->dp,t,HFLEN);
+    if (FF_parity(PRIV->dp)==0) FF_add(PRIV->dp,PRIV->dp,t,HFLEN);
+    FF_norm(PRIV->dp,HFLEN);
+
+    FF_copy(t,q1,HFLEN);
+    FF_shr(t,HFLEN);
+    FF_init(PRIV->dq,e,HFLEN);
+    FF_invmodp(PRIV->dq,PRIV->dq,t,HFLEN);
+    if (FF_parity(PRIV->dq)==0) FF_add(PRIV->dq,PRIV->dq,t,HFLEN);
+    FF_norm(PRIV->dq,HFLEN);
+
+    FF_invmodp(PRIV->c,PRIV->p,PRIV->q,HFLEN);
+
+    return;
+}
+
+/* Mask Generation Function */
+
+void MGF1(int sha,octet *z,int olen,octet *mask)
+{
+    char h[64];
+    octet H= {0,sizeof(h),h};
+    int hlen=sha;
+    int counter,cthreshold;
+
+    OCT_empty(mask);
+
+    cthreshold=ROUNDUP(olen,hlen);
+    for (counter=0; counter<cthreshold; counter++)
+    {
+        hashit(sha,z,counter,&H);
+        if (mask->len+hlen>olen) OCT_jbytes(mask,H.val,olen%hlen);
+        else                     OCT_joctet(mask,&H);
+    }
+    OCT_clear(&H);
+}
+
+/* SHAXXX identifier strings */
+const char SHA256ID[]= {0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20};
+const char SHA384ID[]= {0x30,0x41,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00,0x04,0x30};
+const char SHA512ID[]= {0x30,0x51,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0x04,0x40};
+
+/* PKCS 1.5 padding of a message to be signed */
+/* NOTE: length of output encoded in w->max */
+
+int PKCS15(int sha,octet *m,octet *w)
+{
+    int olen=w->max;
+    int hlen=sha;
+    int idlen=19;
+    char h[64];
+    octet H= {0,sizeof(h),h};
+
+    if (olen<idlen+hlen+10) return 0;
+    hashit(sha,m,-1,&H);
+
+    OCT_empty(w);
+    OCT_jbyte(w,0x00,1);
+    OCT_jbyte(w,0x01,1);
+    OCT_jbyte(w,0xff,olen-idlen-hlen-3);
+    OCT_jbyte(w,0x00,1);
+
+    if (hlen==32) OCT_jbytes(w,(char *)SHA256ID,idlen);
+    if (hlen==48) OCT_jbytes(w,(char *)SHA384ID,idlen);
+    if (hlen==64) OCT_jbytes(w,(char *)SHA512ID,idlen);
+
+    OCT_joctet(w,&H);
+
+    return 1;
+}
+
+/* OAEP Message Encoding for Encryption */
+/* NOTE: length of output encoded in f->max */
+
+int OAEP_ENCODE(int sha,octet *m,csprng *RNG,octet *p,octet *f)
+{
+    int slen,olen=f->max-1;
+    int mlen=m->len;
+    int hlen,seedlen;
+    char dbmask[MAX_RSA_BYTES],seed[64];
+    octet DBMASK= {0,sizeof(dbmask),dbmask};
+    octet SEED= {0,sizeof(seed),seed};
+
+    hlen=seedlen=sha;
+    if (mlen>olen-hlen-seedlen-1) return 0;
+    if (m==f) return 0;  /* must be distinct octets */
+
+    hashit(sha,p,-1,f);
+
+    slen=olen-mlen-hlen-seedlen-1;
+
+    OCT_jbyte(f,0,slen);
+    OCT_jbyte(f,0x1,1);
+    OCT_joctet(f,m);
+
+    OCT_rand(&SEED,RNG,seedlen);
+
+    MGF1(sha,&SEED,olen-seedlen,&DBMASK);
+
+    OCT_xor(&DBMASK,f);
+    MGF1(sha,&DBMASK,seedlen,f);
+
+    OCT_xor(f,&SEED);
+
+    OCT_joctet(f,&DBMASK);
+
+    OCT_pad(f,f->max);
+    OCT_clear(&SEED);
+    OCT_clear(&DBMASK);
+
+    return 1;
+}
+
+/* OAEP Message Decoding for Decryption */
+
+int OAEP_DECODE(int sha,octet *p,octet *f)
+{
+    int comp,x,t;
+    int i,k,olen=f->max-1;
+    int hlen,seedlen;
+    char dbmask[MAX_RSA_BYTES],seed[64],chash[64];
+    octet DBMASK= {0,sizeof(dbmask),dbmask};
+    octet SEED= {0,sizeof(seed),seed};
+    octet CHASH= {0,sizeof(chash),chash};
+
+    seedlen=hlen=sha;
+    if (olen<seedlen+hlen+1) return 0;
+    if (!OCT_pad(f,olen+1)) return 0;
+    hashit(sha,p,-1,&CHASH);
+
+    x=f->val[0];
+    for (i=seedlen; i<olen; i++)
+        DBMASK.val[i-seedlen]=f->val[i+1];
+    DBMASK.len=olen-seedlen;
+
+    MGF1(sha,&DBMASK,seedlen,&SEED);
+    for (i=0; i<seedlen; i++) SEED.val[i]^=f->val[i+1];
+    MGF1(sha,&SEED,olen-seedlen,f);
+    OCT_xor(&DBMASK,f);
+
+    comp=OCT_ncomp(&CHASH,&DBMASK,hlen);
+
+    OCT_shl(&DBMASK,hlen);
+
+    OCT_clear(&SEED);
+    OCT_clear(&CHASH);
+
+    for (k=0;; k++)
+    {
+        if (k>=DBMASK.len)
+        {
+            OCT_clear(&DBMASK);
+            return 0;
+        }
+        if (DBMASK.val[k]!=0) break;
+    }
+
+    t=DBMASK.val[k];
+    if (!comp || x!=0 || t!=0x01)
+    {
+        OCT_clear(&DBMASK);
+        return 0;
+    }
+
+    OCT_shl(&DBMASK,k+1);
+    OCT_copy(f,&DBMASK);
+    OCT_clear(&DBMASK);
+
+    return 1;
+}
+
+/* destroy the Private Key structure */
+void RSA_PRIVATE_KEY_KILL(rsa_private_key *PRIV)
+{
+    FF_zero(PRIV->p,HFLEN);
+    FF_zero(PRIV->q,HFLEN);
+    FF_zero(PRIV->dp,HFLEN);
+    FF_zero(PRIV->dq,HFLEN);
+    FF_zero(PRIV->c,HFLEN);
+}
+
+/* RSA encryption with the public key */
+void RSA_ENCRYPT(rsa_public_key *PUB,octet *F,octet *G)
+{
+    BIG f[FFLEN];
+    FF_fromOctet(f,F,FFLEN);
+
+    FF_power(f,f,PUB->e,PUB->n,FFLEN);
+
+    FF_toOctet(G,f,FFLEN);
+}
+
+/* RSA decryption with the private key */
+void RSA_DECRYPT(rsa_private_key *PRIV,octet *G,octet *F)
+{
+    BIG g[FFLEN],t[FFLEN],jp[HFLEN],jq[HFLEN];
+
+    FF_fromOctet(g,G,FFLEN);
+
+    FF_dmod(jp,g,PRIV->p,HFLEN);
+    FF_dmod(jq,g,PRIV->q,HFLEN);
+
+    FF_skpow(jp,jp,PRIV->dp,PRIV->p,HFLEN);
+    FF_skpow(jq,jq,PRIV->dq,PRIV->q,HFLEN);
+
+
+    FF_zero(g,FFLEN);
+    FF_copy(g,jp,HFLEN);
+    FF_mod(jp,PRIV->q,HFLEN);
+    if (FF_comp(jp,jq,HFLEN)>0)
+        FF_add(jq,jq,PRIV->q,HFLEN);
+    FF_sub(jq,jq,jp,HFLEN);
+    FF_norm(jq,HFLEN);
+
+    FF_mul(t,PRIV->c,jq,HFLEN);
+    FF_dmod(jq,t,PRIV->q,HFLEN);
+
+    FF_mul(t,jq,PRIV->p,HFLEN);
+    FF_add(g,t,g,FFLEN);
+    FF_norm(g,FFLEN);
+
+    FF_toOctet(F,g,FFLEN);
+
+    return;
+}
+
diff --git a/version22/c/rsa.h b/version22/c/rsa.h
new file mode 100644
index 0000000..b2c6ea0
--- /dev/null
+++ b/version22/c/rsa.h
@@ -0,0 +1,99 @@
+/*
+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.
+*/
+
+/**
+ * @file rsa.h
+ * @author Mike Scott and Kealan McCusker
+ * @date 2nd June 2015
+ * @brief RSA Header file for implementation of RSA protocol
+ *
+ * declares functions
+ *
+ */
+
+#ifndef RSA_H
+#define RSA_H
+
+#include "amcl.h"
+
+#define MAX_RSA_BYTES 512 // Maximum of 4096
+#define HASH_TYPE_RSA SHA256 /**< Chosen Hash algorithm */
+#define RFS MODBYTES*FFLEN /**< RSA Public Key Size in bytes */
+
+/* RSA Auxiliary Functions */
+
+/**	@brief RSA Key Pair Generator
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param e the encryption exponent
+	@param PRIV the output RSA private key
+	@param PUB the output RSA public key
+        @param P Input prime number. Used when R is equal to NULL for testing
+        @param Q Inpuy prime number. Used when R is equal to NULL for testing
+ */
+extern void RSA_KEY_PAIR(csprng *R,sign32 e,rsa_private_key* PRIV,rsa_public_key* PUB,octet *P, octet* Q);
+/**	@brief PKCS V1.5 padding of a message prior to RSA signature
+ *
+	@param h is the hash type
+	@param M is the input message
+	@param W is the output encoding, ready for RSA signature
+	@return 1 if OK, else 0
+ */
+extern int PKCS15(int h,octet *M,octet *W);
+/**	@brief OAEP padding of a message prior to RSA encryption
+ *
+	@param h is the hash type
+	@param M is the input message
+	@param R is a pointer to a cryptographically secure random number generator
+	@param P are input encoding parameter string (could be NULL)
+	@param F is the output encoding, ready for RSA encryption
+	@return 1 if OK, else 0
+ */
+extern int	OAEP_ENCODE(int h,octet *M,csprng *R,octet *P,octet *F);
+/**	@brief OAEP unpadding of a message after RSA decryption
+ *
+	Unpadding is done in-place
+	@param h is the hash type
+	@param P are input encoding parameter string (could be NULL)
+	@param F is input padded message, unpadded on output
+	@return 1 if OK, else 0
+ */
+extern int  OAEP_DECODE(int h,octet *P,octet *F);
+/**	@brief RSA encryption of suitably padded plaintext
+ *
+	@param PUB the input RSA public key
+	@param F is input padded message
+	@param G is the output ciphertext
+ */
+extern void RSA_ENCRYPT(rsa_public_key* PUB,octet *F,octet *G);
+/**	@brief RSA decryption of ciphertext
+ *
+	@param PRIV the input RSA private key
+	@param G is the input ciphertext
+	@param F is output plaintext (requires unpadding)
+
+ */
+extern void RSA_DECRYPT(rsa_private_key* PRIV,octet *G,octet *F);
+/**	@brief Destroy an RSA private Key
+ *
+	@param PRIV the input RSA private key. Destroyed on output.
+ */
+extern void RSA_PRIVATE_KEY_KILL(rsa_private_key *PRIV);
+
+#endif
diff --git a/version22/c/testecdh.c b/version22/c/testecdh.c
new file mode 100644
index 0000000..31e4944
--- /dev/null
+++ b/version22/c/testecdh.c
@@ -0,0 +1,207 @@
+/*
+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.
+*/
+
+/* test driver and function exerciser for ECDH/ECIES/ECDSA API Functions */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "ecdh.h"
+#include "randapi.h"
+
+int ecdh(csprng *RNG)
+{
+    int i,res;
+    char *pp="M0ng00se";
+    /* These octets are automatically protected against buffer overflow attacks */
+    /* Note salt must be big enough to include an appended word */
+    /* Note ECIES ciphertext C must be big enough to include at least 1 appended block */
+    /* Recall EFS is field size in bytes. So EFS=32 for 256-bit curve */
+    char s0[2*EGS],s1[EGS],w0[2*EFS+1],w1[2*EFS+1],z0[EFS],z1[EFS],key[EAS],salt[40],pw[40];
+    octet S0= {0,sizeof(s0),s0};
+    octet S1= {0,sizeof(s1),s1};
+    octet W0= {0,sizeof(w0),w0};
+    octet W1= {0,sizeof(w1),w1};
+    octet Z0= {0,sizeof(z0),z0};
+    octet Z1= {0,sizeof(z1),z1};
+    octet KEY= {0,sizeof(key),key};
+    octet SALT= {0,sizeof(salt),salt};
+    octet PW= {0,sizeof(pw),pw};
+
+    SALT.len=8;
+    for (i=0; i<8; i++) SALT.val[i]=i+1; // set Salt
+
+    printf("Alice's Passphrase= %s\n",pp);
+
+    OCT_empty(&PW);
+    OCT_jstring(&PW,pp);   // set Password from string
+
+    /* private key S0 of size EGS bytes derived from Password and Salt */
+
+    PBKDF2(HASH_TYPE_ECC,&PW,&SALT,1000,EGS,&S0);
+
+    printf("Alices private key= 0x");
+    OCT_output(&S0);
+
+    /* Generate Key pair S/W */
+
+    ECP_KEY_PAIR_GENERATE(NULL,&S0,&W0);
+    printf("Alices public key= 0x");
+    OCT_output(&W0);
+
+    res=ECP_PUBLIC_KEY_VALIDATE(1,&W0);
+    if (res!=0)
+    {
+        printf("ECP Public Key is invalid!\n");
+        return 0;
+    }
+
+    /* Random private key for other party */
+    ECP_KEY_PAIR_GENERATE(RNG,&S1,&W1);
+    res=ECP_PUBLIC_KEY_VALIDATE(1,&W1);
+    if (res!=0)
+    {
+        printf("ECP Public Key is invalid!\n");
+        return 0;
+    }
+    printf("Servers private key= 0x");
+    OCT_output(&S1);
+    printf("Servers public key= 0x");
+    OCT_output(&W1);
+
+    /* Calculate common key using DH - IEEE 1363 method */
+
+    ECPSVDP_DH(&S0,&W1,&Z0);
+    ECPSVDP_DH(&S1,&W0,&Z1);
+
+    if (!OCT_comp(&Z0,&Z1))
+    {
+        printf("*** ECPSVDP-DH Failed\n");
+        return 0;
+    }
+
+    KDF2(HASH_TYPE_ECC,&Z0,NULL,EAS,&KEY);
+
+    printf("Alice's DH Key=  0x");
+    OCT_output(&KEY);
+    printf("Servers DH Key=  0x");
+    OCT_output(&KEY);
+
+#if CURVETYPE != MONTGOMERY
+
+    char ds[EGS],p1[30],p2[30],v[2*EFS+1],m[32],c[64],t[32],cs[EGS];
+    octet DS= {0,sizeof(ds),ds};
+    octet CS= {0,sizeof(cs),cs};
+    octet P1= {0,sizeof(p1),p1};
+    octet P2= {0,sizeof(p2),p2};
+    octet V= {0,sizeof(v),v};
+    octet M= {0,sizeof(m),m};
+    octet C= {0,sizeof(c),c};
+    octet T= {0,sizeof(t),t};
+
+    printf("Testing ECIES\n");
+
+    P1.len=3;
+    P1.val[0]=0x0;
+    P1.val[1]=0x1;
+    P1.val[2]=0x2;
+    P2.len=4;
+    P2.val[0]=0x0;
+    P2.val[1]=0x1;
+    P2.val[2]=0x2;
+    P2.val[3]=0x3;
+
+    M.len=17;
+    for (i=0; i<=16; i++) M.val[i]=i;
+
+    ECP_ECIES_ENCRYPT(HASH_TYPE_ECC,&P1,&P2,RNG,&W1,&M,12,&V,&C,&T);
+
+    printf("Ciphertext= \n");
+    printf("V= 0x");
+    OCT_output(&V);
+    printf("C= 0x");
+    OCT_output(&C);
+    printf("T= 0x");
+    OCT_output(&T);
+
+    if (!ECP_ECIES_DECRYPT(HASH_TYPE_ECC,&P1,&P2,&V,&C,&T,&S1,&M))
+    {
+        printf("*** ECIES Decryption Failed\n");
+        return 0;
+    }
+    else printf("Decryption succeeded\n");
+
+    printf("Message is 0x");
+    OCT_output(&M);
+
+
+    printf("Testing ECDSA\n");
+
+    if (ECPSP_DSA(HASH_TYPE_ECC,RNG,NULL,&S0,&M,&CS,&DS)!=0)
+    {
+        printf("***ECDSA Signature Failed\n");
+        return 0;
+    }
+
+    printf("Signature C = 0x");
+    OCT_output(&CS);
+    printf("Signature D = 0x");
+    OCT_output(&DS);
+
+    if (ECPVP_DSA(HASH_TYPE_ECC,&W0,&M,&CS,&DS)!=0)
+    {
+        printf("***ECDSA Verification Failed\n");
+        return 0;
+    }
+    else 
+    {
+      printf("ECDSA Signature/Verification succeeded\n");
+    }
+
+#endif
+
+    return 0;
+}
+
+int main()
+{
+    int i;
+    unsigned long ran;
+
+	char raw[100];
+    octet RAW= {0,sizeof(raw),raw};
+    csprng RNG;                /* Crypto Strong RNG */
+
+    time((time_t *)&ran);
+
+    RAW.len=100;				/* fake random seed source */
+    RAW.val[0]=ran;
+    RAW.val[1]=ran>>8;
+    RAW.val[2]=ran>>16;
+    RAW.val[3]=ran>>24;
+    for (i=0; i<100; i++) RAW.val[i]=i+1;
+
+    CREATE_CSPRNG(&RNG,&RAW);   /* initialise strong RNG */
+
+	ecdh(&RNG);
+
+	KILL_CSPRNG(&RNG);
+}
+
diff --git a/version22/c/testmpin.c b/version22/c/testmpin.c
new file mode 100644
index 0000000..f3ba165
--- /dev/null
+++ b/version22/c/testmpin.c
@@ -0,0 +1,313 @@
+/*
+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.
+*/
+
+/* test driver and function exerciser for MPIN Functions */
+/* Version 3.0 - supports Time Permits */
+
+/* Build executible after installation:
+
+  gcc -std=c99 -g ./testmpin.c -I/opt/amcl/include -L/opt/amcl/lib -lamcl -lmpin -o testmpin
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "mpin.h"
+#include "randapi.h"
+
+#define PERMITS  /* for time permits ON or OFF */
+#define PINERROR /* For PIN ERROR detection ON or OFF */
+#define FULL     /* for M-Pin Full or M-Pin regular */
+//#define SINGLE_PASS /* SINGLE PASS M-Pin */
+
+int mpin(csprng *RNG)
+{
+    int pin,rtn,err;
+#ifdef PERMITS
+    int date=MPIN_today();
+#else
+    int date=0;
+#endif
+    char x[PGS],s[PGS],y[PGS],client_id[100],sst[4*PFS],token[2*PFS+1],sec[2*PFS+1],permit[2*PFS+1],xcid[2*PFS+1],xid[2*PFS+1],e[12*PFS],f[12*PFS];
+    char hcid[PFS],hsid[PFS],hid[2*PFS+1],htid[2*PFS+1],h[PGS];
+#ifdef FULL
+    char r[PGS],z[2*PFS+1],w[PGS],t[2*PFS+1];
+    char g1[12*PFS],g2[12*PFS];
+    char ck[PAS],sk[PAS];
+#endif
+    octet S= {0,sizeof(s),s};
+    octet X= {0,sizeof(x),x};
+    octet Y= {0,sizeof(y),y};
+    octet H= {0,sizeof(h),h};
+    octet CLIENT_ID= {0,sizeof(client_id),client_id};
+    octet SST= {0,sizeof(sst),sst};
+    octet TOKEN= {0,sizeof(token),token};
+    octet SEC= {0,sizeof(sec),sec};
+    octet PERMIT= {0,sizeof(permit),permit};
+    octet xCID= {0,sizeof(xcid),xcid};
+    octet xID= {0,sizeof(xid),xid};
+    octet HCID= {0,sizeof(hcid),hcid};
+    octet HSID= {0,sizeof(hsid),hsid};
+    octet HID= {0,sizeof(hid),hid};
+    octet HTID= {0,sizeof(htid),htid};
+    octet E= {0,sizeof(e),e};
+    octet F= {0,sizeof(f),f};
+#ifdef FULL
+    octet R= {0,sizeof(r),r};
+    octet Z= {0,sizeof(z),z};
+    octet W= {0,sizeof(w),w};
+    octet T= {0,sizeof(t),t};
+    octet G1= {0,sizeof(g1),g1};
+    octet G2= {0,sizeof(g2),g2};
+    octet SK= {0,sizeof(sk),sk};
+    octet CK= {0,sizeof(ck),ck};
+#endif
+    octet *pxID,*pxCID,*pHID,*pHTID,*pE,*pF,*pPERMIT,*prHID;
+    char idhex[100];
+
+    /* Trusted Authority set-up */
+    MPIN_RANDOM_GENERATE(RNG,&S);
+    printf("Master Secret= ");
+    OCT_output(&S);
+
+    /* Create Client Identity */
+    OCT_jstring(&CLIENT_ID,"testUser@miracl.com");
+    MPIN_HASH_ID(HASH_TYPE_MPIN,&CLIENT_ID,&HCID);  /* Either Client or TA calculates Hash(ID) - you decide! */
+
+    printf("Client ID Hash= ");
+    OCT_output(&HCID);
+    printf("\n");
+
+    OCT_toHex(&CLIENT_ID,idhex);
+    printf("Client ID= %s\n",idhex);// OCT_toHex(&CLIENT_ID); printf("\n");
+
+    /* Client and Server are issued secrets by DTA */
+    MPIN_GET_SERVER_SECRET(&S,&SST);
+    printf("Server Secret= ");
+    OCT_output(&SST);
+
+    MPIN_GET_CLIENT_SECRET(&S,&HCID,&TOKEN);
+    printf("Client Secret= ");
+    OCT_output(&TOKEN);
+
+    /* Client extracts PIN from secret to create Token */
+    pin=1234;
+    printf("Client extracts PIN= %d\n",pin);
+    MPIN_EXTRACT_PIN(HASH_TYPE_MPIN,&CLIENT_ID,pin,&TOKEN);
+    printf("Client Token= ");
+    OCT_output(&TOKEN);
+
+#ifdef FULL
+    MPIN_PRECOMPUTE(&TOKEN,&HCID,NULL,&G1,&G2);
+#endif
+
+#ifdef PERMITS
+    /* Client gets "Time Permit" from DTA */
+    printf("Client gets Time Permit\n");
+
+    MPIN_GET_CLIENT_PERMIT(HASH_TYPE_MPIN,date,&S,&HCID,&PERMIT);
+    printf("Time Permit= ");
+    OCT_output(&PERMIT);
+
+    /* This encoding makes Time permit look random */
+    if (MPIN_ENCODING(RNG,&PERMIT)!=0) printf("Encoding error\n");
+    /* printf("Encoded Time Permit= "); OCT_output(&PERMIT); */
+    if (MPIN_DECODING(&PERMIT)!=0) printf("Decoding error\n");
+    /* printf("Decoded Time Permit= "); OCT_output(&PERMIT); */
+#endif
+
+    /* MPin Protocol */
+
+    /* Client enters PIN */
+    printf("\nPIN= ");
+    if(scanf("%d",&pin)) {};
+    /* to avoid silly compile error */
+    getchar();
+
+    /* 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
+
+    HSID - hashed client ID as calculated by the server
+    HCID - hashed client ID as calculated by the client
+
+    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.
+
+    */
+
+    pxID=&xID;
+    pxCID=&xCID;
+    pHID=&HID;
+    pHTID=&HTID;
+    pE=&E;
+    pF=&F;
+    pPERMIT=&PERMIT;
+
+#ifdef PERMITS
+    prHID=pHTID;
+#ifndef PINERROR
+    pxID=NULL;
+//   pHID=NULL;  //new
+#endif
+#else
+    prHID=pHID;
+    pPERMIT=NULL;
+    pxCID=NULL;
+    pHTID=NULL;
+#endif
+#ifndef PINERROR
+    pE=NULL;
+    pF=NULL;
+#endif
+
+    /* When set only send hashed IDs to server */
+    octet *pID;
+#ifdef USE_ANONYMOUS
+    pID = &HCID;
+#else
+    pID = &CLIENT_ID;
+#endif
+
+#ifdef SINGLE_PASS
+    int timeValue;
+    printf("MPIN Single Pass\n");
+    timeValue = MPIN_GET_TIME();
+
+    rtn=MPIN_CLIENT(HASH_TYPE_MPIN,date,&CLIENT_ID,RNG,&X,pin,&TOKEN,&SEC,pxID,pxCID,pPERMIT,NULL,timeValue,&Y);
+
+    if (rtn != 0)
+    {
+        printf("MPIN_CLIENT ERROR %d\n", rtn);
+        return 1;
+    }
+
+#ifdef FULL
+    MPIN_GET_G1_MULTIPLE(RNG,1,&R,&HCID,&Z);  /* Also Send Z=r.ID to Server, remember random r */
+#endif
+
+
+    rtn=MPIN_SERVER(HASH_TYPE_MPIN,date,pHID,pHTID,&Y,&SST,pxID,pxCID,&SEC,pE,pF,pID,NULL,timeValue);
+
+#ifdef FULL
+    MPIN_HASH_ID(HASH_TYPE_MPIN,&CLIENT_ID,&HSID);  // new
+    MPIN_GET_G1_MULTIPLE(RNG,0,&W,prHID,&T);  /* Also send T=w.ID to client, remember random w  */
+#endif
+
+#else // SINGLE_PASS
+    printf("MPIN Multi Pass\n");
+    if (MPIN_CLIENT_1(HASH_TYPE_MPIN,date,&CLIENT_ID,RNG,&X,pin,&TOKEN,&SEC,pxID,pxCID,pPERMIT)!=0)
+    {
+        printf("Error from Client side - First Pass\n");
+        return 0;
+    }
+
+    /* Send U=x.ID to server, and recreate secret from token and pin */
+
+#ifdef FULL
+    MPIN_HASH_ID(HASH_TYPE_MPIN,&CLIENT_ID,&HCID);
+    MPIN_GET_G1_MULTIPLE(RNG,1,&R,&HCID,&Z);  /* Also Send Z=r.ID to Server, remember random r, DH component */
+#endif
+
+    /* Server calculates H(ID) and H(ID)+H(T|H(ID)) (if time permits enabled), and maps them to points on the curve HID and HTID resp. */
+    MPIN_SERVER_1(HASH_TYPE_MPIN,date,pID,pHID,pHTID);
+
+    /* Server generates Random number Y and sends it to Client */
+    MPIN_RANDOM_GENERATE(RNG,&Y);
+
+#ifdef FULL
+    MPIN_HASH_ID(HASH_TYPE_MPIN,&CLIENT_ID,&HSID); //new
+    MPIN_GET_G1_MULTIPLE(RNG,0,&W,prHID,&T);  /* Also send T=w.ID to client, remember random w, DH component  */
+#endif
+
+    /* Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC */
+    if (MPIN_CLIENT_2(&X,&Y,&SEC)!=0)
+    {
+        printf("Error from Client side - Second Pass\n");
+        return 1;
+    }
+
+    /* Server Second phase. 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=MPIN_SERVER_2(date,pHID,pHTID,&Y,&SST,pxID,pxCID,&SEC,pE,pF);
+#endif // SINGLE_PASS
+
+    if (rtn!=0)
+    {
+        printf("Server says - Bad Pin.\n");
+#ifdef PINERROR
+
+        err=MPIN_KANGAROO(&E,&F);
+        if (err) printf("(Client PIN is out by %d)\n",err);
+
+#endif
+        return 1;
+    }
+    else
+    {
+        printf("Server says - PIN is good! You really are ");
+        OCT_output_string(&CLIENT_ID);
+        printf(".\n");
+    }
+
+#ifdef FULL
+    MPIN_HASH_ALL(HASH_TYPE_MPIN,&HCID,pxID,pxCID,&SEC,&Y,&Z,&T,&H);  // new
+    MPIN_CLIENT_KEY(HASH_TYPE_MPIN,&G1,&G2,pin,&R,&X,&H,&T,&CK);      // new H
+    printf("Client Key = ");
+    OCT_output(&CK);
+
+    MPIN_HASH_ALL(HASH_TYPE_MPIN,&HSID,pxID,pxCID,&SEC,&Y,&Z,&T,&H);
+    MPIN_SERVER_KEY(HASH_TYPE_MPIN,&Z,&SST,&W,&H,pHID,pxID,pxCID,&SK); // new H,pHID
+    printf("Server Key = ");
+    OCT_output(&SK);
+#endif
+    return 0;
+}
+
+int main()
+{
+  int i;
+    unsigned long ran;
+
+	char raw[100];
+    octet RAW= {0,sizeof(raw),raw};
+    csprng RNG;                /* Crypto Strong RNG */
+
+    time((time_t *)&ran);
+
+    RAW.len=100;				/* fake random seed source */
+    RAW.val[0]=ran;
+    RAW.val[1]=ran>>8;
+    RAW.val[2]=ran>>16;
+    RAW.val[3]=ran>>24;
+    for (i=0; i<100; i++) RAW.val[i]=i+1;
+
+    CREATE_CSPRNG(&RNG,&RAW);   /* initialise strong RNG */
+
+	mpin(&RNG);
+
+	KILL_CSPRNG(&RNG);
+}
+
diff --git a/version22/c/testrsa.c b/version22/c/testrsa.c
new file mode 100644
index 0000000..247ba97
--- /dev/null
+++ b/version22/c/testrsa.c
@@ -0,0 +1,104 @@
+/*
+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.
+*/
+
+/* test driver and function exerciser for RSA API Functions */
+
+#include <stdio.h>
+#include <time.h>
+#include "rsa.h"
+#include "randapi.h"
+
+int rsa(csprng *RNG)
+{
+    char m[RFS],ml[RFS],c[RFS],e[RFS],s[RFS];
+    rsa_public_key pub;
+    rsa_private_key priv;
+    
+    octet M= {0,sizeof(m),m};
+    octet ML= {0,sizeof(ml),ml};
+    octet C= {0,sizeof(c),c};
+    octet E= {0,sizeof(e),e};
+    octet S= {0,sizeof(s),s};
+
+    printf("Generating public/private key pair\n");
+    RSA_KEY_PAIR(RNG,65537,&priv,&pub,NULL,NULL);
+
+    printf("Encrypting test string\n");
+    OCT_jstring(&M,(char *)"Hello World\n");
+
+    OAEP_ENCODE(HASH_TYPE_RSA,&M,RNG,NULL,&E); /* OAEP encode message m to e  */
+
+    RSA_ENCRYPT(&pub,&E,&C);     /* encrypt encoded message */
+    printf("Ciphertext= ");
+    OCT_output(&C);
+
+    printf("Decrypting test string\n");
+    RSA_DECRYPT(&priv,&C,&ML);   /* ... and then decrypt it */
+
+    OAEP_DECODE(HASH_TYPE_RSA,NULL,&ML);    /* decode it */
+    OCT_output_string(&ML);
+
+    printf("Signing message\n");
+    PKCS15(HASH_TYPE_RSA,&M,&C);
+
+    RSA_DECRYPT(&priv,&C,&S); /* create signature in S */
+
+    printf("Signature= ");
+    OCT_output(&S);
+
+    RSA_ENCRYPT(&pub,&S,&ML);
+
+    if (OCT_comp(&C,&ML)) printf("Signature is valid\n");
+    else printf("Signature is INVALID\n");
+
+    RSA_PRIVATE_KEY_KILL(&priv);
+
+    OCT_clear(&M);
+    OCT_clear(&ML);   /* clean up afterwards */
+    OCT_clear(&C);
+    OCT_clear(&E);
+
+    return 0;
+}
+
+int main()
+{
+    int i;
+    unsigned long ran;
+
+	char raw[100];
+    octet RAW= {0,sizeof(raw),raw};
+    csprng RNG;                /* Crypto Strong RNG */
+
+    time((time_t *)&ran);
+
+    RAW.len=100;				/* fake random seed source */
+    RAW.val[0]=ran;
+    RAW.val[1]=ran>>8;
+    RAW.val[2]=ran>>16;
+    RAW.val[3]=ran>>24;
+    for (i=0; i<100; i++) RAW.val[i]=i+1;
+
+    CREATE_CSPRNG(&RNG,&RAW);   /* initialise strong RNG */
+
+	rsa(&RNG);
+
+	KILL_CSPRNG(&RNG);
+}
+
diff --git a/version22/c/x509.c b/version22/c/x509.c
new file mode 100644
index 0000000..6a59294
--- /dev/null
+++ b/version22/c/x509.c
@@ -0,0 +1,1079 @@
+/*
+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.
+*/
+
+/* AMCL X.509 Functions */
+
+// To run test program, define HAS_MAIN
+// gcc x509.c ecdh.c rsa.c amcl.a -o x509.exe
+
+#define HAS_MAIN
+
+#include <stdio.h>
+#include "ecdh.h"
+#include "rsa.h"
+#include "x509.h"
+
+// ASN.1 tags
+
+#define ANY 0x00
+#define SEQ 0x30
+#define OID 0x06
+#define INT 0x02
+#define NUL 0x05
+#define ZER 0x00
+#define UTF 0x0C
+#define UTC 0x17
+#define LOG 0x01
+#define BIT 0x03
+#define OCT 0x04
+#define STR 0x13
+#define SET 0x31
+#define IA5 0x16
+
+// Supported Encryption Methods
+
+#define ECC 1
+#define RSA 2
+#define ECC_H256 11
+#define ECC_H384 12
+#define ECC_H512 13
+#define RSA_H256 21
+#define RSA_H384 22
+#define RSA_H512 23
+
+// return xxxxxxxxxxxxxxxx | xxxx | xxxx
+//        2048 | 2 | 3  -> 2048-bit RSA with SHA512
+
+#define H256 2
+#define H384 3
+#define H512 4
+
+// Define some OIDs
+
+// Elliptic Curve with SHA256
+static char eccsha256[8]= {0x2a,0x86,0x48,0xce,0x3d,0x04,0x03,0x02};
+static octet ECCSHA256= {8,sizeof(eccsha256),eccsha256};
+
+// Elliptic Curve with SHA384
+static char eccsha384[8]= {0x2a,0x86,0x48,0xce,0x3d,0x04,0x03,0x03};
+static octet ECCSHA384= {8,sizeof(eccsha384),eccsha384};
+
+// Elliptic Curve with SHA512
+static char eccsha512[8]= {0x2a,0x86,0x48,0xce,0x3d,0x04,0x03,0x04};
+static octet ECCSHA512= {8,sizeof(eccsha512),eccsha512};
+
+// EC Public Key
+static char ecpk[7]= {0x2a,0x86,0x48,0xce,0x3d,0x02,0x01};
+static octet ECPK= {7,sizeof(ecpk),ecpk};
+
+// C25519 curve
+static char prime25519[9]= {0x2B,0x06,0x01,0x04,0x01,0xDA,0x47,0x0F,0x01}; /*****/
+static octet PRIME25519= {9,sizeof(prime25519),prime25519};
+
+// NIST256 curve
+static char prime256v1[8]= {0x2a,0x86,0x48,0xce,0x3d,0x03,0x01,0x07};
+static octet PRIME256V1= {8,sizeof(prime256v1),prime256v1};
+
+// NIST384 curve
+static char secp384r1[5]= {0x2B,0x81,0x04,0x00,0x22};
+static octet SECP384R1= {5,sizeof(secp384r1),secp384r1};
+
+// NIST521 curve
+static char secp521r1[5]= {0x2B,0x81,0x04,0x00,0x23};
+static octet SECP521R1= {5,sizeof(secp521r1),secp521r1};
+
+// RSA Public Key
+static char rsapk[9]= {0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01};
+static octet RSAPK= {9,sizeof(rsapk),rsapk};
+
+// RSA with SHA256
+static char rsasha256[9]= {0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b};
+static octet RSASHA256= {9,sizeof(rsasha256),rsasha256};
+
+// RSA with SHA384
+static char rsasha384[9]= {0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0c};
+static octet RSASHA384= {9,sizeof(rsasha384),rsasha384};
+
+// RSA with SHA512
+static char rsasha512[9]= {0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0d};
+static octet RSASHA512= {9,sizeof(rsasha512),rsasha512};
+
+#ifdef HAS_MAIN
+// countryName
+static char cn[3]= {0x55,0x04,0x06};
+static octet CN= {3,sizeof(cn),cn};
+
+// stateName
+// static char sn[3]= {0x55,0x04,0x08};
+// static octet SN= {3,sizeof(sn),sn};
+
+// localName
+// static char ln[3]= {0x55,0x04,0x07};
+// static octet LN= {3,sizeof(ln),ln};
+
+// orgName
+static char on[3]= {0x55,0x04,0x0A};
+static octet ON= {3,sizeof(on),on};
+
+// unitName
+// static char un[3]= {0x55,0x04,0x0B};
+// static octet UN= {3,sizeof(un),un};
+
+// myName
+// static char mn[3]= {0x55,0x04,0x03};
+// static octet MN= {3,sizeof(mn),mn};
+
+// emailName
+static char en[9]= {0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x09,0x01};
+static octet EN= {9,sizeof(en),en};
+#endif // HAS_MAIN
+
+/* Check expected TAG and return ASN.1 field length. If tag=0 skip check. */
+static int getalen(int tag,char *b,int j)
+{
+    int len;
+
+    if (tag!=0 && (unsigned char)b[j]!=tag) return -1; // not a valid tag
+    j++;
+
+    if ((unsigned char)b[j]==0x81)
+    {
+        j++;
+        len=(unsigned char)b[j];
+    }
+    else if ((unsigned char)b[j]==0x82)
+    {
+        j++;
+        len=256*b[j++];
+        len+=(unsigned char)b[j];
+    }
+    else
+    {
+        len=(unsigned char)b[j];
+        if (len>127) return -1;
+    }
+    return len;
+}
+
+/* jump over length field */
+static int skip(int len)
+{
+    if (len<128) return 2;
+    if (len>=128 && len<256) return 3;
+    return 4;
+}
+
+/* round length up to nearest 8-byte length */
+static int bround(int len)
+{
+    if (len%8==0) return len;
+    return len+(8-len%8);
+
+}
+
+//	Input signed cert as octet, and extract signature
+//	Return 0 for failure, ECC for Elliptic Curve signature, RSA for RSA signature
+//  Note that signature type is not provided here - its the type of the public key that
+//  is used to verify it that matters, and which determines for example the curve to be used!
+
+pktype X509_extract_cert_sig(octet *sc,octet *sig)
+{
+    int i,j,k,fin,len,rlen,sj,ex;
+    char soid[9];
+    octet SOID= {0,sizeof(soid),soid};
+    pktype ret;
+
+    ret.type=0;
+    ret.hash=0;
+
+    j=0;
+
+    len=getalen(SEQ,sc->val,j);		// Check for expected SEQ clause, and get length
+    if (len<0) return ret;			// if not a SEQ clause, there is a problem, exit
+    j+=skip(len);					// skip over length to clause contents. Add len to skip clause
+
+    if (len+j!=sc->len) return ret;
+
+    len=getalen(SEQ,sc->val,j);
+    if (len<0) return ret;
+    j+=skip(len)+len; // jump over cert to signature OID
+
+    len=getalen(SEQ,sc->val,j);
+    if (len<0) return ret;
+    j+=skip(len);
+
+    sj=j+len; // Needed to jump over signature OID
+
+// dive in to extract OID
+    len=getalen(OID,sc->val,j);
+    if (len<0) return ret;
+    j+=skip(len);
+
+    fin=j+len;
+    SOID.len=len;
+    for (i=0; j<fin; j++)
+        SOID.val[i++]= sc->val[j];
+
+    // check OID here..
+
+    if (OCT_comp(&ECCSHA256,&SOID))
+    {
+        ret.type=ECC;
+        ret.hash=H256;
+    }
+    if (OCT_comp(&ECCSHA384,&SOID))
+    {
+        ret.type=ECC;
+        ret.hash=H384;
+    }
+    if (OCT_comp(&ECCSHA512,&SOID))
+    {
+        ret.type=ECC;
+        ret.hash=H512;
+    }
+    if (OCT_comp(&RSASHA256,&SOID))
+    {
+        ret.type=RSA;
+        ret.hash=H256;
+    }
+    if (OCT_comp(&RSASHA384,&SOID))
+    {
+        ret.type=RSA;
+        ret.hash=H384;
+    }
+    if (OCT_comp(&RSASHA512,&SOID))
+    {
+        ret.type=RSA;
+        ret.hash=H512;
+    }
+
+    if (ret.type==0) return ret; // unsupported type
+
+    j=sj;  // jump out to signature
+
+    len=getalen(BIT,sc->val,j);
+    if (len<0)
+    {
+        ret.type=0;
+        return ret;
+    }
+    j+=skip(len);
+    j++;
+    len--; // skip bit shift (hopefully 0!)
+
+    if (ret.type==ECC)
+    {
+        // signature in the form (r,s)
+        len=getalen(SEQ,sc->val,j);
+        if (len<0)
+        {
+            ret.type=0;
+            return ret;
+        }
+        j+=skip(len);
+
+        // pick up r part of signature
+        len=getalen(INT,sc->val,j);
+        if (len<0)
+        {
+            ret.type=0;
+            return ret;
+        }
+        j+=skip(len);
+
+        if (sc->val[j]==0)
+        {
+            // skip leading zero
+            j++;
+            len--;
+        }
+        rlen=bround(len);
+
+        ex=rlen-len;
+        sig->len=2*rlen;
+
+        i=0;
+        for (k=0; k<ex; k++)
+            sig->val[i++]=0;
+
+        fin=j+len;
+        for (; j<fin; j++)
+            sig->val[i++]= sc->val[j];
+
+        // pick up s part of signature
+        len=getalen(INT,sc->val,j);
+        if (len<0)
+        {
+            ret.type=0;
+            return ret;
+        }
+        j+=skip(len);
+
+        if (sc->val[j]==0)
+        {
+            // skip leading zeros
+            j++;
+            len--;
+        }
+        rlen=bround(len);
+        ex=rlen-len;
+        for (k=0; k<ex; k++)
+            sig->val[i++]=0;
+
+        fin=j+len;
+        for (; j<fin; j++)
+            sig->val[i++]= sc->val[j];
+
+    }
+    if (ret.type==RSA)
+    {
+        rlen=bround(len);
+        ex=rlen-len;
+
+        sig->len=rlen;
+        i=0;
+        for (k=0; k<ex; k++)
+            sig->val[i++]=0;
+
+        fin=j+len;
+        for (; j<fin; j++)
+            sig->val[i++]= sc->val[j];
+
+    }
+    if (ret.hash==H256) ret.curve=NIST256;
+    if (ret.hash==H384) ret.curve=NIST384;
+    if (ret.hash==H512) ret.curve=NIST521;
+
+    return ret;
+}
+
+// Extract certificate from signed cert
+int X509_extract_cert(octet *sc,octet *cert)
+{
+    int i,j,fin,len,k;
+
+    j=0;
+    len=getalen(SEQ,sc->val,j);
+
+    if (len<0) return 0;
+    j+=skip(len);
+
+    k=j;
+
+    len=getalen(SEQ,sc->val,j);
+    if (len<0) return 0;
+    j+=skip(len);
+
+    fin=j+len;
+    cert->len=fin-k;
+    for (i=k; i<fin; i++) cert->val[i-k]=sc->val[i];
+
+    return 1;
+}
+
+// Extract Public Key from inside Certificate
+pktype X509_extract_public_key(octet *c,octet *key)
+{
+    int i,j,fin,len,sj;
+    char koid[12];     /*****/
+    octet KOID= {0,sizeof(koid),koid};
+    pktype ret;
+
+    ret.type=ret.hash=0;
+    ret.curve=-1;
+
+    j=0;
+
+    len=getalen(SEQ,c->val,j);
+    if (len<0) return ret;
+    j+=skip(len);
+
+    if (len+j!=c->len) return ret;
+
+    len=getalen(0,c->val,j);
+    if (len<0) return ret;
+    j+=skip(len)+len; //jump over version clause
+
+    len=getalen(INT,c->val,j);
+
+    if (len>0) j+=skip(len)+len; // jump over serial number clause (if there is one)
+
+    len=getalen(SEQ,c->val,j);
+    if (len<0) return ret;
+    j+=skip(len)+len;  // jump over signature algorithm
+
+    len=getalen(SEQ,c->val,j);
+    if (len<0) return ret;
+    j+=skip(len)+len; // skip issuer
+
+    len=getalen(SEQ,c->val,j);
+    if (len<0) return ret;
+    j+=skip(len)+len; // skip validity
+
+    len=getalen(SEQ,c->val,j);
+    if (len<0) return ret;
+    j+=skip(len)+len; // skip subject
+
+    len=getalen(SEQ,c->val,j);
+    if (len<0) return ret;
+    j+=skip(len); //
+
+    len=getalen(SEQ,c->val,j);
+    if (len<0) return ret;
+    j+=skip(len);
+
+// ** Maybe dive in and check Public Key OIDs here?
+// ecpublicKey & prime256v1, secp384r1 or secp521r1 for ECC
+// rsapublicKey for RSA
+
+    sj=j+len;
+
+    len=getalen(OID,c->val,j);
+    if (len<0) return ret;
+    j+=skip(len);
+
+    fin=j+len;
+    KOID.len=len;
+    for (i=0; j<fin; j++)
+        KOID.val[i++]= c->val[j];
+
+    ret.type=0;
+    if (OCT_comp(&ECPK,&KOID)) ret.type=ECC;
+    if (OCT_comp(&RSAPK,&KOID)) ret.type=RSA;
+
+    if (ret.type==0) return ret;
+
+    if (ret.type==ECC)
+    {
+        // which elliptic curve?
+        len=getalen(OID,c->val,j);
+        if (len<0)
+        {
+            ret.type=0;
+            return ret;
+        }
+        j+=skip(len);
+
+        fin=j+len;
+        KOID.len=len;
+        for (i=0; j<fin; j++)
+            KOID.val[i++]= c->val[j];
+
+        if (OCT_comp(&PRIME25519,&KOID)) ret.curve=C25519;   /*****/
+        if (OCT_comp(&PRIME256V1,&KOID)) ret.curve=NIST256;
+        if (OCT_comp(&SECP384R1,&KOID)) ret.curve=NIST384;
+        if (OCT_comp(&SECP521R1,&KOID)) ret.curve=NIST521;
+    }
+
+    j=sj; // skip to actual Public Key
+
+    len=getalen(BIT,c->val,j);
+    if (len<0)
+    {
+        ret.type=0;
+        return ret;
+    }
+    j+=skip(len); //
+    j++;
+    len--; // skip bit shift (hopefully 0!)
+
+// extract key
+    if (ret.type==ECC)
+    {
+        key->len=len;
+        fin=j+len;
+        for (i=0; j<fin; j++)
+            key->val[i++]= c->val[j];
+
+    }
+    if (ret.type==RSA)
+    {
+        // Key is (modulus,exponent) - assume exponent is 65537
+        len=getalen(SEQ,c->val,j);
+        if (len<0)
+        {
+            ret.type=0;
+            return ret;
+        }
+        j+=skip(len); //
+
+        len=getalen(INT,c->val,j); // get modulus
+        if (len<0)
+        {
+            ret.type=0;
+            return ret;
+        }
+        j+=skip(len); //
+        if (c->val[j]==0)
+        {
+            j++;
+            len--; // remove leading zero
+        }
+
+        key->len=len;
+        fin=j+len;
+        for (i=0; j<fin; j++)
+            key->val[i++]= c->val[j];
+
+    }
+    return ret;
+}
+
+// Find pointer to main sections of cert, before extracting individual field
+// Find index to issuer in cert
+int X509_find_issuer(octet *c)
+{
+    int j,len;
+    j=0;
+    len=getalen(SEQ,c->val,j);
+    if (len<0) return 0;
+    j+=skip(len);
+
+    if (len+j!=c->len) return 0;
+
+    len=getalen(0,c->val,j);
+    if (len<0) return 0;
+    j+=skip(len)+len; //jump over version clause
+
+    len=getalen(INT,c->val,j);
+
+    if (len>0) j+=skip(len)+len; // jump over serial number clause (if there is one)
+
+    len=getalen(SEQ,c->val,j);
+    if (len<0) return 0;
+    j+=skip(len)+len;  // jump over signature algorithm
+
+    return j;
+}
+
+// Find index to validity period
+int X509_find_validity(octet *c)
+{
+    int j,len;
+    j=X509_find_issuer(c);
+
+    len=getalen(SEQ,c->val,j);
+    if (len<0) return 0;
+    j+=skip(len)+len; // skip issuer
+
+    return j;
+}
+
+// Find index to subject in cert
+int X509_find_subject(octet *c)
+{
+    int j,len;
+    j=X509_find_validity(c);
+
+    len=getalen(SEQ,c->val,j);
+    if (len<0) return 0;
+    j+=skip(len)+len; // skip validity
+
+    return j;
+}
+
+// NOTE: When extracting cert information, we actually return just an index to the data inside the cert, and maybe its length
+// So no memory is assigned to store cert info. It is the callers responsibility to allocate such memory if required, and copy
+// cert information into it.
+
+// Find entity property indicated by SOID, given start of issuer or subject field. Return index in cert, flen=length of field
+
+int X509_find_entity_property(octet *c,octet *SOID,int start,int *flen)
+{
+    int i,j,k,fin,len,tlen;
+    char foid[50];  /*****/
+    octet FOID= {0,sizeof(foid),foid};
+
+    j=start;
+
+    tlen=getalen(SEQ,c->val,j);
+    if (tlen<0) return 0;
+    j+=skip(tlen);
+
+    for (k=j; j<k+tlen;)
+    {
+        // search for Owner OID
+        len=getalen(SET,c->val,j);
+        if (len<0) return 0;
+        j+=skip(len);
+        len=getalen(SEQ,c->val,j);
+        if (len<0) return 0;
+        j+=skip(len);
+        len=getalen(OID,c->val,j);
+        if (len<0) return 0;
+        j+=skip(len);
+        fin=j+len;  // extract OID
+        FOID.len=len;
+        for (i=0; j<fin; j++)
+            FOID.val[i++]= c->val[j];
+        len=getalen(ANY,c->val,j);  // get text, could be any type
+        if (len<0) return 0;
+
+        j+=skip(len);
+        if (OCT_comp(&FOID,SOID))
+        {
+            // if its the right one return
+            *flen=len;
+            return j;
+        }
+        j+=len;  // skip over it
+    }
+    *flen=0; /*****/
+    return 0;
+}
+
+// Find start date of certificate validity period
+int X509_find_start_date(octet *c,int start)
+{
+    int j,len;
+    j=start;
+
+    len=getalen(SEQ,c->val,j);
+    if (len<0) return 0;
+    j+=skip(len);
+
+    len=getalen(UTC,c->val,j);
+    if (len<0) return 0;
+    j+=skip(len);
+    return j;
+}
+
+// Find expiry date of certificate validity period
+int X509_find_expiry_date(octet *c,int start)
+{
+    int j,len;
+    j=start;
+
+    len=getalen(SEQ,c->val,j);
+    if (len<0) return 0;
+    j+=skip(len);
+
+    len=getalen(UTC,c->val,j);
+    if (len<0) return 0;
+    j+=skip(len)+len;
+
+    len=getalen(UTC,c->val,j);
+    if (len<0) return 0;
+    j+=skip(len);
+
+    return j;
+}
+
+void print_out(char *des,octet *c,int index,int len)
+{
+    int i;
+    printf("%s [",des);
+    for (i=0; i<len; i++)
+        printf("%c",c->val[index+i]);
+    printf("]\n");
+}
+
+void print_date(char *des,octet *c,int index)
+{
+    int i=index;
+    printf("%s [",des);
+    if (i==0) printf("]\n");
+    else printf("20%c%c-%c%c-%c%c %c%c:%c%c:%c%c]\n",c->val[i],c->val[i+1],c->val[i+2],c->val[i+3],c->val[i+4],c->val[i+5],c->val[i+6],c->val[i+7],c->val[i+8],c->val[i+9],c->val[i+10],c->val[i+11]);
+}
+
+
+#ifdef HAS_MAIN
+
+/* test driver program */
+// Sample Certs. Uncomment one CA cert and one example cert. Note that AMCL library must be built to support given curve.
+// Sample Certs all created using OpenSSL - see http://blog.didierstevens.com/2008/12/30/howto-make-your-own-cert-with-openssl/
+// Note - SSL currently only supports NIST curves. Howevever version 1.1.0 of OpenSSL now supports C25519
+
+#if CHOICE==C25519
+// ** CA is RSA 2048-bit based - for use with C25519 build of the library - assumes use of SHA256 in Certs
+
+char ca_b64[]="MIID6zCCAtOgAwIBAgIJALJxywTGMUA7MA0GCSqGSIb3DQEBCwUAMIGLMQswCQYDVQQGEwJJRTEQMA4GA1UECAwHSXJlbGFuZDEPMA0GA1UEBwwGRHVibGluMQ8wDQYDVQQKDAZNSVJBQ0wxDTALBgNVBAsMBGxhYnMxEzARBgNVBAMMCk1pa2UgU2NvdHQxJDAiBgkqhkiG9w0BCQEWFW1pa2Uuc2NvdHRAbWlyYWNsLmNvbTAeFw0xNjA2MzAxNzQyNDFaFw0yMTA2MzAxNzQyNDFaMIGLMQswCQYDVQQGEwJJRTEQMA4GA1UECAwHSXJlbGFuZDEPMA0GA1UEBwwGRHVibGluMQ8wDQYDVQQKDAZNSVJBQ0wxDTALBgNVBAsMBGxhYnMxEzARBgNVBAMMCk1pa2UgU2NvdHQxJDAiBgkqhkiG9w0BCQEWFW1pa2Uuc2NvdHRAbWlyYWNsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPCTPcPWgiI0ka5Czd0ZzW+gTaMEe9QW7FGu5+9fS6ALrCpdbxdwDX8+OQXZuQJpLYEAIq1pDh3fVQguH/jUM9gQQrS2Lmz3KhXC/J3yv85FRotCGv13ztapMedTy2IxzbtPvoQQc+IAlUPX6DtD8JqBoAstrlQUnkMChKztMGR2OERdjNzXmXm+KMMPlZzk+EvRwCornVA+SB5QAWj7y/3ISFo0y1WG8ewoQEx3HQYrjXbQP1VTdiLW7dHPQP86XKoTMtTBEYWuFhKB9ClCeu4Qqqxqa9UPIVfdro7SoZScCt+OX4KhzLnOCFupoLxE+yTDhDpYcCcmI1yglCv9DpMCAwEAAaNQME4wHQYDVR0OBBYEFFH18YEMoxms7121N/nQ+Wm3b5smMB8GA1UdIwQYMBaAFFH18YEMoxms7121N/nQ+Wm3b5smMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBALCUob0y2O4DSzsqG76yrtCxXWxDdgjSkHKzwFK62BzZK5EuCDJrVgCyoLX0SvYvoT9x0wtS+bxJ7TNEGn7Rkp5/iSQCUSF7sVRoHqzErk70xVKKDy5FS+zre8k08nJrtRg2u1PmY95NO1SE96BtUVLs+8rQuqEX283tqlmqE/SF2+lxOb0WaVrya4oCJfj/XT83pRTcd5w9i7huWltMbKbagkmlQ/5q9Ayp/Jh1lLXmxr+/xEbZ2xEop/y+mgVF0vLxap7R5toBA0Yk7vvirlYv0hZGqGi5lBc9VeUqm1H/7XCi5xRU3AtJ4QRk4Z1xUa4qAPKfiqlPKd1dVe3Ah3w=";
+
+// an ECC 255-bit CA-signed cert
+char cert_b64[]="MIICqjCCAZICCQCk9jKdJYtnjDANBgkqhkiG9w0BAQsFADCBizELMAkGA1UEBhMCSUUxEDAOBgNVBAgMB0lyZWxhbmQxDzANBgNVBAcMBkR1YmxpbjEPMA0GA1UECgwGTUlSQUNMMQ0wCwYDVQQLDARsYWJzMRMwEQYDVQQDDApNaWtlIFNjb3R0MSQwIgYJKoZIhvcNAQkBFhVtaWtlLnNjb3R0QG1pcmFjbC5jb20wHhcNMTYwNjMwMTc0NjQ4WhcNMTYwNzMwMTc0NjQ4WjCBjDELMAkGA1UEBhMCSUUxEDAOBgNVBAgMB0lyZWxhbmQxDzANBgNVBAcMBkR1YmxpbjEPMA0GA1UECgwGTUlSQUNMMQ0wCwYDVQQLDARsYWJzMRgwFgYDVQQDDA9LZWFsYW4gTWNDdXNrZXIxIDAeBgkqhkiG9w0BCQEWEWtlYWxhbkBtaXJhY2wuY29tMDkwFAYHKoZIzj0CAQYJKwYBBAHaRw8BAyEASiRQmhO9PP+SqodOhXYrnSlcyAOog63E6a4KLDFvAzEwDQYJKoZIhvcNAQELBQADggEBALByfCM/EhdqWBrEnDHtH2/U8xr1eSylHdcfnDSDR+X6KXH5rIJ/397lZQMHB6QSsEiVrWzfFDFPPjDN3xEDsZw09ZTT+L8Wi5P3UKR1gtawQCx3ciKEywAU1CU2dV05gvyebqIsbFUyH7jOlj6/1hIx9zaiLcoEex6D55MYQuWo664HF3CNdJFk1k4HF+fclRhyl4iryp0F9p0Wl5vyn96kg0NwaBZG860oCWDHZsjRq1JeSSaRf9CKNXWbQwjByeEcDphpprqmoVcI60cC0TvZZm1x4y7vjCXLD6uCDw3P7fnSp40yce64+IKUr8/cS+QYus58KHdLaLXsojZHL3c=";
+#endif
+
+#if CHOICE==NIST256
+
+// ** CA is RSA 2048-bit based - for use with NIST256 build of library - assumes use of SHA256 in Certs
+// RSA 2048 Self-Signed CA cert
+char ca_b64[]="MIIDuzCCAqOgAwIBAgIJAP44jcM1MOROMA0GCSqGSIb3DQEBCwUAMHQxCzAJBgNVBAYTAklFMRAwDgYDVQQIDAdJcmVsYW5kMQ8wDQYDVQQHDAZEdWJsaW4xITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEfMB0GCSqGSIb3DQEJARYQbXNjb3R0QGluZGlnby5pZTAeFw0xNTExMjYwOTUwMzlaFw0yMDExMjUwOTUwMzlaMHQxCzAJBgNVBAYTAklFMRAwDgYDVQQIDAdJcmVsYW5kMQ8wDQYDVQQHDAZEdWJsaW4xITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEfMB0GCSqGSIb3DQEJARYQbXNjb3R0QGluZGlnby5pZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANUs7/nri9J8zw8rW8JVszXP0ZqeLoQJaq2X28ebm8x5VT3okr9rnBjFjpx0YKQCAFQf8iSOOYuNpDvtZ/YpsjPbk2rg5sLY9G0eUMqrTuZ7moPSxnrXS5evizjD9Z9HqaqeNEYD3sPouPg+lhU1oAUQjUTJVFhEr1x0EnSEYbbrWtY9ZDSuZv+d4NIeqqPOYFd1yZc+LYZyQbAAQqwRLNPZH/rnIykLa6I7w7mGT7H6SBz2O09BtgpTHhalL40ecXa4ZOEze0xwzlc+mEFIrnmdadg3vQrJt42RVbo3LN6RfDIqUZOMOtQW/53pUR1lIpCwVWJTiOpmSEIEqhhjFq0CAwEAAaNQME4wHQYDVR0OBBYEFJrz6LHeT6FcjRahpUC3hAMxKRTCMB8GA1UdIwQYMBaAFJrz6LHeT6FcjRahpUC3hAMxKRTCMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBADqkqCYVa3X8XO9Ufu6XIUoZafFPRjSeJXvEIWqlbm7ixJZ2FPOvf2eMc5RCZYigNKhsxru5Ojw0lPcpa8DDmEsdZDf7p0vlmf7T7xH9gtoInh4DzgI8HRHFc8R/z2/jLX7nlLoopKX5yp7F1gRACg0pd4tGpQ6EnBNcYZZghFH9UIRDmx+vDlwDCu8vyRPt35orrEiI4XGq/QkvxxAb5YWxQ4i06064ULfyCI7suu3KoobdM1aAaA8zhpOOBXKbq+Wi9IGFe/wiEMHLmfHdt9CBTjIWb//IHji4RT05kCmTVrx97pb7EHafuL3L10mM5cpTyBWKnb4kMFtx9yw+S2U=";
+// an RSA 2048 CA-signed cert
+//char cert_b64[]="MIIDcjCCAloCAQEwDQYJKoZIhvcNAQELBQAwdDELMAkGA1UEBhMCSUUxEDAOBgNVBAgMB0lyZWxhbmQxDzANBgNVBAcMBkR1YmxpbjEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMR8wHQYJKoZIhvcNAQkBFhBtc2NvdHRAaW5kaWdvLmllMB4XDTE1MTEyNjEwMzQzMFoXDTE3MTEyNTEwMzQzMFowgYkxCzAJBgNVBAYTAklFMRAwDgYDVQQIDAdJcmVsYW5kMQ8wDQYDVQQHDAZEdWJsaW4xETAPBgNVBAoMCENlcnRpVm94MQ0wCwYDVQQLDARMYWJzMQ0wCwYDVQQDDARNSUtFMSYwJAYJKoZIhvcNAQkBFhdtaWtlLnNjb3R0QGNlcnRpdm94LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMIoxaQHFQzfyNChrw+3i7FjRFMHZ4zspkjkAcJW21LdBCqrxU+sdjyBoSFlrlafQOHshbrEP93AKX1bfaYbuV4fzq7OlRaLxaK+b+xrOJdewMI2WZ5OwEzj3onZATISogIoB6dTdzJ41NuxuMqQ/DqOnVrRA0SoIespbQhB8FGHBLw0hJATBzUk+bqOIt0HmnMp2EbYgtuG4lYINU/lD3Qt16SunUukWRLtxqJkioie+dkhP2zm+bOlSVmeQb4Wp8AI14OKkTfkdYC8qCxb5eabg90Q33rQUhNwRQHhHwopZwD/BgodasoSrPfwUlj0awh6y87eMGcik5Q/mjkCk5MCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAFrd7R/67ClkbLhpiX++6QTOa47siUAB9v+Qil9hZfhPNeeM589ixYkD4zH5pOK2B0ea+CXEKkanQ6lXx9KV86yS7fq6Yww7wO0diecusHd0+P82i46Tq0nm8nlsnAuhYoFRUGa2m2DkB1HSsB0ts8DjzFLySonFjSSLHDU0ox9/uFbJMzipy3ijAA4XM0N4jRrUfrmxpA7DOOsbEbGkvvB7VK9+s9PHE/4dJTwhSteplUnhxVFkkDo/JwaLx4/IEQRlCF3KEQ5s3AwRHnbrIjOY2yONxHBtJEp7QN5aOHruwvMNRNheCBPiQJyLitUsFGr4voANmobkrFgYtu0tRMQ==";
+// an ECC 256 CA-signed cert
+char cert_b64[]="MIICojCCAYoCAQMwDQYJKoZIhvcNAQELBQAwdDELMAkGA1UEBhMCSUUxEDAOBgNVBAgMB0lyZWxhbmQxDzANBgNVBAcMBkR1YmxpbjEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMR8wHQYJKoZIhvcNAQkBFhBtc2NvdHRAaW5kaWdvLmllMB4XDTE1MTEyNjEzNDcyOVoXDTE3MTEyNTEzNDcyOVowgYQxCzAJBgNVBAYTAklFMRAwDgYDVQQIDAdJcmVsYW5kMQ8wDQYDVQQHDAZEdWJsaW4xETAPBgNVBAoMCENlcnRpdm94MQ0wCwYDVQQLDARMYWJzMQ8wDQYDVQQDDAZtc2NvdHQxHzAdBgkqhkiG9w0BCQEWEG1zY290dEBpbmRpZ28uaWUwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATO2iZiQZsXxzwBKnufKfZcsctNXZ4PmfJm638PmX9DQ3Xdb+nD5VxiOakNcB9xf5im8CriiOF5Z/7yPGyzUMbdMA0GCSqGSIb3DQEBCwUAA4IBAQAK5fMgGCCiPts8hMUZvYDpu8hd7qtPKPBc10QUccHb7PGrhqf/Ex2Gpj1aaURmx7SGZG0HX97LtkdW8KQpEoyaa60r7cjVA589TznxXKSGg5ggVoFJNpuZUm7VcolLjwIgTxtGbPzrvVMiZ4cl4PwFePXVKTl4f8XkOFX5gLmVSuCf729lEBmpx3IzqGmTjmnBixaApUElOKVeL7hiUKP3TqMUxZN+QNJBq4Mh9K9h4Sks2oneLwBwhMqQvpmcOb/7SucJn5N0IgJoGaMbfX0oCJJID1NSbagUSbFD1XciR2Ng9VtvnRP+htmEQ7jtww8phFdrWt5M5zPGOHUppqDx";
+
+// ** CA is ECC 256 based  - for use with NIST256 build of library
+// ECC 256 Self-Signed CA cert
+//char ca_b64[]="MIIB7TCCAZOgAwIBAgIJANp4nGS/VYj2MAoGCCqGSM49BAMCMFMxCzAJBgNVBAYTAklFMRAwDgYDVQQIDAdJcmVsYW5kMQ8wDQYDVQQHDAZEdWJsaW4xITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0xNTExMjYxMzI0MTBaFw0yMDExMjUxMzI0MTBaMFMxCzAJBgNVBAYTAklFMRAwDgYDVQQIDAdJcmVsYW5kMQ8wDQYDVQQHDAZEdWJsaW4xITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABPb6IjYNKyfbEtL1aafzW1jrn6ALn3PnGm7AyX+pcvwG0GKmb3Z/uHzhT4GysNE0/GB1n4Y/mrORQIm2X98rRs6jUDBOMB0GA1UdDgQWBBSfXUNkgJVklIhuXq4DCnVYhsdzwDAfBgNVHSMEGDAWgBSfXUNkgJVklIhuXq4DCnVYhsdzwDAMBgNVHRMEBTADAQH/MAoGCCqGSM49BAMCA0gAMEUCIQDrZJ1tshwTl/jabU2i49EOgbWe0ZgE3QZywJclf5IVwwIgVmz79AAf7e098lyrOKYAqbwjHVyMZGfmkNNGIuIhp/Q=";
+// an ECC 256 CA-signed cert
+//char cert_b64[]="MIIBvjCCAWQCAQEwCgYIKoZIzj0EAwIwUzELMAkGA1UEBhMCSUUxEDAOBgNVBAgMB0lyZWxhbmQxDzANBgNVBAcMBkR1YmxpbjEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMB4XDTE1MTEyNjEzMjc1N1oXDTE3MTEyNTEzMjc1N1owgYIxCzAJBgNVBAYTAklFMRAwDgYDVQQIDAdJcmVsYW5kMQ8wDQYDVQQHDAZEdWJsaW4xETAPBgNVBAoMCENlcnRpdm94MQ0wCwYDVQQLDARMYWJzMQ0wCwYDVQQDDARtaWtlMR8wHQYJKoZIhvcNAQkBFhBtc2NvdHRAaW5kaWdvLmllMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEY42H52TfWMLueKB1o2Sq8uKaKErbHJ2GRAxrnJdNxex0hxZF5FUx7664BbPUolKhpvKTnJxDq5/gMqXzpKgR6DAKBggqhkjOPQQDAgNIADBFAiEA0ew08Xg32g7BwheslVKwXo9XRRx4kygYha1+cn0tvaUCIEKCEwnosZlAckjcZt8aHN5zslE9K9Y7XxTErTstthKc";
+// an RSA 2048 CA-signed cert
+//char cert_b64[]="MIICiDCCAi4CAQIwCgYIKoZIzj0EAwIwUzELMAkGA1UEBhMCSUUxEDAOBgNVBAgMB0lyZWxhbmQxDzANBgNVBAcMBkR1YmxpbjEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMB4XDTE1MTEyNjEzMzcwNVoXDTE3MTEyNTEzMzcwNVowgYExCzAJBgNVBAYTAklFMQ8wDQYDVQQIDAZJZWxhbmQxDzANBgNVBAcMBkR1YmxpbjERMA8GA1UECgwIQ2VydGl2b3gxDTALBgNVBAsMBExhYnMxDTALBgNVBAMMBE1pa2UxHzAdBgkqhkiG9w0BCQEWEG1zY290dEBpbmRpZ28uaWUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCjPBVwmPg8Gwx0+8xekmomptA0BDwS7NUfBetqDqNMNyji0bSe8LAfpciU7NW/HWfUE1lndCqSDDwnMJmwC5e3GAl/Bus+a+z8ruEhWGbn95xrHXFkOawbRlXuS7UcEQCvPr8KQHhNsg4cyV7Hn527CPUl27n+WN8/pANo01cTN/dQaK87naU0Mid09vktlMKSN0zyJOnc5CsaTLs+vCRKJ9sUL3d4IQIA2y7gvrTe+iY/QI26nqhGpNWYyFkAdy9PdHUEnDI6JsfF7jFh37yG7XEgDDA3asp/oi1T1+ZoASj2boL++opdqCzDndeWwzDWAWuvJ9wULd80ti6x737ZAgMBAAEwCgYIKoZIzj0EAwIDSAAwRQIgCDwgl98+9moBo+etaLt8MvB/z5Ti6i9neRTZkvoFl7YCIQDq//M3OB757fepErRzIQo3aFAFYjOooi6WdSqP3XqGIg==";
+
+#endif
+
+#if CHOICE==NIST384
+
+// ** CA is RSA 3072-bit based  - for use with NIST384 build of library - assumes use of SHA384 in Certs
+// RSA 3072 Self-Signed CA cert
+char ca_b64[]="MIIElzCCAv+gAwIBAgIJAJA+8OyEeK4FMA0GCSqGSIb3DQEBDAUAMGIxCzAJBgNVBAYTAklFMRAwDgYDVQQIDAdJcmVsYW5kMQ8wDQYDVQQHDAZEdWJsaW4xITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDENMAsGA1UEAwwETWlrZTAeFw0xNTExMjYxNDQ0MDBaFw0yMDExMjUxNDQ0MDBaMGIxCzAJBgNVBAYTAklFMRAwDgYDVQQIDAdJcmVsYW5kMQ8wDQYDVQQHDAZEdWJsaW4xITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDENMAsGA1UEAwwETWlrZTCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBANvNO8ahsanxzqwkp3A3bujwObJoP3xpOiAAxwGbW867wx4EqBjPRZP+Wcm9Du6e4Fx9U7tHrOLocIUUBcRrmxUJ7Z375hX0cV9yuoYPNv0o2klJhB8+i4YXddkOrSmDLV4r46Ytt1/gjImziat6ZJALdd/uIuhaXwjzy1fFqSEBpkzhrFwFP9MG+5CgbRQed+YxZ10l/rjk+h3LKq9UFsxRCMPYhBFgmEKAVTMnbTfNNxawTRCKtK7nxxruGvAEM+k0ge5rvybERQ0NxtizefBSsB3Q6QVZOsRJiyC0HQhE6ZBHn4h3A5nHUZwPeh71KShw3uMPPB3Kp1pb/1Euq8azyXSshEMPivvgcGJSlm2b/xqsyrT1tie82MqB0APYAtbx3i5q8p+rD143NiNO8fzCq/J+EV82rVyvqDxf7AaTdJqDbZmnFRbIcrLcQdigWZdSjc+WxrCeOtebRmRknuUmetsCUPVzGv71PLMUNQ2qEiq8KGWmnMBJYVMl96bPxwIDAQABo1AwTjAdBgNVHQ4EFgQUsSjrHeZ5TNI2tMcQd6wUnFpU8DcwHwYDVR0jBBgwFoAUsSjrHeZ5TNI2tMcQd6wUnFpU8DcwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQwFAAOCAYEADlnC1gYIHpVf4uSuBpYNHMO324hhGajHNraHYQAoYc0bW4OcKi0732ib5CHDrV3LCxjxF4lxZVo61gatg5LnfJYldXc0vP0GQRcaqC6lXlLb8ZJ0O3oPgZkAqpzc+AQxYW1wFxbzX8EJU0stSwAuxkgs9bwg8tTxIhDutrcjQl3osnAqGDyM+7VAG5QLRMzxiZumyD7s/xBUOa+L6OKXf4QRr/SH/rPU8H+ENaNkv4PApSVzCgTBPOFBIzqEuO4hcQI0laUopsp2kK1w6wYB5oY/rR/O6lNNfB2WEtfdIhdbQru4cUE3boKerM8Mjd21RuerAuK4X8cbDudHIFsaopGSNuzZwPo/bu0OsmZkORxvdjahHJ0G3/6jM6nEDoIy6mXUCGOUOMhGQKCa8TYlZdPKz29QIxk6HA1wCA38MxUo/29Z7oYw27Mx3x8Gcr+UA4vc+oBN3IEzRmhRZKAYQ10MhYPx3NmYGZBDqHvT06oG5hysTCtlVzx0Tm+o01JQ";
+// an RSA 3072 CA-signed cert
+//char cert_b64[]="MIIEWzCCAsMCAQYwDQYJKoZIhvcNAQEMBQAwYjELMAkGA1UEBhMCSUUxEDAOBgNVBAgMB0lyZWxhbmQxDzANBgNVBAcMBkR1YmxpbjEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMQ0wCwYDVQQDDARNaWtlMB4XDTE1MTEyNjE0NDY0MloXDTE3MTEyNTE0NDY0MlowgYQxCzAJBgNVBAYTAklFMRAwDgYDVQQIDAdJcmVsYW5kMQ8wDQYDVQQHDAZEdWJsaW4xETAPBgNVBAoMCENlcnRpdm94MQ0wCwYDVQQLDARMYWJzMQ8wDQYDVQQDDAZtc2NvdHQxHzAdBgkqhkiG9w0BCQEWEG1zY290dEBpbmRpZ28uaWUwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQC6SrDiE4BpTEks1YpX209q8iH0dfvhGO8hi1rGYFYnz+eeiOvPdXiCdIPVPbGwxQGMEnZQV1X0KupYJw3LR2EsXhN4LZBxnQZmDvUXsTU+Ft/CKZUxVoXpNMxzwl70RC6XeUpPxvdPXa78AnfLL/DsOKsxCfNaKYZZ6G53L6Y69+HrCbyM7g2KrZ9/K/FXS1veMpRj9EbA6Mcdv1TUDNK2fTDV952AQO3kC3+PqywdVgPvntraAoQomrni+tcFW7UXe2Sk7DRcF/acBSuo2UtP3m9UWNL+8HOXvtRqmhns55Vj4DxKuPln759UBS7WZ11apCvC3BvCHR/k3WRf9PQWnW2cmT73/kEShvTRi8h7F9RWvYTEF1MuwSVy+l51q8O3rJU4XxnLm/YbtIGXZUf5Rqb0985zQkA+6rip/OSc8X5a3OV3kp38U7tXJ5sqBMg9RdIIz42cmiRLG5NYSj0/T6zjYEdwj3SYEBoPN/7UGSmhu8fdxS7JYPNpOsgeiu8CAwEAATANBgkqhkiG9w0BAQwFAAOCAYEAyxxEg0hWLFuN2fiukX6vqzSDx5Ac8w1JI4W/bamRd7iDZfHQYqyPDZi9s07I2PcGbByj2oqoyGiIEBLbsljdIEF4D229h2kisn1gA9O+0IM44EgjhBTUoNDgC+SbfJrXlU2GZ1XI3OWjbK7+1wiv0NaBShbbiPgSdjQBP8S+9W7lyyIrZEM1J7maBdepie1BS//DUDmpQzEi0UlB1J+HmQpyZsnT97J9uIPKsK4t2/+iOiknl6iS4GzAQKMLqj2yIBRf/O44ZZ6UZIKLtI4PCVS/8H5Lrg3AC0kr4ZkPAXzefUiTwyLVkqYSxSSTvtb3BpgOxIbmA6juFid0rvUyjN4fuDQkxl3PZyQwIHjpz33HyKrmo4BZ8Dg4JT8LCsQgd0AaD3r0QOS5FdLhkb+rD8EMSsCoOCEtPI6lqLJCrGOQWj7zbcUdPOEsczWMI9hSfK3u/P9+gOUBUFkb0gBIn3WvNuHifIHpsZ5bzbR+SGtu5Tgc7CCCPyNgz1Beb247";
+// an ECC 384 CA-signed cert
+char cert_b64[]="MIIDCDCCAXACAQcwDQYJKoZIhvcNAQEMBQAwYjELMAkGA1UEBhMCSUUxEDAOBgNVBAgMB0lyZWxhbmQxDzANBgNVBAcMBkR1YmxpbjEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMQ0wCwYDVQQDDARNaWtlMB4XDTE1MTEyNjE1MzU1M1oXDTE3MTEyNTE1MzU1M1owYDELMAkGA1UEBhMCSUUxEDAOBgNVBAgMB0lyZWxhbmQxDzANBgNVBAcMBkR1YmxpbjEQMA4GA1UECgwHQ2VydGl2bzENMAsGA1UECwwETGFiczENMAsGA1UEAwwEbWlrZTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJ1J+FT5mxxYEM4aYKM0CvZHmh8JFXzoBmzibabrvyTz79+1QOrR+6MEEsKtmJIYPJi+GsQ0PmjF2HmJncM1zeQh7DQYJf2Xc8p5Vjd8//6YREBVfN3UIyrl87MSucy+mjANBgkqhkiG9w0BAQwFAAOCAYEAmuwa64+K1qlCELpcnCyWwMhSb+Zsw0Hh6q/BfxalZhsX1UFEwE9nHoVJcokaEEYF4u4AYXU5rdysRHxYBfgMbohguTT7sJwCfve2JqpqvhQOkGDG1DB4Ho4y7NPPYB2+UMd7JMD0TOcHXdgQ8FtAE0ClD8VkW0gAC0lCrbQbynfLoUjIWqg3w2g79hvdZPgRt208nFiHuezynOaEFePoXl8CxHInsxAnMaJn2fEs5/QH67pwD65mPdNFsvlr0zdzYcceqEmEHpRAXFOQAJtffGjWAGGX/CsghLuqlpdCiTGA1B53XoXKJvArr/kHpTNMsU1NnkQIHZ5n4USCo4QgL6n9nwem7U2mYBYjmxPi5Y3JJnTZz4zUnv0bD0vSwoivnFZox9H6qTAkeIX1ojJ2ujxWHNOMvOFb6nU2gqNZj2vYcO38OIrK9gwM9lm4FF20YBufh+WOzQthrHJv0YuQt3NuDQEMkvz+23YvzZlr+e2XqDlMhyR01Kk0MXeLGGcv";
+
+// ** CA is ECC 384 based - - for use with NIST384 build of library - assumes use of SHA384 in Certs
+// ECC 384 Self-Signed CA Cert
+//char ca_b64[]="MIICSTCCAc6gAwIBAgIJAIwHpOFSZLXnMAoGCCqGSM49BAMDMGIxCzAJBgNVBAYTAklFMRAwDgYDVQQIDAdJcmVsYW5kMQ8wDQYDVQQHDAZEdWJsaW4xITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDENMAsGA1UEAwwEbWlrZTAeFw0xNTExMjYxNTQ0NTlaFw0yMDExMjUxNTQ0NTlaMGIxCzAJBgNVBAYTAklFMRAwDgYDVQQIDAdJcmVsYW5kMQ8wDQYDVQQHDAZEdWJsaW4xITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDENMAsGA1UEAwwEbWlrZTB2MBAGByqGSM49AgEGBSuBBAAiA2IABOEPMYBqzIn1hJAMZ0aEVxQ08gBF2aSfWtEJtmKj64014w7VfWdeFQSIMP9SjmhatFbAvxep8xgcwbeAobGTqCgUp+0EdFZR1ktKSND/S+UDU1YSNCFRvlNTJ6YmXUkW36NQME4wHQYDVR0OBBYEFDQxIZoKNniNuW91UMJ1KWEjs045MB8GA1UdIwQYMBaAFDQxIZoKNniNuW91UMJ1KWEjs045MAwGA1UdEwQFMAMBAf8wCgYIKoZIzj0EAwMDaQAwZgIxANbml6sp5A92qQiCM/OtBf+TbXpSpIO83TuNP9V2lsphp0CEX3KwAuqBXB95m9/xWAIxAOXAT2LqieSbUh4fpxcdaeY01RoGtD2AQch1a6BuIugcQqTfqLcXy7D51R70R729sA==";
+// an ECC 384 CA-signed cert
+//char cert_b64[]="MIICCjCCAZACAQgwCgYIKoZIzj0EAwMwYjELMAkGA1UEBhMCSUUxEDAOBgNVBAgMB0lyZWxhbmQxDzANBgNVBAcMBkR1YmxpbjEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMQ0wCwYDVQQDDARtaWtlMB4XDTE1MTEyNjE1NTIxMFoXDTE3MTEyNTE1NTIxMFowgYIxCzAJBgNVBAYTAklFMRAwDgYDVQQIDAdJcmVsYW5kMQ8wDQYDVQQHDAZEdWJsaW4xETAPBgNVBAoMCENlcnRpdm94MQ0wCwYDVQQLDARMYWJzMQ0wCwYDVQQDDARtaWtlMR8wHQYJKoZIhvcNAQkBFhBtc2NvdHRAaW5kaWdvLmllMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEf2Qm6jH2U+vhAApsMqH9gzGCH8rk+mUwFSD3Uud4NiyPBqrJRC1eetVvr3cYb6ucDTa15km6QKvZZrsRW+Z4ZpryoEE6esmD4XPLrtrOtoxtxFNRhiMmT/M9zcrfMJC5MAoGCCqGSM49BAMDA2gAMGUCMF0x6PAvvnJR3riZdUPC4OWFC2K3eiz3QuLCdFOZVIqX7mkLftdS8BtzusXWMMgFCQIxALJNMKLs39P9wYQHu1C+v9ieltQr20C+WVYxqUvgL/KTdxd9dzc3wseZRDT1CydqOA==";
+// an RSA 3072 CA-signed cert
+//char cert_b64[]="MIIDFjCCAp4CAQkwCgYIKoZIzj0EAwMwYjELMAkGA1UEBhMCSUUxEDAOBgNVBAgMB0lyZWxhbmQxDzANBgNVBAcMBkR1YmxpbjEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMQ0wCwYDVQQDDARtaWtlMB4XDTE1MTEyNjE2MTYwNloXDTE3MTEyNTE2MTYwNlowYzELMAkGA1UEBhMCSUUxEDAOBgNVBAgMB0lyZWxhbmQxDzANBgNVBAcMBkR1YmxpbjERMA8GA1UECgwIQ2VydGl2b3gxDTALBgNVBAsMBGxhYnMxDzANBgNVBAMMBmtlYWxhbjCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAK5QhVjR+UGt3ZWPSGicpviqaOhxXmmvOepdl5Seqr+Iweb3IuEDgtHGwrw/EEgWlKPfS/2LW9ncptdNbVQh7+2rojj7ZtedrAK5p7I9b22f2U3sSHIqjtTT0BjqzL0qEwy/ATqbf93Tcr3yT0Ygh3yzbvn4zodrWQZK8kkN3PQKkiHBCuIxo+8MlTs8d99dl1hbJ84MYZuPmhrkB4oLEAt8+srtL+a4Yd0wPhuCYrLjBnYkD9TlcWLWWh8/iwXiznrY8gQsXSveQNzQjcmHilZrTlTL2dnyI2v7BAXXHSwo6UeES0n064fnYTr3JB0GArMcty6RD3E7xr64HNzzTE2+8cDxufNvU0tq2Z72oZ9cAReHUL5P6mLfORI+AhtCHrXGJch/F07ZX9h8UFpzok8NK5++Q7lHKuezTYRRPlDL5hDB3BUpBwvILdqujcbNil04cuLRBNT/WgqRXEBRjlHLgZaLChFV2VSJ9Z1Uke2lfm5X2O0XPQLhjMSiuvr4HwIDAQABMAoGCCqGSM49BAMDA2YAMGMCLxHSQAYP2EsuIpR4TzDDSIlsw4BBsD7W0ZfH91v9J0j5UWQJD/yNjMtyA2Qlkq/0AjB+SJQbLgycNJH5SnR/X5wx26/62ln9s0swUtlCYVtNzyEQ3YRHSZbmTbh16RUT7Ak=";
+
+#endif
+
+#if CHOICE==NIST521
+
+// ** CA is ECC 521 based - - for use with NIST521 build of library - assumes use of SHA512 in Certs
+// ECC 521 Self-Signed CA Cert
+char ca_b64[]="MIIC+TCCAlqgAwIBAgIJAKlppiHsRpY8MAoGCCqGSM49BAMEMIGUMQswCQYDVQQGEwJJRTEQMA4GA1UECAwHSXJlbGFuZDEPMA0GA1UEBwwGRHVibGluMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxDTALBgNVBAsMBExhYnMxDzANBgNVBAMMBm1zY290dDEfMB0GCSqGSIb3DQEJARYQbXNjb3R0QGluZGlnby5pZTAeFw0xNTEyMDExMzE5MjZaFw0yMDExMzAxMzE5MjZaMIGUMQswCQYDVQQGEwJJRTEQMA4GA1UECAwHSXJlbGFuZDEPMA0GA1UEBwwGRHVibGluMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxDTALBgNVBAsMBExhYnMxDzANBgNVBAMMBm1zY290dDEfMB0GCSqGSIb3DQEJARYQbXNjb3R0QGluZGlnby5pZTCBmzAQBgcqhkjOPQIBBgUrgQQAIwOBhgAEAKUj6Qa4Vr1vyango8XHlLIIEzY9IVppdpGUrMlNfo0Spu+AXGhnluwJTZXOYLi8jSIPEAL7vuwS5H6uPPIz1QWXALRETVYAQfK0pIfPHq+edTHVTXMcAUpdNla2d4LwYO7HpkSQFHd7aaDN3yVhSL2J0LBLgy0wGkEHuyK1O2r0xNu6o1AwTjAdBgNVHQ4EFgQU966PLshKffU/NRCivMmNq8RiRkAwHwYDVR0jBBgwFoAU966PLshKffU/NRCivMmNq8RiRkAwDAYDVR0TBAUwAwEB/zAKBggqhkjOPQQDBAOBjAAwgYgCQgHkLczeTWXq5BfY0bsTOSNU8bYy39OhiQ8wr5rlXY0zOg0fDyokueL4dhkXp8FjbIyUfQBY5OMxjtcn2p+cXU+6MwJCAci61REgxZvjpf1X8pGeSsOKa7GhfsfVnbQm+LQmjVmhMHbVRkQ4h93CENN4MH/86XNozO9USh+ydTislAcXvCb0";
+// an ECC 521 CA-signed cert
+char cert_b64[]="MIICZjCCAccCAQMwCgYIKoZIzj0EAwQwgZQxCzAJBgNVBAYTAklFMRAwDgYDVQQIDAdJcmVsYW5kMQ8wDQYDVQQHDAZEdWJsaW4xITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDENMAsGA1UECwwETGFiczEPMA0GA1UEAwwGbXNjb3R0MR8wHQYJKoZIhvcNAQkBFhBtc2NvdHRAaW5kaWdvLmllMB4XDTE1MTIwMTEzMjkxN1oXDTE3MTEzMDEzMjkxN1owYTELMAkGA1UEBhMCSUUxEDAOBgNVBAgMB0lyZWxhbmQxDzANBgNVBAcMBkR1YmxpbjERMA8GA1UECgwIQ2VydGlWb3gxDTALBgNVBAsMBExhYnMxDTALBgNVBAMMBE1pa2UwgZswEAYHKoZIzj0CAQYFK4EEACMDgYYABAAva/N4kP2LMSGJZ5tvULlfdNx2M/+xYeCrQkuFmY8sG+mdcUAaSx819fztn2jz1nfdTJnuj79AhfUOL8hlTW14BwErp3DnqWa7Y/rpSJP+AsnJ2bZg4yGUDfVy/Q0AQychSzJm2oGRfdliyBIc+2SoQJ/Rf0ZVKVJ5FfRbWUUiKqYUqjAKBggqhkjOPQQDBAOBjAAwgYgCQgFE1Y7d9aBdxpZqROtkdVNG8XBCTSlMX0fISWkSM8ZEiQfYf7YgXzLjk8wHnv04Mv6kmAuV0V1AHs2M0/753CYEfAJCAPZo801McsGe+3jYALrFFw9Wj7KQC/sFEJ7/I+PYyJtrlfTTqmV0IFKdJzjEsk7ic+Gd4Nbs6kIe1GyYbrcyC4wT";
+
+#endif
+
+char io[5000];
+octet IO= {0,sizeof(io),io};
+
+#define MAXMODBYTES 72
+#define MAXFFLEN 16
+
+char sig[MAXMODBYTES*MAXFFLEN];
+octet SIG= {0,sizeof(sig),sig};
+
+char r[MAXMODBYTES];
+octet R= {0,sizeof(r),r};
+
+char s[MAXMODBYTES];
+octet S= {0,sizeof(s),s};
+
+char cakey[MAXMODBYTES*MAXFFLEN];
+octet CAKEY= {0,sizeof(cakey),cakey};
+
+char certkey[MAXMODBYTES*MAXFFLEN];
+octet CERTKEY= {0,sizeof(certkey),certkey};
+
+char h[5000];
+octet H= {0,sizeof(h),h};
+
+char hh[5000];
+octet HH= {0,sizeof(hh),hh};
+
+char hp[RFS];
+octet HP= {0,sizeof(hp),hp};
+
+
+int main()
+{
+    int res,len,sha;
+    int c,ic;
+    rsa_public_key PK;
+    pktype st,ca,pt;
+
+    printf("First check signature on self-signed cert and extract CA public key\n");
+    OCT_frombase64(&IO,ca_b64);
+    printf("CA Self-Signed Cert= \n");
+    OCT_output(&IO);
+    printf("\n");
+
+    st=X509_extract_cert_sig(&IO,&SIG); // returns signature type
+
+    if (st.type==0)
+    {
+        printf("Unable to extract cert signature\n");
+        return 0;
+    }
+
+    if (st.type==ECC)
+    {
+        OCT_chop(&SIG,&S,SIG.len/2);
+        OCT_copy(&R,&SIG);
+        printf("ECC SIG= \n");
+        OCT_output(&R);
+        OCT_output(&S);
+        printf("\n");
+    }
+
+    if (st.type==RSA)
+    {
+        printf("RSA SIG= \n");
+        OCT_output(&SIG);
+        printf("\n");
+    }
+
+    if (st.hash==H256) printf("Hashed with SHA256\n");
+    if (st.hash==H384) printf("Hashed with SHA384\n");
+    if (st.hash==H512) printf("Hashed with SHA512\n");
+
+// Extract Cert from signed Cert
+
+    c=X509_extract_cert(&IO,&H);
+
+    printf("\nCert= \n");
+    OCT_output(&H);
+    printf("\n");
+
+// show some details
+    printf("Issuer Details\n");
+    ic=X509_find_issuer(&H);
+    c=X509_find_entity_property(&H,&ON,ic,&len);
+    print_out("owner=",&H,c,len);
+    c=X509_find_entity_property(&H,&CN,ic,&len);
+    print_out("country=",&H,c,len);
+    c=X509_find_entity_property(&H,&EN,ic,&len);
+    print_out("email=",&H,c,len);
+    printf("\n");
+
+    ca=X509_extract_public_key(&H,&CAKEY);
+
+    if (ca.type==0)
+    {
+        printf("Not supported by library\n");
+        return 0;
+    }
+    if (ca.type!=st.type)
+    {
+        printf("Not self-signed\n");
+    }
+
+    if (ca.type==ECC)
+    {
+        printf("EXTRACTED ECC PUBLIC KEY= \n");
+        OCT_output(&CAKEY);
+    }
+    if (ca.type==RSA)
+    {
+        printf("EXTRACTED RSA PUBLIC KEY= \n");
+        OCT_output(&CAKEY);
+    }
+    printf("\n");
+
+// Cert is self-signed - so check signature
+
+    printf("Checking Self-Signed Signature\n");
+    if (ca.type==ECC)
+    {
+        if (ca.curve!=CHOICE)
+        {
+            printf("Curve is not supported\n");
+            return 0;
+        }
+        res=ECP_PUBLIC_KEY_VALIDATE(1,&CAKEY);
+        if (res!=0)
+        {
+            printf("ECP Public Key is invalid!\n");
+            return 0;
+        }
+        else printf("ECP Public Key is Valid\n");
+
+        sha=0;
+
+        if (st.hash==H256) sha=SHA256;
+        if (st.hash==H384) sha=SHA384;
+        if (st.hash==H512) sha=SHA512;
+        if (st.hash==0)
+        {
+            printf("Hash Function not supported\n");
+            return 0;
+        }
+
+        if (ECPVP_DSA(sha,&CAKEY,&H,&R,&S)!=0)
+        {
+            printf("***ECDSA Verification Failed\n");
+            return 0;
+        }
+        else
+            printf("ECDSA Signature/Verification succeeded \n");
+    }
+
+    if (ca.type==RSA)
+    {
+        PK.e=65537; // assuming this!
+        FF_fromOctet(PK.n,&CAKEY,FFLEN);
+
+        sha=0;
+
+        if (st.hash==H256) sha=SHA256;
+        if (st.hash==H384) sha=SHA384;
+        if (st.hash==H512) sha=SHA512;
+        if (st.hash==0)
+        {
+            printf("Hash Function not supported\n");
+            return 0;
+        }
+        PKCS15(sha,&H,&HP);
+
+        RSA_ENCRYPT(&PK,&SIG,&HH);
+
+        if (OCT_comp(&HP,&HH))
+            printf("RSA Signature/Verification succeeded \n");
+        else
+        {
+            printf("***RSA Verification Failed\n");
+            return 0;
+        }
+    }
+
+    printf("\nNext check CA signature on cert, and extract public key\n");
+
+    OCT_frombase64(&IO,cert_b64);
+    printf("Example Cert= \n");
+    OCT_output(&IO);
+    printf("\n");
+
+    st=X509_extract_cert_sig(&IO,&SIG);
+
+    if (st.type==0)
+    {
+        printf("Unable to check cert signature\n");
+        return 0;
+    }
+
+    if (st.type==ECC)
+    {
+        OCT_chop(&SIG,&S,SIG.len/2);
+        OCT_copy(&R,&SIG);
+        printf("SIG= \n");
+        OCT_output(&R);
+
+        OCT_output(&S);
+
+        printf("\n");
+    }
+
+    if (st.type==RSA)
+    {
+        printf("SIG= \n");
+        OCT_output(&SIG);
+        printf("\n");
+    }
+
+    c=X509_extract_cert(&IO,&H);
+
+    printf("Cert= \n");
+    OCT_output(&H);
+    printf("\n");
+
+    printf("Subject Details\n");
+    ic=X509_find_subject(&H);
+    c=X509_find_entity_property(&H,&ON,ic,&len);
+    print_out("owner=",&H,c,len);
+    c=X509_find_entity_property(&H,&CN,ic,&len);
+    print_out("country=",&H,c,len);
+    c=X509_find_entity_property(&H,&EN,ic,&len);
+    print_out("email=",&H,c,len);
+    printf("\n");
+
+    ic=X509_find_validity(&H);
+    c=X509_find_start_date(&H,ic);
+    print_date("start date= ",&H,c);
+    c=X509_find_expiry_date(&H,ic);
+    print_date("expiry date=",&H,c);
+    printf("\n");
+
+    pt=X509_extract_public_key(&H,&CERTKEY);
+
+    if (pt.type==0)
+    {
+        printf("Not supported by library\n");
+        return 0;
+    }
+
+    if (pt.type==ECC)
+    {
+        printf("EXTRACTED ECC PUBLIC KEY= \n");
+        OCT_output(&CERTKEY);
+    }
+    if (pt.type==RSA)
+    {
+        printf("EXTRACTED RSA PUBLIC KEY= \n");
+        OCT_output(&CERTKEY);
+    }
+
+    printf("\n");
+
+    /* Check CA signature */
+
+    if (ca.type==ECC)
+    {
+        printf("Checking CA's ECC Signature on Cert\n");
+        res=ECP_PUBLIC_KEY_VALIDATE(1,&CAKEY);
+        if (res!=0)
+            printf("ECP Public Key is invalid!\n");
+        else printf("ECP Public Key is Valid\n");
+
+        sha=0;
+
+        if (st.hash==H256) sha=SHA256;
+        if (st.hash==H384) sha=SHA384;
+        if (st.hash==H512) sha=SHA512;
+        if (st.hash==0)
+        {
+            printf("Hash Function not supported\n");
+            return 0;
+        }
+
+        if (ECPVP_DSA(sha,&CAKEY,&H,&R,&S)!=0)
+            printf("***ECDSA Verification Failed\n");
+        else
+            printf("ECDSA Signature/Verification succeeded \n");
+    }
+
+    if (ca.type==RSA)
+    {
+        printf("Checking CA's RSA Signature on Cert\n");
+        PK.e=65537; // assuming this!
+        FF_fromOctet(PK.n,&CAKEY,FFLEN);
+
+        sha=0;
+
+        if (st.hash==H256) sha=SHA256;
+        if (st.hash==H384) sha=SHA384;
+        if (st.hash==H512) sha=SHA512;
+        if (st.hash==0)
+        {
+            printf("Hash Function not supported\n");
+            return 0;
+        }
+        PKCS15(sha,&H,&HP);
+
+        RSA_ENCRYPT(&PK,&SIG,&HH);
+
+        if (OCT_comp(&HP,&HH))
+            printf("RSA Signature/Verification succeeded \n");
+        else
+            printf("***RSA Verification Failed\n");
+
+    }
+
+    return 0;
+}
+
+#endif
diff --git a/version22/c/x509.h b/version22/c/x509.h
new file mode 100644
index 0000000..b0f0941
--- /dev/null
+++ b/version22/c/x509.h
@@ -0,0 +1,113 @@
+/*
+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.
+*/
+
+/* AMCL x509 header file */
+
+/**
+ * @file x509.h
+ * @author Mike Scott and Kealan McCusker
+ * @date 19th May 2015
+ * @brief X509 function Header File
+ *
+ * defines structures
+ * declares functions
+ *
+ */
+
+#ifndef X509_H
+#define X509_H
+
+/**
+ * @brief Public key type
+ */
+typedef struct
+{
+    int type;  /**< signature type (ECC or RSA) */
+    int hash;  /**< hash type */
+    int curve; /**< elliptic curve used  */
+} pktype;
+
+
+/* X.509 functions */
+/** @brief Extract certificate signature
+ *
+	@param c an X.509 certificate
+	@param s the extracted signature
+	@return 0 on failure, or indicator of signature type (ECC or RSA)
+
+*/
+extern pktype X509_extract_cert_sig(octet *c,octet *s);
+/** @brief
+ *
+	@param sc a signed certificate
+	@param c the extracted certificate
+	@return 0 on failure
+*/
+extern int X509_extract_cert(octet *sc,octet *c);
+/** @brief
+ *
+	@param c an X.509 certificate
+	@param k the extracted key
+	@return 0 on failure, or indicator of public key type (ECC or RSA)
+*/
+extern pktype X509_extract_public_key(octet *c,octet *k);
+/** @brief
+ *
+	@param c an X.509 certificate
+	@return 0 on failure, or pointer to issuer field in cert
+*/
+extern int X509_find_issuer(octet *c);
+/** @brief
+ *
+	@param c an X.509 certificate
+	@return 0 on failure, or pointer to validity field in cert
+*/
+extern int X509_find_validity(octet *c);
+/** @brief
+ *
+	@param c an X.509 certificate
+	@return 0 on failure, or pointer to subject field in cert
+*/
+extern int X509_find_subject(octet *c);
+/** @brief
+ *
+	@param c an X.509 certificate
+	@param S is OID of property we are looking for
+	@param s is a pointer to the section of interest in the cert
+	@param f is pointer to the length of the property
+	@return 0 on failure, or pointer to the property
+*/
+extern int X509_find_entity_property(octet *c,octet *S,int s,int *f);
+/** @brief
+ *
+	@param c an X.509 certificate
+	@param s is a pointer to the start of the validity field
+	@return 0 on failure, or pointer to the start date
+*/
+extern int X509_find_start_date(octet *c,int s);
+/** @brief
+ *
+	@param c an X.509 certificate
+	@param s is a pointer to the start of the validity field
+	@return 0 on failure, or pointer to the expiry date
+*/
+extern int X509_find_expiry_date(octet *c,int s);
+
+
+#endif
diff --git a/version22/check.cpp b/version22/check.cpp
new file mode 100644
index 0000000..f0a31d9
--- /dev/null
+++ b/version22/check.cpp
@@ -0,0 +1,100 @@
+/*
+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.
+*/
+
+/* Utility to recommend best choice for BASEBITS 
+
+(MINGW build)
+
+g++ -O2 check.cpp big.cpp miracl.a -o check.exe */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "big.h"
+
+using namespace std;
+
+Miracl precision=20;
+
+int main(int argc, char *argv[])
+{
+	int p,w,b,n,s,t,e,ex;
+	Big lhs,rhs;
+
+	argc--; argv++;
+
+    if (argc!=2)
+    {
+       printf("Bad arguments\n");
+       printf("check wordlength modulus-length\n");
+	   printf("Wordlength can be 16, 32 or 64 (or 26 for Javascript)\n");
+       printf("Example:\n");
+       printf("check 32 256\n");
+	   printf("Outputs choices for BASEBITS, number of words per Big, and number of spare bits\n");
+	   printf("Normally choose for minimum words per Big, and maximum spare bits\n");
+	   printf("(But >= 12 spare bits is enough, and tidier if BASEBITS =0 mod 4) \n");
+       exit(0);
+    }
+
+    n=atoi(argv[0]);
+	p=atoi(argv[1]); // Number of bits in prime modulus
+
+	if (n!=16 && n!=26 && n!=32 && n!=64)
+	{
+		printf("wordlength must be 16, 32 or 64\n");
+		return 0;
+	}
+
+	rhs=pow((Big)2,2*n-1);
+	e=3;            // need at least 3 bits to allow adds and subtracts without normalisation
+	if (n==26)
+	{
+		rhs*=2;	// no sign bit to worry about in Javascript
+		e=1;	// not an issue for Javascript
+	}
+
+	for (b=n-e;b>=n-8;b--)
+	{
+		if (n==64 && b%2!=0) continue; // insist on even values for 64-bit builds 
+		w=p/b; if (p%b!=0) w++;
+		s=w*b-p;
+
+		lhs=(w+2)*pow((Big)2,2*b);  // sum of products plus carry plus one for redc
+
+		if (lhs>=rhs)    {printf("Stability violation for BASEBITS= %d\n",b); continue;}
+		ex=1;		
+		while (lhs<rhs)
+		{
+			ex*=2; lhs*=2;
+		}
+		ex/=2;
+
+
+// Top bits of Modulus must appear in top word of representation. Also at least 4 bits spare needed for field excess.  
+		if (s<4 || s>=b) {printf("Not enough Fp spare for BASEBITS= %d\n",b); continue;}
+// At least 2 spare bits needed for FF excess 
+		t=b*(1+(p-1)/b) - 8*(1+(p-1)/8);
+		if (t<2 || t>=b) {printf("Not enough FF spare for BASEBITS= %d\n",b);}
+
+		printf("Solution for BASEBITS= %d, Words Per Big=%d, Fp spare bits= %d, FF spare bits= %d (%d)\n",b,w,s,t,ex);
+		//break;
+	}
+	
+	return 0;
+}
diff --git a/version22/cs/readme.txt b/version22/cs/readme.txt
new file mode 100644
index 0000000..de1039d
--- /dev/null
+++ b/version22/cs/readme.txt
@@ -0,0 +1,36 @@
+AMCL is very simple to build for C#.
+
+NOTE: The C# code is automatically generated from the Java code using 
+the Java to C# Converter from Tangible Software Solutions. We noted a few minor
+fix-ups that were required when we tried the current version of the Converter.
+
+
+** In HASH384.cs and HASH512.cs change long to ulong. Remove castes in S() and R(). Add (ulong) caste 
+in process()
+** Comment out debug "main" programs in files other than Test***.cs
+** In BIG.cs function mod() change "checked" to "unchecked"
+** In BIG.cs in modmul() change BIG.mod(m);BIG.mod(m) to a.mod(m);b.mod(m). Same in modsqr() and modneg()
+** In BIG.cs in jacobi() change BIG.mod(p) to x.mod(p) and BIG.mod(m) to t.mod(m)
+** In TestMPIN.java change line Scanner ...; pin=scan.next(); to pin = int.Parse(Console.ReadLine());
+
+
+Three example API files will be generated, MPIN.cs which 
+supports our M-Pin (tm) protocol, ECDH.cs which supports elliptic 
+curve key exchange, digital signature and public key crypto, and RSA.cs
+which supports the RSA method.
+
+In the ROM.cs file you must provide the curve constants for the curve you want to use. 
+Several examples are provided in the Java code, if you are willing to convert and use one of these.
+
+When the translation is complete, for a quick jumpstart:-
+
+csc TestMPIN.cs MPIN.cs FP.cs BIG.cs DBIG.cs AES.cs HASH256.cs HASH384.cs HASH512.cs RAND.cs ROM.cs StringHelperClass.cs ECP.cs FP2.cs ECP2.cs FP4.cs FP12.cs PAIR.cs RectangularArrays.cs
+
+or 
+
+csc TestECDH.cs ECDH.cs FP.cs BIG.cs DBIG.cs AES.cs HASH256.cs HASH384.cs HASH512.cs RAND.cs ROM.cs StringHelperClass.cs ECP.cs
+
+or
+
+csc TestRSA.cs RSA.cs FF.cs BIG.cs DBIG.cs HASH256.cs HASH384.cs HASH512.cs RAND.cs ROM.cs StringHelperClass.cs
+
diff --git a/version22/ecgen.cpp b/version22/ecgen.cpp
new file mode 100644
index 0000000..8abf112
--- /dev/null
+++ b/version22/ecgen.cpp
@@ -0,0 +1,125 @@
+/*
+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.
+*/
+
+/* ECGEN - Helper MIRACL program to generate constants for EC curves 
+
+(MINGW build)
+
+g++ -O3 ecgen.cpp ecn.cpp big.cpp miracl.a -o ecgen.exe
+
+
+*/
+
+#include <iostream>
+#include "big.h"
+#include "zzn2.h"
+#include "ecn2.h"
+
+using namespace std;
+
+Miracl precision(20,0);
+
+Big output(int chunk,int w,Big t,Big m)
+{
+	Big last,y=t;
+
+	cout << "{";
+	for (int i=0;i<w;i++)
+	{
+		last=y%m;
+		cout << "0x" << last;
+		y/=m;
+		if (i==w-1) break;
+		if (chunk==64) cout << "L,";
+		else cout << ",";
+	}
+
+	if (chunk==64) cout << "L}";
+	else cout << "}";
+	return last;
+}
+
+#define NOT_SPECIAL 0
+#define PSEUDO_MERSENNE 1
+#define GENERALISED_MERSENNE 2
+#define MONTGOMERY_FRIENDLY 3
+
+#define WEIERSTRASS 0
+#define EDWARDS 1
+#define MONTGOMERY 2
+
+/*** Set Modulus and Curve Type Here ***/ 
+
+/* Fill in this bit.... */
+
+#define CHUNK 64   /* processor word size */
+#define MBITS 336  /* Modulus size in bits */
+
+/* This next from output of check.cpp program */
+#define BASEBITS 60
+
+#define WORDS (1+((MBITS-1)/BASEBITS))
+#define MODTYPE  PSEUDO_MERSENNE
+#define CURVETYPE EDWARDS
+#define CURVE_A 1  // like A parameter in CURVE: y^2=x^3+Ax+B
+
+/* .....to here */
+
+
+int main()
+{
+	miracl *mip=&precision;
+	Big p,q,R,B;
+	Big m,x,y,w,t,c,n,r,a,b,gx,gy,D,C,MC;
+	int i,A;
+
+
+/* Fill in this bit... */
+
+	p=pow((Big)2,MBITS)-3;   // Modulus
+	mip->IOBASE=16;
+	r=(char *)"200000000000000000000000000000000000000000071415FA9850C0BD6B87F93BAA7B2F95973E9FA805"; // Group Order
+	B=11111;    // B parameter of elliptic curve
+	gx=(char *)"C";  // generator point
+	gy=(char *)"C0DC616B56502E18E1C161D007853D1B14B46C3811C7EF435B6DB5D5650CA0365DB12BEC68505FE8632";
+
+/* .....to here */
+	
+	cout << "MOD8 = " << p%8 << endl;
+
+	m=pow((Big)2,BASEBITS);
+
+	cout << "Modulus="; MC=output(CHUNK,WORDS,p,m); cout << ";" << endl;
+
+#if MODTYPE==NOT_SPECIAL
+		cout << "MConst=0x" << inverse(m-p%m,m) << ";" << endl;	
+#endif
+#if MODTYPE==MONTGOMERY_FRIENDLY
+		cout << "MConst=0x" << MC+1 << ";" << endl;	
+#endif
+#if MODTYPE==PSEUDO_MERSENNE
+		cout << "MConst=0x" << pow((Big)2,MBITS)-p << ";" << endl;			
+#endif
+
+	cout << "Order="; output(CHUNK,WORDS,r,m); cout << ";" << endl;
+	cout << "CURVE_B="; output(CHUNK,WORDS,B,m); cout << ";" <<  endl;
+	cout << "CURVE_Gx="; output(CHUNK,WORDS,gx,m); cout << ";" << endl;
+	cout << "CURVE_Gy="; output(CHUNK,WORDS,gy,m); cout << ";" << endl;
+
+}
diff --git a/version22/go/AES.go b/version22/go/AES.go
new file mode 100644
index 0000000..1aeb6d7
--- /dev/null
+++ b/version22/go/AES.go
@@ -0,0 +1,634 @@
+/*
+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.
+*/
+
+/* AES Encryption */ 
+
+package main
+
+//import "fmt"
+
+const aes_ECB int=0
+const aes_CBC int=1
+const aes_CFB1 int=2
+const aes_CFB2 int=3
+const aes_CFB4 int=5
+const aes_OFB1 int=14
+const aes_OFB2 int=15
+const aes_OFB4 int=17
+const aes_OFB8 int=21
+const aes_OFB16 int=29
+const aes_CTR1 int=30
+const aes_CTR2 int=31
+const aes_CTR4 int=33 
+const aes_CTR8 int=37 
+const aes_CTR16 int=45 
+
+var aes_InCo = [...]byte {0xB,0xD,0x9,0xE}  /* Inverse Coefficients */
+
+var aes_ptab = [...]byte {
+     1, 3, 5, 15, 17, 51, 85, 255, 26, 46, 114, 150, 161, 248, 19, 53,
+     95, 225, 56, 72, 216, 115, 149, 164, 247, 2, 6, 10, 30, 34, 102, 170,
+     229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217, 112, 144, 171, 230, 49,
+     83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104, 184, 211, 110, 178, 205,
+     76, 212, 103, 169, 224, 59, 77, 215, 98, 166, 241, 8, 24, 40, 120, 136,
+     131, 158, 185, 208, 107, 189, 220, 127, 129, 152, 179, 206, 73, 219, 118, 154,
+     181, 196, 87, 249, 16, 48, 80, 240, 11, 29, 39, 105, 187, 214, 97, 163,
+     254, 25, 43, 125, 135, 146, 173, 236, 47, 113, 147, 174, 233, 32, 96, 160,
+     251, 22, 58, 78, 210, 109, 183, 194, 93, 231, 50, 86, 250, 21, 63, 65,
+     195, 94, 226, 61, 71, 201, 64, 192, 91, 237, 44, 116, 156, 191, 218, 117,
+     159, 186, 213, 100, 172, 239, 42, 126, 130, 157, 188, 223, 122, 142, 137, 128,
+     155, 182, 193, 88, 232, 35, 101, 175, 234, 37, 111, 177, 200, 67, 197, 84,
+     252, 31, 33, 99, 165, 244, 7, 9, 27, 45, 119, 153, 176, 203, 70, 202,
+     69, 207, 74, 222, 121, 139, 134, 145, 168, 227, 62, 66, 198, 81, 243, 14,
+     18, 54, 90, 238, 41, 123, 141, 140, 143, 138, 133, 148, 167, 242, 13, 23,
+     57, 75, 221, 124, 132, 151, 162, 253, 28, 36, 108, 180, 199, 82, 246, 1}
+
+var aes_ltab = [...]byte {
+      0, 255, 25, 1, 50, 2, 26, 198, 75, 199, 27, 104, 51, 238, 223, 3,
+     100, 4, 224, 14, 52, 141, 129, 239, 76, 113, 8, 200, 248, 105, 28, 193,
+     125, 194, 29, 181, 249, 185, 39, 106, 77, 228, 166, 114, 154, 201, 9, 120,
+     101, 47, 138, 5, 33, 15, 225, 36, 18, 240, 130, 69, 53, 147, 218, 142,
+     150, 143, 219, 189, 54, 208, 206, 148, 19, 92, 210, 241, 64, 70, 131, 56,
+     102, 221, 253, 48, 191, 6, 139, 98, 179, 37, 226, 152, 34, 136, 145, 16,
+     126, 110, 72, 195, 163, 182, 30, 66, 58, 107, 40, 84, 250, 133, 61, 186,
+     43, 121, 10, 21, 155, 159, 94, 202, 78, 212, 172, 229, 243, 115, 167, 87,
+     175, 88, 168, 80, 244, 234, 214, 116, 79, 174, 233, 213, 231, 230, 173, 232,
+     44, 215, 117, 122, 235, 22, 11, 245, 89, 203, 95, 176, 156, 169, 81, 160,
+     127, 12, 246, 111, 23, 196, 73, 236, 216, 67, 31, 45, 164, 118, 123, 183,
+     204, 187, 62, 90, 251, 96, 177, 134, 59, 82, 161, 108, 170, 85, 41, 157,
+     151, 178, 135, 144, 97, 190, 220, 252, 188, 149, 207, 205, 55, 63, 91, 209,
+     83, 57, 132, 60, 65, 162, 109, 71, 20, 42, 158, 93, 86, 242, 211, 171,
+     68, 17, 146, 217, 35, 32, 46, 137, 180, 124, 184, 38, 119, 153, 227, 165,
+     103, 74, 237, 222, 197, 49, 254, 24, 13, 99, 140, 128, 192, 247, 112, 7}
+   
+
+var aes_fbsub = [...]byte {
+     99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118,
+     202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192,
+     183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21,
+     4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117,
+     9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132,
+     83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207,
+     208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168,
+     81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210,
+     205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115,
+     96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219,
+     224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121,
+     231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8,
+     186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138,
+     112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158,
+     225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223,
+     140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22}
+    
+var aes_rbsub = [...]byte {
+     82, 9, 106, 213, 48, 54, 165, 56, 191, 64, 163, 158, 129, 243, 215, 251,
+     124, 227, 57, 130, 155, 47, 255, 135, 52, 142, 67, 68, 196, 222, 233, 203,
+     84, 123, 148, 50, 166, 194, 35, 61, 238, 76, 149, 11, 66, 250, 195, 78,
+     8, 46, 161, 102, 40, 217, 36, 178, 118, 91, 162, 73, 109, 139, 209, 37,
+     114, 248, 246, 100, 134, 104, 152, 22, 212, 164, 92, 204, 93, 101, 182, 146,
+     108, 112, 72, 80, 253, 237, 185, 218, 94, 21, 70, 87, 167, 141, 157, 132,
+     144, 216, 171, 0, 140, 188, 211, 10, 247, 228, 88, 5, 184, 179, 69, 6,
+     208, 44, 30, 143, 202, 63, 15, 2, 193, 175, 189, 3, 1, 19, 138, 107,
+     58, 145, 17, 65, 79, 103, 220, 234, 151, 242, 207, 206, 240, 180, 230, 115,
+     150, 172, 116, 34, 231, 173, 53, 133, 226, 249, 55, 232, 28, 117, 223, 110,
+     71, 241, 26, 113, 29, 41, 197, 137, 111, 183, 98, 14, 170, 24, 190, 27,
+     252, 86, 62, 75, 198, 210, 121, 32, 154, 219, 192, 254, 120, 205, 90, 244,
+     31, 221, 168, 51, 136, 7, 199, 49, 177, 18, 16, 89, 39, 128, 236, 95,
+     96, 81, 127, 169, 25, 181, 74, 13, 45, 229, 122, 159, 147, 201, 156, 239,
+     160, 224, 59, 77, 174, 42, 245, 176, 200, 235, 187, 60, 131, 83, 153, 97,
+     23, 43, 4, 126, 186, 119, 214, 38, 225, 105, 20, 99, 85, 33, 12, 125}
+    
+
+var aes_rco = [...]byte {1,2,4,8,16,32,64,128,27,54,108,216,171,77,154,47}
+
+var aes_ftable = [...]uint32 {
+    0xa56363c6,0x847c7cf8,0x997777ee,0x8d7b7bf6,0xdf2f2ff,0xbd6b6bd6,
+    0xb16f6fde,0x54c5c591,0x50303060,0x3010102,0xa96767ce,0x7d2b2b56,
+    0x19fefee7,0x62d7d7b5,0xe6abab4d,0x9a7676ec,0x45caca8f,0x9d82821f,
+    0x40c9c989,0x877d7dfa,0x15fafaef,0xeb5959b2,0xc947478e,0xbf0f0fb,
+    0xecadad41,0x67d4d4b3,0xfda2a25f,0xeaafaf45,0xbf9c9c23,0xf7a4a453,
+    0x967272e4,0x5bc0c09b,0xc2b7b775,0x1cfdfde1,0xae93933d,0x6a26264c,
+    0x5a36366c,0x413f3f7e,0x2f7f7f5,0x4fcccc83,0x5c343468,0xf4a5a551,
+    0x34e5e5d1,0x8f1f1f9,0x937171e2,0x73d8d8ab,0x53313162,0x3f15152a,
+    0xc040408,0x52c7c795,0x65232346,0x5ec3c39d,0x28181830,0xa1969637,
+    0xf05050a,0xb59a9a2f,0x907070e,0x36121224,0x9b80801b,0x3de2e2df,
+    0x26ebebcd,0x6927274e,0xcdb2b27f,0x9f7575ea,0x1b090912,0x9e83831d,
+    0x742c2c58,0x2e1a1a34,0x2d1b1b36,0xb26e6edc,0xee5a5ab4,0xfba0a05b,
+    0xf65252a4,0x4d3b3b76,0x61d6d6b7,0xceb3b37d,0x7b292952,0x3ee3e3dd,
+    0x712f2f5e,0x97848413,0xf55353a6,0x68d1d1b9,0x0,0x2cededc1,
+    0x60202040,0x1ffcfce3,0xc8b1b179,0xed5b5bb6,0xbe6a6ad4,0x46cbcb8d,
+    0xd9bebe67,0x4b393972,0xde4a4a94,0xd44c4c98,0xe85858b0,0x4acfcf85,
+    0x6bd0d0bb,0x2aefefc5,0xe5aaaa4f,0x16fbfbed,0xc5434386,0xd74d4d9a,
+    0x55333366,0x94858511,0xcf45458a,0x10f9f9e9,0x6020204,0x817f7ffe,
+    0xf05050a0,0x443c3c78,0xba9f9f25,0xe3a8a84b,0xf35151a2,0xfea3a35d,
+    0xc0404080,0x8a8f8f05,0xad92923f,0xbc9d9d21,0x48383870,0x4f5f5f1,
+    0xdfbcbc63,0xc1b6b677,0x75dadaaf,0x63212142,0x30101020,0x1affffe5,
+    0xef3f3fd,0x6dd2d2bf,0x4ccdcd81,0x140c0c18,0x35131326,0x2fececc3,
+    0xe15f5fbe,0xa2979735,0xcc444488,0x3917172e,0x57c4c493,0xf2a7a755,
+    0x827e7efc,0x473d3d7a,0xac6464c8,0xe75d5dba,0x2b191932,0x957373e6,
+    0xa06060c0,0x98818119,0xd14f4f9e,0x7fdcdca3,0x66222244,0x7e2a2a54,
+    0xab90903b,0x8388880b,0xca46468c,0x29eeeec7,0xd3b8b86b,0x3c141428,
+    0x79dedea7,0xe25e5ebc,0x1d0b0b16,0x76dbdbad,0x3be0e0db,0x56323264,
+    0x4e3a3a74,0x1e0a0a14,0xdb494992,0xa06060c,0x6c242448,0xe45c5cb8,
+    0x5dc2c29f,0x6ed3d3bd,0xefacac43,0xa66262c4,0xa8919139,0xa4959531,
+    0x37e4e4d3,0x8b7979f2,0x32e7e7d5,0x43c8c88b,0x5937376e,0xb76d6dda,
+    0x8c8d8d01,0x64d5d5b1,0xd24e4e9c,0xe0a9a949,0xb46c6cd8,0xfa5656ac,
+    0x7f4f4f3,0x25eaeacf,0xaf6565ca,0x8e7a7af4,0xe9aeae47,0x18080810,
+    0xd5baba6f,0x887878f0,0x6f25254a,0x722e2e5c,0x241c1c38,0xf1a6a657,
+    0xc7b4b473,0x51c6c697,0x23e8e8cb,0x7cdddda1,0x9c7474e8,0x211f1f3e,
+    0xdd4b4b96,0xdcbdbd61,0x868b8b0d,0x858a8a0f,0x907070e0,0x423e3e7c,
+    0xc4b5b571,0xaa6666cc,0xd8484890,0x5030306,0x1f6f6f7,0x120e0e1c,
+    0xa36161c2,0x5f35356a,0xf95757ae,0xd0b9b969,0x91868617,0x58c1c199,
+    0x271d1d3a,0xb99e9e27,0x38e1e1d9,0x13f8f8eb,0xb398982b,0x33111122,
+    0xbb6969d2,0x70d9d9a9,0x898e8e07,0xa7949433,0xb69b9b2d,0x221e1e3c,
+    0x92878715,0x20e9e9c9,0x49cece87,0xff5555aa,0x78282850,0x7adfdfa5,
+    0x8f8c8c03,0xf8a1a159,0x80898909,0x170d0d1a,0xdabfbf65,0x31e6e6d7,
+    0xc6424284,0xb86868d0,0xc3414182,0xb0999929,0x772d2d5a,0x110f0f1e,
+    0xcbb0b07b,0xfc5454a8,0xd6bbbb6d,0x3a16162c}
+
+var aes_rtable = [...]uint32 {
+    0x50a7f451,0x5365417e,0xc3a4171a,0x965e273a,0xcb6bab3b,0xf1459d1f,
+    0xab58faac,0x9303e34b,0x55fa3020,0xf66d76ad,0x9176cc88,0x254c02f5,
+    0xfcd7e54f,0xd7cb2ac5,0x80443526,0x8fa362b5,0x495ab1de,0x671bba25,
+    0x980eea45,0xe1c0fe5d,0x2752fc3,0x12f04c81,0xa397468d,0xc6f9d36b,
+    0xe75f8f03,0x959c9215,0xeb7a6dbf,0xda595295,0x2d83bed4,0xd3217458,
+    0x2969e049,0x44c8c98e,0x6a89c275,0x78798ef4,0x6b3e5899,0xdd71b927,
+    0xb64fe1be,0x17ad88f0,0x66ac20c9,0xb43ace7d,0x184adf63,0x82311ae5,
+    0x60335197,0x457f5362,0xe07764b1,0x84ae6bbb,0x1ca081fe,0x942b08f9,
+    0x58684870,0x19fd458f,0x876cde94,0xb7f87b52,0x23d373ab,0xe2024b72,
+    0x578f1fe3,0x2aab5566,0x728ebb2,0x3c2b52f,0x9a7bc586,0xa50837d3,
+    0xf2872830,0xb2a5bf23,0xba6a0302,0x5c8216ed,0x2b1ccf8a,0x92b479a7,
+    0xf0f207f3,0xa1e2694e,0xcdf4da65,0xd5be0506,0x1f6234d1,0x8afea6c4,
+    0x9d532e34,0xa055f3a2,0x32e18a05,0x75ebf6a4,0x39ec830b,0xaaef6040,
+    0x69f715e,0x51106ebd,0xf98a213e,0x3d06dd96,0xae053edd,0x46bde64d,
+    0xb58d5491,0x55dc471,0x6fd40604,0xff155060,0x24fb9819,0x97e9bdd6,
+    0xcc434089,0x779ed967,0xbd42e8b0,0x888b8907,0x385b19e7,0xdbeec879,
+    0x470a7ca1,0xe90f427c,0xc91e84f8,0x0,0x83868009,0x48ed2b32,
+    0xac70111e,0x4e725a6c,0xfbff0efd,0x5638850f,0x1ed5ae3d,0x27392d36,
+    0x64d90f0a,0x21a65c68,0xd1545b9b,0x3a2e3624,0xb1670a0c,0xfe75793,
+    0xd296eeb4,0x9e919b1b,0x4fc5c080,0xa220dc61,0x694b775a,0x161a121c,
+    0xaba93e2,0xe52aa0c0,0x43e0223c,0x1d171b12,0xb0d090e,0xadc78bf2,
+    0xb9a8b62d,0xc8a91e14,0x8519f157,0x4c0775af,0xbbdd99ee,0xfd607fa3,
+    0x9f2601f7,0xbcf5725c,0xc53b6644,0x347efb5b,0x7629438b,0xdcc623cb,
+    0x68fcedb6,0x63f1e4b8,0xcadc31d7,0x10856342,0x40229713,0x2011c684,
+    0x7d244a85,0xf83dbbd2,0x1132f9ae,0x6da129c7,0x4b2f9e1d,0xf330b2dc,
+    0xec52860d,0xd0e3c177,0x6c16b32b,0x99b970a9,0xfa489411,0x2264e947,
+    0xc48cfca8,0x1a3ff0a0,0xd82c7d56,0xef903322,0xc74e4987,0xc1d138d9,
+    0xfea2ca8c,0x360bd498,0xcf81f5a6,0x28de7aa5,0x268eb7da,0xa4bfad3f,
+    0xe49d3a2c,0xd927850,0x9bcc5f6a,0x62467e54,0xc2138df6,0xe8b8d890,
+    0x5ef7392e,0xf5afc382,0xbe805d9f,0x7c93d069,0xa92dd56f,0xb31225cf,
+    0x3b99acc8,0xa77d1810,0x6e639ce8,0x7bbb3bdb,0x97826cd,0xf418596e,
+    0x1b79aec,0xa89a4f83,0x656e95e6,0x7ee6ffaa,0x8cfbc21,0xe6e815ef,
+    0xd99be7ba,0xce366f4a,0xd4099fea,0xd67cb029,0xafb2a431,0x31233f2a,
+    0x3094a5c6,0xc066a235,0x37bc4e74,0xa6ca82fc,0xb0d090e0,0x15d8a733,
+    0x4a9804f1,0xf7daec41,0xe50cd7f,0x2ff69117,0x8dd64d76,0x4db0ef43,
+    0x544daacc,0xdf0496e4,0xe3b5d19e,0x1b886a4c,0xb81f2cc1,0x7f516546,
+    0x4ea5e9d,0x5d358c01,0x737487fa,0x2e410bfb,0x5a1d67b3,0x52d2db92,
+    0x335610e9,0x1347d66d,0x8c61d79a,0x7a0ca137,0x8e14f859,0x893c13eb,
+    0xee27a9ce,0x35c961b7,0xede51ce1,0x3cb1477a,0x59dfd29c,0x3f73f255,
+    0x79ce1418,0xbf37c773,0xeacdf753,0x5baafd5f,0x146f3ddf,0x86db4478,
+    0x81f3afca,0x3ec468b9,0x2c342438,0x5f40a3c2,0x72c31d16,0xc25e2bc,
+    0x8b493c28,0x41950dff,0x7101a839,0xdeb30c08,0x9ce4b4d8,0x90c15664,
+    0x6184cb7b,0x70b632d5,0x745c6c48,0x4257b8d0}
+
+type AES struct {
+	Nk int
+	Nr int
+	mode int
+	fkey [60]uint32
+	rkey [60]uint32
+	f [16]byte
+}
+
+/* Rotates 32-bit word left by 1, 2 or 3 byte  */
+
+func aes_ROTL8(x uint32) uint32 {
+	return (((x)<<8)|((x)>>24))
+}
+
+func aes_ROTL16(x uint32) uint32 {
+	return (((x)<<16)|((x)>>16))
+}
+
+func aes_ROTL24(x uint32) uint32 {
+	return (((x)<<24)|((x)>>8))
+}
+
+func aes_pack(b [4]byte) uint32 { /* pack bytes into a 32-bit Word */
+        return ((uint32(b[3])&0xff)<<24)|((uint32(b[2])&0xff)<<16)|((uint32(b[1])&0xff)<<8)|(uint32(b[0])&0xff)
+}
+  
+func aes_unpack(a uint32) [4]byte { /* unpack bytes from a word */
+        var b=[4]byte{byte(a&0xff),byte((a>>8)&0xff),byte((a>>16)&0xff),byte((a>>24)&0xff)}
+	return b;
+}
+  
+func aes_bmul(x byte,y byte) byte { /* x.y= AntiLog(Log(x) + Log(y)) */
+    
+        ix:=int(x)&0xff
+        iy:=int(y)&0xff
+        lx:=int(aes_ltab[ix])&0xff
+        ly:=int(aes_ltab[iy])&0xff
+    
+        if x != 0 && y != 0 {
+		return aes_ptab[(lx+ly)%255]
+	} else {return byte(0)}
+}
+  
+func aes_SubByte(a uint32) uint32 {
+        b:=aes_unpack(a)
+        b[0]=aes_fbsub[int(b[0])]
+        b[1]=aes_fbsub[int(b[1])]
+        b[2]=aes_fbsub[int(b[2])]
+        b[3]=aes_fbsub[int(b[3])]
+        return aes_pack(b);
+}    
+
+func aes_product(x uint32,y uint32) byte { /* dot product of two 4-byte arrays */
+        xb:=aes_unpack(x)
+        yb:=aes_unpack(y)
+    
+        return (aes_bmul(xb[0],yb[0])^aes_bmul(xb[1],yb[1])^aes_bmul(xb[2],yb[2])^aes_bmul(xb[3],yb[3]))
+}
+
+func aes_InvMixCol(x uint32) uint32 { /* matrix Multiplication */
+        var b [4]byte
+        m:=aes_pack(aes_InCo)
+        b[3]=aes_product(m,x)
+        m=aes_ROTL24(m)
+        b[2]=aes_product(m,x)
+        m=aes_ROTL24(m)
+        b[1]=aes_product(m,x)
+        m=aes_ROTL24(m)
+        b[0]=aes_product(m,x)
+        var y=aes_pack(b)
+        return y
+}
+
+func aes_increment(f []byte) {
+	for i:=0;i<16;i++ {
+		f[i]++
+		if f[i]!=0 {break}
+	}
+}
+
+/* reset cipher */
+func (A *AES) Reset(m int,iv []byte) { /* reset mode, or reset iv */
+	A.mode=m;
+        for i:=0;i<16;i++ {A.f[i]=0}
+        if (A.mode != aes_ECB) && (iv != nil) {
+            for i:=0;i<16;i++ {A.f[i]=iv[i]}
+	}
+}
+
+func (A *AES) Init(m int,nk int,key []byte,iv []byte) bool { 
+/* Key Scheduler. Create expanded encryption key */
+	var CipherKey [8]uint32
+        var b [4]byte
+        nk/=4
+	if nk!=4 && nk!=6 && nk!=8 {return false}
+	nr:=6+nk
+	A.Nk=nk
+	A.Nr=nr
+        A.Reset(m,iv);
+        N:=4*(nr+1)
+        
+        j:=0
+        for  i:=0;i<nk;i++ {
+            for k:=0;k<4;k++ {b[k]=key[j+k]}
+            CipherKey[i]=aes_pack(b);
+            j+=4;
+        }
+        for i:=0;i<nk;i++ {A.fkey[i]=CipherKey[i]}
+        j=nk
+        for k:=0;j<N;k++ {
+            A.fkey[j]=A.fkey[j-nk]^aes_SubByte(aes_ROTL24(A.fkey[j-1]))^uint32(aes_rco[k])
+            for i:=1;i<nk && (i+j)<N;i++ {
+                A.fkey[i+j]=A.fkey[i+j-nk]^A.fkey[i+j-1]
+            }
+            j+=nk
+        }
+        
+        /* now for the expanded decrypt key in reverse order */
+        
+        for j:=0;j<4;j++ {A.rkey[j+N-4]=A.fkey[j]}
+        for i:=4;i<N-4;i+=4 {
+            k:=N-4-i;
+            for j:=0;j<4;j++ {A.rkey[k+j]=aes_InvMixCol(A.fkey[i+j])}
+        }
+        for j:=N-4;j<N;j++ {A.rkey[j-N+4]=A.fkey[j]}
+	return true
+}
+
+func NewAES() *AES {
+	var A=new(AES)
+	return A
+}
+
+func (A *AES) Getreg() [16]byte {
+        var ir [16]byte
+        for i:=0;i<16;i++ {ir[i]=A.f[i]}
+        return ir
+}
+
+    /* Encrypt a single block */
+func (A *AES) ecb_encrypt(buff []byte) {
+        var b [4]byte
+        var p [4]uint32
+        var q [4]uint32
+    
+        j:=0
+        for i:=0;i<4;i++ {
+            for k:=0;k<4;k++ {b[k]=buff[j+k]}
+            p[i]=aes_pack(b)
+            p[i]^=A.fkey[i]
+            j+=4
+        }
+    
+        k:=4
+    
+    /* State alternates between p and q */
+        for i:=1;i<A.Nr;i++ {
+            q[0]=A.fkey[k]^aes_ftable[int(p[0]&0xff)]^aes_ROTL8(aes_ftable[int((p[1]>>8)&0xff)])^aes_ROTL16(aes_ftable[int((p[2]>>16)&0xff)])^aes_ROTL24(aes_ftable[int((p[3]>>24)&0xff)])
+            
+            q[1]=A.fkey[k+1]^aes_ftable[int(p[1]&0xff)]^aes_ROTL8(aes_ftable[int((p[2]>>8)&0xff)])^aes_ROTL16(aes_ftable[int((p[3]>>16)&0xff)])^aes_ROTL24(aes_ftable[int((p[0]>>24)&0xff)])
+            
+            q[2]=A.fkey[k+2]^aes_ftable[int(p[2]&0xff)]^aes_ROTL8(aes_ftable[int((p[3]>>8)&0xff)])^aes_ROTL16(aes_ftable[int((p[0]>>16)&0xff)])^aes_ROTL24(aes_ftable[int((p[1]>>24)&0xff)])
+            
+            q[3]=A.fkey[k+3]^aes_ftable[int(p[3]&0xff)]^aes_ROTL8(aes_ftable[int((p[0]>>8)&0xff)])^aes_ROTL16(aes_ftable[int((p[1]>>16)&0xff)])^aes_ROTL24(aes_ftable[int((p[2]>>24)&0xff)])
+            
+            k+=4;
+            for j=0;j<4;j++ {
+		t:=p[j]; p[j]=q[j]; q[j]=t
+            }
+        }
+    
+    /* Last Round */
+    
+        q[0]=A.fkey[k]^uint32(aes_fbsub[int(p[0]&0xff)])^aes_ROTL8(uint32(aes_fbsub[int((p[1]>>8)&0xff)]))^aes_ROTL16(uint32(aes_fbsub[int((p[2]>>16)&0xff)]))^aes_ROTL24(uint32(aes_fbsub[int((p[3]>>24)&0xff)]))
+    
+        q[1]=A.fkey[k+1]^uint32(aes_fbsub[int(p[1]&0xff)])^aes_ROTL8(uint32(aes_fbsub[int((p[2]>>8)&0xff)]))^aes_ROTL16(uint32(aes_fbsub[int((p[3]>>16)&0xff)]))^aes_ROTL24(uint32(aes_fbsub[int((p[0]>>24)&0xff)]))
+    
+        q[2]=A.fkey[k+2]^uint32(aes_fbsub[int(p[2]&0xff)])^aes_ROTL8(uint32(aes_fbsub[int((p[3]>>8)&0xff)]))^aes_ROTL16(uint32(aes_fbsub[int((p[0]>>16)&0xff)]))^aes_ROTL24(uint32(aes_fbsub[int((p[1]>>24)&0xff)]))
+    
+        q[3]=A.fkey[k+3]^uint32(aes_fbsub[int(p[3]&0xff)])^aes_ROTL8(uint32(aes_fbsub[int((p[0]>>8)&0xff)]))^aes_ROTL16(uint32(aes_fbsub[int((p[1]>>16)&0xff)]))^aes_ROTL24(uint32(aes_fbsub[int((p[2]>>24)&0xff)]))
+    
+        j=0
+        for i:=0;i<4;i++ {
+            b=aes_unpack(q[i])
+            for k=0;k<4;k++ {buff[j+k]=b[k]}
+            j+=4
+        }
+}
+    
+    /* Decrypt a single block */
+func (A *AES)  ecb_decrypt(buff []byte) {
+        var b [4]byte
+        var p [4]uint32
+        var q [4]uint32
+    
+        j:=0
+        for i:=0;i<4;i++ {
+            for k:=0;k<4;k++ {b[k]=buff[j+k]}
+            p[i]=aes_pack(b)
+            p[i]^=A.rkey[i]
+            j+=4
+        }
+    
+        k:=4
+    
+    /* State alternates between p and q */
+        for i:=1;i<A.Nr;i++ {
+            
+            q[0]=A.rkey[k]^aes_rtable[int(p[0]&0xff)]^aes_ROTL8(aes_rtable[int((p[3]>>8)&0xff)])^aes_ROTL16(aes_rtable[int((p[2]>>16)&0xff)])^aes_ROTL24(aes_rtable[int((p[1]>>24)&0xff)])
+            
+            q[1]=A.rkey[k+1]^aes_rtable[int(p[1]&0xff)]^aes_ROTL8(aes_rtable[int((p[0]>>8)&0xff)])^aes_ROTL16(aes_rtable[int((p[3]>>16)&0xff)])^aes_ROTL24(aes_rtable[int((p[2]>>24)&0xff)])
+            
+        
+            q[2]=A.rkey[k+2]^aes_rtable[int(p[2]&0xff)]^aes_ROTL8(aes_rtable[int((p[1]>>8)&0xff)])^aes_ROTL16(aes_rtable[int((p[0]>>16)&0xff)])^aes_ROTL24(aes_rtable[int((p[3]>>24)&0xff)])
+       
+            q[3]=A.rkey[k+3]^aes_rtable[int(p[3]&0xff)]^aes_ROTL8(aes_rtable[int((p[2]>>8)&0xff)])^aes_ROTL16(aes_rtable[int((p[1]>>16)&0xff)])^aes_ROTL24(aes_rtable[int((p[0]>>24)&0xff)])
+            
+    
+            k+=4;
+            for j:=0;j<4;j++ {
+			t:=p[j]; p[j]=q[j]; q[j]=t
+            }
+        }
+    
+    /* Last Round */
+        
+        q[0]=A.rkey[k]^uint32(aes_rbsub[int(p[0]&0xff)])^aes_ROTL8(uint32(aes_rbsub[int((p[3]>>8)&0xff)]))^aes_ROTL16(uint32(aes_rbsub[int((p[2]>>16)&0xff)]))^aes_ROTL24(uint32(aes_rbsub[int((p[1]>>24)&0xff)]))
+        
+        q[1]=A.rkey[k+1]^uint32(aes_rbsub[int(p[1]&0xff)])^aes_ROTL8(uint32(aes_rbsub[int((p[0]>>8)&0xff)]))^aes_ROTL16(uint32(aes_rbsub[int((p[3]>>16)&0xff)]))^aes_ROTL24(uint32(aes_rbsub[int((p[2]>>24)&0xff)]))
+        
+        
+        q[2]=A.rkey[k+2]^uint32(aes_rbsub[int(p[2]&0xff)])^aes_ROTL8(uint32(aes_rbsub[int((p[1]>>8)&0xff)]))^aes_ROTL16(uint32(aes_rbsub[int((p[0]>>16)&0xff)]))^aes_ROTL24(uint32(aes_rbsub[int((p[3]>>24)&0xff)]))
+
+        q[3]=A.rkey[k+3]^uint32(aes_rbsub[int((p[3])&0xff)])^aes_ROTL8(uint32(aes_rbsub[int((p[2]>>8)&0xff)]))^aes_ROTL16(uint32(aes_rbsub[int((p[1]>>16)&0xff)]))^aes_ROTL24(uint32(aes_rbsub[int((p[0]>>24)&0xff)]))
+    
+        j=0
+        for i:=0;i<4;i++ {
+            b=aes_unpack(q[i]);
+            for k:=0;k<4;k++ {buff[j+k]=b[k]}
+            j+=4
+        }
+}
+
+/* Encrypt using selected mode of operation */
+func (A *AES) Encrypt(buff []byte) uint32 {
+	var st [16]byte
+    
+    // Supported Modes of Operation
+    
+        var fell_off uint32=0
+        switch A.mode {
+        case aes_ECB:
+            A.ecb_encrypt(buff)
+            return 0
+        case aes_CBC:
+            for j:=0;j<16;j++ {buff[j]^=A.f[j]}
+            A.ecb_encrypt(buff)
+            for j:=0;j<16;j++ {A.f[j]=buff[j]}
+            return 0
+    
+        case aes_CFB1:
+            fallthrough
+        case aes_CFB2:
+            fallthrough
+        case aes_CFB4:
+            bytes:=A.mode-aes_CFB1+1
+            for j:=0;j<bytes;j++ {fell_off=(fell_off<<8)|uint32(A.f[j])}
+            for j:=0;j<16;j++ {st[j]=A.f[j]}
+            for j:=bytes;j<16;j++ {A.f[j-bytes]=A.f[j]}
+            A.ecb_encrypt(st[:])
+            for j:=0;j<bytes;j++ {
+		buff[j]^=st[j]
+		A.f[16-bytes+j]=buff[j]
+            }
+            return fell_off
+    
+        case aes_OFB1:
+            fallthrough
+        case aes_OFB2:
+            fallthrough
+        case aes_OFB4:
+            fallthrough
+        case aes_OFB8:
+            fallthrough
+        case aes_OFB16:
+    
+            bytes:=A.mode-aes_OFB1+1
+            A.ecb_encrypt(A.f[:])
+            for j:=0;j<bytes;j++ {buff[j]^=A.f[j]}
+            return 0;
+    
+	case aes_CTR1:
+	    fallthrough
+	case aes_CTR2:
+	    fallthrough
+	case aes_CTR4:
+	    fallthrough
+	case aes_CTR8:
+	    fallthrough
+	case aes_CTR16:
+	    bytes:=A.mode-aes_CTR1+1
+	    for j:=0;j<16;j++ {st[j]=A.f[j]}
+	    A.ecb_encrypt(st[:])
+	    for j:=0;j<bytes;j++ {buff[j]^=st[j]}
+	    aes_increment(A.f[:])
+	    return 0
+
+        default:
+            return 0
+        }
+}
+    
+    /* Decrypt using selected mode of operation */
+func (A *AES) Decrypt(buff []byte) uint32 {
+
+	var st [16]byte
+        
+        // Supported Modes of Operation
+        
+        var fell_off uint32=0
+        switch A.mode {
+        case aes_ECB:
+            A.ecb_decrypt(buff);
+            return 0;
+        case aes_CBC:
+            for j:=0;j<16;j++ {
+		st[j]=A.f[j];
+		A.f[j]=buff[j];
+            }
+            A.ecb_decrypt(buff);
+            for j:=0;j<16;j++ {
+		buff[j]^=st[j];
+		st[j]=0
+            }
+            return 0
+        case aes_CFB1:
+            fallthrough
+        case aes_CFB2:
+            fallthrough
+        case aes_CFB4:
+            bytes:=A.mode-aes_CFB1+1;
+            for j:=0;j<bytes;j++ {fell_off=(fell_off<<8)|uint32(A.f[j])}
+            for j:=0;j<16;j++ {st[j]=A.f[j]}
+            for j:=bytes;j<16;j++ {A.f[j-bytes]=A.f[j]}
+            A.ecb_encrypt(st[:])
+            for j:=0;j<bytes;j++ {
+		A.f[16-bytes+j]=buff[j]
+		buff[j]^=st[j]
+            }
+            return fell_off
+        case aes_OFB1:
+            fallthrough
+        case aes_OFB2:
+            fallthrough
+        case aes_OFB4:
+            fallthrough
+        case aes_OFB8:
+            fallthrough
+        case aes_OFB16:
+            bytes:=A.mode-aes_OFB1+1
+            A.ecb_encrypt(A.f[:]);
+            for j:=0;j<bytes;j++ {buff[j]^=A.f[j]}
+            return 0
+
+	case aes_CTR1:
+	    fallthrough
+	case aes_CTR2:
+	    fallthrough
+	case aes_CTR4:
+	    fallthrough
+	case aes_CTR8:
+	    fallthrough
+	case aes_CTR16:
+	    bytes:=A.mode-aes_CTR1+1
+	    for j:=0;j<16;j++ {st[j]=A.f[j]}
+	    A.ecb_encrypt(st[:])
+	    for j:=0;j<bytes;j++ {buff[j]^=st[j]}
+	    aes_increment(A.f[:])
+	    return 0
+
+        default:
+            return 0;
+        }
+    } 
+    
+/* Clean up and delete left-overs */
+func (A *AES) End() { // clean up
+    for i:=0;i<4*(A.Nr+1);i++ {A.fkey[i]=0; A.rkey[i]=0}
+    for i:=0;i<16;i++ {A.f[i]=0}
+}
+/*
+func main() {
+	var key [32]byte
+	var block [16]byte
+	var iv [16]byte
+
+	for i:=0;i<32;i++ {key[i]=0}
+	key[0]=1
+	for i:=0;i<16;i++ {iv[i]=byte(i)}
+	for i:=0;i<16;i++ {block[i]=byte(i)}
+
+	a:=NewAES()
+
+	a.Init(aes_CTR16,32,key[:],iv[:])
+	fmt.Printf("Plain= \n")
+	for i:=0;i<16;i++  {fmt.Printf("%02X ", block[i]&0xff)}
+	fmt.Printf("\n")
+
+	a.Encrypt(block[:])
+
+	fmt.Printf("Encrypt= \n") 
+	for i:=0;i<16;i++  {fmt.Printf("%02X ", block[i]&0xff)}
+	fmt.Printf("\n")
+
+	a.Reset(aes_CTR16,iv[:])
+	a.Decrypt(block[:])
+
+	fmt.Printf("Decrypt= \n") 
+	for i:=0;i<16;i++  {fmt.Printf("%02X ", block[i]&0xff)}
+	fmt.Printf("\n")
+
+	a.End();
+}
+*/
diff --git a/version22/go/BIG.go b/version22/go/BIG.go
new file mode 100644
index 0000000..3e0eca5
--- /dev/null
+++ b/version22/go/BIG.go
@@ -0,0 +1,850 @@
+/*
+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.
+*/
+
+/* AMCL BIG number class */ 
+
+package main
+
+import "strconv"
+//import "fmt"
+
+
+type BIG struct {
+	w [NLEN]Chunk
+}
+
+type DBIG struct {
+	w [2*NLEN]Chunk
+}
+
+func (r *BIG) get(i int) Chunk {
+	return r.w[i] 
+}
+
+func (r *BIG) set(i int,x Chunk) {
+	r.w[i]=x	
+}
+
+func (r *BIG) xortop(x Chunk) {
+	r.w[NLEN-1]^=x
+}
+
+/* calculate Field Excess */
+func EXCESS(a *BIG) Chunk {
+	return ((a.w[NLEN-1]&OMASK)>>(MODBITS%BASEBITS))
+}
+
+func FF_EXCESS(a* BIG) Chunk {
+	return ((a.w[NLEN-1]&P_OMASK)>>(P_MB))
+}
+
+/* normalise BIG - force all digits < 2^BASEBITS */
+func (r *BIG) norm() Chunk {
+	carry:=Chunk(0)
+	for i:=0;i<NLEN-1;i++ {
+		d:=r.w[i]+carry
+		r.w[i]=d&BMASK
+		carry=d>>BASEBITS
+	}
+	r.w[NLEN-1]=(r.w[NLEN-1]+carry)
+	return (r.w[NLEN-1]>>((8*MODBYTES)%BASEBITS))  
+}
+
+/* Shift right by less than a word */
+func (r *BIG) fshr(k uint) int {
+	w:=r.w[0]&((Chunk(1)<<k)-1) /* shifted out part */
+	for i:=0;i<NLEN-1;i++ {
+		r.w[i]=(r.w[i]>>k)|((r.w[i+1]<<(BASEBITS-k))&BMASK)
+	}
+	r.w[NLEN-1]=r.w[NLEN-1]>>k
+	return int(w)
+}
+
+/* Shift right by less than a word */
+func (r *BIG) fshl(k uint) int {
+	r.w[NLEN-1]=((r.w[NLEN-1]<<k))|(r.w[NLEN-2]>>(BASEBITS-k))
+	for i:=NLEN-2;i>0;i-- {
+		r.w[i]=((r.w[i]<<k)&BMASK)|(r.w[i-1]>>(BASEBITS-k))
+	}
+	r.w[0]=(r.w[0]<<k)&BMASK
+	return int(r.w[NLEN-1]>>((8*MODBYTES)%BASEBITS)) /* return excess - only used in ff.c */
+}
+
+func NewBIG() *BIG {
+	b:=new(BIG)
+	for i:=0;i<NLEN;i++ {
+		b.w[i]=0
+	}
+	return b
+}
+
+func NewBIGints(x [NLEN]Chunk) *BIG {
+	b:=new(BIG)
+	for i:=0;i<NLEN;i++ {
+		b.w[i]=x[i]
+	}
+	return b	
+}
+
+func NewBIGint(x int) *BIG {
+	b:=new(BIG)
+	b.w[0]=Chunk(x)
+	for i:=1;i<NLEN;i++ {
+		b.w[i]=0
+	}
+	return b
+}
+
+func NewBIGcopy(x *BIG) *BIG {
+	b:=new(BIG)
+	for i:=0;i<NLEN;i++ {
+		b.w[i]=x.w[i]
+	}
+	return b
+}
+
+func NewBIGdcopy(x *DBIG) *BIG {
+	b:=new(BIG)
+	for i:=0;i<NLEN;i++ {
+		b.w[i]=x.w[i]
+	}
+	return b
+}
+
+/* test for zero */
+func (r *BIG) iszilch() bool {
+	for i:=0;i<NLEN;i++ {
+		if r.w[i]!=0 {return false}
+	}
+	return true; 
+}
+
+/* set to zero */
+func (r *BIG) zero() {
+	for i:=0;i<NLEN;i++ {
+		r.w[i]=0
+	}
+}
+
+/* Test for equal to one */
+func (r *BIG) isunity() bool {
+	for i:=1;i<NLEN;i++ {
+		if r.w[i]!=0 {return false}
+	}
+	if r.w[0]!=1 {return false}
+	return true;
+}
+
+
+/* set to one */
+func (r *BIG) one() {
+	r.w[0]=1
+	for i:=1;i<NLEN;i++ {
+		r.w[i]=0
+	}
+}
+
+/* Copy from another BIG */
+func (r *BIG) copy(x *BIG) {
+	for i:=0;i<NLEN;i++ {
+		r.w[i]=x.w[i]
+	}
+}
+
+/* Copy from another DBIG */
+func (r *BIG) dcopy(x *DBIG) {
+	for i:=0;i<NLEN;i++ {
+		r.w[i]=x.w[i]
+	}
+}
+
+/* Conditional swap of two bigs depending on d using XOR - no branches */
+func (r *BIG) cswap(b *BIG,d int) {
+	c:=Chunk(d)
+	c=^(c-1)
+
+	for i:=0;i<NLEN;i++ {
+		t:=c&(r.w[i]^b.w[i])
+		r.w[i]^=t
+		b.w[i]^=t
+	}
+}
+
+func (r *BIG) cmove(g *BIG,d int){
+	b:=Chunk(-d)
+
+	for i:=0;i<NLEN;i++ {
+		r.w[i]^=(r.w[i]^g.w[i])&b
+	}
+}
+
+/* general shift right */
+func (r *BIG) shr(k uint) {
+	n:=(k%BASEBITS)
+	m:=int(k/BASEBITS)	
+	for i:=0;i<NLEN-m-1;i++ {
+		r.w[i]=(r.w[m+i]>>n)|((r.w[m+i+1]<<(BASEBITS-n))&BMASK)
+	}
+	r.w[NLEN-m-1]=r.w[NLEN-1]>>n;
+	for i:=NLEN-m;i<NLEN;i++ {r.w[i]=0}
+}
+
+
+/* general shift left */
+func (r *BIG) shl(k uint) {
+	n:=k%BASEBITS
+	m:=int(k/BASEBITS)
+
+	r.w[NLEN-1]=((r.w[NLEN-1-m]<<n))
+	if NLEN>=m+2 {r.w[NLEN-1]|=(r.w[NLEN-m-2]>>(BASEBITS-n))}
+	for i:=NLEN-2;i>m;i-- {
+		r.w[i]=((r.w[i-m]<<n)&BMASK)|(r.w[i-m-1]>>(BASEBITS-n))
+	}
+	r.w[m]=(r.w[0]<<n)&BMASK; 
+	for i:=0;i<m;i++ {r.w[i]=0}
+}
+
+/* return number of bits */
+func (r *BIG) nbits() int {
+	k:=NLEN-1
+	r.norm()
+	for (k>=0 && r.w[k]==0) {k--}
+	if k<0 {return 0}
+	bts:=int(BASEBITS)*k;
+	c:=r.w[k];
+	for c!=0 {c/=2; bts++}
+	return bts
+}
+
+/* Convert to Hex String */
+func (r *BIG) toString() string {
+	s:=""
+	len:=r.nbits()
+
+	if len%4==0 {
+		len/=4
+	} else {
+		len/=4 
+		len++
+
+	}
+	MB:=int(MODBYTES*2)
+	if len<MB {len=MB}
+
+	for i:=len-1;i>=0;i-- {
+		b:=NewBIGcopy(r)
+		
+		b.shr(uint(i*4))
+		s+=strconv.FormatInt(int64(b.w[0]&15),16)
+	}
+	return s
+}
+
+func (r *BIG) add(x *BIG) {
+	for i:=0;i<NLEN;i++ {
+		r.w[i]=r.w[i]+x.w[i] 
+	}
+}
+
+/* return this+x */
+func (r *BIG) plus(x *BIG) *BIG {
+	s:=new(BIG)
+	for i:=0;i<NLEN;i++ {
+		s.w[i]=r.w[i]+x.w[i];
+	}
+	return s;
+}
+
+/* this+=x, where x is int */
+func (r *BIG) inc(x int) {
+	r.norm();
+	r.w[0]+=Chunk(x);
+}
+
+/* this*=c and catch overflow in DBIG */
+func (r *BIG) pxmul(c int) *DBIG {
+	m:=NewDBIG()	
+	carry:=Chunk(0)
+	for j:=0;j<NLEN;j++ {
+		carry,m.w[j]=muladd(r.w[j],Chunk(c),carry,m.w[j])
+	}
+	m.w[NLEN]=carry;		
+	return m;
+}
+
+/* return this-x */
+func (r *BIG) minus(x *BIG) *BIG {
+	d:=new(BIG)
+	for i:=0;i<NLEN;i++ {
+		d.w[i]=r.w[i]-x.w[i] 
+	}
+	return d;
+}
+
+/* this-=x */
+func (r *BIG) sub(x *BIG) {
+	for i:=0;i<NLEN;i++ {
+		r.w[i]=r.w[i]-x.w[i] 
+	}
+} 
+
+/* reverse subtract this=x-this */ 
+func (r *BIG) rsub(x *BIG) {
+	for i:=0;i<NLEN;i++ {
+		r.w[i]=x.w[i]-r.w[i] 
+	}
+} 
+
+/* this-=x, where x is int */
+func (r *BIG) dec(x int) {
+	r.norm();
+	r.w[0]-=Chunk(x)
+} 
+
+/* this*=x, where x is small int<NEXCESS */
+func (r *BIG) imul(c int) {
+	for i:=0;i<NLEN;i++{ 
+		r.w[i]*=Chunk(c)
+	}
+}
+
+/* this*=x, where x is >NEXCESS */
+func (r *BIG) pmul(c int) Chunk {
+	carry:=Chunk(0)
+	r.norm();
+	for i:=0;i<NLEN;i++ {
+		ak:=r.w[i]
+		r.w[i]=0
+		carry,r.w[i]=muladd(ak,Chunk(c),carry,r.w[i])
+	}
+	return carry
+}
+
+/* convert this BIG to byte array */
+func (r *BIG) tobytearray(b []byte,n int) {
+	r.norm();
+	c:=NewBIGcopy(r)
+
+	for i:=int(MODBYTES)-1;i>=0;i-- {
+		b[i+n]=byte(c.w[0])
+		c.fshr(8)
+	}
+}
+
+/* convert from byte array to BIG */
+func frombytearray(b []byte,n int) *BIG {
+	m:=NewBIG();
+	for i:=0;i<int(MODBYTES);i++ {
+		m.fshl(8); m.w[0]+=Chunk(int(b[i+n]&0xff))
+	}
+	return m
+}
+
+func (r *BIG) toBytes(b []byte) {
+	r.tobytearray(b,0)
+}
+
+func fromBytes(b []byte) *BIG {
+	return frombytearray(b,0)
+}
+
+/* divide by 3 */
+func (r *BIG) div3() int {	
+	carry:=Chunk(0)
+	r.norm();
+	base:=(Chunk(1)<<BASEBITS)
+	for i:=NLEN-1;i>=0;i-- {
+		ak:=(carry*base+r.w[i])
+		r.w[i]=ak/3;
+		carry=ak%3;
+	}
+	return int(carry)
+}
+
+/* return a*b where result fits in a BIG */
+func smul(a *BIG,b *BIG) *BIG {
+	carry:=Chunk(0)
+	c:=NewBIG()
+	for i:=0;i<NLEN;i++ {
+		carry=0;
+		for j:=0;j<NLEN;j++ {
+			if i+j<NLEN {
+				carry,c.w[i+j]=muladd(a.w[i],b.w[j],carry,c.w[i+j])
+				//carry=c.muladd(a.w[i],b.w[j],carry,i+j)
+			}
+		}
+	}
+	return c;
+}
+
+/* reduce a DBIG to a BIG using the appropriate form of the modulus */
+func mod(d *DBIG) *BIG {
+	if MODTYPE==PSEUDO_MERSENNE {
+		t:=d.split(MODBITS)
+		b:=NewBIGdcopy(d)
+
+		v:=t.pmul(int(MConst))
+		tw:=t.w[NLEN-1]
+		t.w[NLEN-1]&=TMASK
+		t.w[0]+=(MConst*((tw>>TBITS)+(v<<(BASEBITS-TBITS))))
+
+		b.add(t)
+		b.norm()
+		return b		
+	}
+	if MODTYPE==MONTGOMERY_FRIENDLY {
+		for i:=0;i<NLEN;i++ {
+			top,bot:=muladd(d.w[i],MConst-1,d.w[i],d.w[NLEN+i-1])
+			d.w[NLEN+i-1]=bot
+			d.w[NLEN+i]+=top
+			//d.w[NLEN+i]+=d.muladd(d.w[i],MConst-1,d.w[i],NLEN+i-1)
+		}
+		b:=NewBIG()
+
+		for i:=0;i<NLEN;i++ {
+			b.w[i]=d.w[NLEN+i]
+		}
+		b.norm()
+		return b		
+	}
+
+	if MODTYPE==GENERALISED_MERSENNE { // GoldiLocks only
+		t:=d.split(MODBITS)
+		b:=NewBIGdcopy(d)
+		b.add(t);
+		dd:=NewDBIGscopy(t)
+		dd.shl(MODBITS/2)
+
+		tt:=dd.split(MODBITS)
+		lo:=NewBIGdcopy(dd)
+		b.add(tt)
+		b.add(lo)
+		b.norm()
+		tt.shl(MODBITS/2)
+		b.add(tt)
+
+		carry:=b.w[NLEN-1]>>TBITS
+		b.w[NLEN-1]&=TMASK
+		b.w[0]+=carry
+			
+		b.w[224/BASEBITS]+=carry<<(224%BASEBITS);
+		b.norm()
+		return b		
+	}
+
+	if MODTYPE==NOT_SPECIAL {
+		md:=NewBIGints(Modulus)
+		return monty(md,MConst,d) 
+	}
+	return NewBIG()
+}
+
+/* Compare a and b, return 0 if a==b, -1 if a<b, +1 if a>b. Inputs must be normalised */
+func comp(a *BIG,b *BIG) int {
+	for i:=NLEN-1;i>=0;i-- {
+		if a.w[i]==b.w[i] {continue}
+		if a.w[i]>b.w[i] {
+			return 1
+		} else  {return -1}
+	}
+	return 0
+}
+
+/* return parity */
+func (r *BIG) parity() int {
+	return int(r.w[0]%2)
+}
+
+/* return n-th bit */
+func (r *BIG) bit(n int) int {
+	if (r.w[n/int(BASEBITS)]&(Chunk(1)<<(uint(n)%BASEBITS)))>0 {return 1}
+	return 0;
+}
+
+/* return n last bits */
+func (r *BIG) lastbits(n int) int {
+	msk:=(1<<uint(n))-1;
+	r.norm();
+	return (int(r.w[0]))&msk
+}
+
+
+/* set x = x mod 2^m */
+func (r *BIG) mod2m(m uint) {
+	wd:=int(m/BASEBITS)
+	bt:=m%BASEBITS
+	msk:=(Chunk(1)<<bt)-1
+	r.w[wd]&=msk
+	for i:=wd+1;i<NLEN;i++ {r.w[i]=0}
+}
+
+/* Arazi and Qi inversion mod 256 */
+func invmod256(a int) int {
+	var t1 int=0
+	c:=(a>>1)&1
+	t1+=c
+	t1&=1
+	t1=2-t1
+	t1<<=1
+	U:=t1+1;
+
+// i=2
+	b:=a&3;
+	t1=U*b; t1>>=2
+	c=(a>>2)&3
+	t2:=(U*c)&3
+	t1+=t2;
+	t1*=U; t1&=3
+	t1=4-t1
+	t1<<=2
+	U+=t1
+
+// i=4
+	b=a&15
+	t1=U*b; t1>>=4
+	c=(a>>4)&15
+	t2=(U*c)&15
+	t1+=t2
+	t1*=U; t1&=15
+	t1=16-t1
+	t1<<=4
+	U+=t1
+
+	return U;
+}
+
+/* a=1/a mod 2^256. This is very fast! */
+func (r *BIG) invmod2m() {
+	U:=NewBIG()
+	b:=NewBIG()
+	c:=NewBIG()
+
+	U.inc(invmod256(r.lastbits(8)))
+
+	for i:=8;i<BIGBITS;i<<=1 {
+		ui:=uint(i);
+		b.copy(r); b.mod2m(ui)
+		t1:=smul(U,b); t1.shr(ui)
+		c.copy(r); c.shr(ui); c.mod2m(ui)
+
+		t2:=smul(U,c); t2.mod2m(ui)
+		t1.add(t2)
+		b=smul(t1,U); t1.copy(b)
+		t1.mod2m(ui);
+
+		t2.one(); t2.shl(ui); t1.rsub(t2); t1.norm()
+		t1.shl(ui);
+		U.add(t1);
+	}
+	U.mod2m(8*MODBYTES)
+	r.copy(U)
+	r.norm()
+}
+
+/* reduce this mod m */
+func (r *BIG) mod(m *BIG) {
+	sr:=NewBIG()
+	r.norm()
+	if comp(r,m)<0 {return}
+
+	m.fshl(1); k:=1
+
+	for comp(r,m)>=0 {
+		m.fshl(1)
+		k++;
+	}
+
+	for k>0 {
+		m.fshr(1);
+
+			sr.copy(r)
+			sr.sub(m)
+			sr.norm()
+			r.cmove(sr,int(1-((sr.w[NLEN-1]>>uint(CHUNK-1))&1)));
+/*
+		if comp(r,m)>=0 {
+			r.sub(m)
+			r.norm()
+		} */
+		k--;
+	}
+}
+
+/* divide this by m */
+func (r *BIG) div(m *BIG) {
+	var d int
+	k:=0
+	r.norm();
+	sr:=NewBIG();
+	e:=NewBIGint(1)
+	b:=NewBIGcopy(r)
+	r.zero();
+
+	for (comp(b,m)>=0) {
+		e.fshl(1)
+		m.fshl(1)
+		k++
+	}
+
+	for k>0 {
+		m.fshr(1)
+		e.fshr(1)
+
+		sr.copy(b);
+		sr.sub(m);
+		sr.norm();
+		d=int(1-((sr.w[NLEN-1]>>uint(CHUNK-1))&1));
+		b.cmove(sr,d);
+		sr.copy(r);
+		sr.add(e);
+		sr.norm();
+		r.cmove(sr,d);
+/*
+		if comp(b,m)>=0 {
+			r.add(e)
+			r.norm()
+			b.sub(m)
+			b.norm()
+		} */
+		k--
+	}
+}
+
+/* get 8*MODBYTES size random number */
+func random(rng *RAND) *BIG {
+	m:=NewBIG()
+	var j int=0
+	var r byte=0
+/* generate random BIG */ 
+	for i:=0;i<8*int(MODBYTES);i++   {
+		if j==0 {
+			r=rng.GetByte()
+		} else {r>>=1}
+
+		b:=Chunk(int(r&1))
+		m.shl(1); m.w[0]+=b// m.inc(b)
+		j++; j&=7; 
+	}
+	return m;
+}
+
+/* Create random BIG in portable way, one bit at a time */
+func randomnum(q *BIG,rng *RAND) *BIG {
+	d:=NewDBIG();
+	var j int=0
+	var r byte=0
+	for i:=0;i<2*int(MODBITS);i++ {
+		if (j==0) {
+			r=rng.GetByte();
+		} else {r>>=1}
+
+		b:=Chunk(int(r&1))
+		d.shl(1); d.w[0]+=b// m.inc(b);
+		j++; j&=7 
+	}
+	m:=d.mod(q)
+	return m;
+}
+
+
+/* return NAF value as +/- 1, 3 or 5. x and x3 should be normed. 
+nbs is number of bits processed, and nzs is number of trailing 0s detected */
+/*
+func nafbits(x *BIG,x3 *BIG ,i int) [3]int {
+	var n [3]int
+	var j int
+	nb:=x3.bit(i)-x.bit(i)
+
+
+	n[1]=1
+	n[0]=0
+	if nb==0 {n[0]=0; return n}
+	if i==0 {n[0]=nb; return n}
+	if nb>0 {
+		n[0]=1;
+	} else  {n[0]=(-1)}
+
+	for j=i-1;j>0;j-- {
+		n[1]++
+		n[0]*=2
+		nb=x3.bit(j)-x.bit(j)
+		if nb>0 {n[0]+=1}
+		if nb<0 {n[0]-=1}
+		if (n[0]>5 || n[0] < -5) {break}
+	}
+
+	if n[0]%2!=0 && j!=0 { // backtrack 
+		if nb>0 {n[0]=(n[0]-1)/2}
+		if nb<0 {n[0]=(n[0]+1)/2}
+		n[1]--
+	}
+	for n[0]%2==0 { // remove trailing zeros 
+		n[0]/=2
+		n[2]++
+		n[1]--
+	}
+	return n;
+}
+*/
+
+/* return a*b mod m */
+func modmul(a,b,m *BIG) *BIG {
+	a.mod(m)
+	b.mod(m)
+	d:=mul(a,b);
+	return d.mod(m)
+}
+
+/* return a^2 mod m */
+func modsqr(a,m *BIG) *BIG {
+	a.mod(m)
+	d:=sqr(a)
+	return d.mod(m)
+}
+
+/* return -a mod m */
+func modneg(a,m *BIG) *BIG {
+	a.mod(m)
+	return m.minus(a)
+}
+
+/* Jacobi Symbol (this/p). Returns 0, 1 or -1 */
+func (r *BIG) jacobi(p *BIG) int {
+	m:=0;
+	t:=NewBIGint(0)
+	x:=NewBIGint(0)
+	n:=NewBIGint(0)
+	zilch:=NewBIGint(0)
+	one:=NewBIGint(1)
+	if (p.parity()==0 || comp(r,zilch)==0 || comp(p,one)<=0) {return 0}
+	r.norm()
+	x.copy(r)
+	n.copy(p)
+	x.mod(p)
+
+	for comp(n,one)>0 {
+		if comp(x,zilch)==0 {return 0}
+		n8:=n.lastbits(3)
+		k:=0
+		for x.parity()==0 {
+			k++
+			x.shr(1)
+		}
+		if k%2==1 {m+=(n8*n8-1)/8}
+		m+=(n8-1)*(x.lastbits(2)-1)/4
+		t.copy(n)
+		t.mod(x)
+		n.copy(x)
+		x.copy(t)
+		m%=2
+
+	}
+	if m==0 {return 1}
+	return -1
+}
+
+/* this=1/this mod p. Binary method */
+func (r *BIG) invmodp(p *BIG) {
+	r.mod(p)
+	u:=NewBIGcopy(r)
+
+	v:=NewBIGcopy(p)
+	x1:=NewBIGint(1)
+	x2:=NewBIGint(0)
+	t:=NewBIGint(0)
+	one:=NewBIGint(1)
+	for (comp(u,one)!=0 && comp(v,one)!=0) {
+		for u.parity()==0 {
+			u.shr(1);
+			if x1.parity()!=0 {
+				x1.add(p)
+				x1.norm()
+			}
+			x1.shr(1)
+		}
+		for v.parity()==0 {
+			v.shr(1);
+			if x2.parity()!=0 {
+				x2.add(p)
+				x2.norm()
+			}
+			x2.shr(1)
+		}
+		if comp(u,v)>=0 {
+			u.sub(v)
+			u.norm()
+			if comp(x1,x2)>=0 {
+				x1.sub(x2)
+			} else {
+				t.copy(p)
+				t.sub(x2)
+				x1.add(t)
+			}
+			x1.norm()
+		} else {
+			v.sub(u)
+			v.norm()
+			if comp(x2,x1)>=0 { 
+				x2.sub(x1)
+			} else {
+				t.copy(p)
+				t.sub(x1)
+				x2.add(t)
+			}
+			x2.norm()
+		}
+	}
+	if comp(u,one)==0 {
+		r.copy(x1)
+	} else {r.copy(x2)}
+}
+
+/* return this^e mod m */
+func (r *BIG) powmod(e *BIG,m *BIG) *BIG {
+	r.norm()
+	e.norm()
+	a:=NewBIGint(1)
+	z:=NewBIGcopy(e)
+	s:=NewBIGcopy(r)
+	for true {
+		bt:=z.parity()
+		z.fshr(1)
+		if bt==1 {a=modmul(a,s,m)}
+		if z.iszilch() {break}
+		s=modsqr(s,m)
+	}
+	return a;
+}
+/*
+func main() {
+	a := NewBIGint(3)
+	m := NewBIGints(Modulus)
+
+	fmt.Printf("Modulus= "+m.toString())
+	fmt.Printf("\n")
+
+
+	e := NewBIGcopy(m);
+	e.dec(1); e.norm();
+	fmt.Printf("Exponent= "+e.toString())
+	fmt.Printf("\n")
+	a=a.powmod(e,m);
+	fmt.Printf("Result= "+a.toString())
+}
+*/
diff --git a/version22/go/BenchtestEC.go b/version22/go/BenchtestEC.go
new file mode 100644
index 0000000..86510c0
--- /dev/null
+++ b/version22/go/BenchtestEC.go
@@ -0,0 +1,154 @@
+/*
+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.
+*/
+
+/* Test and benchmark elliptic curve and RSA functions */
+
+package main
+
+import "fmt"
+
+import "time"
+
+const MIN_TIME int=10
+const MIN_ITERS int=10
+
+func main() {
+
+	var RAW [100]byte
+	var P [RSA_RFS]byte
+	var M [RSA_RFS]byte
+	var C [RSA_RFS]byte
+
+	rng:=NewRAND()
+
+	rng.Clean();
+	for i:=0;i<100;i++ {RAW[i]=byte(i)}
+
+	rng.Seed(100,RAW[:])
+
+	pub:=New_rsa_public_key(FFLEN)
+	priv:=New_rsa_private_key(HFLEN)
+
+	if CURVETYPE==WEIERSTRASS {
+		fmt.Printf("Weierstrass parameterization\n")
+	}		
+	if CURVETYPE==EDWARDS {
+		fmt.Printf("Edwards parameterization\n")
+	}
+	if CURVETYPE==MONTGOMERY {
+		fmt.Printf("Montgomery parameterization\n")
+	}
+
+	if MODTYPE==PSEUDO_MERSENNE {
+		fmt.Printf("Pseudo-Mersenne Modulus\n")
+	}
+	if MODTYPE==MONTGOMERY_FRIENDLY {
+		fmt.Printf("Montgomery friendly Modulus\n")
+	}
+	if MODTYPE==GENERALISED_MERSENNE {
+		fmt.Printf("Generalised-Mersenne Modulus\n")
+	}
+	if MODTYPE==NOT_SPECIAL {
+		fmt.Printf("Not special Modulus\n")
+	}
+
+	fmt.Printf("Modulus size %d bits\n",MODBITS)
+	fmt.Printf("%d bit build\n",CHUNK)
+
+	var s *BIG
+	var G *ECP
+
+	gx:=NewBIGints(CURVE_Gx)
+	if CURVETYPE!=MONTGOMERY {
+		gy:=NewBIGints(CURVE_Gy)
+		G=NewECPbigs(gx,gy)
+	} else {
+		G=NewECPbig(gx)
+	}
+
+	r:=NewBIGints(CURVE_Order)
+	s=randomnum(r,rng)
+
+	WP:=G.mul(r)
+	if !WP.is_infinity() {
+		fmt.Printf("FAILURE - rG!=O\n")
+		return
+	}
+
+	start := time.Now()
+	iterations:=0
+	elapsed:=time.Since(start)
+	for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS {
+		WP=G.mul(s)
+		iterations++
+		elapsed=time.Since(start)
+	} 
+	dur:=float64(elapsed/time.Millisecond)/float64(iterations)
+	fmt.Printf("EC  mul - %8d iterations  ",iterations)
+	fmt.Printf(" %8.2f ms per iteration\n",dur)
+
+	fmt.Printf("Generating %d-bit RSA public/private key pair\n",FFLEN*BIGBITS);
+
+	start = time.Now()
+	iterations=0
+	elapsed=time.Since(start)
+	for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS {
+		RSA_KEY_PAIR(rng,65537,priv,pub)
+		iterations++
+		elapsed=time.Since(start)
+	} 
+	dur=float64(elapsed/time.Millisecond)/float64(iterations)
+	fmt.Printf("RSA gen - %8d iterations  ",iterations)
+	fmt.Printf(" %8.2f ms per iteration\n",dur)
+
+	for i:=0;i<RSA_RFS;i++ {M[i]=byte(i%128)};
+
+	start = time.Now()
+	iterations=0
+	elapsed=time.Since(start)
+	for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS {
+		RSA_ENCRYPT(pub,M[:],C[:])
+		iterations++
+		elapsed=time.Since(start)
+	} 
+	dur=float64(elapsed/time.Millisecond)/float64(iterations)
+	fmt.Printf("RSA enc - %8d iterations  ",iterations)
+	fmt.Printf(" %8.2f ms per iteration\n",dur)
+
+	start = time.Now()
+	iterations=0
+	elapsed=time.Since(start)
+	for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS {
+		RSA_DECRYPT(priv,C[:],P[:])
+		iterations++
+		elapsed=time.Since(start)
+	} 
+	dur=float64(elapsed/time.Millisecond)/float64(iterations)
+	fmt.Printf("RSA dec - %8d iterations  ",iterations)
+	fmt.Printf(" %8.2f ms per iteration\n",dur)
+
+	for i:=0;i<RSA_RFS;i++ {
+		if (P[i]!=M[i]) {
+			fmt.Printf("FAILURE - RSA decryption\n")
+			return
+		}
+	}
+
+	fmt.Printf("All tests pass\n")
+}
diff --git a/version22/go/BenchtestPAIR.go b/version22/go/BenchtestPAIR.go
new file mode 100644
index 0000000..bb1f710
--- /dev/null
+++ b/version22/go/BenchtestPAIR.go
@@ -0,0 +1,206 @@
+/*
+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.
+*/
+
+/* Test and benchmark elliptic curve and RSA functions */
+
+package main
+
+import "fmt"
+
+import "time"
+
+const MIN_TIME int=10
+const MIN_ITERS int=10
+
+func main() {
+	var RAW [100]byte
+
+	rng:=NewRAND()
+
+	rng.Clean();
+	for i:=0;i<100;i++ {RAW[i]=byte(i)}
+
+	rng.Seed(100,RAW[:])
+
+	if CURVE_PAIRING_TYPE==BN_CURVE {
+		fmt.Printf("BN Pairing-Friendly Curve\n")
+	}
+	if CURVE_PAIRING_TYPE==BLS_CURVE {
+		fmt.Printf("BLS Pairing-Friendly Curve\n")
+	}
+
+	fmt.Printf("Modulus size %d bits\n",MODBITS)
+	fmt.Printf("%d bit build\n",CHUNK)
+
+	G:=NewECPbigs(NewBIGints(CURVE_Gx),NewBIGints(CURVE_Gy))
+	r:=NewBIGints(CURVE_Order)
+	s:=randomnum(r,rng)
+
+	P:=G1mul(G,r)
+
+	if !P.is_infinity() {
+		fmt.Printf("FAILURE - rP!=O\n");
+		return;
+	}
+
+	start := time.Now()
+	iterations:=0
+	elapsed:=time.Since(start)
+	for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS {
+		P=G1mul(G,s)
+		iterations++
+		elapsed=time.Since(start)
+	} 
+	dur:=float64(elapsed/time.Millisecond)/float64(iterations)
+	fmt.Printf("G1 mul              - %8d iterations  ",iterations)
+	fmt.Printf(" %8.2f ms per iteration\n",dur)
+
+	Q:=NewECP2fp2s(NewFP2bigs(NewBIGints(CURVE_Pxa),NewBIGints(CURVE_Pxb)),NewFP2bigs(NewBIGints(CURVE_Pya),NewBIGints(CURVE_Pyb)))
+	W:=G2mul(Q,r)
+
+	if !W.is_infinity() {
+		fmt.Printf("FAILURE - rQ!=O\n");
+		return;
+	}
+
+	start = time.Now()
+	iterations=0
+	elapsed=time.Since(start)
+	for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS {
+		W=G2mul(Q,s)
+		iterations++
+		elapsed=time.Since(start)
+	} 
+	dur=float64(elapsed/time.Millisecond)/float64(iterations)
+	fmt.Printf("G2 mul              - %8d iterations  ",iterations)
+	fmt.Printf(" %8.2f ms per iteration\n",dur)
+
+	w:=ate(Q,P)
+	w=fexp(w)
+
+	g:=GTpow(w,r)
+
+	if !g.isunity() {
+		fmt.Printf("FAILURE - g^r!=1\n");
+		return;
+	}
+
+	start = time.Now()
+	iterations=0
+	elapsed=time.Since(start)
+	for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS {
+		g=GTpow(w,s)
+		iterations++
+		elapsed=time.Since(start)
+	} 
+	dur=float64(elapsed/time.Millisecond)/float64(iterations)
+	fmt.Printf("GT pow              - %8d iterations  ",iterations)
+	fmt.Printf(" %8.2f ms per iteration\n",dur)
+
+	f:=NewFP2bigs(NewBIGints(CURVE_Fra),NewBIGints(CURVE_Frb))
+	q:=NewBIGints(Modulus)
+
+	m:=NewBIGcopy(q)
+	m.mod(r)
+
+	a:=NewBIGcopy(s)
+	a.mod(m)
+
+	b:=NewBIGcopy(s)
+	b.div(m)
+
+	g.copy(w)
+	c:=g.trace()
+
+	g.frob(f)
+	cp:=g.trace()
+
+	w.conj()
+	g.mul(w)
+	cpm1:=g.trace()
+	g.mul(w)
+	cpm2:=g.trace()
+
+	start = time.Now()
+	iterations=0
+	elapsed=time.Since(start)
+	for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS {
+		c=c.xtr_pow2(cp,cpm1,cpm2,a,b)
+		iterations++
+		elapsed=time.Since(start)
+	} 
+	dur=float64(elapsed/time.Millisecond)/float64(iterations)
+	fmt.Printf("GT pow (compressed) - %8d iterations  ",iterations)
+	fmt.Printf(" %8.2f ms per iteration\n",dur)
+
+	start = time.Now()
+	iterations=0
+	elapsed=time.Since(start)
+	for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS {
+		w=ate(Q,P)
+		iterations++
+		elapsed=time.Since(start)
+	} 
+	dur=float64(elapsed/time.Millisecond)/float64(iterations)
+	fmt.Printf("PAIRing ATE         - %8d iterations  ",iterations)
+	fmt.Printf(" %8.2f ms per iteration\n",dur)
+
+	start = time.Now()
+	iterations=0
+	elapsed=time.Since(start)
+	for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS {
+		g=fexp(w)
+		iterations++
+		elapsed=time.Since(start)
+	} 
+	dur=float64(elapsed/time.Millisecond)/float64(iterations)
+	fmt.Printf("PAIRing FEXP        - %8d iterations  ",iterations)
+	fmt.Printf(" %8.2f ms per iteration\n",dur)
+
+	P.copy(G)
+	Q.copy(W)
+
+	P=G1mul(P,s)
+
+	g=ate(Q,P)
+	g=fexp(g)
+
+	P.copy(G)
+	Q=G2mul(Q,s)
+
+	w=ate(Q,P)
+	w=fexp(w)
+
+	if !g.equals(w) {
+		fmt.Printf("FAILURE - e(sQ,p)!=e(Q,sP) \n")
+		return
+	}
+
+	Q.copy(W);
+	g=ate(Q,P)
+	g=fexp(g)
+	g=GTpow(g,s)
+
+	if !g.equals(w) {
+		fmt.Printf("FAILURE - e(sQ,p)!=e(Q,P)^s \n")
+		return
+	}
+
+	fmt.Printf("All tests pass\n") 
+}
diff --git a/version22/go/DBIG.go b/version22/go/DBIG.go
new file mode 100644
index 0000000..b58b0c0
--- /dev/null
+++ b/version22/go/DBIG.go
@@ -0,0 +1,256 @@
+/*
+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.
+*/
+
+/* MiotCL double length DBIG number class */ 
+
+
+package main
+
+import "strconv"
+//import "fmt"
+
+func NewDBIG() *DBIG {
+	b:=new(DBIG)
+	for i:=0;i<DNLEN;i++ {
+		b.w[i]=0
+	}
+	return b
+}
+
+func NewDBIGcopy(x *DBIG) *DBIG {
+	b:=new(DBIG)
+	for i:=0;i<DNLEN;i++ {
+		b.w[i]=x.w[i]
+	}
+	return b
+}
+
+func NewDBIGscopy(x *BIG) *DBIG {
+	b:=new(DBIG)
+	for i:=0;i<NLEN-1;i++ {
+		b.w[i]=x.w[i]
+	}
+	b.w[NLEN-1]=x.get(NLEN-1)&BMASK /* top word normalized */
+	b.w[NLEN]=x.get(NLEN-1)>>BASEBITS
+
+	for i:=NLEN+1;i<DNLEN;i++  {b.w[i]=0}
+	return b
+}
+
+/* normalise this */
+func (r *DBIG) norm() {
+	carry:=Chunk(0)
+	for i:=0;i<DNLEN-1;i++ {
+		d:=r.w[i]+carry
+		r.w[i]=d&BMASK
+		carry=d>>BASEBITS
+	}
+	r.w[DNLEN-1]=(r.w[DNLEN-1]+carry)
+}
+
+/* split DBIG at position n, return higher half, keep lower half */
+func (r *DBIG) split(n uint) *BIG {
+	t:=NewBIG()
+	m:=n%BASEBITS;
+	carry:=r.w[DNLEN-1]<<(BASEBITS-m)
+
+	for i:=DNLEN-2;i>=NLEN-1;i-- {
+		nw:=(r.w[i]>>m)|carry;
+		carry=(r.w[i]<<(BASEBITS-m))&BMASK;
+		t.set(i-NLEN+1,nw);
+	}
+	r.w[NLEN-1]&=((Chunk(1)<<m)-1)
+	return t;
+}
+
+func (r *DBIG) cmove(g *DBIG,d int){
+	var b=Chunk(-d)
+
+	for i:=0;i<DNLEN;i++ {
+		r.w[i]^=(r.w[i]^g.w[i])&b
+	}
+}
+
+/* Compare a and b, return 0 if a==b, -1 if a<b, +1 if a>b. Inputs must be normalised */
+func dcomp(a *DBIG,b *DBIG) int {
+	for i:=DNLEN-1;i>=0;i-- {
+		if a.w[i]==b.w[i] {continue}
+		if a.w[i]>b.w[i] {
+			return 1
+		} else  {return -1}
+	}
+	return 0
+}
+
+/* Copy from another BIG */
+func (r *DBIG) copy(x *DBIG) {
+	for i:=0;i<DNLEN;i++ {
+		r.w[i]=x.w[i]
+	}
+}
+
+func (r *DBIG) add(x *DBIG) {
+	for i:=0;i<DNLEN;i++ {
+		r.w[i]=r.w[i]+x.w[i] 
+	}
+}
+
+/* this-=x */
+func (r *DBIG) sub(x *DBIG) {
+	for i:=0;i<DNLEN;i++ {
+		r.w[i]=r.w[i]-x.w[i] 
+	}
+} 
+
+/* general shift left */
+func (r *DBIG) shl(k uint) {
+	n:=k%BASEBITS
+	m:=int(k/BASEBITS)
+
+	r.w[DNLEN-1]=((r.w[DNLEN-1-m]<<n))|(r.w[DNLEN-m-2]>>(BASEBITS-n))
+	for i:=DNLEN-2;i>m;i-- {
+		r.w[i]=((r.w[i-m]<<n)&BMASK)|(r.w[i-m-1]>>(BASEBITS-n))
+	}
+	r.w[m]=(r.w[0]<<n)&BMASK; 
+	for i:=0;i<m;i++ {r.w[i]=0}
+}
+
+/* general shift right */
+func (r *DBIG) shr(k uint) {
+	n:=(k%BASEBITS)
+	m:=int(k/BASEBITS)	
+	for i:=0;i<DNLEN-m-1;i++ {
+		r.w[i]=(r.w[m+i]>>n)|((r.w[m+i+1]<<(BASEBITS-n))&BMASK)
+	}
+	r.w[DNLEN-m-1]=r.w[DNLEN-1]>>n;
+	for i:=DNLEN-m;i<DNLEN;i++ {r.w[i]=0}
+}
+
+/* reduces this DBIG mod a BIG, and returns the BIG */
+func (r *DBIG) mod(c *BIG) *BIG {
+	r.norm()
+	m:=NewDBIGscopy(c)
+	dr:=NewDBIG();
+
+	if dcomp(r,m)<0 {
+		return NewBIGdcopy(r)
+	}
+
+	m.shl(1);
+	k:=1;
+		
+	for dcomp(r,m)>=0 {
+		m.shl(1);
+		k++;
+	}
+
+	for k>0 {
+		m.shr(1);
+
+		dr.copy(r);
+		dr.sub(m);
+		dr.norm();
+		r.cmove(dr,int(1-((dr.w[DNLEN-1]>>uint(CHUNK-1))&1)));
+/*
+		if dcomp(r,m)>=0 {
+			r.sub(m);
+			r.norm();
+		} */
+		k--;
+	}
+	return NewBIGdcopy(r)
+}
+
+/* return this/c */
+func (r *DBIG) div(c *BIG) *BIG {
+	var d int
+	k:=0
+	m:=NewDBIGscopy(c)
+	a:=NewBIGint(0)
+	e:=NewBIGint(1)
+	sr:=NewBIG()
+	dr:=NewDBIG()
+	r.norm()
+
+	for dcomp(r,m)>=0 {
+		e.fshl(1)
+		m.shl(1)
+		k++
+	}
+
+	for k>0 {
+		m.shr(1)
+		e.shr(1)
+
+		dr.copy(r);
+		dr.sub(m);
+		dr.norm();
+		d=int(1-((dr.w[DNLEN-1]>>uint(CHUNK-1))&1));
+		r.cmove(dr,d);
+		sr.copy(a);
+		sr.add(e);
+		sr.norm();
+		a.cmove(sr,d);
+
+/*
+		if dcomp(r,m)>0 {
+			a.add(e)
+			a.norm()
+			r.sub(m)
+			r.norm()
+		} */
+		k--
+	}
+	return a
+}
+
+/* Convert to Hex String */
+func (r *DBIG) toString() string {
+	s:=""
+	len:=r.nbits()
+
+	if len%4==0 {
+		len/=4
+	} else {
+		len/=4 
+		len++
+
+	}
+
+	for i:=len-1;i>=0;i-- {
+		b:=NewDBIGcopy(r)
+		
+		b.shr(uint(i*4))
+		s+=strconv.FormatInt(int64(b.w[0]&15),16)
+	}
+	return s
+}
+
+/* return number of bits */
+func (r *DBIG) nbits() int {
+	k:=DNLEN-1
+	r.norm()
+	for (k>=0 && r.w[k]==0) {k--}
+	if k<0 {return 0}
+	bts:=int(BASEBITS)*k;
+	c:=r.w[k];
+	for c!=0 {c/=2; bts++}
+	return bts
+}
+
diff --git a/version22/go/ECDH.go b/version22/go/ECDH.go
new file mode 100644
index 0000000..9656113
--- /dev/null
+++ b/version22/go/ECDH.go
@@ -0,0 +1,547 @@
+/*
+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.
+*/
+
+/* Elliptic Curve API high-level functions  */
+
+package main
+
+//import "fmt"
+
+const ECDH_INVALID_PUBLIC_KEY int=-2
+const ECDH_ERROR int=-3
+const ECDH_INVALID int=-4
+const ECDH_EFS int=int(MODBYTES)
+const ECDH_EGS int=int(MODBYTES)
+const ECDH_EAS int=16
+const ECDH_EBS int=16
+const ECDH_SHA256 int=32
+const ECDH_SHA384 int=48
+const ECDH_SHA512 int=64
+
+const ECDH_HASH_TYPE int=ECDH_SHA512
+
+/* Convert Integer to n-byte array */
+func inttoBytes(n int,len int) []byte {
+	var b []byte
+	var i int
+	for i=0;i<len;i++ {b=append(b,0)}
+	i=len
+	for (n>0 && i>0) {
+		i--;
+		b[i]=byte(n&0xff)
+		n/=256
+	}	
+	return b
+}
+
+func ehashit(sha int,A []byte,n int,B []byte,pad int) []byte {
+	var R []byte
+	if sha==ECDH_SHA256 {
+		H:=NewHASH256()
+		H.Process_array(A)
+		if n>0 {H.Process_num(int32(n))}
+		if B!=nil {H.Process_array(B)}
+		R=H.Hash()
+	}
+	if sha==ECDH_SHA384 {
+		H:=NewHASH384()
+		H.Process_array(A)
+		if n>0 {H.Process_num(int32(n))}
+		if B!=nil {H.Process_array(B)}
+		R=H.Hash()
+	}
+	if sha==ECDH_SHA512 {
+		H:=NewHASH512()
+		H.Process_array(A)
+		if n>0 {H.Process_num(int32(n))}
+		if B!=nil {H.Process_array(B)}
+		R=H.Hash()
+	}
+	if R==nil {return nil}
+
+	if pad==0 {return R}
+	var W []byte
+	for i:=0;i<pad;i++ {W=append(W,0)}
+	if pad<=sha {
+		for i:=0;i<pad;i++ {W[i]=R[i]}
+	} else {
+		for i:=0;i<sha;i++ {W[i]=R[i]}
+		for i:=sha;i<pad;i++ {W[i]=0}
+	}
+	return W
+}
+
+/* Key Derivation Functions */
+/* Input octet Z */
+/* Output key of length olen */
+func KDF1(sha int,Z []byte,olen int) []byte {
+/* NOTE: the parameter olen is the length of the output K in bytes */
+	hlen:=sha
+	var K []byte
+	k:=0
+    
+	for i:=0;i<olen;i++ {K=append(K,0)}
+
+	cthreshold:=olen/hlen; if olen%hlen!=0 {cthreshold++}
+
+	for counter:=0;counter<cthreshold;counter++ {
+		B:=ehashit(sha,Z,counter,nil,0)
+		if k+hlen>olen {
+			for i:=0;i<olen%hlen;i++ {K[k]=B[i]; k++}
+		} else {
+			for i:=0;i<hlen;i++ {K[k]=B[i]; k++}
+		}
+	}
+	return K;
+}
+
+func KDF2(sha int,Z []byte,P []byte,olen int) []byte {
+/* NOTE: the parameter olen is the length of the output k in bytes */
+	hlen:=sha
+	var K []byte
+	k:=0
+    
+	for i:=0;i<olen;i++ {K=append(K,0)}
+
+	cthreshold:=olen/hlen; if olen%hlen!=0 {cthreshold++}
+
+	for counter:=1;counter<=cthreshold;counter++ {
+		B:=ehashit(sha,Z,counter,P,0)
+		if k+hlen>olen {
+			for i:=0;i<olen%hlen;i++ {K[k]=B[i]; k++}
+		} else {
+			for i:=0;i<hlen;i++ {K[k]=B[i]; k++}
+		}
+	}
+	return K
+}
+
+/* Password based Key Derivation Function */
+/* Input password p, salt s, and repeat count */
+/* Output key of length olen */
+func PBKDF2(sha int,Pass []byte,Salt []byte,rep int,olen int) []byte {
+	d:=olen/sha; if olen%sha!=0 {d++}
+
+	var F []byte
+	var U []byte
+	var S []byte
+	var K []byte
+	
+	for i:=0;i<sha;i++{F=append(F,0); U=append(U,0)}
+
+	for i:=1;i<=d;i++ {
+		for j:=0;j<len(Salt);j++ {S=append(S,Salt[j])} 
+		N:=inttoBytes(i,4)
+		for j:=0;j<4;j++ {S=append(S,N[j])}   
+
+		HMAC(sha,S,Pass,F[:])
+
+		for j:=0;j<sha;j++ {U[j]=F[j]}
+		for j:=2;j<=rep;j++ {
+			HMAC(sha,U[:],Pass,U[:]);
+			for k:=0;k<sha;k++ {F[k]^=U[k]}
+		}
+		for j:=0;j<sha;j++ {K=append(K,F[j])} 
+	}
+	var key []byte
+	for i:=0;i<olen;i++ {key=append(key,K[i])}
+	return key
+}
+
+/* Calculate HMAC of m using key k. HMAC is tag of length olen (which is length of tag) */
+func HMAC(sha int,M []byte,K []byte,tag []byte) int {
+	/* Input is from an octet m        *
+	* olen is requested output length in bytes. k is the key  *
+	* The output is the calculated tag */
+	var B []byte
+	b:=64
+	if sha>32 {b=128}
+
+	var K0 [128]byte
+	olen:=len(tag)
+
+	if (olen<4 /*|| olen>sha */) {return 0}
+
+	for i:=0;i<b;i++ {K0[i]=0}
+
+	if len(K) > b {
+		B=ehashit(sha,K,0,nil,0) 
+		for i:=0;i<sha;i++ {K0[i]=B[i]}
+	} else {
+		for i:=0;i<len(K);i++  {K0[i]=K[i]}
+	}
+		
+	for i:=0;i<b;i++ {K0[i]^=0x36}
+	B=ehashit(sha,K0[0:b],0,M,0);
+
+	for i:=0;i<b;i++ {K0[i]^=0x6a}
+	B=ehashit(sha,K0[0:b],0,B,olen)
+
+	for i:=0;i<olen;i++ {tag[i]=B[i]}
+
+	return 1
+}
+
+/* AES encryption/decryption. Encrypt byte array M using key K and returns ciphertext */
+func AES_CBC_IV0_ENCRYPT(K []byte,M []byte) []byte { /* AES CBC encryption, with Null IV and key K */
+	/* Input is from an octet string M, output is to an octet string C */
+	/* Input is padded as necessary to make up a full final block */
+	a:=NewAES()
+	fin:=false
+
+	var buff [16]byte
+	var C []byte
+
+	a.Init(aes_CBC,len(K),K,nil)
+
+	ipt:=0; //opt:=0
+	var i int
+	for true {
+		for i=0;i<16;i++ {
+			if ipt<len(M) {
+				buff[i]=M[ipt]; ipt++;
+			} else {fin=true; break;}
+		}
+		if fin {break}
+		a.Encrypt(buff[:])
+		for i=0;i<16;i++ {
+			C=append(C,buff[i])
+		}
+	}    
+
+/* last block, filled up to i-th index */
+
+	padlen:=16-i
+	for j:=i;j<16;j++ {buff[j]=byte(padlen)}
+
+	a.Encrypt(buff[:])
+
+	for i=0;i<16;i++ {
+		C=append(C,buff[i])
+	}
+	a.End()   
+	return C
+}
+
+/* returns plaintext if all consistent, else returns null string */
+func AES_CBC_IV0_DECRYPT(K []byte,C []byte) []byte { /* padding is removed */
+	a:=NewAES()
+	var buff [16]byte
+	var MM []byte
+	var M []byte
+
+	var i int
+	ipt:=0; opt:=0
+
+	a.Init(aes_CBC,len(K),K,nil);
+
+	if len(C)==0 {return nil}
+	ch:=C[ipt]; ipt++
+  
+	fin:=false
+
+	for true {
+		for i=0;i<16;i++ {
+			buff[i]=ch    
+			if ipt>=len(C) {
+				fin=true; break
+			}  else {ch=C[ipt]; ipt++ }
+		}
+		a.Decrypt(buff[:])
+		if fin {break}
+		for i=0;i<16;i++ {
+			MM=append(MM,buff[i]); opt++
+		}
+	}    
+
+	a.End();
+	bad:=false
+	padlen:=int(buff[15])
+	if (i!=15 || padlen<1 || padlen>16) {bad=true}
+	if (padlen>=2 && padlen<=16) {
+		for i=16-padlen;i<16;i++ {
+			if buff[i]!=byte(padlen) {bad=true}
+		}
+	}
+    
+	if !bad { 
+		for i=0;i<16-padlen;i++ {
+			MM=append(MM,buff[i]); opt++
+		}
+	}
+
+	if bad {return nil}
+
+	for i=0;i<opt;i++ {M=append(M,MM[i])}
+
+	return M;
+}
+
+/* Calculate a public/private EC GF(p) key pair W,S where W=S.G mod EC(p),
+ * where S is the secret key and W is the public key
+ * and G is fixed generator.
+ * If RNG is NULL then the private key is provided externally in S
+ * otherwise it is generated randomly internally */
+func ECDH_KEY_PAIR_GENERATE(RNG *RAND,S []byte,W []byte) int {
+	res:=0
+//	var T [ECDH_EFS]byte
+	var s *BIG
+	var G *ECP
+
+	gx:=NewBIGints(CURVE_Gx)
+	if CURVETYPE!=MONTGOMERY {
+		gy:=NewBIGints(CURVE_Gy)
+		G=NewECPbigs(gx,gy)
+	} else {
+		G=NewECPbig(gx)
+	}
+
+	r:=NewBIGints(CURVE_Order)
+
+	if RNG==nil {
+		s=fromBytes(S)
+		s.mod(r)
+	} else {
+		s=randomnum(r,RNG)
+		
+	//	s.toBytes(T[:])
+	//	for i:=0;i<ECDH_EGS;i++ {S[i]=T[i]}
+	}
+
+	if AES_S>0 {
+		s.mod2m(2*AES_S)
+	}
+	s.toBytes(S)
+
+	WP:=G.mul(s)
+
+	WP.toBytes(W)
+
+	return res
+}
+
+/* validate public key. Set full=true for fuller check */
+func ECDH_PUBLIC_KEY_VALIDATE(full bool,W []byte) int {
+	WP:=ECP_fromBytes(W)
+	res:=0
+
+	r:=NewBIGints(CURVE_Order)
+
+	if WP.is_infinity() {res=ECDH_INVALID_PUBLIC_KEY}
+	if res==0 && full {
+		WP=WP.mul(r)
+		if !WP.is_infinity() {res=ECDH_INVALID_PUBLIC_KEY} 
+	}
+	return res
+}
+
+/* IEEE-1363 Diffie-Hellman online calculation Z=S.WD */
+func ECPSVDP_DH(S []byte,WD []byte,Z []byte) int {
+	res:=0;
+	var T [ECDH_EFS]byte
+
+	s:=fromBytes(S)
+
+	W:=ECP_fromBytes(WD)
+	if W.is_infinity() {res=ECDH_ERROR}
+
+	if res==0 {
+		r:=NewBIGints(CURVE_Order)
+		s.mod(r)
+		W=W.mul(s)
+		if W.is_infinity() { 
+			res=ECDH_ERROR
+		} else {
+			W.getX().toBytes(T[:])
+			for i:=0;i<ECDH_EFS;i++ {Z[i]=T[i]}
+		}
+	}
+	return res
+}
+
+/* IEEE ECDSA Signature, C and D are signature on F using private key S */
+func ECPSP_DSA(sha int,RNG *RAND,S []byte,F []byte,C []byte,D []byte) int {
+	var T [ECDH_EFS]byte
+
+	B:=ehashit(sha,F,0,nil,int(MODBYTES));
+
+	gx:=NewBIGints(CURVE_Gx)
+	gy:=NewBIGints(CURVE_Gy)
+
+	G:=NewECPbigs(gx,gy)
+	r:=NewBIGints(CURVE_Order)
+
+	s:=fromBytes(S)
+	f:=fromBytes(B[:])
+
+	c:=NewBIGint(0)
+	d:=NewBIGint(0)
+	V:=NewECP()
+
+	for d.iszilch() {
+		u:=randomnum(r,RNG);
+		w:=randomnum(r,RNG);
+		if AES_S>0 {
+			u.mod2m(2*AES_S)
+		}			
+		V.copy(G)
+		V=V.mul(u)   		
+		vx:=V.getX()
+		c.copy(vx)
+		c.mod(r);
+		if c.iszilch() {continue}
+		u.copy(modmul(u,w,r))
+		u.invmodp(r)
+		d.copy(modmul(s,c,r))
+		d.add(f)
+		d.copy(modmul(d,w,r))
+		d.copy(modmul(u,d,r))
+	} 
+       
+	c.toBytes(T[:])
+	for i:=0;i<ECDH_EFS;i++ {C[i]=T[i]}
+	d.toBytes(T[:])
+	for i:=0;i<ECDH_EFS;i++ {D[i]=T[i]}
+	return 0
+}
+
+/* IEEE1363 ECDSA Signature Verification. Signature C and D on F is verified using public key W */
+func ECPVP_DSA(sha int,W []byte,F []byte,C []byte,D []byte) int {
+	res:=0
+
+	B:=ehashit(sha,F,0,nil,int(MODBYTES));
+
+	gx:=NewBIGints(CURVE_Gx)
+	gy:=NewBIGints(CURVE_Gy)
+
+	G:=NewECPbigs(gx,gy)
+	r:=NewBIGints(CURVE_Order)
+
+	c:=fromBytes(C)
+	d:=fromBytes(D)
+	f:=fromBytes(B[:])
+     
+	if (c.iszilch() || comp(c,r)>=0 || d.iszilch() || comp(d,r)>=0) {
+            res=ECDH_INVALID;
+	}
+
+	if res==0 {
+		d.invmodp(r)
+		f.copy(modmul(f,d,r))
+		h2:=modmul(c,d,r)
+
+		WP:=ECP_fromBytes(W)
+		if WP.is_infinity() {
+			res=ECDH_ERROR
+		} else {
+			P:=NewECP()
+			P.copy(WP)
+
+			P=P.mul2(h2,G,f)
+
+			if P.is_infinity() {
+				res=ECDH_INVALID;
+			} else {
+				d=P.getX()
+				d.mod(r)
+
+				if comp(d,c)!=0 {res=ECDH_INVALID}
+			}
+		}
+	}
+
+	return res
+}
+
+/* IEEE1363 ECIES encryption. Encryption of plaintext M uses public key W and produces ciphertext V,C,T */
+func ECIES_ENCRYPT(sha int,P1 []byte,P2 []byte,RNG *RAND,W []byte,M []byte,V []byte,T []byte) []byte { 
+	var Z [ECDH_EFS]byte
+	var VZ [3*ECDH_EFS+1]byte
+	var K1 [ECDH_EAS]byte
+	var K2 [ECDH_EAS]byte
+	var U [ECDH_EGS]byte
+
+	if ECDH_KEY_PAIR_GENERATE(RNG,U[:],V)!=0 {return nil}
+	if ECPSVDP_DH(U[:],W,Z[:])!=0 {return nil}     
+
+	for i:=0;i<2*ECDH_EFS+1;i++ {VZ[i]=V[i]}
+	for i:=0;i<ECDH_EFS;i++ {VZ[2*ECDH_EFS+1+i]=Z[i]}
+
+
+	K:=KDF2(sha,VZ[:],P1,ECDH_EFS)
+
+	for i:=0;i<ECDH_EAS;i++ {K1[i]=K[i]; K2[i]=K[ECDH_EAS+i]} 
+
+	C:=AES_CBC_IV0_ENCRYPT(K1[:],M)
+
+	L2:=inttoBytes(len(P2),8)	
+	
+	var AC []byte
+
+	for i:=0;i<len(C);i++ {AC=append(AC,C[i])}   
+	for i:=0;i<len(P2);i++ {AC=append(AC,P2[i])}
+	for i:=0;i<8;i++ {AC=append(AC,L2[i])}
+	
+	HMAC(sha,AC,K2[:],T)
+
+	return C
+}
+
+/* IEEE1363 ECIES decryption. Decryption of ciphertext V,C,T using private key U outputs plaintext M */
+func ECIES_DECRYPT(sha int,P1 []byte,P2 []byte,V []byte,C []byte,T []byte,U []byte) []byte { 
+	var Z [ECDH_EFS]byte
+	var VZ [3*ECDH_EFS+1]byte
+	var K1 [ECDH_EAS]byte
+	var K2 [ECDH_EAS]byte
+
+	var TAG []byte =T[:]  
+
+	if ECPSVDP_DH(U,V,Z[:])!=0 {return nil}
+
+	for i:=0;i<2*ECDH_EFS+1;i++ {VZ[i]=V[i]}
+	for i:=0;i<ECDH_EFS;i++ {VZ[2*ECDH_EFS+1+i]=Z[i]}
+
+	K:=KDF2(sha,VZ[:],P1,ECDH_EFS)
+
+	for i:=0;i<ECDH_EAS;i++ {K1[i]=K[i]; K2[i]=K[ECDH_EAS+i]} 
+
+	M:=AES_CBC_IV0_DECRYPT(K1[:],C)
+
+	if M==nil {return nil}
+
+	L2:=inttoBytes(len(P2),8)	
+	
+	var AC []byte
+	
+	for i:=0;i<len(C);i++ {AC=append(AC,C[i])}   
+	for i:=0;i<len(P2);i++ {AC=append(AC,P2[i])}
+	for i:=0;i<8;i++ {AC=append(AC,L2[i])}
+	
+	HMAC(sha,AC,K2[:],TAG)
+
+	same:=true
+	for i:=0;i<len(T);i++ {
+		if T[i]!=TAG[i] {same=false}
+	}
+	if !same {return nil}
+	
+	return M
+}
+
+
diff --git a/version22/go/ECP.go b/version22/go/ECP.go
new file mode 100644
index 0000000..e33b52b
--- /dev/null
+++ b/version22/go/ECP.go
@@ -0,0 +1,893 @@
+/*
+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.
+*/
+
+package main
+
+//import "fmt"
+
+/* Elliptic Curve Point Structure */
+
+type ECP struct {
+	x *FP
+	y *FP
+	z *FP
+	INF bool
+}
+
+/* Constructors */
+func NewECP() *ECP {
+	E:=new(ECP)
+	E.x=NewFPint(0)
+	E.y=NewFPint(0)
+	E.z=NewFPint(0)
+	E.INF=true
+	return E
+}
+
+/* set (x,y) from two BIGs */
+func NewECPbigs(ix *BIG,iy *BIG) *ECP {
+	E:=new(ECP)
+	E.x=NewFPbig(ix)
+	E.y=NewFPbig(iy)
+	E.z=NewFPint(1)
+	rhs:=RHS(E.x)
+
+	if CURVETYPE==MONTGOMERY {
+		if rhs.jacobi()==1 {
+			E.INF=false
+		} else {E.inf()}
+	} else {
+		y2:=NewFPcopy(E.y)
+		y2.sqr()
+		if y2.equals(rhs) {
+			E.INF=false
+		} else {E.inf()}
+	}
+	return E
+}
+
+/* set (x,y) from BIG and a bit */
+func NewECPbigint(ix *BIG,s int) *ECP {
+	E:=new(ECP)
+	E.x=NewFPbig(ix)
+	E.y=NewFPint(0)
+	rhs:=RHS(E.x)
+	E.z=NewFPint(1)
+	if rhs.jacobi()==1 {
+		ny:=rhs.sqrt()
+		if ny.redc().parity()!=s {ny.neg()}
+		E.y.copy(ny)
+		E.INF=false
+	} else {E.inf()}
+	return E;
+}
+
+/* set from x - calculate y from curve equation */
+func NewECPbig(ix *BIG) *ECP {
+	E:=new(ECP)	
+	E.x=NewFPbig(ix)
+	E.y=NewFPint(0)
+	rhs:=RHS(E.x)
+	E.z=NewFPint(1)
+	if rhs.jacobi()==1 {
+		if CURVETYPE!=MONTGOMERY {E.y.copy(rhs.sqrt())}
+		E.INF=false
+	} else {E.INF=true}
+	return E
+}
+
+/* test for O point-at-infinity */
+func (E *ECP) is_infinity() bool {
+	if CURVETYPE==EDWARDS {
+		E.x.reduce(); E.y.reduce(); E.z.reduce()
+		return (E.x.iszilch() && E.y.equals(E.z))
+	} else {return E.INF}
+}
+
+/* Conditional swap of P and Q dependant on d */
+func (E *ECP) cswap(Q *ECP,d int) {
+	E.x.cswap(Q.x,d)
+	if CURVETYPE!=MONTGOMERY {E.y.cswap(Q.y,d)}
+	E.z.cswap(Q.z,d)
+	if CURVETYPE!=EDWARDS {
+		bd:=true
+		if d==0 {bd=false}
+		bd=bd&&(E.INF!=Q.INF)
+		E.INF=(bd!=E.INF)
+		Q.INF=(bd!=Q.INF)
+	}
+}
+
+/* Conditional move of Q to P dependant on d */
+func (E *ECP) cmove(Q *ECP,d int) {
+	E.x.cmove(Q.x,d)
+	if CURVETYPE!=MONTGOMERY {E.y.cmove(Q.y,d)}
+	E.z.cmove(Q.z,d);
+	if CURVETYPE!=EDWARDS {
+		bd:=true
+		if d==0 {bd=false}
+		E.INF=(E.INF!=((E.INF!=Q.INF)&&bd))
+	}
+}
+
+/* return 1 if b==c, no branching */
+func teq(b int32,c int32) int {
+	x:=b^c
+	x-=1  // if x=0, x now -1
+	return int((x>>31)&1)
+}
+
+/* this=P */
+func (E *ECP) copy(P *ECP) {
+	E.x.copy(P.x);
+	if CURVETYPE!=MONTGOMERY {E.y.copy(P.y)}
+	E.z.copy(P.z);
+	E.INF=P.INF;
+}
+
+/* this=-this */
+func (E *ECP) neg() {
+	if E.is_infinity() {return}
+	if CURVETYPE==WEIERSTRASS {
+		E.y.neg(); E.y.norm()
+	}
+	if CURVETYPE==EDWARDS {
+		E.x.neg(); E.x.norm()
+	}
+	return;
+}
+
+/* Constant time select from pre-computed table */
+func (E *ECP) selector(W []*ECP,b int32) {
+	MP:=NewECP()
+	m:=b>>31;
+	babs:=(b^m)-m;
+
+	babs=(babs-1)/2
+
+	E.cmove(W[0],teq(babs,0))  // conditional move
+	E.cmove(W[1],teq(babs,1))
+	E.cmove(W[2],teq(babs,2))
+	E.cmove(W[3],teq(babs,3))
+	E.cmove(W[4],teq(babs,4))
+	E.cmove(W[5],teq(babs,5))
+	E.cmove(W[6],teq(babs,6))
+	E.cmove(W[7],teq(babs,7))
+ 
+	MP.copy(E);
+	MP.neg()
+	E.cmove(MP,int(m&1));
+}
+
+/* set this=O */
+func (E *ECP) inf() {
+	E.INF=true;
+	E.x.zero()
+	E.y.one()
+	E.z.one()
+}
+
+/* Test P == Q */
+func( E *ECP) equals(Q *ECP) bool {
+	if E.is_infinity() && Q.is_infinity() {return true}
+	if E.is_infinity() || Q.is_infinity() {return false}
+	if CURVETYPE==WEIERSTRASS {
+		zs2:=NewFPcopy(E.z); zs2.sqr()
+		zo2:=NewFPcopy(Q.z); zo2.sqr()
+		zs3:=NewFPcopy(zs2); zs3.mul(E.z)
+		zo3:=NewFPcopy(zo2); zo3.mul(Q.z)
+		zs2.mul(Q.x)
+		zo2.mul(E.x)
+		if !zs2.equals(zo2) {return false}
+		zs3.mul(Q.y)
+		zo3.mul(E.y)
+		if !zs3.equals(zo3) {return false}
+	} else {
+		a:=NewFPint(0)
+		b:=NewFPint(0)
+		a.copy(E.x); a.mul(Q.z); a.reduce()
+		b.copy(Q.x); b.mul(E.z); b.reduce()
+		if !a.equals(b) {return false}
+		if CURVETYPE==EDWARDS {
+			a.copy(E.y); a.mul(Q.z); a.reduce()
+			b.copy(Q.y); b.mul(E.z); b.reduce()
+			if !a.equals(b) {return false}
+		}
+	}
+	return true
+}
+
+/* Calculate RHS of curve equation */
+func RHS(x *FP) *FP {
+	x.norm()
+	r:=NewFPcopy(x)
+	r.sqr();
+
+	if CURVETYPE==WEIERSTRASS { // x^3+Ax+B
+		b:=NewFPbig(NewBIGints(CURVE_B))
+		r.mul(x);
+		if CURVE_A==-3 {
+			cx:=NewFPcopy(x)
+			cx.imul(3)
+			cx.neg(); cx.norm()
+			r.add(cx)
+		}
+		r.add(b)
+	}
+	if CURVETYPE==EDWARDS { // (Ax^2-1)/(Bx^2-1) 
+		b:=NewFPbig(NewBIGints(CURVE_B))
+
+		one:=NewFPint(1)
+		b.mul(r)
+		b.sub(one)
+		if CURVE_A==-1 {r.neg()}
+		r.sub(one)
+		b.inverse()
+		r.mul(b)
+	}
+	if CURVETYPE==MONTGOMERY { // x^3+Ax^2+x
+		x3:=NewFPint(0)
+		x3.copy(r)
+		x3.mul(x)
+		r.imul(CURVE_A)
+		r.add(x3)
+		r.add(x)
+	}
+	r.reduce()
+	return r
+}
+
+/* set to affine - from (x,y,z) to (x,y) */
+func (E *ECP) affine() {
+	if E.is_infinity() {return}
+	one:=NewFPint(1)
+	if E.z.equals(one) {return}
+	E.z.inverse()
+	if CURVETYPE==WEIERSTRASS {
+		z2:=NewFPcopy(E.z)
+		z2.sqr()
+		E.x.mul(z2); E.x.reduce()
+		E.y.mul(z2)
+		E.y.mul(E.z);  E.y.reduce()
+	}
+	if CURVETYPE==EDWARDS {
+		E.x.mul(E.z); E.x.reduce()
+		E.y.mul(E.z); E.y.reduce()
+	}
+	if CURVETYPE==MONTGOMERY {
+		E.x.mul(E.z); E.x.reduce()
+	}
+	E.z.one()
+}
+
+/* extract x as a BIG */
+func (E *ECP) getX() *BIG {
+	E.affine()
+	return E.x.redc()
+}
+/* extract y as a BIG */
+func (E *ECP) getY() *BIG {
+	E.affine()
+	return E.y.redc()
+}
+
+/* get sign of Y */
+func (E *ECP) getS() int {
+	E.affine()
+	y:=E.getY()
+	return y.parity()
+}
+/* extract x as an FP */
+func (E *ECP) getx() *FP {
+	return E.x;
+}
+/* extract y as an FP */
+func (E *ECP) gety() *FP {
+	return E.y
+}
+/* extract z as an FP */
+func (E *ECP) getz() *FP {
+	return E.z
+}
+
+/* convert to byte array */
+func (E *ECP) toBytes(b []byte) {
+	var t [int(MODBYTES)]byte
+	MB:=int(MODBYTES)
+	if CURVETYPE!=MONTGOMERY {
+		b[0]=0x04
+	} else {b[0]=0x02}
+	
+	E.affine()
+	E.x.redc().toBytes(t[:])
+	for i:=0;i<MB;i++ {b[i+1]=t[i]}
+	if CURVETYPE!=MONTGOMERY {
+		E.y.redc().toBytes(t[:])
+		for i:=0;i<MB;i++ {b[i+MB+1]=t[i]}
+	}
+}
+
+/* convert from byte array to point */
+func ECP_fromBytes(b []byte) *ECP {
+	var t [int(MODBYTES)]byte
+	MB:=int(MODBYTES)
+	p:=NewBIGints(Modulus)
+
+	for i:=0;i<MB;i++ {t[i]=b[i+1]}
+	px:=fromBytes(t[:])
+	if comp(px,p)>=0 {return NewECP()}
+
+	if (b[0]==0x04) {
+		for i:=0;i<MB;i++ {t[i]=b[i+MB+1]}
+		py:=fromBytes(t[:])
+		if comp(py,p)>=0 {return NewECP()}
+		return NewECPbigs(px,py)
+	} else {return NewECPbig(px)}
+}
+
+/* convert to hex string */
+func (E *ECP) toString() string {
+	if E.is_infinity() {return "infinity"}
+	E.affine();
+	if CURVETYPE==MONTGOMERY {
+		return "("+E.x.redc().toString()+")"
+	} else {return "("+E.x.redc().toString()+","+E.y.redc().toString()+")"}
+}
+
+/* this*=2 */
+func (E *ECP) dbl() {
+	if CURVETYPE==WEIERSTRASS {
+		if E.INF {return}
+		if E.y.iszilch() {
+			E.inf()
+			return
+		}
+
+		w1:=NewFPcopy(E.x);
+		w6:=NewFPcopy(E.z);
+		w2:=NewFPint(0);
+		w3:=NewFPcopy(E.x)
+		w8:=NewFPcopy(E.x)
+
+		if CURVE_A==-3 {
+			w6.sqr()
+			w1.copy(w6)
+			w1.neg()
+			w3.add(w1)
+
+			w8.add(w6)
+
+			w3.mul(w8)
+			w8.copy(w3)
+			w8.imul(3)
+		} else {
+			w1.sqr()
+			w8.copy(w1)
+			w8.imul(3)
+		}
+
+		w2.copy(E.y); w2.sqr()
+		w3.copy(E.x); w3.mul(w2)
+		w3.imul(4)
+		w1.copy(w3); w1.neg()
+	//		w1.norm();
+
+
+		E.x.copy(w8); E.x.sqr()
+		E.x.add(w1)
+		E.x.add(w1)
+	//		x.reduce();
+		E.x.norm()
+
+		E.z.mul(E.y)
+		E.z.add(E.z)
+
+		w2.add(w2)
+		w2.sqr()
+		w2.add(w2)
+		w3.sub(E.x)
+		E.y.copy(w8); E.y.mul(w3);
+	//		w2.norm();
+		E.y.sub(w2)
+	//		y.reduce();
+	//		z.reduce();
+		E.y.norm()
+		E.z.norm()
+
+	}
+	if CURVETYPE==EDWARDS {
+		C:=NewFPcopy(E.x)
+		D:=NewFPcopy(E.y)
+		H:=NewFPcopy(E.z)
+		J:=NewFPint(0)
+	
+		E.x.mul(E.y); E.x.add(E.x)
+		C.sqr()
+		D.sqr()
+		if CURVE_A==-1 {C.neg()}	
+		E.y.copy(C); E.y.add(D)
+	//		y.norm();
+		H.sqr(); H.add(H)
+		E.z.copy(E.y)
+		J.copy(E.y); J.sub(H)
+		E.x.mul(J)
+		C.sub(D)
+		E.y.mul(C)
+		E.z.mul(J)
+
+		E.x.norm()
+		E.y.norm()
+		E.z.norm()
+	}
+	if CURVETYPE==MONTGOMERY {
+		A:=NewFPcopy(E.x)
+		B:=NewFPcopy(E.x)	
+		AA:=NewFPint(0)
+		BB:=NewFPint(0)
+		C:=NewFPint(0)
+	
+		if E.INF {return}
+
+		A.add(E.z)
+		AA.copy(A); AA.sqr()
+		B.sub(E.z)
+		BB.copy(B); BB.sqr()
+		C.copy(AA); C.sub(BB)
+	//		C.norm();
+
+		E.x.copy(AA); E.x.mul(BB)
+
+		A.copy(C); A.imul((CURVE_A+2)/4)
+
+		BB.add(A)
+		E.z.copy(BB); E.z.mul(C)
+	//		x.reduce();
+	//		z.reduce();
+		E.x.norm()
+		E.z.norm()
+	}
+	return;
+}
+
+/* this+=Q */
+func (E *ECP) add(Q *ECP) {
+	if CURVETYPE==WEIERSTRASS {
+		if E.INF {
+			E.copy(Q)
+			return
+		}
+		if Q.INF {return}
+
+		aff:=false
+
+		one:=NewFPint(1)
+		if Q.z.equals(one) {aff=true}
+
+		var A,C *FP
+		B:=NewFPcopy(E.z)
+		D:=NewFPcopy(E.z)
+		if !aff {
+			A=NewFPcopy(Q.z)
+			C=NewFPcopy(Q.z)
+
+			A.sqr(); B.sqr()
+			C.mul(A); D.mul(B)
+
+			A.mul(E.x)
+			C.mul(E.y)
+		} else {
+			A=NewFPcopy(E.x)
+			C=NewFPcopy(E.y)
+	
+			B.sqr()
+			D.mul(B)
+		}
+
+		B.mul(Q.x); B.sub(A)
+		D.mul(Q.y); D.sub(C)
+
+		if B.iszilch() {
+			if D.iszilch() {
+				E.dbl()
+				return
+			} else {
+				E.INF=true
+				return
+			}
+		}
+
+		if !aff {E.z.mul(Q.z)}
+		E.z.mul(B)
+
+		e:=NewFPcopy(B); e.sqr()
+		B.mul(e)
+		A.mul(e)
+
+		e.copy(A)
+		e.add(A); e.add(B)
+		E.x.copy(D); E.x.sqr(); E.x.sub(e);
+
+		A.sub(E.x);
+		E.y.copy(A); E.y.mul(D)
+		C.mul(B); E.y.sub(C)
+
+		//	x.reduce();
+		//	y.reduce();
+		//	z.reduce();
+		E.x.norm()
+		E.y.norm()
+		E.z.norm()
+	}
+	if CURVETYPE==EDWARDS {
+		b:=NewFPbig(NewBIGints(CURVE_B))
+		A:=NewFPcopy(E.z)
+		B:=NewFPint(0)
+		C:=NewFPcopy(E.x)
+		D:=NewFPcopy(E.y)
+		EE:=NewFPint(0)
+		F:=NewFPint(0)
+		G:=NewFPint(0)
+		//H:=NewFPint(0)
+		//I:=NewFPint(0)
+	
+		A.mul(Q.z);
+		B.copy(A); B.sqr()
+		C.mul(Q.x)
+		D.mul(Q.y)
+
+		EE.copy(C); EE.mul(D); EE.mul(b)
+		F.copy(B); F.sub(EE)
+		G.copy(B); G.add(EE)
+
+		if CURVE_A==1 {
+			EE.copy(D); EE.sub(C)
+		}
+		C.add(D)
+
+		B.copy(E.x); B.add(E.y)
+		D.copy(Q.x); D.add(Q.y)
+		B.mul(D)
+		B.sub(C)
+		B.mul(F)
+		E.x.copy(A); E.x.mul(B)
+
+		if CURVE_A==1 {
+			C.copy(EE); C.mul(G)
+		}
+		if CURVE_A==-1 {
+			C.mul(G)
+		}
+		E.y.copy(A); E.y.mul(C)
+		E.z.copy(F); E.z.mul(G)
+		//	x.reduce(); y.reduce(); z.reduce();
+		E.x.norm(); E.y.norm(); E.z.norm()
+	}
+	return
+}
+
+/* Differential Add for Montgomery curves. this+=Q where W is this-Q and is affine. */
+func (E *ECP) dadd(Q *ECP,W *ECP) {
+	A:=NewFPcopy(E.x)
+	B:=NewFPcopy(E.x)
+	C:=NewFPcopy(Q.x)
+	D:=NewFPcopy(Q.x)
+	DA:=NewFPint(0)
+	CB:=NewFPint(0)
+			
+	A.add(E.z)
+	B.sub(E.z)
+
+	C.add(Q.z)
+	D.sub(Q.z)
+
+	DA.copy(D); DA.mul(A)
+	CB.copy(C); CB.mul(B)
+
+	A.copy(DA); A.add(CB); A.sqr()
+	B.copy(DA); B.sub(CB); B.sqr()
+
+	E.x.copy(A)
+	E.z.copy(W.x); E.z.mul(B)
+
+	if E.z.iszilch() {
+		E.inf()
+	} else {E.INF=false;}
+
+	//	x.reduce();
+	E.x.norm();
+}
+
+/* this-=Q */
+func (E *ECP) sub(Q *ECP) {
+	Q.neg()
+	E.add(Q)
+	Q.neg()
+}
+
+func multiaffine(m int,P []*ECP) {
+	t1:=NewFPint(0)
+	t2:=NewFPint(0)
+
+	var work []*FP
+
+	for i:=0;i<m;i++ {
+		work=append(work,NewFPint(0))
+	}
+	
+	work[0].one()
+	work[1].copy(P[0].z)
+
+	for i:=2;i<m;i++ {
+		work[i].copy(work[i-1])
+		work[i].mul(P[i-1].z)
+	}
+
+	t1.copy(work[m-1])
+	t1.mul(P[m-1].z)
+	t1.inverse()
+	t2.copy(P[m-1].z)
+	work[m-1].mul(t1)
+
+	for i:=m-2;;i-- {
+		if i==0 {
+			work[0].copy(t1)
+			work[0].mul(t2)
+			break
+		}
+		work[i].mul(t2)
+		work[i].mul(t1)
+		t2.mul(P[i].z)
+	}
+/* now work[] contains inverses of all Z coordinates */
+
+	for i:=0;i<m;i++ {
+		P[i].z.one()
+		t1.copy(work[i])
+		t1.sqr()
+		P[i].x.mul(t1)
+		t1.mul(work[i])
+		P[i].y.mul(t1)
+	}    
+}
+
+/* constant time multiply by small integer of length bts - use ladder */
+func (E *ECP) pinmul(e int32,bts int32) *ECP {	
+	if CURVETYPE==MONTGOMERY {
+		return E.mul(NewBIGint(int(e)))
+	} else {
+		P:=NewECP()
+		R0:=NewECP()
+		R1:=NewECP(); R1.copy(E)
+
+		for i:=bts-1;i>=0;i-- {
+			b:=int((e>>uint32(i))&1)
+			P.copy(R1)
+			P.add(R0)
+			R0.cswap(R1,b)
+			R1.copy(P)
+			R0.dbl()
+			R0.cswap(R1,b)
+		}
+		P.copy(R0)
+		P.affine()
+		return P
+	}
+}
+
+/* return e.this */
+
+func (E *ECP) mul(e *BIG) *ECP {
+	if (e.iszilch() || E.is_infinity()) {return NewECP()}
+	P:=NewECP()
+	if CURVETYPE==MONTGOMERY {
+/* use Ladder */
+		D:=NewECP();
+		R0:=NewECP(); R0.copy(E)
+		R1:=NewECP(); R1.copy(E)
+		R1.dbl()
+		D.copy(E); D.affine()
+		nb:=e.nbits()
+		for i:=nb-2;i>=0;i-- {
+			b:=int(e.bit(i))
+			P.copy(R1)
+			P.dadd(R0,D)
+			R0.cswap(R1,b)
+			R1.copy(P)
+			R0.dbl()
+			R0.cswap(R1,b)
+		}
+		P.copy(R0)
+	} else {
+// fixed size windows 
+		mt:=NewBIG()
+		t:=NewBIG()
+		Q:=NewECP()
+		C:=NewECP()
+
+		var W []*ECP
+		var w [1+(NLEN*int(BASEBITS)+3)/4]int8
+
+		E.affine();
+
+		Q.copy(E);
+		Q.dbl();
+
+		W=append(W,NewECP());
+		W[0].copy(E);
+
+		for i:=1;i<8;i++ {
+			W=append(W,NewECP())
+			W[i].copy(W[i-1])
+			W[i].add(Q)
+		}
+
+
+// convert the table to affine 
+		if CURVETYPE==WEIERSTRASS {
+			multiaffine(8,W[:])
+		}
+
+
+// make exponent odd - add 2P if even, P if odd 
+		t.copy(e)
+		s:=int(t.parity())
+		t.inc(1); t.norm(); ns:=int(t.parity()); mt.copy(t); mt.inc(1); mt.norm()
+		t.cmove(mt,s)
+		Q.cmove(E,ns)
+		C.copy(Q)
+
+		nb:=1+(t.nbits()+3)/4
+
+// convert exponent to signed 4-bit window 
+		for i:=0;i<nb;i++ {
+			w[i]=int8(t.lastbits(5)-16)
+			t.dec(int(w[i])); t.norm()
+			t.fshr(4)	
+		}
+		w[nb]=int8(t.lastbits(5))
+
+		P.copy(W[(int(w[nb])-1)/2])  
+		for i:=nb-1;i>=0;i-- {
+			Q.selector(W,int32(w[i]))
+			P.dbl()
+			P.dbl()
+			P.dbl()
+			P.dbl()
+			P.add(Q)
+		}
+		P.sub(C) /* apply correction */
+	}
+	P.affine()
+	return P
+}
+
+/* Return e.this+f.Q */
+
+func (E *ECP) mul2(e *BIG,Q *ECP,f *BIG) *ECP {
+	te:=NewBIG()
+	tf:=NewBIG()
+	mt:=NewBIG()
+	S:=NewECP()
+	T:=NewECP()
+	C:=NewECP()
+	var W [] *ECP
+	//ECP[] W=new ECP[8];
+	var w [1+(NLEN*int(BASEBITS)+1)/2]int8		
+
+	E.affine()
+	Q.affine()
+
+	te.copy(e)
+	tf.copy(f)
+
+// precompute table 
+	for i:=0;i<8;i++ {
+		W=append(W,NewECP())
+	}
+	W[1].copy(E); W[1].sub(Q)
+	W[2].copy(E); W[2].add(Q);
+	S.copy(Q); S.dbl();
+	W[0].copy(W[1]); W[0].sub(S);
+	W[3].copy(W[2]); W[3].add(S);
+	T.copy(E); T.dbl();
+	W[5].copy(W[1]); W[5].add(T);
+	W[6].copy(W[2]); W[6].add(T);
+	W[4].copy(W[5]); W[4].sub(S);
+	W[7].copy(W[6]); W[7].add(S);
+
+// convert the table to affine 
+	if CURVETYPE==WEIERSTRASS { 
+		multiaffine(8,W)
+	}
+
+// if multiplier is odd, add 2, else add 1 to multiplier, and add 2P or P to correction 
+
+	s:=int(te.parity());
+	te.inc(1); te.norm(); ns:=int(te.parity()); mt.copy(te); mt.inc(1); mt.norm()
+	te.cmove(mt,s)
+	T.cmove(E,ns)
+	C.copy(T)
+
+	s=int(tf.parity())
+	tf.inc(1); tf.norm(); ns=int(tf.parity()); mt.copy(tf); mt.inc(1); mt.norm()
+	tf.cmove(mt,s)
+	S.cmove(Q,ns)
+	C.add(S)
+
+	mt.copy(te); mt.add(tf); mt.norm()
+	nb:=1+(mt.nbits()+1)/2
+
+// convert exponent to signed 2-bit window 
+	for i:=0;i<nb;i++ {
+		a:=(te.lastbits(3)-4)
+		te.dec(int(a)); te.norm()
+		te.fshr(2)
+		b:=(tf.lastbits(3)-4)
+		tf.dec(int(b)); tf.norm()
+		tf.fshr(2)
+		w[i]=int8(4*a+b)
+	}
+	w[nb]=int8(4*te.lastbits(3)+tf.lastbits(3))
+	S.copy(W[(w[nb]-1)/2])  
+
+	for i:=nb-1;i>=0;i-- {
+		T.selector(W,int32(w[i]));
+		S.dbl()
+		S.dbl()
+		S.add(T)
+	}
+	S.sub(C) /* apply correction */
+	S.affine()
+	return S
+}
+
+/*
+func main() {
+	Gx:=NewBIGints(CURVE_Gx);
+	var Gy *BIG
+	var P *ECP
+
+	if CURVETYPE!=MONTGOMERY {Gy=NewBIGints(CURVE_Gy)}
+	r:=NewBIGints(CURVE_Order)
+
+	//r.dec(7);
+	
+	fmt.Printf("Gx= "+Gx.toString())
+	fmt.Printf("\n")
+
+	if CURVETYPE!=MONTGOMERY {
+		fmt.Printf("Gy= "+Gy.toString())
+		fmt.Printf("\n")
+	}	
+
+	if CURVETYPE!=MONTGOMERY {
+		P=NewECPbigs(Gx,Gy)
+	} else  {P=NewECPbig(Gx)}
+
+	fmt.Printf("P= "+P.toString());		
+	fmt.Printf("\n")
+
+	R:=P.mul(r);
+		//for (int i=0;i<10000;i++)
+		//	R=P.mul(r);
+	
+	fmt.Printf("R= "+R.toString())
+	fmt.Printf("\n")
+}
+*/
\ No newline at end of file
diff --git a/version22/go/ECP2.go b/version22/go/ECP2.go
new file mode 100644
index 0000000..30fe1e4
--- /dev/null
+++ b/version22/go/ECP2.go
@@ -0,0 +1,568 @@
+/*
+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.
+*/
+
+/* MiotCL Weierstrass elliptic curve functions over FP2 */
+
+package main
+
+//import "fmt"
+
+type ECP2 struct {
+	x *FP2
+	y *FP2
+	z *FP2
+	INF bool
+}
+
+func NewECP2() *ECP2 {
+	E:=new(ECP2)
+	E.x=NewFP2int(0)
+	E.y=NewFP2int(1)
+	E.z=NewFP2int(1)
+	E.INF=true
+	return E
+}
+
+/* Test this=O? */
+func (E *ECP2) is_infinity() bool {
+		return E.INF
+}
+/* copy this=P */
+func (E *ECP2) copy(P *ECP2) {
+	E.x.copy(P.x)
+	E.y.copy(P.y)
+	E.z.copy(P.z)
+	E.INF=P.INF
+}
+/* set this=O */
+func (E *ECP2) inf() {
+	E.INF=true
+	E.x.zero()
+	E.y.zero()
+	E.z.zero()
+}
+
+/* set this=-this */
+func (E *ECP2) neg() {
+	if E.is_infinity() {return}
+	E.y.neg(); E.y.reduce()
+}
+
+/* Conditional move of Q to P dependant on d */
+func (E *ECP2) cmove(Q *ECP2,d int) {
+	E.x.cmove(Q.x,d)
+	E.y.cmove(Q.y,d)
+	E.z.cmove(Q.z,d)
+
+	var bd bool
+	if (d==0) {
+		bd=false
+	} else {bd=true}
+	E.INF=(E.INF!=(E.INF!=Q.INF)&&bd)
+}
+
+/* Constant time select from pre-computed table */
+func (E *ECP2) selector(W []*ECP2,b int32) {
+	MP:=NewECP2() 
+	m:=b>>31
+	babs:=(b^m)-m
+
+	babs=(babs-1)/2
+
+	E.cmove(W[0],teq(babs,0))  // conditional move
+	E.cmove(W[1],teq(babs,1))
+	E.cmove(W[2],teq(babs,2))
+	E.cmove(W[3],teq(babs,3))
+	E.cmove(W[4],teq(babs,4))
+	E.cmove(W[5],teq(babs,5))
+	E.cmove(W[6],teq(babs,6))
+	E.cmove(W[7],teq(babs,7))
+ 
+	MP.copy(E)
+	MP.neg()
+	E.cmove(MP,int(m&1))
+}
+
+/* Test if P == Q */
+func (E *ECP2) equals(Q *ECP2) bool {
+	if E.is_infinity() && Q.is_infinity() {return true}
+	if E.is_infinity() || Q.is_infinity() {return false}
+
+	zs2:=NewFP2copy(E.z); zs2.sqr()
+	zo2:=NewFP2copy(Q.z); zo2.sqr()
+	zs3:=NewFP2copy(zs2); zs3.mul(E.z)
+	zo3:=NewFP2copy(zo2); zo3.mul(Q.z)
+	zs2.mul(Q.x)
+	zo2.mul(E.x)
+	if !zs2.equals(zo2) {return false}
+	zs3.mul(Q.y)
+	zo3.mul(E.y)
+	if !zs3.equals(zo3) {return false}
+
+	return true
+}
+
+/* set to Affine - (x,y,z) to (x,y) */
+func (E *ECP2) affine() {
+	if E.is_infinity() {return}
+	one:=NewFP2int(1)
+	if E.z.equals(one) {return}
+	E.z.inverse()
+
+	z2:=NewFP2copy(E.z);
+	z2.sqr()
+	E.x.mul(z2); E.x.reduce()
+	E.y.mul(z2) 
+	E.y.mul(E.z);  E.y.reduce()
+	E.z.copy(one)
+}
+
+/* extract affine x as FP2 */
+func (E *ECP2) getX() *FP2 {
+	E.affine()
+	return E.x
+}
+/* extract affine y as FP2 */
+func (E *ECP2) getY() *FP2 {
+	E.affine();
+	return E.y;
+}
+/* extract projective x */
+func (E *ECP2) getx() *FP2 {
+	return E.x
+}
+/* extract projective y */
+func (E *ECP2) gety() *FP2 {
+	return E.y
+}
+/* extract projective z */
+func (E *ECP2) getz() *FP2 {
+	return E.z
+}
+
+/* convert to byte array */
+func (E *ECP2) toBytes(b []byte) {
+	var t [int(MODBYTES)]byte
+	MB:=int(MODBYTES)
+
+	E.affine()
+	E.x.getA().toBytes(t[:])
+	for i:=0;i<MB;i++ { b[i]=t[i]}
+	E.x.getB().toBytes(t[:])
+	for i:=0;i<MB;i++ { b[i+MB]=t[i]}
+
+	E.y.getA().toBytes(t[:])
+	for i:=0;i<MB;i++ {b[i+2*MB]=t[i]}
+	E.y.getB().toBytes(t[:])
+	for i:=0;i<MB;i++ {b[i+3*MB]=t[i]}
+}
+
+/* convert from byte array to point */
+func ECP2_fromBytes(b []byte) *ECP2 {
+	var t [int(MODBYTES)]byte
+	MB:=int(MODBYTES)
+
+	for i:=0;i<MB;i++ {t[i]=b[i]}
+	ra:=fromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=b[i+MB]}
+	rb:=fromBytes(t[:])
+	rx:=NewFP2bigs(ra,rb)
+
+	for i:=0;i<MB;i++ {t[i]=b[i+2*MB]}
+	ra=fromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=b[i+3*MB]}
+	rb=fromBytes(t[:])
+	ry:=NewFP2bigs(ra,rb)
+
+	return NewECP2fp2s(rx,ry)
+}
+
+/* convert this to hex string */
+func (E *ECP2) toString() string {
+	if E.is_infinity() {return "infinity"}
+	E.affine()
+	return "("+E.x.toString()+","+E.y.toString()+")"
+}
+
+/* Calculate RHS of twisted curve equation x^3+B/i */
+func RHS2(x *FP2) *FP2 {
+	x.norm()
+	r:=NewFP2copy(x)
+	r.sqr()
+	b:=NewFP2big(NewBIGints(CURVE_B))
+	b.div_ip()
+	r.mul(x)
+	r.add(b)
+
+	r.reduce()
+	return r
+}
+
+/* construct this from (x,y) - but set to O if not on curve */
+func NewECP2fp2s(ix *FP2,iy *FP2) *ECP2 {
+	E:=new(ECP2)
+	E.x=NewFP2copy(ix)
+	E.y=NewFP2copy(iy)
+	E.z=NewFP2int(1)
+	rhs:=RHS2(E.x)
+	y2:=NewFP2copy(E.y)
+	y2.sqr()
+	if y2.equals(rhs) {
+		E.INF=false
+	} else {E.x.zero();E.INF=true}
+	return E
+}
+
+/* construct this from x - but set to O if not on curve */
+func NewECP2fp2(ix *FP2) *ECP2 {	
+	E:=new(ECP2)
+	E.x=NewFP2copy(ix)
+	E.y=NewFP2int(1)
+	E.z=NewFP2int(1)
+	rhs:=RHS2(E.x)
+	if rhs.sqrt() {
+			E.y.copy(rhs)
+			E.INF=false;
+	} else {E.x.zero();E.INF=true}
+	return E
+}
+
+/* this+=this */
+func (E *ECP2) dbl() int {
+	if E.INF {return -1}
+	if E.y.iszilch() {
+		E.inf()
+		return -1
+	}
+
+	w1:=NewFP2copy(E.x)
+	w2:=NewFP2int(0)
+	w3:=NewFP2copy(E.x)
+	w8:=NewFP2copy(E.x)
+
+	w1.sqr()
+	w8.copy(w1)
+	w8.imul(3)
+
+	w2.copy(E.y); w2.sqr()
+	w3.copy(E.x); w3.mul(w2)
+	w3.imul(4)
+	w1.copy(w3); w1.neg()
+	w1.norm();
+
+	E.x.copy(w8); E.x.sqr()
+	E.x.add(w1)
+	E.x.add(w1)
+	E.x.norm()
+
+	E.z.mul(E.y)
+	E.z.add(E.z)
+
+	w2.add(w2)
+	w2.sqr()
+	w2.add(w2)
+	w3.sub(E.x);
+	E.y.copy(w8); E.y.mul(w3)
+	//	w2.norm();
+	E.y.sub(w2)
+
+	E.y.norm()
+	E.z.norm()
+
+	return 1
+}
+
+/* this+=Q - return 0 for add, 1 for double, -1 for O */
+func (E *ECP2) add(Q *ECP2) int {
+	if E.INF {
+		E.copy(Q)
+		return -1
+	}
+	if Q.INF {return -1}
+
+	aff:=false
+
+	if Q.z.isunity() {aff=true}
+
+	var A,C *FP2
+	B:=NewFP2copy(E.z)
+	D:=NewFP2copy(E.z)
+	if !aff{
+		A=NewFP2copy(Q.z)
+		C=NewFP2copy(Q.z)
+
+		A.sqr(); B.sqr()
+		C.mul(A); D.mul(B)
+
+		A.mul(E.x)
+		C.mul(E.y)
+	} else {
+		A=NewFP2copy(E.x)
+		C=NewFP2copy(E.y)
+	
+		B.sqr()
+		D.mul(B)
+	}
+
+	B.mul(Q.x); B.sub(A)
+	D.mul(Q.y); D.sub(C)
+
+	if B.iszilch() {
+		if D.iszilch() {
+			E.dbl()
+			return 1
+		} else	{
+			E.INF=true
+			return -1
+		}
+	}
+
+	if !aff {E.z.mul(Q.z)}
+	E.z.mul(B)
+
+	e:=NewFP2copy(B); e.sqr()
+	B.mul(e)
+	A.mul(e)
+
+	e.copy(A)
+	e.add(A); e.add(B)
+	E.x.copy(D); E.x.sqr(); E.x.sub(e)
+
+	A.sub(E.x);
+	E.y.copy(A); E.y.mul(D)
+	C.mul(B); E.y.sub(C)
+
+	E.x.norm()
+	E.y.norm()
+	E.z.norm()
+
+	return 0
+}
+
+/* set this-=Q */
+func (E *ECP2) sub(Q *ECP2) int {
+	Q.neg()
+	D:=E.add(Q)
+	Q.neg()
+	return D
+}
+/* set this*=q, where q is Modulus, using Frobenius */
+func (E *ECP2) frob(X *FP2) {
+	if E.INF {return}
+	X2:=NewFP2copy(X)
+	X2.sqr()
+	E.x.conj()
+	E.y.conj()
+	E.z.conj()
+	E.z.reduce();
+	E.x.mul(X2)
+	E.y.mul(X2)
+	E.y.mul(X)
+}
+
+/* normalises m-array of ECP2 points. Requires work vector of m FP2s */
+
+func multiaffine2(m int,P []*ECP2) {
+	t1:=NewFP2int(0)
+	t2:=NewFP2int(0)
+
+	var work []*FP2
+
+	for i:=0;i<m;i++ {
+		work=append(work,NewFP2int(0))
+	}
+
+	work[0].one()
+	work[1].copy(P[0].z)
+
+	for i:=2;i<m;i++ {
+		work[i].copy(work[i-1])
+		work[i].mul(P[i-1].z)
+	}
+
+	t1.copy(work[m-1]); t1.mul(P[m-1].z)
+
+	t1.inverse()
+
+	t2.copy(P[m-1].z)
+	work[m-1].mul(t1)
+
+	for i:=m-2;;i-- {
+		if i==0 {
+			work[0].copy(t1)
+			work[0].mul(t2)
+			break
+		}
+		work[i].mul(t2);
+		work[i].mul(t1);
+		t2.mul(P[i].z);
+	}
+/* now work[] contains inverses of all Z coordinates */
+
+	for i:=0;i<m;i++ {
+		P[i].z.one();
+		t1.copy(work[i]); t1.sqr()
+		P[i].x.mul(t1)
+		t1.mul(work[i])
+		P[i].y.mul(t1)
+	}    
+}
+
+/* P*=e */
+func (E *ECP2) mul(e *BIG) *ECP2 {
+/* fixed size windows */
+	mt:=NewBIG()
+	t:=NewBIG()
+	P:=NewECP2()
+	Q:=NewECP2()
+	C:=NewECP2()
+
+	if E.is_infinity() {return NewECP2()}
+
+	var W []*ECP2
+	var w [1+(NLEN*int(BASEBITS)+3)/4]int8
+
+	E.affine()
+
+/* precompute table */
+	Q.copy(E)
+	Q.dbl()
+		
+	W=append(W,NewECP2())
+	W[0].copy(E);
+
+	for i:=1;i<8;i++ {
+		W=append(W,NewECP2())
+		W[i].copy(W[i-1])
+		W[i].add(Q)
+	}
+
+/* convert the table to affine */
+
+	multiaffine2(8,W[:])
+
+/* make exponent odd - add 2P if even, P if odd */
+	t.copy(e)
+	s:=int(t.parity())
+	t.inc(1); t.norm(); ns:=int(t.parity()); mt.copy(t); mt.inc(1); mt.norm()
+	t.cmove(mt,s)
+	Q.cmove(E,ns)
+	C.copy(Q)
+
+	nb:=1+(t.nbits()+3)/4
+/* convert exponent to signed 4-bit window */
+	for i:=0;i<nb;i++ {
+		w[i]=int8(t.lastbits(5)-16)
+		t.dec(int(w[i])); t.norm()
+		t.fshr(4)	
+	}
+	w[nb]=int8(t.lastbits(5))
+		
+	P.copy(W[(w[nb]-1)/2])
+	for i:=nb-1;i>=0;i-- {
+		Q.selector(W,int32(w[i]))
+		P.dbl()
+		P.dbl()
+		P.dbl()
+		P.dbl()
+		P.add(Q)
+	}
+	P.sub(C)
+	P.affine()
+	return P
+}
+
+/* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3 */
+func mul4(Q []*ECP2,u []*BIG) *ECP2 {
+	var a [4]int8
+	T:=NewECP2()
+	C:=NewECP2()
+	P:=NewECP2()
+
+	var W [] *ECP2
+
+	mt:=NewBIG()
+	var t []*BIG
+
+	var w [NLEN*int(BASEBITS)+1]int8	
+
+	for i:=0;i<4;i++ {
+		t=append(t,NewBIGcopy(u[i]));
+		Q[i].affine();
+	}
+
+/* precompute table */
+
+	W=append(W,NewECP2()); W[0].copy(Q[0]); W[0].sub(Q[1])
+	W=append(W,NewECP2()); W[1].copy(W[0])
+	W=append(W,NewECP2()); W[2].copy(W[0])
+	W=append(W,NewECP2()); W[3].copy(W[0])
+	W=append(W,NewECP2()); W[4].copy(Q[0]); W[4].add(Q[1])
+	W=append(W,NewECP2()); W[5].copy(W[4])
+	W=append(W,NewECP2()); W[6].copy(W[4])
+	W=append(W,NewECP2()); W[7].copy(W[4])
+
+	T.copy(Q[2]); T.sub(Q[3])
+	W[1].sub(T)
+	W[2].add(T)
+	W[5].sub(T)
+	W[6].add(T)
+	T.copy(Q[2]); T.add(Q[3])
+	W[0].sub(T)
+	W[3].add(T)
+	W[4].sub(T)
+	W[7].add(T)
+
+	multiaffine2(8,W[:])
+
+/* if multiplier is even add 1 to multiplier, and add P to correction */
+	mt.zero(); C.inf()
+	for i:=0;i<4;i++ {
+		if t[i].parity()==0 {
+			t[i].inc(1); t[i].norm()
+			C.add(Q[i])
+		}
+		mt.add(t[i]); mt.norm()
+	}
+
+	nb:=1+mt.nbits();
+
+/* convert exponent to signed 1-bit window */
+	for j:=0;j<nb;j++ {
+		for i:=0;i<4;i++ {
+			a[i]=int8(t[i].lastbits(2)-2)
+			t[i].dec(int(a[i])); t[i].norm()
+			t[i].fshr(1)
+		}
+		w[j]=(8*a[0]+4*a[1]+2*a[2]+a[3])
+	}
+	w[nb]=int8(8*t[0].lastbits(2)+4*t[1].lastbits(2)+2*t[2].lastbits(2)+t[3].lastbits(2))
+
+	P.copy(W[(w[nb]-1)/2])  
+	for i:=nb-1;i>=0;i-- {
+		T.selector(W,int32(w[i]))
+		P.dbl()
+		P.add(T)
+	}
+	P.sub(C) /* apply correction */
+
+	P.affine()
+	return P
+}
+
diff --git a/version22/go/FF.go b/version22/go/FF.go
new file mode 100644
index 0000000..553f7ac
--- /dev/null
+++ b/version22/go/FF.go
@@ -0,0 +1,905 @@
+/*
+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.
+*/
+
+package main
+
+//import "fmt"
+//import "os"
+
+//var debug bool = false
+
+type FF struct {
+	length int
+	v []*BIG
+}
+
+/* Constructors */
+func NewFFint(n int) *FF {
+	F:=new(FF)
+	for i:=0;i<n;i++ {
+		F.v=append(F.v,NewBIG())
+	}
+	F.length=n
+	return F
+}
+/*
+func NewFFints(x [][NLEN]int64,n int) *FF {
+	F:=new(FF)
+	for i:=0;i<n;i++ {
+		F.v=append(F.v,NewBIGints(x[i]))
+	}
+	F.length=n
+	return F
+}
+*/
+/* set to zero */
+func (F *FF) zero() {
+	for i:=0;i<F.length;i++ {
+		F.v[i].zero()
+	}
+}
+
+func (F *FF) getlen() int {
+		return F.length
+	}
+
+/* set to integer */
+func (F *FF) set(m int) {
+	F.zero()
+	F.v[0].set(0,Chunk(m))
+}
+
+/* copy from FF b */
+func (F *FF) copy(b *FF) {
+	for i:=0;i<F.length;i++ {
+		F.v[i].copy(b.v[i])
+	}
+}
+
+/* x=y<<n */
+func (F *FF) dsucopy(b *FF) {
+	for i:=0;i<b.length;i++ {
+		F.v[b.length+i].copy(b.v[i])
+		F.v[i].zero()
+	}
+}
+
+/* x=y */
+func (F *FF) dscopy(b *FF) {
+	for i:=0;i<b.length;i++ {
+		F.v[i].copy(b.v[i])
+		F.v[b.length+i].zero()
+	}
+}
+
+/* x=y>>n */
+func (F *FF) sducopy(b *FF) {
+	for i:=0;i<F.length;i++ {
+		F.v[i].copy(b.v[F.length+i])
+	}
+}
+
+func (F *FF) one() {
+	F.v[0].one();
+	for i:=1;i<F.length;i++ {
+		F.v[i].zero()
+	}
+}
+
+/* test equals 0 */
+func (F *FF) iszilch() bool {
+	for i:=0;i<F.length;i++ {
+		if !F.v[i].iszilch() {return false}
+	}
+	return true
+}
+
+/* shift right by BIGBITS-bit words */
+func (F *FF) shrw(n int) {
+	for i:=0;i<n;i++ {
+		F.v[i].copy(F.v[i+n])
+		F.v[i+n].zero()
+	}
+}
+
+/* shift left by BIGBITS-bit words */
+func (F *FF) shlw(n int) {
+	for i:=0;i<n;i++ {
+		F.v[n+i].copy(F.v[i])
+		F.v[i].zero()
+	}
+}
+
+/* extract last bit */
+func (F *FF) parity() int {
+	return F.v[0].parity()
+}
+
+func (F *FF) lastbits(m int) int {
+	return F.v[0].lastbits(m)
+}
+
+/* compare x and y - must be normalised, and of same length */
+func ff_comp(a *FF,b *FF) int {
+	for i:=a.length-1;i>=0;i-- {
+		j:=comp(a.v[i],b.v[i])
+		if j!=0 {return j}
+	}
+	return 0
+}
+
+/* recursive add */
+func (F *FF) radd(vp int,x *FF,xp int,y *FF,yp int,n int) {
+	for i:=0;i<n;i++ {
+		F.v[vp+i].copy(x.v[xp+i])
+		F.v[vp+i].add(y.v[yp+i])
+	}
+}
+
+/* recursive inc */
+func (F *FF) rinc(vp int,y *FF,yp int,n int) {
+	for i:=0;i<n;i++ {
+		F.v[vp+i].add(y.v[yp+i])
+	}
+}
+
+/* recursive sub */
+func (F *FF) rsub(vp int,x *FF,xp int,y *FF,yp int,n int) {
+	for i:=0;i<n;i++ {
+		F.v[vp+i].copy(x.v[xp+i])
+		F.v[vp+i].sub(y.v[yp+i])
+	}
+}
+
+/* recursive dec */
+func (F *FF) rdec(vp int,y *FF,yp int,n int) {
+	for i:=0;i<n;i++ {
+		F.v[vp+i].sub(y.v[yp+i])
+	}
+}
+
+/* simple add */
+func (F *FF) add(b *FF) {
+	for i:=0;i<F.length;i++ {
+		F.v[i].add(b.v[i])
+	}
+}
+
+/* simple sub */
+func (F *FF) sub(b *FF) {
+	for i:=0;i<F.length;i++ {
+		F.v[i].sub(b.v[i])
+	}
+}
+	
+/* reverse sub */
+func (F *FF) revsub(b *FF) {
+	for i:=0;i<F.length;i++ {
+		F.v[i].rsub(b.v[i])
+	}
+}
+
+/* normalise - but hold any overflow in top part unless n<0 */
+func (F *FF) rnorm(vp int,n int) {
+	trunc:=false
+	var carry Chunk
+	if n<0 { /* -v n signals to do truncation */
+		n=-n
+		trunc=true
+	}
+	for i:=0;i<n-1;i++ {
+		carry=F.v[vp+i].norm()
+		F.v[vp+i].xortop(carry<<P_TBITS)
+		F.v[vp+i+1].w[0]+=carry; // inc(carry)
+	}
+	carry=F.v[vp+n-1].norm()
+	if trunc {
+		F.v[vp+n-1].xortop(carry<<P_TBITS)
+	}
+}
+
+func (F *FF) norm() {
+	F.rnorm(0,F.length)
+}
+
+/* increment/decrement by a small integer */
+func (F *FF) inc(m int) {
+	F.v[0].inc(m)
+	F.norm()
+}
+
+func (F *FF) dec(m int) {
+	F.v[0].dec(m)
+	F.norm()
+}
+
+/* shift left by one bit */
+func (F *FF) shl() {
+	var delay_carry int=0
+	for i:=0;i<F.length-1;i++ {
+		carry:=F.v[i].fshl(1)
+		F.v[i].inc(delay_carry)
+		F.v[i].xortop(Chunk(carry)<<P_TBITS)
+		delay_carry=int(carry)
+	}
+	F.v[F.length-1].fshl(1)
+	F.v[F.length-1].inc(delay_carry)
+}
+
+/* shift right by one bit */
+
+func (F *FF) shr() {
+	for i:=F.length-1;i>0;i-- {
+		carry:=F.v[i].fshr(1)
+		F.v[i-1].xortop(Chunk(carry)<<P_TBITS)
+	}
+	F.v[0].fshr(1)
+}
+
+/* Convert to Hex String */
+func (F *FF) toString() string {
+	F.norm()
+	s:=""
+	for i:=F.length-1;i>=0;i-- {
+		s+=F.v[i].toString()
+	}
+	return s
+}
+
+/* Convert FFs to/from byte arrays */
+func (F *FF) toBytes(b []byte) {
+	for i:=0;i<F.length;i++ {
+		F.v[i].tobytearray(b,(F.length-i-1)*int(MODBYTES))
+	}
+}
+
+func ff_fromBytes(x *FF,b []byte) {
+	for i:=0;i<x.length;i++ {
+		x.v[i]=frombytearray(b,(x.length-i-1)*int(MODBYTES))
+	}
+}
+
+/* in-place swapping using xor - side channel resistant - lengths must be the same */
+func ff_cswap(a *FF,b *FF,d int) {
+	for i:=0;i<a.length;i++ {
+		a.v[i].cswap(b.v[i],d)
+	}
+}
+
+/* z=x*y, t is workspace */
+func (F *FF) karmul(vp int,x *FF,xp int,y *FF,yp int,t *FF,tp int,n int) {
+	if n==1 {
+		d:=mul(x.v[xp],y.v[yp])
+		F.v[vp+1]=d.split(8*MODBYTES)
+		F.v[vp].dcopy(d)
+		return
+	}
+	nd2:=n/2
+	F.radd(vp,x,xp,x,xp+nd2,nd2)
+		F.rnorm(vp,nd2)
+	F.radd(vp+nd2,y,yp,y,yp+nd2,nd2)
+		F.rnorm(vp+nd2,nd2)
+	t.karmul(tp,F,vp,F,vp+nd2,t,tp+n,nd2)
+	F.karmul(vp,x,xp,y,yp,t,tp+n,nd2)
+	F.karmul(vp+n,x,xp+nd2,y,yp+nd2,t,tp+n,nd2)
+	t.rdec(tp,F,vp,n)
+	t.rdec(tp,F,vp+n,n)
+	F.rinc(vp+nd2,t,tp,n)
+	F.rnorm(vp,2*n)
+}
+
+func (F *FF) karsqr(vp int,x *FF,xp int,t *FF,tp int,n int) {
+	if n==1 {
+		d:=sqr(x.v[xp])
+		F.v[vp+1].copy(d.split(8*MODBYTES))
+		F.v[vp].dcopy(d)
+		return
+	}	
+
+	nd2:=n/2
+	F.karsqr(vp,x,xp,t,tp+n,nd2)
+	F.karsqr(vp+n,x,xp+nd2,t,tp+n,nd2)
+	t.karmul(tp,x,xp,x,xp+nd2,t,tp+n,nd2)
+	F.rinc(vp+nd2,t,tp,n)
+	F.rinc(vp+nd2,t,tp,n)
+	F.rnorm(vp+nd2,n)
+}
+
+/* Calculates Least Significant bottom half of x*y */
+func (F *FF) karmul_lower(vp int,x *FF,xp int,y *FF,yp int,t *FF,tp int,n int) { 
+	if n==1 { /* only calculate bottom half of product */
+		F.v[vp].copy(smul(x.v[xp],y.v[yp]))
+		return
+	}
+	nd2:=n/2
+
+	F.karmul(vp,x,xp,y,yp,t,tp+n,nd2)
+	t.karmul_lower(tp,x,xp+nd2,y,yp,t,tp+n,nd2)
+	F.rinc(vp+nd2,t,tp,nd2)
+	t.karmul_lower(tp,x,xp,y,yp+nd2,t,tp+n,nd2)
+	F.rinc(vp+nd2,t,tp,nd2)
+	F.rnorm(vp+nd2,-nd2)  /* truncate it */
+}
+
+/* Calculates Most Significant upper half of x*y, given lower part */
+func (F *FF) karmul_upper(x *FF,y *FF,t *FF,n int) { 
+	nd2:=n/2
+	F.radd(n,x,0,x,nd2,nd2)
+	F.radd(n+nd2,y,0,y,nd2,nd2)
+	F.rnorm(n,nd2)
+	F.rnorm(n+nd2,nd2)
+
+	t.karmul(0,F,n+nd2,F,n,t,n,nd2)  /* t = (a0+a1)(b0+b1) */
+	F.karmul(n,x,nd2,y,nd2,t,n,nd2) /* z[n]= a1*b1 */
+
+					/* z[0-nd2]=l(a0b0) z[nd2-n]= h(a0b0)+l(t)-l(a0b0)-l(a1b1) */
+	t.rdec(0,F,n,n)              /* t=t-a1b1  */	
+						
+	F.rinc(nd2,F,0,nd2)  /* z[nd2-n]+=l(a0b0) = h(a0b0)+l(t)-l(a1b1)  */
+	F.rdec(nd2,t,0,nd2)   /* z[nd2-n]=h(a0b0)+l(t)-l(a1b1)-l(t-a1b1)=h(a0b0) */
+
+	F.rnorm(0,-n)		/* a0b0 now in z - truncate it */
+
+	t.rdec(0,F,0,n)         /* (a0+a1)(b0+b1) - a0b0 */
+	F.rinc(nd2,t,0,n)
+
+	F.rnorm(nd2,n)
+}
+
+/* z=x*y. Assumes x and y are of same length. */
+func ff_mul(x *FF,y *FF) *FF {
+	n:=x.length
+	z:=NewFFint(2*n)
+	t:=NewFFint(2*n)
+	z.karmul(0,x,0,y,0,t,0,n)
+	return z
+}
+
+/* return low part of product this*y */
+func (F *FF) lmul(y *FF) {
+	n:=F.length
+	t:=NewFFint(2*n)
+	x:=NewFFint(n); x.copy(F)
+	F.karmul_lower(0,x,0,y,0,t,0,n)
+}
+
+/* Set b=b mod c */
+func (F *FF) mod(c *FF) {
+	var k int=1  
+
+	F.norm()
+	if ff_comp(F,c)<0 {return}
+
+	c.shl()
+	for ff_comp(F,c)>=0 {
+		c.shl()
+		k++
+	}
+
+	for k>0 {
+		c.shr()
+		if ff_comp(F,c)>=0 {
+			F.sub(c)
+			F.norm()
+		}
+		k--
+	}
+}
+
+/* z=x^2 */
+func ff_sqr(x *FF) *FF {
+	n:=x.length
+	z:=NewFFint(2*n)
+	t:=NewFFint(2*n)
+	z.karsqr(0,x,0,t,0,n)
+	return z
+}
+
+/* return This mod modulus, N is modulus, ND is Montgomery Constant */
+func (F *FF) reduce(N *FF,ND *FF) *FF { /* fast karatsuba Montgomery reduction */
+	n:=N.length
+	t:=NewFFint(2*n)
+	r:=NewFFint(n)
+	m:=NewFFint(n)
+
+	r.sducopy(F)
+	m.karmul_lower(0,F,0,ND,0,t,0,n)
+
+	F.karmul_upper(N,m,t,n)
+	
+	m.sducopy(F)
+	r.add(N)
+	r.sub(m)
+	r.norm()
+
+	return r
+
+}
+
+/* Set r=this mod b */
+/* this is of length - 2*n */
+/* r,b is of length - n */
+func (F *FF) dmod(b *FF) *FF {
+	n:=b.length
+	m:=NewFFint(2*n)
+	x:=NewFFint(2*n)
+	r:=NewFFint(n)
+
+	x.copy(F)
+	x.norm()
+	m.dsucopy(b); k:=BIGBITS*n
+
+	for ff_comp(x,m)>=0 {
+		x.sub(m)
+		x.norm()
+	}
+
+	for k>0 {	
+		m.shr()
+
+		if ff_comp(x,m)>=0 {
+			x.sub(m)
+			x.norm()
+		}
+		k--
+	}
+
+	r.copy(x)
+	r.mod(b)
+	return r
+}
+
+/* Set return=1/this mod p. Binary method - a<p on entry */
+
+func (F *FF) invmodp(p *FF) {
+	n:=p.length
+
+	u:=NewFFint(n)
+	v:=NewFFint(n)
+	x1:=NewFFint(n)
+	x2:=NewFFint(n)
+	t:=NewFFint(n)
+	one:=NewFFint(n)
+
+	one.one()
+	u.copy(F)
+	v.copy(p)
+	x1.copy(one)
+	x2.zero()
+
+	// reduce n in here as well! 
+	for (ff_comp(u,one)!=0 && ff_comp(v,one)!=0) {
+		for u.parity()==0 {
+			u.shr()
+			if x1.parity()!=0 {
+				x1.add(p)
+				x1.norm()
+			}
+			x1.shr()
+		}
+		for v.parity()==0 {
+			v.shr() 
+			if x2.parity()!=0 {
+				x2.add(p)
+				x2.norm()
+			}
+			x2.shr()
+		}
+		if ff_comp(u,v)>=0 {
+			u.sub(v)
+			u.norm()
+			if ff_comp(x1,x2)>=0 {
+				x1.sub(x2)
+			} else {
+				t.copy(p)
+				t.sub(x2)
+				x1.add(t)
+			}
+			x1.norm()
+		} else {
+			v.sub(u)
+			v.norm()
+			if ff_comp(x2,x1)>=0 { 
+				x2.sub(x1)
+			} else {
+				t.copy(p)
+				t.sub(x1)
+				x2.add(t)
+			}
+			x2.norm()
+		}
+	}
+	if ff_comp(u,one)==0 {
+		F.copy(x1)
+	} else {
+		F.copy(x2)
+	}
+}
+
+/* nresidue mod m */
+func (F *FF) nres(m *FF) {
+	n:=m.length
+	if n==1 {
+		d:=NewDBIGscopy(F.v[0])
+		d.shl(uint(NLEN)*BASEBITS)
+		F.v[0].copy(d.mod(m.v[0]))
+	} else {
+		d:=NewFFint(2*n)
+		d.dsucopy(F)
+		F.copy(d.dmod(m))
+	}
+}
+
+func (F *FF) redc(m *FF,ND *FF) {
+	n:=m.length
+	if n==1 {
+		d:=NewDBIGscopy(F.v[0])
+		F.v[0].copy(monty(m.v[0],Chunk(1)<<BASEBITS-ND.v[0].w[0],d))
+	} else {
+		d:=NewFFint(2*n)
+		F.mod(m)
+		d.dscopy(F)
+		F.copy(d.reduce(m,ND))
+		F.mod(m)
+	}
+}
+
+func (F *FF) mod2m(m int) {
+	for i:=m;i<F.length;i++ {
+		F.v[i].zero()
+	}
+}
+
+/* U=1/a mod 2^m - Arazi & Qi */
+func (F *FF) invmod2m() *FF {
+	n:=F.length
+
+	b:=NewFFint(n)
+	c:=NewFFint(n)
+	U:=NewFFint(n)
+
+	U.zero()
+	U.v[0].copy(F.v[0])
+	U.v[0].invmod2m()
+
+	for i:=1;i<n;i<<=1 {
+		b.copy(F); b.mod2m(i)
+		t:=ff_mul(U,b); t.shrw(i); b.copy(t)
+		c.copy(F); c.shrw(i); c.mod2m(i)
+		c.lmul(U); c.mod2m(i)
+
+		b.add(c); b.norm()
+		b.lmul(U); b.mod2m(i)
+
+		c.one(); c.shlw(i); b.revsub(c); b.norm()
+		b.shlw(i)
+		U.add(b)
+	}
+	U.norm()
+	return U
+}
+
+func (F *FF) random(rng *RAND) {
+	n:=F.length
+	for i:=0;i<n;i++ {
+		F.v[i].copy(random(rng))
+	}
+	/* make sure top bit is 1 */
+	for (F.v[n-1].nbits()<int(MODBYTES*8)) {
+		F.v[n-1].copy(random(rng))
+	}
+}
+
+/* generate random x less than p */
+func (F *FF) randomnum(p *FF,rng *RAND) {
+	n:=F.length
+	d:=NewFFint(2*n)
+
+	for i:=0;i<2*n;i++ {
+		d.v[i].copy(random(rng))
+	}
+	F.copy(d.dmod(p))
+}
+
+/* this*=y mod p */
+func (F *FF) modmul(y *FF,p *FF,nd *FF) {
+	if ff_pexceed(F.v[F.length-1],y.v[y.length-1]) {F.mod(p)}
+	n:=p.length
+	if n==1 {
+		d:=mul(F.v[0],y.v[0])
+		F.v[0].copy(monty(p.v[0],Chunk(1)<<BASEBITS-nd.v[0].w[0],d))		
+	} else {
+		d:=ff_mul(F,y)
+		F.copy(d.reduce(p,nd))
+	}
+}
+
+/* this*=y mod p */
+func (F *FF) modsqr(p *FF,nd *FF) {
+	if ff_sexceed(F.v[F.length-1]) {F.mod(p)}
+	n:=p.length
+	if n==1 {
+		d:=sqr(F.v[0])
+		F.v[0].copy(monty(p.v[0],Chunk(1)<<BASEBITS-nd.v[0].w[0],d))			
+	} else {
+		d:=ff_sqr(F)
+		F.copy(d.reduce(p,nd))
+	}
+}
+
+/* this=this^e mod p using side-channel resistant Montgomery Ladder, for large e */
+func (F *FF) skpow(e *FF,p *FF) {
+	n:=p.length
+	R0:=NewFFint(n)
+	R1:=NewFFint(n)
+	ND:=p.invmod2m()
+
+	F.mod(p)
+	R0.one()
+	R1.copy(F)
+	R0.nres(p)
+	R1.nres(p)
+
+	for i:=int(8*MODBYTES)*n-1;i>=0;i-- {
+		b:=int(e.v[i/BIGBITS].bit(i%BIGBITS))
+		F.copy(R0)
+		F.modmul(R1,p,ND)
+
+		ff_cswap(R0,R1,b)
+		R0.modsqr(p,ND)
+
+		R1.copy(F)
+		ff_cswap(R0,R1,b)
+	}
+	F.copy(R0)
+	F.redc(p,ND)
+}
+
+/* this =this^e mod p using side-channel resistant Montgomery Ladder, for short e */
+func (F *FF) skpows(e *BIG,p *FF) {
+	n:=p.length
+	R0:=NewFFint(n)
+	R1:=NewFFint(n)
+	ND:=p.invmod2m()
+
+	F.mod(p)
+	R0.one()
+	R1.copy(F)
+	R0.nres(p)
+	R1.nres(p)
+
+	for i:=int(8*MODBYTES)-1;i>=0;i-- {
+		b:=int(e.bit(i))
+		F.copy(R0)
+		F.modmul(R1,p,ND)
+
+		ff_cswap(R0,R1,b)
+		R0.modsqr(p,ND)
+
+		R1.copy(F)
+		ff_cswap(R0,R1,b)
+	}
+	F.copy(R0)
+	F.redc(p,ND)
+}
+
+/* raise to an integer power - right-to-left method */
+func (F *FF) power(e int,p *FF) {
+	n:=p.length
+	w:=NewFFint(n)
+	ND:=p.invmod2m()
+	f:=true
+
+	w.copy(F)
+	w.nres(p)
+//i:=0;
+	if e==2 {
+		F.copy(w)
+		F.modsqr(p,ND)
+	} else {
+		for (true) {
+			if e%2==1 {
+				if f {
+					F.copy(w)
+				} else {F.modmul(w,p,ND)}
+				f=false
+
+			}
+			e>>=1
+			if e==0 {break}
+//fmt.Printf("wb= "+w.toString()+"\n");
+//debug=true;
+			w.modsqr(p,ND)
+//debug=false;
+//fmt.Printf("wa= "+w.toString()+"\n");
+//i+=1;
+//os.Exit(0);
+		}
+	}
+
+	F.redc(p,ND)
+
+}
+
+/* this=this^e mod p, faster but not side channel resistant */
+func (F *FF) pow(e *FF,p *FF) {
+	n:=p.length
+	w:=NewFFint(n)
+	ND:=p.invmod2m()
+//fmt.Printf("ND= "+ND.toString() +"\n");
+	w.copy(F)
+	F.one()
+	F.nres(p)
+	w.nres(p)
+	for i:=int(8*MODBYTES)*n-1;i>=0;i-- {
+		F.modsqr(p,ND)
+		b:=e.v[i/BIGBITS].bit(i%BIGBITS)
+		if b==1 {F.modmul(w,p,ND)}
+	}
+	F.redc(p,ND)
+}
+
+/* double exponentiation r=x^e.y^f mod p */
+func (F *FF) pow2(e *BIG,y *FF,f *BIG,p *FF) {
+	n:=p.length
+	xn:=NewFFint(n)
+	yn:=NewFFint(n)
+	xy:=NewFFint(n)
+	ND:=p.invmod2m()
+
+	xn.copy(F)
+	yn.copy(y)
+	xn.nres(p)
+	yn.nres(p)
+	xy.copy(xn); xy.modmul(yn,p,ND)
+	F.one()
+	F.nres(p)
+
+	for i:=int(8*MODBYTES)-1;i>=0;i-- {
+		eb:=e.bit(i)
+		fb:=f.bit(i)
+		F.modsqr(p,ND)
+		if eb==1 {
+			if fb==1 {
+				F.modmul(xy,p,ND)
+			} else {F.modmul(xn,p,ND)}
+		} else	{
+			if fb==1 {F.modmul(yn,p,ND)}
+		}
+	}
+	F.redc(p,ND)
+}
+
+func igcd(x int,y int) int { /* integer GCD, returns GCD of x and y */
+	var r int
+	if y==0 {return x}
+	for true {
+		r=x%y
+		if r==0 {break}
+		x=y;y=r
+	}
+	return y
+}
+
+/* quick and dirty check for common factor with n */
+func (F *FF) cfactor(s int) bool {
+	n:=F.length
+
+	x:=NewFFint(n)
+	y:=NewFFint(n)
+
+	y.set(s)
+	x.copy(F)
+	x.norm()
+
+	x.sub(y)
+	x.norm()
+
+	for (!x.iszilch() && x.parity()==0) {x.shr()}
+
+	for (ff_comp(x,y)>0) {
+		x.sub(y)
+		x.norm()
+		for (!x.iszilch() && x.parity()==0) {x.shr()}
+	}
+
+	g:=int(x.v[0].get(0))
+	r:=igcd(s,g)
+	if r>1 {return true}
+	return false
+}
+
+/* Miller-Rabin test for primality. Slow. */
+func prime(p *FF,rng *RAND) bool {
+	s:=0
+	n:=p.length
+	d:=NewFFint(n)
+	x:=NewFFint(n)
+	unity:=NewFFint(n)
+	nm1:=NewFFint(n)
+
+	sf:=4849845 /* 3*5*.. *19 */
+	p.norm()
+
+	if p.cfactor(sf) {return false}
+	unity.one()
+	nm1.copy(p)
+	nm1.sub(unity)
+	nm1.norm()
+	d.copy(nm1)
+
+	for d.parity()==0 {
+		d.shr()
+		s++
+	}
+	if s==0 {return false}
+
+	for i:=0;i<10;i++ {
+		x.randomnum(p,rng)
+		x.pow(d,p)
+
+		if (ff_comp(x,unity)==0 || ff_comp(x,nm1)==0) {continue}
+		loop:=false
+		for j:=1;j<s;j++ {
+			x.power(2,p)
+			if ff_comp(x,unity)==0 {return false}
+			if ff_comp(x,nm1)==0 {loop=true; break}
+		}
+		if loop {continue}
+		return false
+	}
+
+	return true
+}
+/*
+func main() {
+
+	var P = [4][5]int64 {{0xAD19A781670957,0x76A79C00965796,0xDEFCC5FC9A9717,0xF02F2940E20E9,0xBF59E34F},{0x6894F31844C908,0x8DADA70E82C79F,0xFD29F3836046F6,0x8C1D874D314DD0,0x46D077B},{0x3C515217813331,0x56680FD1CE935B,0xE55C53EEA8838E,0x92C2F7E14A4A95,0xD945E5B1},{0xACF673E919F5EF,0x6723E7E7DAB446,0x6B6FA69B36EB1B,0xF7D13920ECA300,0xB5FC2165}}
+
+	fmt.Printf("Testing FF\n")
+	var raw [100]byte
+	rng:=NewRAND()
+
+	rng.Clean()
+	for i:=0;i<100;i++ {
+		raw[i]=byte(i)
+	}
+
+	rng.Seed(100,raw[:])
+
+	n:=4
+
+	x:=NewFFint(n)
+	x.set(3)
+
+	p:=NewFFints(P[:],n)
+
+	if prime(p,rng) {fmt.Printf("p is a prime\n"); fmt.Printf("\n")}
+
+	e:=NewFFint(n)
+	e.copy(p)
+	e.dec(1); e.norm()
+
+	fmt.Printf("e= "+e.toString())
+	fmt.Printf("\n")
+	x.skpow(e,p)
+	fmt.Printf("x= "+x.toString())
+	fmt.Printf("\n")
+}
+*/
\ No newline at end of file
diff --git a/version22/go/FP.go b/version22/go/FP.go
new file mode 100644
index 0000000..89bcbda
--- /dev/null
+++ b/version22/go/FP.go
@@ -0,0 +1,279 @@
+/*
+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.
+*/
+
+/* Finite Field arithmetic */
+/* CLINT mod p functions */
+
+package main
+
+//import "fmt"
+
+type FP struct {
+	x *BIG
+}
+
+/* Constructors */
+func NewFPint(a int) *FP {
+	F:=new(FP)
+	F.x=NewBIGint(a)
+	F.nres()
+	return F
+}
+
+func NewFPbig(a *BIG) *FP {
+	F:=new(FP)
+	F.x=NewBIGcopy(a)
+	F.nres()
+	return F
+}
+
+func NewFPcopy(a *FP) *FP {
+	F:=new(FP)
+	F.x=NewBIGcopy(a.x)
+	return F
+}
+
+func (F *FP) toString() string {
+	return F.redc().toString()
+}
+
+/* convert to Montgomery n-residue form */
+func (F *FP) nres() {
+	if MODTYPE!=PSEUDO_MERSENNE && MODTYPE!=GENERALISED_MERSENNE {
+		p:=NewBIGints(Modulus);
+		d:=NewDBIGscopy(F.x)
+		d.shl(uint(NLEN)*BASEBITS)
+		F.x.copy(d.mod(p))
+	}
+}
+
+/* convert back to regular form */
+func (F *FP) redc() *BIG {
+	if MODTYPE!=PSEUDO_MERSENNE && MODTYPE!=GENERALISED_MERSENNE {
+		d:=NewDBIGscopy(F.x)
+		return mod(d)
+	} else {
+		r:=NewBIGcopy(F.x)
+		return r
+	}
+}
+
+/* reduce this mod Modulus */
+func (F *FP) reduce() {
+	p:=NewBIGints(Modulus)
+	F.x.mod(p)
+}
+
+/* test this=0? */
+func (F *FP) iszilch() bool {
+	F.reduce()
+	return F.x.iszilch()
+}
+
+/* copy from FP b */
+func (F *FP) copy(b *FP ) {
+	F.x.copy(b.x)
+}
+
+/* set this=0 */
+func (F *FP) zero() {
+	F.x.zero()
+}
+	
+/* set this=1 */
+func (F *FP) one() {
+	F.x.one(); F.nres()
+}
+
+/* normalise this */
+func (F *FP) norm() {
+	F.x.norm();
+}
+
+/* swap FPs depending on d */
+func (F *FP) cswap(b *FP,d int) {
+	F.x.cswap(b.x,d);
+}
+
+/* copy FPs depending on d */
+func (F *FP) cmove(b *FP,d int) {
+	F.x.cmove(b.x,d)
+}
+
+/* this*=b mod Modulus */
+func (F *FP) mul(b *FP) {
+
+	F.norm()
+	b.norm()
+	if pexceed(F.x,b.x) {F.reduce()}
+	d:=mul(F.x,b.x)
+	F.x.copy(mod(d))
+}
+
+func logb2(w uint32) uint {
+	v:=w
+	v |= (v >> 1)
+	v |= (v >> 2)
+	v |= (v >> 4)
+	v |= (v >> 8)
+	v |= (v >> 16)
+
+	v = v - ((v >> 1) & 0x55555555)                 
+	v = (v & 0x33333333) + ((v >> 2) & 0x33333333)  
+	r:= uint((   ((v + (v >> 4)) & 0xF0F0F0F)   * 0x1010101) >> 24)
+	return (r+1)
+}
+
+/* this = -this mod Modulus */
+func (F *FP) neg() {
+	p:=NewBIGints(Modulus)
+	m:=NewBIGcopy(p)
+	F.norm()
+	sb:=logb2(uint32(EXCESS(F.x)))
+
+//	ov:=EXCESS(F.x); 
+//	sb:=uint(1); for ov!=0 {sb++;ov>>=1} 
+
+	m.fshl(sb)
+	F.x.rsub(m)		
+
+	if EXCESS(F.x)>=FEXCESS {F.reduce()}
+}
+
+
+/* this*=c mod Modulus, where c is a small int */
+func (F *FP) imul(c int) {
+	F.norm()
+	s:=false
+	if (c<0) {
+		c=-c
+		s=true
+	}
+	afx:=(EXCESS(F.x)+1)*(Chunk(c)+1)+1;
+	if (c<NEXCESS && afx<FEXCESS) {
+		F.x.imul(c);
+	} else {
+		if (afx<FEXCESS) {
+			F.x.pmul(c)
+		} else {
+			p:=NewBIGints(Modulus);
+			d:=F.x.pxmul(c)
+			F.x.copy(d.mod(p))
+		}
+	}
+	if s {F.neg()}
+	F.norm()
+}
+
+/* this*=this mod Modulus */
+func (F *FP) sqr() {
+	F.norm();
+	if sexceed(F.x) {F.reduce()}
+	d:=sqr(F.x)	
+	F.x.copy(mod(d))
+}
+
+/* this+=b */
+func (F *FP) add(b *FP) {
+	F.x.add(b.x)
+	if (EXCESS(F.x)+2>=FEXCESS) {F.reduce()}
+}
+
+/* this-=b */
+func (F *FP) sub(b *FP) {
+	n:=NewFPcopy(b)
+	n.neg()
+	F.add(n)
+}
+
+/* this/=2 mod Modulus */
+func (F *FP) div2() {
+	F.x.norm()
+	if (F.x.parity()==0) {
+		F.x.fshr(1)
+	} else {
+		p:=NewBIGints(Modulus);
+		F.x.add(p)
+		F.x.norm()
+		F.x.fshr(1)
+	}
+}
+
+/* this=1/this mod Modulus */
+func (F *FP) inverse() {
+	p:=NewBIGints(Modulus);
+	r:=F.redc()
+	r.invmodp(p)
+	F.x.copy(r)
+	F.nres()
+}
+
+/* return TRUE if this==a */
+func (F *FP) equals(a *FP) bool {
+	a.reduce()
+	F.reduce()
+	if (comp(a.x,F.x)==0) {return true}
+	return false
+}
+
+/* return this^e mod Modulus */
+func (F *FP) pow(e *BIG) *FP {
+	r:=NewFPint(1)
+	e.norm()
+	F.x.norm()
+	m:=NewFPcopy(F)
+	for true {
+		bt:=e.parity();
+		e.fshr(1);
+		if bt==1 {r.mul(m)}
+		if e.iszilch() {break}
+		m.sqr();
+	}
+	p:=NewBIGints(Modulus);
+	r.x.mod(p);
+	return r;
+}
+
+/* return sqrt(this) mod Modulus */
+func (F *FP) sqrt() *FP {
+	F.reduce();
+	p:=NewBIGints(Modulus);
+	b:=NewBIGcopy(p)
+	if MOD8==5 {
+		b.dec(5); b.norm(); b.shr(3)
+		i:=NewFPcopy(F); i.x.shl(1)
+		v:=i.pow(b)
+		i.mul(v); i.mul(v)
+		i.x.dec(1)
+		r:=NewFPcopy(F)
+		r.mul(v); r.mul(i) 
+		r.reduce()
+		return r
+	} else {
+		b.inc(1); b.norm(); b.shr(2)
+		return F.pow(b);
+	}
+}
+
+/* return jacobi symbol (this/Modulus) */
+func (F *FP) jacobi() int {
+	w:=F.redc();
+	p:=NewBIGints(Modulus);
+	return w.jacobi(p)
+}
diff --git a/version22/go/FP12.go b/version22/go/FP12.go
new file mode 100644
index 0000000..88371b2
--- /dev/null
+++ b/version22/go/FP12.go
@@ -0,0 +1,551 @@
+/*
+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.
+*/
+
+/* MiotCL Fp^12 functions */
+/* FP12 elements are of the form a+i.b+i^2.c */
+
+package main
+
+//import "fmt"
+
+type FP12 struct {
+	a *FP4
+	b *FP4
+	c *FP4
+}
+
+/* Constructors */
+func NewFP12fp4(d *FP4) *FP12 {
+	F:=new(FP12)
+	F.a=NewFP4copy(d)
+	F.b=NewFP4int(0)
+	F.c=NewFP4int(0)
+	return F
+}
+
+func NewFP12int(d int) *FP12 {
+	F:=new(FP12)
+	F.a=NewFP4int(d)
+	F.b=NewFP4int(0)
+	F.c=NewFP4int(0)
+	return F
+}
+
+func NewFP12fp4s(d *FP4,e *FP4,f *FP4) *FP12 {
+	F:=new(FP12)
+	F.a=NewFP4copy(d)
+	F.b=NewFP4copy(e)
+	F.c=NewFP4copy(f)
+	return F
+}
+
+func NewFP12copy(x *FP12) *FP12 {
+	F:=new(FP12)
+	F.a=NewFP4copy(x.a)
+	F.b=NewFP4copy(x.b)
+	F.c=NewFP4copy(x.c)
+	return F
+}
+
+/* reduce all components of this mod Modulus */
+func (F *FP12) reduce() {
+	F.a.reduce()
+	F.b.reduce()
+	F.c.reduce()
+}
+/* normalise all components of this */
+func (F *FP12) norm() {
+	F.a.norm()
+	F.b.norm()
+	F.c.norm()
+}
+/* test x==0 ? */
+func (F *FP12) iszilch() bool {
+	F.reduce()
+	return (F.a.iszilch() && F.b.iszilch() && F.c.iszilch())
+}
+/* test x==1 ? */
+func (F *FP12) isunity() bool {
+	one:=NewFP4int(1)
+	return (F.a.equals(one) && F.b.iszilch() && F.c.iszilch())
+}
+/* return 1 if x==y, else 0 */
+func (F *FP12) equals(x *FP12) bool {
+	return (F.a.equals(x.a) && F.b.equals(x.b) && F.c.equals(x.c))
+}
+
+/* extract a from this */
+func (F *FP12) geta() *FP4 {
+	return F.a
+}
+/* extract b */
+func (F *FP12) getb() *FP4 {
+	return F.b
+}
+/* extract c */
+func (F *FP12) getc() *FP4 {
+	return F.c
+}
+/* copy this=x */
+func (F *FP12) copy(x *FP12) {
+	F.a.copy(x.a)
+	F.b.copy(x.b)
+	F.c.copy(x.c)
+}
+/* set this=1 */
+func (F *FP12) one() {
+	F.a.one()
+	F.b.zero()
+	F.c.zero()
+}
+/* this=conj(this) */
+func (F *FP12) conj() {
+	F.a.conj()
+	F.b.nconj()
+	F.c.conj()
+}
+
+/* Granger-Scott Unitary Squaring */
+func (F *FP12) usqr() {
+	A:=NewFP4copy(F.a)
+	B:=NewFP4copy(F.c)
+	C:=NewFP4copy(F.b)
+	D:=NewFP4int(0)
+
+	F.a.sqr()
+	D.copy(F.a); D.add(F.a)
+	F.a.add(D)
+
+	F.a.norm();
+	A.nconj()
+
+	A.add(A)
+	F.a.add(A)
+	B.sqr()
+	B.times_i()
+
+	D.copy(B); D.add(B)
+	B.add(D)
+	B.norm();
+
+	C.sqr()
+	D.copy(C); D.add(C)
+	C.add(D)
+	C.norm();
+
+	F.b.conj()
+	F.b.add(F.b)
+	F.c.nconj()
+
+	F.c.add(F.c)
+	F.b.add(B)
+	F.c.add(C)
+	F.reduce()
+
+}
+
+/* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
+func (F *FP12)  sqr() {
+	A:=NewFP4copy(F.a)
+	B:=NewFP4copy(F.b)
+	C:=NewFP4copy(F.c)
+	D:=NewFP4copy(F.a)
+
+	A.sqr()
+	B.mul(F.c)
+	B.add(B)
+	C.sqr()
+	D.mul(F.b)
+	D.add(D)
+
+	F.c.add(F.a)
+	F.c.add(F.b)
+	F.c.sqr()
+
+	F.a.copy(A)
+
+	A.add(B)
+	A.norm();
+	A.add(C)
+	A.add(D)
+	A.norm();
+
+	A.neg()
+	B.times_i();
+	C.times_i()
+
+	F.a.add(B)
+
+	F.b.copy(C); F.b.add(D)
+	F.c.add(A)
+	F.norm()
+}
+
+/* FP12 full multiplication this=this*y */
+func (F *FP12) mul(y *FP12) {
+	z0:=NewFP4copy(F.a)
+	z1:=NewFP4int(0)
+	z2:=NewFP4copy(F.b)
+	z3:=NewFP4int(0)
+	t0:=NewFP4copy(F.a)
+	t1:=NewFP4copy(y.a)
+
+	z0.mul(y.a)
+	z2.mul(y.b)
+
+	t0.add(F.b)
+	t1.add(y.b)
+
+	z1.copy(t0); z1.mul(t1)
+	t0.copy(F.b); t0.add(F.c)
+
+	t1.copy(y.b); t1.add(y.c)
+	z3.copy(t0); z3.mul(t1)
+
+	t0.copy(z0); t0.neg()
+	t1.copy(z2); t1.neg()
+
+	z1.add(t0)
+	z1.norm();
+	F.b.copy(z1); F.b.add(t1)
+
+	z3.add(t1)
+	z2.add(t0)
+
+	t0.copy(F.a); t0.add(F.c)
+	t1.copy(y.a); t1.add(y.c)
+	t0.mul(t1)
+	z2.add(t0)
+
+	t0.copy(F.c); t0.mul(y.c)
+	t1.copy(t0); t1.neg()
+
+	z2.norm();
+	z3.norm();
+	F.b.norm();
+
+	F.c.copy(z2); F.c.add(t1)
+	z3.add(t1)
+	t0.times_i()
+	F.b.add(t0)
+
+	z3.times_i()
+	F.a.copy(z0); F.a.add(z3)
+	F.norm()
+}
+
+/* Special case of multiplication arises from special form of ATE pairing line function */
+func (F *FP12) smul(y *FP12) {
+	z0:=NewFP4copy(F.a)
+	z2:=NewFP4copy(F.b)
+	z3:=NewFP4copy(F.b)
+	t0:=NewFP4int(0)
+	t1:=NewFP4copy(y.a)
+		
+	z0.mul(y.a)
+	z2.pmul(y.b.real());
+	F.b.add(F.a)
+	t1.real().add(y.b.real())
+
+	F.b.mul(t1)
+	z3.add(F.c);
+	z3.pmul(y.b.real())
+
+	t0.copy(z0); t0.neg()
+	t1.copy(z2); t1.neg()
+
+	F.b.add(t0)
+	F.b.norm();
+
+	F.b.add(t1)
+	z3.add(t1)
+	z2.add(t0)
+
+	t0.copy(F.a); t0.add(F.c)
+	t0.mul(y.a)
+	F.c.copy(z2); F.c.add(t0)
+
+	z3.times_i()
+	F.a.copy(z0); F.a.add(z3)
+
+	F.norm()
+}
+
+/* this=1/this */
+func (F *FP12) inverse() {
+	f0:=NewFP4copy(F.a)
+	f1:=NewFP4copy(F.b)
+	f2:=NewFP4copy(F.a)
+	f3:=NewFP4int(0)
+
+	F.norm()
+	f0.sqr()
+	f1.mul(F.c)
+	f1.times_i()
+	f0.sub(f1)
+
+	f1.copy(F.c); f1.sqr()
+	f1.times_i()
+	f2.mul(F.b)
+	f1.sub(f2)
+
+	f2.copy(F.b); f2.sqr()
+	f3.copy(F.a); f3.mul(F.c)
+	f2.sub(f3)
+
+	f3.copy(F.b); f3.mul(f2)
+	f3.times_i()
+	F.a.mul(f0)
+	f3.add(F.a)
+	F.c.mul(f1)
+	F.c.times_i()
+
+	f3.add(F.c)
+	f3.inverse()
+	F.a.copy(f0); F.a.mul(f3)
+	F.b.copy(f1); F.b.mul(f3)
+	F.c.copy(f2); F.c.mul(f3)
+}
+
+/* this=this^p using Frobenius */
+func (F *FP12) frob(f *FP2) {
+	f2:=NewFP2copy(f)
+	f3:=NewFP2copy(f)
+
+	f2.sqr()
+	f3.mul(f2)
+
+	F.a.frob(f3);
+	F.b.frob(f3);
+	F.c.frob(f3);
+
+	F.b.pmul(f);
+	F.c.pmul(f2);
+}
+
+/* trace function */
+func (F *FP12) trace() *FP4 {
+	t:=NewFP4int(0)
+	t.copy(F.a)
+	t.imul(3)
+	t.reduce()
+	return t;
+}
+
+
+/* convert from byte array to FP12 */
+func FP12_fromBytes(w []byte) *FP12 {
+	var t [int(MODBYTES)]byte
+	MB:=int(MODBYTES)
+
+	for i:=0;i<MB;i++ {t[i]=w[i]}
+	a:=fromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+MB]}
+	b:=fromBytes(t[:])
+	c:=NewFP2bigs(a,b)
+
+	for i:=0;i<MB;i++ {t[i]=w[i+2*MB]}
+	a=fromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+3*MB]}
+	b=fromBytes(t[:])
+	d:=NewFP2bigs(a,b)
+
+	e:=NewFP4fp2s(c,d)
+
+
+	for i:=0;i<MB;i++ {t[i]=w[i+4*MB]}
+	a=fromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+5*MB]}
+	b=fromBytes(t[:])
+	c=NewFP2bigs(a,b)
+
+	for i:=0;i<MB;i++ {t[i]=w[i+6*MB]}
+	a=fromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+7*MB]}
+	b=fromBytes(t[:])
+	d=NewFP2bigs(a,b)
+
+	f:=NewFP4fp2s(c,d)
+
+
+	for i:=0;i<MB;i++ {t[i]=w[i+8*MB]}
+	a=fromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+9*MB]}
+	b=fromBytes(t[:]);
+		
+	c=NewFP2bigs(a,b)
+
+	for i:=0;i<MB;i++ {t[i]=w[i+10*MB]}
+	a=fromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+11*MB]}
+	b=fromBytes(t[:])
+	d=NewFP2bigs(a,b)
+
+	g:=NewFP4fp2s(c,d)
+
+	return NewFP12fp4s(e,f,g)
+}
+
+/* convert this to byte array */
+func (F *FP12) toBytes(w []byte) {
+	var t [int(MODBYTES)]byte
+	MB:=int(MODBYTES)
+	F.a.geta().getA().toBytes(t[:])
+	for i:=0;i<MB;i++ {w[i]=t[i]}
+	F.a.geta().getB().toBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+MB]=t[i]}
+	F.a.getb().getA().toBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+2*MB]=t[i]}
+	F.a.getb().getB().toBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+3*MB]=t[i]}
+
+	F.b.geta().getA().toBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+4*MB]=t[i]}
+	F.b.geta().getB().toBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+5*MB]=t[i]}
+	F.b.getb().getA().toBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+6*MB]=t[i]}
+	F.b.getb().getB().toBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+7*MB]=t[i]}
+
+	F.c.geta().getA().toBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+8*MB]=t[i]}
+	F.c.geta().getB().toBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+9*MB]=t[i]}
+	F.c.getb().getA().toBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+10*MB]=t[i]}
+	F.c.getb().getB().toBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+11*MB]=t[i]}
+}
+
+/* convert to hex string */
+func (F *FP12) toString() string {
+	return ("["+F.a.toString()+","+F.b.toString()+","+F.c.toString()+"]")
+}
+
+/* this=this^e */ 
+func (F *FP12) pow(e *BIG) *FP12 {
+	F.norm()
+	e.norm()
+	w:=NewFP12copy(F)
+	z:=NewBIGcopy(e)
+	r:=NewFP12int(1)
+
+	for true {
+		bt:=z.parity()
+		z.fshr(1)
+		if bt==1 {r.mul(w)}
+		if z.iszilch() {break}
+		w.usqr()
+	}
+	r.reduce();
+	return r;
+}
+
+/* constant time powering by small integer of max length bts */
+func (F *FP12) pinpow(e int,bts int) {
+	var R []*FP12
+	R=append(R,NewFP12int(1))
+	R=append(R,NewFP12copy(F))
+
+	for i:=bts-1;i>=0;i-- {
+		b:=(e>>uint(i))&1
+		R[1-b].mul(R[b])
+		R[b].usqr()
+	}
+	F.copy(R[0])
+}
+
+/* p=q0^u0.q1^u1.q2^u2.q3^u3 */
+/* Timing attack secure, but not cache attack secure */
+
+ func pow4(q []*FP12,u []*BIG) *FP12 {
+	var a [4]int8
+	var g []*FP12
+	var s []*FP12
+	c:=NewFP12int(1)
+	p:=NewFP12int(0)
+	var w [NLEN*int(BASEBITS)+1]int8
+	var t []*BIG
+	mt:=NewBIGint(0)
+
+	for i:=0;i<4;i++ {
+		t=append(t,NewBIGcopy(u[i]))
+	}
+
+	s=append(s,NewFP12int(0))
+	s=append(s,NewFP12int(0))
+
+	g=append(g,NewFP12copy(q[0])); s[0].copy(q[1]); s[0].conj(); g[0].mul(s[0])
+	g=append(g,NewFP12copy(g[0]))
+	g=append(g,NewFP12copy(g[0]))
+	g=append(g,NewFP12copy(g[0]))
+	g=append(g,NewFP12copy(q[0])); g[4].mul(q[1])
+	g=append(g,NewFP12copy(g[4]))
+	g=append(g,NewFP12copy(g[4]))
+	g=append(g,NewFP12copy(g[4]))
+
+	s[1].copy(q[2]); s[0].copy(q[3]); s[0].conj(); s[1].mul(s[0])
+	s[0].copy(s[1]); s[0].conj(); g[1].mul(s[0])
+	g[2].mul(s[1])
+	g[5].mul(s[0])
+	g[6].mul(s[1])
+	s[1].copy(q[2]); s[1].mul(q[3])
+	s[0].copy(s[1]); s[0].conj(); g[0].mul(s[0])
+	g[3].mul(s[1])
+	g[4].mul(s[0])
+	g[7].mul(s[1])
+
+/* if power is even add 1 to power, and add q to correction */
+
+	for i:=0;i<4;i++ {
+		if t[i].parity()==0 {
+			t[i].inc(1); t[i].norm()
+			c.mul(q[i])
+		}
+		mt.add(t[i]); mt.norm()
+	}
+	c.conj()
+	nb:=1+mt.nbits()
+
+/* convert exponent to signed 1-bit window */
+	for j:=0;j<nb;j++ {
+		for i:=0;i<4;i++ {
+			a[i]=int8(t[i].lastbits(2)-2)
+			t[i].dec(int(a[i])); t[i].norm();
+			t[i].fshr(1)
+		}
+		w[j]=(8*a[0]+4*a[1]+2*a[2]+a[3])
+	}
+	w[nb]=int8(8*t[0].lastbits(2)+4*t[1].lastbits(2)+2*t[2].lastbits(2)+t[3].lastbits(2))
+	p.copy(g[(w[nb]-1)/2])
+
+	for i:=nb-1;i>=0;i-- {
+		m:=w[i]>>7
+		j:=(w[i]^m)-m  /* j=abs(w[i]) */
+		j=(j-1)/2
+		s[0].copy(g[j]); s[1].copy(g[j]); s[1].conj()
+		p.usqr()
+		p.mul(s[m&1]);
+	}
+	p.mul(c)  /* apply correction */
+	p.reduce()
+	return p;
+}
+
diff --git a/version22/go/FP2.go b/version22/go/FP2.go
new file mode 100644
index 0000000..d4993e2
--- /dev/null
+++ b/version22/go/FP2.go
@@ -0,0 +1,300 @@
+/*
+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.
+*/
+
+/* Finite Field arithmetic  Fp^2 functions */
+
+/* FP2 elements are of the form a+ib, where i is sqrt(-1) */
+
+package main
+
+//import "fmt"
+
+type FP2 struct {
+	a *FP
+	b *FP
+}
+
+/* Constructors */
+func NewFP2int(a int) *FP2 {
+	F:=new(FP2)
+	F.a=NewFPint(a)
+	F.b=NewFPint(0)
+	return F
+}
+
+func NewFP2copy(x *FP2) *FP2 {
+	F:=new(FP2)
+	F.a=NewFPcopy(x.a)
+	F.b=NewFPcopy(x.b)
+	return F
+}
+
+func NewFP2fps(c *FP,d *FP) *FP2 {
+	F:=new(FP2)
+	F.a=NewFPcopy(c)
+	F.b=NewFPcopy(d)
+	return F
+}
+
+func NewFP2bigs(c *BIG,d *BIG) *FP2 {
+	F:=new(FP2)
+	F.a=NewFPbig(c)
+	F.b=NewFPbig(d)
+	return F
+}
+
+func NewFP2fp(c *FP) *FP2 {
+	F:=new(FP2)
+	F.a=NewFPcopy(c)
+	F.b=NewFPint(0)
+	return F
+}
+
+func NewFP2big(c *BIG) *FP2 {
+	F:=new(FP2)
+	F.a=NewFPbig(c)
+	F.b=NewFPint(0)
+	return F
+}
+
+/* reduce components mod Modulus */
+func (F *FP2) reduce() {
+	F.a.reduce()
+	F.b.reduce()
+}
+
+/* normalise components of w */
+func (F *FP2) norm() {
+	F.a.norm()
+	F.b.norm()
+}
+
+/* test this=0 ? */
+func (F *FP2) iszilch() bool {
+	F.reduce()
+	return (F.a.iszilch() && F.b.iszilch())
+}
+
+func (F *FP2) cmove(g *FP2,d int) {
+	F.a.cmove(g.a,d)
+	F.b.cmove(g.b,d)
+}
+
+/* test this=1 ? */
+func (F *FP2)  isunity() bool {
+	one:=NewFPint(1)
+	return (F.a.equals(one) && F.b.iszilch())
+}
+
+/* test this=x */
+func (F *FP2) equals(x *FP2) bool {
+	return (F.a.equals(x.a) && F.b.equals(x.b))
+}
+
+/* extract a */
+func (F *FP2) getA() *BIG { 
+	return F.a.redc()
+}
+
+/* extract b */
+func (F *FP2) getB() *BIG {
+	return F.b.redc()
+}
+
+/* copy this=x */
+func (F *FP2) copy(x *FP2) {
+	F.a.copy(x.a)
+	F.b.copy(x.b)
+}
+
+/* set this=0 */
+func (F *FP2) zero() {
+	F.a.zero()
+	F.b.zero()
+}
+
+/* set this=1 */
+func (F *FP2) one() {
+	F.a.one()
+	F.b.zero()
+}
+
+/* negate this mod Modulus */
+func (F *FP2) neg() {
+	F.norm()
+	m:=NewFPcopy(F.a)
+	t:= NewFPint(0)
+
+	m.add(F.b)
+	m.neg()
+	m.norm()
+	t.copy(m); t.add(F.b)
+	F.b.copy(m)
+	F.b.add(F.a)
+	F.a.copy(t)
+}
+
+/* set to a-ib */
+func (F *FP2) conj() {
+	F.b.neg()
+}
+
+/* this+=a */
+func (F *FP2) add(x *FP2) {
+	F.a.add(x.a)
+	F.b.add(x.b)
+}
+
+/* this-=a */
+func (F *FP2) sub(x *FP2) {
+	m:=NewFP2copy(x)
+	m.neg()
+	F.add(m)
+}
+
+/* this*=s, where s is an FP */
+func (F *FP2) pmul(s *FP) {
+	F.a.mul(s)
+	F.b.mul(s)
+}
+
+/* this*=i, where i is an int */
+func (F *FP2) imul(c int) {
+	F.a.imul(c)
+	F.b.imul(c)
+}
+
+/* this*=this */
+func (F *FP2) sqr() {
+	F.norm()
+	w1:=NewFPcopy(F.a)
+	w3:=NewFPcopy(F.a)
+	mb:=NewFPcopy(F.b)
+
+	w3.mul(F.b)
+	w1.add(F.b)
+	mb.neg()
+	F.a.add(mb)
+	F.a.mul(w1)
+	F.b.copy(w3); F.b.add(w3)
+
+	F.norm()
+}
+
+/* this*=y */
+func (F *FP2) mul(y *FP2) {
+	F.norm();  /* This is needed here as {a,b} is not normed before additions */
+
+	w1:=NewFPcopy(F.a)
+	w2:=NewFPcopy(F.b)
+	w5:=NewFPcopy(F.a)
+	mw:=NewFPint(0)
+
+	w1.mul(y.a)  // w1=a*y.a  - this norms w1 and y.a, NOT a
+	w2.mul(y.b)  // w2=b*y.b  - this norms w2 and y.b, NOT b
+	w5.add(F.b)    // w5=a+b
+	F.b.copy(y.a); F.b.add(y.b) // b=y.a+y.b
+
+	F.b.mul(w5);
+	mw.copy(w1); mw.add(w2); mw.neg()
+
+	F.b.add(mw); mw.add(w1)
+	F.a.copy(w1);	F.a.add(mw)
+
+	F.norm()
+}
+
+/* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */
+/* returns true if this is QR */
+func (F *FP2) sqrt() bool {
+	if F.iszilch() {return true}
+	w1:=NewFPcopy(F.b)
+	w2:=NewFPcopy(F.a)
+	w1.sqr(); w2.sqr(); w1.add(w2)
+	if w1.jacobi()!=1 { F.zero(); return false }
+	w1=w1.sqrt()
+	w2.copy(F.a); w2.add(w1); w2.div2()
+	if w2.jacobi()!=1 {
+		w2.copy(F.a); w2.sub(w1); w2.div2()
+		if w2.jacobi()!=1 { F.zero(); return false }
+	}
+	w2=w2.sqrt()
+	F.a.copy(w2)
+	w2.add(w2)
+	w2.inverse()
+	F.b.mul(w2)
+	return true
+}
+
+/* output to hex string */
+func (F *FP2) toString() string {
+	return ("["+F.a.toString()+","+F.b.toString()+"]")
+}
+
+/* this=1/this */
+func (F *FP2) inverse() {
+	F.norm()
+	w1:=NewFPcopy(F.a)
+	w2:=NewFPcopy(F.b)
+
+	w1.sqr()
+	w2.sqr()
+	w1.add(w2)
+	w1.inverse()
+	F.a.mul(w1)
+	w1.neg()
+	F.b.mul(w1)
+}
+
+/* this/=2 */
+func (F *FP2) div2() {
+	F.a.div2()
+	F.b.div2()
+}
+
+/* this*=sqrt(-1) */
+func (F *FP2) times_i() {
+	//	a.norm();
+	z:=NewFPcopy(F.a)
+	F.a.copy(F.b); F.a.neg()
+	F.b.copy(z)
+}
+
+/* w*=(1+sqrt(-1)) */
+/* where X*2-(1+sqrt(-1)) is irreducible for FP4, assumes p=3 mod 8 */
+func (F *FP2) mul_ip() {
+	F.norm()
+	t:=NewFP2copy(F)
+	z:=NewFPcopy(F.a)
+	F.a.copy(F.b)
+	F.a.neg()
+	F.b.copy(z)
+	F.add(t)
+	F.norm()
+}
+
+/* w/=(1+sqrt(-1)) */
+func (F *FP2) div_ip() {
+	t:=NewFP2int(0)
+	F.norm()
+	t.a.copy(F.a); t.a.add(F.b)
+	t.b.copy(F.b); t.b.sub(F.a);
+	F.copy(t)
+	F.div2()
+}
diff --git a/version22/go/FP4.go b/version22/go/FP4.go
new file mode 100644
index 0000000..649b88c
--- /dev/null
+++ b/version22/go/FP4.go
@@ -0,0 +1,479 @@
+/*
+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.
+*/
+
+/* Finite Field arithmetic  Fp^4 functions */
+
+/* FP4 elements are of the form a+ib, where i is sqrt(-1+sqrt(-1)) */
+
+package main
+
+//import "fmt"
+
+type FP4 struct {
+	a *FP2
+	b *FP2
+}
+
+/* Constructors */
+func NewFP4int(a int) *FP4 {
+	F:=new(FP4)
+	F.a=NewFP2int(a)
+	F.b=NewFP2int(0)
+	return F
+}
+
+func NewFP4copy(x *FP4) *FP4 {
+	F:=new(FP4)
+	F.a=NewFP2copy(x.a)
+	F.b=NewFP2copy(x.b)
+	return F
+}
+
+func NewFP4fp2s(c *FP2,d *FP2) *FP4 {
+	F:=new(FP4)
+	F.a=NewFP2copy(c)
+	F.b=NewFP2copy(d)
+	return F
+}
+
+func NewFP4fp2(c *FP2) *FP4 {
+	F:=new(FP4)
+	F.a=NewFP2copy(c)
+	F.b=NewFP2int(0)
+	return F
+}
+
+/* reduce all components of this mod Modulus */
+func (F *FP4) reduce() {
+	F.a.reduce()
+	F.b.reduce()
+}
+
+/* normalise all components of this mod Modulus */
+func (F *FP4) norm() {
+	F.a.norm()
+	F.b.norm()
+}
+
+/* test this==0 ? */
+func (F *FP4) iszilch() bool {
+	F.reduce()
+	return F.a.iszilch() && F.b.iszilch()
+}
+
+/* test this==1 ? */
+func (F *FP4) isunity() bool {
+	one:=NewFP2int(1)
+	return F.a.equals(one) && F.b.iszilch()
+}
+
+/* test is w real? That is in a+ib test b is zero */
+func (F *FP4) isreal() bool {
+	return F.b.iszilch()
+}
+/* extract real part a */
+func (F *FP4) real() *FP2 {
+	return F.a
+}
+
+func (F *FP4) geta() *FP2 {
+	return F.a
+}
+/* extract imaginary part b */
+func (F *FP4) getb() *FP2 {
+	return F.b
+}
+/* test this=x? */
+func (F *FP4) equals(x *FP4) bool {
+	return (F.a.equals(x.a) && F.b.equals(x.b))
+}
+
+/* copy this=x */
+func (F *FP4) copy(x *FP4) {
+	F.a.copy(x.a)
+	F.b.copy(x.b)
+}
+/* set this=0 */
+func (F *FP4) zero() {
+	F.a.zero()
+	F.b.zero()
+	}
+/* set this=1 */
+func (F *FP4) one() {
+	F.a.one()
+	F.b.zero()
+}
+
+/* set this=-this */
+func (F *FP4) neg() {
+	m:=NewFP2copy(F.a);
+	t:=NewFP2int(0)
+	m.add(F.b)
+	m.neg()
+	m.norm()
+	t.copy(m); t.add(F.b)
+	F.b.copy(m)
+	F.b.add(F.a)
+	F.a.copy(t)
+}
+
+/* this=conjugate(this) */
+func (F *FP4) conj() {
+	F.b.neg(); F.b.norm()
+}
+
+/* this=-conjugate(this) */
+func (F *FP4) nconj() {
+	F.a.neg(); F.a.norm()
+}
+
+/* this+=x */
+func (F *FP4) add(x *FP4) {
+	F.a.add(x.a)
+	F.b.add(x.b)
+}
+/* this-=x */
+func (F *FP4) sub(x *FP4) {
+	m:=NewFP4copy(x)
+	m.neg()
+	F.add(m)
+}
+
+/* this*=s where s is FP2 */
+func (F *FP4) pmul(s *FP2) {
+	F.a.mul(s)
+	F.b.mul(s)
+}
+/* this*=c where c is int */
+func (F *FP4) imul(c int) {
+	F.a.imul(c)
+	F.b.imul(c)
+}
+
+/* this*=this */	
+func (F *FP4) sqr() {
+	F.norm()
+
+	t1:=NewFP2copy(F.a)
+	t2:=NewFP2copy(F.b)
+	t3:=NewFP2copy(F.a)
+
+	t3.mul(F.b)
+	t1.add(F.b)
+	t2.mul_ip()
+
+	t2.add(F.a)
+	F.a.copy(t1)
+
+	F.a.mul(t2)
+
+	t2.copy(t3)
+	t2.mul_ip()
+	t2.add(t3)
+	t2.neg()
+	F.a.add(t2)
+
+	F.b.copy(t3)
+	F.b.add(t3)
+
+	F.norm()
+}
+
+/* this*=y */
+func (F *FP4) mul(y *FP4) {
+	F.norm()
+
+	t1:=NewFP2copy(F.a)
+	t2:=NewFP2copy(F.b)
+	t3:=NewFP2int(0)
+	t4:=NewFP2copy(F.b)
+
+	t1.mul(y.a)
+	t2.mul(y.b)
+	t3.copy(y.b)
+	t3.add(y.a)
+	t4.add(F.a)
+
+	t4.mul(t3)
+	t4.sub(t1)
+	t4.norm();
+
+	F.b.copy(t4)
+	F.b.sub(t2)
+	t2.mul_ip()
+	F.a.copy(t2)
+	F.a.add(t1)
+
+	F.norm()
+}
+
+/* convert this to hex string */
+func (F *FP4) toString() string {
+	return ("["+F.a.toString()+","+F.b.toString()+"]")
+}
+
+/* this=1/this */
+func (F *FP4) inverse() {
+	F.norm()
+
+	t1:=NewFP2copy(F.a)
+	t2:=NewFP2copy(F.b)
+
+	t1.sqr()
+	t2.sqr()
+	t2.mul_ip()
+	t1.sub(t2)
+	t1.inverse()
+	F.a.mul(t1)
+	t1.neg()
+	F.b.mul(t1)
+}
+
+/* this*=i where i = sqrt(-1+sqrt(-1)) */
+func (F *FP4) times_i() {
+	F.norm()
+	s:=NewFP2copy(F.b)
+	t:=NewFP2copy(F.b)
+	s.times_i()
+	t.add(s)
+	t.norm();
+	F.b.copy(F.a)
+	F.a.copy(t)
+}
+
+/* this=this^p using Frobenius */
+func (F *FP4) frob(f *FP2) {
+	F.a.conj()
+	F.b.conj()
+	F.b.mul(f)
+}
+
+/* this=this^e */
+func (F *FP4) pow(e *BIG) *FP4 {
+	F.norm()
+	e.norm()
+	w:=NewFP4copy(F)
+	z:=NewBIGcopy(e)
+	r:=NewFP4int(1)
+	for true {
+		bt:=z.parity()
+		z.fshr(1)
+		if bt==1 {r.mul(w)}
+		if z.iszilch() {break}
+		w.sqr()
+	}
+	r.reduce()
+	return r
+}
+
+/* XTR xtr_a function */
+func (F *FP4) xtr_A(w *FP4,y *FP4,z *FP4) {
+	r:=NewFP4copy(w)
+	t:=NewFP4copy(w)
+	r.sub(y);
+	r.pmul(F.a)
+	t.add(y)
+	t.pmul(F.b)
+	t.times_i()
+
+	F.copy(r)
+	F.add(t)
+	F.add(z)
+
+	F.norm()
+}
+
+/* XTR xtr_d function */
+func (F *FP4) xtr_D() {
+	w:=NewFP4copy(F)
+	F.sqr(); w.conj()
+	w.add(w)
+	F.sub(w)
+	F.reduce()
+}
+
+/* r=x^n using XTR method on traces of FP12s */
+func (F *FP4) xtr_pow(n *BIG) *FP4 {
+	a:=NewFP4int(3)
+	b:=NewFP4copy(F)
+	c:=NewFP4copy(b)
+	c.xtr_D()
+	t:=NewFP4int(0)
+	r:=NewFP4int(0)
+
+	n.norm()
+	par:=n.parity()
+	v:=NewBIGcopy(n); v.fshr(1)
+	if (par==0) {v.dec(1); v.norm()}
+
+	nb:=v.nbits();
+	for i:=nb-1;i>=0;i-- {
+		if v.bit(i)!=1 {
+			t.copy(b)
+			F.conj()
+			c.conj()
+			b.xtr_A(a,F,c)
+			F.conj()
+			c.copy(t)
+			c.xtr_D()
+			a.xtr_D()
+		} else {
+			t.copy(a); t.conj()
+			a.copy(b)
+			a.xtr_D()
+			b.xtr_A(c,F,t)
+			c.xtr_D()
+		}
+	}
+	if par==0 {
+		r.copy(c)
+	} else {r.copy(b)}
+	r.reduce()
+	return r
+}
+
+/* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */
+func (F *FP4) xtr_pow2(ck *FP4,ckml *FP4,ckm2l *FP4,a *BIG,b *BIG) *FP4 {
+	a.norm(); b.norm()
+	e:=NewBIGcopy(a)
+	d:=NewBIGcopy(b)
+	w:=NewBIGint(0)
+
+	cu:=NewFP4copy(ck)  // can probably be passed in w/o copying
+	cv:=NewFP4copy(F);
+	cumv:=NewFP4copy(ckml)
+	cum2v:=NewFP4copy(ckm2l)
+	r:=NewFP4int(0)
+	t:=NewFP4int(0)
+
+	f2:=0
+	for (d.parity()==0 && e.parity()==0) {
+		d.fshr(1)
+		e.fshr(1)
+		f2++
+	}
+
+	for comp(d,e)!=0 {
+		if comp(d,e)>0 {
+			w.copy(e); w.imul(4); w.norm()
+			if comp(d,w)<=0 {
+				w.copy(d); d.copy(e)
+				e.rsub(w); e.norm()
+
+				t.copy(cv);
+				t.xtr_A(cu,cumv,cum2v)
+				cum2v.copy(cumv);
+				cum2v.conj()
+				cumv.copy(cv)
+				cv.copy(cu)
+				cu.copy(t)
+			} else {
+					if (d.parity()==0) {
+					d.fshr(1)
+					r.copy(cum2v); r.conj()
+					t.copy(cumv)
+					t.xtr_A(cu,cv,r)
+					cum2v.copy(cumv)
+					cum2v.xtr_D()
+					cumv.copy(t)
+					cu.xtr_D()
+				} else {
+					if (e.parity()==1) {
+						d.sub(e); d.norm()
+						d.fshr(1)
+						t.copy(cv)
+						t.xtr_A(cu,cumv,cum2v)
+						cu.xtr_D()
+						cum2v.copy(cv)
+						cum2v.xtr_D()
+						cum2v.conj()
+						cv.copy(t)
+					} else {
+						w.copy(d)
+						d.copy(e); d.fshr(1)
+						e.copy(w)
+						t.copy(cumv)
+						t.xtr_D()
+						cumv.copy(cum2v); cumv.conj()
+						cum2v.copy(t); cum2v.conj()
+						t.copy(cv)
+						t.xtr_D()
+						cv.copy(cu)
+						cu.copy(t)
+					}
+				}
+			}
+		}
+		if comp(d,e)<0 {
+			w.copy(d); w.imul(4); w.norm()
+			if comp(e,w)<=0 {
+				e.sub(d); e.norm()
+				t.copy(cv)
+				t.xtr_A(cu,cumv,cum2v)
+				cum2v.copy(cumv)
+				cumv.copy(cu)
+				cu.copy(t)
+			} else {
+				if (e.parity()==0) {
+					w.copy(d)
+					d.copy(e); d.fshr(1)
+					e.copy(w)
+					t.copy(cumv)
+					t.xtr_D()
+					cumv.copy(cum2v); cumv.conj()
+					cum2v.copy(t); cum2v.conj()
+					t.copy(cv)
+					t.xtr_D()
+					cv.copy(cu)
+					cu.copy(t)
+				} else {
+					if (d.parity()==1) {
+						w.copy(e)
+						e.copy(d)
+						w.sub(d); w.norm()
+						d.copy(w); d.fshr(1)
+						t.copy(cv)
+						t.xtr_A(cu,cumv,cum2v)
+						cumv.conj()
+						cum2v.copy(cu)
+						cum2v.xtr_D()
+						cum2v.conj()
+						cu.copy(cv)
+						cu.xtr_D()
+						cv.copy(t)
+					} else {
+						d.fshr(1)
+						r.copy(cum2v); r.conj()
+						t.copy(cumv)
+						t.xtr_A(cu,cv,r)
+						cum2v.copy(cumv)
+						cum2v.xtr_D()
+						cumv.copy(t)
+						cu.xtr_D()
+					}
+				}
+			}
+		}
+	}
+	r.copy(cv)
+	r.xtr_A(cu,cumv,cum2v)
+	for i:=0;i<f2;i++ {r.xtr_D()}
+	r=r.xtr_pow(d)
+	return r
+}
diff --git a/version22/go/GCM.go b/version22/go/GCM.go
new file mode 100644
index 0000000..fcd7310
--- /dev/null
+++ b/version22/go/GCM.go
@@ -0,0 +1,337 @@
+/*
+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.
+*/
+
+/*
+* Implementation of the AES-GCM Encryption/Authentication
+*
+* Some restrictions..
+* 1. Only for use with AES
+* 2. Returned tag is always 128-bits. Truncate at your own risk.
+* 3. The order of function calls must follow some rules
+*
+* Typical sequence of calls..
+* 1. call GCM_init
+* 2. call GCM_add_header any number of times, as long as length of header is multiple of 16 bytes (block size)
+* 3. call GCM_add_header one last time with any length of header
+* 4. call GCM_add_cipher any number of times, as long as length of cipher/plaintext is multiple of 16 bytes
+* 5. call GCM_add_cipher one last time with any length of cipher/plaintext
+* 6. call GCM_finish to extract the tag.
+*
+* See http://www.mindspring.com/~dmcgrew/gcm-nist-6.pdf
+*/
+
+
+package main
+
+import
+(
+//	"fmt"
+	"strconv"
+)
+
+const gcm_NB int=4
+const GCM_ACCEPTING_HEADER int=0
+const GCM_ACCEPTING_CIPHER int=1
+const GCM_NOT_ACCEPTING_MORE int=2
+const GCM_FINISHED int=3
+const GCM_ENCRYPTING int=0
+const GCM_DECRYPTING int=1
+
+
+type GCM struct {
+	table [128][4]uint32 /* 2k bytes */
+	stateX [16]byte
+	Y_0 [16]byte
+	counter int
+	lenA [2]uint32
+	lenC [2]uint32
+	status int
+	a  *AES
+}
+
+func gcm_pack(b [4]byte) uint32 { /* pack bytes into a 32-bit Word */
+        return ((uint32(b[0])&0xff)<<24)|((uint32(b[1])&0xff)<<16)|((uint32(b[2])&0xff)<<8)|(uint32(b[3])&0xff)
+}
+
+func gcm_unpack(a uint32) [4]byte { /* unpack bytes from a word */
+        var b=[4]byte{byte((a>>24)&0xff),byte((a>>16)&0xff),byte((a>>8)&0xff),byte(a&0xff)}
+	return b;
+}
+
+func (G *GCM) precompute(H []byte) {
+        var b [4]byte
+        j:=0
+        for i:=0;i<gcm_NB;i++ {
+            b[0]=H[j]; b[1]=H[j+1]; b[2]=H[j+2]; b[3]=H[j+3]
+            G.table[0][i]=gcm_pack(b);
+            j+=4
+        }
+        for i:=1;i<128;i++ {
+	    c:=uint32(0)
+            for j:=0;j<gcm_NB;j++ {G.table[i][j]=c|(G.table[i-1][j])>>1; c=G.table[i-1][j]<<31;}
+            if c != 0  {G.table[i][0]^=0xE1000000} /* irreducible polynomial */
+        }
+}
+
+func (G *GCM) gf2mul() { /* gf2m mul - Z=H*X mod 2^128 */
+        var P [4]uint32
+    
+        for i:=0;i<4;i++ {P[i]=0}
+        j:=uint(8); m:=0
+        for i:=0;i<128;i++ {
+	    j--
+            c:=uint32((G.stateX[m]>>j)&1); c=^c+1
+	    for k:=0;k<gcm_NB;k++ {P[k]^=(G.table[i][k]&c)}
+            if j==0 {
+		j=8; m++;
+                if m==16 {break}
+            }
+        }
+        j=0
+        for i:=0;i<gcm_NB;i++ {
+            b:=gcm_unpack(P[i])
+            G.stateX[j]=b[0]; G.stateX[j+1]=b[1]; G.stateX[j+2]=b[2]; G.stateX[j+3]=b[3];
+            j+=4
+        }
+}
+
+func (G *GCM) wrap() { /* Finish off GHASH */
+	var F [4]uint32
+	var L [16]byte
+   
+    /* convert lengths from bytes to bits */
+        F[0]=(G.lenA[0]<<3)|(G.lenA[1]&0xE0000000)>>29
+        F[1]=G.lenA[1]<<3
+        F[2]=(G.lenC[0]<<3)|(G.lenC[1]&0xE0000000)>>29
+        F[3]=G.lenC[1]<<3
+        j:=0
+        for i:=0;i<gcm_NB;i++ {
+            b:=gcm_unpack(F[i]);
+            L[j]=b[0]; L[j+1]=b[1]; L[j+2]=b[2]; L[j+3]=b[3]
+            j+=4
+        }
+        for i:=0;i<16;i++ {G.stateX[i]^=L[i]}
+        G.gf2mul()
+}
+
+func (G *GCM) ghash(plain []byte,len int) bool {
+        if G.status==GCM_ACCEPTING_HEADER {G.status=GCM_ACCEPTING_CIPHER}
+        if G.status != GCM_ACCEPTING_CIPHER {return false}
+        
+        j:=0
+        for (j<len) {
+            for i:=0;i<16 && j<len;i++ {
+		G.stateX[i]^=plain[j]; j++
+                G.lenC[1]++; if G.lenC[1]==0 {G.lenC[0]++}
+            }
+            G.gf2mul();
+        }
+        if len%16 != 0 {G.status=GCM_NOT_ACCEPTING_MORE}
+        return true;
+    }
+
+    /* Initialize GCM mode */
+func (G *GCM) Init(nk int,key []byte,niv int,iv []byte) { /* iv size niv is usually 12 bytes (96 bits). AES key size nk can be 16,24 or 32 bytes */
+	var H [16]byte
+    
+        for i:=0;i<16;i++ {H[i]=0; G.stateX[i]=0}
+        
+	   G.a=new(AES)
+
+        G.a.Init(aes_ECB,nk,key,iv)
+        G.a.ecb_encrypt(H[:])    /* E(K,0) */
+        G.precompute(H[:])
+        
+        G.lenA[0]=0;G.lenC[0]=0;G.lenA[1]=0;G.lenC[1]=0
+        if niv==12 {
+            for i:=0;i<12;i++ {G.a.f[i]=iv[i]}
+            b:=gcm_unpack(uint32(1))
+            G.a.f[12]=b[0]; G.a.f[13]=b[1]; G.a.f[14]=b[2]; G.a.f[15]=b[3];  /* initialise IV */
+            for i:=0;i<16;i++ {G.Y_0[i]=G.a.f[i]}
+        } else {
+            G.status=GCM_ACCEPTING_CIPHER;
+            G.ghash(iv,niv) /* GHASH(H,0,IV) */
+            G.wrap()
+            for i:=0;i<16;i++ {G.a.f[i]=G.stateX[i];G.Y_0[i]=G.a.f[i];G.stateX[i]=0}
+            G.lenA[0]=0;G.lenC[0]=0;G.lenA[1]=0;G.lenC[1]=0
+        }
+        G.status=GCM_ACCEPTING_HEADER
+}
+
+/* Add Header data - included but not encrypted */
+func (G *GCM) Add_header(header []byte,len int) bool { /* Add some header. Won't be encrypted, but will be authenticated. len is length of header */
+        if G.status != GCM_ACCEPTING_HEADER {return false}
+  
+        j:=0
+        for j<len {
+            for i:=0;i<16 && j<len;i++ {
+		G.stateX[i]^=header[j]; j++
+                G.lenA[1]++; if G.lenA[1]==0 {G.lenA[0]++}
+            }
+            G.gf2mul();
+        }
+        if len%16 != 0 {G.status=GCM_ACCEPTING_CIPHER}
+
+        return true;
+    }
+
+/* Add Plaintext - included and encrypted */
+func (G *GCM) Add_plain(plain []byte,len int) []byte {
+	var B [16]byte
+	var b [4]byte
+        
+        cipher:=make([]byte,len)
+        var counter uint32=0
+        if G.status == GCM_ACCEPTING_HEADER {G.status=GCM_ACCEPTING_CIPHER}
+        if G.status != GCM_ACCEPTING_CIPHER {return nil}
+        
+        j:=0
+        for j<len {
+    
+            b[0]=G.a.f[12]; b[1]=G.a.f[13]; b[2]=G.a.f[14]; b[3]=G.a.f[15];
+            counter=gcm_pack(b)
+            counter++
+            b=gcm_unpack(counter)
+            G.a.f[12]=b[0]; G.a.f[13]=b[1]; G.a.f[14]=b[2]; G.a.f[15]=b[3] /* increment counter */
+            for i:=0;i<16;i++ {B[i]=G.a.f[i]}
+            G.a.ecb_encrypt(B[:]);        /* encrypt it  */
+    
+            for i:=0;i<16 && j<len;i++ {
+		cipher[j]=(plain[j]^B[i])
+		G.stateX[i]^=cipher[j]; j++
+                G.lenC[1]++; if G.lenC[1]==0 {G.lenC[0]++}
+            }
+            G.gf2mul()
+        }
+        if len%16 != 0 {G.status=GCM_NOT_ACCEPTING_MORE}
+        return cipher
+}
+
+/* Add Ciphertext - decrypts to plaintext */
+func (G *GCM) Add_cipher(cipher []byte,len int) []byte {
+	var B [16]byte
+	var b [4]byte
+        
+        plain:=make([]byte,len)
+        var counter uint32=0
+        
+        if G.status==GCM_ACCEPTING_HEADER {G.status=GCM_ACCEPTING_CIPHER}
+        if G.status != GCM_ACCEPTING_CIPHER {return nil}
+    
+        j:=0
+        for j<len {
+            b[0]=G.a.f[12]; b[1]=G.a.f[13]; b[2]=G.a.f[14]; b[3]=G.a.f[15]
+            counter=gcm_pack(b);
+            counter++
+            b=gcm_unpack(counter)
+            G.a.f[12]=b[0]; G.a.f[13]=b[1]; G.a.f[14]=b[2]; G.a.f[15]=b[3]; /* increment counter */
+            for i:=0;i<16;i++ {B[i]=G.a.f[i]}
+            G.a.ecb_encrypt(B[:])        /* encrypt it  */
+            for i:=0;i<16 && j<len;i++ {
+		oc:=cipher[j];
+		plain[j]=(cipher[j]^B[i])
+		G.stateX[i]^=oc; j++
+                G.lenC[1]++; if G.lenC[1]==0 {G.lenC[0]++}
+            }
+            G.gf2mul()
+        }
+        if len%16 != 0 {G.status=GCM_NOT_ACCEPTING_MORE}
+        return plain
+}
+
+/* Finish and extract Tag */
+func (G *GCM) Finish(extract bool) [16]byte { /* Finish off GHASH and extract tag (MAC) */
+	var tag [16]byte
+    
+        G.wrap()
+        /* extract tag */
+        if extract {
+            G.a.ecb_encrypt(G.Y_0[:]);        /* E(K,Y0) */
+            for i:=0;i<16;i++ {G.Y_0[i]^=G.stateX[i]}
+            for i:=0;i<16;i++ {tag[i]=G.Y_0[i];G.Y_0[i]=0;G.stateX[i]=0}
+        }
+        G.status=GCM_FINISHED
+        G.a.End()
+        return tag
+}
+
+func hex2bytes(s string) []byte {
+	lgh:=len(s)
+	data:=make([]byte,lgh/2)
+       
+        for i:=0;i<lgh;i+=2 {
+            a,_ := strconv.ParseInt(s[i:i+2],16,32)
+	    data[i/2]=byte(a)
+        }
+        return data
+}
+
+/*
+func main() {
+
+	KT:="feffe9928665731c6d6a8f9467308308"
+	MT:="d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39"
+	HT:="feedfacedeadbeeffeedfacedeadbeefabaddad2"
+
+	NT:="9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b";
+// Tag should be 619cc5aefffe0bfa462af43c1699d050
+
+	g:=new(GCM)
+
+	M:=hex2bytes(MT)
+	H:=hex2bytes(HT)
+	N:=hex2bytes(NT)
+	K:=hex2bytes(KT)
+
+	lenM:=len(M)
+	lenH:=len(H)
+	lenK:=len(K)
+	lenIV:=len(N)
+
+ 	fmt.Printf("Plaintext=\n");
+	for i:=0;i<lenM;i++ {fmt.Printf("%02x",M[i])}
+	fmt.Printf("\n")
+
+	g.Init(lenK,K,lenIV,N)
+	g.Add_header(H,lenH)
+	C:=g.Add_plain(M,lenM)
+	T:=g.Finish(true)
+
+	fmt.Printf("Ciphertext=\n")
+	for i:=0;i<lenM;i++ {fmt.Printf("%02x",C[i])}
+	fmt.Printf("\n")
+        
+	fmt.Printf("Tag=\n")
+	for i:=0;i<16;i++ {fmt.Printf("%02x",T[i])}
+	fmt.Printf("\n")
+
+	g.Init(lenK,K,lenIV,N)
+	g.Add_header(H,lenH)
+	P:=g.Add_cipher(C,lenM)
+	T=g.Finish(true)
+
+ 	fmt.Printf("Plaintext=\n");
+	for i:=0;i<lenM;i++ {fmt.Printf("%02x",P[i])}
+	fmt.Printf("\n")
+
+	fmt.Printf("Tag=\n");
+	for i:=0;i<16;i++ {fmt.Printf("%02x",T[i])}
+	fmt.Printf("\n")
+}
+*/
diff --git a/version22/go/HASH256.go b/version22/go/HASH256.go
new file mode 100644
index 0000000..e6d30c8
--- /dev/null
+++ b/version22/go/HASH256.go
@@ -0,0 +1,192 @@
+/*
+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.
+*/
+
+/*
+ * Implementation of the Secure Hashing Algorithm (SHA-256)
+ *
+ * Generates a 256 bit message digest. It should be impossible to come
+ * come up with two messages that hash to the same value ("collision free").
+ *
+ * For use with byte-oriented messages only. 
+ */
+
+
+package main
+
+//import "fmt"
+
+const hash256_H0 uint32=0x6A09E667
+const hash256_H1 uint32=0xBB67AE85
+const hash256_H2 uint32=0x3C6EF372
+const hash256_H3 uint32=0xA54FF53A
+const hash256_H4 uint32=0x510E527F
+const hash256_H5 uint32=0x9B05688C
+const hash256_H6 uint32=0x1F83D9AB
+const hash256_H7 uint32=0x5BE0CD19
+
+var hash256_K = [...]uint32 {
+	0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,
+	0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,
+	0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,
+	0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,
+	0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
+	0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070,
+	0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,
+	0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2}
+
+
+type HASH256 struct {
+	length [2]uint32
+	h [8]uint32
+	w [64]uint32
+
+}
+
+/* functions */
+func hash256_S(n uint32,x uint32) uint32 {
+	return (((x)>>n) | ((x)<<(32-n)))
+}
+
+func hash256_R(n uint32,x uint32) uint32 {
+	return ((x)>>n)
+}
+
+func hash256_Ch(x,y,z uint32) uint32 {
+	return ((x&y)^(^(x)&z))
+}
+
+func hash256_Maj(x,y,z uint32) uint32 {
+	return ((x&y)^(x&z)^(y&z))
+}
+
+func hash256_Sig0(x uint32) uint32 {
+	return (hash256_S(2,x)^hash256_S(13,x)^hash256_S(22,x))
+}
+
+func hash256_Sig1(x uint32) uint32 {
+	return (hash256_S(6,x)^hash256_S(11,x)^hash256_S(25,x))
+}
+
+func hash256_theta0(x uint32) uint32 {
+	return (hash256_S(7,x)^hash256_S(18,x)^hash256_R(3,x));
+}
+
+func hash256_theta1(x uint32) uint32 {
+		return (hash256_S(17,x)^hash256_S(19,x)^hash256_R(10,x))
+}
+
+func (H *HASH256) transform() { /* basic transformation step */
+	for j:=16;j<64;j++ {
+		H.w[j]=hash256_theta1(H.w[j-2])+H.w[j-7]+hash256_theta0(H.w[j-15])+H.w[j-16]
+	}
+	a:=H.h[0]; b:=H.h[1]; c:=H.h[2]; d:=H.h[3] 
+	e:=H.h[4]; f:=H.h[5]; g:=H.h[6]; hh:=H.h[7]
+	for j:=0;j<64;j++ { /* 64 times - mush it up */
+		t1:=hh+hash256_Sig1(e)+hash256_Ch(e,f,g)+hash256_K[j]+H.w[j]
+		t2:=hash256_Sig0(a)+hash256_Maj(a,b,c)
+		hh=g; g=f; f=e
+		e=d+t1
+		d=c
+		c=b
+		b=a
+		a=t1+t2  
+	}
+	H.h[0]+=a; H.h[1]+=b; H.h[2]+=c; H.h[3]+=d 
+	H.h[4]+=e; H.h[5]+=f; H.h[6]+=g; H.h[7]+=hh 
+} 
+
+/* Initialise Hash function */
+func (H *HASH256) Init() { /* initialise */
+	for i:=0;i<64;i++ {H.w[i]=0}
+	H.length[0]=0; H.length[1]=0
+	H.h[0]=hash256_H0
+	H.h[1]=hash256_H1
+	H.h[2]=hash256_H2
+	H.h[3]=hash256_H3
+	H.h[4]=hash256_H4
+	H.h[5]=hash256_H5
+	H.h[6]=hash256_H6
+	H.h[7]=hash256_H7
+}
+
+func NewHASH256() *HASH256 {
+	H:= new(HASH256)
+	H.Init()
+	return H
+}
+
+/* process a single byte */
+func (H *HASH256) Process(byt byte) { /* process the next message byte */
+	cnt:=(H.length[0]/32)%16;
+    
+	H.w[cnt]<<=8;
+	H.w[cnt]|=uint32(byt&0xFF);
+	H.length[0]+=8;
+	if H.length[0]==0 {H.length[1]++; H.length[0]=0}
+	if (H.length[0]%512)==0 {H.transform()}
+}
+
+/* process an array of bytes */	
+func (H *HASH256) Process_array(b []byte) {
+	for i:=0;i<len(b);i++ {H.Process((b[i]))}
+}
+
+/* process a 32-bit integer */
+func (H *HASH256) Process_num(n int32) {
+	H.Process(byte((n>>24)&0xff));
+	H.Process(byte((n>>16)&0xff));
+	H.Process(byte((n>>8)&0xff));
+	H.Process(byte(n&0xff));
+}
+
+/* Generate 32-byte Hash */
+func (H *HASH256) Hash() []byte { /* pad message and finish - supply digest */
+	var digest [32]byte
+	len0:=H.length[0]
+	len1:=H.length[1]
+	H.Process(0x80);
+	for (H.length[0]%512)!=448 {H.Process(0)}
+	H.w[14]=len1;
+	H.w[15]=len0;    
+	H.transform();
+	for i:=0;i<32;i++ { /* convert to bytes */
+		digest[i]=byte((H.h[i/4]>>uint(8*(3-i%4))) & 0xff);
+	}
+	H.Init()
+	return digest[0:32]
+}
+
+/* test program: should produce digest */
+
+//248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1
+/*
+func main() {
+
+	test := []byte("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")
+	sh:=NewHASH256()
+
+	for i:=0;i<len(test);i++ {
+		sh.Process(test[i])
+	}
+		
+	digest:=sh.Hash()    
+	for i:=0;i<32;i++ {fmt.Printf("%02x",digest[i])}
+
+} */
+
diff --git a/version22/go/HASH384.go b/version22/go/HASH384.go
new file mode 100644
index 0000000..ee3e535
--- /dev/null
+++ b/version22/go/HASH384.go
@@ -0,0 +1,204 @@
+/*
+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.
+*/
+
+/*
+ * Implementation of the Secure Hashing Algorithm (SHA-384)
+ *
+ * Generates a 384 bit message digest. It should be impossible to come
+ * come up with two messages that hash to the same value ("collision free").
+ *
+ * For use with byte-oriented messages only. 
+ */
+
+
+package main
+
+//import "fmt"
+
+const hash384_H0 uint64=0xcbbb9d5dc1059ed8
+const hash384_H1 uint64=0x629a292a367cd507
+const hash384_H2 uint64=0x9159015a3070dd17
+const hash384_H3 uint64=0x152fecd8f70e5939
+const hash384_H4 uint64=0x67332667ffc00b31
+const hash384_H5 uint64=0x8eb44a8768581511
+const hash384_H6 uint64=0xdb0c2e0d64f98fa7
+const hash384_H7 uint64=0x47b5481dbefa4fa4
+
+var hash384_K = [...]uint64 {
+	0x428a2f98d728ae22,0x7137449123ef65cd,0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc,
+	0x3956c25bf348b538,0x59f111f1b605d019,0x923f82a4af194f9b,0xab1c5ed5da6d8118,
+	0xd807aa98a3030242,0x12835b0145706fbe,0x243185be4ee4b28c,0x550c7dc3d5ffb4e2,
+	0x72be5d74f27b896f,0x80deb1fe3b1696b1,0x9bdc06a725c71235,0xc19bf174cf692694,
+	0xe49b69c19ef14ad2,0xefbe4786384f25e3,0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65,
+	0x2de92c6f592b0275,0x4a7484aa6ea6e483,0x5cb0a9dcbd41fbd4,0x76f988da831153b5,
+	0x983e5152ee66dfab,0xa831c66d2db43210,0xb00327c898fb213f,0xbf597fc7beef0ee4,
+	0xc6e00bf33da88fc2,0xd5a79147930aa725,0x06ca6351e003826f,0x142929670a0e6e70,
+	0x27b70a8546d22ffc,0x2e1b21385c26c926,0x4d2c6dfc5ac42aed,0x53380d139d95b3df,
+	0x650a73548baf63de,0x766a0abb3c77b2a8,0x81c2c92e47edaee6,0x92722c851482353b,
+	0xa2bfe8a14cf10364,0xa81a664bbc423001,0xc24b8b70d0f89791,0xc76c51a30654be30,
+	0xd192e819d6ef5218,0xd69906245565a910,0xf40e35855771202a,0x106aa07032bbd1b8,
+	0x19a4c116b8d2d0c8,0x1e376c085141ab53,0x2748774cdf8eeb99,0x34b0bcb5e19b48a8,
+	0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb,0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3,
+	0x748f82ee5defb2fc,0x78a5636f43172f60,0x84c87814a1f0ab72,0x8cc702081a6439ec,
+	0x90befffa23631e28,0xa4506cebde82bde9,0xbef9a3f7b2c67915,0xc67178f2e372532b,
+	0xca273eceea26619c,0xd186b8c721c0c207,0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178,
+	0x06f067aa72176fba,0x0a637dc5a2c898a6,0x113f9804bef90dae,0x1b710b35131c471b,
+	0x28db77f523047d84,0x32caab7b40c72493,0x3c9ebe0a15c9bebc,0x431d67c49c100d4c,
+	0x4cc5d4becb3e42b6,0x597f299cfc657e2a,0x5fcb6fab3ad6faec,0x6c44198c4a475817}
+
+
+type HASH384 struct {
+	length [2]uint64
+	h [8]uint64
+	w [80]uint64
+
+}
+
+/* functions */
+func hash384_S(n uint64,x uint64) uint64 {
+	return (((x)>>n) | ((x)<<(64-n)))
+}
+
+func hash384_R(n uint64,x uint64) uint64 {
+	return ((x)>>n)
+}
+
+func hash384_Ch(x,y,z uint64) uint64 {
+	return ((x&y)^(^(x)&z))
+}
+
+func hash384_Maj(x,y,z uint64) uint64 {
+	return ((x&y)^(x&z)^(y&z))
+}
+
+func hash384_Sig0(x uint64) uint64 {
+	return (hash384_S(28,x)^hash384_S(34,x)^hash384_S(39,x))
+}
+
+func hash384_Sig1(x uint64) uint64 {
+	return (hash384_S(14,x)^hash384_S(18,x)^hash384_S(41,x))
+}
+
+func hash384_theta0(x uint64) uint64 {
+	return (hash384_S(1,x)^hash384_S(8,x)^hash384_R(7,x));
+}
+
+func hash384_theta1(x uint64) uint64 {
+		return (hash384_S(19,x)^hash384_S(61,x)^hash384_R(6,x))
+}
+
+func (H *HASH384) transform() { /* basic transformation step */
+	for j:=16;j<80;j++ {
+		H.w[j]=hash384_theta1(H.w[j-2])+H.w[j-7]+hash384_theta0(H.w[j-15])+H.w[j-16]
+	}
+	a:=H.h[0]; b:=H.h[1]; c:=H.h[2]; d:=H.h[3] 
+	e:=H.h[4]; f:=H.h[5]; g:=H.h[6]; hh:=H.h[7]
+	for j:=0;j<80;j++ { /* 80 times - mush it up */
+		t1:=hh+hash384_Sig1(e)+hash384_Ch(e,f,g)+hash384_K[j]+H.w[j]
+		t2:=hash384_Sig0(a)+hash384_Maj(a,b,c)
+		hh=g; g=f; f=e
+		e=d+t1
+		d=c
+		c=b
+		b=a
+		a=t1+t2  
+	}
+	H.h[0]+=a; H.h[1]+=b; H.h[2]+=c; H.h[3]+=d 
+	H.h[4]+=e; H.h[5]+=f; H.h[6]+=g; H.h[7]+=hh 
+} 
+
+/* Initialise Hash function */
+func (H *HASH384) Init() { /* initialise */
+	for i:=0;i<80;i++ {H.w[i]=0}
+	H.length[0]=0; H.length[1]=0
+	H.h[0]=hash384_H0
+	H.h[1]=hash384_H1
+	H.h[2]=hash384_H2
+	H.h[3]=hash384_H3
+	H.h[4]=hash384_H4
+	H.h[5]=hash384_H5
+	H.h[6]=hash384_H6
+	H.h[7]=hash384_H7
+}
+
+func NewHASH384() *HASH384 {
+	H:= new(HASH384)
+	H.Init()
+	return H
+}
+
+/* process a single byte */
+func (H *HASH384) Process(byt byte) { /* process the next message byte */
+	cnt:=(H.length[0]/64)%16;
+    
+	H.w[cnt]<<=8;
+	H.w[cnt]|=uint64(byt&0xFF);
+	H.length[0]+=8;
+	if H.length[0]==0 {H.length[1]++; H.length[0]=0}
+	if (H.length[0]%1024)==0 {H.transform()}
+}
+
+/* process an array of bytes */	
+func (H *HASH384) Process_array(b []byte) {
+	for i:=0;i<len(b);i++ {H.Process((b[i]))}
+}
+
+/* process a 32-bit integer */
+func (H *HASH384) Process_num(n int32) {
+	H.Process(byte((n>>24)&0xff));
+	H.Process(byte((n>>16)&0xff));
+	H.Process(byte((n>>8)&0xff));
+	H.Process(byte(n&0xff));
+}
+
+/* Generate 32-byte Hash */
+func (H *HASH384) Hash() []byte { /* pad message and finish - supply digest */
+	var digest [48]byte
+	len0:=H.length[0]
+	len1:=H.length[1]
+	H.Process(0x80);
+	for (H.length[0]%1024)!=896 {H.Process(0)}
+	H.w[14]=len1;
+	H.w[15]=len0;    
+	H.transform();
+	for i:=0;i<48;i++ { /* convert to bytes */
+		digest[i]=byte((H.h[i/8]>>uint(8*(7-i%8))) & 0xff);
+	}
+	H.Init()
+	return digest[0:48]
+}
+
+/* test program: should produce digest */
+
+//09330c33f71147e8 3d192fc782cd1b47 53111b173b3b05d2 2fa08086e3b0f712 fcc7c71a557e2db9 66c3e9fa91746039
+/*
+func main() {
+
+	test := []byte("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu")
+	sh:=NewHASH384()
+
+	for i:=0;i<len(test);i++ {
+		sh.Process(test[i])
+	}
+		
+	digest:=sh.Hash()    
+	for i:=0;i<48;i++ {fmt.Printf("%02x",digest[i])}
+
+}
+*/
diff --git a/version22/go/HASH512.go b/version22/go/HASH512.go
new file mode 100644
index 0000000..be274f3
--- /dev/null
+++ b/version22/go/HASH512.go
@@ -0,0 +1,204 @@
+/*
+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.
+*/
+
+/*
+ * Implementation of the Secure Hashing Algorithm (SHA-384)
+ *
+ * Generates a 384 bit message digest. It should be impossible to come
+ * come up with two messages that hash to the same value ("collision free").
+ *
+ * For use with byte-oriented messages only. 
+ */
+
+
+package main
+
+//import "fmt"
+
+const hash512_H0 uint64=0x6a09e667f3bcc908
+const hash512_H1 uint64=0xbb67ae8584caa73b
+const hash512_H2 uint64=0x3c6ef372fe94f82b
+const hash512_H3 uint64=0xa54ff53a5f1d36f1
+const hash512_H4 uint64=0x510e527fade682d1
+const hash512_H5 uint64=0x9b05688c2b3e6c1f
+const hash512_H6 uint64=0x1f83d9abfb41bd6b
+const hash512_H7 uint64=0x5be0cd19137e2179
+
+var hash512_K = [...]uint64 {
+	0x428a2f98d728ae22,0x7137449123ef65cd,0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc,
+	0x3956c25bf348b538,0x59f111f1b605d019,0x923f82a4af194f9b,0xab1c5ed5da6d8118,
+	0xd807aa98a3030242,0x12835b0145706fbe,0x243185be4ee4b28c,0x550c7dc3d5ffb4e2,
+	0x72be5d74f27b896f,0x80deb1fe3b1696b1,0x9bdc06a725c71235,0xc19bf174cf692694,
+	0xe49b69c19ef14ad2,0xefbe4786384f25e3,0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65,
+	0x2de92c6f592b0275,0x4a7484aa6ea6e483,0x5cb0a9dcbd41fbd4,0x76f988da831153b5,
+	0x983e5152ee66dfab,0xa831c66d2db43210,0xb00327c898fb213f,0xbf597fc7beef0ee4,
+	0xc6e00bf33da88fc2,0xd5a79147930aa725,0x06ca6351e003826f,0x142929670a0e6e70,
+	0x27b70a8546d22ffc,0x2e1b21385c26c926,0x4d2c6dfc5ac42aed,0x53380d139d95b3df,
+	0x650a73548baf63de,0x766a0abb3c77b2a8,0x81c2c92e47edaee6,0x92722c851482353b,
+	0xa2bfe8a14cf10364,0xa81a664bbc423001,0xc24b8b70d0f89791,0xc76c51a30654be30,
+	0xd192e819d6ef5218,0xd69906245565a910,0xf40e35855771202a,0x106aa07032bbd1b8,
+	0x19a4c116b8d2d0c8,0x1e376c085141ab53,0x2748774cdf8eeb99,0x34b0bcb5e19b48a8,
+	0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb,0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3,
+	0x748f82ee5defb2fc,0x78a5636f43172f60,0x84c87814a1f0ab72,0x8cc702081a6439ec,
+	0x90befffa23631e28,0xa4506cebde82bde9,0xbef9a3f7b2c67915,0xc67178f2e372532b,
+	0xca273eceea26619c,0xd186b8c721c0c207,0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178,
+	0x06f067aa72176fba,0x0a637dc5a2c898a6,0x113f9804bef90dae,0x1b710b35131c471b,
+	0x28db77f523047d84,0x32caab7b40c72493,0x3c9ebe0a15c9bebc,0x431d67c49c100d4c,
+	0x4cc5d4becb3e42b6,0x597f299cfc657e2a,0x5fcb6fab3ad6faec,0x6c44198c4a475817}
+
+
+type HASH512 struct {
+	length [2]uint64
+	h [8]uint64
+	w [80]uint64
+
+}
+
+/* functions */
+func hash512_S(n uint64,x uint64) uint64 {
+	return (((x)>>n) | ((x)<<(64-n)))
+}
+
+func hash512_R(n uint64,x uint64) uint64 {
+	return ((x)>>n)
+}
+
+func hash512_Ch(x,y,z uint64) uint64 {
+	return ((x&y)^(^(x)&z))
+}
+
+func hash512_Maj(x,y,z uint64) uint64 {
+	return ((x&y)^(x&z)^(y&z))
+}
+
+func hash512_Sig0(x uint64) uint64 {
+	return (hash512_S(28,x)^hash512_S(34,x)^hash512_S(39,x))
+}
+
+func hash512_Sig1(x uint64) uint64 {
+	return (hash512_S(14,x)^hash512_S(18,x)^hash512_S(41,x))
+}
+
+func hash512_theta0(x uint64) uint64 {
+	return (hash512_S(1,x)^hash512_S(8,x)^hash512_R(7,x));
+}
+
+func hash512_theta1(x uint64) uint64 {
+		return (hash512_S(19,x)^hash512_S(61,x)^hash512_R(6,x))
+}
+
+func (H *HASH512) transform() { /* basic transformation step */
+	for j:=16;j<80;j++ {
+		H.w[j]=hash512_theta1(H.w[j-2])+H.w[j-7]+hash512_theta0(H.w[j-15])+H.w[j-16]
+	}
+	a:=H.h[0]; b:=H.h[1]; c:=H.h[2]; d:=H.h[3] 
+	e:=H.h[4]; f:=H.h[5]; g:=H.h[6]; hh:=H.h[7]
+	for j:=0;j<80;j++ { /* 80 times - mush it up */
+		t1:=hh+hash512_Sig1(e)+hash512_Ch(e,f,g)+hash512_K[j]+H.w[j]
+		t2:=hash512_Sig0(a)+hash512_Maj(a,b,c)
+		hh=g; g=f; f=e
+		e=d+t1
+		d=c
+		c=b
+		b=a
+		a=t1+t2  
+	}
+	H.h[0]+=a; H.h[1]+=b; H.h[2]+=c; H.h[3]+=d 
+	H.h[4]+=e; H.h[5]+=f; H.h[6]+=g; H.h[7]+=hh 
+} 
+
+/* Initialise Hash function */
+func (H *HASH512) Init() { /* initialise */
+	for i:=0;i<80;i++ {H.w[i]=0}
+	H.length[0]=0; H.length[1]=0
+	H.h[0]=hash512_H0
+	H.h[1]=hash512_H1
+	H.h[2]=hash512_H2
+	H.h[3]=hash512_H3
+	H.h[4]=hash512_H4
+	H.h[5]=hash512_H5
+	H.h[6]=hash512_H6
+	H.h[7]=hash512_H7
+}
+
+func NewHASH512() *HASH512 {
+	H:= new(HASH512)
+	H.Init()
+	return H
+}
+
+/* process a single byte */
+func (H *HASH512) Process(byt byte) { /* process the next message byte */
+	cnt:=(H.length[0]/64)%16;
+    
+	H.w[cnt]<<=8;
+	H.w[cnt]|=uint64(byt&0xFF);
+	H.length[0]+=8;
+	if H.length[0]==0 {H.length[1]++; H.length[0]=0}
+	if (H.length[0]%1024)==0 {H.transform()}
+}
+
+/* process an array of bytes */	
+func (H *HASH512) Process_array(b []byte) {
+	for i:=0;i<len(b);i++ {H.Process((b[i]))}
+}
+
+/* process a 32-bit integer */
+func (H *HASH512) Process_num(n int32) {
+	H.Process(byte((n>>24)&0xff));
+	H.Process(byte((n>>16)&0xff));
+	H.Process(byte((n>>8)&0xff));
+	H.Process(byte(n&0xff));
+}
+
+/* Generate 32-byte Hash */
+func (H *HASH512) Hash() []byte { /* pad message and finish - supply digest */
+	var digest [64]byte
+	len0:=H.length[0]
+	len1:=H.length[1]
+	H.Process(0x80);
+	for (H.length[0]%1024)!=896 {H.Process(0)}
+	H.w[14]=len1;
+	H.w[15]=len0;    
+	H.transform();
+	for i:=0;i<64;i++ { /* convert to bytes */
+		digest[i]=byte((H.h[i/8]>>uint(8*(7-i%8))) & 0xff);
+	}
+	H.Init()
+	return digest[0:64]
+}
+
+/* test program: should produce digest */
+
+//8e959b75dae313da 8cf4f72814fc143f 8f7779c6eb9f7fa1 7299aeadb6889018 501d289e4900f7e4 331b99dec4b5433a c7d329eeb6dd2654 5e96e55b874be909
+/*
+func main() {
+
+	test := []byte("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu")
+	sh:=NewHASH512()
+
+	for i:=0;i<len(test);i++ {
+		sh.Process(test[i])
+	}
+		
+	digest:=sh.Hash()    
+	for i:=0;i<64;i++ {fmt.Printf("%02x",digest[i])}
+
+}
+*/
diff --git a/version22/go/MPIN.go b/version22/go/MPIN.go
new file mode 100644
index 0000000..43b5f32
--- /dev/null
+++ b/version22/go/MPIN.go
@@ -0,0 +1,769 @@
+/*
+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.
+*/
+
+/* MPIN API Functions */
+
+package main
+
+import "time"
+
+//import "fmt"
+
+/* Configure mode of operation */
+
+const PERMITS bool=true
+const PINERROR bool=true
+const FULL bool=true
+const SINGLE_PASS bool=false
+
+
+const MPIN_EFS int=int(MODBYTES)
+const MPIN_EGS int=int(MODBYTES)
+const MPIN_PAS int=16
+const MPIN_BAD_PARAMS int=-11
+const MPIN_INVALID_POINT int=-14
+const MPIN_WRONG_ORDER int=-18
+const MPIN_BAD_PIN int=-19
+const MPIN_SHA256 int=32
+const MPIN_SHA384 int=48
+const MPIN_SHA512 int=64
+
+/* Configure your PIN here */
+
+const MPIN_MAXPIN int32=10000  /* PIN less than this */
+const MPIN_PBLEN int32=14      /* Number of bits in PIN */
+const MPIN_TS int=10         /* 10 for 4 digit PIN, 14 for 6-digit PIN - 2^TS/TS approx = sqrt(MAXPIN) */
+const MPIN_TRAP int=200      /* 200 for 4 digit PIN, 2000 for 6-digit PIN  - approx 2*sqrt(MAXPIN) */
+
+const MPIN_HASH_TYPE int=MPIN_SHA256
+
+func mpin_hash(sha int,c *FP4,U *ECP) []byte {
+	var w [MPIN_EFS]byte
+	var t [6*MPIN_EFS]byte
+	var h []byte
+
+	c.geta().getA().toBytes(w[:]); for i:=0;i<MPIN_EFS;i++ {t[i]=w[i]}
+	c.geta().getB().toBytes(w[:]); for i:=MPIN_EFS;i<2*MPIN_EFS;i++ {t[i]=w[i-MPIN_EFS]}
+	c.getb().getA().toBytes(w[:]); for i:=2*MPIN_EFS;i<3*MPIN_EFS;i++ {t[i]=w[i-2*MPIN_EFS]}
+	c.getb().getB().toBytes(w[:]); for i:=3*MPIN_EFS;i<4*MPIN_EFS;i++ {t[i]=w[i-3*MPIN_EFS]}
+
+	U.getX().toBytes(w[:]); for i:=4*MPIN_EFS;i<5*MPIN_EFS;i++ {t[i]=w[i-4*MPIN_EFS]}
+	U.getY().toBytes(w[:]); for i:=5*MPIN_EFS;i<6*MPIN_EFS;i++ {t[i]=w[i-5*MPIN_EFS]}
+
+	if sha==MPIN_SHA256 {
+		H:=NewHASH256()
+		H.Process_array(t[:])
+		h=H.Hash()
+	}
+	if sha==MPIN_SHA384 {
+		H:=NewHASH384()
+		H.Process_array(t[:])
+		h=H.Hash()
+	}
+	if sha==MPIN_SHA512 {
+		H:=NewHASH512()
+		H.Process_array(t[:])
+		h=H.Hash()
+	}
+	if h==nil {return nil}
+	R:=make([]byte,MPIN_PAS)
+	for i:=0;i<MPIN_PAS;i++ {R[i]=h[i]}
+	return R
+}
+
+/* Hash number (optional) and string to coordinate on curve */
+
+func mhashit(sha int,n int32,ID []byte) []byte {
+	var R []byte
+	if sha==MPIN_SHA256 {
+		H:=NewHASH256()
+		if n!=0 {H.Process_num(n)}
+		H.Process_array(ID)
+		R=H.Hash()
+	}
+	if sha==MPIN_SHA384 {
+		H:=NewHASH384()
+		if n!=0 {H.Process_num(n)}
+		H.Process_array(ID)
+		R=H.Hash()
+	}
+	if sha==MPIN_SHA512 {
+		H:=NewHASH512()
+		if n!=0 {H.Process_num(n)}
+		H.Process_array(ID)
+		R=H.Hash()
+	}
+	if R==nil {return nil}
+	const RM int=int(MODBYTES)
+	var W [RM]byte
+	if sha>RM {
+		for i:=0;i<RM;i++ {W[i]=R[i]}
+	} else {
+		for i:=0;i<sha;i++ {W[i]=R[i]}	
+		for i:=sha;i<RM;i++ {W[i]=0}
+	}
+
+	return W[:]
+}
+
+func mapit(h []byte) *ECP {
+	q:=NewBIGints(Modulus)
+	x:=fromBytes(h[:])
+	x.mod(q)
+	var P *ECP
+	for true {
+		P=NewECPbigint(x,0)
+		if !P.is_infinity() {break}
+		x.inc(1); x.norm()
+	}
+	if CURVE_PAIRING_TYPE!=BN_CURVE {
+		c:=NewBIGints(CURVE_Cof)
+		P=P.mul(c)
+	}	
+	return P
+}
+
+/* needed for SOK */
+func mapit2(h []byte) *ECP2 {
+	q:=NewBIGints(Modulus)
+	x:=fromBytes(h[:])
+	one:=NewBIGint(1)
+	var X *FP2
+	var Q,T,K *ECP2
+	x.mod(q)
+	for true {
+		X=NewFP2bigs(one,x)
+		Q=NewECP2fp2(X)
+		if !Q.is_infinity() {break}
+		x.inc(1); x.norm()
+	}
+/* Fast Hashing to G2 - Fuentes-Castaneda, Knapp and Rodriguez-Henriquez */
+	Fra:=NewBIGints(CURVE_Fra)
+	Frb:=NewBIGints(CURVE_Frb)
+	X=NewFP2bigs(Fra,Frb)
+	x=NewBIGints(CURVE_Bnx)
+
+	T=NewECP2(); T.copy(Q)
+	T.mul(x); T.neg()
+	K=NewECP2(); K.copy(T)
+	K.dbl(); K.add(T); K.affine()
+
+	K.frob(X)
+	Q.frob(X); Q.frob(X); Q.frob(X)
+	Q.add(T); Q.add(K)
+	T.frob(X); T.frob(X)
+	Q.add(T)
+	Q.affine()
+	return Q
+}
+
+/* return time in slots since epoch */
+func MPIN_today() int {
+	now:=time.Now()
+	return int(now.Unix())/(60*1440)
+}
+
+/* these next two functions help to implement elligator squared - http://eprint.iacr.org/2014/043 */
+/* maps a random u to a point on the curve */
+func emap(u *BIG,cb int) *ECP {
+	var P *ECP
+	x:=NewBIGcopy(u)
+	p:=NewBIGints(Modulus)
+	x.mod(p)
+	for true {
+		P=NewECPbigint(x,cb)
+		if !P.is_infinity() {break}
+		x.inc(1);  x.norm()
+	}
+	return P
+}
+
+/* returns u derived from P. Random value in range 1 to return value should then be added to u */
+func unmap(u* BIG,P *ECP) int {
+	s:=P.getS()
+	var R *ECP
+	r:=0
+	x:=P.getX()
+	u.copy(x)
+	for true {
+		u.dec(1); u.norm()
+		r++
+		R=NewECPbigint(u,s)
+		if !R.is_infinity() {break}
+	}
+	return r
+}
+
+func MPIN_HASH_ID(sha int,ID []byte) []byte {
+	return mhashit(sha,0,ID)
+}
+
+/* these next two functions implement elligator squared - http://eprint.iacr.org/2014/043 */
+/* Elliptic curve point E in format (0x04,x,y} is converted to form {0x0-,u,v} */
+/* Note that u and v are indistinguisible from random strings */
+func MPIN_ENCODING(rng *RAND,E []byte) int {
+	var T [MPIN_EFS]byte
+
+	for i:=0;i<MPIN_EFS;i++ {T[i]=E[i+1]}
+	u:=fromBytes(T[:])
+	for i:=0;i<MPIN_EFS;i++ {T[i]=E[i+MPIN_EFS+1]}
+	v:=fromBytes(T[:])
+		
+	P:=NewECPbigs(u,v)
+	if P.is_infinity() {return MPIN_INVALID_POINT}
+
+	p:=NewBIGints(Modulus)
+	u=randomnum(p,rng)
+
+	su:=int(rng.GetByte()); /*if (su<0) su=-su;*/ su%=2
+		
+	W:=emap(u,su)
+	P.sub(W)
+	sv:=P.getS()
+	rn:=unmap(v,P)
+	m:=int(rng.GetByte()); /*if (m<0) m=-m;*/ m%=rn
+	v.inc(m+1)
+	E[0]=byte(su+2*sv)
+	u.toBytes(T[:])
+	for i:=0;i<MPIN_EFS;i++ {E[i+1]=T[i]}
+	v.toBytes(T[:])
+	for i:=0;i<MPIN_EFS;i++ {E[i+MPIN_EFS+1]=T[i]}		
+		
+	return 0
+}
+
+func MPIN_DECODING(D []byte) int {
+	var T [MPIN_EFS]byte
+
+	if (D[0]&0x04)!=0 {return MPIN_INVALID_POINT}
+
+	for i:=0;i<MPIN_EFS;i++ {T[i]=D[i+1]}
+	u:=fromBytes(T[:])
+	for i:=0;i<MPIN_EFS;i++ {T[i]=D[i+MPIN_EFS+1]}
+	v:=fromBytes(T[:])
+
+	su:=int(D[0]&1)
+	sv:=int((D[0]>>1)&1)
+	W:=emap(u,su)
+	P:=emap(v,sv)
+	P.add(W)
+	u=P.getX()
+	v=P.getY()
+	D[0]=0x04
+	u.toBytes(T[:])
+	for i:=0;i<MPIN_EFS;i++ {D[i+1]=T[i]}
+	v.toBytes(T[:])
+	for i:=0;i<MPIN_EFS;i++ {D[i+MPIN_EFS+1]=T[i]}		
+		
+	return 0
+}
+
+/* R=R1+R2 in group G1 */
+func MPIN_RECOMBINE_G1(R1 []byte,R2 []byte,R []byte) int {
+	P:=ECP_fromBytes(R1)
+	Q:=ECP_fromBytes(R2)
+
+	if (P.is_infinity() || Q.is_infinity()) {return MPIN_INVALID_POINT}
+
+	P.add(Q)
+
+	P.toBytes(R[:])
+	return 0
+}
+
+/* W=W1+W2 in group G2 */
+func MPIN_RECOMBINE_G2(W1 []byte,W2 []byte,W []byte) int {
+	P:=ECP2_fromBytes(W1)
+	Q:=ECP2_fromBytes(W2)
+
+	if (P.is_infinity() || Q.is_infinity()) {return MPIN_INVALID_POINT}
+
+	P.add(Q)
+	
+	P.toBytes(W)
+	return 0
+}
+	
+/* create random secret S */
+func MPIN_RANDOM_GENERATE(rng *RAND,S []byte) int {
+	r:=NewBIGints(CURVE_Order);
+	s:=randomnum(r,rng)
+	if AES_S>0 {
+		s.mod2m(2*AES_S)
+	}		
+	s.toBytes(S)
+	return 0
+}
+
+/* Extract PIN from TOKEN for identity CID */
+func MPIN_EXTRACT_PIN(sha int,CID []byte,pin int,TOKEN []byte) int {
+	P:=ECP_fromBytes(TOKEN)
+	if P.is_infinity() {return MPIN_INVALID_POINT}
+	h:=mhashit(sha,0,CID)
+	R:=mapit(h)
+
+	R=R.pinmul(int32(pin)%MPIN_MAXPIN,MPIN_PBLEN)
+	P.sub(R)
+
+	P.toBytes(TOKEN)
+
+	return 0
+}
+
+/* Implement step 2 on client side of MPin protocol */
+func MPIN_CLIENT_2(X []byte,Y []byte,SEC []byte) int {
+	r:=NewBIGints(CURVE_Order)
+	P:=ECP_fromBytes(SEC)
+	if P.is_infinity() {return MPIN_INVALID_POINT}
+
+	px:=fromBytes(X)
+	py:=fromBytes(Y)
+	px.add(py)
+	px.mod(r)
+	//px.rsub(r)
+
+	P=G1mul(P,px)
+	P.neg()
+	P.toBytes(SEC)
+	//G1mul(P,px).toBytes(SEC)
+	return 0
+}
+
+/* Implement step 1 on client side of MPin protocol */
+func MPIN_CLIENT_1(sha int,date int,CLIENT_ID []byte,rng *RAND,X []byte,pin int,TOKEN []byte,SEC []byte,xID []byte,xCID []byte,PERMIT []byte) int {
+	r:=NewBIGints(CURVE_Order)
+		
+	var x *BIG
+	if (rng!=nil) {
+		x=randomnum(r,rng)
+		if AES_S>0 {
+			x.mod2m(2*AES_S)
+		}
+		x.toBytes(X)
+	} else {
+		x=fromBytes(X)
+	}
+
+	h:=mhashit(sha,0,CLIENT_ID)
+	P:=mapit(h)
+	
+	T:=ECP_fromBytes(TOKEN)
+	if T.is_infinity() {return MPIN_INVALID_POINT}
+
+	W:=P.pinmul(int32(pin)%MPIN_MAXPIN,MPIN_PBLEN)
+	T.add(W)
+	if date!=0 {
+		W=ECP_fromBytes(PERMIT)
+		if W.is_infinity() {return MPIN_INVALID_POINT}
+		T.add(W)
+		h=mhashit(sha,int32(date),h)
+		W=mapit(h)
+		if xID!=nil {
+			P=G1mul(P,x)
+			P.toBytes(xID)
+			W=G1mul(W,x)
+			P.add(W)
+		} else {
+			P.add(W)
+			P=G1mul(P,x)
+		}
+		if xCID!=nil {P.toBytes(xCID)}
+	} else {
+		if xID!=nil {
+			P=G1mul(P,x)
+			P.toBytes(xID)
+		}
+	}
+
+
+	T.toBytes(SEC)
+	return 0
+}
+
+/* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */
+func MPIN_GET_SERVER_SECRET(S []byte,SST []byte) int {
+	Q:=NewECP2fp2s(NewFP2bigs(NewBIGints(CURVE_Pxa),NewBIGints(CURVE_Pxb)),NewFP2bigs(NewBIGints(CURVE_Pya),NewBIGints(CURVE_Pyb)))
+
+	s:=fromBytes(S)
+	Q=G2mul(Q,s)
+	Q.toBytes(SST)
+	return 0
+}
+
+/*
+ W=x*H(G);
+ if RNG == NULL then X is passed in 
+ if RNG != NULL the X is passed out 
+ if type=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve
+*/
+func MPIN_GET_G1_MULTIPLE(rng *RAND,typ int,X []byte,G []byte,W []byte) int {
+	var x *BIG
+	r:=NewBIGints(CURVE_Order)
+	if rng!=nil {
+		x=randomnum(r,rng)
+		if AES_S>0 {
+			x.mod2m(2*AES_S)
+		}
+		x.toBytes(X)
+	} else {
+		x=fromBytes(X)
+	}
+	var P *ECP
+	if typ==0 {
+		P=ECP_fromBytes(G)
+		if P.is_infinity() {return MPIN_INVALID_POINT}
+	} else {P=mapit(G)}
+
+	G1mul(P,x).toBytes(W)
+	return 0
+}
+
+/* Client secret CST=S*H(CID) where CID is client ID and S is master secret */
+/* CID is hashed externally */
+func MPIN_GET_CLIENT_SECRET(S []byte,CID []byte,CST []byte) int {
+	return MPIN_GET_G1_MULTIPLE(nil,1,S,CID,CST)
+}
+
+/* Time Permit CTT=S*(date|H(CID)) where S is master secret */
+func MPIN_GET_CLIENT_PERMIT(sha,date int,S []byte,CID []byte,CTT []byte) int {
+	h:=mhashit(sha,int32(date),CID)
+	P:=mapit(h)
+
+	s:=fromBytes(S)
+	G1mul(P,s).toBytes(CTT)
+	return 0
+}
+
+/* Outputs H(CID) and H(T|H(CID)) for time permits. If no time permits set HID=HTID */
+func MPIN_SERVER_1(sha int,date int,CID []byte,HID []byte,HTID []byte) {
+	h:=mhashit(sha,0,CID)
+	P:=mapit(h)
+	
+	P.toBytes(HID);
+	if date!=0 {
+	//	if HID!=nil {P.toBytes(HID)}
+		h=mhashit(sha,int32(date),h)
+		R:=mapit(h)
+		P.add(R)
+		P.toBytes(HTID)
+	} //else {P.toBytes(HID)}
+}
+
+/* Implement step 2 of MPin protocol on server side */
+func MPIN_SERVER_2(date int,HID []byte,HTID []byte,Y []byte,SST []byte,xID []byte,xCID []byte,mSEC []byte,E []byte,F []byte) int {
+//	q:=NewBIGints(Modulus)
+	Q:=NewECP2fp2s(NewFP2bigs(NewBIGints(CURVE_Pxa),NewBIGints(CURVE_Pxb)),NewFP2bigs(NewBIGints(CURVE_Pya),NewBIGints(CURVE_Pyb)))
+
+	sQ:=ECP2_fromBytes(SST)
+	if sQ.is_infinity() {return MPIN_INVALID_POINT}	
+
+	var R *ECP
+	if date!=0 {
+		R=ECP_fromBytes(xCID)
+	} else {
+		if xID==nil {return MPIN_BAD_PARAMS}
+		R=ECP_fromBytes(xID)
+	}
+	if R.is_infinity() {return MPIN_INVALID_POINT}
+
+	y:=fromBytes(Y)
+	var P *ECP
+	if date!=0 {
+		P=ECP_fromBytes(HTID)
+	} else {
+		if HID==nil {return MPIN_BAD_PARAMS}
+		P=ECP_fromBytes(HID)
+	}
+	
+	if P.is_infinity() {return MPIN_INVALID_POINT}
+
+	P=G1mul(P,y)
+	P.add(R)
+	R=ECP_fromBytes(mSEC)
+	if R.is_infinity() {return MPIN_INVALID_POINT}
+
+	var g *FP12
+//		FP12 g1=new FP12(0);
+
+	g=ate2(Q,R,sQ,P)
+	g=fexp(g)
+
+	if !g.isunity() {
+		if (HID!=nil && xID!=nil && E!=nil && F!=nil) {
+			g.toBytes(E)
+			if date!=0 {
+				P=ECP_fromBytes(HID)
+				if P.is_infinity() {return MPIN_INVALID_POINT}
+				R=ECP_fromBytes(xID)
+				if R.is_infinity() {return MPIN_INVALID_POINT}
+
+				P=G1mul(P,y)
+				P.add(R)
+			}
+			g=ate(Q,P)
+			g=fexp(g)
+			g.toBytes(F)
+		}
+		return MPIN_BAD_PIN
+	}
+
+	return 0
+}
+
+/* Pollards kangaroos used to return PIN error */
+func MPIN_KANGAROO(E []byte,F []byte) int {
+	ge:=FP12_fromBytes(E)
+	gf:=FP12_fromBytes(F)
+	var distance [MPIN_TS]int
+	t:=NewFP12copy(gf)
+
+	var table []*FP12
+	var i int
+	s:=1
+	for m:=0;m<MPIN_TS;m++ {
+		distance[m]=s
+		table=append(table,NewFP12copy(t))
+		s*=2
+		t.usqr()
+	}
+	t.one()
+	dn:=0
+	for j:=0;j<MPIN_TRAP;j++ {
+		i=t.geta().geta().getA().lastbits(20)%MPIN_TS
+		t.mul(table[i])
+		dn+=distance[i]
+	}
+	gf.copy(t); gf.conj()
+	steps:=0; dm:=0
+	res:=0
+	for dm-dn<int(MPIN_MAXPIN) {
+		steps++
+		if steps>4*MPIN_TRAP {break}
+		i=ge.geta().geta().getA().lastbits(20)%MPIN_TS;
+		ge.mul(table[i])
+		dm+=distance[i]
+		if ge.equals(t) {
+			res=dm-dn
+			break;
+		}
+		if ge.equals(gf) {
+			res=dn-dm
+			break
+		}
+
+	}
+	if (steps>4*MPIN_TRAP || dm-dn>=int(MPIN_MAXPIN)) {res=0 }    // Trap Failed  - probable invalid token
+	return int(res)
+}
+
+/* Functions to support M-Pin Full */
+
+func MPIN_PRECOMPUTE(TOKEN []byte,CID []byte,G1 []byte,G2 []byte) int {
+	var P,T *ECP
+	var g *FP12
+
+	T=ECP_fromBytes(TOKEN)
+	if T.is_infinity() {return MPIN_INVALID_POINT} 
+
+	P=mapit(CID)
+
+	Q:=NewECP2fp2s(NewFP2bigs(NewBIGints(CURVE_Pxa),NewBIGints(CURVE_Pxb)),NewFP2bigs(NewBIGints(CURVE_Pya),NewBIGints(CURVE_Pyb)))
+
+	g=ate(Q,T)
+	g=fexp(g)
+	g.toBytes(G1)
+
+	g=ate(Q,P)
+	g=fexp(g)
+	g.toBytes(G2)
+
+	return 0
+}
+
+/* Hash the M-Pin transcript - new */
+
+func MPIN_HASH_ALL(sha int,HID []byte,xID []byte,xCID []byte,SEC []byte,Y []byte,R []byte,W []byte) []byte {
+	tlen:=0
+	var T [10*int(MODBYTES)+4]byte
+
+	for i:=0;i<len(HID);i++ {T[i]=HID[i]}
+	tlen+=len(HID)
+	if xCID!=nil {
+		for i:=0;i<len(xCID);i++ {T[i+tlen]=xCID[i]}
+		tlen+=len(xCID)
+	} else {
+		for i:=0;i<len(xID);i++ {T[i+tlen]=xID[i]}
+		tlen+=len(xID)
+	}	
+	for i:=0;i<len(SEC);i++ {T[i+tlen]=SEC[i]}
+	tlen+=len(SEC)		
+	for i:=0;i<len(Y);i++ {T[i+tlen]=Y[i]}
+	tlen+=len(Y)
+	for i:=0;i<len(R);i++ {T[i+tlen]=R[i]}
+	tlen+=len(R)		
+	for i:=0;i<len(W);i++ {T[i+tlen]=W[i]}
+	tlen+=len(W)	
+
+	return mhashit(sha,0,T[:])
+}
+
+/* calculate common key on client side */
+/* wCID = w.(A+AT) */
+func MPIN_CLIENT_KEY(sha int,G1 []byte,G2 []byte,pin int,R []byte,X []byte,H []byte,wCID []byte,CK []byte) int {
+
+	g1:=FP12_fromBytes(G1)
+	g2:=FP12_fromBytes(G2)
+	z:=fromBytes(R)
+	x:=fromBytes(X)
+	h:=fromBytes(H)
+
+	W:=ECP_fromBytes(wCID)
+	if W.is_infinity() {return MPIN_INVALID_POINT} 
+
+	W=G1mul(W,x)
+
+	f:=NewFP2bigs(NewBIGints(CURVE_Fra),NewBIGints(CURVE_Frb))
+	r:=NewBIGints(CURVE_Order)
+	q:=NewBIGints(Modulus)
+
+	z.add(h);	//new
+	z.mod(r);
+
+	m:=NewBIGcopy(q)
+	m.mod(r)
+
+	a:=NewBIGcopy(z)
+	a.mod(m)
+
+	b:=NewBIGcopy(z)
+	b.div(m)
+
+	g2.pinpow(pin,int(MPIN_PBLEN))
+	g1.mul(g2)
+
+	c:=g1.trace()
+	g2.copy(g1)
+	g2.frob(f)
+	cp:=g2.trace()
+	g1.conj()
+	g2.mul(g1)
+	cpm1:=g2.trace()
+	g2.mul(g1)
+	cpm2:=g2.trace()
+
+	c=c.xtr_pow2(cp,cpm1,cpm2,a,b)
+
+	t:=mpin_hash(sha,c,W);
+
+	for i:=0;i<MPIN_PAS;i++ {CK[i]=t[i]}
+
+	return 0
+}
+
+/* calculate common key on server side */
+/* Z=r.A - no time permits involved */
+
+func MPIN_SERVER_KEY(sha int,Z []byte,SST []byte,W []byte,H []byte,HID []byte,xID []byte,xCID []byte,SK []byte) int {
+	sQ:=ECP2_fromBytes(SST)
+	if sQ.is_infinity() {return MPIN_INVALID_POINT} 
+	R:=ECP_fromBytes(Z)
+	if R.is_infinity() {return MPIN_INVALID_POINT} 
+	A:=ECP_fromBytes(HID)
+	if A.is_infinity() {return MPIN_INVALID_POINT} 
+
+	var U *ECP
+	if xCID!=nil {
+		U=ECP_fromBytes(xCID)
+	} else	{U=ECP_fromBytes(xID)}
+	if U.is_infinity() {return MPIN_INVALID_POINT} 
+
+	w:=fromBytes(W)
+	h:=fromBytes(H)
+	A=G1mul(A,h)	// new
+	R.add(A)
+
+	U=G1mul(U,w)
+	g:=ate(sQ,R)
+	g=fexp(g)
+
+	c:=g.trace()
+
+	t:=mpin_hash(sha,c,U)
+
+	for i:=0;i<MPIN_PAS;i++ {SK[i]=t[i]}
+
+	return 0
+}
+
+/* return time since epoch */
+func MPIN_GET_TIME() int {
+	now:=time.Now()
+	return int(now.Unix())
+}
+
+/* Generate Y = H(epoch, xCID/xID) */
+func MPIN_GET_Y(sha int,TimeValue int,xCID []byte,Y []byte) {
+	h:= mhashit(sha,int32(TimeValue),xCID)
+	y:= fromBytes(h)
+	q:=NewBIGints(CURVE_Order)
+	y.mod(q)
+	if AES_S>0 {
+		y.mod2m(2*AES_S)
+	}
+	y.toBytes(Y)
+}
+        
+/* One pass MPIN Client */
+func MPIN_CLIENT(sha int,date int,CLIENT_ID []byte,RNG *RAND,X []byte,pin int,TOKEN []byte,SEC []byte,xID []byte,xCID []byte,PERMIT []byte,TimeValue int,Y []byte) int {
+	rtn:=0
+        
+	var pID []byte
+	if date == 0 {
+		pID = xID
+	} else {pID = xCID}
+          
+	rtn = MPIN_CLIENT_1(sha,date,CLIENT_ID,RNG,X,pin,TOKEN,SEC,xID,xCID,PERMIT)
+	if rtn != 0 {return rtn}
+        
+	MPIN_GET_Y(sha,TimeValue,pID,Y)
+        
+	rtn = MPIN_CLIENT_2(X,Y,SEC)
+	if rtn != 0 {return rtn}
+        
+	return 0
+}
+
+/* One pass MPIN Server */
+func MPIN_SERVER(sha int,date int,HID []byte,HTID []byte,Y []byte,SST []byte,xID []byte,xCID []byte,SEC []byte,E []byte,F []byte,CID []byte,TimeValue int) int {
+	rtn:=0
+        
+	var pID []byte
+	if date == 0 {
+		pID = xID
+	} else {pID = xCID}
+       
+	MPIN_SERVER_1(sha,date,CID,HID,HTID)
+	MPIN_GET_Y(sha,TimeValue,pID,Y);
+    
+	rtn = MPIN_SERVER_2(date,HID,HTID,Y,SST,xID,xCID,SEC,E,F)
+	if rtn != 0 {return rtn}
+        
+	return 0
+}
+
diff --git a/version22/go/PAIR.go b/version22/go/PAIR.go
new file mode 100644
index 0000000..89c80ce
--- /dev/null
+++ b/version22/go/PAIR.go
@@ -0,0 +1,641 @@
+/*
+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.
+*/
+
+/* MiotCL BN Curve Pairing functions */
+
+package main
+
+//import "fmt"
+
+/* Line function */
+func line(A *ECP2,B *ECP2,Qx *FP,Qy *FP) *FP12 {
+	P:=NewECP2()
+
+	P.copy(A);
+	ZZ:=NewFP2copy(P.getz())
+	ZZ.sqr()
+	var D int
+	if A==B {
+		D=A.dbl() 
+	} else {D=A.add(B)}
+
+	if D<0 {return NewFP12int(1)}
+
+	Z3:=NewFP2copy(A.getz())
+
+	var a *FP4
+	var b *FP4
+	c:=NewFP4int(0)
+
+	if (D==0) { /* Addition */
+		X:=NewFP2copy(B.getx())
+		Y:=NewFP2copy(B.gety())
+		T:=NewFP2copy(P.getz()) 
+		T.mul(Y)
+		ZZ.mul(T)
+
+		NY:=NewFP2copy(P.gety()); NY.neg()
+		ZZ.add(NY)
+		Z3.pmul(Qy)
+		T.mul(P.getx());
+		X.mul(NY);
+		T.add(X);
+		a=NewFP4fp2s(Z3,T)
+		ZZ.neg();
+		ZZ.pmul(Qx)
+		b=NewFP4fp2(ZZ)
+	} else { /* Doubling */
+		X:=NewFP2copy(P.getx())
+		Y:=NewFP2copy(P.gety())
+		T:=NewFP2copy(P.getx())
+		T.sqr()
+		T.imul(3)
+
+		Y.sqr()
+		Y.add(Y)
+		Z3.mul(ZZ)
+		Z3.pmul(Qy)
+
+		X.mul(T)
+		X.sub(Y)
+		a=NewFP4fp2s(Z3,X)
+		T.neg()
+		ZZ.mul(T)
+		ZZ.pmul(Qx)
+		b=NewFP4fp2(ZZ)
+	}
+	return NewFP12fp4s(a,b,c)
+}
+
+/* Optimal R-ate pairing */
+func ate(P *ECP2,Q *ECP) *FP12 {
+	f:=NewFP2bigs(NewBIGints(CURVE_Fra),NewBIGints(CURVE_Frb))
+	x:=NewBIGints(CURVE_Bnx)
+	n:=NewBIGcopy(x)
+	K:=NewECP2()
+	var lv *FP12
+	
+	if CURVE_PAIRING_TYPE == BN_CURVE {
+		n.pmul(6); n.dec(2)
+	} else {n.copy(x)}
+	
+	n.norm()
+	P.affine()
+	Q.affine()
+	Qx:=NewFPcopy(Q.getx())
+	Qy:=NewFPcopy(Q.gety())
+
+	A:=NewECP2()
+	r:=NewFP12int(1)
+
+	A.copy(P)
+	nb:=n.nbits()
+
+	for i:=nb-2;i>=1;i-- {
+		lv=line(A,A,Qx,Qy)
+		r.smul(lv)
+		if n.bit(i)==1 {
+	
+			lv=line(A,P,Qx,Qy)
+			
+			r.smul(lv)
+		}		
+		r.sqr()
+	}
+
+	lv=line(A,A,Qx,Qy)
+	r.smul(lv)
+
+	if n.parity()==1 {
+		lv=line(A,P,Qx,Qy)
+		r.smul(lv)
+	}
+
+/* R-ate fixup required for BN curves */
+
+	if CURVE_PAIRING_TYPE == BN_CURVE {
+		r.conj()
+		K.copy(P)
+		K.frob(f)
+		A.neg()
+		lv=line(A,K,Qx,Qy)
+		r.smul(lv)
+		K.frob(f)
+		K.neg()
+		lv=line(A,K,Qx,Qy)
+		r.smul(lv)
+	}
+
+	return r
+}
+
+/* Optimal R-ate double pairing e(P,Q).e(R,S) */
+func ate2(P *ECP2,Q *ECP,R *ECP2,S *ECP) *FP12 {
+	f:=NewFP2bigs(NewBIGints(CURVE_Fra),NewBIGints(CURVE_Frb))
+	x:=NewBIGints(CURVE_Bnx)
+	n:=NewBIGcopy(x)
+	K:=NewECP2()
+	var lv *FP12
+
+	if CURVE_PAIRING_TYPE == BN_CURVE {
+		n.pmul(6); n.dec(2)
+	} else {n.copy(x)}
+	
+	n.norm()
+	P.affine()
+	Q.affine()
+	R.affine()
+	S.affine()
+
+	Qx:=NewFPcopy(Q.getx())
+	Qy:=NewFPcopy(Q.gety())
+	Sx:=NewFPcopy(S.getx())
+	Sy:=NewFPcopy(S.gety())
+
+	A:=NewECP2()
+	B:=NewECP2()
+	r:=NewFP12int(1)
+
+	A.copy(P)
+	B.copy(R)
+	nb:=n.nbits()
+
+	for i:=nb-2;i>=1;i-- {
+		lv=line(A,A,Qx,Qy)
+		r.smul(lv)
+		lv=line(B,B,Sx,Sy)
+		r.smul(lv)
+
+		if n.bit(i)==1 {
+			lv=line(A,P,Qx,Qy)
+			r.smul(lv)
+			lv=line(B,R,Sx,Sy)
+			r.smul(lv)
+		}
+		r.sqr()
+	}
+
+	lv=line(A,A,Qx,Qy)
+	r.smul(lv)
+	lv=line(B,B,Sx,Sy)
+	r.smul(lv)
+	if n.parity()==1 {
+		lv=line(A,P,Qx,Qy)
+		r.smul(lv)
+		lv=line(B,R,Sx,Sy)
+		r.smul(lv)
+	}
+
+/* R-ate fixup */
+	if CURVE_PAIRING_TYPE == BN_CURVE {
+		r.conj()
+		K.copy(P)
+		K.frob(f)
+		A.neg()
+		lv=line(A,K,Qx,Qy)
+		r.smul(lv)
+		K.frob(f)
+		K.neg()
+		lv=line(A,K,Qx,Qy)
+		r.smul(lv)
+
+		K.copy(R)
+		K.frob(f)
+		B.neg()
+		lv=line(B,K,Sx,Sy)
+		r.smul(lv)
+		K.frob(f)
+		K.neg()
+		lv=line(B,K,Sx,Sy)
+		r.smul(lv)
+	}
+
+	return r
+}
+
+/* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */
+func fexp(m *FP12) *FP12 {
+	f:=NewFP2bigs(NewBIGints(CURVE_Fra),NewBIGints(CURVE_Frb))
+	x:=NewBIGints(CURVE_Bnx)
+	r:=NewFP12copy(m)
+		
+/* Easy part of final exp */
+	lv:=NewFP12copy(r)
+	lv.inverse()
+	r.conj()
+
+	r.mul(lv)
+	lv.copy(r)
+	r.frob(f)
+	r.frob(f)
+	r.mul(lv)
+/* Hard part of final exp */
+	if CURVE_PAIRING_TYPE == BN_CURVE {
+		lv.copy(r)
+		lv.frob(f)
+		x0:=NewFP12copy(lv)
+		x0.frob(f)
+		lv.mul(r)
+		x0.mul(lv)
+		x0.frob(f)
+		x1:=NewFP12copy(r)
+		x1.conj()
+		x4:=r.pow(x)
+
+		x3:=NewFP12copy(x4)
+		x3.frob(f)
+
+		x2:=x4.pow(x)
+
+		x5:=NewFP12copy(x2); x5.conj()
+		lv=x2.pow(x)
+
+		x2.frob(f)
+		r.copy(x2); r.conj()
+
+		x4.mul(r)
+		x2.frob(f)
+
+		r.copy(lv)
+		r.frob(f)
+		lv.mul(r)
+
+		lv.usqr()
+		lv.mul(x4)
+		lv.mul(x5)
+		r.copy(x3)
+		r.mul(x5)
+		r.mul(lv)
+		lv.mul(x2)
+		r.usqr()
+		r.mul(lv)
+		r.usqr()
+		lv.copy(r)
+		lv.mul(x1)
+		r.mul(x0)
+		lv.usqr()
+		r.mul(lv)
+		r.reduce()
+	} else {
+		
+// Ghamman & Fouotsa Method
+		y0:=NewFP12copy(r); y0.usqr()
+		y1:=y0.pow(x)
+		x.fshr(1); y2:=y1.pow(x); x.fshl(1)
+		y3:=NewFP12copy(r); y3.conj()
+		y1.mul(y3)
+
+		y1.conj()
+		y1.mul(y2)
+
+		y2=y1.pow(x)
+
+		y3=y2.pow(x)
+		y1.conj()
+		y3.mul(y1)
+
+		y1.conj();
+		y1.frob(f); y1.frob(f); y1.frob(f)
+		y2.frob(f); y2.frob(f)
+		y1.mul(y2)
+
+		y2=y3.pow(x)
+		y2.mul(y0)
+		y2.mul(r)
+
+		y1.mul(y2)
+		y2.copy(y3); y2.frob(f)
+		y1.mul(y2)
+		r.copy(y1)
+		r.reduce()
+
+
+/*
+		x0:=NewFP12copy(r)
+		x1:=NewFP12copy(r)
+		lv.copy(r); lv.frob(f)
+		x3:=NewFP12copy(lv); x3.conj(); x1.mul(x3)
+		lv.frob(f); lv.frob(f)
+		x1.mul(lv)
+
+		r.copy(r.pow(x))  //r=r.pow(x);
+		x3.copy(r); x3.conj(); x1.mul(x3)
+		lv.copy(r); lv.frob(f)
+		x0.mul(lv)
+		lv.frob(f)
+		x1.mul(lv)
+		lv.frob(f)
+		x3.copy(lv); x3.conj(); x0.mul(x3)
+
+		r.copy(r.pow(x))
+		x0.mul(r)
+		lv.copy(r); lv.frob(f); lv.frob(f)
+		x3.copy(lv); x3.conj(); x0.mul(x3)
+		lv.frob(f)
+		x1.mul(lv)
+
+		r.copy(r.pow(x))
+		lv.copy(r); lv.frob(f)
+		x3.copy(lv); x3.conj(); x0.mul(x3)
+		lv.frob(f)
+		x1.mul(lv)
+
+		r.copy(r.pow(x))
+		x3.copy(r); x3.conj(); x0.mul(x3)
+		lv.copy(r); lv.frob(f)
+		x1.mul(lv)
+
+		r.copy(r.pow(x))
+		x1.mul(r)
+
+		x0.usqr()
+		x0.mul(x1)
+		r.copy(x0)
+		r.reduce() */
+	}
+	return r
+}
+
+/* GLV method */
+func glv(e *BIG) []*BIG {
+	var u []*BIG
+	if CURVE_PAIRING_TYPE == BN_CURVE {
+		t:=NewBIGint(0)
+		q:=NewBIGints(CURVE_Order)
+		var v []*BIG
+
+		for i:=0;i<2;i++ {
+			t.copy(NewBIGints(CURVE_W[i]))  // why not just t=new BIG(ROM.CURVE_W[i]); 
+			d:=mul(t,e)
+			v=append(v,NewBIGcopy(d.div(q)))
+			u=append(u,NewBIGint(0))
+		}
+		u[0].copy(e)
+		for i:=0;i<2;i++ {
+			for j:=0;j<2;j++ {
+				t.copy(NewBIGints(CURVE_SB[j][i]))
+				t.copy(modmul(v[j],t,q))
+				u[i].add(q)
+				u[i].sub(t)
+				u[i].mod(q)
+			}
+		}
+	} else {
+		q:=NewBIGints(CURVE_Order)
+		x:=NewBIGints(CURVE_Bnx)
+		x2:=smul(x,x)
+		u=append(u,NewBIGcopy(e))
+		u[0].mod(x2)
+		u=append(u,NewBIGcopy(e))
+		u[1].div(x2)
+		u[1].rsub(q)
+	}
+	return u
+}
+
+/* Galbraith & Scott Method */
+func gs(e *BIG) []*BIG {
+	var u []*BIG
+	if CURVE_PAIRING_TYPE == BN_CURVE {
+		t:=NewBIGint(0)
+		q:=NewBIGints(CURVE_Order)
+
+		var v []*BIG
+		for i:=0;i<4;i++ {
+			t.copy(NewBIGints(CURVE_WB[i]))
+			d:=mul(t,e)
+			v=append(v,NewBIGcopy(d.div(q)))
+			u=append(u,NewBIGint(0))
+		}
+		u[0].copy(e)
+		for i:=0;i<4;i++ {
+			for j:=0;j<4;j++ {
+				t.copy(NewBIGints(CURVE_BB[j][i]))
+				t.copy(modmul(v[j],t,q))
+				u[i].add(q)
+				u[i].sub(t)
+				u[i].mod(q)
+			}
+		}
+	} else {
+		x:=NewBIGints(CURVE_Bnx)
+		w:=NewBIGcopy(e)
+		for i:=0;i<4;i++ {
+			u=append(u,NewBIGcopy(w))
+			u[i].mod(x)
+			w.div(x)
+		}
+	}
+	return u
+}	
+
+/* Multiply P by e in group G1 */
+func G1mul(P *ECP,e *BIG) *ECP {
+	var R *ECP
+	if (USE_GLV) {
+		P.affine()
+		R=NewECP()
+		R.copy(P)
+		Q:=NewECP()
+		Q.copy(P)
+		q:=NewBIGints(CURVE_Order);
+		cru:=NewFPbig(NewBIGints(CURVE_Cru))
+		t:=NewBIGint(0)
+		u:=glv(e)
+		Q.getx().mul(cru)
+
+		np:=u[0].nbits()
+		t.copy(modneg(u[0],q))
+		nn:=t.nbits()
+		if nn<np {
+			u[0].copy(t)
+			R.neg()
+		}
+
+		np=u[1].nbits()
+		t.copy(modneg(u[1],q))
+		nn=t.nbits()
+		if nn<np {
+			u[1].copy(t)
+			Q.neg()
+		}
+
+		R=R.mul2(u[0],Q,u[1])
+			
+	} else {
+		R=P.mul(e)
+	}
+	return R
+}
+
+/* Multiply P by e in group G2 */
+func G2mul(P *ECP2,e *BIG) *ECP2 {
+	var R *ECP2
+	if (USE_GS_G2) {
+		var Q []*ECP2
+		f:=NewFP2bigs(NewBIGints(CURVE_Fra),NewBIGints(CURVE_Frb))
+		q:=NewBIGints(CURVE_Order)
+		u:=gs(e)
+
+		t:=NewBIGint(0)
+		P.affine()
+		Q=append(Q,NewECP2());  Q[0].copy(P);
+		for i:=1;i<4;i++ {
+			Q=append(Q,NewECP2()); Q[i].copy(Q[i-1])
+			Q[i].frob(f)
+		}
+		for i:=0;i<4;i++ {
+			np:=u[i].nbits()
+			t.copy(modneg(u[i],q))
+			nn:=t.nbits()
+			if nn<np {
+				u[i].copy(t)
+				Q[i].neg()
+			}
+		}
+
+		R=mul4(Q,u)
+
+	} else {
+		R=P.mul(e)
+	}
+	return R
+}
+
+/* f=f^e */
+/* Note that this method requires a lot of RAM! Better to use compressed XTR method, see FP4.java */
+func GTpow(d *FP12,e *BIG) *FP12 {
+	var r *FP12
+	if USE_GS_GT {
+		var g []*FP12
+		f:=NewFP2bigs(NewBIGints(CURVE_Fra),NewBIGints(CURVE_Frb))
+		q:=NewBIGints(CURVE_Order)
+		t:=NewBIGint(0)
+	
+		u:=gs(e)
+
+		g=append(g,NewFP12copy(d))
+		for i:=1;i<4;i++ {
+			g=append(g,NewFP12int(0))
+			g[i].copy(g[i-1])
+			g[i].frob(f)
+		}
+		for i:=0;i<4;i++ {
+			np:=u[i].nbits()
+			t.copy(modneg(u[i],q))
+			nn:=t.nbits()
+			if nn<np {
+				u[i].copy(t)
+				g[i].conj()
+			}
+		}
+		r=pow4(g,u)
+	} else {
+		r=d.pow(e)
+	}
+	return r
+}
+
+/* test group membership - no longer needed*/
+/* with GT-Strong curve, now only check that m!=1, conj(m)*m==1, and m.m^{p^4}=m^{p^2} */
+/*
+func GTmember(m *FP12) bool {
+	if m.isunity() {return false}
+	r:=NewFP12copy(m)
+	r.conj()
+	r.mul(m)
+	if !r.isunity() {return false}
+
+	f:=NewFP2bigs(NewBIGints(CURVE_Fra),NewBIGints(CURVE_Frb))
+
+	r.copy(m); r.frob(f); r.frob(f)
+	w:=NewFP12copy(r); w.frob(f); w.frob(f)
+	w.mul(m)
+	if !GT_STRONG {
+		if !w.equals(r) {return false}
+		x:=NewBIGints(CURVE_Bnx);
+		r.copy(m); w=r.pow(x); w=w.pow(x)
+		r.copy(w); r.sqr(); r.mul(w); r.sqr()
+		w.copy(m); w.frob(f)
+	}
+	return w.equals(r)
+}
+*/
+/*
+func main() {
+
+	Q:=NewECPbigs(NewBIGints(CURVE_Gx),NewBIGints(CURVE_Gy))
+	P:=NewECP2fp2s(NewFP2bigs(NewBIGints(CURVE_Pxa),NewBIGints(CURVE_Pxb)),NewFP2bigs(NewBIGints(CURVE_Pya),NewBIGints(CURVE_Pyb)))
+
+	//r:=NewBIGints(CURVE_Order)
+	//xa:=NewBIGints(CURVE_Pxa)
+
+	fmt.Printf("P= "+P.toString())
+	fmt.Printf("\n");
+	fmt.Printf("Q= "+Q.toString());
+	fmt.Printf("\n");
+
+	//m:=NewBIGint(17)
+
+	e:=ate(P,Q)
+	e=fexp(e)
+	for i:=1;i<1000;i++ {
+		e=ate(P,Q)
+//	fmt.Printf("\ne= "+e.toString())
+//	fmt.Printf("\n")
+
+		e=fexp(e)
+	}
+	//	e=GTpow(e,m);
+
+	fmt.Printf("\ne= "+e.toString())
+	fmt.Printf("\n");
+	GLV:=glv(r)
+
+	fmt.Printf("GLV[0]= "+GLV[0].toString())
+	fmt.Printf("\n")
+
+	fmt.Printf("GLV[0]= "+GLV[1].toString())
+	fmt.Printf("\n")
+
+	G:=NewECP(); G.copy(Q)
+	R:=NewECP2(); R.copy(P)
+
+
+	e=ate(R,Q)
+	e=fexp(e)
+
+	e=GTpow(e,xa)
+	fmt.Printf("\ne= "+e.toString());
+	fmt.Printf("\n")
+
+	R=G2mul(R,xa)
+	e=ate(R,G)
+	e=fexp(e)
+
+	fmt.Printf("\ne= "+e.toString())
+	fmt.Printf("\n")
+
+	G=G1mul(G,xa)
+	e=ate(P,G)
+	e=fexp(e)
+	fmt.Printf("\ne= "+e.toString())
+	fmt.Printf("\n") 
+}
+*/
diff --git a/version22/go/RAND.go b/version22/go/RAND.go
new file mode 100644
index 0000000..2b30ec4
--- /dev/null
+++ b/version22/go/RAND.go
@@ -0,0 +1,153 @@
+/*
+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.
+*/
+
+/*
+ *   Cryptographic strong random number generator 
+ *
+ *   Unguessable seed -> SHA -> PRNG internal state -> SHA -> random numbers
+ *   Slow - but secure
+ *
+ *   See ftp://ftp.rsasecurity.com/pub/pdfs/bull-1.pdf for a justification
+ */
+
+/* Marsaglia & Zaman Random number generator constants */
+
+
+package main
+
+//import "fmt"
+
+const rand_NK int=21
+const rand_NJ int=6
+const rand_NV int=8
+
+type RAND struct {
+	ira [rand_NK]uint32  /* random number...   */
+	rndptr int
+	borrow uint32
+	pool_ptr int
+	pool [32]byte
+}
+
+/* Terminate and clean up */
+func (R *RAND) Clean() { /* kill internal state */
+	R.pool_ptr=0; R.rndptr=0;
+	for i:=0;i<32;i++ {R.pool[i]=0}
+	for i:=0;i<rand_NK;i++ {R.ira[i]=0}
+	R.borrow=0;
+}
+
+func NewRAND() *RAND {
+	R:=new(RAND)
+	R.Clean()
+	return R
+}
+
+func (R *RAND) sbrand() uint32 { /* Marsaglia & Zaman random number generator */
+	R.rndptr++
+	if R.rndptr<rand_NK {return R.ira[R.rndptr]}
+	R.rndptr=0
+	k:=rand_NK-rand_NJ
+	for i:=0;i<rand_NK;i++{ /* calculate next NK values */
+		if k==rand_NK {k=0}
+		t:=R.ira[k]
+		pdiff:=t-R.ira[i]-R.borrow
+		if pdiff<t {R.borrow=0}
+		if pdiff>t {R.borrow=1}
+		R.ira[i]=pdiff 
+		k++
+	}
+
+	return R.ira[0];
+}
+
+func (R *RAND) sirand(seed uint32) {
+	var m uint32=1;
+	R.borrow=0
+	R.rndptr=0
+	R.ira[0]^=seed;
+	for i:=1;i<rand_NK;i++ { /* fill initialisation vector */
+		in:=(rand_NV*i)%rand_NK;
+		R.ira[in]^=m;      /* note XOR */
+		t:=m
+		m=seed-m
+		seed=t
+	}
+	for i:=0;i<10000;i++ {R.sbrand()} /* "warm-up" & stir the generator */
+}
+
+func (R *RAND) fill_pool() {
+	sh:=NewHASH256()
+	for i:=0;i<128;i++ {sh.Process(byte(R.sbrand()&0xff))}
+	W:=sh.Hash()
+	for i:=0;i<32;i++ {R.pool[i]=W[i]}
+	R.pool_ptr=0;
+}
+
+func pack(b [4]byte) uint32 { /* pack 4 bytes into a 32-bit Word */
+	return (((uint32(b[3]))&0xff)<<24)|((uint32(b[2])&0xff)<<16)|((uint32(b[1])&0xff)<<8)|(uint32(b[0])&0xff)
+}
+
+/* Initialize RNG with some real entropy from some external source */
+func (R *RAND) Seed(rawlen int,raw []byte) { /* initialise from at least 128 byte string of raw random entropy */
+	var b [4]byte
+	sh:=NewHASH256()
+	R.pool_ptr=0;
+
+	for i:=0;i<rand_NK;i++ {R.ira[i]=0}
+	if rawlen>0 {
+		for i:=0;i<rawlen;i++ {
+			sh.Process(raw[i])
+		}
+		digest:=sh.Hash()
+
+/* initialise PRNG from distilled randomness */
+
+		for i:=0;i<8;i++  {
+			b[0]=digest[4*i]; b[1]=digest[4*i+1]; b[2]=digest[4*i+2]; b[3]=digest[4*i+3]
+			R.sirand(pack(b))
+		}
+	}
+	R.fill_pool()
+}
+
+/* get random byte */
+func (R *RAND) GetByte() byte { 
+	r:=R.pool[R.pool_ptr]
+	R.pool_ptr++
+	if R.pool_ptr>=32 {R.fill_pool()}
+	return byte(r&0xff)
+}
+
+/* test main program */
+/*
+func main() {
+	var raw [100]byte
+	rng:=NewRAND()
+
+	rng.Clean()
+	for i:=0;i<100;i++ {raw[i]=byte(i)}
+
+	rng.Seed(100,raw[:])
+ 
+	for i:=0;i<1000;i++ {
+		fmt.Printf("%03d ",rng.GetByte())
+	}
+}
+*/
diff --git a/version22/go/ROM32.go b/version22/go/ROM32.go
new file mode 100644
index 0000000..9bf8ed1
--- /dev/null
+++ b/version22/go/ROM32.go
@@ -0,0 +1,825 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package main
+
+type Chunk int32
+type DChunk int64
+
+/* First the 32/64-bit dependent BIG code */
+/* Note that because of the lack of a 128-bit integer, 32 and 64-bit code needs to be done differently */
+
+func pexceed(a *BIG,b *BIG) bool {
+	ea:=EXCESS(a)
+	eb:=EXCESS(b)
+	if DChunk(ea+1)*DChunk(eb+1)>DChunk(FEXCESS) {return true}
+	return false
+}
+
+func sexceed(a *BIG) bool {
+	ea:=EXCESS(a)
+	if DChunk(ea+1)*DChunk(ea+1)>DChunk(FEXCESS) {return true}
+	return false
+}
+
+func ff_pexceed(a *BIG,b *BIG) bool {
+	ea:=FF_EXCESS(a)
+	eb:=FF_EXCESS(b)
+	if DChunk(ea+1)*DChunk(eb+1)>DChunk(P_FEXCESS) {return true}
+	return false
+}
+
+func ff_sexceed(a *BIG) bool {
+	ea:=FF_EXCESS(a)
+	if DChunk(ea+1)*DChunk(ea+1)>DChunk(P_FEXCESS) {return true}
+	return false
+}
+
+/* return a*b as DBIG */
+func mul(a *BIG,b *BIG) *DBIG {
+	c:=NewDBIG()
+	var d [NLEN]DChunk
+
+	for i:=0;i<NLEN;i++ {
+		d[i]=DChunk(a.w[i])*DChunk(b.w[i])
+	}
+	s:=d[0]
+	t:=s; c.w[0]=Chunk(t)&BMASK; co:=t>>BASEBITS
+
+	for k:=1;k<NLEN;k++ {
+		s+=d[k]; t=co+s; for i:=k;i>=1+k/2;i-- {t+=DChunk(a.w[i]-a.w[k-i])*DChunk(b.w[k-i]-b.w[i])}; c.w[k]=Chunk(t)&BMASK; co=t>>BASEBITS
+	}
+
+	for k:=NLEN;k<2*NLEN-1;k++ {
+		s-=d[k-NLEN]; t=co+s; for i:=NLEN-1;i>=1+k/2;i-- {t+=DChunk(a.w[i]-a.w[k-i])*DChunk(b.w[k-i]-b.w[i])}; c.w[k]=Chunk(t)&BMASK; co=t>>BASEBITS
+	}
+	c.w[2*NLEN-1]=Chunk(co)
+
+	return c
+}
+
+/* return a^2 as DBIG */
+func sqr(a *BIG) *DBIG {
+	var j int
+	c:=NewDBIG()
+
+	t:=DChunk(a.w[0])*DChunk(a.w[0])
+	c.w[0]=Chunk(t)&BMASK; co:=t>>BASEBITS;
+
+	t=DChunk(a.w[1])*DChunk(a.w[0]); t+=t; t+=co 
+	c.w[1]=Chunk(t)&BMASK; co=t>>BASEBITS
+
+	last:=NLEN-(NLEN%2)
+	for j=2;j<last;j+=2 {
+		t=DChunk(a.w[j])*DChunk(a.w[0]); for i:=1;i<(j+1)/2;i++ {t+=DChunk(a.w[j-i])*DChunk(a.w[i])}; t+=t; t+=co;  t+=DChunk(a.w[j/2])*DChunk(a.w[j/2])
+		c.w[j]=Chunk(t)&BMASK; co=t>>BASEBITS
+		t=DChunk(a.w[j+1])*DChunk(a.w[0]); for i:=1;i<(j+2)/2;i++ {t+=DChunk(a.w[j+1-i])*DChunk(a.w[i])}; t+=t; t+=co 
+		c.w[j+1]=Chunk(t)&BMASK; co=t>>BASEBITS	
+	}
+	j=last;
+	if (NLEN%2)==1 {
+		t=DChunk(a.w[j])*DChunk(a.w[0]); for i:=1;i<(j+1)/2;i++ {t+=DChunk(a.w[j-i])*DChunk(a.w[i])}; t+=t; t+=co;  t+=DChunk(a.w[j/2])*DChunk(a.w[j/2])
+		c.w[j]=Chunk(t)&BMASK; co=t>>BASEBITS; j+=1
+		t=DChunk(a.w[NLEN-1])*DChunk(a.w[j-NLEN+1]); for i:=j-NLEN+2;i<(j+1)/2;i++ {t+=DChunk(a.w[j-i])*DChunk(a.w[i])}; t+=t; t+=co 
+		c.w[j]=Chunk(t)&BMASK; co=t>>BASEBITS; j+=1
+	}
+	for ;j<DNLEN-2;j+=2 {
+		t=DChunk(a.w[NLEN-1])*DChunk(a.w[j-NLEN+1]); for i:=j-NLEN+2;i<(j+1)/2;i++ {t+=DChunk(a.w[j-i])*DChunk(a.w[i])}; t+=t; t+=co; t+=DChunk(a.w[j/2])*DChunk(a.w[j/2])
+		c.w[j]=Chunk(t)&BMASK; co=t>>BASEBITS
+		t=DChunk(a.w[NLEN-1])*DChunk(a.w[j-NLEN+2]); for i:=j-NLEN+3;i<(j+2)/2;i++ {t+=DChunk(a.w[j+1-i])*DChunk(a.w[i])}; t+=t; t+=co
+		c.w[j+1]=Chunk(t)&BMASK; co=t>>BASEBITS
+	}
+
+	t=DChunk(a.w[NLEN-1])*DChunk(a.w[NLEN-1])+co
+	c.w[DNLEN-2]=Chunk(t)&BMASK; co=t>>BASEBITS
+	c.w[DNLEN-1]=Chunk(co)
+
+	return c
+}
+
+func monty(m* BIG, mc Chunk,d* DBIG) *BIG {
+	var dd [NLEN]DChunk
+
+	var v [NLEN]Chunk
+	b:=NewBIG()
+
+	t:=DChunk(d.w[0]); v[0]=(Chunk(t)*mc)&BMASK; t+=DChunk(v[0])*DChunk(m.w[0]); c:=(t>>BASEBITS)+DChunk(d.w[1]); s:=DChunk(0)
+
+	for k:=1;k<NLEN;k++ {
+		t=c+s+DChunk(v[0])*DChunk(m.w[k])
+		for i:=k-1;i>k/2;i-- {t+=DChunk(v[k-i]-v[i])*DChunk(m.w[i]-m.w[k-i])}
+		v[k]=(Chunk(t)*mc)&BMASK; t+=DChunk(v[k])*DChunk(m.w[0]); c=(t>>BASEBITS)+DChunk(d.w[k+1])
+		dd[k]=DChunk(v[k])*DChunk(m.w[k]); s+=dd[k]
+	}
+	for k:=NLEN;k<2*NLEN-1;k++ {
+		t=c+s;
+		for i:=NLEN-1;i>=1+k/2;i-- {t+=DChunk(v[k-i]-v[i])*DChunk(m.w[i]-m.w[k-i])}
+		b.w[k-NLEN]=Chunk(t)&BMASK; c=(t>>BASEBITS)+DChunk(d.w[k+1]); s-=dd[k-NLEN+1]
+	}
+	b.w[NLEN-1]=Chunk(c)&BMASK;	
+	b.norm()
+	return b
+}
+
+
+/* set this[i]+=x*y+c, and return high part */
+func muladd(a Chunk,b Chunk,c Chunk,r Chunk) (Chunk,Chunk) {
+	var prod=DChunk(a)*DChunk(b)+DChunk(c)+DChunk(r);
+	bot:=Chunk(prod)&BMASK;
+	top:=Chunk(prod>>BASEBITS);
+	return top,bot
+}
+
+
+/********************************************/
+
+/* Set Curve */
+/* Don't Modify from here... */
+
+const CHUNK int=32	/* Set word size */
+
+const NOT_SPECIAL int=0
+const PSEUDO_MERSENNE int=1
+const MONTGOMERY_FRIENDLY int=2
+const GENERALISED_MERSENNE int=3
+const WEIERSTRASS int=0
+const EDWARDS int=1
+const MONTGOMERY int=2
+const BN_CURVE int=0
+const BLS_CURVE int=1
+
+/* ...to here */
+
+
+/*** Enter Some Field details here  ***/
+// Curve 25519
+//  const MODBITS uint=255
+//  const MOD8 uint=5
+//  const BASEBITS uint=29
+//  const AES_S uint= 0
+
+// NIST256 or Brainpool
+//  const MODBITS uint=256
+//  const MOD8 uint=7 
+//  const BASEBITS uint=29
+//  const AES_S uint= 0
+
+// MF254 
+//  const MODBITS uint=254
+//  const MOD8 uint=7 
+//  const BASEBITS uint=29
+//  const AES_S uint= 0
+
+// MS255
+//  const MODBITS uint= 255
+//  const MOD8 uint= 3
+//  const BASEBITS uint=29
+//  const AES_S uint= 0
+
+// MF256
+//  const MODBITS uint=256 
+//  const MOD8 uint=7 
+//  const BASEBITS uint=29
+//  const AES_S uint= 0
+
+// MS256
+//  const MODBITS uint= 256
+//  const MOD8 uint= 3
+//  const BASEBITS uint=29
+//  const AES_S uint= 0
+
+// ANSSI
+//  const MODBITS uint= 256
+//  const MOD8 uint= 3
+//  const BASEBITS uint=29
+//  const AES_S uint= 0
+
+// BN254 Curve
+// const MODBITS uint=254 /* Number of bits in Modulus */
+// const MOD8 uint=3  /* Modulus mod 8 */
+// const BASEBITS uint=29
+// const AES_S uint= 0
+
+// BN454 Curve
+//const MODBITS uint=454 /* Number of bits in Modulus */
+//const MOD8 uint=3  /* Modulus mod 8 */
+//const BASEBITS uint=29
+//const AES_S uint= 128
+
+// BLS383 Curve
+const MODBITS uint=383 /* Number of bits in Modulus */
+const MOD8 uint=3  /* Modulus mod 8 */
+const BASEBITS uint=28
+const AES_S uint= 0
+
+// BLS455 Curve
+//const MODBITS uint=455 /* Number of bits in Modulus */
+//const MOD8 uint=3  /* Modulus mod 8 */
+//const BASEBITS uint=29
+//const AES_S uint= 128
+
+// HIFIVE Curve
+//  const MODBITS uint=336
+//  const MOD8 uint=5 
+//  const BASEBITS uint=29
+//  const AES_S uint= 128
+
+// GOLDILOCKS
+//  const MODBITS uint=448
+//  const MOD8 uint=7
+//  const BASEBITS uint=29
+//  const AES_S uint= 0
+
+// NIST384
+//  const MODBITS uint=384
+//  const MOD8 uint=7
+//  const BASEBITS uint=29
+//  const AES_S uint= 0
+
+// C41417
+//  const MODBITS uint=414
+//  const MOD8 uint=7
+//  const BASEBITS uint=29	
+//  const AES_S uint= 0
+
+// NIST521
+//  const MODBITS uint=521
+//  const MOD8 uint=7
+//  const BASEBITS uint=28
+//  const AES_S uint= 0
+
+// BN646 Curve
+//  const MODBITS uint=646
+//  const MOD8 uint=3
+//  const BASEBITS uint=29
+//  const AES_S uint= 192
+
+/* RSA/DH modulus length as multiple of BIGBITS */
+const FFLEN int=4
+
+/* Don't Modify from here... */
+const NLEN int=int((1+((MODBITS-1)/BASEBITS)))
+const DNLEN int=2*NLEN
+const BMASK Chunk= ((Chunk(1)<<BASEBITS)-1)
+const MODBYTES uint=(1+(MODBITS-1)/8)
+const HBITS uint=(BASEBITS/2)
+const HMASK Chunk= ((Chunk(1)<<HBITS)-1)
+const NEXCESS int=(1<<(uint(CHUNK)-BASEBITS-1));
+const FEXCESS Chunk=(Chunk(1)<<(BASEBITS*uint(NLEN)-MODBITS))
+const OMASK Chunk= ((Chunk(-1))<<(MODBITS%BASEBITS))
+const TBITS uint=MODBITS%BASEBITS // Number of active bits in top word 
+const TMASK Chunk=(Chunk(1)<<TBITS)-1
+const BIGBITS int=int(MODBYTES*8)
+
+/* Finite field support - for RSA, DH etc. */
+const FF_BITS int=(BIGBITS*FFLEN) /* Finite Field Size in bits - must be 256.2^n */
+const HFLEN int=(FFLEN/2)  /* Useful for half-size RSA private key operations */
+
+const P_MBITS uint=MODBYTES*8
+const P_MB uint=(P_MBITS%BASEBITS)
+const P_OMASK Chunk=(Chunk(-1)<<(P_MBITS%BASEBITS))
+const P_FEXCESS Chunk=(Chunk(1)<<(BASEBITS*uint(NLEN)-P_MBITS))
+const P_TBITS uint=(P_MBITS%BASEBITS)
+
+/* ...to here */
+
+
+// START SPECIFY FIELD DETAILS HERE
+//*********************************************************************************
+// Curve25519 Modulus 
+//  const MODTYPE int=PSEUDO_MERSENNE
+//  var Modulus = [...]Chunk {0x1FFFFFED,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFFF}
+//  const MConst Chunk=0x13
+
+// NIST-256 Curve 
+//  const MODTYPE int=NOT_SPECIAL
+//  var Modulus = [...]Chunk {0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FF,0x0,0x0,0x40000,0x1FE00000,0xFFFFFF}
+//  const MConst Chunk=0x1
+
+// MF254 Modulus
+//  const MODTYPE int=MONTGOMERY_FRIENDLY
+//  var Modulus= [...]Chunk {0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3F80FF}
+//  const MConst Chunk=0x3F8100
+
+// MS255 Modulus
+//  const MODTYPE int= 1
+//  var Modulus= [...]Chunk {0x1FFFFD03,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFFF}
+//  const MConst Chunk=0x2FD
+
+// MF256 Modulus
+//  const MODTYPE int= 2
+//  var Modulus= [...]Chunk {0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFFA7FF}
+//  const MConst Chunk=0xFFA800
+
+// MS256 Modulus
+//  const MODTYPE int= 1
+//  var Modulus= [...]Chunk {0x1FFFFF43,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFFFFFF}
+//  const MConst Chunk=0xBD
+
+// Brainpool
+//  const MODTYPE int= NOT_SPECIAL
+//  var Modulus= [...]Chunk {0x1F6E5377,0x9A40E8,0x9880A08,0x17EC47AA,0x18D726E3,0x5484EC1,0x6F0F998,0x1B743DD5,0xA9FB57}
+//  const MConst Chunk =0xEFD89B9
+
+// ANSSI
+//const MODTYPE int= 0
+//  var Modulus= [...]Chunk {0x186E9C03,0x7E79A9E,0x12329B7A,0x35B7957,0x435B396,0x16F46721,0x163C4049,0x1181675A,0xF1FD17}
+//  const MConst Chunk=0x164E1155
+
+// BNCX Curve Modulus
+//const MODTYPE int=NOT_SPECIAL
+//var Modulus= [...]Chunk {0x1C1B55B3,0x13311F7A,0x24FB86F,0x1FADDC30,0x166D3243,0xFB23D31,0x836C2F7,0x10E05,0x240000}
+//const MConst Chunk=0x19789E85
+
+// HIFIVE Curve
+//  const MODTYPE int=PSEUDO_MERSENNE
+//  var Modulus= [...]Chunk {0x1FFFFFFD,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFF}
+//  const MConst Chunk=0x3
+
+//GOLDILOCKS
+//  const MODTYPE int=GENERALISED_MERSENNE
+//  var Modulus= [...]Chunk {0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FDFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFF}
+//  const MConst Chunk=0x1
+
+// NIST384 Curve Modulus
+//  const MODTYPE int=NOT_SPECIAL
+//  var Modulus= [...]Chunk {0x1FFFFFFF,0x7,0x0,0x1FFFFE00,0x1FFFEFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F}
+//  const MConst Chunk=0x1
+
+// C41417 Curve Modulus
+//  const MODTYPE int=PSEUDO_MERSENNE
+//  var Modulus= [...]Chunk {0x1FFFFFEF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFF}
+//  const MConst Chunk=0x11
+
+// NIST521
+//  const MODTYPE int=PSEUDO_MERSENNE
+//  var Modulus= [...]Chunk {0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0x1FFFF}
+//  const MConst Chunk=0x1
+
+// BN646
+//  const MODTYPE int=NOT_SPECIAL
+//  var Modulus= [...]Chunk {0x404E013,0x1203604,0x4E0000,0x80A2084,0x2,0xC90420,0x4051078,0x3600001,0xA20660,0x36,0x5100900,0x10288468,0xD,0x2881200,0x1B0,0x0,0x6C0D80,0x48,0x0,0x480,0x0,0x0,0x90}
+//  const MConst Chunk=0x15F615E5	
+
+
+// BN254 Curve
+//  const MODTYPE int=NOT_SPECIAL
+//  var Modulus= [...]Chunk  {0x13,0x18000000,0x4E9,0x2000000,0x8612,0x6C00000,0x6E8D1,0x10480000,0x252364}
+//  const MConst Chunk=0x179435E5
+
+// BN454 Curve
+//  const MODTYPE int=NOT_SPECIAL
+//  var Modulus= [...]Chunk  {0x13,0x270,0x2100,0x1C00D89C,0x25084,0xA284,0x24720,0x10803AA1,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000}
+//  const MConst Chunk=0x179435E5
+
+// BLS383 Curve
+  const MODTYPE int=NOT_SPECIAL
+  var Modulus= [...]Chunk  {0xAAD556B,0xACAAB52,0x5F75D7A,0x1BB0147,0xD5D7520,0xCF73083,0xF99EB16,0x531820,0xA68EA32,0x2C01355,0x552A785,0x5C6105C,0x80A9F7,0x7AC52}
+  const MConst Chunk=0x123D0BD
+
+
+// BLS455 Curve
+//  const MODTYPE int=NOT_SPECIAL
+//  var Modulus= [...]Chunk  {0x2AB,0x1500000C,0xAAA55AA,0xB12AAD6,0x6D1BA6C,0xCCA5674,0x12E2CF6E,0xA9F9662,0x34BD939,0x12D8EAB1,0xFD9978E,0x9240600,0xE0F95B,0xAAB9550,0x55555E5,0xAAAAB}
+//  const MConst Chunk=0x1F4017FD
+
+
+// BNT Curve
+//  const MODTYPE int=NOT_SPECIAL
+//  var Modulus= [...]Chunk {0xEB4A713,0x14EDDFF7,0x1D192EAF,0x14AAAC29,0xD5F06E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120}
+//  const MConst Chunk=0x1914C4E5
+
+// BNT2 Curve
+//  const MODTYPE int=NOT_SPECIAL
+//  var Modulus= [...]Chunk {0x1460A48B,0x596E15D,0x1C35947A,0x1F27C851,0x1D00081C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004}
+//  const MConst Chunk=0x6505CDD
+
+// START SPECIFY CURVE DETAILS HERE
+//*********************************************************************************
+
+// Ed25519 Curve 
+//  const CURVETYPE int=EDWARDS
+//  const CURVE_A int = -1
+//  var CURVE_B = [...]Chunk {0x135978A3,0xF5A6E50,0x10762ADD,0x149A82,0x1E898007,0x3CBBBC,0x19CE331D,0x1DC56DFF,0x52036C}
+//  var CURVE_Order = [...]Chunk {0x1CF5D3ED,0x9318D2,0x1DE73596,0x1DF3BD45,0x14D,0x0,0x0,0x0,0x100000}
+//  var CURVE_Gx = [...]Chunk {0xF25D51A,0xAB16B04,0x969ECB2,0x198EC12A,0xDC5C692,0x1118FEEB,0xFFB0293,0x1A79ADCA,0x216936}
+//  var CURVE_Gy = [...]Chunk {0x6666658,0x13333333,0x19999999,0xCCCCCCC,0x6666666,0x13333333,0x19999999,0xCCCCCCC,0x666666}
+
+// NIST-256 Curve
+//  const CURVETYPE int=WEIERSTRASS
+//  const CURVE_A int = -3
+//  var CURVE_B = [...]Chunk {0x7D2604B,0x1E71E1F1,0x14EC3D8E,0x1A0D6198,0x86BC651,0x1EAABB4C,0xF9ECFAE,0x1B154752,0x5AC635};
+//  var CURVE_Order = [...]Chunk {0x1C632551,0x1DCE5617,0x5E7A13C,0xDF55B4E,0x1FFFFBCE,0x1FFFFFFF,0x3FFFF,0x1FE00000,0xFFFFFF}; 
+//  var CURVE_Gx = [...]Chunk {0x1898C296,0x509CA2E,0x1ACCE83D,0x6FB025B,0x40F2770,0x1372B1D2,0x91FE2F3,0x1E5C2588,0x6B17D1};
+//  var CURVE_Gy = [...]Chunk {0x17BF51F5,0x1DB20341,0xC57B3B2,0x1C66AED6,0x19E162BC,0x15A53E07,0x1E6E3B9F,0x1C5FC34F,0x4FE342};
+
+
+// MF254 Modulus, Weierstrass Curve w-254-mont
+//  const CURVETYPE int=WEIERSTRASS
+//  const CURVE_A int = -3
+//  var CURVE_B = [...]Chunk {0x1FFFD08D,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3F80FF}
+//  var CURVE_Order = [...]Chunk {0xF8DF83F,0x1D20CE25,0x8DD701B,0x317D41B,0x1FFFFEB8,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3F80FF}
+//  var CURVE_Gx = [...]Chunk {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+//  var CURVE_Gy = [...]Chunk {0x190D4EBC,0xB2EF9BF,0x14464C6B,0xE71C7F0,0x18AEBDFB,0xD3ADEBB,0x18052B85,0x1A6765CA,0x140E3F}
+
+
+// MF254 Modulus, Edwards Curve ed-254-mont
+//  const CURVETYPE int= EDWARDS
+//  const CURVE_A int= -1
+//  var CURVE_B = [...]Chunk {0x367B,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+//  var CURVE_Order=[...]Chunk {0x46E98C7,0x179E9FF6,0x158BEC3A,0xA60D917,0x1FFFFEB9,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFE03F}
+//  var CURVE_Gx =[...]Chunk {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+//  var CURVE_Gy =[...]Chunk {0xF2701E5,0x29687ED,0xC84861F,0x535081C,0x3F4E363,0x6A811B,0xCD65474,0x121AD498,0x19F0E6}
+
+// MF254 Modulus, Montgomery Curve
+//  const CURVETYPE int=MONTGOMERY
+//  const CURVE_A int= -55790;
+//  var CURVE_B = [...]Chunk {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0} // not used
+//  var CURVE_Order=[...]Chunk {0x46E98C7,0x179E9FF6,0x158BEC3A,0xA60D917,0x1FFFFEB9,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFE03F}
+//  var CURVE_Gx =[...]Chunk {0x3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+//  var CURVE_Gy =[...]Chunk {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0} // not used
+
+// MS255 Modulus, Weierstrass Curve
+//  const CURVETYPE int= WEIERSTRASS;
+//  const CURVE_A int= -3;
+//  var CURVE_B = [...]Chunk {0x1FFFAB46,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFFF}
+//  var CURVE_Order=[...]Chunk {0x1C594AEB,0x1C7D64C1,0x14ACF7EA,0x14705075,0x1FFFF864,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFFF}
+//  var CURVE_Gx =[...]Chunk {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+//  var CURVE_Gy =[...]Chunk {0x9CB44BA,0x199FFB3B,0x1F698345,0xD8F19BB,0x17D177DB,0x1FFCD97F,0xCE487A,0x181DB74F,0x6F7A6A}
+
+
+// MS255 Modulus, Edwards Curve
+//  const CURVETYPE int= EDWARDS
+//  const CURVE_A int= -1
+//  var CURVE_B = [...]Chunk {0xEA97,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+//  var CURVE_Order=[...]Chunk {0x436EB75,0x24E8F68,0x9A0CBAB,0x34F0BDB,0x1FFFFDCF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFF}
+//  var CURVE_Gx =[...]Chunk {0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+//  var CURVE_Gy =[...]Chunk {0x108736A0,0x11512ADE,0x1116916E,0x29715DA,0x47E5529,0x66EC706,0x1517B095,0xA694F76,0x26CB78}
+
+
+// MS255 Modulus, Montgomery Curve
+//  const CURVETYPE int=MONTGOMERY
+//  const CURVE_A int=-240222
+//  var CURVE_B = [...]Chunk {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0} // not used
+//  var CURVE_Order=[...]Chunk {0x436EB75,0x24E8F68,0x9A0CBAB,0x34F0BDB,0x1FFFFDCF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFF}
+//  var CURVE_Gx =[...]Chunk {0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+//  var CURVE_Gy =[...]Chunk {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0} // not used
+
+
+// MF256 Modulus, Weierstrass Curve
+//  const CURVETYPE int= WEIERSTRASS;
+//  const CURVE_A int= -3;
+//  var CURVE_B = [...]Chunk {0x14E6A,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+//  var CURVE_Order=[...]Chunk {0x79857EB,0x8862F0D,0x1941D2E7,0x2EA27CD,0x1FFFFFC5,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFFA7FF};
+//  var CURVE_Gx =[...]Chunk {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+//  var CURVE_Gy =[...]Chunk {0xB724D2A,0x3CAA61,0x5371984,0x128FD71B,0x1AE28956,0x1D13091E,0x339EEAE,0x10F7C301,0x20887C};
+
+// MF256, Edwards Curve
+//  const CURVETYPE int= EDWARDS;
+//  const CURVE_A int= -1;
+//  var CURVE_B = [...]Chunk {0x350A,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+//  var CURVE_Order=[...]Chunk {0x18EC7BAB,0x16C976F6,0x19CCF259,0x9775F70,0x1FFFFB15,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3FE9FF};
+//  var CURVE_Gx =[...]Chunk {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+//  var CURVE_Gy =[...]Chunk {0x12F3C908,0xF553917,0x1FA9A35F,0xBCC91B,0x1AACA0C,0x1779ED96,0x156BABAF,0x1F1F1989,0xDAD8D4};
+
+// MF256 Modulus, Montgomery Curve
+// 	  const CURVETYPE int=MONTGOMERY;
+//	  const CURVE_A int=-54314;
+//	  var CURVE_B = [...]Chunk {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}; // not used
+//	  var CURVE_Order=[...]Chunk {0x18EC7BAB,0x16C976F6,0x19CCF259,0x9775F70,0x1FFFFB15,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3FE9FF};
+//	  var CURVE_Gx =[...]Chunk {0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+//	  var CURVE_Gy =[...]Chunk {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}; // not used
+
+// Brainpool
+//	  const CURVETYPE int= WEIERSTRASS;
+//	  const CURVE_A int= -3;
+//	  var CURVE_B = [...]Chunk {0x1EE92B04,0x172C080F,0xBD2495A,0x7D7895E,0x176B7BF9,0x13B99E85,0x1A93F99A,0x18861B09,0x662C61};
+//	  var CURVE_Order=[...]Chunk {0x174856A7,0xF07414,0x1869BDE4,0x12F5476A,0x18D718C3,0x5484EC1,0x6F0F998,0x1B743DD5,0xA9FB57};
+//	  var CURVE_Gx =[...]Chunk {0xE1305F4,0xD0C8AB1,0xBEF0ADE,0x28588F5,0x16149AFA,0x9D91D32,0x1EDDCC88,0x79839FC,0xA3E8EB};
+//	  var CURVE_Gy =[...]Chunk {0x1B25C9BE,0xD5F479A,0x1409C007,0x196DBC73,0x417E69B,0x1170A322,0x15B5FDEC,0x10468738,0x2D996C};
+
+// ANSSI
+//    const CURVETYPE int= WEIERSTRASS;
+//    const CURVE_A int= -3;
+//    var CURVE_B = [...]Chunk {0x1B7BB73F,0x3AF6CB3,0xC68600C,0x181935C9,0xC00FDFE,0x1D3AA522,0x4C0352A,0x194A8515,0xEE353F};
+//    var CURVE_Order=[...]Chunk {0x6D655E1,0x1FEEA2CE,0x14AFE507,0x18CFC281,0x435B53D,0x16F46721,0x163C4049,0x1181675A,0xF1FD17};
+//    var CURVE_Gx =[...]Chunk {0x198F5CFF,0x64BD16E,0x62DC059,0xFA5B95F,0x23958C2,0x1EA3A4EA,0x7ACC460,0x186AD827,0xB6B3D4};
+//    var CURVE_Gy =[...]Chunk {0x14062CFB,0x188AD0AA,0x19327860,0x3860FD1,0xEF8C270,0x18F879F6,0x12447E49,0x1EF91640,0x6142E0};
+
+// HIFIVE 
+//	  const CURVETYPE int=EDWARDS;
+//	  const CURVE_A int=1;
+//	  var CURVE_Order=[...]Chunk {0x1E9FA805,0x197CACB9,0x1E4EEA9E,0x17AD70F,0x1FA9850C,0x38A0A,0x0,0x0,0x0,0x0,0x0,0x4000};
+//	  var CURVE_B = [...]Chunk {0x2B67,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+//	  var CURVE_Gx =[...]Chunk {0xC,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+//	  var CURVE_Gy =[...]Chunk {0x5FE8632,0x15F63428,0xD976C4,0x1AACA194,0x35B6DB5,0x8E3F7A,0x52D1B0E,0xF0A7A36,0x1C161D00,0x8170C70,0x1185AD59,0x181B};
+
+// GOLDILOCKS
+//	  const CURVETYPE int=EDWARDS;
+//	  const CURVE_A int=1;
+//	  var CURVE_Order=[...]Chunk {0xB5844F3,0x1BC61495,0x1163D548,0x1984E51B,0x3690216,0xDA4D76B,0xFA7113B,0x1FEF9944,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FF};
+//	  var CURVE_B = [...]Chunk {0x1FFF6756,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FDFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFF};
+//	  var CURVE_Gx =[...]Chunk {0x15555555,0xAAAAAAA,0x15555555,0xAAAAAAA,0x15555555,0xAAAAAAA,0x15555555,0x152AAAAA,0xAAAAAAA,0x15555555,0xAAAAAAA,0x15555555,0xAAAAAAA,0x15555555,0xAAAAAAA,0x1555};
+//	  var CURVE_Gy =[...]Chunk {0xA9386ED,0x1757DE6F,0x13681AF6,0x19657DA3,0x3098BBB,0x12C19D15,0x12E03595,0xE515B18,0x17B7E36D,0x1AC426E,0xDBB5E8,0x10D8560,0x159D6205,0xB8246D9,0x17A58D2B,0x15C0};
+
+// NIST384
+//	  const CURVETYPE int=WEIERSTRASS;
+//	  const CURVE_A int=-3;
+//	  var CURVE_Order=[...]Chunk  {0xCC52973,0x760CB56,0xC29DEBB,0x141B6491,0x12DDF581,0x6C0FA1B,0x1FFF1D8D,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F};
+//	  var CURVE_B = [...]Chunk {0x13EC2AEF,0x142E476E,0xBB4674A,0xC731B14,0x1875AC65,0x447A809,0x4480C50,0xDDFD028,0x19181D9C,0x1F1FC168,0x623815A,0x47DCFC9,0x1312FA7E,0x59};
+//	  var CURVE_Gx =[...]Chunk  {0x12760AB7,0x12A2F1C3,0x154A5B0E,0x5E4BB7E,0x2A38550,0xF0412A,0xE6167DD,0xC5174F3,0x146E1D3B,0x1799056B,0x3AC71C7,0x1D160A6F,0x87CA22B,0x55};
+//	  var CURVE_Gy =[...]Chunk  {0x10EA0E5F,0x1218EBE4,0x1FA0675E,0x1639C3A,0xB8C00A6,0x1889DAF8,0x11F3A768,0x17A51342,0x9F8F41D,0x1C9496E1,0x1767A62F,0xC4C58DE,0x17DE4A9,0x1B};
+
+// C41417
+//	  const CURVETYPE int=EDWARDS;
+//	  const CURVE_A int=1;
+//	  var CURVE_Order=[...]Chunk  {0x106AF79,0x18738D2F,0x18F3C606,0x1806715A,0x22B36F1,0xA67B830,0xCF32490,0x1FFFFFFD,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1F};
+//	  var CURVE_B = [...]Chunk {0xE21,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+//	  var CURVE_Gx =[...]Chunk  {0x13CBC595,0x7E9C097,0x14DF1931,0x14E7F550,0x1A111301,0x15A6B6B5,0xD526292,0x18FEAFFE,0x1F44C03E,0x1E6A31B4,0x70C9B97,0x43180C6,0x1443300,0x19A4828A,0x68};
+//	  var CURVE_Gy =[...]Chunk  {0x22,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+
+// NIST521
+//	  const CURVETYPE int=WEIERSTRASS;
+//	  const CURVE_A int=-3;
+//	  var CURVE_Order=[...]Chunk  {0x1386409,0x6FB71E9,0xC47AEBB,0xC9B8899,0x5D03BB5,0x48F709A,0xB7FCC01,0xBF2F966,0x1868783,0xFFFFFA5,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0x1FFFF};
+//	  var CURVE_B = [...]Chunk {0xB503F00,0x451FD46,0xC34F1EF,0xDF883D2,0xF073573,0xBD3BB1B,0xB1652C0,0xEC7E937,0x6193951,0xF109E15,0x489918E,0x15F3B8B,0x25B99B3,0xEEA2DA7,0xB68540,0x929A21A,0xE1C9A1F,0x3EB9618,0x5195};
+//	  var CURVE_Gx =[...]Chunk  {0x2E5BD66,0x7E7E31C,0xA429BF9,0xB3C1856,0x8DE3348,0x27A2FFA,0x8FE1DC1,0xEFE7592,0x14B5E77,0x4D3DBAA,0x8AF606B,0xB521F82,0x139053F,0x429C648,0x62395B4,0x9E3ECB6,0x404E9CD,0x8E06B70,0xC685};
+//	  var CURVE_Gy =[...]Chunk  {0xFD16650,0xBE94769,0x2C24088,0x7086A27,0x761353C,0x13FAD0,0xC550B9,0x5EF4264,0x7EE7299,0x3E662C9,0xFBD1727,0x446817A,0x449579B,0xD998F54,0x42C7D1B,0x5C8A5FB,0xA3BC004,0x296A789,0x11839};
+
+//BN646 Curve
+/*
+	  const CURVETYPE int=WEIERSTRASS;
+	  const CURVE_PAIRING_TYPE int=BN_CURVE;
+	  const CURVE_A int= 0;
+	  var CURVE_Order=[...]Chunk {0x1E04200D,0x1203603,0x420000,0x80A207E,0x2,0xC303F0,0x4051075,0x3600001,0xA20630,0x36,0x5100900,0x1028845C,0xD,0x2881200,0x1B0,0x0,0x6C0D80,0x48,0x0,0x480,0x0,0x0,0x90};
+	  var CURVE_B = [...]Chunk {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	  var CURVE_Cof = [...]Chunk {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+
+	  var CURVE_Gx =[...]Chunk  {0x404E012,0x1203604,0x4E0000,0x80A2084,0x2,0xC90420,0x4051078,0x3600001,0xA20660,0x36,0x5100900,0x10288468,0xD,0x2881200,0x1B0,0x0,0x6C0D80,0x48,0x0,0x480,0x0,0x0,0x90};
+	  var CURVE_Gy =[...]Chunk  {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+
+	  var CURVE_Bnx=[...]Chunk {0x1001,0x0,0x10000,0x0,0x0,0x8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	  var CURVE_Cru=[...]Chunk  {0x401B007,0x901,0x1B0000,0x1B024,0x0,0x288120,0xD812,0x900000,0x1B0120,0x0,0xD80000,0x6C048,0x0,0x6C0000,0x0,0x0,0x120000,0x0,0x0,0x0,0x0,0x0,0x0};
+	  var CURVE_Fra=[...]Chunk {0x4929A14,0x3B756CA,0x4337DD0,0xFC1417C,0x193166BB,0x1DC54515,0x1C0DF653,0x19BF8961,0x155980E,0x1983CB14,0x4D76309,0x1DEAB1A4,0xF9C3CF5,0x128FEC2D,0x867E339,0xDA0548A,0x1A480AF,0xA3CBCD2,0x116DA6E0,0x2A546E9,0x789577C,0x1F9459D2,0x27};
+	  var CURVE_Frb=[...]Chunk {0x1F7245FF,0x1D68DF39,0x1C1A822F,0x1848DF07,0x6CE9946,0x303BF0A,0x7F71A24,0x9A0769F,0x1F4C6E51,0x67C3521,0x38A5F6,0x123DD2C4,0x1063C317,0xFF825D2,0x17981E76,0x125FAB75,0x1EC78CD0,0x15C34375,0xE92591F,0x1D5ABD96,0x1876A883,0x6BA62D,0x68};
+	  var CURVE_Pxa=[...]Chunk {0x1CCC5E10,0x119F939,0xC6C7FE9,0x81022FF,0x6486AA6,0x1CBC560B,0x1F707429,0xC82F7B9,0x1A7F5CDA,0x14C0EB47,0x11412373,0x13DAF21E,0x126BE416,0x166744A7,0x506E81,0x1048FFA3,0x13A6B0C9,0x1A90979A,0xE78C338,0x1722C561,0xBFFF9A1,0xC1AF83C,0x3F};
+	  var CURVE_Pxb=[...]Chunk {0x67F4BC0,0x1BFC3C9,0x1E9DC3B6,0x87E2B03,0xB820274,0x1DD03B1E,0x517C463,0x1EFCBBC9,0x19F786A8,0x5572E90,0xD0BA5E0,0x16E8A40A,0x1013CF3B,0x11A7F82B,0x1C27B302,0x15E7CD12,0xB79A6DF,0x1EC6895B,0x5775A7E,0xBB28D24,0x416A171,0x127D284E,0x5D};
+	  var CURVE_Pya=[...]Chunk {0xC3FB414,0x2B868EE,0xD858793,0x157FCFE,0x16C849AD,0x1D17B0A4,0x1353CFEA,0x940A061,0x1CEF834E,0x7BE766A,0x4584C1C,0xE2397E9,0x418E9D4,0x8F53B8,0x53B37E0,0x11CA29D9,0xE425654,0x9EFF9AF,0x18CF27A1,0x17755A26,0x3F5481A,0x6C531BC,0x1E};
+	  var CURVE_Pyb=[...]Chunk {0x133908AD,0x17F1F1ED,0x14196532,0x19A85214,0x173EC3F7,0x1021EC2C,0xD798A3E,0x18F4C857,0x82EE2FA,0x11B5296D,0x1831D9C6,0x4463DB5,0x11B4812C,0xF93B884,0xC72653,0xEC6F6ED,0x916CFFF,0x1E81ED0A,0x1103518E,0x1E478B01,0x6B01074,0xC46CCAA,0x48};
+	  var CURVE_W=[2][23]Chunk {{0x6008003,0x0,0x80000,0x6,0x0,0x40030,0x3,0x0,0x30,0x0,0x0,0xC,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x2001,0x0,0x20000,0x0,0x0,0x10000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+	  var CURVE_SB=[2][2][23]Chunk {{{0x600A004,0x0,0xA0000,0x6,0x0,0x50030,0x3,0x0,0x30,0x0,0x0,0xC,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x2001,0x0,0x20000,0x0,0x0,0x10000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x2001,0x0,0x20000,0x0,0x0,0x10000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1803A00A,0x1203603,0x3A0000,0x80A2078,0x2,0xBF03C0,0x4051072,0x3600001,0xA20600,0x36,0x5100900,0x10288450,0xD,0x2881200,0x1B0,0x0,0x6C0D80,0x48,0x0,0x480,0x0,0x0,0x90}}};
+	  var CURVE_WB=[4][23]Chunk {{0x2001000,0x0,0x10000,0x2,0x0,0x8010,0x1,0x0,0x10,0x0,0x0,0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1C015005,0x600,0x150000,0x1201C,0x0,0x1C80E0,0x900E,0x600000,0x1200E0,0x0,0x900000,0x48038,0x0,0x480000,0x0,0x0,0xC0000,0x0,0x0,0x0,0x0,0x0,0x0},{0xE00B003,0x300,0xB0000,0x900E,0x0,0xE8070,0x4807,0x300000,0x90070,0x0,0x480000,0x2401C,0x0,0x240000,0x0,0x0,0x60000,0x0,0x0,0x0,0x0,0x0,0x0},{0x2003001,0x0,0x30000,0x2,0x0,0x18010,0x1,0x0,0x10,0x0,0x0,0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+	  var CURVE_BB=[4][4][23]Chunk {{{0x1E04100D,0x1203603,0x410000,0x80A207E,0x2,0xC283F0,0x4051075,0x3600001,0xA20630,0x36,0x5100900,0x1028845C,0xD,0x2881200,0x1B0,0x0,0x6C0D80,0x48,0x0,0x480,0x0,0x0,0x90},{0x1E04100C,0x1203603,0x410000,0x80A207E,0x2,0xC283F0,0x4051075,0x3600001,0xA20630,0x36,0x5100900,0x1028845C,0xD,0x2881200,0x1B0,0x0,0x6C0D80,0x48,0x0,0x480,0x0,0x0,0x90},{0x1E04100C,0x1203603,0x410000,0x80A207E,0x2,0xC283F0,0x4051075,0x3600001,0xA20630,0x36,0x5100900,0x1028845C,0xD,0x2881200,0x1B0,0x0,0x6C0D80,0x48,0x0,0x480,0x0,0x0,0x90},{0x2002,0x0,0x20000,0x0,0x0,0x10000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x2001,0x0,0x20000,0x0,0x0,0x10000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1E04100C,0x1203603,0x410000,0x80A207E,0x2,0xC283F0,0x4051075,0x3600001,0xA20630,0x36,0x5100900,0x1028845C,0xD,0x2881200,0x1B0,0x0,0x6C0D80,0x48,0x0,0x480,0x0,0x0,0x90},{0x1E04100D,0x1203603,0x410000,0x80A207E,0x2,0xC283F0,0x4051075,0x3600001,0xA20630,0x36,0x5100900,0x1028845C,0xD,0x2881200,0x1B0,0x0,0x6C0D80,0x48,0x0,0x480,0x0,0x0,0x90},{0x1E04100C,0x1203603,0x410000,0x80A207E,0x2,0xC283F0,0x4051075,0x3600001,0xA20630,0x36,0x5100900,0x1028845C,0xD,0x2881200,0x1B0,0x0,0x6C0D80,0x48,0x0,0x480,0x0,0x0,0x90}},{{0x2002,0x0,0x20000,0x0,0x0,0x10000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x2001,0x0,0x20000,0x0,0x0,0x10000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x2001,0x0,0x20000,0x0,0x0,0x10000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x2001,0x0,0x20000,0x0,0x0,0x10000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x1002,0x0,0x10000,0x0,0x0,0x8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x4002,0x0,0x40000,0x0,0x0,0x20000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1E04000A,0x1203603,0x400000,0x80A207E,0x2,0xC203F0,0x4051075,0x3600001,0xA20630,0x36,0x5100900,0x1028845C,0xD,0x2881200,0x1B0,0x0,0x6C0D80,0x48,0x0,0x480,0x0,0x0,0x90},{0x1002,0x0,0x10000,0x0,0x0,0x8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+
+const USE_GLV bool=true
+const USE_GS_G2 bool=true
+const USE_GS_GT bool=true	
+const GT_STRONG bool=true
+
+*/
+// BNCX Curve 
+/*
+	  const CURVETYPE int=WEIERSTRASS;
+	  const CURVE_PAIRING_TYPE int=BN_CURVE;
+	  const CURVE_A int= 0;
+	  var CURVE_B = [...]Chunk {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	  var CURVE_Cof = [...]Chunk {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+
+	  var CURVE_Order=[...]Chunk {0x16EB1F6D,0x108E0531,0x1241B3AF,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000};
+	  var CURVE_Bnx=[...]Chunk {0x3C012B1,0x0,0x10,0x0,0x0,0x0,0x0,0x0,0x0};
+	  var CURVE_Cru=[...]Chunk  {0x14235C97,0xF0498BC,0x1BE1D58C,0x1BBEC8E3,0x3F1440B,0x654,0x12000,0x0,0x0};
+	  var CURVE_Fra=[...]Chunk {0x15C80EA3,0x1EC8419A,0x1CFE0856,0xEE64DE2,0x11898686,0x5C55653,0x592BF86,0x5F4C740,0x135908};
+	  var CURVE_Frb=[...]Chunk {0x6534710,0x1468DDE0,0x551B018,0x10C78E4D,0x4E3ABBD,0x9ECE6DE,0x2A40371,0x1A0C46C5,0x10A6F7};
+	  var CURVE_Pxa=[...]Chunk {0x4D2EC74,0x428E777,0xF89C9B0,0x190B7F40,0x14BBB907,0x12807AE1,0x958D62C,0x58E0A76,0x19682D};
+	  var CURVE_Pxb=[...]Chunk {0xE29CFE1,0x1D2C7459,0x270C3D1,0x172F6184,0x19743F81,0x49BD474,0x192A8047,0x1D87C33E,0x1466B9};
+	  var CURVE_Pya=[...]Chunk {0xF0BE09F,0x7DFE75E,0x1FB06CC3,0x3667B08,0xE209636,0x110ABED7,0xE376078,0x1B2E4665,0xA79ED};
+	  var CURVE_Pyb=[...]Chunk {0x898EE9D,0xC825914,0x14BB7AFB,0xC9D4AD3,0x13461C28,0x122896C6,0x240D71B,0x73D9898,0x6160C};
+	  var CURVE_Gx =[...]Chunk {0x1C1B55B2,0x13311F7A,0x24FB86F,0x1FADDC30,0x166D3243,0xFB23D31,0x836C2F7,0x10E05,0x240000};
+	  var CURVE_Gy =[...]Chunk {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	  var CURVE_W=[2][9]Chunk {{0x162FEB83,0x2A31A48,0x100E0480,0x16,0x600,0x0,0x0,0x0,0x0},{0x7802561,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0}};
+	  var CURVE_SB=[2][2][9]Chunk {{{0x1DB010E4,0x2A31A48,0x100E04A0,0x16,0x600,0x0,0x0,0x0,0x0},{0x7802561,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x7802561,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0xBB33EA,0xDEAEAE9,0x233AF2F,0x1FADDC03,0x166D2643,0xFB23D31,0x836C2F7,0x10E05,0x240000}}};
+	  var CURVE_WB=[4][9]Chunk {{0x167A84B0,0xE108C2,0x1004AC10,0x7,0x200,0x0,0x0,0x0,0x0},{0x1E220475,0x166FCCAD,0x129FE68D,0x1D29DB51,0x2A0DC07,0x438,0xC000,0x0,0x0},{0xF10B93,0x1B37E657,0x194FF34E,0x1E94EDA8,0x1506E03,0x21C,0x6000,0x0,0x0},{0x1DFAAA11,0xE108C2,0x1004AC30,0x7,0x200,0x0,0x0,0x0,0x0}};
+	  var CURVE_BB=[4][4][9]Chunk {{{0x132B0CBD,0x108E0531,0x1241B39F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000},{0x132B0CBC,0x108E0531,0x1241B39F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000},{0x132B0CBC,0x108E0531,0x1241B39F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000},{0x7802562,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x7802561,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0x132B0CBC,0x108E0531,0x1241B39F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000},{0x132B0CBD,0x108E0531,0x1241B39F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000},{0x132B0CBC,0x108E0531,0x1241B39F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000}},{{0x7802562,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0x7802561,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0x7802561,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0x7802561,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x3C012B2,0x0,0x10,0x0,0x0,0x0,0x0,0x0,0x0},{0xF004AC2,0x0,0x40,0x0,0x0,0x0,0x0,0x0,0x0},{0xF6AFA0A,0x108E0531,0x1241B38F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000},{0x3C012B2,0x0,0x10,0x0,0x0,0x0,0x0,0x0,0x0}}};
+
+const USE_GLV bool=true
+const USE_GS_G2 bool=true
+const USE_GS_GT bool=true	
+const GT_STRONG bool=true
+
+*/
+// BNT2 Curve
+/*
+	  const CURVETYPE int=WEIERSTRASS;
+	  const CURVE_PAIRING_TYPE int=BN_CURVE;
+	  const CURVE_A int= 0;
+	  var CURVE_B = [...]Chunk {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	  var CURVE_Cof = [...]Chunk {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+
+	  var CURVE_Order=[...]Chunk {0x11AA2BF5,0x1FDB8D28,0xDCE0CF5,0x1F1BC24F,0x1D00021C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004};
+	  var CURVE_Bnx=[...]Chunk {0x608205,0x1008,0x10,0x0,0x0,0x0,0x0,0x0,0x0};
+	  var CURVE_Cru=[...]Chunk  {0x866BD33,0x1A813A22,0x591C3BE,0xAB6EE60,0x1ECF2367,0x361B0BD,0x12000,0x0,0x0};
+	  var CURVE_Fra=[...]Chunk {0x13AEF062,0x1593464B,0x10EF3924,0x198D3667,0x17F195BB,0xFB3FD1,0xADAF429,0x11A53D19,0x124E0B};
+	  var CURVE_Frb=[...]Chunk {0xB1B429,0x10039B12,0xB465B55,0x59A91EA,0x50E7261,0xF0C5DF3,0x1FDBE90F,0x1EA2E4D1,0x11B1F8};
+	  var CURVE_Pxa=[...]Chunk {0x1F40A3C8,0x166491CC,0x19845E12,0xB9B49D2,0x161706B3,0xBBD82B4,0x18C609E7,0x19F2D278,0x16FC17};
+	  var CURVE_Pxb=[...]Chunk {0x18549540,0x2ABD456,0x1D944184,0x16DEF7CD,0x1A95D17D,0x42B2C83,0x16427206,0x17AB2E,0x1EB5B5};
+	  var CURVE_Pya=[...]Chunk {0x14220513,0x3DF6628,0x39CDEC5,0x894F10C,0x135F1268,0x1D28DC1C,0xAAA7537,0x130EC284,0x1E8EE4};
+	  var CURVE_Pyb=[...]Chunk {0x177CE78E,0x1DC9947A,0x1BE95E07,0x1D6E8DC4,0x1FB8E27,0x1B549EDE,0xF6E8A75,0x19B75C67,0x23CEF4};	
+	  var CURVE_Gx =[...]Chunk {0x1460A48A,0x596E15D,0x1C35947A,0x1F27C851,0x1D00081C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004};
+	  var CURVE_Gy =[...]Chunk {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	  var CURVE_W=[2][9]Chunk {{0x1347083,0x5BB1415,0xE678744,0xC0602,0x600,0x0,0x0,0x0,0x0},{0xC10409,0x2010,0x20,0x0,0x0,0x0,0x0,0x0,0x0}};
+	  var CURVE_SB=[2][2][9]Chunk {{{0x1F5748C,0x5BB3425,0xE678764,0xC0602,0x600,0x0,0x0,0x0,0x0},{0xC10409,0x2010,0x20,0x0,0x0,0x0,0x0,0x0,0x0}},{{0xC10409,0x2010,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0x1075BB72,0x1A207913,0x1F6685B1,0x1F0FBC4C,0x1CFFFC1C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004}}};
+	  var CURVE_WB=[4][9]Chunk {{0xA70A224,0xC9396A4,0x1A228251,0x40200,0x200,0x0,0x0,0x0,0x0},{0x1030EF19,0xAD2B967,0xD50DC87,0x72CA2EC,0x148A1B9A,0x241207E,0xC000,0x0,0x0},{0x1848B88F,0x156964B7,0x6A86E4B,0x3965176,0xA450DCD,0x120903F,0x6000,0x0,0x0},{0xB31A62D,0xC93B6B4,0x1A228271,0x40200,0x200,0x0,0x0,0x0,0x0}};
+	  var CURVE_BB=[4][4][9]Chunk {{{0x1149A9F1,0x1FDB7D20,0xDCE0CE5,0x1F1BC24F,0x1D00021C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004},{0x1149A9F0,0x1FDB7D20,0xDCE0CE5,0x1F1BC24F,0x1D00021C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004},{0x1149A9F0,0x1FDB7D20,0xDCE0CE5,0x1F1BC24F,0x1D00021C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004},{0xC1040A,0x2010,0x20,0x0,0x0,0x0,0x0,0x0,0x0}},{{0xC10409,0x2010,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0x1149A9F0,0x1FDB7D20,0xDCE0CE5,0x1F1BC24F,0x1D00021C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004},{0x1149A9F1,0x1FDB7D20,0xDCE0CE5,0x1F1BC24F,0x1D00021C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004},{0x1149A9F0,0x1FDB7D20,0xDCE0CE5,0x1F1BC24F,0x1D00021C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004}},{{0xC1040A,0x2010,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0xC10409,0x2010,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0xC10409,0x2010,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0xC10409,0x2010,0x20,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x608206,0x1008,0x10,0x0,0x0,0x0,0x0,0x0,0x0},{0x1820812,0x4020,0x40,0x0,0x0,0x0,0x0,0x0,0x0},{0x10E927EA,0x1FDB6D18,0xDCE0CD5,0x1F1BC24F,0x1D00021C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004},{0x608206,0x1008,0x10,0x0,0x0,0x0,0x0,0x0,0x0}}};
+
+const USE_GLV bool=true
+const USE_GS_G2 bool=true
+const USE_GS_GT bool=true	
+const GT_STRONG bool=true
+
+*/
+
+// BN254 Curve
+/*
+	  const CURVETYPE int=WEIERSTRASS;
+	  const CURVE_PAIRING_TYPE int=BN_CURVE;
+	  const CURVE_A int= 0;
+	  var CURVE_B = [...]Chunk {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	  var CURVE_Cof = [...]Chunk {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+
+	  var CURVE_Order=[...]Chunk {0xD,0x8000000,0x428,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364};
+	  var CURVE_Bnx=[...]Chunk {0x1,0x4000000,0x10,0x0,0x0,0x0,0x0,0x0,0x0};
+	  var CURVE_Cru=[...]Chunk  {0x7,0xC000000,0x1B3,0x12000000,0x2490,0x11200000,0x126CD,0x0,0x0};
+	  var CURVE_Fra=[...]Chunk {0xF2A6DE9,0xBEF3603,0xFDDF0B8,0x12E9249A,0x953F850,0xDA85423,0x1232D926,0x32425CF,0x1B3776};
+	  var CURVE_Frb=[...]Chunk {0x10D5922A,0xC10C9FC,0x10221431,0xF16DB65,0x16AC8DC1,0x1917ABDC,0xDD40FAA,0xD23DA30,0x9EBEE};
+	  var CURVE_Pxa=[...]Chunk {0x803FB2B,0xF721126,0x62FC364,0x9177691,0x1EDB6A46,0x63F4630,0x18BFAE36,0x176A33D6,0x61A10};
+	  var CURVE_Pxb=[...]Chunk {0x7D54CF3,0xC61A60F,0xDE12DC3,0x1AE8D75C,0xAA5B1F4,0x13C62CC1,0xCCC42A,0x1F374E6F,0x516AA};
+	  var CURVE_Pya=[...]Chunk {0x11CD2B9A,0xF8703C4,0xF826F46,0x1A15CD7B,0x822329B,0x104B34C6,0xD0E6A43,0x140D75F2,0x21897};
+	  var CURVE_Pyb=[...]Chunk {0xB3ACE9B,0x1168D763,0xE7255E2,0xDFFAE,0x18D37B09,0x22B7AF9,0x149A3DB5,0x1CF9162,0xEBB2B};
+	  var CURVE_Gx =[...]Chunk {0x12,0x18000000,0x4E9,0x2000000,0x8612,0x6C00000,0x6E8D1,0x10480000,0x252364};
+	  var CURVE_Gy =[...]Chunk {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	  var CURVE_W=[2][9]Chunk {{0x3,0x0,0x81,0x3000000,0x618,0x0,0x0,0x0,0x0},{0x1,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0}};
+	  var CURVE_SB=[2][2][9]Chunk {{{0x4,0x8000000,0xA1,0x3000000,0x618,0x0,0x0,0x0,0x0},{0x1,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x1,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0xA,0x8000000,0x3A7,0x1C000000,0x79E1,0x6C00000,0x6E8D1,0x10480000,0x252364}}};
+	  var CURVE_WB=[4][9]Chunk {{0x0,0x4000000,0x10,0x1000000,0x208,0x0,0x0,0x0,0x0},{0x5,0x14000000,0x152,0xE000000,0x1C70,0xC00000,0xC489,0x0,0x0},{0x3,0xC000000,0xB1,0x7000000,0xE38,0x10600000,0x6244,0x0,0x0},{0x1,0xC000000,0x30,0x1000000,0x208,0x0,0x0,0x0,0x0}};
+	  var CURVE_BB=[4][4][9]Chunk {{{0xD,0x4000000,0x418,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364},{0xC,0x4000000,0x418,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364},{0xC,0x4000000,0x418,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364},{0x2,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x1,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0xC,0x4000000,0x418,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364},{0xD,0x4000000,0x418,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364},{0xC,0x4000000,0x418,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364}},{{0x2,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x2,0x4000000,0x10,0x0,0x0,0x0,0x0,0x0,0x0},{0x2,0x10000000,0x40,0x0,0x0,0x0,0x0,0x0,0x0},{0xA,0x0,0x408,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364},{0x2,0x4000000,0x10,0x0,0x0,0x0,0x0,0x0,0x0}}};
+
+const USE_GLV bool=true
+const USE_GS_G2 bool=true
+const USE_GS_GT bool=true	
+const GT_STRONG bool=false
+
+*/
+// BN454 Curve
+/*
+	  const CURVETYPE int=WEIERSTRASS;
+	  const CURVE_PAIRING_TYPE int=BN_CURVE;
+	  const CURVE_A int= 0;
+	  var CURVE_B = [...]Chunk {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	  var CURVE_Cof = [...]Chunk {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+
+	  var CURVE_Order=[...]Chunk {0xD,0x210,0x1F80,0x400D884,0x24FC4,0xA27E,0x10024708,0xFC03A9F,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000};
+	  var CURVE_Gx =[...]Chunk  {0x12,0x270,0x2100,0x1C00D89C,0x25084,0xA284,0x24720,0x10803AA1,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000};
+	  var CURVE_Gy =[...]Chunk  {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+
+	  var CURVE_Bnx=[...]Chunk {0x1,0x8,0x0,0x2000002,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	  var CURVE_Cru=[...]Chunk  {0x7,0xD8,0x900,0x16002436,0x481,0x1B24,0x168,0x48006C9,0x1600006C,0x10000091,0xD80000D,0x240000,0x0,0x0,0x0,0x0};
+	  var CURVE_Fra=[...]Chunk {0x1573B0EC,0x1816E4FE,0xA42E6E0,0x15DDCD87,0x2B17EC7,0x35B9A50,0x15AA1F74,0x1B7B2AC5,0x1CB5A200,0x9937657,0x17389A4A,0x738BADB,0xD92B321,0x3F5F0E6,0x1B1C9E9A,0x25CF3};
+	  var CURVE_Frb=[...]Chunk {0xA8C4F27,0x7E91D71,0x15BD3A1F,0x6230B14,0x1D50D1BD,0x1CA50833,0xA5827AB,0x15050FDB,0x74B3887,0x166C9A92,0x19C78A3C,0x199F4886,0x1B6D4F39,0x80A0F61,0x7236169,0x2230C};
+	  var CURVE_Pxa=[...]Chunk {0xF02B14,0x1DD1DD61,0x330AEC7,0x178617DE,0x1CEFFF36,0x116D35AF,0x1F879FBF,0x105DBF83,0x8345436,0x13664BCA,0x12EE86B5,0x776BB31,0x14AAFE16,0x41B3478,0x13E03554,0x2807A};
+	  var CURVE_Pxb=[...]Chunk {0x45BF266,0xE036876,0x8F0DBA,0xCB5976F,0x10DBC523,0x1723123C,0xBDDA7F4,0x10077CDE,0x11971DE0,0x14F1554A,0x195995EE,0x82E6FD7,0x40D5258,0x1400A58F,0x15A7850B,0x2B2A5};
+	  var CURVE_Pya=[...]Chunk {0x1E1B15C7,0x9CD5B5D,0x1571B2D2,0x1E4C048A,0x1474FB5D,0x18E2328C,0x11775519,0x144EF51F,0xF2FAABA,0x438F741,0x1930EAC0,0x144DC38,0x1287A0FE,0x36D8962,0x10011EAF,0x3ACF4};
+	  var CURVE_Pyb=[...]Chunk {0x571D60,0x8737DB,0xC4A363B,0x124E308F,0x13A65C7E,0x1387693A,0x10CDDA2F,0x184C096E,0x385175,0x5A34088,0xF17A93C,0x1E194915,0x1903ED91,0x4D6FA9F,0x8D8210B,0x12EDC};
+	  var CURVE_W=[2][16]Chunk {{0x3,0x40,0x180,0x10000010,0xC0,0x6,0x10000018,0xC00001,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+	  var CURVE_SB=[2][2][16]Chunk {{{0x4,0x50,0x180,0x14000014,0xC0,0x6,0x10000018,0xC00001,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x1,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xA,0x1D0,0x1E00,0x1400D874,0x24F03,0xA278,0x246F0,0xF003A9E,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000}}};
+	  var CURVE_WB=[4][16]Chunk {{0x0,0x8,0x80,0x2000002,0x40,0x2,0x10000008,0x400000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x5,0xA8,0x700,0xA00182A,0x381,0x121C,0x100,0x3800487,0x4000048,0x61,0x9000009,0x180000,0x0,0x0,0x0,0x0},{0x3,0x58,0x380,0x16000C16,0x1C0,0x90E,0x10000080,0x1C00243,0x12000024,0x10000030,0x4800004,0xC0000,0x0,0x0,0x0,0x0},{0x1,0x18,0x80,0x6000006,0x40,0x2,0x10000008,0x400000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+	  var CURVE_BB=[4][4][16]Chunk {{{0xD,0x208,0x1F80,0x200D882,0x24FC4,0xA27E,0x10024708,0xFC03A9F,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000},{0xC,0x208,0x1F80,0x200D882,0x24FC4,0xA27E,0x10024708,0xFC03A9F,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000},{0xC,0x208,0x1F80,0x200D882,0x24FC4,0xA27E,0x10024708,0xFC03A9F,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000},{0x2,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x1,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xC,0x208,0x1F80,0x200D882,0x24FC4,0xA27E,0x10024708,0xFC03A9F,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000},{0xD,0x208,0x1F80,0x200D882,0x24FC4,0xA27E,0x10024708,0xFC03A9F,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000},{0xC,0x208,0x1F80,0x200D882,0x24FC4,0xA27E,0x10024708,0xFC03A9F,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000}},{{0x2,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x2,0x8,0x0,0x2000002,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x2,0x20,0x0,0x8000008,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xA,0x200,0x1F80,0xD880,0x24FC4,0xA27E,0x10024708,0xFC03A9F,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000},{0x2,0x8,0x0,0x2000002,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+
+const USE_GLV bool=true
+const USE_GS_G2 bool=true
+const USE_GS_GT bool=true	
+const GT_STRONG bool=false
+
+*/
+
+// BLS455 Curve
+/*
+	  const CURVETYPE int=WEIERSTRASS;
+	  const CURVE_PAIRING_TYPE int=BLS_CURVE;
+	  const CURVE_A int= 0;
+	  var CURVE_B = [...]Chunk {0xA,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	  var CURVE_Cof = [...]Chunk {0xABFFAAB,0x14AABFFD,0xD52AADA,0x1562AAAB,0x15556AAA,0x2A,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+
+	  var CURVE_Order=[...]Chunk {0x1FC00001,0x3FFF,0x10000070,0x1400000,0x1D100,0xF0003A8,0x13C0009,0x1E200,0x180002E0,0x400001,0x4000,0x0,0x0,0x0,0x0,0x0};
+	  var CURVE_Gx =[...]Chunk  {0x1DFCEDD1,0x16A62EEF,0xE80D3ED,0xB8DE876,0x179C7253,0x182DAB52,0x46CC85F,0x1E571D9C,0x1E8392B1,0x1A155867,0x19E6527C,0x23DC64E,0xABEDA59,0xF20662B,0x17CECC01,0x310A};
+	  var CURVE_Gy =[...]Chunk  {0x6619B9B,0x27EBCD,0x1BE80A19,0x13B014BA,0x191A4936,0x13911916,0x107A5A3B,0x1DCB0863,0x1F5FB1,0xDE44A9C,0x18E23B2A,0x1FA81FD3,0xB0D6DFA,0xC2FE1EF,0xDDFA7E2,0x3351B};
+
+	  var CURVE_Bnx=[...]Chunk {0x800,0x1000004,0x40000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	  var CURVE_Cru=[...]Chunk  {0xAA9,0x9017FE0,0x128DD8AA,0x1F4A321E,0x148FEC90,0x195CDEEA,0xE961AA2,0x168D3B66,0xAFD99D7,0xB989AA6,0x1F9A5724,0x91A05FF,0xE0EF5B,0xAAB9548,0x55555E5,0xAAAAB};
+	  var CURVE_Fra=[...]Chunk {0xA2EBF21,0x4E67DEE,0xCDE6590,0xE5EA94E,0x15454985,0x140CFC43,0x7E14D1C,0x1778395A,0x1944F022,0x166BEA1A,0xC3DEEA0,0x9F031A0,0x16A7459,0x1F1D6E00,0x125CFB72,0x72FD4};
+	  var CURVE_Frb=[...]Chunk {0x15D1438A,0x1019821D,0x1DCBF01A,0x1CB40187,0x118C70E6,0x18BD5A30,0xB018251,0x13275D08,0xA06E916,0x1C6D0096,0x39BA8ED,0x1F33D460,0x1F768501,0xB8E274F,0x12F85A72,0x37AD6};
+	  var CURVE_Pxa=[...]Chunk {0x10C1F542,0x23AF907,0x159F840,0xBAC0E1F,0x133D7766,0x1C034C5D,0x14C5C875,0x1ED0BDA2,0x16A49C71,0x1E9FF62D,0x14F3ACC0,0x1E0C9FEA,0xC4638DE,0x74D18DA,0xBEA0030,0x5D962};
+	  var CURVE_Pxb=[...]Chunk {0x749F03D,0xC843773,0xB17BCBA,0x1134AB4B,0x8EA016E,0x1A0D766C,0x58F819E,0x48A1FCC,0xE296F62,0x83370E4,0xC9BA1D5,0x1E43290E,0xEE59A80,0x1FDD85F5,0x1F3819B6,0x1D9F};
+	  var CURVE_Pya=[...]Chunk {0x181A77F4,0x191AD22,0x1E9F842A,0x1E1E6CF6,0xD55B9D9,0x1D062533,0x15BB1323,0x7ECBC1,0x1A9EC2EF,0x1EE14CE0,0x1E96B271,0xA794439,0x1C544324,0xE6AD5DC,0x16429B0F,0x448E3};
+	  var CURVE_Pyb=[...]Chunk {0x1E1FDBA2,0x1A09DB6C,0xF680D5B,0xFCC6122,0xC488E2A,0x1E489ECD,0x1005617E,0x1CF9EC36,0x1C89ED72,0x16C00D90,0x1563E595,0x1243DDC0,0x8698F9E,0x1BD81E7E,0xF2A0F4A,0x66A0};
+
+// not used
+	  var CURVE_W=[2][16]Chunk {{},{}};
+	  var CURVE_SB=[2][2][16]Chunk {{{},{}},{{},{}}};
+	  var CURVE_WB=[4][16]Chunk {{},{},{},{}};
+	  var CURVE_BB=[4][4][16]Chunk {{{},{},{},{}},{{},{},{},{}},{{},{},{},{}},{{},{},{},{}}};
+
+const USE_GLV bool=true
+const USE_GS_G2 bool=true
+const USE_GS_GT bool=true	
+const GT_STRONG bool=false
+
+*/
+
+
+// BNT Curve
+/*
+	  const CURVETYPE int=WEIERSTRASS;
+	  const CURVE_PAIRING_TYPE int=BN_CURVE;
+	  const CURVE_A int= 0;
+	  var CURVE_B = [...]Chunk {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	  var CURVE_Cof = [...]Chunk {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+
+	  var CURVE_Order=[...]Chunk {0xD30210D,0x13ABBBF4,0xCB2CD8E,0x11A86925,0xD5F00E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120};
+	  var CURVE_Bnx=[...]Chunk {0x4081,0x40300,0x10,0x0,0x0,0x0,0x0,0x0,0x0};
+	  var CURVE_Cru=[...]Chunk  {0xB4FCD87,0xF5A9EAD,0xEAC47EB,0x19054BE5,0x104C9764,0x18A3B28A,0x12006,0x0,0x0};
+	  var CURVE_Fra=[...]Chunk {0xDC80022,0xFAE8A75,0x1EB338D6,0x189209AD,0x13211BE6,0x4F8C850,0x10E53D94,0x12593778,0x1328A2};
+	  var CURVE_Frb=[...]Chunk {0xECA6F1,0x53F5582,0x1E65F5D9,0x1C18A27B,0x1A3DEB01,0x10A2832B,0x1456AA9A,0x9136B67,0x10D87E};
+	  var CURVE_Pxa=[...]Chunk {0x88E65BB,0x144C3F11,0xA98C4EF,0x18015A39,0x1548B7CC,0xA992820,0xE7AF301,0x19A09826,0x14483F};
+	  var CURVE_Pxb=[...]Chunk {0x8DBE2C0,0x133C4440,0x78D214E,0xAFFC3F0,0x51B57B9,0x285318D,0xC0B68FF,0x166709D8,0x87F46};
+	  var CURVE_Pya=[...]Chunk {0x20CA1D,0x101623F,0xE67CDB,0x19682CFD,0x19F72C94,0x14E372A1,0xF5D28B1,0x13820561,0x14E8C2};
+	  var CURVE_Pyb=[...]Chunk {0x116628F2,0x1EC21BE3,0xF2DF71A,0x144FC2CF,0x172681D0,0xC54163A,0xF47B7B0,0x148C48A9,0x17AFE2};
+	  var CURVE_Gx =[...]Chunk {0xEB4A712,0x14EDDFF7,0x1D192EAF,0x14AAAC29,0xD5F06E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120};
+	  var CURVE_Gy =[...]Chunk {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	  var CURVE_W=[2][9]Chunk {{0x1838403,0x1321803,0x106660E1,0x3024304,0x600,0x0,0x0,0x0,0x0},{0x8101,0x80600,0x20,0x0,0x0,0x0,0x0,0x0,0x0}};
+	  var CURVE_SB=[2][2][9]Chunk {{{0x1840504,0x13A1E03,0x10666101,0x3024304,0x600,0x0,0x0,0x0,0x0},{0x8101,0x80600,0x20,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x8101,0x80600,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0xBAC9D0A,0x1279A3F1,0x1C4C6CAD,0xEA62620,0xD5EFAE8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120}}};
+	  var CURVE_WB=[4][9]Chunk {{0x80C080,0xB0A0301,0x10222030,0x100C101,0x200,0x0,0x0,0x0,0x0},{0x88C4A85,0x15A9C820,0x14B71B0D,0x1D5A5F46,0x158868ED,0x106D21B1,0xC004,0x0,0x0},{0x4464583,0x1AD6E590,0xA5B8D8E,0x1EAD2FA3,0x1AC43476,0x83690D8,0x6002,0x0,0x0},{0x814181,0xB120901,0x10222050,0x100C101,0x200,0x0,0x0,0x0,0x0}};
+	  var CURVE_BB=[4][4][9]Chunk {{{0xD2FE08D,0x13A7B8F4,0xCB2CD7E,0x11A86925,0xD5F00E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120},{0xD2FE08C,0x13A7B8F4,0xCB2CD7E,0x11A86925,0xD5F00E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120},{0xD2FE08C,0x13A7B8F4,0xCB2CD7E,0x11A86925,0xD5F00E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120},{0x8102,0x80600,0x20,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x8101,0x80600,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0xD2FE08C,0x13A7B8F4,0xCB2CD7E,0x11A86925,0xD5F00E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120},{0xD2FE08D,0x13A7B8F4,0xCB2CD7E,0x11A86925,0xD5F00E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120},{0xD2FE08C,0x13A7B8F4,0xCB2CD7E,0x11A86925,0xD5F00E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120}},{{0x8102,0x80600,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0x8101,0x80600,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0x8101,0x80600,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0x8101,0x80600,0x20,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x4082,0x40300,0x10,0x0,0x0,0x0,0x0,0x0,0x0},{0x10202,0x100C00,0x40,0x0,0x0,0x0,0x0,0x0,0x0},{0xD2FA00A,0x13A3B5F4,0xCB2CD6E,0x11A86925,0xD5F00E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120},{0x4082,0x40300,0x10,0x0,0x0,0x0,0x0,0x0,0x0}}};
+
+const USE_GLV bool=true
+const USE_GS_G2 bool=true
+const USE_GS_GT bool=true	
+const GT_STRONG bool=true
+
+
+*/
+
+
+// BLS383 Curve
+
+const CURVETYPE int=WEIERSTRASS
+const CURVE_PAIRING_TYPE int=BLS_CURVE
+const CURVE_A int= 0
+
+var CURVE_Order=[...]Chunk {0xFFF001,0xFFF8000,0xFE7800,0xBFDE007,0xC5EDF1C,0x3000049,0x910007A,0xC40007F,0x641004C,0x14,0x0,0x0,0x0,0x0};
+var CURVE_B = [...]Chunk {0x9,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+var CURVE_Cof = [...]Chunk {0x52B,0x2A00,0xAAB2CA0,0x5560AAA,0x6055,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+var CURVE_Gx =[...]Chunk {0xD10786B,0xD59B348,0x3F54AD0,0x3477C0E,0x4578B9B,0xBF25B73,0x7BB6F65,0x4F6AC00,0xFF57E9C,0xEFD5830,0xFB6EC02,0xADB9F88,0xEE4BC98,0xB08C};
+var CURVE_Gy =[...]Chunk {0xD145DDB,0x5DA023,0x5FEF7CC,0x13F518C,0x2B2A66F,0x56EC346,0xC7A925F,0x96F3019,0x981223E,0x9061047,0x8F5BE59,0x4810AD,0x9337671,0x1F390};
+
+var CURVE_Bnx=[...]Chunk {0x40,0x100,0x110,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+var CURVE_Cru=[...]Chunk {0xDA155A9,0xA3AAC4E,0x61E5E3D,0xDF2FE87,0xE632625,0xBCDFAAD,0xD3035A6,0x5123128,0xBEAD683,0xDBF3A2B,0x424190,0x5C5FAB2,0x80A9F7,0x7AC52};
+
+
+var CURVE_Fra=[...]Chunk {0x2B4508B,0x2BA59A9,0x6EEF343,0x63DB7A0,0x1DFBC74,0x40341CB,0x32D55D3,0x1639E9D,0x5CC36D4,0xB19B3F0,0xD86AB98,0xF323EE4,0xB198672,0x5A5F};
+var CURVE_Frb=[...]Chunk {0x7F904E0,0x81051A9,0xF086A37,0xB7D49A6,0xB7DB8AB,0x8F3EEB8,0xC6C9543,0xEEF7983,0x49CB35D,0x7A65F65,0x7CBFBEC,0x693D177,0x5672384,0x751F2};
+var CURVE_Pxa=[...]Chunk {0xBAC9472,0x6059885,0xE2DC36D,0x7C4D31D,0x8C88A7,0xBDC90C3,0x1C688FC,0x29F0197,0xC43F167,0x3693539,0x61EB8BF,0xD81E5A5,0x22B56BF,0x4D507};
+var CURVE_Pxb=[...]Chunk {0x272AB23,0x9B4BD7A,0xF44DCE8,0x7AF19D4,0x3206A34,0x3F6F7B9,0x2A819FB,0x571DD3E,0x635D7EE,0x3A2BA3B,0xC1A126,0xAC28C78,0x17C3E5B,0xEE36};
+var CURVE_Pya=[...]Chunk {0x77BD4FD,0x81D2309,0xDFDFC6,0xB66072,0xC89A0C,0x41FC959,0x878287A,0x2E1FBCF,0x14EEE65,0x11C230,0x6BB325E,0x2887881,0x859A05C,0x8F40};
+var CURVE_Pyb=[...]Chunk {0x52C4CE6,0xA5E20A2,0xAFF40C8,0x5907A74,0x2448EF3,0x41760A4,0xFDA199,0xFFEF82B,0x8D4EA49,0xA0F29A1,0x6E4997B,0xAC7F7B8,0xBA88C12,0x1DCAB};
+
+// Not used
+var CURVE_W=[2][14]Chunk {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+var CURVE_SB=[2][2][14]Chunk {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+var CURVE_WB=[4][14]Chunk {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+var CURVE_BB=[4][4][14]Chunk {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+
+const USE_GLV bool=true
+const USE_GS_G2 bool=true
+const USE_GS_GT bool=true	
+const GT_STRONG bool=false
+
+
+
+
diff --git a/version22/go/ROM64.go b/version22/go/ROM64.go
new file mode 100644
index 0000000..438c99f
--- /dev/null
+++ b/version22/go/ROM64.go
@@ -0,0 +1,826 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package main
+
+type Chunk int64
+
+
+/* First the 32/64-bit dependent BIG code */
+/* Note that because of the lack of a 128-bit integer, 32 and 64-bit code needs to be done differently */
+
+func pexceed(a *BIG,b *BIG) bool {
+	ea:=EXCESS(a)
+	eb:=EXCESS(b)
+	if (ea+1)>FEXCESS/(eb+1) {return true}
+	return false
+}
+
+func sexceed(a *BIG) bool {
+	ea:=EXCESS(a)
+	if (ea+1)>FEXCESS/(ea+1) {return true}
+	return false
+}
+
+func ff_pexceed(a *BIG,b *BIG) bool {
+	ea:=FF_EXCESS(a)
+	eb:=FF_EXCESS(b)
+	if (ea+1)>P_FEXCESS/(eb+1) {return true}
+	return false
+}
+
+func ff_sexceed(a *BIG) bool {
+	ea:=FF_EXCESS(a)
+	if (ea+1)>P_FEXCESS/(ea+1) {return true}
+	return false
+}
+
+/* return a*b as DBIG */
+func mul(a *BIG,b *BIG) *DBIG {
+	c:=NewDBIG()
+	carry:= Chunk(0)
+//	a.norm()
+//	b.norm()
+
+	for i:=0;i<NLEN;i++ {
+		carry=0
+		for j:=0;j<NLEN;j++ {
+			carry,c.w[i+j]=muladd(a.w[i],b.w[j],carry,c.w[i+j])
+			//carry=c.muladd(a.w[i],b.w[j],carry,i+j)
+		}
+		c.w[NLEN+i]=carry
+	}
+	
+	return c
+}
+
+/* return a^2 as DBIG */
+func sqr(a *BIG) *DBIG {
+	c:=NewDBIG()
+	carry:= Chunk(0)
+//	a.norm()
+	for i:=0;i<NLEN;i++ {
+		carry=0;
+		for j:=i+1;j<NLEN;j++ {
+			carry,c.w[i+j]=muladd(2*a.w[i],a.w[j],carry,c.w[i+j])
+			//carry=c.muladd(2*a.w[i],a.w[j],carry,i+j)
+		}
+		c.w[NLEN+i]=carry
+	}
+
+	for i:=0;i<NLEN;i++ {
+		top,bot:=muladd(a.w[i],a.w[i],0,c.w[2*i])
+		c.w[2*i]=bot
+		c.w[2*i+1]+=top
+		//c.w[2*i+1]+=c.muladd(a.w[i],a.w[i],0,2*i)
+
+	}
+	c.norm()
+	return c
+}
+
+func monty(md* BIG, mc Chunk,d* DBIG) *BIG {
+	carry:=Chunk(0)
+	m:=Chunk(0)
+	for i:=0;i<NLEN;i++ {
+		if (mc==-1) { 
+			m=(-d.w[i])&BMASK
+		} else {
+			if (mc==1) {
+				m=d.w[i]
+			} else {m=(mc*d.w[i])&BMASK}
+		}
+
+		carry=0
+		for j:=0;j<NLEN;j++ {
+			carry,d.w[i+j]=muladd(m,md.w[j],carry,d.w[i+j])
+				//carry=d.muladd(m,md.w[j],carry,i+j)
+		}
+		d.w[NLEN+i]+=carry
+	}
+
+	b:=NewBIG()
+	for i:=0;i<NLEN;i++ {
+		b.w[i]=d.w[NLEN+i]
+	}
+	b.norm()
+	return b		
+}
+
+/* set this[i]+=x*y+c, and return high part */
+func muladd(a Chunk,b Chunk,c Chunk,r Chunk) (Chunk,Chunk) {
+	x0:=a&HMASK
+	x1:=(a>>HBITS)
+	y0:=b&HMASK;
+	y1:=(b>>HBITS)
+	bot:=x0*y0
+	top:=x1*y1
+	mid:=x0*y1+x1*y0
+	x0=mid&HMASK;
+	x1=(mid>>HBITS)
+	bot+=x0<<HBITS; bot+=c; bot+=r 
+	top+=x1;
+	carry:=bot>>BASEBITS
+	bot&=BMASK
+	top+=carry
+	return top,bot
+}
+
+
+/********************************************/
+
+/* Set Curve */
+/* Don't Modify from here... */
+
+const CHUNK int=64	/* Set word size */
+
+const NOT_SPECIAL int=0
+const PSEUDO_MERSENNE int=1
+const MONTGOMERY_FRIENDLY int=2
+const GENERALISED_MERSENNE int=3
+const WEIERSTRASS int=0
+const EDWARDS int=1
+const MONTGOMERY int=2
+const BN_CURVE int=0
+const BLS_CURVE int=1
+
+/* ...to here */
+
+
+/*** Enter Some Field details here  ***/
+// Curve 25519
+//  const MODBITS uint=255
+//  const MOD8 uint=5
+//  const BASEBITS uint=56
+//  const AES_S uint= 0
+
+// NIST256 or Brainpool
+//  const MODBITS uint=256
+//  const MOD8 uint=7 
+//  const BASEBITS uint=56
+//  const AES_S uint= 0
+
+// MF254 
+//  const MODBITS uint=254
+//  const MOD8 uint=7 
+//  const BASEBITS uint=56
+//  const AES_S uint= 0
+
+// MS255
+//  const MODBITS uint= 255
+//  const MOD8 uint= 3
+//  const BASEBITS uint=56
+//  const AES_S uint= 0
+
+// MF256
+//  const MODBITS uint=256 
+//  const MOD8 uint=7 
+//  const BASEBITS uint=56
+//  const AES_S uint= 0
+
+// MS256
+//  const MODBITS uint= 256
+//  const MOD8 uint= 3
+//  const BASEBITS uint=56
+//  const AES_S uint= 0
+
+// ANSSI
+//  const MODBITS uint= 256
+//  const MOD8 uint= 3
+//  const BASEBITS uint=56
+//  const AES_S uint= 0
+
+// BN254 Curve
+//const MODBITS uint=254 /* Number of bits in Modulus */
+//const MOD8 uint=3  /* Modulus mod 8 */
+//const BASEBITS uint=56
+//const AES_S uint= 0
+
+// BN454 Curve
+//const MODBITS uint=454 /* Number of bits in Modulus */
+//const MOD8 uint=3  /* Modulus mod 8 */
+//const BASEBITS uint=60
+//const AES_S uint= 128
+
+// BLS383 Curve
+const MODBITS uint=383 /* Number of bits in Modulus */
+const MOD8 uint=3  /* Modulus mod 8 */
+const BASEBITS uint=56
+const AES_S uint= 0
+
+// BLS455 Curve
+//const MODBITS uint=455 /* Number of bits in Modulus */
+//const MOD8 uint=3  /* Modulus mod 8 */
+//const BASEBITS uint=60
+//const AES_S uint= 128
+
+// HIFIVE Curve
+//  const MODBITS uint=336
+//  const MOD8 uint=5 
+//  const BASEBITS uint=60
+//  const AES_S uint= 128
+
+// GOLDILOCKS
+//  const MODBITS uint=448
+//  const MOD8 uint=7
+//  const BASEBITS uint=60
+//  const AES_S uint= 0
+
+// NIST384
+//  const MODBITS uint=384
+//  const MOD8 uint=7
+//  const BASEBITS uint=60
+//  const AES_S uint= 0
+
+// C41417
+//  const MODBITS uint=414
+//  const MOD8 uint=7
+//  const BASEBITS uint=60	
+//  const AES_S uint= 0
+
+// NIST521
+//  const MODBITS uint=521
+//  const MOD8 uint=7
+//  const BASEBITS uint=60
+//  const AES_S uint= 0
+
+// BN646 Curve
+//  const MODBITS uint=646
+//  const MOD8 uint=3
+//  const BASEBITS uint=60
+//  const AES_S uint= 192
+
+/* RSA/DH modulus length as multiple of BIGBITS */
+const FFLEN int=4
+
+/* Don't Modify from here... */
+const NLEN int=int((1+((MODBITS-1)/BASEBITS)))
+const DNLEN int=2*NLEN
+const BMASK Chunk= ((Chunk(1)<<BASEBITS)-1)
+const MODBYTES uint=(1+(MODBITS-1)/8)
+const HBITS uint=(BASEBITS/2)
+const HMASK Chunk= ((Chunk(1)<<HBITS)-1)
+const NEXCESS int=(1<<(uint(CHUNK)-BASEBITS-1));
+const FEXCESS Chunk=(Chunk(1)<<(BASEBITS*uint(NLEN)-MODBITS))
+const OMASK Chunk= ((Chunk(-1))<<(MODBITS%BASEBITS))
+const TBITS uint=MODBITS%BASEBITS // Number of active bits in top word 
+const TMASK Chunk=(Chunk(1)<<TBITS)-1
+const BIGBITS int=int(MODBYTES*8)
+
+/* Finite field support - for RSA, DH etc. */
+const FF_BITS int=(BIGBITS*FFLEN) /* Finite Field Size in bits - must be 256.2^n */
+const HFLEN int=(FFLEN/2)  /* Useful for half-size RSA private key operations */
+
+const P_MBITS uint=MODBYTES*8
+const P_MB uint=(P_MBITS%BASEBITS)
+const P_OMASK Chunk=(Chunk(-1)<<(P_MBITS%BASEBITS))
+const P_FEXCESS Chunk=(Chunk(1)<<(BASEBITS*uint(NLEN)-P_MBITS))
+const P_TBITS uint=(P_MBITS%BASEBITS)
+
+/* ...to here */
+
+
+// START SPECIFY FIELD DETAILS HERE
+//*********************************************************************************
+// Curve25519 Modulus 
+//  const MODTYPE int=PSEUDO_MERSENNE
+//  var Modulus = [...]Chunk {0xFFFFFFFFFFFFED,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0x7FFFFFFF}
+//  const MConst Chunk=0x13
+
+// NIST-256 Curve 
+//  const MODTYPE int=NOT_SPECIAL
+//  var Modulus = [...]Chunk {0xFFFFFFFFFFFFFF,0xFFFFFFFFFF,0x0,0x1000000,0xFFFFFFFF}
+//  const MConst Chunk=0x1
+
+// MF254 Modulus
+//  const MODTYPE int=MONTGOMERY_FRIENDLY
+//  var Modulus= [...]Chunk {0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0x3F80FFFF}
+//  const MConst Chunk=0x3F810000
+
+// MS255 Modulus
+//  const MODTYPE int= 1
+//  var Modulus= [...]Chunk {0xFFFFFFFFFFFD03,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0x7FFFFFFF}
+//  const MConst Chunk=0x2FD
+
+// MF256 Modulus
+//  const MODTYPE int= 2
+//  var Modulus= [...]Chunk {0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFA7FFFF}
+//  const MConst Chunk=0xFFA80000
+
+// MS256 Modulus
+//  const MODTYPE int= 1
+//  var Modulus= [...]Chunk {0xFFFFFFFFFFFF43,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFF}
+//  const MConst Chunk=0xBD
+
+// Brainpool
+//  const MODTYPE int= NOT_SPECIAL
+//  var Modulus= [...]Chunk {0x13481D1F6E5377,0xF623D526202820,0x909D838D726E3B,0xA1EEA9BC3E660A,0xA9FB57DB}
+//  const MConst Chunk =0xA75590CEFD89B9
+
+// ANSSI
+//const MODTYPE int= 0
+//  var Modulus= [...]Chunk{0xFCF353D86E9C03,0xADBCABC8CA6DE8,0xE8CE42435B3961,0xB3AD58F10126D,0xF1FD178C}
+//  const MConst Chunk=0x97483A164E1155
+
+// BNCX Curve Modulus
+//const MODTYPE int=NOT_SPECIAL
+//var Modulus= [...]Chunk {0x6623EF5C1B55B3,0xD6EE18093EE1BE,0x647A6366D3243F,0x8702A0DB0BDDF,0x24000000}
+//const MConst Chunk=0x4E205BF9789E85
+
+// HIFIVE Curve
+//  const MODTYPE int=PSEUDO_MERSENNE
+//  var Modulus= [...]Chunk {0xFFFFFFFFFFFFFFD,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFF}
+//  const MConst Chunk=0x3
+
+//GOLDILOCKS
+//  const MODTYPE int=GENERALISED_MERSENNE
+//  var Modulus= [...]Chunk {0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFEFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFF}
+//  const MConst Chunk=0x1
+
+// NIST384 Curve Modulus
+//  const MODTYPE int=NOT_SPECIAL
+//  var Modulus= [...]Chunk {0xFFFFFFFF,0xFFFFFF000000000,0xFFFFFFFFFFFFEFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFF}
+//  const MConst Chunk=0x100000001
+
+// C41417 Curve Modulus
+//  const MODTYPE int=PSEUDO_MERSENNE
+//  var Modulus= [...]Chunk {0xFFFFFFFFFFFFFEF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0x3FFFFFFFFFFFFF}
+//  const MConst Chunk=0x11
+
+// NIST521
+//  const MODTYPE int=PSEUDO_MERSENNE
+//  var Modulus= [...]Chunk {0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0x1FFFFFFFFFF}
+//  const MConst Chunk=0x1
+
+// BN646
+//  const MODTYPE int=NOT_SPECIAL
+//  var Modulus= [...]Chunk {0x2406C08404E013,0x240510420138000,0xE01920840000000,0x601B00000901441,0x400000006C0A206,0xD814423414402,0x6C051024000000,0xD8000000000000,0x9006C,0x240000,0x240000000000}
+//  const MConst Chunk=0xCE50F5CF5F615E5	
+
+
+// BN254 Curve
+//  const MODTYPE int=NOT_SPECIAL
+//  var Modulus= [...]Chunk  {0x13,0x13A7,0x80000000086121,0x40000001BA344D,0x25236482}
+//  const MConst Chunk=0x435E50D79435E5
+
+// BN454 Curve
+//  const MODTYPE int=NOT_SPECIAL
+//  var Modulus= [...]Chunk  {0x4E00000013,0x4E006C4E0000840,0x800014508002508,0x888401D5080091C,0x21C00021D4400DA,0x25B06C01B144009,0xD80000909000,0x240000900}
+//  const MConst Chunk=0xF33C46ED79435E5
+
+// BLS383 Curve
+  const MODTYPE int=NOT_SPECIAL
+  var Modulus= [...]Chunk  {0xACAAB52AAD556B,0x1BB01475F75D7A,0xCF73083D5D7520,0x531820F99EB16,0x2C01355A68EA32,0x5C6105C552A785,0x7AC52080A9F7}
+  const MConst Chunk=0xA59AB3B123D0BD
+
+// BLS455 Curve
+//  const MODTYPE int=NOT_SPECIAL
+//  var Modulus= [...]Chunk  {0xAA00001800002AB,0xC589556B2AA956A,0xB9994ACE86D1BA6,0x3954FCB314B8B3D,0xE3A5B1D56234BD9,0x95B49203003F665,0x57955572AA00E0F,0x555559555}
+//  const MConst Chunk=0xB3EF8137F4017FD
+
+
+// BNT Curve
+//  const MODTYPE int=NOT_SPECIAL
+//  var Modulus= [...]Chunk {0x9DBBFEEEB4A713,0x555614F464BABE,0x3696F8D5F06E8A,0x6517014EFA0BAB,0x240120DB}
+//  const MConst Chunk=0xC5A872D914C4E5
+
+// BNT2 Curve
+//  const MODTYPE int=NOT_SPECIAL
+//  var Modulus= [...]Chunk {0xB2DC2BB460A48B,0x93E428F0D651E8,0xF3B89D00081CF,0x410F5AADB74E20,0x24000482}
+//  const MConst Chunk=0xFE6A47A6505CDD
+
+// START SPECIFY CURVE DETAILS HERE
+//*********************************************************************************
+
+// Ed25519 Curve 
+//  const CURVETYPE int=EDWARDS
+//  const CURVE_A int = -1
+//  var CURVE_B = [...]Chunk {0xEB4DCA135978A3,0xA4D4141D8AB75,0x797779E8980070,0x2B6FFE738CC740,0x52036CEE}
+//  var CURVE_Order = [...]Chunk {0x12631A5CF5D3ED,0xF9DEA2F79CD658,0x14DE,0x0,0x10000000}
+//  var CURVE_Gx = [...]Chunk {0x562D608F25D51A,0xC7609525A7B2C9,0x31FDD6DC5C692C,0xCD6E53FEC0A4E2,0x216936D3}
+//  var CURVE_Gy = [...]Chunk {0x66666666666658,0x66666666666666,0x66666666666666,0x66666666666666,0x66666666}
+
+// NIST-256 Curve
+//  const CURVETYPE int=WEIERSTRASS
+//  const CURVE_A int = -3
+//  var CURVE_B = [...]Chunk {0xCE3C3E27D2604B,0x6B0CC53B0F63B,0x55769886BC651D,0xAA3A93E7B3EBBD,0x5AC635D8}
+//  var CURVE_Order = [...]Chunk {0xB9CAC2FC632551,0xFAADA7179E84F3,0xFFFFFFFFFFBCE6,0xFFFFFF,0xFFFFFFFF}
+//  var CURVE_Gx =[...]Chunk {0xA13945D898C296,0x7D812DEB33A0F4,0xE563A440F27703,0xE12C4247F8BCE6,0x6B17D1F2}
+//  var CURVE_Gy =[...]Chunk {0xB6406837BF51F5,0x33576B315ECECB,0x4A7C0F9E162BCE,0xFE1A7F9B8EE7EB,0x4FE342E2}
+
+// MF254 Modulus, Weierstrass Curve w-254-mont
+//  const CURVETYPE int= WEIERSTRASS
+//  const CURVE_A int = -3
+//  var CURVE_B = [...]Chunk {0xFFFFFFFFFFD08D,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0x3F80FFFF}
+//  var CURVE_Order=[...]Chunk {0xA419C4AF8DF83F,0x8BEA0DA375C06F,0xFFFFFFFFFFEB81,0xFFFFFFFFFFFFFF,0x3F80FFFF}
+//  var CURVE_Gx =[...]Chunk {0x2,0x0,0x0,0x0,0x0}
+//  var CURVE_Gy =[...]Chunk {0x65DF37F90D4EBC,0x38E3F8511931AD,0x75BD778AEBDFB7,0x3B2E56014AE15A,0x140E3FD3}
+
+// MF254 Modulus, Edwards Curve ed-254-mont
+//  const CURVETYPE int= EDWARDS
+//  const CURVE_A int= -1
+//  var CURVE_B = [...]Chunk {0x367B,0x0,0x0,0x0,0x0}
+//  var CURVE_Order=[...]Chunk {0xF3D3FEC46E98C7,0x306C8BD62FB0EA,0xFFFFFFFFFFEB95,0xFFFFFFFFFFFFFF,0xFE03FFF}
+//  var CURVE_Gx =[...]Chunk {0x1,0x0,0x0,0x0,0x0}
+//  var CURVE_Gy =[...]Chunk {0x52D0FDAF2701E5,0x9A840E3212187C,0xD502363F4E3632,0xD6A4C335951D00,0x19F0E690}
+
+// MF254 Modulus, Montgomery Curve
+//  const CURVETYPE int=MONTGOMERY
+//  const CURVE_A int= -55790
+//  var CURVE_B = [...]Chunk {0x0,0x0,0x0,0x0,0x0} // not used
+//  var CURVE_Order=[...]Chunk {0xF3D3FEC46E98C7,0x306C8BD62FB0EA,0xFFFFFFFFFFEB95,0xFFFFFFFFFFFFFF,0xFE03FFF}
+//  var CURVE_Gx =[...]Chunk {0x3,0x0,0x0,0x0,0x0}
+//  var CURVE_Gy =[...]Chunk {0x0,0x0,0x0,0x0,0x0} // not used
+
+// MS255 Modulus, Weierstrass Curve
+//  const CURVETYPE int= WEIERSTRASS
+//  const CURVE_A int= -3
+//  var CURVE_B = [...]Chunk {0xFFFFFFFFFFAB46,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0x7FFFFFFF}
+//  var CURVE_Order=[...]Chunk {0x8FAC983C594AEB,0x38283AD2B3DFAB,0xFFFFFFFFFF864A,0xFFFFFFFFFFFFFF,0x7FFFFFFF}
+//  var CURVE_Gx =[...]Chunk {0x1,0x0,0x0,0x0,0x0};
+//  var CURVE_Gy =[...]Chunk {0x33FF6769CB44BA,0xC78CDDFDA60D17,0xF9B2FF7D177DB6,0xEDBA7833921EBF,0x6F7A6AC0}
+
+// MS255 Modulus, Edwards Curve
+//  const CURVETYPE int= EDWARDS
+//  const CURVE_A int= -1
+//  var CURVE_B = [...]Chunk{0xEA97,0x0,0x0,0x0,0x0}
+//  var CURVE_Order=[...]Chunk{0x49D1ED0436EB75,0xA785EDA6832EAC,0xFFFFFFFFFFDCF1,0xFFFFFFFFFFFFFF,0x1FFFFFFF}
+//  var CURVE_Gx =[...]Chunk{0x4,0x0,0x0,0x0,0x0}
+//  var CURVE_Gy =[...]Chunk{0x2A255BD08736A0,0x4B8AED445A45BA,0xDD8E0C47E55291,0x4A7BB545EC254C,0x26CB7853}
+
+// MS255 Modulus, Montgomery Curve
+//  const CURVETYPE int=MONTGOMERY
+//  const CURVE_A int=-240222
+//  var CURVE_B = [...]Chunk {0x0,0x0,0x0,0x0,0x0}
+//  var CURVE_Order=[...]Chunk {0x49D1ED0436EB75,0xA785EDA6832EAC,0xFFFFFFFFFFDCF1,0xFFFFFFFFFFFFFF,0x1FFFFFFF}
+//  var CURVE_Gx =[...]Chunk {0x4,0x0,0x0,0x0,0x0}
+//  var CURVE_Gy =[...]Chunk {0x0,0x0,0x0,0x0,0x0};
+
+// MF256 Modulus, Weierstrass Curve
+//  const CURVETYPE int= WEIERSTRASS
+//  const CURVE_A int= -3
+//  var CURVE_B = [...]Chunk {0x14E6A,0x0,0x0,0x0,0x0}
+//  var CURVE_Order=[...]Chunk {0x10C5E1A79857EB,0x7513E6E5074B9D,0xFFFFFFFFFFFC51,0xFFFFFFFFFFFFFF,0xFFA7FFFF}
+//  var CURVE_Gx =[...]Chunk {0x1,0x0,0x0,0x0,0x0}
+//  var CURVE_Gy =[...]Chunk {0x7954C2B724D2A,0x47EB8D94DC6610,0x26123DAE289569,0xBE1808CE7BABBA,0x20887C87}
+
+// MF256, Edwards Curve
+//  const CURVETYPE int= EDWARDS
+//  const CURVE_A int= -1
+//  var CURVE_B = [...]Chunk {0x350A,0x0,0x0,0x0,0x0}
+//  var CURVE_Order=[...]Chunk {0xD92EDED8EC7BAB,0xBBAFB86733C966,0xFFFFFFFFFFB154,0xFFFFFFFFFFFFFF,0x3FE9FFFF}
+//  var CURVE_Gx =[...]Chunk {0x1,0x0,0x0,0x0,0x0}
+//  var CURVE_Gy =[...]Chunk {0xEAA722F2F3C908,0x5E648DFEA68D7D,0xF3DB2C1AACA0C0,0xF8CC4D5AEAEBEE,0xDAD8D4F8}
+
+// MF256 Modulus, Montgomery Curve
+//  const CURVETYPE int=MONTGOMERY
+//  const CURVE_A int= -54314
+//  var CURVE_B = [...]Chunk {0x0,0x0,0x0,0x0,0x0} // not used
+//  var CURVE_Order=[...]Chunk {0xD92EDED8EC7BAB,0xBBAFB86733C966,0xFFFFFFFFFFB154,0xFFFFFFFFFFFFFF,0x3FE9FFFF}
+//  var CURVE_Gx =[...]Chunk {0x8,0x0,0x0,0x0,0x0}
+//  var CURVE_Gy =[...]Chunk {0x0,0x0,0x0,0x0,0x0} // not used
+
+// MS256, Weierstrass Curve
+//  const CURVETYPE int= WEIERSTRASS
+//  const CURVE_A int= -3
+//  var CURVE_B = [...]Chunk {0x25581,0x0,0x0,0x0,0x0}
+//  var CURVE_Order=[...]Chunk {0xAB20294751A825,0x8275EA265C6020,0xFFFFFFFFFFE43C,0xFFFFFFFFFFFFFF,0xFFFFFFFF}
+//  var CURVE_Gx =[...]Chunk {0x1,0x0,0x0,0x0,0x0}
+//  var CURVE_Gy =[...]Chunk {0xF46306C2B56C77,0x2F9375894EC10B,0x6CCEEEDD6BD02C,0xC1E466D7FC82C9,0x696F1853}
+
+// MS256, Edwards Curve
+//  const CURVETYPE int= EDWARDS
+//  const CURVE_A int= -1
+//  var CURVE_B = [...]Chunk {0x3BEE,0x0,0x0,0x0,0x0}
+//  var CURVE_Order=[...]Chunk {0xB84E6F1122B4AD,0xA55AD0A6BC64E5,0xFFFFFFFFFFBE6A,0xFFFFFFFFFFFFFF,0x3FFFFFFF}
+//  var CURVE_Gx =[...]Chunk {0xD,0x0,0x0,0x0,0x0}
+//  var CURVE_Gy =[...]Chunk {0x7F6FB5331CADBA,0x6D63824D303F70,0xB39FA046BFBE2A,0x2A1276DBA3D330,0x7D0AB41E}
+
+// MS256 Modulus, Montgomery Curve
+//  const CURVETYPE int=MONTGOMERY
+//  const CURVE_A int=-61370
+//  var CURVE_B = [...]Chunk  {0x0,0x0,0x0,0x0,0x0} // not used
+//  var CURVE_Order= [...]Chunk {0xB84E6F1122B4AD,0xA55AD0A6BC64E5,0xFFFFFFFFFFBE6A,0xFFFFFFFFFFFFFF,0x3FFFFFFF}
+//  var CURVE_Gx = [...]Chunk {0xb,0x0,0x0,0x0,0x0}
+//  var CURVE_Gy = [...]Chunk {0x0,0x0,0x0,0x0,0x0} // not used
+
+// Brainpool
+//  const CURVETYPE int= WEIERSTRASS
+//  const CURVE_A int= -3
+//  var CURVE_B = [...]Chunk  {0xE58101FEE92B04,0xEBC4AF2F49256A,0x733D0B76B7BF93,0x30D84EA4FE66A7,0x662C61C4}
+//  var CURVE_Order= [...]Chunk {0x1E0E82974856A7,0x7AA3B561A6F790,0x909D838D718C39,0xA1EEA9BC3E660A,0xA9FB57DB}
+//  var CURVE_Gx = [...]Chunk {0xA191562E1305F4,0x42C47AAFBC2B79,0xB23A656149AFA1,0xC1CFE7B7732213,0xA3E8EB3C}
+//  var CURVE_Gy = [...]Chunk {0xABE8F35B25C9BE,0xB6DE39D027001D,0xE14644417E69BC,0x3439C56D7F7B22,0x2D996C82}
+
+// ANSSI
+//  const CURVETYPE int= WEIERSTRASS
+//  const CURVE_A int= -3
+//  var CURVE_B = [...]Chunk  {0x75ED967B7BB73F,0xC9AE4B1A18030,0x754A44C00FDFEC,0x5428A9300D4ABA,0xEE353FCA}
+//  var CURVE_Order=[...]Chunk  {0xFDD459C6D655E1,0x67E140D2BF941F,0xE8CE42435B53DC,0xB3AD58F10126D,0xF1FD178C}
+//  var CURVE_Gx =[...]Chunk  {0xC97A2DD98F5CFF,0xD2DCAF98B70164,0x4749D423958C27,0x56C139EB31183D,0xB6B3D4C3}
+//  var CURVE_Gy =[...]Chunk  {0x115A1554062CFB,0xC307E8E4C9E183,0xF0F3ECEF8C2701,0xC8B204911F9271,0x6142E0F7}
+
+// HIFIVE
+//  const CURVETYPE int= EDWARDS
+//  const CURVE_A int= 1
+//  var CURVE_B = [...]Chunk  {0x2B67,0x0,0x0,0x0,0x0,0x0}
+//  var CURVE_Order=[...]Chunk  {0xB2F95973E9FA805,0xC0BD6B87F93BAA7,0x71415FA9850,0x0,0x0,0x200000000}
+//  var CURVE_Gx =[...]Chunk  {0xC,0x0,0x0,0x0,0x0,0x0}
+//  var CURVE_Gy =[...]Chunk  {0x2BEC68505FE8632,0x5D5650CA0365DB1,0x3811C7EF435B6DB,0x7853D1B14B46C,0x56502E18E1C161D,0xC0DC616B}
+
+// GOLDILOCKS
+//  const CURVETYPE int= EDWARDS
+//  const CURVE_A int= 1
+//  var CURVE_B = [...]Chunk  {0xFFFFFFFFFFF6756,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFEFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFF}
+//  var CURVE_Order=[...]Chunk  {0x378C292AB5844F3,0x6CC2728DC58F552,0xEDB49AED6369021,0xFFFF7CCA23E9C44,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0x3FFFFFF}
+//  var CURVE_Gx =[...]Chunk  {0x555555555555555,0x555555555555555,0x555555555555555,0xAAA955555555555,0xAAAAAAAAAAAAAAA,0xAAAAAAAAAAAAAAA,0xAAAAAAAAAAAAAAA,0xAAAAAAA}
+//  var CURVE_Gy =[...]Chunk  {0xAEAFBCDEA9386ED,0xBCB2BED1CDA06BD,0x565833A2A3098BB,0x6D728AD8C4B80D6,0x7A035884DD7B7E3,0x205086C2B0036ED,0x34AD7048DB359D6,0xAE05E96}
+
+// NIST384
+//  const CURVETYPE int= WEIERSTRASS
+//  const CURVE_A int= -3
+//  var CURVE_B = [...]Chunk  {0xA85C8EDD3EC2AEF,0x56398D8A2ED19D2,0x4088F5013875AC6,0x9C6EFE814112031,0x56BE3F82D19181D,0xA7E23EE7E4988E0,0xB3312F}
+//  var CURVE_Order=[...]Chunk  {0xCEC196ACCC52973,0x1A0DB248B0A77AE,0x34D81F4372DDF58,0xFFFFFFFFFFFFC76,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFF}
+//  var CURVE_Gx =[...]Chunk  {0xA545E3872760AB7,0x2F25DBF55296C3,0x741E082542A3855,0x3B628BA79B9859F,0x71EF320AD746E1D,0x22BE8B05378EB1C,0xAA87CA}
+//  var CURVE_Gy =[...]Chunk  {0xA431D7C90EA0E5F,0x60B1CE1D7E819D7,0xA3113B5F0B8C00A,0x1DBD289A147CE9D,0x8BF9292DC29F8F4,0x4A96262C6F5D9E9,0x3617DE}
+
+// C41417
+//  const CURVETYPE int= EDWARDS
+//  const CURVE_A int= 1
+//  var CURVE_B = [...]Chunk  {0xE21,0x0,0x0,0x0,0x0,0x0,0x0}
+//  var CURVE_Order=[...]Chunk  {0xB0E71A5E106AF79,0x1C0338AD63CF181,0x414CF706022B36F,0xFFFFFFFFEB3CC92,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0x7FFFFFFFFFFFF}
+//  var CURVE_Gx =[...]Chunk  {0x4FD3812F3CBC595,0x1A73FAA8537C64C,0x4AB4D6D6BA11130,0x3EC7F57FF35498A,0xE5FCD46369F44C0,0x300218C0631C326,0x1A334905141443}
+//  var CURVE_Gy =[...]Chunk  {0x22,0x0,0x0,0x0,0x0,0x0,0x0}
+
+// NIST521
+//  const CURVETYPE int= WEIERSTRASS
+//  const CURVE_A int= -3
+//  var CURVE_B = [...]Chunk  {0xF451FD46B503F00,0x73DF883D2C34F1E,0x2C0BD3BB1BF0735,0x3951EC7E937B165,0x9918EF109E15619,0x5B99B315F3B8B48,0xB68540EEA2DA72,0x8E1C9A1F929A21A,0x51953EB961}
+//  var CURVE_Order=[...]Chunk  {0xB6FB71E91386409,0xB5C9B8899C47AEB,0xC0148F709A5D03B,0x8783BF2F966B7FC,0xFFFFFFFFFFA5186,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0x1FFFFFFFFFF}
+//  var CURVE_Gx =[...]Chunk  {0x97E7E31C2E5BD66,0x48B3C1856A429BF,0xDC127A2FFA8DE33,0x5E77EFE75928FE1,0xF606B4D3DBAA14B,0x39053FB521F828A,0x62395B4429C6481,0x404E9CD9E3ECB6,0xC6858E06B7}
+//  var CURVE_Gy =[...]Chunk  {0x8BE94769FD16650,0x3C7086A272C2408,0xB9013FAD076135,0x72995EF42640C55,0xD17273E662C97EE,0x49579B446817AFB,0x42C7D1BD998F544,0x9A3BC0045C8A5FB,0x11839296A78}
+
+
+// BN646 Curve
+/*
+const CURVETYPE int=WEIERSTRASS
+const CURVE_PAIRING_TYPE int=BN_CURVE
+const CURVE_A int= 0
+
+var CURVE_Order=[...]Chunk {0x2406C07E04200D,0x2405103F0108000,0xD418607E0000000,0x301B00000901441,0x400000006C0A206,0xD814422E14402,0x6C051024000000,0xD8000000000000,0x9006C,0x240000,0x240000000000}
+var CURVE_B = [...]Chunk {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Cof = [...]Chunk {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Gx =[...]Chunk {0x2406C08404E012,0x240510420138000,0xE01920840000000,0x601B00000901441,0x400000006C0A206,0xD814423414402,0x6C051024000000,0xD8000000000000,0x9006C,0x240000,0x240000000000}
+var CURVE_Gy =[...]Chunk {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+
+var CURVE_Bnx=[...]Chunk {0x1001,0x4000,0x10000000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Cru=[...]Chunk {0x1202401B007,0xD812006C000,0x480510240000000,0x200480000000360,0x1B01,0x3602403600,0xD800000000,0x0,0x12,0x0,0x0}
+var CURVE_Fra=[...]Chunk {0x76EAD944929A14,0xB7E0A0BE10CDF74,0x4FB8A8A2B93166B,0xECDFC4B0F037D9,0xC27307962815598,0xCF5EF558D2135D8,0x8CE651FD85AF9C3,0x80AF6D02A45219F,0x69B8147979A41A4,0x9577C152A374C5B,0x9FF28B3A478}
+var CURVE_Frb=[...]Chunk {0xFAD1BE73F7245FF,0x6C246F83F06A08B,0x906077E146CE994,0x514D03B4F9FDC68,0x7D8CF86A43F4C6E,0x31791EE96200E29,0x79D9FF04BA5063C,0x8CD092FD5BADE60,0x9647EB8686EBEC7,0x6A883EAD5ECB3A4,0x1A00D74C5B87}
+var CURVE_Pxa=[...]Chunk {0x4233F273CCC5E10,0x6408117FB1B1FFA,0xA7978AC166486AA,0xDA6417BDCFDC1D0,0xDCE981D68FA7F5C,0x4169ED790F45048,0xBA06CCE894F26BE,0xB0C98247FD18141,0x30CE35212F353A6,0xFF9A1B9162B0B9E,0xFD835F078BF}
+var CURVE_Pxb=[...]Chunk {0x837F879267F4BC0,0x443F1581FA770ED,0x8FBA0763CB82027,0xA8F7E5DE4945F11,0x780AAE5D219F786,0xF3BB745205342E9,0xCC0A34FF057013C,0xA6DFAF3E689709E,0xD69FBD8D12B6B79,0x6A1715D9469215D,0x1764FA509C41}
+var CURVE_Pya=[...]Chunk {0xC570D1DCC3FB414,0xD0ABFE7F36161E4,0xABA2F61496C849A,0x4E4A05030CD4F3F,0x70F7CECD5CEF83,0x9D4711CBF491613,0xDF8011EA770418E,0x56548E514EC94EC,0xC9E853DFF35EE42,0x5481ABBAAD13633,0x78D8A63783F}
+var CURVE_Pyb=[...]Chunk {0xAFE3E3DB33908AD,0x7CD4290A506594C,0xFA043D85973EC3F,0xFAC7A642BB5E628,0x71A36A52DA82EE2,0x12C2231EDAE0C76,0x994DF2771091B48,0xCFFF7637B76831C,0xD463BD03DA14916,0x1074F23C580C40,0x12188D99546B}
+var CURVE_W=[2][NLEN]Chunk {{0x6008003,0x30020000,0xC0080060000000,0x300000000000000,0x0,0x600000,0x0,0x0,0x0,0x0,0x0},{0x2001,0x8000,0x20000000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}
+var CURVE_SB=[2][2][NLEN]Chunk {{{0x600A004,0x30028000,0xC00A0060000000,0x300000000000000,0x0,0x600000,0x0,0x0,0x0,0x0,0x0},{0x2001,0x8000,0x20000000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x2001,0x8000,0x20000000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x2406C07803A00A,0x2405103C00E8000,0xC817E0780000000,0x1B00000901441,0x400000006C0A206,0xD814422814402,0x6C051024000000,0xD8000000000000,0x9006C,0x240000,0x240000000000}}}
+var CURVE_WB=[4][NLEN]Chunk {{0x2001000,0x10004000,0x40010020000000,0x100000000000000,0x0,0x200000,0x0,0x0,0x0,0x0,0x0},{0xC01C015005,0x900E0054000,0x3803901C0000000,0xE00300000000240,0x1200,0x2401C02400,0x9000000000,0x0,0xC,0x0,0x0},{0x600E00B003,0x4807002C000,0x1C01D00E0000000,0x700180000000120,0x900,0x1200E01200,0x4800000000,0x0,0x6,0x0,0x0},{0x2003001,0x1000C000,0x40030020000000,0x100000000000000,0x0,0x200000,0x0,0x0,0x0,0x0,0x0}}
+var CURVE_BB=[4][4][NLEN]Chunk {{{0x2406C07E04100D,0x2405103F0104000,0xD418507E0000000,0x301B00000901441,0x400000006C0A206,0xD814422E14402,0x6C051024000000,0xD8000000000000,0x9006C,0x240000,0x240000000000},{0x2406C07E04100C,0x2405103F0104000,0xD418507E0000000,0x301B00000901441,0x400000006C0A206,0xD814422E14402,0x6C051024000000,0xD8000000000000,0x9006C,0x240000,0x240000000000},{0x2406C07E04100C,0x2405103F0104000,0xD418507E0000000,0x301B00000901441,0x400000006C0A206,0xD814422E14402,0x6C051024000000,0xD8000000000000,0x9006C,0x240000,0x240000000000},{0x2002,0x8000,0x20000000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x2001,0x8000,0x20000000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x2406C07E04100C,0x2405103F0104000,0xD418507E0000000,0x301B00000901441,0x400000006C0A206,0xD814422E14402,0x6C051024000000,0xD8000000000000,0x9006C,0x240000,0x240000000000},{0x2406C07E04100D,0x2405103F0104000,0xD418507E0000000,0x301B00000901441,0x400000006C0A206,0xD814422E14402,0x6C051024000000,0xD8000000000000,0x9006C,0x240000,0x240000000000},{0x2406C07E04100C,0x2405103F0104000,0xD418507E0000000,0x301B00000901441,0x400000006C0A206,0xD814422E14402,0x6C051024000000,0xD8000000000000,0x9006C,0x240000,0x240000000000}},{{0x2002,0x8000,0x20000000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x2001,0x8000,0x20000000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x2001,0x8000,0x20000000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x2001,0x8000,0x20000000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x1002,0x4000,0x10000000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x4002,0x10000,0x40000000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x2406C07E04000A,0x2405103F0100000,0xD418407E0000000,0x301B00000901441,0x400000006C0A206,0xD814422E14402,0x6C051024000000,0xD8000000000000,0x9006C,0x240000,0x240000000000},{0x1002,0x4000,0x10000000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}}
+
+const USE_GLV bool=true
+const USE_GS_G2 bool=true
+const USE_GS_GT bool=true	
+const GT_STRONG bool=false
+*/
+// BNCX Curve 
+/*
+const CURVETYPE int=WEIERSTRASS
+const CURVE_PAIRING_TYPE int=BN_CURVE
+const CURVE_A int= 0
+var CURVE_B = [...]Chunk {0x2,0x0,0x0,0x0,0x0}
+var CURVE_Cof = [...]Chunk {0x1,0x0,0x0,0x0,0x0}
+
+var CURVE_Order=[...]Chunk {0x11C0A636EB1F6D,0xD6EE0CC906CEBE,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000}
+var CURVE_Bnx=[...]Chunk {0x3C012B1,0x40,0x0,0x0,0x0}
+var CURVE_Cru=[...]Chunk {0xE0931794235C97,0xDF6471EF875631,0xCA83F1440BD,0x480000,0x0}
+var CURVE_Fra=[...]Chunk {0xD9083355C80EA3,0x7326F173F8215B,0x8AACA718986867,0xA63A0164AFE18B,0x1359082F}
+var CURVE_Frb=[...]Chunk {0x8D1BBC06534710,0x63C7269546C062,0xD9CDBC4E3ABBD8,0x623628A900DC53,0x10A6F7D0}
+var CURVE_Pxa=[...]Chunk {0x851CEEE4D2EC74,0x85BFA03E2726C0,0xF5C34BBB907C,0x7053B256358B25,0x19682D2C}
+var CURVE_Pxb=[...]Chunk {0xA58E8B2E29CFE1,0x97B0C209C30F47,0x37A8E99743F81B,0x3E19F64AA011C9,0x1466B9EC}
+var CURVE_Pya=[...]Chunk {0xFBFCEBCF0BE09F,0xB33D847EC1B30C,0x157DAEE2096361,0x72332B8DD81E22,0xA79EDD9}
+var CURVE_Pyb=[...]Chunk {0x904B228898EE9D,0x4EA569D2EDEBED,0x512D8D3461C286,0xECC4C09035C6E4,0x6160C39}
+var CURVE_Gx =[...]Chunk {0x6623EF5C1B55B2,0xD6EE18093EE1BE,0x647A6366D3243F,0x8702A0DB0BDDF,0x24000000}
+var CURVE_Gy =[...]Chunk {0x1,0x0,0x0,0x0,0x0}
+var CURVE_W=[2][5]Chunk{{0x546349162FEB83,0xB40381200,0x6000,0x0,0x0},{0x7802561,0x80,0x0,0x0,0x0}}
+var CURVE_SB=[2][2][5]Chunk {{{0x5463491DB010E4,0xB40381280,0x6000,0x0,0x0},{0x7802561,0x80,0x0,0x0,0x0}},{{0x7802561,0x80,0x0,0x0,0x0},{0xBD5D5D20BB33EA,0xD6EE0188CEBCBD,0x647A6366D2643F,0x8702A0DB0BDDF,0x24000000}}}
+var CURVE_WB=[4][5]Chunk {{0x1C2118567A84B0,0x3C012B040,0x2000,0x0,0x0},{0xCDF995BE220475,0x94EDA8CA7F9A36,0x8702A0DC07E,0x300000,0x0},{0x66FCCAE0F10B93,0x4A76D4653FCD3B,0x4381506E03F,0x180000,0x0},{0x1C21185DFAAA11,0x3C012B0C0,0x2000,0x0,0x0}}
+var CURVE_BB=[4][4][5]Chunk {{{0x11C0A6332B0CBD,0xD6EE0CC906CE7E,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000},{0x11C0A6332B0CBC,0xD6EE0CC906CE7E,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000},{0x11C0A6332B0CBC,0xD6EE0CC906CE7E,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000},{0x7802562,0x80,0x0,0x0,0x0}},{{0x7802561,0x80,0x0,0x0,0x0},{0x11C0A6332B0CBC,0xD6EE0CC906CE7E,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000},{0x11C0A6332B0CBD,0xD6EE0CC906CE7E,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000},{0x11C0A6332B0CBC,0xD6EE0CC906CE7E,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000}},{{0x7802562,0x80,0x0,0x0,0x0},{0x7802561,0x80,0x0,0x0,0x0},{0x7802561,0x80,0x0,0x0,0x0},{0x7802561,0x80,0x0,0x0,0x0}},{{0x3C012B2,0x40,0x0,0x0,0x0},{0xF004AC2,0x100,0x0,0x0,0x0},{0x11C0A62F6AFA0A,0xD6EE0CC906CE3E,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000},{0x3C012B2,0x40,0x0,0x0,0x0}}}
+
+const USE_GLV bool=true
+const USE_GS_G2 bool=true
+const USE_GS_GT bool=true	
+const GT_STRONG bool=true
+
+*/
+// BN254 Curve
+/*
+const CURVETYPE int=WEIERSTRASS
+const CURVE_PAIRING_TYPE int=BN_CURVE
+const CURVE_A int= 0
+var CURVE_B = [...]Chunk {0x2,0x0,0x0,0x0,0x0}
+var CURVE_Cof = [...]Chunk {0x1,0x0,0x0,0x0,0x0}
+var CURVE_Order=[...]Chunk {0xD,0x800000000010A1,0x8000000007FF9F,0x40000001BA344D,0x25236482}
+var CURVE_Bnx=[...]Chunk {0x80000000000001,0x40,0x0,0x0,0x0}
+var CURVE_Cru=[...]Chunk {0x80000000000007,0x6CD,0x40000000024909,0x49B362,0x0}
+var CURVE_Fra=[...]Chunk {0x7DE6C06F2A6DE9,0x74924D3F77C2E1,0x50A846953F8509,0x212E7C8CB6499B,0x1B377619}
+var CURVE_Frb=[...]Chunk {0x82193F90D5922A,0x8B6DB2C08850C5,0x2F57B96AC8DC17,0x1ED1837503EAB2,0x9EBEE69}
+var CURVE_Pxa=[...]Chunk {0xEE4224C803FB2B,0x8BBB4898BF0D91,0x7E8C61EDB6A464,0x519EB62FEB8D8C,0x61A10BB}
+var CURVE_Pxb=[...]Chunk {0x8C34C1E7D54CF3,0x746BAE3784B70D,0x8C5982AA5B1F4D,0xBA737833310AA7,0x516AAF9}
+var CURVE_Pya=[...]Chunk {0xF0E07891CD2B9A,0xAE6BDBE09BD19,0x96698C822329BD,0x6BAF93439A90E0,0x21897A0}
+var CURVE_Pyb=[...]Chunk {0x2D1AEC6B3ACE9B,0x6FFD739C9578A,0x56F5F38D37B090,0x7C8B15268F6D44,0xEBB2B0E}
+var CURVE_Gx =[...]Chunk {0x12,0x13A7,0x80000000086121,0x40000001BA344D,0x25236482}
+var CURVE_Gy =[...]Chunk {0x1,0x0,0x0,0x0,0x0}
+var CURVE_W=[2][5]Chunk {{0x3,0x80000000000204,0x6181,0x0,0x0},{0x1,0x81,0x0,0x0,0x0}}
+var CURVE_SB=[2][2][5]Chunk {{{0x4,0x80000000000285,0x6181,0x0,0x0},{0x1,0x81,0x0,0x0,0x0}},{{0x1,0x81,0x0,0x0,0x0},{0xA,0xE9D,0x80000000079E1E,0x40000001BA344D,0x25236482}}}
+var CURVE_WB=[4][5]Chunk {{0x80000000000000,0x80000000000040,0x2080,0x0,0x0},{0x80000000000005,0x54A,0x8000000001C707,0x312241,0x0},{0x80000000000003,0x800000000002C5,0xC000000000E383,0x189120,0x0},{0x80000000000001,0x800000000000C1,0x2080,0x0,0x0}}
+var CURVE_BB=[4][4][5]Chunk {{{0x8000000000000D,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482},{0x8000000000000C,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482},{0x8000000000000C,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482},{0x2,0x81,0x0,0x0,0x0}},{{0x1,0x81,0x0,0x0,0x0},{0x8000000000000C,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482},{0x8000000000000D,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482},{0x8000000000000C,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482}},{{0x2,0x81,0x0,0x0,0x0},{0x1,0x81,0x0,0x0,0x0},{0x1,0x81,0x0,0x0,0x0},{0x1,0x81,0x0,0x0,0x0}},{{0x80000000000002,0x40,0x0,0x0,0x0},{0x2,0x102,0x0,0x0,0x0},{0xA,0x80000000001020,0x8000000007FF9F,0x40000001BA344D,0x25236482},{0x80000000000002,0x40,0x0,0x0,0x0}}}
+
+const USE_GLV bool=true
+const USE_GS_G2 bool=true
+const USE_GS_GT bool=true	
+const GT_STRONG bool=false
+*/
+// BN454 Curve
+/*
+const CURVETYPE int=WEIERSTRASS
+const CURVE_PAIRING_TYPE int=BN_CURVE
+const CURVE_A int= 0
+
+var CURVE_Order=[...]Chunk {0x420000000D,0x42006C4200007E0,0x2000144FC0024FC,0x887E01D4FC0091C,0x21C00021D4400DA,0x25B06C01B144009,0xD80000909000,0x240000900};
+var CURVE_B = [...]Chunk {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+var CURVE_Cof = [...]Chunk {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+var CURVE_Gx =[...]Chunk {0x4E00000012,0x4E006C4E0000840,0x800014508002508,0x888401D5080091C,0x21C00021D4400DA,0x25B06C01B144009,0xD80000909000,0x240000900};
+var CURVE_Gy =[...]Chunk {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+
+var CURVE_Bnx=[...]Chunk {0x100000001,0x10000010000000,0x0,0x0,0x0,0x0,0x0,0x0};
+var CURVE_Cru=[...]Chunk {0x1B00000007,0x1B00121B0000240,0xA00003648000048,0x6C2400364800005,0x36000012360000,0x12000036000,0x0,0x0};
+var CURVE_Fra=[...]Chunk {0x302DC9FD573B0EC,0x7AEEE6C3A90B9B8,0xD06B734A02B17EC,0xDBD9562D6A87D,0x929326ECAFCB5A2,0x32139C5D6DDCE26,0x7A687EBE1CCD92B,0x12E79EC72};
+var CURVE_Frb=[...]Chunk {0xCFD23AE2A8C4F27,0xD311858A56F4E87,0xAF94A1067D50D1B,0x87A8287EDA9609E,0x8F2CD9352474B38,0xF39CCFA443671E2,0x85A50141EC3B6D4,0x111861C8D};
+var CURVE_Pxa=[...]Chunk {0xFBA3BAC20F02B14,0x6BC30BEF0CC2BB1,0xFE2DA6B5FCEFFF3,0x3682EDFC1FE1E7E,0xAD66CC979483454,0xE163BB5D98CBBA1,0xD55083668F14AAF,0x1403D4F80};
+var CURVE_Pxb=[...]Chunk {0x9C06D0EC45BF266,0x365ACBB7823C36E,0xD2E4624790DBC52,0xE0803BE6F2F769F,0x7BA9E2AA951971D,0x25841737EBE5665,0x142E8014B1E40D5,0x15952D69E};
+var CURVE_Pya=[...]Chunk {0x939AB6BBE1B15C7,0xDF26024555C6CB4,0x671C46519474FB5,0xBAA277A8FC5DD54,0xB00871EE82F2FAA,0xFE0A26E1C64C3A,0x7ABC6DB12C5287A,0x1D67A4004};
+var CURVE_Pyb=[...]Chunk {0xC10E6FB60571D60,0xE9271847B128D8E,0xBE70ED2753A65C7,0x75C2604B7433768,0x4F0B46811003851,0xD91F0CA48ABC5EA,0x842C9ADF53F903E,0x976E2360};
+var CURVE_W=[2][8]Chunk {{0x800000003,0x80000080000060,0x60000000C00000C,0x600000C00000,0x0,0x0,0x0,0x0},{0x200000001,0x20000020000000,0x0,0x0,0x0,0x0,0x0,0x0}};
+var CURVE_SB=[2][2][8]Chunk {{{0xA00000004,0xA00000A0000060,0x60000000C00000C,0x600000C00000,0x0,0x0,0x0,0x0},{0x200000001,0x20000020000000,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x200000001,0x20000020000000,0x0,0x0,0x0,0x0,0x0,0x0},{0x3A0000000A,0x3A006C3A0000780,0xC000144F00024F0,0x887801D4F00091B,0x21C00021D4400DA,0x25B06C01B144009,0xD80000909000,0x240000900}}};
+var CURVE_WB=[4][8]Chunk {{0x100000000,0x10000010000020,0x200000004000004,0x200000400000,0x0,0x0,0x0,0x0},{0x1500000005,0x15000C1500001C0,0x2438000038,0x481C00243800004,0x2400000C240000,0xC000024000,0x0,0x0},{0xB00000003,0xB00060B00000E0,0x121C00001C,0x240E00121C00002,0x12000006120000,0x6000012000,0x0,0x0},{0x300000001,0x30000030000020,0x200000004000004,0x200000400000,0x0,0x0,0x0,0x0}};
+var CURVE_BB=[4][4][8]Chunk {{{0x410000000D,0x41006C4100007E0,0x2000144FC0024FC,0x887E01D4FC0091C,0x21C00021D4400DA,0x25B06C01B144009,0xD80000909000,0x240000900},{0x410000000C,0x41006C4100007E0,0x2000144FC0024FC,0x887E01D4FC0091C,0x21C00021D4400DA,0x25B06C01B144009,0xD80000909000,0x240000900},{0x410000000C,0x41006C4100007E0,0x2000144FC0024FC,0x887E01D4FC0091C,0x21C00021D4400DA,0x25B06C01B144009,0xD80000909000,0x240000900},{0x200000002,0x20000020000000,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x200000001,0x20000020000000,0x0,0x0,0x0,0x0,0x0,0x0},{0x410000000C,0x41006C4100007E0,0x2000144FC0024FC,0x887E01D4FC0091C,0x21C00021D4400DA,0x25B06C01B144009,0xD80000909000,0x240000900},{0x410000000D,0x41006C4100007E0,0x2000144FC0024FC,0x887E01D4FC0091C,0x21C00021D4400DA,0x25B06C01B144009,0xD80000909000,0x240000900},{0x410000000C,0x41006C4100007E0,0x2000144FC0024FC,0x887E01D4FC0091C,0x21C00021D4400DA,0x25B06C01B144009,0xD80000909000,0x240000900}},{{0x200000002,0x20000020000000,0x0,0x0,0x0,0x0,0x0,0x0},{0x200000001,0x20000020000000,0x0,0x0,0x0,0x0,0x0,0x0},{0x200000001,0x20000020000000,0x0,0x0,0x0,0x0,0x0,0x0},{0x200000001,0x20000020000000,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x100000002,0x10000010000000,0x0,0x0,0x0,0x0,0x0,0x0},{0x400000002,0x40000040000000,0x0,0x0,0x0,0x0,0x0,0x0},{0x400000000A,0x40006C4000007E0,0x2000144FC0024FC,0x887E01D4FC0091C,0x21C00021D4400DA,0x25B06C01B144009,0xD80000909000,0x240000900},{0x100000002,0x10000010000000,0x0,0x0,0x0,0x0,0x0,0x0}}};
+
+const USE_GLV bool=true
+const USE_GS_G2 bool=true
+const USE_GS_GT bool=true	
+const GT_STRONG bool=false
+*/
+
+
+// BLS383 Curve
+
+const CURVETYPE int=WEIERSTRASS
+const CURVE_PAIRING_TYPE int=BLS_CURVE
+const CURVE_A int= 0
+
+var CURVE_Order=[...]Chunk {0xFFF80000FFF001,0xBFDE0070FE7800,0x3000049C5EDF1C,0xC40007F910007A,0x14641004C,0x0,0x0};
+var CURVE_B = [...]Chunk {0x9,0x0,0x0,0x0,0x0,0x0,0x0};
+var CURVE_Cof = [...]Chunk {0x2A00000052B,0x5560AAAAAB2CA0,0x6055,0x0,0x0,0x0,0x0};
+var CURVE_Gx =[...]Chunk {0xD59B348D10786B,0x3477C0E3F54AD0,0xBF25B734578B9B,0x4F6AC007BB6F65,0xEFD5830FF57E9C,0xADB9F88FB6EC02,0xB08CEE4BC98};
+var CURVE_Gy =[...]Chunk {0x5DA023D145DDB,0x13F518C5FEF7CC,0x56EC3462B2A66F,0x96F3019C7A925F,0x9061047981223E,0x4810AD8F5BE59,0x1F3909337671};
+
+var CURVE_Bnx=[...]Chunk {0x1000000040,0x110,0x0,0x0,0x0,0x0,0x0};
+var CURVE_Cru=[...]Chunk {0xA3AAC4EDA155A9,0xDF2FE8761E5E3D,0xBCDFAADE632625,0x5123128D3035A6,0xDBF3A2BBEAD683,0x5C5FAB20424190,0x7AC52080A9F7};
+var CURVE_Fra=[...]Chunk {0x2BA59A92B4508B,0x63DB7A06EEF343,0x40341CB1DFBC74,0x1639E9D32D55D3,0xB19B3F05CC36D4,0xF323EE4D86AB98,0x5A5FB198672};
+var CURVE_Frb=[...]Chunk {0x81051A97F904E0,0xB7D49A6F086A37,0x8F3EEB8B7DB8AB,0xEEF7983C6C9543,0x7A65F6549CB35D,0x693D1777CBFBEC,0x751F25672384};
+var CURVE_Pxa=[...]Chunk {0x6059885BAC9472,0x7C4D31DE2DC36D,0xBDC90C308C88A7,0x29F01971C688FC,0x3693539C43F167,0xD81E5A561EB8BF,0x4D50722B56BF};
+var CURVE_Pxb=[...]Chunk {0x9B4BD7A272AB23,0x7AF19D4F44DCE8,0x3F6F7B93206A34,0x571DD3E2A819FB,0x3A2BA3B635D7EE,0xAC28C780C1A126,0xEE3617C3E5B};
+var CURVE_Pya=[...]Chunk {0x81D230977BD4FD,0xB660720DFDFC6,0x41FC9590C89A0C,0x2E1FBCF878287A,0x11C23014EEE65,0x28878816BB325E,0x8F40859A05C};
+var CURVE_Pyb=[...]Chunk {0xA5E20A252C4CE6,0x5907A74AFF40C8,0x41760A42448EF3,0xFFEF82B0FDA199,0xA0F29A18D4EA49,0xAC7F7B86E4997B,0x1DCABBA88C12};
+
+// Not used
+var CURVE_W=[2][7]Chunk {{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+var CURVE_SB=[2][2][7]Chunk {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+var CURVE_WB=[4][7]Chunk {{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+var CURVE_BB=[4][4][7]Chunk {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+
+const USE_GLV bool=true
+const USE_GS_G2 bool=true
+const USE_GS_GT bool=true	
+const GT_STRONG bool=false
+
+// BLS455 Curve
+/*
+const CURVETYPE int=WEIERSTRASS
+const CURVE_PAIRING_TYPE int=BLS_CURVE
+const CURVE_A int= 0
+
+var CURVE_Order=[...]Chunk {0x7FFFFC00001,0xA00000400001C,0x25E000750001D10,0xE0000F10004F000,0x80000380002,0x10,0x0,0x0};
+var CURVE_B = [...]Chunk {0xA,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+var CURVE_Cof = [...]Chunk {0xA9557FFAABFFAAB,0xAAB15555B54AAB6,0x555556AA,0x0,0x0,0x0,0x0,0x0};
+var CURVE_Gx =[...]Chunk {0x6D4C5DDFDFCEDD1,0x35C6F43B3A034FB,0x7F05B56A579C725,0xB1F2B8ECE11B321,0x9F342AB0CFE8392,0xA5911EE32767994,0x3005E40CC56ABED,0x18855F3B};
+var CURVE_Gy =[...]Chunk {0x404FD79A6619B9B,0x69D80A5D6FA0286,0xEE722322D91A493,0xB1EE58431C1E968,0xCA9BC8953801F5F,0xDFAFD40FE9E388E,0x9F8985FC3DEB0D6,0x19A8DB77E};
+
+var CURVE_Bnx=[...]Chunk {0x20000080000800,0x10000,0x0,0x0,0x0,0x0,0x0,0x0};
+var CURVE_Cru=[...]Chunk {0x9202FFC00000AA9,0xFA5190F4A3762A,0x8B2B9BDD548FEC9,0xD7B469DB33A586A,0xC91731354CAFD99,0xF5B48D02FFFE695,0x57955572A900E0E,0x555559555};
+var CURVE_Fra=[...]Chunk {0x9CCFBDCA2EBF21,0x572F54A73379964,0x72819F887545498,0x22BBC1CAD1F8534,0xA82CD7D435944F0,0x4594F818D030F7B,0xEDCBE3ADC0016A7,0x397EA4973};
+var CURVE_Frb=[...]Chunk {0xA033043B5D1438A,0x6E5A00C3F72FC06,0x4717AB46118C70E,0x16993AE842C0609,0x3B78DA012CA06E9,0x501F99EA300E6EA,0x69C971C4E9FF768,0x1BD6B4BE1};
+var CURVE_Pxa=[...]Chunk {0x475F20F0C1F542,0x65D6070F8567E10,0xD780698BB33D776,0x71F685ED1531721,0x303D3FEC5B6A49C,0x8DEF064FF553CEB,0xC0E9A31B4C463,0x2ECB12FA8};
+var CURVE_Pxb=[...]Chunk {0x99086EE6749F03D,0xE89A55A5AC5EF2E,0x7B41AECD88EA016,0x622450FE6163E06,0x755066E1C8E296F,0xA80F219487326E8,0x66DBFBB0BEAEE59,0xECFFCE0};
+var CURVE_Pya=[...]Chunk {0x83235A4581A77F4,0x9F0F367B7A7E10A,0x8FA0C4A66D55B9D,0xEF03F65E0D6EC4C,0x9C7DC299C1A9EC2,0x32453CA21CFA5AC,0x6C3DCD5ABB9C544,0x22471D90A};
+var CURVE_Pyb=[...]Chunk {0xF413B6D9E1FDBA2,0xA7E630913DA0356,0xFBC913D9AC488E2,0x72E7CF61B401585,0x656D801B21C89ED,0xF9E921EEE0558F9,0x3D2B7B03CFC8698,0x33503CA8};
+
+// Not used
+var CURVE_W=[2][8]Chunk {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+var CURVE_SB=[2][2][8]Chunk {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+var CURVE_WB=[4][8]Chunk {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+var CURVE_BB=[4][4][8]Chunk {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+
+const USE_GLV bool=true
+const USE_GS_G2 bool=true
+const USE_GS_GT bool=true	
+const GT_STRONG bool=false
+*/
+// BNT Curve
+/*
+const CURVETYPE int=WEIERSTRASS
+const CURVE_PAIRING_TYPE int=BN_CURVE
+const CURVE_A int= 0
+var CURVE_B = [...]Chunk {0x2,0x0,0x0,0x0,0x0}
+var CURVE_Cof = [...]Chunk {0x1,0x0,0x0,0x0,0x0}
+var CURVE_Order=[...]Chunk {0x75777E8D30210D,0xD43492B2CB363A,0x3696F8D5F00E88,0x6517014EFA0BAB,0x240120DB}
+var CURVE_Bnx=[...]Chunk {0x806000004081,0x40,0x0,0x0,0x0}
+var CURVE_Cru=[...]Chunk {0xEB53D5AB4FCD87,0x82A5F2BAB11FAD,0x47651504C9764C,0x4801B1,0x0}
+var CURVE_Fra=[...]Chunk {0xF5D14EADC80022,0x4904D6FACCE359,0xF190A13211BE6C,0xC9BBC4394F6509,0x1328A292}
+var CURVE_Frb=[...]Chunk {0xA7EAB040ECA6F1,0xC513DF997D764,0x450657A3DEB01E,0x9B5B3D15AAA6A1,0x10D87E48}
+var CURVE_Pxa=[...]Chunk {0x8987E2288E65BB,0xAD1CAA6313BE,0x325041548B7CCC,0x4C1339EBCC055,0x14483FCD}
+var CURVE_Pxb=[...]Chunk {0x67888808DBE2C0,0x7FE1F81E34853A,0xA631A51B57B95,0x384EC302DA3FC5,0x87F46B3}
+var CURVE_Pya=[...]Chunk {0x202C47E020CA1D,0xB4167E8399F36C,0xC6E5439F72C94C,0x102B0BD74A2C69,0x14E8C29C}
+var CURVE_Pyb=[...]Chunk {0xD8437C716628F2,0x27E167BCB7DC6B,0xA82C7572681D0A,0x62454BD1EDEC18,0x17AFE2A4}
+var CURVE_Gx =[...]Chunk {0x9DBBFEEEB4A712,0x555614F464BABE,0x3696F8D5F06E8A,0x6517014EFA0BAB,0x240120DB}
+var CURVE_Gy =[...]Chunk {0x1,0x0,0x0,0x0,0x0}
+var CURVE_W=[2][5]Chunk{{0x26430061838403,0x81218241998384,0x6001,0x0,0x0},{0x100C000008101,0x80,0x0,0x0,0x0}}
+var CURVE_SB=[2][2][5]Chunk {{{0x2743C061840504,0x81218241998404,0x6001,0x0,0x0},{0x100C000008101,0x80,0x0,0x0,0x0}},{{0x100C000008101,0x80,0x0,0x0,0x0},{0x4F347E2BAC9D0A,0x5313107131B2B6,0x3696F8D5EFAE87,0x6517014EFA0BAB,0x240120DB}}}
+var CURVE_WB=[4][5]Chunk {{0x6140602080C080,0x806080C08880C1,0x2000,0x0,0x0},{0xB53904088C4A85,0xAD2FA352DC6C36,0xDA436358868EDE,0x300120,0x0},{0x5ADCB204464583,0x5697D1A96E363B,0x6D21B1AC43476F,0x180090,0x0},{0x62412020814181,0x806080C0888141,0x2000,0x0,0x0}}
+var CURVE_BB=[4][4][5]Chunk {{{0x74F71E8D2FE08D,0xD43492B2CB35FA,0x3696F8D5F00E88,0x6517014EFA0BAB,0x240120DB},{0x74F71E8D2FE08C,0xD43492B2CB35FA,0x3696F8D5F00E88,0x6517014EFA0BAB,0x240120DB},{0x74F71E8D2FE08C,0xD43492B2CB35FA,0x3696F8D5F00E88,0x6517014EFA0BAB,0x240120DB},{0x100C000008102,0x80,0x0,0x0,0x0}},{{0x100C000008101,0x80,0x0,0x0,0x0},{0x74F71E8D2FE08C,0xD43492B2CB35FA,0x3696F8D5F00E88,0x6517014EFA0BAB,0x240120DB},{0x74F71E8D2FE08D,0xD43492B2CB35FA,0x3696F8D5F00E88,0x6517014EFA0BAB,0x240120DB},{0x74F71E8D2FE08C,0xD43492B2CB35FA,0x3696F8D5F00E88,0x6517014EFA0BAB,0x240120DB}},{{0x100C000008102,0x80,0x0,0x0,0x0},{0x100C000008101,0x80,0x0,0x0,0x0},{0x100C000008101,0x80,0x0,0x0,0x0},{0x100C000008101,0x80,0x0,0x0,0x0}},{{0x806000004082,0x40,0x0,0x0,0x0},{0x2018000010202,0x100,0x0,0x0,0x0},{0x7476BE8D2FA00A,0xD43492B2CB35BA,0x3696F8D5F00E88,0x6517014EFA0BAB,0x240120DB},{0x806000004082,0x40,0x0,0x0,0x0}}}
+
+const USE_GLV bool=true
+const USE_GS_G2 bool=true
+const USE_GS_GT bool=true	
+const GT_STRONG bool=true
+
+*/
+
+// BNT2 Curve
+/*
+const CURVETYPE int=WEIERSTRASS
+const CURVE_PAIRING_TYPE int=BN_CURVE
+const CURVE_A int= 0
+var CURVE_B = [...]Chunk {0x2,0x0,0x0,0x0,0x0}
+var CURVE_Cof = [...]Chunk {0x1,0x0,0x0,0x0,0x0}
+var CURVE_Order=[...]Chunk {0xFB71A511AA2BF5,0x8DE127B73833D7,0xF3B89D00021CF,0x410F5AADB74E20,0x24000482}
+var CURVE_Bnx=[...]Chunk {0x20100608205,0x40,0x0,0x0,0x0}
+var CURVE_Cru=[...]Chunk {0x5027444866BD33,0x5B773016470EFB,0xC3617BECF23675,0x480006,0x0}
+var CURVE_Fra=[...]Chunk {0xB268C973AEF062,0xC69B33C3BCE492,0xF67FA37F195BBC,0x29E8CAB6BD0A41,0x124E0B8D}
+var CURVE_Frb=[...]Chunk {0x736240B1B429,0xCD48F52D196D56,0x18BBE650E72612,0x17268FF6FA43DE,0x11B1F8F5}
+var CURVE_Pxa=[...]Chunk {0xCC92399F40A3C8,0xCDA4E96611784A,0x7B056961706B35,0x9693C6318279D7,0x16FC17CF}
+var CURVE_Pxb=[...]Chunk {0x557A8AD8549540,0x6F7BE6F6510610,0x565907A95D17DB,0xBD5975909C8188,0x1EB5B500}
+var CURVE_Pya=[...]Chunk {0x7BECC514220513,0x4A78860E737B14,0x51B83935F12684,0x761422AA9D4DFA,0x1E8EE498}
+var CURVE_Pyb=[...]Chunk {0xB9328F577CE78E,0xB746E26FA5781F,0xA93DBC1FB8E27E,0xBAE33BDBA29D76,0x23CEF4CD}
+var CURVE_Gx =[...]Chunk {0xB2DC2BB460A48A,0x93E428F0D651E8,0xF3B89D00081CF,0x410F5AADB74E20,0x24000482}
+var CURVE_Gy =[...]Chunk {0x1,0x0,0x0,0x0,0x0}
+var CURVE_W=[2][5]Chunk {{0xB76282A1347083,0x60301399E1D10,0x6000,0x0,0x0},{0x40200C10409,0x80,0x0,0x0,0x0}}
+var CURVE_SB=[2][2][5]Chunk {{{0xB76684A1F5748C,0x60301399E1D90,0x6000,0x0,0x0},{0x40200C10409,0x80,0x0,0x0,0x0}},{{0x40200C10409,0x80,0x0,0x0,0x0},{0x440F227075BB72,0x87DE267D9A16C7,0xF3B89CFFFC1CF,0x410F5AADB74E20,0x24000482}}}
+var CURVE_WB=[4][5]Chunk {{0x9272D48A70A224,0x20100688A0945,0x2000,0x0,0x0},{0x5A572CF030EF19,0x9651763543721D,0x8240FD48A1B9A3,0x300004,0x0},{0xAD2C96F848B88F,0xCB28BB1AA1B92E,0x41207EA450DCD1,0x180002,0x0},{0x9276D68B31A62D,0x20100688A09C5,0x2000,0x0,0x0}}
+var CURVE_BB=[4][4][5]Chunk {{{0xFB6FA41149A9F1,0x8DE127B7383397,0xF3B89D00021CF,0x410F5AADB74E20,0x24000482},{0xFB6FA41149A9F0,0x8DE127B7383397,0xF3B89D00021CF,0x410F5AADB74E20,0x24000482},{0xFB6FA41149A9F0,0x8DE127B7383397,0xF3B89D00021CF,0x410F5AADB74E20,0x24000482},{0x40200C1040A,0x80,0x0,0x0,0x0}},{{0x40200C10409,0x80,0x0,0x0,0x0},{0xFB6FA41149A9F0,0x8DE127B7383397,0xF3B89D00021CF,0x410F5AADB74E20,0x24000482},{0xFB6FA41149A9F1,0x8DE127B7383397,0xF3B89D00021CF,0x410F5AADB74E20,0x24000482},{0xFB6FA41149A9F0,0x8DE127B7383397,0xF3B89D00021CF,0x410F5AADB74E20,0x24000482}},{{0x40200C1040A,0x80,0x0,0x0,0x0},{0x40200C10409,0x80,0x0,0x0,0x0},{0x40200C10409,0x80,0x0,0x0,0x0},{0x40200C10409,0x80,0x0,0x0,0x0}},{{0x20100608206,0x40,0x0,0x0,0x0},{0x80401820812,0x100,0x0,0x0,0x0},{0xFB6DA310E927EA,0x8DE127B7383357,0xF3B89D00021CF,0x410F5AADB74E20,0x24000482},{0x20100608206,0x40,0x0,0x0,0x0}}}
+
+const USE_GLV bool=true
+const USE_GS_G2 bool=true
+const USE_GS_GT bool=true	
+const GT_STRONG bool=true
+
+*/
+
+
diff --git a/version22/go/RSA.go b/version22/go/RSA.go
new file mode 100644
index 0000000..b8f22fa
--- /dev/null
+++ b/version22/go/RSA.go
@@ -0,0 +1,363 @@
+/*
+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.
+*/
+
+/* RSA API high-level functions  */
+
+package main
+
+//import "fmt"
+
+const RSA_RFS int=int(MODBYTES)*FFLEN
+const RSA_SHA256 int=32
+const RSA_SHA384 int=48
+const RSA_SHA512 int=64
+
+const RSA_HASH_TYPE int=RSA_SHA256
+
+
+type rsa_private_key struct {
+	p,q,dp,dq,c *FF
+}
+
+func New_rsa_private_key(n int) *rsa_private_key {
+	SK:=new(rsa_private_key)
+	SK.p=NewFFint(n)
+	SK.q=NewFFint(n)
+	SK.dp=NewFFint(n)
+	SK.dq=NewFFint(n)
+	SK.c=NewFFint(n)
+	return SK
+}
+
+type rsa_public_key struct {
+	e int
+	n *FF
+}
+
+func New_rsa_public_key(m int) *rsa_public_key{
+	PK:=new(rsa_public_key)
+	PK.e=0
+	PK.n=NewFFint(m)
+	return PK
+}
+
+func hashit(sha int,A []byte,n int) []byte {
+	var R []byte
+	if sha==RSA_SHA256 {
+		H:=NewHASH256()
+		if A!=nil {H.Process_array(A)}
+		if n>=0 {H.Process_num(int32(n))}
+		R=H.Hash()
+	}
+	if sha==RSA_SHA384 {
+		H:=NewHASH384()
+		if A!=nil {H.Process_array(A)}
+		if n>=0 {H.Process_num(int32(n))}
+		R=H.Hash()
+	}
+	if sha==RSA_SHA512 {
+		H:=NewHASH512()
+		if A!=nil {H.Process_array(A)}
+		if n>=0 {H.Process_num(int32(n))}
+		R=H.Hash()
+	}
+	return R
+}
+
+func RSA_KEY_PAIR(rng *RAND,e int,PRIV *rsa_private_key,PUB *rsa_public_key) { /* IEEE1363 A16.11/A16.12 more or less */
+	n:=PUB.n.getlen()/2
+	t:=NewFFint(n)
+	p1:=NewFFint(n)
+	q1:=NewFFint(n)
+
+	for true {
+		PRIV.p.random(rng)
+		for PRIV.p.lastbits(2)!=3 {PRIV.p.inc(1)}	
+		for !prime(PRIV.p,rng) {
+			PRIV.p.inc(4)
+		}
+			
+		p1.copy(PRIV.p)
+		p1.dec(1)
+
+		if p1.cfactor(e) {continue}
+		break;
+	}
+
+	for true {
+		PRIV.q.random(rng);
+		for PRIV.q.lastbits(2)!=3 {PRIV.q.inc(1)}
+		for !prime(PRIV.q,rng) {
+			PRIV.q.inc(4)
+		}
+			
+		q1.copy(PRIV.q);
+		q1.dec(1);
+
+		if q1.cfactor(e) {continue}
+
+		break;
+	}
+	
+	PUB.n=ff_mul(PRIV.p,PRIV.q);
+	PUB.e=e;
+
+	t.copy(p1)
+	t.shr()
+	PRIV.dp.set(e)
+	PRIV.dp.invmodp(t)
+	if PRIV.dp.parity()==0 {PRIV.dp.add(t)}
+	PRIV.dp.norm();
+
+	t.copy(q1)
+	t.shr()
+	PRIV.dq.set(e)
+	PRIV.dq.invmodp(t)
+	if PRIV.dq.parity()==0 {PRIV.dq.add(t)}
+	PRIV.dq.norm()
+
+	PRIV.c.copy(PRIV.p)
+	PRIV.c.invmodp(PRIV.q)
+
+}
+
+/* Mask Generation Function */
+
+func RSA_MGF1(sha int,Z []byte,olen int,K []byte) {
+	hlen:=sha
+
+	var k int=0
+	for i:=0;i<len(K);i++ {K[i]=0}
+
+	cthreshold:=olen/hlen 
+	if olen%hlen!=0 {cthreshold++}
+	for counter:=0;counter<cthreshold;counter++ {
+		B:=hashit(sha,Z,counter)
+
+		if (k+hlen>olen) {
+			for i:=0;i<olen%hlen;i++ {K[k]=B[i]; k++}
+		} else {
+			for i:=0;i<hlen;i++ {K[k]=B[i]; k++}
+		}
+	}	
+}
+
+/* SHAXXX identifier strings */
+var SHA256ID= [...]byte {0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20}
+var SHA384ID= [...]byte {0x30,0x41,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00,0x04,0x30};
+var SHA512ID= [...]byte {0x30,0x51,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0x04,0x40};
+
+func PKCS15(sha int,m []byte,w []byte) bool {
+	olen:=FF_BITS/8
+	hlen:=sha
+	idlen:=19
+
+	if olen<idlen+hlen+10 {return false}
+	H:=hashit(sha,m,-1)
+
+	for i:=0;i<len(w);i++ {w[i]=0}
+	i:=0
+	w[i]=0; i++
+	w[i]=1; i++
+	for j:=0;j<olen-idlen-hlen-3;j++ {w[i]=0xff; i++}
+	w[i]=0; i++
+
+	if hlen==RSA_SHA256 {
+		for j:=0;j<idlen;j++ {w[i]=SHA256ID[j]; i++}
+	}
+	if hlen==RSA_SHA384 {
+		for j:=0;j<idlen;j++ {w[i]=SHA384ID[j]; i++}
+	}
+	if hlen==RSA_SHA512 {
+		for j:=0;j<idlen;j++ {w[i]=SHA512ID[j]; i++}
+	}
+	for j:=0;j<hlen;j++ {w[i]=H[j]; i++}
+
+	return true
+}
+
+
+/* OAEP Message Encoding for Encryption */
+func RSA_OAEP_ENCODE(sha int,m []byte,rng *RAND,p []byte) []byte { 
+	olen:=RSA_RFS-1
+	mlen:=len(m)
+	var f [RSA_RFS]byte
+
+	hlen:=sha
+
+	SEED:=make([]byte,hlen);
+
+	seedlen:=hlen
+	if (mlen>olen-hlen-seedlen-1) {return nil} 
+
+	DBMASK:=make([]byte,olen-seedlen)
+
+	h:=hashit(sha,p,-1);
+
+	for i:=0;i<hlen;i++ {f[i]=h[i]}
+
+	slen:=olen-mlen-hlen-seedlen-1      
+
+	for i:=0;i<slen;i++ {f[hlen+i]=0}
+	f[hlen+slen]=1
+	for i:=0;i<mlen;i++ {f[hlen+slen+1+i]=m[i]}
+
+	for i:=0;i<seedlen;i++ {SEED[i]=rng.GetByte()}
+	RSA_MGF1(sha,SEED,olen-seedlen,DBMASK)
+
+	for i:=0;i<olen-seedlen;i++ {DBMASK[i]^=f[i]}
+
+	RSA_MGF1(sha,DBMASK,seedlen,f[:])
+
+	for i:=0;i<seedlen;i++ {f[i]^=SEED[i]}
+
+	for i:=0;i<olen-seedlen;i++ {f[i+seedlen]=DBMASK[i]}
+
+	/* pad to length RFS */
+	d:=1
+	for i:=RSA_RFS-1;i>=d;i-- {
+		f[i]=f[i-d]
+	}
+	for i:=d-1;i>=0;i-- {
+		f[i]=0
+	}
+	return f[:]
+}
+
+/* OAEP Message Decoding for Decryption */
+func RSA_OAEP_DECODE(sha int,p []byte,f []byte) [] byte {
+	olen:=RSA_RFS-1
+
+	hlen:=sha
+	SEED:=make([]byte,hlen)
+	seedlen:=hlen;
+	CHASH:=make([]byte,hlen)
+	
+	if olen<seedlen+hlen+1 {return nil}
+	DBMASK:=make([]byte,olen-seedlen)
+	for i:=0;i<olen-seedlen;i++ {DBMASK[i]=0}
+
+	if len(f)<RSA_RFS {
+		d:=RSA_RFS-len(f)
+		for i:=RSA_RFS-1;i>=d;i-- {
+			f[i]=f[i-d]
+		}
+		for i:=d-1;i>=0;i-- {
+			f[i]=0
+		}
+	}
+
+	h:=hashit(sha,p,-1)
+	for i:=0;i<hlen;i++ {CHASH[i]=h[i]}
+
+	x:=f[0]
+
+	for i:=seedlen;i<olen;i++ {
+		DBMASK[i-seedlen]=f[i+1]
+	}
+
+	RSA_MGF1(sha,DBMASK,seedlen,SEED)
+	for i:=0;i<seedlen;i++ {SEED[i]^=f[i+1]}
+	RSA_MGF1(sha,SEED,olen-seedlen,f)
+	for i:=0;i<olen-seedlen;i++ {DBMASK[i]^=f[i]}
+
+	comp:=true
+	for i:=0;i<hlen;i++ {
+		if CHASH[i]!=DBMASK[i] {comp=false}
+	}
+
+	for i:=0;i<olen-seedlen-hlen;i++ {
+		DBMASK[i]=DBMASK[i+hlen]
+	}
+
+	for i:=0;i<hlen;i++ {
+		SEED[i]=0; CHASH[i]=0
+	}
+		
+	var k int
+	for k=0;;k++ {
+		if k>=olen-seedlen-hlen {return nil}
+		if DBMASK[k]!=0 {break}
+	}
+
+	t:=DBMASK[k]
+	if (!comp || x!=0 || t!=0x01) {
+		for i:=0;i<olen-seedlen;i++ {DBMASK[i]=0}
+		return nil
+	}
+
+	var r = make([]byte,olen-seedlen-hlen-k-1)
+
+	for i:=0;i<olen-seedlen-hlen-k-1;i++ {
+		r[i]=DBMASK[i+k+1]
+	}
+	
+	for i:=0;i<olen-seedlen;i++  {DBMASK[i]=0}
+
+	return r
+}
+
+/* destroy the Private Key structure */
+func RSA_PRIVATE_KEY_KILL(PRIV *rsa_private_key) {
+	PRIV.p.zero();
+	PRIV.q.zero();
+	PRIV.dp.zero();
+	PRIV.dq.zero();
+	PRIV.c.zero();
+}
+
+/* RSA encryption with the public key */
+func RSA_ENCRYPT(PUB *rsa_public_key,F []byte,G []byte) {
+	n:=PUB.n.getlen()
+	f:=NewFFint(n)
+
+	ff_fromBytes(f,F)
+	f.power(PUB.e,PUB.n)
+	f.toBytes(G)
+}
+
+/* RSA decryption with the private key */
+func RSA_DECRYPT(PRIV *rsa_private_key,G []byte,F []byte) {
+	n:=PRIV.p.getlen()
+	g:=NewFFint(2*n)
+
+	ff_fromBytes(g,G);
+	jp:=g.dmod(PRIV.p)
+	jq:=g.dmod(PRIV.q)
+
+	jp.skpow(PRIV.dp,PRIV.p)
+	jq.skpow(PRIV.dq,PRIV.q)
+
+	g.zero()
+	g.dscopy(jp)
+	jp.mod(PRIV.q)
+	if ff_comp(jp,jq)>0 {jq.add(PRIV.q)}
+	jq.sub(jp)
+	jq.norm()
+
+	t:=ff_mul(PRIV.c,jq)
+	jq=t.dmod(PRIV.q)
+
+	t=ff_mul(jq,PRIV.p)
+	g.add(t)
+	g.norm()
+
+	g.toBytes(F)
+}
+
diff --git a/version22/go/TestECDH.go b/version22/go/TestECDH.go
new file mode 100644
index 0000000..c3fbf87
--- /dev/null
+++ b/version22/go/TestECDH.go
@@ -0,0 +1,164 @@
+/*
+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.
+*/
+
+/* test driver and function exerciser for ECDH/ECIES/ECDSA API Functions */
+
+package main
+
+import "fmt"
+
+func ECDH_printBinary(array []byte) {
+	for i:=0;i<len(array);i++ {
+		fmt.Printf("%02x", array[i])
+	}
+	fmt.Printf("\n")
+}  
+
+func main() {
+
+//	j:=0
+	pp:="M0ng00se"
+	res:=0
+
+	var sha=ECDH_HASH_TYPE
+
+	var S1 [ECDH_EGS]byte
+	var W0 [2*ECDH_EFS+1]byte
+	var W1 [2*ECDH_EFS+1]byte
+	var Z0 [ECDH_EFS]byte
+	var Z1 [ECDH_EFS]byte
+	var RAW [100]byte
+	var SALT [8]byte
+	var P1 [3]byte
+	var P2 [4]byte
+	var V [2*ECDH_EFS+1]byte
+	var M [17]byte
+	var T [12]byte
+	var CS [ECDH_EGS]byte
+	var DS [ECDH_EGS]byte
+
+	rng:=NewRAND()
+
+	rng.Clean();
+	for i:=0;i<100;i++ {RAW[i]=byte(i)}
+
+	rng.Seed(100,RAW[:])
+
+//for j:=0;j<100;j++ {
+
+	for i:=0;i<8;i++ {SALT[i]=byte(i+1)}  // set Salt
+
+	fmt.Printf("Alice's Passphrase= "+pp)
+	fmt.Printf("\n");
+	PW:=[]byte(pp)
+
+/* private key S0 of size EGS bytes derived from Password and Salt */
+
+	S0:=PBKDF2(sha,PW,SALT[:],1000,ECDH_EGS)
+
+	fmt.Printf("Alice's private key= 0x")
+	ECDH_printBinary(S0)
+
+/* Generate Key pair S/W */
+	ECDH_KEY_PAIR_GENERATE(nil,S0,W0[:])
+
+	fmt.Printf("Alice's public key= 0x")
+	ECDH_printBinary(W0[:]);
+
+	res=ECDH_PUBLIC_KEY_VALIDATE(true,W0[:])
+	if res!=0 {
+		fmt.Printf("ECP Public Key is invalid!\n")
+		return
+	}
+
+/* Random private key for other party */
+	ECDH_KEY_PAIR_GENERATE(rng,S1[:],W1[:])
+
+	fmt.Printf("Servers private key= 0x");
+	ECDH_printBinary(S1[:])
+
+	fmt.Printf("Servers public key= 0x")
+	ECDH_printBinary(W1[:])
+
+
+	res=ECDH_PUBLIC_KEY_VALIDATE(true,W1[:])
+	if res!=0 {
+		fmt.Printf("ECP Public Key is invalid!\n")
+		return
+	}
+/* Calculate common key using DH - IEEE 1363 method */
+
+	ECPSVDP_DH(S0,W1[:],Z0[:])
+	ECPSVDP_DH(S1[:],W0[:],Z1[:])
+
+	same:=true
+	for i:=0;i<ECDH_EFS;i++ {
+		if Z0[i]!=Z1[i] {same=false}
+	}
+
+	if !same {
+		fmt.Printf("*** ECPSVDP-DH Failed\n");
+		return
+	}
+
+	KEY:=KDF2(sha,Z0[:],nil,ECDH_EAS);
+
+	fmt.Printf("Alice's DH Key=  0x"); ECDH_printBinary(KEY)
+	fmt.Printf("Servers DH Key=  0x"); ECDH_printBinary(KEY)
+	
+	if CURVETYPE!=MONTGOMERY {
+		fmt.Printf("Testing ECIES\n");
+
+		P1[0]=0x0; P1[1]=0x1; P1[2]=0x2
+		P2[0]=0x0; P2[1]=0x1; P2[2]=0x2; P2[3]=0x3
+
+		for i:=0;i<=16;i++ {M[i]=byte(i)} 
+
+		C:=ECIES_ENCRYPT(sha,P1[:],P2[:],rng,W1[:],M[:],V[:],T[:])
+
+		fmt.Printf("Ciphertext= \n")
+		fmt.Printf("V= 0x"); ECDH_printBinary(V[:])
+		fmt.Printf("C= 0x"); ECDH_printBinary(C)
+		fmt.Printf("T= 0x"); ECDH_printBinary(T[:])
+
+
+		RM:=ECIES_DECRYPT(sha,P1[:],P2[:],V[:],C,T[:],S1[:])
+		if RM==nil {
+			fmt.Printf("*** ECIES Decryption Failed\n")
+			return
+		} else {fmt.Printf("Decryption succeeded\n")}
+
+		fmt.Printf("Message is 0x"); ECDH_printBinary(RM)
+
+		fmt.Printf("Testing ECDSA\n");
+
+		if ECPSP_DSA(sha,rng,S0,M[:],CS[:],DS[:])!=0 {
+			fmt.Printf("***ECDSA Signature Failed\n")
+			return
+		}
+		fmt.Printf("Signature= \n")
+		fmt.Printf("C= 0x"); ECDH_printBinary(CS[:])
+		fmt.Printf("D= 0x"); ECDH_printBinary(DS[:])
+
+		if ECPVP_DSA(sha,W0[:],M[:],CS[:],DS[:])!=0 {
+			fmt.Printf("***ECDSA Verification Failed\n")
+			return
+		} else {fmt.Printf("ECDSA Signature/Verification succeeded \n")}
+	}
+}
diff --git a/version22/go/TestMPIN.go b/version22/go/TestMPIN.go
new file mode 100644
index 0000000..60ca3de
--- /dev/null
+++ b/version22/go/TestMPIN.go
@@ -0,0 +1,241 @@
+/*
+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.
+*/
+
+/* test driver and function exerciser for MPIN API Functions */
+
+package main
+
+import "fmt"
+
+func MPIN_printBinary(array []byte) {
+	for i:=0;i<len(array);i++ {
+		fmt.Printf("%02x", array[i])
+	}
+	fmt.Printf("\n")
+} 
+
+func main() {
+
+
+	rng:=NewRAND()
+	var raw [100]byte
+	for i:=0;i<100;i++ {raw[i]=byte(i+1)}
+	rng.Seed(100,raw[:])
+
+	var sha=MPIN_HASH_TYPE
+
+	const EGS=MPIN_EGS
+	const EFS=MPIN_EFS
+	const G1S=2*EFS+1 /* Group 1 Size */
+	const G2S=4*EFS; /* Group 2 Size */
+	const EAS int=16
+
+	var S [EGS]byte
+	var SST [G2S]byte
+	var TOKEN [G1S]byte
+	var PERMIT [G1S]byte
+	var SEC [G1S]byte
+	var xID [G1S]byte
+	var xCID [G1S]byte
+	var X [EGS]byte
+	var Y [EGS]byte
+	var E [12*EFS]byte
+	var F [12*EFS]byte
+	var HID [G1S]byte
+	var HTID [G1S]byte
+
+	var G1 [12*EFS]byte
+	var G2 [12*EFS]byte
+	var R [EGS]byte
+	var Z [G1S]byte
+	var W [EGS]byte
+	var T [G1S]byte
+	var CK [EAS]byte
+	var SK [EAS]byte
+
+	var HSID []byte
+
+
+/* Trusted Authority set-up */
+
+	MPIN_RANDOM_GENERATE(rng,S[:])
+	fmt.Printf("Master Secret s: 0x");  MPIN_printBinary(S[:])
+
+ /* Create Client Identity */
+ 	IDstr:= "testUser@miracl.com"
+	CLIENT_ID:=[]byte(IDstr)
+
+	HCID:=MPIN_HASH_ID(sha,CLIENT_ID)  /* Either Client or TA calculates Hash(ID) - you decide! */
+		
+	fmt.Printf("Client ID= "); MPIN_printBinary(CLIENT_ID)
+	fmt.Printf("\n")
+
+/* Client and Server are issued secrets by DTA */
+	MPIN_GET_SERVER_SECRET(S[:],SST[:])
+	fmt.Printf("Server Secret SS: 0x");  MPIN_printBinary(SST[:])
+
+	MPIN_GET_CLIENT_SECRET(S[:],HCID,TOKEN[:])
+	fmt.Printf("Client Secret CS: 0x");        
+	MPIN_printBinary(TOKEN[:])
+
+/* Client extracts PIN from secret to create Token */
+	pin:=1234
+	fmt.Printf("Client extracts PIN= %d",pin)
+	fmt.Printf("\n")
+	rtn:=MPIN_EXTRACT_PIN(sha,CLIENT_ID,pin,TOKEN[:])
+	if rtn != 0 {
+		fmt.Printf("FAILURE: EXTRACT_PIN rtn: %d",rtn);
+		fmt.Printf("\n")
+	}
+
+	fmt.Printf("Client Token TK: 0x")       
+	MPIN_printBinary(TOKEN[:]); 
+
+	if FULL {
+		MPIN_PRECOMPUTE(TOKEN[:],HCID,G1[:],G2[:])
+	}
+
+	date:=0
+	if PERMITS {
+		date=MPIN_today()
+/* Client gets "Time Token" permit from DTA */ 
+		MPIN_GET_CLIENT_PERMIT(sha,date,S[:],HCID,PERMIT[:])
+		fmt.Printf("Time Permit TP: 0x");  MPIN_printBinary(PERMIT[:])
+
+/* This encoding makes Time permit look random - Elligator squared */
+		MPIN_ENCODING(rng,PERMIT[:])
+		fmt.Printf("Encoded Time Permit TP: 0x");  MPIN_printBinary(PERMIT[:])
+		MPIN_DECODING(PERMIT[:])
+		fmt.Printf("Decoded Time Permit TP: 0x");  MPIN_printBinary(PERMIT[:])
+	}
+
+	pin=0
+	fmt.Printf("\nPIN= ")
+	fmt.Scanf("%d",&pin)
+
+	pxID:=xID[:]
+	pxCID:=xCID[:]
+	pHID:=HID[:]
+	pHTID:=HTID[:]
+	pE:=E[:]
+	pF:=F[:]
+	pPERMIT:=PERMIT[:]
+	var prHID []byte
+
+	if date!=0 {
+		prHID=pHTID;
+		if !PINERROR {
+			pxID=nil
+			// pHID=nil
+		}
+	} else {
+		prHID=pHID
+		pPERMIT=nil
+		pxCID=nil
+		pHTID=nil
+	}
+	if !PINERROR {
+		pE=nil
+		pF=nil
+	}
+
+	if SINGLE_PASS {
+		fmt.Printf("MPIN Single Pass\n")
+		timeValue:= MPIN_GET_TIME()
+		rtn=MPIN_CLIENT(sha,date,CLIENT_ID,rng,X[:],pin,TOKEN[:],SEC[:],pxID,pxCID,pPERMIT,timeValue,Y[:])
+		if rtn != 0 {
+			fmt.Printf("FAILURE: CLIENT rtn: %d\n",rtn)
+		}
+
+		if FULL {
+			HCID=MPIN_HASH_ID(sha,CLIENT_ID)
+			MPIN_GET_G1_MULTIPLE(rng,1,R[:],HCID,Z[:])  /* Also Send Z=r.ID to Server, remember random r */
+		}
+
+		rtn=MPIN_SERVER(sha,date,pHID,pHTID,Y[:],SST[:],pxID,pxCID,SEC[:],pE,pF,CLIENT_ID,timeValue)
+		if rtn != 0 {
+  		    fmt.Printf("FAILURE: SERVER rtn: %d\n",rtn)
+		}
+
+		if FULL {
+			HSID=MPIN_HASH_ID(sha,CLIENT_ID);
+			MPIN_GET_G1_MULTIPLE(rng,0,W[:],prHID,T[:]);  /* Also send T=w.ID to client, remember random w  */
+		}
+	} else {
+		fmt.Printf("MPIN Multi Pass\n")
+        /* Send U=x.ID to server, and recreate secret from token and pin */
+		rtn=MPIN_CLIENT_1(sha,date,CLIENT_ID,rng,X[:],pin,TOKEN[:],SEC[:],pxID,pxCID,pPERMIT);
+		if rtn != 0 {
+			fmt.Printf("FAILURE: CLIENT_1 rtn: %d\n",rtn)
+		}
+  
+		if FULL {
+			HCID=MPIN_HASH_ID(sha,CLIENT_ID)
+			MPIN_GET_G1_MULTIPLE(rng,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. */
+		MPIN_SERVER_1(sha,date,CLIENT_ID,pHID,pHTID)
+  
+        /* Server generates Random number Y and sends it to Client */
+		MPIN_RANDOM_GENERATE(rng,Y[:]);
+  
+		if FULL {
+			HSID=MPIN_HASH_ID(sha,CLIENT_ID);
+			MPIN_GET_G1_MULTIPLE(rng,0,W[:],prHID,T[:])  /* Also send T=w.ID to client, remember random w  */
+		}
+  
+       /* Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC */
+		rtn=MPIN_CLIENT_2(X[:],Y[:],SEC[:])
+		if rtn != 0 {
+			fmt.Printf("FAILURE: CLIENT_2 rtn: %d\n",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=MPIN_SERVER_2(date,pHID,pHTID,Y[:],SST[:],pxID,pxCID,SEC[:],pE,pF)
+  
+		if rtn!=0 {
+			fmt.Printf("FAILURE: SERVER_1 rtn: %d\n",rtn)
+		}
+  
+		if rtn == MPIN_BAD_PIN {
+			fmt.Printf("Server says - Bad Pin. I don't know you. Feck off.\n")
+			if PINERROR {
+				err:=MPIN_KANGAROO(E[:],F[:])
+				if err!=0 {fmt.Printf("(Client PIN is out by %d)\n",err)}
+			}
+			return
+		} else {
+			fmt.Printf("Server says - PIN is good! You really are "+IDstr)
+			fmt.Printf("\n")
+		}
+
+		if  FULL {
+			H:=MPIN_HASH_ALL(sha,HCID[:],pxID,pxCID,SEC[:],Y[:],Z[:],T[:]);
+			MPIN_CLIENT_KEY(sha,G1[:],G2[:],pin,R[:],X[:],H[:],T[:],CK[:])
+			fmt.Printf("Client Key =  0x");  MPIN_printBinary(CK[:])
+
+			H=MPIN_HASH_ALL(sha,HSID[:],pxID,pxCID,SEC[:],Y[:],Z[:],T[:]);			
+			MPIN_SERVER_KEY(sha,Z[:],SST[:],W[:],H[:],pHID,pxID,pxCID,SK[:])
+			fmt.Printf("Server Key =  0x");  MPIN_printBinary(SK[:])
+		}
+	}
+}
diff --git a/version22/go/TestRSA.go b/version22/go/TestRSA.go
new file mode 100644
index 0000000..652fd9a
--- /dev/null
+++ b/version22/go/TestRSA.go
@@ -0,0 +1,98 @@
+/*
+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.
+*/
+
+/* test driver and function exerciser for RSA API Functions */
+
+package main
+
+import "fmt"
+
+func RSA_printBinary(array []byte) {
+	for i:=0;i<len(array);i++ {
+		fmt.Printf("%02x", array[i])
+	}
+	fmt.Printf("\n")
+}  
+
+func main() {
+
+	var sha=RSA_HASH_TYPE
+	message:="Hello World\n"
+
+	pub:=New_rsa_public_key(FFLEN)
+	priv:=New_rsa_private_key(HFLEN)
+
+	var ML [RSA_RFS]byte
+	var C [RSA_RFS]byte
+	var S [RSA_RFS]byte
+	var RAW [100]byte
+	
+	rng:=NewRAND()
+
+	rng.Clean();
+	for i:=0;i<100;i++ {RAW[i]=byte(i)}
+
+	rng.Seed(100,RAW[:]);
+//for (i=0;i<10;i++)
+//{
+	fmt.Printf("Generating public/private key pair\n")
+	RSA_KEY_PAIR(rng,65537,priv,pub)
+
+	M:=[]byte(message)
+
+	fmt.Printf("Encrypting test string\n")
+	E:=RSA_OAEP_ENCODE(sha,M,rng,nil) /* OAEP encode message M to E  */
+
+	RSA_ENCRYPT(pub,E,C[:])    /* encrypt encoded message */
+	fmt.Printf("Ciphertext= 0x"); RSA_printBinary(C[:])
+
+	fmt.Printf("Decrypting test string\n");
+	RSA_DECRYPT(priv,C[:],ML[:])
+	MS:=RSA_OAEP_DECODE(sha,nil,ML[:]) /* OAEP decode message  */
+
+	message=string(MS)
+	fmt.Printf(message)
+
+	fmt.Printf("Signing message\n")
+	PKCS15(sha,M,C[:]); 
+
+	RSA_DECRYPT(priv,C[:],S[:])  /* create signature in S */ 
+
+	fmt.Printf("Signature= 0x"); RSA_printBinary(S[:])
+
+	RSA_ENCRYPT(pub,S[:],ML[:])
+
+	cmp:=true
+	if len(C)!=len(ML) {
+		cmp=false
+	} else {
+		for j:=0;j<len(C);j++ {
+			if C[j]!=ML[j] {cmp=false}
+		}
+	}
+	if cmp {
+		fmt.Printf("Signature is valid")
+	} else {
+		fmt.Printf("Signature is INVALID")
+	}
+
+
+//}
+	RSA_PRIVATE_KEY_KILL(priv)
+}
diff --git a/version22/go/readme.txt b/version22/go/readme.txt
new file mode 100644
index 0000000..054048c
--- /dev/null
+++ b/version22/go/readme.txt
@@ -0,0 +1,50 @@
+AMCL is very simple to build for Go.
+
+This version supports both 32-bit and 64-bit builds.
+If your processor and operating system are both 64-bit, a 64-bit build 
+will probably be best. Otherwise use a 32-bit build.
+
+Next - decide the modulus and curve type you want to use. Edit ROM32.go 
+or ROM64.go where indicated. You will probably want to use one of the curves whose 
+details are already in there.
+
+Three example API files are provided, TestMPIN.go which 
+supports our M-Pin (tm) protocol, TestECDH.go which supports elliptic 
+curve key exchange, digital signature and public key crypto, and TestRSA.go
+which supports the RSA method.
+
+In the ROM32.go/ROM64.go file you must provide the curve constants. 
+Several examples are provided there, if you are willing to use one of these.
+
+Use ROM32.go for a 32-bit build
+Use ROM64.go for a 64-bit build
+
+To help generate the ROM constants for your own curve some MIRACL helper 
+programs are included. The programs bngen.cpp and blsgen.cpp generate ROM 
+data for a BN and BLS pairing friendly curves, and the program ecgen.cpp 
+generates ROM data for regular EC curves.
+
+The MIRACL based program check.cpp helps choose the best number base for
+big number representation, given the word-length and the size of the modulus.
+
+The program bigtobig.cpp converts a big number to the AMCL 
+BIG format.
+
+
+For a quick jumpstart:-
+
+go run TestMPIN.go MPIN.go PAIR.go FP12.go FP4.go FP2.go FP.go BIG.go DBIG.go ECP.go ECP2.go HASH256.go HASH384.go HASH512.go AES.go RAND.go ROM64.go
+
+or 
+
+go run TestECDH.go ECDH.go FP.go BIG.go DBIG.go ECP.go HASH256.go HASH384.go HASH512.go AES.go RAND.go ROM64.go
+
+or
+
+go run TestRSA.go RSA.go FF.go BIG.go DBIG.go HASH256.go HASH384.go HASH512.go AES.go RAND.go ROM64.go
+
+also
+
+go run BenchtestEC.go RSA.go FF.go FP.go BIG.go DBIG.go ECP.go HASH256.go HASH384.go HASH512.go AES.go RAND.go ROM64.go
+
+go run BenchtestPAIR.go PAIR.go FP12.go FP4.go FP2.go FP.go BIG.go DBIG.go ECP.go ECP2.go HASH256.go HASH384.go HASH512.go AES.go RAND.go ROM64.go
\ No newline at end of file
diff --git a/version22/java/AES.java b/version22/java/AES.java
new file mode 100644
index 0000000..648db7c
--- /dev/null
+++ b/version22/java/AES.java
@@ -0,0 +1,695 @@
+/*
+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.
+*/
+
+
+/* AES Encryption */ 
+
+
+public class AES {
+	int Nk,Nr;
+	int mode;
+	private int[] fkey=new int[60];
+	private int[] rkey=new int[60];
+	public byte[] f=new byte[16];
+
+
+	public static final int ECB=0;
+	public static final int CBC=1;
+	public static final int CFB1=2;
+	public static final int CFB2=3;
+	public static final int CFB4=5;
+	public static final int OFB1=14;
+	public static final int OFB2=15;
+	public static final int OFB4=17;
+	public static final int OFB8=21;
+	public static final int OFB16=29;
+	public static final int CTR1=30;
+	public static final int CTR2=31;
+	public static final int CTR4=33; 
+	public static final int CTR8=37; 
+	public static final int CTR16=45; 
+
+	private static final byte[] InCo={(byte)0xB,(byte)0xD,(byte)0x9,(byte)0xE};  /* Inverse Coefficients */
+
+	public static final int KS=16; /* Key Size in bytes */
+	public static final int BS=16; /* Block Size */
+
+	private static final byte[] ptab=
+	{(byte)1,(byte)3,(byte)5,(byte)15,(byte)17,(byte)51,(byte)85,(byte)255,(byte)26,(byte)46,(byte)114,(byte)150,(byte)161,(byte)248,(byte)19,(byte)53,
+	(byte)95,(byte)225,(byte)56,(byte)72,(byte)216,(byte)115,(byte)149,(byte)164,(byte)247,(byte)2,(byte)6,(byte)10,(byte)30,(byte)34,(byte)102,(byte)170,
+	(byte)229,(byte)52,(byte)92,(byte)228,(byte)55,(byte)89,(byte)235,(byte)38,(byte)106,(byte)190,(byte)217,(byte)112,(byte)144,(byte)171,(byte)230,(byte)49,
+	(byte)83,(byte)245,(byte)4,(byte)12,(byte)20,(byte)60,(byte)68,(byte)204,(byte)79,(byte)209,(byte)104,(byte)184,(byte)211,(byte)110,(byte)178,(byte)205,
+	(byte)76,(byte)212,(byte)103,(byte)169,(byte)224,(byte)59,(byte)77,(byte)215,(byte)98,(byte)166,(byte)241,(byte)8,(byte)24,(byte)40,(byte)120,(byte)136,
+	(byte)131,(byte)158,(byte)185,(byte)208,(byte)107,(byte)189,(byte)220,(byte)127,(byte)129,(byte)152,(byte)179,(byte)206,(byte)73,(byte)219,(byte)118,(byte)154,
+	(byte)181,(byte)196,(byte)87,(byte)249,(byte)16,(byte)48,(byte)80,(byte)240,(byte)11,(byte)29,(byte)39,(byte)105,(byte)187,(byte)214,(byte)97,(byte)163,
+	(byte)254,(byte)25,(byte)43,(byte)125,(byte)135,(byte)146,(byte)173,(byte)236,(byte)47,(byte)113,(byte)147,(byte)174,(byte)233,(byte)32,(byte)96,(byte)160,
+	(byte)251,(byte)22,(byte)58,(byte)78,(byte)210,(byte)109,(byte)183,(byte)194,(byte)93,(byte)231,(byte)50,(byte)86,(byte)250,(byte)21,(byte)63,(byte)65,
+	(byte)195,(byte)94,(byte)226,(byte)61,(byte)71,(byte)201,(byte)64,(byte)192,(byte)91,(byte)237,(byte)44,(byte)116,(byte)156,(byte)191,(byte)218,(byte)117,
+	(byte)159,(byte)186,(byte)213,(byte)100,(byte)172,(byte)239,(byte)42,(byte)126,(byte)130,(byte)157,(byte)188,(byte)223,(byte)122,(byte)142,(byte)137,(byte)128,
+	(byte)155,(byte)182,(byte)193,(byte)88,(byte)232,(byte)35,(byte)101,(byte)175,(byte)234,(byte)37,(byte)111,(byte)177,(byte)200,(byte)67,(byte)197,(byte)84,
+	(byte)252,(byte)31,(byte)33,(byte)99,(byte)165,(byte)244,(byte)7,(byte)9,(byte)27,(byte)45,(byte)119,(byte)153,(byte)176,(byte)203,(byte)70,(byte)202,
+	(byte)69,(byte)207,(byte)74,(byte)222,(byte)121,(byte)139,(byte)134,(byte)145,(byte)168,(byte)227,(byte)62,(byte)66,(byte)198,(byte)81,(byte)243,(byte)14,
+	(byte)18,(byte)54,(byte)90,(byte)238,(byte)41,(byte)123,(byte)141,(byte)140,(byte)143,(byte)138,(byte)133,(byte)148,(byte)167,(byte)242,(byte)13,(byte)23,
+	(byte)57,(byte)75,(byte)221,(byte)124,(byte)132,(byte)151,(byte)162,(byte)253,(byte)28,(byte)36,(byte)108,(byte)180,(byte)199,(byte)82,(byte)246,(byte)1};
+
+	private static final byte[] ltab=
+	{(byte)0,(byte)255,(byte)25,(byte)1,(byte)50,(byte)2,(byte)26,(byte)198,(byte)75,(byte)199,(byte)27,(byte)104,(byte)51,(byte)238,(byte)223,(byte)3,
+	(byte)100,(byte)4,(byte)224,(byte)14,(byte)52,(byte)141,(byte)129,(byte)239,(byte)76,(byte)113,(byte)8,(byte)200,(byte)248,(byte)105,(byte)28,(byte)193,
+	(byte)125,(byte)194,(byte)29,(byte)181,(byte)249,(byte)185,(byte)39,(byte)106,(byte)77,(byte)228,(byte)166,(byte)114,(byte)154,(byte)201,(byte)9,(byte)120,
+	(byte)101,(byte)47,(byte)138,(byte)5,(byte)33,(byte)15,(byte)225,(byte)36,(byte)18,(byte)240,(byte)130,(byte)69,(byte)53,(byte)147,(byte)218,(byte)142,
+	(byte)150,(byte)143,(byte)219,(byte)189,(byte)54,(byte)208,(byte)206,(byte)148,(byte)19,(byte)92,(byte)210,(byte)241,(byte)64,(byte)70,(byte)131,(byte)56,
+	(byte)102,(byte)221,(byte)253,(byte)48,(byte)191,(byte)6,(byte)139,(byte)98,(byte)179,(byte)37,(byte)226,(byte)152,(byte)34,(byte)136,(byte)145,(byte)16,
+	(byte)126,(byte)110,(byte)72,(byte)195,(byte)163,(byte)182,(byte)30,(byte)66,(byte)58,(byte)107,(byte)40,(byte)84,(byte)250,(byte)133,(byte)61,(byte)186,
+	(byte)43,(byte)121,(byte)10,(byte)21,(byte)155,(byte)159,(byte)94,(byte)202,(byte)78,(byte)212,(byte)172,(byte)229,(byte)243,(byte)115,(byte)167,(byte)87,
+	(byte)175,(byte)88,(byte)168,(byte)80,(byte)244,(byte)234,(byte)214,(byte)116,(byte)79,(byte)174,(byte)233,(byte)213,(byte)231,(byte)230,(byte)173,(byte)232,
+	(byte)44,(byte)215,(byte)117,(byte)122,(byte)235,(byte)22,(byte)11,(byte)245,(byte)89,(byte)203,(byte)95,(byte)176,(byte)156,(byte)169,(byte)81,(byte)160,
+	(byte)127,(byte)12,(byte)246,(byte)111,(byte)23,(byte)196,(byte)73,(byte)236,(byte)216,(byte)67,(byte)31,(byte)45,(byte)164,(byte)118,(byte)123,(byte)183,
+	(byte)204,(byte)187,(byte)62,(byte)90,(byte)251,(byte)96,(byte)177,(byte)134,(byte)59,(byte)82,(byte)161,(byte)108,(byte)170,(byte)85,(byte)41,(byte)157,
+	(byte)151,(byte)178,(byte)135,(byte)144,(byte)97,(byte)190,(byte)220,(byte)252,(byte)188,(byte)149,(byte)207,(byte)205,(byte)55,(byte)63,(byte)91,(byte)209,
+	(byte)83,(byte)57,(byte)132,(byte)60,(byte)65,(byte)162,(byte)109,(byte)71,(byte)20,(byte)42,(byte)158,(byte)93,(byte)86,(byte)242,(byte)211,(byte)171,
+	(byte)68,(byte)17,(byte)146,(byte)217,(byte)35,(byte)32,(byte)46,(byte)137,(byte)180,(byte)124,(byte)184,(byte)38,(byte)119,(byte)153,(byte)227,(byte)165,
+	(byte)103,(byte)74,(byte)237,(byte)222,(byte)197,(byte)49,(byte)254,(byte)24,(byte)13,(byte)99,(byte)140,(byte)128,(byte)192,(byte)247,(byte)112,(byte)7};
+
+	private static final byte[] fbsub=
+	{(byte)99,(byte)124,(byte)119,(byte)123,(byte)242,(byte)107,(byte)111,(byte)197,(byte)48,(byte)1,(byte)103,(byte)43,(byte)254,(byte)215,(byte)171,(byte)118,
+	(byte)202,(byte)130,(byte)201,(byte)125,(byte)250,(byte)89,(byte)71,(byte)240,(byte)173,(byte)212,(byte)162,(byte)175,(byte)156,(byte)164,(byte)114,(byte)192,
+	(byte)183,(byte)253,(byte)147,(byte)38,(byte)54,(byte)63,(byte)247,(byte)204,(byte)52,(byte)165,(byte)229,(byte)241,(byte)113,(byte)216,(byte)49,(byte)21,
+	(byte)4,(byte)199,(byte)35,(byte)195,(byte)24,(byte)150,(byte)5,(byte)154,(byte)7,(byte)18,(byte)128,(byte)226,(byte)235,(byte)39,(byte)178,(byte)117,
+	(byte)9,(byte)131,(byte)44,(byte)26,(byte)27,(byte)110,(byte)90,(byte)160,(byte)82,(byte)59,(byte)214,(byte)179,(byte)41,(byte)227,(byte)47,(byte)132,
+	(byte)83,(byte)209,(byte)0,(byte)237,(byte)32,(byte)252,(byte)177,(byte)91,(byte)106,(byte)203,(byte)190,(byte)57,(byte)74,(byte)76,(byte)88,(byte)207,
+	(byte)208,(byte)239,(byte)170,(byte)251,(byte)67,(byte)77,(byte)51,(byte)133,(byte)69,(byte)249,(byte)2,(byte)127,(byte)80,(byte)60,(byte)159,(byte)168,
+	(byte)81,(byte)163,(byte)64,(byte)143,(byte)146,(byte)157,(byte)56,(byte)245,(byte)188,(byte)182,(byte)218,(byte)33,(byte)16,(byte)255,(byte)243,(byte)210,
+	(byte)205,(byte)12,(byte)19,(byte)236,(byte)95,(byte)151,(byte)68,(byte)23,(byte)196,(byte)167,(byte)126,(byte)61,(byte)100,(byte)93,(byte)25,(byte)115,
+	(byte)96,(byte)129,(byte)79,(byte)220,(byte)34,(byte)42,(byte)144,(byte)136,(byte)70,(byte)238,(byte)184,(byte)20,(byte)222,(byte)94,(byte)11,(byte)219,
+	(byte)224,(byte)50,(byte)58,(byte)10,(byte)73,(byte)6,(byte)36,(byte)92,(byte)194,(byte)211,(byte)172,(byte)98,(byte)145,(byte)149,(byte)228,(byte)121,
+	(byte)231,(byte)200,(byte)55,(byte)109,(byte)141,(byte)213,(byte)78,(byte)169,(byte)108,(byte)86,(byte)244,(byte)234,(byte)101,(byte)122,(byte)174,(byte)8,
+	(byte)186,(byte)120,(byte)37,(byte)46,(byte)28,(byte)166,(byte)180,(byte)198,(byte)232,(byte)221,(byte)116,(byte)31,(byte)75,(byte)189,(byte)139,(byte)138,
+	(byte)112,(byte)62,(byte)181,(byte)102,(byte)72,(byte)3,(byte)246,(byte)14,(byte)97,(byte)53,(byte)87,(byte)185,(byte)134,(byte)193,(byte)29,(byte)158,
+	(byte)225,(byte)248,(byte)152,(byte)17,(byte)105,(byte)217,(byte)142,(byte)148,(byte)155,(byte)30,(byte)135,(byte)233,(byte)206,(byte)85,(byte)40,(byte)223,
+	(byte)140,(byte)161,(byte)137,(byte)13,(byte)191,(byte)230,(byte)66,(byte)104,(byte)65,(byte)153,(byte)45,(byte)15,(byte)176,(byte)84,(byte)187,(byte)22};
+
+	private static final byte[] rbsub=
+	{(byte)82,(byte)9,(byte)106,(byte)213,(byte)48,(byte)54,(byte)165,(byte)56,(byte)191,(byte)64,(byte)163,(byte)158,(byte)129,(byte)243,(byte)215,(byte)251,
+	(byte)124,(byte)227,(byte)57,(byte)130,(byte)155,(byte)47,(byte)255,(byte)135,(byte)52,(byte)142,(byte)67,(byte)68,(byte)196,(byte)222,(byte)233,(byte)203,
+	(byte)84,(byte)123,(byte)148,(byte)50,(byte)166,(byte)194,(byte)35,(byte)61,(byte)238,(byte)76,(byte)149,(byte)11,(byte)66,(byte)250,(byte)195,(byte)78,
+	(byte)8,(byte)46,(byte)161,(byte)102,(byte)40,(byte)217,(byte)36,(byte)178,(byte)118,(byte)91,(byte)162,(byte)73,(byte)109,(byte)139,(byte)209,(byte)37,
+	(byte)114,(byte)248,(byte)246,(byte)100,(byte)134,(byte)104,(byte)152,(byte)22,(byte)212,(byte)164,(byte)92,(byte)204,(byte)93,(byte)101,(byte)182,(byte)146,
+	(byte)108,(byte)112,(byte)72,(byte)80,(byte)253,(byte)237,(byte)185,(byte)218,(byte)94,(byte)21,(byte)70,(byte)87,(byte)167,(byte)141,(byte)157,(byte)132,
+	(byte)144,(byte)216,(byte)171,(byte)0,(byte)140,(byte)188,(byte)211,(byte)10,(byte)247,(byte)228,(byte)88,(byte)5,(byte)184,(byte)179,(byte)69,(byte)6,
+	(byte)208,(byte)44,(byte)30,(byte)143,(byte)202,(byte)63,(byte)15,(byte)2,(byte)193,(byte)175,(byte)189,(byte)3,(byte)1,(byte)19,(byte)138,(byte)107,
+	(byte)58,(byte)145,(byte)17,(byte)65,(byte)79,(byte)103,(byte)220,(byte)234,(byte)151,(byte)242,(byte)207,(byte)206,(byte)240,(byte)180,(byte)230,(byte)115,
+	(byte)150,(byte)172,(byte)116,(byte)34,(byte)231,(byte)173,(byte)53,(byte)133,(byte)226,(byte)249,(byte)55,(byte)232,(byte)28,(byte)117,(byte)223,(byte)110,
+	(byte)71,(byte)241,(byte)26,(byte)113,(byte)29,(byte)41,(byte)197,(byte)137,(byte)111,(byte)183,(byte)98,(byte)14,(byte)170,(byte)24,(byte)190,(byte)27,
+	(byte)252,(byte)86,(byte)62,(byte)75,(byte)198,(byte)210,(byte)121,(byte)32,(byte)154,(byte)219,(byte)192,(byte)254,(byte)120,(byte)205,(byte)90,(byte)244,
+	(byte)31,(byte)221,(byte)168,(byte)51,(byte)136,(byte)7,(byte)199,(byte)49,(byte)177,(byte)18,(byte)16,(byte)89,(byte)39,(byte)128,(byte)236,(byte)95,
+	(byte)96,(byte)81,(byte)127,(byte)169,(byte)25,(byte)181,(byte)74,(byte)13,(byte)45,(byte)229,(byte)122,(byte)159,(byte)147,(byte)201,(byte)156,(byte)239,
+	(byte)160,(byte)224,(byte)59,(byte)77,(byte)174,(byte)42,(byte)245,(byte)176,(byte)200,(byte)235,(byte)187,(byte)60,(byte)131,(byte)83,(byte)153,(byte)97,
+	(byte)23,(byte)43,(byte)4,(byte)126,(byte)186,(byte)119,(byte)214,(byte)38,(byte)225,(byte)105,(byte)20,(byte)99,(byte)85,(byte)33,(byte)12,(byte)125};
+
+	private static final byte[] rco=
+	{(byte)1,(byte)2,(byte)4,(byte)8,(byte)16,(byte)32,(byte)64,(byte)128,(byte)27,(byte)54,(byte)108,(byte)216,(byte)171,(byte)77,(byte)154,(byte)47};
+
+	private static final int[] ftable=
+	{0xa56363c6,0x847c7cf8,0x997777ee,0x8d7b7bf6,0xdf2f2ff,0xbd6b6bd6,
+	0xb16f6fde,0x54c5c591,0x50303060,0x3010102,0xa96767ce,0x7d2b2b56,
+	0x19fefee7,0x62d7d7b5,0xe6abab4d,0x9a7676ec,0x45caca8f,0x9d82821f,
+	0x40c9c989,0x877d7dfa,0x15fafaef,0xeb5959b2,0xc947478e,0xbf0f0fb,
+	0xecadad41,0x67d4d4b3,0xfda2a25f,0xeaafaf45,0xbf9c9c23,0xf7a4a453,
+	0x967272e4,0x5bc0c09b,0xc2b7b775,0x1cfdfde1,0xae93933d,0x6a26264c,
+	0x5a36366c,0x413f3f7e,0x2f7f7f5,0x4fcccc83,0x5c343468,0xf4a5a551,
+	0x34e5e5d1,0x8f1f1f9,0x937171e2,0x73d8d8ab,0x53313162,0x3f15152a,
+	0xc040408,0x52c7c795,0x65232346,0x5ec3c39d,0x28181830,0xa1969637,
+	0xf05050a,0xb59a9a2f,0x907070e,0x36121224,0x9b80801b,0x3de2e2df,
+	0x26ebebcd,0x6927274e,0xcdb2b27f,0x9f7575ea,0x1b090912,0x9e83831d,
+	0x742c2c58,0x2e1a1a34,0x2d1b1b36,0xb26e6edc,0xee5a5ab4,0xfba0a05b,
+	0xf65252a4,0x4d3b3b76,0x61d6d6b7,0xceb3b37d,0x7b292952,0x3ee3e3dd,
+	0x712f2f5e,0x97848413,0xf55353a6,0x68d1d1b9,0x0,0x2cededc1,
+	0x60202040,0x1ffcfce3,0xc8b1b179,0xed5b5bb6,0xbe6a6ad4,0x46cbcb8d,
+	0xd9bebe67,0x4b393972,0xde4a4a94,0xd44c4c98,0xe85858b0,0x4acfcf85,
+	0x6bd0d0bb,0x2aefefc5,0xe5aaaa4f,0x16fbfbed,0xc5434386,0xd74d4d9a,
+	0x55333366,0x94858511,0xcf45458a,0x10f9f9e9,0x6020204,0x817f7ffe,
+	0xf05050a0,0x443c3c78,0xba9f9f25,0xe3a8a84b,0xf35151a2,0xfea3a35d,
+	0xc0404080,0x8a8f8f05,0xad92923f,0xbc9d9d21,0x48383870,0x4f5f5f1,
+	0xdfbcbc63,0xc1b6b677,0x75dadaaf,0x63212142,0x30101020,0x1affffe5,
+	0xef3f3fd,0x6dd2d2bf,0x4ccdcd81,0x140c0c18,0x35131326,0x2fececc3,
+	0xe15f5fbe,0xa2979735,0xcc444488,0x3917172e,0x57c4c493,0xf2a7a755,
+	0x827e7efc,0x473d3d7a,0xac6464c8,0xe75d5dba,0x2b191932,0x957373e6,
+	0xa06060c0,0x98818119,0xd14f4f9e,0x7fdcdca3,0x66222244,0x7e2a2a54,
+	0xab90903b,0x8388880b,0xca46468c,0x29eeeec7,0xd3b8b86b,0x3c141428,
+	0x79dedea7,0xe25e5ebc,0x1d0b0b16,0x76dbdbad,0x3be0e0db,0x56323264,
+	0x4e3a3a74,0x1e0a0a14,0xdb494992,0xa06060c,0x6c242448,0xe45c5cb8,
+	0x5dc2c29f,0x6ed3d3bd,0xefacac43,0xa66262c4,0xa8919139,0xa4959531,
+	0x37e4e4d3,0x8b7979f2,0x32e7e7d5,0x43c8c88b,0x5937376e,0xb76d6dda,
+	0x8c8d8d01,0x64d5d5b1,0xd24e4e9c,0xe0a9a949,0xb46c6cd8,0xfa5656ac,
+	0x7f4f4f3,0x25eaeacf,0xaf6565ca,0x8e7a7af4,0xe9aeae47,0x18080810,
+	0xd5baba6f,0x887878f0,0x6f25254a,0x722e2e5c,0x241c1c38,0xf1a6a657,
+	0xc7b4b473,0x51c6c697,0x23e8e8cb,0x7cdddda1,0x9c7474e8,0x211f1f3e,
+	0xdd4b4b96,0xdcbdbd61,0x868b8b0d,0x858a8a0f,0x907070e0,0x423e3e7c,
+	0xc4b5b571,0xaa6666cc,0xd8484890,0x5030306,0x1f6f6f7,0x120e0e1c,
+	0xa36161c2,0x5f35356a,0xf95757ae,0xd0b9b969,0x91868617,0x58c1c199,
+	0x271d1d3a,0xb99e9e27,0x38e1e1d9,0x13f8f8eb,0xb398982b,0x33111122,
+	0xbb6969d2,0x70d9d9a9,0x898e8e07,0xa7949433,0xb69b9b2d,0x221e1e3c,
+	0x92878715,0x20e9e9c9,0x49cece87,0xff5555aa,0x78282850,0x7adfdfa5,
+	0x8f8c8c03,0xf8a1a159,0x80898909,0x170d0d1a,0xdabfbf65,0x31e6e6d7,
+	0xc6424284,0xb86868d0,0xc3414182,0xb0999929,0x772d2d5a,0x110f0f1e,
+	0xcbb0b07b,0xfc5454a8,0xd6bbbb6d,0x3a16162c};
+
+	private static final int[] rtable=
+	{0x50a7f451,0x5365417e,0xc3a4171a,0x965e273a,0xcb6bab3b,0xf1459d1f,
+	0xab58faac,0x9303e34b,0x55fa3020,0xf66d76ad,0x9176cc88,0x254c02f5,
+	0xfcd7e54f,0xd7cb2ac5,0x80443526,0x8fa362b5,0x495ab1de,0x671bba25,
+	0x980eea45,0xe1c0fe5d,0x2752fc3,0x12f04c81,0xa397468d,0xc6f9d36b,
+	0xe75f8f03,0x959c9215,0xeb7a6dbf,0xda595295,0x2d83bed4,0xd3217458,
+	0x2969e049,0x44c8c98e,0x6a89c275,0x78798ef4,0x6b3e5899,0xdd71b927,
+	0xb64fe1be,0x17ad88f0,0x66ac20c9,0xb43ace7d,0x184adf63,0x82311ae5,
+	0x60335197,0x457f5362,0xe07764b1,0x84ae6bbb,0x1ca081fe,0x942b08f9,
+	0x58684870,0x19fd458f,0x876cde94,0xb7f87b52,0x23d373ab,0xe2024b72,
+	0x578f1fe3,0x2aab5566,0x728ebb2,0x3c2b52f,0x9a7bc586,0xa50837d3,
+	0xf2872830,0xb2a5bf23,0xba6a0302,0x5c8216ed,0x2b1ccf8a,0x92b479a7,
+	0xf0f207f3,0xa1e2694e,0xcdf4da65,0xd5be0506,0x1f6234d1,0x8afea6c4,
+	0x9d532e34,0xa055f3a2,0x32e18a05,0x75ebf6a4,0x39ec830b,0xaaef6040,
+	0x69f715e,0x51106ebd,0xf98a213e,0x3d06dd96,0xae053edd,0x46bde64d,
+	0xb58d5491,0x55dc471,0x6fd40604,0xff155060,0x24fb9819,0x97e9bdd6,
+	0xcc434089,0x779ed967,0xbd42e8b0,0x888b8907,0x385b19e7,0xdbeec879,
+	0x470a7ca1,0xe90f427c,0xc91e84f8,0x0,0x83868009,0x48ed2b32,
+	0xac70111e,0x4e725a6c,0xfbff0efd,0x5638850f,0x1ed5ae3d,0x27392d36,
+	0x64d90f0a,0x21a65c68,0xd1545b9b,0x3a2e3624,0xb1670a0c,0xfe75793,
+	0xd296eeb4,0x9e919b1b,0x4fc5c080,0xa220dc61,0x694b775a,0x161a121c,
+	0xaba93e2,0xe52aa0c0,0x43e0223c,0x1d171b12,0xb0d090e,0xadc78bf2,
+	0xb9a8b62d,0xc8a91e14,0x8519f157,0x4c0775af,0xbbdd99ee,0xfd607fa3,
+	0x9f2601f7,0xbcf5725c,0xc53b6644,0x347efb5b,0x7629438b,0xdcc623cb,
+	0x68fcedb6,0x63f1e4b8,0xcadc31d7,0x10856342,0x40229713,0x2011c684,
+	0x7d244a85,0xf83dbbd2,0x1132f9ae,0x6da129c7,0x4b2f9e1d,0xf330b2dc,
+	0xec52860d,0xd0e3c177,0x6c16b32b,0x99b970a9,0xfa489411,0x2264e947,
+	0xc48cfca8,0x1a3ff0a0,0xd82c7d56,0xef903322,0xc74e4987,0xc1d138d9,
+	0xfea2ca8c,0x360bd498,0xcf81f5a6,0x28de7aa5,0x268eb7da,0xa4bfad3f,
+	0xe49d3a2c,0xd927850,0x9bcc5f6a,0x62467e54,0xc2138df6,0xe8b8d890,
+	0x5ef7392e,0xf5afc382,0xbe805d9f,0x7c93d069,0xa92dd56f,0xb31225cf,
+	0x3b99acc8,0xa77d1810,0x6e639ce8,0x7bbb3bdb,0x97826cd,0xf418596e,
+	0x1b79aec,0xa89a4f83,0x656e95e6,0x7ee6ffaa,0x8cfbc21,0xe6e815ef,
+	0xd99be7ba,0xce366f4a,0xd4099fea,0xd67cb029,0xafb2a431,0x31233f2a,
+	0x3094a5c6,0xc066a235,0x37bc4e74,0xa6ca82fc,0xb0d090e0,0x15d8a733,
+	0x4a9804f1,0xf7daec41,0xe50cd7f,0x2ff69117,0x8dd64d76,0x4db0ef43,
+	0x544daacc,0xdf0496e4,0xe3b5d19e,0x1b886a4c,0xb81f2cc1,0x7f516546,
+	0x4ea5e9d,0x5d358c01,0x737487fa,0x2e410bfb,0x5a1d67b3,0x52d2db92,
+	0x335610e9,0x1347d66d,0x8c61d79a,0x7a0ca137,0x8e14f859,0x893c13eb,
+	0xee27a9ce,0x35c961b7,0xede51ce1,0x3cb1477a,0x59dfd29c,0x3f73f255,
+	0x79ce1418,0xbf37c773,0xeacdf753,0x5baafd5f,0x146f3ddf,0x86db4478,
+	0x81f3afca,0x3ec468b9,0x2c342438,0x5f40a3c2,0x72c31d16,0xc25e2bc,
+	0x8b493c28,0x41950dff,0x7101a839,0xdeb30c08,0x9ce4b4d8,0x90c15664,
+	0x6184cb7b,0x70b632d5,0x745c6c48,0x4257b8d0};
+
+
+/* Rotates 32-bit word left by 1, 2 or 3 byte  */
+
+	private static int ROTL8(int x)
+	{
+		return (((x)<<8)|((x)>>>24));
+	}
+
+	private static int ROTL16(int x)
+	{
+		return (((x)<<16)|((x)>>>16));
+	}
+
+	private static int ROTL24(int x)
+	{
+		return (((x)<<24)|((x)>>>8));
+	}
+
+	private static int pack(byte[] b)
+	{ /* pack bytes into a 32-bit Word */
+		return ((((int)b[3])&0xff)<<24)|(((int)b[2]&0xff)<<16)|(((int)b[1]&0xff)<<8)|((int)b[0]&0xff);
+	}
+
+	private static byte[] unpack(int a)
+	{ /* unpack bytes from a word */
+		byte [] b=new byte[4];
+		b[0]=(byte)(a);
+		b[1]=(byte)(a>>>8);
+		b[2]=(byte)(a>>>16);
+		b[3]=(byte)(a>>>24);
+		return b;
+	}
+
+	private static byte bmul(byte x,byte y)
+	{ /* x.y= AntiLog(Log(x) + Log(y)) */
+
+		int ix=((int)x)&0xff;
+		int iy=((int)y)&0xff;
+		int lx=((int)ltab[ix])&0xff;
+		int ly=((int)ltab[iy])&0xff;
+		if (x!=0 && y!=0) return ptab[(lx+ly)%255];
+		else return (byte)0;
+	}
+
+  //  if (x && y) 
+
+	private static int SubByte(int a)
+	{
+		byte [] b=unpack(a);
+		b[0]=fbsub[(int)b[0]&0xff];
+		b[1]=fbsub[(int)b[1]&0xff];
+		b[2]=fbsub[(int)b[2]&0xff];
+		b[3]=fbsub[(int)b[3]&0xff];
+		return pack(b);    
+	}
+
+	private static byte product(int x,int y)
+	{ /* dot product of two 4-byte arrays */
+		byte [] xb;//=new byte[4];
+		byte [] yb;//=new byte[4];
+		xb=unpack(x);
+		yb=unpack(y); 
+
+		return (byte)(bmul(xb[0],yb[0])^bmul(xb[1],yb[1])^bmul(xb[2],yb[2])^bmul(xb[3],yb[3]));
+	}
+
+	private static int InvMixCol(int x)
+	{ /* matrix Multiplication */
+		int y,m;
+		byte [] b=new byte[4];
+
+		m=pack(InCo);
+		b[3]=product(m,x);
+		m=ROTL24(m);
+		b[2]=product(m,x);
+		m=ROTL24(m);
+		b[1]=product(m,x);
+		m=ROTL24(m);
+		b[0]=product(m,x);
+		y=pack(b);
+		return y;
+	}
+
+	private static void increment(byte [] f)
+	{
+		int i;
+		for (i=0;i<16;i++)
+		{
+			f[i]++;
+			if (f[i]!=0) break;
+		}
+	}
+
+/* reset cipher */
+	public void reset(int m,byte[] iv)
+	{ /* reset mode, or reset iv */
+		mode=m;
+		for (int i=0;i<16;i++)
+			f[i]=0;
+		if (mode!=ECB && iv!=null)
+			for (int i=0;i<16;i++)
+				f[i]=iv[i];
+	}
+
+	public byte[] getreg()
+	{
+		byte [] ir=new byte[16];
+		for (int i=0;i<16;i++) ir[i]=f[i];
+		return ir;
+	}
+
+/* Initialise cipher */
+	public boolean init(int m,int nk,byte[] key,byte[] iv)
+	{	/* Key=16 bytes */
+		/* Key Scheduler. Create expanded encryption key */
+		int i,j,k,N,nr;
+		int [] CipherKey=new int[8];
+		byte [] b=new byte[4];
+		nk/=4;
+
+		if (nk!=4 && nk!=6 && nk!=8) return false;
+
+		nr=6+nk;
+
+		Nk=nk; Nr=nr;
+
+		reset(m,iv);
+		N=4*(nr+1);
+    
+		for (i=j=0;i<nk;i++,j+=4)
+		{
+			for (k=0;k<4;k++) b[k]=key[j+k];
+			CipherKey[i]=pack(b);
+		}
+		for (i=0;i<nk;i++) fkey[i]=CipherKey[i];
+		for (j=nk,k=0;j<N;j+=nk,k++)
+		{
+			fkey[j]=fkey[j-nk]^SubByte(ROTL24(fkey[j-1]))^((int)rco[k])&0xff;
+			for (i=1;i<nk && (i+j)<N;i++)
+				fkey[i+j]=fkey[i+j-nk]^fkey[i+j-1];
+		}
+
+ /* now for the expanded decrypt key in reverse order */
+
+		for (j=0;j<4;j++) rkey[j+N-4]=fkey[j]; 
+		for (i=4;i<N-4;i+=4)
+		{
+			k=N-4-i;
+			for (j=0;j<4;j++) rkey[k+j]=InvMixCol(fkey[i+j]);
+		}
+		for (j=N-4;j<N;j++) rkey[j-N+4]=fkey[j];
+		return true;
+	}
+
+/* Encrypt a single block */
+	public void ecb_encrypt(byte[] buff)
+	{
+		int i,j,k;
+		int t;
+    	byte [] b=new byte[4];
+    	int [] p=new int[4];
+    	int [] q=new int[4];
+
+		for (i=j=0;i<4;i++,j+=4)
+		{
+			for (k=0;k<4;k++) b[k]=buff[j+k];
+			p[i]=pack(b);
+			p[i]^=fkey[i];
+		}
+
+		k=4;
+
+/* State alternates between p and q */
+		for (i=1;i<Nr;i++)
+		{ 
+			q[0]=fkey[k]^ftable[p[0]&0xff]^
+				ROTL8(ftable[(p[1]>>>8)&0xff])^
+				ROTL16(ftable[(p[2]>>>16)&0xff])^
+				ROTL24(ftable[(p[3]>>>24)&0xff]);
+			q[1]=fkey[k+1]^ftable[p[1]&0xff]^
+				ROTL8(ftable[(p[2]>>>8)&0xff])^
+				ROTL16(ftable[(p[3]>>>16)&0xff])^
+				ROTL24(ftable[(p[0]>>>24)&0xff]);
+			q[2]=fkey[k+2]^ftable[p[2]&0xff]^
+				ROTL8(ftable[(p[3]>>>8)&0xff])^
+				ROTL16(ftable[(p[0]>>>16)&0xff])^
+				ROTL24(ftable[(p[1]>>>24)&0xff]);
+			q[3]=fkey[k+3]^ftable[p[3]&0xff]^
+				ROTL8(ftable[(p[0]>>>8)&0xff])^
+				ROTL16(ftable[(p[1]>>>16)&0xff])^
+				ROTL24(ftable[(p[2]>>>24)&0xff]);
+
+			k+=4;
+			for (j=0;j<4;j++)
+			{
+				t=p[j]; p[j]=q[j]; q[j]=t;
+			}
+		}
+
+/* Last Round */ 
+    
+		q[0]=fkey[k]^((int)fbsub[p[0]&0xff]&0xff)^
+			ROTL8((int)fbsub[(p[1]>>>8)&0xff]&0xff)^
+			ROTL16((int)fbsub[(p[2]>>>16)&0xff]&0xff)^
+			ROTL24((int)fbsub[(p[3]>>>24)&0xff]&0xff);
+
+		q[1]=fkey[k+1]^((int)fbsub[p[1]&0xff]&0xff)^
+			ROTL8((int)fbsub[(p[2]>>>8)&0xff]&0xff)^
+			ROTL16((int)fbsub[(p[3]>>>16)&0xff]&0xff)^
+			ROTL24((int)fbsub[(p[0]>>>24)&0xff]&0xff);
+
+		q[2]=fkey[k+2]^((int)fbsub[p[2]&0xff]&0xff)^
+			ROTL8((int)fbsub[(p[3]>>>8)&0xff]&0xff)^
+			ROTL16((int)fbsub[(p[0]>>>16)&0xff]&0xff)^
+			ROTL24((int)fbsub[(p[1]>>>24)&0xff]&0xff);
+
+		q[3]=fkey[k+3]^((int)fbsub[(p[3])&0xff]&0xff)^
+			ROTL8((int)fbsub[(p[0]>>>8)&0xff]&0xff)^
+			ROTL16((int)fbsub[(p[1]>>>16)&0xff]&0xff)^
+			ROTL24((int)fbsub[(p[2]>>>24)&0xff]&0xff);
+
+		for (i=j=0;i<4;i++,j+=4)
+		{
+			b=unpack(q[i]);
+			for (k=0;k<4;k++) buff[j+k]=b[k];
+		}
+	}
+
+/* Decrypt a single block */
+	public void ecb_decrypt(byte[] buff)
+	{
+		int i,j,k;
+		int t;
+    	byte [] b=new byte[4];
+    	int [] p=new int[4];
+    	int [] q=new int[4];
+
+		for (i=j=0;i<4;i++,j+=4)
+		{
+			for (k=0;k<4;k++) b[k]=buff[j+k];
+			p[i]=pack(b);
+			p[i]^=rkey[i];
+		}
+
+		k=4;
+
+/* State alternates between p and q */
+		for (i=1;i<Nr;i++)
+		{ 
+			q[0]=rkey[k]^rtable[p[0]&0xff]^
+				ROTL8(rtable[(p[3]>>>8)&0xff])^
+				ROTL16(rtable[(p[2]>>>16)&0xff])^
+				ROTL24(rtable[(p[1]>>>24)&0xff]);
+			q[1]=rkey[k+1]^rtable[p[1]&0xff]^
+				ROTL8(rtable[(p[0]>>>8)&0xff])^
+				ROTL16(rtable[(p[3]>>>16)&0xff])^
+				ROTL24(rtable[(p[2]>>>24)&0xff]);
+			q[2]=rkey[k+2]^rtable[p[2]&0xff]^
+				ROTL8(rtable[(p[1]>>>8)&0xff])^
+				ROTL16(rtable[(p[0]>>>16)&0xff])^
+				ROTL24(rtable[(p[3]>>>24)&0xff]);
+			q[3]=rkey[k+3]^rtable[p[3]&0xff]^
+				ROTL8(rtable[(p[2]>>>8)&0xff])^
+				ROTL16(rtable[(p[1]>>>16)&0xff])^
+				ROTL24(rtable[(p[0]>>>24)&0xff]);
+
+			k+=4;
+			for (j=0;j<4;j++)
+			{
+				t=p[j]; p[j]=q[j]; q[j]=t;
+			}
+		}
+
+/* Last Round */ 
+
+		q[0]=rkey[k]^((int)rbsub[p[0]&0xff]&0xff)^
+			ROTL8((int)rbsub[(p[3]>>>8)&0xff]&0xff)^
+			ROTL16((int)rbsub[(p[2]>>>16)&0xff]&0xff)^
+			ROTL24((int)rbsub[(p[1]>>>24)&0xff]&0xff);
+		q[1]=rkey[k+1]^((int)rbsub[p[1]&0xff]&0xff)^
+			ROTL8((int)rbsub[(p[0]>>>8)&0xff]&0xff)^
+			ROTL16((int)rbsub[(p[3]>>>16)&0xff]&0xff)^
+			ROTL24((int)rbsub[(p[2]>>>24)&0xff]&0xff);
+		q[2]=rkey[k+2]^((int)rbsub[p[2]&0xff]&0xff)^
+			ROTL8((int)rbsub[(p[1]>>>8)&0xff]&0xff)^
+			ROTL16((int)rbsub[(p[0]>>>16)&0xff]&0xff)^
+			ROTL24((int)rbsub[(p[3]>>>24)&0xff]&0xff);
+		q[3]=rkey[k+3]^((int)rbsub[p[3]&0xff]&0xff)^
+			ROTL8((int)rbsub[(p[2]>>>8)&0xff]&0xff)^
+			ROTL16((int)rbsub[(p[1]>>>16)&0xff]&0xff)^
+			ROTL24((int)rbsub[(p[0]>>>24)&0xff]&0xff);
+
+		for (i=j=0;i<4;i++,j+=4)
+		{
+			b=unpack(q[i]);
+			for (k=0;k<4;k++) buff[j+k]=b[k];
+		}
+
+	}
+
+/* Encrypt using selected mode of operation */
+	public int encrypt(byte[] buff)
+	{
+		int j,bytes;
+		byte[] st=new byte[16];
+		int fell_off;
+
+// Supported Modes of Operation 
+
+		fell_off=0;
+		switch (mode)
+		{
+		case ECB: 
+			ecb_encrypt(buff);
+			return 0;
+		case CBC:
+			for (j=0;j<16;j++) buff[j]^=f[j];
+			ecb_encrypt(buff);
+			for (j=0;j<16;j++) f[j]=buff[j];
+			return 0;
+
+		case CFB1:
+		case CFB2:
+		case CFB4:
+			bytes=mode-CFB1+1;
+			for (j=0;j<bytes;j++) fell_off=(fell_off<<8)|f[j];
+			for (j=0;j<16;j++) st[j]=f[j];
+			for (j=bytes;j<16;j++) f[j-bytes]=f[j];
+			ecb_encrypt(st);
+			for (j=0;j<bytes;j++) 
+			{
+				buff[j]^=st[j];
+				f[16-bytes+j]=buff[j];
+			}
+			return fell_off;
+
+		case OFB1:
+		case OFB2:
+		case OFB4:
+		case OFB8:
+		case OFB16:
+
+			bytes=mode-OFB1+1;
+			ecb_encrypt(f);
+			for (j=0;j<bytes;j++) buff[j]^=f[j];
+			return 0;
+
+		case CTR1:
+		case CTR2:
+		case CTR4:
+		case CTR8:
+		case CTR16:
+
+			bytes=mode-CTR1+1;
+			for (j=0;j<16;j++) st[j]=f[j];
+			ecb_encrypt(st);
+			for (j=0;j<bytes;j++) buff[j]^=st[j];
+			increment(f);
+
+    default:
+			return 0;
+		}
+	}
+
+/* Decrypt using selected mode of operation */
+	public int decrypt(byte[] buff)
+	{
+		int j,bytes;
+		byte[] st=new byte[16];
+		int fell_off;
+
+   // Supported modes of operation 
+		fell_off=0;
+		switch (mode)
+		{
+		case ECB:
+			ecb_decrypt(buff);
+			return 0;
+		case CBC:
+			for (j=0;j<16;j++) 
+			{
+				st[j]=f[j];
+				f[j]=buff[j];
+			}
+			ecb_decrypt(buff);
+			for (j=0;j<16;j++)
+			{	 
+				buff[j]^=st[j];
+				st[j]=0;
+			}
+			return 0;
+		case CFB1:
+		case CFB2:
+		case CFB4:
+			bytes=mode-CFB1+1;
+			for (j=0;j<bytes;j++) fell_off=(fell_off<<8)|f[j];
+			for (j=0;j<16;j++) st[j]=f[j];
+			for (j=bytes;j<16;j++) f[j-bytes]=f[j];
+			ecb_encrypt(st);
+			for (j=0;j<bytes;j++)
+			{
+				f[16-bytes+j]=buff[j];
+				buff[j]^=st[j];
+			}
+			return fell_off;
+		case OFB1:
+		case OFB2:
+		case OFB4:
+		case OFB8:
+		case OFB16:
+			bytes=mode-OFB1+1;
+			ecb_encrypt(f);
+			for (j=0;j<bytes;j++) buff[j]^=f[j];
+			return 0;
+
+		case CTR1:
+		case CTR2:
+		case CTR4:
+		case CTR8:
+		case CTR16:
+
+			bytes=mode-CTR1+1;
+			for (j=0;j<16;j++) st[j]=f[j];
+			ecb_encrypt(st);
+			for (j=0;j<bytes;j++) buff[j]^=st[j];
+			increment(f);
+ 
+		default:
+			return 0;
+		}
+	}
+
+/* Clean up and delete left-overs */
+	public void end()
+	{ // clean up 
+		int i;
+		for (i=0;i<4*(Nr+1);i++)
+			fkey[i]=rkey[i]=0;
+		for (i=0;i<16;i++)
+			f[i]=0;
+	}
+
+	public static void main(String[] args) {
+		int i;
+
+		byte[] key=new byte[32];
+		byte[] block=new byte[16];
+		byte[] iv=new byte[16];
+
+		for (i=0;i<32;i++) key[i]=0;
+		key[0]=1;
+		for (i=0;i<16;i++) iv[i]=(byte)i;
+		for (i=0;i<16;i++) block[i]=(byte)i;
+
+		AES a=new AES();
+
+		a.init(CTR16,32,key,iv);
+		System.out.println("Plain= "); 
+		for (i=0;i<16;i++)  System.out.format("%02X ", block[i]&0xff);
+		System.out.println(""); 
+
+		a.encrypt(block);
+
+		System.out.println("Encrypt= "); 
+		for (i=0;i<16;i++)  System.out.format("%02X ", block[i]&0xff);
+		System.out.println(""); 
+
+		a.reset(CTR16,iv);
+		a.decrypt(block);
+
+		System.out.println("Decrypt= "); 
+		for (i=0;i<16;i++)  System.out.format("%02X ", block[i]&0xff);
+		System.out.println(""); 
+
+		a.end();
+
+	} 
+}
diff --git a/version22/java/BIG32.java b/version22/java/BIG32.java
new file mode 100644
index 0000000..e43e7b4
--- /dev/null
+++ b/version22/java/BIG32.java
@@ -0,0 +1,1016 @@
+/*
+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.
+*/
+
+/* AMCL BIG number class */ 
+
+public class BIG {
+	protected int[] w=new int[ROM.NLEN];
+/* Constructors */
+
+	public BIG()
+	{
+		for (int i=0;i<ROM.NLEN;i++)
+			w[i]=0;
+	}
+
+	public BIG(int x)
+	{
+		w[0]=x;
+		for (int i=1;i<ROM.NLEN;i++)
+			w[i]=0;
+	}
+
+	public BIG(BIG x)
+	{
+		for (int i=0;i<ROM.NLEN;i++)
+			w[i]=x.w[i];
+	}
+
+	public BIG(DBIG x)
+	{
+		for (int i=0;i<ROM.NLEN;i++)
+			w[i]=x.w[i];
+	}
+
+	public BIG(int[] x)
+	{
+		for (int i=0;i<ROM.NLEN;i++)
+			w[i]=x[i];
+	}
+
+	public int get(int i)
+	{
+		return w[i];
+	}
+
+	public void set(int i,int x)
+	{
+		w[i]=x;
+	} 
+
+/* calculate Field Excess */
+	public static int EXCESS(BIG a)
+	{
+		return ((a.w[ROM.NLEN-1]&ROM.OMASK)>>(ROM.MODBITS%ROM.BASEBITS));
+	}
+
+/* Check if product causes excess */
+	public static boolean pexceed(BIG a,BIG b)
+	{
+		int ea,eb;
+		ea=EXCESS(a);
+		eb=EXCESS(b);
+		if ((long)(ea+1)*(eb+1)>ROM.FEXCESS) return true;
+		return false;
+	}
+
+/* Check if square causes excess */
+	public static boolean sexceed(BIG a)
+	{
+		int ea,eb;
+		ea=EXCESS(a);
+		if ((long)(ea+1)*(ea+1)>ROM.FEXCESS) return true;
+		return false;
+	}
+
+	public static int FF_EXCESS(BIG a)
+	{
+		return ((a.get(ROM.NLEN-1)&ROM.P_OMASK)>>(ROM.P_TBITS));
+	}
+
+/* Check if product causes excess */
+	public static boolean ff_pexceed(BIG a,BIG b)
+	{
+		int ea,eb;
+		ea=FF_EXCESS(a);
+		eb=FF_EXCESS(b);
+		if ((long)(ea+1)*(eb+1)>ROM.P_FEXCESS) return true;
+		return false;
+	}
+
+/* Check if square causes excess */
+	public static boolean ff_sexceed(BIG a)
+	{
+		int ea;
+		ea=FF_EXCESS(a);
+		if ((long)(ea+1)*(ea+1)>ROM.P_FEXCESS) return true;
+		return false;
+	}
+
+/* Conditional swap of two bigs depending on d using XOR - no branches */
+	public void cswap(BIG b,int d)
+	{
+		int i;
+		int t,c=d;
+		c=~(c-1);
+
+		for (i=0;i<ROM.NLEN;i++)
+		{
+			t=c&(w[i]^b.w[i]);
+			w[i]^=t;
+			b.w[i]^=t;
+		}
+	}
+
+	public void cmove(BIG g,int d)
+	{
+		int i;
+		int b=-d;
+
+		for (i=0;i<ROM.NLEN;i++)
+		{
+			w[i]^=(w[i]^g.w[i])&b;
+		}
+	}
+
+    public static int cast_to_chunk(int x)
+	{
+		return (int)x;
+	}
+
+/* normalise BIG - force all digits < 2^BASEBITS */
+	public long norm() {
+		int d,carry=0;
+		for (int i=0;i<ROM.NLEN-1;i++)
+		{
+			d=w[i]+carry;
+			w[i]=d&ROM.BMASK;
+			carry=d>>ROM.BASEBITS;
+		}
+		w[ROM.NLEN-1]=(w[ROM.NLEN-1]+carry);
+		return (long)(w[ROM.NLEN-1]>>((8*ROM.MODBYTES)%ROM.BASEBITS));  
+	}
+
+/* return number of bits */
+	public int nbits() {
+		int bts,k=ROM.NLEN-1;
+		int c;
+		norm();
+		while (k>=0 && w[k]==0) k--;
+		if (k<0) return 0;
+		bts=ROM.BASEBITS*k;
+		c=w[k];
+		while (c!=0) {c/=2; bts++;}
+		return bts;
+	}
+
+	public String toRawString()
+	{
+		BIG b=new BIG(this);
+		String s="(";
+		for (int i=0;i<ROM.NLEN-1;i++)
+		{
+			s+=Integer.toHexString(b.w[i]); s+=",";
+		}
+		s+=Integer.toHexString(b.w[ROM.NLEN-1]); s+=")";
+		return s;
+	}
+
+/* Convert to Hex String */
+	public String toString() {
+		BIG b;
+		String s="";
+		int len=nbits();
+
+		if (len%4==0) len/=4;
+		else {len/=4; len++;}
+		if (len<ROM.MODBYTES*2) len=ROM.MODBYTES*2;
+
+		for (int i=len-1;i>=0;i--)
+		{
+			b=new BIG(this);
+			b.shr(i*4);
+			s+=Integer.toHexString(b.w[0]&15);
+		}
+		return s;
+	}
+
+	public static int[] muladd(int x,int y,int c,int r)
+	{
+		int[] tb=new int[2];
+		long prod=(long)x*y+c+r;	
+		tb[1]=(int)prod&ROM.BMASK;
+		tb[0]=(int)(prod>>ROM.BASEBITS);
+		return tb;
+	}
+
+/* this*=x, where x is >NEXCESS */
+	public int pmul(int c)
+	{
+		int ak,carry=0;
+		int[] cr=new int[2];
+
+		norm();
+		for (int i=0;i<ROM.NLEN;i++)
+		{
+			ak=w[i];
+			w[i]=0;
+			cr=muladd(ak,c,carry,w[i]);
+			carry=cr[0];
+			w[i]=cr[1];
+		}
+		return carry;
+	}
+
+/* this*=c and catch overflow in DBIG */
+	public DBIG pxmul(int c)
+	{
+		DBIG m=new DBIG(0);	
+		int[] cr=new int[2];	
+		int carry=0;
+		for (int j=0;j<ROM.NLEN;j++)
+		{
+			cr=muladd(w[j],c,carry,m.w[j]);
+			carry=cr[0];
+			m.w[j]=cr[1];
+		}
+		m.w[ROM.NLEN]=carry;		
+		return m;
+	}
+
+/* divide by 3 */
+	public int div3()
+	{	
+		int ak,base,carry=0;
+		norm();
+		base=((int)1<<ROM.BASEBITS);
+		for (int i=ROM.NLEN-1;i>=0;i--)
+		{
+			ak=(carry*base+w[i]);
+			w[i]=ak/3;
+			carry=ak%3;
+		}
+		return (int)carry;
+	}
+
+/* return a*b where result fits in a BIG */
+	public static BIG smul(BIG a,BIG b)
+	{
+		int carry;
+		BIG c=new BIG(0);
+		int[] cr=new int[2];			
+		for (int i=0;i<ROM.NLEN;i++)
+		{
+			carry=0;
+			for (int j=0;j<ROM.NLEN;j++)
+			{
+				if (i+j<ROM.NLEN) 
+				{
+					cr=muladd(a.w[i],b.w[j],carry,c.w[i+j]);
+					carry=cr[0];
+					c.w[i+j]=cr[1];
+				}
+			}
+		}
+		return c;
+	}
+
+/* return a*b as DBIG */
+	public static DBIG mul(BIG a,BIG b)
+	{
+		long t,co;
+		DBIG c=new DBIG(0);
+	//	a.norm();
+	//	b.norm();
+
+		long[] d=new long[ROM.NLEN];
+		long s;
+		int i,k;
+
+		for (i=0;i<ROM.NLEN;i++)
+			d[i]=(long)a.w[i]*b.w[i];
+
+		s=d[0];
+		t=s; c.w[0]=(int)t&ROM.BMASK; co=t>>ROM.BASEBITS;
+
+		for (k=1;k<ROM.NLEN;k++)
+		{
+			s+=d[k]; t=co+s; for (i=k;i>=1+k/2;i--) t+=(long)(a.w[i]-a.w[k-i])*(b.w[k-i]-b.w[i]); c.w[k]=(int)t&ROM.BMASK; co=t>>ROM.BASEBITS;
+		}
+		for (k=ROM.NLEN;k<2*ROM.NLEN-1;k++)
+		{
+			s-=d[k-ROM.NLEN]; t=co+s; for (i=ROM.NLEN-1;i>=1+k/2;i--) t+=(long)(a.w[i]-a.w[k-i])*(b.w[k-i]-b.w[i]); c.w[k]=(int)t&ROM.BMASK; co=t>>ROM.BASEBITS;
+		}
+		c.w[2*ROM.NLEN-1]=(int)co;
+
+		return c;
+	}
+
+/* return a^2 as DBIG */
+	public static DBIG sqr(BIG a)
+	{
+		int i,j,last;
+		long t,co;
+		DBIG c=new DBIG(0);
+	//	a.norm();
+
+		t=(long)a.w[0]*a.w[0];
+		c.w[0]=(int)t&ROM.BMASK; co=t>>ROM.BASEBITS;
+		t=(long)a.w[1]*a.w[0]; t+=t; t+=co; 
+		c.w[1]=(int)t&ROM.BMASK; co=t>>ROM.BASEBITS;
+
+		last=ROM.NLEN-ROM.NLEN%2;
+		for (j=2;j<last;j+=2)
+		{
+			t=(long)a.w[j]*a.w[0]; for (i=1;i<(j+1)/2;i++) t+=(long)a.w[j-i]*a.w[i]; t+=t; t+=co;  t+=(long)a.w[j/2]*a.w[j/2];
+			c.w[j]=(int)t&ROM.BMASK; co=t>>ROM.BASEBITS;
+			t=(long)a.w[j+1]*a.w[0]; for (i=1;i<(j+2)/2;i++) t+=(long)a.w[j+1-i]*a.w[i]; t+=t; t+=co; 
+			c.w[j+1]=(int)t&ROM.BMASK; co=t>>ROM.BASEBITS;	
+		}
+		j=last;
+		if (ROM.NLEN%2==1)
+		{
+			t=(long)a.w[j]*a.w[0]; for (i=1;i<(j+1)/2;i++) t+=(long)a.w[j-i]*a.w[i]; t+=t; t+=co;  t+=(long)a.w[j/2]*a.w[j/2];
+			c.w[j]=(int)t&ROM.BMASK; co=t>>ROM.BASEBITS; j++;
+			t=(long)a.w[ROM.NLEN-1]*a.w[j-ROM.NLEN+1]; for (i=j-ROM.NLEN+2;i<(j+1)/2;i++) t+=(long)a.w[j-i]*a.w[i]; t+=t; t+=co; 
+			c.w[j]=(int)t&ROM.BMASK; co=t>>ROM.BASEBITS; j++;
+		}
+		for (;j<ROM.DNLEN-2;j+=2)
+		{
+			t=(long)a.w[ROM.NLEN-1]*a.w[j-ROM.NLEN+1]; for (i=j-ROM.NLEN+2;i<(j+1)/2;i++) t+=(long)a.w[j-i]*a.w[i]; t+=t; t+=co; t+=(long)a.w[j/2]*a.w[j/2];
+			c.w[j]=(int)t&ROM.BMASK; co=t>>ROM.BASEBITS;
+			t=(long)a.w[ROM.NLEN-1]*a.w[j-ROM.NLEN+2]; for (i=j-ROM.NLEN+3;i<(j+2)/2;i++) t+=(long)a.w[j+1-i]*a.w[i]; t+=t; t+=co;
+			c.w[j+1]=(int)t&ROM.BMASK; co=t>>ROM.BASEBITS;
+		}
+
+		t=(long)a.w[ROM.NLEN-1]*a.w[ROM.NLEN-1]+co;
+		c.w[ROM.DNLEN-2]=(int)t&ROM.BMASK; co=t>>ROM.BASEBITS;
+		c.w[ROM.DNLEN-1]=(int)co;
+
+		return c;
+	}
+
+	static BIG monty(DBIG d)
+	{
+		BIG b;
+		long t,c,s;
+		int i,k;
+		long[] dd=new long[ROM.NLEN];
+		int[] v=new int[ROM.NLEN];
+		BIG m=new BIG(ROM.Modulus);
+		b=new BIG(0);
+
+		t=d.w[0]; v[0]=((int)t*ROM.MConst)&ROM.BMASK; t+=(long)v[0]*m.w[0]; c=(t>>ROM.BASEBITS)+d.w[1]; s=0;
+
+		for (k=1;k<ROM.NLEN;k++)
+		{
+			t=c+s+(long)v[0]*m.w[k];
+			for (i=k-1;i>k/2;i--) t+=(long)(v[k-i]-v[i])*(m.w[i]-m.w[k-i]);
+			v[k]=((int)t*ROM.MConst)&ROM.BMASK; t+=(long)v[k]*m.w[0]; c=(t>>ROM.BASEBITS)+d.w[k+1];
+			dd[k]=(long)v[k]*m.w[k]; s+=dd[k];
+		}
+		for (k=ROM.NLEN;k<2*ROM.NLEN-1;k++)
+		{
+			t=c+s;
+			for (i=ROM.NLEN-1;i>=1+k/2;i--) t+=(long)(v[k-i]-v[i])*(m.w[i]-m.w[k-i]);
+			b.w[k-ROM.NLEN]=(int)t&ROM.BMASK; c=(t>>ROM.BASEBITS)+d.w[k+1]; s-=dd[k-ROM.NLEN+1];
+		}
+		b.w[ROM.NLEN-1]=(int)c&ROM.BMASK;	
+		b.norm();
+		return b;		
+	}
+
+/* reduce a DBIG to a BIG using the appropriate form of the modulus */
+	public static BIG mod(DBIG d)
+	{
+		if (ROM.MODTYPE==ROM.PSEUDO_MERSENNE)
+		{
+			BIG b;
+			int v,tw;
+			BIG t=d.split(ROM.MODBITS);
+			b=new BIG(d);
+
+			v=t.pmul((int)ROM.MConst);
+			tw=t.w[ROM.NLEN-1];
+			t.w[ROM.NLEN-1]&=ROM.TMASK;
+			t.w[0]+=(ROM.MConst*((tw>>ROM.TBITS)+(v<<(ROM.BASEBITS-ROM.TBITS))));
+
+			b.add(t);
+			b.norm();
+			return b;
+		}
+		if (ROM.MODTYPE==ROM.MONTGOMERY_FRIENDLY)
+		{
+			BIG b;
+			int[] cr=new int[2];				
+			for (int i=0;i<ROM.NLEN;i++)
+			{
+				cr=muladd(d.w[i],ROM.MConst-1,d.w[i],d.w[ROM.NLEN+i-1]);
+				d.w[ROM.NLEN+i]+=cr[0];
+				d.w[ROM.NLEN+i-1]=cr[1];	
+			}
+			
+			b=new BIG(0);
+			for (int i=0;i<ROM.NLEN;i++ )
+				b.w[i]=d.w[ROM.NLEN+i];
+			b.norm();
+			return b;
+		}
+		if (ROM.MODTYPE==ROM.GENERALISED_MERSENNE)
+		{ // GoldiLocks Only
+			BIG b;
+			BIG t=d.split(ROM.MODBITS);
+			b=new BIG(d);
+			b.add(t);
+			DBIG dd=new DBIG(t);
+			dd.shl(ROM.MODBITS/2);
+
+			BIG tt=dd.split(ROM.MODBITS);
+			BIG lo=new BIG(dd);
+			b.add(tt);
+			b.add(lo);
+			b.norm();
+			tt.shl(ROM.MODBITS/2);
+			b.add(tt);
+
+			int carry=b.w[ROM.NLEN-1]>>ROM.TBITS;
+			b.w[ROM.NLEN-1]&=ROM.TMASK;
+			b.w[0]+=carry;
+			
+			b.w[224/ROM.BASEBITS]+=carry<<(224%ROM.BASEBITS);
+			b.norm();
+			return b;
+		}
+		if (ROM.MODTYPE==ROM.NOT_SPECIAL)
+		{
+			return monty(d);
+		}
+
+		return new BIG(0);
+	}
+
+
+
+/****************************************************************************/
+	public void xortop(long x)
+	{
+		w[ROM.NLEN-1]^=x;
+	}
+
+/* set x = x mod 2^m */
+	public void mod2m(int m)
+	{
+		int i,wd,bt;
+		wd=m/ROM.BASEBITS;
+		bt=m%ROM.BASEBITS;
+		w[wd]&=((cast_to_chunk(1)<<bt)-1);
+		for (i=wd+1;i<ROM.NLEN;i++) w[i]=0;
+	}
+
+/* return n-th bit */
+	public int bit(int n)
+	{
+		if ((w[n/ROM.BASEBITS]&(cast_to_chunk(1)<<(n%ROM.BASEBITS)))>0) return 1;
+		else return 0;
+	}
+
+/* Shift right by less than a word */
+	public int fshr(int k) {
+		int r=(int)(w[0]&((cast_to_chunk(1)<<k)-1)); /* shifted out part */
+		for (int i=0;i<ROM.NLEN-1;i++)
+			w[i]=(w[i]>>k)|((w[i+1]<<(ROM.BASEBITS-k))&ROM.BMASK);
+		w[ROM.NLEN-1]=w[ROM.NLEN-1]>>k;
+		return r;
+	}
+
+/* Shift right by less than a word */
+	public int fshl(int k) {
+		w[ROM.NLEN-1]=((w[ROM.NLEN-1]<<k))|(w[ROM.NLEN-2]>>(ROM.BASEBITS-k));
+		for (int i=ROM.NLEN-2;i>0;i--)
+			w[i]=((w[i]<<k)&ROM.BMASK)|(w[i-1]>>(ROM.BASEBITS-k));
+		w[0]=(w[0]<<k)&ROM.BMASK; 
+		return (int)(w[ROM.NLEN-1]>>((8*ROM.MODBYTES)%ROM.BASEBITS)); /* return excess - only used in FF.java */
+	}
+
+/* test for zero */
+	public boolean iszilch() {
+		for (int i=0;i<ROM.NLEN;i++)
+			if (w[i]!=0) return false;
+		return true; 
+	}
+
+/* set to zero */
+	public void zero()
+	{
+		for (int i=0;i<ROM.NLEN;i++)
+			w[i]=0;
+	}
+
+/* set to one */
+	public void one()
+	{
+		w[0]=1;
+		for (int i=1;i<ROM.NLEN;i++)
+			w[i]=0;
+	}
+
+/* Test for equal to one */
+	public boolean isunity()
+	{
+		for (int i=1;i<ROM.NLEN;i++)
+			if (w[i]!=0) return false;
+		if (w[0]!=1) return false;
+		return true;
+	}
+
+/* Copy from another BIG */
+	public void copy(BIG x)
+	{
+		for (int i=0;i<ROM.NLEN;i++)
+			w[i]=x.w[i];
+	}
+
+	public void copy(DBIG x)
+	{
+		for (int i=0;i<ROM.NLEN;i++)
+			w[i]=x.w[i];
+	}
+
+/* general shift right */
+	public void shr(int k) {
+		int n=k%ROM.BASEBITS;
+		int m=k/ROM.BASEBITS;	
+		for (int i=0;i<ROM.NLEN-m-1;i++)
+			w[i]=(w[m+i]>>n)|((w[m+i+1]<<(ROM.BASEBITS-n))&ROM.BMASK);
+		if (ROM.NLEN>m) w[ROM.NLEN-m-1]=w[ROM.NLEN-1]>>n;
+		for (int i=ROM.NLEN-m;i<ROM.NLEN;i++) w[i]=0;
+	}
+
+/* general shift left */
+	public void shl(int k) {
+		int n=k%ROM.BASEBITS;
+		int m=k/ROM.BASEBITS;
+
+		w[ROM.NLEN-1]=((w[ROM.NLEN-1-m]<<n));
+		if (ROM.NLEN>=m+2) w[ROM.NLEN-1]|=(w[ROM.NLEN-m-2]>>(ROM.BASEBITS-n));
+
+		for (int i=ROM.NLEN-2;i>m;i--)
+			w[i]=((w[i-m]<<n)&ROM.BMASK)|(w[i-m-1]>>(ROM.BASEBITS-n));
+		w[m]=(w[0]<<n)&ROM.BMASK;
+		for (int i=0;i<m;i++) w[i]=0;
+	}
+
+/* return this+x */
+	public BIG plus(BIG x) {
+		BIG s=new BIG(0);
+		for (int i=0;i<ROM.NLEN;i++)
+			s.w[i]=w[i]+x.w[i];	
+		return s;
+	}
+
+/* this+=x */
+	public void add(BIG x) {
+		for (int i=0;i<ROM.NLEN;i++)
+			w[i]+=x.w[i];
+	}
+
+/* this+=x, where x is int */
+	public void inc(int x) {
+		norm();
+		w[0]+=x;
+	}
+
+/* this+=x, where x is long */
+	public void incl(long x) {
+		norm();
+		w[0]+=x;
+	}	
+
+/* return this.x */
+	public BIG minus(BIG x) {
+		BIG d=new BIG(0);
+		for (int i=0;i<ROM.NLEN;i++)
+			d.w[i]=w[i]-x.w[i];
+		return d;
+	}
+
+/* this-=x */
+	public void sub(BIG x) {
+		for (int i=0;i<ROM.NLEN;i++)
+			w[i]-=x.w[i];
+	}
+
+/* reverse subtract this=x-this */
+	public void rsub(BIG x) {
+		for (int i=0;i<ROM.NLEN;i++)
+			w[i]=x.w[i]-w[i];
+	}
+
+/* this-=x where x is int */
+	public void dec(int x) {
+		norm();
+		w[0]-=x;
+	}
+
+/* this*=x, where x is small int<NEXCESS */
+	public void imul(int c)
+	{
+		for (int i=0;i<ROM.NLEN;i++) w[i]*=c;
+	}
+
+/* convert this BIG to byte array */
+	public void tobytearray(byte[] b,int n)
+	{
+		norm();
+		BIG c=new BIG(this);
+
+		for (int i=ROM.MODBYTES-1;i>=0;i--)
+		{
+			b[i+n]=(byte)c.w[0];
+			c.fshr(8);
+		}
+	}
+
+/* convert from byte array to BIG */
+	public static BIG frombytearray(byte[] b,int n)
+	{
+		BIG m=new BIG(0);
+
+		for (int i=0;i<ROM.MODBYTES;i++)
+		{
+			m.fshl(8); m.w[0]+=(int)b[i+n]&0xff;
+			//m.inc((int)b[i]&0xff);
+		}
+		return m; 
+	}
+
+	public void toBytes(byte[] b)
+	{
+		tobytearray(b,0);
+	}
+
+	public static BIG fromBytes(byte[] b)
+	{
+		return frombytearray(b,0);
+	}
+
+/* Compare a and b, return 0 if a==b, -1 if a<b, +1 if a>b. Inputs must be normalised */
+	public static int comp(BIG a,BIG b)
+	{
+		for (int i=ROM.NLEN-1;i>=0;i--)
+		{
+			if (a.w[i]==b.w[i]) continue;
+			if (a.w[i]>b.w[i]) return 1;
+			else  return -1;
+		}
+		return 0;
+	}
+
+/* Arazi and Qi inversion mod 256 */
+	public static int invmod256(int a)
+	{
+		int U,t1,t2,b,c;
+		t1=0;
+		c=(a>>1)&1;  
+		t1+=c;
+		t1&=1;
+		t1=2-t1;
+		t1<<=1;
+		U=t1+1;
+
+// i=2
+		b=a&3;
+		t1=U*b; t1>>=2;
+		c=(a>>2)&3;
+		t2=(U*c)&3;
+		t1+=t2;
+		t1*=U; t1&=3;
+		t1=4-t1;
+		t1<<=2;
+		U+=t1;
+
+// i=4
+		b=a&15;
+		t1=U*b; t1>>=4;
+		c=(a>>4)&15;
+		t2=(U*c)&15;
+		t1+=t2;
+		t1*=U; t1&=15;
+		t1=16-t1;
+		t1<<=4;
+		U+=t1;
+
+		return U;
+	}
+
+/* a=1/a mod 2^256. This is very fast! */
+	public void invmod2m()
+	{
+		int i;
+		BIG U=new BIG(0);
+		BIG b=new BIG(0);
+		BIG c=new BIG(0);
+
+		U.inc(invmod256(lastbits(8)));
+
+		for (i=8;i<ROM.BIGBITS;i<<=1)
+		{
+			b.copy(this); b.mod2m(i);
+			BIG t1=BIG.smul(U,b); 
+			t1.shr(i);
+
+			c.copy(this); c.shr(i); c.mod2m(i);
+			BIG t2=BIG.smul(U,c); t2.mod2m(i);
+			t1.add(t2);
+			b=BIG.smul(t1,U); t1.copy(b);
+			t1.mod2m(i);
+
+			t2.one(); t2.shl(i); t1.rsub(t2); t1.norm();
+
+			t1.shl(i);
+			U.add(t1);
+		}
+		U.mod2m(ROM.BIGBITS);
+		copy(U);
+		norm();
+	}
+
+/* reduce this mod m */
+	public void mod(BIG m)
+	{
+		int k=0;  
+		BIG r=new BIG(0);
+
+		norm();
+		if (comp(this,m)<0) return;
+		do
+		{
+			m.fshl(1);
+			k++;
+		} while (comp(this,m)>=0);
+
+		while (k>0)
+		{
+			m.fshr(1);
+
+			r.copy(this);
+			r.sub(m);
+			r.norm();
+			cmove(r,(int)(1-((r.w[ROM.NLEN-1]>>(ROM.CHUNK-1))&1)));
+/*
+			if (comp(this,m)>=0)
+			{
+				sub(m);
+				norm();
+			} */
+			k--;
+		}
+	}
+
+/* divide this by m */
+	public void div(BIG m)
+	{
+		int d,k=0;
+		norm();
+		BIG e=new BIG(1);
+		BIG b=new BIG(this);
+		BIG r=new BIG(0);
+		zero();
+
+		while (comp(b,m)>=0)
+		{
+			e.fshl(1);
+			m.fshl(1);
+			k++;
+		}
+
+		while (k>0)
+		{
+			m.fshr(1);
+			e.fshr(1);
+
+			r.copy(b);
+			r.sub(m);
+			r.norm();
+			d=(int)(1-((r.w[ROM.NLEN-1]>>(ROM.CHUNK-1))&1));
+			b.cmove(r,d);
+			r.copy(this);
+			r.add(e);
+			r.norm();
+			cmove(r,d);
+
+/*
+			if (comp(b,m)>=0)
+			{
+				add(e);
+				norm();
+				b.sub(m);
+				b.norm();
+			} */
+			k--;
+		}
+	}
+
+/* return parity */
+	public int parity()
+	{
+		return (int)(w[0]%2);
+	}
+
+/* return n last bits */
+	public int lastbits(int n)
+	{
+		int msk=(1<<n)-1;
+		norm();
+		return ((int)w[0])&msk;
+	}
+
+/* get 8*MODBYTES size random number */
+	public static BIG random(RAND rng)
+	{
+		BIG m=new BIG(0);
+		int i,b,j=0,r=0;
+
+/* generate random BIG */ 
+		for (i=0;i<8*ROM.MODBYTES;i++)   
+		{
+			if (j==0) r=rng.getByte();
+			else r>>=1;
+
+			b=r&1;
+			m.shl(1); m.w[0]+=b;// m.inc(b);
+			j++; j&=7; 
+		}
+		return m;
+	}
+
+/* Create random BIG in portable way, one bit at a time */
+	public static BIG randomnum(BIG q,RAND rng) 
+	{
+		DBIG d=new DBIG(0);
+		int i,b,j=0,r=0;
+		for (i=0;i<2*ROM.MODBITS;i++)
+		{
+			if (j==0) r=rng.getByte();
+			else r>>=1;
+
+			b=r&1;
+			d.shl(1); d.w[0]+=b;// m.inc(b);
+			j++; j&=7; 
+		}
+		BIG m=d.mod(q);
+		return m;
+	}
+
+/* return a*b mod m */
+	public static BIG modmul(BIG a,BIG b,BIG m)
+	{
+		a.mod(m);
+		b.mod(m);
+		DBIG d=mul(a,b);
+		return d.mod(m);
+	}
+
+/* return a^2 mod m */
+	public static BIG modsqr(BIG a,BIG m)
+	{
+		a.mod(m);
+		DBIG d=sqr(a);
+		return d.mod(m);
+	}
+
+/* return -a mod m */
+	public static BIG modneg(BIG a,BIG m)
+	{
+		a.mod(m);
+		return m.minus(a);
+	}
+
+/* return this^e mod m */
+	public BIG powmod(BIG e,BIG m)
+	{
+		int bt;
+		norm();
+		e.norm();
+		BIG a=new BIG(1);
+		BIG z=new BIG(e);
+		BIG s=new BIG(this);
+		while (true)
+		{
+			bt=z.parity();
+			z.fshr(1);
+			if (bt==1) a=modmul(a,s,m);
+			if (z.iszilch()) break;
+			s=modsqr(s,m);
+		}
+		return a;
+	}
+
+/* Jacobi Symbol (this/p). Returns 0, 1 or -1 */
+	public int jacobi(BIG p)
+	{
+		int n8,k,m=0;
+		BIG t=new BIG(0);
+		BIG x=new BIG(0);
+		BIG n=new BIG(0);
+		BIG zilch=new BIG(0);
+		BIG one=new BIG(1);
+		if (p.parity()==0 || comp(this,zilch)==0 || comp(p,one)<=0) return 0;
+		norm();
+		x.copy(this);
+		n.copy(p);
+		x.mod(p);
+
+		while (comp(n,one)>0)
+		{
+			if (comp(x,zilch)==0) return 0;
+			n8=n.lastbits(3);
+			k=0;
+			while (x.parity()==0)
+			{
+				k++;
+				x.shr(1);
+			}
+			if (k%2==1) m+=(n8*n8-1)/8;
+			m+=(n8-1)*(x.lastbits(2)-1)/4;
+			t.copy(n);
+			t.mod(x);
+			n.copy(x);
+			x.copy(t);
+			m%=2;
+
+		}
+		if (m==0) return 1;
+		else return -1;
+	}
+
+/* this=1/this mod p. Binary method */
+	public void invmodp(BIG p)
+	{
+		mod(p);
+		BIG u=new BIG(this);
+		BIG v=new BIG(p);
+		BIG x1=new BIG(1);
+		BIG x2=new BIG(0);
+		BIG t=new BIG(0);
+		BIG one=new BIG(1);
+
+		while (comp(u,one)!=0 && comp(v,one)!=0)
+		{
+			while (u.parity()==0)
+			{
+				u.shr(1);
+				if (x1.parity()!=0)
+				{
+					x1.add(p);
+					x1.norm();
+				}
+				x1.shr(1);
+			}
+			while (v.parity()==0)
+			{
+				v.shr(1);
+				if (x2.parity()!=0)
+				{
+					x2.add(p);
+					x2.norm();
+				}
+				x2.shr(1);
+			}
+			if (comp(u,v)>=0)
+			{
+				u.sub(v);
+				u.norm();
+				if (comp(x1,x2)>=0) x1.sub(x2);
+				else
+				{
+					t.copy(p);
+					t.sub(x2);
+					x1.add(t);
+				}
+				x1.norm();
+			}
+			else
+			{
+				v.sub(u);
+				v.norm();
+				if (comp(x2,x1)>=0) x2.sub(x1);
+				else
+				{
+					t.copy(p);
+					t.sub(x1);
+					x2.add(t);
+				}
+				x2.norm();
+			}
+		}
+		if (comp(u,one)==0) copy(x1);
+		else copy(x2);
+	}
+}
diff --git a/version22/java/BIG64.java b/version22/java/BIG64.java
new file mode 100644
index 0000000..c66b495
--- /dev/null
+++ b/version22/java/BIG64.java
@@ -0,0 +1,1040 @@
+/*
+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.
+*/
+
+/* AMCL BIG number class */ 
+
+public class BIG {
+	protected long[] w=new long[ROM.NLEN];
+/* Constructors */
+	public BIG()
+	{
+		for (int i=0;i<ROM.NLEN;i++)
+			w[i]=0;
+	}
+
+	public BIG(int x)
+	{
+		w[0]=x;
+		for (int i=1;i<ROM.NLEN;i++)
+			w[i]=0;
+	}
+
+	public BIG(BIG x)
+	{
+		for (int i=0;i<ROM.NLEN;i++)
+			w[i]=x.w[i];
+	}
+
+	public BIG(DBIG x)
+	{
+		for (int i=0;i<ROM.NLEN;i++)
+			w[i]=x.w[i];
+	}
+
+	public BIG(long[] x)
+	{
+			for (int i=0;i<ROM.NLEN;i++)
+				w[i]=x[i];
+	}
+
+	public long get(int i)
+	{
+		return w[i];
+	}
+
+	public void set(int i,long x)
+	{
+		w[i]=x;
+	} 
+
+/* calculate Field Excess */
+	public static long EXCESS(BIG a)
+	{
+		return ((a.w[ROM.NLEN-1]&ROM.OMASK)>>(ROM.MODBITS%ROM.BASEBITS));
+	}
+
+/* Check if product causes excess */
+	public static boolean pexceed(BIG a,BIG b)
+	{
+		long ea,eb;
+		ea=EXCESS(a);
+		eb=EXCESS(b);
+		if ((ea+1)>ROM.FEXCESS/(eb+1)) return true;
+		return false;
+	}
+
+/* Check if square causes excess */
+	public static boolean sexceed(BIG a)
+	{
+		long ea;
+		ea=EXCESS(a);
+		if ((ea+1)>ROM.FEXCESS/(ea+1)) return true;
+		return false;
+	}
+
+	public static long FF_EXCESS(BIG a)
+	{
+		return ((a.get(ROM.NLEN-1)&ROM.P_OMASK)>>(ROM.P_TBITS));
+	}
+
+/* Check if product causes excess */
+	public static boolean ff_pexceed(BIG a,BIG b)
+	{
+		long ea,eb;
+		ea=FF_EXCESS(a);
+		eb=FF_EXCESS(b);
+		if ((ea+1)>ROM.P_FEXCESS/(eb+1)) return true;
+		return false;
+	}
+
+/* Check if square causes excess */
+	public static boolean ff_sexceed(BIG a)
+	{
+		long ea;
+		ea=FF_EXCESS(a);
+		if ((ea+1)>ROM.P_FEXCESS/(ea+1)) return true;
+		return false;
+	}
+
+/* Conditional swap of two bigs depending on d using XOR - no branches */
+	public void cswap(BIG b,int d)
+	{
+		int i;
+		long t,c=(long)d;
+		c=~(c-1);
+
+		for (i=0;i<ROM.NLEN;i++)
+		{
+			t=c&(w[i]^b.w[i]);
+			w[i]^=t;
+			b.w[i]^=t;
+		}
+	}
+
+	public void cmove(BIG g,int d)
+	{
+		int i;
+		long t,b=-d;
+
+		for (i=0;i<ROM.NLEN;i++)
+		{
+			w[i]^=(w[i]^g.w[i])&b;
+		}
+	}
+
+    public static long cast_to_chunk(int x)
+	{
+		return (long)x;
+	}
+
+/* normalise BIG - force all digits < 2^BASEBITS */
+	public long norm() {
+		long d,carry=0;
+		for (int i=0;i<ROM.NLEN-1;i++)
+		{
+			d=w[i]+carry;
+			w[i]=d&ROM.BMASK;
+			carry=(d>>ROM.BASEBITS);
+		}
+		w[ROM.NLEN-1]=(w[ROM.NLEN-1]+carry);
+		return (long)(w[ROM.NLEN-1]>>((8*ROM.MODBYTES)%ROM.BASEBITS));  
+	}
+
+/* return number of bits */
+	public int nbits() {
+		int bts,k=ROM.NLEN-1;
+		long c;
+		norm();
+		while (k>=0 && w[k]==0) k--;
+		if (k<0) return 0;
+		bts=ROM.BASEBITS*k;
+		c=w[k];
+		while (c!=0) {c/=2; bts++;}
+		return bts;
+	}
+
+	public String toRawString()
+	{
+		BIG b=new BIG(this);
+		String s="(";
+		for (int i=0;i<ROM.NLEN-1;i++)
+		{
+			s+=Long.toHexString(b.w[i]); s+=",";
+		}
+		s+=Long.toHexString(b.w[ROM.NLEN-1]); s+=")";
+		return s;
+	}
+
+/* Convert to Hex String */
+	public String toString() {
+		BIG b;
+		String s="";
+		int len=nbits();
+
+		if (len%4==0) len/=4;
+		else {len/=4; len++;}
+		if (len<ROM.MODBYTES*2) len=ROM.MODBYTES*2;
+
+		for (int i=len-1;i>=0;i--)
+		{
+			b=new BIG(this);
+			b.shr(i*4);
+			s+=Long.toHexString(b.w[0]&15);
+		}
+		return s;
+	}
+
+/* set this[i]+=x*y+c, and return high part */
+/*
+	public long muladd(long a,long b,long c,int i)
+	{
+		long x0,x1,y0,y1;
+		x0=a&ROM.HMASK;
+		x1=(a>>ROM.HBITS);
+		y0=b&ROM.HMASK;
+		y1=(b>>ROM.HBITS);
+		long bot=x0*y0;
+		long top=x1*y1;
+		long mid=x0*y1+x1*y0;
+
+		x0=mid&ROM.HMASK;
+		x1=(mid>>ROM.HBITS);
+		bot+=x0<<ROM.HBITS; bot+=c; bot+=w[i]; 
+
+		top+=x1;
+		long carry=bot>>ROM.BASEBITS;
+		bot&=ROM.BMASK;
+		top+=carry;
+		w[i]=bot;
+		return top;
+	}
+*/
+
+	public static long[] muladd(long a,long b,long c,long r)
+	{
+		long x0,x1,y0,y1;
+		long[] tb=new long[2];
+		x0=a&ROM.HMASK;
+		x1=(a>>ROM.HBITS);
+		y0=b&ROM.HMASK;
+		y1=(b>>ROM.HBITS);
+		long bot=x0*y0;
+		long top=x1*y1;
+		long mid=x0*y1+x1*y0;
+		x0=mid&ROM.HMASK;
+		x1=(mid>>ROM.HBITS);
+		bot+=x0<<ROM.HBITS; bot+=c; bot+=r;
+		top+=x1;
+		long carry=bot>>ROM.BASEBITS;
+		bot&=ROM.BMASK;
+		top+=carry;
+		tb[0]=top;
+		tb[1]=bot;
+		return tb;
+	}
+
+
+
+
+/* this*=x, where x is >NEXCESS */
+	public long pmul(int c)
+	{
+		long ak,carry=0;
+		long[] cr=new long[2];
+		norm();
+		for (int i=0;i<ROM.NLEN;i++)
+		{
+			ak=w[i];
+			w[i]=0;
+
+			cr=muladd(ak,(long)c,carry,w[i]);
+			carry=cr[0];
+			w[i]=cr[1];
+
+		}
+		return carry;
+	}
+
+/* this*=c and catch overflow in DBIG */
+	public DBIG pxmul(int c)
+	{
+		DBIG m=new DBIG(0);	
+		long[] cr=new long[2];
+		long carry=0;
+		for (int j=0;j<ROM.NLEN;j++)
+		{
+			cr=muladd(w[j],(long)c,carry,m.w[j]);
+			carry=cr[0];
+			m.w[j]=cr[1];
+		}
+		m.w[ROM.NLEN]=carry;		
+		return m;
+	}
+
+/* divide by 3 */
+	public int div3()
+	{	
+		long ak,base,carry=0;
+		norm();
+		base=((long)1<<ROM.BASEBITS);
+		for (int i=ROM.NLEN-1;i>=0;i--)
+		{
+			ak=(carry*base+w[i]);
+			w[i]=ak/3;
+			carry=ak%3;
+		}
+		return (int)carry;
+	}
+
+/* return a*b where result fits in a BIG */
+	public static BIG smul(BIG a,BIG b)
+	{
+		long carry;
+		long[] cr=new long[2];
+		BIG c=new BIG(0);
+		for (int i=0;i<ROM.NLEN;i++)
+		{
+			carry=0;
+			for (int j=0;j<ROM.NLEN;j++)
+				if (i+j<ROM.NLEN)
+				{
+					cr=muladd(a.w[i],b.w[j],carry,c.w[i+j]);
+					carry=cr[0];
+					c.w[i+j]=cr[1];
+				}
+		}
+		return c;
+	}
+
+/* return a*b as DBIG */
+	public static DBIG mul(BIG a,BIG b)
+	{
+		DBIG c=new DBIG(0);
+		long carry;
+		long[] cr=new long[2];
+//		a.norm();
+//		b.norm();
+
+		for (int i=0;i<ROM.NLEN;i++)
+		{
+			carry=0;
+			for (int j=0;j<ROM.NLEN;j++)
+			{
+				cr=muladd(a.w[i],b.w[j],carry,c.w[i+j]);
+				carry=cr[0];
+				c.w[i+j]=cr[1];
+				//carry=c.muladd(a.w[i],b.w[j],carry,i+j);
+			}
+			c.w[ROM.NLEN+i]=carry;
+		}
+
+		return c;
+	}
+
+/* return a^2 as DBIG */
+	public static DBIG sqr(BIG a)
+	{
+		DBIG c=new DBIG(0);
+		long carry;
+		long[] cr=new long[2];
+	//	a.norm();
+		for (int i=0;i<ROM.NLEN;i++)
+		{
+			carry=0;
+			for (int j=i+1;j<ROM.NLEN;j++)
+			{
+				cr=muladd(2*a.w[i],a.w[j],carry,c.w[i+j]);
+				carry=cr[0];
+				c.w[i+j]=cr[1];
+				//carry=c.muladd(2*a.w[i],a.w[j],carry,i+j);
+			}
+			c.w[ROM.NLEN+i]=carry;
+		}
+
+		for (int i=0;i<ROM.NLEN;i++)
+		{
+			cr=muladd(a.w[i],a.w[i],0,c.w[2*i]);
+			c.w[2*i+1]+=cr[0];
+			c.w[2*i]=cr[1];
+			//c.w[2*i+1]+=c.muladd(a.w[i],a.w[i],0,2*i);
+		}
+		c.norm(); 
+		return c;
+	}
+
+	static BIG monty(DBIG d)
+	{
+		BIG b;
+		BIG md=new BIG(ROM.Modulus);
+		long m,carry;
+		long[] cr=new long[2];
+		for (int i=0;i<ROM.NLEN;i++) 
+		{
+			if (ROM.MConst==-1) m=(-d.w[i])&ROM.BMASK;
+			else
+			{
+				if (ROM.MConst==1) m=d.w[i];
+				else m=(ROM.MConst*d.w[i])&ROM.BMASK;
+			}
+
+			carry=0;
+			for (int j=0;j<ROM.NLEN;j++)
+			{
+				cr=muladd(m,md.w[j],carry,d.w[i+j]);
+				carry=cr[0];
+				d.w[i+j]=cr[1];
+			}
+			d.w[ROM.NLEN+i]+=carry;
+		}
+
+		b=new BIG(0);
+		for (int i=0;i<ROM.NLEN;i++ )
+			b.w[i]=d.w[ROM.NLEN+i];
+		b.norm();
+		return b;		
+	}
+
+/* reduce a DBIG to a BIG using the appropriate form of the modulus */
+	public static BIG mod(DBIG d)
+	{
+		if (ROM.MODTYPE==ROM.PSEUDO_MERSENNE)
+		{
+			BIG b;		
+			long v,tw;
+			BIG t=d.split(ROM.MODBITS);
+			b=new BIG(d);
+
+			v=t.pmul((int)ROM.MConst);
+			tw=t.w[ROM.NLEN-1];
+			t.w[ROM.NLEN-1]&=ROM.TMASK;
+			t.w[0]+=(ROM.MConst*((tw>>ROM.TBITS)+(v<<(ROM.BASEBITS-ROM.TBITS))));
+
+			b.add(t);
+			b.norm();
+			return b;		
+		}
+		if (ROM.MODTYPE==ROM.MONTGOMERY_FRIENDLY)
+		{
+			BIG b;		
+			long[] cr=new long[2];
+			for (int i=0;i<ROM.NLEN;i++)
+			{
+				cr=muladd(d.w[i],ROM.MConst-1,d.w[i],d.w[ROM.NLEN+i-1]);
+				d.w[ROM.NLEN+i]+=cr[0];
+				d.w[ROM.NLEN+i-1]=cr[1];
+			}
+			
+			b=new BIG(0);
+			for (int i=0;i<ROM.NLEN;i++ )
+				b.w[i]=d.w[ROM.NLEN+i];
+			b.norm();
+			return b;		
+		}
+		if (ROM.MODTYPE==ROM.GENERALISED_MERSENNE)
+		{ // GoldiLocks Only
+			BIG b;		
+			BIG t=d.split(ROM.MODBITS);
+			b=new BIG(d);
+			b.add(t);
+			DBIG dd=new DBIG(t);
+			dd.shl(ROM.MODBITS/2);
+
+			BIG tt=dd.split(ROM.MODBITS);
+			BIG lo=new BIG(dd);
+			b.add(tt);
+			b.add(lo);
+			b.norm();
+			tt.shl(ROM.MODBITS/2);
+			b.add(tt);
+
+			long carry=b.w[ROM.NLEN-1]>>ROM.TBITS;
+			b.w[ROM.NLEN-1]&=ROM.TMASK;
+			b.w[0]+=carry;
+			
+			b.w[224/ROM.BASEBITS]+=carry<<(224%ROM.BASEBITS);
+			b.norm();
+			return b;		
+		}
+		if (ROM.MODTYPE==ROM.NOT_SPECIAL)
+		{
+			return monty(d);
+		}
+
+		return new BIG(0);
+	}
+
+
+/****************************************************************************/
+
+	public void xortop(long x)
+	{
+		w[ROM.NLEN-1]^=x;
+	}
+
+/* set x = x mod 2^m */
+	public void mod2m(int m)
+	{
+		int i,wd,bt;
+		wd=m/ROM.BASEBITS;
+		bt=m%ROM.BASEBITS;
+		w[wd]&=((cast_to_chunk(1)<<bt)-1);
+		for (i=wd+1;i<ROM.NLEN;i++) w[i]=0;
+	}
+
+/* return n-th bit */
+	public int bit(int n)
+	{
+		if ((w[n/ROM.BASEBITS]&(cast_to_chunk(1)<<(n%ROM.BASEBITS)))>0) return 1;
+		else return 0;
+	}
+
+/* Shift right by less than a word */
+	public int fshr(int k) {
+		int r=(int)(w[0]&((cast_to_chunk(1)<<k)-1)); /* shifted out part */
+		for (int i=0;i<ROM.NLEN-1;i++)
+			w[i]=(w[i]>>k)|((w[i+1]<<(ROM.BASEBITS-k))&ROM.BMASK);
+		w[ROM.NLEN-1]=w[ROM.NLEN-1]>>k;
+		return r;
+	}
+
+/* Shift right by less than a word */
+	public int fshl(int k) {
+		w[ROM.NLEN-1]=((w[ROM.NLEN-1]<<k))|(w[ROM.NLEN-2]>>(ROM.BASEBITS-k));
+		for (int i=ROM.NLEN-2;i>0;i--)
+			w[i]=((w[i]<<k)&ROM.BMASK)|(w[i-1]>>(ROM.BASEBITS-k));
+		w[0]=(w[0]<<k)&ROM.BMASK; 
+		return (int)(w[ROM.NLEN-1]>>((8*ROM.MODBYTES)%ROM.BASEBITS)); /* return excess - only used in FF.java */
+	}
+
+/* test for zero */
+	public boolean iszilch() {
+		for (int i=0;i<ROM.NLEN;i++)
+			if (w[i]!=0) return false;
+		return true; 
+	}
+
+/* set to zero */
+	public void zero()
+	{
+		for (int i=0;i<ROM.NLEN;i++)
+			w[i]=0;
+	}
+
+/* set to one */
+	public void one()
+	{
+		w[0]=1;
+		for (int i=1;i<ROM.NLEN;i++)
+			w[i]=0;
+	}
+
+/* Test for equal to one */
+	public boolean isunity()
+	{
+		for (int i=1;i<ROM.NLEN;i++)
+			if (w[i]!=0) return false;
+		if (w[0]!=1) return false;
+		return true;
+	}
+
+/* Copy from another BIG */
+	public void copy(BIG x)
+	{
+		for (int i=0;i<ROM.NLEN;i++)
+			w[i]=x.w[i];
+	}
+
+	public void copy(DBIG x)
+	{
+		for (int i=0;i<ROM.NLEN;i++)
+			w[i]=x.w[i];
+	}
+
+/* general shift right */
+	public void shr(int k) {
+		int n=k%ROM.BASEBITS;
+		int m=k/ROM.BASEBITS;	
+		for (int i=0;i<ROM.NLEN-m-1;i++)
+			w[i]=(w[m+i]>>n)|((w[m+i+1]<<(ROM.BASEBITS-n))&ROM.BMASK);
+		if (ROM.NLEN>m) w[ROM.NLEN-m-1]=w[ROM.NLEN-1]>>n;
+		for (int i=ROM.NLEN-m;i<ROM.NLEN;i++) w[i]=0;
+	}
+
+/* general shift left */
+	public void shl(int k) {
+		int n=k%ROM.BASEBITS;
+		int m=k/ROM.BASEBITS;
+
+		w[ROM.NLEN-1]=((w[ROM.NLEN-1-m]<<n));
+		if (ROM.NLEN>=m+2) w[ROM.NLEN-1]|=(w[ROM.NLEN-m-2]>>(ROM.BASEBITS-n));
+
+		for (int i=ROM.NLEN-2;i>m;i--)
+			w[i]=((w[i-m]<<n)&ROM.BMASK)|(w[i-m-1]>>(ROM.BASEBITS-n));
+		w[m]=(w[0]<<n)&ROM.BMASK;
+		for (int i=0;i<m;i++) w[i]=0;
+	}
+
+/* return this+x */
+	public BIG plus(BIG x) {
+		BIG s=new BIG(0);
+		for (int i=0;i<ROM.NLEN;i++)
+			s.w[i]=w[i]+x.w[i];	
+		return s;
+	}
+
+/* this+=x */
+	public void add(BIG x) {
+		for (int i=0;i<ROM.NLEN;i++)
+			w[i]+=x.w[i];
+	}
+
+/* this+=x, where x is int */
+	public void inc(int x) {
+		norm();
+		w[0]+=x;
+	}
+
+/* this+=x, where x is long */
+	public void incl(long x) {
+		norm();
+		w[0]+=x;
+	}	
+
+/* return this.x */
+	public BIG minus(BIG x) {
+		BIG d=new BIG(0);
+		for (int i=0;i<ROM.NLEN;i++)
+			d.w[i]=w[i]-x.w[i];
+		return d;
+	}
+
+/* this-=x */
+	public void sub(BIG x) {
+		for (int i=0;i<ROM.NLEN;i++)
+			w[i]-=x.w[i];
+	}
+
+/* reverse subtract this=x-this */
+	public void rsub(BIG x) {
+		for (int i=0;i<ROM.NLEN;i++)
+			w[i]=x.w[i]-w[i];
+	}
+
+/* this-=x where x is int */
+	public void dec(int x) {
+		norm();
+		w[0]-=x;
+	}
+
+/* this*=x, where x is small int<NEXCESS */
+	public void imul(int c)
+	{
+		for (int i=0;i<ROM.NLEN;i++) w[i]*=c;
+	}
+
+/* convert this BIG to byte array */
+	public void tobytearray(byte[] b,int n)
+	{
+		norm();
+		BIG c=new BIG(this);
+
+		for (int i=ROM.MODBYTES-1;i>=0;i--)
+		{
+			b[i+n]=(byte)c.w[0];
+			c.fshr(8);
+		}
+	}
+
+/* convert from byte array to BIG */
+	public static BIG frombytearray(byte[] b,int n)
+	{
+		BIG m=new BIG(0);
+
+		for (int i=0;i<ROM.MODBYTES;i++)
+		{
+			m.fshl(8); m.w[0]+=(int)b[i+n]&0xff;
+			//m.inc((int)b[i]&0xff);
+		}
+		return m; 
+	}
+
+	public void toBytes(byte[] b)
+	{
+		tobytearray(b,0);
+	}
+
+	public static BIG fromBytes(byte[] b)
+	{
+		return frombytearray(b,0);
+	}
+
+/* Compare a and b, return 0 if a==b, -1 if a<b, +1 if a>b. Inputs must be normalised */
+	public static int comp(BIG a,BIG b)
+	{
+		for (int i=ROM.NLEN-1;i>=0;i--)
+		{
+			if (a.w[i]==b.w[i]) continue;
+			if (a.w[i]>b.w[i]) return 1;
+			else  return -1;
+		}
+		return 0;
+	}
+
+/* Arazi and Qi inversion mod 256 */
+	public static int invmod256(int a)
+	{
+		int U,t1,t2,b,c;
+		t1=0;
+		c=(a>>1)&1;  
+		t1+=c;
+		t1&=1;
+		t1=2-t1;
+		t1<<=1;
+		U=t1+1;
+
+// i=2
+		b=a&3;
+		t1=U*b; t1>>=2;
+		c=(a>>2)&3;
+		t2=(U*c)&3;
+		t1+=t2;
+		t1*=U; t1&=3;
+		t1=4-t1;
+		t1<<=2;
+		U+=t1;
+
+// i=4
+		b=a&15;
+		t1=U*b; t1>>=4;
+		c=(a>>4)&15;
+		t2=(U*c)&15;
+		t1+=t2;
+		t1*=U; t1&=15;
+		t1=16-t1;
+		t1<<=4;
+		U+=t1;
+
+		return U;
+	}
+
+/* a=1/a mod 2^256. This is very fast! */
+	public void invmod2m()
+	{
+		int i;
+		BIG U=new BIG(0);
+		BIG b=new BIG(0);
+		BIG c=new BIG(0);
+
+		U.inc(invmod256(lastbits(8)));
+
+		for (i=8;i<ROM.BIGBITS;i<<=1)
+		{
+			b.copy(this); b.mod2m(i);
+			BIG t1=BIG.smul(U,b); 
+			t1.shr(i);
+
+			c.copy(this); c.shr(i); c.mod2m(i);
+			BIG t2=BIG.smul(U,c); t2.mod2m(i);
+			t1.add(t2);
+			b=BIG.smul(t1,U); t1.copy(b);
+			t1.mod2m(i);
+
+			t2.one(); t2.shl(i); t1.rsub(t2); t1.norm();
+
+			t1.shl(i);
+			U.add(t1);
+		}
+		U.mod2m(ROM.BIGBITS);
+		copy(U);
+		norm();
+	}
+
+/* reduce this mod m */
+	public void mod(BIG m)
+	{
+		int k=0;  
+		BIG r=new BIG(0);
+
+		norm();
+		if (comp(this,m)<0) return;
+		do
+		{
+			m.fshl(1);
+			k++;
+		} while (comp(this,m)>=0);
+
+		while (k>0)
+		{
+			m.fshr(1);
+
+			r.copy(this);
+			r.sub(m);
+			r.norm();
+			cmove(r,(int)(1-((r.w[ROM.NLEN-1]>>(ROM.CHUNK-1))&1)));
+/*
+			if (comp(this,m)>=0)
+			{
+				sub(m);
+				norm();
+			} */
+			k--;
+		}
+	}
+
+/* divide this by m */
+	public void div(BIG m)
+	{
+		int d,k=0;
+		norm();
+		BIG e=new BIG(1);
+		BIG b=new BIG(this);
+		BIG r=new BIG(0);
+		zero();
+
+		while (comp(b,m)>=0)
+		{
+			e.fshl(1);
+			m.fshl(1);
+			k++;
+		}
+
+		while (k>0)
+		{
+			m.fshr(1);
+			e.fshr(1);
+
+			r.copy(b);
+			r.sub(m);
+			r.norm();
+			d=(int)(1-((r.w[ROM.NLEN-1]>>(ROM.CHUNK-1))&1));
+			b.cmove(r,d);
+			r.copy(this);
+			r.add(e);
+			r.norm();
+			cmove(r,d);
+
+/*
+			if (comp(b,m)>=0)
+			{
+				add(e);
+				norm();
+				b.sub(m);
+				b.norm();
+			} */
+			k--;
+		}
+	}
+
+/* return parity */
+	public int parity()
+	{
+		return (int)(w[0]%2);
+	}
+
+/* return n last bits */
+	public int lastbits(int n)
+	{
+		int msk=(1<<n)-1;
+		norm();
+		return ((int)w[0])&msk;
+	}
+
+/* get 8*MODBYTES size random number */
+	public static BIG random(RAND rng)
+	{
+		BIG m=new BIG(0);
+		int i,b,j=0,r=0;
+
+/* generate random BIG */ 
+		for (i=0;i<8*ROM.MODBYTES;i++)   
+		{
+			if (j==0) r=rng.getByte();
+			else r>>=1;
+
+			b=r&1;
+			m.shl(1); m.w[0]+=b;// m.inc(b);
+			j++; j&=7; 
+		}
+		return m;
+	}
+
+/* Create random BIG in portable way, one bit at a time */
+	public static BIG randomnum(BIG q,RAND rng) 
+	{
+		DBIG d=new DBIG(0);
+		int i,b,j=0,r=0;
+		for (i=0;i<2*ROM.MODBITS;i++)
+		{
+			if (j==0) r=rng.getByte();
+			else r>>=1;
+
+			b=r&1;
+			d.shl(1); d.w[0]+=b;// m.inc(b);
+			j++; j&=7; 
+		}
+		BIG m=d.mod(q);
+		return m;
+	}
+
+/* return a*b mod m */
+	public static BIG modmul(BIG a,BIG b,BIG m)
+	{
+		a.mod(m);
+		b.mod(m);
+		DBIG d=mul(a,b);
+		return d.mod(m);
+	}
+
+/* return a^2 mod m */
+	public static BIG modsqr(BIG a,BIG m)
+	{
+		a.mod(m);
+		DBIG d=sqr(a);
+		return d.mod(m);
+	}
+
+/* return -a mod m */
+	public static BIG modneg(BIG a,BIG m)
+	{
+		a.mod(m);
+		return m.minus(a);
+	}
+
+/* return this^e mod m */
+	public BIG powmod(BIG e,BIG m)
+	{
+		int bt;
+		norm();
+		e.norm();
+		BIG a=new BIG(1);
+		BIG z=new BIG(e);
+		BIG s=new BIG(this);
+		while (true)
+		{
+			bt=z.parity();
+			z.fshr(1);
+			if (bt==1) a=modmul(a,s,m);
+			if (z.iszilch()) break;
+			s=modsqr(s,m);
+		}
+		return a;
+	}
+
+/* Jacobi Symbol (this/p). Returns 0, 1 or -1 */
+	public int jacobi(BIG p)
+	{
+		int n8,k,m=0;
+		BIG t=new BIG(0);
+		BIG x=new BIG(0);
+		BIG n=new BIG(0);
+		BIG zilch=new BIG(0);
+		BIG one=new BIG(1);
+		if (p.parity()==0 || comp(this,zilch)==0 || comp(p,one)<=0) return 0;
+		norm();
+		x.copy(this);
+		n.copy(p);
+		x.mod(p);
+
+		while (comp(n,one)>0)
+		{
+			if (comp(x,zilch)==0) return 0;
+			n8=n.lastbits(3);
+			k=0;
+			while (x.parity()==0)
+			{
+				k++;
+				x.shr(1);
+			}
+			if (k%2==1) m+=(n8*n8-1)/8;
+			m+=(n8-1)*(x.lastbits(2)-1)/4;
+			t.copy(n);
+			t.mod(x);
+			n.copy(x);
+			x.copy(t);
+			m%=2;
+
+		}
+		if (m==0) return 1;
+		else return -1;
+	}
+
+/* this=1/this mod p. Binary method */
+	public void invmodp(BIG p)
+	{
+		mod(p);
+		BIG u=new BIG(this);
+		BIG v=new BIG(p);
+		BIG x1=new BIG(1);
+		BIG x2=new BIG(0);
+		BIG t=new BIG(0);
+		BIG one=new BIG(1);
+
+		while (comp(u,one)!=0 && comp(v,one)!=0)
+		{
+			while (u.parity()==0)
+			{
+				u.shr(1);
+				if (x1.parity()!=0)
+				{
+					x1.add(p);
+					x1.norm();
+				}
+				x1.shr(1);
+			}
+			while (v.parity()==0)
+			{
+				v.shr(1);
+				if (x2.parity()!=0)
+				{
+					x2.add(p);
+					x2.norm();
+				}
+				x2.shr(1);
+			}
+			if (comp(u,v)>=0)
+			{
+				u.sub(v);
+				u.norm();
+				if (comp(x1,x2)>=0) x1.sub(x2);
+				else
+				{
+					t.copy(p);
+					t.sub(x2);
+					x1.add(t);
+				}
+				x1.norm();
+			}
+			else
+			{
+				v.sub(u);
+				v.norm();
+				if (comp(x2,x1)>=0) x2.sub(x1);
+				else
+				{
+					t.copy(p);
+					t.sub(x1);
+					x2.add(t);
+				}
+				x2.norm();
+			}
+		}
+		if (comp(u,one)==0) copy(x1);
+		else copy(x2);
+	}
+}
diff --git a/version22/java/BenchtestEC.java b/version22/java/BenchtestEC.java
new file mode 100644
index 0000000..1800635
--- /dev/null
+++ b/version22/java/BenchtestEC.java
@@ -0,0 +1,160 @@
+/*
+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.
+*/
+
+/* Test and benchmark elliptic curve and RSA functions */
+
+public class BenchtestEC
+{
+/* generate an RSA key pair */
+	public static final int MIN_TIME=10; /* seconds */
+	public static final int MIN_ITERS=10; 
+
+	public static void main(String[] args) 
+	{
+		int i,iterations;
+		long start,elapsed;
+		byte[] RAW=new byte[100];
+		RAND rng=new RAND();
+		double dur;
+		rsa_public_key pub=new rsa_public_key(ROM.FFLEN);
+		rsa_private_key priv=new rsa_private_key(ROM.HFLEN);
+		byte[] P=new byte[RSA.RFS];
+		byte[] M=new byte[RSA.RFS];
+		byte[] C=new byte[RSA.RFS];
+
+
+		rng.clean();
+		for (i=0;i<100;i++) RAW[i]=(byte)(i);
+
+		rng.seed(100,RAW);	
+		if (ROM.CURVETYPE==ROM.WEIERSTRASS)
+		{
+			System.out.print("Weierstrass parameterization\n");
+		}		
+		if (ROM.CURVETYPE==ROM.EDWARDS)
+		{
+			System.out.print("Edwards parameterization\n");
+		}
+		if (ROM.CURVETYPE==ROM.MONTGOMERY)
+		{
+			System.out.print("Montgomery parameterization\n");
+		}
+
+		if (ROM.MODTYPE==ROM.PSEUDO_MERSENNE)
+		{
+			System.out.print("Pseudo-Mersenne Modulus\n");
+		}
+		if (ROM.MODTYPE==ROM.MONTGOMERY_FRIENDLY)
+		{
+			System.out.print("Montgomery friendly Modulus\n");
+		}
+		if (ROM.MODTYPE==ROM.GENERALISED_MERSENNE)
+		{
+			System.out.print("Generalised-Mersenne Modulus\n");
+		}
+		if (ROM.MODTYPE==ROM.NOT_SPECIAL)
+		{
+			System.out.print("Not special Modulus\n");
+		}
+
+		System.out.format("Modulus size %d bits\n",ROM.MODBITS); 
+		System.out.format("%d bit build\n",ROM.CHUNK); 
+		BIG r,gx,gy,s,wx,wy;
+		ECP G,WP;
+
+		gx=new BIG(ROM.CURVE_Gx);
+		if (ROM.CURVETYPE!=ROM.MONTGOMERY)
+		{
+			gy=new BIG(ROM.CURVE_Gy);
+			G=new ECP(gx,gy);
+		}
+		else
+			G=new ECP(gx);
+
+		r=new BIG(ROM.CURVE_Order);
+		s=BIG.randomnum(r,rng);
+
+		WP=G.mul(r);
+		if (!WP.is_infinity())
+		{
+			System.out.print("FAILURE - rG!=O\n");
+			return;
+		}
+
+		start = System.currentTimeMillis();
+		iterations=0;
+		do {
+			WP=G.mul(s);
+			iterations++;
+			elapsed=(System.currentTimeMillis()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=(double)elapsed/iterations;
+		System.out.format("EC  mul - %8d iterations  ",iterations);
+		System.out.format(" %8.2f ms per iteration\n",dur);
+
+
+		System.out.format("Generating %d-bit RSA public/private key pair\n",ROM.FFLEN*ROM.BIGBITS);
+
+		iterations=0;
+		start=System.currentTimeMillis();
+		do {
+			RSA.KEY_PAIR(rng,65537,priv,pub);
+			iterations++;
+			elapsed=(System.currentTimeMillis()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=(double)elapsed/iterations;
+		System.out.format("RSA gen - %8d iterations  ",iterations);
+		System.out.format(" %8.2f ms per iteration\n",dur);
+
+		for (i=0;i<RSA.RFS;i++) M[i]=(byte)(i%128);
+
+		iterations=0;
+		start=System.currentTimeMillis();
+		do {
+			RSA.ENCRYPT(pub,M,C);
+			iterations++;
+			elapsed=(System.currentTimeMillis()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=(double)elapsed/iterations;
+    	System.out.format("RSA enc - %8d iterations  ",iterations);
+    	System.out.format(" %8.2f ms per iteration\n",dur);
+
+		iterations=0;
+		start=System.currentTimeMillis();
+		do {
+			RSA.DECRYPT(priv,C,P);
+			iterations++;
+			elapsed=(System.currentTimeMillis()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=(double)elapsed/iterations;
+    	System.out.format("RSA dec - %8d iterations  ",iterations);
+    	System.out.format(" %8.2f ms per iteration\n",dur);
+
+		for (i=0;i<RSA.RFS;i++)
+		{
+			if (P[i]!=M[i])
+			{
+				System.out.print("FAILURE - RSA decryption\n");
+				return;
+			}
+		}
+
+		System.out.print("All tests pass\n");
+	}
+}
diff --git a/version22/java/BenchtestPAIR.java b/version22/java/BenchtestPAIR.java
new file mode 100644
index 0000000..6958643
--- /dev/null
+++ b/version22/java/BenchtestPAIR.java
@@ -0,0 +1,208 @@
+/*
+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.
+*/
+
+/* Test and benchmark pairing functions */
+
+public class BenchtestPAIR
+{
+	public static final int MIN_TIME=10; /* seconds */
+	public static final int MIN_ITERS=10; 
+
+	public static void main(String[] args) 
+	{
+		int i,iterations;
+		long start,elapsed;
+		byte[] RAW=new byte[100];
+		RAND rng=new RAND();
+		double dur;
+
+		rng.clean();
+		for (i=0;i<100;i++) RAW[i]=(byte)(i);
+		rng.seed(100,RAW);	
+
+		if (ROM.CURVE_PAIRING_TYPE==ROM.BN_CURVE)
+		{
+			System.out.print("BN Pairing-Friendly Curve\n");
+		}
+		if (ROM.CURVE_PAIRING_TYPE==ROM.BLS_CURVE)
+		{
+			System.out.print("BLS Pairing-Friendly Curve\n");
+		}
+
+		System.out.format("Modulus size %d bits\n",ROM.MODBITS); 
+		System.out.format("%d bit build\n",ROM.CHUNK); 
+
+		ECP G=new ECP(new BIG(ROM.CURVE_Gx),new BIG(ROM.CURVE_Gy));
+
+		BIG r=new BIG(ROM.CURVE_Order);
+		BIG s=BIG.randomnum(r,rng);
+
+		ECP P=PAIR.G1mul(G,r);
+
+		if (!P.is_infinity())
+		{
+			System.out.print("FAILURE - rP!=O\n");
+			return;
+		}
+
+		iterations=0;
+		start=System.currentTimeMillis();
+		do {
+			P=PAIR.G1mul(G,s);
+			iterations++;
+			elapsed=(System.currentTimeMillis()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=(double)elapsed/iterations;
+		System.out.format("G1 mul              - %8d iterations  ",iterations);
+		System.out.format(" %8.2f ms per iteration\n",dur);
+	
+		ECP2 Q=new ECP2(new FP2(new BIG(ROM.CURVE_Pxa),new BIG(ROM.CURVE_Pxb)),new FP2(new BIG(ROM.CURVE_Pya),new BIG(ROM.CURVE_Pyb)));
+		ECP2 W=PAIR.G2mul(Q,r);
+
+		if (!W.is_infinity())
+		{
+			System.out.print("FAILURE - rQ!=O\n");
+			return;
+		}
+
+		iterations=0;
+		start=System.currentTimeMillis();
+		do {
+			W=PAIR.G2mul(Q,s);
+			iterations++;
+			elapsed=(System.currentTimeMillis()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=(double)elapsed/iterations;
+		System.out.format("G2 mul              - %8d iterations  ",iterations);
+		System.out.format(" %8.2f ms per iteration\n",dur);
+
+		FP12 w=PAIR.ate(Q,P);
+		w=PAIR.fexp(w);
+
+		FP12 g=PAIR.GTpow(w,r);
+
+		if (!g.isunity())
+		{
+			System.out.print("FAILURE - g^r!=1\n");
+			return;
+		}
+
+		iterations=0;
+		start=System.currentTimeMillis();
+		do {
+			g=PAIR.GTpow(w,s);
+			iterations++;
+			elapsed=(System.currentTimeMillis()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=(double)elapsed/iterations;
+		System.out.format("GT pow              - %8d iterations  ",iterations);
+		System.out.format(" %8.2f ms per iteration\n",dur);
+	
+		FP2 f=new FP2(new BIG(ROM.CURVE_Fra),new BIG(ROM.CURVE_Frb));
+		BIG q=new BIG(ROM.Modulus);
+
+		BIG m=new BIG(q);
+		m.mod(r);
+
+		BIG a=new BIG(s);
+		a.mod(m);
+
+		BIG b=new BIG(s);
+		b.div(m);
+
+		g.copy(w);
+		FP4 c=g.trace();
+
+		g.frob(f);
+		FP4 cp=g.trace();
+
+		w.conj();
+		g.mul(w);
+		FP4 cpm1=g.trace();
+		g.mul(w);
+		FP4 cpm2=g.trace();
+		FP4 cr;
+
+		iterations=0;
+		start=System.currentTimeMillis();
+		do {
+			cr=c.xtr_pow2(cp,cpm1,cpm2,a,b);
+			iterations++;
+			elapsed=(System.currentTimeMillis()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=(double)elapsed/iterations;
+		System.out.format("GT pow (compressed) - %8d iterations  ",iterations);
+		System.out.format(" %8.2f ms per iteration\n",dur);
+
+		iterations=0;
+		start=System.currentTimeMillis();
+		do {
+			w=PAIR.ate(Q,P);
+			iterations++;
+			elapsed=(System.currentTimeMillis()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=(double)elapsed/iterations;
+		System.out.format("PAIRing ATE         - %8d iterations  ",iterations);
+		System.out.format(" %8.2f ms per iteration\n",dur);
+
+		iterations=0;
+		start=System.currentTimeMillis();
+		do {
+			g=PAIR.fexp(w);
+			iterations++;
+			elapsed=(System.currentTimeMillis()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=(double)elapsed/iterations;
+		System.out.format("PAIRing FEXP        - %8d iterations  ",iterations);
+		System.out.format(" %8.2f ms per iteration\n",dur);
+
+		P.copy(G);
+		Q.copy(W);
+
+		P=PAIR.G1mul(P,s);
+
+		g=PAIR.ate(Q,P);
+		g=PAIR.fexp(g);
+
+		P.copy(G);
+		Q=PAIR.G2mul(Q,s);
+
+		w=PAIR.ate(Q,P);
+		w=PAIR.fexp(w);
+
+		if (!g.equals(w))
+		{
+			System.out.print("FAILURE - e(sQ,p)!=e(Q,sP) \n");
+			return;
+		}
+
+		Q.copy(W);
+		g=PAIR.ate(Q,P);
+		g=PAIR.fexp(g);
+		g=PAIR.GTpow(g,s);
+
+		if (!g.equals(w))
+		{
+			System.out.print("FAILURE - e(sQ,p)!=e(Q,P)^s \n");
+			return;
+		}
+
+		System.out.print("All tests pass\n"); 
+	}
+}
diff --git a/version22/java/DBIG32.java b/version22/java/DBIG32.java
new file mode 100644
index 0000000..892fcd1
--- /dev/null
+++ b/version22/java/DBIG32.java
@@ -0,0 +1,308 @@
+/*
+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.
+*/
+
+/* AMCL double length DBIG number class */ 
+
+public class DBIG {
+	protected int[] w=new int[ROM.DNLEN];
+
+/* normalise this */
+	public void norm() {
+		int d,carry=0;
+		for (int i=0;i<ROM.DNLEN-1;i++)
+		{
+			d=w[i]+carry;
+			carry=d>>ROM.BASEBITS;
+			w[i]=d&ROM.BMASK;
+		}
+		w[ROM.DNLEN-1]=(w[ROM.DNLEN-1]+carry);
+	}
+
+
+/*
+	public String toRawString()
+	{
+		DBIG b=new DBIG(this);
+		String s="(";
+		for (int i=0;i<ROM.DNLEN-1;i++)
+		{
+			s+=Integer.toHexString(b.w[i]); s+=",";
+		}
+		s+=Integer.toHexString(b.w[ROM.DNLEN-1]); s+=")";
+		return s;
+	}
+*/
+
+
+/****************************************************************************/
+
+
+/* return number of bits in this */
+	public int nbits() {
+		int bts,k=ROM.DNLEN-1;
+		long c;
+		norm();
+		while (w[k]==0 && k>=0) k--;
+		if (k<0) return 0;
+		bts=ROM.BASEBITS*k;
+		c=w[k];
+		while (c!=0) {c/=2; bts++;}
+		return bts;
+	}
+
+/* convert this to string */
+	public String toString() {
+		DBIG b;
+		String s="";
+		int len=nbits();
+		if (len%4==0) len>>=2; //len/=4;
+		else {len>>=2; len++;}
+
+		for (int i=len-1;i>=0;i--)
+		{
+			b=new DBIG(this);
+			b.shr(i*4);
+			s+=Integer.toHexString((int)(b.w[0]&15));
+		}
+		return s;
+	}
+
+	public void cmove(DBIG g,int d)
+	{
+		int i;
+	//	int b=-d;
+
+		for (i=0;i<ROM.DNLEN;i++)
+		{
+			w[i]^=(w[i]^g.w[i])&BIG.cast_to_chunk(-d);
+		}
+	}
+
+/* Constructors */
+	public DBIG(int x)
+	{
+		w[0]=x;
+		for (int i=1;i<ROM.DNLEN;i++)
+			w[i]=0;
+	}
+
+	public DBIG(DBIG x)
+	{
+		for (int i=0;i<ROM.DNLEN;i++)
+			w[i]=x.w[i];
+	}
+
+	public DBIG(BIG x)
+	{
+		for (int i=0;i<ROM.NLEN-1;i++)
+			w[i]=x.w[i];//get(i);
+
+		w[ROM.NLEN-1]=x.w[(ROM.NLEN-1)]&ROM.BMASK; /* top word normalized */
+		w[ROM.NLEN]=(x.w[(ROM.NLEN-1)]>>ROM.BASEBITS);
+
+		for (int i=ROM.NLEN+1;i<ROM.DNLEN;i++) w[i]=0;
+	}
+
+/* split DBIG at position n, return higher half, keep lower half */
+	public BIG split(int n)
+	{
+		BIG t=new BIG(0);
+		int nw,m=n%ROM.BASEBITS;
+		int carry=w[ROM.DNLEN-1]<<(ROM.BASEBITS-m);
+
+		for (int i=ROM.DNLEN-2;i>=ROM.NLEN-1;i--)
+		{
+			nw=(w[i]>>m)|carry;
+			carry=(w[i]<<(ROM.BASEBITS-m))&ROM.BMASK;
+			t.w[i-ROM.NLEN+1]=nw;
+		//	t.set(i-ROM.NLEN+1,nw);
+		}
+		w[ROM.NLEN-1]&=(((int)1<<m)-1);
+		return t;
+	}
+
+/* Copy from another DBIG */
+	public void copy(DBIG x)
+	{
+		for (int i=0;i<ROM.DNLEN;i++)
+			w[i]=x.w[i];
+	}
+
+/* test this=0? */
+	public boolean iszilch() {
+		for (int i=0;i<ROM.DNLEN;i++)
+			if (w[i]!=0) return false;
+		return true; 
+	}
+
+/* shift this right by k bits */
+	public void shr(int k) {
+		int n=k%ROM.BASEBITS;
+		int m=k/ROM.BASEBITS;	
+		for (int i=0;i<ROM.DNLEN-m-1;i++)
+			w[i]=(w[m+i]>>n)|((w[m+i+1]<<(ROM.BASEBITS-n))&ROM.BMASK);
+		w[ROM.DNLEN-m-1]=w[ROM.DNLEN-1]>>n;
+		for (int i=ROM.DNLEN-m;i<ROM.DNLEN;i++) w[i]=0;
+	}
+
+/* shift this left by k bits */
+	public void shl(int k) {
+		int n=k%ROM.BASEBITS;
+		int m=k/ROM.BASEBITS;
+
+		w[ROM.DNLEN-1]=((w[ROM.DNLEN-1-m]<<n))|(w[ROM.DNLEN-m-2]>>(ROM.BASEBITS-n));
+		for (int i=ROM.DNLEN-2;i>m;i--)
+			w[i]=((w[i-m]<<n)&ROM.BMASK)|(w[i-m-1]>>(ROM.BASEBITS-n));
+		w[m]=(w[0]<<n)&ROM.BMASK; 
+		for (int i=0;i<m;i++) w[i]=0;
+	}
+
+/* this+=x */
+	public void add(DBIG x) {
+		for (int i=0;i<ROM.DNLEN;i++)
+			w[i]+=x.w[i];	
+	}
+
+/* this-=x */
+	public void sub(DBIG x) {
+		for (int i=0;i<ROM.DNLEN;i++)
+			w[i]-=x.w[i];
+	}
+
+/* Compare a and b, return 0 if a==b, -1 if a<b, +1 if a>b. Inputs must be normalised */
+	public static int comp(DBIG a,DBIG b)
+	{
+		for (int i=ROM.DNLEN-1;i>=0;i--)
+		{
+			if (a.w[i]==b.w[i]) continue;
+			if (a.w[i]>b.w[i]) return 1;
+			else  return -1;
+		}
+		return 0;
+	}
+
+/* reduces this DBIG mod a BIG, and returns the BIG */
+	public BIG mod(BIG c)
+	{
+		int k=0;  
+		norm();
+		DBIG m=new DBIG(c);
+		DBIG r=new DBIG(0);
+
+		if (comp(this,m)<0) return new BIG(this);
+		
+		do
+		{
+			m.shl(1);
+			k++;
+		}
+		while (comp(this,m)>=0);
+
+		while (k>0)
+		{
+			m.shr(1);
+
+			r.copy(this);
+			r.sub(m);
+			r.norm();
+			cmove(r,(int)(1-((r.w[ROM.DNLEN-1]>>(ROM.CHUNK-1))&1)));
+/*
+			if (comp(this,m)>=0)
+			{
+				sub(m);
+				norm();
+			}
+*/
+			k--;
+		}
+		return new BIG(this);
+	}
+
+/* reduces this DBIG mod a DBIG in place */
+/*	public void mod(DBIG m)
+	{
+		int k=0;
+		if (comp(this,m)<0) return;
+
+		do
+		{
+			m.shl(1);
+			k++;
+		}
+		while (comp(this,m)>=0);
+
+		while (k>0)
+		{
+			m.shr(1);
+			if (comp(this,m)>=0)
+			{
+				sub(m);
+				norm();
+			}
+			k--;
+		}
+		return;
+
+	}*/
+
+/* return this/c */
+	public BIG div(BIG c)
+	{
+		int d,k=0;
+		DBIG m=new DBIG(c);
+		DBIG dr=new DBIG(0);
+		BIG r=new BIG(0);
+		BIG a=new BIG(0);
+		BIG e=new BIG(1);
+		norm();
+
+		while (comp(this,m)>=0)
+		{
+			e.fshl(1);
+			m.shl(1);
+			k++;
+		}
+
+		while (k>0)
+		{
+			m.shr(1);
+			e.shr(1);
+
+			dr.copy(this);
+			dr.sub(m);
+			dr.norm();
+			d=(int)(1-((dr.w[ROM.DNLEN-1]>>(ROM.CHUNK-1))&1));
+			cmove(dr,d);
+			r.copy(a);
+			r.add(e);
+			r.norm();
+			a.cmove(r,d);
+/*
+			if (comp(this,m)>0)
+			{
+				a.add(e);
+				a.norm();
+				sub(m);
+				norm();
+			} */
+			k--;
+		}
+		return a;
+	}
+}
diff --git a/version22/java/DBIG64.java b/version22/java/DBIG64.java
new file mode 100644
index 0000000..4596077
--- /dev/null
+++ b/version22/java/DBIG64.java
@@ -0,0 +1,306 @@
+/*
+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.
+*/
+
+/* AMCL double length DBIG number class */ 
+
+public class DBIG {
+	protected long[] w=new long[ROM.DNLEN];
+
+/* normalise this */
+	public void norm() {
+		long d,carry=0;
+		for (int i=0;i<ROM.DNLEN-1;i++)
+		{
+			d=w[i]+carry;
+			carry=d>>ROM.BASEBITS;
+			w[i]=d&ROM.BMASK;
+		}
+		w[ROM.DNLEN-1]=(w[ROM.DNLEN-1]+carry);
+	}
+
+
+/*
+	public String toRawString()
+	{
+		DBIG b=new DBIG(this);
+		String s="(";
+		for (int i=0;i<ROM.DNLEN-1;i++)
+		{
+			s+=Long.toHexString(b.w[i]); s+=",";
+		}
+		s+=Long.toHexString(b.w[ROM.DNLEN-1]); s+=")";
+		return s;
+	}
+*/
+
+/****************************************************************************/
+
+/* return number of bits in this */
+	public int nbits() {
+		int bts,k=ROM.DNLEN-1;
+		long c;
+		norm();
+		while (w[k]==0 && k>=0) k--;
+		if (k<0) return 0;
+		bts=ROM.BASEBITS*k;
+		c=w[k];
+		while (c!=0) {c/=2; bts++;}
+		return bts;
+	}
+
+/* convert this to string */
+	public String toString() {
+		DBIG b;
+		String s="";
+		int len=nbits();
+		if (len%4==0) len>>=2; //len/=4;
+		else {len>>=2; len++;}
+
+		for (int i=len-1;i>=0;i--)
+		{
+			b=new DBIG(this);
+			b.shr(i*4);
+			s+=Integer.toHexString((int)(b.w[0]&15));
+		}
+		return s;
+	}
+
+	public void cmove(DBIG g,int d)
+	{
+		int i;
+		//long b=-d;
+
+		for (i=0;i<ROM.DNLEN;i++)
+		{
+			w[i]^=(w[i]^g.w[i])&BIG.cast_to_chunk(-d);
+		}
+	}
+
+/* Constructors */
+	public DBIG(int x)
+	{
+		w[0]=x;
+		for (int i=1;i<ROM.DNLEN;i++)
+			w[i]=0;
+	}
+
+	public DBIG(DBIG x)
+	{
+		for (int i=0;i<ROM.DNLEN;i++)
+			w[i]=x.w[i];
+	}
+
+	public DBIG(BIG x)
+	{
+		for (int i=0;i<ROM.NLEN-1;i++)
+			w[i]=x.w[i]; //get(i);
+
+		w[ROM.NLEN-1]=x.w[(ROM.NLEN-1)]&ROM.BMASK; /* top word normalized */
+		w[ROM.NLEN]=(x.w[(ROM.NLEN-1)]>>ROM.BASEBITS);
+
+		for (int i=ROM.NLEN+1;i<ROM.DNLEN;i++) w[i]=0;
+	}
+
+/* split DBIG at position n, return higher half, keep lower half */
+	public BIG split(int n)
+	{
+		BIG t=new BIG(0);
+		int m=n%ROM.BASEBITS;
+		long nw,carry=w[ROM.DNLEN-1]<<(ROM.BASEBITS-m);
+
+		for (int i=ROM.DNLEN-2;i>=ROM.NLEN-1;i--)
+		{
+			nw=(w[i]>>m)|carry;
+			carry=(w[i]<<(ROM.BASEBITS-m))&ROM.BMASK;
+			t.w[i-ROM.NLEN+1]=nw;
+			//t.set(i-ROM.NLEN+1,nw);
+		}
+		w[ROM.NLEN-1]&=(((long)1<<m)-1);
+		return t;
+	}
+
+/* Copy from another DBIG */
+	public void copy(DBIG x)
+	{
+		for (int i=0;i<ROM.DNLEN;i++)
+			w[i]=x.w[i];
+	}
+
+/* test this=0? */
+	public boolean iszilch() {
+		for (int i=0;i<ROM.DNLEN;i++)
+			if (w[i]!=0) return false;
+		return true; 
+	}
+
+/* shift this right by k bits */
+	public void shr(int k) {
+		int n=k%ROM.BASEBITS;
+		int m=k/ROM.BASEBITS;	
+		for (int i=0;i<ROM.DNLEN-m-1;i++)
+			w[i]=(w[m+i]>>n)|((w[m+i+1]<<(ROM.BASEBITS-n))&ROM.BMASK);
+		w[ROM.DNLEN-m-1]=w[ROM.DNLEN-1]>>n;
+		for (int i=ROM.DNLEN-m;i<ROM.DNLEN;i++) w[i]=0;
+	}
+
+/* shift this left by k bits */
+	public void shl(int k) {
+		int n=k%ROM.BASEBITS;
+		int m=k/ROM.BASEBITS;
+
+		w[ROM.DNLEN-1]=((w[ROM.DNLEN-1-m]<<n))|(w[ROM.DNLEN-m-2]>>(ROM.BASEBITS-n));
+		for (int i=ROM.DNLEN-2;i>m;i--)
+			w[i]=((w[i-m]<<n)&ROM.BMASK)|(w[i-m-1]>>(ROM.BASEBITS-n));
+		w[m]=(w[0]<<n)&ROM.BMASK; 
+		for (int i=0;i<m;i++) w[i]=0;
+	}
+
+/* this+=x */
+	public void add(DBIG x) {
+		for (int i=0;i<ROM.DNLEN;i++)
+			w[i]+=x.w[i];	
+	}
+
+/* this-=x */
+	public void sub(DBIG x) {
+		for (int i=0;i<ROM.DNLEN;i++)
+			w[i]-=x.w[i];
+	}
+
+/* Compare a and b, return 0 if a==b, -1 if a<b, +1 if a>b. Inputs must be normalised */
+	public static int comp(DBIG a,DBIG b)
+	{
+		for (int i=ROM.DNLEN-1;i>=0;i--)
+		{
+			if (a.w[i]==b.w[i]) continue;
+			if (a.w[i]>b.w[i]) return 1;
+			else  return -1;
+		}
+		return 0;
+	}
+
+/* reduces this DBIG mod a BIG, and returns the BIG */
+	public BIG mod(BIG c)
+	{
+		int k=0;  
+		norm();
+		DBIG m=new DBIG(c);
+		DBIG r=new DBIG(0);
+
+		if (comp(this,m)<0) return new BIG(this);
+		
+		do
+		{
+			m.shl(1);
+			k++;
+		}
+		while (comp(this,m)>=0);
+
+		while (k>0)
+		{
+			m.shr(1);
+
+			r.copy(this);
+			r.sub(m);
+			r.norm();
+			cmove(r,(int)(1-((r.w[ROM.DNLEN-1]>>(ROM.CHUNK-1))&1)));
+/*
+			if (comp(this,m)>=0)
+			{
+				sub(m);
+				norm();
+			}
+*/
+			k--;
+		}
+		return new BIG(this);
+	}
+
+/* reduces this DBIG mod a DBIG in place */
+/*	public void mod(DBIG m)
+	{
+		int k=0;
+		if (comp(this,m)<0) return;
+
+		do
+		{
+			m.shl(1);
+			k++;
+		}
+		while (comp(this,m)>=0);
+
+		while (k>0)
+		{
+			m.shr(1);
+			if (comp(this,m)>=0)
+			{
+				sub(m);
+				norm();
+			}
+			k--;
+		}
+		return;
+
+	}*/
+
+/* return this/c */
+	public BIG div(BIG c)
+	{
+		int d,k=0;
+		DBIG m=new DBIG(c);
+		DBIG dr=new DBIG(0);
+		BIG r=new BIG(0);
+		BIG a=new BIG(0);
+		BIG e=new BIG(1);
+		norm();
+
+		while (comp(this,m)>=0)
+		{
+			e.fshl(1);
+			m.shl(1);
+			k++;
+		}
+
+		while (k>0)
+		{
+			m.shr(1);
+			e.shr(1);
+
+			dr.copy(this);
+			dr.sub(m);
+			dr.norm();
+			d=(int)(1-((dr.w[ROM.DNLEN-1]>>(ROM.CHUNK-1))&1));
+			cmove(dr,d);
+			r.copy(a);
+			r.add(e);
+			r.norm();
+			a.cmove(r,d);
+/*
+			if (comp(this,m)>0)
+			{
+				a.add(e);
+				a.norm();
+				sub(m);
+				norm();
+			} */
+			k--;
+		}
+		return a;
+	}
+}
diff --git a/version22/java/ECDH.java b/version22/java/ECDH.java
new file mode 100644
index 0000000..12b7589
--- /dev/null
+++ b/version22/java/ECDH.java
@@ -0,0 +1,581 @@
+/*
+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.
+*/
+
+/* Elliptic Curve API high-level functions  */
+
+public final class ECDH {
+	public static final int INVALID_PUBLIC_KEY=-2;
+	public static final int ERROR=-3;
+	public static final int INVALID=-4;
+	public static final int EFS=ROM.MODBYTES;
+	public static final int EGS=ROM.MODBYTES;
+	public static final int EAS=16;
+	public static final int EBS=16;
+	public static final int SHA256=32;
+	public static final int SHA384=48;
+	public static final int SHA512=64;
+
+	public static final int HASH_TYPE=SHA512;
+
+/* Convert Integer to n-byte array */
+	private static byte[] inttoBytes(int n,int len)
+	{
+		int i;
+		byte[] b=new byte[len];
+
+		for (i=0;i<len;i++) b[i]=0;
+		i=len; 
+		while (n>0 && i>0)
+		{
+			i--;
+			b[i]=(byte)(n&0xff);
+			n/=256;
+		}	
+		return b;
+	}
+
+	private static byte[] hashit(int sha,byte[] A,int n,byte[] B,int pad)
+	{
+		byte[] R=null;
+
+		if (sha==SHA256)
+		{
+			HASH256 H=new HASH256();
+			H.process_array(A); if (n>0) H.process_num(n);
+			if (B!=null) H.process_array(B);
+			R=H.hash();
+		}
+		if (sha==SHA384)
+		{
+			HASH384 H=new HASH384();
+			H.process_array(A); if (n>0) H.process_num(n);
+			if (B!=null) H.process_array(B);
+			R=H.hash();
+		}
+		if (sha==SHA512)
+		{
+			HASH512 H=new HASH512();
+			H.process_array(A); if (n>0) H.process_num(n);
+			if (B!=null) H.process_array(B);
+			R=H.hash();
+		}
+		if (R==null) return null;
+
+		if (pad==0) return R;
+/* If pad>0 output is truncated or padded to pad bytes */
+		byte[] W=new byte[pad];
+		if (pad<=sha) 
+		{
+			for (int i=0;i<pad;i++) W[i]=R[i];
+		}
+		else
+		{
+			for (int i=0;i<sha;i++) W[i]=R[i];
+			for (int i=sha;i<pad;i++) W[i]=0;
+		}
+		return W;
+	}
+
+/* Key Derivation Functions */
+/* Input octet Z */
+/* Output key of length olen */
+	public static byte[] KDF1(int sha,byte[] Z,int olen)
+	{
+/* NOTE: the parameter olen is the length of the output K in bytes */
+		int hlen=sha;
+		byte[] K=new byte[olen];
+		byte[] B;
+		int counter,cthreshold,k=0;
+    
+		for (int i=0;i<K.length;i++) K[i]=0;
+
+		cthreshold=olen/hlen; if (olen%hlen!=0) cthreshold++;
+
+		for (counter=0;counter<cthreshold;counter++)
+		{
+			B=hashit(sha,Z,counter,null,0);
+			if (k+hlen>olen) for (int i=0;i<olen%hlen;i++) K[k++]=B[i];
+			else for (int i=0;i<hlen;i++) K[k++]=B[i];
+		}
+		return K;
+	}
+
+	public static byte[] KDF2(int sha,byte[] Z,byte[] P,int olen)
+	{
+/* NOTE: the parameter olen is the length of the output k in bytes */
+		int hlen=sha;
+		byte[] K=new byte[olen];
+		byte[] B;
+		int counter,cthreshold,k=0;
+    
+		for (int i=0;i<K.length;i++) K[i]=0;
+
+		cthreshold=olen/hlen; if (olen%hlen!=0) cthreshold++;
+
+		for (counter=1;counter<=cthreshold;counter++)
+		{
+			B=hashit(sha,Z,counter,P,0);
+			if (k+hlen>olen) for (int i=0;i<olen%hlen;i++) K[k++]=B[i];
+			else for (int i=0;i<hlen;i++) K[k++]=B[i];
+		}
+
+		return K;
+	}
+
+/* Password based Key Derivation Function */
+/* Input password p, salt s, and repeat count */
+/* Output key of length olen */
+	public static byte[] PBKDF2(int sha,byte[] Pass,byte[] Salt,int rep,int olen)
+	{
+		int i,j,k,len,d,opt;
+		d=olen/sha; if (olen%sha!=0) d++;
+		byte[] F=new byte[sha];
+		byte[] U=new byte[sha];
+		byte[] S=new byte[Salt.length+4];
+
+		byte[] K=new byte[d*sha];
+		opt=0;
+
+		for (i=1;i<=d;i++)
+		{
+			for (j=0;j<Salt.length;j++) S[j]=Salt[j];
+			byte[] N=inttoBytes(i,4);
+			for (j=0;j<4;j++) S[Salt.length+j]=N[j];
+
+			HMAC(sha,S,Pass,F);
+
+			for (j=0;j<sha;j++) U[j]=F[j];
+			for (j=2;j<=rep;j++)
+			{
+				HMAC(sha,U,Pass,U);
+				for (k=0;k<sha;k++) F[k]^=U[k];
+			}
+			for (j=0;j<sha;j++) K[opt++]=F[j];
+		}
+		byte[] key=new byte[olen];
+		for (i=0;i<olen;i++) key[i]=K[i];
+		return key;
+	}
+
+/* Calculate HMAC of m using key k. HMAC is tag of length olen */
+	public static int HMAC(int sha,byte[] M,byte[] K,byte[] tag)
+	{
+	/* Input is from an octet m        *
+	* olen is requested output length in bytes. k is the key  *
+	* The output is the calculated tag */
+		int b=64;
+		if (sha>32) b=128;
+		byte[] B;
+		byte[] K0=new byte[b];
+		int olen=tag.length;
+
+		//b=K0.length;
+		if (olen<4 /*|| olen>sha*/) return 0;
+
+		for (int i=0;i<b;i++) K0[i]=0;
+
+		if (K.length > b) 
+		{
+			B=hashit(sha,K,0,null,0);
+			for (int i=0;i<sha;i++) K0[i]=B[i];
+		}
+		else
+			for (int i=0;i<K.length;i++ ) K0[i]=K[i];
+		
+		for (int i=0;i<b;i++) K0[i]^=0x36;
+		B=hashit(sha,K0,0,M,0);
+
+		for (int i=0;i<b;i++) K0[i]^=0x6a;
+		B=hashit(sha,K0,0,B,olen);
+
+		for (int i=0;i<olen;i++) tag[i]=B[i];
+
+		return 1;
+	}
+
+/* AES encryption/decryption. Encrypt byte array M using key K and returns ciphertext */
+	public static byte[] AES_CBC_IV0_ENCRYPT(byte[] K,byte[] M)
+	{ /* AES CBC encryption, with Null IV and key K */
+	/* Input is from an octet string M, output is to an octet string C */
+	/* Input is padded as necessary to make up a full final block */
+		AES a=new AES();
+		boolean fin;
+		int i,j,ipt,opt;
+		byte[] buff=new byte[16];
+		int clen=16+(M.length/16)*16;
+
+		byte[] C=new byte[clen];
+		int padlen;
+
+		a.init(AES.CBC,K.length,K,null);
+
+		ipt=opt=0;
+		fin=false;
+		for(;;)
+		{
+			for (i=0;i<16;i++)
+			{
+				if (ipt<M.length) buff[i]=M[ipt++];
+				else {fin=true; break;}
+			}
+			if (fin) break;
+			a.encrypt(buff);
+			for (i=0;i<16;i++)
+				C[opt++]=buff[i];
+		}    
+
+/* last block, filled up to i-th index */
+
+		padlen=16-i;
+		for (j=i;j<16;j++) buff[j]=(byte)padlen;
+
+		a.encrypt(buff);
+
+		for (i=0;i<16;i++)
+			C[opt++]=buff[i];
+		a.end();    
+		return C;
+	}
+
+/* returns plaintext if all consistent, else returns null string */
+	public static byte[] AES_CBC_IV0_DECRYPT(byte[] K,byte[] C)
+	{ /* padding is removed */
+		AES a=new AES();
+		int i,ipt,opt,ch;
+		byte[] buff=new byte[16];
+		byte[] MM=new byte[C.length];
+		boolean fin,bad;
+		int padlen;
+		ipt=opt=0;
+
+		a.init(AES.CBC,K.length,K,null);
+
+		if (C.length==0) return new byte[0];
+		ch=C[ipt++]; 
+  
+		fin=false;
+
+		for(;;)
+		{
+			for (i=0;i<16;i++)
+			{
+				buff[i]=(byte)ch;      
+				if (ipt>=C.length) {fin=true; break;}  
+				else ch=C[ipt++];  
+			}
+			a.decrypt(buff);
+			if (fin) break;
+			for (i=0;i<16;i++)
+				MM[opt++]=buff[i];
+		}    
+
+		a.end();
+		bad=false;
+		padlen=buff[15];
+		if (i!=15 || padlen<1 || padlen>16) bad=true;
+		if (padlen>=2 && padlen<=16)
+			for (i=16-padlen;i<16;i++) if (buff[i]!=padlen) bad=true;
+    
+		if (!bad) for (i=0;i<16-padlen;i++)
+					MM[opt++]=buff[i];
+
+		if (bad) return new byte[0];
+
+		byte[] M=new byte[opt];
+		for (i=0;i<opt;i++) M[i]=MM[i];
+
+		return M;
+	}
+
+/* Calculate a public/private EC GF(p) key pair W,S where W=S.G mod EC(p),
+ * where S is the secret key and W is the public key
+ * and G is fixed generator.
+ * If RNG is NULL then the private key is provided externally in S
+ * otherwise it is generated randomly internally */
+	public static int KEY_PAIR_GENERATE(RAND RNG,byte[] S,byte[] W)
+	{
+		BIG r,gx,gy,s,wx,wy;
+		ECP G,WP;
+		int res=0;
+	//	byte[] T=new byte[EFS];
+
+		gx=new BIG(ROM.CURVE_Gx);
+
+		if (ROM.CURVETYPE!=ROM.MONTGOMERY)
+		{
+			gy=new BIG(ROM.CURVE_Gy);
+			G=new ECP(gx,gy);
+		}
+		else
+			G=new ECP(gx);
+
+		r=new BIG(ROM.CURVE_Order);
+
+		if (RNG==null)
+		{
+			s=BIG.fromBytes(S);
+			s.mod(r);
+		}
+		else
+		{
+			s=BIG.randomnum(r,RNG);
+		}
+
+		if (ROM.AES_S>0)
+		{
+			s.mod2m(2*ROM.AES_S);
+		}
+		s.toBytes(S);
+
+		WP=G.mul(s);
+		WP.toBytes(W);
+
+		return res;
+	}
+
+/* validate public key. Set full=true for fuller check */
+	public static int PUBLIC_KEY_VALIDATE(boolean full,byte[] W)
+	{
+		BIG r;
+		ECP WP=ECP.fromBytes(W);
+		int res=0;
+
+		r=new BIG(ROM.CURVE_Order);
+
+		if (WP.is_infinity()) res=INVALID_PUBLIC_KEY;
+
+		if (res==0 && full)
+		{
+			WP=WP.mul(r);
+			if (!WP.is_infinity()) res=INVALID_PUBLIC_KEY; 
+		}
+		return res;
+	}
+
+/* IEEE-1363 Diffie-Hellman online calculation Z=S.WD */
+	public static int ECPSVDP_DH(byte[] S,byte[] WD,byte[] Z)    
+	{
+		BIG r,s,wx,wy,z;
+		int valid;
+		ECP W;
+		int res=0;
+		byte[] T=new byte[EFS];
+
+		s=BIG.fromBytes(S);
+
+		W=ECP.fromBytes(WD);
+		if (W.is_infinity()) res=ERROR;
+
+		if (res==0)
+		{
+			r=new BIG(ROM.CURVE_Order);
+			s.mod(r);
+
+			W=W.mul(s);
+			if (W.is_infinity()) res=ERROR; 
+			else 
+			{
+				W.getX().toBytes(T);
+				for (int i=0;i<EFS;i++) Z[i]=T[i];
+			}
+		}
+		return res;
+	}
+
+/* IEEE ECDSA Signature, C and D are signature on F using private key S */
+	public static int ECPSP_DSA(int sha,RAND RNG,byte[] S,byte[] F,byte[] C,byte[] D)
+	{
+		byte[] T=new byte[EFS];
+		BIG gx,gy,r,s,f,c,d,u,vx,w;
+		ECP G,V;
+		byte[] B=hashit(sha,F,0,null,ROM.MODBYTES);
+
+		gx=new BIG(ROM.CURVE_Gx);
+		gy=new BIG(ROM.CURVE_Gy);
+
+		G=new ECP(gx,gy);
+		r=new BIG(ROM.CURVE_Order);
+
+		s=BIG.fromBytes(S);
+		f=BIG.fromBytes(B);
+
+		c=new BIG(0);
+		d=new BIG(0);
+		V=new ECP();
+
+		do {
+			u=BIG.randomnum(r,RNG);
+			w=BIG.randomnum(r,RNG);
+			if (ROM.AES_S>0)
+			{
+				u.mod2m(2*ROM.AES_S);
+			}			
+			V.copy(G);
+			V=V.mul(u);   		
+			vx=V.getX();
+			c.copy(vx);
+			c.mod(r);
+			if (c.iszilch()) continue;
+
+			u.copy(BIG.modmul(u,w,r));
+
+			u.invmodp(r);
+			d.copy(BIG.modmul(s,c,r));
+			d.add(f);
+
+			d.copy(BIG.modmul(d,w,r));
+
+			d.copy(BIG.modmul(u,d,r));
+		} while (d.iszilch());
+       
+		c.toBytes(T);
+		for (int i=0;i<EFS;i++) C[i]=T[i];
+		d.toBytes(T);
+		for (int i=0;i<EFS;i++) D[i]=T[i];
+		return 0;
+	}
+
+/* IEEE1363 ECDSA Signature Verification. Signature C and D on F is verified using public key W */
+	public static int ECPVP_DSA(int sha,byte[] W,byte[] F, byte[] C,byte[] D)
+	{
+		BIG r,gx,gy,f,c,d,h2;
+		int res=0;
+		ECP G,WP,P;
+		int valid; 
+
+		byte[] B=hashit(sha,F,0,null,ROM.MODBYTES);
+
+		gx=new BIG(ROM.CURVE_Gx);
+		gy=new BIG(ROM.CURVE_Gy);
+
+		G=new ECP(gx,gy);
+		r=new BIG(ROM.CURVE_Order);
+
+		c=BIG.fromBytes(C);
+		d=BIG.fromBytes(D);
+		f=BIG.fromBytes(B);
+     
+		if (c.iszilch() || BIG.comp(c,r)>=0 || d.iszilch() || BIG.comp(d,r)>=0) 
+            res=INVALID;
+
+		if (res==0)
+		{
+			d.invmodp(r);
+			f.copy(BIG.modmul(f,d,r));
+			h2=BIG.modmul(c,d,r);
+
+			WP=ECP.fromBytes(W);
+			if (WP.is_infinity()) res=ERROR;
+			else
+			{
+				P=new ECP();
+				P.copy(WP);
+				P=P.mul2(h2,G,f);
+				if (P.is_infinity()) res=INVALID;
+				else
+				{
+					d=P.getX();
+					d.mod(r);
+					if (BIG.comp(d,c)!=0) res=INVALID;
+				}
+			}
+		}
+
+		return res;
+	}
+
+/* IEEE1363 ECIES encryption. Encryption of plaintext M uses public key W and produces ciphertext V,C,T */
+	public static byte[] ECIES_ENCRYPT(int sha,byte[] P1,byte[] P2,RAND RNG,byte[] W,byte[] M,byte[] V,byte[] T)
+	{ 
+		int i,len;
+
+		byte[] Z=new byte[EFS];
+		byte[] VZ=new byte[3*EFS+1];
+		byte[] K1=new byte[EAS];
+		byte[] K2=new byte[EAS];
+		byte[] U=new byte[EGS];
+
+		if (KEY_PAIR_GENERATE(RNG,U,V)!=0) return new byte[0];  
+		if (ECPSVDP_DH(U,W,Z)!=0) return new byte[0];     
+
+		for (i=0;i<2*EFS+1;i++) VZ[i]=V[i];
+		for (i=0;i<EFS;i++) VZ[2*EFS+1+i]=Z[i];
+
+
+		byte[] K=KDF2(sha,VZ,P1,EFS);
+
+		for (i=0;i<EAS;i++) {K1[i]=K[i]; K2[i]=K[EAS+i];} 
+
+		byte[] C=AES_CBC_IV0_ENCRYPT(K1,M);
+
+		byte[] L2=inttoBytes(P2.length,8);	
+	
+		byte[] AC=new byte[C.length+P2.length+8];
+		for (i=0;i<C.length;i++) AC[i]=C[i];
+		for (i=0;i<P2.length;i++) AC[C.length+i]=P2[i];
+		for (i=0;i<8;i++) AC[C.length+P2.length+i]=L2[i];
+	
+		HMAC(sha,AC,K2,T);
+
+		return C;
+	}
+
+/* IEEE1363 ECIES decryption. Decryption of ciphertext V,C,T using private key U outputs plaintext M */
+	public static byte[] ECIES_DECRYPT(int sha,byte[] P1,byte[] P2,byte[] V,byte[] C,byte[] T,byte[] U)
+	{ 
+
+		int i,len;
+
+		byte[] Z=new byte[EFS];
+		byte[] VZ=new byte[3*EFS+1];
+		byte[] K1=new byte[EAS];
+		byte[] K2=new byte[EAS];
+		byte[] TAG=new byte[T.length];
+
+		if (ECPSVDP_DH(U,V,Z)!=0) return new byte[0];  
+
+		for (i=0;i<2*EFS+1;i++) VZ[i]=V[i];
+		for (i=0;i<EFS;i++) VZ[2*EFS+1+i]=Z[i];
+
+		byte[] K=KDF2(sha,VZ,P1,EFS);
+
+		for (i=0;i<EAS;i++) {K1[i]=K[i]; K2[i]=K[EAS+i];} 
+
+		byte[] M=AES_CBC_IV0_DECRYPT(K1,C); 
+
+		if (M.length==0) return M;
+
+		byte[] L2=inttoBytes(P2.length,8);	
+	
+		byte[] AC=new byte[C.length+P2.length+8];
+
+		for (i=0;i<C.length;i++) AC[i]=C[i];
+		for (i=0;i<P2.length;i++) AC[C.length+i]=P2[i];
+		for (i=0;i<8;i++) AC[C.length+P2.length+i]=L2[i];
+	
+		HMAC(sha,AC,K2,TAG);
+
+		boolean same=true;
+		for (i=0;i<T.length;i++) if (T[i]!=TAG[i]) same=false;
+		if (!same) return new byte[0];
+	
+		return M;
+
+	}
+}
diff --git a/version22/java/ECP.java b/version22/java/ECP.java
new file mode 100644
index 0000000..d315e45
--- /dev/null
+++ b/version22/java/ECP.java
@@ -0,0 +1,917 @@
+/*
+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.
+*/
+
+/* Elliptic Curve Point class */
+
+public final class ECP {
+	private FP x;
+	private FP y;
+	private FP z;
+	private boolean INF;
+
+/* Constructor - set to O */
+	public ECP() {
+		INF=true;
+		x=new FP(0);
+		y=new FP(1);
+		z=new FP(1);
+	}
+/* test for O point-at-infinity */
+	public boolean is_infinity() {
+		if (ROM.CURVETYPE==ROM.EDWARDS)
+		{
+			x.reduce(); y.reduce(); z.reduce();
+			return (x.iszilch() && y.equals(z));
+		}
+		else return INF;
+	}
+/* Conditional swap of P and Q dependant on d */
+	private void cswap(ECP Q,int d)
+	{
+		x.cswap(Q.x,d);
+		if (ROM.CURVETYPE!=ROM.MONTGOMERY) y.cswap(Q.y,d);
+		z.cswap(Q.z,d);
+		if (ROM.CURVETYPE!=ROM.EDWARDS)
+		{
+			boolean bd;
+			if (d==0) bd=false;
+			else bd=true;
+			bd=bd&(INF^Q.INF);
+			INF^=bd;
+			Q.INF^=bd;
+		}
+	}
+
+/* Conditional move of Q to P dependant on d */
+	private void cmove(ECP Q,int d)
+	{
+		x.cmove(Q.x,d);
+		if (ROM.CURVETYPE!=ROM.MONTGOMERY) y.cmove(Q.y,d);
+		z.cmove(Q.z,d);
+		if (ROM.CURVETYPE!=ROM.EDWARDS)
+		{
+			boolean bd;
+			if (d==0) bd=false;
+			else bd=true;
+			INF^=(INF^Q.INF)&bd;
+		}
+	}
+
+/* return 1 if b==c, no branching */
+	private static int teq(int b,int c)
+	{
+		int x=b^c;
+		x-=1;  // if x=0, x now -1
+		return ((x>>31)&1);
+	}
+
+/* Constant time select from pre-computed table */
+	private void select(ECP W[],int b)
+	{
+		ECP MP=new ECP(); 
+		int m=b>>31;
+		int babs=(b^m)-m;
+
+		babs=(babs-1)/2;
+
+		cmove(W[0],teq(babs,0));  // conditional move
+		cmove(W[1],teq(babs,1));
+		cmove(W[2],teq(babs,2));
+		cmove(W[3],teq(babs,3));
+		cmove(W[4],teq(babs,4));
+		cmove(W[5],teq(babs,5));
+		cmove(W[6],teq(babs,6));
+		cmove(W[7],teq(babs,7));
+ 
+		MP.copy(this);
+		MP.neg();
+		cmove(MP,(int)(m&1));
+	}
+
+/* Test P == Q */
+	public boolean equals(ECP Q) {
+		if (is_infinity() && Q.is_infinity()) return true;
+		if (is_infinity() || Q.is_infinity()) return false;
+		if (ROM.CURVETYPE==ROM.WEIERSTRASS)
+		{
+			FP zs2=new FP(z); zs2.sqr();
+			FP zo2=new FP(Q.z); zo2.sqr();
+			FP zs3=new FP(zs2); zs3.mul(z);
+			FP zo3=new FP(zo2); zo3.mul(Q.z);
+			zs2.mul(Q.x);
+			zo2.mul(x);
+			if (!zs2.equals(zo2)) return false;
+			zs3.mul(Q.y);
+			zo3.mul(y);
+			if (!zs3.equals(zo3)) return false;
+		}
+		else
+		{
+			FP a=new FP(0);
+			FP b=new FP(0);
+			a.copy(x); a.mul(Q.z); a.reduce();
+			b.copy(Q.x); b.mul(z); b.reduce();
+			if (!a.equals(b)) return false;
+			if (ROM.CURVETYPE==ROM.EDWARDS)
+			{
+				a.copy(y); a.mul(Q.z); a.reduce();
+				b.copy(Q.y); b.mul(z); b.reduce();
+				if (!a.equals(b)) return false;
+			}
+		}
+		return true;
+	}
+
+/* this=P */
+	public void copy(ECP P)
+	{
+		x.copy(P.x);
+		if (ROM.CURVETYPE!=ROM.MONTGOMERY) y.copy(P.y);
+		z.copy(P.z);
+		INF=P.INF;
+	}
+/* this=-this */
+	public void neg() {
+		if (is_infinity()) return;
+		if (ROM.CURVETYPE==ROM.WEIERSTRASS)
+		{
+			y.neg(); y.norm();
+		}
+		if (ROM.CURVETYPE==ROM.EDWARDS)
+		{
+			x.neg(); x.norm();
+		}
+		return;
+	}
+/* set this=O */
+	public void inf() {
+		INF=true;
+		x.zero();
+		y.one();
+		z.one();
+	//	y=new FP(1);
+	//	z=new FP(1);
+	}
+
+/* Calculate RHS of curve equation */
+	public static FP RHS(FP x) {
+		x.norm();
+		FP r=new FP(x);
+		r.sqr();
+
+		if (ROM.CURVETYPE==ROM.WEIERSTRASS)
+		{ // x^3+Ax+B
+			FP b=new FP(new BIG(ROM.CURVE_B));
+			r.mul(x);
+			if (ROM.CURVE_A==-3)
+			{
+				FP cx=new FP(x);
+				cx.imul(3);
+				cx.neg(); cx.norm();
+				r.add(cx);
+			}
+			r.add(b);
+		}
+		if (ROM.CURVETYPE==ROM.EDWARDS)
+		{ // (Ax^2-1)/(Bx^2-1) 
+			FP b=new FP(new BIG(ROM.CURVE_B));
+
+			FP one=new FP(1);
+			b.mul(r);
+			b.sub(one);
+			if (ROM.CURVE_A==-1) r.neg();
+			r.sub(one);
+
+			b.inverse();
+
+			r.mul(b);
+		}
+		if (ROM.CURVETYPE==ROM.MONTGOMERY)
+		{ // x^3+Ax^2+x
+			FP x3=new FP(0);
+			x3.copy(r);
+			x3.mul(x);
+			r.imul(ROM.CURVE_A);
+			r.add(x3);
+			r.add(x);
+		}
+		r.reduce();
+		return r;
+	}
+
+/* set (x,y) from two BIGs */
+	public ECP(BIG ix,BIG iy) {
+		x=new FP(ix);
+		y=new FP(iy);
+		z=new FP(1);
+		FP rhs=RHS(x);
+
+		if (ROM.CURVETYPE==ROM.MONTGOMERY)
+		{
+			if (rhs.jacobi()==1) INF=false;
+			else inf();
+		}
+		else
+		{
+			FP y2=new FP(y);
+			y2.sqr();
+			if (y2.equals(rhs)) INF=false;
+			else inf();
+		}
+	}
+/* set (x,y) from BIG and a bit */
+	public ECP(BIG ix,int s) {
+		x=new FP(ix);
+		FP rhs=RHS(x);
+		y=new FP(0);
+		z=new FP(1);
+		if (rhs.jacobi()==1)
+		{
+			FP ny=rhs.sqrt();
+			if (ny.redc().parity()!=s) ny.neg();
+			y.copy(ny);
+			INF=false;
+		}
+		else inf();
+	}
+
+/* set from x - calculate y from curve equation */
+	public ECP(BIG ix) {
+		x=new FP(ix);
+		FP rhs=RHS(x);
+		y=new FP(0);
+		z=new FP(1);
+		if (rhs.jacobi()==1)
+		{
+			if (ROM.CURVETYPE!=ROM.MONTGOMERY) y.copy(rhs.sqrt());
+			INF=false;
+		}
+		else INF=true;
+	}
+
+/* set to affine - from (x,y,z) to (x,y) */
+	public void affine() {
+		if (is_infinity()) return;
+		FP one=new FP(1);
+		if (z.equals(one)) return;
+		z.inverse();
+		if (ROM.CURVETYPE==ROM.WEIERSTRASS)
+		{
+			FP z2=new FP(z);
+			z2.sqr();
+			x.mul(z2); x.reduce();
+			y.mul(z2); 
+			y.mul(z);  y.reduce();
+		}
+		if (ROM.CURVETYPE==ROM.EDWARDS)
+		{
+			x.mul(z); x.reduce();
+			y.mul(z); y.reduce();
+		}
+		if (ROM.CURVETYPE==ROM.MONTGOMERY)
+		{
+			x.mul(z); x.reduce();
+		}
+		z.copy(one);
+	}
+/* extract x as a BIG */
+	public BIG getX()
+	{
+		affine();
+		return x.redc();
+	}
+/* extract y as a BIG */
+	public BIG getY()
+	{
+		affine();
+		return y.redc();
+	}
+
+/* get sign of Y */
+	public int getS()
+	{
+		affine();
+		BIG y=getY();
+		return y.parity();
+	}
+/* extract x as an FP */
+	public FP getx()
+	{
+		return x;
+	}
+/* extract y as an FP */
+	public FP gety()
+	{
+		return y;
+	}
+/* extract z as an FP */
+	public FP getz()
+	{
+		return z;
+	}
+/* convert to byte array */
+	public void toBytes(byte[] b)
+	{
+		byte[] t=new byte[ROM.MODBYTES];
+		if (ROM.CURVETYPE!=ROM.MONTGOMERY) b[0]=0x04;
+		else b[0]=0x02;
+	
+		affine();
+		x.redc().toBytes(t);
+		for (int i=0;i<ROM.MODBYTES;i++) b[i+1]=t[i];
+		if (ROM.CURVETYPE!=ROM.MONTGOMERY)
+		{
+			y.redc().toBytes(t);
+			for (int i=0;i<ROM.MODBYTES;i++) b[i+ROM.MODBYTES+1]=t[i];
+		}
+	}
+/* convert from byte array to point */
+	public static ECP fromBytes(byte[] b)
+	{
+		byte[] t=new byte[ROM.MODBYTES];
+		BIG p=new BIG(ROM.Modulus);
+
+		for (int i=0;i<ROM.MODBYTES;i++) t[i]=b[i+1];
+		BIG px=BIG.fromBytes(t);
+		if (BIG.comp(px,p)>=0) return new ECP();
+
+		if (b[0]==0x04)
+		{
+			for (int i=0;i<ROM.MODBYTES;i++) t[i]=b[i+ROM.MODBYTES+1];
+			BIG py=BIG.fromBytes(t);
+			if (BIG.comp(py,p)>=0) return new ECP();
+			return new ECP(px,py);
+		}
+		else return new ECP(px);
+	}
+/* convert to hex string */
+	public String toString() {
+		if (is_infinity()) return "infinity";
+		affine();
+		if (ROM.CURVETYPE==ROM.MONTGOMERY) return "("+x.redc().toString()+")";
+		else return "("+x.redc().toString()+","+y.redc().toString()+")";
+	}
+/* this*=2 */
+	public void dbl() {
+		if (ROM.CURVETYPE==ROM.WEIERSTRASS)
+		{
+			if (INF) return;
+			if (y.iszilch())
+			{
+				inf();
+				return;
+			}
+
+			FP w1=new FP(x);
+			FP w6=new FP(z);
+			FP w2=new FP(0);
+			FP w3=new FP(x);
+			FP w8=new FP(x);
+
+			if (ROM.CURVE_A==-3)
+			{
+				w6.sqr();
+				w1.copy(w6);
+				w1.neg();
+				w3.add(w1);
+				w8.add(w6);
+				w3.mul(w8);
+				w8.copy(w3);
+				w8.imul(3);
+			}
+			else
+			{
+				w1.sqr();
+				w8.copy(w1);
+				w8.imul(3);
+			}
+
+			w2.copy(y); w2.sqr();
+			w3.copy(x); w3.mul(w2);
+			w3.imul(4);
+			w1.copy(w3); w1.neg();
+			w1.norm();
+
+			x.copy(w8); x.sqr();
+			x.add(w1);
+			x.add(w1);
+			x.norm();
+
+			z.mul(y);
+			z.add(z);
+
+			w2.add(w2);
+			w2.sqr();
+			w2.add(w2);
+			w3.sub(x);
+			y.copy(w8); y.mul(w3);
+			y.sub(w2);
+			y.norm();
+			z.norm();
+		}
+		if (ROM.CURVETYPE==ROM.EDWARDS)
+		{
+			FP C=new FP(x);
+			FP D=new FP(y);
+			FP H=new FP(z);
+			FP J=new FP(0);
+	
+			x.mul(y); x.add(x);
+			C.sqr();
+			D.sqr();
+			if (ROM.CURVE_A==-1) C.neg();	
+			y.copy(C); y.add(D);
+			y.norm();
+			H.sqr(); H.add(H);
+			z.copy(y);
+			J.copy(y); J.sub(H);
+			x.mul(J);
+			C.sub(D);
+			y.mul(C);
+			z.mul(J);
+
+			x.norm();
+			y.norm();
+			z.norm();
+		}
+		if (ROM.CURVETYPE==ROM.MONTGOMERY)
+		{
+			FP A=new FP(x);
+			FP B=new FP(x);		
+			FP AA=new FP(0);
+			FP BB=new FP(0);
+			FP C=new FP(0);
+	
+			if (INF) return;
+
+			A.add(z);
+			AA.copy(A); AA.sqr();
+			B.sub(z);
+			BB.copy(B); BB.sqr();
+			C.copy(AA); C.sub(BB);
+
+			x.copy(AA); x.mul(BB);
+
+			A.copy(C); A.imul((ROM.CURVE_A+2)/4);
+
+			BB.add(A);
+			z.copy(BB); z.mul(C);
+			x.norm();
+			z.norm();
+		}
+		return;
+	}
+
+/* this+=Q */
+	public void add(ECP Q) {
+		if (ROM.CURVETYPE==ROM.WEIERSTRASS)
+		{
+			if (INF)
+			{
+				copy(Q);
+				return;
+			}
+			if (Q.INF) return;
+
+			boolean aff=false;
+
+			FP one=new FP(1);
+			if (Q.z.equals(one)) aff=true;
+
+			FP A,C;
+			FP B=new FP(z);
+			FP D=new FP(z);
+			if (!aff)
+			{
+				A=new FP(Q.z);
+				C=new FP(Q.z);
+
+				A.sqr(); B.sqr();
+				C.mul(A); D.mul(B);
+
+				A.mul(x);
+				C.mul(y);
+			}
+			else
+			{
+				A=new FP(x);
+				C=new FP(y);
+	
+				B.sqr();
+				D.mul(B);
+			}
+
+			B.mul(Q.x); B.sub(A);
+			D.mul(Q.y); D.sub(C);
+
+			if (B.iszilch())
+			{
+				if (D.iszilch())
+				{
+					dbl();
+					return;
+				}
+				else
+				{
+					INF=true;
+					return;
+				}
+			}
+
+			if (!aff) z.mul(Q.z);
+			z.mul(B);
+
+			FP e=new FP(B); e.sqr();
+			B.mul(e);
+			A.mul(e);
+
+			e.copy(A);
+			e.add(A); e.add(B);
+			x.copy(D); x.sqr(); x.sub(e);
+
+			A.sub(x);
+			y.copy(A); y.mul(D); 
+			C.mul(B); y.sub(C);
+
+			x.norm();
+			y.norm();
+			z.norm();
+		}
+		if (ROM.CURVETYPE==ROM.EDWARDS)
+		{
+			FP b=new FP(new BIG(ROM.CURVE_B));
+			FP A=new FP(z);
+			FP B=new FP(0);
+			FP C=new FP(x);
+			FP D=new FP(y);
+			FP E=new FP(0);
+			FP F=new FP(0);
+			FP G=new FP(0);
+		//	FP H=new FP(0);
+		//	FP I=new FP(0);
+	
+			A.mul(Q.z);
+			B.copy(A); B.sqr();
+			C.mul(Q.x);
+			D.mul(Q.y);
+
+			E.copy(C); E.mul(D); E.mul(b);
+			F.copy(B); F.sub(E); 
+			G.copy(B); G.add(E); 
+
+			if (ROM.CURVE_A==1)
+			{
+				E.copy(D); E.sub(C);
+			}
+			C.add(D);
+
+			B.copy(x); B.add(y);
+			D.copy(Q.x); D.add(Q.y); 
+			B.mul(D);
+			B.sub(C);
+			B.mul(F);
+			x.copy(A); x.mul(B);
+
+			if (ROM.CURVE_A==1)
+			{
+				C.copy(E); C.mul(G);
+			}
+			if (ROM.CURVE_A==-1)
+			{
+				C.mul(G);
+			}
+			y.copy(A); y.mul(C);
+			z.copy(F); z.mul(G);
+			x.norm(); y.norm(); z.norm();
+		}
+		return;
+	}
+
+/* Differential Add for Montgomery curves. this+=Q where W is this-Q and is affine. */
+	public void dadd(ECP Q,ECP W) {
+			FP A=new FP(x);
+			FP B=new FP(x);
+			FP C=new FP(Q.x);
+			FP D=new FP(Q.x);
+			FP DA=new FP(0);
+			FP CB=new FP(0);	
+			
+			A.add(z); 
+			B.sub(z); 
+
+			C.add(Q.z);
+			D.sub(Q.z);
+
+			DA.copy(D); DA.mul(A);
+			CB.copy(C); CB.mul(B);
+
+			A.copy(DA); A.add(CB); A.sqr();
+			B.copy(DA); B.sub(CB); B.sqr();
+
+			x.copy(A);
+			z.copy(W.x); z.mul(B);
+
+			if (z.iszilch()) inf();
+			else INF=false;
+
+			x.norm();
+	}
+/* this-=Q */
+	public void sub(ECP Q) {
+		Q.neg();
+		add(Q);
+		Q.neg();
+	}
+
+	public static void multiaffine(int m,ECP[] P)
+	{
+		int i;
+		FP t1=new FP(0);
+		FP t2=new FP(0);
+
+		FP[] work=new FP[m];
+
+		for (i=0;i<m;i++)
+			work[i]=new FP(0);
+	
+		work[0].one();
+		work[1].copy(P[0].z);
+
+		for (i=2;i<m;i++)
+		{
+			work[i].copy(work[i-1]);
+			work[i].mul(P[i-1].z);
+		}
+
+		t1.copy(work[m-1]);
+		t1.mul(P[m-1].z);
+		t1.inverse();
+		t2.copy(P[m-1].z);
+		work[m-1].mul(t1);
+
+		for (i=m-2;;i--)
+		{
+			if (i==0)
+			{
+				work[0].copy(t1);
+				work[0].mul(t2);
+				break;
+			}
+			work[i].mul(t2);
+			work[i].mul(t1);
+			t2.mul(P[i].z);
+		}
+/* now work[] contains inverses of all Z coordinates */
+
+		for (i=0;i<m;i++)
+		{
+			P[i].z.one();
+			t1.copy(work[i]);
+			t1.sqr();
+			P[i].x.mul(t1);
+			t1.mul(work[i]);
+			P[i].y.mul(t1);
+		}    
+	}
+
+/* constant time multiply by small integer of length bts - use ladder */
+	public ECP pinmul(int e,int bts) {	
+		if (ROM.CURVETYPE==ROM.MONTGOMERY)
+			return this.mul(new BIG(e));
+		else
+		{
+			int nb,i,b;
+			ECP P=new ECP();
+			ECP R0=new ECP();
+			ECP R1=new ECP(); R1.copy(this);
+
+			for (i=bts-1;i>=0;i--)
+			{
+				b=(e>>i)&1;
+				P.copy(R1);
+				P.add(R0);
+				R0.cswap(R1,b);
+				R1.copy(P);
+				R0.dbl();
+				R0.cswap(R1,b);
+			}
+			P.copy(R0);
+			P.affine();
+			return P;
+		}
+	}
+
+/* return e.this */
+
+	public ECP mul(BIG e) {
+		if (e.iszilch() || is_infinity()) return new ECP();
+		ECP P=new ECP();
+		if (ROM.CURVETYPE==ROM.MONTGOMERY)
+		{
+/* use Ladder */
+			int nb,i,b;
+			ECP D=new ECP();
+			ECP R0=new ECP(); R0.copy(this);
+			ECP R1=new ECP(); R1.copy(this);
+			R1.dbl();
+			D.copy(this); D.affine();
+			nb=e.nbits();
+			for (i=nb-2;i>=0;i--)
+			{
+				b=e.bit(i);
+				P.copy(R1);
+				P.dadd(R0,D);
+				R0.cswap(R1,b);
+				R1.copy(P);
+				R0.dbl();
+				R0.cswap(R1,b);
+			}
+			P.copy(R0);
+		}
+		else
+		{
+// fixed size windows 
+			int i,b,nb,m,s,ns;
+			BIG mt=new BIG();
+			BIG t=new BIG();
+			ECP Q=new ECP();
+			ECP C=new ECP();
+			ECP[] W=new ECP[8];
+			byte[] w=new byte[1+(ROM.NLEN*ROM.BASEBITS+3)/4];
+
+			affine();
+
+// precompute table 
+			Q.copy(this);
+			Q.dbl();
+			W[0]=new ECP();
+			W[0].copy(this);
+
+			for (i=1;i<8;i++)
+			{
+				W[i]=new ECP();
+				W[i].copy(W[i-1]);
+				W[i].add(Q);
+			}
+
+// convert the table to affine 
+			if (ROM.CURVETYPE==ROM.WEIERSTRASS) 
+				multiaffine(8,W);
+
+// make exponent odd - add 2P if even, P if odd 
+			t.copy(e);
+			s=t.parity();
+			t.inc(1); t.norm(); ns=t.parity(); mt.copy(t); mt.inc(1); mt.norm();
+			t.cmove(mt,s);
+			Q.cmove(this,ns);
+			C.copy(Q);
+
+			nb=1+(t.nbits()+3)/4;
+
+// convert exponent to signed 4-bit window 
+			for (i=0;i<nb;i++)
+			{
+				w[i]=(byte)(t.lastbits(5)-16);
+				t.dec(w[i]); t.norm();
+				t.fshr(4);	
+			}
+			w[nb]=(byte)t.lastbits(5);
+	
+			P.copy(W[(w[nb]-1)/2]);  
+			for (i=nb-1;i>=0;i--)
+			{
+				Q.select(W,w[i]);
+				P.dbl();
+				P.dbl();
+				P.dbl();
+				P.dbl();
+				P.add(Q);
+			}
+			P.sub(C); /* apply correction */
+		}
+		P.affine();
+		return P;
+	}
+
+/* Return e.this+f.Q */
+
+	public ECP mul2(BIG e,ECP Q,BIG f) {
+		BIG te=new BIG();
+		BIG tf=new BIG();
+		BIG mt=new BIG();
+		ECP S=new ECP();
+		ECP T=new ECP();
+		ECP C=new ECP();
+		ECP[] W=new ECP[8];
+		byte[] w=new byte[1+(ROM.NLEN*ROM.BASEBITS+1)/2];		
+		int i,s,ns,nb;
+		byte a,b;
+
+		affine();
+		Q.affine();
+
+		te.copy(e);
+		tf.copy(f);
+
+// precompute table 
+		W[1]=new ECP(); W[1].copy(this); W[1].sub(Q);
+		W[2]=new ECP(); W[2].copy(this); W[2].add(Q);
+		S.copy(Q); S.dbl();
+		W[0]=new ECP(); W[0].copy(W[1]); W[0].sub(S);
+		W[3]=new ECP(); W[3].copy(W[2]); W[3].add(S);
+		T.copy(this); T.dbl();
+		W[5]=new ECP(); W[5].copy(W[1]); W[5].add(T);
+		W[6]=new ECP(); W[6].copy(W[2]); W[6].add(T);
+		W[4]=new ECP(); W[4].copy(W[5]); W[4].sub(S);
+		W[7]=new ECP(); W[7].copy(W[6]); W[7].add(S);
+
+// convert the table to affine 
+		if (ROM.CURVETYPE==ROM.WEIERSTRASS) 
+			multiaffine(8,W);
+
+// if multiplier is odd, add 2, else add 1 to multiplier, and add 2P or P to correction 
+
+		s=te.parity();
+		te.inc(1); te.norm(); ns=te.parity(); mt.copy(te); mt.inc(1); mt.norm();
+		te.cmove(mt,s);
+		T.cmove(this,ns);
+		C.copy(T);
+
+		s=tf.parity();
+		tf.inc(1); tf.norm(); ns=tf.parity(); mt.copy(tf); mt.inc(1); mt.norm();
+		tf.cmove(mt,s);
+		S.cmove(Q,ns);
+		C.add(S);
+
+		mt.copy(te); mt.add(tf); mt.norm();
+		nb=1+(mt.nbits()+1)/2;
+
+// convert exponent to signed 2-bit window 
+		for (i=0;i<nb;i++)
+		{
+			a=(byte)(te.lastbits(3)-4);
+			te.dec(a); te.norm(); 
+			te.fshr(2);
+			b=(byte)(tf.lastbits(3)-4);
+			tf.dec(b); tf.norm(); 
+			tf.fshr(2);
+			w[i]=(byte)(4*a+b);
+		}
+		w[nb]=(byte)(4*te.lastbits(3)+tf.lastbits(3));
+		S.copy(W[(w[nb]-1)/2]);  
+
+		for (i=nb-1;i>=0;i--)
+		{
+			T.select(W,w[i]);
+			S.dbl();
+			S.dbl();
+			S.add(T);
+		}
+		S.sub(C); /* apply correction */
+		S.affine();
+		return S;
+	}
+
+/*
+	public static void main(String[] args) {
+
+		BIG Gx=new BIG(ROM.CURVE_Gx);
+		BIG Gy;
+		ECP P;
+		if (ROM.CURVETYPE!=ROM.MONTGOMERY) Gy=new BIG(ROM.CURVE_Gy);
+		BIG r=new BIG(ROM.CURVE_Order);
+
+		//r.dec(7);
+	
+		System.out.println("Gx= "+Gx.toString());		
+		if (ROM.CURVETYPE!=ROM.MONTGOMERY) System.out.println("Gy= "+Gy.toString());	
+
+		if (ROM.CURVETYPE!=ROM.MONTGOMERY) P=new ECP(Gx,Gy);
+		else  P=new ECP(Gx);
+
+		System.out.println("P= "+P.toString());		
+
+		ECP R=P.mul(r);
+		//for (int i=0;i<10000;i++)
+		//	R=P.mul(r);
+	
+		System.out.println("R= "+R.toString());
+    } */
+}
+
diff --git a/version22/java/ECP2.java b/version22/java/ECP2.java
new file mode 100644
index 0000000..ec9f674
--- /dev/null
+++ b/version22/java/ECP2.java
@@ -0,0 +1,624 @@
+/*
+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.
+*/
+
+/* AMCL Weierstrass elliptic curve functions over FP2 */
+
+public final class ECP2 {
+	private FP2 x;
+	private FP2 y;
+	private FP2 z;
+	private boolean INF;
+
+/* Constructor - set this=O */
+	public ECP2() {
+		INF=true;
+		x=new FP2(0);
+		y=new FP2(1);
+		z=new FP2(1);
+	}
+
+/* Test this=O? */
+	public boolean is_infinity() {
+		return INF;
+	}
+/* copy this=P */
+	public void copy(ECP2 P)
+	{
+		x.copy(P.x);
+		y.copy(P.y);
+		z.copy(P.z);
+		INF=P.INF;
+	}
+/* set this=O */
+	public void inf() {
+		INF=true;
+		x.zero();
+		y.zero();
+		z.zero();
+	}
+
+/* Conditional move of Q to P dependant on d */
+	public void cmove(ECP2 Q,int d)
+	{
+		x.cmove(Q.x,d);
+		y.cmove(Q.y,d);
+		z.cmove(Q.z,d);
+
+		boolean bd;
+		if (d==0) bd=false;
+		else bd=true;
+		INF^=(INF^Q.INF)&bd;
+	}
+
+/* return 1 if b==c, no branching */
+	public static int teq(int b,int c)
+	{
+		int x=b^c;
+		x-=1;  // if x=0, x now -1
+		return ((x>>31)&1);
+	}
+
+/* Constant time select from pre-computed table */
+	public void select(ECP2 W[],int b)
+	{
+		ECP2 MP=new ECP2(); 
+		int m=b>>31;
+		int babs=(b^m)-m;
+
+		babs=(babs-1)/2;
+
+		cmove(W[0],teq(babs,0));  // conditional move
+		cmove(W[1],teq(babs,1));
+		cmove(W[2],teq(babs,2));
+		cmove(W[3],teq(babs,3));
+		cmove(W[4],teq(babs,4));
+		cmove(W[5],teq(babs,5));
+		cmove(W[6],teq(babs,6));
+		cmove(W[7],teq(babs,7));
+ 
+		MP.copy(this);
+		MP.neg();
+		cmove(MP,(int)(m&1));
+	}
+
+/* Test if P == Q */
+	public boolean equals(ECP2 Q) {
+		if (is_infinity() && Q.is_infinity()) return true;
+		if (is_infinity() || Q.is_infinity()) return false;
+
+		FP2 zs2=new FP2(z); zs2.sqr();
+		FP2 zo2=new FP2(Q.z); zo2.sqr();
+		FP2 zs3=new FP2(zs2); zs3.mul(z);
+		FP2 zo3=new FP2(zo2); zo3.mul(Q.z);
+		zs2.mul(Q.x);
+		zo2.mul(x);
+		if (!zs2.equals(zo2)) return false;
+		zs3.mul(Q.y);
+		zo3.mul(y);
+		if (!zs3.equals(zo3)) return false;
+
+		return true;
+	}
+/* set this=-this */
+	public void neg() {
+		if (is_infinity()) return;
+		y.neg(); y.norm();
+		return;
+	}
+/* set to Affine - (x,y,z) to (x,y) */
+	public void affine() {
+		if (is_infinity()) return;
+		FP2 one=new FP2(1);
+		if (z.equals(one)) return;
+		z.inverse();
+
+		FP2 z2=new FP2(z);
+		z2.sqr();
+		x.mul(z2); x.reduce();
+		y.mul(z2); 
+		y.mul(z);  y.reduce();
+		z.copy(one);
+	}
+/* extract affine x as FP2 */
+	public FP2 getX()
+	{
+		affine();
+		return x;
+	}
+/* extract affine y as FP2 */
+	public FP2 getY()
+	{
+		affine();
+		return y;
+	}
+/* extract projective x */
+	public FP2 getx()
+	{
+		return x;
+	}
+/* extract projective y */
+	public FP2 gety()
+	{
+		return y;
+	}
+/* extract projective z */
+	public FP2 getz()
+	{
+		return z;
+	}
+/* convert to byte array */
+	public void toBytes(byte[] b)
+	{
+		byte[] t=new byte[ROM.MODBYTES];
+		affine();
+		x.getA().toBytes(t);
+		for (int i=0;i<ROM.MODBYTES;i++)
+			b[i]=t[i];
+		x.getB().toBytes(t);
+		for (int i=0;i<ROM.MODBYTES;i++)
+			b[i+ROM.MODBYTES]=t[i];
+
+		y.getA().toBytes(t);
+		for (int i=0;i<ROM.MODBYTES;i++)
+			b[i+2*ROM.MODBYTES]=t[i];
+		y.getB().toBytes(t);
+		for (int i=0;i<ROM.MODBYTES;i++)
+			b[i+3*ROM.MODBYTES]=t[i];
+	}
+/* convert from byte array to point */
+	public static ECP2 fromBytes(byte[] b)
+	{
+		byte[] t=new byte[ROM.MODBYTES];
+		BIG ra;
+		BIG rb;
+
+		for (int i=0;i<ROM.MODBYTES;i++) t[i]=b[i];
+		ra=BIG.fromBytes(t);
+		for (int i=0;i<ROM.MODBYTES;i++) t[i]=b[i+ROM.MODBYTES];
+		rb=BIG.fromBytes(t);
+		FP2 rx=new FP2(ra,rb);
+
+		for (int i=0;i<ROM.MODBYTES;i++) t[i]=b[i+2*ROM.MODBYTES];
+		ra=BIG.fromBytes(t);
+		for (int i=0;i<ROM.MODBYTES;i++) t[i]=b[i+3*ROM.MODBYTES];
+		rb=BIG.fromBytes(t);
+		FP2 ry=new FP2(ra,rb);
+
+		return new ECP2(rx,ry);
+	}
+/* convert this to hex string */
+	public String toString() {
+		if (is_infinity()) return "infinity";
+		affine();
+		return "("+x.toString()+","+y.toString()+")";
+	}
+
+/* Calculate RHS of twisted curve equation x^3+B/i */
+	public static FP2 RHS(FP2 x) {
+		x.norm();
+		FP2 r=new FP2(x);
+		r.sqr();
+		FP2 b=new FP2(new BIG(ROM.CURVE_B));
+		b.div_ip();
+		r.mul(x);
+		r.add(b);
+
+		r.reduce();
+		return r;
+	}
+
+/* construct this from (x,y) - but set to O if not on curve */
+	public ECP2(FP2 ix,FP2 iy) {
+		x=new FP2(ix);
+		y=new FP2(iy);
+		z=new FP2(1);
+		FP2 rhs=RHS(x);
+		FP2 y2=new FP2(y);
+		y2.sqr();
+		if (y2.equals(rhs)) INF=false;
+		else {x.zero();INF=true;}
+	}
+
+/* construct this from x - but set to O if not on curve */
+	public ECP2(FP2 ix) {
+		x=new FP2(ix);
+		y=new FP2(1);
+		z=new FP2(1);
+		FP2 rhs=RHS(x);
+		if (rhs.sqrt()) 
+		{
+			y.copy(rhs);
+			INF=false;
+		}
+		else {x.zero();INF=true;}
+	}
+
+/* this+=this */
+	public int dbl() {
+		if (INF) return -1;
+		if (y.iszilch())
+		{
+			inf();
+			return -1;
+		}
+
+		FP2 w1=new FP2(x);
+		FP2 w2=new FP2(0);
+		FP2 w3=new FP2(x);
+		FP2 w8=new FP2(x);
+
+		w1.sqr();
+		w8.copy(w1);
+		w8.imul(3);
+
+		w2.copy(y); w2.sqr();
+		w3.copy(x); w3.mul(w2);
+		w3.imul(4);
+		w1.copy(w3); w1.neg();
+		w1.norm();
+
+		x.copy(w8); x.sqr();
+		x.add(w1);
+		x.add(w1);
+		x.norm();
+
+		z.mul(y);
+		z.add(z);
+
+		w2.add(w2);
+		w2.sqr();
+		w2.add(w2);
+		w3.sub(x);
+		y.copy(w8); y.mul(w3);
+	//	w2.norm();
+		y.sub(w2);
+
+		y.norm();
+		z.norm();
+
+		return 1;
+	}
+
+/* this+=Q - return 0 for add, 1 for double, -1 for O */
+	public int add(ECP2 Q) {
+		if (INF)
+		{
+			copy(Q);
+			return -1;
+		}
+		if (Q.INF) return -1;
+
+		boolean aff=false;
+
+		if (Q.z.isunity()) aff=true;
+
+		FP2 A,C;
+		FP2 B=new FP2(z);
+		FP2 D=new FP2(z);
+		if (!aff)
+		{
+			A=new FP2(Q.z);
+			C=new FP2(Q.z);
+
+			A.sqr(); B.sqr();
+			C.mul(A); D.mul(B);
+
+			A.mul(x);
+			C.mul(y);
+		}
+		else
+		{
+			A=new FP2(x);
+			C=new FP2(y);
+	
+			B.sqr();
+			D.mul(B);
+		}
+
+		B.mul(Q.x); B.sub(A);
+		D.mul(Q.y); D.sub(C);
+
+		if (B.iszilch())
+		{
+			if (D.iszilch())
+			{
+				dbl();
+				return 1;
+			}
+			else
+			{
+				INF=true;
+				return -1;
+			}
+		}
+
+		if (!aff) z.mul(Q.z);
+		z.mul(B);
+
+		FP2 e=new FP2(B); e.sqr();
+		B.mul(e);
+		A.mul(e);
+
+		e.copy(A);
+		e.add(A); e.add(B);
+		x.copy(D); x.sqr(); x.sub(e);
+
+		A.sub(x);
+		y.copy(A); y.mul(D); 
+		C.mul(B); y.sub(C);
+
+		x.norm();
+		y.norm();
+		z.norm();
+
+		return 0;
+	}
+
+/* set this-=Q */
+	public int sub(ECP2 Q) {
+		Q.neg();
+		int D=add(Q);
+		Q.neg();
+		return D;
+	}
+/* set this*=q, where q is Modulus, using Frobenius */
+	public void frob(FP2 X)
+	{
+		if (INF) return;
+		FP2 X2=new FP2(X);
+		X2.sqr();
+		x.conj();
+		y.conj();
+		z.conj();
+		z.reduce();
+		x.mul(X2);
+		y.mul(X2);
+		y.mul(X);
+	}
+
+/* normalises m-array of ECP2 points. Requires work vector of m FP2s */
+
+	public static void multiaffine(int m,ECP2[] P)
+	{
+		int i;
+		FP2 t1=new FP2(0);
+		FP2 t2=new FP2(0);
+
+		FP2[] work=new FP2[m];
+		work[0]=new FP2(1);
+		work[1]=new FP2(P[0].z);
+		for (i=2;i<m;i++)
+		{
+			work[i]=new FP2(work[i-1]);
+			work[i].mul(P[i-1].z);
+		}
+
+		t1.copy(work[m-1]); t1.mul(P[m-1].z);
+
+		t1.inverse();
+
+		t2.copy(P[m-1].z);
+		work[m-1].mul(t1);
+
+		for (i=m-2;;i--)
+		{
+			if (i==0)
+			{
+				work[0].copy(t1);
+				work[0].mul(t2);
+				break;
+			}
+			work[i].mul(t2);
+			work[i].mul(t1);
+			t2.mul(P[i].z);
+		}
+/* now work[] contains inverses of all Z coordinates */
+
+		for (i=0;i<m;i++)
+		{
+			P[i].z.one();
+			t1.copy(work[i]); t1.sqr();
+			P[i].x.mul(t1);
+			t1.mul(work[i]);
+			P[i].y.mul(t1);
+		}    
+	}
+
+/* P*=e */
+	public ECP2 mul(BIG e)
+	{
+/* fixed size windows */
+		int i,b,nb,m,s,ns;
+		BIG mt=new BIG();
+		BIG t=new BIG();
+		ECP2 P=new ECP2();
+		ECP2 Q=new ECP2();
+		ECP2 C=new ECP2();
+		ECP2[] W=new ECP2[8];
+		byte[] w=new byte[1+(ROM.NLEN*ROM.BASEBITS+3)/4];
+
+		if (is_infinity()) return new ECP2();
+
+		affine();
+
+/* precompute table */
+		Q.copy(this);
+		Q.dbl();
+		W[0]=new ECP2();
+		W[0].copy(this);
+
+		for (i=1;i<8;i++)
+		{
+			W[i]=new ECP2();
+			W[i].copy(W[i-1]);
+			W[i].add(Q);
+		}
+
+/* convert the table to affine */
+
+		multiaffine(8,W);
+
+/* make exponent odd - add 2P if even, P if odd */
+		t.copy(e);
+		s=t.parity();
+		t.inc(1); t.norm(); ns=t.parity(); mt.copy(t); mt.inc(1); mt.norm();
+		t.cmove(mt,s);
+		Q.cmove(this,ns);
+		C.copy(Q);
+
+		nb=1+(t.nbits()+3)/4;
+/* convert exponent to signed 4-bit window */
+		for (i=0;i<nb;i++)
+		{
+			w[i]=(byte)(t.lastbits(5)-16);
+			t.dec(w[i]); t.norm();
+			t.fshr(4);	
+		}
+		w[nb]=(byte)t.lastbits(5);
+	
+		P.copy(W[(w[nb]-1)/2]);  
+		for (i=nb-1;i>=0;i--)
+		{
+			Q.select(W,w[i]);
+			P.dbl();
+			P.dbl();
+			P.dbl();
+			P.dbl();
+			P.add(Q);
+		}
+		P.sub(C);
+		P.affine();
+		return P;
+	}
+
+/* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3 */
+	public static ECP2 mul4(ECP2[] Q,BIG[] u)
+	{
+		int i,j,nb;
+		int[] a=new int[4];
+		ECP2 T=new ECP2();
+		ECP2 C=new ECP2();
+		ECP2 P=new ECP2();
+		ECP2[] W=new ECP2[8];
+
+		BIG mt=new BIG();
+		BIG[] t=new BIG[4];
+
+		byte[] w=new byte[ROM.NLEN*ROM.BASEBITS+1];
+
+		for (i=0;i<4;i++)
+		{
+			t[i]=new BIG(u[i]);
+			Q[i].affine();
+		}
+
+/* precompute table */
+
+		W[0]=new ECP2(); W[0].copy(Q[0]); W[0].sub(Q[1]);
+		W[1]=new ECP2(); W[1].copy(W[0]);
+		W[2]=new ECP2(); W[2].copy(W[0]);
+		W[3]=new ECP2(); W[3].copy(W[0]);
+		W[4]=new ECP2(); W[4].copy(Q[0]); W[4].add(Q[1]);
+		W[5]=new ECP2(); W[5].copy(W[4]);
+		W[6]=new ECP2(); W[6].copy(W[4]);
+		W[7]=new ECP2(); W[7].copy(W[4]);
+		T.copy(Q[2]); T.sub(Q[3]);
+		W[1].sub(T);
+		W[2].add(T);
+		W[5].sub(T);
+		W[6].add(T);
+		T.copy(Q[2]); T.add(Q[3]);
+		W[0].sub(T);
+		W[3].add(T);
+		W[4].sub(T);
+		W[7].add(T);
+
+		multiaffine(8,W);
+
+/* if multiplier is even add 1 to multiplier, and add P to correction */
+		mt.zero(); C.inf();
+		for (i=0;i<4;i++)
+		{
+			if (t[i].parity()==0)
+			{
+				t[i].inc(1); t[i].norm();
+				C.add(Q[i]);
+			}
+			mt.add(t[i]); mt.norm();
+		}
+
+		nb=1+mt.nbits();
+
+/* convert exponent to signed 1-bit window */
+		for (j=0;j<nb;j++)
+		{
+			for (i=0;i<4;i++)
+			{
+				a[i]=(byte)(t[i].lastbits(2)-2);
+				t[i].dec(a[i]); t[i].norm(); 
+				t[i].fshr(1);
+			}
+			w[j]=(byte)(8*a[0]+4*a[1]+2*a[2]+a[3]);
+		}
+		w[nb]=(byte)(8*t[0].lastbits(2)+4*t[1].lastbits(2)+2*t[2].lastbits(2)+t[3].lastbits(2));
+
+		P.copy(W[(w[nb]-1)/2]);  
+		for (i=nb-1;i>=0;i--)
+		{
+			T.select(W,w[i]);
+			P.dbl();
+			P.add(T);
+		}
+		P.sub(C); /* apply correction */
+
+		P.affine();
+		return P;
+	}
+
+/*
+	public static void main(String[] args) {
+		BIG r=new BIG(ROM.Modulus);
+
+		BIG Pxa=new BIG(ROM.CURVE_Pxa);
+		BIG Pxb=new BIG(ROM.CURVE_Pxb);
+		BIG Pya=new BIG(ROM.CURVE_Pya);
+		BIG Pyb=new BIG(ROM.CURVE_Pyb);
+
+		BIG Fra=new BIG(ROM.CURVE_Fra);
+		BIG Frb=new BIG(ROM.CURVE_Frb);
+
+		FP2 f=new FP2(Fra,Frb);
+
+		FP2 Px=new FP2(Pxa,Pxb);
+		FP2 Py=new FP2(Pya,Pyb);
+
+		ECP2 P=new ECP2(Px,Py);
+
+		System.out.println("P= "+P.toString());
+
+		P=P.mul(r);
+		System.out.println("P= "+P.toString());
+
+		ECP2 Q=new ECP2(Px,Py);
+		Q.frob(f);
+		System.out.println("Q= "+Q.toString());
+	} */
+
+
+}
\ No newline at end of file
diff --git a/version22/java/FF.java b/version22/java/FF.java
new file mode 100644
index 0000000..a6ee1fe
--- /dev/null
+++ b/version22/java/FF.java
@@ -0,0 +1,941 @@
+/*
+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.
+*/
+
+/* Large Finite Field arithmetic */
+/* AMCL mod p functions */
+
+public final class FF {
+	private final BIG[] v;
+	private final int length;
+
+/* Constructors */
+	public FF(int n)
+	{
+		v=new BIG[n];
+		for (int i=0;i<n;i++)
+			v[i]=new BIG(0);
+		length=n;
+	}
+
+	public int getlen()
+	{
+		return length;
+	}
+
+/* set to integer */
+	public void set(int m)
+	{
+		zero();
+		v[0].set(0,(m&ROM.BMASK));
+		v[0].set(1,(m>>ROM.BASEBITS));
+	}
+
+/* copy from FF b */
+	public void copy(FF b)
+	{
+		for (int i=0;i<length;i++)
+		{
+			v[i].copy(b.v[i]);
+		}
+	}
+
+/* x=y<<n */
+	public void dsucopy(FF b)
+	{
+		for (int i=0;i<b.length;i++)
+		{
+			v[b.length+i].copy(b.v[i]);
+			v[i].zero();
+		}
+	}
+
+/* x=y */
+	public void dscopy(FF b)
+	{
+		for (int i=0;i<b.length;i++)
+		{
+			v[i].copy(b.v[i]);
+			v[b.length+i].zero();
+		}
+	}
+
+/* x=y>>n */
+	public void sducopy(FF b)
+	{
+		for (int i=0;i<length;i++)
+		{
+			v[i].copy(b.v[length+i]);
+		}
+	}
+
+/* set to zero */
+	public void zero()
+	{
+		for (int i=0;i<length;i++)
+		{
+			v[i].zero();
+		}
+	}
+
+	public void one()
+	{
+		v[0].one();
+		for (int i=1;i<length;i++)
+		{
+			v[i].zero();
+		}
+	}
+
+/* test equals 0 */
+	public boolean iszilch() 
+	{
+		for (int i=0;i<length;i++)
+		{
+			if (!v[i].iszilch()) return false;
+		}
+		return true;
+	}
+
+/* shift right by BIGBITS-bit words */
+	public void shrw(int n)
+	{
+		for (int i=0;i<n;i++) 
+		{
+			v[i].copy(v[i+n]);
+			v[i+n].zero();
+		}
+	}
+
+/* shift left by BIGBITS-bit words */
+	public void shlw(int n)
+	{
+		for (int i=0;i<n;i++) 
+		{
+			v[n+i].copy(v[i]);
+			v[i].zero();
+		}
+	}
+
+/* extract last bit */
+	public int parity()
+	{
+		return v[0].parity();
+	}
+
+	public int lastbits(int m)
+	{
+		return v[0].lastbits(m);
+	}
+
+/* compare x and y - must be normalised, and of same length */
+	public static int comp(FF a,FF b)
+	{
+		int i,j;
+		for (i=a.length-1;i>=0;i--)
+		{
+			j=BIG.comp(a.v[i],b.v[i]);
+			if (j!=0) return j;
+		}
+		return 0;
+	}
+
+/* recursive add */
+	public void radd(int vp,FF x,int xp,FF y,int yp,int n)
+	{
+		for (int i=0;i<n;i++)
+		{
+			v[vp+i].copy(x.v[xp+i]);
+			v[vp+i].add(y.v[yp+i]);
+		}
+	}
+
+/* recursive inc */
+	public void rinc(int vp,FF y,int yp,int n)
+	{
+		for (int i=0;i<n;i++)
+		{
+			v[vp+i].add(y.v[yp+i]);
+		}
+	}
+
+/* recursive sub */
+	public void rsub(int vp,FF x,int xp,FF y,int yp,int n)
+	{
+		for (int i=0;i<n;i++)
+		{
+			v[vp+i].copy(x.v[xp+i]);
+			v[vp+i].sub(y.v[yp+i]);
+		}
+	}
+
+/* recursive dec */
+	public void rdec(int vp,FF y,int yp,int n)
+	{
+		for (int i=0;i<n;i++)
+		{
+			v[vp+i].sub(y.v[yp+i]);
+		}
+	}
+
+/* simple add */
+	public void add(FF b)
+	{
+		for (int i=0;i<length;i++)
+			v[i].add(b.v[i]);
+	}
+
+/* simple sub */
+	public void sub(FF b)
+	{
+		for (int i=0;i<length;i++)
+			v[i].sub(b.v[i]);
+	}
+	
+/* reverse sub */
+	public void revsub(FF b)
+	{
+		for (int i=0;i<length;i++)
+			v[i].rsub(b.v[i]);
+	}
+
+/* increment/decrement by a small integer */
+	public void inc(int m)
+	{
+		v[0].inc(m);
+		norm();
+	}
+
+	public void dec(int m)
+	{
+		v[0].dec(m);
+		norm();
+	}
+
+	/* normalise - but hold any overflow in top part unless n<0 */
+	private void rnorm(int vp,int n)
+	{
+		boolean trunc=false;
+		int i;
+		long carry;
+		if (n<0)
+		{ /* -v n signals to do truncation */
+			n=-n;
+			trunc=true;
+		}
+		for (i=0;i<n-1;i++)
+		{
+			carry=v[vp+i].norm();  
+			v[vp+i].xortop(carry<<ROM.P_TBITS);
+			v[vp+i+1].incl(carry);
+		}
+		carry=v[vp+n-1].norm();
+		if (trunc) 
+			v[vp+n-1].xortop(carry<<ROM.P_TBITS);
+	}
+
+	public void norm()
+	{
+		rnorm(0,length);
+	}
+
+/* shift left by one bit */
+	public void shl()
+	{
+		int i,carry,delay_carry=0;
+		for (i=0;i<length-1;i++)
+		{
+			carry=v[i].fshl(1);
+			v[i].inc(delay_carry);
+			v[i].xortop((long)carry<<ROM.P_TBITS);
+			delay_carry=carry;
+		}
+		v[length-1].fshl(1);
+		v[length-1].inc(delay_carry);
+	}
+
+/* shift right by one bit */
+
+	public void shr()
+	{
+		int carry;
+		for (int i=length-1;i>0;i--)
+		{
+			carry=v[i].fshr(1);
+			v[i-1].xortop((long)carry<<ROM.P_TBITS);
+		}
+		v[0].fshr(1);
+	}
+
+/* Convert to Hex String */
+	public String toString() 
+	{
+		norm();
+		String s="";
+		for (int i=length-1;i>=0;i--)
+		{
+			s+=v[i].toString(); //s+=" ";
+		}
+		return s;
+	}
+
+/*
+	public String toRawString(int len) 
+	{
+	//	norm(len);
+		String s="";
+		for (int i=len-1;i>=0;i--)
+		{
+			s+=v[i].toRawString(); s+=" ";
+		}
+		return s;
+	}
+*/
+/* Convert FFs to/from byte arrays */
+	public void toBytes(byte[] b)
+	{
+		for (int i=0;i<length;i++)
+		{
+			v[i].tobytearray(b,(length-i-1)*ROM.MODBYTES);
+		}
+	}
+
+	public static void fromBytes(FF x,byte[] b)
+	{
+		for (int i=0;i<x.length;i++)
+		{
+			x.v[i]=BIG.frombytearray(b,(x.length-i-1)*ROM.MODBYTES);
+		}
+	}
+
+/* in-place swapping using xor - side channel resistant - lengths must be the same */
+	private static void cswap(FF a,FF b,int d)
+	{
+		for (int i=0;i<a.length;i++)
+		{
+		//	BIG.cswap(a.v[i],b.v[i],d);
+			a.v[i].cswap(b.v[i],d);
+		}
+	}
+
+/* z=x*y, t is workspace */
+	private void karmul(int vp,FF x,int xp,FF y,int yp,FF t,int tp,int n)
+	{
+		int nd2;
+		if (n==1)
+		{
+			DBIG d=BIG.mul(x.v[xp],y.v[yp]);
+			v[vp+1]=d.split(8*ROM.MODBYTES);
+			v[vp].copy(d);
+			return;
+		}
+		nd2=n/2;
+		radd(vp,x,xp,x,xp+nd2,nd2);
+		rnorm(vp,nd2);                   /* Important - required for 32-bit build */
+		radd(vp+nd2,y,yp,y,yp+nd2,nd2);
+		rnorm(vp+nd2,nd2);               /* Important - required for 32-bit build */
+
+		t.karmul(tp,this,vp,this,vp+nd2,t,tp+n,nd2);
+		karmul(vp,x,xp,y,yp,t,tp+n,nd2);
+		karmul(vp+n,x,xp+nd2,y,yp+nd2,t,tp+n,nd2);
+		t.rdec(tp,this,vp,n);
+		t.rdec(tp,this,vp+n,n);
+		rinc(vp+nd2,t,tp,n);
+		rnorm(vp,2*n);
+	}
+
+	private void karsqr(int vp,FF x,int xp,FF t,int tp,int n)
+	{
+		int nd2;
+		if (n==1)
+		{
+			DBIG d=BIG.sqr(x.v[xp]);
+			v[vp+1].copy(d.split(8*ROM.MODBYTES));
+			v[vp].copy(d);
+			return;
+		}	
+
+		nd2=n/2;
+		karsqr(vp,x,xp,t,tp+n,nd2);
+		karsqr(vp+n,x,xp+nd2,t,tp+n,nd2);
+		t.karmul(tp,x,xp,x,xp+nd2,t,tp+n,nd2);
+		rinc(vp+nd2,t,tp,n);
+		rinc(vp+nd2,t,tp,n);
+		rnorm(vp+nd2,n);
+	}
+
+
+	private void karmul_lower(int vp,FF x,int xp,FF y,int yp,FF t,int tp,int n)
+	{ /* Calculates Least Significant bottom half of x*y */
+		int nd2;
+		if (n==1)
+		{ /* only calculate bottom half of product */
+			v[vp].copy(BIG.smul(x.v[xp],y.v[yp]));
+			return;
+		}
+		nd2=n/2;
+		karmul(vp,x,xp,y,yp,t,tp+n,nd2);
+		t.karmul_lower(tp,x,xp+nd2,y,yp,t,tp+n,nd2);
+		rinc(vp+nd2,t,tp,nd2);
+		t.karmul_lower(tp,x,xp,y,yp+nd2,t,tp+n,nd2);
+
+		rinc(vp+nd2,t,tp,nd2);
+		rnorm(vp+nd2,-nd2);  /* truncate it */
+	}
+
+	private void karmul_upper(FF x,FF y,FF t,int n)
+	{ /* Calculates Most Significant upper half of x*y, given lower part */
+		int nd2;
+ 
+		nd2=n/2;
+		radd(n,x,0,x,nd2,nd2);
+		radd(n+nd2,y,0,y,nd2,nd2);
+		rnorm(n,nd2);
+		rnorm(n+nd2,nd2);
+
+		t.karmul(0,this,n+nd2,this,n,t,n,nd2);  /* t = (a0+a1)(b0+b1) */
+		karmul(n,x,nd2,y,nd2,t,n,nd2); /* z[n]= a1*b1 */
+									/* z[0-nd2]=l(a0b0) z[nd2-n]= h(a0b0)+l(t)-l(a0b0)-l(a1b1) */
+		t.rdec(0,this,n,n);              /* t=t-a1b1  */
+		rinc(nd2,this,0,nd2);   /* z[nd2-n]+=l(a0b0) = h(a0b0)+l(t)-l(a1b1)  */
+		rdec(nd2,t,0,nd2);   /* z[nd2-n]=h(a0b0)+l(t)-l(a1b1)-l(t-a1b1)=h(a0b0) */
+		rnorm(0,-n);					/* a0b0 now in z - truncate it */
+		t.rdec(0,this,0,n);         /* (a0+a1)(b0+b1) - a0b0 */
+		rinc(nd2,t,0,n);
+
+		rnorm(nd2,n);
+	}
+
+	/* z=x*y. Assumes x and y are of same length. */
+	public static FF mul(FF x,FF y)
+	{
+		int n=x.length;
+		FF z=new FF(2*n);
+		FF t=new FF(2*n);
+//		x.norm(); y.norm();
+		z.karmul(0,x,0,y,0,t,0,n);
+		return z;
+	}
+
+	/* z=x^2 */
+	public static FF sqr(FF x)
+	{
+		int n=x.length;
+		FF z=new FF(2*n);
+		FF t=new FF(2*n);
+//		x.norm(); 
+		z.karsqr(0,x,0,t,0,n);
+		return z;
+	}
+
+/* return low part of product this*y */
+	public void lmul(FF y)
+	{
+		int n=length;
+		FF t=new FF(2*n);
+		FF x=new FF(n); x.copy(this);
+//		x.norm(); y.norm();
+		karmul_lower(0,x,0,y,0,t,0,n);
+	}
+
+/* Set b=b mod c */
+	public void mod(FF c)
+	{
+		int k=0;  
+
+		norm();
+		if (comp(this,c)<0) 
+			return;
+		do
+		{
+			c.shl();
+			k++;
+		} while (comp(this,c)>=0);
+
+		while (k>0)
+		{
+			c.shr();
+			if (comp(this,c)>=0)
+			{
+				sub(c);
+				norm();
+			}
+			k--;
+		}
+	}
+
+/* return This mod modulus, N is modulus, ND is Montgomery Constant */
+	public FF reduce(FF N,FF ND)
+	{ /* fast karatsuba Montgomery reduction */
+		int n=N.length;
+		FF t=new FF(2*n);
+		FF r=new FF(n);
+		FF m=new FF(n);
+
+		r.sducopy(this);
+		m.karmul_lower(0,this,0,ND,0,t,0,n);
+		karmul_upper(N,m,t,n);
+		m.sducopy(this);
+
+		r.add(N);
+		r.sub(m);
+		r.norm();
+
+		return r;
+	}
+
+/* Set r=this mod b */
+/* this is of length - 2*n */
+/* r,b is of length - n */
+	public FF dmod(FF b)
+	{
+		int k,n=b.length;
+		FF m=new FF(2*n);
+		FF x=new FF(2*n);
+		FF r=new FF(n);
+
+		x.copy(this);
+		x.norm();
+		m.dsucopy(b); k=ROM.BIGBITS*n;
+
+		while (comp(x,m)>=0)
+		{
+			x.sub(m);
+			x.norm();
+		}
+
+		while (k>0)
+		{	
+			m.shr();
+
+			if (comp(x,m)>=0)
+			{
+				x.sub(m);
+				x.norm();
+			}
+			k--;
+		}
+
+		r.copy(x);
+		r.mod(b);
+		return r;
+	}
+
+/* Set return=1/this mod p. Binary method - a<p on entry */
+
+	public void invmodp(FF p)
+	{
+		int n=p.length;
+
+		FF u=new FF(n);
+		FF v=new FF(n);
+		FF x1=new FF(n);
+		FF x2=new FF(n);
+		FF t=new FF(n);
+		FF one=new FF(n);
+
+		one.one();
+		u.copy(this);
+		v.copy(p);
+		x1.copy(one);
+		x2.zero();
+
+	// reduce n in here as well! 
+		while (comp(u,one)!=0 && comp(v,one)!=0)
+		{
+			while (u.parity()==0)
+			{
+				u.shr();
+				if (x1.parity()!=0)
+				{
+					x1.add(p); 
+					x1.norm();
+				}
+				x1.shr(); 
+			}
+			while (v.parity()==0)
+			{
+				v.shr(); 
+				if (x2.parity()!=0)
+				{
+					x2.add(p);
+					x2.norm();
+				}
+				x2.shr();
+			}
+			if (comp(u,v)>=0)
+			{
+
+				u.sub(v);
+				u.norm();
+				if (comp(x1,x2)>=0) x1.sub(x2);
+				else
+				{
+					t.copy(p);
+					t.sub(x2);
+					x1.add(t);
+				}
+				x1.norm();
+			}
+			else
+			{
+				v.sub(u);
+				v.norm();
+				if (comp(x2,x1)>=0) x2.sub(x1);
+				else
+				{
+					t.copy(p);
+					t.sub(x1);
+					x2.add(t);
+				}
+				x2.norm();
+			}
+		}
+		if (comp(u,one)==0)
+			copy(x1);
+		else
+			copy(x2);
+	}
+
+/* nresidue mod m */
+	public void nres(FF m)
+	{
+		int n=m.length;
+		FF d=new FF(2*n);
+		d.dsucopy(this);
+		copy(d.dmod(m));
+	}
+
+	public void redc(FF m,FF ND)
+	{
+		int n=m.length;
+		FF d=new FF(2*n);
+		mod(m);
+		d.dscopy(this);
+		copy(d.reduce(m,ND));
+		mod(m);
+	}
+
+	private void mod2m(int m)
+	{
+		for (int i=m;i<length;i++)
+			v[i].zero();
+	}
+
+	/* U=1/a mod 2^m - Arazi & Qi */
+	private FF invmod2m()
+	{
+		int i,n=length;
+
+		FF b=new FF(n);
+		FF c=new FF(n);
+		FF U=new FF(n);
+		FF t;
+
+		U.zero();
+		U.v[0].copy(v[0]);
+		U.v[0].invmod2m();
+
+		for (i=1;i<n;i<<=1)
+		{
+			b.copy(this); b.mod2m(i);
+			t=mul(U,b);
+
+			t.shrw(i); b.copy(t);
+			c.copy(this); c.shrw(i); c.mod2m(i);
+			c.lmul(U); c.mod2m(i);
+
+			b.add(c); b.norm();
+			b.lmul(U); b.mod2m(i);
+
+			c.one(); c.shlw(i); b.revsub(c); b.norm();
+			b.shlw(i);
+			U.add(b);
+		}
+		U.norm();
+		return U;
+	}
+
+	public void random(RAND rng)
+	{
+		int n=length;
+		for (int i=0;i<n;i++)
+		{
+			v[i].copy(BIG.random(rng));
+		}
+	/* make sure top bit is 1 */
+		while (v[n-1].nbits()<ROM.MODBYTES*8) v[n-1].copy(BIG.random(rng));
+	}
+
+	/* generate random x */
+	public void randomnum(FF p,RAND rng)
+	{
+		int n=length;
+		FF d=new FF(2*n);
+
+		for (int i=0;i<2*n;i++)
+		{
+			d.v[i].copy(BIG.random(rng));
+		}
+		copy(d.dmod(p));
+	}
+
+	/* this*=y mod p */
+	public void modmul(FF y,FF p,FF nd)
+	{
+		if (BIG.ff_pexceed(v[length-1],y.v[y.length-1])) mod(p);
+		FF d=mul(this,y);
+		copy(d.reduce(p,nd));
+	}
+
+	/* this*=y mod p */
+	public void modsqr(FF p,FF nd)
+	{
+		if (BIG.ff_sexceed(v[length-1])) mod(p);
+		FF d=sqr(this);
+		copy(d.reduce(p,nd));
+	}
+
+	/* this=this^e mod p using side-channel resistant Montgomery Ladder, for large e */
+	public void skpow(FF e,FF p)
+	{
+		int i,b,n=p.length;
+		FF R0=new FF(n);
+		FF R1=new FF(n);
+		FF ND=p.invmod2m();
+
+		mod(p);
+		R0.one();
+		R1.copy(this);
+		R0.nres(p);
+		R1.nres(p);
+
+		for (i=8*ROM.MODBYTES*n-1;i>=0;i--)
+		{
+			b=e.v[i/ROM.BIGBITS].bit(i%ROM.BIGBITS);
+			copy(R0);
+			modmul(R1,p,ND);
+
+			cswap(R0,R1,b);
+			R0.modsqr(p,ND);
+
+			R1.copy(this);
+			cswap(R0,R1,b);
+		}
+		copy(R0);
+		redc(p,ND);
+	}
+
+	/* this =this^e mod p using side-channel resistant Montgomery Ladder, for short e */
+	public void skpow(BIG e,FF p)
+	{
+		int i,b,n=p.length;
+		FF R0=new FF(n);
+		FF R1=new FF(n);
+		FF ND=p.invmod2m();
+
+		mod(p);
+		R0.one();
+		R1.copy(this);
+		R0.nres(p);
+		R1.nres(p);
+
+		for (i=8*ROM.MODBYTES-1;i>=0;i--)
+		{
+			b=e.bit(i);
+			copy(R0);
+			modmul(R1,p,ND);
+
+			cswap(R0,R1,b);
+			R0.modsqr(p,ND);
+
+			R1.copy(this);
+			cswap(R0,R1,b);
+		}
+		copy(R0);
+		redc(p,ND);
+	}
+
+	/* raise to an integer power - right-to-left method */
+	public void power(int e,FF p)
+	{
+		int n=p.length;
+		FF w=new FF(n);
+		FF ND=p.invmod2m();
+		boolean f=true;
+
+		w.copy(this);
+		w.nres(p);
+
+		if (e==2)
+		{
+			copy(w);
+			modsqr(p,ND);
+		}
+		else for (; ; )
+		{
+			if (e%2==1)
+			{
+				if (f) copy(w);
+				else modmul(w,p,ND);
+				f=false;
+			}
+			e>>=1;
+			if (e==0) break;
+			w.modsqr(p,ND);
+		}
+		redc(p,ND);
+	}
+
+	/* this=this^e mod p, faster but not side channel resistant */
+	public void pow(FF e,FF p)
+	{
+		int i,b,n=p.length;
+		FF w=new FF(n);
+		FF ND=p.invmod2m();
+
+		w.copy(this);
+		one();
+		nres(p);
+		w.nres(p);
+		for (i=8*ROM.MODBYTES*n-1;i>=0;i--)
+		{
+			modsqr(p,ND);
+			b=e.v[i/ROM.BIGBITS].bit(i%ROM.BIGBITS);
+			if (b==1) modmul(w,p,ND);
+		}
+		redc(p,ND);
+	}
+
+	/* double exponentiation r=x^e.y^f mod p */
+	public void pow2(BIG e,FF y,BIG f,FF p)
+	{
+		int i,eb,fb,n=p.length;
+		FF xn=new FF(n);
+		FF yn=new FF(n);
+		FF xy=new FF(n);
+		FF ND=p.invmod2m();
+
+		xn.copy(this);
+		yn.copy(y);
+		xn.nres(p);
+		yn.nres(p);
+		xy.copy(xn); xy.modmul(yn,p,ND);
+		one();
+		nres(p);
+
+		for (i=8*ROM.MODBYTES-1;i>=0;i--)
+		{
+			eb=e.bit(i);
+			fb=f.bit(i);
+			modsqr(p,ND);
+			if (eb==1)
+			{
+				if (fb==1) modmul(xy,p,ND);
+				else modmul(xn,p,ND);
+			}
+			else
+			{
+				if (fb==1) modmul(yn,p,ND);
+			}
+		}
+		redc(p,ND);
+	}
+
+	private static int igcd(int x,int y)
+	{ /* integer GCD, returns GCD of x and y */
+		int r;
+		if (y==0) return x;
+		while ((r=x%y)!=0)
+			{x=y;y=r;}
+		return y;
+	}
+
+	/* quick and dirty check for common factor with n */
+	public boolean cfactor(int s)
+	{
+		int r,n=length;
+		int g;
+
+		FF x=new FF(n);
+		FF y=new FF(n);
+
+		y.set(s);
+		x.copy(this);
+		x.norm();
+
+		do
+		{
+			x.sub(y);
+			x.norm();
+			while (!x.iszilch() && x.parity()==0) x.shr();
+		}
+		while (comp(x,y)>0);
+
+		g=(int)x.v[0].get(0);
+		r=igcd(s,g);
+		if (r>1) return true;
+		return false;
+	}
+
+	/* Miller-Rabin test for primality. Slow. */
+	public static boolean prime(FF p,RAND rng)
+	{
+		int i,j,s=0,n=p.length;
+		boolean loop;
+		FF d=new FF(n);
+		FF x=new FF(n);
+		FF unity=new FF(n);
+		FF nm1=new FF(n);
+
+		int sf=4849845; /* 3*5*.. *19 */
+		p.norm();
+
+		if (p.cfactor(sf)) return false;
+		unity.one();
+		nm1.copy(p);
+		nm1.sub(unity);
+		nm1.norm();
+		d.copy(nm1);
+
+		while (d.parity()==0)
+		{
+			d.shr();
+			s++;
+		}
+		if (s==0) return false;
+		for (i=0;i<10;i++)
+		{
+			x.randomnum(p,rng);
+			x.pow(d,p);
+
+			if (comp(x,unity)==0 || comp(x,nm1)==0) continue;
+			loop=false;
+			for (j=1;j<s;j++)
+			{
+				x.power(2,p);
+				if (comp(x,unity)==0) return false;
+				if (comp(x,nm1)==0) {loop=true; break;}
+			}
+			if (loop) continue;
+			return false;
+		}
+		return true;
+	}
+
+}
\ No newline at end of file
diff --git a/version22/java/FP.java b/version22/java/FP.java
new file mode 100644
index 0000000..bafa46b
--- /dev/null
+++ b/version22/java/FP.java
@@ -0,0 +1,345 @@
+/*
+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.
+*/
+
+/* Finite Field arithmetic */
+/* AMCL mod p functions */
+
+public final class FP {
+	private final BIG x;
+	private static BIG p=new BIG(ROM.Modulus);
+
+/* Constructors */
+	public FP(int a)
+	{
+		x=new BIG(a);
+		nres();
+	}
+
+	public FP()
+	{
+		x=new BIG(0);
+	}
+
+	public FP(BIG a)
+	{
+		x=new BIG(a);
+		nres();
+	}
+	
+	public FP(FP a)
+	{
+		x=new BIG(a.x);
+	}
+
+/* convert to string */
+	public String toString() 
+	{
+		String s=redc().toString();
+		return s;
+	}
+
+	public String toRawString() 
+	{
+		String s=x.toRawString();
+		return s;
+	}
+
+/* convert to Montgomery n-residue form */
+	public void nres()
+	{
+		if (ROM.MODTYPE!=ROM.PSEUDO_MERSENNE && ROM.MODTYPE!=ROM.GENERALISED_MERSENNE)
+		{
+			DBIG d=new DBIG(x);
+			d.shl(ROM.NLEN*ROM.BASEBITS);
+			x.copy(d.mod(p));
+		}
+	}
+
+/* convert back to regular form */
+	public BIG redc()
+	{
+		if (ROM.MODTYPE!=ROM.PSEUDO_MERSENNE && ROM.MODTYPE!=ROM.GENERALISED_MERSENNE)
+		{
+			DBIG d=new DBIG(x);
+			return BIG.mod(d);
+		}
+		else 
+		{
+			BIG r=new BIG(x);
+			return r;
+		}
+	}
+
+/* test this=0? */
+	public boolean iszilch() {
+		reduce();
+		return x.iszilch();
+	}
+
+/* copy from FP b */
+	public void copy(FP b)
+	{
+		x.copy(b.x);
+	}
+
+/* set this=0 */
+	public void zero()
+	{
+		x.zero();
+	}
+	
+/* set this=1 */
+	public void one()
+	{
+		x.one(); nres();
+	}
+
+/* normalise this */
+	public void norm()
+	{
+		x.norm();
+	}
+
+/* swap FPs depending on d */
+	public void cswap(FP b,int d)
+	{
+		x.cswap(b.x,d);
+	}
+
+/* copy FPs depending on d */
+	public void cmove(FP b,int d)
+	{
+		x.cmove(b.x,d);
+	}
+
+/* this*=b mod Modulus */
+	public void mul(FP b)
+	{
+		norm();
+		b.norm();
+
+		if (BIG.pexceed(x,b.x)) reduce();
+
+		DBIG d=BIG.mul(x,b.x);
+		x.copy(BIG.mod(d));
+	}
+
+/* this*=c mod Modulus, where c is a small int */
+	public void imul(int c)
+	{
+		norm();
+		boolean s=false;
+		if (c<0)
+		{
+			c=-c;
+			s=true;
+		}
+		if (c<ROM.NEXCESS && ((BIG.EXCESS(x)+1)*(c+1)+1)<ROM.FEXCESS)
+		{
+			x.imul(c);
+		}
+		else
+		{
+			if (((BIG.EXCESS(x)+1)*(c+1)+1)<ROM.FEXCESS) x.pmul(c);
+			else
+			{
+				DBIG d=x.pxmul(c);
+				x.copy(d.mod(p));
+			}
+		}
+		if (s) neg();
+		norm();
+	}
+
+/* this*=this mod Modulus */
+	public void sqr()
+	{
+		DBIG d;
+		norm();
+
+		if (BIG.sexceed(x)) reduce();
+
+		d=BIG.sqr(x);	
+		x.copy(BIG.mod(d));
+	}
+
+/* this+=b */
+	public void add(FP b) {
+		x.add(b.x);
+		if (BIG.EXCESS(x)+2>=ROM.FEXCESS) reduce();
+	}
+
+// https://graphics.stanford.edu/~seander/bithacks.html
+// constant time log to base 2 (or number of bits in)
+
+	private static int logb2(int v)
+	{
+		int r;
+		v |= v >>> 1;
+		v |= v >>> 2;
+		v |= v >>> 4;
+		v |= v >>> 8;
+		v |= v >>> 16;
+
+		v = v - ((v >>> 1) & 0x55555555);                  
+		v = (v & 0x33333333) + ((v >>> 2) & 0x33333333);  
+		r = ((v + (v >>> 4) & 0xF0F0F0F) * 0x1010101) >>> 24; 
+		return r+1;
+	}
+
+/* this = -this mod Modulus */
+	public void neg()
+	{
+		int sb;
+		BIG m=new BIG(p);
+
+		norm();
+		sb=logb2((int)BIG.EXCESS(x));
+/*
+		ov=BIG.EXCESS(x); 
+		sb=1; while(ov!=0) {sb++;ov>>=1;} 
+*/
+		m.fshl(sb);
+		x.rsub(m);		
+
+		if (BIG.EXCESS(x)>=ROM.FEXCESS) reduce();
+	}
+
+/* this-=b */
+	public void sub(FP b)
+	{
+		FP n=new FP(b);
+		n.neg();
+		this.add(n);
+	}
+
+/* this/=2 mod Modulus */
+	public void div2()
+	{
+		x.norm();
+		if (x.parity()==0)
+			x.fshr(1);
+		else
+		{
+			x.add(p);
+			x.norm();
+			x.fshr(1);
+		}
+	}
+
+/* this=1/this mod Modulus */
+	public void inverse()
+	{
+		BIG r=redc();
+		r.invmodp(p);
+		x.copy(r);
+		nres();
+	}
+
+/* return TRUE if this==a */
+	public boolean equals(FP a)
+	{
+		a.reduce();
+		reduce();
+		if (BIG.comp(a.x,x)==0) return true;
+		return false;
+	}
+
+/* reduce this mod Modulus */
+	public void reduce()
+	{
+		x.mod(p);
+	}
+
+/* return this^e mod Modulus */
+	public FP pow(BIG e)
+	{
+		int bt;
+		FP r=new FP(1);
+		e.norm();
+		x.norm();
+		FP m=new FP(this);
+		while (true)
+		{
+			bt=e.parity();
+			e.fshr(1);
+			if (bt==1) r.mul(m);
+			if (e.iszilch()) break;
+			m.sqr();
+		}
+		r.x.mod(p);
+		return r;
+	}
+
+/* return sqrt(this) mod Modulus */
+	public FP sqrt()
+	{
+		reduce();
+		BIG b=new BIG(p);
+		if (ROM.MOD8==5)
+		{
+			b.dec(5); b.norm(); b.shr(3);
+			FP i=new FP(this); i.x.shl(1);
+			FP v=i.pow(b);
+			i.mul(v); i.mul(v);
+			i.x.dec(1);
+			FP r=new FP(this);
+			r.mul(v); r.mul(i); 
+			r.reduce();
+			return r;
+		}
+		else
+		{
+			b.inc(1); b.norm(); b.shr(2);
+			return pow(b);
+		}
+	}
+
+/* return jacobi symbol (this/Modulus) */
+	public int jacobi()
+	{
+		BIG w=redc();
+		return w.jacobi(p);
+	}
+/*
+	public static void main(String[] args) {
+		BIG m=new BIG(ROM.Modulus);
+		BIG x=new BIG(3);
+		BIG e=new BIG(m);
+		e.dec(1);
+
+		System.out.println("m= "+m.nbits());	
+
+
+		BIG r=x.powmod(e,m);
+
+		System.out.println("m= "+m.toString());	
+		System.out.println("r= "+r.toString());	
+
+		BIG.cswap(m,r,0);
+
+		System.out.println("m= "+m.toString());	
+		System.out.println("r= "+r.toString());	
+
+//		FP y=new FP(3);
+//		FP s=y.pow(e);
+//		System.out.println("s= "+s.toString());	
+
+	} */
+}
diff --git a/version22/java/FP12.java b/version22/java/FP12.java
new file mode 100644
index 0000000..7ef0607
--- /dev/null
+++ b/version22/java/FP12.java
@@ -0,0 +1,641 @@
+/*
+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.
+*/
+
+/* AMCL Fp^12 functions */
+/* FP12 elements are of the form a+i.b+i^2.c */
+
+public final class FP12 {
+	private final FP4 a;
+	private final FP4 b;
+	private final FP4 c;
+/* reduce all components of this mod Modulus */
+	public void reduce()
+	{
+		a.reduce();
+		b.reduce();
+		c.reduce();
+	}
+/* normalise all components of this */
+	public void norm()
+	{
+		a.norm();
+		b.norm();
+		c.norm();
+	}
+/* test x==0 ? */
+	public boolean iszilch() {
+		reduce();
+		return (a.iszilch() && b.iszilch() && c.iszilch());
+	}
+/* test x==1 ? */
+	public boolean isunity() {
+		FP4 one=new FP4(1);
+		return (a.equals(one) && b.iszilch() && c.iszilch());
+	}
+/* return 1 if x==y, else 0 */
+	public boolean equals(FP12 x)
+	{
+		return (a.equals(x.a) && b.equals(x.b) && c.equals(x.c));
+	}
+/* extract a from this */
+	public FP4 geta()
+	{
+		return a;
+	}
+/* extract b */
+	public FP4 getb()
+	{
+		return b;
+	}
+/* extract c */
+	public FP4 getc()
+	{
+		return c;
+	}
+/* copy this=x */
+	public void copy(FP12 x)
+	{
+		a.copy(x.a);
+		b.copy(x.b);
+		c.copy(x.c);
+	}
+/* set this=1 */
+	public void one()
+	{
+		a.one();
+		b.zero();
+		c.zero();
+	}
+/* this=conj(this) */
+	public void conj()
+	{
+		a.conj();
+		b.nconj();
+		c.conj();
+	}
+/* Constructors */
+	public FP12(FP4 d)
+	{
+		a=new FP4(d);
+		b=new FP4(0);
+		c=new FP4(0);
+	}
+
+	public FP12(int d)
+	{
+		a=new FP4(d);
+		b=new FP4(0);
+		c=new FP4(0);
+	}
+
+	public FP12(FP4 d,FP4 e,FP4 f)
+	{
+		a=new FP4(d);
+		b=new FP4(e);
+		c=new FP4(f);
+	}
+
+	public FP12(FP12 x)
+	{
+		a=new FP4(x.a);
+		b=new FP4(x.b);
+		c=new FP4(x.c);
+	}
+
+/* Granger-Scott Unitary Squaring */
+	public void usqr()
+	{
+		FP4 A=new FP4(a);
+		FP4 B=new FP4(c);
+		FP4 C=new FP4(b);
+		FP4 D=new FP4(0);
+
+		a.sqr();
+		D.copy(a); D.add(a);
+		a.add(D);
+
+		a.norm();
+		A.nconj();
+
+		A.add(A);
+		a.add(A);
+		B.sqr();
+		B.times_i();
+
+		D.copy(B); D.add(B);
+		B.add(D);
+		B.norm();
+
+		C.sqr();
+		D.copy(C); D.add(C);
+		C.add(D);
+		C.norm();
+
+		b.conj();
+		b.add(b);
+		c.nconj();
+
+		c.add(c);
+		b.add(B);
+		c.add(C);
+		reduce();
+
+	}
+
+/* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
+	public void sqr()
+	{
+		FP4 A=new FP4(a);
+		FP4 B=new FP4(b);
+		FP4 C=new FP4(c);
+		FP4 D=new FP4(a);
+
+		A.sqr();
+		B.mul(c);
+		B.add(B);
+		C.sqr();
+		D.mul(b);
+		D.add(D);
+
+		c.add(a);
+		c.add(b);
+		c.sqr();
+
+		a.copy(A);
+
+		A.add(B);
+		A.norm();
+		A.add(C);
+		A.add(D);
+		A.norm();
+
+		A.neg();
+		B.times_i();
+		C.times_i();
+
+		a.add(B);
+
+		b.copy(C); b.add(D);
+		c.add(A);
+		norm();
+	}
+
+/* FP12 full multiplication this=this*y */
+	public void mul(FP12 y)
+	{
+		FP4 z0=new FP4(a);
+		FP4 z1=new FP4(0);
+		FP4 z2=new FP4(b);
+		FP4 z3=new FP4(0);
+		FP4 t0=new FP4(a);
+		FP4 t1=new FP4(y.a);
+
+		z0.mul(y.a);
+		z2.mul(y.b);
+
+		t0.add(b);
+		t1.add(y.b);
+
+		z1.copy(t0); z1.mul(t1);
+		t0.copy(b); t0.add(c);
+
+		t1.copy(y.b); t1.add(y.c);
+		z3.copy(t0); z3.mul(t1);
+
+		t0.copy(z0); t0.neg();
+		t1.copy(z2); t1.neg();
+
+		z1.add(t0);
+		z1.norm();
+		b.copy(z1); b.add(t1);
+
+		z3.add(t1);
+		z2.add(t0);
+
+		t0.copy(a); t0.add(c);
+		t1.copy(y.a); t1.add(y.c);
+		t0.mul(t1);
+		z2.add(t0);
+
+		t0.copy(c); t0.mul(y.c);
+		t1.copy(t0); t1.neg();
+
+		z2.norm();
+		z3.norm();
+		b.norm();
+
+		c.copy(z2); c.add(t1);
+		z3.add(t1);
+		t0.times_i();
+		b.add(t0);
+
+		z3.times_i();
+		a.copy(z0); a.add(z3);
+		norm();
+	}
+
+/* Special case of multiplication arises from special form of ATE pairing line function */
+	public void smul(FP12 y)
+	{
+		FP4 z0=new FP4(a);
+		FP4 z2=new FP4(b);
+		FP4 z3=new FP4(b);
+		FP4 t0=new FP4(0);
+		FP4 t1=new FP4(y.a);
+		
+		z0.mul(y.a);
+		z2.pmul(y.b.real());
+		b.add(a);
+		t1.real().add(y.b.real());
+
+		b.mul(t1);
+		z3.add(c);
+		z3.pmul(y.b.real());
+
+		t0.copy(z0); t0.neg();
+		t1.copy(z2); t1.neg();
+
+		b.add(t0);
+		b.norm();
+
+		b.add(t1);
+		z3.add(t1);
+		z2.add(t0);
+
+		t0.copy(a); t0.add(c);
+		t0.mul(y.a);
+		c.copy(z2); c.add(t0);
+
+		z3.times_i();
+		a.copy(z0); a.add(z3);
+
+		norm();
+	}
+
+/* this=1/this */
+	public void inverse()
+	{
+		FP4 f0=new FP4(a);
+		FP4 f1=new FP4(b);
+		FP4 f2=new FP4(a);
+		FP4 f3=new FP4(0);
+
+		norm();
+		f0.sqr();
+		f1.mul(c);
+		f1.times_i();
+		f0.sub(f1);
+
+		f1.copy(c); f1.sqr();
+		f1.times_i();
+		f2.mul(b);
+		f1.sub(f2);
+
+		f2.copy(b); f2.sqr();
+		f3.copy(a); f3.mul(c);
+		f2.sub(f3);
+
+		f3.copy(b); f3.mul(f2);
+		f3.times_i();
+		a.mul(f0);
+		f3.add(a);
+		c.mul(f1);
+		c.times_i();
+
+		f3.add(c);
+		f3.inverse();
+		a.copy(f0); a.mul(f3);
+		b.copy(f1); b.mul(f3);
+		c.copy(f2); c.mul(f3);
+	}
+
+/* this=this^p using Frobenius */
+	public void frob(FP2 f)
+	{
+		FP2 f2=new FP2(f);
+		FP2 f3=new FP2(f);
+
+		f2.sqr();
+		f3.mul(f2);
+
+		a.frob(f3);
+		b.frob(f3);
+		c.frob(f3);
+
+		b.pmul(f);
+		c.pmul(f2);
+	}
+
+/* trace function */
+	public FP4 trace()
+	{
+		FP4 t=new FP4(0);
+		t.copy(a);
+		t.imul(3);
+		t.reduce();
+		return t;
+	}
+
+/* convert from byte array to FP12 */
+	public static FP12 fromBytes(byte[] w)
+	{
+		BIG a,b;
+		FP2 c,d;
+		FP4 e,f,g;
+		byte[] t=new byte[ROM.MODBYTES];
+
+		for (int i=0;i<ROM.MODBYTES;i++) t[i]=w[i];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<ROM.MODBYTES;i++) t[i]=w[i+ROM.MODBYTES];
+		b=BIG.fromBytes(t);
+		c=new FP2(a,b);
+
+		for (int i=0;i<ROM.MODBYTES;i++) t[i]=w[i+2*ROM.MODBYTES];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<ROM.MODBYTES;i++) t[i]=w[i+3*ROM.MODBYTES];
+		b=BIG.fromBytes(t);
+		d=new FP2(a,b);
+
+		e=new FP4(c,d);
+
+
+		for (int i=0;i<ROM.MODBYTES;i++) t[i]=w[i+4*ROM.MODBYTES];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<ROM.MODBYTES;i++) t[i]=w[i+5*ROM.MODBYTES];
+		b=BIG.fromBytes(t);
+		c=new FP2(a,b);
+
+		for (int i=0;i<ROM.MODBYTES;i++) t[i]=w[i+6*ROM.MODBYTES];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<ROM.MODBYTES;i++) t[i]=w[i+7*ROM.MODBYTES];
+		b=BIG.fromBytes(t);
+		d=new FP2(a,b);
+
+		f=new FP4(c,d);
+
+
+		for (int i=0;i<ROM.MODBYTES;i++) t[i]=w[i+8*ROM.MODBYTES];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<ROM.MODBYTES;i++) t[i]=w[i+9*ROM.MODBYTES];
+		b=BIG.fromBytes(t);
+		c=new FP2(a,b);
+
+		for (int i=0;i<ROM.MODBYTES;i++) t[i]=w[i+10*ROM.MODBYTES];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<ROM.MODBYTES;i++) t[i]=w[i+11*ROM.MODBYTES];
+		b=BIG.fromBytes(t);
+		d=new FP2(a,b);
+
+		g=new FP4(c,d);
+
+		return new FP12(e,f,g);
+	}
+
+/* convert this to byte array */
+	public void toBytes(byte[] w)
+	{
+		byte[] t=new byte[ROM.MODBYTES];
+		a.geta().getA().toBytes(t);
+		for (int i=0;i<ROM.MODBYTES;i++) w[i]=t[i];
+		a.geta().getB().toBytes(t);
+		for (int i=0;i<ROM.MODBYTES;i++) w[i+ROM.MODBYTES]=t[i];
+		a.getb().getA().toBytes(t);
+		for (int i=0;i<ROM.MODBYTES;i++) w[i+2*ROM.MODBYTES]=t[i];
+		a.getb().getB().toBytes(t);
+		for (int i=0;i<ROM.MODBYTES;i++) w[i+3*ROM.MODBYTES]=t[i];
+
+		b.geta().getA().toBytes(t);
+		for (int i=0;i<ROM.MODBYTES;i++) w[i+4*ROM.MODBYTES]=t[i];
+		b.geta().getB().toBytes(t);
+		for (int i=0;i<ROM.MODBYTES;i++) w[i+5*ROM.MODBYTES]=t[i];
+		b.getb().getA().toBytes(t);
+		for (int i=0;i<ROM.MODBYTES;i++) w[i+6*ROM.MODBYTES]=t[i];
+		b.getb().getB().toBytes(t);
+		for (int i=0;i<ROM.MODBYTES;i++) w[i+7*ROM.MODBYTES]=t[i];
+
+		c.geta().getA().toBytes(t);
+		for (int i=0;i<ROM.MODBYTES;i++) w[i+8*ROM.MODBYTES]=t[i];
+		c.geta().getB().toBytes(t);
+		for (int i=0;i<ROM.MODBYTES;i++) w[i+9*ROM.MODBYTES]=t[i];
+		c.getb().getA().toBytes(t);
+		for (int i=0;i<ROM.MODBYTES;i++) w[i+10*ROM.MODBYTES]=t[i];
+		c.getb().getB().toBytes(t);
+		for (int i=0;i<ROM.MODBYTES;i++) w[i+11*ROM.MODBYTES]=t[i];
+	}
+
+/* convert to hex string */
+	public String toString() 
+	{
+		return ("["+a.toString()+","+b.toString()+","+c.toString()+"]");
+	}
+
+/* this=this^e */ 
+/* Note this is simple square and multiply, so not side-channel safe */
+	public FP12 pow(BIG e)
+	{
+		norm();
+		e.norm();
+		FP12 w=new FP12(this);
+		BIG z=new BIG(e);
+		FP12 r=new FP12(1);
+
+		while (true)
+		{
+			int bt=z.parity();
+			z.fshr(1);
+			if (bt==1) r.mul(w);
+			if (z.iszilch()) break;
+			w.usqr();
+		}
+		r.reduce();
+		return r;
+	}
+
+/* constant time powering by small integer of max length bts */
+	public void pinpow(int e,int bts)
+	{
+		int i,b;
+		FP12 [] R=new FP12[2];
+		R[0]=new FP12(1);
+		R[1]=new FP12(this);
+		for (i=bts-1;i>=0;i--)
+		{
+			b=(e>>i)&1;
+			R[1-b].mul(R[b]);
+			R[b].usqr();
+		}
+		this.copy(R[0]);
+	}
+
+/* p=q0^u0.q1^u1.q2^u2.q3^u3 */
+/* Timing attack secure, but not cache attack secure */
+
+	public static FP12 pow4(FP12[] q,BIG[] u)
+	{
+		int i,j,nb,m;
+		int[] a=new int[4];
+		FP12 [] g=new FP12[8];
+		FP12 [] s=new FP12[2];
+		FP12 c=new FP12(1);
+		FP12 p=new FP12(0);
+		BIG [] t=new BIG[4];
+		BIG mt=new BIG(0);
+		byte[] w=new byte[ROM.NLEN*ROM.BASEBITS+1];
+
+		for (i=0;i<4;i++)
+			t[i]=new BIG(u[i]);
+
+		s[0]=new FP12(0);
+		s[1]=new FP12(0);
+
+		g[0]=new FP12(q[0]); s[0].copy(q[1]); s[0].conj(); g[0].mul(s[0]);
+		g[1]=new FP12(g[0]);
+		g[2]=new FP12(g[0]);
+		g[3]=new FP12(g[0]);
+		g[4]=new FP12(q[0]); g[4].mul(q[1]);
+		g[5]=new FP12(g[4]);
+		g[6]=new FP12(g[4]);
+		g[7]=new FP12(g[4]);
+
+		s[1].copy(q[2]); s[0].copy(q[3]); s[0].conj(); s[1].mul(s[0]);
+		s[0].copy(s[1]); s[0].conj(); g[1].mul(s[0]);
+		g[2].mul(s[1]);
+		g[5].mul(s[0]);
+		g[6].mul(s[1]);
+		s[1].copy(q[2]); s[1].mul(q[3]);
+		s[0].copy(s[1]); s[0].conj(); g[0].mul(s[0]);
+		g[3].mul(s[1]);
+		g[4].mul(s[0]);
+		g[7].mul(s[1]);
+
+/* if power is even add 1 to power, and add q to correction */
+
+		for (i=0;i<4;i++)
+		{
+			if (t[i].parity()==0)
+			{
+				t[i].inc(1); t[i].norm();
+				c.mul(q[i]);
+			}
+			mt.add(t[i]); mt.norm();
+		}
+		c.conj();
+		nb=1+mt.nbits();
+
+/* convert exponent to signed 1-bit window */
+		for (j=0;j<nb;j++)
+		{
+			for (i=0;i<4;i++)
+			{
+				a[i]=(t[i].lastbits(2)-2);
+				t[i].dec(a[i]); t[i].norm(); 
+				t[i].fshr(1);
+			}
+			w[j]=(byte)(8*a[0]+4*a[1]+2*a[2]+a[3]);
+		}
+		w[nb]=(byte)(8*t[0].lastbits(2)+4*t[1].lastbits(2)+2*t[2].lastbits(2)+t[3].lastbits(2));
+		p.copy(g[(w[nb]-1)/2]);  
+
+		for (i=nb-1;i>=0;i--)
+		{
+			m=w[i]>>7;
+			j=(w[i]^m)-m;  /* j=abs(w[i]) */
+			j=(j-1)/2;
+			s[0].copy(g[j]); s[1].copy(g[j]); s[1].conj();
+			p.usqr();
+			p.mul(s[m&1]);
+		}
+		p.mul(c);  /* apply correction */
+		p.reduce();
+		return p;
+	}
+
+/*
+	public static void main(String[] args) {
+		BIG p=new BIG(ROM.Modulus);
+		FP2 w0,w1;
+		BIG a=new BIG(0);
+		BIG b=new BIG(0);
+		
+		a.zero(); b.zero(); a.inc(1); b.inc(2);
+		w0=new FP2(a,b);
+		a.zero(); b.zero(); a.inc(3); b.inc(4);
+		w1=new FP2(a,b);
+		FP4 t0=new FP4(w0,w1);
+
+		a.zero(); b.zero(); a.inc(5); b.inc(6);
+		w0=new FP2(a,b);
+		a.zero(); b.zero(); a.inc(7); b.inc(8);
+		w1=new FP2(a,b);
+		FP4 t1=new FP4(w0,w1);
+
+		a.zero(); b.zero(); a.inc(9); b.inc(10);
+		w0=new FP2(a,b);
+		a.zero(); b.zero(); a.inc(11); b.inc(12);
+		w1=new FP2(a,b);
+		FP4 t2=new FP4(w0,w1);
+
+		FP12 w=new FP12(t0,t1,t2);
+		FP12 t=new FP12(w);
+
+		System.out.println("w= "+w.toString());
+
+		a=new BIG(ROM.CURVE_Fra);
+		b=new BIG(ROM.CURVE_Frb);
+
+		FP2 f=new FP2(a,b);
+
+		w.frob(f);
+		System.out.println("w= "+w.toString());
+
+		w=t.pow(p);
+
+		System.out.println("w= "+w.toString());
+
+		w.inverse();
+
+		System.out.println("1/w= "+w.toString());
+
+		w.inverse();
+
+		System.out.println("w= "+w.toString());
+
+		t.copy(w);
+		w.conj();
+		t.inverse();
+		w.mul(t);
+
+		System.out.println("w^(p^6-1)= "+w.toString());
+
+		t.copy(w);
+		w.frob(f);
+		w.frob(f);
+		w.mul(t);
+
+		System.out.println("w^(p^6-1)(p^2+1)= "+w.toString());
+
+		t.copy(w);
+
+		t.inverse();
+		w.conj();
+
+		System.out.println("w= "+w.toString());
+		System.out.println("t= "+t.toString());
+	} */
+}
diff --git a/version22/java/FP2.java b/version22/java/FP2.java
new file mode 100644
index 0000000..9667db9
--- /dev/null
+++ b/version22/java/FP2.java
@@ -0,0 +1,393 @@
+/*
+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.
+*/
+
+/* Finite Field arithmetic  Fp^2 functions */
+
+/* FP2 elements are of the form a+ib, where i is sqrt(-1) */
+
+public final class FP2 {
+	private final FP a;
+	private final FP b;
+
+/* reduce components mod Modulus */
+	public void reduce()
+	{
+		a.reduce();
+		b.reduce();
+	}
+
+/* normalise components of w */
+	public void norm()
+	{
+		a.norm();
+		b.norm();
+	}
+
+/* test this=0 ? */
+	public boolean iszilch() {
+		reduce();
+		return (a.iszilch() && b.iszilch());
+	}
+
+	public void cmove(FP2 g,int d)
+	{
+		a.cmove(g.a,d);
+		b.cmove(g.b,d);
+	}
+
+/* test this=1 ? */
+	public boolean isunity() {
+		FP one=new FP(1);
+		return (a.equals(one) && b.iszilch());
+	}
+
+/* test this=x */
+	public boolean equals(FP2 x) {
+		return (a.equals(x.a) && b.equals(x.b));
+	}
+
+/* Constructors */
+	public FP2(int c)
+	{
+		a=new FP(c);
+		b=new FP(0);
+	}
+
+	public FP2(FP2 x)
+	{
+		a=new FP(x.a);
+		b=new FP(x.b);
+	}
+
+	public FP2(FP c,FP d)
+	{
+		a=new FP(c);
+		b=new FP(d);
+	}
+
+	public FP2(BIG c,BIG d)
+	{
+		a=new FP(c);
+		b=new FP(d);
+	}
+
+	public FP2(FP c)
+	{
+		a=new FP(c);
+		b=new FP(0);
+	}
+
+	public FP2(BIG c)
+	{
+		a=new FP(c);
+		b=new FP(0);
+	}
+/*
+	public BIG geta()
+	{
+		return a.tobig();
+	}
+*/
+/* extract a */
+	public BIG getA()
+	{ 
+		return a.redc();
+	}
+
+/* extract b */
+	public BIG getB()
+	{
+		return b.redc();
+	}
+
+/* copy this=x */
+	public void copy(FP2 x)
+	{
+		a.copy(x.a);
+		b.copy(x.b);
+	}
+
+/* set this=0 */
+	public void zero()
+	{
+		a.zero();
+		b.zero();
+	}
+
+/* set this=1 */
+	public void one()
+	{
+		a.one();
+		b.zero();
+	}
+
+/* negate this mod Modulus */
+	public void neg()
+	{
+		norm();
+		FP m=new FP(a);
+		FP t=new FP(0);
+
+		m.add(b);
+		m.neg();
+		m.norm();
+		t.copy(m); t.add(b);
+		b.copy(m);
+		b.add(a);
+		a.copy(t);
+	}
+
+/* set to a-ib */
+	public void conj()
+	{
+		b.neg();
+	}
+
+/* this+=a */
+	public void add(FP2 x)
+	{
+		a.add(x.a);
+		b.add(x.b);
+	}
+
+/* this-=a */
+	public void sub(FP2 x)
+	{
+		FP2 m=new FP2(x);
+		m.neg();
+		add(m);
+	}
+
+/* this*=s, where s is an FP */
+	public void pmul(FP s)
+	{
+		a.mul(s);
+		b.mul(s);
+	}
+
+/* this*=i, where i is an int */
+	public void imul(int c)
+	{
+		a.imul(c);
+		b.imul(c);
+	}
+
+/* this*=this */
+	public void sqr()
+	{
+		norm();
+		FP w1=new FP(a);
+		FP w3=new FP(a);
+		FP mb=new FP(b);
+
+		w3.mul(b);
+		w1.add(b);
+		mb.neg();
+		a.add(mb);
+		a.mul(w1);
+		b.copy(w3); b.add(w3);
+		norm();
+	}
+
+/* this*=y */
+	public void mul(FP2 y)
+	{
+		norm();  /* This is needed here as {a,b} is not normed before additions */
+
+		FP w1=new FP(a);
+		FP w2=new FP(b);
+		FP w5=new FP(a);
+		FP mw=new FP(0);
+
+		w1.mul(y.a);  // w1=a*y.a  - this norms w1 and y.a, NOT a
+		w2.mul(y.b);  // w2=b*y.b  - this norms w2 and y.b, NOT b
+		w5.add(b);    // w5=a+b
+		b.copy(y.a); b.add(y.b); // b=y.a+y.b
+
+		b.mul(w5);
+		mw.copy(w1); mw.add(w2); mw.neg();
+
+		b.add(mw); mw.add(w1);
+		a.copy(w1);	a.add(mw);
+
+		norm();
+	}
+
+/* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */
+/* returns true if this is QR */
+	public boolean sqrt()
+	{
+		if (iszilch()) return true;
+		FP w1=new FP(b);
+		FP w2=new FP(a);
+		w1.sqr(); w2.sqr(); w1.add(w2);
+		if (w1.jacobi()!=1) { zero(); return false; }
+		w1=w1.sqrt();
+		w2.copy(a); w2.add(w1); w2.div2();
+		if (w2.jacobi()!=1)
+		{
+			w2.copy(a); w2.sub(w1); w2.div2();
+			if (w2.jacobi()!=1) { zero(); return false; }
+		}
+		w2=w2.sqrt();
+		a.copy(w2);
+		w2.add(w2);
+		w2.inverse();
+		b.mul(w2);
+		return true;
+	}
+
+/* output to hex string */
+	public String toString() 
+	{
+		return ("["+a.toString()+","+b.toString()+"]");
+	}
+
+	public String toRawString() 
+	{
+		return ("["+a.toRawString()+","+b.toRawString()+"]");
+	}
+
+/* this=1/this */
+	public void inverse()
+	{
+		norm();
+		FP w1=new FP(a);
+		FP w2=new FP(b);
+
+		w1.sqr();
+		w2.sqr();
+		w1.add(w2);
+		w1.inverse();
+		a.mul(w1);
+		w1.neg();
+		b.mul(w1);
+	}
+
+/* this/=2 */
+	public void div2()
+	{
+		a.div2();
+		b.div2();
+	}
+
+/* this*=sqrt(-1) */
+	public void times_i()
+	{
+	//	a.norm();
+		FP z=new FP(a);
+		a.copy(b); a.neg();
+		b.copy(z);
+	}
+
+/* w*=(1+sqrt(-1)) */
+/* where X*2-(1+sqrt(-1)) is irreducible for FP4, assumes p=3 mod 8 */
+	public void mul_ip()
+	{
+		norm();
+		FP2 t=new FP2(this);
+		FP z=new FP(a);
+		a.copy(b);
+		a.neg();
+		b.copy(z);
+		add(t);
+		norm();
+	}
+
+/* w/=(1+sqrt(-1)) */
+	public void div_ip()
+	{
+		FP2 t=new FP2(0);
+		norm();
+		t.a.copy(a); t.a.add(b);
+		t.b.copy(b); t.b.sub(a);
+		copy(t);
+		div2();
+	}
+/*
+	public FP2 pow(BIG e)
+	{
+		int bt;
+		FP2 r=new FP2(1);
+		e.norm();
+		norm();
+		while (true)
+		{
+			bt=e.parity();
+			e.fshr(1);
+			if (bt==1) r.mul(this);
+			if (e.iszilch()) break;
+			sqr();
+		}
+
+		r.reduce();
+		return r;
+	}
+
+	public static void main(String[] args) {
+		BIG m=new BIG(ROM.Modulus);
+		BIG x=new BIG(3);
+		BIG e=new BIG(27);
+		BIG pp1=new BIG(m);
+		BIG pm1=new BIG(m);
+		BIG a=new BIG(1);
+		BIG b=new BIG(1);
+		FP2 w=new FP2(a,b);
+		FP2 z=new FP2(w);
+
+		byte[] RAW=new byte[100];
+
+		RAND rng=new RAND();
+		for (int i=0;i<100;i++) RAW[i]=(byte)(i);
+
+		rng.seed(100,RAW);
+
+	//	for (int i=0;i<100;i++)
+	//	{
+			a.randomnum(rng);
+			b.randomnum(rng);
+
+			w=new FP2(a,b);
+			System.out.println("w="+w.toString());
+
+			z=new FP2(w);
+			z.inverse();
+			System.out.println("z="+z.toString());
+
+			z.inverse();
+			if (!z.equals(w)) System.out.println("Error");
+	//	}
+
+//		System.out.println("m="+m.toString());
+//		w.sqr();
+//		w.mul(z);
+
+		System.out.println("w="+w.toString());
+
+
+		pp1.inc(1); pp1.norm();
+		pm1.dec(1); pm1.norm();
+		System.out.println("p+1="+pp1.toString());
+		System.out.println("p-1="+pm1.toString());
+		w=w.pow(pp1);
+		w=w.pow(pm1);
+		System.out.println("w="+w.toString());
+	}
+*/
+}
\ No newline at end of file
diff --git a/version22/java/FP4.java b/version22/java/FP4.java
new file mode 100644
index 0000000..7d8912a
--- /dev/null
+++ b/version22/java/FP4.java
@@ -0,0 +1,584 @@
+/*
+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.
+*/
+
+/* Finite Field arithmetic  Fp^4 functions */
+
+/* FP4 elements are of the form a+ib, where i is sqrt(-1+sqrt(-1))  */
+
+public final class FP4 {
+	private final FP2 a;
+	private final FP2 b;
+/* reduce all components of this mod Modulus */
+	public void reduce()
+	{
+		a.reduce();
+		b.reduce();
+	}
+/* normalise all components of this mod Modulus */
+	public void norm()
+	{
+		a.norm();
+		b.norm();
+	}
+/* test this==0 ? */
+	public boolean iszilch() {
+		reduce();
+		return (a.iszilch() && b.iszilch());
+	}
+/* test this==1 ? */
+	public boolean isunity() {
+		FP2 one=new FP2(1);
+		return (a.equals(one) && b.iszilch());
+	}
+
+/* test is w real? That is in a+ib test b is zero */
+	public boolean isreal()
+	{
+		return b.iszilch();
+	}
+/* extract real part a */
+	public FP2 real()
+	{
+		return a;
+	}
+
+	public FP2 geta()
+	{
+		return a;
+	}
+/* extract imaginary part b */
+	public FP2 getb()
+	{
+		return b;
+	}
+/* test this=x? */
+	public boolean equals(FP4 x)
+	{
+		return (a.equals(x.a) && b.equals(x.b));
+	}
+/* constructors */
+	public FP4(int c)
+	{
+		a=new FP2(c);
+		b=new FP2(0);
+	}
+
+	public FP4(FP4 x)
+	{
+		a=new FP2(x.a);
+		b=new FP2(x.b);
+	}
+
+	public FP4(FP2 c,FP2 d)
+	{
+		a=new FP2(c);
+		b=new FP2(d);
+	}
+
+	public FP4(FP2 c)
+	{
+		a=new FP2(c);
+		b=new FP2(0);
+	}
+/* copy this=x */
+	public void copy(FP4 x)
+	{
+		a.copy(x.a);
+		b.copy(x.b);
+	}
+/* set this=0 */
+	public void zero()
+	{
+		a.zero();
+		b.zero();
+	}
+/* set this=1 */
+	public void one()
+	{
+		a.one();
+		b.zero();
+	}
+/* set this=-this */
+	public void neg()
+	{
+		FP2 m=new FP2(a);
+		FP2 t=new FP2(0);
+		m.add(b);
+		m.neg();
+		m.norm();
+		t.copy(m); t.add(b);
+		b.copy(m);
+		b.add(a);
+		a.copy(t);
+	}
+/* this=conjugate(this) */
+	public void conj()
+	{
+		b.neg(); b.norm();
+	}
+/* this=-conjugate(this) */
+	public void nconj()
+	{
+		a.neg(); a.norm();
+	}
+/* this+=x */
+	public void add(FP4 x)
+	{
+		a.add(x.a);
+		b.add(x.b);
+	}
+/* this-=x */
+	public void sub(FP4 x)
+	{
+		FP4 m=new FP4(x);
+		m.neg();
+		add(m);
+	}
+
+/* this*=s where s is FP2 */
+	public void pmul(FP2 s)
+	{
+		a.mul(s);
+		b.mul(s);
+	}
+/* this*=c where c is int */
+	public void imul(int c)
+	{
+		a.imul(c);
+		b.imul(c);
+	}
+/* this*=this */	
+	public void sqr()
+	{
+		norm();
+
+		FP2 t1=new FP2(a);
+		FP2 t2=new FP2(b);
+		FP2 t3=new FP2(a);
+
+		t3.mul(b);
+		t1.add(b);
+		t2.mul_ip();
+
+		t2.add(a);
+		a.copy(t1);
+
+		a.mul(t2);
+
+		t2.copy(t3);
+		t2.mul_ip();
+		t2.add(t3);
+		t2.neg();
+		a.add(t2);
+
+		b.copy(t3);
+		b.add(t3);
+
+		norm();
+	}
+/* this*=y */
+	public void mul(FP4 y)
+	{
+		norm();
+
+		FP2 t1=new FP2(a);
+		FP2 t2=new FP2(b);
+		FP2 t3=new FP2(0);
+		FP2 t4=new FP2(b);
+
+		t1.mul(y.a);
+		t2.mul(y.b);
+		t3.copy(y.b);
+		t3.add(y.a);
+		t4.add(a);
+
+		t4.mul(t3);
+		t4.sub(t1);
+		t4.norm();
+
+		b.copy(t4);
+		b.sub(t2);
+		t2.mul_ip();
+		a.copy(t2);
+		a.add(t1);
+
+		norm();
+	}
+/* convert this to hex string */
+	public String toString() 
+	{
+		return ("["+a.toString()+","+b.toString()+"]");
+	}
+
+	public String toRawString() 
+	{
+		return ("["+a.toRawString()+","+b.toRawString()+"]");
+	}
+
+/* this=1/this */
+	public void inverse()
+	{
+		norm();
+
+		FP2 t1=new FP2(a);
+		FP2 t2=new FP2(b);
+
+		t1.sqr();
+		t2.sqr();
+		t2.mul_ip();
+		t1.sub(t2);
+		t1.inverse();
+		a.mul(t1);
+		t1.neg();
+		b.mul(t1);
+	}
+
+
+/* this*=i where i = sqrt(-1+sqrt(-1)) */
+	public void times_i()
+	{
+		norm();
+		FP2 s=new FP2(b);
+		FP2 t=new FP2(b);
+		s.times_i();
+		t.add(s);
+		t.norm();
+		b.copy(a);
+		a.copy(t);
+	}
+
+/* this=this^p using Frobenius */
+	public void frob(FP2 f)
+	{
+		a.conj();
+		b.conj();
+		b.mul(f);
+	}
+
+/* this=this^e */
+	public FP4 pow(BIG e)
+	{
+		norm();
+		e.norm();
+		FP4 w=new FP4(this);
+		BIG z=new BIG(e);
+		FP4 r=new FP4(1);
+		while (true)
+		{
+			int bt=z.parity();
+			z.fshr(1);
+			if (bt==1) r.mul(w);
+			if (z.iszilch()) break;
+			w.sqr();
+		}
+		r.reduce();
+		return r;
+	}
+/* XTR xtr_a function */
+	public void xtr_A(FP4 w,FP4 y,FP4 z) 
+	{
+		FP4 r=new FP4(w);
+		FP4 t=new FP4(w);
+		r.sub(y);
+		r.pmul(a);
+		t.add(y);
+		t.pmul(b);
+		t.times_i();
+
+		copy(r);
+		add(t);
+		add(z);
+
+		norm();
+	}
+
+/* XTR xtr_d function */
+	public void xtr_D() {
+		FP4 w=new FP4(this);
+		sqr(); w.conj();
+		w.add(w);
+		sub(w);
+		reduce();
+	}
+
+/* r=x^n using XTR method on traces of FP12s */
+	public FP4 xtr_pow(BIG n) {
+		FP4 a=new FP4(3);
+		FP4 b=new FP4(this);
+		FP4 c=new FP4(b);
+		c.xtr_D();
+		FP4 t=new FP4(0);
+		FP4 r=new FP4(0);
+
+		n.norm();
+		int par=n.parity();
+		BIG v=new BIG(n); v.fshr(1);
+		if (par==0) {v.dec(1); v.norm();}
+
+		int nb=v.nbits();
+		for (int i=nb-1;i>=0;i--)
+		{
+			if (v.bit(i)!=1)
+			{
+				t.copy(b);
+				conj();
+				c.conj();
+				b.xtr_A(a,this,c);
+				conj();
+				c.copy(t);
+				c.xtr_D();
+				a.xtr_D();
+			}
+			else
+			{
+				t.copy(a); t.conj();
+				a.copy(b);
+				a.xtr_D();
+				b.xtr_A(c,this,t);
+				c.xtr_D();
+			}
+		}
+		if (par==0) r.copy(c);
+		else r.copy(b);
+		r.reduce();
+		return r;
+	}
+
+/* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */
+	public FP4 xtr_pow2(FP4 ck,FP4 ckml,FP4 ckm2l,BIG a,BIG b)
+	{
+		a.norm(); b.norm();
+		BIG e=new BIG(a);
+		BIG d=new BIG(b);
+		BIG w=new BIG(0);
+
+		FP4 cu=new FP4(ck);  // can probably be passed in w/o copying
+		FP4 cv=new FP4(this);
+		FP4 cumv=new FP4(ckml);
+		FP4 cum2v=new FP4(ckm2l);
+		FP4 r=new FP4(0);
+		FP4 t=new FP4(0);
+
+		int f2=0;
+		while (d.parity()==0 && e.parity()==0)
+		{
+			d.fshr(1);
+			e.fshr(1);
+			f2++;
+		}
+
+		while (BIG.comp(d,e)!=0)
+		{
+			if (BIG.comp(d,e)>0)
+			{
+				w.copy(e); w.imul(4); w.norm();
+				if (BIG.comp(d,w)<=0)
+				{
+					w.copy(d); d.copy(e);
+					e.rsub(w); e.norm();
+
+					t.copy(cv); 
+					t.xtr_A(cu,cumv,cum2v);
+					cum2v.copy(cumv); 
+					cum2v.conj();
+					cumv.copy(cv);
+					cv.copy(cu);
+					cu.copy(t);
+
+				}
+				else if (d.parity()==0)
+				{
+					d.fshr(1);
+					r.copy(cum2v); r.conj();
+					t.copy(cumv);
+					t.xtr_A(cu,cv,r);
+					cum2v.copy(cumv);
+					cum2v.xtr_D();
+					cumv.copy(t);
+					cu.xtr_D();
+				}
+				else if (e.parity()==1)
+				{
+					d.sub(e); d.norm();
+					d.fshr(1);
+					t.copy(cv);
+					t.xtr_A(cu,cumv,cum2v);
+					cu.xtr_D();
+					cum2v.copy(cv);
+					cum2v.xtr_D();
+					cum2v.conj();
+					cv.copy(t);
+				}
+				else
+				{
+					w.copy(d);
+					d.copy(e); d.fshr(1);
+					e.copy(w);
+					t.copy(cumv);
+					t.xtr_D();
+					cumv.copy(cum2v); cumv.conj();
+					cum2v.copy(t); cum2v.conj();
+					t.copy(cv);
+					t.xtr_D();
+					cv.copy(cu);
+					cu.copy(t);
+				}
+			}
+			if (BIG.comp(d,e)<0)
+			{
+				w.copy(d); w.imul(4); w.norm();
+				if (BIG.comp(e,w)<=0)
+				{
+					e.sub(d); e.norm();
+					t.copy(cv);
+					t.xtr_A(cu,cumv,cum2v);
+					cum2v.copy(cumv);
+					cumv.copy(cu);
+					cu.copy(t);
+				}
+				else if (e.parity()==0)
+				{
+					w.copy(d);
+					d.copy(e); d.fshr(1);
+					e.copy(w);
+					t.copy(cumv);
+					t.xtr_D();
+					cumv.copy(cum2v); cumv.conj();
+					cum2v.copy(t); cum2v.conj();
+					t.copy(cv);
+					t.xtr_D();
+					cv.copy(cu);
+					cu.copy(t);
+				}
+				else if (d.parity()==1)
+				{
+					w.copy(e);
+					e.copy(d);
+					w.sub(d); w.norm();
+					d.copy(w); d.fshr(1);
+					t.copy(cv);
+					t.xtr_A(cu,cumv,cum2v);
+					cumv.conj();
+					cum2v.copy(cu);
+					cum2v.xtr_D();
+					cum2v.conj();
+					cu.copy(cv);
+					cu.xtr_D();
+					cv.copy(t);
+				}
+				else
+				{
+					d.fshr(1);
+					r.copy(cum2v); r.conj();
+					t.copy(cumv);
+					t.xtr_A(cu,cv,r);
+					cum2v.copy(cumv);
+					cum2v.xtr_D();
+					cumv.copy(t);
+					cu.xtr_D();
+				}
+			}
+		}
+		r.copy(cv);
+		r.xtr_A(cu,cumv,cum2v);
+		for (int i=0;i<f2;i++)
+			r.xtr_D();
+		r=r.xtr_pow(d);
+		return r;
+	}
+
+/*
+	public static void main(String[] args) {
+		BIG m=new BIG(ROM.Modulus);
+		BIG e=new BIG(12);
+		BIG a=new BIG(0);
+		BIG b=new BIG(0);
+		
+		a.inc(27); b.inc(45);
+
+		FP2 w0=new FP2(a,b);
+
+		a.zero(); b.zero();
+		a.inc(33); b.inc(54);
+
+		FP2 w1=new FP2(a,b);
+
+
+		FP4 w=new FP4(w0,w1);
+		FP4 t=new FP4(w);
+
+		a=new BIG(ROM.CURVE_Fra);
+		b=new BIG(ROM.CURVE_Frb);
+
+		FP2 f=new FP2(a,b);
+
+		System.out.println("w= "+w.toString());
+
+		w=w.pow(m);
+
+		System.out.println("w^p= "+w.toString());
+
+		t.frob(f);
+
+
+		System.out.println("w^p= "+t.toString());
+
+		w=w.pow(m);
+		w=w.pow(m);
+		w=w.pow(m);
+		System.out.println("w^p4= "+w.toString());
+
+
+	System.out.println("Test Inversion");
+
+		w=new FP4(w0,w1);
+
+		w.inverse();
+
+		System.out.println("1/w mod p^4 = "+w.toString());
+
+		w.inverse();
+
+		System.out.println("1/(1/w) mod p^4 = "+w.toString());
+
+		FP4 ww=new FP4(w);
+
+		w=w.xtr_pow(e);
+		System.out.println("w^e= "+w.toString());
+
+
+		a.zero(); b.zero();
+		a.inc(37); b.inc(17);
+		w0=new FP2(a,b);
+		a.zero(); b.zero();
+		a.inc(49); b.inc(31);
+		w1=new FP2(a,b);
+
+		FP4 c1=new FP4(w0,w1);
+		FP4 c2=new FP4(w0,w1);
+		FP4 c3=new FP4(w0,w1);
+
+		BIG e1=new BIG(3331);
+		BIG e2=new BIG(3372);
+
+		FP4 cr=w.xtr_pow2(c1,c2,c3,e1,e2);
+
+		System.out.println("c^e= "+cr.toString()); 
+	} */
+}
diff --git a/version22/java/GCM.java b/version22/java/GCM.java
new file mode 100644
index 0000000..47e5bb2
--- /dev/null
+++ b/version22/java/GCM.java
@@ -0,0 +1,374 @@
+/*
+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.
+*/
+
+
+/*
+ * Implementation of the AES-GCM Encryption/Authentication
+ *
+ * Some restrictions.. 
+ * 1. Only for use with AES
+ * 2. Returned tag is always 128-bits. Truncate at your own risk.
+ * 3. The order of function calls must follow some rules
+ *
+ * Typical sequence of calls..
+ * 1. call GCM_init
+ * 2. call GCM_add_header any number of times, as long as length of header is multiple of 16 bytes (block size)
+ * 3. call GCM_add_header one last time with any length of header
+ * 4. call GCM_add_cipher any number of times, as long as length of cipher/plaintext is multiple of 16 bytes
+ * 5. call GCM_add_cipher one last time with any length of cipher/plaintext
+ * 6. call GCM_finish to extract the tag.
+ *
+ * See http://www.mindspring.com/~dmcgrew/gcm-nist-6.pdf
+ */
+
+public class GCM {
+	public static final int NB=4;
+	public static final int GCM_ACCEPTING_HEADER=0;
+	public static final int GCM_ACCEPTING_CIPHER=1;
+	public static final int GCM_NOT_ACCEPTING_MORE=2;
+	public static final int GCM_FINISHED=3;
+	public static final int GCM_ENCRYPTING=0;
+	public static final int GCM_DECRYPTING=1;
+
+	private int[][] table=new int[128][4]; /* 2k bytes */
+	private byte[] stateX=new byte[16];
+	private byte[]Y_0=new byte[16];
+	private int counter;
+	private int[] lenA=new int[2];
+	private int[] lenC=new int[2];
+	private int status;
+	private AES a=new AES();
+
+	private static int pack(byte[] b)
+	{ /* pack bytes into a 32-bit Word */
+		return ((((int)b[0])&0xff)<<24)|(((int)b[1]&0xff)<<16)|(((int)b[2]&0xff)<<8)|((int)b[3]&0xff);
+	}
+
+	private static byte[] unpack(int a)
+	{ /* unpack bytes from a word */
+		byte [] b=new byte[4];
+		b[3]=(byte)(a);
+		b[2]=(byte)(a>>>8);
+		b[1]=(byte)(a>>>16);
+		b[0]=(byte)(a>>>24);
+		return b;
+	}
+
+	private void precompute(byte[] H)
+	{
+		int i,j,c;
+		byte[] b=new byte[4];
+
+		for (i=j=0;i<NB;i++,j+=4) 
+		{
+			b[0]=H[j]; b[1]=H[j+1]; b[2]=H[j+2]; b[3]=H[j+3];
+			table[0][i]=pack(b);
+		}
+		for (i=1;i<128;i++)
+		{
+			c=0;
+			for (j=0;j<NB;j++) {table[i][j]=c|(table[i-1][j])>>>1; c=table[i-1][j]<<31;}
+			if (c!=0) table[i][0]^=0xE1000000; /* irreducible polynomial */
+		}
+	}
+
+	private void gf2mul()
+	{ /* gf2m mul - Z=H*X mod 2^128 */
+		int i,j,m,k;
+		int[] P=new int[4];
+		int c;
+		byte[] b;//=new byte[4];
+
+		P[0]=P[1]=P[2]=P[3]=0;
+		j=8; m=0;
+		for (i=0;i<128;i++)
+		{
+			c=(stateX[m]>>>(--j))&1; c=~c+1;
+			for (k=0;k<NB;k++) P[k]^=(table[i][k]&c);
+			if (j==0)
+			{
+				j=8; m++;
+				if (m==16) break;
+			}
+		}
+		for (i=j=0;i<NB;i++,j+=4) 
+		{
+			b=unpack(P[i]);
+			stateX[j]=b[0]; stateX[j+1]=b[1]; stateX[j+2]=b[2]; stateX[j+3]=b[3];
+		}
+	}
+
+	private void wrap()
+	{ /* Finish off GHASH */
+		int i,j;
+		int[] F=new int[4];
+		byte[] L=new byte[16];
+		byte[] b;//=new byte[4];
+
+/* convert lengths from bytes to bits */
+		F[0]=(lenA[0]<<3)|(lenA[1]&0xE0000000)>>>29;
+		F[1]=lenA[1]<<3;
+		F[2]=(lenC[0]<<3)|(lenC[1]&0xE0000000)>>>29;
+		F[3]=lenC[1]<<3;
+		for (i=j=0;i<NB;i++,j+=4)
+		{
+			b=unpack(F[i]);
+			L[j]=b[0]; L[j+1]=b[1]; L[j+2]=b[2]; L[j+3]=b[3];
+		}
+		for (i=0;i<16;i++) stateX[i]^=L[i];
+		gf2mul();
+	}
+
+/* Initialize GCM mode */
+	public void init(int nk,byte[] key,int niv,byte[] iv)
+	{ /* iv size niv is usually 12 bytes (96 bits). AES key size nk can be 16,24 or 32 bytes */
+		int i;
+		byte[] H=new byte[16];
+		byte[] b;//=new byte[4];
+
+		for (i=0;i<16;i++) {H[i]=0; stateX[i]=0;}
+
+		a.init(AES.ECB,nk,key,iv);
+		a.ecb_encrypt(H);     /* E(K,0) */
+		precompute(H);
+	
+		lenA[0]=lenC[0]=lenA[1]=lenC[1]=0;
+		if (niv==12)
+		{
+			for (i=0;i<12;i++) a.f[i]=iv[i];
+			b=unpack((int)1);
+			a.f[12]=b[0]; a.f[13]=b[1]; a.f[14]=b[2]; a.f[15]=b[3];  /* initialise IV */
+			for (i=0;i<16;i++) Y_0[i]=a.f[i];
+		}
+		else
+		{
+			status=GCM_ACCEPTING_CIPHER;
+			ghash(iv,niv); /* GHASH(H,0,IV) */
+			wrap();
+			for (i=0;i<16;i++) {a.f[i]=stateX[i];Y_0[i]=a.f[i];stateX[i]=0;}
+			lenA[0]=lenC[0]=lenA[1]=lenC[1]=0;
+		}
+		status=GCM_ACCEPTING_HEADER;
+	}
+
+/* Add Header data - included but not encrypted */
+	public boolean add_header(byte[] header,int len)
+	{ /* Add some header. Won't be encrypted, but will be authenticated. len is length of header */
+		int i,j=0;
+		if (status!=GCM_ACCEPTING_HEADER) return false;
+
+		while (j<len)
+		{
+			for (i=0;i<16 && j<len;i++)
+			{
+				stateX[i]^=header[j++];
+				lenA[1]++; if (lenA[1]==0) lenA[0]++;
+			}
+			gf2mul();
+		}
+		if (len%16!=0) status=GCM_ACCEPTING_CIPHER;
+		return true;
+	}
+
+	private boolean ghash(byte[] plain,int len)
+	{
+		int i,j=0;
+		int counter;
+	//	byte[] B=new byte[16];
+	//	byte[] b=new byte[4];
+
+		if (status==GCM_ACCEPTING_HEADER) status=GCM_ACCEPTING_CIPHER;
+		if (status!=GCM_ACCEPTING_CIPHER) return false;
+		
+		while (j<len)
+		{
+			for (i=0;i<16 && j<len;i++)
+			{
+				stateX[i]^=plain[j++];
+				lenC[1]++; if (lenC[1]==0) lenC[0]++;
+			}
+			gf2mul();
+		}
+		if (len%16!=0) status=GCM_NOT_ACCEPTING_MORE;
+		return true;
+	}
+
+/* Add Plaintext - included and encrypted */
+	public byte[] add_plain(byte[] plain,int len)
+	{
+		int i,j=0;
+		int counter;
+		byte[] B=new byte[16];
+		byte[] b=new byte[4];
+		byte[] cipher=new byte[len];
+
+		if (status==GCM_ACCEPTING_HEADER) status=GCM_ACCEPTING_CIPHER;
+		if (status!=GCM_ACCEPTING_CIPHER) return new byte[0];
+		
+		while (j<len)
+		{
+
+			b[0]=a.f[12]; b[1]=a.f[13]; b[2]=a.f[14]; b[3]=a.f[15];
+			counter=pack(b);
+			counter++;
+			b=unpack(counter);
+			a.f[12]=b[0]; a.f[13]=b[1]; a.f[14]=b[2]; a.f[15]=b[3]; /* increment counter */
+			for (i=0;i<16;i++) B[i]=a.f[i];
+			a.ecb_encrypt(B);        /* encrypt it  */
+		
+			for (i=0;i<16 && j<len;i++)
+			{
+				cipher[j]=(byte)(plain[j]^B[i]);
+				stateX[i]^=cipher[j++];
+				lenC[1]++; if (lenC[1]==0) lenC[0]++;
+			}
+			gf2mul();
+		}
+		if (len%16!=0) status=GCM_NOT_ACCEPTING_MORE;
+		return cipher;
+	}
+
+/* Add Ciphertext - decrypts to plaintext */
+	public byte[] add_cipher(byte[] cipher,int len)
+	{
+		int i,j=0;
+		int counter;
+		byte[] B=new byte[16];
+		byte[] b=new byte[4];
+		byte[] plain=new byte[len];
+
+		if (status==GCM_ACCEPTING_HEADER) status=GCM_ACCEPTING_CIPHER;
+		if (status!=GCM_ACCEPTING_CIPHER) return new byte[0];
+	
+		while (j<len)
+		{
+
+			b[0]=a.f[12]; b[1]=a.f[13]; b[2]=a.f[14]; b[3]=a.f[15];
+			counter=pack(b);
+			counter++;
+			b=unpack(counter);
+			a.f[12]=b[0]; a.f[13]=b[1]; a.f[14]=b[2]; a.f[15]=b[3]; /* increment counter */
+			for (i=0;i<16;i++) B[i]=a.f[i];
+			a.ecb_encrypt(B);        /* encrypt it  */
+			for (i=0;i<16 && j<len;i++)
+			{
+				byte oc=cipher[j];
+				plain[j]=(byte)(cipher[j]^B[i]);
+				stateX[i]^=oc; j++;
+				lenC[1]++; if (lenC[1]==0) lenC[0]++;
+			}
+			gf2mul();
+		}
+		if (len%16!=0) status=GCM_NOT_ACCEPTING_MORE;
+		return plain;
+	}
+
+/* Finish and extract Tag */
+	public byte[] finish(boolean extract)
+	{ /* Finish off GHASH and extract tag (MAC) */
+		int i;
+		byte[] tag=new byte[16];
+
+		wrap();
+/* extract tag */
+		if (extract)
+		{
+			a.ecb_encrypt(Y_0);        /* E(K,Y0) */
+			for (i=0;i<16;i++) Y_0[i]^=stateX[i];
+			for (i=0;i<16;i++) {tag[i]=Y_0[i];Y_0[i]=stateX[i]=0;}
+		}
+		status=GCM_FINISHED;
+		a.end();
+		return tag;
+	}
+
+	public static byte[] hex2bytes(String s) {
+		int len = s.length();
+		byte[] data = new byte[len / 2];
+		for (int i = 0; i < len; i += 2) {
+			data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+                             + Character.digit(s.charAt(i+1), 16));
+		}
+		return data;
+	}
+/*
+	public static void main(String[] args) {
+		int i;
+
+		String KT="feffe9928665731c6d6a8f9467308308";
+		String MT="d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39";
+		String HT="feedfacedeadbeeffeedfacedeadbeefabaddad2";
+//	char* NT="cafebabefacedbaddecaf888";
+// Tag should be 5bc94fbc3221a5db94fae95ae7121a47
+		String NT="9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b";
+// Tag should be 619cc5aefffe0bfa462af43c1699d050
+
+
+		byte[] T=new byte[16];   // Tag
+		byte[] K=new byte[16];   // AES Key
+		byte[] H=new byte[64];   // Header - to be included in Authentication, but not encrypted
+		byte[] N=new byte[100];   // IV - Initialisation vector
+		byte[] M=new byte[100];  // Plaintext to be encrypted/authenticated
+		byte[] C=new byte[100];  // Ciphertext
+		byte[] P=new byte[100];  // Recovered Plaintext 
+
+		GCM g=new GCM();
+
+		M=hex2bytes(MT);
+		H=hex2bytes(HT);
+		N=hex2bytes(NT);
+		K=hex2bytes(KT);
+
+		int len=M.length;
+		int lenH=H.length;
+		int lenK=K.length;
+		int lenIV=N.length;
+
+ 		System.out.format("Plaintext=\n");
+		for (i=0;i<len;i++) System.out.format("%02x",M[i]);
+		System.out.format("\n");
+
+		g.init(16,K,lenIV,N);
+		g.add_header(H,lenH);
+		C=g.add_plain(M,len);
+		T=g.finish(true);
+
+		System.out.format("Ciphertext=\n");
+		for (i=0;i<len;i++) System.out.format("%02x",C[i]);
+		System.out.format("\n");
+        
+		System.out.format("Tag=\n");
+		for (i=0;i<16;i++) System.out.format("%02x",T[i]);
+		System.out.format("\n");
+
+		g.init(16,K,lenIV,N);
+		g.add_header(H,lenH);
+		P=g.add_cipher(C,len);
+		T=g.finish(true);
+
+ 		System.out.format("Plaintext=\n");
+		for (i=0;i<len;i++) System.out.format("%02x",P[i]);
+		System.out.format("\n");
+
+		System.out.format("Tag=\n");
+		for (i=0;i<16;i++) System.out.format("%02x",T[i]);
+		System.out.format("\n");
+	}
+*/	
+}
diff --git a/version22/java/HASH256.java b/version22/java/HASH256.java
new file mode 100644
index 0000000..c1ddbd0
--- /dev/null
+++ b/version22/java/HASH256.java
@@ -0,0 +1,216 @@
+/*
+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.
+*/
+
+/*
+ * Implementation of the Secure Hashing Algorithm (SHA-256)
+ *
+ * Generates a 256 bit message digest. It should be impossible to come
+ * come up with two messages that hash to the same value ("collision free").
+ *
+ * For use with byte-oriented messages only. 
+ */
+
+public class HASH256 {
+	private int[] length=new int[2];
+	private int[] h=new int[8];
+	private int[] w=new int[80];
+
+	public static final int H0=0x6A09E667;
+	public static final int H1=0xBB67AE85;
+	public static final int H2=0x3C6EF372;
+	public static final int H3=0xA54FF53A;
+	public static final int H4=0x510E527F;
+	public static final int H5=0x9B05688C;
+	public static final int H6=0x1F83D9AB;
+	public static final int H7=0x5BE0CD19;
+
+	public static final int len=32;
+
+	public static final int[] K={
+	0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,
+	0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,
+	0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,
+	0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,
+	0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
+	0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070,
+	0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,
+	0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2};
+
+
+/* functions */
+	private static int S(int n,int x)
+	{
+		return (((x)>>>n) | ((x)<<(32-n)));
+	}
+
+	private static int R(int n,int x)
+	{
+		return ((x)>>>n);
+	}
+
+	private static int Ch(int x,int y,int z)
+	{
+		return ((x&y)^(~(x)&z));
+	}
+
+	private static int Maj(int x,int y,int z)
+	{
+		return ((x&y)^(x&z)^(y&z));
+	}
+
+	private static int Sig0(int x)
+	{
+		return (S(2,x)^S(13,x)^S(22,x));
+	}
+
+	private static int Sig1(int x)
+	{
+		return (S(6,x)^S(11,x)^S(25,x));
+	}
+
+	private static int theta0(int x)
+	{
+		return (S(7,x)^S(18,x)^R(3,x));
+	}
+
+	private static int theta1(int x)
+	{
+		return (S(17,x)^S(19,x)^R(10,x));
+	}
+
+
+	private void transform()
+	{ /* basic transformation step */
+		int a,b,c,d,e,f,g,hh,t1,t2;
+		int j;
+		for (j=16;j<64;j++) 
+			w[j]=theta1(w[j-2])+w[j-7]+theta0(w[j-15])+w[j-16];
+		a=h[0]; b=h[1]; c=h[2]; d=h[3]; 
+		e=h[4]; f=h[5]; g=h[6]; hh=h[7];
+
+		for (j=0;j<64;j++)
+		{ /* 64 times - mush it up */
+			t1=hh+Sig1(e)+Ch(e,f,g)+K[j]+w[j];
+			t2=Sig0(a)+Maj(a,b,c);
+			hh=g; g=f; f=e;
+			e=d+t1;
+			d=c;
+			c=b;
+			b=a;
+			a=t1+t2;   
+		
+		}
+		h[0]+=a; h[1]+=b; h[2]+=c; h[3]+=d; 
+		h[4]+=e; h[5]+=f; h[6]+=g; h[7]+=hh; 
+	} 
+
+/* Initialise Hash function */
+	public void init()
+	{ /* initialise */
+		int i;
+		for (i=0;i<64;i++) w[i]=0;
+		length[0]=length[1]=0;
+		h[0]=H0;
+		h[1]=H1;
+		h[2]=H2;
+		h[3]=H3;
+		h[4]=H4;
+		h[5]=H5;
+		h[6]=H6;
+		h[7]=H7;
+	}
+
+/* Constructor */
+	public HASH256()
+	{
+		init();
+	}
+
+/* process a single byte */
+	public void process(int byt)
+	{ /* process the next message byte */
+		int cnt;
+		cnt=(length[0]/32)%16;
+    
+		w[cnt]<<=8;
+		w[cnt]|=(byt&0xFF);
+		length[0]+=8;
+		if (length[0]==0) { length[1]++; length[0]=0; }
+		if ((length[0]%512)==0) transform();
+	}
+
+/* process an array of bytes */	
+	public void process_array(byte[] b)
+	{
+		for (int i=0;i<b.length;i++) process((int)b[i]);
+	}
+
+/* process a 32-bit integer */
+	public void process_num(int n)
+	{
+		process((n>>24)&0xff);
+		process((n>>16)&0xff);
+		process((n>>8)&0xff);
+		process(n&0xff);
+	}
+
+/* Generate 32-byte Hash */
+	public byte[] hash()
+	{ /* pad message and finish - supply digest */
+		int i;
+		byte[] digest=new byte[32];
+		int len0,len1;
+		len0=length[0];
+		len1=length[1];
+		process(0x80);
+		while ((length[0]%512)!=448) process(0);
+		w[14]=len1;
+		w[15]=len0;    
+		transform();
+		for (i=0;i<len;i++)
+		{ /* convert to bytes */
+			digest[i]=(byte)((h[i/4]>>(8*(3-i%4))) & 0xff);
+		}
+		init();
+		return digest;
+	}
+
+/* test program: should produce digest */
+
+//248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1
+
+	public static void main(String[] args) {
+		byte[] test="abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq".getBytes();
+		byte[] digest;
+		int i;
+		HASH256 sh=new HASH256();
+  
+		for (i=0;i<test.length;i++)
+			sh.process(test[i]);
+		
+		digest=sh.hash();    
+		for (i=0;i<32;i++) System.out.format("%02x",digest[i]);
+
+	//	for (i=0;i<32;i++) System.out.format("%d ",digest[i]);
+
+		System.out.println("");
+	} 
+}
+
+
diff --git a/version22/java/HASH384.java b/version22/java/HASH384.java
new file mode 100644
index 0000000..5422792
--- /dev/null
+++ b/version22/java/HASH384.java
@@ -0,0 +1,227 @@
+/*
+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.
+*/
+
+/*
+ * Implementation of the Secure Hashing Algorithm (SHA-512)
+ *
+ * Generates a 512 bit message digest. It should be impossible to come
+ * come up with two messages that hash to the same value ("collision free").
+ *
+ * For use with byte-oriented messages only. 
+ */
+
+public class HASH384 {
+	private long[] length=new long[2];
+	private long[] h=new long[8];
+	private long[] w=new long[80];
+
+	public static final long H0=0xcbbb9d5dc1059ed8L;
+	public static final long H1=0x629a292a367cd507L;
+	public static final long H2=0x9159015a3070dd17L;
+	public static final long H3=0x152fecd8f70e5939L;
+	public static final long H4=0x67332667ffc00b31L;
+	public static final long H5=0x8eb44a8768581511L;
+	public static final long H6=0xdb0c2e0d64f98fa7L;
+	public static final long H7=0x47b5481dbefa4fa4L;
+
+	public static final int len=48;
+
+	public static final long[] K=
+	{0x428a2f98d728ae22L,0x7137449123ef65cdL,0xb5c0fbcfec4d3b2fL,0xe9b5dba58189dbbcL,
+	0x3956c25bf348b538L,0x59f111f1b605d019L,0x923f82a4af194f9bL,0xab1c5ed5da6d8118L,
+	0xd807aa98a3030242L,0x12835b0145706fbeL,0x243185be4ee4b28cL,0x550c7dc3d5ffb4e2L,
+	0x72be5d74f27b896fL,0x80deb1fe3b1696b1L,0x9bdc06a725c71235L,0xc19bf174cf692694L,
+	0xe49b69c19ef14ad2L,0xefbe4786384f25e3L,0x0fc19dc68b8cd5b5L,0x240ca1cc77ac9c65L,
+	0x2de92c6f592b0275L,0x4a7484aa6ea6e483L,0x5cb0a9dcbd41fbd4L,0x76f988da831153b5L,
+	0x983e5152ee66dfabL,0xa831c66d2db43210L,0xb00327c898fb213fL,0xbf597fc7beef0ee4L,
+	0xc6e00bf33da88fc2L,0xd5a79147930aa725L,0x06ca6351e003826fL,0x142929670a0e6e70L,
+	0x27b70a8546d22ffcL,0x2e1b21385c26c926L,0x4d2c6dfc5ac42aedL,0x53380d139d95b3dfL,
+	0x650a73548baf63deL,0x766a0abb3c77b2a8L,0x81c2c92e47edaee6L,0x92722c851482353bL,
+	0xa2bfe8a14cf10364L,0xa81a664bbc423001L,0xc24b8b70d0f89791L,0xc76c51a30654be30L,
+	0xd192e819d6ef5218L,0xd69906245565a910L,0xf40e35855771202aL,0x106aa07032bbd1b8L,
+	0x19a4c116b8d2d0c8L,0x1e376c085141ab53L,0x2748774cdf8eeb99L,0x34b0bcb5e19b48a8L,
+	0x391c0cb3c5c95a63L,0x4ed8aa4ae3418acbL,0x5b9cca4f7763e373L,0x682e6ff3d6b2b8a3L,
+	0x748f82ee5defb2fcL,0x78a5636f43172f60L,0x84c87814a1f0ab72L,0x8cc702081a6439ecL,
+	0x90befffa23631e28L,0xa4506cebde82bde9L,0xbef9a3f7b2c67915L,0xc67178f2e372532bL,
+	0xca273eceea26619cL,0xd186b8c721c0c207L,0xeada7dd6cde0eb1eL,0xf57d4f7fee6ed178L,
+	0x06f067aa72176fbaL,0x0a637dc5a2c898a6L,0x113f9804bef90daeL,0x1b710b35131c471bL,
+	0x28db77f523047d84L,0x32caab7b40c72493L,0x3c9ebe0a15c9bebcL,0x431d67c49c100d4cL,
+	0x4cc5d4becb3e42b6L,0x597f299cfc657e2aL,0x5fcb6fab3ad6faecL,0x6c44198c4a475817L};
+
+/* functions */
+	private static long S(int n,long x)
+	{
+		return (((x)>>>n) | ((x)<<(64-n)));
+	}
+
+	private static long R(int n,long x)
+	{
+		return ((x)>>>n);
+	}
+
+	private static long Ch(long x,long y,long z)
+	{
+		return ((x&y)^(~(x)&z));
+	}
+
+	private static long Maj(long x,long y,long z)
+	{
+		return ((x&y)^(x&z)^(y&z));
+	}
+
+	private static long Sig0(long x)
+	{
+		return (S(28,x)^S(34,x)^S(39,x));
+	}
+
+	private static long Sig1(long x)
+	{
+		return (S(14,x)^S(18,x)^S(41,x));
+	}
+
+	private static long theta0(long x)
+	{
+		return (S(1,x)^S(8,x)^R(7,x));
+	}
+
+	private static long theta1(long x)
+	{
+		return (S(19,x)^S(61,x)^R(6,x));
+	}
+
+	private void transform()
+	{ /* basic transformation step */
+		long a,b,c,d,e,f,g,hh,t1,t2;
+		int j;
+		for (j=16;j<80;j++) 
+			w[j]=theta1(w[j-2])+w[j-7]+theta0(w[j-15])+w[j-16];
+		a=h[0]; b=h[1]; c=h[2]; d=h[3]; 
+		e=h[4]; f=h[5]; g=h[6]; hh=h[7];
+
+		for (j=0;j<80;j++)
+		{ /* 80 times - mush it up */
+			t1=hh+Sig1(e)+Ch(e,f,g)+K[j]+w[j];
+			t2=Sig0(a)+Maj(a,b,c);
+			hh=g; g=f; f=e;
+			e=d+t1;
+			d=c;
+			c=b;
+			b=a;
+			a=t1+t2;   
+		
+		}
+		h[0]+=a; h[1]+=b; h[2]+=c; h[3]+=d; 
+		h[4]+=e; h[5]+=f; h[6]+=g; h[7]+=hh; 
+	} 
+
+/* Initialise Hash function */
+	public void init()
+	{ /* initialise */
+		int i;
+		for (i=0;i<80;i++) w[i]=0L;
+		length[0]=length[1]=0L;
+		h[0]=H0;
+		h[1]=H1;
+		h[2]=H2;
+		h[3]=H3;
+		h[4]=H4;
+		h[5]=H5;
+		h[6]=H6;
+		h[7]=H7;
+	}
+
+/* Constructor */
+	public HASH384()
+	{
+		init();
+	}
+
+/* process a single byte */
+	public void process(int byt)
+	{ /* process the next message byte */
+		int cnt;
+		cnt=(int)(length[0]/64)%16;
+    
+		w[cnt]<<=8;
+		w[cnt]|=(byt&0xFF);
+		length[0]+=8;
+		if (length[0]==0L) { length[1]++; length[0]=0L; }
+		if ((length[0]%1024)==0) transform();
+	}
+
+/* process an array of bytes */	
+	public void process_array(byte[] b)
+	{
+		for (int i=0;i<b.length;i++) process((int)b[i]);
+	}
+
+/* process a 32-bit integer */
+	public void process_num(int n)
+	{
+		process((n>>24)&0xff);
+		process((n>>16)&0xff);
+		process((n>>8)&0xff);
+		process(n&0xff);
+	}
+
+/* Generate 48-byte Hash */
+	public byte[] hash()
+	{ /* pad message and finish - supply digest */
+		int i;
+		byte[] digest=new byte[48];
+		long len0,len1;
+		len0=length[0];
+		len1=length[1];
+		process(0x80);
+		while ((length[0]%1024)!=896) process(0);
+		w[14]=len1;
+		w[15]=len0;    
+		transform();
+		for (i=0;i<len;i++)
+		{ /* convert to bytes */
+			digest[i]=(byte)((h[i/8]>>(8*(7-i%8))) & 0xffL);
+		}
+		init();
+		return digest;
+	}
+
+/* test program: should produce digest */
+
+//09330c33f71147e8 3d192fc782cd1b47 53111b173b3b05d2 2fa08086e3b0f712 fcc7c71a557e2db9 66c3e9fa91746039
+
+	public static void main(String[] args) {
+
+		byte[] test="abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu".getBytes();
+		byte[] digest;
+		int i;
+		HASH384 sh=new HASH384();
+  
+		for (i=0;i<test.length;i++)
+			sh.process(test[i]);
+		
+		digest=sh.hash();    
+		for (i=0;i<48;i++) System.out.format("%02x",digest[i]);
+
+	//	for (i=0;i<32;i++) System.out.format("%d ",digest[i]);
+
+		System.out.println("");
+
+	} 
+}
+
diff --git a/version22/java/HASH512.java b/version22/java/HASH512.java
new file mode 100644
index 0000000..75379e3
--- /dev/null
+++ b/version22/java/HASH512.java
@@ -0,0 +1,229 @@
+/*
+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.
+*/
+
+/*
+ * Implementation of the Secure Hashing Algorithm (SHA-512)
+ *
+ * Generates a 512 bit message digest. It should be impossible to come
+ * come up with two messages that hash to the same value ("collision free").
+ *
+ * For use with byte-oriented messages only. 
+ */
+
+
+public class HASH512 {
+	private long[] length=new long[2];
+	private long[] h=new long[8];
+	private long[] w=new long[80];
+
+	public static final long H0=0x6a09e667f3bcc908L;
+	public static final long H1=0xbb67ae8584caa73bL;
+	public static final long H2=0x3c6ef372fe94f82bL;
+	public static final long H3=0xa54ff53a5f1d36f1L;
+	public static final long H4=0x510e527fade682d1L;
+	public static final long H5=0x9b05688c2b3e6c1fL;
+	public static final long H6=0x1f83d9abfb41bd6bL;
+	public static final long H7=0x5be0cd19137e2179L;
+
+	public static final int len=64;
+
+	public static final long[] K=
+	{0x428a2f98d728ae22L,0x7137449123ef65cdL,0xb5c0fbcfec4d3b2fL,0xe9b5dba58189dbbcL,
+	0x3956c25bf348b538L,0x59f111f1b605d019L,0x923f82a4af194f9bL,0xab1c5ed5da6d8118L,
+	0xd807aa98a3030242L,0x12835b0145706fbeL,0x243185be4ee4b28cL,0x550c7dc3d5ffb4e2L,
+	0x72be5d74f27b896fL,0x80deb1fe3b1696b1L,0x9bdc06a725c71235L,0xc19bf174cf692694L,
+	0xe49b69c19ef14ad2L,0xefbe4786384f25e3L,0x0fc19dc68b8cd5b5L,0x240ca1cc77ac9c65L,
+	0x2de92c6f592b0275L,0x4a7484aa6ea6e483L,0x5cb0a9dcbd41fbd4L,0x76f988da831153b5L,
+	0x983e5152ee66dfabL,0xa831c66d2db43210L,0xb00327c898fb213fL,0xbf597fc7beef0ee4L,
+	0xc6e00bf33da88fc2L,0xd5a79147930aa725L,0x06ca6351e003826fL,0x142929670a0e6e70L,
+	0x27b70a8546d22ffcL,0x2e1b21385c26c926L,0x4d2c6dfc5ac42aedL,0x53380d139d95b3dfL,
+	0x650a73548baf63deL,0x766a0abb3c77b2a8L,0x81c2c92e47edaee6L,0x92722c851482353bL,
+	0xa2bfe8a14cf10364L,0xa81a664bbc423001L,0xc24b8b70d0f89791L,0xc76c51a30654be30L,
+	0xd192e819d6ef5218L,0xd69906245565a910L,0xf40e35855771202aL,0x106aa07032bbd1b8L,
+	0x19a4c116b8d2d0c8L,0x1e376c085141ab53L,0x2748774cdf8eeb99L,0x34b0bcb5e19b48a8L,
+	0x391c0cb3c5c95a63L,0x4ed8aa4ae3418acbL,0x5b9cca4f7763e373L,0x682e6ff3d6b2b8a3L,
+	0x748f82ee5defb2fcL,0x78a5636f43172f60L,0x84c87814a1f0ab72L,0x8cc702081a6439ecL,
+	0x90befffa23631e28L,0xa4506cebde82bde9L,0xbef9a3f7b2c67915L,0xc67178f2e372532bL,
+	0xca273eceea26619cL,0xd186b8c721c0c207L,0xeada7dd6cde0eb1eL,0xf57d4f7fee6ed178L,
+	0x06f067aa72176fbaL,0x0a637dc5a2c898a6L,0x113f9804bef90daeL,0x1b710b35131c471bL,
+	0x28db77f523047d84L,0x32caab7b40c72493L,0x3c9ebe0a15c9bebcL,0x431d67c49c100d4cL,
+	0x4cc5d4becb3e42b6L,0x597f299cfc657e2aL,0x5fcb6fab3ad6faecL,0x6c44198c4a475817L};
+
+/* functions */
+	private static long S(int n,long x)
+	{
+		return (((x)>>>n) | ((x)<<(64-n)));
+	}
+
+	private static long R(int n,long x)
+	{
+		return ((x)>>>n);
+	}
+
+	private static long Ch(long x,long y,long z)
+	{
+		return ((x&y)^(~(x)&z));
+	}
+
+	private static long Maj(long x,long y,long z)
+	{
+		return ((x&y)^(x&z)^(y&z));
+	}
+
+	private static long Sig0(long x)
+	{
+		return (S(28,x)^S(34,x)^S(39,x));
+	}
+
+	private static long Sig1(long x)
+	{
+		return (S(14,x)^S(18,x)^S(41,x));
+	}
+
+	private static long theta0(long x)
+	{
+		return (S(1,x)^S(8,x)^R(7,x));
+	}
+
+	private static long theta1(long x)
+	{
+		return (S(19,x)^S(61,x)^R(6,x));
+	}
+
+
+	private void transform()
+	{ /* basic transformation step */
+		long a,b,c,d,e,f,g,hh,t1,t2;
+		int j;
+		for (j=16;j<80;j++) 
+			w[j]=theta1(w[j-2])+w[j-7]+theta0(w[j-15])+w[j-16];
+		a=h[0]; b=h[1]; c=h[2]; d=h[3]; 
+		e=h[4]; f=h[5]; g=h[6]; hh=h[7];
+
+		for (j=0;j<80;j++)
+		{ /* 80 times - mush it up */
+			t1=hh+Sig1(e)+Ch(e,f,g)+K[j]+w[j];
+			t2=Sig0(a)+Maj(a,b,c);
+			hh=g; g=f; f=e;
+			e=d+t1;
+			d=c;
+			c=b;
+			b=a;
+			a=t1+t2;   
+		
+		}
+		h[0]+=a; h[1]+=b; h[2]+=c; h[3]+=d; 
+		h[4]+=e; h[5]+=f; h[6]+=g; h[7]+=hh; 
+	} 
+
+/* Initialise Hash function */
+	public void init()
+	{ /* initialise */
+		int i;
+		for (i=0;i<80;i++) w[i]=0L;
+		length[0]=length[1]=0L;
+		h[0]=H0;
+		h[1]=H1;
+		h[2]=H2;
+		h[3]=H3;
+		h[4]=H4;
+		h[5]=H5;
+		h[6]=H6;
+		h[7]=H7;
+	}
+
+/* Constructor */
+	public HASH512()
+	{
+		init();
+	}
+
+/* process a single byte */
+	public void process(int byt)
+	{ /* process the next message byte */
+		int cnt;
+		cnt=(int)(length[0]/64)%16;
+    
+		w[cnt]<<=8;
+		w[cnt]|=(byt&0xFF);
+		length[0]+=8;
+		if (length[0]==0L) { length[1]++; length[0]=0L; }
+		if ((length[0]%1024)==0) transform();
+	}
+
+/* process an array of bytes */	
+	public void process_array(byte[] b)
+	{
+		for (int i=0;i<b.length;i++) process((int)b[i]);
+	}
+
+/* process a 32-bit integer */
+	public void process_num(int n)
+	{
+		process((n>>24)&0xff);
+		process((n>>16)&0xff);
+		process((n>>8)&0xff);
+		process(n&0xff);
+	}
+
+/* Generate 64-byte Hash */
+	public byte[] hash()
+	{ /* pad message and finish - supply digest */
+		int i;
+		byte[] digest=new byte[64];
+		long len0,len1;
+		len0=length[0];
+		len1=length[1];
+		process(0x80);
+		while ((length[0]%1024)!=896) process(0);
+		w[14]=len1;
+		w[15]=len0;    
+		transform();
+		for (i=0;i<len;i++)
+		{ /* convert to bytes */
+			digest[i]=(byte)((h[i/8]>>(8*(7-i%8))) & 0xffL);
+		}
+		init();
+		return digest;
+	}
+
+/* test program: should produce digest */
+
+//8e959b75dae313da 8cf4f72814fc143f 8f7779c6eb9f7fa1 7299aeadb6889018 501d289e4900f7e4 331b99dec4b5433a c7d329eeb6dd2654 5e96e55b874be909
+
+	public static void main(String[] args) {
+
+		byte[] test="abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu".getBytes();
+		byte[] digest;
+		int i;
+		HASH512 sh=new HASH512();
+  
+		for (i=0;i<test.length;i++)
+			sh.process(test[i]);
+		
+		digest=sh.hash();    
+		for (i=0;i<64;i++) System.out.format("%02x",digest[i]);
+
+	//	for (i=0;i<32;i++) System.out.format("%d ",digest[i]);
+
+		System.out.println("");
+
+	} 
+}
+
diff --git a/version22/java/MPIN.java b/version22/java/MPIN.java
new file mode 100644
index 0000000..a2bd094
--- /dev/null
+++ b/version22/java/MPIN.java
@@ -0,0 +1,853 @@
+/*
+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.
+*/
+
+/* MPIN API Functions */
+
+import java.util.Date;
+
+public class MPIN
+{
+	public static final int EFS=ROM.MODBYTES;
+	public static final int EGS=ROM.MODBYTES;
+	public static final int PAS=16;
+	public static final int INVALID_POINT=-14;
+	public static final int BAD_PARAMS=-11;
+	public static final int WRONG_ORDER=-18;
+	public static final int BAD_PIN=-19;
+	public static final int SHA256=32;
+	public static final int SHA384=48;
+	public static final int SHA512=64;
+
+/* Configure your PIN here */
+
+	public static final int MAXPIN=10000;  /* PIN less than this */
+	public static final int PBLEN=14;      /* Number of bits in PIN */
+	public static final int TS=10;         /* 10 for 4 digit PIN, 14 for 6-digit PIN - 2^TS/TS approx = sqrt(MAXPIN) */
+	public static final int TRAP=200;      /* 200 for 4 digit PIN, 2000 for 6-digit PIN  - approx 2*sqrt(MAXPIN) */
+
+	public static final int HASH_TYPE=SHA256;
+
+	public static byte[] mpin_hash(int sha,FP4 c,ECP U)
+	{
+		byte[] w=new byte[EFS];
+		byte[] t=new byte[6*EFS];
+		byte[] h=null;
+		c.geta().getA().toBytes(w); for (int i=0;i<EFS;i++) t[i]=w[i];
+		c.geta().getB().toBytes(w); for (int i=EFS;i<2*EFS;i++) t[i]=w[i-EFS];
+		c.getb().getA().toBytes(w); for (int i=2*EFS;i<3*EFS;i++) t[i]=w[i-2*EFS];
+		c.getb().getB().toBytes(w); for (int i=3*EFS;i<4*EFS;i++) t[i]=w[i-3*EFS];
+		
+		U.getX().toBytes(w); for (int i=4*EFS;i<5*EFS;i++) t[i]=w[i-4*EFS];
+		U.getY().toBytes(w); for (int i=5*EFS;i<6*EFS;i++) t[i]=w[i-5*EFS];
+		
+		if (sha==SHA256)
+		{
+			HASH256 H=new HASH256();
+			H.process_array(t);
+			h=H.hash();
+		}
+		if (sha==SHA384)
+		{
+			HASH384 H=new HASH384();
+			H.process_array(t);
+			h=H.hash();
+		}
+		if (sha==SHA512)
+		{
+			HASH512 H=new HASH512();
+			H.process_array(t);
+			h=H.hash();
+		}
+		if (h==null) return null;
+		byte[] R=new byte[PAS];
+		for (int i=0;i<PAS;i++) R[i]=h[i];
+		return R;
+	}
+
+/* Hash number (optional) and string to array size of Bigs */
+
+	public static byte[] hashit(int sha,int n,byte[] B)
+	{
+		byte[] R=null;
+
+		if (sha==SHA256)
+		{
+			HASH256 H=new HASH256();
+			if (n>0) H.process_num(n);
+			H.process_array(B);
+			R=H.hash();
+		}
+		if (sha==SHA384)
+		{
+			HASH384 H=new HASH384();
+			if (n>0) H.process_num(n);
+			H.process_array(B);
+			R=H.hash();
+		}
+		if (sha==SHA512)
+		{
+			HASH512 H=new HASH512();
+			if (n>0) H.process_num(n);
+			H.process_array(B);
+			R=H.hash();
+		}
+		if (R==null) return null;
+		byte[] W=new byte[ROM.MODBYTES];
+
+		if (sha>=ROM.MODBYTES)
+			for (int i=0;i<ROM.MODBYTES;i++) W[i]=R[i];
+		else
+		{
+			for (int i=0;i<sha;i++) W[i]=R[i];
+			for (int i=sha;i<ROM.MODBYTES;i++) W[i]=0;
+		}
+		return W;
+	}
+
+	public static ECP mapit(byte[] h)
+	{
+		BIG q=new BIG(ROM.Modulus);
+		BIG x=BIG.fromBytes(h);
+		x.mod(q);
+		ECP P;
+		while (true)
+		{
+			P=new ECP(x,0);
+			if (!P.is_infinity()) break;
+			x.inc(1); x.norm();
+		}
+
+		if (ROM.CURVE_PAIRING_TYPE!=ROM.BN_CURVE)
+		{
+			BIG c=new BIG(ROM.CURVE_Cof);
+			P=P.mul(c);
+		}
+		return P;
+	}
+
+/* needed for SOK */
+	public static ECP2 mapit2(byte[] h)
+	{
+		BIG q=new BIG(ROM.Modulus);
+		BIG x=BIG.fromBytes(h);
+		BIG one=new BIG(1);
+		FP2 X;
+		ECP2 Q,T,K;
+		x.mod(q);
+		while (true)
+		{
+			X=new FP2(one,x);
+			Q=new ECP2(X);
+			if (!Q.is_infinity()) break;
+			x.inc(1); x.norm();
+		}
+/* Fast Hashing to G2 - Fuentes-Castaneda, Knapp and Rodriguez-Henriquez */
+		BIG Fra=new BIG(ROM.CURVE_Fra);
+		BIG Frb=new BIG(ROM.CURVE_Frb);
+		X=new FP2(Fra,Frb);
+		x=new BIG(ROM.CURVE_Bnx);
+
+		T=new ECP2(); T.copy(Q);
+		T.mul(x); T.neg();
+		K=new ECP2(); K.copy(T);
+		K.dbl(); K.add(T); K.affine();
+
+		K.frob(X);
+		Q.frob(X); Q.frob(X); Q.frob(X);
+		Q.add(T); Q.add(K);
+		T.frob(X); T.frob(X);
+		Q.add(T);
+		Q.affine();
+		return Q;
+	}
+
+/* return time in slots since epoch */
+	public static int today() {
+		Date date=new Date();
+		return (int) (date.getTime()/(1000*60*1440));
+	}
+
+/* these next two functions help to implement elligator squared - http://eprint.iacr.org/2014/043 */
+/* maps a random u to a point on the curve */
+	public static ECP map(BIG u,int cb)
+	{
+		ECP P;
+		BIG x=new BIG(u);
+		BIG p=new BIG(ROM.Modulus);
+		x.mod(p);
+		while (true)
+		{
+			P=new ECP(x,cb);
+			if (!P.is_infinity()) break;
+			x.inc(1);  x.norm();
+		}
+		return P;
+	}
+
+/* returns u derived from P. Random value in range 1 to return value should then be added to u */
+	public static int unmap(BIG u,ECP P)
+	{
+		int s=P.getS();
+		ECP R;
+		int r=0;
+		BIG x=P.getX();
+		u.copy(x);
+		while (true)
+		{
+			u.dec(1); u.norm();
+			r++;
+			R=new ECP(u,s);
+			if (!R.is_infinity()) break;
+		}
+		return r;
+	}
+
+	public static byte[] HASH_ID(int sha,byte[] ID)
+	{
+		return hashit(sha,0,ID);
+	}
+
+
+/* these next two functions implement elligator squared - http://eprint.iacr.org/2014/043 */
+/* Elliptic curve point E in format (0x04,x,y} is converted to form {0x0-,u,v} */
+/* Note that u and v are indistinguisible from random strings */
+	public static int ENCODING(RAND rng,byte[] E)
+	{
+		int rn,m,su,sv;
+		byte[] T=new byte[EFS];
+
+		for (int i=0;i<EFS;i++) T[i]=E[i+1];
+		BIG u=BIG.fromBytes(T);
+		for (int i=0;i<EFS;i++) T[i]=E[i+EFS+1];
+		BIG v=BIG.fromBytes(T);
+		
+		ECP P=new ECP(u,v);
+		if (P.is_infinity()) return INVALID_POINT;
+
+		BIG p=new BIG(ROM.Modulus);
+		u=BIG.randomnum(p,rng);
+
+		su=rng.getByte(); /*if (su<0) su=-su;*/ su%=2;
+		
+		ECP W=map(u,su);
+		P.sub(W);
+		sv=P.getS();
+		rn=unmap(v,P);
+		m=rng.getByte(); /*if (m<0) m=-m;*/ m%=rn;
+		v.inc(m+1);
+		E[0]=(byte)(su+2*sv);
+		u.toBytes(T);
+		for (int i=0;i<EFS;i++) E[i+1]=T[i];
+		v.toBytes(T);
+		for (int i=0;i<EFS;i++) E[i+EFS+1]=T[i];		
+		
+		return 0;
+	}
+
+	public static int DECODING(byte[] D)
+	{
+		int su,sv;
+		byte[] T=new byte[EFS];
+
+		if ((D[0]&0x04)!=0) return INVALID_POINT;
+
+		for (int i=0;i<EFS;i++) T[i]=D[i+1];
+		BIG u=BIG.fromBytes(T);
+		for (int i=0;i<EFS;i++) T[i]=D[i+EFS+1];
+		BIG v=BIG.fromBytes(T);
+
+		su=D[0]&1;
+		sv=(D[0]>>1)&1;
+		ECP W=map(u,su);
+		ECP P=map(v,sv);
+		P.add(W);
+		u=P.getX();
+		v=P.getY();
+		D[0]=0x04;
+		u.toBytes(T);
+		for (int i=0;i<EFS;i++) D[i+1]=T[i];
+		v.toBytes(T);
+		for (int i=0;i<EFS;i++) D[i+EFS+1]=T[i];		
+		
+		return 0;
+	}
+
+/* R=R1+R2 in group G1 */
+	public static int RECOMBINE_G1(byte[] R1,byte[] R2,byte[] R)
+	{
+		ECP P=ECP.fromBytes(R1);
+		ECP Q=ECP.fromBytes(R2);
+
+		if (P.is_infinity() || Q.is_infinity()) return INVALID_POINT;
+
+		P.add(Q);
+
+		P.toBytes(R);
+		return 0;
+	}
+
+/* W=W1+W2 in group G2 */
+	public static int RECOMBINE_G2(byte[] W1,byte[] W2,byte[] W)
+	{
+		ECP2 P=ECP2.fromBytes(W1);
+		ECP2 Q=ECP2.fromBytes(W2);
+
+		if (P.is_infinity() || Q.is_infinity()) return INVALID_POINT;
+
+		P.add(Q);
+	
+		P.toBytes(W);
+		return 0;
+	}
+	
+/* create random secret S */
+	public static int RANDOM_GENERATE(RAND rng,byte[] S)
+	{
+		BIG s;
+		BIG r=new BIG(ROM.CURVE_Order);
+		s=BIG.randomnum(r,rng);
+		if (ROM.AES_S>0)
+		{
+			s.mod2m(2*ROM.AES_S);
+		}
+		s.toBytes(S);
+		return 0;
+	}
+
+/* Extract PIN from TOKEN for identity CID */
+	public static int EXTRACT_PIN(int sha,byte[] CID,int pin,byte[] TOKEN)
+	{
+		ECP P=ECP.fromBytes(TOKEN);
+		if (P.is_infinity()) return INVALID_POINT;
+		byte[] h=hashit(sha,0,CID);
+		ECP R=mapit(h);
+
+
+		pin%=MAXPIN;
+
+		R=R.pinmul(pin,PBLEN);
+		P.sub(R);
+
+		P.toBytes(TOKEN);
+
+		return 0;
+	}
+
+/* Implement step 2 on client side of MPin protocol */
+	public static int CLIENT_2(byte[] X,byte[] Y,byte[] SEC)
+	{
+		BIG r=new BIG(ROM.CURVE_Order);
+		ECP P=ECP.fromBytes(SEC);
+		if (P.is_infinity()) return INVALID_POINT;
+
+		BIG px=BIG.fromBytes(X);
+		BIG py=BIG.fromBytes(Y);
+		px.add(py);
+		px.mod(r);
+	//	px.rsub(r);
+
+		P=PAIR.G1mul(P,px);
+		P.neg();
+		P.toBytes(SEC);
+		return 0;
+	}
+
+/* Implement step 1 on client side of MPin protocol */
+	public static int CLIENT_1(int sha,int date,byte[] CLIENT_ID,RAND rng,byte[] X,int pin,byte[] TOKEN,byte[] SEC,byte[] xID,byte[] xCID,byte[] PERMIT)
+	{
+		BIG r=new BIG(ROM.CURVE_Order);
+		BIG x;
+		if (rng!=null)
+		{
+			x=BIG.randomnum(r,rng);
+			if (ROM.AES_S>0)
+			{
+				x.mod2m(2*ROM.AES_S);
+			}
+			x.toBytes(X);
+		}
+		else
+		{
+			x=BIG.fromBytes(X);
+		}
+		ECP P,T,W;
+		BIG px;
+//		byte[] t=new byte[EFS];
+
+		byte[] h=hashit(sha,0,CLIENT_ID);
+		P=mapit(h);
+	
+		T=ECP.fromBytes(TOKEN);
+		if (T.is_infinity()) return INVALID_POINT;
+
+		pin%=MAXPIN;
+		W=P.pinmul(pin,PBLEN);
+		T.add(W);
+		if (date!=0)
+		{
+			W=ECP.fromBytes(PERMIT);
+			if (W.is_infinity()) return INVALID_POINT;
+			T.add(W);
+			h=hashit(sha,date,h);
+			W=mapit(h);
+			if (xID!=null)
+			{
+				P=PAIR.G1mul(P,x);
+				P.toBytes(xID);
+				W=PAIR.G1mul(W,x);
+				P.add(W);
+			}
+			else
+			{
+				P.add(W);
+				P=PAIR.G1mul(P,x);
+			}
+			if (xCID!=null) P.toBytes(xCID);
+		}
+		else
+		{
+			if (xID!=null)
+			{
+				P=PAIR.G1mul(P,x);
+				P.toBytes(xID);
+			}
+		}
+
+
+		T.toBytes(SEC);
+		return 0;
+	}
+
+/* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */
+	public static int GET_SERVER_SECRET(byte[] S,byte[] SST)
+	{
+		ECP2 Q=new ECP2(new FP2(new BIG(ROM.CURVE_Pxa),new BIG(ROM.CURVE_Pxb)),new FP2(new BIG(ROM.CURVE_Pya),new BIG(ROM.CURVE_Pyb)));
+
+		BIG s=BIG.fromBytes(S);
+		Q=PAIR.G2mul(Q,s);
+		Q.toBytes(SST);
+		return 0;
+	}
+
+/*
+ W=x*H(G);
+ if RNG == NULL then X is passed in 
+ if RNG != NULL the X is passed out 
+ if type=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve
+*/
+	public static int GET_G1_MULTIPLE(RAND rng, int type,byte[] X,byte[] G,byte[] W)
+	{
+		BIG x;
+		BIG r=new BIG(ROM.CURVE_Order);
+		if (rng!=null)
+		{
+			x=BIG.randomnum(r,rng);
+			if (ROM.AES_S>0)
+			{
+				x.mod2m(2*ROM.AES_S);
+			}
+			x.toBytes(X);
+		}
+		else
+		{
+			x=BIG.fromBytes(X);
+		}
+		ECP P;
+		if (type==0)
+		{
+			P=ECP.fromBytes(G);
+			if (P.is_infinity()) return INVALID_POINT;
+		}
+		else
+			P=mapit(G);
+
+		PAIR.G1mul(P,x).toBytes(W);
+		return 0;
+	}
+
+/* Client secret CST=S*H(CID) where CID is client ID and S is master secret */
+/* CID is hashed externally */
+	public static int GET_CLIENT_SECRET(byte[] S,byte[] CID,byte[] CST)
+	{
+		return GET_G1_MULTIPLE(null,1,S,CID,CST);
+	}
+
+/* Time Permit CTT=S*(date|H(CID)) where S is master secret */
+	public static int GET_CLIENT_PERMIT(int sha,int date,byte[] S,byte[] CID,byte[] CTT)
+	{
+		byte[] h=hashit(sha,date,CID);
+		ECP P=mapit(h);
+
+		BIG s=BIG.fromBytes(S);
+		PAIR.G1mul(P,s).toBytes(CTT);
+		return 0;
+	}
+
+/* Outputs H(CID) and H(T|H(CID)) for time permits. If no time permits set HID=HTID */
+	public static void SERVER_1(int sha,int date,byte[] CID,byte[] HID,byte[] HTID)
+	{
+		byte[] h=hashit(sha,0,CID);
+		ECP R,P=mapit(h);
+
+		P.toBytes(HID);   // new
+		if (date!=0)
+		{
+	//		if (HID!=null) P.toBytes(HID);
+			h=hashit(sha,date,h);
+			R=mapit(h);
+			P.add(R);
+			P.toBytes(HTID);
+		}
+	//	else P.toBytes(HID);
+	}
+
+/* Implement step 2 of MPin protocol on server side */
+	public static int SERVER_2(int date,byte[] HID,byte[] HTID,byte[] Y,byte[] SST,byte[] xID,byte[] xCID,byte[] mSEC,byte[] E,byte[] F)
+	{
+		BIG q=new BIG(ROM.Modulus);
+		ECP2 Q=new ECP2(new FP2(new BIG(ROM.CURVE_Pxa),new BIG(ROM.CURVE_Pxb)),new FP2(new BIG(ROM.CURVE_Pya),new BIG(ROM.CURVE_Pyb)));
+
+		ECP2 sQ=ECP2.fromBytes(SST);
+		if (sQ.is_infinity()) return INVALID_POINT;	
+
+		ECP R;
+		if (date!=0)
+			R=ECP.fromBytes(xCID);
+		else 
+		{
+			if (xID==null) return BAD_PARAMS;
+			R=ECP.fromBytes(xID);
+		}
+		if (R.is_infinity()) return INVALID_POINT;
+
+		BIG y=BIG.fromBytes(Y);
+		ECP P;
+		if (date!=0) P=ECP.fromBytes(HTID);
+		else 
+		{
+			if (HID==null) return BAD_PARAMS;
+			P=ECP.fromBytes(HID);
+		}
+	
+		if (P.is_infinity()) return INVALID_POINT;
+
+		P=PAIR.G1mul(P,y);
+		P.add(R);
+		R=ECP.fromBytes(mSEC);
+		if (R.is_infinity()) return INVALID_POINT;
+
+		FP12 g;
+
+		g=PAIR.ate2(Q,R,sQ,P);
+		g=PAIR.fexp(g);
+
+		if (!g.isunity())
+		{
+			if (HID!=null && xID!=null && E!=null && F!=null)
+			{
+				g.toBytes(E);
+				if (date!=0)
+				{
+					P=ECP.fromBytes(HID);
+					if (P.is_infinity()) return INVALID_POINT;
+					R=ECP.fromBytes(xID);
+					if (R.is_infinity()) return INVALID_POINT;
+
+					P=PAIR.G1mul(P,y);
+					P.add(R);
+				}
+				g=PAIR.ate(Q,P);
+				g=PAIR.fexp(g);
+				g.toBytes(F);
+			}
+			return BAD_PIN;
+		}
+
+		return 0;
+	}
+
+/* Pollards kangaroos used to return PIN error */
+	public static int KANGAROO(byte[] E,byte[] F)
+	{
+		FP12 ge=FP12.fromBytes(E);
+		FP12 gf=FP12.fromBytes(F);
+		int[] distance = new int[TS];
+		FP12 t=new FP12(gf);
+		FP12[] table=new FP12[TS];
+		int i,j,m,s,dn,dm,res,steps;
+
+		s=1;
+		for (m=0;m<TS;m++)
+		{
+			distance[m]=s;
+			table[m]=new FP12(t);
+			s*=2;
+			t.usqr();
+		}
+		t.one();
+		dn=0;
+		for (j=0;j<TRAP;j++)
+		{
+			i=t.geta().geta().getA().lastbits(20)%TS;
+			t.mul(table[i]);
+			dn+=distance[i];
+		}
+		gf.copy(t); gf.conj();
+		steps=0; dm=0;
+		res=0;
+		while (dm-dn<MAXPIN)
+		{
+			steps++;
+			if (steps>4*TRAP) break;
+			i=ge.geta().geta().getA().lastbits(20)%TS;
+			ge.mul(table[i]);
+			dm+=distance[i];
+			if (ge.equals(t))
+			{
+				res=dm-dn;
+				break;
+			}
+			if (ge.equals(gf))
+			{
+				res=dn-dm;
+				break;
+			}
+
+		}
+		if (steps>4*TRAP || dm-dn>=MAXPIN) {res=0; }    // Trap Failed  - probable invalid token
+		return res;
+	}
+
+/* Functions to support M-Pin Full */
+
+	public static int PRECOMPUTE(byte[] TOKEN,byte[] CID,byte[] G1,byte[] G2)
+	{
+		ECP P,T;
+		FP12 g;
+
+		T=ECP.fromBytes(TOKEN);
+		if (T.is_infinity()) return INVALID_POINT; 
+
+		P=mapit(CID);
+
+		ECP2 Q=new ECP2(new FP2(new BIG(ROM.CURVE_Pxa),new BIG(ROM.CURVE_Pxb)),new FP2(new BIG(ROM.CURVE_Pya),new BIG(ROM.CURVE_Pyb)));
+
+		g=PAIR.ate(Q,T);
+		g=PAIR.fexp(g);
+		g.toBytes(G1);
+
+		g=PAIR.ate(Q,P);
+		g=PAIR.fexp(g);
+		g.toBytes(G2);
+
+		return 0;
+	}
+
+/* Hash the M-Pin transcript - new */
+
+	public static byte[] HASH_ALL(int sha,byte[] HID,byte[] xID,byte[] xCID,byte[] SEC,byte[] Y,byte[] R,byte[] W)
+	{
+		int i,tlen=0;
+		byte[] T = new byte[10*ROM.MODBYTES+4];
+
+		for (i=0;i<HID.length;i++) T[i]=HID[i];
+		tlen+=HID.length;
+		if (xCID!=null)
+		{
+			for (i=0;i<xCID.length;i++) T[i+tlen]=xCID[i];
+			tlen+=xCID.length;
+		}	
+		else
+		{
+			for (i=0;i<xID.length;i++) T[i+tlen]=xID[i];
+			tlen+=xID.length;
+		}	
+		for (i=0;i<SEC.length;i++) T[i+tlen]=SEC[i];
+		tlen+=SEC.length;		
+		for (i=0;i<Y.length;i++) T[i+tlen]=Y[i];
+		tlen+=Y.length;	
+		for (i=0;i<R.length;i++) T[i+tlen]=R[i];
+		tlen+=R.length;		
+		for (i=0;i<W.length;i++) T[i+tlen]=W[i];
+		tlen+=W.length;		
+
+		return hashit(sha,0,T);
+	}
+
+/* calculate common key on client side */
+/* wCID = w.(A+AT) */
+	public static int CLIENT_KEY(int sha,byte[] G1,byte[] G2,int pin,byte[] R,byte[] X,byte[] H,byte[] wCID,byte[] CK)
+	{
+		byte[] t;
+
+		FP12 g1=FP12.fromBytes(G1);
+		FP12 g2=FP12.fromBytes(G2);
+		BIG z=BIG.fromBytes(R);
+		BIG x=BIG.fromBytes(X);
+		BIG h=BIG.fromBytes(H);
+
+		ECP W=ECP.fromBytes(wCID);
+		if (W.is_infinity()) return INVALID_POINT; 
+
+		W=PAIR.G1mul(W,x);
+
+		FP2 f=new FP2(new BIG(ROM.CURVE_Fra),new BIG(ROM.CURVE_Frb));
+		BIG r=new BIG(ROM.CURVE_Order);
+		BIG q=new BIG(ROM.Modulus);
+
+		z.add(h);	//new
+		z.mod(r);
+
+		BIG m=new BIG(q);
+		m.mod(r);
+
+		BIG a=new BIG(z);
+		a.mod(m);
+
+		BIG b=new BIG(z);
+		b.div(m);
+
+		g2.pinpow(pin,PBLEN);
+		g1.mul(g2);
+
+		FP4 c=g1.trace();
+		g2.copy(g1);
+		g2.frob(f);
+		FP4 cp=g2.trace();
+		g1.conj();
+		g2.mul(g1);
+		FP4 cpm1=g2.trace();
+		g2.mul(g1);
+		FP4 cpm2=g2.trace();
+
+		c=c.xtr_pow2(cp,cpm1,cpm2,a,b);
+
+		t=mpin_hash(sha,c,W);
+
+		for (int i=0;i<PAS;i++) CK[i]=t[i];
+
+		return 0;
+	}
+
+/* calculate common key on server side */
+/* Z=r.A - no time permits involved */
+
+	public static int SERVER_KEY(int sha,byte[] Z,byte[] SST,byte[] W,byte[] H,byte[] HID,byte[] xID,byte[] xCID,byte[] SK)
+	{
+		byte[] t;
+
+		ECP2 sQ=ECP2.fromBytes(SST);
+		if (sQ.is_infinity()) return INVALID_POINT; 
+		ECP R=ECP.fromBytes(Z);
+		if (R.is_infinity()) return INVALID_POINT; 
+		ECP A=ECP.fromBytes(HID);
+		if (A.is_infinity()) return INVALID_POINT; 
+
+		ECP U;
+		if (xCID!=null)
+			U=ECP.fromBytes(xCID);
+		else
+			U=ECP.fromBytes(xID);
+		if (U.is_infinity()) return INVALID_POINT; 
+
+		BIG w=BIG.fromBytes(W);
+		BIG h=BIG.fromBytes(H);
+		A=PAIR.G1mul(A,h);	// new
+		R.add(A);
+
+		U=PAIR.G1mul(U,w);
+		FP12 g=PAIR.ate(sQ,R);
+		g=PAIR.fexp(g);
+
+		FP4 c=g.trace();
+
+		t=mpin_hash(sha,c,U);
+
+		for (int i=0;i<PAS;i++) SK[i]=t[i];
+
+		return 0;
+	}
+
+/* return time since epoch */
+	public static int GET_TIME() {
+		Date date=new Date();
+		return (int) (date.getTime()/1000);
+	}
+
+/* Generate Y = H(epoch, xCID/xID) */
+	public static void GET_Y(int sha,int TimeValue,byte[] xCID,byte[] Y)
+	{
+		byte[] h = hashit(sha,TimeValue,xCID);
+		BIG y = BIG.fromBytes(h);
+		BIG q=new BIG(ROM.CURVE_Order);
+		y.mod(q);
+		if (ROM.AES_S>0)
+		{
+			y.mod2m(2*ROM.AES_S);
+		}
+		y.toBytes(Y);
+	}
+        
+/* One pass MPIN Client */
+        public static int CLIENT(int sha,int date,byte[] CLIENT_ID,RAND RNG,byte[] X,int pin,byte[] TOKEN,byte[] SEC,byte[] xID,byte[] xCID,byte[] PERMIT, int TimeValue, byte[] Y)
+        {
+          int rtn=0;
+        
+          byte[] pID;
+          if (date == 0)
+            pID = xID;
+          else
+            pID = xCID;
+          
+          rtn = CLIENT_1(sha,date,CLIENT_ID,RNG,X,pin,TOKEN,SEC,xID,xCID,PERMIT);
+          if (rtn != 0)
+            return rtn;
+        
+          GET_Y(sha,TimeValue,pID,Y);
+        
+          rtn = CLIENT_2(X,Y,SEC);
+          if (rtn != 0)
+            return rtn;
+        
+          return 0;
+        }
+        
+/* One pass MPIN Server */
+        public static int SERVER(int sha,int date,byte[] HID,byte[] HTID,byte[] Y,byte[] SST,byte[] xID,byte[] xCID,byte[] SEC,byte[] E,byte[] F,byte[] CID, int TimeValue)
+        {
+          int rtn=0;
+        
+          byte[] pID;
+          if (date == 0)
+            pID = xID;
+          else
+            pID = xCID;
+          
+          SERVER_1(sha,date,CID,HID,HTID);
+        
+          GET_Y(sha,TimeValue,pID,Y);
+          
+          rtn = SERVER_2(date,HID,HTID,Y,SST,xID,xCID,SEC,E,F);
+          if (rtn != 0)
+            return rtn;
+        
+          return 0;
+        }
+        
+}
diff --git a/version22/java/PAIR.java b/version22/java/PAIR.java
new file mode 100644
index 0000000..518f3ae
--- /dev/null
+++ b/version22/java/PAIR.java
@@ -0,0 +1,685 @@
+/*
+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.
+*/
+
+/* AMCL BN Curve Pairing functions */
+
+public final class PAIR {
+
+/* Line function */
+	public static FP12 line(ECP2 A,ECP2 B,FP Qx,FP Qy)
+	{
+		ECP2 P=new ECP2();
+
+		FP4 a,b,c;
+		P.copy(A);
+		FP2 ZZ=new FP2(P.getz());
+		ZZ.sqr();
+		int D;
+		if (A==B) D=A.dbl(); /* Check this return value in ecp2.c */
+		else D=A.add(B);
+		if (D<0) 
+			return new FP12(1);
+		FP2 Z3=new FP2(A.getz());
+		c=new FP4(0);
+		if (D==0)
+		{ /* Addition */
+			FP2 X=new FP2(B.getx());
+			FP2 Y=new FP2(B.gety());
+			FP2 T=new FP2(P.getz()); 
+			T.mul(Y);
+			ZZ.mul(T);
+
+			FP2 NY=new FP2(P.gety()); NY.neg();
+			ZZ.add(NY);
+			Z3.pmul(Qy);
+			T.mul(P.getx());
+			X.mul(NY);
+			T.add(X);
+			a=new FP4(Z3,T);
+			ZZ.neg();
+			ZZ.pmul(Qx);
+			b=new FP4(ZZ);
+		}
+		else
+		{ /* Doubling */
+			FP2 X=new FP2(P.getx());
+			FP2 Y=new FP2(P.gety());
+			FP2 T=new FP2(P.getx());
+			T.sqr();
+			T.imul(3);
+
+			Y.sqr();
+			Y.add(Y);
+			Z3.mul(ZZ);
+			Z3.pmul(Qy);
+
+			X.mul(T);
+			X.sub(Y);
+			a=new FP4(Z3,X);
+			T.neg();
+			ZZ.mul(T);
+			ZZ.pmul(Qx);
+			b=new FP4(ZZ);
+		}
+		return new FP12(a,b,c);
+	}
+
+/* Optimal R-ate pairing */
+	public static FP12 ate(ECP2 P,ECP Q)
+	{
+		FP2 f=new FP2(new BIG(ROM.CURVE_Fra),new BIG(ROM.CURVE_Frb));
+		BIG x=new BIG(ROM.CURVE_Bnx);
+		BIG n=new BIG(x);
+		ECP2 K=new ECP2();
+		FP12 lv;
+
+		if (ROM.CURVE_PAIRING_TYPE==ROM.BN_CURVE)
+		{
+			n.pmul(6); n.dec(2);
+		}
+		else
+			n.copy(x);
+		n.norm();
+		
+		P.affine();
+		Q.affine();
+		FP Qx=new FP(Q.getx());
+		FP Qy=new FP(Q.gety());
+
+		ECP2 A=new ECP2();
+		FP12 r=new FP12(1);
+
+		A.copy(P);
+		int nb=n.nbits();
+
+		for (int i=nb-2;i>=1;i--)
+		{
+			lv=line(A,A,Qx,Qy);
+			r.smul(lv);
+
+			if (n.bit(i)==1)
+			{
+				lv=line(A,P,Qx,Qy);
+				r.smul(lv);
+			}
+			r.sqr();
+		}
+
+		lv=line(A,A,Qx,Qy);
+		r.smul(lv);
+		if (n.parity()==1)
+		{
+			lv=line(A,P,Qx,Qy);
+			r.smul(lv);
+		}
+
+/* R-ate fixup required for BN curves */
+		if (ROM.CURVE_PAIRING_TYPE==ROM.BN_CURVE)
+		{
+			r.conj();
+			K.copy(P);
+			K.frob(f);
+			A.neg();
+			lv=line(A,K,Qx,Qy);
+			r.smul(lv);
+			K.frob(f);
+			K.neg();
+			lv=line(A,K,Qx,Qy);
+			r.smul(lv);
+		}
+		return r;
+	}
+
+/* Optimal R-ate double pairing e(P,Q).e(R,S) */
+	public static FP12 ate2(ECP2 P,ECP Q,ECP2 R,ECP S)
+	{
+		FP2 f=new FP2(new BIG(ROM.CURVE_Fra),new BIG(ROM.CURVE_Frb));
+		BIG x=new BIG(ROM.CURVE_Bnx);
+		BIG n=new BIG(x);
+		ECP2 K=new ECP2();
+		FP12 lv;
+
+		if (ROM.CURVE_PAIRING_TYPE==ROM.BN_CURVE)
+		{
+			n.pmul(6); n.dec(2);
+		}
+		else
+			n.copy(x);
+		n.norm();
+
+		P.affine();
+		Q.affine();
+		R.affine();
+		S.affine();
+
+		FP Qx=new FP(Q.getx());
+		FP Qy=new FP(Q.gety());
+		FP Sx=new FP(S.getx());
+		FP Sy=new FP(S.gety());
+
+		ECP2 A=new ECP2();
+		ECP2 B=new ECP2();
+		FP12 r=new FP12(1);
+
+		A.copy(P);
+		B.copy(R);
+		int nb=n.nbits();
+
+		for (int i=nb-2;i>=1;i--)
+		{
+			lv=line(A,A,Qx,Qy);
+			r.smul(lv);
+			lv=line(B,B,Sx,Sy);
+			r.smul(lv);
+
+			if (n.bit(i)==1)
+			{
+				lv=line(A,P,Qx,Qy);
+				r.smul(lv);
+				lv=line(B,R,Sx,Sy);
+				r.smul(lv);
+			}
+			r.sqr();
+		}
+
+		lv=line(A,A,Qx,Qy);
+		r.smul(lv);
+		lv=line(B,B,Sx,Sy);
+		r.smul(lv);
+		if (n.parity()==1)
+		{
+			lv=line(A,P,Qx,Qy);
+			r.smul(lv);
+			lv=line(B,R,Sx,Sy);
+			r.smul(lv);
+		}
+
+/* R-ate fixup required for BN curves */
+		if (ROM.CURVE_PAIRING_TYPE==ROM.BN_CURVE)
+		{
+			r.conj();
+			K.copy(P);
+			K.frob(f);
+			A.neg();
+			lv=line(A,K,Qx,Qy);
+			r.smul(lv);
+			K.frob(f);
+			K.neg();
+			lv=line(A,K,Qx,Qy);
+			r.smul(lv);
+
+			K.copy(R);
+			K.frob(f);
+			B.neg();
+			lv=line(B,K,Sx,Sy);
+			r.smul(lv);
+			K.frob(f);
+			K.neg();
+			lv=line(B,K,Sx,Sy);
+			r.smul(lv);
+		}
+		return r;
+	}
+
+/* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */
+	public static FP12 fexp(FP12 m)
+	{
+		FP2 f=new FP2(new BIG(ROM.CURVE_Fra),new BIG(ROM.CURVE_Frb));
+		BIG x=new BIG(ROM.CURVE_Bnx);
+		FP12 r=new FP12(m);
+
+/* Easy part of final exp */
+		FP12 lv=new FP12(r);
+		lv.inverse();
+		r.conj();
+
+		r.mul(lv);
+		lv.copy(r);
+		r.frob(f);
+		r.frob(f);
+		r.mul(lv);
+/* Hard part of final exp */
+		if (ROM.CURVE_PAIRING_TYPE==ROM.BN_CURVE)
+		{
+			FP12 x0,x1,x2,x3,x4,x5;			
+			lv.copy(r);
+			lv.frob(f);
+			x0=new FP12(lv);
+			x0.frob(f);
+			lv.mul(r);
+			x0.mul(lv);
+			x0.frob(f);
+			x1=new FP12(r);
+			x1.conj();
+			x4=r.pow(x);
+
+			x3=new FP12(x4);
+			x3.frob(f);
+
+			x2=x4.pow(x);
+
+			x5=new FP12(x2); x5.conj();
+			lv=x2.pow(x);
+
+			x2.frob(f);
+			r.copy(x2); r.conj();
+
+			x4.mul(r);
+			x2.frob(f);
+
+			r.copy(lv);
+			r.frob(f);
+			lv.mul(r);
+
+			lv.usqr();
+			lv.mul(x4);
+			lv.mul(x5);
+			r.copy(x3);
+			r.mul(x5);
+			r.mul(lv);
+			lv.mul(x2);
+			r.usqr();
+			r.mul(lv);
+			r.usqr();
+			lv.copy(r);
+			lv.mul(x1);
+			r.mul(x0);
+			lv.usqr();
+			r.mul(lv);
+			r.reduce();
+		}
+		else
+		{
+
+			FP12 y0,y1,y2,y3;
+// Ghamman & Fouotsa Method
+			y0=new FP12(r); y0.usqr();
+			y1=y0.pow(x);
+			x.fshr(1); y2=y1.pow(x); x.fshl(1);
+			y3=new FP12(r); y3.conj();
+			y1.mul(y3);
+
+			y1.conj();
+			y1.mul(y2);
+
+			y2=y1.pow(x);
+
+			y3=y2.pow(x);
+			y1.conj();
+			y3.mul(y1);
+
+			y1.conj();
+			y1.frob(f); y1.frob(f); y1.frob(f);
+			y2.frob(f); y2.frob(f);
+			y1.mul(y2);
+
+			y2=y3.pow(x);
+			y2.mul(y0);
+			y2.mul(r);
+
+			y1.mul(y2);
+			y2.copy(y3); y2.frob(f);
+			y1.mul(y2);
+			r.copy(y1);
+			r.reduce();
+
+/*
+			x0=new FP12(r);
+			x1=new FP12(r);
+			lv.copy(r); lv.frob(f);
+			x3=new FP12(lv); x3.conj(); x1.mul(x3);
+			lv.frob(f); lv.frob(f);
+			x1.mul(lv);
+
+			r.copy(r.pow(x));  //r=r.pow(x);
+			x3.copy(r); x3.conj(); x1.mul(x3);
+			lv.copy(r); lv.frob(f);
+			x0.mul(lv);
+			lv.frob(f);
+			x1.mul(lv);
+			lv.frob(f);
+			x3.copy(lv); x3.conj(); x0.mul(x3);
+
+			r.copy(r.pow(x));
+			x0.mul(r);
+			lv.copy(r); lv.frob(f); lv.frob(f);
+			x3.copy(lv); x3.conj(); x0.mul(x3);
+			lv.frob(f);
+			x1.mul(lv);
+
+			r.copy(r.pow(x));
+			lv.copy(r); lv.frob(f);
+			x3.copy(lv); x3.conj(); x0.mul(x3);
+			lv.frob(f);
+			x1.mul(lv);
+
+			r.copy(r.pow(x));
+			x3.copy(r); x3.conj(); x0.mul(x3);
+			lv.copy(r); lv.frob(f);
+			x1.mul(lv);
+
+			r.copy(r.pow(x));
+			x1.mul(r);
+
+			x0.usqr();
+			x0.mul(x1);
+			r.copy(x0);
+			r.reduce(); */
+		}
+		
+		return r;
+	}
+
+/* GLV method */
+	public static BIG[] glv(BIG e)
+	{
+		BIG[] u=new BIG[2];
+		if (ROM.CURVE_PAIRING_TYPE==ROM.BN_CURVE)
+		{
+			int i,j;
+			BIG t=new BIG(0);
+			BIG q=new BIG(ROM.CURVE_Order);
+
+			BIG[] v=new BIG[2];
+			for (i=0;i<2;i++)
+			{
+				t.copy(new BIG(ROM.CURVE_W[i]));  // why not just t=new BIG(ROM.CURVE_W[i]); 
+				DBIG d=BIG.mul(t,e);
+				v[i]=new BIG(d.div(q));
+				u[i]=new BIG(0);
+			}
+			u[0].copy(e);
+			for (i=0;i<2;i++)
+				for (j=0;j<2;j++)
+				{
+					t.copy(new BIG(ROM.CURVE_SB[j][i]));
+					t.copy(BIG.modmul(v[j],t,q));
+					u[i].add(q);
+					u[i].sub(t);
+					u[i].mod(q);
+				}
+		}
+		else
+		{ // -(x^2).P = (Beta.x,y)
+			BIG q=new BIG(ROM.CURVE_Order);
+			BIG x=new BIG(ROM.CURVE_Bnx);
+			BIG x2=BIG.smul(x,x);
+			u[0]=new BIG(e);
+			u[0].mod(x2);
+			u[1]=new BIG(e);
+			u[1].div(x2);
+			u[1].rsub(q);
+		}
+		return u;
+	}
+
+/* Galbraith & Scott Method */
+	public static BIG[] gs(BIG e)
+	{
+		BIG[] u=new BIG[4];
+		if (ROM.CURVE_PAIRING_TYPE==ROM.BN_CURVE)
+		{
+			int i,j;
+			BIG t=new BIG(0);
+			BIG q=new BIG(ROM.CURVE_Order);
+			BIG[] v=new BIG[4];
+			for (i=0;i<4;i++)
+			{
+				t.copy(new BIG(ROM.CURVE_WB[i]));
+				DBIG d=BIG.mul(t,e);
+				v[i]=new BIG(d.div(q));
+				u[i]=new BIG(0);
+			}
+			u[0].copy(e);
+			for (i=0;i<4;i++)
+				for (j=0;j<4;j++)
+				{
+					t.copy(new BIG(ROM.CURVE_BB[j][i]));
+					t.copy(BIG.modmul(v[j],t,q));
+					u[i].add(q);
+					u[i].sub(t);
+					u[i].mod(q);
+				}
+		}
+		else
+		{
+			BIG x=new BIG(ROM.CURVE_Bnx);
+			BIG w=new BIG(e);
+			for (int i=0;i<4;i++)
+			{
+				u[i]=new BIG(w);
+				u[i].mod(x);
+				w.div(x);
+			}
+		}
+		return u;
+	}	
+
+/* Multiply P by e in group G1 */
+	public static ECP G1mul(ECP P,BIG e)
+	{
+		ECP R;
+		if (ROM.USE_GLV)
+		{
+			P.affine();
+			R=new ECP();
+			R.copy(P);
+			int i,np,nn;
+			ECP Q=new ECP();
+			Q.copy(P);
+			BIG q=new BIG(ROM.CURVE_Order);
+			FP cru=new FP(new BIG(ROM.CURVE_Cru));
+			BIG t=new BIG(0);
+			BIG[] u=glv(e);
+			Q.getx().mul(cru);
+
+			np=u[0].nbits();
+			t.copy(BIG.modneg(u[0],q));
+			nn=t.nbits();
+			if (nn<np)
+			{
+				u[0].copy(t);
+				R.neg();
+			}
+
+			np=u[1].nbits();
+			t.copy(BIG.modneg(u[1],q));
+			nn=t.nbits();
+			if (nn<np)
+			{
+				u[1].copy(t);
+				Q.neg();
+			}
+
+			R=R.mul2(u[0],Q,u[1]);
+			
+		}
+		else
+		{
+			R=P.mul(e);
+		}
+		return R;
+	}
+
+/* Multiply P by e in group G2 */
+	public static ECP2 G2mul(ECP2 P,BIG e)
+	{
+		ECP2 R;
+		if (ROM.USE_GS_G2)
+		{
+			ECP2[] Q=new ECP2[4];
+			FP2 f=new FP2(new BIG(ROM.CURVE_Fra),new BIG(ROM.CURVE_Frb));
+			BIG q=new BIG(ROM.CURVE_Order);
+			BIG[] u=gs(e);
+
+
+
+			BIG t=new BIG(0);
+			int i,np,nn;
+			P.affine();
+			Q[0]=new ECP2(); Q[0].copy(P);
+			for (i=1;i<4;i++)
+			{
+				Q[i]=new ECP2(); Q[i].copy(Q[i-1]);
+				Q[i].frob(f);
+			}
+			for (i=0;i<4;i++)
+			{
+				np=u[i].nbits();
+				t.copy(BIG.modneg(u[i],q));
+				nn=t.nbits();
+				if (nn<np)
+				{
+					u[i].copy(t);
+					Q[i].neg();
+				}
+			}
+
+			R=ECP2.mul4(Q,u);
+		}
+		else
+		{
+			R=P.mul(e);
+		}
+		return R;
+	}
+
+/* f=f^e */
+/* Note that this method requires a lot of RAM! Better to use compressed XTR method, see FP4.java */
+	public static FP12 GTpow(FP12 d,BIG e)
+	{
+		FP12 r;
+		if (ROM.USE_GS_GT)
+		{
+			FP12[] g=new FP12[4];
+			FP2 f=new FP2(new BIG(ROM.CURVE_Fra),new BIG(ROM.CURVE_Frb));
+			BIG q=new BIG(ROM.CURVE_Order);
+			BIG t=new BIG(0);
+			int i,np,nn;
+			BIG[] u=gs(e);
+
+			g[0]=new FP12(d);
+			for (i=1;i<4;i++)
+			{
+				g[i]=new FP12(0); g[i].copy(g[i-1]);
+				g[i].frob(f);
+			}
+			for (i=0;i<4;i++)
+			{
+				np=u[i].nbits();
+				t.copy(BIG.modneg(u[i],q));
+				nn=t.nbits();
+				if (nn<np)
+				{
+					u[i].copy(t);
+					g[i].conj();
+				}
+			}
+			r=FP12.pow4(g,u);
+		}
+		else
+		{
+			r=d.pow(e);
+		}
+		return r;
+	}
+
+/* test group membership - no longer needed */
+/* with GT-Strong curve, now only check that m!=1, conj(m)*m==1, and m.m^{p^4}=m^{p^2} */
+/*
+	public static boolean GTmember(FP12 m)
+	{
+		if (m.isunity()) return false;
+		FP12 r=new FP12(m);
+		r.conj();
+		r.mul(m);
+		if (!r.isunity()) return false;
+
+		FP2 f=new FP2(new BIG(ROM.CURVE_Fra),new BIG(ROM.CURVE_Frb));
+
+		r.copy(m); r.frob(f); r.frob(f);
+		FP12 w=new FP12(r); w.frob(f); w.frob(f);
+		w.mul(m);
+		if (!ROM.GT_STRONG)
+		{
+			if (!w.equals(r)) return false;
+			BIG x=new BIG(ROM.CURVE_Bnx);
+			r.copy(m); w=r.pow(x); w=w.pow(x);
+			r.copy(w); r.sqr(); r.mul(w); r.sqr();
+			w.copy(m); w.frob(f);
+		}
+		return w.equals(r);
+	}
+*/
+/*
+	public static void main(String[] args) {
+		ECP Q=new ECP(new BIG(ROM.CURVE_Gx),new BIG(ROM.CURVE_Gy));
+		ECP2 P=new ECP2(new FP2(new BIG(ROM.CURVE_Pxa),new BIG(ROM.CURVE_Pxb)),new FP2(new BIG(ROM.CURVE_Pya),new BIG(ROM.CURVE_Pyb)));
+
+		BIG r=new BIG(ROM.CURVE_Order);
+		BIG xa=new BIG(ROM.CURVE_Pxa);
+
+		System.out.println("P= "+P.toString());
+		System.out.println("Q= "+Q.toString());
+
+		BIG m=new BIG(17);
+
+		FP12 e=ate(P,Q);
+		System.out.println("\ne= "+e.toString());
+
+		e=fexp(e);
+
+		for (int i=1;i<1000;i++)
+		{
+			e=ate(P,Q);
+			e=fexp(e);
+		}
+	//	e=GTpow(e,m);
+
+		System.out.println("\ne= "+e.toString());
+
+		BIG [] GLV=glv(r);
+
+		System.out.println("GLV[0]= "+GLV[0].toString());
+		System.out.println("GLV[0]= "+GLV[1].toString());
+
+		ECP G=new ECP(); G.copy(Q);
+		ECP2 R=new ECP2(); R.copy(P);
+
+
+		e=ate(R,Q);
+		e=fexp(e);
+
+		e=GTpow(e,xa);
+		System.out.println("\ne= "+e.toString()); 
+
+
+		R=G2mul(R,xa);
+		e=ate(R,G);
+		e=fexp(e);
+
+		System.out.println("\ne= "+e.toString());
+
+		G=G1mul(G,xa);
+		e=ate(P,G);
+		e=fexp(e);
+		System.out.println("\ne= "+e.toString()); 
+	} */
+}
+
diff --git a/version22/java/RAND.java b/version22/java/RAND.java
new file mode 100644
index 0000000..7494eff
--- /dev/null
+++ b/version22/java/RAND.java
@@ -0,0 +1,161 @@
+/*
+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.
+*/
+
+/*
+ *   Cryptographic strong random number generator 
+ *
+ *   Unguessable seed -> SHA -> PRNG internal state -> SHA -> random numbers
+ *   Slow - but secure
+ *
+ *   See ftp://ftp.rsasecurity.com/pub/pdfs/bull-1.pdf for a justification
+ */
+
+/* Marsaglia & Zaman Random number generator constants */
+
+
+public class RAND {
+/* Cryptographically strong pseudo-random number generator */
+
+	private static final int NK=21;
+	private static final int NJ=6;
+	private static final int NV=8;
+	private int[] ira=new int[NK];  /* random number...   */
+	private int rndptr;   /* ...array & pointer */
+	private int borrow;
+	private int pool_ptr;
+	private byte[] pool=new byte[32];    /* random pool */
+
+	public RAND()
+	{
+		clean();
+	}
+
+	private int sbrand()
+	{ /* Marsaglia & Zaman random number generator */
+		int i,k;
+		long pdiff,t;
+
+		rndptr++;
+		if (rndptr<NK) return ira[rndptr];
+		rndptr=0;
+		for (i=0,k=NK-NJ;i<NK;i++,k++)
+		{ /* calculate next NK values */
+			if (k==NK) k=0;
+			t=((long)ira[k])&0xffffffffL;
+			pdiff=(t - (((long)ira[i])&0xffffffffL) - (long)borrow)&0xffffffffL;
+			if (pdiff<t) borrow=0;
+			if (pdiff>t) borrow=1;
+			ira[i]=(int)(pdiff&0xffffffffL); 
+		}
+
+		return ira[0];
+	}
+
+	public void sirand(int seed)
+	{
+		int i,in;
+		int t,m=1;
+		borrow=0;
+		rndptr=0;
+		ira[0]^=seed;
+		for (i=1;i<NK;i++)
+		{ /* fill initialisation vector */
+			in=(NV*i)%NK;
+			ira[in]^=m;      /* note XOR */
+			t=m;
+			m=seed-m;
+			seed=t;
+		}
+		for (i=0;i<10000;i++) sbrand(); /* "warm-up" & stir the generator */
+	}
+
+	private void fill_pool()
+	{
+		HASH256 sh=new HASH256();
+		for (int i=0;i<128;i++) sh.process(sbrand());
+		pool=sh.hash();
+		pool_ptr=0;
+	}
+
+	private static int pack(byte[] b)
+	{ /* pack 4 bytes into a 32-bit Word */
+		return ((((int)b[3])&0xff)<<24)|(((int)b[2]&0xff)<<16)|(((int)b[1]&0xff)<<8)|((int)b[0]&0xff);
+	}
+
+/* Initialize RNG with some real entropy from some external source */
+	public void seed(int rawlen,byte[] raw)
+	{ /* initialise from at least 128 byte string of raw random entropy */
+		int i;
+		byte [] digest;
+		byte [] b=new byte[4];
+		HASH256 sh=new HASH256();
+		pool_ptr=0;
+		for (i=0;i<NK;i++) ira[i]=0;
+		if (rawlen>0)
+		{
+			for (i=0;i<rawlen;i++)
+				sh.process(raw[i]);
+			digest=sh.hash();
+
+/* initialise PRNG from distilled randomness */
+
+			for (i=0;i<8;i++) 
+			{
+				b[0]=digest[4*i]; b[1]=digest[4*i+1]; b[2]=digest[4*i+2]; b[3]=digest[4*i+3];
+				sirand(pack(b));
+			}
+		}
+		fill_pool();
+	}
+
+/* Terminate and clean up */
+	public void clean()
+	{ /* kill internal state */
+		int i;
+		pool_ptr=rndptr=0;
+		for (i=0;i<32;i++) pool[i]=0;
+		for (i=0;i<NK;i++) ira[i]=0;
+		borrow=0;
+	}
+
+/* get random byte */
+	public int getByte()
+	{ 
+		int r;
+		r=pool[pool_ptr++];
+		if (pool_ptr>=32) fill_pool();
+		return (r&0xff);
+	}
+
+/* test main program */
+/*
+	public static void main(String[] args) {
+		int i;
+		byte[] raw=new byte[100];
+		RAND rng=new RAND();
+
+		rng.clean();
+		for (i=0;i<100;i++) raw[i]=(byte)i;
+
+		rng.seed(100,raw);
+ 
+		for (i=0;i<1000;i++)
+			System.out.format("%03d ",rng.getByte());
+	} */
+}
diff --git a/version22/java/ROM32.java b/version22/java/ROM32.java
new file mode 100644
index 0000000..db75cdc
--- /dev/null
+++ b/version22/java/ROM32.java
@@ -0,0 +1,714 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+public class ROM
+{
+/* Don't Modify from here... */
+
+	public static final int CHUNK=32; /* Set word size */
+	public static final int NOT_SPECIAL=0;
+	public static final int PSEUDO_MERSENNE=1;
+	public static final int MONTGOMERY_FRIENDLY=2;
+	public static final int GENERALISED_MERSENNE=3;
+	public static final int WEIERSTRASS=0;
+	public static final int EDWARDS=1;
+	public static final int MONTGOMERY=2;
+	public static final int BN_CURVE=0;
+	public static final int BLS_CURVE=1;
+
+/* ...to here */
+
+/*** Enter Some Field details here  ***/
+// BN254 Curve
+//	public static final int MODBITS=254; /* Number of bits in Modulus */
+//	public static final int MOD8=3;  /* Modulus mod 8 */
+//	public static final int BASEBITS=29; /* Almost always 29, 28 for NIST521 */
+//	public static final int AES_S=0;  /* AES equivalaent strength if significantly less than group size */
+
+// BLS383 Curve
+	public static final int MODBITS=383; /* Number of bits in Modulus */
+	public static final int MOD8=3;  /* Modulus mod 8 */
+	public static final int BASEBITS=28; /* Almost always 29 or 28  */
+	public static final int AES_S=0;
+
+// BLS455 Curve
+//	public static final int MODBITS=455; /* Number of bits in Modulus */
+//	public static final int MOD8=3;  /* Modulus mod 8 */
+//	public static final int BASEBITS=29; /* Almost always 29, 28 for NIST521 */
+//	public static final int AES_S=128;
+
+// BN454 Curve
+//	public static final int MODBITS=454; /* Number of bits in Modulus */
+//	public static final int MOD8=3;  /* Modulus mod 8 */
+//	public static final int BASEBITS=29; /* Almost always 29, 28 for NIST521 */
+//	public static final int AES_S=128;
+
+// HIFIVE Curve
+//	public static final int MODBITS=336;
+//	public static final int MOD8=5;
+//	public static final int BASEBITS=29;
+//	public static final int AES_S=128; 
+
+// GOLDILOCKS
+//	public static final int MODBITS=448;
+//	public static final int MOD8=7;
+//	public static final int BASEBITS=29;
+//	public static final int AES_S=0; 
+
+// NIST384
+//	public static final int MODBITS=384;
+//	public static final int MOD8=7;
+//	public static final int BASEBITS=29;	
+//	public static final int AES_S=0; 
+
+// C41417
+//	public static final int MODBITS=414;
+//	public static final int MOD8=7;
+//	public static final int BASEBITS=29;	
+//	public static final int AES_S=0; 
+
+// NIST521
+//	public static final int MODBITS=521;
+//	public static final int MOD8=7;
+//	public static final int BASEBITS=28;	
+//	public static final int AES_S=0; 
+
+// BN646 Curve
+//	public static final int MODBITS=646;
+//	public static final int MOD8=3;
+//	public static final int BASEBITS=29;	
+//	public static final int AES_S=192; 
+
+// Curve 25519
+//	public static final int MODBITS=255; 
+//	public static final int MOD8=5;  
+//	public static final int BASEBITS=29;	
+//	public static final int AES_S=0; 
+
+// NIST256 or Brainpool
+//	public static final int MODBITS=256; 
+//	public static final int MOD8=7;  
+//	public static final int BASEBITS=29;
+//	public static final int AES_S=0; 
+
+// MF254 
+//	public static final int MODBITS=254; 
+//	public static final int MOD8=7;  
+//	public static final int BASEBITS=29;
+//	public static final int AES_S=0; 
+
+// MS255
+//	public static final int MODBITS= 255;
+//	public static final int MOD8= 3;
+//	public static final int BASEBITS=29;
+//	public static final int AES_S=0; 
+
+// MF256
+//	public static final int MODBITS=256; 
+//	public static final int MOD8=7;
+//	public static final int BASEBITS=29;
+//	public static final int AES_S=0; 
+
+// MS256
+//	public static final int MODBITS= 256;
+//	public static final int MOD8= 3;
+//	public static final int BASEBITS=29;
+//	public static final int AES_S=0; 
+
+// ANSSI
+// public static final int MODBITS= 256;
+// public static final int MOD8= 3;
+//	public static final int BASEBITS=29;
+//	public static final int AES_S=0; 
+
+	public static final int FFLEN=4; /* 2^n multiplier of BIGBITS to specify supported Finite Field size, e.g 2048=256*2^3 where BIGBITS=256 */
+
+
+/* Don't Modify from here... */
+
+	public static final int NLEN=(1+((MODBITS-1)/BASEBITS));
+	public static final int DNLEN=2*NLEN;
+	public static final int BMASK=(((int)1<<BASEBITS)-1);
+	public static final int MODBYTES=(1+(MODBITS-1)/8);
+	public static final int NEXCESS =((int)1<<(CHUNK-BASEBITS-1));
+	public static final int FEXCESS =((int)1<<(BASEBITS*NLEN-MODBITS)); 
+	public static final int OMASK=(int)(-1)<<(MODBITS%BASEBITS);
+	public static final int TBITS=MODBITS%BASEBITS; // Number of active bits in top word 
+	public static final int TMASK=((int)1<<TBITS)-1;
+	public static final int BIGBITS=(MODBYTES*8);
+
+/* Finite field support - for RSA, DH etc. */
+	public static final int FF_BITS=(BIGBITS*FFLEN); /* Finite Field Size in bits - must be 256.2^n */
+	public static final int HFLEN=(FFLEN/2);  /* Useful for half-size RSA private key operations */
+
+	public static final int P_MBITS=MODBYTES*8;
+	public static final int P_OMASK=((int)(-1)<<(P_MBITS%BASEBITS));
+	public static final int P_FEXCESS=((int)1<<(BASEBITS*NLEN-P_MBITS));
+	public static final int P_TBITS=(P_MBITS%BASEBITS);
+
+/* ...to here */
+
+// START SPECIFY FIELD DETAILS HERE
+//*********************************************************************************
+// Curve25519 Modulus 
+// 	public static final int MODTYPE=PSEUDO_MERSENNE;
+//	public static final int[] Modulus={0x1FFFFFED,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFFF};
+//	public static final int MConst=19;
+
+// NIST-256 Modulus 
+//	public static final int MODTYPE=NOT_SPECIAL;
+//	public static final int[] Modulus={0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FF,0x0,0x0,0x40000,0x1FE00000,0xFFFFFF};
+//	public static final int MConst=1;
+
+// MF254 Modulus
+//	public static final int MODTYPE=MONTGOMERY_FRIENDLY;
+//	public static final int[] Modulus={0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3F80FF};
+//	public static final int MConst=0x3F8100;
+
+// MS255 Modulus
+//public static final int MODTYPE= 1;
+//public static final int[] Modulus= {0x1FFFFD03,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFFF};
+//public static final int MConst=0x2FD;
+
+// MS256 Modulus
+//public static final int MODTYPE= 1;
+//public static final int[] Modulus= {0x1FFFFF43,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFFFFFF};
+//public static final int MConst=0xBD;
+
+// MF256 Modulus
+//public static final int MODTYPE= 2;
+//public static final int[] Modulus= {0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFFA7FF};
+//public static final int MConst=0xFFA800;
+
+// Brainpool Modulus
+//	public static final int MODTYPE= 0;
+//	public static final int[] Modulus= {0x1F6E5377,0x9A40E8,0x9880A08,0x17EC47AA,0x18D726E3,0x5484EC1,0x6F0F998,0x1B743DD5,0xA9FB57};
+//	public static final int MConst=0xEFD89B9;
+
+// ANSSI Modulus
+//  public static final int MODTYPE= 0;
+//  public static final int[] Modulus= {0x186E9C03,0x7E79A9E,0x12329B7A,0x35B7957,0x435B396,0x16F46721,0x163C4049,0x1181675A,0xF1FD17};
+//  public static final int MConst=0x164E1155;
+
+
+// BNCX Curve Modulus
+//	public static final int MODTYPE=NOT_SPECIAL;
+//	public static final int[] Modulus= {0x1C1B55B3,0x13311F7A,0x24FB86F,0x1FADDC30,0x166D3243,0xFB23D31,0x836C2F7,0x10E05,0x240000};
+//	public static final int MConst=0x19789E85;
+
+// HIFIVE Curve Modulus
+//	public static final int MODTYPE=PSEUDO_MERSENNE;
+//	public static final int[] Modulus={0x1FFFFFFD,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFF};
+//	public static final int MConst=0x3;
+
+// GOLDILOCKS Curve Modulus
+//	public static final int MODTYPE=GENERALISED_MERSENNE;
+//	public static final int[] Modulus={0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FDFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFF};
+//	public static final int MConst=0x1;
+
+// NIST384 Curve Modulus
+//	public static final int MODTYPE=NOT_SPECIAL;
+//	public static final int[] Modulus={0x1FFFFFFF,0x7,0x0,0x1FFFFE00,0x1FFFEFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F};
+//	public static final int MConst=0x1;
+
+// C41417 Curve Modulus
+//	public static final int MODTYPE=PSEUDO_MERSENNE;
+//	public static final int[] Modulus={0x1FFFFFEF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFF};
+//	public static final int MConst=0x11;
+
+// NIST521 Curve Modulus
+//	public static final int MODTYPE=PSEUDO_MERSENNE;
+//	public static final int[] Modulus={0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0x1FFFF};
+//	public static final int MConst=0x1;
+
+
+// BN646 Curve Modulus
+//	public static final int MODTYPE=NOT_SPECIAL;
+//	public static final int[] Modulus={0x404E013,0x1203604,0x4E0000,0x80A2084,0x2,0xC90420,0x4051078,0x3600001,0xA20660,0x36,0x5100900,0x10288468,0xD,0x2881200,0x1B0,0x0,0x6C0D80,0x48,0x0,0x480,0x0,0x0,0x90};
+//	public static final int MConst=0x15F615E5;
+
+// BN254 Curve Modulus
+//	public static final int MODTYPE=NOT_SPECIAL;
+//	public static final int[] Modulus= {0x13,0x18000000,0x4E9,0x2000000,0x8612,0x6C00000,0x6E8D1,0x10480000,0x252364};
+//	public static final int MConst=0x179435E5;
+
+// BN454 Curve Modulus
+//	public static final int MODTYPE=NOT_SPECIAL;
+//	public static final int[] Modulus= {0x13,0x270,0x2100,0x1C00D89C,0x25084,0xA284,0x24720,0x10803AA1,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000};
+//	public static final int MConst=0x179435E5;
+
+// BLS383 Curve Modulus
+	public static final int MODTYPE=NOT_SPECIAL;
+	public static final int[] Modulus= {0xAAD556B,0xACAAB52,0x5F75D7A,0x1BB0147,0xD5D7520,0xCF73083,0xF99EB16,0x531820,0xA68EA32,0x2C01355,0x552A785,0x5C6105C,0x80A9F7,0x7AC52};
+	public static final int MConst=0x123D0BD;
+
+// BLS455 Curve Modulus
+//	public static final int MODTYPE=NOT_SPECIAL;
+//	public static final int[] Modulus= {0x2AB,0x1500000C,0xAAA55AA,0xB12AAD6,0x6D1BA6C,0xCCA5674,0x12E2CF6E,0xA9F9662,0x34BD939,0x12D8EAB1,0xFD9978E,0x9240600,0xE0F95B,0xAAB9550,0x55555E5,0xAAAAB};
+//	public static final int MConst=0x1F4017FD;
+
+
+// BNT Curve Modulus
+//	public static final int MODTYPE=NOT_SPECIAL;
+//	public static final int[] Modulus= {0xEB4A713,0x14EDDFF7,0x1D192EAF,0x14AAAC29,0xD5F06E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120};
+//	public static final int MConst=0x1914C4E5;
+
+// BNT2 Curve Modulus
+//	public static final int MODTYPE=NOT_SPECIAL;
+//	public static final int[] Modulus= {0x1460A48B,0x596E15D,0x1C35947A,0x1F27C851,0x1D00081C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004};
+//	public static final int MConst=0x6505CDD;
+
+// START SPECIFY CURVE DETAILS HERE
+//*********************************************************************************
+// Original Curve25519 
+// 	public static final int CURVETYPE=MONTGOMERY;
+//	public static final int CURVE_A =486662;
+//	public static final int[] CURVE_B = {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}; // not used
+//	public static final int[] CURVE_Order={0x1CF5D3ED,0x9318D2,0x1DE73596,0x1DF3BD45,0x14D,0x0,0x0,0x0,0x100000};
+//	public static final int[] CURVE_Gx ={0x9,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+//	public static final int[] CURVE_Gy ={0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}; // not used
+
+
+// Ed25519 Curve 
+//	public static final int CURVETYPE=EDWARDS;
+//	public static final int CURVE_A = -1;
+//	public static final int[] CURVE_B = {0x135978A3,0xF5A6E50,0x10762ADD,0x149A82,0x1E898007,0x3CBBBC,0x19CE331D,0x1DC56DFF,0x52036C};
+//	public static final int[] CURVE_Order={0x1CF5D3ED,0x9318D2,0x1DE73596,0x1DF3BD45,0x14D,0x0,0x0,0x0,0x100000};
+//	public static final int[] CURVE_Gx ={0xF25D51A,0xAB16B04,0x969ECB2,0x198EC12A,0xDC5C692,0x1118FEEB,0xFFB0293,0x1A79ADCA,0x216936};
+//	public static final int[] CURVE_Gy={0x6666658,0x13333333,0x19999999,0xCCCCCCC,0x6666666,0x13333333,0x19999999,0xCCCCCCC,0x666666};
+
+// WS25519 Curve
+//	public static final int CURVETYPE=WEIERSTRASS;
+//	public static final int CURVE_A = -3;
+//	public static final int[] CURVE_B = {0x28,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+//	public static final int[] CURVE_Order = {0x1728ACA1,0x8E7230C,0x10E8DCDB,0x1C1FC966,0x5D5,0x0,0x0,0x0,0x800000}; 
+//	public static final int[] CURVE_Gx={0x14D8261F,0x23A9C3B,0x1E392613,0xE9D560D,0x19BD0F9A,0x1A9EF052,0xCFB499,0x4242BE1,0x67E3F5};
+//	public static final int[] CURVE_Gy={0x1DEEF38,0x1A31963F,0x4871D5,0x16572E70,0x1DEA014C,0x1AE6A722,0x165D7907,0x1903CD0B,0x36856};
+
+// NIST-256 Curve
+//	public static final int CURVETYPE=WEIERSTRASS;
+//	public static final int CURVE_A = -3;
+//	public static final int[] CURVE_B={0x7D2604B,0x1E71E1F1,0x14EC3D8E,0x1A0D6198,0x86BC651,0x1EAABB4C,0xF9ECFAE,0x1B154752,0x5AC635};
+//	public static final int[] CURVE_Order={0x1C632551,0x1DCE5617,0x5E7A13C,0xDF55B4E,0x1FFFFBCE,0x1FFFFFFF,0x3FFFF,0x1FE00000,0xFFFFFF}; 
+//	public static final int[] CURVE_Gx={0x1898C296,0x509CA2E,0x1ACCE83D,0x6FB025B,0x40F2770,0x1372B1D2,0x91FE2F3,0x1E5C2588,0x6B17D1};
+//	public static final int[] CURVE_Gy={0x17BF51F5,0x1DB20341,0xC57B3B2,0x1C66AED6,0x19E162BC,0x15A53E07,0x1E6E3B9F,0x1C5FC34F,0x4FE342};
+//
+// MF254 Modulus, Weierstrass Curve w-254-mont
+//public static final int CURVETYPE= 0;
+//public static final int CURVE_A = -3;
+//public static final int[] CURVE_B = {0x1FFFD08D,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3F80FF};
+//public static final int[] CURVE_Order={0xF8DF83F,0x1D20CE25,0x8DD701B,0x317D41B,0x1FFFFEB8,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3F80FF};
+//public static final int[] CURVE_Gx ={0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+//public static final int[] CURVE_Gy ={0x190D4EBC,0xB2EF9BF,0x14464C6B,0xE71C7F0,0x18AEBDFB,0xD3ADEBB,0x18052B85,0x1A6765CA,0x140E3F};
+
+// MF254 Modulus, Edwards Curve ed-254-mont
+//public static final int CURVETYPE= 1;
+//public static final int CURVE_A = -1;
+//public static final int[] CURVE_B = {0x367B,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+//public static final int[] CURVE_Order={0x46E98C7,0x179E9FF6,0x158BEC3A,0xA60D917,0x1FFFFEB9,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFE03F};
+//public static final int[] CURVE_Gx ={0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+//public static final int[] CURVE_Gy ={0xF2701E5,0x29687ED,0xC84861F,0x535081C,0x3F4E363,0x6A811B,0xCD65474,0x121AD498,0x19F0E6};
+
+// MF254 Modulus, Montgomery Curve
+// 	public static final int CURVETYPE=MONTGOMERY;
+//	public static final int CURVE_A =-55790;
+//	public static final int[] CURVE_B = {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}; // not used
+//	public static final int[] CURVE_Order={0x46E98C7,0x179E9FF6,0x158BEC3A,0xA60D917,0x1FFFFEB9,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFE03F};
+//	public static final int[] CURVE_Gx ={0x3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+//	public static final int[] CURVE_Gy ={0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}; // not used
+
+// MS255 Modulus, Weierstrass Curve
+//public static final int CURVETYPE= WEIERSTRASS;
+//public static final int CURVE_A = -3;
+//public static final int[] CURVE_B = {0x1FFFAB46,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFFF};
+//public static final int[] CURVE_Order={0x1C594AEB,0x1C7D64C1,0x14ACF7EA,0x14705075,0x1FFFF864,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFFF};
+//public static final int[] CURVE_Gx ={0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+//public static final int[] CURVE_Gy ={0x9CB44BA,0x199FFB3B,0x1F698345,0xD8F19BB,0x17D177DB,0x1FFCD97F,0xCE487A,0x181DB74F,0x6F7A6A};
+
+// MS255 Modulus, Edwards Curve
+//public static final int CURVETYPE= EDWARDS;
+//public static final int CURVE_A = -1;
+//public static final int[] CURVE_B = {0xEA97,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+//public static final int[] CURVE_Order={0x436EB75,0x24E8F68,0x9A0CBAB,0x34F0BDB,0x1FFFFDCF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFF};
+//public static final int[] CURVE_Gx ={0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+//public static final int[] CURVE_Gy ={0x108736A0,0x11512ADE,0x1116916E,0x29715DA,0x47E5529,0x66EC706,0x1517B095,0xA694F76,0x26CB78};
+
+// MS255 Modulus, Montgomery Curve
+// 	public static final int CURVETYPE=MONTGOMERY;
+//	public static final int CURVE_A =-240222;
+//	public static final int[] CURVE_B = {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}; // not used
+//	public static final int[] CURVE_Order={0x436EB75,0x24E8F68,0x9A0CBAB,0x34F0BDB,0x1FFFFDCF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFF};
+//	public static final int[] CURVE_Gx ={0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+//	public static final int[] CURVE_Gy ={0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}; // not used
+
+// MS256, Weierstrass Curve
+//public static final int CURVETYPE= WEIERSTRASS;
+//public static final int CURVE_A = -3;
+//public static final int[] CURVE_B = {0x25581,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+//public static final int[] CURVE_Order={0x751A825,0x559014A,0x9971808,0x1904EBD4,0x1FFFFE43,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFFFFFF};
+//public static final int[] CURVE_Gx ={0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+//public static final int[] CURVE_Gy ={0x2B56C77,0x1FA31836,0x253B042,0x185F26EB,0xDD6BD02,0x4B66777,0x1B5FF20B,0xA783C8C,0x696F18};
+
+// MS256, Edwards Curve
+//public static final int CURVETYPE= EDWARDS;
+//public static final int CURVE_A = -1;
+//public static final int[] CURVE_B = {0x3BEE,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+//public static final int[] CURVE_Order={0x1122B4AD,0xDC27378,0x9AF1939,0x154AB5A1,0x1FFFFBE6,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3FFFFF};
+//public static final int[] CURVE_Gx ={0xD,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+//public static final int[] CURVE_Gy ={0x131CADBA,0x3FB7DA9,0x134C0FDC,0x14DAC704,0x46BFBE2,0x1859CFD0,0x1B6E8F4C,0x3C5424E,0x7D0AB4};
+
+// MS256 Modulus, Montgomery Curve
+// 	public static final int CURVETYPE=MONTGOMERY;
+//	public static final int CURVE_A =-61370;
+//	public static final int[] CURVE_B = {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}; // not used
+//  public static final int[] CURVE_Order={0x1122B4AD,0xDC27378,0x9AF1939,0x154AB5A1,0x1FFFFBE6,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3FFFFF};
+//	public static final int[] CURVE_Gx ={0xb,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+//	public static final int[] CURVE_Gy ={0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}; // not used
+
+// MF256 Modulus, Weierstrass Curve
+//public static final int CURVETYPE= WEIERSTRASS;
+//public static final int CURVE_A = -3;
+//public static final int[] CURVE_B = {0x14E6A,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+//public static final int[] CURVE_Order={0x79857EB,0x8862F0D,0x1941D2E7,0x2EA27CD,0x1FFFFFC5,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFFA7FF};
+//public static final int[] CURVE_Gx ={0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+//public static final int[] CURVE_Gy ={0xB724D2A,0x3CAA61,0x5371984,0x128FD71B,0x1AE28956,0x1D13091E,0x339EEAE,0x10F7C301,0x20887C};
+
+// MF256, Edwards Curve
+//public static final int CURVETYPE= EDWARDS;
+//public static final int CURVE_A = -1;
+//public static final int[] CURVE_B = {0x350A,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+//public static final int[] CURVE_Order={0x18EC7BAB,0x16C976F6,0x19CCF259,0x9775F70,0x1FFFFB15,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3FE9FF};
+//public static final int[] CURVE_Gx ={0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+//public static final int[] CURVE_Gy ={0x12F3C908,0xF553917,0x1FA9A35F,0xBCC91B,0x1AACA0C,0x1779ED96,0x156BABAF,0x1F1F1989,0xDAD8D4};
+
+// MF256 Modulus, Montgomery Curve
+// 	public static final int CURVETYPE=MONTGOMERY;
+//	public static final int CURVE_A =-54314;
+//	public static final int[] CURVE_B = {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}; // not used
+//  public static final int[] CURVE_Order={0x18EC7BAB,0x16C976F6,0x19CCF259,0x9775F70,0x1FFFFB15,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3FE9FF};
+//	public static final int[] CURVE_Gx ={0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+//	public static final int[] CURVE_Gy ={0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}; // not used
+
+// Brainpool
+//	public static final int CURVETYPE= WEIERSTRASS;
+//	public static final int CURVE_A = -3;
+//	public static final int[] CURVE_B = {0x1EE92B04,0x172C080F,0xBD2495A,0x7D7895E,0x176B7BF9,0x13B99E85,0x1A93F99A,0x18861B09,0x662C61};
+//	public static final int[] CURVE_Order={0x174856A7,0xF07414,0x1869BDE4,0x12F5476A,0x18D718C3,0x5484EC1,0x6F0F998,0x1B743DD5,0xA9FB57};
+//	public static final int[] CURVE_Gx ={0xE1305F4,0xD0C8AB1,0xBEF0ADE,0x28588F5,0x16149AFA,0x9D91D32,0x1EDDCC88,0x79839FC,0xA3E8EB};
+//	public static final int[] CURVE_Gy ={0x1B25C9BE,0xD5F479A,0x1409C007,0x196DBC73,0x417E69B,0x1170A322,0x15B5FDEC,0x10468738,0x2D996C};
+
+// ANSSI
+//  public static final int CURVETYPE= WEIERSTRASS;
+//  public static final int CURVE_A = -3;
+//  public static final int[] CURVE_B = {0x1B7BB73F,0x3AF6CB3,0xC68600C,0x181935C9,0xC00FDFE,0x1D3AA522,0x4C0352A,0x194A8515,0xEE353F};
+//  public static final int[] CURVE_Order={0x6D655E1,0x1FEEA2CE,0x14AFE507,0x18CFC281,0x435B53D,0x16F46721,0x163C4049,0x1181675A,0xF1FD17};
+//  public static final int[] CURVE_Gx ={0x198F5CFF,0x64BD16E,0x62DC059,0xFA5B95F,0x23958C2,0x1EA3A4EA,0x7ACC460,0x186AD827,0xB6B3D4};
+//  public static final int[] CURVE_Gy ={0x14062CFB,0x188AD0AA,0x19327860,0x3860FD1,0xEF8C270,0x18F879F6,0x12447E49,0x1EF91640,0x6142E0};
+
+// HIFIVE 
+//	public static final int CURVETYPE=EDWARDS;
+//	public static final int CURVE_A=1;
+//	public static final int[] CURVE_Order={0x1E9FA805,0x197CACB9,0x1E4EEA9E,0x17AD70F,0x1FA9850C,0x38A0A,0x0,0x0,0x0,0x0,0x0,0x4000};
+//	public static final int[] CURVE_B = {0x2B67,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+//	public static final int[] CURVE_Gx ={0xC,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+//	public static final int[] CURVE_Gy ={0x5FE8632,0x15F63428,0xD976C4,0x1AACA194,0x35B6DB5,0x8E3F7A,0x52D1B0E,0xF0A7A36,0x1C161D00,0x8170C70,0x1185AD59,0x181B};
+
+// GOLDILOCKS
+//	public static final int CURVETYPE=EDWARDS;
+//	public static final int CURVE_A=1;
+//	public static final int[] CURVE_Order={0xB5844F3,0x1BC61495,0x1163D548,0x1984E51B,0x3690216,0xDA4D76B,0xFA7113B,0x1FEF9944,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FF};
+//	public static final int[] CURVE_B = {0x1FFF6756,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FDFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFF};
+//	public static final int[] CURVE_Gx ={0x15555555,0xAAAAAAA,0x15555555,0xAAAAAAA,0x15555555,0xAAAAAAA,0x15555555,0x152AAAAA,0xAAAAAAA,0x15555555,0xAAAAAAA,0x15555555,0xAAAAAAA,0x15555555,0xAAAAAAA,0x1555};
+//	public static final int[] CURVE_Gy ={0xA9386ED,0x1757DE6F,0x13681AF6,0x19657DA3,0x3098BBB,0x12C19D15,0x12E03595,0xE515B18,0x17B7E36D,0x1AC426E,0xDBB5E8,0x10D8560,0x159D6205,0xB8246D9,0x17A58D2B,0x15C0};
+
+// NIST384
+//	public static final int CURVETYPE=WEIERSTRASS;
+//	public static final int CURVE_A=-3;
+//	public static final int[] CURVE_Order = {0xCC52973,0x760CB56,0xC29DEBB,0x141B6491,0x12DDF581,0x6C0FA1B,0x1FFF1D8D,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F};
+//	public static final int[] CURVE_B = {0x13EC2AEF,0x142E476E,0xBB4674A,0xC731B14,0x1875AC65,0x447A809,0x4480C50,0xDDFD028,0x19181D9C,0x1F1FC168,0x623815A,0x47DCFC9,0x1312FA7E,0x59};
+//	public static final int[] CURVE_Gx = {0x12760AB7,0x12A2F1C3,0x154A5B0E,0x5E4BB7E,0x2A38550,0xF0412A,0xE6167DD,0xC5174F3,0x146E1D3B,0x1799056B,0x3AC71C7,0x1D160A6F,0x87CA22B,0x55};
+//	public static final int[] CURVE_Gy = {0x10EA0E5F,0x1218EBE4,0x1FA0675E,0x1639C3A,0xB8C00A6,0x1889DAF8,0x11F3A768,0x17A51342,0x9F8F41D,0x1C9496E1,0x1767A62F,0xC4C58DE,0x17DE4A9,0x1B};
+
+// C41417
+//	public static final int CURVETYPE=EDWARDS;
+//	public static final int CURVE_A=1;
+//	public static final int[] CURVE_Order = {0x106AF79,0x18738D2F,0x18F3C606,0x1806715A,0x22B36F1,0xA67B830,0xCF32490,0x1FFFFFFD,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1F};
+//	public static final int[] CURVE_B = {0xE21,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+//	public static final int[] CURVE_Gx = {0x13CBC595,0x7E9C097,0x14DF1931,0x14E7F550,0x1A111301,0x15A6B6B5,0xD526292,0x18FEAFFE,0x1F44C03E,0x1E6A31B4,0x70C9B97,0x43180C6,0x1443300,0x19A4828A,0x68};
+//	public static final int[] CURVE_Gy = {0x22,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+
+// NIST521
+//	public static final int CURVETYPE=WEIERSTRASS;
+//	public static final int CURVE_A=-3;
+//	public static final int[] CURVE_Order = {0x1386409,0x6FB71E9,0xC47AEBB,0xC9B8899,0x5D03BB5,0x48F709A,0xB7FCC01,0xBF2F966,0x1868783,0xFFFFFA5,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0x1FFFF};
+//	public static final int[] CURVE_B = {0xB503F00,0x451FD46,0xC34F1EF,0xDF883D2,0xF073573,0xBD3BB1B,0xB1652C0,0xEC7E937,0x6193951,0xF109E15,0x489918E,0x15F3B8B,0x25B99B3,0xEEA2DA7,0xB68540,0x929A21A,0xE1C9A1F,0x3EB9618,0x5195};
+//	public static final int[] CURVE_Gx = {0x2E5BD66,0x7E7E31C,0xA429BF9,0xB3C1856,0x8DE3348,0x27A2FFA,0x8FE1DC1,0xEFE7592,0x14B5E77,0x4D3DBAA,0x8AF606B,0xB521F82,0x139053F,0x429C648,0x62395B4,0x9E3ECB6,0x404E9CD,0x8E06B70,0xC685};
+//	public static final int[] CURVE_Gy = {0xFD16650,0xBE94769,0x2C24088,0x7086A27,0x761353C,0x13FAD0,0xC550B9,0x5EF4264,0x7EE7299,0x3E662C9,0xFBD1727,0x446817A,0x449579B,0xD998F54,0x42C7D1B,0x5C8A5FB,0xA3BC004,0x296A789,0x11839};
+
+//BN646 Curve
+/*
+	public static final int CURVETYPE=WEIERSTRASS;
+	public static final int CURVE_PAIRING_TYPE=BN_CURVE;
+	public static final int CURVE_A = 0;
+	public static final int[] CURVE_Order={0x1E04200D,0x1203603,0x420000,0x80A207E,0x2,0xC303F0,0x4051075,0x3600001,0xA20630,0x36,0x5100900,0x1028845C,0xD,0x2881200,0x1B0,0x0,0x6C0D80,0x48,0x0,0x480,0x0,0x0,0x90};
+	public static final int[] CURVE_B= {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int[] CURVE_Cof= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+
+	public static final int[] CURVE_Gx={0x404E012,0x1203604,0x4E0000,0x80A2084,0x2,0xC90420,0x4051078,0x3600001,0xA20660,0x36,0x5100900,0x10288468,0xD,0x2881200,0x1B0,0x0,0x6C0D80,0x48,0x0,0x480,0x0,0x0,0x90};
+	public static final int[] CURVE_Gy={0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+
+	public static final int[] CURVE_Bnx={0x1001,0x0,0x10000,0x0,0x0,0x8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int[] CURVE_Cru={0x401B007,0x901,0x1B0000,0x1B024,0x0,0x288120,0xD812,0x900000,0x1B0120,0x0,0xD80000,0x6C048,0x0,0x6C0000,0x0,0x0,0x120000,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int[] CURVE_Fra={0x4929A14,0x3B756CA,0x4337DD0,0xFC1417C,0x193166BB,0x1DC54515,0x1C0DF653,0x19BF8961,0x155980E,0x1983CB14,0x4D76309,0x1DEAB1A4,0xF9C3CF5,0x128FEC2D,0x867E339,0xDA0548A,0x1A480AF,0xA3CBCD2,0x116DA6E0,0x2A546E9,0x789577C,0x1F9459D2,0x27};
+	public static final int[] CURVE_Frb={0x1F7245FF,0x1D68DF39,0x1C1A822F,0x1848DF07,0x6CE9946,0x303BF0A,0x7F71A24,0x9A0769F,0x1F4C6E51,0x67C3521,0x38A5F6,0x123DD2C4,0x1063C317,0xFF825D2,0x17981E76,0x125FAB75,0x1EC78CD0,0x15C34375,0xE92591F,0x1D5ABD96,0x1876A883,0x6BA62D,0x68};
+	public static final int[] CURVE_Pxa={0x1CCC5E10,0x119F939,0xC6C7FE9,0x81022FF,0x6486AA6,0x1CBC560B,0x1F707429,0xC82F7B9,0x1A7F5CDA,0x14C0EB47,0x11412373,0x13DAF21E,0x126BE416,0x166744A7,0x506E81,0x1048FFA3,0x13A6B0C9,0x1A90979A,0xE78C338,0x1722C561,0xBFFF9A1,0xC1AF83C,0x3F};
+	public static final int[] CURVE_Pxb={0x67F4BC0,0x1BFC3C9,0x1E9DC3B6,0x87E2B03,0xB820274,0x1DD03B1E,0x517C463,0x1EFCBBC9,0x19F786A8,0x5572E90,0xD0BA5E0,0x16E8A40A,0x1013CF3B,0x11A7F82B,0x1C27B302,0x15E7CD12,0xB79A6DF,0x1EC6895B,0x5775A7E,0xBB28D24,0x416A171,0x127D284E,0x5D};
+	public static final int[] CURVE_Pya={0xC3FB414,0x2B868EE,0xD858793,0x157FCFE,0x16C849AD,0x1D17B0A4,0x1353CFEA,0x940A061,0x1CEF834E,0x7BE766A,0x4584C1C,0xE2397E9,0x418E9D4,0x8F53B8,0x53B37E0,0x11CA29D9,0xE425654,0x9EFF9AF,0x18CF27A1,0x17755A26,0x3F5481A,0x6C531BC,0x1E};
+	public static final int[] CURVE_Pyb={0x133908AD,0x17F1F1ED,0x14196532,0x19A85214,0x173EC3F7,0x1021EC2C,0xD798A3E,0x18F4C857,0x82EE2FA,0x11B5296D,0x1831D9C6,0x4463DB5,0x11B4812C,0xF93B884,0xC72653,0xEC6F6ED,0x916CFFF,0x1E81ED0A,0x1103518E,0x1E478B01,0x6B01074,0xC46CCAA,0x48};
+	public static final int[][] CURVE_W={{0x6008003,0x0,0x80000,0x6,0x0,0x40030,0x3,0x0,0x30,0x0,0x0,0xC,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x2001,0x0,0x20000,0x0,0x0,0x10000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+	public static final int[][][] CURVE_SB={{{0x600A004,0x0,0xA0000,0x6,0x0,0x50030,0x3,0x0,0x30,0x0,0x0,0xC,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x2001,0x0,0x20000,0x0,0x0,0x10000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x2001,0x0,0x20000,0x0,0x0,0x10000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1803A00A,0x1203603,0x3A0000,0x80A2078,0x2,0xBF03C0,0x4051072,0x3600001,0xA20600,0x36,0x5100900,0x10288450,0xD,0x2881200,0x1B0,0x0,0x6C0D80,0x48,0x0,0x480,0x0,0x0,0x90}}};
+	public static final int[][] CURVE_WB={{0x2001000,0x0,0x10000,0x2,0x0,0x8010,0x1,0x0,0x10,0x0,0x0,0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1C015005,0x600,0x150000,0x1201C,0x0,0x1C80E0,0x900E,0x600000,0x1200E0,0x0,0x900000,0x48038,0x0,0x480000,0x0,0x0,0xC0000,0x0,0x0,0x0,0x0,0x0,0x0},{0xE00B003,0x300,0xB0000,0x900E,0x0,0xE8070,0x4807,0x300000,0x90070,0x0,0x480000,0x2401C,0x0,0x240000,0x0,0x0,0x60000,0x0,0x0,0x0,0x0,0x0,0x0},{0x2003001,0x0,0x30000,0x2,0x0,0x18010,0x1,0x0,0x10,0x0,0x0,0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+	public static final int[][][] CURVE_BB={{{0x1E04100D,0x1203603,0x410000,0x80A207E,0x2,0xC283F0,0x4051075,0x3600001,0xA20630,0x36,0x5100900,0x1028845C,0xD,0x2881200,0x1B0,0x0,0x6C0D80,0x48,0x0,0x480,0x0,0x0,0x90},{0x1E04100C,0x1203603,0x410000,0x80A207E,0x2,0xC283F0,0x4051075,0x3600001,0xA20630,0x36,0x5100900,0x1028845C,0xD,0x2881200,0x1B0,0x0,0x6C0D80,0x48,0x0,0x480,0x0,0x0,0x90},{0x1E04100C,0x1203603,0x410000,0x80A207E,0x2,0xC283F0,0x4051075,0x3600001,0xA20630,0x36,0x5100900,0x1028845C,0xD,0x2881200,0x1B0,0x0,0x6C0D80,0x48,0x0,0x480,0x0,0x0,0x90},{0x2002,0x0,0x20000,0x0,0x0,0x10000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x2001,0x0,0x20000,0x0,0x0,0x10000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1E04100C,0x1203603,0x410000,0x80A207E,0x2,0xC283F0,0x4051075,0x3600001,0xA20630,0x36,0x5100900,0x1028845C,0xD,0x2881200,0x1B0,0x0,0x6C0D80,0x48,0x0,0x480,0x0,0x0,0x90},{0x1E04100D,0x1203603,0x410000,0x80A207E,0x2,0xC283F0,0x4051075,0x3600001,0xA20630,0x36,0x5100900,0x1028845C,0xD,0x2881200,0x1B0,0x0,0x6C0D80,0x48,0x0,0x480,0x0,0x0,0x90},{0x1E04100C,0x1203603,0x410000,0x80A207E,0x2,0xC283F0,0x4051075,0x3600001,0xA20630,0x36,0x5100900,0x1028845C,0xD,0x2881200,0x1B0,0x0,0x6C0D80,0x48,0x0,0x480,0x0,0x0,0x90}},{{0x2002,0x0,0x20000,0x0,0x0,0x10000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x2001,0x0,0x20000,0x0,0x0,0x10000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x2001,0x0,0x20000,0x0,0x0,0x10000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x2001,0x0,0x20000,0x0,0x0,0x10000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x1002,0x0,0x10000,0x0,0x0,0x8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x4002,0x0,0x40000,0x0,0x0,0x20000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1E04000A,0x1203603,0x400000,0x80A207E,0x2,0xC203F0,0x4051075,0x3600001,0xA20630,0x36,0x5100900,0x1028845C,0xD,0x2881200,0x1B0,0x0,0x6C0D80,0x48,0x0,0x480,0x0,0x0,0x90},{0x1002,0x0,0x10000,0x0,0x0,0x8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+
+	public static final boolean USE_GLV =true;
+	public static final boolean USE_GS_G2 =true;
+	public static final boolean USE_GS_GT =true;	
+	public static final boolean GT_STRONG=false;
+*/
+// BNCX Curve 
+/*
+	public static final int CURVETYPE=WEIERSTRASS;
+	public static final int CURVE_PAIRING_TYPE=BN_CURVE;
+	public static final int CURVE_A = 0;
+	public static final int[] CURVE_B = {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int[] CURVE_Cof = {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+
+	public static final int[] CURVE_Order={0x16EB1F6D,0x108E0531,0x1241B3AF,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000};
+	public static final int[] CURVE_Bnx={0x3C012B1,0x0,0x10,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int[] CURVE_Cru={0x14235C97,0xF0498BC,0x1BE1D58C,0x1BBEC8E3,0x3F1440B,0x654,0x12000,0x0,0x0};
+	public static final int[] CURVE_Fra={0x15C80EA3,0x1EC8419A,0x1CFE0856,0xEE64DE2,0x11898686,0x5C55653,0x592BF86,0x5F4C740,0x135908};
+	public static final int[] CURVE_Frb={0x6534710,0x1468DDE0,0x551B018,0x10C78E4D,0x4E3ABBD,0x9ECE6DE,0x2A40371,0x1A0C46C5,0x10A6F7};
+	public static final int[] CURVE_Pxa={0x4D2EC74,0x428E777,0xF89C9B0,0x190B7F40,0x14BBB907,0x12807AE1,0x958D62C,0x58E0A76,0x19682D};
+	public static final int[] CURVE_Pxb={0xE29CFE1,0x1D2C7459,0x270C3D1,0x172F6184,0x19743F81,0x49BD474,0x192A8047,0x1D87C33E,0x1466B9};
+	public static final int[] CURVE_Pya={0xF0BE09F,0x7DFE75E,0x1FB06CC3,0x3667B08,0xE209636,0x110ABED7,0xE376078,0x1B2E4665,0xA79ED};
+	public static final int[] CURVE_Pyb={0x898EE9D,0xC825914,0x14BB7AFB,0xC9D4AD3,0x13461C28,0x122896C6,0x240D71B,0x73D9898,0x6160C};
+	public static final int[] CURVE_Gx ={0x1C1B55B2,0x13311F7A,0x24FB86F,0x1FADDC30,0x166D3243,0xFB23D31,0x836C2F7,0x10E05,0x240000};
+	public static final int[] CURVE_Gy ={0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int[][] CURVE_W={{0x162FEB83,0x2A31A48,0x100E0480,0x16,0x600,0x0,0x0,0x0,0x0},{0x7802561,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0}};
+	public static final int[][][] CURVE_SB={{{0x1DB010E4,0x2A31A48,0x100E04A0,0x16,0x600,0x0,0x0,0x0,0x0},{0x7802561,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x7802561,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0xBB33EA,0xDEAEAE9,0x233AF2F,0x1FADDC03,0x166D2643,0xFB23D31,0x836C2F7,0x10E05,0x240000}}};
+	public static final int[][] CURVE_WB={{0x167A84B0,0xE108C2,0x1004AC10,0x7,0x200,0x0,0x0,0x0,0x0},{0x1E220475,0x166FCCAD,0x129FE68D,0x1D29DB51,0x2A0DC07,0x438,0xC000,0x0,0x0},{0xF10B93,0x1B37E657,0x194FF34E,0x1E94EDA8,0x1506E03,0x21C,0x6000,0x0,0x0},{0x1DFAAA11,0xE108C2,0x1004AC30,0x7,0x200,0x0,0x0,0x0,0x0}};
+	public static final int[][][] CURVE_BB={{{0x132B0CBD,0x108E0531,0x1241B39F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000},{0x132B0CBC,0x108E0531,0x1241B39F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000},{0x132B0CBC,0x108E0531,0x1241B39F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000},{0x7802562,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x7802561,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0x132B0CBC,0x108E0531,0x1241B39F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000},{0x132B0CBD,0x108E0531,0x1241B39F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000},{0x132B0CBC,0x108E0531,0x1241B39F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000}},{{0x7802562,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0x7802561,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0x7802561,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0x7802561,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x3C012B2,0x0,0x10,0x0,0x0,0x0,0x0,0x0,0x0},{0xF004AC2,0x0,0x40,0x0,0x0,0x0,0x0,0x0,0x0},{0xF6AFA0A,0x108E0531,0x1241B38F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000},{0x3C012B2,0x0,0x10,0x0,0x0,0x0,0x0,0x0,0x0}}};
+
+	public static final boolean USE_GLV =true;
+	public static final boolean USE_GS_G2 =true;
+	public static final boolean USE_GS_GT =true;	
+	public static final boolean GT_STRONG=true;
+*/
+// BNT2 Curve
+/*
+	public static final int CURVETYPE=WEIERSTRASS;
+	public static final int CURVE_PAIRING_TYPE=BN_CURVE;
+	public static final int CURVE_A = 0;
+	public static final int[] CURVE_B = {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int[] CURVE_Cof = {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+
+	public static final int[] CURVE_Order={0x11AA2BF5,0x1FDB8D28,0xDCE0CF5,0x1F1BC24F,0x1D00021C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004};
+	public static final int[] CURVE_Bnx={0x608205,0x1008,0x10,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int[] CURVE_Cru={0x866BD33,0x1A813A22,0x591C3BE,0xAB6EE60,0x1ECF2367,0x361B0BD,0x12000,0x0,0x0};
+	public static final int[] CURVE_Fra={0x13AEF062,0x1593464B,0x10EF3924,0x198D3667,0x17F195BB,0xFB3FD1,0xADAF429,0x11A53D19,0x124E0B};
+	public static final int[] CURVE_Frb={0xB1B429,0x10039B12,0xB465B55,0x59A91EA,0x50E7261,0xF0C5DF3,0x1FDBE90F,0x1EA2E4D1,0x11B1F8};
+	public static final int[] CURVE_Pxa={0x1F40A3C8,0x166491CC,0x19845E12,0xB9B49D2,0x161706B3,0xBBD82B4,0x18C609E7,0x19F2D278,0x16FC17};
+	public static final int[] CURVE_Pxb={0x18549540,0x2ABD456,0x1D944184,0x16DEF7CD,0x1A95D17D,0x42B2C83,0x16427206,0x17AB2E,0x1EB5B5};
+	public static final int[] CURVE_Pya={0x14220513,0x3DF6628,0x39CDEC5,0x894F10C,0x135F1268,0x1D28DC1C,0xAAA7537,0x130EC284,0x1E8EE4};
+	public static final int[] CURVE_Pyb={0x177CE78E,0x1DC9947A,0x1BE95E07,0x1D6E8DC4,0x1FB8E27,0x1B549EDE,0xF6E8A75,0x19B75C67,0x23CEF4};	
+	public static final int[] CURVE_Gx ={0x1460A48A,0x596E15D,0x1C35947A,0x1F27C851,0x1D00081C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004};
+	public static final int[] CURVE_Gy ={0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int[][] CURVE_W={{0x1347083,0x5BB1415,0xE678744,0xC0602,0x600,0x0,0x0,0x0,0x0},{0xC10409,0x2010,0x20,0x0,0x0,0x0,0x0,0x0,0x0}};
+	public static final int[][][] CURVE_SB={{{0x1F5748C,0x5BB3425,0xE678764,0xC0602,0x600,0x0,0x0,0x0,0x0},{0xC10409,0x2010,0x20,0x0,0x0,0x0,0x0,0x0,0x0}},{{0xC10409,0x2010,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0x1075BB72,0x1A207913,0x1F6685B1,0x1F0FBC4C,0x1CFFFC1C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004}}};
+	public static final int[][] CURVE_WB={{0xA70A224,0xC9396A4,0x1A228251,0x40200,0x200,0x0,0x0,0x0,0x0},{0x1030EF19,0xAD2B967,0xD50DC87,0x72CA2EC,0x148A1B9A,0x241207E,0xC000,0x0,0x0},{0x1848B88F,0x156964B7,0x6A86E4B,0x3965176,0xA450DCD,0x120903F,0x6000,0x0,0x0},{0xB31A62D,0xC93B6B4,0x1A228271,0x40200,0x200,0x0,0x0,0x0,0x0}};
+	public static final int[][][] CURVE_BB={{{0x1149A9F1,0x1FDB7D20,0xDCE0CE5,0x1F1BC24F,0x1D00021C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004},{0x1149A9F0,0x1FDB7D20,0xDCE0CE5,0x1F1BC24F,0x1D00021C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004},{0x1149A9F0,0x1FDB7D20,0xDCE0CE5,0x1F1BC24F,0x1D00021C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004},{0xC1040A,0x2010,0x20,0x0,0x0,0x0,0x0,0x0,0x0}},{{0xC10409,0x2010,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0x1149A9F0,0x1FDB7D20,0xDCE0CE5,0x1F1BC24F,0x1D00021C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004},{0x1149A9F1,0x1FDB7D20,0xDCE0CE5,0x1F1BC24F,0x1D00021C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004},{0x1149A9F0,0x1FDB7D20,0xDCE0CE5,0x1F1BC24F,0x1D00021C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004}},{{0xC1040A,0x2010,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0xC10409,0x2010,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0xC10409,0x2010,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0xC10409,0x2010,0x20,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x608206,0x1008,0x10,0x0,0x0,0x0,0x0,0x0,0x0},{0x1820812,0x4020,0x40,0x0,0x0,0x0,0x0,0x0,0x0},{0x10E927EA,0x1FDB6D18,0xDCE0CD5,0x1F1BC24F,0x1D00021C,0x10079DC4,0xAB6DD38,0x104821EB,0x240004},{0x608206,0x1008,0x10,0x0,0x0,0x0,0x0,0x0,0x0}}};
+
+	public static final boolean USE_GLV =true;
+	public static final boolean USE_GS_G2 =true;
+	public static final boolean USE_GS_GT =true;	
+	public static final boolean GT_STRONG=true;
+*/
+
+// BN254 Curve
+/*
+	public static final int CURVETYPE=WEIERSTRASS;
+	public static final int CURVE_PAIRING_TYPE=BN_CURVE;
+	public static final int CURVE_A = 0;
+	public static final int[] CURVE_B = {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int[] CURVE_Cof = {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+
+	public static final int[] CURVE_Order={0xD,0x8000000,0x428,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364};
+	public static final int[] CURVE_Bnx={0x1,0x4000000,0x10,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int[] CURVE_Cru={0x7,0xC000000,0x1B3,0x12000000,0x2490,0x11200000,0x126CD,0x0,0x0};
+	public static final int[] CURVE_Fra={0xF2A6DE9,0xBEF3603,0xFDDF0B8,0x12E9249A,0x953F850,0xDA85423,0x1232D926,0x32425CF,0x1B3776};
+	public static final int[] CURVE_Frb={0x10D5922A,0xC10C9FC,0x10221431,0xF16DB65,0x16AC8DC1,0x1917ABDC,0xDD40FAA,0xD23DA30,0x9EBEE};
+	public static final int[] CURVE_Pxa={0x803FB2B,0xF721126,0x62FC364,0x9177691,0x1EDB6A46,0x63F4630,0x18BFAE36,0x176A33D6,0x61A10};
+	public static final int[] CURVE_Pxb={0x7D54CF3,0xC61A60F,0xDE12DC3,0x1AE8D75C,0xAA5B1F4,0x13C62CC1,0xCCC42A,0x1F374E6F,0x516AA};
+	public static final int[] CURVE_Pya={0x11CD2B9A,0xF8703C4,0xF826F46,0x1A15CD7B,0x822329B,0x104B34C6,0xD0E6A43,0x140D75F2,0x21897};
+	public static final int[] CURVE_Pyb={0xB3ACE9B,0x1168D763,0xE7255E2,0xDFFAE,0x18D37B09,0x22B7AF9,0x149A3DB5,0x1CF9162,0xEBB2B};
+	public static final int[] CURVE_Gx ={0x12,0x18000000,0x4E9,0x2000000,0x8612,0x6C00000,0x6E8D1,0x10480000,0x252364};
+	public static final int[] CURVE_Gy ={0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int[][] CURVE_W={{0x3,0x0,0x81,0x3000000,0x618,0x0,0x0,0x0,0x0},{0x1,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0}};
+	public static final int[][][] CURVE_SB={{{0x4,0x8000000,0xA1,0x3000000,0x618,0x0,0x0,0x0,0x0},{0x1,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x1,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0xA,0x8000000,0x3A7,0x1C000000,0x79E1,0x6C00000,0x6E8D1,0x10480000,0x252364}}};
+	public static final int[][] CURVE_WB={{0x0,0x4000000,0x10,0x1000000,0x208,0x0,0x0,0x0,0x0},{0x5,0x14000000,0x152,0xE000000,0x1C70,0xC00000,0xC489,0x0,0x0},{0x3,0xC000000,0xB1,0x7000000,0xE38,0x10600000,0x6244,0x0,0x0},{0x1,0xC000000,0x30,0x1000000,0x208,0x0,0x0,0x0,0x0}};
+	public static final int[][][] CURVE_BB={{{0xD,0x4000000,0x418,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364},{0xC,0x4000000,0x418,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364},{0xC,0x4000000,0x418,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364},{0x2,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x1,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0xC,0x4000000,0x418,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364},{0xD,0x4000000,0x418,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364},{0xC,0x4000000,0x418,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364}},{{0x2,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x2,0x4000000,0x10,0x0,0x0,0x0,0x0,0x0,0x0},{0x2,0x10000000,0x40,0x0,0x0,0x0,0x0,0x0,0x0},{0xA,0x0,0x408,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364},{0x2,0x4000000,0x10,0x0,0x0,0x0,0x0,0x0,0x0}}};
+
+	public static final boolean USE_GLV =true;
+	public static final boolean USE_GS_G2 =true;
+	public static final boolean USE_GS_GT =true;	
+	public static final boolean GT_STRONG=false;
+*/
+// BN454 Curve
+/*
+	public static final int CURVETYPE=WEIERSTRASS;
+	public static final int CURVE_PAIRING_TYPE=BN_CURVE;
+	public static final int CURVE_A = 0;
+	public static final int[] CURVE_B = {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int[] CURVE_Cof = {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+
+	public static final int[] CURVE_Order={0xD,0x210,0x1F80,0x400D884,0x24FC4,0xA27E,0x10024708,0xFC03A9F,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000};
+	public static final int[] CURVE_Gx={0x12,0x270,0x2100,0x1C00D89C,0x25084,0xA284,0x24720,0x10803AA1,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000};
+	public static final int[] CURVE_Gy={0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+
+	public static final int[] CURVE_Bnx={0x1,0x8,0x0,0x2000002,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int[] CURVE_Cru={0x7,0xD8,0x900,0x16002436,0x481,0x1B24,0x168,0x48006C9,0x1600006C,0x10000091,0xD80000D,0x240000,0x0,0x0,0x0,0x0};
+	public static final int[] CURVE_Fra={0x1573B0EC,0x1816E4FE,0xA42E6E0,0x15DDCD87,0x2B17EC7,0x35B9A50,0x15AA1F74,0x1B7B2AC5,0x1CB5A200,0x9937657,0x17389A4A,0x738BADB,0xD92B321,0x3F5F0E6,0x1B1C9E9A,0x25CF3};
+	public static final int[] CURVE_Frb={0xA8C4F27,0x7E91D71,0x15BD3A1F,0x6230B14,0x1D50D1BD,0x1CA50833,0xA5827AB,0x15050FDB,0x74B3887,0x166C9A92,0x19C78A3C,0x199F4886,0x1B6D4F39,0x80A0F61,0x7236169,0x2230C};
+	public static final int[] CURVE_Pxa={0xF02B14,0x1DD1DD61,0x330AEC7,0x178617DE,0x1CEFFF36,0x116D35AF,0x1F879FBF,0x105DBF83,0x8345436,0x13664BCA,0x12EE86B5,0x776BB31,0x14AAFE16,0x41B3478,0x13E03554,0x2807A};
+	public static final int[] CURVE_Pxb={0x45BF266,0xE036876,0x8F0DBA,0xCB5976F,0x10DBC523,0x1723123C,0xBDDA7F4,0x10077CDE,0x11971DE0,0x14F1554A,0x195995EE,0x82E6FD7,0x40D5258,0x1400A58F,0x15A7850B,0x2B2A5};
+	public static final int[] CURVE_Pya={0x1E1B15C7,0x9CD5B5D,0x1571B2D2,0x1E4C048A,0x1474FB5D,0x18E2328C,0x11775519,0x144EF51F,0xF2FAABA,0x438F741,0x1930EAC0,0x144DC38,0x1287A0FE,0x36D8962,0x10011EAF,0x3ACF4};
+	public static final int[] CURVE_Pyb={0x571D60,0x8737DB,0xC4A363B,0x124E308F,0x13A65C7E,0x1387693A,0x10CDDA2F,0x184C096E,0x385175,0x5A34088,0xF17A93C,0x1E194915,0x1903ED91,0x4D6FA9F,0x8D8210B,0x12EDC};
+	public static final int[][] CURVE_W={{0x3,0x40,0x180,0x10000010,0xC0,0x6,0x10000018,0xC00001,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+	public static final int[][][] CURVE_SB={{{0x4,0x50,0x180,0x14000014,0xC0,0x6,0x10000018,0xC00001,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x1,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xA,0x1D0,0x1E00,0x1400D874,0x24F03,0xA278,0x246F0,0xF003A9E,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000}}};
+	public static final int[][] CURVE_WB={{0x0,0x8,0x80,0x2000002,0x40,0x2,0x10000008,0x400000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x5,0xA8,0x700,0xA00182A,0x381,0x121C,0x100,0x3800487,0x4000048,0x61,0x9000009,0x180000,0x0,0x0,0x0,0x0},{0x3,0x58,0x380,0x16000C16,0x1C0,0x90E,0x10000080,0x1C00243,0x12000024,0x10000030,0x4800004,0xC0000,0x0,0x0,0x0,0x0},{0x1,0x18,0x80,0x6000006,0x40,0x2,0x10000008,0x400000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+	public static final int[][][] CURVE_BB={{{0xD,0x208,0x1F80,0x200D882,0x24FC4,0xA27E,0x10024708,0xFC03A9F,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000},{0xC,0x208,0x1F80,0x200D882,0x24FC4,0xA27E,0x10024708,0xFC03A9F,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000},{0xC,0x208,0x1F80,0x200D882,0x24FC4,0xA27E,0x10024708,0xFC03A9F,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000},{0x2,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x1,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xC,0x208,0x1F80,0x200D882,0x24FC4,0xA27E,0x10024708,0xFC03A9F,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000},{0xD,0x208,0x1F80,0x200D882,0x24FC4,0xA27E,0x10024708,0xFC03A9F,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000},{0xC,0x208,0x1F80,0x200D882,0x24FC4,0xA27E,0x10024708,0xFC03A9F,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000}},{{0x2,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x2,0x8,0x0,0x2000002,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x2,0x20,0x0,0x8000008,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xA,0x200,0x1F80,0xD880,0x24FC4,0xA27E,0x10024708,0xFC03A9F,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000},{0x2,0x8,0x0,0x2000002,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+
+	public static final boolean USE_GLV =true;
+	public static final boolean USE_GS_G2 =true;
+	public static final boolean USE_GS_GT =true;	
+	public static final boolean GT_STRONG=false;
+*/
+
+// BLS455 Curve
+/*
+	public static final int CURVETYPE=WEIERSTRASS;
+	public static final int CURVE_PAIRING_TYPE=BLS_CURVE;
+	public static final int CURVE_A = 0;
+	public static final int[] CURVE_B = {0xA,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int[] CURVE_Cof = {0xABFFAAB,0x14AABFFD,0xD52AADA,0x1562AAAB,0x15556AAA,0x2A,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+
+	public static final int[] CURVE_Order={0x1FC00001,0x3FFF,0x10000070,0x1400000,0x1D100,0xF0003A8,0x13C0009,0x1E200,0x180002E0,0x400001,0x4000,0x0,0x0,0x0,0x0,0x0};
+	public static final int[] CURVE_Gx={0x1DFCEDD1,0x16A62EEF,0xE80D3ED,0xB8DE876,0x179C7253,0x182DAB52,0x46CC85F,0x1E571D9C,0x1E8392B1,0x1A155867,0x19E6527C,0x23DC64E,0xABEDA59,0xF20662B,0x17CECC01,0x310A};
+	public static final int[] CURVE_Gy={0x6619B9B,0x27EBCD,0x1BE80A19,0x13B014BA,0x191A4936,0x13911916,0x107A5A3B,0x1DCB0863,0x1F5FB1,0xDE44A9C,0x18E23B2A,0x1FA81FD3,0xB0D6DFA,0xC2FE1EF,0xDDFA7E2,0x3351B};
+
+	public static final int[] CURVE_Bnx={0x800,0x1000004,0x40000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int[] CURVE_Cru={0xAA9,0x9017FE0,0x128DD8AA,0x1F4A321E,0x148FEC90,0x195CDEEA,0xE961AA2,0x168D3B66,0xAFD99D7,0xB989AA6,0x1F9A5724,0x91A05FF,0xE0EF5B,0xAAB9548,0x55555E5,0xAAAAB};
+	public static final int[] CURVE_Fra={0xA2EBF21,0x4E67DEE,0xCDE6590,0xE5EA94E,0x15454985,0x140CFC43,0x7E14D1C,0x1778395A,0x1944F022,0x166BEA1A,0xC3DEEA0,0x9F031A0,0x16A7459,0x1F1D6E00,0x125CFB72,0x72FD4};
+	public static final int[] CURVE_Frb={0x15D1438A,0x1019821D,0x1DCBF01A,0x1CB40187,0x118C70E6,0x18BD5A30,0xB018251,0x13275D08,0xA06E916,0x1C6D0096,0x39BA8ED,0x1F33D460,0x1F768501,0xB8E274F,0x12F85A72,0x37AD6};
+	public static final int[] CURVE_Pxa={0x10C1F542,0x23AF907,0x159F840,0xBAC0E1F,0x133D7766,0x1C034C5D,0x14C5C875,0x1ED0BDA2,0x16A49C71,0x1E9FF62D,0x14F3ACC0,0x1E0C9FEA,0xC4638DE,0x74D18DA,0xBEA0030,0x5D962};
+	public static final int[] CURVE_Pxb={0x749F03D,0xC843773,0xB17BCBA,0x1134AB4B,0x8EA016E,0x1A0D766C,0x58F819E,0x48A1FCC,0xE296F62,0x83370E4,0xC9BA1D5,0x1E43290E,0xEE59A80,0x1FDD85F5,0x1F3819B6,0x1D9F};
+	public static final int[] CURVE_Pya={0x181A77F4,0x191AD22,0x1E9F842A,0x1E1E6CF6,0xD55B9D9,0x1D062533,0x15BB1323,0x7ECBC1,0x1A9EC2EF,0x1EE14CE0,0x1E96B271,0xA794439,0x1C544324,0xE6AD5DC,0x16429B0F,0x448E3};
+	public static final int[] CURVE_Pyb={0x1E1FDBA2,0x1A09DB6C,0xF680D5B,0xFCC6122,0xC488E2A,0x1E489ECD,0x1005617E,0x1CF9EC36,0x1C89ED72,0x16C00D90,0x1563E595,0x1243DDC0,0x8698F9E,0x1BD81E7E,0xF2A0F4A,0x66A0};
+
+// not used
+	public static final int[][] CURVE_W={{},{}};
+	public static final int[][][] CURVE_SB={{{},{}},{{},{}}};
+	public static final int[][] CURVE_WB={{},{},{},{}};
+	public static final int[][][] CURVE_BB={{{},{},{},{}},{{},{},{},{}},{{},{},{},{}},{{},{},{},{}}};
+
+	public static final boolean USE_GLV =true;
+	public static final boolean USE_GS_G2 =true;
+	public static final boolean USE_GS_GT =true;	
+	public static final boolean GT_STRONG=false;
+*/
+
+
+// BNT Curve
+/*
+	public static final int CURVETYPE=WEIERSTRASS;
+	public static final int CURVE_PAIRING_TYPE=BN_CURVE;
+	public static final int CURVE_A = 0;
+	public static final int[] CURVE_B = {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int[] CURVE_Cof = {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+
+	public static final int[] CURVE_Order={0xD30210D,0x13ABBBF4,0xCB2CD8E,0x11A86925,0xD5F00E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120};
+	public static final int[] CURVE_Bnx={0x4081,0x40300,0x10,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int[] CURVE_Cru={0xB4FCD87,0xF5A9EAD,0xEAC47EB,0x19054BE5,0x104C9764,0x18A3B28A,0x12006,0x0,0x0};
+	public static final int[] CURVE_Fra={0xDC80022,0xFAE8A75,0x1EB338D6,0x189209AD,0x13211BE6,0x4F8C850,0x10E53D94,0x12593778,0x1328A2};
+	public static final int[] CURVE_Frb={0xECA6F1,0x53F5582,0x1E65F5D9,0x1C18A27B,0x1A3DEB01,0x10A2832B,0x1456AA9A,0x9136B67,0x10D87E};
+	public static final int[] CURVE_Pxa={0x88E65BB,0x144C3F11,0xA98C4EF,0x18015A39,0x1548B7CC,0xA992820,0xE7AF301,0x19A09826,0x14483F};
+	public static final int[] CURVE_Pxb={0x8DBE2C0,0x133C4440,0x78D214E,0xAFFC3F0,0x51B57B9,0x285318D,0xC0B68FF,0x166709D8,0x87F46};
+	public static final int[] CURVE_Pya={0x20CA1D,0x101623F,0xE67CDB,0x19682CFD,0x19F72C94,0x14E372A1,0xF5D28B1,0x13820561,0x14E8C2};
+	public static final int[] CURVE_Pyb={0x116628F2,0x1EC21BE3,0xF2DF71A,0x144FC2CF,0x172681D0,0xC54163A,0xF47B7B0,0x148C48A9,0x17AFE2};
+	public static final int[] CURVE_Gx ={0xEB4A712,0x14EDDFF7,0x1D192EAF,0x14AAAC29,0xD5F06E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120};
+	public static final int[] CURVE_Gy ={0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int[][] CURVE_W={{0x1838403,0x1321803,0x106660E1,0x3024304,0x600,0x0,0x0,0x0,0x0},{0x8101,0x80600,0x20,0x0,0x0,0x0,0x0,0x0,0x0}};
+	public static final int[][][] CURVE_SB={{{0x1840504,0x13A1E03,0x10666101,0x3024304,0x600,0x0,0x0,0x0,0x0},{0x8101,0x80600,0x20,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x8101,0x80600,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0xBAC9D0A,0x1279A3F1,0x1C4C6CAD,0xEA62620,0xD5EFAE8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120}}};
+	public static final int[][] CURVE_WB={{0x80C080,0xB0A0301,0x10222030,0x100C101,0x200,0x0,0x0,0x0,0x0},{0x88C4A85,0x15A9C820,0x14B71B0D,0x1D5A5F46,0x158868ED,0x106D21B1,0xC004,0x0,0x0},{0x4464583,0x1AD6E590,0xA5B8D8E,0x1EAD2FA3,0x1AC43476,0x83690D8,0x6002,0x0,0x0},{0x814181,0xB120901,0x10222050,0x100C101,0x200,0x0,0x0,0x0,0x0}};
+	public static final int[][][] CURVE_BB={{{0xD2FE08D,0x13A7B8F4,0xCB2CD7E,0x11A86925,0xD5F00E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120},{0xD2FE08C,0x13A7B8F4,0xCB2CD7E,0x11A86925,0xD5F00E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120},{0xD2FE08C,0x13A7B8F4,0xCB2CD7E,0x11A86925,0xD5F00E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120},{0x8102,0x80600,0x20,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x8101,0x80600,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0xD2FE08C,0x13A7B8F4,0xCB2CD7E,0x11A86925,0xD5F00E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120},{0xD2FE08D,0x13A7B8F4,0xCB2CD7E,0x11A86925,0xD5F00E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120},{0xD2FE08C,0x13A7B8F4,0xCB2CD7E,0x11A86925,0xD5F00E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120}},{{0x8102,0x80600,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0x8101,0x80600,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0x8101,0x80600,0x20,0x0,0x0,0x0,0x0,0x0,0x0},{0x8101,0x80600,0x20,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x4082,0x40300,0x10,0x0,0x0,0x0,0x0,0x0,0x0},{0x10202,0x100C00,0x40,0x0,0x0,0x0,0x0,0x0,0x0},{0xD2FA00A,0x13A3B5F4,0xCB2CD6E,0x11A86925,0xD5F00E8,0x159B4B7C,0x53BE82E,0x1B6CA2E0,0x240120},{0x4082,0x40300,0x10,0x0,0x0,0x0,0x0,0x0,0x0}}};
+
+	public static final boolean USE_GLV =true;
+	public static final boolean USE_GS_G2 =true;
+	public static final boolean USE_GS_GT =true;	
+	public static final boolean GT_STRONG=true;
+
+*/
+
+// BLS383 Curve
+
+	public static final int CURVETYPE=WEIERSTRASS;
+	public static final int CURVE_PAIRING_TYPE=BLS_CURVE;
+	public static final int CURVE_A = 0;
+	public static final int[] CURVE_B = {0x9,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int[] CURVE_Cof = {0x52B,0x2A00,0xAAB2CA0,0x5560AAA,0x6055,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+
+	public static final int[] CURVE_Order={0xFFF001,0xFFF8000,0xFE7800,0xBFDE007,0xC5EDF1C,0x3000049,0x910007A,0xC40007F,0x641004C,0x14,0x0,0x0,0x0,0x0};
+	public static final int[] CURVE_Gx={0xD10786B,0xD59B348,0x3F54AD0,0x3477C0E,0x4578B9B,0xBF25B73,0x7BB6F65,0x4F6AC00,0xFF57E9C,0xEFD5830,0xFB6EC02,0xADB9F88,0xEE4BC98,0xB08C};
+	public static final int[] CURVE_Gy={0xD145DDB,0x5DA023,0x5FEF7CC,0x13F518C,0x2B2A66F,0x56EC346,0xC7A925F,0x96F3019,0x981223E,0x9061047,0x8F5BE59,0x4810AD,0x9337671,0x1F390};
+
+	public static final int[] CURVE_Bnx={0x40,0x100,0x110,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int[] CURVE_Cru={0xDA155A9,0xA3AAC4E,0x61E5E3D,0xDF2FE87,0xE632625,0xBCDFAAD,0xD3035A6,0x5123128,0xBEAD683,0xDBF3A2B,0x424190,0x5C5FAB2,0x80A9F7,0x7AC52};
+	public static final int[] CURVE_Fra={0x2B4508B,0x2BA59A9,0x6EEF343,0x63DB7A0,0x1DFBC74,0x40341CB,0x32D55D3,0x1639E9D,0x5CC36D4,0xB19B3F0,0xD86AB98,0xF323EE4,0xB198672,0x5A5F};
+	public static final int[] CURVE_Frb={0x7F904E0,0x81051A9,0xF086A37,0xB7D49A6,0xB7DB8AB,0x8F3EEB8,0xC6C9543,0xEEF7983,0x49CB35D,0x7A65F65,0x7CBFBEC,0x693D177,0x5672384,0x751F2};
+	public static final int[] CURVE_Pxa={0xBAC9472,0x6059885,0xE2DC36D,0x7C4D31D,0x8C88A7,0xBDC90C3,0x1C688FC,0x29F0197,0xC43F167,0x3693539,0x61EB8BF,0xD81E5A5,0x22B56BF,0x4D507};
+	public static final int[] CURVE_Pxb={0x272AB23,0x9B4BD7A,0xF44DCE8,0x7AF19D4,0x3206A34,0x3F6F7B9,0x2A819FB,0x571DD3E,0x635D7EE,0x3A2BA3B,0xC1A126,0xAC28C78,0x17C3E5B,0xEE36};
+	public static final int[] CURVE_Pya={0x77BD4FD,0x81D2309,0xDFDFC6,0xB66072,0xC89A0C,0x41FC959,0x878287A,0x2E1FBCF,0x14EEE65,0x11C230,0x6BB325E,0x2887881,0x859A05C,0x8F40};
+	public static final int[] CURVE_Pyb={0x52C4CE6,0xA5E20A2,0xAFF40C8,0x5907A74,0x2448EF3,0x41760A4,0xFDA199,0xFFEF82B,0x8D4EA49,0xA0F29A1,0x6E4997B,0xAC7F7B8,0xBA88C12,0x1DCAB};
+
+// not used
+	public static final int[][] CURVE_W={{},{}};
+	public static final int[][][] CURVE_SB={{{},{}},{{},{}}};
+	public static final int[][] CURVE_WB={{},{},{},{}};
+	public static final int[][][] CURVE_BB={{{},{},{},{}},{{},{},{},{}},{{},{},{},{}},{{},{},{},{}}};
+
+	public static final boolean USE_GLV =true;
+	public static final boolean USE_GS_G2 =true;
+	public static final boolean USE_GS_GT =true;	
+	public static final boolean GT_STRONG=false;
+
+
+	public static boolean debug=false;
+}
diff --git a/version22/java/ROM64.java b/version22/java/ROM64.java
new file mode 100644
index 0000000..aa7b337
--- /dev/null
+++ b/version22/java/ROM64.java
@@ -0,0 +1,703 @@
+/*
+	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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+public class ROM
+{
+/* Don't Modify from here... */
+	public static final int CHUNK=64; /* Set word size */
+	public static final int NOT_SPECIAL=0;
+	public static final int PSEUDO_MERSENNE=1;
+	public static final int MONTGOMERY_FRIENDLY=2;
+	public static final int GENERALISED_MERSENNE=3;
+	public static final int WEIERSTRASS=0;
+	public static final int EDWARDS=1;
+	public static final int MONTGOMERY=2;
+	public static final int BN_CURVE=0;
+	public static final int BLS_CURVE=1;
+
+/* ...to here */
+
+/*** Enter Some Field details here  ***/
+// BN254 Curve
+//	public static final int MODBITS=254; /* Number of bits in Modulus */
+//	public static final int MOD8=3;  /* Modulus mod 8 */
+//	public static final int BASEBITS=56;
+//	public static final int AES_S=0;  /* AES equivalaent strength if significantly less than group size */
+
+// BN454 Curve
+//	public static final int MODBITS=454; /* Number of bits in Modulus */
+//	public static final int MOD8=3;  /* Modulus mod 8 */
+//	public static final int BASEBITS=60;
+//	public static final int AES_S=128;
+
+// BLS455 Curve
+//	public static final int MODBITS=455; /* Number of bits in Modulus */
+//	public static final int MOD8=3;  /* Modulus mod 8 */
+//	public static final int BASEBITS=60;
+//	public static final int AES_S=128;
+
+// BLS383 Curve
+	public static final int MODBITS=383; /* Number of bits in Modulus */
+	public static final int MOD8=3;  /* Modulus mod 8 */
+	public static final int BASEBITS=56; 
+	public static final int AES_S=0;
+
+
+// HIFIVE Curve
+//	public static final int MODBITS=336;
+//	public static final int MOD8=5; 
+//	public static final int BASEBITS=60;
+//	public static final int AES_S=128;
+
+// GOLDILOCKS
+//	public static final int MODBITS=448;
+//	public static final int MOD8=7;
+//	public static final int BASEBITS=60;
+//	public static final int AES_S=0; 
+
+// NIST384
+//	public static final int MODBITS=384;
+//	public static final int MOD8=7;
+//	public static final int BASEBITS=60;	
+//	public static final int AES_S=0; 
+
+// C41417
+//	public static final int MODBITS=414;
+//	public static final int MOD8=7;
+//	public static final int BASEBITS=60;	
+//	public static final int AES_S=0; 
+
+// NIST521
+//	public static final int MODBITS=521;
+//	public static final int MOD8=7;
+//	public static final int BASEBITS=60;	
+//	public static final int AES_S=0; 
+	
+// BN646 Curve
+//	public static final int MODBITS=646;
+//	public static final int MOD8=3;
+//	public static final int BASEBITS=60;	
+//	public static final int AES_S=192; 
+
+// Curve 25519
+//	public static final int MODBITS=255; 
+//	public static final int MOD8=5;  
+//	public static final int BASEBITS=56;	
+//	public static final int AES_S=0; 
+
+// NIST256 or Brainpool
+//	public static final int MODBITS=256; 
+//	public static final int MOD8=7;  
+//	public static final int BASEBITS=56;	
+//	public static final int AES_S=0; 
+
+// MF254 
+//	public static final int MODBITS=254; 
+//	public static final int MOD8=7;  
+//	public static final int BASEBITS=56;
+//	public static final int AES_S=0; 
+
+// MS255
+//	public static final int MODBITS= 255;
+//	public static final int MOD8= 3;
+//	public static final int BASEBITS=56;
+//	public static final int AES_S=0; 
+
+// MF256
+//	public static final int MODBITS=256; 
+//	public static final int MOD8=7;  
+//	public static final int BASEBITS=56;
+//	public static final int AES_S=0; 
+
+// MS256
+//	public static final int MODBITS= 256;
+//	public static final int MOD8= 3;
+//	public static final int BASEBITS=56;
+//	public static final int AES_S=0; 
+
+// ANSSI
+//  public static final int MODBITS= 256;
+//  public static final int MOD8= 3;
+//	public static final int BASEBITS=56;
+//	public static final int AES_S=0; 
+
+
+/* RSA/DH modulus length as multiple of BIGBITS */
+	public static final int FFLEN=4;
+
+/* Don't Modify from here... */
+	public static final int NLEN=(1+((MODBITS-1)/BASEBITS));
+	public static final int DNLEN=2*NLEN;
+	public static final long BMASK=(((long)1<<BASEBITS)-1);
+	public static final int MODBYTES=(1+(MODBITS-1)/8);
+	public static final int HBITS=BASEBITS/2;
+	public static final long HMASK=(((long)1<<HBITS)-1);
+	public static final int NEXCESS =((int)1<<(CHUNK-BASEBITS-1));
+	public static final long FEXCESS =((long)1<<(BASEBITS*NLEN-MODBITS)); 
+	public static final long OMASK=(long)(-1)<<(MODBITS%BASEBITS);
+	public static final int TBITS=MODBITS%BASEBITS; // Number of active bits in top word 
+	public static final long TMASK=((long)1<<TBITS)-1;
+	public static final int BIGBITS=(MODBYTES*8);
+
+/* Finite field support - for RSA, DH etc. */
+	public static final int FF_BITS=(BIGBITS*FFLEN); /* Finite Field Size in bits - must be 256.2^n */
+	public static final int HFLEN=(FFLEN/2);  /* Useful for half-size RSA private key operations */
+
+	public static final int P_MBITS=MODBYTES*8;
+	public static final long P_OMASK=((long)(-1)<<(P_MBITS%BASEBITS));
+	public static final long P_FEXCESS=((long)1<<(BASEBITS*NLEN-P_MBITS));
+	public static final int P_TBITS=(P_MBITS%BASEBITS);
+
+/* ...to here */
+
+// START SPECIFY FIELD DETAILS HERE
+//*********************************************************************************
+// Curve25519 Modulus 
+//	public static final int MODTYPE=PSEUDO_MERSENNE;
+//	public static final long[] Modulus= {0xFFFFFFFFFFFFEDL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0x7FFFFFFFL};
+//	public static final long MConst=0x13L;
+
+
+// NIST-256 Curve 
+//	public static final int MODTYPE=NOT_SPECIAL;
+//	public static final long[] Modulus= {0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFL,0x0L,0x1000000L,0xFFFFFFFFL};
+//	public static final long MConst=0x1L;
+
+// MF254 Modulus
+//	public static final int MODTYPE=MONTGOMERY_FRIENDLY;
+//	public static final long[] Modulus= {0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0x3F80FFFFL};
+//	public static final long MConst=0x3F810000L;
+
+// MS255 Modulus
+//public static final int MODTYPE= 1;
+//public static final long[] Modulus= {0xFFFFFFFFFFFD03L,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0x7FFFFFFFL};
+//public static final long MConst=0x2FDL;
+
+// MS256 Modulus
+//public static final int MODTYPE= 1;
+//public static final long[] Modulus= {0xFFFFFFFFFFFF43L,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFL};
+//public static final long MConst=0xBDL;
+
+// MF256 Modulus
+//public static final int MODTYPE= 2;
+//public static final long[] Modulus= {0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFA7FFFFL};
+//public static final long MConst=0xFFA80000L;
+
+// Brainpool
+//	public static final int MODTYPE= NOT_SPECIAL;
+//	public static final long[] Modulus= {0x13481D1F6E5377L,0xF623D526202820L,0x909D838D726E3BL,0xA1EEA9BC3E660AL,0xA9FB57DBL};
+//	public static final long MConst=0xA75590CEFD89B9L;
+
+// ANSSI
+//  public static final int MODTYPE= 0;
+//  public static final long[] Modulus= {0xFCF353D86E9C03L,0xADBCABC8CA6DE8L,0xE8CE42435B3961L,0xB3AD58F10126DL,0xF1FD178CL};
+//  public static final long MConst=0x97483A164E1155L;
+
+// BNCX Curve Modulus
+//public static final int MODTYPE=NOT_SPECIAL;
+//public static final long[] Modulus= {0x6623EF5C1B55B3L,0xD6EE18093EE1BEL,0x647A6366D3243FL,0x8702A0DB0BDDFL,0x24000000L};
+//public static final long MConst=0x4E205BF9789E85L;
+
+// HIFIVE Curve
+//public static final int MODTYPE=PSEUDO_MERSENNE;
+//public static final long[] Modulus= {0xFFFFFFFFFFFFFFDL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFL};
+//public static final long MConst=0x3L;
+
+//GOLDILOCKS
+//	public static final int MODTYPE=GENERALISED_MERSENNE;
+//	public static final long[] Modulus={0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFEFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFL};
+//	public static final long MConst=0x1;
+
+// NIST384 Curve Modulus
+//	public static final int MODTYPE=NOT_SPECIAL;
+//	public static final long[] Modulus={0xFFFFFFFFL,0xFFFFFF000000000L,0xFFFFFFFFFFFFEFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFL};
+//	public static final long MConst=0x100000001L;
+
+// C41417 Curve Modulus
+//	public static final int MODTYPE=PSEUDO_MERSENNE;
+//	public static final long[] Modulus={0xFFFFFFFFFFFFFEFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFL};
+//	public static final long MConst=0x11L;
+
+// NIST521
+//	public static final int MODTYPE=PSEUDO_MERSENNE;
+//	public static final long[] Modulus={0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0x1FFFFFFFFFFL};
+//	public static final long MConst=0x1L;
+
+// BN646
+//	public static final int MODTYPE=NOT_SPECIAL;
+//	public static final long[] Modulus=	{0x2406C08404E013L,0x240510420138000L,0xE01920840000000L,0x601B00000901441L,0x400000006C0A206L,0xD814423414402L,0x6C051024000000L,0xD8000000000000L,0x9006CL,0x240000L,0x240000000000L};
+//	public static final long MConst=0xCE50F5CF5F615E5L;		
+
+// BN254 Curve
+//	public static final int MODTYPE=NOT_SPECIAL;
+//	public static final long[] Modulus= {0x13L,0x13A7L,0x80000000086121L,0x40000001BA344DL,0x25236482L};
+//	public static final long MConst=0x435E50D79435E5L;
+
+// BN454 Curve
+//	public static final int MODTYPE=NOT_SPECIAL;
+//	public static final long[] Modulus= {0x4E00000013L,0x4E006C4E0000840L,0x800014508002508L,0x888401D5080091CL,0x21C00021D4400DAL,0x25B06C01B144009L,0xD80000909000L,0x240000900L};
+//	public static final long MConst=0xF33C46ED79435E5L;
+
+// BLS455 Curve
+//	public static final int MODTYPE=NOT_SPECIAL;
+//	public static final long[] Modulus= {0xAA00001800002ABL,0xC589556B2AA956AL,0xB9994ACE86D1BA6L,0x3954FCB314B8B3DL,0xE3A5B1D56234BD9L,0x95B49203003F665L,0x57955572AA00E0FL,0x555559555L};
+//	public static final long MConst=0xB3EF8137F4017FDL;
+
+// BLS383 Curve
+	public static final int MODTYPE=NOT_SPECIAL;
+	public static final long[] Modulus= {0xACAAB52AAD556BL,0x1BB01475F75D7AL,0xCF73083D5D7520L,0x531820F99EB16L,0x2C01355A68EA32L,0x5C6105C552A785L,0x7AC52080A9F7L};
+	public static final long MConst=0xA59AB3B123D0BDL;
+
+
+// BNT Curve
+//	public static final int MODTYPE=NOT_SPECIAL;
+//	public static final long[] Modulus= {0x9DBBFEEEB4A713L,0x555614F464BABEL,0x3696F8D5F06E8AL,0x6517014EFA0BABL,0x240120DBL};
+//	public static final long MConst=0xC5A872D914C4E5L;
+
+// BNT2 Curve
+//	public static final int MODTYPE=NOT_SPECIAL;
+//	public static final long[] Modulus= {0xB2DC2BB460A48BL,0x93E428F0D651E8L,0xF3B89D00081CFL,0x410F5AADB74E20L,0x24000482L};
+//	public static final long MConst=0xFE6A47A6505CDDL;
+
+// START SPECIFY CURVE DETAILS HERE
+//*********************************************************************************
+
+// Ed25519 Curve 
+//	public static final int CURVETYPE=EDWARDS;
+//	public static final int CURVE_A = -1;
+//	public static final long[] CURVE_B = {0xEB4DCA135978A3L,0xA4D4141D8AB75L,0x797779E8980070L,0x2B6FFE738CC740L,0x52036CEEL};
+//	public static final long[] CURVE_Order={0x12631A5CF5D3EDL,0xF9DEA2F79CD658L,0x14DEL,0x0L,0x10000000L};
+//	public static final long[] CURVE_Gx ={0x562D608F25D51AL,0xC7609525A7B2C9L,0x31FDD6DC5C692CL,0xCD6E53FEC0A4E2L,0x216936D3L};
+//	public static final long[] CURVE_Gy ={0x66666666666658L,0x66666666666666L,0x66666666666666L,0x66666666666666L,0x66666666L};
+
+// Original Curve25519 
+//	public static final int CURVETYPE=MONTGOMERY;
+//	public static final int CURVE_A =486662;
+//	public static final long[] CURVE_B = {0x0L,0x0L,0x0L,0x0L,0x0L}; // not used
+//	public static final long[] CURVE_Order={0x12631A5CF5D3EDL,0xF9DEA2F79CD658L,0x14DEL,0x0L,0x10000000L};
+//	public static final long[] CURVE_Gx ={0x9L,0x0L,0x0L,0x0L,0x0L};
+//	public static final long[] CURVE_Gy ={0x0L,0x0L,0x0L,0x0L,0x0L}; // not used
+
+// NIST-256 Curve
+//	public static final int CURVETYPE=WEIERSTRASS;
+//	public static final int CURVE_A = -3;
+//	public static final long[] CURVE_B = {0xCE3C3E27D2604BL,0x6B0CC53B0F63BL,0x55769886BC651DL,0xAA3A93E7B3EBBDL,0x5AC635D8L};
+//	public static final long[] CURVE_Order={0xB9CAC2FC632551L,0xFAADA7179E84F3L,0xFFFFFFFFFFBCE6L,0xFFFFFFL,0xFFFFFFFFL};
+//	public static final long[] CURVE_Gx ={0xA13945D898C296L,0x7D812DEB33A0F4L,0xE563A440F27703L,0xE12C4247F8BCE6L,0x6B17D1F2L};
+//	public static final long[] CURVE_Gy ={0xB6406837BF51F5L,0x33576B315ECECBL,0x4A7C0F9E162BCEL,0xFE1A7F9B8EE7EBL,0x4FE342E2L};
+
+// MF254 Modulus, Weierstrass Curve w-254-mont
+//public static final int CURVETYPE= WEIERSTRASS;
+//public static final int CURVE_A = -3;
+//public static final long[] CURVE_B = {0xFFFFFFFFFFD08DL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0x3F80FFFFL};
+//public static final long[] CURVE_Order={0xA419C4AF8DF83FL,0x8BEA0DA375C06FL,0xFFFFFFFFFFEB81L,0xFFFFFFFFFFFFFFL,0x3F80FFFFL};
+//public static final long[] CURVE_Gx ={0x2L,0x0L,0x0L,0x0L,0x0L};
+//public static final long[] CURVE_Gy ={0x65DF37F90D4EBCL,0x38E3F8511931ADL,0x75BD778AEBDFB7L,0x3B2E56014AE15AL,0x140E3FD3L};
+
+// MF254 Modulus, Edwards Curve ed-254-mont
+//public static final int CURVETYPE= EDWARDS;
+//public static final int CURVE_A = -1;
+//public static final long[] CURVE_B = {0x367BL,0x0L,0x0L,0x0L,0x0L};
+//public static final long[] CURVE_Order={0xF3D3FEC46E98C7L,0x306C8BD62FB0EAL,0xFFFFFFFFFFEB95L,0xFFFFFFFFFFFFFFL,0xFE03FFFL};
+//public static final long[] CURVE_Gx ={0x1L,0x0L,0x0L,0x0L,0x0L};
+//public static final long[] CURVE_Gy ={0x52D0FDAF2701E5L,0x9A840E3212187CL,0xD502363F4E3632L,0xD6A4C335951D00L,0x19F0E690L};
+
+// MF254 Modulus, Montgomery Curve
+//	public static final int CURVETYPE=MONTGOMERY;
+//	public static final int CURVE_A =-55790;
+//	public static final long[] CURVE_B = {0x0L,0x0L,0x0L,0x0L,0x0L}; // not used
+//	public static final long[] CURVE_Order={0xF3D3FEC46E98C7L,0x306C8BD62FB0EAL,0xFFFFFFFFFFEB95L,0xFFFFFFFFFFFFFFL,0xFE03FFFL};
+//	public static final long[] CURVE_Gx ={0x3L,0x0L,0x0L,0x0L,0x0L};
+//	public static final long[] CURVE_Gy ={0x0L,0x0L,0x0L,0x0L,0x0L}; // not used
+
+// MS255 Modulus, Weierstrass Curve
+//public static final int CURVETYPE= WEIERSTRASS;
+//public static final int CURVE_A = -3;
+//public static final long[] CURVE_B = {0xFFFFFFFFFFAB46L,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0x7FFFFFFFL};
+//public static final long[] CURVE_Order={0x8FAC983C594AEBL,0x38283AD2B3DFABL,0xFFFFFFFFFF864AL,0xFFFFFFFFFFFFFFL,0x7FFFFFFFL};
+//public static final long[] CURVE_Gx ={0x1L,0x0L,0x0L,0x0L,0x0L};
+//public static final long[] CURVE_Gy ={0x33FF6769CB44BAL,0xC78CDDFDA60D17L,0xF9B2FF7D177DB6L,0xEDBA7833921EBFL,0x6F7A6AC0L};
+
+// MS255 Modulus, Edwards Curve
+//public static final int CURVETYPE= EDWARDS;
+//public static final int CURVE_A = -1;
+//public static final long[] CURVE_B = {0xEA97L,0x0L,0x0L,0x0L,0x0L};
+//public static final long[] CURVE_Order={0x49D1ED0436EB75L,0xA785EDA6832EACL,0xFFFFFFFFFFDCF1L,0xFFFFFFFFFFFFFFL,0x1FFFFFFFL};
+//public static final long[] CURVE_Gx ={0x4L,0x0L,0x0L,0x0L,0x0L};
+//public static final long[] CURVE_Gy ={0x2A255BD08736A0L,0x4B8AED445A45BAL,0xDD8E0C47E55291L,0x4A7BB545EC254CL,0x26CB7853L};
+
+// MS255 Modulus, Montgomery Curve
+//	public static final int CURVETYPE=MONTGOMERY;
+//	public static final int CURVE_A =-240222;
+//	public static final long[] CURVE_B = {0x0L,0x0L,0x0L,0x0L,0x0L}; // not used
+//	public static final long[] CURVE_Order={0x49D1ED0436EB75L,0xA785EDA6832EACL,0xFFFFFFFFFFDCF1L,0xFFFFFFFFFFFFFFL,0x1FFFFFFFL};
+//	public static final long[] CURVE_Gx ={0x4L,0x0L,0x0L,0x0L,0x0L};
+//	public static final long[] CURVE_Gy ={0x0L,0x0L,0x0L,0x0L,0x0L}; // not used
+
+// MS256, Weierstrass Curve
+//public static final int CURVETYPE= WEIERSTRASS;
+//public static final int CURVE_A = -3;
+//public static final long[] CURVE_B = {0x25581L,0x0L,0x0L,0x0L,0x0L};
+//public static final long[] CURVE_Order={0xAB20294751A825L,0x8275EA265C6020L,0xFFFFFFFFFFE43CL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFL};
+//public static final long[] CURVE_Gx ={0x1L,0x0L,0x0L,0x0L,0x0L};
+//public static final long[] CURVE_Gy ={0xF46306C2B56C77L,0x2F9375894EC10BL,0x6CCEEEDD6BD02CL,0xC1E466D7FC82C9L,0x696F1853L};
+
+// MS256, Edwards Curve
+//public static final int CURVETYPE= EDWARDS;
+//public static final int CURVE_A = -1;
+//public static final long[] CURVE_B = {0x3BEEL,0x0L,0x0L,0x0L,0x0L};
+//public static final long[] CURVE_Order={0xB84E6F1122B4ADL,0xA55AD0A6BC64E5L,0xFFFFFFFFFFBE6AL,0xFFFFFFFFFFFFFFL,0x3FFFFFFFL};
+//public static final long[] CURVE_Gx ={0xDL,0x0L,0x0L,0x0L,0x0L};
+//public static final long[] CURVE_Gy ={0x7F6FB5331CADBAL,0x6D63824D303F70L,0xB39FA046BFBE2AL,0x2A1276DBA3D330L,0x7D0AB41EL};
+
+// MS256 Modulus, Montgomery Curve
+//	public static final int CURVETYPE=MONTGOMERY;
+//	public static final int CURVE_A =-61370;
+//	public static final long[] CURVE_B = {0x0L,0x0L,0x0L,0x0L,0x0L}; // not used
+//  public static final long[] CURVE_Order={0xB84E6F1122B4ADL,0xA55AD0A6BC64E5L,0xFFFFFFFFFFBE6AL,0xFFFFFFFFFFFFFFL,0x3FFFFFFFL};
+//	public static final long[] CURVE_Gx ={0xbL,0x0L,0x0L,0x0L,0x0L};
+//	public static final long[] CURVE_Gy ={0x0L,0x0L,0x0L,0x0L,0x0L}; // not used
+
+// MF256 Modulus, Weierstrass Curve
+//public static final int CURVETYPE= WEIERSTRASS;
+//public static final int CURVE_A = -3;
+//public static final long[] CURVE_B = {0x14E6AL,0x0L,0x0L,0x0L,0x0L};
+//public static final long[] CURVE_Order={0x10C5E1A79857EBL,0x7513E6E5074B9DL,0xFFFFFFFFFFFC51L,0xFFFFFFFFFFFFFFL,0xFFA7FFFFL};
+//public static final long[] CURVE_Gx ={0x1L,0x0L,0x0L,0x0L,0x0L};
+//public static final long[] CURVE_Gy ={0x7954C2B724D2AL,0x47EB8D94DC6610L,0x26123DAE289569L,0xBE1808CE7BABBAL,0x20887C87L};
+
+// MF256, Edwards Curve
+//public static final int CURVETYPE= EDWARDS;
+//public static final int CURVE_A = -1;
+//public static final long[] CURVE_B = {0x350AL,0x0L,0x0L,0x0L,0x0L};
+//public static final long[] CURVE_Order={0xD92EDED8EC7BABL,0xBBAFB86733C966L,0xFFFFFFFFFFB154L,0xFFFFFFFFFFFFFFL,0x3FE9FFFFL};
+//public static final long[] CURVE_Gx ={0x1L,0x0L,0x0L,0x0L,0x0L};
+//public static final long[] CURVE_Gy ={0xEAA722F2F3C908L,0x5E648DFEA68D7DL,0xF3DB2C1AACA0C0L,0xF8CC4D5AEAEBEEL,0xDAD8D4F8L};
+
+// MF256 Modulus, Montgomery Curve
+//	public static final int CURVETYPE=MONTGOMERY;
+//	public static final int CURVE_A =-54314;
+//	public static final long[] CURVE_B = {0x0L,0x0L,0x0L,0x0L,0x0L}; // not used
+//  public static final long[] CURVE_Order={0xD92EDED8EC7BABL,0xBBAFB86733C966L,0xFFFFFFFFFFB154L,0xFFFFFFFFFFFFFFL,0x3FE9FFFFL};
+//	public static final long[] CURVE_Gx ={0x8L,0x0L,0x0L,0x0L,0x0L};
+//	public static final long[] CURVE_Gy ={0x0L,0x0L,0x0L,0x0L,0x0L}; // not used
+
+// Brainpool
+//	public static final int CURVETYPE= 0;
+//	public static final int CURVE_A = -3;
+//	public static final long[] CURVE_B = {0xE58101FEE92B04L,0xEBC4AF2F49256AL,0x733D0B76B7BF93L,0x30D84EA4FE66A7L,0x662C61C4L};
+//	public static final long[] CURVE_Order={0x1E0E82974856A7L,0x7AA3B561A6F790L,0x909D838D718C39L,0xA1EEA9BC3E660AL,0xA9FB57DBL};
+//	public static final long[] CURVE_Gx ={0xA191562E1305F4L,0x42C47AAFBC2B79L,0xB23A656149AFA1L,0xC1CFE7B7732213L,0xA3E8EB3CL};
+//	public static final long[] CURVE_Gy ={0xABE8F35B25C9BEL,0xB6DE39D027001DL,0xE14644417E69BCL,0x3439C56D7F7B22L,0x2D996C82L};
+
+// ANSSI
+//  public static final int CURVETYPE= 0;
+//  public static final int CURVE_A = -3;
+//  public static final long[] CURVE_B = {0x75ED967B7BB73FL,0xC9AE4B1A18030L,0x754A44C00FDFECL,0x5428A9300D4ABAL,0xEE353FCAL};
+//  public static final long[] CURVE_Order={0xFDD459C6D655E1L,0x67E140D2BF941FL,0xE8CE42435B53DCL,0xB3AD58F10126DL,0xF1FD178CL};
+//  public static final long[] CURVE_Gx ={0xC97A2DD98F5CFFL,0xD2DCAF98B70164L,0x4749D423958C27L,0x56C139EB31183DL,0xB6B3D4C3L};
+//  public static final long[] CURVE_Gy ={0x115A1554062CFBL,0xC307E8E4C9E183L,0xF0F3ECEF8C2701L,0xC8B204911F9271L,0x6142E0F7L};
+
+// HIFIVE
+//  public static final int CURVETYPE= EDWARDS;
+//  public static final int CURVE_A = 1;
+//  public static final long[] CURVE_B = {0x2B67L,0x0L,0x0L,0x0L,0x0L,0x0L};
+//  public static final long[] CURVE_Order={0xB2F95973E9FA805L,0xC0BD6B87F93BAA7L,0x71415FA9850L,0x0L,0x0L,0x200000000L};
+//  public static final long[] CURVE_Gx ={0xCL,0x0L,0x0L,0x0L,0x0L,0x0L};
+//  public static final long[] CURVE_Gy ={0x2BEC68505FE8632L,0x5D5650CA0365DB1L,0x3811C7EF435B6DBL,0x7853D1B14B46CL,0x56502E18E1C161DL,0xC0DC616BL};
+
+// GOLDILOCKS
+//	public static final int CURVETYPE= EDWARDS;
+//	public static final int CURVE_A = 1;
+//	public static final long[] CURVE_B = {0xFFFFFFFFFFF6756L,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFEFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFL};
+//	public static final long[] CURVE_Order={0x378C292AB5844F3L,0x6CC2728DC58F552L,0xEDB49AED6369021L,0xFFFF7CCA23E9C44L,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0x3FFFFFFL};
+//	public static final long[] CURVE_Gx ={0x555555555555555L,0x555555555555555L,0x555555555555555L,0xAAA955555555555L,0xAAAAAAAAAAAAAAAL,0xAAAAAAAAAAAAAAAL,0xAAAAAAAAAAAAAAAL,0xAAAAAAAL};
+//	public static final long[] CURVE_Gy ={0xAEAFBCDEA9386EDL,0xBCB2BED1CDA06BDL,0x565833A2A3098BBL,0x6D728AD8C4B80D6L,0x7A035884DD7B7E3L,0x205086C2B0036EDL,0x34AD7048DB359D6L,0xAE05E96L};
+
+// NIST384
+//	public static final int CURVETYPE= WEIERSTRASS;
+//	public static final int CURVE_A = -3;
+//  public static final long[] CURVE_B = {0xA85C8EDD3EC2AEFL,0x56398D8A2ED19D2L,0x4088F5013875AC6L,0x9C6EFE814112031L,0x56BE3F82D19181DL,0xA7E23EE7E4988E0L,0xB3312FL};
+//	public static final long[] CURVE_Order= {0xCEC196ACCC52973L,0x1A0DB248B0A77AEL,0x34D81F4372DDF58L,0xFFFFFFFFFFFFC76L,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFL};
+//	public static final long[] CURVE_Gx = {0xA545E3872760AB7L,0x2F25DBF55296C3L,0x741E082542A3855L,0x3B628BA79B9859FL,0x71EF320AD746E1DL,0x22BE8B05378EB1CL,0xAA87CAL};
+//  public static final long[] CURVE_Gy = {0xA431D7C90EA0E5FL,0x60B1CE1D7E819D7L,0xA3113B5F0B8C00AL,0x1DBD289A147CE9DL,0x8BF9292DC29F8F4L,0x4A96262C6F5D9E9L,0x3617DEL};
+
+// C41417
+//	public static final int CURVETYPE= EDWARDS;
+//	public static final int CURVE_A = 1;
+//  public static final long[] CURVE_B =  {0xE21L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+//	public static final long[] CURVE_Order=	{0xB0E71A5E106AF79L,0x1C0338AD63CF181L,0x414CF706022B36FL,0xFFFFFFFFEB3CC92L,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0x7FFFFFFFFFFFFL};
+//	public static final long[] CURVE_Gx =  {0x4FD3812F3CBC595L,0x1A73FAA8537C64CL,0x4AB4D6D6BA11130L,0x3EC7F57FF35498AL,0xE5FCD46369F44C0L,0x300218C0631C326L,0x1A334905141443L};
+//	public static final long[] CURVE_Gy =  {0x22L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+
+// NIST521
+//	public static final int CURVETYPE= WEIERSTRASS;
+//	public static final int CURVE_A = -3;
+//	public static final long[] CURVE_B = {0xF451FD46B503F00L,0x73DF883D2C34F1EL,0x2C0BD3BB1BF0735L,0x3951EC7E937B165L,0x9918EF109E15619L,0x5B99B315F3B8B48L,0xB68540EEA2DA72L,0x8E1C9A1F929A21AL,0x51953EB961L};
+//	public static final long[] CURVE_Order=	{0xB6FB71E91386409L,0xB5C9B8899C47AEBL,0xC0148F709A5D03BL,0x8783BF2F966B7FCL,0xFFFFFFFFFFA5186L,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0x1FFFFFFFFFFL};
+//	public static final long[] CURVE_Gx = {0x97E7E31C2E5BD66L,0x48B3C1856A429BFL,0xDC127A2FFA8DE33L,0x5E77EFE75928FE1L,0xF606B4D3DBAA14BL,0x39053FB521F828AL,0x62395B4429C6481L,0x404E9CD9E3ECB6L,0xC6858E06B7L};
+//	public static final long[] CURVE_Gy = {0x8BE94769FD16650L,0x3C7086A272C2408L,0xB9013FAD076135L,0x72995EF42640C55L,0xD17273E662C97EEL,0x49579B446817AFBL,0x42C7D1BD998F544L,0x9A3BC0045C8A5FBL,0x11839296A78L};
+
+// BN646 Curve
+/*
+	public static final int CURVETYPE=WEIERSTRASS;
+	public static final int CURVE_PAIRING_TYPE=BN_CURVE;
+	public static final int CURVE_A = 0;
+
+	public static final long[] CURVE_Order={0x2406C07E04200DL,0x2405103F0108000L,0xD418607E0000000L,0x301B00000901441L,0x400000006C0A206L,0xD814422E14402L,0x6C051024000000L,0xD8000000000000L,0x9006CL,0x240000L,0x240000000000L};
+	public static final long[] CURVE_B= {0x2L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+	public static final long[] CURVE_Cof= {0x1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+	public static final long[] CURVE_Gx={0x2406C08404E012L,0x240510420138000L,0xE01920840000000L,0x601B00000901441L,0x400000006C0A206L,0xD814423414402L,0x6C051024000000L,0xD8000000000000L,0x9006CL,0x240000L,0x240000000000L};
+	public static final long[] CURVE_Gy={0x1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+
+	public static final long[] CURVE_Bnx={0x1001L,0x4000L,0x10000000000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+	public static final long[] CURVE_Cru={0x1202401B007L,0xD812006C000L,0x480510240000000L,0x200480000000360L,0x1B01L,0x3602403600L,0xD800000000L,0x0L,0x12L,0x0L,0x0L};
+	public static final long[] CURVE_Fra={0x76EAD944929A14L,0xB7E0A0BE10CDF74L,0x4FB8A8A2B93166BL,0xECDFC4B0F037D9L,0xC27307962815598L,0xCF5EF558D2135D8L,0x8CE651FD85AF9C3L,0x80AF6D02A45219FL,0x69B8147979A41A4L,0x9577C152A374C5BL,0x9FF28B3A478L};
+	public static final long[] CURVE_Frb={0xFAD1BE73F7245FFL,0x6C246F83F06A08BL,0x906077E146CE994L,0x514D03B4F9FDC68L,0x7D8CF86A43F4C6EL,0x31791EE96200E29L,0x79D9FF04BA5063CL,0x8CD092FD5BADE60L,0x9647EB8686EBEC7L,0x6A883EAD5ECB3A4L,0x1A00D74C5B87L};
+	public static final long[] CURVE_Pxa={0x4233F273CCC5E10L,0x6408117FB1B1FFAL,0xA7978AC166486AAL,0xDA6417BDCFDC1D0L,0xDCE981D68FA7F5CL,0x4169ED790F45048L,0xBA06CCE894F26BEL,0xB0C98247FD18141L,0x30CE35212F353A6L,0xFF9A1B9162B0B9EL,0xFD835F078BFL};
+	public static final long[] CURVE_Pxb={0x837F879267F4BC0L,0x443F1581FA770EDL,0x8FBA0763CB82027L,0xA8F7E5DE4945F11L,0x780AAE5D219F786L,0xF3BB745205342E9L,0xCC0A34FF057013CL,0xA6DFAF3E689709EL,0xD69FBD8D12B6B79L,0x6A1715D9469215DL,0x1764FA509C41L};
+	public static final long[] CURVE_Pya={0xC570D1DCC3FB414L,0xD0ABFE7F36161E4L,0xABA2F61496C849AL,0x4E4A05030CD4F3FL,0x70F7CECD5CEF83L,0x9D4711CBF491613L,0xDF8011EA770418EL,0x56548E514EC94ECL,0xC9E853DFF35EE42L,0x5481ABBAAD13633L,0x78D8A63783FL};
+	public static final long[] CURVE_Pyb={0xAFE3E3DB33908ADL,0x7CD4290A506594CL,0xFA043D85973EC3FL,0xFAC7A642BB5E628L,0x71A36A52DA82EE2L,0x12C2231EDAE0C76L,0x994DF2771091B48L,0xCFFF7637B76831CL,0xD463BD03DA14916L,0x1074F23C580C40L,0x12188D99546BL};
+	public static final long[][] CURVE_W={{0x6008003L,0x30020000L,0xC0080060000000L,0x300000000000000L,0x0L,0x600000L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x2001L,0x8000L,0x20000000000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}};
+	public static final long[][][] CURVE_SB={{{0x600A004L,0x30028000L,0xC00A0060000000L,0x300000000000000L,0x0L,0x600000L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x2001L,0x8000L,0x20000000000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x2001L,0x8000L,0x20000000000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x2406C07803A00AL,0x2405103C00E8000L,0xC817E0780000000L,0x1B00000901441L,0x400000006C0A206L,0xD814422814402L,0x6C051024000000L,0xD8000000000000L,0x9006CL,0x240000L,0x240000000000L}}};
+	public static final long[][] CURVE_WB={{0x2001000L,0x10004000L,0x40010020000000L,0x100000000000000L,0x0L,0x200000L,0x0L,0x0L,0x0L,0x0L,0x0L},{0xC01C015005L,0x900E0054000L,0x3803901C0000000L,0xE00300000000240L,0x1200L,0x2401C02400L,0x9000000000L,0x0L,0xCL,0x0L,0x0L},{0x600E00B003L,0x4807002C000L,0x1C01D00E0000000L,0x700180000000120L,0x900L,0x1200E01200L,0x4800000000L,0x0L,0x6L,0x0L,0x0L},{0x2003001L,0x1000C000L,0x40030020000000L,0x100000000000000L,0x0L,0x200000L,0x0L,0x0L,0x0L,0x0L,0x0L}};
+	public static final long[][][] CURVE_BB={{{0x2406C07E04100DL,0x2405103F0104000L,0xD418507E0000000L,0x301B00000901441L,0x400000006C0A206L,0xD814422E14402L,0x6C051024000000L,0xD8000000000000L,0x9006CL,0x240000L,0x240000000000L},{0x2406C07E04100CL,0x2405103F0104000L,0xD418507E0000000L,0x301B00000901441L,0x400000006C0A206L,0xD814422E14402L,0x6C051024000000L,0xD8000000000000L,0x9006CL,0x240000L,0x240000000000L},{0x2406C07E04100CL,0x2405103F0104000L,0xD418507E0000000L,0x301B00000901441L,0x400000006C0A206L,0xD814422E14402L,0x6C051024000000L,0xD8000000000000L,0x9006CL,0x240000L,0x240000000000L},{0x2002L,0x8000L,0x20000000000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x2001L,0x8000L,0x20000000000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x2406C07E04100CL,0x2405103F0104000L,0xD418507E0000000L,0x301B00000901441L,0x400000006C0A206L,0xD814422E14402L,0x6C051024000000L,0xD8000000000000L,0x9006CL,0x240000L,0x240000000000L},{0x2406C07E04100DL,0x2405103F0104000L,0xD418507E0000000L,0x301B00000901441L,0x400000006C0A206L,0xD814422E14402L,0x6C051024000000L,0xD8000000000000L,0x9006CL,0x240000L,0x240000000000L},{0x2406C07E04100CL,0x2405103F0104000L,0xD418507E0000000L,0x301B00000901441L,0x400000006C0A206L,0xD814422E14402L,0x6C051024000000L,0xD8000000000000L,0x9006CL,0x240000L,0x240000000000L}},{{0x2002L,0x8000L,0x20000000000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x2001L,0x8000L,0x20000000000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x2001L,0x8000L,0x20000000000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x2001L,0x8000L,0x20000000000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x1002L,0x4000L,0x10000000000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x4002L,0x10000L,0x40000000000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x2406C07E04000AL,0x2405103F0100000L,0xD418407E0000000L,0x301B00000901441L,0x400000006C0A206L,0xD814422E14402L,0x6C051024000000L,0xD8000000000000L,0x9006CL,0x240000L,0x240000000000L},{0x1002L,0x4000L,0x10000000000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}}};
+
+	public static final boolean USE_GLV =true;
+	public static final boolean USE_GS_G2 =true;
+	public static final boolean USE_GS_GT =true;	
+	public static final boolean GT_STRONG=false;
+*/
+// BNCX Curve 
+/*
+	public static final int CURVETYPE=WEIERSTRASS;
+	public static final int CURVE_PAIRING_TYPE=BN_CURVE;
+	public static final int CURVE_A = 0;
+	public static final long[] CURVE_B = {0x2L,0x0L,0x0L,0x0L,0x0L};
+	public static final long[] CURVE_Cof = {0x1L,0x0L,0x0L,0x0L,0x0L};
+	public static final long[] CURVE_Order={0x11C0A636EB1F6DL,0xD6EE0CC906CEBEL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L};
+	public static final long[] CURVE_Bnx={0x3C012B1L,0x40L,0x0L,0x0L,0x0L};
+	public static final long[] CURVE_Cru={0xE0931794235C97L,0xDF6471EF875631L,0xCA83F1440BDL,0x480000L,0x0L};
+	public static final long[] CURVE_Fra={0xD9083355C80EA3L,0x7326F173F8215BL,0x8AACA718986867L,0xA63A0164AFE18BL,0x1359082FL};
+	public static final long[] CURVE_Frb={0x8D1BBC06534710L,0x63C7269546C062L,0xD9CDBC4E3ABBD8L,0x623628A900DC53L,0x10A6F7D0L};
+	public static final long[] CURVE_Pxa={0x851CEEE4D2EC74L,0x85BFA03E2726C0L,0xF5C34BBB907CL,0x7053B256358B25L,0x19682D2CL};
+	public static final long[] CURVE_Pxb={0xA58E8B2E29CFE1L,0x97B0C209C30F47L,0x37A8E99743F81BL,0x3E19F64AA011C9L,0x1466B9ECL};
+	public static final long[] CURVE_Pya={0xFBFCEBCF0BE09FL,0xB33D847EC1B30CL,0x157DAEE2096361L,0x72332B8DD81E22L,0xA79EDD9L};
+	public static final long[] CURVE_Pyb={0x904B228898EE9DL,0x4EA569D2EDEBEDL,0x512D8D3461C286L,0xECC4C09035C6E4L,0x6160C39L};
+	public static final long[] CURVE_Gx ={0x6623EF5C1B55B2L,0xD6EE18093EE1BEL,0x647A6366D3243FL,0x8702A0DB0BDDFL,0x24000000L};
+	public static final long[] CURVE_Gy ={0x1L,0x0L,0x0L,0x0L,0x0L};
+	public static final long[][] CURVE_W={{0x546349162FEB83L,0xB40381200L,0x6000L,0x0L,0x0L},{0x7802561L,0x80L,0x0L,0x0L,0x0L}};
+	public static final long[][][] CURVE_SB={{{0x5463491DB010E4L,0xB40381280L,0x6000L,0x0L,0x0L},{0x7802561L,0x80L,0x0L,0x0L,0x0L}},{{0x7802561L,0x80L,0x0L,0x0L,0x0L},{0xBD5D5D20BB33EAL,0xD6EE0188CEBCBDL,0x647A6366D2643FL,0x8702A0DB0BDDFL,0x24000000L}}};
+	public static final long[][] CURVE_WB={{0x1C2118567A84B0L,0x3C012B040L,0x2000L,0x0L,0x0L},{0xCDF995BE220475L,0x94EDA8CA7F9A36L,0x8702A0DC07EL,0x300000L,0x0L},{0x66FCCAE0F10B93L,0x4A76D4653FCD3BL,0x4381506E03FL,0x180000L,0x0L},{0x1C21185DFAAA11L,0x3C012B0C0L,0x2000L,0x0L,0x0L}};
+	public static final long[][][] CURVE_BB={{{0x11C0A6332B0CBDL,0xD6EE0CC906CE7EL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L},{0x11C0A6332B0CBCL,0xD6EE0CC906CE7EL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L},{0x11C0A6332B0CBCL,0xD6EE0CC906CE7EL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L},{0x7802562L,0x80L,0x0L,0x0L,0x0L}},{{0x7802561L,0x80L,0x0L,0x0L,0x0L},{0x11C0A6332B0CBCL,0xD6EE0CC906CE7EL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L},{0x11C0A6332B0CBDL,0xD6EE0CC906CE7EL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L},{0x11C0A6332B0CBCL,0xD6EE0CC906CE7EL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L}},{{0x7802562L,0x80L,0x0L,0x0L,0x0L},{0x7802561L,0x80L,0x0L,0x0L,0x0L},{0x7802561L,0x80L,0x0L,0x0L,0x0L},{0x7802561L,0x80L,0x0L,0x0L,0x0L}},{{0x3C012B2L,0x40L,0x0L,0x0L,0x0L},{0xF004AC2L,0x100L,0x0L,0x0L,0x0L},{0x11C0A62F6AFA0AL,0xD6EE0CC906CE3EL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L},{0x3C012B2L,0x40L,0x0L,0x0L,0x0L}}};
+
+	public static final boolean USE_GLV =true;
+	public static final boolean USE_GS_G2 =true;
+	public static final boolean USE_GS_GT =true;	
+	public static final boolean GT_STRONG=true;
+*/
+// BNT Curve
+/*
+public static final int CURVETYPE=WEIERSTRASS;
+public static final int CURVE_PAIRING_TYPE=BN_CURVE;
+public static final int CURVE_A = 0;
+public static final long[] CURVE_B = {0x2L,0x0L,0x0L,0x0L,0x0L};
+public static final long[] CURVE_Cof = {0x1L,0x0L,0x0L,0x0L,0x0L};
+public static final long[] CURVE_Order={0x75777E8D30210DL,0xD43492B2CB363AL,0x3696F8D5F00E88L,0x6517014EFA0BABL,0x240120DBL};
+public static final long[] CURVE_Bnx={0x806000004081L,0x40L,0x0L,0x0L,0x0L};
+public static final long[] CURVE_Cru={0xEB53D5AB4FCD87L,0x82A5F2BAB11FADL,0x47651504C9764CL,0x4801B1L,0x0L};
+public static final long[] CURVE_Fra={0xF5D14EADC80022L,0x4904D6FACCE359L,0xF190A13211BE6CL,0xC9BBC4394F6509L,0x1328A292L};
+public static final long[] CURVE_Frb={0xA7EAB040ECA6F1L,0xC513DF997D764L,0x450657A3DEB01EL,0x9B5B3D15AAA6A1L,0x10D87E48L};
+public static final long[] CURVE_Pxa={0x8987E2288E65BBL,0xAD1CAA6313BEL,0x325041548B7CCCL,0x4C1339EBCC055L,0x14483FCDL};
+public static final long[] CURVE_Pxb={0x67888808DBE2C0L,0x7FE1F81E34853AL,0xA631A51B57B95L,0x384EC302DA3FC5L,0x87F46B3L};
+public static final long[] CURVE_Pya={0x202C47E020CA1DL,0xB4167E8399F36CL,0xC6E5439F72C94CL,0x102B0BD74A2C69L,0x14E8C29CL};
+public static final long[] CURVE_Pyb={0xD8437C716628F2L,0x27E167BCB7DC6BL,0xA82C7572681D0AL,0x62454BD1EDEC18L,0x17AFE2A4L};
+public static final long[] CURVE_Gx ={0x9DBBFEEEB4A712L,0x555614F464BABEL,0x3696F8D5F06E8AL,0x6517014EFA0BABL,0x240120DBL};
+public static final long[] CURVE_Gy ={0x1L,0x0L,0x0L,0x0L,0x0L};
+public static final long[][] CURVE_W={{0x26430061838403L,0x81218241998384L,0x6001L,0x0L,0x0L},{0x100C000008101L,0x80L,0x0L,0x0L,0x0L}};
+public static final long[][][] CURVE_SB={{{0x2743C061840504L,0x81218241998404L,0x6001L,0x0L,0x0L},{0x100C000008101L,0x80L,0x0L,0x0L,0x0L}},{{0x100C000008101L,0x80L,0x0L,0x0L,0x0L},{0x4F347E2BAC9D0AL,0x5313107131B2B6L,0x3696F8D5EFAE87L,0x6517014EFA0BABL,0x240120DBL}}};
+public static final long[][] CURVE_WB={{0x6140602080C080L,0x806080C08880C1L,0x2000L,0x0L,0x0L},{0xB53904088C4A85L,0xAD2FA352DC6C36L,0xDA436358868EDEL,0x300120L,0x0L},{0x5ADCB204464583L,0x5697D1A96E363BL,0x6D21B1AC43476FL,0x180090L,0x0L},{0x62412020814181L,0x806080C0888141L,0x2000L,0x0L,0x0L}};
+public static final long[][][] CURVE_BB={{{0x74F71E8D2FE08DL,0xD43492B2CB35FAL,0x3696F8D5F00E88L,0x6517014EFA0BABL,0x240120DBL},{0x74F71E8D2FE08CL,0xD43492B2CB35FAL,0x3696F8D5F00E88L,0x6517014EFA0BABL,0x240120DBL},{0x74F71E8D2FE08CL,0xD43492B2CB35FAL,0x3696F8D5F00E88L,0x6517014EFA0BABL,0x240120DBL},{0x100C000008102L,0x80L,0x0L,0x0L,0x0L}},{{0x100C000008101L,0x80L,0x0L,0x0L,0x0L},{0x74F71E8D2FE08CL,0xD43492B2CB35FAL,0x3696F8D5F00E88L,0x6517014EFA0BABL,0x240120DBL},{0x74F71E8D2FE08DL,0xD43492B2CB35FAL,0x3696F8D5F00E88L,0x6517014EFA0BABL,0x240120DBL},{0x74F71E8D2FE08CL,0xD43492B2CB35FAL,0x3696F8D5F00E88L,0x6517014EFA0BABL,0x240120DBL}},{{0x100C000008102L,0x80L,0x0L,0x0L,0x0L},{0x100C000008101L,0x80L,0x0L,0x0L,0x0L},{0x100C000008101L,0x80L,0x0L,0x0L,0x0L},{0x100C000008101L,0x80L,0x0L,0x0L,0x0L}},{{0x806000004082L,0x40L,0x0L,0x0L,0x0L},{0x2018000010202L,0x100L,0x0L,0x0L,0x0L},{0x7476BE8D2FA00AL,0xD43492B2CB35BAL,0x3696F8D5F00E88L,0x6517014EFA0BABL,0x240120DBL},{0x806000004082L,0x40L,0x0L,0x0L,0x0L}}};
+
+	public static final boolean USE_GLV =true;
+	public static final boolean USE_GS_G2 =true;
+	public static final boolean USE_GS_GT =true;	
+	public static final boolean GT_STRONG=true;
+
+*/
+
+// BNT2 Curve
+/*
+	public static final int CURVETYPE=WEIERSTRASS;
+	public static final int CURVE_PAIRING_TYPE=BN_CURVE;
+	public static final int CURVE_A = 0;
+	public static final long[] CURVE_B = {0x2L,0x0L,0x0L,0x0L,0x0L};
+	public static final long[] CURVE_Cof = {0x1L,0x0L,0x0L,0x0L,0x0L};
+	public static final long[] CURVE_Order={0xFB71A511AA2BF5L,0x8DE127B73833D7L,0xF3B89D00021CFL,0x410F5AADB74E20L,0x24000482L};
+	public static final long[] CURVE_Bnx={0x20100608205L,0x40L,0x0L,0x0L,0x0L};
+	public static final long[] CURVE_Cru={0x5027444866BD33L,0x5B773016470EFBL,0xC3617BECF23675L,0x480006L,0x0L};
+	public static final long[] CURVE_Fra={0xB268C973AEF062L,0xC69B33C3BCE492L,0xF67FA37F195BBCL,0x29E8CAB6BD0A41L,0x124E0B8DL};
+	public static final long[] CURVE_Frb={0x736240B1B429L,0xCD48F52D196D56L,0x18BBE650E72612L,0x17268FF6FA43DEL,0x11B1F8F5L};
+	public static final long[] CURVE_Pxa={0xCC92399F40A3C8L,0xCDA4E96611784AL,0x7B056961706B35L,0x9693C6318279D7L,0x16FC17CFL};
+	public static final long[] CURVE_Pxb={0x557A8AD8549540L,0x6F7BE6F6510610L,0x565907A95D17DBL,0xBD5975909C8188L,0x1EB5B500L};
+	public static final long[] CURVE_Pya={0x7BECC514220513L,0x4A78860E737B14L,0x51B83935F12684L,0x761422AA9D4DFAL,0x1E8EE498L};
+	public static final long[] CURVE_Pyb={0xB9328F577CE78EL,0xB746E26FA5781FL,0xA93DBC1FB8E27EL,0xBAE33BDBA29D76L,0x23CEF4CDL};
+	public static final long[] CURVE_Gx ={0xB2DC2BB460A48AL,0x93E428F0D651E8L,0xF3B89D00081CFL,0x410F5AADB74E20L,0x24000482L};
+	public static final long[] CURVE_Gy ={0x1L,0x0L,0x0L,0x0L,0x0L};
+	public static final long[][] CURVE_W={{0xB76282A1347083L,0x60301399E1D10L,0x6000L,0x0L,0x0L},{0x40200C10409L,0x80L,0x0L,0x0L,0x0L}};
+	public static final long[][][] CURVE_SB={{{0xB76684A1F5748CL,0x60301399E1D90L,0x6000L,0x0L,0x0L},{0x40200C10409L,0x80L,0x0L,0x0L,0x0L}},{{0x40200C10409L,0x80L,0x0L,0x0L,0x0L},{0x440F227075BB72L,0x87DE267D9A16C7L,0xF3B89CFFFC1CFL,0x410F5AADB74E20L,0x24000482L}}};
+	public static final long[][] CURVE_WB={{0x9272D48A70A224L,0x20100688A0945L,0x2000L,0x0L,0x0L},{0x5A572CF030EF19L,0x9651763543721DL,0x8240FD48A1B9A3L,0x300004L,0x0L},{0xAD2C96F848B88FL,0xCB28BB1AA1B92EL,0x41207EA450DCD1L,0x180002L,0x0L},{0x9276D68B31A62DL,0x20100688A09C5L,0x2000L,0x0L,0x0L}};
+	public static final long[][][] CURVE_BB={{{0xFB6FA41149A9F1L,0x8DE127B7383397L,0xF3B89D00021CFL,0x410F5AADB74E20L,0x24000482L},{0xFB6FA41149A9F0L,0x8DE127B7383397L,0xF3B89D00021CFL,0x410F5AADB74E20L,0x24000482L},{0xFB6FA41149A9F0L,0x8DE127B7383397L,0xF3B89D00021CFL,0x410F5AADB74E20L,0x24000482L},{0x40200C1040AL,0x80L,0x0L,0x0L,0x0L}},{{0x40200C10409L,0x80L,0x0L,0x0L,0x0L},{0xFB6FA41149A9F0L,0x8DE127B7383397L,0xF3B89D00021CFL,0x410F5AADB74E20L,0x24000482L},{0xFB6FA41149A9F1L,0x8DE127B7383397L,0xF3B89D00021CFL,0x410F5AADB74E20L,0x24000482L},{0xFB6FA41149A9F0L,0x8DE127B7383397L,0xF3B89D00021CFL,0x410F5AADB74E20L,0x24000482L}},{{0x40200C1040AL,0x80L,0x0L,0x0L,0x0L},{0x40200C10409L,0x80L,0x0L,0x0L,0x0L},{0x40200C10409L,0x80L,0x0L,0x0L,0x0L},{0x40200C10409L,0x80L,0x0L,0x0L,0x0L}},{{0x20100608206L,0x40L,0x0L,0x0L,0x0L},{0x80401820812L,0x100L,0x0L,0x0L,0x0L},{0xFB6DA310E927EAL,0x8DE127B7383357L,0xF3B89D00021CFL,0x410F5AADB74E20L,0x24000482L},{0x20100608206L,0x40L,0x0L,0x0L,0x0L}}};
+
+	public static final boolean USE_GLV =true;
+	public static final boolean USE_GS_G2 =true;
+	public static final boolean USE_GS_GT =true;	
+	public static final boolean GT_STRONG=true;
+*/
+
+// BN254 Curve
+/*
+	public static final int CURVETYPE=WEIERSTRASS;
+	public static final int CURVE_PAIRING_TYPE=BN_CURVE;
+	public static final int CURVE_A = 0;
+	public static final long[] CURVE_B = {0x2L,0x0L,0x0L,0x0L,0x0L};
+	public static final long[] CURVE_Cof = {0x1L,0x0L,0x0L,0x0L,0x0L};
+	public static final long[] CURVE_Order={0xDL,0x800000000010A1L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L};
+	public static final long[] CURVE_Bnx={0x80000000000001L,0x40L,0x0L,0x0L,0x0L};
+	public static final long[] CURVE_Cru={0x80000000000007L,0x6CDL,0x40000000024909L,0x49B362L,0x0L};
+	public static final long[] CURVE_Fra={0x7DE6C06F2A6DE9L,0x74924D3F77C2E1L,0x50A846953F8509L,0x212E7C8CB6499BL,0x1B377619L};
+	public static final long[] CURVE_Frb={0x82193F90D5922AL,0x8B6DB2C08850C5L,0x2F57B96AC8DC17L,0x1ED1837503EAB2L,0x9EBEE69L};
+	public static final long[] CURVE_Pxa={0xEE4224C803FB2BL,0x8BBB4898BF0D91L,0x7E8C61EDB6A464L,0x519EB62FEB8D8CL,0x61A10BBL};
+	public static final long[] CURVE_Pxb={0x8C34C1E7D54CF3L,0x746BAE3784B70DL,0x8C5982AA5B1F4DL,0xBA737833310AA7L,0x516AAF9L};
+	public static final long[] CURVE_Pya={0xF0E07891CD2B9AL,0xAE6BDBE09BD19L,0x96698C822329BDL,0x6BAF93439A90E0L,0x21897A0L};
+	public static final long[] CURVE_Pyb={0x2D1AEC6B3ACE9BL,0x6FFD739C9578AL,0x56F5F38D37B090L,0x7C8B15268F6D44L,0xEBB2B0EL};
+	public static final long[] CURVE_Gx ={0x12L,0x13A7L,0x80000000086121L,0x40000001BA344DL,0x25236482L};
+	public static final long[] CURVE_Gy ={0x1L,0x0L,0x0L,0x0L,0x0L};
+	public static final long[][] CURVE_W={{0x3L,0x80000000000204L,0x6181L,0x0L,0x0L},{0x1L,0x81L,0x0L,0x0L,0x0L}};
+	public static final long[][][] CURVE_SB={{{0x4L,0x80000000000285L,0x6181L,0x0L,0x0L},{0x1L,0x81L,0x0L,0x0L,0x0L}},{{0x1L,0x81L,0x0L,0x0L,0x0L},{0xAL,0xE9DL,0x80000000079E1EL,0x40000001BA344DL,0x25236482L}}};
+	public static final long[][] CURVE_WB={{0x80000000000000L,0x80000000000040L,0x2080L,0x0L,0x0L},{0x80000000000005L,0x54AL,0x8000000001C707L,0x312241L,0x0L},{0x80000000000003L,0x800000000002C5L,0xC000000000E383L,0x189120L,0x0L},{0x80000000000001L,0x800000000000C1L,0x2080L,0x0L,0x0L}};
+	public static final long[][][] CURVE_BB={{{0x8000000000000DL,0x80000000001060L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L},{0x8000000000000CL,0x80000000001060L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L},{0x8000000000000CL,0x80000000001060L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L},{0x2L,0x81L,0x0L,0x0L,0x0L}},{{0x1L,0x81L,0x0L,0x0L,0x0L},{0x8000000000000CL,0x80000000001060L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L},{0x8000000000000DL,0x80000000001060L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L},{0x8000000000000CL,0x80000000001060L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L}},{{0x2L,0x81L,0x0L,0x0L,0x0L},{0x1L,0x81L,0x0L,0x0L,0x0L},{0x1L,0x81L,0x0L,0x0L,0x0L},{0x1L,0x81L,0x0L,0x0L,0x0L}},{{0x80000000000002L,0x40L,0x0L,0x0L,0x0L},{0x2L,0x102L,0x0L,0x0L,0x0L},{0xAL,0x80000000001020L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L},{0x80000000000002L,0x40L,0x0L,0x0L,0x0L}}};
+
+	public static final boolean USE_GLV =true;
+	public static final boolean USE_GS_G2 =true;
+	public static final boolean USE_GS_GT =true;	
+	public static final boolean GT_STRONG=false;
+
+*/
+// BN454 Curve
+/*
+	public static final int CURVETYPE=WEIERSTRASS;
+	public static final int CURVE_PAIRING_TYPE=BN_CURVE;
+	public static final int CURVE_A = 0;
+	public static final long[] CURVE_Order={0x420000000DL,0x42006C4200007E0L,0x2000144FC0024FCL,0x887E01D4FC0091CL,0x21C00021D4400DAL,0x25B06C01B144009L,0xD80000909000L,0x240000900L};
+	public static final long[] CURVE_B= {0x2L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+	public static final long[] CURVE_Cof= {0x1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+	public static final long[] CURVE_Gx={0x4E00000012L,0x4E006C4E0000840L,0x800014508002508L,0x888401D5080091CL,0x21C00021D4400DAL,0x25B06C01B144009L,0xD80000909000L,0x240000900L};
+	public static final long[] CURVE_Gy={0x1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+
+	public static final long[] CURVE_Bnx={0x100000001L,0x10000010000000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+	public static final long[] CURVE_Cru={0x1B00000007L,0x1B00121B0000240L,0xA00003648000048L,0x6C2400364800005L,0x36000012360000L,0x12000036000L,0x0L,0x0L};
+	public static final long[] CURVE_Fra={0x302DC9FD573B0ECL,0x7AEEE6C3A90B9B8L,0xD06B734A02B17ECL,0xDBD9562D6A87DL,0x929326ECAFCB5A2L,0x32139C5D6DDCE26L,0x7A687EBE1CCD92BL,0x12E79EC72L};
+	public static final long[] CURVE_Frb={0xCFD23AE2A8C4F27L,0xD311858A56F4E87L,0xAF94A1067D50D1BL,0x87A8287EDA9609EL,0x8F2CD9352474B38L,0xF39CCFA443671E2L,0x85A50141EC3B6D4L,0x111861C8DL};
+	public static final long[] CURVE_Pxa={0xFBA3BAC20F02B14L,0x6BC30BEF0CC2BB1L,0xFE2DA6B5FCEFFF3L,0x3682EDFC1FE1E7EL,0xAD66CC979483454L,0xE163BB5D98CBBA1L,0xD55083668F14AAFL,0x1403D4F80L};
+	public static final long[] CURVE_Pxb={0x9C06D0EC45BF266L,0x365ACBB7823C36EL,0xD2E4624790DBC52L,0xE0803BE6F2F769FL,0x7BA9E2AA951971DL,0x25841737EBE5665L,0x142E8014B1E40D5L,0x15952D69EL};
+	public static final long[] CURVE_Pya={0x939AB6BBE1B15C7L,0xDF26024555C6CB4L,0x671C46519474FB5L,0xBAA277A8FC5DD54L,0xB00871EE82F2FAAL,0xFE0A26E1C64C3AL,0x7ABC6DB12C5287AL,0x1D67A4004L};
+	public static final long[] CURVE_Pyb={0xC10E6FB60571D60L,0xE9271847B128D8EL,0xBE70ED2753A65C7L,0x75C2604B7433768L,0x4F0B46811003851L,0xD91F0CA48ABC5EAL,0x842C9ADF53F903EL,0x976E2360L};
+	public static final long[][] CURVE_W={{0x800000003L,0x80000080000060L,0x60000000C00000CL,0x600000C00000L,0x0L,0x0L,0x0L,0x0L},{0x200000001L,0x20000020000000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}};
+	public static final long[][][] CURVE_SB={{{0xA00000004L,0xA00000A0000060L,0x60000000C00000CL,0x600000C00000L,0x0L,0x0L,0x0L,0x0L},{0x200000001L,0x20000020000000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x200000001L,0x20000020000000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x3A0000000AL,0x3A006C3A0000780L,0xC000144F00024F0L,0x887801D4F00091BL,0x21C00021D4400DAL,0x25B06C01B144009L,0xD80000909000L,0x240000900L}}};
+	public static final long[][] CURVE_WB={{0x100000000L,0x10000010000020L,0x200000004000004L,0x200000400000L,0x0L,0x0L,0x0L,0x0L},{0x1500000005L,0x15000C1500001C0L,0x2438000038L,0x481C00243800004L,0x2400000C240000L,0xC000024000L,0x0L,0x0L},{0xB00000003L,0xB00060B00000E0L,0x121C00001CL,0x240E00121C00002L,0x12000006120000L,0x6000012000L,0x0L,0x0L},{0x300000001L,0x30000030000020L,0x200000004000004L,0x200000400000L,0x0L,0x0L,0x0L,0x0L}};
+	public static final long[][][] CURVE_BB={{{0x410000000DL,0x41006C4100007E0L,0x2000144FC0024FCL,0x887E01D4FC0091CL,0x21C00021D4400DAL,0x25B06C01B144009L,0xD80000909000L,0x240000900L},{0x410000000CL,0x41006C4100007E0L,0x2000144FC0024FCL,0x887E01D4FC0091CL,0x21C00021D4400DAL,0x25B06C01B144009L,0xD80000909000L,0x240000900L},{0x410000000CL,0x41006C4100007E0L,0x2000144FC0024FCL,0x887E01D4FC0091CL,0x21C00021D4400DAL,0x25B06C01B144009L,0xD80000909000L,0x240000900L},{0x200000002L,0x20000020000000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x200000001L,0x20000020000000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x410000000CL,0x41006C4100007E0L,0x2000144FC0024FCL,0x887E01D4FC0091CL,0x21C00021D4400DAL,0x25B06C01B144009L,0xD80000909000L,0x240000900L},{0x410000000DL,0x41006C4100007E0L,0x2000144FC0024FCL,0x887E01D4FC0091CL,0x21C00021D4400DAL,0x25B06C01B144009L,0xD80000909000L,0x240000900L},{0x410000000CL,0x41006C4100007E0L,0x2000144FC0024FCL,0x887E01D4FC0091CL,0x21C00021D4400DAL,0x25B06C01B144009L,0xD80000909000L,0x240000900L}},{{0x200000002L,0x20000020000000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x200000001L,0x20000020000000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x200000001L,0x20000020000000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x200000001L,0x20000020000000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x100000002L,0x10000010000000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x400000002L,0x40000040000000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x400000000AL,0x40006C4000007E0L,0x2000144FC0024FCL,0x887E01D4FC0091CL,0x21C00021D4400DAL,0x25B06C01B144009L,0xD80000909000L,0x240000900L},{0x100000002L,0x10000010000000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}}};
+
+	public static final boolean USE_GLV =true;
+	public static final boolean USE_GS_G2 =true;
+	public static final boolean USE_GS_GT =true;	
+	public static final boolean GT_STRONG=false;
+
+*/
+
+// BLS383 Curve
+
+	public static final int CURVETYPE=WEIERSTRASS;
+	public static final int CURVE_PAIRING_TYPE=BLS_CURVE;
+	public static final int CURVE_A = 0;
+
+	public static final long[] CURVE_Order={0xFFF80000FFF001L,0xBFDE0070FE7800L,0x3000049C5EDF1CL,0xC40007F910007AL,0x14641004CL,0x0L,0x0L};
+	public static final long[] CURVE_B= {0x9L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+	public static final long[] CURVE_Cof= {0x2A00000052BL,0x5560AAAAAB2CA0L,0x6055L,0x0L,0x0L,0x0L,0x0L};
+	public static final long[] CURVE_Gx={0xD59B348D10786BL,0x3477C0E3F54AD0L,0xBF25B734578B9BL,0x4F6AC007BB6F65L,0xEFD5830FF57E9CL,0xADB9F88FB6EC02L,0xB08CEE4BC98L};
+	public static final long[] CURVE_Gy={0x5DA023D145DDBL,0x13F518C5FEF7CCL,0x56EC3462B2A66FL,0x96F3019C7A925FL,0x9061047981223EL,0x4810AD8F5BE59L,0x1F3909337671L};
+
+	public static final long[] CURVE_Bnx={0x1000000040L,0x110L,0x0L,0x0L,0x0L,0x0L,0x0L};
+	public static final long[] CURVE_Cru={0xA3AAC4EDA155A9L,0xDF2FE8761E5E3DL,0xBCDFAADE632625L,0x5123128D3035A6L,0xDBF3A2BBEAD683L,0x5C5FAB20424190L,0x7AC52080A9F7L};
+	public static final long[] CURVE_Fra={0x2BA59A92B4508BL,0x63DB7A06EEF343L,0x40341CB1DFBC74L,0x1639E9D32D55D3L,0xB19B3F05CC36D4L,0xF323EE4D86AB98L,0x5A5FB198672L};
+	public static final long[] CURVE_Frb={0x81051A97F904E0L,0xB7D49A6F086A37L,0x8F3EEB8B7DB8ABL,0xEEF7983C6C9543L,0x7A65F6549CB35DL,0x693D1777CBFBECL,0x751F25672384L};
+	public static final long[] CURVE_Pxa={0x6059885BAC9472L,0x7C4D31DE2DC36DL,0xBDC90C308C88A7L,0x29F01971C688FCL,0x3693539C43F167L,0xD81E5A561EB8BFL,0x4D50722B56BFL};
+	public static final long[] CURVE_Pxb={0x9B4BD7A272AB23L,0x7AF19D4F44DCE8L,0x3F6F7B93206A34L,0x571DD3E2A819FBL,0x3A2BA3B635D7EEL,0xAC28C780C1A126L,0xEE3617C3E5BL};
+	public static final long[] CURVE_Pya={0x81D230977BD4FDL,0xB660720DFDFC6L,0x41FC9590C89A0CL,0x2E1FBCF878287AL,0x11C23014EEE65L,0x28878816BB325EL,0x8F40859A05CL};
+	public static final long[] CURVE_Pyb={0xA5E20A252C4CE6L,0x5907A74AFF40C8L,0x41760A42448EF3L,0xFFEF82B0FDA199L,0xA0F29A18D4EA49L,0xAC7F7B86E4997BL,0x1DCABBA88C12L};
+// not used
+	public static final long[][] CURVE_W={{},{}};
+	public static final long[][][] CURVE_SB={{{},{}},{{},{}}};
+	public static final long[][] CURVE_WB={{},{},{},{}};
+	public static final long[][][] CURVE_BB={{{},{},{},{}},{{},{},{},{}},{{},{},{},{}},{{},{},{},{}}};
+
+	public static final boolean USE_GLV =true;
+	public static final boolean USE_GS_G2 =true;
+	public static final boolean USE_GS_GT =true;	
+	public static final boolean GT_STRONG=false;
+
+
+
+// BLS455 Curve
+/*
+	public static final int CURVETYPE=WEIERSTRASS;
+	public static final int CURVE_PAIRING_TYPE=BLS_CURVE;
+	public static final int CURVE_A = 0;
+
+	public static final long[] CURVE_Order={0x7FFFFC00001L,0xA00000400001CL,0x25E000750001D10L,0xE0000F10004F000L,0x80000380002L,0x10L,0x0L,0x0L};
+	public static final long[] CURVE_B= {0xAL,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+	public static final long[] CURVE_Cof= {0xA9557FFAABFFAABL,0xAAB15555B54AAB6L,0x555556AAL,0x0L,0x0L,0x0L,0x0L,0x0L};
+	public static final long[] CURVE_Gx={0x6D4C5DDFDFCEDD1L,0x35C6F43B3A034FBL,0x7F05B56A579C725L,0xB1F2B8ECE11B321L,0x9F342AB0CFE8392L,0xA5911EE32767994L,0x3005E40CC56ABEDL,0x18855F3BL};
+	public static final long[] CURVE_Gy={0x404FD79A6619B9BL,0x69D80A5D6FA0286L,0xEE722322D91A493L,0xB1EE58431C1E968L,0xCA9BC8953801F5FL,0xDFAFD40FE9E388EL,0x9F8985FC3DEB0D6L,0x19A8DB77EL};
+
+	public static final long[] CURVE_Bnx={0x20000080000800L,0x10000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+	public static final long[] CURVE_Cru={0x9202FFC00000AA9L,0xFA5190F4A3762AL,0x8B2B9BDD548FEC9L,0xD7B469DB33A586AL,0xC91731354CAFD99L,0xF5B48D02FFFE695L,0x57955572A900E0EL,0x555559555L};
+	public static final long[] CURVE_Fra={0x9CCFBDCA2EBF21L,0x572F54A73379964L,0x72819F887545498L,0x22BBC1CAD1F8534L,0xA82CD7D435944F0L,0x4594F818D030F7BL,0xEDCBE3ADC0016A7L,0x397EA4973L};
+	public static final long[] CURVE_Frb={0xA033043B5D1438AL,0x6E5A00C3F72FC06L,0x4717AB46118C70EL,0x16993AE842C0609L,0x3B78DA012CA06E9L,0x501F99EA300E6EAL,0x69C971C4E9FF768L,0x1BD6B4BE1L};
+	public static final long[] CURVE_Pxa={0x475F20F0C1F542L,0x65D6070F8567E10L,0xD780698BB33D776L,0x71F685ED1531721L,0x303D3FEC5B6A49CL,0x8DEF064FF553CEBL,0xC0E9A31B4C463L,0x2ECB12FA8L};
+	public static final long[] CURVE_Pxb={0x99086EE6749F03DL,0xE89A55A5AC5EF2EL,0x7B41AECD88EA016L,0x622450FE6163E06L,0x755066E1C8E296FL,0xA80F219487326E8L,0x66DBFBB0BEAEE59L,0xECFFCE0L};
+	public static final long[] CURVE_Pya={0x83235A4581A77F4L,0x9F0F367B7A7E10AL,0x8FA0C4A66D55B9DL,0xEF03F65E0D6EC4CL,0x9C7DC299C1A9EC2L,0x32453CA21CFA5ACL,0x6C3DCD5ABB9C544L,0x22471D90AL};
+	public static final long[] CURVE_Pyb={0xF413B6D9E1FDBA2L,0xA7E630913DA0356L,0xFBC913D9AC488E2L,0x72E7CF61B401585L,0x656D801B21C89EDL,0xF9E921EEE0558F9L,0x3D2B7B03CFC8698L,0x33503CA8L};
+// not used
+	public static final long[][] CURVE_W={{},{}};
+	public static final long[][][] CURVE_SB={{{},{}},{{},{}}};
+	public static final long[][] CURVE_WB={{},{},{},{}};
+	public static final long[][][] CURVE_BB={{{},{},{},{}},{{},{},{},{}},{{},{},{},{}},{{},{},{},{}}};
+
+	public static final boolean USE_GLV =true;
+	public static final boolean USE_GS_G2 =true;
+	public static final boolean USE_GS_GT =true;	
+	public static final boolean GT_STRONG=false;
+*/
+	public static boolean debug=false;
+
+}
+
diff --git a/version22/java/RSA.java b/version22/java/RSA.java
new file mode 100644
index 0000000..1c275fe
--- /dev/null
+++ b/version22/java/RSA.java
@@ -0,0 +1,362 @@
+/*
+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.
+*/
+
+/* RSA API high-level functions  */
+
+public final class RSA {
+
+	public static final int RFS=ROM.MODBYTES*ROM.FFLEN;
+	public static final int SHA256=32;
+	public static final int SHA384=48;
+	public static final int SHA512=64;
+
+	public static final int HASH_TYPE=SHA256;
+
+/* Hash number (optional) and string to array size of Bigs */
+
+	public static byte[] hashit(int sha,byte[] A,int n)
+	{
+		byte[] R=null;
+
+		if (sha==SHA256)
+		{
+			HASH256 H=new HASH256();
+			if (A!=null) H.process_array(A);
+			if (n>=0) H.process_num(n);
+			R=H.hash();
+		}
+		if (sha==SHA384)
+		{
+			HASH384 H=new HASH384();
+			if (A!=null) H.process_array(A);
+			if (n>=0) H.process_num(n);
+			R=H.hash();
+		}
+		if (sha==SHA512)
+		{
+			HASH512 H=new HASH512();
+			if (A!=null) H.process_array(A);
+			if (n>=0) H.process_num(n);
+			R=H.hash();
+		}
+		return R;
+	}
+
+/* generate an RSA key pair */
+
+	public static void KEY_PAIR(RAND rng,int e,rsa_private_key PRIV,rsa_public_key PUB)
+	{ /* IEEE1363 A16.11/A16.12 more or less */
+
+		int n=PUB.n.getlen()/2;
+		FF t = new FF(n);
+		FF p1=new FF(n);
+		FF q1=new FF(n);
+
+		for (;;)
+		{
+			PRIV.p.random(rng);
+			while (PRIV.p.lastbits(2)!=3) PRIV.p.inc(1);
+			while (!FF.prime(PRIV.p,rng)) PRIV.p.inc(4);
+
+			p1.copy(PRIV.p);
+			p1.dec(1);
+
+			if (p1.cfactor(e)) continue;
+			break;
+		}
+
+		for (;;)
+		{
+			PRIV.q.random(rng);
+			while (PRIV.q.lastbits(2)!=3) PRIV.q.inc(1);
+			while (!FF.prime(PRIV.q,rng)) PRIV.q.inc(4);
+			
+			q1.copy(PRIV.q);
+			q1.dec(1);
+
+			if (q1.cfactor(e)) continue;
+
+			break;
+		}
+
+		PUB.n=FF.mul(PRIV.p,PRIV.q);
+		PUB.e=e;
+
+		t.copy(p1);
+		t.shr();
+		PRIV.dp.set(e);
+		PRIV.dp.invmodp(t);
+		if (PRIV.dp.parity()==0) PRIV.dp.add(t);
+		PRIV.dp.norm();
+
+		t.copy(q1);
+		t.shr();
+		PRIV.dq.set(e);
+		PRIV.dq.invmodp(t);
+		if (PRIV.dq.parity()==0) PRIV.dq.add(t);
+		PRIV.dq.norm();
+
+		PRIV.c.copy(PRIV.p);
+		PRIV.c.invmodp(PRIV.q);
+
+		return;
+	}
+
+/* Mask Generation Function */
+
+	public static void MGF1(int sha,byte[] Z,int olen,byte[] K)
+	{
+		int hlen=sha;
+		byte[] B;
+
+		int counter,cthreshold,k=0;
+
+		for (int i=0;i<K.length;i++) K[i]=0;
+
+		cthreshold=olen/hlen; if (olen%hlen!=0) cthreshold++;
+		for (counter=0;counter<cthreshold;counter++)
+		{
+			B=hashit(sha,Z,counter);
+			if (k+hlen>olen) for (int i=0;i<olen%hlen;i++) K[k++]=B[i];
+			else for (int i=0;i<hlen;i++) K[k++]=B[i];
+		}	
+	}
+
+	public static void printBinary(byte[] array)
+	{
+		int i;
+		for (i=0;i<array.length;i++)
+		{
+			System.out.printf("%02x", array[i]);
+		}
+		System.out.println();
+	}  
+
+
+
+/* SHAXXX identifier strings */
+	private static final byte[] SHA256ID={0x30,0x31,0x30,0x0d,0x06,0x09,0x60,(byte)0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20};
+	private static final byte[] SHA384ID={0x30,0x41,0x30,0x0d,0x06,0x09,0x60,(byte)0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00,0x04,0x30};
+	private static final byte[] SHA512ID={0x30,0x51,0x30,0x0d,0x06,0x09,0x60,(byte)0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0x04,0x40};
+
+/* PKCS 1.5 padding of a message to be signed */
+
+	public static boolean PKCS15(int sha,byte[] m,byte[] w)
+	{
+		int olen=ROM.FF_BITS/8;
+		int i,hlen=sha;
+		int idlen=19; 
+
+		if (olen<idlen+hlen+10) return false;
+		byte[] H=hashit(sha,m,-1);
+
+		for (i=0;i<w.length;i++) w[i]=0;
+		i=0;
+		w[i++]=0;
+		w[i++]=1;
+		for (int j=0;j<olen-idlen-hlen-3;j++)
+			w[i++]=(byte)0xff;
+		w[i++]=0;
+
+
+		if (hlen==SHA256) for (int j=0;j<idlen;j++) w[i++]=SHA256ID[j];
+		if (hlen==SHA384) for (int j=0;j<idlen;j++) w[i++]=SHA384ID[j];
+		if (hlen==SHA512) for (int j=0;j<idlen;j++) w[i++]=SHA512ID[j];
+
+		for (int j=0;j<hlen;j++)
+			w[i++]=H[j];
+
+		return true;
+	}
+
+
+	/* OAEP Message Encoding for Encryption */
+	public static byte[] OAEP_ENCODE(int sha,byte[] m,RAND rng,byte[] p)
+	{ 
+		int i,slen,olen=RFS-1;
+		int mlen=m.length;
+		int hlen,seedlen;
+		byte[] f=new byte[RFS];
+
+		hlen=sha;
+		byte[] SEED=new byte[hlen];
+		seedlen=hlen;
+
+		if (mlen>olen-hlen-seedlen-1) return new byte[0]; 
+
+		byte[] DBMASK=new byte[olen-seedlen];
+
+		byte[] h=hashit(sha,p,-1);
+
+		for (i=0;i<hlen;i++) f[i]=h[i];
+
+		slen=olen-mlen-hlen-seedlen-1;      
+
+		for (i=0;i<slen;i++) f[hlen+i]=0;
+		f[hlen+slen]=1;
+		for (i=0;i<mlen;i++) f[hlen+slen+1+i]=m[i];
+
+		for (i=0;i<seedlen;i++) SEED[i]=(byte)rng.getByte();
+
+		MGF1(sha,SEED,olen-seedlen,DBMASK);
+
+		for (i=0;i<olen-seedlen;i++) DBMASK[i]^=f[i];
+
+		MGF1(sha,DBMASK,seedlen,f);
+
+		for (i=0;i<seedlen;i++) f[i]^=SEED[i];
+
+		for (i=0;i<olen-seedlen;i++) f[i+seedlen]=DBMASK[i];
+
+		/* pad to length RFS */
+		int d=1;
+		for (i=RFS-1;i>=d;i--)
+			f[i]=f[i-d];
+		for (i=d-1;i>=0;i--)
+			f[i]=0;
+
+		return f;
+	}
+
+	/* OAEP Message Decoding for Decryption */
+	public static byte[] OAEP_DECODE(int sha,byte[] p,byte[] f)
+	{
+		int x,t;
+		boolean comp;
+		int i,k,olen=RFS-1;
+		int hlen,seedlen;
+
+		hlen=sha;
+		byte[] SEED=new byte[hlen];
+		seedlen=hlen;
+		byte[] CHASH=new byte[hlen];
+	
+		if (olen<seedlen+hlen+1) return new byte[0];
+		byte[] DBMASK=new byte[olen-seedlen];
+		for (i=0;i<olen-seedlen;i++) DBMASK[i]=0;
+
+		if (f.length<RFS)
+		{
+			int d=RFS-f.length;
+			for (i=RFS-1;i>=d;i--)
+				f[i]=f[i-d];
+			for (i=d-1;i>=0;i--)
+				f[i]=0;
+
+		}
+
+		byte[] h=hashit(sha,p,-1);
+
+		for (i=0;i<hlen;i++) CHASH[i]=h[i];
+
+		x=f[0];
+
+		for (i=seedlen;i<olen;i++)
+			DBMASK[i-seedlen]=f[i+1]; 
+
+		MGF1(sha,DBMASK,seedlen,SEED);
+		for (i=0;i<seedlen;i++) SEED[i]^=f[i+1];
+		MGF1(sha,SEED,olen-seedlen,f);
+		for (i=0;i<olen-seedlen;i++) DBMASK[i]^=f[i];
+
+		comp=true;
+		for (i=0;i<hlen;i++)
+		{
+			if (CHASH[i]!=DBMASK[i]) comp=false;
+		}
+
+		for (i=0;i<olen-seedlen-hlen;i++)
+			DBMASK[i]=DBMASK[i+hlen];
+
+		for (i=0;i<hlen;i++)
+			SEED[i]=CHASH[i]=0;
+		
+		for (k=0;;k++)
+		{
+			if (k>=olen-seedlen-hlen) return new byte[0];
+			if (DBMASK[k]!=0) break;
+		}
+
+		t=DBMASK[k];
+		if (!comp || x!=0 || t!=0x01) 
+		{
+			for (i=0;i<olen-seedlen;i++) DBMASK[i]=0;
+			return new byte[0];
+		}
+
+		byte[] r=new byte[olen-seedlen-hlen-k-1];
+
+		for (i=0;i<olen-seedlen-hlen-k-1;i++)
+			r[i]=DBMASK[i+k+1];
+	
+		for (i=0;i<olen-seedlen;i++) DBMASK[i]=0;
+
+		return r;
+	}
+
+	/* destroy the Private Key structure */
+	public static void PRIVATE_KEY_KILL(rsa_private_key PRIV)
+	{
+		PRIV.p.zero();
+		PRIV.q.zero();
+		PRIV.dp.zero();
+		PRIV.dq.zero();
+		PRIV.c.zero();
+	}
+
+	/* RSA encryption with the public key */
+	public static void ENCRYPT(rsa_public_key PUB,byte[] F,byte[] G)
+	{
+		int n=PUB.n.getlen();
+		FF f=new FF(n);
+		FF.fromBytes(f,F);
+		f.power(PUB.e,PUB.n);
+		f.toBytes(G);
+	}
+
+	/* RSA decryption with the private key */
+	public static void DECRYPT(rsa_private_key PRIV,byte[] G,byte[] F)
+	{
+		int n=PRIV.p.getlen();
+		FF g=new FF(2*n);
+
+		FF.fromBytes(g,G);
+		FF jp=g.dmod(PRIV.p);
+		FF jq=g.dmod(PRIV.q);
+
+		jp.skpow(PRIV.dp,PRIV.p);
+		jq.skpow(PRIV.dq,PRIV.q);
+
+		g.zero();
+		g.dscopy(jp);
+		jp.mod(PRIV.q);
+		if (FF.comp(jp,jq)>0) jq.add(PRIV.q);
+		jq.sub(jp);
+		jq.norm();
+
+		FF t=FF.mul(PRIV.c,jq);
+		jq=t.dmod(PRIV.q);
+
+		t=FF.mul(jq,PRIV.p);
+		g.add(t);
+		g.norm();
+
+		g.toBytes(F);
+	}
+}
diff --git a/version22/java/TestECDH.java b/version22/java/TestECDH.java
new file mode 100644
index 0000000..7a556b1
--- /dev/null
+++ b/version22/java/TestECDH.java
@@ -0,0 +1,179 @@
+/*
+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.
+*/
+
+/* test driver and function exerciser for ECDH/ECIES/ECDSA API Functions */
+
+public class TestECDH
+{
+	public static void printBinary(byte[] array)
+	{
+		int i;
+		for (i=0;i<array.length;i++)
+		{
+			System.out.printf("%02x", array[i]);
+		}
+		System.out.println();
+	}    
+
+	public static void main(String[] args) 
+	{
+		int i,j=0,res;
+		int result;
+		String pp=new String("M0ng00se");
+
+		int EGS=ECDH.EGS;
+		int EFS=ECDH.EFS;
+		int EAS=AES.KS;
+		int sha=ECDH.HASH_TYPE;
+
+		byte[] S1=new byte[EGS];
+		byte[] W0=new byte[2*EFS+1];
+		byte[] W1=new byte[2*EFS+1];
+		byte[] Z0=new byte[EFS];
+		byte[] Z1=new byte[EFS];
+		byte[] RAW=new byte[100];
+		byte[] SALT=new byte[8];
+		byte[] P1=new byte[3];
+		byte[] P2=new byte[4];
+		byte[] V=new byte[2*EFS+1];
+		byte[] M=new byte[17];
+		byte[] T=new byte[12];
+		byte[] CS=new byte[EGS];
+		byte[] DS=new byte[EGS];
+
+		RAND rng=new RAND();
+
+		rng.clean();
+		for (i=0;i<100;i++) RAW[i]=(byte)(i);
+
+		rng.seed(100,RAW);
+
+//for (j=0;j<100;j++)
+//{
+
+		for (i=0;i<8;i++) SALT[i]=(byte)(i+1);  // set Salt
+
+		System.out.println("Alice's Passphrase= "+pp);
+		byte[] PW=pp.getBytes();
+
+/* private key S0 of size EGS bytes derived from Password and Salt */
+
+		byte[] S0=ECDH.PBKDF2(sha,PW,SALT,1000,EGS);
+
+		System.out.print("Alice's private key= 0x");
+		printBinary(S0);
+
+/* Generate Key pair S/W */
+		ECDH.KEY_PAIR_GENERATE(null,S0,W0); 
+
+		System.out.print("Alice's public key= 0x");
+		printBinary(W0);
+
+		res=ECDH.PUBLIC_KEY_VALIDATE(true,W0);
+		if (res!=0)
+		{
+			System.out.println("ECP Public Key is invalid!\n");
+			return;
+		}
+/* Random private key for other party */
+		ECDH.KEY_PAIR_GENERATE(rng,S1,W1);
+
+		System.out.print("Servers private key= 0x");
+		printBinary(S1);
+
+		System.out.print("Servers public key= 0x");
+		printBinary(W1);
+
+
+		res=ECDH.PUBLIC_KEY_VALIDATE(true,W1);
+		if (res!=0)
+		{
+			System.out.print("ECP Public Key is invalid!\n");
+			return;
+		}
+
+/* Calculate common key using DH - IEEE 1363 method */
+
+		ECDH.ECPSVDP_DH(S0,W1,Z0);
+		ECDH.ECPSVDP_DH(S1,W0,Z1);
+
+		boolean same=true;
+		for (i=0;i<EFS;i++)
+			if (Z0[i]!=Z1[i]) same=false;
+
+		if (!same)
+		{
+			System.out.println("*** ECPSVDP-DH Failed");
+			return;
+		}
+
+		byte[] KEY=ECDH.KDF2(sha,Z0,null,EAS);
+
+		System.out.print("Alice's DH Key=  0x"); printBinary(KEY);
+		System.out.print("Servers DH Key=  0x"); printBinary(KEY);
+
+		if (ROM.CURVETYPE!=ROM.MONTGOMERY)
+		{
+			System.out.println("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=0;i<=16;i++) M[i]=(byte)i; 
+
+			byte[] C=ECDH.ECIES_ENCRYPT(sha,P1,P2,rng,W1,M,V,T);
+
+			System.out.println("Ciphertext= ");
+			System.out.print("V= 0x"); printBinary(V);
+			System.out.print("C= 0x"); printBinary(C);
+			System.out.print("T= 0x"); printBinary(T);
+
+
+			M=ECDH.ECIES_DECRYPT(sha,P1,P2,V,C,T,S1);
+			if (M.length==0)
+			{
+				System.out.println("*** ECIES Decryption Failed\n");
+				return;
+			}
+			else System.out.println("Decryption succeeded");
+
+			System.out.print("Message is 0x"); printBinary(M);
+
+			System.out.println("Testing ECDSA");
+
+			if (ECDH.ECPSP_DSA(sha,rng,S0,M,CS,DS)!=0)
+			{
+				System.out.println("***ECDSA Signature Failed");
+				return;
+			}
+			System.out.println("Signature= ");
+			System.out.print("C= 0x"); printBinary(CS);
+			System.out.print("D= 0x"); printBinary(DS);
+
+			if (ECDH.ECPVP_DSA(sha,W0,M,CS,DS)!=0)
+			{
+				System.out.println("***ECDSA Verification Failed");
+				return;
+			}
+			else System.out.println("ECDSA Signature/Verification succeeded "+j);
+//}
+//System.out.println("Test Completed Successfully");
+		}
+	}
+}
diff --git a/version22/java/TestMPIN.java b/version22/java/TestMPIN.java
new file mode 100644
index 0000000..c021e71
--- /dev/null
+++ b/version22/java/TestMPIN.java
@@ -0,0 +1,270 @@
+/*
+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.
+*/
+
+/* test driver and function exerciser for MPIN API Functions */
+
+import java.util.Date;
+import java.util.Scanner;
+
+public class TestMPIN
+{
+	static boolean PERMITS=true;
+	static boolean PINERROR=true;
+	static boolean FULL=true;
+	static boolean SINGLE_PASS=false;
+
+	static void printBinary(byte[] array)
+	{
+		int i;
+		for (i=0;i<array.length;i++)
+		{
+			System.out.printf("%02x", array[i]);
+		}
+		System.out.println();
+	} 
+
+	public static void main(String[] args) {
+		RAND rng=new RAND();
+		byte[] raw=new byte[100];
+		for (int i=0;i<100;i++) raw[i]=(byte)(i+1);
+		rng.seed(100,raw);
+
+		int EGS=MPIN.EGS;
+		int EFS=MPIN.EFS;
+		int G1S=2*EFS+1; /* Group 1 Size */
+		int G2S=4*EFS; /* Group 2 Size */
+		int EAS=16;
+
+		int sha=MPIN.HASH_TYPE;
+
+		byte[] S = new byte[EGS];
+		byte[] SST = new byte[G2S];
+		byte[] TOKEN = new byte[G1S];
+		byte[] PERMIT = new byte[G1S];
+		byte[] SEC = new byte[G1S];
+		byte[] xID = new byte[G1S];
+		byte[] xCID = new byte[G1S];
+		byte[] X= new byte[EGS];
+		byte[] Y= new byte[EGS];
+		byte[] E=new byte[12*EFS];
+		byte[] F=new byte[12*EFS];
+		byte[] HID=new byte[G1S];
+		byte[] HTID=new byte[G1S];
+
+		byte[] G1=new byte[12*EFS];
+		byte[] G2=new byte[12*EFS];
+		byte[] R=new byte[EGS];
+		byte[] Z=new byte[G1S];
+		byte[] W=new byte[EGS];
+		byte[] T=new byte[G1S];
+		byte[] CK=new byte[EAS];
+		byte[] SK=new byte[EAS];
+
+		byte[] HSID=null;
+
+/* Trusted Authority set-up */
+
+		MPIN.RANDOM_GENERATE(rng,S);
+		System.out.print("Master Secret s: 0x");  printBinary(S);
+ 
+ /* Create Client Identity */
+ 		String IDstr = "testUser@miracl.com";
+		byte[] CLIENT_ID = IDstr.getBytes();   
+
+		byte[] HCID=MPIN.HASH_ID(sha,CLIENT_ID);  /* Either Client or TA calculates Hash(ID) - you decide! */
+
+		System.out.print("Client ID Hash= "); printBinary(HCID);
+		System.out.print("Client ID= "); printBinary(CLIENT_ID);
+
+/* Client and Server are issued secrets by DTA */
+		MPIN.GET_SERVER_SECRET(S,SST);
+		System.out.print("Server Secret SS: 0x");  printBinary(SST); 
+
+		MPIN.GET_CLIENT_SECRET(S,HCID,TOKEN);
+		System.out.print("Client Secret CS: 0x");        
+		printBinary(TOKEN); 
+
+/* Client extracts PIN from secret to create Token */
+		int pin=1234;
+		System.out.println("Client extracts PIN= "+pin); 
+		int rtn=MPIN.EXTRACT_PIN(sha,CLIENT_ID,pin,TOKEN);
+		if (rtn != 0)
+			System.out.println("FAILURE: EXTRACT_PIN rtn: " + rtn);
+
+		System.out.print("Client Token TK: 0x"); printBinary(TOKEN);
+
+		if (FULL)
+		{
+			MPIN.PRECOMPUTE(TOKEN,HCID,G1,G2);
+		}
+		int date;
+		if (PERMITS)
+		{
+			date=MPIN.today();
+/* Client gets "Time Token" permit from DTA */ 
+			MPIN.GET_CLIENT_PERMIT(sha,date,S,HCID,PERMIT);
+			System.out.print("Time Permit TP: 0x");  printBinary(PERMIT); 
+
+/* This encoding makes Time permit look random - Elligator squared */
+			MPIN.ENCODING(rng,PERMIT);
+			System.out.print("Encoded Time Permit TP: 0x");  printBinary(PERMIT); 
+			MPIN.DECODING(PERMIT);
+			System.out.print("Decoded Time Permit TP: 0x");  printBinary(PERMIT); 
+		}
+		else date=0;
+
+		System.out.print("\nPIN= ");
+		Scanner scan=new Scanner(System.in);
+		pin=scan.nextInt();
+
+/* 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.
+
+
+*/
+
+		byte[] pxID=xID;
+		byte[] pxCID=xCID;
+		byte[] pHID=HID;
+		byte[] pHTID=HTID;
+		byte[] pE=E;
+		byte[] pF=F;
+		byte[] pPERMIT=PERMIT;
+		byte[] prHID;
+
+		if (date!=0)
+		{
+
+			prHID=pHTID;
+			if (!PINERROR)
+			{
+				pxID=null;
+		//		pHID=null;  // new
+			}
+		}
+		else
+		{
+			prHID=pHID;
+			pPERMIT=null;
+			pxCID=null;
+			pHTID=null;
+		}
+		if (!PINERROR)
+		{
+			pE=null;
+			pF=null;
+		}
+                 
+		if (SINGLE_PASS)
+		{
+  			System.out.println("MPIN Single Pass");
+			int timeValue = MPIN.GET_TIME();
+			rtn=MPIN.CLIENT(sha,date,CLIENT_ID,rng,X,pin,TOKEN,SEC,pxID,pxCID,pPERMIT,timeValue,Y);
+			if (rtn != 0)
+  				System.out.println("FAILURE: CLIENT rtn: " + rtn);
+
+			if (FULL)
+			{
+				HCID=MPIN.HASH_ID(sha,CLIENT_ID);
+				MPIN.GET_G1_MULTIPLE(rng,1,R,HCID,Z);  /* Also Send Z=r.ID to Server, remember random r */
+			}
+
+			rtn=MPIN.SERVER(sha,date,pHID,pHTID,Y,SST,pxID,pxCID,SEC,pE,pF,CLIENT_ID,timeValue);
+			if (rtn != 0)
+  		    System.out.println("FAILURE: SERVER rtn: " + rtn);
+
+			if (FULL)
+			{
+				HSID=MPIN.HASH_ID(sha,CLIENT_ID);
+				MPIN.GET_G1_MULTIPLE(rng,0,W,prHID,T);  /* Also send T=w.ID to client, remember random w  */
+			}
+		}
+		else
+		{
+  			System.out.println("MPIN Multi Pass");
+                  /* Send U=x.ID to server, and recreate secret from token and pin */
+  			rtn=MPIN.CLIENT_1(sha,date,CLIENT_ID,rng,X,pin,TOKEN,SEC,pxID,pxCID,pPERMIT);
+  			if (rtn != 0)
+  				System.out.println("FAILURE: CLIENT_1 rtn: " + rtn);
+  
+  			if (FULL)
+  			{
+  				HCID=MPIN.HASH_ID(sha,CLIENT_ID);
+  				MPIN.GET_G1_MULTIPLE(rng,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. */
+  			MPIN.SERVER_1(sha,date,CLIENT_ID,pHID,pHTID);
+  
+                  /* Server generates Random number Y and sends it to Client */
+  			MPIN.RANDOM_GENERATE(rng,Y);
+  
+			if (FULL)
+			{
+				HSID=MPIN.HASH_ID(sha,CLIENT_ID);
+  				MPIN.GET_G1_MULTIPLE(rng,0,W,prHID,T);  /* Also send T=w.ID to client, remember random w  */
+			}
+  
+                  /* Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC */
+  			rtn=MPIN.CLIENT_2(X,Y,SEC);
+  			if (rtn != 0)
+  				System.out.println("FAILURE: CLIENT_2 rtn: " + rtn);
+  
+                  /* Server Second pass. Inputs hashed client id, random Y, -(x+y)*SEC, xID and xCID and Server secret SST. E and F help kangaroos to find error. */
+                  /* If PIN error not required, set E and F = null */
+  
+  			rtn=MPIN.SERVER_2(date,pHID,pHTID,Y,SST,pxID,pxCID,SEC,pE,pF);
+  
+  			if (rtn != 0)
+  				System.out.println("FAILURE: SERVER_2 rtn: " + rtn);
+		}
+  
+		if (rtn == MPIN.BAD_PIN)
+		{
+			System.out.println("Server says - Bad Pin. I don't know you. Feck off.\n");
+			if (PINERROR)
+			{
+				int err=MPIN.KANGAROO(E,F);
+				if (err!=0) System.out.format("(Client PIN is out by %d)\n",err);
+			}
+			return;
+		}
+		else System.out.println("Server says - PIN is good! You really are "+IDstr);
+
+
+		if (FULL)
+		{
+			byte[] H=MPIN.HASH_ALL(sha,HCID,pxID,pxCID,SEC,Y,Z,T);
+			MPIN.CLIENT_KEY(sha,G1,G2,pin,R,X,H,T,CK);
+			System.out.print("Client Key =  0x");  printBinary(CK); 
+
+			H=MPIN.HASH_ALL(sha,HSID,pxID,pxCID,SEC,Y,Z,T);
+			MPIN.SERVER_KEY(sha,Z,SST,W,H,pHID,pxID,pxCID,SK);
+			System.out.print("Server Key =  0x");  printBinary(SK); 
+		}
+	}
+}
diff --git a/version22/java/TestRSA.java b/version22/java/TestRSA.java
new file mode 100644
index 0000000..d5ac5d3
--- /dev/null
+++ b/version22/java/TestRSA.java
@@ -0,0 +1,92 @@
+/*
+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.
+*/
+
+/* test driver and function exerciser for RSA API Functions */
+
+public class TestRSA
+{
+	public static void main(String[] args) 
+	{
+		int i;
+		int RFS=RSA.RFS;
+		int sha=RSA.HASH_TYPE;
+
+		String message="Hello World\n";
+
+		rsa_public_key pub=new rsa_public_key(ROM.FFLEN);
+		rsa_private_key priv=new rsa_private_key(ROM.HFLEN);
+
+		byte[] ML=new byte[RFS];
+		byte[] C=new byte[RFS];
+		byte[] S=new byte[RFS];
+		byte[] RAW=new byte[100];
+	
+		RAND rng=new RAND();
+
+		rng.clean();
+		for (i=0;i<100;i++) RAW[i]=(byte)(i);
+
+		rng.seed(100,RAW);
+
+//for (i=0;i<10;i++)
+//{
+		System.out.println("Generating public/private key pair");
+		RSA.KEY_PAIR(rng,65537,priv,pub);
+
+		byte[] M=message.getBytes();
+		System.out.print("Encrypting test string\n");
+
+
+		byte[] E=RSA.OAEP_ENCODE(sha,M,rng,null); /* OAEP encode message M to E  */
+
+		if (E.length==0) System.out.println("Encoding failed\n");
+
+		RSA.ENCRYPT(pub,E,C);     /* encrypt encoded message */
+		System.out.print("Ciphertext= 0x"); RSA.printBinary(C);
+
+		System.out.print("Decrypting test string\n");
+		RSA.DECRYPT(priv,C,ML); 
+		byte[] MS=RSA.OAEP_DECODE(sha,null,ML); /* OAEP decode message  */
+
+		message=new String(MS);
+		System.out.print(message);
+//}
+
+		System.out.println("Signing message");
+		RSA.PKCS15(sha,M,C);
+
+		RSA.DECRYPT(priv,C,S); /* create signature in S */ 
+
+		System.out.print("Signature= 0x"); RSA.printBinary(S);
+
+		RSA.ENCRYPT(pub,S,ML); 
+
+		boolean cmp=true;
+		if (C.length!=ML.length) cmp=false;
+		else
+		{
+			for (int j=0;j<C.length;j++)
+				if (C[j]!=ML[j]) cmp=false;
+		}
+		if (cmp) System.out.println("Signature is valid");
+		else System.out.println("Signature is INVALID");
+
+		RSA.PRIVATE_KEY_KILL(priv);
+	}
+}
\ No newline at end of file
diff --git a/version22/java/readme.txt b/version22/java/readme.txt
new file mode 100644
index 0000000..21180c9
--- /dev/null
+++ b/version22/java/readme.txt
@@ -0,0 +1,61 @@
+AMCL is very simple to build for Java. 
+
+The first decision is whether to do a 32-bit or 64-bit build. In general a 
+64-bit build will probably be faster if both your processor and operating 
+system are 64-bit. Otherwise a 32-bit build is probably best.
+
+For a 32-bit build, copy BIG32.java, DBIG32.java and ROM32.java to BIG.java,
+DBIG.java and ROM.java respectively.
+
+For a 64-bit build, copy BIG64.java, DBIG64.java and ROM64.java to BIG.java,
+DBIG.java and ROM.java respectively.
+
+Next - decide the modulus type and curve type you want to use. Edit ROM.java 
+where indicated. You might want to use one of the curves whose details are
+already in there.
+
+Three example API files are provided, MPIN.java which 
+supports our M-Pin (tm) protocol, ECDH.java which supports elliptic 
+curve key exchange, digital signature and public key crypto, and RSA.java
+which supports the RSA method. The first  can be tested using the 
+TestMPIN.java driver programs, the second can be tested using TestECDH.java, 
+and the third with TestRSA.java
+
+In the ROM.java file you must provide the curve constants. Several examples
+are provided there, if you are willing to use one of these.
+
+To help generate the ROM constants for your own curve some MIRACL helper 
+programs are included. The programs bngen.cpp and blsgen.cpp generate ROM 
+data for a BN and BLS pairing friendly curves, and the program ecgen.cpp 
+generates ROM data for regular EC curves.
+
+The MIRACL based program check.cpp helps choose the best number base for
+big number representation, given the word-length and the size of the modulus.
+
+The program bigtobig.cpp converts a big number to the AMCL 
+BIG format.
+
+Don't forget to delete all .class files before rebuilding projects.
+
+For a quick jumpstart:-
+
+del *.class
+javac TestECDH.java
+java TestECDH
+
+del *.class
+javac TestRSA.java
+java TestRSA
+
+del *.class
+javac TestMPIN.java
+java TestMPIN
+
+del *.class
+javac BenchtestEC.java
+java BenchtestEC
+
+del *.class
+javac BenchtestPAIR.java
+java BenchtestPAIR
+
diff --git a/version22/java/rsa_private_key.java b/version22/java/rsa_private_key.java
new file mode 100644
index 0000000..3500dce
--- /dev/null
+++ b/version22/java/rsa_private_key.java
@@ -0,0 +1,13 @@
+public final class rsa_private_key
+{
+    public FF p,q,dp,dq,c;
+	
+	public rsa_private_key(int n)
+	{
+		p=new FF(n);
+		q=new FF(n);
+		dp=new FF(n);
+		dq=new FF(n);
+		c=new FF(n);
+	}
+}
\ No newline at end of file
diff --git a/version22/java/rsa_public_key.java b/version22/java/rsa_public_key.java
new file mode 100644
index 0000000..10491fc
--- /dev/null
+++ b/version22/java/rsa_public_key.java
@@ -0,0 +1,11 @@
+public final class rsa_public_key
+{
+    public int e;
+    public FF n;
+
+	public rsa_public_key(int m)
+	{
+		e=0;
+		n=new FF(m);
+	}
+}
diff --git a/version22/js/AES.js b/version22/js/AES.js
new file mode 100644
index 0000000..140e9c3
--- /dev/null
+++ b/version22/js/AES.js
@@ -0,0 +1,634 @@
+/*
+	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.
+*/
+
+var AES = function() {
+	this.Nk=0;
+	this.Nr=0;
+	this.mode=0;
+	this.fkey=[];
+	this.rkey=[];
+	this.f=[];
+};
+
+AES.prototype={
+/* reset cipher */
+	reset:function(m,iv)
+	{ /* reset mode, or reset iv */
+		var i;
+		this.mode=m;
+		for (i=0;i<16;i++)
+			this.f[i]=0;
+		if (this.mode!=ROM.ECB && iv!==null)
+			for (i=0;i<16;i++)
+				this.f[i]=iv[i];
+	},
+
+	getreg:function()
+	{
+		var ir=[];
+		for (var i=0;i<16;i++) ir[i]=this.f[i];
+		return ir;
+	},
+
+	increment:function()
+	{
+		for (var i=0;i<16;i++)
+		{
+			this.f[i]++;
+			if ((this.f[i]&0xff)!=0) break;
+		}
+	},
+
+/* Initialise cipher */
+	init: function(m,nk,key,iv)
+	{	/* Key=16 bytes */
+		/* Key Scheduler. Create expanded encryption key */
+		var i,j,k,N,nr;
+		var CipherKey= [];
+    	var b=[];
+		nk/=4;
+
+		if (nk!=4 && nk!=6 && nk!=8) return false;
+
+		nr=6+nk;
+
+		this.Nk=nk; this.Nr=nr;
+
+
+		this.reset(m,iv);
+		N=4*(nr+1);
+    
+		for (i=j=0;i<nk;i++,j+=4)
+		{
+			for (k=0;k<4;k++) b[k]=key[j+k];
+			CipherKey[i]=AES.pack(b);
+		}
+		for (i=0;i<nk;i++) this.fkey[i]=CipherKey[i];
+		for (j=nk,k=0;j<N;j+=nk,k++)
+		{
+			this.fkey[j]=this.fkey[j-nk]^AES.SubByte(AES.ROTL24(this.fkey[j-1]))^(AES.rco[k])&0xff;
+			for (i=1;i<nk && (i+j)<N;i++)
+				this.fkey[i+j]=this.fkey[i+j-nk]^this.fkey[i+j-1];
+		}
+
+ /* now for the expanded decrypt key in reverse order */
+
+		for (j=0;j<4;j++) this.rkey[j+N-4]=this.fkey[j]; 
+		for (i=4;i<N-4;i+=4)
+		{
+			k=N-4-i;
+			for (j=0;j<4;j++) this.rkey[k+j]=AES.InvMixCol(this.fkey[i+j]);
+		}
+		for (j=N-4;j<N;j++) this.rkey[j-N+4]=this.fkey[j];
+	},
+
+/* Encrypt a single block */
+	ecb_encrypt: function(buff)
+	{
+		var i,j,k;
+		var t;
+    	var b=[];
+    	var p=[];
+    	var q=[];
+
+		for (i=j=0;i<4;i++,j+=4)
+		{
+			for (k=0;k<4;k++) b[k]=buff[j+k];
+			p[i]=AES.pack(b);
+			p[i]^=this.fkey[i];
+		}
+
+		k=4;
+
+/* State alternates between p and q */
+		for (i=1;i<this.Nr;i++)
+		{ 
+			q[0]=this.fkey[k]^AES.ftable[p[0]&0xff]^
+				AES.ROTL8(AES.ftable[(p[1]>>>8)&0xff])^
+				AES.ROTL16(AES.ftable[(p[2]>>>16)&0xff])^
+				AES.ROTL24(AES.ftable[(p[3]>>>24)&0xff]);
+			q[1]=this.fkey[k+1]^AES.ftable[p[1]&0xff]^
+				AES.ROTL8(AES.ftable[(p[2]>>>8)&0xff])^
+				AES.ROTL16(AES.ftable[(p[3]>>>16)&0xff])^
+				AES.ROTL24(AES.ftable[(p[0]>>>24)&0xff]);
+			q[2]=this.fkey[k+2]^AES.ftable[p[2]&0xff]^
+				AES.ROTL8(AES.ftable[(p[3]>>>8)&0xff])^
+				AES.ROTL16(AES.ftable[(p[0]>>>16)&0xff])^
+				AES.ROTL24(AES.ftable[(p[1]>>>24)&0xff]);
+			q[3]=this.fkey[k+3]^AES.ftable[p[3]&0xff]^
+				AES.ROTL8(AES.ftable[(p[0]>>>8)&0xff])^
+				AES.ROTL16(AES.ftable[(p[1]>>>16)&0xff])^
+				AES.ROTL24(AES.ftable[(p[2]>>>24)&0xff]);
+
+			k+=4;
+			for (j=0;j<4;j++)
+			{
+				t=p[j]; p[j]=q[j]; q[j]=t;
+			}
+		}
+
+/* Last Round */ 
+    
+		q[0]=this.fkey[k]^(AES.fbsub[p[0]&0xff]&0xff)^
+			AES.ROTL8(AES.fbsub[(p[1]>>>8)&0xff]&0xff)^
+			AES.ROTL16(AES.fbsub[(p[2]>>>16)&0xff]&0xff)^
+			AES.ROTL24(AES.fbsub[(p[3]>>>24)&0xff]&0xff);
+
+		q[1]=this.fkey[k+1]^(AES.fbsub[p[1]&0xff]&0xff)^
+			AES.ROTL8(AES.fbsub[(p[2]>>>8)&0xff]&0xff)^
+			AES.ROTL16(AES.fbsub[(p[3]>>>16)&0xff]&0xff)^
+			AES.ROTL24(AES.fbsub[(p[0]>>>24)&0xff]&0xff);
+
+		q[2]=this.fkey[k+2]^(AES.fbsub[p[2]&0xff]&0xff)^
+			AES.ROTL8(AES.fbsub[(p[3]>>>8)&0xff]&0xff)^
+			AES.ROTL16(AES.fbsub[(p[0]>>>16)&0xff]&0xff)^
+			AES.ROTL24(AES.fbsub[(p[1]>>>24)&0xff]&0xff);
+
+		q[3]=this.fkey[k+3]^(AES.fbsub[(p[3])&0xff]&0xff)^
+			AES.ROTL8(AES.fbsub[(p[0]>>>8)&0xff]&0xff)^
+			AES.ROTL16(AES.fbsub[(p[1]>>>16)&0xff]&0xff)^
+			AES.ROTL24(AES.fbsub[(p[2]>>>24)&0xff]&0xff);
+
+		for (i=j=0;i<4;i++,j+=4)
+		{
+			b=AES.unpack(q[i]);
+			for (k=0;k<4;k++) buff[j+k]=b[k];
+		}
+	},
+
+/* Decrypt a single block */
+	ecb_decrypt: function(buff)
+	{
+		var i,j,k;
+		var t;
+    	var b=[];
+    	var p=[];
+    	var q=[];
+
+		for (i=j=0;i<4;i++,j+=4)
+		{
+			for (k=0;k<4;k++) b[k]=buff[j+k];
+			p[i]=AES.pack(b);
+			p[i]^=this.rkey[i];
+		}
+
+		k=4;
+
+/* State alternates between p and q */
+		for (i=1;i<this.Nr;i++)
+		{ 
+			q[0]=this.rkey[k]^AES.rtable[p[0]&0xff]^
+				AES.ROTL8(AES.rtable[(p[3]>>>8)&0xff])^
+				AES.ROTL16(AES.rtable[(p[2]>>>16)&0xff])^
+				AES.ROTL24(AES.rtable[(p[1]>>>24)&0xff]);
+			q[1]=this.rkey[k+1]^AES.rtable[p[1]&0xff]^
+				AES.ROTL8(AES.rtable[(p[0]>>>8)&0xff])^
+				AES.ROTL16(AES.rtable[(p[3]>>>16)&0xff])^
+				AES.ROTL24(AES.rtable[(p[2]>>>24)&0xff]);
+			q[2]=this.rkey[k+2]^AES.rtable[p[2]&0xff]^
+				AES.ROTL8(AES.rtable[(p[1]>>>8)&0xff])^
+				AES.ROTL16(AES.rtable[(p[0]>>>16)&0xff])^
+				AES.ROTL24(AES.rtable[(p[3]>>>24)&0xff]);
+			q[3]=this.rkey[k+3]^AES.rtable[p[3]&0xff]^
+				AES.ROTL8(AES.rtable[(p[2]>>>8)&0xff])^
+				AES.ROTL16(AES.rtable[(p[1]>>>16)&0xff])^
+				AES.ROTL24(AES.rtable[(p[0]>>>24)&0xff]);
+
+			k+=4;
+			for (j=0;j<4;j++)
+			{
+				t=p[j]; p[j]=q[j]; q[j]=t;
+			}
+		}
+
+/* Last Round */ 
+
+		q[0]=this.rkey[k]^(AES.rbsub[p[0]&0xff]&0xff)^
+			AES.ROTL8(AES.rbsub[(p[3]>>>8)&0xff]&0xff)^
+			AES.ROTL16(AES.rbsub[(p[2]>>>16)&0xff]&0xff)^
+			AES.ROTL24(AES.rbsub[(p[1]>>>24)&0xff]&0xff);
+		q[1]=this.rkey[k+1]^(AES.rbsub[p[1]&0xff]&0xff)^
+			AES.ROTL8(AES.rbsub[(p[0]>>>8)&0xff]&0xff)^
+			AES.ROTL16(AES.rbsub[(p[3]>>>16)&0xff]&0xff)^
+			AES.ROTL24(AES.rbsub[(p[2]>>>24)&0xff]&0xff);
+		q[2]=this.rkey[k+2]^(AES.rbsub[p[2]&0xff]&0xff)^
+			AES.ROTL8(AES.rbsub[(p[1]>>>8)&0xff]&0xff)^
+			AES.ROTL16(AES.rbsub[(p[0]>>>16)&0xff]&0xff)^
+			AES.ROTL24(AES.rbsub[(p[3]>>>24)&0xff]&0xff);
+		q[3]=this.rkey[k+3]^(AES.rbsub[p[3]&0xff]&0xff)^
+			AES.ROTL8(AES.rbsub[(p[2]>>>8)&0xff]&0xff)^
+			AES.ROTL16(AES.rbsub[(p[1]>>>16)&0xff]&0xff)^
+			AES.ROTL24(AES.rbsub[(p[0]>>>24)&0xff]&0xff);
+
+		for (i=j=0;i<4;i++,j+=4)
+		{
+			b=AES.unpack(q[i]);
+			for (k=0;k<4;k++) buff[j+k]=b[k];
+		}
+
+	},
+
+/* Encrypt using selected mode of operation */	
+	encrypt: function(buff)
+	{
+		var j,bytes;
+		var st=[];
+		var fell_off;
+
+// Supported Modes of Operation 
+
+		fell_off=0;
+
+		switch (this.mode)
+		{
+		case ROM.ECB: 
+			this.ecb_encrypt(buff);
+			return 0;
+		case ROM.CBC:
+			for (j=0;j<16;j++) buff[j]^=this.f[j];
+			this.ecb_encrypt(buff);
+			for (j=0;j<16;j++) this.f[j]=buff[j];
+			return 0;
+
+		case ROM.CFB1:
+		case ROM.CFB2:
+		case ROM.CFB4:
+			bytes=this.mode-ROM.CFB1+1;
+			for (j=0;j<bytes;j++) fell_off=(fell_off<<8)|this.f[j];
+			for (j=0;j<16;j++) st[j]=this.f[j];
+			for (j=bytes;j<16;j++) this.f[j-bytes]=this.f[j];
+			this.ecb_encrypt(st);
+			for (j=0;j<bytes;j++) 
+			{
+				buff[j]^=st[j];
+				this.f[16-bytes+j]=buff[j];
+			}
+			return fell_off;
+
+		case ROM.OFB1:
+		case ROM.OFB2:
+		case ROM.OFB4:
+		case ROM.OFB8:
+		case ROM.OFB16:
+
+			bytes=this.mode-ROM.OFB1+1;
+			this.ecb_encrypt(this.f);
+			for (j=0;j<bytes;j++) buff[j]^=this.f[j];
+			return 0;
+
+		case ROM.CTR1:
+		case ROM.CTR2:
+		case ROM.CTR4:
+		case ROM.CTR8:
+		case ROM.CTR16:
+
+			bytes=this.mode-ROM.CTR1+1;
+			for (j=0;j<16;j++) st[j]=this.f[j];
+			this.ecb_encrypt(st);
+			for (j=0;j<bytes;j++) buff[j]^=st[j];
+			this.increment();
+
+    default:
+			return 0;
+		}
+	},
+
+/* Decrypt using selected mode of operation */
+	decrypt: function(buff)
+	{
+		var j,bytes;
+		var st=[];
+		var fell_off;
+
+   // Supported modes of operation 
+		fell_off=0;
+		switch (this.mode)
+		{
+		case ROM.ECB:
+			this.ecb_decrypt(buff);
+			return 0;
+		case ROM.CBC:
+			for (j=0;j<16;j++) 
+			{
+				st[j]=this.f[j];
+				this.f[j]=buff[j];
+			}
+			this.ecb_decrypt(buff);
+			for (j=0;j<16;j++)
+			{	 
+				buff[j]^=st[j];
+				st[j]=0;
+			}
+			return 0;
+		case ROM.CFB1:
+		case ROM.CFB2:
+		case ROM.CFB4:
+			bytes=this.mode-ROM.CFB1+1;
+			for (j=0;j<bytes;j++) fell_off=(fell_off<<8)|this.f[j];
+			for (j=0;j<16;j++) st[j]=this.f[j];
+			for (j=bytes;j<16;j++) this.f[j-bytes]=this.f[j];
+			this.ecb_encrypt(st);
+			for (j=0;j<bytes;j++)
+			{
+				this.f[16-bytes+j]=buff[j];
+				buff[j]^=st[j];
+			}
+			return fell_off;
+		case ROM.OFB1:
+		case ROM.OFB2:
+		case ROM.OFB4:
+		case ROM.OFB8:
+		case ROM.OFB16:
+			bytes=this.mode-ROM.OFB1+1;
+			this.ecb_encrypt(this.f);
+			for (j=0;j<bytes;j++) buff[j]^=this.f[j];
+			return 0;
+
+ 		case ROM.CTR1:
+		case ROM.CTR2:
+		case ROM.CTR4:
+		case ROM.CTR8:
+		case ROM.CTR16:
+			bytes=this.mode-ROM.CTR1+1;
+			for (j=0;j<16;j++) st[j]=this.f[j];
+			this.ecb_encrypt(st);
+			for (j=0;j<bytes;j++) buff[j]^=st[j];
+			this.increment();
+		default:
+			return 0;
+		}
+	},
+
+/* Clean up and delete left-overs */
+	end: function()
+	{ // clean up 
+		var i;
+		for (i=0;i<4*(this.Nr+1);i++)
+			this.fkey[i]=this.rkey[i]=0;
+		for (i=0;i<16;i++)
+			this.f[i]=0;
+	}
+
+};
+
+/* static functions */
+
+AES.ROTL8=function(x)
+{
+	return (((x)<<8)|((x)>>>24));
+};
+
+AES.ROTL16=function(x)
+{
+	return (((x)<<16)|((x)>>>16));
+};
+
+AES.ROTL24=function(x)
+{
+	return (((x)<<24)|((x)>>>8));
+};
+
+AES.pack= function(b)
+{ /* pack 4 bytes into a 32-bit Word */
+		return (((b[3])&0xff)<<24)|((b[2]&0xff)<<16)|((b[1]&0xff)<<8)|(b[0]&0xff);
+};
+
+AES.unpack=function(a)
+{ /* unpack bytes from a word */
+	var b=[];
+	b[0]=(a&0xff);
+	b[1]=((a>>>8)&0xff);
+	b[2]=((a>>>16)&0xff);
+	b[3]=((a>>>24)&0xff);
+	return b;
+};
+
+AES.bmul=function(x,y)
+{ /* x.y= AntiLog(Log(x) + Log(y)) */
+
+	var ix=(x&0xff);
+	var iy=(y&0xff);
+	var lx=(AES.ltab[ix])&0xff;
+	var ly=(AES.ltab[iy])&0xff;
+	if (x!==0 && y!==0) return AES.ptab[(lx+ly)%255];
+	else return 0;
+};
+
+//  if (x && y) 
+
+AES.SubByte=function(a)
+{
+	var b=AES.unpack(a);  
+	b[0]=AES.fbsub[b[0]&0xff];
+	b[1]=AES.fbsub[b[1]&0xff];
+	b[2]=AES.fbsub[b[2]&0xff];
+	b[3]=AES.fbsub[b[3]&0xff];
+	return AES.pack(b);    
+};
+
+AES.product=function(x,y)
+{ /* dot product of two 4-byte arrays */
+	var xb=AES.unpack(x); 
+	var yb=AES.unpack(y); 
+	return (AES.bmul(xb[0],yb[0])^AES.bmul(xb[1],yb[1])^AES.bmul(xb[2],yb[2])^AES.bmul(xb[3],yb[3]))&0xff;
+};
+
+AES.InvMixCol=function(x)
+{ /* matrix Multiplication */
+	var y,m;
+	var b=[];
+	m=AES.pack(AES.InCo);
+	b[3]=AES.product(m,x);
+	m=AES.ROTL24(m);
+	b[2]=AES.product(m,x);
+	m=AES.ROTL24(m);
+	b[1]=AES.product(m,x);
+	m=AES.ROTL24(m);
+	b[0]=AES.product(m,x);
+	y=AES.pack(b);
+	return y;
+};
+
+AES.InCo=[0xB,0xD,0x9,0xE];  /* Inverse Coefficients */
+AES.rco=[1,2,4,8,16,32,64,128,27,54,108,216,171,77,154,47];
+
+AES.ptab=[
+	1,3,5,15,17,51,85,255,26,46,114,150,161,248,19,53,
+	95,225,56,72,216,115,149,164,247,2,6,10,30,34,102,170,
+	229,52,92,228,55,89,235,38,106,190,217,112,144,171,230,49,
+	83,245,4,12,20,60,68,204,79,209,104,184,211,110,178,205,
+	76,212,103,169,224,59,77,215,98,166,241,8,24,40,120,136,
+	131,158,185,208,107,189,220,127,129,152,179,206,73,219,118,154,
+	181,196,87,249,16,48,80,240,11,29,39,105,187,214,97,163,
+	254,25,43,125,135,146,173,236,47,113,147,174,233,32,96,160,
+	251,22,58,78,210,109,183,194,93,231,50,86,250,21,63,65,
+	195,94,226,61,71,201,64,192,91,237,44,116,156,191,218,117,
+	159,186,213,100,172,239,42,126,130,157,188,223,122,142,137,128,
+	155,182,193,88,232,35,101,175,234,37,111,177,200,67,197,84,
+	252,31,33,99,165,244,7,9,27,45,119,153,176,203,70,202,
+	69,207,74,222,121,139,134,145,168,227,62,66,198,81,243,14,
+	18,54,90,238,41,123,141,140,143,138,133,148,167,242,13,23,
+	57,75,221,124,132,151,162,253,28,36,108,180,199,82,246,1
+	];
+AES.ltab=[
+	0,255,25,1,50,2,26,198,75,199,27,104,51,238,223,3,
+	100,4,224,14,52,141,129,239,76,113,8,200,248,105,28,193,
+	125,194,29,181,249,185,39,106,77,228,166,114,154,201,9,120,
+	101,47,138,5,33,15,225,36,18,240,130,69,53,147,218,142,
+	150,143,219,189,54,208,206,148,19,92,210,241,64,70,131,56,
+	102,221,253,48,191,6,139,98,179,37,226,152,34,136,145,16,
+	126,110,72,195,163,182,30,66,58,107,40,84,250,133,61,186,
+	43,121,10,21,155,159,94,202,78,212,172,229,243,115,167,87,
+	175,88,168,80,244,234,214,116,79,174,233,213,231,230,173,232,
+	44,215,117,122,235,22,11,245,89,203,95,176,156,169,81,160,
+	127,12,246,111,23,196,73,236,216,67,31,45,164,118,123,183,
+	204,187,62,90,251,96,177,134,59,82,161,108,170,85,41,157,
+	151,178,135,144,97,190,220,252,188,149,207,205,55,63,91,209,
+	83,57,132,60,65,162,109,71,20,42,158,93,86,242,211,171,
+	68,17,146,217,35,32,46,137,180,124,184,38,119,153,227,165,
+	103,74,237,222,197,49,254,24,13,99,140,128,192,247,112,7
+	];
+AES.fbsub=[
+	99,124,119,123,242,107,111,197,48,1,103,43,254,215,171,118,
+	202,130,201,125,250,89,71,240,173,212,162,175,156,164,114,192,
+	183,253,147,38,54,63,247,204,52,165,229,241,113,216,49,21,
+	4,199,35,195,24,150,5,154,7,18,128,226,235,39,178,117,
+	9,131,44,26,27,110,90,160,82,59,214,179,41,227,47,132,
+	83,209,0,237,32,252,177,91,106,203,190,57,74,76,88,207,
+	208,239,170,251,67,77,51,133,69,249,2,127,80,60,159,168,
+	81,163,64,143,146,157,56,245,188,182,218,33,16,255,243,210,
+	205,12,19,236,95,151,68,23,196,167,126,61,100,93,25,115,
+	96,129,79,220,34,42,144,136,70,238,184,20,222,94,11,219,
+	224,50,58,10,73,6,36,92,194,211,172,98,145,149,228,121,
+	231,200,55,109,141,213,78,169,108,86,244,234,101,122,174,8,
+	186,120,37,46,28,166,180,198,232,221,116,31,75,189,139,138,
+	112,62,181,102,72,3,246,14,97,53,87,185,134,193,29,158,
+	225,248,152,17,105,217,142,148,155,30,135,233,206,85,40,223,
+	140,161,137,13,191,230,66,104,65,153,45,15,176,84,187,22
+	];
+AES.rbsub=[
+	82,9,106,213,48,54,165,56,191,64,163,158,129,243,215,251,
+	124,227,57,130,155,47,255,135,52,142,67,68,196,222,233,203,
+	84,123,148,50,166,194,35,61,238,76,149,11,66,250,195,78,
+	8,46,161,102,40,217,36,178,118,91,162,73,109,139,209,37,
+	114,248,246,100,134,104,152,22,212,164,92,204,93,101,182,146,
+	108,112,72,80,253,237,185,218,94,21,70,87,167,141,157,132,
+	144,216,171,0,140,188,211,10,247,228,88,5,184,179,69,6,
+	208,44,30,143,202,63,15,2,193,175,189,3,1,19,138,107,
+	58,145,17,65,79,103,220,234,151,242,207,206,240,180,230,115,
+	150,172,116,34,231,173,53,133,226,249,55,232,28,117,223,110,
+	71,241,26,113,29,41,197,137,111,183,98,14,170,24,190,27,
+	252,86,62,75,198,210,121,32,154,219,192,254,120,205,90,244,
+	31,221,168,51,136,7,199,49,177,18,16,89,39,128,236,95,
+	96,81,127,169,25,181,74,13,45,229,122,159,147,201,156,239,
+	160,224,59,77,174,42,245,176,200,235,187,60,131,83,153,97,
+	23,43,4,126,186,119,214,38,225,105,20,99,85,33,12,125
+	];
+AES.ftable=[
+	0xa56363c6,0x847c7cf8,0x997777ee,0x8d7b7bf6,0xdf2f2ff,0xbd6b6bd6,
+	0xb16f6fde,0x54c5c591,0x50303060,0x3010102,0xa96767ce,0x7d2b2b56,
+	0x19fefee7,0x62d7d7b5,0xe6abab4d,0x9a7676ec,0x45caca8f,0x9d82821f,
+	0x40c9c989,0x877d7dfa,0x15fafaef,0xeb5959b2,0xc947478e,0xbf0f0fb,
+	0xecadad41,0x67d4d4b3,0xfda2a25f,0xeaafaf45,0xbf9c9c23,0xf7a4a453,
+	0x967272e4,0x5bc0c09b,0xc2b7b775,0x1cfdfde1,0xae93933d,0x6a26264c,
+	0x5a36366c,0x413f3f7e,0x2f7f7f5,0x4fcccc83,0x5c343468,0xf4a5a551,
+	0x34e5e5d1,0x8f1f1f9,0x937171e2,0x73d8d8ab,0x53313162,0x3f15152a,
+	0xc040408,0x52c7c795,0x65232346,0x5ec3c39d,0x28181830,0xa1969637,
+	0xf05050a,0xb59a9a2f,0x907070e,0x36121224,0x9b80801b,0x3de2e2df,
+	0x26ebebcd,0x6927274e,0xcdb2b27f,0x9f7575ea,0x1b090912,0x9e83831d,
+	0x742c2c58,0x2e1a1a34,0x2d1b1b36,0xb26e6edc,0xee5a5ab4,0xfba0a05b,
+	0xf65252a4,0x4d3b3b76,0x61d6d6b7,0xceb3b37d,0x7b292952,0x3ee3e3dd,
+	0x712f2f5e,0x97848413,0xf55353a6,0x68d1d1b9,0x0,0x2cededc1,
+	0x60202040,0x1ffcfce3,0xc8b1b179,0xed5b5bb6,0xbe6a6ad4,0x46cbcb8d,
+	0xd9bebe67,0x4b393972,0xde4a4a94,0xd44c4c98,0xe85858b0,0x4acfcf85,
+	0x6bd0d0bb,0x2aefefc5,0xe5aaaa4f,0x16fbfbed,0xc5434386,0xd74d4d9a,
+	0x55333366,0x94858511,0xcf45458a,0x10f9f9e9,0x6020204,0x817f7ffe,
+	0xf05050a0,0x443c3c78,0xba9f9f25,0xe3a8a84b,0xf35151a2,0xfea3a35d,
+	0xc0404080,0x8a8f8f05,0xad92923f,0xbc9d9d21,0x48383870,0x4f5f5f1,
+	0xdfbcbc63,0xc1b6b677,0x75dadaaf,0x63212142,0x30101020,0x1affffe5,
+	0xef3f3fd,0x6dd2d2bf,0x4ccdcd81,0x140c0c18,0x35131326,0x2fececc3,
+	0xe15f5fbe,0xa2979735,0xcc444488,0x3917172e,0x57c4c493,0xf2a7a755,
+	0x827e7efc,0x473d3d7a,0xac6464c8,0xe75d5dba,0x2b191932,0x957373e6,
+	0xa06060c0,0x98818119,0xd14f4f9e,0x7fdcdca3,0x66222244,0x7e2a2a54,
+	0xab90903b,0x8388880b,0xca46468c,0x29eeeec7,0xd3b8b86b,0x3c141428,
+	0x79dedea7,0xe25e5ebc,0x1d0b0b16,0x76dbdbad,0x3be0e0db,0x56323264,
+	0x4e3a3a74,0x1e0a0a14,0xdb494992,0xa06060c,0x6c242448,0xe45c5cb8,
+	0x5dc2c29f,0x6ed3d3bd,0xefacac43,0xa66262c4,0xa8919139,0xa4959531,
+	0x37e4e4d3,0x8b7979f2,0x32e7e7d5,0x43c8c88b,0x5937376e,0xb76d6dda,
+	0x8c8d8d01,0x64d5d5b1,0xd24e4e9c,0xe0a9a949,0xb46c6cd8,0xfa5656ac,
+	0x7f4f4f3,0x25eaeacf,0xaf6565ca,0x8e7a7af4,0xe9aeae47,0x18080810,
+	0xd5baba6f,0x887878f0,0x6f25254a,0x722e2e5c,0x241c1c38,0xf1a6a657,
+	0xc7b4b473,0x51c6c697,0x23e8e8cb,0x7cdddda1,0x9c7474e8,0x211f1f3e,
+	0xdd4b4b96,0xdcbdbd61,0x868b8b0d,0x858a8a0f,0x907070e0,0x423e3e7c,
+	0xc4b5b571,0xaa6666cc,0xd8484890,0x5030306,0x1f6f6f7,0x120e0e1c,
+	0xa36161c2,0x5f35356a,0xf95757ae,0xd0b9b969,0x91868617,0x58c1c199,
+	0x271d1d3a,0xb99e9e27,0x38e1e1d9,0x13f8f8eb,0xb398982b,0x33111122,
+	0xbb6969d2,0x70d9d9a9,0x898e8e07,0xa7949433,0xb69b9b2d,0x221e1e3c,
+	0x92878715,0x20e9e9c9,0x49cece87,0xff5555aa,0x78282850,0x7adfdfa5,
+	0x8f8c8c03,0xf8a1a159,0x80898909,0x170d0d1a,0xdabfbf65,0x31e6e6d7,
+	0xc6424284,0xb86868d0,0xc3414182,0xb0999929,0x772d2d5a,0x110f0f1e,
+	0xcbb0b07b,0xfc5454a8,0xd6bbbb6d,0x3a16162c
+	];
+AES.rtable=[
+	0x50a7f451,0x5365417e,0xc3a4171a,0x965e273a,0xcb6bab3b,0xf1459d1f,
+	0xab58faac,0x9303e34b,0x55fa3020,0xf66d76ad,0x9176cc88,0x254c02f5,
+	0xfcd7e54f,0xd7cb2ac5,0x80443526,0x8fa362b5,0x495ab1de,0x671bba25,
+	0x980eea45,0xe1c0fe5d,0x2752fc3,0x12f04c81,0xa397468d,0xc6f9d36b,
+	0xe75f8f03,0x959c9215,0xeb7a6dbf,0xda595295,0x2d83bed4,0xd3217458,
+	0x2969e049,0x44c8c98e,0x6a89c275,0x78798ef4,0x6b3e5899,0xdd71b927,
+	0xb64fe1be,0x17ad88f0,0x66ac20c9,0xb43ace7d,0x184adf63,0x82311ae5,
+	0x60335197,0x457f5362,0xe07764b1,0x84ae6bbb,0x1ca081fe,0x942b08f9,
+	0x58684870,0x19fd458f,0x876cde94,0xb7f87b52,0x23d373ab,0xe2024b72,
+	0x578f1fe3,0x2aab5566,0x728ebb2,0x3c2b52f,0x9a7bc586,0xa50837d3,
+	0xf2872830,0xb2a5bf23,0xba6a0302,0x5c8216ed,0x2b1ccf8a,0x92b479a7,
+	0xf0f207f3,0xa1e2694e,0xcdf4da65,0xd5be0506,0x1f6234d1,0x8afea6c4,
+	0x9d532e34,0xa055f3a2,0x32e18a05,0x75ebf6a4,0x39ec830b,0xaaef6040,
+	0x69f715e,0x51106ebd,0xf98a213e,0x3d06dd96,0xae053edd,0x46bde64d,
+	0xb58d5491,0x55dc471,0x6fd40604,0xff155060,0x24fb9819,0x97e9bdd6,
+	0xcc434089,0x779ed967,0xbd42e8b0,0x888b8907,0x385b19e7,0xdbeec879,
+	0x470a7ca1,0xe90f427c,0xc91e84f8,0x0,0x83868009,0x48ed2b32,
+	0xac70111e,0x4e725a6c,0xfbff0efd,0x5638850f,0x1ed5ae3d,0x27392d36,
+	0x64d90f0a,0x21a65c68,0xd1545b9b,0x3a2e3624,0xb1670a0c,0xfe75793,
+	0xd296eeb4,0x9e919b1b,0x4fc5c080,0xa220dc61,0x694b775a,0x161a121c,
+	0xaba93e2,0xe52aa0c0,0x43e0223c,0x1d171b12,0xb0d090e,0xadc78bf2,
+	0xb9a8b62d,0xc8a91e14,0x8519f157,0x4c0775af,0xbbdd99ee,0xfd607fa3,
+	0x9f2601f7,0xbcf5725c,0xc53b6644,0x347efb5b,0x7629438b,0xdcc623cb,
+	0x68fcedb6,0x63f1e4b8,0xcadc31d7,0x10856342,0x40229713,0x2011c684,
+	0x7d244a85,0xf83dbbd2,0x1132f9ae,0x6da129c7,0x4b2f9e1d,0xf330b2dc,
+	0xec52860d,0xd0e3c177,0x6c16b32b,0x99b970a9,0xfa489411,0x2264e947,
+	0xc48cfca8,0x1a3ff0a0,0xd82c7d56,0xef903322,0xc74e4987,0xc1d138d9,
+	0xfea2ca8c,0x360bd498,0xcf81f5a6,0x28de7aa5,0x268eb7da,0xa4bfad3f,
+	0xe49d3a2c,0xd927850,0x9bcc5f6a,0x62467e54,0xc2138df6,0xe8b8d890,
+	0x5ef7392e,0xf5afc382,0xbe805d9f,0x7c93d069,0xa92dd56f,0xb31225cf,
+	0x3b99acc8,0xa77d1810,0x6e639ce8,0x7bbb3bdb,0x97826cd,0xf418596e,
+	0x1b79aec,0xa89a4f83,0x656e95e6,0x7ee6ffaa,0x8cfbc21,0xe6e815ef,
+	0xd99be7ba,0xce366f4a,0xd4099fea,0xd67cb029,0xafb2a431,0x31233f2a,
+	0x3094a5c6,0xc066a235,0x37bc4e74,0xa6ca82fc,0xb0d090e0,0x15d8a733,
+	0x4a9804f1,0xf7daec41,0xe50cd7f,0x2ff69117,0x8dd64d76,0x4db0ef43,
+	0x544daacc,0xdf0496e4,0xe3b5d19e,0x1b886a4c,0xb81f2cc1,0x7f516546,
+	0x4ea5e9d,0x5d358c01,0x737487fa,0x2e410bfb,0x5a1d67b3,0x52d2db92,
+	0x335610e9,0x1347d66d,0x8c61d79a,0x7a0ca137,0x8e14f859,0x893c13eb,
+	0xee27a9ce,0x35c961b7,0xede51ce1,0x3cb1477a,0x59dfd29c,0x3f73f255,
+	0x79ce1418,0xbf37c773,0xeacdf753,0x5baafd5f,0x146f3ddf,0x86db4478,
+	0x81f3afca,0x3ec468b9,0x2c342438,0x5f40a3c2,0x72c31d16,0xc25e2bc,
+	0x8b493c28,0x41950dff,0x7101a839,0xdeb30c08,0x9ce4b4d8,0x90c15664,
+	0x6184cb7b,0x70b632d5,0x745c6c48,0x4257b8d0
+	];
+
+
diff --git a/version22/js/BIG.js b/version22/js/BIG.js
new file mode 100644
index 0000000..11a7fa1
--- /dev/null
+++ b/version22/js/BIG.js
@@ -0,0 +1,1037 @@
+/*
+	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.
+*/
+
+/* AMCL BIG number class */
+
+/* General purpose Constructor */
+var BIG = function(x) {
+	this.w=new Array(ROM.NLEN);
+	switch (typeof(x))
+	{
+	case "object":
+		this.copy(x);
+		break;
+	case "number":
+		this.zero();
+		this.w[0]=x;
+		break;
+	default:
+		this.zero();
+	}
+};
+
+BIG.prototype={
+/* set to zero */
+	zero: function()
+	{
+		for (var i=0;i<ROM.NLEN;i++) this.w[i]=0;
+		return this;
+	},
+/* set to one */
+	one: function()
+	{
+		this.w[0]=1;
+		for (var i=1;i<ROM.NLEN;i++) this.w[i]=0;
+		return this;
+	},
+
+	get: function(i)
+	{
+		return this.w[i];
+	},
+
+	set: function(i,x)
+	{
+		this.w[i]=x;
+	},
+/* test for zero */
+	iszilch: function()
+	{
+		for (var i=0;i<ROM.NLEN;i++)
+			if (this.w[i]!==0) return false;
+		return true; 
+	},
+/* test for unity */
+	isunity: function()
+	{
+		for (var i=1;i<ROM.NLEN;i++)
+			if (this.w[i]!==0) return false;
+		if (this.w[0]!=1) return false;
+		return true;
+	},
+
+/* Conditional swap of two bigs depending on d using XOR - no branches */
+	cswap: function(b,d)
+	{
+		var i;
+		var t,c=d;
+		c=~(c-1);
+
+		for (i=0;i<ROM.NLEN;i++)
+		{
+			t=c&(this.w[i]^b.w[i]);
+			this.w[i]^=t;
+			b.w[i]^=t;
+		}
+	},
+
+/* Conditional move of big depending on d using XOR - no branches */
+	cmove: function(b,d)
+	{
+		var i;
+		var c=d;
+		c=~(c-1);
+
+		for (i=0;i<ROM.NLEN;i++)
+		{
+			this.w[i]^=(this.w[i]^b.w[i])&c;
+		}
+	},
+
+/* copy from another BIG */
+	copy: function(y)
+	{
+		for (var i=0;i<ROM.NLEN;i++)
+			this.w[i]=y.w[i];
+		return this;
+	},
+/* copy from bottom half of DBIG */
+	hcopy: function(y)
+	{
+		for (var i=0;i<ROM.NLEN;i++)
+			this.w[i]=y.w[i];
+		return this;
+	},
+/* copy from ROM */
+	rcopy: function(y)
+	{
+		for (var i=0;i<ROM.NLEN;i++)
+			this.w[i]=y[i];
+		return this;
+	},
+
+	xortop: function(x)
+	{
+		this.w[ROM.NLEN-1]^=x;
+	},
+
+	ortop: function(x)
+	{
+		this.w[ROM.NLEN-1]|=x;
+	},
+
+/* normalise BIG - force all digits < 2^BASEBITS */
+	norm: function()
+	{
+		var d,carry=0;
+		for (var i=0;i<ROM.NLEN-1;i++)
+		{
+			d=this.w[i]+carry;
+			this.w[i]=d&ROM.BMASK;
+			carry=d>>ROM.BASEBITS;
+		}
+		this.w[ROM.NLEN-1]=(this.w[ROM.NLEN-1]+carry);
+
+		return (this.w[ROM.NLEN-1]>>((8*ROM.MODBYTES)%ROM.BASEBITS));  
+
+	},
+/* quick shift right by less than a word */
+	fshr: function(k)
+	{
+		var r=this.w[0]&((1<<k)-1); /* shifted out part */
+		for (var i=0;i<ROM.NLEN-1;i++)
+			this.w[i]=(this.w[i]>>k)|((this.w[i+1]<<(ROM.BASEBITS-k))&ROM.BMASK);
+		this.w[ROM.NLEN-1]=this.w[ROM.NLEN-1]>>k;
+		return r;
+	},
+/* General shift right by k bits */
+	shr: function(k)
+	{
+		var n=k%ROM.BASEBITS;
+		var m=Math.floor(k/ROM.BASEBITS);	
+		for (var i=0;i<ROM.NLEN-m-1;i++)
+			this.w[i]=(this.w[m+i]>>n)|((this.w[m+i+1]<<(ROM.BASEBITS-n))&ROM.BMASK);
+		this.w[ROM.NLEN-m-1]=this.w[ROM.NLEN-1]>>n;
+		for (i=ROM.NLEN-m;i<ROM.NLEN;i++) this.w[i]=0;
+		return this;
+	},
+/* quick shift left by less than a word */
+	fshl: function(k)
+	{
+		this.w[ROM.NLEN-1]=((this.w[ROM.NLEN-1]<<k))|(this.w[ROM.NLEN-2]>>(ROM.BASEBITS-k));
+		for (var i=ROM.NLEN-2;i>0;i--)
+			this.w[i]=((this.w[i]<<k)&ROM.BMASK)|(this.w[i-1]>>(ROM.BASEBITS-k));
+		this.w[0]=(this.w[0]<<k)&ROM.BMASK; 
+
+		return (this.w[ROM.NLEN-1]>>((8*ROM.MODBYTES)%ROM.BASEBITS)); /* return excess - only used in FF.java */
+	},
+/* General shift left by k bits */
+	shl: function(k)
+	{
+		var i,n=k%ROM.BASEBITS;
+		var m=Math.floor(k/ROM.BASEBITS);
+
+		this.w[ROM.NLEN-1]=(this.w[ROM.NLEN-1-m]<<n);
+		if (ROM.NLEN>m+2) this.w[ROM.NLEN-1]|=(this.w[ROM.NLEN-m-2]>>(ROM.BASEBITS-n));
+		for (i=ROM.NLEN-2;i>m;i--)
+			this.w[i]=((this.w[i-m]<<n)&ROM.BMASK)|(this.w[i-m-1]>>(ROM.BASEBITS-n));
+		this.w[m]=(this.w[0]<<n)&ROM.BMASK; 
+		for (i=0;i<m;i++) this.w[i]=0;
+		return this;
+	},
+/* return length in bits */
+	nbits: function()
+	{
+		var bts,k=ROM.NLEN-1;
+		var c;
+		this.norm();
+		while (k>=0 && this.w[k]===0) k--;
+		if (k<0) return 0;
+		bts=ROM.BASEBITS*k;
+		c=this.w[k];
+		while (c!==0) {c=Math.floor(c/2); bts++;}
+		return bts;
+	},
+/* convert this to string */
+	toString: function()
+	{
+		var b;
+		var s="";
+		var len=this.nbits();
+		if (len%4===0) len=Math.floor(len/4);
+		else {len=Math.floor(len/4); len++;}
+		if (len<ROM.MODBYTES*2) len=ROM.MODBYTES*2;
+		for (var i=len-1;i>=0;i--)
+		{
+			b=new BIG(0);
+			b.copy(this);
+			b.shr(i*4);
+			s+=(b.w[0]&15).toString(16);
+		}
+		return s;
+	},
+/* this+=y */
+	add: function(y)
+	{
+		for (var i=0;i<ROM.NLEN;i++) this.w[i]+=y.w[i];
+		return this;
+	},
+/* return this+x */
+	plus: function(x) 
+	{
+		var s=new BIG(0);
+		for (var i=0;i<ROM.NLEN;i++)
+			s.w[i]=this.w[i]+x.w[i];	
+		return s;
+	},
+/* this+=i, where i is int */
+	inc: function(i)
+	{
+		this.norm();
+		this.w[0]+=i;
+		return this;
+	},
+/* this-=y */
+	sub: function(y)
+	{
+		for (var i=0;i<ROM.NLEN;i++) this.w[i]-=y.w[i];
+		return this;
+	},
+
+/* reverse subtract this=x-this */
+	rsub: function(x) 
+	{
+		for (var i=0;i<ROM.NLEN;i++)
+			this.w[i]=x.w[i]-this.w[i];
+		return this;
+	},
+/* this-=i, where i is int */
+	dec: function(i)
+	{
+		this.norm();
+		this.w[0]-=i;
+		return this;
+	},
+/* return this-x */
+	minus: function(x) {
+		var d=new BIG(0);
+		for (var i=0;i<ROM.NLEN;i++)
+			d.w[i]=this.w[i]-x.w[i];
+		return d;
+	},
+/* multiply by small integer */
+	imul: function(c)
+	{
+		for (var i=0;i<ROM.NLEN;i++) this.w[i]*=c;
+		return this;
+	},
+/* convert this BIG to byte array */
+	tobytearray: function(b,n)
+	{
+		this.norm();
+		var c=new BIG(0);
+		c.copy(this);
+
+		for (var i=ROM.MODBYTES-1;i>=0;i--)
+		{
+			b[i+n]=c.w[0]&0xff;
+			c.fshr(8);
+		}
+		return this;
+	},
+/* convert this to byte array */
+	toBytes: function(b)
+	{
+		this.tobytearray(b,0);
+	},
+
+/* set this[i]+=x*y+c, and return high part */
+	muladd: function(x,y,c,i)
+	{
+		var prod=x*y+c+this.w[i];
+		this.w[i]=prod&ROM.BMASK;
+		return ((prod-this.w[i])*ROM.MODINV);
+	},
+/* multiply by larger int */
+	pmul: function(c)
+	{
+		var ak,carry=0;
+		this.norm();
+		for (var i=0;i<ROM.NLEN;i++)
+		{
+			ak=this.w[i];
+			this.w[i]=0;
+			carry=this.muladd(ak,c,carry,i);
+		}
+		return carry;
+	},
+/* multiply by still larger int - results requires a DBIG */
+	pxmul: function(c)
+	{
+		var m=new DBIG(0);	
+		var carry=0;
+		for (var j=0;j<ROM.NLEN;j++)
+			carry=m.muladd(this.w[j],c,carry,j);
+		m.w[ROM.NLEN]=carry;		
+		return m;
+	},
+/* divide by 3 */
+	div3: function()
+	{	
+		var ak,base,carry=0;
+		this.norm();
+		base=(1<<ROM.BASEBITS);
+		for (var i=ROM.NLEN-1;i>=0;i--)
+		{
+			ak=(carry*base+this.w[i]);
+			this.w[i]=Math.floor(ak/3);
+			carry=ak%3;
+		}
+		return carry;
+	},
+
+/* set x = x mod 2^m */
+	mod2m: function(m)
+	{
+		var i,wd,bt;
+		var msk;
+		wd=Math.floor(m/ROM.BASEBITS);
+		bt=m%ROM.BASEBITS;
+		msk=(1<<bt)-1;
+		this.w[wd]&=msk;
+		for (i=wd+1;i<ROM.NLEN;i++) this.w[i]=0;
+	},
+
+/* a=1/a mod 2^256. This is very fast! */
+	invmod2m: function()
+	{
+		var U=new BIG(0);
+		var b=new BIG(0);
+		var c=new BIG(0);
+
+		U.inc(BIG.invmod256(this.lastbits(8)));
+
+		for (var i=8;i<ROM.BIGBITS;i<<=1)
+		{
+			b.copy(this); b.mod2m(i);
+			var t1=BIG.smul(U,b); t1.shr(i);
+			c.copy(this); c.shr(i); c.mod2m(i);
+
+			var t2=BIG.smul(U,c); t2.mod2m(i);
+			t1.add(t2);
+			b=BIG.smul(t1,U); t1.copy(b);
+			t1.mod2m(i);
+
+			t2.one(); t2.shl(i); t1.rsub(t2); t1.norm();
+			t1.shl(i);
+			U.add(t1);
+		}
+		U.mod2m(ROM.BIGBITS);
+		this.copy(U);
+		this.norm();
+	},
+
+/* reduce this mod m */
+	mod: function(m)
+	{
+		var k=0;  
+		var r=new BIG(0);
+
+		this.norm();
+		if (BIG.comp(this,m)<0) return;
+		do
+		{
+			m.fshl(1);
+			k++;
+		} while (BIG.comp(this,m)>=0);
+
+		while (k>0)
+		{
+			m.fshr(1);
+
+			r.copy(this);
+			r.sub(m);
+			r.norm();
+			this.cmove(r,(1-((r.w[ROM.NLEN-1]>>(ROM.CHUNK-1))&1)));
+
+/*
+			if (BIG.comp(this,m)>=0)
+			{
+				this.sub(m);
+				this.norm();
+			} */
+			k--;
+		}
+	},
+/* this/=m */
+	div: function(m)
+	{
+		var k=0;
+		var d=0;
+		this.norm();
+		var e=new BIG(1);
+		var b=new BIG(0);
+		var r=new BIG(0);
+		b.copy(this);
+		this.zero();
+
+		while (BIG.comp(b,m)>=0)
+		{
+			e.fshl(1);
+			m.fshl(1);
+			k++;
+		}
+
+		while (k>0)
+		{
+			m.fshr(1);
+			e.fshr(1);
+
+			r.copy(b);
+			r.sub(m);
+			r.norm();
+			d=(1-((r.w[ROM.NLEN-1]>>(ROM.CHUNK-1))&1));
+			b.cmove(r,d);
+			r.copy(this);
+			r.add(e);
+			r.norm();
+			this.cmove(r,d); 
+
+/*
+			if (BIG.comp(b,m)>=0)
+			{
+				this.add(e);
+				this.norm();
+				b.sub(m);
+				b.norm();
+			} */
+
+
+			k--;
+		}
+	},
+/* return parity of this */
+	parity: function()
+	{
+		return this.w[0]%2;
+	},
+/* return n-th bit of this */
+	bit: function(n)
+	{
+		if ((this.w[Math.floor(n/ROM.BASEBITS)]&(1<<(n%ROM.BASEBITS)))>0) return 1;
+		else return 0;
+	},
+/* return last n bits of this */
+	lastbits: function(n)
+	{
+		var msk=(1<<n)-1;
+		this.norm();
+		return (this.w[0])&msk;
+	},
+/* Jacobi Symbol (this/p). Returns 0, 1 or -1 */
+	jacobi: function(p)
+	{
+		var n8,k,m=0;
+		var t=new BIG(0);
+		var x=new BIG(0);
+		var n=new BIG(0);
+		var zilch=new BIG(0);
+		var one=new BIG(1);
+		if (p.parity()===0 || BIG.comp(this,zilch)===0 || BIG.comp(p,one)<=0) return 0;
+		this.norm();
+		x.copy(this);
+		n.copy(p);
+		x.mod(p);
+
+		while (BIG.comp(n,one)>0)
+		{
+			if (BIG.comp(x,zilch)===0) return 0;
+			n8=n.lastbits(3);
+			k=0;
+			while (x.parity()===0)
+			{
+				k++;
+				x.shr(1);
+			}
+			if (k%2==1) m+=(n8*n8-1)/8;
+			m+=(n8-1)*(x.lastbits(2)-1)/4;
+			t.copy(n);
+			t.mod(x);
+			n.copy(x);
+			x.copy(t);
+			m%=2;
+
+		}
+		if (m===0) return 1;
+		else return -1;
+	},
+/* this=1/this mod p. Binary method */
+	invmodp: function(p)
+	{
+		this.mod(p);
+		var u=new BIG(0);
+		u.copy(this);
+		var v=new BIG(0);
+		v.copy(p);
+		var x1=new BIG(1);
+		var x2=new BIG(0);
+		var t=new BIG(0);
+		var one=new BIG(1);
+
+		while (BIG.comp(u,one)!==0 && BIG.comp(v,one)!==0)
+		{
+			while (u.parity()===0)
+			{
+				u.shr(1);
+				if (x1.parity()!==0)
+				{
+					x1.add(p);
+					x1.norm();
+				}
+				x1.shr(1);
+			}
+			while (v.parity()===0)
+			{
+				v.shr(1);
+				if (x2.parity()!==0)
+				{
+					x2.add(p);
+					x2.norm();
+				}
+				x2.shr(1);
+			}
+			if (BIG.comp(u,v)>=0)
+			{
+				u.sub(v);
+				u.norm();
+				if (BIG.comp(x1,x2)>=0) x1.sub(x2);
+				else
+				{
+					t.copy(p);
+					t.sub(x2);
+					x1.add(t);
+				}
+				x1.norm();
+			}
+			else
+			{
+				v.sub(u);
+				v.norm();
+				if (BIG.comp(x2,x1)>=0) x2.sub(x1);
+				else
+				{
+					t.copy(p);
+					t.sub(x1);
+					x2.add(t);
+				}
+				x2.norm();
+			}
+		}
+		if (BIG.comp(u,one)===0) this.copy(x1);
+		else this.copy(x2);
+	},
+/* return this^e mod m */
+	powmod:function(e,m)
+	{
+		var bt;
+		this.norm();
+		e.norm();
+		var a=new BIG(1);
+		var z=new BIG(0);
+		z.copy(e);
+		var s=new BIG(0);
+		s.copy(this);
+		var i=0;
+		while (true)
+		{
+			i++;
+			bt=z.parity();
+			z.fshr(1);
+			if (bt==1) a=BIG.modmul(a,s,m);
+//ROM.debug=false;
+			if (z.iszilch()) break;
+			s=BIG.modsqr(s,m);
+		}
+		return a;
+	}
+
+};
+/* convert from byte array to BIG */
+BIG.frombytearray=function(b,n)
+{
+	var m=new BIG(0);
+
+	for (var i=0;i<ROM.MODBYTES;i++)
+	{
+		m.fshl(8); m.w[0]+=b[i+n]&0xff;
+		//m.inc(b[i]&0xff);
+	}
+	return m; 
+};
+
+BIG.fromBytes=function(b)
+{
+	return BIG.frombytearray(b,0);
+};
+
+/* return a*b where product fits a BIG */
+BIG.smul=function(a,b)
+{
+	var carry;
+	var c=new BIG(0);
+	for (var i=0;i<ROM.NLEN;i++)
+	{
+		carry=0;
+		for (var j=0;j<ROM.NLEN;j++)
+			if (i+j<ROM.NLEN) carry=c.muladd(a.w[i],b.w[j],carry,i+j);
+	}
+	return c;
+};
+/* Compare a and b, return 0 if a==b, -1 if a<b, +1 if a>b. Inputs must be normalised */
+BIG.comp=function(a,b)
+{
+	for (var i=ROM.NLEN-1;i>=0;i--)
+	{
+		if (a.w[i]==b.w[i]) continue;
+		if (a.w[i]>b.w[i]) return 1;
+		else  return -1;
+	}
+	return 0;
+};
+
+/* get 8*MODBYTES size random number */
+BIG.random=function(rng)
+{
+	var m=new BIG(0);
+	var i,b,j=0,r=0;
+
+/* generate random BIG */ 
+	for (i=0;i<8*ROM.MODBYTES;i++)   
+	{
+		if (j===0) r=rng.getByte();
+		else r>>=1;
+
+		b=r&1;
+		m.shl(1); m.w[0]+=b;// m.inc(b);
+		j++; j&=7; 
+	}
+	return m;
+};
+
+/* Create random BIG in portable way, one bit at a time */
+BIG.randomnum=function(q,rng)
+{
+	var d=new DBIG(0);
+	var i,b,j=0,r=0;
+	for (i=0;i<2*ROM.MODBITS;i++)
+	{
+		if (j===0) r=rng.getByte();
+		else r>>=1;
+
+		b=r&1;
+		d.shl(1); d.w[0]+=b; 
+		j++; j&=7;
+	}
+
+	var m=d.mod(q);
+
+	return m;
+};
+
+/* return NAF value as +/- 1, 3 or 5. x and x3 should be normed. 
+nbs is number of bits processed, and nzs is number of trailing 0s detected */
+/*
+BIG.nafbits=function(x,x3,i)
+{
+	var n=[];
+	var nb=x3.bit(i)-x.bit(i);
+	var j;
+	n[1]=1;
+	n[0]=0;
+	if (nb===0) {n[0]=0; return n;}
+	if (i===0) {n[0]=nb; return n;}
+	if (nb>0) n[0]=1;
+	else      n[0]=(-1);
+
+	for (j=i-1;j>0;j--)
+	{
+		n[1]++;
+		n[0]*=2;
+		nb=x3.bit(j)-x.bit(j);
+		if (nb>0) n[0]+=1;
+		if (nb<0) n[0]-=1;
+		if (n[0]>5 || n[0]<-5) break;
+	}
+
+	if (n[0]%2!==0 && j!==0)
+	{ // backtrack 
+		if (nb>0) n[0]=(n[0]-1)/2;
+		if (nb<0) n[0]=(n[0]+1)/2;
+		n[1]--;
+	}
+	while (n[0]%2===0)
+	{ // remove trailing zeros 
+		n[0]/=2;
+		n[2]++;
+		n[1]--;
+	}
+	return n;
+};
+*/
+/* return a*b as DBIG */
+BIG.mul=function(a,b)
+{
+	var n,c=new DBIG(0);
+//	a.norm();
+//	b.norm();
+
+		var d=[];
+		var s,t;
+
+		for (var i=0;i<ROM.NLEN;i++)
+			d[i]=a.w[i]*b.w[i];
+
+		s=d[0];
+		t=s; c.w[0]=t;
+
+		for (var k=1;k<ROM.NLEN;k++)
+		{
+			s+=d[k]; t=s; for (i=k;i>=1+Math.floor(k/2);i--) t+=(a.w[i]-a.w[k-i])*(b.w[k-i]-b.w[i]); c.w[k]=t;
+		}
+		for (var k=ROM.NLEN;k<2*ROM.NLEN-1;k++)
+		{
+			s-=d[k-ROM.NLEN]; t=s; for (i=ROM.NLEN-1;i>=1+Math.floor(k/2);i--) t+=(a.w[i]-a.w[k-i])*(b.w[k-i]-b.w[i]); c.w[k]=t; 
+		}
+
+		var co=0;
+		for (var i=0;i<ROM.DNLEN-1;i++)
+		{
+			n=c.w[i]+co;
+			c.w[i]=n&ROM.BMASK;
+			co=(n-c.w[i])*ROM.MODINV;
+		}
+		c.w[ROM.DNLEN-1]=co;		
+
+
+/*
+	for (var j=0;j<ROM.NLEN;j++)
+	{
+		t=0; for (var i=0;i<=j;i++) t+=a.w[j-i]*b.w[i];
+		c.w[j]=t;
+	}
+	for (var j=ROM.NLEN;j<ROM.DNLEN-2;j++)
+	{
+		t=0; for (var i=j-ROM.NLEN+1;i<ROM.NLEN;i++) t+=a.w[j-i]*b.w[i];
+		c.w[j]=t; 
+	}
+	t=a.w[ROM.NLEN-1]*b.w[ROM.NLEN-1];
+	c.w[ROM.DNLEN-2]=t;
+	var co=0;
+	for (var i=0;i<ROM.DNLEN-1;i++)
+	{
+		n=c.w[i]+co;
+		c.w[i]=n&ROM.BMASK;
+		co=(n-c.w[i])*ROM.MODINV;
+	}
+	c.w[ROM.DNLEN-1]=co;
+*/
+	return c;
+};
+
+/* return a^2 as DBIG */
+BIG.sqr=function(a)
+{
+	var n,c=new DBIG(0);
+//	a.norm();
+
+	c.w[0]=a.w[0]*a.w[0];
+	t=a.w[1]*a.w[0]; t+=t; c.w[1]=t;
+
+	var last=ROM.NLEN-ROM.NLEN%2;
+	for (j=2;j<last;j+=2)
+	{
+		t=a.w[j]*a.w[0]; for (var i=1;i<(j+1)>>1;i++) t+=a.w[j-i]*a.w[i]; t+=t; t+=a.w[j>>1]*a.w[j>>1];
+		c.w[j]=t;
+		t=a.w[j+1]*a.w[0]; for (var i=1;i<(j+2)>>1;i++) t+=a.w[j+1-i]*a.w[i]; t+=t;
+		c.w[j+1]=t;
+	}	
+	j=last;
+	if (ROM.NLEN%2==1)
+	{
+		t=a.w[j]*a.w[0]; for (var i=1;i<(j+1)>>1;i++) t+=a.w[j-i]*a.w[i]; t+=t; t+=a.w[j>>1]*a.w[j>>1];
+		c.w[j]=t; j++;
+		t=a.w[ROM.NLEN-1]*a.w[j-ROM.NLEN+1]; for (var i=j-ROM.NLEN+2;i<(j+1)>>1;i++) t+=a.w[j-i]*a.w[i]; t+=t;
+		c.w[j]=t; j++;
+	}
+
+//	j=ROM.NLEN;
+//	t=a.w[ROM.NLEN-1]*a.w[j-ROM.NLEN+1]; for (var i=j-ROM.NLEN+2;i<(j+1)>>1;i++) t+=a.w[j-i]*a.w[i]; t+=t; 
+//	c.w[j]=t;
+
+
+	for (;j<ROM.DNLEN-2;j+=2)
+	{
+		t=a.w[ROM.NLEN-1]*a.w[j-ROM.NLEN+1]; for (var i=j-ROM.NLEN+2;i<(j+1)>>1;i++) t+=a.w[j-i]*a.w[i]; t+=t; t+=a.w[j>>1]*a.w[j>>1];
+		c.w[j]=t;
+		t=a.w[ROM.NLEN-1]*a.w[j-ROM.NLEN+2]; for (var i=j-ROM.NLEN+3;i<(j+2)>>1;i++) t+=a.w[j+1-i]*a.w[i]; t+=t; 
+		c.w[j+1]=t;
+	}
+
+	t=a.w[ROM.NLEN-1]*a.w[ROM.NLEN-1];
+	c.w[ROM.DNLEN-2]=t;
+
+	var co=0;
+	for (var i=0;i<ROM.DNLEN-1;i++)
+	{
+		n=c.w[i]+co;
+		c.w[i]=n&ROM.BMASK;
+		co=(n-c.w[i])*ROM.MODINV;
+	}
+	c.w[ROM.DNLEN-1]=co;
+	return c;
+};
+
+/* reduce a DBIG to a BIG using a "special" modulus */
+BIG.mod=function(d)
+{
+	var i,j,b=new BIG(0);
+	if (ROM.MODTYPE==ROM.PSEUDO_MERSENNE)
+	{
+		var v,tw;
+		var t=d.split(ROM.MODBITS);
+		b.hcopy(d);
+
+		if (ROM.MConst!=1)
+			v=t.pmul(ROM.MConst);
+		else v=0;
+		tw=t.w[ROM.NLEN-1];
+		t.w[ROM.NLEN-1]&=ROM.TMASK;
+		t.inc(ROM.MConst*((tw>>ROM.TBITS)+(v<<(ROM.BASEBITS-ROM.TBITS))));
+		b.add(t);
+	}
+	
+	if (ROM.MODTYPE==ROM.MONTGOMERY_FRIENDLY)
+	{
+		for (i=0;i<ROM.NLEN;i++)
+			d.w[ROM.NLEN+i]+=d.muladd(d.w[i],ROM.MConst-1,d.w[i],ROM.NLEN+i-1);
+		for (i=0;i<ROM.NLEN;i++)
+			b.w[i]=d.w[ROM.NLEN+i];
+	}
+
+	if (ROM.MODTYPE==ROM.GENERALISED_MERSENNE)
+	{ // GoldiLocks Only
+		var t=d.split(ROM.MODBITS);
+		b.hcopy(d);
+		b.add(t);
+		var dd=new DBIG(0);
+		dd.hcopy(t);
+		dd.shl(ROM.MODBITS/2);
+
+		var tt=dd.split(ROM.MODBITS);
+		var lo=new BIG();
+		lo.hcopy(dd);
+
+		b.add(tt);
+		b.add(lo);
+		//b.norm();
+		tt.shl(ROM.MODBITS/2);
+		b.add(tt);
+
+		var carry=b.w[ROM.NLEN-1]>>ROM.TBITS;
+		b.w[ROM.NLEN-1]&=ROM.TMASK;
+		b.w[0]+=carry;
+			
+		b.w[Math.floor(224/ROM.BASEBITS)]+=carry<<(224%ROM.BASEBITS);
+	}
+
+	if (ROM.MODTYPE==ROM.NOT_SPECIAL)
+	{
+
+		var m=new BIG(0);
+		var v=[];
+		var dd=[];
+		var s,c,t;
+
+		m.rcopy(ROM.Modulus);
+
+
+		t=d.w[0]; v[0]=((t&ROM.BMASK)*ROM.MConst)&ROM.BMASK; t+=v[0]*m.w[0]; 
+		c=d.w[1]+(t*ROM.MODINV); s=0;
+
+		for (var k=1;k<ROM.NLEN;k++)
+		{
+			t=c+s+v[0]*m.w[k];
+			for (i=k-1;i>Math.floor(k/2);i--) t+=(v[k-i]-v[i])*(m.w[i]-m.w[k-i]);
+			v[k]=((t&ROM.BMASK)*ROM.MConst)&ROM.BMASK; t+=v[k]*m.w[0]; 
+			c=(t*ROM.MODINV)+d.w[k+1];
+
+			dd[k]=v[k]*m.w[k]; s+=dd[k];
+		}
+		for (var k=ROM.NLEN;k<2*ROM.NLEN-1;k++)
+		{
+			t=c+s;
+			for (i=ROM.NLEN-1;i>=1+Math.floor(k/2);i--) t+=(v[k-i]-v[i])*(m.w[i]-m.w[k-i]);
+			b.w[k-ROM.NLEN]=t&ROM.BMASK; 
+			c=((t-b.w[k-ROM.NLEN])*ROM.MODINV)+d.w[k+1]; 
+
+			s-=dd[k-ROM.NLEN+1];
+		}
+		b.w[ROM.NLEN-1]=c&ROM.BMASK;	
+
+
+/*	
+		var md=new BIG(0);
+		md.rcopy(ROM.Modulus);
+		var sum;
+
+		sum=d.w[0];
+		for (j=0;j<ROM.NLEN;j++)
+		{
+			for (i=0;i<j;i++) sum+=d.w[i]*md.w[j-i];
+			d.w[j]=((sum&ROM.BMASK)*ROM.MConst)&ROM.BMASK; sum+=d.w[j]*md.w[0];
+			sum=d.w[j+1]+(sum*ROM.MODINV);
+		}
+
+
+		for (j=ROM.NLEN;j<ROM.DNLEN-2;j++)
+		{
+			for (i=j-ROM.NLEN+1;i<ROM.NLEN;i++) sum+=d.w[i]*md.w[j-i];
+			d.w[j]=sum&ROM.BMASK;
+			sum=d.w[j+1]+((sum-d.w[j])*ROM.MODINV);
+		}
+
+		sum+=d.w[ROM.NLEN-1]*md.w[ROM.NLEN-1];
+		d.w[ROM.DNLEN-2]=sum&ROM.BMASK;
+		sum=d.w[ROM.DNLEN-1]+((sum-d.w[ROM.DNLEN-2])*ROM.MODINV);
+		d.w[ROM.DNLEN-1]=sum&ROM.BMASK;
+		for (i=0;i<ROM.NLEN;i++)
+			b.w[i]=d.w[ROM.NLEN+i];
+*/		
+	}
+	b.norm();
+	return b;
+};
+
+/* return a*b mod m */
+BIG.modmul=function(a,b,m)
+{
+	a.mod(m);
+	b.mod(m);
+	var d=BIG.mul(a,b);
+	return d.mod(m);
+};
+
+/* return a^2 mod m */
+BIG.modsqr=function(a,m)
+{
+	a.mod(m);
+	var d=BIG.sqr(a);
+	return d.mod(m);
+};
+
+/* return -a mod m */
+BIG.modneg=function(a,m)
+{
+	a.mod(m);
+	return m.minus(a);
+};
+
+/* calculate Field Excess */
+BIG.EXCESS=function(a)
+{
+	return ((a.w[ROM.NLEN-1]&ROM.OMASK)>>(ROM.MODBITS%ROM.BASEBITS));
+};
+
+/* Arazi and Qi inversion mod 256 */
+BIG.invmod256=function(a)
+{
+	var U,t1,t2,b,c;
+	t1=0;
+	c=(a>>1)&1;  
+	t1+=c;
+	t1&=1;
+	t1=2-t1;
+	t1<<=1;
+	U=t1+1;
+
+// i=2
+	b=a&3;
+	t1=U*b; t1>>=2;
+	c=(a>>2)&3;
+	t2=(U*c)&3;
+	t1+=t2;
+	t1*=U; t1&=3;
+	t1=4-t1;
+	t1<<=2;
+	U+=t1;
+
+// i=4
+	b=a&15;
+	t1=U*b; t1>>=4;
+	c=(a>>4)&15;
+	t2=(U*c)&15;
+	t1+=t2;
+	t1*=U; t1&=15;
+	t1=16-t1;
+	t1<<=4;
+	U+=t1;
+
+	return U;
+};
+
diff --git a/version22/js/BenchtestEC.html b/version22/js/BenchtestEC.html
new file mode 100644
index 0000000..49ca241
--- /dev/null
+++ b/version22/js/BenchtestEC.html
@@ -0,0 +1,162 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>JavaScript Elliptic Curve Benchtest</title>
+</head>
+<body>
+<h1>JavaScript Benchmark ECC and RSA</h1>
+<script type="text/javascript" src="DBIG.js"></script>
+<script type="text/javascript" src="BIG.js"></script>
+<script type="text/javascript" src="FP.js"></script>
+<script type="text/javascript" src="ROM.js"></script>
+<script type="text/javascript" src="FF.js"></script>
+<script type="text/javascript" src="ECP.js"></script>
+<script type="text/javascript" src="RSA.js"></script>
+<script type="text/javascript" src="HASH256.js"></script>
+<script type="text/javascript" src="RAND.js"></script>
+<script>
+/* test driver and function exerciser ECC functions */
+		var i,j;
+		var result;
+		var MIN_ITERS=10;
+		var MIN_TIME=10;
+		var pub=new rsa_public_key(ROM.FFLEN);
+		var priv=new rsa_private_key(ROM.HFLEN);
+		var fail=false;
+
+		var RAW=[];
+		var M=[];
+		var C=[];
+		var P=[];
+
+		var rng=new RAND();
+
+		rng.clean();
+		for (i=0;i<100;i++) RAW[i]=i;
+
+		rng.seed(100,RAW);
+
+		if (ROM.CURVETYPE==ROM.WEIERSTRASS)
+		{
+			window.document.write("Weierstrass parameterization "+ "<br>");
+		}		
+		if (ROM.CURVETYPE==ROM.EDWARDS)
+		{
+			window.document.write("Edwards parameterization"+ "<br>");
+		}
+		if (ROM.CURVETYPE==ROM.MONTGOMERY)
+		{
+			window.document.write("Montgomery parameterization"+ "<br>");
+		}
+
+		if (ROM.MODTYPE==ROM.PSEUDO_MERSENNE)
+		{
+			window.document.write("Pseudo-Mersenne Modulus"+ "<br>");
+		}
+		if (ROM.MODTYPE==ROM.MONTGOMERY_FRIENDLY)
+		{
+			window.document.write("Montgomery friendly Modulus"+ "<br>");
+		}
+		if (ROM.MODTYPE==ROM.GENERALISED_MERSENNE)
+		{
+			window.document.write("Generalised-Mersenne Modulus"+ "<br>");
+		}
+		if (ROM.MODTYPE==ROM.NOT_SPECIAL)
+		{
+			window.document.write("Not special Modulus"+ "<br>");
+		}
+
+		window.document.write("Modulus size "+ROM.MODBITS+ " bits"+ "<br>"); 
+		window.document.write(ROM.CHUNK + " bit build"+ "<br>"); 
+		var r,gx,gy,s;
+		var G,WP;
+		var res=0;
+
+		G=new ECP(0);
+
+		gx=new BIG(0); gx.rcopy(ROM.CURVE_Gx);
+
+		if (ROM.CURVETYPE!=ROM.MOMTGOMERY)
+		{
+			gy=new BIG(0); gy.rcopy(ROM.CURVE_Gy);
+			G.setxy(gx,gy);
+		}
+		else G.setx(gx);
+
+		r=new BIG(0); r.rcopy(ROM.CURVE_Order);
+		s=BIG.randomnum(r,rng);
+			
+		WP=G.mul(r);
+		if (!WP.is_infinity())
+		{
+			alert("FAILURE - rG!=O");
+			fail=true;
+		}
+		var elapsed;
+		var start = performance.now();
+		iterations=0;
+		do {
+			WP=G.mul(s);
+			iterations++;
+			elapsed=(performance.now()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=elapsed/iterations;
+		window.document.write("EC  mul - " + iterations + " iterations  ");
+		window.document.write(dur.toFixed(2) + " ms per iteration"+ "<br>");
+
+		window.document.write("Generating " +ROM.FFLEN*ROM.BIGBITS + " - bit RSA public/private key pair"+ "<br>");
+
+		MIN_ITERS=1;
+		start = performance.now();
+		iterations=0;
+		do {
+			RSA.KEY_PAIR(rng,65537,priv,pub);
+			iterations++;
+			elapsed=(performance.now()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=elapsed/iterations;
+		window.document.write("RSA gen - " + iterations + " iteration  ");
+		window.document.write(dur.toFixed(2) + " ms per iteration"+ "<br>");
+
+		MIN_ITERS=10;
+
+		for (i=0;i<RSA.RFS;i++) M[i]=(i%128);
+
+		start = performance.now();
+		iterations=0;
+		do {
+			RSA.ENCRYPT(pub,M,C);
+			iterations++;
+			elapsed=(performance.now()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=elapsed/iterations;
+		window.document.write("RSA enc - " + iterations + " iterations  ");
+		window.document.write(dur.toFixed(2) + " ms per iteration"+ "<br>");
+
+		start = performance.now();
+		iterations=0;
+		do {
+			RSA.DECRYPT(priv,C,P);
+			iterations++;
+			elapsed=(performance.now()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=elapsed/iterations;
+		window.document.write("RSA dec - " + iterations + " iterations  ");
+		window.document.write(dur.toFixed(2) + " ms per iteration"+ "<br>");
+
+		var cmp=true;
+		for (i=0;i<RSA.RFS;i++)
+		{
+			if (P[i]!=M[i]) cmp=false;
+		}
+
+		if (!cmp)
+		{
+			alert("FAILURE - RSA decryption");
+			fail=true;
+		}
+		if (!fail) window.document.write("All tests pass"+ "<br>");
+
+</script>
+</body>
+</html>
diff --git a/version22/js/BenchtestPAIR.html b/version22/js/BenchtestPAIR.html
new file mode 100644
index 0000000..b6a9bb5
--- /dev/null
+++ b/version22/js/BenchtestPAIR.html
@@ -0,0 +1,226 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>JavaScript PAIRing Benchtest</title>
+</head>
+<body>
+<h1>JavaScript Benchmark Pairings</h1>
+<script type="text/javascript" src="DBIG.js"></script>
+<script type="text/javascript" src="BIG.js"></script>
+<script type="text/javascript" src="FP.js"></script>
+<script type="text/javascript" src="ROM.js"></script>
+<script type="text/javascript" src="UInt64.js"></script>
+<script type="text/javascript" src="HASH256.js"></script>
+<script type="text/javascript" src="HASH384.js"></script>
+<script type="text/javascript" src="HASH512.js"></script>
+<script type="text/javascript" src="RAND.js"></script>
+<script type="text/javascript" src="AES.js"></script>
+<script type="text/javascript" src="GCM.js"></script>
+<script type="text/javascript" src="ECP.js"></script>
+<script type="text/javascript" src="FP2.js"></script>
+<script type="text/javascript" src="ECP2.js"></script>
+<script type="text/javascript" src="FP4.js"></script>
+<script type="text/javascript" src="FP12.js"></script>
+<script type="text/javascript" src="PAIR.js"></script>
+
+<script>
+/* test driver and function exerciser for PAIRING Functions */
+
+		var i;
+		var result;
+		var MIN_ITERS=1;
+		var MIN_TIME=10;
+		var RAW=[];
+		var fail=false;
+		var G=new ECP(0);
+		var Q=new ECP2(0);
+
+		var rng=new RAND();
+		rng.clean();
+
+		for (i=0;i<100;i++) RAW[i]=i+1;
+		rng.seed(100,RAW);
+
+		if (ROM.CURVE_PAIRING_TYPE==ROM.BN_CURVE)
+		{
+			window.document.write("BN Pairing-Friendly Curve"+ "<br>");
+		}
+		if (ROM.CURVE_PAIRING_TYPE==ROM.BLS_CURVE)
+		{
+			window.document.write("BLS Pairing-Friendly Curve"+ "<br>");
+		}
+
+		window.document.write("Modulus size " + ROM.MODBITS + " bits"+ "<br>"); 
+		window.document.write(ROM.CHUNK + " bit build"+ "<br>"); 
+
+		var gx=new BIG(0); gx.rcopy(ROM.CURVE_Gx);	
+		var gy=new BIG(0); gy.rcopy(ROM.CURVE_Gy);
+		G.setxy(gx,gy);			
+
+		r=new BIG(0); r.rcopy(ROM.CURVE_Order);
+		s=BIG.randomnum(r,rng);
+
+		var P=PAIR.G1mul(G,r);
+
+		if (!P.is_infinity())
+		{
+			alert("FAILURE - rP!=O");
+			fail=true;
+		}	
+
+		var elapsed;
+		var start = performance.now();
+		iterations=0;
+		do {
+			P=PAIR.G1mul(G,s);
+			iterations++;
+			elapsed=(performance.now()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=elapsed/iterations;
+		window.document.write("G1 mul -                " + iterations + " iterations  ");
+		window.document.write(dur.toFixed(2) + " ms per iteration"+ "<br>");
+
+		var A=new BIG(0);
+		var B=new BIG(0);
+		A.rcopy(ROM.CURVE_Pxa); B.rcopy(ROM.CURVE_Pxb);
+		var QX=new FP2(0); QX.bset(A,B);
+		A.rcopy(ROM.CURVE_Pya); B.rcopy(ROM.CURVE_Pyb);
+		var QY=new FP2(0); QY.bset(A,B);
+		Q.setxy(QX,QY);
+
+		W=PAIR.G2mul(Q,r);
+
+		if (!W.is_infinity())
+		{
+			alert("FAILURE - rQ!=O");
+			fail=true;
+		}
+
+		start = performance.now();
+		iterations=0;
+		do {
+			W=PAIR.G2mul(Q,s);
+			iterations++;
+			elapsed=(performance.now()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=elapsed/iterations;
+		window.document.write("G2 mul -                " + iterations + " iteration  ");
+		window.document.write(dur.toFixed(2) + " ms per iteration"+ "<br>");
+
+		var w=PAIR.ate(Q,P);
+		w=PAIR.fexp(w);
+
+		var g=PAIR.GTpow(w,r);
+
+		if (!g.isunity())
+		{
+			alert("FAILURE - g^r!=1");
+			fail=true;
+		}
+
+		start = performance.now();
+		iterations=0;
+		do {
+			g=PAIR.GTpow(w,s);
+			iterations++;
+			elapsed=(performance.now()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=elapsed/iterations;
+		window.document.write("GT pow -                " + iterations + " iteration  ");
+		window.document.write(dur.toFixed(2) + " ms per iteration"+ "<br>");
+
+		var fa=new BIG(0); fa.rcopy(ROM.CURVE_Fra);
+		var fb=new BIG(0); fb.rcopy(ROM.CURVE_Frb);
+		var f=new FP2(fa,fb); //f.bset(fa,fb);
+
+		q=new BIG(0); q.rcopy(ROM.Modulus);
+
+		var m=new BIG(q);
+		m.mod(r);
+
+		var a=new BIG(s);
+		a.mod(m);
+
+		var b=new BIG(s);
+		b.div(m);
+
+		g.copy(w);
+		var c=g.trace();
+
+		g.frob(f);
+		var cp=g.trace();
+
+		w.conj();
+		g.mul(w);
+		var cpm1=g.trace();
+		g.mul(w);
+		var cpm2=g.trace();
+
+		var cr;
+		start = performance.now();
+		iterations=0;
+		do {
+			cr=c.xtr_pow2(cp,cpm1,cpm2,a,b);
+			iterations++;
+			elapsed=(performance.now()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=elapsed/iterations;
+		window.document.write("GT pow (compressed) -   " + iterations + " iteration  ");
+		window.document.write(dur.toFixed(2) + " ms per iteration"+ "<br>");
+
+		start = performance.now();
+		iterations=0;
+		do {
+			w=PAIR.ate(Q,P);
+			iterations++;
+			elapsed=(performance.now()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=elapsed/iterations;
+		window.document.write("PAIRing ATE   -         " + iterations + " iteration  ");
+		window.document.write(dur.toFixed(2) + " ms per iteration"+ "<br>");
+
+		start = performance.now();
+		iterations=0;
+		do {
+			g=PAIR.fexp(w);
+			iterations++;
+			elapsed=(performance.now()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=elapsed/iterations;
+		window.document.write("PAIRing FEXP -          " + iterations + " iteration  ");
+		window.document.write(dur.toFixed(2) + " ms per iteration"+ "<br>");
+
+		P.copy(G);
+		Q.copy(W);
+
+		P=PAIR.G1mul(P,s);
+		g=PAIR.ate(Q,P);
+		g=PAIR.fexp(g);
+
+		P.copy(G);
+		Q=PAIR.G2mul(Q,s);
+		w=PAIR.ate(Q,P);
+		w=PAIR.fexp(w);
+
+		if (!g.equals(w))
+		{
+			alert("FAILURE - e(sQ,p)!=e(Q,sP)");
+			fail=true;
+		}
+
+		Q.copy(W);
+		g=PAIR.ate(Q,P);
+		g=PAIR.fexp(g);
+		g=PAIR.GTpow(g,s);
+
+		if (!g.equals(w))
+		{
+			alert("FAILURE - e(sQ,p)!=e(Q,P)^s");
+			fail=true;
+		}
+
+		if (!fail) window.document.write("All tests pass"+ "<br>");
+
+</script>
+</body>
+</html>
diff --git a/version22/js/DBIG.js b/version22/js/DBIG.js
new file mode 100644
index 0000000..38ff462
--- /dev/null
+++ b/version22/js/DBIG.js
@@ -0,0 +1,284 @@
+/*
+	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.
+*/
+
+/* AMCL double length DBIG number class */ 
+
+/* constructor */
+var DBIG = function(x) {
+	this.w=[]; 
+	this.zero();
+	this.w[0]=x;
+};
+
+DBIG.prototype={
+
+/* set this=0 */
+	zero: function()
+	{
+		for (var i=0;i<ROM.DNLEN;i++) this.w[i]=0;
+		return this;
+	},
+
+/* set this=b */
+	copy: function(b)
+	{
+		for (var i=0;i<ROM.DNLEN;i++) this.w[i]=b.w[i];
+		return this;
+	},
+
+
+/* copy from BIG */
+	hcopy: function(b)
+	{
+		var i;
+		for (i=0;i<ROM.NLEN;i++) this.w[i]=b.w[i];
+		for (i=ROM.NLEN;i<ROM.DNLEN;i++) this.w[i]=0;
+		return this;
+	},
+
+/* normalise this */
+	norm: function()
+	{
+		var d,carry=0;
+		for (var i=0;i<ROM.DNLEN-1;i++)
+		{
+			d=this.w[i]+carry;
+			this.w[i]=d&ROM.BMASK;
+			carry=d>>ROM.BASEBITS;
+		}
+		this.w[ROM.DNLEN-1]=(this.w[ROM.DNLEN-1]+carry);
+		return this;
+	},
+
+/* set this[i]+=x*y+c, and return high part */
+	muladd: function(x,y,c,i)
+	{
+		var prod=x*y+c+this.w[i];
+		this.w[i]=prod&ROM.BMASK;
+		return ((prod-this.w[i])*ROM.MODINV);
+	},
+
+/* shift this right by k bits */
+	shr: function(k) 
+	{
+		var i,n=k%ROM.BASEBITS;
+		var m=Math.floor(k/ROM.BASEBITS);	
+		for (i=0;i<ROM.DNLEN-m-1;i++)
+			this.w[i]=(this.w[m+i]>>n)|((this.w[m+i+1]<<(ROM.BASEBITS-n))&ROM.BMASK);
+		this.w[ROM.DNLEN-m-1]=this.w[ROM.DNLEN-1]>>n;
+		for (i=ROM.DNLEN-m;i<ROM.DNLEN;i++) this.w[i]=0;
+		return this;
+	},
+
+/* shift this left by k bits */
+	shl: function(k) 
+	{
+		var i,n=k%ROM.BASEBITS;
+		var m=Math.floor(k/ROM.BASEBITS);
+
+		this.w[ROM.DNLEN-1]=((this.w[ROM.DNLEN-1-m]<<n))|(this.w[ROM.DNLEN-m-2]>>(ROM.BASEBITS-n));
+		for (i=ROM.DNLEN-2;i>m;i--)
+			this.w[i]=((this.w[i-m]<<n)&ROM.BMASK)|(this.w[i-m-1]>>(ROM.BASEBITS-n));
+		this.w[m]=(this.w[0]<<n)&ROM.BMASK; 
+		for (i=0;i<m;i++) this.w[i]=0;
+		return this;
+	},
+
+/* Conditional move of big depending on d using XOR - no branches */
+	cmove: function(b,d)
+	{
+		var i;
+		var c=d;
+		c=~(c-1);
+
+		for (i=0;i<ROM.DNLEN;i++)
+		{
+			this.w[i]^=(this.w[i]^b.w[i])&c;
+		}
+	},
+
+
+/* this+=x */
+	add: function(x) 
+	{
+		for (var i=0;i<ROM.DNLEN;i++)
+			this.w[i]+=x.w[i];	
+	},
+
+/* this-=x */
+	sub: function(x) 
+	{
+		for (var i=0;i<ROM.DNLEN;i++)
+			this.w[i]-=x.w[i];
+	},
+
+/* return number of bits in this */
+	nbits: function()
+	{
+		var bts,k=ROM.DNLEN-1;
+		var c;
+		this.norm();
+		while (k>=0 && this.w[k]===0) k--;
+		if (k<0) return 0;
+		bts=ROM.BASEBITS*k;
+		c=this.w[k];
+		while (c!==0) {c=Math.floor(c/2); bts++;}
+		return bts;
+	},
+
+/* convert this to string */
+	toString: function()
+	{
+
+		var b;
+		var s="";
+		var len=this.nbits();
+		if (len%4===0) len=Math.floor(len/4);
+		else {len=Math.floor(len/4); len++;}
+
+		for (var i=len-1;i>=0;i--)
+		{
+			b=new DBIG(0);
+			b.copy(this);
+			b.shr(i*4);
+			s+=(b.w[0]&15).toString(16);
+		}
+		return s;
+	},
+
+/* reduces this DBIG mod a BIG, and returns the BIG */
+	mod: function(c)
+	{
+		var k=0;  
+		this.norm();
+		var m=new DBIG(0);
+		var dr=new DBIG(0);
+		m.hcopy(c);
+		var r=new BIG(0);
+		r.hcopy(this);
+
+		if (DBIG.comp(this,m)<0) return r;
+
+		do
+		{
+			m.shl(1);
+			k++;
+		}
+		while (DBIG.comp(this,m)>=0);
+
+		while (k>0)
+		{
+			m.shr(1);
+
+			dr.copy(this);
+			dr.sub(m);
+			dr.norm();
+			this.cmove(dr,(1-((dr.w[ROM.DNLEN-1]>>(ROM.CHUNK-1))&1)));
+
+/*
+			if (DBIG.comp(this,m)>=0)
+			{
+				this.sub(m);
+				this.norm();
+			} */
+			k--;
+		}
+
+		r.hcopy(this);
+		return r;
+	},
+
+/* this/=c */
+	div: function(c)
+	{
+		var d=0;
+		var k=0;
+		var m=new DBIG(0); m.hcopy(c);
+		var dr=new DBIG(0);
+		var r=new BIG(0);
+		var a=new BIG(0);
+		var e=new BIG(1);
+		this.norm();
+
+		while (DBIG.comp(this,m)>=0)
+		{
+			e.fshl(1);
+			m.shl(1);
+			k++;
+		}
+
+		while (k>0)
+		{
+			m.shr(1);
+			e.shr(1);
+
+			dr.copy(this);
+			dr.sub(m);
+			dr.norm();
+			d=(1-((dr.w[ROM.DNLEN-1]>>(ROM.CHUNK-1))&1));
+			this.cmove(dr,d);
+			r.copy(a);
+			r.add(e);
+			r.norm();
+			a.cmove(r,d);  
+/*
+			if (DBIG.comp(this,m)>0)
+			{
+				a.add(e);
+				a.norm();
+				this.sub(m);
+				this.norm();
+			}  */
+			k--;
+		}
+		return a;
+	},
+
+/* split this DBIG at position n, return higher half, keep lower half */
+	split: function(n)
+	{
+		var t=new BIG(0);
+		var nw,m=n%ROM.BASEBITS;
+		var carry=this.w[ROM.DNLEN-1]<<(ROM.BASEBITS-m);
+
+	
+		for (var i=ROM.DNLEN-2;i>=ROM.NLEN-1;i--)
+		{
+			nw=(this.w[i]>>m)|carry;
+			carry=(this.w[i]<<(ROM.BASEBITS-m))&ROM.BMASK;
+			t.w[i-ROM.NLEN+1]=nw;
+		}
+		this.w[ROM.NLEN-1]&=((1<<m)-1);
+
+		return t;
+	}
+
+};
+
+/* Compare a and b, return 0 if a==b, -1 if a<b, +1 if a>b. Inputs must be normalised */
+DBIG.comp=function(a,b)
+{
+	for (var i=ROM.DNLEN-1;i>=0;i--)
+	{
+		if (a.w[i]==b.w[i]) continue;
+		if (a.w[i]>b.w[i]) return 1;
+		else  return -1;
+	}
+	return 0;
+};
diff --git a/version22/js/ECDH.js b/version22/js/ECDH.js
new file mode 100644
index 0000000..326d90d
--- /dev/null
+++ b/version22/js/ECDH.js
@@ -0,0 +1,585 @@
+/*
+	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.
+*/
+
+var ECDH = {
+
+	INVALID_PUBLIC_KEY:-2,
+	ERROR:-3,
+	INVALID:-4,
+	EFS:ROM.MODBYTES,
+	EGS:ROM.MODBYTES,
+	EAS:16,
+	EBS:16,
+	SHA256:32,
+	SHA384:48,
+	SHA512:64,
+
+	HASH_TYPE:64,
+
+	/* Convert Integer to n-byte array */
+	inttobytes: function(n,len)
+	{
+		var i;
+		var b=[];
+
+		for (i=0;i<len;i++) b[i]=0;
+		i=len; 
+		while (n>0 && i>0)
+		{
+			i--;
+			b[i]=(n&0xff);
+			n=Math.floor(n/256);
+		}	
+		return b;
+	},
+
+	bytestostring: function(b)
+	{
+		var s="";
+		var len=b.length;
+		var ch;
+
+		for (var i=0;i<len;i++)
+		{
+			ch=b[i];
+			s+=((ch>>>4)&15).toString(16);
+			s+=(ch&15).toString(16);
+
+		}
+		return s;
+	},
+
+	stringtobytes: function(s)
+	{
+		var b=[];
+		for (var i=0;i<s.length;i++)
+			b.push(s.charCodeAt(i));
+		return b;
+	},
+
+	hashit: function(sha,A,n,B,pad)
+	{
+		var R=[];
+		if (sha==this.SHA256)
+		{
+			var H=new HASH256();
+			H.process_array(A); if (n>0) H.process_num(n);
+			if (B!=null) H.process_array(B);
+			R=H.hash();
+		}
+		if (sha==this.SHA384)
+		{
+			H=new HASH384();
+			H.process_array(A); if (n>0) H.process_num(n);
+			if (B!=null) H.process_array(B);
+			R=H.hash();
+		}
+		if (sha==this.SHA512)
+		{
+			H=new HASH512();
+			H.process_array(A); if (n>0) H.process_num(n);
+			if (B!=null) H.process_array(B);
+			R=H.hash();
+		}
+		if (R.length==0) return null;
+
+		if (pad==0) return R;
+		var W=[];
+		if (pad<=sha) 
+		{
+			for (var i=0;i<pad;i++) W[i]=R[i];
+		}
+		else
+		{
+			for (var i=0;i<sha;i++) W[i]=R[i];
+			for (var i=sha;i<pad;i++) W[i]=0;
+		}
+		return W;
+	},
+
+	KDF1: function(sha,Z,olen)
+	{
+/* NOTE: the parameter olen is the length of the output K in bytes */
+		var i,hlen=sha;
+		var K=[];
+
+		var B=[];
+		var counter,cthreshold,k=0;
+    
+		for (i=0;i<K.length;i++) K[i]=0;  // redundant?
+
+		cthreshold=Math.floor(olen/hlen); if (olen%hlen!==0) cthreshold++;
+
+		for (counter=0;counter<cthreshold;counter++)
+		{
+			B=this.hashit(sha,Z,counter,null,0);
+			if (k+hlen>olen) for (i=0;i<olen%hlen;i++) K[k++]=B[i];
+			else for (i=0;i<hlen;i++) K[k++]=B[i];
+		}
+		return K;
+	},
+
+	KDF2: function(sha,Z,P,olen)
+	{
+/* NOTE: the parameter olen is the length of the output k in bytes */
+		var i,hlen=sha;
+		var K=[];
+
+		var B=[];
+		var counter,cthreshold,k=0;
+    
+		for (i=0;i<K.length;i++) K[i]=0;  // redundant?
+
+		cthreshold=Math.floor(olen/hlen); if (olen%hlen!==0) cthreshold++;
+
+		for (counter=1;counter<=cthreshold;counter++)
+		{
+			B=this.hashit(sha,Z,counter,P,0);
+			if (k+hlen>olen) for (i=0;i<olen%hlen;i++) K[k++]=B[i];
+			else for (i=0;i<hlen;i++) K[k++]=B[i];
+		}
+		return K;
+	},
+
+/* Password based Key Derivation Function */
+/* Input password p, salt s, and repeat count */
+/* Output key of length olen */
+
+	PBKDF2: function(sha,Pass,Salt,rep,olen)
+	{
+		var i,j,k,d,opt;
+		d=Math.floor(olen/sha); if (olen%sha!==0) d++;
+		var F=new Array(sha);
+		var U=[];
+		var S=[];
+
+		var K=[];
+		opt=0;
+
+		for (i=1;i<=d;i++)
+		{
+			for (j=0;j<Salt.length;j++) S[j]=Salt[j];
+			var N=this.inttobytes(i,4);
+			for (j=0;j<4;j++) S[Salt.length+j]=N[j];
+			this.HMAC(sha,S,Pass,F);
+			for (j=0;j<sha;j++) U[j]=F[j];
+			for (j=2;j<=rep;j++)
+			{
+				this.HMAC(sha,U,Pass,U);
+				for (k=0;k<sha;k++) F[k]^=U[k];
+			}
+			for (j=0;j<sha;j++) K[opt++]=F[j];
+		}
+		var key=[];
+		for (i=0;i<olen;i++) key[i]=K[i];
+		return key;
+	},
+
+	HMAC: function(sha,M,K,tag)
+	{
+	/* Input is from an octet m        *
+	* olen is requested output length in bytes. k is the key  *
+	* The output is the calculated tag */
+		var i,b;
+		var B=[];
+		b=64;
+		if (sha>32) b=128;
+		var K0=new Array(b); 
+		var olen=tag.length;
+
+		//b=K0.length;
+		if (olen<4 ) return 0;
+
+		for (i=0;i<b;i++) K0[i]=0;
+
+		if (K.length > b) 
+		{
+			B=this.hashit(sha,K,0,null,0); 
+			for (i=0;i<sha;i++) K0[i]=B[i];
+		}
+		else
+			for (i=0;i<K.length;i++) K0[i]=K[i];
+		
+		for (i=0;i<b;i++) K0[i]^=0x36;
+		B=this.hashit(sha,K0,0,M,0);
+
+		for (i=0;i<b;i++) K0[i]^=0x6a;
+		B=this.hashit(sha,K0,0,B,olen);
+
+		for (i=0;i<olen;i++) tag[i]=B[i];
+
+		return 1;
+	},
+
+/* AES encryption/decryption */
+
+	AES_CBC_IV0_ENCRYPT: function(K,M)
+	{ /* AES CBC encryption, with Null IV and key K */
+	/* Input is from an octet string M, output is to an octet string C */
+	/* Input is padded as necessary to make up a full final block */
+		var a=new AES();
+		var fin;
+		var i,j,ipt,opt;
+		var buff=[];
+		/*var clen=16+(Math.floor(M.length/16))*16;*/
+
+		var C=[];
+		var padlen;
+
+		a.init(ROM.CBC,K.length,K,null);
+
+		ipt=opt=0;
+		fin=false;
+		for(;;)
+		{
+			for (i=0;i<16;i++)
+			{
+				if (ipt<M.length) buff[i]=M[ipt++];
+				else {fin=true; break;}
+			}
+			if (fin) break;
+			a.encrypt(buff);
+			for (i=0;i<16;i++)
+				C[opt++]=buff[i];
+		}    
+
+/* last block, filled up to i-th index */
+
+		padlen=16-i;
+		for (j=i;j<16;j++) buff[j]=padlen;
+		a.encrypt(buff);
+		for (i=0;i<16;i++)
+			C[opt++]=buff[i];
+		a.end();    
+		return C;
+	},
+
+	AES_CBC_IV0_DECRYPT: function(K,C)
+	{ /* padding is removed */
+		var a=new AES();
+		var i,ipt,opt,ch;
+		var buff=[];
+		var MM=[];
+		var fin,bad;
+		var padlen;
+		ipt=opt=0;
+
+		a.init(ROM.CBC,K.length,K,null);
+
+		if (C.length===0) return [];
+		ch=C[ipt++]; 
+  
+		fin=false;
+
+		for(;;)
+		{
+			for (i=0;i<16;i++)
+			{
+				buff[i]=ch;      
+				if (ipt>=C.length) {fin=true; break;}  
+				else ch=C[ipt++];  
+			}
+			a.decrypt(buff);
+			if (fin) break;
+			for (i=0;i<16;i++)
+				MM[opt++]=buff[i];
+		}    
+
+		a.end();
+		bad=false;
+		padlen=buff[15];
+		if (i!=15 || padlen<1 || padlen>16) bad=true;
+		if (padlen>=2 && padlen<=16)
+			for (i=16-padlen;i<16;i++) if (buff[i]!=padlen) bad=true;
+    
+		if (!bad) for (i=0;i<16-padlen;i++)
+					MM[opt++]=buff[i];
+
+		var M=[];
+		if (bad) return M;
+
+		for (i=0;i<opt;i++) M[i]=MM[i];
+		return M;
+	},
+
+	KEY_PAIR_GENERATE: function(RNG,S,W)
+	{
+		var r,gx,gy,s;
+		var G,WP;
+		var res=0;
+//		var T=[];
+		G=new ECP(0);
+
+		gx=new BIG(0); gx.rcopy(ROM.CURVE_Gx);
+
+		if (ROM.CURVETYPE!=ROM.MONTGOMERY)
+		{
+			gy=new BIG(0); gy.rcopy(ROM.CURVE_Gy);
+			G.setxy(gx,gy);
+		}
+		else G.setx(gx);
+
+		r=new BIG(0); r.rcopy(ROM.CURVE_Order);
+
+		if (RNG===null)
+		{
+			s=BIG.fromBytes(S);
+			s.mod(r);
+		}
+		else
+		{
+			s=BIG.randomnum(r,RNG);
+			
+	//		s.toBytes(T);
+	//		for (var i=0;i<this.EGS;i++) S[i]=T[i];
+		}
+		if (ROM.AES_S>0)
+		{
+			s.mod2m(2*ROM.AES_S);
+		}
+		s.toBytes(S);
+
+		WP=G.mul(s);
+		WP.toBytes(W);
+
+		return res;
+	},
+
+	PUBLIC_KEY_VALIDATE: function(full,W)
+	{
+		var r;
+		var WP=ECP.fromBytes(W);
+		var res=0;
+
+		r=new BIG(0); r.rcopy(ROM.CURVE_Order);
+
+		if (WP.is_infinity()) res=this.INVALID_PUBLIC_KEY;
+
+		if (res===0 && full)
+		{
+			WP=WP.mul(r);
+			if (!WP.is_infinity()) res=this.INVALID_PUBLIC_KEY; 
+		}
+		return res;
+	},
+
+	ECPSVDP_DH: function(S,WD,Z)    
+	{
+		var r,s;
+		var W;
+		var res=0;
+		var T=[];
+
+		s=BIG.fromBytes(S);
+
+		W=ECP.fromBytes(WD);
+		if (W.is_infinity()) res=this.ERROR;
+
+		if (res===0)
+		{
+			r=new BIG(0); r.rcopy(ROM.CURVE_Order);
+			s.mod(r);
+			W=W.mul(s);
+			if (W.is_infinity()) res=this.ERROR; 
+			else 
+			{
+				W.getX().toBytes(T);
+				for (var i=0;i<this.EFS;i++) Z[i]=T[i];
+			}
+		}
+		return res;
+	},
+
+	ECPSP_DSA: function(sha,RNG,S,F,C,D)
+	{
+		var T=[];
+		var i,gx,gy,r,s,f,c,d,u,vx,w;
+		var G,V;
+
+		var B=this.hashit(sha,F,0,null,ROM.MODBYTES);
+
+		gx=new BIG(0); gx.rcopy(ROM.CURVE_Gx);
+		gy=new BIG(0); gy.rcopy(ROM.CURVE_Gy);
+
+		G=new ECP(0);
+		G.setxy(gx,gy);
+		r=new BIG(0); r.rcopy(ROM.CURVE_Order);
+
+		s=BIG.fromBytes(S);
+		f=BIG.fromBytes(B);
+
+		c=new BIG(0);
+		d=new BIG(0);
+		V=new ECP();
+
+		do {
+			u=BIG.randomnum(r,RNG);
+			w=BIG.randomnum(r,RNG);
+			if (ROM.AES_S>0)
+			{
+				u.mod2m(2*ROM.AES_S);
+			}				
+			V.copy(G);
+			V=V.mul(u);   		
+			vx=V.getX();
+			c.copy(vx);
+			c.mod(r);
+			if (c.iszilch()) continue;
+			u=BIG.modmul(u,w,r);
+			u.invmodp(r);
+			d=BIG.modmul(s,c,r);
+			d.add(f);
+			d=BIG.modmul(d,w,r);
+			d=BIG.modmul(u,d,r);
+		} while (d.iszilch());
+       
+		c.toBytes(T);
+		for (i=0;i<this.EFS;i++) C[i]=T[i];
+		d.toBytes(T);
+		for (i=0;i<this.EFS;i++) D[i]=T[i];
+		return 0;
+	},
+
+	ECPVP_DSA: function(sha,W,F,C,D)
+	{
+		var B=[];
+		var r,gx,gy,f,c,d,h2;
+		var res=0;
+		var G,WP,P;
+
+		B=this.hashit(sha,F,0,null,ROM.MODBYTES);
+
+		gx=new BIG(0); gx.rcopy(ROM.CURVE_Gx);
+		gy=new BIG(0); gy.rcopy(ROM.CURVE_Gy);
+
+		G=new ECP(0);
+		G.setxy(gx,gy);
+		r=new BIG(0); r.rcopy(ROM.CURVE_Order);
+
+		c=BIG.fromBytes(C);
+		d=BIG.fromBytes(D);
+		f=BIG.fromBytes(B);
+     
+		if (c.iszilch() || BIG.comp(c,r)>=0 || d.iszilch() || BIG.comp(d,r)>=0) 
+            res=this.INVALID;
+
+		if (res===0)
+		{
+			d.invmodp(r);
+			f=BIG.modmul(f,d,r);
+			h2=BIG.modmul(c,d,r);
+
+			WP=ECP.fromBytes(W);
+			if (WP.is_infinity()) res=this.ERROR;
+			else
+			{
+				P=new ECP();
+				P.copy(WP);
+				P=P.mul2(h2,G,f);
+				if (P.is_infinity()) res=this.INVALID;
+				else
+				{
+					d=P.getX();
+					d.mod(r);
+					if (BIG.comp(d,c)!==0) res=this.INVALID;
+				}
+			}
+		}
+
+		return res;
+	},
+
+	ECIES_ENCRYPT: function(sha,P1,P2,RNG,W,M,V,T)
+	{ 
+		var i;
+
+		var Z=[];
+		var VZ=[];
+		var K1=[];
+		var K2=[];
+		var U=[];
+		var C=[];
+
+		if (this.KEY_PAIR_GENERATE(RNG,U,V)!==0) return C;  
+		if (this.ECPSVDP_DH(U,W,Z)!==0) return C;     
+
+		for (i=0;i<2*this.EFS+1;i++) VZ[i]=V[i];
+		for (i=0;i<this.EFS;i++) VZ[2*this.EFS+1+i]=Z[i];
+
+
+		var K=this.KDF2(sha,VZ,P1,EFS);
+
+		for (i=0;i<this.EAS;i++) {K1[i]=K[i]; K2[i]=K[this.EAS+i];} 
+
+		C=this.AES_CBC_IV0_ENCRYPT(K1,M);
+
+		var L2=this.inttobytes(P2.length,8);	
+	
+		var AC=[];
+		for (i=0;i<C.length;i++) AC[i]=C[i];
+		for (i=0;i<P2.length;i++) AC[C.length+i]=P2[i];
+		for (i=0;i<8;i++) AC[C.length+P2.length+i]=L2[i];
+	
+		this.HMAC(sha,AC,K2,T);
+
+		return C;
+	},
+
+	ECIES_DECRYPT: function(sha,P1,P2,V,C,T,U)
+	{ 
+
+		var i;
+
+		var Z=[];
+		var VZ=[];
+		var K1=[];
+		var K2=[];
+		var TAG=new Array(T.length);
+		var M=[];
+
+		if (this.ECPSVDP_DH(U,V,Z)!==0) return M;  
+
+		for (i=0;i<2*this.EFS+1;i++) VZ[i]=V[i];
+		for (i=0;i<this.EFS;i++) VZ[2*this.EFS+1+i]=Z[i];
+
+		var K=this.KDF2(sha,VZ,P1,this.EFS);
+
+		for (i=0;i<this.EAS;i++) {K1[i]=K[i]; K2[i]=K[this.EAS+i];} 
+
+		M=this.AES_CBC_IV0_DECRYPT(K1,C); 
+
+		if (M.length===0) return M;
+
+		var L2=this.inttobytes(P2.length,8);	
+	
+		var AC=[];
+
+		for (i=0;i<C.length;i++) AC[i]=C[i];
+		for (i=0;i<P2.length;i++) AC[C.length+i]=P2[i];
+		for (i=0;i<8;i++) AC[C.length+P2.length+i]=L2[i];
+	
+		this.HMAC(sha,AC,K2,TAG);
+
+		var same=true;
+		for (i=0;i<T.length;i++) if (T[i]!=TAG[i]) same=false;
+		if (!same) return [];
+	
+		return M;
+	}
+};
diff --git a/version22/js/ECP.js b/version22/js/ECP.js
new file mode 100644
index 0000000..ade058b
--- /dev/null
+++ b/version22/js/ECP.js
@@ -0,0 +1,903 @@
+/*
+	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.
+*/
+
+/* Elliptic Curve Point class */
+
+/* Constructor */
+var ECP = function() 
+{
+	this.x=new FP(0);
+	this.y=new FP(1);
+	this.z=new FP(1);
+	this.INF=true;
+};
+
+ECP.prototype={
+/* test this=O point-at-infinity */
+	is_infinity: function() 
+	{
+		if (ROM.CURVETYPE==ROM.EDWARDS)
+		{
+			this.x.reduce(); this.y.reduce(); this.z.reduce();
+			return (this.x.iszilch() && this.y.equals(this.z));
+		}
+		else return this.INF;
+	},
+
+
+/* conditional swap of this and Q dependant on d */
+	cswap: function(Q,d)
+	{
+		this.x.cswap(Q.x,d);
+		if (ROM.CURVETYPE!=ROM.MONTGOMERY) this.y.cswap(Q.y,d);
+		this.z.cswap(Q.z,d);
+		if (ROM.CURVETYPE!=ROM.EDWARDS)
+		{
+			var bd=(d!==0)?true:false;
+			bd=bd&(this.INF^Q.INF);
+			this.INF^=bd;
+			Q.INF^=bd;
+		}
+	},
+
+/* conditional move of Q to P dependant on d */
+	cmove: function(Q,d)
+	{
+		this.x.cmove(Q.x,d);
+		if (ROM.CURVETYPE!=ROM.MONTGOMERY) this.y.cmove(Q.y,d);
+		this.z.cmove(Q.z,d);
+		if (ROM.CURVETYPE!=ROM.EDWARDS)
+		{
+			var bd=(d!==0)?true:false;
+			this.INF^=(this.INF^Q.INF)&bd;
+		}
+	},
+
+/* Constant time select from pre-computed table */
+	select: function(W,b)
+	{
+		var MP=new ECP(); 
+		var m=b>>31;
+		var babs=(b^m)-m;
+
+		babs=(babs-1)/2;
+
+		this.cmove(W[0],ECP.teq(babs,0));  // conditional move
+		this.cmove(W[1],ECP.teq(babs,1));
+		this.cmove(W[2],ECP.teq(babs,2));
+		this.cmove(W[3],ECP.teq(babs,3));
+		this.cmove(W[4],ECP.teq(babs,4));
+		this.cmove(W[5],ECP.teq(babs,5));
+		this.cmove(W[6],ECP.teq(babs,6));
+		this.cmove(W[7],ECP.teq(babs,7));
+ 
+		MP.copy(this);
+		MP.neg();
+		this.cmove(MP,(m&1));
+	},
+
+/* Test P == Q */
+
+	equals: function(Q) 
+	{
+		if (this.is_infinity() && Q.is_infinity()) return true;
+		if (this.is_infinity() || Q.is_infinity()) return false;
+		if (ROM.CURVETYPE==ROM.WEIERSTRASS)
+		{
+			var zs2=new FP(0); zs2.copy(this.z); zs2.sqr();
+			var zo2=new FP(0); zo2.copy(Q.z); zo2.sqr();
+			var zs3=new FP(0); zs3.copy(zs2); zs3.mul(this.z);
+			var zo3=new FP(0); zo3.copy(zo2); zo3.mul(Q.z);
+			zs2.mul(Q.x);
+			zo2.mul(this.x);
+			if (!zs2.equals(zo2)) return false;
+			zs3.mul(Q.y);
+			zo3.mul(this.y);
+			if (!zs3.equals(zo3)) return false;
+		}
+		else
+		{
+			var a=new FP(0);
+			var b=new FP(0);
+			a.copy(this.x); a.mul(Q.z); a.reduce();
+			b.copy(Q.x); b.mul(this.z); b.reduce();
+			if (!a.equals(b)) return false;
+			if (ROM.CURVETYPE==ROM.EDWARDS)
+			{
+				a.copy(this.y); a.mul(Q.z); a.reduce();
+				b.copy(Q.y); b.mul(this.z); b.reduce();
+				if (!a.equals(b)) return false;
+			}
+		}
+		return true;
+	},
+/* copy this=P */
+	copy: function(P)
+	{
+		this.x.copy(P.x);
+		if (ROM.CURVETYPE!=ROM.MONTGOMERY) this.y.copy(P.y);
+		this.z.copy(P.z);
+		this.INF=P.INF;
+	},
+/* this=-this */
+	neg: function() 
+	{
+		if (this.is_infinity()) return;
+		if (ROM.CURVETYPE==ROM.WEIERSTRASS)
+		{
+			this.y.neg(); this.y.norm();
+		}
+		if (ROM.CURVETYPE==ROM.EDWARDS)
+		{
+			this.x.neg(); this.x.norm();
+		}
+		return;
+	},
+/* set this=O */
+	inf: function() 
+	{
+		this.INF=true;
+		this.x.zero();
+		this.y=new FP(1);
+		this.z=new FP(1);
+	},
+/* set this=(x,y) where x and y are BIGs */
+	setxy: function(ix,iy) 
+	{
+
+		this.x=new FP(0); this.x.bcopy(ix);
+		var bx=this.x.redc();
+
+		this.y=new FP(0); this.y.bcopy(iy);
+		this.z=new FP(1);
+		var rhs=ECP.RHS(this.x);
+
+		if (ROM.CURVETYPE==ROM.MONTGOMERY)
+		{
+			if (rhs.jacobi()==1) this.INF=false;
+			else this.inf();
+		}
+		else
+		{
+			var y2=new FP(0); y2.copy(this.y);
+			y2.sqr();
+			if (y2.equals(rhs)) this.INF=false;
+			else this.inf();
+
+		}
+	},
+/* set this=x, where x is BIG, y is derived from sign s */
+	setxi: function(ix,s) 
+	{
+		this.x=new FP(0); this.x.bcopy(ix);
+		var rhs=ECP.RHS(this.x);
+		this.z=new FP(1);
+		if (rhs.jacobi()==1)
+		{
+			var ny=rhs.sqrt();
+			if (ny.redc().parity()!=s) ny.neg();
+			this.y=ny;
+			this.INF=false;
+		}
+		else this.inf();
+	},
+/* set this=x, y calcuated from curve equation */
+	setx: function(ix) 
+	{
+		this.x=new FP(0); this.x.bcopy(ix);
+		var rhs=ECP.RHS(this.x);
+		this.z=new FP(1);
+		if (rhs.jacobi()==1)
+		{
+			if (ROM.CURVETYPE!=ROM.MONTGOMERY) this.y=rhs.sqrt();
+			this.INF=false;
+		}
+		else this.INF=true;
+	},
+/* set this to affine - from (x,y,z) to (x,y) */
+	affine: function() 
+	{
+		if (this.is_infinity()) return;
+		var one=new FP(1);
+		if (this.z.equals(one)) return;
+		this.z.inverse();
+		if (ROM.CURVETYPE==ROM.WEIERSTRASS)
+		{
+			var z2=new FP(0); z2.copy(this.z);
+			z2.sqr();
+			this.x.mul(z2); this.x.reduce();
+			this.y.mul(z2); 
+			this.y.mul(this.z); this.y.reduce();
+			this.z=one;
+		}
+		if (ROM.CURVETYPE==ROM.EDWARDS)
+		{
+			this.x.mul(this.z); this.x.reduce();
+			this.y.mul(this.z); this.y.reduce();
+			this.z=one;
+		}
+		if (ROM.CURVETYPE==ROM.MONTGOMERY)
+		{
+			this.x.mul(this.z); this.x.reduce();
+			this.z=one;
+		}
+	},
+/* extract x as BIG */
+	getX: function()
+	{
+		this.affine();
+		return this.x.redc();
+	},
+/* extract y as BIG */
+	getY: function()
+	{
+		this.affine();
+		return this.y.redc();
+	},
+
+/* get sign of Y */
+	getS: function()
+	{
+		this.affine();
+		var y=this.getY();
+		return y.parity();
+	},
+/* extract x as FP */
+	getx: function()
+	{
+		return this.x;
+	},
+/* extract y as FP */
+	gety: function()
+	{
+		return this.y;
+	},
+/* extract z as FP */
+	getz: function()
+	{
+		return this.z;
+	},
+/* convert to byte array */
+	toBytes: function(b)
+	{
+		var i,t=[];
+		if (ROM.CURVETYPE!=ROM.MONTGOMERY) b[0]=0x04;
+		else b[0]=0x02;
+	
+		this.affine();
+		this.x.redc().toBytes(t);
+		for (i=0;i<ROM.MODBYTES;i++) b[i+1]=t[i];
+		if (ROM.CURVETYPE!=ROM.MONTGOMERY)
+		{
+			this.y.redc().toBytes(t);
+			for (i=0;i<ROM.MODBYTES;i++) b[i+ROM.MODBYTES+1]=t[i];
+		}
+	},
+/* convert to hex string */
+	toString: function() 
+	{
+		if (this.is_infinity()) return "infinity";
+		this.affine();
+		if (ROM.CURVETYPE==ROM.MONTGOMERY) return "("+this.x.redc().toString()+")";
+		else return "("+this.x.redc().toString()+","+this.y.redc().toString()+")";
+	},
+
+/* this+=this */
+	dbl: function() 
+	{
+		if (ROM.CURVETYPE==ROM.WEIERSTRASS)
+		{
+			if (this.INF) return;
+			if (this.y.iszilch())
+			{
+				this.inf();
+				return;
+			}
+
+			var w1=new FP(0); w1.copy(this.x);
+			var w6=new FP(0); w6.copy(this.z);
+			var w2=new FP(0);
+			var w3=new FP(0); w3.copy(this.x);
+			var w8=new FP(0); w8.copy(this.x);
+
+			if (ROM.CURVE_A==-3)
+			{
+				w6.sqr();
+				w1.copy(w6);
+				w1.neg();
+				w3.add(w1);
+				w8.add(w6);
+				w3.mul(w8);
+				w8.copy(w3);
+				w8.imul(3);
+			}
+			else
+			{
+				w1.sqr();
+				w8.copy(w1);
+				w8.imul(3);
+			}
+
+			w2.copy(this.y); w2.sqr();
+			w3.copy(this.x); w3.mul(w2);
+			w3.imul(4);
+			w1.copy(w3); w1.neg();
+
+			this.x.copy(w8); this.x.sqr();
+			this.x.add(w1);
+			this.x.add(w1);
+			this.x.norm();
+
+			this.z.mul(this.y);
+			this.z.add(this.z);
+
+			w2.add(w2);
+			w2.sqr();
+			w2.add(w2);
+			w3.sub(this.x);
+			this.y.copy(w8); this.y.mul(w3);
+			this.y.sub(w2);
+			this.y.norm();
+			this.z.norm();
+		}
+		if (ROM.CURVETYPE==ROM.EDWARDS)
+		{
+			var C=new FP(0); C.copy(this.x);
+			var D=new FP(0); D.copy(this.y);
+			var H=new FP(0); H.copy(this.z);
+			var J=new FP(0);
+
+			this.x.mul(this.y); this.x.add(this.x);
+			C.sqr();
+			D.sqr();
+			if (ROM.CURVE_A==-1) C.neg();	
+			this.y.copy(C); this.y.add(D);
+			H.sqr(); H.add(H);
+			this.z.copy(this.y);
+			J.copy(this.y); J.sub(H);
+			this.x.mul(J);
+			C.sub(D);
+			this.y.mul(C);
+			this.z.mul(J);
+
+			this.x.norm();
+			this.y.norm();
+			this.z.norm();
+		}
+		if (ROM.CURVETYPE==ROM.MONTGOMERY)
+		{
+			var A=new FP(0); A.copy(this.x);
+			var B=new FP(0); B.copy(this.x);		
+			var AA=new FP(0);
+			var BB=new FP(0);
+			var C=new FP(0);
+	
+			if (this.INF) return;
+
+			A.add(this.z);
+			AA.copy(A); AA.sqr();
+			B.sub(this.z);
+			BB.copy(B); BB.sqr();
+			C.copy(AA); C.sub(BB);
+
+			this.x.copy(AA); this.x.mul(BB);
+
+			A.copy(C); A.imul((ROM.CURVE_A+2)>>2);
+
+			BB.add(A);
+			this.z.copy(BB); this.z.mul(C);
+			this.x.norm();
+			this.z.norm();
+		}
+		return;
+	},
+
+/* this+=Q */
+	add: function(Q) 
+	{
+		if (ROM.CURVETYPE==ROM.WEIERSTRASS)
+		{
+			if (this.INF)
+			{
+				this.copy(Q);
+				return;
+			}
+			if (Q.INF) return;
+
+			var aff=false;
+			var one=new FP(1);
+			if (Q.z.equals(one)) aff=true;
+
+			var A,C;
+			var B=new FP(this.z);
+			var D=new FP(this.z);
+			if (!aff)
+			{
+				A=new FP(Q.z);
+				C=new FP(Q.z);
+
+				A.sqr(); B.sqr();
+				C.mul(A); D.mul(B);
+
+				A.mul(this.x);
+				C.mul(this.y);
+			}
+			else
+			{
+				A=new FP(this.x);
+				C=new FP(this.y);
+	
+				B.sqr();
+				D.mul(B);
+			}
+
+			B.mul(Q.x); B.sub(A);
+			D.mul(Q.y); D.sub(C);
+			
+			if (B.iszilch())
+			{
+				if (D.iszilch())
+				{
+					this.dbl();
+					return;
+				}
+				else
+				{
+					this.INF=true;
+					return;
+				}
+			}
+
+			if (!aff) this.z.mul(Q.z);
+			this.z.mul(B);
+
+			var e=new FP(B); e.sqr();
+			B.mul(e);
+			A.mul(e);
+
+			e.copy(A);
+			e.add(A); e.add(B);
+			this.x.copy(D); this.x.sqr(); this.x.sub(e);
+
+			A.sub(this.x);
+			this.y.copy(A); this.y.mul(D); 
+			C.mul(B); this.y.sub(C);
+
+			this.x.norm();
+			this.y.norm();
+			this.z.norm();
+
+		}
+		if (ROM.CURVETYPE==ROM.EDWARDS)
+		{
+			var b=new FP(0); b.rcopy(ROM.CURVE_B);
+			var A=new FP(0); A.copy(this.z);
+			var B=new FP(0);
+			var C=new FP(0); C.copy(this.x);
+			var D=new FP(0); D.copy(this.y);
+			var E=new FP(0);
+			var F=new FP(0);
+			var G=new FP(0);
+
+			A.mul(Q.z);
+			B.copy(A); B.sqr();
+			C.mul(Q.x);
+			D.mul(Q.y);
+
+			E.copy(C); E.mul(D); E.mul(b);
+			F.copy(B); F.sub(E); 
+			G.copy(B); G.add(E); 
+
+			if (ROM.CURVE_A==1)
+			{
+				E.copy(D); E.sub(C);
+			}
+			C.add(D);
+
+			B.copy(this.x); B.add(this.y);
+			D.copy(Q.x); D.add(Q.y); 
+			B.mul(D);
+			B.sub(C);
+			B.mul(F);
+			this.x.copy(A); this.x.mul(B);
+
+			if (ROM.CURVE_A==1)
+			{
+				C.copy(E); C.mul(G);
+			}
+			if (ROM.CURVE_A==-1)
+			{
+				C.mul(G);
+			}
+			this.y.copy(A); this.y.mul(C);
+			this.z.copy(F); this.z.mul(G);
+			this.x.norm(); this.y.norm(); this.z.norm();
+		}
+		return;
+	},
+
+/* Differential Add for Montgomery curves. this+=Q where W is this-Q and is affine. */
+	dadd: function(Q,W) 
+	{
+		var A=new FP(0); A.copy(this.x);
+		var B=new FP(0); B.copy(this.x);
+		var C=new FP(0); C.copy(Q.x);
+		var D=new FP(0); D.copy(Q.x);
+		var DA=new FP(0);
+		var CB=new FP(0);	
+			
+		A.add(this.z); 
+		B.sub(this.z); 
+
+		C.add(Q.z);
+		D.sub(Q.z);
+
+		DA.copy(D); DA.mul(A);
+		CB.copy(C); CB.mul(B);
+
+		A.copy(DA); A.add(CB); A.sqr();
+		B.copy(DA); B.sub(CB); B.sqr();
+
+		this.x.copy(A);
+		this.z.copy(W.x); this.z.mul(B);
+
+		if (this.z.iszilch()) this.inf();
+		else this.INF=false;
+
+		this.x.norm();
+	},
+
+/* this-=Q */
+	sub: function(Q) {
+		Q.neg();
+		this.add(Q);
+		Q.neg();
+	},
+
+/* constant time multiply by small integer of length bts - use ladder */
+	pinmul: function(e,bts) {	
+		if (ROM.CURVETYPE==ROM.MONTGOMERY)
+			return this.mul(new BIG(e));
+		else
+		{
+			var nb,i,b;
+			var P=new ECP();
+			var R0=new ECP();
+			var R1=new ECP(); R1.copy(this);
+		
+			for (i=bts-1;i>=0;i--)
+			{
+				b=(e>>i)&1;
+				P.copy(R1);
+				P.add(R0);
+				R0.cswap(R1,b);
+				R1.copy(P);
+				R0.dbl();
+				R0.cswap(R1,b);
+			}
+			P.copy(R0);
+			P.affine();
+			return P;
+		}
+	},
+
+/* return e.this - SPA immune, using Ladder */
+
+	mul: function(e) 
+	{
+		if (e.iszilch() || this.is_infinity()) return new ECP();
+		var P=new ECP();
+		if (ROM.CURVETYPE==ROM.MONTGOMERY)
+		{ /* use ladder */
+			var nb,i,b;
+			var D=new ECP();
+			var R0=new ECP(); R0.copy(this);
+			var R1=new ECP(); R1.copy(this);
+			R1.dbl();
+			D.copy(this); D.affine();
+			nb=e.nbits();
+			for (i=nb-2;i>=0;i--)
+			{
+				b=e.bit(i);
+				P.copy(R1);
+				P.dadd(R0,D);
+
+				R0.cswap(R1,b);
+				R1.copy(P);
+				R0.dbl();
+				R0.cswap(R1,b);
+			}
+			P.copy(R0);
+		}
+		else
+		{
+// fixed size windows 
+			var i,b,nb,m,s,ns;
+			var mt=new BIG();
+			var t=new BIG();
+			var Q=new ECP();
+			var C=new ECP();
+			var W=[];
+			var w=[];
+
+			this.affine();
+
+// precompute table 
+			Q.copy(this);
+			Q.dbl();
+			W[0]=new ECP();
+			W[0].copy(this);
+
+			for (i=1;i<8;i++)
+			{
+				W[i]=new ECP();
+				W[i].copy(W[i-1]);
+				W[i].add(Q);
+			}
+
+// convert the table to affine 
+			if (ROM.CURVETYPE==ROM.WEIERSTRASS) 
+				ECP.multiaffine(8,W);
+
+// make exponent odd - add 2P if even, P if odd 
+			t.copy(e);
+			s=t.parity();
+			t.inc(1); t.norm(); ns=t.parity(); mt.copy(t); mt.inc(1); mt.norm();
+			t.cmove(mt,s);
+			Q.cmove(this,ns);
+			C.copy(Q);
+
+			nb=1+Math.floor((t.nbits()+3)/4);
+
+// convert exponent to signed 4-bit window 
+			for (i=0;i<nb;i++)
+			{
+				w[i]=(t.lastbits(5)-16);
+				t.dec(w[i]); t.norm();
+				t.fshr(4);	
+			}
+			w[nb]=t.lastbits(5);
+	
+			P.copy(W[Math.floor((w[nb]-1)/2)]);  
+			for (i=nb-1;i>=0;i--)
+			{
+				Q.select(W,w[i]);
+				P.dbl();
+				P.dbl();
+				P.dbl();
+				P.dbl();
+				P.add(Q);
+			}
+			P.sub(C);
+		}
+		P.affine();
+		return P;
+	},
+
+/* Return e.this+f.Q */
+
+	mul2: function(e,Q,f) {
+		var te=new BIG();
+		var tf=new BIG();
+		var mt=new BIG();
+		var S=new ECP();
+		var T=new ECP();
+		var C=new ECP();
+		var W=[];
+		var w=[];		
+		var i,s,ns,nb;
+		var a,b;
+
+		this.affine();
+		Q.affine();
+
+		te.copy(e);
+		tf.copy(f);
+
+// precompute table 
+		W[1]=new ECP(); W[1].copy(this); W[1].sub(Q);
+		W[2]=new ECP(); W[2].copy(this); W[2].add(Q);
+		S.copy(Q); S.dbl();
+		W[0]=new ECP(); W[0].copy(W[1]); W[0].sub(S);
+		W[3]=new ECP(); W[3].copy(W[2]); W[3].add(S);
+		T.copy(this); T.dbl();
+		W[5]=new ECP(); W[5].copy(W[1]); W[5].add(T);
+		W[6]=new ECP(); W[6].copy(W[2]); W[6].add(T);
+		W[4]=new ECP(); W[4].copy(W[5]); W[4].sub(S);
+		W[7]=new ECP(); W[7].copy(W[6]); W[7].add(S);
+
+// convert the table to affine 
+		if (ROM.CURVETYPE==ROM.WEIERSTRASS) 
+			ECP.multiaffine(8,W);
+
+// if multiplier is odd, add 2, else add 1 to multiplier, and add 2P or P to correction 
+
+		s=te.parity();
+		te.inc(1); te.norm(); ns=te.parity(); mt.copy(te); mt.inc(1); mt.norm();
+		te.cmove(mt,s);
+		T.cmove(this,ns);
+		C.copy(T);
+
+		s=tf.parity();
+		tf.inc(1); tf.norm(); ns=tf.parity(); mt.copy(tf); mt.inc(1); mt.norm();
+		tf.cmove(mt,s);
+		S.cmove(Q,ns);
+		C.add(S);
+
+		mt.copy(te); mt.add(tf); mt.norm();
+		nb=1+Math.floor((mt.nbits()+1)/2);
+
+// convert exponent to signed 2-bit window 
+		for (i=0;i<nb;i++)
+		{
+			a=(te.lastbits(3)-4);
+			te.dec(a); te.norm(); 
+			te.fshr(2);
+			b=(tf.lastbits(3)-4);
+			tf.dec(b); tf.norm(); 
+			tf.fshr(2);
+			w[i]=(4*a+b);
+		}
+		w[nb]=(4*te.lastbits(3)+tf.lastbits(3));
+		S.copy(W[Math.floor((w[nb]-1)/2)]);  
+
+		for (i=nb-1;i>=0;i--)
+		{
+			T.select(W,w[i]);
+			S.dbl();
+			S.dbl();
+			S.add(T);
+		}
+		S.sub(C); /* apply correction */
+		S.affine();
+		return S;
+	}
+
+};
+
+ECP.multiaffine=function(m,P)
+{
+	var i;
+	var t1=new FP(0);
+	var t2=new FP(0);
+	var work=[];
+
+	for (i=0;i<m;i++)
+		work[i]=new FP(0);
+	
+	work[0].one();
+	work[1].copy(P[0].z);
+
+	for (i=2;i<m;i++)
+	{
+		work[i].copy(work[i-1]);
+		work[i].mul(P[i-1].z);
+	}
+
+	t1.copy(work[m-1]);
+	t1.mul(P[m-1].z);
+	t1.inverse();
+	t2.copy(P[m-1].z);
+	work[m-1].mul(t1);
+
+	for (i=m-2;;i--)
+	{
+		if (i==0)
+		{
+			work[0].copy(t1);
+			work[0].mul(t2);
+			break;
+		}
+		work[i].mul(t2);
+		work[i].mul(t1);
+		t2.mul(P[i].z);
+	}
+/* now work[] contains inverses of all Z coordinates */
+
+	for (i=0;i<m;i++)
+	{
+		P[i].z.one();
+		t1.copy(work[i]);
+		t1.sqr();
+		P[i].x.mul(t1);
+		t1.mul(work[i]);
+		P[i].y.mul(t1);
+	}    
+};
+
+/* return 1 if b==c, no branching */
+ECP.teq=function(b,c)
+{
+	var x=b^c;
+	x-=1;  // if x=0, x now -1
+	return ((x>>31)&1);
+};
+
+/* convert from byte array to ECP */
+ECP.fromBytes= function(b)
+{
+	var i,t=[];
+	var P=new ECP();
+	var p=new BIG(0); p.rcopy(ROM.Modulus);
+
+	for (i=0;i<ROM.MODBYTES;i++) t[i]=b[i+1];
+	var px=BIG.fromBytes(t);
+	if (BIG.comp(px,p)>=0) return P;
+
+	if (b[0]==0x04)
+	{
+		for (i=0;i<ROM.MODBYTES;i++) t[i]=b[i+ROM.MODBYTES+1];
+		var py=BIG.fromBytes(t);
+		if (BIG.comp(py,p)>=0) return P;
+		P.setxy(px,py);
+		return P;
+	}
+	else 
+	{
+		P.setx(px);
+		return P;
+	}
+};
+
+/* Calculate RHS of curve equation */
+ECP.RHS= function(x) 
+{
+	x.norm();
+	var r=new FP(0); r.copy(x);
+	r.sqr();
+
+	if (ROM.CURVETYPE==ROM.WEIERSTRASS)   
+	{ // x^3+Ax+B
+		var b=new FP(0); b.rcopy(ROM.CURVE_B);
+		r.mul(x);
+		if (ROM.CURVE_A==-3)
+		{
+			var cx=new FP(0); cx.copy(x);
+			cx.imul(3);
+			cx.neg(); cx.norm();
+			r.add(cx);
+		}
+		r.add(b);
+	}
+	if (ROM.CURVETYPE==ROM.EDWARDS)
+	{ // (Ax^2-1)/(Bx^2-1) 
+		var b=new FP(0); b.rcopy(ROM.CURVE_B);
+
+		var one=new FP(1);
+		b.mul(r);
+		b.sub(one);
+		if (ROM.CURVE_A==-1) r.neg();
+		r.sub(one);
+
+		b.inverse();
+
+		r.mul(b);
+	}
+	if (ROM.CURVETYPE==ROM.MONTGOMERY)
+	{ // x^3+Ax^2+x
+		var x3=new FP(0);
+		x3.copy(r);
+		x3.mul(x);
+		r.imul(ROM.CURVE_A);
+		r.add(x3);
+		r.add(x);
+	}
+	r.reduce();
+	return r;
+};
diff --git a/version22/js/ECP2.js b/version22/js/ECP2.js
new file mode 100644
index 0000000..6c75271
--- /dev/null
+++ b/version22/js/ECP2.js
@@ -0,0 +1,604 @@
+/*
+	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.
+*/
+
+/* AMCL Weierstrass elliptic curve functions over FP2 */
+
+/* Constructor, set this=O */
+var ECP2=function()
+{
+	this.x=new FP2(0);
+	this.y=new FP2(1);
+	this.z=new FP2(1);
+	this.INF=true;
+};
+
+ECP2.prototype={
+/* Test this=O? */
+	is_infinity: function() 
+	{
+		return this.INF;
+	},
+/* copy this=P */
+	copy: function(P)
+	{
+		this.x.copy(P.x);
+		this.y.copy(P.y);
+		this.z.copy(P.z);
+		this.INF=P.INF;
+	},
+/* set this=O */
+	inf: function() 
+	{
+		this.INF=true;
+		this.x.zero();
+		this.y.zero();
+		this.z.zero();
+	},
+
+/* conditional move of Q to P dependant on d */
+	cmove: function(Q,d)
+	{
+		this.x.cmove(Q.x,d);
+		this.y.cmove(Q.y,d);
+		this.z.cmove(Q.z,d);
+
+		var bd=(d!==0)?true:false;
+		this.INF^=(this.INF^Q.INF)&bd;
+	},
+
+/* Constant time select from pre-computed table */
+	select: function(W,b)
+	{
+		var MP=new ECP2(); 
+		var m=b>>31;
+		var babs=(b^m)-m;
+
+		babs=(babs-1)/2;
+
+		this.cmove(W[0],ECP2.teq(babs,0));  // conditional move
+		this.cmove(W[1],ECP2.teq(babs,1));
+		this.cmove(W[2],ECP2.teq(babs,2));
+		this.cmove(W[3],ECP2.teq(babs,3));
+		this.cmove(W[4],ECP2.teq(babs,4));
+		this.cmove(W[5],ECP2.teq(babs,5));
+		this.cmove(W[6],ECP2.teq(babs,6));
+		this.cmove(W[7],ECP2.teq(babs,7));
+
+		MP.copy(this);
+		MP.neg();
+		this.cmove(MP,(m&1));
+	},
+
+/* Test P == Q */
+
+	equals: function(Q) {
+		if (this.is_infinity() && Q.is_infinity()) return true;
+		if (this.is_infinity() || Q.is_infinity()) return false;
+
+		var zs2=new FP2(this.z); /*zs2.copy(this.z);*/ zs2.sqr();
+		var zo2=new FP2(Q.z); /*zo2.copy(Q.z);*/  zo2.sqr();
+		var zs3=new FP2(zs2); /*zs3.copy(zs2);*/ zs3.mul(this.z);
+		var zo3=new FP2(zo2); /*zo3.copy(zo2);*/  zo3.mul(Q.z);
+		zs2.mul(Q.x);
+		zo2.mul(this.x);
+		if (!zs2.equals(zo2)) return false;
+		zs3.mul(Q.y);
+		zo3.mul(this.y);
+		if (!zs3.equals(zo3)) return false;
+
+		return true;
+	},
+/* set this=-this */
+	neg: function() 
+	{
+		if (this.is_infinity()) return;
+		this.y.neg(); this.y.norm();
+		return;
+	},
+/* convert this to affine, from (x,y,z) to (x,y) */
+	affine: function() 
+	{
+		if (this.is_infinity()) return;
+		var one=new FP2(1);
+		if (this.z.equals(one)) return;
+		this.z.inverse();
+
+		var z2=new FP2(this.z); //z2.copy(this.z);
+		z2.sqr();
+		this.x.mul(z2); this.x.reduce();
+		this.y.mul(z2); 
+		this.y.mul(this.z);  this.y.reduce();
+		this.z=one;
+	},
+/* extract affine x as FP2 */
+	getX: function()
+	{
+		this.affine();
+		return this.x;
+	},
+/* extract affine y as FP2 */
+	getY: function()
+	{
+		this.affine();
+		return this.y;
+	},
+/* extract projective x */
+	getx: function()
+	{
+		return this.x;
+	},
+/* extract projective y */
+	gety: function()
+	{
+		return this.y;
+	},
+/* extract projective z */
+	getz: function()
+	{
+		return this.z;
+	},
+/* convert this to byte array */
+	toBytes: function(b)
+	{
+		var i,t=[];
+		this.affine();
+		this.x.getA().toBytes(t);
+		for (i=0;i<ROM.MODBYTES;i++)
+			b[i]=t[i];
+		this.x.getB().toBytes(t);
+		for (i=0;i<ROM.MODBYTES;i++)
+			b[i+ROM.MODBYTES]=t[i];
+
+		this.y.getA().toBytes(t);
+		for (i=0;i<ROM.MODBYTES;i++)
+			b[i+2*ROM.MODBYTES]=t[i];
+		this.y.getB().toBytes(t);
+		for (i=0;i<ROM.MODBYTES;i++)
+			b[i+3*ROM.MODBYTES]=t[i];
+	},
+/* convert this to hex string */
+	toString: function() 
+	{
+		if (this.is_infinity()) return "infinity";
+		this.affine();
+		return "("+this.x.toString()+","+this.y.toString()+")";
+	},
+/* set this=(x,y) */
+	setxy: function(ix,iy) 
+	{
+		this.x.copy(ix);
+		this.y.copy(iy);
+		this.z.one();
+
+		var rhs=ECP2.RHS(this.x);
+
+		var y2=new FP2(this.y); //y2.copy(this.y);
+		y2.sqr();
+		if (y2.equals(rhs)) this.INF=false;
+		else this.inf();
+	},
+
+/* set this=(x,.) */
+	setx: function(ix) 
+	{
+		this.x.copy(ix);
+		this.z.one();
+
+		var rhs=ECP2.RHS(this.x);
+
+		if (rhs.sqrt())
+		{
+			this.y.copy(rhs);
+			this.INF=false;
+		}
+		else this.inf();
+	},
+
+/* set this*=q, where q is Modulus, using Frobenius */
+	frob: function(X)
+	{
+		if (this.INF) return;
+		var X2=new FP2(X); //X2.copy(X);
+		X2.sqr();
+		this.x.conj();
+		this.y.conj();
+		this.z.conj();
+		this.z.reduce();
+		this.x.mul(X2);
+		this.y.mul(X2);
+		this.y.mul(X);
+	},
+/* this+=this */
+	dbl: function() 
+	{
+		if (this.INF) return -1;
+		if (this.y.iszilch())
+		{
+			this.inf();
+			return -1;
+		}
+
+		var w1=new FP2(this.x); //w1.copy(this.x);
+		var w2=new FP2(0); 
+		var w3=new FP2(this.x); //w3.copy(this.x);
+		var w8=new FP2(this.x); //w8.copy(this.x);
+
+		w1.sqr();
+		w8.copy(w1);
+		w8.imul(3);
+
+		w2.copy(this.y); w2.sqr();
+		w3.copy(this.x); w3.mul(w2);
+		w3.imul(4);
+		w1.copy(w3); w1.neg();
+
+
+		this.x.copy(w8); this.x.sqr();
+		this.x.add(w1);
+		this.x.add(w1);
+		this.x.norm();
+
+		this.z.mul(this.y);
+		this.z.add(this.z);
+
+		w2.add(w2);
+		w2.sqr();
+		w2.add(w2);
+		w3.sub(this.x);
+		this.y.copy(w8); this.y.mul(w3);
+		this.y.sub(w2);
+		this.y.norm();
+		this.z.norm();
+
+		return 1;
+	},
+/* this+=Q - return 0 for add, 1 for double, -1 for O */
+/* this+=Q */
+	add: function(Q) 
+	{
+		if (this.INF)
+		{
+			this.copy(Q);
+			return -1;
+		}
+		if (Q.INF) return -1;
+
+		var aff=false;
+
+		if (Q.z.isunity()) aff=true;
+
+		var A,C;
+		var B=new FP2(this.z);
+		var D=new FP2(this.z);
+		if (!aff)
+		{
+			A=new FP2(Q.z);
+			C=new FP2(Q.z);
+
+			A.sqr(); B.sqr();
+			C.mul(A); D.mul(B);
+
+			A.mul(this.x);
+			C.mul(this.y);
+		}
+		else
+		{
+			A=new FP2(this.x);
+			C=new FP2(this.y);
+	
+			B.sqr();
+			D.mul(B);
+		}
+
+		B.mul(Q.x); B.sub(A);
+		D.mul(Q.y); D.sub(C);
+			
+		if (B.iszilch())
+		{
+			if (D.iszilch())
+			{
+				this.dbl();
+				return 1;
+			}
+			else
+			{
+				this.INF=true;
+				return -1;
+			}
+		}
+
+		if (!aff) this.z.mul(Q.z);
+		this.z.mul(B);
+
+		var e=new FP2(B); e.sqr();
+		B.mul(e);
+		A.mul(e);
+
+		e.copy(A);
+		e.add(A); e.add(B);
+		this.x.copy(D); this.x.sqr(); this.x.sub(e);
+
+		A.sub(this.x);
+		this.y.copy(A); this.y.mul(D); 
+		C.mul(B); this.y.sub(C);
+
+		this.x.norm();
+		this.y.norm();
+		this.z.norm();
+		return 0;
+	},
+/* this-=Q */
+	sub: function(Q) 
+	{
+		Q.neg();
+		var D=this.add(Q);
+		Q.neg();
+		return D;
+	},
+
+/* P*=e */
+	mul: function(e)
+	{
+/* fixed size windows */
+		var i,b,nb,m,s,ns;
+		var mt=new BIG();
+		var t=new BIG();
+		var C=new ECP2();
+		var P=new ECP2();
+		var Q=new ECP2();
+		var W=[];
+		var w=[];
+
+		if (this.is_infinity()) return new ECP2();
+
+		this.affine();
+
+// precompute table 
+		Q.copy(this);
+		Q.dbl();
+		W[0]=new ECP2();
+		W[0].copy(this);
+
+		for (i=1;i<8;i++)
+		{
+			W[i]=new ECP2();
+			W[i].copy(W[i-1]);
+			W[i].add(Q);
+		}
+
+// convert the table to affine 
+
+		ECP2.multiaffine(8,W);
+
+// make exponent odd - add 2P if even, P if odd 
+		t.copy(e);
+		s=t.parity();
+		t.inc(1); t.norm(); ns=t.parity(); mt.copy(t); mt.inc(1); mt.norm();
+		t.cmove(mt,s);
+		Q.cmove(this,ns);
+		C.copy(Q);
+
+		nb=1+Math.floor((t.nbits()+3)/4);
+
+// convert exponent to signed 4-bit window 
+		for (i=0;i<nb;i++)
+		{
+			w[i]=(t.lastbits(5)-16);
+			t.dec(w[i]); t.norm();
+			t.fshr(4);	
+		}
+		w[nb]=t.lastbits(5);
+	
+		P.copy(W[Math.floor((w[nb]-1)/2)]);  
+		for (i=nb-1;i>=0;i--)
+		{
+			Q.select(W,w[i]);
+			P.dbl();
+			P.dbl();
+			P.dbl();
+			P.dbl();
+			P.add(Q);
+		}
+		P.sub(C);
+		P.affine();
+		return P;
+	}
+};
+
+/* convert from byte array to point */
+ECP2.fromBytes=function(b)
+{
+	var i,t=[];
+	var ra,rb;
+
+	for (i=0;i<ROM.MODBYTES;i++) t[i]=b[i];
+	ra=BIG.fromBytes(t);
+	for (i=0;i<ROM.MODBYTES;i++) t[i]=b[i+ROM.MODBYTES];
+	rb=BIG.fromBytes(t);
+
+	var rx=new FP2(ra,rb); //rx.bset(ra,rb);
+
+	for (i=0;i<ROM.MODBYTES;i++) t[i]=b[i+2*ROM.MODBYTES];
+	ra=BIG.fromBytes(t);
+	for (i=0;i<ROM.MODBYTES;i++) t[i]=b[i+3*ROM.MODBYTES];
+	rb=BIG.fromBytes(t);
+
+	var ry=new FP2(ra,rb); //ry.bset(ra,rb);
+
+	var P=new ECP2();
+	P.setxy(rx,ry);
+	return P;
+};
+
+/* Calculate RHS of curve equation x^3+B */
+ECP2.RHS=function(x) 
+{
+	x.norm();
+	var r=new FP2(x); //r.copy(x);
+	r.sqr();
+
+	var c=new BIG(0); c.rcopy(ROM.CURVE_B);
+	var b=new FP2(c); //b.bseta(c);
+	b.div_ip();
+	r.mul(x);
+	r.add(b);
+
+	r.reduce();
+	return r;
+};
+
+/* normalises m-array of ECP2 points. Requires work vector of m FP2s */
+
+ECP2.multiaffine=function(m,P)
+{
+	var i;
+	var t1=new FP2(0);
+	var t2=new FP2(0);
+	var work=[];
+
+	work[0]=new FP2(1);
+	work[1]=new FP2(P[0].z);
+	for (i=2;i<m;i++)
+	{
+		work[i]=new FP2(work[i-1]);
+		work[i].mul(P[i-1].z);
+	}
+
+	t1.copy(work[m-1]); t1.mul(P[m-1].z);
+
+	t1.inverse();
+
+	t2.copy(P[m-1].z);
+	work[m-1].mul(t1);
+
+	for (i=m-2;;i--)
+	{
+		if (i==0)
+		{
+			work[0].copy(t1);
+			work[0].mul(t2);
+			break;
+		}
+		work[i].mul(t2);
+		work[i].mul(t1);
+		t2.mul(P[i].z);
+	}
+/* now work[] contains inverses of all Z coordinates */
+
+	for (i=0;i<m;i++)
+	{
+		P[i].z.one();
+		t1.copy(work[i]); t1.sqr();
+		P[i].x.mul(t1);
+		t1.mul(work[i]);
+		P[i].y.mul(t1);
+	}    
+};
+
+/* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3 */
+ECP2.mul4=function(Q,u)
+{
+	var i,j,nb;
+	var a=[];
+	var T=new ECP2();
+	var C=new ECP2();
+	var P=new ECP2();
+	var W=[];
+	var mt=new BIG();
+	var t=[];
+	var w=[];
+
+	for (i=0;i<4;i++)
+	{
+		t[i]=new BIG(u[i]);
+		Q[i].affine();
+	}
+
+/* precompute table */
+
+	W[0]=new ECP2(); W[0].copy(Q[0]); W[0].sub(Q[1]);
+	W[1]=new ECP2(); W[1].copy(W[0]);
+	W[2]=new ECP2(); W[2].copy(W[0]);
+	W[3]=new ECP2(); W[3].copy(W[0]);
+	W[4]=new ECP2(); W[4].copy(Q[0]); W[4].add(Q[1]);
+	W[5]=new ECP2(); W[5].copy(W[4]);
+	W[6]=new ECP2(); W[6].copy(W[4]);
+	W[7]=new ECP2(); W[7].copy(W[4]);
+	T.copy(Q[2]); T.sub(Q[3]);
+	W[1].sub(T);
+	W[2].add(T);
+	W[5].sub(T);
+	W[6].add(T);
+	T.copy(Q[2]); T.add(Q[3]);
+	W[0].sub(T);
+	W[3].add(T);
+	W[4].sub(T);
+	W[7].add(T);
+
+	ECP2.multiaffine(8,W);
+
+/* if multiplier is even add 1 to multiplier, and add P to correction */
+	mt.zero(); C.inf();
+	for (i=0;i<4;i++)
+	{
+		if (t[i].parity()==0)
+		{
+			t[i].inc(1); t[i].norm();
+			C.add(Q[i]);
+		}
+		mt.add(t[i]); mt.norm();
+	}
+
+	nb=1+mt.nbits();
+
+/* convert exponent to signed 1-bit window */
+	for (j=0;j<nb;j++)
+	{
+		for (i=0;i<4;i++)
+		{
+			a[i]=(t[i].lastbits(2)-2);
+			t[i].dec(a[i]); t[i].norm(); 
+			t[i].fshr(1);
+		}
+		w[j]=(8*a[0]+4*a[1]+2*a[2]+a[3]);
+	}
+	w[nb]=(8*t[0].lastbits(2)+4*t[1].lastbits(2)+2*t[2].lastbits(2)+t[3].lastbits(2));
+
+	P.copy(W[Math.floor((w[nb]-1)/2)]);  
+
+	for (i=nb-1;i>=0;i--)
+	{
+		T.select(W,w[i]);
+		P.dbl();
+		P.add(T);
+	}
+	P.sub(C); /* apply correction */
+
+	P.affine();
+	return P;
+};
+
+/* return 1 if b==c, no branching */
+ECP2.teq=function(b,c)
+{
+	var x=b^c;
+	x-=1;  // if x=0, x now -1
+	return ((x>>31)&1);
+};
+
diff --git a/version22/js/FF.js b/version22/js/FF.js
new file mode 100644
index 0000000..94dedc6
--- /dev/null
+++ b/version22/js/FF.js
@@ -0,0 +1,947 @@
+/*
+	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.
+*/
+
+/* AMCL FF number class */
+
+/* General purpose Constructor */
+var FF = function(n) {
+	this.v=new Array(n);
+	this.length=n;
+	for (var i=0;i<n;i++)
+		this.v[i]=new BIG(0);
+};
+
+FF.prototype={
+/* set to zero */
+
+	P_EXCESS: function() 
+	{
+		return ((this.v[this.length-1].get(ROM.NLEN-1)&FF.P_OMASK)>>(FF.P_TBITS));
+	},
+
+	zero: function()
+	{
+		for (var i=0;i<this.length;i++) this.v[i].zero();
+		return this;
+	},
+
+	getlen: function()
+	{
+		return this.length;
+	},
+
+/* set to integer */
+	set: function(m)
+	{
+		this.zero();
+		this.v[0].set(0,(m&ROM.BMASK));
+		this.v[0].set(1,(m>>ROM.BASEBITS));
+	},
+/* copy from FF b */
+	copy: function(b)
+	{
+		for (var i=0;i<this.length;i++)
+		{
+			this.v[i].copy(b.v[i]);
+		}
+	},
+/* copy from FF b */
+	rcopy: function(b)
+	{
+		for (var i=0;i<this.length;i++)
+		{
+			this.v[i].rcopy(b[i]);
+		}
+	},
+/* x=y<<n */
+	dsucopy: function(b)
+	{
+		for (var i=0;i<b.length;i++)
+		{
+			this.v[b.length+i].copy(b.v[i]);
+			this.v[i].zero();
+		}
+	},
+/* x=y */
+	dscopy: function(b)
+	{
+		for (var i=0;i<b.length;i++)
+		{
+			this.v[i].copy(b.v[i]);
+			this.v[b.length+i].zero();
+		}
+	},
+
+/* x=y>>n */
+	sducopy: function(b)
+	{
+		for (var i=0;i<this.length;i++)
+		{
+			this.v[i].copy(b.v[this.length+i]);
+		}
+	},
+	one: function()
+	{
+		this.v[0].one();
+		for (var i=1;i<this.length;i++)
+		{
+			this.v[i].zero();
+		}
+	},
+/* test equals 0 */
+	iszilch: function() 
+	{
+		for (var i=0;i<this.length;i++)
+		{
+			if (!this.v[i].iszilch()) return false;
+		}
+		return true;
+	},
+/* shift right by BIGBITS-bit words */
+	shrw: function(n)
+	{
+		for (var i=0;i<n;i++) 
+		{
+			this.v[i].copy(this.v[i+n]);
+			this.v[i+n].zero();
+		}
+	},
+
+/* shift left by BIGBITS-bit words */
+	shlw: function(n)
+	{
+		for (var i=0;i<n;i++) 
+		{
+			this.v[n+i].copy(this.v[i]);
+			this.v[i].zero();
+		}
+	},
+/* extract last bit */
+	parity: function()
+	{
+		return this.v[0].parity();
+	},
+
+	lastbits: function(m)
+	{
+		return this.v[0].lastbits(m);
+	},
+	
+
+/* recursive add */
+	radd: function(vp,x,xp,y,yp,n)
+	{
+		for (var i=0;i<n;i++)
+		{
+			this.v[vp+i].copy(x.v[xp+i]);
+			this.v[vp+i].add(y.v[yp+i]);
+		}
+	},
+
+/* recursive inc */
+	rinc: function(vp,y,yp,n)
+	{
+		for (var i=0;i<n;i++)
+		{
+			this.v[vp+i].add(y.v[yp+i]);
+		}
+	},
+
+/* recursive sub */
+	rsub: function(vp,x,xp,y,yp,n)
+	{
+		for (var i=0;i<n;i++)
+		{
+			this.v[vp+i].copy(x.v[xp+i]);
+			this.v[vp+i].sub(y.v[yp+i]);
+		}
+	},
+
+/* recursive dec */
+	rdec: function(vp,y,yp,n)
+	{
+		for (var i=0;i<n;i++)
+		{
+			this.v[vp+i].sub(y.v[yp+i]);
+		}
+	},
+
+/* simple add */
+	add: function(b)
+	{
+		for (var i=0;i<this.length;i++)
+			this.v[i].add(b.v[i]);
+	},
+
+/* simple sub */
+	sub: function(b)
+	{
+		for (var i=0;i<this.length;i++)
+			this.v[i].sub(b.v[i]);
+	},
+	
+/* reverse sub */
+	revsub: function(b)
+	{
+		for (var i=0;i<this.length;i++)
+			this.v[i].rsub(b.v[i]);
+	},
+
+/* increment/decrement by a small integer */
+	inc: function(m)
+	{
+		this.v[0].inc(m);
+		this.norm();
+	},
+
+	dec: function(m)
+	{
+		this.v[0].dec(m);
+		this.norm();
+	},
+
+	/* normalise - but hold any overflow in top part unless n<0 */
+	rnorm: function(vp,n)
+	{
+		var trunc=false;
+		var i,carry;
+		if (n<0)
+		{ /* -v n signals to do truncation */
+			n=-n;
+			trunc=true;
+		}
+		for (i=0;i<n-1;i++)
+		{
+			carry=this.v[vp+i].norm();  
+			this.v[vp+i].xortop(carry<<FF.P_TBITS);
+			this.v[vp+i+1].inc(carry);
+		}
+		carry=this.v[vp+n-1].norm();
+		if (trunc) 
+			this.v[vp+n-1].xortop(carry<<FF.P_TBITS);
+		return this;
+	},
+	norm: function()
+	{
+		this.rnorm(0,this.length);
+	},
+
+/* shift left by one bit */
+	shl: function()
+	{
+		var i,carry,delay_carry=0;
+		for (i=0;i<this.length-1;i++)
+		{
+			carry=this.v[i].fshl(1);
+			this.v[i].inc(delay_carry);
+			this.v[i].xortop(carry<<FF.P_TBITS);
+			delay_carry=carry;
+		}
+		this.v[this.length-1].fshl(1);
+		this.v[this.length-1].inc(delay_carry);
+	},
+
+/* shift right by one bit */
+	shr: function()
+	{
+		var i,carry;
+		for (i=this.length-1;i>0;i--)
+		{
+			carry=this.v[i].fshr(1);
+			this.v[i-1].ortop(carry<<FF.P_TBITS);
+		}
+		this.v[0].fshr(1);
+	},
+
+/* Convert to Hex String */
+	toString: function() 
+	{
+		this.norm();
+		var s="";
+
+		for (var i=this.length-1;i>=0;i--)
+		{
+			s+=this.v[i].toString();
+		}
+		return s;
+	},
+/* Convert FFs to/from byte arrays */
+	toBytes: function(b)
+	{
+		for (var i=0;i<this.length;i++)
+		{
+			this.v[i].tobytearray(b,(this.length-i-1)*ROM.MODBYTES);
+		}
+	},
+
+/* z=x*y, t is workspace */
+	karmul: function(vp,x,xp,y,yp,t,tp,n)
+	{
+		var nd2;
+		if (n==1)
+		{
+			var d=BIG.mul(x.v[xp],y.v[yp]);
+			this.v[vp+1]=d.split(8*ROM.MODBYTES);
+			this.v[vp].copy(d);
+			return;
+		}
+		nd2=n/2;
+		this.radd(vp,x,xp,x,xp+nd2,nd2);
+		this.rnorm(vp,nd2);                   /* Important - required for 32-bit build */
+		this.radd(vp+nd2,y,yp,y,yp+nd2,nd2);
+		this.rnorm(vp+nd2,nd2);               /* Important - required for 32-bit build */
+		t.karmul(tp,this,vp,this,vp+nd2,t,tp+n,nd2);
+		this.karmul(vp,x,xp,y,yp,t,tp+n,nd2);
+		this.karmul(vp+n,x,xp+nd2,y,yp+nd2,t,tp+n,nd2);
+		t.rdec(tp,this,vp,n);
+		t.rdec(tp,this,vp+n,n);
+		this.rinc(vp+nd2,t,tp,n);
+		this.rnorm(vp,2*n);
+	},
+
+	karsqr: function(vp,x,xp,t,tp,n)
+	{
+		var nd2;
+		if (n==1)
+		{
+			var d=BIG.sqr(x.v[xp]);
+			this.v[vp+1].copy(d.split(8*ROM.MODBYTES));
+			this.v[vp].copy(d);
+			return;
+		}	
+
+		nd2=n/2;
+		this.karsqr(vp,x,xp,t,tp+n,nd2);
+		this.karsqr(vp+n,x,xp+nd2,t,tp+n,nd2);
+		t.karmul(tp,x,xp,x,xp+nd2,t,tp+n,nd2);
+		this.rinc(vp+nd2,t,tp,n);
+		this.rinc(vp+nd2,t,tp,n);
+		this.rnorm(vp+nd2,n);
+	},
+
+	karmul_lower: function(vp,x,xp,y,yp,t,tp,n)
+	{ /* Calculates Least Significant bottom half of x*y */
+		var nd2;
+		if (n==1)
+		{ /* only calculate bottom half of product */
+			this.v[vp].copy(BIG.smul(x.v[xp],y.v[yp]));
+			return;
+		}
+		nd2=n/2;
+
+		this.karmul(vp,x,xp,y,yp,t,tp+n,nd2);
+		t.karmul_lower(tp,x,xp+nd2,y,yp,t,tp+n,nd2);
+		this.rinc(vp+nd2,t,tp,nd2);
+		t.karmul_lower(tp,x,xp,y,yp+nd2,t,tp+n,nd2);
+
+		this.rinc(vp+nd2,t,tp,nd2);
+		this.rnorm(vp+nd2,-nd2);  /* truncate it */
+	},
+
+	karmul_upper: function(x,y,t,n)
+	{ /* Calculates Most Significant upper half of x*y, given lower part */
+		var nd2;
+ 
+		nd2=n/2;
+		this.radd(n,x,0,x,nd2,nd2);  
+		this.radd(n+nd2,y,0,y,nd2,nd2);
+		this.rnorm(n,nd2);
+		this.rnorm(n+nd2,nd2);
+
+		t.karmul(0,this,n+nd2,this,n,t,n,nd2);  /* t = (a0+a1)(b0+b1) */
+		this.karmul(n,x,nd2,y,nd2,t,n,nd2); /* z[n]= a1*b1 */
+									/* z[0-nd2]=l(a0b0) z[nd2-n]= h(a0b0)+l(t)-l(a0b0)-l(a1b1) */
+		t.rdec(0,this,n,n);              /* t=t-a1b1  */							
+		this.rinc(nd2,this,0,nd2);   /* z[nd2-n]+=l(a0b0) = h(a0b0)+l(t)-l(a1b1)  */
+		this.rdec(nd2,t,0,nd2);   /* z[nd2-n]=h(a0b0)+l(t)-l(a1b1)-l(t-a1b1)=h(a0b0) */
+		this.rnorm(0,-n);					/* a0b0 now in z - truncate it */
+		t.rdec(0,this,0,n);         /* (a0+a1)(b0+b1) - a0b0 */
+		this.rinc(nd2,t,0,n);
+
+		this.rnorm(nd2,n);
+	},
+
+/* return low part of product this*y */
+	lmul: function(y)
+	{
+		var n=this.length;
+		var t=new FF(2*n);
+		var x=new FF(n); x.copy(this);
+		this.karmul_lower(0,x,0,y,0,t,0,n);
+	},
+
+/* Set b=b mod c */
+	mod: function(c)
+	{
+		var k=0;  
+
+		this.norm();
+		if (FF.comp(this,c)<0) 
+			return;
+		do
+		{
+			c.shl();
+			k++;
+		} while (FF.comp(this,c)>=0);
+
+		while (k>0)
+		{
+			c.shr();
+			if (FF.comp(this,c)>=0)
+			{
+				this.sub(c);
+				this.norm();
+			}
+			k--;
+		}
+	},
+
+/* return This mod modulus, N is modulus, ND is Montgomery Constant */
+	reduce: function(N,ND)
+	{ /* fast karatsuba Montgomery reduction */
+		var n=N.length;
+		var t=new FF(2*n);
+		var r=new FF(n);
+		var m=new FF(n);
+
+		r.sducopy(this);
+		m.karmul_lower(0,this,0,ND,0,t,0,n);
+		this.karmul_upper(N,m,t,n);
+		m.sducopy(this);
+
+		r.add(N);
+		r.sub(m);
+		r.norm();
+
+		return r;
+
+	},
+
+/* Set r=this mod b */
+/* this is of length - 2*n */
+/* r,b is of length - n */
+	dmod: function(b)
+	{
+		var k,n=b.length;
+		var m=new FF(2*n);
+		var x=new FF(2*n);
+		var r=new FF(n);
+
+		x.copy(this);
+		x.norm();
+		m.dsucopy(b); k=ROM.BIGBITS*n;
+
+		while (FF.comp(x,m)>=0)
+		{
+			x.sub(m);
+			x.norm();
+		}
+
+		while (k>0)
+		{	
+			m.shr();
+
+			if (FF.comp(x,m)>=0)
+			{
+				x.sub(m);
+				x.norm();
+			}
+			k--;
+		}
+
+		r.copy(x);
+		r.mod(b);
+		return r;
+	},
+
+/* Set return=1/this mod p. Binary method - a<p on entry */
+	invmodp: function(p)
+	{
+		var n=p.length;
+
+		var u=new FF(n);
+		var v=new FF(n);
+		var x1=new FF(n);
+		var x2=new FF(n);
+		var t=new FF(n);
+		var one=new FF(n);
+
+		one.one();
+		u.copy(this);
+		v.copy(p);
+		x1.copy(one);
+		x2.zero();
+
+	// reduce n in here as well! 
+		while (FF.comp(u,one)!==0 && FF.comp(v,one)!==0)
+		{
+			while (u.parity()===0)
+			{
+				u.shr();
+				if (x1.parity()!==0)
+				{
+					x1.add(p); 
+					x1.norm();
+				}
+				x1.shr(); 
+			}
+			while (v.parity()===0)
+			{
+				v.shr(); 
+				if (x2.parity()!==0)
+				{
+					x2.add(p);
+					x2.norm();
+				}
+				x2.shr();
+			}
+			if (FF.comp(u,v)>=0)
+			{
+
+				u.sub(v);
+				u.norm();
+				if (FF.comp(x1,x2)>=0) x1.sub(x2);
+				else
+				{
+					t.copy(p);
+					t.sub(x2);
+					x1.add(t);
+				}
+				x1.norm();
+			}
+			else
+			{
+				v.sub(u);
+				v.norm();
+				if (FF.comp(x2,x1)>=0) x2.sub(x1);
+				else
+				{
+					t.copy(p);
+					t.sub(x1);
+					x2.add(t);
+				}
+				x2.norm();
+			}
+		}
+		if (FF.comp(u,one)===0)
+			this.copy(x1);
+		else
+			this.copy(x2);
+	},
+
+/* nresidue mod m */
+	nres: function(m)
+	{
+		var n=m.length;
+		var d=new FF(2*n);
+		d.dsucopy(this);
+		this.copy(d.dmod(m));
+	},
+
+	redc: function(m,ND)
+	{
+		var n=m.length;
+		var d=new FF(2*n);
+
+		this.mod(m);
+		d.dscopy(this);
+
+		this.copy(d.reduce(m,ND));
+		this.mod(m);
+	},
+
+	mod2m: function(m)
+	{
+		for (var i=m;i<this.length;i++)
+			this.v[i].zero();
+	},
+
+	/* U=1/a mod 2^m - Arazi & Qi */
+	invmod2m: function()
+	{
+		var i,n=this.length;
+
+		var b=new FF(n);
+		var c=new FF(n);
+		var U=new FF(n);
+
+		var t;
+
+		U.zero();
+		U.v[0].copy(this.v[0]);
+		U.v[0].invmod2m();
+
+		for (i=1;i<n;i<<=1)
+		{
+			b.copy(this); b.mod2m(i);
+			t=FF.mul(U,b); t.shrw(i); b.copy(t);
+			c.copy(this); c.shrw(i); c.mod2m(i);
+			c.lmul(U); c.mod2m(i);
+
+			b.add(c); b.norm();
+			b.lmul(U); b.mod2m(i);
+
+			c.one(); c.shlw(i); b.revsub(c); b.norm();
+			b.shlw(i);
+			U.add(b);
+		}
+		U.norm();
+		return U;
+	},
+
+	random: function(rng)
+	{
+		var n=this.length;
+		for (var i=0;i<n;i++)
+		{
+			this.v[i].copy(BIG.random(rng));
+		}
+	/* make sure top bit is 1 */
+		while (this.v[n-1].nbits()<ROM.MODBYTES*8) this.v[n-1].copy(BIG.random(rng));
+
+	},
+
+	/* generate random x */
+	randomnum: function(p,rng)
+	{
+		var n=this.length;
+		var d=new FF(2*n);
+
+		for (var i=0;i<2*n;i++)
+		{
+			d.v[i].copy(BIG.random(rng));
+		}
+		this.copy(d.dmod(p));
+	},
+
+	/* this*=y mod p */
+	modmul: function(y,p,nd)
+	{
+		var ex=this.P_EXCESS();
+		var ey=y.P_EXCESS();
+		if ((ex+1)>=Math.floor((FF.P_FEXCESS-1)/(ey+1))) this.mod(p);
+		var d=FF.mul(this,y);
+		this.copy(d.reduce(p,nd));
+	},
+
+	/* this*=y mod p */
+	modsqr: function(p,nd)
+	{
+		var ex=this.P_EXCESS();
+		if ((ex+1)>=Math.floor((FF.P_FEXCESS-1)/(ex+1))) this.mod(p); 
+		var d=FF.sqr(this);
+		this.copy(d.reduce(p,nd));
+	},
+
+	/* this=this^e mod p using side-channel resistant Montgomery Ladder, for large e */
+	skpow: function(e,p)
+	{
+		var i,b,n=p.length;
+		var R0=new FF(n);
+		var R1=new FF(n);
+		var ND=p.invmod2m();
+
+		this.mod(p);
+		R0.one();
+		R1.copy(this);
+		R0.nres(p);
+		R1.nres(p);
+
+		for (i=8*ROM.MODBYTES*n-1;i>=0;i--)
+		{
+
+			b=e.v[Math.floor(i/ROM.BIGBITS)].bit(i%ROM.BIGBITS);
+
+			this.copy(R0);
+			this.modmul(R1,p,ND);
+
+			FF.cswap(R0,R1,b);
+			R0.modsqr(p,ND);
+
+			R1.copy(this);
+			FF.cswap(R0,R1,b);
+
+		}
+
+		this.copy(R0);
+		this.redc(p,ND);
+	},
+
+	/* this =this^e mod p using side-channel resistant Montgomery Ladder, for short e */
+	skspow: function(e,p)
+	{
+		var i,b,n=p.length;
+		var R0=new FF(n);
+		var R1=new FF(n);
+		var ND=p.invmod2m();
+
+		this.mod(p);
+		R0.one();
+		R1.copy(this);
+		R0.nres(p);
+		R1.nres(p);
+
+		for (i=8*ROM.MODBYTES-1;i>=0;i--)
+		{
+			b=e.bit(i);
+			this.copy(R0);
+			this.modmul(R1,p,ND);
+
+			FF.cswap(R0,R1,b);
+			R0.modsqr(p,ND);
+
+			R1.copy(this);
+			FF.cswap(R0,R1,b);
+		}
+		this.copy(R0);
+		this.redc(p,ND);
+	},
+
+	/* raise to an integer power - right-to-left method */
+	power: function(e,p)
+	{
+		var n=p.length;
+		var f=true;
+		var w=new FF(n);
+		var ND=p.invmod2m();
+
+		w.copy(this);
+		w.nres(p);
+
+		if (e==2)
+		{
+			this.copy(w);
+			this.modsqr(p,ND);
+		}
+		else for (; ; )
+		{
+			if (e%2==1) 
+			{
+				if (f) this.copy(w);
+				else 
+				{
+					ROM.debug=true;
+					this.modmul(w,p,ND);
+					ROM.debug=false;
+				}
+				f=false;
+
+			}
+			e>>=1;
+			if (e===0) break;
+			w.modsqr(p,ND);
+		}
+
+		this.redc(p,ND);
+	},
+
+	/* this=this^e mod p, faster but not side channel resistant */
+	pow: function(e,p)
+	{
+		var i,b,n=p.length;
+		var w=new FF(n);
+		var ND=p.invmod2m();
+
+		w.copy(this);
+		this.one();
+		this.nres(p);
+		w.nres(p);
+		for (i=8*ROM.MODBYTES*n-1;i>=0;i--)
+		{
+			this.modsqr(p,ND);
+			b=e.v[Math.floor(i/ROM.BIGBITS)].bit(i%ROM.BIGBITS);
+			if (b==1) this.modmul(w,p,ND);
+		}
+		this.redc(p,ND);
+	},
+
+	/* double exponentiation r=x^e.y^f mod p */
+	pow2: function(e,y,f,p)
+	{
+		var i,eb,fb,n=p.length;
+		var xn=new FF(n);
+		var yn=new FF(n);
+		var xy=new FF(n);
+		var ND=p.invmod2m();
+
+		xn.copy(this);
+		yn.copy(y);
+		xn.nres(p);
+		yn.nres(p);
+		xy.copy(xn); xy.modmul(yn,p,ND);
+		this.one();
+		this.nres(p);
+
+		for (i=8*ROM.MODBYTES-1;i>=0;i--)
+		{
+			eb=e.bit(i);
+			fb=f.bit(i);
+			this.modsqr(p,ND);
+			if (eb==1)
+			{
+				if (fb==1) this.modmul(xy,p,ND);
+				else this.modmul(xn,p,ND);
+			}
+			else
+			{
+				if (fb==1) this.modmul(yn,p,ND);
+			}
+		}
+		this.redc(p,ND);
+	},
+
+	/* quick and dirty check for common factor with n */
+	cfactor: function(s)
+	{
+		var r,n=this.length;
+		var g;
+
+		var x=new FF(n);
+		var y=new FF(n);
+		y.set(s);
+
+		x.copy(this);
+		x.norm();
+
+		do
+		{
+			x.sub(y);
+			x.norm();
+			while (!x.iszilch() && x.parity()===0) x.shr();
+		}
+		while (FF.comp(x,y)>0);
+
+		g=x.v[0].get(0);
+		r=FF.igcd(s,g);
+		if (r>1) return true;
+		return false;
+	}
+
+
+};
+
+FF.P_MBITS=ROM.MODBYTES*8;
+FF.P_OMASK=((-1)<<(FF.P_MBITS%ROM.BASEBITS));
+FF.P_FEXCESS=(1<<(ROM.BASEBITS*ROM.NLEN-FF.P_MBITS));
+FF.P_TBITS=(FF.P_MBITS%ROM.BASEBITS);
+
+
+/* compare x and y - must be normalised, and of same length */
+FF.comp=function(a,b)
+{
+	var i,j;
+	for (i=a.length-1;i>=0;i--)
+	{
+		j=BIG.comp(a.v[i],b.v[i]);
+		if (j!==0) return j;
+	}
+	return 0;
+};
+
+FF.fromBytes=function(x,b)
+{
+	for (var i=0;i<x.length;i++)
+	{
+		x.v[i]=BIG.frombytearray(b,(x.length-i-1)*ROM.MODBYTES);
+	}
+};
+
+/* in-place swapping using xor - side channel resistant - lengths must be the same */
+FF.cswap=function(a,b,d)
+{
+	for (var i=0;i<a.length;i++)
+	{
+	//	BIG.cswap(a.v[i],b.v[i],d);
+		a.v[i].cswap(b.v[i],d);
+	}
+};
+
+	/* z=x*y. Assumes x and y are of same length. */
+FF.mul=function(x,y)
+{
+	var n=x.length;
+	var z=new FF(2*n);
+	var t=new FF(2*n);
+	z.karmul(0,x,0,y,0,t,0,n);
+	return z;
+};
+
+	/* z=x^2 */
+FF.sqr=function(x)
+{
+	var n=x.length;
+	var z=new FF(2*n);
+	var t=new FF(2*n);
+	z.karsqr(0,x,0,t,0,n);
+	return z;
+};
+
+FF.igcd=function(x,y)
+{ /* integer GCD, returns GCD of x and y */
+	var r;
+	if (y===0) return x;
+	while ((r=x%y)!==0)
+		{x=y;y=r;}
+	return y;
+};
+
+/* Miller-Rabin test for primality. Slow. */
+FF.prime=function(p,rng)
+{
+	var i,j,s=0,n=p.length;
+	var loop;
+	var d=new FF(n);
+	var x=new FF(n);
+	var unity=new FF(n);
+	var nm1=new FF(n);
+
+	var sf=4849845; /* 3*5*.. *19 */
+	p.norm();
+
+	if (p.cfactor(sf)) return false;
+	unity.one();
+	nm1.copy(p);
+	nm1.sub(unity);
+	nm1.norm();
+	d.copy(nm1);
+
+	while (d.parity()===0)
+	{
+		d.shr();
+		s++;
+	}
+	if (s===0) return false;
+
+	for (i=0;i<10;i++)
+	{
+		x.randomnum(p,rng);
+		x.pow(d,p);
+		if (FF.comp(x,unity)===0 || FF.comp(x,nm1)===0) continue;
+		loop=false;
+		for (j=1;j<s;j++)
+		{
+			x.power(2,p);
+			if (FF.comp(x,unity)===0) return false;
+			if (FF.comp(x,nm1)===0) {loop=true; break;}
+		}
+		if (loop) continue;
+		return false;
+	}
+	return true;
+};
diff --git a/version22/js/FP.js b/version22/js/FP.js
new file mode 100644
index 0000000..0d23382
--- /dev/null
+++ b/version22/js/FP.js
@@ -0,0 +1,360 @@
+/*
+	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.
+*/
+
+/* Finite Field arithmetic */
+/* AMCL mod p functions */
+
+/* General purpose COnstructor */
+var FP = function(x) {
+	if (x instanceof FP)
+	{
+		this.f=new BIG(x.f);
+	}
+	else
+	{
+		this.f=new BIG(x);
+		this.nres();
+	}
+};
+
+FP.prototype={
+/* set this=0 */
+	zero: function()
+	{
+		return this.f.zero();
+	},
+
+/* copy from a BIG in ROM */
+	rcopy: function(y)
+	{
+		this.f.rcopy(y);
+		this.nres();
+	},
+
+/* copy from another BIG */
+	bcopy: function(y)
+	{
+		this.f.copy(y);
+		this.nres();
+//alert("4. f= "+this.f.toString());
+	},
+
+/* copy from another FP */
+	copy: function(y)
+	{
+		return this.f.copy(y.f);
+	},
+
+/* conditional swap of a and b depending on d */
+	cswap: function(b,d)
+	{
+		this.f.cswap(b.f,d);
+	},
+
+/* conditional copy of b to a depending on d */
+	cmove: function(b,d)
+	{
+		this.f.cmove(b.f,d);
+	},
+
+/* convert to Montgomery n-residue form */
+	nres: function()
+	{
+		if (ROM.MODTYPE!=ROM.PSEUDO_MERSENNE && ROM.MODTYPE!=ROM.GENERALISED_MERSENNE)
+		{
+			var p=new BIG();
+			p.rcopy(ROM.Modulus);
+			var d=new DBIG(0);
+//alert("f= "+this.f.toString());
+			d.hcopy(this.f);
+			d.norm();
+//alert("1. d= "+d.toString());
+			d.shl(ROM.NLEN*ROM.BASEBITS);
+//alert("2. d= "+d.toString());
+			this.f.copy(d.mod(p));
+//alert("3. f= "+this.f.toString());
+
+		}
+		return this;
+	},
+	
+/* convert back to regular form */
+	redc: function()
+	{
+		var r=new BIG(0);
+		r.copy(this.f);
+		if (ROM.MODTYPE!=ROM.PSEUDO_MERSENNE && ROM.MODTYPE!=ROM.GENERALISED_MERSENNE)
+		{
+			var d=new DBIG(0);
+			d.hcopy(this.f);
+//alert("rd= "+d.toString());
+			var w=BIG.mod(d);
+//alert("w= "+w.toString());
+			r.copy(w);
+		}
+
+		return r;
+	},	
+
+/* convert this to string */
+	toString: function() 
+	{
+		var s=this.redc().toString();
+		return s;
+	},
+
+/* test this=0 */
+	iszilch: function() 
+	{
+		this.reduce();
+		return this.f.iszilch();
+	},
+
+/* reduce this mod Modulus */
+	reduce: function()
+	{
+		var p=new BIG(0);
+		p.rcopy(ROM.Modulus);
+		return this.f.mod(p);
+	},
+
+/* set this=1 */
+	one: function()
+	{
+		this.f.one(); 
+		return this.nres();
+	},
+
+/* normalise this */
+	norm: function()
+	{
+		return this.f.norm();
+	},
+
+/* this*=b mod Modulus */
+	mul: function(b)
+	{
+		this.norm();
+		b.norm();
+		var ea=BIG.EXCESS(this.f);
+		var eb=BIG.EXCESS(b.f);
+
+		if ((ea+1)*(eb+1)>ROM.FEXCESS) this.reduce();
+		//if ((ea+1) >= Math.floor((ROM.FEXCESS-1)/(eb+1))) this.reduce();
+
+		var d=BIG.mul(this.f,b.f);
+		this.f.copy(BIG.mod(d));
+		return this;
+	},
+
+/* this*=c mod Modulus where c is an int */
+	imul: function(c)
+	{
+		var s=false;
+		this.norm();
+		if (c<0)
+		{
+			c=-c;
+			s=true;
+		}
+
+		var afx=(BIG.EXCESS(this.f)+1)*(c+1)+1;
+		if (c<ROM.NEXCESS && afx<ROM.FEXCESS)
+		{
+			this.f.imul(c);
+		}
+		else
+		{
+			if (afx<ROM.FEXCESS) this.f.pmul(c);
+			else
+			{
+				var p=new BIG(0);
+				p.rcopy(ROM.Modulus);
+				var d=this.f.pxmul(c);
+				this.f.copy(d.mod(p));
+			}
+		}
+		if (s) this.neg();
+		return this.norm();
+	},
+
+/* this*=this mod Modulus */
+	sqr: function()
+	{
+		var d;
+		this.norm();
+		var ea=BIG.EXCESS(this.f);
+
+		if ((ea+1)*(ea+1)>ROM.FEXCESS) this.reduce();
+		//if ((ea+1)>= Math.floor((ROM.FEXCESS-1)/(ea+1))) this.reduce();
+
+		d=BIG.sqr(this.f);
+		var t=BIG.mod(d); 
+		this.f.copy(t);
+		return this;
+	},
+
+/* this+=b */
+	add: function(b) 
+	{
+		this.f.add(b.f);
+		if (BIG.EXCESS(this.f)+2>=ROM.FEXCESS) this.reduce();
+		return this;
+	},
+/* this=-this mod Modulus */
+	neg: function()
+	{
+		var sb,ov;
+		var m=new BIG(0);
+		m.rcopy(ROM.Modulus);
+
+		this.norm();
+		sb=FP.logb2(BIG.EXCESS(this.f));
+
+//		ov=BIG.EXCESS(this.f); 
+//		sb=1; while(ov!==0) {sb++;ov>>=1;} 
+
+		m.fshl(sb);
+		this.f.rsub(m);	
+		if (BIG.EXCESS(this.f)>=ROM.FEXCESS) this.reduce();
+		return this;
+	},
+
+/* this-=b */
+	sub: function(b)
+	{
+		var n=new FP(0);
+		n.copy(b);
+		n.neg();
+		this.add(n);
+		return this;
+	},
+
+/* this/=2 mod Modulus */
+	div2: function()
+	{
+		this.norm();
+		if (this.f.parity()===0)
+			this.f.fshr(1);
+		else
+		{
+			var p=new BIG(0);
+			p.rcopy(ROM.Modulus);
+
+			this.f.add(p);
+			this.f.norm();
+			this.f.fshr(1);
+		}
+		return this;
+	},
+
+/* this=1/this mod Modulus */
+	inverse: function()
+	{
+		var p=new BIG(0);
+		p.rcopy(ROM.Modulus);
+		var r=this.redc();
+		r.invmodp(p);
+		this.f.copy(r);
+		return this.nres();
+	},
+
+/* return TRUE if this==a */
+	equals: function(a)
+	{
+		a.reduce();
+		this.reduce();
+		if (BIG.comp(a.f,this.f)===0) return true;
+		return false;
+	},
+
+/* return this^e mod Modulus */
+	pow: function(e)
+	{
+		var bt;
+		var r=new FP(1);
+		e.norm();
+		this.norm();
+		var m=new FP(0);
+		m.copy(this);
+		while (true)
+		{
+			bt=e.parity();
+			e.fshr(1);
+			if (bt==1) r.mul(m);
+			if (e.iszilch()) break;
+			m.sqr();
+		}
+
+		r.reduce();
+		return r;
+	},
+
+/* return jacobi symbol (this/Modulus) */
+	jacobi: function()
+	{
+		var p=new BIG(0);
+		p.rcopy(ROM.Modulus);
+		var w=this.redc();
+		return w.jacobi(p);
+	},
+
+/* return sqrt(this) mod Modulus */
+	sqrt: function()
+	{
+		this.reduce();
+		var b=new BIG(0);
+		b.rcopy(ROM.Modulus);
+		if (ROM.MOD8==5)
+		{
+			b.dec(5); b.norm(); b.shr(3);
+			var i=new FP(0); 
+			i.copy(this);
+			i.f.shl(1);
+			var v=i.pow(b);
+			i.mul(v); i.mul(v);
+			i.f.dec(1);
+			var r=new FP(0);
+			r.copy(this);
+			r.mul(v); r.mul(i); 
+			r.reduce();
+			return r;
+		}
+		else
+		{
+			b.inc(1); b.norm(); b.shr(2);
+			return this.pow(b);
+		}
+	}
+
+};
+
+FP.logb2=function(v)
+{
+		v |= v >>> 1;
+		v |= v >>> 2;
+		v |= v >>> 4;
+		v |= v >>> 8;
+		v |= v >>> 16;
+
+		v = v - ((v >>> 1) & 0x55555555);                  
+		v = (v & 0x33333333) + ((v >>> 2) & 0x33333333);  
+		var r = ((v + (v >>> 4) & 0xF0F0F0F) * 0x1010101) >>> 24; 
+		return r+1;
+};
diff --git a/version22/js/FP12.js b/version22/js/FP12.js
new file mode 100644
index 0000000..0d85044
--- /dev/null
+++ b/version22/js/FP12.js
@@ -0,0 +1,558 @@
+/*
+	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.
+*/
+
+/* AMCL Fp^12 functions */
+
+/* FP12 elements are of the form a+i.b+i^2.c */
+
+/* general purpose constructor */
+var FP12= function(d,e,f) 
+{
+	if (d instanceof FP12)
+	{
+		this.a=new FP4(d.a);
+		this.b=new FP4(d.b);
+		this.c=new FP4(d.c);
+	}
+	else
+	{
+		this.a=new FP4(d);
+		this.b=new FP4(e);
+		this.c=new FP4(f);
+	}
+};
+
+FP12.prototype={
+/* reduce all components of this mod Modulus */
+	reduce: function()
+	{
+		this.a.reduce();
+		this.b.reduce();
+		this.c.reduce();
+	},
+/* normalize all components of this mod Modulus */
+	norm: function()
+	{
+		this.a.norm();
+		this.b.norm();
+		this.c.norm();
+	},
+/* test x==0 ? */
+	iszilch: function() 
+	{
+		this.reduce();
+		return (this.a.iszilch() && this.b.iszilch() && this.c.iszilch());
+	},
+/* test x==1 ? */
+	isunity: function() 
+	{
+		var one=new FP4(1);
+		return (this.a.equals(one) && this.b.iszilch() && this.b.iszilch());
+	},
+/* extract a from this */
+	geta: function()
+	{
+		return this.a;
+	},
+/* extract b */
+	getb: function()
+	{
+		return this.b;
+	},
+/* extract c */
+	getc: function()
+	{
+		return this.c;
+	},
+/* return 1 if x==y, else 0 */
+	equals: function(x)
+	{
+		return (this.a.equals(x.a) && this.b.equals(x.b)&& this.c.equals(x.c));
+	},
+/* copy this=x */
+	copy: function(x)
+	{
+		this.a.copy(x.a);
+		this.b.copy(x.b);
+		this.c.copy(x.c);
+	},
+/* set this=1 */
+	one: function()
+	{
+		this.a.one();
+		this.b.zero();
+		this.c.zero();
+	},
+/* this=conj(this) */
+	conj: function()
+	{
+		this.a.conj();
+		this.b.nconj();
+		this.c.conj();
+	},
+
+/* set this from 3 FP4s */
+	set: function(d,e,f)
+	{
+		this.a.copy(d);
+		this.b.copy(e);
+		this.c.copy(f);
+	},
+/* set this from one FP4 */
+	seta: function(d)
+	{
+		this.a.copy(d);
+		this.b.zero();
+		this.c.zero();
+	},
+
+/* Granger-Scott Unitary Squaring */
+	usqr: function()
+	{
+		var A=new FP4(this.a); //A.copy(this.a);
+		var B=new FP4(this.c); //B.copy(this.c);
+		var C=new FP4(this.b); //C.copy(this.b);
+		var D=new FP4(0);
+
+		this.a.sqr();
+		D.copy(this.a); D.add(this.a);
+		this.a.add(D);
+
+		A.nconj();
+
+		A.add(A);
+		this.a.add(A);
+		B.sqr();
+		B.times_i();
+
+		D.copy(B); D.add(B);
+		B.add(D);
+
+		C.sqr();
+		D.copy(C); D.add(C);
+		C.add(D);
+
+		this.b.conj();
+		this.b.add(this.b);
+		this.c.nconj();
+
+		this.c.add(this.c);
+		this.b.add(B);
+		this.c.add(C);
+		this.reduce();
+	},
+
+/* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
+	sqr: function()
+	{
+		var A=new FP4(this.a); //A.copy(this.a);
+		var B=new FP4(this.b); //B.copy(this.b);
+		var C=new FP4(this.c); //C.copy(this.c);
+		var D=new FP4(this.a); //D.copy(this.a);
+
+		A.sqr();
+		B.mul(this.c);
+		B.add(B);
+		C.sqr();
+		D.mul(this.b);
+		D.add(D);
+
+		this.c.add(this.a);
+		this.c.add(this.b);
+		this.c.sqr();
+
+		this.a.copy(A);
+
+		A.add(B);
+		A.add(C);
+		A.add(D);
+		A.neg();
+		B.times_i();
+		C.times_i();
+
+		this.a.add(B);
+		this.b.copy(C); this.b.add(D);
+		this.c.add(A);
+
+		this.norm();
+	},
+
+/* FP12 full multiplication this=this*y */
+	mul: function(y)
+	{
+		var z0=new FP4(this.a); //z0.copy(this.a);
+		var z1=new FP4(0);
+		var z2=new FP4(this.b); //z2.copy(this.b);
+		var z3=new FP4(0);
+		var t0=new FP4(this.a); //t0.copy(this.a);
+		var t1=new FP4(y.a); //t1.copy(y.a);
+
+		z0.mul(y.a);
+		z2.mul(y.b);
+
+		t0.add(this.b);
+		t1.add(y.b);
+
+		z1.copy(t0); z1.mul(t1);
+		t0.copy(this.b); t0.add(this.c);
+
+		t1.copy(y.b); t1.add(y.c);
+		z3.copy(t0); z3.mul(t1);
+
+		t0.copy(z0); t0.neg();
+		t1.copy(z2); t1.neg();
+
+		z1.add(t0);
+		this.b.copy(z1); this.b.add(t1);
+
+		z3.add(t1);
+		z2.add(t0);
+
+		t0.copy(this.a); t0.add(this.c);
+		t1.copy(y.a); t1.add(y.c);
+		t0.mul(t1);
+		z2.add(t0);
+
+		t0.copy(this.c); t0.mul(y.c);
+		t1.copy(t0); t1.neg();
+
+		this.c.copy(z2); this.c.add(t1);
+		z3.add(t1);
+		t0.times_i();
+		this.b.add(t0);
+
+		z3.times_i();
+		this.a.copy(z0); this.a.add(z3);
+
+		this.norm();
+	},
+
+/* Special case this*=y that arises from special form of ATE pairing line function */
+	smul: function(y)
+	{
+		var z0=new FP4(this.a); //z0.copy(this.a);
+		var z2=new FP4(this.b); //z2.copy(this.b);
+		var z3=new FP4(this.b); //z3.copy(this.b);
+		var t0=new FP4(0); 
+		var t1=new FP4(y.a); //t1.copy(y.a);
+		
+		z0.mul(y.a);
+		z2.pmul(y.b.real());
+		this.b.add(this.a);
+		t1.real().add(y.b.real());
+
+		this.b.mul(t1);
+		z3.add(this.c);
+		z3.pmul(y.b.real());
+
+		t0.copy(z0); t0.neg();
+		t1.copy(z2); t1.neg();
+
+		this.b.add(t0);
+
+		this.b.add(t1);
+		z3.add(t1);
+		z2.add(t0);
+
+		t0.copy(this.a); t0.add(this.c);
+		t0.mul(y.a);
+		this.c.copy(z2); this.c.add(t0);
+
+		z3.times_i();
+		this.a.copy(z0); this.a.add(z3);
+
+		this.norm();
+	},
+
+/* this=1/this */
+	inverse: function()
+	{
+		var f0=new FP4(this.a); //f0.copy(this.a);
+		var f1=new FP4(this.b); //f1.copy(this.b);
+		var f2=new FP4(this.a); //f2.copy(this.a);
+		var f3=new FP4(0);
+
+		f0.sqr();
+		f1.mul(this.c);
+		f1.times_i();
+		f0.sub(f1);
+
+		f1.copy(this.c); f1.sqr();
+		f1.times_i();
+		f2.mul(this.b);
+		f1.sub(f2);
+
+		f2.copy(this.b); f2.sqr();
+		f3.copy(this.a); f3.mul(this.c);
+		f2.sub(f3);
+
+		f3.copy(this.b); f3.mul(f2);
+		f3.times_i();
+		this.a.mul(f0);
+		f3.add(this.a);
+		this.c.mul(f1);
+		this.c.times_i();
+
+		f3.add(this.c);
+		f3.inverse();
+		this.a.copy(f0); this.a.mul(f3);
+		this.b.copy(f1); this.b.mul(f3);
+		this.c.copy(f2); this.c.mul(f3);
+	},
+
+/* this=this^p, where p=Modulus, using Frobenius */
+	frob: function(f)
+	{
+		var f2=new FP2(f); 
+		var f3=new FP2(f); 
+
+		f2.sqr();
+		f3.mul(f2);
+
+		this.a.frob(f3);
+		this.b.frob(f3);
+		this.c.frob(f3);
+
+		this.b.pmul(f);
+		this.c.pmul(f2);
+	},
+
+/* trace function */
+	trace: function()
+	{
+		var t=new FP4(0);
+		t.copy(this.a);
+		t.imul(3);
+		t.reduce();
+		return t;
+	},
+/* convert this to hex string */
+	toString: function() 
+	{
+		return ("["+this.a.toString()+","+this.b.toString()+","+this.c.toString()+"]");
+	},
+/* convert this to byte array */
+	toBytes: function(w)
+	{
+		var i;
+		var t=[];
+		this.a.geta().getA().toBytes(t);
+		for (i=0;i<ROM.MODBYTES;i++) w[i]=t[i];
+		this.a.geta().getB().toBytes(t);
+		for (i=0;i<ROM.MODBYTES;i++) w[i+ROM.MODBYTES]=t[i];
+		this.a.getb().getA().toBytes(t);
+		for (i=0;i<ROM.MODBYTES;i++) w[i+2*ROM.MODBYTES]=t[i];
+		this.a.getb().getB().toBytes(t);
+		for (i=0;i<ROM.MODBYTES;i++) w[i+3*ROM.MODBYTES]=t[i];
+
+		this.b.geta().getA().toBytes(t);
+		for (i=0;i<ROM.MODBYTES;i++) w[i+4*ROM.MODBYTES]=t[i];
+		this.b.geta().getB().toBytes(t);
+		for (i=0;i<ROM.MODBYTES;i++) w[i+5*ROM.MODBYTES]=t[i];
+		this.b.getb().getA().toBytes(t);
+		for (i=0;i<ROM.MODBYTES;i++) w[i+6*ROM.MODBYTES]=t[i];
+		this.b.getb().getB().toBytes(t);
+		for (i=0;i<ROM.MODBYTES;i++) w[i+7*ROM.MODBYTES]=t[i];
+
+		this.c.geta().getA().toBytes(t);
+		for (i=0;i<ROM.MODBYTES;i++) w[i+8*ROM.MODBYTES]=t[i];
+		this.c.geta().getB().toBytes(t);
+		for (i=0;i<ROM.MODBYTES;i++) w[i+9*ROM.MODBYTES]=t[i];
+		this.c.getb().getA().toBytes(t);
+		for (i=0;i<ROM.MODBYTES;i++) w[i+10*ROM.MODBYTES]=t[i];
+		this.c.getb().getB().toBytes(t);
+		for (i=0;i<ROM.MODBYTES;i++) w[i+11*ROM.MODBYTES]=t[i];
+	},
+
+/* set this=this^e */
+	pow: function(e)
+	{
+		this.norm();
+		e.norm();
+		var w=new FP12(this); //w.copy(this);
+		var z=new BIG(e); //z.copy(e);
+		var r=new FP12(1);
+
+		while (true)
+		{
+			var bt=z.parity();
+			z.fshr(1);
+			if (bt==1) r.mul(w);
+			if (z.iszilch()) break;
+			w.usqr();
+		}
+		r.reduce();
+		return r;
+	},
+
+/* constant time powering by small integer of max length bts */
+	pinpow: function(e,bts)
+	{
+		var i,b;
+		var R=[];
+		R[0]=new FP12(1);
+		R[1]=new FP12(this);
+		for (i=bts-1;i>=0;i--)
+		{
+			b=(e>>i)&1;
+			R[1-b].mul(R[b]);
+			R[b].usqr();
+		}
+		this.copy(R[0]);
+	}
+};
+
+/* convert from byte array to FP12 */
+FP12.fromBytes= function(w)
+{
+	var i,a,b,c,d,e,f,g;
+	var t=[];
+
+	for (i=0;i<ROM.MODBYTES;i++) t[i]=w[i];
+	a=BIG.fromBytes(t);
+	for (i=0;i<ROM.MODBYTES;i++) t[i]=w[i+ROM.MODBYTES];
+	b=BIG.fromBytes(t);
+	c=new FP2(a,b); //c.bset(a,b);
+
+	for (i=0;i<ROM.MODBYTES;i++) t[i]=w[i+2*ROM.MODBYTES];
+	a=BIG.fromBytes(t);
+	for (i=0;i<ROM.MODBYTES;i++) t[i]=w[i+3*ROM.MODBYTES];
+	b=BIG.fromBytes(t);
+	d=new FP2(a,b); //d.bset(a,b);
+
+	e=new FP4(c,d); //e.set(c,d);
+
+	for (i=0;i<ROM.MODBYTES;i++) t[i]=w[i+4*ROM.MODBYTES];
+	a=BIG.fromBytes(t);
+	for (i=0;i<ROM.MODBYTES;i++) t[i]=w[i+5*ROM.MODBYTES];
+	b=BIG.fromBytes(t);
+	c=new FP2(a,b); //c.bset(a,b);
+
+	for (i=0;i<ROM.MODBYTES;i++) t[i]=w[i+6*ROM.MODBYTES];
+	a=BIG.fromBytes(t);
+	for (i=0;i<ROM.MODBYTES;i++) t[i]=w[i+7*ROM.MODBYTES];
+	b=BIG.fromBytes(t);
+	d=new FP2(a,b);
+
+	f=new FP4(c,d); //f.set(c,d);
+
+	for (i=0;i<ROM.MODBYTES;i++) t[i]=w[i+8*ROM.MODBYTES];
+	a=BIG.fromBytes(t);
+	for (i=0;i<ROM.MODBYTES;i++) t[i]=w[i+9*ROM.MODBYTES];
+	b=BIG.fromBytes(t);
+	c=new FP2(a,b); //c.bset(a,b);
+
+	for (i=0;i<ROM.MODBYTES;i++) t[i]=w[i+10*ROM.MODBYTES];
+	a=BIG.fromBytes(t);
+	for (i=0;i<ROM.MODBYTES;i++) t[i]=w[i+11*ROM.MODBYTES];
+	b=BIG.fromBytes(t);
+	d=new FP2(a,b); //d.bset(a,b);
+
+	g=new FP4(c,d); //g.set(c,d);
+
+	var r=new FP12(e,f,g); //r.set(e,f,g);
+
+	return r;
+};
+
+/* p=q0^u0.q1^u1.q2^u2.q3^u3 */
+/* Timing attack secure, but not cache attack secure */
+
+FP12.pow4= function(q,u)
+{
+	var i,j,nb,m;
+	var a=[];
+	var g=[];
+	var s=[];
+
+	var c=new FP12(1);
+	var p=new FP12(0);
+	var t=[];
+
+	var mt=new BIG(0);
+	var w=[];
+
+	for (i=0;i<4;i++)
+		t[i]=new BIG(u[i]);
+
+	s[0]=new FP12(0);
+	s[1]=new FP12(0);
+
+	g[0]=new FP12(q[0]); s[0].copy(q[1]); s[0].conj(); g[0].mul(s[0]);
+	g[1]=new FP12(g[0]);
+	g[2]=new FP12(g[0]);
+	g[3]=new FP12(g[0]);
+	g[4]=new FP12(q[0]); g[4].mul(q[1]);
+	g[5]=new FP12(g[4]);
+	g[6]=new FP12(g[4]);
+	g[7]=new FP12(g[4]);
+
+	s[1].copy(q[2]); s[0].copy(q[3]); s[0].conj(); s[1].mul(s[0]);
+	s[0].copy(s[1]); s[0].conj(); g[1].mul(s[0]);
+	g[2].mul(s[1]);
+	g[5].mul(s[0]);
+	g[6].mul(s[1]);
+	s[1].copy(q[2]); s[1].mul(q[3]);
+	s[0].copy(s[1]); s[0].conj(); g[0].mul(s[0]);
+	g[3].mul(s[1]);
+	g[4].mul(s[0]);
+	g[7].mul(s[1]);
+
+/* if power is even add 1 to power, and add q to correction */
+
+	for (i=0;i<4;i++)
+	{
+		if (t[i].parity()==0)
+		{
+			t[i].inc(1); t[i].norm();
+			c.mul(q[i]);
+		}
+		mt.add(t[i]); mt.norm();
+	}
+	c.conj();
+	nb=1+mt.nbits();
+
+/* convert exponent to signed 1-bit window */
+	for (j=0;j<nb;j++)
+	{
+		for (i=0;i<4;i++)
+		{
+			a[i]=(t[i].lastbits(2)-2);
+			t[i].dec(a[i]); t[i].norm(); 
+			t[i].fshr(1);
+		}
+		w[j]=(8*a[0]+4*a[1]+2*a[2]+a[3]);
+	}
+	w[nb]=(8*t[0].lastbits(2)+4*t[1].lastbits(2)+2*t[2].lastbits(2)+t[3].lastbits(2));
+	p.copy(g[Math.floor((w[nb]-1)/2)]);  
+
+	for (i=nb-1;i>=0;i--)
+	{
+		m=w[i]>>31;
+		j=(w[i]^m)-m;  /* j=abs(w[i]) */
+		j=(j-1)/2;
+		s[0].copy(g[j]); s[1].copy(g[j]); s[1].conj();
+		p.usqr();
+		p.mul(s[m&1]);
+	}
+	p.mul(c);  /* apply correction */
+	p.reduce();
+	return p;
+};
+
diff --git a/version22/js/FP2.js b/version22/js/FP2.js
new file mode 100644
index 0000000..a7b4e95
--- /dev/null
+++ b/version22/js/FP2.js
@@ -0,0 +1,321 @@
+/*
+	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.
+*/
+
+/* Finite Field arithmetic  Fp^2 functions */
+
+/* FP2 elements are of the form a+ib, where i is sqrt(-1) */
+
+/* general purpose constructor */
+var FP2 =function(c,d)
+{
+	if (c instanceof FP2)
+	{
+		this.a=new FP(c.a);
+		this.b=new FP(c.b);
+	}
+	else
+	{
+		this.a=new FP(c);
+		this.b=new FP(d);
+	}
+};
+
+FP2.prototype={
+/* reduce components mod Modulus */
+	reduce: function()
+	{
+		this.a.reduce();
+		this.b.reduce();
+	},
+/* normalise components of w */
+	norm: function()
+	{
+		this.a.norm();
+		this.b.norm();
+	},
+/* test this=0 ? */
+	iszilch: function() 
+	{
+		this.reduce();
+		return (this.a.iszilch() && this.b.iszilch());
+	},
+/* test this=1 ? */
+	isunity: function() 
+	{
+		var one=new FP(1);
+		return (this.a.equals(one) && this.b.iszilch());
+	},
+/* conditional copy of g to this depending on d */
+	cmove:function(g,d)
+	{
+		this.a.cmove(g.a,d);
+		this.b.cmove(g.b,d);
+	},
+
+/* test this=x */
+	equals: function(x) {
+		return (this.a.equals(x.a) && this.b.equals(x.b));
+	},
+/* extract a */
+	getA: function()
+	{ 
+		return this.a.redc();
+	},
+/* extract b */
+	getB: function()
+	{
+		return this.b.redc();
+	},
+
+/* set from pair of FPs */
+	set: function(c,d)
+	{
+		this.a.copy(c);
+		this.b.copy(d);
+	},
+/* set a */
+	seta: function(c)
+	{
+		this.a.copy(c);
+		this.b.zero();
+	},
+
+/* set from two BIGs */
+	bset: function(c,d)
+	{
+		this.a.bcopy(c);
+		this.b.bcopy(d);
+	},
+
+/* set from one BIG */
+	bseta: function(c)
+	{
+		this.a.bcopy(c);
+		this.b.zero();		
+	},
+/* copy this=x */
+	copy: function(x)
+	{
+		this.a.copy(x.a);
+		this.b.copy(x.b);
+	},
+/* set this=0 */
+	zero: function()
+	{
+		this.a.zero();
+		this.b.zero();
+	},
+/* set this=1 */
+	one: function()
+	{
+		this.a.one();
+		this.b.zero();
+	},
+/* negate this */
+	neg: function()
+	{
+		this.norm();
+		var m=new FP(this.a); 
+		var t=new FP(0);
+
+		m.add(this.b);
+		m.neg();
+		m.norm();
+		t.copy(m); t.add(this.b);
+		this.b.copy(m);
+		this.b.add(this.a);
+		this.a.copy(t);
+		//this.norm();
+	},
+/* conjugate this */
+	conj: function()
+	{
+		this.b.neg();
+	},
+/* this+=a */
+	add: function(x)
+	{
+		this.a.add(x.a);
+		this.b.add(x.b);
+	},
+/* this-=x */
+	sub: function(x)
+	{
+		var m=new FP2(x); //var m=new FP2(0); m.copy(x);
+		m.neg();
+		this.add(m);
+	},
+/* this*=s, where s is FP */
+	pmul: function(s)
+	{
+		this.a.mul(s);
+		this.b.mul(s);
+	},
+/* this*=c, where s is int */
+	imul: function(c)
+	{
+		this.a.imul(c);
+		this.b.imul(c);
+	},
+/* this*=this */
+	sqr: function()
+	{
+		this.norm();
+
+		var w1=new FP(this.a); 
+		var w3=new FP(this.a); 
+		var mb=new FP(this.b); 
+
+		w3.mul(this.b);
+		w1.add(this.b);
+		mb.neg();
+		this.a.add(mb);
+		this.a.mul(w1);
+		this.b.copy(w3); this.b.add(w3);
+		this.norm();
+	},
+/* this*=y */
+	mul: function(y)
+	{
+		this.norm();  // This is needed here as {a,b} is not normed before additions
+
+		var w1=new FP(this.a); 
+		var w2=new FP(this.b); 
+		var w5=new FP(this.a); 
+		var mw=new FP(0);
+
+		w1.mul(y.a);  // w1=a*y.a  - this norms w1 and y.a, NOT a
+		w2.mul(y.b);  // w2=b*y.b  - this norms w2 and y.b, NOT b
+		w5.add(this.b);    // w5=a+b
+		this.b.copy(y.a); this.b.add(y.b); // b=y.a+y.b
+
+		this.b.mul(w5);
+		mw.copy(w1); mw.add(w2); mw.neg();
+
+		this.b.add(mw); mw.add(w1);
+		this.a.copy(w1); this.a.add(mw);
+
+		this.norm();
+	},
+
+/* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */
+/* returns true if this is QR */
+	sqrt: function()
+	{
+		if (this.iszilch()) return true;
+		var w1=new FP(this.b);
+		var w2=new FP(this.a);
+
+		w1.sqr(); w2.sqr(); w1.add(w2);
+		if (w1.jacobi()!=1) { this.zero(); return false; }
+		w1=w1.sqrt();
+		w2.copy(this.a); w2.add(w1); w2.div2();
+		if (w2.jacobi()!=1)
+		{
+			w2.copy(this.a); w2.sub(w1); w2.div2();
+			if (w2.jacobi()!=1) { this.zero(); return false; }
+		}
+		w2=w2.sqrt();
+		this.a.copy(w2);
+		w2.add(w2);
+		w2.inverse();
+		this.b.mul(w2);
+		return true;
+	},
+
+/* convert this to hex string */
+	toString: function() 
+	{
+		return ("["+this.a.toString()+","+this.b.toString()+"]");
+	},
+/* this=1/this */
+	inverse: function()
+	{
+		this.norm();
+		var w1=new FP(this.a); 
+		var w2=new FP(this.b); 
+		w1.sqr();
+		w2.sqr();
+		w1.add(w2);
+		w1.inverse();
+		this.a.mul(w1);
+		w1.neg();
+		this.b.mul(w1);
+	},
+/* this/=2 */
+	div2: function()
+	{
+		this.a.div2();
+		this.b.div2();
+	},
+/* this*=sqrt(-1) */
+	times_i: function()
+	{
+		var z=new FP(this.a); //z.copy(this.a);
+		this.a.copy(this.b); this.a.neg();
+		this.b.copy(z);
+	},
+
+/* w*=(1+sqrt(-1)) */
+/* where X*2-(1+sqrt(-1)) is irreducible for FP4, assumes p=3 mod 8 */
+	mul_ip: function()
+	{
+		this.norm();
+		var t=new FP2(this);// t.copy(this);
+		var z=new FP(this.a); //z.copy(this.a);
+		this.a.copy(this.b);
+		this.a.neg();
+		this.b.copy(z);
+		this.add(t);
+		this.norm();
+	},
+
+/* w/=(1+sqrt(-1)) */
+	div_ip: function()
+	{
+		var t=new FP2(0);
+		this.norm();
+		t.a.copy(this.a); t.a.add(this.b);
+		t.b.copy(this.b); t.b.sub(this.a);
+		this.copy(t);
+		this.div2();
+	},
+/* this=this^e */
+	pow: function(e)
+	{
+		var bt;
+		var r=new FP2(1);
+		this.norm();
+		var x=new FP2(this); //x.copy(this);
+		e.norm();
+		while (true)
+		{
+			bt=e.parity();
+			e.fshr(1);
+			if (bt==1) r.mul(x);
+			if (e.iszilch()) break;
+			x.sqr();
+		}
+
+		r.reduce();
+		return r;
+	}
+
+};
+
diff --git a/version22/js/FP4.js b/version22/js/FP4.js
new file mode 100644
index 0000000..640ac63
--- /dev/null
+++ b/version22/js/FP4.js
@@ -0,0 +1,501 @@
+/*
+	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.
+*/
+
+/* Finite Field arithmetic  Fp^4 functions */
+
+/* FP4 elements are of the form a+ib, where i is sqrt(-1+sqrt(-1))  */
+
+/* general purpose constructor */
+var FP4=function(c,d) 
+{
+	if (c instanceof FP4)
+	{
+		this.a=new FP2(c.a);
+		this.b=new FP2(c.b);
+	}
+	else
+	{
+		this.a=new FP2(c);
+		this.b=new FP2(d);
+	}
+};
+
+FP4.prototype={
+/* reduce all components of this mod Modulus */
+	reduce: function()
+	{
+		this.a.reduce();
+		this.b.reduce();
+	},
+/* normalise all components of this mod Modulus */
+	norm: function()
+	{
+		this.a.norm();
+		this.b.norm();
+	},
+/* test this==0 ? */
+	iszilch: function() 
+	{
+		this.reduce();
+		return (this.a.iszilch() && this.b.iszilch());
+	},
+/* test this==1 ? */
+	isunity: function() 
+	{
+		var one=new FP2(1);
+		return (this.a.equals(one) && this.b.iszilch());
+	},
+/* test is w real? That is in a+ib test b is zero */
+	isreal: function()
+	{
+		return this.b.iszilch();
+	},
+/* extract real part a */
+	real: function()
+	{
+		return this.a;
+	},
+
+	geta: function()
+	{
+		return this.a;
+	},
+/* extract imaginary part b */
+	getb: function()
+	{
+		return this.b;
+	},
+/* test this=x? */
+	equals: function(x)
+	{
+		return (this.a.equals(x.a) && this.b.equals(x.b));
+	},
+/* copy this=x */
+	copy: function(x)
+	{
+		this.a.copy(x.a);
+		this.b.copy(x.b);
+	},
+/* this=0 */
+	zero: function()
+	{
+		this.a.zero();
+		this.b.zero();
+	},
+/* this=1 */
+	one: function()
+	{
+		this.a.one();
+		this.b.zero();
+	},
+
+/* set from two FP2s */
+	set: function(c,d)
+	{
+		this.a.copy(c);
+		this.b.copy(d);
+	},
+/* set a */
+	seta: function(c)
+	{
+		this.a.copy(c);
+		this.b.zero();
+	},
+/* this=-this */
+	neg: function()
+	{
+		var m=new FP2(this.a); //m.copy(this.a);
+		var t=new FP2(0);
+		m.add(this.b);
+		m.neg();
+		m.norm();
+		t.copy(m); t.add(this.b);
+		this.b.copy(m);
+		this.b.add(this.a);
+		this.a.copy(t);
+	},
+/* this=conjugate(this) */
+	conj: function()
+	{
+		this.b.neg(); this.b.norm();
+	},
+/* this=-conjugate(this) */
+	nconj: function()
+	{
+		this.a.neg(); this.a.norm();
+	},
+/* this+=x */
+	add: function(x)
+	{
+		this.a.add(x.a);
+		this.b.add(x.b);
+	},
+/* this-=x */
+	sub: function(x)
+	{
+		var m=new FP4(x); // m.copy(x); 
+		m.neg();
+		this.add(m);
+	},
+/* this*=s where s is FP2 */
+	pmul: function(s)
+	{
+		this.a.mul(s);
+		this.b.mul(s);
+	},
+/* this*=c where s is int */
+	imul: function(c)
+	{
+		this.a.imul(c);
+		this.b.imul(c);
+	},
+/* this*=this */
+	sqr: function()
+	{
+		this.norm();
+
+		var t1=new FP2(this.a); //t1.copy(this.a);
+		var t2=new FP2(this.b); //t2.copy(this.b);
+		var t3=new FP2(this.a); //t3.copy(this.a);
+
+		t3.mul(this.b);
+		t1.add(this.b);
+		t2.mul_ip();
+
+		t2.add(this.a);
+		this.a.copy(t1);
+
+		this.a.mul(t2);
+
+		t2.copy(t3);
+		t2.mul_ip();
+		t2.add(t3);
+
+		t2.neg();
+
+		this.a.add(t2);
+
+		this.b.copy(t3);
+		this.b.add(t3);
+
+		this.norm();
+	},
+/* this*=y */
+	mul: function(y)
+	{
+		this.norm();
+
+		var t1=new FP2(this.a); //t1.copy(this.a);
+		var t2=new FP2(this.b); //t2.copy(this.b);
+		var t3=new FP2(0);
+		var t4=new FP2(this.b); //t4.copy(this.b);
+
+		t1.mul(y.a);
+		t2.mul(y.b);
+		t3.copy(y.b);
+		t3.add(y.a);
+		t4.add(this.a);
+
+		t4.mul(t3);
+		t4.sub(t1);
+
+		this.b.copy(t4);
+		this.b.sub(t2);
+		t2.mul_ip();
+		this.a.copy(t2);
+		this.a.add(t1);
+
+		this.norm();
+	},
+/* convert to hex string */
+	toString: function() 
+	{
+		return ("["+this.a.toString()+","+this.b.toString()+"]");
+	},
+/* this=1/this */
+	inverse: function()
+	{
+		this.norm();
+
+		var t1=new FP2(this.a); //t1.copy(this.a);
+		var t2=new FP2(this.b);// t2.copy(this.b);
+
+		t1.sqr();
+		t2.sqr();
+		t2.mul_ip();
+		t1.sub(t2);
+		t1.inverse();
+		this.a.mul(t1);
+		t1.neg();
+		this.b.mul(t1);
+	},
+
+/* this*=i where i = sqrt(-1+sqrt(-1)) */
+	times_i: function()
+	{
+		var s=new FP2(this.b); //s.copy(this.b);
+		var t=new FP2(this.b); //t.copy(this.b);
+		s.times_i();
+		t.add(s);
+		this.b.copy(this.a);
+		this.a.copy(t);
+	},
+
+/* this=this^q using Frobenius, where q is Modulus */
+	frob: function(f)
+	{
+		this.a.conj();
+		this.b.conj();
+		this.b.mul(f);
+	},
+
+/* this=this^e */
+	pow: function(e)
+	{
+		this.norm();
+		e.norm();
+		var w=new FP4(this); //w.copy(this);
+		var z=new BIG(e); //z.copy(e);
+		var r=new FP4(1);
+		while (true)
+		{
+			var bt=z.parity();
+			z.fshr(1);
+			if (bt==1) r.mul(w);
+			if (z.iszilch()) break;
+			w.sqr();
+		}
+		r.reduce();
+		return r;
+	},
+
+/* XTR xtr_a function */
+	xtr_A: function(w,y,z) 
+	{
+		var r=new FP4(w); //r.copy(w);
+		var t=new FP4(w); //t.copy(w);
+		r.sub(y);
+		r.pmul(this.a);
+		t.add(y);
+		t.pmul(this.b);
+		t.times_i();
+
+		this.copy(r);
+		this.add(t);
+		this.add(z);
+
+		this.norm();
+	},
+/* XTR xtr_d function */
+	xtr_D: function() 
+	{
+		var w=new FP4(this); //w.copy(this);
+		this.sqr(); w.conj();
+		w.add(w);
+		this.sub(w);
+		this.reduce();
+	},
+/* r=x^n using XTR method on traces of FP12s */
+	xtr_pow: function(n) 
+	{
+		var a=new FP4(3);
+		var b=new FP4(this);  
+		var c=new FP4(b); 
+		c.xtr_D();
+		var t=new FP4(0);
+		var r=new FP4(0);
+
+		n.norm();
+		var par=n.parity();
+		var v=new BIG(n); v.fshr(1);
+		if (par===0) {v.dec(1); v.norm();}
+
+		var nb=v.nbits();
+		for (var i=nb-1;i>=0;i--)
+		{
+			if (v.bit(i)!=1)
+			{
+				t.copy(b);
+				this.conj();
+				c.conj();
+				b.xtr_A(a,this,c);
+				this.conj();
+				c.copy(t);
+				c.xtr_D();
+				a.xtr_D();
+			}
+			else
+			{
+				t.copy(a); t.conj();
+				a.copy(b);
+				a.xtr_D();
+				b.xtr_A(c,this,t);
+				c.xtr_D();
+			}
+		}
+		if (par===0) r.copy(c);
+		else r.copy(b);
+		r.reduce();
+		return r;
+	},
+
+/* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */
+	xtr_pow2: function(ck,ckml,ckm2l,a,b)
+	{
+		a.norm(); b.norm();
+		var e=new BIG(a); //e.copy(a);
+		var d=new BIG(b); //d.copy(b);
+		var w=new BIG(0);
+
+		var cu=new FP4(ck); //cu.copy(ck); // can probably be passed in w/o copying
+		var cv=new FP4(this); //cv.copy(this);
+		var cumv=new FP4(ckml); //cumv.copy(ckml);
+		var cum2v=new FP4(ckm2l); //cum2v.copy(ckm2l);
+		var r=new FP4(0);
+		var t=new FP4(0);
+
+		var f2=0;
+		while (d.parity()===0 && e.parity()===0)
+		{
+			d.fshr(1);
+			e.fshr(1);
+			f2++;
+		}
+
+		while (BIG.comp(d,e)!==0)
+		{
+			if (BIG.comp(d,e)>0)
+			{
+				w.copy(e); w.imul(4); w.norm();
+				if (BIG.comp(d,w)<=0)
+				{
+					w.copy(d); d.copy(e);
+					e.rsub(w); e.norm();
+
+					t.copy(cv); 
+					t.xtr_A(cu,cumv,cum2v);
+					cum2v.copy(cumv); 
+					cum2v.conj();
+					cumv.copy(cv);
+					cv.copy(cu);
+					cu.copy(t);
+
+				}
+				else if (d.parity()===0)
+				{
+					d.fshr(1);
+					r.copy(cum2v); r.conj();
+					t.copy(cumv);
+					t.xtr_A(cu,cv,r);
+					cum2v.copy(cumv);
+					cum2v.xtr_D();
+					cumv.copy(t);
+					cu.xtr_D();
+				}
+				else if (e.parity()==1)
+				{
+					d.sub(e); d.norm();
+					d.fshr(1);
+					t.copy(cv);
+					t.xtr_A(cu,cumv,cum2v);
+					cu.xtr_D();
+					cum2v.copy(cv);
+					cum2v.xtr_D();
+					cum2v.conj();
+					cv.copy(t);
+				}
+				else
+				{
+					w.copy(d);
+					d.copy(e); d.fshr(1);
+					e.copy(w);
+					t.copy(cumv);
+					t.xtr_D();
+					cumv.copy(cum2v); cumv.conj();
+					cum2v.copy(t); cum2v.conj();
+					t.copy(cv);
+					t.xtr_D();
+					cv.copy(cu);
+					cu.copy(t);
+				}
+			}
+			if (BIG.comp(d,e)<0)
+			{
+				w.copy(d); w.imul(4); w.norm();
+				if (BIG.comp(e,w)<=0)
+				{
+					e.sub(d); e.norm();
+					t.copy(cv);
+					t.xtr_A(cu,cumv,cum2v);
+					cum2v.copy(cumv);
+					cumv.copy(cu);
+					cu.copy(t);
+				}
+				else if (e.parity()===0)
+				{
+					w.copy(d);
+					d.copy(e); d.fshr(1);
+					e.copy(w);
+					t.copy(cumv);
+					t.xtr_D();
+					cumv.copy(cum2v); cumv.conj();
+					cum2v.copy(t); cum2v.conj();
+					t.copy(cv);
+					t.xtr_D();
+					cv.copy(cu);
+					cu.copy(t);
+				}
+				else if (d.parity()==1)
+				{
+					w.copy(e);
+					e.copy(d);
+					w.sub(d); w.norm();
+					d.copy(w); d.fshr(1);
+					t.copy(cv);
+					t.xtr_A(cu,cumv,cum2v);
+					cumv.conj();
+					cum2v.copy(cu);
+					cum2v.xtr_D();
+					cum2v.conj();
+					cu.copy(cv);
+					cu.xtr_D();
+					cv.copy(t);
+				}
+				else
+				{
+					d.fshr(1);
+					r.copy(cum2v); r.conj();
+					t.copy(cumv);
+					t.xtr_A(cu,cv,r);
+					cum2v.copy(cumv);
+					cum2v.xtr_D();
+					cumv.copy(t);
+					cu.xtr_D();
+				}
+			}
+		}
+		r.copy(cv);
+		r.xtr_A(cu,cumv,cum2v);
+		for (var i=0;i<f2;i++)
+			r.xtr_D();
+		r=r.xtr_pow(d);
+		return r;
+	}
+
+};
diff --git a/version22/js/GCM.js b/version22/js/GCM.js
new file mode 100644
index 0000000..16482d0
--- /dev/null
+++ b/version22/js/GCM.js
@@ -0,0 +1,305 @@
+/*
+	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.
+*/
+
+/*
+ * Implementation of the AES-GCM Encryption/Authentication
+ *
+ * Some restrictions.. 
+ * 1. Only for use with AES
+ * 2. Returned tag is always 128-bits. Truncate at your own risk.
+ * 3. The order of function calls must follow some rules
+ *
+ * Typical sequence of calls..
+ * 1. call GCM_init
+ * 2. call GCM_add_header any number of times, as long as length of header is multiple of 16 bytes (block size)
+ * 3. call GCM_add_header one last time with any length of header
+ * 4. call GCM_add_cipher any number of times, as long as length of cipher/plaintext is multiple of 16 bytes
+ * 5. call GCM_add_cipher one last time with any length of cipher/plaintext
+ * 6. call GCM_finish to extract the tag.
+ *
+ * See http://www.mindspring.com/~dmcgrew/gcm-nist-6.pdf
+ */
+
+var GCM = function() {
+	this.table=new Array(128);
+	for (var i=0;i<128;i++)
+		this.table[i]=new Array(4);  /* 2k bytes */
+	this.stateX=[];
+	this.Y_0=[];
+	this.counter=0;
+	this.lenA=[];
+	this.lenC=[];
+	this.status=0;
+	this.a=new AES();
+};
+
+GCM.prototype={
+
+	precompute: function(H)
+	{
+		var i,j,c;
+		var b=[];
+
+		for (i=j=0;i<4;i++,j+=4) 
+		{
+			b[0]=H[j]; b[1]=H[j+1]; b[2]=H[j+2]; b[3]=H[j+3];
+			this.table[0][i]=GCM.pack(b);
+		}
+		for (i=1;i<128;i++)
+		{
+			c=0;
+			for (j=0;j<4;j++) 
+			{
+				this.table[i][j]=c|(this.table[i-1][j])>>>1; 
+				c=this.table[i-1][j]<<31;
+			}
+			if (c!==0) this.table[i][0]^=0xE1000000; /* irreducible polynomial */
+		}
+	},
+
+	gf2mul: function()
+	{ /* gf2m mul - Z=H*X mod 2^128 */
+		var i,j,m,k;
+		var P=[];
+		var c;
+		var b=[];
+
+		P[0]=P[1]=P[2]=P[3]=0;
+		j=8; m=0;
+		for (i=0;i<128;i++)
+		{
+			c=(this.stateX[m]>>>(--j))&1; c=~c+1;
+			for (k=0;k<4;k++) P[k]^=(this.table[i][k]&c);
+			if (j===0)
+			{
+				j=8; m++;
+				if (m==16) break;
+			}
+		}
+		for (i=j=0;i<4;i++,j+=4) 
+		{
+			b=GCM.unpack(P[i]);
+			this.stateX[j]=b[0]; this.stateX[j+1]=b[1]; this.stateX[j+2]=b[2]; this.stateX[j+3]=b[3];
+		}
+	},
+
+	wrap: function()
+	{ /* Finish off GHASH */
+		var i,j;
+		var F=[];
+		var L=[];
+		var b=[];
+
+/* convert lengths from bytes to bits */
+		F[0]=(this.lenA[0]<<3)|(this.lenA[1]&0xE0000000)>>>29;
+		F[1]=this.lenA[1]<<3;
+		F[2]=(this.lenC[0]<<3)|(this.lenC[1]&0xE0000000)>>>29;
+		F[3]=this.lenC[1]<<3;
+		for (i=j=0;i<4;i++,j+=4)
+		{
+			b=GCM.unpack(F[i]);
+			L[j]=b[0]; L[j+1]=b[1]; L[j+2]=b[2]; L[j+3]=b[3];
+		}
+		for (i=0;i<16;i++) this.stateX[i]^=L[i];
+		this.gf2mul();
+	},
+
+/* Initialize GCM mode */
+	init: function(nk,key,niv,iv)
+	{ /* iv size niv is usually 12 bytes (96 bits). AES key size nk can be 16,24 or 32 bytes */
+		var i;
+		var H=[];
+		var b=[];
+
+		for (i=0;i<16;i++) {H[i]=0; this.stateX[i]=0;}
+
+		this.a.init(ROM.ECB,nk,key,iv);
+		this.a.ecb_encrypt(H);     /* E(K,0) */
+		this.precompute(H);
+	
+		this.lenA[0]=this.lenC[0]=this.lenA[1]=this.lenC[1]=0;
+		if (niv==12)
+		{
+			for (i=0;i<12;i++) this.a.f[i]=iv[i];
+			b=GCM.unpack(1);
+			this.a.f[12]=b[0]; this.a.f[13]=b[1]; this.a.f[14]=b[2]; this.a.f[15]=b[3];  /* initialise IV */
+			for (i=0;i<16;i++) this.Y_0[i]=this.a.f[i];
+		}
+		else
+		{
+			this.status=ROM.GCM_ACCEPTING_CIPHER;
+			this.ghash(iv,niv); /* GHASH(H,0,IV) */
+			this.wrap();
+			for (i=0;i<16;i++) {this.a.f[i]=this.stateX[i];this.Y_0[i]=this.a.f[i];this.stateX[i]=0;}
+			this.lenA[0]=this.lenC[0]=this.lenA[1]=this.lenC[1]=0;
+		}
+		this.status=ROM.GCM_ACCEPTING_HEADER;
+	},
+
+/* Add Header data - included but not encrypted */
+	add_header: function(header,len)
+	{ /* Add some header. Won't be encrypted, but will be authenticated. len is length of header */
+		var i,j=0;
+		if (this.status!=ROM.GCM_ACCEPTING_HEADER) return false;
+
+		while (j<len)
+		{
+			for (i=0;i<16 && j<len;i++)
+			{
+				this.stateX[i]^=header[j++];
+				this.lenA[1]++; this.lenA[1]|=0; if (this.lenA[1]===0) this.lenA[0]++;
+			}
+			this.gf2mul();
+		}
+		if (len%16!==0) this.status=ROM.GCM_ACCEPTING_CIPHER;
+		return true;
+	},
+
+	ghash: function(plain,len)
+	{
+		var i,j=0;
+
+		if (this.status==ROM.GCM_ACCEPTING_HEADER) this.status=ROM.GCM_ACCEPTING_CIPHER;
+		if (this.status!=ROM.GCM_ACCEPTING_CIPHER) return false;
+		
+		while (j<len)
+		{
+			for (i=0;i<16 && j<len;i++)
+			{
+				this.stateX[i]^=plain[j++];
+				this.lenC[1]++; this.lenC[1]|=0; if (this.lenC[1]===0) this.lenC[0]++;
+			}
+			this.gf2mul();
+		}
+		if (len%16!==0) this.status=ROM.GCM_NOT_ACCEPTING_MORE;
+		return true;
+	},
+
+/* Add Plaintext - included and encrypted */
+	add_plain: function(plain,len)
+	{
+		var i,j=0;
+		var B=[];
+		var b=[];
+		var cipher=[];
+
+		if (this.status==ROM.GCM_ACCEPTING_HEADER) this.status=ROM.GCM_ACCEPTING_CIPHER;
+		if (this.status!=ROM.GCM_ACCEPTING_CIPHER) return cipher;
+		
+		while (j<len)
+		{
+
+			b[0]=this.a.f[12]; b[1]=this.a.f[13]; b[2]=this.a.f[14]; b[3]=this.a.f[15];
+			this.counter=GCM.pack(b);
+			this.counter++;
+			b=GCM.unpack(this.counter);
+			this.a.f[12]=b[0]; this.a.f[13]=b[1]; this.a.f[14]=b[2]; this.a.f[15]=b[3]; /* increment counter */
+			for (i=0;i<16;i++) B[i]=this.a.f[i];
+			this.a.ecb_encrypt(B);        /* encrypt it  */
+		
+			for (i=0;i<16 && j<len;i++)
+			{
+				cipher[j]=(plain[j]^B[i]);
+				this.stateX[i]^=cipher[j++];
+				this.lenC[1]++; this.lenC[1]|=0; if (this.lenC[1]===0) this.lenC[0]++;
+			}
+			this.gf2mul();
+		}
+		if (len%16!==0) this.status=ROM.GCM_NOT_ACCEPTING_MORE;
+		return cipher;
+	},
+
+/* Add Ciphertext - decrypts to plaintext */
+	add_cipher: function(cipher,len)
+	{
+		var i,j=0;
+		var B=[];
+		var b=[];
+		var plain=[];
+
+		if (this.status==ROM.GCM_ACCEPTING_HEADER) this.status=ROM.GCM_ACCEPTING_CIPHER;
+		if (this.status!=ROM.GCM_ACCEPTING_CIPHER) return plain;
+	
+		while (j<len)
+		{
+			b[0]=this.a.f[12]; b[1]=this.a.f[13]; b[2]=this.a.f[14]; b[3]=this.a.f[15];
+			this.counter=GCM.pack(b);
+			this.counter++;
+			b=GCM.unpack(this.counter);
+			this.a.f[12]=b[0]; this.a.f[13]=b[1]; this.a.f[14]=b[2]; this.a.f[15]=b[3]; /* increment counter */
+			for (i=0;i<16;i++) B[i]=this.a.f[i];
+			this.a.ecb_encrypt(B);        /* encrypt it  */
+			for (i=0;i<16 && j<len;i++)
+			{
+				var oc=cipher[j];
+				plain[j]=(cipher[j]^B[i]);
+				this.stateX[i]^=oc; j++;
+				this.lenC[1]++; this.lenC[1]|=0; if (this.lenC[1]===0) this.lenC[0]++;
+			}
+			this.gf2mul();
+		}
+		if (len%16!==0) this.status=ROM.GCM_NOT_ACCEPTING_MORE;
+		return plain;
+	},
+
+/* Finish and extract Tag */
+	finish: function(extract)
+	{ /* Finish off GHASH and extract tag (MAC) */
+		var i;
+		var tag=[];
+
+		this.wrap();
+/* extract tag */
+		if (extract)
+		{
+			this.a.ecb_encrypt(this.Y_0);        /* E(K,Y0) */
+			for (i=0;i<16;i++) this.Y_0[i]^=this.stateX[i];
+			for (i=0;i<16;i++) {tag[i]=this.Y_0[i];this.Y_0[i]=this.stateX[i]=0;}
+		}
+		this.status=ROM.GCM_FINISHED;
+		this.a.end();
+		return tag;
+	}
+
+};
+
+GCM.pack= function(b)
+{ /* pack 4 bytes into a 32-bit Word */
+		return (((b[0])&0xff)<<24)|((b[1]&0xff)<<16)|((b[2]&0xff)<<8)|(b[3]&0xff);
+};
+
+GCM.unpack=function(a)
+{ /* unpack bytes from a word */
+	var b=[];
+	b[3]=(a&0xff);
+	b[2]=((a>>>8)&0xff);
+	b[1]=((a>>>16)&0xff);
+	b[0]=((a>>>24)&0xff);
+	return b;
+};
+
+GCM.hex2bytes=function(s) 
+{
+	var len = s.length;
+	var data = [];
+	for (var i = 0; i < len; i += 2) 
+		data[i / 2] = parseInt(s.substr(i,2),16);
+
+	return data;
+};
diff --git a/version22/js/HASH256.js b/version22/js/HASH256.js
new file mode 100644
index 0000000..a683916
--- /dev/null
+++ b/version22/js/HASH256.js
@@ -0,0 +1,180 @@
+/*
+	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.
+*/
+
+var HASH256 = function() {
+	this.length=[];
+	this.h=[];
+	this.w=[];
+	this.init();
+};
+
+HASH256.prototype={
+
+	/* functions */
+
+	transform: function()
+	{ /* basic transformation step */
+		var a,b,c,d,e,f,g,hh,t1,t2;
+		var j;
+		for (j=16;j<64;j++) 
+			this.w[j]=(HASH256.theta1(this.w[j-2])+this.w[j-7]+HASH256.theta0(this.w[j-15])+this.w[j-16])|0; 
+
+		a=this.h[0]; b=this.h[1]; c=this.h[2]; d=this.h[3]; 
+		e=this.h[4]; f=this.h[5]; g=this.h[6]; hh=this.h[7];
+
+		for (j=0;j<64;j++)
+		{ /* 64 times - mush it up */
+			t1=(hh+HASH256.Sig1(e)+HASH256.Ch(e,f,g)+HASH256.HK[j]+this.w[j])|0;  
+			t2=(HASH256.Sig0(a)+HASH256.Maj(a,b,c))|0; 
+			hh=g; g=f; f=e;
+			e=(d+t1)|0; // Need to knock these back down to prevent 52-bit overflow
+			d=c;
+			c=b;
+			b=a;
+			a=(t1+t2)|0;    
+
+		}
+		this.h[0]+=a; this.h[1]+=b; this.h[2]+=c; this.h[3]+=d; 
+		this.h[4]+=e; this.h[5]+=f; this.h[6]+=g; this.h[7]+=hh; 
+
+	},
+
+/* Initialise Hash function */
+	init: function()
+	{ /* initialise */
+		var i;
+		for (i=0;i<64;i++) this.w[i]=0;
+		this.length[0]=this.length[1]=0;
+		this.h[0]=HASH256.H[0];
+		this.h[1]=HASH256.H[1];
+		this.h[2]=HASH256.H[2];
+		this.h[3]=HASH256.H[3];
+		this.h[4]=HASH256.H[4];
+		this.h[5]=HASH256.H[5];
+		this.h[6]=HASH256.H[6];
+		this.h[7]=HASH256.H[7];
+	},
+
+/* process a single byte */
+	process: function(byt)
+	{ /* process the next message byte */
+		var cnt;
+
+		cnt=(this.length[0]>>>5)%16;
+		this.w[cnt]<<=8;
+		this.w[cnt]|=(byt&0xFF);
+		this.length[0]+=8;
+		if ((this.length[0]&0xffffffff)===0) { this.length[1]++; this.length[0]=0; }
+		if ((this.length[0]%512)===0) this.transform();
+	},
+
+/* process an array of bytes */	
+	process_array: function(b)
+	{
+		for (var i=0;i<b.length;i++) this.process(b[i]);
+	},
+
+/* process a 32-bit integer */
+	process_num: function(n)
+	{
+		this.process((n>>24)&0xff);
+		this.process((n>>16)&0xff);
+		this.process((n>>8)&0xff);
+		this.process(n&0xff);
+	},
+
+	hash: function()
+	{ /* pad message and finish - supply digest */
+		var i;
+		var digest=[];
+		var len0,len1;
+		len0=this.length[0];
+		len1=this.length[1];
+		this.process(0x80);
+		while ((this.length[0]%512)!=448) this.process(0);
+
+		this.w[14]=len1;
+		this.w[15]=len0;    
+		this.transform();
+
+		for (i=0;i<HASH256.len;i++)
+		{ /* convert to bytes */
+			digest[i]=((this.h[i>>>2]>>(8*(3-i%4))) & 0xff);
+		}
+		this.init();
+		return digest;
+	}
+};
+
+/* static functions */
+
+HASH256.S= function(n,x)
+{
+	return (((x)>>>n) | ((x)<<(32-n)));
+};
+
+HASH256.R= function(n,x)
+{
+	return ((x)>>>n);
+};
+
+HASH256.Ch= function(x,y,z)
+{
+	return ((x&y)^(~(x)&z));
+};
+
+HASH256.Maj= function(x,y,z)
+{
+	return ((x&y)^(x&z)^(y&z));
+};
+
+HASH256.Sig0= function(x)
+{
+	return (HASH256.S(2,x)^HASH256.S(13,x)^HASH256.S(22,x));
+};
+
+HASH256.Sig1= function(x)
+{
+	return (HASH256.S(6,x)^HASH256.S(11,x)^HASH256.S(25,x));
+};
+
+HASH256.theta0= function(x)
+{
+	return (HASH256.S(7,x)^HASH256.S(18,x)^HASH256.R(3,x));
+};
+
+HASH256.theta1= function(x)
+{
+	return (HASH256.S(17,x)^HASH256.S(19,x)^HASH256.R(10,x));
+};
+
+/* constants */
+HASH256.len= 32;
+
+HASH256.H = [0x6A09E667,0xBB67AE85,0x3C6EF372,0xA54FF53A,0x510E527F,0x9B05688C,0x1F83D9AB,0x5BE0CD19];
+
+HASH256.HK = [0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+    0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+    0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+    0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+    0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+    0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+    0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+    0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2];
+
diff --git a/version22/js/HASH384.js b/version22/js/HASH384.js
new file mode 100644
index 0000000..1aa89a1
--- /dev/null
+++ b/version22/js/HASH384.js
@@ -0,0 +1,238 @@
+/*
+	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.
+*/
+
+var HASH384 = function() {
+	this.length=[];
+	this.h=[];
+	this.w=[];
+	this.init();
+};
+
+HASH384.prototype={
+/* constants */
+
+
+	transform: function()
+	{ /* basic transformation step */
+		var a,b,c,d,e,ee,zz,f,g,hh,t1,t2;
+		var j,r;
+		for (j=16;j<80;j++) 
+			this.w[j]=HASH384.theta1(this.w[j-2]).add(this.w[j-7]).add(HASH384.theta0(this.w[j-15])).add(this.w[j-16]);
+
+		a=this.h[0].copy(); b=this.h[1].copy(); c=this.h[2].copy(); d=this.h[3].copy(); 
+		e=this.h[4].copy(); f=this.h[5].copy(); g=this.h[6].copy(); hh=this.h[7].copy();
+	
+		for (j=0;j<80;j++)
+		{ /* 80 times - mush it up */
+			t1=hh.copy();
+			t1.add(HASH384.Sig1(e)).add(HASH384.Ch(e,f,g)).add(HASH384.HK[j]).add(this.w[j]);
+
+			t2=HASH384.Sig0(a); t2.add(HASH384.Maj(a,b,c));
+			hh=g; g=f; f=e;
+			e=d.copy(); e.add(t1);
+
+			d=c;
+			c=b;
+			b=a;
+			a=t1.copy(); a.add(t2);
+		}
+
+		this.h[0].add(a); this.h[1].add(b); this.h[2].add(c); this.h[3].add(d);
+		this.h[4].add(e); this.h[5].add(f); this.h[6].add(g); this.h[7].add(hh);
+	},
+
+/* Initialise Hash function */
+	init: function()
+	{ /* initialise */
+		var i;
+		for (i=0;i<80;i++) this.w[i]=new UInt64(0,0);
+		this.length[0]=new UInt64(0,0); this.length[1]=new UInt64(0,0);
+		this.h[0]=HASH384.H[0].copy();
+		this.h[1]=HASH384.H[1].copy();
+		this.h[2]=HASH384.H[2].copy();
+		this.h[3]=HASH384.H[3].copy();
+		this.h[4]=HASH384.H[4].copy();
+		this.h[5]=HASH384.H[5].copy();
+		this.h[6]=HASH384.H[6].copy();
+		this.h[7]=HASH384.H[7].copy();
+	},	
+
+/* process a single byte */
+	process: function(byt)
+	{ /* process the next message byte */
+		var cnt;
+		cnt=(this.length[0].bot>>>6)%16;
+		this.w[cnt].shlb();
+		this.w[cnt].bot|=(byt&0xFF);
+
+		var e=new UInt64(0,8);
+		this.length[0].add(e);
+		if (this.length[0].top===0 && this.length[0].bot==0) { e=new UInt64(0,1); this.length[1].add(e); }
+		if ((this.length[0].bot%1024)===0) this.transform();
+	},
+
+/* process an array of bytes */	
+	process_array: function(b)
+	{
+		for (var i=0;i<b.length;i++) this.process(b[i]);
+	},
+
+/* process a 32-bit integer */
+	process_num: function(n)
+	{
+		this.process((n>>24)&0xff);
+		this.process((n>>16)&0xff);
+		this.process((n>>8)&0xff);
+		this.process(n&0xff);
+	},
+
+	hash: function()
+	{ /* pad message and finish - supply digest */
+		var i;
+		var digest=[];
+		var len0,len1;
+		len0=this.length[0].copy();
+		len1=this.length[1].copy();
+		this.process(0x80);
+		while ((this.length[0].bot%1024)!=896) this.process(0);
+
+		this.w[14]=len1;
+		this.w[15]=len0;    
+		this.transform();
+
+		for (i=0;i<HASH384.len;i++)
+		{ /* convert to bytes */
+			digest[i]=HASH384.R(8*(7-i%8),this.h[i>>>3]).bot&0xff;
+		}
+
+		this.init();
+		return digest;
+	}
+};
+
+
+/* static  functions */
+HASH384.S= function(n,x)
+{
+	if (n==0) return x;
+	if (n<32)
+		return new UInt64((x.top>>>n) | (x.bot<<(32-n)),       (x.bot>>>n) | (x.top << (32-n)));
+	else
+		return new UInt64((x.bot>>>(n-32)) | (x.top << (64-n)),(x.top>>>(n-32)) | (x.bot<<(64-n)));
+	
+};
+
+HASH384.R= function(n,x)
+{
+	if (n==0) return x;
+	if (n<32)
+		return new UInt64((x.top>>>n),(x.bot>>>n | (x.top << (32-n))));
+	else
+		return new UInt64(0,x.top >>> (n-32));
+};
+
+HASH384.Ch= function(x,y,z)
+{
+	return new UInt64((x.top&y.top)^(~(x.top)&z.top),(x.bot&y.bot)^(~(x.bot)&z.bot));
+};
+
+HASH384.Maj= function(x,y,z)
+{
+	return new UInt64((x.top&y.top)^(x.top&z.top)^(y.top&z.top),(x.bot&y.bot)^(x.bot&z.bot)^(y.bot&z.bot));
+};
+
+HASH384.Sig0= function(x)
+{
+	var r1=HASH384.S(28,x);
+	var r2=HASH384.S(34,x);
+	var r3=HASH384.S(39,x);
+	return new UInt64(r1.top^r2.top^r3.top,r1.bot^r2.bot^r3.bot);
+};
+
+HASH384.Sig1= function(x)
+{
+	var r1=HASH384.S(14,x);
+	var r2=HASH384.S(18,x);
+	var r3=HASH384.S(41,x);
+	return new UInt64(r1.top^r2.top^r3.top,r1.bot^r2.bot^r3.bot);
+};
+
+HASH384.theta0= function(x)
+{
+	var r1=HASH384.S(1,x);
+	var r2=HASH384.S(8,x);
+	var r3=HASH384.R(7,x);
+	return new UInt64(r1.top^r2.top^r3.top,r1.bot^r2.bot^r3.bot);
+};
+
+HASH384.theta1= function(x)
+{
+	var r1=HASH384.S(19,x);
+	var r2=HASH384.S(61,x);
+	var r3=HASH384.R(6,x);
+	return new UInt64(r1.top^r2.top^r3.top,r1.bot^r2.bot^r3.bot);
+};
+
+HASH384.len= 48;
+
+HASH384.H = [new UInt64(0xcbbb9d5d,0xc1059ed8), new UInt64(0x629a292a,0x367cd507),
+      new UInt64(0x9159015a,0x3070dd17), new UInt64(0x152fecd8,0xf70e5939),
+      new UInt64(0x67332667,0xffc00b31), new UInt64(0x8eb44a87,0x68581511),
+      new UInt64(0xdb0c2e0d,0x64f98fa7), new UInt64(0x47b5481d,0xbefa4fa4)];
+
+HASH384.HK = [new UInt64(0x428a2f98, 0xd728ae22), new UInt64(0x71374491, 0x23ef65cd),
+      new UInt64(0xb5c0fbcf, 0xec4d3b2f), new UInt64(0xe9b5dba5, 0x8189dbbc),
+      new UInt64(0x3956c25b, 0xf348b538), new UInt64(0x59f111f1, 0xb605d019),
+      new UInt64(0x923f82a4, 0xaf194f9b), new UInt64(0xab1c5ed5, 0xda6d8118),
+      new UInt64(0xd807aa98, 0xa3030242), new UInt64(0x12835b01, 0x45706fbe),
+      new UInt64(0x243185be, 0x4ee4b28c), new UInt64(0x550c7dc3, 0xd5ffb4e2),
+      new UInt64(0x72be5d74, 0xf27b896f), new UInt64(0x80deb1fe, 0x3b1696b1),
+      new UInt64(0x9bdc06a7, 0x25c71235), new UInt64(0xc19bf174, 0xcf692694),
+      new UInt64(0xe49b69c1, 0x9ef14ad2), new UInt64(0xefbe4786, 0x384f25e3),
+      new UInt64(0x0fc19dc6, 0x8b8cd5b5), new UInt64(0x240ca1cc, 0x77ac9c65),
+      new UInt64(0x2de92c6f, 0x592b0275), new UInt64(0x4a7484aa, 0x6ea6e483),
+      new UInt64(0x5cb0a9dc, 0xbd41fbd4), new UInt64(0x76f988da, 0x831153b5),
+      new UInt64(0x983e5152, 0xee66dfab), new UInt64(0xa831c66d, 0x2db43210),
+      new UInt64(0xb00327c8, 0x98fb213f), new UInt64(0xbf597fc7, 0xbeef0ee4),
+      new UInt64(0xc6e00bf3, 0x3da88fc2), new UInt64(0xd5a79147, 0x930aa725),
+      new UInt64(0x06ca6351, 0xe003826f), new UInt64(0x14292967, 0x0a0e6e70),
+      new UInt64(0x27b70a85, 0x46d22ffc), new UInt64(0x2e1b2138, 0x5c26c926),
+      new UInt64(0x4d2c6dfc, 0x5ac42aed), new UInt64(0x53380d13, 0x9d95b3df),
+      new UInt64(0x650a7354, 0x8baf63de), new UInt64(0x766a0abb, 0x3c77b2a8),
+      new UInt64(0x81c2c92e, 0x47edaee6), new UInt64(0x92722c85, 0x1482353b),
+      new UInt64(0xa2bfe8a1, 0x4cf10364), new UInt64(0xa81a664b, 0xbc423001),
+      new UInt64(0xc24b8b70, 0xd0f89791), new UInt64(0xc76c51a3, 0x0654be30),
+      new UInt64(0xd192e819, 0xd6ef5218), new UInt64(0xd6990624, 0x5565a910),
+      new UInt64(0xf40e3585, 0x5771202a), new UInt64(0x106aa070, 0x32bbd1b8),
+      new UInt64(0x19a4c116, 0xb8d2d0c8), new UInt64(0x1e376c08, 0x5141ab53),
+      new UInt64(0x2748774c, 0xdf8eeb99), new UInt64(0x34b0bcb5, 0xe19b48a8),
+      new UInt64(0x391c0cb3, 0xc5c95a63), new UInt64(0x4ed8aa4a, 0xe3418acb),
+      new UInt64(0x5b9cca4f, 0x7763e373), new UInt64(0x682e6ff3, 0xd6b2b8a3),
+      new UInt64(0x748f82ee, 0x5defb2fc), new UInt64(0x78a5636f, 0x43172f60),
+      new UInt64(0x84c87814, 0xa1f0ab72), new UInt64(0x8cc70208, 0x1a6439ec),
+      new UInt64(0x90befffa, 0x23631e28), new UInt64(0xa4506ceb, 0xde82bde9),
+      new UInt64(0xbef9a3f7, 0xb2c67915), new UInt64(0xc67178f2, 0xe372532b),
+      new UInt64(0xca273ece, 0xea26619c), new UInt64(0xd186b8c7, 0x21c0c207),
+      new UInt64(0xeada7dd6, 0xcde0eb1e), new UInt64(0xf57d4f7f, 0xee6ed178),
+      new UInt64(0x06f067aa, 0x72176fba), new UInt64(0x0a637dc5, 0xa2c898a6),
+      new UInt64(0x113f9804, 0xbef90dae), new UInt64(0x1b710b35, 0x131c471b),
+      new UInt64(0x28db77f5, 0x23047d84), new UInt64(0x32caab7b, 0x40c72493),
+      new UInt64(0x3c9ebe0a, 0x15c9bebc), new UInt64(0x431d67c4, 0x9c100d4c),
+      new UInt64(0x4cc5d4be, 0xcb3e42b6), new UInt64(0x597f299c, 0xfc657e2a),
+      new UInt64(0x5fcb6fab, 0x3ad6faec), new UInt64(0x6c44198c, 0x4a475817)];
\ No newline at end of file
diff --git a/version22/js/HASH512.js b/version22/js/HASH512.js
new file mode 100644
index 0000000..5a6f47a
--- /dev/null
+++ b/version22/js/HASH512.js
@@ -0,0 +1,236 @@
+/*
+	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.
+*/
+
+var HASH512 = function() {
+	this.length=[];
+	this.h=[];
+	this.w=[];
+	this.init();
+};
+
+HASH512.prototype={
+
+	transform: function()
+	{ /* basic transformation step */
+		var a,b,c,d,e,ee,zz,f,g,hh,t1,t2;
+		var j,r;
+		for (j=16;j<80;j++) 
+			this.w[j]=HASH512.theta1(this.w[j-2]).add(this.w[j-7]).add(HASH512.theta0(this.w[j-15])).add(this.w[j-16]);
+
+		a=this.h[0].copy(); b=this.h[1].copy(); c=this.h[2].copy(); d=this.h[3].copy(); 
+		e=this.h[4].copy(); f=this.h[5].copy(); g=this.h[6].copy(); hh=this.h[7].copy();
+	
+		for (j=0;j<80;j++)
+		{ /* 80 times - mush it up */
+			t1=hh.copy();
+			t1.add(HASH512.Sig1(e)).add(HASH512.Ch(e,f,g)).add(HASH512.HK[j]).add(this.w[j]);
+
+			t2=HASH512.Sig0(a); t2.add(HASH512.Maj(a,b,c));
+			hh=g; g=f; f=e;
+			e=d.copy(); e.add(t1);
+
+			d=c;
+			c=b;
+			b=a;
+			a=t1.copy(); a.add(t2);
+		}
+
+		this.h[0].add(a); this.h[1].add(b); this.h[2].add(c); this.h[3].add(d);
+		this.h[4].add(e); this.h[5].add(f); this.h[6].add(g); this.h[7].add(hh);
+	},
+
+/* Initialise Hash function */
+	init: function()
+	{ /* initialise */
+		var i;
+		for (i=0;i<80;i++) this.w[i]=new UInt64(0,0);
+		this.length[0]=new UInt64(0,0); this.length[1]=new UInt64(0,0);
+		this.h[0]=HASH512.H[0].copy();
+		this.h[1]=HASH512.H[1].copy();
+		this.h[2]=HASH512.H[2].copy();
+		this.h[3]=HASH512.H[3].copy();
+		this.h[4]=HASH512.H[4].copy();
+		this.h[5]=HASH512.H[5].copy();
+		this.h[6]=HASH512.H[6].copy();
+		this.h[7]=HASH512.H[7].copy();
+	},	
+
+/* process a single byte */
+	process: function(byt)
+	{ /* process the next message byte */
+		var cnt;
+		cnt=(this.length[0].bot>>>6)%16;
+		this.w[cnt].shlb();
+		this.w[cnt].bot|=(byt&0xFF);
+
+		var e=new UInt64(0,8);
+		this.length[0].add(e);
+		if (this.length[0].top===0 && this.length[0].bot==0) { e=new UInt64(0,1); this.length[1].add(e); }
+		if ((this.length[0].bot%1024)===0) this.transform();
+	},
+
+/* process an array of bytes */	
+	process_array: function(b)
+	{
+		for (var i=0;i<b.length;i++) this.process(b[i]);
+	},
+
+/* process a 32-bit integer */
+	process_num: function(n)
+	{
+		this.process((n>>24)&0xff);
+		this.process((n>>16)&0xff);
+		this.process((n>>8)&0xff);
+		this.process(n&0xff);
+	},
+
+	hash: function()
+	{ /* pad message and finish - supply digest */
+		var i;
+		var digest=[];
+		var len0,len1;
+		len0=this.length[0].copy();
+		len1=this.length[1].copy();
+		this.process(0x80);
+		while ((this.length[0].bot%1024)!=896) this.process(0);
+
+		this.w[14]=len1;
+		this.w[15]=len0;    
+		this.transform();
+
+		for (i=0;i<HASH512.len;i++)
+		{ /* convert to bytes */
+			digest[i]=HASH512.R(8*(7-i%8),this.h[i>>>3]).bot&0xff;
+		}
+
+		this.init();
+		return digest;
+	}
+};
+
+/* static functions */
+HASH512.S= function(n,x)
+{
+	if (n==0) return x;
+	if (n<32)
+		return new UInt64((x.top>>>n) | (x.bot<<(32-n)),       (x.bot>>>n) | (x.top << (32-n)));
+	else
+		return new UInt64((x.bot>>>(n-32)) | (x.top << (64-n)),(x.top>>>(n-32)) | (x.bot<<(64-n)));
+	
+};
+
+HASH512.R= function(n,x)
+{
+	if (n==0) return x;
+	if (n<32)
+		return new UInt64((x.top>>>n),(x.bot>>>n | (x.top << (32-n))));
+	else
+		return new UInt64(0,x.top >>> (n-32));
+};
+
+HASH512.Ch= function(x,y,z)
+{
+	return new UInt64((x.top&y.top)^(~(x.top)&z.top),(x.bot&y.bot)^(~(x.bot)&z.bot));
+};
+
+HASH512.Maj= function(x,y,z)
+{
+	return new UInt64((x.top&y.top)^(x.top&z.top)^(y.top&z.top),(x.bot&y.bot)^(x.bot&z.bot)^(y.bot&z.bot));
+};
+
+HASH512.Sig0= function(x)
+{
+	var r1=HASH512.S(28,x);
+	var r2=HASH512.S(34,x);
+	var r3=HASH512.S(39,x);
+	return new UInt64(r1.top^r2.top^r3.top,r1.bot^r2.bot^r3.bot);
+};
+
+HASH512.Sig1= function(x)
+{
+	var r1=HASH512.S(14,x);
+	var r2=HASH512.S(18,x);
+	var r3=HASH512.S(41,x);
+	return new UInt64(r1.top^r2.top^r3.top,r1.bot^r2.bot^r3.bot);
+};
+
+HASH512.theta0= function(x)
+{
+	var r1=HASH512.S(1,x);
+	var r2=HASH512.S(8,x);
+	var r3=HASH512.R(7,x);
+	return new UInt64(r1.top^r2.top^r3.top,r1.bot^r2.bot^r3.bot);
+};
+
+HASH512.theta1= function(x)
+{
+	var r1=HASH512.S(19,x);
+	var r2=HASH512.S(61,x);
+	var r3=HASH512.R(6,x);
+	return new UInt64(r1.top^r2.top^r3.top,r1.bot^r2.bot^r3.bot);
+};
+
+/* constants */
+HASH512.len= 64;
+
+HASH512.H = [new UInt64(0x6a09e667, 0xf3bcc908), new UInt64(0xbb67ae85, 0x84caa73b),
+      new UInt64(0x3c6ef372, 0xfe94f82b), new UInt64(0xa54ff53a, 0x5f1d36f1),
+      new UInt64(0x510e527f, 0xade682d1), new UInt64(0x9b05688c, 0x2b3e6c1f),
+      new UInt64(0x1f83d9ab, 0xfb41bd6b), new UInt64(0x5be0cd19, 0x137e2179)];
+
+HASH512.HK = [new UInt64(0x428a2f98, 0xd728ae22), new UInt64(0x71374491, 0x23ef65cd),
+      new UInt64(0xb5c0fbcf, 0xec4d3b2f), new UInt64(0xe9b5dba5, 0x8189dbbc),
+      new UInt64(0x3956c25b, 0xf348b538), new UInt64(0x59f111f1, 0xb605d019),
+      new UInt64(0x923f82a4, 0xaf194f9b), new UInt64(0xab1c5ed5, 0xda6d8118),
+      new UInt64(0xd807aa98, 0xa3030242), new UInt64(0x12835b01, 0x45706fbe),
+      new UInt64(0x243185be, 0x4ee4b28c), new UInt64(0x550c7dc3, 0xd5ffb4e2),
+      new UInt64(0x72be5d74, 0xf27b896f), new UInt64(0x80deb1fe, 0x3b1696b1),
+      new UInt64(0x9bdc06a7, 0x25c71235), new UInt64(0xc19bf174, 0xcf692694),
+      new UInt64(0xe49b69c1, 0x9ef14ad2), new UInt64(0xefbe4786, 0x384f25e3),
+      new UInt64(0x0fc19dc6, 0x8b8cd5b5), new UInt64(0x240ca1cc, 0x77ac9c65),
+      new UInt64(0x2de92c6f, 0x592b0275), new UInt64(0x4a7484aa, 0x6ea6e483),
+      new UInt64(0x5cb0a9dc, 0xbd41fbd4), new UInt64(0x76f988da, 0x831153b5),
+      new UInt64(0x983e5152, 0xee66dfab), new UInt64(0xa831c66d, 0x2db43210),
+      new UInt64(0xb00327c8, 0x98fb213f), new UInt64(0xbf597fc7, 0xbeef0ee4),
+      new UInt64(0xc6e00bf3, 0x3da88fc2), new UInt64(0xd5a79147, 0x930aa725),
+      new UInt64(0x06ca6351, 0xe003826f), new UInt64(0x14292967, 0x0a0e6e70),
+      new UInt64(0x27b70a85, 0x46d22ffc), new UInt64(0x2e1b2138, 0x5c26c926),
+      new UInt64(0x4d2c6dfc, 0x5ac42aed), new UInt64(0x53380d13, 0x9d95b3df),
+      new UInt64(0x650a7354, 0x8baf63de), new UInt64(0x766a0abb, 0x3c77b2a8),
+      new UInt64(0x81c2c92e, 0x47edaee6), new UInt64(0x92722c85, 0x1482353b),
+      new UInt64(0xa2bfe8a1, 0x4cf10364), new UInt64(0xa81a664b, 0xbc423001),
+      new UInt64(0xc24b8b70, 0xd0f89791), new UInt64(0xc76c51a3, 0x0654be30),
+      new UInt64(0xd192e819, 0xd6ef5218), new UInt64(0xd6990624, 0x5565a910),
+      new UInt64(0xf40e3585, 0x5771202a), new UInt64(0x106aa070, 0x32bbd1b8),
+      new UInt64(0x19a4c116, 0xb8d2d0c8), new UInt64(0x1e376c08, 0x5141ab53),
+      new UInt64(0x2748774c, 0xdf8eeb99), new UInt64(0x34b0bcb5, 0xe19b48a8),
+      new UInt64(0x391c0cb3, 0xc5c95a63), new UInt64(0x4ed8aa4a, 0xe3418acb),
+      new UInt64(0x5b9cca4f, 0x7763e373), new UInt64(0x682e6ff3, 0xd6b2b8a3),
+      new UInt64(0x748f82ee, 0x5defb2fc), new UInt64(0x78a5636f, 0x43172f60),
+      new UInt64(0x84c87814, 0xa1f0ab72), new UInt64(0x8cc70208, 0x1a6439ec),
+      new UInt64(0x90befffa, 0x23631e28), new UInt64(0xa4506ceb, 0xde82bde9),
+      new UInt64(0xbef9a3f7, 0xb2c67915), new UInt64(0xc67178f2, 0xe372532b),
+      new UInt64(0xca273ece, 0xea26619c), new UInt64(0xd186b8c7, 0x21c0c207),
+      new UInt64(0xeada7dd6, 0xcde0eb1e), new UInt64(0xf57d4f7f, 0xee6ed178),
+      new UInt64(0x06f067aa, 0x72176fba), new UInt64(0x0a637dc5, 0xa2c898a6),
+      new UInt64(0x113f9804, 0xbef90dae), new UInt64(0x1b710b35, 0x131c471b),
+      new UInt64(0x28db77f5, 0x23047d84), new UInt64(0x32caab7b, 0x40c72493),
+      new UInt64(0x3c9ebe0a, 0x15c9bebc), new UInt64(0x431d67c4, 0x9c100d4c),
+      new UInt64(0x4cc5d4be, 0xcb3e42b6), new UInt64(0x597f299c, 0xfc657e2a),
+      new UInt64(0x5fcb6fab, 0x3ad6faec), new UInt64(0x6c44198c, 0x4a475817)];
diff --git a/version22/js/MPIN.js b/version22/js/MPIN.js
new file mode 100644
index 0000000..fdd1d80
--- /dev/null
+++ b/version22/js/MPIN.js
@@ -0,0 +1,933 @@
+/*
+	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.
+*/
+
+/* MPIN API Functions */
+
+var MPIN = {
+	BAD_PARAMS:-11,
+	INVALID_POINT:-14,
+	WRONG_ORDER:-18,
+	BAD_PIN:-19,
+/* configure PIN here */
+	MAXPIN:10000,  /* max PIN */
+	PBLEN:14,     /* MAXPIN length in bits */
+	TS:10,        /* 10 for 4 digit PIN, 14 for 6-digit PIN - 2^TS/TS approx = sqrt(MAXPIN) */
+	TRAP:200,     /* 200 for 4 digit PIN, 2000 for 6-digit PIN  - approx 2*sqrt(MAXPIN) */
+	EFS:ROM.MODBYTES,
+	EGS:ROM.MODBYTES,
+	PAS:16,
+
+	SHA256 : 32,
+	SHA384 : 48,
+	SHA512 : 64,
+
+	HASH_TYPE : 32,
+
+
+/* return time in slots since epoch */
+	today: function() {
+		var now=new Date();
+		return Math.floor(now.getTime()/(60000*1440));  // for daily tokens
+	},
+
+	bytestostring: function(b)
+	{
+		var s="";
+		var len=b.length;
+		var ch;
+
+		for (var i=0;i<len;i++)
+		{
+			ch=b[i];
+			s+=((ch>>>4)&15).toString(16);
+			s+=(ch&15).toString(16);
+
+		}
+		return s;
+	},
+
+	stringtobytes: function(s)
+	{
+		var b=[];
+		for (var i=0;i<s.length;i++)
+			b.push(s.charCodeAt(i));
+		return b;
+	},
+
+	comparebytes: function(a,b)
+	{
+		if (a.length!=b.length) return false;
+		for (var i=0;i<a.length;i++)
+		{
+			if (a[i]!=b[i]) return false;
+		}
+		return true;
+	},
+
+	mpin_hash: function(sha,c,U)
+	{
+		var t=[];
+		var w=[];
+		var h=[];
+
+		c.geta().getA().toBytes(w); for (var i=0;i<this.EFS;i++) t[i]=w[i];
+		c.geta().getB().toBytes(w); for (var i=this.EFS;i<2*this.EFS;i++) t[i]=w[i-this.EFS];
+		c.getb().getA().toBytes(w); for (var i=2*this.EFS;i<3*this.EFS;i++) t[i]=w[i-2*this.EFS];
+		c.getb().getB().toBytes(w); for (var i=3*this.EFS;i<4*this.EFS;i++) t[i]=w[i-3*this.EFS];
+		
+		U.getX().toBytes(w); for (var i=4*this.EFS;i<5*this.EFS;i++) t[i]=w[i-4*this.EFS];
+		U.getY().toBytes(w); for (var i=5*this.EFS;i<6*this.EFS;i++) t[i]=w[i-5*this.EFS];
+	
+		if (sha==this.SHA256)
+		{
+			var H=new HASH256();
+			H.process_array(t);
+			h=H.hash();
+		}
+		if (sha==this.SHA384)
+		{
+			var H=new HASH384();
+			H.process_array(t);
+			h=H.hash();
+		}
+		if (sha==this.SHA512)
+		{
+			var H=new HASH512();
+			H.process_array(t);
+			h=H.hash();
+		}
+		if (h.length==0) return null;
+		var R=[];
+		for (var i=0;i<this.PAS;i++) R[i]=h[i];
+		return R;
+	},
+/* Hash number (optional) and string to point on curve */
+
+	hashit: function(sha,n,B)
+	{
+		var R=[];
+
+		if (sha==this.SHA256)
+		{
+			var H=new HASH256();
+			if (n>0) H.process_num(n);
+			H.process_array(B);
+			R=H.hash();
+		}
+		if (sha==this.SHA384)
+		{
+			var H=new HASH384();
+			if (n>0) H.process_num(n);
+			H.process_array(B);
+			R=H.hash();
+		}
+		if (sha==this.SHA512)
+		{
+			var H=new HASH512();
+			if (n>0) H.process_num(n);
+			H.process_array(B);
+			R=H.hash();
+		}
+		if (R.length==0) return null;
+		var W=[];
+
+		if (sha>=ROM.MODBYTES)
+			for (var i=0;i<ROM.MODBYTES;i++) W[i]=R[i];
+		else
+		{
+			for (var i=0;i<sha;i++) W[i]=R[i];
+			for (var i=sha;i<ROM.MODBYTES;i++) W[i]=0;
+		}
+		return W;
+	},
+
+	mapit: function(h)
+	{
+		var q=new BIG(0); q.rcopy(ROM.Modulus);
+		var x=BIG.fromBytes(h);
+		x.mod(q);
+		var P=new ECP();
+		while (true)
+		{
+			P.setxi(x,0);
+			if (!P.is_infinity()) break;
+			x.inc(1); x.norm();
+		}
+		if (ROM.CURVE_PAIRING_TYPE!=ROM.BN_CURVE)
+		{
+			var c=new BIG(0); c.rcopy(ROM.CURVE_Cof);
+			P=P.mul(c);
+		}
+		return P;
+	},
+
+/* needed for SOK */
+	mapit2: function(h)
+	{
+		var q=new BIG(0); q.rcopy(ROM.Modulus);
+		var x=BIG.fromBytes(h);
+		var one=new BIG(1);
+		x.mod(q);
+		var Q,T,K,X;
+		while (true)
+		{
+			X=new FP2(one,x);
+			Q=new ECP2(); Q.setx(X);
+			if (!Q.is_infinity()) break;
+			x.inc(1); x.norm();
+		}
+/* Fast Hashing to G2 - Fuentes-Castaneda, Knapp and Rodriguez-Henriquez */
+
+		var Fa=new BIG(0); Fa.rcopy(ROM.CURVE_Fra);
+		var Fb=new BIG(0); Fb.rcopy(ROM.CURVE_Frb);
+		X=new FP2(Fa,Fb); 
+		x=new BIG(0); x.rcopy(ROM.CURVE_Bnx);
+
+		T=new ECP2(); T.copy(Q);
+		T.mul(x); T.neg();
+		K=new ECP2(); K.copy(T);
+		K.dbl(); K.add(T); K.affine();
+
+		K.frob(X);
+		Q.frob(X); Q.frob(X); Q.frob(X);
+		Q.add(T); Q.add(K);
+		T.frob(X); T.frob(X);
+		Q.add(T);
+		Q.affine();
+		return Q;
+
+	},
+
+/* these next two functions help to implement elligator squared - http://eprint.iacr.org/2014/043 */
+/* maps a random u to a point on the curve */
+	map: function(u,cb)
+	{
+		var P=new ECP();
+		var x=new BIG(u);
+		var p=new BIG(0); p.rcopy(ROM.Modulus);
+		x.mod(p);
+		while (true)
+		{
+			P.setxi(x,cb);
+			if (!P.is_infinity()) break;
+			x.inc(1);  x.norm();
+		}
+		return P;
+	},
+
+/* returns u derived from P. Random value in range 1 to return value should then be added to u */
+	unmap: function(u,P)
+	{
+		var s=P.getS();
+		var R=new ECP();
+		var r=0;
+		var x=P.getX();
+		u.copy(x);
+		while (true)
+		{
+			u.dec(1); u.norm();
+			r++;
+			R.setxi(u,s); //=new ECP(u,s);
+			if (!R.is_infinity()) break;
+		}
+		return r;
+	},
+
+/* these next two functions implement elligator squared - http://eprint.iacr.org/2014/043 */
+/* Elliptic curve point E in format (0x04,x,y} is converted to form {0x0-,u,v} */
+/* Note that u and v are indistinguisible from random strings */
+	ENCODING: function(rng,E)
+	{
+		var i,rn,m,su,sv;
+		var T=[];
+
+		for (i=0;i<this.EFS;i++) T[i]=E[i+1];
+		var u=BIG.fromBytes(T);
+		for (i=0;i<this.EFS;i++) T[i]=E[i+this.EFS+1];
+		var v=BIG.fromBytes(T);
+		
+		var P=new ECP(0); P.setxy(u,v);
+		if (P.is_infinity()) return this.INVALID_POINT;
+
+		var p=new BIG(0); p.rcopy(ROM.Modulus);
+		u=BIG.randomnum(p,rng);
+
+		su=rng.getByte(); if (su<0) su=-su; su%=2;
+		
+		var W=this.map(u,su);
+		P.sub(W);
+		sv=P.getS();
+		rn=this.unmap(v,P);
+		m=rng.getByte(); if (m<0) m=-m; m%=rn;
+		v.inc(m+1);
+		E[0]=(su+2*sv);
+		u.toBytes(T);
+		for (i=0;i<this.EFS;i++) E[i+1]=T[i];
+		v.toBytes(T);
+		for (i=0;i<this.EFS;i++) E[i+this.EFS+1]=T[i];		
+		
+		return 0;
+	},
+
+	DECODING: function(D)
+	{
+		var i,su,sv;
+		var T=[];
+
+		if ((D[0]&0x04)!==0) return this.INVALID_POINT;
+
+		for (i=0;i<this.EFS;i++) T[i]=D[i+1];
+		var u=BIG.fromBytes(T);
+		for (i=0;i<this.EFS;i++) T[i]=D[i+this.EFS+1];
+		var v=BIG.fromBytes(T);
+
+		su=D[0]&1;
+		sv=(D[0]>>1)&1;
+		var W=this.map(u,su);
+		var P=this.map(v,sv);
+		P.add(W);
+		u=P.getX();
+		v=P.getY();
+		D[0]=0x04;
+		u.toBytes(T);
+		for (i=0;i<this.EFS;i++) D[i+1]=T[i];
+		v.toBytes(T);
+		for (i=0;i<this.EFS;i++) D[i+this.EFS+1]=T[i];		
+		
+		return 0;
+	},
+
+/* R=R1+R2 in group G1 */
+	RECOMBINE_G1: function(R1,R2,R)
+	{
+		var P=ECP.fromBytes(R1);
+		var Q=ECP.fromBytes(R2);
+
+		if (P.is_infinity() || Q.is_infinity()) return this.INVALID_POINT;
+
+		P.add(Q);
+
+		P.toBytes(R);
+		return 0;
+	},
+
+/* W=W1+W2 in group G2 */
+	RECOMBINE_G2: function(W1,W2,W)
+	{
+		var P=ECP2.fromBytes(W1);
+		var Q=ECP2.fromBytes(W2);
+
+		if (P.is_infinity() || Q.is_infinity()) return this.INVALID_POINT;
+
+		P.add(Q);
+	
+		P.toBytes(W);
+		return 0;
+	},
+
+	HASH_ID: function(sha,ID)
+	{
+		return this.hashit(sha,0,ID);
+	},
+
+/* create random secret S */
+	RANDOM_GENERATE: function(rng,S)
+	{
+		var r=new BIG(0); r.rcopy(ROM.CURVE_Order);
+		var s=BIG.randomnum(r,rng);
+		if (ROM.AES_S>0)
+		{
+			s.mod2m(2*ROM.AES_S);
+		}		
+		s.toBytes(S);
+		return 0;
+	},
+
+/* Extract PIN from TOKEN for identity CID */
+	EXTRACT_PIN: function(sha,CID,pin,TOKEN)
+	{
+		var P=ECP.fromBytes(TOKEN);
+		if (P.is_infinity()) return this.INVALID_POINT;
+		var h=this.hashit(sha,0,CID);
+		var R=this.mapit(h);
+
+		pin%=this.MAXPIN;
+
+		R=R.pinmul(pin,this.PBLEN);
+		P.sub(R);
+
+		P.toBytes(TOKEN);
+
+		return 0;
+	},
+
+/* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */
+	GET_SERVER_SECRET: function(S,SST)
+	{
+
+		var A=new BIG(0);
+		var B=new BIG(0);
+		A.rcopy(ROM.CURVE_Pxa); B.rcopy(ROM.CURVE_Pxb);
+		var QX=new FP2(0); QX.bset(A,B);
+		A.rcopy(ROM.CURVE_Pya); B.rcopy(ROM.CURVE_Pyb);
+		var QY=new FP2(0); QY.bset(A,B);
+
+		var Q=new ECP2();
+		Q.setxy(QX,QY);
+
+		var s=BIG.fromBytes(S);
+		Q=PAIR.G2mul(Q,s);
+		Q.toBytes(SST);
+		return 0;
+	},
+
+	TEST_PAIR: function(PR)
+	{
+		var G=new ECP(0);
+		var A=new BIG(0);
+		var B=new BIG(0);
+		A.rcopy(ROM.CURVE_Pxa); B.rcopy(ROM.CURVE_Pxb);
+		var QX=new FP2(0); QX.bset(A,B);
+		A.rcopy(ROM.CURVE_Pya); B.rcopy(ROM.CURVE_Pyb);
+		var QY=new FP2(0); QY.bset(A,B);
+
+		var Q=new ECP2();
+		Q.setxy(QX,QY);		
+
+		var gx=new BIG(0); gx.rcopy(ROM.CURVE_Gx);	
+		var gy=new BIG(0); gy.rcopy(ROM.CURVE_Gy);
+		G.setxy(gx,gy);			
+
+		var g=PAIR.ate(Q,G);
+		g=PAIR.fexp(g);	
+		g.toBytes(PR);
+	},
+
+/*
+ W=x*H(G);
+ if RNG == NULL then X is passed in 
+ if RNG != NULL the X is passed out 
+ if type=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve
+*/
+	GET_G1_MULTIPLE: function(rng,type,X,G,W)
+	{
+		var x;
+		var r=new BIG(0); r.rcopy(ROM.CURVE_Order);
+
+		if (rng!=null)
+		{
+			x=BIG.randomnum(r,rng);
+			if (ROM.AES_S>0)
+			{
+				x.mod2m(2*ROM.AES_S);
+			}
+			x.toBytes(X);
+		}
+		else
+		{
+			x=BIG.fromBytes(X);
+		}
+		var P;
+		if (type==0)
+		{
+			P=ECP.fromBytes(G);
+			if (P.is_infinity()) return INVALID_POINT;
+		}
+		else
+			P=this.mapit(G);
+
+		PAIR.G1mul(P,x).toBytes(W);
+		return 0;
+	},
+
+
+/* Client secret CST=S*H(CID) where CID is client ID and S is master secret */
+	GET_CLIENT_SECRET: function(S,CID,CST)
+	{
+		return this.GET_G1_MULTIPLE(null,1,S,CID,CST);
+	},
+
+/* Time Permit CTT=S*(date|H(CID)) where S is master secret */
+	GET_CLIENT_PERMIT: function(sha,date,S,CID,CTT)
+	{
+		var h=this.hashit(sha,date,CID);
+		var P=this.mapit(h);
+
+		var s=BIG.fromBytes(S);
+		P=PAIR.G1mul(P,s);
+		P.toBytes(CTT);
+		return 0;
+	},
+
+/* Implement step 1 on client side of MPin protocol */
+	CLIENT_1: function(sha,date,CLIENT_ID,rng,X,pin,TOKEN,SEC,xID,xCID,PERMIT)
+	{
+		var r=new BIG(0); r.rcopy(ROM.CURVE_Order);
+	//	var q=new BIG(0); q.rcopy(ROM.Modulus);
+		var x;
+		if (rng!==null)
+		{
+			x=BIG.randomnum(r,rng);
+			if (ROM.AES_S>0)
+			{
+				x.mod2m(2*ROM.AES_S);
+			}
+			x.toBytes(X);
+		}
+		else
+		{
+			x=BIG.fromBytes(X);
+		}
+		var P,T,W;
+
+		var h=this.hashit(sha,0,CLIENT_ID);
+		P=this.mapit(h);
+		T=ECP.fromBytes(TOKEN);
+		if (T.is_infinity()) return this.INVALID_POINT;
+
+		pin%=this.MAXPIN;
+		W=P.pinmul(pin,this.PBLEN);
+		T.add(W);
+
+		if (date!=0)
+		{
+			W=ECP.fromBytes(PERMIT);
+			if (W.is_infinity()) return this.INVALID_POINT;
+			T.add(W);
+			h=this.hashit(sha,date,h);
+			W=this.mapit(h);
+			if (xID!=null)
+			{
+				P=PAIR.G1mul(P,x);
+				P.toBytes(xID);
+				W=PAIR.G1mul(W,x);
+				P.add(W);
+			}
+			else
+			{
+				P.add(W);
+				P=PAIR.G1mul(P,x);
+			}
+			if (xCID!=null) P.toBytes(xCID);
+		}
+		else
+		{
+			if (xID!=null)
+			{
+				P=PAIR.G1mul(P,x);
+				P.toBytes(xID);
+			}
+		}		
+		
+		T.toBytes(SEC);
+		return 0;
+	},
+
+/* Implement step 2 on client side of MPin protocol */
+	CLIENT_2: function(X,Y,SEC)
+	{
+		var r=new BIG(0); r.rcopy(ROM.CURVE_Order);
+		var P=ECP.fromBytes(SEC);
+		if (P.is_infinity()) return this.INVALID_POINT;
+
+		var px=BIG.fromBytes(X);
+		var py=BIG.fromBytes(Y);
+		px.add(py);
+		px.mod(r);
+	//	px.rsub(r);
+
+		P=PAIR.G1mul(P,px);
+		P.neg();
+		P.toBytes(SEC);
+		//PAIR.G1mul(P,px).toBytes(SEC);
+		return 0;
+	},
+
+/* Outputs H(CID) and H(T|H(CID)) for time permits. If no time permits set HID=HTID */
+	SERVER_1: function(sha,date,CID,HID,HTID)
+	{
+		var h=this.hashit(sha,0,CID);
+		var R,P=this.mapit(h);
+
+		P.toBytes(HID);
+		if (date!==0)
+		{
+			//if (HID!=null) P.toBytes(HID);
+			h=this.hashit(sha,date,h);
+			R=this.mapit(h);
+			P.add(R);
+			P.toBytes(HTID);
+		}
+		//else P.toBytes(HID);
+	},
+
+/* Implement step 1 of MPin protocol on server side */
+	SERVER_2: function(date,HID,HTID,Y,SST,xID,xCID,mSEC,E,F)
+	{
+		var A=new BIG(0);
+		var B=new BIG(0);
+		A.rcopy(ROM.CURVE_Pxa); B.rcopy(ROM.CURVE_Pxb);
+		var QX=new FP2(0); QX.bset(A,B);
+		A.rcopy(ROM.CURVE_Pya); B.rcopy(ROM.CURVE_Pyb);
+		var QY=new FP2(0); QY.bset(A,B);
+
+		var Q=new ECP2();
+		Q.setxy(QX,QY);
+
+		var sQ=ECP2.fromBytes(SST);
+		if (sQ.is_infinity()) return this.INVALID_POINT;	
+
+		var R;
+		if (date!==0)
+			R=ECP.fromBytes(xCID);
+		else 
+		{
+			if (xID==null) return this.BAD_PARAMS;
+			R=ECP.fromBytes(xID);
+		}
+		if (R.is_infinity()) return this.INVALID_POINT;
+
+		var y=BIG.fromBytes(Y);
+		var P;
+
+		if (date!=0) P=ECP.fromBytes(HTID);
+		else
+		{
+			if (HID==null) return this.BAD_PARAMS;
+			P=ECP.fromBytes(HID);
+		}
+		if (P.is_infinity()) return this.INVALID_POINT;
+
+		P=PAIR.G1mul(P,y);
+		P.add(R);
+		R=ECP.fromBytes(mSEC);
+		if (R.is_infinity()) return this.INVALID_POINT;
+
+		var g=PAIR.ate2(Q,R,sQ,P);
+		g=PAIR.fexp(g);
+
+		if (!g.isunity())
+		{
+			if (HID!=null && xID!=null && E!=null && F!=null)
+			{
+				g.toBytes(E);
+				if (date!==0)
+				{
+					P=ECP.fromBytes(HID);
+					if (P.is_infinity()) return this.INVALID_POINT;
+					R=ECP.fromBytes(xID);
+					if (R.is_infinity()) return this.INVALID_POINT;
+
+					P=PAIR.G1mul(P,y);
+					P.add(R);
+				}
+				g=PAIR.ate(Q,P);
+				g=PAIR.fexp(g);
+
+				g.toBytes(F);
+			}
+			return this.BAD_PIN;
+		}
+		return 0;
+	},
+
+/* Pollards kangaroos used to return PIN error */
+	KANGAROO: function(E,F)
+	{
+		var ge=FP12.fromBytes(E);
+		var gf=FP12.fromBytes(F);
+		var distance = [];
+		var t=new FP12(gf);
+		var table=[];
+		var i,j,m,s,dn,dm,res,steps;
+
+		s=1;
+		for (m=0;m<this.TS;m++)
+		{
+			distance[m]=s;
+			table[m]=new FP12(t);
+			s*=2;
+			t.usqr();
+		}
+		t.one();
+		dn=0;
+		for (j=0;j<this.TRAP;j++)
+		{
+			i=t.geta().geta().getA().lastbits(20)%this.TS;
+			t.mul(table[i]);
+			dn+=distance[i];
+		}
+		gf.copy(t); gf.conj();
+		steps=0; dm=0;
+		res=0;
+		while (dm-dn<this.MAXPIN)
+		{
+			steps++;
+			if (steps>4*this.TRAP) break;
+			i=ge.geta().geta().getA().lastbits(20)%this.TS;
+			ge.mul(table[i]);
+			dm+=distance[i];
+			if (ge.equals(t))
+			{
+				res=dm-dn;
+				break;
+			}
+			if (ge.equals(gf))
+			{
+				res=dn-dm;
+				break;
+			}
+
+		}
+		if (steps>4*this.TRAP || dm-dn>=this.MAXPIN) {res=0; }    // Trap Failed  - probable invalid token
+		return res;
+	},
+
+        /* return time  since epoch */
+	GET_TIME: function() {
+		var now=new Date();
+		return Math.floor(now.getTime()/(1000));
+	},
+
+        /* y = H(time,xCID) */
+	GET_Y: function(sha,TimeValue,xCID,Y)
+	{
+		var q=new BIG(0); 
+		q.rcopy(ROM.CURVE_Order);
+		var h=this.hashit(sha,TimeValue,xCID);
+		var y=BIG.fromBytes(h);
+		y.mod(q);
+		if (ROM.AES_S>0)
+		{
+			y.mod2m(2*ROM.AES_S);
+		}
+		y.toBytes(Y);
+		return 0;
+	},
+
+        /* One pass MPIN Client */
+	CLIENT: function(sha,date,CLIENT_ID,rng,X,pin,TOKEN,SEC,xID,xCID,PERMIT,TimeValue,Y)
+	{
+
+                var rtn=0;
+                var pID;
+                if (date == 0) {
+                  pID = xID;
+		} else {
+                  pID = xCID;
+                  xID = null;
+		}
+
+                rtn = this.CLIENT_1(sha,date,CLIENT_ID,rng,X,pin,TOKEN,SEC,xID,xCID,PERMIT);
+                if (rtn != 0)
+                  return rtn;
+
+                this.GET_Y(sha,TimeValue,pID,Y);
+
+                rtn = this.CLIENT_2(X,Y,SEC);
+                if (rtn != 0)
+                  return rtn;
+
+                return 0;
+        },
+
+        /* One pass MPIN Server */
+	SERVER: function(sha,date,HID,HTID,Y,SST,xID,xCID,mSEC,E,F,CID,TimeValue)
+        {
+                var rtn=0;
+                var pID;
+                if (date == 0) {
+                  pID = xID;
+		} else {
+                  pID = xCID;
+		}
+
+                this.SERVER_1(sha,date,CID,HID,HTID);
+
+                this.GET_Y(sha,TimeValue,pID,Y);
+  
+                rtn = this.SERVER_2(date,HID,HTID,Y,SST,xID,xCID,mSEC,E,F);
+                if (rtn != 0)
+                  return rtn;
+
+                return 0;
+        },
+
+/* Functions to support M-Pin Full */
+
+	PRECOMPUTE: function(TOKEN,CID,G1,G2)
+	{
+		var P,T;
+		var g;
+		
+		T=ECP.fromBytes(TOKEN);
+		if (T.is_infinity()) return INVALID_POINT; 
+
+		P=this.mapit(CID);
+
+		var A=new BIG(0);
+		var B=new BIG(0);
+		A.rcopy(ROM.CURVE_Pxa); B.rcopy(ROM.CURVE_Pxb);
+		var QX=new FP2(0); QX.bset(A,B);
+		A.rcopy(ROM.CURVE_Pya); B.rcopy(ROM.CURVE_Pyb);
+		var QY=new FP2(0); QY.bset(A,B);
+
+		var Q=new ECP2();
+		Q.setxy(QX,QY);
+
+		g=PAIR.ate(Q,T);
+		g=PAIR.fexp(g);
+		g.toBytes(G1);
+
+		g=PAIR.ate(Q,P);
+		g=PAIR.fexp(g);
+		g.toBytes(G2);
+
+		return 0;
+	},
+
+/* Hash the M-Pin transcript - new */
+
+	HASH_ALL: function(sha,HID,xID,xCID,SEC,Y,R,W)
+	{
+		var tlen=0;
+		var T=[];
+
+
+		for (var i=0;i<HID.length;i++) T[i]=HID[i];
+		tlen+=HID.length;
+		if (xCID!=null)
+		{
+			for (var i=0;i<xCID.length;i++) T[i+tlen]=xCID[i];
+			tlen+=xCID.length;
+		}	
+		else
+		{
+			for (i=0;i<xID.length;i++) T[i+tlen]=xID[i];
+			tlen+=xID.length;
+		}	
+		for (var i=0;i<SEC.length;i++) T[i+tlen]=SEC[i];
+		tlen+=SEC.length;		
+		for (var i=0;i<Y.length;i++) T[i+tlen]=Y[i];
+		tlen+=Y.length;	
+		for (var i=0;i<R.length;i++) T[i+tlen]=R[i];
+		tlen+=R.length;		
+		for (var i=0;i<W.length;i++) T[i+tlen]=W[i];
+		tlen+=W.length;		
+
+		return this.hashit(sha,0,T);
+	},
+
+/* calculate common key on client side */
+/* wCID = w.(A+AT) */
+	CLIENT_KEY: function(sha,G1,G2,pin,R,X,H,wCID,CK)
+	{
+		var t=[];
+
+		var g1=FP12.fromBytes(G1);
+		var g2=FP12.fromBytes(G2);
+		var z=BIG.fromBytes(R);
+		var x=BIG.fromBytes(X);
+		var h=BIG.fromBytes(H);
+
+		var W=ECP.fromBytes(wCID);
+		if (W.is_infinity()) return this.INVALID_POINT; 
+
+		W=PAIR.G1mul(W,x);
+
+		var fa=new BIG(0); fa.rcopy(ROM.CURVE_Fra);
+		var fb=new BIG(0); fb.rcopy(ROM.CURVE_Frb);
+		var f=new FP2(fa,fb); //f.bset(fa,fb);
+
+		var r=new BIG(0); r.rcopy(ROM.CURVE_Order);
+		var q=new BIG(0); q.rcopy(ROM.Modulus);
+
+		z.add(h);
+		z.mod(r);
+
+		var m=new BIG(q);
+		m.mod(r);
+
+		var a=new BIG(z);
+		a.mod(m);
+
+		var b=new BIG(z);
+		b.div(m);
+
+		g2.pinpow(pin,this.PBLEN);
+		g1.mul(g2);
+
+		var c=g1.trace();
+		g2.copy(g1);
+		g2.frob(f);
+		var cp=g2.trace();
+		g1.conj();
+		g2.mul(g1);
+		var cpm1=g2.trace();
+		g2.mul(g1);
+		var cpm2=g2.trace();
+
+		c=c.xtr_pow2(cp,cpm1,cpm2,a,b);
+
+		t=this.mpin_hash(sha,c,W);
+
+		for (var i=0;i<this.PAS;i++) CK[i]=t[i];
+
+		return 0;
+	},
+
+/* calculate common key on server side */
+/* Z=r.A - no time permits involved */
+
+	SERVER_KEY: function(sha,Z,SST,W,H,HID,xID,xCID,SK)
+	{
+		var t=[];
+
+		var sQ=ECP2.fromBytes(SST);
+		if (sQ.is_infinity()) return this.INVALID_POINT; 
+		var R=ECP.fromBytes(Z);
+		if (R.is_infinity()) return this.INVALID_POINT; 
+		var A=ECP.fromBytes(HID);
+		if (A.is_infinity()) return this.INVALID_POINT; 
+
+		var U;
+		if (xCID!=null)
+			U=ECP.fromBytes(xCID);
+		else
+			U=ECP.fromBytes(xID);
+		if (U.is_infinity()) return this.INVALID_POINT; 
+
+		var w=BIG.fromBytes(W);
+		var h=BIG.fromBytes(H);
+		A=PAIR.G1mul(A,h);
+		R.add(A);
+
+		U=PAIR.G1mul(U,w);
+		var g=PAIR.ate(sQ,R);
+		g=PAIR.fexp(g);
+
+		var c=g.trace();
+
+		t=this.mpin_hash(sha,c,U);
+
+		for (var i=0;i<this.PAS;i++) SK[i]=t[i];
+
+		return 0;
+	}
+};
diff --git a/version22/js/PAIR.js b/version22/js/PAIR.js
new file mode 100644
index 0000000..e7c5878
--- /dev/null
+++ b/version22/js/PAIR.js
@@ -0,0 +1,650 @@
+/*
+	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.
+*/
+
+var PAIR = {
+/* Line function */
+	line: function(A,B,Qx,Qy)
+	{
+		var P=new ECP2();
+		var a,b,c;
+		var r=new FP12(1);
+		P.copy(A);
+
+		var ZZ=new FP2(P.getz()); //ZZ.copy(P.getz());
+		ZZ.sqr();
+		var D;
+		if (A==B) D=A.dbl(); 
+		else D=A.add(B);
+		if (D<0) return r;
+		var Z3=new FP2(A.getz()); //Z3.copy(A.getz());
+		c=new FP4(0);
+		var X,Y,T;
+		if (D===0)
+		{ /* Addition */
+			X=new FP2(B.getx()); //X.copy(B.getx());
+			Y=new FP2(B.gety()); //Y.copy(B.gety());
+			T=new FP2(P.getz()); //T.copy(P.getz());
+
+			T.mul(Y);
+			ZZ.mul(T);
+
+			var NY=new FP2(P.gety()); /*NY.copy(P.gety());*/ NY.neg();
+			ZZ.add(NY);
+			Z3.pmul(Qy);
+			T.mul(P.getx());
+			X.mul(NY);
+			T.add(X);
+			a=new FP4(Z3,T); //a.set(Z3,T);
+			ZZ.neg();
+			ZZ.pmul(Qx);
+			b=new FP4(ZZ); //b.seta(ZZ);
+		}
+		else
+		{ /* Doubling */
+			X=new FP2(P.getx()); //X.copy(P.getx());
+			Y=new FP2(P.gety()); //Y.copy(P.gety());
+			T=new FP2(P.getx()); //T.copy(P.getx());
+			T.sqr();
+			T.imul(3);
+
+			Y.sqr();
+			Y.add(Y);
+			Z3.mul(ZZ);
+			Z3.pmul(Qy);
+
+			X.mul(T);
+			X.sub(Y);
+			a=new FP4(Z3,X); //a.set(Z3,X);
+			T.neg();
+			ZZ.mul(T);
+
+			ZZ.pmul(Qx);
+
+			b=new FP4(ZZ); //b.seta(ZZ);
+		}
+		r.set(a,b,c);
+		return r;		
+	},
+
+/* Optimal R-ate pairing */
+	ate: function(P,Q)
+	{
+		var fa=new BIG(0); fa.rcopy(ROM.CURVE_Fra);
+		var fb=new BIG(0); fb.rcopy(ROM.CURVE_Frb);
+		var f=new FP2(fa,fb); //f.bset(fa,fb);
+	
+		var x=new BIG(0); x.rcopy(ROM.CURVE_Bnx);
+		var n=new BIG(x); //n.copy(x);
+		var K=new ECP2();
+		var lv;
+
+		if (ROM.CURVE_PAIRING_TYPE==ROM.BN_CURVE)
+		{
+			n.pmul(6); n.dec(2);
+		}
+		else
+			n.copy(x);
+		n.norm();
+
+		P.affine();
+		Q.affine();
+		var Qx=new FP(Q.getx()); //Qx.copy(Q.getx());
+		var Qy=new FP(Q.gety()); //Qy.copy(Q.gety());
+
+		var A=new ECP2();
+		var r=new FP12(1);
+
+		A.copy(P);
+		var nb=n.nbits();
+
+		for (var i=nb-2;i>=1;i--)
+		{
+			lv=PAIR.line(A,A,Qx,Qy);
+
+			r.smul(lv);
+
+			if (n.bit(i)==1)
+			{
+				lv=PAIR.line(A,P,Qx,Qy);
+				r.smul(lv);
+			}
+			r.sqr();
+		}
+		lv=PAIR.line(A,A,Qx,Qy);
+		r.smul(lv);
+		if (n.parity()==1)
+		{
+			lv=line(A,P,Qx,Qy);
+			r.smul(lv);
+		}
+
+/* R-ate fixup */
+		if (ROM.CURVE_PAIRING_TYPE==ROM.BN_CURVE)
+		{
+			r.conj();
+			K.copy(P);
+			K.frob(f);
+			A.neg();
+			lv=PAIR.line(A,K,Qx,Qy);
+			r.smul(lv);
+			K.frob(f);
+			K.neg();
+			lv=PAIR.line(A,K,Qx,Qy);
+			r.smul(lv);
+		}
+		return r;
+	},
+
+/* Optimal R-ate double pairing e(P,Q).e(R,S) */
+	ate2: function(P,Q,R,S)
+	{
+		var fa=new BIG(0); fa.rcopy(ROM.CURVE_Fra);
+		var fb=new BIG(0); fb.rcopy(ROM.CURVE_Frb);
+		var f=new FP2(fa,fb); //f.bset(fa,fb);
+		var x=new BIG(0); x.rcopy(ROM.CURVE_Bnx);
+
+		var n=new BIG(x); //n.copy(x);
+		var K=new ECP2();
+		var lv;
+
+		if (ROM.CURVE_PAIRING_TYPE==ROM.BN_CURVE)
+		{
+			n.pmul(6); n.dec(2);
+		}
+		else
+			n.copy(x);
+		n.norm();
+
+		P.affine();
+		Q.affine();
+		R.affine();
+		S.affine();
+
+		var Qx=new FP(Q.getx()); //Qx.copy(Q.getx());
+		var Qy=new FP(Q.gety()); //Qy.copy(Q.gety());
+
+		var Sx=new FP(S.getx()); //Sx.copy(S.getx());
+		var Sy=new FP(S.gety()); //Sy.copy(S.gety());
+
+		var A=new ECP2();
+		var B=new ECP2();
+		var r=new FP12(1);
+
+		A.copy(P);
+		B.copy(R);
+		var nb=n.nbits();
+
+		for (var i=nb-2;i>=1;i--)
+		{
+			lv=PAIR.line(A,A,Qx,Qy);
+			r.smul(lv);
+			lv=PAIR.line(B,B,Sx,Sy);
+			r.smul(lv);
+			if (n.bit(i)==1)
+			{
+				lv=PAIR.line(A,P,Qx,Qy);
+				r.smul(lv);
+				lv=PAIR.line(B,R,Sx,Sy);
+				r.smul(lv);
+			}
+			r.sqr();
+		}
+
+		lv=PAIR.line(A,A,Qx,Qy);
+		r.smul(lv);
+		lv=PAIR.line(B,B,Sx,Sy);
+		r.smul(lv);
+		if (n.parity()==1)
+		{
+			lv=line(A,P,Qx,Qy);
+			r.smul(lv);
+			lv=line(B,R,Sx,Sy);
+			r.smul(lv);
+		}
+		
+/* R-ate fixup required for BN curves */
+		if (ROM.CURVE_PAIRING_TYPE==ROM.BN_CURVE)
+		{
+			r.conj();
+
+			K.copy(P);
+			K.frob(f);
+			A.neg();
+			lv=PAIR.line(A,K,Qx,Qy);
+			r.smul(lv);
+			K.frob(f);
+			K.neg();
+			lv=PAIR.line(A,K,Qx,Qy);
+			r.smul(lv);
+
+			K.copy(R);
+			K.frob(f);
+			B.neg();
+			lv=PAIR.line(B,K,Sx,Sy);
+			r.smul(lv);
+			K.frob(f);
+			K.neg();
+			lv=PAIR.line(B,K,Sx,Sy);
+			r.smul(lv);
+		}
+		return r;
+	},
+
+/* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */
+	fexp: function(m)
+	{
+		var fa=new BIG(0); fa.rcopy(ROM.CURVE_Fra);
+		var fb=new BIG(0); fb.rcopy(ROM.CURVE_Frb);
+		var f=new FP2(fa,fb);
+		var x=new BIG(0); x.rcopy(ROM.CURVE_Bnx);
+
+		var r=new FP12(m); //r.copy(m);
+	
+/* Easy part of final exp */
+		var lv=new FP12(r); //lv.copy(r);
+		lv.inverse();
+		r.conj();
+		r.mul(lv);
+		lv.copy(r);
+		r.frob(f);	
+		r.frob(f);
+		r.mul(lv);
+
+/* Hard part of final exp */
+		if (ROM.CURVE_PAIRING_TYPE==ROM.BN_CURVE)
+		{
+			var x0,x1,x2,x3,x4,x5;			
+			lv.copy(r);
+			lv.frob(f);
+			x0=new FP12(lv); //x0.copy(lv);
+			x0.frob(f);
+			lv.mul(r);
+			x0.mul(lv);
+			x0.frob(f);
+			x1=new FP12(r); //x1.copy(r);
+			x1.conj();
+
+			x4=r.pow(x);
+
+			x3=new FP12(x4); //x3.copy(x4);
+			x3.frob(f);
+			x2=x4.pow(x);
+
+			x5=new FP12(x2); /*x5.copy(x2);*/  x5.conj();
+			lv=x2.pow(x);
+
+			x2.frob(f);
+			r.copy(x2); r.conj();
+
+			x4.mul(r);
+			x2.frob(f);
+
+			r.copy(lv);
+			r.frob(f);
+			lv.mul(r);
+
+			lv.usqr();
+			lv.mul(x4);
+			lv.mul(x5);
+			r.copy(x3);
+			r.mul(x5);
+			r.mul(lv);
+			lv.mul(x2);
+			r.usqr();
+			r.mul(lv);
+			r.usqr();
+			lv.copy(r);
+			lv.mul(x1);
+			r.mul(x0);
+			lv.usqr();
+			r.mul(lv);
+			r.reduce();
+		}
+		else
+		{
+			var y0,y1,y2,y3;
+// Ghamman & Fouotsa Method
+			y0=new FP12(r); y0.usqr();
+			y1=y0.pow(x);
+			x.fshr(1); y2=y1.pow(x); x.fshl(1);
+			y3=new FP12(r); y3.conj();
+			y1.mul(y3);
+
+			y1.conj();
+			y1.mul(y2);
+
+			y2=y1.pow(x);
+
+			y3=y2.pow(x);
+			y1.conj();
+			y3.mul(y1);
+
+			y1.conj();
+			y1.frob(f); y1.frob(f); y1.frob(f);
+			y2.frob(f); y2.frob(f);
+			y1.mul(y2);
+
+			y2=y3.pow(x);
+			y2.mul(y0);
+			y2.mul(r);
+
+			y1.mul(y2);
+			y2.copy(y3); y2.frob(f);
+			y1.mul(y2);
+			r.copy(y1);
+			r.reduce();
+
+
+/*
+			x0=new FP12(r);
+			x1=new FP12(r);
+			lv.copy(r); lv.frob(f);
+			x3=new FP12(lv); x3.conj(); x1.mul(x3);
+			lv.frob(f); lv.frob(f);
+			x1.mul(lv);
+
+			r.copy(r.pow(x));  //r=r.pow(x);
+			x3.copy(r); x3.conj(); x1.mul(x3);
+			lv.copy(r); lv.frob(f);
+			x0.mul(lv);
+			lv.frob(f);
+			x1.mul(lv);
+			lv.frob(f);
+			x3.copy(lv); x3.conj(); x0.mul(x3);
+
+			r.copy(r.pow(x));
+			x0.mul(r);
+			lv.copy(r); lv.frob(f); lv.frob(f);
+			x3.copy(lv); x3.conj(); x0.mul(x3);
+			lv.frob(f);
+			x1.mul(lv);
+
+			r.copy(r.pow(x));
+			lv.copy(r); lv.frob(f);
+			x3.copy(lv); x3.conj(); x0.mul(x3);
+			lv.frob(f);
+			x1.mul(lv);
+
+			r.copy(r.pow(x));
+			x3.copy(r); x3.conj(); x0.mul(x3);
+			lv.copy(r); lv.frob(f);
+			x1.mul(lv);
+
+			r.copy(r.pow(x));
+			x1.mul(r);
+
+			x0.usqr();
+			x0.mul(x1);
+			r.copy(x0);
+			r.reduce(); */
+		}
+		return r;
+	}
+};
+
+/* GLV method */
+PAIR.glv= function(e)
+{
+	var u=[];
+	if (ROM.CURVE_PAIRING_TYPE==ROM.BN_CURVE)
+	{
+		var i,j;
+		var t=new BIG(0);
+		var q=new BIG(0); q.rcopy(ROM.CURVE_Order);
+		var v=[];
+
+		for (i=0;i<2;i++)
+		{
+			t.rcopy(ROM.CURVE_W[i]);
+			var d=BIG.mul(t,e);
+			v[i]=new BIG(d.div(q));
+			u[i]=new BIG(0);
+		}
+		u[0].copy(e);
+		for (i=0;i<2;i++)
+			for (j=0;j<2;j++)
+			{
+				t.rcopy(ROM.CURVE_SB[j][i]);
+				t.copy(BIG.modmul(v[j],t,q));
+				u[i].add(q);
+				u[i].sub(t);
+				u[i].mod(q);
+			}
+	}
+	else
+	{ // -(x^2).P = (Beta.x,y)
+		var q=new BIG(0); q.rcopy(ROM.CURVE_Order);
+		var x=new BIG(0); x.rcopy(ROM.CURVE_Bnx);
+		var x2=BIG.smul(x,x);
+		u[0]=new BIG(e);
+		u[0].mod(x2);
+		u[1]=new BIG(e);
+		u[1].div(x2);
+		u[1].rsub(q);
+	}
+	return u;
+};
+
+/* Galbraith & Scott Method */
+PAIR.gs= function(e)
+{
+	var u=[];
+	if (ROM.CURVE_PAIRING_TYPE==ROM.BN_CURVE)
+	{
+		var i,j;
+		var t=new BIG(0);
+		var q=new BIG(0); q.rcopy(ROM.CURVE_Order);
+
+		var v=[];
+
+		for (i=0;i<4;i++)
+		{
+			t.rcopy(ROM.CURVE_WB[i]);
+			var d=BIG.mul(t,e);
+			v[i]=new BIG(d.div(q));
+			u[i]=new BIG(0);
+		}
+
+		u[0].copy(e);
+		for (i=0;i<4;i++)
+			for (j=0;j<4;j++)
+			{
+				t.rcopy(ROM.CURVE_BB[j][i]);
+				t.copy(BIG.modmul(v[j],t,q));
+				u[i].add(q);
+				u[i].sub(t);
+				u[i].mod(q);
+			}
+	}
+	else
+	{
+		var x=new BIG(0); x.rcopy(ROM.CURVE_Bnx);
+		var w=new BIG(e);
+		for (var i=0;i<4;i++)
+		{
+			u[i]=new BIG(w);
+			u[i].mod(x);
+			w.div(x);
+		}
+	}
+	return u;
+};	
+
+/* Multiply P by e in group G1 */
+PAIR.G1mul= function(P,e)
+{
+	var R;
+	if (ROM.USE_GLV)
+	{
+		P.affine();
+		R=new ECP();
+		R.copy(P);
+		var np,nn;
+		var Q=new ECP();
+		Q.copy(P);
+		var q=new BIG(0); q.rcopy(ROM.CURVE_Order);
+		var bcru=new BIG(0); bcru.rcopy(ROM.CURVE_Cru);
+		var cru=new FP(bcru);
+		var t=new BIG(0);
+		var u=PAIR.glv(e);
+
+		Q.getx().mul(cru);
+
+		np=u[0].nbits();
+		t.copy(BIG.modneg(u[0],q));
+		nn=t.nbits();
+		if (nn<np)
+		{
+			u[0].copy(t);
+			R.neg();
+		}
+
+		np=u[1].nbits();
+		t.copy(BIG.modneg(u[1],q));
+		nn=t.nbits();
+		if (nn<np)
+		{
+			u[1].copy(t);
+			Q.neg();
+		}
+
+		R=R.mul2(u[0],Q,u[1]);
+			
+	}
+	else
+	{
+		R=P.mul(e);
+	}
+	return R;
+};
+
+/* Multiply P by e in group G2 */
+PAIR.G2mul= function(P,e)
+{
+	var R;
+	if (ROM.USE_GS_G2)
+	{
+		var Q=[];
+		var fa=new BIG(0); fa.rcopy(ROM.CURVE_Fra);
+		var fb=new BIG(0); fb.rcopy(ROM.CURVE_Frb);
+		var f=new FP2(fa,fb); //f.bset(fa,fb);
+		var q=new BIG(0); q.rcopy(ROM.CURVE_Order);
+
+		var u=PAIR.gs(e);
+		var t=new BIG(0);
+		var i,np,nn;
+		P.affine();
+		Q[0]=new ECP2(); Q[0].copy(P);
+		for (i=1;i<4;i++)
+		{
+			Q[i]=new ECP2(); Q[i].copy(Q[i-1]);
+			Q[i].frob(f);
+		}
+
+		for (i=0;i<4;i++)
+		{
+			np=u[i].nbits();
+			t.copy(BIG.modneg(u[i],q));
+			nn=t.nbits();
+			if (nn<np)
+			{
+				u[i].copy(t);
+				Q[i].neg();
+			}
+		}
+
+		R=ECP2.mul4(Q,u);
+	}
+	else
+	{
+		R=P.mul(e);
+	}
+	return R;
+};
+
+/* Note that this method requires a lot of RAM! Better to use compressed XTR method, see FP4.js */
+PAIR.GTpow= function(d,e)
+{
+	var r;
+	if (ROM.USE_GS_GT)
+	{
+		var g=[];
+		var fa=new BIG(0); fa.rcopy(ROM.CURVE_Fra);
+		var fb=new BIG(0); fb.rcopy(ROM.CURVE_Frb);
+		var f=new FP2(fa,fb);
+		var q=new BIG(0); q.rcopy(ROM.CURVE_Order);
+		var t=new BIG(0);
+		var i,np,nn;
+		var u=PAIR.gs(e);
+
+		g[0]=new FP12(d);
+		for (i=1;i<4;i++)
+		{
+			g[i]=new FP12(0); g[i].copy(g[i-1]);
+			g[i].frob(f);
+		}
+		for (i=0;i<4;i++)
+		{
+			np=u[i].nbits();
+			t.copy(BIG.modneg(u[i],q));
+			nn=t.nbits();
+			if (nn<np)
+			{
+				u[i].copy(t);
+				g[i].conj();
+			}
+		}
+		r=FP12.pow4(g,u);
+	}
+	else
+	{
+		r=d.pow(e);
+	}
+	return r;
+};
+
+/* test group membership - no longer needed */
+/* with GT-Strong curve, now only check that m!=1, conj(m)*m==1, and m.m^{p^4}=m^{p^2} */
+/*
+PAIR.GTmember= function(m)
+{
+	if (m.isunity()) return false;
+	var r=new FP12(m);
+	r.conj();
+	r.mul(m);
+	if (!r.isunity()) return false;
+
+	var fa=new BIG(0); fa.rcopy(ROM.CURVE_Fra);
+	var fb=new BIG(0); fb.rcopy(ROM.CURVE_Frb);
+	var f=new FP2(fa,fb); //f.bset(fa,fb);
+
+	r.copy(m); r.frob(f); r.frob(f);
+	var w=new FP12(r); w.frob(f); w.frob(f);
+	w.mul(m);
+	if (!ROM.GT_STRONG)
+	{
+		if (!w.equals(r)) return false;
+		var x=new BIG(0); x.rcopy(ROM.CURVE_Bnx);
+		r.copy(m); w=r.pow(x); w=w.pow(x);
+		r.copy(w); r.sqr(); r.mul(w); r.sqr();
+		w.copy(m); w.frob(f);
+	}
+	return w.equals(r);
+};
+*/
diff --git a/version22/js/RAND.js b/version22/js/RAND.js
new file mode 100644
index 0000000..9e2dddd
--- /dev/null
+++ b/version22/js/RAND.js
@@ -0,0 +1,148 @@
+/*
+	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.
+*/
+
+/*
+ *   Cryptographic strong random number generator 
+ *
+ *   Unguessable seed -> SHA -> PRNG internal state -> SHA -> random numbers
+ *   Slow - but secure
+ *
+ *   See ftp://ftp.rsasecurity.com/pub/pdfs/bull-1.pdf for a justification
+ */
+
+/* Marsaglia & Zaman Random number generator constants */
+
+
+var RAND=function() 
+{
+/* Cryptographically strong pseudo-random number generator */
+	this.ira=[]; /* random number...   */
+	this.rndptr=0;  /* ...array & pointer */
+	this.borrow=0;
+	this.pool_ptr=0;
+	this.pool=[]; /* random pool */
+	this.clean();
+};
+
+RAND.prototype=
+{
+	NK:21,
+	NJ:6,
+	NV:8,
+
+/* Terminate and clean up */
+	clean : function()
+	{
+		var i;
+		for (i=0;i<32;i++) this.pool[i]=0;
+		for (i=0;i<this.NK;i++) this.ira[i]=0;
+		this.rndptr=0;
+		this.borrow=0;
+		this.pool_ptr=0;
+	},
+
+	sbrand: function()
+	{ /* Marsaglia & Zaman random number generator */
+		var i,k;
+		var pdiff,t; /* unsigned 32-bit */
+
+		this.rndptr++;
+		if (this.rndptr<this.NK) return this.ira[this.rndptr];
+		this.rndptr=0;
+		for (i=0,k=this.NK-this.NJ;i<this.NK;i++,k++)
+		{ /* calculate next NK values */
+			if (k==this.NK) k=0;
+			t=this.ira[k]>>>0;
+			pdiff=(t - this.ira[i] - this.borrow)|0;
+			pdiff>>>=0;  /* This is seriously wierd shit. I got to do this to get a proper unsigned comparison... */
+			if (pdiff<t) this.borrow=0;
+			if (pdiff>t) this.borrow=1;
+			this.ira[i]=(pdiff|0); 
+		}
+		return this.ira[0];
+	},
+
+	sirand: function(seed)
+	{
+		var i,inn;
+		var t,m=1;
+		this.borrow=0;
+		this.rndptr=0;
+		seed>>>=0;
+		this.ira[0]^=seed;
+
+		for (i=1;i<this.NK;i++)
+		{ /* fill initialisation vector */
+			inn=(this.NV*i)%this.NK;
+			this.ira[inn]^=m;      /* note XOR */
+			t=m;
+			m=(seed-m)|0;
+			seed=t;
+		}
+
+		for (i=0;i<10000;i++) this.sbrand(); /* "warm-up" & stir the generator */
+	},
+
+	fill_pool: function()
+	{
+		var sh=new HASH256();
+		for (var i=0;i<128;i++) sh.process(this.sbrand());
+		this.pool=sh.hash();
+		this.pool_ptr=0;
+	},
+
+/* Initialize RNG with some real entropy from some external source */
+	seed: function(rawlen,raw)
+	{ /* initialise from at least 128 byte string of raw random entropy */
+		var i;
+		var digest=[];
+		var b=[];
+		var sh=new HASH256();
+		this.pool_ptr=0;
+		for (i=0;i<this.NK;i++) this.ira[i]=0;
+		if (rawlen>0)
+		{
+			for (i=0;i<rawlen;i++)
+				sh.process(raw[i]);
+			digest=sh.hash();
+
+/* initialise PRNG from distilled randomness */
+			for (i=0;i<8;i++) 
+			{
+				b[0]=digest[4*i]; b[1]=digest[4*i+1]; b[2]=digest[4*i+2]; b[3]=digest[4*i+3];
+				this.sirand(RAND.pack(b));
+			}
+		}
+		this.fill_pool();
+	},
+
+/* get random byte */
+	getByte: function()
+	{ 
+		var r=this.pool[this.pool_ptr++];
+		if (this.pool_ptr>=32) this.fill_pool();
+		return (r&0xff);
+	}
+};
+
+RAND.pack= function(b)
+{ /* pack 4 bytes into a 32-bit Word */
+		return (((b[3])&0xff)<<24)|((b[2]&0xff)<<16)|((b[1]&0xff)<<8)|(b[0]&0xff);
+};
+
diff --git a/version22/js/ROM.js b/version22/js/ROM.js
new file mode 100644
index 0000000..dcf2af1
--- /dev/null
+++ b/version22/js/ROM.js
@@ -0,0 +1,716 @@
+/*
+	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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+var ROM={
+	CHUNK: 32,
+
+/* Field Type */
+	NOT_SPECIAL: 0,
+	PSEUDO_MERSENNE: 1,
+	GENERALISED_MERSENNE: 2,
+	MONTGOMERY_FRIENDLY: 3,
+
+/* Curve Type */
+	WEIERSTRASS: 0,
+	EDWARDS: 1,
+	MONTGOMERY: 2,
+	BN_CURVE: 0,
+	BLS_CURVE: 1,
+
+/* Finite field support - for RSA, DH etc. */
+	FFLEN: 4, /* Defines Finite Field size n = BIGBITS.FFLEN, where FFLEN mustbe power of 2 */
+
+/*** Enter Some Field details here  ***/
+/* C25519 */
+//	MODBITS: 255, /* Number of bits in Modulus */
+//	MOD8: 5,  /* Modulus mod 8 */
+//	BASEBITS: 24,
+//	AES_S: 0,
+
+/* NIST Curve */
+/*  Brainpool */
+//	MODBITS: 256,
+//	MOD8: 7,
+//	BASEBITS: 24,
+//  AES_S: 0
+
+/* BN254/BNCX */
+	MODBITS: 254,
+	MOD8: 3,
+	BASEBITS: 24,
+	AES_S: 0,
+
+/* BLS383 */
+//	MODBITS: 383,
+//	MOD8: 3,
+//	BASEBITS: 23,
+//	AES_S: 0,
+
+/* BN454 */
+//	MODBITS: 454,
+//	MOD8: 3,
+//	BASEBITS: 23,
+//	AES_S: 128,
+
+/* BLS455 */
+//	MODBITS: 455,
+//	MOD8: 3,
+//	BASEBITS: 23,
+//	AES_S: 128,	
+
+/* MF254 */
+//	MODBITS: 254,
+//	MOD8: 7,
+//	BASEBITS: 24,
+
+/* MS255 */
+//	MODBITS: 255,
+//	MOD8: 3,
+//	BASEBITS: 24,
+//  AES_S: 0
+
+/* MF256 */
+//	MODBITS: 256,
+//	MOD8: 7,
+//	BASEBITS: 24,
+//  AES_S: 0
+
+/* MS256 */
+//	MODBITS: 256,
+//	MOD8: 3,
+//	BASEBITS: 24,
+//  AES_S: 0
+
+/* ANSSI */
+//  MODBITS: 256,
+//  MOD8: 3,
+//	BASEBITS: 24,
+//  AES_S: 0
+
+/* HIFIVE */
+//  MODBITS: 336,
+//  MOD8: 5,
+//  BASEBITS: 23,
+//  AES_S: 128
+
+/* GOLDILOCKS */
+//  MODBITS: 448,
+//  MOD8: 5,
+//  BASEBITS: 23,	
+//  AES_S: 0
+
+/* C41417 */
+//  MODBITS: 414,
+//  MOD8: 7,
+//  BASEBITS: 22,
+//  AES_S: 0
+
+/* NIST384 */
+//  MODBITS: 384,
+//  MOD8: 7,
+//  BASEBITS: 23,
+//  AES_S: 0
+
+/* NIST521 */
+//  MODBITS: 521,
+//  MOD8: 7,
+//  BASEBITS: 23,
+//  AES_S: 0
+
+/* Specify Field here */
+
+/* C25519 */
+//	MODTYPE: 1, 
+//	Modulus: [0xFFFFED,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0x7FFF],
+//	MConst: 19,
+
+/* BNCX */
+	MODTYPE:0,
+	Modulus: [0x1B55B3,0x23EF5C,0xE1BE66,0x18093E,0x3FD6EE,0x66D324,0x647A63,0xB0BDDF,0x702A0D,0x8,0x2400],
+	MConst:0x789E85,
+
+/* BLS383 */
+//	MODTYPE:0,
+//	Modulus: [0x2D556B,0x556A55,0x75EAB2,0x23AFBA,0x1BB01,0x2BAEA4,0x5CC20F,0x758B67,0x20F99,0x640A63,0x69A3A8,0x6009AA,0x2A7852,0x20B8AA,0x7DD718,0x104054,0x7AC5],
+//	MConst:0x23D0BD,
+
+/* HIFIVE */
+//	MODTYPE:1,
+//	Modulus: [0x7FFFFD,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x3FFF],
+//	MConst: 0x3,
+
+/* GOLDILOCKS */
+//	MODTYPE: 2,
+//	Modulus: [0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7DFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FF],
+//	MConst: 0x1,
+
+/* C41417 */
+//	MODTYPE: 1,
+//	Modulus: [0x3FFFEF,0x3FFFFF,0x3FFFFF,0x3FFFFF,0x3FFFFF,0x3FFFFF,0x3FFFFF,0x3FFFFF,0x3FFFFF,0x3FFFFF,0x3FFFFF,0x3FFFFF,0x3FFFFF,0x3FFFFF,0x3FFFFF,0x3FFFFF,0x3FFFFF,0x3FFFFF,0x3FFFF],
+//	MConst: 0x11,
+
+/* NIST384 */
+//  MODTYPE: 0,
+//  Modulus: [0x7FFFFF,0x1FF,0x0,0x0,0x7FFFF0,0x7FDFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0xFFFF],
+//  MConst: 0x1,
+
+/* NIST521 */
+//  MODTYPE: 1,
+//  Modulus: [0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFF],
+//  MConst: 0x1,
+
+/* BN254 Curve */
+//MODTYPE:0,
+//Modulus: [0x13,0x0,0x13A700,0x0,0x210000,0x861,0x800000,0xBA344D,0x1,0x648240,0x2523],
+//MConst:0x9435E5,
+
+/* BN454 Curve */
+//MODTYPE:0,
+//Modulus: [0x13,0x9C00,0x100000,0x700004,0x6006C4,0x4A109,0x514200,0x640000,0x80091,0x803AA,0x36A22,0x10EA20,0x21C000,0x288012,0x1B006C,0x12D8,0x9090,0x1B000,0x24000,0x12000],
+//MConst:0x1435E5,
+
+/* BLS455 Curve */
+//MODTYPE:0,
+//Modulus: [0x2AB,0x300,0x5AAA80,0x59554A,0x589556,0x2374D8,0x2B3A1B,0x6DCCCA,0x14B8B3,0x29F966,0x2F64E5,0x6AB11A,0x63A5B1,0x7ECCB,0x2480C0,0x7CADA,0x2AA00E,0x72AAAE,0x655555,0x2AAAA],
+//MConst:0x4017FD,
+
+/* BNT Curve */
+//MODTYPE:0,
+//Modulus: [0xB4A713,0xBBFEEE,0xBABE9D,0x14F464,0x8A5556,0xD5F06E,0x3696F8,0xFA0BAB,0x17014E,0x20DB65,0x2401],
+//MConst:0x14C4E5,
+
+/* BNT2 */
+//MODTYPE:0,
+//Modulus: [0x60A48B,0xDC2BB4,0x51E8B2,0x28F0D6,0xCF93E4,0xD00081,0xF3B89,0xB74E20,0xF5AAD,0x48241,0x2400],
+//MConst:0x505CDD,
+
+/* NIST Modulus */
+//	MODTYPE:0,
+//	Modulus: [0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0x0,0x0,0x0,0x0,0x1,0xFFFF00,0xFFFF],
+//	MConst:0x1,
+
+/* MF254 Modulus */
+//	MODTYPE:3,
+//	Modulus: [0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0x3F80],
+//	MConst:0x3F81,
+
+/* MS255 Modulus */
+//MODTYPE:1,
+//Modulus: [0xFFFD03,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0x7FFF],
+//MConst:0x2FD,
+
+/* MS256 Modulus */
+//MODTYPE:1,
+//Modulus: [0xFFFF43,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFF],
+//MConst:0xBD,
+
+/* MF256 Modulus */
+//MODTYPE:3,
+//Modulus: [0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFA7],
+//MConst:0xFFA8,
+
+/*  Brainpool Modulus */
+//	MODTYPE:0,
+//	Modulus: [0x6E5377,0x481D1F,0x282013,0xD52620,0x3BF623,0x8D726E,0x909D83,0x3E660A,0xEEA9BC,0x57DBA1,0xA9FB],
+//	MConst:0xFD89B9,
+
+/* ANSSI Modulus */
+//  MODTYPE:0,
+//  Modulus: [0x6E9C03,0xF353D8,0x6DE8FC,0xABC8CA,0x61ADBC,0x435B39,0xE8CE42,0x10126D,0x3AD58F,0x178C0B,0xF1FD],
+//  MConst:0x4E1155,
+
+/* Specify Curve here */
+
+/* ED25519 Edwards */
+//	CURVETYPE: 1,  
+//	CURVE_A : -1,
+//	CURVE_B : [0x5978A3,0x4DCA13,0xAB75EB,0x4141D8,0x700A4D,0xE89800,0x797779,0x8CC740,0x6FFE73,0x6CEE2B,0x5203],
+//	CURVE_Order: [0xF5D3ED,0x631A5C,0xD65812,0xA2F79C,0xDEF9DE,0x14,0x0,0x0,0x0,0x0,0x1000],
+//	CURVE_Gx: [0x25D51A,0x2D608F,0xB2C956,0x9525A7,0x2CC760,0xDC5C69,0x31FDD6,0xC0A4E2,0x6E53FE,0x36D3CD,0x2169],
+//	CURVE_Gy: [0x666658,0x666666,0x666666,0x666666,0x666666,0x666666,0x666666,0x666666,0x666666,0x666666,0x6666],
+
+/* Curve25519 */
+//	CURVETYPE: 2,  
+//	CURVE_A : 486662,
+//	CURVE_B : [0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+//	CURVE_Order: [0xF5D3ED,0x631A5C,0xD65812,0xA2F79C,0xDEF9DE,0x14,0x0,0x0,0x0,0x0,0x1000],
+//	CURVE_Gx: [0x9,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+//	CURVE_Gy: [0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+
+/* NIST Curve */
+//	CURVETYPE:0,
+//	CURVE_A : -3,
+//	CURVE_B : [0xD2604B,0x3C3E27,0xF63BCE,0xCC53B0,0x1D06B0,0x86BC65,0x557698,0xB3EBBD,0x3A93E7,0x35D8AA,0x5AC6],
+//	CURVE_Order:[0x632551,0xCAC2FC,0x84F3B9,0xA7179E,0xE6FAAD,0xFFFFBC,0xFFFFFF,0xFFFFFF,0x0,0xFFFF00,0xFFFF],
+//	CURVE_Gx :[0x98C296,0x3945D8,0xA0F4A1,0x2DEB33,0x37D81,0x40F277,0xE563A4,0xF8BCE6,0x2C4247,0xD1F2E1,0x6B17],
+//	CURVE_Gy :[0xBF51F5,0x406837,0xCECBB6,0x6B315E,0xCE3357,0x9E162B,0x4A7C0F,0x8EE7EB,0x1A7F9B,0x42E2FE,0x4FE3],
+
+/* MF254 Modulus, Weierstrass Curve */
+//CURVETYPE:0,
+//CURVE_A : -3,
+//CURVE_B : [0xFFD08D,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0x3F80],
+//CURVE_Order:[0x8DF83F,0x19C4AF,0xC06FA4,0xDA375,0x818BEA,0xFFFFEB,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0x3F80],
+//CURVE_Gx :[0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+//CURVE_Gy :[0xD4EBC,0xDF37F9,0x31AD65,0xF85119,0xB738E3,0x8AEBDF,0x75BD77,0x4AE15A,0x2E5601,0x3FD33B,0x140E],
+
+/* MF254 Modulus, Edwards Curve */
+//CURVETYPE:1,
+//CURVE_A : -1,
+//CURVE_B : [0x367B,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+//CURVE_Order:[0x6E98C7,0xD3FEC4,0xB0EAF3,0x8BD62F,0x95306C,0xFFFFEB,0xFFFFFF,0xFFFFFF,0xFFFFFF,0x3FFFFF,0xFE0],
+//CURVE_Gx :[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+//CURVE_Gy :[0x2701E5,0xD0FDAF,0x187C52,0xE3212,0x329A84,0x3F4E36,0xD50236,0x951D00,0xA4C335,0xE690D6,0x19F0],
+
+
+/* MF254 Modulus, Montgomery Curve */
+//	CURVETYPE: 2,  
+//	CURVE_A : -55790,
+//	CURVE_B : [0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+//	CURVE_Order: [0x6E98C7,0xD3FEC4,0xB0EAF3,0x8BD62F,0x95306C,0xFFFFEB,0xFFFFFF,0xFFFFFF,0xFFFFFF,0x3FFFFF,0xFE0],
+//	CURVE_Gx: [0x3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+//	CURVE_Gy: [0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+
+/* MS255 Modulus, Weierstrass Curve */
+//CURVETYPE:0,
+//CURVE_A : -3,
+//CURVE_B : [0xFFAB46,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0x7FFF],
+//CURVE_Order:[0x594AEB,0xAC983C,0xDFAB8F,0x3AD2B3,0x4A3828,0xFFFF86,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0x7FFF],
+//CURVE_Gx :[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+//CURVE_Gy :[0xCB44BA,0xFF6769,0xD1733,0xDDFDA6,0xB6C78C,0x7D177D,0xF9B2FF,0x921EBF,0xBA7833,0x6AC0ED,0x6F7A],
+
+/* MS255 Modulus, Edwards Curve */
+//CURVETYPE:1,
+//CURVE_A : -1,
+//CURVE_B : [0xEA97,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+//CURVE_Order:[0x36EB75,0xD1ED04,0x2EAC49,0xEDA683,0xF1A785,0xFFFFDC,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0x1FFF],
+//CURVE_Gx :[0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+//CURVE_Gy :[0x8736A0,0x255BD0,0x45BA2A,0xED445A,0x914B8A,0x47E552,0xDD8E0C,0xEC254C,0x7BB545,0x78534A,0x26CB],
+
+/* MS255 Modulus, Montgomery Curve */
+//	CURVETYPE: 2,  
+//	CURVE_A : -240222,
+//	CURVE_B : [0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+//	CURVE_Order: [0x36EB75,0xD1ED04,0x2EAC49,0xEDA683,0xF1A785,0xFFFFDC,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0x1FFF],
+//	CURVE_Gx: [0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+//	CURVE_Gy: [0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+
+/* MS256 Modulus, Weierstrass Curve */
+//CURVETYPE:0,
+//CURVE_A : -3,
+//CURVE_B : [0x25581,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+//CURVE_Order:[0x51A825,0x202947,0x6020AB,0xEA265C,0x3C8275,0xFFFFE4,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFF],
+//CURVE_Gx :[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+//CURVE_Gy :[0xB56C77,0x6306C2,0xC10BF4,0x75894E,0x2C2F93,0xDD6BD0,0x6CCEEE,0xFC82C9,0xE466D7,0x1853C1,0x696F],
+
+/* MS256 Modulus, Edwards Curve */
+//CURVETYPE:1,
+//CURVE_A : -1,
+//CURVE_B : [0x3BEE,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+//CURVE_Order:[0x22B4AD,0x4E6F11,0x64E5B8,0xD0A6BC,0x6AA55A,0xFFFFBE,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0x3FFF],
+//CURVE_Gx :[0xD,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+//CURVE_Gy :[0x1CADBA,0x6FB533,0x3F707F,0x824D30,0x2A6D63,0x46BFBE,0xB39FA0,0xA3D330,0x1276DB,0xB41E2A,0x7D0A],
+
+/* MS256 Modulus, Montgomery Curve */
+//	CURVETYPE: 2,  
+//	CURVE_A : -61370,
+//	CURVE_B : [0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+//  CURVE_Order:[0x22B4AD,0x4E6F11,0x64E5B8,0xD0A6BC,0x6AA55A,0xFFFFBE,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0x3FFF],
+//	CURVE_Gx: [0xb,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+//	CURVE_Gy: [0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+
+/* MF256 Modulus, Weierstrass Curve */
+//CURVETYPE:0,
+//CURVE_A : -3,
+//CURVE_B : [0x14E6A,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+//CURVE_Order:[0x9857EB,0xC5E1A7,0x4B9D10,0xE6E507,0x517513,0xFFFFFC,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFA7],
+//CURVE_Gx :[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+//CURVE_Gy :[0x724D2A,0x954C2B,0x661007,0x8D94DC,0x6947EB,0xAE2895,0x26123D,0x7BABBA,0x1808CE,0x7C87BE,0x2088],
+
+/* MF256 Modulus, Edwards Curve */
+//CURVETYPE:1,
+//CURVE_A : -1,
+//CURVE_B : [0x350A,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+//CURVE_Order:[0xEC7BAB,0x2EDED8,0xC966D9,0xB86733,0x54BBAF,0xFFFFB1,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0x3FE9],
+//CURVE_Gx :[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+//CURVE_Gy :[0xF3C908,0xA722F2,0x8D7DEA,0x8DFEA6,0xC05E64,0x1AACA0,0xF3DB2C,0xEAEBEE,0xCC4D5A,0xD4F8F8,0xDAD8],
+
+/* MF256 Modulus, Montgomery Curve */
+//	CURVETYPE: 2,  
+//	CURVE_A : -54314,
+//	CURVE_B : [0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+//  CURVE_Order:[0xEC7BAB,0x2EDED8,0xC966D9,0xB86733,0x54BBAF,0xFFFFB1,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0x3FE9],
+//	CURVE_Gx: [0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+//	CURVE_Gy: [0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+
+/* Brainpool */
+//	CURVETYPE:0,
+//	CURVE_A : -3,
+//	CURVE_B : [0xE92B04,0x8101FE,0x256AE5,0xAF2F49,0x93EBC4,0x76B7BF,0x733D0B,0xFE66A7,0xD84EA4,0x61C430,0x662C],
+//	CURVE_Order:[0x4856A7,0xE8297,0xF7901E,0xB561A6,0x397AA3,0x8D718C,0x909D83,0x3E660A,0xEEA9BC,0x57DBA1,0xA9FB],
+//	CURVE_Gx :[0x1305F4,0x91562E,0x2B79A1,0x7AAFBC,0xA142C4,0x6149AF,0xB23A65,0x732213,0xCFE7B7,0xEB3CC1,0xA3E8],
+//	CURVE_Gy :[0x25C9BE,0xE8F35B,0x1DAB,0x39D027,0xBCB6DE,0x417E69,0xE14644,0x7F7B22,0x39C56D,0x6C8234,0x2D99],
+
+/* ANSSI */
+//  CURVETYPE:0,
+//  CURVE_A : -3,
+//  CURVE_B : [0x7BB73F,0xED967B,0x803075,0xE4B1A1,0xEC0C9A,0xC00FDF,0x754A44,0xD4ABA,0x28A930,0x3FCA54,0xEE35],
+//  CURVE_Order:[0xD655E1,0xD459C6,0x941FFD,0x40D2BF,0xDC67E1,0x435B53,0xE8CE42,0x10126D,0x3AD58F,0x178C0B,0xF1FD],
+//  CURVE_Gx :[0x8F5CFF,0x7A2DD9,0x164C9,0xAF98B7,0x27D2DC,0x23958C,0x4749D4,0x31183D,0xC139EB,0xD4C356,0xB6B3],
+//  CURVE_Gy :[0x62CFB,0x5A1554,0xE18311,0xE8E4C9,0x1C307,0xEF8C27,0xF0F3EC,0x1F9271,0xB20491,0xE0F7C8,0x6142],
+
+/* HIFIVE */
+//  CURVETYPE:1,
+//  CURVE_A : 1,
+//  CURVE_B : [0x2B67,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+//  CURVE_Order:[0x1FA805,0x2B2E7D,0x29ECBE,0x3FC9DD,0xBD6B8,0x530A18,0x45057E,0x3,0x0,0x0,0x0,0x0,0x0,0x0,0x800],
+//  CURVE_Gx :[0xC,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+//  CURVE_Gy :[0x7E8632,0xD0A0B,0x6C4AFB,0x501B2E,0x55650C,0x36DB6B,0x1FBD0D,0x61C08E,0x314B46,0x70A7A3,0x587401,0xC70E0,0x56502E,0x38C2D6,0x303],
+
+/* GOLDILOCKS */
+//  CURVETYPE:1,
+//  CURVE_A : 1,
+//  CURVE_B : [0x7F6756,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7DFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FF],
+//  CURVE_Order:[0x5844F3,0x52556,0x548DE3,0x6E2C7A,0x4C2728,0x52042D,0x6BB58D,0x276DA4,0x23E9C4,0x7EF994,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x1FF],
+//  CURVE_Gx :[0x555555,0x2AAAAA,0x555555,0x2AAAAA,0x555555,0x2AAAAA,0x555555,0x2AAAAA,0x555555,0x52AAAA,0x2AAAAA,0x555555,0x2AAAAA,0x555555,0x2AAAAA,0x555555,0x2AAAAA,0x555555,0x2AAAAA,0x555],
+//  CURVE_Gy :[0x1386ED,0x779BD5,0x2F6BAB,0xE6D03,0x4B2BED,0x131777,0x4E8A8C,0x32B2C1,0x44B80D,0x6515B1,0x5F8DB5,0x426EBD,0x7A0358,0x6DDA,0x21B0AC,0x6B1028,0xDB359,0x15AE09,0x17A58D,0x570],
+
+/* C41417 */
+//  CURVETYPE:1,
+//  CURVE_A : 1,
+//  CURVE_B : [0xE21,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+//  CURVE_Order:[0x6AF79,0x69784,0x1B0E7,0x18F3C6,0x338AD,0xDBC70,0x6022B,0x533DC,0x3CC924,0x3FFFAC,0x3FFFFF,0x3FFFFF,0x3FFFFF,0x3FFFFF,0x3FFFFF,0x3FFFFF,0x3FFFFF,0x3FFFFF,0x7FFF],
+//  CURVE_Gx :[0xBC595,0x204BCF,0xC4FD3,0x14DF19,0x33FAA8,0x4C069,0x16BA11,0x2AD35B,0x1498A4,0x15FFCD,0x3EC7F,0x27D130,0xD4636,0x9B97F,0x631C3,0x8630,0x144330,0x241450,0x1A334],
+//  CURVE_Gy :[0x22,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+
+/* NIST384 */
+//  CURVETYPE:0,
+//  CURVE_A : -3,
+//  CURVE_B : [0x6C2AEF,0x11DBA7,0x74AA17,0x51768C,0x6398D8,0x6B58CA,0x5404E1,0xA0447,0x411203,0x5DFD02,0x607671,0x4168C8,0x56BE3F,0x1311C0,0xFB9F9,0x17D3F1,0xB331],
+//  CURVE_Order:[0x452973,0x32D599,0x6BB3B0,0x45853B,0x20DB24,0x3BEB03,0x7D0DCB,0x31A6C0,0x7FFFC7,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0xFFFF],
+//  CURVE_Gx :[0x760AB7,0x3C70E4,0x30E951,0x7AA94B,0x2F25DB,0x470AA0,0x20950A,0x7BA0F0,0x1B9859,0x45174F,0x3874ED,0x56BA3,0x71EF32,0x71D638,0x22C14D,0x65115F,0xAA87],
+//  CURVE_Gy :[0x6A0E5F,0x3AF921,0x75E90C,0x6BF40C,0xB1CE1,0x18014C,0x6D7C2E,0x6D1889,0x147CE9,0x7A5134,0x63D076,0x16E14F,0xBF929,0x6BB3D3,0x98B1B,0x6F254B,0x3617],
+
+/* NIST521 */
+//  CURVETYPE:0,
+//  CURVE_A : -3,
+//  CURVE_B : [0x503F00,0x3FA8D6,0x47BD14,0x6961A7,0x3DF883,0x60E6AE,0x4EEC6F,0x29605E,0x137B16,0x23D8FD,0x5864E5,0x84F0A,0x1918EF,0x771691,0x6CC57C,0x392DCC,0x6EA2DA,0x6D0A81,0x688682,0x50FC94,0x18E1C9,0x27D72C,0x1465],
+//  CURVE_Order:[0x386409,0x6E3D22,0x3AEDBE,0x4CE23D,0x5C9B88,0x3A0776,0x3DC269,0x6600A4,0x166B7F,0x77E5F,0x461A1E,0x7FFFD2,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFF],
+//  CURVE_Gx :[0x65BD66,0x7C6385,0x6FE5F9,0x2B5214,0xB3C18,0x1BC669,0x68BFEA,0xEE093,0x5928FE,0x6FDFCE,0x52D79,0x69EDD5,0x7606B4,0x3F0515,0x4FED48,0x409C82,0x429C64,0x472B68,0x7B2D98,0x4E6CF1,0x70404E,0x31C0D6,0x31A1],
+//  CURVE_Gy :[0x516650,0x28ED3F,0x222FA,0x139612,0x47086A,0x6C26A7,0x4FEB41,0x285C80,0x2640C5,0x32BDE8,0x5FB9CA,0x733164,0x517273,0x2F5F7,0x66D11A,0x2224AB,0x5998F5,0x58FA37,0x297ED0,0x22E4,0x9A3BC,0x252D4F,0x460E],
+
+/* BNCX Curve */	
+
+	CURVETYPE:0,
+	CURVE_PAIRING_TYPE: 0,
+	CURVE_A : 0,
+	CURVE_B : [0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+	CURVE_Cof : [0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+	CURVE_Order:[0xEB1F6D,0xC0A636,0xCEBE11,0xCC906,0x3FD6EE,0x66D2C4,0x647A63,0xB0BDDF,0x702A0D,0x8,0x2400],
+	CURVE_Bnx:[0xC012B1,0x3,0x4000],
+	CURVE_Cru:[0x235C97,0x931794,0x5631E0,0x71EF87,0xBDDF64,0x3F1440,0xCA8,0x480000],
+	CURVE_Fra:[0xC80EA3,0x83355,0x215BD9,0xF173F8,0x677326,0x189868,0x8AACA7,0xAFE18B,0x3A0164,0x82FA6,0x1359],
+	CURVE_Frb:[0x534710,0x1BBC06,0xC0628D,0x269546,0xD863C7,0x4E3ABB,0xD9CDBC,0xDC53,0x3628A9,0xF7D062,0x10A6],
+	CURVE_Pxa:[0xD2EC74,0x1CEEE4,0x26C085,0xA03E27,0x7C85BF,0x4BBB90,0xF5C3,0x358B25,0x53B256,0x2D2C70,0x1968],
+	CURVE_Pxb:[0x29CFE1,0x8E8B2E,0xF47A5,0xC209C3,0x1B97B0,0x9743F8,0x37A8E9,0xA011C9,0x19F64A,0xB9EC3E,0x1466],
+	CURVE_Pya:[0xBE09F,0xFCEBCF,0xB30CFB,0x847EC1,0x61B33D,0xE20963,0x157DAE,0xD81E22,0x332B8D,0xEDD972,0xA79],
+	CURVE_Pyb:[0x98EE9D,0x4B2288,0xEBED90,0x69D2ED,0x864EA5,0x3461C2,0x512D8D,0x35C6E4,0xC4C090,0xC39EC,0x616],
+	CURVE_Gx :[0x1B55B2,0x23EF5C,0xE1BE66,0x18093E,0x3FD6EE,0x66D324,0x647A63,0xB0BDDF,0x702A0D,0x8,0x2400],
+	CURVE_Gy :[0x1],
+
+// Arrays must be padded!
+
+	CURVE_W:[[0x2FEB83,0x634916,0x120054,0xB4038,0x0,0x60,0x0,0x0,0x0,0x0,0x0],[0x802561,0x7,0x8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],
+	CURVE_SB:[[[0xB010E4,0x63491D,0x128054,0xB4038,0x0,0x60,0x0,0x0,0x0,0x0,0x0],
+	           [0x802561,0x7,0x8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],
+			   [[0x802561,0x7,0x8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+			   [0xBB33EA,0x5D5D20,0xBCBDBD,0x188CE,0x3FD6EE,0x66D264,0x647A63,0xB0BDDF,0x702A0D,0x8,0x2400]]],
+	CURVE_WB:[[0x7A84B0,0x211856,0xB0401C,0x3C012,0x0,0x20,0x0,0x0,0x0,0x0,0x0],
+	          [0x220475,0xF995BE,0x9A36CD,0xA8CA7F,0x7E94ED,0x2A0DC0,0x870,0x300000,0x0,0x0,0x0],
+			  [0xF10B93,0xFCCAE0,0xCD3B66,0xD4653F,0x3F4A76,0x1506E0,0x438,0x180000,0x0,0x0,0x0],
+			  [0xFAAA11,0x21185D,0xB0C01C,0x3C012,0x0,0x20,0x0,0x0,0x0,0x0,0x0]],
+	CURVE_BB:[[[0x2B0CBD,0xC0A633,0xCE7E11,0xCC906,0x3FD6EE,0x66D2C4,0x647A63,0xB0BDDF,0x702A0D,0x8,0x2400],
+	           [0x2B0CBC,0xC0A633,0xCE7E11,0xCC906,0x3FD6EE,0x66D2C4,0x647A63,0xB0BDDF,0x702A0D,0x8,0x2400],
+			   [0x2B0CBC,0xC0A633,0xCE7E11,0xCC906,0x3FD6EE,0x66D2C4,0x647A63,0xB0BDDF,0x702A0D,0x8,0x2400],
+			   [0x802562,0x7,0x8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],
+			   [[0x802561,0x7,0x8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+			   [0x2B0CBC,0xC0A633,0xCE7E11,0xCC906,0x3FD6EE,0x66D2C4,0x647A63,0xB0BDDF,0x702A0D,0x8,0x2400],
+			   [0x2B0CBD,0xC0A633,0xCE7E11,0xCC906,0x3FD6EE,0x66D2C4,0x647A63,0xB0BDDF,0x702A0D,0x8,0x2400],
+			   [0x2B0CBC,0xC0A633,0xCE7E11,0xCC906,0x3FD6EE,0x66D2C4,0x647A63,0xB0BDDF,0x702A0D,0x8,0x2400]],
+			   [[0x802562,0x7,0x8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+			   [0x802561,0x7,0x8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+			   [0x802561,0x7,0x8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+			   [0x802561,0x7,0x8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],
+			   [[0xC012B2,0x3,0x4000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+			   [0x4AC2,0xF,0x10000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+			   [0x6AFA0A,0xC0A62F,0xCE3E11,0xCC906,0x3FD6EE,0x66D2C4,0x647A63,0xB0BDDF,0x702A0D,0x8,0x2400],
+			   [0xC012B2,0x3,0x4000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]],
+
+/* BNT Curve */
+/*
+CURVETYPE:0,
+CURVE_PAIRING_TYPE: 0,
+CURVE_A : 0,
+CURVE_B : [0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+CURVE_Cof : [0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+CURVE_Order:[0x30210D,0x777E8D,0x363A75,0x92B2CB,0x88D434,0xD5F00E,0x3696F8,0xFA0BAB,0x17014E,0x20DB65,0x2401],
+CURVE_Bnx:[0x4081,0x806000,0x4000],
+CURVE_Cru:[0x4FCD87,0x53D5AB,0x1FADEB,0xF2BAB1,0x4C82A5,0x4C976,0x476515,0x4801B1],
+CURVE_Fra:[0xC80022,0xD14EAD,0xE359F5,0xD6FACC,0x6C4904,0x3211BE,0xF190A1,0x4F6509,0xBBC439,0xA292C9,0x1328],
+CURVE_Frb:[0xECA6F1,0xEAB040,0xD764A7,0x3DF997,0x1E0C51,0xA3DEB0,0x450657,0xAAA6A1,0x5B3D15,0x7E489B,0x10D8],
+CURVE_Pxa:[0x8E65BB,0x87E228,0x13BE89,0x1CAA63,0xCC00AD,0x548B7C,0x325041,0xBCC055,0xC1339E,0x3FCD04,0x1448],
+CURVE_Pxb:[0xDBE2C0,0x888808,0x853A67,0xF81E34,0x957FE1,0x51B57B,0xA631A,0xDA3FC5,0x4EC302,0x46B338,0x87F],
+CURVE_Pya:[0x20CA1D,0x2C47E0,0xF36C20,0x7E8399,0x4CB416,0x9F72C9,0xC6E543,0x4A2C69,0x2B0BD7,0xC29C10,0x14E8],
+CURVE_Pyb:[0x6628F2,0x437C71,0xDC6BD8,0x67BCB7,0xA27E1,0x72681D,0xA82C75,0xEDEC18,0x454BD1,0xE2A462,0x17AF],
+CURVE_Gx :[0xB4A712,0xBBFEEE,0xBABE9D,0x14F464,0x8A5556,0xD5F06E,0x3696F8,0xFA0BAB,0x17014E,0x20DB65,0x2401],
+CURVE_Gy :[0x1],
+CURVE_W:[[0x838403,0x430061,0x838426,0x824199,0x18121,0x60,0x0,0x0,0x0,0x0,0x0],[0x8101,0xC000,0x8001,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],
+CURVE_SB:[[[0x840504,0x43C061,0x840427,0x824199,0x18121,0x60,0x0,0x0,0x0,0x0,0x0],
+         [0x8101,0xC000,0x8001,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],
+		 [[0x8101,0xC000,0x8001,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+		 [0xAC9D0A,0x347E2B,0xB2B64F,0x107131,0x875313,0xD5EFAE,0x3696F8,0xFA0BAB,0x17014E,0x20DB65,0x2401]]],
+CURVE_WB:[[0x80C080,0x406020,0x80C161,0x80C088,0x8060,0x20,0x0,0x0,0x0,0x0,0x0],
+         [0x8C4A85,0x390408,0x6C36B5,0xA352DC,0xDEAD2F,0x58868E,0xDA4363,0x300120,0x0,0x0,0x0],
+		 [0x464583,0xDCB204,0x363B5A,0xD1A96E,0x6F5697,0xAC4347,0x6D21B1,0x180090,0x0,0x0,0x0],
+		 [0x814181,0x412020,0x814162,0x80C088,0x8060,0x20,0x0,0x0,0x0,0x0,0x0]],
+CURVE_BB:[[[0x2FE08D,0xF71E8D,0x35FA74,0x92B2CB,0x88D434,0xD5F00E,0x3696F8,0xFA0BAB,0x17014E,0x20DB65,0x2401],
+         [0x2FE08C,0xF71E8D,0x35FA74,0x92B2CB,0x88D434,0xD5F00E,0x3696F8,0xFA0BAB,0x17014E,0x20DB65,0x2401],
+		 [0x2FE08C,0xF71E8D,0x35FA74,0x92B2CB,0x88D434,0xD5F00E,0x3696F8,0xFA0BAB,0x17014E,0x20DB65,0x2401],
+		 [0x8102,0xC000,0x8001,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],
+		 [[0x8101,0xC000,0x8001,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+		 [0x2FE08C,0xF71E8D,0x35FA74,0x92B2CB,0x88D434,0xD5F00E,0x3696F8,0xFA0BAB,0x17014E,0x20DB65,0x2401],
+		 [0x2FE08D,0xF71E8D,0x35FA74,0x92B2CB,0x88D434,0xD5F00E,0x3696F8,0xFA0BAB,0x17014E,0x20DB65,0x2401],
+		 [0x2FE08C,0xF71E8D,0x35FA74,0x92B2CB,0x88D434,0xD5F00E,0x3696F8,0xFA0BAB,0x17014E,0x20DB65,0x2401]],
+		 [[0x8102,0xC000,0x8001,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+		 [0x8101,0xC000,0x8001,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+		 [0x8101,0xC000,0x8001,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+		 [0x8101,0xC000,0x8001,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],
+		 [[0x4082,0x806000,0x4000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+		 [0x10202,0x18000,0x10002,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+		 [0x2FA00A,0x76BE8D,0x35BA74,0x92B2CB,0x88D434,0xD5F00E,0x3696F8,0xFA0BAB,0x17014E,0x20DB65,0x2401],
+		 [0x4082,0x806000,0x4000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]],
+
+*/
+
+/* BNT2 Curve */
+/*
+CURVETYPE:0,
+CURVE_PAIRING_TYPE: 0,
+CURVE_A : 0,
+CURVE_B : [0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+CURVE_Cof : [0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+CURVE_Order:[0xAA2BF5,0x71A511,0x33D7FB,0x27B738,0xCF8DE1,0xD00021,0xF3B89,0xB74E20,0xF5AAD,0x48241,0x2400],
+CURVE_Bnx:[0x608205,0x20100,0x4000],
+CURVE_Cru:[0x66BD33,0x274448,0xEFB50,0x301647,0x755B77,0xECF236,0xC3617B,0x480006],
+CURVE_Fra:[0xAEF062,0x68C973,0xE492B2,0x33C3BC,0xBCC69B,0x7F195B,0xF67FA3,0xBD0A41,0xE8CAB6,0xB8D29,0x124E],
+CURVE_Frb:[0xB1B429,0x736240,0x6D5600,0xF52D19,0x12CD48,0x50E726,0x18BBE6,0xFA43DE,0x268FF6,0xF8F517,0x11B1],
+CURVE_Pxa:[0x40A3C8,0x92399F,0x784ACC,0xE96611,0x35CDA4,0x61706B,0x7B0569,0x8279D7,0x93C631,0x17CF96,0x16FC],
+CURVE_Pxb:[0x549540,0x7A8AD8,0x61055,0xE6F651,0xDB6F7B,0xA95D17,0x565907,0x9C8188,0x597590,0xB500BD,0x1EB5],
+CURVE_Pya:[0x220513,0xECC514,0x7B147B,0x860E73,0x844A78,0x35F126,0x51B839,0x9D4DFA,0x1422AA,0xE49876,0x1E8E],
+CURVE_Pyb:[0x7CE78E,0x328F57,0x781FB9,0xE26FA5,0x7EB746,0x1FB8E2,0xA93DBC,0xA29D76,0xE33BDB,0xF4CDBA,0x23CE],
+CURVE_Gx :[0x60A48A,0xDC2BB4,0x51E8B2,0x28F0D6,0xCF93E4,0xD00081,0xF3B89,0xB74E20,0xF5AAD,0x48241,0x2400],
+CURVE_Gy :[0x1],
+CURVE_W:[[0x347083,0x6282A1,0x1D10B7,0x1399E,0x603,0x60,0x0,0x0,0x0,0x0,0x0],
+        [0xC10409,0x40200,0x8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],
+CURVE_SB:[[[0xF5748C,0x6684A1,0x1D90B7,0x1399E,0x603,0x60,0x0,0x0,0x0,0x0,0x0],
+         [0xC10409,0x40200,0x8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],
+		 [[0xC10409,0x40200,0x8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+		 [0x75BB72,0xF2270,0x16C744,0x267D9A,0xCF87DE,0xCFFFC1,0xF3B89,0xB74E20,0xF5AAD,0x48241,0x2400]]],
+CURVE_WB:[[0x70A224,0x72D48A,0x94592,0x688A,0x201,0x20,0x0,0x0,0x0,0x0,0x0],
+         [0x30EF19,0x572CF0,0x721D5A,0x763543,0xA39651,0x48A1B9,0x8240FD,0x300004,0x0,0x0,0x0],
+		 [0x48B88F,0x2C96F8,0xB92EAD,0xBB1AA1,0xD1CB28,0xA450DC,0x41207E,0x180002,0x0,0x0,0x0],
+		 [0x31A62D,0x76D68B,0x9C592,0x688A,0x201,0x20,0x0,0x0,0x0,0x0,0x0]],
+CURVE_BB:[[[0x49A9F1,0x6FA411,0x3397FB,0x27B738,0xCF8DE1,0xD00021,0xF3B89,0xB74E20,0xF5AAD,0x48241,0x2400],
+         [0x49A9F0,0x6FA411,0x3397FB,0x27B738,0xCF8DE1,0xD00021,0xF3B89,0xB74E20,0xF5AAD,0x48241,0x2400],
+		 [0x49A9F0,0x6FA411,0x3397FB,0x27B738,0xCF8DE1,0xD00021,0xF3B89,0xB74E20,0xF5AAD,0x48241,0x2400],
+		 [0xC1040A,0x40200,0x8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],
+		 [[0xC10409,0x40200,0x8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+		 [0x49A9F0,0x6FA411,0x3397FB,0x27B738,0xCF8DE1,0xD00021,0xF3B89,0xB74E20,0xF5AAD,0x48241,0x2400],
+		 [0x49A9F1,0x6FA411,0x3397FB,0x27B738,0xCF8DE1,0xD00021,0xF3B89,0xB74E20,0xF5AAD,0x48241,0x2400],
+		 [0x49A9F0,0x6FA411,0x3397FB,0x27B738,0xCF8DE1,0xD00021,0xF3B89,0xB74E20,0xF5AAD,0x48241,0x2400]],
+		 [[0xC1040A,0x40200,0x8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+		 [0xC10409,0x40200,0x8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+		 [0xC10409,0x40200,0x8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+		 [0xC10409,0x40200,0x8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],
+		 [[0x608206,0x20100,0x4000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+		 [0x820812,0x80401,0x10000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+		 [0xE927EA,0x6DA310,0x3357FB,0x27B738,0xCF8DE1,0xD00021,0xF3B89,0xB74E20,0xF5AAD,0x48241,0x2400],
+		 [0x608206,0x20100,0x4000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]],
+*/
+
+/* BN254 Curve */
+/*
+CURVETYPE:0,
+CURVE_PAIRING_TYPE: 0,
+CURVE_A : 0,
+CURVE_B : [0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+CURVE_Cof : [0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+CURVE_Order:[0xD,0x0,0x10A100,0x0,0x9F8000,0x7FF,0x800000,0xBA344D,0x1,0x648240,0x2523],
+CURVE_Bnx:[0x1,0x0,0x4080],
+CURVE_Cru:[0x7,0x0,0x6CD80,0x0,0x90000,0x249,0x400000,0x49B362],
+CURVE_Fra:[0x2A6DE9,0xE6C06F,0xC2E17D,0x4D3F77,0x97492,0x953F85,0x50A846,0xB6499B,0x2E7C8C,0x761921,0x1B37],
+CURVE_Frb:[0xD5922A,0x193F90,0x50C582,0xB2C088,0x178B6D,0x6AC8DC,0x2F57B9,0x3EAB2,0xD18375,0xEE691E,0x9EB],
+CURVE_Pxa:[0x3FB2B,0x4224C8,0xD91EE,0x4898BF,0x648BBB,0xEDB6A4,0x7E8C61,0xEB8D8C,0x9EB62F,0x10BB51,0x61A],
+CURVE_Pxb:[0xD54CF3,0x34C1E7,0xB70D8C,0xAE3784,0x4D746B,0xAA5B1F,0x8C5982,0x310AA7,0x737833,0xAAF9BA,0x516],
+CURVE_Pya:[0xCD2B9A,0xE07891,0xBD19F0,0xBDBE09,0xBD0AE6,0x822329,0x96698C,0x9A90E0,0xAF9343,0x97A06B,0x218],
+CURVE_Pyb:[0x3ACE9B,0x1AEC6B,0x578A2D,0xD739C9,0x9006FF,0x8D37B0,0x56F5F3,0x8F6D44,0x8B1526,0x2B0E7C,0xEBB],
+CURVE_Gx :[0x12,0x0,0x13A700,0x0,0x210000,0x861,0x800000,0xBA344D,0x1,0x648240,0x2523],
+CURVE_Gy :[0x1],
+CURVE_W:[[0x3,0x0,0x20400,0x0,0x818000,0x61,0x0,0x0,0x0,0x0,0x0],[0x1,0x0,0x8100,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],
+CURVE_SB:[[[0x4,0x0,0x28500,0x0,0x818000,0x61,0x0,0x0,0x0,0x0,0x0],[0x1,0x0,0x8100,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x1,0x0,0x8100,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0xA,0x0,0xE9D00,0x0,0x1E0000,0x79E,0x800000,0xBA344D,0x1,0x648240,0x2523]]],
+CURVE_WB:[[0x0,0x0,0x4080,0x0,0x808000,0x20,0x0,0x0,0x0,0x0,0x0],[0x5,0x0,0x54A80,0x0,0x70000,0x1C7,0x800000,0x312241,0x0,0x0,0x0],[0x3,0x0,0x2C580,0x0,0x838000,0xE3,0xC00000,0x189120,0x0,0x0,0x0],[0x1,0x0,0xC180,0x0,0x808000,0x20,0x0,0x0,0x0,0x0,0x0]],
+CURVE_BB:[[[0xD,0x0,0x106080,0x0,0x9F8000,0x7FF,0x800000,0xBA344D,0x1,0x648240,0x2523],[0xC,0x0,0x106080,0x0,0x9F8000,0x7FF,0x800000,0xBA344D,0x1,0x648240,0x2523],[0xC,0x0,0x106080,0x0,0x9F8000,0x7FF,0x800000,0xBA344D,0x1,0x648240,0x2523],[0x2,0x0,0x8100,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x1,0x0,0x8100,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0xC,0x0,0x106080,0x0,0x9F8000,0x7FF,0x800000,0xBA344D,0x1,0x648240,0x2523],[0xD,0x0,0x106080,0x0,0x9F8000,0x7FF,0x800000,0xBA344D,0x1,0x648240,0x2523],[0xC,0x0,0x106080,0x0,0x9F8000,0x7FF,0x800000,0xBA344D,0x1,0x648240,0x2523]],[[0x2,0x0,0x8100,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1,0x0,0x8100,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1,0x0,0x8100,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1,0x0,0x8100,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x2,0x0,0x4080,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x2,0x0,0x10200,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0xA,0x0,0x102000,0x0,0x9F8000,0x7FF,0x800000,0xBA344D,0x1,0x648240,0x2523],[0x2,0x0,0x4080,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]],
+*/
+
+/* BN454 Curve */
+/*
+CURVETYPE:0,
+CURVE_PAIRING_TYPE: 0,
+CURVE_A : 0,
+
+CURVE_Order:[0xD,0x8400,0x780000,0x100003,0x2006C4,0x49F88,0x513F00,0x610000,0x7C0091,0x7C03A9,0x36A21,0x10EA20,0x21C000,0x288012,0x1B006C,0x12D8,0x9090,0x1B000,0x24000,0x12000],
+CURVE_B: [0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+CURVE_Cof: [0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+CURVE_Gx:[0x12,0x9C00,0x100000,0x700004,0x6006C4,0x4A109,0x514200,0x640000,0x80091,0x803AA,0x36A22,0x10EA20,0x21C000,0x288012,0x1B006C,0x12D8,0x9090,0x1B000,0x24000,0x12000],
+CURVE_Gy:[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+
+CURVE_Bnx:[0x1,0x200,0x0,0x80000,0x100000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+CURVE_Cru:[0x7,0x3600,0x100000,0x580001,0x300121,0x903,0xD9200,0x2D0000,0x480000,0x48006C,0x1B0,0x91B0,0x36000,0x6C000,0x48000,0x0,0x0,0x0,0x0,0x0],
+CURVE_Fra:[0x73B0EC,0x393FAA,0x6E0C0B,0x1D485C,0x2EEE6C,0x62FD8F,0x4D280A,0x6E835B,0x2D6A87,0x37B2AC,0x568803,0x7657E5,0x129326,0x3B9C4D,0x67175B,0x159909,0x61CCD9,0x4D0FD7,0x7B1C9E,0x973C],
+CURVE_Frb:[0xC4F27,0x475C55,0x21F3F4,0x52B7A7,0x311858,0x21A37A,0x419F5,0x757CA5,0x5A9609,0x5050FD,0x2CE21E,0x1A923A,0xF2CD9,0x6CE3C5,0x33E910,0x6A79CE,0x1EC3B6,0x34A028,0x72361,0x88C3],
+CURVE_Pxa:[0x702B14,0x775841,0x6C7EE8,0x786615,0x3C30BE,0x5FFE6D,0x1AD7F3,0x77F16D,0x1FE1E7,0x5DBF8,0x5150DA,0x4BCA41,0x2D66CC,0x197743,0x6ED766,0x57F0B1,0x68F14A,0x2A106C,0x53E035,0xA01E],
+CURVE_Pxb:[0x5BF266,0x5A1D88,0x5BA701,0x3C11E1,0x65ACBB,0x378A46,0x91E43,0x7E9723,0x72F769,0x77CD,0x5C7782,0x554A8C,0x7BA9E2,0x7CACCA,0x5CDFA,0x6A92C2,0x4B1E40,0x5D002,0x35A785,0xACA9],
+CURVE_Pya:[0x1B15C7,0x56D77C,0x2D24E6,0x2AAE36,0x726024,0x69F6BB,0x194651,0x2338E2,0x7C5DD5,0x44EF51,0x3EAAEA,0x774179,0x300871,0xC9875,0x289B87,0x3D07F0,0x12C528,0x578DB6,0x10011E,0xEB3D],
+CURVE_Pyb:[0x571D60,0x4DF6C0,0x63B043,0x3D8946,0x127184,0x4CB8FD,0x349D4E,0x45F387,0x743376,0x4C096,0x6145D7,0x408801,0x4F0B46,0x578BD4,0x432922,0x1F6C8F,0x753F90,0x5935B,0x8D821,0x4BB7],
+CURVE_W:[[0x3,0x1000,0x180000,0x400000,0x0,0x181,0x300,0x30000,0xC0000,0xC0000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1,0x400,0x0,0x100000,0x200000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],
+CURVE_SB:[[[0x4,0x1400,0x180000,0x500000,0x200000,0x181,0x300,0x30000,0xC0000,0xC0000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1,0x400,0x0,0x100000,0x200000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x1,0x400,0x0,0x100000,0x200000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0xA,0x7400,0x600000,0x500003,0x2006C3,0x49E07,0x513C00,0x5E0000,0x700091,0x7003A9,0x36A21,0x10EA20,0x21C000,0x288012,0x1B006C,0x12D8,0x9090,0x1B000,0x24000,0x12000]]],
+CURVE_WB:[[0x0,0x200,0x80000,0x80000,0x100000,0x80,0x100,0x10000,0x40000,0x40000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x5,0x2A00,0x700000,0x280000,0x5000C1,0x702,0x90E00,0x200000,0x380000,0x380048,0x120,0x6120,0x24000,0x48000,0x30000,0x0,0x0,0x0,0x0,0x0],[0x3,0x1600,0x380000,0x580000,0x300060,0x381,0x48700,0x100000,0x1C0000,0x1C0024,0x90,0x3090,0x12000,0x24000,0x18000,0x0,0x0,0x0,0x0,0x0],[0x1,0x600,0x80000,0x180000,0x300000,0x80,0x100,0x10000,0x40000,0x40000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],
+CURVE_BB:[[[0xD,0x8200,0x780000,0x80003,0x1006C4,0x49F88,0x513F00,0x610000,0x7C0091,0x7C03A9,0x36A21,0x10EA20,0x21C000,0x288012,0x1B006C,0x12D8,0x9090,0x1B000,0x24000,0x12000],[0xC,0x8200,0x780000,0x80003,0x1006C4,0x49F88,0x513F00,0x610000,0x7C0091,0x7C03A9,0x36A21,0x10EA20,0x21C000,0x288012,0x1B006C,0x12D8,0x9090,0x1B000,0x24000,0x12000],[0xC,0x8200,0x780000,0x80003,0x1006C4,0x49F88,0x513F00,0x610000,0x7C0091,0x7C03A9,0x36A21,0x10EA20,0x21C000,0x288012,0x1B006C,0x12D8,0x9090,0x1B000,0x24000,0x12000],[0x2,0x400,0x0,0x100000,0x200000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x1,0x400,0x0,0x100000,0x200000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0xC,0x8200,0x780000,0x80003,0x1006C4,0x49F88,0x513F00,0x610000,0x7C0091,0x7C03A9,0x36A21,0x10EA20,0x21C000,0x288012,0x1B006C,0x12D8,0x9090,0x1B000,0x24000,0x12000],[0xD,0x8200,0x780000,0x80003,0x1006C4,0x49F88,0x513F00,0x610000,0x7C0091,0x7C03A9,0x36A21,0x10EA20,0x21C000,0x288012,0x1B006C,0x12D8,0x9090,0x1B000,0x24000,0x12000],[0xC,0x8200,0x780000,0x80003,0x1006C4,0x49F88,0x513F00,0x610000,0x7C0091,0x7C03A9,0x36A21,0x10EA20,0x21C000,0x288012,0x1B006C,0x12D8,0x9090,0x1B000,0x24000,0x12000]],[[0x2,0x400,0x0,0x100000,0x200000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1,0x400,0x0,0x100000,0x200000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1,0x400,0x0,0x100000,0x200000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1,0x400,0x0,0x100000,0x200000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x2,0x200,0x0,0x80000,0x100000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x2,0x800,0x0,0x200000,0x400000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0xA,0x8000,0x780000,0x3,0x6C4,0x49F88,0x513F00,0x610000,0x7C0091,0x7C03A9,0x36A21,0x10EA20,0x21C000,0x288012,0x1B006C,0x12D8,0x9090,0x1B000,0x24000,0x12000],[0x2,0x200,0x0,0x80000,0x100000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]],
+*/
+
+/* BLS455 Curve */
+/*
+CURVETYPE:0,
+CURVE_PAIRING_TYPE: 1,
+CURVE_A : 0,
+
+CURVE_Order:[0x400001,0xFFFFF,0x70000,0x20000,0xA0000,0x3A200,0x1D400,0x12F00,0x4F00,0x1E20,0xB80,0x1C0,0x80,0x20,0x0,0x0,0x0,0x0,0x0,0x0],
+CURVE_B: [0xA,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+CURVE_Cof: [0x3FFAAB,0x2FFF55,0x2DAA55,0x2DAA55,0x2B1555,0x2AD555,0x1555,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+CURVE_Gx:[0x7CEDD1,0xBBBFB,0x3EDB53,0x59D01A,0x5C6F43,0x38E4A6,0x55A95E,0xBF82D,0x611B32,0x6571D9,0xE4AC7,0x5867F4,0x1F342A,0x6CF329,0x47B8C9,0x76D2C8,0x4C56AB,0xBC81,0x57CECC,0xC42],
+CURVE_Gy:[0x619B9B,0x7AF34C,0x219013,0x6B7D01,0x1D80A5,0x34926D,0xC8B64,0x477391,0x1C1E96,0x5CB086,0x7D7EC7,0x4A9C00,0x4A9BC8,0x3C711D,0x7503FA,0x6B6FD7,0x43DEB0,0x7130BF,0x6DDFA7,0xCD46],
+
+CURVE_Bnx:[0x800,0x100,0x80,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+CURVE_Cru:[0xAA9,0x5FF800,0xAA480,0x7A51BB,0x7A5190,0x1FD921,0x6F7552,0x54595C,0x33A586,0x68D3B6,0x76675E,0x1AA657,0x491731,0x7FCD2B,0x2340BF,0x77ADA,0x2A900E,0x72AAAE,0x655555,0x2AAAA],
+CURVE_Fra:[0x2EBF21,0x1F7B94,0x590273,0x399BCC,0x72F54A,0xA930A,0x7E21D5,0x23940C,0x51F853,0x778395,0x13C08A,0x6A1ACA,0x282CD7,0x61EF7,0x3E0634,0x53A2CA,0x5C0016,0x397C75,0x125CFB,0x1CBF5],
+CURVE_Frb:[0x51438A,0x60876B,0x1A80C,0x1FB97E,0x65A00C,0x18E1CD,0x2D1846,0x4A38BD,0x42C060,0x3275D0,0x1BA45A,0x9650,0x3B78DA,0x1CDD4,0x667A8C,0x34280F,0x4E9FF7,0x392E38,0x52F85A,0xDEB5],
+CURVE_Pxa:[0x41F542,0x3E41E1,0x4011D,0x7C2B3F,0x5D6070,0x7AEECC,0x262ECC,0xEBC03,0x153172,0x6D0BDA,0x1271C7,0x762DB5,0x303D3F,0x2A79D6,0x4193FD,0x31C6F7,0x31B4C4,0x181D34,0x4BEA00,0x17658],
+CURVE_Pxb:[0x49F03D,0xDDCCE,0x4BA642,0x2D62F7,0x9A55A,0x5402DD,0x3B3623,0x33DA0D,0x6163E0,0x48A1FC,0x25BD88,0x70E471,0x755066,0x664DD0,0x486521,0x2CD407,0xBEAEE,0x5B7F76,0x7F3819,0x767],
+CURVE_Pya:[0x1A77F4,0x6B48B0,0x42A0C8,0x5BD3F0,0x70F367,0x2B73B3,0x1299B5,0x647D06,0xD6EC4,0x7ECBC,0x7B0BBC,0x4CE0D4,0x1C7DC2,0x1F4B59,0x4F2887,0x221922,0x2BB9C5,0x7B9AB,0x76429B,0x11238],
+CURVE_Pyb:[0x1FDBA2,0x76DB3C,0x55BD04,0x9ED01,0x7E6309,0x111C54,0x4F66B1,0x2FDE48,0x340158,0x4F9EC3,0x27B5CB,0xD90E4,0x656D80,0xAB1F2,0x487BB8,0x4C7CF4,0x3CFC86,0x256F60,0xF2A0F,0x19A8],
+
+// not used 
+CURVE_W:[[],[]],
+CURVE_SB:[[[],[]],[[],[]]],
+CURVE_WB:[[],[],[],[]],
+CURVE_BB:[[[],[],[],[]],[[],[],[],[]],[[],[],[],[]],[[],[],[],[]]],
+*/
+
+
+/* BLS383 Curve */
+/*
+CURVETYPE:0,
+CURVE_PAIRING_TYPE: 1,
+CURVE_A : 0,
+
+CURVE_Order:[0x7FF001,0x700001,0x6003FF,0x387F3,0x4BFDE0,0xBDBE3,0x127,0x3D18,0x7F910,0x198800,0x190401,0xA,0x0,0x0,0x0,0x0,0x0],
+CURVE_B: [0x9,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+CURVE_Cof: [0x52B,0x54000,0x328000,0x555559,0x55560A,0xC0A,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+CURVE_Gx:[0x10786B,0x36691A,0x2B4356,0x71FAA,0x33477C,0xAF173,0x496DCD,0x37B2DF,0x4007BB,0x389ED5,0x3FD5FA,0x7EAC18,0x6EC02E,0x3F11F6,0x262B6E,0x67725E,0xB08],
+CURVE_Gy:[0x145DDB,0x34047A,0x5F3017,0x462FF7,0x713F51,0x5654CD,0x3B0D18,0x492FAB,0x19C7A,0x7D2DE6,0x660488,0x30823,0x5BE599,0x215B1E,0x1C4120,0x499BB,0x1F39],
+
+CURVE_Bnx:[0x40,0x2000,0x44000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+CURVE_Cru:[0x2155A9,0x5589DB,0x78F68E,0x43B0F2,0x5DF2FE,0x4C64C4,0x37EAB7,0x1AD35E,0x128D30,0x6A246,0x6FAB5A,0x5F9D15,0x24190D,0x756408,0x7DD717,0x104054,0x7AC5],
+CURVE_Fra:[0x34508B,0x4B3525,0x4D0CAE,0x503777,0x463DB7,0x3BF78E,0xD072C,0x2AE9A0,0x69D32D,0x282C73,0x1730DB,0xCD9F8,0x6AB98B,0x7DC9B0,0x1CBCC8,0x7D8CC3,0x5A5],
+CURVE_Frb:[0x7904E0,0xA352F,0x28DE04,0x537843,0x3B7D49,0x6FB715,0x4FBAE2,0x4AA1C7,0x183C6C,0x3BDDEF,0x5272CD,0x532FB2,0x3FBEC7,0x22EEF9,0x611A4F,0x12B391,0x751F],
+CURVE_Pxa:[0x2C9472,0x3310B7,0xDB581,0xEF16E,0x77C4D3,0x119114,0x72430C,0x447E5E,0x1971C6,0x4E53E0,0x710FC5,0x349A9C,0x6B8BF3,0x4B4AC3,0x2FF607,0x3915AB,0x4D50],
+CURVE_Pxb:[0x72AB23,0x17AF44,0x73A26D,0x6A7A26,0x47AF19,0x640D46,0x5BDEE4,0xCFD9F,0x53E2A8,0x5CAE3B,0x58D75F,0x515D1D,0x1A1263,0x18F018,0x16EB0A,0x30BE1F,0xEE3],
+CURVE_Pya:[0x7BD4FD,0x24612E,0x7F1A07,0x3906FE,0x40B660,0x191341,0x7F2564,0x143D20,0x3CF878,0x4A5C3F,0x53BB9,0x8E118,0x3325E0,0x7102D7,0x170A21,0x42CD0,0x8F4],
+CURVE_Pyb:[0x2C4CE6,0x44144A,0x32297,0x3A57FA,0x35907A,0x4891DE,0x5D8290,0x50CCA0,0x2B0FD,0x13FFDF,0x6353A9,0x794D0,0x4997BA,0x6F70DC,0x4AB1F,0x5DD446,0x1DCA],
+
+// not used 
+CURVE_W:[[],[]],
+CURVE_SB:[[[],[]],[[],[]]],
+CURVE_WB:[[],[],[],[]],
+CURVE_BB:[[[],[],[],[]],[[],[],[],[]],[[],[],[],[]],[[],[],[],[]]],
+
+*/
+
+	USE_GLV: false,
+	USE_GS_G2: false,
+	USE_GS_GT: false,	
+	GT_STRONG: false,
+
+	debug: false,
+
+
+// AES constants
+
+	ECB:0,
+	CBC:1,
+	CFB1:2,
+	CFB2:3,
+	CFB4:5,
+	OFB1:14,
+	OFB2:15,
+	OFB4:17,
+	OFB8:21,
+	OFB16:29,
+	CTR1:30,
+	CTR2:31,
+	CTR4:33, 
+	CTR8:37, 
+	CTR16:45, 
+
+// GCM constants
+
+	GCM_ACCEPTING_HEADER:0,
+	GCM_ACCEPTING_CIPHER:1,
+	GCM_NOT_ACCEPTING_MORE:2,
+	GCM_FINISHED:3,
+	GCM_ENCRYPTING:0,
+	GCM_DECRYPTING:1
+
+};
+
+ROM.MODINV=(Math.pow(2,-ROM.BASEBITS))
+ROM.NLEN=(1+(Math.floor((ROM.MODBITS-1)/ROM.BASEBITS)));
+ROM.DNLEN=2*ROM.NLEN;
+ROM.BMASK=(1<<ROM.BASEBITS)-1;
+ROM.MODBYTES=(1+(Math.floor((ROM.MODBITS-1)/8)));
+ROM.NEXCESS=(1<<(ROM.CHUNK-ROM.BASEBITS-1)); // 2^(CHUNK-BASEBITS-1)
+ROM.FEXCESS=(1<<(ROM.BASEBITS*ROM.NLEN-ROM.MODBITS)); // 2^(BASEBITS*NLEN-MODBITS)
+ROM.OMASK=(-1)<<ROM.TBITS;
+ROM.TBITS=ROM.MODBITS%ROM.BASEBITS;
+ROM.TMASK=(1<<ROM.TBITS)-1;
+ROM.BIGBITS=(8*ROM.MODBYTES);
+
+ROM.FF_BITS=(ROM.BIGBITS*ROM.FFLEN);
+ROM.HFLEN=(ROM.FFLEN/2);  /* Useful for half-size RSA private key operations */
diff --git a/version22/js/RSA.js b/version22/js/RSA.js
new file mode 100644
index 0000000..ff27ac6
--- /dev/null
+++ b/version22/js/RSA.js
@@ -0,0 +1,392 @@
+/*
+	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.
+*/
+
+/* RSA API Functions */
+
+var rsa_private_key=function(n)
+{
+	this.p=new FF(n);
+	this.q=new FF(n);
+	this.dp=new FF(n);
+	this.dq=new FF(n);
+	this.c=new FF(n);
+};
+
+var rsa_public_key=function(m)
+{
+	this.e=0;
+	this.n=new FF(m);
+};
+
+RSA= {
+	RFS: ROM.MODBYTES*ROM.FFLEN,
+	SHA256 : 32,
+	SHA384 : 48,
+	SHA512 : 64,
+
+	HASH_TYPE:32,
+
+/* SHAXXX identifier strings */
+	SHA256ID : [0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20],
+	SHA384ID : [0x30,0x41,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00,0x04,0x30],
+	SHA512ID : [0x30,0x51,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0x04,0x40],
+
+	bytestohex: function(b)
+	{
+		var s="";
+		var len=b.length;
+		var ch;
+
+		for (var i=0;i<len;i++)
+		{
+			ch=b[i];
+			s+=((ch>>>4)&15).toString(16);
+			s+=(ch&15).toString(16);
+
+		}
+		return s;
+	},
+
+	bytestostring: function(b)
+	{
+		var s="";
+		for (var i=0;i<b.length;i++)
+		{
+			s+=String.fromCharCode(b[i]);
+		}
+		return s;
+	},
+
+	stringtobytes: function(s)
+	{
+		var b=[];
+		for (var i=0;i<s.length;i++)
+			b.push(s.charCodeAt(i));
+		return b;
+	},
+
+	hashit: function(sha,A,n)
+	{
+		var R=[];
+		if (sha==this.SHA256)
+		{
+			var H=new HASH256();
+			if (A!=null) H.process_array(A); 
+			if (n>=0) H.process_num(n);
+			R=H.hash();
+		}
+		if (sha==this.SHA384)
+		{
+			H=new HASH384();
+			if (A!=null) H.process_array(A); 
+			if (n>=0) H.process_num(n);
+			R=H.hash();
+		}
+		if (sha==this.SHA512)
+		{
+			H=new HASH512();
+			if (A!=null) H.process_array(A); 
+			if (n>=0) H.process_num(n);
+			R=H.hash();
+		}
+		return R;
+	},
+
+	KEY_PAIR: function(rng,e,PRIV,PUB)
+	{ /* IEEE1363 A16.11/A16.12 more or less */
+
+	//	var m,r,bytes,hbytes,words,err,res=0;
+		var n=PUB.n.length>>1;
+		var t = new FF(n);
+		var p1=new FF(n);
+		var q1=new FF(n);
+
+		for (;;)
+		{
+
+			PRIV.p.random(rng);
+			while (PRIV.p.lastbits(2)!=3) PRIV.p.inc(1);
+			while (!FF.prime(PRIV.p,rng)) PRIV.p.inc(4);
+
+			p1.copy(PRIV.p);
+			p1.dec(1);
+
+			if (p1.cfactor(e)) continue;
+			break;
+		}
+
+		for (;;)
+		{
+			PRIV.q.random(rng);
+			while (PRIV.q.lastbits(2)!=3) PRIV.q.inc(1);
+			while (!FF.prime(PRIV.q,rng)) PRIV.q.inc(4);
+			
+			q1.copy(PRIV.q);
+			q1.dec(1);
+
+			if (q1.cfactor(e)) continue;
+			break;
+		}
+
+		PUB.n=FF.mul(PRIV.p,PRIV.q);
+		PUB.e=e;
+
+		t.copy(p1);
+		t.shr();
+		PRIV.dp.set(e);
+		PRIV.dp.invmodp(t);
+		if (PRIV.dp.parity()===0) PRIV.dp.add(t);
+		PRIV.dp.norm();
+
+		t.copy(q1);
+		t.shr();
+		PRIV.dq.set(e);
+		PRIV.dq.invmodp(t);
+		if (PRIV.dq.parity()===0) PRIV.dq.add(t);
+		PRIV.dq.norm();
+
+		PRIV.c.copy(PRIV.p);
+		PRIV.c.invmodp(PRIV.q);
+
+		return;
+	},
+
+/* Mask Generation Function */
+	MGF1: function(sha,Z,olen,K)
+	{
+		var i,hlen=sha;
+		var B=[];
+
+		var counter,cthreshold,k=0;
+		for (i=0;i<K.length;i++) K[i]=0;
+
+		cthreshold=Math.floor(olen/hlen); if (olen%hlen!==0) cthreshold++;
+		for (counter=0;counter<cthreshold;counter++)
+		{
+			B=this.hashit(sha,Z,counter);
+			if (k+hlen>olen) for (i=0;i<olen%hlen;i++) K[k++]=B[i];
+			else for (i=0;i<hlen;i++) K[k++]=B[i];
+		}	
+	},
+
+	PKCS15: function(sha,m,w)
+	{
+		var olen=ROM.FF_BITS/8;
+		var i,hlen=sha;
+		var idlen=19; 
+
+		if (olen<idlen+hlen+10) return false;
+		var H=this.hashit(sha,m,-1);
+
+		for (i=0;i<w.length;i++) w[i]=0;
+		i=0;
+		w[i++]=0;
+		w[i++]=1;
+		for (var j=0;j<olen-idlen-hlen-3;j++)
+			w[i++]=0xff;
+		w[i++]=0;
+
+
+		if (hlen==this.SHA256) for (var j=0;j<idlen;j++) w[i++]=this.SHA256ID[j];
+		if (hlen==this.SHA384) for (var j=0;j<idlen;j++) w[i++]=this.SHA384ID[j];
+		if (hlen==this.SHA512) for (var j=0;j<idlen;j++) w[i++]=this.SHA512ID[j];
+
+		for (var j=0;j<hlen;j++)
+			w[i++]=H[j];
+
+		return true;
+	},
+
+	/* OAEP Message Encoding for Encryption */
+	OAEP_ENCODE: function(sha,m,rng,p)
+	{ 
+		var i,slen,olen=RSA.RFS-1;
+		var mlen=m.length;
+		var hlen,seedlen;
+		var f=[];
+
+		hlen=sha;
+		var SEED=[];
+		seedlen=hlen;
+
+		if (mlen>olen-hlen-seedlen-1) return null; 
+
+		var DBMASK=[];
+
+		var h=this.hashit(sha,p,-1);
+		for (i=0;i<hlen;i++) f[i]=h[i];
+
+		slen=olen-mlen-hlen-seedlen-1;      
+
+		for (i=0;i<slen;i++) f[hlen+i]=0;
+		f[hlen+slen]=1;
+		for (i=0;i<mlen;i++) f[hlen+slen+1+i]=m[i];
+
+		for (i=0;i<seedlen;i++) SEED[i]=rng.getByte();
+		this.MGF1(sha,SEED,olen-seedlen,DBMASK);
+
+		for (i=0;i<olen-seedlen;i++) DBMASK[i]^=f[i];
+		this.MGF1(sha,DBMASK,seedlen,f);
+
+		for (i=0;i<seedlen;i++) f[i]^=SEED[i];
+
+		for (i=0;i<olen-seedlen;i++) f[i+seedlen]=DBMASK[i];
+
+		/* pad to length RFS */
+		var d=1;
+		for (i=RSA.RFS-1;i>=d;i--)
+			f[i]=f[i-d];
+		for (i=d-1;i>=0;i--)
+			f[i]=0;
+
+		return f;
+	},
+
+	/* OAEP Message Decoding for Decryption */
+	OAEP_DECODE: function(sha,p,f)
+	{
+		var x,t;
+		var comp;
+		var i,k,olen=RSA.RFS-1;
+		var hlen,seedlen;
+
+		hlen=sha;
+		var SEED=[];
+		seedlen=hlen;
+		var CHASH=[];
+		seedlen=hlen=sha;
+
+		if (olen<seedlen+hlen+1) return null;
+
+		var DBMASK=[];
+		for (i=0;i<olen-seedlen;i++) DBMASK[i]=0;
+
+		if (f.length<RSA.RFS)
+		{
+			var d=RSA.RFS-f.length;
+			for (i=RFS-1;i>=d;i--)
+				f[i]=f[i-d];
+			for (i=d-1;i>=0;i--)
+				f[i]=0;
+
+		}
+
+		var h=this.hashit(sha,p,-1);
+		for (i=0;i<hlen;i++) CHASH[i]=h[i];
+
+		x=f[0];
+
+		for (i=seedlen;i<olen;i++)
+			DBMASK[i-seedlen]=f[i+1]; 
+
+		this.MGF1(sha,DBMASK,seedlen,SEED);
+		for (i=0;i<seedlen;i++) SEED[i]^=f[i+1];
+		this.MGF1(sha,SEED,olen-seedlen,f);
+		for (i=0;i<olen-seedlen;i++) DBMASK[i]^=f[i];
+
+		comp=true;
+		for (i=0;i<hlen;i++)
+		{
+			if (CHASH[i]!=DBMASK[i]) comp=false;
+		}
+
+		for (i=0;i<olen-seedlen-hlen;i++)
+			DBMASK[i]=DBMASK[i+hlen];
+
+		for (i=0;i<hlen;i++)
+			SEED[i]=CHASH[i]=0;
+		
+		for (k=0;;k++)
+		{
+			if (k>=olen-seedlen-hlen) return null;
+			if (DBMASK[k]!==0) break;
+		}
+
+		t=DBMASK[k];
+
+		if (!comp || x!==0 || t!=0x01) 
+		{
+			for (i=0;i<olen-seedlen;i++) DBMASK[i]=0;
+			return null;
+		}
+
+		var r=[];
+
+		for (i=0;i<olen-seedlen-hlen-k-1;i++)
+			r[i]=DBMASK[i+k+1];
+	
+		for (i=0;i<olen-seedlen;i++) DBMASK[i]=0;
+
+		return r;
+	},
+
+	/* destroy the Private Key structure */
+	PRIVATE_KEY_KILL: function(PRIV)
+	{
+		PRIV.p.zero();
+		PRIV.q.zero();
+		PRIV.dp.zero();
+		PRIV.dq.zero();
+		PRIV.c.zero();
+	},
+
+	/* RSA encryption with the public key */
+	ENCRYPT: function(PUB,F,G)
+	{
+		var n=PUB.n.getlen();
+		var f=new FF(n);
+
+		FF.fromBytes(f,F);
+
+		f.power(PUB.e,PUB.n);	
+		
+		f.toBytes(G);
+	},
+
+	/* RSA decryption with the private key */
+	DECRYPT: function(PRIV,G,F)
+	{
+		var n=PRIV.p.getlen();
+		var g=new FF(2*n);
+
+		FF.fromBytes(g,G);
+		var jp=g.dmod(PRIV.p);
+		var jq=g.dmod(PRIV.q);
+
+		jp.skpow(PRIV.dp,PRIV.p);
+		jq.skpow(PRIV.dq,PRIV.q);
+
+		g.zero();
+		g.dscopy(jp);
+		jp.mod(PRIV.q);
+		if (FF.comp(jp,jq)>0) jq.add(PRIV.q);
+		jq.sub(jp);
+		jq.norm();
+
+		var t=FF.mul(PRIV.c,jq);
+		jq=t.dmod(PRIV.q);
+
+		t=FF.mul(jq,PRIV.p);
+		g.add(t);
+		g.norm();
+
+		g.toBytes(F);
+	}
+
+};
\ No newline at end of file
diff --git a/version22/js/TestECDH.html b/version22/js/TestECDH.html
new file mode 100644
index 0000000..1ddf0c2
--- /dev/null
+++ b/version22/js/TestECDH.html
@@ -0,0 +1,143 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>JavaScript Test ECC</title>
+</head>
+<body>
+<h1>JavaScript Test ECC Example</h1>
+<script type="text/javascript" src="DBIG.js"></script>
+<script type="text/javascript" src="BIG.js"></script>
+<script type="text/javascript" src="FP.js"></script>
+<script type="text/javascript" src="ROM.js"></script>
+<script type="text/javascript" src="UInt64.js"></script>
+<script type="text/javascript" src="HASH256.js"></script>
+<script type="text/javascript" src="HASH384.js"></script>
+<script type="text/javascript" src="HASH512.js"></script>
+<script type="text/javascript" src="RAND.js"></script>
+<script type="text/javascript" src="AES.js"></script>
+<script type="text/javascript" src="GCM.js"></script>
+<script type="text/javascript" src="ECP.js"></script>
+<script type="text/javascript" src="ECDH.js"></script>
+
+<script>
+/* test driver and function exerciser for ECDH/ECIES/ECDSA API Functions */
+		var i,j=0,res;
+		var result;
+		var pp="M0ng00se";
+
+		var EGS=ECDH.EGS;
+		var EFS=ECDH.EFS;
+		var EAS=16;
+		var sha=ECDH.HASH_TYPE;
+
+		var S1=[];
+		var W0=[];
+		var W1=[];
+		var Z0=[];
+		var Z1=[];
+		var RAW=[];
+		var SALT=[];
+		var P1=[];
+		var P2=[];
+		var V=[];
+		var M=[];
+		var T=new Array(12);  // must specify required length
+		var CS=[];
+		var DS=[];
+
+		var rng=new RAND();
+
+		rng.clean();
+		for (i=0;i<100;i++) RAW[i]=i;
+
+		rng.seed(100,RAW);
+//for (j=0;j<100;j++)
+//{
+
+		for (i=0;i<8;i++) SALT[i]=(i+1);  // set Salt
+
+		window.document.write("Alice's Passphrase= " + pp + "<br>");
+
+		var PW=ECDH.stringtobytes(pp);
+/* private key S0 of size EGS bytes derived from Password and Salt */
+		var S0=ECDH.PBKDF2(sha,PW,SALT,1000,EGS);
+
+		window.document.write("Alice's private key= 0x"+ECDH.bytestostring(S0)+ "<br>");
+/* Generate Key pair S/W */
+		ECDH.KEY_PAIR_GENERATE(null,S0,W0); 
+
+		window.document.write("Alice's public key= 0x"+ECDH.bytestostring(W0)+ "<br>");
+
+		res=ECDH.PUBLIC_KEY_VALIDATE(true,W0);
+		if (res!=0)
+			alert("ECP Public Key is invalid!");
+/* Random private key for other party */
+		ECDH.KEY_PAIR_GENERATE(rng,S1,W1);
+
+		window.document.write("Servers private key= 0x"+ECDH.bytestostring(S1)+ "<br>");
+		window.document.write("Servers public key= 0x"+ECDH.bytestostring(W1)+ "<br>");
+
+		res=ECDH.PUBLIC_KEY_VALIDATE(true,W1);
+		if (res!=0)
+			alert("ECP Public Key is invalid!");
+			
+
+/* Calculate common key using DH - IEEE 1363 method */
+
+		ECDH.ECPSVDP_DH(S0,W1,Z0);
+		ECDH.ECPSVDP_DH(S1,W0,Z1);
+
+		var same=true;
+		for (i=0;i<ECDH.EFS;i++)
+			if (Z0[i]!=Z1[i]) same=false;
+
+		if (!same)
+			alert("*** ECPSVDP-DH Failed");
+
+		var KEY=ECDH.KDF2(sha,Z0,null,ECDH.EAS);
+
+		window.document.write("Alice's DH Key=  0x"+ECDH.bytestostring(KEY)+ "<br>");
+		window.document.write("Servers DH Key=  0x"+ECDH.bytestostring(KEY)+ "<br>");
+
+		if (ROM.CURVETYPE!=ROM.MONTGOMERY)
+		{
+			window.document.write("Testing ECIES"+ "<br>");
+
+			P1[0]=0x0; P1[1]=0x1; P1[2]=0x2; 
+			P2[0]=0x0; P2[1]=0x1; P2[2]=0x2; P2[3]=0x3; 
+
+			for (i=0;i<=16;i++) M[i]=i; 
+
+			var C=ECDH.ECIES_ENCRYPT(sha,P1,P2,rng,W1,M,V,T);
+
+			window.document.write("Ciphertext= "+ "<br>");
+			window.document.write("V= 0x"+ECDH.bytestostring(V)+ "<br>");
+			window.document.write("C= 0x"+ECDH.bytestostring(C)+ "<br>");
+			window.document.write("T= 0x"+ECDH.bytestostring(T)+ "<br>");
+
+
+			M=ECDH.ECIES_DECRYPT(sha,P1,P2,V,C,T,S1);
+			if (M.length==0)
+				alert("*** ECIES Decryption Failed ");
+			else window.document.write("Decryption succeeded"+ "<br>");
+
+			window.document.write("Message is 0x"+ECDH.bytestostring(M)+ "<br>");
+
+			window.document.write("Testing ECDSA"+ "<br>");
+
+			if (ECDH.ECPSP_DSA(sha,rng,S0,M,CS,DS)!=0)
+				alert("***ECDSA Signature Failed");
+		
+			window.document.write("Signature= "+ "<br>");
+			window.document.write("C= 0x"+ECDH.bytestostring(CS)+ "<br>");
+			window.document.write("D= 0x"+ECDH.bytestostring(DS)+ "<br>");
+
+			if (ECDH.ECPVP_DSA(sha,W0,M,CS,DS)!=0)
+				alert("***ECDSA Verification Failed");
+			else window.document.write("ECDSA Signature/Verification succeeded "+  "<br>");
+		}
+//}
+//window.document.write("Test Completed Successfully"+ "<br>");
+</script>
+</body>
+</html>
diff --git a/version22/js/TestMPIN.html b/version22/js/TestMPIN.html
new file mode 100644
index 0000000..0cb6f67
--- /dev/null
+++ b/version22/js/TestMPIN.html
@@ -0,0 +1,330 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>JavaScript Test MPIN</title>
+</head>
+<body>
+<h1>JavaScript Test MPIN Example</h1>
+<script type="text/javascript" src="DBIG.js"></script>
+<script type="text/javascript" src="BIG.js"></script>
+<script type="text/javascript" src="FP.js"></script>
+<script type="text/javascript" src="ROM.js"></script>
+<script type="text/javascript" src="UInt64.js"></script>
+<script type="text/javascript" src="HASH256.js"></script>
+<script type="text/javascript" src="HASH384.js"></script>
+<script type="text/javascript" src="HASH512.js"></script>
+<script type="text/javascript" src="RAND.js"></script>
+<script type="text/javascript" src="AES.js"></script>
+<script type="text/javascript" src="GCM.js"></script>
+<script type="text/javascript" src="ECP.js"></script>
+<script type="text/javascript" src="FP2.js"></script>
+<script type="text/javascript" src="ECP2.js"></script>
+<script type="text/javascript" src="FP4.js"></script>
+<script type="text/javascript" src="FP12.js"></script>
+<script type="text/javascript" src="PAIR.js"></script>
+<script type="text/javascript" src="MPIN.js"></script>
+
+<script>
+/* test driver and function exerciser for MPIN API Functions */
+
+		var i,res;
+		var result;
+
+		var EGS=MPIN.EGS;
+		var EFS=MPIN.EFS;
+		var EAS=16;
+
+		var sha=MPIN.HASH_TYPE;
+
+		var rng=new RAND();
+		rng.clean();
+
+		var RAW=[];
+		for (i=0;i<100;i++) RAW[i]=i+1;
+		rng.seed(100,RAW);
+
+		var G1S=2*EFS+1; /* Group 1 Size */
+		var G2S=4*EFS; /* Group 2 Size */
+
+		var S=[];
+		var SST=[];
+		var TOKEN = [];
+		var PERMIT = [];
+		var SEC = [];
+		var xID = [];
+		var xCID = [];
+		var X= [];
+		var Y= [];
+		var E=[];
+		var F=[];
+		var HCID=[];
+		var HID=[];
+		var HTID=[];
+
+		var G1=[];
+		var G2=[];
+		var R=[];
+		var Z=[];
+		var W=[];
+		var T=[];
+		var CK=[];
+		var SK=[];
+
+		var HSID=[];
+
+/* Set configuration */
+		var PERMITS=true;
+		var PINERROR=true;
+		var FULL=true;
+    var ONE_PASS=false;
+    var TIME_FUNCTIONS=false;
+    var total_time=0;
+    var nIter=100
+/*
+    var PR=[];
+ pin=parseInt(prompt("Enter PIN= "));
+    window.document.write("Test Pairing" + "<br>");
+    for (i=0;i<100;i++)
+      MPIN.TEST_PAIR(PR);
+    window.document.write("Pairing= "+MPIN.bytestostring(PR) + "<br>");
+
+  pin=parseInt(prompt("Enter PIN= "));
+*/
+
+/* Trusted Authority set-up */
+		MPIN.RANDOM_GENERATE(rng,S);
+		window.document.write("Master Secret s: 0x"+MPIN.bytestostring(S) + "<br>");
+ 
+ /* Create Client Identity */
+ 		var IDstr = "testUser@miracl.com";
+		var CLIENT_ID = MPIN.stringtobytes(IDstr);  
+		HCID=MPIN.HASH_ID(sha,CLIENT_ID);  /* Either Client or TA calculates Hash(ID) - you decide! */
+		
+		window.document.write("Client ID= "+MPIN.bytestostring(CLIENT_ID) + "<br>");
+
+/* Client and Server are issued secrets by DTA */
+		MPIN.GET_SERVER_SECRET(S,SST);
+		window.document.write("Server Secret SS: 0x"+MPIN.bytestostring(SST) + "<br>");
+
+		MPIN.GET_CLIENT_SECRET(S,HCID,TOKEN);
+		window.document.write("Client Secret CS: 0x"+MPIN.bytestostring(TOKEN) + "<br>");     
+	
+/* Client extracts PIN from secret to create Token */
+		var pin=1234;
+	window.document.write("Client extracts PIN= "+pin + "<br>"); 
+		var rtn=MPIN.EXTRACT_PIN(sha,CLIENT_ID,pin,TOKEN);
+		if (rtn != 0)
+			window.document.write("Failed to extract PIN " + "<br>");  
+
+		window.document.write("Client Token TK: 0x"+MPIN.bytestostring(TOKEN) + "<br>");        
+
+		if (FULL)
+		{
+			MPIN.PRECOMPUTE(TOKEN,HCID,G1,G2);
+		}
+
+		var date;
+		if (PERMITS)
+		{
+			date=MPIN.today();
+/* Client gets "Time Token" permit from DTA */ 	
+			MPIN.GET_CLIENT_PERMIT(sha,date,S,HCID,PERMIT);
+			window.document.write("Time Permit TP: 0x"+MPIN.bytestostring(PERMIT) + "<br>");   
+
+/* This encoding makes Time permit look random - Elligator squared */
+			MPIN.ENCODING(rng,PERMIT);
+			window.document.write("Encoded Time Permit TP: 0x"+MPIN.bytestostring(PERMIT) + "<br>");   
+			MPIN.DECODING(PERMIT);
+			window.document.write("Decoded Time Permit TP: 0x"+MPIN.bytestostring(PERMIT) + "<br>");   
+		}
+		else date=0;
+
+
+		pin=parseInt(prompt("Enter PIN= "));
+
+/* 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_T(date|H(CLIENT_ID)))
+Random value x is supplied externally if RNG=null, otherwise generated and passed out by RNG
+
+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=xID;
+		var pxCID=xCID;
+		var pHID=HID;
+		var pHTID=HTID;
+		var pE=E;
+		var pF=F;
+		var pPERMIT=PERMIT;
+		var prHID;
+
+		if (date!=0)
+		{
+			prHID=pHTID;
+			if (!PINERROR)
+			{
+				pxID=null;
+			//	pHID=null;
+			}
+		}
+		else
+		{
+			prHID=pHID;
+			pPERMIT=null;
+			pxCID=null;
+			pHTID=null;
+		}
+		if (!PINERROR)
+		{
+			pE=null;
+			pF=null;
+		}
+
+                if (ONE_PASS)
+                {
+                  window.document.write("MPIN Single Pass " + "<br>");   
+                  timeValue = MPIN.GET_TIME();
+                  window.document.write("Epoch " + timeValue + "<br>");   
+                  if (TIME_FUNCTIONS)
+                  {
+                   var start = new Date().getTime();
+                   for (i = 0; i < nIter; ++i) {
+                     rtn=MPIN.CLIENT(sha,date,CLIENT_ID,rng,X,pin,TOKEN,SEC,pxID,pxCID,pPERMIT,timeValue,Y);
+                   }
+                   var end = new Date().getTime();
+                   var t1 = end - start;
+                   total_time = total_time + t1;
+                   var iter_time = t1 / nIter;
+                   var iter_per_sec = nIter / (t1 / 1000);
+                   window.document.write("MPIN.CLIENT: time " + t1 + "ms iteration time " + iter_time + "ms iterations per second " + iter_per_sec + "<br>");   
+                  }
+                  else
+                  {
+                    rtn=MPIN.CLIENT(sha,date,CLIENT_ID,rng,X,pin,TOKEN,SEC,pxID,pxCID,pPERMIT,timeValue,Y);
+                  }
+		  if (rtn != 0)
+                    window.document.write("FAILURE: CLIENT rtn: " + rtn + "<br>");   
+
+                  if (FULL)
+		  {
+                    if (TIME_FUNCTIONS)
+                    {
+                     var start = new Date().getTime();
+                     for (i = 0; i < nIter; ++i) {
+                        HCID=MPIN.HASH_ID(sha,CLIENT_ID);
+                        MPIN.GET_G1_MULTIPLE(rng,1,R,HCID,Z); 
+                     }
+                     var end = new Date().getTime();
+                     var t2 = end - start;
+                     total_time = total_time + t2;
+                     var iter_time = t2 / nIter;
+                     var iter_per_sec = nIter / (t2 / 1000);
+                     window.document.write("MPIN.GET_G1_MULTIPLE: time " + t2 + "ms iteration time " + iter_time + "ms iterations per second " + iter_per_sec + "<br>");   
+                    }
+                    else
+                    {
+                      HCID=MPIN.HASH_ID(sha,CLIENT_ID);
+                      MPIN.GET_G1_MULTIPLE(rng,1,R,HCID,Z);  /* Also Send Z=r.ID to Server, remember random r */
+                    }
+                  }
+
+                  rtn=MPIN.SERVER(sha,date,pHID,pHTID,Y,SST,pxID,pxCID,SEC,pE,pF,CLIENT_ID,timeValue);
+                  if (rtn != 0)
+                    window.document.write("FAILURE: SERVER rtn: " + rtn+ "<br>");  
+
+                  if (FULL)
+                  {
+					HSID=MPIN.HASH_ID(sha,CLIENT_ID);
+                    MPIN.GET_G1_MULTIPLE(rng,0,W,prHID,T);  /* Also send T=w.ID to client, remember random w  */
+                  }
+                }
+                else 
+                {
+                  window.document.write("MPIN Multi Pass " + "<br>");   
+                  rtn=MPIN.CLIENT_1(sha,date,CLIENT_ID,rng,X,pin,TOKEN,SEC,pxID,pxCID,pPERMIT);
+  		  if (rtn != 0)
+  			window.document.write("FAILURE: CLIENT_1 rtn: " + rtn + "<br>");   
+  
+  		  if (FULL)
+  		  {
+  			HCID=MPIN.HASH_ID(sha,CLIENT_ID);
+  			MPIN.GET_G1_MULTIPLE(rng,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. */
+    		  MPIN.SERVER_1(sha,date,CLIENT_ID,pHID,pHTID);
+    
+                  /* Server generates Random number Y and sends it to Client */
+    		  MPIN.RANDOM_GENERATE(rng,Y);
+    
+    		  if (FULL)
+    		  {
+					HSID=MPIN.HASH_ID(sha,CLIENT_ID);
+    				MPIN.GET_G1_MULTIPLE(rng,0,W,prHID,T);  /* Also send T=w.ID to client, remember random w  */
+    		  }
+    
+                  /* Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC */
+    		  rtn=MPIN.CLIENT_2(X,Y,SEC);
+    		  if (rtn != 0)
+    		    window.document.write("FAILURE: CLIENT_2 rtn: " + rtn + "<br>");  
+                    /* 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=MPIN.SERVER_2(date,pHID,pHTID,Y,SST,pxID,pxCID,SEC,pE,pF);
+    
+    		  if (rtn != 0)
+    			window.document.write("FAILURE: SERVER_1 rtn: " + rtn+ "<br>");  
+    
+                }
+    		  
+
+                if (rtn == this.MPIN.BAD_PIN)
+    		{
+    		  window.document.write("Server says - Bad Pin. I don't know you. Feck off." + "<br>"); 
+    		  if (PINERROR)
+    		  {
+    		    var err=MPIN.KANGAROO(E,F);
+    		    if (err!=0) window.document.write("(Client PIN is out by "+err + ")<br>");
+    		  }
+                }
+    		else 
+    		{
+    		  window.document.write("Server says - PIN is good! You really are "+IDstr + "<br>"); 
+    		  if (FULL)
+    		  {
+                    if (TIME_FUNCTIONS)
+                    {
+                     var start = new Date().getTime();
+                     for (i = 0; i < nIter; ++i) {
+                       MPIN.CLIENT_KEY(sha,G1,G2,pin,R,X,T,CK);
+                     }
+                     var end = new Date().getTime();
+                     var t3 = end - start;
+                     total_time = total_time + t3;
+                     var iter_time = t3 / nIter;
+                     var iter_per_sec = nIter / (t3 / 1000);
+                     window.document.write("MPIN.CLIENT_KEY: time " + t1 + "ms iteration time " + iter_time + "ms iterations per second " + iter_per_sec + "<br>");   
+                    }
+                    else
+                    {
+						H=MPIN.HASH_ALL(sha,HCID,pxID,pxCID,SEC,Y,Z,T);
+						MPIN.CLIENT_KEY(sha,G1,G2,pin,R,X,H,T,CK);
+                    }
+    		    window.document.write("Client Key =  0x"+MPIN.bytestostring(CK) + "<br>");    
+					H=MPIN.HASH_ALL(sha,HSID,pxID,pxCID,SEC,Y,Z,T);
+                    MPIN.SERVER_KEY(sha,Z,SST,W,H,pHID,pxID,pxCID,SK);
+                    window.document.write("Server Key =  0x"+MPIN.bytestostring(SK) + "<br>");    
+    		  }
+                }
+         //       var iter_time = total_time / nIter;
+         //       var iter_per_sec = nIter / (total_time / 1000);
+         //       window.document.write("CLIENT: total time " + total_time + "ms iteration time " + iter_time + "ms iterations per second " + iter_per_sec + "<br>");   
+
+    
+</script>
+</body>
+</html>
diff --git a/version22/js/TestRSA.html b/version22/js/TestRSA.html
new file mode 100644
index 0000000..ba650ca
--- /dev/null
+++ b/version22/js/TestRSA.html
@@ -0,0 +1,115 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>JavaScript Test RSA</title>
+</head>
+<body>
+<h1>JavaScript Test RSA Example</h1>
+<script type="text/javascript" src="ROM.js"></script>
+<script type="text/javascript" src="DBIG.js"></script>
+<script type="text/javascript" src="BIG.js"></script>
+<script type="text/javascript" src="UInt64.js"></script>
+<script type="text/javascript" src="HASH256.js"></script>
+<script type="text/javascript" src="HASH384.js"></script>
+<script type="text/javascript" src="HASH512.js"></script>
+<script type="text/javascript" src="RAND.js"></script>
+<script type="text/javascript" src="FF.js"></script>
+<script type="text/javascript" src="RSA.js"></script>
+
+
+<script>
+/* test driver and function exerciser for RSA API Functions */
+
+	var i,j=0,res;
+	var result;
+
+	var RFS=RSA.RFS;
+	var sha=RSA.HASH_TYPE;
+
+	var message="Hello World\n";
+
+	var pub=new rsa_public_key(ROM.FFLEN);
+	var priv=new rsa_private_key(ROM.HFLEN);
+
+	var ML=[];
+	var C=[];
+	var S=[];
+	var RAW=[];
+	
+	var rng=new RAND();
+	rng.clean();
+
+	for (i=0;i<100;i++) RAW[i]=i;
+	rng.seed(100,RAW);
+
+	var start,end,time;
+	start=new Date().getTime();
+	window.document.write("Generating public/private key pair (slow!)  <br>");
+	RSA.KEY_PAIR(rng,65537,priv,pub);
+	end=new Date().getTime();
+	time=end-start;
+	window.document.write("Time in ms= "+time+"<br>");
+
+	var M=RSA.stringtobytes(message);  
+	window.document.write("Encrypting test string <br>");
+
+	var E=RSA.OAEP_ENCODE(sha,M,rng,null); /* OAEP encode message m to e  */
+	window.document.write("Encoding= 0x" + RSA.bytestohex(E) + "<br>");  
+
+	window.document.write("Public key= 0x"+pub.n.toString() + "<br>"); 
+
+	start=new Date().getTime();	
+	RSA.ENCRYPT(pub,E,C);     /* encrypt encoded message */
+	end=new Date().getTime();	
+	time=end-start;
+	window.document.write("Time in ms= "+time+"<br>");
+
+	window.document.write("Ciphertext= 0x" + RSA.bytestohex(C) + "<br>");  
+
+	window.document.write("Decrypting test string <br>");
+	start=new Date().getTime();	
+	RSA.DECRYPT(priv,C,ML); 
+	end=new Date().getTime();
+	time=end-start;
+	window.document.write("Time in ms= "+time+"<br>");
+
+	var cmp=true;
+	if (E.length!=ML.length) cmp=false;
+	else
+	{
+		for (var j=0;j<E.length;j++)
+			if (E[j]!=ML[j]) cmp=false;
+	}
+	if (cmp) window.document.write("Decryption is OK <br>");
+	else window.document.write("Decryption Failed <br>");
+
+	var MS=RSA.OAEP_DECODE(sha,null,ML); /* OAEP decode message  */
+	window.document.write("Decoding= 0x" + RSA.bytestohex(MS) + "<br>");  
+
+	window.document.write("message= "+RSA.bytestostring(MS) + "<br>");  
+
+
+	window.document.write("Signing message <br>");
+	RSA.PKCS15(sha,M,C);
+
+	RSA.DECRYPT(priv,C,S); /* create signature in S */ 
+
+	window.document.write("Signature= 0x" + RSA.bytestohex(S) + "<br>");  
+
+	RSA.ENCRYPT(pub,S,ML); 
+
+	cmp=true;
+	if (C.length!=ML.length) cmp=false;
+	else
+	{
+		for (var j=0;j<C.length;j++)
+			if (C[j]!=ML[j]) cmp=false;
+	}
+	if (cmp) window.document.write("Signature is valid <br>");
+	else window.document.write("Signature is INVALID <br>");
+
+	RSA.PRIVATE_KEY_KILL(priv);
+
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/version22/js/UInt64.js b/version22/js/UInt64.js
new file mode 100644
index 0000000..2d93b9c
--- /dev/null
+++ b/version22/js/UInt64.js
@@ -0,0 +1,54 @@
+/*
+	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.
+*/
+
+/* rudimentary unsigned 64-bit type for SHA384 and SHA512 */
+
+var UInt64 = function(top,bot) {
+	this.top=top;
+	this.bot=bot;
+};
+
+UInt64.prototype={
+	add: function(y)
+	{
+		var t=(this.bot>>>0)+(y.bot>>>0);
+		var low=t >>> 0;
+		var high=(this.top>>>0)+(y.top>>>0);
+
+		this.bot=low;
+		if (low!=t)
+			this.top=(high+1)>>>0;
+		else
+			this.top=high;
+
+		return this;
+	},
+	copy: function()
+	{
+		var r=new UInt64(this.top,this.bot);
+		return r;
+	},
+	shlb: function()
+	{
+		var t=this.bot>>>24;
+		this.top=t+(this.top<<8);
+		this.bot<<=8;
+		return this;
+	}
+};
diff --git a/version22/js/readme.txt b/version22/js/readme.txt
new file mode 100644
index 0000000..e040021
--- /dev/null
+++ b/version22/js/readme.txt
@@ -0,0 +1,41 @@
+AMCL is very simple to build for JavaScript.
+
+First - decide the modulus type and curve type you want to use. Edit ROM.js 
+where indicated. You might want to use one of the curves whose details are
+already in there.
+
+Three example API files are provided, MPIN.js which 
+supports our M-Pin (tm) protocol, ECDH.js which supports elliptic 
+curve key exchange, digital signature and public key crypto, and RSA.js
+which supports RSA encryption. The first  can be tested using the 
+TestMPIN.html driver programs, the second can be tested using TestECDH.html, 
+and the third using TestRSA.html
+
+In the ROM.js file you must provide the curve constants. Several examples
+are provided there, if you are willing to use one of these.
+
+To help generate the ROM constants for your own curve some MIRACL helper 
+programs are included. The programs bngen.cpp and blsgen.cpp generate ROM 
+data for a BN and BLS pairing friendly curves, and the program ecgen.cpp 
+generates ROM data for regular EC curves.
+
+The MIRACL based program check.cpp helps choose the best number base for
+big number representation, given the word-length and the size of the modulus.
+
+The program bigtobig.cpp converts a big number to the AMCL 
+BIG format.
+
+
+For quick jumpstart:-
+
+Run Chrome browser and navigate to TestECDH.html
+
+or TestMPIN.html
+
+or BenchtestEC.html
+
+or BenchtestPAIR.html
+
+You might need to wait a couple of minutes for the output to appear.
+
+
diff --git a/version22/rust/.gitignore b/version22/rust/.gitignore
new file mode 100644
index 0000000..fc8bcce
--- /dev/null
+++ b/version22/rust/.gitignore
@@ -0,0 +1,5 @@
+cargo-registry
+target
+Cargo.lock
+.idea
+
diff --git a/version22/rust/Cargo.toml b/version22/rust/Cargo.toml
new file mode 100644
index 0000000..2e83270
--- /dev/null
+++ b/version22/rust/Cargo.toml
@@ -0,0 +1,24 @@
+[package]
+name = "amcl"
+version = "0.1.2"
+authors = [
+  "Vyacheslav Gudkov <vyacheslav.gudkov@dsr-company.com>",
+  "Evgeniy Razinkov <evgeniy.razinkov@dsr-company.com.ru>"
+  ]
+
+description = "The Apache Milagro Cryptographic Library(version 2.2)"
+license = "Apache-2.0"
+repository = "https://github.com/MRJCrunch/amcl"
+[lib]
+name = "amcl"
+path = "src/lib.rs"
+
+[features]
+default = ["BLS383"]
+Ed25519 = []
+GOLDILOCKS = []
+BN254 = []
+BLS383 = []
+BLS455 = []
+
+[dependencies]
\ No newline at end of file
diff --git a/version22/rust/readme.txt b/version22/rust/readme.txt
new file mode 100644
index 0000000..128f665
--- /dev/null
+++ b/version22/rust/readme.txt
@@ -0,0 +1,56 @@
+AMCL is very simple to build for Rust.
+
+This version supports both 32-bit and 64-bit builds.
+If your processor and operating system are both 64-bit, a 64-bit build 
+will probably be best. Otherwise use a 32-bit build.
+
+First - decide the modulus and curve type you want to use. Edit rom32.rs 
+or rom64.rs where indicated. You will probably want to use one of the curves 
+whose details are already in there. You might want to "raid" the rom 
+file from the C version of the library for more curves.
+
+Three example API files are provided, mpin.rs which 
+supports our M-Pin (tm) protocol, ecdh.rs which supports elliptic 
+curve key exchange, digital signature and public key crypto, and rsa.rs
+which supports the RSA method. The first can be tested using the 
+TestMPIN.rs driver program, the second can be tested using TestECDH.rs,
+and the third with TestRSA.rs
+
+
+In the rom32.rs/rom64.rs file you must provide the curve constants. Several 
+examples are provided there, if you are willing to use one of these.
+
+To help generate the ROM constants for your own curve some MIRACL helper 
+programs are included. The programs bngen.cpp and blsgen.cpp generate ROM 
+data for a BN and BLS pairing friendly curves, and the program ecgen.cpp 
+generates ROM data for regular EC curves.
+
+The MIRACL based program check.cpp helps choose the best number base for
+big number representation, given the word-length and the size of the modulus.
+
+The program bigtobig.cpp converts a big number to the AMCL 
+BIG format.
+
+For a quick jumpstart:-
+
+Copy rom32.rs to rom.rs for a 32-bit build
+
+rustc --cfg D32 -O -A dead_code TestMPIN.rs
+
+or 
+
+rustc --cfg D32 -O -A dead_code TestECDH.rs
+
+or
+
+rustc --cfg D32 -O -A dead_code TestRSA.rs
+
+also
+
+rustc --cfg D32 -O -A dead_code BenchtestEC.rs
+
+rustc --cfg D32 -O -A dead_code BenchtestPAIR.rs
+
+
+For a 64-bit build copy rom64.rs to rom.rs, and use instead the 
+flag --cfg D64
diff --git a/version22/rust/src/aes.rs b/version22/rust/src/aes.rs
new file mode 100644
index 0000000..5298837
--- /dev/null
+++ b/version22/rust/src/aes.rs
@@ -0,0 +1,628 @@
+/*
+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.
+*/
+
+pub const ECB: usize=0;
+pub const CBC: usize=1;
+pub const CFB1: usize=2;
+pub const CFB2: usize=3;
+pub const CFB4: usize=5;
+pub const OFB1: usize=14;
+pub const OFB2: usize=15;
+pub const OFB4: usize=17;
+pub const OFB8:usize=21;
+pub const OFB16: usize=29;
+pub const CTR1: usize=30;
+pub const CTR2: usize=31;
+pub const CTR4: usize=33;
+pub const CTR8: usize=37;
+pub const CTR16: usize=45;
+
+const INCO : [u8;4] = [0xB,0xD,0x9,0xE];  /* Inverse Coefficients */
+
+const PTAB : [u8;256] = [
+     1, 3, 5, 15, 17, 51, 85, 255, 26, 46, 114, 150, 161, 248, 19, 53,
+     95, 225, 56, 72, 216, 115, 149, 164, 247, 2, 6, 10, 30, 34, 102, 170,
+     229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217, 112, 144, 171, 230, 49,
+     83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104, 184, 211, 110, 178, 205,
+     76, 212, 103, 169, 224, 59, 77, 215, 98, 166, 241, 8, 24, 40, 120, 136,
+     131, 158, 185, 208, 107, 189, 220, 127, 129, 152, 179, 206, 73, 219, 118, 154,
+     181, 196, 87, 249, 16, 48, 80, 240, 11, 29, 39, 105, 187, 214, 97, 163,
+     254, 25, 43, 125, 135, 146, 173, 236, 47, 113, 147, 174, 233, 32, 96, 160,
+     251, 22, 58, 78, 210, 109, 183, 194, 93, 231, 50, 86, 250, 21, 63, 65,
+     195, 94, 226, 61, 71, 201, 64, 192, 91, 237, 44, 116, 156, 191, 218, 117,
+     159, 186, 213, 100, 172, 239, 42, 126, 130, 157, 188, 223, 122, 142, 137, 128,
+     155, 182, 193, 88, 232, 35, 101, 175, 234, 37, 111, 177, 200, 67, 197, 84,
+     252, 31, 33, 99, 165, 244, 7, 9, 27, 45, 119, 153, 176, 203, 70, 202,
+     69, 207, 74, 222, 121, 139, 134, 145, 168, 227, 62, 66, 198, 81, 243, 14,
+     18, 54, 90, 238, 41, 123, 141, 140, 143, 138, 133, 148, 167, 242, 13, 23,
+     57, 75, 221, 124, 132, 151, 162, 253, 28, 36, 108, 180, 199, 82, 246, 1];
+
+const LTAB : [u8;256] = [
+      0, 255, 25, 1, 50, 2, 26, 198, 75, 199, 27, 104, 51, 238, 223, 3,
+     100, 4, 224, 14, 52, 141, 129, 239, 76, 113, 8, 200, 248, 105, 28, 193,
+     125, 194, 29, 181, 249, 185, 39, 106, 77, 228, 166, 114, 154, 201, 9, 120,
+     101, 47, 138, 5, 33, 15, 225, 36, 18, 240, 130, 69, 53, 147, 218, 142,
+     150, 143, 219, 189, 54, 208, 206, 148, 19, 92, 210, 241, 64, 70, 131, 56,
+     102, 221, 253, 48, 191, 6, 139, 98, 179, 37, 226, 152, 34, 136, 145, 16,
+     126, 110, 72, 195, 163, 182, 30, 66, 58, 107, 40, 84, 250, 133, 61, 186,
+     43, 121, 10, 21, 155, 159, 94, 202, 78, 212, 172, 229, 243, 115, 167, 87,
+     175, 88, 168, 80, 244, 234, 214, 116, 79, 174, 233, 213, 231, 230, 173, 232,
+     44, 215, 117, 122, 235, 22, 11, 245, 89, 203, 95, 176, 156, 169, 81, 160,
+     127, 12, 246, 111, 23, 196, 73, 236, 216, 67, 31, 45, 164, 118, 123, 183,
+     204, 187, 62, 90, 251, 96, 177, 134, 59, 82, 161, 108, 170, 85, 41, 157,
+     151, 178, 135, 144, 97, 190, 220, 252, 188, 149, 207, 205, 55, 63, 91, 209,
+     83, 57, 132, 60, 65, 162, 109, 71, 20, 42, 158, 93, 86, 242, 211, 171,
+     68, 17, 146, 217, 35, 32, 46, 137, 180, 124, 184, 38, 119, 153, 227, 165,
+     103, 74, 237, 222, 197, 49, 254, 24, 13, 99, 140, 128, 192, 247, 112, 7];
+
+
+const FBSUB : [u8;256] = [
+     99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118,
+     202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192,
+     183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21,
+     4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117,
+     9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132,
+     83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207,
+     208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168,
+     81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210,
+     205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115,
+     96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219,
+     224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121,
+     231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8,
+     186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138,
+     112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158,
+     225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223,
+     140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22];
+
+const RBSUB : [u8;256] = [
+     82, 9, 106, 213, 48, 54, 165, 56, 191, 64, 163, 158, 129, 243, 215, 251,
+     124, 227, 57, 130, 155, 47, 255, 135, 52, 142, 67, 68, 196, 222, 233, 203,
+     84, 123, 148, 50, 166, 194, 35, 61, 238, 76, 149, 11, 66, 250, 195, 78,
+     8, 46, 161, 102, 40, 217, 36, 178, 118, 91, 162, 73, 109, 139, 209, 37,
+     114, 248, 246, 100, 134, 104, 152, 22, 212, 164, 92, 204, 93, 101, 182, 146,
+     108, 112, 72, 80, 253, 237, 185, 218, 94, 21, 70, 87, 167, 141, 157, 132,
+     144, 216, 171, 0, 140, 188, 211, 10, 247, 228, 88, 5, 184, 179, 69, 6,
+     208, 44, 30, 143, 202, 63, 15, 2, 193, 175, 189, 3, 1, 19, 138, 107,
+     58, 145, 17, 65, 79, 103, 220, 234, 151, 242, 207, 206, 240, 180, 230, 115,
+     150, 172, 116, 34, 231, 173, 53, 133, 226, 249, 55, 232, 28, 117, 223, 110,
+     71, 241, 26, 113, 29, 41, 197, 137, 111, 183, 98, 14, 170, 24, 190, 27,
+     252, 86, 62, 75, 198, 210, 121, 32, 154, 219, 192, 254, 120, 205, 90, 244,
+     31, 221, 168, 51, 136, 7, 199, 49, 177, 18, 16, 89, 39, 128, 236, 95,
+     96, 81, 127, 169, 25, 181, 74, 13, 45, 229, 122, 159, 147, 201, 156, 239,
+     160, 224, 59, 77, 174, 42, 245, 176, 200, 235, 187, 60, 131, 83, 153, 97,
+     23, 43, 4, 126, 186, 119, 214, 38, 225, 105, 20, 99, 85, 33, 12, 125];
+
+const RCO : [u8;16] = [1,2,4,8,16,32,64,128,27,54,108,216,171,77,154,47];
+
+const FTABLE : [u32;256] = [
+    0xa56363c6,0x847c7cf8,0x997777ee,0x8d7b7bf6,0xdf2f2ff,0xbd6b6bd6,
+    0xb16f6fde,0x54c5c591,0x50303060,0x3010102,0xa96767ce,0x7d2b2b56,
+    0x19fefee7,0x62d7d7b5,0xe6abab4d,0x9a7676ec,0x45caca8f,0x9d82821f,
+    0x40c9c989,0x877d7dfa,0x15fafaef,0xeb5959b2,0xc947478e,0xbf0f0fb,
+    0xecadad41,0x67d4d4b3,0xfda2a25f,0xeaafaf45,0xbf9c9c23,0xf7a4a453,
+    0x967272e4,0x5bc0c09b,0xc2b7b775,0x1cfdfde1,0xae93933d,0x6a26264c,
+    0x5a36366c,0x413f3f7e,0x2f7f7f5,0x4fcccc83,0x5c343468,0xf4a5a551,
+    0x34e5e5d1,0x8f1f1f9,0x937171e2,0x73d8d8ab,0x53313162,0x3f15152a,
+    0xc040408,0x52c7c795,0x65232346,0x5ec3c39d,0x28181830,0xa1969637,
+    0xf05050a,0xb59a9a2f,0x907070e,0x36121224,0x9b80801b,0x3de2e2df,
+    0x26ebebcd,0x6927274e,0xcdb2b27f,0x9f7575ea,0x1b090912,0x9e83831d,
+    0x742c2c58,0x2e1a1a34,0x2d1b1b36,0xb26e6edc,0xee5a5ab4,0xfba0a05b,
+    0xf65252a4,0x4d3b3b76,0x61d6d6b7,0xceb3b37d,0x7b292952,0x3ee3e3dd,
+    0x712f2f5e,0x97848413,0xf55353a6,0x68d1d1b9,0x0,0x2cededc1,
+    0x60202040,0x1ffcfce3,0xc8b1b179,0xed5b5bb6,0xbe6a6ad4,0x46cbcb8d,
+    0xd9bebe67,0x4b393972,0xde4a4a94,0xd44c4c98,0xe85858b0,0x4acfcf85,
+    0x6bd0d0bb,0x2aefefc5,0xe5aaaa4f,0x16fbfbed,0xc5434386,0xd74d4d9a,
+    0x55333366,0x94858511,0xcf45458a,0x10f9f9e9,0x6020204,0x817f7ffe,
+    0xf05050a0,0x443c3c78,0xba9f9f25,0xe3a8a84b,0xf35151a2,0xfea3a35d,
+    0xc0404080,0x8a8f8f05,0xad92923f,0xbc9d9d21,0x48383870,0x4f5f5f1,
+    0xdfbcbc63,0xc1b6b677,0x75dadaaf,0x63212142,0x30101020,0x1affffe5,
+    0xef3f3fd,0x6dd2d2bf,0x4ccdcd81,0x140c0c18,0x35131326,0x2fececc3,
+    0xe15f5fbe,0xa2979735,0xcc444488,0x3917172e,0x57c4c493,0xf2a7a755,
+    0x827e7efc,0x473d3d7a,0xac6464c8,0xe75d5dba,0x2b191932,0x957373e6,
+    0xa06060c0,0x98818119,0xd14f4f9e,0x7fdcdca3,0x66222244,0x7e2a2a54,
+    0xab90903b,0x8388880b,0xca46468c,0x29eeeec7,0xd3b8b86b,0x3c141428,
+    0x79dedea7,0xe25e5ebc,0x1d0b0b16,0x76dbdbad,0x3be0e0db,0x56323264,
+    0x4e3a3a74,0x1e0a0a14,0xdb494992,0xa06060c,0x6c242448,0xe45c5cb8,
+    0x5dc2c29f,0x6ed3d3bd,0xefacac43,0xa66262c4,0xa8919139,0xa4959531,
+    0x37e4e4d3,0x8b7979f2,0x32e7e7d5,0x43c8c88b,0x5937376e,0xb76d6dda,
+    0x8c8d8d01,0x64d5d5b1,0xd24e4e9c,0xe0a9a949,0xb46c6cd8,0xfa5656ac,
+    0x7f4f4f3,0x25eaeacf,0xaf6565ca,0x8e7a7af4,0xe9aeae47,0x18080810,
+    0xd5baba6f,0x887878f0,0x6f25254a,0x722e2e5c,0x241c1c38,0xf1a6a657,
+    0xc7b4b473,0x51c6c697,0x23e8e8cb,0x7cdddda1,0x9c7474e8,0x211f1f3e,
+    0xdd4b4b96,0xdcbdbd61,0x868b8b0d,0x858a8a0f,0x907070e0,0x423e3e7c,
+    0xc4b5b571,0xaa6666cc,0xd8484890,0x5030306,0x1f6f6f7,0x120e0e1c,
+    0xa36161c2,0x5f35356a,0xf95757ae,0xd0b9b969,0x91868617,0x58c1c199,
+    0x271d1d3a,0xb99e9e27,0x38e1e1d9,0x13f8f8eb,0xb398982b,0x33111122,
+    0xbb6969d2,0x70d9d9a9,0x898e8e07,0xa7949433,0xb69b9b2d,0x221e1e3c,
+    0x92878715,0x20e9e9c9,0x49cece87,0xff5555aa,0x78282850,0x7adfdfa5,
+    0x8f8c8c03,0xf8a1a159,0x80898909,0x170d0d1a,0xdabfbf65,0x31e6e6d7,
+    0xc6424284,0xb86868d0,0xc3414182,0xb0999929,0x772d2d5a,0x110f0f1e,
+    0xcbb0b07b,0xfc5454a8,0xd6bbbb6d,0x3a16162c];
+
+const RTABLE : [u32;256] = [
+    0x50a7f451,0x5365417e,0xc3a4171a,0x965e273a,0xcb6bab3b,0xf1459d1f,
+    0xab58faac,0x9303e34b,0x55fa3020,0xf66d76ad,0x9176cc88,0x254c02f5,
+    0xfcd7e54f,0xd7cb2ac5,0x80443526,0x8fa362b5,0x495ab1de,0x671bba25,
+    0x980eea45,0xe1c0fe5d,0x2752fc3,0x12f04c81,0xa397468d,0xc6f9d36b,
+    0xe75f8f03,0x959c9215,0xeb7a6dbf,0xda595295,0x2d83bed4,0xd3217458,
+    0x2969e049,0x44c8c98e,0x6a89c275,0x78798ef4,0x6b3e5899,0xdd71b927,
+    0xb64fe1be,0x17ad88f0,0x66ac20c9,0xb43ace7d,0x184adf63,0x82311ae5,
+    0x60335197,0x457f5362,0xe07764b1,0x84ae6bbb,0x1ca081fe,0x942b08f9,
+    0x58684870,0x19fd458f,0x876cde94,0xb7f87b52,0x23d373ab,0xe2024b72,
+    0x578f1fe3,0x2aab5566,0x728ebb2,0x3c2b52f,0x9a7bc586,0xa50837d3,
+    0xf2872830,0xb2a5bf23,0xba6a0302,0x5c8216ed,0x2b1ccf8a,0x92b479a7,
+    0xf0f207f3,0xa1e2694e,0xcdf4da65,0xd5be0506,0x1f6234d1,0x8afea6c4,
+    0x9d532e34,0xa055f3a2,0x32e18a05,0x75ebf6a4,0x39ec830b,0xaaef6040,
+    0x69f715e,0x51106ebd,0xf98a213e,0x3d06dd96,0xae053edd,0x46bde64d,
+    0xb58d5491,0x55dc471,0x6fd40604,0xff155060,0x24fb9819,0x97e9bdd6,
+    0xcc434089,0x779ed967,0xbd42e8b0,0x888b8907,0x385b19e7,0xdbeec879,
+    0x470a7ca1,0xe90f427c,0xc91e84f8,0x0,0x83868009,0x48ed2b32,
+    0xac70111e,0x4e725a6c,0xfbff0efd,0x5638850f,0x1ed5ae3d,0x27392d36,
+    0x64d90f0a,0x21a65c68,0xd1545b9b,0x3a2e3624,0xb1670a0c,0xfe75793,
+    0xd296eeb4,0x9e919b1b,0x4fc5c080,0xa220dc61,0x694b775a,0x161a121c,
+    0xaba93e2,0xe52aa0c0,0x43e0223c,0x1d171b12,0xb0d090e,0xadc78bf2,
+    0xb9a8b62d,0xc8a91e14,0x8519f157,0x4c0775af,0xbbdd99ee,0xfd607fa3,
+    0x9f2601f7,0xbcf5725c,0xc53b6644,0x347efb5b,0x7629438b,0xdcc623cb,
+    0x68fcedb6,0x63f1e4b8,0xcadc31d7,0x10856342,0x40229713,0x2011c684,
+    0x7d244a85,0xf83dbbd2,0x1132f9ae,0x6da129c7,0x4b2f9e1d,0xf330b2dc,
+    0xec52860d,0xd0e3c177,0x6c16b32b,0x99b970a9,0xfa489411,0x2264e947,
+    0xc48cfca8,0x1a3ff0a0,0xd82c7d56,0xef903322,0xc74e4987,0xc1d138d9,
+    0xfea2ca8c,0x360bd498,0xcf81f5a6,0x28de7aa5,0x268eb7da,0xa4bfad3f,
+    0xe49d3a2c,0xd927850,0x9bcc5f6a,0x62467e54,0xc2138df6,0xe8b8d890,
+    0x5ef7392e,0xf5afc382,0xbe805d9f,0x7c93d069,0xa92dd56f,0xb31225cf,
+    0x3b99acc8,0xa77d1810,0x6e639ce8,0x7bbb3bdb,0x97826cd,0xf418596e,
+    0x1b79aec,0xa89a4f83,0x656e95e6,0x7ee6ffaa,0x8cfbc21,0xe6e815ef,
+    0xd99be7ba,0xce366f4a,0xd4099fea,0xd67cb029,0xafb2a431,0x31233f2a,
+    0x3094a5c6,0xc066a235,0x37bc4e74,0xa6ca82fc,0xb0d090e0,0x15d8a733,
+    0x4a9804f1,0xf7daec41,0xe50cd7f,0x2ff69117,0x8dd64d76,0x4db0ef43,
+    0x544daacc,0xdf0496e4,0xe3b5d19e,0x1b886a4c,0xb81f2cc1,0x7f516546,
+    0x4ea5e9d,0x5d358c01,0x737487fa,0x2e410bfb,0x5a1d67b3,0x52d2db92,
+    0x335610e9,0x1347d66d,0x8c61d79a,0x7a0ca137,0x8e14f859,0x893c13eb,
+    0xee27a9ce,0x35c961b7,0xede51ce1,0x3cb1477a,0x59dfd29c,0x3f73f255,
+    0x79ce1418,0xbf37c773,0xeacdf753,0x5baafd5f,0x146f3ddf,0x86db4478,
+    0x81f3afca,0x3ec468b9,0x2c342438,0x5f40a3c2,0x72c31d16,0xc25e2bc,
+    0x8b493c28,0x41950dff,0x7101a839,0xdeb30c08,0x9ce4b4d8,0x90c15664,
+    0x6184cb7b,0x70b632d5,0x745c6c48,0x4257b8d0];
+
+
+pub struct AES {
+	nk: usize,
+	nr: usize,
+	mode: usize,
+	fkey: [u32;60],
+	rkey: [u32;60],
+	pub f: [u8;16]
+}
+
+impl AES {
+
+	fn rotl8(x: u32) -> u32 {
+		return ((x)<<8)|((x)>>24);
+	}
+
+	fn rotl16(x: u32) -> u32 {
+		return ((x)<<16)|((x)>>16);
+	}
+
+	fn rotl24(x: u32) -> u32 {
+		return ((x)<<24)|((x)>>8);
+	}
+
+	fn pack(b: [u8;4]) -> u32 { /* pack bytes into a 32-bit Word */
+        return ((((b[3])&0xff) as u32)<<24)|((((b[2])&0xff) as u32)<<16)|((((b[1])&0xff) as u32)<<8)|(((b[0])&0xff) as u32);
+	}
+  
+	fn unpack(a: u32) -> [u8;4] { /* unpack bytes from a word */
+        let b:[u8;4]=[(a&0xff) as u8,((a>>8)&0xff) as u8,((a>>16)&0xff) as u8,((a>>24)&0xff) as u8];
+		return b;
+	}
+
+	fn bmul(x: u8,y: u8) -> u8 { /* x.y= AntiLog(Log(x) + Log(y)) */
+        let ix=(x as usize)&0xff;
+        let iy=(y as usize)&0xff;
+        let lx=(LTAB[ix] as usize)&0xff;
+        let ly=(LTAB[iy] as usize)&0xff;
+    
+        if x != 0 && y != 0 {
+			return PTAB[(lx+ly)%255];
+		} else {return 0}
+	}	
+
+	fn subbyte(a: u32) -> u32 {
+        let mut b=AES::unpack(a);
+        b[0]=FBSUB[b[0] as usize];
+        b[1]=FBSUB[b[1] as usize];
+        b[2]=FBSUB[b[2] as usize];
+        b[3]=FBSUB[b[3] as usize];
+        return AES::pack(b);
+	}   
+
+	fn product(x: u32,y: u32) -> u8 { /* dot product of two 4-byte arrays */
+        let xb=AES::unpack(x);
+        let yb=AES::unpack(y);
+    
+        return AES::bmul(xb[0],yb[0])^AES::bmul(xb[1],yb[1])^AES::bmul(xb[2],yb[2])^AES::bmul(xb[3],yb[3]);
+	}
+
+	fn invmixcol(x: u32) -> u32 { /* matrix Multiplication */
+        let mut b:[u8;4]=[0;4];
+        let mut m=AES::pack(INCO);
+        b[3]=AES::product(m,x);
+        m=AES::rotl24(m);
+        b[2]=AES::product(m,x);
+        m=AES::rotl24(m);
+        b[1]=AES::product(m,x);
+        m=AES::rotl24(m);
+        b[0]=AES::product(m,x);
+        let y=AES::pack(b);
+        return y;
+	}
+
+	fn increment(f: &mut [u8;16]) {
+		for i in 0..16 {
+			f[i]+=1;
+			if f[i]!=0 {break}
+		}
+	}
+
+	pub fn new() -> AES {
+		AES {
+			nk:0,
+			nr:0,
+			mode:0,
+			fkey:[0;60],
+			rkey:[0;60],
+			f:[0;16]
+
+		}
+	}
+
+/* reset cipher */
+	pub fn reset(&mut self,m: usize,iv: Option<[u8;16]>) { /* reset mode, or reset iv */
+		self.mode=m;
+        for i in 0..16 {self.f[i]=0}
+        if self.mode != ECB
+        {
+        	if let Some(x) = iv {
+        		for i in 0..16 {self.f[i]=x[i]}
+        	}
+		}
+	}	
+
+	pub fn init(&mut self,m: usize,nkey: usize,key: &[u8],iv: Option<[u8;16]>) -> bool {   
+/* Key Scheduler. Create expanded encryption key */
+		let mut cipherkey:[u32;8]=[0;8];
+        let mut b:[u8;4]=[0;4];
+        let nk=nkey/4;
+		if nk!=4 && nk!=6 && nk!=8 {return false}
+		let nr=6+nk;
+		self.nk=nk;
+		self.nr=nr;
+        self.reset(m,iv);
+        let n=4*(nr+1);
+        
+        let mut j=0;
+        for  i in 0..nk {
+            for k in 0..4 {b[k]=key[j+k]}
+            cipherkey[i]=AES::pack(b);
+            j+=4;
+        }
+
+        for i in 0..nk {self.fkey[i]=cipherkey[i]}
+        j=nk;
+		let mut k=0;    
+        while j<n  {      	
+            self.fkey[j]=self.fkey[j-nk]^AES::subbyte(AES::rotl24(self.fkey[j-1]))^(RCO[k] as u32);
+            for i in 1..nk {
+            	if (i+j) >= n {break}       	
+                self.fkey[i+j]=self.fkey[i+j-nk]^self.fkey[i+j-1];             
+            }
+            j+=nk;
+            k+=1;
+        }
+     
+        /* now for the expanded decrypt key in reverse order */
+        
+        for j in 0..4 {self.rkey[j+n-4]=self.fkey[j]}
+        let mut i=4;
+        while i<n-4 {
+            let k=n-4-i;
+            for j in 0..4 {self.rkey[k+j]=AES::invmixcol(self.fkey[i+j])}
+            i+=4;
+        }
+        for j in n-4..n {self.rkey[j-n+4]=self.fkey[j]}
+		return true;
+	}
+
+	pub fn getreg(&mut self) -> [u8;16] {
+        let mut ir:[u8;16]=[0;16];
+        for i in 0..16 {ir[i]=self.f[i]}
+        return ir;
+	}
+
+    /* Encrypt a single block */
+	pub fn ecb_encrypt(&mut self,buff: &mut [u8;16]) {
+        let mut b:[u8;4]=[0;4]; 
+        let mut p:[u32;4]=[0;4]; 
+        let mut q:[u32;4]=[0;4]; 
+    
+        let mut j=0;
+        for i in 0..4 {
+            for k in 0..4 {b[k]=buff[j+k]}
+            p[i]=AES::pack(b);
+            p[i]^=self.fkey[i];
+            j+=4;
+        }
+    
+        let mut k=4;
+    
+    /* State alternates between p and q */
+        for _ in 1..self.nr {
+            q[0]=self.fkey[k]^FTABLE[(p[0]&0xff) as usize]^AES::rotl8(FTABLE[((p[1]>>8)&0xff) as usize])^AES::rotl16(FTABLE[((p[2]>>16)&0xff) as usize])^AES::rotl24(FTABLE[((p[3]>>24)&0xff) as usize]);
+            
+            q[1]=self.fkey[k+1]^FTABLE[(p[1]&0xff) as usize]^AES::rotl8(FTABLE[((p[2]>>8)&0xff) as usize])^AES::rotl16(FTABLE[((p[3]>>16)&0xff) as usize])^AES::rotl24(FTABLE[((p[0]>>24)&0xff) as usize]);
+            
+            q[2]=self.fkey[k+2]^FTABLE[(p[2]&0xff) as usize]^AES::rotl8(FTABLE[((p[3]>>8)&0xff) as usize])^AES::rotl16(FTABLE[((p[0]>>16)&0xff) as usize])^AES::rotl24(FTABLE[((p[1]>>24)&0xff) as usize]);
+            
+            q[3]=self.fkey[k+3]^FTABLE[(p[3]&0xff) as usize]^AES::rotl8(FTABLE[((p[0]>>8)&0xff) as usize])^AES::rotl16(FTABLE[((p[1]>>16)&0xff) as usize])^AES::rotl24(FTABLE[((p[2]>>24)&0xff) as usize]);
+            
+            k+=4;
+            for j in 0..4 {
+				let t=p[j]; p[j]=q[j]; q[j]=t;
+            }
+        }
+    
+    /* Last Round */
+    
+        q[0]=self.fkey[k]^(FBSUB[(p[0]&0xff) as usize] as u32)^AES::rotl8((FBSUB[((p[1]>>8)&0xff) as usize]) as u32)^AES::rotl16((FBSUB[((p[2]>>16)&0xff) as usize]) as u32)^AES::rotl24((FBSUB[((p[3]>>24)&0xff) as usize]) as u32);
+    
+        q[1]=self.fkey[k+1]^(FBSUB[(p[1]&0xff) as usize] as u32)^AES::rotl8((FBSUB[((p[2]>>8)&0xff) as usize]) as u32)^AES::rotl16((FBSUB[((p[3]>>16)&0xff) as usize]) as u32)^AES::rotl24((FBSUB[((p[0]>>24)&0xff) as usize]) as u32);
+    
+        q[2]=self.fkey[k+2]^(FBSUB[(p[2]&0xff) as usize] as u32)^AES::rotl8((FBSUB[((p[3]>>8)&0xff) as usize]) as u32)^AES::rotl16((FBSUB[((p[0]>>16)&0xff) as usize]) as u32)^AES::rotl24((FBSUB[((p[1]>>24)&0xff) as usize]) as u32);
+    
+        q[3]=self.fkey[k+3]^(FBSUB[(p[3]&0xff) as usize] as u32)^AES::rotl8((FBSUB[((p[0]>>8)&0xff) as usize]) as u32)^AES::rotl16((FBSUB[((p[1]>>16)&0xff) as usize]) as u32)^AES::rotl24((FBSUB[((p[2]>>24)&0xff) as usize]) as u32);
+    
+        j=0;
+        for i in 0..4 {
+            b=AES::unpack(q[i]);
+            for k in 0..4 {buff[j+k]=b[k]}
+            j+=4;
+        }
+	}
+
+    /* Decrypt a single block */
+	pub fn ecb_decrypt(&mut self,buff: &mut [u8;16]) {
+        let mut b:[u8;4]=[0;4]; 
+        let mut p:[u32;4]=[0;4]; 
+        let mut q:[u32;4]=[0;4]; 
+    
+        let mut j=0;
+        for i in 0..4 {
+            for k in 0..4 {b[k]=buff[j+k]}
+            p[i]=AES::pack(b);
+            p[i]^=self.rkey[i];
+            j+=4;
+        }
+    
+         let mut k=4;
+    
+    /* State alternates between p and q */
+        for _ in 1..self.nr {
+            
+            q[0]=self.rkey[k]^RTABLE[(p[0]&0xff) as usize]^AES::rotl8(RTABLE[((p[3]>>8)&0xff) as usize])^AES::rotl16(RTABLE[((p[2]>>16)&0xff) as usize])^AES::rotl24(RTABLE[((p[1]>>24)&0xff) as usize]);
+            
+            q[1]=self.rkey[k+1]^RTABLE[(p[1]&0xff) as usize]^AES::rotl8(RTABLE[((p[0]>>8)&0xff) as usize])^AES::rotl16(RTABLE[((p[3]>>16)&0xff) as usize])^AES::rotl24(RTABLE[((p[2]>>24)&0xff) as usize]);
+            
+        
+            q[2]=self.rkey[k+2]^RTABLE[(p[2]&0xff) as usize]^AES::rotl8(RTABLE[((p[1]>>8)&0xff) as usize])^AES::rotl16(RTABLE[((p[0]>>16)&0xff) as usize])^AES::rotl24(RTABLE[((p[3]>>24)&0xff) as usize]);
+       
+            q[3]=self.rkey[k+3]^RTABLE[(p[3]&0xff) as usize]^AES::rotl8(RTABLE[((p[2]>>8)&0xff) as usize])^AES::rotl16(RTABLE[((p[1]>>16)&0xff) as usize])^AES::rotl24(RTABLE[((p[0]>>24)&0xff) as usize]);
+            
+    
+            k+=4;
+            for j in 0..4 {
+				let t=p[j]; p[j]=q[j]; q[j]=t;
+            }
+        }
+    
+    /* Last Round */
+        
+        q[0]=self.rkey[k]^(RBSUB[(p[0]&0xff) as usize] as u32)^AES::rotl8((RBSUB[((p[3]>>8)&0xff) as usize]) as u32)^AES::rotl16((RBSUB[((p[2]>>16)&0xff) as usize]) as u32)^AES::rotl24((RBSUB[((p[1]>>24)&0xff) as usize]) as u32);
+        
+        q[1]=self.rkey[k+1]^(RBSUB[(p[1]&0xff) as usize] as u32)^AES::rotl8((RBSUB[((p[0]>>8)&0xff) as usize]) as u32)^AES::rotl16((RBSUB[((p[3]>>16)&0xff) as usize]) as u32)^AES::rotl24((RBSUB[((p[2]>>24)&0xff) as usize]) as u32);
+        
+        
+        q[2]=self.rkey[k+2]^(RBSUB[(p[2]&0xff) as usize] as u32)^AES::rotl8((RBSUB[((p[1]>>8)&0xff) as usize]) as u32)^AES::rotl16((RBSUB[((p[0]>>16)&0xff) as usize]) as u32)^AES::rotl24((RBSUB[((p[3]>>24)&0xff) as usize]) as u32);
+
+        q[3]=self.rkey[k+3]^(RBSUB[((p[3])&0xff) as usize] as u32)^AES::rotl8((RBSUB[((p[2]>>8)&0xff) as usize]) as u32)^AES::rotl16((RBSUB[((p[1]>>16)&0xff) as usize]) as u32)^AES::rotl24((RBSUB[((p[0]>>24)&0xff) as usize]) as u32);
+    
+        j=0;
+        for i in 0..4 {
+            b=AES::unpack(q[i]);
+            for k in 0..4 {buff[j+k]=b[k]}
+            j+=4;
+        }
+	}
+
+/* Encrypt using selected mode of operation */
+	pub fn encrypt(&mut self,buff: &mut [u8;16]) -> u32 {
+		let mut st:[u8;16]=[0;16]; 
+    
+    // Supported Modes of Operation
+    
+        let mut fell_off: u32=0;
+
+        match self.mode {
+        	ECB => {
+            	self.ecb_encrypt(buff);
+            	return 0;
+        	},
+        	CBC => {
+            	for j in 0..16 {buff[j]^=self.f[j]}
+            	self.ecb_encrypt(buff);
+            	for j in 0..16 {self.f[j]=buff[j]}
+            	return 0;
+        	},
+    
+        	CFB1 | CFB2 | CFB4 => {
+            	let bytes=self.mode-CFB1+1;
+            	for j in 0..bytes {fell_off=(fell_off<<8)|(self.f[j] as u32)}
+            	for j in 0..16 {st[j]=self.f[j]}
+            	for j in bytes..16 {self.f[j-bytes]=self.f[j]}
+            	self.ecb_encrypt(&mut st);
+            	for j in 0..bytes {
+					buff[j]^=st[j];
+				self.f[16-bytes+j]=buff[j];
+            	}
+            	return fell_off;
+        	},
+    
+        	OFB1 | OFB2 | OFB4 | OFB8 | OFB16 => {
+           		let bytes=self.mode-OFB1+1;
+             	for j in 0..16 {st[j]=self.f[j]}
+            	self.ecb_encrypt(&mut st);
+           		for j in 0..bytes {buff[j]^=st[j]}       
+              	for j in 0..16 {self.f[j]=st[j]}          		     	            	
+
+            	//self.ecb_encrypt(&mut (self.f));
+            	//for j in 0..bytes {buff[j]^=self.f[j]}
+            	return 0;
+        	},
+    
+			CTR1 | CTR2 | CTR4 | CTR8 | CTR16 => {
+	    		let bytes=self.mode-CTR1+1;
+	    		for j in 0..16 {st[j]=self.f[j]}
+	    		self.ecb_encrypt(&mut st);
+	    		for j in 0..bytes {buff[j]^=st[j]}
+	    		AES::increment(&mut (self.f));
+	    		return 0;
+	    	},
+
+        	_ => {
+            	return 0;
+        	}
+        }
+    }
+
+    /* Decrypt using selected mode of operation */
+	pub fn decrypt(&mut self,buff: &mut [u8;16]) -> u32 {
+
+		let mut st:[u8;16]=[0;16]; 
+        
+        // Supported Modes of Operation
+        
+       	let mut fell_off: u32=0;
+
+        match self.mode {
+        	ECB => {
+            	self.ecb_decrypt(buff);
+            	return 0;
+            },
+        	CBC => {
+            	for j in 0..16 {
+					st[j]=self.f[j];
+					self.f[j]=buff[j];
+            	}
+            	self.ecb_decrypt(buff);
+            	for j in 0..16 {
+					buff[j]^=st[j];
+					st[j]=0;
+            	}
+            	return 0;
+           	},
+        	CFB1 | CFB2 | CFB4 => {
+            	let bytes=self.mode-CFB1+1;
+            	for j in 0..bytes {fell_off=(fell_off<<8)|(self.f[j] as u32)}
+            	for j in 0..16 {st[j]=self.f[j]}
+            	for j in bytes..16 {self.f[j-bytes]=self.f[j]}
+            	self.ecb_encrypt(&mut st);
+            	for j in 0..bytes {
+					self.f[16-bytes+j]=buff[j];
+					buff[j]^=st[j];
+            	}
+            	return fell_off;
+            },
+        	OFB1 | OFB2 | OFB4 | OFB8 | OFB16 => {
+           		let bytes=self.mode-OFB1+1;
+             	for j in 0..16 {st[j]=self.f[j]}
+            	self.ecb_encrypt(&mut st);
+           		for j in 0..bytes {buff[j]^=st[j]}       
+              	for j in 0..16 {self.f[j]=st[j]}          		
+            //	self.ecb_encrypt(A.f[:]);
+            //	for j in 0..bytes {buff[j]^=self.f[j]}
+            	return 0;
+            },
+
+			CTR1 | CTR2 | CTR4 | CTR8 | CTR16 => {
+	    		let bytes=self.mode-CTR1+1;
+	    		for j in 0..16 {st[j]=self.f[j]}
+	    		self.ecb_encrypt(&mut st);
+	    		for j in 0..bytes {buff[j]^=st[j]}
+	    		AES::increment(&mut (self.f));
+	    		return 0;
+	    	},
+
+        	_ => {
+            	return 0;
+        	}
+        }
+    } 
+
+/* Clean up and delete left-overs */
+	pub fn end(&mut self) { // clean up
+    	for i in 0..4*(self.nr+1) {self.fkey[i]=0; self.rkey[i]=0}
+    	for i in 0..16 {self.f[i]=0}
+	}
+}
+
+/*
+fn main()
+{
+	let mut key:[u8;32]=[0;32];
+	let mut block:[u8;16]=[0;16];
+	let mut iv: [u8;16] = [0;16];
+
+	for i in 0..32 {key[i]=0}
+	key[0]=1;
+	for i in 0..16 {iv[i]=i as u8}
+	for i in 0..16 {block[i]=i as u8}
+
+	let mut aes=AES::new();
+	aes.init(CTR16,32,&key,Some(iv));
+
+	println!("Plain= ");
+	for i in 0..16 {print!("{:02x} ",block[i])}
+	println!("");	
+
+	aes.encrypt(&mut block);
+
+	println!("Encrypt= ");
+	for i in 0..16 {print!("{:02x} ",block[i])}
+	println!("");	
+
+	aes.reset(CTR16,Some(iv));
+	aes.decrypt(&mut block);
+
+	println!("Decrypt= ");
+	for i in 0..16 {print!("{:02x} ",block[i])}
+	println!("");	
+
+	aes.end();
+}
+*/
diff --git a/version22/rust/src/big.rs b/version22/rust/src/big.rs
new file mode 100644
index 0000000..5e3fb1d
--- /dev/null
+++ b/version22/rust/src/big.rs
@@ -0,0 +1,1227 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use std::fmt;
+use std::cmp::Ordering;
+use std::str::SplitWhitespace;
+
+use rom;
+use rom::{Chunk, NLEN};
+
+#[cfg(target_pointer_width = "32")]
+use rom::DChunk;
+
+#[derive(Copy, Clone)]
+pub struct BIG {
+ 	pub w: [Chunk; rom::NLEN]
+}
+
+//mod dbig;
+
+use dbig::DBIG;
+use rand::RAND;
+
+impl fmt::Display for BIG {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let mut big = self.clone();
+        write!(f, "BIG: [ {} ]", big.tostring())
+    }
+}
+
+impl fmt::Debug for BIG {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let mut big = self.clone();
+        write!(f, "BIG: [ {} ]", big.tostring())
+    }
+}
+
+impl PartialEq for BIG {
+    fn eq(&self, other: &BIG) -> bool {
+        return self.w == other.w;
+    }
+}
+
+impl Ord for BIG {
+    fn cmp(&self, other: &BIG) -> Ordering {
+        let r = BIG::comp(self, other);
+        if r > 0 {
+            return Ordering::Greater;
+        }
+        if r < 0 {
+            return Ordering::Less;
+        }
+        return Ordering::Equal;
+    }
+}
+
+impl Eq for BIG { }
+
+impl PartialOrd for BIG {
+    fn partial_cmp(&self, other: &BIG) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+impl BIG {
+
+   pub fn new() -> BIG {
+        BIG {
+        	w: [0; rom::NLEN]
+         }
+    }
+
+    pub fn new_int(x:isize) -> BIG {
+    	let mut s= BIG::new();
+    	s.w[0]=x as Chunk;
+    	return s;
+    }
+
+    pub fn new_ints(a:&[Chunk]) -> BIG {
+    	let mut s= BIG::new();
+    	for i in 0..rom::NLEN {s.w[i]=a[i]}
+    	return s;
+    }
+
+    pub fn new_copy(y:&BIG) -> BIG {
+    	let mut s= BIG::new();   
+    	for i in 0..rom::NLEN {s.w[i]=y.w[i]}
+    	return s;	
+    }
+
+    pub fn new_big(y:&BIG) -> BIG {
+        let mut s= BIG::new();   
+        for i in 0..rom::NLEN {s.w[i]=y.w[i]}
+        return s;   
+    }
+
+    pub fn new_dcopy(y:&DBIG) -> BIG {
+    	let mut s= BIG::new();   
+    	for i in 0..rom::NLEN {s.w[i]=y.w[i]}
+    	return s;	
+    } 
+
+	pub fn get(&self,i:usize) -> Chunk {
+		return self.w[i]; 
+	}
+
+	pub fn set(&mut self,i:usize,x:Chunk) {
+		self.w[i]=x;	
+	}
+
+	pub fn xortop(&mut self,x:Chunk) {
+		self.w[rom::NLEN-1]^=x;
+	}
+
+	pub fn ortop(&mut self,x:Chunk) {
+		self.w[rom::NLEN-1]|=x;
+	}
+
+/* test for zero */
+	pub fn iszilch(&self) -> bool {
+		for i in 0 ..rom::NLEN {
+			if self.w[i]!=0 {return false}
+		}
+		return true; 
+	}
+
+/* set to zero */
+	pub fn zero(&mut self) {
+		for i in 0 ..rom::NLEN {
+			self.w[i]=0
+		}
+	}
+
+/* Test for equal to one */
+	pub fn isunity(&self) -> bool {
+		for i in 0 ..rom::NLEN {
+			if self.w[i]!=0 {return false}
+		}
+		if self.w[0]!=1 {return false}
+		return true;
+	}
+
+/* set to one */
+	pub fn one(&mut self) {
+		self.w[0]=1;
+		for i in 1 ..rom::NLEN {
+			self.w[i]=0;
+		}
+	}
+
+/* Copy from another BIG */
+	pub fn copy(&mut self,x: &BIG) {
+		for i in 0 ..rom::NLEN {
+			self.w[i]=x.w[i]
+		}
+	}
+
+    pub fn dcopy(&mut self,x: &DBIG)
+    {
+        for i in 0 ..rom::NLEN {self.w[i] = x.w[i]}
+    }
+
+/* calculate Field Excess */
+	pub fn excess(a:&BIG) -> Chunk {
+		return (a.w[rom::NLEN-1]&rom::OMASK)>>(rom::MODBITS%rom::BASEBITS)
+	}
+
+    pub fn ff_excess(a:&BIG) -> Chunk {
+        return (a.w[rom::NLEN-1]&rom::P_OMASK)>>(rom::P_MB)
+    }
+
+#[cfg(target_pointer_width = "32")]
+    pub fn pexceed(a: &BIG,b: &BIG) -> bool {
+        let ea=BIG::excess(a);
+        let eb=BIG::excess(b);        
+        if ((ea+1) as DChunk)*((eb+1) as DChunk) > rom::FEXCESS as DChunk {return true}
+        return false
+    }
+
+#[cfg(target_pointer_width = "32")]
+    pub fn sexceed(a: &BIG) -> bool {
+        let ea=BIG::excess(a);
+        if ((ea+1) as DChunk)*((ea+1) as DChunk) > rom::FEXCESS as DChunk {return true}
+        return false
+    }
+
+#[cfg(target_pointer_width = "32")]
+    pub fn ff_pexceed(a: &BIG,b: &BIG) -> bool {
+        let ea=BIG::ff_excess(a);
+        let eb=BIG::ff_excess(b);
+        if ((ea+1) as DChunk)*((eb+1) as DChunk) > rom::P_FEXCESS as DChunk {return true}
+        return false;
+    }
+
+#[cfg(target_pointer_width = "32")]
+    pub fn ff_sexceed(a: &BIG) -> bool {
+        let ea=BIG::ff_excess(a);
+        if ((ea+1) as DChunk)*((ea+1) as DChunk) > rom::P_FEXCESS as DChunk {return true}
+        return false;
+    }
+
+/* Get top and bottom half of =x*y+c+r */
+#[cfg(target_pointer_width = "32")]
+    pub fn muladd(a: Chunk,b: Chunk,c: Chunk,r: Chunk) -> (Chunk,Chunk) {
+        let prod:DChunk = (a as DChunk)*(b as DChunk)+(c as DChunk)+(r as DChunk);
+        let bot=(prod&(rom::BMASK as DChunk)) as Chunk;
+        let top=(prod>>rom::BASEBITS) as Chunk;   
+        return (top,bot);     
+    }
+
+#[cfg(target_pointer_width = "64")]
+    pub fn pexceed(a: &BIG,b: &BIG) -> bool {
+        let ea=BIG::excess(a);
+        let eb=BIG::excess(b);        
+        if (ea+1) > rom::FEXCESS/(eb+1) {return true}
+        return false
+    }
+
+#[cfg(target_pointer_width = "64")]
+    pub fn sexceed(a: &BIG) -> bool {
+        let ea=BIG::excess(a);
+        if (ea+1) > rom::FEXCESS/(ea+1) {return true}
+        return false
+    }
+
+#[cfg(target_pointer_width = "64")]
+    pub fn ff_pexceed(a: &BIG,b: &BIG) -> bool {
+        let ea=BIG::ff_excess(a);
+        let eb=BIG::ff_excess(b);
+        if (ea+1) > rom::P_FEXCESS/(eb+1) {return true}
+        return false;
+    }
+
+#[cfg(target_pointer_width = "64")]
+    pub fn ff_sexceed(a: &BIG) -> bool {
+        let ea=BIG::ff_excess(a);
+        if (ea+1) > rom::P_FEXCESS/(ea+1) {return true}
+        return false;
+    }    
+
+#[cfg(target_pointer_width = "64")]
+    pub fn muladd(a: Chunk,b: Chunk,c: Chunk,r: Chunk) -> (Chunk,Chunk) {
+        let x0=a&rom::HMASK;
+        let x1=a>>rom::HBITS;
+        let y0=b&rom::HMASK;
+        let y1=b>>rom::HBITS;
+        let mut bot=x0*y0;
+        let mut top=x1*y1;
+        let mid=x0*y1+x1*y0;
+        let u0=mid&rom::HMASK;
+        let u1=mid>>rom::HBITS;
+        bot+= u0 <<rom::HBITS;
+        bot+=c; bot+=r;
+        top+=u1;
+        let carry=bot>>rom::BASEBITS;
+        bot&=rom::BMASK;
+        top+=carry;
+        return (top,bot);
+    }
+
+/* 
+alise BIG - force all digits < 2^rom::BASEBITS */
+    pub fn norm(&mut self) -> Chunk
+    {
+        let mut carry=0 as Chunk;
+        for i in 0 ..rom::NLEN-1 {
+            let d=self.w[i]+carry;
+            self.w[i]=d&rom::BMASK;
+            carry=d>>rom::BASEBITS;
+        }
+        self.w[rom::NLEN-1]+=carry;
+        return (self.w[rom::NLEN-1]>>((8*rom::MODBYTES)%rom::BASEBITS)) as Chunk;
+    }
+
+/* Conditional swap of two bigs depending on d using XOR - no branches */
+	pub fn cswap(&mut self,b: &mut BIG,d: isize) {
+		let mut c= d as Chunk;
+		c=!(c-1);
+		for i in 0 ..rom::NLEN {
+			let t=c&(self.w[i]^b.w[i]);
+			self.w[i]^=t;
+			b.w[i]^=t;
+		}
+	}
+
+	pub fn cmove(&mut self,g:&BIG,d: isize) {
+		let b= -d as Chunk;
+		for i in 0 ..rom::NLEN {
+			self.w[i]^=(self.w[i]^g.w[i])&b;
+		}
+	}
+
+/* Shift right by less than a word */
+	pub fn fshr(&mut self, k: usize) -> isize {
+		let n = k;
+		let w=self.w[0]&((1<<n)-1); /* shifted out part */
+		for i in 0 ..rom::NLEN-1 {
+			self.w[i]=(self.w[i]>>k)|((self.w[i+1]<<(rom::BASEBITS-n))&rom::BMASK);
+		}
+		self.w[rom::NLEN-1]=self.w[rom::NLEN-1]>>k;
+		return w as isize;
+	}
+
+ /* general shift right */
+	pub fn shr(&mut self,k:usize) {
+		let n=k%rom::BASEBITS;
+		let m=k/rom::BASEBITS;
+		for i in 0 ..rom::NLEN-m-1 {
+			self.w[i]=(self.w[m+i]>>n)|((self.w[m+i+1]<<(rom::BASEBITS-n))&rom::BMASK)
+		}
+		self.w[rom::NLEN-m-1]=self.w[rom::NLEN-1]>>n;
+		for i in rom::NLEN-m ..rom::NLEN 
+			{self.w[i]=0}
+	}	
+
+/* Shift right by less than a word */
+	pub fn fshl(&mut self,k:usize) -> isize {
+		let n=k;
+		self.w[rom::NLEN-1]=((self.w[rom::NLEN-1]<<n))|(self.w[rom::NLEN-2]>>(rom::BASEBITS-n));
+		for i in (1 ..rom::NLEN-1).rev() {
+			self.w[i]=((self.w[i]<<k)&rom::BMASK)|(self.w[i-1]>>(rom::BASEBITS-n));
+		}
+		self.w[0]=(self.w[0]<<n)&rom::BMASK;
+		return (self.w[rom::NLEN-1]>>((8*rom::MODBYTES)%rom::BASEBITS)) as isize /* return excess - only used in ff.c */
+	}
+
+/* general shift left */
+	pub fn shl(&mut self,k: usize) {
+		let n=k%rom::BASEBITS;
+		let m=k/rom::BASEBITS;
+
+		self.w[rom::NLEN-1]=self.w[rom::NLEN-1-m]<<n;
+		if rom::NLEN>=m+2 {self.w[rom::NLEN-1]|=self.w[rom::NLEN-m-2]>>(rom::BASEBITS-n)}
+		for i in (m+1 ..rom::NLEN-1).rev() {
+			self.w[i]=((self.w[i-m]<<n)&rom::BMASK)|(self.w[i-m-1]>>(rom::BASEBITS-n));
+		}
+		self.w[m]=(self.w[0]<<n)&rom::BMASK; 
+		for i in 0 ..m {self.w[i]=0}
+	}
+
+/* return number of bits */
+	pub fn nbits(&mut self) -> usize {
+		let mut k=rom::NLEN-1;
+		self.norm();
+		while (k as isize)>=0 && self.w[k]==0 {k=k.wrapping_sub(1)}
+		if (k as isize) <0 {return 0}
+		let mut bts=rom::BASEBITS*k;
+		let mut c=self.w[k];
+		while c!=0 {c/=2; bts+=1;}
+		return bts;
+	}
+
+/* Convert to Hex String */
+	pub fn tostring(&mut self) -> String {
+		let mut s = String::new();
+		let mut len=self.nbits();
+
+		if len%4==0 {
+			len/=4;
+		} else {
+			len/=4;
+			len+=1;
+		}
+		let mb=(rom::MODBYTES*2) as usize;
+		if len<mb {len=mb}
+
+		for i in (0 ..len).rev() {
+			let mut b=BIG::new_copy(&self);
+			b.shr(i*4);
+			s=s + &format!("{:X}", b.w[0]&15);
+		}
+		return s;
+	}	
+
+    pub fn add(&mut self,r:&BIG) {
+		for i in 0 ..rom::NLEN {
+			self.w[i]+=r.w[i] 
+		}
+	}
+
+    pub fn dbl(&mut self) {
+        for i in 0 ..rom::NLEN {
+            self.w[i]+=self.w[i]
+        }        
+    }
+
+/* return this+x */
+	pub fn plus(&self,x: &BIG) -> BIG {
+		let mut s=BIG::new();
+		for i in 0 ..rom::NLEN {
+			s.w[i]=self.w[i]+x.w[i];
+		}
+		return s;
+	}
+
+    pub fn inc(&mut self,x:isize) {
+    	self.norm();
+    	self.w[0]+=x as Chunk; 
+    }
+
+//    pub fn incl(&mut self,x:Chunk) {
+//        self.norm();
+//        self.w[0]+=x; 
+//    }
+
+/* return self-x */
+	pub fn minus(&self,x:& BIG) -> BIG {
+		let mut d=BIG::new();
+		for i in 0 ..rom::NLEN {
+			d.w[i]=self.w[i]-x.w[i];
+		}
+		return d;
+	}
+
+/* self-=x */
+	pub fn sub(&mut self,x:&BIG) {
+		for i in 0 ..rom::NLEN {
+			self.w[i]-=x.w[i]; 
+		}
+	} 
+
+/* reverse subtract this=x-this */ 
+	pub fn rsub(&mut self,x:&BIG) {
+		for i in 0 ..rom::NLEN {
+			self.w[i]=x.w[i]-self.w[i] 
+		}
+	} 
+
+/* self-=x, where x is int */
+	pub fn dec(&mut self,x:isize) {
+		self.norm();
+		self.w[0]-= x as Chunk;
+	} 
+
+/* self*=x, where x is small int<NEXCESS */
+	pub fn imul(&mut self,c: isize) {
+		for i in 0 ..rom::NLEN { 
+			self.w[i]*=c as Chunk;
+		}
+	}
+
+/* convert this BIG to byte array */
+	pub fn tobytearray(&mut self,b: &mut [u8],n:usize) {
+		self.norm();
+		let mut c=BIG::new_copy(self);
+
+		for i in (0 ..(rom::MODBYTES as usize)).rev() {
+			b[i+n]=(c.w[0]&0xff) as u8;
+			c.fshr(8);
+		}
+	}
+
+/* convert from byte array to BIG */
+	pub fn frombytearray(b: &[u8],n:usize) -> BIG {
+		let mut m=BIG::new();
+		for i in 0 ..(rom::MODBYTES as usize) {
+			m.fshl(8); m.w[0]+=(b[i+n]&0xff) as Chunk;
+		}
+		return m; 
+	}
+
+	pub fn tobytes(&mut self,b: &mut [u8]) {
+		self.tobytearray(b,0)
+	}
+
+	pub fn frombytes(b: &[u8]) -> BIG {
+		return BIG::frombytearray(b,0)
+	}
+
+    pub fn to_hex(&self) -> String {
+        let mut ret: String = String::with_capacity(NLEN * 16 + NLEN - 1);
+
+        for i in 0..NLEN {
+            if i == NLEN-1 {
+                ret.push_str(&format!("{:X}", self.w[i]));
+            } else {
+                ret.push_str(&format!("{:X} ", self.w[i]));
+            }
+        }
+        return ret;
+    }
+
+    pub fn from_hex_iter(iter: &mut SplitWhitespace) -> BIG {
+        let mut ret:BIG = BIG::new();
+        for i in 0..NLEN {
+            let v = iter.next();
+            match v {
+                Some(x) => {
+                    ret.w[i] = u64::from_str_radix(x, 16).unwrap() as Chunk;
+                },
+                None => {
+                    break;
+                }
+            }
+        }
+        return ret;
+    }
+
+    pub fn from_hex(val: String) -> BIG {
+        let mut iter = val.split_whitespace();
+        return BIG::from_hex_iter(&mut iter);
+    }
+
+/* self*=x, where x is >NEXCESS */
+    pub fn pmul(&mut self,c: isize) -> Chunk {
+        let mut carry=0 as Chunk;
+        self.norm();
+        for i in 0 ..rom::NLEN {
+            let ak=self.w[i];
+            let tuple=BIG::muladd(ak,c as Chunk,carry,0 as Chunk);
+            carry=tuple.0; self.w[i]=tuple.1;
+        }
+        return carry;
+    }  
+
+/* self*=c and catch overflow in DBIG */
+    pub fn pxmul(&mut self,c: isize) -> DBIG
+    {
+        let mut m=DBIG::new();
+        let mut carry=0 as Chunk;
+        for j in 0 ..rom::NLEN {
+            let tuple=BIG::muladd(self.w[j],c as Chunk,carry,m.w[j]);
+            carry=tuple.0; m.w[j]=tuple.1; 
+        }
+        m.w[rom::NLEN]=carry;
+        return m;
+    }
+
+/* divide by 3 */
+    pub fn div3(&mut self) -> Chunk
+    {
+        let mut carry=0 as Chunk;
+        self.norm();
+        let base=1<<rom::BASEBITS;
+        for i in (0 ..rom::NLEN).rev() {
+            let ak=carry*base+self.w[i];
+            self.w[i]=ak/3;
+            carry=ak%3;
+        }
+        return carry;
+    }
+
+/* return a*b where result fits in a BIG */
+    pub fn smul(a: &BIG,b: &BIG) -> BIG {
+        let mut c=BIG::new();
+        for i in 0 ..rom::NLEN {
+            let mut carry=0 as Chunk; 
+            for j in 0 ..rom::NLEN {
+                if i+j<rom::NLEN {
+                    let tuple=BIG::muladd(a.w[i],b.w[j],carry,c.w[i+j]);
+                    carry=tuple.0; c.w[i+j]=tuple.1;
+                }
+            }
+        }
+        return c;
+    }
+
+/* Compare a and b, return 0 if a==b, -1 if a<b, +1 if a>b. Inputs must be normalised */
+    pub fn comp(a: &BIG,b: &BIG) -> isize {
+        for i in (0 ..rom::NLEN).rev() {
+            if a.w[i]==b.w[i] {continue}
+            if a.w[i]>b.w[i] {return 1}
+            else  {return -1}
+        }
+        return 0;
+    }
+
+/* set x = x mod 2^m */
+    pub fn mod2m(&mut self,m: usize)
+    {
+        let wd=m/rom::BASEBITS;
+        let bt=m%rom::BASEBITS;
+        let msk=(1<<bt)-1;
+        self.w[wd]&=msk;
+        for i in wd+1 ..rom::NLEN {self.w[i]=0}
+    }
+
+/* Arazi and Qi inversion mod 256 */
+    pub fn invmod256(a: isize) -> isize {
+        let mut t1:isize=0;
+        let mut c=(a>>1)&1;
+        t1+=c;
+        t1&=1;
+        t1=2-t1;
+        t1<<=1;
+        let mut u=t1+1;
+    
+    // i=2
+        let mut b=a&3;
+        t1=u*b; t1>>=2;
+        c=(a>>2)&3;
+        let mut t2=(u*c)&3;
+        t1+=t2;
+        t1*=u; t1&=3;
+        t1=4-t1;
+        t1<<=2;
+        u+=t1;
+    
+    // i=4
+        b=a&15;
+        t1=u*b; t1>>=4;
+        c=(a>>4)&15;
+        t2=(u*c)&15;
+        t1+=t2;
+        t1*=u; t1&=15;
+        t1=16-t1;
+        t1<<=4;
+        u+=t1;
+    
+        return u;
+    }
+
+/* return parity */
+    pub fn parity(&self) -> isize {
+        return (self.w[0]%2) as isize;
+    }
+
+/* return n-th bit */
+    pub fn bit(&self,n: usize) -> isize {
+        if (self.w[n/(rom::BASEBITS as usize)]&(1<<(n%rom::BASEBITS)))>0 {return 1;}
+        else {return 0;}
+    }
+
+/* return n last bits */
+    pub fn lastbits(&mut self,n: usize) -> isize
+    {
+        let msk =  ((1<<n)-1) as Chunk; 
+        self.norm();
+        return (self.w[0]&msk) as isize;
+    }
+
+/* a=1/a mod 2^256. This is very fast! */
+    pub fn invmod2m(&mut self) {
+        let mut u=BIG::new();
+        let mut b=BIG::new();
+        let mut c=BIG::new();
+    
+        u.inc(BIG::invmod256(self.lastbits(8)));
+    
+        let mut i=8;
+        while i<rom::BIGBITS {
+            b.copy(self);
+            b.mod2m(i);
+            let mut t1=BIG::smul(&u,&b);
+            t1.shr(i);
+            c.copy(self);
+            c.shr(i);
+            c.mod2m(i);
+    
+            let mut t2=BIG::smul(&u,&c);
+            t2.mod2m(i);
+            t1.add(&t2);
+            b=BIG::smul(&t1,&u);
+            t1.copy(&b);
+            t1.mod2m(i);
+    
+            t2.one(); t2.shl(i); t1.rsub(&t2); t1.norm();
+            t1.shl(i);
+            u.add(&t1);
+            i<<=1;
+        }
+        u.mod2m(rom::BIGBITS);
+        self.copy(&u);
+        self.norm();
+    }
+
+/* reduce self mod m */
+    pub fn rmod(&mut self,n: &BIG) {
+        let mut k=0;
+        let mut m=BIG::new_copy(n);
+	    let mut r=BIG::new();
+        self.norm();
+        if BIG::comp(self,&m)<0 {return}
+        loop {
+            m.fshl(1);
+            k += 1;
+            if BIG::comp(self,&m)<0 {break}
+        }
+    
+        while k>0 {
+            m.fshr(1);
+
+		r.copy(self);
+		r.sub(&m);
+		r.norm();
+		self.cmove(&r,(1-((r.w[rom::NLEN-1]>>(rom::CHUNK-1))&1)) as isize);
+/*
+            if BIG::comp(self,&m)>=0 {
+				self.sub(&m);
+				self.norm();
+            } */
+            k -= 1;
+        }
+    }
+
+/* divide self by m */
+    pub fn div(&mut self,n: &BIG) {
+        let mut k=0;
+        self.norm();
+        let mut e=BIG::new_int(1);
+        let mut b=BIG::new_copy(self);
+        let mut m=BIG::new_copy(n);
+        let mut r=BIG::new();
+        self.zero();
+    
+        while BIG::comp(&b,&m)>=0 {
+            e.fshl(1);
+            m.fshl(1);
+            k += 1;
+        }
+    
+        while k>0 {
+            m.fshr(1);
+            e.fshr(1);
+
+		r.copy(&b);
+		r.sub(&m);
+		r.norm();
+		let d=(1-((r.w[rom::NLEN-1]>>(rom::CHUNK-1))&1)) as isize;
+		b.cmove(&r,d);
+		r.copy(self);
+		r.add(&e);
+		r.norm();
+		self.cmove(&r,d);
+/*
+            if BIG::comp(&b,&m)>=0 {
+				self.add(&e);
+				self.norm();
+				b.sub(&m);
+				b.norm();
+            } */
+            k -= 1;
+        }
+    }
+
+/* get 8*MODBYTES size random number */
+    pub fn random(rng: &mut RAND) -> BIG {
+        let mut m=BIG::new();
+        let mut j=0;
+        let mut r:u8=0;
+/* generate random BIG */ 
+        for _ in 0..8*(rom::MODBYTES as usize)  {
+            if j==0 {
+                r=rng.getbyte()
+            } else {r>>=1}
+
+            let b= (r as Chunk)&1; 
+            m.shl(1); m.w[0]+=b;// m.inc(b)
+            j+=1; j&=7; 
+        }
+        return m;
+    }
+
+/* Create random BIG in portable way, one bit at a time */
+    pub fn randomnum(q: &BIG,rng: &mut RAND) -> BIG {
+        let mut d=DBIG::new();
+        let mut j=0;
+        let mut r:u8=0;
+        for _ in 0..2*(rom::MODBITS as usize) {
+            if j==0 {
+                r=rng.getbyte();
+            } else {r>>=1}
+
+            let b= (r as Chunk)&1;
+            d.shl(1); d.w[0]+=b; // m.inc(b);
+            j+=1; j&=7; 
+        }
+        let m=d.dmod(q);
+        return m;
+    }
+
+
+   /* Jacobi Symbol (this/p). Returns 0, 1 or -1 */
+    pub fn jacobi(&mut self,p: &BIG) -> isize {
+        let mut m:usize=0;
+        let mut t=BIG::new();
+        let mut x=BIG::new();
+        let mut n=BIG::new();
+        let zilch=BIG::new();
+        let one=BIG::new_int(1);
+        if p.parity()==0 || BIG::comp(self,&zilch)==0 || BIG::comp(p,&one)<=0 {return 0}
+        self.norm();
+
+        x.copy(self);
+        n.copy(p);
+        x.rmod(p);
+
+        while BIG::comp(&n,&one)>0 {
+            if BIG::comp(&x,&zilch)==0 {return 0}
+            let n8=n.lastbits(3) as usize;
+            let mut k=0;
+            while x.parity()==0 {
+				k += 1;
+				x.shr(1);
+            }
+            if k%2==1 {m+=(n8*n8-1)/8}
+            m+=(n8-1)*((x.lastbits(2) as usize)-1)/4;
+            t.copy(&n);
+            t.rmod(&x);
+            n.copy(&x);
+            x.copy(&t);
+            m%=2;
+    
+        }
+        if m==0 {return 1}
+        else {return -1}
+    }
+
+/* self=1/self mod p. Binary method */
+    pub fn invmodp(&mut self,p: &BIG) {
+        self.rmod(p);
+        let mut u=BIG::new_copy(self);
+        let mut v=BIG::new_copy(p);
+        let mut x1=BIG::new_int(1);
+        let mut x2=BIG::new();
+        let mut t=BIG::new();
+        let one=BIG::new_int(1);
+    
+        while (BIG::comp(&u,&one) != 0 ) && (BIG::comp(&v,&one) != 0 ) {
+            while u.parity()==0 {
+				u.shr(1);
+				if x1.parity() != 0 {
+                    x1.add(p);
+                    x1.norm();
+				}
+				x1.shr(1);
+            }
+            while v.parity()==0 {
+				v.shr(1);
+				if x2.parity() != 0  {
+                    x2.add(p);
+                    x2.norm();
+				}
+				x2.shr(1);
+            }
+            if BIG::comp(&u,&v)>=0 {
+				u.sub(&v);
+				u.norm();
+                if BIG::comp(&x1,&x2)>=0 {x1.sub(&x2)}
+				else
+				{
+                    t.copy(p);
+                    t.sub(&x2);
+                    x1.add(&t);
+				}
+				x1.norm();
+            }
+            else
+            {
+				v.sub(&u);
+				v.norm();
+                if BIG::comp(&x2,&x1)>=0 {x2.sub(&x1)}
+				else
+				{
+                    t.copy(p);
+                    t.sub(&x1);
+                    x2.add(&t);
+				}
+				x2.norm();
+            }
+        }
+        if BIG::comp(&u,&one)==0 {self.copy(&x1)}
+        else {self.copy(&x2)}
+    }
+
+   /* return a*b as DBIG */
+#[cfg(target_pointer_width = "32")]
+    pub fn mul(a: &BIG,b: &BIG) -> DBIG {
+        let mut c=DBIG::new();
+        let rm=rom::BMASK as DChunk;
+        let rb=rom::BASEBITS;
+     //   a.norm();
+     //   b.norm();
+
+        let mut d: [DChunk; rom::DNLEN] = [0; rom::DNLEN];
+        for i in 0 ..rom::NLEN {
+            d[i]=(a.w[i] as DChunk)*(b.w[i] as DChunk);
+        }
+        let mut s=d[0];
+        let mut t=s; c.w[0]=(t&rm) as Chunk; 
+        let mut co=t>>rb;
+        for k in 1 ..rom::NLEN {
+            s+=d[k]; t=co+s;
+            for i in 1+k/2..k+1
+                {t+=((a.w[i]-a.w[k-i]) as DChunk)*((b.w[k-i]-b.w[i]) as DChunk)}
+            c.w[k]=(t&rm) as Chunk; co=t>>rb;
+        }
+        for k in rom::NLEN ..2*rom::NLEN-1 {
+            s-=d[k-rom::NLEN]; t=co+s;
+            let mut i=1+k/2;
+            while i<rom::NLEN {
+                t+=((a.w[i]-a.w[k-i]) as DChunk)*((b.w[k-i]-b.w[i]) as DChunk);
+                i+=1;
+            }
+        
+            c.w[k]=(t&rm) as Chunk; co=t>>rb;
+        }
+        c.w[2*rom::NLEN-1]=co as Chunk;
+        return c;
+    }
+
+/* return a^2 as DBIG */
+#[cfg(target_pointer_width = "32")]
+    pub fn sqr(a: &BIG) -> DBIG {
+        let mut c=DBIG::new();
+        let rm=rom::BMASK as DChunk;
+        let rb=rom::BASEBITS;
+    //    a.norm();
+ 
+        let mut t=(a.w[0] as DChunk)*(a.w[0] as DChunk);
+        c.w[0]=(t&rm) as Chunk; let mut co=t>>rb;
+        t=(a.w[1] as DChunk)*(a.w[0] as DChunk); t+=t; t+=co;
+        c.w[1]=(t&rm) as Chunk; co=t>>rb;
+        
+        let last=rom::NLEN-(rom::NLEN%2);
+        let mut j=2;
+        while j<last {
+            t=(a.w[j] as DChunk)*(a.w[0] as DChunk); for i in 1 ..(j+1)/2 {t+=(a.w[j-i] as DChunk)*(a.w[i] as DChunk)} ; t+=t; t+=co; t+=(a.w[j/2] as DChunk)*(a.w[j/2] as DChunk);
+            c.w[j]=(t&rm) as Chunk; co=t>>rb;
+            t=(a.w[j+1] as DChunk)*(a.w[0] as DChunk); for i in 1 ..(j+2)/2 {t+=(a.w[j+1-i] as DChunk)*(a.w[i] as DChunk)} ; t+=t; t+=co;
+            c.w[j+1]=(t&rm) as Chunk; co=t>>rb;
+            j+=2;
+        }
+        j=last;
+        if rom::NLEN%2==1 {
+            t=(a.w[j] as DChunk)*(a.w[0] as DChunk); for i in 1 ..(j+1)/2 {t+=(a.w[j-i] as DChunk)*(a.w[i] as DChunk)} ; t+=t; t+=co; t+=(a.w[j/2] as DChunk)*(a.w[j/2] as DChunk);
+            c.w[j]=(t&rm) as Chunk; co=t>>rb; j += 1;
+            t=(a.w[rom::NLEN-1] as DChunk)*(a.w[j-rom::NLEN+1] as DChunk); for i in j-rom::NLEN+2 ..(j+1)/2 {t+=(a.w[j-i] as DChunk)*(a.w[i] as DChunk)}; t+=t; t+=co;
+            c.w[j]=(t&rm) as Chunk; co=t>>rb; j += 1;
+        }
+        while j<rom::DNLEN-2 {
+            t=(a.w[rom::NLEN-1] as DChunk)*(a.w[j-rom::NLEN+1] as DChunk); for i in j-rom::NLEN+2 ..(j+1)/2 {t+=(a.w[j-i] as DChunk)*(a.w[i] as DChunk)} ; t+=t; t+=co; t+=(a.w[j/2] as DChunk)*(a.w[j/2] as DChunk);
+            c.w[j]=(t&rm) as Chunk; co=t>>rb;
+            t=(a.w[rom::NLEN-1] as DChunk)*(a.w[j-rom::NLEN+2] as DChunk); for i in j-rom::NLEN+3 ..(j+2)/2 {t+=(a.w[j+1-i] as DChunk)*(a.w[i] as DChunk)} ; t+=t; t+=co;
+            c.w[j+1]=(t&rm) as Chunk; co=t>>rb;
+            j+=2;
+        }
+        t=(a.w[rom::NLEN-1] as DChunk)*(a.w[rom::NLEN-1] as DChunk)+co;
+        c.w[rom::DNLEN-2]=(t&rm) as Chunk; co=t>>rb;
+        c.w[rom::DNLEN-1]=co as Chunk;
+        
+        return c;
+    }
+
+
+#[cfg(target_pointer_width = "32")]
+    fn monty(d: &mut DBIG) -> BIG {
+        let mut b=BIG::new();           
+        let md=BIG::new_ints(&rom::MODULUS);
+        let rm=rom::BMASK as DChunk;
+        let rb=rom::BASEBITS;
+
+        let mut dd: [DChunk; rom::NLEN] = [0; rom::NLEN];
+        let mut v: [Chunk; rom::NLEN] = [0; rom::NLEN];
+            
+        b.zero();
+            
+        let mut t=d.w[0] as DChunk; v[0]=(((t&rm) as Chunk).wrapping_mul(rom::MCONST))&rom::BMASK; t+=(v[0] as DChunk)*(md.w[0] as DChunk); let mut c=(d.w[1] as DChunk)+(t>>rb); let mut s:DChunk=0;
+        for k in 1 ..rom::NLEN {
+            t=c+s+(v[0] as DChunk)*(md.w[k] as DChunk);
+            let mut i=1+k/2;
+            while i<k {
+                t+=((v[k-i]-v[i]) as DChunk)*((md.w[i]-md.w[k-i]) as DChunk);
+                i+=1;
+            }
+            v[k]=(((t&rm) as Chunk).wrapping_mul(rom::MCONST))&rom::BMASK; t+=(v[k] as DChunk)*(md.w[0] as DChunk); c=(d.w[k+1] as DChunk)+(t>>rb);
+            dd[k]=(v[k] as DChunk)*(md.w[k] as DChunk); s+=dd[k];
+        }
+            
+        for k in rom::NLEN ..2*rom::NLEN-1
+        {
+            t=c+s;
+            let mut i=1+k/2;
+            while i<rom::NLEN {
+                t+=((v[k-i]-v[i]) as DChunk)*((md.w[i]-md.w[k-i]) as DChunk);
+                i+=1;
+            }
+            b.w[k-rom::NLEN]=(t&rm) as Chunk; c=(d.w[k+1] as DChunk)+(t>>rb); s-=dd[k-rom::NLEN+1];
+        }
+        b.w[rom::NLEN-1]=(c&rm) as Chunk;  
+        b.norm();
+        return b;
+    }
+    
+
+
+/* return a*b as DBIG */
+#[cfg(target_pointer_width = "64")]
+    pub fn mul(a: &BIG,b: &BIG) -> DBIG {
+        let mut c=DBIG::new();
+        let mut carry;
+
+        for i in 0 ..rom::NLEN {
+            carry=0;
+            for j in 0 ..rom::NLEN {
+                let tuple=BIG::muladd(a.w[i],b.w[j],carry,c.w[i+j]);
+                carry=tuple.0; c.w[i+j]=tuple.1;
+            }
+            c.w[rom::NLEN+i]=carry;
+        }
+        return c;
+    } 
+
+/* return a^2 as DBIG */
+#[cfg(target_pointer_width = "64")]
+    pub fn sqr(a: &BIG) -> DBIG {
+        let mut c=DBIG::new();
+        let mut carry;
+
+        for i in 0 ..rom::NLEN {
+            carry=0;
+            for j in i+1 ..rom::NLEN {
+                let tuple=BIG::muladd(2*a.w[i],a.w[j],carry,c.w[i+j]);
+                carry=tuple.0; c.w[i+j]=tuple.1;
+            //carry,c.w[i+j]=muladd(2*a.w[i],a.w[j],carry,c.w[i+j])
+            //carry=c.muladd(2*a.w[i],a.w[j],carry,i+j)
+            }
+            c.w[rom::NLEN+i]=carry;
+        }
+
+        for i in 0 ..rom::NLEN {
+            let tuple=BIG::muladd(a.w[i],a.w[i],0,c.w[2*i]);
+            c.w[2*i]=tuple.1;
+            c.w[2*i+1]+=tuple.0;
+        //c.w[2*i+1]+=c.muladd(a.w[i],a.w[i],0,2*i)
+        }
+        c.norm();
+        return c;
+    } 
+
+#[cfg(target_pointer_width = "64")]
+    fn monty(d: &mut DBIG) -> BIG {
+        let mut b=BIG::new();     
+        let md=BIG::new_ints(&rom::MODULUS);
+        let mut carry;
+        let mut m;
+        for i in 0 ..rom::NLEN {
+            if rom::MCONST==-1 { 
+                m=(-d.w[i])&rom::BMASK;
+            } else {
+                if rom::MCONST==1 {
+                    m=d.w[i];
+                } else {
+                    m=(rom::MCONST.wrapping_mul(d.w[i]))&rom::BMASK;
+                }
+            }
+
+            carry=0;
+            for j in 0 ..rom::NLEN {
+                let tuple=BIG::muladd(m,md.w[j],carry,d.w[i+j]);
+                carry=tuple.0; d.w[i+j]=tuple.1;
+            }
+            d.w[rom::NLEN+i]+=carry;
+        }
+
+        for i in 0 ..rom::NLEN {
+            b.w[i]=d.w[rom::NLEN+i];
+        } 
+        b.norm();
+        return b;  
+    }
+
+
+/* reduce a DBIG to a BIG using the appropriate form of the modulus */
+/* dd */
+    pub fn modulo(d: &mut DBIG) -> BIG {
+    
+        if rom::MODTYPE==rom::PSEUDO_MERSENNE {
+            let mut b=BIG::new();
+            let mut t=d.split(rom::MODBITS);
+            b.dcopy(&d);
+            let v=t.pmul(rom::MCONST as isize);
+            let tw=t.w[rom::NLEN-1];
+            t.w[rom::NLEN-1] &= rom::TMASK;
+            t.w[0]+=rom::MCONST*((tw>>rom::TBITS)+(v<<(rom::BASEBITS-rom::TBITS)));
+    
+            b.add(&t);
+            b.norm();
+            return b;
+        }
+    
+        if rom::MODTYPE==rom::MONTGOMERY_FRIENDLY
+        {
+            let mut b=BIG::new();
+            for i in 0 ..rom::NLEN {
+                let x=d.w[i];
+
+                let tuple=BIG::muladd(x,rom::MCONST-1,x,d.w[rom::NLEN+i-1]);
+                d.w[rom::NLEN+i]+=tuple.0; d.w[rom::NLEN+i-1]=tuple.1;
+            }
+    
+            b.zero();
+    
+            for i in 0 ..rom::NLEN {
+                b.w[i]=d.w[rom::NLEN+i];
+            }
+            b.norm();
+            return b;
+        }
+            
+        if rom::MODTYPE==rom::GENERALISED_MERSENNE
+        { // GoldiLocks Only
+            let mut b=BIG::new();            
+            let t=d.split(rom::MODBITS);
+            let rm2=(rom::MODBITS/2) as usize;
+            b.dcopy(&d);
+            b.add(&t);
+            let mut dd=DBIG::new_scopy(&t);
+            dd.shl(rm2);
+            
+            let mut tt=dd.split(rom::MODBITS);
+            let lo=BIG::new_dcopy(&dd);
+            b.add(&tt);
+            b.add(&lo);
+            b.norm();
+            tt.shl(rm2);
+            b.add(&tt);
+            
+            let carry=b.w[rom::NLEN-1]>>rom::TBITS;
+            b.w[rom::NLEN-1]&=rom::TMASK;
+            b.w[0]+=carry;
+            
+            b.w[(224/rom::BASEBITS) as usize]+=carry<<(224%rom::BASEBITS);
+            b.norm();
+            return b;
+        }
+       
+        if rom::MODTYPE==rom::NOT_SPECIAL {
+            return BIG::monty(d);
+        }     
+        return BIG::new();
+    }
+
+    /* return a*b mod m */
+    pub fn modmul(a: &mut BIG,b: &mut BIG,m: &BIG) -> BIG {
+        a.rmod(m);
+        b.rmod(m);
+        let mut d=BIG::mul(a,b);
+        return d.dmod(m);
+    }
+    
+    /* return a^2 mod m */
+    pub fn modsqr(a: &mut BIG,m: &BIG) -> BIG {
+        a.rmod(m);
+        let mut d=BIG::sqr(a);
+        return d.dmod(m);
+    }
+    
+    /* return -a mod m */
+    pub fn modneg(a: &mut BIG,m: &BIG) -> BIG {
+        a.rmod(m);
+        return m.minus(a);
+    }
+
+    /* return this^e mod m */
+    pub fn powmod(&mut self,e: &mut BIG,m: &BIG) -> BIG {
+        self.norm();
+        e.norm();
+        let mut a=BIG::new_int(1);
+        let mut z=BIG::new_copy(e);
+        let mut s=BIG::new_copy(self);
+        loop {      
+            let bt=z.parity();       
+            z.fshr(1);    
+            if bt==1 {a=BIG::modmul(&mut a,&mut s,m)}
+            if z.iszilch() {break}
+            s=BIG::modsqr(&mut s,m);         
+        }
+        return a;
+    }
+
+}
+ 
+/*
+fn main() {
+	let fd: [i32; rom::NLEN as usize] = [1, 2, 3, 4, 5, 6, 7, 8, 9];	
+	let mut x= BIG::new();
+	x.inc(3);
+ 	println!("{}", x.w[0]);	
+ 	let mut y= BIG::new_int(7);
+ 	println!("{}", y.w[0]);	
+ 	y=BIG::new_copy(&x);
+	println!("{}", y.w[0]); 	
+	x.add(&y);
+	x.add(&y);
+	println!("{}", x.w[0]); 	
+	let mut z= BIG::new_ints(&fd);
+	println!("{}", z.w[0]); 	
+	z.shr(3);
+	z.norm();
+	println!("{:X}", z.w[0]); 	
+
+	println!("{}",z.tostring());
+
+    let mut a = BIG::new_int(3);
+    let mut m = BIG::new_ints(&MODULUS);
+
+    println!("rom::MODULUS= {}",m.tostring());
+
+    let mut e = BIG::new_copy(&m);
+    e.dec(1); e.norm();
+    println!("Exponent= {}",e.tostring());
+//    for i in 0..20
+//    {
+        a=a.powmod(&mut e,&mut m);
+//        a.inc(2);
+//    }
+    println!("Result= {}",a.tostring());
+
+}
+*/
diff --git a/version22/rust/src/dbig.rs b/version22/rust/src/dbig.rs
new file mode 100644
index 0000000..167cfaf
--- /dev/null
+++ b/version22/rust/src/dbig.rs
@@ -0,0 +1,249 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use rom;
+
+use rom::Chunk;
+
+//#[derive(Copy, Clone)]
+pub struct DBIG {
+ 	pub w: [Chunk; rom::DNLEN]
+}
+
+//mod big;
+use big::BIG;
+
+impl DBIG {
+   pub fn new() -> DBIG {
+        DBIG {
+        	w: [0; rom::DNLEN as usize]
+         }
+    }	
+
+    pub fn new_copy(y:&DBIG) -> DBIG {
+    	let mut s= DBIG::new();   
+    	for i in 0..rom::NLEN {s.w[i]=y.w[i]}
+    	return s;	
+    }
+
+    pub fn new_scopy(x:&BIG) -> DBIG {
+    	let mut b= DBIG::new();   
+		for i in 0 ..rom::NLEN {
+			b.w[i]=x.w[i];
+		}
+		b.w[rom::NLEN-1]=x.get(rom::NLEN-1)&rom::BMASK; /* top word normalized */
+		b.w[rom::NLEN]=x.get(rom::NLEN-1)>>rom::BASEBITS;
+
+		for i in rom::NLEN+1 ..rom::DNLEN {b.w[i]=0}
+    	return b; 	
+    }
+
+/* split DBIG at position n, return higher half, keep lower half */
+    pub fn split(&mut self,n: usize) -> BIG
+    {
+        let mut t=BIG::new();
+        let m=n%rom::BASEBITS;
+        let mut carry=self.w[rom::DNLEN-1]<<(rom::BASEBITS-m);
+    
+        for i in (rom::NLEN-1..rom::DNLEN-1).rev() {
+            let nw=(self.w[i]>>m)|carry;
+            carry= (self.w[i]<<(rom::BASEBITS-m))&rom::BMASK;
+            t.set(i-rom::NLEN+1,nw);
+        }
+        self.w[rom::NLEN-1]&=((1 as Chunk)<<m)-1;
+        return t;
+    }
+
+/* general shift left */
+    pub fn shl(&mut self,k: usize)
+    {
+        let n=k%rom::BASEBITS; 
+        let m=k/rom::BASEBITS; 
+        self.w[rom::DNLEN-1]=((self.w[rom::DNLEN-1-m]<<n))|(self.w[rom::DNLEN-m-2]>>(rom::BASEBITS-n));
+        for i in (m+1..rom::DNLEN-1).rev() {
+            self.w[i]=((self.w[i-m]<<n)&rom::BMASK)|(self.w[i-m-1]>>(rom::BASEBITS-n));
+        }
+  
+        self.w[m]=(self.w[0]<<n)&rom::BMASK;
+        for i in 0 ..m {self.w[i]=0}
+    }
+
+/* general shift right */
+    pub fn shr(&mut self,k: usize) {
+		let n=k%rom::BASEBITS;
+		let m=k/rom::BASEBITS;
+        for i in 0 ..rom::DNLEN-m-1 {
+            self.w[i]=(self.w[m+i]>>n)|((self.w[m+i+1]<<(rom::BASEBITS-n))&rom::BMASK);
+        }
+        self.w[rom::DNLEN-m-1]=self.w[rom::DNLEN-1]>>n;
+        for i in rom::DNLEN - m ..rom::DNLEN {self.w[i]=0}
+    }
+
+/* Copy from another DBIG */
+	pub fn copy(&mut self,x: &DBIG) {
+		for i in 0 ..rom::DNLEN {
+			self.w[i]=x.w[i]
+		}
+	}
+
+	pub fn cmove(&mut self,g:&DBIG,d: isize) {
+		let b=-d as Chunk;
+		for i in 0 ..rom::DNLEN {
+			self.w[i]^=(self.w[i]^g.w[i])&b;
+		}
+	}
+
+/* self-=x */
+	pub fn sub(&mut self,x:&DBIG) {
+		for i in 0 ..rom::DNLEN {
+			self.w[i]-=x.w[i]; 
+		}
+	} 
+
+/* Compare a and b, return 0 if a==b, -1 if a<b, +1 if a>b. Inputs must be normalised */
+    pub fn comp(a: &DBIG,b: &DBIG) -> isize {
+        for i in (0 ..rom::DNLEN).rev() {
+            if a.w[i]==b.w[i] {continue}
+            if a.w[i]>b.w[i] {return 1}
+            else  {return -1}
+        }
+        return 0;
+    }
+
+/* normalise BIG - force all digits < 2^rom::BASEBITS */
+    pub fn norm(&mut self) {
+        let mut carry=0 as Chunk;
+        for i in 0 ..rom::DNLEN-1 {
+            let d=self.w[i]+carry;
+            self.w[i]=d&rom::BMASK;
+            carry=d>>rom::BASEBITS;
+        }
+        self.w[rom::DNLEN-1]+=carry
+    }
+
+/* reduces self DBIG mod a BIG, and returns the BIG */
+    pub fn dmod(&mut self,c: &BIG) -> BIG {
+        let mut k=0;
+        self.norm();
+        let mut m=DBIG::new_scopy(c);
+        let mut dr=DBIG::new();
+    
+        if DBIG::comp(self,&m)<0 {
+        	let r=BIG::new_dcopy(self);
+        	return r;
+        }
+    
+        loop {
+            m.shl(1);
+            k += 1;
+            if DBIG::comp(self,&m)<0 {break;}
+        }
+    
+        while k>0 {
+            m.shr(1);
+
+		dr.copy(self);
+		dr.sub(&m);
+		dr.norm();
+		self.cmove(&dr,(1-((dr.w[rom::DNLEN-1]>>(rom::CHUNK-1))&1)) as isize);
+/*
+            if DBIG::comp(self,&m)>=0 {
+				self.sub(&m);
+				self.norm();
+            } */
+            k -= 1;
+        }
+        let r=BIG::new_dcopy(self);
+        return r;
+    }
+
+/* return this/c */
+    pub fn div(&mut self,c: &BIG) -> BIG {
+        let mut k=0;
+        let mut m=DBIG::new_scopy(c);
+        let mut a=BIG::new();
+        let mut e=BIG::new_int(1);
+	let mut dr=DBIG::new();
+	let mut r=BIG::new();
+        self.norm();
+
+        while DBIG::comp(self,&m)>=0 {
+            e.fshl(1);
+            m.shl(1);
+            k+=1;
+        }
+
+        while k>0 {
+            m.shr(1);
+            e.shr(1);
+
+		dr.copy(self);
+		dr.sub(&m);
+		dr.norm();
+		let d=(1-((dr.w[rom::DNLEN-1]>>(rom::CHUNK-1))&1)) as isize;
+		self.cmove(&dr,d);
+		r.copy(&a);
+		r.add(&e);
+		r.norm();
+		a.cmove(&r,d);
+/*
+            if DBIG::comp(self,&m)>0 {
+                a.add(&e);
+                a.norm();
+                self.sub(&m);
+                self.norm();
+            } */
+            k-=1;
+        }
+        return a;
+    }
+
+/* return number of bits */
+	pub fn nbits(&mut self) -> usize {
+		let mut k=rom::DNLEN-1;
+		self.norm();
+		while (k as isize)>=0 && self.w[k]==0 {k=k-1}
+		if (k as isize) <0 {return 0}
+		let mut bts=(rom::BASEBITS as usize)*k;
+		let mut c=self.w[k];
+		while c!=0 {c/=2; bts+=1;}
+		return bts;
+	}
+
+/* Convert to Hex String */
+	pub fn to_string(&mut self) -> String {
+		let mut s = String::new();
+		let mut len=self.nbits();
+
+		if len%4==0 {
+			len/=4;
+		} else {
+			len/=4;
+			len+=1;
+		}
+
+		for i in (0 ..len).rev() {
+			let mut b=DBIG::new_copy(&self);
+			b.shr(i*4);
+			s=s + &format!("{:X}", b.w[0]&15);
+		}
+		return s;
+	}	
+
+}
diff --git a/version22/rust/src/ecdh.rs b/version22/rust/src/ecdh.rs
new file mode 100644
index 0000000..1511140
--- /dev/null
+++ b/version22/rust/src/ecdh.rs
@@ -0,0 +1,585 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use ecp::ECP;
+use big::BIG;
+use rand::RAND;
+use hash256::HASH256;
+use hash384::HASH384;
+use hash512::HASH512;
+use aes;
+use aes::AES;
+use rom;
+
+
+pub const INVALID_PUBLIC_KEY:isize=-2;
+pub const ERROR:  isize=-3;
+pub const INVALID: isize=-4;
+pub const EFS: usize=rom::MODBYTES as usize;
+pub const EGS: usize=rom::MODBYTES as usize;
+pub const EAS: usize=16;
+pub const EBS: usize=16;
+pub const SHA256: usize=32;
+pub const SHA384: usize=48;
+pub const SHA512: usize=64;
+
+pub const HASH_TYPE: usize=SHA512;
+
+#[allow(non_snake_case)]
+
+fn inttobytes(n: usize,b:&mut [u8]) {
+	let mut i=b.len();
+	let mut m=n;
+	while m>0 && i>0 {
+		i-=1;
+		b[i]=(m&0xff) as u8;
+		m/=256;
+	}	
+}
+
+fn hashit(sha: usize, a: &[u8],n: usize,b: Option<&[u8]>,pad: usize,w: &mut [u8])  {
+	let mut r:[u8;64]=[0;64];
+	if sha==SHA256 {
+		let mut h=HASH256::new();
+		h.process_array(a);
+		if n>0 {h.process_num(n as i32)}
+		if let Some(x) = b {
+			h.process_array(x);
+        }
+        let hs=h.hash();	
+        for i in 0..sha {r[i]=hs[i];}	
+	}
+	if sha==SHA384 {
+		let mut h=HASH384::new();
+		h.process_array(a);
+		if n>0 {h.process_num(n as i32)}		
+		if let Some(x) = b {
+			h.process_array(x);
+        }
+        let hs=h.hash();	
+        for i in 0..sha {r[i]=hs[i];}	        
+	}
+	if sha==SHA512 {
+		let mut h=HASH512::new();
+		h.process_array(a);
+		if n>0 {h.process_num(n as i32)}
+		if let Some(x) = b {
+			h.process_array(x);
+        }
+        let hs=h.hash();
+        for i in 0..sha {r[i]=hs[i];}	        	
+	}
+
+	if pad==0 {
+		for i in 0..sha {w[i]=r[i]}
+	} else {
+
+		if pad<=sha {
+			for i in 0..pad {w[i]=r[i]}
+		} else {
+			for i in 0..sha {w[i]=r[i]}
+			for i in sha..pad {w[i]=0}
+		}
+	}
+}
+
+/* Key Derivation Functions */
+/* Input octet Z */
+/* Output key of length olen */
+pub fn kdf1(sha: usize,z: &[u8],olen: usize,k: &mut [u8])  {
+/* NOTE: the parameter olen is the length of the output K in bytes */
+	let hlen=sha;
+	let mut lk=0;
+
+	let mut cthreshold=olen/hlen; if olen%hlen!=0 {cthreshold+=1}
+
+	for counter in 0..cthreshold {
+		let mut b:[u8;64]=[0;64];
+		hashit(sha,z,counter,None,0,&mut b);
+		if lk+hlen>olen {
+			for i in 0..(olen%hlen) {k[lk]=b[i]; lk+=1}
+		} else {
+			for i in 0..hlen {k[lk]=b[i]; lk+=1}
+		}
+	}
+}
+
+pub fn kdf2(sha: usize,z: &[u8],p: Option<&[u8]>,olen: usize,k: &mut [u8])  {
+/* NOTE: the parameter olen is the length of the output K in bytes */
+	let hlen=sha;
+	let mut lk=0;
+
+	let mut cthreshold=olen/hlen; if olen%hlen!=0 {cthreshold+=1}
+
+	for counter in 1..cthreshold+1 {
+		let mut b:[u8;64]=[0;64];
+		hashit(sha,z,counter,p,0,&mut b);
+		if lk+hlen>olen {
+			for i in 0..(olen%hlen) {k[lk]=b[i]; lk+=1}
+		} else {
+			for i in 0..hlen {k[lk]=b[i]; lk+=1}
+		}
+	}
+}
+
+/* Password based Key Derivation Function */
+/* Input password p, salt s, and repeat count */
+/* Output key of length olen */
+pub fn pbkdf2(sha: usize,pass: &[u8],salt: &[u8],rep: usize,olen: usize,k: &mut [u8]) {
+	let mut d=olen/sha; if olen%sha!=0 {d+=1}
+	let mut f:[u8;64]=[0;64];
+	let mut u:[u8;64]=[0;64];
+	let mut ku:[u8;64]=[0;64];	
+	let mut s:[u8;36]=[0;36];    // Maximum salt of 32 bytes + 4
+	let mut n:[u8;4]=[0;4];
+
+	let sl=salt.len();
+	let mut kp=0;
+	for i in 0..d {
+		for j in 0..sl {s[j]=salt[j]} 
+		inttobytes(i+1,&mut n);
+		for j in 0..4 {s[sl+j]=n[j]}   
+
+		hmac(sha,&s[0..sl+4],pass,sha,&mut f);
+
+		for j in 0..sha {u[j]=f[j]}
+		for _ in 1..rep {
+			hmac(sha,&mut u,pass,sha,&mut ku);
+			for k in 0..sha {u[k]=ku[k]; f[k]^=u[k]}
+		}
+		for j in 0..EFS {if kp<olen {k[kp]=f[j]} kp+=1} 
+	}
+}
+
+/* Calculate HMAC of m using key k. HMAC is tag of length olen (which is length of tag) */
+pub fn hmac(sha: usize,m: &[u8],k: &[u8],olen: usize,tag: &mut [u8]) -> bool {
+	/* Input is from an octet m        *
+	* olen is requested output length in bytes. k is the key  *
+	* The output is the calculated tag */
+	let mut b:[u8;64]=[0;64];  /* Not good */
+	let mut k0:[u8;128]=[0;128];
+//	let olen=tag.len();    /* length of HMAC */
+
+	if olen<4 /*|| olen>sha */ {return false}
+
+	let mut lb=64;
+	if sha>32 {lb=128}
+
+	for i in 0..lb {k0[i]=0}
+
+	if k.len() > lb {
+		hashit(sha,k,0,None,0,&mut b); 
+		for i in 0..sha {k0[i]=b[i]}
+	} else {
+		for i in 0..k.len()  {k0[i]=k[i]}
+	}
+		
+	for i in 0..lb {k0[i]^=0x36}
+	hashit(sha,&mut k0[0..lb],0,Some(m),0,&mut b);
+
+	for i in 0..lb {k0[i]^=0x6a}
+	hashit(sha,&mut k0[0..lb],0,Some(&b[0..sha]),olen,tag); 
+
+	return true;
+}
+
+/* AES encryption/decryption. Encrypt byte array m using key k and returns ciphertext c */
+pub fn cbc_iv0_encrypt(k: &[u8],m: &[u8]) -> Vec<u8> { /* AES CBC encryption, with Null IV and key K */
+	/* Input is from an octet string m, output is to an octet string c */
+	/* Input is padded as necessary to make up a full final block */
+	let mut a=AES::new();	
+	let mut fin=false;
+	let mut c:Vec<u8>=Vec::new();
+
+	let mut buff:[u8;16]=[0;16];
+
+	a.init(aes::CBC,k.len(),k,None);
+
+	let mut ipt=0; 
+//	let mut opt=0;
+	let mut i;
+	loop {
+		i=0;
+		while i<16 {
+			if ipt<m.len() {
+				buff[i]=m[ipt]; i+=1; ipt+=1;
+			} else {fin=true; break;}
+		}
+		if fin {break}
+		a.encrypt(&mut buff);
+		for j in 0..16 {
+			c.push(buff[j]);
+			//c[opt]=buff[j]; opt+=1;
+		}
+	}    
+
+/* last block, filled up to i-th index */
+
+	let padlen=16-i;
+	for j in i..16 {buff[j]=padlen as u8}
+
+	a.encrypt(&mut buff);
+
+	for j in 0..16 {
+		c.push(buff[j]);
+		//c[opt]=buff[j]; opt+=1;
+	}
+	a.end();   
+	return c;
+}
+
+/* returns plaintext if all consistent, else returns null string */
+pub fn cbc_iv0_decrypt(k: &[u8],c: &[u8]) -> Option<Vec<u8>> { /* padding is removed */
+	let mut a=AES::new();	
+	let mut fin=false;
+	let mut m:Vec<u8>=Vec::new();
+
+	let mut buff:[u8;16]=[0;16];
+
+	a.init(aes::CBC,k.len(),k,None);
+
+	let mut ipt=0; 
+	//let mut opt=0;
+	let mut i;
+
+	if c.len()==0 {return None}
+	let mut ch=c[ipt]; ipt+=1;
+
+	loop {
+		i=0;
+		while i<16 {
+			buff[i]=ch;    
+			if ipt>=c.len() {
+				fin=true; break;
+			}  else {ch=c[ipt]; ipt+=1 }
+			i+=1;
+		}
+		a.decrypt(&mut buff);
+		if fin {break}
+		for j in 0..16 {
+			m.push(buff[j]);
+			//m[opt]=buff[j]; opt+=1;
+		}
+	}    
+
+	a.end();
+	let mut bad=false;
+	let padlen=buff[15] as usize;
+	if i!=15 || padlen<1 || padlen>16 {bad=true}
+	if padlen>=2 && padlen<=16 {
+		for j in 16-padlen..16 {
+			if buff[j]!=padlen as u8 {bad=true}
+		}
+	}
+    
+	if !bad { 
+		for _ in 0..16-padlen {
+			m.push(buff[i]);
+			//m[opt]=buff[j]; opt+=1;
+		}
+	}
+
+	if bad {return None}
+	return Some(m);
+}
+
+/* Calculate a public/private EC GF(p) key pair w,s where W=s.G mod EC(p),
+ * where s is the secret key and W is the public key
+ * and G is fixed generator.
+ * If RNG is NULL then the private key is provided externally in s
+ * otherwise it is generated randomly internally */
+ #[allow(non_snake_case)]
+pub fn key_pair_generate(rng: Option<&mut RAND>,s: &mut [u8],w: &mut [u8]) -> isize {
+	let res=0;
+	let mut sc:BIG;
+	let mut G:ECP;
+
+	let gx=BIG::new_ints(&rom::CURVE_GX);
+	
+	if rom::CURVETYPE!=rom::MONTGOMERY {
+		let gy=BIG::new_ints(&rom::CURVE_GY);
+		G=ECP::new_bigs(&gx,&gy);
+	} else {
+		G=ECP::new_big(&gx);
+	}
+
+	let r=BIG::new_ints(&rom::CURVE_ORDER);
+
+	if let Some(mut x)=rng {
+		sc=BIG::randomnum(&r,&mut x);
+	} else {
+		sc=BIG::frombytes(&s);
+		sc.rmod(&r);		
+	}
+
+	if rom::AES_S>0 {
+		sc.mod2m(2*rom::AES_S)
+	}
+	sc.tobytes(s);
+
+	let mut WP=G.mul(&mut sc);
+
+	WP.tobytes(w);
+
+	return res;
+}
+
+/* validate public key. Set full=true for fuller check */
+#[allow(non_snake_case)]
+pub fn public_key_validate(full: bool,w: &[u8]) -> isize {
+	let mut WP=ECP::frombytes(w);
+	let mut res=0;
+
+	let mut r=BIG::new_ints(&rom::CURVE_ORDER);
+
+	if WP.is_infinity() {res=INVALID_PUBLIC_KEY}
+	if res==0 && full {
+		WP=WP.mul(&mut r);
+		if !WP.is_infinity() {res=INVALID_PUBLIC_KEY} 
+	}
+	return res;
+}
+
+/* IEEE-1363 Diffie-Hellman online calculation Z=S.WD */
+#[allow(non_snake_case)]
+pub fn ecpsvdp_dh(s: &[u8],wd: &[u8],z: &mut [u8]) -> isize {
+	let mut res=0;
+	let mut t:[u8;EFS]=[0;EFS];
+
+	let mut sc=BIG::frombytes(&s);
+
+	let mut W=ECP::frombytes(&wd);
+	if W.is_infinity() {res=ERROR}
+
+	if res==0 {
+		let r=BIG::new_ints(&rom::CURVE_ORDER);
+		sc.rmod(&r);
+		W=W.mul(&mut sc);
+		if W.is_infinity() { 
+			res=ERROR;
+		} else {
+			W.getx().tobytes(&mut t);
+			for i in 0..EFS {z[i]=t[i]}
+		}
+	}
+	return res;
+}
+
+/* IEEE ECDSA Signature, C and D are signature on F using private key S */
+#[allow(non_snake_case)]
+pub fn ecpsp_dsa(sha: usize,rng: &mut RAND,s: &[u8],f: &[u8],c: &mut [u8],d: &mut [u8]) -> isize {
+	let mut t:[u8;EFS]=[0;EFS];
+	let mut b:[u8;rom::MODBYTES as usize]=[0;rom::MODBYTES as usize];
+
+	hashit(sha,f,0,None,rom::MODBYTES as usize,&mut b);
+
+	let gx=BIG::new_ints(&rom::CURVE_GX);
+	let gy=BIG::new_ints(&rom::CURVE_GY);
+
+	let G=ECP::new_bigs(&gx,&gy);
+	let r=BIG::new_ints(&rom::CURVE_ORDER);
+
+	let mut sc=BIG::frombytes(s);  /* s or &s? */
+	let fb=BIG::frombytes(&b);
+
+	let mut cb=BIG::new();
+	let mut db=BIG::new();
+	let mut tb=BIG::new();	
+	let mut V=ECP::new();
+
+	while db.iszilch() {
+		let mut u=BIG::randomnum(&r,rng);
+		let mut w=BIG::randomnum(&r,rng);
+		if rom::AES_S>0 {
+			u.mod2m(2*rom::AES_S);
+		}			
+		V.copy(&G);
+		V=V.mul(&mut u);   		
+		let vx=V.getx();
+		cb.copy(&vx);
+		cb.rmod(&r);
+		if cb.iszilch() {continue}
+
+		tb.copy(&BIG::modmul(&mut u,&mut w,&r));
+		u.copy(&tb);
+
+		u.invmodp(&r);
+		db.copy(&BIG::modmul(&mut sc,&mut cb,&r));
+		db.add(&fb);
+
+		tb.copy(&BIG::modmul(&mut db,&mut w,&r));
+		db.copy(&tb);
+
+		tb.copy(&BIG::modmul(&mut u,&mut db,&r));
+		db.copy(&tb);
+	} 
+       
+	cb.tobytes(&mut t);
+	for i in 0..EFS {c[i]=t[i]}
+	db.tobytes(&mut t);
+	for i in 0..EFS {d[i]=t[i]}
+	return 0;
+}
+
+/* IEEE1363 ECDSA Signature Verification. Signature C and D on F is verified using public key W */
+#[allow(non_snake_case)]
+pub fn ecpvp_dsa(sha: usize,w: &[u8],f: &[u8],c: &[u8],d: &[u8]) -> isize {
+	let mut res=0;
+
+	let mut b:[u8;rom::MODBYTES as usize]=[0;rom::MODBYTES as usize];
+
+	hashit(sha,f,0,None,rom::MODBYTES as usize,&mut b);
+
+	let gx=BIG::new_ints(&rom::CURVE_GX);
+	let gy=BIG::new_ints(&rom::CURVE_GY);
+
+	let mut G=ECP::new_bigs(&gx,&gy);
+	let r=BIG::new_ints(&rom::CURVE_ORDER);
+
+	let mut cb=BIG::frombytes(c);  /* c or &c ? */
+	let mut db=BIG::frombytes(d);  /* d or &d ? */
+	let mut fb=BIG::frombytes(&b);
+	let mut tb=BIG::new();		
+     
+	if cb.iszilch() || BIG::comp(&cb,&r)>=0 || db.iszilch() || BIG::comp(&db,&r)>=0 {
+            res=INVALID;
+	}
+
+	if res==0 {
+		db.invmodp(&r);
+		tb.copy(&BIG::modmul(&mut fb,&mut db,&r));
+		fb.copy(&tb);
+		let h2=BIG::modmul(&mut cb,&mut db,&r);
+
+		let mut WP=ECP::frombytes(&w);
+		if WP.is_infinity() {
+			res=ERROR;
+		} else {
+			let mut P=ECP::new();
+			P.copy(&WP);
+
+			P=P.mul2(&h2,&mut G,&fb);
+
+			if P.is_infinity() {
+				res=INVALID;
+			} else {
+				db=P.getx();
+				db.rmod(&r);
+
+				if BIG::comp(&db,&cb)!=0 {res=INVALID}
+			}
+		}
+	}
+
+	return res;
+}
+
+/* IEEE1363 ECIES encryption. Encryption of plaintext M uses public key W and produces ciphertext V,C,T */
+#[allow(non_snake_case)]
+pub fn ecies_encrypt(sha: usize,p1: &[u8],p2: &[u8],rng: &mut RAND,w: &[u8],m: &[u8],v: &mut [u8],t: &mut [u8]) -> Option<Vec<u8>> { 
+	let mut z:[u8;EFS]=[0;EFS];
+	let mut k1:[u8;EAS]=[0;EAS];
+	let mut k2:[u8;EAS]=[0;EAS];
+	let mut u:[u8;EGS]=[0;EGS];
+	let mut vz:[u8;3*EFS+1]=[0;3*EFS+1];	
+	let mut k:[u8;EFS]=[0;EFS];
+
+	if key_pair_generate(Some(rng),&mut u,v)!=0 {return None}
+	if ecpsvdp_dh(&u,&w,&mut z)!=0 {return None}     
+
+	for i in 0..2*EFS+1 {vz[i]=v[i]}
+	for i in 0..EFS {vz[2*EFS+1+i]=z[i]}
+
+
+	kdf2(sha,&vz,Some(p1),EFS,&mut k);
+
+	for i in 0..EAS {k1[i]=k[i]; k2[i]=k[EAS+i]} 
+
+	let mut c=cbc_iv0_encrypt(&k1,m);
+
+	let mut l2:[u8;8]=[0;8];
+	let p2l=p2.len();
+
+	inttobytes(p2l,&mut l2);	
+
+	for i in 0..p2l {
+		c.push(p2[i]);
+	}
+	for i in 0..8 {
+		c.push(l2[i]);
+	}
+
+	hmac(sha,&c,&k2,t.len(),t);
+
+	for _ in 0..p2l+8 {c.pop();}
+	
+	return Some(c);
+}
+
+/* IEEE1363 ECIES decryption. Decryption of ciphertext V,C,T using private key U outputs plaintext M */
+#[allow(non_snake_case)]
+pub fn ecies_decrypt(sha: usize,p1: &[u8],p2: &[u8],v: &[u8],c: &mut Vec<u8>,t: &[u8],u: &[u8]) -> Option<Vec<u8>>  { 
+	let mut z:[u8;EFS]=[0;EFS];
+	let mut k1:[u8;EAS]=[0;EAS];
+	let mut k2:[u8;EAS]=[0;EAS];
+	let mut vz:[u8;3*EFS+1]=[0;3*EFS+1];	
+	let mut k:[u8;EFS]=[0;EFS];
+
+	let mut tag:[u8;32]=[0;32];  /* 32 is max length of tag */
+
+	for i in 0..t.len() {tag[i]=t[i]}
+
+	if ecpsvdp_dh(&u,&v,&mut z)!=0 {return None}
+
+	for i in 0..2*EFS+1 {vz[i]=v[i]}
+	for i in 0..EFS {vz[2*EFS+1+i]=z[i]}
+
+	kdf2(sha,&vz,Some(p1),EFS,&mut k);
+
+	for i in 0..EAS {k1[i]=k[i]; k2[i]=k[EAS+i]} 
+
+	let m=cbc_iv0_decrypt(&k1,&c);
+
+	if m==None {return None}
+
+	let mut l2:[u8;8]=[0;8];
+	let p2l=p2.len();
+
+	inttobytes(p2l,&mut l2);	
+
+	for i in 0..p2l {
+		c.push(p2[i]);
+	}
+	for i in 0..8 {
+		c.push(l2[i]);
+	}
+
+	hmac(sha,&c,&k2,t.len(),&mut tag);
+
+	for _ in 0..p2l+8 {c.pop();}
+
+	let mut same=true;
+	for i in 0..t.len() {
+		if t[i]!=tag[i] {same=false}
+	}
+	if !same {return None}
+	
+	return m;
+}
+
diff --git a/version22/rust/src/ecp.rs b/version22/rust/src/ecp.rs
new file mode 100644
index 0000000..69b6c57
--- /dev/null
+++ b/version22/rust/src/ecp.rs
@@ -0,0 +1,955 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use std::fmt;
+use std::str::SplitWhitespace;
+
+#[derive(Copy, Clone)]
+pub struct ECP {
+	x:FP,
+	y:FP,
+	z:FP,
+	inf: bool
+}
+
+
+//use rom;
+//mod fp;
+use fp::FP;
+//mod big;
+use big::BIG;
+//mod dbig;
+//use dbig::DBIG;
+//mod rand;
+//mod hash256;
+//mod rom;
+use rom;
+use rom::BIG_HEX_STRING_LEN;
+
+impl fmt::Display for ECP {
+	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+		write!(f, "ECP: [ {}, {}, {}, {} ]", self.inf, self.x, self.y, self.z)
+	}
+}
+
+impl fmt::Debug for ECP {
+	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+		write!(f, "ECP: [ {}, {}, {}, {} ]", self.inf, self.x, self.y, self.z)
+	}
+}
+
+impl PartialEq for ECP {
+	fn eq(&self, other: &ECP) -> bool {
+		return (self.inf == other.inf) &&
+			(self.x == other.x) &&
+			(self.y == other.y) &&
+			(self.z == other.z);
+	}
+}
+
+#[allow(non_snake_case)]
+impl ECP {
+
+	pub fn new() -> ECP {
+		ECP {
+				x: FP::new(),
+				y: FP::new(),
+				z: FP::new(),
+				inf: true
+		}
+	}
+
+/* set (x,y) from two BIGs */
+	pub fn new_bigs(ix: &BIG,iy: &BIG) -> ECP {
+		let mut E=ECP::new();
+		E.x.bcopy(ix); 
+		E.y.bcopy(iy); 
+		E.z.one(); 
+		let mut rhs=ECP::rhs(&mut E.x);
+		if rom::CURVETYPE==rom::MONTGOMERY {
+			if rhs.jacobi()==1 {
+				E.inf=false;
+			} else {E.inf()}
+		} else {
+			let mut y2=FP::new_copy(&E.y);
+			y2.sqr();	
+			if y2.equals(&mut rhs) {
+				E.inf=false
+			} else {E.inf()}
+		}
+		return E;
+	}
+
+/* set (x,y) from BIG and a bit */
+	pub fn new_bigint(ix: &BIG,s: isize) -> ECP {
+		let mut E=ECP::new();
+		E.x.bcopy(ix); 
+		E.z.one(); 
+
+		let mut rhs=ECP::rhs(&mut E.x);
+
+		if rhs.jacobi()==1 {
+			let mut ny=rhs.sqrt();
+			if ny.redc().parity()!=s {ny.neg()}
+			E.y.copy(&ny);
+			E.inf=false;
+		} else {E.inf()}
+		return E;
+	}
+
+#[allow(non_snake_case)]
+/* set from x - calculate y from curve equation */
+	pub fn new_big(ix: &BIG) -> ECP {
+		let mut E=ECP::new();
+		E.x.bcopy(ix); 
+		E.z.one(); 
+		let mut rhs=ECP::rhs(&mut E.x);
+		if rhs.jacobi()==1 {
+			if rom::CURVETYPE!=rom::MONTGOMERY {E.y.copy(&rhs.sqrt())}
+			E.inf=false;
+		} else {E.inf=true}
+		return E;
+	}
+
+/* set this=O */
+	pub fn inf(&mut self) {
+		self.inf=true;
+		self.x.zero();
+		self.y.one();
+		self.z.one();
+	}
+
+/* Calculate RHS of curve equation */
+	fn rhs(x: &mut FP) -> FP {
+		x.norm();
+		let mut r=FP::new_copy(x);
+		r.sqr();
+
+		if rom::CURVETYPE==rom::WEIERSTRASS { // x^3+Ax+B
+			let b=FP::new_big(&BIG::new_ints(&rom::CURVE_B));
+			r.mul(x);
+			if rom::CURVE_A==-3 {
+				let mut cx=FP::new_copy(x);
+				cx.imul(3);
+				cx.neg(); cx.norm();
+				r.add(&cx);
+			}
+			r.add(&b);
+		}
+		if rom::CURVETYPE==rom::EDWARDS { // (Ax^2-1)/(Bx^2-1) 
+			let mut b=FP::new_big(&BIG::new_ints(&rom::CURVE_B));
+			let one=FP::new_int(1);
+			b.mul(&mut r);
+			b.sub(&one);
+			if rom::CURVE_A==-1 {r.neg()}
+			r.sub(&one);
+			b.inverse();
+			r.mul(&mut b);
+		}
+		if rom::CURVETYPE==rom::MONTGOMERY { // x^3+Ax^2+x
+			let mut x3=FP::new();
+			x3.copy(&r);
+			x3.mul(x);
+			r.imul(rom::CURVE_A);
+			r.add(&x3);
+			r.add(&x);
+		}
+		r.reduce();
+		return r;
+	}
+
+/* test for O point-at-infinity */
+	pub fn is_infinity(&mut self) -> bool {
+		if rom::CURVETYPE==rom::EDWARDS {
+			self.x.reduce(); self.y.reduce(); self.z.reduce();
+			return self.x.iszilch() && self.y.equals(&mut self.z);
+		} else {return self.inf}
+ 	}
+
+/* Conditional swap of P and Q dependant on d */
+	pub fn cswap(&mut self,Q: &mut ECP,d: isize) {
+		self.x.cswap(&mut Q.x,d);
+		if rom::CURVETYPE!=rom::MONTGOMERY {self.y.cswap(&mut Q.y,d)}
+		self.z.cswap(&mut Q.z,d);
+		if rom::CURVETYPE!=rom::EDWARDS {
+			let mut bd=true;
+			if d==0 {bd=false}
+			bd=bd&&(self.inf!=Q.inf);
+			self.inf=bd!=self.inf;
+			Q.inf=bd!=Q.inf;
+		}
+	}
+
+/* Conditional move of Q to P dependant on d */
+	pub fn cmove(&mut self,Q: &ECP,d: isize) {
+		self.x.cmove(&Q.x,d);
+		if rom::CURVETYPE!=rom::MONTGOMERY {self.y.cmove(&Q.y,d)}
+		self.z.cmove(&Q.z,d);
+		if rom::CURVETYPE!=rom::EDWARDS {
+			let mut bd=true;
+			if d==0 {bd=false}
+			self.inf=self.inf!=((self.inf!=Q.inf)&&bd);
+		}
+	}
+
+/* return 1 if b==c, no branching */
+	fn teq(b: i32,c: i32) -> isize {
+		let mut x=b^c;
+		x-=1;  // if x=0, x now -1
+		return ((x>>31)&1) as isize;
+	}
+
+/* this=P */
+	pub fn copy(&mut self,P: & ECP) {
+		self.x.copy(&P.x);
+		if rom::CURVETYPE!=rom::MONTGOMERY {self.y.copy(&P.y)}
+		self.z.copy(&P.z);
+		self.inf=P.inf;
+}
+
+/* this=-this */
+	pub fn neg(&mut self) {
+		if self.is_infinity() {return}
+		if rom::CURVETYPE==rom::WEIERSTRASS {
+			self.y.neg(); self.y.norm();
+		}
+		if rom::CURVETYPE==rom::EDWARDS {
+			self.x.neg(); self.x.norm();
+		}
+		return;
+	}
+/* multiply x coordinate */
+	pub fn mulx(&mut self,c: &mut FP) {
+		self.x.mul(c);
+	}
+
+/* Constant time select from pre-computed table */
+	fn selector(&mut self, W: &[ECP],b: i32) {   // unsure about &[& syntax. An array of pointers I hope..
+		let mut MP=ECP::new();
+		let m=b>>31;
+		let mut babs=(b^m)-m;
+
+		babs=(babs-1)/2;
+
+		self.cmove(&W[0],ECP::teq(babs,0));  // conditional move
+		self.cmove(&W[1],ECP::teq(babs,1));
+		self.cmove(&W[2],ECP::teq(babs,2));
+		self.cmove(&W[3],ECP::teq(babs,3));
+		self.cmove(&W[4],ECP::teq(babs,4));
+		self.cmove(&W[5],ECP::teq(babs,5));
+		self.cmove(&W[6],ECP::teq(babs,6));
+		self.cmove(&W[7],ECP::teq(babs,7));
+ 
+		MP.copy(self);
+		MP.neg();
+		self.cmove(&MP,(m&1) as isize);
+	}
+
+/* Test P == Q */
+	pub fn equals(&mut self,Q: &mut ECP) -> bool {
+		if self.is_infinity() && Q.is_infinity() {return true}
+		if self.is_infinity() || Q.is_infinity() {return false}
+		if rom::CURVETYPE==rom::WEIERSTRASS {
+			let mut zs2=FP::new_copy(&self.z); zs2.sqr();
+			let mut zo2=FP::new_copy(&Q.z); zo2.sqr();
+			let mut zs3=FP::new_copy(&zs2); zs3.mul(&mut self.z);
+			let mut zo3=FP::new_copy(&zo2); zo3.mul(&mut Q.z);
+			zs2.mul(&mut Q.x);
+			zo2.mul(&mut self.x);
+			if !zs2.equals(&mut zo2) {return false}
+			zs3.mul(&mut Q.y);
+			zo3.mul(&mut self.y);
+			if !zs3.equals(&mut zo3) {return false}
+		} else {
+			let mut a=FP::new();
+			let mut b=FP::new();
+			a.copy(&self.x); a.mul(&mut Q.z); a.reduce();
+			b.copy(&Q.x); b.mul(&mut self.z); b.reduce();
+			if !a.equals(&mut b) {return false}
+			if rom::CURVETYPE==rom::EDWARDS {
+				a.copy(&self.y); a.mul(&mut Q.z); a.reduce();
+				b.copy(&Q.y); b.mul(&mut self.z); b.reduce();
+				if !a.equals(&mut b) {return false}
+			}
+		}
+		return true;
+	}
+
+/* set to affine - from (x,y,z) to (x,y) */
+	pub fn affine(&mut self) {
+		if self.is_infinity() {return}
+		let mut one=FP::new_int(1);
+		if self.z.equals(&mut one) {return}
+		self.z.inverse();
+		if rom::CURVETYPE==rom::WEIERSTRASS {
+			let mut z2=FP::new_copy(&self.z);
+			z2.sqr();
+			self.x.mul(&mut z2); self.x.reduce();
+			self.y.mul(&mut z2);
+			self.y.mul(&mut self.z); self.y.reduce();
+		}
+		if rom::CURVETYPE==rom::EDWARDS {
+			self.x.mul(&mut self.z); self.x.reduce();
+			self.y.mul(&mut self.z); self.y.reduce();
+		}
+		if rom::CURVETYPE==rom::MONTGOMERY {
+			self.x.mul(&mut self.z); self.x.reduce();
+		}
+		self.z.one();
+	}
+
+/* extract x as a BIG */
+	pub fn getx(&mut self) -> BIG {
+		self.affine();
+		return self.x.redc();
+	}
+
+/* extract y as a BIG */
+	pub fn gety(&mut self) -> BIG {
+		self.affine();
+		return self.y.redc();
+	}
+
+/* get sign of Y */
+	pub fn gets(&mut self) -> isize {
+		self.affine();
+		let y=self.gety();
+		return y.parity();
+	}
+
+/* extract x as an FP */
+	pub fn getpx(&self) -> FP {
+		let w=FP::new_copy(&self.x);
+		return w;
+	}
+/* extract y as an FP */
+	pub fn getpy(&self) -> FP {
+		let w=FP::new_copy(&self.y);
+		return w;
+	}
+
+/* extract z as an FP */
+	pub fn getpz(&self) -> FP {
+		let w=FP::new_copy(&self.z);
+		return w;
+	}
+
+/* convert to byte array */
+	pub fn tobytes(&mut self,b: &mut [u8]) {
+		let mb=rom::MODBYTES as usize;
+		let mut t:[u8;rom::MODBYTES as usize]=[0;rom::MODBYTES as usize];
+		if rom::CURVETYPE!=rom::MONTGOMERY {
+			b[0]=0x04;
+		} else {b[0]=0x02}
+	
+		self.affine();
+		self.x.redc().tobytes(&mut t);
+		for i in 0..mb {b[i+1]=t[i]}
+		if rom::CURVETYPE!=rom::MONTGOMERY {
+			self.y.redc().tobytes(&mut t);
+			for i in 0..mb {b[i+mb+1]=t[i]}
+		}
+	}
+
+/* convert from byte array to point */
+	pub fn frombytes(b: &[u8]) -> ECP {
+		let mut t:[u8;rom::MODBYTES as usize]=[0;rom::MODBYTES as usize];
+		let mb=rom::MODBYTES as usize;
+		let p=BIG::new_ints(&rom::MODULUS);
+
+		for i in 0..mb {t[i]=b[i+1]}
+		let px=BIG::frombytes(&t);
+		if BIG::comp(&px,&p)>=0 {return ECP::new()}
+
+		if b[0]==0x04 {
+			for i in 0..mb {t[i]=b[i+mb+1]}
+			let py=BIG::frombytes(&t);
+			if BIG::comp(&py,&p)>=0 {return ECP::new()}
+			return ECP::new_bigs(&px,&py);
+		} else {return ECP::new_big(&px)}
+	}
+
+	pub fn to_hex(&self) -> String {
+		let mut ret: String = String::with_capacity(4 * BIG_HEX_STRING_LEN);
+		ret.push_str(&format!("{} {} {} {}", self.inf, self.x.to_hex(), self.y.to_hex(), self.z.to_hex()));
+		return ret;
+	}
+
+	pub fn from_hex_iter(iter: &mut SplitWhitespace) -> ECP {
+		let mut ret:ECP = ECP::new();
+		if let Some(x) = iter.next() {
+			ret.inf = x == "true";
+			ret.x = FP::from_hex_iter(iter);
+			ret.y = FP::from_hex_iter(iter);
+			ret.z = FP::from_hex_iter(iter);
+		}
+		return ret;
+	}
+
+	pub fn from_hex(val: String) -> ECP {
+		let mut iter = val.split_whitespace();
+		return ECP::from_hex_iter(&mut iter);
+	}
+
+/* convert to hex string */
+	pub fn tostring(&mut self) -> String {
+	 	if self.is_infinity() {return String::from("infinity")}
+		self.affine();
+		if rom::CURVETYPE==rom::MONTGOMERY {
+			return format!("({})",self.x.redc().tostring());
+		} else {return format!("({},{})",self.x.redc().tostring(),self.y.redc().tostring())} ; 
+	}
+
+/* this*=2 */
+	pub fn dbl(&mut self) {
+		if rom::CURVETYPE==rom::WEIERSTRASS {
+			if self.inf {return}
+			if self.y.iszilch() {
+				self.inf();
+				return;
+			}
+
+			let mut w1=FP::new_copy(&self.x);
+			let mut w6=FP::new_copy(&self.z);
+			let mut w2=FP::new();
+			let mut w3=FP::new_copy(&self.x);
+			let mut w8=FP::new_copy(&self.x);
+
+			if rom::CURVE_A==-3 {
+				w6.sqr();
+				w1.copy(&w6);
+				w1.neg();
+				w3.add(&w1);
+
+				w8.add(&w6);
+
+				w3.mul(&mut w8);
+				w8.copy(&w3);
+				w8.imul(3);
+			} else {
+				w1.sqr();
+				w8.copy(&w1);
+				w8.imul(3);
+			}
+
+			w2.copy(&self.y); w2.sqr();
+			w3.copy(&self.x); w3.mul(&mut w2);
+			w3.imul(4);
+			w1.copy(&w3); w1.neg();
+			w1.norm();
+
+           	self.x.copy(&w8); self.x.sqr();
+            self.x.add(&w1);
+            self.x.add(&w1);
+            self.x.norm();
+    
+            self.z.mul(&mut self.y);
+            self.z.dbl();
+    
+            w2.dbl();  
+            w2.sqr();
+            w2.dbl();
+            w3.sub(&self.x);
+            self.y.copy(&w8); self.y.mul(&mut w3);
+            //w2.norm();
+            self.y.sub(&w2);
+            self.y.norm();
+            self.z.norm();
+        }
+        if rom::CURVETYPE==rom::EDWARDS {
+            let mut c=FP::new_copy(&self.x);
+            let mut d=FP::new_copy(&self.y);
+            let mut h=FP::new_copy(&self.z);
+            let mut j=FP::new();
+    
+            self.x.mul(&mut self.y); self.x.dbl();
+            c.sqr();
+            d.sqr();
+            if rom::CURVE_A == -1 {c.neg()}
+            self.y.copy(&c); self.y.add(&d);
+            self.y.norm();
+            h.sqr(); h.dbl(); 
+            self.z.copy(&self.y);
+            j.copy(&self.y); j.sub(&h);
+            self.x.mul(&mut j);
+            c.sub(&d);
+            self.y.mul(&mut c);
+            self.z.mul(&mut j);
+    
+            self.x.norm();
+            self.y.norm();
+            self.z.norm();
+        }
+        if rom::CURVETYPE==rom::MONTGOMERY {
+            let mut a=FP::new_copy(&self.x);
+            let mut b=FP::new_copy(&self.x);
+            let mut aa=FP::new();
+            let mut bb=FP::new();
+            let mut c=FP::new();
+    
+            if self.inf {return}
+    
+            a.add(&self.z);
+            aa.copy(&a); aa.sqr();
+            b.sub(&self.z);
+            bb.copy(&b); bb.sqr();
+            c.copy(&aa); c.sub(&bb);
+    
+            self.x.copy(&aa); self.x.mul(&mut bb);
+    
+            a.copy(&c); a.imul((rom::CURVE_A+2)/4);
+    
+            bb.add(&a);
+            self.z.copy(&bb); self.z.mul(&mut c);
+            self.x.norm();
+            self.z.norm();
+        }
+        return;
+    }
+
+    /* self+=Q */
+    pub fn add(&mut self,Q:&mut ECP)
+    {
+        if rom::CURVETYPE==rom::WEIERSTRASS {
+            if self.inf {
+				self.copy(&Q);
+				return;
+            }
+            if Q.inf {return}
+    
+            let mut aff=false;
+    
+            let mut one=FP::new_int(1);
+            if Q.z.equals(&mut one) {aff=true}
+    
+            let mut a=FP::new();
+            let mut c=FP::new();
+            let mut b=FP::new_copy(&self.z);
+            let mut d=FP::new_copy(&self.z);
+            if !aff {
+            	a.copy(&Q.z);
+            	c.copy(&Q.z);
+    
+				a.sqr(); b.sqr();
+				c.mul(&mut a); d.mul(&mut b);
+    
+				a.mul(&mut self.x);
+				c.mul(&mut self.y);
+            }
+            else
+            {
+				a.copy(&self.x);
+				c.copy(&self.y);
+    
+				b.sqr();
+				d.mul(&mut b);
+            }
+    
+            b.mul(&mut Q.x); b.sub(&a);
+            d.mul(&mut Q.y); d.sub(&c);
+    
+            if b.iszilch()
+            {
+				if d.iszilch()
+				{
+                    self.dbl();
+                    return;
+				}
+				else
+				{
+                    self.inf=true;
+                    return;
+				}
+            }
+    
+            if !aff {self.z.mul(&mut Q.z)}
+            self.z.mul(&mut b);
+    
+            let mut e=FP::new_copy(&b); e.sqr();
+            b.mul(&mut e);
+            a.mul(&mut e);
+    
+            e.copy(&a);
+            e.add(&a); e.add(&b);
+            self.x.copy(&d); self.x.sqr(); self.x.sub(&e);
+    
+            a.sub(&self.x);
+            self.y.copy(&a); self.y.mul(&mut d);
+            c.mul(&mut b); self.y.sub(&c);
+    
+            self.x.norm();
+            self.y.norm();
+            self.z.norm();
+        }
+        if rom::CURVETYPE==rom::EDWARDS {
+            let mut bb=FP::new_big(&BIG::new_ints(&rom::CURVE_B));
+            let mut a=FP::new_copy(&self.z);
+            let mut b=FP::new();
+            let mut c=FP::new_copy(&self.x);
+            let mut d=FP::new_copy(&self.y);
+            let mut e=FP::new();
+            let mut f=FP::new();
+            let mut g=FP::new();
+    
+            a.mul(&mut Q.z);
+            b.copy(&a); b.sqr();
+            c.mul(&mut Q.x);
+            d.mul(&mut Q.y);
+    
+            e.copy(&c); e.mul(&mut d); e.mul(&mut bb);
+            f.copy(&b); f.sub(&e);
+            g.copy(&b); g.add(&e);
+    
+            if rom::CURVE_A==1 {
+				e.copy(&d); e.sub(&c);
+            }
+            c.add(&d);
+    
+            b.copy(&self.x); b.add(&self.y);
+            d.copy(&Q.x); d.add(&Q.y);
+            b.mul(&mut d);
+            b.sub(&c);
+            b.mul(&mut f);
+            self.x.copy(&a); self.x.mul(&mut b);
+
+            if rom::CURVE_A==1 {
+				c.copy(&e); c.mul(&mut g);
+            }
+            if rom::CURVE_A == -1 {
+				c.mul(&mut g);
+            }
+            self.y.copy(&a); self.y.mul(&mut c);
+            self.z.copy(&f); self.z.mul(&mut g);
+            self.x.norm(); self.y.norm(); self.z.norm();
+        }
+        return;
+    }
+
+/* Differential Add for Montgomery curves. this+=Q where W is this-Q and is affine. */
+	pub fn dadd(&mut self,Q: &ECP,W: &ECP) {
+		let mut a=FP::new_copy(&self.x);
+		let mut b=FP::new_copy(&self.x);
+		let mut c=FP::new_copy(&Q.x);
+		let mut d=FP::new_copy(&Q.x);
+		let mut da=FP::new();
+		let mut cb=FP::new();
+			
+		a.add(&self.z);
+		b.sub(&self.z);
+
+		c.add(&Q.z);
+		d.sub(&Q.z);
+
+		da.copy(&d); da.mul(&mut a);
+		cb.copy(&c); cb.mul(&mut b);
+
+		a.copy(&da); a.add(&cb); a.sqr();
+		b.copy(&da); b.sub(&cb); b.sqr();
+
+		self.x.copy(&a);
+		self.z.copy(&W.x); self.z.mul(&mut b);
+
+		if self.z.iszilch() {
+			self.inf();
+		} else {self.inf=false;}
+
+		self.x.norm();
+	}
+
+/* self-=Q */
+	pub fn sub(&mut self,Q:&mut ECP) {
+		Q.neg();
+		self.add(Q);
+		Q.neg();
+	}
+
+	fn multiaffine(P: &mut [ECP]) {
+		let mut t1=FP::new();
+		let mut t2=FP::new();
+
+		let mut work:[FP;8]=[FP::new(),FP::new(),FP::new(),FP::new(),FP::new(),FP::new(),FP::new(),FP::new()];
+		let m=8;
+
+		work[0].one();
+		work[1].copy(&P[0].z);
+
+		for i in 2..m {
+			t1.copy(&work[i-1]);
+			work[i].copy(&t1);
+			work[i].mul(&mut P[i-1].z);
+		}
+
+		t1.copy(&work[m-1]);
+		t1.mul(&mut P[m-1].z);
+		t1.inverse();
+		t2.copy(&P[m-1].z);
+		work[m-1].mul(&mut t1);
+
+		let mut i=m-2;
+		loop {
+			if i==0 {
+				work[0].copy(&t1);
+				work[0].mul(&mut t2);
+				break;
+			}
+			work[i].mul(&mut t2);
+			work[i].mul(&mut t1);
+			t2.mul(&mut P[i].z);
+			i-=1;
+		}
+/* now work[] contains inverses of all Z coordinates */
+
+		for i in 0..m {
+			P[i].z.one();
+			t1.copy(&work[i]);
+			t1.sqr();
+			P[i].x.mul(&mut t1);
+			t1.mul(&mut work[i]);
+			P[i].y.mul(&mut t1);
+		}    
+	}
+
+/* constant time multiply by small integer of length bts - use ladder */
+	pub fn pinmul(&mut self,e: i32,bts: i32) -> ECP {	
+		if rom::CURVETYPE==rom::MONTGOMERY {
+			return self.mul(&mut BIG::new_int(e as isize));
+		} else {
+			let mut P=ECP::new();
+			let mut R0=ECP::new();
+			let mut R1=ECP::new(); R1.copy(&self);
+
+			for i in (0..bts).rev() {
+				let b=((e>>i)&1) as isize;
+				P.copy(&R1);
+				P.add(&mut R0);
+				R0.cswap(&mut R1,b);
+				R1.copy(&P);
+				R0.dbl();
+				R0.cswap(&mut R1,b);
+			}
+			P.copy(&R0);
+			P.affine();
+			return P;
+		}
+	}
+
+/* return e.self */
+
+	pub fn mul(&mut self,e:&mut BIG) -> ECP {
+		if e.iszilch() || self.is_infinity() {return ECP::new()}
+		let mut P=ECP::new();
+		if rom::CURVETYPE==rom::MONTGOMERY {
+/* use Ladder */
+			let mut D=ECP::new();
+			let mut R0=ECP::new(); R0.copy(&self);
+			let mut R1=ECP::new(); R1.copy(&self);
+			R1.dbl();
+			D.copy(&self); D.affine();
+			let nb=e.nbits();
+
+			for i in (0..nb-1).rev() {
+				let b=e.bit(i);
+				P.copy(&R1);
+				P.dadd(&mut R0,&D);
+				R0.cswap(&mut R1,b);
+				R1.copy(&P);
+				R0.dbl();
+				R0.cswap(&mut R1,b);
+			}
+			P.copy(&R0)
+		} else {
+// fixed size windows 
+			let mut mt=BIG::new();
+			let mut t=BIG::new();
+			let mut Q=ECP::new();
+			let mut C=ECP::new();
+
+		 	let mut W:[ECP;8]=[ECP::new(),ECP::new(),ECP::new(),ECP::new(),ECP::new(),ECP::new(),ECP::new(),ECP::new()];
+
+		 	const CT:usize=1+(rom::NLEN*(rom::BASEBITS as usize)+3)/4;
+			let mut w:[i8;CT]=[0;CT];
+
+			self.affine();
+
+			Q.copy(&self);
+			Q.dbl();
+
+			W[0].copy(&self);
+
+			for i in 1..8 {
+				C.copy(&W[i-1]);
+				W[i].copy(&C);
+				W[i].add(&mut Q);
+			}
+
+// convert the table to affine 
+			if rom::CURVETYPE==rom::WEIERSTRASS {
+				ECP::multiaffine(&mut W);
+			}
+
+// make exponent odd - add 2P if even, P if odd 
+			t.copy(&e);
+			let s=t.parity();
+			t.inc(1); t.norm(); let ns=t.parity(); mt.copy(&t); mt.inc(1); mt.norm();
+			t.cmove(&mt,s);
+			Q.cmove(&self,ns);
+			C.copy(&Q);
+
+			let nb=1+(t.nbits()+3)/4;
+
+// convert exponent to signed 4-bit window 
+			for i in 0..nb {
+				w[i]=(t.lastbits(5)-16) as i8;
+				t.dec(w[i] as isize); t.norm();
+				t.fshr(4);	
+			}
+			w[nb]=t.lastbits(5) as i8;
+
+			P.copy(&W[((w[nb] as usize)-1)/2]); 
+			for i in (0..nb).rev() {
+				Q.selector(&W,w[i] as i32);
+				P.dbl();
+				P.dbl();
+				P.dbl();
+				P.dbl();
+				P.add(&mut Q);
+			}
+			P.sub(&mut C); /* apply correction */
+		}
+		P.affine();
+		return P;
+	}
+
+/* Return e.this+f.Q */
+
+	pub fn mul2(&mut self,e: &BIG,Q: &mut ECP,f: &BIG) -> ECP {
+		let mut te=BIG::new();
+		let mut tf=BIG::new();
+		let mut mt=BIG::new();
+		let mut S=ECP::new();
+		let mut T=ECP::new();
+		let mut C=ECP::new();
+
+		let mut W:[ECP;8]=[ECP::new(),ECP::new(),ECP::new(),ECP::new(),ECP::new(),ECP::new(),ECP::new(),ECP::new()];
+
+		const CT:usize=1+(rom::NLEN*(rom::BASEBITS as usize)+1)/2;
+		let mut w: [i8;CT]=[0;CT];		
+
+		self.affine();
+		Q.affine();
+
+		te.copy(e);
+		tf.copy(f);
+
+// precompute table 
+
+		W[1].copy(&self); W[1].sub(Q);
+		W[2].copy(&self); W[2].add(Q);
+		S.copy(&Q); S.dbl();
+		C.copy(&W[1]); W[0].copy(&C); W[0].sub(&mut S); // copy to C is stupid Rust thing..
+		C.copy(&W[2]); W[3].copy(&C); W[3].add(&mut S);
+		T.copy(&self); T.dbl();
+		C.copy(&W[1]); W[5].copy(&C); W[5].add(&mut T);
+		C.copy(&W[2]); W[6].copy(&C); W[6].add(&mut T);
+		C.copy(&W[5]); W[4].copy(&C); W[4].sub(&mut S);
+		C.copy(&W[6]); W[7].copy(&C); W[7].add(&mut S);
+
+// convert the table to affine 
+		if rom::CURVETYPE==rom::WEIERSTRASS { 
+			ECP::multiaffine(&mut W);
+		}
+
+// if multiplier is odd, add 2, else add 1 to multiplier, and add 2P or P to correction 
+
+		let mut s=te.parity();
+		te.inc(1); te.norm(); let mut ns=te.parity(); mt.copy(&te); mt.inc(1); mt.norm();
+		te.cmove(&mt,s);
+		T.cmove(&self,ns);
+		C.copy(&T);
+
+		s=tf.parity();
+		tf.inc(1); tf.norm(); ns=tf.parity(); mt.copy(&tf); mt.inc(1); mt.norm();
+		tf.cmove(&mt,s);
+		S.cmove(&Q,ns);
+		C.add(&mut S);
+
+		mt.copy(&te); mt.add(&tf); mt.norm();
+		let nb=1+(mt.nbits()+1)/2;
+
+// convert exponent to signed 2-bit window 
+		for i in 0..nb {
+			let a=te.lastbits(3)-4;
+			te.dec(a); te.norm();
+			te.fshr(2);
+			let b=tf.lastbits(3)-4;
+			tf.dec(b); tf.norm();
+			tf.fshr(2);
+			w[i]=(4*a+b) as i8;
+		}
+		w[nb]=(4*te.lastbits(3)+tf.lastbits(3)) as i8;
+		S.copy(&W[((w[nb] as usize)-1)/2]);  
+
+		for i in (0..nb).rev() {
+			T.selector(&W,w[i] as i32);
+			S.dbl();
+			S.dbl();
+			S.add(&mut T);
+		}
+		S.sub(&mut C); /* apply correction */
+		S.affine();
+		return S;
+	}
+
+
+}
+/*
+fn main()
+{
+	let mut E=ECP::new();
+
+	let mut W:[&ECP;8]=[&ECP::new(),&ECP::new(),&ECP::new(),&ECP::new(),&ECP::new(),&ECP::new(),&ECP::new(),&ECP::new()];
+
+	let mut gx=BIG::new_ints(&rom::CURVE_GX);
+	let mut gy=BIG::new();
+	let mut P=ECP::new();
+
+	if rom::CURVETYPE!=rom::MONTGOMERY {gy.copy(&BIG::new_ints(&rom::CURVE_GY))}
+	let mut r=BIG::new_ints(&rom::CURVE_ORDER);
+
+	//r.dec(7);
+	
+	println!("gx= {}",gx.tostring());
+
+	if rom::CURVETYPE!=rom::MONTGOMERY {
+		println!("gy= {}",gy.tostring());
+	}	
+
+	if rom::CURVETYPE!=rom::MONTGOMERY {
+		P.copy(&ECP::new_bigs(&gx,&gy))}
+	else  {P.copy(&ECP::new_big(&gx))}
+
+	println!("P= {}",P.tostring());		
+
+	let mut R=P.mul(&mut r);
+		//for i in 0..10000	(R=P.mul(r));
+	
+	println!("R= {}",R.tostring());
+
+}
+*/
diff --git a/version22/rust/src/ecp2.rs b/version22/rust/src/ecp2.rs
new file mode 100644
index 0000000..cee55a6
--- /dev/null
+++ b/version22/rust/src/ecp2.rs
@@ -0,0 +1,677 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use std::fmt;
+use std::str::SplitWhitespace;
+
+#[derive(Copy, Clone)]
+pub struct ECP2 {
+	x:FP2,
+	y:FP2,
+	z:FP2,
+	inf: bool
+}
+
+
+use rom;
+use rom::BIG_HEX_STRING_LEN;
+//mod fp2;
+use fp2::FP2;
+//mod fp;
+//use fp::FP;
+//mod big;
+use big::BIG;
+//mod dbig;
+//use dbig::DBIG;
+//mod rand;
+//mod hash256;
+//mod rom;
+
+impl fmt::Display for ECP2 {
+	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+		write!(f, "ECP2: [ {}, {}, {}, {} ]", self.inf, self.x, self.y, self.z)
+	}
+}
+
+impl fmt::Debug for ECP2 {
+	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+		write!(f, "ECP2: [ {}, {}, {}, {} ]", self.inf, self.x, self.y, self.z)
+	}
+}
+
+impl PartialEq for ECP2 {
+	fn eq(&self, other: &ECP2) -> bool {
+		return (self.inf == other.inf) &&
+			(self.x == other.x) &&
+			(self.y == other.y) &&
+			(self.z == other.z);
+	}
+}
+
+#[allow(non_snake_case)]
+impl ECP2 {
+
+	pub fn new() -> ECP2 {
+		ECP2 {
+				x: FP2::new(),
+				y: FP2::new(),
+				z: FP2::new(),
+				inf: true
+		}
+	}
+#[allow(non_snake_case)]
+/* construct this from (x,y) - but set to O if not on curve */
+	pub fn new_fp2s(ix:&FP2,iy:&FP2) -> ECP2 {
+		let mut E=ECP2::new();
+		E.x.copy(&ix);
+		E.y.copy(&iy);
+		E.z.one();
+
+		let mut rhs=ECP2::rhs(&mut E.x);
+		let mut y2=FP2::new_copy(&E.y);
+		y2.sqr();
+		if y2.equals(&mut rhs) {
+			E.inf=false;
+		} else {E.x.zero();E.inf=true}
+		return E;
+}
+
+/* construct this from x - but set to O if not on curve */
+	pub fn new_fp2(ix:&FP2) -> ECP2 {	
+		let mut E=ECP2::new();
+		E.x.copy(&ix);
+		E.y.one();
+		E.z.one();
+
+		let mut rhs=ECP2::rhs(&mut E.x);
+		if rhs.sqrt() {
+			E.y.copy(&rhs);
+			E.inf=false;
+		} else {E.x.zero();E.inf=true}
+		return E;
+	}
+
+/* Test this=O? */
+	pub fn is_infinity(&mut self) -> bool {
+		return self.inf;
+	}
+
+/* copy self=P */
+	pub fn copy(&mut self,P: &ECP2) {
+		self.x.copy(&P.x);
+		self.y.copy(&P.y);
+		self.z.copy(&P.z);
+		self.inf=P.inf;
+	}
+
+/* set self=O */
+	pub fn inf(&mut self) {
+		self.inf=true;
+		self.x.zero();
+		self.y.zero();
+		self.z.zero();
+	}
+
+/* set self=-self */
+	pub fn neg(&mut self) {
+		if self.is_infinity() {return}
+		self.y.neg(); self.y.reduce();
+	}	
+
+/* Conditional move of Q to self dependant on d */
+	pub fn cmove(&mut self,Q: &ECP2,d: isize) {
+		self.x.cmove(&Q.x,d);
+		self.y.cmove(&Q.y,d);
+		self.z.cmove(&Q.z,d);
+
+		let bd:bool;
+		if d==0 {bd=false}
+		else {bd=true}
+
+		self.inf=self.inf!=(self.inf!=Q.inf)&&bd;
+	}
+
+/* return 1 if b==c, no branching */
+	fn teq(b: i32,c: i32) -> isize {
+		let mut x=b^c;
+		x-=1;  // if x=0, x now -1
+		return ((x>>31)&1) as isize;
+	}
+
+/* Constant time select from pre-computed table */
+	pub fn selector(&mut self,W: &[ECP2],b: i32) {
+		let mut MP=ECP2::new(); 
+		let m=b>>31;
+		let mut babs=(b^m)-m;
+
+		babs=(babs-1)/2;
+
+		self.cmove(&W[0],ECP2::teq(babs,0));  // conditional move
+		self.cmove(&W[1],ECP2::teq(babs,1));
+		self.cmove(&W[2],ECP2::teq(babs,2));
+		self.cmove(&W[3],ECP2::teq(babs,3));
+		self.cmove(&W[4],ECP2::teq(babs,4));
+		self.cmove(&W[5],ECP2::teq(babs,5));
+		self.cmove(&W[6],ECP2::teq(babs,6));
+		self.cmove(&W[7],ECP2::teq(babs,7));
+ 
+		MP.copy(self);
+		MP.neg();
+		self.cmove(&MP,(m&1) as isize);
+	}	
+
+/* Test if P == Q */
+	pub fn equals(&mut self,Q :&mut ECP2) -> bool {
+		if self.is_infinity() && Q.is_infinity() {return true}
+		if self.is_infinity() || Q.is_infinity() {return false}
+
+		let mut zs2=FP2::new_copy(&self.z); zs2.sqr();
+		let mut zo2=FP2::new_copy(&Q.z); zo2.sqr();
+		let mut zs3=FP2::new_copy(&zs2); zs3.mul(&mut self.z);
+		let mut zo3=FP2::new_copy(&zo2); zo3.mul(&mut Q.z);
+		zs2.mul(&mut Q.x);
+		zo2.mul(&mut self.x);
+		if !zs2.equals(&mut zo2) {return false}
+		zs3.mul(&mut Q.y);
+		zo3.mul(&mut self.y);
+		if !zs3.equals(&mut zo3) {return false}
+
+		return true;
+	}
+
+/* set to Affine - (x,y,z) to (x,y) */
+	pub fn affine(&mut self) {
+		if self.is_infinity() {return}
+		let mut one=FP2::new_int(1);
+		if self.z.equals(&mut one) {return}
+		self.z.inverse();
+
+		let mut z2=FP2::new_copy(&self.z);
+		z2.sqr();
+		self.x.mul(&mut z2); self.x.reduce();
+		self.y.mul(&mut z2); 
+		self.y.mul(&mut self.z); self.y.reduce();
+		self.z.copy(&one);
+	}
+
+/* extract affine x as FP2 */
+	pub fn getx(&mut self) -> FP2 {
+		self.affine();
+		return FP2::new_copy(&self.x);
+	}
+
+/* extract affine y as FP2 */
+	pub fn gety(&mut self) -> FP2 {
+		self.affine();
+		return FP2::new_copy(&self.y);
+	}
+
+/* extract projective x */
+	pub fn getpx(&mut self) -> FP2 {
+		return FP2::new_copy(&self.x);
+	}
+/* extract projective y */
+	pub fn getpy(&mut self) -> FP2 {
+		return FP2::new_copy(&self.y);
+	}
+/* extract projective z */
+	pub fn getpz(&mut self) -> FP2 {
+		return FP2::new_copy(&self.z);
+	}
+
+/* convert to byte array */
+	pub fn tobytes(&mut self,b: &mut [u8]) {
+		let mut t:[u8;rom::MODBYTES as usize]=[0;rom::MODBYTES as usize];
+		let mb=rom::MODBYTES as usize;
+
+		self.affine();
+		self.x.geta().tobytes(&mut t);
+		for i in 0..mb { b[i]=t[i]}
+		self.x.getb().tobytes(&mut t);
+		for i in 0..mb { b[i+mb]=t[i]}
+
+		self.y.geta().tobytes(&mut t);
+		for i in 0..mb {b[i+2*mb]=t[i]}
+		self.y.getb().tobytes(&mut t);
+		for i in 0..mb {b[i+3*mb]=t[i]}
+	}
+
+/* convert from byte array to point */
+	pub fn frombytes(b: &[u8]) -> ECP2 {
+		let mut t:[u8;rom::MODBYTES as usize]=[0;rom::MODBYTES as usize];
+		let mb=rom::MODBYTES as usize;
+
+		for i in 0..mb {t[i]=b[i]}
+		let mut ra=BIG::frombytes(&t);
+		for i in 0..mb {t[i]=b[i+mb]}
+		let mut rb=BIG::frombytes(&t);
+		let rx=FP2::new_bigs(&ra,&rb);
+
+		for i in 0..mb {t[i]=b[i+2*mb]}
+		ra.copy(&BIG::frombytes(&t));
+		for i in 0..mb {t[i]=b[i+3*mb]}
+		rb.copy(&BIG::frombytes(&t));
+		let ry=FP2::new_bigs(&ra,&rb);
+
+		return ECP2::new_fp2s(&rx,&ry);
+	}
+
+/* convert this to hex string */
+	pub fn tostring(&mut  self) -> String {
+		if self.is_infinity() {return String::from("infinity")}
+		self.affine();
+		return format!("({},{})",self.x.tostring(),self.y.tostring());
+}
+
+	pub fn to_hex(&self) -> String {
+		let mut ret: String = String::with_capacity(7 * BIG_HEX_STRING_LEN);
+		ret.push_str(&format!("{} {} {} {}", self.inf, self.x.to_hex(), self.y.to_hex(), self.z.to_hex()));
+		return ret;
+	}
+
+	pub fn from_hex_iter(iter: &mut SplitWhitespace) -> ECP2 {
+		let mut ret:ECP2 = ECP2::new();
+		if let Some(x) = iter.next() {
+			ret.inf = x == "true";
+			ret.x = FP2::from_hex_iter(iter);
+			ret.y = FP2::from_hex_iter(iter);
+			ret.z = FP2::from_hex_iter(iter);
+		}
+		return ret;
+	}
+
+	pub fn from_hex(val: String) -> ECP2 {
+		let mut iter = val.split_whitespace();
+		return ECP2::from_hex_iter(&mut iter);
+	}
+
+/* Calculate RHS of twisted curve equation x^3+B/i */
+	pub fn rhs(x:&mut FP2) -> FP2 {
+		x.norm();
+		let mut r=FP2::new_copy(x);
+		r.sqr();
+		let mut b=FP2::new_big(&BIG::new_ints(&rom::CURVE_B));
+		b.div_ip();
+		r.mul(x);
+		r.add(&b);
+
+		r.reduce();
+		return r;
+	}
+
+/* self+=self */
+	pub fn dbl(&mut self) -> isize {
+		if self.inf {return -1}
+		if self.y.iszilch() {
+			self.inf();
+			return -1
+		}
+
+		let mut w1=FP2::new_copy(&self.x);
+		let mut w2=FP2::new();
+		let mut w3=FP2::new_copy(&self.x);
+		let mut w8=FP2::new_copy(&self.x);
+
+		w1.sqr();
+		w8.copy(&w1);
+		w8.imul(3);
+
+		w2.copy(&self.y); w2.sqr();
+		w3.copy(&self.x); w3.mul(&mut w2);
+		w3.imul(4);
+		w1.copy(&w3); w1.neg();
+		w1.norm();
+
+		self.x.copy(&w8); self.x.sqr();
+		self.x.add(&w1);
+		self.x.add(&w1);
+		self.x.norm();
+
+		self.z.mul(&mut self.y);
+		self.z.dbl();
+
+		w2.dbl();
+		w2.sqr();
+		w2.dbl();
+		w3.sub(&self.x);
+		self.y.copy(&w8); self.y.mul(&mut w3);
+		w2.norm();
+		self.y.sub(&w2);
+
+		self.y.norm();
+		self.z.norm();
+
+		return 1;
+	}
+
+/* self+=Q - return 0 for add, 1 for double, -1 for O */
+	pub fn add(&mut self,Q:&mut ECP2) -> isize {
+		if self.inf {
+			self.copy(Q);
+			return -1;
+		}
+		if Q.inf {return -1}
+
+		let mut aff=false;
+
+		if Q.z.isunity() {aff=true}
+
+		let mut a=FP2::new();
+		let mut c=FP2::new();
+		let mut b=FP2::new_copy(&self.z);
+		let mut d=FP2::new_copy(&self.z);
+
+		if !aff {
+			a.copy(&Q.z);
+			c.copy(&Q.z);
+
+			a.sqr(); b.sqr();
+			c.mul(&mut a); d.mul(&mut b);
+
+			a.mul(&mut self.x);
+			c.mul(&mut self.y);
+		} else {
+			a.copy(&self.x);
+			c.copy(&self.y);
+	
+			b.sqr();
+			d.mul(&mut b);
+		}
+
+		b.mul(&mut Q.x); b.sub(&a);
+		d.mul(&mut Q.y); d.sub(&c);
+
+		if b.iszilch() {
+			if d.iszilch() {
+				self.dbl();
+				return 1;
+			} else	{
+				self.inf=true;
+				return -1;
+			}
+		}
+
+		if !aff {self.z.mul(&mut Q.z)}
+		self.z.mul(&mut b);
+
+		let mut e=FP2::new_copy(&b); e.sqr();
+		b.mul(&mut e);
+		a.mul(&mut e);
+
+		e.copy(&a);
+		e.add(&a); e.add(&b);
+		self.x.copy(&d); self.x.sqr(); self.x.sub(&e);
+
+		a.sub(&self.x);
+		self.y.copy(&a); self.y.mul(&mut d);
+		c.mul(&mut b); self.y.sub(&c);
+
+		self.x.norm();
+		self.y.norm();
+		self.z.norm();
+
+		return 0;
+	}
+
+/* set this-=Q */
+	pub fn sub(&mut self,Q :&mut ECP2) -> isize {
+		Q.neg();
+		let d=self.add(Q);
+		Q.neg();
+		return d;
+	}
+
+/* set this*=q, where q is Modulus, using Frobenius */
+	pub fn frob(&mut self,x:&mut FP2) {
+	 	if self.inf {return}
+		let mut x2=FP2::new_copy(x);
+		x2.sqr();
+		self.x.conj();
+		self.y.conj();
+		self.z.conj();
+		self.z.reduce();
+		self.x.mul(&mut x2);
+		self.y.mul(&mut x2);
+		self.y.mul(x);
+	}
+
+/* normalises m-array of ECP2 points. Requires work vector of m FP2s */
+
+	pub fn multiaffine(P: &mut [ECP2]) {
+		let mut t1=FP2::new();
+		let mut t2=FP2::new();
+
+		let mut work:[FP2;8]=[FP2::new(),FP2::new(),FP2::new(),FP2::new(),FP2::new(),FP2::new(),FP2::new(),FP2::new()];
+		let m=8;
+
+		work[0].one();
+		work[1].copy(&P[0].z);
+
+		for i in 2..m {
+			t1.copy(&work[i-1]);
+			work[i].copy(&t1);
+			work[i].mul(&mut P[i-1].z)
+		}
+
+		t1.copy(&work[m-1]); 
+		t1.mul(&mut P[m-1].z);
+		t1.inverse();
+		t2.copy(&P[m-1].z);
+		work[m-1].mul(&mut t1);
+
+		let mut i=m-2;
+
+		loop {
+			if i==0 {
+				work[0].copy(&t1);
+				work[0].mul(&mut t2);
+				break;
+			}
+			work[i].mul(&mut t2);
+			work[i].mul(&mut t1);
+			t2.mul(&mut P[i].z);
+			i-=1;
+		}
+/* now work[] contains inverses of all Z coordinates */
+
+		for i in 0..m {
+			P[i].z.one();
+			t1.copy(&work[i]); t1.sqr();
+			P[i].x.mul(&mut t1);
+			t1.mul(&mut work[i]);
+			P[i].y.mul(&mut t1);
+		}    
+	}
+
+/* self*=e */
+	pub fn mul(&mut self,e: &BIG) -> ECP2 {
+/* fixed size windows */
+		let mut mt=BIG::new();
+		let mut t=BIG::new();
+		let mut P=ECP2::new();
+		let mut Q=ECP2::new();
+		let mut C=ECP2::new();
+
+		if self.is_infinity() {return P}
+
+		let mut W:[ECP2;8]=[ECP2::new(),ECP2::new(),ECP2::new(),ECP2::new(),ECP2::new(),ECP2::new(),ECP2::new(),ECP2::new()];
+
+		const CT:usize=1+(rom::NLEN*(rom::BASEBITS as usize)+3)/4;
+		let mut w:[i8;CT]=[0;CT]; 
+
+		self.affine();
+
+/* precompute table */
+		Q.copy(&self);
+		Q.dbl();
+		
+		W[0].copy(&self);
+
+		for i in 1..8 {
+			C.copy(&W[i-1]);
+			W[i].copy(&C);
+			W[i].add(&mut Q);
+		}
+
+/* convert the table to affine */
+
+		ECP2::multiaffine(&mut W);
+
+/* make exponent odd - add 2P if even, P if odd */
+		t.copy(&e);
+		let s=t.parity();
+		t.inc(1); t.norm(); let ns=t.parity(); mt.copy(&t); mt.inc(1); mt.norm();
+		t.cmove(&mt,s);
+		Q.cmove(&self,ns);
+		C.copy(&Q);
+
+		let nb=1+(t.nbits()+3)/4;
+
+/* convert exponent to signed 4-bit window */
+		for i in 0..nb {
+			w[i]=(t.lastbits(5)-16) as i8;
+			t.dec(w[i] as isize); t.norm();
+			t.fshr(4);	
+		}
+		w[nb]=(t.lastbits(5)) as i8;
+		
+		P.copy(&W[((w[nb] as usize) -1)/2]);
+		for i in (0..nb).rev() {
+			Q.selector(&W,w[i] as i32);
+			P.dbl();
+			P.dbl();
+			P.dbl();
+			P.dbl();
+			P.add(&mut Q);
+		}
+		P.sub(&mut C);
+		P.affine();
+		return P;
+	}
+
+/* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3 */
+	pub fn mul4(Q: &mut [ECP2],u: &[BIG]) -> ECP2 {
+		let mut a:[i8;4]=[0;4];
+		let mut T=ECP2::new();
+		let mut C=ECP2::new();
+		let mut P=ECP2::new();
+
+		let mut W:[ECP2;8]=[ECP2::new(),ECP2::new(),ECP2::new(),ECP2::new(),ECP2::new(),ECP2::new(),ECP2::new(),ECP2::new()];
+
+		let mut mt=BIG::new();
+
+		let mut t:[BIG;4]=[BIG::new_copy(&u[0]),BIG::new_copy(&u[1]),BIG::new_copy(&u[2]),BIG::new_copy(&u[3])];
+
+		const CT:usize=1+rom::NLEN*(rom::BASEBITS as usize);
+		let mut w:[i8;CT]=[0;CT];
+
+		for i in 0..4 {
+			Q[i].affine();
+		}
+
+/* precompute table */
+
+		W[0].copy(&Q[0]); W[0].sub(&mut Q[1]);
+		C.copy(&W[0]); W[1].copy(&C);
+		W[2].copy(&C);
+		W[3].copy(&C);
+		W[4].copy(&Q[0]); W[4].add(&mut Q[1]);
+		C.copy(&W[4]); W[5].copy(&C);
+		W[6].copy(&C);
+		W[7].copy(&C);
+
+		T.copy(&Q[2]); T.sub(&mut Q[3]);
+		W[1].sub(&mut T);
+		W[2].add(&mut T);
+		W[5].sub(&mut T);
+		W[6].add(&mut T);
+		T.copy(&Q[2]); T.add(&mut Q[3]);
+		W[0].sub(&mut T);
+		W[3].add(&mut T);
+		W[4].sub(&mut T);
+		W[7].add(&mut T);
+
+		ECP2::multiaffine(&mut W);
+
+/* if multiplier is even add 1 to multiplier, and add P to correction */
+		mt.zero(); C.inf();
+		for i in 0..4 {
+			if t[i].parity()==0 {
+				t[i].inc(1); t[i].norm();
+				C.add(&mut Q[i]);
+			}
+			mt.add(&t[i]); mt.norm();
+		}
+
+		let nb=1+mt.nbits();
+
+/* convert exponent to signed 1-bit window */
+		for j in 0..nb {
+			for i in 0..4 {
+				a[i]=(t[i].lastbits(2)-2) as i8;
+				t[i].dec(a[i] as isize); t[i].norm();
+				t[i].fshr(1);
+			}
+			w[j]=8*a[0]+4*a[1]+2*a[2]+a[3];
+		}
+		w[nb]=(8*t[0].lastbits(2)+4*t[1].lastbits(2)+2*t[2].lastbits(2)+t[3].lastbits(2)) as i8;
+
+		P.copy(&W[((w[nb] as usize)-1)/2]);  
+		for i in (0..nb).rev() {
+			T.selector(&W,w[i] as i32);
+			P.dbl();
+			P.add(&mut T);
+		}
+		P.sub(&mut C); /* apply correction */
+
+		P.affine();
+		return P;
+	}
+
+}
+/*
+fn main()
+{
+	let mut r=BIG::new_ints(&rom::MODULUS);
+
+	let pxa=BIG::new_ints(&rom::CURVE_PXA);
+	let pxb=BIG::new_ints(&rom::CURVE_PXB);
+	let pya=BIG::new_ints(&rom::CURVE_PYA);
+	let pyb=BIG::new_ints(&rom::CURVE_PYB);
+
+	let fra=BIG::new_ints(&rom::CURVE_FRA);
+	let frb=BIG::new_ints(&rom::CURVE_FRB);
+
+	let mut f=FP2::new_bigs(&fra,&frb);
+
+	let px=FP2::new_bigs(&pxa,&pxb);
+	let py=FP2::new_bigs(&pya,&pyb);
+
+	let mut P=ECP2::new_fp2s(&px,&py);
+
+	println!("P= {}",P.tostring());
+
+	P=P.mul(&mut r);
+	println!("P= {}",P.tostring());
+
+	let mut  Q=ECP2::new_fp2s(&px,&py);
+	Q.frob(&mut f);
+	println!("Q= {}",Q.tostring());
+}
+*/
diff --git a/version22/rust/src/ff.rs b/version22/rust/src/ff.rs
new file mode 100644
index 0000000..d59525f
--- /dev/null
+++ b/version22/rust/src/ff.rs
@@ -0,0 +1,944 @@
+/*
+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
+if debug {println!("sf2= {}",self.tostring())}	
+  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.
+*/
+
+//#[derive(Copy, Clone)]
+pub struct FF {
+	v:Vec<BIG>,
+	length:usize
+}
+
+//mod big;
+use big::BIG;
+//mod dbig;
+//use dbig::DBIG;
+//mod rom;
+use rom;
+use rom::Chunk;
+//mod rand;
+use rand::RAND;
+//mod hash256;
+//use std::process;
+
+
+//static mut debug:bool=false;
+
+impl FF { 
+
+/* Constructors */
+	pub fn new_int(n:usize) -> FF {
+		let mut f=FF{v:Vec::new(),length:0};
+		for _ in 0..n {
+			f.v.push(BIG::new());
+		}
+		f.length=n;
+		return f;
+	}
+/*
+	pub fn new_ints(x: &[&[i32];rom::NLEN],n: usize) -> FF {
+		let mut f=FF{v:Vec::new(),length:0};
+		for i in 0..n {
+			f.v.push(BIG::new_ints(x[i]));
+		}
+		f.length=n;
+		return f;
+	}
+*/
+	pub fn zero(&mut self) {
+		for i in 0..self.length {
+			self.v[i].zero();
+		}
+	}
+
+	pub fn getlen(&self) -> usize {
+		return self.length;
+	}
+
+/* set to integer */
+	pub fn set(&mut self,m:isize) {
+		self.zero();
+		self.v[0].set(0,m as Chunk);
+	}
+
+/* copy from FF b */
+	pub fn copy(&mut self,b: &FF) {
+		for i in 0..self.length {
+			self.v[i].copy(&b.v[i]);
+	 	}
+ 	}
+
+/* x=y<<n */
+	pub fn dsucopy(&mut self,b: &FF) {
+		for i in 0..b.length {
+			self.v[b.length+i].copy(&b.v[i]);
+			self.v[i].zero();
+		}
+	}
+
+/* x=y */
+	pub fn dscopy(&mut self,b: &FF) {
+		for i in 0..b.length {
+			self.v[i].copy(&b.v[i]);
+			self.v[b.length+i].zero();
+		}
+	}
+
+/* x=y>>n */
+	pub fn sducopy(&mut self,b: &FF) {
+		for i in 0..self.length {
+			self.v[i].copy(&b.v[self.length+i]);
+		}
+	}
+
+	pub fn one(&mut self) {
+		self.v[0].one();
+		for i in 1..self.length {
+			self.v[i].zero();
+		}
+	}
+
+/* test equals 0 */
+	pub fn iszilch(&mut self) -> bool {
+		for i in 0..self.length {
+			if !self.v[i].iszilch() {return false}
+		}
+		return true;
+	}
+
+/* shift right by BIGBITS-bit words */
+	pub fn shrw(&mut self,n: usize) {
+    	let mut t= BIG::new(); 
+		for i in 0..n {
+			t.copy(&self.v[i+n]);
+			self.v[i].copy(&t);
+			self.v[i+n].zero();
+		}
+	}
+
+/* shift left by BIGBITS-bit words */
+	pub fn shlw(&mut self,n: usize) {
+    	let mut t= BIG::new(); 		
+		for i in 0..n {
+			t.copy(&self.v[i]);
+			self.v[n+i].copy(&t);
+			self.v[i].zero();
+		}
+	}
+
+/* extract last bit */
+	pub fn parity(&self) -> isize {
+		return self.v[0].parity();
+	}
+
+	pub fn lastbits(&mut self,m: usize) -> isize {
+		return self.v[0].lastbits(m);
+	}
+
+/* compare x and y - must be normalised, and of same length */
+	pub fn comp(a: &FF,b: &FF) -> isize {
+		let mut i=a.length-1;
+
+		loop {
+			let j=BIG::comp(&a.v[i],&b.v[i]);
+			if j!=0 {return j}
+			if i==0 {break;}
+			i-=1;
+		}
+		return 0;
+	}	
+
+/* recursive add */
+	pub fn radd(&mut self,vp: usize,x: &FF,xp: usize,y: &FF,yp: usize,n: usize) {
+		for i in 0..n {
+			self.v[vp+i].copy(&x.v[xp+i]);
+			self.v[vp+i].add(&y.v[yp+i]);
+		}
+	}	
+
+/* recursive inc */
+	pub fn rinc(&mut self,vp: usize,y: &FF,yp: usize,n: usize) {
+		for i in 0..n {
+			self.v[vp+i].add(&y.v[yp+i]);
+		}
+	}
+
+	pub fn rsinc(&mut self,n: usize) {
+		let mut t=BIG::new();
+		for i in 0..n {
+			t.copy(&self.v[i]);
+			self.v[n+i].add(&t);
+		}		
+	}
+
+/* recursive sub */
+	pub fn rsub(&mut self,vp: usize,x: &FF,xp: usize,y: &FF,yp: usize,n: usize) {
+		for i in 0..n {
+			self.v[vp+i].copy(&x.v[xp+i]);
+			self.v[vp+i].sub(&y.v[yp+i]);
+		}
+	}
+
+/* recursive dec */
+	pub fn rdec(&mut self,vp: usize,y: &FF,yp: usize,n: usize) {
+		for i in 0..n {
+			self.v[vp+i].sub(&y.v[yp+i]);
+		}
+	}
+
+/* simple add */
+	pub fn add(&mut self,b: &FF) {
+		for i in 0..self.length {
+			self.v[i].add(&b.v[i]);
+		}
+	}
+
+/* simple sub */
+	pub fn sub(&mut self,b: &FF) {
+		for i in 0..self.length {
+			self.v[i].sub(&b.v[i]);
+		}
+	}
+	
+/* reverse sub */
+	pub fn revsub(&mut self,b: &FF) {
+		for i in 0..self.length {
+			self.v[i].rsub(&b.v[i]);
+		}
+	}
+
+/* normalise - but hold any overflow in top part unless n<0 */
+	pub fn rnorm(&mut self,vp: usize,n: isize) {
+		let mut trunc=false;
+		let mut carry:Chunk;
+		let mut nn:usize=n as usize; 
+		if n<0 { /* -v n signals to do truncation */
+			nn=(-n) as usize;
+			trunc=true;
+		}
+		for i in 0..nn-1 {
+			carry=self.v[vp+i].norm();
+			self.v[vp+i].xortop(carry<<rom::P_TBITS);
+			self.v[vp+i+1].w[0]+=carry; //incl(carry);
+		}
+		carry=self.v[vp+nn-1].norm();
+		if trunc {
+			self.v[vp+nn-1].xortop(carry<<rom::P_TBITS);
+		}
+	}
+
+	pub fn norm(&mut self) {
+		let n:isize=self.length as isize;
+		self.rnorm(0,n);
+	}
+
+/* increment/decrement by a small integer */
+	pub fn inc(&mut self,m: isize) {
+		self.v[0].inc(m);
+		self.norm();
+	}
+
+	pub fn dec(&mut self,m: isize) {
+		self.v[0].dec(m);
+		self.norm();
+	}
+
+/* shift left by one bit */
+	pub fn shl(&mut self) {
+		let mut delay_carry:isize=0;
+		for i in 0..self.length-1 {
+			let carry=self.v[i].fshl(1);
+			self.v[i].inc(delay_carry);
+			self.v[i].xortop((carry as Chunk)<<rom::P_TBITS);
+			delay_carry=carry;
+		}
+		self.v[self.length-1].fshl(1);
+		self.v[self.length-1].inc(delay_carry);
+	}
+
+/* shift right by one bit */
+
+	pub fn shr(&mut self) {
+		let mut i=self.length-1;
+		while i>0 {
+			let carry=self.v[i].fshr(1);
+			self.v[i-1].xortop((carry as Chunk)<<rom::P_TBITS);
+			i-=1;
+		}
+		self.v[0].fshr(1);
+	}
+
+/* Convert to Hex String */
+	pub fn tostring(&mut self) -> String {
+		self.norm();
+		let mut s = String::new();
+		let mut i:usize=self.length-1;
+		loop {
+			s=s+self.v[i].tostring().as_ref();
+			if i==0 {break}
+			i-=1;
+		}
+		return s;
+	}
+
+/* Convert to Hex String 
+	pub fn tostr(&mut self,n:usize) -> String {
+		let mut t=FF::new_int(n);
+		for i in 0..n {
+			t.v[i].copy(&self.v[i]);
+		}
+		t.norm();
+		let mut s = String::new();
+		let mut i:usize=t.length-1;
+		loop {
+			s=s+t.v[i].tostring().as_ref();
+			if i==0 {break}
+			i-=1;
+		}
+		return s;
+	}*/
+
+/* Convert FFs to/from byte arrays */
+	pub fn tobytes(&mut self,b: &mut [u8]) {
+		for i in 0..self.length {
+			self.v[i].tobytearray(b,(self.length-i-1)*(rom::MODBYTES as usize))
+		}
+	}
+
+	pub fn frombytes(x: &mut FF,b: &[u8]) {
+		for i in 0..x.length {
+			x.v[i]=BIG::frombytearray(b,(x.length-i-1)*(rom::MODBYTES as usize))
+		}
+	}
+
+/* in-place swapping using xor - side channel resistant - lengths must be the same */
+	pub fn cswap(a: &mut FF,b: &mut FF,d: isize) {
+		for i in 0..a.length {
+			a.v[i].cswap(&mut b.v[i],d);
+		}
+	}
+
+/* z=x*y, t is workspace */
+	fn karmul(&mut self,vp: usize,x: &FF,xp: usize,y: &FF,yp: usize,t: *mut FF,tp: usize,n: usize) {
+		if n==1 {
+			let mut d=BIG::mul(&x.v[xp],&y.v[yp]);
+			self.v[vp+1]=d.split(8*rom::MODBYTES);
+			self.v[vp].dcopy(&d);
+			return;
+		}
+		let nd2=n/2;
+		self.radd(vp,x,xp,x,xp+nd2,nd2);
+		self.rnorm(vp,nd2 as isize);       /* Important - required for 32-bit build */
+		self.radd(vp+nd2,y,yp,y,yp+nd2,nd2);
+		self.rnorm(vp+nd2,nd2 as isize);    /* Important - required for 32-bit build */
+		unsafe{
+			(*t).karmul(tp,self,vp,self,vp+nd2,t,tp+n,nd2);
+		}
+		self.karmul(vp,x,xp,y,yp,t,tp+n,nd2);
+		self.karmul(vp+n,x,xp+nd2,y,yp+nd2,t,tp+n,nd2);
+		unsafe {
+			(*t).rdec(tp,self,vp,n);
+			(*t).rdec(tp,self,vp+n,n);
+			self.rinc(vp+nd2,&(*t),tp,n);
+		}
+		self.rnorm(vp,(2*n) as isize);
+	}
+
+	fn karsqr(&mut self,vp: usize,x: &FF,xp: usize,t: *mut FF,tp: usize,n: usize) {
+		if n==1 {
+			let mut d=BIG::sqr(&x.v[xp]);
+			self.v[vp+1].copy(&d.split(8*rom::MODBYTES));
+			self.v[vp].dcopy(&d);
+			return;
+		}	
+
+		let nd2=n/2;
+		self.karsqr(vp,x,xp,t,tp+n,nd2);
+		self.karsqr(vp+n,x,xp+nd2,t,tp+n,nd2);
+		unsafe {
+			(*t).karmul(tp,x,xp,x,xp+nd2,t,tp+n,nd2);
+			self.rinc(vp+nd2,&(*t),tp,n);
+			self.rinc(vp+nd2,&(*t),tp,n);
+		}
+		self.rnorm(vp+nd2,n as isize);
+	}
+
+/* Calculates Least Significant bottom half of x*y */
+	fn karmul_lower(&mut self,vp: usize,x: &FF,xp: usize,y: &FF,yp: usize,t: *mut FF,tp: usize,n: usize) { 
+		if n==1 { /* only calculate bottom half of product */
+			self.v[vp].copy(&BIG::smul(&x.v[xp],&y.v[yp]));
+			return;
+		}
+		let nd2=n/2;
+
+		self.karmul(vp,x,xp,y,yp,t,tp+n,nd2);
+		unsafe {
+			(*t).karmul_lower(tp,x,xp+nd2,y,yp,t,tp+n,nd2);
+			self.rinc(vp+nd2,&(*t),tp,nd2);
+			(*t).karmul_lower(tp,x,xp,y,yp+nd2,t,tp+n,nd2);
+			self.rinc(vp+nd2,&(*t),tp,nd2);
+		}
+		let sn:isize=nd2 as isize;
+		self.rnorm(vp+nd2,-sn);  /* truncate it */
+	}
+
+/* Calculates Most Significant upper half of x*y, given lower part */
+	fn karmul_upper(&mut self,x: &FF,y: &FF,t: *mut FF,n: usize) { 
+		let nd2=n/2;
+		self.radd(n,x,0,x,nd2,nd2);
+		self.radd(n+nd2,y,0,y,nd2,nd2);
+		self.rnorm(n,nd2 as isize);
+		self.rnorm(n+nd2,nd2 as isize);
+
+		unsafe {			
+			(*t).karmul(0,self,n+nd2,self,n,t,n,nd2);  /* t = (a0+a1)(b0+b1) */
+
+		}
+		self.karmul(n,x,nd2,y,nd2,t,n,nd2); /* z[n]= a1*b1 */
+					/* z[0-nd2]=l(a0b0) z[nd2-n]= h(a0b0)+l(t)-l(a0b0)-l(a1b1) */
+		unsafe {
+			(*t).rdec(0,self,n,n);              /* t=t-a1b1  */										
+			self.rsinc(nd2);  /* z[nd2-n]+=l(a0b0) = h(a0b0)+l(t)-l(a1b1)  */
+			self.rdec(nd2,&(*t),0,nd2);   /* z[nd2-n]=h(a0b0)+l(t)-l(a1b1)-l(t-a1b1)=h(a0b0) */			
+		}
+
+		let sn:isize=n as isize;
+		self.rnorm(0,-sn);		/* a0b0 now in z - truncate it */
+		unsafe {
+			(*t).rdec(0,self,0,n);         /* (a0+a1)(b0+b1) - a0b0 */
+			self.rinc(nd2,&(*t),0,n);
+		}
+		self.rnorm(nd2,sn);
+	}
+
+/* z=x*y. Assumes x and y are of same length. */
+	pub fn mul(x: &FF,y: &FF) -> FF {
+		let n=x.length;
+		let mut z=FF::new_int(2*n);
+		let mut t=FF::new_int(2*n);
+	//	x.norm(); y.norm();
+		z.karmul(0,&x,0,&y,0,&mut t,0,n);
+		return z;
+	}
+
+/* return low part of product this*y */
+	pub fn lmul(&mut self,y: &FF) {
+		let n=self.length;
+		let mut t=FF::new_int(2*n);
+		let mut x=FF::new_int(n); x.copy(&self);
+	//	x.norm(); y.norm();		
+		self.karmul_lower(0,&x,0,&y,0,&mut t,0,n);
+	}
+
+/* Set b=b mod c */
+	pub fn rmod(&mut self,m: &FF) {
+		let mut k=1;  
+		let n=m.length;
+		let mut c=FF::new_int(n); c.copy(m);
+
+		self.norm();
+		if FF::comp(&self,&c)<0 {return}
+
+		c.shl();
+		while FF::comp(&self,&c)>=0 {
+			c.shl();
+			k+=1;
+		}
+
+		while k>0 {
+			c.shr();
+			if FF::comp(&self,&c)>=0 {
+				self.sub(&c);
+				self.norm();
+			}
+			k-=1;
+		}
+	}
+
+/* z=x^2 */
+	pub fn sqr(x: &FF) -> FF {
+		let n=x.length;
+		let mut z=FF::new_int(2*n);
+		let mut t=FF::new_int(2*n);
+	//	x.norm();
+		z.karsqr(0,&x,0,&mut t,0,n);
+		return z;
+	}
+
+/* return This mod modulus, ms is modulus, md is Montgomery Constant */
+	pub fn reduce(&mut self,ms: &FF,md: &FF) -> FF { /* fast karatsuba Montgomery reduction */
+		let n=ms.length;
+		let mut t=FF::new_int(2*n);
+		let mut r=FF::new_int(n);
+		let mut m=FF::new_int(n);
+
+		r.sducopy(&self);
+		m.karmul_lower(0,&self,0,&md,0,&mut t,0,n);
+		self.karmul_upper(&ms,&m,&mut t,n);
+	
+		m.sducopy(self);
+		r.add(&ms);	
+		r.sub(&m);	
+		r.norm();
+
+		return r;
+	}
+
+/* Set r=this mod b */
+/* this is of length - 2*n */
+/* r,b is of length - n */
+	pub fn dmod(&mut self,b: &FF) -> FF {
+		let n=b.length;
+		let mut m=FF::new_int(2*n);
+		let mut x=FF::new_int(2*n);
+		let mut r=FF::new_int(n);
+
+		x.copy(&self);
+		x.norm();
+		m.dsucopy(&b); let mut k=rom::BIGBITS*n;
+
+		while FF::comp(&x,&m)>=0 {
+			x.sub(&m);
+			x.norm();
+		}
+
+		while k>0 {	
+			m.shr();
+
+			if FF::comp(&x,&m)>=0 {
+				x.sub(&m);
+				x.norm();
+			}
+			k-=1;
+		}
+
+		r.copy(&x);
+		r.rmod(b);
+		return r;
+	}
+
+/* Set return=1/this mod p. Binary method - a<p on entry */
+
+	pub fn invmodp(&mut self,p: &FF) {
+		let n=p.length;
+
+		let mut u=FF::new_int(n);
+		let mut v=FF::new_int(n);
+		let mut x1=FF::new_int(n);
+		let mut x2=FF::new_int(n);
+		let mut t=FF::new_int(n);
+		let mut one=FF::new_int(n);
+
+		one.one();
+		u.copy(&self);
+		v.copy(&p);
+		x1.copy(&one);
+		x2.zero();
+
+	// reduce n in here as well! 
+		while FF::comp(&u,&one)!=0 && FF::comp(&v,&one)!=0 {
+			while u.parity()==0 {
+				u.shr();
+				if x1.parity()!=0 {
+					x1.add(&p);
+					x1.norm();
+				}
+				x1.shr();
+			}
+			while v.parity()==0 {
+				v.shr(); 
+				if x2.parity()!=0 {
+					x2.add(&p);
+					x2.norm();
+				}
+				x2.shr();
+			}
+			if FF::comp(&u,&v)>=0 {
+				u.sub(&v);
+				u.norm();
+				if FF::comp(&x1,&x2)>=0 {
+					x1.sub(&x2);
+				} else {
+					t.copy(&p);
+					t.sub(&x2);
+					x1.add(&t);
+				}
+				x1.norm();
+			} else {
+				v.sub(&u);
+				v.norm();
+				if FF::comp(&x2,&x1)>=0 { 
+					x2.sub(&x1);
+				} else {
+					t.copy(&p);
+					t.sub(&x1);
+					x2.add(&t);
+				}
+				x2.norm();
+			}
+		}
+		if FF::comp(&u,&one)==0 {
+			self.copy(&x1);
+		} else {
+			self.copy(&x2);
+		}
+	}
+
+/* nresidue mod m */
+	pub fn nres(&mut self,m: &FF) {
+		let n=m.length;
+		let mut d=FF::new_int(2*n);
+		d.dsucopy(&self);
+		self.copy(&d.dmod(m));
+	}
+
+	pub fn redc(&mut self,m: &FF,md: &FF) {
+		let n=m.length;
+		let mut d=FF::new_int(2*n);
+		self.rmod(m);
+		d.dscopy(&self);
+		self.copy(&d.reduce(&m,&md));
+		self.rmod(m);
+	}
+
+	pub fn mod2m(&mut self,m: usize) {
+	 	for i in m..self.length {
+			self.v[i].zero()
+		}
+	}
+
+/* U=1/a mod 2^m - Arazi & Qi */
+	pub fn invmod2m(&self) -> FF {
+		let n=self.length;
+
+		let mut b=FF::new_int(n);
+		let mut c=FF::new_int(n);
+		let mut u=FF::new_int(n);
+
+		u.zero();
+		u.v[0].copy(&self.v[0]);
+		u.v[0].invmod2m();
+
+		let mut i=1;
+		while i<n {
+			b.copy(&self); b.mod2m(i);
+			let mut t=FF::mul(&u,&b); t.shrw(i); b.copy(&t);
+			c.copy(&self); c.shrw(i); c.mod2m(i);
+			c.lmul(&u); c.mod2m(i);
+
+			b.add(&c); b.norm();
+			b.lmul(&u); b.mod2m(i);
+
+			c.one(); c.shlw(i); b.revsub(&c); b.norm();
+			b.shlw(i);
+			u.add(&b);
+			i<<=1;
+		}
+		u.norm();
+		return u;
+	}	
+
+	pub fn random(&mut self,rng: &mut RAND) {
+		let n=self.length;
+		for i in 0..n {
+			self.v[i].copy(&BIG::random(rng))
+		}
+	/* make sure top bit is 1 */
+		while self.v[n-1].nbits()<(rom::MODBYTES as usize)*8 {
+			self.v[n-1].copy(&BIG::random(rng));
+		}
+	}
+
+/* generate random x less than p */
+	pub fn randomnum(&mut self,p: &FF,rng: &mut RAND) {
+		let n=self.length;
+		let mut d=FF::new_int(2*n);
+
+		for i in 0..2*n {
+			d.v[i].copy(&BIG::random(rng));
+		}
+		self.copy(&d.dmod(p));
+	}
+
+/* this*=y mod p */
+	pub fn modmul(&mut self,y: &FF,p: &FF,nd: &FF) {
+		if BIG::ff_pexceed(&self.v[self.length-1],&y.v[y.length-1]) {
+			self.rmod(p)
+		}
+		let mut d=FF::mul(&self,y);
+		self.copy(&d.reduce(p,nd));
+	}
+
+/* this*=y mod p */
+	pub fn modsqr(&mut self,p: &FF,nd: &FF) {
+		if BIG::ff_sexceed(&self.v[self.length-1]) {
+			self.rmod(p);
+		}
+		let mut d=FF::sqr(&self);
+		d.norm();
+		self.copy(&d.reduce(p,nd));
+	}
+
+/* this=this^e mod p using side-channel resistant Montgomery Ladder, for large e */
+	pub fn skpow(&mut self,e: &FF,p: &FF) {
+		let n=p.length;
+		let mut r0=FF::new_int(n);
+		let mut r1=FF::new_int(n);
+		let nd=p.invmod2m();
+
+		self.rmod(p);
+		r0.one();
+		r1.copy(&self);
+		r0.nres(p);
+		r1.nres(p);
+
+		let mut i=8*(rom::MODBYTES as usize)*n-1;
+		loop {
+			let b=(e.v[i/(rom::BIGBITS as usize)]).bit(i%(rom::BIGBITS as usize)) as isize;
+			self.copy(&r0);
+			self.modmul(&r1,p,&nd);
+
+			FF::cswap(&mut r0,&mut r1,b);
+			r0.modsqr(p,&nd);
+
+			r1.copy(&self);
+			FF::cswap(&mut r0,&mut r1,b);
+			if i==0 {break}
+			i-=1;
+		}
+		self.copy(&r0);
+		self.redc(p,&nd);
+	}
+
+/* this =this^e mod p using side-channel resistant Montgomery Ladder, for short e */
+	pub fn skpows(&mut self,e: &BIG,p: &FF) {
+		let n=p.length;
+		let mut r0=FF::new_int(n);
+		let mut r1=FF::new_int(n);
+		let nd=p.invmod2m();
+
+		self.rmod(p);
+		r0.one();
+		r1.copy(&self);
+		r0.nres(p);
+		r1.nres(p);
+
+		let mut i=8*(rom::MODBYTES as usize)-1;
+		loop {
+			let b=e.bit(i);
+			self.copy(&r0);
+			self.modmul(&r1,p,&nd);
+
+			FF::cswap(&mut r0,&mut r1,b);
+			r0.modsqr(p,&nd);
+
+			r1.copy(&self);
+			FF::cswap(&mut r0,&mut r1,b);
+			if i==0 {break}
+			i-=1;			
+		}
+		self.copy(&r0);
+		self.redc(p,&nd);
+	}
+
+
+
+
+/* raise to an integer power - right-to-left method */
+	pub fn power(&mut self,e: isize,p: &FF) {
+		let n=p.length;
+		let mut w=FF::new_int(n);
+		let nd=p.invmod2m();
+		let mut f=true;
+		let mut ee=e;
+
+		w.copy(&self);
+		w.nres(p);
+
+		if ee==2 {
+			self.copy(&w);
+			self.modsqr(p,&nd);
+		} else {
+			loop {
+				if ee%2==1 {
+					if f {
+						self.copy(&w);
+					} else {self.modmul(&w,p,&nd)}
+					f=false;
+				}
+				ee>>=1;
+				if ee==0 {break}
+				w.modsqr(p,&nd);	
+			}
+		}
+
+		self.redc(p,&nd);
+	}
+
+/* this=this^e mod p, faster but not side channel resistant */
+	pub fn pow(&mut self,e: &FF,p: &FF) {
+		let n=p.length;
+		let mut w=FF::new_int(n);
+		let nd=p.invmod2m();
+
+		w.copy(&self);
+		self.one();
+		self.nres(p);
+		w.nres(p);
+		let mut i=8*(rom::MODBYTES as usize)*n-1;
+		loop {
+			self.modsqr(p,&nd);
+			let b=(e.v[i/(rom::BIGBITS as usize)]).bit(i%(rom::BIGBITS as usize)) as isize;			
+			if b==1 {self.modmul(&w,p,&nd)}
+			if i==0 {break}
+			i-=1;				
+		}
+		self.redc(p,&nd);
+	}
+
+/* double exponentiation r=x^e.y^f mod p */
+	pub fn pow2(&mut self,e: &BIG,y: &FF,f: &BIG,p: &FF) {
+		let n=p.length;
+		let mut xn=FF::new_int(n);
+		let mut yn=FF::new_int(n);
+		let mut xy=FF::new_int(n);
+		let nd=p.invmod2m();
+
+		xn.copy(&self);
+		yn.copy(y);
+		xn.nres(p);
+		yn.nres(p);
+		xy.copy(&xn); xy.modmul(&yn,p,&nd);
+		self.one();
+		self.nres(p);
+
+		let mut i=8*(rom::MODBYTES as usize)-1;
+		loop {
+			let eb=e.bit(i);
+			let fb=f.bit(i);
+			self.modsqr(p,&nd);
+			if eb==1 {
+				if fb==1 {
+					self.modmul(&xy,p,&nd);
+				} else {self.modmul(&xn,p,&nd)}
+			} else	{
+				if fb==1 {self.modmul(&yn,p,&nd)}
+			}
+			if i==0 {break}
+			i-=1;				
+		}
+		self.redc(p,&nd);
+	}
+
+	pub fn igcd(x: isize,y: isize) -> isize { /* integer GCD, returns GCD of x and y */
+
+		if y==0 {return x}	
+		let mut xx=x;
+		let mut yy=y;		
+		loop {
+			let r=xx%yy;
+			if r==0 {break}
+			xx=yy;yy=r;
+		}
+		return yy;
+	}
+
+/* quick and dirty check for common factor with n */
+	pub fn cfactor(&self,s: isize) -> bool {
+		let n=self.length;
+
+		let mut x=FF::new_int(n);
+		let mut y=FF::new_int(n);
+
+		y.set(s);
+		x.copy(&self);
+		x.norm();
+
+		x.sub(&y);
+		x.norm();
+
+		while !x.iszilch() && x.parity()==0 {x.shr()}
+
+		while FF::comp(&x,&y)>0 {
+			x.sub(&y);
+			x.norm();
+			while !x.iszilch() && x.parity()==0 {x.shr()}
+		}
+
+		let g=x.v[0].get(0) as isize;
+		let r=FF::igcd(s,g);
+		if r>1 {return true}
+		return false
+	}
+
+/* Miller-Rabin test for primality. Slow. */
+	pub fn prime(pp: &FF,rng: &mut RAND) -> bool {
+		let mut s=0;
+		let n=pp.length;
+		let mut d=FF::new_int(n);
+		let mut x=FF::new_int(n);
+		let mut unity=FF::new_int(n);
+		let mut nm1=FF::new_int(n);
+		let mut p=FF::new_int(n); p.copy(pp);
+
+		let sf=4849845; /* 3*5*.. *19 */
+		p.norm();
+
+		if p.cfactor(sf) {return false}
+		unity.one();
+		nm1.copy(&p);
+		nm1.sub(&unity);
+		nm1.norm();
+		d.copy(&nm1);
+
+		while d.parity()==0 {
+			d.shr();
+			s+=1;
+		}
+		if s==0 {return false}
+		for _ in 0..10 {
+			x.randomnum(&p,rng);
+
+			x.pow(&d,&p);
+		
+			if FF::comp(&x,&unity)==0 || FF::comp(&x,&nm1)==0 {continue}
+			let mut looper=false;
+			for _ in 1..s {
+				x.power(2,&p);
+				if FF::comp(&x,&unity)==0 {return false}
+				if FF::comp(&x,&nm1)==0 {looper=true; break}
+			}
+			if looper {continue}
+			return false;
+		}
+
+		return true;
+	}
+
+}
+/*
+fn main()
+{
+	let mut x=FF::new_int(4);
+	let mut y=FF::new_int(4);
+
+	x.one(); y.one();
+	let mut z=FF::mul(&mut x,&mut y);
+
+	println!("z= {}",z.tostring());
+}
+*/
diff --git a/version22/rust/src/fp.rs b/version22/rust/src/fp.rs
new file mode 100644
index 0000000..39104bd
--- /dev/null
+++ b/version22/rust/src/fp.rs
@@ -0,0 +1,354 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use std::fmt;
+use std::str::SplitWhitespace;
+
+#[derive(Copy, Clone)]
+pub struct FP {
+ 	x:BIG
+}
+
+use big::BIG;
+use dbig::DBIG;
+use rom;
+use rom::{Chunk, BIG_HEX_STRING_LEN};
+
+impl fmt::Display for FP {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "FP: [ {} ]", self.x)
+    }
+}
+
+impl fmt::Debug for FP {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "FP: [ {} ]", self.x)
+    }
+}
+
+impl PartialEq for FP {
+    fn eq(&self, other: &FP) -> bool {
+        return self.x == other.x;
+    }
+}
+
+impl FP {
+
+/* Constructors */
+	pub fn new() -> FP {
+		FP {
+				x: BIG::new()
+		}
+	}
+
+	pub fn new_int(a:isize) -> FP {
+		let mut f=FP::new(); 
+		f.x.inc(a);
+		f.nres();
+		return f;		
+	}
+
+	pub fn new_copy(y:&FP) -> FP {
+		let mut f=FP::new(); 
+		f.x.copy(&(y.x));
+		return f;
+	}
+
+	pub fn new_big(y:&BIG) -> FP {
+		let mut f=FP::new(); 
+		f.x.copy(y);
+        f.nres();
+		return f;		
+	}
+
+    pub fn nres(&mut self) {
+        if rom::MODTYPE != rom::PSEUDO_MERSENNE && rom::MODTYPE != rom::GENERALISED_MERSENNE {
+   			let p = BIG::new_ints(&rom::MODULUS);        	
+            let mut d=DBIG::new_scopy(&(self.x));
+            d.shl(rom::NLEN*(rom::BASEBITS as usize));
+            self.x.copy(&d.dmod(&p));
+        }
+    }
+
+/* convert back to regular form */
+    pub fn redc(&mut self) -> BIG {
+        if rom::MODTYPE != rom::PSEUDO_MERSENNE && rom::MODTYPE != rom::GENERALISED_MERSENNE {
+            let mut d=DBIG::new_scopy(&(self.x));
+            return BIG::modulo(&mut d);
+        } else {
+            let r=BIG::new_copy(&(self.x));
+            return r;
+        }
+    }
+
+   /* convert to string */
+	pub fn tostring(&mut self) -> String {
+        let s=self.redc().tostring();
+        return s;
+    }
+
+    pub fn to_hex(&self) -> String {
+        let mut ret: String = String::with_capacity(2 * BIG_HEX_STRING_LEN);
+        ret.push_str(&format!("{}", self.x.to_hex()));
+        return ret;
+    }
+
+    pub fn from_hex_iter(iter: &mut SplitWhitespace) -> FP {
+        FP {
+            x: BIG::from_hex_iter(iter)
+        }
+    }
+
+    pub fn from_hex(val: String) -> FP {
+        let mut iter = val.split_whitespace();
+        return FP::from_hex_iter(&mut iter);
+    }
+
+/* reduce this mod Modulus */
+    pub fn reduce(&mut self) {
+  		let p = BIG::new_ints(&rom::MODULUS);      	
+        self.x.rmod(&p)
+    }
+    
+/* test this=0? */
+    pub fn iszilch(&mut self) -> bool {
+        self.reduce();
+        return self.x.iszilch();
+    }
+    
+/* copy from FP b */
+    pub fn copy(&mut self,b: &FP) {
+        self.x.copy(&(b.x));
+    }
+    
+/* copy from BIG b */
+    pub fn bcopy(&mut self,b: &BIG) {
+        self.x.copy(&b);
+        self.nres();
+    }
+
+/* set this=0 */
+    pub fn zero(&mut self) {
+        self.x.zero();
+    }
+    
+/* set this=1 */
+    pub fn one(&mut self) {
+        self.x.one(); self.nres()
+    }
+    
+/* normalise this */
+    pub fn norm(&mut self) {
+        self.x.norm();
+    }
+/* swap FPs depending on d */
+    pub fn cswap(&mut self,b: &mut FP,d: isize) {
+        self.x.cswap(&mut (b.x),d);
+    }
+    
+/* copy FPs depending on d */
+    pub fn cmove(&mut self,b: &FP,d: isize) {
+        self.x.cmove(&(b.x),d);
+    }
+
+/* this*=b mod Modulus */
+    pub fn mul(&mut self,b: &mut FP)
+    {
+        self.norm();
+        b.norm();
+        if BIG::pexceed(&(self.x),&(b.x)) {self.reduce()}
+
+        let mut d=BIG::mul(&(self.x),&(b.x));
+        self.x.copy(&BIG::modulo(&mut d))
+    }
+
+    fn logb2(w: u32) -> usize {
+        let mut v=w;
+        v |= v >> 1;
+        v |= v >> 2;
+        v |= v >> 4;
+        v |= v >> 8;
+        v |= v >> 16;
+
+        v = v - ((v >> 1) & 0x55555555);                 
+        v = (v & 0x33333333) + ((v >> 2) & 0x33333333);  
+        let r= ((   ((v + (v >> 4)) & 0xF0F0F0F).wrapping_mul(0x1010101)) >> 24) as usize;
+        return r+1;    
+    }
+
+/* this = -this mod Modulus */
+    pub fn neg(&mut self) {
+  		let mut p = BIG::new_ints(&rom::MODULUS);   
+    
+        self.norm();
+
+        let sb=FP::logb2(BIG::excess(&(self.x)) as u32);
+
+    //    let mut ov=BIG::excess(&(self.x));
+    //    let mut sb=1; while ov != 0 {sb += 1;ov>>=1}
+    
+        p.fshl(sb);
+        self.x.rsub(&p);
+    
+        if BIG::excess(&(self.x))>=rom::FEXCESS {self.reduce()}
+    }
+
+    /* this*=c mod Modulus, where c is a small int */
+    pub fn imul(&mut self,c: isize) {
+        let mut cc=c;
+        self.norm();
+        let mut s=false;
+        if cc<0 {
+            cc = -cc;
+            s=true;
+        }
+        let afx=(BIG::excess(&(self.x))+1)*((cc as Chunk)+1)+1;
+        if cc<rom::NEXCESS && afx<rom::FEXCESS {
+            self.x.imul(cc);
+        } else {
+            if afx<rom::FEXCESS {
+            	self.x.pmul(cc);
+            } else {
+  				let p = BIG::new_ints(&rom::MODULUS);               	
+				let mut d=self.x.pxmul(cc);
+				self.x.copy(&d.dmod(&p));
+            }
+        }
+        if s {self.neg()}
+        self.norm();
+    }
+
+/* self*=self mod Modulus */
+    pub fn sqr(&mut self) {
+        self.norm();
+        if BIG::sexceed(&(self.x)) {self.reduce()}
+
+        let mut d=BIG::sqr(&(self.x));
+        self.x.copy(&BIG::modulo(&mut d))
+    }
+
+/* self+=b */
+    pub fn add(&mut self,b: &FP) {
+        self.x.add(&(b.x));
+        if BIG::excess(&(self.x))+2>=rom::FEXCESS {self.reduce()}
+    }
+
+/* self+=self */
+    pub fn dbl(&mut self) {
+        self.x.dbl();
+        if BIG::excess(&(self.x))+2>=rom::FEXCESS {self.reduce()}
+    }
+    
+/* self-=b */
+    pub fn sub(&mut self,b: &FP)
+    {
+        let mut n=FP::new_copy(b);
+        n.neg();
+        self.add(&n);
+    }    
+
+/* self/=2 mod Modulus */
+    pub fn div2(&mut self) {
+        self.x.norm();
+        if self.x.parity()==0 {
+        	self.x.fshr(1);
+        } else {
+  			let p = BIG::new_ints(&rom::MODULUS);           	
+            self.x.add(&p);
+            self.x.norm();
+            self.x.fshr(1);
+        }
+    }
+/* self=1/self mod Modulus */
+    pub fn inverse(&mut self) {
+  		let mut p = BIG::new_ints(&rom::MODULUS);      	
+        let mut r=self.redc();
+        r.invmodp(&mut p);
+        self.x.copy(&r);
+        self.nres();
+    }
+
+/* return TRUE if self==a */
+    pub fn equals(&mut self,a: &mut FP) -> bool {
+        a.reduce();
+        self.reduce();
+        if BIG::comp(&(a.x),(&self.x))==0 {return true}
+        return false;
+    }   
+
+/* return self^e mod Modulus */
+    pub fn pow(&mut self,e: &mut BIG) -> FP {
+      	let p = BIG::new_ints(&rom::MODULUS);   	
+        let mut r=FP::new_int(1);
+        e.norm();
+        self.x.norm();
+		let mut m=FP::new_copy(self);
+        loop {
+            let bt=e.parity();
+            e.fshr(1);
+            if bt==1 {r.mul(&mut m)}
+            if e.iszilch() {break}
+            m.sqr();
+        }
+        r.x.rmod(&p);
+        return r;
+    }
+
+/* return sqrt(this) mod Modulus */
+    pub fn sqrt(&mut self) -> FP {
+        self.reduce();
+      	let mut p = BIG::new_ints(&rom::MODULUS);  
+        if rom::MOD8==5 {
+            p.dec(5); p.norm(); p.shr(3);
+            let mut i=FP::new_copy(self); i.x.shl(1);
+            let mut v=i.pow(&mut p);
+            i.mul(&mut v); i.mul(&mut v);
+            i.x.dec(1);
+            let mut r=FP::new_copy(self);
+            r.mul(&mut v); r.mul(&mut i);
+            r.reduce();
+            return r;
+        }
+        else
+        {
+            p.inc(1); p.norm(); p.shr(2);
+            return self.pow(&mut p);
+        }
+    }
+/* return jacobi symbol (this/Modulus) */
+    pub fn jacobi(&mut self) -> isize
+    {
+     	let mut p = BIG::new_ints(&rom::MODULUS);      	
+        let mut w=self.redc();
+        return w.jacobi(&mut p);
+    }
+
+}
+/*
+fn main() {
+    let p = BIG::new_ints(&rom::MODULUS);  
+	let mut e = BIG::new_copy(&p);
+	e.dec(1);
+
+    let mut x = FP::new_int(3);
+    let mut s=x.pow(&mut e);
+
+    println!("s= {}",s.tostring());
+}
+*/
diff --git a/version22/rust/src/fp12.rs b/version22/rust/src/fp12.rs
new file mode 100644
index 0000000..4610e67
--- /dev/null
+++ b/version22/rust/src/fp12.rs
@@ -0,0 +1,628 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use std::fmt;
+use std::str::SplitWhitespace;
+
+#[derive(Copy, Clone)]
+pub struct FP12 {
+	a:FP4,
+	b:FP4,
+	c:FP4
+}
+
+use rom::BIG_HEX_STRING_LEN;
+
+//mod fp;
+//use fp::FP;
+//mod fp2;
+use fp2::FP2;
+//mod fp4;
+use fp4::FP4;
+//mod big;
+use big::BIG;
+//mod dbig;
+//use dbig::DBIG;
+//mod rand;
+//mod hash256;
+//mod rom;
+use rom;
+
+impl PartialEq for FP12 {
+	fn eq(&self, other: &FP12) -> bool {
+		return (self.a == other.a) &&
+			(self.b == other.b) &&
+			(self.c == other.c);
+	}
+}
+
+impl fmt::Display for FP12 {
+	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+		write!(f, "FP12: [ {}, {}, {} ]", self.a, self.b, self.c)
+	}
+}
+
+impl fmt::Debug for FP12 {
+	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+		write!(f, "FP12: [ {}, {}, {} ]", self.a, self.b, self.c)
+	}
+}
+
+impl FP12 {
+
+	pub fn new() -> FP12 {
+		FP12 {
+				a: FP4::new(),
+				b: FP4::new(),
+				c: FP4::new()
+		}
+	}
+
+	pub fn new_int(a: isize) -> FP12 {
+		let mut f=FP12::new();
+		f.a.copy(&FP4::new_int(a));
+		f.b.zero();
+		f.c.zero();
+		return f;
+	}	
+
+	pub fn new_copy(x: &FP12) -> FP12 {
+		let mut f=FP12::new();
+		f.a.copy(&x.a);
+		f.b.copy(&x.b);
+		f.c.copy(&x.c);
+		return f;
+	}
+
+	pub fn new_fp4s(d: &FP4,e: &FP4,f: &FP4) -> FP12 {
+		let mut g=FP12::new();
+		g.a.copy(d);
+		g.b.copy(e);
+		g.c.copy(f);
+		return g;
+	}	
+
+	pub fn new_fp4(d: &FP4) -> FP12 {
+		let mut g=FP12::new();
+		g.a.copy(d);
+		g.b.zero();
+		g.c.zero();
+		return g;
+	}
+
+/* reduce components mod Modulus */
+	pub fn reduce(&mut self) {
+		self.a.reduce();
+		self.b.reduce();
+		self.c.reduce();
+	}
+
+/* normalise components of w */
+	pub fn norm(&mut self) {
+		self.a.norm();
+		self.b.norm();
+		self.c.norm();
+	}	
+
+/* test self=0 ? */
+	pub fn iszilch(&mut self) -> bool {
+		self.reduce();
+		return self.a.iszilch() && self.b.iszilch() && self.c.iszilch();
+	}	
+
+/* test self=1 ? */
+	pub fn isunity(&mut self) -> bool {
+		let mut one=FP4::new_int(1);
+		return self.a.equals(&mut one) && self.b.iszilch() && self.c.iszilch();
+	}
+
+/* test self=x */
+	pub fn equals(&mut self,x:&mut FP12) -> bool {
+		return self.a.equals(&mut x.a) && self.b.equals(&mut x.b) && self.c.equals(&mut x.c);
+	}
+
+	pub fn geta(&mut self) -> FP4 {
+		let f=FP4::new_copy(&self.a);
+		return f;
+	}
+
+	pub fn getb(&mut self) -> FP4 {
+		let f=FP4::new_copy(&self.b);
+		return f;
+	}
+
+	pub fn getc(&mut self) -> FP4 {
+		let f=FP4::new_copy(&self.c);
+		return f;
+	}	
+
+/* copy self=x */
+	pub fn copy(&mut self,x :&FP12) {
+		self.a.copy(&x.a);
+		self.b.copy(&x.b);
+		self.c.copy(&x.c);
+	}
+
+/* set self=1 */
+	pub fn one(&mut self) {
+		self.a.one();
+		self.b.zero();
+		self.c.zero();
+	}
+
+/* this=conj(this) */
+	pub fn conj(&mut self) {
+		self.a.conj();
+		self.b.nconj();
+		self.c.conj();
+	}
+
+/* Granger-Scott Unitary Squaring */
+	pub fn usqr(&mut self) {
+		let mut a=FP4::new_copy(&self.a);
+		let mut b=FP4::new_copy(&self.c);
+		let mut c=FP4::new_copy(&self.b);
+		let mut d=FP4::new();
+
+		self.a.sqr();
+		d.copy(&self.a); d.add(&self.a);
+		self.a.add(&d);
+
+		self.a.norm();
+		a.nconj();
+
+		a.dbl();
+		self.a.add(&a);
+		b.sqr();
+		b.times_i();
+
+		d.copy(&b); d.add(&b);
+		b.add(&d);
+		b.norm();
+
+		c.sqr();
+		d.copy(&c); d.add(&c);
+		c.add(&d);
+		c.norm();
+
+		self.b.conj();
+		self.b.dbl();
+		self.c.nconj();
+
+		self.c.dbl();
+		self.b.add(&b);
+		self.c.add(&c);
+		self.reduce();
+
+	}
+
+/* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
+	pub fn sqr(&mut self) {
+		let mut a=FP4::new_copy(&self.a);
+		let mut b=FP4::new_copy(&self.b);
+		let mut c=FP4::new_copy(&self.c);
+		let mut d=FP4::new_copy(&self.a);
+
+		a.sqr();
+		b.mul(&mut self.c);
+		b.dbl();
+		c.sqr();
+		d.mul(&mut self.b);
+		d.dbl();
+
+		self.c.add(&self.a);
+		self.c.add(&self.b);
+		self.c.sqr();
+
+		self.a.copy(&a);
+		a.add(&b);
+		a.norm();
+		a.add(&c);
+		a.add(&d);
+		a.norm();
+
+		a.neg();
+		b.times_i();
+		c.times_i();
+
+		self.a.add(&b);
+
+		self.b.copy(&c); self.b.add(&d);
+		self.c.add(&a);
+		self.norm();
+	}
+
+
+/* FP12 full multiplication self=self*y */
+	pub fn mul(&mut self,y: &mut FP12) {
+		let mut z0=FP4::new_copy(&self.a);
+		let mut z1=FP4::new();
+		let mut z2=FP4::new_copy(&mut self.b);
+		let mut z3=FP4::new();
+		let mut t0=FP4::new_copy(&self.a);
+		let mut t1=FP4::new_copy(&y.a);
+
+		z0.mul(&mut y.a);
+		z2.mul(&mut y.b);
+
+		t0.add(&self.b);
+		t1.add(&y.b);
+
+		z1.copy(&t0); z1.mul(&mut t1);
+		t0.copy(&self.b); t0.add(&self.c);
+
+		t1.copy(&y.b); t1.add(&y.c);
+		z3.copy(&t0); z3.mul(&mut t1);
+
+		t0.copy(&z0); t0.neg();
+		t1.copy(&z2); t1.neg();
+
+		z1.add(&t0);
+		z1.norm();
+		self.b.copy(&z1); self.b.add(&t1);
+
+		z3.add(&t1);
+		z2.add(&t0);
+
+		t0.copy(&self.a); t0.add(&self.c);
+		t1.copy(&y.a); t1.add(&y.c);
+		t0.mul(&mut t1);
+		z2.add(&t0);
+
+		t0.copy(&self.c); t0.mul(&mut y.c);
+		t1.copy(&t0); t1.neg();
+
+		z2.norm();
+		z3.norm();
+		self.b.norm();
+
+		self.c.copy(&z2); self.c.add(&t1);
+		z3.add(&t1);
+		t0.times_i();
+		self.b.add(&t0);
+
+		z3.times_i();
+		self.a.copy(&z0); self.a.add(&z3);
+		self.norm();
+	}
+
+/* Special case of multiplication arises from special form of ATE pairing line function */
+	pub fn smul(&mut self,y: &mut FP12) {
+		let mut z0=FP4::new_copy(&self.a);
+		let mut z2=FP4::new_copy(&self.b);
+		let mut z3=FP4::new_copy(&self.b);
+		let mut t0=FP4::new();
+		let mut t1=FP4::new_copy(&y.a);
+		
+		z0.mul(&mut y.a);
+		z2.pmul(&mut y.b.real());
+		self.b.add(&self.a);
+		t1.padd(&y.b.real());
+
+		self.b.mul(&mut t1);
+		z3.add(&self.c);
+		z3.pmul(&mut y.b.real());
+
+		t0.copy(&z0); t0.neg();
+		t1.copy(&z2); t1.neg();
+
+		self.b.add(&t0);
+		self.b.norm();
+
+		self.b.add(&t1);
+		z3.add(&t1);
+		z2.add(&t0);
+
+		t0.copy(&self.a); t0.add(&self.c);
+		t0.mul(&mut y.a);
+		self.c.copy(&z2); self.c.add(&t0);
+
+		z3.times_i();
+		self.a.copy(&z0); self.a.add(&z3);
+
+		self.norm();
+	}
+
+/* self=1/self */
+	pub fn inverse(&mut self) {
+		let mut f0=FP4::new_copy(&self.a);
+		let mut f1=FP4::new_copy(&self.b);
+		let mut f2=FP4::new_copy(&self.a);
+		let mut f3=FP4::new();
+
+		self.norm();
+		f0.sqr();
+		f1.mul(&mut self.c);
+		f1.times_i();
+		f0.sub(&f1);
+
+		f1.copy(&self.c); f1.sqr();
+		f1.times_i();
+		f2.mul(&mut self.b);
+		f1.sub(&f2);
+
+		f2.copy(&self.b); f2.sqr();
+		f3.copy(&self.a); f3.mul(&mut self.c);
+		f2.sub(&f3);
+
+		f3.copy(&self.b); f3.mul(&mut f2);
+		f3.times_i();
+		self.a.mul(&mut f0);
+		f3.add(&self.a);
+		self.c.mul(&mut f1);
+		self.c.times_i();
+
+		f3.add(&self.c);
+		f3.inverse();
+		self.a.copy(&f0); self.a.mul(&mut f3);
+		self.b.copy(&f1); self.b.mul(&mut f3);
+		self.c.copy(&f2); self.c.mul(&mut f3);
+	}
+
+/* self=self^p using Frobenius */
+	pub fn frob(&mut self,f: &mut FP2) {
+		let mut f2=FP2::new_copy(f);
+		let mut f3=FP2::new_copy(f);
+
+		f2.sqr();
+		f3.mul(&mut f2);
+
+		self.a.frob(&mut f3);
+		self.b.frob(&mut f3);
+		self.c.frob(&mut f3);
+
+		self.b.pmul(f);
+		self.c.pmul(&mut f2);
+	}
+
+/* trace function */
+	pub fn trace(&mut self) -> FP4 {
+		let mut t=FP4::new();
+		t.copy(&self.a);
+		t.imul(3);
+		t.reduce();
+		return t;
+	}
+
+/* convert from byte array to FP12 */
+	pub fn frombytes(w: &[u8]) -> FP12 {
+		let mut t:[u8;rom::MODBYTES as usize]=[0;rom::MODBYTES as usize];
+		let mb=rom::MODBYTES as usize;
+
+		for i in 0..mb {t[i]=w[i]}
+		let mut a=BIG::frombytes(&t);
+		for i in 0..mb {t[i]=w[i+mb]}
+		let mut b=BIG::frombytes(&t);
+		let mut c=FP2::new_bigs(&a,&b);
+
+		for i in 0..mb {t[i]=w[i+2*mb]}
+		a=BIG::frombytes(&t);
+		for i in 0..mb {t[i]=w[i+3*mb]}
+		b=BIG::frombytes(&t);
+		let mut d=FP2::new_bigs(&a,&b);
+
+		let e=FP4::new_fp2s(&c,&d);
+
+
+		for i in 0..mb {t[i]=w[i+4*mb]}
+		a=BIG::frombytes(&t);
+		for i in 0..mb {t[i]=w[i+5*mb]}
+		b=BIG::frombytes(&t);
+		c=FP2::new_bigs(&a,&b);
+
+		for i in 0..mb {t[i]=w[i+6*mb]}
+		a=BIG::frombytes(&t);
+		for i in 0..mb {t[i]=w[i+7*mb]}
+		b=BIG::frombytes(&t);
+		d=FP2::new_bigs(&a,&b);
+
+		let f=FP4::new_fp2s(&c,&d);
+
+
+		for i in 0..mb {t[i]=w[i+8*mb]}
+		a=BIG::frombytes(&t);
+		for i in 0..mb {t[i]=w[i+9*mb]}
+		b=BIG::frombytes(&t);
+		
+		c=FP2::new_bigs(&a,&b);
+
+		for i in 0..mb {t[i]=w[i+10*mb]}
+		a=BIG::frombytes(&t);
+		for i in 0..mb {t[i]=w[i+11*mb]}
+		b=BIG::frombytes(&t);
+		d=FP2::new_bigs(&a,&b);
+
+		let g=FP4::new_fp2s(&c,&d);
+
+		return FP12::new_fp4s(&e,&f,&g);
+	}
+
+/* convert this to byte array */
+	pub fn tobytes(&mut self,w: &mut [u8]) {
+		let mut t:[u8;rom::MODBYTES as usize]=[0;rom::MODBYTES as usize];
+		let mb=rom::MODBYTES as usize;
+
+		self.a.geta().geta().tobytes(&mut t);
+		for i in 0..mb {w[i]=t[i]}
+		self.a.geta().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+mb]=t[i]}
+		self.a.getb().geta().tobytes(&mut t);
+		for i in 0..mb {w[i+2*mb]=t[i]}
+		self.a.getb().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+3*mb]=t[i]}
+
+		self.b.geta().geta().tobytes(&mut t);
+		for i in 0..mb {w[i+4*mb]=t[i]}
+		self.b.geta().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+5*mb]=t[i]}
+		self.b.getb().geta().tobytes(&mut t);
+		for i in 0..mb {w[i+6*mb]=t[i]}
+		self.b.getb().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+7*mb]=t[i]}
+
+		self.c.geta().geta().tobytes(&mut t);
+		for i in 0..mb {w[i+8*mb]=t[i]}
+		self.c.geta().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+9*mb]=t[i]}
+		self.c.getb().geta().tobytes(&mut t);
+		for i in 0..mb {w[i+10*mb]=t[i]}
+		self.c.getb().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+11*mb]=t[i]}
+	}
+
+/* output to hex string */
+	pub fn tostring(&mut self) -> String {
+		return format!("[{},{},{}]",self.a.tostring(),self.b.tostring(),self.c.tostring());		
+	}
+
+	pub fn to_hex(&self) -> String {
+		let mut ret: String = String::with_capacity(12 * BIG_HEX_STRING_LEN);
+		ret.push_str(&format!("{} {} {}", self.a.to_hex(), self.b.to_hex(), self.c.to_hex()));
+		return ret;
+	}
+
+	pub fn from_hex_iter(iter: &mut SplitWhitespace) -> FP12 {
+		let mut ret:FP12 = FP12::new();
+		ret.a = FP4::from_hex_iter(iter);
+		ret.b = FP4::from_hex_iter(iter);
+		ret.c = FP4::from_hex_iter(iter);
+		return ret;
+	}
+
+	pub fn from_hex(val: String) -> FP12 {
+		let mut iter = val.split_whitespace();
+		return FP12::from_hex_iter(&mut iter);
+	}
+
+/* self=self^e */
+	pub fn pow(&mut self,e: &mut BIG) -> FP12 {
+		self.norm();
+		e.norm();
+		let mut w=FP12::new_copy(self);
+		let mut z=BIG::new_copy(&e);
+		let mut r=FP12::new_int(1);
+		loop {
+			let bt=z.parity();
+			z.fshr(1);
+			if bt==1 {r.mul(&mut w)};
+			if z.iszilch() {break}
+			w.usqr();
+		}
+		r.reduce();
+		return r;
+	}	
+
+/* constant time powering by small integer of max length bts */
+	pub fn pinpow(&mut self,e: i32,bts: i32) {
+		let mut r:[FP12;2]=[FP12::new_int(1),FP12::new_copy(self)];
+		let mut t=FP12::new();
+
+		for i in (0..bts).rev() {
+			let b:usize=((e>>i)&1) as usize;
+			t.copy(&r[b]);
+			r[1-b].mul(&mut t);
+			r[b].usqr();
+		}
+		self.copy(&r[0]);
+	}
+
+/* p=q0^u0.q1^u1.q2^u2.q3^u3 */
+/* Timing attack secure, but not cache attack secure */
+
+ 	pub fn pow4(q:&mut [FP12],u:&[BIG]) -> FP12 {
+		let mut a:[i8;4]=[0;4];
+		let mut s:[FP12;2]=[FP12::new(),FP12::new()];
+		let mut g:[FP12;8]=[FP12::new(),FP12::new(),FP12::new(),FP12::new(),FP12::new(),FP12::new(),FP12::new(),FP12::new()];
+
+		let mut c=FP12::new_int(1);
+		let mut p=FP12::new();
+		const CT:usize=1+rom::NLEN*(rom::BASEBITS as usize);		
+		let mut w:[i8;CT]=[0;CT];
+
+		let mut mt=BIG::new();
+		let mut t:[BIG;4]=[BIG::new_copy(&u[0]),BIG::new_copy(&u[1]),BIG::new_copy(&u[2]),BIG::new_copy(&u[3])];
+
+		g[0].copy(&q[0]); s[0].copy(&q[1]); s[0].conj(); g[0].mul(&mut s[0]);
+		p.copy(&g[0]);
+		g[1].copy(&p);
+		g[2].copy(&p);
+		g[3].copy(&p);
+		g[4].copy(&q[0]); g[4].mul(&mut q[1]);
+		p.copy(&g[4]);
+		g[5].copy(&p);
+		g[6].copy(&p);
+		g[7].copy(&p);
+
+
+		s[1].copy(&q[2]); s[0].copy(&q[3]); s[0].conj(); p.copy(&s[0]); s[1].mul(&mut p);
+		p.copy(&s[1]); s[0].copy(&p); s[0].conj(); g[1].mul(&mut s[0]);
+		g[2].mul(&mut s[1]);
+		g[5].mul(&mut s[0]);
+		g[6].mul(&mut s[1]);
+		s[1].copy(&q[2]); s[1].mul(&mut q[3]);
+		p.copy(&s[1]); s[0].copy(&p); s[0].conj(); g[0].mul(&mut s[0]);
+		g[3].mul(&mut s[1]);
+		g[4].mul(&mut s[0]);
+		g[7].mul(&mut s[1]);
+
+/* if power is even add 1 to power, and add q to correction */
+
+		for i in 0..4 {
+			if t[i].parity()==0 {
+				t[i].inc(1); t[i].norm();
+				c.mul(&mut q[i]);
+			}
+			mt.add(&t[i]); mt.norm();
+		}
+		c.conj();
+		let nb=1+mt.nbits();
+
+/* convert exponent to signed 1-bit window */
+		for j in 0..nb {
+			for i in 0..4 {
+				a[i]=(t[i].lastbits(2)-2) as i8;
+				t[i].dec(a[i] as isize); t[i].norm();
+				t[i].fshr(1);
+			}
+			w[j]=8*a[0]+4*a[1]+2*a[2]+a[3];
+		}
+		w[nb]=(8*t[0].lastbits(2)+4*t[1].lastbits(2)+2*t[2].lastbits(2)+t[3].lastbits(2)) as i8;
+		p.copy(&g[((w[nb] as usize)-1)/2]);
+
+		for i in (0..nb).rev() {
+			let m=w[i]>>7;
+			let mut j=((w[i]^m)-m) as usize;  /* j=abs(w[i]) */
+			j=(j-1)/2;
+			s[0].copy(&g[j]); s[1].copy(&g[j]); s[1].conj();
+			p.usqr();
+			p.mul(&mut s[(m&1) as usize]);
+		}
+		p.mul(&mut c);  /* apply correction */
+		p.reduce();
+		return p;
+	}
+
+
+}
+/*
+fn main()
+{
+	let mut w=FP12::new();
+}
+*/
diff --git a/version22/rust/src/fp2.rs b/version22/rust/src/fp2.rs
new file mode 100644
index 0000000..7ad62cc
--- /dev/null
+++ b/version22/rust/src/fp2.rs
@@ -0,0 +1,366 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use std::fmt;
+use std::str::SplitWhitespace;
+
+#[derive(Copy, Clone)]
+pub struct FP2 {
+	a:FP,
+	b:FP,
+}
+
+use rom::BIG_HEX_STRING_LEN;
+//mod fp;
+use fp::FP;
+//mod big;
+use big::BIG;
+//mod dbig;
+//use dbig::DBIG;
+//mod rand;
+//mod hash256;
+//mod rom;
+//use rom;
+
+impl fmt::Display for FP2 {
+	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+		write!(f, "FP2: [ {}, {} ]", self.a, self.b)
+	}
+}
+
+impl fmt::Debug for FP2 {
+	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+		write!(f, "FP2: [ {}, {} ]", self.a, self.b)
+	}
+}
+
+impl PartialEq for FP2 {
+	fn eq(&self, other: &FP2) -> bool {
+		return (self.a == other.a) &&
+			(self.b == other.b);
+	}
+}
+
+impl FP2 {
+
+	pub fn new() -> FP2 {
+		FP2 {
+				a: FP::new(),
+				b: FP::new(),
+		}
+	}
+
+	pub fn new_int(a: isize) -> FP2 {
+		let mut f=FP2::new();
+		f.a.copy(&FP::new_int(a));
+		f.b.zero();
+		return f;
+	}	
+
+	pub fn new_copy(x: &FP2) -> FP2 {
+		let mut f=FP2::new();
+		f.a.copy(&x.a);
+		f.b.copy(&x.b);
+		return f
+	}	
+
+	pub fn new_fps(c: &FP,d: &FP) -> FP2 {
+		let mut f=FP2::new();
+		f.a.copy(c);
+		f.b.copy(d);
+		return f;
+	}	
+
+	pub fn new_bigs(c: &BIG,d: &BIG) -> FP2 {
+		let mut f=FP2::new();
+		f.a.copy(&FP::new_big(c));
+		f.b.copy(&FP::new_big(d));
+		return f;
+	}	
+
+	pub fn new_fp(c: &FP) -> FP2 {
+		let mut f=FP2::new();
+		f.a.copy(c);
+		f.b.zero();
+		return f;
+	}	
+
+	pub fn new_big(c: &BIG) -> FP2 {
+		let mut f=FP2::new();
+		f.a.copy(&FP::new_big(c));
+		f.b.zero();
+		return f;
+	}	
+
+/* reduce components mod Modulus */
+	pub fn reduce(&mut self) {
+		self.a.reduce();
+		self.b.reduce();
+	}
+
+/* normalise components of w */
+	pub fn norm(&mut self) {
+		self.a.norm();
+		self.b.norm();
+	}	
+
+/* test self=0 ? */
+	pub fn iszilch(&mut self) -> bool {
+		self.reduce();
+		return self.a.iszilch() && self.b.iszilch();
+	}	
+
+	pub fn cmove(&mut self,g:&FP2,d: isize) {
+		self.a.cmove(&g.a,d);
+		self.b.cmove(&g.b,d);
+	}		
+
+/* test self=1 ? */
+	pub fn isunity(&mut self) -> bool {
+		let mut one=FP::new_int(1);
+		return self.a.equals(&mut one) && self.b.iszilch();
+	}
+
+/* test self=x */
+	pub fn equals(&mut self,x:&mut FP2) -> bool {
+		return self.a.equals(&mut x.a) && self.b.equals(&mut x.b);
+	}
+
+/* extract a */
+	pub fn geta(&mut self) -> BIG { 
+		return self.a.redc();
+	}
+
+/* extract b */
+	pub fn getb(&mut self) -> BIG {
+		return self.b.redc();
+	}
+
+/* copy self=x */
+	pub fn copy(&mut self,x :&FP2) {
+		self.a.copy(&x.a);
+		self.b.copy(&x.b);
+	}
+
+/* set self=0 */
+	pub fn zero(&mut self) {
+		self.a.zero();
+		self.b.zero();
+	}
+
+/* set self=1 */
+	pub fn one(&mut self) {
+		self.a.one();
+		self.b.zero();
+	}	
+
+/* negate self mod Modulus */
+	pub fn neg(&mut self) {
+		self.norm();
+		let mut m=FP::new_copy(&self.a);
+		let mut t=FP::new();
+
+		m.add(&self.b);
+		m.neg();
+		m.norm();
+		t.copy(&m); t.add(&self.b);
+		self.b.copy(&m);
+		self.b.add(&self.a);
+		self.a.copy(&t);
+	}	
+
+/* set to a-ib */
+	pub fn conj(&mut self) {
+		self.b.neg();
+	}
+
+/* self+=a */
+	pub fn add(&mut self,x:&FP2) {
+		self.a.add(&x.a);
+		self.b.add(&x.b);
+	}
+
+	pub fn dbl(&mut self) {
+		self.a.dbl();
+		self.b.dbl();
+	}
+
+/* self-=a */
+	pub fn sub(&mut self,x:&FP2) {
+		let mut m=FP2::new_copy(x);
+		m.neg();
+		self.add(&m);
+	}
+
+/* self*=s, where s is an FP */
+	pub fn pmul(&mut self,s:&mut FP) {
+		self.a.mul(s);
+		self.b.mul(s);
+	}
+
+/* self*=i, where i is an int */
+	pub fn imul(&mut self,c: isize) {
+		self.a.imul(c);
+		self.b.imul(c);
+	}
+
+/* self*=self */
+	pub fn sqr(&mut self) {
+		self.norm();
+		let mut w1=FP::new_copy(&self.a);
+		let mut w3=FP::new_copy(&self.a);
+		let mut mb=FP::new_copy(&self.b);
+
+		w3.mul(&mut self.b);
+		w1.add(&self.b);
+		mb.neg();
+		self.a.add(&mb);
+		self.a.mul(&mut w1);
+		self.b.copy(&w3); self.b.add(&w3);
+
+		self.norm();
+	}	
+
+/* this*=y */
+	pub fn mul(&mut self,y :&mut FP2) {
+		self.norm();  /* This is needed here as {a,b} is not normed before additions */
+
+		let mut w1=FP::new_copy(&self.a);
+		let mut w2=FP::new_copy(&self.b);
+		let mut w5=FP::new_copy(&self.a);
+		let mut mw=FP::new();
+
+		w1.mul(&mut y.a);  // w1=a*y.a  - this norms w1 and y.a, NOT a
+		w2.mul(&mut y.b);  // w2=b*y.b  - this norms w2 and y.b, NOT b
+		w5.add(&self.b);    // w5=a+b
+		self.b.copy(&y.a); self.b.add(&y.b); // b=y.a+y.b
+
+		self.b.mul(&mut w5);
+		mw.copy(&w1); mw.add(&w2); mw.neg();
+
+		self.b.add(&mw); mw.add(&w1);
+		self.a.copy(&w1); self.a.add(&mw);
+
+		self.norm();
+	}
+
+/* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */
+/* returns true if this is QR */
+	pub fn sqrt(&mut self) -> bool {
+		if self.iszilch() {return true}
+		let mut w1=FP::new_copy(&self.b);
+		let mut w2=FP::new_copy(&self.a);
+		w1.sqr(); w2.sqr(); w1.add(&w2);
+		if w1.jacobi()!=1 { self.zero(); return false }
+		w2.copy(&w1.sqrt()); w1.copy(&w2);
+		w2.copy(&self.a); w2.add(&w1); w2.div2();
+		if w2.jacobi()!=1 {
+			w2.copy(&self.a); w2.sub(&w1); w2.div2();
+			if w2.jacobi()!=1 { self.zero(); return false }
+		}
+		w1.copy(&w2.sqrt());
+		self.a.copy(&w1);
+		w1.dbl();
+		w1.inverse();
+		self.b.mul(&mut w1);
+		return true;
+	}
+
+/* output to hex string */
+	pub fn tostring(&mut self) -> String {
+		return format!("[{},{}]",self.a.tostring(),self.b.tostring());		
+	}
+
+	pub fn to_hex(&self) -> String {
+		let mut ret: String = String::with_capacity(2 * BIG_HEX_STRING_LEN);
+		ret.push_str(&format!("{} {}", self.a.to_hex(), self.b.to_hex()));
+		return ret;
+	}
+
+	pub fn from_hex_iter(iter: &mut SplitWhitespace) -> FP2 {
+		let mut ret:FP2 = FP2::new();
+		ret.a = FP::from_hex_iter(iter);
+		ret.b = FP::from_hex_iter(iter);
+		return ret;
+	}
+
+	pub fn from_hex(val: String) -> FP2 {
+		let mut iter = val.split_whitespace();
+		return FP2::from_hex_iter(&mut iter);
+	}
+
+/* self=1/self */
+	pub fn inverse(&mut self) {
+		self.norm();
+		let mut w1=FP::new_copy(&self.a);
+		let mut w2=FP::new_copy(&self.b);
+
+		w1.sqr();
+		w2.sqr();
+		w1.add(&w2);
+		w1.inverse();
+		self.a.mul(&mut w1);
+		w1.neg();
+		self.b.mul(&mut w1);
+	}
+
+/* self/=2 */
+	pub fn div2(&mut self) {
+		self.a.div2();
+		self.b.div2();
+	}
+
+/* self*=sqrt(-1) */
+	pub fn times_i(&mut self) {
+	//	a.norm();
+		let z=FP::new_copy(&self.a);
+		self.a.copy(&self.b); self.a.neg();
+		self.b.copy(&z);
+	}
+
+/* w*=(1+sqrt(-1)) */
+/* where X*2-(1+sqrt(-1)) is irreducible for FP4, assumes p=3 mod 8 */
+	pub fn mul_ip(&mut self) {
+		self.norm();
+		let t=FP2::new_copy(self);
+		let z=FP::new_copy(&self.a);
+		self.a.copy(&self.b);
+		self.a.neg();
+		self.b.copy(&z);
+		self.add(&t);
+		self.norm();
+	}
+
+/* w/=(1+sqrt(-1)) */
+	pub fn div_ip(&mut self) {
+		let mut t=FP2::new();
+		self.norm();
+		t.a.copy(&self.a); t.a.add(&self.b);
+		t.b.copy(&self.b); t.b.sub(&self.a);
+		self.copy(&t);
+		self.div2();
+	}
+
+}
+/*
+fn main()
+{
+	let mut x=FP2::new();
+}
+*/
diff --git a/version22/rust/src/fp4.rs b/version22/rust/src/fp4.rs
new file mode 100644
index 0000000..ea2806d
--- /dev/null
+++ b/version22/rust/src/fp4.rs
@@ -0,0 +1,563 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use std::fmt;
+use std::str::SplitWhitespace;
+
+#[derive(Copy, Clone)]
+pub struct FP4 {
+	a:FP2,
+	b:FP2,
+}
+
+use rom::BIG_HEX_STRING_LEN;
+//mod fp;
+//use fp::FP;
+//mod fp2;
+use fp2::FP2;
+//mod big;
+use big::BIG;
+//mod dbig;
+//use dbig::DBIG;
+//mod rand;
+//mod hash256;
+//mod rom;
+//use rom;
+
+impl PartialEq for FP4 {
+	fn eq(&self, other: &FP4) -> bool {
+		return (self.a == other.a) &&
+			(self.b == other.b);
+	}
+}
+
+impl fmt::Display for FP4 {
+	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+		write!(f, "FP4: [ {}, {} ]", self.a, self.b)
+	}
+}
+
+impl fmt::Debug for FP4 {
+	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+		write!(f, "FP4: [ {}, {} ]", self.a, self.b)
+	}
+}
+
+impl FP4 {
+
+	pub fn new() -> FP4 {
+		FP4 {
+				a: FP2::new(),
+				b: FP2::new(),
+		}
+	}
+
+	pub fn new_int(a: isize) -> FP4 {
+		let mut f=FP4::new();
+		f.a.copy(&FP2::new_int(a));
+		f.b.zero();
+		return f;
+	}	
+
+	pub fn new_copy(x: &FP4) -> FP4 {
+		let mut f=FP4::new();
+		f.a.copy(&x.a);
+		f.b.copy(&x.b);
+		return f;
+	}	
+
+	pub fn new_fp2s(c: &FP2,d: &FP2) -> FP4 {
+		let mut f=FP4::new();
+		f.a.copy(c);
+		f.b.copy(d);
+		return f;
+	}	
+
+	pub fn new_fp2(c: &FP2) -> FP4 {
+		let mut f=FP4::new();
+		f.a.copy(c);
+		f.b.zero();
+		return f;
+	}	
+
+/* reduce components mod Modulus */
+	pub fn reduce(&mut self) {
+		self.a.reduce();
+		self.b.reduce();
+	}
+
+/* normalise components of w */
+	pub fn norm(&mut self) {
+		self.a.norm();
+		self.b.norm();
+	}	
+
+/* test self=0 ? */
+	pub fn iszilch(&mut self) -> bool {
+		self.reduce();
+		return self.a.iszilch() && self.b.iszilch();
+	}	
+
+/* test self=1 ? */
+	pub fn isunity(&mut self) -> bool {
+		let mut one=FP2::new_int(1);
+		return self.a.equals(&mut one) && self.b.iszilch();
+	}
+
+/* test is w real? That is in a+ib test b is zero */
+	pub fn isreal(&mut self) -> bool {
+		return self.b.iszilch();
+	}
+/* extract real part a */
+	pub fn real(&mut self) -> FP2 {
+		let f=FP2::new_copy(&self.a);
+		return f;
+	}
+
+	pub fn geta(&mut self) -> FP2 {
+		let f=FP2::new_copy(&self.a);
+		return f;
+	}
+/* extract imaginary part b */
+	pub fn getb(&mut self) -> FP2 {
+		let f=FP2::new_copy(&self.b);
+		return f;
+	}
+
+/* test self=x */
+	pub fn equals(&mut self,x:&mut FP4) -> bool {
+		return self.a.equals(&mut x.a) && self.b.equals(&mut x.b);
+	}
+/* copy self=x */
+	pub fn copy(&mut self,x :&FP4) {
+		self.a.copy(&x.a);
+		self.b.copy(&x.b);
+	}
+
+/* set self=0 */
+	pub fn zero(&mut self) {
+		self.a.zero();
+		self.b.zero();
+	}
+
+/* set self=1 */
+	pub fn one(&mut self) {
+		self.a.one();
+		self.b.zero();
+	}	
+
+/* negate self mod Modulus */
+	pub fn neg(&mut self) {
+		self.norm();
+		let mut m=FP2::new_copy(&self.a);
+		let mut t=FP2::new();
+
+		m.add(&self.b);
+		m.neg();
+		m.norm();
+		t.copy(&m); t.add(&self.b);
+		self.b.copy(&m);
+		self.b.add(&self.a);
+		self.a.copy(&t);
+	}	
+
+/* set to a-ib */
+	pub fn conj(&mut self) {
+		self.b.neg();
+		self.b.norm();
+	}
+
+/* self=-conjugate(self) */
+	pub fn nconj(&mut self) {
+		self.a.neg(); self.a.norm();
+	}
+
+/* self+=a */
+	pub fn add(&mut self,x:&FP4) {
+		self.a.add(&x.a);
+		self.b.add(&x.b);
+	}
+
+	pub fn padd(&mut self,x:&FP2) {
+		self.a.add(x);
+	}
+
+	pub fn dbl(&mut self) {
+		self.a.dbl();
+		self.b.dbl();
+	}
+
+/* self-=a */
+	pub fn sub(&mut self,x:&FP4) {
+		let mut m=FP4::new_copy(x);
+		m.neg();
+		self.add(&m);
+	}
+
+/* self*=s, where s is an FP */
+	pub fn pmul(&mut self,s:&mut FP2) {
+		self.a.mul(s);
+		self.b.mul(s);
+	}
+
+/* self*=i, where i is an int */
+	pub fn imul(&mut self,c: isize) {
+		self.a.imul(c);
+		self.b.imul(c);
+	}
+
+/* self*=self */	
+	pub fn sqr(&mut self) {
+		self.norm();
+
+		let mut t1=FP2::new_copy(&self.a);
+		let mut t2=FP2::new_copy(&self.b);
+		let mut t3=FP2::new_copy(&self.a);
+
+
+		t3.mul(&mut self.b);
+		t1.add(&self.b);
+		t2.mul_ip();
+
+		t2.add(&mut self.a);
+		self.a.copy(&t1);
+
+		self.a.mul(&mut t2);
+
+		t2.copy(&t3);
+		t2.mul_ip();
+		t2.add(&mut t3);
+		t2.neg();
+		self.a.add(&t2);
+
+		t3.dbl();
+		self.b.copy(&t3);
+
+		self.norm();
+	}
+
+/* self*=y */
+	pub fn mul(&mut self,y :&mut FP4) {
+		self.norm();
+
+		let mut t1=FP2::new_copy(&self.a);
+		let mut t2=FP2::new_copy(&self.b);
+		let mut t3=FP2::new();
+		let mut t4=FP2::new_copy(&self.b);
+
+		t1.mul(&mut y.a);
+		t2.mul(&mut y.b);
+		t3.copy(&y.b);
+		t3.add(&y.a);
+		t4.add(&self.a);
+
+		t4.mul(&mut t3);
+		t4.sub(&t1);
+		t4.norm();
+
+		self.b.copy(&t4);
+		self.b.sub(&t2);
+		t2.mul_ip();
+		self.a.copy(&t2);
+		self.a.add(&t1);
+
+		self.norm();
+	}	
+
+/* output to hex string */
+	pub fn tostring(&mut self) -> String {
+		return format!("[{},{}]",self.a.tostring(),self.b.tostring());		
+	}
+
+	pub fn to_hex(&self) -> String {
+		let mut ret: String = String::with_capacity(4 * BIG_HEX_STRING_LEN);
+		ret.push_str(&format!("{} {}", self.a.to_hex(), self.b.to_hex()));
+		return ret;
+	}
+
+	pub fn from_hex_iter(iter: &mut SplitWhitespace) -> FP4 {
+		let mut ret:FP4 = FP4::new();
+		ret.a = FP2::from_hex_iter(iter);
+		ret.b = FP2::from_hex_iter(iter);
+		return ret;
+	}
+
+	pub fn from_hex(val: String) -> FP4 {
+		let mut iter = val.split_whitespace();
+		return FP4::from_hex_iter(&mut iter);
+	}
+
+/* self=1/self */
+	pub fn inverse(&mut self) {
+		self.norm();
+
+		let mut t1=FP2::new_copy(&self.a);
+		let mut t2=FP2::new_copy(&self.b);
+
+		t1.sqr();
+		t2.sqr();
+		t2.mul_ip();
+		t1.sub(&t2);
+		t1.inverse();
+		self.a.mul(&mut t1);
+		t1.neg();
+		self.b.mul(&mut t1);
+	}	
+
+/* self*=i where i = sqrt(-1+sqrt(-1)) */
+	pub fn times_i(&mut self) {
+		self.norm();
+		let mut s=FP2::new_copy(&self.b);
+		let mut t=FP2::new_copy(&self.b);
+		s.times_i();
+		t.add(&s);
+		t.norm();
+		self.b.copy(&self.a);
+		self.a.copy(&t);
+	}	
+
+/* self=self^p using Frobenius */
+	pub fn frob(&mut self,f: &mut FP2) {
+		self.a.conj();
+		self.b.conj();
+		self.b.mul(f);
+	}	
+
+/* self=self^e */
+	pub fn pow(&mut self,e: &mut BIG) -> FP4 {
+		self.norm();
+		e.norm();
+		let mut w=FP4::new_copy(self);
+		let mut z=BIG::new_copy(&e);
+		let mut r=FP4::new_int(1);
+		loop {
+			let bt=z.parity();
+			z.fshr(1);
+			if bt==1 {r.mul(&mut w)};
+			if z.iszilch() {break}
+			w.sqr();
+		}
+		r.reduce();
+		return r;
+	}	
+
+/* XTR xtr_a function */
+	pub fn xtr_a(&mut self,w:&FP4,y:&FP4,z:&FP4) {
+		let mut r=FP4::new_copy(w);
+		let mut t=FP4::new_copy(w);
+		r.sub(y);
+		r.pmul(&mut self.a);
+		t.add(y);
+		t.pmul(&mut self.b);
+		t.times_i();
+
+		self.copy(&r);
+		self.add(&t);	
+		self.add(z);
+
+		self.norm();
+	}
+
+/* XTR xtr_d function */
+	pub fn xtr_d(&mut self) {
+		let mut w=FP4::new_copy(self);
+		self.sqr(); w.conj();
+		w.dbl();
+		self.sub(&w);
+		self.reduce();
+	}
+
+/* r=x^n using XTR method on traces of FP12s */
+	pub fn xtr_pow(&mut self,n: &mut BIG) -> FP4 {
+		let mut a=FP4::new_int(3);
+		let mut b=FP4::new_copy(self);
+		let mut c=FP4::new_copy(&b);
+		c.xtr_d();
+		let mut t=FP4::new();
+		let mut r=FP4::new();
+
+		n.norm();
+		let par=n.parity();
+		let mut v=BIG::new_copy(n); v.fshr(1);
+		if par==0 {v.dec(1); v.norm(); }
+
+		let nb=v.nbits();
+		for i in (0..nb).rev() {
+			if v.bit(i)!=1 {
+				t.copy(&b);
+				self.conj();
+				c.conj();
+				b.xtr_a(&a,self,&c);
+				self.conj();
+				c.copy(&t);
+				c.xtr_d();
+				a.xtr_d();
+			} else {
+				t.copy(&a); t.conj();
+				a.copy(&b);
+				a.xtr_d();
+				b.xtr_a(&c,self,&t);
+				c.xtr_d();
+			}
+		}
+		if par==0 {
+			r.copy(&c)
+		} else {r.copy(&b)}
+		r.reduce();
+		return r;
+	}
+
+/* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */
+	pub fn xtr_pow2(&mut self,ck: &FP4,ckml: &FP4,ckm2l: &FP4,a: &mut BIG,b: &mut BIG) -> FP4 {
+		a.norm(); b.norm();
+		let mut e=BIG::new_copy(a);
+		let mut d=BIG::new_copy(b);
+		let mut w=BIG::new();
+
+		let mut cu=FP4::new_copy(ck);  // can probably be passed in w/o copying
+		let mut cv=FP4::new_copy(self);
+		let mut cumv=FP4::new_copy(ckml);
+		let mut cum2v=FP4::new_copy(ckm2l);
+		let mut r=FP4::new();
+		let mut t=FP4::new();
+
+		let mut f2:usize=0;
+		while d.parity()==0 && e.parity()==0 {
+			d.fshr(1);
+			e.fshr(1);
+			f2+=1;
+		}
+
+		while BIG::comp(&d,&e)!=0 {
+			if BIG::comp(&d,&e)>0 {
+				w.copy(&e); w.imul(4); w.norm();
+				if BIG::comp(&d,&w)<=0 {
+					w.copy(&d); d.copy(&e);
+					e.rsub(&w); e.norm();
+
+					t.copy(&cv);
+					t.xtr_a(&cu,&cumv,&cum2v);
+					cum2v.copy(&cumv);
+					cum2v.conj();
+					cumv.copy(&cv);
+					cv.copy(&cu);
+					cu.copy(&t);
+				} else {
+					if d.parity()==0 {
+						d.fshr(1);
+						r.copy(&cum2v); r.conj();
+						t.copy(&cumv);
+						t.xtr_a(&cu,&cv,&r);
+						cum2v.copy(&cumv);
+						cum2v.xtr_d();
+						cumv.copy(&t);
+						cu.xtr_d();
+					} else {
+						if e.parity()==1 {
+							d.sub(&e); d.norm();
+							d.fshr(1);
+							t.copy(&cv);
+							t.xtr_a(&cu,&cumv,&cum2v);
+							cu.xtr_d();
+							cum2v.copy(&cv);
+							cum2v.xtr_d();
+							cum2v.conj();
+							cv.copy(&t);
+						} else {
+							w.copy(&d);
+							d.copy(&e); d.fshr(1);
+							e.copy(&w);
+							t.copy(&cumv);
+							t.xtr_d();
+							cumv.copy(&cum2v); cumv.conj();
+							cum2v.copy(&t); cum2v.conj();
+							t.copy(&cv);
+							t.xtr_d();
+							cv.copy(&cu);
+							cu.copy(&t);
+						}
+					}	
+				}
+			}
+			if BIG::comp(&d,&e)<0 {
+				w.copy(&d); w.imul(4); w.norm();
+				if BIG::comp(&e,&w)<=0 {
+					e.sub(&d); e.norm();
+					t.copy(&cv);
+					t.xtr_a(&cu,&cumv,&cum2v);
+					cum2v.copy(&cumv);
+					cumv.copy(&cu);
+					cu.copy(&t);
+				} else {
+					if e.parity()==0 {
+						w.copy(&d);
+						d.copy(&e); d.fshr(1);
+						e.copy(&w);
+						t.copy(&cumv);
+						t.xtr_d();
+						cumv.copy(&cum2v); cumv.conj();
+						cum2v.copy(&t); cum2v.conj();
+						t.copy(&cv);
+						t.xtr_d();
+						cv.copy(&cu);
+						cu.copy(&t);
+					} else {
+						if d.parity()==1 {
+							w.copy(&e);
+							e.copy(&d);
+							w.sub(&d); w.norm();
+							d.copy(&w); d.fshr(1);
+							t.copy(&cv);
+							t.xtr_a(&cu,&cumv,&cum2v);
+							cumv.conj();
+							cum2v.copy(&cu);
+							cum2v.xtr_d();
+							cum2v.conj();
+							cu.copy(&cv);
+							cu.xtr_d();
+							cv.copy(&t);
+						} else {
+							d.fshr(1);
+							r.copy(&cum2v); r.conj();
+							t.copy(&cumv);
+							t.xtr_a(&cu,&cv,&r);
+							cum2v.copy(&cumv);
+							cum2v.xtr_d();
+							cumv.copy(&t);
+							cu.xtr_d();
+						}
+					}
+				}
+			}
+		}
+		r.copy(&cv);
+		r.xtr_a(&cu,&cumv,&cum2v);
+		for _ in 0..f2 {r.xtr_d()}
+		r=r.xtr_pow(&mut d);
+		return r;
+	}
+
+
+}
+/*
+fn main()
+{
+	let mut w=FP4::new();
+}
+*/
diff --git a/version22/rust/src/gcm.rs b/version22/rust/src/gcm.rs
new file mode 100644
index 0000000..32e2749
--- /dev/null
+++ b/version22/rust/src/gcm.rs
@@ -0,0 +1,356 @@
+/*
+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.
+*/
+
+const GCM_NB:usize=4;
+const GCM_ACCEPTING_HEADER:usize=0;
+const GCM_ACCEPTING_CIPHER:usize=1;
+const GCM_NOT_ACCEPTING_MORE:usize=2;
+const GCM_FINISHED:usize=3;
+const GCM_ENCRYPTING:usize=0;
+const GCM_DECRYPTING:usize=1;
+
+use aes;
+use aes::AES;
+
+pub struct GCM {
+	table: [[u32;4];128],
+	statex: [u8;16],
+	y_0: [u8;16],
+//	counter: usize,
+	lena:[u32;2],
+	lenc:[u32;2],
+	status:usize,
+	a:AES
+}
+
+impl GCM {
+
+	fn pack(b: [u8;4]) -> u32 { /* pack bytes into a 32-bit Word */
+        return ((((b[0])&0xff) as u32)<<24)|((((b[1])&0xff) as u32)<<16)|((((b[2])&0xff) as u32)<<8)|(((b[3])&0xff) as u32);
+	}
+  
+	fn unpack(a: u32) -> [u8;4] { /* unpack bytes from a word */
+        let b:[u8;4]=[((a>>24)&0xff) as u8,((a>>16)&0xff) as u8,((a>>8)&0xff) as u8,(a&0xff) as u8];
+		return b;
+	}
+
+	fn precompute(&mut self,h: &[u8]) {
+		let mut b:[u8;4]=[0;4];
+        let mut j=0;
+        for i in 0..GCM_NB {
+            b[0]=h[j]; b[1]=h[j+1]; b[2]=h[j+2]; b[3]=h[j+3];
+            self.table[0][i]=GCM::pack(b);
+            j+=4;
+        }
+        for i in 1..128 {
+	    	let mut c:u32=0;
+            for j in 0..GCM_NB {self.table[i][j]=c|(self.table[i-1][j])>>1; c=self.table[i-1][j]<<31;}
+            if c != 0  {self.table[i][0]^=0xE1000000} /* irreducible polynomial */
+        }          
+	}
+
+	fn gf2mul(&mut self) { /* gf2m mul - Z=H*X mod 2^128 */
+        let mut p:[u32;4]=[0;4]; 
+    
+        for i in 0..4 {p[i]=0}
+        let mut j:usize=8; 
+        let mut m=0;
+        for i in 0..128 {
+	    	j-=1;
+            let mut c=((self.statex[m]>>j)&1) as u32; c= (!c) +1;
+	    	for k in 0..GCM_NB {p[k]^=self.table[i][k]&c}
+            if j==0 {
+				j=8; m+=1;
+                if m==16 {break}
+            }
+        }
+        j=0;
+        for i in 0..GCM_NB {
+            let b=GCM::unpack(p[i]);
+            self.statex[j]=b[0]; self.statex[j+1]=b[1]; self.statex[j+2]=b[2]; self.statex[j+3]=b[3];
+            j+=4;
+        }
+	}
+
+	fn wrap(&mut self) { /* Finish off GHASH */
+        let mut f:[u32;4]=[0;4]; 
+        let mut el:[u8;16]=[0;16];  
+   
+    /* convert lengths from bytes to bits */
+        f[0]=(self.lena[0]<<3)|(self.lena[1]&0xE0000000)>>29;
+        f[1]=self.lena[1]<<3;
+        f[2]=(self.lenc[0]<<3)|(self.lenc[1]&0xE0000000)>>29;
+        f[3]=self.lenc[1]<<3;
+        let mut j=0;
+        for i in 0..GCM_NB {
+            let b=GCM::unpack(f[i]);
+            el[j]=b[0]; el[j+1]=b[1]; el[j+2]=b[2]; el[j+3]=b[3];
+            j+=4;
+        }
+        for i in 0..16 {self.statex[i]^=el[i]}
+        self.gf2mul();
+	}
+
+	fn ghash(&mut self,plain: &[u8],len: usize) -> bool {
+        if self.status==GCM_ACCEPTING_HEADER {self.status=GCM_ACCEPTING_CIPHER}
+        if self.status != GCM_ACCEPTING_CIPHER {return false}
+        
+        let mut j=0;
+        while j<len {
+            for i in 0..16 {
+            	if j>=len {break}
+				self.statex[i]^=plain[j]; j+=1;
+                self.lenc[1]+=1; if self.lenc[1]==0 {self.lenc[0]+=1}
+            }
+            self.gf2mul();
+        }
+        if len%16 != 0 {self.status=GCM_NOT_ACCEPTING_MORE}
+        return true;
+    }
+
+    /* Initialize GCM mode */
+	pub fn init(&mut self,nk: usize,key: &[u8],niv: usize,iv: &[u8]) { /* iv size niv is usually 12 bytes (96 bits). AES key size nk can be 16,24 or 32 bytes */
+		let mut h:[u8;16]=[0;16];
+    
+        for i in 0..16 {h[i]=0; self.statex[i]=0}
+        
+		self.a=AES::new();
+
+        self.a.init(aes::ECB,nk,key,None);
+        self.a.ecb_encrypt(&mut h);    /* E(K,0) */
+        self.precompute(&h);
+        
+        self.lena[0]=0;self.lenc[0]=0;self.lena[1]=0;self.lenc[1]=0;
+        if niv==12 {
+            for i in 0..12 {self.a.f[i]=iv[i]}
+            let b=GCM::unpack(1);
+            self.a.f[12]=b[0]; self.a.f[13]=b[1]; self.a.f[14]=b[2]; self.a.f[15]=b[3];  /* initialise IV */
+            for i in 0..16 {self.y_0[i]=self.a.f[i]}
+        } else {
+            self.status=GCM_ACCEPTING_CIPHER;
+            self.ghash(iv,niv); /* GHASH(H,0,IV) */
+            self.wrap();
+            for i in 0..16 {self.a.f[i]=self.statex[i];self.y_0[i]=self.a.f[i];self.statex[i]=0}
+            self.lena[0]=0;self.lenc[0]=0;self.lena[1]=0;self.lenc[1]=0;
+        }
+        self.status=GCM_ACCEPTING_HEADER;
+	}
+
+	pub fn new() -> GCM {
+		GCM {
+			table:[[0;4];128],
+			statex:[0;16],
+			y_0:[0;16],
+			//counter:0,
+			lena:[0;2],
+			lenc:[0;2],
+			status:0,
+			a:AES::new()
+		}
+	}
+
+/* Add Header data - included but not encrypted */
+	pub fn add_header(&mut self,header: &[u8],len: usize) -> bool { /* Add some header. Won't be encrypted, but will be authenticated. len is length of header */
+        if self.status != GCM_ACCEPTING_HEADER {return false}
+        let mut j=0;
+        while j<len {
+            for i in 0..16 {
+            	if j>=len {break}
+				self.statex[i]^=header[j]; j+=1;
+                self.lena[1]+=1; if self.lena[1]==0 {self.lena[0]+=1}
+            }
+            self.gf2mul();
+        }
+        if len%16 != 0 {self.status=GCM_ACCEPTING_CIPHER}
+        return true;
+    }
+
+/* Add Plaintext - included and encrypted */
+	pub fn add_plain(&mut self,cipher: &mut [u8],plain: &[u8],len: usize) -> bool {
+		let mut cb:[u8;16]=[0;16]; 
+		let mut b:[u8;4]=[0;4];
+       
+        let mut counter: u32;
+        if self.status == GCM_ACCEPTING_HEADER {self.status=GCM_ACCEPTING_CIPHER}
+        if self.status != GCM_ACCEPTING_CIPHER {return false}
+        
+        let mut j=0;
+        while j<len {
+            b[0]=self.a.f[12]; b[1]=self.a.f[13]; b[2]=self.a.f[14]; b[3]=self.a.f[15];
+            counter=GCM::pack(b);
+            counter+=1;
+            b=GCM::unpack(counter);
+            self.a.f[12]=b[0]; self.a.f[13]=b[1]; self.a.f[14]=b[2]; self.a.f[15]=b[3]; /* increment counter */
+            for i in 0..16 {cb[i]=self.a.f[i]}
+            self.a.ecb_encrypt(&mut cb);        /* encrypt it  */
+    
+            for i in 0..16 {
+            	if j>=len {break}
+				cipher[j]=plain[j]^cb[i];
+				self.statex[i]^=cipher[j]; j+=1;
+                self.lenc[1]+=1; if self.lenc[1]==0 {self.lenc[0]+=1}
+            }
+            self.gf2mul()
+        }
+        if len%16 != 0 {self.status=GCM_NOT_ACCEPTING_MORE}
+        return true;
+	}
+
+/* Add Ciphertext - decrypts to plaintext */
+	pub fn add_cipher(&mut self,plain: &mut [u8],cipher: &[u8],len: usize) -> bool {
+		let mut cb:[u8;16]=[0;16]; 
+		let mut b:[u8;4]=[0;4];
+        
+       let mut counter: u32;
+        
+        if self.status==GCM_ACCEPTING_HEADER {self.status=GCM_ACCEPTING_CIPHER}
+        if self.status != GCM_ACCEPTING_CIPHER {return false}
+    
+        let mut j=0;
+        while j<len {
+            b[0]=self.a.f[12]; b[1]=self.a.f[13]; b[2]=self.a.f[14]; b[3]=self.a.f[15];
+            counter=GCM::pack(b);
+            counter+=1;
+            b=GCM::unpack(counter);
+            self.a.f[12]=b[0]; self.a.f[13]=b[1]; self.a.f[14]=b[2]; self.a.f[15]=b[3]; /* increment counter */
+            for i in 0..16 {cb[i]=self.a.f[i]}
+            self.a.ecb_encrypt(&mut cb);        /* encrypt it  */
+            for i in 0..16 {
+            	if j>=len {break}
+				let oc=cipher[j];
+				plain[j]=cipher[j]^cb[i];
+				self.statex[i]^=oc; j+=1;
+                self.lenc[1]+=1; if self.lenc[1]==0 {self.lenc[0]+=1}
+            }
+            self.gf2mul()
+        }
+        if len%16 != 0 {self.status=GCM_NOT_ACCEPTING_MORE}
+        return true;
+	}
+
+/* Finish and extract Tag */
+	pub fn finish(&mut self,extract: bool) -> [u8;16]  { /* Finish off GHASH and extract tag (MAC) */
+		let mut tag:[u8;16]=[0;16]; 
+    
+        self.wrap();
+        /* extract tag */
+        if extract {
+            self.a.ecb_encrypt(&mut (self.y_0));        /* E(K,Y0) */
+            for i in 0..16 {self.y_0[i]^=self.statex[i]}
+            for i in 0..16 {tag[i]=self.y_0[i];self.y_0[i]=0;self.statex[i]=0}
+        }
+        self.status=GCM_FINISHED;
+        self.a.end();
+        return tag;
+	}
+
+	pub fn hex2bytes(hex: &[u8],bin: &mut [u8]) {
+		let len=hex.len();
+
+		for i in 0..len/2 {
+			let mut v:u8;
+        	let mut c = hex[2*i];
+        	if c >= b'0' && c <= b'9' {
+            	v = c - b'0';
+        	} else if c >= b'A' && c <= b'F' {
+            	v = c - b'A' + 10;
+        	} else if c >= b'a' && c <= b'f' {
+            	v = c - b'a' + 10;
+        	} else {
+            	v = 0;
+        	}
+        	v <<= 4;
+        	c = hex[2*i + 1];
+        	if c >= b'0' && c <= b'9' {
+            	v += c - b'0';
+        	} else if c >= b'A' && c <= b'F' {
+            	v += c - b'A' + 10;
+        	} else if c >= b'a' && c <= b'f' {
+            	v += c - b'a' + 10;
+        	} else {
+            	v = 0;
+        	}
+        	bin[i] = v;
+    	}
+	}
+
+}
+/*
+fn main()
+{
+	let kt=b"feffe9928665731c6d6a8f9467308308";
+	let mt=b"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39";
+	let ht=b"feedfacedeadbeeffeedfacedeadbeefabaddad2";
+	let nt=b"9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b";
+// Tag should be 619cc5aefffe0bfa462af43c1699d050
+
+	let mut gcm=GCM::new();
+
+	let len=mt.len()/2;
+	let lenh=ht.len()/2;
+	let lenk=kt.len()/2;
+	let leniv=nt.len()/2;
+
+	//let mut t:[u8;16]=[0;16];	// Tag
+	let mut k:[u8;16]=[0;16];   // AES Key
+	let mut h:[u8;64]=[0;64];  	// Header - to be included in Authentication, but not encrypted
+	let mut n:[u8;100]=[0;100];	// IV - Initialisation vector
+	let mut m:[u8;100]=[0;100];	// Plaintext to be encrypted/authenticated
+	let mut c:[u8;100]=[0;100];	// Ciphertext
+	let mut p:[u8;100]=[0;100];	// Recovered Plaintext 
+
+	GCM::hex2bytes(mt,&mut m);
+	GCM::hex2bytes(ht,&mut h);
+	GCM::hex2bytes(kt,&mut k);
+	GCM::hex2bytes(nt,&mut n);
+
+ 	println!("Plaintext=");
+	for i in 0..len {print!("{:02x}",m[i])}
+	println!("");
+
+	gcm.init(lenk,&k,leniv,&n);
+	
+	gcm.add_header(&h,lenh);
+	gcm.add_plain(&mut c,&m,len);
+	let mut t=gcm.finish(true);
+
+ 	println!("Ciphertext=");
+	for i in 0..len {print!("{:02x}",c[i])}
+	println!("");
+  
+ 	println!("Tag=");
+	for i in 0..16 {print!("{:02x}",t[i])}
+	println!("");
+
+	gcm.init(lenk,&k,leniv,&n);
+	
+	gcm.add_header(&h,lenh);
+	gcm.add_cipher(&mut p,&c,len);
+	t=gcm.finish(true);
+
+ 	println!("Plaintext=");
+	for i in 0..len {print!("{:02x}",p[i])}
+	println!("");
+
+	println!("Tag=");
+	for i in 0..16 {print!("{:02x}",t[i])}
+	println!("");
+
+}
+*/
diff --git a/version22/rust/src/hash256.rs b/version22/rust/src/hash256.rs
new file mode 100644
index 0000000..e2aca06
--- /dev/null
+++ b/version22/rust/src/hash256.rs
@@ -0,0 +1,182 @@
+/*
+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.
+*/
+
+const HASH256_H0: u32=0x6A09E667;
+const HASH256_H1: u32=0xBB67AE85;
+const HASH256_H2: u32=0x3C6EF372;
+const HASH256_H3: u32=0xA54FF53A;
+const HASH256_H4: u32=0x510E527F;
+const HASH256_H5: u32=0x9B05688C;
+const HASH256_H6: u32=0x1F83D9AB;
+const HASH256_H7: u32=0x5BE0CD19;
+
+const HASH256_K : [u32;64]=[
+	0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,
+	0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,
+	0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,
+	0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,
+	0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
+	0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070,
+	0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,
+	0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2];
+
+
+pub struct HASH256 {
+	length: [u32;2],
+	h: [u32;8],
+	w: [u32;64]
+}
+
+impl HASH256 {
+	fn s(n: u32,x: u32) -> u32 {
+		return ((x)>>n) | ((x)<<(32-n));
+	}
+	fn r(n: u32,x: u32) -> u32 {
+		return (x)>>n;
+	}
+
+	fn ch(x: u32,y: u32,z: u32) -> u32 {
+		return (x&y)^(!(x)&z);
+	}
+
+	fn maj(x: u32,y: u32,z: u32) -> u32 {
+		return (x&y)^(x&z)^(y&z);
+	}
+	fn sig0(x: u32) -> u32 {
+		return HASH256::s(2,x)^HASH256::s(13,x)^HASH256::s(22,x);
+	}
+
+	fn sig1(x: u32) -> u32 {
+		return HASH256::s(6,x)^HASH256::s(11,x)^HASH256::s(25,x);
+	}
+
+	fn theta0(x: u32) -> u32 {
+		return HASH256::s(7,x)^HASH256::s(18,x)^HASH256::r(3,x);
+	}
+
+	fn theta1(x: u32) -> u32 {
+		return HASH256::s(17,x)^HASH256::s(19,x)^HASH256::r(10,x);
+	}
+
+	fn transform(&mut self) { /* basic transformation step */
+		for j in 16..64 {
+			self.w[j]=HASH256::theta1(self.w[j-2]).wrapping_add(self.w[j-7]).wrapping_add(HASH256::theta0(self.w[j-15])).wrapping_add(self.w[j-16]);
+		}
+		let mut a=self.h[0]; let mut b=self.h[1]; let mut c=self.h[2]; let mut d=self.h[3];
+		let mut e=self.h[4]; let mut f=self.h[5]; let mut g=self.h[6]; let mut hh=self.h[7];
+		for j in 0..64 { /* 64 times - mush it up */
+			let t1=hh.wrapping_add(HASH256::sig1(e)).wrapping_add(HASH256::ch(e,f,g)).wrapping_add(HASH256_K[j]).wrapping_add(self.w[j]);
+			let t2=HASH256::sig0(a).wrapping_add(HASH256::maj(a,b,c));
+			hh=g; g=f; f=e;
+			e=d.wrapping_add(t1);
+			d=c;
+			c=b;
+			b=a;
+			a=t1.wrapping_add(t2);
+		}
+		self.h[0] = self.h[0].wrapping_add(a);
+		self.h[1] = self.h[1].wrapping_add(b);
+		self.h[2] = self.h[2].wrapping_add(c);
+		self.h[3] = self.h[3].wrapping_add(d);
+		self.h[4] = self.h[4].wrapping_add(e);
+		self.h[5] = self.h[5].wrapping_add(f);
+		self.h[6] = self.h[6].wrapping_add(g);
+		self.h[7] = self.h[7].wrapping_add(hh);
+	}
+
+/* Initialise Hash function */
+	pub fn init(&mut self) { /* initialise */
+		for i in 0..64 {self.w[i]=0}
+		self.length[0]=0; self.length[1]=0;
+		self.h[0]=HASH256_H0;
+		self.h[1]=HASH256_H1;
+		self.h[2]=HASH256_H2;
+		self.h[3]=HASH256_H3;
+		self.h[4]=HASH256_H4;
+		self.h[5]=HASH256_H5;
+		self.h[6]=HASH256_H6;
+		self.h[7]=HASH256_H7;
+	}	
+
+	pub fn new() -> HASH256 {
+		let mut nh=HASH256 {
+			length: [0;2],
+			h: [0;8],
+			w: [0;64]
+		};
+		nh.init();
+		return nh;
+	}
+
+/* process a single byte */
+	pub fn process(&mut self,byt: u8) { /* process the next message byte */
+		let cnt=((self.length[0]/32)%16) as usize;
+		self.w[cnt]<<=8;
+		self.w[cnt]|=(byt&0xFF) as u32;
+		self.length[0]+=8;
+		if self.length[0]==0 {self.length[1]+=1; self.length[0]=0}
+		if (self.length[0]%512)==0 {self.transform()}
+	}
+
+/* process an array of bytes */	
+	pub fn process_array(&mut self,b: &[u8]) {
+		for i in 0..b.len() {self.process((b[i]))}
+	}
+
+/* process a 32-bit integer */
+	pub fn process_num(&mut self,n: i32) {
+		self.process(((n>>24)&0xff) as u8);
+		self.process(((n>>16)&0xff) as u8);
+		self.process(((n>>8)&0xff) as u8);
+		self.process((n&0xff) as u8);
+	}
+
+/* Generate 32-byte Hash */
+	pub fn hash(&mut self) -> [u8;32] { /* pad message and finish - supply digest */
+		let mut digest:[u8;32]=[0;32];
+		let len0=self.length[0];
+		let len1=self.length[1];
+		self.process(0x80);
+		while (self.length[0]%512)!=448 {self.process(0)}
+		self.w[14]=len1;
+		self.w[15]=len0;    
+		self.transform();
+		for i in 0..32 { /* convert to bytes */
+			digest[i]=((self.h[i/4]>>(8*(3-i%4))) & 0xff) as u8;
+		}
+		self.init();
+		return digest;
+	}
+}
+
+//248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1
+/*
+fn main() {
+	let s = String::from("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");	
+	let test = s.into_bytes();
+	let mut sh=HASH256::new();
+
+	for i in 0..test.len(){
+		sh.process(test[i]);
+	}
+		
+	let digest=sh.hash();    
+	for i in 0..32 {print!("{:02x}",digest[i])}
+}
+*/
diff --git a/version22/rust/src/hash384.rs b/version22/rust/src/hash384.rs
new file mode 100644
index 0000000..2c8fc6f
--- /dev/null
+++ b/version22/rust/src/hash384.rs
@@ -0,0 +1,188 @@
+/*
+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.
+*/
+
+const HASH384_H0: u64=0xcbbb9d5dc1059ed8;
+const HASH384_H1: u64=0x629a292a367cd507;
+const HASH384_H2: u64=0x9159015a3070dd17;
+const HASH384_H3: u64=0x152fecd8f70e5939;
+const HASH384_H4: u64=0x67332667ffc00b31;
+const HASH384_H5: u64=0x8eb44a8768581511;
+const HASH384_H6: u64=0xdb0c2e0d64f98fa7;
+const HASH384_H7: u64=0x47b5481dbefa4fa4;
+
+const HASH384_K : [u64;80]=[
+	0x428a2f98d728ae22,0x7137449123ef65cd,0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc,
+	0x3956c25bf348b538,0x59f111f1b605d019,0x923f82a4af194f9b,0xab1c5ed5da6d8118,
+	0xd807aa98a3030242,0x12835b0145706fbe,0x243185be4ee4b28c,0x550c7dc3d5ffb4e2,
+	0x72be5d74f27b896f,0x80deb1fe3b1696b1,0x9bdc06a725c71235,0xc19bf174cf692694,
+	0xe49b69c19ef14ad2,0xefbe4786384f25e3,0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65,
+	0x2de92c6f592b0275,0x4a7484aa6ea6e483,0x5cb0a9dcbd41fbd4,0x76f988da831153b5,
+	0x983e5152ee66dfab,0xa831c66d2db43210,0xb00327c898fb213f,0xbf597fc7beef0ee4,
+	0xc6e00bf33da88fc2,0xd5a79147930aa725,0x06ca6351e003826f,0x142929670a0e6e70,
+	0x27b70a8546d22ffc,0x2e1b21385c26c926,0x4d2c6dfc5ac42aed,0x53380d139d95b3df,
+	0x650a73548baf63de,0x766a0abb3c77b2a8,0x81c2c92e47edaee6,0x92722c851482353b,
+	0xa2bfe8a14cf10364,0xa81a664bbc423001,0xc24b8b70d0f89791,0xc76c51a30654be30,
+	0xd192e819d6ef5218,0xd69906245565a910,0xf40e35855771202a,0x106aa07032bbd1b8,
+	0x19a4c116b8d2d0c8,0x1e376c085141ab53,0x2748774cdf8eeb99,0x34b0bcb5e19b48a8,
+	0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb,0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3,
+	0x748f82ee5defb2fc,0x78a5636f43172f60,0x84c87814a1f0ab72,0x8cc702081a6439ec,
+	0x90befffa23631e28,0xa4506cebde82bde9,0xbef9a3f7b2c67915,0xc67178f2e372532b,
+	0xca273eceea26619c,0xd186b8c721c0c207,0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178,
+	0x06f067aa72176fba,0x0a637dc5a2c898a6,0x113f9804bef90dae,0x1b710b35131c471b,
+	0x28db77f523047d84,0x32caab7b40c72493,0x3c9ebe0a15c9bebc,0x431d67c49c100d4c,
+	0x4cc5d4becb3e42b6,0x597f299cfc657e2a,0x5fcb6fab3ad6faec,0x6c44198c4a475817];
+
+
+pub struct HASH384 {
+	length: [u64;2],
+	h: [u64;8],
+	w: [u64;80]
+}
+
+impl HASH384 {
+	fn s(n: u64,x: u64) -> u64 {
+		return ((x)>>n) | ((x)<<(64-n));
+	}
+	fn r(n: u64,x: u64) -> u64 {
+		return (x)>>n;
+	}
+
+	fn ch(x: u64,y: u64,z: u64) -> u64 {
+		return (x&y)^(!(x)&z);
+	}
+
+	fn maj(x: u64,y: u64,z: u64) -> u64 {
+		return (x&y)^(x&z)^(y&z);
+	}
+
+	fn sig0(x: u64) -> u64 {
+		return HASH384::s(28,x)^HASH384::s(34,x)^HASH384::s(39,x);
+	}
+
+	fn sig1(x: u64) -> u64 {
+		return HASH384::s(14,x)^HASH384::s(18,x)^HASH384::s(41,x);
+	}
+
+	fn theta0(x: u64) -> u64 {
+		return HASH384::s(1,x)^HASH384::s(8,x)^HASH384::r(7,x);
+	}
+
+	fn theta1(x: u64) -> u64 {
+		return HASH384::s(19,x)^HASH384::s(61,x)^HASH384::r(6,x);
+	}
+
+	fn transform(&mut self) { /* basic transformation step */
+		for j in 16..80 {
+			self.w[j]=HASH384::theta1(self.w[j-2])+self.w[j-7]+HASH384::theta0(self.w[j-15])+self.w[j-16];
+		}
+		let mut a=self.h[0]; let mut b=self.h[1]; let mut c=self.h[2]; let mut d=self.h[3]; 
+		let mut e=self.h[4]; let mut f=self.h[5]; let mut g=self.h[6]; let mut hh=self.h[7];
+		for j in 0..80 { /* 64 times - mush it up */
+			let t1=hh+HASH384::sig1(e)+HASH384::ch(e,f,g)+HASH384_K[j]+self.w[j];
+			let t2=HASH384::sig0(a)+HASH384::maj(a,b,c);
+			hh=g; g=f; f=e;
+			e=d+t1;
+			d=c;
+			c=b;
+			b=a;
+			a=t1+t2 ; 
+		}
+		self.h[0]+=a; self.h[1]+=b; self.h[2]+=c; self.h[3]+=d;
+		self.h[4]+=e; self.h[5]+=f; self.h[6]+=g; self.h[7]+=hh; 
+	} 	
+
+/* Initialise Hash function */
+	pub fn init(&mut self) { /* initialise */
+		for i in 0..64 {self.w[i]=0}
+		self.length[0]=0; self.length[1]=0;
+		self.h[0]=HASH384_H0;
+		self.h[1]=HASH384_H1;
+		self.h[2]=HASH384_H2;
+		self.h[3]=HASH384_H3;
+		self.h[4]=HASH384_H4;
+		self.h[5]=HASH384_H5;
+		self.h[6]=HASH384_H6;
+		self.h[7]=HASH384_H7;
+	}	
+
+	pub fn new() -> HASH384 {
+		let mut nh=HASH384 {
+			length: [0;2],
+			h: [0;8],
+			w: [0;80]
+		};
+		nh.init();
+		return nh;
+	}
+
+/* process a single byte */
+	pub fn process(&mut self,byt: u8) { /* process the next message byte */
+		let cnt=((self.length[0]/64)%16) as usize;
+		self.w[cnt]<<=8;
+		self.w[cnt]|=(byt&0xFF) as u64;
+		self.length[0]+=8;
+		if self.length[0]==0 {self.length[1]+=1; self.length[0]=0}
+		if (self.length[0]%1024)==0 {self.transform()}
+	}
+
+/* process an array of bytes */	
+	pub fn process_array(&mut self,b: &[u8]) {
+		for i in 0..b.len() {self.process((b[i]))}
+	}
+
+/* process a 32-bit integer */
+	pub fn process_num(&mut self,n: i32) {
+		self.process(((n>>24)&0xff) as u8);
+		self.process(((n>>16)&0xff) as u8);
+		self.process(((n>>8)&0xff) as u8);
+		self.process((n&0xff) as u8);
+	}
+
+/* Generate 32-byte Hash */
+	pub fn hash(&mut self) -> [u8;48] { /* pad message and finish - supply digest */
+		let mut digest:[u8;48]=[0;48];
+		let len0=self.length[0];
+		let len1=self.length[1];
+		self.process(0x80);
+		while (self.length[0]%1024)!=896 {self.process(0)}
+		self.w[14]=len1;
+		self.w[15]=len0;    
+		self.transform();
+		for i in 0..48 { /* convert to bytes */
+			digest[i]=((self.h[i/8]>>(8*(7-i%8))) & 0xff) as u8;
+		}
+		self.init();
+		return digest;
+	}
+}
+
+//09330c33f71147e8 3d192fc782cd1b47 53111b173b3b05d2 2fa08086e3b0f712 fcc7c71a557e2db9 66c3e9fa91746039
+/*
+fn main() {
+	let s = String::from("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu");	
+	let test = s.into_bytes();
+	let mut sh=HASH384::new();
+
+	for i in 0..test.len(){
+		sh.process(test[i]);
+	}
+		
+	let digest=sh.hash();    
+	for i in 0..48 {print!("{:02x}",digest[i])}
+} */
diff --git a/version22/rust/src/hash512.rs b/version22/rust/src/hash512.rs
new file mode 100644
index 0000000..a345781
--- /dev/null
+++ b/version22/rust/src/hash512.rs
@@ -0,0 +1,189 @@
+/*
+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.
+*/
+
+
+const HASH512_H0: u64=0x6a09e667f3bcc908;
+const HASH512_H1: u64=0xbb67ae8584caa73b;
+const HASH512_H2: u64=0x3c6ef372fe94f82b;
+const HASH512_H3: u64=0xa54ff53a5f1d36f1;
+const HASH512_H4: u64=0x510e527fade682d1;
+const HASH512_H5: u64=0x9b05688c2b3e6c1f;
+const HASH512_H6: u64=0x1f83d9abfb41bd6b;
+const HASH512_H7: u64=0x5be0cd19137e2179;
+
+const HASH512_K : [u64;80]=[
+	0x428a2f98d728ae22,0x7137449123ef65cd,0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc,
+	0x3956c25bf348b538,0x59f111f1b605d019,0x923f82a4af194f9b,0xab1c5ed5da6d8118,
+	0xd807aa98a3030242,0x12835b0145706fbe,0x243185be4ee4b28c,0x550c7dc3d5ffb4e2,
+	0x72be5d74f27b896f,0x80deb1fe3b1696b1,0x9bdc06a725c71235,0xc19bf174cf692694,
+	0xe49b69c19ef14ad2,0xefbe4786384f25e3,0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65,
+	0x2de92c6f592b0275,0x4a7484aa6ea6e483,0x5cb0a9dcbd41fbd4,0x76f988da831153b5,
+	0x983e5152ee66dfab,0xa831c66d2db43210,0xb00327c898fb213f,0xbf597fc7beef0ee4,
+	0xc6e00bf33da88fc2,0xd5a79147930aa725,0x06ca6351e003826f,0x142929670a0e6e70,
+	0x27b70a8546d22ffc,0x2e1b21385c26c926,0x4d2c6dfc5ac42aed,0x53380d139d95b3df,
+	0x650a73548baf63de,0x766a0abb3c77b2a8,0x81c2c92e47edaee6,0x92722c851482353b,
+	0xa2bfe8a14cf10364,0xa81a664bbc423001,0xc24b8b70d0f89791,0xc76c51a30654be30,
+	0xd192e819d6ef5218,0xd69906245565a910,0xf40e35855771202a,0x106aa07032bbd1b8,
+	0x19a4c116b8d2d0c8,0x1e376c085141ab53,0x2748774cdf8eeb99,0x34b0bcb5e19b48a8,
+	0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb,0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3,
+	0x748f82ee5defb2fc,0x78a5636f43172f60,0x84c87814a1f0ab72,0x8cc702081a6439ec,
+	0x90befffa23631e28,0xa4506cebde82bde9,0xbef9a3f7b2c67915,0xc67178f2e372532b,
+	0xca273eceea26619c,0xd186b8c721c0c207,0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178,
+	0x06f067aa72176fba,0x0a637dc5a2c898a6,0x113f9804bef90dae,0x1b710b35131c471b,
+	0x28db77f523047d84,0x32caab7b40c72493,0x3c9ebe0a15c9bebc,0x431d67c49c100d4c,
+	0x4cc5d4becb3e42b6,0x597f299cfc657e2a,0x5fcb6fab3ad6faec,0x6c44198c4a475817];
+
+
+pub struct HASH512 {
+	length: [u64;2],
+	h: [u64;8],
+	w: [u64;80]
+}
+
+impl HASH512 {
+	fn s(n: u64,x: u64) -> u64 {
+		return ((x)>>n) | ((x)<<(64-n));
+	}
+	fn r(n: u64,x: u64) -> u64 {
+		return (x)>>n;
+	}
+
+	fn ch(x: u64,y: u64,z: u64) -> u64 {
+		return (x&y)^(!(x)&z);
+	}
+
+	fn maj(x: u64,y: u64,z: u64) -> u64 {
+		return (x&y)^(x&z)^(y&z);
+	}
+
+	fn sig0(x: u64) -> u64 {
+		return HASH512::s(28,x)^HASH512::s(34,x)^HASH512::s(39,x);
+	}
+
+	fn sig1(x: u64) -> u64 {
+		return HASH512::s(14,x)^HASH512::s(18,x)^HASH512::s(41,x);
+	}
+
+	fn theta0(x: u64) -> u64 {
+		return HASH512::s(1,x)^HASH512::s(8,x)^HASH512::r(7,x);
+	}
+
+	fn theta1(x: u64) -> u64 {
+		return HASH512::s(19,x)^HASH512::s(61,x)^HASH512::r(6,x);
+	}
+
+	fn transform(&mut self) { /* basic transformation step */
+		for j in 16..80 {
+			self.w[j]=HASH512::theta1(self.w[j-2])+self.w[j-7]+HASH512::theta0(self.w[j-15])+self.w[j-16];
+		}
+		let mut a=self.h[0]; let mut b=self.h[1]; let mut c=self.h[2]; let mut d=self.h[3]; 
+		let mut e=self.h[4]; let mut f=self.h[5]; let mut g=self.h[6]; let mut hh=self.h[7];
+		for j in 0..80 { /* 64 times - mush it up */
+			let t1=hh+HASH512::sig1(e)+HASH512::ch(e,f,g)+HASH512_K[j]+self.w[j];
+			let t2=HASH512::sig0(a)+HASH512::maj(a,b,c);
+			hh=g; g=f; f=e;
+			e=d+t1;
+			d=c;
+			c=b;
+			b=a;
+			a=t1+t2 ; 
+		}
+		self.h[0]+=a; self.h[1]+=b; self.h[2]+=c; self.h[3]+=d;
+		self.h[4]+=e; self.h[5]+=f; self.h[6]+=g; self.h[7]+=hh; 
+	} 	
+
+/* Initialise Hash function */
+	pub fn init(&mut self) { /* initialise */
+		for i in 0..64 {self.w[i]=0}
+		self.length[0]=0; self.length[1]=0;
+		self.h[0]=HASH512_H0;
+		self.h[1]=HASH512_H1;
+		self.h[2]=HASH512_H2;
+		self.h[3]=HASH512_H3;
+		self.h[4]=HASH512_H4;
+		self.h[5]=HASH512_H5;
+		self.h[6]=HASH512_H6;
+		self.h[7]=HASH512_H7;
+	}	
+
+	pub fn new() -> HASH512 {
+		let mut nh=HASH512 {
+			length: [0;2],
+			h: [0;8],
+			w: [0;80]
+		};
+		nh.init();
+		return nh;
+	}
+
+/* process a single byte */
+	pub fn process(&mut self,byt: u8) { /* process the next message byte */
+		let cnt=((self.length[0]/64)%16) as usize;
+		self.w[cnt]<<=8;
+		self.w[cnt]|=(byt&0xFF) as u64;
+		self.length[0]+=8;
+		if self.length[0]==0 {self.length[1]+=1; self.length[0]=0}
+		if (self.length[0]%1024)==0 {self.transform()}
+	}
+
+/* process an array of bytes */	
+	pub fn process_array(&mut self,b: &[u8]) {
+		for i in 0..b.len() {self.process((b[i]))}
+	}
+
+/* process a 32-bit integer */
+	pub fn process_num(&mut self,n: i32) {
+		self.process(((n>>24)&0xff) as u8);
+		self.process(((n>>16)&0xff) as u8);
+		self.process(((n>>8)&0xff) as u8);
+		self.process((n&0xff) as u8);
+	}
+
+/* Generate 32-byte Hash */
+	pub fn hash(&mut self) -> [u8;64] { /* pad message and finish - supply digest */
+		let mut digest:[u8;64]=[0;64];
+		let len0=self.length[0];
+		let len1=self.length[1];
+		self.process(0x80);
+		while (self.length[0]%1024)!=896 {self.process(0)}
+		self.w[14]=len1;
+		self.w[15]=len0;    
+		self.transform();
+		for i in 0..64 { /* convert to bytes */
+			digest[i]=((self.h[i/8]>>(8*(7-i%8))) & 0xff) as u8;
+		}
+		self.init();
+		return digest;
+	}
+}
+
+//8e959b75dae313da 8cf4f72814fc143f 8f7779c6eb9f7fa1 7299aeadb6889018 501d289e4900f7e4 331b99dec4b5433a c7d329eeb6dd2654 5e96e55b874be909
+/*
+fn main() {
+	let s = String::from("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu");	
+	let test = s.into_bytes();
+	let mut sh=HASH512::new();
+
+	for i in 0..test.len(){
+		sh.process(test[i]);
+	}
+		
+	let digest=sh.hash();    
+	for i in 0..64 {print!("{:02x}",digest[i])}
+} */
diff --git a/version22/rust/src/lib.rs b/version22/rust/src/lib.rs
new file mode 100644
index 0000000..db9c412
--- /dev/null
+++ b/version22/rust/src/lib.rs
@@ -0,0 +1,36 @@
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+pub mod aes;
+pub mod big;
+pub mod dbig;
+pub mod ecdh;
+pub mod ecp;
+pub mod ecp2;
+pub mod ff;
+pub mod fp;
+pub mod fp2;
+pub mod fp4;
+pub mod fp12;
+pub mod pair;
+pub mod mpin;
+pub mod rand;
+pub mod hash256;
+pub mod hash384;
+pub mod hash512;
+pub mod rsa;
+
+#[cfg(target_pointer_width = "32")]
+#[path = "rom32.rs"]
+pub mod rom;
+
+#[cfg(target_pointer_width = "64")]
+#[path = "rom64.rs"]
+pub mod rom;
+
+#[cfg(test)]
+mod tests {
+    #[test]
+    fn it_works() {
+    }
+}
diff --git a/version22/rust/src/mpin.rs b/version22/rust/src/mpin.rs
new file mode 100644
index 0000000..8644d1a
--- /dev/null
+++ b/version22/rust/src/mpin.rs
@@ -0,0 +1,768 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use std::time::{SystemTime};
+use std::time::UNIX_EPOCH;
+
+use ecp::ECP;
+use fp2::FP2;
+use ecp2::ECP2;
+use fp4::FP4;
+use fp12::FP12;
+use big::BIG;
+use rand::RAND;
+use hash256::HASH256;
+use hash384::HASH384;
+use hash512::HASH512;
+use pair;
+use rom;
+
+/* MPIN API Functions */
+
+/* Configure mode of operation */
+
+pub const PERMITS:bool=true;
+pub const PINERROR:bool=true;
+pub const FULL: bool=true;
+pub const SINGLE_PASS:bool=false;
+
+pub const EFS: usize=rom::MODBYTES as usize;
+pub const EGS: usize=rom::MODBYTES as usize;
+pub const PAS: usize=16;
+pub const BAD_PARAMS: isize=-11;
+pub const INVALID_POINT: isize=-14;
+pub const WRONG_ORDER: isize=-18;
+pub const BAD_PIN: isize=-19;
+pub const SHA256: usize=32;
+pub const SHA384: usize=48;
+pub const SHA512: usize=64;
+
+/* Configure your PIN here */
+
+pub const MAXPIN: i32=10000;  /* PIN less than this */
+pub const PBLEN: i32=14;      /* Number of bits in PIN */
+pub const TS: usize=10;         /* 10 for 4 digit PIN, 14 for 6-digit PIN - 2^TS/TS approx = sqrt(MAXPIN) */
+pub const TRAP:usize=200;      /* 200 for 4 digit PIN, 2000 for 6-digit PIN  - approx 2*sqrt(MAXPIN) */
+
+pub const HASH_TYPE: usize=SHA256;
+
+#[allow(non_snake_case)]
+fn hash(sha: usize,c: &mut FP4,U: &mut ECP,r: &mut [u8]) -> bool {
+	let mut w:[u8;EFS]=[0;EFS];
+	let mut t:[u8;6*EFS]=[0;6*EFS];
+
+	c.geta().geta().tobytes(&mut w); for i in 0..EFS {t[i]=w[i]}
+	c.geta().getb().tobytes(&mut w); for i in EFS..2*EFS {t[i]=w[i-EFS]}
+	c.getb().geta().tobytes(&mut w); for i in 2*EFS..3*EFS {t[i]=w[i-2*EFS]}
+	c.getb().getb().tobytes(&mut w); for i in 3*EFS..4*EFS {t[i]=w[i-3*EFS]}
+
+	U.getx().tobytes(&mut w); for i in 4*EFS..5*EFS {t[i]=w[i-4*EFS]}
+	U.gety().tobytes(&mut w); for i in 5*EFS..6*EFS {t[i]=w[i-5*EFS]}
+
+	if sha==SHA256 {
+		let mut h=HASH256::new();
+		h.process_array(&t);
+		let sh=h.hash();
+		for i in 0..PAS {r[i]=sh[i]}	
+		return true;	
+	}
+	if sha==SHA384 {
+		let mut h=HASH384::new();
+		h.process_array(&t);
+		let sh=h.hash();
+		for i in 0..PAS {r[i]=sh[i]}		
+		return true;
+	}
+	if sha==SHA512 {
+		let mut h=HASH512::new();
+		h.process_array(&t);
+		let sh=h.hash();
+		for i in 0..PAS {r[i]=sh[i]}
+		return true;		
+	}
+	return false;
+
+}
+
+/* Hash number (optional) and string to point on curve */
+
+fn hashit(sha: usize,n: usize,id: &[u8],w: &mut [u8]) -> bool {
+	let mut r:[u8;64]=[0;64];
+	let mut didit=false;
+	if sha==SHA256 {
+		let mut h=HASH256::new();
+		if n>0 {h.process_num(n as i32)}
+		h.process_array(id);
+        let hs=h.hash();	
+        for i in 0..sha {r[i]=hs[i];}	
+        didit=true;
+	}
+	if sha==SHA384 {
+		let mut h=HASH384::new();
+		if n>0 {h.process_num(n as i32)}
+		h.process_array(id);
+		let hs=h.hash();
+        for i in 0..sha {r[i]=hs[i];}			
+		didit=true;
+	}
+	if sha==SHA512 {
+		let mut h=HASH512::new();
+		if n>0 {h.process_num(n as i32)}
+		h.process_array(id);
+		let hs=h.hash();
+        for i in 0..sha {r[i]=hs[i];}	
+        didit=true;		
+	}
+	if !didit {return false}
+
+	let rm=rom::MODBYTES as usize;
+
+	if sha>rm {
+		for i in 0..rm {w[i]=r[i]}
+	} else {
+		for i in 0..sha {w[i]=r[i]}	
+		for i in sha..rm {w[i]=0}
+	}
+
+	return true;
+}
+
+#[allow(non_snake_case)]
+fn mapit(h: &[u8]) -> ECP {
+	let mut q=BIG::new_ints(&rom::MODULUS);
+	let mut x=BIG::frombytes(h);
+	x.rmod(&mut q);
+	let mut P:ECP;
+
+	loop {
+		P=ECP::new_bigint(&x,0);
+		if !P.is_infinity() {break}
+		x.inc(1); x.norm();
+	}
+	if rom::CURVE_PAIRING_TYPE!=rom::BN_CURVE {
+		let mut c=BIG::new_ints(&rom::CURVE_COF);
+		P=P.mul(&mut c);
+	}	
+	return P;
+}
+
+/* return time in slots since epoch */
+pub fn today() -> usize {
+  	return (SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()/(60*1440)) as usize;
+}
+
+/* these next two functions help to implement elligator squared - http://eprint.iacr.org/2014/043 */
+/* maps a random u to a point on the curve */
+#[allow(non_snake_case)]
+fn emap(u: &BIG,cb: isize) -> ECP {
+	let mut P:ECP;
+	let mut x=BIG::new_copy(u);
+	let mut p=BIG::new_ints(&rom::MODULUS);
+	x.rmod(&mut p);
+	loop {
+		P=ECP::new_bigint(&x,cb);
+		if !P.is_infinity() {break}
+		x.inc(1);  x.norm();
+	}
+	return P;
+}
+
+/* returns u derived from P. Random value in range 1 to return value should then be added to u */
+#[allow(non_snake_case)]
+fn unmap(u: &mut BIG,P: &mut ECP) -> isize {
+	let s=P.gets();
+	let mut R:ECP;
+	let mut r=0;
+	let x=P.getx();
+	u.copy(&x);
+	loop {
+		u.dec(1); u.norm();
+		r+=1;
+		R=ECP::new_bigint(u,s);
+		if !R.is_infinity() {break}
+	}
+	return r as isize;
+}
+
+pub fn hash_id(sha: usize,id: &[u8],w: &mut [u8]) -> bool {
+	return hashit(sha,0,id,w);
+}
+
+/* these next two functions implement elligator squared - http://eprint.iacr.org/2014/043 */
+/* Elliptic curve point E in format (0x04,x,y} is converted to form {0x0-,u,v} */
+/* Note that u and v are indistinguisible from random strings */
+#[allow(non_snake_case)]
+pub fn encoding(rng: &mut RAND,e: &mut [u8]) ->isize {
+	let mut t:[u8;EFS]=[0;EFS];
+
+	for i in 0..EFS {t[i]=e[i+1]}
+	let mut u=BIG::frombytes(&t);
+	for i in 0..EFS {t[i]=e[i+EFS+1]}
+	let mut v=BIG::frombytes(&t);
+		
+	let mut P=ECP::new_bigs(&u,&v);
+	if P.is_infinity() {return INVALID_POINT}
+
+	let p=BIG::new_ints(&rom::MODULUS);
+	u=BIG::randomnum(&p,rng);
+
+	let mut su=rng.getbyte() as isize; /*if (su<0) su=-su;*/ su%=2;
+		
+	let mut W=emap(&mut u,su);
+	P.sub(&mut W);
+	let sv=P.gets();
+	let rn=unmap(&mut v,&mut P);
+	let mut m=rng.getbyte() as isize; /*if (m<0) m=-m;*/ m%=rn;
+	v.inc(m+1);
+	e[0]=(su+2*sv) as u8;
+	u.tobytes(&mut t);
+	for i in 0..EFS {e[i+1]=t[i]}
+	v.tobytes(&mut t);
+	for i in 0..EFS {e[i+EFS+1]=t[i]}		
+		
+	return 0;
+}
+
+#[allow(non_snake_case)]
+pub fn decoding(d: &mut [u8]) -> isize {
+	let mut t:[u8;EFS]=[0;EFS];
+
+	if (d[0]&0x04)!=0 {return INVALID_POINT}
+
+	for i in 0..EFS {t[i]=d[i+1]}
+	let mut u=BIG::frombytes(&t);
+	for i in 0..EFS {t[i]=d[i+EFS+1]}
+	let mut v=BIG::frombytes(&t);
+
+	let su=(d[0]&1) as isize;
+	let sv=((d[0]>>1)&1) as isize;
+	let mut W=emap(&mut u,su);
+	let mut P=emap(&mut v,sv);
+	P.add(&mut W);
+	u=P.getx();
+	v=P.gety();
+	d[0]=0x04;
+	u.tobytes(&mut t);
+	for i in 0..EFS {d[i+1]=t[i]}
+	v.tobytes(&mut t);
+	for i in 0..EFS {d[i+EFS+1]=t[i]}		
+		
+	return 0;
+}
+
+/* R=R1+R2 in group G1 */
+#[allow(non_snake_case)]
+pub fn recombine_g1(r1: &[u8],r2: &[u8],r: &mut [u8]) -> isize {
+	let mut P=ECP::frombytes(&r1);
+	let mut Q=ECP::frombytes(&r2);
+
+	if P.is_infinity() || Q.is_infinity() {return INVALID_POINT}
+
+	P.add(&mut Q);
+
+	P.tobytes(r);
+	return 0;
+}
+
+/* W=W1+W2 in group G2 */
+#[allow(non_snake_case)]
+pub fn recombine_g2(w1: &[u8],w2: &[u8],w: &mut [u8]) -> isize {
+	let mut P=ECP2::frombytes(&w1);
+	let mut Q=ECP2::frombytes(&w2);
+
+	if P.is_infinity() || Q.is_infinity() {return INVALID_POINT}
+
+	P.add(&mut Q);
+	
+	P.tobytes(w);
+	return 0;
+}
+	
+/* create random secret S */
+pub fn random_generate(rng: &mut RAND,s: &mut [u8]) -> isize {
+	let r=BIG::new_ints(&rom::CURVE_ORDER);
+	let mut sc=BIG::randomnum(&r,rng);
+	if rom::AES_S>0 {
+		sc.mod2m(2*rom::AES_S);
+	}		
+	sc.tobytes(s);
+	return 0;
+}
+
+/* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */
+#[allow(non_snake_case)]
+pub fn get_server_secret(s: &[u8],sst: &mut [u8]) -> isize {
+
+	let mut Q=ECP2::new_fp2s(&FP2::new_bigs(&BIG::new_ints(&rom::CURVE_PXA),&BIG::new_ints(&rom::CURVE_PXB)),&FP2::new_bigs(&BIG::new_ints(&rom::CURVE_PYA),&BIG::new_ints(&rom::CURVE_PYB)));
+
+	let mut sc=BIG::frombytes(s);
+	Q=pair::g2mul(&mut Q,&mut sc);
+	Q.tobytes(sst);
+	return 0;
+}
+
+/*
+ W=x*H(G);
+ if RNG == NULL then X is passed in 
+ if RNG != NULL the X is passed out 
+ if type=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve
+*/
+#[allow(non_snake_case)]
+pub fn get_g1_multiple(rng: Option<&mut RAND>,typ: usize,x: &mut [u8],g: &[u8],w: &mut [u8]) -> isize {
+	let mut sx:BIG;
+	let r=BIG::new_ints(&rom::CURVE_ORDER);
+
+	if let Some(mut rd)=rng
+	{
+		sx=BIG::randomnum(&r,rd);
+		if rom::AES_S>0 {
+			sx.mod2m(2*rom::AES_S);
+		}
+		sx.tobytes(x);
+	} else {
+		sx=BIG::frombytes(x);
+	}
+	let mut P:ECP;
+
+	if typ==0 {
+		P=ECP::frombytes(g);
+		if P.is_infinity() {return INVALID_POINT}
+	} else {
+		P=mapit(g)
+	}
+
+
+
+	pair::g1mul(&mut P,&mut sx).tobytes(w);
+	return 0;
+}
+
+
+/* Client secret CST=S*H(CID) where CID is client ID and S is master secret */
+/* CID is hashed externally */
+pub fn get_client_secret(s: &mut [u8],cid: &[u8],cst: &mut [u8]) -> isize {
+	return get_g1_multiple(None,1,s,cid,cst);
+}
+
+/* Extract PIN from TOKEN for identity CID */
+#[allow(non_snake_case)]
+pub fn extract_pin(sha: usize,cid: &[u8],pin: i32,token: &mut [u8]) -> isize {
+	let mut P=ECP::frombytes(&token);
+	const RM:usize=rom::MODBYTES as usize;
+	let mut h:[u8;RM]=[0;RM];
+	if P.is_infinity() {return INVALID_POINT}
+	hashit(sha,0,cid,&mut h);
+	let mut R=mapit(&h);
+
+	R=R.pinmul(pin%MAXPIN,PBLEN);
+	P.sub(&mut R);
+
+	P.tobytes(token);
+
+	return 0;
+}
+
+/* Functions to support M-Pin Full */
+#[allow(non_snake_case)]
+pub fn precompute(token: &[u8],cid: &[u8],g1: &mut [u8],g2: &mut [u8]) -> isize {
+	let mut T=ECP::frombytes(&token);
+	if T.is_infinity() {return INVALID_POINT} 
+
+	let mut P=mapit(&cid);
+
+	let mut Q=ECP2::new_fp2s(&FP2::new_bigs(&BIG::new_ints(&rom::CURVE_PXA),&BIG::new_ints(&rom::CURVE_PXB)),&FP2::new_bigs(&BIG::new_ints(&rom::CURVE_PYA),&BIG::new_ints(&rom::CURVE_PYB)));
+
+	let mut g=pair::ate(&mut Q,&mut T);
+	g=pair::fexp(&g);
+	g.tobytes(g1);
+
+	g=pair::ate(&mut Q,&mut P);
+	g=pair::fexp(&g);
+	g.tobytes(g2);
+
+	return 0;
+}
+
+/* Time Permit CTT=S*(date|H(CID)) where S is master secret */
+#[allow(non_snake_case)]
+pub fn get_client_permit(sha: usize,date: usize,s: &[u8],cid: &[u8],ctt: &mut [u8]) ->isize {
+	const RM:usize=rom::MODBYTES as usize;
+	let mut h:[u8;RM]=[0;RM];	
+	hashit(sha,date,cid,&mut h);
+	let mut P=mapit(&h);
+
+	let mut sc=BIG::frombytes(s);
+	pair::g1mul(&mut P,&mut sc).tobytes(ctt);
+	return 0;
+}
+
+/* Implement step 1 on client side of MPin protocol */
+#[allow(non_snake_case)]
+pub fn client_1(sha: usize,date: usize,client_id: &[u8],rng: Option<&mut RAND>,x: &mut [u8],pin: usize,token: &[u8],sec: &mut [u8],xid: Option<&mut [u8]>,xcid: Option<&mut [u8]>,permit: Option<&[u8]>) ->isize {
+	let r=BIG::new_ints(&rom::CURVE_ORDER);
+		
+	let mut sx:BIG;
+
+	if let Some(mut rd)=rng
+	{
+		sx=BIG::randomnum(&r,rd);
+		if rom::AES_S>0 {
+			sx.mod2m(2*rom::AES_S);
+		}
+		sx.tobytes(x);
+	} else {
+		sx=BIG::frombytes(x);
+	}
+
+	const RM:usize=rom::MODBYTES as usize;
+	let mut h:[u8;RM]=[0;RM];
+
+	hashit(sha,0,&client_id,&mut h);
+	let mut P=mapit(&h);
+	
+	let mut T=ECP::frombytes(&token);
+	if T.is_infinity() {return INVALID_POINT}
+
+	let mut W=P.pinmul((pin as i32)%MAXPIN,PBLEN);
+	T.add(&mut W);
+	if date!=0 {
+		if let Some(rpermit)=permit {W=ECP::frombytes(&rpermit);}
+		if W.is_infinity() {return INVALID_POINT}
+		T.add(&mut W);
+		let mut h2:[u8;RM]=[0;RM];		
+		hashit(sha,date,&h,&mut h2);
+		W=mapit(&h2);
+		if let Some(mut rxid)=xid {
+			P=pair::g1mul(&mut P,&mut sx);
+			P.tobytes(&mut rxid);
+			W=pair::g1mul(&mut W,&mut sx);
+			P.add(&mut W);
+		} else {
+			P.add(&mut W);
+			P=pair::g1mul(&mut P,&mut sx);
+		}
+		if let Some(mut rxcid)=xcid {P.tobytes(&mut rxcid)}
+	} else {
+		if let Some(mut rxid)=xid {
+			P=pair::g1mul(&mut P,&mut sx);
+			P.tobytes(&mut rxid);
+		}
+	}
+
+	T.tobytes(sec);
+	return 0;
+}
+
+/* Outputs H(CID) and H(T|H(CID)) for time permits. If no time permits set HID=HTID */
+#[allow(non_snake_case)]
+pub fn server_1(sha: usize,date: usize,cid: &[u8],hid: &mut [u8],htid: Option<&mut [u8]>) {
+	const RM:usize=rom::MODBYTES as usize;
+	let mut h:[u8;RM]=[0;RM];
+
+	hashit(sha,0,cid,&mut h);	
+
+	let mut P=mapit(&h);
+	
+	P.tobytes(hid);
+	if date!=0 {
+		let mut h2:[u8;RM]=[0;RM];		
+		hashit(sha,date,&h,&mut h2);
+		let mut R=mapit(&h2);
+		P.add(&mut R);
+		if let Some(rhtid)=htid {P.tobytes(rhtid);}
+	} 
+}
+
+/* Implement step 2 on client side of MPin protocol */
+#[allow(non_snake_case)]
+pub fn client_2(x: &[u8],y: &[u8],sec: &mut [u8]) -> isize {
+	let mut r=BIG::new_ints(&rom::CURVE_ORDER);
+	let mut P=ECP::frombytes(sec);
+	if P.is_infinity() {return INVALID_POINT}
+
+	let mut px=BIG::frombytes(x);
+	let py=BIG::frombytes(y);
+	px.add(&py);
+	px.rmod(&mut r);
+	//px.rsub(r)
+
+	P=pair::g1mul(&mut P,&mut px);
+	P.neg();
+	P.tobytes(sec);
+	
+	return 0;
+}
+
+/* return time since epoch */
+pub fn get_time() -> usize {
+  	return (SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) as usize;	
+}
+
+/* Generate Y = H(epoch, xCID/xID) */
+pub fn get_y(sha: usize,timevalue: usize,xcid: &[u8],y: &mut [u8]) {
+	const RM:usize=rom::MODBYTES as usize;
+	let mut h:[u8;RM]=[0;RM];
+
+	hashit(sha,timevalue,xcid,&mut h);	
+
+	let mut sy= BIG::frombytes(&h);
+	let mut q=BIG::new_ints(&rom::CURVE_ORDER);
+	sy.rmod(&mut q);
+	if rom::AES_S>0 {
+		sy.mod2m(2*rom::AES_S);
+	}
+	sy.tobytes(y);
+}
+
+/* Implement step 2 of MPin protocol on server side */
+#[allow(non_snake_case)]
+pub fn server_2(date: usize,hid: &[u8],htid: Option<&[u8]>,y: &[u8],sst: &[u8],xid: Option<&[u8]>,xcid: Option<&[u8]>,msec: &[u8],e: Option<&mut [u8]>,f: Option<&mut [u8]>) -> isize {
+//	q:=NewBIGints(Modulus)
+	let mut Q=ECP2::new_fp2s(&FP2::new_bigs(&BIG::new_ints(&rom::CURVE_PXA),&BIG::new_ints(&rom::CURVE_PXB)),&FP2::new_bigs(&BIG::new_ints(&rom::CURVE_PYA),&BIG::new_ints(&rom::CURVE_PYB)));
+
+	let mut sQ=ECP2::frombytes(&sst);
+	if sQ.is_infinity() {return INVALID_POINT}	
+
+	let mut R:ECP;
+	if date!=0 {
+		if let Some(rxcid)=xcid {R=ECP::frombytes(&rxcid);}
+		else {return BAD_PARAMS}
+	} else {
+		if let Some(rxid)=xid {R=ECP::frombytes(&rxid)}
+		else {return BAD_PARAMS}
+	}
+	if R.is_infinity() {return INVALID_POINT}
+
+	let mut sy=BIG::frombytes(&y);
+	let mut P:ECP;
+	if date!=0 {
+		if let Some(rhtid)=htid {P=ECP::frombytes(&rhtid)}
+		else {return BAD_PARAMS}
+	} else {
+		P=ECP::frombytes(&hid);
+	}
+	
+	if P.is_infinity() {return INVALID_POINT}
+
+	P=pair::g1mul(&mut P,&mut sy);
+	P.add(&mut R);
+	R=ECP::frombytes(&msec);
+	if R.is_infinity() {return INVALID_POINT}
+
+	let mut g:FP12;
+//		FP12 g1=new FP12(0);
+
+	g=pair::ate2(&mut Q,&mut R,&mut sQ,&mut P);
+	g=pair::fexp(&g);
+
+	if !g.isunity() {
+		
+		if let Some(rxid)=xid {
+			if let Some(re)=e {
+				if let Some(rf)=f {
+
+					g.tobytes(re);
+					if date!=0 {
+						P=ECP::frombytes(&hid);
+						if P.is_infinity() {return INVALID_POINT}		
+						R=ECP::frombytes(&rxid);
+						if R.is_infinity() {return INVALID_POINT}			
+						P=pair::g1mul(&mut P,&mut sy);
+						P.add(&mut R);									
+					}
+					g=pair::ate(&mut Q,&mut P);
+					g=pair::fexp(&g);
+					g.tobytes(rf);
+
+				}
+			}
+		}
+	
+		return BAD_PIN;
+	}
+
+	return 0;
+}
+
+/* Pollards kangaroos used to return PIN error */
+pub fn kangaroo(e: &[u8],f: &[u8]) -> isize {
+	let mut ge=FP12::frombytes(e);
+	let mut gf=FP12::frombytes(f);
+	let mut distance: [isize;TS]=[0;TS];
+	let mut t=FP12::new_copy(&gf);
+
+	let mut table: [FP12;TS]=[FP12::new();TS];
+	let mut s:isize=1;
+	for m in 0..TS {
+		distance[m]=s;
+		table[m]=FP12::new_copy(&t);
+		s*=2;
+		t.usqr();
+	}
+	t.one();
+	let mut dn:isize=0;
+	let mut i:usize;
+	for _ in 0..TRAP {
+		i=(t.geta().geta().geta().lastbits(20)%(TS as isize)) as usize;
+		t.mul(&mut table[i]);
+		dn+=distance[i];
+	}
+	gf.copy(&t); gf.conj();
+	let mut steps:usize=0; let mut dm:isize=0;
+	let mut res:isize=0;
+	while dm-dn<MAXPIN as isize {
+		steps+=1;
+		if steps>4*TRAP {break}
+		i=(ge.geta().geta().geta().lastbits(20)%(TS as isize)) as usize;
+		ge.mul(&mut table[i]);
+		dm+=distance[i];
+		if ge.equals(&mut t) {
+			res=dm-dn;
+			break;
+		}
+		if ge.equals(&mut gf) {
+			res=dn-dm;
+			break;
+		}
+
+	}
+	if steps>4*TRAP || dm-dn>=MAXPIN as isize {res=0 }    // Trap Failed  - probable invalid token
+	return res;
+}
+
+/* Hash the M-Pin transcript - new */
+
+pub fn hash_all(sha: usize,hid: &[u8],xid: &[u8],xcid: Option<&[u8]>,sec: &[u8],y: &[u8],r: &[u8],w: &[u8],h: &mut[u8]) -> bool {
+	let mut tlen:usize=0;
+	const RM:usize=rom::MODBYTES as usize;	
+	let mut t: [u8;10*RM+4]=[0;10*RM+4];
+
+	for i in 0 .. hid.len() {t[i]=hid[i]}
+	tlen+=hid.len();
+
+	if let Some(rxcid)=xcid {
+		for i in 0..rxcid.len() {t[i+tlen]=rxcid[i]}
+		tlen+=rxcid.len();
+	} else {
+		for i in 0..xid.len() {t[i+tlen]=xid[i]}
+		tlen+=xid.len();
+	}	
+
+	for i in 0..sec.len() {t[i+tlen]=sec[i]}
+	tlen+=sec.len();		
+	for i in 0..y.len() {t[i+tlen]=y[i]}
+	tlen+=y.len();
+	for i in 0..r.len() {t[i+tlen]=r[i]}
+	tlen+=r.len();		
+	for i in 0..w.len() {t[i+tlen]=w[i]}
+	tlen+=w.len();	
+	if tlen!=10*RM+4 {return false}
+
+	return hashit(sha,0,&t,h);
+}
+
+/* calculate common key on client side */
+/* wCID = w.(A+AT) */
+#[allow(non_snake_case)]
+pub fn client_key(sha: usize,g1: &[u8],g2: &[u8],pin: usize,r: &[u8],x: &[u8],h: &[u8],wcid: &[u8],ck: &mut [u8]) -> isize {
+
+	let mut g1=FP12::frombytes(&g1);
+	let mut g2=FP12::frombytes(&g2);
+	let mut z=BIG::frombytes(&r);
+	let mut x=BIG::frombytes(&x);
+	let h=BIG::frombytes(&h);
+
+	let mut W=ECP::frombytes(&wcid);
+	if W.is_infinity() {return INVALID_POINT} 
+
+	W=pair::g1mul(&mut W,&mut x);
+
+	let mut f=FP2::new_bigs(&BIG::new_ints(&rom::CURVE_FRA),&BIG::new_ints(&rom::CURVE_FRB));
+	let mut r=BIG::new_ints(&rom::CURVE_ORDER);
+	let q=BIG::new_ints(&rom::MODULUS);
+
+	z.add(&h);	//new
+	z.rmod(&mut r);
+
+	let mut m=BIG::new_copy(&q);
+	m.rmod(&mut r);
+
+	let mut a=BIG::new_copy(&z);
+	a.rmod(&mut m);
+
+	let mut b=BIG::new_copy(&z);
+	b.div(&mut m);
+
+	g2.pinpow(pin as i32,PBLEN);
+	g1.mul(&mut g2);
+
+	let mut c=g1.trace();
+	g2.copy(&g1);
+	g2.frob(&mut f);
+	let cp=g2.trace();
+	g1.conj();
+	g2.mul(&mut g1);
+	let cpm1=g2.trace();
+	g2.mul(&mut g1);
+	let cpm2=g2.trace();
+
+	c=c.xtr_pow2(&cp,&cpm1,&cpm2,&mut a,&mut b);
+
+	hash(sha,&mut c,&mut W,ck);
+
+	return 0
+}
+
+/* calculate common key on server side */
+/* Z=r.A - no time permits involved */
+#[allow(non_snake_case)]
+pub fn server_key(sha: usize,z: &[u8],sst: &[u8],w: &[u8],h: &[u8],hid: &[u8],xid: &[u8],xcid: Option<&[u8]>,sk: &mut [u8]) -> isize {
+	let mut sQ=ECP2::frombytes(&sst);
+	if sQ.is_infinity() {return INVALID_POINT} 
+	let mut R=ECP::frombytes(&z);
+	if R.is_infinity() {return INVALID_POINT} 
+	let mut A=ECP::frombytes(&hid);
+	if A.is_infinity() {return INVALID_POINT} 
+
+	let mut U=ECP::new();
+	if let Some(rxcid)=xcid {
+		U.copy(&ECP::frombytes(&rxcid));
+	} else {
+		U.copy(&ECP::frombytes(&xid));
+	}
+	
+	if U.is_infinity() {return INVALID_POINT} 
+
+	let mut w=BIG::frombytes(&w);
+	let mut h=BIG::frombytes(&h);
+	A=pair::g1mul(&mut A,&mut h);	// new
+	R.add(&mut A);
+
+	U=pair::g1mul(&mut U,&mut w);
+	let mut g=pair::ate(&mut sQ,&mut R);
+	g=pair::fexp(&g);
+
+	let mut c=g.trace();
+
+	hash(sha,&mut c,&mut U,sk);
+
+	return 0
+}
+
+
diff --git a/version22/rust/src/pair.rs b/version22/rust/src/pair.rs
new file mode 100644
index 0000000..9e162db
--- /dev/null
+++ b/version22/rust/src/pair.rs
@@ -0,0 +1,674 @@
+/*
+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.
+*/
+
+//mod fp;
+use fp::FP;
+//mod ecp;
+use ecp::ECP;
+//mod fp2;
+use fp2::FP2;
+//mod ecp2;
+use ecp2::ECP2;
+//mod fp4;
+use fp4::FP4;
+//mod fp12;
+use fp12::FP12;
+//mod big;
+use big::BIG;
+//mod dbig;
+use dbig::DBIG;
+//mod rand;
+//mod hash256;
+//mod rom;
+use rom;
+
+#[allow(non_snake_case)]
+
+fn linedbl(A: &mut ECP2,qx: &mut FP,qy: &mut  FP) -> FP12 {
+	let mut P=ECP2::new();
+
+	P.copy(A);
+	let mut zz=FP2::new_copy(&P.getpz());
+	zz.sqr();
+	let d=A.dbl();	
+
+	if d<0 {return FP12::new_int(1)}
+
+	let mut z3=FP2::new_copy(&A.getpz());
+	let mut a=FP4::new();
+	let mut b=FP4::new();
+	let c=FP4::new();	
+
+	let mut x=FP2::new_copy(&P.getpx());
+	let mut y=FP2::new_copy(&P.getpy());
+	let mut t=FP2::new_copy(&P.getpx());
+	t.sqr();
+	t.imul(3);
+
+	y.sqr();
+	y.dbl();
+	z3.mul(&mut zz);
+	z3.pmul(qy);
+
+	x.mul(&mut t);
+	x.sub(&y);
+	a.copy(&FP4::new_fp2s(&z3,&x));
+	t.neg();
+	zz.mul(&mut t);
+	zz.pmul(qx);
+	b.copy(&FP4::new_fp2(&zz));
+
+	return FP12::new_fp4s(&a,&b,&c);
+}
+
+#[allow(non_snake_case)]
+fn lineadd(A: &mut ECP2,B: &mut ECP2,qx: &mut FP,qy: &mut  FP) -> FP12 {
+
+	let mut P=ECP2::new();
+
+	P.copy(A);
+	let mut zz=FP2::new_copy(&P.getpz());
+	zz.sqr();
+
+	let d=A.add(B);
+	if d<0 {return FP12::new_int(1)}	
+
+	let mut z3=FP2::new_copy(&A.getpz());
+	let mut a=FP4::new();
+	let mut b=FP4::new();
+	let c=FP4::new();	
+
+	if d==0 { /* Addition */
+		let mut x=FP2::new_copy(&B.getpx());
+		let mut y=FP2::new_copy(&B.getpy());
+		let mut t=FP2::new_copy(&P.getpz()); 
+		t.mul(&mut y);
+		zz.mul(&mut t);
+
+		let mut ny=FP2::new_copy(&P.getpy()); ny.neg();
+		zz.add(&ny); 
+		z3.pmul(qy);
+		t.mul(&mut P.getpx());
+		x.mul(&mut ny);
+		t.add(&x);
+		a.copy(&FP4::new_fp2s(&z3,&t));
+		zz.neg();
+		zz.pmul(qx);
+		b.copy(&FP4::new_fp2(&zz));
+	} else { /* Doubling */
+		let mut x=FP2::new_copy(&P.getpx());
+		let mut y=FP2::new_copy(&P.getpy());
+		let mut t=FP2::new_copy(&P.getpx());
+		t.sqr();
+		t.imul(3);
+
+		y.sqr();
+		y.dbl();
+		z3.mul(&mut zz);
+		z3.pmul(qy);
+
+		x.mul(&mut t);
+		x.sub(&y);
+		a.copy(&FP4::new_fp2s(&z3,&x));
+		t.neg();
+		zz.mul(&mut t);
+		zz.pmul(qx);
+		b.copy(&FP4::new_fp2(&zz));
+	}
+	return FP12::new_fp4s(&a,&b,&c);
+}
+
+#[allow(non_snake_case)]
+/* Optimal R-ate pairing */
+pub fn ate(P: & mut ECP2,Q: &mut ECP) -> FP12 {
+	let mut f = FP2::new_bigs(&BIG::new_ints(&rom::CURVE_FRA),&BIG::new_ints(&rom::CURVE_FRB));
+	let x = BIG::new_ints(&rom::CURVE_BNX);
+	let mut n = BIG::new_copy(&x);
+	let mut K = ECP2::new();
+
+	
+	if rom::CURVE_PAIRING_TYPE == rom::BN_CURVE {
+		n.pmul(6); n.dec(2);
+	} else {n.copy(&x)}
+	
+	n.norm();
+	P.affine();
+	Q.affine();
+	let mut qx=FP::new_copy(&Q.getpx());
+	let mut qy=FP::new_copy(&Q.getpy());
+
+	let mut A=ECP2::new();
+	let mut r=FP12::new_int(1);
+
+	A.copy(&P);
+	let nb=n.nbits();
+
+	for i in (1..nb-1).rev() {
+		let mut lv=linedbl(&mut A,&mut qx,&mut qy);
+		r.smul(&mut lv);
+		if n.bit(i)==1 {
+		
+			lv=lineadd(&mut A,P,&mut qx,&mut qy);
+		
+			r.smul(&mut lv);
+		}		
+		r.sqr();	
+	}
+
+	let mut lv=linedbl(&mut A,&mut qx,&mut qy);
+	r.smul(&mut lv);
+
+	if n.parity()==1 {
+		lv=lineadd(&mut A,P,&mut qx,&mut qy);
+		r.smul(&mut lv);
+	}
+
+/* R-ate fixup required for BN curves */
+
+	if rom::CURVE_PAIRING_TYPE == rom::BN_CURVE {
+		r.conj();
+		K.copy(&P);
+		K.frob(&mut f);
+		A.neg();
+		lv=lineadd(&mut A,&mut K,&mut qx,&mut qy);
+		r.smul(&mut lv);
+		K.frob(&mut f);
+		K.neg();
+		lv=lineadd(&mut A,&mut K,&mut qx,&mut qy);
+		r.smul(&mut lv);
+	}
+
+	return r;
+}
+
+#[allow(non_snake_case)]
+/* Optimal R-ate double pairing e(P,Q).e(R,S) */
+pub fn ate2(P: &mut ECP2,Q: &mut ECP,R: &mut ECP2,S: &mut ECP) -> FP12 {
+	let mut f = FP2::new_bigs(&BIG::new_ints(&rom::CURVE_FRA),&BIG::new_ints(&rom::CURVE_FRB));
+	let x = BIG::new_ints(&rom::CURVE_BNX);
+	let mut n = BIG::new_copy(&x);
+	let mut K = ECP2::new();
+
+
+	if rom::CURVE_PAIRING_TYPE == rom::BN_CURVE {
+		n.pmul(6); n.dec(2);
+	} else {n.copy(&x)}
+	
+	n.norm();
+	P.affine();
+	Q.affine();
+	R.affine();
+	S.affine();
+
+	let mut qx=FP::new_copy(&Q.getpx());
+	let mut qy=FP::new_copy(&Q.getpy());
+
+	let mut sx=FP::new_copy(&S.getpx());
+	let mut sy=FP::new_copy(&S.getpy());
+
+	let mut A=ECP2::new();
+	let mut B=ECP2::new();
+	let mut r=FP12::new_int(1);
+
+	A.copy(&P);
+	B.copy(&R);
+	let nb=n.nbits();
+
+	for i in (1..nb-1).rev() {
+		let mut lv=linedbl(&mut A,&mut qx,&mut qy);
+		r.smul(&mut lv);
+		lv=linedbl(&mut B,&mut sx,&mut sy);
+		r.smul(&mut lv);
+
+		if n.bit(i)==1 {
+			lv=lineadd(&mut A,P,&mut qx,&mut qy);
+			r.smul(&mut lv);
+			lv=lineadd(&mut B,R,&mut sx,&mut sy);
+			r.smul(&mut lv);
+		}
+		r.sqr();
+	}
+
+	let mut lv=linedbl(&mut A,&mut qx,&mut qy);
+	r.smul(&mut lv);
+	lv=linedbl(&mut B,&mut sx,&mut sy);
+	r.smul(&mut lv);
+	if n.parity()==1 {
+		lv=lineadd(&mut A,P,&mut qx,&mut qy);
+		r.smul(&mut lv);
+		lv=lineadd(&mut B,R,&mut sx,&mut sy);
+		r.smul(&mut lv);
+	}
+
+/* R-ate fixup */
+	if rom::CURVE_PAIRING_TYPE == rom::BN_CURVE {
+		r.conj();
+		K.copy(&P);
+		K.frob(&mut f);
+		A.neg();
+		lv=lineadd(&mut A,&mut K,&mut qx,&mut qy);
+		r.smul(&mut lv);
+		K.frob(&mut f);
+		K.neg();
+		lv=lineadd(&mut A,&mut K,&mut qx,&mut qy);
+		r.smul(&mut lv);
+
+		K.copy(&R);
+		K.frob(&mut f);
+		B.neg();
+		lv=lineadd(&mut B,&mut K,&mut sx,&mut sy);
+		r.smul(&mut lv);
+		K.frob(&mut f);
+		K.neg();
+		lv=lineadd(&mut B,&mut K,&mut sx,&mut sy);
+		r.smul(&mut lv);
+	}
+
+	return r;
+}
+
+/* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */
+pub fn fexp(m: &FP12) -> FP12 {
+	let mut f = FP2::new_bigs(&BIG::new_ints(&rom::CURVE_FRA),&BIG::new_ints(&rom::CURVE_FRB));
+	let mut x = BIG::new_ints(&rom::CURVE_BNX);
+	let mut r=FP12::new_copy(m);
+		
+/* Easy part of final exp */
+	let mut lv=FP12::new_copy(&r);
+	lv.inverse();
+	r.conj();
+
+	r.mul(&mut lv);
+	lv.copy(&r);
+	r.frob(&mut f);
+	r.frob(&mut f);
+	r.mul(&mut lv);
+/* Hard part of final exp */
+	if rom::CURVE_PAIRING_TYPE == rom::BN_CURVE {
+		lv.copy(&r);
+		lv.frob(&mut f);
+		let mut x0=FP12::new_copy(&lv);
+		x0.frob(&mut f);
+		lv.mul(&mut r);
+		x0.mul(&mut lv);
+		x0.frob(&mut f);
+		let mut x1=FP12::new_copy(&r);
+		x1.conj();
+		let mut x4=r.pow(&mut x);
+
+		let mut x3=FP12::new_copy(&x4);
+		x3.frob(&mut f);
+
+		let mut x2=x4.pow(&mut x);
+
+		let mut x5=FP12::new_copy(&x2); x5.conj();
+		lv=x2.pow(&mut x);
+
+		x2.frob(&mut f);
+		r.copy(&x2); r.conj();
+
+		x4.mul(&mut r);
+		x2.frob(&mut f);
+
+		r.copy(&lv);
+		r.frob(&mut f);
+		lv.mul(&mut r);
+
+		lv.usqr();
+		lv.mul(&mut x4);
+		lv.mul(&mut x5);
+		r.copy(&x3);
+		r.mul(&mut x5);
+		r.mul(&mut lv);
+		lv.mul(&mut x2);
+		r.usqr();
+		r.mul(&mut lv);
+		r.usqr();
+		lv.copy(&r);
+		lv.mul(&mut x1);
+		r.mul(&mut x0);
+		lv.usqr();
+		r.mul(&mut lv);
+		r.reduce();
+	} else {
+
+// Ghamman & Fouotsa Method
+
+		let mut y0=FP12::new_copy(&r); y0.usqr();
+		let mut y1=y0.pow(&mut x);
+		x.fshr(1); let mut y2=y1.pow(&mut x); x.fshl(1);
+		let mut y3=FP12::new_copy(&r); y3.conj();
+		y1.mul(&mut y3);
+
+		y1.conj();
+		y1.mul(&mut y2);
+
+		y2=y1.pow(&mut x);
+
+		y3=y2.pow(&mut x);
+		y1.conj();
+		y3.mul(&mut y1);
+
+		y1.conj();
+		y1.frob(&mut f); y1.frob(&mut f); y1.frob(&mut f);
+		y2.frob(&mut f); y2.frob(&mut f);
+		y1.mul(&mut y2);
+
+		y2=y3.pow(&mut x);
+		y2.mul(&mut y0);
+		y2.mul(&mut r);
+
+		y1.mul(&mut y2);
+		y2.copy(&y3); y2.frob(&mut f);
+		y1.mul(&mut y2);
+		r.copy(&y1);
+		r.reduce();
+
+
+/*
+		let mut x0=FP12::new_copy(&r);
+		let mut x1=FP12::new_copy(&r);
+		lv.copy(&r); lv.frob(&mut f);
+		let mut x3=FP12::new_copy(&lv); x3.conj(); x1.mul(&mut x3);
+		lv.frob(&mut f); lv.frob(&mut f);
+		x1.mul(&mut lv);
+
+		r=r.pow(&mut x);  //r=r.pow(x);
+		x3.copy(&r); x3.conj(); x1.mul(&mut x3);
+		lv.copy(&r); lv.frob(&mut f);
+		x0.mul(&mut lv);
+		lv.frob(&mut f);
+		x1.mul(&mut lv);
+		lv.frob(&mut f);
+		x3.copy(&lv); x3.conj(); x0.mul(&mut x3);
+
+		r=r.pow(&mut x);
+		x0.mul(&mut r);
+		lv.copy(&r); lv.frob(&mut f); lv.frob(&mut f);
+		x3.copy(&lv); x3.conj(); x0.mul(&mut x3);
+		lv.frob(&mut f);
+		x1.mul(&mut lv);
+
+		r=r.pow(&mut x);
+		lv.copy(&r); lv.frob(&mut f);
+		x3.copy(&lv); x3.conj(); x0.mul(&mut x3);
+		lv.frob(&mut f);
+		x1.mul(&mut lv);
+
+		r=r.pow(&mut x);
+		x3.copy(&r); x3.conj(); x0.mul(&mut x3);
+		lv.copy(&r); lv.frob(&mut f);
+		x1.mul(&mut lv);
+
+		r=r.pow(&mut x);
+		x1.mul(&mut r);
+
+		x0.usqr();
+		x0.mul(&mut x1);
+		r.copy(&x0);
+		r.reduce();  */
+	}
+	return r;
+}
+
+#[allow(non_snake_case)]
+/* GLV method */
+fn glv(e: &mut BIG) -> [BIG;2] {
+	let mut u:[BIG;2]=[BIG::new(),BIG::new()];
+	if rom::CURVE_PAIRING_TYPE == rom::BN_CURVE {
+		let mut t=BIG::new();
+		let q=BIG::new_ints(&rom::CURVE_ORDER);
+		let mut v:[BIG;2]=[BIG::new(),BIG::new()];
+
+		for i in 0..2 {
+			t.copy(&BIG::new_ints(&rom::CURVE_W[i]));  // why not just t=new BIG(ROM.CURVE_W[i]); 
+			let mut d:DBIG = BIG::mul(&mut t,e);
+			v[i].copy(&d.div(&q));
+		}
+		u[0].copy(&e);
+		for i in 0..2 {
+			for j in 0..2 {
+				t=BIG::new_ints(&rom::CURVE_SB[j][i]);
+				t=BIG::modmul(&mut v[j],&mut t,&q);
+				u[i].add(&q);
+				u[i].sub(&t);
+				u[i].rmod(&q);
+			}
+		}
+	} else {
+		let q=BIG::new_ints(&rom::CURVE_ORDER);
+		let x=BIG::new_ints(&rom::CURVE_BNX);
+		let x2=BIG::smul(&x,&x);
+		u[0].copy(&e);  
+		u[0].rmod(&x2);
+		u[1].copy(&e); 
+		u[1].div(&x2);
+		u[1].rsub(&q);
+	}
+	return u;
+}
+
+#[allow(non_snake_case)]
+/* Galbraith & Scott Method */
+pub fn gs(e: &mut BIG) -> [BIG;4] {
+	let mut u:[BIG;4]=[BIG::new(),BIG::new(),BIG::new(),BIG::new()];
+	if rom::CURVE_PAIRING_TYPE == rom::BN_CURVE {
+		let mut t=BIG::new();
+		let q=BIG::new_ints(&rom::CURVE_ORDER);
+
+		let mut v:[BIG;4]=[BIG::new(),BIG::new(),BIG::new(),BIG::new()];
+		for i in 0..4 {
+			t.copy(&BIG::new_ints(&rom::CURVE_WB[i]));
+			let mut d:DBIG=BIG::mul(&mut t,e);
+			v[i].copy(&d.div(&q));
+		}
+		u[0].copy(&e);
+		for i in 0..4 {
+			for j in 0..4 {
+				t=BIG::new_ints(&rom::CURVE_BB[j][i]);
+				t=BIG::modmul(&mut v[j],&mut t,&q);
+				u[i].add(&q);
+				u[i].sub(&t);
+				u[i].rmod(&q);
+			}
+		}
+	} else {
+		let x=BIG::new_ints(&rom::CURVE_BNX);
+		let mut w=BIG::new_copy(&e);
+		for i in 0..4 {
+			u[i].copy(&w);
+			u[i].rmod(&x);
+			w.div(&x);
+		}
+	}
+	return u;
+}	
+
+#[allow(non_snake_case)]
+/* Multiply P by e in group G1 */
+pub fn g1mul(P: &mut ECP,e: &mut BIG) -> ECP {
+	let mut R=ECP::new();
+	if rom::USE_GLV {
+		P.affine();
+		R.copy(P);
+		let mut Q=ECP::new();
+		Q.copy(P);
+		let q=BIG::new_ints(&rom::CURVE_ORDER);
+		let mut cru=FP::new_big(&BIG::new_ints(&rom::CURVE_CRU));
+		let mut u=glv(e);
+		Q.mulx(&mut cru);
+
+		let mut np=u[0].nbits();
+		let mut t:BIG=BIG::modneg(&mut u[0],&q);
+		let mut nn=t.nbits();
+		if nn<np {
+			u[0].copy(&t);
+			R.neg();
+		}
+
+		np=u[1].nbits();
+		t=BIG::modneg(&mut u[1],&q);
+		nn=t.nbits();
+		if nn<np {
+			u[1].copy(&t);
+			Q.neg();
+		}
+
+		R=R.mul2(&u[0],&mut Q,&u[1]);
+			
+	} else {
+		R=P.mul(e);
+	}
+	return R;
+}
+
+#[allow(non_snake_case)]
+/* Multiply P by e in group G2 */
+pub fn g2mul(P: &mut ECP2,e: &mut BIG) -> ECP2 {
+	let mut R=ECP2::new();
+	if rom::USE_GS_G2 {
+		let mut Q:[ECP2;4]=[ECP2::new(),ECP2::new(),ECP2::new(),ECP2::new()];
+		let mut f = FP2::new_bigs(&BIG::new_ints(&rom::CURVE_FRA),&BIG::new_ints(&rom::CURVE_FRB));
+		let q=BIG::new_ints(&rom::CURVE_ORDER);
+		let mut u=gs(e);
+		let mut T=ECP2::new();
+
+		let mut t=BIG::new();
+		P.affine();
+		Q[0].copy(&P);
+		for i in 1..4 {
+			T.copy(&Q[i-1]);
+			Q[i].copy(&T);
+			Q[i].frob(&mut f);
+		}
+		for i in 0..4 {
+			let np=u[i].nbits();
+			t.copy(&BIG::modneg(&mut u[i],&q));
+			let nn=t.nbits();
+			if nn<np {
+				u[i].copy(&t);
+				Q[i].neg();
+			}
+		}
+
+		R.copy(&ECP2::mul4(&mut Q,&u));
+
+	} else {
+		R.copy(&P.mul(e));
+	}
+	return R;
+}
+
+/* f=f^e */
+/* Note that this method requires a lot of RAM! Better to use compressed XTR method, see FP4.java */
+pub fn gtpow(d: &mut FP12,e: &mut BIG) -> FP12 {
+	let mut r=FP12::new();
+	if rom::USE_GS_GT {
+		let mut g:[FP12;4]=[FP12::new(),FP12::new(),FP12::new(),FP12::new()];
+		let mut f = FP2::new_bigs(&BIG::new_ints(&rom::CURVE_FRA),&BIG::new_ints(&rom::CURVE_FRB));
+		let q=BIG::new_ints(&rom::CURVE_ORDER);
+		let mut t=BIG::new();
+		let mut u=gs(e);
+		let mut w=FP12::new();
+
+		g[0].copy(&d);
+		for i in 1..4 {
+			w.copy(&g[i-1]);
+			g[i].copy(&w);
+			g[i].frob(&mut f);
+		}
+		for i in 0..4 {
+			let np=u[i].nbits();
+			t.copy(&BIG::modneg(&mut u[i],&q));
+			let nn=t.nbits();
+			if nn<np {
+				u[i].copy(&t);
+				g[i].conj();
+			}
+		}
+		r.copy(&FP12::pow4(&mut g,&u));
+	} else {
+		r.copy(&d.pow(e));
+	}
+	return r;
+}
+
+/*
+#[allow(non_snake_case)]
+fn main()
+{
+	let mut Q=ECP::new_bigs(&BIG::new_ints(&rom::CURVE_GX),&BIG::new_ints(&rom::CURVE_GY));
+	let mut P=ECP2::new_fp2s(&FP2::new_bigs(&BIG::new_ints(&rom::CURVE_PXA),&BIG::new_ints(&rom::CURVE_PXB)),&FP2::new_bigs(&BIG::new_ints(&rom::CURVE_PYA),&BIG::new_ints(&rom::CURVE_PYB)));
+
+	let mut r=BIG::new_ints(&rom::CURVE_ORDER);
+	
+	println!("P= {}",P.tostring());
+	println!("Q= {}",Q.tostring());
+
+	//m:=NewBIGint(17)
+
+	let mut e=ate(&mut P,&mut Q);
+	println!("\ne= {}",e.tostring());
+
+	e=fexp(&e);
+
+	for i in 1..10 {
+		e=ate(&mut P,&mut Q);
+		e=fexp(&e);
+	}
+
+
+	//	e=GTpow(e,m);
+
+	println!("\ne= {}",e.tostring());
+
+	
+	fmt.Printf("\n");
+	GLV:=glv(r)
+
+	fmt.Printf("GLV[0]= "+GLV[0].toString())
+	fmt.Printf("\n")
+
+	fmt.Printf("GLV[0]= "+GLV[1].toString())
+	fmt.Printf("\n")
+
+	G:=NewECP(); G.copy(Q)
+	R:=NewECP2(); R.copy(P)
+
+
+	e=ate(R,Q)
+	e=fexp(e)
+
+	e=GTpow(e,xa)
+	fmt.Printf("\ne= "+e.toString());
+	fmt.Printf("\n")
+
+	R=G2mul(R,xa)
+	e=ate(R,G)
+	e=fexp(e)
+
+	fmt.Printf("\ne= "+e.toString())
+	fmt.Printf("\n")
+
+	G=G1mul(G,xa)
+	e=ate(P,G)
+	e=fexp(e)
+	fmt.Printf("\ne= "+e.toString())
+	fmt.Printf("\n") 
+}*/
diff --git a/version22/rust/src/rand.rs b/version22/rust/src/rand.rs
new file mode 100644
index 0000000..5cf79ac
--- /dev/null
+++ b/version22/rust/src/rand.rs
@@ -0,0 +1,147 @@
+/*
+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.
+*/
+
+//mod hash256;
+
+use hash256::HASH256;
+
+const RAND_NK: usize=21;
+const RAND_NJ: usize=6;
+const RAND_NV: usize=8;
+
+pub struct RAND {
+	ira: [u32;RAND_NK],  /* random number...   */
+	rndptr: usize,
+	borrow: u32,
+	pool_ptr: usize,
+	pool: [u8;32]
+}
+
+impl RAND {
+
+	pub fn new() -> RAND {
+		RAND {
+			ira: [0;RAND_NK],
+			rndptr:0,
+			borrow: 0,
+			pool_ptr:0,
+			pool:[0;32]
+		}
+	}
+
+	pub fn clean(&mut self) {
+		self.pool_ptr=0; self.rndptr=0;
+		for i in 0..32 {self.pool[i]=0}
+		for i in 0..RAND_NK {self.ira[i]=0}
+		self.borrow=0;		
+	}
+
+	fn sbrand(&mut self) -> u32 { /* Marsaglia & Zaman random number generator */
+		self.rndptr+=1;
+		if self.rndptr<RAND_NK {return self.ira[self.rndptr]}
+		self.rndptr=0;
+		let mut k=RAND_NK-RAND_NJ;
+		for i in 0..RAND_NK { /* calculate next NK values */
+			if k==RAND_NK {k=0}
+			let t=self.ira[k];
+			let pdiff=t.wrapping_sub(self.ira[i]).wrapping_sub(self.borrow);
+			if pdiff<t {self.borrow=0}
+			if pdiff>t {self.borrow=1}
+			self.ira[i]=pdiff;
+			k+=1;
+		}
+		return self.ira[0];
+	}
+
+	fn sirand(&mut self,seed: u32) {
+		let mut m: u32=1;
+		let mut sd=seed;
+		self.borrow=0;
+		self.rndptr=0;
+		self.ira[0]^=sd;
+		for i in 1..RAND_NK { /* fill initialisation vector */
+			let inn=(RAND_NV*i)%RAND_NK;
+			self.ira[inn]^=m;      /* note XOR */
+			let t=m;
+			m=sd.wrapping_sub(m);
+			sd=t;
+		}
+		for _ in 0..10000 {self.sbrand();} /* "warm-up" & stir the generator */
+	}
+
+	fn fill_pool(&mut self) {
+		let mut sh=HASH256::new();
+		for _ in 0..128 {sh.process((self.sbrand()&0xff) as u8)}
+		let w=sh.hash();
+		for i in 0..32 {self.pool[i]=w[i]}
+		self.pool_ptr=0;
+	}
+
+	fn pack(b: [u8;4]) -> u32 { /* pack 4 bytes into a 32-bit Word */
+		return ((((b[3] as u32))&0xff)<<24)|(((b[2] as u32)&0xff)<<16)|(((b[1] as u32)&0xff)<<8)|((b[0] as u32)&0xff);
+	}
+
+/* Initialize RNG with some real entropy from some external source */
+	pub fn seed(&mut self,rawlen: usize,raw: &[u8]) { /* initialise from at least 128 byte string of raw random entropy */
+		let mut b: [u8;4]=[0;4];
+		let mut sh=HASH256::new();
+		self.pool_ptr=0;
+
+		for i in 0..RAND_NK {self.ira[i]=0}
+		if rawlen>0 {
+			for i in 0..rawlen {
+				sh.process(raw[i]);
+			}
+			let digest=sh.hash();
+
+/* initialise PRNG from distilled randomness */
+
+			for i in 0..8  {
+				b[0]=digest[4*i]; b[1]=digest[4*i+1]; b[2]=digest[4*i+2]; b[3]=digest[4*i+3];
+				self.sirand(RAND::pack(b));
+			}
+		}
+		self.fill_pool();
+	}	
+
+/* get random byte */
+	pub fn getbyte(&mut self) -> u8 { 
+		let r=self.pool[self.pool_ptr];
+		self.pool_ptr+=1;
+		if self.pool_ptr>=32 {self.fill_pool()}
+		return (r&0xff) as u8;
+	}
+}
+
+/* test main program */
+/*
+fn main() {
+	let mut raw : [u8;100]=[0;100];
+	let mut rng=RAND::new();
+
+	rng.clean();
+	for i in 0..100 {raw[i]=i as u8}
+
+	rng.seed(100,&raw);
+ 
+	for _ in 0..1000 {
+		print!("{:03} ",rng.getbyte());
+	}
+}
+*/
diff --git a/version22/rust/src/rom32.rs b/version22/rust/src/rom32.rs
new file mode 100644
index 0000000..72f5e00
--- /dev/null
+++ b/version22/rust/src/rom32.rs
@@ -0,0 +1,349 @@
+/*
+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.
+*/
+
+pub type Chunk=i32;
+pub type DChunk=i64;
+pub const CHUNK:usize=32;
+
+pub const NOT_SPECIAL:usize =0;
+pub const PSEUDO_MERSENNE:usize=1;
+pub const MONTGOMERY_FRIENDLY:usize=2;
+pub const GENERALISED_MERSENNE:usize=3;
+pub const WEIERSTRASS:usize=0;
+pub const EDWARDS:usize=1;
+pub const MONTGOMERY:usize=2;
+pub const BN_CURVE: usize=0;
+pub const BLS_CURVE: usize=1;
+
+
+// Curve 25519
+#[cfg(feature = "Ed25519")]
+pub const MODBITS: usize = 255;
+#[cfg(feature = "Ed25519")]
+pub const MOD8: usize = 5;
+#[cfg(feature = "Ed25519")]
+pub const BASEBITS: usize = 29;
+#[cfg(feature = "Ed25519")]
+pub const AES_S: usize=0;
+
+// GOLDILOCKS
+#[cfg(feature = "GOLDILOCKS")]
+pub const MODBITS: usize=448;
+#[cfg(feature = "GOLDILOCKS")]
+pub const MOD8: usize=7;
+#[cfg(feature = "GOLDILOCKS")]
+pub const BASEBITS: usize=29;
+#[cfg(feature = "GOLDILOCKS")]
+pub const AES_S: usize= 0;
+
+
+// BN254 Curve
+#[cfg(feature = "BN254")]
+pub const MODBITS:usize = 254; /* Number of bits in Modulus */
+#[cfg(feature = "BN254")]
+pub const MOD8:usize = 3;   /* Modulus mod 8 */
+#[cfg(feature = "BN254")]
+pub const BASEBITS:usize = 29;
+#[cfg(feature = "BN254")]
+pub const AES_S:usize=0;
+
+// BLS383 Curve
+#[cfg(feature = "BLS383")]
+pub const MODBITS:usize = 383; /* Number of bits in Modulus */
+#[cfg(feature = "BLS383")]
+pub const MOD8: usize = 3;  /* Modulus mod 8 */
+#[cfg(feature = "BLS383")]
+pub const BASEBITS:usize = 28;
+#[cfg(feature = "BLS383")]
+pub const AES_S: usize= 0;
+
+// BLS455 Curve
+#[cfg(feature = "BLS455")]
+pub const MODBITS:usize = 455; /* Number of bits in Modulus */
+#[cfg(feature = "BLS455")]
+pub const MOD8: usize = 3;  /* Modulus mod 8 */
+#[cfg(feature = "BLS455")]
+pub const BASEBITS:usize = 29;
+#[cfg(feature = "BLS455")]
+pub const AES_S: usize= 128;
+
+//---------------
+
+/* RSA/DH modulus length as multiple of BIGBITS */
+pub const FFLEN:usize=4;
+
+pub const NLEN: usize = (1+((MODBITS-1)/BASEBITS));
+pub const BIG_HEX_STRING_LEN:usize = NLEN * 16 + NLEN - 1;
+pub const DNLEN: usize = 2*NLEN;
+pub const BMASK: Chunk= ((1<<BASEBITS)-1);
+pub const MODBYTES: usize = 1+(MODBITS-1)/8;
+pub const NEXCESS:isize = (1<<((CHUNK)-BASEBITS-1));
+pub const FEXCESS:Chunk = ((1 as Chunk)<<(BASEBITS*(NLEN)-MODBITS));
+pub const OMASK:Chunk = (-1)<<(MODBITS%BASEBITS);
+pub const TBITS:usize=MODBITS%BASEBITS; // Number of active bits in top word
+pub const TMASK:Chunk=(1<<TBITS)-1;
+pub const BIGBITS:usize = (MODBYTES*8);
+pub const HBITS: usize=(BASEBITS/2);
+pub const HMASK: Chunk= ((1<<HBITS)-1);
+
+/* Finite field support - for RSA, DH etc. */
+pub const FF_BITS:usize=(BIGBITS*FFLEN); /* Finite Field Size in bits - must be 256.2^n */
+pub const HFLEN:usize=(FFLEN/2);  /* Useful for half-size RSA private key operations */
+
+pub const P_MBITS:usize=(MODBYTES as usize)*8;
+pub const P_MB: usize=(P_MBITS%BASEBITS);
+pub const P_OMASK:Chunk=((-1)<<(P_MBITS%BASEBITS));
+pub const P_FEXCESS: Chunk=(1<<(BASEBITS*NLEN-P_MBITS));
+pub const P_TBITS: usize=(P_MBITS%BASEBITS);
+
+
+// Curve25519 Modulus 
+#[cfg(feature = "Ed25519")]
+pub const MODTYPE:usize=PSEUDO_MERSENNE;
+#[cfg(feature = "Ed25519")]
+pub const MODULUS:[Chunk;NLEN]=[0x1FFFFFED,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFFF];
+#[cfg(feature = "Ed25519")]
+pub const MCONST:Chunk=19;
+
+//GOLDILOCKS
+#[cfg(feature = "GOLDILOCKS")]
+pub const MODTYPE: usize=GENERALISED_MERSENNE;
+#[cfg(feature = "GOLDILOCKS")]
+pub const MODULUS:[Chunk;NLEN]=[0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FDFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFF];
+#[cfg(feature = "GOLDILOCKS")]
+pub const MCONST: Chunk=0x1;
+
+
+// BN254 Curve Modulus
+#[cfg(feature = "BN254")]
+pub const MODTYPE:usize = NOT_SPECIAL;
+#[cfg(feature = "BN254")]
+pub const MODULUS:[Chunk;NLEN] = [0x13,0x18000000,0x4E9,0x2000000,0x8612,0x6C00000,0x6E8D1,0x10480000,0x252364];
+#[cfg(feature = "BN254")]
+pub const MCONST:Chunk=0x179435E5;
+
+// BLS383 Curve
+#[cfg(feature = "BLS383")]
+pub const MODTYPE:usize = NOT_SPECIAL;
+#[cfg(feature = "BLS383")]
+pub const MODULUS:[Chunk;NLEN] = [0xAAD556B,0xACAAB52,0x5F75D7A,0x1BB0147,0xD5D7520,0xCF73083,0xF99EB16,0x531820,0xA68EA32,0x2C01355,0x552A785,0x5C6105C,0x80A9F7,0x7AC52];
+#[cfg(feature = "BLS383")]
+pub const MCONST:Chunk=0x123D0BD;
+
+// BLS455 Curve
+#[cfg(feature = "BLS455")]
+pub const MODTYPE:usize = NOT_SPECIAL;
+#[cfg(feature = "BLS455")]
+pub const MODULUS:[Chunk;NLEN] = [0x2AB,0x1500000C,0xAAA55AA,0xB12AAD6,0x6D1BA6C,0xCCA5674,0x12E2CF6E,0xA9F9662,0x34BD939,0x12D8EAB1,0xFD9978E,0x9240600,0xE0F95B,0xAAB9550,0x55555E5,0xAAAAB];
+#[cfg(feature = "BLS455")]
+pub const MCONST:Chunk=0x1F4017FD;
+
+
+// Ed25519 Curve 
+#[cfg(feature = "Ed25519")]
+pub const CURVETYPE:usize=EDWARDS;
+#[cfg(feature = "Ed25519")]
+pub const CURVE_A:isize = -1;
+#[cfg(feature = "Ed25519")]
+pub const CURVE_B:[Chunk;NLEN]=[0x135978A3,0xF5A6E50,0x10762ADD,0x149A82,0x1E898007,0x3CBBBC,0x19CE331D,0x1DC56DFF,0x52036C];
+#[cfg(feature = "Ed25519")]
+pub const CURVE_ORDER:[Chunk;NLEN]=[0x1CF5D3ED,0x9318D2,0x1DE73596,0x1DF3BD45,0x14D,0x0,0x0,0x0,0x100000];
+#[cfg(feature = "Ed25519")]
+pub const CURVE_GX:[Chunk;NLEN]=[0xF25D51A,0xAB16B04,0x969ECB2,0x198EC12A,0xDC5C692,0x1118FEEB,0xFFB0293,0x1A79ADCA,0x216936];
+#[cfg(feature = "Ed25519")]
+pub const CURVE_GY:[Chunk;NLEN]=[0x6666658,0x13333333,0x19999999,0xCCCCCCC,0x6666666,0x13333333,0x19999999,0xCCCCCCC,0x666666];
+
+// GOLDILOCKS
+#[cfg(feature = "GOLDILOCKS")]
+pub const CURVETYPE: usize=EDWARDS;
+#[cfg(feature = "GOLDILOCKS")]
+pub const CURVE_A: isize=1;
+#[cfg(feature = "GOLDILOCKS")]
+pub const CURVE_ORDER:[Chunk;NLEN]=[0xB5844F3,0x1BC61495,0x1163D548,0x1984E51B,0x3690216,0xDA4D76B,0xFA7113B,0x1FEF9944,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FF];
+#[cfg(feature = "GOLDILOCKS")]
+pub const CURVE_B:[Chunk;NLEN]=[0x1FFF6756,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FDFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFF];
+#[cfg(feature = "GOLDILOCKS")]
+pub const CURVE_GX:[Chunk;NLEN]=[0x15555555,0xAAAAAAA,0x15555555,0xAAAAAAA,0x15555555,0xAAAAAAA,0x15555555,0x152AAAAA,0xAAAAAAA,0x15555555,0xAAAAAAA,0x15555555,0xAAAAAAA,0x15555555,0xAAAAAAA,0x1555];
+#[cfg(feature = "GOLDILOCKS")]
+pub const CURVE_GY:[Chunk;NLEN]=[0xA9386ED,0x1757DE6F,0x13681AF6,0x19657DA3,0x3098BBB,0x12C19D15,0x12E03595,0xE515B18,0x17B7E36D,0x1AC426E,0xDBB5E8,0x10D8560,0x159D6205,0xB8246D9,0x17A58D2B,0x15C0];
+
+// BN254 Curve
+#[cfg(feature = "BN254")]
+pub const CURVETYPE:usize = WEIERSTRASS;
+#[cfg(feature = "BN254")]
+pub const CURVE_PAIRING_TYPE:usize = BN_CURVE;
+#[cfg(feature = "BN254")]
+pub const CURVE_A:isize = 0;
+#[cfg(feature = "BN254")]
+pub const CURVE_B:[Chunk;NLEN]=[0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+#[cfg(feature = "BN254")]
+pub const CURVE_ORDER:[Chunk;NLEN]=[0xD,0x8000000,0x428,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364];
+#[cfg(feature = "BN254")]
+pub const CURVE_GX:[Chunk;NLEN]=[0x12,0x18000000,0x4E9,0x2000000,0x8612,0x6C00000,0x6E8D1,0x10480000,0x252364];
+#[cfg(feature = "BN254")]
+pub const CURVE_GY:[Chunk;NLEN]=[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+
+#[cfg(feature = "BN254")]
+pub const CURVE_FRA:[Chunk;NLEN]=[0xF2A6DE9,0xBEF3603,0xFDDF0B8,0x12E9249A,0x953F850,0xDA85423,0x1232D926,0x32425CF,0x1B3776];
+#[cfg(feature = "BN254")]
+pub const CURVE_FRB:[Chunk;NLEN]=[0x10D5922A,0xC10C9FC,0x10221431,0xF16DB65,0x16AC8DC1,0x1917ABDC,0xDD40FAA,0xD23DA30,0x9EBEE];
+#[cfg(feature = "BN254")]
+pub const CURVE_PXA:[Chunk;NLEN]=[0x803FB2B,0xF721126,0x62FC364,0x9177691,0x1EDB6A46,0x63F4630,0x18BFAE36,0x176A33D6,0x61A10];
+#[cfg(feature = "BN254")]
+pub const CURVE_PXB:[Chunk;NLEN]=[0x7D54CF3,0xC61A60F,0xDE12DC3,0x1AE8D75C,0xAA5B1F4,0x13C62CC1,0xCCC42A,0x1F374E6F,0x516AA];
+#[cfg(feature = "BN254")]
+pub const CURVE_PYA:[Chunk;NLEN]=[0x11CD2B9A,0xF8703C4,0xF826F46,0x1A15CD7B,0x822329B,0x104B34C6,0xD0E6A43,0x140D75F2,0x21897];
+#[cfg(feature = "BN254")]
+pub const CURVE_PYB:[Chunk;NLEN]=[0xB3ACE9B,0x1168D763,0xE7255E2,0xDFFAE,0x18D37B09,0x22B7AF9,0x149A3DB5,0x1CF9162,0xEBB2B];
+#[cfg(feature = "BN254")]
+pub const CURVE_BNX:[Chunk;NLEN]=[0x1,0x4000000,0x10,0x0,0x0,0x0,0x0,0x0,0x0];
+#[cfg(feature = "BN254")]
+pub const CURVE_COF:[Chunk;NLEN]=[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+#[cfg(feature = "BN254")]
+pub const CURVE_CRU:[Chunk;NLEN]=[0x7,0xC000000,0x1B3,0x12000000,0x2490,0x11200000,0x126CD,0x0,0x0];
+#[cfg(feature = "BN254")]
+pub const CURVE_W:[[Chunk;NLEN];2]=[[0x3,0x0,0x81,0x3000000,0x618,0x0,0x0,0x0,0x0],[0x1,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0]];
+#[cfg(feature = "BN254")]
+pub const CURVE_SB:[[[Chunk;NLEN];2];2]=[[[0x4,0x8000000,0xA1,0x3000000,0x618,0x0,0x0,0x0,0x0],[0x1,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x1,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0],[0xA,0x8000000,0x3A7,0x1C000000,0x79E1,0x6C00000,0x6E8D1,0x10480000,0x252364]]];
+#[cfg(feature = "BN254")]
+pub const CURVE_WB:[[Chunk;NLEN];4]=[[0x0,0x4000000,0x10,0x1000000,0x208,0x0,0x0,0x0,0x0],[0x5,0x14000000,0x152,0xE000000,0x1C70,0xC00000,0xC489,0x0,0x0],[0x3,0xC000000,0xB1,0x7000000,0xE38,0x10600000,0x6244,0x0,0x0],[0x1,0xC000000,0x30,0x1000000,0x208,0x0,0x0,0x0,0x0]];
+#[cfg(feature = "BN254")]
+pub const CURVE_BB:[[[Chunk;NLEN];4];4]=[[[0xD,0x4000000,0x418,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364],[0xC,0x4000000,0x418,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364],[0xC,0x4000000,0x418,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364],[0x2,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x1,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0],[0xC,0x4000000,0x418,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364],[0xD,0x4000000,0x418,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364],[0xC,0x4000000,0x418,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364]],[[0x2,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0],[0x1,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0],[0x1,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0],[0x1,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x2,0x4000000,0x10,0x0,0x0,0x0,0x0,0x0,0x0],[0x2,0x10000000,0x40,0x0,0x0,0x0,0x0,0x0,0x0],[0xA,0x0,0x408,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364],[0x2,0x4000000,0x10,0x0,0x0,0x0,0x0,0x0,0x0]]];
+
+#[cfg(feature = "BN254")]
+pub const USE_GLV:bool = true;
+#[cfg(feature = "BN254")]
+pub const USE_GS_G2:bool = true;
+#[cfg(feature = "BN254")]
+pub const USE_GS_GT:bool = true;
+#[cfg(feature = "BN254")]
+pub const GT_STRONG:bool = false;
+
+
+
+// BLS383 Curve
+#[cfg(feature = "BLS383")]
+pub const CURVETYPE:usize = WEIERSTRASS;
+#[cfg(feature = "BLS383")]
+pub const CURVE_PAIRING_TYPE:usize = BLS_CURVE;
+#[cfg(feature = "BLS383")]
+pub const CURVE_A:isize = 0;
+
+#[cfg(feature = "BLS383")]
+pub const CURVE_ORDER:[Chunk;NLEN]=[0xFFF001,0xFFF8000,0xFE7800,0xBFDE007,0xC5EDF1C,0x3000049,0x910007A,0xC40007F,0x641004C,0x14,0x0,0x0,0x0,0x0];
+#[cfg(feature = "BLS383")]
+pub const CURVE_B:[Chunk;NLEN]=[0x9,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+#[cfg(feature = "BLS383")]
+pub const CURVE_COF:[Chunk;NLEN]=[0x52B,0x2A00,0xAAB2CA0,0x5560AAA,0x6055,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+#[cfg(feature = "BLS383")]
+pub const CURVE_GX:[Chunk;NLEN]=[0xD10786B,0xD59B348,0x3F54AD0,0x3477C0E,0x4578B9B,0xBF25B73,0x7BB6F65,0x4F6AC00,0xFF57E9C,0xEFD5830,0xFB6EC02,0xADB9F88,0xEE4BC98,0xB08C];
+#[cfg(feature = "BLS383")]
+pub const CURVE_GY:[Chunk;NLEN]=[0xD145DDB,0x5DA023,0x5FEF7CC,0x13F518C,0x2B2A66F,0x56EC346,0xC7A925F,0x96F3019,0x981223E,0x9061047,0x8F5BE59,0x4810AD,0x9337671,0x1F390];
+
+#[cfg(feature = "BLS383")]
+pub const CURVE_BNX:[Chunk;NLEN]=[0x40,0x100,0x110,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+#[cfg(feature = "BLS383")]
+pub const CURVE_CRU:[Chunk;NLEN]=[0xDA155A9,0xA3AAC4E,0x61E5E3D,0xDF2FE87,0xE632625,0xBCDFAAD,0xD3035A6,0x5123128,0xBEAD683,0xDBF3A2B,0x424190,0x5C5FAB2,0x80A9F7,0x7AC52];
+#[cfg(feature = "BLS383")]
+pub const CURVE_FRA:[Chunk;NLEN]=[0x2B4508B,0x2BA59A9,0x6EEF343,0x63DB7A0,0x1DFBC74,0x40341CB,0x32D55D3,0x1639E9D,0x5CC36D4,0xB19B3F0,0xD86AB98,0xF323EE4,0xB198672,0x5A5F];
+#[cfg(feature = "BLS383")]
+pub const CURVE_FRB:[Chunk;NLEN]=[0x7F904E0,0x81051A9,0xF086A37,0xB7D49A6,0xB7DB8AB,0x8F3EEB8,0xC6C9543,0xEEF7983,0x49CB35D,0x7A65F65,0x7CBFBEC,0x693D177,0x5672384,0x751F2];
+#[cfg(feature = "BLS383")]
+pub const CURVE_PXA:[Chunk;NLEN]=[0xBAC9472,0x6059885,0xE2DC36D,0x7C4D31D,0x8C88A7,0xBDC90C3,0x1C688FC,0x29F0197,0xC43F167,0x3693539,0x61EB8BF,0xD81E5A5,0x22B56BF,0x4D507];
+#[cfg(feature = "BLS383")]
+pub const CURVE_PXB:[Chunk;NLEN]=[0x272AB23,0x9B4BD7A,0xF44DCE8,0x7AF19D4,0x3206A34,0x3F6F7B9,0x2A819FB,0x571DD3E,0x635D7EE,0x3A2BA3B,0xC1A126,0xAC28C78,0x17C3E5B,0xEE36];
+#[cfg(feature = "BLS383")]
+pub const CURVE_PYA:[Chunk;NLEN]=[0x77BD4FD,0x81D2309,0xDFDFC6,0xB66072,0xC89A0C,0x41FC959,0x878287A,0x2E1FBCF,0x14EEE65,0x11C230,0x6BB325E,0x2887881,0x859A05C,0x8F40];
+#[cfg(feature = "BLS383")]
+pub const CURVE_PYB:[Chunk;NLEN]=[0x52C4CE6,0xA5E20A2,0xAFF40C8,0x5907A74,0x2448EF3,0x41760A4,0xFDA199,0xFFEF82B,0x8D4EA49,0xA0F29A1,0x6E4997B,0xAC7F7B8,0xBA88C12,0x1DCAB];
+
+#[cfg(feature = "BLS383")]
+pub const CURVE_W:[[Chunk;0];2]=[[],[]];
+#[cfg(feature = "BLS383")]
+pub const CURVE_SB:[[[Chunk;0];2];2]=[[[],[]],[[],[]]];
+#[cfg(feature = "BLS383")]
+pub const CURVE_WB:[[Chunk;0];4]=[[],[],[],[]];
+#[cfg(feature = "BLS383")]
+pub const CURVE_BB:[[[Chunk;0];4];4]=[[[],[],[],[]],[[],[],[],[]],[[],[],[],[]],[[],[],[],[]]];
+
+
+#[cfg(feature = "BLS383")]
+pub const USE_GLV:bool = true;
+#[cfg(feature = "BLS383")]
+pub const USE_GS_G2:bool = true;
+#[cfg(feature = "BLS383")]
+pub const USE_GS_GT:bool = true;
+#[cfg(feature = "BLS383")]
+pub const GT_STRONG:bool = false;
+
+// BLS455 Curve
+#[cfg(feature = "BLS455")]
+pub const CURVETYPE:usize = WEIERSTRASS;
+#[cfg(feature = "BLS455")]
+pub const CURVE_PAIRING_TYPE:usize = BLS_CURVE;
+#[cfg(feature = "BLS455")]
+pub const CURVE_A:isize = 0;
+
+#[cfg(feature = "BLS455")]
+pub const CURVE_ORDER:[Chunk;NLEN]=[0x1FC00001,0x3FFF,0x10000070,0x1400000,0x1D100,0xF0003A8,0x13C0009,0x1E200,0x180002E0,0x400001,0x4000,0x0,0x0,0x0,0x0,0x0];
+#[cfg(feature = "BLS455")]
+pub const CURVE_B:[Chunk;NLEN]=[0xA,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+#[cfg(feature = "BLS455")]
+pub const CURVE_COF:[Chunk;NLEN]=[0xABFFAAB,0x14AABFFD,0xD52AADA,0x1562AAAB,0x15556AAA,0x2A,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+#[cfg(feature = "BLS455")]
+pub const CURVE_GX:[Chunk;NLEN]=[0x1DFCEDD1,0x16A62EEF,0xE80D3ED,0xB8DE876,0x179C7253,0x182DAB52,0x46CC85F,0x1E571D9C,0x1E8392B1,0x1A155867,0x19E6527C,0x23DC64E,0xABEDA59,0xF20662B,0x17CECC01,0x310A];
+#[cfg(feature = "BLS455")]
+pub const CURVE_GY:[Chunk;NLEN]=[0x6619B9B,0x27EBCD,0x1BE80A19,0x13B014BA,0x191A4936,0x13911916,0x107A5A3B,0x1DCB0863,0x1F5FB1,0xDE44A9C,0x18E23B2A,0x1FA81FD3,0xB0D6DFA,0xC2FE1EF,0xDDFA7E2,0x3351B];
+
+#[cfg(feature = "BLS455")]
+pub const CURVE_BNX:[Chunk;NLEN]=[0x800,0x1000004,0x40000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+#[cfg(feature = "BLS455")]
+pub const CURVE_CRU:[Chunk;NLEN]=[0xAA9,0x9017FE0,0x128DD8AA,0x1F4A321E,0x148FEC90,0x195CDEEA,0xE961AA2,0x168D3B66,0xAFD99D7,0xB989AA6,0x1F9A5724,0x91A05FF,0xE0EF5B,0xAAB9548,0x55555E5,0xAAAAB];
+#[cfg(feature = "BLS455")]
+pub const CURVE_FRA:[Chunk;NLEN]=[0xA2EBF21,0x4E67DEE,0xCDE6590,0xE5EA94E,0x15454985,0x140CFC43,0x7E14D1C,0x1778395A,0x1944F022,0x166BEA1A,0xC3DEEA0,0x9F031A0,0x16A7459,0x1F1D6E00,0x125CFB72,0x72FD4];
+#[cfg(feature = "BLS455")]
+pub const CURVE_FRB:[Chunk;NLEN]=[0x15D1438A,0x1019821D,0x1DCBF01A,0x1CB40187,0x118C70E6,0x18BD5A30,0xB018251,0x13275D08,0xA06E916,0x1C6D0096,0x39BA8ED,0x1F33D460,0x1F768501,0xB8E274F,0x12F85A72,0x37AD6];
+#[cfg(feature = "BLS455")]
+pub const CURVE_PXA:[Chunk;NLEN]=[0x10C1F542,0x23AF907,0x159F840,0xBAC0E1F,0x133D7766,0x1C034C5D,0x14C5C875,0x1ED0BDA2,0x16A49C71,0x1E9FF62D,0x14F3ACC0,0x1E0C9FEA,0xC4638DE,0x74D18DA,0xBEA0030,0x5D962];
+#[cfg(feature = "BLS455")]
+pub const CURVE_PXB:[Chunk;NLEN]=[0x749F03D,0xC843773,0xB17BCBA,0x1134AB4B,0x8EA016E,0x1A0D766C,0x58F819E,0x48A1FCC,0xE296F62,0x83370E4,0xC9BA1D5,0x1E43290E,0xEE59A80,0x1FDD85F5,0x1F3819B6,0x1D9F];
+#[cfg(feature = "BLS455")]
+pub const CURVE_PYA:[Chunk;NLEN]=[0x181A77F4,0x191AD22,0x1E9F842A,0x1E1E6CF6,0xD55B9D9,0x1D062533,0x15BB1323,0x7ECBC1,0x1A9EC2EF,0x1EE14CE0,0x1E96B271,0xA794439,0x1C544324,0xE6AD5DC,0x16429B0F,0x448E3];
+#[cfg(feature = "BLS455")]
+pub const CURVE_PYB:[Chunk;NLEN]=[0x1E1FDBA2,0x1A09DB6C,0xF680D5B,0xFCC6122,0xC488E2A,0x1E489ECD,0x1005617E,0x1CF9EC36,0x1C89ED72,0x16C00D90,0x1563E595,0x1243DDC0,0x8698F9E,0x1BD81E7E,0xF2A0F4A,0x66A0];
+
+#[cfg(feature = "BLS455")]
+pub const CURVE_W:[[Chunk;0];2]=[[],[]];
+#[cfg(feature = "BLS455")]
+pub const CURVE_SB:[[[Chunk;0];2];2]=[[[],[]],[[],[]]];
+#[cfg(feature = "BLS455")]
+pub const CURVE_WB:[[Chunk;0];4]=[[],[],[],[]];
+#[cfg(feature = "BLS455")]
+pub const CURVE_BB:[[[Chunk;0];4];4]=[[[],[],[],[]],[[],[],[],[]],[[],[],[],[]],[[],[],[],[]]];
+
+
+#[cfg(feature = "BLS455")]
+pub const USE_GLV:bool = true;
+#[cfg(feature = "BLS455")]
+pub const USE_GS_G2:bool = true;
+#[cfg(feature = "BLS455")]
+pub const USE_GS_GT:bool = true;
+#[cfg(feature = "BLS455")]
+pub const GT_STRONG:bool = false;
+
diff --git a/version22/rust/src/rom64.rs b/version22/rust/src/rom64.rs
new file mode 100644
index 0000000..fc900ab
--- /dev/null
+++ b/version22/rust/src/rom64.rs
@@ -0,0 +1,348 @@
+/*
+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.
+*/
+
+pub type Chunk=i64;
+//pub type DChunk=i128;
+pub const CHUNK:usize=64;
+
+pub const NOT_SPECIAL:usize =0;
+pub const PSEUDO_MERSENNE:usize=1;
+pub const MONTGOMERY_FRIENDLY:usize=2;
+pub const GENERALISED_MERSENNE:usize=3;
+pub const WEIERSTRASS:usize=0;
+pub const EDWARDS:usize=1;
+pub const MONTGOMERY:usize=2;
+pub const BN_CURVE: usize=0;
+pub const BLS_CURVE: usize=1;
+
+
+// Curve 25519
+#[cfg(feature = "Ed25519")]
+pub const MODBITS: usize = 255;
+#[cfg(feature = "Ed25519")]
+pub const MOD8: usize = 5;
+#[cfg(feature = "Ed25519")]
+pub const BASEBITS: usize = 56;
+#[cfg(feature = "Ed25519")]
+pub const AES_S: usize=0;
+
+// GOLDILOCKS
+#[cfg(feature = "GOLDILOCKS")]
+pub const MODBITS: usize=448;
+#[cfg(feature = "GOLDILOCKS")]
+pub const MOD8: usize=7;
+#[cfg(feature = "GOLDILOCKS")]
+pub const BASEBITS: usize=60;
+#[cfg(feature = "GOLDILOCKS")]
+pub const AES_S: usize= 0;
+
+
+// BN254 Curve
+#[cfg(feature = "BN254")]
+pub const MODBITS:usize = 254; /* Number of bits in Modulus */
+#[cfg(feature = "BN254")]
+pub const MOD8:usize = 3;   /* Modulus mod 8 */
+#[cfg(feature = "BN254")]
+pub const BASEBITS:usize = 56;
+#[cfg(feature = "BN254")]
+pub const AES_S:usize=0;
+
+// BLS383 Curve
+#[cfg(feature = "BLS383")]
+pub const MODBITS:usize = 383; /* Number of bits in Modulus */
+#[cfg(feature = "BLS383")]
+pub const MOD8: usize = 3;  /* Modulus mod 8 */
+#[cfg(feature = "BLS383")]
+pub const BASEBITS:usize = 56;
+#[cfg(feature = "BLS383")]
+pub const AES_S: usize= 0;
+
+// BLS455 Curve
+#[cfg(feature = "BLS455")]
+pub const MODBITS:usize = 455; /* Number of bits in Modulus */
+#[cfg(feature = "BLS455")]
+pub const MOD8: usize = 3;  /* Modulus mod 8 */
+#[cfg(feature = "BLS455")]
+pub const BASEBITS:usize = 60;
+#[cfg(feature = "BLS455")]
+pub const AES_S: usize= 128;
+
+//---------------
+
+/* RSA/DH modulus length as multiple of BIGBITS */
+pub const FFLEN:usize=8;
+
+pub const NLEN: usize = (1+((MODBITS-1)/BASEBITS));
+pub const BIG_HEX_STRING_LEN:usize = NLEN * 16 + NLEN - 1;
+pub const DNLEN: usize = 2*NLEN;
+pub const BMASK: Chunk= ((1<<BASEBITS)-1);
+pub const MODBYTES: usize = 1+(MODBITS-1)/8;
+pub const NEXCESS:isize = (1<<((CHUNK)-BASEBITS-1));
+pub const FEXCESS:Chunk = ((1 as Chunk)<<(BASEBITS*(NLEN)-MODBITS));
+pub const OMASK:Chunk = (-1)<<(MODBITS%BASEBITS);
+pub const TBITS:usize=MODBITS%BASEBITS; // Number of active bits in top word
+pub const TMASK:Chunk=(1<<TBITS)-1;
+pub const BIGBITS:usize = (MODBYTES*8);
+pub const HBITS: usize=(BASEBITS/2);
+pub const HMASK: Chunk= ((1<<HBITS)-1);
+
+/* Finite field support - for RSA, DH etc. */
+pub const FF_BITS:usize=(BIGBITS*FFLEN); /* Finite Field Size in bits - must be 256.2^n */
+pub const HFLEN:usize=(FFLEN/2);  /* Useful for half-size RSA private key operations */
+
+pub const P_MBITS:usize=(MODBYTES as usize)*8;
+pub const P_MB: usize=(P_MBITS%BASEBITS);
+pub const P_OMASK:Chunk=((-1)<<(P_MBITS%BASEBITS));
+pub const P_FEXCESS: Chunk=(1<<(BASEBITS*NLEN-P_MBITS));
+pub const P_TBITS: usize=(P_MBITS%BASEBITS);
+
+
+// Curve25519 Modulus 
+#[cfg(feature = "Ed25519")]
+pub const MODTYPE:usize=PSEUDO_MERSENNE;
+#[cfg(feature = "Ed25519")]
+pub const MODULUS:[Chunk;NLEN]=[0xFFFFFFFFFFFFED,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0x7FFFFFFF];
+#[cfg(feature = "Ed25519")]
+pub const MCONST:Chunk=19;
+
+//GOLDILOCKS
+#[cfg(feature = "GOLDILOCKS")]
+pub const MODTYPE: usize=GENERALISED_MERSENNE;
+#[cfg(feature = "GOLDILOCKS")]
+pub const MODULUS: [Chunk;NLEN]= [0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFEFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFF];
+#[cfg(feature = "GOLDILOCKS")]
+pub const MCONST: Chunk=0x1;
+
+// BN254 Curve Modulus
+#[cfg(feature = "BN254")]
+pub const MODTYPE:usize = NOT_SPECIAL;
+#[cfg(feature = "BN254")]
+pub const MODULUS:[Chunk;NLEN] = [0x13,0x13A7,0x80000000086121,0x40000001BA344D,0x25236482];
+#[cfg(feature = "BN254")]
+pub const MCONST:Chunk=0x435E50D79435E5;
+
+// BLS383 Curve
+#[cfg(feature = "BLS383")]
+pub const MODTYPE:usize = NOT_SPECIAL;
+#[cfg(feature = "BLS383")]
+pub const MODULUS:[Chunk;NLEN] = [0xACAAB52AAD556B,0x1BB01475F75D7A,0xCF73083D5D7520,0x531820F99EB16,0x2C01355A68EA32,0x5C6105C552A785,0x7AC52080A9F7];
+#[cfg(feature = "BLS383")]
+pub const MCONST:Chunk=0xA59AB3B123D0BD;
+
+
+// BLS455 Curve
+#[cfg(feature = "BLS455")]
+pub const MODTYPE:usize = NOT_SPECIAL;
+#[cfg(feature = "BLS455")]
+pub const MODULUS:[Chunk;NLEN] = [0xAA00001800002AB,0xC589556B2AA956A,0xB9994ACE86D1BA6,0x3954FCB314B8B3D,0xE3A5B1D56234BD9,0x95B49203003F665,0x57955572AA00E0F,0x555559555];
+#[cfg(feature = "BLS455")]
+pub const MCONST:Chunk=0xB3EF8137F4017FD;
+
+
+// Ed25519 Curve 
+#[cfg(feature = "Ed25519")]
+pub const CURVETYPE:usize=EDWARDS;
+#[cfg(feature = "Ed25519")]
+pub const CURVE_A:isize = -1;
+#[cfg(feature = "Ed25519")]
+pub const CURVE_B:[Chunk;NLEN]=[0xEB4DCA135978A3,0xA4D4141D8AB75,0x797779E8980070,0x2B6FFE738CC740,0x52036CEE];
+#[cfg(feature = "Ed25519")]
+pub const CURVE_ORDER:[Chunk;NLEN]=[0x12631A5CF5D3ED,0xF9DEA2F79CD658,0x14DE,0x0,0x10000000];
+#[cfg(feature = "Ed25519")]
+pub const CURVE_GX:[Chunk;NLEN]=[0x562D608F25D51A,0xC7609525A7B2C9,0x31FDD6DC5C692C,0xCD6E53FEC0A4E2,0x216936D3];
+#[cfg(feature = "Ed25519")]
+pub const CURVE_GY:[Chunk;NLEN]=[0x66666666666658,0x66666666666666,0x66666666666666,0x66666666666666,0x66666666];
+
+// GOLDILOCKS
+#[cfg(feature = "GOLDILOCKS")]
+pub const CURVETYPE: usize= EDWARDS;
+#[cfg(feature = "GOLDILOCKS")]
+pub const CURVE_A: isize = 1;
+#[cfg(feature = "GOLDILOCKS")]
+pub const CURVE_B: [Chunk;NLEN]=[0xFFFFFFFFFFF6756,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFEFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFF];
+#[cfg(feature = "GOLDILOCKS")]
+pub const CURVE_ORDER: [Chunk;NLEN]=[0x378C292AB5844F3,0x6CC2728DC58F552,0xEDB49AED6369021,0xFFFF7CCA23E9C44,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0x3FFFFFF];
+#[cfg(feature = "GOLDILOCKS")]
+pub const CURVE_GX: [Chunk;NLEN]=[0x555555555555555,0x555555555555555,0x555555555555555,0xAAA955555555555,0xAAAAAAAAAAAAAAA,0xAAAAAAAAAAAAAAA,0xAAAAAAAAAAAAAAA,0xAAAAAAA];
+#[cfg(feature = "GOLDILOCKS")]
+pub const CURVE_GY: [Chunk;NLEN]=[0xAEAFBCDEA9386ED,0xBCB2BED1CDA06BD,0x565833A2A3098BB,0x6D728AD8C4B80D6,0x7A035884DD7B7E3,0x205086C2B0036ED,0x34AD7048DB359D6,0xAE05E96];
+
+
+// BN254 Curve
+#[cfg(feature = "BN254")]
+pub const CURVETYPE:usize = WEIERSTRASS;
+#[cfg(feature = "BN254")]
+pub const CURVE_PAIRING_TYPE:usize = BN_CURVE;
+#[cfg(feature = "BN254")]
+pub const CURVE_A:isize = 0;
+#[cfg(feature = "BN254")]
+pub const CURVE_B:[Chunk;NLEN]=[0x2,0x0,0x0,0x0,0x0];
+#[cfg(feature = "BN254")]
+pub const CURVE_ORDER:[Chunk;NLEN]=[0xD,0x800000000010A1,0x8000000007FF9F,0x40000001BA344D,0x25236482];
+#[cfg(feature = "BN254")]
+pub const CURVE_GX:[Chunk;NLEN]=[0x12,0x13A7,0x80000000086121,0x40000001BA344D,0x25236482];
+#[cfg(feature = "BN254")]
+pub const CURVE_GY:[Chunk;NLEN]=[0x1,0x0,0x0,0x0,0x0];
+
+#[cfg(feature = "BN254")]
+pub const CURVE_FRA:[Chunk;NLEN]=[0x7DE6C06F2A6DE9,0x74924D3F77C2E1,0x50A846953F8509,0x212E7C8CB6499B,0x1B377619];
+#[cfg(feature = "BN254")]
+pub const CURVE_FRB:[Chunk;NLEN]=[0x82193F90D5922A,0x8B6DB2C08850C5,0x2F57B96AC8DC17,0x1ED1837503EAB2,0x9EBEE69];
+#[cfg(feature = "BN254")]
+pub const CURVE_PXA:[Chunk;NLEN]=[0xEE4224C803FB2B,0x8BBB4898BF0D91,0x7E8C61EDB6A464,0x519EB62FEB8D8C,0x61A10BB];
+#[cfg(feature = "BN254")]
+pub const CURVE_PXB:[Chunk;NLEN]=[0x8C34C1E7D54CF3,0x746BAE3784B70D,0x8C5982AA5B1F4D,0xBA737833310AA7,0x516AAF9];
+#[cfg(feature = "BN254")]
+pub const CURVE_PYA:[Chunk;NLEN]=[0xF0E07891CD2B9A,0xAE6BDBE09BD19,0x96698C822329BD,0x6BAF93439A90E0,0x21897A0];
+#[cfg(feature = "BN254")]
+pub const CURVE_PYB:[Chunk;NLEN]=[0x2D1AEC6B3ACE9B,0x6FFD739C9578A,0x56F5F38D37B090,0x7C8B15268F6D44,0xEBB2B0E];
+#[cfg(feature = "BN254")]
+pub const CURVE_BNX:[Chunk;NLEN]=[0x80000000000001,0x40,0x0,0x0,0x0];
+#[cfg(feature = "BN254")]
+pub const CURVE_COF:[Chunk;NLEN]=[0x1,0x0,0x0,0x0,0x0];
+#[cfg(feature = "BN254")]
+pub const CURVE_CRU:[Chunk;NLEN]=[0x80000000000007,0x6CD,0x40000000024909,0x49B362,0x0];
+#[cfg(feature = "BN254")]
+pub const CURVE_W:[[Chunk;NLEN];2]=[[0x3,0x80000000000204,0x6181,0x0,0x0],[0x1,0x81,0x0,0x0,0x0]];
+#[cfg(feature = "BN254")]
+pub const CURVE_SB:[[[Chunk;NLEN];2];2]=[[[0x4,0x80000000000285,0x6181,0x0,0x0],[0x1,0x81,0x0,0x0,0x0]],[[0x1,0x81,0x0,0x0,0x0],[0xA,0xE9D,0x80000000079E1E,0x40000001BA344D,0x25236482]]];
+#[cfg(feature = "BN254")]
+pub const CURVE_WB:[[Chunk;NLEN];4]=[[0x80000000000000,0x80000000000040,0x2080,0x0,0x0],[0x80000000000005,0x54A,0x8000000001C707,0x312241,0x0],[0x80000000000003,0x800000000002C5,0xC000000000E383,0x189120,0x0],[0x80000000000001,0x800000000000C1,0x2080,0x0,0x0]];
+#[cfg(feature = "BN254")]
+pub const CURVE_BB:[[[Chunk;NLEN];4];4]=[[[0x8000000000000D,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482],[0x8000000000000C,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482],[0x8000000000000C,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482],[0x2,0x81,0x0,0x0,0x0]],[[0x1,0x81,0x0,0x0,0x0],[0x8000000000000C,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482],[0x8000000000000D,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482],[0x8000000000000C,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482]],[[0x2,0x81,0x0,0x0,0x0],[0x1,0x81,0x0,0x0,0x0],[0x1,0x81,0x0,0x0,0x0],[0x1,0x81,0x0,0x0,0x0]],[[0x80000000000002,0x40,0x0,0x0,0x0],[0x2,0x102,0x0,0x0,0x0],[0xA,0x80000000001020,0x8000000007FF9F,0x40000001BA344D,0x25236482],[0x80000000000002,0x40,0x0,0x0,0x0]]];
+
+#[cfg(feature = "BN254")]
+pub const USE_GLV:bool = true;
+#[cfg(feature = "BN254")]
+pub const USE_GS_G2:bool = true;
+#[cfg(feature = "BN254")]
+pub const USE_GS_GT:bool = true;
+#[cfg(feature = "BN254")]
+pub const GT_STRONG:bool = false;
+
+// BLS383 Curve
+#[cfg(feature = "BLS383")]
+pub const CURVETYPE:usize = WEIERSTRASS;
+#[cfg(feature = "BLS383")]
+pub const CURVE_PAIRING_TYPE:usize = BLS_CURVE;
+#[cfg(feature = "BLS383")]
+pub const CURVE_A:isize = 0;
+
+#[cfg(feature = "BLS383")]
+pub const CURVE_ORDER:[Chunk;NLEN]=[0xFFF80000FFF001,0xBFDE0070FE7800,0x3000049C5EDF1C,0xC40007F910007A,0x14641004C,0x0,0x0];
+#[cfg(feature = "BLS383")]
+pub const CURVE_B:[Chunk;NLEN]=[0x9,0x0,0x0,0x0,0x0,0x0,0x0];
+#[cfg(feature = "BLS383")]
+pub const CURVE_COF:[Chunk;NLEN]=[0x2A00000052B,0x5560AAAAAB2CA0,0x6055,0x0,0x0,0x0,0x0];
+#[cfg(feature = "BLS383")]
+pub const CURVE_GX:[Chunk;NLEN]=[0xD59B348D10786B,0x3477C0E3F54AD0,0xBF25B734578B9B,0x4F6AC007BB6F65,0xEFD5830FF57E9C,0xADB9F88FB6EC02,0xB08CEE4BC98];
+#[cfg(feature = "BLS383")]
+pub const CURVE_GY:[Chunk;NLEN]=[0x5DA023D145DDB,0x13F518C5FEF7CC,0x56EC3462B2A66F,0x96F3019C7A925F,0x9061047981223E,0x4810AD8F5BE59,0x1F3909337671];
+
+#[cfg(feature = "BLS383")]
+pub const CURVE_BNX:[Chunk;NLEN]=[0x1000000040,0x110,0x0,0x0,0x0,0x0,0x0];
+#[cfg(feature = "BLS383")]
+pub const CURVE_CRU:[Chunk;NLEN]=[0xA3AAC4EDA155A9,0xDF2FE8761E5E3D,0xBCDFAADE632625,0x5123128D3035A6,0xDBF3A2BBEAD683,0x5C5FAB20424190,0x7AC52080A9F7];
+#[cfg(feature = "BLS383")]
+pub const CURVE_FRA:[Chunk;NLEN]=[0x2BA59A92B4508B,0x63DB7A06EEF343,0x40341CB1DFBC74,0x1639E9D32D55D3,0xB19B3F05CC36D4,0xF323EE4D86AB98,0x5A5FB198672];
+#[cfg(feature = "BLS383")]
+pub const CURVE_FRB:[Chunk;NLEN]=[0x81051A97F904E0,0xB7D49A6F086A37,0x8F3EEB8B7DB8AB,0xEEF7983C6C9543,0x7A65F6549CB35D,0x693D1777CBFBEC,0x751F25672384];
+#[cfg(feature = "BLS383")]
+pub const CURVE_PXA:[Chunk;NLEN]=[0x6059885BAC9472,0x7C4D31DE2DC36D,0xBDC90C308C88A7,0x29F01971C688FC,0x3693539C43F167,0xD81E5A561EB8BF,0x4D50722B56BF];
+#[cfg(feature = "BLS383")]
+pub const CURVE_PXB:[Chunk;NLEN]=[0x9B4BD7A272AB23,0x7AF19D4F44DCE8,0x3F6F7B93206A34,0x571DD3E2A819FB,0x3A2BA3B635D7EE,0xAC28C780C1A126,0xEE3617C3E5B];
+#[cfg(feature = "BLS383")]
+pub const CURVE_PYA:[Chunk;NLEN]=[0x81D230977BD4FD,0xB660720DFDFC6,0x41FC9590C89A0C,0x2E1FBCF878287A,0x11C23014EEE65,0x28878816BB325E,0x8F40859A05C];
+#[cfg(feature = "BLS383")]
+pub const CURVE_PYB:[Chunk;NLEN]=[0xA5E20A252C4CE6,0x5907A74AFF40C8,0x41760A42448EF3,0xFFEF82B0FDA199,0xA0F29A18D4EA49,0xAC7F7B86E4997B,0x1DCABBA88C12];
+
+#[cfg(feature = "BLS383")]
+pub const CURVE_W:[[Chunk;0];2]=[[],[]];
+#[cfg(feature = "BLS383")]
+pub const CURVE_SB:[[[Chunk;0];2];2]=[[[],[]],[[],[]]];
+#[cfg(feature = "BLS383")]
+pub const CURVE_WB:[[Chunk;0];4]=[[],[],[],[]];
+#[cfg(feature = "BLS383")]
+pub const CURVE_BB:[[[Chunk;0];4];4]=[[[],[],[],[]],[[],[],[],[]],[[],[],[],[]],[[],[],[],[]]];
+
+
+#[cfg(feature = "BLS383")]
+pub const USE_GLV:bool = true;
+#[cfg(feature = "BLS383")]
+pub const USE_GS_G2:bool = true;
+#[cfg(feature = "BLS383")]
+pub const USE_GS_GT:bool = true;
+#[cfg(feature = "BLS383")]
+pub const GT_STRONG:bool = false;
+
+
+// BLS455 Curve
+#[cfg(feature = "BLS455")]
+pub const CURVETYPE:usize = WEIERSTRASS;
+#[cfg(feature = "BLS455")]
+pub const CURVE_PAIRING_TYPE:usize = BLS_CURVE;
+#[cfg(feature = "BLS455")]
+pub const CURVE_A:isize = 0;
+
+#[cfg(feature = "BLS455")]
+pub const CURVE_ORDER:[Chunk;NLEN]=[0x7FFFFC00001,0xA00000400001C,0x25E000750001D10,0xE0000F10004F000,0x80000380002,0x10,0x0,0x0];
+#[cfg(feature = "BLS455")]
+pub const CURVE_B:[Chunk;NLEN]=[0xA,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+#[cfg(feature = "BLS455")]
+pub const CURVE_COF:[Chunk;NLEN]=[0xA9557FFAABFFAAB,0xAAB15555B54AAB6,0x555556AA,0x0,0x0,0x0,0x0,0x0];
+#[cfg(feature = "BLS455")]
+pub const CURVE_GX:[Chunk;NLEN]=[0x6D4C5DDFDFCEDD1,0x35C6F43B3A034FB,0x7F05B56A579C725,0xB1F2B8ECE11B321,0x9F342AB0CFE8392,0xA5911EE32767994,0x3005E40CC56ABED,0x18855F3B];
+#[cfg(feature = "BLS455")]
+pub const CURVE_GY:[Chunk;NLEN]=[0x404FD79A6619B9B,0x69D80A5D6FA0286,0xEE722322D91A493,0xB1EE58431C1E968,0xCA9BC8953801F5F,0xDFAFD40FE9E388E,0x9F8985FC3DEB0D6,0x19A8DB77E];
+
+#[cfg(feature = "BLS455")]
+pub const CURVE_BNX:[Chunk;NLEN]=[0x20000080000800,0x10000,0x0,0x0,0x0,0x0,0x0,0x0];
+#[cfg(feature = "BLS455")]
+pub const CURVE_CRU:[Chunk;NLEN]=[0x9202FFC00000AA9,0xFA5190F4A3762A,0x8B2B9BDD548FEC9,0xD7B469DB33A586A,0xC91731354CAFD99,0xF5B48D02FFFE695,0x57955572A900E0E,0x555559555];
+#[cfg(feature = "BLS455")]
+pub const CURVE_FRA:[Chunk;NLEN]=[0x9CCFBDCA2EBF21,0x572F54A73379964,0x72819F887545498,0x22BBC1CAD1F8534,0xA82CD7D435944F0,0x4594F818D030F7B,0xEDCBE3ADC0016A7,0x397EA4973];
+#[cfg(feature = "BLS455")]
+pub const CURVE_FRB:[Chunk;NLEN]=[0xA033043B5D1438A,0x6E5A00C3F72FC06,0x4717AB46118C70E,0x16993AE842C0609,0x3B78DA012CA06E9,0x501F99EA300E6EA,0x69C971C4E9FF768,0x1BD6B4BE1];
+#[cfg(feature = "BLS455")]
+pub const CURVE_PXA:[Chunk;NLEN]=[0x475F20F0C1F542,0x65D6070F8567E10,0xD780698BB33D776,0x71F685ED1531721,0x303D3FEC5B6A49C,0x8DEF064FF553CEB,0xC0E9A31B4C463,0x2ECB12FA8];
+#[cfg(feature = "BLS455")]
+pub const CURVE_PXB:[Chunk;NLEN]=[0x99086EE6749F03D,0xE89A55A5AC5EF2E,0x7B41AECD88EA016,0x622450FE6163E06,0x755066E1C8E296F,0xA80F219487326E8,0x66DBFBB0BEAEE59,0xECFFCE0];
+#[cfg(feature = "BLS455")]
+pub const CURVE_PYA:[Chunk;NLEN]=[0x83235A4581A77F4,0x9F0F367B7A7E10A,0x8FA0C4A66D55B9D,0xEF03F65E0D6EC4C,0x9C7DC299C1A9EC2,0x32453CA21CFA5AC,0x6C3DCD5ABB9C544,0x22471D90A];
+#[cfg(feature = "BLS455")]
+pub const CURVE_PYB:[Chunk;NLEN]=[0xF413B6D9E1FDBA2,0xA7E630913DA0356,0xFBC913D9AC488E2,0x72E7CF61B401585,0x656D801B21C89ED,0xF9E921EEE0558F9,0x3D2B7B03CFC8698,0x33503CA8];
+
+#[cfg(feature = "BLS455")]
+pub const CURVE_W:[[Chunk;0];2]=[[],[]];
+#[cfg(feature = "BLS455")]
+pub const CURVE_SB:[[[Chunk;0];2];2]=[[[],[]],[[],[]]];
+#[cfg(feature = "BLS455")]
+pub const CURVE_WB:[[Chunk;0];4]=[[],[],[],[]];
+#[cfg(feature = "BLS455")]
+pub const CURVE_BB:[[[Chunk;0];4];4]=[[[],[],[],[]],[[],[],[],[]],[[],[],[],[]],[[],[],[],[]]];
+
+
+#[cfg(feature = "BLS455")]
+pub const USE_GLV:bool = true;
+#[cfg(feature = "BLS455")]
+pub const USE_GS_G2:bool = true;
+#[cfg(feature = "BLS455")]
+pub const USE_GS_GT:bool = true;
+#[cfg(feature = "BLS455")]
+pub const GT_STRONG:bool = false;
\ No newline at end of file
diff --git a/version22/rust/src/rsa.rs b/version22/rust/src/rsa.rs
new file mode 100644
index 0000000..4915816
--- /dev/null
+++ b/version22/rust/src/rsa.rs
@@ -0,0 +1,372 @@
+/*
+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.
+*/
+
+//mod big;
+//use big::BIG;
+//mod dbig;
+//use dbig::DBIG;
+//mod ff;
+use ff::FF;
+//mod big;
+//mod dbig;
+//mod rom;
+use rom;
+//mod rand;
+use rand::RAND;
+//mod hash256;
+use hash256::HASH256;
+//mod hash384;
+use hash384::HASH384;
+//mod hash512;
+use hash512::HASH512;
+
+pub const RFS:usize =(rom::MODBYTES as usize)*rom::FFLEN;
+pub const SHA256:usize=32;
+pub const SHA384:usize=48;
+pub const SHA512:usize=64;
+
+pub const HASH_TYPE:usize=SHA256;
+
+pub struct RsaPrivateKey {
+	p:FF,
+	q:FF,
+	dp:FF,
+	dq:FF,
+	c:FF
+}
+
+pub struct RsaPublicKey {
+	e: isize,
+	n: FF
+}
+
+pub fn new_private_key(n: usize) -> RsaPrivateKey {
+	RsaPrivateKey {p:FF::new_int(n),q:FF::new_int(n),dp:FF::new_int(n),dq:FF::new_int(n),c:FF::new_int(n)}
+}
+
+pub fn new_public_key(m: usize) -> RsaPublicKey {
+	RsaPublicKey {e:0,n:FF::new_int(m)}
+}
+
+fn hashit(sha: usize,a: Option<&[u8]>,n: isize,w: &mut [u8]) {
+	if sha==SHA256 {
+		let mut h=HASH256::new();
+		if let Some(x)=a {
+			h.process_array(x);
+		}
+		if n>=0 {h.process_num(n as i32)}
+        let hs=h.hash();	
+        for i in 0..sha {w[i]=hs[i]}
+	}
+	if sha==SHA384 {
+		let mut h=HASH384::new();
+		if let Some(x)=a {
+			h.process_array(x);
+		}
+		if n>=0 {h.process_num(n as i32)}
+        let hs=h.hash();	
+        for i in 0..sha {w[i]=hs[i]}
+	}
+	if sha==SHA512 {
+		let mut h=HASH512::new();
+		if let Some(x)=a {
+			h.process_array(x);
+		}
+		if n>=0 {h.process_num(n as i32)}
+        let hs=h.hash();	
+        for i in 0..sha {w[i]=hs[i]}
+	}
+}
+
+pub fn key_pair(rng: &mut RAND,e: isize,prv: &mut RsaPrivateKey,pbc: &mut RsaPublicKey) { /* IEEE1363 A16.11/A16.12 more or less */
+	let n=pbc.n.getlen()/2;
+	let mut t=FF::new_int(n);
+	let mut p1=FF::new_int(n);
+	let mut q1=FF::new_int(n);
+
+	loop {
+		prv.p.random(rng);
+		while prv.p.lastbits(2)!=3 {prv.p.inc(1)}		
+		while !FF::prime(&prv.p,rng) {			
+			prv.p.inc(4);		
+		}
+		
+		p1.copy(&prv.p);
+		p1.dec(1);
+
+		if p1.cfactor(e) {continue}
+		break;
+	}
+
+	loop {
+		prv.q.random(rng);
+		while prv.q.lastbits(2)!=3 {prv.q.inc(1)}
+		while !FF::prime(&prv.q,rng) {
+			prv.q.inc(4);
+		}
+			
+		q1.copy(&prv.q);
+		q1.dec(1);
+
+		if q1.cfactor(e) {continue}
+
+		break;
+	}
+	
+	pbc.n=FF::mul(&prv.p,&prv.q);
+	pbc.e=e;
+
+	t.copy(&p1);
+	t.shr();
+	prv.dp.set(e);
+	prv.dp.invmodp(&t);
+	if prv.dp.parity()==0 {prv.dp.add(&t)}
+	prv.dp.norm();
+
+	t.copy(&q1);
+	t.shr();
+	prv.dq.set(e);
+	prv.dq.invmodp(&t);
+	if prv.dq.parity()==0 {prv.dq.add(&t)}
+	prv.dq.norm();
+
+	prv.c.copy(&prv.p);
+	prv.c.invmodp(&prv.q);
+}
+
+/* Mask Generation Function */
+
+pub fn mgf1(sha: usize,z: &[u8],olen: usize,k: &mut [u8]) {
+	let hlen=sha;
+
+	let mut j=0;
+	for i in 0..k.len() {k[i]=0}
+
+	let mut cthreshold=olen/hlen; 
+	if olen%hlen!=0 {cthreshold+=1}
+	for counter in 0..cthreshold {
+		let mut b:[u8;64]=[0;64];		
+		hashit(sha,Some(z),counter as isize,&mut b);
+
+		if j+hlen>olen {
+			for i in 0..(olen%hlen) {k[j]=b[i]; j+=1}
+		} else {
+			for i in 0..hlen {k[j]=b[i]; j+=1}
+		}
+	}	
+}
+
+/* SHAXXX identifier strings */
+const SHA256ID:[u8;19]= [0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20];
+const SHA384ID:[u8;19]= [0x30,0x41,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00,0x04,0x30];
+const SHA512ID:[u8;19]= [0x30,0x51,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0x04,0x40];
+
+pub fn pkcs15(sha: usize,m: &[u8],w: &mut [u8]) -> bool {
+	let olen=rom::FF_BITS/8;
+	let hlen=sha;
+	let idlen=19;
+	let mut b:[u8;64]=[0;64];  /* Not good */	
+
+	if olen<idlen+hlen+10 {return false}
+	hashit(sha,Some(m),-1,&mut b);
+
+	for i in 0..w.len() {w[i]=0}
+	let mut i=0;
+	w[i]=0; i+=1;
+	w[i]=1; i+=1;
+	for _ in 0..olen-idlen-hlen-3 {w[i]=0xff; i+=1}
+	w[i]=0; i+=1;
+
+	if hlen==SHA256 {
+		for j in 0..idlen {w[i]=SHA256ID[j]; i+=1}
+	}
+	if hlen==SHA384 {
+		for j in 0..idlen {w[i]=SHA384ID[j]; i+=1}
+	}
+	if hlen==SHA512 {
+		for j in 0..idlen {w[i]=SHA512ID[j]; i+=1}
+	}
+	for j in 0..hlen {w[i]=b[j]; i+=1}
+
+	return true;
+}
+
+/* OAEP Message Encoding for Encryption */
+pub fn oaep_encode(sha: usize,m: &[u8],rng: &mut RAND,p: Option<&[u8]>,f: &mut [u8]) -> bool { 
+	let olen=RFS-1;
+	let mlen=m.len();
+
+	let hlen=sha;
+
+	let mut seed:[u8;64]=[0;64];
+
+	let seedlen=hlen;
+	if mlen>olen-hlen-seedlen-1 {return false} 
+
+	let mut dbmask:[u8;RFS]=[0;RFS];
+
+	hashit(sha,p,-1,f);
+	let slen=olen-mlen-hlen-seedlen-1;      
+
+	for i in 0..slen {f[hlen+i]=0}
+	f[hlen+slen]=1;
+	for i in 0..mlen {f[hlen+slen+1+i]=m[i]}
+
+	for i in 0..seedlen {seed[i]=rng.getbyte()}
+	
+	mgf1(sha,&seed,olen-seedlen,&mut dbmask);
+
+	for i in 0..olen-seedlen {dbmask[i]^=f[i]}
+
+	mgf1(sha,&dbmask[0..olen-seedlen],seedlen,f);
+
+	for i in 0..seedlen {f[i]^=seed[i]}
+
+	for i in 0..olen-seedlen {f[i+seedlen]=dbmask[i]}
+
+	/* pad to length RFS */
+	let d=1;
+	for i in (d..RFS).rev() {
+		f[i]=f[i-d];
+	}
+	for i in (0..d).rev() {
+		f[i]=0;
+	}
+	return true;
+}
+
+/* OAEP Message Decoding for Decryption */
+pub fn oaep_decode(sha: usize,p: Option<&[u8]>,f: &mut [u8]) -> usize {
+	let olen=RFS-1;
+
+	let hlen=sha;
+	let mut seed:[u8;64]=[0;64];
+	let seedlen=hlen;
+	let mut chash:[u8;64]=[0;64];
+	
+	if olen<seedlen+hlen+1 {return 0}
+	let mut dbmask:[u8;RFS]=[0;RFS];
+	//for i in 0..olen-seedlen {dbmask[i]=0}
+
+	if f.len()<RFS {
+		let d=RFS-f.len();
+		for i in (d..RFS).rev() {
+			f[i]=f[i-d];
+		}
+		for i in (0..d).rev() {
+			f[i]=0;
+		}
+	}
+
+	hashit(sha,p,-1,&mut chash);
+
+	let x=f[0];
+
+	for i in seedlen..olen {
+		dbmask[i-seedlen]=f[i+1];
+	}
+
+	mgf1(sha,&dbmask[0..olen-seedlen],seedlen,&mut seed);
+	for i in 0..seedlen {seed[i]^=f[i+1]}
+	mgf1(sha,&seed,olen-seedlen,f);
+	for i in 0..olen-seedlen {dbmask[i]^=f[i]}
+
+	let mut comp=true;
+	for i in 0..hlen {
+		if chash[i]!=dbmask[i] {comp=false}
+	}
+
+	for i in 0..olen-seedlen-hlen {
+		dbmask[i]=dbmask[i+hlen]
+	}
+
+	for i in 0..hlen {
+		seed[i]=0; chash[i]=0
+	}
+		
+	let mut k=0;
+	loop {
+		if k>=olen-seedlen-hlen {return 0}
+		if dbmask[k]!=0 {break}
+		k+=1;
+	}
+
+	let t=dbmask[k];
+	if !comp || x!=0 || t!=0x01 {
+		for i in 0..olen-seedlen {dbmask[i]=0}
+		return 0;
+	}
+
+	for i in 0..olen-seedlen-hlen-k-1 {
+		f[i]=dbmask[i+k+1];
+	}
+	
+	for i in 0..olen-seedlen  {dbmask[i]=0}
+
+	return olen-seedlen-hlen-k-1;
+}
+
+/* destroy the Private Key structure */
+pub fn private_key_kill(prv: &mut RsaPrivateKey) {
+	prv.p.zero();
+	prv.q.zero();
+	prv.dp.zero();
+	prv.dq.zero();
+	prv.c.zero();
+}
+
+/* RSA encryption with the public key */
+pub fn encrypt(pbc: &RsaPublicKey,f: &[u8],g: &mut [u8]) {
+	let m=pbc.n.getlen();
+	let mut r=FF::new_int(m);
+
+	FF::frombytes(&mut r,f);
+	r.power(pbc.e,&pbc.n);
+	r.tobytes(g);
+}
+
+/* RSA decryption with the private key */
+pub fn decrypt(prv: &RsaPrivateKey,g: &[u8],f: &mut [u8]) {
+	let n=prv.p.getlen();
+	let mut r=FF::new_int(2*n);
+
+	FF::frombytes(&mut r,g);
+	let mut jp=r.dmod(&prv.p);
+	let mut jq=r.dmod(&prv.q);
+
+	jp.skpow(&prv.dp,&prv.p);
+	jq.skpow(&prv.dq,&prv.q);
+
+	r.zero();
+	r.dscopy(&jp);
+	jp.rmod(&prv.q);
+	if FF::comp(&jp,&jq)>0 {jq.add(&prv.q)}
+	jq.sub(&jp);
+	jq.norm();
+
+	let mut t=FF::mul(&prv.c,&jq);
+	jq=t.dmod(&prv.q);
+
+	t=FF::mul(&jq,&prv.p);
+	r.add(&t);
+	r.norm();
+
+	r.tobytes(f);
+}
+
diff --git a/version22/rust/tests/benchtest_ec.rs b/version22/rust/tests/benchtest_ec.rs
new file mode 100644
index 0000000..eee1ced
--- /dev/null
+++ b/version22/rust/tests/benchtest_ec.rs
@@ -0,0 +1,185 @@
+/*
+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.
+*/
+
+extern crate amcl;
+
+use  amcl::ecdh;
+use  amcl::ecp;
+use  amcl::ecp2;
+use  amcl::fp;
+use  amcl::fp2;
+use  amcl::fp4;
+use  amcl::fp12;
+use  amcl::big;
+use  amcl::dbig;
+use  amcl::rand;
+use  amcl::hash256;
+use  amcl::hash384;
+use  amcl::hash512;
+use  amcl::aes;
+use  amcl::rom;
+use  amcl::ff;
+use  amcl::rsa;
+
+use rand::RAND;
+use ecp::ECP;
+use big::BIG;
+
+use std::time::Instant;
+
+const MIN_ITERS:isize=10;
+const MIN_TIME: isize=10;
+
+#[allow(non_snake_case)]
+#[test]
+fn benchtest_ec()
+{
+	let mut raw:[u8;100]=[0;100];	
+	let mut fail=false;
+	let mut pbc=rsa::new_public_key(rom::FFLEN);
+	let mut prv=rsa::new_private_key(rom::HFLEN);	
+	let mut c: [u8;rsa::RFS]=[0;rsa::RFS];
+	let mut m: [u8;rsa::RFS]=[0;rsa::RFS];
+	let mut p: [u8;rsa::RFS]=[0;rsa::RFS];	
+
+	let mut rng=RAND::new();
+	rng.clean();
+	for i in 0..100 {raw[i]=i as u8}
+
+	rng.seed(100,&raw);	
+
+	if rom::CURVETYPE==rom::WEIERSTRASS {
+		println!("Weierstrass parameterization");
+	}		
+	if rom::CURVETYPE==rom::EDWARDS {
+		println!("Edwards parameterization");
+	}
+	if rom::CURVETYPE==rom::MONTGOMERY {
+		println!("Montgomery parameterization");
+	}
+
+	if rom::MODTYPE==rom::PSEUDO_MERSENNE {
+		println!("Pseudo-Mersenne Modulus");
+	}
+	if rom::MODTYPE==rom::MONTGOMERY_FRIENDLY {
+		println!("Montgomery friendly Modulus");
+	}
+	if rom::MODTYPE==rom::GENERALISED_MERSENNE {
+		println!("Generalised-Mersenne Modulus");
+	}
+	if rom::MODTYPE==rom::NOT_SPECIAL {
+		println!("Not special Modulus");
+	}
+
+	println!("Modulus size {:} bits",rom::MODBITS); 
+	println!("{:} bit build",rom::CHUNK); 
+
+	let mut G:ECP;
+
+	let gx=BIG::new_ints(&rom::CURVE_GX);
+	
+	if rom::CURVETYPE!=rom::MONTGOMERY {
+		let gy=BIG::new_ints(&rom::CURVE_GY);
+		G=ECP::new_bigs(&gx,&gy);
+	} else {
+		G=ECP::new_big(&gx);
+	}
+
+	let mut r=BIG::new_ints(&rom::CURVE_ORDER);
+	let mut s=BIG::randomnum(&r,&mut rng);
+
+	let mut P=G.mul(&mut r);
+	if !P.is_infinity() {
+		println!("FAILURE - rG!=O");
+		fail=true;
+	} 
+
+	let start = Instant::now();
+	let mut iterations=0;
+	let mut dur=0 as u64;
+	while dur<(MIN_TIME as u64)*1000 || iterations<MIN_ITERS {
+		P=G.mul(&mut s);
+		iterations+=1;
+		let elapsed=start.elapsed();
+		dur=(elapsed.as_secs() * 1_000) + (elapsed.subsec_nanos() / 1_000_000) as u64;
+	} 
+	let duration=(dur as f64)/(iterations as f64);
+	print!("EC  mul - {:} iterations  ",iterations);
+	println!(" {:0.2} ms per iteration",duration);
+
+	println!("Generating {:}-bit RSA public/private key pair",rom::FFLEN*rom::BIGBITS);
+
+
+	let start = Instant::now();
+	let mut iterations=0;
+	let mut dur=0 as u64;
+	while dur<(MIN_TIME as u64)*1000 || iterations<MIN_ITERS {
+		rsa::key_pair(&mut rng,65537,&mut prv,&mut pbc);
+		iterations+=1;
+		let elapsed=start.elapsed();
+		dur=(elapsed.as_secs() * 1_000) + (elapsed.subsec_nanos() / 1_000_000) as u64;
+	} 
+	let duration=(dur as f64)/(iterations as f64);
+	print!("RSA gen - {:} iterations  ",iterations);
+	println!(" {:0.2} ms per iteration",duration);
+
+	for i in 0..rsa::RFS {m[i]=(i%128) as u8;}
+
+	let start = Instant::now();
+	let mut iterations=0;
+	let mut dur=0 as u64;
+	while dur<(MIN_TIME as u64)*1000 || iterations<MIN_ITERS {
+		rsa::encrypt(&pbc,&m,&mut c); 
+		iterations+=1;
+		let elapsed=start.elapsed();
+		dur=(elapsed.as_secs() * 1_000) + (elapsed.subsec_nanos() / 1_000_000) as u64;
+	} 
+	let duration=(dur as f64)/(iterations as f64);
+	print!("RSA enc - {:} iterations  ",iterations);
+	println!(" {:0.2} ms per iteration",duration);
+
+	let start = Instant::now();
+	let mut iterations=0;
+	let mut dur=0 as u64;
+	while dur<(MIN_TIME as u64)*1000 || iterations<MIN_ITERS {
+		rsa::decrypt(&prv,&c,&mut p); 
+		iterations+=1;
+		let elapsed=start.elapsed();
+		dur=(elapsed.as_secs() * 1_000) + (elapsed.subsec_nanos() / 1_000_000) as u64;
+	} 
+	let duration=(dur as f64)/(iterations as f64);
+	print!("RSA dec - {:} iterations  ",iterations);
+	println!(" {:0.2} ms per iteration",duration);
+
+	let mut cmp=true;
+	for i in 0..rsa::RFS {
+			if p[i]!=m[i] {cmp=false;}
+		}
+
+	if !cmp {
+		println!("FAILURE - RSA decryption");
+		fail=true;
+	}
+
+	if !fail {
+		println!("All tests pass");
+	}
+
+	assert!(!fail)
+}
diff --git a/version22/rust/tests/benchtest_pair.rs b/version22/rust/tests/benchtest_pair.rs
new file mode 100644
index 0000000..67a9035
--- /dev/null
+++ b/version22/rust/tests/benchtest_pair.rs
@@ -0,0 +1,245 @@
+/*
+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.
+*/
+
+extern crate amcl;
+
+use amcl::mpin;
+use amcl::ecp;
+use amcl::ecp2;
+use amcl::fp;
+use amcl::fp2;
+use amcl::fp4;
+use amcl::fp12;
+use amcl::pair;
+use amcl::big;
+use amcl::dbig;
+use amcl::rand;
+use amcl::hash256;
+use amcl::hash384;
+use amcl::hash512;
+use amcl::aes;
+use amcl::rom;
+
+use rand::RAND;
+use ecp::ECP;
+use big::BIG;
+use ecp2::ECP2;
+use fp2::FP2;
+
+use std::time::Instant;
+
+const MIN_ITERS:isize=10;
+const MIN_TIME: isize=10;
+
+#[allow(non_snake_case)]
+#[test]
+fn benchtest_pair()
+{
+	let mut raw:[u8;100]=[0;100];	
+	let mut fail=false;
+
+	let mut rng=RAND::new();
+	rng.clean();
+	for i in 0..100 {raw[i]=i as u8}
+
+	rng.seed(100,&raw);	
+
+	if rom::CURVE_PAIRING_TYPE==rom::BN_CURVE {
+		println!("BN Pairing-Friendly Curve");
+	}
+	if rom::CURVE_PAIRING_TYPE==rom::BLS_CURVE {
+		println!("BLS Pairing-Friendly Curve");
+	}
+
+	println!("Modulus size {:} bits",rom::MODBITS); 
+	println!("{:} bit build",rom::CHUNK); 
+
+	let mut G:ECP;
+
+	let gx=BIG::new_ints(&rom::CURVE_GX);
+	
+	let gy=BIG::new_ints(&rom::CURVE_GY);
+	G=ECP::new_bigs(&gx,&gy);
+
+	let mut r=BIG::new_ints(&rom::CURVE_ORDER);
+	let mut s=BIG::randomnum(&r,&mut rng);
+
+	let mut P=pair::g1mul(&mut G,&mut r);
+
+	if !P.is_infinity() {
+		println!("FAILURE - rP!=O");
+		fail=true;
+	}
+
+	let start = Instant::now();
+	let mut iterations=0;
+	let mut dur=0 as u64;
+	while dur<(MIN_TIME as u64)*1000 || iterations<MIN_ITERS {
+		P=pair::g1mul(&mut G,&mut s);
+		iterations+=1;
+		let elapsed=start.elapsed();
+		dur=(elapsed.as_secs() * 1_000) + (elapsed.subsec_nanos() / 1_000_000) as u64;
+	} 
+	let duration=(dur as f64)/(iterations as f64);
+	print!("G1  mul              - {:} iterations  ",iterations);
+	println!(" {:0.2} ms per iteration",duration);
+
+	let mut Q=ECP2::new_fp2s(&FP2::new_bigs(&BIG::new_ints(&rom::CURVE_PXA),&BIG::new_ints(&rom::CURVE_PXB)),&FP2::new_bigs(&BIG::new_ints(&rom::CURVE_PYA),&BIG::new_ints(&rom::CURVE_PYB)));
+
+	let mut W=pair::g2mul(&mut Q,&mut r);
+
+	if !W.is_infinity() {
+		println!("FAILURE - rQ!=O");
+		fail=true;
+	}
+
+	let start = Instant::now();
+	let mut iterations=0;
+	let mut dur=0 as u64;
+	while dur<(MIN_TIME as u64)*1000 || iterations<MIN_ITERS {
+		W=pair::g2mul(&mut Q,&mut s);
+		iterations+=1;
+		let elapsed=start.elapsed();
+		dur=(elapsed.as_secs() * 1_000) + (elapsed.subsec_nanos() / 1_000_000) as u64;
+	} 
+	let duration=(dur as f64)/(iterations as f64);
+	print!("G2  mul              - {:} iterations  ",iterations);
+	println!(" {:0.2} ms per iteration",duration);
+
+	let mut w=pair::ate(&mut Q,&mut P);
+	w=pair::fexp(&w);
+
+	let mut g=pair::gtpow(&mut w,&mut r);
+
+	if !g.isunity() {
+		println!("FAILURE - g^r!=1");
+		return;
+	}
+
+	let start = Instant::now();
+	let mut iterations=0;
+	let mut dur=0 as u64;
+	while dur<(MIN_TIME as u64)*1000 || iterations<MIN_ITERS {
+		g=pair::gtpow(&mut w,&mut s);
+		iterations+=1;
+		let elapsed=start.elapsed();
+		dur=(elapsed.as_secs() * 1_000) + (elapsed.subsec_nanos() / 1_000_000) as u64;
+	} 
+	let duration=(dur as f64)/(iterations as f64);
+	print!("GT  pow              - {:} iterations  ",iterations);
+	println!(" {:0.2} ms per iteration",duration);
+
+
+	let mut f = FP2::new_bigs(&BIG::new_ints(&rom::CURVE_FRA),&BIG::new_ints(&rom::CURVE_FRB));
+	let q=BIG::new_ints(&rom::MODULUS);
+
+	let mut m=BIG::new_copy(&q);
+	m.rmod(&mut r);
+
+	let mut a=BIG::new_copy(&s);
+	a.rmod(&mut m);
+
+	let mut b=BIG::new_copy(&s);
+	b.div(&mut m);
+
+	g.copy(&w);
+	let mut c=g.trace();
+
+	g.frob(&mut f);
+	let cp=g.trace();
+
+	w.conj();
+	g.mul(&mut w);
+	let cpm1=g.trace();
+	g.mul(&mut w);
+	let cpm2=g.trace();
+
+	let start = Instant::now();
+	let mut iterations=0;
+	let mut dur=0 as u64;
+	while dur<(MIN_TIME as u64)*1000 || iterations<MIN_ITERS {
+		c=c.xtr_pow2(&cp,&cpm1,&cpm2,&mut a,&mut b);
+		iterations+=1;
+		let elapsed=start.elapsed();
+		dur=(elapsed.as_secs() * 1_000) + (elapsed.subsec_nanos() / 1_000_000) as u64;
+	} 
+	let duration=(dur as f64)/(iterations as f64);
+	print!("GT  pow (compressed) - {:} iterations  ",iterations);
+	println!(" {:0.2} ms per iteration",duration);
+
+	let start = Instant::now();
+	let mut iterations=0;
+	let mut dur=0 as u64;
+	while dur<(MIN_TIME as u64)*1000 || iterations<MIN_ITERS {
+		w=pair::ate(&mut Q,&mut P);
+		iterations+=1;
+		let elapsed=start.elapsed();
+		dur=(elapsed.as_secs() * 1_000) + (elapsed.subsec_nanos() / 1_000_000) as u64;
+	} 
+	let duration=(dur as f64)/(iterations as f64);
+	print!("PAIRing ATE          - {:} iterations  ",iterations);
+	println!(" {:0.2} ms per iteration",duration);
+
+
+	let start = Instant::now();
+	let mut iterations=0;
+	let mut dur=0 as u64;
+	while dur<(MIN_TIME as u64)*1000 || iterations<MIN_ITERS {
+		g=pair::fexp(&w);
+		iterations+=1;
+		let elapsed=start.elapsed();
+		dur=(elapsed.as_secs() * 1_000) + (elapsed.subsec_nanos() / 1_000_000) as u64;
+	} 
+	let duration=(dur as f64)/(iterations as f64);
+	print!("PAIRing FEXP         - {:} iterations  ",iterations);
+	println!(" {:0.2} ms per iteration",duration);
+
+	P.copy(&G);
+	Q.copy(&W);
+
+	P=pair::g1mul(&mut P,&mut s);
+	g=pair::ate(&mut Q,&mut P);
+	g=pair::fexp(&g);
+
+	P.copy(&G);
+	Q=pair::g2mul(&mut Q,&mut s);
+	w=pair::ate(&mut Q,&mut P);
+	w=pair::fexp(&w);
+
+	if !g.equals(&mut w) {
+		println!("FAILURE - e(sQ,p)!=e(Q,sP) ");
+		fail=true;
+	}
+
+	Q.copy(&W);
+	g=pair::ate(&mut Q,&mut P);
+	g=pair::fexp(&g);
+	g=pair::gtpow(&mut g,&mut s);
+
+	if !g.equals(&mut w) {
+		println!("FAILURE - e(sQ,p)!=e(Q,P)^s ");
+		fail=true;
+	}
+
+	if !fail {
+		println!("All tests pass");
+	}
+
+	assert!(!fail)
+}
\ No newline at end of file
diff --git a/version22/rust/tests/test_ecdh.rs b/version22/rust/tests/test_ecdh.rs
new file mode 100644
index 0000000..4623d17
--- /dev/null
+++ b/version22/rust/tests/test_ecdh.rs
@@ -0,0 +1,180 @@
+/*
+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.
+*/
+
+extern crate amcl;
+
+use amcl::ecdh;
+use amcl::ecp;
+use amcl::ecp2;
+use amcl::fp;
+use amcl::fp2;
+use amcl::fp4;
+use amcl::fp12;
+use amcl::big;
+use amcl::dbig;
+use amcl::rand;
+use amcl::hash256;
+use amcl::hash384;
+use amcl::hash512;
+use amcl::aes;
+use amcl::rom;
+use rand::RAND;
+
+pub fn printbinary(array: &[u8]) {
+	for i in 0..array.len() {
+		print!("{:02X}", array[i])
+	}
+	println!("")
+}
+
+#[test]
+fn test_ecdh()
+{
+	let pw="M0ng00se";
+	let pp:&[u8] = b"M0ng00se";
+	let sha=ecdh::HASH_TYPE;
+	let mut salt:[u8;8]=[0;8];
+	let mut raw:[u8;100]=[0;100];	
+	let mut s1:[u8;ecdh::EGS]=[0;ecdh::EGS];
+	let mut w0:[u8;2*ecdh::EFS+1]=[0;2*ecdh::EFS+1];
+	let mut w1:[u8;2*ecdh::EFS+1]=[0;2*ecdh::EFS+1];
+	let mut z0:[u8;ecdh::EFS]=[0;ecdh::EFS];
+	let mut z1:[u8;ecdh::EFS]=[0;ecdh::EFS];
+	let mut key:[u8;ecdh::EAS]=[0;ecdh::EAS];
+	let mut cs: [u8;ecdh::EGS]=[0;ecdh::EGS];
+	let mut ds: [u8;ecdh::EGS]=[0;ecdh::EGS];	
+	let mut m: Vec<u8> = vec![0;32];   // array that could be of any length. So use heap.
+	let mut p1: [u8;3]=[0;3];
+	let mut p2: [u8;4]=[0;4];	
+	let mut v: [u8;2*ecdh::EFS+1]=[0;2*ecdh::EFS+1];
+	let mut t: [u8;12]=[0;12];
+
+	let mut rng=RAND::new();
+	rng.clean();
+	for i in 0..100 {raw[i]=i as u8}
+
+	rng.seed(100,&raw);	
+
+	for i in 0..8 {salt[i]=(i+1) as u8}  // set Salt	
+
+	println!("Alice's Passphrase= {}",pw);
+
+	let mut s0:[u8;ecdh::EFS]=[0;ecdh::EGS];
+	ecdh::pbkdf2(sha,pp,&salt,1000,ecdh::EGS,&mut s0);
+
+	print!("Alice's private key= 0x");
+	printbinary(&s0);
+
+/* Generate Key pair S/W */
+	ecdh::key_pair_generate(None,&mut s0,&mut w0);
+
+	print!("Alice's public key= 0x");
+	printbinary(&w0);
+
+	let mut res=ecdh::public_key_validate(true,&w0);
+	if res!=0 {
+		println!("ECP Public Key is invalid!");
+		return;
+	}
+
+/* Random private key for other party */
+	ecdh::key_pair_generate(Some(&mut rng),&mut s1,&mut w1);
+
+	print!("Servers private key= 0x");
+	printbinary(&s1);
+
+	print!("Servers public key= 0x");
+	printbinary(&w1);
+
+
+	res=ecdh::public_key_validate(true,&w1);
+	if res!=0 {
+		println!("ECP Public Key is invalid!");
+		return;
+	}
+/* Calculate common key using DH - IEEE 1363 method */
+
+	ecdh::ecpsvdp_dh(&s0,&w1,&mut z0);
+	ecdh::ecpsvdp_dh(&s1,&w0,&mut z1);
+
+	let mut same=true;
+	for i in 0..ecdh::EFS {
+		if z0[i]!=z1[i] {same=false}
+	}
+
+	if !same {
+		println!("*** ECPSVDP-DH Failed");
+		return;
+	}
+
+	ecdh::kdf2(sha,&z0,None,ecdh::EAS,&mut key);
+
+	print!("Alice's DH Key=  0x"); printbinary(&key);
+	print!("Servers DH Key=  0x"); printbinary(&key);
+
+	if rom::CURVETYPE!=rom::MONTGOMERY {
+
+		for i in 0..17 {m[i]=i as u8} 
+
+		println!("Testing ECIES");
+
+		p1[0]=0x0; p1[1]=0x1; p1[2]=0x2;
+		p2[0]=0x0; p2[1]=0x1; p2[2]=0x2; p2[3]=0x3;
+
+		let cc=ecdh::ecies_encrypt(sha,&p1,&p2,&mut rng,&w1,&m[0..17],&mut v,&mut t);
+
+		if let Some(mut c)=cc {
+			println!("Ciphertext= ");
+			print!("V= 0x"); printbinary(&v);
+			print!("C= 0x"); printbinary(&c);
+			print!("T= 0x"); printbinary(&t);
+		
+
+			let mm=ecdh::ecies_decrypt(sha,&p1,&p2,&v,&mut c,&t,&s1);
+			if let Some(rm)=mm {
+				println!("Decryption succeeded");
+				println!("Message is 0x"); printbinary(&rm);				
+			}
+			else {
+				println!("*** ECIES Decryption Failed");
+				return;
+			} 
+		}
+		else {
+			println!("*** ECIES Encryption Failed");
+			return;
+		} 
+
+		println!("Testing ECDSA");
+
+		if ecdh::ecpsp_dsa(sha,&mut rng,&s0,&m[0..17],&mut cs,&mut ds)!=0 {
+			println!("***ECDSA Signature Failed");
+			return;
+		}
+		println!("Signature= ");
+		print!("C= 0x"); printbinary(&cs);
+		print!("D= 0x"); printbinary(&ds);
+
+		if ecdh::ecpvp_dsa(sha,&w0,&m[0..17],&cs,&ds)!=0 {
+			println!("***ECDSA Verification Failed");
+			return;
+		} else {println!("ECDSA Signature/Verification succeeded ")}
+	}
+
+}
diff --git a/version22/rust/tests/test_mpin.rs b/version22/rust/tests/test_mpin.rs
new file mode 100644
index 0000000..8900254
--- /dev/null
+++ b/version22/rust/tests/test_mpin.rs
@@ -0,0 +1,217 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use std::io;
+
+extern crate amcl;
+
+use amcl::mpin;
+use amcl::ecp;
+use amcl::ecp2;
+use amcl::fp;
+use amcl::fp2;
+use amcl::fp4;
+use amcl::fp12;
+use amcl::pair;
+use amcl::big;
+use amcl::dbig;
+use amcl::rand;
+use amcl::hash256;
+use amcl::hash384;
+use amcl::hash512;
+use amcl::aes;
+use amcl::rom;
+
+use rand::RAND;
+
+pub fn printbinary(array: &[u8]) {
+	for i in 0..array.len() {
+		print!("{:02X}", array[i])
+	}
+	println!("")
+}
+
+#[test]
+fn test_mpin()
+{
+	let mut raw:[u8;100]=[0;100];	
+	let mut s:[u8;mpin::EGS]=[0;mpin::EGS];
+	const RM:usize=rom::MODBYTES as usize;
+	let mut hcid:[u8;RM]=[0;RM];
+	let mut hsid:[u8;RM]=[0;RM];
+
+	const G1S:usize=2*mpin::EFS+1; /* Group 1 Size */
+	const G2S:usize=4*mpin::EFS; /* Group 2 Size */
+	const EAS:usize=16;
+
+	let mut sst:[u8;G2S]=[0;G2S];
+	let mut token: [u8;G1S]=[0;G1S];	
+	let mut permit:[u8;G1S]=[0;G1S];	
+	let mut g1: [u8;12*mpin::EFS]=[0;12*mpin::EFS];
+	let mut g2: [u8;12*mpin::EFS]=[0;12*mpin::EFS];	
+	let mut xid: [u8;G1S]=[0;G1S];
+	let mut xcid: [u8;G1S]=[0;G1S];	
+	let mut x: [u8;mpin::EGS]=[0;mpin::EGS];	
+	let mut y: [u8;mpin::EGS]=[0;mpin::EGS];
+	let mut sec: [u8;G1S]=[0;G1S];	
+	let mut r: [u8;mpin::EGS]=[0;mpin::EGS];
+	let mut z: [u8;G1S]=[0;G1S];	
+	let mut hid: [u8;G1S]=[0;G1S];
+	let mut htid: [u8;G1S]=[0;G1S];
+	let mut rhid: [u8;G1S]=[0;G1S];
+	let mut w: [u8;mpin::EGS]=[0;mpin::EGS];
+	let mut t: [u8;G1S]=[0;G1S];
+	let mut e: [u8;12*mpin::EFS]=[0;12*mpin::EFS];
+	let mut f: [u8;12*mpin::EFS]=[0;12*mpin::EFS];
+	let mut h: [u8;RM]=[0;RM];
+	let mut ck: [u8;EAS]=[0;EAS];
+	let mut sk: [u8;EAS]=[0;EAS];	
+
+
+	let sha=mpin::HASH_TYPE;
+	let mut rng=RAND::new();
+	rng.clean();
+	for i in 0..100 {raw[i]=(i+1) as u8}
+
+	rng.seed(100,&raw);	
+
+/* Trusted Authority set-up */
+
+	mpin::random_generate(&mut rng,&mut s);
+	print!("Master Secret s: 0x");  printbinary(&s);
+
+/* Create Client Identity */
+ 	let name= "testUser@miracl.com";
+ 	let client_id=name.as_bytes();
+
+	print!("Client ID= "); printbinary(&client_id); 
+
+
+	mpin::hash_id(sha,&client_id,&mut hcid);  /* Either Client or TA calculates Hash(ID) - you decide! */
+		
+/* Client and Server are issued secrets by DTA */
+	mpin::get_server_secret(&s,&mut sst);
+	print!("Server Secret SS: 0x");  printbinary(&sst);	
+
+	mpin::get_client_secret(&mut s,&hcid,&mut token);
+	print!("Client Secret CS: 0x"); printbinary(&token); 
+
+/* Client extracts PIN from secret to create Token */
+	let pin:i32=1234;
+	println!("Client extracts PIN= {}",pin);
+	let mut rtn=mpin::extract_pin(sha,&client_id,pin,&mut token);
+	if rtn != 0 {
+		println!("FAILURE: EXTRACT_PIN rtn: {}",rtn);
+	}
+
+	print!("Client Token TK: 0x"); printbinary(&token); 
+
+	if mpin::FULL {
+		mpin::precompute(&token,&hcid,&mut g1,&mut g2);
+	}
+
+	let mut date=0;
+	if mpin::PERMITS {
+		date=mpin::today();
+/* Client gets "Time Token" permit from DTA */ 
+		mpin::get_client_permit(sha,date,&s,&hcid,&mut permit);
+		print!("Time Permit TP: 0x");  printbinary(&permit);
+
+/* This encoding makes Time permit look random - Elligator squared */
+		mpin::encoding(&mut rng,&mut permit);
+		print!("Encoded Time Permit TP: 0x"); printbinary(&permit);
+		mpin::decoding(&mut permit);
+		print!("Decoded Time Permit TP: 0x"); printbinary(&permit);
+	}
+
+	print!("\nPIN= "); let _ =io::Write::flush(&mut io::stdout());
+    let mut input_text = String::new();
+    let _ = io::stdin().read_line(&mut input_text);
+
+    let pin=input_text.trim().parse::<usize>().unwrap();
+
+	println!("MPIN Multi Pass");
+/* Send U=x.ID to server, and recreate secret from token and pin */
+	rtn=mpin::client_1(sha,date,&client_id,Some(&mut rng),&mut x,pin,&token,&mut sec,Some(&mut xid[..]),Some(&mut xcid[..]),Some(&permit[..]));
+	if rtn != 0 {
+		println!("FAILURE: CLIENT_1 rtn: {}",rtn);
+	}
+  
+	if mpin::FULL {
+		mpin::hash_id(sha,&client_id,&mut hcid);
+		mpin::get_g1_multiple(Some(&mut rng),1,&mut r,&hcid,&mut z);  /* Also Send Z=r.ID to Server, remember random r */
+	}
+  
+/* Server calculates H(ID) and H(T|H(ID)) (if time mpin::PERMITS enabled), and maps them to points on the curve HID and HTID resp. */
+		
+	mpin::server_1(sha,date,&client_id,&mut hid,Some(&mut htid[..]));
+
+
+    if date!=0 {rhid.clone_from_slice(&htid[..]);}
+    else {rhid.clone_from_slice(&hid[..]);}
+    	
+/* Server generates Random number Y and sends it to Client */
+	mpin::random_generate(&mut rng,&mut y);
+  
+	if mpin::FULL {
+		mpin::hash_id(sha,&client_id,&mut hsid);
+		mpin::get_g1_multiple(Some(&mut rng),0,&mut w,&rhid,&mut t);  /* Also send T=w.ID to client, remember random w  */
+	}
+  
+/* Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC */
+	rtn=mpin::client_2(&x,&y,&mut sec);
+	if rtn != 0 {
+		println!("FAILURE: CLIENT_2 rtn: {}",rtn);
+	}
+  
+/* Server Second pass. Inputs hashed client id, random Y, -(x+y)*SEC, xID and xCID and Server secret SST. E and F help kangaroos to find error. */
+/* If PIN error not required, set E and F = null */
+  
+	if !mpin::PINERROR {
+		rtn=mpin::server_2(date,&hid,Some(&htid[..]),&y,&sst,Some(&xid[..]),Some(&xcid[..]),&sec,None,None);
+	} else {
+		rtn=mpin::server_2(date,&hid,Some(&htid[..]),&y,&sst,Some(&xid[..]),Some(&xcid[..]),&sec,Some(&mut e),Some(&mut f));
+	}
+
+	if rtn == mpin::BAD_PIN {
+		println!("Server says - Bad Pin. I don't know you. Feck off.");
+		if mpin::PINERROR {
+			let err=mpin::kangaroo(&e,&f);
+			if err!=0 {println!("(Client PIN is out by {})",err)}
+		}
+		return;
+	} else {
+		println!("Server says - PIN is good! You really are {}",name);
+	}
+
+	if  mpin::FULL {
+
+		let mut pxcid=None;
+		if mpin::PERMITS {pxcid=Some(&xcid[..])};
+
+		mpin::hash_all(sha,&hcid,&xid,pxcid,&sec,&y,&z,&t,&mut h);	
+		mpin::client_key(sha,&g1,&g2,pin,&r,&x,&h,&t,&mut ck);
+		print!("Client Key =  0x");  printbinary(&ck);
+
+		mpin::hash_all(sha,&hsid,&xid,pxcid,&sec,&y,&z,&t,&mut h);			
+		mpin::server_key(sha,&z,&sst,&w,&h,&hid,&xid,pxcid,&mut sk);
+		print!("Server Key =  0x"); printbinary(&sk);
+	}
+
+}
diff --git a/version22/rust/tests/test_rsa.rs b/version22/rust/tests/test_rsa.rs
new file mode 100644
index 0000000..dd63b67
--- /dev/null
+++ b/version22/rust/tests/test_rsa.rs
@@ -0,0 +1,109 @@
+/*
+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.
+*/
+
+extern crate amcl;
+
+use  amcl::ff;
+use  amcl::big;
+use  amcl::dbig;
+use  amcl::rom;
+use  amcl::rand;
+use  amcl::hash256;
+use  amcl::hash384;
+use  amcl::hash512;
+use  amcl::rsa;
+
+use rand::RAND;
+
+pub fn printbinary(array: &[u8]) {
+	for i in 0..array.len() {
+		print!("{:02X}", array[i]);
+	}
+	println!("");
+} 
+
+use std::str;
+//use std::process;
+
+#[test]
+fn test_rsa()
+{
+	let sha=rsa::HASH_TYPE;
+	let message:&[u8] = b"Hello World\n";
+
+	let mut pbc=rsa::new_public_key(rom::FFLEN);
+	let mut prv=rsa::new_private_key(rom::HFLEN);
+
+	let mut ml:[u8;rsa::RFS]=[0;rsa::RFS];
+	let mut ms:[u8;rsa::RFS]=[0;rsa::RFS];	
+	let mut c: [u8;rsa::RFS]=[0;rsa::RFS];
+	let mut s: [u8;rsa::RFS]=[0;rsa::RFS];
+	let mut e: [u8;rsa::RFS]=[0;rsa::RFS];
+
+	let mut raw:[u8;100]=[0;100];
+	
+	let mut rng=RAND::new();
+
+	rng.clean();
+	for i in 0..100 {raw[i]=i as u8}
+
+	rng.seed(100,&raw);
+
+	println!("Generating public/private key pair");
+	rsa::key_pair(&mut rng,65537,&mut prv,&mut pbc);
+
+	println!("Encrypting test string\n");
+	rsa::oaep_encode(sha,&message,&mut rng,None,&mut e); /* OAEP encode message M to E  */
+
+	rsa::encrypt(&pbc,&e,&mut c);    /* encrypt encoded message */
+	print!("Ciphertext= 0x"); printbinary(&c);
+
+	println!("Decrypting test string");
+	rsa::decrypt(&prv,&c,&mut ml);
+	let mlen=rsa::oaep_decode(sha,None,&mut ml); /* OAEP decode message  */
+
+	let mess=str::from_utf8(&ml[0..mlen]).unwrap();
+	print!("{}",&mess);
+
+	println!("Signing message");
+	rsa::pkcs15(sha,message,&mut c); 
+
+	rsa::decrypt(&prv,&c,&mut s);  /* create signature in S */ 
+
+	print!("Signature= 0x"); printbinary(&s);
+
+	rsa::encrypt(&pbc,&s,&mut ms);
+
+	let mut cmp=true;
+	if c.len()!=ms.len() {
+		cmp=false;
+	} else {
+		for j in 0..c.len() {
+			if c[j]!=ms[j] {cmp=false}
+		}
+	}
+	if cmp {
+		println!("Signature is valid");
+	} else {
+		println!("Signature is INVALID");
+	}
+
+	rsa::private_key_kill(&mut prv);
+}
+
diff --git a/version22/swift/BenchtestEC.swift b/version22/swift/BenchtestEC.swift
new file mode 100644
index 0000000..126873c
--- /dev/null
+++ b/version22/swift/BenchtestEC.swift
@@ -0,0 +1,161 @@
+/*
+	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
+
+public func BenchtestEC()
+{
+    let pub=rsa_public_key(Int(ROM.FFLEN))
+    let priv=rsa_private_key(Int(ROM.HFLEN))
+    var C=[UInt8](repeating: 0,count: RSA.RFS)
+    var P=[UInt8](repeating: 0,count: RSA.RFS)
+    var M=[UInt8](repeating: 0,count: RSA.RFS)
+    let MIN_TIME=10.0
+    let MIN_ITERS=10
+    
+    var fail=false;
+    var RAW=[UInt8](repeating: 0,count: 100)
+    
+    let rng=RAND()
+    rng.clean();
+    for i in 0 ..< 100 {RAW[i]=UInt8(i&0xff)}
+    
+    rng.seed(100,RAW)
+    
+    if ROM.CURVETYPE==ROM.WEIERSTRASS {
+        print("Weierstrass parameterisation")
+    }
+    if ROM.CURVETYPE==ROM.EDWARDS {
+        print("Edwards parameterisation")
+    }
+    if ROM.CURVETYPE==ROM.MONTGOMERY {
+        print("Montgomery representation")
+    }
+    if ROM.MODTYPE==ROM.PSEUDO_MERSENNE {
+        print("Pseudo-Mersenne Modulus")
+    }
+    if ROM.MODTYPE==ROM.MONTGOMERY_FRIENDLY {
+        print("Montgomery Friendly Modulus")
+    }
+    if ROM.MODTYPE==ROM.GENERALISED_MERSENNE {
+        print("Generalised-Mersenne Modulus")
+    }
+    if ROM.MODTYPE==ROM.NOT_SPECIAL {
+        print("Not special Modulus")
+    }
+    print("Modulus size \(ROM.MODBITS) bits")
+    print("\(ROM.CHUNK) bit build")
+    
+    let gx=BIG(ROM.CURVE_Gx);
+    var s:BIG
+    var G:ECP
+    if ROM.CURVETYPE != ROM.MONTGOMERY
+    {
+        let gy=BIG(ROM.CURVE_Gy)
+        G=ECP(gx,gy)
+    }
+    else
+        {G=ECP(gx)}
+    
+    let r=BIG(ROM.CURVE_Order)
+    s=BIG.randomnum(r,rng)
+    
+    var W=G.mul(r)
+    if !W.is_infinity() {
+        print("FAILURE - rG!=O")
+        fail=true;
+    }
+    
+    var start=Date()
+    var iterations=0
+    var elapsed=0.0
+    while elapsed<MIN_TIME || iterations<MIN_ITERS {
+        W=G.mul(s)
+        iterations+=1
+        elapsed = -start.timeIntervalSinceNow
+    }
+    elapsed=1000.0*elapsed/Double(iterations)
+    print(String(format: "EC  mul - %d iterations",iterations),terminator: "");
+    print(String(format: " %.2f ms per iteration",elapsed))
+    
+    print("Generating \(ROM.FFLEN*ROM.BIGBITS) RSA public/private key pair")
+    
+    start=Date()
+    iterations=0
+    elapsed=0.0
+    while elapsed<MIN_TIME || iterations<MIN_ITERS {
+        RSA.KEY_PAIR(rng,65537,priv,pub)
+        iterations+=1
+        elapsed = -start.timeIntervalSinceNow
+    }
+    elapsed=1000.0*elapsed/Double(iterations)
+    print(String(format: "RSA gen - %d iterations",iterations),terminator: "");
+    print(String(format: " %.2f ms per iteration",elapsed))
+    
+    for i in 0..<RSA.RFS {M[i]=UInt8(i%128)}
+    
+    start=Date()
+    iterations=0
+    elapsed=0.0
+    while elapsed<MIN_TIME || iterations<MIN_ITERS {
+        RSA.ENCRYPT(pub,M,&C)
+        iterations+=1
+        elapsed = -start.timeIntervalSinceNow
+    }
+    elapsed=1000.0*elapsed/Double(iterations)
+    print(String(format: "RSA enc - %d iterations",iterations),terminator: "");
+    print(String(format: " %.2f ms per iteration",elapsed))
+   
+    start=Date()
+    iterations=0
+    elapsed=0.0
+    while elapsed<MIN_TIME || iterations<MIN_ITERS {
+        RSA.DECRYPT(priv,C,&P)
+        iterations+=1
+        elapsed = -start.timeIntervalSinceNow
+    }
+    elapsed=1000.0*elapsed/Double(iterations)
+    print(String(format: "RSA dec - %d iterations",iterations),terminator: "");
+    print(String(format: " %.2f ms per iteration",elapsed))
+   
+    var cmp=true
+    for i in 0..<RSA.RFS {
+        if P[i] != M[i] {cmp=false}
+    }
+    
+    if !cmp {
+        print("FAILURE - RSA decryption")
+        fail=true;
+    }
+    
+    if !fail {
+       print("All tests pass")
+    }
+}
+
+//BenchtestEC()
+
diff --git a/version22/swift/BenchtestPAIR.swift b/version22/swift/BenchtestPAIR.swift
new file mode 100644
index 0000000..6b60f21
--- /dev/null
+++ b/version22/swift/BenchtestPAIR.swift
@@ -0,0 +1,206 @@
+/*
+	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.
+ */
+
+//
+//  TestMPIN.swift
+//
+//  Created by Michael Scott on 08/07/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+import Foundation
+//import amcl  // comment out for Xcode
+
+public func BenchtestPAIR()
+{
+    let MIN_TIME=10.0
+    let MIN_ITERS=10
+    
+    let rng=RAND()
+    var fail=false;
+    
+    var RAW=[UInt8](repeating: 0,count: 100)
+    
+    for i in 0 ..< 100 {RAW[i]=UInt8((i+1)&0xff)}
+    rng.seed(100,RAW)
+
+    if ROM.CURVE_PAIRING_TYPE==ROM.BN_CURVE {
+        print("BN Pairing-Friendly Curve")
+    }
+    if ROM.CURVE_PAIRING_TYPE==ROM.BLS_CURVE {
+        print("BLS Pairing-Friendly Curve")
+    }
+    print("Modulus size \(ROM.MODBITS) bits")
+    print("\(ROM.CHUNK) bit build")
+    
+    let gx=BIG(ROM.CURVE_Gx);
+
+    let gy=BIG(ROM.CURVE_Gy)
+    let G=ECP(gx,gy)
+    
+    let r=BIG(ROM.CURVE_Order)
+    let s=BIG.randomnum(r,rng)
+    
+    var P=PAIR.G1mul(G,r);
+    
+    if !P.is_infinity() {
+        print("FAILURE - rP!=O")
+        fail=true
+    }
+    
+    var start=Date()
+    var iterations=0
+    var elapsed=0.0
+    while elapsed<MIN_TIME || iterations<MIN_ITERS {
+        P=PAIR.G1mul(G,s)
+        iterations+=1
+        elapsed = -start.timeIntervalSinceNow
+    }
+    elapsed=1000.0*elapsed/Double(iterations)
+    print(String(format: "G1  mul              - %d iterations",iterations),terminator: "");
+    print(String(format: " %.2f ms per iteration",elapsed))
+    
+    var Q=ECP2(FP2(BIG(ROM.CURVE_Pxa),BIG(ROM.CURVE_Pxb)),FP2(BIG(ROM.CURVE_Pya),BIG(ROM.CURVE_Pyb)))
+    
+    var W=PAIR.G2mul(Q,r)
+    
+    if !W.is_infinity() {
+        print("FAILURE - rQ!=O")
+        fail=true
+    }
+    
+    start=Date()
+    iterations=0
+    elapsed=0.0
+    while elapsed<MIN_TIME || iterations<MIN_ITERS {
+        W=PAIR.G2mul(Q,s)
+        iterations+=1
+        elapsed = -start.timeIntervalSinceNow
+    }
+    elapsed=1000.0*elapsed/Double(iterations)
+    print(String(format: "G2  mul              - %d iterations",iterations),terminator: "");
+    print(String(format: " %.2f ms per iteration",elapsed))
+    
+    var w=PAIR.ate(Q,P)
+    w=PAIR.fexp(w)
+    
+    var g=PAIR.GTpow(w,r)
+    
+    if !g.isunity() {
+        print("FAILURE - g^r!=1")
+        fail=true
+    }
+    
+    start=Date()
+    iterations=0
+    elapsed=0.0
+    while elapsed<MIN_TIME || iterations<MIN_ITERS {
+        g=PAIR.GTpow(w,s)
+        iterations+=1
+        elapsed = -start.timeIntervalSinceNow
+    }
+    elapsed=1000.0*elapsed/Double(iterations)
+    print(String(format: "GT  pow              - %d iterations",iterations),terminator: "");
+    print(String(format: " %.2f ms per iteration",elapsed))
+   
+    let f=FP2(BIG(ROM.CURVE_Fra),BIG(ROM.CURVE_Frb))
+    let q=BIG(ROM.Modulus)
+    
+    var m=BIG(q)
+    m.mod(r)
+    
+    let a=BIG(s)
+    a.mod(m)
+    
+    let b=BIG(s)
+    b.div(m)
+    
+    g.copy(w)
+    var c=g.trace()
+    
+    g.frob(f)
+    let cp=g.trace()
+    
+    w.conj()
+    g.mul(w);
+    let cpm1=g.trace()
+    
+    g.mul(w)
+    let cpm2=g.trace()
+    
+    start=Date()
+    iterations=0
+    elapsed=0.0
+    while elapsed<MIN_TIME || iterations<MIN_ITERS {
+        c=c.xtr_pow2(cp,cpm1,cpm2,a,b)
+        iterations+=1
+        elapsed = -start.timeIntervalSinceNow
+    }
+    elapsed=1000.0*elapsed/Double(iterations)
+    print(String(format: "GT  pow (compressed) - %d iterations",iterations),terminator: "");
+    print(String(format: " %.2f ms per iteration",elapsed))
+    
+    start=Date()
+    iterations=0
+    elapsed=0.0
+    while elapsed<MIN_TIME || iterations<MIN_ITERS {
+        w=PAIR.ate(Q,P)
+        iterations+=1
+        elapsed = -start.timeIntervalSinceNow
+    }
+    elapsed=1000.0*elapsed/Double(iterations)
+    print(String(format: "PAIRing ATE          - %d iterations",iterations),terminator: "");
+    print(String(format: " %.2f ms per iteration",elapsed))
+
+    start=Date()
+    iterations=0
+    elapsed=0.0
+    while elapsed<MIN_TIME || iterations<MIN_ITERS {
+        g=PAIR.fexp(w)
+        iterations+=1
+        elapsed = -start.timeIntervalSinceNow
+    }
+    elapsed=1000.0*elapsed/Double(iterations)
+    print(String(format: "PAIRing FEXP         - %d iterations",iterations),terminator: "");
+    print(String(format: " %.2f ms per iteration",elapsed))
+ 
+    P.copy(G)
+    Q.copy(W)
+    
+    P=PAIR.G1mul(P,s)
+    g=PAIR.ate(Q,P)
+    g=PAIR.fexp(g)
+    
+    P.copy(G)
+    Q=PAIR.G2mul(Q,s)
+    w=PAIR.ate(Q,P)
+    w=PAIR.fexp(w)
+    
+    if !g.equals(w) {
+        print("FAILURE - e(sQ,P)!=e(Q,sP)")
+        fail=true
+    }
+    
+    if !fail {
+        print("All tests pass")
+    }
+}
+
+//BenchtestPAIR()
+
diff --git a/version22/swift/TestECDH.swift b/version22/swift/TestECDH.swift
new file mode 100644
index 0000000..3302d75
--- /dev/null
+++ b/version22/swift/TestECDH.swift
@@ -0,0 +1,167 @@
+/*
+	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
+
+public func TestECDH()
+{
+    let pp=String("M0ng00se");
+    
+    let EGS=ECDH.EGS
+    let EFS=ECDH.EFS
+    let EAS=16
+    let sha=ECDH.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 RAW=[UInt8](repeating: 0,count: 100)
+    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)
+    
+    let rng=RAND()
+    
+    rng.clean();
+    for i in 0 ..< 100 {RAW[i]=UInt8(i&0xff)}
+    
+    rng.seed(100,RAW)
+    
+    
+    for i in 0 ..< 8 {SALT[i]=UInt8(i+1)}  // set Salt
+    
+    print("Alice's Passphrase= " + pp!)
+    let PW=[UInt8]( (!pp).utf8)
+    
+    /* private key S0 of size EGS bytes derived from Password and Salt */
+    
+    var S0=ECDH.PBKDF2(sha,PW,SALT,1000,EGS)
+    print("Alice's private key= 0x",terminator: ""); ECDH.printBinary(S0)
+    
+    /* Generate Key pair S/W */
+    ECDH.KEY_PAIR_GENERATE(nil,&S0,&W0);
+    
+    print("Alice's public key= 0x",terminator: ""); ECDH.printBinary(W0)
+    
+    var res=ECDH.PUBLIC_KEY_VALIDATE(true,W0);
+
+    if res != 0
+    {
+        print("ECP Public Key is invalid!");
+        return;
+    }
+    
+    /* Random private key for other party */
+    ECDH.KEY_PAIR_GENERATE(rng,&S1,&W1)
+    
+    print("Servers private key= 0x",terminator: ""); ECDH.printBinary(S1)
+    
+    print("Servers public key= 0x",terminator: ""); ECDH.printBinary(W1);
+    
+    res=ECDH.PUBLIC_KEY_VALIDATE(true,W1)
+    if res != 0
+    {
+        print("ECP Public Key is invalid!")
+        return
+    }
+    
+    /* Calculate common key using DH - IEEE 1363 method */
+    
+    ECDH.ECPSVDP_DH(S0,W1,&Z0)
+    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=ECDH.KDF2(sha,Z0,nil,EAS)
+    
+    print("Alice's DH Key=  0x",terminator: ""); ECDH.printBinary(KEY)
+    print("Servers DH Key=  0x",terminator: ""); ECDH.printBinary(KEY)
+
+    if ROM.CURVETYPE != ROM.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=ECDH.ECIES_ENCRYPT(sha,P1,P2,rng,W1,M,&V,&T)
+
+        print("Ciphertext= ")
+        print("V= 0x",terminator: ""); ECDH.printBinary(V)
+        print("C= 0x",terminator: ""); ECDH.printBinary(C)
+        print("T= 0x",terminator: ""); ECDH.printBinary(T)
+
+        M=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"); ECDH.printBinary(M)
+    
+        print("Testing ECDSA")
+
+        if ECDH.ECPSP_DSA(sha,rng,S0,M,&CS,&DS) != 0
+        {
+            print("***ECDSA Signature Failed")
+            return
+        }
+        print("Signature= ")
+        print("C= 0x",terminator: ""); ECDH.printBinary(CS)
+        print("D= 0x",terminator: ""); ECDH.printBinary(DS)
+    
+        if ECDH.ECPVP_DSA(sha,W0,M,CS,DS) != 0
+        {
+            print("***ECDSA Verification Failed")
+            return
+        }
+        else {print("ECDSA Signature/Verification succeeded ")}
+    }
+}
+
+//TestECDH()  // comment out for Xcode
diff --git a/version22/swift/TestMPIN.swift b/version22/swift/TestMPIN.swift
new file mode 100644
index 0000000..8df61ea
--- /dev/null
+++ b/version22/swift/TestMPIN.swift
@@ -0,0 +1,259 @@
+/*
+	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.
+*/
+
+//
+//  TestMPIN.swift
+//
+//  Created by Michael Scott on 08/07/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+import Foundation
+//import amcl  // comment out for Xcode
+
+public func TestMPIN()
+{
+    let PERMITS=true
+    let PINERROR=true
+    let FULL=true
+    let SINGLE_PASS=false
+   
+    let rng=RAND()
+    
+    var RAW=[UInt8](repeating: 0,count: 100)
+    
+    for i in 0 ..< 100 {RAW[i]=UInt8((i+1)&0xff)}
+    rng.seed(100,RAW)
+    
+    let EGS=MPIN.EFS
+    let EFS=MPIN.EGS
+    let G1S=2*EFS+1    // Group 1 Size
+    let G2S=4*EFS;     // Group 2 Size
+    let EAS=MPIN.PAS
+    
+    let sha=MPIN.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
+    
+    MPIN.RANDOM_GENERATE(rng,&S)
+    print("Master Secret s: 0x",terminator: "");  MPIN.printBinary(S)
+    
+    // Create Client Identity
+    let IDstr = "testUser@miracl.com"
+    let CLIENT_ID=[UInt8](IDstr.utf8)
+    
+    var HCID=MPIN.HASH_ID(sha,CLIENT_ID)  // Either Client or TA calculates Hash(ID) - you decide!
+    
+    print("Client ID= "); MPIN.printBinary(CLIENT_ID)
+    
+    // Client and Server are issued secrets by DTA
+    MPIN.GET_SERVER_SECRET(S,&SST);
+    print("Server Secret SS: 0x",terminator: "");  MPIN.printBinary(SST);
+    
+    MPIN.GET_CLIENT_SECRET(&S,HCID,&TOKEN);
+    print("Client Secret CS: 0x",terminator: ""); MPIN.printBinary(TOKEN);
+    
+    // Client extracts PIN from secret to create Token
+    var pin:Int32=1234
+    print("Client extracts PIN= \(pin)")
+    var rtn=MPIN.EXTRACT_PIN(sha,CLIENT_ID,pin,&TOKEN)
+    if rtn != 0 {print("FAILURE: EXTRACT_PIN rtn: \(rtn)")}
+    
+    print("Client Token TK: 0x",terminator: ""); MPIN.printBinary(TOKEN);
+
+    if FULL
+    {
+        MPIN.PRECOMPUTE(TOKEN,HCID,&G1,&G2);
+    }
+    
+    var date:Int32=0
+    if (PERMITS)
+    {
+        date=MPIN.today()
+        // Client gets "Time Token" permit from DTA
+        MPIN.GET_CLIENT_PERMIT(sha,date,S,HCID,&PERMIT)
+        print("Time Permit TP: 0x",terminator: "");  MPIN.printBinary(PERMIT)
+        
+        // This encoding makes Time permit look random - Elligator squared
+        MPIN.ENCODING(rng,&PERMIT);
+        print("Encoded Time Permit TP: 0x",terminator: "");  MPIN.printBinary(PERMIT)
+        MPIN.DECODING(&PERMIT)
+        print("Decoded Time Permit TP: 0x",terminator: "");  MPIN.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
+    
+    if date != 0
+    {
+        if (!PINERROR)
+        {
+            pxID=nil;
+   //         pHID=nil;
+        }
+    }
+    else
+    {
+        pPERMIT=nil;
+        pxCID=nil;
+        pHTID=nil;
+    }
+    if (!PINERROR)
+    {
+        pE=nil;
+        pF=nil;
+    }
+    
+    if (SINGLE_PASS)
+    {
+        print("MPIN Single Pass")
+        let timeValue = MPIN.GET_TIME()
+
+        rtn=MPIN.CLIENT(sha,date,CLIENT_ID,rng,&X,pin,TOKEN,&SEC,&pxID,&pxCID,pPERMIT!,timeValue,&Y)
+        
+        if rtn != 0 {print("FAILURE: CLIENT rtn: \(rtn)")}
+        
+        if (FULL)
+        {
+            HCID=MPIN.HASH_ID(sha,CLIENT_ID);
+            MPIN.GET_G1_MULTIPLE(rng,1,&R,HCID,&Z); // Also Send Z=r.ID to Server, remember random r
+        }
+        rtn=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=MPIN.HASH_ID(sha,CLIENT_ID);	
+            if date != 0 {MPIN.GET_G1_MULTIPLE(rng,0,&W,pHTID!,&T)}
+            else {MPIN.GET_G1_MULTIPLE(rng,0,&W,pHID,&T)}
+            
+        }
+    }
+    else
+    {
+        print("MPIN Multi Pass");
+        // Send U=x.ID to server, and recreate secret from token and pin
+        rtn=MPIN.CLIENT_1(sha,date,CLIENT_ID,rng,&X,pin,TOKEN,&SEC,&pxID,&pxCID,pPERMIT!)
+        if rtn != 0 {print("FAILURE: CLIENT_1 rtn: \(rtn)")}
+            
+        if (FULL)
+        {
+            HCID=MPIN.HASH_ID(sha,CLIENT_ID);
+            MPIN.GET_G1_MULTIPLE(rng,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.
+        MPIN.SERVER_1(sha,date,CLIENT_ID,&pHID,&pHTID!);
+            
+            // Server generates Random number Y and sends it to Client
+        MPIN.RANDOM_GENERATE(rng,&Y);
+            
+        if (FULL)
+        { // Also send T=w.ID to client, remember random w
+            HSID=MPIN.HASH_ID(sha,CLIENT_ID);
+            if date != 0 {MPIN.GET_G1_MULTIPLE(rng,0,&W,pHTID!,&T)}
+            else {MPIN.GET_G1_MULTIPLE(rng,0,&W,pHID,&T)}
+        }
+            
+        // Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC
+        rtn=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=MPIN.SERVER_2(date,pHID,pHTID!,Y,SST,pxID!,pxCID!,SEC,&pE,&pF);
+            
+        if rtn != 0 {print("FAILURE: SERVER_1 rtn: \(rtn)")}
+    }
+    if (rtn == MPIN.BAD_PIN)
+    {
+        print("Server says - Bad Pin. I don't know you. Feck off.\n");
+        if (PINERROR)
+        {
+            let err=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=MPIN.HASH_ALL(sha,HCID,pxID!,pxCID!,SEC,Y,Z,T);
+        MPIN.CLIENT_KEY(sha,G1,G2,pin,R,X,H,T,&CK);
+        print("Client Key =  0x",terminator: "");  MPIN.printBinary(CK)
+        
+        H=MPIN.HASH_ALL(sha,HSID,pxID!,pxCID!,SEC,Y,Z,T);
+        MPIN.SERVER_KEY(sha,Z,SST,W,H,pHID,pxID!,pxCID!,&SK);
+        print("Server Key =  0x",terminator: "");  MPIN.printBinary(SK)
+    }
+    
+}
+
+//TestMPIN() // comment out for Xcode
+
diff --git a/version22/swift/TestRSA.swift b/version22/swift/TestRSA.swift
new file mode 100644
index 0000000..a2a8dcb
--- /dev/null
+++ b/version22/swift/TestRSA.swift
@@ -0,0 +1,100 @@
+/*
+	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.
+*/
+
+//
+//  TestRSA.swift
+//
+//  Created by Michael Scott on 25/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+import Foundation
+//import amcl   // comment out for Xcode
+
+public func TestRSA()
+{
+    let RFS=RSA.RFS
+
+    var message="Hello World\n"
+
+    let pub=rsa_public_key(Int(ROM.FFLEN))
+    let priv=rsa_private_key(Int(ROM.HFLEN))
+
+    var ML=[UInt8](repeating: 0,count: RFS)
+    var C=[UInt8](repeating: 0,count: RFS)
+    var S=[UInt8](repeating: 0,count: RFS)
+    var RAW=[UInt8](repeating: 0,count: 100)
+
+    let rng=RAND()
+
+    rng.clean()
+    for i in 0 ..< 100 {RAW[i]=UInt8(i)}
+
+    rng.seed(100,RAW)
+
+    print("Generating 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: ""); RSA.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: ""); RSA.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);
+}
+
+//TestRSA() // comment out for Xcode
+
+
+
diff --git a/version22/swift/aes.swift b/version22/swift/aes.swift
new file mode 100644
index 0000000..0de2980
--- /dev/null
+++ b/version22/swift/aes.swift
@@ -0,0 +1,639 @@
+/*
+	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.
+*/
+
+//
+//  aes.swift
+//
+//  Created by Michael Scott on 22/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+//   AES Encryption
+//
+
+final public class AES {
+    var mode:Int=0;
+    private var fkey=[UInt32](repeating: 0,count: 44)
+    private var rkey=[UInt32](repeating: 0,count: 44)
+    var f=[UInt8](repeating: 0,count: 16)
+    
+    static let ECB:Int=0
+    static let CBC:Int=1
+    static let CFB1:Int=2
+    static let CFB2:Int=3
+    static let CFB4:Int=5
+    static let OFB1:Int=14
+    static let OFB2:Int=15
+    static let OFB4:Int=17
+    static let OFB8:Int=21
+    static let OFB16:Int=29
+    static let CTR1:Int=30
+    static let CTR2:Int=31
+    static let CTR4:Int=33 
+    static let CTR8:Int=37 
+    static let CTR16:Int=45
+
+    static public let KS:Int=16; /* Key Size in bytes */
+    static public let BS:Int=16; /* Block Size */
+    
+    private static let InCo:[UInt8] = [ 0xB,0xD,0x9,0xE]  /* Inverse Coefficients */
+    
+    private static let ptab:[UInt8] =
+    [ 1, 3, 5, 15, 17, 51, 85, 255, 26, 46, 114, 150, 161, 248, 19, 53,
+     95, 225, 56, 72, 216, 115, 149, 164, 247, 2, 6, 10, 30, 34, 102, 170,
+     229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217, 112, 144, 171, 230, 49,
+     83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104, 184, 211, 110, 178, 205,
+     76, 212, 103, 169, 224, 59, 77, 215, 98, 166, 241, 8, 24, 40, 120, 136,
+     131, 158, 185, 208, 107, 189, 220, 127, 129, 152, 179, 206, 73, 219, 118, 154,
+     181, 196, 87, 249, 16, 48, 80, 240, 11, 29, 39, 105, 187, 214, 97, 163,
+     254, 25, 43, 125, 135, 146, 173, 236, 47, 113, 147, 174, 233, 32, 96, 160,
+     251, 22, 58, 78, 210, 109, 183, 194, 93, 231, 50, 86, 250, 21, 63, 65,
+     195, 94, 226, 61, 71, 201, 64, 192, 91, 237, 44, 116, 156, 191, 218, 117,
+     159, 186, 213, 100, 172, 239, 42, 126, 130, 157, 188, 223, 122, 142, 137, 128,
+     155, 182, 193, 88, 232, 35, 101, 175, 234, 37, 111, 177, 200, 67, 197, 84,
+     252, 31, 33, 99, 165, 244, 7, 9, 27, 45, 119, 153, 176, 203, 70, 202,
+     69, 207, 74, 222, 121, 139, 134, 145, 168, 227, 62, 66, 198, 81, 243, 14,
+     18, 54, 90, 238, 41, 123, 141, 140, 143, 138, 133, 148, 167, 242, 13, 23,
+     57, 75, 221, 124, 132, 151, 162, 253, 28, 36, 108, 180, 199, 82, 246, 1]
+    
+    private static let ltab:[UInt8] =
+    [ 0, 255, 25, 1, 50, 2, 26, 198, 75, 199, 27, 104, 51, 238, 223, 3,
+     100, 4, 224, 14, 52, 141, 129, 239, 76, 113, 8, 200, 248, 105, 28, 193,
+     125, 194, 29, 181, 249, 185, 39, 106, 77, 228, 166, 114, 154, 201, 9, 120,
+     101, 47, 138, 5, 33, 15, 225, 36, 18, 240, 130, 69, 53, 147, 218, 142,
+     150, 143, 219, 189, 54, 208, 206, 148, 19, 92, 210, 241, 64, 70, 131, 56,
+     102, 221, 253, 48, 191, 6, 139, 98, 179, 37, 226, 152, 34, 136, 145, 16,
+     126, 110, 72, 195, 163, 182, 30, 66, 58, 107, 40, 84, 250, 133, 61, 186,
+     43, 121, 10, 21, 155, 159, 94, 202, 78, 212, 172, 229, 243, 115, 167, 87,
+     175, 88, 168, 80, 244, 234, 214, 116, 79, 174, 233, 213, 231, 230, 173, 232,
+     44, 215, 117, 122, 235, 22, 11, 245, 89, 203, 95, 176, 156, 169, 81, 160,
+     127, 12, 246, 111, 23, 196, 73, 236, 216, 67, 31, 45, 164, 118, 123, 183,
+     204, 187, 62, 90, 251, 96, 177, 134, 59, 82, 161, 108, 170, 85, 41, 157,
+     151, 178, 135, 144, 97, 190, 220, 252, 188, 149, 207, 205, 55, 63, 91, 209,
+     83, 57, 132, 60, 65, 162, 109, 71, 20, 42, 158, 93, 86, 242, 211, 171,
+     68, 17, 146, 217, 35, 32, 46, 137, 180, 124, 184, 38, 119, 153, 227, 165,
+     103, 74, 237, 222, 197, 49, 254, 24, 13, 99, 140, 128, 192, 247, 112, 7]
+    
+    private static let fbsub:[UInt8] =
+    [ 99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118,
+     202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192,
+     183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21,
+     4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117,
+     9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132,
+     83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207,
+     208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168,
+     81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210,
+     205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115,
+     96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219,
+     224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121,
+     231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8,
+     186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138,
+     112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158,
+     225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223,
+     140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22]
+    
+    private static let rbsub:[UInt8] =
+    [ 82, 9, 106, 213, 48, 54, 165, 56, 191, 64, 163, 158, 129, 243, 215, 251,
+     124, 227, 57, 130, 155, 47, 255, 135, 52, 142, 67, 68, 196, 222, 233, 203,
+     84, 123, 148, 50, 166, 194, 35, 61, 238, 76, 149, 11, 66, 250, 195, 78,
+     8, 46, 161, 102, 40, 217, 36, 178, 118, 91, 162, 73, 109, 139, 209, 37,
+     114, 248, 246, 100, 134, 104, 152, 22, 212, 164, 92, 204, 93, 101, 182, 146,
+     108, 112, 72, 80, 253, 237, 185, 218, 94, 21, 70, 87, 167, 141, 157, 132,
+     144, 216, 171, 0, 140, 188, 211, 10, 247, 228, 88, 5, 184, 179, 69, 6,
+     208, 44, 30, 143, 202, 63, 15, 2, 193, 175, 189, 3, 1, 19, 138, 107,
+     58, 145, 17, 65, 79, 103, 220, 234, 151, 242, 207, 206, 240, 180, 230, 115,
+     150, 172, 116, 34, 231, 173, 53, 133, 226, 249, 55, 232, 28, 117, 223, 110,
+     71, 241, 26, 113, 29, 41, 197, 137, 111, 183, 98, 14, 170, 24, 190, 27,
+     252, 86, 62, 75, 198, 210, 121, 32, 154, 219, 192, 254, 120, 205, 90, 244,
+     31, 221, 168, 51, 136, 7, 199, 49, 177, 18, 16, 89, 39, 128, 236, 95,
+     96, 81, 127, 169, 25, 181, 74, 13, 45, 229, 122, 159, 147, 201, 156, 239,
+     160, 224, 59, 77, 174, 42, 245, 176, 200, 235, 187, 60, 131, 83, 153, 97,
+     23, 43, 4, 126, 186, 119, 214, 38, 225, 105, 20, 99, 85, 33, 12, 125]
+    
+    private static let rco:[UInt8] =
+    [1,2,4,8,16,32,64,128,27,54,108,216,171,77,154,47]
+
+    private static let ftable:[UInt32] =
+    [0xa56363c6,0x847c7cf8,0x997777ee,0x8d7b7bf6,0xdf2f2ff,0xbd6b6bd6,
+    0xb16f6fde,0x54c5c591,0x50303060,0x3010102,0xa96767ce,0x7d2b2b56,
+    0x19fefee7,0x62d7d7b5,0xe6abab4d,0x9a7676ec,0x45caca8f,0x9d82821f,
+    0x40c9c989,0x877d7dfa,0x15fafaef,0xeb5959b2,0xc947478e,0xbf0f0fb,
+    0xecadad41,0x67d4d4b3,0xfda2a25f,0xeaafaf45,0xbf9c9c23,0xf7a4a453,
+    0x967272e4,0x5bc0c09b,0xc2b7b775,0x1cfdfde1,0xae93933d,0x6a26264c,
+    0x5a36366c,0x413f3f7e,0x2f7f7f5,0x4fcccc83,0x5c343468,0xf4a5a551,
+    0x34e5e5d1,0x8f1f1f9,0x937171e2,0x73d8d8ab,0x53313162,0x3f15152a,
+    0xc040408,0x52c7c795,0x65232346,0x5ec3c39d,0x28181830,0xa1969637,
+    0xf05050a,0xb59a9a2f,0x907070e,0x36121224,0x9b80801b,0x3de2e2df,
+    0x26ebebcd,0x6927274e,0xcdb2b27f,0x9f7575ea,0x1b090912,0x9e83831d,
+    0x742c2c58,0x2e1a1a34,0x2d1b1b36,0xb26e6edc,0xee5a5ab4,0xfba0a05b,
+    0xf65252a4,0x4d3b3b76,0x61d6d6b7,0xceb3b37d,0x7b292952,0x3ee3e3dd,
+    0x712f2f5e,0x97848413,0xf55353a6,0x68d1d1b9,0x0,0x2cededc1,
+    0x60202040,0x1ffcfce3,0xc8b1b179,0xed5b5bb6,0xbe6a6ad4,0x46cbcb8d,
+    0xd9bebe67,0x4b393972,0xde4a4a94,0xd44c4c98,0xe85858b0,0x4acfcf85,
+    0x6bd0d0bb,0x2aefefc5,0xe5aaaa4f,0x16fbfbed,0xc5434386,0xd74d4d9a,
+    0x55333366,0x94858511,0xcf45458a,0x10f9f9e9,0x6020204,0x817f7ffe,
+    0xf05050a0,0x443c3c78,0xba9f9f25,0xe3a8a84b,0xf35151a2,0xfea3a35d,
+    0xc0404080,0x8a8f8f05,0xad92923f,0xbc9d9d21,0x48383870,0x4f5f5f1,
+    0xdfbcbc63,0xc1b6b677,0x75dadaaf,0x63212142,0x30101020,0x1affffe5,
+    0xef3f3fd,0x6dd2d2bf,0x4ccdcd81,0x140c0c18,0x35131326,0x2fececc3,
+    0xe15f5fbe,0xa2979735,0xcc444488,0x3917172e,0x57c4c493,0xf2a7a755,
+    0x827e7efc,0x473d3d7a,0xac6464c8,0xe75d5dba,0x2b191932,0x957373e6,
+    0xa06060c0,0x98818119,0xd14f4f9e,0x7fdcdca3,0x66222244,0x7e2a2a54,
+    0xab90903b,0x8388880b,0xca46468c,0x29eeeec7,0xd3b8b86b,0x3c141428,
+    0x79dedea7,0xe25e5ebc,0x1d0b0b16,0x76dbdbad,0x3be0e0db,0x56323264,
+    0x4e3a3a74,0x1e0a0a14,0xdb494992,0xa06060c,0x6c242448,0xe45c5cb8,
+    0x5dc2c29f,0x6ed3d3bd,0xefacac43,0xa66262c4,0xa8919139,0xa4959531,
+    0x37e4e4d3,0x8b7979f2,0x32e7e7d5,0x43c8c88b,0x5937376e,0xb76d6dda,
+    0x8c8d8d01,0x64d5d5b1,0xd24e4e9c,0xe0a9a949,0xb46c6cd8,0xfa5656ac,
+    0x7f4f4f3,0x25eaeacf,0xaf6565ca,0x8e7a7af4,0xe9aeae47,0x18080810,
+    0xd5baba6f,0x887878f0,0x6f25254a,0x722e2e5c,0x241c1c38,0xf1a6a657,
+    0xc7b4b473,0x51c6c697,0x23e8e8cb,0x7cdddda1,0x9c7474e8,0x211f1f3e,
+    0xdd4b4b96,0xdcbdbd61,0x868b8b0d,0x858a8a0f,0x907070e0,0x423e3e7c,
+    0xc4b5b571,0xaa6666cc,0xd8484890,0x5030306,0x1f6f6f7,0x120e0e1c,
+    0xa36161c2,0x5f35356a,0xf95757ae,0xd0b9b969,0x91868617,0x58c1c199,
+    0x271d1d3a,0xb99e9e27,0x38e1e1d9,0x13f8f8eb,0xb398982b,0x33111122,
+    0xbb6969d2,0x70d9d9a9,0x898e8e07,0xa7949433,0xb69b9b2d,0x221e1e3c,
+    0x92878715,0x20e9e9c9,0x49cece87,0xff5555aa,0x78282850,0x7adfdfa5,
+    0x8f8c8c03,0xf8a1a159,0x80898909,0x170d0d1a,0xdabfbf65,0x31e6e6d7,
+    0xc6424284,0xb86868d0,0xc3414182,0xb0999929,0x772d2d5a,0x110f0f1e,
+    0xcbb0b07b,0xfc5454a8,0xd6bbbb6d,0x3a16162c]
+
+    private static let rtable:[UInt32] =
+    [0x50a7f451,0x5365417e,0xc3a4171a,0x965e273a,0xcb6bab3b,0xf1459d1f,
+    0xab58faac,0x9303e34b,0x55fa3020,0xf66d76ad,0x9176cc88,0x254c02f5,
+    0xfcd7e54f,0xd7cb2ac5,0x80443526,0x8fa362b5,0x495ab1de,0x671bba25,
+    0x980eea45,0xe1c0fe5d,0x2752fc3,0x12f04c81,0xa397468d,0xc6f9d36b,
+    0xe75f8f03,0x959c9215,0xeb7a6dbf,0xda595295,0x2d83bed4,0xd3217458,
+    0x2969e049,0x44c8c98e,0x6a89c275,0x78798ef4,0x6b3e5899,0xdd71b927,
+    0xb64fe1be,0x17ad88f0,0x66ac20c9,0xb43ace7d,0x184adf63,0x82311ae5,
+    0x60335197,0x457f5362,0xe07764b1,0x84ae6bbb,0x1ca081fe,0x942b08f9,
+    0x58684870,0x19fd458f,0x876cde94,0xb7f87b52,0x23d373ab,0xe2024b72,
+    0x578f1fe3,0x2aab5566,0x728ebb2,0x3c2b52f,0x9a7bc586,0xa50837d3,
+    0xf2872830,0xb2a5bf23,0xba6a0302,0x5c8216ed,0x2b1ccf8a,0x92b479a7,
+    0xf0f207f3,0xa1e2694e,0xcdf4da65,0xd5be0506,0x1f6234d1,0x8afea6c4,
+    0x9d532e34,0xa055f3a2,0x32e18a05,0x75ebf6a4,0x39ec830b,0xaaef6040,
+    0x69f715e,0x51106ebd,0xf98a213e,0x3d06dd96,0xae053edd,0x46bde64d,
+    0xb58d5491,0x55dc471,0x6fd40604,0xff155060,0x24fb9819,0x97e9bdd6,
+    0xcc434089,0x779ed967,0xbd42e8b0,0x888b8907,0x385b19e7,0xdbeec879,
+    0x470a7ca1,0xe90f427c,0xc91e84f8,0x0,0x83868009,0x48ed2b32,
+    0xac70111e,0x4e725a6c,0xfbff0efd,0x5638850f,0x1ed5ae3d,0x27392d36,
+    0x64d90f0a,0x21a65c68,0xd1545b9b,0x3a2e3624,0xb1670a0c,0xfe75793,
+    0xd296eeb4,0x9e919b1b,0x4fc5c080,0xa220dc61,0x694b775a,0x161a121c,
+    0xaba93e2,0xe52aa0c0,0x43e0223c,0x1d171b12,0xb0d090e,0xadc78bf2,
+    0xb9a8b62d,0xc8a91e14,0x8519f157,0x4c0775af,0xbbdd99ee,0xfd607fa3,
+    0x9f2601f7,0xbcf5725c,0xc53b6644,0x347efb5b,0x7629438b,0xdcc623cb,
+    0x68fcedb6,0x63f1e4b8,0xcadc31d7,0x10856342,0x40229713,0x2011c684,
+    0x7d244a85,0xf83dbbd2,0x1132f9ae,0x6da129c7,0x4b2f9e1d,0xf330b2dc,
+    0xec52860d,0xd0e3c177,0x6c16b32b,0x99b970a9,0xfa489411,0x2264e947,
+    0xc48cfca8,0x1a3ff0a0,0xd82c7d56,0xef903322,0xc74e4987,0xc1d138d9,
+    0xfea2ca8c,0x360bd498,0xcf81f5a6,0x28de7aa5,0x268eb7da,0xa4bfad3f,
+    0xe49d3a2c,0xd927850,0x9bcc5f6a,0x62467e54,0xc2138df6,0xe8b8d890,
+    0x5ef7392e,0xf5afc382,0xbe805d9f,0x7c93d069,0xa92dd56f,0xb31225cf,
+    0x3b99acc8,0xa77d1810,0x6e639ce8,0x7bbb3bdb,0x97826cd,0xf418596e,
+    0x1b79aec,0xa89a4f83,0x656e95e6,0x7ee6ffaa,0x8cfbc21,0xe6e815ef,
+    0xd99be7ba,0xce366f4a,0xd4099fea,0xd67cb029,0xafb2a431,0x31233f2a,
+    0x3094a5c6,0xc066a235,0x37bc4e74,0xa6ca82fc,0xb0d090e0,0x15d8a733,
+    0x4a9804f1,0xf7daec41,0xe50cd7f,0x2ff69117,0x8dd64d76,0x4db0ef43,
+    0x544daacc,0xdf0496e4,0xe3b5d19e,0x1b886a4c,0xb81f2cc1,0x7f516546,
+    0x4ea5e9d,0x5d358c01,0x737487fa,0x2e410bfb,0x5a1d67b3,0x52d2db92,
+    0x335610e9,0x1347d66d,0x8c61d79a,0x7a0ca137,0x8e14f859,0x893c13eb,
+    0xee27a9ce,0x35c961b7,0xede51ce1,0x3cb1477a,0x59dfd29c,0x3f73f255,
+    0x79ce1418,0xbf37c773,0xeacdf753,0x5baafd5f,0x146f3ddf,0x86db4478,
+    0x81f3afca,0x3ec468b9,0x2c342438,0x5f40a3c2,0x72c31d16,0xc25e2bc,
+    0x8b493c28,0x41950dff,0x7101a839,0xdeb30c08,0x9ce4b4d8,0x90c15664,
+    0x6184cb7b,0x70b632d5,0x745c6c48,0x4257b8d0]
+    
+    /* Rotates 32-bit word left by 1, 2 or 3 byte  */
+    
+    private static func ROTL8(_ x: UInt32) -> UInt32
+    {
+        return (((x)<<8)|((x)>>24))
+    }
+    
+    private static func ROTL16(_ x: UInt32) -> UInt32
+    {
+        return (((x)<<16)|((x)>>16))
+    }
+    
+    private static func ROTL24(_ x: UInt32) -> UInt32
+    {
+        return (((x)<<24)|((x)>>8))
+    }
+    
+    private static func pack(_ b: [UInt8]) -> UInt32
+    { /* pack bytes into a 32-bit Word */
+        var r=((UInt32(b[3])&0xff)<<24)|((UInt32(b[2])&0xff)<<16)
+        r = r|((UInt32(b[1])&0xff)<<8)|(UInt32(b[0])&0xff)
+        return r
+    }
+  
+    private static func unpack(_ a: UInt32) -> [UInt8]
+    { /* unpack bytes from a word */
+        let b:[UInt8]=[UInt8(a&0xff),UInt8((a>>8)&0xff),UInt8((a>>16)&0xff),UInt8((a>>24)&0xff)];
+        return b;
+    }
+    
+    private static func bmul(_ x: UInt8,_ y:UInt8) -> UInt8
+    { /* x.y= AntiLog(Log(x) + Log(y)) */
+    
+        let ix=Int(x)&0xff
+        let iy=Int(y)&0xff
+        let lx=Int(ltab[ix])&0xff
+        let ly=Int(ltab[iy])&0xff
+    
+        if x != 0 && y != 0 {return ptab[(lx+ly)%255]}
+        else {return UInt8(0)}
+    }
+    
+    private static func SubByte(_ a: UInt32) -> UInt32
+    {
+        var b=unpack(a)
+        b[0]=fbsub[Int(b[0])]
+        b[1]=fbsub[Int(b[1])]
+        b[2]=fbsub[Int(b[2])]
+        b[3]=fbsub[Int(b[3])]
+        return pack(b);
+    }
+    
+    private static func product(_ x: UInt32,_ y: UInt32) -> UInt8
+    { /* dot product of two 4-byte arrays */
+        var xb=unpack(x);
+        var yb=unpack(y);
+    
+        return (bmul(xb[0],yb[0])^bmul(xb[1],yb[1])^bmul(xb[2],yb[2])^bmul(xb[3],yb[3]))
+    }
+
+    private static func InvMixCol(_ x: UInt32) -> UInt32
+    { /* matrix Multiplication */
+        var b=[UInt8](repeating: 0,count: 4)
+        var m=pack(InCo);
+        b[3]=product(m,x);
+        m=ROTL24(m);
+        b[2]=product(m,x);
+        m=ROTL24(m);
+        b[1]=product(m,x);
+        m=ROTL24(m);
+        b[0]=product(m,x);
+        let y=pack(b)
+        return y
+    }
+  
+    private static func increment(_ f:inout [UInt8])
+    {
+        for i in 0 ..< 16
+        {
+            f[i]+=1
+            if f[i] != 0 {break}
+        }
+    }   
+
+    /* reset cipher */
+    func reset(_ m: Int,_ iv:[UInt8]?)
+    { /* reset mode, or reset iv */
+        mode=m;
+        for i in 0 ..< 16 {f[i]=0}
+        if (mode != AES.ECB) && (iv != nil)
+            {for i in 0 ..< 16 {f[i]=iv![i]}} /*??*/
+    }
+    
+    func init_it(_ m:Int,_ key:[UInt8],_ iv:[UInt8]?)
+    {   /* Key=16 bytes */
+        /* Key Scheduler. Create expanded encryption key */
+        var CipherKey=[UInt32](repeating: 0,count: 4)
+        var b=[UInt8](repeating: 0,count: 4)
+        let nk=4;
+        reset(m,iv);
+        let N=44;
+        
+        var j=0
+        for  i in 0 ..< nk
+        {
+            for k in 0 ..< 4 {b[k]=key[j+k]}
+            CipherKey[i]=AES.pack(b);
+            j+=4;
+        }
+        for i in 0 ..< nk {fkey[i]=CipherKey[i]}
+        j=nk
+        var k=0
+        while j<N
+        {
+            fkey[j]=fkey[j-nk]^AES.SubByte(AES.ROTL24(fkey[j-1]))^UInt32(AES.rco[k])
+            var i=1
+            while i<nk && (i+j)<N
+            {
+                fkey[i+j]=fkey[i+j-nk]^fkey[i+j-1]
+                i+=1
+            }
+            j+=nk
+            k+=1
+        }
+        
+        /* now for the expanded decrypt key in reverse order */
+        
+        for j in 0 ..< 4 {rkey[j+N-4]=fkey[j]}
+        var i=4
+        while i<N-4
+        {
+            let k=N-4-i;
+            for j in 0 ..< 4 {rkey[k+j]=AES.InvMixCol(fkey[i+j])}
+            i+=4
+        }
+        for j in N-4 ..< N {rkey[j-N+4]=fkey[j]}
+    }
+    
+    func getreg() -> [UInt8]
+    {
+        var ir=[UInt8](repeating: 0,count: 16)
+        for i in 0 ..< 16 {ir[i]=f[i]}
+        return ir;
+    }
+    
+    /* Encrypt a single block */
+    func ecb_encrypt(_ buff:inout [UInt8])
+    {
+        var b=[UInt8](repeating: 0,count: 4)
+        var p=[UInt32](repeating: 0,count: 4)
+        var q=[UInt32](repeating: 0,count: 4)
+    
+        var j=0
+        for i in 0 ..< 4
+        {
+            for k in 0 ..< 4 {b[k]=buff[j+k]}
+            p[i]=AES.pack(b);
+            p[i]^=fkey[i];
+            j+=4
+        }
+    
+        var k=4;
+    
+    /* State alternates between p and q */
+        for _ in 1 ..< 10
+        {
+            q[0]=fkey[k]^AES.ftable[Int(p[0]&0xff)]^AES.ROTL8(AES.ftable[Int((p[1]>>8)&0xff)])^AES.ROTL16(AES.ftable[Int((p[2]>>16)&0xff)])^AES.ROTL24(AES.ftable[Int((p[3]>>24)&0xff)])
+            
+            q[1]=fkey[k+1]^AES.ftable[Int(p[1]&0xff)]^AES.ROTL8(AES.ftable[Int((p[2]>>8)&0xff)])^AES.ROTL16(AES.ftable[Int((p[3]>>16)&0xff)])^AES.ROTL24(AES.ftable[Int((p[0]>>24)&0xff)])
+            
+            q[2]=fkey[k+2]^AES.ftable[Int(p[2]&0xff)]^AES.ROTL8(AES.ftable[Int((p[3]>>8)&0xff)])^AES.ROTL16(AES.ftable[Int((p[0]>>16)&0xff)])^AES.ROTL24(AES.ftable[Int((p[1]>>24)&0xff)])
+            
+            q[3]=fkey[k+3]^AES.ftable[Int(p[3]&0xff)]^AES.ROTL8(AES.ftable[Int((p[0]>>8)&0xff)])^AES.ROTL16(AES.ftable[Int((p[1]>>16)&0xff)])^AES.ROTL24(AES.ftable[Int((p[2]>>24)&0xff)])
+            
+            k+=4;
+            for j in 0 ..< 4
+            {
+				let t=p[j]; p[j]=q[j]; q[j]=t;
+            }
+        }
+    
+    /* Last Round */
+    
+        q[0]=fkey[k]^UInt32(AES.fbsub[Int(p[0]&0xff)])^AES.ROTL8(UInt32(AES.fbsub[Int((p[1]>>8)&0xff)]))^AES.ROTL16(UInt32(AES.fbsub[Int((p[2]>>16)&0xff)]))^AES.ROTL24(UInt32(AES.fbsub[Int((p[3]>>24)&0xff)]))
+    
+        q[1]=fkey[k+1]^UInt32(AES.fbsub[Int(p[1]&0xff)])^AES.ROTL8(UInt32(AES.fbsub[Int((p[2]>>8)&0xff)]))^AES.ROTL16(UInt32(AES.fbsub[Int((p[3]>>16)&0xff)]))^AES.ROTL24(UInt32(AES.fbsub[Int((p[0]>>24)&0xff)]))
+    
+        q[2]=fkey[k+2]^UInt32(AES.fbsub[Int(p[2]&0xff)])^AES.ROTL8(UInt32(AES.fbsub[Int((p[3]>>8)&0xff)]))^AES.ROTL16(UInt32(AES.fbsub[Int((p[0]>>16)&0xff)]))^AES.ROTL24(UInt32(AES.fbsub[Int((p[1]>>24)&0xff)]))
+    
+        q[3]=fkey[k+3]^UInt32(AES.fbsub[Int((p[3])&0xff)])^AES.ROTL8(UInt32(AES.fbsub[Int((p[0]>>8)&0xff)]))^AES.ROTL16(UInt32(AES.fbsub[Int((p[1]>>16)&0xff)]))^AES.ROTL24(UInt32(AES.fbsub[Int((p[2]>>24)&0xff)]))
+    
+        j=0
+        for i in 0 ..< 4
+        {
+            b=AES.unpack(q[i])
+            for k in 0 ..< 4 {buff[j+k]=b[k]}
+            j+=4
+        }
+    }
+    
+    /* Decrypt a single block */
+    func ecb_decrypt(_ buff:inout [UInt8])
+    {
+        var b=[UInt8](repeating: 0,count: 4)
+        var p=[UInt32](repeating: 0,count: 4)
+        var q=[UInt32](repeating: 0,count: 4)
+    
+        var j=0
+        for i in 0 ..< 4
+        {
+            for k in 0 ..< 4 {b[k]=buff[j+k]}
+            p[i]=AES.pack(b);
+            p[i]^=rkey[i];
+            j+=4
+        }
+    
+        var k=4
+    
+    /* State alternates between p and q */
+        for _ in 1 ..< 10
+        {
+            
+            q[0]=rkey[k]^AES.rtable[Int(p[0]&0xff)]^AES.ROTL8(AES.rtable[Int((p[3]>>8)&0xff)])^AES.ROTL16(AES.rtable[Int((p[2]>>16)&0xff)])^AES.ROTL24(AES.rtable[Int((p[1]>>24)&0xff)])
+            
+            q[1]=rkey[k+1]^AES.rtable[Int(p[1]&0xff)]^AES.ROTL8(AES.rtable[Int((p[0]>>8)&0xff)])^AES.ROTL16(AES.rtable[Int((p[3]>>16)&0xff)])^AES.ROTL24(AES.rtable[Int((p[2]>>24)&0xff)])
+            
+        
+            q[2]=rkey[k+2]^AES.rtable[Int(p[2]&0xff)]^AES.ROTL8(AES.rtable[Int((p[1]>>8)&0xff)])^AES.ROTL16(AES.rtable[Int((p[0]>>16)&0xff)])^AES.ROTL24(AES.rtable[Int((p[3]>>24)&0xff)])
+       
+            q[3]=rkey[k+3]^AES.rtable[Int(p[3]&0xff)]^AES.ROTL8(AES.rtable[Int((p[2]>>8)&0xff)])^AES.ROTL16(AES.rtable[Int((p[1]>>16)&0xff)])^AES.ROTL24(AES.rtable[Int((p[0]>>24)&0xff)])
+            
+    
+            k+=4;
+            for j in 0 ..< 4
+            {
+				let t=p[j]; p[j]=q[j]; q[j]=t;
+            }
+        }
+    
+    /* Last Round */
+        
+        q[0]=rkey[k]^UInt32(AES.rbsub[Int(p[0]&0xff)])^AES.ROTL8(UInt32(AES.rbsub[Int((p[3]>>8)&0xff)]))^AES.ROTL16(UInt32(AES.rbsub[Int((p[2]>>16)&0xff)]))^AES.ROTL24(UInt32(AES.rbsub[Int((p[1]>>24)&0xff)]))
+        
+        q[1]=rkey[k+1]^UInt32(AES.rbsub[Int(p[1]&0xff)])^AES.ROTL8(UInt32(AES.rbsub[Int((p[0]>>8)&0xff)]))^AES.ROTL16(UInt32(AES.rbsub[Int((p[3]>>16)&0xff)]))^AES.ROTL24(UInt32(AES.rbsub[Int((p[2]>>24)&0xff)]))
+        
+        
+        q[2]=rkey[k+2]^UInt32(AES.rbsub[Int(p[2]&0xff)])^AES.ROTL8(UInt32(AES.rbsub[Int((p[1]>>8)&0xff)]))^AES.ROTL16(UInt32(AES.rbsub[Int((p[0]>>16)&0xff)]))^AES.ROTL24(UInt32(AES.rbsub[Int((p[3]>>24)&0xff)]))
+
+        q[3]=rkey[k+3]^UInt32(AES.rbsub[Int((p[3])&0xff)])^AES.ROTL8(UInt32(AES.rbsub[Int((p[2]>>8)&0xff)]))^AES.ROTL16(UInt32(AES.rbsub[Int((p[1]>>16)&0xff)]))^AES.ROTL24(UInt32(AES.rbsub[Int((p[0]>>24)&0xff)]))
+    
+        j=0
+        for i in 0 ..< 4
+        {
+            b=AES.unpack(q[i]);
+            for k in 0 ..< 4 {buff[j+k]=b[k]}
+            j+=4
+        }
+    }
+    
+    /* Encrypt using selected mode of operation */
+    func encrypt(_ buff:inout [UInt8]) -> UInt32
+    {
+        var st=[UInt8](repeating: 0,count: 16)
+    
+    // Supported Modes of Operation
+    
+        var fell_off:UInt32=0;
+        switch (mode)
+        {
+        case AES.ECB:
+            ecb_encrypt(&buff)
+            return 0
+        case AES.CBC:
+            for j in 0 ..< 16 {buff[j]^=f[j]}
+            ecb_encrypt(&buff);
+            for j in 0 ..< 16 {f[j]=buff[j]}
+            return 0;
+    
+        case AES.CFB1:
+            fallthrough
+        case AES.CFB2:
+            fallthrough
+        case AES.CFB4:
+            let bytes=mode-AES.CFB1+1
+            for j in 0 ..< bytes {fell_off=(fell_off<<8)|UInt32(f[j])}
+            for j in 0 ..< 16 {st[j]=f[j]}
+            for j in bytes ..< 16 {f[j-bytes]=f[j]}
+            ecb_encrypt(&st);
+            for j in 0 ..< bytes
+            {
+				buff[j]^=st[j];
+				f[16-bytes+j]=buff[j];
+            }
+            return fell_off;
+    
+        case AES.OFB1:
+            fallthrough
+        case AES.OFB2:
+            fallthrough
+        case AES.OFB4:
+            fallthrough
+        case AES.OFB8:
+            fallthrough
+        case AES.OFB16:
+    
+            let bytes=mode-AES.OFB1+1
+            ecb_encrypt(&f)
+            for j in 0 ..< bytes {buff[j]^=f[j]}
+            return 0;
+    
+        case AES.CTR1:
+            fallthrough
+        case AES.CTR2:
+            fallthrough
+        case AES.CTR4:
+            fallthrough
+        case AES.CTR8:
+            fallthrough
+        case AES.CTR16:
+            let bytes=mode-AES.CTR1+1
+            for j in 0 ..< 16 {st[j]=f[j]}
+            ecb_encrypt(&st)
+            for j in 0 ..< bytes {buff[j]^=st[j]}
+            AES.increment(&f)
+            return 0
+
+        default:
+            return 0;
+        }
+    }
+    
+    /* Decrypt using selected mode of operation */
+    func decrypt(_ buff:inout [UInt8]) -> UInt32
+    {
+
+        var st=[UInt8](repeating: 0,count: 16)
+        
+        // Supported Modes of Operation
+        
+        var fell_off:UInt32=0;
+        switch (mode)
+        {
+        case AES.ECB:
+            ecb_decrypt(&buff);
+            return 0;
+        case AES.CBC:
+            for j in 0 ..< 16
+            {
+				st[j]=f[j];
+				f[j]=buff[j];
+            }
+            ecb_decrypt(&buff);
+            for j in 0 ..< 16
+            {
+				buff[j]^=st[j];
+				st[j]=0;
+            }
+            return 0;
+        case AES.CFB1:
+            fallthrough
+        case AES.CFB2:
+            fallthrough
+        case AES.CFB4:
+            let bytes=mode-AES.CFB1+1;
+            for j in 0 ..< bytes {fell_off=(fell_off<<8)|UInt32(f[j])}
+            for j in 0 ..< 16 {st[j]=f[j]}
+            for j in bytes ..< 16 {f[j-bytes]=f[j]}
+            ecb_encrypt(&st);
+            for j in 0 ..< bytes
+            {
+				f[16-bytes+j]=buff[j]
+				buff[j]^=st[j]
+            }
+            return fell_off
+        case AES.OFB1:
+            fallthrough
+        case AES.OFB2:
+            fallthrough
+        case AES.OFB4:
+            fallthrough
+        case AES.OFB8:
+            fallthrough
+        case AES.OFB16:
+            let bytes=mode-AES.OFB1+1
+            ecb_encrypt(&f);
+            for j in 0 ..< bytes {buff[j]^=f[j]}
+            return 0;
+
+        case AES.CTR1:
+            fallthrough
+        case AES.CTR2:
+            fallthrough
+        case AES.CTR4:
+            fallthrough
+        case AES.CTR8:
+            fallthrough
+        case AES.CTR16:
+            let bytes=mode-AES.CTR1+1
+            for j in 0 ..< 16 {st[j]=f[j]}
+            ecb_encrypt(&st)
+            for j in 0 ..< bytes {buff[j]^=st[j]}
+            AES.increment(&f)
+            return 0
+
+        default:
+            return 0;
+        }
+    }
+        
+    /* Clean up and delete left-overs */
+    func end()
+    { // clean up
+        for i in 0 ..< 44
+            {fkey[i]=0; rkey[i]=0}
+        for i in 0 ..< 16
+            {f[i]=0}
+    }
+    
+}
diff --git a/version22/swift/big.swift b/version22/swift/big.swift
new file mode 100644
index 0000000..11fe17a
--- /dev/null
+++ b/version22/swift/big.swift
@@ -0,0 +1,1169 @@
+/*
+	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.
+*/
+
+//
+//  big.swift
+//
+//  Created by Michael Scott on 12/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//  BIG number class
+//
+
+final class BIG{
+    var w=[Chunk](repeating: 0,count: ROM.NLEN)
+/* Constructors */
+    init() {
+        for i in 0 ..< ROM.NLEN {w[i]=0}
+    }
+    init(_ x: Int)
+    {
+        w[0]=Chunk(x);
+        for i in 1 ..< ROM.NLEN {w[i]=0}
+    }
+    init(_ x: BIG)
+    {
+        for i in 0 ..< ROM.NLEN {w[i]=x.w[i]}
+    }
+    init(_ x: DBIG)
+    {
+        for i in 0 ..< ROM.NLEN {w[i]=x.w[i]}
+    }
+    init(_ x: [Chunk])
+    {
+        for i in 0 ..< ROM.NLEN {w[i]=x[i]}
+    }
+    func get(_ i: Int) -> Chunk
+    {
+        return w[i]
+    }
+    func set(_ i: Int,_ x: Chunk)
+    {
+        w[i]=x
+    }
+    func xortop(_ x: Chunk)
+    {
+        w[ROM.NLEN-1]^=x
+    }
+    func ortop(_ x: Chunk)
+    {
+        w[ROM.NLEN-1]|=x
+    }
+/* calculate Field Excess */
+    static func EXCESS(_ a: BIG) -> Chunk
+    {
+        return ((a.w[ROM.NLEN-1] & ROM.OMASK)>>Chunk(ROM.MODBITS%ROM.BASEBITS))
+    }
+    static func FF_EXCESS(_ a: BIG) -> Chunk
+    {
+        return ((a.w[ROM.NLEN-1] & ROM.P_OMASK)>>Chunk(ROM.P_MBITS%ROM.BASEBITS))
+    }
+#if D32
+    static func pexceed(_ a: BIG,_ b : BIG) -> Bool
+    {
+        let ea=BIG.EXCESS(a)
+        let eb=BIG.EXCESS(b)
+        if (DChunk(ea)+1)*(DChunk(eb)+1) > DChunk(ROM.FEXCESS) {return true}
+        return false;
+    }
+    static func sexceed(_ a: BIG) -> Bool
+    {
+        let ea=BIG.EXCESS(a)
+        if (DChunk(ea)+1)*(DChunk(ea)+1) > DChunk(ROM.FEXCESS) {return true}
+        return false;
+    }
+
+    static func ff_pexceed(_ a: BIG,_ b : BIG) -> Bool
+    {
+        let ea=BIG.FF_EXCESS(a)
+        let eb=BIG.FF_EXCESS(b)
+        if (DChunk(ea)+1)*(DChunk(eb)+1) > DChunk(ROM.P_FEXCESS) {return true}
+        return false;
+    }
+    static func ff_sexceed(_ a: BIG) -> Bool
+    {
+        let ea=BIG.FF_EXCESS(a)
+        if (DChunk(ea)+1)*(DChunk(ea)+1) > DChunk(ROM.P_FEXCESS) {return true}
+        return false;
+    }
+    static func muladd(_ a: Chunk,_ b: Chunk,_ c: Chunk,_ r: Chunk) -> (Chunk,Chunk)
+    {
+        let prod:DChunk = DChunk(a)*DChunk(b)+DChunk(c)+DChunk(r)
+        let bot=Chunk(prod&DChunk(ROM.BMASK))
+        let top=Chunk(prod>>DChunk(ROM.BASEBITS))
+        return (top,bot)
+    }
+#endif
+#if D64
+
+    static func pexceed(_ a: BIG,_ b : BIG) -> Bool
+    {
+        let ea=BIG.EXCESS(a)
+        let eb=BIG.EXCESS(b)
+        if (ea+1) > ROM.FEXCESS/(eb+1) {return true}
+        return false;
+    }
+    static func sexceed(_ a: BIG) -> Bool
+    {
+        let ea=BIG.EXCESS(a)
+        if (ea+1) > ROM.FEXCESS/(ea+1) {return true}
+        return false;
+    }
+    
+    static func ff_pexceed(_ a: BIG,_ b : BIG) -> Bool
+    {
+        let ea=BIG.FF_EXCESS(a)
+        let eb=BIG.FF_EXCESS(b)
+        if (ea+1) > ROM.P_FEXCESS/(eb+1) {return true}
+        return false;
+    }
+    static func ff_sexceed(_ a: BIG) -> Bool
+    {
+        let ea=BIG.FF_EXCESS(a)
+        if (ea+1) > ROM.P_FEXCESS/(ea+1) {return true}
+        return false;
+    }
+    
+    static func muladd(_ a: Chunk,_ b: Chunk,_ c: Chunk,_ r: Chunk) -> (Chunk,Chunk)
+    {
+        let x0=a&ROM.HMASK;
+        let x1=(a>>Chunk(ROM.HBITS))
+        let y0=b&ROM.HMASK;
+        let y1=(b>>Chunk(ROM.HBITS))
+        var bot=x0*y0
+        var top=x1*y1
+        let mid=x0*y1+x1*y0
+        let u0=mid&ROM.HMASK
+        let u1=(mid>>Chunk(ROM.HBITS))
+        bot=bot+(u0<<Chunk(ROM.HBITS))
+        bot+=c; bot+=r
+        top+=u1
+        let carry=bot>>Chunk(ROM.BASEBITS)
+        bot &= ROM.BMASK
+        top+=carry
+        return (top,bot)
+    }
+    
+#endif
+    /* test for zero */
+    func iszilch() -> Bool
+    {
+        for i in 0 ..< ROM.NLEN {if w[i] != 0 {return false}}
+        return true
+    }
+/* set to zero */
+    func zero()
+    {
+        for i in 0 ..< ROM.NLEN {w[i] = 0}
+    }
+/* set to one */
+    func one()
+    {
+        w[0]=1
+        for i in 1 ..< ROM.NLEN {w[i]=0}
+    }
+/* Test for equal to one */
+    func isunity() -> Bool
+    {
+        for i in 1 ..< ROM.NLEN {if w[i] != 0 {return false}}
+        if w[0] != 1 {return false}
+        return true
+    }
+/* Copy from another BIG */
+    func copy(_ x: BIG)
+    {
+        for i in 0 ..< ROM.NLEN {w[i] = x.w[i]}
+    }
+    func copy(_ x: DBIG)
+    {
+        for i in 0 ..< ROM.NLEN {w[i] = x.w[i]}
+    }
+/* Conditional swap of two bigs depending on d using XOR - no branches */
+    func cswap(_ b: BIG,_ d: Int)
+    {
+        var c = Chunk(d)
+        c = ~(c-1)
+        for i in 0 ..< ROM.NLEN
+        {
+            let t=c&(w[i]^b.w[i])
+            w[i]^=t
+            b.w[i]^=t
+        }
+    }
+    func cmove(_ g: BIG,_ d: Int)
+    {
+        let b=Chunk(-d)
+        for i in 0 ..< ROM.NLEN
+        {
+            w[i]^=(w[i]^g.w[i])&b;
+        }
+    }
+/* normalise BIG - force all digits < 2^BASEBITS */
+    func norm() -> Chunk
+    {
+        var carry=Chunk(0);
+        for i in 0 ..< ROM.NLEN-1
+        {
+            let d=w[i]+carry
+            w[i]=d&ROM.BMASK
+            carry=d>>Chunk(ROM.BASEBITS)
+        }
+        w[ROM.NLEN-1]+=carry
+        return (w[ROM.NLEN-1]>>Chunk((8*ROM.MODBYTES)%ROM.BASEBITS))
+    }
+/* Shift right by less than a word */
+    func fshr(_ k: UInt) -> Int
+    {
+        let kw=Chunk(k);
+        let r=w[0]&((Chunk(1)<<kw)-1)
+        for i in 0 ..< ROM.NLEN-1
+        {
+            w[i]=(w[i]>>kw)|((w[i+1]<<(Chunk(ROM.BASEBITS)-kw))&ROM.BMASK)
+        }
+        w[ROM.NLEN-1]>>=kw;
+        return Int(r)
+    }
+/* general shift right */
+    func shr(_ k: UInt)
+    {
+        let n=k%ROM.BASEBITS
+        let m=Int(k/ROM.BASEBITS)
+        for i in 0 ..< ROM.NLEN-m-1
+        {
+            w[i]=(w[m+i]>>Chunk(n))|((w[m+i+1]<<Chunk(ROM.BASEBITS-n))&ROM.BMASK)
+        }
+        w[ROM.NLEN - m - 1]=w[ROM.NLEN-1]>>Chunk(n)
+        for i in ROM.NLEN - m ..< ROM.NLEN {w[i]=0}
+    }
+/* Shift right by less than a word */
+    func fshl(_ k: Int) -> Int
+    {
+        let kw=Chunk(k)
+        w[ROM.NLEN-1]=((w[ROM.NLEN-1]<<kw))|(w[ROM.NLEN-2]>>(Chunk(ROM.BASEBITS)-kw))
+        for i in (1...ROM.NLEN-2).reversed()
+        {
+            w[i]=((w[i]<<kw)&ROM.BMASK)|(w[i-1]>>(Chunk(ROM.BASEBITS)-kw))
+        }
+        w[0]=(w[0]<<kw)&ROM.BMASK
+        return Int(w[ROM.NLEN-1]>>Chunk((8*ROM.MODBYTES)%ROM.BASEBITS))
+    }
+/* general shift left */
+    func shl(_ k: UInt)
+    {
+        let n=k%ROM.BASEBITS
+        let m=Int(k/ROM.BASEBITS)
+        
+        w[ROM.NLEN-1]=(w[ROM.NLEN-1-m]<<Chunk(n))
+        if ROM.NLEN>=m+2 {w[ROM.NLEN-1]|=(w[ROM.NLEN-m-2]>>Chunk(ROM.BASEBITS-n))}
+        for i in (m+1...ROM.NLEN-2).reversed()
+        {
+            w[i]=((w[i-m]<<Chunk(n))&ROM.BMASK)|(w[i-m-1]>>Chunk(ROM.BASEBITS-n))
+        }
+        w[m]=(w[0]<<Chunk(n))&ROM.BMASK
+        for i in 0 ..< m {w[i]=0}
+    }
+/* return number of bits */
+    func nbits() -> Int
+    {
+        var k=(ROM.NLEN-1)
+        norm()
+        while k>=0 && w[k]==0 {k -= 1}
+        if k<0 {return 0}
+        var bts=Int(ROM.BASEBITS)*k
+        var c=w[k];
+        while c != 0 {c/=2; bts += 1}
+        return bts
+    }
+    func toRawString() -> String
+    {
+        var s:String="("
+        for i in 0 ..< ROM.NLEN-1
+        {
+            let n=String(w[i],radix:16,uppercase:false)
+            s+=n
+            s+=","
+            
+        }
+        let n=String(w[ROM.NLEN-1],radix:16,uppercase:false)
+        s+=n
+        s+=")"
+        return s
+    }
+/* Convert to Hex String */
+    func toString() -> String
+    {
+        _ = BIG()
+        var s:String=""
+        var len=nbits()
+        if len%4 == 0 {len/=4}
+        else {len/=4; len += 1}
+        if len<2*Int(ROM.MODBYTES) {len=2*Int(ROM.MODBYTES)}
+
+        for i in (0...len-1).reversed()
+        {
+            let b = BIG(self)
+            b.shr(UInt(i*4))
+            let n=String(b.w[0]&15,radix:16,uppercase:false)
+            s+=n
+        }
+        
+        return s
+    }
+/* return this+x */
+    func plus(_ x: BIG) -> BIG
+    {
+        let s=BIG()
+        for i in 0 ..< ROM.NLEN
+        {
+            s.w[i]=w[i]+x.w[i]
+        }
+        return s
+    }
+/* this+=x */
+    func add(_ x: BIG)
+    {
+        for i in 0 ..< ROM.NLEN
+        {
+            w[i]+=x.w[i]
+        }
+    }
+/* this+=x, where x is int */
+    func inc(_ x: Int) {
+        norm();
+        w[0]+=Chunk(x);
+    }
+/* return this.x */
+   	func minus(_ x: BIG) -> BIG
+    {
+        let d=BIG();
+        for i in 0 ..< ROM.NLEN
+        {
+            d.w[i]=w[i]-x.w[i];
+        }
+        return d;
+    }
+/* this-=x */
+    func sub(_ x: BIG)
+    {
+        for i in 0 ..< ROM.NLEN
+        {
+            w[i]-=x.w[i]
+        }
+    }
+/* reverse subtract this=x-this */
+    func rsub(_ x: BIG)
+    {
+        for i in 0 ..< ROM.NLEN
+        {
+            w[i]=x.w[i]-w[i]
+        }
+    }
+/* this-=x where x is int */
+    func dec(_ x: Int) {
+        norm();
+        w[0]-=Chunk(x);
+    }
+/* this*=x, where x is small int<NEXCESS */
+    func imul(_ c: Int)
+    {
+        for i in 0 ..< ROM.NLEN {w[i]*=Chunk(c)}
+    }
+/* convert this BIG to byte array */
+    func tobytearray(_ b: inout [UInt8],_ n: Int)
+    {
+        norm();
+        let c=BIG(self);
+        for i in (0...Int(ROM.MODBYTES)-1).reversed()
+        {
+            b[i+n]=UInt8(c.w[0]&0xff);
+            c.fshr(8);
+        }
+    }
+/* convert from byte array to BIG */
+    static func frombytearray(_ b: [UInt8],_ n: Int) -> BIG
+    {
+        let m=BIG();
+    
+        for i in 0 ..< Int(ROM.MODBYTES)
+        {
+            m.fshl(8)
+            m.w[0]+=Chunk(b[i+n])&0xff    //(int)b[i+n]&0xff;
+        }
+        return m;
+    }
+    func toBytes(_ b: inout [UInt8])
+    {
+        tobytearray(&b,0)
+    }
+    static func fromBytes(_ b: [UInt8]) -> BIG
+    {
+        return frombytearray(b,0)
+    }
+/* set this[i]+=x*y+c, and return high part
+    func muladd(_ x: Int32,_ y: Int32,_ c: Int32,_ i: Int) -> Int32
+    {
+        let prod:DChunk = DChunk(x)*DChunk(y)+DChunk(c)+DChunk(w[i])
+        w[i]=Int32(prod&DChunk(ROM.BMASK))
+        return Int32(prod>>DChunk(ROM.BASEBITS))
+    } */
+
+/* this*=x, where x is >NEXCESS */
+    func pmul(_ c: Int) -> Chunk
+    {
+        var carry=Chunk(0);
+        norm();
+        for i in 0 ..< ROM.NLEN
+        {
+            let ak=w[i]
+            let (top,bot)=BIG.muladd(ak,Chunk(c),carry,Chunk(0))
+            carry=top; w[i]=bot;
+            //carry=muladd(ak,Chunk(c),carry,i);
+            
+        }
+        return carry;
+    }
+/* this*=c and catch overflow in DBIG */
+    func pxmul(_ c: Int) -> DBIG
+    {
+        let m=DBIG()
+        var carry=Chunk(0)
+        for j in 0 ..< ROM.NLEN
+        {
+            let (top,bot)=BIG.muladd(w[j],Chunk(c),carry,m.w[j])
+            carry=top; m.w[j]=bot
+  //          carry=m.muladd(w[j],c,carry,j)
+        }
+        m.w[ROM.NLEN]=carry
+        return m;
+    }
+/* divide by 3 */
+    func div3() -> Chunk
+    {
+        var carry=Chunk(0)
+        norm();
+        let base=Chunk(1<<ROM.BASEBITS);
+        for i in (0...ROM.NLEN-1).reversed()
+        {
+            let ak=(carry*base+w[i]);
+            w[i]=ak/3;
+            carry=ak%3;
+        }
+        return carry;
+    }
+/* return a*b where result fits in a BIG */
+    static func smul(_ a: BIG,_ b: BIG) -> BIG
+    {
+        let c=BIG()
+        for i in 0 ..< ROM.NLEN
+        {
+            var carry=Chunk(0)
+            for j in 0 ..< ROM.NLEN
+            {
+                if (i+j<ROM.NLEN) {
+                    let (top,bot)=BIG.muladd(a.w[i],b.w[j],carry,c.w[i+j])
+                    carry=top; c.w[i+j]=bot
+                    //carry=c.muladd(a.w[i],b.w[j],carry,i+j)
+                }
+            }
+        }
+        return c;
+    }
+/* Compare a and b, return 0 if a==b, -1 if a<b, +1 if a>b. Inputs must be normalised */
+    static func comp(_ a: BIG,_ b: BIG) -> Int
+    {
+        for i in (0...ROM.NLEN-1).reversed()
+        {
+            if (a.w[i]==b.w[i]) {continue}
+            if (a.w[i]>b.w[i]) {return 1}
+            else  {return -1}
+        }
+        return 0;
+    }
+/* set x = x mod 2^m */
+    func mod2m(_ m: UInt)
+    {
+        let wd=Int(m/ROM.BASEBITS)
+        let bt=m%ROM.BASEBITS
+        let msk=Chunk(1<<bt)-1;
+        w[wd]&=msk;
+        for i in wd+1 ..< ROM.NLEN {w[i]=0}
+    }
+/* Arazi and Qi inversion mod 256 */
+    static func invmod256(_ a: Int) -> Int
+    {
+        var t1:Int=0
+        var c=(a>>1)&1
+        t1+=c
+        t1&=1
+        t1=2-t1
+        t1<<=1
+        var U=t1+1
+    
+    // i=2
+        var b=a&3
+        t1=U*b; t1>>=2
+        c=(a>>2)&3
+        var t2=(U*c)&3
+        t1+=t2
+        t1*=U; t1&=3
+        t1=4-t1
+        t1<<=2
+        U+=t1
+    
+    // i=4
+        b=a&15
+        t1=U*b; t1>>=4
+        c=(a>>4)&15
+        t2=(U*c)&15
+        t1+=t2
+        t1*=U; t1&=15
+        t1=16-t1
+        t1<<=4
+        U+=t1
+    
+        return U
+    }
+/* return parity */
+    func parity() -> Int
+    {
+        return Int(w[0]%2)
+    }
+    
+/* return n-th bit */
+    func bit(_ n: UInt) -> Int
+    {
+        if ((w[Int(n/ROM.BASEBITS)]&(1<<Chunk(n%ROM.BASEBITS)))>0) {return 1;}
+        else {return 0;}
+    }
+    
+    /* return n last bits */
+    func lastbits(_ n: UInt) -> Int
+    {
+        let msk=(1<<Chunk(n))-1;
+        norm();
+        return Int((w[0])&msk)
+    }
+/* a=1/a mod 2^256. This is very fast! */
+    func invmod2m()
+    {
+        let U=BIG()
+        var b=BIG()
+        let c=BIG()
+    
+        U.inc(BIG.invmod256(lastbits(8)))
+    
+        var i=UInt(8)
+        while (i<ROM.BIGBITS)
+        {
+            b.copy(self)
+            b.mod2m(i)
+            let t1=BIG.smul(U,b)
+            t1.shr(i)
+            c.copy(self)
+            c.shr(i)
+            c.mod2m(i)
+    
+            let t2=BIG.smul(U,c)
+            t2.mod2m(i)
+            t1.add(t2)
+            b=BIG.smul(t1,U)
+            t1.copy(b)
+            t1.mod2m(i)
+    
+            t2.one(); t2.shl(i); t1.rsub(t2); t1.norm()
+            t1.shl(i)
+            U.add(t1)
+            i<<=1
+        }
+        U.mod2m(ROM.BIGBITS)
+        self.copy(U)
+        self.norm()
+    }
+    /* reduce this mod m */
+    func mod(_ m: BIG)
+    {
+        var k=0
+        let r=BIG(0)
+        norm()
+        if (BIG.comp(self,m)<0) {return}
+        repeat
+        {
+            m.fshl(1)
+            k += 1
+        } while (BIG.comp(self,m)>=0)
+    
+        while (k>0)
+        {
+            m.fshr(1)
+
+		r.copy(self)
+		r.sub(m)
+		r.norm()
+		cmove(r,Int(1-((r.w[ROM.NLEN-1]>>Chunk(ROM.CHUNK-1))&1)))
+/*
+            if (BIG.comp(self,m)>=0)
+            {
+				sub(m)
+				norm()
+            } */
+            k -= 1
+        }
+    }
+    /* divide this by m */
+    func div(_ m: BIG)
+    {
+        var k=0
+        norm()
+        let e=BIG(1)
+        let b=BIG(self)
+        let r=BIG(0)
+        zero()
+    
+        while (BIG.comp(b,m)>=0)
+        {
+            e.fshl(1)
+            m.fshl(1)
+            k += 1
+        }
+    
+        while (k>0)
+        {
+            m.fshr(1)
+            e.fshr(1)
+
+		r.copy(b)
+		r.sub(m)
+		r.norm()
+		let d=Int(1-((r.w[ROM.NLEN-1]>>Chunk(ROM.CHUNK-1))&1))
+		b.cmove(r,d)
+		r.copy(self)
+		r.add(e)
+		r.norm()
+		cmove(r,d)
+/*
+            if (BIG.comp(b,m)>=0)
+            {
+				add(e)
+				norm()
+				b.sub(m)
+				b.norm()
+            } */
+            k -= 1;
+        }
+    }
+    /* get 8*MODBYTES size random number */
+    static func random(_ rng: RAND) -> BIG
+    {
+        let m=BIG();
+        var j:Int=0
+        var r:UInt8=0
+        /* generate random BIG */
+        for _ in 0 ..< Int(8*ROM.MODBYTES)
+        {
+            if (j==0) {r=rng.getByte()}
+            else {r>>=1}
+    
+            let b=Chunk(r&1);
+            m.shl(1); m.w[0]+=b;// m.inc(b);
+            j += 1; j&=7;
+        }
+        return m;
+    }
+    
+    /* Create random BIG in portable way, one bit at a time, less than q */
+    static func randomnum(_ q: BIG,_ rng: RAND) -> BIG
+    {
+        let d=DBIG(0);
+        var j:Int=0
+        var r:UInt8=0
+        
+        for _ in 0 ..< Int(2*ROM.MODBITS)
+        {
+            if (j==0) {r=rng.getByte()}
+            else {r>>=1}
+    
+            let b=Chunk(r&1);
+            d.shl(1); d.w[0]+=b; // m.inc(b);
+            j += 1; j&=7;
+        }
+        let m=d.mod(q);
+        return m;
+    }
+    
+    /* return NAF value as +/- 1, 3 or 5. x and x3 should be normed.
+    nbs is number of bits processed, and nzs is number of trailing 0s detected
+    static func nafbits(_ x: BIG,_ x3:BIG ,i:Int) -> [Chunk]
+    {
+        var j:Int
+        var n=[Chunk](repeating: 0,count: 3)
+        var nb=x3.bit(UInt(i))-x.bit(UInt(i))
+        n[1]=1;
+        n[0]=0;
+        if (nb==0) {n[0]=0; return n}
+        if (i==0) {n[0]=Chunk(nb); return n}
+        if (nb>0) {n[0]=1}
+        else      {n[0]=(-1)}
+    
+        j=i-1
+        while (true)
+        {
+            n[1] += 1
+            n[0]*=2
+            nb=x3.bit(UInt(j))-x.bit(UInt(j))
+            if (nb>0) {n[0]+=1}
+            if (nb<0) {n[0]-=1}
+            if (n[0]>5 || n[0] < -5) {break}
+            j-=1
+            if j==0 {break}
+        }
+    
+        if ((n[0]%2 != 0) && (j != 0))
+        { /* backtrack */
+            if (nb>0) {n[0]=(n[0]-1)/2}
+            if (nb<0) {n[0]=(n[0]+1)/2}
+            n[1] -= 1;
+        }
+        while (n[0]%2==0)
+        { /* remove trailing zeros */
+            n[0]/=2
+            n[2] += 1
+            n[1] -= 1
+        }
+        return n;
+    } */
+    
+    /* Jacobi Symbol (this/p). Returns 0, 1 or -1 */
+    func jacobi(_ p: BIG) -> Int
+    {
+        var n8:Int
+        var k:Int
+        var m:Int=0;
+        let t=BIG()
+        let x=BIG()
+        let n=BIG()
+        let zilch=BIG()
+        let one=BIG(1)
+        if (p.parity()==0 || BIG.comp(self,zilch)==0 || BIG.comp(p,one)<=0) {return 0}
+        norm()
+        x.copy(self)
+        n.copy(p)
+        x.mod(p)
+    
+        while (BIG.comp(n,one)>0)
+        {
+            if (BIG.comp(x,zilch)==0) {return 0}
+            n8=n.lastbits(3)
+            k=0
+            while (x.parity()==0)
+            {
+				k += 1
+				x.shr(1)
+            }
+            if (k%2==1) {m+=((n8*n8-1)/8)}
+            let w=Int(x.lastbits(2)-1)
+            m+=(n8-1)*w/4
+            t.copy(n)
+            t.mod(x)
+            n.copy(x)
+            x.copy(t)
+            m%=2
+    
+        }
+        if (m==0) {return 1}
+        else {return -1}
+    }
+    /* this=1/this mod p. Binary method */
+    func invmodp(_ p: BIG)
+    {
+        mod(p)
+        let u=BIG(self)
+        let v=BIG(p)
+        let x1=BIG(1)
+        let x2=BIG()
+        let t=BIG()
+        let one=BIG(1)
+    
+        while ((BIG.comp(u,one) != 0 ) && (BIG.comp(v,one) != 0 ))
+        {
+            while (u.parity()==0)
+            {
+				u.shr(1);
+				if (x1.parity() != 0 )
+				{
+                    x1.add(p);
+                    x1.norm();
+				}
+				x1.shr(1);
+            }
+            while (v.parity()==0)
+            {
+				v.shr(1);
+				if (x2.parity() != 0 )
+				{
+                    x2.add(p);
+                    x2.norm();
+				}
+				x2.shr(1);
+            }
+            if (BIG.comp(u,v)>=0)
+            {
+				u.sub(v);
+				u.norm();
+                if (BIG.comp(x1,x2)>=0) {x1.sub(x2)}
+				else
+				{
+                    t.copy(p);
+                    t.sub(x2);
+                    x1.add(t);
+				}
+				x1.norm();
+            }
+            else
+            {
+				v.sub(u);
+				v.norm();
+                if (BIG.comp(x2,x1)>=0) {x2.sub(x1)}
+				else
+				{
+                    t.copy(p);
+                    t.sub(x1);
+                    x2.add(t);
+				}
+				x2.norm();
+            }
+        }
+        if (BIG.comp(u,one)==0) {copy(x1)}
+        else {copy(x2)}
+    }
+    /* return a*b as DBIG */
+#if D32
+    static func mul(_ a: BIG,_ b:BIG) -> DBIG
+    {
+        var t:DChunk
+        var co:DChunk
+        let c=DBIG()
+        let RM:DChunk=DChunk(ROM.BMASK);
+        let RB:DChunk=DChunk(ROM.BASEBITS)
+   //     a.norm();
+   //     b.norm();
+        
+        var d=[DChunk](repeating: 0,count: ROM.NLEN)
+        var s:DChunk
+        for i in 0 ..< ROM.NLEN
+        {
+            d[i]=DChunk(a.w[i])*DChunk(b.w[i]);
+        }
+        s=d[0]
+        t=s; c.w[0]=Chunk(t&RM); co=t>>RB
+        for k in 1 ..< ROM.NLEN
+        {
+            s+=d[k]; t=co+s;
+            for i in 1+k/2...k
+                {t+=DChunk(a.w[i]-a.w[k-i])*DChunk(b.w[k-i]-b.w[i])}
+            c.w[k]=Chunk(t&RM); co=t>>RB
+        }
+        for k in ROM.NLEN ..< 2*ROM.NLEN-1
+        {
+            s-=d[k-ROM.NLEN]; t=co+s;
+  
+            //for var i=ROM.NLEN-1;i>=1+k/2;i--
+            var i=1+k/2
+            while i<ROM.NLEN
+            //for i in 1+k/2...ROM.NLEN-1
+            {
+                t+=DChunk(a.w[i]-a.w[k-i])*DChunk(b.w[k-i]-b.w[i])
+                i+=1
+            }
+        
+            c.w[k]=Chunk(t&RM); co=t>>RB
+        }
+        c.w[2*ROM.NLEN-1]=Chunk(co);
+        
+        return c
+    }
+    
+    /* return a^2 as DBIG */
+    static func sqr(_ a: BIG) -> DBIG
+    {
+        var t:DChunk
+        var co:DChunk
+        let c=DBIG()
+        let RM:DChunk=DChunk(ROM.BMASK);
+        let RB:DChunk=DChunk(ROM.BASEBITS)
+   //     a.norm();
+ 
+        t=DChunk(a.w[0])*DChunk(a.w[0])
+        c.w[0]=Chunk(t&RM); co=t>>RB
+        t=DChunk(a.w[1])*DChunk(a.w[0]); t+=t; t+=co
+        c.w[1]=Chunk(t&RM); co=t>>RB
+        
+        var j:Int
+        let last=ROM.NLEN-(ROM.NLEN%2)
+        j=2
+        //for j=2;j<last;j+=2
+        while (j<last)
+        {
+            t=DChunk(a.w[j])*DChunk(a.w[0]); for i in 1 ..< (j+1)/2 {t+=DChunk(a.w[j-i])*DChunk(a.w[i])} ; t+=t; t+=co; t+=DChunk(a.w[j/2])*DChunk(a.w[j/2])
+            c.w[j]=Chunk(t&RM); co=t>>RB
+            t=DChunk(a.w[j+1])*DChunk(a.w[0]); for i in 1 ..< (j+2)/2 {t+=DChunk(a.w[j+1-i])*DChunk(a.w[i])} ; t+=t; t+=co
+            c.w[j+1]=Chunk(t&RM); co=t>>RB
+            j+=2
+        }
+        j=last
+        if (ROM.NLEN%2)==1
+        {
+            t=DChunk(a.w[j])*DChunk(a.w[0]); for i in 1 ..< (j+1)/2 {t+=DChunk(a.w[j-i])*DChunk(a.w[i])} ; t+=t; t+=co; t+=DChunk(a.w[j/2])*DChunk(a.w[j/2])
+            c.w[j]=Chunk(t&RM); co=t>>RB; j += 1
+            t=DChunk(a.w[ROM.NLEN-1])*DChunk(a.w[j-ROM.NLEN+1]); for i in j-ROM.NLEN+2 ..< (j+1)/2 {t+=DChunk(a.w[j-i])*DChunk(a.w[i])}; t+=t; t+=co
+            c.w[j]=Chunk(t&RM); co=t>>RB; j += 1
+        }
+        while (j<ROM.DNLEN-2)
+        {
+            t=DChunk(a.w[ROM.NLEN-1])*DChunk(a.w[j-ROM.NLEN+1]); for i in j-ROM.NLEN+2 ..< (j+1)/2 {t+=DChunk(a.w[j-i])*DChunk(a.w[i])} ; t+=t; t+=co; t+=DChunk(a.w[j/2])*DChunk(a.w[j/2])
+            c.w[j]=Chunk(t&RM); co=t>>RB
+            t=DChunk(a.w[ROM.NLEN-1])*DChunk(a.w[j-ROM.NLEN+2]); for i in j-ROM.NLEN+3 ..< (j+2)/2 {t+=DChunk(a.w[j+1-i])*DChunk(a.w[i])} ; t+=t; t+=co
+            c.w[j+1]=Chunk(t&RM); co=t>>RB
+            j+=2
+        }
+        t=DChunk(a.w[ROM.NLEN-1])*DChunk(a.w[ROM.NLEN-1])+co
+        c.w[ROM.DNLEN-2]=Chunk(t&RM); co=t>>RB
+        c.w[ROM.DNLEN-1]=Chunk(co)
+    
+        return c;
+    }
+    static func monty(_ d:DBIG) -> BIG
+    {
+        let md=BIG(ROM.Modulus);
+        let RM:DChunk=DChunk(ROM.BMASK)
+        let RB:DChunk=DChunk(ROM.BASEBITS)
+        
+        
+        var t:DChunk
+        var s:DChunk
+        var c:DChunk
+        var dd=[DChunk](repeating: 0,count: ROM.NLEN)
+        var v=[Chunk](repeating: 0,count: ROM.NLEN)
+        let b=BIG(0)
+        
+        t=DChunk(d.w[0]); v[0]=(Chunk(t&RM)&*ROM.MConst)&ROM.BMASK; t+=DChunk(v[0])*DChunk(md.w[0]); c=DChunk(d.w[1])+(t>>RB); s=0
+        for k in 1 ..< ROM.NLEN
+        {
+            t=c+s+DChunk(v[0])*DChunk(md.w[k])
+            //for i in 1+k/2...k-1
+            //for var i=k-1;i>k/2;i--
+            var i=1+k/2
+            while i<k
+            {
+                t+=DChunk(v[k-i]-v[i])*DChunk(md.w[i]-md.w[k-i])
+                i+=1
+            }
+            v[k]=(Chunk(t&RM)&*ROM.MConst)&ROM.BMASK; t+=DChunk(v[k])*DChunk(md.w[0]); c=DChunk(d.w[k+1])+(t>>RB)
+            dd[k]=DChunk(v[k])*DChunk(md.w[k]); s+=dd[k]
+        }
+        for k in ROM.NLEN ..< 2*ROM.NLEN-1
+        {
+            t=c+s;
+            //for i in 1+k/2...ROM.NLEN-1
+            //for var i=ROM.NLEN-1;i>=1+k/2;i--
+            var i=1+k/2
+            while i<ROM.NLEN
+            {
+                t+=DChunk(v[k-i]-v[i])*DChunk(md.w[i]-md.w[k-i])
+                i+=1
+            }
+            b.w[k-ROM.NLEN]=Chunk(t&RM); c=DChunk(d.w[k+1])+(t>>RB); s-=dd[k-ROM.NLEN+1]
+        }
+        b.w[ROM.NLEN-1]=Chunk(c&RM)
+        b.norm()
+        return b;
+    }
+#endif
+#if D64
+    static func mul(_ a: BIG,_ b:BIG) -> DBIG
+    {
+        let c=DBIG()
+        var carry:Chunk
+        for i in 0 ..< ROM.NLEN {
+            carry=0
+            for j in 0..<ROM.NLEN {
+                let (top,bot)=BIG.muladd(a.w[i],b.w[j],carry,c.w[i+j])
+                carry=top; c.w[i+j]=bot
+            }
+            c.w[ROM.NLEN+i]=carry
+        }
+        return c
+    }
+    static func sqr(_ a: BIG) -> DBIG
+    {
+        let c=DBIG()
+        var carry:Chunk
+        for i in 0 ..< ROM.NLEN {
+            carry=0
+            for j in i+1 ..< ROM.NLEN {
+                let (top,bot)=BIG.muladd(2*a.w[i],a.w[j],carry,c.w[i+j])
+                carry=top; c.w[i+j]=bot
+            }
+            c.w[ROM.NLEN+i]=carry
+        }
+        for i in 0 ..< ROM.NLEN {
+            let (top,bot)=BIG.muladd(a.w[i],a.w[i],Chunk(0),c.w[2*i])
+            c.w[2*i]=bot
+            c.w[2*i+1]+=top
+        }
+        c.norm()
+        return c
+    }
+    static func monty(_ d:DBIG) -> BIG
+    {
+        let b=BIG()
+        let md=BIG(ROM.Modulus);
+        var carry:Chunk
+        var m:Chunk
+        for i in 0 ..< ROM.NLEN {
+            if ROM.MConst == -1 {
+                m=(-d.w[i])&ROM.BMASK
+            } else {
+                if ROM.MConst == 1 {
+                    m=d.w[i]
+                } else {
+                    m=(ROM.MConst&*d.w[i])&ROM.BMASK;
+                }
+            }
+            carry=0
+            for j in 0 ..< ROM.NLEN {
+                let (top,bot)=BIG.muladd(m,md.w[j],carry,d.w[i+j])
+                carry=top; d.w[i+j]=bot
+            }
+            d.w[ROM.NLEN+i]+=carry
+        }
+        for i in 0 ..< ROM.NLEN {
+            b.w[i]=d.w[ROM.NLEN+i]
+        }
+        b.norm();
+        return b
+    }
+#endif
+    /* reduce a DBIG to a BIG using the appropriate form of the modulus */
+    static func mod(_ d: DBIG) -> BIG
+    {
+ 
+        if ROM.MODTYPE==ROM.PSEUDO_MERSENNE
+        {
+            let t=d.split(ROM.MODBITS)
+            var b=BIG(d)
+            let v=t.pmul(Int(ROM.MConst))
+            let tw=t.w[ROM.NLEN-1]
+            t.w[ROM.NLEN-1] &= ROM.TMASK
+            t.inc(Int(ROM.MConst*((tw>>Chunk(ROM.TBITS))+(v<<Chunk(ROM.BASEBITS-ROM.TBITS)))))
+    
+            b.add(t)
+            b.norm()
+            return b
+        }
+        if ROM.MODTYPE==ROM.MONTGOMERY_FRIENDLY
+        {
+            for i in 0 ..< ROM.NLEN {
+                let (top,bot)=BIG.muladd(d.w[i],ROM.MConst-1,d.w[i],d.w[ROM.NLEN+i-1])
+                d.w[ROM.NLEN+i]+=top; d.w[ROM.NLEN+i-1]=bot
+ //                   d.w[ROM.NLEN+i]+=d.muladd(d.w[i],ROM.MConst-1,d.w[i],ROM.NLEN+i-1)
+            }
+    
+            var b=BIG(0);
+    
+            for i in 0 ..< ROM.NLEN
+            {
+                b.w[i]=d.w[ROM.NLEN+i]
+            }
+            b.norm()
+            return b;
+        }
+        if ROM.MODTYPE==ROM.GENERALISED_MERSENNE
+        { // GoldiLocks Only
+            let t=d.split(ROM.MODBITS)
+            let RM2=ROM.MODBITS/2
+            var b=BIG(d)
+            b.add(t)
+            let dd=DBIG(t)
+            dd.shl(RM2)
+            
+            let tt=dd.split(ROM.MODBITS)
+            let lo=BIG(dd)
+            b.add(tt)
+            b.add(lo)
+            b.norm()
+            tt.shl(RM2)
+            b.add(tt)
+            
+            let carry=b.w[ROM.NLEN-1]>>Chunk(ROM.TBITS)
+            b.w[ROM.NLEN-1]&=ROM.TMASK
+            b.w[0]+=carry
+            
+            b.w[Int(224/ROM.BASEBITS)]+=carry<<Chunk(224%ROM.BASEBITS)
+            b.norm()
+            return b;
+        }
+        if ROM.MODTYPE==ROM.NOT_SPECIAL
+        {
+            return BIG.monty(d)
+        }
+        return BIG(0)
+    }
+    
+    /* return a*b mod m */
+    static func modmul(_ a: BIG,_ b :BIG,_ m: BIG) -> BIG
+    {
+        a.mod(m)
+        b.mod(m)
+        let d=mul(a,b)
+        return d.mod(m)
+    }
+    
+    /* return a^2 mod m */
+    static func modsqr(_ a: BIG,_ m: BIG) -> BIG
+    {
+        a.mod(m)
+        let d=sqr(a)
+        return d.mod(m)
+    }
+    
+    /* return -a mod m */
+    static func modneg(_ a: BIG,_ m: BIG) -> BIG
+    {
+        a.mod(m)
+        return m.minus(a)
+    }
+    
+    /* return this^e mod m */
+    func powmod(_ e: BIG,_ m: BIG) -> BIG
+    {
+        norm();
+        e.norm();
+        var a=BIG(1)
+        let z=BIG(e)
+        var s=BIG(self)
+        while (true)
+        {
+            let bt=z.parity();
+            z.fshr(1)
+            if bt==1 {a=BIG.modmul(a,s,m)}
+            if (z.iszilch()) {break}
+            s=BIG.modsqr(s,m)
+        }
+        return a
+    }
+}
diff --git a/version22/swift/dbig.swift b/version22/swift/dbig.swift
new file mode 100644
index 0000000..8a1ac64
--- /dev/null
+++ b/version22/swift/dbig.swift
@@ -0,0 +1,265 @@
+/*
+	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.
+*/
+
+//
+//  dbig.swift
+//
+//  Created by Michael Scott on 13/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+final class DBIG{
+    var w=[Chunk](repeating: 0,count: ROM.DNLEN)
+    init() {
+        for i in 0 ..< ROM.DNLEN {w[i]=0}
+    }
+    init(_ x: Int)
+    {
+        w[0]=Chunk(x);
+        for i in 1 ..< ROM.DNLEN {w[i]=0}
+    }
+    init(_ x: BIG)
+    {
+        for i in 0 ..< ROM.NLEN {w[i]=x.w[i]}
+        w[ROM.NLEN-1]=x.w[ROM.NLEN-1]&ROM.BMASK
+        w[ROM.NLEN]=x.w[ROM.NLEN-1]>>Chunk(ROM.BASEBITS)
+        for i in ROM.NLEN+1 ..< ROM.DNLEN {w[i]=0}
+    }
+    init(_ x: DBIG)
+    {
+        for i in 0 ..< ROM.DNLEN {w[i]=x.w[i]}
+    }
+    init(_ x: [Chunk])
+    {
+        for i in 0 ..< ROM.DNLEN {w[i]=x[i]}
+    }
+
+    func cmove(_ g: DBIG,_ d: Int)
+    {
+        let b = Chunk(-d)
+    
+        for i in 0 ..< ROM.DNLEN
+        {
+            w[i]^=(w[i]^g.w[i])&b;
+        }
+    }
+
+/* Copy from another DBIG */
+    func copy(_ x: DBIG)
+    {
+        for i in 0 ..< ROM.DNLEN {w[i] = x.w[i]}
+    }
+
+    /* this-=x */
+    func sub(_ x: DBIG)
+    {
+        for i in 0 ..< ROM.DNLEN
+        {
+            w[i]-=x.w[i]
+        }
+    }
+/*    func muladd(_ x: Int32,_ y: Int32,_ c: Int32,_ i: Int) -> Int32
+    {
+        let prod:Int64 = Int64(x)*Int64(y)+Int64(c)+Int64(w[i])
+        w[i]=Int32(prod&Int64(ROM.BMASK))
+        return Int32(prod>>Int64(ROM.BASEBITS))
+    } */
+    /* general shift left */
+    func shl(_ k: UInt)
+    {
+        let n=k%ROM.BASEBITS
+        let m=Int(k/ROM.BASEBITS)
+        w[ROM.DNLEN-1]=((w[ROM.DNLEN-1-m]<<Chunk(n)))|(w[ROM.DNLEN-m-2]>>Chunk(ROM.BASEBITS-n))
+        for i in (m+1...ROM.DNLEN-2).reversed()
+     //   for var i=ROM.DNLEN-2;i>m;i--
+        {
+            w[i]=((w[i-m]<<Chunk(n))&ROM.BMASK)|(w[i-m-1]>>Chunk(ROM.BASEBITS-n))
+        }
+        w[m]=(w[0]<<Chunk(n))&ROM.BMASK
+        for i in 0 ..< m {w[i]=0}
+    }
+    /* general shift right */
+    func shr(_ k: UInt)
+    {
+        let n=k%ROM.BASEBITS
+        let m=Int(k/ROM.BASEBITS)
+        for i in 0 ..< ROM.DNLEN-m-1
+        {
+            w[i]=(w[m+i]>>Chunk(n))|((w[m+i+1]<<Chunk(ROM.BASEBITS-n))&ROM.BMASK)
+        }
+        w[ROM.DNLEN - m - 1]=w[ROM.DNLEN-1]>>Chunk(n)
+        for i in ROM.DNLEN - m ..< ROM.DNLEN {w[i]=0}
+    }
+    /* Compare a and b, return 0 if a==b, -1 if a<b, +1 if a>b. Inputs must be normalised */
+    static func comp(_ a: DBIG,_ b: DBIG) -> Int
+    {
+        for i in (0...ROM.DNLEN-1).reversed()
+       // for var i=ROM.DNLEN-1;i>=0;i--
+        {
+            if (a.w[i]==b.w[i]) {continue}
+            if (a.w[i]>b.w[i]) {return 1}
+            else  {return -1}
+        }
+        return 0;
+    }
+    /* normalise BIG - force all digits < 2^BASEBITS */
+    func norm()
+    {
+        var carry:Chunk=0
+        for i in 0 ..< ROM.DNLEN-1
+        {
+            let d=w[i]+carry
+            w[i]=d&ROM.BMASK
+            carry=d>>Chunk(ROM.BASEBITS)
+        }
+        w[ROM.DNLEN-1]+=carry
+    }
+    /* reduces this DBIG mod a BIG, and returns the BIG */
+    func mod(_ c: BIG) -> BIG
+    {
+        var k:Int=0
+        norm()
+        let m=DBIG(c)
+        let r=DBIG(0)
+    
+        if DBIG.comp(self,m)<0 {return BIG(self)}
+    
+        repeat
+        {
+            m.shl(1)
+            k += 1
+        }
+        while (DBIG.comp(self,m)>=0);
+    
+        while (k>0)
+        {
+            m.shr(1)
+
+		r.copy(self)
+		r.sub(m)
+		r.norm()
+		cmove(r,Int(1-((r.w[ROM.DNLEN-1]>>Chunk(ROM.CHUNK-1))&1)))
+/*
+
+            if (DBIG.comp(self,m)>=0)
+            {
+				sub(m)
+				norm()
+            } */
+            k -= 1;
+        }
+        return BIG(self)
+    }
+    /* return this/c */
+    func div(_ c:BIG) -> BIG
+    {
+        var k:Int=0
+        let m=DBIG(c)
+        let a=BIG(0)
+        let e=BIG(1)
+        let r=BIG(0)
+        let dr=DBIG(0)
+
+        norm()
+    
+        while (DBIG.comp(self,m)>=0)
+        {
+            e.fshl(1)
+            m.shl(1)
+            k += 1
+        }
+    
+        while (k>0)
+        {
+            m.shr(1)
+            e.shr(1)
+
+		dr.copy(self)
+		dr.sub(m)
+		dr.norm()
+		let d=Int(1-((dr.w[ROM.DNLEN-1]>>Chunk(ROM.CHUNK-1))&1))
+		cmove(dr,d)
+		r.copy(a)
+		r.add(e)
+		r.norm()
+		a.cmove(r,d)
+/*
+            if (DBIG.comp(self,m)>0)
+            {
+				a.add(e)
+				a.norm()
+				sub(m)
+				norm()
+            } */
+            k -= 1
+        }
+        return a
+    }
+    
+    /* split DBIG at position n, return higher half, keep lower half */
+    func split(_ n: UInt) -> BIG
+    {
+        let t=BIG(0)
+        let m=n%ROM.BASEBITS
+        var carry=w[ROM.DNLEN-1]<<Chunk(ROM.BASEBITS-m)
+    
+        for i in (ROM.NLEN-1...ROM.DNLEN-2).reversed()
+      //  for var i=ROM.DNLEN-2;i>=ROM.NLEN-1;i--
+        {
+            let nw=(w[i]>>Chunk(m))|carry;
+            carry=(w[i]<<Chunk(ROM.BASEBITS-m))&ROM.BMASK;
+            t.set(i-ROM.NLEN+1,nw);
+        }
+        w[ROM.NLEN-1]&=((1<<Chunk(m))-1);
+        return t;
+    }
+    /* return number of bits */
+    func nbits() -> Int
+    {
+        var k=(ROM.DNLEN-1)
+        norm()
+        while k>=0 && w[k]==0 {k -= 1}
+        if k<0 {return 0}
+        var bts=Int(ROM.BASEBITS)*k
+        var c=w[k];
+        while c != 0 {c/=2; bts+=1}
+        return bts
+    }
+    /* Convert to Hex String */
+    func toString() -> String
+    {
+        _ = DBIG()
+        var s:String=""
+        var len=nbits()
+        if len%4 == 0 {len/=4}
+        else {len/=4; len += 1}
+        
+        for i in (0...len-1).reversed()
+    //    for var i=len-1;i>=0;i--
+        {
+            let b = DBIG(self)
+            b.shr(UInt(i*4))
+            let n=String(b.w[0]&15,radix:16,uppercase:false)
+            s+=n
+        }
+        
+        return s
+    }
+    
+}
diff --git a/version22/swift/ecdh.swift b/version22/swift/ecdh.swift
new file mode 100644
index 0000000..fd1d863
--- /dev/null
+++ b/version22/swift/ecdh.swift
@@ -0,0 +1,587 @@
+/*
+	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.
+*/
+
+//
+//  ecdh.swift
+//
+//  Created by Michael Scott on 30/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+import Foundation
+import Darwin
+
+/* Elliptic Curve API high-level functions  */
+
+final public class ECDH
+{
+    static let INVALID_PUBLIC_KEY:Int = -2
+    static let ERROR:Int = -3
+    static let INVALID:Int = -4
+    static public let EFS=Int(ROM.MODBYTES);
+    static public let EGS=Int(ROM.MODBYTES);
+    static public let EAS=16;
+    static public let EBS=16;
+    static public let SHA256=32
+    static public let SHA384=48
+    static public let SHA512=64
+    
+    static public let HASH_TYPE=SHA512
+
+    /* Convert Integer to n-byte array */
+    private static func inttoBytes(_ n: Int,_ len:Int) -> [UInt8]
+    {
+        var b=[UInt8](repeating: 0,count: len)
+        var nn=n
+    
+        var i=len;
+        while (nn>0 && i>0)
+        {
+            i -= 1;
+            b[i]=UInt8(nn&0xff);
+            nn /= 256;
+        }
+        return b;
+    }
+    
+    private static func hashit(_ sha: Int,_ A:[UInt8],_ n: Int32,_ B:[UInt8]?,_ pad:Int) -> [UInt8]
+    {
+        var R=[UInt8]()
+        if sha==SHA256
+        {
+            let H=HASH256()
+            H.process_array(A); if n>0 {H.process_num(n)}
+                if B != nil {H.process_array(B!)}
+            R=H.hash()
+        }
+        if sha==SHA384
+        {
+            let H=HASH384()
+            H.process_array(A); if n>0 {H.process_num(n)}
+            if B != nil {H.process_array(B!)}
+            R=H.hash()
+        }
+        if sha==SHA512
+        {
+            let H=HASH512()
+            H.process_array(A); if n>0 {H.process_num(n)}
+            if B != nil {H.process_array(B!)}
+            R=H.hash()
+        }
+        if R.isEmpty || pad==0 {return R}
+        var W=[UInt8](repeating: 0,count: pad)
+        if pad<=sha
+        {
+            for i in 0 ..< pad {W[i]=R[i]}
+        }
+        else
+        {
+            for i in 0 ..< sha {W[i]=R[i]}
+        }
+        return W
+    }
+    
+    /* Key Derivation Functions */
+    /* Input octet Z */
+    /* Output key of length olen */
+    static public func KDF1(_ sha: Int,_ Z: [UInt8],_ olen:Int) -> [UInt8]
+    {
+    /* NOTE: the parameter olen is the length of the output K in bytes */
+        let hlen=sha
+        var K=[UInt8](repeating: 0,count: olen)
+        var k=0;
+    
+        var cthreshold=olen/hlen; if (olen%hlen) != 0 {cthreshold += 1}
+    
+        for counter in 0 ..< cthreshold
+        {
+            let B=hashit(sha,Z,Int32(counter),nil,0)
+            if k+hlen>olen {for i in 0 ..< olen%hlen {K[k]=B[i]; k+=1}}
+            else {for i in 0 ..< hlen {K[k]=B[i]; k+=1}}
+        }
+        return K;
+    }
+    
+    static public func KDF2(_ sha:Int,_ Z:[UInt8],_ P:[UInt8]?,_ olen:Int) -> [UInt8]
+    {
+    /* NOTE: the parameter olen is the length of the output k in bytes */
+        let hlen=sha
+        var K=[UInt8](repeating: 0,count: olen)
+        var k=0;
+    
+        var cthreshold=olen/hlen; if (olen%hlen) != 0 {cthreshold += 1}
+    
+        for counter in 1...cthreshold
+        {
+            let B=hashit(sha,Z,Int32(counter),P,0)
+            if k+hlen>olen {for i in 0 ..< olen%hlen {K[k]=B[i]; k+=1}}
+            else {for i in 0 ..< hlen {K[k]=B[i]; k+=1}}
+        }
+        return K;
+    }
+   
+    /* Password based Key Derivation Function */
+    /* Input password p, salt s, and repeat count */
+    /* Output key of length olen */
+    static public func PBKDF2(_ sha:Int,_ Pass:[UInt8],_ Salt:[UInt8],_ rep:Int,_ olen:Int) -> [UInt8]
+    {
+        var d=olen/sha;
+        if (olen%sha) != 0 {d+=1}
+        var F=[UInt8](repeating: 0,count: sha)
+        var U=[UInt8](repeating: 0,count: sha)
+        var S=[UInt8](repeating: 0,count: Salt.count+4)
+    
+        var K=[UInt8](repeating: 0,count: d*sha)
+        
+        var opt=0;
+    
+        for i in 1...d
+        {
+            for j in 0 ..< Salt.count {S[j]=Salt[j]}
+            var N=ECDH.inttoBytes(i,4);
+            for j in 0 ..< 4 {S[Salt.count+j]=N[j]}
+    
+            printBinary(Pass);
+            
+            ECDH.HMAC(sha,S,Pass,&F);
+             
+            for j in 0 ..< sha {U[j]=F[j]}
+            for _ in 2...rep
+            {
+		ECDH.HMAC(sha,U,Pass,&U);
+                for k in 0 ..< sha {F[k]^=U[k]}
+            }
+            for j in 0 ..< sha {K[opt]=F[j]; opt+=1}
+        }
+        var key=[UInt8](repeating: 0,count: olen)
+        for i in 0 ..< olen {key[i]=K[i]}
+        return key;
+    }
+    
+    /* Calculate HMAC of m using key k. HMAC is tag of length olen */
+    static public func HMAC(_ sha:Int,_ M:[UInt8],_ K:[UInt8],_ tag:inout [UInt8]) -> Int
+    {
+    /* Input is from an octet m        *
+    * olen is requested output length in bytes. k is the key  *
+    * The output is the calculated tag */
+        var b=64
+        if sha>32 {b=128}
+        
+        var K0=[UInt8](repeating: 0,count: b)
+        let olen=tag.count;
+        var B=[UInt8]();
+        
+        if olen<4 /*|| olen>HASH.len*/ {return 0}
+    
+        if (K.count > b)
+        {
+            //H.process_array(K); var B=H.hash();
+            B=hashit(sha,K,0,nil,0)
+            for i in 0 ..< sha {K0[i]=B[i]}
+        }
+        else
+        {
+            for i in 0 ..< K.count {K0[i]=K[i]}
+        }
+        for i in 0 ..< b {K0[i]^=0x36}
+  
+ //       printBinary(K0)
+        
+        B=hashit(sha,K0,0,M,0)
+        
+ //       printBinary(B);
+    
+        for i in 0 ..< b {K0[i]^=0x6a}
+        B=hashit(sha,K0,0,B,olen)
+        
+        for i in 0 ..< olen {tag[i]=B[i]}
+    
+        return 1;
+    }
+    /* AES encryption/decryption. Encrypt byte array M using key K and returns ciphertext */
+    static public func AES_CBC_IV0_ENCRYPT(_ K:[UInt8],_ M:[UInt8]) -> [UInt8]
+    { /* AES CBC encryption, with Null IV and key K */
+    /* Input is from an octet string M, output is to an octet string C */
+    /* Input is padded as necessary to make up a full final block */
+        let a=AES();
+        var buff=[UInt8](repeating: 0,count: 16)
+        let clen=16+(M.count/16)*16;
+    
+        var C=[UInt8](repeating: 0,count: clen)
+    
+        a.init_it(AES.CBC,K,nil)
+    
+        var ipt=0; var opt=0;
+        var fin=false;
+        var i:Int=0
+        while true
+        {
+            i=0
+            while i<16
+            {
+                if (ipt<M.count) {buff[i]=M[ipt]; ipt+=1}
+				else {fin=true; break;}
+                i+=1
+            }
+            if fin {break}
+            a.encrypt(&buff);
+            for j in 0 ..< 16
+                {C[opt]=buff[j]; opt+=1}
+        }
+    
+    /* last block, filled up to i-th index */
+    
+        let padlen=16-i;
+        for j in i ..< 16 {buff[j]=UInt8(padlen&0xff)}
+    
+        a.encrypt(&buff);
+    
+        for j in 0 ..< 16
+            {C[opt]=buff[j]; opt+=1}
+        a.end();
+        return C;
+    }
+    
+    /* returns plaintext if all consistent, else returns null string */
+    static public func AES_CBC_IV0_DECRYPT(_ K:[UInt8],_ C:[UInt8]) -> [UInt8]
+    { /* padding is removed */
+        let a=AES();
+        
+        var buff=[UInt8](repeating: 0,count: 16)
+        var MM=[UInt8](repeating: 0,count: C.count)
+    
+        var ipt=0; var opt=0;
+    
+        a.init_it(AES.CBC,K,nil);
+    
+        if C.count==0 {return [UInt8]()}
+        var ch=C[ipt]; ipt+=1
+    
+        var fin=false;
+        var i:Int=0
+        while true
+        {
+            i=0
+            while i<16
+            {
+				buff[i]=ch;
+				if ipt>=C.count {fin=true; break;}
+                else {ch=C[ipt]; ipt+=1}
+                i+=1
+            }
+            a.decrypt(&buff);
+            if fin {break}
+            for j in 0 ..< 16
+                {MM[opt]=buff[j]; opt+=1}
+        }
+    
+        a.end();
+        var bad=false;
+        let padlen:Int=Int(buff[15]);
+        if i != 15 || padlen<1 || padlen>16 {bad=true}
+        if padlen>=2 && padlen<=16
+        {
+            for j in 16-padlen ..< 16 {if buff[j] != buff[15] {bad=true}}
+        }
+        if !bad
+        {
+            for j in 0 ..< 16-padlen
+                {MM[opt]=buff[j]; opt+=1}
+        }
+    
+        if bad {return [UInt8]()}
+    
+        var M=[UInt8](repeating: 0,count: opt)
+        for j in 0 ..< opt {M[j]=MM[j]}
+    
+        return M;
+    }
+    
+    /* Calculate a public/private EC GF(p) key pair W,S where W=S.G mod EC(p),
+    * where S is the secret key and W is the public key
+    * and G is fixed generator.
+    * If RNG is NULL then the private key is provided externally in S
+    * otherwise it is generated randomly internally */
+    static public func KEY_PAIR_GENERATE(_ RNG:RAND?,_ S:inout [UInt8],_ W:inout [UInt8]) -> Int
+    {
+        let res=0;
+     //   var T=[UInt8](count:ECDH.EFS,repeatedValue:0)
+        let gx=BIG(ROM.CURVE_Gx);
+        var s:BIG
+        var G:ECP
+        if ROM.CURVETYPE != ROM.MONTGOMERY
+        {
+            let gy=BIG(ROM.CURVE_Gy)
+            G=ECP(gx,gy)
+        }
+        else
+            {G=ECP(gx)}
+    
+        let r=BIG(ROM.CURVE_Order)
+    
+        if (RNG==nil)
+        {
+            s=BIG.fromBytes(S)
+	    s.mod(r)
+        }
+        else
+        {
+            s=BIG.randomnum(r,RNG!)
+    
+         //   s.toBytes(&T)
+         //   for i in 0 ..< EGS {S[i]=T[i]}
+        }
+    
+	if (ROM.AES_S>0)
+	{
+	    s.mod2m(2*ROM.AES_S)
+	}
+	s.toBytes(&S)
+
+        let WP=G.mul(s)
+        WP.toBytes(&W)
+    
+        return res;
+    }
+   
+    /* validate public key. Set full=true for fuller check */
+    static public func PUBLIC_KEY_VALIDATE(_ full:Bool,_ W:[UInt8]) -> Int
+    {
+        var WP=ECP.fromBytes(W);
+        var res=0;
+    
+        let r=BIG(ROM.CURVE_Order)
+    
+        if WP.is_infinity() {res=INVALID_PUBLIC_KEY}
+    
+        if res==0 && full
+        {
+            WP=WP.mul(r)
+            if !WP.is_infinity() {res=INVALID_PUBLIC_KEY}
+        }
+        return res;
+    }
+    /* IEEE-1363 Diffie-Hellman online calculation Z=S.WD */
+    static public func ECPSVDP_DH(_ S:[UInt8],_ WD:[UInt8],_ Z:inout [UInt8]) -> Int
+    {
+        var res=0
+        var T=[UInt8](repeating: 0,count: ECDH.EFS)
+    
+        let s=BIG.fromBytes(S)
+    
+        var W=ECP.fromBytes(WD)
+        if W.is_infinity() {res=ECDH.ERROR}
+    
+        if (res==0)
+        {
+            let r=BIG(ROM.CURVE_Order)
+            s.mod(r)
+    
+            W=W.mul(s);
+            if W.is_infinity() {res=ERROR}
+            else
+            {
+		W.getX().toBytes(&T);
+                for i in 0 ..< ECDH.EFS {Z[i]=T[i]}
+            }
+        }
+        return res;
+    }
+    /* IEEE ECDSA Signature, C and D are signature on F using private key S */
+    static public func ECPSP_DSA(_ sha:Int,_ RNG:RAND,_ S:[UInt8],_ F:[UInt8],_ C:inout [UInt8],_ D:inout [UInt8]) -> Int
+    {
+        var T=[UInt8](repeating: 0,count: ECDH.EFS)
+        let B=hashit(sha,F,0,nil,Int(ROM.MODBYTES))
+    
+        let gx=BIG(ROM.CURVE_Gx)
+        let gy=BIG(ROM.CURVE_Gy)
+    
+        let G=ECP(gx,gy)
+        let r=BIG(ROM.CURVE_Order)
+    
+        let s=BIG.fromBytes(S)
+        let f=BIG.fromBytes(B)
+    
+        let c=BIG(0)
+        let d=BIG(0)
+        var V=ECP()
+    
+        repeat {
+            let u=BIG.randomnum(r,RNG);
+	    let w=BIG.randomnum(r,RNG);
+  	    if ROM.AES_S>0
+	    {
+		u.mod2m(2*ROM.AES_S)
+	    }  
+            V.copy(G)
+            V=V.mul(u)
+            let vx=V.getX()
+            c.copy(vx)
+            c.mod(r)
+            if c.iszilch() {continue}
+	    u.copy(BIG.modmul(u,w,r))
+            u.invmodp(r)
+            d.copy(BIG.modmul(s,c,r))
+            d.add(f)
+	    d.copy(BIG.modmul(d,w,r))
+            d.copy(BIG.modmul(u,d,r))
+        } while d.iszilch()
+    
+        c.toBytes(&T)
+        for i in 0 ..< ECDH.EFS {C[i]=T[i]}
+        d.toBytes(&T)
+        for i in 0 ..< ECDH.EFS {D[i]=T[i]}
+        return 0;
+    }
+    
+    /* IEEE1363 ECDSA Signature Verification. Signature C and D on F is verified using public key W */
+    static public func ECPVP_DSA(_ sha:Int,_ W:[UInt8],_ F:[UInt8],_ C:[UInt8],_ D:[UInt8]) -> Int
+    {
+        var res=0
+        let B=hashit(sha,F,0,nil,Int(ROM.MODBYTES))
+    
+        let gx=BIG(ROM.CURVE_Gx)
+        let gy=BIG(ROM.CURVE_Gy)
+    
+        let G=ECP(gx,gy)
+        let r=BIG(ROM.CURVE_Order)
+    
+        let c=BIG.fromBytes(C)
+        var d=BIG.fromBytes(D)
+        let f=BIG.fromBytes(B)
+    
+        if c.iszilch() || BIG.comp(c,r)>=0 || d.iszilch() || BIG.comp(d,r)>=0
+            {res=ECDH.INVALID}
+    
+        if res==0
+        {
+            d.invmodp(r);
+            f.copy(BIG.modmul(f,d,r))
+            let h2=BIG.modmul(c,d,r)
+    
+            let WP=ECP.fromBytes(W)
+            if WP.is_infinity() {res=ECDH.ERROR}
+            else
+            {
+				var P=ECP();
+				P.copy(WP);
+				P=P.mul2(h2,G,f);
+                if P.is_infinity() {res=INVALID}
+				else
+				{
+                    d=P.getX();
+                    d.mod(r);
+                    if (BIG.comp(d,c) != 0) {res=ECDH.INVALID}
+				}
+            }
+        }
+    
+        return res;
+    }
+    
+    /* IEEE1363 ECIES encryption. Encryption of plaintext M uses public key W and produces ciphertext V,C,T */
+    static public func ECIES_ENCRYPT(_ sha:Int,_ P1:[UInt8],_ P2:[UInt8],_ RNG:RAND,_ W:[UInt8],_ M:[UInt8],_ V:inout [UInt8],_ T:inout [UInt8]) -> [UInt8]
+    {
+        var Z=[UInt8](repeating: 0,count: ECDH.EFS)
+        var VZ=[UInt8](repeating: 0,count: 3*ECDH.EFS+1)
+        var K1=[UInt8](repeating: 0,count: ECDH.EAS)
+        var K2=[UInt8](repeating: 0,count: ECDH.EAS)
+        var U=[UInt8](repeating: 0,count: ECDH.EGS)
+    
+        if ECDH.KEY_PAIR_GENERATE(RNG,&U,&V) != 0 {return [UInt8]()}
+        if ECDH.ECPSVDP_DH(U,W,&Z) != 0 {return [UInt8]()}
+    
+        for i in 0 ..< 2*ECDH.EFS+1 {VZ[i]=V[i]}
+        for i in 0 ..< ECDH.EFS {VZ[2*ECDH.EFS+1+i]=Z[i]}
+    
+    
+        var K=KDF2(sha,VZ,P1,ECDH.EFS)
+    
+        for i in 0 ..< ECDH.EAS {K1[i]=K[i]; K2[i]=K[EAS+i];}
+    
+        var C=AES_CBC_IV0_ENCRYPT(K1,M)
+    
+        var L2=inttoBytes(P2.count,8)
+    
+        var AC=[UInt8](repeating: 0,count: C.count+P2.count+8)
+        
+        for i in 0 ..< C.count {AC[i]=C[i]}
+        for i in 0 ..< P2.count {AC[C.count+i]=P2[i]}
+        for i in 0 ..< 8 {AC[C.count+P2.count+i]=L2[i]}
+    
+        ECDH.HMAC(sha,AC,K2,&T)
+    
+        return C
+    }
+
+    /* IEEE1363 ECIES decryption. Decryption of ciphertext V,C,T using private key U outputs plaintext M */
+    static public func ECIES_DECRYPT(_ sha:Int,_ P1:[UInt8],_ P2:[UInt8],_ V:[UInt8],_ C:[UInt8],_ T:[UInt8],_ U:[UInt8]) -> [UInt8]
+    {
+        var Z=[UInt8](repeating: 0,count: ECDH.EFS)
+        var VZ=[UInt8](repeating: 0,count: 3*ECDH.EFS+1)
+        var K1=[UInt8](repeating: 0,count: ECDH.EAS)
+        var K2=[UInt8](repeating: 0,count: ECDH.EAS)
+
+        var TAG=[UInt8](repeating: 0,count: T.count)
+    
+        if ECPSVDP_DH(U,V,&Z) != 0 {return [UInt8]()}
+    
+        for i in 0 ..< 2*ECDH.EFS+1 {VZ[i]=V[i]}
+        for i in 0 ..< ECDH.EFS {VZ[2*EFS+1+i]=Z[i]}
+    
+        var K=KDF2(sha,VZ,P1,ECDH.EFS)
+    
+        for i in 0 ..< ECDH.EAS {K1[i]=K[i]; K2[i]=K[ECDH.EAS+i]}
+    
+        let M=ECDH.AES_CBC_IV0_DECRYPT(K1,C)
+    
+        if M.count==0 {return M}
+    
+        var L2=inttoBytes(P2.count,8)
+    
+        var AC=[UInt8](repeating: 0,count: C.count+P2.count+8)
+    
+        for i in 0 ..< C.count {AC[i]=C[i]}
+        for i in 0 ..< P2.count {AC[C.count+i]=P2[i]}
+        for i in 0 ..< 8 {AC[C.count+P2.count+i]=L2[i]}
+    
+        ECDH.HMAC(sha,AC,K2,&TAG)
+    
+        var same=true
+        for i in 0 ..< T.count
+        {
+            if T[i] != TAG[i] {same=false}
+        }
+        if !same {return [UInt8]()}
+    
+        return M;
+    
+    }
+    
+    static public func printBinary(_ array: [UInt8])
+    {
+        for i in 0 ..< array.count
+        {
+            let h=String(array[i],radix:16);
+            print("\(h)", terminator: "")
+        }
+        print("");
+    }
+    
+}
diff --git a/version22/swift/ecp.swift b/version22/swift/ecp.swift
new file mode 100644
index 0000000..d4e5c37
--- /dev/null
+++ b/version22/swift/ecp.swift
@@ -0,0 +1,923 @@
+/*
+	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.
+*/
+//
+//  ecp.swift
+//
+//  Created by Michael Scott on 30/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+final class ECP {
+    private var x:FP
+    private var y:FP
+    private var z:FP
+    private var INF:Bool
+    
+   /* Constructor - set to O */
+    init()
+    {
+        x=FP(0)
+        y=FP(0)
+        z=FP(1)
+        INF=true
+    }
+    
+    /* test for O point-at-infinity */
+    func is_infinity() -> Bool
+    {
+        if (ROM.CURVETYPE==ROM.EDWARDS)
+        {
+            x.reduce(); y.reduce(); z.reduce()
+            return x.iszilch() && y.equals(z)
+        }
+        else {return INF}
+    }
+ 
+    /* Conditional swap of P and Q dependant on d */
+    private func cswap(_ Q: ECP,_ d:Int)
+    {
+        x.cswap(Q.x,d);
+        if ROM.CURVETYPE != ROM.MONTGOMERY {y.cswap(Q.y,d)}
+        z.cswap(Q.z,d);
+        if (ROM.CURVETYPE != ROM.EDWARDS)
+        {
+            var bd:Bool
+            if d==0 {bd=false}
+            else {bd=true}
+            bd=bd && (INF != Q.INF)
+            INF = (INF != bd)
+            Q.INF = (Q.INF != bd)
+        }
+    }
+    
+    /* Conditional move of Q to P dependant on d */
+    private func cmove(_ Q: ECP,_ d:Int)
+    {
+        x.cmove(Q.x,d);
+        if ROM.CURVETYPE != ROM.MONTGOMERY {y.cmove(Q.y,d)}
+        z.cmove(Q.z,d);
+        if (ROM.CURVETYPE != ROM.EDWARDS)
+        {
+            var bd:Bool
+            if d==0 {bd=false}
+            else {bd=true}
+            INF = (INF != Q.INF) && bd;
+        }
+    }
+    
+    /* return 1 if b==c, no branching */
+    private static func teq(_ b: Int32,_ c:Int32) -> Int
+    {
+        var x=b^c
+        x-=1  // if x=0, x now -1
+        return Int((x>>31)&1)
+    }
+ 
+    /* self=P */
+    func copy(_ P: ECP)
+    {
+        x.copy(P.x)
+        if ROM.CURVETYPE != ROM.MONTGOMERY {y.copy(P.y)}
+        z.copy(P.z)
+        INF=P.INF
+    }
+    /* self=-self */
+    func neg() {
+        if is_infinity() {return}
+        if (ROM.CURVETYPE==ROM.WEIERSTRASS)
+        {
+            y.neg(); y.norm();
+        }
+        if (ROM.CURVETYPE==ROM.EDWARDS)
+        {
+            x.neg(); x.norm();
+        }
+        return;
+    }
+    
+    /* Constant time select from pre-computed table */
+    private func select(_ W:[ECP],_ b:Int32)
+    {
+        let MP=ECP()
+        let m=b>>31
+        var babs=(b^m)-m
+    
+        babs=(babs-1)/2
+    
+        cmove(W[0],ECP.teq(babs,0)); // conditional move
+        cmove(W[1],ECP.teq(babs,1))
+        cmove(W[2],ECP.teq(babs,2))
+        cmove(W[3],ECP.teq(babs,3))
+        cmove(W[4],ECP.teq(babs,4))
+        cmove(W[5],ECP.teq(babs,5))
+        cmove(W[6],ECP.teq(babs,6))
+        cmove(W[7],ECP.teq(babs,7))
+    
+        MP.copy(self)
+        MP.neg()
+        cmove(MP,Int(m&1))
+    }
+    
+    /* Test P == Q */
+    func equals(_ Q: ECP) -> Bool
+    {
+        if (is_infinity() && Q.is_infinity()) {return true}
+        if (is_infinity() || Q.is_infinity()) {return false}
+        if (ROM.CURVETYPE==ROM.WEIERSTRASS)
+        {
+            let zs2=FP(z); zs2.sqr()
+            let zo2=FP(Q.z); zo2.sqr()
+            let zs3=FP(zs2); zs3.mul(z)
+            let zo3=FP(zo2); zo3.mul(Q.z)
+            zs2.mul(Q.x)
+            zo2.mul(x)
+            if !zs2.equals(zo2) {return false}
+            zs3.mul(Q.y)
+            zo3.mul(y)
+            if !zs3.equals(zo3) {return false}
+        }
+        else
+        {
+            let a=FP(0)
+            let b=FP(0)
+            a.copy(x); a.mul(Q.z); a.reduce()
+            b.copy(Q.x); b.mul(z); b.reduce()
+            if !a.equals(b) {return false}
+            if ROM.CURVETYPE==ROM.EDWARDS
+            {
+				a.copy(y); a.mul(Q.z); a.reduce()
+				b.copy(Q.y); b.mul(z); b.reduce()
+				if !a.equals(b) {return false}
+            }
+        }
+        return true
+    }
+  
+/* set self=O */
+    func inf()
+    {
+        INF=true;
+        x.zero()
+        y.one()
+        z.one()
+    }
+    
+    /* Calculate RHS of curve equation */
+    static func RHS(_ x: FP) -> FP
+    {
+        x.norm();
+        let r=FP(x);
+        r.sqr();
+    
+        if ROM.CURVETYPE==ROM.WEIERSTRASS
+        { // x^3+Ax+B
+            let b=FP(BIG(ROM.CURVE_B))
+            r.mul(x)
+            if (ROM.CURVE_A == -3)
+            {
+				let cx=FP(x)
+				cx.imul(3)
+				cx.neg(); cx.norm()
+				r.add(cx)
+            }
+            r.add(b);
+        }
+        if (ROM.CURVETYPE==ROM.EDWARDS)
+        { // (Ax^2-1)/(Bx^2-1)
+            let b=FP(BIG(ROM.CURVE_B))
+    
+            let one=FP(1);
+            b.mul(r);
+            b.sub(one);
+            if ROM.CURVE_A == -1 {r.neg()}
+            r.sub(one)
+            b.inverse()
+            r.mul(b);
+        }
+        if ROM.CURVETYPE==ROM.MONTGOMERY
+        { // x^3+Ax^2+x
+            let x3=FP(0)
+            x3.copy(r);
+            x3.mul(x);
+            r.imul(ROM.CURVE_A);
+            r.add(x3);
+            r.add(x);
+        }
+        r.reduce();
+        return r;
+    }
+    
+    /* set (x,y) from two BIGs */
+    init(_ ix: BIG,_ iy: BIG)
+    {
+        x=FP(ix)
+        y=FP(iy)
+        z=FP(1)
+        INF=true
+        let rhs=ECP.RHS(x);
+    
+        if ROM.CURVETYPE==ROM.MONTGOMERY
+        {
+            if rhs.jacobi()==1 {INF=false}
+            else {inf()}
+        }
+        else
+        {
+            let y2=FP(y)
+            y2.sqr()
+            if y2.equals(rhs) {INF=false}
+            else {inf()}
+        }
+    }
+    
+    /* set (x,y) from BIG and a bit */
+    init(_ ix: BIG,_ s:Int)
+    {
+        x=FP(ix)
+        let rhs=ECP.RHS(x)
+        y=FP(0)
+        z=FP(1)
+        INF=true
+        if rhs.jacobi()==1
+        {
+            let ny=rhs.sqrt()
+            if (ny.redc().parity() != s) {ny.neg()}
+            y.copy(ny)
+            INF=false;
+        }
+        else {inf()}
+    }
+    
+    /* set from x - calculate y from curve equation */
+    init(_ ix:BIG)
+    {
+        x=FP(ix)
+        let rhs=ECP.RHS(x)
+        y=FP(0)
+        z=FP(1)
+        if rhs.jacobi()==1
+        {
+            if ROM.CURVETYPE != ROM.MONTGOMERY {y.copy(rhs.sqrt())}
+            INF=false;
+        }
+        else {INF=true}
+    }
+    
+    /* set to affine - from (x,y,z) to (x,y) */
+    func affine()
+    {
+        if is_infinity() {return}
+        let one=FP(1)
+        if (z.equals(one)) {return}
+        z.inverse()
+        if ROM.CURVETYPE==ROM.WEIERSTRASS
+        {
+            let z2=FP(z)
+            z2.sqr()
+            x.mul(z2); x.reduce()
+            y.mul(z2)
+            y.mul(z);  y.reduce()
+        }
+        if ROM.CURVETYPE==ROM.EDWARDS
+        {
+            x.mul(z); x.reduce()
+            y.mul(z); y.reduce()
+        }
+        if ROM.CURVETYPE==ROM.MONTGOMERY
+        {
+            x.mul(z); x.reduce()
+ 
+        }
+        z.copy(one)
+    }
+    /* extract x as a BIG */
+    func getX() -> BIG
+    {
+        affine()
+        return x.redc()
+    }
+    /* extract y as a BIG */
+    func getY() -> BIG
+    {
+        affine();
+        return y.redc();
+    }
+    
+    /* get sign of Y */
+    func getS() -> Int
+    {
+        affine()
+        let y=getY()
+        return y.parity()
+    }
+    /* extract x as an FP */
+    func getx() -> FP
+    {
+        return x;
+    }
+    /* extract y as an FP */
+    func gety() -> FP
+    {
+        return y;
+    }
+    /* extract z as an FP */
+    func getz() -> FP
+    {
+        return z;
+    }
+    /* convert to byte array */
+    func toBytes(_ b:inout [UInt8])
+    {
+        let RM=Int(ROM.MODBYTES)
+        var t=[UInt8](repeating: 0,count: RM)
+        if ROM.CURVETYPE != ROM.MONTGOMERY {b[0]=0x04}
+        else {b[0]=0x02}
+    
+        affine()
+        x.redc().toBytes(&t)
+        for i in 0 ..< RM {b[i+1]=t[i]}
+        if ROM.CURVETYPE != ROM.MONTGOMERY
+        {
+            y.redc().toBytes(&t);
+            for i in 0 ..< RM {b[i+RM+1]=t[i]}
+        }
+    }
+    /* convert from byte array to point */
+    static func fromBytes(_ b: [UInt8]) -> ECP
+    {
+        let RM=Int(ROM.MODBYTES)
+        var t=[UInt8](repeating: 0,count: RM)
+        let p=BIG(ROM.Modulus);
+    
+        for i in 0 ..< RM {t[i]=b[i+1]}
+        let px=BIG.fromBytes(t)
+        if BIG.comp(px,p)>=0 {return ECP()}
+    
+        if (b[0]==0x04)
+        {
+            for i in 0 ..< RM {t[i]=b[i+RM+1]}
+            let py=BIG.fromBytes(t)
+            if BIG.comp(py,p)>=0 {return ECP()}
+            return ECP(px,py)
+        }
+        else {return ECP(px)}
+    }
+    /* convert to hex string */
+    func toString() -> String
+    {
+        if is_infinity() {return "infinity"}
+        affine();
+        if ROM.CURVETYPE==ROM.MONTGOMERY {return "("+x.redc().toString()+")"}
+        else {return "("+x.redc().toString()+","+y.redc().toString()+")"}
+    }
+    
+    /* self*=2 */
+    func dbl()
+    {
+        if (ROM.CURVETYPE==ROM.WEIERSTRASS)
+        {
+            if INF {return}
+            if y.iszilch()
+            {
+				inf()
+				return
+            }
+    
+            let w1=FP(x)
+            let w6=FP(z)
+            let w2=FP(0)
+            let w3=FP(x)
+            let w8=FP(x)
+    
+            if (ROM.CURVE_A == -3)
+            {
+				w6.sqr()
+				w1.copy(w6)
+				w1.neg()
+				w3.add(w1)
+				w8.add(w6)
+				w3.mul(w8)
+				w8.copy(w3)
+				w8.imul(3)
+            }
+            else
+            {
+				w1.sqr()
+				w8.copy(w1)
+				w8.imul(3)
+            }
+    
+            w2.copy(y); w2.sqr()
+            w3.copy(x); w3.mul(w2)
+            w3.imul(4)
+            w1.copy(w3); w1.neg()
+            w1.norm()
+    
+            x.copy(w8); x.sqr()
+            x.add(w1)
+            x.add(w1)
+            x.norm()
+    
+            z.mul(y)
+            z.add(z)
+    
+            w2.add(w2)
+            w2.sqr()
+            w2.add(w2)
+            w3.sub(x)
+            y.copy(w8); y.mul(w3)
+            //w2.norm();
+            y.sub(w2)
+            y.norm()
+            z.norm()
+        }
+        if ROM.CURVETYPE==ROM.EDWARDS
+        {
+            let C=FP(x)
+            let D=FP(y)
+            let H=FP(z)
+            let J=FP(0)
+    
+            x.mul(y); x.add(x)
+            C.sqr()
+            D.sqr()
+            if ROM.CURVE_A == -1 {C.neg()}
+            y.copy(C); y.add(D)
+            y.norm()
+            H.sqr(); H.add(H)
+            z.copy(y)
+            J.copy(y); J.sub(H)
+            x.mul(J)
+            C.sub(D)
+            y.mul(C)
+            z.mul(J)
+    
+            x.norm();
+            y.norm();
+            z.norm();
+        }
+        if ROM.CURVETYPE==ROM.MONTGOMERY
+        {
+            let A=FP(x)
+            let B=FP(x);
+            let AA=FP(0);
+            let BB=FP(0);
+            let C=FP(0);
+    
+            if INF {return}
+    
+            A.add(z)
+            AA.copy(A); AA.sqr()
+            B.sub(z)
+            BB.copy(B); BB.sqr()
+            C.copy(AA); C.sub(BB)
+    //C.norm();
+    
+            x.copy(AA); x.mul(BB)
+    
+            A.copy(C); A.imul((ROM.CURVE_A+2)/4)
+    
+            BB.add(A)
+            z.copy(BB); z.mul(C)
+            x.norm()
+            z.norm()
+        }
+        return
+    }
+    
+    /* self+=Q */
+    func add(_ Q:ECP)
+    {
+        if ROM.CURVETYPE==ROM.WEIERSTRASS
+        {
+            if (INF)
+            {
+				copy(Q)
+				return
+            }
+            if Q.INF {return}
+    
+            var aff=false;
+    
+            let one=FP(1);
+            if Q.z.equals(one) {aff=true}
+    
+            var A:FP
+            var C:FP
+            let B=FP(z)
+            let D=FP(z)
+            if (!aff)
+            {
+				A=FP(Q.z)
+				C=FP(Q.z)
+    
+				A.sqr(); B.sqr()
+				C.mul(A); D.mul(B)
+    
+				A.mul(x)
+				C.mul(y)
+            }
+            else
+            {
+				A=FP(x)
+				C=FP(y)
+    
+				B.sqr()
+				D.mul(B)
+            }
+    
+            B.mul(Q.x); B.sub(A)
+            D.mul(Q.y); D.sub(C)
+    
+            if B.iszilch()
+            {
+				if (D.iszilch())
+				{
+                    dbl()
+                    return
+				}
+				else
+				{
+                    INF=true
+                    return
+				}
+            }
+    
+            if !aff {z.mul(Q.z)}
+            z.mul(B);
+    
+            let e=FP(B); e.sqr()
+            B.mul(e)
+            A.mul(e)
+    
+            e.copy(A)
+            e.add(A); e.add(B)
+            x.copy(D); x.sqr(); x.sub(e)
+    
+            A.sub(x)
+            y.copy(A); y.mul(D)
+            C.mul(B); y.sub(C)
+    
+            x.norm()
+            y.norm()
+            z.norm()
+        }
+        if ROM.CURVETYPE==ROM.EDWARDS
+        {
+            let b=FP(BIG(ROM.CURVE_B))
+            let A=FP(z)
+            let B=FP(0)
+            let C=FP(x)
+            let D=FP(y)
+            let E=FP(0)
+            let F=FP(0)
+            let G=FP(0)
+    
+            A.mul(Q.z)
+            B.copy(A); B.sqr()
+            C.mul(Q.x)
+            D.mul(Q.y)
+    
+            E.copy(C); E.mul(D); E.mul(b)
+            F.copy(B); F.sub(E)
+            G.copy(B); G.add(E)
+    
+            if ROM.CURVE_A==1
+            {
+				E.copy(D); E.sub(C)
+            }
+            C.add(D)
+    
+            B.copy(x); B.add(y)
+            D.copy(Q.x); D.add(Q.y)
+            B.mul(D)
+            B.sub(C)
+            B.mul(F)
+            x.copy(A); x.mul(B)
+
+            if ROM.CURVE_A==1
+            {
+				C.copy(E); C.mul(G)
+            }
+            if ROM.CURVE_A == -1
+            {
+				C.mul(G)
+            }
+            y.copy(A); y.mul(C)
+            z.copy(F); z.mul(G)
+            x.norm(); y.norm(); z.norm()
+        }
+        return;
+    }
+    
+    /* Differential Add for Montgomery curves. self+=Q where W is self-Q and is affine. */
+    func dadd(_ Q:ECP,_ W:ECP)
+    {
+        let A=FP(x)
+        let B=FP(x)
+        let C=FP(Q.x)
+        let D=FP(Q.x)
+        let DA=FP(0)
+        let CB=FP(0)
+    
+        A.add(z)
+        B.sub(z)
+    
+        C.add(Q.z)
+        D.sub(Q.z)
+    
+        DA.copy(D); DA.mul(A)
+        CB.copy(C); CB.mul(B)
+        
+        A.copy(DA); A.add(CB); A.sqr()
+        B.copy(DA); B.sub(CB); B.sqr()
+    
+        x.copy(A)
+        z.copy(W.x); z.mul(B)
+    
+        if z.iszilch() {inf()}
+        else {INF=false}
+    
+        x.norm()
+    }
+    /* this-=Q */
+    func sub(_ Q:ECP)
+    {
+        Q.neg()
+        add(Q)
+        Q.neg()
+    }
+    static func multiaffine(_ m: Int,_ P:[ECP])
+    {
+        let t1=FP(0)
+        let t2=FP(0)
+    
+        var work=[FP]()
+        
+        for _ in 0 ..< m
+            {work.append(FP(0))}
+    
+        work[0].one()
+        work[1].copy(P[0].z)
+    
+        for i in 2 ..< m
+        {
+            work[i].copy(work[i-1])
+            work[i].mul(P[i-1].z)
+        }
+    
+        t1.copy(work[m-1]);
+        t1.mul(P[m-1].z);
+        t1.inverse();
+        t2.copy(P[m-1].z);
+        work[m-1].mul(t1);
+        var i=m-2;
+        while (true)
+        {
+            if i==0
+            {
+				work[0].copy(t1)
+				work[0].mul(t2)
+				break
+            }
+            work[i].mul(t2);
+            work[i].mul(t1);
+            t2.mul(P[i].z);
+            i=i-1;
+        }
+    /* now work[] contains inverses of all Z coordinates */
+    
+        for i in 0 ..< m
+        {
+            P[i].z.one();
+            t1.copy(work[i]);
+            t1.sqr();
+            P[i].x.mul(t1);
+            t1.mul(work[i]);
+            P[i].y.mul(t1);
+        }
+    }
+    /* constant time multiply by small integer of length bts - use ladder */
+    func pinmul(_ e:Int32,_ bts:Int32) -> ECP
+    {
+        if ROM.CURVETYPE==ROM.MONTGOMERY
+            {return self.mul(BIG(Int(e)))}
+        else
+        {
+            let P=ECP()
+            let R0=ECP()
+            let R1=ECP(); R1.copy(self)
+    
+            for i in (0...bts-1).reversed()
+            {
+				let b=Int(e>>i)&1;
+				P.copy(R1);
+				P.add(R0);
+				R0.cswap(R1,b);
+				R1.copy(P);
+				R0.dbl();
+				R0.cswap(R1,b);
+            }
+            P.copy(R0);
+            P.affine();
+            return P;
+        }
+    }
+    
+    /* return e.self */
+    
+    func mul(_ e:BIG) -> ECP
+    {
+        if (e.iszilch() || is_infinity()) {return ECP()}
+    
+        let P=ECP()
+        if ROM.CURVETYPE==ROM.MONTGOMERY
+        {
+            /* use Ladder */
+            let D=ECP()
+            let R0=ECP(); R0.copy(self)
+            let R1=ECP(); R1.copy(self)
+            R1.dbl();
+            D.copy(self); D.affine();
+            let nb=e.nbits();
+            
+            for i in (0...nb-2).reversed()
+            {
+				let b=e.bit(UInt(i))
+                //print("\(b)")
+				P.copy(R1)
+				P.dadd(R0,D)
+				R0.cswap(R1,b)
+				R1.copy(P)
+				R0.dbl()
+				R0.cswap(R1,b)
+            }
+            P.copy(R0)
+        }
+        else
+        {
+    // fixed size windows
+            let mt=BIG()
+            let t=BIG()
+            let Q=ECP()
+            let C=ECP()
+            var W=[ECP]()
+            let n=1+(ROM.NLEN*Int(ROM.BASEBITS)+3)/4
+            var w=[Int8](repeating: 0,count: n)
+    
+            affine();
+    
+    // precompute table
+            Q.copy(self)
+            Q.dbl()
+            W.append(ECP())
+            
+            W[0].copy(self)
+    
+            for i in 1 ..< 8
+            {
+                W.append(ECP())
+				W[i].copy(W[i-1])
+				W[i].add(Q)
+            }
+    
+    // convert the table to affine
+            if ROM.CURVETYPE==ROM.WEIERSTRASS
+                {ECP.multiaffine(8,W)}
+    
+    // make exponent odd - add 2P if even, P if odd
+            t.copy(e);
+            let s=t.parity();
+            t.inc(1); t.norm(); let ns=t.parity();
+            mt.copy(t); mt.inc(1); mt.norm();
+            t.cmove(mt,s);
+            Q.cmove(self,ns);
+            C.copy(Q);
+    
+            let nb=1+(t.nbits()+3)/4;
+    
+    // convert exponent to signed 4-bit window
+            for i in 0 ..< nb
+            {
+				w[i]=Int8(t.lastbits(5)-16);
+				t.dec(Int(w[i]));
+                t.norm();
+				t.fshr(4);
+            }
+            w[nb]=Int8(t.lastbits(5))
+    
+            P.copy(W[Int((w[nb])-1)/2]);
+            for i in (0...nb-1).reversed()
+            {
+				Q.select(W,Int32(w[i]));
+				P.dbl();
+				P.dbl();
+				P.dbl();
+				P.dbl();
+				P.add(Q);
+            }
+            P.sub(C); /* apply correction */
+        }
+        P.affine();
+        return P;
+    }
+    
+    /* Return e.this+f.Q */
+    
+    func mul2(_ e:BIG,_ Q:ECP,_ f:BIG) -> ECP
+    {
+        let te=BIG()
+        let tf=BIG()
+        let mt=BIG()
+        let S=ECP()
+        let T=ECP()
+        let C=ECP()
+        var W=[ECP]()
+        let n=1+(ROM.NLEN*Int(ROM.BASEBITS)+1)/2
+        var w=[Int8](repeating: 0,count: n);
+        
+        affine();
+        Q.affine();
+    
+        te.copy(e);
+        tf.copy(f);
+    
+    // precompute table
+        for _ in 0 ..< 8 {W.append(ECP())}
+        W[1].copy(self); W[1].sub(Q)
+        W[2].copy(self); W[2].add(Q)
+        S.copy(Q); S.dbl();
+        W[0].copy(W[1]); W[0].sub(S)
+        W[3].copy(W[2]); W[3].add(S)
+        T.copy(self); T.dbl()
+        W[5].copy(W[1]); W[5].add(T)
+        W[6].copy(W[2]); W[6].add(T)
+        W[4].copy(W[5]); W[4].sub(S)
+        W[7].copy(W[6]); W[7].add(S)
+    
+    // convert the table to affine
+        if ROM.CURVETYPE==ROM.WEIERSTRASS
+            {ECP.multiaffine(8,W)}
+    
+    // if multiplier is odd, add 2, else add 1 to multiplier, and add 2P or P to correction
+    
+        var s=te.parity()
+        te.inc(1); te.norm(); var ns=te.parity(); mt.copy(te); mt.inc(1); mt.norm()
+        te.cmove(mt,s)
+        T.cmove(self,ns)
+        C.copy(T)
+    
+        s=tf.parity()
+        tf.inc(1); tf.norm(); ns=tf.parity(); mt.copy(tf); mt.inc(1); mt.norm()
+        tf.cmove(mt,s)
+        S.cmove(Q,ns)
+        C.add(S)
+    
+        mt.copy(te); mt.add(tf); mt.norm()
+        let nb=1+(mt.nbits()+1)/2
+    
+    // convert exponent to signed 2-bit window
+        for i in 0 ..< nb
+        {
+            let a=(te.lastbits(3)-4);
+            te.dec(a); te.norm();
+            te.fshr(2);
+            let b=(tf.lastbits(3)-4);
+            tf.dec(b); tf.norm();
+            tf.fshr(2);
+            w[i]=Int8(4*a+b);
+        }
+        w[nb]=Int8(4*te.lastbits(3)+tf.lastbits(3));
+        S.copy(W[Int(w[nb]-1)/2]);
+        for i in (0...nb-1).reversed()
+        {
+            T.select(W,Int32(w[i]));
+            S.dbl();
+            S.dbl();
+            S.add(T);
+        }
+        S.sub(C); /* apply correction */
+        S.affine();
+        return S;
+    }
+    
+    
+   
+    
+}
diff --git a/version22/swift/ecp2.swift b/version22/swift/ecp2.swift
new file mode 100644
index 0000000..e1288d6
--- /dev/null
+++ b/version22/swift/ecp2.swift
@@ -0,0 +1,618 @@
+/*
+	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.
+*/
+//
+//  ecp2.swift
+//
+//  Created by Michael Scott on 07/07/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+/* AMCL Weierstrass elliptic curve functions over FP2 */
+
+final class ECP2 {
+    private var x:FP2
+    private var y:FP2
+    private var z:FP2
+    private var INF:Bool
+    
+    /* Constructor - set self=O */
+    init()
+    {
+        INF=true
+        x=FP2(0)
+        y=FP2(1)
+        z=FP2(1)
+    }
+    /* Test self=O? */
+    func is_infinity() -> Bool
+    {
+        return INF
+    }
+    /* copy self=P */
+    func copy(_ P:ECP2)
+    {
+        x.copy(P.x)
+        y.copy(P.y)
+        z.copy(P.z)
+        INF=P.INF
+    }
+    /* set self=O */
+    func inf() {
+        INF=true
+        x.zero()
+        y.zero()
+        z.zero()
+    }
+    /* Conditional move of Q to P dependant on d */
+    func cmove(_ Q:ECP2,_ d:Int)
+    {
+        x.cmove(Q.x,d);
+        y.cmove(Q.y,d);
+        z.cmove(Q.z,d);
+    
+        var bd:Bool
+        if d==0 {bd=false}
+        else {bd=true}
+        INF = (INF != ((INF != Q.INF) && bd))
+    }
+    
+    /* return 1 if b==c, no branching */
+    private static func teq(_ b:Int32,_ c:Int32) -> Int
+    {
+        var x=b^c
+        x-=1  // if x=0, x now -1
+        return Int((x>>31)&1)
+    }
+    /* Constant time select from pre-computed table */
+    func select(_ W:[ECP2],_ b:Int32)
+    {
+        let MP=ECP2()
+        let m=b>>31
+        var babs=(b^m)-m
+        
+        babs=(babs-1)/2
+    
+        cmove(W[0],ECP2.teq(babs,0)) // conditional move
+        cmove(W[1],ECP2.teq(babs,1))
+        cmove(W[2],ECP2.teq(babs,2))
+        cmove(W[3],ECP2.teq(babs,3))
+        cmove(W[4],ECP2.teq(babs,4))
+        cmove(W[5],ECP2.teq(babs,5))
+        cmove(W[6],ECP2.teq(babs,6))
+        cmove(W[7],ECP2.teq(babs,7))
+    
+        MP.copy(self)
+        MP.neg()
+        cmove(MP,Int(m&1))
+    }
+ 
+    /* Test if P == Q */
+    func equals(_ Q:ECP2) -> Bool
+    {
+        if is_infinity() && Q.is_infinity() {return true}
+        if is_infinity() || Q.is_infinity() {return false}
+    
+        let zs2=FP2(z); zs2.sqr()
+        let zo2=FP2(Q.z); zo2.sqr()
+        let zs3=FP2(zs2); zs3.mul(z)
+        let zo3=FP2(zo2); zo3.mul(Q.z)
+        zs2.mul(Q.x)
+        zo2.mul(x)
+        if !zs2.equals(zo2) {return false}
+        zs3.mul(Q.y)
+        zo3.mul(y)
+        if !zs3.equals(zo3) {return false}
+    
+        return true;
+    }
+    /* set self=-self */
+    func neg()
+    {
+        if is_infinity() {return}
+        y.neg(); y.norm()
+        return
+    }
+    /* set to Affine - (x,y,z) to (x,y) */
+    func affine() {
+        if is_infinity() {return}
+        let one=FP2(1)
+        if z.equals(one) {return}
+        z.inverse()
+    
+        let z2=FP2(z)
+        z2.sqr()
+        x.mul(z2); x.reduce()
+        y.mul(z2)
+        y.mul(z);  y.reduce()
+        z.copy(one)
+    }
+    /* extract affine x as FP2 */
+    func getX() -> FP2
+    {
+        affine()
+        return x
+    }
+    /* extract affine y as FP2 */
+    func getY() -> FP2
+    {
+        affine()
+        return y
+    }
+    /* extract projective x */
+    func getx() -> FP2
+    {
+        return x
+    }
+    /* extract projective y */
+    func gety() -> FP2
+    {
+        return y
+    }
+    /* extract projective z */
+    func getz() -> FP2
+    {
+        return z
+    }
+    /* convert to byte array */
+    func toBytes(_ b:inout [UInt8])
+    {
+        let RM=Int(ROM.MODBYTES)
+        var t=[UInt8](repeating: 0,count: RM)
+
+        affine();
+        x.getA().toBytes(&t)
+        for i in 0 ..< RM
+            {b[i]=t[i]}
+        x.getB().toBytes(&t);
+        for i in 0 ..< RM
+            {b[i+RM]=t[i]}
+    
+        y.getA().toBytes(&t);
+        for i in 0 ..< RM
+            {b[i+2*RM]=t[i]}
+        y.getB().toBytes(&t);
+        for i in 0 ..< RM
+            {b[i+3*RM]=t[i]}
+    }
+    /* convert from byte array to point */
+    static func fromBytes(_ b:[UInt8]) -> ECP2
+    {
+        let RM=Int(ROM.MODBYTES)
+        var t=[UInt8](repeating: 0,count: RM)
+
+    
+        for i in 0 ..< RM {t[i]=b[i]}
+        var ra=BIG.fromBytes(t);
+        for i in 0 ..< RM {t[i]=b[i+RM]}
+        var rb=BIG.fromBytes(t);
+        let rx=FP2(ra,rb)
+    
+        for i in 0 ..< RM {t[i]=b[i+2*RM]}
+        ra=BIG.fromBytes(t)
+        for i in 0 ..< RM {t[i]=b[i+3*RM]}
+        rb=BIG.fromBytes(t)
+        let ry=FP2(ra,rb)
+    
+        return ECP2(rx,ry)
+    }
+/* convert self to hex string */
+    func toString() -> String
+    {
+        if is_infinity() {return "infinity"}
+        affine()
+        return "("+x.toString()+","+y.toString()+")"
+    }
+    
+/* Calculate RHS of twisted curve equation x^3+B/i */
+    static func RHS(_ x:FP2) -> FP2
+    {
+        x.norm()
+        let r=FP2(x)
+        r.sqr()
+        let b=FP2(BIG(ROM.CURVE_B))
+        b.div_ip();
+        r.mul(x);
+        r.add(b);
+    
+        r.reduce();
+        return r;
+    }
+/* construct self from (x,y) - but set to O if not on curve */
+    init(_ ix:FP2,_ iy:FP2)
+    {
+        x=FP2(ix)
+        y=FP2(iy)
+        z=FP2(1)
+        let rhs=ECP2.RHS(x)
+        let y2=FP2(y)
+        y2.sqr()
+        if y2.equals(rhs) {INF=false}
+        else {x.zero(); INF=true}
+    }
+    /* construct this from x - but set to O if not on curve */
+    init(_ ix:FP2)
+    {
+        x=FP2(ix)
+        y=FP2(1)
+        z=FP2(1)
+        let rhs=ECP2.RHS(x)
+        if rhs.sqrt()
+        {
+            y.copy(rhs);
+            INF=false;
+        }
+        else {x.zero(); INF=true;}
+    }
+    
+    /* this+=this */
+    func dbl() -> Int
+    {
+        if (INF) {return -1}
+        if y.iszilch()
+        {
+            inf();
+            return -1;
+        }
+    
+        let w1=FP2(x)
+        let w2=FP2(0)
+        let w3=FP2(x)
+        let w8=FP2(x)
+    
+        w1.sqr()
+        w8.copy(w1)
+        w8.imul(3)
+    
+        w2.copy(y); w2.sqr()
+        w3.copy(x); w3.mul(w2)
+        w3.imul(4)
+        w1.copy(w3); w1.neg()
+        w1.norm()
+    
+        x.copy(w8); x.sqr()
+        x.add(w1)
+        x.add(w1)
+        x.norm()
+    
+        z.mul(y)
+        z.add(z)
+    
+        w2.add(w2)
+        w2.sqr()
+        w2.add(w2)
+        w3.sub(x)
+        y.copy(w8); y.mul(w3)
+        w2.norm()
+        y.sub(w2)
+        y.norm()
+        z.norm()
+    
+        return 1
+    }
+/* this+=Q - return 0 for add, 1 for double, -1 for O */
+    func add(_ Q:ECP2) -> Int
+    {
+        if INF
+        {
+            copy(Q)
+            return -1
+        }
+        if Q.INF {return -1}
+    
+        var aff=false
+    
+        if Q.z.isunity() {aff=true}
+    
+        var A:FP2
+        var C:FP2
+        let B=FP2(z)
+        let D=FP2(z)
+        if (!aff)
+        {
+            A=FP2(Q.z)
+            C=FP2(Q.z)
+    
+            A.sqr(); B.sqr()
+            C.mul(A); D.mul(B)
+    
+            A.mul(x)
+            C.mul(y)
+        }
+        else
+        {
+            A=FP2(x)
+            C=FP2(y)
+    
+            B.sqr()
+            D.mul(B)
+        }
+    
+        B.mul(Q.x); B.sub(A)
+        D.mul(Q.y); D.sub(C)
+    
+        if B.iszilch()
+        {
+            if D.iszilch()
+            {
+				dbl()
+				return 1
+            }
+            else
+            {
+				INF=true
+				return -1
+            }
+        }
+    
+        if !aff {z.mul(Q.z)}
+        z.mul(B)
+    
+        let e=FP2(B); e.sqr()
+        B.mul(e)
+        A.mul(e)
+    
+        e.copy(A)
+        e.add(A); e.add(B)
+        x.copy(D); x.sqr(); x.sub(e)
+    
+        A.sub(x)
+        y.copy(A); y.mul(D)
+        C.mul(B); y.sub(C)
+    
+        x.norm()
+        y.norm()
+        z.norm()
+    
+        return 0
+    }
+
+    /* set self-=Q */
+    func sub(_ Q:ECP2) -> Int
+    {
+        Q.neg()
+        let D=add(Q)
+        Q.neg()
+        return D
+    }
+/* set self*=q, where q is Modulus, using Frobenius */
+    func frob(_ X:FP2)
+    {
+        if INF {return}
+        let X2=FP2(X)
+        X2.sqr()
+        x.conj()
+        y.conj()
+        z.conj()
+        z.reduce()
+        x.mul(X2)
+        y.mul(X2)
+        y.mul(X)
+    }
+    /* normalises m-array of ECP2 points. Requires work vector of m FP2s */
+    
+    private static func multiaffine(_ m:Int,_ P:[ECP2])
+    {
+        let t1=FP2(0)
+        let t2=FP2(0)
+    
+        var work=[FP2]()
+        for _ in 0 ..< m
+            {work.append(FP2(0))}
+     
+        work[0].one()
+        work[1].copy(P[0].z)
+        
+        for i in 2 ..< m
+        {
+            work[i].copy(work[i-1])
+            work[i].mul(P[i-1].z)
+        }
+    
+        t1.copy(work[m-1]); t1.mul(P[m-1].z)
+    
+        t1.inverse()
+    
+        t2.copy(P[m-1].z)
+        work[m-1].mul(t1)
+    
+        var i=m-2
+        while true
+        {
+            if (i==0)
+            {
+				work[0].copy(t1)
+				work[0].mul(t2)
+				break;
+            }
+            work[i].mul(t2)
+            work[i].mul(t1)
+            t2.mul(P[i].z)
+            i-=1
+        }
+    /* now work[] contains inverses of all Z coordinates */
+    
+        for i in 0 ..< m
+        {
+            P[i].z.one()
+            t1.copy(work[i]); t1.sqr()
+            P[i].x.mul(t1)
+            t1.mul(work[i])
+            P[i].y.mul(t1)
+        }
+    }
+    
+    /* P*=e */
+    func mul(_ e:BIG) -> ECP2
+    {
+    /* fixed size windows */
+        let mt=BIG()
+        let t=BIG()
+        let P=ECP2()
+        let Q=ECP2()
+        let C=ECP2()
+        
+        var W=[ECP2]();
+        for _ in 0 ..< 8 {W.append(ECP2())}
+        
+        var w=[Int8](repeating: 0,count: 1+(ROM.NLEN*Int(ROM.BASEBITS)+3)/4)
+    
+        if is_infinity() {return ECP2()}
+    
+        affine()
+    
+    /* precompute table */
+        Q.copy(self)
+        Q.dbl()
+        W[0].copy(self)
+    
+        for i in 1 ..< 8
+        {
+            W[i].copy(W[i-1])
+            W[i].add(Q)
+        }
+    
+    /* convert the table to affine */
+ 
+        ECP2.multiaffine(8,W);
+    
+    /* make exponent odd - add 2P if even, P if odd */
+        t.copy(e)
+        let s=t.parity()
+        t.inc(1); t.norm(); let ns=t.parity(); mt.copy(t); mt.inc(1); mt.norm()
+        t.cmove(mt,s)
+        Q.cmove(self,ns)
+        C.copy(Q)
+    
+        let nb=1+(t.nbits()+3)/4
+    /* convert exponent to signed 4-bit window */
+        for i in 0 ..< nb
+        {
+            w[i]=Int8(t.lastbits(5)-16)
+            t.dec(Int(w[i])); t.norm()
+            t.fshr(4)
+        }
+        w[nb]=Int8(t.lastbits(5))
+    
+        P.copy(W[Int(w[nb]-1)/2])
+        for i in (0...nb-1).reversed()
+        //for var i=nb-1;i>=0;i--
+        {
+            Q.select(W,Int32(w[i]))
+            P.dbl()
+            P.dbl()
+            P.dbl()
+            P.dbl()
+            P.add(Q)
+        }
+        P.sub(C);
+        P.affine()
+        return P;
+    }
+    
+    /* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3 */
+    static func mul4(_ Q:[ECP2],_ u:[BIG]) -> ECP2
+    {
+        var a=[Int32](repeating: 0,count: 4)
+        let T=ECP2()
+        let C=ECP2()
+        let P=ECP2()
+        
+        var W=[ECP2]();
+        for _ in 0 ..< 8 {W.append(ECP2())}
+    
+        let mt=BIG()
+        var t=[BIG]()
+    
+        var w=[Int8](repeating: 0,count: ROM.NLEN*Int(ROM.BASEBITS)+1)
+    
+        for i in 0 ..< 4
+        {
+            t.append(BIG(u[i]))
+            Q[i].affine()
+        }
+    
+    /* precompute table */
+    
+        W[0].copy(Q[0]); W[0].sub(Q[1])
+        W[1].copy(W[0])
+        W[2].copy(W[0])
+        W[3].copy(W[0])
+        W[4].copy(Q[0]); W[4].add(Q[1])
+        W[5].copy(W[4])
+        W[6].copy(W[4])
+        W[7].copy(W[4])
+        T.copy(Q[2]); T.sub(Q[3])
+        W[1].sub(T)
+        W[2].add(T)
+        W[5].sub(T)
+        W[6].add(T)
+        T.copy(Q[2]); T.add(Q[3])
+        W[0].sub(T)
+        W[3].add(T)
+        W[4].sub(T)
+        W[7].add(T)
+    
+        ECP2.multiaffine(8,W);
+    
+    /* if multiplier is even add 1 to multiplier, and add P to correction */
+        mt.zero(); C.inf()
+        for i in 0 ..< 4
+        {
+            if (t[i].parity()==0)
+            {
+				t[i].inc(1); t[i].norm()
+                C.add(Q[i])
+            }
+            mt.add(t[i]); mt.norm()
+        }
+    
+        let nb=1+mt.nbits();
+    
+    /* convert exponent to signed 1-bit window */
+        for j in 0 ..< nb
+        {
+            for i in 0 ..< 4 {
+				a[i]=Int32(t[i].lastbits(2)-2)
+                
+				t[i].dec(Int(a[i]))
+                t[i].norm()
+				t[i].fshr(1)
+            }
+            w[j]=Int8(8*a[0]+4*a[1]+2*a[2]+a[3])
+        }
+        w[nb]=Int8(8*t[0].lastbits(2)+4*t[1].lastbits(2))
+        w[nb]+=Int8(2*t[2].lastbits(2)+t[3].lastbits(2))
+    
+        P.copy(W[Int(w[nb]-1)/2])
+        for i in (0...nb-1).reversed()
+        //for var i=nb-1;i>=0;i--
+        {
+            T.select(W,Int32(w[i]))
+            P.dbl()
+            P.add(T)
+        }
+        P.sub(C) /* apply correction */
+    
+        P.affine()
+        return P
+    }
+    
+    
+    
+}
diff --git a/version22/swift/ff.swift b/version22/swift/ff.swift
new file mode 100644
index 0000000..ab87c91
--- /dev/null
+++ b/version22/swift/ff.swift
@@ -0,0 +1,927 @@
+/*
+	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.
+*/
+
+//
+//  ff.swift
+//
+//  Created by Michael Scott on 24/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+/* Large Finite Field arithmetic */
+/* AMCL mod p functions */
+
+final class FF {
+    var v = [BIG]()
+    var length:Int=1
+    
+ /*   func P_EXCESS() -> Int32
+    {
+        return ((v[length-1].w[ROM.NLEN-1]&FF.P_OMASK)>>FF.P_TBITS)
+    } */
+    /* Constructors */
+    init(_ n: Int)
+    {
+        for _ in 0 ..< n
+        {
+            v.append(BIG(0));
+        }
+        length=n;
+    }
+    
+    init(_ x: [[Chunk]],n: Int)
+    {
+        for i in 0 ..< n
+        {
+            v.append(BIG(x[i]))
+        }
+        length=n;
+    }
+    
+    func getlen() -> Int
+    {
+        return length;
+    }
+    
+    /* set to zero */
+    func zero()
+    {
+        for i in 0 ..< length
+        {
+            v[i].zero();
+        }
+    }
+    
+    /* set to integer */
+    func set(_ m: Int)
+    {
+        zero();
+        v[0].set(0,Chunk(m));
+    }
+    
+    /* copy from FF b */
+    func copy(_ b: FF)
+    {
+        for i in 0 ..< length
+        {
+            v[i].copy(b.v[i]);
+        }
+    }
+    
+    /* x=y<<n */
+    func dsucopy(_ b: FF)
+    {
+        for i in 0 ..< b.length
+        {
+            v[b.length+i].copy(b.v[i]);
+            v[i].zero();
+        }
+    }
+    /* x=y */
+    func dscopy(_ b: FF)
+    {
+        for i in 0 ..< b.length
+        {
+            v[i].copy(b.v[i]);
+            v[b.length+i].zero();
+        }
+    }
+    /* x=y>>n */
+    func sducopy(_ b: FF)
+    {
+        for i in 0 ..< length
+        {
+            v[i].copy(b.v[length+i]);
+        }
+    }
+    func one()
+    {
+        v[0].one();
+        for i in 1 ..< length
+        {
+            v[i].zero();
+        }
+    }
+    /* test equals 0 */
+    func iszilch() -> Bool
+    {
+        for i in 0 ..< length
+        {
+            if (!v[i].iszilch()) {return false}
+        }
+        return true;
+    }
+    /* shift right by BIGBITS-bit words */
+    func shrw(_ n: Int)
+    {
+        for i in 0 ..< n
+        {
+            v[i].copy(v[i+n]);
+            v[i+n].zero();
+        }
+    }
+    
+    /* shift left by BIGBITS-bit words */
+    func shlw(_ n: Int)
+    {
+        for i in 0 ..< n
+        {
+        v[n+i].copy(v[i]);
+        v[i].zero();
+        }
+    }
+    
+    /* extract last bit */
+    func parity() -> Int
+    {
+        return v[0].parity()
+    }
+    
+    func lastbits(_ m: Int) ->Int
+    {
+        return v[0].lastbits(UInt(m));
+    }
+    
+    /* compare x and y - must be normalised, and of same length */
+    static func comp(_ a: FF,_ b:FF) -> Int
+    {
+        for i in (0...a.length-1).reversed()
+       // for var i=a.length-1;i>=0;i--
+        {
+            let j=BIG.comp(a.v[i],b.v[i])
+            if j != 0 {return j}
+        }
+        return 0;
+    }
+    /* recursive add */
+    func radd(_ vp: Int,_ x:FF,_ xp:Int,_ y:FF,_ yp:Int,_ n: Int)
+    {
+        for i in 0 ..< n
+        {
+            v[vp+i].copy(x.v[xp+i])
+            v[vp+i].add(y.v[yp+i])
+        }
+    }
+    /* recursive inc */
+    func rinc(_ vp: Int,_ y: FF,_ yp: Int,_ n:Int)
+    {
+        for i in 0 ..< n
+        {
+            v[vp+i].add(y.v[yp+i])
+        }
+    }
+    /* recursive add */
+    func rsub(_ vp: Int,_ x:FF,_ xp:Int,_ y:FF,_ yp:Int,_ n: Int)
+    {
+        for i in 0 ..< n
+        {
+            v[vp+i].copy(x.v[xp+i])
+            v[vp+i].sub(y.v[yp+i])
+        }
+    }
+    /* recursive inc */
+    func rdec(_ vp: Int,_ y: FF,_ yp: Int,_ n:Int)
+    {
+        for i in 0 ..< n
+        {
+            v[vp+i].sub(y.v[yp+i])
+        }
+    }
+    /* simple add */
+    func add(_ b: FF)
+    {
+        for i in 0 ..< length
+            {v[i].add(b.v[i])}
+    }
+    
+    /* simple sub */
+    func sub(_ b: FF)
+    {
+        for i in 0 ..< length
+            {v[i].sub(b.v[i])}
+    }
+    /* reverse sub */
+    func revsub(_ b: FF)
+    {
+        for i in 0 ..< length
+            {v[i].rsub(b.v[i])}
+    }
+    /* normalise - but hold any overflow in top part unless n<0 */
+    private func rnorm(_ vp: Int,_ n: Int)
+    {
+        var trunc=false;
+        var nn=n
+   
+        if (nn<0)
+        { /* -v n signals to do truncation */
+            nn = -nn
+            trunc=true;
+        }
+        for i in 0 ..< nn-1
+        {
+            let carry=v[vp+i].norm();
+            v[vp+i].xortop(carry<<Chunk(ROM.P_TBITS))
+            v[vp+i+1].w[0]+=carry; //inc(carry)
+        }
+        let carry=v[vp+nn-1].norm();
+        if (trunc)
+            {v[vp+nn-1].xortop(carry<<Chunk(ROM.P_TBITS))}
+    }
+    
+    func norm()
+    {
+        rnorm(0,length)
+    }
+    
+    /* increment/decrement by a small integer */
+    func inc(_ m: Int)
+    {
+        v[0].inc(m);
+        norm();
+    }
+    
+    func dec(_ m: Int)
+    {
+        v[0].dec(m);
+        norm();
+    }
+    
+    /* shift left by one bit */
+    func shl()
+    {
+        var delay_carry=0;
+        for i in 0 ..< length-1
+        {
+            let carry=v[i].fshl(1)
+            v[i].inc(delay_carry);
+            v[i].xortop(Chunk(carry)<<Chunk(ROM.P_TBITS));
+            delay_carry=carry;
+        }
+        v[length-1].fshl(1)
+        v[length-1].inc(delay_carry)
+    }
+    
+    /* shift right by one bit */
+    func shr()
+    {
+        for i in (1...length-1).reversed()
+        {
+            let carry=v[i].fshr(1);
+            v[i-1].ortop(Chunk(carry)<<Chunk(ROM.P_TBITS));
+        }
+        v[0].fshr(1);
+    }
+    
+    /* Convert to Hex String */
+    func toString() -> String
+    {
+        norm();
+        var s="";
+        for i in (0...length-1).reversed()
+        {
+            s+=v[i].toString();
+        }
+        return s;
+    }
+    
+    /* Convert FFs to/from byte arrays */
+    func toBytes(_ b: inout [UInt8])
+    {
+        for i in 0 ..< length
+        {
+            v[i].tobytearray(&b,(length-i-1)*Int(ROM.MODBYTES))
+        }
+    }
+    static func fromBytes(_ x: FF,_ b:[UInt8])
+    {
+        for i in 0 ..< x.length
+        {
+            x.v[i]=BIG.frombytearray(b,(x.length-i-1)*Int(ROM.MODBYTES))
+        }
+    }
+    
+    /* in-place swapping using xor - side channel resistant - lengths must be the same */
+    private static func cswap(_ a: FF,_ b:FF,_ d:Int)
+    {
+        for i in 0 ..< a.length
+        {
+            a.v[i].cswap(b.v[i],d)
+        }
+    }
+    /* z=x*y, t is workspace */
+    private func karmul(_ vp: Int,_ x: FF,_ xp: Int,_ y:FF,_ yp: Int,_ t:FF,_ tp:Int,_ n:Int)
+    {
+        if (n==1)
+        {
+            let d=BIG.mul(x.v[xp],y.v[yp])
+            v[vp+1]=d.split(8*ROM.MODBYTES)
+            v[vp].copy(d)
+            return
+        }
+        let nd2=n/2
+        radd(vp,x,xp,x,xp+nd2,nd2)
+        rnorm(vp,nd2)
+        radd(vp+nd2,y,yp,y,yp+nd2,nd2)
+        rnorm(vp+nd2,nd2)
+        
+        t.karmul(tp,self,vp,self,vp+nd2,t,tp+n,nd2)
+        karmul(vp,x,xp,y,yp,t,tp+n,nd2)
+        karmul(vp+n,x,xp+nd2,y,yp+nd2,t,tp+n,nd2)
+        t.rdec(tp,self,vp,n)
+        t.rdec(tp,self,vp+n,n)
+        rinc(vp+nd2,t,tp,n)
+        rnorm(vp,2*n)
+    }
+    
+    private func karsqr(_ vp: Int,_ x: FF,_ xp:Int,_ t:FF,_ tp:Int,_ n:Int)
+    {
+        if (n==1)
+        {
+            let d=BIG.sqr(x.v[xp])
+            v[vp+1].copy(d.split(8*ROM.MODBYTES))
+            v[vp].copy(d);
+            return;
+        }
+    
+        let nd2=n/2
+        karsqr(vp,x,xp,t,tp+n,nd2)
+        karsqr(vp+n,x,xp+nd2,t,tp+n,nd2)
+        t.karmul(tp,x,xp,x,xp+nd2,t,tp+n,nd2)
+        rinc(vp+nd2,t,tp,n)
+        rinc(vp+nd2,t,tp,n)
+        rnorm(vp+nd2,n)
+    }
+    private func karmul_lower(_ vp:Int,_ x:FF,_ xp:Int,_ y:FF,_ yp:Int,_ t:FF,_ tp:Int,_ n: Int)
+    { /* Calculates Least Significant bottom half of x*y */
+        if (n==1)
+        { /* only calculate bottom half of product */
+            v[vp].copy(BIG.smul(x.v[xp],y.v[yp]))
+            return
+        }
+        let nd2=n/2
+    
+        karmul(vp,x,xp,y,yp,t,tp+n,nd2)
+        t.karmul_lower(tp,x,xp+nd2,y,yp,t,tp+n,nd2);
+        rinc(vp+nd2,t,tp,nd2);
+        t.karmul_lower(tp,x,xp,y,yp+nd2,t,tp+n,nd2);
+        rinc(vp+nd2,t,tp,nd2);
+        rnorm(vp+nd2,-nd2);  /* truncate it */
+    }
+    
+    private func karmul_upper(_ x: FF,_ y:FF,_ t:FF,_ n:Int)
+    { /* Calculates Most Significant upper half of x*y, given lower part */
+        let nd2=n/2;
+        radd(n,x,0,x,nd2,nd2);
+        radd(n+nd2,y,0,y,nd2,nd2);
+	rnorm(n,nd2);
+	rnorm(n+nd2,nd2);
+    
+        t.karmul(0,self,n+nd2,self,n,t,n,nd2);  /* t = (a0+a1)(b0+b1) */
+        karmul(n,x,nd2,y,nd2,t,n,nd2);          /* z[n]= a1*b1 */
+    /* z[0-nd2]=l(a0b0) z[nd2-n]= h(a0b0)+l(t)-l(a0b0)-l(a1b1) */
+        t.rdec(0,self,n,n);                     /* t=t-a1b1  */
+        rinc(nd2,self,0,nd2);                   /* z[nd2-n]+=l(a0b0) = h(a0b0)+l(t)-l(a1b1)  */
+        rdec(nd2,t,0,nd2);                      /* z[nd2-n]=h(a0b0)+l(t)-l(a1b1)-l(t-a1b1)=h(a0b0) */
+        rnorm(0,-n);                            /* a0b0 now in z - truncate it */
+        t.rdec(0,self,0,n);                     /* (a0+a1)(b0+b1) - a0b0 */
+        rinc(nd2,t,0,n);
+    
+        rnorm(nd2,n);
+    }
+    /* z=x*y. Assumes x and y are of same length. */
+    static func mul(_ x: FF,_ y:FF) -> FF
+    {
+        let n=x.length
+        let z=FF(2*n)
+        let t=FF(2*n)
+        z.karmul(0,x,0,y,0,t,0,n)
+        return z
+    }
+    
+    /* z=x^2 */
+    static func sqr(_ x: FF) -> FF
+    {
+        let n=x.length
+        let z=FF(2*n)
+        let t=FF(2*n)
+        z.karsqr(0,x,0,t,0,n)
+        return z
+    }
+    /* return low part of product self*y */
+    func lmul(_ y: FF)
+    {
+        let n=length;
+        let t=FF(2*n);
+        let x=FF(n); x.copy(self);
+        karmul_lower(0,x,0,y,0,t,0,n);
+    }
+    
+    /* Set b=b mod c */
+    func mod(_ c: FF)
+    {
+        var k=0
+    
+        norm()
+        if (FF.comp(self,c)<0)
+            {return}
+        repeat
+        {
+            c.shl()
+            k+=1
+        } while (FF.comp(self,c)>=0)
+    
+        while (k>0)
+        {
+            c.shr();
+            if (FF.comp(self,c)>=0)
+            {
+				sub(c)
+				norm()
+            }
+            k-=1
+        }
+    }
+    
+    /* return This mod modulus, N is modulus, ND is Montgomery Constant */
+    func reduce(_ N: FF,_ ND:FF) -> FF
+    { /* fast karatsuba Montgomery reduction */
+        let n=N.length
+        let t=FF(2*n)
+        let r=FF(n)
+        let m=FF(n)
+    
+        r.sducopy(self)
+        m.karmul_lower(0,self,0,ND,0,t,0,n)
+        karmul_upper(N,m,t,n)
+        m.sducopy(self)
+    
+        r.add(N);
+        r.sub(m);
+        r.norm();
+    
+        return r;
+    }
+    /* Set r=this mod b */
+    /* this is of length - 2*n */
+    /* r,b is of length - n */
+    func dmod(_ b: FF) -> FF
+    {
+        let n=b.length
+        let m=FF(2*n)
+        let x=FF(2*n)
+        let r=FF(n)
+    
+        x.copy(self)
+        x.norm()
+        m.dsucopy(b)
+        var k=Int(ROM.BIGBITS)*n
+    
+        while (FF.comp(x,m)>=0)
+        {
+		x.sub(m);
+		x.norm();
+        }
+
+        while (k>0)
+        {
+            m.shr()
+    
+            if (FF.comp(x,m)>=0)
+            {
+				x.sub(m);
+				x.norm();
+            }
+            k -= 1;
+        }
+    
+        r.copy(x);
+        r.mod(b);
+        return r;
+    }
+    /* Set return=1/this mod p. Binary method - a<p on entry */
+    
+    func invmodp(_ p: FF)
+    {
+        let n=p.length;
+    
+        let u=FF(n)
+        let v=FF(n)
+        let x1=FF(n)
+        let x2=FF(n)
+        let t=FF(n)
+        let one=FF(n)
+    
+        one.one()
+        u.copy(self)
+        v.copy(p)
+        x1.copy(one)
+        x2.zero()
+    
+    // reduce n in here as well!
+        while (FF.comp(u,one) != 0 && FF.comp(v,one) != 0)
+        {
+            while (u.parity()==0)
+            {
+                u.shr()
+                if (x1.parity() != 0)
+                {
+                    x1.add(p)
+                    x1.norm()
+                }
+                x1.shr()
+            }
+            while (v.parity()==0)
+            {
+                v.shr()
+                if (x2.parity() != 0)
+                {
+                    x2.add(p)
+                    x2.norm()
+                }
+                x2.shr();
+            }
+            if (FF.comp(u,v)>=0)
+            {
+                u.sub(v)
+                u.norm()
+                if (FF.comp(x1,x2)>=0) {x1.sub(x2)}
+                else
+                {
+                    t.copy(p)
+                    t.sub(x2)
+                    x1.add(t)
+                }
+                x1.norm()
+            }
+            else
+            {
+                v.sub(u)
+                v.norm()
+                if (FF.comp(x2,x1)>=0) {x2.sub(x1)}
+                else
+                {
+                    t.copy(p)
+                    t.sub(x1)
+                    x2.add(t)
+                }
+                x2.norm()
+            }
+        }
+        if FF.comp(u,one)==0
+            {copy(x1)}
+        else
+            {copy(x2)}
+    }
+    
+    /* nresidue mod m */
+    func nres(_ m: FF)
+    {
+        let n=m.length
+        let d=FF(2*n)
+        d.dsucopy(self)
+        copy(d.dmod(m))
+    }
+    
+    func redc(_ m: FF,_ ND:FF)
+    {
+        let n=m.length
+        let d=FF(2*n)
+        mod(m)
+        d.dscopy(self)
+        copy(d.reduce(m,ND))
+        mod(m)
+    }
+    private func mod2m(_ m: Int)
+    {
+        for i in m ..< length
+            {v[i].zero()}
+    }
+    /* U=1/a mod 2^m - Arazi & Qi */
+    private func invmod2m() -> FF
+    {
+        let n=length;
+    
+        let b=FF(n);
+        let c=FF(n);
+        let U=FF(n);
+    
+        U.zero();
+        U.v[0].copy(v[0]);
+        U.v[0].invmod2m();
+    
+        var i=1
+        //for var i=1;i<n;i<<=1
+        while (i<n)
+        {
+            b.copy(self); b.mod2m(i);
+            let t=FF.mul(U,b); t.shrw(i); b.copy(t);
+            c.copy(self); c.shrw(i); c.mod2m(i);
+            c.lmul(U); c.mod2m(i);
+    
+            b.add(c); b.norm();
+            b.lmul(U); b.mod2m(i);
+    
+            c.one(); c.shlw(i); b.revsub(c); b.norm();
+            b.shlw(i);
+            U.add(b);
+            i<<=1
+        }
+        U.norm();
+        return U;
+    }
+    
+    func random(_ rng: RAND)
+    {
+        let n=length;
+        for i in 0 ..< n
+        {
+            v[i].copy(BIG.random(rng));
+        }
+    /* make sure top bit is 1 */
+        while (v[n-1].nbits()<Int(ROM.MODBYTES)*8) {v[n-1].copy(BIG.random(rng))}
+    }
+    /* generate random x */
+    func randomnum(_ p: FF,_ rng: RAND)
+    {
+        let n=length;
+        let d=FF(2*n);
+    
+        for i in 0 ..< 2*n
+        {
+            d.v[i].copy(BIG.random(rng));
+        }
+        copy(d.dmod(p));
+    }
+    /* this*=y mod p */
+    func modmul(_ y: FF,_ p:FF,_ nd: FF)
+    {
+        if BIG.ff_pexceed(v[length-1],y.v[y.length-1]) {mod(p)}
+       // let ex=P_EXCESS();
+       //let ey=y.P_EXCESS();
+       // if ((ex+1)>=(FF.P_FEXCESS-1)/(ey+1)) {mod(p)}
+        let d=FF.mul(self,y);
+        copy(d.reduce(p,nd));
+    }
+    
+    /* this*=y mod p */
+    func modsqr(_ p: FF,_ nd:FF)
+    {
+        if BIG.ff_sexceed(v[length-1]) {mod(p)}
+ //       let ex=P_EXCESS();
+   //     if ((ex+1)>=(FF.P_FEXCESS-1)/(ex+1)) {mod(p)}
+        let d=FF.sqr(self);
+        copy(d.reduce(p,nd));
+    }
+    
+    /* self=self^e mod p using side-channel resistant Montgomery Ladder, for large e */
+    func skpow(_ e: FF,_ p:FF)
+    {
+        let n=p.length
+        let R0=FF(n)
+        let R1=FF(n)
+        let ND=p.invmod2m()
+    
+        mod(p)
+        R0.one()
+        R1.copy(self)
+        R0.nres(p)
+        R1.nres(p)
+    
+        for i in (0...8*Int(ROM.MODBYTES)*n-1).reversed()
+        {
+            let b=Int(e.v[i/Int(ROM.BIGBITS)].bit(UInt(i%Int(ROM.BIGBITS))))
+            copy(R0)
+            modmul(R1,p,ND)
+    
+            FF.cswap(R0,R1,b)
+            R0.modsqr(p,ND)
+    
+            R1.copy(self)
+            FF.cswap(R0,R1,b)
+    
+        }
+    
+        copy(R0)
+        redc(p,ND)
+    }
+    
+    /* this =this^e mod p using side-channel resistant Montgomery Ladder, for short e */
+    func skpow(_ e: BIG,_ p:FF)
+    {
+        let n=p.length
+        let R0=FF(n)
+        let R1=FF(n)
+        let ND=p.invmod2m()
+    
+        mod(p)
+        R0.one()
+        R1.copy(self)
+        R0.nres(p)
+        R1.nres(p)
+    
+        for i in (0...8*Int(ROM.MODBYTES)-1).reversed()
+        {
+            let b=(e.bit(UInt(i)))
+            copy(R0)
+            modmul(R1,p,ND)
+    
+            FF.cswap(R0,R1,b)
+            R0.modsqr(p,ND)
+    
+            R1.copy(self)
+            FF.cswap(R0,R1,b)
+        }
+        copy(R0)
+        redc(p,ND)
+    }
+    
+    /* raise to an integer power - right-to-left method */
+    func power(_ e:Int,_ p:FF)
+    {
+        let n=p.length
+        var f=true
+        let w=FF(n)
+        let ND=p.invmod2m()
+        var ee=e;
+    
+        w.copy(self)
+        w.nres(p)
+    
+        if (ee==2)
+        {
+            copy(w)
+            modsqr(p,ND)
+        }
+        else
+        {
+            while true
+            {
+                if (ee%2==1)
+                {
+                    if (f) {copy(w)}
+                    else {modmul(w,p,ND)}
+                    f=false;
+                }
+                ee>>=1;
+                if (ee==0) {break}
+                w.modsqr(p,ND)
+            }
+        }
+        redc(p,ND)
+    }
+    
+    /* this=this^e mod p, faster but not side channel resistant */
+    func pow(_ e: FF,_ p:FF)
+    {
+        let n=p.length
+        let w=FF(n)
+        let ND=p.invmod2m()
+    
+        w.copy(self);
+        one();
+        nres(p);
+        w.nres(p);
+        for i in (0...8*Int(ROM.MODBYTES)*n-1).reversed()
+      //  for var i=8*Int(ROM.MODBYTES)*n-1;i>=0;i--
+        {
+            modsqr(p,ND)
+            let b=e.v[i/Int(ROM.BIGBITS)].bit(UInt(i%Int(ROM.BIGBITS)))
+            if (b==1) {modmul(w,p,ND)}
+        }
+        redc(p,ND);
+    }
+    /* double exponentiation r=x^e.y^f mod p */
+    func pow2(_ e: BIG,_ y:FF,_ f:BIG,_ p:FF)
+    {
+        let n=p.length
+        let xn=FF(n)
+        let yn=FF(n)
+        let xy=FF(n)
+        let ND=p.invmod2m()
+    
+        xn.copy(self)
+        yn.copy(y)
+        xn.nres(p)
+        yn.nres(p)
+        xy.copy(xn); xy.modmul(yn,p,ND)
+        one()
+        nres(p)
+    
+        for i in (0...8*Int(ROM.MODBYTES)-1).reversed()
+    //    for var i=8*Int(ROM.MODBYTES)-1;i>=0;i--
+        {
+            let eb=e.bit(UInt(i))
+            let fb=f.bit(UInt(i))
+            modsqr(p,ND)
+            if (eb==1)
+            {
+                if (fb==1) {modmul(xy,p,ND)}
+                else {modmul(xn,p,ND)}
+            }
+            else
+            {
+                if (fb==1) {modmul(yn,p,ND)}
+            }
+        }
+        redc(p,ND)
+    }
+    static func igcd(_ x:Int,_ y:Int) -> Int
+    { /* integer GCD, returns GCD of x and y */
+        var xx=x;
+        var yy=y;
+        if (yy==0) {return xx}
+        while true
+        {
+            let r=xx%yy; if r==0 {break}
+            xx=yy; yy=r;
+        }
+        return yy;
+    }
+   
+    /* quick and dirty check for common factor with n */
+    func cfactor(_ s: Int) -> Bool
+    {
+        let n=length;
+        let x=FF(n);
+        let y=FF(n);
+        y.set(s);
+        
+        x.copy(self);
+        x.norm();
+        
+        repeat
+        {
+            x.sub(y);
+            x.norm();
+            while ( (!x.iszilch()) && x.parity()==0) {x.shr()}
+        } while (FF.comp(x,y)>0);
+        let g=x.v[0].get(0);
+        let r=FF.igcd(s,Int(g));
+        
+        if (r>1) {return true}
+        return false;
+    }
+ 
+    /* Miller-Rabin test for primality. Slow. */
+    static func prime(_ p: FF,_ rng:RAND) -> Bool
+    {
+        var s=0
+        let n=p.length
+        var loop:Bool
+
+        let d=FF(n)
+        let x=FF(n)
+        let unity=FF(n)
+        let nm1=FF(n)
+    
+        let sf:Int=4849845; /* 3*5*.. *19 */
+        p.norm();
+        if (p.cfactor(sf)) {return false}
+        unity.one();
+        nm1.copy(p);
+        nm1.sub(unity);
+        nm1.norm();
+        d.copy(nm1);
+        
+        while (d.parity()==0)
+        {
+            d.shr();
+            s += 1;
+        }
+        
+        if (s==0) {return false}
+        for _ in 0 ..< 10
+        {
+            x.randomnum(p,rng)
+            x.pow(d,p)
+            if (FF.comp(x,unity)==0 || FF.comp(x,nm1)==0) {continue}
+            loop=false
+            for _ in 1 ..< s
+            {
+				x.power(2,p);
+                if (FF.comp(x,unity)==0) {return false}
+				if (FF.comp(x,nm1)==0) {loop=true; break;}
+            }
+            if (loop) {continue}
+            return false;
+        }
+        return true;
+    }
+
+}
diff --git a/version22/swift/fp.swift b/version22/swift/fp.swift
new file mode 100644
index 0000000..b4c0ba0
--- /dev/null
+++ b/version22/swift/fp.swift
@@ -0,0 +1,309 @@
+/*
+	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.
+*/
+//
+//  fp.swift
+//
+//  Created by Michael Scott on 20/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//  Small Finite Field arithmetic
+//  AMCL mod p functions
+//
+
+final class FP {
+    var x:BIG
+    static let p=BIG(ROM.Modulus)
+/* convert to Montgomery n-residue form */
+    func nres()
+    {
+        if ROM.MODTYPE != ROM.PSEUDO_MERSENNE && ROM.MODTYPE != ROM.GENERALISED_MERSENNE
+        {
+            let d=DBIG(x)
+            d.shl(UInt(ROM.NLEN)*ROM.BASEBITS)
+            x.copy(d.mod(FP.p))
+        }
+    }
+/* convert back to regular form */
+    func redc() -> BIG
+    {
+        if ROM.MODTYPE != ROM.PSEUDO_MERSENNE && ROM.MODTYPE != ROM.GENERALISED_MERSENNE
+        {
+            let d=DBIG(x)
+            return BIG.mod(d)
+        }
+        else
+        {
+            let r=BIG(x)
+            return r;
+        }
+    }
+    
+    init()
+    {
+        x=BIG(0)
+    }
+    init(_ a: Int)
+    {
+        x=BIG(a)
+        nres()
+    }
+    init(_ a: BIG)
+    {
+        x=BIG(a)
+        nres()
+    }
+    init(_ a: FP)
+    {
+        x=BIG(a.x)
+    }
+    /* convert to string */
+    func toString() -> String
+    {
+        let s=redc().toString();
+        return s;
+    }
+    
+    func toRawString() -> String
+    {
+        let s=x.toRawString();
+        return s;
+    }
+/* reduce this mod Modulus */
+    func reduce()
+    {
+        x.mod(FP.p)
+    }
+    
+/* test this=0? */
+    func iszilch() -> Bool
+    {
+        reduce();
+        return x.iszilch()
+    }
+    
+/* copy from FP b */
+    func copy(_ b: FP)
+    {
+        x.copy(b.x);
+    }
+    
+/* set this=0 */
+    func zero()
+    {
+        x.zero();
+    }
+    
+/* set this=1 */
+    func one()
+    {
+        x.one(); nres()
+    }
+    
+/* normalise this */
+    func norm()
+    {
+        x.norm();
+    }
+/* swap FPs depending on d */
+    func cswap(_ b: FP,_ d: Int)
+    {
+        x.cswap(b.x,d)
+    }
+    
+/* copy FPs depending on d */
+    func cmove(_ b: FP,_ d:Int)
+    {
+        x.cmove(b.x,d);
+    }
+/* this*=b mod Modulus */
+    func mul(_ b: FP)
+    {
+        norm()
+        b.norm()
+        let ea=BIG.EXCESS(x)
+        let eb=BIG.EXCESS(b.x)
+        
+        if Int64(ea+1)*Int64(eb+1)>Int64(ROM.FEXCESS) {reduce()}
+        /*if (ea+1)>=(ROM.FEXCESS-1)/(eb+1) {reduce()}*/
+        
+        let d=BIG.mul(x,b.x)
+        x.copy(BIG.mod(d))
+    }
+    static func logb2(_ w: UInt32) -> Int
+    {
+        var v = w
+        v |= (v >> 1)
+        v |= (v >> 2)
+        v |= (v >> 4)
+        v |= (v >> 8)
+        v |= (v >> 16)
+        
+        v = v - ((v >> 1) & 0x55555555)
+        v = (v & 0x33333333) + ((v >> 2) & 0x33333333)
+        let r = Int((   ((v + (v >> 4)) & 0xF0F0F0F)   &* 0x1010101) >> 24)
+        return (r+1)
+    }
+    /* this = -this mod Modulus */
+    func neg()
+    {
+        let m=BIG(FP.p);
+    
+        norm();
+        let sb=FP.logb2(UInt32(BIG.EXCESS(x)))
+ //       var ov=BIG.EXCESS(x);
+ //       var sb=1; while(ov != 0) {sb += 1;ov>>=1}
+    
+        m.fshl(sb)
+        x.rsub(m)
+    
+        if BIG.EXCESS(x)>=ROM.FEXCESS {reduce()}
+    }
+    /* this*=c mod Modulus, where c is a small int */
+    func imul(_ c: Int)
+    {
+        var cc=c
+        norm();
+        var s=false
+        if (cc<0)
+        {
+            cc = -cc
+            s=true
+        }
+        let afx=(BIG.EXCESS(x)+1)*(cc+1)+1;
+        if cc<ROM.NEXCESS && afx<ROM.FEXCESS
+        {
+            x.imul(cc);
+        }
+        else
+        {
+            if afx<ROM.FEXCESS {x.pmul(cc)}
+            else
+            {
+				let d=x.pxmul(cc);
+				x.copy(d.mod(FP.p));
+            }
+        }
+        if s {neg()}
+        norm();
+    }
+    
+/* this*=this mod Modulus */
+    func sqr()
+    {
+        norm()
+        let ea=BIG.EXCESS(x);
+        
+        if Int64(ea+1)*Int64(ea+1)>Int64(ROM.FEXCESS) {reduce()}
+        /*if (ea+1)>=(ROM.FEXCESS-1)/(ea+1) {reduce()}*/
+        
+        let d=BIG.sqr(x);
+        x.copy(BIG.mod(d));
+    }
+    
+    /* this+=b */
+    func add(_ b: FP)
+    {
+        x.add(b.x);
+        if BIG.EXCESS(x)+2>=ROM.FEXCESS {reduce()}
+    }
+/* this-=b */
+    func sub(_ b: FP)
+    {
+        let n=FP(b)
+        n.neg()
+        self.add(n)
+    }
+/* this/=2 mod Modulus */
+    func div2()
+    {
+        x.norm()
+        if (x.parity()==0)
+            {x.fshr(1)}
+        else
+        {
+            x.add(FP.p)
+            x.norm()
+            x.fshr(1)
+        }
+    }
+/* this=1/this mod Modulus */
+    func inverse()
+    {
+        let r=redc()
+        r.invmodp(FP.p)
+        x.copy(r)
+        nres()
+    }
+    
+/* return TRUE if this==a */
+    func equals(_ a: FP) -> Bool
+    {
+        a.reduce()
+        reduce()
+        if (BIG.comp(a.x,x)==0) {return true}
+        return false;
+    }
+/* return this^e mod Modulus */
+    func pow(_ e: BIG) -> FP
+    {
+        let r=FP(1)
+        e.norm()
+        x.norm()
+	let m=FP(self)
+        while (true)
+        {
+            let bt=e.parity()
+            e.fshr(1)
+            if bt==1 {r.mul(m)}
+            if e.iszilch() {break}
+            m.sqr();
+        }
+        r.x.mod(FP.p);
+        return r;
+    }
+/* return sqrt(this) mod Modulus */
+    func sqrt() -> FP
+    {
+        reduce();
+        let b=BIG(FP.p)
+        if (ROM.MOD8==5)
+        {
+            b.dec(5); b.norm(); b.shr(3)
+            let i=FP(self); i.x.shl(1)
+            let v=i.pow(b)
+            i.mul(v); i.mul(v)
+            i.x.dec(1)
+            let r=FP(self)
+            r.mul(v); r.mul(i)
+            r.reduce()
+            return r
+        }
+        else
+        {
+            b.inc(1); b.norm(); b.shr(2)
+            return pow(b)
+        }
+    }
+/* return jacobi symbol (this/Modulus) */
+    func jacobi() -> Int
+    {
+        let w=redc()
+        return w.jacobi(FP.p)
+    }
+    
+}
diff --git a/version22/swift/fp12.swift b/version22/swift/fp12.swift
new file mode 100644
index 0000000..8743677
--- /dev/null
+++ b/version22/swift/fp12.swift
@@ -0,0 +1,584 @@
+/*
+	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.
+*/
+
+//
+//  fp12.swift
+//
+//  Created by Michael Scott on 07/07/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+/* AMCL Fp^12 functions */
+/* FP12 elements are of the form a+i.b+i^2.c */
+
+final class FP12
+{
+    private final var a:FP4
+    private final var b:FP4
+    private final var c:FP4
+    
+    /* reduce all components of this mod Modulus */
+    func reduce()
+    {
+        a.reduce()
+        b.reduce()
+        c.reduce()
+    }
+    /* normalise all components of this */
+    func norm()
+    {
+        a.norm();
+        b.norm();
+        c.norm();
+    }
+    /* Constructors */
+    init(_ d:FP4)
+    {
+        a=FP4(d)
+        b=FP4(0)
+        c=FP4(0)
+    }
+    
+    init(_ d:Int)
+    {
+        a=FP4(d)
+        b=FP4(0)
+        c=FP4(0)
+    }
+    
+    init(_ d:FP4,_ e:FP4,_ f:FP4)
+    {
+        a=FP4(d)
+        b=FP4(e)
+        c=FP4(f)
+    }
+    
+    init(_ x:FP12)
+    {
+        a=FP4(x.a)
+        b=FP4(x.b)
+        c=FP4(x.c)
+    }
+    /* test x==0 ? */
+    func iszilch() -> Bool
+    {
+        reduce();
+        return a.iszilch() && b.iszilch() && c.iszilch()
+    }
+    /* test x==1 ? */
+    func isunity() -> Bool
+    {
+        let one=FP4(1)
+        return a.equals(one) && b.iszilch() && c.iszilch()
+    }
+    /* return 1 if x==y, else 0 */
+    func equals(_ x:FP12) -> Bool
+    {
+        return a.equals(x.a) && b.equals(x.b) && c.equals(x.c)
+    }
+    /* extract a from self */
+    func geta() -> FP4
+    {
+        return a
+    }
+    /* extract b */
+    func getb()  -> FP4
+    {
+        return b
+    }
+    /* extract c */
+    func getc() -> FP4
+    {
+        return c
+    }
+    /* copy self=x */
+    func copy(_ x:FP12)
+    {
+        a.copy(x.a)
+        b.copy(x.b)
+        c.copy(x.c)
+    }
+    /* set self=1 */
+    func one()
+    {
+        a.one()
+        b.zero()
+        c.zero()
+    }
+    /* self=conj(self) */
+    func conj()
+    {
+        a.conj()
+        b.nconj()
+        c.conj()
+    }
+    /* Granger-Scott Unitary Squaring */
+    func usqr()
+    {
+        let A=FP4(a)
+        let B=FP4(c)
+        let C=FP4(b)
+        let D=FP4(0)
+    
+        a.sqr()
+        D.copy(a); D.add(a)
+        a.add(D)
+    
+        a.norm()
+        A.nconj()
+    
+        A.add(A)
+        a.add(A)
+        B.sqr()
+        B.times_i()
+    
+        D.copy(B); D.add(B)
+        B.add(D)
+        B.norm()
+    
+        C.sqr()
+        D.copy(C); D.add(C)
+        C.add(D)
+        C.norm()
+    
+        b.conj()
+        b.add(b)
+        c.nconj()
+    
+        c.add(c)
+        b.add(B)
+        c.add(C)
+        reduce()
+    
+    }
+    /* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
+    func sqr()
+    {
+        let A=FP4(a)
+        let B=FP4(b)
+        let C=FP4(c)
+        let D=FP4(a)
+    
+        A.sqr()
+        B.mul(c)
+        B.add(B)
+        C.sqr()
+        D.mul(b)
+        D.add(D)
+
+        c.add(a)
+        c.add(b)
+        c.sqr()
+    
+        a.copy(A)
+    
+        A.add(B)
+        A.norm()
+        A.add(C)
+        A.add(D)
+        A.norm()
+    
+        A.neg()
+        B.times_i()
+        C.times_i()
+    
+        a.add(B)
+
+        b.copy(C); b.add(D)
+        c.add(A)
+    
+        norm()
+    }
+    
+    /* FP12 full multiplication this=this*y */
+    func mul(_ y:FP12)
+    {
+        let z0=FP4(a)
+        let z1=FP4(0)
+        let z2=FP4(b)
+        let z3=FP4(0)
+        let t0=FP4(a)
+        let t1=FP4(y.a)
+    
+        z0.mul(y.a)
+        z2.mul(y.b)
+    
+        t0.add(b)
+        t1.add(y.b)
+    
+        z1.copy(t0); z1.mul(t1)
+        t0.copy(b); t0.add(c)
+    
+        t1.copy(y.b); t1.add(y.c)
+        z3.copy(t0); z3.mul(t1)
+    
+        t0.copy(z0); t0.neg()
+        t1.copy(z2); t1.neg()
+    
+        z1.add(t0)
+        z1.norm()
+        b.copy(z1); b.add(t1)
+    
+        z3.add(t1)
+        z2.add(t0)
+    
+        t0.copy(a); t0.add(c)
+        t1.copy(y.a); t1.add(y.c)
+        t0.mul(t1)
+        z2.add(t0)
+    
+        t0.copy(c); t0.mul(y.c)
+        t1.copy(t0); t1.neg()
+    
+        z2.norm()
+        z3.norm()
+        b.norm()
+    
+        c.copy(z2); c.add(t1)
+        z3.add(t1)
+        t0.times_i()
+        b.add(t0)
+    
+        z3.times_i()
+        a.copy(z0); a.add(z3)
+    
+        norm()
+    }
+    
+    /* Special case of multiplication arises from special form of ATE pairing line function */
+    func smul(_ y:FP12)
+    {
+        let z0=FP4(a)
+        let z2=FP4(b)
+        let z3=FP4(b)
+        let t0=FP4(0)
+        let t1=FP4(y.a)
+    
+        z0.mul(y.a)
+        z2.pmul(y.b.real())
+        b.add(a)
+        t1.real().add(y.b.real())
+    
+        b.mul(t1)
+        z3.add(c)
+        z3.pmul(y.b.real())
+    
+        t0.copy(z0); t0.neg()
+        t1.copy(z2); t1.neg()
+    
+        b.add(t0)
+        b.norm()
+    
+        b.add(t1)
+        z3.add(t1)
+        z2.add(t0)
+    
+        t0.copy(a); t0.add(c)
+        t0.mul(y.a)
+        c.copy(z2); c.add(t0)
+    
+        z3.times_i()
+        a.copy(z0); a.add(z3)
+    
+        norm()
+    }
+    /* self=1/self */
+    func inverse()
+    {
+        let f0=FP4(a)
+        let f1=FP4(b)
+        let f2=FP4(a)
+        let f3=FP4(0)
+    
+        norm()
+        f0.sqr()
+        f1.mul(c)
+        f1.times_i()
+        f0.sub(f1)
+    
+        f1.copy(c); f1.sqr()
+        f1.times_i()
+        f2.mul(b)
+        f1.sub(f2)
+    
+        f2.copy(b); f2.sqr()
+        f3.copy(a); f3.mul(c)
+        f2.sub(f3)
+    
+        f3.copy(b); f3.mul(f2)
+        f3.times_i()
+        a.mul(f0)
+        f3.add(a)
+        c.mul(f1)
+        c.times_i()
+    
+        f3.add(c)
+        f3.inverse()
+        a.copy(f0); a.mul(f3)
+        b.copy(f1); b.mul(f3)
+        c.copy(f2); c.mul(f3)
+    }
+    
+    /* self=self^p using Frobenius */
+    func frob(_ f:FP2)
+    {
+        let f2=FP2(f)
+        let f3=FP2(f)
+    
+        f2.sqr()
+        f3.mul(f2)
+    
+        a.frob(f3)
+        b.frob(f3)
+        c.frob(f3)
+    
+        b.pmul(f)
+        c.pmul(f2)
+    }
+    
+    /* trace function */
+    func trace() -> FP4
+    {
+        let t=FP4(0)
+        t.copy(a)
+        t.imul(3)
+        t.reduce()
+        return t
+    }
+    /* convert from byte array to FP12 */
+    static func fromBytes(_ w:[UInt8]) -> FP12
+    {
+        let RM=Int(ROM.MODBYTES)
+        var t=[UInt8](repeating: 0,count: RM)
+    
+        for i in 0 ..< RM {t[i]=w[i]}
+        var a=BIG.fromBytes(t)
+        for i in 0 ..< RM {t[i]=w[i+RM]}
+        var b=BIG.fromBytes(t)
+        var c=FP2(a,b)
+    
+        for i in 0 ..< RM {t[i]=w[i+2*RM]}
+        a=BIG.fromBytes(t)
+        for i in 0 ..< RM {t[i]=w[i+3*RM]}
+        b=BIG.fromBytes(t)
+        var d=FP2(a,b)
+    
+        let e=FP4(c,d)
+    
+        for i in 0 ..< RM {t[i]=w[i+4*RM]}
+        a=BIG.fromBytes(t)
+        for i in 0 ..< RM {t[i]=w[i+5*RM]}
+        b=BIG.fromBytes(t)
+        c=FP2(a,b)
+    
+        for i in 0 ..< RM {t[i]=w[i+6*RM]}
+        a=BIG.fromBytes(t)
+        for i in 0 ..< RM {t[i]=w[i+7*RM]}
+        b=BIG.fromBytes(t)
+        d=FP2(a,b)
+    
+        let f=FP4(c,d)
+    
+    
+        for i in 0 ..< RM {t[i]=w[i+8*RM]}
+        a=BIG.fromBytes(t)
+        for i in 0 ..< RM {t[i]=w[i+9*RM]}
+        b=BIG.fromBytes(t)
+        c=FP2(a,b)
+    
+        for i in 0 ..< RM {t[i]=w[i+10*RM]}
+        a=BIG.fromBytes(t)
+        for i in 0 ..< RM {t[i]=w[i+11*RM]}
+        b=BIG.fromBytes(t);
+        d=FP2(a,b)
+    
+        let g=FP4(c,d)
+    
+        return FP12(e,f,g)
+    }
+    
+    /* convert this to byte array */
+    func toBytes(_ w:inout [UInt8])
+    {
+        let RM=Int(ROM.MODBYTES)
+        var t=[UInt8](repeating: 0,count: RM)
+
+        a.geta().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i]=t[i]}
+        a.geta().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+RM]=t[i]}
+        a.getb().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+2*RM]=t[i]}
+        a.getb().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+3*RM]=t[i]}
+    
+        b.geta().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+4*RM]=t[i]}
+        b.geta().getB().toBytes(&t);
+        for i in 0 ..< RM {w[i+5*RM]=t[i]}
+        b.getb().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+6*RM]=t[i]}
+        b.getb().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+7*RM]=t[i]}
+    
+        c.geta().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+8*RM]=t[i]}
+        c.geta().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+9*RM]=t[i]}
+        c.getb().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+10*RM]=t[i]}
+        c.getb().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+11*RM]=t[i]}
+    }
+    /* convert to hex string */
+    func toString() -> String
+    {
+        return ("["+a.toString()+","+b.toString()+","+c.toString()+"]")
+    }
+    
+    /* self=self^e */
+    /* Note this is simple square and multiply, so not side-channel safe */
+    func pow(_ e:BIG) -> FP12
+    {
+        norm()
+        e.norm()
+        let w=FP12(self)
+        let z=BIG(e)
+        let r=FP12(1)
+    
+        while (true)
+        {
+            let bt=z.parity()
+            z.fshr(1)
+            if bt==1 {r.mul(w)}
+            if z.iszilch() {break}
+            w.usqr()
+        }
+        r.reduce()
+        return r
+    }
+    /* constant time powering by small integer of max length bts */
+    func pinpow(_ e:Int32,_ bts:Int32)
+    {
+        var R=[FP12]()
+        R.append(FP12(1));
+        R.append(FP12(self));
+
+        //for var i=bts-1;i>=0;i--
+        for i in (0...bts-1).reversed()
+        {
+            let b=Int((e>>i)&1)
+            R[1-b].mul(R[b])
+            R[b].usqr()
+        }
+        copy(R[0]);
+    }
+    
+    /* p=q0^u0.q1^u1.q2^u2.q3^u3 */
+    /* Timing attack secure, but not cache attack secure */
+    
+    static func pow4(_ q:[FP12],_ u:[BIG]) -> FP12
+    {
+        var a=[Int32](repeating: 0,count: 4)
+        var g=[FP12]();
+        
+        for _ in 0 ..< 8 {g.append(FP12(0))}
+        var s=[FP12]();
+        for _ in 0 ..< 2 {s.append(FP12(0))}
+        
+        let c=FP12(1)
+        let p=FP12(0)
+        
+        var t=[BIG]()
+        for i in 0 ..< 4
+            {t.append(BIG(u[i]))}
+        
+        let mt=BIG(0);
+        var w=[Int8](repeating: 0,count: ROM.NLEN*Int(ROM.BASEBITS)+1)
+    
+        g[0].copy(q[0]); s[0].copy(q[1]); s[0].conj(); g[0].mul(s[0])
+        g[1].copy(g[0])
+        g[2].copy(g[0])
+        g[3].copy(g[0])
+        g[4].copy(q[0]); g[4].mul(q[1])
+        g[5].copy(g[4])
+        g[6].copy(g[4])
+        g[7].copy(g[4])
+    
+        s[1].copy(q[2]); s[0].copy(q[3]); s[0].conj(); s[1].mul(s[0])
+        s[0].copy(s[1]); s[0].conj(); g[1].mul(s[0])
+        g[2].mul(s[1])
+        g[5].mul(s[0])
+        g[6].mul(s[1])
+        s[1].copy(q[2]); s[1].mul(q[3])
+        s[0].copy(s[1]); s[0].conj(); g[0].mul(s[0])
+        g[3].mul(s[1])
+        g[4].mul(s[0])
+        g[7].mul(s[1])
+
+    /* if power is even add 1 to power, and add q to correction */
+    
+        for i in 0 ..< 4
+        {
+            if t[i].parity()==0
+            {
+				t[i].inc(1); t[i].norm()
+				c.mul(q[i])
+            }
+            mt.add(t[i]); mt.norm()
+        }
+        c.conj();
+        let nb=1+mt.nbits();
+    
+    /* convert exponent to signed 1-bit window */
+        for j in 0 ..< nb
+        {
+            for i in 0 ..< 4
+            {
+				a[i]=Int32(t[i].lastbits(2)-2)
+				t[i].dec(Int(a[i]));
+                t[i].norm()
+				t[i].fshr(1)
+            }
+            w[j]=Int8(8*a[0]+4*a[1]+2*a[2]+a[3])
+        }
+        w[nb]=Int8(8*t[0].lastbits(2)+4*t[1].lastbits(2))
+        w[nb]+=Int8(2*t[2].lastbits(2)+t[3].lastbits(2))
+        p.copy(g[Int(w[nb]-1)/2])
+    
+        //for var i=nb-1;i>=0;i--
+        for i in (0...nb-1).reversed()
+        {
+            let m=w[i]>>7
+            let j=(w[i]^m)-m  /* j=abs(w[i]) */
+            let k=Int((j-1)/2)
+            s[0].copy(g[k]); s[1].copy(g[k]); s[1].conj()
+            p.usqr()
+            p.mul(s[Int(m&1)])
+        }
+        p.mul(c)  /* apply correction */
+        p.reduce()
+        return p
+    }
+    
+    
+    
+    
+
+}
diff --git a/version22/swift/fp2.swift b/version22/swift/fp2.swift
new file mode 100644
index 0000000..cdc1711
--- /dev/null
+++ b/version22/swift/fp2.swift
@@ -0,0 +1,329 @@
+/*
+	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.
+*/
+
+//
+//  fp2.swift
+//
+//  Created by Michael Scott on 07/07/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+/* Finite Field arithmetic  Fp^2 functions */
+
+/* FP2 elements are of the form a+ib, where i is sqrt(-1) */
+
+
+final class FP2
+{
+    private var a:FP
+    private var b:FP
+
+    /* Constructors */
+    init(_ c: Int)
+    {
+        a=FP(c)
+        b=FP(0)
+    }
+    
+    init(_ x:FP2)
+    {
+        a=FP(x.a)
+        b=FP(x.b)
+    }
+
+    init(_ c:FP,_ d:FP)
+    {
+        a=FP(c)
+        b=FP(d)
+    }
+    
+    init(_ c:BIG,_ d:BIG)
+    {
+        a=FP(c)
+        b=FP(d)
+    }
+
+    init(_ c:FP)
+    {
+        a=FP(c)
+        b=FP(0)
+    }
+    
+    init(_ c:BIG)
+    {
+        a=FP(c)
+        b=FP(0)
+    }
+
+    /* test this=0 ? */
+    func iszilch() -> Bool
+    {
+        reduce()
+        return (a.iszilch() && b.iszilch())
+    }
+    
+    func cmove(_ g:FP2,_ d:Int)
+    {
+        a.cmove(g.a,d)
+        b.cmove(g.b,d)
+    }
+
+    /* test this=1 ? */
+    func isunity() -> Bool
+    {
+        let one=FP(1)
+        return (a.equals(one) && b.iszilch())
+    }
+    
+    /* test this=x */
+    func equals(_ x:FP2) -> Bool
+    {
+        return (a.equals(x.a) && b.equals(x.b));
+    }
+    
+    
+    /* reduce components mod Modulus */
+    func reduce()
+    {
+        a.reduce()
+        b.reduce()
+    }
+    
+    /* normalise components of w */
+    func norm()
+    {
+        a.norm()
+        b.norm()
+    }
+    
+    /* extract a */
+    func getA() -> BIG
+    {
+        return a.redc()
+    }
+    
+    /* extract b */
+    func getB() -> BIG
+    {
+        return b.redc()
+    }
+
+    /* copy self=x */
+    func copy(_ x:FP2)
+    {
+        a.copy(x.a)
+        b.copy(x.b)
+    }
+    
+    /* set self=0 */
+    func zero()
+    {
+        a.zero()
+        b.zero()
+    }
+    
+    /* set self=1 */
+    func one()
+    {
+        a.one()
+        b.zero()
+    }
+    
+    /* negate self mod Modulus */
+    func neg()
+    {
+        norm();
+        let m=FP(a)
+        let t=FP(0)
+    
+        m.add(b)
+        m.neg()
+        m.norm()
+        t.copy(m); t.add(b)
+        b.copy(m)
+        b.add(a)
+        a.copy(t)
+    }
+    
+    /* set to a-ib */
+    func conj()
+    {
+        b.neg()
+    }
+
+    /* self+=a */
+    func add(_ x:FP2)
+    {
+        a.add(x.a)
+        b.add(x.b)
+    }
+    
+    /* self-=a */
+    func sub(_ x:FP2)
+    {
+        let m=FP2(x)
+        m.neg()
+        add(m)
+    }
+
+    /* self*=s, where s is an FP */
+    func pmul(_ s:FP)
+    {
+        a.mul(s)
+        b.mul(s)
+    }
+    
+    /* self*=i, where i is an int */
+    func imul(_ c:Int)
+    {
+        a.imul(c);
+        b.imul(c);
+    }
+    
+    /* self*=self */
+    func sqr()
+    {
+        norm();
+    
+        let w1=FP(a)
+        let w3=FP(a)
+        let mb=FP(b)
+        w3.mul(b)
+        w1.add(b)
+        mb.neg()
+        a.add(mb)
+        a.mul(w1)
+        b.copy(w3); b.add(w3)
+        norm()
+    }
+    /* self*=y */
+    func mul(_ y:FP2)
+    {
+        norm();  /* This is needed here as {a,b} is not normed before additions */
+    
+        let w1=FP(a)
+        let w2=FP(b)
+        let w5=FP(a)
+        let mw=FP(0)
+    
+        w1.mul(y.a)  // w1=a*y.a  - this norms w1 and y.a, NOT a
+        w2.mul(y.b)  // w2=b*y.b  - this norms w2 and y.b, NOT b
+        w5.add(b)    // w5=a+b
+        b.copy(y.a); b.add(y.b) // b=y.a+y.b
+    
+        b.mul(w5)
+        mw.copy(w1); mw.add(w2); mw.neg()
+    
+        b.add(mw); mw.add(w1)
+        a.copy(w1);	a.add(mw)
+    
+        norm()
+    
+    }
+ 
+    /* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */
+    /* returns true if this is QR */
+    func sqrt() -> Bool
+    {
+        if iszilch() {return true}
+        var w1=FP(b)
+        var w2=FP(a)
+        w1.sqr(); w2.sqr(); w1.add(w2)
+        if w1.jacobi() != 1 { zero(); return false; }
+        w1=w1.sqrt()
+        w2.copy(a); w2.add(w1); w2.div2()
+        if w2.jacobi() != 1
+        {
+            w2.copy(a); w2.sub(w1); w2.div2()
+            if w2.jacobi() != 1 { zero(); return false }
+        }
+        w2=w2.sqrt()
+        a.copy(w2)
+        w2.add(w2)
+        w2.inverse()
+        b.mul(w2)
+        return true
+    }
+    /* output to hex string */
+    func toString() -> String
+    {
+        return ("["+a.toString()+","+b.toString()+"]")
+    }
+    
+    func toRawString() -> String
+    {
+        return ("["+a.toRawString()+","+b.toRawString()+"]")
+    }
+
+    /* self=1/self */
+    func inverse()
+    {
+        norm();
+        let w1=FP(a)
+        let w2=FP(b)
+    
+        w1.sqr()
+        w2.sqr()
+        w1.add(w2)
+        w1.inverse()
+        a.mul(w1)
+        w1.neg()
+        b.mul(w1)
+    }
+
+    /* self/=2 */
+    func div2()
+    {
+        a.div2();
+        b.div2();
+    }
+    
+    /* self*=sqrt(-1) */
+    func times_i()
+    {
+        let z=FP(a)
+        a.copy(b); a.neg()
+        b.copy(z)
+    }
+
+    /* w*=(1+sqrt(-1)) */
+    /* where X*2-(1+sqrt(-1)) is irreducible for FP4, assumes p=3 mod 8 */
+    func mul_ip()
+    {
+        norm();
+        let t=FP2(self)
+        let z=FP(a)
+        a.copy(b)
+        a.neg()
+        b.copy(z)
+        add(t)
+        norm()
+    }
+    /* w/=(1+sqrt(-1)) */
+    func div_ip()
+    {
+        let t=FP2(0)
+        norm()
+        t.a.copy(a); t.a.add(b)
+        t.b.copy(b); t.b.sub(a)
+        copy(t)
+        div2()
+    }
+    
+}
diff --git a/version22/swift/fp4.swift b/version22/swift/fp4.swift
new file mode 100644
index 0000000..3cba394
--- /dev/null
+++ b/version22/swift/fp4.swift
@@ -0,0 +1,517 @@
+/*
+	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.
+*/
+
+//
+//  fp4.swift
+//
+//  Created by Michael Scott on 07/07/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+/* Finite Field arithmetic  Fp^4 functions */
+
+/* FP4 elements are of the form a+ib, where i is sqrt(-1+sqrt(-1))  */
+
+final class FP4 {
+    private final var a:FP2
+    private final var b:FP2
+
+    /* constructors */
+    init(_ c:Int)
+    {
+        a=FP2(c)
+        b=FP2(0)
+    }
+    
+    init(_ x:FP4)
+    {
+        a=FP2(x.a)
+        b=FP2(x.b)
+    }
+    
+    init(_ c:FP2,_ d:FP2)
+    {
+        a=FP2(c)
+        b=FP2(d)
+    }
+    
+    init(_ c:FP2)
+    {
+        a=FP2(c)
+        b=FP2(0)
+    }
+    /* reduce all components of this mod Modulus */
+    func reduce()
+    {
+        a.reduce()
+        b.reduce()
+    }
+    /* normalise all components of this mod Modulus */
+    func norm()
+    {
+        a.norm()
+        b.norm()
+    }
+    /* test this==0 ? */
+    func iszilch() -> Bool
+    {
+        reduce()
+        return a.iszilch() && b.iszilch()
+    }
+    /* test this==1 ? */
+    func isunity() -> Bool
+    {
+    let one=FP2(1);
+    return a.equals(one) && b.iszilch()
+    }
+    
+    /* test is w real? That is in a+ib test b is zero */
+    func isreal() -> Bool
+    {
+        return b.iszilch();
+    }
+    /* extract real part a */
+    func real() -> FP2
+    {
+        return a;
+    }
+    
+    func geta() -> FP2
+    {
+        return a;
+    }
+    /* extract imaginary part b */
+    func getb() -> FP2
+    {
+    return b;
+    }
+    /* test self=x? */
+    func equals(_ x:FP4) -> Bool
+    {
+        return a.equals(x.a) && b.equals(x.b)
+    }
+    /* copy self=x */
+    func copy(_ x:FP4)
+    {
+        a.copy(x.a)
+        b.copy(x.b)
+    }
+    /* set this=0 */
+    func zero()
+    {
+        a.zero()
+        b.zero()
+    }
+    /* set this=1 */
+    func one()
+    {
+        a.one()
+        b.zero()
+    }
+    /* set self=-self */
+    func neg()
+    {
+        let m=FP2(a)
+        let t=FP2(0)
+        m.add(b)
+        m.neg()
+        m.norm()
+        t.copy(m); t.add(b)
+        b.copy(m)
+        b.add(a)
+        a.copy(t)
+    }
+    /* self=conjugate(self) */
+    func conj()
+    {
+        b.neg(); b.norm()
+    }
+    /* this=-conjugate(this) */
+    func nconj()
+    {
+        a.neg(); a.norm()
+    }
+    /* self+=x */
+    func add(_ x:FP4)
+    {
+        a.add(x.a)
+        b.add(x.b)
+    }
+    /* self-=x */
+    func sub(_ x:FP4)
+    {
+        let m=FP4(x)
+        m.neg()
+        add(m)
+    }
+    
+    /* self*=s where s is FP2 */
+    func pmul(_ s:FP2)
+    {
+        a.mul(s)
+        b.mul(s)
+    }
+    /* self*=c where c is int */
+    func imul(_ c:Int)
+    {
+        a.imul(c)
+        b.imul(c)
+    }
+    /* self*=self */
+    func sqr()
+    {
+        norm();
+    
+        let t1=FP2(a)
+        let t2=FP2(b)
+        let t3=FP2(a)
+    
+        t3.mul(b)
+        t1.add(b)
+        t2.mul_ip()
+    
+        t2.add(a)
+        a.copy(t1)
+    
+        a.mul(t2)
+    
+        t2.copy(t3)
+        t2.mul_ip()
+        t2.add(t3)
+        t2.neg()
+        a.add(t2)
+    
+        b.copy(t3)
+        b.add(t3)
+    
+        norm()
+    }
+    /* self*=y */
+    func mul(_ y:FP4)
+    {
+        norm();
+    
+        let t1=FP2(a)
+        let t2=FP2(b)
+        let t3=FP2(0)
+        let t4=FP2(b)
+    
+        t1.mul(y.a)
+        t2.mul(y.b)
+        t3.copy(y.b)
+        t3.add(y.a)
+        t4.add(a)
+    
+        t4.mul(t3)
+        t4.sub(t1)
+        t4.norm()
+    
+        b.copy(t4)
+        b.sub(t2)
+        t2.mul_ip()
+        a.copy(t2)
+        a.add(t1)
+    
+        norm()
+    }
+    /* convert this to hex string */
+    func toString() -> String
+    {
+        return ("["+a.toString()+","+b.toString()+"]")
+    }
+    
+    func toRawString() -> String
+    {
+        return ("["+a.toRawString()+","+b.toRawString()+"]")
+    }
+    /* self=1/self */
+    func inverse()
+    {
+        norm();
+    
+        let t1=FP2(a)
+        let t2=FP2(b)
+    
+        t1.sqr()
+        t2.sqr()
+        t2.mul_ip()
+        t1.sub(t2)
+        t1.inverse()
+        a.mul(t1)
+        t1.neg()
+        b.mul(t1)
+    }
+    
+    /* self*=i where i = sqrt(-1+sqrt(-1)) */
+    func times_i()
+    {
+        norm();
+        let s=FP2(b)
+        let t=FP2(b)
+        s.times_i()
+        t.add(s)
+        t.norm()
+        b.copy(a)
+        a.copy(t)
+    }
+    
+    /* self=self^p using Frobenius */
+    func frob(_ f:FP2)
+    {
+        a.conj()
+        b.conj()
+        b.mul(f)
+    }
+    /* self=self^e */
+    func pow(_ e:BIG) -> FP4
+    {
+        norm()
+        e.norm()
+        let w=FP4(self)
+        let z=BIG(e)
+        let r=FP4(1)
+        while (true)
+        {
+            let bt=z.parity()
+            z.fshr(1)
+            if bt==1 {r.mul(w)}
+            if z.iszilch() {break}
+            w.sqr()
+        }
+        r.reduce()
+        return r
+    }
+    /* XTR xtr_a function */
+    func xtr_A(_ w:FP4,_ y:FP4,_ z:FP4)
+    {
+        let r=FP4(w)
+        let t=FP4(w)
+        r.sub(y)
+        r.pmul(a)
+        t.add(y)
+        t.pmul(b)
+        t.times_i()
+    
+        copy(r)
+        add(t)
+        add(z)
+    
+        norm()
+    }
+    /* XTR xtr_d function */
+    func xtr_D()
+    {
+        let w=FP4(self)
+        sqr(); w.conj()
+        w.add(w)
+        sub(w)
+        reduce()
+    }
+    /* r=x^n using XTR method on traces of FP12s */
+    func xtr_pow(_ n:BIG) -> FP4
+    {
+        let a=FP4(3)
+        let b=FP4(self)
+        let c=FP4(b)
+        c.xtr_D()
+        let t=FP4(0)
+        let r=FP4(0)
+    
+        n.norm();
+        let par=n.parity()
+        let v=BIG(n); v.fshr(1)
+        if par==0 {v.dec(1); v.norm()}
+    
+        let nb=v.nbits()
+        //for i in (0...nb-1).reverse()
+        var i=nb-1
+        //for var i=nb-1;i>=0;i--
+        while i>=0
+        {
+            if (v.bit(UInt(i)) != 1)
+            {
+				t.copy(b)
+				conj()
+				c.conj()
+				b.xtr_A(a,self,c)
+				conj()
+				c.copy(t)
+				c.xtr_D()
+				a.xtr_D()
+            }
+            else
+            {
+				t.copy(a); t.conj()
+				a.copy(b)
+				a.xtr_D()
+				b.xtr_A(c,self,t)
+				c.xtr_D()
+            }
+            i-=1
+        }
+        if par==0 {r.copy(c)}
+        else {r.copy(b)}
+        r.reduce()
+        return r
+    }
+    
+    /* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */
+    func xtr_pow2(_ ck:FP4,_ ckml:FP4,_ ckm2l:FP4,_ a:BIG,_ b:BIG) -> FP4
+    {
+        a.norm(); b.norm()
+        let e=BIG(a)
+        let d=BIG(b)
+        let w=BIG(0)
+    
+        let cu=FP4(ck)  // can probably be passed in w/o copying
+        let cv=FP4(self)
+        let cumv=FP4(ckml)
+        let cum2v=FP4(ckm2l)
+        var r=FP4(0)
+        let t=FP4(0)
+    
+        var f2:Int=0
+        while d.parity()==0 && e.parity()==0
+        {
+            d.fshr(1);
+            e.fshr(1);
+            f2 += 1;
+        }
+    
+        while (BIG.comp(d,e) != 0)
+        {
+            if BIG.comp(d,e)>0
+            {
+				w.copy(e); w.imul(4); w.norm()
+				if BIG.comp(d,w)<=0
+				{
+                    w.copy(d); d.copy(e)
+                    e.rsub(w); e.norm()
+    
+                    t.copy(cv)
+                    t.xtr_A(cu,cumv,cum2v)
+                    cum2v.copy(cumv)
+                    cum2v.conj()
+                    cumv.copy(cv)
+                    cv.copy(cu)
+                    cu.copy(t)
+    
+				}
+				else if d.parity()==0
+				{
+                    d.fshr(1)
+                    r.copy(cum2v); r.conj()
+                    t.copy(cumv)
+                    t.xtr_A(cu,cv,r)
+                    cum2v.copy(cumv)
+                    cum2v.xtr_D()
+                    cumv.copy(t)
+                    cu.xtr_D()
+				}
+				else if e.parity()==1
+				{
+                    d.sub(e); d.norm()
+                    d.fshr(1)
+                    t.copy(cv)
+                    t.xtr_A(cu,cumv,cum2v)
+                    cu.xtr_D()
+                    cum2v.copy(cv)
+                    cum2v.xtr_D()
+                    cum2v.conj()
+                    cv.copy(t)
+				}
+				else
+				{
+                    w.copy(d)
+                    d.copy(e); d.fshr(1)
+                    e.copy(w)
+                    t.copy(cumv)
+                    t.xtr_D()
+                    cumv.copy(cum2v); cumv.conj()
+                    cum2v.copy(t); cum2v.conj()
+                    t.copy(cv)
+                    t.xtr_D()
+                    cv.copy(cu)
+                    cu.copy(t)
+				}
+            }
+            if BIG.comp(d,e)<0
+            {
+				w.copy(d); w.imul(4); w.norm()
+				if BIG.comp(e,w)<=0
+				{
+                    e.sub(d); e.norm()
+                    t.copy(cv)
+                    t.xtr_A(cu,cumv,cum2v)
+                    cum2v.copy(cumv)
+                    cumv.copy(cu)
+                    cu.copy(t)
+				}
+				else if e.parity()==0
+				{
+                    w.copy(d)
+                    d.copy(e); d.fshr(1)
+                    e.copy(w)
+                    t.copy(cumv)
+                    t.xtr_D()
+                    cumv.copy(cum2v); cumv.conj()
+                    cum2v.copy(t); cum2v.conj()
+                    t.copy(cv)
+                    t.xtr_D()
+                    cv.copy(cu)
+                    cu.copy(t)
+				}
+				else if d.parity()==1
+				{
+                    w.copy(e)
+                    e.copy(d)
+                    w.sub(d); w.norm()
+                    d.copy(w); d.fshr(1)
+                    t.copy(cv)
+                    t.xtr_A(cu,cumv,cum2v)
+                    cumv.conj()
+                    cum2v.copy(cu)
+                    cum2v.xtr_D()
+                    cum2v.conj()
+                    cu.copy(cv)
+                    cu.xtr_D()
+                    cv.copy(t)
+				}
+				else
+				{
+                    d.fshr(1)
+                    r.copy(cum2v); r.conj()
+                    t.copy(cumv)
+                    t.xtr_A(cu,cv,r)
+                    cum2v.copy(cumv)
+                    cum2v.xtr_D()
+                    cumv.copy(t)
+                    cu.xtr_D()
+				}
+            }
+        }
+        r.copy(cv)
+        r.xtr_A(cu,cumv,cum2v)
+        for _ in 0 ..< f2
+            {r.xtr_D()}
+        r=r.xtr_pow(d)
+        return r
+    }
+    
+}
diff --git a/version22/swift/gcm.swift b/version22/swift/gcm.swift
new file mode 100644
index 0000000..15a6657
--- /dev/null
+++ b/version22/swift/gcm.swift
@@ -0,0 +1,326 @@
+/*
+	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.
+*/
+
+//
+//  gcm.swift
+//
+//  Created by Michael Scott on 23/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+import Foundation
+
+/*
+* Implementation of the AES-GCM Encryption/Authentication
+*
+* Some restrictions..
+* 1. Only for use with AES
+* 2. Returned tag is always 128-bits. Truncate at your own risk.
+* 3. The order of function calls must follow some rules
+*
+* Typical sequence of calls..
+* 1. call GCM_init
+* 2. call GCM_add_header any number of times, as long as length of header is multiple of 16 bytes (block size)
+* 3. call GCM_add_header one last time with any length of header
+* 4. call GCM_add_cipher any number of times, as long as length of cipher/plaintext is multiple of 16 bytes
+* 5. call GCM_add_cipher one last time with any length of cipher/plaintext
+* 6. call GCM_finish to extract the tag.
+*
+* See http://www.mindspring.com/~dmcgrew/gcm-nist-6.pdf
+*/
+
+final class GCM {
+    static let NB:Int=4
+    static let GCM_ACCEPTING_HEADER:Int=0
+    static let GCM_ACCEPTING_CIPHER:Int=1
+    static let GCM_NOT_ACCEPTING_MORE:Int=2
+    static let GCM_FINISHED:Int=3
+    static let GCM_ENCRYPTING:Int=0
+    static let GCM_DECRYPTING:Int=1
+    
+    private var table=[[UInt32]](repeating: [UInt32](repeating: 0,count: 4),count: 128) /* 2k bytes */
+    private var stateX=[UInt8](repeating: 0,count: 16)
+    private var Y_0=[UInt8](repeating: 0,count: 16)
+    
+    private var counter:Int=0
+    private var lenA=[UInt32](repeating: 0,count: 2)
+    private var lenC=[UInt32](repeating: 0,count: 2)
+    private var status:Int=0
+    private var a=AES()
+    
+    private static func pack(_ b: [UInt8]) -> UInt32
+    { /* pack bytes into a 32-bit Word */
+        var r=((UInt32(b[0])&0xff)<<24)|((UInt32(b[1])&0xff)<<16)
+        r = r|((UInt32(b[2])&0xff)<<8)|(UInt32(b[3])&0xff)
+        return r
+    }
+    
+    private static func unpack(_ a: UInt32) -> [UInt8]
+    { /* unpack bytes from a word */
+        let b:[UInt8]=[UInt8((a>>24)&0xff),UInt8((a>>16)&0xff),UInt8((a>>8)&0xff),UInt8(a&0xff)];
+        return b
+    }
+    
+    private func precompute(_ H: [UInt8])
+    {
+        var b=[UInt8](repeating: 0,count: 4)
+        var j=0
+        for i in 0 ..< GCM.NB
+        {
+            b[0]=H[j]; b[1]=H[j+1]; b[2]=H[j+2]; b[3]=H[j+3];
+            table[0][i]=GCM.pack(b);
+            j+=4
+        }
+        for i in 1 ..< 128
+        {
+            var c:UInt32=0
+            for j in 0 ..< GCM.NB {table[i][j]=c|(table[i-1][j])>>1; c=table[i-1][j]<<31;}
+            if c != 0  {table[i][0]^=0xE1000000} /* irreducible polynomial */
+        }
+    }
+ 
+    private func gf2mul()
+    { /* gf2m mul - Z=H*X mod 2^128 */
+        var P=[UInt32](repeating: 0,count: 4)
+    
+        for i in 0 ..< 4 {P[i]=0}
+        var j=8; var m=0;
+        for i in 0 ..< 128
+        {
+            j-=1
+            var c=UInt32((stateX[m]>>UInt8(j))&1); c = ( ~c ) + 1
+            for k in 0 ..< GCM.NB {P[k]^=(table[i][k] & c)}
+            if (j==0)
+            {
+		j=8; m += 1;
+                if (m==16) {break}
+            }
+        }
+        j=0
+        for i in 0 ..< GCM.NB
+        {
+            var b=GCM.unpack(P[i])
+            stateX[j]=b[0]; stateX[j+1]=b[1]; stateX[j+2]=b[2]; stateX[j+3]=b[3];
+            j+=4
+        }
+    }
+    private func wrap()
+    { /* Finish off GHASH */
+        var F=[UInt32](repeating: 0,count: 4)
+        var L=[UInt8](repeating: 0,count: 16)
+    
+    /* convert lengths from bytes to bits */
+        F[0]=(lenA[0]<<3)|(lenA[1]&0xE0000000)>>29
+        F[1]=lenA[1]<<3;
+        F[2]=(lenC[0]<<3)|(lenC[1]&0xE0000000)>>29
+        F[3]=lenC[1]<<3;
+        var j=0
+        for i in 0 ..< GCM.NB
+        {
+            var b=GCM.unpack(F[i]);
+            L[j]=b[0]; L[j+1]=b[1]; L[j+2]=b[2]; L[j+3]=b[3]
+            j+=4
+        }
+        for i in 0 ..< 16 {stateX[i]^=L[i]}
+        gf2mul()
+    }
+    
+    private func ghash(_ plain: [UInt8],_ len: Int) -> Bool
+    {
+    //    var B=[UInt8](count:16,repeatedValue:0)
+    
+        if status==GCM.GCM_ACCEPTING_HEADER {status=GCM.GCM_ACCEPTING_CIPHER}
+        if (status != GCM.GCM_ACCEPTING_CIPHER) {return false}
+        
+        var j=0;
+        while (j<len)
+        {
+            for i in 0 ..< 16
+            {
+				stateX[i]^=plain[j];
+                j+=1;
+                lenC[1]+=1; if lenC[1]==0 {lenC[0]+=1}
+                if j>=len {break;}
+            }
+            gf2mul();
+        }
+        if len%16 != 0 {status=GCM.GCM_NOT_ACCEPTING_MORE}
+        return true;
+    }
+    
+    /* Initialize GCM mode */
+    func init_it(_ key: [UInt8],_ niv: Int,_ iv: [UInt8])
+    { /* iv size niv is usually 12 bytes (96 bits). AES key size nk can be 16,24 or 32 bytes */
+        var H=[UInt8](repeating: 0,count: 16)
+        
+        for i in 0 ..< 16 {H[i]=0; stateX[i]=0}
+        
+        a.init_it(AES.ECB,key,iv)
+        a.ecb_encrypt(&H);    /* E(K,0) */
+        precompute(H)
+        
+        lenA[0]=0;lenC[0]=0;lenA[1]=0;lenC[1]=0;
+        if (niv==12)
+        {
+            for i in 0 ..< 12 {a.f[i]=iv[i]}
+            var b=GCM.unpack(UInt32(1))
+            a.f[12]=b[0]; a.f[13]=b[1]; a.f[14]=b[2]; a.f[15]=b[3];  /* initialise IV */
+            for i in 0 ..< 16 {Y_0[i]=a.f[i]}
+        }
+        else
+        {
+            status=GCM.GCM_ACCEPTING_CIPHER;
+            ghash(iv,niv) /* GHASH(H,0,IV) */
+            wrap()
+            for i in 0 ..< 16 {a.f[i]=stateX[i];Y_0[i]=a.f[i];stateX[i]=0}
+            lenA[0]=0;lenC[0]=0;lenA[1]=0;lenC[1]=0;
+        }
+        status=GCM.GCM_ACCEPTING_HEADER;
+    }
+    
+    /* Add Header data - included but not encrypted */
+    func add_header(_ header: [UInt8],_ len: Int) -> Bool
+    { /* Add some header. Won't be encrypted, but will be authenticated. len is length of header */
+        if status != GCM.GCM_ACCEPTING_HEADER {return false}
+    
+        var j=0
+        while (j<len)
+        {
+            for i in 0 ..< 16
+            {
+				stateX[i]^=header[j];
+                j+=1;
+                lenA[1]+=1; if lenA[1]==0 {lenA[0]+=1}
+                if j>=len {break}
+            }
+            gf2mul();
+        }
+        if len%16 != 0 {status=GCM.GCM_ACCEPTING_CIPHER}
+        return true;
+    }
+    /* Add Plaintext - included and encrypted */
+    func add_plain(_ plain: [UInt8],_ len: Int) -> [UInt8]
+    {
+        var B=[UInt8](repeating: 0,count: 16)
+        var b=[UInt8](repeating: 0,count: 4)
+        
+        var cipher=[UInt8](repeating: 0,count: len)
+        var counter:UInt32=0
+        if status == GCM.GCM_ACCEPTING_HEADER {status=GCM.GCM_ACCEPTING_CIPHER}
+        if status != GCM.GCM_ACCEPTING_CIPHER {return [UInt8]()}
+        
+        var j=0
+        while (j<len)
+        {
+    
+            b[0]=a.f[12]; b[1]=a.f[13]; b[2]=a.f[14]; b[3]=a.f[15];
+            counter=GCM.pack(b);
+            counter+=1;
+            b=GCM.unpack(counter);
+            a.f[12]=b[0]; a.f[13]=b[1]; a.f[14]=b[2]; a.f[15]=b[3]; /* increment counter */
+            for i in 0 ..< 16 {B[i]=a.f[i]}
+            a.ecb_encrypt(&B);        /* encrypt it  */
+    
+            for i in 0 ..< 16
+            {
+		cipher[j]=(plain[j]^B[i]);
+		stateX[i]^=cipher[j];
+                j+=1;
+                lenC[1]+=1; if lenC[1]==0 {lenC[0]+=1}
+                if j>=len {break}
+            }
+            gf2mul();
+        }
+        if len%16 != 0 {status=GCM.GCM_NOT_ACCEPTING_MORE}
+        return cipher;
+    }
+    /* Add Ciphertext - decrypts to plaintext */
+    func add_cipher(_ cipher: [UInt8],_ len: Int) -> [UInt8]
+    {
+        var B=[UInt8](repeating: 0,count: 16)
+        var b=[UInt8](repeating: 0,count: 4)
+        
+        var plain=[UInt8](repeating: 0,count: len)
+        var counter:UInt32=0
+        
+        if status==GCM.GCM_ACCEPTING_HEADER {status=GCM.GCM_ACCEPTING_CIPHER}
+        if status != GCM.GCM_ACCEPTING_CIPHER {return [UInt8]()}
+    
+        var j=0
+        while (j<len)
+        {
+    
+            b[0]=a.f[12]; b[1]=a.f[13]; b[2]=a.f[14]; b[3]=a.f[15];
+            counter=GCM.pack(b);
+            counter+=1;
+            b=GCM.unpack(counter);
+            a.f[12]=b[0]; a.f[13]=b[1]; a.f[14]=b[2]; a.f[15]=b[3]; /* increment counter */
+            for i in 0 ..< 16 {B[i]=a.f[i]}
+            a.ecb_encrypt(&B);        /* encrypt it  */
+            for i in 0 ..< 16
+            {
+                let oc=cipher[j]
+                plain[j]=(cipher[j]^B[i]);
+                stateX[i]^=oc;
+                j+=1;
+                lenC[1]+=1; if lenC[1]==0 {lenC[0]+=1}
+                if j>=len {break}
+            }
+            gf2mul()
+        }
+        if len%16 != 0 {status=GCM.GCM_NOT_ACCEPTING_MORE}
+        return plain;
+    }
+    
+    /* Finish and extract Tag */
+    func finish(_ extract: Bool) -> [UInt8]
+    { /* Finish off GHASH and extract tag (MAC) */
+        var tag=[UInt8](repeating: 0,count: 16)
+    
+        wrap();
+        /* extract tag */
+        if (extract)
+        {
+            a.ecb_encrypt(&Y_0);        /* E(K,Y0) */
+            for i in 0 ..< 16 {Y_0[i]^=stateX[i]}
+            for i in 0 ..< 16 {tag[i]=Y_0[i];Y_0[i]=0;stateX[i]=0;}
+        }
+        status=GCM.GCM_FINISHED;
+        a.end();
+        return tag;
+    }
+    
+    static func hex2bytes(_ s: String) -> [UInt8]
+    {
+        var array=Array(arrayLiteral: s)
+        let len=array.count;
+        var data=[UInt8](repeating: 0,count: len/2)
+
+        var i=0
+        while (i<len)
+        {
+            data[i / 2] = UInt8(strtoul(String(array[i]),nil,16)<<4)+UInt8(strtoul(String(array[i+1]),nil,16))
+            i+=2
+        }
+        return data;
+    }
+    
+    
+}
+
diff --git a/version22/swift/hash256.swift b/version22/swift/hash256.swift
new file mode 100644
index 0000000..6140da5
--- /dev/null
+++ b/version22/swift/hash256.swift
@@ -0,0 +1,188 @@
+/*
+	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.
+*/
+
+//
+//  hash256.swift - Implementation of SHA-256
+//
+//  Created by Michael Scott on 17/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//  SHA256 Implementation
+//
+
+final class HASH256{
+    
+    private var length=[UInt32](repeating: 0,count: 2)
+    private var h=[UInt32](repeating: 0,count: 8)
+    private var w=[UInt32](repeating: 0,count: 64)
+    static let H0:UInt32=0x6A09E667
+    static let H1:UInt32=0xBB67AE85
+    static let H2:UInt32=0x3C6EF372
+    static let H3:UInt32=0xA54FF53A
+    static let H4:UInt32=0x510E527F
+    static let H5:UInt32=0x9B05688C
+    static let H6:UInt32=0x1F83D9AB
+    static let H7:UInt32=0x5BE0CD19
+    
+    static let len:Int=32
+    
+    static let K:[UInt32]=[
+    0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,
+    0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,
+    0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,
+    0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,
+    0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
+    0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070,
+    0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,
+    0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2]
+    
+    
+    private static func S(_ n: UInt32,_ x: UInt32) -> UInt32
+    {
+        return ((x>>n)|(x<<(32-n)))
+    }
+
+    private static func R(_ n: UInt32,_ x: UInt32) -> UInt32
+    {
+        return (x>>n)
+    }
+    
+    private static func Ch(_ x: UInt32,_ y: UInt32,_ z:UInt32) -> UInt32
+    {
+        return ((x&y)^(~(x)&z))
+    }
+    
+    private static func Maj(_ x: UInt32,_ y: UInt32,_ z:UInt32) -> UInt32
+    {
+        return ((x&y)^(x&z)^(y&z))
+    }
+    
+    private static func Sig0(_ x: UInt32) -> UInt32
+    {
+        return (S(2,x)^S(13,x)^S(22,x))
+    }
+    
+    private static func Sig1(_ x: UInt32) -> UInt32
+    {
+        return (S(6,x)^S(11,x)^S(25,x))
+    }
+    
+    private static func theta0(_ x: UInt32) -> UInt32
+    {
+        return (S(7,x)^S(18,x)^R(3,x))
+    }
+    
+    private static func theta1(_ x: UInt32) -> UInt32
+    {
+        return (S(17,x)^S(19,x)^R(10,x))
+    }
+ 
+    private func transform()
+    { /* basic transformation step */
+        var a,b,c,d,e,f,g,hh,t1,t2 :UInt32
+        for j in 16 ..< 64
+        {
+            w[j]=HASH256.theta1(w[j-2])&+w[j-7]&+HASH256.theta0(w[j-15])&+w[j-16]
+        }
+        a=h[0]; b=h[1]; c=h[2]; d=h[3]
+        e=h[4]; f=h[5]; g=h[6]; hh=h[7]
+    
+        for j in 0 ..< 64
+        { /* 64 times - mush it up */
+            t1=hh&+HASH256.Sig1(e)&+HASH256.Ch(e,f,g)&+HASH256.K[j]&+w[j]
+            t2=HASH256.Sig0(a)&+HASH256.Maj(a,b,c)
+            hh=g; g=f; f=e;
+            e=d&+t1;
+            d=c;
+            c=b;
+            b=a;
+            a=t1&+t2;
+        }
+        h[0]=h[0]&+a; h[1]=h[1]&+b; h[2]=h[2]&+c; h[3]=h[3]&+d
+        h[4]=h[4]&+e; h[5]=h[5]&+f; h[6]=h[6]&+g; h[7]=h[7]&+hh;
+    }
+    
+    /* Re-Initialise Hash function */
+    func init_it()
+    { /* initialise */
+        for i in 0 ..< 64 {w[i]=0}
+        length[0]=0; length[1]=0
+        h[0]=HASH256.H0;
+        h[1]=HASH256.H1;
+        h[2]=HASH256.H2;
+        h[3]=HASH256.H3;
+        h[4]=HASH256.H4;
+        h[5]=HASH256.H5;
+        h[6]=HASH256.H6;
+        h[7]=HASH256.H7;
+    }
+    
+    init()
+    {
+        init_it()
+    }
+    
+    /* process a single byte */
+    func process(_ byt: UInt8)
+    { /* process the next message byte */
+        let cnt=Int((length[0]/32)%16)
+        w[cnt]<<=8;
+        w[cnt]|=(UInt32(byt)&0xFF);
+        length[0]+=8;
+        if (length[0]==0) { length[1] += 1; length[0]=0 }
+        if ((length[0]%512)==0) {transform()}
+    }
+    
+    /* process an array of bytes */
+    func process_array(_ b: [UInt8])
+    {
+        for i in 0 ..< b.count {process((b[i]))}
+    }
+    
+    /* process a 32-bit integer */
+    func process_num(_ n:Int32)
+    {
+        process(UInt8((n>>24)&0xff))
+        process(UInt8((n>>16)&0xff))
+        process(UInt8((n>>8)&0xff))
+        process(UInt8(n&0xff))
+    }
+
+    /* Generate 32-byte Hash */
+    func hash() -> [UInt8]
+    { /* pad message and finish - supply digest */
+        var digest=[UInt8](repeating: 0,count: 32)
+        
+        let len0=length[0]
+        let len1=length[1]
+        process(0x80);
+        while ((length[0]%512) != 448) {process(0)}
+        w[14]=len1
+        w[15]=len0;
+        transform()
+        for i in 0 ..< HASH256.len
+        { /* convert to bytes */
+            let r=(8*(3-UInt32(i)%4));
+            digest[i]=UInt8((h[i/4]>>r) & 0xff);
+        }
+        init_it();
+        return digest;
+    }
+    
+    
+}
diff --git a/version22/swift/hash384.swift b/version22/swift/hash384.swift
new file mode 100644
index 0000000..de89d4c
--- /dev/null
+++ b/version22/swift/hash384.swift
@@ -0,0 +1,198 @@
+/*
+	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.
+*/
+
+//
+//  hash384.swift - Implementation of SHA-384
+//
+//  Created by Michael Scott on 29/03/2016.
+//  Copyright © 2016 Michael Scott. All rights reserved.
+//
+
+import Foundation
+
+final class HASH384{
+    
+    private var length=[UInt64](repeating: 0,count: 2)
+    private var h=[UInt64](repeating: 0,count: 8)
+    private var w=[UInt64](repeating: 0,count: 80)
+    static let H0:UInt64=0xcbbb9d5dc1059ed8
+    static let H1:UInt64=0x629a292a367cd507
+    static let H2:UInt64=0x9159015a3070dd17
+    static let H3:UInt64=0x152fecd8f70e5939
+    static let H4:UInt64=0x67332667ffc00b31
+    static let H5:UInt64=0x8eb44a8768581511
+    static let H6:UInt64=0xdb0c2e0d64f98fa7
+    static let H7:UInt64=0x47b5481dbefa4fa4
+    
+    static let len:Int=48
+    
+    static let K:[UInt64]=[
+        0x428a2f98d728ae22,0x7137449123ef65cd,0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc,
+        0x3956c25bf348b538,0x59f111f1b605d019,0x923f82a4af194f9b,0xab1c5ed5da6d8118,
+        0xd807aa98a3030242,0x12835b0145706fbe,0x243185be4ee4b28c,0x550c7dc3d5ffb4e2,
+        0x72be5d74f27b896f,0x80deb1fe3b1696b1,0x9bdc06a725c71235,0xc19bf174cf692694,
+        0xe49b69c19ef14ad2,0xefbe4786384f25e3,0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65,
+        0x2de92c6f592b0275,0x4a7484aa6ea6e483,0x5cb0a9dcbd41fbd4,0x76f988da831153b5,
+        0x983e5152ee66dfab,0xa831c66d2db43210,0xb00327c898fb213f,0xbf597fc7beef0ee4,
+        0xc6e00bf33da88fc2,0xd5a79147930aa725,0x06ca6351e003826f,0x142929670a0e6e70,
+        0x27b70a8546d22ffc,0x2e1b21385c26c926,0x4d2c6dfc5ac42aed,0x53380d139d95b3df,
+        0x650a73548baf63de,0x766a0abb3c77b2a8,0x81c2c92e47edaee6,0x92722c851482353b,
+        0xa2bfe8a14cf10364,0xa81a664bbc423001,0xc24b8b70d0f89791,0xc76c51a30654be30,
+        0xd192e819d6ef5218,0xd69906245565a910,0xf40e35855771202a,0x106aa07032bbd1b8,
+        0x19a4c116b8d2d0c8,0x1e376c085141ab53,0x2748774cdf8eeb99,0x34b0bcb5e19b48a8,
+        0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb,0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3,
+        0x748f82ee5defb2fc,0x78a5636f43172f60,0x84c87814a1f0ab72,0x8cc702081a6439ec,
+        0x90befffa23631e28,0xa4506cebde82bde9,0xbef9a3f7b2c67915,0xc67178f2e372532b,
+        0xca273eceea26619c,0xd186b8c721c0c207,0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178,
+        0x06f067aa72176fba,0x0a637dc5a2c898a6,0x113f9804bef90dae,0x1b710b35131c471b,
+        0x28db77f523047d84,0x32caab7b40c72493,0x3c9ebe0a15c9bebc,0x431d67c49c100d4c,
+        0x4cc5d4becb3e42b6,0x597f299cfc657e2a,0x5fcb6fab3ad6faec,0x6c44198c4a475817]
+
+    private static func S(_ n: UInt32,_ x: UInt64) -> UInt64
+    {
+        return ((x>>UInt64(n))|(x<<(64-UInt64(n))))
+    }
+    
+    private static func R(_ n: UInt32,_ x: UInt64) -> UInt64
+    {
+        return (x>>UInt64(n))
+    }
+    
+    private static func Ch(_ x: UInt64,_ y: UInt64,_ z:UInt64) -> UInt64
+    {
+        return ((x&y)^(~(x)&z))
+    }
+    
+    private static func Maj(_ x: UInt64,_ y: UInt64,_ z:UInt64) -> UInt64
+    {
+        return ((x&y)^(x&z)^(y&z))
+    }
+    
+    private static func Sig0(_ x: UInt64) -> UInt64
+    {
+        return (S(28,x)^S(34,x)^S(39,x))
+    }
+    
+    private static func Sig1(_ x: UInt64) -> UInt64
+    {
+        return (S(14,x)^S(18,x)^S(41,x))
+    }
+    
+    private static func theta0(_ x: UInt64) -> UInt64
+    {
+        return (S(1,x)^S(8,x)^R(7,x))
+    }
+    
+    private static func theta1(_ x: UInt64) -> UInt64
+    {
+        return (S(19,x)^S(61,x)^R(6,x))
+    }
+    
+    private func transform()
+    { /* basic transformation step */
+        var a,b,c,d,e,f,g,hh,t1,t2 :UInt64
+        for j in 16 ..< 80
+        {
+            w[j]=HASH384.theta1(w[j-2])&+w[j-7]&+HASH384.theta0(w[j-15])&+w[j-16]
+        }
+        a=h[0]; b=h[1]; c=h[2]; d=h[3]
+        e=h[4]; f=h[5]; g=h[6]; hh=h[7]
+        
+        for j in 0 ..< 80
+        { /* 64 times - mush it up */
+            t1=hh&+HASH384.Sig1(e)&+HASH384.Ch(e,f,g)&+HASH384.K[j]&+w[j]
+            t2=HASH384.Sig0(a)&+HASH384.Maj(a,b,c)
+            hh=g; g=f; f=e;
+            e=d&+t1;
+            d=c;
+            c=b;
+            b=a;
+            a=t1&+t2;
+        }
+        h[0]=h[0]&+a; h[1]=h[1]&+b; h[2]=h[2]&+c; h[3]=h[3]&+d
+        h[4]=h[4]&+e; h[5]=h[5]&+f; h[6]=h[6]&+g; h[7]=h[7]&+hh;
+    }
+    
+    /* Re-Initialise Hash function */
+    func init_it()
+    { /* initialise */
+        for i in 0 ..< 80 {w[i]=0}
+        length[0]=0; length[1]=0
+        h[0]=HASH384.H0;
+        h[1]=HASH384.H1;
+        h[2]=HASH384.H2;
+        h[3]=HASH384.H3;
+        h[4]=HASH384.H4;
+        h[5]=HASH384.H5;
+        h[6]=HASH384.H6;
+        h[7]=HASH384.H7;
+    }
+    
+    init()
+    {
+        init_it()
+    }
+    
+    /* process a single byte */
+    func process(_ byt: UInt8)
+    { /* process the next message byte */
+        let cnt=Int((length[0]/64)%16)
+        w[cnt]<<=8;
+        w[cnt]|=(UInt64(byt)&0xFF);
+        length[0]+=8;
+        if (length[0]==0) { length[1] += 1; length[0]=0 }
+        if ((length[0]%1024)==0) {transform()}
+    }
+    
+    /* process an array of bytes */
+    func process_array(_ b: [UInt8])
+    {
+        for i in 0 ..< b.count {process((b[i]))}
+    }
+    
+    /* process a 32-bit integer */
+    func process_num(_ n:Int32)
+    {
+        process(UInt8((n>>24)&0xff))
+        process(UInt8((n>>16)&0xff))
+        process(UInt8((n>>8)&0xff))
+        process(UInt8(n&0xff))
+    }
+    
+    /* Generate 48-byte Hash */
+    func hash() -> [UInt8]
+    { /* pad message and finish - supply digest */
+        var digest=[UInt8](repeating: 0,count: 48)
+        
+        let len0=length[0]
+        let len1=length[1]
+        process(0x80);
+        while ((length[0]%1024) != 896) {process(0)}
+        w[14]=len1
+        w[15]=len0;
+        transform()
+        for i in 0 ..< HASH384.len
+        { /* convert to bytes */
+            digest[i]=UInt8((h[i/8]>>(8*(7-UInt64(i)%8))) & 0xff);
+        }
+        init_it();
+        return digest;
+    }
+    
+}
diff --git a/version22/swift/hash512.swift b/version22/swift/hash512.swift
new file mode 100644
index 0000000..634f944
--- /dev/null
+++ b/version22/swift/hash512.swift
@@ -0,0 +1,198 @@
+/*
+	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.
+*/
+
+//
+//  hash512.swift - Implementation of SHA-512
+//
+//  Created by Michael Scott on 29/03/2016.
+//  Copyright © 2016 Michael Scott. All rights reserved.
+//
+
+import Foundation
+
+final class HASH512{
+    
+    private var length=[UInt64](repeating: 0,count: 2)
+    private var h=[UInt64](repeating: 0,count: 8)
+    private var w=[UInt64](repeating: 0,count: 80)
+    static let H0:UInt64=0x6a09e667f3bcc908
+    static let H1:UInt64=0xbb67ae8584caa73b
+    static let H2:UInt64=0x3c6ef372fe94f82b
+    static let H3:UInt64=0xa54ff53a5f1d36f1
+    static let H4:UInt64=0x510e527fade682d1
+    static let H5:UInt64=0x9b05688c2b3e6c1f
+    static let H6:UInt64=0x1f83d9abfb41bd6b
+    static let H7:UInt64=0x5be0cd19137e2179
+    
+    static let len:Int=64
+    
+    static let K:[UInt64]=[
+        0x428a2f98d728ae22,0x7137449123ef65cd,0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc,
+        0x3956c25bf348b538,0x59f111f1b605d019,0x923f82a4af194f9b,0xab1c5ed5da6d8118,
+        0xd807aa98a3030242,0x12835b0145706fbe,0x243185be4ee4b28c,0x550c7dc3d5ffb4e2,
+        0x72be5d74f27b896f,0x80deb1fe3b1696b1,0x9bdc06a725c71235,0xc19bf174cf692694,
+        0xe49b69c19ef14ad2,0xefbe4786384f25e3,0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65,
+        0x2de92c6f592b0275,0x4a7484aa6ea6e483,0x5cb0a9dcbd41fbd4,0x76f988da831153b5,
+        0x983e5152ee66dfab,0xa831c66d2db43210,0xb00327c898fb213f,0xbf597fc7beef0ee4,
+        0xc6e00bf33da88fc2,0xd5a79147930aa725,0x06ca6351e003826f,0x142929670a0e6e70,
+        0x27b70a8546d22ffc,0x2e1b21385c26c926,0x4d2c6dfc5ac42aed,0x53380d139d95b3df,
+        0x650a73548baf63de,0x766a0abb3c77b2a8,0x81c2c92e47edaee6,0x92722c851482353b,
+        0xa2bfe8a14cf10364,0xa81a664bbc423001,0xc24b8b70d0f89791,0xc76c51a30654be30,
+        0xd192e819d6ef5218,0xd69906245565a910,0xf40e35855771202a,0x106aa07032bbd1b8,
+        0x19a4c116b8d2d0c8,0x1e376c085141ab53,0x2748774cdf8eeb99,0x34b0bcb5e19b48a8,
+        0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb,0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3,
+        0x748f82ee5defb2fc,0x78a5636f43172f60,0x84c87814a1f0ab72,0x8cc702081a6439ec,
+        0x90befffa23631e28,0xa4506cebde82bde9,0xbef9a3f7b2c67915,0xc67178f2e372532b,
+        0xca273eceea26619c,0xd186b8c721c0c207,0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178,
+        0x06f067aa72176fba,0x0a637dc5a2c898a6,0x113f9804bef90dae,0x1b710b35131c471b,
+        0x28db77f523047d84,0x32caab7b40c72493,0x3c9ebe0a15c9bebc,0x431d67c49c100d4c,
+        0x4cc5d4becb3e42b6,0x597f299cfc657e2a,0x5fcb6fab3ad6faec,0x6c44198c4a475817]
+    
+    private static func S(_ n: UInt32,_ x: UInt64) -> UInt64
+    {
+        return ((x>>UInt64(n))|(x<<(64-UInt64(n))))
+    }
+    
+    private static func R(_ n: UInt32,_ x: UInt64) -> UInt64
+    {
+        return (x>>UInt64(n))
+    }
+    
+    private static func Ch(_ x: UInt64,_ y: UInt64,_ z:UInt64) -> UInt64
+    {
+        return ((x&y)^(~(x)&z))
+    }
+    
+    private static func Maj(_ x: UInt64,_ y: UInt64,_ z:UInt64) -> UInt64
+    {
+        return ((x&y)^(x&z)^(y&z))
+    }
+    
+    private static func Sig0(_ x: UInt64) -> UInt64
+    {
+        return (S(28,x)^S(34,x)^S(39,x))
+    }
+    
+    private static func Sig1(_ x: UInt64) -> UInt64
+    {
+        return (S(14,x)^S(18,x)^S(41,x))
+    }
+    
+    private static func theta0(_ x: UInt64) -> UInt64
+    {
+        return (S(1,x)^S(8,x)^R(7,x))
+    }
+    
+    private static func theta1(_ x: UInt64) -> UInt64
+    {
+        return (S(19,x)^S(61,x)^R(6,x))
+    }
+    
+    private func transform()
+    { /* basic transformation step */
+        var a,b,c,d,e,f,g,hh,t1,t2 :UInt64
+        for j in 16 ..< 80
+        {
+            w[j]=HASH512.theta1(w[j-2])&+w[j-7]&+HASH512.theta0(w[j-15])&+w[j-16]
+        }
+        a=h[0]; b=h[1]; c=h[2]; d=h[3]
+        e=h[4]; f=h[5]; g=h[6]; hh=h[7]
+        
+        for j in 0 ..< 80
+        { /* 64 times - mush it up */
+            t1=hh&+HASH512.Sig1(e)&+HASH512.Ch(e,f,g)&+HASH512.K[j]&+w[j]
+            t2=HASH512.Sig0(a)&+HASH512.Maj(a,b,c)
+            hh=g; g=f; f=e;
+            e=d&+t1;
+            d=c;
+            c=b;
+            b=a;
+            a=t1&+t2;
+        }
+        h[0]=h[0]&+a; h[1]=h[1]&+b; h[2]=h[2]&+c; h[3]=h[3]&+d
+        h[4]=h[4]&+e; h[5]=h[5]&+f; h[6]=h[6]&+g; h[7]=h[7]&+hh;
+    }
+    
+    /* Re-Initialise Hash function */
+    func init_it()
+    { /* initialise */
+        for i in 0 ..< 80 {w[i]=0}
+        length[0]=0; length[1]=0
+        h[0]=HASH512.H0;
+        h[1]=HASH512.H1;
+        h[2]=HASH512.H2;
+        h[3]=HASH512.H3;
+        h[4]=HASH512.H4;
+        h[5]=HASH512.H5;
+        h[6]=HASH512.H6;
+        h[7]=HASH512.H7;
+    }
+    
+    init()
+    {
+        init_it()
+    }
+    
+    /* process a single byte */
+    func process(_ byt: UInt8)
+    { /* process the next message byte */
+        let cnt=Int((length[0]/64)%16)
+        w[cnt]<<=8;
+        w[cnt]|=(UInt64(byt)&0xFF);
+        length[0]+=8;
+        if (length[0]==0) { length[1] += 1; length[0]=0 }
+        if ((length[0]%1024)==0) {transform()}
+    }
+    
+    /* process an array of bytes */
+    func process_array(_ b: [UInt8])
+    {
+        for i in 0 ..< b.count {process((b[i]))}
+    }
+    
+    /* process a 32-bit integer */
+    func process_num(_ n:Int32)
+    {
+        process(UInt8((n>>24)&0xff))
+        process(UInt8((n>>16)&0xff))
+        process(UInt8((n>>8)&0xff))
+        process(UInt8(n&0xff))
+    }
+    
+    /* Generate 48-byte Hash */
+    func hash() -> [UInt8]
+    { /* pad message and finish - supply digest */
+        var digest=[UInt8](repeating: 0,count: 64)
+        
+        let len0=length[0]
+        let len1=length[1]
+        process(0x80);
+        while ((length[0]%1024) != 896) {process(0)}
+        w[14]=len1
+        w[15]=len0;
+        transform()
+        for i in 0 ..< HASH512.len
+        { /* convert to bytes */
+            digest[i]=UInt8((h[i/8]>>(8*(7-UInt64(i)%8))) & 0xff);
+        }
+        init_it();
+        return digest;
+    }
+    
+}
diff --git a/version22/swift/main.swift b/version22/swift/main.swift
new file mode 100644
index 0000000..e464a0e
--- /dev/null
+++ b/version22/swift/main.swift
@@ -0,0 +1,13 @@
+//
+//  main.swift
+//
+//  Created by Michael Scott on 12/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+BenchtestPAIR()
+BenchtestEC()
+TestRSA()
+TestECDH()
+TestMPIN()
+
diff --git a/version22/swift/mpin.swift b/version22/swift/mpin.swift
new file mode 100644
index 0000000..c4bc28e
--- /dev/null
+++ b/version22/swift/mpin.swift
@@ -0,0 +1,833 @@
+/*
+	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.
+*/
+
+//
+//  mpin.swift
+//
+//  Created by Michael Scott on 08/07/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+
+import Foundation
+
+final public class MPIN
+{
+    static public let EFS=Int(ROM.MODBYTES)
+    static public let EGS=Int(ROM.MODBYTES)
+    static public let PAS:Int=16
+    static let INVALID_POINT:Int = -14
+    static let BAD_PARAMS:Int = -11
+    static let WRONG_ORDER:Int = -18
+    static public let BAD_PIN:Int = -19
+    static public let SHA256=32
+    static public let SHA384=48
+    static public let SHA512=64
+    
+    /* Configure your PIN here */
+    
+    static let MAXPIN:Int32 = 10000  // PIN less than this
+    static let PBLEN:Int32 = 14      // Number of bits in PIN
+    static let TS:Int = 10         // 10 for 4 digit PIN, 14 for 6-digit PIN - 2^TS/TS approx = sqrt(MAXPIN)
+    static let TRAP:Int = 200      // 200 for 4 digit PIN, 2000 for 6-digit PIN  - approx 2*sqrt(MAXPIN)
+
+    static public let HASH_TYPE=SHA256
+    
+    private static func mpin_hash(_ sha:Int,_ c: FP4,_ U: ECP) -> [UInt8]
+    {
+        var w=[UInt8](repeating: 0,count: EFS)
+        var t=[UInt8](repeating: 0,count: 6*EFS)
+        var h=[UInt8]()
+        
+        c.geta().getA().toBytes(&w); for i in 0 ..< EFS {t[i]=w[i]}
+        c.geta().getB().toBytes(&w); for i in EFS ..< 2*EFS {t[i]=w[i-EFS]}
+        c.getb().getA().toBytes(&w); for i in 2*EFS ..< 3*EFS {t[i]=w[i-2*EFS]}
+        c.getb().getB().toBytes(&w); for i in 3*EFS ..< 4*EFS {t[i]=w[i-3*EFS]}
+        
+        U.getX().toBytes(&w); for i in 4*EFS ..< 5*EFS {t[i]=w[i-4*EFS]}
+        U.getY().toBytes(&w); for i in 5*EFS ..< 6*EFS {t[i]=w[i-5*EFS]}
+        
+        if sha==SHA256
+        {
+            let H=HASH256()
+            H.process_array(t)
+            h=H.hash()
+        }
+        if sha==SHA384
+        {
+            let H=HASH384()
+            H.process_array(t)
+            h=H.hash()
+        }
+        if sha==SHA512
+        {
+            let H=HASH512()
+            H.process_array(t)
+            h=H.hash()
+        }
+        if h.isEmpty {return h}
+        var R=[UInt8](repeating: 0,count: PAS)
+        for i in 0 ..< PAS {R[i]=h[i]}
+        return R
+    }
+    
+    // Hash number (optional) and string to point on curve
+    
+    private static func hashit(_ sha:Int,_ n:Int32,_ ID:[UInt8]) -> [UInt8]
+    {
+        var R=[UInt8]()
+        if sha==SHA256
+        {
+            let H=HASH256()
+            if n != 0 {H.process_num(n)}
+            H.process_array(ID)
+            R=H.hash()
+        }
+        if sha==SHA384
+        {
+            let H=HASH384()
+            if n != 0 {H.process_num(n)}
+            H.process_array(ID)
+            R=H.hash()
+        }
+        if sha==SHA512
+        {
+            let H=HASH512()
+            if n != 0 {H.process_num(n)}
+            H.process_array(ID)
+            R=H.hash()
+        }
+        if R.isEmpty {return R}
+        let RM=Int(ROM.MODBYTES)
+        var W=[UInt8](repeating: 0,count: RM)
+        if sha >= RM
+        {
+            for i in 0 ..< RM {W[i]=R[i]}
+        }
+        else
+        {
+            for i in 0 ..< sha {W[i]=R[i]}
+        }
+        return W
+    }
+    
+    static func mapit(_ h:[UInt8]) -> ECP
+    {
+        let q=BIG(ROM.Modulus)
+        let x=BIG.fromBytes(h)
+        x.mod(q)
+        var P=ECP(x,0)
+        while (true)
+        {
+            if !P.is_infinity() {break}
+            x.inc(1); x.norm();
+            P=ECP(x,0);
+        }
+        if ROM.CURVE_PAIRING_TYPE != ROM.BN_CURVE {
+            let c=BIG(ROM.CURVE_Cof)
+            P=P.mul(c)
+        }
+
+        return P
+    }
+
+    // needed for SOK
+    static func mapit2(_ h:[UInt8]) -> ECP2
+    {
+        let q=BIG(ROM.Modulus)
+        var x=BIG.fromBytes(h)
+        let one=BIG(1)
+        var Q=ECP2()
+        x.mod(q);
+        while (true)
+        {
+            let X=FP2(one,x);
+            Q=ECP2(X);
+            if !Q.is_infinity() {break}
+            x.inc(1); x.norm();
+        }
+    // Fast Hashing to G2 - Fuentes-Castaneda, Knapp and Rodriguez-Henriquez
+        let Fra=BIG(ROM.CURVE_Fra);
+        let Frb=BIG(ROM.CURVE_Frb);
+        let X=FP2(Fra,Frb);
+        x=BIG(ROM.CURVE_Bnx);
+    
+        let T=ECP2(); T.copy(Q)
+        T.mul(x); T.neg()
+        let K=ECP2(); K.copy(T)
+        K.dbl(); K.add(T); K.affine()
+    
+        K.frob(X)
+        Q.frob(X); Q.frob(X); Q.frob(X)
+        Q.add(T); Q.add(K)
+        T.frob(X); T.frob(X)
+        Q.add(T)
+        Q.affine()
+        return Q
+    }
+    
+    // return time in slots since epoch
+    static public func today() -> Int32
+    {
+        let date=Date()
+        return (Int32(date.timeIntervalSince1970/(60*1440)))
+    }
+
+    // these next two functions help to implement elligator squared - http://eprint.iacr.org/2014/043
+    // maps a random u to a point on the curve
+    static func map(_ u:BIG,_ cb:Int) -> ECP
+    {
+        let x=BIG(u)
+        let p=BIG(ROM.Modulus)
+        x.mod(p)
+        var P=ECP(x,cb)
+        while (true)
+        {
+            if !P.is_infinity() {break}
+            x.inc(1);  x.norm()
+            P=ECP(x,cb)
+        }
+        return P
+    }
+
+    // returns u derived from P. Random value in range 1 to return value should then be added to u
+    static func unmap(_ u:inout BIG,_ P:ECP) -> Int
+    {
+        let s=P.getS()
+        var r:Int32=0
+        let x=P.getX()
+        u.copy(x)
+        var R=ECP()
+        while (true)
+        {
+            u.dec(1); u.norm()
+            r += 1
+            R=ECP(u,s)
+            if !R.is_infinity() {break}
+        }
+        return Int(r)
+    }
+    
+    static public func HASH_ID(_ sha:Int,_ ID:[UInt8]) -> [UInt8]
+    {
+        return hashit(sha,0,ID)
+    }
+    
+    // these next two functions implement elligator squared - http://eprint.iacr.org/2014/043
+    // Elliptic curve point E in format (0x04,x,y} is converted to form {0x0-,u,v}
+    // Note that u and v are indistinguisible from random strings
+    static public func ENCODING(_ rng:RAND,_ E:inout [UInt8]) -> Int
+    {
+        var T=[UInt8](repeating: 0,count: EFS)
+    
+        for i in 0 ..< EFS {T[i]=E[i+1]}
+        var u=BIG.fromBytes(T);
+        for i in 0 ..< EFS {T[i]=E[i+EFS+1]}
+        var v=BIG.fromBytes(T)
+    
+        let P=ECP(u,v);
+        if P.is_infinity() {return INVALID_POINT}
+    
+        let p=BIG(ROM.Modulus)
+        u=BIG.randomnum(p,rng)
+    
+        var su=rng.getByte();
+        su%=2
+    
+        let W=MPIN.map(u,Int(su))
+        P.sub(W);
+        let sv=P.getS();
+        let rn=MPIN.unmap(&v,P)
+        let m=rng.getByte();
+        let incr=1+Int(m)%rn
+        v.inc(incr)
+        E[0]=(su+UInt8(2*sv))
+        u.toBytes(&T)
+        for i in 0 ..< EFS {E[i+1]=T[i]}
+        v.toBytes(&T)
+        for i in 0 ..< EFS {E[i+EFS+1]=T[i]}
+    
+        return 0;
+    }
+
+    static public func DECODING(_ D:inout [UInt8]) -> Int
+    {
+        var T=[UInt8](repeating: 0,count: EFS)
+    
+        if (D[0]&0x04) != 0 {return INVALID_POINT}
+    
+        for i in 0 ..< EFS {T[i]=D[i+1]}
+        var u=BIG.fromBytes(T)
+        for i in 0 ..< EFS {T[i]=D[i+EFS+1]}
+        var v=BIG.fromBytes(T)
+    
+        let su=D[0]&1
+        let sv=(D[0]>>1)&1
+        let W=map(u,Int(su))
+        let P=map(v,Int(sv))
+        P.add(W)
+        u=P.getX()
+        v=P.getY()
+        D[0]=0x04
+        u.toBytes(&T);
+        for i in 0 ..< EFS {D[i+1]=T[i]}
+        v.toBytes(&T)
+        for i in 0 ..< EFS {D[i+EFS+1]=T[i]}
+    
+        return 0
+    }
+    // R=R1+R2 in group G1
+    static public func RECOMBINE_G1(_ R1:[UInt8],_ R2:[UInt8],_ R:inout [UInt8]) -> Int
+    {
+        let P=ECP.fromBytes(R1)
+        let Q=ECP.fromBytes(R2)
+    
+        if P.is_infinity() || Q.is_infinity() {return INVALID_POINT}
+    
+        P.add(Q)
+    
+        P.toBytes(&R)
+        return 0;
+    }
+    // W=W1+W2 in group G2
+    static public func RECOMBINE_G2(_ W1:[UInt8],_ W2:[UInt8],_  W:inout [UInt8]) -> Int
+    {
+        let P=ECP2.fromBytes(W1)
+        let Q=ECP2.fromBytes(W2)
+    
+        if P.is_infinity() || Q.is_infinity() {return INVALID_POINT}
+    
+        P.add(Q)
+        
+        P.toBytes(&W)
+        return 0
+    }
+    // create random secret S
+    static public func RANDOM_GENERATE(_ rng:RAND,_ S:inout [UInt8]) -> Int
+    {
+        let r=BIG(ROM.CURVE_Order)
+        let s=BIG.randomnum(r,rng)
+	if ROM.AES_S>0
+	{
+		s.mod2m(2*ROM.AES_S)
+	}    
+        s.toBytes(&S);
+        return 0;
+    }
+    // Extract PIN from TOKEN for identity CID
+    static public func EXTRACT_PIN(_ sha:Int,_ CID:[UInt8],_ pin:Int32,_ TOKEN:inout [UInt8]) -> Int
+    {
+        let P=ECP.fromBytes(TOKEN)
+        if P.is_infinity() {return INVALID_POINT}
+        let h=MPIN.hashit(sha,0,CID)
+        var R=MPIN.mapit(h)
+
+        R=R.pinmul(pin%MAXPIN,MPIN.PBLEN)
+        P.sub(R)
+    
+        P.toBytes(&TOKEN)
+    
+        return 0
+    }
+    // Implement step 2 on client side of MPin protocol
+    static public func CLIENT_2(_ X:[UInt8],_ Y:[UInt8],_ SEC:inout [UInt8]) -> Int
+    {
+        let r=BIG(ROM.CURVE_Order)
+        var P=ECP.fromBytes(SEC)
+        if P.is_infinity() {return INVALID_POINT}
+    
+        let px=BIG.fromBytes(X)
+        let py=BIG.fromBytes(Y)
+        px.add(py)
+        px.mod(r)
+     //   px.rsub(r)
+
+        P=PAIR.G1mul(P,px)
+        P.neg()
+        P.toBytes(&SEC);
+      //  PAIR.G1mul(P,px).toBytes(&SEC)
+        return 0
+    }
+    
+    // Implement step 1 on client side of MPin protocol
+    static public func CLIENT_1(_ sha:Int,_ date:Int32,_ CLIENT_ID:[UInt8],_ rng:RAND?,_ X:inout [UInt8],_ pin:Int32,_ TOKEN:[UInt8],_ SEC:inout [UInt8],_ xID:inout [UInt8]?,_ xCID:inout [UInt8]?,_ PERMIT:[UInt8]) -> Int
+    {
+        let r=BIG(ROM.CURVE_Order)
+   //     let q=BIG(ROM.Modulus)
+        var x:BIG
+        if rng != nil
+        {
+            x=BIG.randomnum(r,rng!)
+            if ROM.AES_S>0
+            {
+                x.mod2m(2*ROM.AES_S)
+            }
+            x.toBytes(&X);
+        }
+        else
+        {
+            x=BIG.fromBytes(X);
+        }
+    //    var t=[UInt8](count:EFS,repeatedValue:0)
+    
+        var h=MPIN.hashit(sha,0,CLIENT_ID)
+        var P=mapit(h);
+    
+        let T=ECP.fromBytes(TOKEN);
+        if T.is_infinity() {return INVALID_POINT}
+    
+        var W=P.pinmul(pin%MPIN.MAXPIN,MPIN.PBLEN)
+        T.add(W)
+        if date != 0
+        {
+            W=ECP.fromBytes(PERMIT)
+            if W.is_infinity() {return INVALID_POINT}
+            T.add(W);
+            h=MPIN.hashit(sha,date,h)
+            W=MPIN.mapit(h);
+            if xID != nil
+            {
+				P=PAIR.G1mul(P,x)
+				P.toBytes(&xID!)
+				W=PAIR.G1mul(W,x)
+				P.add(W)
+            }
+            else
+            {
+				P.add(W);
+				P=PAIR.G1mul(P,x);
+            }
+            if xCID != nil {P.toBytes(&xCID!)}
+        }
+        else
+        {
+            if xID != nil
+            {
+				P=PAIR.G1mul(P,x)
+				P.toBytes(&xID!)
+            }
+        }
+    
+    
+        T.toBytes(&SEC);
+        return 0;
+    }
+    // Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret
+    static public func GET_SERVER_SECRET(_ S:[UInt8],_ SST:inout [UInt8]) -> Int
+    {
+        var Q=ECP2(FP2(BIG(ROM.CURVE_Pxa),BIG(ROM.CURVE_Pxb)),FP2(BIG(ROM.CURVE_Pya),BIG(ROM.CURVE_Pyb)))
+    
+        let s=BIG.fromBytes(S)
+        Q=PAIR.G2mul(Q,s)
+        Q.toBytes(&SST)
+        return 0
+    }
+ 
+    
+    //W=x*H(G);
+    //if RNG == NULL then X is passed in
+    //if RNG != NULL the X is passed out
+    //if type=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve
+    
+    static public func GET_G1_MULTIPLE(_ rng:RAND?,_ type:Int,_ X:inout [UInt8],_ G:[UInt8],_ W:inout [UInt8]) -> Int
+    {
+        var x:BIG
+        let r=BIG(ROM.CURVE_Order)
+        if rng != nil
+        {
+            x=BIG.randomnum(r,rng!)
+            if ROM.AES_S>0
+            {
+                x.mod2m(2*ROM.AES_S)
+            }
+            x.toBytes(&X)
+        }
+        else
+        {
+            x=BIG.fromBytes(X);
+        }
+        var P:ECP
+        if type==0
+        {
+            P=ECP.fromBytes(G)
+            if P.is_infinity() {return INVALID_POINT}
+        }
+        else
+            {P=MPIN.mapit(G)}
+    
+        PAIR.G1mul(P,x).toBytes(&W)
+        return 0;
+    }
+    // Client secret CST=S*H(CID) where CID is client ID and S is master secret
+    // CID is hashed externally
+    static public func GET_CLIENT_SECRET(_ S:inout [UInt8],_ CID:[UInt8],_ CST:inout [UInt8]) -> Int
+    {
+        return GET_G1_MULTIPLE(nil,1,&S,CID,&CST)
+    }
+    // Time Permit CTT=S*(date|H(CID)) where S is master secret
+    static public func GET_CLIENT_PERMIT(_ sha:Int,_ date:Int32,_ S:[UInt8],_ CID:[UInt8],_ CTT:inout [UInt8]) -> Int
+    {
+        let h=MPIN.hashit(sha,date,CID)
+        let P=MPIN.mapit(h)
+    
+        let s=BIG.fromBytes(S)
+        PAIR.G1mul(P,s).toBytes(&CTT)
+        return 0;
+    }
+  
+    // Outputs H(CID) and H(T|H(CID)) for time permits. If no time permits set HID=HTID
+    static public func SERVER_1(_ sha:Int,_ date:Int32,_ CID:[UInt8],_ HID:inout [UInt8],_ HTID:inout [UInt8])
+    {
+        var h=MPIN.hashit(sha,0,CID)
+        let P=MPIN.mapit(h)
+
+	P.toBytes(&HID)
+        if date != 0
+        {
+       //     if HID != nil {P.toBytes(&HID!)}
+            h=hashit(sha,date,h)
+            let R=MPIN.mapit(h)
+            P.add(R)
+            P.toBytes(&HTID)
+        }
+        //else {P.toBytes(&HID!)}
+    }
+    // Implement step 2 of MPin protocol on server side
+    static public func SERVER_2(_ date:Int32,_ HID:[UInt8]?,_ HTID:[UInt8]?,_ Y:[UInt8],_ SST:[UInt8],_ xID:[UInt8]?,_ xCID:[UInt8]?,_ mSEC:[UInt8],_ E:inout [UInt8]?,_ F:inout [UInt8]?) -> Int
+    {
+      //  _=BIG(ROM.Modulus);
+        let Q=ECP2(FP2(BIG(ROM.CURVE_Pxa),BIG(ROM.CURVE_Pxb)),FP2(BIG(ROM.CURVE_Pya),BIG(ROM.CURVE_Pyb)))
+        let sQ=ECP2.fromBytes(SST)
+        if sQ.is_infinity() {return INVALID_POINT}
+    
+        var R:ECP
+        if date != 0
+            {R=ECP.fromBytes(xCID!)}
+        else
+        {
+            if xID==nil {return MPIN.BAD_PARAMS}
+            R=ECP.fromBytes(xID!)
+        }
+        if R.is_infinity() {return INVALID_POINT}
+    
+        let y=BIG.fromBytes(Y)
+        var P:ECP
+        if date != 0 {P=ECP.fromBytes(HTID!)}
+        else
+        {
+            if HID==nil {return MPIN.BAD_PARAMS}
+            P=ECP.fromBytes(HID!)
+        }
+    
+        if P.is_infinity() {return INVALID_POINT}
+    
+        P=PAIR.G1mul(P,y)
+        P.add(R)
+        R=ECP.fromBytes(mSEC)
+        if R.is_infinity() {return MPIN.INVALID_POINT}
+
+    
+        var g=PAIR.ate2(Q,R,sQ,P)
+        g=PAIR.fexp(g)
+    
+        if !g.isunity()
+        {
+            if HID != nil && xID != nil && E != nil && F != nil
+            {
+				g.toBytes(&E!)
+				if date != 0
+				{
+                    P=ECP.fromBytes(HID!)
+                    if P.is_infinity() {return MPIN.INVALID_POINT}
+                    R=ECP.fromBytes(xID!)
+                    if R.is_infinity() {return MPIN.INVALID_POINT}
+    
+                    P=PAIR.G1mul(P,y);
+                    P.add(R);
+				}
+				g=PAIR.ate(Q,P);
+				g=PAIR.fexp(g);
+				g.toBytes(&F!);
+            }
+            return MPIN.BAD_PIN;
+        }
+    
+        return 0
+    }
+    // Pollards kangaroos used to return PIN error
+    static public func KANGAROO(_ E:[UInt8],_ F:[UInt8]) -> Int
+    {
+        let ge=FP12.fromBytes(E)
+        let gf=FP12.fromBytes(F)
+        var distance=[Int]();
+        let t=FP12(gf);
+        var table=[FP12]()
+        
+        var s:Int=1
+        for _ in 0 ..< Int(TS)
+        {
+            distance.append(s)
+            table.append(FP12(t))
+            s*=2
+            t.usqr()
+ 
+        }
+        t.one()
+        var dn:Int=0
+        for _ in 0 ..< TRAP
+        {
+            let i=Int(t.geta().geta().getA().lastbits(8))%TS
+            t.mul(table[i])
+            dn+=distance[i]
+        }
+        gf.copy(t); gf.conj()
+        var steps=0; var dm:Int=0
+        var res=0;
+        while (dm-dn<Int(MAXPIN))
+        {
+            steps += 1;
+            if steps>4*TRAP {break}
+            let i=Int(ge.geta().geta().getA().lastbits(8))%TS
+            ge.mul(table[i])
+            dm+=distance[i]
+            if (ge.equals(t))
+            {
+				res=dm-dn;
+				break;
+            }
+            if (ge.equals(gf))
+            {
+				res=dn-dm
+				break
+            }
+    
+        }
+        if steps>4*TRAP || dm-dn>=Int(MAXPIN) {res=0 }    // Trap Failed  - probable invalid token
+        return res
+    }
+    // Functions to support M-Pin Full
+    
+    static public func PRECOMPUTE(_ TOKEN:[UInt8],_ CID:[UInt8],_ G1:inout [UInt8],_ G2:inout [UInt8]) -> Int
+    {
+        let T=ECP.fromBytes(TOKEN);
+        if T.is_infinity() {return INVALID_POINT}
+    
+        let P=MPIN.mapit(CID)
+    
+        let Q=ECP2(FP2(BIG(ROM.CURVE_Pxa),BIG(ROM.CURVE_Pxb)),FP2(BIG(ROM.CURVE_Pya),BIG(ROM.CURVE_Pyb)))
+    
+        var g=PAIR.ate(Q,T)
+        g=PAIR.fexp(g)
+        g.toBytes(&G1)
+    
+        g=PAIR.ate(Q,P)
+        g=PAIR.fexp(g)
+        g.toBytes(&G2)
+    
+        return 0
+    }
+    
+    static public func HASH_ALL(_ sha:Int,_ HID:[UInt8],_ xID:[UInt8]?,_ xCID:[UInt8]?,_ SEC:[UInt8],_ Y:[UInt8],_ R:[UInt8],_ W:[UInt8]  ) -> [UInt8]
+    {
+        var T=[UInt8](repeating: 0,count: 10*EFS+4)
+        var tlen=0
+
+        for i in 0 ..< HID.count  {T[i]=HID[i]}
+        tlen+=HID.count
+        if xCID != nil {
+            for i in 0 ..< xCID!.count  {T[i+tlen]=xCID![i]}
+            tlen+=xCID!.count
+        } else {
+            for i in 0 ..< xID!.count {T[i+tlen]=xID![i]}
+            tlen+=xID!.count
+        }
+        for i in 0 ..< SEC.count {T[i+tlen]=SEC[i]}
+        tlen+=SEC.count;
+        for i in 0 ..< Y.count {T[i+tlen]=Y[i]}
+        tlen+=Y.count;
+        for i in 0 ..< R.count {T[i+tlen]=R[i]}
+        tlen+=R.count;
+        for i in 0 ..< W.count {T[i+tlen]=W[i]}
+        tlen+=W.count;
+
+        return hashit(sha,0,T);
+    }
+
+    // calculate common key on client side
+    // wCID = w.(A+AT)
+    static public func CLIENT_KEY(_ sha:Int,_ G1:[UInt8],_ G2:[UInt8],_ pin:Int32,_ R:[UInt8],_ X:[UInt8],_ H:[UInt8],_ wCID:[UInt8],_ CK:inout [UInt8]) -> Int
+    {
+        let g1=FP12.fromBytes(G1)
+        let g2=FP12.fromBytes(G2)
+        let z=BIG.fromBytes(R)
+        let x=BIG.fromBytes(X)
+        let h=BIG.fromBytes(H)
+    
+        var W=ECP.fromBytes(wCID)
+        if W.is_infinity() {return INVALID_POINT}
+    
+        W=PAIR.G1mul(W,x)
+    
+        let f=FP2(BIG(ROM.CURVE_Fra),BIG(ROM.CURVE_Frb))
+        let r=BIG(ROM.CURVE_Order)
+        let q=BIG(ROM.Modulus)
+    
+        z.add(h)   // new
+        z.mod(r)
+
+        let m=BIG(q)
+        m.mod(r)
+    
+        let a=BIG(z)
+        a.mod(m)
+    
+        let b=BIG(z)
+        b.div(m);
+    
+        g2.pinpow(pin,PBLEN);
+        g1.mul(g2);
+    
+        var c=g1.trace()
+        g2.copy(g1)
+        g2.frob(f)
+        let cp=g2.trace()
+        g1.conj()
+        g2.mul(g1)
+        let cpm1=g2.trace()
+        g2.mul(g1)
+        let cpm2=g2.trace()
+    
+        c=c.xtr_pow2(cp,cpm1,cpm2,a,b)
+      
+        let t=mpin_hash(sha,c,W)
+
+        for i in 0 ..< PAS {CK[i]=t[i]}
+    
+        return 0
+    }
+    // calculate common key on server side
+    // Z=r.A - no time permits involved
+    
+    static public func SERVER_KEY(_ sha:Int,_ Z:[UInt8],_ SST:[UInt8],_ W:[UInt8],_ H:[UInt8],_ HID:[UInt8],_ xID:[UInt8],_ xCID:[UInt8]?,_ SK:inout [UInt8]) -> Int
+    {
+   //     var t=[UInt8](count:EFS,repeatedValue:0)
+    
+        let sQ=ECP2.fromBytes(SST)
+        if sQ.is_infinity() {return INVALID_POINT}
+        let R=ECP.fromBytes(Z)
+        if R.is_infinity() {return INVALID_POINT}
+        var A=ECP.fromBytes(HID)
+        if A.is_infinity() {return INVALID_POINT}
+    
+        var U:ECP
+        if xCID != nil
+            {U=ECP.fromBytes(xCID!)}
+        else
+            {U=ECP.fromBytes(xID)}
+        
+        if U.is_infinity() {return INVALID_POINT}
+    
+        let w=BIG.fromBytes(W)
+        let h=BIG.fromBytes(H)
+        A=PAIR.G1mul(A,h)
+        R.add(A)
+
+        U=PAIR.G1mul(U,w)
+        var g=PAIR.ate(sQ,R)
+        g=PAIR.fexp(g)
+    
+        let c=g.trace()
+        
+        let t=mpin_hash(sha,c,U)
+ 
+        for i in 0 ..< PAS {SK[i]=t[i]}
+    
+        return 0
+    }
+    
+    // return time since epoch
+    static public func GET_TIME() -> Int32
+    {
+        let date=Date()
+        return (Int32(date.timeIntervalSince1970))
+    }
+
+    // Generate Y = H(epoch, xCID/xID)
+    static public func GET_Y(_ sha:Int,_ TimeValue:Int32,_ xCID:[UInt8],_ Y:inout [UInt8])
+    {
+        let h = MPIN.hashit(sha,TimeValue,xCID)
+        let y = BIG.fromBytes(h)
+        let q=BIG(ROM.CURVE_Order)
+        y.mod(q)
+	if ROM.AES_S>0
+	{
+		y.mod2m(2*ROM.AES_S)
+	}
+        y.toBytes(&Y)
+    }
+    // One pass MPIN Client
+    static public func CLIENT(_ sha:Int,_ date:Int32,_ CLIENT_ID:[UInt8],_ RNG:RAND?,_ X:inout [UInt8],_ pin:Int32,_ TOKEN:[UInt8],_  SEC:inout [UInt8],_ xID:inout [UInt8]?,_ xCID:inout [UInt8]?,_ PERMIT:[UInt8],_ TimeValue:Int32,_ Y:inout [UInt8]) -> Int
+    {
+        var rtn=0
+  
+        rtn = MPIN.CLIENT_1(sha,date,CLIENT_ID,RNG,&X,pin,TOKEN,&SEC,&xID,&xCID,PERMIT)
+
+        if rtn != 0 {return rtn}
+    
+        if date==0 {MPIN.GET_Y(sha,TimeValue,xID!,&Y)}
+        else {MPIN.GET_Y(sha,TimeValue,xCID!,&Y)}
+    
+        rtn = MPIN.CLIENT_2(X,Y,&SEC)
+        if (rtn != 0) {return rtn}
+    
+        return 0
+    }
+    // One pass MPIN Server
+    static public func SERVER(_ sha:Int,_ date:Int32,_ HID:inout [UInt8],_ HTID:inout [UInt8]?,_ Y:inout [UInt8],_ SST:[UInt8],_ xID:[UInt8]?,_ xCID:[UInt8],_ SEC:[UInt8],_ E:inout [UInt8]?,_ F:inout [UInt8]?,_ CID:[UInt8],_ TimeValue:Int32) -> Int
+    {
+        var rtn=0
+    
+        var pID:[UInt8]
+        if date == 0
+            {pID = xID!}
+        else
+            {pID = xCID}
+    
+        SERVER_1(sha,date,CID,&HID,&HTID!);
+    
+        GET_Y(sha,TimeValue,pID,&Y);
+    
+        rtn = SERVER_2(date,HID,HTID!,Y,SST,xID,xCID,SEC,&E,&F);
+        if rtn != 0 {return rtn}
+    
+        return 0
+    }
+   
+    static public func printBinary(_ array: [UInt8])
+    {
+        for i in 0 ..< array.count
+        {
+            let h=String(format:"%02x",array[i])
+            print("\(h)", terminator: "")
+        }
+        print(" ");
+    }
+}
+ 
+
diff --git a/version22/swift/pair.swift b/version22/swift/pair.swift
new file mode 100644
index 0000000..93d2c20
--- /dev/null
+++ b/version22/swift/pair.swift
@@ -0,0 +1,592 @@
+/*
+	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.
+*/
+
+//
+//  pair.swift
+//
+//  Created by Michael Scott on 07/07/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+/* AMCL BN Curve Pairing functions */
+
+final class PAIR {
+    
+    // Line function
+    static func line(_ A:ECP2,_ B:ECP2,_ Qx:FP,_ Qy:FP) -> FP12
+    {
+        let P=ECP2()
+        var a:FP4
+        var b:FP4
+        var c:FP4
+        P.copy(A);
+        let ZZ=FP2(P.getz())
+        ZZ.sqr();
+        var D:Int
+        if A===B {D=A.dbl()} // Check this return value in ecp2.c
+        else {D=A.add(B)}
+        if (D<0) {return FP12(1)}
+        let Z3=FP2(A.getz())
+        c=FP4(0)
+        if D==0
+        { /* Addition */
+            let X=FP2(B.getx())
+            let Y=FP2(B.gety())
+            let T=FP2(P.getz())
+            T.mul(Y)
+            ZZ.mul(T)
+    
+            let NY=FP2(P.gety()); NY.neg()
+            ZZ.add(NY)
+            Z3.pmul(Qy)
+            T.mul(P.getx())
+            X.mul(NY)
+            T.add(X)
+            a=FP4(Z3,T)
+            ZZ.neg()
+            ZZ.pmul(Qx)
+            b=FP4(ZZ)
+        }
+        else
+        { // Doubling
+            let X=FP2(P.getx())
+            let Y=FP2(P.gety())
+            let T=FP2(P.getx())
+            T.sqr()
+            T.imul(3)
+    
+            Y.sqr()
+            Y.add(Y)
+            Z3.mul(ZZ)
+            Z3.pmul(Qy)
+    
+            X.mul(T)
+            X.sub(Y)
+            a=FP4(Z3,X)
+            T.neg()
+            ZZ.mul(T)
+            ZZ.pmul(Qx)
+            b=FP4(ZZ)
+        }
+        return FP12(a,b,c)
+    }
+    // Optimal R-ate pairing
+    static func ate(_ P:ECP2,_ Q:ECP) -> FP12
+    {
+        let f=FP2(BIG(ROM.CURVE_Fra),BIG(ROM.CURVE_Frb))
+        let x=BIG(ROM.CURVE_Bnx)
+        let n=BIG(x)
+        let K=ECP2()
+        
+        var lv:FP12
+
+	if ROM.CURVE_PAIRING_TYPE == ROM.BN_CURVE {
+		n.pmul(6); n.dec(2)
+	} else {n.copy(x)}
+	
+	n.norm()
+        P.affine()
+        Q.affine()
+        let Qx=FP(Q.getx())
+        let Qy=FP(Q.gety())
+    
+        let A=ECP2()
+        let r=FP12(1)
+    
+        A.copy(P)
+        let nb=n.nbits()
+    
+        for i in (1...nb-2).reversed()
+        //for var i=nb-2;i>=1;i--
+        {
+            lv=line(A,A,Qx,Qy)
+            r.smul(lv)
+    
+            if (n.bit(UInt(i))==1)
+            {
+		lv=line(A,P,Qx,Qy)
+		r.smul(lv)
+            }
+            r.sqr()
+        }
+    
+        lv=line(A,A,Qx,Qy)
+        r.smul(lv)
+	if n.parity()==1 {
+		lv=line(A,P,Qx,Qy)
+		r.smul(lv)
+	}
+    
+    // R-ate fixup required for BN curves
+
+	if ROM.CURVE_PAIRING_TYPE == ROM.BN_CURVE {
+		r.conj()
+		K.copy(P)
+		K.frob(f)
+		A.neg()
+		lv=line(A,K,Qx,Qy)
+		r.smul(lv)
+		K.frob(f)
+		K.neg()
+		lv=line(A,K,Qx,Qy)
+		r.smul(lv)
+	}
+        return r
+    }
+    // Optimal R-ate double pairing e(P,Q).e(R,S)
+    static func ate2(_ P:ECP2,_ Q:ECP,_ R:ECP2,_ S:ECP) -> FP12
+    {
+        let f=FP2(BIG(ROM.CURVE_Fra),BIG(ROM.CURVE_Frb))
+        let x=BIG(ROM.CURVE_Bnx)
+        let n=BIG(x)
+        let K=ECP2()
+        var lv:FP12
+
+ 	if ROM.CURVE_PAIRING_TYPE == ROM.BN_CURVE {
+		n.pmul(6); n.dec(2)
+	} else {n.copy(x)}
+	
+	n.norm()
+        P.affine()
+        Q.affine()
+        R.affine()
+        S.affine()
+    
+        let Qx=FP(Q.getx())
+        let Qy=FP(Q.gety())
+        let Sx=FP(S.getx())
+        let Sy=FP(S.gety())
+    
+        let A=ECP2()
+        let B=ECP2()
+        let r=FP12(1)
+    
+        A.copy(P)
+        B.copy(R)
+        let nb=n.nbits()
+    
+        for i in (1...nb-2).reversed()
+        //for var i=nb-2;i>=1;i--
+        {
+            lv=line(A,A,Qx,Qy)
+            r.smul(lv)
+            lv=line(B,B,Sx,Sy)
+            r.smul(lv)
+            if n.bit(UInt(i))==1
+            {
+		lv=line(A,P,Qx,Qy)
+		r.smul(lv)
+		lv=line(B,R,Sx,Sy)
+		r.smul(lv)
+            }
+            r.sqr()
+        }
+    
+        lv=line(A,A,Qx,Qy)
+        r.smul(lv)
+        lv=line(B,B,Sx,Sy)
+        r.smul(lv)
+	if n.parity()==1 {
+		lv=line(A,P,Qx,Qy)
+		r.smul(lv)
+		lv=line(B,R,Sx,Sy)
+		r.smul(lv)
+	}
+    
+    // R-ate fixup required for BN curves
+
+	if ROM.CURVE_PAIRING_TYPE == ROM.BN_CURVE {
+		r.conj()
+    
+		K.copy(P)
+		K.frob(f)
+		A.neg()
+		lv=line(A,K,Qx,Qy)
+		r.smul(lv)
+		K.frob(f)
+		K.neg()
+		lv=line(A,K,Qx,Qy)
+		r.smul(lv)
+    
+		K.copy(R)
+		K.frob(f)
+		B.neg()
+		lv=line(B,K,Sx,Sy)
+		r.smul(lv)
+		K.frob(f)
+		K.neg()
+		lv=line(B,K,Sx,Sy)
+		r.smul(lv)
+	}
+        return r
+    }
+    
+    // final exponentiation - keep separate for multi-pairings and to avoid thrashing stack
+    static func fexp(_ m:FP12) -> FP12
+    {
+        let f=FP2(BIG(ROM.CURVE_Fra),BIG(ROM.CURVE_Frb));
+        let x=BIG(ROM.CURVE_Bnx)
+        let r=FP12(m)
+    
+    // Easy part of final exp
+        var lv=FP12(r)
+        lv.inverse()
+        r.conj()
+    
+        r.mul(lv)
+        lv.copy(r)
+        r.frob(f)
+        r.frob(f)
+        r.mul(lv)
+        
+    // Hard part of final exp
+	if ROM.CURVE_PAIRING_TYPE == ROM.BN_CURVE {
+		lv.copy(r)
+		lv.frob(f)
+		let x0=FP12(lv)
+		x0.frob(f)
+		lv.mul(r)
+		x0.mul(lv)
+		x0.frob(f)
+		let x1=FP12(r)
+		x1.conj()
+		let x4=r.pow(x)
+
+		let x3=FP12(x4)
+		x3.frob(f)
+    
+		let x2=x4.pow(x)
+    
+		let x5=FP12(x2); x5.conj()
+		lv=x2.pow(x)
+    
+		x2.frob(f)
+		r.copy(x2); r.conj()
+    
+		x4.mul(r)
+		x2.frob(f)
+    
+		r.copy(lv)
+		r.frob(f)
+		lv.mul(r)
+    
+		lv.usqr()
+		lv.mul(x4)
+		lv.mul(x5)
+		r.copy(x3)
+		r.mul(x5)
+		r.mul(lv)
+		lv.mul(x2)
+		r.usqr()
+		r.mul(lv)
+		r.usqr()
+		lv.copy(r)
+		lv.mul(x1)
+		r.mul(x0)
+		lv.usqr()
+		r.mul(lv)
+		r.reduce()
+	} else {
+		let x0=FP12(r)
+		let x1=FP12(r)
+		lv.copy(r); lv.frob(f)
+		let x3=FP12(lv); x3.conj(); x1.mul(x3)
+		lv.frob(f); lv.frob(f)
+		x1.mul(lv)
+
+		r.copy(r.pow(x))  //r=r.pow(x);
+		x3.copy(r); x3.conj(); x1.mul(x3)
+		lv.copy(r); lv.frob(f)
+		x0.mul(lv)
+		lv.frob(f)
+		x1.mul(lv)
+		lv.frob(f)
+		x3.copy(lv); x3.conj(); x0.mul(x3)
+
+		r.copy(r.pow(x))
+		x0.mul(r)
+		lv.copy(r); lv.frob(f); lv.frob(f)
+		x3.copy(lv); x3.conj(); x0.mul(x3)
+		lv.frob(f)
+		x1.mul(lv)
+
+		r.copy(r.pow(x))
+		lv.copy(r); lv.frob(f)
+		x3.copy(lv); x3.conj(); x0.mul(x3)
+		lv.frob(f)
+		x1.mul(lv)
+
+		r.copy(r.pow(x))
+		x3.copy(r); x3.conj(); x0.mul(x3)
+		lv.copy(r); lv.frob(f)
+		x1.mul(lv)
+
+		r.copy(r.pow(x))
+		x1.mul(r)
+
+		x0.usqr()
+		x0.mul(x1)
+		r.copy(x0)
+		r.reduce()
+	}
+        return r
+    }
+    
+    // GLV method
+    static func glv(_ e:BIG) -> [BIG]
+    {
+	var u=[BIG]();
+	if ROM.CURVE_PAIRING_TYPE == ROM.BN_CURVE {
+		let t=BIG(0)
+		let q=BIG(ROM.CURVE_Order)
+		var v=[BIG]();
+		for _ in 0 ..< 2
+		{
+			u.append(BIG(0))
+			v.append(BIG(0))
+		}
+        
+		for i in 0 ..< 2
+		{
+			t.copy(BIG(ROM.CURVE_W[i]))
+			let d=BIG.mul(t,e)
+			v[i].copy(d.div(q))
+		}
+		u[0].copy(e);
+		for i in 0 ..< 2
+		{
+			for j in 0 ..< 2
+			{
+				t.copy(BIG(ROM.CURVE_SB[j][i]))
+				t.copy(BIG.modmul(v[j],t,q))
+				u[i].add(q)
+				u[i].sub(t)
+				u[i].mod(q)
+			}
+		}
+	} else { // -(x^2).P = (Beta.x,y)
+		let q=BIG(ROM.CURVE_Order)
+		let x=BIG(ROM.CURVE_Bnx)
+		let x2=BIG.smul(x,x)
+		u.append(BIG(e))
+		u[0].mod(x2)
+		u.append(BIG(e))
+		u[1].div(x2)
+		u[1].rsub(q)
+
+	}
+        return u
+    }
+    // Galbraith & Scott Method
+    static func gs(_ e:BIG) -> [BIG]
+    {
+        var u=[BIG]();
+	if ROM.CURVE_PAIRING_TYPE == ROM.BN_CURVE {
+		let t=BIG(0)
+		let q=BIG(ROM.CURVE_Order)
+		var v=[BIG]();
+		for _ in 0 ..< 4
+		{
+			u.append(BIG(0))
+			v.append(BIG(0))
+		}
+        
+		for i in 0 ..< 4
+		{
+			t.copy(BIG(ROM.CURVE_WB[i]))
+			let d=BIG.mul(t,e)
+			v[i].copy(d.div(q))
+		}
+		u[0].copy(e);
+		for i in 0 ..< 4
+		{
+			for j in 0 ..< 4
+			{
+				t.copy(BIG(ROM.CURVE_BB[j][i]))
+				t.copy(BIG.modmul(v[j],t,q))
+				u[i].add(q)
+				u[i].sub(t)
+				u[i].mod(q)
+			}
+		}
+	} else {
+		let x=BIG(ROM.CURVE_Bnx)
+		var w=BIG(e)
+		for i in 0 ..< 4
+		{
+			u.append(BIG(w))
+			u[i].mod(x)
+			w.div(x)
+		}
+	}
+        return u
+    }	
+    
+    // Multiply P by e in group G1
+    static func G1mul(_ P:ECP,_ e:BIG) -> ECP
+    {
+        var R:ECP
+        if (ROM.USE_GLV)
+        {
+            P.affine()
+            R=ECP()
+            R.copy(P)
+            let Q=ECP()
+            Q.copy(P)
+            let q=BIG(ROM.CURVE_Order)
+            let cru=FP(BIG(ROM.CURVE_Cru))
+            let t=BIG(0)
+            var u=PAIR.glv(e)
+            Q.getx().mul(cru);
+    
+            var np=u[0].nbits()
+            t.copy(BIG.modneg(u[0],q))
+            var nn=t.nbits()
+            if (nn<np)
+            {
+				u[0].copy(t)
+				R.neg()
+            }
+    
+            np=u[1].nbits()
+            t.copy(BIG.modneg(u[1],q))
+            nn=t.nbits()
+            if (nn<np)
+            {
+				u[1].copy(t)
+				Q.neg()
+            }
+    
+            R=R.mul2(u[0],Q,u[1])
+        }
+        else
+        {
+            R=P.mul(e)
+        }
+        return R
+    }
+    
+    // Multiply P by e in group G2
+    static func G2mul(_ P:ECP2,_ e:BIG) -> ECP2
+    {
+        var R:ECP2
+        if (ROM.USE_GS_G2)
+        {
+            var Q=[ECP2]()
+            let f=FP2(BIG(ROM.CURVE_Fra),BIG(ROM.CURVE_Frb));
+            let q=BIG(ROM.CURVE_Order);
+            var u=PAIR.gs(e);
+    
+            let t=BIG(0);
+            P.affine()
+            Q.append(ECP2())
+            Q[0].copy(P);
+            for i in 1 ..< 4
+            {
+                Q.append(ECP2()); Q[i].copy(Q[i-1]);
+				Q[i].frob(f);
+            }
+            for i in 0 ..< 4
+            {
+				let np=u[i].nbits();
+				t.copy(BIG.modneg(u[i],q));
+				let nn=t.nbits();
+				if (nn<np)
+				{
+                    u[i].copy(t);
+                    Q[i].neg();
+				}
+            }
+    
+            R=ECP2.mul4(Q,u);
+        }
+        else
+        {
+            R=P.mul(e);
+        }
+        return R;
+    }
+    // f=f^e
+    // Note that this method requires a lot of RAM! Better to use compressed XTR method, see FP4.java
+    static func GTpow(_ d:FP12,_ e:BIG) -> FP12
+    {
+        var r:FP12
+        if (ROM.USE_GS_GT)
+        {
+            var g=[FP12]()
+            let f=FP2(BIG(ROM.CURVE_Fra),BIG(ROM.CURVE_Frb))
+            let q=BIG(ROM.CURVE_Order)
+            let t=BIG(0)
+        
+            var u=gs(e)
+            g.append(FP12(0))
+            g[0].copy(d);
+            for i in 1 ..< 4
+            {
+                g.append(FP12(0)); g[i].copy(g[i-1])
+				g[i].frob(f)
+            }
+            for i in 0 ..< 4
+            {
+				let np=u[i].nbits()
+				t.copy(BIG.modneg(u[i],q))
+				let nn=t.nbits()
+				if (nn<np)
+				{
+                    u[i].copy(t)
+                    g[i].conj()
+				}
+            }
+            r=FP12.pow4(g,u)
+        }
+        else
+        {
+            r=d.pow(e)
+        }
+        return r
+    }
+    // test group membership - no longer needed
+    // with GT-Strong curve, now only check that m!=1, conj(m)*m==1, and m.m^{p^4}=m^{p^2}
+/*
+    static func GTmember(m:FP12) -> Bool
+    {
+        if m.isunity() {return false}
+        let r=FP12(m)
+        r.conj()
+        r.mul(m)
+        if !r.isunity() {return false}
+    
+        let f=FP2(BIG(ROM.CURVE_Fra),BIG(ROM.CURVE_Frb))
+    
+        r.copy(m); r.frob(f); r.frob(f)
+        var w=FP12(r); w.frob(f); w.frob(f)
+        w.mul(m)
+        if !ROM.GT_STRONG
+        {
+            if !w.equals(r) {return false}
+            let x=BIG(ROM.CURVE_Bnx)
+            r.copy(m); w=r.pow(x); w=w.pow(x)
+            r.copy(w); r.sqr(); r.mul(w); r.sqr()
+            w.copy(m); w.frob(f)
+        }
+        return w.equals(r)
+    }
+*/   
+}
+
diff --git a/version22/swift/rand.swift b/version22/swift/rand.swift
new file mode 100644
index 0000000..429a0eb
--- /dev/null
+++ b/version22/swift/rand.swift
@@ -0,0 +1,131 @@
+/*
+	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.
+*/
+
+//
+//  rand.swift
+//
+//  Created by Michael Scott on 17/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+//  Cryptographic strong random number generator
+
+/* Marsaglia & Zaman Random number generator constants */
+final public class RAND {
+    private static let NK:Int=21
+    private static let NJ:Int=6
+    private static let NV:Int=8
+    private var ira=[UInt32](repeating: 0,count: NK)
+    private var rndptr:Int=0
+    private var borrow:UInt32=0
+    private var pool_ptr:Int=0
+    private var pool=[UInt8](repeating: 0,count: 32)
+    
+    public func clean()
+    {
+        pool_ptr=0
+        rndptr=0
+        for i in 0 ..< 32 {pool[i]=0}
+        for i in 0 ..< RAND.NK {ira[i]=0}
+        borrow=0;
+    }
+    
+    public init() {clean()}
+    
+    private func sbrand() -> UInt32
+    { /* Marsaglia & Zaman random number generator */
+        rndptr+=1;
+        if rndptr<RAND.NK {return ira[rndptr]}
+        rndptr=0;
+        var k=RAND.NK-RAND.NJ
+        for i in 0 ..< RAND.NK
+        {
+            if k==RAND.NK {k=0}
+            let t=ira[k];
+            let pdiff=t &- ira[i] &- borrow
+            if pdiff<t {borrow=0}
+            if pdiff>t {borrow=1}
+            ira[i]=pdiff
+            k += 1;
+        }
+        return ira[0]
+    }
+    
+    func sirand(_ seed: UInt32)
+    {
+        var m:UInt32=1
+        var s:UInt32=seed
+        borrow=0;
+        rndptr=0
+        ira[0]^=s
+        for i in 1 ..< RAND.NK
+        { /* fill initialisation vector */
+            let ipn=(RAND.NV*i)%RAND.NK
+            ira[ipn]^=m
+            let t=m
+            m=s &- m
+            s=t
+        }
+        for _ in 0 ..< 10000 {sbrand()}
+    }
+    
+    private func fill_pool()
+    {
+        let sh=HASH256()
+        for _ in 0 ..< 128 {sh.process(UInt8(sbrand()&0xff))}
+        pool=sh.hash()
+        pool_ptr=0
+    }
+    
+    private func pack(_ b: [UInt8]) -> UInt32
+    {
+        return (UInt32(b[3])<<24)|(UInt32(b[2])<<16)|(UInt32(b[1])<<8)|(UInt32(b[0]))
+    }
+  
+/* Initialize RNG with some real entropy from some external source */
+    public func seed(_ rawlen: Int,_ raw: [UInt8])
+    { /* initialise from at least 128 byte string of raw random entropy */
+        var digest=[UInt8]()
+        var b=[UInt8](repeating: 0, count: 4)
+        let sh=HASH256()
+        pool_ptr=0
+        for i in 0 ..< RAND.NK {ira[i]=0}
+        if rawlen>0
+        {
+            for i in 0 ..< rawlen {sh.process(raw[i])}
+            digest=sh.hash()
+            
+            for i in 0 ..< 8
+            {
+                b[0]=digest[4*i]; b[1]=digest[4*i+1]; b[2]=digest[4*i+2]; b[3]=digest[4*i+3]
+                sirand(pack(b))
+            }
+            
+        }
+        fill_pool()
+    }
+    
+    public func getByte() -> UInt8
+    {
+        let r=pool[pool_ptr]; pool_ptr+=1
+        if pool_ptr>=32 {fill_pool()}
+        return r
+    }
+    
+    
+}
diff --git a/version22/swift/readme.txt b/version22/swift/readme.txt
new file mode 100644
index 0000000..02d78b2
--- /dev/null
+++ b/version22/swift/readme.txt
@@ -0,0 +1,135 @@
+AMCL is very simple to build for Swift.
+
+
+This version supports both 32-bit and 64-bit builds. 
+If your processor and 
+operating system are both 64-bit, a 64-bit build 
+will probably be best. 
+Otherwise use a 32-bit build.
+
+
+First - decide the modulus and curve type you want to use. Edit rom32.swift 
+
+or rom64.swift where indicated. You will probably want to use one of the 
+curves 
+whose details are already in there. You might want to "raid" the 
+rom
+file from the C version of the library for more curves.
+
+Three example API files are provided, mpin.swift which 
+supports our M-Pin (tm) protocol, ecdh.swift which supports elliptic 
+curve key exchange, digital signature and public key crypto, and rsa.swift
+which supports the RSA method. The first  can be tested using the 
+TestMPIN.swift driver programs, the second can be tested using TestECDH.swift, 
+
+and the third with TestRSA.swift
+
+In the rom32.swift/rom64.swift file you must provide the curve constants. 
+
+Several examples are provided there, if you are willing to use one of these.
+
+To help generate the ROM constants for your own curve some MIRACL helper 
+programs are included. The programs bngen.cpp and blsgen.cpp generate ROM 
+data for a BN and BLS pairing friendly curves, and the program ecgen.cpp 
+generates ROM data for regular EC curves.
+
+The MIRACL based program check.cpp helps choose the best number base for
+big number representation, given the word-length and the size of the modulus.
+
+The program bigtobig.cpp converts a big number to the AMCL 
+BIG format.
+
+For a quick jumpstart:-
+
+
+Copy rom32.swift to rom.swift for a 32-bit build.
+
+
+
+If using Xcode, load all of the swift files into a project. In "Build 
+Options",
+under "Swift Compiler - Custom Flags", set the compilation 
+condition D32. Then 
+build the project. 
+
+
+
+For a 64-bit build copy rom64.swift instead, and set D64 in Xcode. 
+
+Then build 
+and run the program main.swift
+
+
+
+
+Alternatively from a terminal window in a /lib directory create a dynamic 
+
+library using the command
+
+swiftc -DD32 big.swift rom.swift dbig.swift rand.swift hash256.swift hash384.swift hash512.swift fp.swift fp2.swift ecp.swift ecp2.swift aes.swift gcm.swift fp4.swift fp12.swift ff.swift pair.swift rsa.swift ecdh.swift mpin.swift -O -Ounchecked -whole-module-optimization -emit-library -emit-module -module-name amcl
+
+This creates the files 
+
+libamcl.dylib
+amcl.swiftmodule
+
+Copy these to a project directory, which contains only the files 
+
+TestECDH.swift
+TestRSA.swift
+TestMPIN.swift
+
+
+Edit these files to uncomment the line
+
+ 
+
+import amcl
+
+ 
+
+at the start of the program, and 
+
+
+
+TestXXXX()
+
+
+
+at the end of the program
+
+
+Finally create and run the projects by issuing the commands
+
+swift -lamcl -I. TestMPIN.swift 
+swift -lamcl -I. TestECDH.swift 
+swift -lamcl -I. TestRSA.swift 
+
+
+
+
+Note that classes and methods that need to be exposed to consuming programs, 
+should be made "public" when and if needed. Here we have done this as needed 
+just for these example programs.
+
+------------------------------------------------
+
+An alternative method to build applications is to use the swiftc compiler 
+directly. For example:-
+
+Edit main.swift to just include a call to BenchtestPAIR()
+
+Copy rom32.swift to rom.swift
+
+Compile directly using swiftc
+
+swiftc -DD32 -O -Ounchecked -whole-module-optimization main.swift BenchtestPAIR.swift pair.swift fp12.swift fp4.swift fp2.swift fp.swift big.swift dbig.swift ecp.swift ecp2.swift hash256.swift hash384.swift hash512.swift aes.swift rand.swift rom.swift -o main 
+
+Run the BenchtestPAIR() program by
+
+./main
+
+For the files needed to build other applications, see go/readme.txt
+
+Change "32" to "64" for a 64-bit build
+
diff --git a/version22/swift/rom32.swift b/version22/swift/rom32.swift
new file mode 100644
index 0000000..9ac5f11
--- /dev/null
+++ b/version22/swift/rom32.swift
@@ -0,0 +1,645 @@
+/*
+	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.
+*/
+
+//
+//  rom.swift
+//
+//  Created by Michael Scott on 12/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+typealias Chunk = Int32
+typealias DChunk = Int64
+
+final public class ROM{
+    
+    static let CHUNK:Int=32
+    
+    /* Don't Modify from here... */
+    static let NOT_SPECIAL=0
+    static let PSEUDO_MERSENNE=1
+    static let MONTGOMERY_FRIENDLY=2
+    static let GENERALISED_MERSENNE=3
+    static let WEIERSTRASS=0
+    static let EDWARDS=1
+    static let MONTGOMERY=2
+    static let BN_CURVE=0
+    static let BLS_CURVE=1
+
+    /* ...to here */
+    
+/*** Enter Some Field details here  ***/
+// BN254 Curve
+//    static let MODBITS:UInt = 254 /* Number of bits in Modulus */
+//    static let MOD8:UInt = 3   /* Modulus mod 8 */
+//    static let BASEBITS:UInt=29
+//    static let AES_S:UInt=0
+    
+// BN454 Curve
+//    static let MODBITS:UInt = 454 /* Number of bits in Modulus */
+//    static let MOD8:UInt = 3   /* Modulus mod 8 */
+//    static let BASEBITS:UInt=29
+//    static let AES_S:UInt=128
+
+// BLS383 Curve
+  static let MODBITS:UInt = 383
+  static let MOD8:UInt = 3
+  static let BASEBITS:UInt = 28
+  static let AES_S:UInt =  0
+    
+// BLS455 Curve
+//    static let MODBITS:UInt = 455 /* Number of bits in Modulus */
+//    static let MOD8:UInt = 3   /* Modulus mod 8 */
+//    static let BASEBITS:UInt=29
+//    static let AES_S:UInt=128
+	
+// HIFIVE Curve
+//  static let MODBITS:UInt = 336
+//  static let MOD8:UInt = 5
+//  static let BASEBITS:UInt = 29
+//  static let AES_S:UInt=128
+        
+// GOLDILOCKS
+//	static let MODBITS:UInt=448
+//	static let MOD8:UInt=7
+//	static let BASEBITS:UInt=29
+//	static let AES_S:UInt=0
+    
+// NIST384
+//    static let MODBITS:UInt=384
+//    static let MOD8:UInt=7
+//    static let BASEBITS:UInt=29
+//    static let AES_S:UInt=0
+   
+// C41417
+//    static let MODBITS:UInt=414
+//    static let MOD8:UInt=7
+//    static let BASEBITS:UInt=29
+//    static let AES_S:UInt=0
+
+// NIST521
+//    static let MODBITS:UInt=521
+//    static let MOD8:UInt=7
+//    static let BASEBITS:UInt=28
+//    static let AES_S:UInt=0
+
+// BN646
+//    static let MODBITS:UInt=646
+//    static let MOD8:UInt=3
+//    static let BASEBITS:UInt=29
+//    static let AES_S:UInt=192
+
+// Curve 25519
+//    static let MODBITS:UInt=255
+//    static let MOD8:UInt=5
+//    static let BASEBITS:UInt=29
+//    static let AES_S:UInt=0
+
+// NIST256 or Brainpool
+//    static let MODBITS:UInt=256
+//    static let MOD8:UInt=7
+//    static let BASEBITS:UInt=29
+//    static let AES_S:UInt=0
+
+// MF254
+//    static let MODBITS:UInt=254
+//    static let MOD8:UInt=7
+//    static let BASEBITS:UInt=29
+//    static let AES_S:UInt=0
+
+// MS255
+//    static let MODBITS:UInt = 255
+//    static let MOD8:UInt = 3
+//    static let BASEBITS:UInt=29
+//    static let AES_S:UInt=0
+
+// MF256
+//    static let MODBITS:UInt = 256
+//    static let MOD8:UInt = 7
+//    static let BASEBITS:UInt=29
+//    static let AES_S:UInt=0
+
+// MS256
+//    static let MODBITS:UInt = 256
+//    static let MOD8:UInt = 3
+//    static let BASEBITS:UInt=29
+//    static let AES_S:UInt=0
+
+// ANSSI
+//    static let MODBITS:UInt = 256
+//    static let MOD8:UInt = 3
+//    static let BASEBITS:UInt=29
+//    static let AES_S:UInt=0
+
+    static let FFLEN:UInt=4
+    
+/* Don't Modify from here... */
+    static let NLEN:Int=Int(1+((MODBITS-1)/BASEBITS))
+    static let DNLEN:Int=2*NLEN
+    static let BMASK:Chunk=((1<<Chunk(BASEBITS))-1)
+    static let MODBYTES:UInt=(1+(MODBITS-1)/8)
+    static let NEXCESS:Int = (1<<(CHUNK-Int(BASEBITS)-1))
+    static let FEXCESS:Chunk = (1<<Chunk(BASEBITS*UInt(NLEN)-MODBITS));
+    static let OMASK:Chunk=Chunk(-1)<<Chunk(MODBITS%BASEBITS)
+    static let TBITS:UInt=MODBITS%BASEBITS; // Number of active bits in top word
+    static let TMASK:Chunk=(1<<Chunk(TBITS))-1
+    static let BIGBITS:UInt = (MODBYTES*8)
+    static let HBITS = (BASEBITS/2)
+    static let HMASK:Chunk = ((1<<Chunk(HBITS))-1)
+    
+   
+    /* Finite field support - for RSA, DH etc. */
+    static let FF_BITS:UInt=(BIGBITS*FFLEN) /* Finite Field Size in bits - must be BIGBITS.2^n */
+    static let HFLEN=(FFLEN/2);  /* Useful for half-size RSA private key operations */
+    
+    static let P_MBITS:UInt=ROM.MODBYTES*8
+    static let P_OMASK:Chunk=Chunk(-1)<<Chunk(P_MBITS%BASEBITS)
+    static let P_FEXCESS:Chunk=(1<<Chunk(BASEBITS*UInt(NLEN)-P_MBITS))
+    static let P_TBITS=(P_MBITS%ROM.BASEBITS)
+    
+/* ...to here */
+    
+// START SPECIFY FIELD DETAILS HERE
+//*********************************************************************************
+// Curve25519 Modulus
+//    static let MODTYPE=PSEUDO_MERSENNE
+//    static let Modulus:[Chunk]=[0x1FFFFFED,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFFF]
+//    static let MConst:Chunk=19
+    
+// NIST-256 Modulus
+//    static let MODTYPE=NOT_SPECIAL
+//    static let Modulus:[Chunk]=[0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FF,0x0,0x0,0x40000,0x1FE00000,0xFFFFFF]
+//    static let MConst:Chunk=1
+
+// MF254 Modulus
+//    static let MODTYPE=MONTGOMERY_FRIENDLY
+//    static let Modulus:[Chunk]=[0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3F80FF]
+//    static let MConst:Chunk=0x3F8100
+// MS255 Modulus
+//    static let MODTYPE = PSEUDO_MERSENNE
+//    static let Modulus:[Chunk]=[0x1FFFFD03,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFFF]
+//    static let MConst:Chunk=0x2FD
+// MF256 Modulus
+//    static let MODTYPE = MONTGOMERY_FRIENDLY
+//    static let Modulus:[Chunk]=[0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFFA7FF]
+//    static let MConst:Chunk=0xFFA800
+// MS256 Modulus
+//    static let MODTYPE = PSEUDO_MERSENNE
+//    static let Modulus:[Chunk]=[0x1FFFFF43,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFFFFFF]
+//    static let MConst:Chunk = 0xBD
+// Brainpool Modulus
+//    static let MODTYPE = NOT_SPECIAL
+//    static let Modulus:[Chunk]=[0x1F6E5377,0x9A40E8,0x9880A08,0x17EC47AA,0x18D726E3,0x5484EC1,0x6F0F998,0x1B743DD5,0xA9FB57]
+//    static let MConst:Chunk = 0xEFD89B9
+// ANSSI Modulus
+//    static let MODTYPE = NOT_SPECIAL
+//    static let Modulus:[Chunk]=[0x186E9C03,0x7E79A9E,0x12329B7A,0x35B7957,0x435B396,0x16F46721,0x163C4049,0x1181675A,0xF1FD17]
+//    static let MConst:Chunk = 0x164E1155
+    
+// HIFIVE Curve Modulus
+//  static let MODTYPE = PSEUDO_MERSENNE
+//  static let Modulus:[Chunk]=[0x1FFFFFFD,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFF]
+//  static let MConst:Chunk = 0x3
+    
+// GOLDILOCKS Curve Modulus
+//  static let MODTYPE = GENERALISED_MERSENNE
+//  static let Modulus:[Chunk]=[0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FDFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFF]
+//  static let MConst:Chunk = 0x1
+    
+// NIST384 Curve Modulus
+//    static let MODTYPE = NOT_SPECIAL
+//    static let Modulus:[Chunk]=[0x1FFFFFFF,0x7,0x0,0x1FFFFE00,0x1FFFEFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F]
+//    static let MConst:Chunk = 0x1
+   
+// C41417 Curve Modulus
+//    static let MODTYPE = PSEUDO_MERSENNE
+//    static let Modulus:[Chunk]=[0x1FFFFFEF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFF]
+//    static let MConst:Chunk = 0x11
+   
+// NIST521 Curve Modulus
+//    static let MODTYPE = PSEUDO_MERSENNE
+//    static let Modulus:[Chunk]=[0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0x1FFFF]
+//    static let MConst:Chunk = 0x1
+  
+// BN646 Curve Modulus
+//    static let MODTYPE = NOT_SPECIAL
+//    static let Modulus:[Chunk]=[0x404E013,0x1203604,0x4E0000,0x80A2084,0x2,0xC90420,0x4051078,0x3600001,0xA20660,0x36,0x5100900,0x10288468,0xD,0x2881200,0x1B0,0x0,0x6C0D80,0x48,0x0,0x480,0x0,0x0,0x90]
+//    static let MConst:Chunk = 0x15F615E5
+    
+// BNCX Curve Modulus
+//   static let MODTYPE = NOT_SPECIAL
+//   static let Modulus:[Chunk]=[0x1C1B55B3,0x13311F7A,0x24FB86F,0x1FADDC30,0x166D3243,0xFB23D31,0x836C2F7,0x10E05,0x240000]
+//   static let MConst:Chunk=0x19789E85
+
+// BN254 Curve Modulus
+//   static let MODTYPE = NOT_SPECIAL
+//   static let Modulus:[Chunk] = [0x13,0x18000000,0x4E9,0x2000000,0x8612,0x6C00000,0x6E8D1,0x10480000,0x252364]
+//   static let MConst:Chunk=0x179435E5
+    
+// BLS383 Curve
+    static let MODTYPE =  NOT_SPECIAL;
+    static let Modulus:[Chunk] = [0xAAD556B,0xACAAB52,0x5F75D7A,0x1BB0147,0xD5D7520,0xCF73083,0xF99EB16,0x531820,0xA68EA32,0x2C01355,0x552A785,0x5C6105C,0x80A9F7,0x7AC52];
+    static let MConst:Chunk=0x123D0BD;
+    
+
+// BN454 Curve Modulus
+//   static let MODTYPE = NOT_SPECIAL
+//   static let Modulus:[Chunk] = [0x13,0x270,0x2100,0x1C00D89C,0x25084,0xA284,0x24720,0x10803AA1,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000]
+//   static let MConst:Chunk=0x179435E5
+
+// BLS455 Curve Modulus
+ //  static let MODTYPE = NOT_SPECIAL
+ //  static let Modulus:[Chunk] = [0x2AB,0x1500000C,0xAAA55AA,0xB12AAD6,0x6D1BA6C,0xCCA5674,0x12E2CF6E,0xA9F9662,0x34BD939,0x12D8EAB1,0xFD9978E,0x9240600,0xE0F95B,0xAAB9550,0x55555E5,0xAAAAB]
+//   static let MConst:Chunk=0x1F4017FD
+
+    // START SPECIFY CURVE DETAILS HERE
+    //*********************************************************************************
+    // Original Curve25519
+    // 	static let CURVETYPE=MONTGOMERY
+    //	static let CURVE_A:Int = 486662
+    //	static let CURVE_B:[Chunk]=[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0] // not used
+    //	static let CURVE_Order:[Chunk]=[0x1CF5D3ED,0x9318D2,0x1DE73596,0x1DF3BD45,0x14D,0x0,0x0,0x0,0x100000]
+    //	static let CURVE_Gx:[Chunk]=[0x9,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+    //	static let CURVE_Gy:[Chunk]=[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0] // not used
+// Ed25519 Curve
+//    static let CURVETYPE=EDWARDS
+//    static let CURVE_A:Int = -1
+//    static let CURVE_B:[Chunk]=[0x135978A3,0xF5A6E50,0x10762ADD,0x149A82,0x1E898007,0x3CBBBC,0x19CE331D,0x1DC56DFF,0x52036C]
+//    static let CURVE_Order:[Chunk]=[0x1CF5D3ED,0x9318D2,0x1DE73596,0x1DF3BD45,0x14D,0x0,0x0,0x0,0x100000]
+//    static let CURVE_Gx:[Chunk]=[0xF25D51A,0xAB16B04,0x969ECB2,0x198EC12A,0xDC5C692,0x1118FEEB,0xFFB0293,0x1A79ADCA,0x216936]
+//    static let CURVE_Gy:[Chunk]=[0x6666658,0x13333333,0x19999999,0xCCCCCCC,0x6666666,0x13333333,0x19999999,0xCCCCCCC,0x666666]
+  
+// HIFIVE Curve
+//    	static let CURVETYPE=EDWARDS
+//    	static let CURVE_A:Int = 1
+//    	static let CURVE_Order:[Chunk]=[0x1E9FA805,0x197CACB9,0x1E4EEA9E,0x17AD70F,0x1FA9850C,0x38A0A,0x0,0x0,0x0,0x0,0x0,0x4000]
+//    	static let CURVE_B:[Chunk] = [0x2B67,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+//    	static let CURVE_Gx:[Chunk] = [0xC,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+//    	static let CURVE_Gy:[Chunk] = [0x5FE8632,0x15F63428,0xD976C4,0x1AACA194,0x35B6DB5,0x8E3F7A,0x52D1B0E,0xF0A7A36,0x1C161D00,0x8170C70,0x1185AD59,0x181B]
+ 
+// GOLDILOCKS Curve
+//    	static let CURVETYPE=EDWARDS
+//    	static let CURVE_A:Int = 1
+//    	static let CURVE_Order:[Chunk]=[0xB5844F3,0x1BC61495,0x1163D548,0x1984E51B,0x3690216,0xDA4D76B,0xFA7113B,0x1FEF9944,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FF]
+//    	static let CURVE_B:[Chunk] = [0x1FFF6756,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FDFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFF]
+//    	static let CURVE_Gx:[Chunk] = [0x15555555,0xAAAAAAA,0x15555555,0xAAAAAAA,0x15555555,0xAAAAAAA,0x15555555,0x152AAAAA,0xAAAAAAA,0x15555555,0xAAAAAAA,0x15555555,0xAAAAAAA,0x15555555,0xAAAAAAA,0x1555]
+//    	static let CURVE_Gy:[Chunk] = [0xA9386ED,0x1757DE6F,0x13681AF6,0x19657DA3,0x3098BBB,0x12C19D15,0x12E03595,0xE515B18,0x17B7E36D,0x1AC426E,0xDBB5E8,0x10D8560,0x159D6205,0xB8246D9,0x17A58D2B,0x15C0]
+    
+// NIST384 Curve
+//    static let CURVETYPE=WEIERSTRASS
+//    static let CURVE_A:Int = -3
+//    static let CURVE_Order:[Chunk]=[0xCC52973,0x760CB56,0xC29DEBB,0x141B6491,0x12DDF581,0x6C0FA1B,0x1FFF1D8D,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F]
+//    static let CURVE_B:[Chunk] = [0x13EC2AEF,0x142E476E,0xBB4674A,0xC731B14,0x1875AC65,0x447A809,0x4480C50,0xDDFD028,0x19181D9C,0x1F1FC168,0x623815A,0x47DCFC9,0x1312FA7E,0x59]
+//    static let CURVE_Gx:[Chunk] = [0x12760AB7,0x12A2F1C3,0x154A5B0E,0x5E4BB7E,0x2A38550,0xF0412A,0xE6167DD,0xC5174F3,0x146E1D3B,0x1799056B,0x3AC71C7,0x1D160A6F,0x87CA22B,0x55]
+//    static let CURVE_Gy:[Chunk] = [0x10EA0E5F,0x1218EBE4,0x1FA0675E,0x1639C3A,0xB8C00A6,0x1889DAF8,0x11F3A768,0x17A51342,0x9F8F41D,0x1C9496E1,0x1767A62F,0xC4C58DE,0x17DE4A9,0x1B]
+  
+// C41417 Curve
+//    static let CURVETYPE=EDWARDS
+//    static let CURVE_A:Int = 1
+//    static let CURVE_Order:[Chunk]=[0x106AF79,0x18738D2F,0x18F3C606,0x1806715A,0x22B36F1,0xA67B830,0xCF32490,0x1FFFFFFD,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1F]
+//    static let CURVE_B:[Chunk] = [0xE21,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+//    static let CURVE_Gx:[Chunk] = [0x13CBC595,0x7E9C097,0x14DF1931,0x14E7F550,0x1A111301,0x15A6B6B5,0xD526292,0x18FEAFFE,0x1F44C03E,0x1E6A31B4,0x70C9B97,0x43180C6,0x1443300,0x19A4828A,0x68]
+//    static let CURVE_Gy:[Chunk] = [0x22,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+   
+// NIST521 Curve
+//    static let CURVETYPE=WEIERSTRASS
+//    static let CURVE_A:Int = -3
+//    static let CURVE_Order:[Chunk]=[0x1386409,0x6FB71E9,0xC47AEBB,0xC9B8899,0x5D03BB5,0x48F709A,0xB7FCC01,0xBF2F966,0x1868783,0xFFFFFA5,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0x1FFFF]
+//    static let CURVE_B:[Chunk] = [0xB503F00,0x451FD46,0xC34F1EF,0xDF883D2,0xF073573,0xBD3BB1B,0xB1652C0,0xEC7E937,0x6193951,0xF109E15,0x489918E,0x15F3B8B,0x25B99B3,0xEEA2DA7,0xB68540,0x929A21A,0xE1C9A1F,0x3EB9618,0x5195]
+//    static let CURVE_Gx:[Chunk] = [0x2E5BD66,0x7E7E31C,0xA429BF9,0xB3C1856,0x8DE3348,0x27A2FFA,0x8FE1DC1,0xEFE7592,0x14B5E77,0x4D3DBAA,0x8AF606B,0xB521F82,0x139053F,0x429C648,0x62395B4,0x9E3ECB6,0x404E9CD,0x8E06B70,0xC685]
+//    static let CURVE_Gy:[Chunk] = [0xFD16650,0xBE94769,0x2C24088,0x7086A27,0x761353C,0x13FAD0,0xC550B9,0x5EF4264,0x7EE7299,0x3E662C9,0xFBD1727,0x446817A,0x449579B,0xD998F54,0x42C7D1B,0x5C8A5FB,0xA3BC004,0x296A789,0x11839]
+    
+// NIST-256 Curve
+    //	static let CURVETYPE=WEIERSTRASS
+    //    static let CURVE_A:Int = -3;
+    //    static let CURVE_B:[Chunk]=[0x7D2604B,0x1E71E1F1,0x14EC3D8E,0x1A0D6198,0x86BC651,0x1EAABB4C,0xF9ECFAE,0x1B154752,0x5AC635]
+    //    static let CURVE_Order:[Chunk]=[0x1C632551,0x1DCE5617,0x5E7A13C,0xDF55B4E,0x1FFFFBCE,0x1FFFFFFF,0x3FFFF,0x1FE00000,0xFFFFFF]
+    //    static let CURVE_Gx:[Chunk]=[0x1898C296,0x509CA2E,0x1ACCE83D,0x6FB025B,0x40F2770,0x1372B1D2,0x91FE2F3,0x1E5C2588,0x6B17D1]
+    //    static let CURVE_Gy:[Chunk]=[0x17BF51F5,0x1DB20341,0xC57B3B2,0x1C66AED6,0x19E162BC,0x15A53E07,0x1E6E3B9F,0x1C5FC34F,0x4FE342]
+
+    // MF254 Modulus, Weierstrass Curve w-254-mont
+    //    static let CURVETYPE=WEIERSTRASS
+    //    static let CURVE_A:Int = -3
+    //    static let CURVE_B:[Chunk]=[0x1FFFD08D,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3F80FF]
+    //    static let CURVE_Order:[Chunk]=[0xF8DF83F,0x1D20CE25,0x8DD701B,0x317D41B,0x1FFFFEB8,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3F80FF]
+    //    static let CURVE_Gx:[Chunk]=[0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+    //    static let CURVE_Gy:[Chunk]=[0x190D4EBC,0xB2EF9BF,0x14464C6B,0xE71C7F0,0x18AEBDFB,0xD3ADEBB,0x18052B85,0x1A6765CA,0x140E3F]
+    
+    // MF254 Modulus, Edwards Curve ed-254-mont
+    //    static let CURVETYPE = EDWARDS
+    //    static let CURVE_A:Int = -1
+    //    static let CURVE_B:[Chunk]=[0x367B,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+    //    static let CURVE_Order:[Chunk]=[0x46E98C7,0x179E9FF6,0x158BEC3A,0xA60D917,0x1FFFFEB9,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFE03F]
+    //    static let CURVE_Gx:[Chunk]=[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+    //    static let CURVE_Gy:[Chunk]=[0xF2701E5,0x29687ED,0xC84861F,0x535081C,0x3F4E363,0x6A811B,0xCD65474,0x121AD498,0x19F0E6]
+
+    // MF254 Modulus, Montgomery Curve
+    //static let CURVETYPE = MONTGOMERY
+    //static let CURVE_A:Int = -55790;
+    //static let CURVE_B:[Chunk]=[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0] // not used
+    //static let CURVE_Order:[Chunk]=[0x46E98C7,0x179E9FF6,0x158BEC3A,0xA60D917,0x1FFFFEB9,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFE03F]
+    //static let CURVE_Gx:[Chunk]=[0x3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+    //static let CURVE_Gy:[Chunk]=[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0] // not used
+ 
+    // MS255 Modulus, Weierstrass Curve
+    //static let CURVETYPE = WEIERSTRASS
+    //static let CURVE_A:Int = -3
+    //static let CURVE_B:[Chunk]=[0x1FFFAB46,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFFF]
+    //static let CURVE_Order:[Chunk]=[0x1C594AEB,0x1C7D64C1,0x14ACF7EA,0x14705075,0x1FFFF864,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFFF]
+    //static let CURVE_Gx:[Chunk]=[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+    //static let CURVE_Gy:[Chunk]=[0x9CB44BA,0x199FFB3B,0x1F698345,0xD8F19BB,0x17D177DB,0x1FFCD97F,0xCE487A,0x181DB74F,0x6F7A6A]
+
+    // MS255 Modulus, Edwards Curve
+    //static let CURVETYPE = EDWARDS
+    //static let CURVE_A:Int = -1
+    //static let CURVE_B:[Chunk]=[0xEA97,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+    //static let CURVE_Order:[Chunk]=[0x436EB75,0x24E8F68,0x9A0CBAB,0x34F0BDB,0x1FFFFDCF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFF]
+    //static let CURVE_Gx:[Chunk]=[0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+    //static let CURVE_Gy:[Chunk]=[0x108736A0,0x11512ADE,0x1116916E,0x29715DA,0x47E5529,0x66EC706,0x1517B095,0xA694F76,0x26CB78]
+
+    // MS255 Modulus, Montgomery Curve
+    //static let CURVETYPE=MONTGOMERY
+    //static let CURVE_A:Int = -240222
+    //static let CURVE_B:[Chunk]=[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0] // not used
+    //static let CURVE_Order:[Chunk]=[0x436EB75,0x24E8F68,0x9A0CBAB,0x34F0BDB,0x1FFFFDCF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFF]
+    //static let CURVE_Gx:[Chunk]=[0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+    //static let CURVE_Gy:[Chunk]=[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0] // not used
+    
+    // MF256 Modulus, Weierstrass Curve
+    //static let CURVETYPE = WEIERSTRASS
+    //static let CURVE_A:Int = -3;
+    //static let CURVE_B:[Chunk]=[0x14E6A,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+    //static let CURVE_Order:[Chunk]=[0x79857EB,0x8862F0D,0x1941D2E7,0x2EA27CD,0x1FFFFFC5,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFFA7FF]
+    //static let CURVE_Gx:[Chunk]=[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+    //static let CURVE_Gy:[Chunk]=[0xB724D2A,0x3CAA61,0x5371984,0x128FD71B,0x1AE28956,0x1D13091E,0x339EEAE,0x10F7C301,0x20887C]
+    
+    // MF256, Edwards Curve
+    //static let CURVETYPE = EDWARDS
+    //static let CURVE_A:Int = -1
+    //static let CURVE_B:[Chunk]=[0x350A,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+    //static let CURVE_Order:[Chunk]=[0x18EC7BAB,0x16C976F6,0x19CCF259,0x9775F70,0x1FFFFB15,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3FE9FF]
+    //static let CURVE_Gx:[Chunk]=[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+    //static let CURVE_Gy:[Chunk]=[0x12F3C908,0xF553917,0x1FA9A35F,0xBCC91B,0x1AACA0C,0x1779ED96,0x156BABAF,0x1F1F1989,0xDAD8D4]
+   
+    // MF256 Modulus, Montgomery Curve
+    //static let CURVETYPE = MONTGOMERY
+    //static let CURVE_A:Int = -54314
+    //static let CURVE_B:[Chunk]=[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0] // not used
+    //static let CURVE_Order:[Chunk]=[0x18EC7BAB,0x16C976F6,0x19CCF259,0x9775F70,0x1FFFFB15,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3FE9FF]
+    //static let CURVE_Gx:[Chunk]=[0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+    //static let CURVE_Gy:[Chunk]=[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0] // not used
+
+    // MS256, Weierstrass Curve
+    //static let CURVETYPE  = WEIERSTRASS
+    //static let CURVE_A:Int = -3
+    //static let CURVE_B:[Chunk]=[0x25581,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+    //static let CURVE_Order:[Chunk]=[0x751A825,0x559014A,0x9971808,0x1904EBD4,0x1FFFFE43,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFFFFFF]
+    //static let CURVE_Gx:[Chunk]=[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+    //static let CURVE_Gy:[Chunk]=[0x2B56C77,0x1FA31836,0x253B042,0x185F26EB,0xDD6BD02,0x4B66777,0x1B5FF20B,0xA783C8C,0x696F18]
+
+    // MS256, Edwards Curve
+    //static let CURVETYPE = EDWARDS
+    //static let CURVE_A:Int = -1;
+    //static let CURVE_B:[Chunk]=[0x3BEE,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+    //static let CURVE_Order:[Chunk]=[0x1122B4AD,0xDC27378,0x9AF1939,0x154AB5A1,0x1FFFFBE6,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3FFFFF]
+    //static let CURVE_Gx:[Chunk]=[0xD,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+    //static let CURVE_Gy:[Chunk]=[0x131CADBA,0x3FB7DA9,0x134C0FDC,0x14DAC704,0x46BFBE2,0x1859CFD0,0x1B6E8F4C,0x3C5424E,0x7D0AB4]
+
+    // MS256 Modulus, Montgomery Curve
+    //static let CURVETYPE = MONTGOMERY
+    //static let CURVE_A:Int = -61370
+    //static let CURVE_B:[Chunk]=[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0] // not used
+    //static let CURVE_Order:[Chunk]=[0x1122B4AD,0xDC27378,0x9AF1939,0x154AB5A1,0x1FFFFBE6,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x3FFFFF]
+    //static let CURVE_Gx:[Chunk]=[0xb,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+    //static let CURVE_Gy:[Chunk]=[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0] // not used
+    
+    // Brainpool
+    //static let CURVETYPE = WEIERSTRASS
+    //static let CURVE_A:Int = -3
+    //static let CURVE_B:[Chunk]=[0x1EE92B04,0x172C080F,0xBD2495A,0x7D7895E,0x176B7BF9,0x13B99E85,0x1A93F99A,0x18861B09,0x662C61]
+    //static let CURVE_Order:[Chunk]=[0x174856A7,0xF07414,0x1869BDE4,0x12F5476A,0x18D718C3,0x5484EC1,0x6F0F998,0x1B743DD5,0xA9FB57]
+    //static let CURVE_Gx:[Chunk]=[0xE1305F4,0xD0C8AB1,0xBEF0ADE,0x28588F5,0x16149AFA,0x9D91D32,0x1EDDCC88,0x79839FC,0xA3E8EB]
+    //static let CURVE_Gy:[Chunk]=[0x1B25C9BE,0xD5F479A,0x1409C007,0x196DBC73,0x417E69B,0x1170A322,0x15B5FDEC,0x10468738,0x2D996C]
+    
+    // ANSSI
+    //static let CURVETYPE = WEIERSTRASS
+    //static let CURVE_A:Int = -3;
+    //static let CURVE_B:[Chunk]=[0x1B7BB73F,0x3AF6CB3,0xC68600C,0x181935C9,0xC00FDFE,0x1D3AA522,0x4C0352A,0x194A8515,0xEE353F]
+    //static let CURVE_Order:[Chunk]=[0x6D655E1,0x1FEEA2CE,0x14AFE507,0x18CFC281,0x435B53D,0x16F46721,0x163C4049,0x1181675A,0xF1FD17]
+    //static let CURVE_Gx:[Chunk]=[0x198F5CFF,0x64BD16E,0x62DC059,0xFA5B95F,0x23958C2,0x1EA3A4EA,0x7ACC460,0x186AD827,0xB6B3D4]
+    //static let CURVE_Gy:[Chunk]=[0x14062CFB,0x188AD0AA,0x19327860,0x3860FD1,0xEF8C270,0x18F879F6,0x12447E49,0x1EF91640,0x6142E0]
+
+
+    // BN254 Curve
+/*
+    static let CURVETYPE = WEIERSTRASS
+    static let CURVE_PAIRING_TYPE = BN_CURVE
+    static let CURVE_A:Int = 0
+    static let CURVE_B:[Chunk]=[0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+    static let CURVE_Cof:[Chunk]=[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+    static let CURVE_Order:[Chunk]=[0xD,0x8000000,0x428,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364]
+    static let CURVE_Bnx:[Chunk]=[0x1,0x4000000,0x10,0x0,0x0,0x0,0x0,0x0,0x0]
+    static let CURVE_Cru:[Chunk]=[0x7,0xC000000,0x1B3,0x12000000,0x2490,0x11200000,0x126CD,0x0,0x0]
+    static let CURVE_Fra:[Chunk]=[0xF2A6DE9,0xBEF3603,0xFDDF0B8,0x12E9249A,0x953F850,0xDA85423,0x1232D926,0x32425CF,0x1B3776]
+    static let CURVE_Frb:[Chunk]=[0x10D5922A,0xC10C9FC,0x10221431,0xF16DB65,0x16AC8DC1,0x1917ABDC,0xDD40FAA,0xD23DA30,0x9EBEE]
+    static let CURVE_Pxa:[Chunk]=[0x803FB2B,0xF721126,0x62FC364,0x9177691,0x1EDB6A46,0x63F4630,0x18BFAE36,0x176A33D6,0x61A10]
+    static let CURVE_Pxb:[Chunk]=[0x7D54CF3,0xC61A60F,0xDE12DC3,0x1AE8D75C,0xAA5B1F4,0x13C62CC1,0xCCC42A,0x1F374E6F,0x516AA]
+    static let CURVE_Pya:[Chunk]=[0x11CD2B9A,0xF8703C4,0xF826F46,0x1A15CD7B,0x822329B,0x104B34C6,0xD0E6A43,0x140D75F2,0x21897]
+    static let CURVE_Pyb:[Chunk]=[0xB3ACE9B,0x1168D763,0xE7255E2,0xDFFAE,0x18D37B09,0x22B7AF9,0x149A3DB5,0x1CF9162,0xEBB2B]
+    static let CURVE_Gx:[Chunk]=[0x12,0x18000000,0x4E9,0x2000000,0x8612,0x6C00000,0x6E8D1,0x10480000,0x252364]
+    static let CURVE_Gy:[Chunk]=[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+    static let CURVE_W:[[Chunk]]=[[0x3,0x0,0x81,0x3000000,0x618,0x0,0x0,0x0,0x0],[0x1,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0]]
+    static let CURVE_SB:[[[Chunk]]]=[[[0x4,0x8000000,0xA1,0x3000000,0x618,0x0,0x0,0x0,0x0],[0x1,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x1,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0],[0xA,0x8000000,0x3A7,0x1C000000,0x79E1,0x6C00000,0x6E8D1,0x10480000,0x252364]]]
+    static let CURVE_WB:[[Chunk]]=[[0x0,0x4000000,0x10,0x1000000,0x208,0x0,0x0,0x0,0x0],[0x5,0x14000000,0x152,0xE000000,0x1C70,0xC00000,0xC489,0x0,0x0],[0x3,0xC000000,0xB1,0x7000000,0xE38,0x10600000,0x6244,0x0,0x0],[0x1,0xC000000,0x30,0x1000000,0x208,0x0,0x0,0x0,0x0]]
+    static let CURVE_BB:[[[Chunk]]]=[[[0xD,0x4000000,0x418,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364],[0xC,0x4000000,0x418,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364],[0xC,0x4000000,0x418,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364],[0x2,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x1,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0],[0xC,0x4000000,0x418,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364],[0xD,0x4000000,0x418,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364],[0xC,0x4000000,0x418,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364]],[[0x2,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0],[0x1,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0],[0x1,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0],[0x1,0x8000000,0x20,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x2,0x4000000,0x10,0x0,0x0,0x0,0x0,0x0,0x0],[0x2,0x10000000,0x40,0x0,0x0,0x0,0x0,0x0,0x0],[0xA,0x0,0x408,0x1F000000,0x7FF9,0x6C00000,0x6E8D1,0x10480000,0x252364],[0x2,0x4000000,0x10,0x0,0x0,0x0,0x0,0x0,0x0]]]
+
+    static let USE_GLV = true
+    static let USE_GS_G2 = true
+    static let USE_GS_GT = true
+    static let GT_STRONG = false
+*/
+
+    // BLS383 Curve
+    
+    static let CURVETYPE = WEIERSTRASS;
+    static let CURVE_PAIRING_TYPE = BLS_CURVE;
+    static let CURVE_A:Int = 0;
+    
+    static let CURVE_Order:[Chunk]=[0xFFF001,0xFFF8000,0xFE7800,0xBFDE007,0xC5EDF1C,0x3000049,0x910007A,0xC40007F,0x641004C,0x14,0x0,0x0,0x0,0x0];
+    static let CURVE_B:[Chunk]=[0x9,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+    static let CURVE_Cof:[Chunk]=[0x52B,0x2A00,0xAAB2CA0,0x5560AAA,0x6055,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+    static let CURVE_Gx:[Chunk]=[0xD10786B,0xD59B348,0x3F54AD0,0x3477C0E,0x4578B9B,0xBF25B73,0x7BB6F65,0x4F6AC00,0xFF57E9C,0xEFD5830,0xFB6EC02,0xADB9F88,0xEE4BC98,0xB08C];
+    static let CURVE_Gy:[Chunk]=[0xD145DDB,0x5DA023,0x5FEF7CC,0x13F518C,0x2B2A66F,0x56EC346,0xC7A925F,0x96F3019,0x981223E,0x9061047,0x8F5BE59,0x4810AD,0x9337671,0x1F390];
+    
+    static let CURVE_Bnx:[Chunk]=[0x40,0x100,0x110,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+    static let CURVE_Cru:[Chunk]=[0xDA155A9,0xA3AAC4E,0x61E5E3D,0xDF2FE87,0xE632625,0xBCDFAAD,0xD3035A6,0x5123128,0xBEAD683,0xDBF3A2B,0x424190,0x5C5FAB2,0x80A9F7,0x7AC52];
+    static let CURVE_Fra:[Chunk]=[0x2B4508B,0x2BA59A9,0x6EEF343,0x63DB7A0,0x1DFBC74,0x40341CB,0x32D55D3,0x1639E9D,0x5CC36D4,0xB19B3F0,0xD86AB98,0xF323EE4,0xB198672,0x5A5F];
+    static let CURVE_Frb:[Chunk]=[0x7F904E0,0x81051A9,0xF086A37,0xB7D49A6,0xB7DB8AB,0x8F3EEB8,0xC6C9543,0xEEF7983,0x49CB35D,0x7A65F65,0x7CBFBEC,0x693D177,0x5672384,0x751F2];
+    static let CURVE_Pxa:[Chunk]=[0xBAC9472,0x6059885,0xE2DC36D,0x7C4D31D,0x8C88A7,0xBDC90C3,0x1C688FC,0x29F0197,0xC43F167,0x3693539,0x61EB8BF,0xD81E5A5,0x22B56BF,0x4D507];
+    static let CURVE_Pxb:[Chunk]=[0x272AB23,0x9B4BD7A,0xF44DCE8,0x7AF19D4,0x3206A34,0x3F6F7B9,0x2A819FB,0x571DD3E,0x635D7EE,0x3A2BA3B,0xC1A126,0xAC28C78,0x17C3E5B,0xEE36];
+    static let CURVE_Pya:[Chunk]=[0x77BD4FD,0x81D2309,0xDFDFC6,0xB66072,0xC89A0C,0x41FC959,0x878287A,0x2E1FBCF,0x14EEE65,0x11C230,0x6BB325E,0x2887881,0x859A05C,0x8F40];
+    static let CURVE_Pyb:[Chunk]=[0x52C4CE6,0xA5E20A2,0xAFF40C8,0x5907A74,0x2448EF3,0x41760A4,0xFDA199,0xFFEF82B,0x8D4EA49,0xA0F29A1,0x6E4997B,0xAC7F7B8,0xBA88C12,0x1DCAB];
+    
+    static let CURVE_W:[[Chunk]]=[[],[]];
+    static let CURVE_SB:[[[Chunk]]]=[[[],[]],[[],[]]];
+    static let CURVE_WB:[[Chunk]]=[[],[],[],[]];
+    static let CURVE_BB:[[[Chunk]]]=[[[],[],[],[]],[[],[],[],[]],[[],[],[],[]],[[],[],[],[]]];
+    
+    static let USE_GLV = true
+    static let USE_GS_G2 = true
+    static let USE_GS_GT = true
+    static let GT_STRONG = false
+    
+    // BN454 Curve
+/*
+    static let CURVETYPE = WEIERSTRASS
+    static let CURVE_PAIRING_TYPE = BN_CURVE
+    static let CURVE_A:Int = 0
+
+    static let CURVE_Order:[Chunk]=[0xD,0x210,0x1F80,0x400D884,0x24FC4,0xA27E,0x10024708,0xFC03A9F,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000]
+    static let CURVE_B:[Chunk]=[0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+    static let CURVE_Cof:[Chunk]=[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+    static let CURVE_Gx:[Chunk]=[0x12,0x270,0x2100,0x1C00D89C,0x25084,0xA284,0x24720,0x10803AA1,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000]
+    static let CURVE_Gy:[Chunk]=[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+
+    static let CURVE_Bnx:[Chunk]=[0x1,0x8,0x0,0x2000002,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+    static let CURVE_Cru:[Chunk]=[0x7,0xD8,0x900,0x16002436,0x481,0x1B24,0x168,0x48006C9,0x1600006C,0x10000091,0xD80000D,0x240000,0x0,0x0,0x0,0x0]
+    static let CURVE_Fra:[Chunk]=[0x1573B0EC,0x1816E4FE,0xA42E6E0,0x15DDCD87,0x2B17EC7,0x35B9A50,0x15AA1F74,0x1B7B2AC5,0x1CB5A200,0x9937657,0x17389A4A,0x738BADB,0xD92B321,0x3F5F0E6,0x1B1C9E9A,0x25CF3]
+    static let CURVE_Frb:[Chunk]=[0xA8C4F27,0x7E91D71,0x15BD3A1F,0x6230B14,0x1D50D1BD,0x1CA50833,0xA5827AB,0x15050FDB,0x74B3887,0x166C9A92,0x19C78A3C,0x199F4886,0x1B6D4F39,0x80A0F61,0x7236169,0x2230C]
+    static let CURVE_Pxa:[Chunk]=[0xF02B14,0x1DD1DD61,0x330AEC7,0x178617DE,0x1CEFFF36,0x116D35AF,0x1F879FBF,0x105DBF83,0x8345436,0x13664BCA,0x12EE86B5,0x776BB31,0x14AAFE16,0x41B3478,0x13E03554,0x2807A]
+    static let CURVE_Pxb:[Chunk]=[0x45BF266,0xE036876,0x8F0DBA,0xCB5976F,0x10DBC523,0x1723123C,0xBDDA7F4,0x10077CDE,0x11971DE0,0x14F1554A,0x195995EE,0x82E6FD7,0x40D5258,0x1400A58F,0x15A7850B,0x2B2A5]
+    static let CURVE_Pya:[Chunk]=[0x1E1B15C7,0x9CD5B5D,0x1571B2D2,0x1E4C048A,0x1474FB5D,0x18E2328C,0x11775519,0x144EF51F,0xF2FAABA,0x438F741,0x1930EAC0,0x144DC38,0x1287A0FE,0x36D8962,0x10011EAF,0x3ACF4]
+    static let CURVE_Pyb:[Chunk]=[0x571D60,0x8737DB,0xC4A363B,0x124E308F,0x13A65C7E,0x1387693A,0x10CDDA2F,0x184C096E,0x385175,0x5A34088,0xF17A93C,0x1E194915,0x1903ED91,0x4D6FA9F,0x8D8210B,0x12EDC]
+    static let CURVE_W:[[Chunk]]=[[0x3,0x40,0x180,0x10000010,0xC0,0x6,0x10000018,0xC00001,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]
+    static let CURVE_SB:[[[Chunk]]]=[[[0x4,0x50,0x180,0x14000014,0xC0,0x6,0x10000018,0xC00001,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x1,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0xA,0x1D0,0x1E00,0x1400D874,0x24F03,0xA278,0x246F0,0xF003A9E,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000]]]
+    static let CURVE_WB:[[Chunk]]=[[0x0,0x8,0x80,0x2000002,0x40,0x2,0x10000008,0x400000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x5,0xA8,0x700,0xA00182A,0x381,0x121C,0x100,0x3800487,0x4000048,0x61,0x9000009,0x180000,0x0,0x0,0x0,0x0],[0x3,0x58,0x380,0x16000C16,0x1C0,0x90E,0x10000080,0x1C00243,0x12000024,0x10000030,0x4800004,0xC0000,0x0,0x0,0x0,0x0],[0x1,0x18,0x80,0x6000006,0x40,0x2,0x10000008,0x400000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]
+    static let CURVE_BB:[[[Chunk]]]=[[[0xD,0x208,0x1F80,0x200D882,0x24FC4,0xA27E,0x10024708,0xFC03A9F,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000],[0xC,0x208,0x1F80,0x200D882,0x24FC4,0xA27E,0x10024708,0xFC03A9F,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000],[0xC,0x208,0x1F80,0x200D882,0x24FC4,0xA27E,0x10024708,0xFC03A9F,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000],[0x2,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x1,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0xC,0x208,0x1F80,0x200D882,0x24FC4,0xA27E,0x10024708,0xFC03A9F,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000],[0xD,0x208,0x1F80,0x200D882,0x24FC4,0xA27E,0x10024708,0xFC03A9F,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000],[0xC,0x208,0x1F80,0x200D882,0x24FC4,0xA27E,0x10024708,0xFC03A9F,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000]],[[0x2,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x2,0x8,0x0,0x2000002,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x2,0x20,0x0,0x8000008,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0xA,0x200,0x1F80,0xD880,0x24FC4,0xA27E,0x10024708,0xFC03A9F,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000],[0x2,0x8,0x0,0x2000002,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]]
+
+    static let USE_GLV = true
+    static let USE_GS_G2 = true
+    static let USE_GS_GT = true
+    static let GT_STRONG = false
+*/
+    // BLS455 Curve
+/*
+    static let CURVETYPE = WEIERSTRASS
+    static let CURVE_PAIRING_TYPE = BLS_CURVE
+    static let CURVE_A:Int = 0
+
+    static let CURVE_Order:[Chunk]=[0x1FC00001,0x3FFF,0x10000070,0x1400000,0x1D100,0xF0003A8,0x13C0009,0x1E200,0x180002E0,0x400001,0x4000,0x0,0x0,0x0,0x0,0x0]
+    static let CURVE_B:[Chunk]=[0xA,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+    static let CURVE_Cof:[Chunk]=[0xABFFAAB,0x14AABFFD,0xD52AADA,0x1562AAAB,0x15556AAA,0x2A,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+    static let CURVE_Gx:[Chunk]=[0x1DFCEDD1,0x16A62EEF,0xE80D3ED,0xB8DE876,0x179C7253,0x182DAB52,0x46CC85F,0x1E571D9C,0x1E8392B1,0x1A155867,0x19E6527C,0x23DC64E,0xABEDA59,0xF20662B,0x17CECC01,0x310A]
+    static let CURVE_Gy:[Chunk]=[0x6619B9B,0x27EBCD,0x1BE80A19,0x13B014BA,0x191A4936,0x13911916,0x107A5A3B,0x1DCB0863,0x1F5FB1,0xDE44A9C,0x18E23B2A,0x1FA81FD3,0xB0D6DFA,0xC2FE1EF,0xDDFA7E2,0x3351B]
+
+    static let CURVE_Bnx:[Chunk]=[0x800,0x1000004,0x40000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+    static let CURVE_Cru:[Chunk]=[0xAA9,0x9017FE0,0x128DD8AA,0x1F4A321E,0x148FEC90,0x195CDEEA,0xE961AA2,0x168D3B66,0xAFD99D7,0xB989AA6,0x1F9A5724,0x91A05FF,0xE0EF5B,0xAAB9548,0x55555E5,0xAAAAB]
+    static let CURVE_Fra:[Chunk]=[0xA2EBF21,0x4E67DEE,0xCDE6590,0xE5EA94E,0x15454985,0x140CFC43,0x7E14D1C,0x1778395A,0x1944F022,0x166BEA1A,0xC3DEEA0,0x9F031A0,0x16A7459,0x1F1D6E00,0x125CFB72,0x72FD4]
+    static let CURVE_Frb:[Chunk]=[0x15D1438A,0x1019821D,0x1DCBF01A,0x1CB40187,0x118C70E6,0x18BD5A30,0xB018251,0x13275D08,0xA06E916,0x1C6D0096,0x39BA8ED,0x1F33D460,0x1F768501,0xB8E274F,0x12F85A72,0x37AD6]
+    static let CURVE_Pxa:[Chunk]=[0x10C1F542,0x23AF907,0x159F840,0xBAC0E1F,0x133D7766,0x1C034C5D,0x14C5C875,0x1ED0BDA2,0x16A49C71,0x1E9FF62D,0x14F3ACC0,0x1E0C9FEA,0xC4638DE,0x74D18DA,0xBEA0030,0x5D962]
+    static let CURVE_Pxb:[Chunk]=[0x749F03D,0xC843773,0xB17BCBA,0x1134AB4B,0x8EA016E,0x1A0D766C,0x58F819E,0x48A1FCC,0xE296F62,0x83370E4,0xC9BA1D5,0x1E43290E,0xEE59A80,0x1FDD85F5,0x1F3819B6,0x1D9F]
+    static let CURVE_Pya:[Chunk]=[0x181A77F4,0x191AD22,0x1E9F842A,0x1E1E6CF6,0xD55B9D9,0x1D062533,0x15BB1323,0x7ECBC1,0x1A9EC2EF,0x1EE14CE0,0x1E96B271,0xA794439,0x1C544324,0xE6AD5DC,0x16429B0F,0x448E3]
+    static let CURVE_Pyb:[Chunk]=[0x1E1FDBA2,0x1A09DB6C,0xF680D5B,0xFCC6122,0xC488E2A,0x1E489ECD,0x1005617E,0x1CF9EC36,0x1C89ED72,0x16C00D90,0x1563E595,0x1243DDC0,0x8698F9E,0x1BD81E7E,0xF2A0F4A,0x66A0]
+
+// Not used
+//    static let CURVE_W:[[Chunk]]=[[0x3,0x40,0x180,0x10000010,0xC0,0x6,0x10000018,0xC00001,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]
+//    static let CURVE_SB:[[[Chunk]]]=[[[0x4,0x50,0x180,0x14000014,0xC0,0x6,0x10000018,0xC00001,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x1,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0xA,0x1D0,0x1E00,0x1400D874,0x24F03,0xA278,0x246F0,0xF003A9E,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000]]]
+//    static let CURVE_WB:[[Chunk]]=[[0x0,0x8,0x80,0x2000002,0x40,0x2,0x10000008,0x400000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x5,0xA8,0x700,0xA00182A,0x381,0x121C,0x100,0x3800487,0x4000048,0x61,0x9000009,0x180000,0x0,0x0,0x0,0x0],[0x3,0x58,0x380,0x16000C16,0x1C0,0x90E,0x10000080,0x1C00243,0x12000024,0x10000030,0x4800004,0xC0000,0x0,0x0,0x0,0x0],[0x1,0x18,0x80,0x6000006,0x40,0x2,0x10000008,0x400000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]
+//    static let CURVE_BB:[[[Chunk]]]=[[[0xD,0x208,0x1F80,0x200D882,0x24FC4,0xA27E,0x10024708,0xFC03A9F,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000],[0xC,0x208,0x1F80,0x200D882,0x24FC4,0xA27E,0x10024708,0xFC03A9F,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000],[0xC,0x208,0x1F80,0x200D882,0x24FC4,0xA27E,0x10024708,0xFC03A9F,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000],[0x2,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x1,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0xC,0x208,0x1F80,0x200D882,0x24FC4,0xA27E,0x10024708,0xFC03A9F,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000],[0xD,0x208,0x1F80,0x200D882,0x24FC4,0xA27E,0x10024708,0xFC03A9F,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000],[0xC,0x208,0x1F80,0x200D882,0x24FC4,0xA27E,0x10024708,0xFC03A9F,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000]],[[0x2,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1,0x10,0x0,0x4000004,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x2,0x8,0x0,0x2000002,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x2,0x20,0x0,0x8000008,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0xA,0x200,0x1F80,0xD880,0x24FC4,0xA27E,0x10024708,0xFC03A9F,0x400DA88,0x10EA,0x11002487,0xD80362,0x900025B,0xC000048,0x2400003,0x48000],[0x2,0x8,0x0,0x2000002,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]]
+
+    static let CURVE_W:[[Chunk]]=[[],[]]
+    static let CURVE_SB:[[[Chunk]]]=[[[],[]],[[],[]]]
+    static let CURVE_WB:[[Chunk]]=[[],[],[],[]]
+    static let CURVE_BB:[[[Chunk]]]=[[[],[],[],[]],[[],[],[],[]],[[],[],[],[]],[[],[],[],[]]]
+
+
+    static let USE_GLV = true
+    static let USE_GS_G2 = true
+    static let USE_GS_GT = true
+    static let GT_STRONG = false
+*/
+    // BNCX Curve
+ /*
+    static let CURVETYPE = WEIERSTRASS
+    static let CURVE_PAIRING_TYPE = BN_CURVE
+    static let CURVE_A:Int = 0
+    static let CURVE_B:[Chunk]=[0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+    static let CURVE_Cof:[Chunk]=[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+    static let CURVE_Order:[Chunk]=[0x16EB1F6D,0x108E0531,0x1241B3AF,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000]
+    static let CURVE_Bnx:[Chunk]=[0x3C012B1,0x0,0x10,0x0,0x0,0x0,0x0,0x0,0x0]
+    static let CURVE_Cru:[Chunk]=[0x14235C97,0xF0498BC,0x1BE1D58C,0x1BBEC8E3,0x3F1440B,0x654,0x12000,0x0,0x0]
+    static let CURVE_Fra:[Chunk]=[0x15C80EA3,0x1EC8419A,0x1CFE0856,0xEE64DE2,0x11898686,0x5C55653,0x592BF86,0x5F4C740,0x135908]
+    static let CURVE_Frb:[Chunk]=[0x6534710,0x1468DDE0,0x551B018,0x10C78E4D,0x4E3ABBD,0x9ECE6DE,0x2A40371,0x1A0C46C5,0x10A6F7]
+    static let CURVE_Pxa:[Chunk]=[0x4D2EC74,0x428E777,0xF89C9B0,0x190B7F40,0x14BBB907,0x12807AE1,0x958D62C,0x58E0A76,0x19682D]
+    static let CURVE_Pxb:[Chunk]=[0xE29CFE1,0x1D2C7459,0x270C3D1,0x172F6184,0x19743F81,0x49BD474,0x192A8047,0x1D87C33E,0x1466B9]
+    static let CURVE_Pya:[Chunk]=[0xF0BE09F,0x7DFE75E,0x1FB06CC3,0x3667B08,0xE209636,0x110ABED7,0xE376078,0x1B2E4665,0xA79ED]
+    static let CURVE_Pyb:[Chunk]=[0x898EE9D,0xC825914,0x14BB7AFB,0xC9D4AD3,0x13461C28,0x122896C6,0x240D71B,0x73D9898,0x6160C]
+    static let CURVE_Gx:[Chunk]=[0x1C1B55B2,0x13311F7A,0x24FB86F,0x1FADDC30,0x166D3243,0xFB23D31,0x836C2F7,0x10E05,0x240000]
+    static let CURVE_Gy:[Chunk]=[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+    static let CURVE_W:[[Chunk]]=[[0x162FEB83,0x2A31A48,0x100E0480,0x16,0x600,0x0,0x0,0x0,0x0],[0x7802561,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0]]
+
+    
+    static let CURVE_SB:[[[Chunk]]]=[[[0x1DB010E4,0x2A31A48,0x100E04A0,0x16,0x600,0x0,0x0,0x0,0x0],[0x7802561,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x7802561,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0],[0xBB33EA,0xDEAEAE9,0x233AF2F,0x1FADDC03,0x166D2643,0xFB23D31,0x836C2F7,0x10E05,0x240000]]]
+    
+    static let CURVE_WB:[[Chunk]]=[[0x167A84B0,0xE108C2,0x1004AC10,0x7,0x200,0x0,0x0,0x0,0x0],[0x1E220475,0x166FCCAD,0x129FE68D,0x1D29DB51,0x2A0DC07,0x438,0xC000,0x0,0x0],[0xF10B93,0x1B37E657,0x194FF34E,0x1E94EDA8,0x1506E03,0x21C,0x6000,0x0,0x0],[0x1DFAAA11,0xE108C2,0x1004AC30,0x7,0x200,0x0,0x0,0x0,0x0]]
+    
+    static let CURVE_BB:[[[Chunk]]]=[[[0x132B0CBD,0x108E0531,0x1241B39F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000],[0x132B0CBC,0x108E0531,0x1241B39F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000],[0x132B0CBC,0x108E0531,0x1241B39F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000],[0x7802562,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x7802561,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0],[0x132B0CBC,0x108E0531,0x1241B39F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000],[0x132B0CBD,0x108E0531,0x1241B39F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000],[0x132B0CBC,0x108E0531,0x1241B39F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000]],[[0x7802562,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0],[0x7802561,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0],[0x7802561,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0],[0x7802561,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x3C012B2,0x0,0x10,0x0,0x0,0x0,0x0,0x0,0x0],[0xF004AC2,0x0,0x40,0x0,0x0,0x0,0x0,0x0,0x0],[0xF6AFA0A,0x108E0531,0x1241B38F,0x1FADDC19,0x166D2C43,0xFB23D31,0x836C2F7,0x10E05,0x240000],[0x3C012B2,0x0,0x10,0x0,0x0,0x0,0x0,0x0,0x0]]]
+    
+    static let USE_GLV = true
+    static let USE_GS_G2 = true
+    static let USE_GS_GT = true
+    static let GT_STRONG = true
+*/
+    
+// BN646 Curve
+/*
+    static let CURVETYPE=WEIERSTRASS
+    static let CURVE_PAIRING_TYPE = BN_CURVE
+    static let CURVE_A:Int = 0
+    static let CURVE_Order:[Chunk]=[0x1E04200D,0x1203603,0x420000,0x80A207E,0x2,0xC303F0,0x4051075,0x3600001,0xA20630,0x36,0x5100900,0x1028845C,0xD,0x2881200,0x1B0,0x0,0x6C0D80,0x48,0x0,0x480,0x0,0x0,0x90]
+    static let CURVE_B:[Chunk] = [0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+    static let CURVE_Cof:[Chunk] = [0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+    static let CURVE_Gx:[Chunk] = [0x404E012,0x1203604,0x4E0000,0x80A2084,0x2,0xC90420,0x4051078,0x3600001,0xA20660,0x36,0x5100900,0x10288468,0xD,0x2881200,0x1B0,0x0,0x6C0D80,0x48,0x0,0x480,0x0,0x0,0x90]
+    static let CURVE_Gy:[Chunk] = [0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+    
+    static let CURVE_Bnx:[Chunk]=[0x1001,0x0,0x10000,0x0,0x0,0x8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+    static let CURVE_Cru:[Chunk]=[0x401B007,0x901,0x1B0000,0x1B024,0x0,0x288120,0xD812,0x900000,0x1B0120,0x0,0xD80000,0x6C048,0x0,0x6C0000,0x0,0x0,0x120000,0x0,0x0,0x0,0x0,0x0,0x0]
+    static let CURVE_Fra:[Chunk]=[0x4929A14,0x3B756CA,0x4337DD0,0xFC1417C,0x193166BB,0x1DC54515,0x1C0DF653,0x19BF8961,0x155980E,0x1983CB14,0x4D76309,0x1DEAB1A4,0xF9C3CF5,0x128FEC2D,0x867E339,0xDA0548A,0x1A480AF,0xA3CBCD2,0x116DA6E0,0x2A546E9,0x789577C,0x1F9459D2,0x27]
+    static let CURVE_Frb:[Chunk]=[0x1F7245FF,0x1D68DF39,0x1C1A822F,0x1848DF07,0x6CE9946,0x303BF0A,0x7F71A24,0x9A0769F,0x1F4C6E51,0x67C3521,0x38A5F6,0x123DD2C4,0x1063C317,0xFF825D2,0x17981E76,0x125FAB75,0x1EC78CD0,0x15C34375,0xE92591F,0x1D5ABD96,0x1876A883,0x6BA62D,0x68]
+    static let CURVE_Pxa:[Chunk]=[0x1CCC5E10,0x119F939,0xC6C7FE9,0x81022FF,0x6486AA6,0x1CBC560B,0x1F707429,0xC82F7B9,0x1A7F5CDA,0x14C0EB47,0x11412373,0x13DAF21E,0x126BE416,0x166744A7,0x506E81,0x1048FFA3,0x13A6B0C9,0x1A90979A,0xE78C338,0x1722C561,0xBFFF9A1,0xC1AF83C,0x3F]
+    static let CURVE_Pxb:[Chunk]=[0x67F4BC0,0x1BFC3C9,0x1E9DC3B6,0x87E2B03,0xB820274,0x1DD03B1E,0x517C463,0x1EFCBBC9,0x19F786A8,0x5572E90,0xD0BA5E0,0x16E8A40A,0x1013CF3B,0x11A7F82B,0x1C27B302,0x15E7CD12,0xB79A6DF,0x1EC6895B,0x5775A7E,0xBB28D24,0x416A171,0x127D284E,0x5D]
+    static let CURVE_Pya:[Chunk]=[0xC3FB414,0x2B868EE,0xD858793,0x157FCFE,0x16C849AD,0x1D17B0A4,0x1353CFEA,0x940A061,0x1CEF834E,0x7BE766A,0x4584C1C,0xE2397E9,0x418E9D4,0x8F53B8,0x53B37E0,0x11CA29D9,0xE425654,0x9EFF9AF,0x18CF27A1,0x17755A26,0x3F5481A,0x6C531BC,0x1E]
+    static let CURVE_Pyb:[Chunk]=[0x133908AD,0x17F1F1ED,0x14196532,0x19A85214,0x173EC3F7,0x1021EC2C,0xD798A3E,0x18F4C857,0x82EE2FA,0x11B5296D,0x1831D9C6,0x4463DB5,0x11B4812C,0xF93B884,0xC72653,0xEC6F6ED,0x916CFFF,0x1E81ED0A,0x1103518E,0x1E478B01,0x6B01074,0xC46CCAA,0x48]
+ 
+    static let CURVE_W:[[Chunk]]=[[0x6008003,0x0,0x80000,0x6,0x0,0x40030,0x3,0x0,0x30,0x0,0x0,0xC,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x2001,0x0,0x20000,0x0,0x0,0x10000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]
+    
+    static let CURVE_SB:[[[Chunk]]]=[[[0x600A004,0x0,0xA0000,0x6,0x0,0x50030,0x3,0x0,0x30,0x0,0x0,0xC,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x2001,0x0,0x20000,0x0,0x0,0x10000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x2001,0x0,0x20000,0x0,0x0,0x10000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1803A00A,0x1203603,0x3A0000,0x80A2078,0x2,0xBF03C0,0x4051072,0x3600001,0xA20600,0x36,0x5100900,0x10288450,0xD,0x2881200,0x1B0,0x0,0x6C0D80,0x48,0x0,0x480,0x0,0x0,0x90]]]
+    
+    static let CURVE_WB:[[Chunk]]=[[0x2001000,0x0,0x10000,0x2,0x0,0x8010,0x1,0x0,0x10,0x0,0x0,0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1C015005,0x600,0x150000,0x1201C,0x0,0x1C80E0,0x900E,0x600000,0x1200E0,0x0,0x900000,0x48038,0x0,0x480000,0x0,0x0,0xC0000,0x0,0x0,0x0,0x0,0x0,0x0],[0xE00B003,0x300,0xB0000,0x900E,0x0,0xE8070,0x4807,0x300000,0x90070,0x0,0x480000,0x2401C,0x0,0x240000,0x0,0x0,0x60000,0x0,0x0,0x0,0x0,0x0,0x0],[0x2003001,0x0,0x30000,0x2,0x0,0x18010,0x1,0x0,0x10,0x0,0x0,0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]
+    
+    static let CURVE_BB:[[[Chunk]]]=[[[0x1E04100D,0x1203603,0x410000,0x80A207E,0x2,0xC283F0,0x4051075,0x3600001,0xA20630,0x36,0x5100900,0x1028845C,0xD,0x2881200,0x1B0,0x0,0x6C0D80,0x48,0x0,0x480,0x0,0x0,0x90],[0x1E04100C,0x1203603,0x410000,0x80A207E,0x2,0xC283F0,0x4051075,0x3600001,0xA20630,0x36,0x5100900,0x1028845C,0xD,0x2881200,0x1B0,0x0,0x6C0D80,0x48,0x0,0x480,0x0,0x0,0x90],[0x1E04100C,0x1203603,0x410000,0x80A207E,0x2,0xC283F0,0x4051075,0x3600001,0xA20630,0x36,0x5100900,0x1028845C,0xD,0x2881200,0x1B0,0x0,0x6C0D80,0x48,0x0,0x480,0x0,0x0,0x90],[0x2002,0x0,0x20000,0x0,0x0,0x10000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x2001,0x0,0x20000,0x0,0x0,0x10000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1E04100C,0x1203603,0x410000,0x80A207E,0x2,0xC283F0,0x4051075,0x3600001,0xA20630,0x36,0x5100900,0x1028845C,0xD,0x2881200,0x1B0,0x0,0x6C0D80,0x48,0x0,0x480,0x0,0x0,0x90],[0x1E04100D,0x1203603,0x410000,0x80A207E,0x2,0xC283F0,0x4051075,0x3600001,0xA20630,0x36,0x5100900,0x1028845C,0xD,0x2881200,0x1B0,0x0,0x6C0D80,0x48,0x0,0x480,0x0,0x0,0x90],[0x1E04100C,0x1203603,0x410000,0x80A207E,0x2,0xC283F0,0x4051075,0x3600001,0xA20630,0x36,0x5100900,0x1028845C,0xD,0x2881200,0x1B0,0x0,0x6C0D80,0x48,0x0,0x480,0x0,0x0,0x90]],[[0x2002,0x0,0x20000,0x0,0x0,0x10000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x2001,0x0,0x20000,0x0,0x0,0x10000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x2001,0x0,0x20000,0x0,0x0,0x10000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x2001,0x0,0x20000,0x0,0x0,0x10000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x1002,0x0,0x10000,0x0,0x0,0x8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x4002,0x0,0x40000,0x0,0x0,0x20000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1E04000A,0x1203603,0x400000,0x80A207E,0x2,0xC203F0,0x4051075,0x3600001,0xA20630,0x36,0x5100900,0x1028845C,0xD,0x2881200,0x1B0,0x0,0x6C0D80,0x48,0x0,0x480,0x0,0x0,0x90],[0x1002,0x0,0x10000,0x0,0x0,0x8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]]
+    
+    
+    static let USE_GLV = true
+    static let USE_GS_G2 = true
+    static let USE_GS_GT = true
+    static let GT_STRONG = false
+*/  
+}
+
diff --git a/version22/swift/rom64.swift b/version22/swift/rom64.swift
new file mode 100644
index 0000000..cc48b20
--- /dev/null
+++ b/version22/swift/rom64.swift
@@ -0,0 +1,258 @@
+/*
+	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.
+*/
+
+//
+//  rom.swift
+//
+//  Created by Michael Scott on 12/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+typealias Chunk = Int64
+
+final public class ROM{
+    
+    static let CHUNK:Int=64
+    
+    /* Don't Modify from here... */
+    static let NOT_SPECIAL=0
+    static let PSEUDO_MERSENNE=1
+    static let MONTGOMERY_FRIENDLY=2
+    static let GENERALISED_MERSENNE=3
+    static let WEIERSTRASS=0
+    static let EDWARDS=1
+    static let MONTGOMERY=2
+    static let BN_CURVE=0
+    static let BLS_CURVE=1
+
+    /* ...to here */
+    
+/*** Enter Some Field details here  ***/
+
+// Curve 25519
+//    static let MODBITS:UInt=255
+//    static let MOD8:UInt=5
+//    static let BASEBITS:UInt=56
+//    static let AES_S:UInt=0
+    
+// GOLDILOCKS
+//  static let MODBITS:UInt=448
+//  static let MOD8:UInt=7
+//  static let BASEBITS:UInt=60
+//  static let AES_S:UInt=0
+
+    
+    
+// BN254 Curve
+//  static let MODBITS:UInt=254
+//  static let MOD8:UInt=3
+//  static let BASEBITS:UInt=56
+//  static let AES_S:UInt=0
+
+// BLS383 Curve
+static let MODBITS:UInt=383
+static let MOD8:UInt=3
+static let BASEBITS:UInt=56
+static let AES_S:UInt=0
+
+    
+// BLS455 Curve
+//  static let MODBITS:UInt=455
+//  static let MOD8:UInt=3
+//  static let BASEBITS:UInt=60
+//  static let AES_S:UInt=128
+    
+
+    static let FFLEN:UInt=4
+    
+/* Don't Modify from here... */
+    static let NLEN:Int=Int(1+((MODBITS-1)/BASEBITS))
+    static let DNLEN:Int=2*NLEN
+    static let BMASK:Chunk=((1<<Chunk(BASEBITS))-1)
+    static let MODBYTES:UInt=(1+(MODBITS-1)/8)
+    static let NEXCESS:Int = (1<<(CHUNK-Int(BASEBITS)-1))
+    static let FEXCESS:Chunk = (1<<Chunk(BASEBITS*UInt(NLEN)-MODBITS));
+    static let OMASK:Chunk=Chunk(-1)<<Chunk(MODBITS%BASEBITS)
+    static let TBITS:UInt=MODBITS%BASEBITS; // Number of active bits in top word
+    static let TMASK:Chunk=(1<<Chunk(TBITS))-1
+    static let BIGBITS:UInt = (MODBYTES*8)
+    static let HBITS = (BASEBITS/2)
+    static let HMASK:Chunk = ((1<<Chunk(HBITS))-1)
+    
+   
+    /* Finite field support - for RSA, DH etc. */
+    static let FF_BITS:UInt=(BIGBITS*FFLEN) /* Finite Field Size in bits - must be BIGBITS.2^n */
+    static let HFLEN=(FFLEN/2);  /* Useful for half-size RSA private key operations */
+    
+    static let P_MBITS:UInt=ROM.MODBYTES*8
+    static let P_OMASK:Chunk=Chunk(-1)<<Chunk(P_MBITS%BASEBITS)
+    static let P_FEXCESS:Chunk=(1<<Chunk(BASEBITS*UInt(NLEN)-P_MBITS))
+    static let P_TBITS=(P_MBITS%ROM.BASEBITS)
+    
+/* ...to here */
+    
+// START SPECIFY FIELD DETAILS HERE
+//*********************************************************************************
+// Curve25519 Modulus
+//    static let MODTYPE=PSEUDO_MERSENNE
+//    static let Modulus:[Chunk]=[0xFFFFFFFFFFFFED,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0x7FFFFFFF]
+//    static let MConst:Chunk=19
+  
+//GOLDILOCKS
+//static let MODTYPE=GENERALISED_MERSENNE
+//static let Modulus:[Chunk]=[0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFEFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFF]
+//static let MConst:Chunk= 0x1
+    
+// BN254 Curve Modulus
+//static let MODTYPE=NOT_SPECIAL
+//static let Modulus:[Chunk]=[0x13,0x13A7,0x80000000086121,0x40000001BA344D,0x25236482]
+//static let MConst:Chunk=0x435E50D79435E5
+   
+// BLS383 Curve
+static let MODTYPE=NOT_SPECIAL
+static let Modulus:[Chunk]=[0xACAAB52AAD556B,0x1BB01475F75D7A,0xCF73083D5D7520,0x531820F99EB16,0x2C01355A68EA32,0x5C6105C552A785,0x7AC52080A9F7]
+static let MConst:Chunk=0xA59AB3B123D0BD
+    
+    
+// BLS455 Curve
+//static let MODTYPE=NOT_SPECIAL
+//static let Modulus:[Chunk]=[0xAA00001800002AB,0xC589556B2AA956A,0xB9994ACE86D1BA6,0x3954FCB314B8B3D,0xE3A5B1D56234BD9,0x95B49203003F665,0x57955572AA00E0F,0x555559555]
+//static let MConst:Chunk=0xB3EF8137F4017FD
+   
+    
+
+// START SPECIFY CURVE DETAILS HERE
+//*********************************************************************************
+
+// Ed25519 Curve
+//    static let CURVETYPE=EDWARDS
+//    static let CURVE_A:Int = -1
+//    static let CURVE_B:[Chunk]=[0xEB4DCA135978A3,0xA4D4141D8AB75,0x797779E8980070,0x2B6FFE738CC740,0x52036CEE]
+//    static let CURVE_Order:[Chunk]=[0x12631A5CF5D3ED,0xF9DEA2F79CD658,0x14DE,0x0,0x10000000]
+//    static let CURVE_Gx:[Chunk]=[0x562D608F25D51A,0xC7609525A7B2C9,0x31FDD6DC5C692C,0xCD6E53FEC0A4E2,0x216936D3]
+//    static let CURVE_Gy:[Chunk]=[0x66666666666658,0x66666666666666,0x66666666666666,0x66666666666666,0x66666666]
+  
+    
+    
+// GOLDILOCKS
+//  static let CURVETYPE= EDWARDS
+//  static let CURVE_A:Int = 1;
+//  static let CURVE_B:[Chunk]=[0xFFFFFFFFFFF6756,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFEFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFF];
+//  static let CURVE_Order:[Chunk]=[0x378C292AB5844F3,0x6CC2728DC58F552,0xEDB49AED6369021,0xFFFF7CCA23E9C44,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0x3FFFFFF];
+//  static let CURVE_Gx:[Chunk]=[0x555555555555555,0x555555555555555,0x555555555555555,0xAAA955555555555,0xAAAAAAAAAAAAAAA,0xAAAAAAAAAAAAAAA,0xAAAAAAAAAAAAAAA,0xAAAAAAA];
+//  static let CURVE_Gy:[Chunk]=[0xAEAFBCDEA9386ED,0xBCB2BED1CDA06BD,0x565833A2A3098BB,0x6D728AD8C4B80D6,0x7A035884DD7B7E3,0x205086C2B0036ED,0x34AD7048DB359D6,0xAE05E96];
+    
+    
+// BN254 Curve
+/*
+     static let CURVETYPE= WEIERSTRASS;
+     static let CURVE_PAIRING_TYPE = BN_CURVE;
+     static let CURVE_A:Int = 0;
+     static let CURVE_B:[Chunk]=[0x2,0x0,0x0,0x0,0x0];
+     static let CURVE_Order:[Chunk]=[0xD,0x800000000010A1,0x8000000007FF9F,0x40000001BA344D,0x25236482];
+     static let CURVE_Gx:[Chunk]=[0x12,0x13A7,0x80000000086121,0x40000001BA344D,0x25236482];
+     static let CURVE_Gy:[Chunk]=[0x1,0x0,0x0,0x0,0x0];
+     
+     static let CURVE_Fra:[Chunk]=[0x7DE6C06F2A6DE9,0x74924D3F77C2E1,0x50A846953F8509,0x212E7C8CB6499B,0x1B377619];
+     static let CURVE_Frb:[Chunk]=[0x82193F90D5922A,0x8B6DB2C08850C5,0x2F57B96AC8DC17,0x1ED1837503EAB2,0x9EBEE69];
+     static let CURVE_Pxa:[Chunk]=[0xEE4224C803FB2B,0x8BBB4898BF0D91,0x7E8C61EDB6A464,0x519EB62FEB8D8C,0x61A10BB];
+     static let CURVE_Pxb:[Chunk]=[0x8C34C1E7D54CF3,0x746BAE3784B70D,0x8C5982AA5B1F4D,0xBA737833310AA7,0x516AAF9];
+     static let CURVE_Pya:[Chunk]=[0xF0E07891CD2B9A,0xAE6BDBE09BD19,0x96698C822329BD,0x6BAF93439A90E0,0x21897A0];
+     static let CURVE_Pyb:[Chunk]=[0x2D1AEC6B3ACE9B,0x6FFD739C9578A,0x56F5F38D37B090,0x7C8B15268F6D44,0xEBB2B0E];
+     static let CURVE_Bnx:[Chunk]=[0x80000000000001,0x40,0x0,0x0,0x0];
+     static let CURVE_Cof:[Chunk]=[0x1,0x0,0x0,0x0,0x0];
+     static let CURVE_Cru:[Chunk]=[0x80000000000007,0x6CD,0x40000000024909,0x49B362,0x0];
+     static let CURVE_W:[[Chunk]]=[[0x3,0x80000000000204,0x6181,0x0,0x0],[0x1,0x81,0x0,0x0,0x0]];
+     static let CURVE_SB:[[[Chunk]]]=[[[0x4,0x80000000000285,0x6181,0x0,0x0],[0x1,0x81,0x0,0x0,0x0]],[[0x1,0x81,0x0,0x0,0x0],[0xA,0xE9D,0x80000000079E1E,0x40000001BA344D,0x25236482]]];
+     static let CURVE_WB:[[Chunk]]=[[0x80000000000000,0x80000000000040,0x2080,0x0,0x0],[0x80000000000005,0x54A,0x8000000001C707,0x312241,0x0],[0x80000000000003,0x800000000002C5,0xC000000000E383,0x189120,0x0],[0x80000000000001,0x800000000000C1,0x2080,0x0,0x0]];
+     static let CURVE_BB:[[[Chunk]]]=[[[0x8000000000000D,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482],[0x8000000000000C,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482],[0x8000000000000C,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482],[0x2,0x81,0x0,0x0,0x0]],[[0x1,0x81,0x0,0x0,0x0],[0x8000000000000C,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482],[0x8000000000000D,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482],[0x8000000000000C,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482]],[[0x2,0x81,0x0,0x0,0x0],[0x1,0x81,0x0,0x0,0x0],[0x1,0x81,0x0,0x0,0x0],[0x1,0x81,0x0,0x0,0x0]],[[0x80000000000002,0x40,0x0,0x0,0x0],[0x2,0x102,0x0,0x0,0x0],[0xA,0x80000000001020,0x8000000007FF9F,0x40000001BA344D,0x25236482],[0x80000000000002,0x40,0x0,0x0,0x0]]];
+     
+     static let USE_GLV = true
+     static let USE_GS_G2 = true
+     static let USE_GS_GT = true
+     static let GT_STRONG = false
+     */
+    
+    // BLS383 Curve
+    
+    static let CURVETYPE = WEIERSTRASS;
+    static let CURVE_PAIRING_TYPE = BLS_CURVE;
+    static let CURVE_A:Int = 0;
+    
+    static let CURVE_Order:[Chunk]=[0xFFF80000FFF001,0xBFDE0070FE7800,0x3000049C5EDF1C,0xC40007F910007A,0x14641004C,0x0,0x0];
+    static let CURVE_B:[Chunk]=[0x9,0x0,0x0,0x0,0x0,0x0,0x0];
+    static let CURVE_Cof:[Chunk]=[0x2A00000052B,0x5560AAAAAB2CA0,0x6055,0x0,0x0,0x0,0x0];
+    static let CURVE_Gx:[Chunk]=[0xD59B348D10786B,0x3477C0E3F54AD0,0xBF25B734578B9B,0x4F6AC007BB6F65,0xEFD5830FF57E9C,0xADB9F88FB6EC02,0xB08CEE4BC98];
+    static let CURVE_Gy:[Chunk]=[0x5DA023D145DDB,0x13F518C5FEF7CC,0x56EC3462B2A66F,0x96F3019C7A925F,0x9061047981223E,0x4810AD8F5BE59,0x1F3909337671];
+    
+    static let CURVE_Bnx:[Chunk]=[0x1000000040,0x110,0x0,0x0,0x0,0x0,0x0];
+    static let CURVE_Cru:[Chunk]=[0xA3AAC4EDA155A9,0xDF2FE8761E5E3D,0xBCDFAADE632625,0x5123128D3035A6,0xDBF3A2BBEAD683,0x5C5FAB20424190,0x7AC52080A9F7];
+    static let CURVE_Fra:[Chunk]=[0x2BA59A92B4508B,0x63DB7A06EEF343,0x40341CB1DFBC74,0x1639E9D32D55D3,0xB19B3F05CC36D4,0xF323EE4D86AB98,0x5A5FB198672];
+    static let CURVE_Frb:[Chunk]=[0x81051A97F904E0,0xB7D49A6F086A37,0x8F3EEB8B7DB8AB,0xEEF7983C6C9543,0x7A65F6549CB35D,0x693D1777CBFBEC,0x751F25672384];
+    static let CURVE_Pxa:[Chunk]=[0x6059885BAC9472,0x7C4D31DE2DC36D,0xBDC90C308C88A7,0x29F01971C688FC,0x3693539C43F167,0xD81E5A561EB8BF,0x4D50722B56BF];
+    static let CURVE_Pxb:[Chunk]=[0x9B4BD7A272AB23,0x7AF19D4F44DCE8,0x3F6F7B93206A34,0x571DD3E2A819FB,0x3A2BA3B635D7EE,0xAC28C780C1A126,0xEE3617C3E5B];
+    static let CURVE_Pya:[Chunk]=[0x81D230977BD4FD,0xB660720DFDFC6,0x41FC9590C89A0C,0x2E1FBCF878287A,0x11C23014EEE65,0x28878816BB325E,0x8F40859A05C];
+    static let CURVE_Pyb:[Chunk]=[0xA5E20A252C4CE6,0x5907A74AFF40C8,0x41760A42448EF3,0xFFEF82B0FDA199,0xA0F29A18D4EA49,0xAC7F7B86E4997B,0x1DCABBA88C12];
+    
+    static let CURVE_W:[[Chunk]]=[[],[]];
+    static let CURVE_SB:[[[Chunk]]]=[[[],[]],[[],[]]];
+    static let CURVE_WB:[[Chunk]]=[[],[],[],[]];
+    static let CURVE_BB:[[[Chunk]]]=[[[],[],[],[]],[[],[],[],[]],[[],[],[],[]],[[],[],[],[]]];
+    
+    
+    static let USE_GLV = true
+    static let USE_GS_G2 = true
+    static let USE_GS_GT = true
+    static let GT_STRONG = false
+    
+    
+    // BLS455 Curve
+    /*
+         static let CURVETYPE= WEIERSTRASS;
+     static let CURVE_PAIRING_TYPE = BLS_CURVE;
+     static let CURVE_A:Int =0;
+     
+     static let CURVE_Order:[Chunk]=[0x7FFFFC00001,0xA00000400001C,0x25E000750001D10,0xE0000F10004F000,0x80000380002,0x10,0x0,0x0];
+     static let CURVE_B:[Chunk]=[0xA,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+     static let CURVE_Cof:[Chunk]=[0xA9557FFAABFFAAB,0xAAB15555B54AAB6,0x555556AA,0x0,0x0,0x0,0x0,0x0];
+     static let CURVE_Gx:[Chunk]=[0x6D4C5DDFDFCEDD1,0x35C6F43B3A034FB,0x7F05B56A579C725,0xB1F2B8ECE11B321,0x9F342AB0CFE8392,0xA5911EE32767994,0x3005E40CC56ABED,0x18855F3B];
+     static let CURVE_Gy:[Chunk]=[0x404FD79A6619B9B,0x69D80A5D6FA0286,0xEE722322D91A493,0xB1EE58431C1E968,0xCA9BC8953801F5F,0xDFAFD40FE9E388E,0x9F8985FC3DEB0D6,0x19A8DB77E];
+     
+     static let CURVE_Bnx:[Chunk]=[0x20000080000800,0x10000,0x0,0x0,0x0,0x0,0x0,0x0];
+     static let CURVE_Cru:[Chunk]=[0x9202FFC00000AA9,0xFA5190F4A3762A,0x8B2B9BDD548FEC9,0xD7B469DB33A586A,0xC91731354CAFD99,0xF5B48D02FFFE695,0x57955572A900E0E,0x555559555];
+     static let CURVE_Fra:[Chunk]=[0x9CCFBDCA2EBF21,0x572F54A73379964,0x72819F887545498,0x22BBC1CAD1F8534,0xA82CD7D435944F0,0x4594F818D030F7B,0xEDCBE3ADC0016A7,0x397EA4973];
+     static let CURVE_Frb:[Chunk]=[0xA033043B5D1438A,0x6E5A00C3F72FC06,0x4717AB46118C70E,0x16993AE842C0609,0x3B78DA012CA06E9,0x501F99EA300E6EA,0x69C971C4E9FF768,0x1BD6B4BE1];
+     static let CURVE_Pxa:[Chunk]=[0x475F20F0C1F542,0x65D6070F8567E10,0xD780698BB33D776,0x71F685ED1531721,0x303D3FEC5B6A49C,0x8DEF064FF553CEB,0xC0E9A31B4C463,0x2ECB12FA8];
+     static let CURVE_Pxb:[Chunk]=[0x99086EE6749F03D,0xE89A55A5AC5EF2E,0x7B41AECD88EA016,0x622450FE6163E06,0x755066E1C8E296F,0xA80F219487326E8,0x66DBFBB0BEAEE59,0xECFFCE0];
+     static let CURVE_Pya:[Chunk]=[0x83235A4581A77F4,0x9F0F367B7A7E10A,0x8FA0C4A66D55B9D,0xEF03F65E0D6EC4C,0x9C7DC299C1A9EC2,0x32453CA21CFA5AC,0x6C3DCD5ABB9C544,0x22471D90A];
+     static let CURVE_Pyb:[Chunk]=[0xF413B6D9E1FDBA2,0xA7E630913DA0356,0xFBC913D9AC488E2,0x72E7CF61B401585,0x656D801B21C89ED,0xF9E921EEE0558F9,0x3D2B7B03CFC8698,0x33503CA8];
+     
+     static let CURVE_W:[[Chunk]]=[[],[]];
+     static let CURVE_SB:[[[Chunk]]]=[[[],[]],[[],[]]];
+     static let CURVE_WB:[[Chunk]]=[[],[],[],[]];
+     static let CURVE_BB:[[[Chunk]]]=[[[],[],[],[]],[[],[],[],[]],[[],[],[],[]],[[],[],[],[]]];
+     
+     
+     static let USE_GLV = true
+     static let USE_GS_G2 = true
+     static let USE_GS_GT = true
+     static let GT_STRONG = false
+     */
+}
+
diff --git a/version22/swift/rsa.swift b/version22/swift/rsa.swift
new file mode 100644
index 0000000..fd3fa84
--- /dev/null
+++ b/version22/swift/rsa.swift
@@ -0,0 +1,400 @@
+/*
+	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.
+*/
+
+//
+//  rsa.swift
+//
+//  Created by Michael Scott on 25/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+import Foundation
+
+/* RSA API high-level functions  */
+
+final public class rsa_private_key {
+    var p:FF
+    var q:FF
+    var dp:FF
+    var dq:FF
+    var c:FF
+    
+    public init(_ n: Int)
+    {
+    p=FF(n);
+    q=FF(n);
+    dp=FF(n);
+    dq=FF(n);
+    c=FF(n);
+    }
+}
+
+final public class rsa_public_key
+{
+    var e:Int
+    var n:FF
+    
+    public init(_ m:Int)
+    {
+        e=0;
+        n=FF(m);
+    }
+}
+
+final public class RSA {
+    
+    static public let RFS=Int(ROM.MODBYTES*ROM.FFLEN)
+    static public let SHA256=32
+    static public let SHA384=48
+    static public let SHA512=64
+    
+    static public let HASH_TYPE=SHA384
+    
+    /* Hash number (optional) and string to array size of Bigs */
+ 
+    static private func hashit(_ sha:Int,_ A: [UInt8]?,_ n: Int32) -> [UInt8]
+    {
+        if sha==RSA.SHA256
+        {
+            let H=HASH256()
+            if A != nil {H.process_array(A!)}
+            if n >= 0 {H.process_num(n)}
+            let R=H.hash()
+            return R
+        }
+        if sha==RSA.SHA384
+        {
+            let H=HASH384()
+            if A != nil {H.process_array(A!)}
+            if n >= 0 {H.process_num(n)}
+            let R=H.hash()
+            return R
+        }
+        if sha==RSA.SHA512
+        {
+            let H=HASH512()
+            if A != nil {H.process_array(A!)}
+            if n >= 0 {H.process_num(n)}
+            let R=H.hash()
+            return R
+        }
+        return [UInt8]()
+    }
+
+    /* generate an RSA key pair */
+    
+    static public func KEY_PAIR(_ rng: RAND,_ e:Int,_ PRIV:rsa_private_key,_ PUB:rsa_public_key)
+    { /* IEEE1363 A16.11/A16.12 more or less */
+    
+        let n=PUB.n.getlen()/2;
+        let t = FF(n);
+        let p1=FF(n);
+        let q1=FF(n);
+    
+        while true
+        {
+    
+            PRIV.p.random(rng);
+            while PRIV.p.lastbits(2) != 3 {PRIV.p.inc(1)}
+            while !FF.prime(PRIV.p,rng) {PRIV.p.inc(4)}
+    
+            p1.copy(PRIV.p);
+            p1.dec(1);
+    
+            if p1.cfactor(e) {continue}
+            break;
+        }
+    
+        while true
+        {
+            PRIV.q.random(rng);
+            while PRIV.q.lastbits(2) != 3 {PRIV.q.inc(1)}
+            while !FF.prime(PRIV.q,rng) {PRIV.q.inc(4)}
+    
+            q1.copy(PRIV.q);
+            q1.dec(1);
+    
+            if q1.cfactor(e) {continue}
+    
+            break;
+        }
+    
+        PUB.n=FF.mul(PRIV.p,PRIV.q);
+        PUB.e=e;
+    
+        t.copy(p1);
+        t.shr();
+        PRIV.dp.set(e);
+        PRIV.dp.invmodp(t);
+        if (PRIV.dp.parity()==0) {PRIV.dp.add(t)}
+        PRIV.dp.norm();
+    
+        t.copy(q1);
+        t.shr();
+        PRIV.dq.set(e);
+        PRIV.dq.invmodp(t);
+        if (PRIV.dq.parity()==0) {PRIV.dq.add(t)}
+        PRIV.dq.norm();
+    
+        PRIV.c.copy(PRIV.p);
+        PRIV.c.invmodp(PRIV.q);
+    
+        return;
+    }
+    /* Mask Generation Function */
+    
+    static func MGF1(_ sha: Int,_ Z: [UInt8],_ olen:Int,_ K:inout [UInt8])
+    {
+        let hlen=sha
+    
+        var k=0;
+        for i in 0 ..< K.count {K[i]=0}
+    
+        var cthreshold=Int32(olen/hlen); if (olen%hlen != 0) {cthreshold += 1}
+        for counter:Int32 in 0 ..< cthreshold
+        {
+            var B=RSA.hashit(sha,Z,counter)
+            if (k+hlen>olen) {for i in 0 ..< olen%hlen {K[k]=B[i]; k+=1}}
+            else {for i in 0 ..< hlen {K[k]=B[i]; k+=1}}
+        }
+    }
+    
+    static public func printBinary(_ array: [UInt8])
+    {
+        for i in 0 ..< array.count
+        {
+            let h=String(array[i],radix:16)
+            print("\(h)", terminator: "")
+        }
+        print("");
+    }
+    
+    static let SHA256ID:[UInt8]=[0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20]
+    static let SHA384ID:[UInt8]=[0x30,0x41,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00,0x04,0x30]
+    static let SHA512ID:[UInt8]=[0x30,0x51,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0x04,0x40]
+    
+    /* PKCS 1.5 padding of a message to be signed */
+    static public func PKCS15(_ sha:Int,_ m:[UInt8],_ w:inout [UInt8])->Bool
+    {
+        let hlen=sha
+        let olen=Int(ROM.FF_BITS/8)
+        let idlen=19;
+        
+        if olen<idlen+hlen+10 {return false}
+        let H=hashit(sha,m,-1)
+        for i in 0 ..< w.count {w[i]=0}
+        
+        w[0]=0
+        w[1]=1
+        var i=2
+        var j=0
+        
+        while j<olen-idlen-hlen-3
+        {
+            w[i]=0xff
+            i+=1; j+=1
+        }
+        w[i]=0; i+=1;
+        
+        if hlen==RSA.SHA256
+        {
+            for j in 0 ..< idlen {w[i]=SHA256ID[j]; i+=1}
+        }
+        if hlen==RSA.SHA384
+        {
+            for j in 0 ..< idlen {w[i]=SHA384ID[j]; i+=1}
+        }
+        if hlen==RSA.SHA512
+        {
+            for j in 0 ..< idlen {w[i]=SHA512ID[j]; i+=1}
+        }
+        
+        for j in 0 ..< hlen {w[i]=H[j];i+=1}
+        
+        return true
+    }
+    
+    
+    /* OAEP Message Encoding for Encryption */
+    static public func OAEP_ENCODE(_ sha:Int,_ m:[UInt8],_ rng:RAND,_ p:[UInt8]?) -> [UInt8]
+    {
+        let olen=RFS-1;
+        let mlen=m.count;
+        var f=[UInt8](repeating: 0,count: RSA.RFS)
+    
+        let hlen=sha;
+        var SEED=[UInt8](repeating: 0,count: hlen)
+        let seedlen=hlen;
+        if (mlen>olen-hlen-seedlen-1) {return [UInt8]()}
+    
+        var DBMASK=[UInt8](repeating: 0,count: olen-seedlen)
+        
+        var h=hashit(sha,p,-1)
+        for i in 0 ..< hlen {f[i]=h[i]}
+    
+        let slen=olen-mlen-hlen-seedlen-1;
+    
+        for i in 0 ..< slen {f[hlen+i]=0}
+        f[hlen+slen]=1;
+        for i in 0 ..< mlen {f[hlen+slen+1+i]=m[i]}
+    
+        for i in 0 ..< seedlen {SEED[i]=rng.getByte()}
+        RSA.MGF1(sha,SEED,olen-seedlen,&DBMASK)
+    
+        for i in 0 ..< olen-seedlen {DBMASK[i]^=f[i]}
+        RSA.MGF1(sha,DBMASK,seedlen,&f)
+    
+        for i in 0 ..< seedlen {f[i]^=SEED[i]}
+    
+        for i in 0 ..< olen-seedlen {f[i+seedlen]=DBMASK[i]}
+    
+    /* pad to length RFS */
+        let d:Int=1;
+        for i in (d...RFS-1).reversed()
+            {f[i]=f[i-d]}
+        for i in 0...d-1
+            {f[i]=0}
+    
+        return f;
+    }
+    
+    /* OAEP Message Decoding for Decryption */
+    static public func OAEP_DECODE(_ sha: Int,_ p: [UInt8]?,_ f:inout [UInt8]) -> [UInt8]
+    {
+        let olen=RFS-1
+        var k:Int
+        let hlen=sha
+        var SEED=[UInt8](repeating: 0,count: hlen)
+        let seedlen=hlen
+        var CHASH=[UInt8](repeating: 0,count: hlen)
+        
+        if olen<seedlen+hlen+1 {return [UInt8()]}
+        var DBMASK=[UInt8](repeating: 0,count: olen-seedlen)
+        for i in 0 ..< olen-seedlen {DBMASK[i]=0}
+    
+        if (f.count<RFS)
+        {
+            let d=RFS-f.count;
+            for i in (d...RFS-1).reversed()
+                {f[i]=f[i-d]}
+            for i in 0...d-1
+                {f[i]=0}
+    
+        }
+    
+        var h=hashit(sha,p,-1)
+        for i in 0 ..< hlen {CHASH[i]=h[i]}
+    
+        let x=f[0];
+    
+        for i in seedlen ..< olen
+            {DBMASK[i-seedlen]=f[i+1]}
+    
+        RSA.MGF1(sha,DBMASK,seedlen,&SEED);
+        for i in 0 ..< seedlen {SEED[i]^=f[i+1]}
+        RSA.MGF1(sha,SEED,olen-seedlen,&f);
+        for i in 0 ..< olen-seedlen {DBMASK[i]^=f[i]}
+    
+        var comp=true;
+        for i in 0 ..< hlen
+        {
+            if (CHASH[i] != DBMASK[i]) {comp=false}
+        }
+    
+        for i in 0 ..< olen-seedlen-hlen
+        {DBMASK[i]=DBMASK[i+hlen]}
+    
+        for i in 0 ..< hlen
+            {SEED[i]=0;CHASH[i]=0;}
+    
+        k=0
+        while (true)
+        {
+            if (k>=olen-seedlen-hlen) {return [UInt8]()}
+            if (DBMASK[k] != 0) {break}
+            k+=1
+        }
+    
+        let t=DBMASK[k];
+        if (!comp || x != 0 || t != 0x01)
+        {
+            for i in 0 ..< olen-seedlen {DBMASK[i]=0}
+            return [UInt8]()
+        }
+    
+        var r=[UInt8](repeating: 0,count: olen-seedlen-hlen-k-1)
+    
+        for i in 0 ..< olen-seedlen-hlen-k-1
+            {r[i]=DBMASK[i+k+1]}
+    
+        for i in 0 ..< olen-seedlen {DBMASK[i]=0}
+    
+        return r;
+    }
+    /* destroy the Private Key structure */
+    static public func PRIVATE_KEY_KILL(_ PRIV: rsa_private_key)
+    {
+        PRIV.p.zero();
+        PRIV.q.zero();
+        PRIV.dp.zero();
+        PRIV.dq.zero();
+        PRIV.c.zero();
+    }
+    /* RSA encryption with the public key */
+    static public func ENCRYPT(_ PUB: rsa_public_key,_ F:[UInt8],_ G:inout [UInt8])
+    {
+        let n=PUB.n.getlen()
+        let f=FF(n)
+    
+        FF.fromBytes(f,F)
+        f.power(PUB.e,PUB.n)
+        f.toBytes(&G)
+    }
+    /* RSA decryption with the private key */
+    static public func DECRYPT(_ PRIV: rsa_private_key,_ G:[UInt8],_ F:inout [UInt8])
+    {
+        let n=PRIV.p.getlen()
+        let g=FF(2*n)
+    
+        FF.fromBytes(g,G)
+        let jp=g.dmod(PRIV.p)
+        var jq=g.dmod(PRIV.q)
+    
+        jp.skpow(PRIV.dp,PRIV.p)
+        jq.skpow(PRIV.dq,PRIV.q)
+    
+        g.zero()
+        g.dscopy(jp)
+        jp.mod(PRIV.q)
+        if (FF.comp(jp,jq)>0) {jq.add(PRIV.q)}
+        jq.sub(jp)
+        jq.norm()
+    
+        var t=FF.mul(PRIV.c,jq)
+        jq=t.dmod(PRIV.q)
+    
+        t=FF.mul(jq,PRIV.p)
+        g.add(t);
+        g.norm();
+    
+        g.toBytes(&F);
+    }
+    
+}
+
diff --git a/version3/amcl3.pdf b/version3/amcl3.pdf
new file mode 100644
index 0000000..de1249d
--- /dev/null
+++ b/version3/amcl3.pdf
Binary files differ
diff --git a/version3/bestpair.cpp b/version3/bestpair.cpp
new file mode 100644
index 0000000..f3e47bd
--- /dev/null
+++ b/version3/bestpair.cpp
@@ -0,0 +1,623 @@
+//
+// Program to generate "best" BN, BLS12, BLS24 and BLS48 curves (with modulus p=3 mod 8)
+//
+// g++ -O2 bestpair.cpp zzn8.cpp zzn4.cpp zzn2.cpp zzn.cpp ecn8.cpp ecn4.cpp ecn2.cpp ecn.cpp big.cpp miracl.a -o bestpair.exe
+//
+// Further tests may be needed to ensure full satisfaction (e.g. twist security, even x, etc.)
+//
+// Note that finding curves that are both GT and G2 Strong, can take a while
+//
+// Suggestions:-
+// For AES-128 security: bestpair BLS12 64 3
+// For AES-192 security: bestpair BLS24 48 4
+// FOr AES-256 security: bestpair BLS48 32 4
+
+// Some possible rational points on y^2=x^3+b (x^3+b is a perfect square)
+// b=1, x=0, -1 or 2
+// b=2, x=-1
+// b=3, x=1
+// b=4, x=0
+// b=5, x=-1
+// b=8, x=-2, 1, 2
+// b=9, x=0, 3, 6, 40
+// b=10, x=-1
+// b=12, x=-2, 13
+
+// b=-1, x=1
+// b=-2, x=3;
+// b=-4, x=2, 5
+// b=-7, x=2, 32
+// b=-8, x=2
+// b=-11, x=3, 15
+
+// of course these points need to be checked for correct order...
+
+#include <iostream>
+#include "big.h"
+#include "ecn.h"
+#include "ecn2.h"
+#include "ecn4.h"
+#include "ecn8.h"
+
+#define BN 0
+#define BLS12 1
+#define BLS24 2
+#define BLS48 3
+
+using namespace std;
+
+Miracl precision=500;
+
+// Number of ways of selecting k items from n
+Big combo(int n,int k)
+{ // calculate n C k
+	int i;
+	Big c,d;
+
+	d=1;
+	for (i=2;i<=k;i++)
+		d*=i;
+
+	c=1;
+	for (i=n;i>n-k;i--)
+		c*=i;
+
+	c/=d;
+	return c;
+}
+
+// Number of candidates to be searched.
+Big count(int b,int h)
+{
+	Big c=combo(b-h+1,h-1)+combo(b-h+1,h-2);
+	c*=pow((Big)2,h);
+	return c;
+}
+
+// Move to next NAF pattern
+int iterate(int *x,int n)
+{
+	int i,j,k,gotone=0;
+	for (i=0;i<n-1;i++)
+	{
+		if (x[i]==1 && x[i+2]==0)
+		{
+			gotone=1;
+			x[i+1]=1;
+			x[i]=0;
+			if (x[0]==1) break;
+			for (k=1;;k++)
+				if (x[k]!=0) break;
+			for (j=0;j<i-k;j+=2)
+			{
+				x[j]=x[j+k];
+				x[j+k]=0;
+			}
+			break;
+		}
+		
+	}
+	return gotone;
+}
+
+int main(int argc, char *argv[])
+{
+	int HW,BITS,S,type,xm8,xm3,xm24,percent,pc;
+	Big cnt,odds,total;
+    int i,j,k,m,jj,bt,hw,twist,pb,nb,b,cb[40],ip;
+	int xb[256];
+	BOOL G2,GT,gotH,gotB,gotT,progress;
+    Big msb,c,r,m1,n,p,q,t,x,y,w,X,Y,cof,cof2,coft,tau[9];
+    Big PP,TT,FF;
+	Big xp[10];
+	int pw[10];
+    miracl *mip=&precision;
+    ECn P;
+
+	argc--; argv++;
+
+    if (argc<2)
+    {
+       cout << "Missing arguments" << endl;
+	   cout << "Program to find best pairing-friendly curves" << endl;
+       cout << "bestpair type bits Hamming-weight" << endl;
+	   cout << "where type is the curve (BN, BLS12, BLS24, BLS48)" << endl;
+	   cout << "where bits is number of bits in curve x parameter (>30 and <200)" << endl;
+       cout << "and hamming-weight is the number of non-zero bits (>1 and <10)" << endl;
+       cout << "e.g. bestpair BLS12 77 3" << endl;
+	   cout << "Use flag /GT for GT-Strong curves" << endl;
+	   cout << "Use flag /G2 for G2-Strong curves" << endl;
+	   cout << "Use flag /P to show progress" << endl;
+
+       exit(0);
+    }
+
+	ip=0; HW=0; BITS=0; 
+	G2=GT=gotB=gotH=gotT=progress=FALSE;
+
+	while (ip<argc)
+	{
+		if (!gotT && strcmp(argv[ip],"BN")==0)
+		{
+			ip++;
+			gotT=TRUE;
+			type=BN;
+		}
+		if (!gotT && strcmp(argv[ip],"BLS12")==0)
+		{
+			ip++;
+			gotT=TRUE;
+			type=BLS12;
+		}
+		if (!gotT && strcmp(argv[ip],"BLS24")==0)
+		{
+			ip++;
+			gotT=TRUE;
+			type=BLS24;
+		}
+		if (!gotT && strcmp(argv[ip],"BLS48")==0)
+		{
+			ip++;
+			gotT=TRUE;
+			type=BLS48;
+		}
+		if (!G2 && strcmp(argv[ip],"/G2")==0)
+		{
+			ip++;
+			G2=TRUE;
+			continue;
+		}
+		if (!GT && strcmp(argv[ip],"/GT")==0)
+		{
+			ip++;
+			GT=TRUE;
+			continue;
+		}
+		if (!progress && strcmp(argv[ip],"/P")==0)
+		{
+			ip++;
+			progress=TRUE;
+			continue;
+		}
+		if (!gotB)
+		{
+			BITS=atoi(argv[ip++]);
+			gotB=TRUE;
+			continue;
+		}
+
+		if (!gotH)
+		{
+			HW=atoi(argv[ip++]);
+			gotH=TRUE;
+			continue;
+		}
+
+        cout << "Error in command line" << endl;
+        return 0;
+
+	}
+    if (!gotH || !gotB || !gotT || HW>9 || HW<2 || BITS>=200 || BITS<30)
+    {
+        cout << "Error in command line" << endl;
+        return 0;
+    }
+
+	hw=HW-1;
+	msb=pow((Big)2,BITS);
+
+	for (i=0;i<=BITS;i++)
+		xb[i]=0;
+
+	for (i=0;i<hw;i++)
+		xb[2*i]=1;
+
+	S=0;
+
+	total=count(BITS,HW);
+	cout << "search " << total << " candidates" << endl;
+
+// very approximate estimate of odds of success. Assumes primes are not correlated (but they are!)
+	if (type==BN)
+	{
+		odds = (7*(4*BITS+5)/10)*(7*(4*BITS+5)/10);
+		if (G2)
+			odds*=(7*(4*BITS+5)/10);
+		if (GT)
+			odds*=(7*(12*BITS+16)/10);
+	}
+	if (type==BLS12)
+	{
+		odds = ((7*4*BITS)/10)*((7*6*BITS)/10);
+		if (G2)
+			odds*=(7*(8*BITS)/10);
+		if (GT)
+			odds*=(7*(20*BITS)/10);
+	}
+	if (type==BLS24)
+	{
+		odds = ((7*8*BITS)/10)*((7*10*BITS)/10);
+		if (G2)
+			odds*=(7*(32*BITS)/10);
+		if (GT)
+			odds*=(7*(72*BITS)/10);
+	}
+	if (type==BLS48)
+	{
+		odds = ((7*16*BITS)/10)*((7*18*BITS)/10);
+		if (G2)
+			odds*=(7*(128*BITS)/10);
+		if (GT)
+			odds*=(7*(272*BITS)/10);
+	}
+
+	odds/=8;  // frig factor
+	cout << "one in " << odds << " expected to be OK" << endl;
+
+//	gprime(1000);
+	percent=-1;
+	cnt=0;
+	for (;;)
+	{
+		if (cnt>0 && !iterate(xb,BITS)) break;
+		for (i=j=0;i<BITS;i++)
+		{ // assign values to set bits
+			if (xb[i]==1)
+			{
+				xp[j]=pow((Big)2,i);
+				pw[j]=i;
+				j++;
+			}
+		}
+		xp[j]=msb;
+		pw[j]=BITS;
+		j++;
+
+		// iterate through all combinations of + and - terms
+		for (i=0;i<(1<<j);i++)
+		{
+			cnt+=1; 
+			if (progress)
+			{
+				pc=toint((100*cnt)/total);
+
+				if (percent<pc)
+				{
+					percent=pc;
+					cout << pc << "\%" << endl;
+				}
+			}
+			x=0;
+			bt=1;
+			//cout << "x= ";
+			for (k=0;k<j;k++)
+			{
+				if ((bt&i)!=0) {x+=xp[k]; /*cout << "+2^" << pw[k];*/}
+				else {x-=xp[k]; /*cout << "-2^" << pw[k];*/}
+				bt<<=1;
+			}
+
+			if (type==BLS12)
+			{
+				xm24=x%24;
+				if (x<0) xm24+=24;
+				xm24%=24;
+				xm3=xm24%3;
+				if (xm3!=1) continue;   // quick exit for p%3=0
+				xm8=xm24%8;
+				if (xm8!=0 && xm8!=7) continue;  // quick exit for p=3 mod 8 condition
+
+				q=pow(x,4)-x*x+1;
+				p=q*(((x-1)*(x-1))/3)+x;
+
+				t=x+1;
+				n=p+1-t;
+
+			}
+			if (type==BLS24)
+			{
+				xm24=x%24;
+				if (x<0) xm24+=24;
+				xm24%=24;
+				xm3=xm24%3;
+				if (xm3!=1) continue;   // quick exit for p%3=0
+				xm8=xm24%8;
+				if (xm8!=0 && xm8!=7) continue;  // quick exit for p=3 mod 8 condition
+
+				q=pow(x,8)-pow(x,4)+1;
+				p=q*(((x-1)*(x-1))/3)+x;
+
+				t=x+1;
+				n=p+1-t;
+				
+			}
+
+			if (type==BLS48)
+			{
+				xm24=x%24;
+				if (x<0) xm24+=24;
+				xm24%=24;
+				xm3=xm24%3;
+				if (xm3!=1) continue;   // quick exit for p%3=0
+				xm8=xm24%8;
+				if (xm8!=0 && xm8!=7) continue;  // quick exit for p=3 mod 8 condition
+
+				q=pow(x,16)-pow(x,8)+1;
+				p=q*(((x-1)*(x-1))/3)+x;
+		
+				t=x+1;
+				n=p+1-t;
+				
+			}
+
+			if (type==BN)
+			{
+				xm8=x%8;
+				if (x<0) xm8+=8;
+				xm8%=8;
+				if (xm8!=3 && xm8!=7) continue;  // quick exit for p=3 mod 8 condition
+
+				p=36*pow(x,4)+36*pow(x,3)+24*x*x+6*x+1;
+				t=6*x*x+1;
+				n=p+1-t;
+				q=n;
+			}
+
+			if (p%8!=3) continue;                           // restriction here could be eased
+
+			if (small_factors(q)) continue;
+			if (small_factors(p)) continue;
+
+			cof=n/q;
+
+			if (type==BLS24)
+			{
+				coft=(pow(p,8)-pow(p,4)+1)/q;
+			}
+
+			if (type==BLS48)
+			{
+				coft=(pow(p,16)-pow(p,8)+1)/q;
+			}
+
+			if (type==BLS12 || type==BN)
+			{
+				coft=(pow(p,4)-p*p+1)/q;
+			}
+
+			if (GT)
+			{
+				if (small_factors(coft)) continue;
+			}
+
+			if (type==BLS12)
+			{
+				TT=t*t-2*p;
+				PP=p*p;
+				FF=t*(2*x*x*x-2*x*x-x+1)/3;
+				m1=PP+1-(-3*FF+TT)/2;
+			}
+
+			if (type==BLS24)
+			{
+				TT=t*t*t*t-4*p*t*t+2*p*p;
+				PP=pow(p,4);
+				FF=sqrt((4*PP-TT*TT)/3);
+				m1=PP+1-(3*FF+TT)/2;
+			}
+			if (type==BLS48)
+			{
+				tau[0]=2;  // count points on twist over extension p^8
+				tau[1]=t;
+				for (jj=1;jj<8;jj++ ) tau[jj+1]=t*tau[jj]-p*tau[jj-1];
+
+				TT=tau[8];
+
+				PP=pow(p,8);
+				FF=sqrt((4*PP-TT*TT)/3);
+				m1=PP+1-(3*FF+TT)/2;  //?
+			}
+			if (type==BN)
+			{
+				TT=t*t-2*p;
+				PP=p*p;
+				FF=sqrt((4*PP-TT*TT)/3);
+				m1=PP+1-(3*FF+TT)/2;
+			}
+			cof2=m1/q;
+
+			if (G2)
+			{
+				if (small_factors(cof2)) continue;
+			}
+
+			if (!prime(q)) continue;
+			if (!prime(p)) continue;
+			modulo(p);
+
+			ZZn2 xi;
+
+			xi.set(1,1);                // for p=3 mod 8
+		
+// make sure its irreducible
+			if (pow(xi,(p*p-1)/2)==1)
+				continue;
+		
+			if (pow(xi,(p*p-1)/3)==1) 
+				continue;  // make sure that x^6-c is irreducible
+
+			if (G2)
+			{
+				if (!prime(cof2)) continue;
+			}
+
+			if (GT)
+			{
+				if (!prime(coft)) continue;
+			}
+
+			
+// we have a solution
+// Find curve b parameter - uses first positive one found (but collect some other possibilities)
+			pb=0;
+			b=0;
+			m=0;
+			while (pb<=20 || b==0)
+			{
+				pb+=1;
+				ecurve(0,pb,p,MR_AFFINE);
+				while (!P.set(rand(p))) ;
+				P*=cof;
+				if ((q*P).iszero())
+				{
+					if (b==0) b=pb;
+					else cb[m++]=pb;
+				}
+
+			}
+			nb=0;
+			while (nb>=-20)
+			{
+				nb-=1;
+				ecurve(0,nb,p,MR_AFFINE);
+				while (!P.set(rand(p))) ;
+				P*=cof;
+				if ((q*P).iszero())
+					cb[m++]=nb;
+			}
+
+			ecurve(0,b,p,MR_AFFINE);
+// find number of points on sextic twist..
+			twist=MR_SEXTIC_D;
+			mip->TWIST=MR_SEXTIC_D;
+
+			if (type==BLS12 || type==BN)
+			{
+				ECn2 Q;
+				ZZn2 rr;
+
+				do
+				{
+					rr=randn2();
+				} while (!Q.set(rr));
+        
+				Q*=cof2;
+				if (!(n*Q).iszero()) 
+				{
+					twist=MR_SEXTIC_M;
+					mip->TWIST=MR_SEXTIC_M;
+					do
+					{
+						rr=randn2();
+					} while (!Q.set(rr));
+        
+					Q*=cof2;
+					if (!(n*Q).iszero()) 
+					{
+						cout << "Never Happens" << endl;
+						continue;
+					}
+				}
+			}
+			if (type==BLS24)
+			{
+				ECn4 Q;
+				ZZn4 rr;
+				do
+				{
+					rr=randn4();
+				} while (!Q.set(rr));
+
+				Q*=cof2;
+				if (!(n*Q).iszero()) 
+				{
+					twist=MR_SEXTIC_M;
+					mip->TWIST=MR_SEXTIC_M;
+					do
+					{
+						rr=randn4();
+					} while (!Q.set(rr));
+        
+					Q*=cof2;
+					if (!(n*Q).iszero()) 
+					{
+						cout << "Never Happens" << endl;
+						continue;
+					}
+				}
+			}
+			if (type==BLS48)
+			{
+				ECn8 Q;
+				ZZn8 rr;
+				do
+				{
+					rr=randn8();
+				} while (!Q.set(rr));
+
+				Q*=cof2;
+				if (!(n*Q).iszero()) 
+				{
+					twist=MR_SEXTIC_M;
+					mip->TWIST=MR_SEXTIC_M;
+					do
+					{
+						rr=randn8();
+					} while (!Q.set(rr));
+        
+					Q*=cof2;
+					if (!(n*Q).iszero()) 
+					{
+						cout << "Never Happens" << endl;
+						continue;
+					}
+				}
+			}
+			S++;
+			cout << endl;
+			cout << "Solution " << S << endl;
+			x=0;
+			bt=1;
+			mip->IOBASE=16;
+
+			cout << "x= ";
+			for (k=0;k<j;k++)
+			{
+				if ((bt&i)!=0) {x+=xp[k]; cout << "+2^" << pw[k];}
+				else {x-=xp[k]; cout << "-2^" << pw[k];}
+				bt<<=1;
+			}
+			cout << " = " << x << endl;
+			cout << "Curve is y^2=x^3+" << b;
+			if (m>0)
+			{
+				cout << " (or) ";
+				for (jj=0;jj<m;jj++)
+					cout << cb[jj] << " ";
+			}
+			else cout << endl;
+			cout << "\np= " << p << " (" << bits(p) << " bits)";
+			if (twist==MR_SEXTIC_D) cout << " D-Type" << endl;
+			if (twist==MR_SEXTIC_M) cout << " M-Type" << endl;
+			if (progress) cout << endl;
+			mip->IOBASE=10;
+		//	cout << "twist= " << p+1+t << endl;
+		}
+	}
+
+	cout << endl;
+	cout << cnt << " candidates searched" << endl;
+
+	if (S==0)
+	{
+		cout << "No solutions found" << endl;
+		return 0;
+	}
+	if (S==1)
+	{
+		cout << "One solution found" << endl;
+		return 0;
+	}
+	cout << S << " solutions found" << endl;
+	return 0;
+}
diff --git a/version3/bigtobig.cpp b/version3/bigtobig.cpp
new file mode 100644
index 0000000..fbc89ea
--- /dev/null
+++ b/version3/bigtobig.cpp
@@ -0,0 +1,292 @@
+/*
+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.
+*/
+
+//
+// Program to convert from Big to AMCL BIG format
+// cl /O2 bigtobig.cpp big.cpp miracl.lib
+// g++ -O2 bigtobig.cpp big.cpp miracl.a -o bigtobig
+//
+//
+
+#include <iostream>
+#include "zzn.h"
+
+using namespace std;
+
+Miracl precision=100;
+
+// Code to parse formula in command line
+// This code isn't mine, but its public domain
+// Shamefully I forget the source
+//
+// NOTE: It may be necessary on some platforms to change the operators * and #
+//
+
+#if defined(unix)
+#define TIMES '.'
+#define RAISE '^'
+#else
+#define TIMES '*'
+#define RAISE '#'
+#endif
+
+Big tt;
+static char *ss;
+
+void eval_power (Big& oldn,Big& n,char op)
+{
+        if (op) n=pow(oldn,toint(n));    // power(oldn,size(n),n,n);
+}
+
+void eval_product (Big& oldn,Big& n,char op)
+{
+        switch (op)
+        {
+        case TIMES:
+                n*=oldn; 
+                break;
+        case '/':
+                n=oldn/n;
+                break;
+        case '%':
+                n=oldn%n;
+        }
+}
+
+void eval_sum (Big& oldn,Big& n,char op)
+{
+        switch (op)
+        {
+        case '+':
+                n+=oldn;
+                break;
+        case '-':
+                n=oldn-n;
+        }
+}
+
+void eval (void)
+{
+        Big oldn[3];
+        Big n;
+        int i;
+        char oldop[3];
+        char op;
+        char minus;
+        for (i=0;i<3;i++)
+        {
+            oldop[i]=0;
+        }
+LOOP:
+        while (*ss==' ')
+        ss++;
+        if (*ss=='-')    /* Unary minus */
+        {
+        ss++;
+        minus=1;
+        }
+        else
+        minus=0;
+        while (*ss==' ')
+        ss++;
+        if (*ss=='(' || *ss=='[' || *ss=='{')    /* Number is subexpression */
+        {
+        ss++;
+        eval ();
+        n=tt;
+        }
+        else            /* Number is decimal value */
+        {
+        for (i=0;ss[i]>='0' && ss[i]<='9';i++)
+                ;
+        if (!i)         /* No digits found */
+        {
+                cout <<  "Error - invalid number" << endl;
+                exit (20);
+        }
+        op=ss[i];
+        ss[i]=0;
+        n=atoi(ss);
+        ss+=i;
+        *ss=op;
+        }
+        if (minus) n=-n;
+        do
+        op=*ss++;
+        while (op==' ');
+        if (op==0 || op==')' || op==']' || op=='}')
+        {
+        eval_power (oldn[2],n,oldop[2]);
+        eval_product (oldn[1],n,oldop[1]);
+        eval_sum (oldn[0],n,oldop[0]);
+        tt=n;
+        return;
+        }
+        else
+        {
+        if (op==RAISE)
+        {
+                eval_power (oldn[2],n,oldop[2]);
+                oldn[2]=n;
+                oldop[2]=RAISE;
+        }
+        else
+        {
+                if (op==TIMES || op=='/' || op=='%')
+                {
+                eval_power (oldn[2],n,oldop[2]);
+                oldop[2]=0;
+                eval_product (oldn[1],n,oldop[1]);
+                oldn[1]=n;
+                oldop[1]=op;
+                }
+                else
+                {
+                if (op=='+' || op=='-')
+                {
+                        eval_power (oldn[2],n,oldop[2]);
+                        oldop[2]=0;
+                        eval_product (oldn[1],n,oldop[1]);
+                        oldop[1]=0;
+                        eval_sum (oldn[0],n,oldop[0]);
+                        oldn[0]=n;
+                        oldop[0]=op;
+                }
+                else    /* Error - invalid operator */
+                {
+                        cout <<  "Error - invalid operator" << endl;
+                        exit (20);
+                }
+                }
+        }
+        }
+        goto LOOP;
+}
+
+void output(int w,Big t,Big m)
+{
+	Big y=t;
+
+	for (int i=0;i<w;i++)
+	{
+		cout << "0x" << y%m ;
+		if (i<w-1) cout << ",";
+		y/=m;
+	}
+	cout << endl;
+}
+
+int main(int argc, char **argv)
+{
+    int i,ip,chunk,basebits;
+    Big n,m;
+    BOOL gotP,gotA,gotB;
+    int Base;
+    miracl *mip=&precision;
+    argv++; argc--;
+    if (argc<1)
+    {
+        cout << "Program converts from Big to BIG" << endl;
+        cout << "bigtobig <big number> <chunk>> <basebits>" << endl;
+        cout << "OR" << endl;
+        cout << "bigtobig <formula for big number> <chunk>> <basebits>" << endl;
+#if defined(unix)
+        cout << "e.g. bigtobig -f 2^255-19 32 29" << endl;
+#else
+        cout << "e.g. bigtobig -f 2#255-19 32 29" << endl;
+#endif
+        cout << "To input Big number in Hex, precede with -h" << endl;
+        return 0;
+    }
+
+    ip=0;
+    gprime(1000);
+    gotP=gotA=gotB=FALSE;
+    n=0;
+    Base=10;
+    while (ip<argc)
+    { 
+        if (!gotP && strcmp(argv[ip],"-f")==0)
+        {
+            ip++;
+            if (!gotP && ip<argc)
+            {
+
+                ss=argv[ip++];
+                tt=0;
+                eval();
+                n=tt;
+                gotP=TRUE;
+                continue;
+            }
+            else
+            {
+                cout << "Error in command line" << endl;
+                return 0;
+            }
+        }
+ 
+
+        if (strcmp(argv[ip],"-h")==0)
+        {
+            ip++;
+            Base=16;
+            continue;
+        }
+   
+        if (!gotP)
+        {
+            mip->IOBASE=Base;
+            n=argv[ip++];
+            mip->IOBASE=10;
+            gotP=TRUE;
+            continue;
+        }
+        if (!gotA) 
+        {
+            mip->IOBASE=Base;
+            chunk=atoi(argv[ip++]);
+            gotA=TRUE;
+            continue;
+        }
+        if (!gotB) 
+        {
+            mip->IOBASE=Base;
+            basebits=atoi(argv[ip++]);
+            gotB=TRUE;
+            continue;
+        }
+        cout << "Error in command line" << endl;
+        return 0;
+    }
+    if (!gotP || !gotA || !gotB)
+    {
+        cout << "Error in command line" << endl;
+        return 0;
+    }
+
+	mip->IOBASE=16;
+
+	m=pow((Big)2,basebits);
+
+	output(1+bits(n)/basebits,n,m);
+
+    return 0;
+}
+
diff --git a/version3/c/aes.c b/version3/c/aes.c
new file mode 100644
index 0000000..656a031
--- /dev/null
+++ b/version3/c/aes.c
@@ -0,0 +1,704 @@
+/*
+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.
+*/
+
+
+/*
+ * Implementation of the NIST Advanced Ecryption Standard
+ *
+ * SU=m, SU is Stack Usage
+ */
+
+#include <stdlib.h>
+#include "arch.h"
+#include "amcl.h"
+
+/* this is fixed */
+#define NB 4
+
+/* Rotates 32-bit word left by 1, 2 or 3 byte  */
+
+#define ROTL8(x) (((x)<<8)|((x)>>24))
+#define ROTL16(x) (((x)<<16)|((x)>>16))
+#define ROTL24(x) (((x)<<24)|((x)>>8))
+
+static const uchar InCo[4]= {0xB,0xD,0x9,0xE}; /* Inverse Coefficients */
+
+static const uchar ptab[]=
+{
+    1,3,5,15,17,51,85,255,26,46,114,150,161,248,19,53,
+    95,225,56,72,216,115,149,164,247,2,6,10,30,34,102,170,
+    229,52,92,228,55,89,235,38,106,190,217,112,144,171,230,49,
+    83,245,4,12,20,60,68,204,79,209,104,184,211,110,178,205,
+    76,212,103,169,224,59,77,215,98,166,241,8,24,40,120,136,
+    131,158,185,208,107,189,220,127,129,152,179,206,73,219,118,154,
+    181,196,87,249,16,48,80,240,11,29,39,105,187,214,97,163,
+    254,25,43,125,135,146,173,236,47,113,147,174,233,32,96,160,
+    251,22,58,78,210,109,183,194,93,231,50,86,250,21,63,65,
+    195,94,226,61,71,201,64,192,91,237,44,116,156,191,218,117,
+    159,186,213,100,172,239,42,126,130,157,188,223,122,142,137,128,
+    155,182,193,88,232,35,101,175,234,37,111,177,200,67,197,84,
+    252,31,33,99,165,244,7,9,27,45,119,153,176,203,70,202,
+    69,207,74,222,121,139,134,145,168,227,62,66,198,81,243,14,
+    18,54,90,238,41,123,141,140,143,138,133,148,167,242,13,23,
+    57,75,221,124,132,151,162,253,28,36,108,180,199,82,246,1
+};
+
+static const uchar ltab[]=
+{
+    0,255,25,1,50,2,26,198,75,199,27,104,51,238,223,3,
+    100,4,224,14,52,141,129,239,76,113,8,200,248,105,28,193,
+    125,194,29,181,249,185,39,106,77,228,166,114,154,201,9,120,
+    101,47,138,5,33,15,225,36,18,240,130,69,53,147,218,142,
+    150,143,219,189,54,208,206,148,19,92,210,241,64,70,131,56,
+    102,221,253,48,191,6,139,98,179,37,226,152,34,136,145,16,
+    126,110,72,195,163,182,30,66,58,107,40,84,250,133,61,186,
+    43,121,10,21,155,159,94,202,78,212,172,229,243,115,167,87,
+    175,88,168,80,244,234,214,116,79,174,233,213,231,230,173,232,
+    44,215,117,122,235,22,11,245,89,203,95,176,156,169,81,160,
+    127,12,246,111,23,196,73,236,216,67,31,45,164,118,123,183,
+    204,187,62,90,251,96,177,134,59,82,161,108,170,85,41,157,
+    151,178,135,144,97,190,220,252,188,149,207,205,55,63,91,209,
+    83,57,132,60,65,162,109,71,20,42,158,93,86,242,211,171,
+    68,17,146,217,35,32,46,137,180,124,184,38,119,153,227,165,
+    103,74,237,222,197,49,254,24,13,99,140,128,192,247,112,7
+};
+
+static const uchar fbsub[]=
+{
+    99,124,119,123,242,107,111,197,48,1,103,43,254,215,171,118,
+    202,130,201,125,250,89,71,240,173,212,162,175,156,164,114,192,
+    183,253,147,38,54,63,247,204,52,165,229,241,113,216,49,21,
+    4,199,35,195,24,150,5,154,7,18,128,226,235,39,178,117,
+    9,131,44,26,27,110,90,160,82,59,214,179,41,227,47,132,
+    83,209,0,237,32,252,177,91,106,203,190,57,74,76,88,207,
+    208,239,170,251,67,77,51,133,69,249,2,127,80,60,159,168,
+    81,163,64,143,146,157,56,245,188,182,218,33,16,255,243,210,
+    205,12,19,236,95,151,68,23,196,167,126,61,100,93,25,115,
+    96,129,79,220,34,42,144,136,70,238,184,20,222,94,11,219,
+    224,50,58,10,73,6,36,92,194,211,172,98,145,149,228,121,
+    231,200,55,109,141,213,78,169,108,86,244,234,101,122,174,8,
+    186,120,37,46,28,166,180,198,232,221,116,31,75,189,139,138,
+    112,62,181,102,72,3,246,14,97,53,87,185,134,193,29,158,
+    225,248,152,17,105,217,142,148,155,30,135,233,206,85,40,223,
+    140,161,137,13,191,230,66,104,65,153,45,15,176,84,187,22
+};
+
+static const uchar rbsub[]=
+{
+    82,9,106,213,48,54,165,56,191,64,163,158,129,243,215,251,
+    124,227,57,130,155,47,255,135,52,142,67,68,196,222,233,203,
+    84,123,148,50,166,194,35,61,238,76,149,11,66,250,195,78,
+    8,46,161,102,40,217,36,178,118,91,162,73,109,139,209,37,
+    114,248,246,100,134,104,152,22,212,164,92,204,93,101,182,146,
+    108,112,72,80,253,237,185,218,94,21,70,87,167,141,157,132,
+    144,216,171,0,140,188,211,10,247,228,88,5,184,179,69,6,
+    208,44,30,143,202,63,15,2,193,175,189,3,1,19,138,107,
+    58,145,17,65,79,103,220,234,151,242,207,206,240,180,230,115,
+    150,172,116,34,231,173,53,133,226,249,55,232,28,117,223,110,
+    71,241,26,113,29,41,197,137,111,183,98,14,170,24,190,27,
+    252,86,62,75,198,210,121,32,154,219,192,254,120,205,90,244,
+    31,221,168,51,136,7,199,49,177,18,16,89,39,128,236,95,
+    96,81,127,169,25,181,74,13,45,229,122,159,147,201,156,239,
+    160,224,59,77,174,42,245,176,200,235,187,60,131,83,153,97,
+    23,43,4,126,186,119,214,38,225,105,20,99,85,33,12,125
+};
+
+static const unsign32 rco[]=
+{1,2,4,8,16,32,64,128,27,54,108,216,171,77,154,47};
+
+static const unsign32 ftable[]=
+{
+    0xa56363c6,0x847c7cf8,0x997777ee,0x8d7b7bf6,0xdf2f2ff,0xbd6b6bd6,
+    0xb16f6fde,0x54c5c591,0x50303060,0x3010102,0xa96767ce,0x7d2b2b56,
+    0x19fefee7,0x62d7d7b5,0xe6abab4d,0x9a7676ec,0x45caca8f,0x9d82821f,
+    0x40c9c989,0x877d7dfa,0x15fafaef,0xeb5959b2,0xc947478e,0xbf0f0fb,
+    0xecadad41,0x67d4d4b3,0xfda2a25f,0xeaafaf45,0xbf9c9c23,0xf7a4a453,
+    0x967272e4,0x5bc0c09b,0xc2b7b775,0x1cfdfde1,0xae93933d,0x6a26264c,
+    0x5a36366c,0x413f3f7e,0x2f7f7f5,0x4fcccc83,0x5c343468,0xf4a5a551,
+    0x34e5e5d1,0x8f1f1f9,0x937171e2,0x73d8d8ab,0x53313162,0x3f15152a,
+    0xc040408,0x52c7c795,0x65232346,0x5ec3c39d,0x28181830,0xa1969637,
+    0xf05050a,0xb59a9a2f,0x907070e,0x36121224,0x9b80801b,0x3de2e2df,
+    0x26ebebcd,0x6927274e,0xcdb2b27f,0x9f7575ea,0x1b090912,0x9e83831d,
+    0x742c2c58,0x2e1a1a34,0x2d1b1b36,0xb26e6edc,0xee5a5ab4,0xfba0a05b,
+    0xf65252a4,0x4d3b3b76,0x61d6d6b7,0xceb3b37d,0x7b292952,0x3ee3e3dd,
+    0x712f2f5e,0x97848413,0xf55353a6,0x68d1d1b9,0x0,0x2cededc1,
+    0x60202040,0x1ffcfce3,0xc8b1b179,0xed5b5bb6,0xbe6a6ad4,0x46cbcb8d,
+    0xd9bebe67,0x4b393972,0xde4a4a94,0xd44c4c98,0xe85858b0,0x4acfcf85,
+    0x6bd0d0bb,0x2aefefc5,0xe5aaaa4f,0x16fbfbed,0xc5434386,0xd74d4d9a,
+    0x55333366,0x94858511,0xcf45458a,0x10f9f9e9,0x6020204,0x817f7ffe,
+    0xf05050a0,0x443c3c78,0xba9f9f25,0xe3a8a84b,0xf35151a2,0xfea3a35d,
+    0xc0404080,0x8a8f8f05,0xad92923f,0xbc9d9d21,0x48383870,0x4f5f5f1,
+    0xdfbcbc63,0xc1b6b677,0x75dadaaf,0x63212142,0x30101020,0x1affffe5,
+    0xef3f3fd,0x6dd2d2bf,0x4ccdcd81,0x140c0c18,0x35131326,0x2fececc3,
+    0xe15f5fbe,0xa2979735,0xcc444488,0x3917172e,0x57c4c493,0xf2a7a755,
+    0x827e7efc,0x473d3d7a,0xac6464c8,0xe75d5dba,0x2b191932,0x957373e6,
+    0xa06060c0,0x98818119,0xd14f4f9e,0x7fdcdca3,0x66222244,0x7e2a2a54,
+    0xab90903b,0x8388880b,0xca46468c,0x29eeeec7,0xd3b8b86b,0x3c141428,
+    0x79dedea7,0xe25e5ebc,0x1d0b0b16,0x76dbdbad,0x3be0e0db,0x56323264,
+    0x4e3a3a74,0x1e0a0a14,0xdb494992,0xa06060c,0x6c242448,0xe45c5cb8,
+    0x5dc2c29f,0x6ed3d3bd,0xefacac43,0xa66262c4,0xa8919139,0xa4959531,
+    0x37e4e4d3,0x8b7979f2,0x32e7e7d5,0x43c8c88b,0x5937376e,0xb76d6dda,
+    0x8c8d8d01,0x64d5d5b1,0xd24e4e9c,0xe0a9a949,0xb46c6cd8,0xfa5656ac,
+    0x7f4f4f3,0x25eaeacf,0xaf6565ca,0x8e7a7af4,0xe9aeae47,0x18080810,
+    0xd5baba6f,0x887878f0,0x6f25254a,0x722e2e5c,0x241c1c38,0xf1a6a657,
+    0xc7b4b473,0x51c6c697,0x23e8e8cb,0x7cdddda1,0x9c7474e8,0x211f1f3e,
+    0xdd4b4b96,0xdcbdbd61,0x868b8b0d,0x858a8a0f,0x907070e0,0x423e3e7c,
+    0xc4b5b571,0xaa6666cc,0xd8484890,0x5030306,0x1f6f6f7,0x120e0e1c,
+    0xa36161c2,0x5f35356a,0xf95757ae,0xd0b9b969,0x91868617,0x58c1c199,
+    0x271d1d3a,0xb99e9e27,0x38e1e1d9,0x13f8f8eb,0xb398982b,0x33111122,
+    0xbb6969d2,0x70d9d9a9,0x898e8e07,0xa7949433,0xb69b9b2d,0x221e1e3c,
+    0x92878715,0x20e9e9c9,0x49cece87,0xff5555aa,0x78282850,0x7adfdfa5,
+    0x8f8c8c03,0xf8a1a159,0x80898909,0x170d0d1a,0xdabfbf65,0x31e6e6d7,
+    0xc6424284,0xb86868d0,0xc3414182,0xb0999929,0x772d2d5a,0x110f0f1e,
+    0xcbb0b07b,0xfc5454a8,0xd6bbbb6d,0x3a16162c
+};
+
+static const unsign32 rtable[]=
+{
+    0x50a7f451,0x5365417e,0xc3a4171a,0x965e273a,0xcb6bab3b,0xf1459d1f,
+    0xab58faac,0x9303e34b,0x55fa3020,0xf66d76ad,0x9176cc88,0x254c02f5,
+    0xfcd7e54f,0xd7cb2ac5,0x80443526,0x8fa362b5,0x495ab1de,0x671bba25,
+    0x980eea45,0xe1c0fe5d,0x2752fc3,0x12f04c81,0xa397468d,0xc6f9d36b,
+    0xe75f8f03,0x959c9215,0xeb7a6dbf,0xda595295,0x2d83bed4,0xd3217458,
+    0x2969e049,0x44c8c98e,0x6a89c275,0x78798ef4,0x6b3e5899,0xdd71b927,
+    0xb64fe1be,0x17ad88f0,0x66ac20c9,0xb43ace7d,0x184adf63,0x82311ae5,
+    0x60335197,0x457f5362,0xe07764b1,0x84ae6bbb,0x1ca081fe,0x942b08f9,
+    0x58684870,0x19fd458f,0x876cde94,0xb7f87b52,0x23d373ab,0xe2024b72,
+    0x578f1fe3,0x2aab5566,0x728ebb2,0x3c2b52f,0x9a7bc586,0xa50837d3,
+    0xf2872830,0xb2a5bf23,0xba6a0302,0x5c8216ed,0x2b1ccf8a,0x92b479a7,
+    0xf0f207f3,0xa1e2694e,0xcdf4da65,0xd5be0506,0x1f6234d1,0x8afea6c4,
+    0x9d532e34,0xa055f3a2,0x32e18a05,0x75ebf6a4,0x39ec830b,0xaaef6040,
+    0x69f715e,0x51106ebd,0xf98a213e,0x3d06dd96,0xae053edd,0x46bde64d,
+    0xb58d5491,0x55dc471,0x6fd40604,0xff155060,0x24fb9819,0x97e9bdd6,
+    0xcc434089,0x779ed967,0xbd42e8b0,0x888b8907,0x385b19e7,0xdbeec879,
+    0x470a7ca1,0xe90f427c,0xc91e84f8,0x0,0x83868009,0x48ed2b32,
+    0xac70111e,0x4e725a6c,0xfbff0efd,0x5638850f,0x1ed5ae3d,0x27392d36,
+    0x64d90f0a,0x21a65c68,0xd1545b9b,0x3a2e3624,0xb1670a0c,0xfe75793,
+    0xd296eeb4,0x9e919b1b,0x4fc5c080,0xa220dc61,0x694b775a,0x161a121c,
+    0xaba93e2,0xe52aa0c0,0x43e0223c,0x1d171b12,0xb0d090e,0xadc78bf2,
+    0xb9a8b62d,0xc8a91e14,0x8519f157,0x4c0775af,0xbbdd99ee,0xfd607fa3,
+    0x9f2601f7,0xbcf5725c,0xc53b6644,0x347efb5b,0x7629438b,0xdcc623cb,
+    0x68fcedb6,0x63f1e4b8,0xcadc31d7,0x10856342,0x40229713,0x2011c684,
+    0x7d244a85,0xf83dbbd2,0x1132f9ae,0x6da129c7,0x4b2f9e1d,0xf330b2dc,
+    0xec52860d,0xd0e3c177,0x6c16b32b,0x99b970a9,0xfa489411,0x2264e947,
+    0xc48cfca8,0x1a3ff0a0,0xd82c7d56,0xef903322,0xc74e4987,0xc1d138d9,
+    0xfea2ca8c,0x360bd498,0xcf81f5a6,0x28de7aa5,0x268eb7da,0xa4bfad3f,
+    0xe49d3a2c,0xd927850,0x9bcc5f6a,0x62467e54,0xc2138df6,0xe8b8d890,
+    0x5ef7392e,0xf5afc382,0xbe805d9f,0x7c93d069,0xa92dd56f,0xb31225cf,
+    0x3b99acc8,0xa77d1810,0x6e639ce8,0x7bbb3bdb,0x97826cd,0xf418596e,
+    0x1b79aec,0xa89a4f83,0x656e95e6,0x7ee6ffaa,0x8cfbc21,0xe6e815ef,
+    0xd99be7ba,0xce366f4a,0xd4099fea,0xd67cb029,0xafb2a431,0x31233f2a,
+    0x3094a5c6,0xc066a235,0x37bc4e74,0xa6ca82fc,0xb0d090e0,0x15d8a733,
+    0x4a9804f1,0xf7daec41,0xe50cd7f,0x2ff69117,0x8dd64d76,0x4db0ef43,
+    0x544daacc,0xdf0496e4,0xe3b5d19e,0x1b886a4c,0xb81f2cc1,0x7f516546,
+    0x4ea5e9d,0x5d358c01,0x737487fa,0x2e410bfb,0x5a1d67b3,0x52d2db92,
+    0x335610e9,0x1347d66d,0x8c61d79a,0x7a0ca137,0x8e14f859,0x893c13eb,
+    0xee27a9ce,0x35c961b7,0xede51ce1,0x3cb1477a,0x59dfd29c,0x3f73f255,
+    0x79ce1418,0xbf37c773,0xeacdf753,0x5baafd5f,0x146f3ddf,0x86db4478,
+    0x81f3afca,0x3ec468b9,0x2c342438,0x5f40a3c2,0x72c31d16,0xc25e2bc,
+    0x8b493c28,0x41950dff,0x7101a839,0xdeb30c08,0x9ce4b4d8,0x90c15664,
+    0x6184cb7b,0x70b632d5,0x745c6c48,0x4257b8d0
+};
+
+#define MR_TOBYTE(x) ((uchar)((x)))
+
+static unsign32 pack(const uchar *b)
+{
+    /* pack bytes into a 32-bit Word */
+    return ((unsign32)b[3]<<24)|((unsign32)b[2]<<16)|((unsign32)b[1]<<8)|(unsign32)b[0];
+}
+
+static void unpack(unsign32 a,uchar *b)
+{
+    /* unpack bytes from a word */
+    b[0]=MR_TOBYTE(a);
+    b[1]=MR_TOBYTE(a>>8);
+    b[2]=MR_TOBYTE(a>>16);
+    b[3]=MR_TOBYTE(a>>24);
+}
+
+/* SU= 8 */
+static uchar bmul(uchar x,uchar y)
+{
+    /* x.y= AntiLog(Log(x) + Log(y)) */
+    if (x && y) return ptab[(ltab[x]+ltab[y])%255];
+    else return 0;
+}
+
+static unsign32 SubByte(unsign32 a)
+{
+    uchar b[4];
+    unpack(a,b);
+    b[0]=fbsub[b[0]];
+    b[1]=fbsub[b[1]];
+    b[2]=fbsub[b[2]];
+    b[3]=fbsub[b[3]];
+    return pack(b);
+}
+
+/* SU= 16 */
+static uchar product(unsign32 x,unsign32 y)
+{
+    /* dot product of two 4-byte arrays */
+    uchar xb[4],yb[4];
+    unpack(x,xb);
+    unpack(y,yb);
+    return bmul(xb[0],yb[0])^bmul(xb[1],yb[1])^bmul(xb[2],yb[2])^bmul(xb[3],yb[3]);
+}
+
+static unsign32 InvMixCol(unsign32 x)
+{
+    /* matrix Multiplication */
+    unsign32 y,m;
+    uchar b[4];
+
+    m=pack(InCo);
+    b[3]=product(m,x);
+    m=ROTL24(m);
+    b[2]=product(m,x);
+    m=ROTL24(m);
+    b[1]=product(m,x);
+    m=ROTL24(m);
+    b[0]=product(m,x);
+    y=pack(b);
+    return y;
+}
+
+/* SU= 8 */
+/* reset cipher */
+void AES_reset(amcl_aes *a,int mode,char *iv)
+{
+    /* reset mode, or reset iv */
+    int i;
+    a->mode=mode;
+    for (i=0; i<4*NB; i++)
+        a->f[i]=0;
+    if (mode!=ECB && iv!=NULL)
+    {
+        for (i=0; i<4*NB; i++)
+            a->f[i]=iv[i];
+    }
+}
+
+void AES_getreg(amcl_aes *a,char *ir)
+{
+    int i;
+    for (i=0; i<4*NB; i++) ir[i]=a->f[i];
+}
+
+/* SU= 72 */
+/* Initialise cipher */
+int AES_init(amcl_aes* a,int mode,int nk,char *key,char *iv)
+{
+    /* Key length Nk=16, 24 or 32 bytes */
+    /* Key Scheduler. Create expanded encryption key */
+    int i,j,k,N,nr;
+    unsign32 CipherKey[8];
+
+    nk/=4;
+
+    if (nk!=4 && nk!=6 && nk!=8) return 0;
+
+    nr=6+nk;
+
+    a->Nk=nk;
+    a->Nr=nr;
+
+    AES_reset(a,mode,iv);
+
+    N=NB*(nr+1);
+
+    for (i=j=0; i<nk; i++,j+=4)
+    {
+        CipherKey[i]=pack((uchar *)&key[j]);
+    }
+    for (i=0; i<nk; i++) a->fkey[i]=CipherKey[i];
+    for (j=nk,k=0; j<N; j+=nk,k++)
+    {
+        a->fkey[j]=a->fkey[j-nk]^SubByte(ROTL24(a->fkey[j-1]))^rco[k];
+        if (nk<=6)
+        {
+            for (i=1; i<nk && (i+j)<N; i++)
+                a->fkey[i+j]=a->fkey[i+j-nk]^a->fkey[i+j-1];
+        }
+        else
+        {
+            for (i=1; i<4 && (i+j)<N; i++)
+                a->fkey[i+j]=a->fkey[i+j-nk]^a->fkey[i+j-1];
+            if ((j+4)<N) a->fkey[j+4]=a->fkey[j+4-nk]^SubByte(a->fkey[j+3]);
+            for (i=5; i<nk && (i+j)<N; i++)
+                a->fkey[i+j]=a->fkey[i+j-nk]^a->fkey[i+j-1];
+        }
+
+    }
+    /* now for the expanded decrypt key in reverse order */
+
+    for (j=0; j<NB; j++) a->rkey[j+N-NB]=a->fkey[j];
+    for (i=NB; i<N-NB; i+=NB)
+    {
+        k=N-NB-i;
+        for (j=0; j<NB; j++) a->rkey[k+j]=InvMixCol(a->fkey[i+j]);
+    }
+    for (j=N-NB; j<N; j++) a->rkey[j-N+NB]=a->fkey[j];
+    return 1;
+}
+
+/* SU= 80 */
+/* Encrypt a single block */
+void AES_ecb_encrypt(amcl_aes *a,uchar *buff)
+{
+    int i,j,k;
+    unsign32 p[4],q[4],*x,*y,*t;
+
+    for (i=j=0; i<NB; i++,j+=4)
+    {
+        p[i]=pack((uchar *)&buff[j]);
+        p[i]^=a->fkey[i];
+    }
+
+    k=NB;
+    x=p;
+    y=q;
+
+    /* State alternates between x and y */
+    for (i=1; i<a->Nr; i++)
+    {
+
+        y[0]=a->fkey[k]^ftable[MR_TOBYTE(x[0])]^
+             ROTL8(ftable[MR_TOBYTE(x[1]>>8)])^
+             ROTL16(ftable[MR_TOBYTE(x[2]>>16)])^
+             ROTL24(ftable[x[3]>>24]);
+        y[1]=a->fkey[k+1]^ftable[MR_TOBYTE(x[1])]^
+             ROTL8(ftable[MR_TOBYTE(x[2]>>8)])^
+             ROTL16(ftable[MR_TOBYTE(x[3]>>16)])^
+             ROTL24(ftable[x[0]>>24]);
+        y[2]=a->fkey[k+2]^ftable[MR_TOBYTE(x[2])]^
+             ROTL8(ftable[MR_TOBYTE(x[3]>>8)])^
+             ROTL16(ftable[MR_TOBYTE(x[0]>>16)])^
+             ROTL24(ftable[x[1]>>24]);
+        y[3]=a->fkey[k+3]^ftable[MR_TOBYTE(x[3])]^
+             ROTL8(ftable[MR_TOBYTE(x[0]>>8)])^
+             ROTL16(ftable[MR_TOBYTE(x[1]>>16)])^
+             ROTL24(ftable[x[2]>>24]);
+
+        k+=4;
+        t=x;
+        x=y;
+        y=t;      /* swap pointers */
+    }
+
+    /* Last Round */
+
+    y[0]=a->fkey[k]^(unsign32)fbsub[MR_TOBYTE(x[0])]^
+         ROTL8((unsign32)fbsub[MR_TOBYTE(x[1]>>8)])^
+         ROTL16((unsign32)fbsub[MR_TOBYTE(x[2]>>16)])^
+         ROTL24((unsign32)fbsub[x[3]>>24]);
+    y[1]=a->fkey[k+1]^(unsign32)fbsub[MR_TOBYTE(x[1])]^
+         ROTL8((unsign32)fbsub[MR_TOBYTE(x[2]>>8)])^
+         ROTL16((unsign32)fbsub[MR_TOBYTE(x[3]>>16)])^
+         ROTL24((unsign32)fbsub[x[0]>>24]);
+    y[2]=a->fkey[k+2]^(unsign32)fbsub[MR_TOBYTE(x[2])]^
+         ROTL8((unsign32)fbsub[MR_TOBYTE(x[3]>>8)])^
+         ROTL16((unsign32)fbsub[MR_TOBYTE(x[0]>>16)])^
+         ROTL24((unsign32)fbsub[x[1]>>24]);
+    y[3]=a->fkey[k+3]^(unsign32)fbsub[MR_TOBYTE(x[3])]^
+         ROTL8((unsign32)fbsub[MR_TOBYTE(x[0]>>8)])^
+         ROTL16((unsign32)fbsub[MR_TOBYTE(x[1]>>16)])^
+         ROTL24((unsign32)fbsub[x[2]>>24]);
+
+    for (i=j=0; i<NB; i++,j+=4)
+    {
+        unpack(y[i],(uchar *)&buff[j]);
+        x[i]=y[i]=0;   /* clean up stack */
+    }
+}
+
+/* SU= 80 */
+/* Decrypt a single block */
+void AES_ecb_decrypt(amcl_aes *a,uchar *buff)
+{
+    int i,j,k;
+    unsign32 p[4],q[4],*x,*y,*t;
+
+    for (i=j=0; i<NB; i++,j+=4)
+    {
+        p[i]=pack((uchar *)&buff[j]);
+        p[i]^=a->rkey[i];
+    }
+
+    k=NB;
+    x=p;
+    y=q;
+
+    /* State alternates between x and y */
+    for (i=1; i<a->Nr; i++)
+    {
+        /* Nr is number of rounds. May be odd. */
+
+        y[0]=a->rkey[k]^rtable[MR_TOBYTE(x[0])]^
+             ROTL8(rtable[MR_TOBYTE(x[3]>>8)])^
+             ROTL16(rtable[MR_TOBYTE(x[2]>>16)])^
+             ROTL24(rtable[x[1]>>24]);
+        y[1]=a->rkey[k+1]^rtable[MR_TOBYTE(x[1])]^
+             ROTL8(rtable[MR_TOBYTE(x[0]>>8)])^
+             ROTL16(rtable[MR_TOBYTE(x[3]>>16)])^
+             ROTL24(rtable[x[2]>>24]);
+        y[2]=a->rkey[k+2]^rtable[MR_TOBYTE(x[2])]^
+             ROTL8(rtable[MR_TOBYTE(x[1]>>8)])^
+             ROTL16(rtable[MR_TOBYTE(x[0]>>16)])^
+             ROTL24(rtable[x[3]>>24]);
+        y[3]=a->rkey[k+3]^rtable[MR_TOBYTE(x[3])]^
+             ROTL8(rtable[MR_TOBYTE(x[2]>>8)])^
+             ROTL16(rtable[MR_TOBYTE(x[1]>>16)])^
+             ROTL24(rtable[x[0]>>24]);
+
+        k+=4;
+        t=x;
+        x=y;
+        y=t;      /* swap pointers */
+    }
+
+
+    /* Last Round */
+    y[0]=a->rkey[k]^(unsign32)rbsub[MR_TOBYTE(x[0])]^
+         ROTL8((unsign32)rbsub[MR_TOBYTE(x[3]>>8)])^
+         ROTL16((unsign32)rbsub[MR_TOBYTE(x[2]>>16)])^
+         ROTL24((unsign32)rbsub[x[1]>>24]);
+    y[1]=a->rkey[k+1]^(unsign32)rbsub[MR_TOBYTE(x[1])]^
+         ROTL8((unsign32)rbsub[MR_TOBYTE(x[0]>>8)])^
+         ROTL16((unsign32)rbsub[MR_TOBYTE(x[3]>>16)])^
+         ROTL24((unsign32)rbsub[x[2]>>24]);
+    y[2]=a->rkey[k+2]^(unsign32)rbsub[MR_TOBYTE(x[2])]^
+         ROTL8((unsign32)rbsub[MR_TOBYTE(x[1]>>8)])^
+         ROTL16((unsign32)rbsub[MR_TOBYTE(x[0]>>16)])^
+         ROTL24((unsign32)rbsub[x[3]>>24]);
+    y[3]=a->rkey[k+3]^(unsign32)rbsub[MR_TOBYTE(x[3])]^
+         ROTL8((unsign32)rbsub[MR_TOBYTE(x[2]>>8)])^
+         ROTL16((unsign32)rbsub[MR_TOBYTE(x[1]>>16)])^
+         ROTL24((unsign32)rbsub[x[0]>>24]);
+
+    for (i=j=0; i<NB; i++,j+=4)
+    {
+        unpack(y[i],(uchar *)&buff[j]);
+        x[i]=y[i]=0;   /* clean up stack */
+    }
+
+}
+
+/* simple default increment function */
+static void increment(char *f)
+{
+    int i;
+    for (i=0; i<16; i++)
+    {
+        f[i]++;
+        if (f[i]!=0) break;
+    }
+}
+
+/* SU= 40 */
+/* Encrypt using selected mode of operation */
+unsign32 AES_encrypt(amcl_aes* a,char *buff)
+{
+    int j,bytes;
+    char st[16];
+    unsign32 fell_off;
+
+    /* Supported Modes of Operation */
+
+    fell_off=0;
+    switch (a->mode)
+    {
+    case ECB:
+        AES_ecb_encrypt(a,(uchar *)buff);
+        return 0;
+    case CBC:
+        for (j=0; j<4*NB; j++) buff[j]^=a->f[j];
+        AES_ecb_encrypt(a,(uchar *)buff);
+        for (j=0; j<4*NB; j++) a->f[j]=buff[j];
+        return 0;
+
+    case CFB1:
+    case CFB2:
+    case CFB4:
+        bytes=a->mode-CFB1+1;
+        for (j=0; j<bytes; j++) fell_off=(fell_off<<8)|a->f[j];
+        for (j=0; j<4*NB; j++) st[j]=a->f[j];
+        for (j=bytes; j<4*NB; j++) a->f[j-bytes]=a->f[j];
+        AES_ecb_encrypt(a,(uchar *)st);
+        for (j=0; j<bytes; j++)
+        {
+            buff[j]^=st[j];
+            a->f[16-bytes+j]=buff[j];
+        }
+        return fell_off;
+
+    case OFB1:
+    case OFB2:
+    case OFB4:
+    case OFB8:
+    case OFB16:
+
+        bytes=a->mode-OFB1+1;
+        AES_ecb_encrypt(a,(uchar *)(a->f));
+        for (j=0; j<bytes; j++) buff[j]^=a->f[j];
+        return 0;
+
+    case CTR1:
+    case CTR2:
+    case CTR4:
+    case CTR8:
+    case CTR16:
+
+        bytes=a->mode-CTR1+1;
+        for (j=0; j<4*NB; j++) st[j]=a->f[j];
+        AES_ecb_encrypt(a,(uchar *)st);
+        for (j=0; j<bytes; j++) buff[j]^=st[j];
+        increment(a->f);
+        return 0;
+
+    default:
+        return 0;
+    }
+}
+
+/* SU= 40 */
+/* Decrypt using selected mode of operation */
+unsign32 AES_decrypt(amcl_aes *a,char *buff)
+{
+    int j,bytes;
+    char st[16];
+    unsign32 fell_off;
+
+    /* Supported modes of operation */
+    fell_off=0;
+    switch (a->mode)
+    {
+    case ECB:
+        AES_ecb_decrypt(a,(uchar *)buff);
+        return 0;
+    case CBC:
+        for (j=0; j<4*NB; j++)
+        {
+            st[j]=a->f[j];
+            a->f[j]=buff[j];
+        }
+        AES_ecb_decrypt(a,(uchar *)buff);
+        for (j=0; j<4*NB; j++)
+        {
+            buff[j]^=st[j];
+            st[j]=0;
+        }
+        return 0;
+    case CFB1:
+    case CFB2:
+    case CFB4:
+        bytes=a->mode-CFB1+1;
+        for (j=0; j<bytes; j++) fell_off=(fell_off<<8)|a->f[j];
+        for (j=0; j<4*NB; j++) st[j]=a->f[j];
+        for (j=bytes; j<4*NB; j++) a->f[j-bytes]=a->f[j];
+        AES_ecb_encrypt(a,(uchar *)st);
+        for (j=0; j<bytes; j++)
+        {
+            a->f[16-bytes+j]=buff[j];
+            buff[j]^=st[j];
+        }
+        return fell_off;
+    case OFB1:
+    case OFB2:
+    case OFB4:
+    case OFB8:
+    case OFB16:
+        bytes=a->mode-OFB1+1;
+        AES_ecb_encrypt(a,(uchar *)(a->f));
+        for (j=0; j<bytes; j++) buff[j]^=a->f[j];
+        return 0;
+
+    case CTR1:
+    case CTR2:
+    case CTR4:
+    case CTR8:
+    case CTR16:
+
+        bytes=a->mode-CTR1+1;
+        for (j=0; j<4*NB; j++) st[j]=a->f[j];
+        AES_ecb_encrypt(a,(uchar *)st);
+        for (j=0; j<bytes; j++) buff[j]^=st[j];
+        increment(a->f);
+        return 0;
+
+    default:
+        return 0;
+    }
+}
+
+/* Clean up and delete left-overs */
+void AES_end(amcl_aes *a)
+{
+    /* clean up */
+    int i;
+    for (i=0; i<NB*(a->Nr+1); i++)
+        a->fkey[i]=a->rkey[i]=0;
+    for (i=0; i<4*NB; i++)
+        a->f[i]=0;
+}
+
+
+/*
+#include <stdio.h>
+
+#define KK 32
+
+int main()
+{
+    int i;
+    amcl_aes a;
+	unsign32 t;
+	uchar x,y;
+
+    char key[KK];
+    char block[16];
+    char iv[16];
+    for (i=0;i<KK;i++) key[i]=5;
+    key[0]=1;
+    for (i=0;i<16;i++) iv[i]=i;
+    for (i=0;i<16;i++) block[i]=i;
+
+    AES_init(&a,CTR16,KK,key,iv);
+
+    printf("Plain=   ");
+    for (i=0;i<16;i++) printf("%02x",block[i]);
+    printf("\n");
+    AES_encrypt(&a,block);
+    printf("Encrypt= ");
+    for (i=0;i<16;i++) printf("%02x",(uchar)block[i]);
+    printf("\n");
+    AES_reset(&a,CTR16,iv);
+    AES_decrypt(&a,block);
+    printf("Decrypt= ");
+    for (i=0;i<16;i++) printf("%02x",(uchar)block[i]);
+    printf("\n");
+
+    AES_end(&a);
+
+    return 0;
+}
+
+*/
+
diff --git a/version3/c/amcl.h b/version3/c/amcl.h
new file mode 100644
index 0000000..2558911
--- /dev/null
+++ b/version3/c/amcl.h
@@ -0,0 +1,590 @@
+/*
+	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.
+*/
+
+
+#ifndef AMCL_H
+#define AMCL_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <inttypes.h>
+#include "arch.h"
+
+#ifdef CMAKE
+#define AMCL_VERSION_MAJOR @AMCL_VERSION_MAJOR@ /**< Major version of the library */
+#define AMCL_VERSION_MINOR @AMCL_VERSION_MINOR@ /**< Minor version of the library */
+#define AMCL_VERSION_PATCH @AMCL_VERSION_PATCH@ /**< Patch version of the library */
+#define OS "@OS@"                               /**< Build OS */
+#endif
+
+/* modulus types */
+
+#define NOT_SPECIAL 0	       /**< Modulus of no exploitable form */
+#define PSEUDO_MERSENNE 1      /**< Pseudo-mersenne modulus of form $2^n-c$  */
+#define MONTGOMERY_FRIENDLY 3  /**< Montgomery Friendly modulus of form $2^a(2^b-c)-1$  */
+#define GENERALISED_MERSENNE 2 /**< Generalised-mersenne modulus of form $2^n-2^m-1$, GOLDILOCKS only */
+
+
+/* Curve types */
+
+#define WEIERSTRASS 0 /**< Short Weierstrass form curve  */
+#define EDWARDS 1     /**< Edwards or Twisted Edwards curve  */
+#define MONTGOMERY 2  /**< Montgomery form curve  */
+
+/* Pairing-Friendly types */
+
+#define NOT 0
+#define BN 1
+#define BLS 2
+
+#define D_TYPE 0
+#define M_TYPE 1
+
+/**
+ * @brief SHA256 hash function instance */
+typedef struct
+{
+    unsign32 length[2]; /**< 64-bit input length */
+    unsign32 h[8];      /**< Internal state */
+    unsign32 w[80];	/**< Internal state */
+    int hlen;		/**< Hash length in bytes */
+} hash256;
+
+/**
+ * @brief SHA384-512 hash function instance */
+typedef struct
+{
+    unsign64 length[2]; /**< 64-bit input length */
+    unsign64 h[8];      /**< Internal state */
+    unsign64 w[80];	/**< Internal state */
+    int hlen;           /**< Hash length in bytes */
+} hash512;
+
+/**
+ * @brief SHA384 hash function instance */
+typedef hash512 hash384;
+
+/**
+ * @brief SHA3 hash function instance */
+typedef struct
+{
+    unsign64 length;   /**< 64-bit input length */
+    unsign64 S[5][5];  /**< Internal state */
+    int rate;          /**< TODO */
+    int len;           /**< Hash length in bytes */
+} sha3;
+
+#define SHA256 32 /**< SHA-256 hashing */
+#define SHA384 48 /**< SHA-384 hashing */
+#define SHA512 64 /**< SHA-512 hashing */
+
+#define SHA3_HASH224 28 /**< SHA3 224 bit hash */
+#define SHA3_HASH256 32 /**< SHA3 256 bit hash */
+#define SHA3_HASH384 48 /**< SHA3 384 bit hash */
+#define SHA3_HASH512 64 /**< SHA3 512 bit hash */
+
+#define SHAKE128 16 /**< SHAKE128   hash */
+#define SHAKE256 32 /**< SHAKE256 hash */
+
+
+/* NewHope parameters */
+
+//q= 12289
+
+#define RLWE_PRIME 0x3001	// q in Hex
+#define RLWE_LGN 10			// Degree n=2^LGN
+#define RLWE_ND 0xF7002FFF	// 1/(R-q) mod R
+#define RLWE_ONE 0x2AC8		// R mod q
+#define RLWE_R2MODP 0x1620	// R^2 mod q
+
+/* Symmetric Encryption AES structure */
+
+#define ECB   0  /**< Electronic Code Book */
+#define CBC   1  /**< Cipher Block Chaining */
+#define CFB1  2  /**< Cipher Feedback - 1 byte */
+#define CFB2  3  /**< Cipher Feedback - 2 bytes */
+#define CFB4  5  /**< Cipher Feedback - 4 bytes */
+#define OFB1  14 /**< Output Feedback - 1 byte */
+#define OFB2  15 /**< Output Feedback - 2 bytes */
+#define OFB4  17 /**< Output Feedback - 4 bytes */
+#define OFB8  21 /**< Output Feedback - 8 bytes */
+#define OFB16 29 /**< Output Feedback - 16 bytes */
+#define CTR1  30 /**< Counter Mode - 1 byte */
+#define CTR2  31 /**< Counter Mode - 2 bytes */
+#define CTR4  33 /**< Counter Mode - 4 bytes */
+#define CTR8  37 /**< Counter Mode - 8 bytes */
+#define CTR16 45 /**< Counter Mode - 16 bytes */
+
+#define uchar unsigned char  /**<  Unsigned char */
+
+/**
+	@brief AES instance
+*/
+
+
+typedef struct
+{
+    int Nk;            /**< AES Key Length */
+    int Nr;            /**< AES Number of rounds */
+    int mode;          /**< AES mode of operation */
+    unsign32 fkey[60]; /**< subkeys for encrypton */
+    unsign32 rkey[60]; /**< subkeys for decrypton */
+    char f[16];        /**< buffer for chaining vector */
+} amcl_aes;
+
+/* AES-GCM suppport.  */
+
+#define GCM_ACCEPTING_HEADER 0   /**< GCM status */
+#define GCM_ACCEPTING_CIPHER 1   /**< GCM status */
+#define GCM_NOT_ACCEPTING_MORE 2 /**< GCM status */
+#define GCM_FINISHED 3           /**< GCM status */
+#define GCM_ENCRYPTING 0         /**< GCM mode */
+#define GCM_DECRYPTING 1         /**< GCM mode */
+
+
+/**
+	@brief GCM mode instance, using AES internally
+*/
+
+typedef struct
+{
+    unsign32 table[128][4]; /**< 2k byte table */
+    uchar stateX[16];	    /**< GCM Internal State */
+    uchar Y_0[16];	    /**< GCM Internal State */
+    unsign32 lenA[2];	    /**< GCM 64-bit length of header */
+    unsign32 lenC[2];	    /**< GCM 64-bit length of ciphertext */
+    int status;		    /**< GCM Status */
+    amcl_aes a;		    /**< Internal Instance of AMCL_AES cipher */
+} gcm;
+
+/* Marsaglia & Zaman Random number generator constants */
+
+#define NK   21 /**< PRNG constant */
+#define NJ   6  /**< PRNG constant */
+#define NV   8  /**< PRNG constant */
+
+
+/**
+	@brief Cryptographically secure pseudo-random number generator instance
+*/
+
+typedef struct
+{
+    unsign32 ira[NK]; /**< random number array   */
+    int      rndptr;  /**< pointer into array */
+    unsign32 borrow;  /**<  borrow as a result of subtraction */
+    int pool_ptr;     /**< pointer into random pool */
+    char pool[32];    /**< random pool */
+} csprng;
+
+
+/**
+	@brief Portable representation of a big positive number
+*/
+
+typedef struct
+{
+    int len;   /**< length in bytes  */
+    int max;   /**< max length allowed - enforce truncation  */
+    char *val; /**< byte array  */
+} octet;
+
+
+/* Octet string handlers */
+/**	@brief Formats and outputs an octet to the console in hex
+ *
+	@param O Octet to be output
+ */
+extern void OCT_output(octet *O);
+/**	@brief Formats and outputs an octet to the console as a character string
+ *
+	@param O Octet to be output
+ */
+extern void OCT_output_string(octet *O);
+/**	@brief Wipe clean an octet
+ *
+	@param O Octet to be cleaned
+ */
+extern void OCT_clear(octet *O);
+/**	@brief Compare two octets
+ *
+	@param O first Octet to be compared
+	@param P second Octet to be compared
+	@return 1 if equal, else 0
+ */
+extern int  OCT_comp(octet *O,octet *P);
+/**	@brief Compare first n bytes of two octets
+ *
+	@param O first Octet to be compared
+	@param P second Octet to be compared
+	@param n number of bytes to compare
+	@return 1 if equal, else 0
+ */
+extern int  OCT_ncomp(octet *O,octet *P,int n);
+/**	@brief Join from a C string to end of an octet
+ *
+	Truncates if there is no room
+	@param O Octet to be written to
+	@param s zero terminated string to be joined to octet
+ */
+extern void OCT_jstring(octet *O,char *s);
+/**	@brief Join bytes to end of an octet
+ *
+	Truncates if there is no room
+	@param O Octet to be written to
+	@param s bytes to be joined to end of octet
+	@param n number of bytes to join
+ */
+extern void OCT_jbytes(octet *O,char *s,int n);
+/**	@brief Join single byte to end of an octet, repeated n times
+ *
+	Truncates if there is no room
+	@param O Octet to be written to
+	@param b byte to be joined to end of octet
+	@param n number of times b is to be joined
+ */
+extern void OCT_jbyte(octet *O,int b,int n);
+/**	@brief Join one octet to the end of another
+ *
+	Truncates if there is no room
+	@param O Octet to be written to
+	@param P Octet to be joined to the end of O
+ */
+extern void OCT_joctet(octet *O,octet *P);
+/**	@brief XOR common bytes of a pair of Octets
+ *
+	@param O Octet - on exit = O xor P
+	@param P Octet to be xored into O
+ */
+extern void OCT_xor(octet *O,octet *P);
+/**	@brief reset Octet to zero length
+ *
+	@param O Octet to be emptied
+ */
+extern void OCT_empty(octet *O);
+/**	@brief Pad out an Octet to the given length
+ *
+	Padding is done by inserting leading zeros, so abcd becomes 00abcd
+	@param O Octet to be padded
+	@param n new length of Octet
+ */
+extern int OCT_pad(octet *O,int n);
+/**	@brief Convert an Octet to printable base64 number
+ *
+	@param b zero terminated byte array to take base64 conversion
+	@param O Octet to be converted
+ */
+extern void OCT_tobase64(char *b,octet *O);
+/**	@brief Populate an Octet from base64 number
+ *
+ 	@param O Octet to be populated
+	@param b zero terminated base64 string
+
+ */
+extern void OCT_frombase64(octet *O,char *b);
+/**	@brief Copy one Octet into another
+ *
+ 	@param O Octet to be copied to
+	@param P Octet to be copied from
+
+ */
+extern void OCT_copy(octet *O,octet *P);
+/**	@brief XOR every byte of an octet with input m
+ *
+ 	@param O Octet
+	@param m byte to be XORed with every byte of O
+
+ */
+extern void OCT_xorbyte(octet *O,int m);
+/**	@brief Chops Octet into two, leaving first n bytes in O, moving the rest to P
+ *
+ 	@param O Octet to be chopped
+	@param P new Octet to be created
+	@param n number of bytes to chop off O
+
+ */
+extern void OCT_chop(octet *O,octet *P,int n);
+/**	@brief Join n bytes of integer m to end of Octet O (big endian)
+ *
+	Typically n is 4 for a 32-bit integer
+ 	@param O Octet to be appended to
+	@param m integer to be appended to O
+	@param n number of bytes in m
+
+ */
+extern void OCT_jint(octet *O,int m,int n);
+/**	@brief Create an Octet from bytes taken from a random number generator
+ *
+	Truncates if there is no room
+ 	@param O Octet to be populated
+	@param R an instance of a Cryptographically Secure Random Number Generator
+	@param n number of bytes to extracted from R
+
+ */
+extern void OCT_rand(octet *O,csprng *R,int n);
+/**	@brief Shifts Octet left by n bytes
+ *
+	Leftmost bytes disappear
+ 	@param O Octet to be shifted
+	@param n number of bytes to shift
+
+ */
+extern void OCT_shl(octet *O,int n);
+/**	@brief Convert a hex number to an Octet
+ *
+	@param dst Octet
+	@param src Hex string to be converted
+ */
+extern void OCT_fromHex(octet *dst,char *src);
+/**	@brief Convert an Octet to printable hex number
+ *
+	@param dst hex value
+	@param src Octet to be converted
+ */
+extern void OCT_toHex(octet *src,char *dst);
+/**	@brief Convert an Octet to string
+ *
+	@param dst string value
+	@param src Octet to be converted
+ */
+extern void OCT_toStr(octet *src,char *dst);
+
+
+
+/* Hash function */
+/**	@brief Initialise an instance of SHA256
+ *
+	@param H an instance SHA256
+ */
+extern void HASH256_init(hash256 *H);
+/**	@brief Add a byte to the hash
+ *
+	@param H an instance SHA256
+	@param b byte to be included in hash
+ */
+extern void HASH256_process(hash256 *H,int b);
+/**	@brief Generate 32-byte hash
+ *
+	@param H an instance SHA256
+	@param h is the output 32-byte hash
+ */
+extern void HASH256_hash(hash256 *H,char *h);
+
+
+/**	@brief Initialise an instance of SHA384
+ *
+	@param H an instance SHA384
+ */
+extern void HASH384_init(hash384 *H);
+/**	@brief Add a byte to the hash
+ *
+	@param H an instance SHA384
+	@param b byte to be included in hash
+ */
+extern void HASH384_process(hash384 *H,int b);
+/**	@brief Generate 48-byte hash
+ *
+	@param H an instance SHA384
+	@param h is the output 48-byte hash
+ */
+extern void HASH384_hash(hash384 *H,char *h);
+
+
+/**	@brief Initialise an instance of SHA512
+ *
+	@param H an instance SHA512
+ */
+extern void HASH512_init(hash512 *H);
+/**	@brief Add a byte to the hash
+ *
+	@param H an instance SHA512
+	@param b byte to be included in hash
+ */
+extern void HASH512_process(hash512 *H,int b);
+/**	@brief Generate 64-byte hash
+ *
+	@param H an instance SHA512
+	@param h is the output 64-byte hash
+ */
+extern void HASH512_hash(hash512 *H,char *h);
+
+
+/**	@brief Initialise an instance of SHA3
+ *
+	@param H an instance SHA3
+	@param t the instance type
+ */
+extern void  SHA3_init(sha3 *H,int t);
+/**	@brief process a byte for SHA3
+ *
+	@param H an instance SHA3
+	@param b a byte of date to be processed
+ */
+extern void  SHA3_process(sha3 *H,int b);
+/**	@brief create fixed length hash output of SHA3
+ *
+	@param H an instance SHA3
+	@param h a byte array to take hash
+ */
+extern void  SHA3_hash(sha3 *H,char *h);
+/**	@brief create variable length hash output of SHA3
+ *
+	@param H an instance SHA3
+	@param h a byte array to take hash
+	@param len is the length of the hash
+ */
+extern void  SHA3_shake(sha3 *H,char *h,int len);
+/**	@brief generate further hash output of SHA3
+ *
+	@param H an instance SHA3
+	@param h a byte array to take hash
+	@param len is the length of the hash
+ */
+extern void  SHA3_squeeze(sha3 *H,char *h,int len);
+
+
+
+/* AES functions */
+/**	@brief Reset AES mode or IV
+ *
+	@param A an instance of the AMCL_AES
+	@param m is the new active mode of operation (ECB, CBC, OFB, CFB etc)
+	@param iv the new Initialisation Vector
+ */
+extern void AES_reset(amcl_aes *A,int m,char *iv);
+/**	@brief Extract chaining vector from AMCL_AES instance
+ *
+	@param A an instance of the AMCL_AES
+	@param f the extracted chaining vector
+ */
+extern void AES_getreg(amcl_aes *A,char * f);
+/**	@brief Initialise an instance of AMCL_AES and its mode of operation
+ *
+	@param A an instance AMCL_AES
+	@param m is the active mode of operation (ECB, CBC, OFB, CFB etc)
+	@param n is the key length in bytes, 16, 24 or 32
+	@param k the AES key as an array of 16 bytes
+	@param iv the Initialisation Vector
+	@return 0 for invalid n
+ */
+extern int AES_init(amcl_aes *A,int m,int n,char *k,char *iv);
+/**	@brief Encrypt a single 16 byte block in ECB mode
+ *
+	@param A an instance of the AMCL_AES
+	@param b is an array of 16 plaintext bytes, on exit becomes ciphertext
+ */
+extern void AES_ecb_encrypt(amcl_aes *A,uchar * b);
+/**	@brief Decrypt a single 16 byte block in ECB mode
+ *
+	@param A an instance of the AMCL_AES
+	@param b is an array of 16 cipherext bytes, on exit becomes plaintext
+ */
+extern void AES_ecb_decrypt(amcl_aes *A,uchar * b);
+/**	@brief Encrypt a single 16 byte block in active mode
+ *
+	@param A an instance of the AMCL_AES
+	@param b is an array of 16 plaintext bytes, on exit becomes ciphertext
+	@return 0, or overflow bytes from CFB mode
+ */
+extern unsign32 AES_encrypt(amcl_aes *A,char *b );
+/**	@brief Decrypt a single 16 byte block in active mode
+ *
+	@param A an instance of the AMCL_AES
+	@param b is an array of 16 ciphertext bytes, on exit becomes plaintext
+	@return 0, or overflow bytes from CFB mode
+ */
+extern unsign32 AES_decrypt(amcl_aes *A,char *b);
+/**	@brief Clean up after application of AES
+ *
+	@param A an instance of the AMCL_AES
+ */
+extern void AES_end(amcl_aes *A);
+
+
+/* AES-GCM functions */
+/**	@brief Initialise an instance of AES-GCM mode
+ *
+	@param G an instance AES-GCM
+	@param nk is the key length in bytes, 16, 24 or 32
+	@param k the AES key as an array of 16 bytes
+	@param n the number of bytes in the Initialisation Vector (IV)
+	@param iv the IV
+ */
+extern void GCM_init(gcm *G,int nk,char *k,int n,char *iv);
+/**	@brief Add header (material to be authenticated but not encrypted)
+ *
+	Note that this function can be called any number of times with n a multiple of 16, and then one last time with any value for n
+	@param G an instance AES-GCM
+	@param b is the header material to be added
+	@param n the number of bytes in the header
+ */
+extern int GCM_add_header(gcm *G,char *b,int n);
+/**	@brief Add plaintext and extract ciphertext
+ *
+	Note that this function can be called any number of times with n a multiple of 16, and then one last time with any value for n
+	@param G an instance AES-GCM
+	@param c is the ciphertext generated
+	@param p is the plaintext material to be added
+	@param n the number of bytes in the plaintext
+ */
+extern int GCM_add_plain(gcm *G,char *c,char *p,int n);
+/**	@brief Add ciphertext and extract plaintext
+ *
+	Note that this function can be called any number of times with n a multiple of 16, and then one last time with any value for n
+	@param G an instance AES-GCM
+	@param p is the plaintext generated
+	@param c is the ciphertext material to be added
+	@param n the number of bytes in the ciphertext
+ */
+extern int GCM_add_cipher(gcm *G,char *p,char *c,int n);
+/**	@brief Finish off and extract authentication tag (HMAC)
+ *
+	@param G is an active instance AES-GCM
+	@param t is the output 16 byte authentication tag
+ */
+extern void GCM_finish(gcm *G,char *t);
+
+
+
+/* random numbers */
+/**	@brief Seed a random number generator from an array of bytes
+ *
+	The provided seed should be truly random
+	@param R an instance of a Cryptographically Secure Random Number Generator
+	@param n the number of seed bytes provided
+	@param b an array of seed bytes
+
+ */
+extern void RAND_seed(csprng *R,int n,char *b);
+/**	@brief Delete all internal state of a random number generator
+ *
+	@param R an instance of a Cryptographically Secure Random Number Generator
+ */
+extern void RAND_clean(csprng *R);
+/**	@brief Return a random byte from a random number generator
+ *
+	@param R an instance of a Cryptographically Secure Random Number Generator
+	@return a random byte
+ */
+extern int RAND_byte(csprng *R);
+
+
+
+#endif
diff --git a/version3/c/arch.h b/version3/c/arch.h
new file mode 100644
index 0000000..1de0332
--- /dev/null
+++ b/version3/c/arch.h
@@ -0,0 +1,129 @@
+/*
+	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.
+*/
+
+/* Architecture definition header file */
+
+/**
+ * @file arch.h
+ * @author Mike Scott
+ * @date 23rd February 2016
+ * @brief Architecture Header File
+ *
+ * Specify Processor Architecture
+ *
+ */
+
+/* NOTE: There is only one user configurable section in this header - see below */
+
+#ifndef ARCH_H
+#define ARCH_H
+
+
+
+
+/*** START OF USER CONFIGURABLE SECTION - set architecture ***/
+
+#ifdef CMAKE
+#define CHUNK @AMCL_CHUNK@  /**< size of chunk in bits = wordlength of computer = 16, 32 or 64. Note not all curve options are supported on 16-bit processors - see rom.c */
+#else
+#define CHUNK @WL@		/**< size of chunk in bits = wordlength of computer = 16, 32 or 64. Note not all curve options are supported on 16-bit processors - see rom.c */
+#endif
+
+/*** END OF USER CONFIGURABLE SECTION ***/
+
+/* Create Integer types */
+/* Support for C99?  Note for GCC need to explicitly include -std=c99 in command line */
+
+#if __STDC_VERSION__ >= 199901L
+/* C99 code */
+#define C99
+#else
+/* Not C99 code */
+#endif
+
+#ifndef C99  /* You are on your own! These are for Microsoft C */
+#define byte unsigned char		/**< 8-bit unsigned integer */
+#define sign32 __int32			/**< 32-bit signed integer */
+#define sign8 signed char		/**< 8-bit signed integer */
+#define sign16 short int		/**< 16-bit signed integer */
+#define sign64 long long		/**< 64-bit signed integer */
+#define unsign32 unsigned __int32 /**< 32-bit unsigned integer */
+#define unsign64 unsigned long long  /**< 64-bit unsigned integer */
+#else
+#include <stdint.h>
+#define byte uint8_t			/**< 8-bit unsigned integer */
+#define sign8 int8_t			/**< 8-bit signed integer */
+#define sign16 int16_t			/**< 16-bit signed integer */
+#define sign32 int32_t			/**< 32-bit signed integer */
+#define sign64 int64_t			/**< 64-bit signed integer */
+#define unsign32 uint32_t		/**< 32-bit unsigned integer */
+#define unsign64 uint64_t		/**< 64-bit unsigned integer */
+#endif
+
+#define uchar unsigned char  /**<  Unsigned char */
+
+/* Don't mess with anything below this line unless you know what you are doing */
+/* This next is probably OK, but may need changing for non-C99-standard environments */
+
+/* This next is probably OK, but may need changing for non-C99-standard environments */
+
+#if CHUNK==16
+#ifndef C99
+#define chunk __int16		/**< C type corresponding to word length */
+#define dchunk __int32		/**< Always define double length chunk type if available */
+#else
+#define chunk int16_t		/**< C type corresponding to word length */
+#define dchunk int32_t		/**< Always define double length chunk type if available */
+#endif
+#endif
+
+#if CHUNK == 32
+#ifndef C99
+#define chunk __int32		/**< C type corresponding to word length */
+#define dchunk __int64		/**< Always define double length chunk type if available */
+#else
+#define chunk int32_t		/**< C type corresponding to word length */
+#define dchunk int64_t		/**< Always define double length chunk type if available */
+#endif
+#endif
+
+#if CHUNK == 64
+
+#ifndef C99
+#define chunk __int64		/**< C type corresponding to word length */
+/**< Note - no 128-bit type available    */
+#else
+#define chunk int64_t		/**< C type corresponding to word length */
+#ifdef __GNUC__
+#define dchunk __int128		/**< Always define double length chunk type if available - GCC supports 128 bit type  ??? */
+#endif
+
+#ifdef __clang__
+#define dchunk __int128
+#endif
+
+#endif
+#endif
+
+#ifdef dchunk
+#define COMBA      /**< Use COMBA method for faster muls, sqrs and reductions */
+#endif
+
+
+#endif
diff --git a/version3/c/benchtest_all.c b/version3/c/benchtest_all.c
new file mode 100644
index 0000000..0acc6dd
--- /dev/null
+++ b/version3/c/benchtest_all.c
@@ -0,0 +1,1019 @@
+/* Test and benchmark elliptic curve and RSA functions
+	First build amcl.a from build_ec batch file
+	gcc -O3 benchtest_ec.c amcl.a -o benchtest_ec.exe
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "rsa_2048.h"
+#include "ecp_ED25519.h"
+#include "pair_BN254.h"
+
+
+#if CHUNK==32 || CHUNK==64
+#include "ecp_NIST256.h"
+#include "ecp_GOLDILOCKS.h"
+#include "pair_BLS383.h"
+#include "pair192_BLS24.h"
+#include "pair256_BLS48.h"
+#endif
+
+#define MIN_TIME 10.0
+#define MIN_ITERS 10 
+
+#if CHUNK==16
+
+#define BIG_ED BIG_256_13
+#define BIG_ED_rcopy BIG_256_13_rcopy
+#define BIG_ED_randomnum BIG_256_13_randomnum 
+
+#define BIG_BN BIG_256_13
+#define BIG_BN_rcopy BIG_256_13_rcopy
+#define BIG_BN_randomnum BIG_256_13_randomnum 
+
+#endif
+
+#if CHUNK==32
+
+#define BIG_ED BIG_256_29
+#define BIG_ED_rcopy BIG_256_29_rcopy
+#define BIG_ED_randomnum BIG_256_29_randomnum 
+
+#define BIG_NT BIG_256_28
+#define BIG_NT_rcopy BIG_256_28_rcopy
+#define BIG_NT_randomnum BIG_256_28_randomnum
+
+#define BIG_GL BIG_448_29
+#define BIG_GL_rcopy BIG_448_29_rcopy
+#define BIG_GL_randomnum BIG_448_29_randomnum 
+
+#define BIG_BN BIG_256_28
+#define BIG_BN_rcopy BIG_256_28_rcopy
+#define BIG_BN_randomnum BIG_256_28_randomnum 
+
+#define BIG_BLS12 BIG_384_29
+#define BIG_BLS12_rcopy BIG_384_29_rcopy
+#define BIG_BLS12_randomnum BIG_384_29_randomnum 
+
+#define BIG_BLS24 BIG_480_29
+#define BIG_BLS24_rcopy BIG_480_29_rcopy
+#define BIG_BLS24_randomnum BIG_480_29_randomnum 
+
+#define BIG_BLS48 BIG_560_29
+#define BIG_BLS48_rcopy BIG_560_29_rcopy
+#define BIG_BLS48_randomnum BIG_560_29_randomnum 
+
+#endif
+
+#if CHUNK==64
+
+#define BIG_ED BIG_256_56
+#define BIG_ED_rcopy BIG_256_56_rcopy
+#define BIG_ED_randomnum BIG_256_56_randomnum 
+
+#define BIG_NT BIG_256_56
+#define BIG_NT_rcopy BIG_256_56_rcopy
+#define BIG_NT_randomnum BIG_256_56_randomnum
+
+#define BIG_GL BIG_448_58
+#define BIG_GL_rcopy BIG_448_58_rcopy
+#define BIG_GL_randomnum BIG_448_58_randomnum 
+
+#define BIG_BN BIG_256_56
+#define BIG_BN_rcopy BIG_256_56_rcopy
+#define BIG_BN_randomnum BIG_256_56_randomnum 
+
+#define BIG_BLS12 BIG_384_58
+#define BIG_BLS12_rcopy BIG_384_58_rcopy
+#define BIG_BLS12_randomnum BIG_384_58_randomnum 
+
+#define BIG_BLS24 BIG_480_56
+#define BIG_BLS24_rcopy BIG_480_56_rcopy
+#define BIG_BLS24_randomnum BIG_480_56_randomnum 
+
+#define BIG_BLS48 BIG_560_58
+#define BIG_BLS48_rcopy BIG_560_58_rcopy
+#define BIG_BLS48_randomnum BIG_560_58_randomnum 
+
+#endif
+
+int ED_25519(csprng *RNG)
+{
+    int i,iterations;
+    clock_t start;
+    double elapsed;
+	ECP_ED25519 EP,EG;
+	BIG_ED s,r,x,y;
+	printf("Testing/Timing ED25519 ECC\n");
+
+#if CURVETYPE_ED25519==WEIERSTRASS
+	printf("Weierstrass parameterization\n");
+#endif
+#if CURVETYPE_ED25519==EDWARDS
+	printf("Edwards parameterization\n");
+#endif
+#if CURVETYPE_ED25519==MONTGOMERY
+	printf("Montgomery parameterization\n");
+#endif
+
+#if CHUNK==16
+	printf("16-bit Build\n");
+#endif
+#if CHUNK==32
+	printf("32-bit Build\n");
+#endif
+#if CHUNK==64
+	printf("64-bit Build\n");
+#endif
+	
+	ECP_ED25519_generator(&EG);
+
+	BIG_ED_rcopy(r,CURVE_Order_ED25519);
+	BIG_ED_randomnum(s,r,RNG);
+	ECP_ED25519_copy(&EP,&EG);
+    ECP_ED25519_mul(&EP,r);
+
+	if (!ECP_ED25519_isinf(&EP))
+	{
+		printf("FAILURE - rG!=O\n");
+		return 0;
+	}
+
+	iterations=0;
+    start=clock();
+    do {
+		ECP_ED25519_copy(&EP,&EG);
+		ECP_ED25519_mul(&EP,s);
+
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("EC  mul - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	return 0;
+}
+
+#if CHUNK==32 || CHUNK==64
+
+int NIST_256(csprng *RNG)
+{
+    int i,iterations;
+    clock_t start;
+    double elapsed;
+	ECP_NIST256 EP,EG;
+	BIG_NT s,r,x,y;
+	printf("Testing/Timing NIST256 ECC\n");
+
+#if CURVETYPE_NIST256==WEIERSTRASS
+	printf("Weierstrass parameterization\n");
+#endif
+#if CURVETYPE_NIST256==EDWARDS
+	printf("Edwards parameterization\n");
+#endif
+#if CURVETYPE_NIST256==MONTGOMERY
+	printf("Montgomery parameterization\n");
+#endif
+
+#if CHUNK==16
+	printf("16-bit Build\n");
+#endif
+#if CHUNK==32
+	printf("32-bit Build\n");
+#endif
+#if CHUNK==64
+	printf("64-bit Build\n");
+#endif
+	
+	ECP_NIST256_generator(&EG);
+
+	BIG_NT_rcopy(r,CURVE_Order_NIST256);
+	BIG_NT_randomnum(s,r,RNG);
+	ECP_NIST256_copy(&EP,&EG);
+    ECP_NIST256_mul(&EP,r);
+
+	if (!ECP_NIST256_isinf(&EP))
+	{
+		printf("FAILURE - rG!=O\n");
+		return 0;
+	}
+
+	iterations=0;
+    start=clock();
+    do {
+		ECP_NIST256_copy(&EP,&EG);
+		ECP_NIST256_mul(&EP,s);
+
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("EC  mul - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	return 0;
+}
+
+int GOLD_LOCKS(csprng *RNG)
+{
+    int i,iterations;
+    clock_t start;
+    double elapsed;
+	ECP_GOLDILOCKS EP,EG;
+	BIG_GL s,r,x,y;
+	printf("Testing/Timing GOLDILOCKS ECC\n");
+
+#if CURVETYPE_GOLDILOCKS==WEIERSTRASS
+	printf("Weierstrass parameterization\n");
+#endif
+#if CURVETYPE_GOLDILOCKS==EDWARDS
+	printf("Edwards parameterization\n");
+#endif
+#if CURVETYPE_GOLDILOCKS==MONTGOMERY
+	printf("Montgomery parameterization\n");
+#endif
+
+#if CHUNK==16
+	printf("16-bit Build\n");
+#endif
+#if CHUNK==32
+	printf("32-bit Build\n");
+#endif
+#if CHUNK==64
+	printf("64-bit Build\n");
+#endif
+	
+	ECP_GOLDILOCKS_generator(&EG);
+
+	BIG_GL_rcopy(r,CURVE_Order_GOLDILOCKS);
+	BIG_GL_randomnum(s,r,RNG);
+	ECP_GOLDILOCKS_copy(&EP,&EG);
+    ECP_GOLDILOCKS_mul(&EP,r);
+
+	if (!ECP_GOLDILOCKS_isinf(&EP))
+	{
+		printf("FAILURE - rG!=O\n");
+		return 0;
+	}
+
+	iterations=0;
+    start=clock();
+    do {
+		ECP_GOLDILOCKS_copy(&EP,&EG);
+		ECP_GOLDILOCKS_mul(&EP,s);
+
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("EC  mul - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	return 0;
+}
+#endif
+
+int BN_254(csprng *RNG)
+{
+    int i,iterations;
+    clock_t start;
+    double elapsed;
+
+	ECP_BN254 P,G;
+	ECP2_BN254 Q,W;
+	FP12_BN254 g,w;
+	FP4_BN254 cm;
+
+	BIG_BN s,r,x,y;
+	printf("\nTesting/Timing BN254 Pairings\n");
+
+	ECP_BN254_generator(&G);
+
+	
+	BIG_BN_rcopy(r,CURVE_Order_BN254);
+	BIG_BN_randomnum(s,r,RNG);
+	ECP_BN254_copy(&P,&G);
+    PAIR_BN254_G1mul(&P,r);
+
+	if (!ECP_BN254_isinf(&P))
+	{
+		printf("FAILURE - rG!=O\n");
+		return 0;
+	}
+	
+	iterations=0;
+    start=clock();
+    do {
+		ECP_BN254_copy(&P,&G);
+		PAIR_BN254_G1mul(&P,s);
+
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("G1 mul              - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	ECP2_BN254_generator(&W);
+
+	ECP2_BN254_copy(&Q,&W);
+    ECP2_BN254_mul(&Q,r);
+
+	if (!ECP2_BN254_isinf(&Q))
+	{
+		printf("FAILURE - rQ!=O\n");
+		return 0;
+	}
+
+	iterations=0;
+    start=clock();
+    do {
+		ECP2_BN254_copy(&Q,&W);
+		PAIR_BN254_G2mul(&Q,s);
+
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("G2 mul              - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	PAIR_BN254_ate(&w,&Q,&P);
+	PAIR_BN254_fexp(&w);
+
+	FP12_BN254_copy(&g,&w);
+
+	PAIR_BN254_GTpow(&g,r);
+
+	if (!FP12_BN254_isunity(&g))
+	{
+		printf("FAILURE - g^r!=1\n");
+		return 0;
+	}
+
+	iterations=0;
+    start=clock();
+    do {
+		FP12_BN254_copy(&g,&w);
+		PAIR_BN254_GTpow(&g,s);
+
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("GT pow              - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	FP12_BN254_copy(&g,&w);
+
+	iterations=0;
+    start=clock();
+    do {
+		FP12_BN254_compow(&cm,&g,s,r);
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("GT pow (compressed) - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	iterations=0;
+    start=clock();
+    do {
+		PAIR_BN254_ate(&w,&Q,&P);
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("PAIRing ATE         - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	iterations=0;
+    start=clock();
+    do {
+		FP12_BN254_copy(&g,&w);
+		PAIR_BN254_fexp(&g);
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("PAIRing FEXP        - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	ECP_BN254_copy(&P,&G);	
+	ECP2_BN254_copy(&Q,&W);
+
+	PAIR_BN254_G1mul(&P,s);
+	PAIR_BN254_ate(&g,&Q,&P);
+	PAIR_BN254_fexp(&g);
+
+	ECP_BN254_copy(&P,&G);
+
+	PAIR_BN254_G2mul(&Q,s);
+	PAIR_BN254_ate(&w,&Q,&P);
+	PAIR_BN254_fexp(&w);
+
+	if (!FP12_BN254_equals(&g,&w))
+	{
+		printf("FAILURE - e(sQ,p)!=e(Q,sP) \n");
+		return 0;
+	}
+
+	ECP2_BN254_copy(&Q,&W);
+	PAIR_BN254_ate(&g,&Q,&P);
+	PAIR_BN254_fexp(&g);
+
+	PAIR_BN254_GTpow(&g,s);
+
+	if (!FP12_BN254_equals(&g,&w))
+	{
+		printf("FAILURE - e(sQ,p)!=e(Q,P)^s \n");
+		return 0;
+	}
+	return 0;
+}
+
+#if CHUNK==32 || CHUNK==64
+
+int BLS_383(csprng *RNG)
+{
+    int i,iterations;
+    clock_t start;
+    double elapsed;
+
+	ECP_BLS383 P,G;
+	ECP2_BLS383 Q,W;
+	FP12_BLS383 g,w;
+	FP4_BLS383 cm;
+
+	BIG_BLS12 s,r,x,y;
+	printf("\nTesting/Timing BLS383 Pairings\n");
+
+	ECP_BLS383_generator(&G);
+
+	
+	BIG_BLS12_rcopy(r,CURVE_Order_BLS383);
+	BIG_BLS12_randomnum(s,r,RNG);
+	ECP_BLS383_copy(&P,&G);
+    PAIR_BLS383_G1mul(&P,r);
+
+	if (!ECP_BLS383_isinf(&P))
+	{
+		printf("FAILURE - rG!=O\n");
+		return 0;
+	}
+	
+	iterations=0;
+    start=clock();
+    do {
+		ECP_BLS383_copy(&P,&G);
+		PAIR_BLS383_G1mul(&P,s);
+
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("G1 mul              - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	ECP2_BLS383_generator(&W);
+
+	ECP2_BLS383_copy(&Q,&W);
+    ECP2_BLS383_mul(&Q,r);
+
+	if (!ECP2_BLS383_isinf(&Q))
+	{
+		printf("FAILURE - rQ!=O\n");
+		return 0;
+	}
+
+	iterations=0;
+    start=clock();
+    do {
+		ECP2_BLS383_copy(&Q,&W);
+		PAIR_BLS383_G2mul(&Q,s);
+
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("G2 mul              - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	PAIR_BLS383_ate(&w,&Q,&P);
+	PAIR_BLS383_fexp(&w);
+
+	FP12_BLS383_copy(&g,&w);
+
+	PAIR_BLS383_GTpow(&g,r);
+
+	if (!FP12_BLS383_isunity(&g))
+	{
+		printf("FAILURE - g^r!=1\n");
+		return 0;
+	}
+
+	iterations=0;
+    start=clock();
+    do {
+		FP12_BLS383_copy(&g,&w);
+		PAIR_BLS383_GTpow(&g,s);
+
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("GT pow              - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	FP12_BLS383_copy(&g,&w);
+
+	iterations=0;
+    start=clock();
+    do {
+		FP12_BLS383_compow(&cm,&g,s,r);
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("GT pow (compressed) - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	iterations=0;
+    start=clock();
+    do {
+		PAIR_BLS383_ate(&w,&Q,&P);
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("PAIRing ATE         - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	iterations=0;
+    start=clock();
+    do {
+		FP12_BLS383_copy(&g,&w);
+		PAIR_BLS383_fexp(&g);
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("PAIRing FEXP        - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	ECP_BLS383_copy(&P,&G);	
+	ECP2_BLS383_copy(&Q,&W);
+
+	PAIR_BLS383_G1mul(&P,s);
+	PAIR_BLS383_ate(&g,&Q,&P);
+	PAIR_BLS383_fexp(&g);
+
+	ECP_BLS383_copy(&P,&G);
+
+	PAIR_BLS383_G2mul(&Q,s);
+	PAIR_BLS383_ate(&w,&Q,&P);
+	PAIR_BLS383_fexp(&w);
+
+	if (!FP12_BLS383_equals(&g,&w))
+	{
+		printf("FAILURE - e(sQ,p)!=e(Q,sP) \n");
+		return 0;
+	}
+
+	ECP2_BLS383_copy(&Q,&W);
+	PAIR_BLS383_ate(&g,&Q,&P);
+	PAIR_BLS383_fexp(&g);
+
+	PAIR_BLS383_GTpow(&g,s);
+
+	if (!FP12_BLS383_equals(&g,&w))
+	{
+		printf("FAILURE - e(sQ,p)!=e(Q,P)^s \n");
+		return 0;
+	}
+	return 0;
+}
+
+int BLS_24(csprng *RNG)
+{
+    int i,iterations;
+    clock_t start;
+    double elapsed;
+
+	ECP_BLS24 P,G;
+	ECP4_BLS24 Q,W;
+	FP24_BLS24 g,w;
+	FP8_BLS24 cm;
+
+	BIG_BLS24 s,r,x,y;
+	printf("\nTesting/Timing BLS24 Pairings\n");
+
+	ECP_BLS24_generator(&G);
+
+	
+	BIG_BLS24_rcopy(r,CURVE_Order_BLS24);
+	BIG_BLS24_randomnum(s,r,RNG);
+	ECP_BLS24_copy(&P,&G);
+    PAIR_BLS24_G1mul(&P,r);
+
+	if (!ECP_BLS24_isinf(&P))
+	{
+		printf("FAILURE - rG!=O\n");
+		return 0;
+	}
+	
+	iterations=0;
+    start=clock();
+    do {
+		ECP_BLS24_copy(&P,&G);
+		PAIR_BLS24_G1mul(&P,s);
+
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("G1 mul              - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	ECP4_BLS24_generator(&W);
+
+	ECP4_BLS24_copy(&Q,&W);
+    ECP4_BLS24_mul(&Q,r);
+
+	if (!ECP4_BLS24_isinf(&Q))
+	{
+		printf("FAILURE - rQ!=O\n");
+		return 0;
+	}
+
+	iterations=0;
+    start=clock();
+    do {
+		ECP4_BLS24_copy(&Q,&W);
+		PAIR_BLS24_G2mul(&Q,s);
+
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("G2 mul              - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	PAIR_BLS24_ate(&w,&Q,&P);
+	PAIR_BLS24_fexp(&w);
+
+	FP24_BLS24_copy(&g,&w);
+
+	PAIR_BLS24_GTpow(&g,r);
+
+	if (!FP24_BLS24_isunity(&g))
+	{
+		printf("FAILURE - g^r!=1\n");
+		return 0;
+	}
+
+	iterations=0;
+    start=clock();
+    do {
+		FP24_BLS24_copy(&g,&w);
+		PAIR_BLS24_GTpow(&g,s);
+
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("GT pow              - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	FP24_BLS24_copy(&g,&w);
+
+	iterations=0;
+    start=clock();
+    do {
+		FP24_BLS24_compow(&cm,&g,s,r);
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("GT pow (compressed) - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	iterations=0;
+    start=clock();
+    do {
+		PAIR_BLS24_ate(&w,&Q,&P);
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("PAIRing ATE         - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	iterations=0;
+    start=clock();
+    do {
+		FP24_BLS24_copy(&g,&w);
+		PAIR_BLS24_fexp(&g);
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("PAIRing FEXP        - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	ECP_BLS24_copy(&P,&G);	
+	ECP4_BLS24_copy(&Q,&W);
+
+	PAIR_BLS24_G1mul(&P,s);
+	PAIR_BLS24_ate(&g,&Q,&P);
+	PAIR_BLS24_fexp(&g);
+
+	ECP_BLS24_copy(&P,&G);
+
+	PAIR_BLS24_G2mul(&Q,s);
+	PAIR_BLS24_ate(&w,&Q,&P);
+	PAIR_BLS24_fexp(&w);
+
+	if (!FP24_BLS24_equals(&g,&w))
+	{
+		printf("FAILURE - e(sQ,p)!=e(Q,sP) \n");
+		return 0;
+	}
+
+	ECP4_BLS24_copy(&Q,&W);
+	PAIR_BLS24_ate(&g,&Q,&P);
+	PAIR_BLS24_fexp(&g);
+
+	PAIR_BLS24_GTpow(&g,s);
+
+	if (!FP24_BLS24_equals(&g,&w))
+	{
+		printf("FAILURE - e(sQ,p)!=e(Q,P)^s \n");
+		return 0;
+	}
+	return 0;
+}
+
+
+int BLS_48(csprng *RNG)
+{
+    int i,iterations;
+    clock_t start;
+    double elapsed;
+
+	ECP_BLS48 P,G;
+	ECP8_BLS48 Q,W;
+	FP48_BLS48 g,w;
+	FP16_BLS48 cm;
+
+	BIG_BLS48 s,r,x,y;
+	printf("\nTesting/Timing BLS48 Pairings\n");
+
+	ECP_BLS48_generator(&G);
+
+	
+	BIG_BLS48_rcopy(r,CURVE_Order_BLS48);
+	BIG_BLS48_randomnum(s,r,RNG);
+	ECP_BLS48_copy(&P,&G);
+    PAIR_BLS48_G1mul(&P,r);
+
+	if (!ECP_BLS48_isinf(&P))
+	{
+		printf("FAILURE - rG!=O\n");
+		return 0;
+	}
+	
+	iterations=0;
+    start=clock();
+    do {
+		ECP_BLS48_copy(&P,&G);
+		PAIR_BLS48_G1mul(&P,s);
+
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("G1 mul              - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	ECP8_BLS48_generator(&W);
+
+	ECP8_BLS48_copy(&Q,&W);
+    ECP8_BLS48_mul(&Q,r);
+
+	if (!ECP8_BLS48_isinf(&Q))
+	{
+		printf("FAILURE - rQ!=O\n");
+		return 0;
+	}
+
+	iterations=0;
+    start=clock();
+    do {
+		ECP8_BLS48_copy(&Q,&W);
+		PAIR_BLS48_G2mul(&Q,s);
+
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("G2 mul              - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	PAIR_BLS48_ate(&w,&Q,&P);
+	PAIR_BLS48_fexp(&w);
+
+	FP48_BLS48_copy(&g,&w);
+
+	PAIR_BLS48_GTpow(&g,r);
+
+	if (!FP48_BLS48_isunity(&g))
+	{
+		printf("FAILURE - g^r!=1\n");
+		return 0;
+	}
+
+	iterations=0;
+    start=clock();
+    do {
+		FP48_BLS48_copy(&g,&w);
+		PAIR_BLS48_GTpow(&g,s);
+
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("GT pow              - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	FP48_BLS48_copy(&g,&w);
+
+	iterations=0;
+    start=clock();
+    do {
+		FP48_BLS48_compow(&cm,&g,s,r);
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("GT pow (compressed) - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	iterations=0;
+    start=clock();
+    do {
+		PAIR_BLS48_ate(&w,&Q,&P);
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("PAIRing ATE         - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	iterations=0;
+    start=clock();
+    do {
+		FP48_BLS48_copy(&g,&w);
+		PAIR_BLS48_fexp(&g);
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("PAIRing FEXP        - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	ECP_BLS48_copy(&P,&G);	
+	ECP8_BLS48_copy(&Q,&W);
+
+	PAIR_BLS48_G1mul(&P,s);
+	PAIR_BLS48_ate(&g,&Q,&P);
+	PAIR_BLS48_fexp(&g);
+
+	ECP_BLS48_copy(&P,&G);
+
+	PAIR_BLS48_G2mul(&Q,s);
+	PAIR_BLS48_ate(&w,&Q,&P);
+	PAIR_BLS48_fexp(&w);
+
+	if (!FP48_BLS48_equals(&g,&w))
+	{
+		printf("FAILURE - e(sQ,p)!=e(Q,sP) \n");
+		return 0;
+	}
+
+	ECP8_BLS48_copy(&Q,&W);
+	PAIR_BLS48_ate(&g,&Q,&P);
+	PAIR_BLS48_fexp(&g);
+
+	PAIR_BLS48_GTpow(&g,s);
+
+	if (!FP48_BLS48_equals(&g,&w))
+	{
+		printf("FAILURE - e(sQ,p)!=e(Q,P)^s \n");
+		return 0;
+	}
+	return 0;
+}
+#endif
+
+int RSA_2048(csprng *RNG)
+{
+    rsa_public_key_2048 pub;
+    rsa_private_key_2048 priv;
+
+    int i,iterations;
+    clock_t start;
+    double elapsed;
+
+    char m[RFS_2048],d[RFS_2048],c[RFS_2048];
+    octet M= {0,sizeof(m),m};
+    octet D= {0,sizeof(d),d};
+    octet C= {0,sizeof(c),c};
+
+	printf("\nTesting/Timing 2048-bit RSA\n");
+
+	printf("Generating 2048-bit RSA public/private key pair\n");
+
+	iterations=0;
+    start=clock();
+    do {
+		RSA_2048_KEY_PAIR(RNG,65537,&priv,&pub,NULL,NULL);
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("RSA gen - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	M.len=RFS_2048;
+	for (i=0;i<RFS_2048;i++) M.val[i]=i%128;
+
+	iterations=0;
+    start=clock();
+    do {
+		RSA_2048_ENCRYPT(&pub,&M,&C);
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("RSA enc - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	iterations=0;
+    start=clock();
+    do {
+		RSA_2048_DECRYPT(&priv,&C,&D);
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("RSA dec - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	for (i=0;i<RFS_2048;i++)
+	{
+		if (M.val[i]!=D.val[i])
+		{
+			printf("FAILURE - RSA decryption\n");
+			return 0;
+		}
+	}
+
+	printf("All tests pass\n");
+
+	return 0;
+}
+
+int main()
+{
+    csprng RNG;
+	int i;
+	char pr[10];
+	unsigned long ran;
+
+	time((time_t *)&ran);
+	pr[0]=ran;
+	pr[1]=ran>>8;
+	pr[2]=ran>>16;
+	pr[3]=ran>>24;
+	for (i=4;i<10;i++) pr[i]=i;
+    RAND_seed(&RNG,10,pr);
+
+	ED_25519(&RNG);
+#if CHUNK==32 || CHUNK==64	
+	NIST_256(&RNG);
+	GOLD_LOCKS(&RNG);
+#endif	
+	BN_254(&RNG);
+#if CHUNK==32 || CHUNK==64	
+	BLS_383(&RNG);
+	BLS_24(&RNG);
+	BLS_48(&RNG);
+#endif	
+	RSA_2048(&RNG);
+	
+}
diff --git a/version3/c/big.c b/version3/c/big.c
new file mode 100644
index 0000000..6845c6b
--- /dev/null
+++ b/version3/c/big.c
@@ -0,0 +1,1535 @@
+/*
+	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.
+*/
+
+/* AMCL basic functions for BIG type */
+/* SU=m, SU is Stack Usage */
+
+#include "big_XXX.h"
+
+/* test a=0? */
+int BIG_XXX_iszilch(BIG_XXX a)
+{
+    int i;
+    for (i=0; i<NLEN_XXX; i++)
+        if (a[i]!=0) return 0;
+    return 1;
+}
+
+/* test a=1? */
+int BIG_XXX_isunity(BIG_XXX a)
+{
+    int i;
+    for(i=1; i<NLEN_XXX; i++)
+        if (a[i]!=0) return 0;
+    if (a[0]!=1) return 0;
+    return 1;
+}
+
+/* test a=0? */
+int BIG_XXX_diszilch(DBIG_XXX a)
+{
+    int i;
+    for (i=0; i<DNLEN_XXX; i++)
+        if (a[i]!=0) return 0;
+    return 1;
+}
+
+/* SU= 56 */
+/* output a */
+void BIG_XXX_output(BIG_XXX a)
+{
+    BIG_XXX b;
+    int i,len;
+    len=BIG_XXX_nbits(a);
+    if (len%4==0) len/=4;
+    else
+    {
+        len/=4;
+        len++;
+    }
+    if (len<MODBYTES_XXX*2) len=MODBYTES_XXX*2;
+
+    for (i=len-1; i>=0; i--)
+    {
+        BIG_XXX_copy(b,a);
+        BIG_XXX_shr(b,i*4);
+        printf("%01x",(unsigned int) b[0]&15);
+    }
+}
+
+/* SU= 16 */
+void BIG_XXX_rawoutput(BIG_XXX a)
+{
+    int i;
+    printf("(");
+    for (i=0; i<NLEN_XXX-1; i++)
+#if CHUNK==64
+        printf("%"PRIxMAX",",(uintmax_t) a[i]);
+    printf("%"PRIxMAX")",(uintmax_t) a[NLEN_XXX-1]);
+#else
+        printf("%x,",(unsigned int) a[i]);
+    printf("%x)",(unsigned int) a[NLEN_XXX-1]);
+#endif
+}
+
+/* Swap a and b if d=1 */
+void BIG_XXX_cswap(BIG_XXX a,BIG_XXX b,int d)
+{
+    int i;
+    chunk t,c=d;
+    c=~(c-1);
+#ifdef DEBUG_NORM
+    for (i=0; i<NLEN_XXX+2; i++)
+#else
+    for (i=0; i<NLEN_XXX; i++)
+#endif
+    {
+        t=c&(a[i]^b[i]);
+        a[i]^=t;
+        b[i]^=t;
+    }
+}
+
+/* Move b to a if d=1 */
+void BIG_XXX_cmove(BIG_XXX f,BIG_XXX g,int d)
+{
+    int i;
+    chunk b=(chunk)-d;
+#ifdef DEBUG_NORM
+    for (i=0; i<NLEN_XXX+2; i++)
+#else
+    for (i=0; i<NLEN_XXX; i++)
+#endif
+    {
+        f[i]^=(f[i]^g[i])&b;
+    }
+}
+
+/* Move g to f if d=1 */
+void BIG_XXX_dcmove(DBIG_XXX f,DBIG_XXX g,int d)
+{
+    int i;
+    chunk b=(chunk)-d;
+#ifdef DEBUG_NORM
+    for (i=0; i<DNLEN_XXX+2; i++)
+#else
+    for (i=0; i<DNLEN_XXX; i++)
+#endif
+    {
+        f[i]^=(f[i]^g[i])&b;
+    }
+}
+
+/* convert BIG to/from bytes */
+/* SU= 64 */
+void BIG_XXX_toBytes(char *b,BIG_XXX a)
+{
+    int i;
+    BIG_XXX c;
+    BIG_XXX_copy(c,a);
+	BIG_XXX_norm(c);
+    for (i=MODBYTES_XXX-1; i>=0; i--)
+    {
+        b[i]=c[0]&0xff;
+        BIG_XXX_fshr(c,8);
+    }
+}
+
+/* SU= 16 */
+void BIG_XXX_fromBytes(BIG_XXX a,char *b)
+{
+    int i;
+    BIG_XXX_zero(a);
+    for (i=0; i<MODBYTES_XXX; i++)
+    {
+        BIG_XXX_fshl(a,8);
+        a[0]+=(int)(unsigned char)b[i];
+        //BIG_XXX_inc(a,(int)(unsigned char)b[i]); BIG_XXX_norm(a);
+    }
+#ifdef DEBUG_NORM
+    a[MPV_XXX]=1;
+    a[MNV_XXX]=0;
+#endif
+}
+
+void BIG_XXX_fromBytesLen(BIG_XXX a,char *b,int s)
+{
+    int i,len=s;
+    BIG_XXX_zero(a);
+
+    if (len>MODBYTES_XXX) len=MODBYTES_XXX;
+    for (i=0; i<len; i++)
+    {
+        BIG_XXX_fshl(a,8);
+        a[0]+=(int)(unsigned char)b[i];
+    }
+#ifdef DEBUG_NORM
+    a[MPV_XXX]=1;
+    a[MNV_XXX]=0;
+#endif
+}
+
+
+
+/* SU= 88 */
+void BIG_XXX_doutput(DBIG_XXX a)
+{
+    DBIG_XXX b;
+    int i,len;
+    BIG_XXX_dnorm(a);
+    len=BIG_XXX_dnbits(a);
+    if (len%4==0) len/=4;
+    else
+    {
+        len/=4;
+        len++;
+    }
+
+    for (i=len-1; i>=0; i--)
+    {
+        BIG_XXX_dcopy(b,a);
+        BIG_XXX_dshr(b,i*4);
+        printf("%01x",(unsigned int) b[0]&15);
+    }
+}
+
+
+void BIG_XXX_drawoutput(DBIG_XXX a)
+{
+    int i;
+    printf("(");
+    for (i=0; i<DNLEN_XXX-1; i++)
+#if CHUNK==64
+        printf("%"PRIxMAX",",(uintmax_t) a[i]);
+    printf("%"PRIxMAX")",(uintmax_t) a[DNLEN_XXX-1]);
+#else
+        printf("%x,",(unsigned int) a[i]);
+    printf("%x)",(unsigned int) a[DNLEN_XXX-1]);
+#endif
+}
+
+/* Copy b=a */
+void BIG_XXX_copy(BIG_XXX b,BIG_XXX a)
+{
+    int i;
+    for (i=0; i<NLEN_XXX; i++)
+        b[i]=a[i];
+#ifdef DEBUG_NORM
+    b[MPV_XXX]=a[MPV_XXX];
+    b[MNV_XXX]=a[MNV_XXX];
+#endif
+}
+
+/* Copy from ROM b=a */
+void BIG_XXX_rcopy(BIG_XXX b,const BIG_XXX a)
+{
+    int i;
+    for (i=0; i<NLEN_XXX; i++)
+        b[i]=a[i];
+#ifdef DEBUG_NORM
+    b[MPV_XXX]=1;
+    b[MNV_XXX]=0;
+#endif
+}
+
+/* double length DBIG copy b=a */
+void BIG_XXX_dcopy(DBIG_XXX b,DBIG_XXX a)
+{
+    int i;
+    for (i=0; i<DNLEN_XXX; i++)
+        b[i]=a[i];
+#ifdef DEBUG_NORM
+    b[DMPV_XXX]=a[DMPV_XXX];
+    b[DMNV_XXX]=a[DMNV_XXX];
+#endif
+}
+
+/* Copy BIG to bottom half of DBIG */
+void BIG_XXX_dscopy(DBIG_XXX b,BIG_XXX a)
+{
+    int i;
+    for (i=0; i<NLEN_XXX-1; i++)
+        b[i]=a[i];
+
+    b[NLEN_XXX-1]=a[NLEN_XXX-1]&BMASK_XXX; /* top word normalized */
+    b[NLEN_XXX]=a[NLEN_XXX-1]>>BASEBITS_XXX;
+
+    for (i=NLEN_XXX+1; i<DNLEN_XXX; i++) b[i]=0;
+#ifdef DEBUG_NORM
+    b[DMPV_XXX]=a[MPV_XXX];
+    b[DMNV_XXX]=a[MNV_XXX];
+#endif
+}
+
+/* Copy BIG to top half of DBIG */
+void BIG_XXX_dsucopy(DBIG_XXX b,BIG_XXX a)
+{
+    int i;
+    for (i=0; i<NLEN_XXX; i++)
+        b[i]=0;
+    for (i=NLEN_XXX; i<DNLEN_XXX; i++)
+        b[i]=a[i-NLEN_XXX];
+#ifdef DEBUG_NORM
+    b[DMPV_XXX]=a[MPV_XXX];
+    b[DMNV_XXX]=a[MNV_XXX];
+#endif
+}
+
+/* Copy bottom half of DBIG to BIG */
+void BIG_XXX_sdcopy(BIG_XXX b,DBIG_XXX a)
+{
+    int i;
+    for (i=0; i<NLEN_XXX; i++)
+        b[i]=a[i];
+#ifdef DEBUG_NORM
+    b[MPV_XXX]=a[DMPV_XXX];
+    b[MNV_XXX]=a[DMNV_XXX];
+#endif
+}
+
+/* Copy top half of DBIG to BIG */
+void BIG_XXX_sducopy(BIG_XXX b,DBIG_XXX a)
+{
+    int i;
+    for (i=0; i<NLEN_XXX; i++)
+        b[i]=a[i+NLEN_XXX];
+#ifdef DEBUG_NORM
+    b[MPV_XXX]=a[DMPV_XXX];
+    b[MNV_XXX]=a[DMNV_XXX];
+
+#endif
+}
+
+/* Set a=0 */
+void BIG_XXX_zero(BIG_XXX a)
+{
+    int i;
+    for (i=0; i<NLEN_XXX; i++)
+        a[i]=0;
+#ifdef DEBUG_NORM
+    a[MPV_XXX]=a[MNV_XXX]=0;
+#endif
+}
+
+void BIG_XXX_dzero(DBIG_XXX a)
+{
+    int i;
+    for (i=0; i<DNLEN_XXX; i++)
+        a[i]=0;
+#ifdef DEBUG_NORM
+    a[DMPV_XXX]=a[DMNV_XXX]=0;
+#endif
+}
+
+/* set a=1 */
+void BIG_XXX_one(BIG_XXX a)
+{
+    int i;
+    a[0]=1;
+    for (i=1; i<NLEN_XXX; i++)
+        a[i]=0;
+#ifdef DEBUG_NORM
+    a[MPV_XXX]=1;
+    a[MNV_XXX]=0;
+#endif
+}
+
+
+
+/* Set c=a+b */
+/* SU= 8 */
+void BIG_XXX_add(BIG_XXX c,BIG_XXX a,BIG_XXX b)
+{
+    int i;
+    for (i=0; i<NLEN_XXX; i++)
+        c[i]=a[i]+b[i];
+#ifdef DEBUG_NORM
+    c[MPV_XXX]=a[MPV_XXX]+b[MPV_XXX];
+    c[MNV_XXX]=a[MNV_XXX]+b[MNV_XXX];
+    if (c[MPV_XXX]>NEXCESS_XXX)  printf("add problem - positive digit overflow %d\n",c[MPV_XXX]);
+    if (c[MNV_XXX]>NEXCESS_XXX)  printf("add problem - negative digit overflow %d\n",c[MNV_XXX]);
+
+#endif
+}
+
+/* Set c=a or b */
+void BIG_XXX_or(BIG_XXX c,BIG_XXX a,BIG_XXX b)
+{
+    int i;
+	BIG_XXX_norm(a);
+	BIG_XXX_norm(b);
+    for (i=0; i<NLEN_XXX; i++)
+        c[i]=a[i]|b[i];
+#ifdef DEBUG_NORM
+    c[MPV_XXX]=1;
+    c[MNV_XXX]=0;
+#endif
+}
+
+
+/* Set c=c+d */
+void BIG_XXX_inc(BIG_XXX c,int d)
+{
+    BIG_XXX_norm(c);
+    c[0]+=(chunk)d;
+#ifdef DEBUG_NORM
+    c[MPV_XXX]+=1;
+#endif
+}
+
+/* Set c=a-b */
+/* SU= 8 */
+void BIG_XXX_sub(BIG_XXX c,BIG_XXX a,BIG_XXX b)
+{
+    int i;
+    for (i=0; i<NLEN_XXX; i++)
+        c[i]=a[i]-b[i];
+#ifdef DEBUG_NORM
+    c[MPV_XXX]=a[MPV_XXX]+b[MNV_XXX];
+    c[MNV_XXX]=a[MNV_XXX]+b[MPV_XXX];
+    if (c[MPV_XXX]>NEXCESS_XXX)  printf("sub problem - positive digit overflow %d\n",c[MPV_XXX]);
+    if (c[MNV_XXX]>NEXCESS_XXX)  printf("sub problem - negative digit overflow %d\n",c[MNV_XXX]);
+
+#endif
+}
+
+/* SU= 8 */
+
+void BIG_XXX_dsub(DBIG_XXX c,DBIG_XXX a,DBIG_XXX b)
+{
+    int i;
+    for (i=0; i<DNLEN_XXX; i++)
+        c[i]=a[i]-b[i];
+#ifdef DEBUG_NORM
+    c[DMPV_XXX]=a[DMPV_XXX]+b[DMNV_XXX];
+    c[DMNV_XXX]=a[DMNV_XXX]+b[DMPV_XXX];
+    if (c[DMPV_XXX]>NEXCESS_XXX)  printf("double sub problem - positive digit overflow %d\n",c[DMPV_XXX]);
+    if (c[DMNV_XXX]>NEXCESS_XXX)  printf("double sub problem - negative digit overflow %d\n",c[DMNV_XXX]);
+#endif
+}
+
+void BIG_XXX_dadd(DBIG_XXX c,DBIG_XXX a,DBIG_XXX b)
+{
+    int i;
+    for (i=0; i<DNLEN_XXX; i++)
+        c[i]=a[i]+b[i];
+#ifdef DEBUG_NORM
+    c[DMPV_XXX]=a[DMPV_XXX]+b[DMNV_XXX];
+    c[DMNV_XXX]=a[DMNV_XXX]+b[DMPV_XXX];
+    if (c[DMPV_XXX]>NEXCESS_XXX)  printf("double add problem - positive digit overflow %d\n",c[DMPV_XXX]);
+    if (c[DMNV_XXX]>NEXCESS_XXX)  printf("double add problem - negative digit overflow %d\n",c[DMNV_XXX]);
+#endif
+}
+
+/* Set c=c-1 */
+void BIG_XXX_dec(BIG_XXX c,int d)
+{
+    BIG_XXX_norm(c);
+    c[0]-=(chunk)d;
+#ifdef DEBUG_NORM
+    c[MNV_XXX]+=1;
+#endif
+}
+
+/* multiplication r=a*c by c<=NEXCESS_XXX */
+void BIG_XXX_imul(BIG_XXX r,BIG_XXX a,int c)
+{
+    int i;
+    for (i=0; i<NLEN_XXX; i++) r[i]=a[i]*c;
+#ifdef DEBUG_NORM
+    r[MPV_XXX]=a[MPV_XXX]*c;
+    r[MNV_XXX]=a[MNV_XXX]*c;
+    if (r[MPV_XXX]>NEXCESS_XXX)  printf("int mul problem - positive digit overflow %d\n",r[MPV_XXX]);
+    if (r[MNV_XXX]>NEXCESS_XXX)  printf("int mul problem - negative digit overflow %d\n",r[MNV_XXX]);
+
+#endif
+}
+
+/* multiplication r=a*c by larger integer - c<=FEXCESS */
+/* SU= 24 */
+chunk BIG_XXX_pmul(BIG_XXX r,BIG_XXX a,int c)
+{
+    int i;
+    chunk ak,carry=0;
+//    BIG_XXX_norm(a);
+    for (i=0; i<NLEN_XXX; i++)
+    {
+        ak=a[i];
+        r[i]=0;
+        carry=muladd_XXX(ak,(chunk)c,carry,&r[i]);
+    }
+#ifdef DEBUG_NORM
+    r[MPV_XXX]=1;
+    r[MNV_XXX]=0;
+#endif
+    return carry;
+}
+
+/* r/=3 */
+/* SU= 16 */
+int BIG_XXX_div3(BIG_XXX r)
+{
+    int i;
+    chunk ak,base,carry=0;
+    BIG_XXX_norm(r);
+    base=((chunk)1<<BASEBITS_XXX);
+    for (i=NLEN_XXX-1; i>=0; i--)
+    {
+        ak=(carry*base+r[i]);
+        r[i]=ak/3;
+        carry=ak%3;
+    }
+    return (int)carry;
+}
+
+/* multiplication c=a*b by even larger integer b>FEXCESS, resulting in DBIG */
+/* SU= 24 */
+void BIG_XXX_pxmul(DBIG_XXX c,BIG_XXX a,int b)
+{
+    int j;
+    chunk carry;
+    BIG_XXX_dzero(c);
+    carry=0;
+    for (j=0; j<NLEN_XXX; j++)
+        carry=muladd_XXX(a[j],(chunk)b,carry,&c[j]);
+    c[NLEN_XXX]=carry;
+#ifdef DEBUG_NORM
+    c[DMPV_XXX]=1;
+    c[DMNV_XXX]=0;
+#endif
+}
+
+/* .. if you know the result will fit in a BIG, c must be distinct from a and b */
+/* SU= 40 */
+void BIG_XXX_smul(BIG_XXX c,BIG_XXX a,BIG_XXX b)
+{
+    int i,j;
+    chunk carry;
+//    BIG_XXX_norm(a);
+//    BIG_XXX_norm(b);
+
+    BIG_XXX_zero(c);
+    for (i=0; i<NLEN_XXX; i++)
+    {
+        carry=0;
+        for (j=0; j<NLEN_XXX; j++)
+        {
+            if (i+j<NLEN_XXX)
+                carry=muladd_XXX(a[i],b[j],carry,&c[i+j]);
+        }
+    }
+#ifdef DEBUG_NORM
+    c[MPV_XXX]=1;
+    c[MNV_XXX]=0;
+#endif
+
+}
+
+/* Set c=a*b */
+/* SU= 72 */
+void BIG_XXX_mul(DBIG_XXX c,BIG_XXX a,BIG_XXX b)
+{
+    int i;
+#ifdef dchunk
+    dchunk t,co;
+    dchunk s;
+    dchunk d[NLEN_XXX];
+    int k;
+#endif
+
+#ifdef DEBUG_NORM
+    if ((a[MPV_XXX]!=1 && a[MPV_XXX]!=0) || a[MNV_XXX]!=0) printf("First input to mul not normed\n");
+    if ((b[MPV_XXX]!=1 && b[MPV_XXX]!=0) || b[MNV_XXX]!=0) printf("Second input to mul not normed\n");
+#endif
+
+    /* Faster to Combafy it.. Let the compiler unroll the loops! */
+
+#ifdef COMBA
+
+    /* faster psuedo-Karatsuba method */
+#ifdef UNWOUND
+
+    /* Insert output of faster.c here */
+
+#else
+    for (i=0; i<NLEN_XXX; i++)
+        d[i]=(dchunk)a[i]*b[i];
+
+    s=d[0];
+    t=s;
+    c[0]=(chunk)t&BMASK_XXX;
+    co=t>>BASEBITS_XXX;
+
+    for (k=1; k<NLEN_XXX; k++)
+    {
+        s+=d[k];
+        t=co+s;
+        for (i=k; i>=1+k/2; i--) t+=(dchunk)(a[i]-a[k-i])*(b[k-i]-b[i]);
+        c[k]=(chunk)t&BMASK_XXX;
+        co=t>>BASEBITS_XXX;
+    }
+    for (k=NLEN_XXX; k<2*NLEN_XXX-1; k++)
+    {
+        s-=d[k-NLEN_XXX];
+        t=co+s;
+        for (i=NLEN_XXX-1; i>=1+k/2; i--) t+=(dchunk)(a[i]-a[k-i])*(b[k-i]-b[i]);
+        c[k]=(chunk)t&BMASK_XXX;
+        co=t>>BASEBITS_XXX;
+    }
+    c[2*NLEN_XXX-1]=(chunk)co;
+
+#endif
+
+#else
+    int j;
+    chunk carry;
+    BIG_XXX_dzero(c);
+    for (i=0; i<NLEN_XXX; i++)
+    {
+        carry=0;
+        for (j=0; j<NLEN_XXX; j++)
+            carry=muladd_XXX(a[i],b[j],carry,&c[i+j]);
+
+        c[NLEN_XXX+i]=carry;
+    }
+
+#endif
+
+#ifdef DEBUG_NORM
+    c[DMPV_XXX]=1;
+    c[DMNV_XXX]=0;
+#endif
+}
+
+/* Set c=a*a */
+/* SU= 80 */
+void BIG_XXX_sqr(DBIG_XXX c,BIG_XXX a)
+{
+    int i,j;
+#ifdef dchunk
+    dchunk t,co;
+#endif
+
+#ifdef DEBUG_NORM
+    if ((a[MPV_XXX]!=1 && a[MPV_XXX]!=0) || a[MNV_XXX]!=0) printf("Input to sqr not normed\n");
+#endif
+    /* Note 2*a[i] in loop below and extra addition */
+
+#ifdef COMBA
+
+#ifdef UNWOUND
+
+    /* Insert output of faster.c here */
+
+#else
+
+
+    t=(dchunk)a[0]*a[0];
+    c[0]=(chunk)t&BMASK_XXX;
+    co=t>>BASEBITS_XXX;
+
+    for (j=1; j<NLEN_XXX-1; )
+    {
+        t=(dchunk)a[j]*a[0];
+        for (i=1; i<(j+1)/2; i++)
+        {
+            t+=(dchunk)a[j-i]*a[i];
+        }
+        t+=t;
+        t+=co;
+        c[j]=(chunk)t&BMASK_XXX;
+        co=t>>BASEBITS_XXX;
+        j++;
+        t=(dchunk)a[j]*a[0];
+        for (i=1; i<(j+1)/2; i++)
+        {
+            t+=(dchunk)a[j-i]*a[i];
+        }
+        t+=t;
+        t+=co;
+        t+=(dchunk)a[j/2]*a[j/2];
+        c[j]=(chunk)t&BMASK_XXX;
+        co=t>>BASEBITS_XXX;
+        j++;
+    }
+
+    for (j=NLEN_XXX-1+NLEN_XXX%2; j<DNLEN_XXX-3; )
+    {
+        t=(dchunk)a[NLEN_XXX-1]*a[j-NLEN_XXX+1];
+        for (i=j-NLEN_XXX+2; i<(j+1)/2; i++)
+        {
+            t+=(dchunk)a[j-i]*a[i];
+        }
+        t+=t;
+        t+=co;
+        c[j]=(chunk)t&BMASK_XXX;
+        co=t>>BASEBITS_XXX;
+        j++;
+        t=(dchunk)a[NLEN_XXX-1]*a[j-NLEN_XXX+1];
+        for (i=j-NLEN_XXX+2; i<(j+1)/2; i++)
+        {
+            t+=(dchunk)a[j-i]*a[i];
+        }
+        t+=t;
+        t+=co;
+        t+=(dchunk)a[j/2]*a[j/2];
+        c[j]=(chunk)t&BMASK_XXX;
+        co=t>>BASEBITS_XXX;
+        j++;
+    }
+
+    t=(dchunk)a[NLEN_XXX-2]*a[NLEN_XXX-1];
+    t+=t;
+    t+=co;
+    c[DNLEN_XXX-3]=(chunk)t&BMASK_XXX;
+    co=t>>BASEBITS_XXX;
+
+    t=(dchunk)a[NLEN_XXX-1]*a[NLEN_XXX-1]+co;
+    c[DNLEN_XXX-2]=(chunk)t&BMASK_XXX;
+    co=t>>BASEBITS_XXX;
+    c[DNLEN_XXX-1]=(chunk)co;
+
+
+#endif
+
+#else
+    chunk carry;
+    BIG_XXX_dzero(c);
+    for (i=0; i<NLEN_XXX; i++)
+    {
+        carry=0;
+        for (j=i+1; j<NLEN_XXX; j++)
+            carry=muladd_XXX(a[i],a[j],carry,&c[i+j]);
+        c[NLEN_XXX+i]=carry;
+    }
+
+    for (i=0; i<DNLEN_XXX; i++) c[i]*=2;
+
+    for (i=0; i<NLEN_XXX; i++)
+        c[2*i+1]+=muladd_XXX(a[i],a[i],0,&c[2*i]);
+
+    BIG_XXX_dnorm(c);
+#endif
+
+
+#ifdef DEBUG_NORM
+    c[DMPV_XXX]=1;
+    c[DMNV_XXX]=0;
+#endif
+
+}
+
+/* Montgomery reduction */
+void BIG_XXX_monty(BIG_XXX a,BIG_XXX md,chunk MC,DBIG_XXX d)
+{
+    int i,k;
+
+#ifdef dchunk
+    dchunk t,c,s;
+    dchunk dd[NLEN_XXX];
+    chunk v[NLEN_XXX];
+#endif
+
+#ifdef COMBA
+
+#ifdef UNWOUND
+
+    /* Insert output of faster.c here */
+
+#else
+
+    t=d[0];
+    v[0]=((chunk)t*MC)&BMASK_XXX;
+    t+=(dchunk)v[0]*md[0];
+    c=(t>>BASEBITS_XXX)+d[1];
+    s=0;
+
+    for (k=1; k<NLEN_XXX; k++)
+    {
+        t=c+s+(dchunk)v[0]*md[k];
+        for (i=k-1; i>k/2; i--) t+=(dchunk)(v[k-i]-v[i])*(md[i]-md[k-i]);
+        v[k]=((chunk)t*MC)&BMASK_XXX;
+        t+=(dchunk)v[k]*md[0];
+        c=(t>>BASEBITS_XXX)+d[k+1];
+        dd[k]=(dchunk)v[k]*md[k];
+        s+=dd[k];
+    }
+    for (k=NLEN_XXX; k<2*NLEN_XXX-1; k++)
+    {
+        t=c+s;
+        for (i=NLEN_XXX-1; i>=1+k/2; i--) t+=(dchunk)(v[k-i]-v[i])*(md[i]-md[k-i]);
+        a[k-NLEN_XXX]=(chunk)t&BMASK_XXX;
+        c=(t>>BASEBITS_XXX)+d[k+1];
+        s-=dd[k-NLEN_XXX+1];
+    }
+    a[NLEN_XXX-1]=(chunk)c&BMASK_XXX;
+
+#endif
+
+
+
+#else
+    int j;
+    chunk m,carry;
+    for (i=0; i<NLEN_XXX; i++)
+    {
+        if (MC==-1) m=(-d[i])&BMASK_XXX;
+        else
+        {
+            if (MC==1) m=d[i];
+            else m=(MC*d[i])&BMASK_XXX;
+        }
+        carry=0;
+        for (j=0; j<NLEN_XXX; j++)
+            carry=muladd_XXX(m,md[j],carry,&d[i+j]);
+        d[NLEN_XXX+i]+=carry;
+    }
+    BIG_XXX_sducopy(a,d);
+    BIG_XXX_norm(a);
+
+#endif
+
+#ifdef DEBUG_NORM
+    a[MPV_XXX]=1;
+    a[MNV_XXX]=0;
+#endif
+}
+
+/* General shift left of a by n bits */
+/* a MUST be normalised */
+/* SU= 32 */
+void BIG_XXX_shl(BIG_XXX a,int k)
+{
+    int i;
+    int n=k%BASEBITS_XXX;
+    int m=k/BASEBITS_XXX;
+
+    a[NLEN_XXX-1]=((a[NLEN_XXX-1-m]<<n));
+    if (NLEN_XXX>=m+2) a[NLEN_XXX-1]|=(a[NLEN_XXX-m-2]>>(BASEBITS_XXX-n));
+
+    for (i=NLEN_XXX-2; i>m; i--)
+        a[i]=((a[i-m]<<n)&BMASK_XXX)|(a[i-m-1]>>(BASEBITS_XXX-n));
+    a[m]=(a[0]<<n)&BMASK_XXX;
+    for (i=0; i<m; i++) a[i]=0;
+
+}
+
+/* Fast shift left of a by n bits, where n less than a word, Return excess (but store it as well) */
+/* a MUST be normalised */
+/* SU= 16 */
+int BIG_XXX_fshl(BIG_XXX a,int n)
+{
+    int i;
+
+    a[NLEN_XXX-1]=((a[NLEN_XXX-1]<<n))|(a[NLEN_XXX-2]>>(BASEBITS_XXX-n)); /* top word not masked */
+    for (i=NLEN_XXX-2; i>0; i--)
+        a[i]=((a[i]<<n)&BMASK_XXX)|(a[i-1]>>(BASEBITS_XXX-n));
+    a[0]=(a[0]<<n)&BMASK_XXX;
+
+    return (int)(a[NLEN_XXX-1]>>((8*MODBYTES_XXX)%BASEBITS_XXX)); /* return excess - only used in ff.c */
+}
+
+/* double length left shift of a by k bits - k can be > BASEBITS , a MUST be normalised */
+/* SU= 32 */
+void BIG_XXX_dshl(DBIG_XXX a,int k)
+{
+    int i;
+    int n=k%BASEBITS_XXX;
+    int m=k/BASEBITS_XXX;
+
+    a[DNLEN_XXX-1]=((a[DNLEN_XXX-1-m]<<n))|(a[DNLEN_XXX-m-2]>>(BASEBITS_XXX-n));
+
+    for (i=DNLEN_XXX-2; i>m; i--)
+        a[i]=((a[i-m]<<n)&BMASK_XXX)|(a[i-m-1]>>(BASEBITS_XXX-n));
+    a[m]=(a[0]<<n)&BMASK_XXX;
+    for (i=0; i<m; i++) a[i]=0;
+
+}
+
+/* General shift right of a by k bits */
+/* a MUST be normalised */
+/* SU= 32 */
+void BIG_XXX_shr(BIG_XXX a,int k)
+{
+    int i;
+    int n=k%BASEBITS_XXX;
+    int m=k/BASEBITS_XXX;
+    for (i=0; i<NLEN_XXX-m-1; i++)
+        a[i]=(a[m+i]>>n)|((a[m+i+1]<<(BASEBITS_XXX-n))&BMASK_XXX);
+    if (NLEN_XXX>m)  a[NLEN_XXX-m-1]=a[NLEN_XXX-1]>>n;
+    for (i=NLEN_XXX-m; i<NLEN_XXX; i++) a[i]=0;
+
+}
+
+/* Fast combined shift, subtract and norm. Return sign of result */
+int BIG_XXX_ssn(BIG_XXX r,BIG_XXX a,BIG_XXX m)
+{
+	int i,n=NLEN_XXX-1;
+	chunk carry;
+	m[0]=(m[0]>>1)|((m[1]<<(BASEBITS_XXX-1))&BMASK_XXX);
+	r[0]=a[0]-m[0];
+    carry=r[0]>>BASEBITS_XXX;
+    r[0]&=BMASK_XXX;
+    
+	for (i=1;i<n;i++)
+	{
+		m[i]=(m[i]>>1)|((m[i+1]<<(BASEBITS_XXX-1))&BMASK_XXX);
+		r[i]=a[i]-m[i]+carry;
+		carry=r[i]>>BASEBITS_XXX;
+		r[i]&=BMASK_XXX;
+	}
+	
+	m[n]>>=1;
+	r[n]=a[n]-m[n]+carry;
+#ifdef DEBUG_NORM
+    r[MPV_XXX]=1;
+    r[MNV_XXX]=0;
+#endif
+	return ((r[n]>>(CHUNK-1))&1);
+}
+
+/* Faster shift right of a by k bits. Return shifted out part */
+/* a MUST be normalised */
+/* SU= 16 */
+int BIG_XXX_fshr(BIG_XXX a,int k)
+{
+    int i;
+    chunk r=a[0]&(((chunk)1<<k)-1); /* shifted out part */
+    for (i=0; i<NLEN_XXX-1; i++)
+        a[i]=(a[i]>>k)|((a[i+1]<<(BASEBITS_XXX-k))&BMASK_XXX);
+    a[NLEN_XXX-1]=a[NLEN_XXX-1]>>k;
+    return (int)r;
+}
+
+/* double length right shift of a by k bits - can be > BASEBITS */
+/* SU= 32 */
+void BIG_XXX_dshr(DBIG_XXX a,int k)
+{
+    int i;
+    int n=k%BASEBITS_XXX;
+    int m=k/BASEBITS_XXX;
+    for (i=0; i<DNLEN_XXX-m-1; i++)
+        a[i]=(a[m+i]>>n)|((a[m+i+1]<<(BASEBITS_XXX-n))&BMASK_XXX);
+    a[DNLEN_XXX-m-1]=a[DNLEN_XXX-1]>>n;
+    for (i=DNLEN_XXX-m; i<DNLEN_XXX; i++ ) a[i]=0;
+}
+
+/* Split DBIG d into two BIGs t|b. Split happens at n bits, where n falls into NLEN word */
+/* d MUST be normalised */
+/* SU= 24 */
+chunk BIG_XXX_split(BIG_XXX t,BIG_XXX b,DBIG_XXX d,int n)
+{
+    int i;
+    chunk nw,carry=0;
+    int m=n%BASEBITS_XXX;
+//	BIG_dnorm(d);
+
+    if (m==0)
+    {
+        for (i=0; i<NLEN_XXX; i++) b[i]=d[i];
+        if (t!=b)
+        {
+            for (i=NLEN_XXX; i<2*NLEN_XXX; i++) t[i-NLEN_XXX]=d[i];
+            carry=t[NLEN_XXX-1]>>BASEBITS_XXX;
+            t[NLEN_XXX-1]=t[NLEN_XXX-1]&BMASK_XXX; /* top word normalized */
+        }
+        return carry;
+    }
+
+    for (i=0; i<NLEN_XXX-1; i++) b[i]=d[i];
+
+    b[NLEN_XXX-1]=d[NLEN_XXX-1]&(((chunk)1<<m)-1);
+
+    if (t!=b)
+    {
+        carry=(d[DNLEN_XXX-1]<<(BASEBITS_XXX-m));
+        for (i=DNLEN_XXX-2; i>=NLEN_XXX-1; i--)
+        {
+            nw=(d[i]>>m)|carry;
+            carry=(d[i]<<(BASEBITS_XXX-m))&BMASK_XXX;
+            t[i-NLEN_XXX+1]=nw;
+        }
+    }
+#ifdef DEBUG_NORM
+    t[MPV_XXX]=1;
+    t[MNV_XXX]=0;
+    b[MPV_XXX]=1;
+    b[MNV_XXX]=0;
+#endif
+    return carry;
+}
+
+/* you gotta keep the sign of carry! Look - no branching! */
+/* Note that sign bit is needed to disambiguate between +ve and -ve values */
+/* normalise BIG - force all digits < 2^BASEBITS */
+chunk BIG_XXX_norm(BIG_XXX a)
+{
+    int i;
+    chunk d,carry=0;
+    for (i=0; i<NLEN_XXX-1; i++)
+    {
+        d=a[i]+carry;
+        a[i]=d&BMASK_XXX;
+        carry=d>>BASEBITS_XXX;
+    }
+    a[NLEN_XXX-1]=(a[NLEN_XXX-1]+carry);
+
+#ifdef DEBUG_NORM
+    a[MPV_XXX]=1;
+    a[MNV_XXX]=0;
+#endif
+    return (a[NLEN_XXX-1]>>((8*MODBYTES_XXX)%BASEBITS_XXX));  /* only used in ff.c */
+}
+
+void BIG_XXX_dnorm(DBIG_XXX a)
+{
+    int i;
+    chunk d,carry=0;
+    for (i=0; i<DNLEN_XXX-1; i++)
+    {
+        d=a[i]+carry;
+        a[i]=d&BMASK_XXX;
+        carry=d>>BASEBITS_XXX;
+    }
+    a[DNLEN_XXX-1]=(a[DNLEN_XXX-1]+carry);
+#ifdef DEBUG_NORM
+    a[DMPV_XXX]=1;
+    a[DMNV_XXX]=0;
+#endif
+}
+
+/* Compare a and b. Return 1 for a>b, -1 for a<b, 0 for a==b */
+/* a and b MUST be normalised before call */
+int BIG_XXX_comp(BIG_XXX a,BIG_XXX b)
+{
+    int i;
+    for (i=NLEN_XXX-1; i>=0; i--)
+    {
+        if (a[i]==b[i]) continue;
+        if (a[i]>b[i]) return 1;
+        else  return -1;
+    }
+    return 0;
+}
+
+int BIG_XXX_dcomp(DBIG_XXX a,DBIG_XXX b)
+{
+    int i;
+    for (i=DNLEN_XXX-1; i>=0; i--)
+    {
+        if (a[i]==b[i]) continue;
+        if (a[i]>b[i]) return 1;
+        else  return -1;
+    }
+    return 0;
+}
+
+/* return number of bits in a */
+/* SU= 8 */
+int BIG_XXX_nbits(BIG_XXX a)
+{
+    int bts,k=NLEN_XXX-1;
+	BIG_XXX t;
+    chunk c;
+	BIG_XXX_copy(t,a);
+    BIG_XXX_norm(t);
+    while (k>=0 && t[k]==0) k--;
+    if (k<0) return 0;
+    bts=BASEBITS_XXX*k;
+    c=t[k];
+    while (c!=0)
+    {
+        c/=2;
+        bts++;
+    }
+    return bts;
+}
+
+/* SU= 8, Calculate number of bits in a DBIG - output normalised */
+int BIG_XXX_dnbits(DBIG_XXX a)
+{
+    int bts,k=DNLEN_XXX-1;
+	DBIG_XXX t;
+    chunk c;
+	BIG_XXX_dcopy(t,a);
+    BIG_XXX_dnorm(t);
+    while (k>=0 && t[k]==0) k--;
+    if (k<0) return 0;
+    bts=BASEBITS_XXX*k;
+    c=t[k];
+    while (c!=0)
+    {
+        c/=2;
+        bts++;
+    }
+    return bts;
+}
+
+
+/* Set b=b mod c */
+/* SU= 16 */
+void BIG_XXX_mod(BIG_XXX b,BIG_XXX c1)
+{
+    int k=0;
+    BIG_XXX r; /**/
+	BIG_XXX c;
+	BIG_XXX_copy(c,c1);
+
+    BIG_XXX_norm(b);
+    if (BIG_XXX_comp(b,c)<0)
+        return;
+    do
+    {
+        BIG_XXX_fshl(c,1);
+        k++;
+    }
+    while (BIG_XXX_comp(b,c)>=0);
+
+    while (k>0)
+    {
+        BIG_XXX_fshr(c,1);
+
+// constant time...
+        BIG_XXX_sub(r,b,c);
+        BIG_XXX_norm(r);
+        BIG_XXX_cmove(b,r,1-((r[NLEN_XXX-1]>>(CHUNK-1))&1));
+        k--;
+    }
+}
+
+/* Set a=b mod c, b is destroyed. Slow but rarely used. */
+/* SU= 96 */
+void BIG_XXX_dmod(BIG_XXX a,DBIG_XXX b,BIG_XXX c)
+{
+    int k=0;
+    DBIG_XXX m,r;
+    BIG_XXX_dnorm(b);
+    BIG_XXX_dscopy(m,c);
+
+    if (BIG_XXX_dcomp(b,m)<0)
+    {
+        BIG_XXX_sdcopy(a,b);
+        return;
+    }
+
+    do
+    {
+        BIG_XXX_dshl(m,1);
+        k++;
+    }
+    while (BIG_XXX_dcomp(b,m)>=0);
+
+    while (k>0)
+    {
+        BIG_XXX_dshr(m,1);
+// constant time...
+        BIG_XXX_dsub(r,b,m);
+        BIG_XXX_dnorm(r);
+        BIG_XXX_dcmove(b,r,1-((r[DNLEN_XXX-1]>>(CHUNK-1))&1));
+
+        k--;
+    }
+    BIG_XXX_sdcopy(a,b);
+}
+
+/* Set a=b/c,  b is destroyed. Slow but rarely used. */
+/* SU= 136 */
+
+void BIG_XXX_ddiv(BIG_XXX a,DBIG_XXX b,BIG_XXX c)
+{
+    int d,k=0;
+    DBIG_XXX m,dr;
+    BIG_XXX e,r;
+    BIG_XXX_dnorm(b);
+    BIG_XXX_dscopy(m,c);
+
+    BIG_XXX_zero(a);
+    BIG_XXX_zero(e);
+    BIG_XXX_inc(e,1);
+
+    while (BIG_XXX_dcomp(b,m)>=0)
+    {
+        BIG_XXX_fshl(e,1);
+        BIG_XXX_dshl(m,1);
+        k++;
+    }
+
+    while (k>0)
+    {
+        BIG_XXX_dshr(m,1);
+        BIG_XXX_fshr(e,1);
+
+        BIG_XXX_dsub(dr,b,m);
+        BIG_XXX_dnorm(dr);
+        d=1-((dr[DNLEN_XXX-1]>>(CHUNK-1))&1);
+        BIG_XXX_dcmove(b,dr,d);
+
+        BIG_XXX_add(r,a,e);
+        BIG_XXX_norm(r);
+        BIG_XXX_cmove(a,r,d);
+
+        k--;
+    }
+}
+
+/* SU= 136 */
+
+void BIG_XXX_sdiv(BIG_XXX a,BIG_XXX c)
+{
+    int d,k=0;
+    BIG_XXX m,e,b,r;
+    BIG_XXX_norm(a);
+    BIG_XXX_copy(b,a);
+    BIG_XXX_copy(m,c);
+
+    BIG_XXX_zero(a);
+    BIG_XXX_zero(e);
+    BIG_XXX_inc(e,1);
+
+    while (BIG_XXX_comp(b,m)>=0)
+    {
+        BIG_XXX_fshl(e,1);
+        BIG_XXX_fshl(m,1);
+        k++;
+    }
+
+    while (k>0)
+    {
+        BIG_XXX_fshr(m,1);
+        BIG_XXX_fshr(e,1);
+
+        BIG_XXX_sub(r,b,m);
+        BIG_XXX_norm(r);
+        d=1-((r[NLEN_XXX-1]>>(CHUNK-1))&1);
+        BIG_XXX_cmove(b,r,d);
+
+        BIG_XXX_add(r,a,e);
+        BIG_XXX_norm(r);
+        BIG_XXX_cmove(a,r,d);
+        k--;
+    }
+}
+
+/* return LSB of a */
+int BIG_XXX_parity(BIG_XXX a)
+{
+    return a[0]%2;
+}
+
+/* return n-th bit of a */
+/* SU= 16 */
+int BIG_XXX_bit(BIG_XXX a,int n)
+{
+    if (a[n/BASEBITS_XXX]&((chunk)1<<(n%BASEBITS_XXX))) return 1;
+    else return 0;
+}
+
+/* return NAF value as +/- 1, 3 or 5. x and x3 should be normed.
+nbs is number of bits processed, and nzs is number of trailing 0s detected */
+/* SU= 32 */
+/*
+int BIG_nafbits(BIG x,BIG x3,int i,int *nbs,int *nzs)
+{
+	int j,r,nb;
+
+	nb=BIG_bit(x3,i)-BIG_bit(x,i);
+	*nbs=1;
+	*nzs=0;
+	if (nb==0) return 0;
+	if (i==0) return nb;
+
+    if (nb>0) r=1;
+    else      r=(-1);
+
+    for (j=i-1;j>0;j--)
+    {
+        (*nbs)++;
+        r*=2;
+        nb=BIG_bit(x3,j)-BIG_bit(x,j);
+        if (nb>0) r+=1;
+        if (nb<0) r-=1;
+        if (abs(r)>5) break;
+    }
+
+	if (r%2!=0 && j!=0)
+    { // backtrack
+        if (nb>0) r=(r-1)/2;
+        if (nb<0) r=(r+1)/2;
+        (*nbs)--;
+    }
+
+    while (r%2==0)
+    { // remove trailing zeros
+        r/=2;
+        (*nzs)++;
+        (*nbs)--;
+    }
+    return r;
+}
+*/
+
+/* return last n bits of a, where n is small < BASEBITS */
+/* SU= 16 */
+int BIG_XXX_lastbits(BIG_XXX a,int n)
+{
+    int msk=(1<<n)-1;
+    BIG_XXX_norm(a);
+    return ((int)a[0])&msk;
+}
+
+/* get 8*MODBYTES size random number */
+void BIG_XXX_random(BIG_XXX m,csprng *rng)
+{
+    int i,b,j=0,r=0;
+    int len=8*MODBYTES_XXX;
+
+    BIG_XXX_zero(m);
+    /* generate random BIG */
+    for (i=0; i<len; i++)
+    {
+        if (j==0) r=RAND_byte(rng);
+        else r>>=1;
+        b=r&1;
+        BIG_XXX_shl(m,1);
+        m[0]+=b;
+        j++;
+        j&=7;
+    }
+
+#ifdef DEBUG_NORM
+    m[MPV_XXX]=1;
+    m[MNV_XXX]=0;
+#endif
+}
+
+/* get random BIG from rng, modulo q. Done one bit at a time, so its portable */
+
+void BIG_XXX_randomnum(BIG_XXX m,BIG_XXX q,csprng *rng)
+{
+    int i,b,j=0,r=0;
+    DBIG_XXX d;
+    BIG_XXX_dzero(d);
+    /* generate random DBIG */
+    for (i=0; i<2*BIG_XXX_nbits(q); i++)
+    {
+        if (j==0) r=RAND_byte(rng);
+        else r>>=1;
+        b=r&1;
+        BIG_XXX_dshl(d,1);
+        d[0]+=b;
+        j++;
+        j&=7;
+    }
+    /* reduce modulo a BIG. Removes bias */
+    BIG_XXX_dmod(m,d,q);
+#ifdef DEBUG_NORM
+    m[MPV_XXX]=1;
+    m[MNV_XXX]=0;
+#endif
+}
+
+/* Set r=a*b mod m */
+/* SU= 96 */
+void BIG_XXX_modmul(BIG_XXX r,BIG_XXX a1,BIG_XXX b1,BIG_XXX m)
+{
+    DBIG_XXX d;
+	BIG_XXX a,b;
+	BIG_XXX_copy(a,a1);
+	BIG_XXX_copy(b,b1);
+    BIG_XXX_mod(a,m);
+    BIG_XXX_mod(b,m);
+
+    BIG_XXX_mul(d,a,b);
+    BIG_XXX_dmod(r,d,m);
+}
+
+/* Set a=a*a mod m */
+/* SU= 88 */
+void BIG_XXX_modsqr(BIG_XXX r,BIG_XXX a1,BIG_XXX m)
+{
+    DBIG_XXX d;
+	BIG_XXX a;
+	BIG_XXX_copy(a,a1);
+    BIG_XXX_mod(a,m);
+    BIG_XXX_sqr(d,a);
+    BIG_XXX_dmod(r,d,m);
+}
+
+/* Set r=-a mod m */
+/* SU= 16 */
+void BIG_XXX_modneg(BIG_XXX r,BIG_XXX a1,BIG_XXX m)
+{
+	BIG_XXX a;
+	BIG_XXX_copy(a,a1);
+    BIG_XXX_mod(a,m);
+    BIG_XXX_sub(r,m,a);
+//    BIG_XXX_mod(r,m);
+}
+
+/* Set a=a/b mod m */
+/* SU= 136 */
+void BIG_XXX_moddiv(BIG_XXX r,BIG_XXX a1,BIG_XXX b1,BIG_XXX m)
+{
+    DBIG_XXX d;
+    BIG_XXX z;
+	BIG_XXX a,b;
+	BIG_XXX_copy(a,a1);
+	BIG_XXX_copy(b,b1);
+
+    BIG_XXX_mod(a,m);
+    BIG_XXX_invmodp(z,b,m);
+
+    BIG_XXX_mul(d,a,z);
+    BIG_XXX_dmod(r,d,m);
+}
+
+/* Get jacobi Symbol (a/p). Returns 0, 1 or -1 */
+/* SU= 216 */
+int BIG_XXX_jacobi(BIG_XXX a,BIG_XXX p)
+{
+    int n8,k,m=0;
+    BIG_XXX t,x,n,zilch,one;
+    BIG_XXX_one(one);
+    BIG_XXX_zero(zilch);
+    if (BIG_XXX_parity(p)==0 || BIG_XXX_comp(a,zilch)==0 || BIG_XXX_comp(p,one)<=0) return 0;
+    BIG_XXX_norm(a);
+    BIG_XXX_copy(x,a);
+    BIG_XXX_copy(n,p);
+    BIG_XXX_mod(x,p);
+
+    while (BIG_XXX_comp(n,one)>0)
+    {
+        if (BIG_XXX_comp(x,zilch)==0) return 0;
+        n8=BIG_XXX_lastbits(n,3);
+        k=0;
+        while (BIG_XXX_parity(x)==0)
+        {
+            k++;
+            BIG_XXX_shr(x,1);
+        }
+        if (k%2==1) m+=(n8*n8-1)/8;
+        m+=(n8-1)*(BIG_XXX_lastbits(x,2)-1)/4;
+        BIG_XXX_copy(t,n);
+
+        BIG_XXX_mod(t,x);
+        BIG_XXX_copy(n,x);
+        BIG_XXX_copy(x,t);
+        m%=2;
+
+    }
+    if (m==0) return 1;
+    else return -1;
+}
+
+/* Set r=1/a mod p. Binary method */
+/* SU= 240 */
+void BIG_XXX_invmodp(BIG_XXX r,BIG_XXX a,BIG_XXX p)
+{
+    BIG_XXX u,v,x1,x2,t,one;
+    BIG_XXX_mod(a,p);
+    BIG_XXX_copy(u,a);
+    BIG_XXX_copy(v,p);
+    BIG_XXX_one(one);
+    BIG_XXX_copy(x1,one);
+    BIG_XXX_zero(x2);
+
+    while (BIG_XXX_comp(u,one)!=0 && BIG_XXX_comp(v,one)!=0)
+    {
+        while (BIG_XXX_parity(u)==0)
+        {
+            BIG_XXX_fshr(u,1);
+            if (BIG_XXX_parity(x1)!=0)
+            {
+                BIG_XXX_add(x1,p,x1);
+                BIG_XXX_norm(x1);
+            }
+            BIG_XXX_fshr(x1,1);
+        }
+        while (BIG_XXX_parity(v)==0)
+        {
+            BIG_XXX_fshr(v,1);
+            if (BIG_XXX_parity(x2)!=0)
+            {
+                BIG_XXX_add(x2,p,x2);
+                BIG_XXX_norm(x2);
+            }
+            BIG_XXX_fshr(x2,1);
+        }
+        if (BIG_XXX_comp(u,v)>=0)
+        {
+            BIG_XXX_sub(u,u,v);
+            BIG_XXX_norm(u);
+            if (BIG_XXX_comp(x1,x2)>=0) BIG_XXX_sub(x1,x1,x2);
+            else
+            {
+                BIG_XXX_sub(t,p,x2);
+                BIG_XXX_add(x1,x1,t);
+            }
+            BIG_XXX_norm(x1);
+        }
+        else
+        {
+            BIG_XXX_sub(v,v,u);
+            BIG_XXX_norm(v);
+            if (BIG_XXX_comp(x2,x1)>=0) BIG_XXX_sub(x2,x2,x1);
+            else
+            {
+                BIG_XXX_sub(t,p,x1);
+                BIG_XXX_add(x2,x2,t);
+            }
+            BIG_XXX_norm(x2);
+        }
+    }
+    if (BIG_XXX_comp(u,one)==0)
+        BIG_XXX_copy(r,x1);
+    else
+        BIG_XXX_copy(r,x2);
+}
+
+/* set x = x mod 2^m */
+void BIG_XXX_mod2m(BIG_XXX x,int m)
+{
+    int i,wd,bt;
+    chunk msk;
+    BIG_XXX_norm(x);
+//	if (m>=MODBITS) return;
+    wd=m/BASEBITS_XXX;
+    bt=m%BASEBITS_XXX;
+    msk=((chunk)1<<bt)-1;
+    x[wd]&=msk;
+    for (i=wd+1; i<NLEN_XXX; i++) x[i]=0;
+}
+
+// new
+/* Convert to DBIG number from byte array of given length */
+void BIG_XXX_dfromBytesLen(DBIG_XXX a,char *b,int s)
+{
+    int i,len=s;
+    BIG_XXX_dzero(a);
+
+    for (i=0; i<len; i++)
+    {
+        BIG_XXX_dshl(a,8);
+        a[0]+=(int)(unsigned char)b[i];
+    }
+#ifdef DEBUG_NORM
+    a[DMPV_XXX]=1;
+    a[DMNV_XXX]=0;
+#endif
+}
diff --git a/version3/c/big.h b/version3/c/big.h
new file mode 100644
index 0000000..36b0c7c
--- /dev/null
+++ b/version3/c/big.h
@@ -0,0 +1,610 @@
+/*
+	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.
+*/
+
+/**
+ * @file big.h
+ * @author Mike Scott
+ * @brief BIG Header File
+ *
+ */
+
+#ifndef BIG_XXX_H
+#define BIG_XXX_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include "arch.h"
+#include "amcl.h"
+#include "config_big_XXX.h"
+
+//#define UNWOUND
+
+#define BIGBITS_XXX (8*MODBYTES_XXX) /**< Length in bits */
+#define NLEN_XXX (1+((8*MODBYTES_XXX-1)/BASEBITS_XXX)) /**< length in bytes */
+#define DNLEN_XXX 2*NLEN_XXX /**< Double length in bytes */
+#define BMASK_XXX (((chunk)1<<BASEBITS_XXX)-1) /**< Mask = 2^BASEBITS-1 */
+#define NEXCESS_XXX (1<<(CHUNK-BASEBITS_XXX-1))           /**< 2^(CHUNK-BASEBITS-1) - digit cannot be multiplied by more than this before normalisation */
+
+#define HBITS_XXX (BASEBITS_XXX/2)      /**< Number of bits in number base divided by 2 */
+#define HMASK_XXX (((chunk)1<<HBITS_XXX)-1)    /**< Mask = 2^HBITS-1 */
+
+//#define DEBUG_NORM
+
+#ifdef DEBUG_NORM  /* Add an extra location to track chunk extension */
+#define MPV_XXX NLEN_XXX
+#define MNV_XXX (NLEN_XXX+1)
+typedef chunk BIG_XXX[NLEN_XXX+2];   /**< Define type BIG as array of chunks */
+#define DMPV_XXX DNLEN_XXX
+#define DMNV_XXX (DNLEN_XXX+1)
+typedef chunk DBIG_XXX[DNLEN_XXX+2]; /**< Define type DBIG as array of chunks */
+#else
+typedef chunk BIG_XXX[NLEN_XXX];     /**< Define type BIG as array of chunks */
+typedef chunk DBIG_XXX[DNLEN_XXX];   /**< Define type DBIG as array of chunks */
+#endif
+
+/* BIG number prototypes */
+
+/**	@brief Tests for BIG equal to zero
+ *
+	@param x a BIG number
+	@return 1 if zero, else returns 0
+ */
+extern int BIG_XXX_iszilch(BIG_XXX x);
+/**	@brief Tests for BIG equal to one
+ *
+	@param x a BIG number
+	@return 1 if one, else returns 0
+ */
+extern int BIG_XXX_isunity(BIG_XXX x);
+/**	@brief Tests for DBIG equal to zero
+ *
+	@param x a DBIG number
+	@return 1 if zero, else returns 0
+ */
+extern int BIG_XXX_diszilch(DBIG_XXX x);
+/**	@brief Outputs a BIG number to the console
+ *
+	@param x a BIG number
+ */
+extern void BIG_XXX_output(BIG_XXX x);
+/**	@brief Outputs a BIG number to the console in raw form (for debugging)
+ *
+	@param x a BIG number
+ */
+extern void BIG_XXX_rawoutput(BIG_XXX x);
+/**	@brief Conditional constant time swap of two BIG numbers
+ *
+	Conditionally swaps parameters in constant time (without branching)
+	@param x a BIG number
+	@param y another BIG number
+	@param s swap takes place if not equal to 0
+ */
+extern void BIG_XXX_cswap(BIG_XXX x,BIG_XXX y,int s);
+/**	@brief Conditional copy of BIG number
+ *
+	Conditionally copies second parameter to the first (without branching)
+	@param x a BIG number
+	@param y another BIG number
+	@param s copy takes place if not equal to 0
+ */
+extern void BIG_XXX_cmove(BIG_XXX x,BIG_XXX y,int s);
+/**	@brief Conditional copy of DBIG number
+ *
+	Conditionally copies second parameter to the first (without branching)
+	@param x a DBIG number
+	@param y another DBIG number
+	@param s copy takes place if not equal to 0
+ */
+extern void BIG_XXX_dcmove(BIG_XXX x,BIG_XXX y,int s);
+/**	@brief Convert from BIG number to byte array
+ *
+	@param a byte array
+	@param x BIG number
+ */
+extern void BIG_XXX_toBytes(char *a,BIG_XXX x);
+/**	@brief Convert to BIG number from byte array
+ *
+	@param x BIG number
+	@param a byte array
+ */
+extern void BIG_XXX_fromBytes(BIG_XXX x,char *a);
+/**	@brief Convert to BIG number from byte array of given length
+ *
+	@param x BIG number
+	@param a byte array
+	@param s byte array length
+ */
+extern void BIG_XXX_fromBytesLen(BIG_XXX x,char *a,int s);
+/**@brief Convert to DBIG number from byte array of given length
+ *
+   @param x DBIG number
+   @param a byte array
+   @param s byte array length
+ */
+extern void BIG_XXX_dfromBytesLen(DBIG_XXX x,char *a,int s);
+/**	@brief Outputs a DBIG number to the console
+ *
+	@param x a DBIG number
+ */
+extern void BIG_XXX_doutput(DBIG_XXX x);
+
+/**	@brief Outputs a DBIG number to the console
+ *
+	@param x a DBIG number
+ */
+extern void BIG_XXX_drawoutput(DBIG_XXX x);
+
+/**	@brief Copy BIG from Read-Only Memory to a BIG
+ *
+	@param x BIG number
+	@param y BIG number in ROM
+ */
+extern void BIG_XXX_rcopy(BIG_XXX x,const BIG_XXX y);
+/**	@brief Copy BIG to another BIG
+ *
+	@param x BIG number
+	@param y BIG number to be copied
+ */
+extern void BIG_XXX_copy(BIG_XXX x,BIG_XXX y);
+/**	@brief Copy DBIG to another DBIG
+ *
+	@param x DBIG number
+	@param y DBIG number to be copied
+ */
+extern void BIG_XXX_dcopy(DBIG_XXX x,DBIG_XXX y);
+/**	@brief Copy BIG to upper half of DBIG
+ *
+	@param x DBIG number
+	@param y BIG number to be copied
+ */
+extern void BIG_XXX_dsucopy(DBIG_XXX x,BIG_XXX y);
+/**	@brief Copy BIG to lower half of DBIG
+ *
+	@param x DBIG number
+	@param y BIG number to be copied
+ */
+extern void BIG_XXX_dscopy(DBIG_XXX x,BIG_XXX y);
+/**	@brief Copy lower half of DBIG to a BIG
+ *
+	@param x BIG number
+	@param y DBIG number to be copied
+ */
+extern void BIG_XXX_sdcopy(BIG_XXX x,DBIG_XXX y);
+/**	@brief Copy upper half of DBIG to a BIG
+ *
+	@param x BIG number
+	@param y DBIG number to be copied
+ */
+extern void BIG_XXX_sducopy(BIG_XXX x,DBIG_XXX y);
+/**	@brief Set BIG to zero
+ *
+	@param x BIG number to be set to zero
+ */
+extern void BIG_XXX_zero(BIG_XXX x);
+/**	@brief Set DBIG to zero
+ *
+	@param x DBIG number to be set to zero
+ */
+extern void BIG_XXX_dzero(DBIG_XXX x);
+/**	@brief Set BIG to one (unity)
+ *
+	@param x BIG number to be set to one.
+ */
+extern void BIG_XXX_one(BIG_XXX x);
+/**	@brief Set BIG to inverse mod 2^256
+ *
+	@param x BIG number to be inverted
+ */
+extern void BIG_XXX_invmod2m(BIG_XXX x);
+/**	@brief Set BIG to sum of two BIGs - output not normalised
+ *
+	@param x BIG number, sum of other two
+	@param y BIG number
+	@param z BIG number
+ */
+extern void BIG_XXX_add(BIG_XXX x,BIG_XXX y,BIG_XXX z);
+
+/**	@brief Set BIG to logical or of two BIGs - output normalised
+ *
+	@param x BIG number, or of other two
+	@param y BIG number
+	@param z BIG number
+ */
+extern void BIG_XXX_or(BIG_XXX x,BIG_XXX y,BIG_XXX z);
+
+/**	@brief Increment BIG by a small integer - output not normalised
+ *
+	@param x BIG number to be incremented
+	@param i integer
+ */
+extern void BIG_XXX_inc(BIG_XXX x,int i);
+/**	@brief Set BIG to difference of two BIGs
+ *
+	@param x BIG number, difference of other two - output not normalised
+	@param y BIG number
+	@param z BIG number
+ */
+extern void BIG_XXX_sub(BIG_XXX x,BIG_XXX y,BIG_XXX z);
+/**	@brief Decrement BIG by a small integer - output not normalised
+ *
+	@param x BIG number to be decremented
+	@param i integer
+ */
+extern void BIG_XXX_dec(BIG_XXX x,int i);
+/**	@brief Set DBIG to sum of two DBIGs
+ *
+	@param x DBIG number, sum of other two - output not normalised
+	@param y DBIG number
+	@param z DBIG number
+ */
+extern void BIG_XXX_dadd(DBIG_XXX x,DBIG_XXX y,DBIG_XXX z);
+/**	@brief Set DBIG to difference of two DBIGs
+ *
+	@param x DBIG number, difference of other two - output not normalised
+	@param y DBIG number
+	@param z DBIG number
+ */
+extern void BIG_XXX_dsub(DBIG_XXX x,DBIG_XXX y,DBIG_XXX z);
+/**	@brief Multiply BIG by a small integer - output not normalised
+ *
+	@param x BIG number, product of other two
+	@param y BIG number
+	@param i small integer
+ */
+extern void BIG_XXX_imul(BIG_XXX x,BIG_XXX y,int i);
+/**	@brief Multiply BIG by not-so-small small integer - output normalised
+ *
+	@param x BIG number, product of other two
+	@param y BIG number
+	@param i small integer
+	@return Overflowing bits
+ */
+extern chunk BIG_XXX_pmul(BIG_XXX x,BIG_XXX y,int i);
+/**	@brief Divide BIG by 3 - output normalised
+ *
+	@param x BIG number
+	@return Remainder
+ */
+extern int BIG_XXX_div3(BIG_XXX x);
+/**	@brief Multiply BIG by even bigger small integer resulting in a DBIG - output normalised
+ *
+	@param x DBIG number, product of other two
+	@param y BIG number
+	@param i small integer
+ */
+extern void BIG_XXX_pxmul(DBIG_XXX x,BIG_XXX y,int i);
+/**	@brief Multiply BIG by another BIG resulting in DBIG - inputs normalised and output normalised
+ *
+	@param x DBIG number, product of other two
+	@param y BIG number
+	@param z BIG number
+ */
+extern void BIG_XXX_mul(DBIG_XXX x,BIG_XXX y,BIG_XXX z);
+/**	@brief Multiply BIG by another BIG resulting in another BIG - inputs normalised and output normalised
+ *
+	Note that the product must fit into a BIG, and x must be distinct from y and z
+	@param x BIG number, product of other two
+	@param y BIG number
+	@param z BIG number
+ */
+extern void BIG_XXX_smul(BIG_XXX x,BIG_XXX y,BIG_XXX z);
+/**	@brief Square BIG resulting in a DBIG - input normalised and output normalised
+ *
+	@param x DBIG number, square of a BIG
+	@param y BIG number to be squared
+ */
+extern void BIG_XXX_sqr(DBIG_XXX x,BIG_XXX y);
+
+/**	@brief Montgomery reduction of a DBIG to a BIG  - input normalised and output normalised
+ *
+	@param a BIG number, reduction of a BIG
+	@param md BIG number, the modulus
+	@param MC the Montgomery Constant
+	@param d DBIG number to be reduced
+ */
+extern void BIG_XXX_monty(BIG_XXX a,BIG_XXX md,chunk MC,DBIG_XXX d);
+
+/**	@brief Shifts a BIG left by any number of bits - input must be normalised, output normalised
+ *
+	@param x BIG number to be shifted
+	@param s Number of bits to shift
+ */
+extern void BIG_XXX_shl(BIG_XXX x,int s);
+/**	@brief Fast shifts a BIG left by a small number of bits - input must be normalised, output will be normalised
+ *
+	The number of bits to be shifted must be less than BASEBITS
+	@param x BIG number to be shifted
+	@param s Number of bits to shift
+	@return Overflow bits
+ */
+extern int BIG_XXX_fshl(BIG_XXX x,int s);
+/**	@brief Shifts a DBIG left by any number of bits - input must be normalised, output normalised
+ *
+	@param x DBIG number to be shifted
+	@param s Number of bits to shift
+ */
+extern void BIG_XXX_dshl(DBIG_XXX x,int s);
+/**	@brief Shifts a BIG right by any number of bits - input must be normalised, output normalised
+ *
+	@param x BIG number to be shifted
+	@param s Number of bits to shift
+ */
+extern void BIG_XXX_shr(BIG_XXX x,int s);
+
+/**	@brief Fast time-critical combined shift by 1 bit, subtract and normalise
+ *
+	@param r BIG number normalised output
+	@param a BIG number to be subtracted from
+	@param m BIG number to be shifted and subtracted
+	@return sign of r
+ */
+extern int BIG_XXX_ssn(BIG_XXX r,BIG_XXX a, BIG_XXX m);
+
+/**	@brief Fast shifts a BIG right by a small number of bits - input must be normalised, output will be normalised
+ *
+	The number of bits to be shifted must be less than BASEBITS
+	@param x BIG number to be shifted
+	@param s Number of bits to shift
+	@return Shifted out bits
+ */
+extern int BIG_XXX_fshr(BIG_XXX x,int s);
+/**	@brief Shifts a DBIG right by any number of bits - input must be normalised, output normalised
+ *
+	@param x DBIG number to be shifted
+	@param s Number of bits to shift
+ */
+extern void BIG_XXX_dshr(DBIG_XXX x,int s);
+/**	@brief Splits a DBIG into two BIGs - input must be normalised, outputs normalised
+ *
+	Internal function. The value of s must be approximately in the middle of the DBIG.
+	Typically used to extract z mod 2^MODBITS and z/2^MODBITS
+	@param x BIG number, top half of z
+	@param y BIG number, bottom half of z
+	@param z DBIG number to be split in two.
+	@param s Bit position at which to split
+	@return carry-out from top half
+ */
+extern chunk BIG_XXX_split(BIG_XXX x,BIG_XXX y,DBIG_XXX z,int s);
+/**	@brief Normalizes a BIG number - output normalised
+ *
+	All digits of the input BIG are reduced mod 2^BASEBITS
+	@param x BIG number to be normalised
+ */
+extern chunk BIG_XXX_norm(BIG_XXX x);
+/**	@brief Normalizes a DBIG number - output normalised
+ *
+	All digits of the input DBIG are reduced mod 2^BASEBITS
+	@param x DBIG number to be normalised
+ */
+extern void BIG_XXX_dnorm(DBIG_XXX x);
+/**	@brief Compares two BIG numbers. Inputs must be normalised externally
+ *
+	@param x first BIG number to be compared
+	@param y second BIG number to be compared
+	@return -1 is x<y, 0 if x=y, 1 if x>y
+ */
+extern int BIG_XXX_comp(BIG_XXX x,BIG_XXX y);
+/**	@brief Compares two DBIG numbers. Inputs must be normalised externally
+ *
+	@param x first DBIG number to be compared
+	@param y second DBIG number to be compared
+	@return -1 is x<y, 0 if x=y, 1 if x>y
+ */
+extern int BIG_XXX_dcomp(DBIG_XXX x,DBIG_XXX y);
+/**	@brief Calculate number of bits in a BIG - output normalised
+ *
+	@param x BIG number
+	@return Number of bits in x
+ */
+extern int BIG_XXX_nbits(BIG_XXX x);
+/**	@brief Calculate number of bits in a DBIG - output normalised
+ *
+	@param x DBIG number
+	@return Number of bits in x
+ */
+extern int BIG_XXX_dnbits(DBIG_XXX x);
+/**	@brief Reduce x mod n - input and output normalised
+ *
+	Slow but rarely used
+	@param x BIG number to be reduced mod n
+	@param n The modulus
+ */
+extern void BIG_XXX_mod(BIG_XXX x,BIG_XXX n);
+/**	@brief Divide x by n - output normalised
+ *
+	Slow but rarely used
+	@param x BIG number to be divided by n
+	@param n The Divisor
+ */
+extern void BIG_XXX_sdiv(BIG_XXX x,BIG_XXX n);
+/**	@brief  x=y mod n - output normalised
+ *
+	Slow but rarely used. y is destroyed.
+	@param x BIG number, on exit = y mod n
+	@param y DBIG number
+	@param n Modulus
+ */
+extern void BIG_XXX_dmod(BIG_XXX x,DBIG_XXX y,BIG_XXX n);
+/**	@brief  x=y/n - output normalised
+ *
+	Slow but rarely used. y is destroyed.
+	@param x BIG number, on exit = y/n
+	@param y DBIG number
+	@param n Modulus
+ */
+extern void BIG_XXX_ddiv(BIG_XXX x,DBIG_XXX y,BIG_XXX n);
+/**	@brief  return parity of BIG, that is the least significant bit
+ *
+	@param x BIG number
+	@return 0 or 1
+ */
+extern int BIG_XXX_parity(BIG_XXX x);
+/**	@brief  return i-th of BIG
+ *
+	@param x BIG number
+	@param i the bit of x to be returned
+	@return 0 or 1
+ */
+extern int BIG_XXX_bit(BIG_XXX x,int i);
+/**	@brief  return least significant bits of a BIG
+ *
+	@param x BIG number
+	@param n number of bits to return. Assumed to be less than BASEBITS.
+	@return least significant n bits as an integer
+ */
+extern int BIG_XXX_lastbits(BIG_XXX x,int n);
+/**	@brief  Create a random BIG from a random number generator
+ *
+	Assumes that the random number generator has been suitably initialised
+	@param x BIG number, on exit a random number
+	@param r A pointer to a Cryptographically Secure Random Number Generator
+ */
+extern void BIG_XXX_random(BIG_XXX x,csprng *r);
+/**	@brief  Create an unbiased random BIG from a random number generator, reduced with respect to a modulus
+ *
+	Assumes that the random number generator has been suitably initialised
+	@param x BIG number, on exit a random number
+	@param n The modulus
+	@param r A pointer to a Cryptographically Secure Random Number Generator
+ */
+extern void BIG_XXX_randomnum(BIG_XXX x,BIG_XXX n,csprng *r);
+/**	brief  return NAF (Non-Adjacent-Form) value as +/- 1, 3 or 5, inputs must be normalised
+ *
+	Given x and 3*x extracts NAF value from given bit position, and returns number of bits processed, and number of trailing zeros detected if any
+	param x BIG number
+	param x3 BIG number, three times x
+	param i bit position
+	param nbs pointer to integer returning number of bits processed
+	param nzs pointer to integer returning number of trailing 0s
+	return + or - 1, 3 or 5
+*/
+
+/**	@brief  Calculate x=y*z mod n
+ *
+	Slow method for modular multiplication
+	@param x BIG number, on exit = y*z mod n
+	@param y BIG number
+	@param z BIG number
+	@param n The BIG Modulus
+ */
+extern void BIG_XXX_modmul(BIG_XXX x,BIG_XXX y,BIG_XXX z,BIG_XXX n);
+/**	@brief  Calculate x=y/z mod n
+ *
+	Slow method for modular division
+	@param x BIG number, on exit = y/z mod n
+	@param y BIG number
+	@param z BIG number
+	@param n The BIG Modulus
+ */
+extern void BIG_XXX_moddiv(BIG_XXX x,BIG_XXX y,BIG_XXX z,BIG_XXX n);
+/**	@brief  Calculate x=y^2 mod n
+ *
+	Slow method for modular squaring
+	@param x BIG number, on exit = y^2 mod n
+	@param y BIG number
+	@param n The BIG Modulus
+ */
+extern void BIG_XXX_modsqr(BIG_XXX x,BIG_XXX y,BIG_XXX n);
+/**	@brief  Calculate x=-y mod n
+ *
+	Modular negation
+	@param x BIG number, on exit = -y mod n
+	@param y BIG number
+	@param n The BIG Modulus
+ */
+extern void BIG_XXX_modneg(BIG_XXX x,BIG_XXX y,BIG_XXX n);
+/**	@brief  Calculate jacobi Symbol (x/y)
+ *
+	@param x BIG number
+	@param y BIG number
+	@return Jacobi symbol, -1,0 or 1
+ */
+extern int BIG_XXX_jacobi(BIG_XXX x,BIG_XXX y);
+/**	@brief  Calculate x=1/y mod n
+ *
+	Modular Inversion - This is slow. Uses binary method.
+	@param x BIG number, on exit = 1/y mod n
+	@param y BIG number
+	@param n The BIG Modulus
+ */
+extern void BIG_XXX_invmodp(BIG_XXX x,BIG_XXX y,BIG_XXX n);
+/** @brief Calculate x=x mod 2^m
+ *
+	Truncation
+	@param x BIG number, on reduced mod 2^m
+	@param m new truncated size
+*/
+extern void BIG_XXX_mod2m(BIG_XXX x,int m);
+
+/**	@brief Calculates a*b+c+*d
+ *
+	Calculate partial product of a.b, add in carry c, and add total to d
+	@param x multiplier
+	@param y multiplicand
+	@param c carry
+	@param r pointer to accumulated bottom half of result
+	@return top half of result
+ */
+
+#ifdef dchunk
+
+/* Method required to calculate x*y+c+r, bottom half in r, top half returned */
+static inline chunk muladd_XXX(chunk x,chunk y,chunk c,chunk *r)
+{
+    dchunk prod=(dchunk)x*y+c+*r;
+    *r=(chunk)prod&BMASK_XXX;
+    return (chunk)(prod>>BASEBITS_XXX);
+}
+
+#else
+
+/* No integer type available that can store double the wordlength */
+/* accumulate partial products */
+
+static inline chunk muladd_XXX(chunk x,chunk y,chunk c,chunk *r)
+{
+    chunk x0,x1,y0,y1;
+    chunk bot,top,mid,carry;
+    x0=x&HMASK_XXX;
+    x1=(x>>HBITS_XXX);
+    y0=y&HMASK_XXX;
+    y1=(y>>HBITS_XXX);
+    bot=x0*y0;
+    top=x1*y1;
+    mid=x0*y1+x1*y0;
+    x0=mid&HMASK_XXX;
+    x1=(mid>>HBITS_XXX);
+    bot+=x0<<HBITS_XXX;
+    bot+=*r;
+    bot+=c;
+
+    top+=x1;
+    carry=bot>>BASEBITS_XXX;
+    bot&=BMASK_XXX;
+    top+=carry;
+
+    *r=bot;
+    return top;
+}
+
+#endif
+
+
+#endif
diff --git a/version3/c/config16.py b/version3/c/config16.py
new file mode 100644
index 0000000..6ad7270
--- /dev/null
+++ b/version3/c/config16.py
@@ -0,0 +1,367 @@
+import os
+import sys
+
+deltext=""
+if sys.platform.startswith("linux")  :
+	deltext="rm"
+	copytext="cp"
+if sys.platform.startswith("darwin")  :
+	deltext="rm"
+	copytext="cp"
+if sys.platform.startswith("win") :
+	deltext="del"
+	copytext="copy"
+
+def replace(namefile,oldtext,newtext):
+	f = open(namefile,'r')
+	filedata = f.read()
+	f.close()
+
+	newdata = filedata.replace(oldtext,newtext)
+
+	f = open(namefile,'w')
+	f.write(newdata)
+	f.close()
+
+
+def rsaset(tb,tff,nb,base,ml) :
+	bd=tb+"_"+base
+	fnameh="config_big_"+bd+".h"
+	os.system(copytext+" config_big.h "+fnameh)
+	replace(fnameh,"XXX",bd)
+	replace(fnameh,"@NB@",nb)
+	replace(fnameh,"@BASE@",base)
+
+	fnameh="config_ff_"+tff+".h"
+	os.system(copytext+" config_ff.h "+fnameh)
+	replace(fnameh,"XXX",bd)
+	replace(fnameh,"WWW",tff)
+	replace(fnameh,"@ML@",ml);
+
+	fnamec="big_"+bd+".c"
+	fnameh="big_"+bd+".h"
+
+	os.system(copytext+" big.c "+fnamec)
+	os.system(copytext+" big.h "+fnameh)
+
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"XXX",bd)
+	os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+	fnamec="ff_"+tff+".c"
+	fnameh="ff_"+tff+".h"
+
+	os.system(copytext+" ff.c "+fnamec)
+	os.system(copytext+" ff.h "+fnameh)
+
+	replace(fnamec,"WWW",tff)
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"WWW",tff)
+	replace(fnameh,"XXX",bd)
+	os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+	fnamec="rsa_"+tff+".c"
+	fnameh="rsa_"+tff+".h"
+
+	os.system(copytext+" rsa.c "+fnamec)
+	os.system(copytext+" rsa.h "+fnameh)
+
+	replace(fnamec,"WWW",tff)
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"WWW",tff)
+	replace(fnameh,"XXX",bd)
+	os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+def curveset(tb,tf,tc,nb,base,nbt,m8,mt,ct,pf,stw,sx,cs) :
+	bd=tb+"_"+base
+	fnameh="config_big_"+bd+".h"
+	os.system(copytext+" config_big.h "+fnameh)
+	replace(fnameh,"XXX",bd)
+	replace(fnameh,"@NB@",nb)
+	replace(fnameh,"@BASE@",base)
+
+	fnameh="config_field_"+tf+".h"
+	os.system(copytext+" config_field.h "+fnameh)
+	replace(fnameh,"XXX",bd)
+	replace(fnameh,"YYY",tf)
+	replace(fnameh,"@NBT@",nbt)
+	replace(fnameh,"@M8@",m8)
+	replace(fnameh,"@MT@",mt)
+
+	ib=int(base)
+	inb=int(nb)
+	inbt=int(nbt)
+	sh=ib*(1+((8*inb-1)//ib))-inbt
+	if sh > 6 :
+		sh=6
+	replace(fnameh,"@SH@",str(sh))
+
+	fnameh="config_curve_"+tc+".h"	
+	os.system(copytext+" config_curve.h "+fnameh)
+	replace(fnameh,"XXX",bd)
+	replace(fnameh,"YYY",tf)
+	replace(fnameh,"ZZZ",tc)
+	replace(fnameh,"@CT@",ct)
+	replace(fnameh,"@PF@",pf)
+
+	replace(fnameh,"@ST@",stw)
+	replace(fnameh,"@SX@",sx)
+	replace(fnameh,"@CS@",cs)
+
+	fnamec="big_"+bd+".c"
+	fnameh="big_"+bd+".h"
+
+	os.system(copytext+" big.c "+fnamec)
+	os.system(copytext+" big.h "+fnameh)
+
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"XXX",bd)
+	os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+	fnamec="fp_"+tf+".c"
+	fnameh="fp_"+tf+".h"
+
+	os.system(copytext+" fp.c "+fnamec)
+	os.system(copytext+" fp.h "+fnameh)
+
+	replace(fnamec,"YYY",tf)
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"YYY",tf)
+	replace(fnameh,"XXX",bd)
+	os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+	os.system("gcc -O3 -std=c99 -c rom_field_"+tf+".c");
+
+	fnamec="ecp_"+tc+".c"
+	fnameh="ecp_"+tc+".h"
+
+	os.system(copytext+" ecp.c "+fnamec)
+	os.system(copytext+" ecp.h "+fnameh)
+
+	replace(fnamec,"ZZZ",tc)
+	replace(fnamec,"YYY",tf)
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"ZZZ",tc)
+	replace(fnameh,"YYY",tf)
+	replace(fnameh,"XXX",bd)
+	os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+	fnamec="ecdh_"+tc+".c"
+	fnameh="ecdh_"+tc+".h"
+
+	os.system(copytext+" ecdh.c "+fnamec)
+	os.system(copytext+" ecdh.h "+fnameh)
+
+	replace(fnamec,"ZZZ",tc)
+	replace(fnamec,"YYY",tf)
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"ZZZ",tc)
+	replace(fnameh,"YYY",tf)
+	replace(fnameh,"XXX",bd)
+	os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+	os.system("gcc -O3 -std=c99 -c rom_curve_"+tc+".c");
+
+	if pf != "NOT" :
+		fnamec="fp2_"+tf+".c"
+		fnameh="fp2_"+tf+".h"
+
+		os.system(copytext+" fp2.c "+fnamec)
+		os.system(copytext+" fp2.h "+fnameh)
+		replace(fnamec,"YYY",tf)
+		replace(fnamec,"XXX",bd)
+		replace(fnameh,"YYY",tf)
+		replace(fnameh,"XXX",bd)
+		os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+		fnamec="fp4_"+tf+".c"
+		fnameh="fp4_"+tf+".h"
+
+		os.system(copytext+" fp4.c "+fnamec)
+		os.system(copytext+" fp4.h "+fnameh)
+		replace(fnamec,"YYY",tf)
+		replace(fnamec,"XXX",bd)
+		replace(fnamec,"ZZZ",tc)
+		replace(fnameh,"YYY",tf)
+		replace(fnameh,"XXX",bd)
+		replace(fnameh,"ZZZ",tc)
+		os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+		fnamec="fp12_"+tf+".c"
+		fnameh="fp12_"+tf+".h"
+
+		os.system(copytext+" fp12.c "+fnamec)
+		os.system(copytext+" fp12.h "+fnameh)
+		replace(fnamec,"YYY",tf)
+		replace(fnamec,"XXX",bd)
+		replace(fnameh,"YYY",tf)
+		replace(fnameh,"XXX",bd)
+		os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+		fnamec="ecp2_"+tc+".c"
+		fnameh="ecp2_"+tc+".h"
+
+		os.system(copytext+" ecp2.c "+fnamec)
+		os.system(copytext+" ecp2.h "+fnameh)
+		replace(fnamec,"ZZZ",tc)
+		replace(fnamec,"YYY",tf)
+		replace(fnamec,"XXX",bd)
+		replace(fnameh,"ZZZ",tc)
+		replace(fnameh,"YYY",tf)
+		replace(fnameh,"XXX",bd)
+		os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+		fnamec="pair_"+tc+".c"
+		fnameh="pair_"+tc+".h"
+
+		os.system(copytext+" pair.c "+fnamec)
+		os.system(copytext+" pair.h "+fnameh)
+		replace(fnamec,"ZZZ",tc)
+		replace(fnamec,"YYY",tf)
+		replace(fnamec,"XXX",bd)
+		replace(fnameh,"ZZZ",tc)
+		replace(fnameh,"YYY",tf)
+		replace(fnameh,"XXX",bd)
+		os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+		fnamec="mpin_"+tc+".c"
+		fnameh="mpin_"+tc+".h"
+
+		os.system(copytext+" mpin.c "+fnamec)
+		os.system(copytext+" mpin.h "+fnameh)
+		replace(fnamec,"ZZZ",tc)
+		replace(fnamec,"YYY",tf)
+		replace(fnamec,"XXX",bd)
+		replace(fnameh,"ZZZ",tc)
+		replace(fnameh,"YYY",tf)
+		replace(fnameh,"XXX",bd)
+		os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+replace("arch.h","@WL@","16")
+print("Elliptic Curves")
+print("1. ED25519")
+print("2. NUMS256E")
+
+print("Pairing-Friendly Elliptic Curves")
+print("3. BN254")
+print("4. BN254CX")
+
+print("RSA")
+print("5. RSA2048")
+
+
+selection=[]
+ptr=0
+max=6
+
+curve_selected=False
+pfcurve_selected=False
+rsa_selected=False
+
+while ptr<max:
+	x=int(input("Choose a Scheme to support - 0 to finish: "))
+	if x == 0:
+		break
+#	print("Choice= ",x)
+	already=False
+	for i in range(0,ptr):
+		if x==selection[i]:
+			already=True
+			break
+	if already:
+		continue
+	
+	selection.append(x)
+	ptr=ptr+1
+
+# curveset(big,field,curve,big_length_bytes,bits_in_base,modulus_bits,modulus_mod_8,modulus_type,curve_type,pairing_friendly,sextic twist,sign of x)
+# for each curve give names for big, field and curve. In many cases the latter two will be the same. 
+# Typically "big" is the size in bits, always a multiple of 8, "field" describes the modulus, and "curve" is the common name for the elliptic curve   
+# big_length_bytes is "big" divided by 8
+# Next give the number base used for 16 bit architectures, as n where the base is 2^n (note that these must be fixed for the same "big" name, if is ever re-used for another curve)
+# modulus_bits is the bit length of the modulus, typically the same or slightly smaller than "big"
+# modulus_mod_8 is the remainder when the modulus is divided by 8
+# modulus_type is NOT_SPECIAL, or PSEUDO_MERSENNE, or MONTGOMERY_Friendly, or GENERALISED_MERSENNE (supported for GOLDILOCKS only)
+# curve_type is WEIERSTRASS, EDWARDS or MONTGOMERY
+# pairing_friendly is BN, BLS or NOT (if not pairing friendly)
+# if pairing friendly. M or D type twist, and sign of the family parameter x
+
+	if x==1:
+		curveset("256","25519","ED25519","32","13","255","5","PSEUDO_MERSENNE","EDWARDS","NOT","","","128")
+		curve_selected=True
+	if x==2:
+		curveset("256","256PME","NUMS256E","32","13","256","3","PSEUDO_MERSENNE","EDWARDS","NOT","","","128")
+		curve_selected=True
+
+
+	if x==3:
+		curveset("256","BN254","BN254","32","13","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+	if x==4:
+		curveset("256","BN254CX","BN254CX","32","13","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+
+# rsaset(big,ring,big_length_bytes,bits_in_base,multiplier)
+# for each choice give distinct names for "big" and "ring".
+# Typically "big" is the length in bits of the underlying big number type
+# "ring" is the RSA modulus size = "big" times 2^m
+# big_length_bytes is "big" divided by 8
+# Next give the number base used for 16 bit architecture, as n where the base is 2^n
+# multiplier is 2^m (see above)
+
+# There are choices here, different ways of getting the same result, but some faster than others
+	if x==5:
+		#256 is slower but may allow reuse of 256-bit BIGs used for elliptic curve
+		#512 is faster.. but best is 1024
+		rsaset("256","2048","32","13","8")
+		rsa_selected=True
+
+
+os.system(deltext+" big.*")
+os.system(deltext+" fp.*")
+os.system(deltext+" ecp.*")
+os.system(deltext+" ecdh.*")
+os.system(deltext+" ff.*")
+os.system(deltext+" rsa.*")
+os.system(deltext+" config_big.h")
+os.system(deltext+" config_field.h")
+os.system(deltext+" config_curve.h")
+os.system(deltext+" config_ff.h")
+os.system(deltext+" fp2.*")
+os.system(deltext+" fp4.*")
+os.system(deltext+" fp12.*")
+os.system(deltext+" ecp2.*")
+os.system(deltext+" pair.*")
+os.system(deltext+" mpin.*")
+
+# create library
+os.system("gcc -O3 -std=c99 -c randapi.c")
+if curve_selected :
+	os.system("gcc -O3 -std=c99 -c ecdh_support.c")
+if rsa_selected :
+	os.system("gcc -O3 -std=c99 -c rsa_support.c")
+if pfcurve_selected :
+	os.system("gcc -O3 -std=c99 -c pbc_support.c")
+
+os.system("gcc -O3 -std=c99 -c hash.c")
+os.system("gcc -O3 -std=c99 -c rand.c")
+os.system("gcc -O3 -std=c99 -c oct.c")
+os.system("gcc -O3 -std=c99 -c aes.c")
+os.system("gcc -O3 -std=c99 -c gcm.c")
+os.system("gcc -O3 -std=c99 -c newhope.c")
+
+if sys.platform.startswith("win") :
+	os.system("for %i in (*.o) do @echo %~nxi >> f.list")
+	os.system("ar rc amcl.a @f.list")
+	os.system(deltext+" f.list")
+
+else :
+	os.system("ar rc amcl.a *.o")
+
+os.system(deltext+" *.o")
+
+
+#print("Your section was ");	
+#for i in range(0,ptr):
+#	print (selection[i])
+
diff --git a/version3/c/config32.py b/version3/c/config32.py
new file mode 100644
index 0000000..ebefbff
--- /dev/null
+++ b/version3/c/config32.py
@@ -0,0 +1,645 @@
+import os
+import sys
+
+deltext=""
+if sys.platform.startswith("linux")  :
+	deltext="rm"
+	copytext="cp"
+if sys.platform.startswith("darwin")  :
+	deltext="rm"
+	copytext="cp"
+if sys.platform.startswith("win") :
+	deltext="del"
+	copytext="copy"
+
+def replace(namefile,oldtext,newtext):
+	f = open(namefile,'r')
+	filedata = f.read()
+	f.close()
+
+	newdata = filedata.replace(oldtext,newtext)
+
+	f = open(namefile,'w')
+	f.write(newdata)
+	f.close()
+
+
+def rsaset(tb,tff,nb,base,ml) :
+	bd=tb+"_"+base
+	fnameh="config_big_"+bd+".h"
+	os.system(copytext+" config_big.h "+fnameh)
+	replace(fnameh,"XXX",bd)
+	replace(fnameh,"@NB@",nb)
+	replace(fnameh,"@BASE@",base)
+
+	fnameh="config_ff_"+tff+".h"
+	os.system(copytext+" config_ff.h "+fnameh)
+	replace(fnameh,"XXX",bd)
+	replace(fnameh,"WWW",tff)
+	replace(fnameh,"@ML@",ml);
+
+	fnamec="big_"+bd+".c"
+	fnameh="big_"+bd+".h"
+
+	os.system(copytext+" big.c "+fnamec)
+	os.system(copytext+" big.h "+fnameh)
+
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"XXX",bd)
+	os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+	fnamec="ff_"+tff+".c"
+	fnameh="ff_"+tff+".h"
+
+	os.system(copytext+" ff.c "+fnamec)
+	os.system(copytext+" ff.h "+fnameh)
+
+	replace(fnamec,"WWW",tff)
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"WWW",tff)
+	replace(fnameh,"XXX",bd)
+	os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+	fnamec="rsa_"+tff+".c"
+	fnameh="rsa_"+tff+".h"
+
+	os.system(copytext+" rsa.c "+fnamec)
+	os.system(copytext+" rsa.h "+fnameh)
+
+	replace(fnamec,"WWW",tff)
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"WWW",tff)
+	replace(fnameh,"XXX",bd)
+	os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+def curveset(tb,tf,tc,nb,base,nbt,m8,mt,ct,pf,stw,sx,cs) :
+	bd=tb+"_"+base
+
+	fnameh="config_big_"+bd+".h"
+	os.system(copytext+" config_big.h "+fnameh)
+
+	replace(fnameh,"XXX",bd)
+	replace(fnameh,"@NB@",nb)
+	replace(fnameh,"@BASE@",base)
+
+
+	fnameh="config_field_"+tf+".h"
+	os.system(copytext+" config_field.h "+fnameh)
+	replace(fnameh,"XXX",bd)
+	replace(fnameh,"YYY",tf)
+	replace(fnameh,"@NBT@",nbt)
+	replace(fnameh,"@M8@",m8)
+	replace(fnameh,"@MT@",mt)
+
+	ib=int(base)
+
+	ib=int(base)
+	inb=int(nb)
+	inbt=int(nbt)
+	sh=ib*(1+((8*inb-1)//ib))-inbt
+	if sh > 14 :
+		sh=14
+	replace(fnameh,"@SH@",str(sh))
+
+	fnameh="config_curve_"+tc+".h"	
+	os.system(copytext+" config_curve.h "+fnameh)
+	replace(fnameh,"XXX",bd)
+	replace(fnameh,"YYY",tf)
+	replace(fnameh,"ZZZ",tc)
+	replace(fnameh,"@CT@",ct)
+	replace(fnameh,"@PF@",pf)
+
+	replace(fnameh,"@ST@",stw)
+	replace(fnameh,"@SX@",sx)
+	replace(fnameh,"@CS@",cs)
+
+	fnamec="big_"+bd+".c"
+	fnameh="big_"+bd+".h"
+
+	os.system(copytext+" big.c "+fnamec)
+	os.system(copytext+" big.h "+fnameh)
+
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"XXX",bd)
+	os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+	fnamec="fp_"+tf+".c"
+	fnameh="fp_"+tf+".h"
+
+	os.system(copytext+" fp.c "+fnamec)
+	os.system(copytext+" fp.h "+fnameh)
+
+	replace(fnamec,"YYY",tf)
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"YYY",tf)
+	replace(fnameh,"XXX",bd)
+	os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+	os.system("gcc -O3 -std=c99 -c rom_field_"+tf+".c");
+
+	fnamec="ecp_"+tc+".c"
+	fnameh="ecp_"+tc+".h"
+
+	os.system(copytext+" ecp.c "+fnamec)
+	os.system(copytext+" ecp.h "+fnameh)
+
+	replace(fnamec,"ZZZ",tc)
+	replace(fnamec,"YYY",tf)
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"ZZZ",tc)
+	replace(fnameh,"YYY",tf)
+	replace(fnameh,"XXX",bd)
+	os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+	fnamec="ecdh_"+tc+".c"
+	fnameh="ecdh_"+tc+".h"
+
+	os.system(copytext+" ecdh.c "+fnamec)
+	os.system(copytext+" ecdh.h "+fnameh)
+
+	replace(fnamec,"ZZZ",tc)
+	replace(fnamec,"YYY",tf)
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"ZZZ",tc)
+	replace(fnameh,"YYY",tf)
+	replace(fnameh,"XXX",bd)
+	os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+	os.system("gcc -O3 -std=c99 -c rom_curve_"+tc+".c");
+
+	if pf != "NOT" :
+		fnamec="fp2_"+tf+".c"
+		fnameh="fp2_"+tf+".h"
+
+		os.system(copytext+" fp2.c "+fnamec)
+		os.system(copytext+" fp2.h "+fnameh)
+		replace(fnamec,"YYY",tf)
+		replace(fnamec,"XXX",bd)
+		replace(fnameh,"YYY",tf)
+		replace(fnameh,"XXX",bd)
+		os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+		fnamec="fp4_"+tf+".c"
+		fnameh="fp4_"+tf+".h"
+
+		os.system(copytext+" fp4.c "+fnamec)
+		os.system(copytext+" fp4.h "+fnameh)
+		replace(fnamec,"YYY",tf)
+		replace(fnamec,"XXX",bd)
+		replace(fnamec,"ZZZ",tc)
+		replace(fnameh,"YYY",tf)
+		replace(fnameh,"XXX",bd)
+		replace(fnameh,"ZZZ",tc)
+		os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+
+		if cs == "128" :
+			fnamec="fp12_"+tf+".c"
+			fnameh="fp12_"+tf+".h"
+
+			os.system(copytext+" fp12.c "+fnamec)
+			os.system(copytext+" fp12.h "+fnameh)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+			fnamec="ecp2_"+tc+".c"
+			fnameh="ecp2_"+tc+".h"
+
+			os.system(copytext+" ecp2.c "+fnamec)
+			os.system(copytext+" ecp2.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+			fnamec="pair_"+tc+".c"
+			fnameh="pair_"+tc+".h"
+
+			os.system(copytext+" pair.c "+fnamec)
+			os.system(copytext+" pair.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+			fnamec="mpin_"+tc+".c"
+			fnameh="mpin_"+tc+".h"
+
+			os.system(copytext+" mpin.c "+fnamec)
+			os.system(copytext+" mpin.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+		if cs == "192" :
+			fnamec="fp8_"+tf+".c"
+			fnameh="fp8_"+tf+".h"
+
+			os.system(copytext+" fp8.c "+fnamec)
+			os.system(copytext+" fp8.h "+fnameh)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+
+			fnamec="fp24_"+tf+".c"
+			fnameh="fp24_"+tf+".h"
+
+			os.system(copytext+" fp24.c "+fnamec)
+			os.system(copytext+" fp24.h "+fnameh)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+			fnamec="ecp4_"+tc+".c"
+			fnameh="ecp4_"+tc+".h"
+
+			os.system(copytext+" ecp4.c "+fnamec)
+			os.system(copytext+" ecp4.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+			fnamec="pair192_"+tc+".c"
+			fnameh="pair192_"+tc+".h"
+
+			os.system(copytext+" pair192.c "+fnamec)
+			os.system(copytext+" pair192.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+			fnamec="mpin192_"+tc+".c"
+			fnameh="mpin192_"+tc+".h"
+
+			os.system(copytext+" mpin192.c "+fnamec)
+			os.system(copytext+" mpin192.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("gcc -O3 -std=c99 -c "+fnamec)		
+
+		if cs == "256" :
+
+			fnamec="fp8_"+tf+".c"
+			fnameh="fp8_"+tf+".h"
+
+			os.system(copytext+" fp8.c "+fnamec)
+			os.system(copytext+" fp8.h "+fnameh)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+
+			fnamec="ecp8_"+tc+".c"
+			fnameh="ecp8_"+tc+".h"
+
+			os.system(copytext+" ecp8.c "+fnamec)
+			os.system(copytext+" ecp8.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+
+			fnamec="fp16_"+tf+".c"
+			fnameh="fp16_"+tf+".h"
+
+			os.system(copytext+" fp16.c "+fnamec)
+			os.system(copytext+" fp16.h "+fnameh)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+
+			fnamec="fp48_"+tf+".c"
+			fnameh="fp48_"+tf+".h"
+
+			os.system(copytext+" fp48.c "+fnamec)
+			os.system(copytext+" fp48.h "+fnameh)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+
+			fnamec="pair256_"+tc+".c"
+			fnameh="pair256_"+tc+".h"
+
+			os.system(copytext+" pair256.c "+fnamec)
+			os.system(copytext+" pair256.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+			fnamec="mpin256_"+tc+".c"
+			fnameh="mpin256_"+tc+".h"
+
+			os.system(copytext+" mpin256.c "+fnamec)
+			os.system(copytext+" mpin256.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("gcc -O3 -std=c99 -c "+fnamec)				
+
+replace("arch.h","@WL@","32")
+print("Elliptic Curves")
+print("1. ED25519")
+print("2. C25519")
+print("3. NIST256")
+print("4. BRAINPOOL")
+print("5. ANSSI")
+print("6. HIFIVE")
+print("7. GOLDILOCKS")
+print("8. NIST384")
+print("9. C41417")
+print("10. NIST521\n")
+print("11. NUMS256W")
+print("12. NUMS256E")
+print("13. NUMS384W")
+print("14. NUMS384E")
+print("15. NUMS512W")
+print("16. NUMS512E")
+print("17. SECP256K1\n")
+
+print("Pairing-Friendly Elliptic Curves")
+print("18. BN254")
+print("19. BN254CX")
+print("20. BLS383")
+print("21. BLS381")
+print("22. FP256BN")
+print("23. FP512BN")
+print("24. BLS461\n")
+print("25. BLS24")
+print("26. BLS48\n")
+
+print("RSA")
+print("27. RSA2048")
+print("28. RSA3072")
+print("29. RSA4096")
+
+selection=[]
+ptr=0
+max=30
+
+curve_selected=False
+pfcurve_selected=False
+rsa_selected=False
+
+while ptr<max:
+	x=int(input("Choose a Scheme to support - 0 to finish: "))
+	if x == 0:
+		break
+#	print("Choice= ",x)
+	already=False
+	for i in range(0,ptr):
+		if x==selection[i]:
+			already=True
+			break
+	if already:
+		continue
+	
+	selection.append(x)
+	ptr=ptr+1
+
+# curveset(big,field,curve,big_length_bytes,bits_in_base,modulus_bits,modulus_mod_8,modulus_type,curve_type,pairing_friendly,sextic twist,sign of x,curve security)
+# for each curve give names for big, field and curve. In many cases the latter two will be the same. 
+# Typically "big" is the size in bits, always a multiple of 8, "field" describes the modulus, and "curve" is the common name for the elliptic curve   
+# big_length_bytes is "big" divided by 8
+# Next give the number base used for 32 bit architectures, as n where the base is 2^n (note that these must be fixed for the same "big" name, if is ever re-used for another curve)
+# modulus_bits is the bit length of the modulus, typically the same or slightly smaller than "big"
+# modulus_mod_8 is the remainder when the modulus is divided by 8
+# modulus_type is NOT_SPECIAL, or PSEUDO_MERSENNE, or MONTGOMERY_Friendly, or GENERALISED_MERSENNE (supported for GOLDILOCKS only)
+# curve_type is WEIERSTRASS, EDWARDS or MONTGOMERY
+# pairing_friendly is BN, BLS or NOT (if not pairing friendly)
+# if pairing friendly. M or D type twist, and sign of the family parameter x
+# curve security is AES equiavlent, rounded up.
+
+	if x==1:
+		curveset("256","25519","ED25519","32","29","255","5","PSEUDO_MERSENNE","EDWARDS","NOT","","","128")
+		curve_selected=True
+	if x==2:
+		curveset("256","25519","C25519","32","29","255","5","PSEUDO_MERSENNE","MONTGOMERY","NOT","","","128")
+		curve_selected=True
+	if x==3:
+		curveset("256","NIST256","NIST256","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","128")
+		curve_selected=True
+	if x==4:
+		curveset("256","BRAINPOOL","BRAINPOOL","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","128")
+		curve_selected=True
+	if x==5:
+		curveset("256","ANSSI","ANSSI","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","128")
+		curve_selected=True
+
+	if x==6:
+		curveset("336","HIFIVE","HIFIVE","42","29","336","5","PSEUDO_MERSENNE","EDWARDS","NOT","","","192")
+		curve_selected=True
+	if x==7:
+		curveset("448","GOLDILOCKS","GOLDILOCKS","56","29","448","7","GENERALISED_MERSENNE","EDWARDS","NOT","","","256")
+		curve_selected=True
+	if x==8:
+		curveset("384","NIST384","NIST384","48","29","384","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","192")
+		curve_selected=True
+	if x==9:
+		curveset("416","C41417","C41417","52","29","414","7","PSEUDO_MERSENNE","EDWARDS","NOT","","","256")
+		curve_selected=True
+	if x==10:
+		curveset("528","NIST521","NIST521","66","28","521","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","256")
+		curve_selected=True
+
+	if x==11:
+		curveset("256","256PMW","NUMS256W","32","28","256","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","128")
+		curve_selected=True
+	if x==12:
+		curveset("256","256PME","NUMS256E","32","29","256","3","PSEUDO_MERSENNE","EDWARDS","NOT","","","128")
+		curve_selected=True
+	if x==13:
+		curveset("384","384PM","NUMS384W","48","29","384","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","192")
+		curve_selected=True
+	if x==14:
+		curveset("384","384PM","NUMS384E","48","29","384","3","PSEUDO_MERSENNE","EDWARDS","NOT","","","192")
+		curve_selected=True
+	if x==15:
+		curveset("512","512PM","NUMS512W","64","29","512","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","256")
+		curve_selected=True
+	if x==16:
+		curveset("512","512PM","NUMS512E","64","29","512","7","PSEUDO_MERSENNE","EDWARDS","NOT","","","256")
+		curve_selected=True
+
+	if x==17:
+		curveset("256","SECP256K1","SECP256K1","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","128")
+		curve_selected=True
+
+
+	if x==18:
+		curveset("256","BN254","BN254","32","28","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+	if x==19:
+		curveset("256","BN254CX","BN254CX","32","28","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+	if x==20:
+		curveset("384","BLS383","BLS383","48","29","383","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","128")
+		pfcurve_selected=True
+
+	if x==21:
+		curveset("384","BLS381","BLS381","48","29","381","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+
+	if x==22:
+		curveset("256","FP256BN","FP256BN","32","28","256","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+	if x==23:
+		curveset("512","FP512BN","FP512BN","64","29","512","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","POSITIVEX","128")
+		pfcurve_selected=True
+# https://eprint.iacr.org/2017/334.pdf
+	if x==24:
+		curveset("464","BLS461","BLS461","58","28","461","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+
+	if x==25:
+		curveset("480","BLS24","BLS24","60","29","479","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","192")
+		pfcurve_selected=True
+
+
+	if x==26:
+		curveset("560","BLS48","BLS48","70","29","556","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","256")
+		pfcurve_selected=True
+
+
+# rsaset(big,ring,big_length_bytes,bits_in_base,multiplier)
+# for each choice give distinct names for "big" and "ring".
+# Typically "big" is the length in bits of the underlying big number type
+# "ring" is the RSA modulus size = "big" times 2^m
+# big_length_bytes is "big" divided by 8
+# Next give the number base used for 32 bit architecture, as n where the base is 2^n
+# multiplier is 2^m (see above)
+
+# There are choices here, different ways of getting the same result, but some faster than others
+	if x==27:
+		#256 is slower but may allow reuse of 256-bit BIGs used for elliptic curve
+		#512 is faster.. but best is 1024
+		rsaset("1024","2048","128","28","2")
+		#rsaset("512","2048","64","29","4")
+		#rsaset("256","2048","32","29","8")
+		rsa_selected=True
+	if x==28:
+		rsaset("384","3072","48","28","8")
+		rsa_selected=True
+	if x==29:
+		#rsaset("256","4096","32","29","16")
+		rsaset("512","4096","64","29","8")
+		rsa_selected=True
+
+
+os.system(deltext+" big.*")
+os.system(deltext+" fp.*")
+os.system(deltext+" ecp.*")
+os.system(deltext+" ecdh.*")
+os.system(deltext+" ff.*")
+os.system(deltext+" rsa.*")
+os.system(deltext+" config_big.h")
+os.system(deltext+" config_field.h")
+os.system(deltext+" config_curve.h")
+os.system(deltext+" config_ff.h")
+os.system(deltext+" fp2.*")
+os.system(deltext+" fp4.*")
+os.system(deltext+" fp8.*")
+os.system(deltext+" fp16.*")
+
+
+os.system(deltext+" fp12.*")
+os.system(deltext+" fp24.*")
+os.system(deltext+" fp48.*")
+
+os.system(deltext+" ecp2.*")
+os.system(deltext+" ecp4.*")
+os.system(deltext+" ecp8.*")
+
+os.system(deltext+" pair.*")
+os.system(deltext+" mpin.*")
+
+os.system(deltext+" pair192.*")
+os.system(deltext+" mpin192.*")
+
+os.system(deltext+" pair256.*")
+os.system(deltext+" mpin256.*")
+
+# create library
+os.system("gcc -O3 -std=c99 -c randapi.c")
+if curve_selected :
+	os.system("gcc -O3 -std=c99 -c ecdh_support.c")
+if rsa_selected :
+	os.system("gcc -O3 -std=c99 -c rsa_support.c")
+if pfcurve_selected :
+	os.system("gcc -O3 -std=c99 -c pbc_support.c")
+
+os.system("gcc -O3 -std=c99 -c hash.c")
+os.system("gcc -O3 -std=c99 -c rand.c")
+os.system("gcc -O3 -std=c99 -c oct.c")
+os.system("gcc -O3 -std=c99 -c aes.c")
+os.system("gcc -O3 -std=c99 -c gcm.c")
+os.system("gcc -O3 -std=c99 -c newhope.c")
+
+if sys.platform.startswith("win") :
+	os.system("for %i in (*.o) do @echo %~nxi >> f.list")
+	os.system("ar rc amcl.a @f.list")
+	os.system(deltext+" f.list")
+
+else :
+	os.system("ar rc amcl.a *.o")
+	
+os.system(deltext+" *.o")
+
+#print("Your section was ");	
+#for i in range(0,ptr):
+#	print (selection[i])
+
diff --git a/version3/c/config64.py b/version3/c/config64.py
new file mode 100644
index 0000000..af08df3
--- /dev/null
+++ b/version3/c/config64.py
@@ -0,0 +1,639 @@
+import os
+import sys
+
+deltext=""
+if sys.platform.startswith("linux")  :
+	deltext="rm"
+	copytext="cp"
+if sys.platform.startswith("darwin")  :
+	deltext="rm"
+	copytext="cp"
+if sys.platform.startswith("win") :
+	deltext="del"
+	copytext="copy"
+
+def replace(namefile,oldtext,newtext):
+	f = open(namefile,'r')
+	filedata = f.read()
+	f.close()
+
+	newdata = filedata.replace(oldtext,newtext)
+
+	f = open(namefile,'w')
+	f.write(newdata)
+	f.close()
+
+
+def rsaset(tb,tff,nb,base,ml) :
+	bd=tb+"_"+base
+	fnameh="config_big_"+bd+".h"
+	os.system(copytext+" config_big.h "+fnameh)
+	replace(fnameh,"XXX",bd)
+	replace(fnameh,"@NB@",nb)
+	replace(fnameh,"@BASE@",base)
+
+	fnameh="config_ff_"+tff+".h"
+	os.system(copytext+" config_ff.h "+fnameh)
+	replace(fnameh,"XXX",bd)
+	replace(fnameh,"WWW",tff)
+	replace(fnameh,"@ML@",ml);
+
+	fnamec="big_"+bd+".c"
+	fnameh="big_"+bd+".h"
+
+	os.system(copytext+" big.c "+fnamec)
+	os.system(copytext+" big.h "+fnameh)
+
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"XXX",bd)
+	os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+	fnamec="ff_"+tff+".c"
+	fnameh="ff_"+tff+".h"
+
+	os.system(copytext+" ff.c "+fnamec)
+	os.system(copytext+" ff.h "+fnameh)
+
+	replace(fnamec,"WWW",tff)
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"WWW",tff)
+	replace(fnameh,"XXX",bd)
+	os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+	fnamec="rsa_"+tff+".c"
+	fnameh="rsa_"+tff+".h"
+
+	os.system(copytext+" rsa.c "+fnamec)
+	os.system(copytext+" rsa.h "+fnameh)
+
+	replace(fnamec,"WWW",tff)
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"WWW",tff)
+	replace(fnameh,"XXX",bd)
+	os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+def curveset(tb,tf,tc,nb,base,nbt,m8,mt,ct,pf,stw,sx,cs) :
+	bd=tb+"_"+base
+	fnameh="config_big_"+bd+".h"
+	os.system(copytext+" config_big.h "+fnameh)
+	replace(fnameh,"XXX",bd)
+	replace(fnameh,"@NB@",nb)
+	replace(fnameh,"@BASE@",base)
+
+	fnameh="config_field_"+tf+".h"
+	os.system(copytext+" config_field.h "+fnameh)
+	replace(fnameh,"XXX",bd)
+	replace(fnameh,"YYY",tf)
+	replace(fnameh,"@NBT@",nbt)
+	replace(fnameh,"@M8@",m8)
+	replace(fnameh,"@MT@",mt)
+
+	ib=int(base)
+	inb=int(nb)
+	inbt=int(nbt)
+	sh=ib*(1+((8*inb-1)//ib))-inbt
+	if sh > 30 :
+		sh=30
+	replace(fnameh,"@SH@",str(sh))
+
+	fnameh="config_curve_"+tc+".h"	
+	os.system(copytext+" config_curve.h "+fnameh)
+	replace(fnameh,"XXX",bd)
+	replace(fnameh,"YYY",tf)
+	replace(fnameh,"ZZZ",tc)
+	replace(fnameh,"@CT@",ct)
+	replace(fnameh,"@PF@",pf)
+
+	replace(fnameh,"@ST@",stw)
+	replace(fnameh,"@SX@",sx)
+	replace(fnameh,"@CS@",cs)
+
+	fnamec="big_"+bd+".c"
+	fnameh="big_"+bd+".h"
+
+	os.system(copytext+" big.c "+fnamec)
+	os.system(copytext+" big.h "+fnameh)
+
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"XXX",bd)
+	os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+	fnamec="fp_"+tf+".c"
+	fnameh="fp_"+tf+".h"
+
+	os.system(copytext+" fp.c "+fnamec)
+	os.system(copytext+" fp.h "+fnameh)
+
+	replace(fnamec,"YYY",tf)
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"YYY",tf)
+	replace(fnameh,"XXX",bd)
+	os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+	os.system("gcc -O3 -std=c99 -c rom_field_"+tf+".c");
+
+	fnamec="ecp_"+tc+".c"
+	fnameh="ecp_"+tc+".h"
+
+	os.system(copytext+" ecp.c "+fnamec)
+	os.system(copytext+" ecp.h "+fnameh)
+
+	replace(fnamec,"ZZZ",tc)
+	replace(fnamec,"YYY",tf)
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"ZZZ",tc)
+	replace(fnameh,"YYY",tf)
+	replace(fnameh,"XXX",bd)
+	os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+	fnamec="ecdh_"+tc+".c"
+	fnameh="ecdh_"+tc+".h"
+
+	os.system(copytext+" ecdh.c "+fnamec)
+	os.system(copytext+" ecdh.h "+fnameh)
+
+	replace(fnamec,"ZZZ",tc)
+	replace(fnamec,"YYY",tf)
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"ZZZ",tc)
+	replace(fnameh,"YYY",tf)
+	replace(fnameh,"XXX",bd)
+	os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+	os.system("gcc -O3 -std=c99 -c rom_curve_"+tc+".c");
+
+	if pf != "NOT" :
+		fnamec="fp2_"+tf+".c"
+		fnameh="fp2_"+tf+".h"
+
+		os.system(copytext+" fp2.c "+fnamec)
+		os.system(copytext+" fp2.h "+fnameh)
+		replace(fnamec,"YYY",tf)
+		replace(fnamec,"XXX",bd)
+		replace(fnameh,"YYY",tf)
+		replace(fnameh,"XXX",bd)
+		os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+		fnamec="fp4_"+tf+".c"
+		fnameh="fp4_"+tf+".h"
+
+		os.system(copytext+" fp4.c "+fnamec)
+		os.system(copytext+" fp4.h "+fnameh)
+		replace(fnamec,"YYY",tf)
+		replace(fnamec,"XXX",bd)
+		replace(fnamec,"ZZZ",tc)
+		replace(fnameh,"YYY",tf)
+		replace(fnameh,"XXX",bd)
+		replace(fnameh,"ZZZ",tc)
+		os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+		if cs == "128" :
+			fnamec="fp12_"+tf+".c"
+			fnameh="fp12_"+tf+".h"
+
+			os.system(copytext+" fp12.c "+fnamec)
+			os.system(copytext+" fp12.h "+fnameh)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+			fnamec="ecp2_"+tc+".c"
+			fnameh="ecp2_"+tc+".h"
+
+			os.system(copytext+" ecp2.c "+fnamec)
+			os.system(copytext+" ecp2.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+			fnamec="pair_"+tc+".c"
+			fnameh="pair_"+tc+".h"
+
+			os.system(copytext+" pair.c "+fnamec)
+			os.system(copytext+" pair.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+			fnamec="mpin_"+tc+".c"
+			fnameh="mpin_"+tc+".h"
+
+			os.system(copytext+" mpin.c "+fnamec)
+			os.system(copytext+" mpin.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+		if cs == "192" :
+			fnamec="fp8_"+tf+".c"
+			fnameh="fp8_"+tf+".h"
+
+			os.system(copytext+" fp8.c "+fnamec)
+			os.system(copytext+" fp8.h "+fnameh)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+
+			fnamec="fp24_"+tf+".c"
+			fnameh="fp24_"+tf+".h"
+
+			os.system(copytext+" fp24.c "+fnamec)
+			os.system(copytext+" fp24.h "+fnameh)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+			fnamec="ecp4_"+tc+".c"
+			fnameh="ecp4_"+tc+".h"
+
+			os.system(copytext+" ecp4.c "+fnamec)
+			os.system(copytext+" ecp4.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+			fnamec="pair192_"+tc+".c"
+			fnameh="pair192_"+tc+".h"
+
+			os.system(copytext+" pair192.c "+fnamec)
+			os.system(copytext+" pair192.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+			fnamec="mpin192_"+tc+".c"
+			fnameh="mpin192_"+tc+".h"
+
+			os.system(copytext+" mpin192.c "+fnamec)
+			os.system(copytext+" mpin192.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+		if cs == "256" :
+
+			fnamec="fp8_"+tf+".c"
+			fnameh="fp8_"+tf+".h"
+
+			os.system(copytext+" fp8.c "+fnamec)
+			os.system(copytext+" fp8.h "+fnameh)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+
+			fnamec="ecp8_"+tc+".c"
+			fnameh="ecp8_"+tc+".h"
+
+			os.system(copytext+" ecp8.c "+fnamec)
+			os.system(copytext+" ecp8.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+
+			fnamec="fp16_"+tf+".c"
+			fnameh="fp16_"+tf+".h"
+
+			os.system(copytext+" fp16.c "+fnamec)
+			os.system(copytext+" fp16.h "+fnameh)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+
+			fnamec="fp48_"+tf+".c"
+			fnameh="fp48_"+tf+".h"
+
+			os.system(copytext+" fp48.c "+fnamec)
+			os.system(copytext+" fp48.h "+fnameh)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+
+			fnamec="pair256_"+tc+".c"
+			fnameh="pair256_"+tc+".h"
+
+			os.system(copytext+" pair256.c "+fnamec)
+			os.system(copytext+" pair256.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+			fnamec="mpin256_"+tc+".c"
+			fnameh="mpin256_"+tc+".h"
+
+			os.system(copytext+" mpin256.c "+fnamec)
+			os.system(copytext+" mpin256.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("gcc -O3 -std=c99 -c "+fnamec)
+
+replace("arch.h","@WL@","64")
+print("Elliptic Curves")
+print("1. ED25519")
+print("2. C25519")
+print("3. NIST256")
+print("4. BRAINPOOL")
+print("5. ANSSI")
+print("6. HIFIVE")
+print("7. GOLDILOCKS")
+print("8. NIST384")
+print("9. C41417")
+print("10. NIST521\n")
+print("11. NUMS256W")
+print("12. NUMS256E")
+print("13. NUMS384W")
+print("14. NUMS384E")
+print("15. NUMS512W")
+print("16. NUMS512E")
+print("17. SECP256K1\n")
+
+print("Pairing-Friendly Elliptic Curves")
+print("18. BN254")
+print("19. BN254CX")
+print("20. BLS383")
+print("21. BLS381")
+print("22. FP256BN")
+print("23. FP512BN")
+print("24. BLS461\n")
+print("25. BLS24")
+print("26. BLS48\n")
+
+print("RSA")
+print("27. RSA2048")
+print("28. RSA3072")
+print("29. RSA4096")
+
+selection=[]
+ptr=0
+max=30
+
+curve_selected=False
+pfcurve_selected=False
+rsa_selected=False
+
+while ptr<max:
+	x=int(input("Choose a Scheme to support - 0 to finish: "))
+	if x == 0:
+		break
+#	print("Choice= ",x)
+	already=False
+	for i in range(0,ptr):
+		if x==selection[i]:
+			already=True
+			break
+	if already:
+		continue
+	
+	selection.append(x)
+	ptr=ptr+1
+
+# curveset(big,field,curve,big_length_bytes,bits_in_base,modulus_bits,modulus_mod_8,modulus_type,curve_type,pairing_friendly,sextic twist,sign of x,curve security)
+# for each curve give names for big, field and curve. In many cases the latter two will be the same. 
+# Typically "big" is the size in bits, always a multiple of 8, "field" describes the modulus, and "curve" is the common name for the elliptic curve   
+# big_length_bytes is "big" divided by 8
+# Next give the number base used for 64 bit architectures, as n where the base is 2^n (note that these must be fixed for the same "big" name, if is ever re-used for another curve)
+# modulus_bits is the bit length of the modulus, typically the same or slightly smaller than "big"
+# modulus_mod_8 is the remainder when the modulus is divided by 8
+# modulus_type is NOT_SPECIAL, or PSEUDO_MERSENNE, or MONTGOMERY_Friendly, or GENERALISED_MERSENNE (supported for GOLDILOCKS only)
+# curve_type is WEIERSTRASS, EDWARDS or MONTGOMERY
+# pairing_friendly is BN, BLS or NOT (if not pairing friendly)
+# if pairing friendly. M or D type twist, and sign of the family parameter x
+# curve security is AES equiavlent, rounded up.
+
+	if x==1:
+		curveset("256","25519","ED25519","32","56","255","5","PSEUDO_MERSENNE","EDWARDS","NOT","","","128")
+		curve_selected=True
+	if x==2:
+		curveset("256","25519","C25519","32","56","255","5","PSEUDO_MERSENNE","MONTGOMERY","NOT","","","128")
+		curve_selected=True
+	if x==3:
+		curveset("256","NIST256","NIST256","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","128")
+		curve_selected=True
+	if x==4:
+		curveset("256","BRAINPOOL","BRAINPOOL","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","128")
+		curve_selected=True
+	if x==5:
+		curveset("256","ANSSI","ANSSI","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","128")
+		curve_selected=True
+
+	if x==6:
+		curveset("336","HIFIVE","HIFIVE","42","60","336","5","PSEUDO_MERSENNE","EDWARDS","NOT","","","128")
+		curve_selected=True
+	if x==7:
+		curveset("448","GOLDILOCKS","GOLDILOCKS","56","58","448","7","GENERALISED_MERSENNE","EDWARDS","NOT","","","128")
+		curve_selected=True
+	if x==8:
+		curveset("384","NIST384","NIST384","48","56","384","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","128")
+		curve_selected=True
+	if x==9:
+		curveset("416","C41417","C41417","52","60","414","7","PSEUDO_MERSENNE","EDWARDS","NOT","","","128")
+		curve_selected=True
+	if x==10:
+		curveset("528","NIST521","NIST521","66","60","521","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","128")
+		curve_selected=True
+
+	if x==11:
+		curveset("256","256PMW","NUMS256W","32","56","256","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","128")
+		curve_selected=True
+	if x==12:
+		curveset("256","256PME","NUMS256E","32","56","256","3","PSEUDO_MERSENNE","EDWARDS","NOT","","","128")
+		curve_selected=True
+	if x==13:
+		curveset("384","384PM","NUMS384W","48","56","384","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","128")
+		curve_selected=True
+	if x==14:
+		curveset("384","384PM","NUMS384E","48","56","384","3","PSEUDO_MERSENNE","EDWARDS","NOT","","","128")
+		curve_selected=True
+	if x==15:
+		curveset("512","512PM","NUMS512W","64","56","512","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","128")
+		curve_selected=True
+	if x==16:
+		curveset("512","512PM","NUMS512E","64","56","512","7","PSEUDO_MERSENNE","EDWARDS","NOT","","","128")
+		curve_selected=True
+
+	if x==17:
+		curveset("256","SECP256K1","SECP256K1","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","128")
+		curve_selected=True
+
+
+	if x==18:
+		curveset("256","BN254","BN254","32","56","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+	if x==19:
+		curveset("256","BN254CX","BN254CX","32","56","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+	if x==20:
+		curveset("384","BLS383","BLS383","48","58","383","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","128")
+		pfcurve_selected=True
+
+	if x==21:
+		curveset("384","BLS381","BLS381","48","58","381","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+
+
+	if x==22:
+		curveset("256","FP256BN","FP256BN","32","56","256","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+	if x==23:
+		curveset("512","FP512BN","FP512BN","64","60","512","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","POSITIVEX","128")
+		pfcurve_selected=True
+# https://eprint.iacr.org/2017/334.pdf
+	if x==24:
+		curveset("464","BLS461","BLS461","58","60","461","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+
+	if x==25:
+		curveset("480","BLS24","BLS24","60","56","479","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","192")
+		pfcurve_selected=True
+
+	if x==26:
+		curveset("560","BLS48","BLS48","70","58","556","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","256")
+		pfcurve_selected=True
+
+
+# rsaset(big,ring,big_length_bytes,bits_in_base,multiplier)
+# for each choice give distinct names for "big" and "ring".
+# Typically "big" is the length in bits of the underlying big number type
+# "ring" is the RSA modulus size = "big" times 2^m
+# big_length_bytes is "big" divided by 8
+# Next give the number base used for 64 bit architecture, as n where the base is 2^n
+# multiplier is 2^m (see above)
+
+# There are choices here, different ways of getting the same result, but some faster than others
+	if x==27:
+		#256 is slower but may allow reuse of 256-bit BIGs used for elliptic curve
+		#512 is faster.. but best is 1024
+		rsaset("1024","2048","128","58","2")
+		#rsaset("512","2048","64","60","4")
+		#rsaset("256","2048","32","56","8")
+		rsa_selected=True
+	if x==28:
+		rsaset("384","3072","48","56","8")
+		rsa_selected=True
+	if x==29:
+		#rsaset("256","4096","32","56","16")
+		rsaset("512","4096","64","60","8")
+		rsa_selected=True
+
+
+os.system(deltext+" big.*")
+os.system(deltext+" fp.*")
+os.system(deltext+" ecp.*")
+os.system(deltext+" ecdh.*")
+os.system(deltext+" ff.*")
+os.system(deltext+" rsa.*")
+os.system(deltext+" config_big.h")
+os.system(deltext+" config_field.h")
+os.system(deltext+" config_curve.h")
+os.system(deltext+" config_ff.h")
+os.system(deltext+" fp2.*")
+os.system(deltext+" fp4.*")
+os.system(deltext+" fp8.*")
+os.system(deltext+" fp16.*")
+
+os.system(deltext+" fp12.*")
+os.system(deltext+" fp24.*")
+os.system(deltext+" fp48.*")
+
+os.system(deltext+" ecp2.*")
+os.system(deltext+" ecp4.*")
+os.system(deltext+" ecp8.*")
+
+os.system(deltext+" pair.*")
+os.system(deltext+" mpin.*")
+
+os.system(deltext+" pair192.*")
+os.system(deltext+" mpin192.*")
+
+os.system(deltext+" pair256.*")
+os.system(deltext+" mpin256.*")
+
+# create library
+os.system("gcc -O3 -std=c99 -c randapi.c")
+if curve_selected :
+	os.system("gcc -O3 -std=c99 -c ecdh_support.c")
+if rsa_selected :
+	os.system("gcc -O3 -std=c99 -c rsa_support.c")
+if pfcurve_selected :
+	os.system("gcc -O3 -std=c99 -c pbc_support.c")
+
+os.system("gcc -O3 -std=c99 -c hash.c")
+os.system("gcc -O3 -std=c99 -c rand.c")
+os.system("gcc -O3 -std=c99 -c oct.c")
+os.system("gcc -O3 -std=c99 -c aes.c")
+os.system("gcc -O3 -std=c99 -c gcm.c")
+os.system("gcc -O3 -std=c99 -c newhope.c")
+
+if sys.platform.startswith("win") :
+	os.system("for %i in (*.o) do @echo %~nxi >> f.list")
+	os.system("ar rc amcl.a @f.list")
+	os.system(deltext+" f.list")
+
+else :
+	os.system("ar rc amcl.a *.o")
+
+os.system(deltext+" *.o")
+
+
+#print("Your section was ");	
+#for i in range(0,ptr):
+#	print (selection[i])
+
diff --git a/version3/c/config_big.h b/version3/c/config_big.h
new file mode 100644
index 0000000..76822ed
--- /dev/null
+++ b/version3/c/config_big.h
@@ -0,0 +1,38 @@
+/*
+	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.
+*/
+
+/**
+ * @file config_big.h
+ * @author Mike Scott
+ * @brief Config BIG  Header File
+ *
+ */
+
+#ifndef CONFIG_BIG_XXX_H
+#define CONFIG_BIG_XXX_H
+
+#include"amcl.h"
+
+// BIG stuff
+
+#define MODBYTES_XXX @NB@  	/**< Number of bytes in Modulus */
+#define BASEBITS_XXX @BASE@ 	/**< Numbers represented to base 2*BASEBITS */
+
+
+#endif
diff --git a/version3/c/config_curve.h b/version3/c/config_curve.h
new file mode 100644
index 0000000..58208df
--- /dev/null
+++ b/version3/c/config_curve.h
@@ -0,0 +1,44 @@
+#ifndef CONFIG_CURVE_ZZZ_H
+#define CONFIG_CURVE_ZZZ_H
+
+#include"amcl.h"
+#include"config_field_YYY.h"
+
+// ECP stuff
+
+#define CURVETYPE_ZZZ @CT@
+#define PAIRING_FRIENDLY_ZZZ @PF@
+#define CURVE_SECURITY_ZZZ @CS@
+
+
+#if PAIRING_FRIENDLY_ZZZ != NOT
+//#define USE_GLV_ZZZ	  /**< Note this method is patented (GLV), so maybe you want to comment this out */
+//#define USE_GS_G2_ZZZ /**< Well we didn't patent it :) But may be covered by GLV patent :( */
+#define USE_GS_GT_ZZZ /**< Not patented, so probably safe to always use this */
+
+#define POSITIVEX 0
+#define NEGATIVEX 1
+
+#define SEXTIC_TWIST_ZZZ @ST@
+#define SIGN_OF_X_ZZZ @SX@
+
+#endif
+
+#if CURVE_SECURITY_ZZZ == 128
+#define AESKEY_ZZZ 16 /**< Symmetric Key size - 128 bits */
+#define HASH_TYPE_ZZZ SHA256  /**< Hash type */
+#endif
+
+#if CURVE_SECURITY_ZZZ == 192
+#define AESKEY_ZZZ 24 /**< Symmetric Key size - 192 bits */
+#define HASH_TYPE_ZZZ SHA384  /**< Hash type */
+#endif
+
+#if CURVE_SECURITY_ZZZ == 256
+#define AESKEY_ZZZ 32 /**< Symmetric Key size - 256 bits */
+#define HASH_TYPE_ZZZ SHA512  /**< Hash type */
+#endif
+
+
+
+#endif
diff --git a/version3/c/config_ff.h b/version3/c/config_ff.h
new file mode 100644
index 0000000..173dab7
--- /dev/null
+++ b/version3/c/config_ff.h
@@ -0,0 +1,38 @@
+/*
+	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.
+*/
+
+/**
+ * @file config_ff.h
+ * @author Mike Scott
+ * @brief COnfig FF Header File
+ *
+ */
+
+#ifndef CONFIG_RSA_WWW_H
+#define CONFIG_RSA_WWW_H
+
+#include "amcl.h"
+#include "config_big_XXX.h"
+
+// FF stuff
+
+#define FFLEN_WWW @ML@ /**< 2^n multiplier of BIGBITS to specify supported Finite Field size, e.g 2048=256*2^3 where BIGBITS=256 */
+
+
+#endif
diff --git a/version3/c/config_field.h b/version3/c/config_field.h
new file mode 100644
index 0000000..2d727f2
--- /dev/null
+++ b/version3/c/config_field.h
@@ -0,0 +1,34 @@
+/*
+	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.
+*/
+
+#ifndef CONFIG_FIELD_YYY_H
+#define CONFIG_FIELD_YYY_H
+
+#include"amcl.h"
+#include "config_big_XXX.h"
+
+// FP stuff
+
+#define MBITS_YYY @NBT@
+#define MOD8_YYY @M8@
+#define MODTYPE_YYY @MT@
+#define MAXXES_YYY @SH@
+
+
+#endif
diff --git a/version3/c/ecdh.c b/version3/c/ecdh.c
new file mode 100644
index 0000000..e9c4c95
--- /dev/null
+++ b/version3/c/ecdh.c
@@ -0,0 +1,424 @@
+/*
+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.
+*/
+
+/* ECDH/ECIES/ECDSA Functions - see main program below */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "ecdh_ZZZ.h"
+
+/* Calculate a public/private EC GF(p) key pair. W=S.G mod EC(p),
+ * where S is the secret key and W is the public key
+ * and G is fixed generator.
+ * If RNG is NULL then the private key is provided externally in S
+ * otherwise it is generated randomly internally */
+int ECP_ZZZ_KEY_PAIR_GENERATE(csprng *RNG,octet* S,octet *W)
+{
+    BIG_XXX r,gx,gy,s;
+    ECP_ZZZ G;
+    int res=0;
+
+	ECP_ZZZ_generator(&G);
+
+    BIG_XXX_rcopy(r,CURVE_Order_ZZZ);
+    if (RNG!=NULL)
+    {
+        BIG_XXX_randomnum(s,r,RNG);
+    }
+    else
+    {
+        BIG_XXX_fromBytes(s,S->val);
+        BIG_XXX_mod(s,r);
+    }
+
+#ifdef AES_S
+    BIG_XXX_mod2m(s,2*AES_S);
+//	BIG_toBytes(S->val,s);
+#endif
+
+    S->len=EGS_ZZZ;
+    BIG_XXX_toBytes(S->val,s);
+
+    ECP_ZZZ_mul(&G,s);
+
+	ECP_ZZZ_toOctet(W,&G,false);  /* To use point compression on public keys, change to true */
+/*
+#if CURVETYPE_ZZZ!=MONTGOMERY
+    ECP_ZZZ_get(gx,gy,&G);
+#else
+    ECP_ZZZ_get(gx,&G);
+
+#endif
+
+
+
+#if CURVETYPE_ZZZ!=MONTGOMERY
+    W->len=2*EFS_ZZZ+1;
+    W->val[0]=4;
+    BIG_XXX_toBytes(&(W->val[1]),gx);
+    BIG_XXX_toBytes(&(W->val[EFS_ZZZ+1]),gy);
+#else
+    W->len=EFS_ZZZ+1;
+    W->val[0]=2;
+    BIG_XXX_toBytes(&(W->val[1]),gx);
+#endif
+*/
+    return res;
+}
+
+/* Validate public key */
+int ECP_ZZZ_PUBLIC_KEY_VALIDATE(octet *W)
+{
+    BIG_XXX q,r,wx,k;
+    ECP_ZZZ WP;
+    int valid,nb;
+    int res=0;
+
+    BIG_XXX_rcopy(q,Modulus_YYY);
+    BIG_XXX_rcopy(r,CURVE_Order_ZZZ);
+
+	valid=ECP_ZZZ_fromOctet(&WP,W);
+	if (!valid) res=ECDH_INVALID_PUBLIC_KEY;
+
+/*
+    BIG_XXX_fromBytes(wx,&(W->val[1]));
+    if (BIG_XXX_comp(wx,q)>=0) res=ECDH_INVALID_PUBLIC_KEY;
+#if CURVETYPE_ZZZ!=MONTGOMERY
+    BIG_XXX wy;
+    BIG_XXX_fromBytes(wy,&(W->val[EFS_ZZZ+1]));
+    if (BIG_XXX_comp(wy,q)>=0) res=ECDH_INVALID_PUBLIC_KEY;
+#endif
+*/
+    if (res==0)
+    {
+
+//#if CURVETYPE_ZZZ!=MONTGOMERY
+//        valid=ECP_ZZZ_set(&WP,wx,wy);
+//#else
+//        valid=ECP_ZZZ_set(&WP,wx);
+//#endif
+//        if (!valid || ECP_ZZZ_isinf(&WP)) res=ECDH_INVALID_PUBLIC_KEY;
+//        if (res==0 )
+//        {
+            /* Check point is not in wrong group */
+            nb=BIG_XXX_nbits(q);
+            BIG_XXX_one(k);
+            BIG_XXX_shl(k,(nb+4)/2);
+            BIG_XXX_add(k,q,k);
+            BIG_XXX_sdiv(k,r); /* get co-factor */
+
+            while (BIG_XXX_parity(k)==0)
+            {
+                ECP_ZZZ_dbl(&WP);
+                BIG_XXX_fshr(k,1);
+            }
+
+            if (!BIG_XXX_isunity(k)) ECP_ZZZ_mul(&WP,k);
+            if (ECP_ZZZ_isinf(&WP)) res=ECDH_INVALID_PUBLIC_KEY;
+//        }
+    }
+
+    return res;
+}
+
+/* IEEE-1363 Diffie-Hellman online calculation Z=S.WD */
+int ECP_ZZZ_SVDP_DH(octet *S,octet *WD,octet *Z)
+{
+    BIG_XXX r,s,wx;
+    int valid;
+    ECP_ZZZ W;
+    int res=0;
+
+    BIG_XXX_fromBytes(s,S->val);
+
+	valid=ECP_ZZZ_fromOctet(&W,WD);
+/*
+    BIG_XXX_fromBytes(wx,&(WD->val[1]));
+#if CURVETYPE_ZZZ!=MONTGOMERY
+    BIG_XXX wy;
+    BIG_XXX_fromBytes(wy,&(WD->val[EFS_ZZZ+1]));
+    valid=ECP_ZZZ_set(&W,wx,wy);
+#else
+    valid=ECP_ZZZ_set(&W,wx);
+#endif
+*/
+    if (!valid) res=ECDH_ERROR;
+    if (res==0)
+    {
+        BIG_XXX_rcopy(r,CURVE_Order_ZZZ);
+        BIG_XXX_mod(s,r);
+
+        ECP_ZZZ_mul(&W,s);
+        if (ECP_ZZZ_isinf(&W)) res=ECDH_ERROR;
+        else
+        {
+#if CURVETYPE_ZZZ!=MONTGOMERY
+            ECP_ZZZ_get(wx,wx,&W);
+#else
+            ECP_ZZZ_get(wx,&W);
+#endif
+            Z->len=MODBYTES_XXX;
+            BIG_XXX_toBytes(Z->val,wx);
+        }
+    }
+    return res;
+}
+
+#if CURVETYPE_ZZZ!=MONTGOMERY
+
+/* IEEE ECDSA Signature, C and D are signature on F using private key S */
+int ECP_ZZZ_SP_DSA(int sha,csprng *RNG,octet *K,octet *S,octet *F,octet *C,octet *D)
+{
+    char h[128];
+    octet H= {0,sizeof(h),h};
+
+    BIG_XXX gx,gy,r,s,f,c,d,u,vx,w;
+    ECP_ZZZ G,V;
+
+    ehashit(sha,F,-1,NULL,&H,sha);
+
+	ECP_ZZZ_generator(&G);
+
+    BIG_XXX_rcopy(r,CURVE_Order_ZZZ);
+
+    BIG_XXX_fromBytes(s,S->val);
+
+    int hlen=H.len;
+    if (H.len>MODBYTES_XXX) hlen=MODBYTES_XXX;
+    BIG_XXX_fromBytesLen(f,H.val,hlen);
+
+	if (RNG!=NULL)
+	{
+		do
+		{
+       
+            BIG_XXX_randomnum(u,r,RNG);
+            BIG_XXX_randomnum(w,r,RNG); /* side channel masking */
+
+#ifdef AES_S
+			BIG_XXX_mod2m(u,2*AES_S);
+#endif
+			ECP_ZZZ_copy(&V,&G);
+			ECP_ZZZ_mul(&V,u);
+
+			ECP_ZZZ_get(vx,vx,&V);
+
+			BIG_XXX_copy(c,vx);
+			BIG_XXX_mod(c,r);
+			if (BIG_XXX_iszilch(c)) continue;
+			
+            BIG_XXX_modmul(u,u,w,r);
+
+			BIG_XXX_invmodp(u,u,r);
+			BIG_XXX_modmul(d,s,c,r);
+
+			BIG_XXX_add(d,f,d);
+			
+            BIG_XXX_modmul(d,d,w,r);
+
+			BIG_XXX_modmul(d,u,d,r);
+		} while (BIG_XXX_iszilch(d));
+	}
+	else
+	{
+		BIG_XXX_fromBytes(u,K->val);
+		BIG_XXX_mod(u,r);
+
+#ifdef AES_S
+        BIG_XXX_mod2m(u,2*AES_S);
+#endif
+        ECP_ZZZ_copy(&V,&G);
+        ECP_ZZZ_mul(&V,u);
+
+        ECP_ZZZ_get(vx,vx,&V);
+
+        BIG_XXX_copy(c,vx);
+        BIG_XXX_mod(c,r);
+        if (BIG_XXX_iszilch(c)) return ECDH_ERROR;
+ 
+
+        BIG_XXX_invmodp(u,u,r);
+        BIG_XXX_modmul(d,s,c,r);
+
+        BIG_XXX_add(d,f,d);
+
+        BIG_XXX_modmul(d,u,d,r);
+        if (BIG_XXX_iszilch(d)) return ECDH_ERROR;
+    }
+
+    C->len=D->len=EGS_ZZZ;
+
+    BIG_XXX_toBytes(C->val,c);
+    BIG_XXX_toBytes(D->val,d);
+
+    return 0;
+}
+
+/* IEEE1363 ECDSA Signature Verification. Signature C and D on F is verified using public key W */
+int ECP_ZZZ_VP_DSA(int sha,octet *W,octet *F, octet *C,octet *D)
+{
+    char h[128];
+    octet H= {0,sizeof(h),h};
+
+    BIG_XXX r,gx,gy,wx,wy,f,c,d,h2;
+    int res=0;
+    ECP_ZZZ G,WP;
+    int valid;
+
+    ehashit(sha,F,-1,NULL,&H,sha);
+
+	ECP_ZZZ_generator(&G);
+
+    BIG_XXX_rcopy(r,CURVE_Order_ZZZ);
+
+    OCT_shl(C,C->len-MODBYTES_XXX);
+    OCT_shl(D,D->len-MODBYTES_XXX);
+
+    BIG_XXX_fromBytes(c,C->val);
+    BIG_XXX_fromBytes(d,D->val);
+
+    int hlen=H.len;
+    if (hlen>MODBYTES_XXX) hlen=MODBYTES_XXX;
+
+    BIG_XXX_fromBytesLen(f,H.val,hlen);
+
+    //BIG_fromBytes(f,H.val);
+
+    if (BIG_XXX_iszilch(c) || BIG_XXX_comp(c,r)>=0 || BIG_XXX_iszilch(d) || BIG_XXX_comp(d,r)>=0)
+        res=ECDH_INVALID;
+
+    if (res==0)
+    {
+        BIG_XXX_invmodp(d,d,r);
+        BIG_XXX_modmul(f,f,d,r);
+        BIG_XXX_modmul(h2,c,d,r);
+
+		valid=ECP_ZZZ_fromOctet(&WP,W);
+/*
+        BIG_XXX_fromBytes(wx,&(W->val[1]));
+        BIG_XXX_fromBytes(wy,&(W->val[EFS_ZZZ+1]));
+
+        valid=ECP_ZZZ_set(&WP,wx,wy);
+*/
+        if (!valid) res=ECDH_ERROR;
+        else
+        {
+            ECP_ZZZ_mul2(&WP,&G,h2,f);
+
+            if (ECP_ZZZ_isinf(&WP)) res=ECDH_INVALID;
+            else
+            {
+                ECP_ZZZ_get(d,d,&WP);
+                BIG_XXX_mod(d,r);
+                if (BIG_XXX_comp(d,c)!=0) res=ECDH_INVALID;
+            }
+        }
+    }
+
+    return res;
+}
+
+/* IEEE1363 ECIES encryption. Encryption of plaintext M uses public key W and produces ciphertext V,C,T */
+void ECP_ZZZ_ECIES_ENCRYPT(int sha,octet *P1,octet *P2,csprng *RNG,octet *W,octet *M,int tlen,octet *V,octet *C,octet *T)
+{
+
+    int i,len;
+    char z[EFS_ZZZ],vz[3*EFS_ZZZ+1],k[2*AESKEY_ZZZ],k1[AESKEY_ZZZ],k2[AESKEY_ZZZ],l2[8],u[EFS_ZZZ];
+    octet Z= {0,sizeof(z),z};
+    octet VZ= {0,sizeof(vz),vz};
+    octet K= {0,sizeof(k),k};
+    octet K1= {0,sizeof(k1),k1};
+    octet K2= {0,sizeof(k2),k2};
+    octet L2= {0,sizeof(l2),l2};
+    octet U= {0,sizeof(u),u};
+
+    if (ECP_ZZZ_KEY_PAIR_GENERATE(RNG,&U,V)!=0) return;
+    if (ECP_ZZZ_SVDP_DH(&U,W,&Z)!=0) return;
+
+    OCT_copy(&VZ,V);
+    OCT_joctet(&VZ,&Z);
+
+    KDF2(sha,&VZ,P1,2*AESKEY_ZZZ,&K);
+
+    K1.len=K2.len=AESKEY_ZZZ;
+    for (i=0; i<AESKEY_ZZZ; i++)
+    {
+        K1.val[i]=K.val[i];
+        K2.val[i]=K.val[AESKEY_ZZZ+i];
+    }
+
+    AES_CBC_IV0_ENCRYPT(&K1,M,C);
+
+    OCT_jint(&L2,P2->len,8);
+
+    len=C->len;
+    OCT_joctet(C,P2);
+    OCT_joctet(C,&L2);
+    HMAC(sha,C,&K2,tlen,T);
+    C->len=len;
+}
+
+/* IEEE1363 ECIES decryption. Decryption of ciphertext V,C,T using private key U outputs plaintext M */
+int ECP_ZZZ_ECIES_DECRYPT(int sha,octet *P1,octet *P2,octet *V,octet *C,octet *T,octet *U,octet *M)
+{
+
+    int i,len;
+    char z[EFS_ZZZ],vz[3*EFS_ZZZ+1],k[2*AESKEY_ZZZ],k1[AESKEY_ZZZ],k2[AESKEY_ZZZ],l2[8],tag[32];
+    octet Z= {0,sizeof(z),z};
+    octet VZ= {0,sizeof(vz),vz};
+    octet K= {0,sizeof(k),k};
+    octet K1= {0,sizeof(k1),k1};
+    octet K2= {0,sizeof(k2),k2};
+    octet L2= {0,sizeof(l2),l2};
+    octet TAG= {0,sizeof(tag),tag};
+
+    if (ECP_ZZZ_SVDP_DH(U,V,&Z)!=0) return 0;
+
+    OCT_copy(&VZ,V);
+    OCT_joctet(&VZ,&Z);
+
+    KDF2(sha,&VZ,P1,2*AESKEY_ZZZ,&K);
+
+    K1.len=K2.len=AESKEY_ZZZ;
+    for (i=0; i<AESKEY_ZZZ; i++)
+    {
+        K1.val[i]=K.val[i];
+        K2.val[i]=K.val[AESKEY_ZZZ+i];
+    }
+
+    if (!AES_CBC_IV0_DECRYPT(&K1,C,M)) return 0;
+
+    OCT_jint(&L2,P2->len,8);
+
+    len=C->len;
+    OCT_joctet(C,P2);
+    OCT_joctet(C,&L2);
+    HMAC(sha,C,&K2,T->len,&TAG);
+    C->len=len;
+
+    if (!OCT_ncomp(T,&TAG,T->len)) return 0;
+
+    return 1;
+
+}
+
+#endif
diff --git a/version3/c/ecdh.h b/version3/c/ecdh.h
new file mode 100644
index 0000000..10a1828
--- /dev/null
+++ b/version3/c/ecdh.h
@@ -0,0 +1,146 @@
+/*
+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.
+*/
+
+/**
+ * @file ecdh.h
+ * @author Mike Scott
+ * @brief ECDH Header file for implementation of standard EC protocols
+ *
+ *
+ */
+
+#ifndef ECDH_ZZZ_H
+#define ECDH_ZZZ_H
+
+#include "ecp_ZZZ.h"
+#include "ecdh_support.h"
+
+
+/*** START OF USER CONFIGURABLE SECTION -  ***/
+
+//#define EAS_ZZZ 16 /**< Symmetric Key size - 128 bits */
+//#define HASH_TYPE_ECC_ZZZ SHA512  /**< Hash type */
+
+/*** END OF USER CONFIGURABLE SECTION ***/
+
+#define EGS_ZZZ MODBYTES_XXX  /**< ECC Group Size in bytes */
+#define EFS_ZZZ MODBYTES_XXX  /**< ECC Field Size in bytes */
+
+#define ECDH_OK                     0     /**< Function completed without error */
+/*#define ECDH_DOMAIN_ERROR          -1*/
+#define ECDH_INVALID_PUBLIC_KEY    -2	/**< Public Key is Invalid */
+#define ECDH_ERROR                 -3	/**< ECDH Internal Error */
+#define ECDH_INVALID               -4	/**< ECDH Internal Error */
+/*#define ECDH_DOMAIN_NOT_FOUND      -5
+#define ECDH_OUT_OF_MEMORY         -6
+#define ECDH_DIV_BY_ZERO           -7
+#define ECDH_BAD_ASSUMPTION        -8*/
+
+/* ECDH primitives */
+/**	@brief Generate an ECC public/private key pair
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param s the private key, an output internally randomly generated if R!=NULL, otherwise must be provided as an input
+	@param W the output public key, which is s.G, where G is a fixed generator
+	@return 0 or an error code
+ */
+extern int  ECP_ZZZ_KEY_PAIR_GENERATE(csprng *R,octet *s,octet *W);
+/**	@brief Validate an ECC public key
+ *
+	@param W the input public key to be validated
+	@return 0 if public key is OK, or an error code
+ */
+extern int  ECP_ZZZ_PUBLIC_KEY_VALIDATE(octet *W);
+
+/* ECDH primitives */
+
+/**	@brief Generate Diffie-Hellman shared key
+ *
+	IEEE-1363 Diffie-Hellman shared secret calculation
+	@param s is the input private key,
+	@param W the input public key of the other party
+	@param K the output shared key, in fact the x-coordinate of s.W
+	@return 0 or an error code
+ */
+extern int ECP_ZZZ_SVDP_DH(octet *s,octet *W,octet *K);
+/*extern int ECPSVDP_DHC(octet *,octet *,int,octet *);*/
+
+/*#if CURVETYPE!=MONTGOMERY */
+/* ECIES functions */
+/*#if CURVETYPE!=MONTGOMERY */
+/* ECIES functions */
+/**	@brief ECIES Encryption
+ *
+	IEEE-1363 ECIES Encryption
+	@param h is the hash type
+	@param P1 input Key Derivation parameters
+	@param P2 input Encoding parameters
+	@param R is a pointer to a cryptographically secure random number generator
+	@param W the input public key of the recieving party
+	@param M is the plaintext message to be encrypted
+	@param len the length of the HMAC tag
+	@param V component of the output ciphertext
+	@param C the output ciphertext
+	@param T the output HMAC tag, part of the ciphertext
+ */
+extern void ECP_ZZZ_ECIES_ENCRYPT(int h,octet *P1,octet *P2,csprng *R,octet *W,octet *M,int len,octet *V,octet *C,octet *T);
+/**	@brief ECIES Decryption
+ *
+	IEEE-1363 ECIES Decryption
+	@param h is the hash type
+	@param P1 input Key Derivation parameters
+	@param P2 input Encoding parameters
+	@param V component of the input ciphertext
+	@param C the input ciphertext
+	@param T the input HMAC tag, part of the ciphertext
+	@param U the input private key for decryption
+	@param M the output plaintext message
+	@return 1 if successful, else 0
+ */
+extern int ECP_ZZZ_ECIES_DECRYPT(int h,octet *P1,octet *P2,octet *V,octet *C,octet *T,octet *U,octet *M);
+
+/* ECDSA functions */
+/**	@brief ECDSA Signature
+ *
+	IEEE-1363 ECDSA Signature
+	@param h is the hash type
+	@param R is a pointer to a cryptographically secure random number generator
+        @param k Ephemeral key. This value is used when R=NULL
+	@param s the input private signing key
+	@param M the input message to be signed
+	@param c component of the output signature
+	@param d component of the output signature
+
+ */
+extern int ECP_ZZZ_SP_DSA(int h,csprng *R,octet *k,octet *s,octet *M,octet *c,octet *d);
+/**	@brief ECDSA Signature Verification
+ *
+	IEEE-1363 ECDSA Signature Verification
+	@param h is the hash type
+	@param W the input public key
+	@param M the input message
+	@param c component of the input signature
+	@param d component of the input signature
+	@return 0 or an error code
+ */
+extern int ECP_ZZZ_VP_DSA(int h,octet *W,octet *M,octet *c,octet *d);
+/*#endif*/
+
+#endif
+
diff --git a/version3/c/ecdh_support.c b/version3/c/ecdh_support.c
new file mode 100644
index 0000000..b01ccc9
--- /dev/null
+++ b/version3/c/ecdh_support.c
@@ -0,0 +1,352 @@
+/*
+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.
+*/
+
+/* Symmetric crypto support functions Functions  */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "ecdh_support.h"
+
+#define ROUNDUP(a,b) ((a)-1)/(b)+1
+
+/* general purpose hash function w=hash(p|n|x|y) */
+/* pad or truncate ouput to length pad if pad!=0 */
+void ehashit(int sha,octet *p,int n,octet *x,octet *w,int pad)
+{
+    int i,c[4],hlen;
+    hash256 sha256;
+    hash512 sha512;
+    char hh[64];
+
+    switch (sha)
+    {
+    case SHA256:
+        HASH256_init(&sha256);
+        break;
+    case SHA384:
+        HASH384_init(&sha512);
+        break;
+    case SHA512:
+        HASH512_init(&sha512);
+        break;
+    }
+
+    hlen=sha;
+
+    for (i=0; i<p->len; i++)
+    {
+        switch(sha)
+        {
+        case SHA256:
+            HASH256_process(&sha256,p->val[i]);
+            break;
+        case SHA384:
+            HASH384_process(&sha512,p->val[i]);
+            break;
+        case SHA512:
+            HASH512_process(&sha512,p->val[i]);
+            break;
+        }
+    }
+    if (n>0)
+    {
+        c[0]=(n>>24)&0xff;
+        c[1]=(n>>16)&0xff;
+        c[2]=(n>>8)&0xff;
+        c[3]=(n)&0xff;
+        for (i=0; i<4; i++)
+        {
+            switch(sha)
+            {
+            case SHA256:
+                HASH256_process(&sha256,c[i]);
+                break;
+            case SHA384:
+                HASH384_process(&sha512,c[i]);
+                break;
+            case SHA512:
+                HASH512_process(&sha512,c[i]);
+                break;
+            }
+        }
+    }
+    if (x!=NULL) for (i=0; i<x->len; i++)
+        {
+            switch(sha)
+            {
+            case SHA256:
+                HASH256_process(&sha256,x->val[i]);
+                break;
+            case SHA384:
+                HASH384_process(&sha512,x->val[i]);
+                break;
+            case SHA512:
+                HASH512_process(&sha512,x->val[i]);
+                break;
+            }
+        }
+
+    switch (sha)
+    {
+    case SHA256:
+        HASH256_hash(&sha256,hh);
+        break;
+    case SHA384:
+        HASH384_hash(&sha512,hh);
+        break;
+    case SHA512:
+        HASH512_hash(&sha512,hh);
+        break;
+    }
+
+    OCT_empty(w);
+    if (!pad)
+        OCT_jbytes(w,hh,hlen);
+    else
+    {
+        if (pad<=hlen)
+            OCT_jbytes(w,hh,pad);
+        else
+        {
+            OCT_jbyte(w,0,pad-hlen);
+            OCT_jbytes(w,hh,hlen);
+
+//            OCT_jbytes(w,hh,hlen);
+//            OCT_jbyte(w,0,pad-hlen);
+        }
+    }
+    return;
+}
+
+/* Hash octet p to octet w */
+void HASH(int sha,octet *p,octet *w)
+{
+    ehashit(sha,p,-1,NULL,w,0);
+}
+
+/* Calculate HMAC of m using key k. HMAC is tag of length olen */
+int HMAC(int sha,octet *m,octet *k,int olen,octet *tag)
+{
+    /* Input is from an octet m        *
+     * olen is requested output length in bytes. k is the key  *
+     * The output is the calculated tag */
+    int hlen,b;
+    char h[128],k0[128];
+    octet H= {0,sizeof(h),h};
+    octet K0= {0,sizeof(k0),k0};
+
+    hlen=sha;
+    if (hlen>32) b=128;
+    else b=64;
+
+    if (olen<4 /*|| olen>hlen*/) return 0;
+
+    if (k->len > b) ehashit(sha,k,-1,NULL,&K0,0);
+    else            OCT_copy(&K0,k);
+
+    OCT_jbyte(&K0,0,b-K0.len);
+
+    OCT_xorbyte(&K0,0x36);
+
+    ehashit(sha,&K0,-1,m,&H,0);
+
+    OCT_xorbyte(&K0,0x6a);   /* 0x6a = 0x36 ^ 0x5c */
+    ehashit(sha,&K0,-1,&H,&H,olen);
+
+    OCT_empty(tag);
+
+    OCT_jbytes(tag,H.val,olen);
+
+    return 1;
+}
+
+/* Key Derivation Functions */
+/* Input octet z */
+/* Output key of length olen */
+/*
+void KDF1(octet *z,int olen,octet *key)
+{
+    char h[32];
+	octet H={0,sizeof(h),h};
+    int counter,cthreshold;
+    int hlen=32;
+
+    OCT_empty(key);
+
+    cthreshold=ROUNDUP(olen,hlen);
+
+    for (counter=0;counter<cthreshold;counter++)
+    {
+        ehashit(z,counter,NULL,NULL,&H);
+        if (key->len+hlen>olen) OCT_jbytes(key,H.val,olen%hlen);
+        else                    OCT_joctet(key,&H);
+    }
+}
+*/
+void KDF2(int sha,octet *z,octet *p,int olen,octet *key)
+{
+    /* NOTE: the parameter olen is the length of the output k in bytes */
+    char h[64];
+    octet H= {0,sizeof(h),h};
+    int counter,cthreshold;
+    int hlen=sha;
+
+    OCT_empty(key);
+
+    cthreshold=ROUNDUP(olen,hlen);
+
+    for (counter=1; counter<=cthreshold; counter++)
+    {
+        ehashit(sha,z,counter,p,&H,0);
+        if (key->len+hlen>olen)  OCT_jbytes(key,H.val,olen%hlen);
+        else                     OCT_joctet(key,&H);
+    }
+
+}
+
+/* Password based Key Derivation Function */
+/* Input password p, salt s, and repeat count */
+/* Output key of length olen */
+void PBKDF2(int sha,octet *p,octet *s,int rep,int olen,octet *key)
+{
+    int i,j,len,d=ROUNDUP(olen,sha);
+    char f[64],u[64];
+    octet F= {0,sizeof(f),f};
+    octet U= {0,sizeof(u),u};
+    OCT_empty(key);
+
+    for (i=1; i<=d; i++)
+    {
+        len=s->len;
+        OCT_jint(s,i,4);
+
+        HMAC(sha,s,p,sha,&F);
+
+        s->len=len;
+        OCT_copy(&U,&F);
+        for (j=2; j<=rep; j++)
+        {
+            HMAC(sha,&U,p,sha,&U);
+            OCT_xor(&F,&U);
+        }
+
+        OCT_joctet(key,&F);
+    }
+
+    OCT_chop(key,NULL,olen);
+}
+
+/* AES encryption/decryption. Encrypt byte array M using key K and returns ciphertext */
+void AES_CBC_IV0_ENCRYPT(octet *k,octet *m,octet *c)
+{
+    /* AES CBC encryption, with Null IV and key k */
+    /* Input is from an octet string m, output is to an octet string c */
+    /* Input is padded as necessary to make up a full final block */
+    amcl_aes a;
+    int fin;
+    int i,j,ipt,opt;
+    char buff[16];
+    int padlen;
+
+    OCT_clear(c);
+    if (m->len==0) return;
+    AES_init(&a,CBC,k->len,k->val,NULL);
+
+    ipt=opt=0;
+    fin=0;
+    for(;;)
+    {
+        for (i=0; i<16; i++)
+        {
+            if (ipt<m->len) buff[i]=m->val[ipt++];
+            else
+            {
+                fin=1;
+                break;
+            }
+        }
+        if (fin) break;
+        AES_encrypt(&a,buff);
+        for (i=0; i<16; i++)
+            if (opt<c->max) c->val[opt++]=buff[i];
+    }
+
+    /* last block, filled up to i-th index */
+
+    padlen=16-i;
+    for (j=i; j<16; j++) buff[j]=padlen;
+    AES_encrypt(&a,buff);
+    for (i=0; i<16; i++)
+        if (opt<c->max) c->val[opt++]=buff[i];
+    AES_end(&a);
+    c->len=opt;
+}
+
+/* decrypts and returns TRUE if all consistent, else returns FALSE */
+int AES_CBC_IV0_DECRYPT(octet *k,octet *c,octet *m)
+{
+    /* padding is removed */
+    amcl_aes a;
+    int i,ipt,opt,ch;
+    char buff[16];
+    int fin,bad;
+    int padlen;
+    ipt=opt=0;
+
+    OCT_clear(m);
+    if (c->len==0) return 1;
+    ch=c->val[ipt++];
+
+    AES_init(&a,CBC,k->len,k->val,NULL);
+    fin=0;
+
+    for(;;)
+    {
+        for (i=0; i<16; i++)
+        {
+            buff[i]=ch;
+            if (ipt>=c->len)
+            {
+                fin=1;
+                break;
+            }
+            else ch=c->val[ipt++];
+        }
+        AES_decrypt(&a,buff);
+        if (fin) break;
+        for (i=0; i<16; i++)
+            if (opt<m->max) m->val[opt++]=buff[i];
+    }
+    AES_end(&a);
+    bad=0;
+    padlen=buff[15];
+    if (i!=15 || padlen<1 || padlen>16) bad=1;
+    if (padlen>=2 && padlen<=16)
+        for (i=16-padlen; i<16; i++) if (buff[i]!=padlen) bad=1;
+
+    if (!bad) for (i=0; i<16-padlen; i++)
+            if (opt<m->max) m->val[opt++]=buff[i];
+
+    m->len=opt;
+    if (bad) return 0;
+    return 1;
+}
diff --git a/version3/c/ecdh_support.h b/version3/c/ecdh_support.h
new file mode 100644
index 0000000..85b200d
--- /dev/null
+++ b/version3/c/ecdh_support.h
@@ -0,0 +1,114 @@
+/*
+	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.
+*/
+
+/**
+ * @file ecdh_support.h
+ * @author Mike Scott
+ * @brief ECDH Support Header File
+ *
+ */
+
+#ifndef ECC_SUPPORT_H
+#define ECC_SUPPORT_H
+
+#include "amcl.h"
+
+/* Auxiliary Functions */
+
+/** @brief general purpose hash function w=hash(p|n|x|y)
+ *
+	@param sha is the hash type
+	@param p first octect involved in the hash
+	@param n integer involved in the hash
+	@param x second octect involved in the h ash
+	@param w output
+	@param pad padding
+ */
+extern void ehashit(int sha,octet *p,int n,octet *x,octet *w,int pad);
+
+/**	@brief hash an octet into another octet
+ *
+ 	@param h is the hash type
+	@param I input octet
+	@param O output octet - H(I)
+ */
+extern void HASH(int h,octet *I,octet *O);
+/**	@brief HMAC of message M using key K to create tag of length len in octet tag
+ *
+	IEEE-1363 MAC1 function. Uses SHA256 internally.
+	@param h is the hash type
+	@param M input message octet
+	@param K input encryption key
+	@param len is output desired length of HMAC tag
+	@param tag is the output HMAC
+	@return 0 for bad parameters, else 1
+ */
+extern int HMAC(int h,octet *M,octet *K,int len,octet *tag);
+
+/*extern void KDF1(octet *,int,octet *);*/
+
+/**	@brief Key Derivation Function - generates key K from inputs Z and P
+ *
+	IEEE-1363 KDF2 Key Derivation Function. Uses SHA256 internally.
+	@param h is the hash type
+	@param Z input octet
+	@param P input key derivation parameters - can be NULL
+	@param len is output desired length of key
+	@param K is the derived key
+ */
+extern void KDF2(int h,octet *Z,octet *P,int len,octet *K);
+/**	@brief Password Based Key Derivation Function - generates key K from password, salt and repeat counter
+ *
+	PBKDF2 Password Based Key Derivation Function. Uses SHA256 internally.
+	@param h is the hash type
+	@param P input password
+	@param S input salt
+	@param rep Number of times to be iterated.
+	@param len is output desired length
+	@param K is the derived key
+ */
+extern void PBKDF2(int h,octet *P,octet *S,int rep,int len,octet *K);
+/**	@brief AES encrypts a plaintext to a ciphtertext
+ *
+	IEEE-1363 AES_CBC_IV0_ENCRYPT function. Encrypts in CBC mode with a zero IV, padding as necessary to create a full final block.
+	@param K AES key
+	@param P input plaintext octet
+	@param C output ciphertext octet
+ */
+extern void AES_CBC_IV0_ENCRYPT(octet *K,octet *P,octet *C);
+/**	@brief AES encrypts a plaintext to a ciphtertext
+ *
+	IEEE-1363 AES_CBC_IV0_DECRYPT function. Decrypts in CBC mode with a zero IV.
+	@param K AES key
+	@param C input ciphertext octet
+	@param P output plaintext octet
+	@return 0 if bad input, else 1
+ */
+extern int AES_CBC_IV0_DECRYPT(octet *K,octet *C,octet *P);
+
+/* ECDH primitives - support functions */
+/**	@brief Generate an ECC public/private key pair
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param s the private key, an output internally randomly generated if R!=NULL, otherwise must be provided as an input
+	@param W the output public key, which is s.G, where G is a fixed generator
+	@return 0 or an error code
+ */
+
+#endif
diff --git a/version3/c/ecp.c b/version3/c/ecp.c
new file mode 100644
index 0000000..39d5c0a
--- /dev/null
+++ b/version3/c/ecp.c
@@ -0,0 +1,1468 @@
+/*
+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.
+*/
+
+/* AMCL Elliptic Curve Functions */
+/* SU=m, SU is Stack Usage (Weierstrass Curves) */
+
+//#define HAS_MAIN
+
+#include "ecp_ZZZ.h"
+
+/* test for P=O point-at-infinity */
+int ECP_ZZZ_isinf(ECP_ZZZ *P)
+{
+//    if (P->inf) return 1;
+//    FP_YYY_reduce(&(P->x));
+//    FP_YYY_reduce(&(P->z));
+#if CURVETYPE_ZZZ==EDWARDS
+//    FP_YYY_reduce(&(P->y));
+    return (FP_YYY_iszilch(&(P->x)) && FP_YYY_equals(&(P->y),&(P->z)));
+#endif
+#if CURVETYPE_ZZZ==WEIERSTRASS
+//    FP_YYY_reduce(&(P->y));
+    return (FP_YYY_iszilch(&(P->x)) && FP_YYY_iszilch(&(P->z)));
+#endif
+#if CURVETYPE_ZZZ==MONTGOMERY
+    return FP_YYY_iszilch(&(P->z));
+#endif
+//    return P->inf;
+
+}
+
+/* Conditional swap of P and Q dependant on d */
+static void ECP_ZZZ_cswap(ECP_ZZZ *P,ECP_ZZZ *Q,int d)
+{
+    FP_YYY_cswap(&(P->x),&(Q->x),d);
+#if CURVETYPE_ZZZ!=MONTGOMERY
+    FP_YYY_cswap(&(P->y),&(Q->y),d);
+#endif
+    FP_YYY_cswap(&(P->z),&(Q->z),d);
+/*
+    d=~(d-1);
+    d=d&(P->inf^Q->inf);
+    P->inf^=d;
+    Q->inf^=d;
+*/
+}
+
+#if CURVETYPE_ZZZ!=MONTGOMERY
+/* Conditional move Q to P dependant on d */
+static void ECP_ZZZ_cmove(ECP_ZZZ *P,ECP_ZZZ *Q,int d)
+{
+    FP_YYY_cmove(&(P->x),&(Q->x),d);
+#if CURVETYPE_ZZZ!=MONTGOMERY
+    FP_YYY_cmove(&(P->y),&(Q->y),d);
+#endif
+    FP_YYY_cmove(&(P->z),&(Q->z),d);
+/*
+    d=~(d-1);
+    P->inf^=(P->inf^Q->inf)&d;
+*/
+}
+
+/* return 1 if b==c, no branching */
+static int teq(sign32 b,sign32 c)
+{
+    sign32 x=b^c;
+    x-=1;  // if x=0, x now -1
+    return (int)((x>>31)&1);
+}
+#endif // CURVETYPE_ZZZ!=MONTGOMERY
+
+#if CURVETYPE_ZZZ!=MONTGOMERY
+/* Constant time select from pre-computed table */
+static void ECP_ZZZ_select(ECP_ZZZ *P,ECP_ZZZ W[],sign32 b)
+{
+    ECP_ZZZ MP;
+    sign32 m=b>>31;
+    sign32 babs=(b^m)-m;
+
+    babs=(babs-1)/2;
+
+    ECP_ZZZ_cmove(P,&W[0],teq(babs,0));  // conditional move
+    ECP_ZZZ_cmove(P,&W[1],teq(babs,1));
+    ECP_ZZZ_cmove(P,&W[2],teq(babs,2));
+    ECP_ZZZ_cmove(P,&W[3],teq(babs,3));
+    ECP_ZZZ_cmove(P,&W[4],teq(babs,4));
+    ECP_ZZZ_cmove(P,&W[5],teq(babs,5));
+    ECP_ZZZ_cmove(P,&W[6],teq(babs,6));
+    ECP_ZZZ_cmove(P,&W[7],teq(babs,7));
+
+    ECP_ZZZ_copy(&MP,P);
+    ECP_ZZZ_neg(&MP);  // minus P
+    ECP_ZZZ_cmove(P,&MP,(int)(m&1));
+}
+#endif
+
+/* Test P == Q */
+/* SU=168 */
+int ECP_ZZZ_equals(ECP_ZZZ *P,ECP_ZZZ *Q)
+{
+    FP_YYY a,b;
+//    if (ECP_ZZZ_isinf(P) && ECP_ZZZ_isinf(Q)) return 1;
+//    if (ECP_ZZZ_isinf(P) || ECP_ZZZ_isinf(Q)) return 0;
+
+
+    FP_YYY_mul(&a,&(P->x),&(Q->z));
+    FP_YYY_mul(&b,&(Q->x),&(P->z));
+    if (!FP_YYY_equals(&a,&b)) return 0;
+
+#if CURVETYPE_ZZZ!=MONTGOMERY
+    FP_YYY_mul(&a,&(P->y),&(Q->z));
+    FP_YYY_mul(&b,&(Q->y),&(P->z));
+    if (!FP_YYY_equals(&a,&b)) return 0;
+#endif
+
+    return 1;
+
+}
+
+/* Set P=Q */
+/* SU=16 */
+void ECP_ZZZ_copy(ECP_ZZZ *P,ECP_ZZZ *Q)
+{
+//    P->inf=Q->inf;
+    FP_YYY_copy(&(P->x),&(Q->x));
+#if CURVETYPE_ZZZ!=MONTGOMERY
+    FP_YYY_copy(&(P->y),&(Q->y));
+#endif
+    FP_YYY_copy(&(P->z),&(Q->z));
+}
+
+/* Set P=-Q */
+#if CURVETYPE_ZZZ!=MONTGOMERY
+/* SU=8 */
+void ECP_ZZZ_neg(ECP_ZZZ *P)
+{
+//    if (ECP_ZZZ_isinf(P)) return;
+#if CURVETYPE_ZZZ==WEIERSTRASS
+    FP_YYY_neg(&(P->y),&(P->y));
+    FP_YYY_norm(&(P->y));
+#else
+    FP_YYY_neg(&(P->x),&(P->x));
+    FP_YYY_norm(&(P->x));
+#endif
+
+}
+#endif
+
+/* Set P=O */
+void ECP_ZZZ_inf(ECP_ZZZ *P)
+{
+    FP_YYY_zero(&(P->x));
+#if CURVETYPE_ZZZ!=MONTGOMERY
+    FP_YYY_one(&(P->y));
+#endif
+#if CURVETYPE_ZZZ!=EDWARDS
+    FP_YYY_zero(&(P->z));
+#else
+    FP_YYY_one(&(P->z));
+#endif
+//    P->inf=1;
+}
+
+/* Calculate right Hand Side of curve equation y^2=RHS */
+/* SU=56 */
+void ECP_ZZZ_rhs(FP_YYY *v,FP_YYY *x)
+{
+#if CURVETYPE_ZZZ==WEIERSTRASS
+    /* x^3+Ax+B */
+    FP_YYY t;
+    FP_YYY_sqr(&t,x);
+    FP_YYY_mul(&t,&t,x);
+
+    if (CURVE_A_ZZZ==-3)
+    {
+        FP_YYY_neg(v,x);
+        FP_YYY_norm(v);
+        FP_YYY_imul(v,v,-CURVE_A_ZZZ);
+        FP_YYY_norm(v);
+        FP_YYY_add(v,&t,v);
+    }
+    else FP_YYY_copy(v,&t);
+
+    FP_YYY_rcopy(&t,CURVE_B_ZZZ);
+
+    FP_YYY_add(v,&t,v);
+    FP_YYY_reduce(v);
+#endif
+
+#if CURVETYPE_ZZZ==EDWARDS
+    /* (Ax^2-1)/(Bx^2-1) */
+    FP_YYY t,one;
+    FP_YYY_sqr(v,x);
+    FP_YYY_one(&one);
+    FP_YYY_rcopy(&t,CURVE_B_ZZZ);
+
+    FP_YYY_mul(&t,v,&t);
+    FP_YYY_sub(&t,&t,&one);
+	FP_YYY_norm(&t);
+    if (CURVE_A_ZZZ==1) FP_YYY_sub(v,v,&one);
+
+    if (CURVE_A_ZZZ==-1)
+    {
+        FP_YYY_add(v,v,&one);
+        FP_YYY_norm(v);
+        FP_YYY_neg(v,v);
+    }
+	FP_YYY_norm(v);
+	FP_YYY_inv(&t,&t);
+	FP_YYY_mul(v,v,&t);
+	FP_YYY_reduce(v);
+#endif
+
+#if CURVETYPE_ZZZ==MONTGOMERY
+    /* x^3+Ax^2+x */
+    FP_YYY x2,x3;
+    FP_YYY_sqr(&x2,x);
+    FP_YYY_mul(&x3,&x2,x);
+    FP_YYY_copy(v,x);
+    FP_YYY_imul(&x2,&x2,CURVE_A_ZZZ);
+    FP_YYY_add(v,v,&x2);
+    FP_YYY_add(v,v,&x3);
+    FP_YYY_reduce(v);
+#endif
+}
+
+/* Set P=(x,y) */
+
+#if CURVETYPE_ZZZ==MONTGOMERY
+
+/* Set P=(x,{y}) */
+
+int ECP_ZZZ_set(ECP_ZZZ *P,BIG_XXX x)
+{
+    BIG_XXX m,b;
+    FP_YYY rhs;
+    BIG_XXX_rcopy(m,Modulus_YYY);
+
+    FP_YYY_nres(&rhs,x);
+
+    ECP_ZZZ_rhs(&rhs,&rhs);
+    FP_YYY_redc(b,&rhs);
+
+    if (BIG_XXX_jacobi(b,m)!=1)
+    {
+        ECP_ZZZ_inf(P);
+        return 0;
+    }
+ //   P->inf=0;
+    FP_YYY_nres(&(P->x),x);
+    FP_YYY_one(&(P->z));
+    return 1;
+}
+
+/* Extract x coordinate as BIG */
+int ECP_ZZZ_get(BIG_XXX x,ECP_ZZZ *P)
+{
+	ECP_ZZZ W;
+	ECP_ZZZ_copy(&W,P);
+	ECP_ZZZ_affine(&W);
+    if (ECP_ZZZ_isinf(&W)) return -1;
+    //ECP_ZZZ_affine(P);
+    FP_YYY_redc(x,&(Wx));
+    return 0;
+}
+
+
+#else
+/* Extract (x,y) and return sign of y. If x and y are the same return only x */
+/* SU=16 */
+int ECP_ZZZ_get(BIG_XXX x,BIG_XXX y,ECP_ZZZ *P)
+{
+	ECP_ZZZ W;
+    int s;
+	ECP_ZZZ_copy(&W,P);
+	ECP_ZZZ_affine(&W);
+
+    if (ECP_ZZZ_isinf(&W)) return -1;
+
+    //ECP_ZZZ_affine(P);
+
+    FP_YYY_redc(y,&(W.y));
+    s=BIG_XXX_parity(y);
+
+    FP_YYY_redc(x,&(W.x));
+
+    return s;
+}
+
+/* Set P=(x,{y}) */
+/* SU=96 */
+int ECP_ZZZ_set(ECP_ZZZ *P,BIG_XXX x,BIG_XXX y)
+{
+    FP_YYY rhs,y2;
+
+    FP_YYY_nres(&y2,y);
+    FP_YYY_sqr(&y2,&y2);
+    FP_YYY_reduce(&y2);
+
+    FP_YYY_nres(&rhs,x);
+    ECP_ZZZ_rhs(&rhs,&rhs);
+
+    if (!FP_YYY_equals(&y2,&rhs))
+    {
+        ECP_ZZZ_inf(P);
+        return 0;
+    }
+
+   // P->inf=0;
+
+    FP_YYY_nres(&(P->x),x);
+    FP_YYY_nres(&(P->y),y);
+    FP_YYY_one(&(P->z));
+    return 1;
+}
+
+/* Set P=(x,y), where y is calculated from x with sign s */
+/* SU=136 */
+int ECP_ZZZ_setx(ECP_ZZZ *P,BIG_XXX x,int s)
+{
+    FP_YYY rhs;
+    BIG_XXX t,m;
+    BIG_XXX_rcopy(m,Modulus_YYY);
+
+    FP_YYY_nres(&rhs,x);
+
+    ECP_ZZZ_rhs(&rhs,&rhs);
+
+    FP_YYY_redc(t,&rhs);
+    if (BIG_XXX_jacobi(t,m)!=1)
+    {
+        ECP_ZZZ_inf(P);
+        return 0;
+    }
+
+  //  P->inf=0;
+
+    FP_YYY_nres(&(P->x),x);
+    FP_YYY_sqrt(&(P->y),&rhs);
+
+//printf("SR= "); FP_YYY_output(&(P->y)); printf("\n");
+
+    FP_YYY_redc(t,&(P->y));
+
+//printf("t= "); BIG_XXX_output(t); printf("\n");
+
+    if (BIG_XXX_parity(t)!=s)
+        FP_YYY_neg(&(P->y),&(P->y));
+    FP_YYY_reduce(&(P->y));
+    FP_YYY_one(&(P->z));
+    return 1;
+}
+
+#endif
+
+void ECP_ZZZ_cfp(ECP_ZZZ *P)
+{ /* multiply point by curves cofactor */
+	BIG_XXX c;
+	int cf=CURVE_Cof_I_ZZZ;
+	if (cf==1) return;
+	if (cf==4)
+	{
+		ECP_ZZZ_dbl(P);
+		ECP_ZZZ_dbl(P);
+		//ECP_ZZZ_affine(P);
+		return;
+	}
+	if (cf==8)
+	{
+		ECP_ZZZ_dbl(P);
+		ECP_ZZZ_dbl(P);
+		ECP_ZZZ_dbl(P);
+		//ECP_ZZZ_affine(P);
+		return;
+	}
+	BIG_XXX_rcopy(c,CURVE_Cof_ZZZ);
+	ECP_ZZZ_mul(P,c);
+	return;
+}
+
+/* map BIG to point on curve of correct order */
+/* The BIG should be the output of some hash function */
+
+void ECP_ZZZ_mapit(ECP_ZZZ *P,octet *W)
+{
+    BIG_XXX q,x;
+	BIG_XXX_fromBytes(x,W->val);
+    BIG_XXX_rcopy(q,Modulus_YYY);
+    BIG_XXX_mod(x,q);
+
+	for (;;)
+	{
+		for (;;)
+		{
+#if CURVETYPE_ZZZ!=MONTGOMERY
+			ECP_ZZZ_setx(P,x,0);
+#else
+			ECP_ZZZ_set(P,x);
+#endif
+			BIG_XXX_inc(x,1); BIG_XXX_norm(x);
+			if (!ECP_ZZZ_isinf(P)) break;
+		}
+		ECP_ZZZ_cfp(P);
+		if (!ECP_ZZZ_isinf(P)) break;
+	}
+}
+
+/* Convert P to Affine, from (x,y,z) to (x,y) */
+/* SU=160 */
+void ECP_ZZZ_affine(ECP_ZZZ *P)
+{
+    FP_YYY one,iz;
+    BIG_XXX b;
+    if (ECP_ZZZ_isinf(P)) return;
+    FP_YYY_one(&one);
+    if (FP_YYY_equals(&(P->z),&one)) return;
+
+	FP_YYY_inv(&iz,&(P->z));
+    FP_YYY_mul(&(P->x),&(P->x),&iz);
+
+#if CURVETYPE_ZZZ==EDWARDS || CURVETYPE_ZZZ==WEIERSTRASS
+
+    FP_YYY_mul(&(P->y),&(P->y),&iz);
+    FP_YYY_reduce(&(P->y));
+
+#endif
+
+    FP_YYY_reduce(&(P->x));
+    FP_YYY_copy(&(P->z),&one);
+}
+
+/* SU=120 */
+void ECP_ZZZ_outputxyz(ECP_ZZZ *P)
+{
+    BIG_XXX x,z;
+    if (ECP_ZZZ_isinf(P))
+    {
+        printf("Infinity\n");
+        return;
+    }
+    FP_YYY_reduce(&(P->x));
+    FP_YYY_redc(x,&(P->x));
+    FP_YYY_reduce(&(P->z));
+    FP_YYY_redc(z,&(P->z));
+
+#if CURVETYPE_ZZZ!=MONTGOMERY
+    BIG_XXX y;
+    FP_YYY_reduce(&(P->y));
+    FP_YYY_redc(y,&(P->y));
+    printf("(");
+    BIG_XXX_output(x);
+    printf(",");
+    BIG_XXX_output(y);
+    printf(",");
+    BIG_XXX_output(z);
+    printf(")\n");
+
+#else
+    printf("(");
+    BIG_XXX_output(x);
+    printf(",");
+    BIG_XXX_output(z);
+    printf(")\n");
+#endif
+}
+
+/* SU=16 */
+/* Output point P */
+void ECP_ZZZ_output(ECP_ZZZ *P)
+{
+    BIG_XXX x;
+    if (ECP_ZZZ_isinf(P))
+    {
+        printf("Infinity\n");
+        return;
+    }
+    ECP_ZZZ_affine(P);
+#if CURVETYPE_ZZZ!=MONTGOMERY
+    BIG_XXX y;
+    FP_YYY_redc(x,&(P->x));
+    FP_YYY_redc(y,&(P->y));
+    printf("(");
+    BIG_XXX_output(x);
+    printf(",");
+    BIG_XXX_output(y);
+    printf(")\n");
+#else
+    FP_YYY_redc(x,&(P->x));
+    printf("(");
+    BIG_XXX_output(x);
+    printf(")\n");
+#endif
+}
+
+/* SU=16 */
+/* Output point P */
+void ECP_ZZZ_rawoutput(ECP_ZZZ *P)
+{
+    BIG_XXX x,z;
+//   if (ECP_ZZZ_isinf(P))
+//   {
+//       printf("Infinity\n");
+//       return;
+//   }
+//    ECP_ZZZ_affine(P);
+#if CURVETYPE_ZZZ!=MONTGOMERY
+    BIG_XXX y;
+    FP_YYY_redc(x,&(P->x));
+    FP_YYY_redc(y,&(P->y));
+    FP_YYY_redc(z,&(P->z));
+    printf("(");
+    BIG_XXX_output(x);
+    printf(",");
+    BIG_XXX_output(y);
+    printf(",");
+    BIG_XXX_output(z);
+    printf(")\n");
+#else
+    FP_YYY_redc(x,&(P->x));
+    FP_YYY_redc(z,&(P->z));
+    printf("(");
+    BIG_XXX_output(x);
+    printf(",");
+    BIG_XXX_output(z);
+    printf(")\n");
+#endif
+}
+
+/* SU=88 */
+/* Convert P to octet string */
+void ECP_ZZZ_toOctet(octet *W,ECP_ZZZ *P,bool compress)
+{
+#if CURVETYPE_ZZZ==MONTGOMERY
+    BIG_XXX x;
+    ECP_ZZZ_get(x,P);
+    W->len=MODBYTES_XXX+1;
+    W->val[0]=6;
+    BIG_XXX_toBytes(&(W->val[1]),x);
+#else
+    BIG_XXX x,y;
+    ECP_ZZZ_get(x,y,P);
+	if (compress)
+	{
+		W->val[0]=0x02;
+		if (BIG_XXX_parity(y)==1) W->val[0]=0x03;
+		W->len=MODBYTES_XXX+1;
+		BIG_XXX_toBytes(&(W->val[1]),x);
+	}
+	else
+	{
+		W->val[0]=4;
+		W->len=2*MODBYTES_XXX+1;
+		BIG_XXX_toBytes(&(W->val[1]),x);
+		BIG_XXX_toBytes(&(W->val[MODBYTES_XXX+1]),y);
+	}
+#endif
+}
+
+/* SU=88 */
+/* Restore P from octet string */
+int ECP_ZZZ_fromOctet(ECP_ZZZ *P,octet *W)
+{
+#if CURVETYPE_ZZZ==MONTGOMERY
+    BIG_XXX x;
+    BIG_XXX_fromBytes(x,&(W->val[1]));
+    if (ECP_ZZZ_set(P,x)) return 1;
+    return 0;
+#else
+    BIG_XXX x,y;
+	int typ=W->val[0];
+	BIG_XXX_fromBytes(x,&(W->val[1]));
+	if (typ==0x04)
+	{
+		BIG_XXX_fromBytes(y,&(W->val[MODBYTES_XXX+1]));
+		if (ECP_ZZZ_set(P,x,y)) return 1;
+	}
+	if (typ==0x02 || typ==0x03)
+	{
+		if (ECP_ZZZ_setx(P,x,typ&1)) return 1;
+	}
+    return 0;
+#endif
+}
+
+
+/* Set P=2P */
+/* SU=272 */
+void ECP_ZZZ_dbl(ECP_ZZZ *P)
+{
+#if CURVETYPE_ZZZ==WEIERSTRASS
+    FP_YYY t0,t1,t2,t3,x3,y3,z3,b;
+
+ //   if (ECP_ZZZ_isinf(P)) return;
+
+    if (CURVE_A_ZZZ==0)
+    {
+        //FP_YYY_copy(&t0,&(P->y));				//FP t0=new FP(y);
+        FP_YYY_sqr(&t0,&(P->y));					//t0.sqr();
+        //FP_YYY_copy(&t1,&(P->y));				//FP t1=new FP(y);
+        FP_YYY_mul(&t1,&(P->y),&(P->z));			//t1.mul(z);
+
+        //FP_YYY_copy(&t2,&(P->z));				//FP t2=new FP(z);
+        FP_YYY_sqr(&t2,&(P->z));					//t2.sqr();
+
+        //FP_YYY_copy(&(P->z),&t0);				//z.copy(t0);
+        FP_YYY_add(&(P->z),&t0,&t0);		//z.add(t0);
+        FP_YYY_norm(&(P->z));					//z.norm();
+        FP_YYY_add(&(P->z),&(P->z),&(P->z));	//z.add(z);
+        FP_YYY_add(&(P->z),&(P->z),&(P->z));	//z.add(z);
+        FP_YYY_norm(&(P->z));					//z.norm();
+
+        FP_YYY_imul(&t2,&t2,3*CURVE_B_I_ZZZ);		//t2.imul(3*ROM.CURVE_B_I);
+        //FP_YYY_copy(&x3,&t2);					//FP x3=new FP(t2);
+        FP_YYY_mul(&x3,&t2,&(P->z));			//x3.mul(z);
+
+        //FP_YYY_copy(&y3,&t0);					//FP y3=new FP(t0);
+        FP_YYY_add(&y3,&t0,&t2);				//y3.add(t2);
+        FP_YYY_norm(&y3);						//y3.norm();
+        FP_YYY_mul(&(P->z),&(P->z),&t1);		//z.mul(t1);
+
+        //FP_YYY_copy(&t1,&t2);					//t1.copy(t2);
+        FP_YYY_add(&t1,&t2,&t2);				//t1.add(t2);
+        FP_YYY_add(&t2,&t2,&t1);				//t2.add(t1);
+        FP_YYY_sub(&t0,&t0,&t2);				//t0.sub(t2);
+        FP_YYY_norm(&t0);						//t0.norm();
+        FP_YYY_mul(&y3,&y3,&t0);				//y3.mul(t0);
+        FP_YYY_add(&y3,&y3,&x3);				//y3.add(x3);
+        //FP_YYY_copy(&t1,&(P->x));				//t1.copy(x);                *** optimization possible
+        FP_YYY_mul(&t1,&(P->x),&(P->y));			//t1.mul(y);
+        //FP_YYY_copy(&(P->x),&t0);				//x.copy(t0);
+        FP_YYY_norm(&t0);					//x.norm();
+        FP_YYY_mul(&(P->x),&t0,&t1);		//x.mul(t1);
+        FP_YYY_add(&(P->x),&(P->x),&(P->x));	//x.add(x);
+        FP_YYY_norm(&(P->x));					//x.norm();
+        FP_YYY_copy(&(P->y),&y3);				//y.copy(y3);
+        FP_YYY_norm(&(P->y));					//y.norm();
+    }
+    else // its -3
+    {
+        //FP_YYY_copy(&t0,&(P->x));				//FP t0=new FP(x);
+        //FP_YYY_copy(&t1,&(P->y));				//FP t1=new FP(y);
+        //FP_YYY_copy(&t2,&(P->z));				//FP t2=new FP(z);
+        //FP_YYY_copy(&t3,&(P->x));				//FP t3=new FP(x);
+        //FP_YYY_copy(&z3,&(P->z));				//FP z3=new FP(z);
+
+        if (CURVE_B_I_ZZZ==0)					//if (ROM.CURVE_B_I==0)
+            FP_YYY_rcopy(&b,CURVE_B_ZZZ);		//b.copy(new FP(new BIG(ROM.CURVE_B)));
+
+        FP_YYY_sqr(&t0,&(P->x));					//t0.sqr();  //1    x^2
+        FP_YYY_sqr(&t1,&(P->y));					//t1.sqr();  //2    y^2
+        FP_YYY_sqr(&t2,&(P->z));					//t2.sqr();  //3
+
+        FP_YYY_mul(&t3,&(P->x),&(P->y));			//t3.mul(y); //4
+        FP_YYY_add(&t3,&t3,&t3);				//t3.add(t3);
+        FP_YYY_norm(&t3);						//t3.norm();//5
+
+        FP_YYY_mul(&z3,&(P->z),&(P->x));			//z3.mul(x);   //6
+        FP_YYY_add(&z3,&z3,&z3);				//z3.add(z3);
+        FP_YYY_norm(&z3);						//z3.norm();//7
+        //FP_YYY_copy(&y3,&t2);					//y3.copy(t2);
+
+        if (CURVE_B_I_ZZZ==0)						//if (ROM.CURVE_B_I==0)
+            FP_YYY_mul(&y3,&t2,&b);				//y3.mul(b); //8
+        else
+            FP_YYY_imul(&y3,&t2,CURVE_B_I_ZZZ);	//y3.imul(ROM.CURVE_B_I);
+
+        FP_YYY_sub(&y3,&y3,&z3);				//y3.sub(z3); //y3.norm(); //9  ***
+        //FP_YYY_copy(&x3,&y3);					//x3.copy(y3);
+        FP_YYY_add(&x3,&y3,&y3);				//x3.add(y3);
+        FP_YYY_norm(&x3);						//x3.norm();//10
+
+        FP_YYY_add(&y3,&y3,&x3);				//y3.add(x3); //y3.norm();//11
+        //FP_YYY_copy(&x3,&t1);					//x3.copy(t1);
+        FP_YYY_sub(&x3,&t1,&y3);				//x3.sub(y3);
+        FP_YYY_norm(&x3);						//x3.norm();//12
+        FP_YYY_add(&y3,&y3,&t1);				//y3.add(t1);
+        FP_YYY_norm(&y3);						//y3.norm();//13
+        FP_YYY_mul(&y3,&y3,&x3);				//y3.mul(x3); //14
+        FP_YYY_mul(&x3,&x3,&t3);				//x3.mul(t3); //15
+        //FP_YYY_copy(&t3,&t2);					//t3.copy(t2);
+        FP_YYY_add(&t3,&t2,&t2);				//t3.add(t2);  //16
+        FP_YYY_add(&t2,&t2,&t3);				//t2.add(t3); //17
+
+        if (CURVE_B_I_ZZZ==0)					//if (ROM.CURVE_B_I==0)
+            FP_YYY_mul(&z3,&z3,&b);				//z3.mul(b); //18
+        else
+            FP_YYY_imul(&z3,&z3,CURVE_B_I_ZZZ);	//z3.imul(ROM.CURVE_B_I);
+
+        FP_YYY_sub(&z3,&z3,&t2);				//z3.sub(t2); //z3.norm();//19
+        FP_YYY_sub(&z3,&z3,&t0);				//z3.sub(t0);
+        FP_YYY_norm(&z3);						//z3.norm();//20  ***
+        //FP_YYY_copy(&t3,&z3);					//t3.copy(z3);
+        FP_YYY_add(&t3,&z3,&z3);				//t3.add(z3); //t3.norm();//21
+
+        FP_YYY_add(&z3,&z3,&t3);				//z3.add(t3);
+        FP_YYY_norm(&z3);						//z3.norm(); //22
+        //FP_YYY_copy(&t3,&t0);					//t3.copy(t0);
+        FP_YYY_add(&t3,&t0,&t0);				//t3.add(t0); //t3.norm(); //23
+        FP_YYY_add(&t0,&t0,&t3);				//t0.add(t3); //t0.norm();//24
+        FP_YYY_sub(&t0,&t0,&t2);				//t0.sub(t2);
+        FP_YYY_norm(&t0);						//t0.norm();//25
+
+        FP_YYY_mul(&t0,&t0,&z3);				//t0.mul(z3);//26
+        FP_YYY_add(&y3,&y3,&t0);				//y3.add(t0); //y3.norm();//27
+        //FP_YYY_copy(&t0,&(P->y));				//t0.copy(y);
+        FP_YYY_mul(&t0,&(P->y),&(P->z));			//t0.mul(z);//28
+        FP_YYY_add(&t0,&t0,&t0);				//t0.add(t0);
+        FP_YYY_norm(&t0);						//t0.norm(); //29
+        FP_YYY_mul(&z3,&z3,&t0);				//z3.mul(t0);//30
+        FP_YYY_sub(&(P->x),&x3,&z3);				//x3.sub(z3); //x3.norm();//31
+        FP_YYY_add(&t0,&t0,&t0);				//t0.add(t0);
+        FP_YYY_norm(&t0);						//t0.norm();//32
+        FP_YYY_add(&t1,&t1,&t1);				//t1.add(t1);
+        FP_YYY_norm(&t1);						//t1.norm();//33
+        //FP_YYY_copy(&z3,&t0);					//z3.copy(t0);
+        FP_YYY_mul(&(P->z),&t0,&t1);				//z3.mul(t1);//34
+
+        //FP_YYY_copy(&(P->x),&x3);				//x.copy(x3);
+        FP_YYY_norm(&(P->x));					//x.norm();
+        FP_YYY_copy(&(P->y),&y3);				//y.copy(y3);
+        FP_YYY_norm(&(P->y));					//y.norm();
+        //FP_YYY_copy(&(P->z),&z3);				//z.copy(z3);
+        FP_YYY_norm(&(P->z));					//z.norm();
+    }
+#endif
+
+#if CURVETYPE_ZZZ==EDWARDS
+    /* Not using square for multiplication swap, as (1) it needs more adds, and (2) it triggers more reductions */
+
+    FP_YYY C,D,H,J;
+
+//    if (ECP_ZZZ_isinf(P)) return;
+
+    //FP_YYY_copy(&C,&(P->x));			//FP C=new FP(x);
+    FP_YYY_sqr(&C,&(P->x));							//C.sqr();
+    //FP_YYY_copy(&D,&(P->y));			//FP D=new FP(y);
+    //FP_YYY_copy(&H,&(P->z));			//FP H=new FP(z);
+
+    FP_YYY_mul(&(P->x),&(P->x),&(P->y));		//x.mul(y);
+    FP_YYY_add(&(P->x),&(P->x),&(P->x));		//x.add(x);
+    FP_YYY_norm(&(P->x));						//x.norm();
+
+    FP_YYY_sqr(&D,&(P->y));							//D.sqr();
+
+    if (CURVE_A_ZZZ==-1)				//if (ROM.CURVE_A==-1)
+        FP_YYY_neg(&C,&C);				//	C.neg();
+
+    //FP_YYY_copy(&(P->y),&C);			//y.copy(C);
+    FP_YYY_add(&(P->y),&C,&D);		//y.add(D);
+    FP_YYY_norm(&(P->y));				//y.norm();
+    FP_YYY_sqr(&H,&(P->z));					//H.sqr();
+    FP_YYY_add(&H,&H,&H);				//H.add(H);
+
+
+    //FP_YYY_copy(&(P->z),&(P->y));		//z.copy(y);
+    //FP_YYY_copy(&J,&(P->y));			//J.copy(y);
+
+    FP_YYY_sub(&J,&(P->y),&H);				//J.sub(H);
+    FP_YYY_norm(&J);					//J.norm();
+
+    FP_YYY_mul(&(P->x),&(P->x),&J);		//x.mul(J);
+    FP_YYY_sub(&C,&C,&D);				//C.sub(D);
+    FP_YYY_norm(&C);					//C.norm();
+    FP_YYY_mul(&(P->z),&(P->y),&J);		//z.mul(J);
+    FP_YYY_mul(&(P->y),&(P->y),&C);		//y.mul(C);
+
+
+#endif
+
+#if CURVETYPE_ZZZ==MONTGOMERY
+    FP_YYY A,B,AA,BB,C;
+
+//    if (ECP_ZZZ_isinf(P)) return;
+
+    //FP_YYY_copy(&A,&(P->x));			//FP A=new FP(x);
+    //FP_YYY_copy(&B,&(P->x));			//FP B=new FP(x);
+
+    FP_YYY_add(&A,&(P->x),&(P->z));			//A.add(z);
+    FP_YYY_norm(&A);					//A.norm();
+    //FP_YYY_copy(&AA,&A);				//AA.copy(A);
+    FP_YYY_sqr(&AA,&A);				//AA.sqr();
+    FP_YYY_sub(&B,&(P->x),&(P->z));			//B.sub(z);
+    FP_YYY_norm(&B);					//B.norm();
+    //FP_YYY_copy(&BB,&B);				//BB.copy(B);
+    FP_YYY_sqr(&BB,&B);				//BB.sqr();
+    //FP_YYY_copy(&C,&AA);				//C.copy(AA);
+    FP_YYY_sub(&C,&AA,&BB);				//C.sub(BB);
+    FP_YYY_norm(&C);					//C.norm();
+    //FP_YYY_copy(&(P->x),&AA);			//x.copy(AA);
+    FP_YYY_mul(&(P->x),&AA,&BB);	//x.mul(BB);
+
+    //FP_YYY_copy(&A,&C);					//A.copy(C);
+    FP_YYY_imul(&A,&C,(CURVE_A_ZZZ+2)/4);	//A.imul((ROM.CURVE_A+2)/4);
+
+    FP_YYY_add(&BB,&BB,&A);				//BB.add(A);
+    FP_YYY_norm(&BB);					//BB.norm();
+    //FP_YYY_copy(&(P->z),&BB);			//z.copy(BB);
+    FP_YYY_mul(&(P->z),&BB,&C);		//z.mul(C);
+
+#endif
+}
+
+#if CURVETYPE_ZZZ==MONTGOMERY
+
+/* Set P+=Q. W is difference between P and Q and is affine */
+void ECP_ZZZ_add(ECP_ZZZ *P,ECP_ZZZ *Q,ECP_ZZZ *W)
+{
+    FP_YYY A,B,C,D,DA,CB;
+
+    //FP_YYY_copy(&A,&(P->x));	//FP A=new FP(x);
+    //FP_YYY_copy(&B,&(P->x));	//FP B=new FP(x);
+    //FP_YYY_copy(&C,&(Q->x));	//FP C=new FP(Q.x);
+    //FP_YYY_copy(&D,&(Q->x));	//FP D=new FP(Q.x);
+
+    FP_YYY_add(&A,&(P->x),&(P->z));	//A.add(z);
+    FP_YYY_sub(&B,&(P->x),&(P->z));	//B.sub(z);
+
+    FP_YYY_add(&C,&(Q->x),&(Q->z));	//C.add(Q.z);
+
+    FP_YYY_sub(&D,&(Q->x),&(Q->z));	//D.sub(Q.z);
+    FP_YYY_norm(&A);			//A.norm();
+
+    FP_YYY_norm(&D);			//D.norm();
+    //FP_YYY_copy(&DA,&D);			//DA.copy(D);
+    FP_YYY_mul(&DA,&D,&A);			//DA.mul(A);
+
+
+
+    FP_YYY_norm(&C);			//C.norm();
+    FP_YYY_norm(&B);			//B.norm();
+    //FP_YYY_copy(&CB,&C);		//CB.copy(C);
+    FP_YYY_mul(&CB,&C,&B);		//CB.mul(B);
+
+    //FP_YYY_copy(&A,&DA);		//A.copy(DA);
+    FP_YYY_add(&A,&DA,&CB);		//A.add(CB);
+    FP_YYY_norm(&A);			//A.norm();
+    FP_YYY_sqr(&(P->x),&A);			//A.sqr();
+    //FP_YYY_copy(&B,&DA);		//B.copy(DA);
+    FP_YYY_sub(&B,&DA,&CB);		//B.sub(CB);
+    FP_YYY_norm(&B);			//B.norm();
+    FP_YYY_sqr(&B,&B);			//B.sqr();
+
+    //FP_YYY_copy(&(P->x),&A);	//x.copy(A);
+    //FP_YYY_copy(&(P->z),&(W->x));//z.copy(W.x);
+    FP_YYY_mul(&(P->z),&(W->x),&B);	//z.mul(B);
+
+}
+
+#else
+
+/* Set P+=Q */
+/* SU=248 */
+void ECP_ZZZ_add(ECP_ZZZ *P,ECP_ZZZ *Q)
+{
+#if CURVETYPE_ZZZ==WEIERSTRASS
+
+    int b3;
+    FP_YYY t0,t1,t2,t3,t4,x3,y3,z3,b;
+/*
+    if (ECP_ZZZ_isinf(Q)) return;
+    if (ECP_ZZZ_isinf(P))
+    {
+        ECP_ZZZ_copy(P,Q);
+        return;
+    }
+*/
+    if (CURVE_A_ZZZ==0)
+    {
+        b3=3*CURVE_B_I_ZZZ;					//int b=3*ROM.CURVE_B_I;
+        //FP_YYY_copy(&t0,&(P->x));			//FP t0=new FP(x);
+        FP_YYY_mul(&t0,&(P->x),&(Q->x));		//t0.mul(Q.x);
+        //FP_YYY_copy(&t1,&(P->y));			//FP t1=new FP(y);
+        FP_YYY_mul(&t1,&(P->y),&(Q->y));		//t1.mul(Q.y);
+        //FP_YYY_copy(&t2,&(P->z));			//FP t2=new FP(z);
+        FP_YYY_mul(&t2,&(P->z),&(Q->z));		//t2.mul(Q.z);
+        //FP_YYY_copy(&t3,&(P->x));			//FP t3=new FP(x);
+        FP_YYY_add(&t3,&(P->x),&(P->y));		//t3.add(y);
+        FP_YYY_norm(&t3);					//t3.norm();
+        //FP_YYY_copy(&t4,&(Q->x));			//FP t4=new FP(Q.x);
+        FP_YYY_add(&t4,&(Q->x),&(Q->y));		//t4.add(Q.y);
+        FP_YYY_norm(&t4);					//t4.norm();
+        FP_YYY_mul(&t3,&t3,&t4);			//t3.mul(t4);
+        //FP_YYY_copy(&t4,&t0);				//t4.copy(t0);
+        FP_YYY_add(&t4,&t0,&t1);			//t4.add(t1);
+
+        FP_YYY_sub(&t3,&t3,&t4);			//t3.sub(t4);
+        FP_YYY_norm(&t3);					//t3.norm();
+        //FP_YYY_copy(&t4,&(P->y));			//t4.copy(y);
+        FP_YYY_add(&t4,&(P->y),&(P->z));		//t4.add(z);
+        FP_YYY_norm(&t4);					//t4.norm();
+        //FP_YYY_copy(&x3,&(Q->y));			//FP x3=new FP(Q.y);
+        FP_YYY_add(&x3,&(Q->y),&(Q->z));		//x3.add(Q.z);
+        FP_YYY_norm(&x3);					//x3.norm();
+
+        FP_YYY_mul(&t4,&t4,&x3);			//t4.mul(x3);
+        //FP_YYY_copy(&x3,&t1);				//x3.copy(t1);
+        FP_YYY_add(&x3,&t1,&t2);			//x3.add(t2);
+
+        FP_YYY_sub(&t4,&t4,&x3);			//t4.sub(x3);
+        FP_YYY_norm(&t4);					//t4.norm();
+        //FP_YYY_copy(&x3,&(P->x));			//x3.copy(x);
+        FP_YYY_add(&x3,&(P->x),&(P->z));		//x3.add(z);
+        FP_YYY_norm(&x3);					//x3.norm();
+        //FP_YYY_copy(&y3,&(Q->x));			//FP y3=new FP(Q.x);
+        FP_YYY_add(&y3,&(Q->x),&(Q->z));		//y3.add(Q.z);
+        FP_YYY_norm(&y3);					//y3.norm();
+        FP_YYY_mul(&x3,&x3,&y3);			//x3.mul(y3);
+        //FP_YYY_copy(&y3,&t0);				//y3.copy(t0);
+        FP_YYY_add(&y3,&t0,&t2);			//y3.add(t2);
+        FP_YYY_sub(&y3,&x3,&y3);			//y3.rsub(x3);
+        FP_YYY_norm(&y3);					//y3.norm();
+        //FP_YYY_copy(&x3,&t0);				//x3.copy(t0);
+        FP_YYY_add(&x3,&t0,&t0);			//x3.add(t0);
+        FP_YYY_add(&t0,&t0,&x3);			//t0.add(x3);
+        FP_YYY_norm(&t0);					//t0.norm();
+        FP_YYY_imul(&t2,&t2,b3);				//t2.imul(b);
+
+        //FP_YYY_copy(&z3,&t1);				//FP z3=new FP(t1);
+        FP_YYY_add(&z3,&t1,&t2);			//z3.add(t2);
+        FP_YYY_norm(&z3);					//z3.norm();
+        FP_YYY_sub(&t1,&t1,&t2);			//t1.sub(t2);
+        FP_YYY_norm(&t1);					//t1.norm();
+        FP_YYY_imul(&y3,&y3,b3);				//y3.imul(b);
+
+        //FP_YYY_copy(&x3,&y3);				//x3.copy(y3);
+        FP_YYY_mul(&x3,&y3,&t4);			//x3.mul(t4);
+        //FP_YYY_copy(&t2,&t3);				//t2.copy(t3);
+        FP_YYY_mul(&t2,&t3,&t1);			//t2.mul(t1);
+        FP_YYY_sub(&(P->x),&t2,&x3);			//x3.rsub(t2);
+        FP_YYY_mul(&y3,&y3,&t0);			//y3.mul(t0);
+        FP_YYY_mul(&t1,&t1,&z3);			//t1.mul(z3);
+        FP_YYY_add(&(P->y),&y3,&t1);			//y3.add(t1);
+        FP_YYY_mul(&t0,&t0,&t3);			//t0.mul(t3);
+        FP_YYY_mul(&z3,&z3,&t4);			//z3.mul(t4);
+        FP_YYY_add(&(P->z),&z3,&t0);			//z3.add(t0);
+
+        //FP_YYY_copy(&(P->x),&x3);			//x.copy(x3);
+        FP_YYY_norm(&(P->x));				//x.norm();
+        //FP_YYY_copy(&(P->y),&y3);			//y.copy(y3);
+        FP_YYY_norm(&(P->y));				//y.norm();
+        //FP_YYY_copy(&(P->z),&z3);			//z.copy(z3);
+        FP_YYY_norm(&(P->z));				//z.norm();
+    }
+    else
+    {
+        //FP_YYY_copy(&t0,&(P->x));			//FP t0=new FP(x);
+        //FP_YYY_copy(&t1,&(P->y));			//FP t1=new FP(y);
+        //FP_YYY_copy(&t2,&(P->z));			//FP t2=new FP(z);
+        //FP_YYY_copy(&t3,&(P->x));			//FP t3=new FP(x);
+        //FP_YYY_copy(&t4,&(Q->x));			//FP t4=new FP(Q.x);
+
+        //FP_YYY_copy(&y3,&(Q->x));			//FP y3=new FP(Q.x);
+        //FP_YYY_copy(&x3,&(Q->y));			//FP x3=new FP(Q.y);
+
+        if (CURVE_B_I_ZZZ==0)				//if (ROM.CURVE_B_I==0)
+            FP_YYY_rcopy(&b,CURVE_B_ZZZ);	//b.copy(new FP(new BIG(ROM.CURVE_B)));
+
+        FP_YYY_mul(&t0,&(P->x),&(Q->x));		//t0.mul(Q.x); //1
+        FP_YYY_mul(&t1,&(P->y),&(Q->y));		//t1.mul(Q.y); //2
+        FP_YYY_mul(&t2,&(P->z),&(Q->z));		//t2.mul(Q.z); //3
+
+        FP_YYY_add(&t3,&(P->x),&(P->y));		//t3.add(y);
+        FP_YYY_norm(&t3);					//t3.norm(); //4
+        FP_YYY_add(&t4,&(Q->x),&(Q->y));		//t4.add(Q.y);
+        FP_YYY_norm(&t4);					//t4.norm();//5
+        FP_YYY_mul(&t3,&t3,&t4);			//t3.mul(t4);//6
+        //FP_YYY_copy(&t4,&t0);				//t4.copy(t0);
+        FP_YYY_add(&t4,&t0,&t1);			//t4.add(t1); //t4.norm(); //7
+        FP_YYY_sub(&t3,&t3,&t4);			//t3.sub(t4);
+        FP_YYY_norm(&t3);					//t3.norm(); //8
+        //FP_YYY_copy(&t4,&(P->y));			//t4.copy(y);
+        FP_YYY_add(&t4,&(P->y),&(P->z));		//t4.add(z);
+        FP_YYY_norm(&t4);					//t4.norm();//9
+        FP_YYY_add(&x3,&(Q->y),&(Q->z));		//x3.add(Q.z);
+        FP_YYY_norm(&x3);					//x3.norm();//10
+        FP_YYY_mul(&t4,&t4,&x3);			//t4.mul(x3); //11
+        //FP_YYY_copy(&x3,&t1);				//x3.copy(t1);
+        FP_YYY_add(&x3,&t1,&t2);			//x3.add(t2); //x3.norm();//12
+
+        FP_YYY_sub(&t4,&t4,&x3);			//t4.sub(x3);
+        FP_YYY_norm(&t4);					//t4.norm();//13
+        //FP_YYY_copy(&x3,&(P->x));			//x3.copy(x);
+        FP_YYY_add(&x3,&(P->x),&(P->z));		//x3.add(z);
+        FP_YYY_norm(&x3);					//x3.norm(); //14
+        FP_YYY_add(&y3,&(Q->x),&(Q->z));		//y3.add(Q.z);
+        FP_YYY_norm(&y3);					//y3.norm();//15
+
+        FP_YYY_mul(&x3,&x3,&y3);			//x3.mul(y3); //16
+        //FP_YYY_copy(&y3,&t0);				//y3.copy(t0);
+        FP_YYY_add(&y3,&t0,&t2);			//y3.add(t2); //y3.norm();//17
+
+        FP_YYY_sub(&y3,&x3,&y3);			//y3.rsub(x3);
+        FP_YYY_norm(&y3);					//y3.norm(); //18
+        //FP_YYY_copy(&z3,&t2);				//z3.copy(t2);
+
+        if (CURVE_B_I_ZZZ==0)				//if (ROM.CURVE_B_I==0)
+            FP_YYY_mul(&z3,&t2,&b);			//z3.mul(b); //18
+        else
+            FP_YYY_imul(&z3,&t2,CURVE_B_I_ZZZ);	//z3.imul(ROM.CURVE_B_I);
+
+        //FP_YYY_copy(&x3,&y3);				//x3.copy(y3);
+        FP_YYY_sub(&x3,&y3,&z3);			//x3.sub(z3);
+        FP_YYY_norm(&x3);					//x3.norm(); //20
+        //FP_YYY_copy(&z3,&x3);				//z3.copy(x3);
+        FP_YYY_add(&z3,&x3,&x3);			//z3.add(x3); //z3.norm(); //21
+
+        FP_YYY_add(&x3,&x3,&z3);			//x3.add(z3); //x3.norm(); //22
+        //FP_YYY_copy(&z3,&t1);				//z3.copy(t1);
+        FP_YYY_sub(&z3,&t1,&x3);			//z3.sub(x3);
+        FP_YYY_norm(&z3);					//z3.norm(); //23
+        FP_YYY_add(&x3,&x3,&t1);			//x3.add(t1);
+        FP_YYY_norm(&x3);					//x3.norm(); //24
+
+        if (CURVE_B_I_ZZZ==0)				//if (ROM.CURVE_B_I==0)
+            FP_YYY_mul(&y3,&y3,&b);			//y3.mul(b); //18
+        else
+            FP_YYY_imul(&y3,&y3,CURVE_B_I_ZZZ);	//y3.imul(ROM.CURVE_B_I);
+
+        //FP_YYY_copy(&t1,&t2);				//t1.copy(t2);
+        FP_YYY_add(&t1,&t2,&t2);			//t1.add(t2); //t1.norm();//26
+        FP_YYY_add(&t2,&t2,&t1);			//t2.add(t1); //t2.norm();//27
+
+        FP_YYY_sub(&y3,&y3,&t2);			//y3.sub(t2); //y3.norm(); //28
+
+        FP_YYY_sub(&y3,&y3,&t0);			//y3.sub(t0);
+        FP_YYY_norm(&y3);					//y3.norm(); //29
+        //FP_YYY_copy(&t1,&y3);				//t1.copy(y3);
+        FP_YYY_add(&t1,&y3,&y3);			//t1.add(y3); //t1.norm();//30
+        FP_YYY_add(&y3,&y3,&t1);			//y3.add(t1);
+        FP_YYY_norm(&y3);					//y3.norm(); //31
+
+        //FP_YYY_copy(&t1,&t0);				//t1.copy(t0);
+        FP_YYY_add(&t1,&t0,&t0);			//t1.add(t0); //t1.norm(); //32
+        FP_YYY_add(&t0,&t0,&t1);			//t0.add(t1); //t0.norm();//33
+        FP_YYY_sub(&t0,&t0,&t2);			//t0.sub(t2);
+        FP_YYY_norm(&t0);					//t0.norm();//34
+        //FP_YYY_copy(&t1,&t4);				//t1.copy(t4);
+        FP_YYY_mul(&t1,&t4,&y3);			//t1.mul(y3);//35
+        //FP_YYY_copy(&t2,&t0);				//t2.copy(t0);
+        FP_YYY_mul(&t2,&t0,&y3);			//t2.mul(y3);//36
+        //FP_YYY_copy(&y3,&x3);				//y3.copy(x3);
+        FP_YYY_mul(&y3,&x3,&z3);			//y3.mul(z3);//37
+        FP_YYY_add(&(P->y),&y3,&t2);			//y3.add(t2); //y3.norm();//38
+        FP_YYY_mul(&x3,&x3,&t3);			//x3.mul(t3);//39
+        FP_YYY_sub(&(P->x),&x3,&t1);			//x3.sub(t1);//40
+        FP_YYY_mul(&z3,&z3,&t4);			//z3.mul(t4);//41
+        //FP_YYY_copy(&t1,&t3);				//t1.copy(t3);
+        FP_YYY_mul(&t1,&t3,&t0);			//t1.mul(t0);//42
+        FP_YYY_add(&(P->z),&z3,&t1);			//z3.add(t1);
+        //FP_YYY_copy(&(P->x),&x3);			//x.copy(x3);
+        FP_YYY_norm(&(P->x));				//x.norm();
+        //FP_YYY_copy(&(P->y),&y3);			//y.copy(y3);
+        FP_YYY_norm(&(P->y));				//y.norm();
+        //FP_YYY_copy(&(P->z),&z3);			//z.copy(z3);
+        FP_YYY_norm(&(P->z));				//z.norm();
+    }
+
+#else
+    FP_YYY A,B,C,D,E,F,G,b;
+
+/*
+    if (ECP_ZZZ_isinf(Q)) return;
+    if (ECP_ZZZ_isinf(P))
+    {
+        ECP_ZZZ_copy(P,Q);
+        return;
+    }
+*/
+
+    //FP_YYY_copy(&A,&(P->z));		//FP A=new FP(z);
+    //FP_YYY_copy(&C,&(P->x));		//FP C=new FP(x);
+    //FP_YYY_copy(&D,&(P->y));		//FP D=new FP(y);
+
+    FP_YYY_mul(&A,&(P->z),&(Q->z));		//A.mul(Q.z);
+    //FP_YYY_copy(&B,&A);				//B.copy(A);
+    FP_YYY_sqr(&B,&A);				//B.sqr();
+    FP_YYY_mul(&C,&(P->x),&(Q->x));		//C.mul(Q.x);
+    FP_YYY_mul(&D,&(P->y),&(Q->y));		//D.mul(Q.y);
+
+    //FP_YYY_copy(&E,&C);				//E.copy(C);
+    FP_YYY_mul(&E,&C,&D);			//E.mul(D);
+
+    if (CURVE_B_I_ZZZ==0)			//if (ROM.CURVE_B_I==0)
+    {
+        FP_YYY_rcopy(&b,CURVE_B_ZZZ);	//FP b=new FP(new BIG(ROM.CURVE_B));
+        FP_YYY_mul(&E,&E,&b);			//E.mul(b);
+    }
+    else
+        FP_YYY_imul(&E,&E,CURVE_B_I_ZZZ);	//E.imul(ROM.CURVE_B_I);
+
+    //FP_YYY_copy(&F,&B);				//F.copy(B);
+    FP_YYY_sub(&F,&B,&E);			//F.sub(E);
+    //FP_YYY_copy(&G,&B);				//G.copy(B);
+    FP_YYY_add(&G,&B,&E);			//G.add(E);
+
+    if (CURVE_A_ZZZ==1)				//if (ROM.CURVE_A==1)
+    {
+        //FP_YYY_copy(&E,&D);			//E.copy(D);
+        FP_YYY_sub(&E,&D,&C);		//E.sub(C);
+    }
+    FP_YYY_add(&C,&C,&D);			//C.add(D);
+
+    //FP_YYY_copy(&B,&(P->x));		//B.copy(x);
+    FP_YYY_add(&B,&(P->x),&(P->y));		//B.add(y);
+    //FP_YYY_copy(&D,&(Q->x));		//D.copy(Q.x);
+    FP_YYY_add(&D,&(Q->x),&(Q->y));		//D.add(Q.y);
+    FP_YYY_norm(&B);				//B.norm();
+    FP_YYY_norm(&D);				//D.norm();
+    FP_YYY_mul(&B,&B,&D);			//B.mul(D);
+    FP_YYY_sub(&B,&B,&C);			//B.sub(C);
+    FP_YYY_norm(&B);				//B.norm();
+    FP_YYY_norm(&F);				//F.norm();
+    FP_YYY_mul(&B,&B,&F);			//B.mul(F);
+    //FP_YYY_copy(&(P->x),&A);		//x.copy(A);
+    FP_YYY_mul(&(P->x),&A,&B); //x.mul(B);
+    FP_YYY_norm(&G);				//G.norm();
+
+    if (CURVE_A_ZZZ==1)				//if (ROM.CURVE_A==1)
+    {
+        FP_YYY_norm(&E);			//E.norm();
+        //FP_YYY_copy(&C,&E);			//C.copy(E);
+        FP_YYY_mul(&C,&E,&G);		//C.mul(G);
+    }
+    if (CURVE_A_ZZZ==-1)			//if (ROM.CURVE_A==-1)
+    {
+        FP_YYY_norm(&C);			//C.norm();
+        FP_YYY_mul(&C,&C,&G);		//C.mul(G);
+    }
+    //FP_YYY_copy(&(P->y),&A);		//y.copy(A);
+    FP_YYY_mul(&(P->y),&A,&C);	//y.mul(C);
+
+    //FP_YYY_copy(&(P->z),&F);		//z.copy(F);
+    FP_YYY_mul(&(P->z),&F,&G);	//z.mul(G);
+
+#endif
+}
+
+/* Set P-=Q */
+/* SU=16 */
+void  ECP_ZZZ_sub(ECP_ZZZ *P,ECP_ZZZ *Q)
+{
+	ECP_ZZZ NQ;
+	ECP_ZZZ_copy(&NQ,Q);
+	ECP_ZZZ_neg(&NQ);
+    //ECP_ZZZ_neg(Q);
+    ECP_ZZZ_add(P,&NQ);
+    //ECP_ZZZ_neg(Q);
+}
+
+#endif
+
+#if CURVETYPE_ZZZ!=MONTGOMERY
+/* constant time multiply by small integer of length bts - use ladder */
+void ECP_ZZZ_pinmul(ECP_ZZZ *P,int e,int bts)
+{
+    int i,b;
+    ECP_ZZZ R0,R1;
+
+    ECP_ZZZ_affine(P);
+    ECP_ZZZ_inf(&R0);
+    ECP_ZZZ_copy(&R1,P);
+
+    for (i=bts-1; i>=0; i--)
+    {
+        b=(e>>i)&1;
+        ECP_ZZZ_copy(P,&R1);
+        ECP_ZZZ_add(P,&R0);
+        ECP_ZZZ_cswap(&R0,&R1,b);
+        ECP_ZZZ_copy(&R1,P);
+        ECP_ZZZ_dbl(&R0);
+        ECP_ZZZ_cswap(&R0,&R1,b);
+    }
+    ECP_ZZZ_copy(P,&R0);
+    ECP_ZZZ_affine(P);
+}
+#endif
+
+/* Set P=r*P */
+/* SU=424 */
+void ECP_ZZZ_mul(ECP_ZZZ *P,BIG_XXX e)
+{
+#if CURVETYPE_ZZZ==MONTGOMERY
+    /* Montgomery ladder */
+    int nb,i,b;
+    ECP_ZZZ R0,R1,D;
+    if (ECP_ZZZ_isinf(P)) return;
+    if (BIG_XXX_iszilch(e))
+    {
+        ECP_ZZZ_inf(P);
+        return;
+    }
+    //ECP_ZZZ_affine(P);
+
+    ECP_ZZZ_copy(&R0,P);
+    ECP_ZZZ_copy(&R1,P);
+    ECP_ZZZ_dbl(&R1);
+
+    ECP_ZZZ_copy(&D,P);
+    ECP_ZZZ_affine(&D);
+
+    nb=BIG_XXX_nbits(e);
+    for (i=nb-2; i>=0; i--)
+    {
+        b=BIG_XXX_bit(e,i);
+        ECP_ZZZ_copy(P,&R1);
+        ECP_ZZZ_add(P,&R0,&D);
+        ECP_ZZZ_cswap(&R0,&R1,b);
+        ECP_ZZZ_copy(&R1,P);
+        ECP_ZZZ_dbl(&R0);
+
+        ECP_ZZZ_cswap(&R0,&R1,b);
+    }
+
+    ECP_ZZZ_copy(P,&R0);
+
+#else
+    /* fixed size windows */
+    int i,nb,s,ns;
+    BIG_XXX mt,t;
+    ECP_ZZZ Q,W[8],C;
+    sign8 w[1+(NLEN_XXX*BASEBITS_XXX+3)/4];
+
+    if (ECP_ZZZ_isinf(P)) return;
+    if (BIG_XXX_iszilch(e))
+    {
+        ECP_ZZZ_inf(P);
+        return;
+    }
+
+    ECP_ZZZ_affine(P);
+
+    /* precompute table */
+
+    ECP_ZZZ_copy(&Q,P);
+    ECP_ZZZ_dbl(&Q);
+
+    ECP_ZZZ_copy(&W[0],P);
+
+    for (i=1; i<8; i++)
+    {
+        ECP_ZZZ_copy(&W[i],&W[i-1]);
+        ECP_ZZZ_add(&W[i],&Q);
+    }
+
+//printf("W[1]= ");ECP_output(&W[1]); printf("\n");
+
+    /* make exponent odd - add 2P if even, P if odd */
+    BIG_XXX_copy(t,e);
+    s=BIG_XXX_parity(t);
+    BIG_XXX_inc(t,1);
+    BIG_XXX_norm(t);
+    ns=BIG_XXX_parity(t);
+    BIG_XXX_copy(mt,t);
+    BIG_XXX_inc(mt,1);
+    BIG_XXX_norm(mt);
+    BIG_XXX_cmove(t,mt,s);
+    ECP_ZZZ_cmove(&Q,P,ns);
+    ECP_ZZZ_copy(&C,&Q);
+
+    nb=1+(BIG_XXX_nbits(t)+3)/4;
+
+    /* convert exponent to signed 4-bit window */
+    for (i=0; i<nb; i++)
+    {
+        w[i]=BIG_XXX_lastbits(t,5)-16;
+        BIG_XXX_dec(t,w[i]);
+        BIG_XXX_norm(t);
+        BIG_XXX_fshr(t,4);
+    }
+    w[nb]=BIG_XXX_lastbits(t,5);
+
+    ECP_ZZZ_copy(P,&W[(w[nb]-1)/2]);
+    for (i=nb-1; i>=0; i--)
+    {
+        ECP_ZZZ_select(&Q,W,w[i]);
+        ECP_ZZZ_dbl(P);
+        ECP_ZZZ_dbl(P);
+        ECP_ZZZ_dbl(P);
+        ECP_ZZZ_dbl(P);
+        ECP_ZZZ_add(P,&Q);
+    }
+    ECP_ZZZ_sub(P,&C); /* apply correction */
+#endif
+    ECP_ZZZ_affine(P);
+}
+
+#if CURVETYPE_ZZZ!=MONTGOMERY
+/* Set P=eP+fQ double multiplication */
+/* constant time - as useful for GLV method in pairings */
+/* SU=456 */
+
+void ECP_ZZZ_mul2(ECP_ZZZ *P,ECP_ZZZ *Q,BIG_XXX e,BIG_XXX f)
+{
+    BIG_XXX te,tf,mt;
+    ECP_ZZZ S,T,W[8],C;
+    sign8 w[1+(NLEN_XXX*BASEBITS_XXX+1)/2];
+    int i,a,b,s,ns,nb;
+
+    //ECP_ZZZ_affine(P);
+    //ECP_ZZZ_affine(Q);
+
+    BIG_XXX_copy(te,e);
+    BIG_XXX_copy(tf,f);
+
+    /* precompute table */
+    ECP_ZZZ_copy(&W[1],P);
+    ECP_ZZZ_sub(&W[1],Q);  /* P+Q */
+    ECP_ZZZ_copy(&W[2],P);
+    ECP_ZZZ_add(&W[2],Q);  /* P-Q */
+    ECP_ZZZ_copy(&S,Q);
+    ECP_ZZZ_dbl(&S);  /* S=2Q */
+    ECP_ZZZ_copy(&W[0],&W[1]);
+    ECP_ZZZ_sub(&W[0],&S);
+    ECP_ZZZ_copy(&W[3],&W[2]);
+    ECP_ZZZ_add(&W[3],&S);
+    ECP_ZZZ_copy(&T,P);
+    ECP_ZZZ_dbl(&T); /* T=2P */
+    ECP_ZZZ_copy(&W[5],&W[1]);
+    ECP_ZZZ_add(&W[5],&T);
+    ECP_ZZZ_copy(&W[6],&W[2]);
+    ECP_ZZZ_add(&W[6],&T);
+    ECP_ZZZ_copy(&W[4],&W[5]);
+    ECP_ZZZ_sub(&W[4],&S);
+    ECP_ZZZ_copy(&W[7],&W[6]);
+    ECP_ZZZ_add(&W[7],&S);
+
+    /* if multiplier is odd, add 2, else add 1 to multiplier, and add 2P or P to correction */
+
+    s=BIG_XXX_parity(te);
+    BIG_XXX_inc(te,1);
+    BIG_XXX_norm(te);
+    ns=BIG_XXX_parity(te);
+    BIG_XXX_copy(mt,te);
+    BIG_XXX_inc(mt,1);
+    BIG_XXX_norm(mt);
+    BIG_XXX_cmove(te,mt,s);
+    ECP_ZZZ_cmove(&T,P,ns);
+    ECP_ZZZ_copy(&C,&T);
+
+    s=BIG_XXX_parity(tf);
+    BIG_XXX_inc(tf,1);
+    BIG_XXX_norm(tf);
+    ns=BIG_XXX_parity(tf);
+    BIG_XXX_copy(mt,tf);
+    BIG_XXX_inc(mt,1);
+    BIG_XXX_norm(mt);
+    BIG_XXX_cmove(tf,mt,s);
+    ECP_ZZZ_cmove(&S,Q,ns);
+    ECP_ZZZ_add(&C,&S);
+
+    BIG_XXX_add(mt,te,tf);
+    BIG_XXX_norm(mt);
+    nb=1+(BIG_XXX_nbits(mt)+1)/2;
+
+    /* convert exponent to signed 2-bit window */
+    for (i=0; i<nb; i++)
+    {
+        a=BIG_XXX_lastbits(te,3)-4;
+        BIG_XXX_dec(te,a);
+        BIG_XXX_norm(te);
+        BIG_XXX_fshr(te,2);
+        b=BIG_XXX_lastbits(tf,3)-4;
+        BIG_XXX_dec(tf,b);
+        BIG_XXX_norm(tf);
+        BIG_XXX_fshr(tf,2);
+        w[i]=4*a+b;
+    }
+    w[nb]=(4*BIG_XXX_lastbits(te,3)+BIG_XXX_lastbits(tf,3));
+
+    ECP_ZZZ_copy(P,&W[(w[nb]-1)/2]);
+    for (i=nb-1; i>=0; i--)
+    {
+        ECP_ZZZ_select(&T,W,w[i]);
+        ECP_ZZZ_dbl(P);
+        ECP_ZZZ_dbl(P);
+        ECP_ZZZ_add(P,&T);
+    }
+    ECP_ZZZ_sub(P,&C); /* apply correction */
+    ECP_ZZZ_affine(P);
+}
+
+#endif
+
+void ECP_ZZZ_generator(ECP_ZZZ *G)
+{
+	BIG_XXX x,y;
+	BIG_XXX_rcopy(x,CURVE_Gx_ZZZ);
+#if CURVETYPE_ZZZ!=MONTGOMERY
+	BIG_XXX_rcopy(y,CURVE_Gy_ZZZ);
+    ECP_ZZZ_set(G,x,y);
+#else
+	ECP_ZZZ_set(G,x);
+#endif
+}
+
+#ifdef HAS_MAIN
+
+int main()
+{
+    int i;
+    ECP_ZZZ G,P;
+    csprng RNG;
+    BIG_XXX r,s,x,y,b,m,w,q;
+    BIG_XXX_rcopy(x,CURVE_Gx);
+#if CURVETYPE_ZZZ!=MONTGOMERY
+    BIG_XXX_rcopy(y,CURVE_Gy);
+#endif
+    BIG_XXX_rcopy(m,Modulus_YYY);
+
+    printf("x= ");
+    BIG_XXX_output(x);
+    printf("\n");
+#if CURVETYPE_ZZZ!=MONTGOMERY
+    printf("y= ");
+    BIG_XXX_output(y);
+    printf("\n");
+#endif
+    RNG_seed(&RNG,3,"abc");
+
+#if CURVETYPE_ZZZ!=MONTGOMERY
+    ECP_ZZZ_set(&G,x,y);
+#else
+    ECP_ZZZ_set(&G,x);
+#endif
+    if (ECP_ZZZ_isinf(&G)) printf("Failed to set - point not on curve\n");
+    else printf("set success\n");
+
+    ECP_ZZZ_output(&G);
+
+    BIG_XXX_rcopy(r,CURVE_Order); //BIG_dec(r,7);
+    printf("r= ");
+    BIG_XXX_output(r);
+    printf("\n");
+
+    ECP_ZZZ_copy(&P,&G);
+
+    ECP_ZZZ_mul(&P,r);
+
+    ECP_ZZZ_output(&P);
+//exit(0);
+    BIG_XXX_randomnum(w,&RNG);
+    BIG_XXX_mod(w,r);
+
+    ECP_ZZZ_copy(&P,&G);
+    ECP_ZZZ_mul(&P,w);
+
+    ECP_ZZZ_output(&P);
+
+    return 0;
+}
+
+#endif
diff --git a/version3/c/ecp.h b/version3/c/ecp.h
new file mode 100644
index 0000000..01dac7c
--- /dev/null
+++ b/version3/c/ecp.h
@@ -0,0 +1,314 @@
+/*
+	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.
+*/
+
+/**
+ * @file ecp.h
+ * @author Mike Scott
+ * @brief ECP Header File
+ *
+ */
+
+#ifndef ECP_ZZZ_H
+#define ECP_ZZZ_H
+
+#include "fp_YYY.h"
+#include "config_curve_ZZZ.h"
+
+/* Curve Params - see rom_zzz.c */
+extern const int CURVE_A_ZZZ;         /**< Elliptic curve A parameter */
+extern const int CURVE_Cof_I_ZZZ;     /**< Elliptic curve cofactor */
+extern const int CURVE_B_I_ZZZ;       /**< Elliptic curve B_i parameter */
+extern const BIG_XXX CURVE_B_ZZZ;     /**< Elliptic curve B parameter */
+extern const BIG_XXX CURVE_Order_ZZZ; /**< Elliptic curve group order */
+extern const BIG_XXX CURVE_Cof_ZZZ;   /**< Elliptic curve cofactor */
+
+/* Generator point on G1 */
+extern const BIG_XXX CURVE_Gx_ZZZ; /**< x-coordinate of generator point in group G1  */
+extern const BIG_XXX CURVE_Gy_ZZZ; /**< y-coordinate of generator point in group G1  */
+
+
+/* For Pairings only */
+
+/* Generator point on G2 */
+extern const BIG_XXX CURVE_Pxa_ZZZ; /**< real part of x-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pxb_ZZZ; /**< imaginary part of x-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pya_ZZZ; /**< real part of y-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pyb_ZZZ; /**< imaginary part of y-coordinate of generator point in group G2 */
+
+
+/*** needed for BLS24 curves ***/
+
+extern const BIG_XXX CURVE_Pxaa_ZZZ; /**< real part of x-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pxab_ZZZ; /**< imaginary part of x-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pxba_ZZZ; /**< real part of x-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pxbb_ZZZ; /**< imaginary part of x-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pyaa_ZZZ; /**< real part of y-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pyab_ZZZ; /**< imaginary part of y-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pyba_ZZZ; /**< real part of y-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pybb_ZZZ; /**< imaginary part of y-coordinate of generator point in group G2 */
+
+/*** needed for BLS48 curves ***/
+
+extern const BIG_XXX CURVE_Pxaaa_ZZZ; /**< real part of x-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pxaab_ZZZ; /**< imaginary part of x-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pxaba_ZZZ; /**< real part of x-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pxabb_ZZZ; /**< imaginary part of x-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pxbaa_ZZZ; /**< real part of x-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pxbab_ZZZ; /**< imaginary part of x-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pxbba_ZZZ; /**< real part of x-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pxbbb_ZZZ; /**< imaginary part of x-coordinate of generator point in group G2 */
+
+extern const BIG_XXX CURVE_Pyaaa_ZZZ; /**< real part of y-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pyaab_ZZZ; /**< imaginary part of y-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pyaba_ZZZ; /**< real part of y-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pyabb_ZZZ; /**< imaginary part of y-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pybaa_ZZZ; /**< real part of y-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pybab_ZZZ; /**< imaginary part of y-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pybba_ZZZ; /**< real part of y-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pybbb_ZZZ; /**< imaginary part of y-coordinate of generator point in group G2 */
+
+
+extern const BIG_XXX CURVE_Bnx_ZZZ; /**< BN curve x parameter */
+
+extern const BIG_XXX CURVE_Cru_ZZZ; /**< BN curve Cube Root of Unity */
+
+extern const BIG_XXX Fra_YYY; /**< real part of BN curve Frobenius Constant */
+extern const BIG_XXX Frb_YYY; /**< imaginary part of BN curve Frobenius Constant */
+
+
+extern const BIG_XXX CURVE_W_ZZZ[2];	 /**< BN curve constant for GLV decomposition */
+extern const BIG_XXX CURVE_SB_ZZZ[2][2]; /**< BN curve constant for GLV decomposition */
+extern const BIG_XXX CURVE_WB_ZZZ[4];	 /**< BN curve constant for GS decomposition */
+extern const BIG_XXX CURVE_BB_ZZZ[4][4]; /**< BN curve constant for GS decomposition */
+
+
+/**
+	@brief ECP structure - Elliptic Curve Point over base field
+*/
+
+typedef struct
+{
+//    int inf; /**< Infinity Flag - not needed for Edwards representation */
+
+    FP_YYY x; /**< x-coordinate of point */
+#if CURVETYPE_ZZZ!=MONTGOMERY
+    FP_YYY y; /**< y-coordinate of point. Not needed for Montgomery representation */
+#endif
+    FP_YYY z;/**< z-coordinate of point */
+} ECP_ZZZ;
+
+
+/* ECP E(Fp) prototypes */
+/**	@brief Tests for ECP point equal to infinity
+ *
+	@param P ECP point to be tested
+	@return 1 if infinity, else returns 0
+ */
+extern int ECP_ZZZ_isinf(ECP_ZZZ *P);
+/**	@brief Tests for equality of two ECPs
+ *
+	@param P ECP instance to be compared
+	@param Q ECP instance to be compared
+	@return 1 if P=Q, else returns 0
+ */
+extern int ECP_ZZZ_equals(ECP_ZZZ *P,ECP_ZZZ *Q);
+/**	@brief Copy ECP point to another ECP point
+ *
+	@param P ECP instance, on exit = Q
+	@param Q ECP instance to be copied
+ */
+extern void ECP_ZZZ_copy(ECP_ZZZ *P,ECP_ZZZ *Q);
+/**	@brief Negation of an ECP point
+ *
+	@param P ECP instance, on exit = -P
+ */
+extern void ECP_ZZZ_neg(ECP_ZZZ *P);
+/**	@brief Set ECP to point-at-infinity
+ *
+	@param P ECP instance to be set to infinity
+ */
+extern void ECP_ZZZ_inf(ECP_ZZZ *P);
+/**	@brief Calculate Right Hand Side of curve equation y^2=f(x)
+ *
+	Function f(x) depends on form of elliptic curve, Weierstrass, Edwards or Montgomery.
+	Used internally.
+	@param r BIG n-residue value of f(x)
+	@param x BIG n-residue x
+ */
+extern void ECP_ZZZ_rhs(FP_YYY *r,FP_YYY *x);
+
+#if CURVETYPE_ZZZ==MONTGOMERY
+/**	@brief Set ECP to point(x,[y]) given x
+ *
+	Point P set to infinity if no such point on the curve. Note that y coordinate is not needed.
+	@param P ECP instance to be set (x,[y])
+	@param x BIG x coordinate of point
+	@return 1 if point exists, else 0
+ */
+extern int ECP_ZZZ_set(ECP_ZZZ *P,BIG_XXX x);
+/**	@brief Extract x coordinate of an ECP point P
+ *
+	@param x BIG on exit = x coordinate of point
+	@param P ECP instance (x,[y])
+	@return -1 if P is point-at-infinity, else 0
+ */
+extern int ECP_ZZZ_get(BIG_XXX x,ECP_ZZZ *P);
+/**	@brief Adds ECP instance Q to ECP instance P, given difference D=P-Q
+ *
+	Differential addition of points on a Montgomery curve
+	@param P ECP instance, on exit =P+Q
+	@param Q ECP instance to be added to P
+	@param D Difference between P and Q
+ */
+extern void ECP_ZZZ_add(ECP_ZZZ *P,ECP_ZZZ *Q,ECP_ZZZ *D);
+#else
+/**	@brief Set ECP to point(x,y) given x and y
+ *
+	Point P set to infinity if no such point on the curve.
+	@param P ECP instance to be set (x,y)
+	@param x BIG x coordinate of point
+	@param y BIG y coordinate of point
+	@return 1 if point exists, else 0
+ */
+extern int ECP_ZZZ_set(ECP_ZZZ *P,BIG_XXX x,BIG_XXX y);
+/**	@brief Extract x and y coordinates of an ECP point P
+ *
+	If x=y, returns only x
+	@param x BIG on exit = x coordinate of point
+	@param y BIG on exit = y coordinate of point (unless x=y)
+	@param P ECP instance (x,y)
+	@return sign of y, or -1 if P is point-at-infinity
+ */
+extern int ECP_ZZZ_get(BIG_XXX x,BIG_XXX y,ECP_ZZZ *P);
+/**	@brief Adds ECP instance Q to ECP instance P
+ *
+	@param P ECP instance, on exit =P+Q
+	@param Q ECP instance to be added to P
+ */
+extern void ECP_ZZZ_add(ECP_ZZZ *P,ECP_ZZZ *Q);
+/**	@brief Subtracts ECP instance Q from ECP instance P
+ *
+	@param P ECP instance, on exit =P-Q
+	@param Q ECP instance to be subtracted from P
+ */
+extern void ECP_ZZZ_sub(ECP_ZZZ *P,ECP_ZZZ *Q);
+/**	@brief Set ECP to point(x,y) given just x and sign of y
+ *
+	Point P set to infinity if no such point on the curve. If x is on the curve then y is calculated from the curve equation.
+	The correct y value (plus or minus) is selected given its sign s.
+	@param P ECP instance to be set (x,[y])
+	@param x BIG x coordinate of point
+	@param s an integer representing the "sign" of y, in fact its least significant bit.
+ */
+extern int ECP_ZZZ_setx(ECP_ZZZ *P,BIG_XXX x,int s);
+
+#endif
+
+/**	@brief Multiplies Point by curve co-factor
+ *
+	@param Q ECP instance
+ */
+extern void ECP_ZZZ_cfp(ECP_ZZZ *Q);
+
+/**	@brief Maps random BIG to curve point of correct order
+ *
+	@param Q ECP instance of correct order
+	@param w OCTET byte array to be mapped
+ */
+extern void ECP_ZZZ_mapit(ECP_ZZZ *Q,octet *w);
+
+/**	@brief Converts an ECP point from Projective (x,y,z) coordinates to affine (x,y) coordinates
+ *
+	@param P ECP instance to be converted to affine form
+ */
+extern void ECP_ZZZ_affine(ECP_ZZZ *P);
+/**	@brief Formats and outputs an ECP point to the console, in projective coordinates
+ *
+	@param P ECP instance to be printed
+ */
+extern void ECP_ZZZ_outputxyz(ECP_ZZZ *P);
+/**	@brief Formats and outputs an ECP point to the console, converted to affine coordinates
+ *
+	@param P ECP instance to be printed
+ */
+extern void ECP_ZZZ_output(ECP_ZZZ * P);
+
+/**	@brief Formats and outputs an ECP point to the console
+ *
+	@param P ECP instance to be printed
+ */
+extern void ECP_ZZZ_rawoutput(ECP_ZZZ * P);
+
+/**	@brief Formats and outputs an ECP point to an octet string
+	The octet string is normally in the standard form 0x04|x|y
+	Here x (and y) are the x and y coordinates in left justified big-endian base 256 form.
+	For Montgomery curve it is 0x06|x
+	If c is true, only the x coordinate is provided as in 0x2|x if y is even, or 0x3|x if y is odd
+	@param c compression required, true or false
+	@param S output octet string
+	@param P ECP instance to be converted to an octet string
+ */
+extern void ECP_ZZZ_toOctet(octet *S,ECP_ZZZ *P,bool c);
+/**	@brief Creates an ECP point from an octet string
+ *
+	The octet string is normally in the standard form 0x04|x|y
+	Here x (and y) are the x and y coordinates in left justified big-endian base 256 form.
+	For Montgomery curve it is 0x06|x
+	If in compressed form only the x coordinate is provided as in 0x2|x if y is even, or 0x3|x if y is odd
+	@param P ECP instance to be created from the octet string
+	@param S input octet string
+	return 1 if octet string corresponds to a point on the curve, else 0
+ */
+extern int ECP_ZZZ_fromOctet(ECP_ZZZ *P,octet *S);
+/**	@brief Doubles an ECP instance P
+ *
+	@param P ECP instance, on exit =2*P
+ */
+extern void ECP_ZZZ_dbl(ECP_ZZZ *P);
+/**	@brief Multiplies an ECP instance P by a small integer, side-channel resistant
+ *
+	@param P ECP instance, on exit =i*P
+	@param i small integer multiplier
+	@param b maximum number of bits in multiplier
+ */
+extern void ECP_ZZZ_pinmul(ECP_ZZZ *P,int i,int b);
+/**	@brief Multiplies an ECP instance P by a BIG, side-channel resistant
+ *
+	Uses Montgomery ladder for Montgomery curves, otherwise fixed sized windows.
+	@param P ECP instance, on exit =b*P
+	@param b BIG number multiplier
+
+ */
+extern void ECP_ZZZ_mul(ECP_ZZZ *P,BIG_XXX b);
+/**	@brief Calculates double multiplication P=e*P+f*Q, side-channel resistant
+ *
+	@param P ECP instance, on exit =e*P+f*Q
+	@param Q ECP instance
+	@param e BIG number multiplier
+	@param f BIG number multiplier
+ */
+extern void ECP_ZZZ_mul2(ECP_ZZZ *P,ECP_ZZZ *Q,BIG_XXX e,BIG_XXX f);
+/**	@brief Get Group Generator from ROM
+ *
+	@param G ECP instance
+ */
+extern void ECP_ZZZ_generator(ECP_ZZZ *G);
+
+
+#endif
diff --git a/version3/c/ecp2.c b/version3/c/ecp2.c
new file mode 100644
index 0000000..e17b37d
--- /dev/null
+++ b/version3/c/ecp2.c
@@ -0,0 +1,912 @@
+/*
+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.
+*/
+
+/* AMCL Weierstrass elliptic curve functions over FP2 */
+/* SU=m, m is Stack Usage */
+
+#include "ecp2_ZZZ.h"
+
+int ECP2_ZZZ_isinf(ECP2_ZZZ *P)
+{
+//    if (P->inf) return 1;
+    return (FP2_YYY_iszilch(&(P->x)) & FP2_YYY_iszilch(&(P->z)));
+}
+
+/* Set P=Q */
+/* SU= 16 */
+void ECP2_ZZZ_copy(ECP2_ZZZ *P,ECP2_ZZZ *Q)
+{
+//    P->inf=Q->inf;
+    FP2_YYY_copy(&(P->x),&(Q->x));
+    FP2_YYY_copy(&(P->y),&(Q->y));
+    FP2_YYY_copy(&(P->z),&(Q->z));
+}
+
+/* set P to Infinity */
+/* SU= 8 */
+void ECP2_ZZZ_inf(ECP2_ZZZ *P)
+{
+//    P->inf=1;
+    FP2_YYY_zero(&(P->x));
+    FP2_YYY_one(&(P->y));
+    FP2_YYY_zero(&(P->z));
+}
+
+/* Conditional move Q to P dependant on d */
+static void ECP2_ZZZ_cmove(ECP2_ZZZ *P,ECP2_ZZZ *Q,int d)
+{
+    FP2_YYY_cmove(&(P->x),&(Q->x),d);
+    FP2_YYY_cmove(&(P->y),&(Q->y),d);
+    FP2_YYY_cmove(&(P->z),&(Q->z),d);
+//    d=~(d-1);
+//    P->inf^=(P->inf^Q->inf)&d;
+}
+
+/* return 1 if b==c, no branching */
+static int teq(sign32 b,sign32 c)
+{
+    sign32 x=b^c;
+    x-=1;  // if x=0, x now -1
+    return (int)((x>>31)&1);
+}
+
+/* Constant time select from pre-computed table */
+static void ECP2_ZZZ_select(ECP2_ZZZ *P,ECP2_ZZZ W[],sign32 b)
+{
+    ECP2_ZZZ MP;
+    sign32 m=b>>31;
+    sign32 babs=(b^m)-m;
+
+    babs=(babs-1)/2;
+
+    ECP2_ZZZ_cmove(P,&W[0],teq(babs,0));  // conditional move
+    ECP2_ZZZ_cmove(P,&W[1],teq(babs,1));
+    ECP2_ZZZ_cmove(P,&W[2],teq(babs,2));
+    ECP2_ZZZ_cmove(P,&W[3],teq(babs,3));
+    ECP2_ZZZ_cmove(P,&W[4],teq(babs,4));
+    ECP2_ZZZ_cmove(P,&W[5],teq(babs,5));
+    ECP2_ZZZ_cmove(P,&W[6],teq(babs,6));
+    ECP2_ZZZ_cmove(P,&W[7],teq(babs,7));
+
+    ECP2_ZZZ_copy(&MP,P);
+    ECP2_ZZZ_neg(&MP);  // minus P
+    ECP2_ZZZ_cmove(P,&MP,(int)(m&1));
+}
+
+/* return 1 if P==Q, else 0 */
+/* SU= 312 */
+int ECP2_ZZZ_equals(ECP2_ZZZ *P,ECP2_ZZZ *Q)
+{
+    FP2_YYY a,b;
+//    if (ECP2_ZZZ_isinf(P) && ECP2_ZZZ_isinf(Q)) return 1;
+//    if (ECP2_ZZZ_isinf(P) || ECP2_ZZZ_isinf(Q)) return 0;
+
+    FP2_YYY_mul(&a,&(P->x),&(Q->z));
+    FP2_YYY_mul(&b,&(Q->x),&(P->z));
+    if (!FP2_YYY_equals(&a,&b)) return 0;
+
+    FP2_YYY_mul(&a,&(P->y),&(Q->z));
+    FP2_YYY_mul(&b,&(Q->y),&(P->z));
+    if (!FP2_YYY_equals(&a,&b)) return 0;
+    return 1;
+}
+
+/* Make P affine (so z=1) */
+/* SU= 232 */
+void ECP2_ZZZ_affine(ECP2_ZZZ *P)
+{
+    FP2_YYY one,iz;
+    if (ECP2_ZZZ_isinf(P)) return;
+
+    FP2_YYY_one(&one);
+    if (FP2_YYY_isunity(&(P->z)))
+    {
+        FP2_YYY_reduce(&(P->x));
+        FP2_YYY_reduce(&(P->y));
+        return;
+    }
+
+    FP2_YYY_inv(&iz,&(P->z));
+    FP2_YYY_mul(&(P->x),&(P->x),&iz);
+    FP2_YYY_mul(&(P->y),&(P->y),&iz);
+
+    FP2_YYY_reduce(&(P->x));
+    FP2_YYY_reduce(&(P->y));
+    FP2_YYY_copy(&(P->z),&one);
+}
+
+/* extract x, y from point P */
+/* SU= 16 */
+int ECP2_ZZZ_get(FP2_YYY *x,FP2_YYY *y,ECP2_ZZZ *P)
+{
+	ECP2_ZZZ W;
+	ECP2_ZZZ_copy(&W,P);
+	ECP2_ZZZ_affine(&W);
+    if (ECP2_ZZZ_isinf(&W)) return -1;
+    //ECP2_ZZZ_affine(P);
+    FP2_YYY_copy(y,&(W.y));
+    FP2_YYY_copy(x,&(W.x));
+    return 0;
+}
+
+/* SU= 152 */
+/* Output point P */
+void ECP2_ZZZ_output(ECP2_ZZZ *P)
+{
+    FP2_YYY x,y;
+    if (ECP2_ZZZ_isinf(P))
+    {
+        printf("Infinity\n");
+        return;
+    }
+    ECP2_ZZZ_get(&x,&y,P);
+    printf("(");
+    FP2_YYY_output(&x);
+    printf(",");
+    FP2_YYY_output(&y);
+    printf(")\n");
+}
+
+/* SU= 232 */
+void ECP2_ZZZ_outputxyz(ECP2_ZZZ *P)
+{
+    ECP2_ZZZ Q;
+    if (ECP2_ZZZ_isinf(P))
+    {
+        printf("Infinity\n");
+        return;
+    }
+    ECP2_ZZZ_copy(&Q,P);
+    printf("(");
+    FP2_YYY_output(&(Q.x));
+    printf(",");
+    FP2_YYY_output(&(Q.y));
+    printf(",");
+    FP2_YYY_output(&(Q.z));
+    printf(")\n");
+}
+
+/* SU= 168 */
+/* Convert Q to octet string */
+void ECP2_ZZZ_toOctet(octet *W,ECP2_ZZZ *Q)
+{
+    BIG_XXX b;
+    FP2_YYY qx,qy;
+    ECP2_ZZZ_get(&qx,&qy,Q);
+
+    FP_YYY_redc(b,&(qx.a));
+    BIG_XXX_toBytes(&(W->val[0]),b);
+    FP_YYY_redc(b,&(qx.b));
+    BIG_XXX_toBytes(&(W->val[MODBYTES_XXX]),b);
+    FP_YYY_redc(b,&(qy.a));
+    BIG_XXX_toBytes(&(W->val[2*MODBYTES_XXX]),b);
+    FP_YYY_redc(b,&(qy.b));
+    BIG_XXX_toBytes(&(W->val[3*MODBYTES_XXX]),b);
+
+    W->len=4*MODBYTES_XXX;
+
+}
+
+/* SU= 176 */
+/* restore Q from octet string */
+int ECP2_ZZZ_fromOctet(ECP2_ZZZ *Q,octet *W)
+{
+    BIG_XXX b;
+    FP2_YYY qx,qy;
+    BIG_XXX_fromBytes(b,&(W->val[0]));
+    FP_YYY_nres(&(qx.a),b);
+    BIG_XXX_fromBytes(b,&(W->val[MODBYTES_XXX]));
+    FP_YYY_nres(&(qx.b),b);
+    BIG_XXX_fromBytes(b,&(W->val[2*MODBYTES_XXX]));
+    FP_YYY_nres(&(qy.a),b);
+    BIG_XXX_fromBytes(b,&(W->val[3*MODBYTES_XXX]));
+    FP_YYY_nres(&(qy.b),b);
+
+    if (ECP2_ZZZ_set(Q,&qx,&qy)) return 1;
+    return 0;
+}
+
+/* SU= 128 */
+/* Calculate RHS of twisted curve equation x^3+B/i or x^3+Bi*/
+void ECP2_ZZZ_rhs(FP2_YYY *rhs,FP2_YYY *x)
+{
+    /* calculate RHS of elliptic curve equation */
+    FP2_YYY t;
+    BIG_XXX b;
+    FP2_YYY_sqr(&t,x);
+
+    FP2_YYY_mul(rhs,&t,x);
+
+    /* Assuming CURVE_A=0 */
+
+    BIG_XXX_rcopy(b,CURVE_B_ZZZ);
+
+    FP2_YYY_from_BIG(&t,b);
+
+#if SEXTIC_TWIST_ZZZ == D_TYPE
+    FP2_YYY_div_ip(&t);   /* IMPORTANT - here we use the correct SEXTIC twist of the curve */
+#endif
+
+#if SEXTIC_TWIST_ZZZ == M_TYPE
+    FP2_YYY_norm(&t);
+    FP2_YYY_mul_ip(&t);   /* IMPORTANT - here we use the correct SEXTIC twist of the curve */
+    FP2_YYY_norm(&t);
+
+#endif
+
+
+    FP2_YYY_add(rhs,&t,rhs);
+    FP2_YYY_reduce(rhs);
+}
+
+
+/* Set P=(x,y). Return 1 if (x,y) is on the curve, else return 0*/
+/* SU= 232 */
+int ECP2_ZZZ_set(ECP2_ZZZ *P,FP2_YYY *x,FP2_YYY *y)
+{
+    FP2_YYY rhs,y2;
+
+    FP2_YYY_sqr(&y2,y);
+    ECP2_ZZZ_rhs(&rhs,x);
+
+    if (!FP2_YYY_equals(&y2,&rhs))
+    {
+		ECP2_ZZZ_inf(P);
+       // P->inf=1;
+        return 0;
+    }
+
+  //  P->inf=0;
+    FP2_YYY_copy(&(P->x),x);
+    FP2_YYY_copy(&(P->y),y);
+
+    FP2_YYY_one(&(P->z));
+    return 1;
+}
+
+/* Set P=(x,y). Return 1 if (x,.) is on the curve, else return 0 */
+/* SU= 232 */
+int ECP2_ZZZ_setx(ECP2_ZZZ *P,FP2_YYY *x)
+{
+    FP2_YYY y;
+    ECP2_ZZZ_rhs(&y,x);
+
+    if (!FP2_YYY_sqrt(&y,&y))
+    {
+		ECP2_ZZZ_inf(P);
+        return 0;
+    }
+
+ //   P->inf=0;
+    FP2_YYY_copy(&(P->x),x);
+    FP2_YYY_copy(&(P->y),&y);
+    FP2_YYY_one(&(P->z));
+    return 1;
+}
+
+/* Set P=-P */
+/* SU= 8 */
+void ECP2_ZZZ_neg(ECP2_ZZZ *P)
+{
+//	if (ECP2_ZZZ_isinf(P)) return;
+    FP2_YYY_norm(&(P->y));
+    FP2_YYY_neg(&(P->y),&(P->y));
+    FP2_YYY_norm(&(P->y));
+}
+
+/* R+=R */
+/* return -1 for Infinity, 0 for addition, 1 for doubling */
+/* SU= 448 */
+int ECP2_ZZZ_dbl(ECP2_ZZZ *P)
+{
+    FP2_YYY t0,t1,t2,iy,x3,y3;
+//    if (P->inf) return -1;
+
+    FP2_YYY_copy(&iy,&(P->y));		//FP2 iy=new FP2(y);
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+    FP2_YYY_mul_ip(&iy);			//iy.mul_ip();
+    FP2_YYY_norm(&iy);				//iy.norm();
+#endif
+    //FP2_YYY_copy(&t0,&(P->y));		//FP2 t0=new FP2(y);                  //***** Change
+    FP2_YYY_sqr(&t0,&(P->y));			//t0.sqr();
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+    FP2_YYY_mul_ip(&t0);			//t0.mul_ip();
+#endif
+    //FP2_YYY_copy(&t1,&iy);				//FP2 t1=new FP2(iy);
+    FP2_YYY_mul(&t1,&iy,&(P->z));	//t1.mul(z);
+    //FP2_YYY_copy(&t2,&(P->z));		//FP2 t2=new FP2(z);
+    FP2_YYY_sqr(&t2,&(P->z));				//t2.sqr();
+
+    //FP2_YYY_copy(&(P->z),&t0);		//z.copy(t0);
+    FP2_YYY_add(&(P->z),&t0,&t0);	//z.add(t0);
+    FP2_YYY_norm(&(P->z));				//z.norm();
+    FP2_YYY_add(&(P->z),&(P->z),&(P->z));	//z.add(z);
+    FP2_YYY_add(&(P->z),&(P->z),&(P->z));	//z.add(z);
+    FP2_YYY_norm(&(P->z));			//z.norm();
+
+    FP2_YYY_imul(&t2,&t2,3*CURVE_B_I_ZZZ);	//t2.imul(3*ROM.CURVE_B_I);
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+    FP2_YYY_mul_ip(&t2);
+    FP2_YYY_norm(&t2);
+#endif
+
+    //FP2_YYY_copy(&x3,&t2);			//FP2 x3=new FP2(t2);
+    FP2_YYY_mul(&x3,&t2,&(P->z));	//x3.mul(z);
+
+    //FP2_YYY_copy(&y3,&t0);			//FP2 y3=new FP2(t0);
+
+    FP2_YYY_add(&y3,&t0,&t2);		//y3.add(t2);
+    FP2_YYY_norm(&y3);				//y3.norm();
+    FP2_YYY_mul(&(P->z),&(P->z),&t1);	//z.mul(t1);
+
+    //FP2_YYY_copy(&t1,&t2);			//t1.copy(t2);
+    FP2_YYY_add(&t1,&t2,&t2);		//t1.add(t2);
+    FP2_YYY_add(&t2,&t2,&t1);		//t2.add(t1);
+    FP2_YYY_norm(&t2);				//t2.norm();
+    FP2_YYY_sub(&t0,&t0,&t2);		//t0.sub(t2);
+    FP2_YYY_norm(&t0);				//t0.norm();                           //y^2-9bz^2
+    FP2_YYY_mul(&y3,&y3,&t0);		//y3.mul(t0);
+    FP2_YYY_add(&(P->y),&y3,&x3);		//y3.add(x3);                          //(y^2+3z*2)(y^2-9z^2)+3b.z^2.8y^2
+    //FP2_YYY_copy(&t1,&(P->x));		//t1.copy(x);
+    FP2_YYY_mul(&t1,&(P->x),&iy);		//t1.mul(iy);						//
+    //FP2_YYY_copy(&(P->x),&t0);		//x.copy(t0);
+    FP2_YYY_norm(&t0);			//x.norm();
+    FP2_YYY_mul(&(P->x),&t0,&t1);	//x.mul(t1);
+    FP2_YYY_add(&(P->x),&(P->x),&(P->x));	//x.add(x);       //(y^2-9bz^2)xy2
+
+    FP2_YYY_norm(&(P->x));			//x.norm();
+    //FP2_YYY_copy(&(P->y),&y3);		//y.copy(y3);
+    FP2_YYY_norm(&(P->y));			//y.norm();
+
+    return 1;
+}
+
+/* Set P+=Q */
+/* SU= 400 */
+int ECP2_ZZZ_add(ECP2_ZZZ *P,ECP2_ZZZ *Q)
+{
+    FP2_YYY t0,t1,t2,t3,t4,x3,y3,z3;
+    int b3=3*CURVE_B_I_ZZZ;
+/*    if (Q->inf) return 0;
+    if (P->inf)
+    {
+        ECP2_ZZZ_copy(P,Q);
+        return 0;
+    }
+*/
+    //FP2_YYY_copy(&t0,&(P->x));		//FP2 t0=new FP2(x);
+    FP2_YYY_mul(&t0,&(P->x),&(Q->x));	//t0.mul(Q.x);         // x.Q.x
+    //FP2_YYY_copy(&t1,&(P->y));		//FP2 t1=new FP2(y);
+    FP2_YYY_mul(&t1,&(P->y),&(Q->y));	//t1.mul(Q.y);		 // y.Q.y
+
+    //FP2_YYY_copy(&t2,&(P->z));		//FP2 t2=new FP2(z);
+    FP2_YYY_mul(&t2,&(P->z),&(Q->z));	//t2.mul(Q.z);
+    //FP2_YYY_copy(&t3,&(P->x));		//FP2 t3=new FP2(x);
+    FP2_YYY_add(&t3,&(P->x),&(P->y));	//t3.add(y);
+    FP2_YYY_norm(&t3);				//t3.norm();          //t3=X1+Y1
+    //FP2_YYY_copy(&t4,&(Q->x));		//FP2 t4=new FP2(Q.x);
+    FP2_YYY_add(&t4,&(Q->x),&(Q->y));	//t4.add(Q.y);
+    FP2_YYY_norm(&t4);				//t4.norm();			//t4=X2+Y2
+    FP2_YYY_mul(&t3,&t3,&t4);		//t3.mul(t4);						//t3=(X1+Y1)(X2+Y2)
+    //FP2_YYY_copy(&t4,&t0);			//t4.copy(t0);
+    FP2_YYY_add(&t4,&t0,&t1);		//t4.add(t1);		//t4=X1.X2+Y1.Y2
+
+    FP2_YYY_sub(&t3,&t3,&t4);		//t3.sub(t4);
+    FP2_YYY_norm(&t3);				//t3.norm();
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+    FP2_YYY_mul_ip(&t3);			//t3.mul_ip();
+    FP2_YYY_norm(&t3);				//t3.norm();         //t3=(X1+Y1)(X2+Y2)-(X1.X2+Y1.Y2) = X1.Y2+X2.Y1
+#endif
+    //FP2_YYY_copy(&t4,&(P->y));		//t4.copy(y);
+    FP2_YYY_add(&t4,&(P->y),&(P->z));	//t4.add(z);
+    FP2_YYY_norm(&t4);				//t4.norm();			//t4=Y1+Z1
+    //FP2_YYY_copy(&x3,&(Q->y));		//FP2 x3=new FP2(Q.y);
+    FP2_YYY_add(&x3,&(Q->y),&(Q->z));	//x3.add(Q.z);
+    FP2_YYY_norm(&x3);				//x3.norm();			//x3=Y2+Z2
+
+    FP2_YYY_mul(&t4,&t4,&x3);		//t4.mul(x3);						//t4=(Y1+Z1)(Y2+Z2)
+    //FP2_YYY_copy(&x3,&t1);			//x3.copy(t1);					//
+    FP2_YYY_add(&x3,&t1,&t2);		//x3.add(t2);						//X3=Y1.Y2+Z1.Z2
+
+    FP2_YYY_sub(&t4,&t4,&x3);		//t4.sub(x3);
+    FP2_YYY_norm(&t4);				//t4.norm();
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+    FP2_YYY_mul_ip(&t4);			//t4.mul_ip();
+    FP2_YYY_norm(&t4);				//t4.norm();          //t4=(Y1+Z1)(Y2+Z2) - (Y1.Y2+Z1.Z2) = Y1.Z2+Y2.Z1
+#endif
+    //FP2_YYY_copy(&x3,&(P->x));		//x3.copy(x);
+    FP2_YYY_add(&x3,&(P->x),&(P->z));	//x3.add(z);
+    FP2_YYY_norm(&x3);				//x3.norm();	// x3=X1+Z1
+    //FP2_YYY_copy(&y3,&(Q->x));		//FP2 y3=new FP2(Q.x);
+    FP2_YYY_add(&y3,&(Q->x),&(Q->z));	//y3.add(Q.z);
+    FP2_YYY_norm(&y3);				//y3.norm();				// y3=X2+Z2
+    FP2_YYY_mul(&x3,&x3,&y3);		//x3.mul(y3);							// x3=(X1+Z1)(X2+Z2)
+    //FP2_YYY_copy(&y3,&t0);			//y3.copy(t0);
+    FP2_YYY_add(&y3,&t0,&t2);		//y3.add(t2);							// y3=X1.X2+Z1+Z2
+    FP2_YYY_sub(&y3,&x3,&y3);		//y3.rsub(x3);
+    FP2_YYY_norm(&y3);				//y3.norm();				// y3=(X1+Z1)(X2+Z2) - (X1.X2+Z1.Z2) = X1.Z2+X2.Z1
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+    FP2_YYY_mul_ip(&t0);			//t0.mul_ip();
+    FP2_YYY_norm(&t0);				//t0.norm(); // x.Q.x
+    FP2_YYY_mul_ip(&t1);			//t1.mul_ip();
+    FP2_YYY_norm(&t1);				//t1.norm(); // y.Q.y
+#endif
+    //FP2_YYY_copy(&x3,&t0);			//x3.copy(t0);
+    FP2_YYY_add(&x3,&t0,&t0);		//x3.add(t0);
+    FP2_YYY_add(&t0,&t0,&x3);		//t0.add(x3);
+    FP2_YYY_norm(&t0);				//t0.norm();
+    FP2_YYY_imul(&t2,&t2,b3);		//t2.imul(b);
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+    FP2_YYY_mul_ip(&t2);
+    FP2_YYY_norm(&t2);
+#endif
+    //FP2_YYY_copy(&z3,&t1);			//FP2 z3=new FP2(t1);
+    FP2_YYY_add(&z3,&t1,&t2);		//z3.add(t2);
+    FP2_YYY_norm(&z3);				//z3.norm();
+    FP2_YYY_sub(&t1,&t1,&t2);		//t1.sub(t2);
+    FP2_YYY_norm(&t1);				//t1.norm();
+    FP2_YYY_imul(&y3,&y3,b3);		//y3.imul(b);
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+    FP2_YYY_mul_ip(&y3);
+    FP2_YYY_norm(&y3);
+#endif
+    //FP2_YYY_copy(&x3,&y3);			//x3.copy(y3);
+    FP2_YYY_mul(&x3,&y3,&t4);		//x3.mul(t4);
+    //FP2_YYY_copy(&t2,&t3);			//t2.copy(t3);
+    FP2_YYY_mul(&t2,&t3,&t1);		//t2.mul(t1);
+    FP2_YYY_sub(&(P->x),&t2,&x3);		//x3.rsub(t2);
+    FP2_YYY_mul(&y3,&y3,&t0);		//y3.mul(t0);
+    FP2_YYY_mul(&t1,&t1,&z3);		//t1.mul(z3);
+    FP2_YYY_add(&(P->y),&y3,&t1);		//y3.add(t1);
+    FP2_YYY_mul(&t0,&t0,&t3);		//t0.mul(t3);
+    FP2_YYY_mul(&z3,&z3,&t4);		//z3.mul(t4);
+    FP2_YYY_add(&(P->z),&z3,&t0);		//z3.add(t0);
+
+    //FP2_YYY_copy(&(P->x),&x3);		//x.copy(x3);
+    FP2_YYY_norm(&(P->x));			//x.norm();
+    //FP2_YYY_copy(&(P->y),&y3);		//y.copy(y3);
+    FP2_YYY_norm(&(P->y));			//y.norm();
+    //FP2_YYY_copy(&(P->z),&z3);		//z.copy(z3);
+    FP2_YYY_norm(&(P->z));			//z.norm();
+
+    return 0;
+}
+
+/* Set P-=Q */
+/* SU= 16 */
+void ECP2_ZZZ_sub(ECP2_ZZZ *P,ECP2_ZZZ *Q)
+{
+	ECP2_ZZZ NQ;
+	ECP2_ZZZ_copy(&NQ,Q);
+	ECP2_ZZZ_neg(&NQ);
+    //ECP2_ZZZ_neg(Q);
+    ECP2_ZZZ_add(P,&NQ);
+    //ECP2_ZZZ_neg(Q);
+}
+
+/* P*=e */
+/* SU= 280 */
+void ECP2_ZZZ_mul(ECP2_ZZZ *P,BIG_XXX e)
+{
+    /* fixed size windows */
+    int i,nb,s,ns;
+    BIG_XXX mt,t;
+    ECP2_ZZZ Q,W[8],C;
+    sign8 w[1+(NLEN_XXX*BASEBITS_XXX+3)/4];
+
+    if (ECP2_ZZZ_isinf(P)) return;
+    //ECP2_ZZZ_affine(P);
+
+
+    /* precompute table */
+
+    ECP2_ZZZ_copy(&Q,P);
+    ECP2_ZZZ_dbl(&Q);
+    ECP2_ZZZ_copy(&W[0],P);
+
+    for (i=1; i<8; i++)
+    {
+        ECP2_ZZZ_copy(&W[i],&W[i-1]);
+        ECP2_ZZZ_add(&W[i],&Q);
+    }
+
+    /* make exponent odd - add 2P if even, P if odd */
+    BIG_XXX_copy(t,e);
+    s=BIG_XXX_parity(t);
+    BIG_XXX_inc(t,1);
+    BIG_XXX_norm(t);
+    ns=BIG_XXX_parity(t);
+    BIG_XXX_copy(mt,t);
+    BIG_XXX_inc(mt,1);
+    BIG_XXX_norm(mt);
+    BIG_XXX_cmove(t,mt,s);
+    ECP2_ZZZ_cmove(&Q,P,ns);
+    ECP2_ZZZ_copy(&C,&Q);
+
+    nb=1+(BIG_XXX_nbits(t)+3)/4;
+
+    /* convert exponent to signed 4-bit window */
+    for (i=0; i<nb; i++)
+    {
+        w[i]=BIG_XXX_lastbits(t,5)-16;
+        BIG_XXX_dec(t,w[i]);
+        BIG_XXX_norm(t);
+        BIG_XXX_fshr(t,4);
+    }
+    w[nb]=BIG_XXX_lastbits(t,5);
+
+    ECP2_ZZZ_copy(P,&W[(w[nb]-1)/2]);
+    for (i=nb-1; i>=0; i--)
+    {
+        ECP2_ZZZ_select(&Q,W,w[i]);
+        ECP2_ZZZ_dbl(P);
+        ECP2_ZZZ_dbl(P);
+        ECP2_ZZZ_dbl(P);
+        ECP2_ZZZ_dbl(P);
+        ECP2_ZZZ_add(P,&Q);
+    }
+    ECP2_ZZZ_sub(P,&C); /* apply correction */
+    ECP2_ZZZ_affine(P);
+}
+
+/* Calculates q.P using Frobenius constant X */
+/* SU= 96 */
+void ECP2_ZZZ_frob(ECP2_ZZZ *P,FP2_YYY *X)
+{
+    FP2_YYY X2;
+//    if (P->inf) return;
+//printf("X= "); FP2_YYY_output(X); printf("\n");
+    FP2_YYY_sqr(&X2,X);
+//printf("X2= "); FP2_YYY_output(&X2); printf("\n");
+    FP2_YYY_conj(&(P->x),&(P->x));
+    FP2_YYY_conj(&(P->y),&(P->y));
+    FP2_YYY_conj(&(P->z),&(P->z));
+    FP2_YYY_reduce(&(P->z));
+
+    FP2_YYY_mul(&(P->x),&X2,&(P->x));
+    FP2_YYY_mul(&(P->y),&X2,&(P->y));
+    FP2_YYY_mul(&(P->y),X,&(P->y));
+
+
+//printf("Px= "); FP2_YYY_output(&(P->x)); printf("\n");
+//printf("Py= "); FP2_YYY_output(&(P->y)); printf("\n");
+//printf("Pz= "); FP2_YYY_output(&(P->z)); printf("\n");
+}
+
+
+// Bos & Costello https://eprint.iacr.org/2013/458.pdf
+// Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
+// Side channel attack secure 
+
+void ECP2_ZZZ_mul4(ECP2_ZZZ *P,ECP2_ZZZ Q[4],BIG_XXX u[4])
+{
+    int i,j,k,nb,pb,bt;
+	ECP2_ZZZ T[8],W;
+    BIG_XXX t[4],mt;
+	sign8 w[NLEN_XXX*BASEBITS_XXX+1];
+	sign8 s[NLEN_XXX*BASEBITS_XXX+1];
+
+    for (i=0; i<4; i++)
+    {
+        BIG_XXX_copy(t[i],u[i]);
+        //ECP2_ZZZ_affine(&Q[i]);
+    }
+
+// Precomputed table
+    ECP2_ZZZ_copy(&T[0],&Q[0]); // Q[0]
+    ECP2_ZZZ_copy(&T[1],&T[0]);
+	ECP2_ZZZ_add(&T[1],&Q[1]);	// Q[0]+Q[1]
+    ECP2_ZZZ_copy(&T[2],&T[0]);
+	ECP2_ZZZ_add(&T[2],&Q[2]);	// Q[0]+Q[2]
+	ECP2_ZZZ_copy(&T[3],&T[1]);
+	ECP2_ZZZ_add(&T[3],&Q[2]);	// Q[0]+Q[1]+Q[2]
+	ECP2_ZZZ_copy(&T[4],&T[0]);
+	ECP2_ZZZ_add(&T[4],&Q[3]);  // Q[0]+Q[3]
+	ECP2_ZZZ_copy(&T[5],&T[1]);
+	ECP2_ZZZ_add(&T[5],&Q[3]);	// Q[0]+Q[1]+Q[3]
+	ECP2_ZZZ_copy(&T[6],&T[2]);
+	ECP2_ZZZ_add(&T[6],&Q[3]);	// Q[0]+Q[2]+Q[3]
+	ECP2_ZZZ_copy(&T[7],&T[3]);
+	ECP2_ZZZ_add(&T[7],&Q[3]);	// Q[0]+Q[1]+Q[2]+Q[3]
+
+// Make it odd
+	pb=1-BIG_XXX_parity(t[0]);
+	BIG_XXX_inc(t[0],pb);
+	BIG_XXX_norm(t[0]);
+
+// Number of bits
+    BIG_XXX_zero(mt);
+    for (i=0; i<4; i++)
+    {
+        BIG_XXX_or(mt,mt,t[i]);
+    }
+    nb=1+BIG_XXX_nbits(mt);
+
+// Sign pivot 
+	s[nb-1]=1;
+	for (i=0;i<nb-1;i++)
+	{
+        BIG_XXX_fshr(t[0],1);
+		s[i]=2*BIG_XXX_parity(t[0])-1;
+	}
+
+// Recoded exponent
+    for (i=0; i<nb; i++)
+    {
+		w[i]=0;
+		k=1;
+		for (j=1; j<4; j++)
+		{
+			bt=s[i]*BIG_XXX_parity(t[j]);
+			BIG_XXX_fshr(t[j],1);
+
+			BIG_XXX_dec(t[j],(bt>>1));
+			BIG_XXX_norm(t[j]);
+			w[i]+=bt*k;
+			k*=2;
+        }
+    }		
+
+// Main loop
+	ECP2_ZZZ_select(P,T,2*w[nb-1]+1);
+    for (i=nb-2; i>=0; i--)
+    {
+        ECP2_ZZZ_select(&W,T,2*w[i]+s[i]);
+        ECP2_ZZZ_dbl(P);
+        ECP2_ZZZ_add(P,&W);
+    }
+
+// apply correction
+	ECP2_ZZZ_copy(&W,P);   
+	ECP2_ZZZ_sub(&W,&Q[0]);
+	ECP2_ZZZ_cmove(P,&W,pb);
+
+    ECP2_ZZZ_affine(P);
+}
+
+
+/*
+void ECP2_ZZZ_mul4(ECP2_ZZZ *P,ECP2_ZZZ Q[4],BIG_XXX u[4])
+{
+    int i,j,a[4],nb;
+    ECP2_ZZZ W[8],T,C;
+    BIG_XXX mt,t[4];
+    sign8 w[NLEN_XXX*BASEBITS_XXX+1];
+
+    for (i=0; i<4; i++)
+    {
+        BIG_XXX_copy(t[i],u[i]);
+        ECP2_ZZZ_affine(&Q[i]);
+    }
+
+    // precompute table 
+
+    ECP2_ZZZ_copy(&W[0],&Q[0]);
+    ECP2_ZZZ_sub(&W[0],&Q[1]);  // P-Q 
+    ECP2_ZZZ_copy(&W[1],&W[0]);
+    ECP2_ZZZ_copy(&W[2],&W[0]);
+    ECP2_ZZZ_copy(&W[3],&W[0]);
+    ECP2_ZZZ_copy(&W[4],&Q[0]);
+    ECP2_ZZZ_add(&W[4],&Q[1]);  // P+Q 
+    ECP2_ZZZ_copy(&W[5],&W[4]);
+    ECP2_ZZZ_copy(&W[6],&W[4]);
+    ECP2_ZZZ_copy(&W[7],&W[4]);
+
+    ECP2_ZZZ_copy(&T,&Q[2]);
+    ECP2_ZZZ_sub(&T,&Q[3]);       // R-S 
+    ECP2_ZZZ_sub(&W[1],&T);
+    ECP2_ZZZ_add(&W[2],&T);
+    ECP2_ZZZ_sub(&W[5],&T);
+    ECP2_ZZZ_add(&W[6],&T);
+    ECP2_ZZZ_copy(&T,&Q[2]);
+    ECP2_ZZZ_add(&T,&Q[3]);      // R+S 
+    ECP2_ZZZ_sub(&W[0],&T);
+    ECP2_ZZZ_add(&W[3],&T);
+    ECP2_ZZZ_sub(&W[4],&T);
+    ECP2_ZZZ_add(&W[7],&T);
+
+    // if multiplier is even add 1 to multiplier, and add P to correction 
+    ECP2_ZZZ_inf(&C);
+
+    BIG_XXX_zero(mt);
+    for (i=0; i<4; i++)
+    {
+        if (BIG_XXX_parity(t[i])==0)
+        {
+            BIG_XXX_inc(t[i],1);
+            BIG_XXX_norm(t[i]);
+            ECP2_ZZZ_add(&C,&Q[i]);
+        }
+        BIG_XXX_add(mt,mt,t[i]);
+        BIG_XXX_norm(mt);
+    }
+
+    nb=1+BIG_XXX_nbits(mt);
+
+    // convert exponent to signed 1-bit window 
+    for (j=0; j<nb; j++)
+    {
+        for (i=0; i<4; i++)
+        {
+            a[i]=BIG_XXX_lastbits(t[i],2)-2;
+            BIG_XXX_dec(t[i],a[i]);
+            BIG_XXX_norm(t[i]);
+            BIG_XXX_fshr(t[i],1);
+        }
+        w[j]=8*a[0]+4*a[1]+2*a[2]+a[3];
+    }
+    w[nb]=8*BIG_XXX_lastbits(t[0],2)+4*BIG_XXX_lastbits(t[1],2)+2*BIG_XXX_lastbits(t[2],2)+BIG_XXX_lastbits(t[3],2);
+
+    ECP2_ZZZ_copy(P,&W[(w[nb]-1)/2]);
+    for (i=nb-1; i>=0; i--)
+    {
+        ECP2_ZZZ_select(&T,W,w[i]);
+        ECP2_ZZZ_dbl(P);
+        ECP2_ZZZ_add(P,&T);
+    }
+    ECP2_ZZZ_sub(P,&C); // apply correction 
+
+    ECP2_ZZZ_affine(P);
+}
+*/
+
+/* Map to hash value to point on G2 from random BIG */
+void ECP2_ZZZ_mapit(ECP2_ZZZ *Q,octet *W)
+{
+    BIG_XXX q,one,Fx,Fy,x,hv;
+    FP2_YYY X;
+#if (PAIRING_FRIENDLY_ZZZ == BN)
+    ECP2_ZZZ T,K;
+#elif (PAIRING_FRIENDLY_ZZZ == BLS)
+    ECP2_ZZZ xQ, x2Q;
+#endif
+    BIG_XXX_fromBytes(hv,W->val);
+    BIG_XXX_rcopy(q,Modulus_ZZZ);
+    BIG_XXX_one(one);
+    BIG_XXX_mod(hv,q);
+
+    for (;;)
+    {
+        FP2_YYY_from_BIGs(&X,one,hv);
+        if (ECP2_ZZZ_setx(Q,&X)) break;
+        BIG_XXX_inc(hv,1);
+    }
+
+    BIG_XXX_rcopy(Fx,Fra_YYY);
+    BIG_XXX_rcopy(Fy,Frb_YYY);
+    FP2_YYY_from_BIGs(&X,Fx,Fy);
+
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+    FP2_YYY_inv(&X,&X);
+    FP2_YYY_norm(&X);
+#endif
+
+    BIG_XXX_rcopy(x,CURVE_Bnx_ZZZ);
+
+#if (PAIRING_FRIENDLY_ZZZ == BN)
+
+    /* Faster Hashing to G2 - Fuentes-Castaneda, Knapp and Rodriguez-Henriquez */
+    /* Q -> xQ + F(3xQ) + F(F(xQ)) + F(F(F(Q))). */
+    ECP2_ZZZ_copy(&T,Q);
+    ECP2_ZZZ_mul(&T,x);
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+    ECP2_ZZZ_neg(&T);   // our x is negative
+#endif
+    ECP2_ZZZ_copy(&K,&T);
+    ECP2_ZZZ_dbl(&K);
+    ECP2_ZZZ_add(&K,&T);
+    //ECP2_ZZZ_affine(&K);
+
+    ECP2_ZZZ_frob(&K,&X);
+    ECP2_ZZZ_frob(Q,&X);
+    ECP2_ZZZ_frob(Q,&X);
+    ECP2_ZZZ_frob(Q,&X);
+    ECP2_ZZZ_add(Q,&T);
+    ECP2_ZZZ_add(Q,&K);
+    ECP2_ZZZ_frob(&T,&X);
+    ECP2_ZZZ_frob(&T,&X);
+    ECP2_ZZZ_add(Q,&T);
+    ECP2_ZZZ_affine(Q);
+
+#elif (PAIRING_FRIENDLY_ZZZ == BLS)
+
+    /* Efficient hash maps to G2 on BLS curves - Budroni, Pintore */
+    /* Q -> x2Q -xQ -Q +F(xQ -Q) +F(F(2Q)) */
+
+    ECP2_ZZZ_copy(&xQ,Q);
+    ECP2_ZZZ_mul(&xQ,x);
+
+    ECP2_ZZZ_copy(&x2Q,&xQ);
+    ECP2_ZZZ_mul(&x2Q,x);
+
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+    ECP2_ZZZ_neg(&xQ);
+#endif
+
+    ECP2_ZZZ_sub(&x2Q,&xQ);
+    ECP2_ZZZ_sub(&x2Q,Q);
+
+    ECP2_ZZZ_sub(&xQ,Q);
+    ECP2_ZZZ_frob(&xQ,&X);
+
+    ECP2_ZZZ_dbl(Q);
+    ECP2_ZZZ_frob(Q,&X);
+    ECP2_ZZZ_frob(Q,&X);
+
+    ECP2_ZZZ_add(Q,&x2Q);
+    ECP2_ZZZ_add(Q,&xQ);
+
+    ECP2_ZZZ_affine(Q);
+
+#endif
+}
+
+void ECP2_ZZZ_generator(ECP2_ZZZ *G)
+{
+	FP2_YYY wx,wy;
+
+    FP_YYY_rcopy(&(wx.a),CURVE_Pxa_ZZZ); 
+    FP_YYY_rcopy(&(wx.b),CURVE_Pxb_ZZZ); 
+    FP_YYY_rcopy(&(wy.a),CURVE_Pya_ZZZ); 
+    FP_YYY_rcopy(&(wy.b),CURVE_Pyb_ZZZ);     
+	ECP2_ZZZ_set(G,&wx,&wy);
+}
+
+/*
+
+int main()
+{
+	int i;
+	ECP2_ZZZ G,P;
+	ECP2_ZZZ *W;
+	FP2_YYY x,y,w,z,f;
+	BIG_XXX r,xa,xb,ya,yb;
+
+	BIG_XXX_rcopy(xa,CURVE_Pxa_ZZZ);
+	BIG_XXX_rcopy(xb,CURVE_Pxb_ZZZ);
+	BIG_XXX_rcopy(ya,CURVE_Pya_ZZZ);
+	BIG_XXX_rcopy(yb,CURVE_Pyb_ZZZ);
+
+	FP2_YYY_from_BIGs(&x,xa,xb);
+	FP2_YYY_from_BIGs(&y,ya,yb);
+	ECP2_ZZZ_set(&G,&x,&y);
+	if (G.inf) printf("Failed to set - point not on curve\n");
+	else printf("set success\n");
+
+	ECP2_ZZZ_output(&G);
+
+//	BIG_XXX_copy(r,CURVE_Order_ZZZ);
+	BIG_XXX_rcopy(r,Modulus_YYY);
+
+	ECP2_ZZZ_copy(&P,&G);
+
+	ECP2_ZZZ_mul(&P,r);
+
+	ECP2_ZZZ_output(&P);
+
+	FP2_YYY_gfc(&f,12);
+
+	ECP2_ZZZ_frob(&G,&f);
+
+	ECP2_ZZZ_output(&G);
+
+	return 0;
+}
+
+*/
diff --git a/version3/c/ecp2.h b/version3/c/ecp2.h
new file mode 100644
index 0000000..32c0420
--- /dev/null
+++ b/version3/c/ecp2.h
@@ -0,0 +1,220 @@
+/*
+	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.
+*/
+
+/**
+ * @file ecp2.h
+ * @author Mike Scott
+ * @brief ECP2 Header File
+ *
+ */
+
+#ifndef ECP2_ZZZ_H
+#define ECP2_ZZZ_H
+
+#include "fp2_YYY.h"
+#include "config_curve_ZZZ.h"
+
+/**
+	@brief ECP2 Structure - Elliptic Curve Point over quadratic extension field
+*/
+
+typedef struct
+{
+//    int inf; /**< Infinity Flag */
+    FP2_YYY x;   /**< x-coordinate of point */
+    FP2_YYY y;   /**< y-coordinate of point */
+    FP2_YYY z;   /**< z-coordinate of point */
+} ECP2_ZZZ;
+
+
+/* Curve Params - see rom_zzz.c */
+extern const int CURVE_A_ZZZ;		/**< Elliptic curve A parameter */
+extern const int CURVE_B_I_ZZZ;		/**< Elliptic curve B parameter */
+extern const BIG_XXX CURVE_B_ZZZ;     /**< Elliptic curve B parameter */
+extern const BIG_XXX CURVE_Order_ZZZ; /**< Elliptic curve group order */
+extern const BIG_XXX CURVE_Cof_ZZZ;   /**< Elliptic curve cofactor */
+extern const BIG_XXX CURVE_Bnx_ZZZ;   /**< Elliptic curve parameter */
+
+extern const BIG_XXX Fra_YYY; /**< real part of BN curve Frobenius Constant */
+extern const BIG_XXX Frb_YYY; /**< imaginary part of BN curve Frobenius Constant */
+
+
+/* Generator point on G1 */
+extern const BIG_XXX CURVE_Gx_ZZZ; /**< x-coordinate of generator point in group G1  */
+extern const BIG_XXX CURVE_Gy_ZZZ; /**< y-coordinate of generator point in group G1  */
+
+/* For Pairings only */
+
+/* Generator point on G2 */
+extern const BIG_XXX CURVE_Pxa_ZZZ; /**< real part of x-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pxb_ZZZ; /**< imaginary part of x-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pya_ZZZ; /**< real part of y-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pyb_ZZZ; /**< imaginary part of y-coordinate of generator point in group G2 */
+
+/* ECP2 E(Fp2) prototypes */
+/**	@brief Tests for ECP2 point equal to infinity
+ *
+	@param P ECP2 point to be tested
+	@return 1 if infinity, else returns 0
+ */
+extern int ECP2_ZZZ_isinf(ECP2_ZZZ *P);
+/**	@brief Copy ECP2 point to another ECP2 point
+ *
+	@param P ECP2 instance, on exit = Q
+	@param Q ECP2 instance to be copied
+ */
+extern void ECP2_ZZZ_copy(ECP2_ZZZ *P,ECP2_ZZZ *Q);
+/**	@brief Set ECP2 to point-at-infinity
+ *
+	@param P ECP2 instance to be set to infinity
+ */
+extern void ECP2_ZZZ_inf(ECP2_ZZZ *P);
+/**	@brief Tests for equality of two ECP2s
+ *
+	@param P ECP2 instance to be compared
+	@param Q ECP2 instance to be compared
+	@return 1 if P=Q, else returns 0
+ */
+extern int ECP2_ZZZ_equals(ECP2_ZZZ *P,ECP2_ZZZ *Q);
+/**	@brief Converts an ECP2 point from Projective (x,y,z) coordinates to affine (x,y) coordinates
+ *
+	@param P ECP2 instance to be converted to affine form
+ */
+extern void ECP2_ZZZ_affine(ECP2_ZZZ *P);
+/**	@brief Extract x and y coordinates of an ECP2 point P
+ *
+	If x=y, returns only x
+	@param x FP2 on exit = x coordinate of point
+	@param y FP2 on exit = y coordinate of point (unless x=y)
+	@param P ECP2 instance (x,y)
+	@return -1 if P is point-at-infinity, else 0
+ */
+extern int ECP2_ZZZ_get(FP2_YYY *x,FP2_YYY *y,ECP2_ZZZ *P);
+/**	@brief Formats and outputs an ECP2 point to the console, converted to affine coordinates
+ *
+	@param P ECP2 instance to be printed
+ */
+extern void ECP2_ZZZ_output(ECP2_ZZZ *P);
+/**	@brief Formats and outputs an ECP2 point to the console, in projective coordinates
+ *
+	@param P ECP2 instance to be printed
+ */
+extern void ECP2_ZZZ_outputxyz(ECP2_ZZZ *P);
+/**	@brief Formats and outputs an ECP2 point to an octet string
+ *
+	The octet string is created in the form x|y.
+	Convert the real and imaginary parts of the x and y coordinates to big-endian base 256 form.
+	@param S output octet string
+	@param P ECP2 instance to be converted to an octet string
+ */
+extern void ECP2_ZZZ_toOctet(octet *S,ECP2_ZZZ *P);
+/**	@brief Creates an ECP2 point from an octet string
+ *
+	The octet string is in the form x|y
+	The real and imaginary parts of the x and y coordinates are in big-endian base 256 form.
+	@param P ECP2 instance to be created from the octet string
+	@param S input octet string
+	return 1 if octet string corresponds to a point on the curve, else 0
+ */
+extern int ECP2_ZZZ_fromOctet(ECP2_ZZZ *P,octet *S);
+/**	@brief Calculate Right Hand Side of curve equation y^2=f(x)
+ *
+	Function f(x)=x^3+Ax+B
+	Used internally.
+	@param r FP2 value of f(x)
+	@param x FP2 instance
+ */
+extern void ECP2_ZZZ_rhs(FP2_YYY *r,FP2_YYY *x);
+/**	@brief Set ECP2 to point(x,y) given x and y
+ *
+	Point P set to infinity if no such point on the curve.
+	@param P ECP2 instance to be set (x,y)
+	@param x FP2 x coordinate of point
+	@param y FP2 y coordinate of point
+	@return 1 if point exists, else 0
+ */
+extern int ECP2_ZZZ_set(ECP2_ZZZ *P,FP2_YYY *x,FP2_YYY *y);
+/**	@brief Set ECP to point(x,[y]) given x
+ *
+	Point P set to infinity if no such point on the curve. Otherwise y coordinate is calculated from x.
+	@param P ECP instance to be set (x,[y])
+	@param x BIG x coordinate of point
+	@return 1 if point exists, else 0
+ */
+extern int ECP2_ZZZ_setx(ECP2_ZZZ *P,FP2_YYY *x);
+/**	@brief Negation of an ECP2 point
+ *
+	@param P ECP2 instance, on exit = -P
+ */
+extern void ECP2_ZZZ_neg(ECP2_ZZZ *P);
+/**	@brief Doubles an ECP2 instance P
+ *
+	@param P ECP2 instance, on exit =2*P
+ */
+extern int ECP2_ZZZ_dbl(ECP2_ZZZ *P);
+/**	@brief Adds ECP2 instance Q to ECP2 instance P
+ *
+	@param P ECP2 instance, on exit =P+Q
+	@param Q ECP2 instance to be added to P
+ */
+extern int ECP2_ZZZ_add(ECP2_ZZZ *P,ECP2_ZZZ *Q);
+/**	@brief Subtracts ECP instance Q from ECP2 instance P
+ *
+	@param P ECP2 instance, on exit =P-Q
+	@param Q ECP2 instance to be subtracted from P
+ */
+extern void ECP2_ZZZ_sub(ECP2_ZZZ *P,ECP2_ZZZ *Q);
+/**	@brief Multiplies an ECP2 instance P by a BIG, side-channel resistant
+ *
+	Uses fixed sized windows.
+	@param P ECP2 instance, on exit =b*P
+	@param b BIG number multiplier
+
+ */
+extern void ECP2_ZZZ_mul(ECP2_ZZZ *P,BIG_XXX b);
+/**	@brief Multiplies an ECP2 instance P by the internal modulus p, using precalculated Frobenius constant f
+ *
+	Fast point multiplication using Frobenius
+	@param P ECP2 instance, on exit = p*P
+	@param f FP2 precalculated Frobenius constant
+
+ */
+extern void ECP2_ZZZ_frob(ECP2_ZZZ *P,FP2_YYY *f);
+/**	@brief Calculates P=b[0]*Q[0]+b[1]*Q[1]+b[2]*Q[2]+b[3]*Q[3]
+ *
+	@param P ECP2 instance, on exit = b[0]*Q[0]+b[1]*Q[1]+b[2]*Q[2]+b[3]*Q[3]
+	@param Q ECP2 array of 4 points
+	@param b BIG array of 4 multipliers
+ */
+extern void ECP2_ZZZ_mul4(ECP2_ZZZ *P,ECP2_ZZZ *Q,BIG_XXX *b);
+
+/**	@brief Maps random BIG to curve point of correct order
+ *
+	@param P ECP2 instance of correct order
+	@param w OCTET byte array to be mapped
+ */
+extern void ECP2_ZZZ_mapit(ECP2_ZZZ *P,octet *w);
+
+/**	@brief Get Group Generator from ROM
+ *
+	@param G ECP2 instance
+ */
+extern void ECP2_ZZZ_generator(ECP2_ZZZ *G);
+
+#endif
diff --git a/version3/c/ecp4.c b/version3/c/ecp4.c
new file mode 100644
index 0000000..1208812
--- /dev/null
+++ b/version3/c/ecp4.c
@@ -0,0 +1,1068 @@
+/*
+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.
+*/
+
+/* AMCL Weierstrass elliptic curve functions over FP2 */
+
+#include "ecp4_ZZZ.h"
+
+int ECP4_ZZZ_isinf(ECP4_ZZZ *P)
+{
+//	if (P->inf) return 1;
+	return (FP4_YYY_iszilch(&(P->x)) & FP4_YYY_iszilch(&(P->z)));
+}
+
+/* Set P=Q */
+void ECP4_ZZZ_copy(ECP4_ZZZ *P,ECP4_ZZZ *Q)
+{
+//    P->inf=Q->inf;
+    FP4_YYY_copy(&(P->x),&(Q->x));
+    FP4_YYY_copy(&(P->y),&(Q->y));
+	FP4_YYY_copy(&(P->z),&(Q->z));
+}
+
+/* set P to Infinity */
+void ECP4_ZZZ_inf(ECP4_ZZZ *P)
+{
+//    P->inf=1;
+    FP4_YYY_zero(&(P->x));
+    FP4_YYY_one(&(P->y));
+    FP4_YYY_zero(&(P->z));
+}
+
+/* Conditional move Q to P dependant on d */
+static void ECP4_ZZZ_cmove(ECP4_ZZZ *P,ECP4_ZZZ *Q,int d)
+{
+    FP4_YYY_cmove(&(P->x),&(Q->x),d);
+    FP4_YYY_cmove(&(P->y),&(Q->y),d);
+    FP4_YYY_cmove(&(P->z),&(Q->z),d);
+//    d=~(d-1);
+//    P->inf^=(P->inf^Q->inf)&d;
+}
+
+/* return 1 if b==c, no branching */
+static int teq(sign32 b,sign32 c)
+{
+    sign32 x=b^c;
+    x-=1;  // if x=0, x now -1
+    return (int)((x>>31)&1);
+}
+
+/* Constant time select from pre-computed table */
+static void ECP4_ZZZ_select(ECP4_ZZZ *P,ECP4_ZZZ W[],sign32 b)
+{
+    ECP4_ZZZ MP;
+    sign32 m=b>>31;
+    sign32 babs=(b^m)-m;
+
+    babs=(babs-1)/2;
+
+    ECP4_ZZZ_cmove(P,&W[0],teq(babs,0));  // conditional move
+    ECP4_ZZZ_cmove(P,&W[1],teq(babs,1));
+    ECP4_ZZZ_cmove(P,&W[2],teq(babs,2));
+    ECP4_ZZZ_cmove(P,&W[3],teq(babs,3));
+    ECP4_ZZZ_cmove(P,&W[4],teq(babs,4));
+    ECP4_ZZZ_cmove(P,&W[5],teq(babs,5));
+    ECP4_ZZZ_cmove(P,&W[6],teq(babs,6));
+    ECP4_ZZZ_cmove(P,&W[7],teq(babs,7));
+
+    ECP4_ZZZ_copy(&MP,P);
+    ECP4_ZZZ_neg(&MP);  // minus P
+    ECP4_ZZZ_cmove(P,&MP,(int)(m&1));
+}
+
+/* Make P affine (so z=1) */
+void ECP4_ZZZ_affine(ECP4_ZZZ *P)
+{
+    FP4_YYY one,iz;
+    if (ECP4_ZZZ_isinf(P)) return;
+
+    FP4_YYY_one(&one);
+    if (FP4_YYY_isunity(&(P->z)))
+    {
+        FP4_YYY_reduce(&(P->x));
+        FP4_YYY_reduce(&(P->y));
+        return;
+    }
+
+    FP4_YYY_inv(&iz,&(P->z));
+    FP4_YYY_mul(&(P->x),&(P->x),&iz);
+    FP4_YYY_mul(&(P->y),&(P->y),&iz);
+
+    FP4_YYY_reduce(&(P->x));
+    FP4_YYY_reduce(&(P->y));
+    FP4_YYY_copy(&(P->z),&one);
+}
+
+/* return 1 if P==Q, else 0 */
+/* SU= 312 */
+int ECP4_ZZZ_equals(ECP4_ZZZ *P,ECP4_ZZZ *Q)
+{
+    FP4_YYY a,b;
+//    if (ECP4_ZZZ_isinf(P) && ECP4_ZZZ_isinf(Q)) return 1;
+//    if (ECP4_ZZZ_isinf(P) || ECP4_ZZZ_isinf(Q)) return 0;
+
+    FP4_YYY_mul(&a,&(P->x),&(Q->z));
+    FP4_YYY_mul(&b,&(Q->x),&(P->z));
+    if (!FP4_YYY_equals(&a,&b)) return 0;
+
+    FP4_YYY_mul(&a,&(P->y),&(Q->z));
+    FP4_YYY_mul(&b,&(Q->y),&(P->z));
+    if (!FP4_YYY_equals(&a,&b)) return 0;
+    return 1;
+
+}
+
+/* extract x, y from point P */
+int ECP4_ZZZ_get(FP4_YYY *x,FP4_YYY *y,ECP4_ZZZ *P)
+{
+	ECP4_ZZZ W;
+	ECP4_ZZZ_copy(&W,P);
+	ECP4_ZZZ_affine(&W);
+    if (ECP4_ZZZ_isinf(&W)) return -1;
+	//ECP4_ZZZ_affine(P);
+    FP4_YYY_copy(y,&(W.y));
+    FP4_YYY_copy(x,&(W.x));
+    return 0;
+}
+
+/* Output point P */
+void ECP4_ZZZ_output(ECP4_ZZZ *P)
+{
+    FP4_YYY x,y;
+    if (ECP4_ZZZ_isinf(P))
+    {
+        printf("Infinity\n");
+        return;
+    }
+    ECP4_ZZZ_get(&x,&y,P);
+    printf("(");
+    FP4_YYY_output(&x);
+    printf(",");
+    FP4_YYY_output(&y);
+    printf(")\n");
+}
+
+/* Convert Q to octet string */
+void ECP4_ZZZ_toOctet(octet *W,ECP4_ZZZ *Q)
+{
+	BIG_XXX b;
+	FP4_YYY qx,qy;
+	FP2_YYY pa,pb;
+
+    ECP4_ZZZ_get(&qx,&qy,Q);
+
+	FP2_YYY_copy(&pa,&(qx.a));
+	FP2_YYY_copy(&pb,&(qx.b));
+
+	FP_YYY_redc(b,&(pa.a));
+    BIG_XXX_toBytes(&(W->val[0]),b);
+    FP_YYY_redc(b,&(pa.b));
+    BIG_XXX_toBytes(&(W->val[MODBYTES_XXX]),b);
+    FP_YYY_redc(b,&(pb.a));
+    BIG_XXX_toBytes(&(W->val[2*MODBYTES_XXX]),b);
+    FP_YYY_redc(b,&(pb.b));
+    BIG_XXX_toBytes(&(W->val[3*MODBYTES_XXX]),b);
+
+	FP2_YYY_copy(&pa,&(qy.a));
+	FP2_YYY_copy(&pb,&(qy.b));
+	
+	FP_YYY_redc(b,&(pa.a));
+    BIG_XXX_toBytes(&(W->val[4*MODBYTES_XXX]),b);
+    FP_YYY_redc(b,&(pa.b));
+    BIG_XXX_toBytes(&(W->val[5*MODBYTES_XXX]),b);
+    FP_YYY_redc(b,&(pb.a));
+    BIG_XXX_toBytes(&(W->val[6*MODBYTES_XXX]),b);
+    FP_YYY_redc(b,&(pb.b));
+    BIG_XXX_toBytes(&(W->val[7*MODBYTES_XXX]),b);
+
+    W->len=8*MODBYTES_XXX;
+}
+
+/* restore Q from octet string */
+int ECP4_ZZZ_fromOctet(ECP4_ZZZ *Q,octet *W)
+{
+	BIG_XXX b;
+    FP4_YYY qx,qy;
+	FP2_YYY pa,pb;
+
+    BIG_XXX_fromBytes(b,&(W->val[0]));
+	FP_YYY_nres(&(pa.a),b);
+    BIG_XXX_fromBytes(b,&(W->val[MODBYTES_XXX]));
+    FP_YYY_nres(&(pa.b),b);
+    BIG_XXX_fromBytes(b,&(W->val[2*MODBYTES_XXX]));
+    FP_YYY_nres(&(pb.a),b);
+    BIG_XXX_fromBytes(b,&(W->val[3*MODBYTES_XXX]));
+    FP_YYY_nres(&(pb.b),b);
+
+	FP2_YYY_copy(&(qx.a),&pa);
+	FP2_YYY_copy(&(qx.b),&pb);
+
+    BIG_XXX_fromBytes(b,&(W->val[4*MODBYTES_XXX]));
+	FP_YYY_nres(&(pa.a),b);
+    BIG_XXX_fromBytes(b,&(W->val[5*MODBYTES_XXX]));
+    FP_YYY_nres(&(pa.b),b);
+    BIG_XXX_fromBytes(b,&(W->val[6*MODBYTES_XXX]));
+    FP_YYY_nres(&(pb.a),b);
+    BIG_XXX_fromBytes(b,&(W->val[7*MODBYTES_XXX]));
+    FP_YYY_nres(&(pb.b),b);
+
+	FP2_YYY_copy(&(qy.a),&pa);
+	FP2_YYY_copy(&(qy.b),&pb);
+
+
+    if (ECP4_ZZZ_set(Q,&qx,&qy)) return 1;
+    return 0;
+}
+
+/* Calculate RHS of twisted curve equation x^3+B/i or x^3+Bi*/
+void ECP4_ZZZ_rhs(FP4_YYY *rhs,FP4_YYY *x)
+{
+    /* calculate RHS of elliptic curve equation */
+    FP4_YYY t;
+	FP2_YYY t2;
+    BIG_XXX b;
+    FP4_YYY_sqr(&t,x);
+
+    FP4_YYY_mul(rhs,&t,x);
+
+    /* Assuming CURVE_A=0 */
+
+    BIG_XXX_rcopy(b,CURVE_B_ZZZ);
+
+    FP2_YYY_from_BIG(&t2,b);
+	FP4_YYY_from_FP2(&t,&t2);
+
+#if SEXTIC_TWIST_ZZZ == D_TYPE	
+    FP4_YYY_div_i(&t);   /* IMPORTANT - here we use the correct SEXTIC twist of the curve */
+#endif
+
+#if SEXTIC_TWIST_ZZZ == M_TYPE	
+    FP4_YYY_times_i(&t);   /* IMPORTANT - here we use the correct SEXTIC twist of the curve */
+#endif
+
+    FP4_YYY_add(rhs,&t,rhs);
+    FP4_YYY_reduce(rhs);
+}
+
+/* Set P=(x,y). Return 1 if (x,y) is on the curve, else return 0*/
+/* SU= 232 */
+int ECP4_ZZZ_set(ECP4_ZZZ *P,FP4_YYY *x,FP4_YYY *y)
+{
+    FP4_YYY rhs,y2;
+
+    FP4_YYY_sqr(&y2,y);
+    ECP4_ZZZ_rhs(&rhs,x);
+
+//cout << "y2= ";
+//FP4_YYY_output(&y2);
+//cout << endl;
+//cout << "rhs= ";
+//FP4_YYY_output(&rhs);
+//cout << endl;
+
+    if (!FP4_YYY_equals(&y2,&rhs))
+    {
+		ECP4_ZZZ_inf(P);
+ //       P->inf=1;
+        return 0;
+    }
+
+ //   P->inf=0;
+    FP4_YYY_copy(&(P->x),x);
+    FP4_YYY_copy(&(P->y),y);
+
+    FP4_YYY_one(&(P->z));
+    return 1;
+}
+
+/* Set P=(x,y). Return 1 if (x,.) is on the curve, else return 0 */
+/* SU= 232 */
+int ECP4_ZZZ_setx(ECP4_ZZZ *P,FP4_YYY *x)
+{
+    FP4_YYY y;
+    ECP4_ZZZ_rhs(&y,x);
+
+    if (!FP4_YYY_sqrt(&y,&y))
+    {
+        ECP4_ZZZ_inf(P);
+        return 0;
+    }
+
+ //   P->inf=0;
+    FP4_YYY_copy(&(P->x),x);
+    FP4_YYY_copy(&(P->y),&y);
+
+    FP4_YYY_one(&(P->z));
+    return 1;
+}
+
+/* Set P=-P */
+/* SU= 8 */
+void ECP4_ZZZ_neg(ECP4_ZZZ *P)
+{
+//	if (ECP4_ZZZ_isinf(P)) return;
+	FP4_YYY_norm(&(P->y));
+    FP4_YYY_neg(&(P->y),&(P->y));
+    FP4_YYY_norm(&(P->y));
+}
+
+
+/* R+=R */
+/* return -1 for Infinity, 0 for addition, 1 for doubling */
+int ECP4_ZZZ_dbl(ECP4_ZZZ *P)
+{
+    FP4_YYY t0,t1,t2,t3,iy,x3,y3;
+//    if (P->inf) return -1;
+
+	FP4_YYY_copy(&iy,&(P->y));		//FP4_YYY iy=new FP4_YYY(y);
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+	FP4_YYY_times_i(&iy);			//iy.mul_ip(); 
+	//FP4_YYY_norm(&iy);				//iy.norm();
+#endif
+
+	FP4_YYY_sqr(&t0,&(P->y));			//t0.sqr();   
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+	FP4_YYY_times_i(&t0);			//t0.mul_ip(); 
+#endif
+
+	FP4_YYY_mul(&t1,&iy,&(P->z));	//t1.mul(z);
+	FP4_YYY_sqr(&t2,&(P->z));				//t2.sqr();
+
+	FP4_YYY_add(&(P->z),&t0,&t0);	//z.add(t0); 
+	FP4_YYY_norm(&(P->z));				//z.norm(); 
+	FP4_YYY_add(&(P->z),&(P->z),&(P->z));	//z.add(z); 
+	FP4_YYY_add(&(P->z),&(P->z),&(P->z));	//z.add(z); 
+	FP4_YYY_norm(&(P->z));			//z.norm();  
+
+	FP4_YYY_imul(&t2,&t2,3*CURVE_B_I_ZZZ);	//t2.imul(3*ROM.CURVE_B_I); 
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+	FP4_YYY_times_i(&t2);
+	//FP4_YYY_norm(&t2);
+#endif
+
+	FP4_YYY_mul(&x3,&t2,&(P->z));	//x3.mul(z); 
+
+	FP4_YYY_add(&y3,&t0,&t2);		//y3.add(t2); 
+	FP4_YYY_norm(&y3);				//y3.norm();
+	FP4_YYY_mul(&(P->z),&(P->z),&t1);	//z.mul(t1);
+
+	FP4_YYY_add(&t1,&t2,&t2);		//t1.add(t2); 
+	FP4_YYY_add(&t2,&t2,&t1);		//t2.add(t1); 
+	FP4_YYY_norm(&t2);				//t2.norm();  
+	FP4_YYY_sub(&t0,&t0,&t2);		//t0.sub(t2); 
+	FP4_YYY_norm(&t0);				//t0.norm();                           //y^2-9bz^2
+	FP4_YYY_mul(&y3,&y3,&t0);		//y3.mul(t0); 
+	FP4_YYY_add(&(P->y),&y3,&x3);		//y3.add(x3);                          //(y^2+3z*2)(y^2-9z^2)+3b.z^2.8y^2
+
+	FP4_YYY_mul(&t1,&(P->x),&iy);		//t1.mul(iy);						//
+
+	FP4_YYY_norm(&t0);			//x.norm(); 
+	FP4_YYY_mul(&(P->x),&t0,&t1);	//x.mul(t1); 
+	FP4_YYY_add(&(P->x),&(P->x),&(P->x));	//x.add(x);       //(y^2-9bz^2)xy2
+
+	FP4_YYY_norm(&(P->x));			//x.norm(); 
+
+	FP4_YYY_norm(&(P->y));			//y.norm();
+
+    return 1;
+}
+
+/* Set P+=Q */
+
+int ECP4_ZZZ_add(ECP4_ZZZ *P,ECP4_ZZZ *Q)
+{
+    FP4_YYY t0,t1,t2,t3,t4,x3,y3,z3;
+	int b3=3*CURVE_B_I_ZZZ;
+/*    if (Q->inf) return 0;
+    if (P->inf)
+    {
+        ECP4_ZZZ_copy(P,Q);
+        return 0;
+    }
+*/
+	FP4_YYY_mul(&t0,&(P->x),&(Q->x));	//t0.mul(Q.x);         // x.Q.x
+	FP4_YYY_mul(&t1,&(P->y),&(Q->y));	//t1.mul(Q.y);		 // y.Q.y
+
+	FP4_YYY_mul(&t2,&(P->z),&(Q->z));	//t2.mul(Q.z);
+	FP4_YYY_add(&t3,&(P->x),&(P->y));	//t3.add(y); 
+	FP4_YYY_norm(&t3);				//t3.norm();          //t3=X1+Y1         
+	FP4_YYY_add(&t4,&(Q->x),&(Q->y));	//t4.add(Q.y); 
+	FP4_YYY_norm(&t4);				//t4.norm();			//t4=X2+Y2
+	FP4_YYY_mul(&t3,&t3,&t4);		//t3.mul(t4);						//t3=(X1+Y1)(X2+Y2)
+	FP4_YYY_add(&t4,&t0,&t1);		//t4.add(t1);		//t4=X1.X2+Y1.Y2
+
+	FP4_YYY_sub(&t3,&t3,&t4);		//t3.sub(t4); 
+	FP4_YYY_norm(&t3);				//t3.norm(); 
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+	FP4_YYY_times_i(&t3);			//t3.mul_ip();  
+	//FP4_YYY_norm(&t3);				//t3.norm();         //t3=(X1+Y1)(X2+Y2)-(X1.X2+Y1.Y2) = X1.Y2+X2.Y1
+#endif
+                   
+	FP4_YYY_add(&t4,&(P->y),&(P->z));	//t4.add(z); 
+	FP4_YYY_norm(&t4);				//t4.norm();			//t4=Y1+Z1
+
+	FP4_YYY_add(&x3,&(Q->y),&(Q->z));	//x3.add(Q.z); 
+	FP4_YYY_norm(&x3);				//x3.norm();			//x3=Y2+Z2
+
+	FP4_YYY_mul(&t4,&t4,&x3);		//t4.mul(x3);						//t4=(Y1+Z1)(Y2+Z2)
+
+	FP4_YYY_add(&x3,&t1,&t2);		//x3.add(t2);						//X3=Y1.Y2+Z1.Z2
+	
+	FP4_YYY_sub(&t4,&t4,&x3);		//t4.sub(x3); 
+	FP4_YYY_norm(&t4);				//t4.norm(); 
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+	FP4_YYY_times_i(&t4);			//t4.mul_ip(); 
+	//FP4_YYY_norm(&t4);				//t4.norm();          //t4=(Y1+Z1)(Y2+Z2) - (Y1.Y2+Z1.Z2) = Y1.Z2+Y2.Z1
+#endif
+
+	FP4_YYY_add(&x3,&(P->x),&(P->z));	//x3.add(z); 
+	FP4_YYY_norm(&x3);				//x3.norm();	// x3=X1+Z1
+		
+	FP4_YYY_add(&y3,&(Q->x),&(Q->z));	//y3.add(Q.z); 
+	FP4_YYY_norm(&y3);				//y3.norm();				// y3=X2+Z2
+	FP4_YYY_mul(&x3,&x3,&y3);		//x3.mul(y3);							// x3=(X1+Z1)(X2+Z2)
+
+	FP4_YYY_add(&y3,&t0,&t2);		//y3.add(t2);							// y3=X1.X2+Z1+Z2
+	FP4_YYY_sub(&y3,&x3,&y3);		//y3.rsub(x3); 
+	FP4_YYY_norm(&y3);				//y3.norm();				// y3=(X1+Z1)(X2+Z2) - (X1.X2+Z1.Z2) = X1.Z2+X2.Z1
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+	FP4_YYY_times_i(&t0);			//t0.mul_ip(); 
+	//FP4_YYY_norm(&t0);				//t0.norm(); // x.Q.x
+	FP4_YYY_times_i(&t1);			//t1.mul_ip(); 
+	//FP4_YYY_norm(&t1);				//t1.norm(); // y.Q.y
+#endif
+
+	FP4_YYY_add(&x3,&t0,&t0);		//x3.add(t0); 
+	FP4_YYY_add(&t0,&t0,&x3);		//t0.add(x3); 
+	FP4_YYY_norm(&t0);				//t0.norm();
+	FP4_YYY_imul(&t2,&t2,b3);		//t2.imul(b); 	
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+	FP4_YYY_times_i(&t2);
+#endif
+
+	FP4_YYY_add(&z3,&t1,&t2);		//z3.add(t2); 
+	FP4_YYY_norm(&z3);				//z3.norm();
+	FP4_YYY_sub(&t1,&t1,&t2);		//t1.sub(t2); 
+	FP4_YYY_norm(&t1);				//t1.norm(); 
+	FP4_YYY_imul(&y3,&y3,b3);		//y3.imul(b); 
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+	FP4_YYY_times_i(&y3);
+	//FP4_YYY_norm(&y3);
+#endif
+
+	FP4_YYY_mul(&x3,&y3,&t4);		//x3.mul(t4); 
+
+	FP4_YYY_mul(&t2,&t3,&t1);		//t2.mul(t1); 
+	FP4_YYY_sub(&(P->x),&t2,&x3);		//x3.rsub(t2);
+	FP4_YYY_mul(&y3,&y3,&t0);		//y3.mul(t0); 
+	FP4_YYY_mul(&t1,&t1,&z3);		//t1.mul(z3); 
+	FP4_YYY_add(&(P->y),&y3,&t1);		//y3.add(t1);
+	FP4_YYY_mul(&t0,&t0,&t3);		//t0.mul(t3); 
+	FP4_YYY_mul(&z3,&z3,&t4);		//z3.mul(t4); 
+	FP4_YYY_add(&(P->z),&z3,&t0);		//z3.add(t0);
+
+
+	FP4_YYY_norm(&(P->x));			//x.norm(); 
+	FP4_YYY_norm(&(P->y));			//y.norm();
+	FP4_YYY_norm(&(P->z));			//z.norm();
+
+    return 0;
+}
+
+/* Set P-=Q */
+/* SU= 16 */
+void ECP4_ZZZ_sub(ECP4_ZZZ *P,ECP4_ZZZ *Q)
+{
+	ECP4_ZZZ NQ;
+	ECP4_ZZZ_copy(&NQ,Q);
+	ECP4_ZZZ_neg(&NQ);
+    //ECP4_ZZZ_neg(Q);
+    ECP4_ZZZ_add(P,&NQ);
+    //ECP4_ZZZ_neg(Q);
+}
+
+
+void ECP4_ZZZ_reduce(ECP4_ZZZ *P)
+{
+	FP4_YYY_reduce(&(P->x));
+	FP4_YYY_reduce(&(P->y));
+	FP4_YYY_reduce(&(P->z));
+}
+
+/* P*=e */
+/* SU= 280 */
+void ECP4_ZZZ_mul(ECP4_ZZZ *P,BIG_XXX e)
+{
+    /* fixed size windows */
+    int i,nb,s,ns;
+    BIG_XXX mt,t;
+    ECP4_ZZZ Q,W[8],C;
+    sign8 w[1+(NLEN_XXX*BASEBITS_XXX+3)/4];
+
+    if (ECP4_ZZZ_isinf(P)) return;
+    //ECP4_ZZZ_affine(P);
+
+    /* precompute table */
+
+    ECP4_ZZZ_copy(&Q,P);
+    ECP4_ZZZ_dbl(&Q);
+    ECP4_ZZZ_copy(&W[0],P);
+
+    for (i=1; i<8; i++)
+    {
+        ECP4_ZZZ_copy(&W[i],&W[i-1]);
+        ECP4_ZZZ_add(&W[i],&Q);
+    }
+
+    /* make exponent odd - add 2P if even, P if odd */
+    BIG_XXX_copy(t,e);
+    s=BIG_XXX_parity(t);
+    BIG_XXX_inc(t,1);
+    BIG_XXX_norm(t);
+    ns=BIG_XXX_parity(t);
+    BIG_XXX_copy(mt,t);
+    BIG_XXX_inc(mt,1);
+    BIG_XXX_norm(mt);
+    BIG_XXX_cmove(t,mt,s);
+    ECP4_ZZZ_cmove(&Q,P,ns);
+    ECP4_ZZZ_copy(&C,&Q);
+
+    nb=1+(BIG_XXX_nbits(t)+3)/4;
+
+    /* convert exponent to signed 4-bit window */
+    for (i=0; i<nb; i++)
+    {
+        w[i]=BIG_XXX_lastbits(t,5)-16;
+        BIG_XXX_dec(t,w[i]);
+        BIG_XXX_norm(t);
+        BIG_XXX_fshr(t,4);
+    }
+    w[nb]=BIG_XXX_lastbits(t,5);
+
+    ECP4_ZZZ_copy(P,&W[(w[nb]-1)/2]);
+    for (i=nb-1; i>=0; i--)
+    {
+        ECP4_ZZZ_select(&Q,W,w[i]);
+        ECP4_ZZZ_dbl(P);
+        ECP4_ZZZ_dbl(P);
+        ECP4_ZZZ_dbl(P);
+        ECP4_ZZZ_dbl(P);
+        ECP4_ZZZ_add(P,&Q);
+    }
+    ECP4_ZZZ_sub(P,&C); /* apply correction */
+	ECP4_ZZZ_affine(P);
+}
+
+// calculate frobenius constants 
+void ECP4_ZZZ_frob_constants(FP2_YYY F[3])
+{
+    FP_YYY fx,fy;
+	FP2_YYY X;
+
+    FP_YYY_rcopy(&fx,Fra_YYY);
+    FP_YYY_rcopy(&fy,Frb_YYY);
+    FP2_YYY_from_FPs(&X,&fx,&fy);
+
+	FP2_YYY_sqr(&F[0],&X);		// FF=F^2=(1+i)^(p-7)/6
+	FP2_YYY_copy(&F[2],&F[0]);
+	FP2_YYY_mul_ip(&F[2]);		// W=(1+i)^6/6.(1+i)^(p-7)/6 = (1+i)^(p-1)/6
+	FP2_YYY_norm(&F[2]);
+	FP2_YYY_sqr(&F[1],&F[2]);
+	FP2_YYY_mul(&F[2],&F[2],&F[1]);  // W=(1+i)^(p-1)/2
+
+	FP2_YYY_copy(&F[1],&X);
+
+#if SEXTIC_TWIST_ZZZ == M_TYPE	
+	FP2_YYY_mul_ip(&F[1]);		// (1+i)^12/12.(1+i)^(p-7)/12 = (1+i)^(p+5)/12
+	FP2_YYY_inv(&F[1],&F[1]);		// (1+i)^-(p+5)/12
+	FP2_YYY_sqr(&F[0],&F[1]);		// (1+i)^-(p+5)/6
+#endif
+
+	FP2_YYY_mul_ip(&F[0]);		// FF=(1+i)^(p-7)/6.(1+i) = (1+i)^(p-1)/6					// (1+i)^6/6.(1+i)^-(p+5)/6 = (1+i)^-(p-1)/6
+	FP2_YYY_norm(&F[0]);
+	FP2_YYY_mul(&F[1],&F[1],&F[0]);  // FFF = (1+i)^(p-7)/12 . (1+i)^(p-1)/6 = (1+i)^(p-3)/4	// (1+i)^-(p+5)/12 . (1+i)^-(p-1)/6 = (1+i)^-(p+1)/4
+
+}
+
+/* Calculates q^n.P using Frobenius constants */
+void ECP4_ZZZ_frob(ECP4_ZZZ *P,FP2_YYY F[3],int n)
+{
+	int i;
+	FP4_YYY X,Y,Z;
+//    if (P->inf) return;
+
+	//ECP4_get(&X,&Y,P);		// F=(1+i)^(p-7)/12
+
+	FP4_YYY_copy(&X,&(P->x));
+	FP4_YYY_copy(&Y,&(P->y));
+	FP4_YYY_copy(&Z,&(P->z));
+
+	for (i=0;i<n;i++)
+	{
+		FP4_YYY_frob(&X,&F[2]);		// X^p
+		FP4_YYY_pmul(&X,&X,&F[0]);	// X^p.(1+i)^(p-1)/6									// X^p.(1+i)^-(p-1)/6
+		
+		FP4_YYY_frob(&Y,&F[2]);		// Y^p
+		FP4_YYY_pmul(&Y,&Y,&F[1]);
+		FP4_YYY_times_i(&Y);		// Y.p.(1+i)^(p-3)/4.(1+i)^(2/4) = Y^p.(1+i)^(p-1)/4	// (1+i)^-(p+1)/4 .(1+i)^2/4 = Y^p.(1+i)^-(p-1)/4
+
+		FP4_YYY_frob(&Z,&F[2]);
+	}
+
+	FP4_YYY_copy(&(P->x),&X);
+	FP4_YYY_copy(&(P->y),&Y);
+	FP4_YYY_copy(&(P->z),&Z);
+}
+
+/* Side channel attack secure */
+// Bos & Costello https://eprint.iacr.org/2013/458.pdf
+// Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
+
+void ECP4_ZZZ_mul8(ECP4_ZZZ *P,ECP4_ZZZ Q[8],BIG_XXX u[8])
+{
+    int i,j,k,nb,pb1,pb2,bt;
+	ECP4_ZZZ T1[8],T2[8],W;
+    BIG_XXX mt,t[8];
+    sign8 w1[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 s1[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 w2[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 s2[NLEN_XXX*BASEBITS_XXX+1];	
+	FP2_YYY X[3];
+
+	ECP4_ZZZ_frob_constants(X);
+
+    for (i=0; i<8; i++)
+	{
+        //ECP4_ZZZ_affine(&Q[i]);
+        BIG_XXX_copy(t[i],u[i]);
+	}
+
+// Precomputed table
+    ECP4_ZZZ_copy(&T1[0],&Q[0]); // Q[0]
+    ECP4_ZZZ_copy(&T1[1],&T1[0]);
+	ECP4_ZZZ_add(&T1[1],&Q[1]);	// Q[0]+Q[1]
+    ECP4_ZZZ_copy(&T1[2],&T1[0]);
+	ECP4_ZZZ_add(&T1[2],&Q[2]);	// Q[0]+Q[2]
+	ECP4_ZZZ_copy(&T1[3],&T1[1]);
+	ECP4_ZZZ_add(&T1[3],&Q[2]);	// Q[0]+Q[1]+Q[2]
+	ECP4_ZZZ_copy(&T1[4],&T1[0]);
+	ECP4_ZZZ_add(&T1[4],&Q[3]);  // Q[0]+Q[3]
+	ECP4_ZZZ_copy(&T1[5],&T1[1]);
+	ECP4_ZZZ_add(&T1[5],&Q[3]);	// Q[0]+Q[1]+Q[3]
+	ECP4_ZZZ_copy(&T1[6],&T1[2]);
+	ECP4_ZZZ_add(&T1[6],&Q[3]);	// Q[0]+Q[2]+Q[3]
+	ECP4_ZZZ_copy(&T1[7],&T1[3]);
+	ECP4_ZZZ_add(&T1[7],&Q[3]);	// Q[0]+Q[1]+Q[2]+Q[3]
+
+//  Use Frobenius 
+
+	for (i=0;i<8;i++)
+	{
+		ECP4_ZZZ_copy(&T2[i],&T1[i]);
+		ECP4_ZZZ_frob(&T2[i],X,4);
+	}
+
+// Make them odd
+	pb1=1-BIG_XXX_parity(t[0]);
+	BIG_XXX_inc(t[0],pb1);
+	BIG_XXX_norm(t[0]);
+
+	pb2=1-BIG_XXX_parity(t[4]);
+	BIG_XXX_inc(t[4],pb2);
+	BIG_XXX_norm(t[4]);
+
+// Number of bits
+    BIG_XXX_zero(mt);
+    for (i=0; i<8; i++)
+    {
+        BIG_XXX_or(mt,mt,t[i]);
+    }
+    nb=1+BIG_XXX_nbits(mt);
+
+// Sign pivot 
+	s1[nb-1]=1;
+	s2[nb-1]=1;
+	for (i=0;i<nb-1;i++)
+	{
+        BIG_XXX_fshr(t[0],1);
+		s1[i]=2*BIG_XXX_parity(t[0])-1;
+        BIG_XXX_fshr(t[4],1);
+		s2[i]=2*BIG_XXX_parity(t[4])-1;
+	}
+
+
+// Recoded exponents
+    for (i=0; i<nb; i++)
+    {
+		w1[i]=0;
+		k=1;
+		for (j=1; j<4; j++)
+		{
+			bt=s1[i]*BIG_XXX_parity(t[j]);
+			BIG_XXX_fshr(t[j],1);
+
+			BIG_XXX_dec(t[j],(bt>>1));
+			BIG_XXX_norm(t[j]);
+			w1[i]+=bt*k;
+			k*=2;
+        }
+
+		w2[i]=0;
+		k=1;
+		for (j=5; j<8; j++)
+		{
+			bt=s2[i]*BIG_XXX_parity(t[j]);
+			BIG_XXX_fshr(t[j],1);
+
+			BIG_XXX_dec(t[j],(bt>>1));
+			BIG_XXX_norm(t[j]);
+			w2[i]+=bt*k;
+			k*=2;
+        }
+    }	
+
+// Main loop
+	ECP4_ZZZ_select(P,T1,2*w1[nb-1]+1);
+	ECP4_ZZZ_select(&W,T2,2*w2[nb-1]+1);
+	ECP4_ZZZ_add(P,&W);
+    for (i=nb-2; i>=0; i--)
+    {
+        ECP4_ZZZ_dbl(P);
+        ECP4_ZZZ_select(&W,T1,2*w1[i]+s1[i]);
+        ECP4_ZZZ_add(P,&W);
+        ECP4_ZZZ_select(&W,T2,2*w2[i]+s2[i]);
+        ECP4_ZZZ_add(P,&W);
+    }
+
+// apply corrections
+	ECP4_ZZZ_copy(&W,P);   
+	ECP4_ZZZ_sub(&W,&Q[0]);
+	ECP4_ZZZ_cmove(P,&W,pb1);
+	ECP4_ZZZ_copy(&W,P);   
+	ECP4_ZZZ_sub(&W,&Q[4]);
+	ECP4_ZZZ_cmove(P,&W,pb2);
+
+	ECP4_ZZZ_affine(P);
+}
+/*
+void ECP4_ZZZ_mul8(ECP4_ZZZ *P,ECP4_ZZZ Q[8],BIG_XXX u[8])
+{
+    int i,j,a[4],nb,pb;
+    ECP4_ZZZ W[8],Z[8],T,C;
+    BIG_XXX mt,t[8];
+    sign8 w[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 z[NLEN_XXX*BASEBITS_XXX+1];
+    FP fx,fy;
+	FP2_YYY X;
+
+    FP_YYY_rcopy(&fx,Fra);
+    FP_YYY_rcopy(&fy,Frb);
+    FP2_YYY_from_FPs(&X,&fx,&fy);
+
+    for (i=0; i<8; i++)
+        BIG_XXX_copy(t[i],u[i]);
+
+    // precompute tables 
+
+// 12 add/subs 
+
+    ECP4_ZZZ_copy(&W[0],&Q[0]);
+    ECP4_ZZZ_sub(&W[0],&Q[1]);  // P-Q 
+    ECP4_ZZZ_copy(&W[1],&W[0]);
+    ECP4_ZZZ_copy(&W[2],&W[0]);
+    ECP4_ZZZ_copy(&W[3],&W[0]);
+    ECP4_ZZZ_copy(&W[4],&Q[0]);
+    ECP4_ZZZ_add(&W[4],&Q[1]);  // P+Q 
+    ECP4_ZZZ_copy(&W[5],&W[4]);
+    ECP4_ZZZ_copy(&W[6],&W[4]);
+    ECP4_ZZZ_copy(&W[7],&W[4]);
+
+    ECP4_ZZZ_copy(&T,&Q[2]);
+    ECP4_ZZZ_sub(&T,&Q[3]);       // R-S 
+    ECP4_ZZZ_sub(&W[1],&T);
+    ECP4_ZZZ_add(&W[2],&T);
+    ECP4_ZZZ_sub(&W[5],&T);
+    ECP4_ZZZ_add(&W[6],&T);
+    ECP4_ZZZ_copy(&T,&Q[2]);
+    ECP4_ZZZ_add(&T,&Q[3]);      // R+S 
+    ECP4_ZZZ_sub(&W[0],&T);
+    ECP4_ZZZ_add(&W[3],&T);
+    ECP4_ZZZ_sub(&W[4],&T);
+    ECP4_ZZZ_add(&W[7],&T);
+
+
+// Use Frobenius 
+
+	for (i=0;i<8;i++)
+	{
+		ECP4_ZZZ_copy(&Z[i],&W[i]);
+		ECP4_ZZZ_frob(&Z[i],&X,4);
+	}
+
+    // if multiplier is even add 1 to multiplier, and add P to correction 
+    ECP4_ZZZ_inf(&C);
+
+    BIG_XXX_zero(mt);
+    for (i=0; i<8; i++)
+    {
+		pb=BIG_XXX_parity(t[i]);
+		BIG_XXX_inc(t[i],1-pb);
+		BIG_XXX_norm(t[i]);
+		ECP4_ZZZ_copy(&T,&C);
+		ECP4_ZZZ_add(&T,&Q[i]);
+		ECP4_ZZZ_cmove(&C,&T,1-pb);
+
+
+        BIG_XXX_add(mt,mt,t[i]);
+        BIG_XXX_norm(mt);
+    }
+
+    nb=1+BIG_XXX_nbits(mt);
+
+    // convert exponents to signed 1-bit windows 
+    for (j=0; j<nb; j++)
+    {
+        for (i=0; i<4; i++)
+        {
+            a[i]=BIG_XXX_lastbits(t[i],2)-2;
+            BIG_XXX_dec(t[i],a[i]);
+            BIG_XXX_norm(t[i]);
+            BIG_XXX_fshr(t[i],1);
+        }
+        w[j]=8*a[0]+4*a[1]+2*a[2]+a[3];
+    }
+    w[nb]=8*BIG_XXX_lastbits(t[0],2)+4*BIG_XXX_lastbits(t[1],2)+2*BIG_XXX_lastbits(t[2],2)+BIG_XXX_lastbits(t[3],2);
+
+
+    for (j=0; j<nb; j++)
+    {
+        for (i=0; i<4; i++)
+        {
+            a[i]=BIG_XXX_lastbits(t[i+4],2)-2;
+            BIG_XXX_dec(t[i+4],a[i]);
+            BIG_XXX_norm(t[i+4]);
+            BIG_XXX_fshr(t[i+4],1);
+        }
+        z[j]=8*a[0]+4*a[1]+2*a[2]+a[3];
+    }
+    z[nb]=8*BIG_XXX_lastbits(t[4],2)+4*BIG_XXX_lastbits(t[5],2)+2*BIG_XXX_lastbits(t[6],2)+BIG_XXX_lastbits(t[7],2);
+
+
+    ECP4_ZZZ_copy(P,&W[(w[nb]-1)/2]);
+	ECP4_ZZZ_add(P,&Z[(z[nb]-1)/2]);
+    for (i=nb-1; i>=0; i--)
+    {
+		ECP4_ZZZ_dbl(P);
+        ECP4_ZZZ_select(&T,W,w[i]);
+        ECP4_ZZZ_add(P,&T);
+        ECP4_ZZZ_select(&T,Z,z[i]);
+        ECP4_ZZZ_add(P,&T);
+    }
+    ECP4_ZZZ_sub(P,&C); // apply correction 
+	ECP4_ZZZ_reduce(P);
+}
+*/
+/* Map to hash value to point on G2 from random BIG_XXX */
+
+void ECP4_ZZZ_mapit(ECP4_ZZZ *Q,octet *W)
+{
+    BIG_XXX q,one,x,hv;
+    FP2_YYY X[3],T;
+	FP4_YYY X4,Y4;
+
+    ECP4_ZZZ xQ, x2Q, x3Q, x4Q;
+
+	BIG_XXX_fromBytes(hv,W->val);
+    BIG_XXX_rcopy(q,Modulus_YYY);
+    BIG_XXX_one(one);
+    BIG_XXX_mod(hv,q);
+
+    for (;;)
+    {
+        FP2_YYY_from_BIGs(&T,one,hv);  /*******/
+		FP4_YYY_from_FP2(&X4,&T);
+        if (ECP4_ZZZ_setx(Q,&X4)) break;
+        BIG_XXX_inc(hv,1);
+    }
+
+	ECP4_ZZZ_frob_constants(X);
+
+    BIG_XXX_rcopy(x,CURVE_Bnx_ZZZ);
+
+    // Efficient hash maps to G2 on BLS24 curves - Budroni, Pintore 
+	// Q -> x4Q -x3Q -Q + F(x3Q-x2Q) + F(F(x2Q-xQ)) + F(F(F(xQ-Q))) +F(F(F(F(2Q))))
+
+	ECP4_ZZZ_copy(&xQ,Q);
+	ECP4_ZZZ_mul(&xQ,x);
+	ECP4_ZZZ_copy(&x2Q,&xQ);
+	ECP4_ZZZ_mul(&x2Q,x);
+	ECP4_ZZZ_copy(&x3Q,&x2Q);
+	ECP4_ZZZ_mul(&x3Q,x);
+	ECP4_ZZZ_copy(&x4Q,&x3Q);
+	ECP4_ZZZ_mul(&x4Q,x);
+
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	ECP4_ZZZ_neg(&xQ);
+	ECP4_ZZZ_neg(&x3Q);
+#endif
+
+	ECP4_ZZZ_sub(&x4Q,&x3Q);
+	ECP4_ZZZ_sub(&x4Q,Q);
+
+	ECP4_ZZZ_sub(&x3Q,&x2Q);
+	ECP4_ZZZ_frob(&x3Q,X,1);
+
+	ECP4_ZZZ_sub(&x2Q,&xQ);
+	ECP4_ZZZ_frob(&x2Q,X,2);
+
+	ECP4_ZZZ_sub(&xQ,Q);
+	ECP4_ZZZ_frob(&xQ,X,3);
+
+	ECP4_ZZZ_dbl(Q);
+	ECP4_ZZZ_frob(Q,X,4);
+
+	ECP4_ZZZ_add(Q,&x4Q);
+	ECP4_ZZZ_add(Q,&x3Q);
+	ECP4_ZZZ_add(Q,&x2Q);
+	ECP4_ZZZ_add(Q,&xQ);
+
+	ECP4_ZZZ_affine(Q);
+
+}
+
+// ECP$ Get Group Generator
+
+void ECP4_ZZZ_generator(ECP4_ZZZ *G)
+{
+	BIG_XXX a,b;
+	FP2_YYY Aa,Bb;
+	FP4_YYY X,Y;
+
+	BIG_XXX_rcopy(a,CURVE_Pxaa_ZZZ);
+	BIG_XXX_rcopy(b,CURVE_Pxab_ZZZ);
+	FP2_YYY_from_BIGs(&Aa,a,b);
+
+	BIG_XXX_rcopy(a,CURVE_Pxba_ZZZ);
+	BIG_XXX_rcopy(b,CURVE_Pxbb_ZZZ);
+	FP2_YYY_from_BIGs(&Bb,a,b);
+
+	FP4_YYY_from_FP2s(&X,&Aa,&Bb);
+
+	BIG_XXX_rcopy(a,CURVE_Pyaa_ZZZ);
+	BIG_XXX_rcopy(b,CURVE_Pyab_ZZZ);
+	FP2_YYY_from_BIGs(&Aa,a,b);
+
+	BIG_XXX_rcopy(a,CURVE_Pyba_ZZZ);
+	BIG_XXX_rcopy(b,CURVE_Pybb_ZZZ);
+	FP2_YYY_from_BIGs(&Bb,a,b);
+
+	FP4_YYY_from_FP2s(&Y,&Aa,&Bb);
+
+	ECP4_ZZZ_set(G,&X,&Y);
+}
+
+
+// g++ -O2 ecp4_BLS24.cpp fp4_BLS24.cpp fp2_BLS24.cpp fp_BLS24.cpp big_XXX.cpp rand.cpp hash.cpp rom_field_BLS24.cpp rom_curve_BLS24.cpp oct.cpp -o ecp4_BLS24.exe
+/*
+int main()
+{
+	int i;
+	ECP4 G,P;
+	FP2 Aa,Bb,f;
+	FP4 X,Y;
+	BIG a,b,r,p;
+	char w[100];
+	octet W= {0,sizeof(w),w};
+
+	ECP4_ggg(&G);
+
+	BIG_rcopy(a,Fra);
+    BIG_rcopy(b,Frb);
+	FP2_from_BIGs(&f,a,b);
+
+	
+	if (G.inf) cout << "Failed to set - point not on curve" << endl;
+	else cout << "set success" << endl;
+
+	ECP4_output(&G);
+	ECP4_copy(&P,&G);
+
+	//ECP4_reduce(&G);
+	//ECP4_reduce(&P);
+
+	BIG_rcopy(r,CURVE_Order);
+	BIG_rcopy(p,Modulus);
+
+	BIG_output(r);
+	cout << endl;
+
+	ECP4_mul(&G,r);
+	ECP4_output(&G);
+	cout << endl;
+
+	ECP4_copy(&G,&P);
+
+	cout << "pG = ";
+	ECP4_mul(&G,p);
+	ECP4_output(&G);
+	cout << endl;
+
+	cout << "G^p= ";
+	ECP4_frob(&P,&f,1);
+	ECP4_output(&P);
+	cout << endl;
+
+
+	for (i=0;i<MODBYTES_XXX;i++)
+	{
+		W.val[i]=i+11;
+	}
+	W.len=MODBYTES_XXX;
+
+	printf("W= ");
+	OCT_output(&W);
+	printf("\n");
+
+	ECP4_mapit(&P,&W);
+
+	cout << "Hash to P= ";
+	ECP4_output(&P);
+	cout << endl;
+
+	ECP4_mul(&P,r);
+
+	cout << "rP= ";
+	ECP4_output(&P);
+	cout << endl;
+
+
+
+//	ECP4_dbl(&G);
+//	ECP4_output(&G);
+//	ECP4_reduce(&G);
+//	cout << endl;
+//	ECP4_add(&G,&P);
+//	ECP4_output(&G);
+//	cout << endl;
+
+
+	return 0;
+}
+*/
+
diff --git a/version3/c/ecp4.h b/version3/c/ecp4.h
new file mode 100644
index 0000000..8e022c9
--- /dev/null
+++ b/version3/c/ecp4.h
@@ -0,0 +1,232 @@
+#ifndef ECP4_ZZZ_H
+#define ECP4_ZZZ_H
+
+#include "fp4_YYY.h"
+#include "config_curve_ZZZ.h"
+
+
+/**
+	@brief ECP4 Structure - Elliptic Curve Point over quadratic extension field
+*/
+
+typedef struct
+{
+ //   int inf; /**< Infinity Flag */
+    FP4_YYY x;   /**< x-coordinate of point */
+    FP4_YYY y;   /**< y-coordinate of point */
+	FP4_YYY z;
+} ECP4_ZZZ;
+
+
+/* Curve Params - see rom.c */
+extern const int CURVE_A_ZZZ;		/**< Elliptic curve A parameter */
+extern const int CURVE_B_I_ZZZ;		/**< Elliptic curve B parameter */
+extern const BIG_XXX CURVE_B_ZZZ;     /**< Elliptic curve B parameter */
+extern const BIG_XXX CURVE_Order_ZZZ; /**< Elliptic curve group order */
+extern const BIG_XXX CURVE_Cof_ZZZ;   /**< Elliptic curve cofactor */
+extern const BIG_XXX CURVE_Bnx_ZZZ;   /**< Elliptic curve parameter */
+
+extern const BIG_XXX Fra_YYY; /**< real part of curve Frobenius Constant */
+extern const BIG_XXX Frb_YYY; /**< imaginary part of curve Frobenius Constant */
+
+/* Generator point on G1 */
+extern const BIG_XXX CURVE_Gx_ZZZ; /**< x-coordinate of generator point in group G1  */
+extern const BIG_XXX CURVE_Gy_ZZZ; /**< y-coordinate of generator point in group G1  */
+
+/* For Pairings only */
+
+/* Generator point on G2 */
+extern const BIG_XXX CURVE_Pxaa_ZZZ; /**< real part of x-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pxab_ZZZ; /**< imaginary part of x-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pxba_ZZZ; /**< real part of x-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pxbb_ZZZ; /**< imaginary part of x-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pyaa_ZZZ; /**< real part of y-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pyab_ZZZ; /**< imaginary part of y-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pyba_ZZZ; /**< real part of y-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pybb_ZZZ; /**< imaginary part of y-coordinate of generator point in group G2 */
+
+/* ECP4 E(FP4) prototypes */
+/**	@brief Tests for ECP4 point equal to infinity
+ *
+	@param P ECP4 point to be tested
+	@return 1 if infinity, else returns 0
+ */
+extern int ECP4_ZZZ_isinf(ECP4_ZZZ *P);
+/**	@brief Copy ECP4 point to another ECP4 point
+ *
+	@param P ECP4 instance, on exit = Q
+	@param Q ECP4 instance to be copied
+ */
+extern void ECP4_ZZZ_copy(ECP4_ZZZ *P,ECP4_ZZZ *Q);
+/**	@brief Set ECP4 to point-at-infinity
+ *
+	@param P ECP4 instance to be set to infinity
+ */
+extern void ECP4_ZZZ_inf(ECP4_ZZZ *P);
+/**	@brief Tests for equality of two ECP4s
+ *
+	@param P ECP4 instance to be compared
+	@param Q ECP4 instance to be compared
+	@return 1 if P=Q, else returns 0
+ */
+extern int ECP4_ZZZ_equals(ECP4_ZZZ *P,ECP4_ZZZ *Q);
+
+/**	@brief Converts an ECP4 point from Projective (x,y,z) coordinates to affine (x,y) coordinates
+ *
+	@param P ECP4 instance to be converted to affine form
+ */
+extern void ECP4_ZZZ_affine(ECP4_ZZZ *P);
+
+/**	@brief Extract x and y coordinates of an ECP4 point P
+ *
+	If x=y, returns only x
+	@param x FP4 on exit = x coordinate of point
+	@param y FP4 on exit = y coordinate of point (unless x=y)
+	@param P ECP4 instance (x,y)
+	@return -1 if P is point-at-infinity, else 0
+ */
+extern int ECP4_ZZZ_get(FP4_YYY *x,FP4_YYY *y,ECP4_ZZZ *P);
+/**	@brief Formats and outputs an ECP4 point to the console, converted to affine coordinates
+ *
+	@param P ECP4 instance to be printed
+ */
+extern void ECP4_ZZZ_output(ECP4_ZZZ *P);
+
+/**	@brief Formats and outputs an ECP4 point to an octet string
+ *
+	The octet string is created in the form x|y.
+	Convert the real and imaginary parts of the x and y coordinates to big-endian base 256 form.
+	@param S output octet string
+	@param P ECP4 instance to be converted to an octet string
+ */
+extern void ECP4_ZZZ_toOctet(octet *S,ECP4_ZZZ *P);
+/**	@brief Creates an ECP4 point from an octet string
+ *
+	The octet string is in the form x|y
+	The real and imaginary parts of the x and y coordinates are in big-endian base 256 form.
+	@param P ECP4 instance to be created from the octet string
+	@param S input octet string
+	return 1 if octet string corresponds to a point on the curve, else 0
+ */
+extern int ECP4_ZZZ_fromOctet(ECP4_ZZZ *P,octet *S);
+/**	@brief Calculate Right Hand Side of curve equation y^2=f(x)
+ *
+	Function f(x)=x^3+Ax+B
+	Used internally.
+	@param r FP4 value of f(x)
+	@param x FP4 instance
+ */
+extern void ECP4_ZZZ_rhs(FP4_YYY *r,FP4_YYY *x);
+/**	@brief Set ECP4 to point(x,y) given x and y
+ *
+	Point P set to infinity if no such point on the curve.
+	@param P ECP4 instance to be set (x,y)
+	@param x FP4 x coordinate of point
+	@param y FP4 y coordinate of point
+	@return 1 if point exists, else 0
+ */
+extern int ECP4_ZZZ_set(ECP4_ZZZ *P,FP4_YYY *x,FP4_YYY *y);
+/**	@brief Set ECP to point(x,[y]) given x
+ *
+	Point P set to infinity if no such point on the curve. Otherwise y coordinate is calculated from x.
+	@param P ECP instance to be set (x,[y])
+	@param x BIG x coordinate of point
+	@return 1 if point exists, else 0
+ */
+extern int ECP4_ZZZ_setx(ECP4_ZZZ *P,FP4_YYY *x);
+/**	@brief Negation of an ECP4 point
+ *
+	@param P ECP4 instance, on exit = -P
+ */
+extern void ECP4_ZZZ_neg(ECP4_ZZZ *P);
+
+/**	@brief Reduction of an ECP4 point
+ *
+	@param P ECP4 instance, on exit (x,y) are reduced wrt the modulus
+ */
+extern void ECP4_ZZZ_reduce(ECP4_ZZZ *P);
+
+
+/**	@brief Doubles an ECP4 instance P and returns slope
+ *
+	@param P ECP4 instance, on exit =2*P
+	@param lam FP4 instance, slope of line
+ */
+//extern int ECP4_ZZZ_sdbl(ECP4_ZZZ *P,FP4_YYY *lam);
+/**	@brief Adds ECP4 instance Q to ECP4 instance P and returns slope
+ *
+	@param P ECP4 instance, on exit =P+Q
+	@param Q ECP4 instance to be added to P
+	@param lam FP4 instance, slope of line
+ */
+//extern int ECP4_ZZZ_sadd(ECP4_ZZZ *P,ECP4_ZZZ *Q,FP4_YYY *lam);
+
+
+/**	@brief Doubles an ECP4 instance P
+ *
+	@param P ECP4 instance, on exit =2*P
+ */
+extern int ECP4_ZZZ_dbl(ECP4_ZZZ *P);
+/**	@brief Adds ECP4 instance Q to ECP4 instance P
+ *
+	@param P ECP4 instance, on exit =P+Q
+	@param Q ECP4 instance to be added to P
+ */
+extern int ECP4_ZZZ_add(ECP4_ZZZ *P,ECP4_ZZZ *Q);
+/**	@brief Subtracts ECP instance Q from ECP4 instance P
+ *
+	@param P ECP4 instance, on exit =P-Q
+	@param Q ECP4 instance to be subtracted from P
+ */
+extern void ECP4_ZZZ_sub(ECP4_ZZZ *P,ECP4_ZZZ *Q);
+/**	@brief Multiplies an ECP4 instance P by a BIG, side-channel resistant
+ *
+	Uses fixed sized windows.
+	@param P ECP4 instance, on exit =b*P
+	@param b BIG number multiplier
+
+ */
+extern void ECP4_ZZZ_mul(ECP4_ZZZ *P,BIG_XXX b);
+
+/**	@brief Calculates required Frobenius constants
+ *
+	Calculate Frobenius constants
+	@param F array of FP2 precalculated constants
+
+ */
+extern void ECP4_ZZZ_frob_constants(FP2_YYY F[3]);
+
+/**	@brief Multiplies an ECP4 instance P by the internal modulus p^n, using precalculated Frobenius constants
+ *
+	Fast point multiplication using Frobenius
+	@param P ECP4 instance, on exit = p^n*P
+	@param F array of FP2 precalculated Frobenius constant
+	@param n power of prime
+
+ */
+extern void ECP4_ZZZ_frob(ECP4_ZZZ *P,FP2_YYY F[3],int n);
+
+/**	@brief Calculates P=Sigma b[i]*Q[i] for i=0 to 7
+ *
+	@param P ECP4 instance, on exit = Sigma b[i]*Q[i] for i=0 to 7
+	@param Q ECP4 array of 4 points
+	@param b BIG array of 4 multipliers
+ */
+extern void ECP4_ZZZ_mul8(ECP4_ZZZ *P,ECP4_ZZZ *Q,BIG_XXX *b);
+
+
+/**	@brief Maps random BIG to curve point of correct order
+ *
+	@param P ECP4 instance of correct order
+	@param W OCTET byte array to be mapped
+ */
+extern void ECP4_ZZZ_mapit(ECP4_ZZZ *P,octet *w);
+
+/**	@brief Get Group Generator from ROM
+ *
+	@param G ECP4 instance
+ */
+extern void ECP4_ZZZ_generator(ECP4_ZZZ *G);
+
+
+#endif
\ No newline at end of file
diff --git a/version3/c/ecp8.c b/version3/c/ecp8.c
new file mode 100644
index 0000000..cb80fcf
--- /dev/null
+++ b/version3/c/ecp8.c
@@ -0,0 +1,1311 @@
+/*
+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.
+*/
+
+/* AMCL Weierstrass elliptic curve functions over FP2 */
+
+//#include <iostream>
+#include "ecp8_ZZZ.h"
+
+
+int ECP8_ZZZ_isinf(ECP8_ZZZ *P)
+{
+//	if (P->inf) return 1;
+	return (FP8_YYY_iszilch(&(P->x)) & FP8_YYY_iszilch(&(P->z)));
+}
+
+/* Set P=Q */
+void ECP8_ZZZ_copy(ECP8_ZZZ *P,ECP8_ZZZ *Q)
+{
+//    P->inf=Q->inf;
+    FP8_YYY_copy(&(P->x),&(Q->x));
+    FP8_YYY_copy(&(P->y),&(Q->y));
+    FP8_YYY_copy(&(P->z),&(Q->z));
+}
+
+/* set P to Infinity */
+void ECP8_ZZZ_inf(ECP8_ZZZ *P)
+{
+//    P->inf=1;
+    FP8_YYY_zero(&(P->x));
+    FP8_YYY_one(&(P->y));
+	FP8_YYY_zero(&(P->z));
+}
+
+/* Conditional move Q to P dependant on d */
+static void ECP8_ZZZ_cmove(ECP8_ZZZ *P,ECP8_ZZZ *Q,int d)
+{
+    FP8_YYY_cmove(&(P->x),&(Q->x),d);
+    FP8_YYY_cmove(&(P->y),&(Q->y),d);
+    FP8_YYY_cmove(&(P->z),&(Q->z),d);
+//    d=~(d-1);
+//    P->inf^=(P->inf^Q->inf)&d;
+}
+
+/* return 1 if b==c, no branching */
+static int teq(sign32 b,sign32 c)
+{
+    sign32 x=b^c;
+    x-=1;  // if x=0, x now -1
+    return (int)((x>>31)&1);
+}
+
+/* Constant time select from pre-computed table */
+static void ECP8_ZZZ_select(ECP8_ZZZ *P,ECP8_ZZZ W[],sign32 b)
+{
+    ECP8_ZZZ MP;
+    sign32 m=b>>31;
+    sign32 babs=(b^m)-m;
+
+    babs=(babs-1)/2;
+
+    ECP8_ZZZ_cmove(P,&W[0],teq(babs,0));  // conditional move
+    ECP8_ZZZ_cmove(P,&W[1],teq(babs,1));
+    ECP8_ZZZ_cmove(P,&W[2],teq(babs,2));
+    ECP8_ZZZ_cmove(P,&W[3],teq(babs,3));
+    ECP8_ZZZ_cmove(P,&W[4],teq(babs,4));
+    ECP8_ZZZ_cmove(P,&W[5],teq(babs,5));
+    ECP8_ZZZ_cmove(P,&W[6],teq(babs,6));
+    ECP8_ZZZ_cmove(P,&W[7],teq(babs,7));
+
+    ECP8_ZZZ_copy(&MP,P);
+    ECP8_ZZZ_neg(&MP);  // minus P
+    ECP8_ZZZ_cmove(P,&MP,(int)(m&1));
+}
+
+/* Make P affine (so z=1) */
+void ECP8_ZZZ_affine(ECP8_ZZZ *P)
+{
+    FP8_YYY one,iz;
+    if (ECP8_ZZZ_isinf(P)) return;
+
+    FP8_YYY_one(&one);
+    if (FP8_YYY_isunity(&(P->z)))
+    {
+        FP8_YYY_reduce(&(P->x));
+        FP8_YYY_reduce(&(P->y));
+        return;
+    }
+
+    FP8_YYY_inv(&iz,&(P->z));
+    FP8_YYY_mul(&(P->x),&(P->x),&iz);
+    FP8_YYY_mul(&(P->y),&(P->y),&iz);
+
+    FP8_YYY_reduce(&(P->x));
+    FP8_YYY_reduce(&(P->y));
+    FP8_YYY_copy(&(P->z),&one);
+}
+
+/* return 1 if P==Q, else 0 */
+/* SU= 312 */
+int ECP8_ZZZ_equals(ECP8_ZZZ *P,ECP8_ZZZ *Q)
+{
+    FP8_YYY a,b;
+//    if (ECP8_ZZZ_isinf(P) && ECP8_ZZZ_isinf(Q)) return 1;
+//    if (ECP8_ZZZ_isinf(P) || ECP8_ZZZ_isinf(Q)) return 0;
+
+    FP8_YYY_mul(&a,&(P->x),&(Q->z));
+    FP8_YYY_mul(&b,&(Q->x),&(P->z));
+    if (!FP8_YYY_equals(&a,&b)) return 0;
+
+    FP8_YYY_mul(&a,&(P->y),&(Q->z));
+    FP8_YYY_mul(&b,&(Q->y),&(P->z));
+    if (!FP8_YYY_equals(&a,&b)) return 0;
+    return 1;
+}
+
+/* extract x, y from point P */
+int ECP8_ZZZ_get(FP8_YYY *x,FP8_YYY *y,ECP8_ZZZ *P)
+{
+	ECP8_ZZZ W;
+	ECP8_ZZZ_copy(&W,P);
+	ECP8_ZZZ_affine(&W);
+    if (ECP8_ZZZ_isinf(&W)) return -1;
+	//ECP8_ZZZ_affine(P);
+    FP8_YYY_copy(y,&(W.y));
+    FP8_YYY_copy(x,&(W.x));
+    return 0;
+}
+
+/* Output point P */
+void ECP8_ZZZ_output(ECP8_ZZZ *P)
+{
+    FP8_YYY x,y;
+    if (ECP8_ZZZ_isinf(P))
+    {
+        printf("Infinity\n");
+        return;
+    }
+    ECP8_ZZZ_get(&x,&y,P);
+    printf("(");
+    FP8_YYY_output(&x);
+    printf(",");
+    FP8_YYY_output(&y);
+    printf(")\n");
+}
+
+/* Convert Q to octet string */
+void ECP8_ZZZ_toOctet(octet *W,ECP8_ZZZ *Q)
+{
+	BIG_XXX b;
+	FP8_YYY qx,qy;
+	FP4_YYY qa,qb;
+	FP2_YYY pa,pb;
+
+    ECP8_ZZZ_get(&qx,&qy,Q);
+
+	FP4_YYY_copy(&qa,&(qx.a));
+	FP4_YYY_copy(&qb,&(qx.b));
+
+	FP2_YYY_copy(&pa,&(qa.a));
+	FP2_YYY_copy(&pb,&(qa.b));
+
+	FP_YYY_redc(b,&(pa.a));
+    BIG_XXX_toBytes(&(W->val[0]),b);
+    FP_YYY_redc(b,&(pa.b));
+    BIG_XXX_toBytes(&(W->val[MODBYTES_XXX]),b);
+    FP_YYY_redc(b,&(pb.a));
+    BIG_XXX_toBytes(&(W->val[2*MODBYTES_XXX]),b);
+    FP_YYY_redc(b,&(pb.b));
+    BIG_XXX_toBytes(&(W->val[3*MODBYTES_XXX]),b);
+
+	FP2_YYY_copy(&pa,&(qb.a));
+	FP2_YYY_copy(&pb,&(qb.b));
+
+	FP_YYY_redc(b,&(pa.a));
+    BIG_XXX_toBytes(&(W->val[4*MODBYTES_XXX]),b);
+    FP_YYY_redc(b,&(pa.b));
+    BIG_XXX_toBytes(&(W->val[5*MODBYTES_XXX]),b);
+    FP_YYY_redc(b,&(pb.a));
+    BIG_XXX_toBytes(&(W->val[6*MODBYTES_XXX]),b);
+    FP_YYY_redc(b,&(pb.b));
+    BIG_XXX_toBytes(&(W->val[7*MODBYTES_XXX]),b);
+
+
+	FP4_YYY_copy(&qa,&(qy.a));
+	FP4_YYY_copy(&qb,&(qy.b));
+
+	FP2_YYY_copy(&pa,&(qa.a));
+	FP2_YYY_copy(&pb,&(qa.b));
+
+	FP_YYY_redc(b,&(pa.a));
+    BIG_XXX_toBytes(&(W->val[8*MODBYTES_XXX]),b);
+    FP_YYY_redc(b,&(pa.b));
+    BIG_XXX_toBytes(&(W->val[9*MODBYTES_XXX]),b);
+    FP_YYY_redc(b,&(pb.a));
+    BIG_XXX_toBytes(&(W->val[10*MODBYTES_XXX]),b);
+    FP_YYY_redc(b,&(pb.b));
+    BIG_XXX_toBytes(&(W->val[11*MODBYTES_XXX]),b);
+
+	FP2_YYY_copy(&pa,&(qb.a));
+	FP2_YYY_copy(&pb,&(qb.b));
+
+	FP_YYY_redc(b,&(pa.a));
+    BIG_XXX_toBytes(&(W->val[12*MODBYTES_XXX]),b);
+    FP_YYY_redc(b,&(pa.b));
+    BIG_XXX_toBytes(&(W->val[13*MODBYTES_XXX]),b);
+    FP_YYY_redc(b,&(pb.a));
+    BIG_XXX_toBytes(&(W->val[14*MODBYTES_XXX]),b);
+    FP_YYY_redc(b,&(pb.b));
+    BIG_XXX_toBytes(&(W->val[15*MODBYTES_XXX]),b);
+
+
+    W->len=16*MODBYTES_XXX;
+}
+
+/* restore Q from octet string */
+int ECP8_ZZZ_fromOctet(ECP8_ZZZ *Q,octet *W)
+{
+	BIG_XXX b;
+    FP8_YYY qx,qy;
+	FP4_YYY qa,qb;
+	FP2_YYY pa,pb;
+
+    BIG_XXX_fromBytes(b,&(W->val[0]));
+	FP_YYY_nres(&(pa.a),b);
+    BIG_XXX_fromBytes(b,&(W->val[MODBYTES_XXX]));
+    FP_YYY_nres(&(pa.b),b);
+    BIG_XXX_fromBytes(b,&(W->val[2*MODBYTES_XXX]));
+    FP_YYY_nres(&(pb.a),b);
+    BIG_XXX_fromBytes(b,&(W->val[3*MODBYTES_XXX]));
+    FP_YYY_nres(&(pb.b),b);
+
+	FP2_YYY_copy(&(qa.a),&pa);
+	FP2_YYY_copy(&(qa.b),&pb);
+
+    BIG_XXX_fromBytes(b,&(W->val[4*MODBYTES_XXX]));
+	FP_YYY_nres(&(pa.a),b);
+    BIG_XXX_fromBytes(b,&(W->val[5*MODBYTES_XXX]));
+    FP_YYY_nres(&(pa.b),b);
+    BIG_XXX_fromBytes(b,&(W->val[6*MODBYTES_XXX]));
+    FP_YYY_nres(&(pb.a),b);
+    BIG_XXX_fromBytes(b,&(W->val[7*MODBYTES_XXX]));
+    FP_YYY_nres(&(pb.b),b);
+
+	FP2_YYY_copy(&(qb.a),&pa);
+	FP2_YYY_copy(&(qb.b),&pb);
+
+	FP4_YYY_copy(&(qx.a),&qa);
+	FP4_YYY_copy(&(qx.b),&qb);
+
+
+    BIG_XXX_fromBytes(b,&(W->val[8*MODBYTES_XXX]));
+	FP_YYY_nres(&(pa.a),b);
+    BIG_XXX_fromBytes(b,&(W->val[9*MODBYTES_XXX]));
+    FP_YYY_nres(&(pa.b),b);
+    BIG_XXX_fromBytes(b,&(W->val[10*MODBYTES_XXX]));
+    FP_YYY_nres(&(pb.a),b);
+    BIG_XXX_fromBytes(b,&(W->val[11*MODBYTES_XXX]));
+    FP_YYY_nres(&(pb.b),b);
+
+	FP2_YYY_copy(&(qa.a),&pa);
+	FP2_YYY_copy(&(qa.b),&pb);
+
+    BIG_XXX_fromBytes(b,&(W->val[12*MODBYTES_XXX]));
+	FP_YYY_nres(&(pa.a),b);
+    BIG_XXX_fromBytes(b,&(W->val[13*MODBYTES_XXX]));
+    FP_YYY_nres(&(pa.b),b);
+    BIG_XXX_fromBytes(b,&(W->val[14*MODBYTES_XXX]));
+    FP_YYY_nres(&(pb.a),b);
+    BIG_XXX_fromBytes(b,&(W->val[15*MODBYTES_XXX]));
+    FP_YYY_nres(&(pb.b),b);
+
+	FP2_YYY_copy(&(qb.a),&pa);
+	FP2_YYY_copy(&(qb.b),&pb);
+
+	FP4_YYY_copy(&(qy.a),&qa);
+	FP4_YYY_copy(&(qy.b),&qb);
+
+
+    if (ECP8_ZZZ_set(Q,&qx,&qy)) return 1;
+    return 0;
+}
+
+/* Calculate RHS of twisted curve equation x^3+B/i or x^3+Bi*/
+void ECP8_ZZZ_rhs(FP8_YYY *rhs,FP8_YYY *x)
+{
+    /* calculate RHS of elliptic curve equation */
+    FP8_YYY t;
+	FP4_YYY t4;
+	FP2_YYY t2;
+    BIG_XXX b;
+    FP8_YYY_sqr(&t,x);
+
+    FP8_YYY_mul(rhs,&t,x);
+
+    /* Assuming CURVE_A=0 */
+
+    BIG_XXX_rcopy(b,CURVE_B_ZZZ);
+
+    FP2_YYY_from_BIG(&t2,b);
+	FP4_YYY_from_FP2(&t4,&t2);
+	FP8_YYY_from_FP4(&t,&t4);
+
+#if SEXTIC_TWIST_ZZZ == D_TYPE	
+    FP8_YYY_div_i(&t);   /* IMPORTANT - here we use the correct SEXTIC twist of the curve */
+#endif
+
+#if SEXTIC_TWIST_ZZZ == M_TYPE	
+    FP8_YYY_times_i(&t);   /* IMPORTANT - here we use the correct SEXTIC twist of the curve */
+#endif
+
+    FP8_YYY_add(rhs,&t,rhs);
+    FP8_YYY_reduce(rhs);
+}
+
+/* Set P=(x,y). Return 1 if (x,y) is on the curve, else return 0*/
+/* SU= 232 */
+int ECP8_ZZZ_set(ECP8_ZZZ *P,FP8_YYY *x,FP8_YYY *y)
+{
+    FP8_YYY rhs,y2;
+
+    FP8_YYY_sqr(&y2,y);
+    ECP8_ZZZ_rhs(&rhs,x);
+
+    if (!FP8_YYY_equals(&y2,&rhs))
+    {
+		ECP8_ZZZ_inf(P);
+      //  P->inf=1;
+        return 0;
+    }
+
+ //   P->inf=0;
+    FP8_YYY_copy(&(P->x),x);
+    FP8_YYY_copy(&(P->y),y);
+
+    FP8_YYY_one(&(P->z));
+    return 1;
+}
+
+/* Set P=(x,y). Return 1 if (x,.) is on the curve, else return 0 */
+/* SU= 232 */
+int ECP8_ZZZ_setx(ECP8_ZZZ *P,FP8_YYY *x)
+{
+    FP8_YYY y;
+    ECP8_ZZZ_rhs(&y,x);
+
+    if (!FP8_YYY_sqrt(&y,&y))
+    {
+		ECP8_ZZZ_inf(P);
+        return 0;
+    }
+
+ //   P->inf=0;
+    FP8_YYY_copy(&(P->x),x);
+    FP8_YYY_copy(&(P->y),&y);
+    FP8_YYY_one(&(P->z));
+    return 1;
+}
+
+/* Set P=-P */
+/* SU= 8 */
+void ECP8_ZZZ_neg(ECP8_ZZZ *P)
+{
+//	if (ECP8_ZZZ_isinf(P)) return;
+	FP8_YYY_norm(&(P->y));
+    FP8_YYY_neg(&(P->y),&(P->y));
+    FP8_YYY_norm(&(P->y));
+}
+
+
+
+/* R+=R */
+/* return -1 for Infinity, 0 for addition, 1 for doubling */
+int ECP8_ZZZ_dbl(ECP8_ZZZ *P)
+{
+    FP8_YYY t0,t1,t2,t3,iy,x3,y3;
+ //   if (P->inf) return -1;
+
+	FP8_YYY_copy(&iy,&(P->y));		//FP8_YYY iy=new FP8_YYY(y);
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+	FP8_YYY_times_i(&iy);			//iy.mul_ip(); 
+	//FP8_YYY_norm(&iy);				//iy.norm();
+#endif
+
+	FP8_YYY_sqr(&t0,&(P->y));			//t0.sqr();   
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+	FP8_YYY_times_i(&t0);			//t0.mul_ip(); 
+#endif
+
+	FP8_YYY_mul(&t1,&iy,&(P->z));	//t1.mul(z);
+	FP8_YYY_sqr(&t2,&(P->z));				//t2.sqr();
+
+	FP8_YYY_add(&(P->z),&t0,&t0);	//z.add(t0); 
+	FP8_YYY_norm(&(P->z));				//z.norm(); 
+	FP8_YYY_add(&(P->z),&(P->z),&(P->z));	//z.add(z); 
+	FP8_YYY_add(&(P->z),&(P->z),&(P->z));	//z.add(z); 
+	FP8_YYY_norm(&(P->z));			//z.norm();  
+
+	FP8_YYY_imul(&t2,&t2,3*CURVE_B_I_ZZZ);	//t2.imul(3*ROM.CURVE_B_I); 
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+	FP8_YYY_times_i(&t2);
+	//FP8_YYY_norm(&t2);
+#endif
+
+	FP8_YYY_mul(&x3,&t2,&(P->z));	//x3.mul(z); 
+
+	FP8_YYY_add(&y3,&t0,&t2);		//y3.add(t2); 
+	FP8_YYY_norm(&y3);				//y3.norm();
+	FP8_YYY_mul(&(P->z),&(P->z),&t1);	//z.mul(t1);
+
+	FP8_YYY_add(&t1,&t2,&t2);		//t1.add(t2); 
+	FP8_YYY_add(&t2,&t2,&t1);		//t2.add(t1); 
+	FP8_YYY_norm(&t2);				//t2.norm();  
+	FP8_YYY_sub(&t0,&t0,&t2);		//t0.sub(t2); 
+	FP8_YYY_norm(&t0);				//t0.norm();                           //y^2-9bz^2
+	FP8_YYY_mul(&y3,&y3,&t0);		//y3.mul(t0); 
+	FP8_YYY_add(&(P->y),&y3,&x3);		//y3.add(x3);                          //(y^2+3z*2)(y^2-9z^2)+3b.z^2.8y^2
+
+	FP8_YYY_mul(&t1,&(P->x),&iy);		//t1.mul(iy);						//
+
+	FP8_YYY_norm(&t0);			//x.norm(); 
+	FP8_YYY_mul(&(P->x),&t0,&t1);	//x.mul(t1); 
+	FP8_YYY_add(&(P->x),&(P->x),&(P->x));	//x.add(x);       //(y^2-9bz^2)xy2
+
+	FP8_YYY_norm(&(P->x));			//x.norm(); 
+
+	FP8_YYY_norm(&(P->y));			//y.norm();
+
+    return 1;
+}
+
+/* Set P+=Q */
+
+int ECP8_ZZZ_add(ECP8_ZZZ *P,ECP8_ZZZ *Q)
+{
+    FP8_YYY t0,t1,t2,t3,t4,x3,y3,z3;
+	int b3=3*CURVE_B_I_ZZZ;
+/*    if (Q->inf) return 0;
+    if (P->inf)
+    {
+        ECP8_ZZZ_copy(P,Q);
+        return 0;
+    }
+*/
+	FP8_YYY_mul(&t0,&(P->x),&(Q->x));	//t0.mul(Q.x);         // x.Q.x
+	FP8_YYY_mul(&t1,&(P->y),&(Q->y));	//t1.mul(Q.y);		 // y.Q.y
+
+	FP8_YYY_mul(&t2,&(P->z),&(Q->z));	//t2.mul(Q.z);
+	FP8_YYY_add(&t3,&(P->x),&(P->y));	//t3.add(y); 
+	FP8_YYY_norm(&t3);				//t3.norm();          //t3=X1+Y1         
+	FP8_YYY_add(&t4,&(Q->x),&(Q->y));	//t4.add(Q.y); 
+	FP8_YYY_norm(&t4);				//t4.norm();			//t4=X2+Y2
+	FP8_YYY_mul(&t3,&t3,&t4);		//t3.mul(t4);						//t3=(X1+Y1)(X2+Y2)
+	FP8_YYY_add(&t4,&t0,&t1);		//t4.add(t1);		//t4=X1.X2+Y1.Y2
+
+	FP8_YYY_sub(&t3,&t3,&t4);		//t3.sub(t4); 
+	FP8_YYY_norm(&t3);				//t3.norm(); 
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+	FP8_YYY_times_i(&t3);			//t3.mul_ip();  
+	//FP8_YYY_norm(&t3);				//t3.norm();         //t3=(X1+Y1)(X2+Y2)-(X1.X2+Y1.Y2) = X1.Y2+X2.Y1
+#endif
+                   
+	FP8_YYY_add(&t4,&(P->y),&(P->z));	//t4.add(z); 
+	FP8_YYY_norm(&t4);				//t4.norm();			//t4=Y1+Z1
+
+	FP8_YYY_add(&x3,&(Q->y),&(Q->z));	//x3.add(Q.z); 
+	FP8_YYY_norm(&x3);				//x3.norm();			//x3=Y2+Z2
+
+	FP8_YYY_mul(&t4,&t4,&x3);		//t4.mul(x3);						//t4=(Y1+Z1)(Y2+Z2)
+
+	FP8_YYY_add(&x3,&t1,&t2);		//x3.add(t2);						//X3=Y1.Y2+Z1.Z2
+	
+	FP8_YYY_sub(&t4,&t4,&x3);		//t4.sub(x3); 
+	FP8_YYY_norm(&t4);				//t4.norm(); 
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+	FP8_YYY_times_i(&t4);			//t4.mul_ip(); 
+	//FP8_YYY_norm(&t4);				//t4.norm();          //t4=(Y1+Z1)(Y2+Z2) - (Y1.Y2+Z1.Z2) = Y1.Z2+Y2.Z1
+#endif
+
+	FP8_YYY_add(&x3,&(P->x),&(P->z));	//x3.add(z); 
+	FP8_YYY_norm(&x3);				//x3.norm();	// x3=X1+Z1
+		
+	FP8_YYY_add(&y3,&(Q->x),&(Q->z));	//y3.add(Q.z); 
+	FP8_YYY_norm(&y3);				//y3.norm();				// y3=X2+Z2
+	FP8_YYY_mul(&x3,&x3,&y3);		//x3.mul(y3);							// x3=(X1+Z1)(X2+Z2)
+
+	FP8_YYY_add(&y3,&t0,&t2);		//y3.add(t2);							// y3=X1.X2+Z1+Z2
+	FP8_YYY_sub(&y3,&x3,&y3);		//y3.rsub(x3); 
+	FP8_YYY_norm(&y3);				//y3.norm();				// y3=(X1+Z1)(X2+Z2) - (X1.X2+Z1.Z2) = X1.Z2+X2.Z1
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+	FP8_YYY_times_i(&t0);			//t0.mul_ip(); 
+	//FP8_YYY_norm(&t0);				//t0.norm(); // x.Q.x
+	FP8_YYY_times_i(&t1);			//t1.mul_ip(); 
+	//FP8_YYY_norm(&t1);				//t1.norm(); // y.Q.y
+#endif
+
+	FP8_YYY_add(&x3,&t0,&t0);		//x3.add(t0); 
+	FP8_YYY_add(&t0,&t0,&x3);		//t0.add(x3); 
+	FP8_YYY_norm(&t0);				//t0.norm();
+	FP8_YYY_imul(&t2,&t2,b3);		//t2.imul(b); 	
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+	FP8_YYY_times_i(&t2);
+#endif
+
+	FP8_YYY_add(&z3,&t1,&t2);		//z3.add(t2); 
+	FP8_YYY_norm(&z3);				//z3.norm();
+	FP8_YYY_sub(&t1,&t1,&t2);		//t1.sub(t2); 
+	FP8_YYY_norm(&t1);				//t1.norm(); 
+	FP8_YYY_imul(&y3,&y3,b3);		//y3.imul(b); 
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+	FP8_YYY_times_i(&y3);
+	//FP8_YYY_norm(&y3);
+#endif
+
+	FP8_YYY_mul(&x3,&y3,&t4);		//x3.mul(t4); 
+
+	FP8_YYY_mul(&t2,&t3,&t1);		//t2.mul(t1); 
+	FP8_YYY_sub(&(P->x),&t2,&x3);		//x3.rsub(t2);
+	FP8_YYY_mul(&y3,&y3,&t0);		//y3.mul(t0); 
+	FP8_YYY_mul(&t1,&t1,&z3);		//t1.mul(z3); 
+	FP8_YYY_add(&(P->y),&y3,&t1);		//y3.add(t1);
+	FP8_YYY_mul(&t0,&t0,&t3);		//t0.mul(t3); 
+	FP8_YYY_mul(&z3,&z3,&t4);		//z3.mul(t4); 
+	FP8_YYY_add(&(P->z),&z3,&t0);		//z3.add(t0);
+
+
+	FP8_YYY_norm(&(P->x));			//x.norm(); 
+	FP8_YYY_norm(&(P->y));			//y.norm();
+	FP8_YYY_norm(&(P->z));			//z.norm();
+
+    return 0;
+}
+
+/* Set P-=Q */
+/* SU= 16 */
+void ECP8_ZZZ_sub(ECP8_ZZZ *P,ECP8_ZZZ *Q)
+{
+	ECP8_ZZZ NQ;
+	ECP8_ZZZ_copy(&NQ,Q);
+	ECP8_ZZZ_neg(&NQ);
+    //ECP8_ZZZ_neg(Q);
+    ECP8_ZZZ_add(P,&NQ);
+    //ECP8_ZZZ_neg(Q);
+}
+
+
+void ECP8_ZZZ_reduce(ECP8_ZZZ *P)
+{
+	FP8_YYY_reduce(&(P->x));
+	FP8_YYY_reduce(&(P->y));
+	FP8_YYY_reduce(&(P->z));
+}
+
+/* P*=e */
+/* SU= 280 */
+void ECP8_ZZZ_mul(ECP8_ZZZ *P,BIG_XXX e)
+{
+    /* fixed size windows */
+    int i,nb,s,ns;
+    BIG_XXX mt,t;
+    ECP8_ZZZ Q,W[8],C;
+    sign8 w[1+(NLEN_XXX*BASEBITS_XXX+3)/4];
+
+    if (ECP8_ZZZ_isinf(P)) return;
+    //ECP8_ZZZ_affine(P);
+    /* precompute table */
+
+    ECP8_ZZZ_copy(&Q,P);
+    ECP8_ZZZ_dbl(&Q);
+    ECP8_ZZZ_copy(&W[0],P);
+
+    for (i=1; i<8; i++)
+    {
+        ECP8_ZZZ_copy(&W[i],&W[i-1]);
+        ECP8_ZZZ_add(&W[i],&Q);
+    }
+
+    /* make exponent odd - add 2P if even, P if odd */
+    BIG_XXX_copy(t,e);
+    s=BIG_XXX_parity(t);
+    BIG_XXX_inc(t,1);
+    BIG_XXX_norm(t);
+    ns=BIG_XXX_parity(t);
+    BIG_XXX_copy(mt,t);
+    BIG_XXX_inc(mt,1);
+    BIG_XXX_norm(mt);
+    BIG_XXX_cmove(t,mt,s);
+    ECP8_ZZZ_cmove(&Q,P,ns);
+    ECP8_ZZZ_copy(&C,&Q);
+
+    nb=1+(BIG_XXX_nbits(t)+3)/4;
+
+    /* convert exponent to signed 4-bit window */
+    for (i=0; i<nb; i++)
+    {
+        w[i]=BIG_XXX_lastbits(t,5)-16;
+        BIG_XXX_dec(t,w[i]);
+        BIG_XXX_norm(t);
+        BIG_XXX_fshr(t,4);
+    }
+    w[nb]=BIG_XXX_lastbits(t,5);
+
+    ECP8_ZZZ_copy(P,&W[(w[nb]-1)/2]);
+    for (i=nb-1; i>=0; i--)
+    {
+        ECP8_ZZZ_select(&Q,W,w[i]);
+        ECP8_ZZZ_dbl(P);
+        ECP8_ZZZ_dbl(P);
+        ECP8_ZZZ_dbl(P);
+        ECP8_ZZZ_dbl(P);
+        ECP8_ZZZ_add(P,&Q);
+    }
+    ECP8_ZZZ_sub(P,&C); /* apply correction */
+	ECP8_ZZZ_affine(P);
+}
+
+void ECP8_ZZZ_frob_constants(FP2_YYY F[3])
+{
+    FP_YYY fx,fy;
+	FP2_YYY X;
+
+    FP_YYY_rcopy(&fx,Fra_YYY);
+    FP_YYY_rcopy(&fy,Frb_YYY);
+    FP2_YYY_from_FPs(&X,&fx,&fy);
+
+
+	FP2_YYY_sqr(&F[0],&X);			// FF=F^2=(1+i)^(p-19)/12
+	FP2_YYY_copy(&F[2],&F[0]);
+	FP2_YYY_mul_ip(&F[2]);			// W=(1+i)^12/12.(1+i)^(p-19)/12 = (1+i)^(p-7)/12
+	FP2_YYY_norm(&F[2]);
+	FP2_YYY_sqr(&F[1],&F[2]);
+	FP2_YYY_mul(&F[2],&F[2],&F[1]);	// W=(1+i)^(p-7)/4
+
+	FP2_YYY_mul_ip(&F[2]);			// W=(1+i)^4/4.W=(1+i)^(p-7)/4 = (1+i)^(p-3)/4
+	FP2_YYY_norm(&F[2]);
+
+	FP2_YYY_copy(&F[1],&X);
+
+#if SEXTIC_TWIST_ZZZ == M_TYPE	
+	FP2_YYY_mul_ip(&F[1]);		// (1+i)^24/24.(1+i)^(p-19)/24 = (1+i)^(p+5)/24
+	FP2_YYY_inv(&F[1],&F[1]);		// (1+i)^-(p+5)/24
+	FP2_YYY_sqr(&F[0],&F[1]);		// (1+i)^-(p+5)/12
+#endif
+
+
+	FP2_YYY_mul_ip(&F[0]);		// FF=(1+i)^(p-19)/12.(1+i)^12/12 = (1+i)^(p-7)/12					// FF=(1+i)^12/12.(1+i)^-(p+5)/12 = (1+i)^-(p-7)/12
+	FP2_YYY_norm(&F[0]);
+
+	FP2_YYY_mul(&F[1],&F[1],&F[0]);  // (1+i)^(p-7)/12 . (1+i)^(p-19)/24 = (1+i)^(p-11)/8				// (1+i)^-(p-7)/12 . (1+i)^-(p+5)/24 = (1+i)^-(p-3)/8
+
+}
+
+/* Calculates q^n.P using Frobenius constant X */
+void ECP8_ZZZ_frob(ECP8_ZZZ *P,FP2_YYY F[3],int n)
+{
+	int i;
+	FP8_YYY X,Y,Z;
+
+//    if (P->inf) return;
+
+	//ECP8_get(&X,&Y,P);		// F=(1+i)^(p-19)/24
+
+	FP8_YYY_copy(&X,&(P->x));
+	FP8_YYY_copy(&Y,&(P->y));
+	FP8_YYY_copy(&Z,&(P->z));
+
+	for (i=0;i<n;i++)
+	{
+		FP8_YYY_frob(&X,&F[2]);		// X^p		
+		FP8_YYY_qmul(&X,&X,&F[0]); 
+#if SEXTIC_TWIST_ZZZ == M_TYPE			
+		FP8_YYY_div_i2(&X);			// X^p.(1+i)^-(p-1)/12
+#endif
+#if SEXTIC_TWIST_ZZZ == D_TYPE			
+		FP8_YYY_times_i2(&X);		// X^p.(1+i)^(p-1)/12
+#endif
+
+		FP8_YYY_frob(&Y,&F[2]);		// Y^p
+		FP8_YYY_qmul(&Y,&Y,&F[1]); 
+#if SEXTIC_TWIST_ZZZ == M_TYPE		
+		FP8_YYY_div_i(&Y);			// Y^p.(1+i)^-(p-1)/8
+#endif
+#if SEXTIC_TWIST_ZZZ == D_TYPE
+		FP8_YYY_times_i2(&Y); FP8_YYY_times_i2(&Y); FP8_YYY_times_i(&Y);  // Y^p.(1+i)^(p-1)/8
+#endif
+		FP8_YYY_frob(&Z,&F[2]);
+	}
+
+	FP8_YYY_copy(&(P->x),&X);
+	FP8_YYY_copy(&(P->y),&Y);
+	FP8_YYY_copy(&(P->z),&Z);
+}
+
+/* Side channel attack secure */
+// Bos & Costello https://eprint.iacr.org/2013/458.pdf
+// Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
+
+void ECP8_ZZZ_mul16(ECP8_ZZZ *P,ECP8_ZZZ Q[16],BIG_XXX u[16])
+{
+    int i,j,k,nb,pb1,pb2,pb3,pb4,bt;
+	ECP8_ZZZ T1[8],T2[8],T3[8],T4[8],W;
+    BIG_XXX mt,t[16];
+    sign8 w1[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 s1[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 w2[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 s2[NLEN_XXX*BASEBITS_XXX+1];	
+    sign8 w3[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 s3[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 w4[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 s4[NLEN_XXX*BASEBITS_XXX+1];	
+
+	FP2_YYY X[3];
+	ECP8_ZZZ_frob_constants(X);
+
+    for (i=0; i<16; i++)
+	{
+        //ECP8_ZZZ_affine(&Q[i]);
+        BIG_XXX_copy(t[i],u[i]);
+	}
+// Precomputed table
+    ECP8_ZZZ_copy(&T1[0],&Q[0]); // Q[0]
+    ECP8_ZZZ_copy(&T1[1],&T1[0]);
+	ECP8_ZZZ_add(&T1[1],&Q[1]);	// Q[0]+Q[1]
+    ECP8_ZZZ_copy(&T1[2],&T1[0]);
+	ECP8_ZZZ_add(&T1[2],&Q[2]);	// Q[0]+Q[2]
+	ECP8_ZZZ_copy(&T1[3],&T1[1]);
+	ECP8_ZZZ_add(&T1[3],&Q[2]);	// Q[0]+Q[1]+Q[2]
+	ECP8_ZZZ_copy(&T1[4],&T1[0]);
+	ECP8_ZZZ_add(&T1[4],&Q[3]);  // Q[0]+Q[3]
+	ECP8_ZZZ_copy(&T1[5],&T1[1]);
+	ECP8_ZZZ_add(&T1[5],&Q[3]);	// Q[0]+Q[1]+Q[3]
+	ECP8_ZZZ_copy(&T1[6],&T1[2]);
+	ECP8_ZZZ_add(&T1[6],&Q[3]);	// Q[0]+Q[2]+Q[3]
+	ECP8_ZZZ_copy(&T1[7],&T1[3]);
+	ECP8_ZZZ_add(&T1[7],&Q[3]);	// Q[0]+Q[1]+Q[2]+Q[3]
+
+//  Use Frobenius 
+
+	for (i=0;i<8;i++)
+	{
+		ECP8_ZZZ_copy(&T2[i],&T1[i]);
+		ECP8_ZZZ_frob(&T2[i],X,4);
+
+		ECP8_ZZZ_copy(&T3[i],&T2[i]);
+		ECP8_ZZZ_frob(&T3[i],X,4);
+
+		ECP8_ZZZ_copy(&T4[i],&T3[i]);
+		ECP8_ZZZ_frob(&T4[i],X,4);
+	}
+
+// Make them odd
+	pb1=1-BIG_XXX_parity(t[0]);
+	BIG_XXX_inc(t[0],pb1);
+	BIG_XXX_norm(t[0]);
+
+	pb2=1-BIG_XXX_parity(t[4]);
+	BIG_XXX_inc(t[4],pb2);
+	BIG_XXX_norm(t[4]);
+
+	pb3=1-BIG_XXX_parity(t[8]);
+	BIG_XXX_inc(t[8],pb3);
+	BIG_XXX_norm(t[8]);
+
+	pb4=1-BIG_XXX_parity(t[12]);
+	BIG_XXX_inc(t[12],pb4);
+	BIG_XXX_norm(t[12]);
+
+// Number of bits
+    BIG_XXX_zero(mt);
+    for (i=0; i<16; i++)
+    {
+        BIG_XXX_or(mt,mt,t[i]);
+    }
+    nb=1+BIG_XXX_nbits(mt);
+
+// Sign pivot 
+	s1[nb-1]=1;
+	s2[nb-1]=1;
+	s3[nb-1]=1;
+	s4[nb-1]=1;
+	for (i=0;i<nb-1;i++)
+	{
+        BIG_XXX_fshr(t[0],1);
+		s1[i]=2*BIG_XXX_parity(t[0])-1;
+        BIG_XXX_fshr(t[4],1);
+		s2[i]=2*BIG_XXX_parity(t[4])-1;
+        BIG_XXX_fshr(t[8],1);
+		s3[i]=2*BIG_XXX_parity(t[8])-1;
+        BIG_XXX_fshr(t[12],1);
+		s4[i]=2*BIG_XXX_parity(t[12])-1;
+	}
+
+
+// Recoded exponents
+    for (i=0; i<nb; i++)
+    {
+		w1[i]=0;
+		k=1;
+		for (j=1; j<4; j++)
+		{
+			bt=s1[i]*BIG_XXX_parity(t[j]);
+			BIG_XXX_fshr(t[j],1);
+
+			BIG_XXX_dec(t[j],(bt>>1));
+			BIG_XXX_norm(t[j]);
+			w1[i]+=bt*k;
+			k*=2;
+        }
+
+		w2[i]=0;
+		k=1;
+		for (j=5; j<8; j++)
+		{
+			bt=s2[i]*BIG_XXX_parity(t[j]);
+			BIG_XXX_fshr(t[j],1);
+
+			BIG_XXX_dec(t[j],(bt>>1));
+			BIG_XXX_norm(t[j]);
+			w2[i]+=bt*k;
+			k*=2;
+        }
+
+		w3[i]=0;
+		k=1;
+		for (j=9; j<12; j++)
+		{
+			bt=s3[i]*BIG_XXX_parity(t[j]);
+			BIG_XXX_fshr(t[j],1);
+
+			BIG_XXX_dec(t[j],(bt>>1));
+			BIG_XXX_norm(t[j]);
+			w3[i]+=bt*k;
+			k*=2;
+        }
+
+		w4[i]=0;
+		k=1;
+		for (j=13; j<16; j++)
+		{
+			bt=s4[i]*BIG_XXX_parity(t[j]);
+			BIG_XXX_fshr(t[j],1);
+
+			BIG_XXX_dec(t[j],(bt>>1));
+			BIG_XXX_norm(t[j]);
+			w4[i]+=bt*k;
+			k*=2;
+        }
+    }	
+
+// Main loop
+	ECP8_ZZZ_select(P,T1,2*w1[nb-1]+1);
+	ECP8_ZZZ_select(&W,T2,2*w2[nb-1]+1);
+	ECP8_ZZZ_add(P,&W);
+	ECP8_ZZZ_select(&W,T3,2*w3[nb-1]+1);
+	ECP8_ZZZ_add(P,&W);
+	ECP8_ZZZ_select(&W,T4,2*w4[nb-1]+1);
+	ECP8_ZZZ_add(P,&W);
+
+    for (i=nb-2; i>=0; i--)
+    {
+        ECP8_ZZZ_dbl(P);
+        ECP8_ZZZ_select(&W,T1,2*w1[i]+s1[i]);
+        ECP8_ZZZ_add(P,&W);
+        ECP8_ZZZ_select(&W,T2,2*w2[i]+s2[i]);
+        ECP8_ZZZ_add(P,&W);
+        ECP8_ZZZ_select(&W,T3,2*w3[i]+s3[i]);
+        ECP8_ZZZ_add(P,&W);
+        ECP8_ZZZ_select(&W,T4,2*w4[i]+s4[i]);
+        ECP8_ZZZ_add(P,&W);
+    }
+
+// apply corrections
+	ECP8_ZZZ_copy(&W,P);   
+	ECP8_ZZZ_sub(&W,&Q[0]);
+	ECP8_ZZZ_cmove(P,&W,pb1);
+	ECP8_ZZZ_copy(&W,P);   
+	ECP8_ZZZ_sub(&W,&Q[4]);
+	ECP8_ZZZ_cmove(P,&W,pb2);
+
+	ECP8_ZZZ_copy(&W,P);   
+	ECP8_ZZZ_sub(&W,&Q[8]);
+	ECP8_ZZZ_cmove(P,&W,pb3);
+	ECP8_ZZZ_copy(&W,P);   
+	ECP8_ZZZ_sub(&W,&Q[12]);
+	ECP8_ZZZ_cmove(P,&W,pb4);
+	ECP8_ZZZ_affine(P);
+}
+
+/*
+void ECP8_ZZZ_mul16(ECP8_ZZZ *P,ECP8_ZZZ Q[16],BIG_XXX u[16])
+{
+    int i,j,a[4],nb,pb;
+    ECP8_ZZZ W[8],Z[8],WW[8],ZZ[8],T,C;
+    BIG_XXX mt,t[16];
+    sign8 w[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 z[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 ww[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 zz[NLEN_XXX*BASEBITS_XXX+1];
+
+    FP_YYY fx,fy;
+	FP2_YYY X;
+
+    FP_YYY_rcopy(&fx,Fra_YYY);
+    FP_YYY_rcopy(&fy,Frb_YYY);
+    FP2_YYY_from_FPs(&X,&fx,&fy);
+
+
+    for (i=0; i<16; i++)
+        BIG_XXX_copy(t[i],u[i]);
+
+    // precompute tables 
+
+// 12 add/subs 
+
+    ECP8_ZZZ_copy(&W[0],&Q[0]);
+    ECP8_ZZZ_sub(&W[0],&Q[1]);  // P-Q
+    ECP8_ZZZ_copy(&W[1],&W[0]);
+    ECP8_ZZZ_copy(&W[2],&W[0]);
+    ECP8_ZZZ_copy(&W[3],&W[0]);
+    ECP8_ZZZ_copy(&W[4],&Q[0]);
+    ECP8_ZZZ_add(&W[4],&Q[1]);  // P+Q 
+    ECP8_ZZZ_copy(&W[5],&W[4]);
+    ECP8_ZZZ_copy(&W[6],&W[4]);
+    ECP8_ZZZ_copy(&W[7],&W[4]);
+
+    ECP8_ZZZ_copy(&T,&Q[2]);
+    ECP8_ZZZ_sub(&T,&Q[3]);       // R-S 
+    ECP8_ZZZ_sub(&W[1],&T);
+    ECP8_ZZZ_add(&W[2],&T);
+    ECP8_ZZZ_sub(&W[5],&T);
+    ECP8_ZZZ_add(&W[6],&T);
+    ECP8_ZZZ_copy(&T,&Q[2]);
+    ECP8_ZZZ_add(&T,&Q[3]);      // R+S 
+    ECP8_ZZZ_sub(&W[0],&T);
+    ECP8_ZZZ_add(&W[3],&T);
+    ECP8_ZZZ_sub(&W[4],&T);
+    ECP8_ZZZ_add(&W[7],&T);
+
+
+// Use Frobenius 
+
+	for (i=0;i<8;i++)
+	{
+		ECP8_ZZZ_copy(&Z[i],&W[i]);
+		ECP8_ZZZ_frob(&Z[i],&X,4);
+	}
+
+	for (i=0;i<8;i++)
+	{
+		ECP8_ZZZ_copy(&WW[i],&Z[i]);
+		ECP8_ZZZ_frob(&WW[i],&X,4);
+	}
+
+	for (i=0;i<8;i++)
+	{
+		ECP8_ZZZ_copy(&ZZ[i],&WW[i]);
+		ECP8_ZZZ_frob(&ZZ[i],&X,4);
+	}
+
+    // if multiplier is even add 1 to multiplier, and add P to correction 
+    ECP8_ZZZ_inf(&C);
+
+    BIG_XXX_zero(mt);
+    for (i=0; i<16; i++)
+    {
+		pb=BIG_XXX_parity(t[i]);
+		BIG_XXX_inc(t[i],1-pb);
+		BIG_XXX_norm(t[i]);
+		ECP8_ZZZ_copy(&T,&C);
+		ECP8_ZZZ_add(&T,&Q[i]);
+		ECP8_ZZZ_cmove(&C,&T,1-pb);
+
+
+        BIG_XXX_add(mt,mt,t[i]);
+        BIG_XXX_norm(mt);
+    }
+
+    nb=1+BIG_XXX_nbits(mt);
+
+    // convert exponents to signed 1-bit windows 
+    for (j=0; j<nb; j++)
+    {
+        for (i=0; i<4; i++)
+        {
+            a[i]=BIG_XXX_lastbits(t[i],2)-2;
+            BIG_XXX_dec(t[i],a[i]);
+            BIG_XXX_norm(t[i]);
+            BIG_XXX_fshr(t[i],1);
+        }
+        w[j]=8*a[0]+4*a[1]+2*a[2]+a[3];
+    }
+    w[nb]=8*BIG_XXX_lastbits(t[0],2)+4*BIG_XXX_lastbits(t[1],2)+2*BIG_XXX_lastbits(t[2],2)+BIG_XXX_lastbits(t[3],2);
+
+
+    for (j=0; j<nb; j++)
+    {
+        for (i=0; i<4; i++)
+        {
+            a[i]=BIG_XXX_lastbits(t[i+4],2)-2;
+            BIG_XXX_dec(t[i+4],a[i]);
+            BIG_XXX_norm(t[i+4]);
+            BIG_XXX_fshr(t[i+4],1);
+        }
+        z[j]=8*a[0]+4*a[1]+2*a[2]+a[3];
+    }
+    z[nb]=8*BIG_XXX_lastbits(t[4],2)+4*BIG_XXX_lastbits(t[5],2)+2*BIG_XXX_lastbits(t[6],2)+BIG_XXX_lastbits(t[7],2);
+
+
+    for (j=0; j<nb; j++)
+    {
+        for (i=0; i<4; i++)
+        {
+            a[i]=BIG_XXX_lastbits(t[i+8],2)-2;
+            BIG_XXX_dec(t[i+8],a[i]);
+            BIG_XXX_norm(t[i+8]);
+            BIG_XXX_fshr(t[i+8],1);
+        }
+        ww[j]=8*a[0]+4*a[1]+2*a[2]+a[3];
+    }
+    ww[nb]=8*BIG_XXX_lastbits(t[8],2)+4*BIG_XXX_lastbits(t[9],2)+2*BIG_XXX_lastbits(t[10],2)+BIG_XXX_lastbits(t[11],2);
+
+    for (j=0; j<nb; j++)
+    {
+        for (i=0; i<4; i++)
+        {
+            a[i]=BIG_XXX_lastbits(t[i+12],2)-2;
+            BIG_XXX_dec(t[i+12],a[i]);
+            BIG_XXX_norm(t[i+12]);
+            BIG_XXX_fshr(t[i+12],1);
+        }
+        zz[j]=8*a[0]+4*a[1]+2*a[2]+a[3];
+    }
+    zz[nb]=8*BIG_XXX_lastbits(t[12],2)+4*BIG_XXX_lastbits(t[13],2)+2*BIG_XXX_lastbits(t[14],2)+BIG_XXX_lastbits(t[15],2);
+
+    ECP8_ZZZ_copy(P,&W[(w[nb]-1)/2]);
+	ECP8_ZZZ_add(P,&Z[(z[nb]-1)/2]);
+	ECP8_ZZZ_add(P,&WW[(ww[nb]-1)/2]);
+	ECP8_ZZZ_add(P,&ZZ[(zz[nb]-1)/2]);
+    for (i=nb-1; i>=0; i--)
+    {
+		ECP8_ZZZ_dbl(P);
+        ECP8_ZZZ_select(&T,W,w[i]);
+        ECP8_ZZZ_add(P,&T);
+        ECP8_ZZZ_select(&T,Z,z[i]);
+        ECP8_ZZZ_add(P,&T);
+        ECP8_ZZZ_select(&T,WW,ww[i]);
+        ECP8_ZZZ_add(P,&T);
+        ECP8_ZZZ_select(&T,ZZ,zz[i]);
+        ECP8_ZZZ_add(P,&T);
+
+    }
+    ECP8_ZZZ_sub(P,&C); // apply correction 
+	ECP8_ZZZ_reduce(P);
+}
+*/
+/* Map to hash value to point on G2 from random BIG_XXX */
+
+void ECP8_ZZZ_mapit(ECP8_ZZZ *Q,octet *W)
+{
+    BIG_XXX q,one,x,hv;
+	FP_YYY Fx,Fy;
+    FP2_YYY T,X[3];
+	FP4_YYY X4;
+	FP8_YYY X8;
+
+    ECP8_ZZZ xQ, x2Q, x3Q, x4Q , x5Q, x6Q, x7Q, x8Q;
+
+	BIG_XXX_fromBytes(hv,W->val);
+    BIG_XXX_rcopy(q,Modulus_YYY);
+    BIG_XXX_one(one);
+    BIG_XXX_mod(hv,q);
+
+    for (;;)
+    {
+        FP2_YYY_from_BIGs(&T,one,hv);  /*******/
+		FP4_YYY_from_FP2(&X4,&T);
+		FP8_YYY_from_FP4(&X8,&X4);
+        if (ECP8_ZZZ_setx(Q,&X8)) break;
+        BIG_XXX_inc(hv,1);
+    }
+
+	ECP8_ZZZ_frob_constants(X);
+
+    BIG_XXX_rcopy(x,CURVE_Bnx_ZZZ);
+
+    // Efficient hash maps to G2 on BLS48 curves - Budroni, Pintore 
+	// Q -> x8Q -x7Q -Q +  F(x7Q-x6Q) + F(F(x6Q-x5Q)) +F(F(F(x5Q-x4Q))) +F(F(F(F(x4Q-x3Q)))) + F(F(F(F(F(x3Q-x2Q))))) + F(F(F(F(F(F(x2Q-xQ)))))) + F(F(F(F(F(F(F(xQ-Q))))))) +F(F(F(F(F(F(F(F(2Q))))))))
+
+	ECP8_ZZZ_copy(&xQ,Q);
+	ECP8_ZZZ_mul(&xQ,x);
+	ECP8_ZZZ_copy(&x2Q,&xQ);
+	ECP8_ZZZ_mul(&x2Q,x);
+	ECP8_ZZZ_copy(&x3Q,&x2Q);
+	ECP8_ZZZ_mul(&x3Q,x);
+	ECP8_ZZZ_copy(&x4Q,&x3Q);
+
+	ECP8_ZZZ_mul(&x4Q,x);
+	ECP8_ZZZ_copy(&x5Q,&x4Q);
+	ECP8_ZZZ_mul(&x5Q,x);
+	ECP8_ZZZ_copy(&x6Q,&x5Q);
+	ECP8_ZZZ_mul(&x6Q,x);
+	ECP8_ZZZ_copy(&x7Q,&x6Q);
+	ECP8_ZZZ_mul(&x7Q,x);
+	ECP8_ZZZ_copy(&x8Q,&x7Q);
+	ECP8_ZZZ_mul(&x8Q,x);
+
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	ECP8_ZZZ_neg(&xQ);
+	ECP8_ZZZ_neg(&x3Q);
+	ECP8_ZZZ_neg(&x5Q);
+	ECP8_ZZZ_neg(&x7Q);
+#endif
+
+	ECP8_ZZZ_sub(&x8Q,&x7Q);
+	ECP8_ZZZ_sub(&x8Q,Q);
+
+	ECP8_ZZZ_sub(&x7Q,&x6Q);
+	ECP8_ZZZ_frob(&x7Q,X,1);
+
+	ECP8_ZZZ_sub(&x6Q,&x5Q);
+	ECP8_ZZZ_frob(&x6Q,X,2);
+	
+	ECP8_ZZZ_sub(&x5Q,&x4Q);
+	ECP8_ZZZ_frob(&x5Q,X,3);
+	
+	ECP8_ZZZ_sub(&x4Q,&x3Q);
+	ECP8_ZZZ_frob(&x4Q,X,4);
+
+	ECP8_ZZZ_sub(&x3Q,&x2Q);
+	ECP8_ZZZ_frob(&x3Q,X,5);
+
+	ECP8_ZZZ_sub(&x2Q,&xQ);
+	ECP8_ZZZ_frob(&x2Q,X,6);
+
+	ECP8_ZZZ_sub(&xQ,Q);
+	ECP8_ZZZ_frob(&xQ,X,7);
+
+	ECP8_ZZZ_dbl(Q);
+	ECP8_ZZZ_frob(Q,X,8);
+
+
+	ECP8_ZZZ_add(Q,&x8Q);
+	ECP8_ZZZ_add(Q,&x7Q);
+	ECP8_ZZZ_add(Q,&x6Q);
+	ECP8_ZZZ_add(Q,&x5Q);
+
+	ECP8_ZZZ_add(Q,&x4Q);
+	ECP8_ZZZ_add(Q,&x3Q);
+	ECP8_ZZZ_add(Q,&x2Q);
+	ECP8_ZZZ_add(Q,&xQ);
+
+	ECP8_ZZZ_affine(Q);
+
+}
+
+// ECP$ Get Group Generator
+
+void ECP8_ZZZ_generator(ECP8_ZZZ *G)
+{
+	BIG_XXX a,b;
+	FP2_YYY Aa,Bb;
+	FP4_YYY A,B;
+	FP8_YYY X,Y;
+
+	BIG_XXX_rcopy(a,CURVE_Pxaaa_ZZZ);
+	BIG_XXX_rcopy(b,CURVE_Pxaab_ZZZ);
+	FP2_YYY_from_BIGs(&Aa,a,b);
+
+	BIG_XXX_rcopy(a,CURVE_Pxaba_ZZZ);
+	BIG_XXX_rcopy(b,CURVE_Pxabb_ZZZ);
+	FP2_YYY_from_BIGs(&Bb,a,b);
+
+	FP4_YYY_from_FP2s(&A,&Aa,&Bb);
+
+	BIG_XXX_rcopy(a,CURVE_Pxbaa_ZZZ);
+	BIG_XXX_rcopy(b,CURVE_Pxbab_ZZZ);
+	FP2_YYY_from_BIGs(&Aa,a,b);
+
+	BIG_XXX_rcopy(a,CURVE_Pxbba_ZZZ);
+	BIG_XXX_rcopy(b,CURVE_Pxbbb_ZZZ);
+	FP2_YYY_from_BIGs(&Bb,a,b);
+
+	FP4_YYY_from_FP2s(&B,&Aa,&Bb);
+
+	FP8_YYY_from_FP4s(&X,&A,&B);
+
+	BIG_XXX_rcopy(a,CURVE_Pyaaa_ZZZ);
+	BIG_XXX_rcopy(b,CURVE_Pyaab_ZZZ);
+	FP2_YYY_from_BIGs(&Aa,a,b);
+
+	BIG_XXX_rcopy(a,CURVE_Pyaba_ZZZ);
+	BIG_XXX_rcopy(b,CURVE_Pyabb_ZZZ);
+	FP2_YYY_from_BIGs(&Bb,a,b);
+
+	FP4_YYY_from_FP2s(&A,&Aa,&Bb);
+
+	BIG_XXX_rcopy(a,CURVE_Pybaa_ZZZ);
+	BIG_XXX_rcopy(b,CURVE_Pybab_ZZZ);
+	FP2_YYY_from_BIGs(&Aa,a,b);
+
+	BIG_XXX_rcopy(a,CURVE_Pybba_ZZZ);
+	BIG_XXX_rcopy(b,CURVE_Pybbb_ZZZ);
+	FP2_YYY_from_BIGs(&Bb,a,b);
+
+	FP4_YYY_from_FP2s(&B,&Aa,&Bb);
+
+	FP8_YYY_from_FP4s(&Y,&A,&B);
+
+	ECP8_ZZZ_set(G,&X,&Y);
+}
+
+
+// g++ -O2 ecp8_BLS48.cpp fp8_BLS48.cpp fp4_BLS48.cpp fp2_BLS48.cpp fp_BLS48.cpp big_B560_29.cpp rand.cpp hash.cpp rom_field_BLS48.cpp rom_curve_BLS48.cpp oct.cpp -o ecp8_BLS48.exe
+/*
+int main()
+{
+	int i;
+	ECP8 G,P;
+	FP2 Aa,Bb,f;
+	FP8_YYY X,Y;
+	BIG a,b,r,p;
+	char w[100];
+	octet W= {0,sizeof(w),w};
+
+	ECP8_generator(&G);
+
+	BIG_rcopy(a,Fra_YYY);
+    BIG_rcopy(b,Frb_YYY);
+	FP2_from_BIGs(&f,a,b);
+
+	if (G.inf) cout << "Failed to set - point not on curve" << endl;
+	else cout << "set success" << endl;
+
+	ECP8_output(&G);
+	ECP8_copy(&P,&G);
+
+	BIG_rcopy(r,CURVE_Order);
+	BIG_rcopy(p,Modulus);
+
+	BIG_output(r);
+	cout << endl;
+
+	ECP8_mul(&G,r);
+	ECP8_output(&G);
+	cout << endl;
+
+	ECP8_copy(&G,&P);
+
+	cout << "pG = ";
+	ECP8_mul(&G,p);
+	ECP8_output(&G);
+	cout << endl;
+
+	cout << "G^p= ";
+	ECP8_frob(&P,&f,1);
+	ECP8_output(&P);
+	cout << endl;
+
+
+	for (i=0;i<MODBYTES_XXX;i++)
+	{
+		W.val[i]=i+11;
+	}
+	W.len=MODBYTES_XXX;
+
+	printf("W= ");
+	OCT_output(&W);
+	printf("\n");
+
+	ECP8_mapit(&P,&W);
+
+	cout << "Hash to P= ";
+	ECP8_output(&P);
+	cout << endl;
+
+	ECP8_mul(&P,r);
+
+	cout << "rP= ";
+	ECP8_output(&P);
+	cout << endl;
+
+
+
+//	ECP8_dbl(&G);
+//	ECP8_output(&G);
+//	ECP8_reduce(&G);
+//	cout << endl;
+//	ECP8_add(&G,&P);
+//	ECP8_output(&G);
+//	cout << endl;
+
+
+	return 0;
+}
+*/
+
diff --git a/version3/c/ecp8.h b/version3/c/ecp8.h
new file mode 100644
index 0000000..13aff45
--- /dev/null
+++ b/version3/c/ecp8.h
@@ -0,0 +1,246 @@
+#ifndef ECP8_ZZZ_H
+#define ECP8_ZZZ_H
+
+#include "fp8_YYY.h"
+#include "config_curve_ZZZ.h"
+
+
+extern const BIG_XXX Fra_YYY; /**< real part of BN curve Frobenius Constant */
+extern const BIG_XXX Frb_YYY; /**< imaginary part of BN curve Frobenius Constant */
+
+
+/**
+	@brief ECP8 Structure - Elliptic Curve Point over quadratic extension field
+*/
+
+typedef struct
+{
+//    int inf; /**< Infinity Flag */
+    FP8_YYY x;   /**< x-coordinate of point */
+    FP8_YYY y;   /**< y-coordinate of point */
+	FP8_YYY z;	/**< z-coordinate of point */
+} ECP8_ZZZ;
+
+
+/* Curve Params - see rom.c */
+extern const int CURVE_A_ZZZ;		/**< Elliptic curve A parameter */
+extern const int CURVE_B_I_ZZZ;		/**< Elliptic curve B parameter */
+extern const BIG_XXX CURVE_B_ZZZ;     /**< Elliptic curve B parameter */
+extern const BIG_XXX CURVE_Order_ZZZ; /**< Elliptic curve group order */
+extern const BIG_XXX CURVE_Cof_ZZZ;   /**< Elliptic curve cofactor */
+extern const BIG_XXX CURVE_Bnx_ZZZ;   /**< Elliptic curve parameter */
+
+
+/* Generator point on G1 */
+extern const BIG_XXX CURVE_Gx; /**< x-coordinate of generator point in group G1  */
+extern const BIG_XXX CURVE_Gy; /**< y-coordinate of generator point in group G1  */
+
+/* For Pairings only */
+
+/* Generator point on G2 */
+extern const BIG_XXX CURVE_Pxaaa_ZZZ; /**< real part of x-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pxaab_ZZZ; /**< imaginary part of x-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pxaba_ZZZ; /**< real part of x-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pxabb_ZZZ; /**< imaginary part of x-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pxbaa_ZZZ; /**< real part of x-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pxbab_ZZZ; /**< imaginary part of x-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pxbba_ZZZ; /**< real part of x-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pxbbb_ZZZ; /**< imaginary part of x-coordinate of generator point in group G2 */
+
+extern const BIG_XXX CURVE_Pyaaa_ZZZ; /**< real part of y-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pyaab_ZZZ; /**< imaginary part of y-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pyaba_ZZZ; /**< real part of y-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pyabb_ZZZ; /**< imaginary part of y-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pybaa_ZZZ; /**< real part of y-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pybab_ZZZ; /**< imaginary part of y-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pybba_ZZZ; /**< real part of y-coordinate of generator point in group G2 */
+extern const BIG_XXX CURVE_Pybbb_ZZZ; /**< imaginary part of y-coordinate of generator point in group G2 */
+
+
+/* ECP8 E(FP8) prototypes */
+/**	@brief Tests for ECP8 point equal to infinity
+ *
+	@param P ECP8 point to be tested
+	@return 1 if infinity, else returns 0
+ */
+extern int ECP8_ZZZ_isinf(ECP8_ZZZ *P);
+/**	@brief Copy ECP8 point to another ECP8 point
+ *
+	@param P ECP8 instance, on exit = Q
+	@param Q ECP8 instance to be copied
+ */
+extern void ECP8_ZZZ_copy(ECP8_ZZZ *P,ECP8_ZZZ *Q);
+/**	@brief Set ECP8 to point-at-infinity
+ *
+	@param P ECP8 instance to be set to infinity
+ */
+extern void ECP8_ZZZ_inf(ECP8_ZZZ *P);
+/**	@brief Tests for equality of two ECP8s
+ *
+	@param P ECP8 instance to be compared
+	@param Q ECP8 instance to be compared
+	@return 1 if P=Q, else returns 0
+ */
+extern int ECP8_ZZZ_equals(ECP8_ZZZ *P,ECP8_ZZZ *Q);
+
+
+/**	@brief Converts an ECP8 point from Projective (x,y,z) coordinates to affine (x,y) coordinates
+ *
+	@param P ECP8 instance to be converted to affine form
+ */
+extern void ECP8_ZZZ_affine(ECP8_ZZZ *P);
+
+
+/**	@brief Extract x and y coordinates of an ECP8 point P
+ *
+	If x=y, returns only x
+	@param x FP8 on exit = x coordinate of point
+	@param y FP8 on exit = y coordinate of point (unless x=y)
+	@param P ECP8 instance (x,y)
+	@return -1 if P is point-at-infinity, else 0
+ */
+extern int ECP8_ZZZ_get(FP8_YYY *x,FP8_YYY *y,ECP8_ZZZ *P);
+/**	@brief Formats and outputs an ECP8 point to the console, converted to affine coordinates
+ *
+	@param P ECP8 instance to be printed
+ */
+extern void ECP8_ZZZ_output(ECP8_ZZZ *P);
+
+/**	@brief Formats and outputs an ECP8 point to an octet string
+ *
+	The octet string is created in the form x|y.
+	Convert the real and imaginary parts of the x and y coordinates to big-endian base 256 form.
+	@param S output octet string
+	@param P ECP8 instance to be converted to an octet string
+ */
+extern void ECP8_ZZZ_toOctet(octet *S,ECP8_ZZZ *P);
+/**	@brief Creates an ECP8 point from an octet string
+ *
+	The octet string is in the form x|y
+	The real and imaginary parts of the x and y coordinates are in big-endian base 256 form.
+	@param P ECP8 instance to be created from the octet string
+	@param S input octet string
+	return 1 if octet string corresponds to a point on the curve, else 0
+ */
+extern int ECP8_ZZZ_fromOctet(ECP8_ZZZ *P,octet *S);
+/**	@brief Calculate Right Hand Side of curve equation y^2=f(x)
+ *
+	Function f(x)=x^3+Ax+B
+	Used internally.
+	@param r FP8 value of f(x)
+	@param x FP8 instance
+ */
+extern void ECP8_ZZZ_rhs(FP8_YYY *r,FP8_YYY *x);
+/**	@brief Set ECP8 to point(x,y) given x and y
+ *
+	Point P set to infinity if no such point on the curve.
+	@param P ECP8 instance to be set (x,y)
+	@param x FP8 x coordinate of point
+	@param y FP8 y coordinate of point
+	@return 1 if point exists, else 0
+ */
+extern int ECP8_ZZZ_set(ECP8_ZZZ *P,FP8_YYY *x,FP8_YYY *y);
+/**	@brief Set ECP to point(x,[y]) given x
+ *
+	Point P set to infinity if no such point on the curve. Otherwise y coordinate is calculated from x.
+	@param P ECP instance to be set (x,[y])
+	@param x BIG x coordinate of point
+	@return 1 if point exists, else 0
+ */
+extern int ECP8_ZZZ_setx(ECP8_ZZZ *P,FP8_YYY *x);
+/**	@brief Negation of an ECP8 point
+ *
+	@param P ECP8 instance, on exit = -P
+ */
+extern void ECP8_ZZZ_neg(ECP8_ZZZ *P);
+
+/**	@brief Reduction of an ECP8 point
+ *
+	@param P ECP8 instance, on exit (x,y) are reduced wrt the modulus
+ */
+extern void ECP8_ZZZ_reduce(ECP8_ZZZ *P);
+
+
+/**	@brief Doubles an ECP8 instance P and returns slope
+ *
+	@param P ECP8 instance, on exit =2*P
+	@param lam FP8 instance, slope of line
+ */
+//extern int ECP8_ZZZ_sdbl(ECP8_ZZZ *P,FP8_YYY *lam);
+/**	@brief Adds ECP8 instance Q to ECP8 instance P and returns slope
+ *
+	@param P ECP8 instance, on exit =P+Q
+	@param Q ECP8 instance to be added to P
+	@param lam FP8 instance, slope of line
+ */
+//extern int ECP8_ZZZ_sadd(ECP8_ZZZ *P,ECP8_ZZZ *Q,FP8_YYY *lam);
+
+
+/**	@brief Doubles an ECP8 instance P
+ *
+	@param P ECP8 instance, on exit =2*P
+ */
+extern int ECP8_ZZZ_dbl(ECP8_ZZZ *P);
+/**	@brief Adds ECP8 instance Q to ECP8 instance P
+ *
+	@param P ECP8 instance, on exit =P+Q
+	@param Q ECP8 instance to be added to P
+ */
+extern int ECP8_ZZZ_add(ECP8_ZZZ *P,ECP8_ZZZ *Q);
+/**	@brief Subtracts ECP instance Q from ECP8 instance P
+ *
+	@param P ECP8 instance, on exit =P-Q
+	@param Q ECP8 instance to be subtracted from P
+ */
+extern void ECP8_ZZZ_sub(ECP8_ZZZ *P,ECP8_ZZZ *Q);
+/**	@brief Multiplies an ECP8 instance P by a BIG, side-channel resistant
+ *
+	Uses fixed sized windows.
+	@param P ECP8 instance, on exit =b*P
+	@param b BIG number multiplier
+
+ */
+extern void ECP8_ZZZ_mul(ECP8_ZZZ *P,BIG_XXX b);
+
+/**	@brief Calculates required Frobenius constants
+ *
+	Calculate Frobenius constants
+	@param F array of FP2 precalculated constants
+
+ */
+extern void ECP8_ZZZ_frob_constants(FP2_YYY F[3]);
+
+/**	@brief Multiplies an ECP8 instance P by the internal modulus p^n, using precalculated Frobenius constants
+ *
+	Fast point multiplication using Frobenius
+	@param P ECP8 instance, on exit = p^n*P
+	@param F array of FP2 precalculated Frobenius constant
+	@param n power of prime
+
+ */
+extern void ECP8_ZZZ_frob(ECP8_ZZZ *P,FP2_YYY F[3],int n);
+
+/**	@brief Calculates P=Sigma b[i]*Q[i] for i=0 to 7
+ *
+	@param P ECP8 instance, on exit = Sigma b[i]*Q[i] for i=0 to 7
+	@param Q ECP8 array of 4 points
+	@param b BIG array of 4 multipliers
+ */
+extern void ECP8_ZZZ_mul16(ECP8_ZZZ *P,ECP8_ZZZ *Q,BIG_XXX *b);
+
+
+/**	@brief Maps random BIG to curve point of correct order
+ *
+	@param P ECP8 instance of correct order
+	@param W OCTET byte array to be mapped
+ */
+extern void ECP8_ZZZ_mapit(ECP8_ZZZ *P,octet *w);
+
+/**	@brief Get Group Generator from ROM
+ *
+	@param G ECP8 instance
+ */
+extern void ECP8_ZZZ_generator(ECP8_ZZZ *G);
+
+
+#endif
\ No newline at end of file
diff --git a/version3/c/faster.c b/version3/c/faster.c
new file mode 100644
index 0000000..6d8bbf5
--- /dev/null
+++ b/version3/c/faster.c
@@ -0,0 +1,97 @@
+
+#include <stdio.h>
+#include "big_XXX.h"
+
+#ifdef COMBA
+
+int main()
+{
+	int i,j,k,N;
+
+	N=NLEN_XXX;
+
+
+	printf("Insert this code in BIG_XXX_mul() in file big_XXX.c between #define UNWOUND and #else \n\n");
+
+	for (i=0;i<N;i++)
+		printf("\td[%d]=(dchunk)a[%d]*b[%d];\n",i,i,i);
+
+	printf("\n\ts=d[0];\n\tt = s; c[0]=(chunk)t&BMASK_XXX; co=t>>BASEBITS_XXX;\n");
+
+	for (k=1;k<N;k++)
+	{
+		printf("\ts+=d[%d]; t=co+s ",k);
+		for (i=k;i>=1+k/2;i--)
+			printf("+(dchunk)(a[%d]-a[%d])*(b[%d]-b[%d])",i,k-i,k-i,i);
+		printf("; c[%d]=(chunk)t&BMASK_XXX; co=t>>BASEBITS_XXX; \n",k);
+	}
+	printf("\n");
+	for (k=N;k<2*N-1;k++)
+	{
+		printf("\ts-=d[%d]; t=co+s ",k-N);
+		for (i=N-1;i>=1+k/2;i--)
+			printf("+(dchunk)(a[%d]-a[%d])*(b[%d]-b[%d])",i,k-i,k-i,i);
+		printf("; c[%d]=(chunk)t&BMASK_XXX; co=t>>BASEBITS_XXX; \n",k);
+	}
+	printf("\tc[%d]=(chunk)co;\n",2*N-1);
+
+
+
+	printf("\nInsert this code in BIG_XXX_sqr() in file big_XXX.c between #define UNWOUND and #else \n\n");
+
+	printf("\n\tt=(dchunk)a[0]*a[0]; c[0]=(chunk)t&BMASK_XXX; co=t>>BASEBITS_XXX;\n");
+
+	for (k=1;k<N;k++)
+	{
+		printf("\tt= ",k);
+		for (i=k;i>=1+k/2;i--)
+			printf("+(dchunk)a[%d]*a[%d]",i,k-i);
+		printf("; t+=t; t+=co;");
+		if (k%2==0) printf(" t+=(dchunk)a[%d]*a[%d];",k/2,k/2);
+		printf(" c[%d]=(chunk)t&BMASK_XXX; co=t>>BASEBITS_XXX; \n", k);
+	}
+	printf("\n");
+
+	for (k=N;k<2*N-2;k++)
+	{
+		printf("\tt= ",k-N);
+		for (i=N-1;i>=1+k/2;i--)
+			printf("+(dchunk)a[%d]*a[%d]",i,k-i);
+		printf("; t+=t; t+=co;");
+		if (k%2==0) printf(" t+=(dchunk)a[%d]*a[%d];",k/2,k/2);
+		printf(" c[%d]=(chunk)t&BMASK_XXX; co=t>>BASEBITS_XXX; \n", k);
+	}
+	printf("\tt=co; t+=(dchunk)a[%d]*a[%d]; c[%d]=(chunk)t&BMASK_XXX; co=t>>BASEBITS_XXX; \n ",N-1,N-1,2*N-2);
+
+	printf("\tc[%d]=(chunk)co;\n",2*N-1);
+
+
+
+
+	printf("\nInsert this code in BIG_XXX_monty() in file big_XXX.c between #define UNWOUND and #else \n\n");
+
+	printf("\tt=d[0]; v[0]=((chunk)t*MC)&BMASK_XXX; t+=(dchunk)v[0]*md[0];  s=0; c=(t>>BASEBITS_XXX);\n\n");
+
+	for (k=1;k<N;k++)
+	{
+		printf("\tt=d[%d]+c+s+(dchunk)v[0]*md[%d]",k,k);
+		for (i=k-1;i>k/2;i--) printf("+(dchunk)(v[%d]-v[%d])*(md[%d]-md[%d])",k-i,i,i,k-i);
+		printf("; v[%d]=((chunk)t*MC)&BMASK_XXX; t+=(dchunk)v[%d]*md[0]; ",k,k);
+		printf(" dd[%d]=(dchunk)v[%d]*md[%d]; s+=dd[%d]; c=(t>>BASEBITS_XXX); \n",k,k,k,k);
+	}
+	printf("\n");
+	for (k=N;k<2*N-1;k++)
+	{
+		printf("\tt=d[%d]+c+s",k);
+		for (i=N-1;i>=1+k/2;i--) printf("+(dchunk)(v[%d]-v[%d])*(md[%d]-md[%d])",k-i,i,i,k-i);
+		printf("; a[%d]=(chunk)t&BMASK_XXX;  s-=dd[%d]; c=(t>>BASEBITS_XXX); \n",k-N,k-N+1);
+	}
+	printf("\ta[%d]=d[%d]+(chunk)c&BMASK_XXX;\n",N-1,2*N-1);	
+
+
+
+}
+
+#endif
+
+
diff --git a/version3/c/faster.txt b/version3/c/faster.txt
new file mode 100644
index 0000000..c6e948c
--- /dev/null
+++ b/version3/c/faster.txt
@@ -0,0 +1,29 @@
+We assume than optimizing compilers will unwind loops at every opportunity. 
+
+But sometimes they don't. So time-critical code will run faster if we step
+in and unwind complex loops for the compiler.
+
+Once the architecture and ECC/RSA support is decided upon choose 
+which BIG numbers need to be optimized. So for example for a 32-bit build and
+if using 256 bit BIGs and a base of 2^29, replace XXX with 256_29 inside 
+faster.c
+
+Then compile and execute the program faster.c like this (using MinGW 
+port of GCC as an example), in the same directory as arch.h and big_256_29.h
+
+gcc -O2 -std=c99 faster.c -o faster.exe
+faster > t.txt
+
+Now extract the code fragments from t.txt and insert them where indicated
+into big_256_29.c (look for UNWOUND)
+
+Finally make sure that
+
+#define UNWOUND
+
+appears somewhere in big_256_29.h
+
+Finally compile and replace the big_256_29 module in the library, and maybe 
+get a 30% speed-up! If there is no significant improvement, don't use this 
+method!
+
diff --git a/version3/c/fastest.c b/version3/c/fastest.c
new file mode 100644
index 0000000..6a6f7c7
--- /dev/null
+++ b/version3/c/fastest.c
@@ -0,0 +1,59 @@
+
+#include <stdio.h>
+#include "fp_YYY.h"
+
+#ifdef COMBA
+
+int main()
+{
+	int i,j,k,N;
+
+	N=NLEN_XXX;
+
+	printf("Insert this code in file fp_YYY.c\n\n");
+
+	printf("void FP_YYY_modmul(BIG_XXX r,BIG_XXX a,BIG_XXX b)\n");
+
+	printf("{\n");
+	printf("\tdchunk t,c,s;\n");
+	printf("\tdchunk d[%d],dd[%d];\n",N,N);
+	printf("\tchunk v[%d],md[%d];\n",N,N);	
+	printf("\tchunk MC=MConst_YYY;\n");
+
+	printf("\tBIG_XXX_rcopy(md,Modulus_YYY);\n");
+
+	for (i=0;i<N;i++)
+		printf("\td[%d]=(dchunk)a[%d]*b[%d];\n",i,i,i);
+
+	printf("\n\ts=d[0];  t=s; v[0]=((chunk)t*MC)&BMASK_XXX; t+=(dchunk)v[0]*md[0]; c=(t>>BASEBITS_XXX);\n\n");
+
+	for (k=1;k<N;k++)
+	{
+		printf("\ts+=d[%d]; t=s ",k);
+		for (i=k;i>=1+k/2;i--)
+			printf("+(dchunk)(a[%d]-a[%d])*(b[%d]-b[%d])",i,k-i,k-i,i);
+		printf("; t+=c+(dchunk)v[0]*md[%d]",k,k);
+		for (i=k-1;i>k/2;i--) printf("+(dchunk)(v[%d]-v[%d])*(md[%d]-md[%d])",k-i,i,i,k-i);
+		printf("; v[%d]=((chunk)t*MC)&BMASK_XXX; t+=(dchunk)v[%d]*md[0]; ",k,k);
+		printf(" dd[%d]=(dchunk)v[%d]*md[%d]; s+=dd[%d]; c=(t>>BASEBITS_XXX); \n",k,k,k,k);
+	}
+	printf("\n");
+	for (k=N;k<2*N-1;k++)
+	{
+		printf("\ts-=d[%d]; t=s ",k-N);
+		for (i=N-1;i>=1+k/2;i--)
+			printf("+(dchunk)(a[%d]-a[%d])*(b[%d]-b[%d])",i,k-i,k-i,i);
+		printf("; t+=c",k);
+		for (i=N-1;i>=1+k/2;i--) printf("+(dchunk)(v[%d]-v[%d])*(md[%d]-md[%d])",k-i,i,i,k-i);
+		printf("; r[%d]=(chunk)t&BMASK_XXX;  s-=dd[%d]; c=(t>>BASEBITS_XXX); \n",k-N,k-N+1);
+	}
+	
+	printf("\tr[%d]=(chunk)c&BMASK_XXX;\n",N-1);	
+
+    printf("}\n");
+
+}
+
+#endif
+
+
diff --git a/version3/c/fastest.txt b/version3/c/fastest.txt
new file mode 100644
index 0000000..cc7ced4
--- /dev/null
+++ b/version3/c/fastest.txt
@@ -0,0 +1,28 @@
+When using Montgomery reduction, some advantage comes from "fusing" the 
+multiplication with the modular reduction and unrolling the loops.
+
+For a 32-bit build and if for example using 256 bit BIGs and a base of 2^28
+with the NIST256 curve, replace XXX with 256_28 and YYY with NIST256 in 
+fastest.c
+
+
+Then compile and execute the program fastest.c like this (using MinGW
+port of GCC as an example), in the same directory as arch.h and fp_NIST256.h
+
+gcc -O2 -std=c99 fastest.c -o fastest.exe
+fastest > t.txt
+
+Now extract the code fragment from t.txt and insert it where indicated
+into fp_NIST256.c (look for FUSED_MODMUL)
+
+Finally make sure that
+
+#define FUSED_MODMUL
+
+appears somewhere in fp_NIST256.h
+
+Finally compile and replace the fp_YYY module in the library, and maybe 
+get a 30% speed-up! If there is no significant improvement, don't use this 
+method!
+
+NOTE: This method is experimental. It might impact on numerical stability.
diff --git a/version3/c/ff.c b/version3/c/ff.c
new file mode 100644
index 0000000..fd64dd9
--- /dev/null
+++ b/version3/c/ff.c
@@ -0,0 +1,1155 @@
+/*
+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.
+*/
+
+/* AMCL basic functions for Large Finite Field support */
+
+#include "ff_WWW.h"
+
+/* Arazi and Qi inversion mod 256 */
+static int invmod256(int a)
+{
+    int U,t1,t2,b,c;
+    t1=0;
+    c=(a>>1)&1;
+    t1+=c;
+    t1&=1;
+    t1=2-t1;
+    t1<<=1;
+    U=t1+1;
+
+// i=2
+    b=a&3;
+    t1=U*b;
+    t1>>=2;
+    c=(a>>2)&3;
+    t2=(U*c)&3;
+    t1+=t2;
+    t1*=U;
+    t1&=3;
+    t1=4-t1;
+    t1<<=2;
+    U+=t1;
+
+// i=4
+    b=a&15;
+    t1=U*b;
+    t1>>=4;
+    c=(a>>4)&15;
+    t2=(U*c)&15;
+    t1+=t2;
+    t1*=U;
+    t1&=15;
+    t1=16-t1;
+    t1<<=4;
+    U+=t1;
+
+    return U;
+}
+
+/* a=1/a mod 2^BIGBITS. This is very fast! */
+void BIG_XXX_invmod2m(BIG_XXX a)
+{
+    int i;
+    BIG_XXX U,t1,b,c;
+    BIG_XXX_zero(U);
+    BIG_XXX_inc(U,invmod256(BIG_XXX_lastbits(a,8)));
+    for (i=8; i<BIGBITS_XXX; i<<=1)
+    {
+        BIG_XXX_norm(U);
+        BIG_XXX_copy(b,a);
+        BIG_XXX_mod2m(b,i);   // bottom i bits of a
+
+        BIG_XXX_smul(t1,U,b);
+        BIG_XXX_shr(t1,i); // top i bits of U*b
+
+        BIG_XXX_copy(c,a);
+        BIG_XXX_shr(c,i);
+        BIG_XXX_mod2m(c,i); // top i bits of a
+
+        BIG_XXX_smul(b,U,c);
+        BIG_XXX_mod2m(b,i);  // bottom i bits of U*c
+
+        BIG_XXX_add(t1,t1,b);
+        BIG_XXX_norm(t1);
+        BIG_XXX_smul(b,t1,U);
+        BIG_XXX_copy(t1,b);  // (t1+b)*U
+        BIG_XXX_mod2m(t1,i);				// bottom i bits of (t1+b)*U
+
+        BIG_XXX_one(b);
+        BIG_XXX_shl(b,i);
+        BIG_XXX_sub(t1,b,t1);
+        BIG_XXX_norm(t1);
+
+        BIG_XXX_shl(t1,i);
+
+        BIG_XXX_add(U,U,t1);
+    }
+    BIG_XXX_copy(a,U);
+    BIG_XXX_norm(a);
+    BIG_XXX_mod2m(a,BIGBITS_XXX);
+}
+
+/*
+void FF_rcopy(BIG x[],const BIG y[],int n)
+{
+	int i;
+	for (i=0;i<n;i++)
+		BIG_rcopy(x[i],y[i]);
+}
+*/
+
+/* x=y */
+void FF_WWW_copy(BIG_XXX x[],BIG_XXX y[],int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+        BIG_XXX_copy(x[i],y[i]);
+}
+
+/* x=y<<n */
+static void FF_WWW_dsucopy(BIG_XXX x[],BIG_XXX y[],int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+    {
+        BIG_XXX_copy(x[n+i],y[i]);
+        BIG_XXX_zero(x[i]);
+    }
+}
+
+/* x=y */
+static void FF_WWW_dscopy(BIG_XXX x[],BIG_XXX y[],int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+    {
+        BIG_XXX_copy(x[i],y[i]);
+        BIG_XXX_zero(x[n+i]);
+    }
+}
+
+/* x=y>>n */
+static void FF_WWW_sducopy(BIG_XXX x[],BIG_XXX y[],int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+        BIG_XXX_copy(x[i],y[n+i]);
+}
+
+/* set to zero */
+void FF_WWW_zero(BIG_XXX x[],int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+        BIG_XXX_zero(x[i]);
+}
+
+/* test equals 0 */
+int FF_WWW_iszilch(BIG_XXX x[],int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+        if (!BIG_XXX_iszilch(x[i])) return 0;
+    return 1;
+}
+
+/* shift right by BIGBITS-bit words */
+static void FF_WWW_shrw(BIG_XXX a[],int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+    {
+        BIG_XXX_copy(a[i],a[i+n]);
+        BIG_XXX_zero(a[i+n]);
+    }
+}
+
+/* shift left by BIGBITS-bit words */
+static void FF_WWW_shlw(BIG_XXX a[],int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+    {
+        BIG_XXX_copy(a[i+n],a[i]);
+        BIG_XXX_zero(a[i]);
+    }
+}
+
+/* extract last bit */
+int FF_WWW_parity(BIG_XXX x[])
+{
+    return BIG_XXX_parity(x[0]);
+}
+
+/* extract last m bits */
+int FF_WWW_lastbits(BIG_XXX x[],int m)
+{
+    return BIG_XXX_lastbits(x[0],m);
+}
+
+/* x=1 */
+void FF_WWW_one(BIG_XXX x[],int n)
+{
+    int i;
+    BIG_XXX_one(x[0]);
+    for (i=1; i<n; i++)
+        BIG_XXX_zero(x[i]);
+}
+
+/* x=m, where m is 32-bit int */
+void FF_WWW_init(BIG_XXX x[],sign32 m,int n)
+{
+    int i;
+    BIG_XXX_zero(x[0]);
+#if CHUNK<64
+    x[0][0]=(chunk)(m&BMASK_XXX);
+    x[0][1]=(chunk)(m>>BASEBITS_XXX);
+#else
+    x[0][0]=(chunk)m;
+#endif
+    for (i=1; i<n; i++)
+        BIG_XXX_zero(x[i]);
+}
+
+/* compare x and y - must be normalised */
+int FF_WWW_comp(BIG_XXX x[],BIG_XXX y[],int n)
+{
+    int i,j;
+    for (i=n-1; i>=0; i--)
+    {
+        j=BIG_XXX_comp(x[i],y[i]);
+        if (j!=0) return j;
+    }
+    return 0;
+}
+
+/* recursive add */
+static void FF_WWW_radd(BIG_XXX z[],int zp,BIG_XXX x[],int xp,BIG_XXX y[],int yp,int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+        BIG_XXX_add(z[zp+i],x[xp+i],y[yp+i]);
+}
+
+/* recursive inc */
+static void FF_WWW_rinc(BIG_XXX z[],int zp,BIG_XXX y[],int yp,int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+        BIG_XXX_add(z[zp+i],z[zp+i],y[yp+i]);
+}
+
+/* recursive sub */
+/*
+static void FF_rsub(BIG z[],int zp,BIG x[],int xp,BIG y[],int yp,int n)
+{
+	int i;
+	for (i=0;i<n;i++)
+		BIG_sub(z[zp+i],x[xp+i],y[yp+i]);
+}
+*/
+
+/* recursive dec */
+static void FF_WWW_rdec(BIG_XXX z[],int zp,BIG_XXX y[],int yp,int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+        BIG_XXX_sub(z[zp+i],z[zp+i],y[yp+i]);
+}
+
+/* simple add */
+void FF_WWW_add(BIG_XXX z[],BIG_XXX x[],BIG_XXX y[],int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+        BIG_XXX_add(z[i],x[i],y[i]);
+}
+
+/* simple sub */
+void FF_WWW_sub(BIG_XXX z[],BIG_XXX x[],BIG_XXX y[],int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+        BIG_XXX_sub(z[i],x[i],y[i]);
+}
+
+/* increment/decrement by a small integer */
+void FF_WWW_inc(BIG_XXX x[],int m,int n)
+{
+    BIG_XXX_inc(x[0],m);
+    FF_WWW_norm(x,n);
+}
+
+void FF_WWW_dec(BIG_XXX x[],int m,int n)
+{
+    BIG_XXX_dec(x[0],m);
+    FF_WWW_norm(x,n);
+}
+
+/* normalise - but hold any overflow in top part unless n<0 */
+static void FF_WWW_rnorm(BIG_XXX z[],int zp,int n)
+{
+    int i,trunc=0;
+    chunk carry;
+    if (n<0)
+    {
+        /* -v n signals to do truncation */
+        n=-n;
+        trunc=1;
+    }
+    for (i=0; i<n-1; i++)
+    {
+        carry=BIG_XXX_norm(z[zp+i]);
+
+        z[zp+i][NLEN_XXX-1]^=carry<<P_TBITS_WWW; /* remove it */
+        z[zp+i+1][0]+=carry;
+    }
+    carry=BIG_XXX_norm(z[zp+n-1]);
+    if (trunc) z[zp+n-1][NLEN_XXX-1]^=carry<<P_TBITS_WWW;
+}
+
+void FF_WWW_norm(BIG_XXX z[],int n)
+{
+    FF_WWW_rnorm(z,0,n);
+}
+
+/* shift left by one bit */
+void FF_WWW_shl(BIG_XXX x[],int n)
+{
+    int i;
+    int carry,delay_carry=0;
+    for (i=0; i<n-1; i++)
+    {
+        carry=BIG_XXX_fshl(x[i],1);
+        x[i][0]|=delay_carry;
+        x[i][NLEN_XXX-1]^=(chunk)carry<<P_TBITS_WWW;
+        delay_carry=carry;
+    }
+    BIG_XXX_fshl(x[n-1],1);
+    x[n-1][0]|=delay_carry;
+}
+
+/* shift right by one bit */
+void FF_WWW_shr(BIG_XXX x[],int n)
+{
+    int i;
+    int carry;
+    for (i=n-1; i>0; i--)
+    {
+        carry=BIG_XXX_fshr(x[i],1);
+        x[i-1][NLEN_XXX-1]|=(chunk)carry<<P_TBITS_WWW;
+    }
+    BIG_XXX_fshr(x[0],1);
+}
+
+void FF_WWW_output(BIG_XXX x[],int n)
+{
+    int i;
+    FF_WWW_norm(x,n);
+    for (i=n-1; i>=0; i--)
+    {
+        BIG_XXX_output(x[i]);
+        printf(" ");
+    }
+}
+
+void FF_WWW_rawoutput(BIG_XXX x[],int n)
+{
+    int i;
+    for (i=n-1; i>=0; i--)
+    {
+        BIG_XXX_rawoutput(x[i]);
+        printf(" ");
+    }
+}
+
+/* Convert FFs to/from octet strings */
+void FF_WWW_toOctet(octet *w,BIG_XXX x[],int n)
+{
+    int i;
+    w->len=n*MODBYTES_XXX;
+    for (i=0; i<n; i++)
+    {
+        BIG_XXX_toBytes(&(w->val[(n-i-1)*MODBYTES_XXX]),x[i]);
+    }
+}
+
+void FF_WWW_fromOctet(BIG_XXX x[],octet *w,int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+    {
+        BIG_XXX_fromBytes(x[i],&(w->val[(n-i-1)*MODBYTES_XXX]));
+    }
+}
+
+/* in-place swapping using xor - side channel resistant */
+static void FF_WWW_cswap(BIG_XXX a[],BIG_XXX b[],int d,int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+        BIG_XXX_cswap(a[i],b[i],d);
+    return;
+}
+
+/* z=x*y, t is workspace */
+static void FF_WWW_karmul(BIG_XXX z[],int zp,BIG_XXX x[],int xp,BIG_XXX y[],int yp,BIG_XXX t[],int tp,int n)
+{
+    int nd2;
+    if (n==1)
+    {
+        BIG_XXX_norm(x[xp]);
+        BIG_XXX_norm(y[yp]);
+        BIG_XXX_mul(t[tp],x[xp],y[yp]);
+        BIG_XXX_split(z[zp+1],z[zp],t[tp],BIGBITS_XXX);
+        return;
+    }
+
+    nd2=n/2;
+    FF_WWW_radd(z,zp,x,xp,x,xp+nd2,nd2);
+    FF_WWW_rnorm(z,zp,nd2);  /* needs this if recursion level too deep */
+
+    FF_WWW_radd(z,zp+nd2,y,yp,y,yp+nd2,nd2);
+    FF_WWW_rnorm(z,zp+nd2,nd2);
+    FF_WWW_karmul(t,tp,z,zp,z,zp+nd2,t,tp+n,nd2);
+    FF_WWW_karmul(z,zp,x,xp,y,yp,t,tp+n,nd2);
+    FF_WWW_karmul(z,zp+n,x,xp+nd2,y,yp+nd2,t,tp+n,nd2);
+    FF_WWW_rdec(t,tp,z,zp,n);
+    FF_WWW_rdec(t,tp,z,zp+n,n);
+    FF_WWW_rinc(z,zp+nd2,t,tp,n);
+    FF_WWW_rnorm(z,zp,2*n);
+}
+
+static void FF_WWW_karsqr(BIG_XXX z[],int zp,BIG_XXX x[],int xp,BIG_XXX t[],int tp,int n)
+{
+    int nd2;
+    if (n==1)
+    {
+        BIG_XXX_norm(x[xp]);
+        BIG_XXX_sqr(t[tp],x[xp]);
+        BIG_XXX_split(z[zp+1],z[zp],t[tp],BIGBITS_XXX);
+        return;
+    }
+    nd2=n/2;
+    FF_WWW_karsqr(z,zp,x,xp,t,tp+n,nd2);
+    FF_WWW_karsqr(z,zp+n,x,xp+nd2,t,tp+n,nd2);
+    FF_WWW_karmul(t,tp,x,xp,x,xp+nd2,t,tp+n,nd2);
+    FF_WWW_rinc(z,zp+nd2,t,tp,n);
+    FF_WWW_rinc(z,zp+nd2,t,tp,n);
+
+    FF_WWW_rnorm(z,zp+nd2,n);  /* was FF_rnorm(z,zp,2*n)  */
+}
+
+static void FF_WWW_karmul_lower(BIG_XXX z[],int zp,BIG_XXX x[],int xp,BIG_XXX y[],int yp,BIG_XXX t[],int tp,int n)
+{
+    /* Calculates Least Significant bottom half of x*y */
+    int nd2;
+    if (n==1)
+    {
+        /* only calculate bottom half of product */
+        BIG_XXX_norm(x[xp]);
+        BIG_XXX_norm(y[yp]);
+        BIG_XXX_smul(z[zp],x[xp],y[yp]);
+        return;
+    }
+    nd2=n/2;
+    FF_WWW_karmul(z,zp,x,xp,y,yp,t,tp+n,nd2);
+    FF_WWW_karmul_lower(t,tp,x,xp+nd2,y,yp,t,tp+n,nd2);
+    FF_WWW_rinc(z,zp+nd2,t,tp,nd2);
+    FF_WWW_karmul_lower(t,tp,x,xp,y,yp+nd2,t,tp+n,nd2);
+    FF_WWW_rinc(z,zp+nd2,t,tp,nd2);
+    FF_WWW_rnorm(z,zp+nd2,-nd2);  /* truncate it */
+}
+
+static void FF_WWW_karmul_upper(BIG_XXX z[],BIG_XXX x[],BIG_XXX y[],BIG_XXX t[],int n)
+{
+    /* Calculates Most Significant upper half of x*y, given lower part */
+    int nd2;
+
+    nd2=n/2;
+    FF_WWW_radd(z,n,x,0,x,nd2,nd2);
+    FF_WWW_radd(z,n+nd2,y,0,y,nd2,nd2);
+    FF_WWW_rnorm(z,n,nd2);
+    FF_WWW_rnorm(z,n+nd2,nd2);
+
+    FF_WWW_karmul(t,0,z,n+nd2,z,n,t,n,nd2);  /* t = (a0+a1)(b0+b1) */
+    FF_WWW_karmul(z,n,x,nd2,y,nd2,t,n,nd2); /* z[n]= a1*b1 */
+    /* z[0-nd2]=l(a0b0) z[nd2-n]= h(a0b0)+l(t)-l(a0b0)-l(a1b1) */
+    FF_WWW_rdec(t,0,z,n,n);              /* t=t-a1b1  */
+    FF_WWW_rinc(z,nd2,z,0,nd2);   /* z[nd2-n]+=l(a0b0) = h(a0b0)+l(t)-l(a1b1)  */
+    FF_WWW_rdec(z,nd2,t,0,nd2);   /* z[nd2-n]=h(a0b0)+l(t)-l(a1b1)-l(t-a1b1)=h(a0b0) */
+    FF_WWW_rnorm(z,0,-n);					/* a0b0 now in z - truncate it */
+    FF_WWW_rdec(t,0,z,0,n);         /* (a0+a1)(b0+b1) - a0b0 */
+    FF_WWW_rinc(z,nd2,t,0,n);
+
+    FF_WWW_rnorm(z,nd2,n);
+}
+
+/* z=x*y */
+void FF_WWW_mul(BIG_XXX z[],BIG_XXX x[],BIG_XXX y[],int n)
+{
+#ifndef C99
+    BIG_XXX t[2*FFLEN_WWW];
+#else
+    BIG_XXX t[2*n];
+#endif
+//	FF_norm(x,n); /* change here */
+//	FF_norm(y,n); /* change here */
+    FF_WWW_karmul(z,0,x,0,y,0,t,0,n);
+}
+
+/* return low part of product */
+static void FF_WWW_lmul(BIG_XXX z[],BIG_XXX x[],BIG_XXX y[],int n)
+{
+#ifndef C99
+    BIG_XXX t[2*FFLEN_WWW];
+#else
+    BIG_XXX t[2*n];
+#endif
+//	FF_norm(x,n); /* change here */
+//	FF_norm(y,n); /* change here */
+    FF_WWW_karmul_lower(z,0,x,0,y,0,t,0,n);
+}
+
+/* Set b=b mod c */
+void FF_WWW_mod(BIG_XXX b[],BIG_XXX c[],int n)
+{
+    int k=0;
+
+    FF_WWW_norm(b,n);
+    if (FF_WWW_comp(b,c,n)<0)
+        return;
+    do
+    {
+        FF_WWW_shl(c,n);
+        k++;
+    }
+    while (FF_WWW_comp(b,c,n)>=0);
+
+    while (k>0)
+    {
+        FF_WWW_shr(c,n);
+        if (FF_WWW_comp(b,c,n)>=0)
+        {
+            FF_WWW_sub(b,b,c,n);
+            FF_WWW_norm(b,n);
+        }
+        k--;
+    }
+}
+
+/* z=x^2 */
+void FF_WWW_sqr(BIG_XXX z[],BIG_XXX x[],int n)
+{
+#ifndef C99
+    BIG_XXX t[2*FFLEN_WWW];
+#else
+    BIG_XXX t[2*n];
+#endif
+//	FF_norm(x,n); /* change here */
+    FF_WWW_karsqr(z,0,x,0,t,0,n);
+}
+
+/* r=t mod modulus, N is modulus, ND is Montgomery Constant */
+static void FF_WWW_reduce(BIG_XXX r[],BIG_XXX T[],BIG_XXX N[],BIG_XXX ND[],int n)
+{
+    /* fast karatsuba Montgomery reduction */
+#ifndef C99
+    BIG_XXX t[2*FFLEN_WWW];
+    BIG_XXX m[FFLEN_WWW];
+#else
+    BIG_XXX t[2*n];
+    BIG_XXX m[n];
+#endif
+    FF_WWW_sducopy(r,T,n);  /* keep top half of T */
+    //FF_norm(T,n); /* change here */
+    FF_WWW_karmul_lower(m,0,T,0,ND,0,t,0,n);  /* m=T.(1/N) mod R */
+
+    //FF_norm(N,n);  /* change here */
+    FF_WWW_karmul_upper(T,N,m,t,n);  /* T=mN */
+    FF_WWW_sducopy(m,T,n);
+
+    FF_WWW_add(r,r,N,n);
+    FF_WWW_sub(r,r,m,n);
+    FF_WWW_norm(r,n);
+}
+
+
+/* Set r=a mod b */
+/* a is of length - 2*n */
+/* r,b is of length - n */
+void FF_WWW_dmod(BIG_XXX r[],BIG_XXX a[],BIG_XXX b[],int n)
+{
+    int k;
+#ifndef C99
+    BIG_XXX m[2*FFLEN_WWW];
+    BIG_XXX x[2*FFLEN_WWW];
+#else
+    BIG_XXX m[2*n];
+    BIG_XXX x[2*n];
+#endif
+    FF_WWW_copy(x,a,2*n);
+    FF_WWW_norm(x,2*n);
+    FF_WWW_dsucopy(m,b,n);
+    k=BIGBITS_XXX*n;
+
+    while (FF_WWW_comp(x,m,2*n)>=0)
+    {
+        FF_WWW_sub(x,x,m,2*n);
+        FF_WWW_norm(x,2*n);
+    }
+
+    while (k>0)
+    {
+        FF_WWW_shr(m,2*n);
+
+        if (FF_WWW_comp(x,m,2*n)>=0)
+        {
+            FF_WWW_sub(x,x,m,2*n);
+            FF_WWW_norm(x,2*n);
+        }
+
+        k--;
+    }
+    FF_WWW_copy(r,x,n);
+    FF_WWW_mod(r,b,n);
+}
+
+/* Set r=1/a mod p. Binary method - a<p on entry */
+
+void FF_WWW_invmodp(BIG_XXX r[],BIG_XXX a[],BIG_XXX p[],int n)
+{
+#ifndef C99
+    BIG_XXX u[FFLEN_WWW],v[FFLEN_WWW],x1[FFLEN_WWW],x2[FFLEN_WWW],t[FFLEN_WWW],one[FFLEN_WWW];
+#else
+    BIG_XXX u[n],v[n],x1[n],x2[n],t[n],one[n];
+#endif
+    FF_WWW_copy(u,a,n);
+    FF_WWW_copy(v,p,n);
+    FF_WWW_one(one,n);
+    FF_WWW_copy(x1,one,n);
+    FF_WWW_zero(x2,n);
+
+// reduce n in here as well!
+    while (FF_WWW_comp(u,one,n)!=0 && FF_WWW_comp(v,one,n)!=0)
+    {
+        while (FF_WWW_parity(u)==0)
+        {
+            FF_WWW_shr(u,n);
+            if (FF_WWW_parity(x1)!=0)
+            {
+                FF_WWW_add(x1,p,x1,n);
+                FF_WWW_norm(x1,n);
+            }
+            FF_WWW_shr(x1,n);
+        }
+        while (FF_WWW_parity(v)==0)
+        {
+            FF_WWW_shr(v,n);
+            if (FF_WWW_parity(x2)!=0)
+            {
+                FF_WWW_add(x2,p,x2,n);
+                FF_WWW_norm(x2,n);
+            }
+            FF_WWW_shr(x2,n);
+        }
+        if (FF_WWW_comp(u,v,n)>=0)
+        {
+
+            FF_WWW_sub(u,u,v,n);
+            FF_WWW_norm(u,n);
+            if (FF_WWW_comp(x1,x2,n)>=0) FF_WWW_sub(x1,x1,x2,n);
+            else
+            {
+                FF_WWW_sub(t,p,x2,n);
+                FF_WWW_add(x1,x1,t,n);
+            }
+            FF_WWW_norm(x1,n);
+        }
+        else
+        {
+            FF_WWW_sub(v,v,u,n);
+            FF_WWW_norm(v,n);
+            if (FF_WWW_comp(x2,x1,n)>=0) FF_WWW_sub(x2,x2,x1,n);
+            else
+            {
+                FF_WWW_sub(t,p,x1,n);
+                FF_WWW_add(x2,x2,t,n);
+            }
+            FF_WWW_norm(x2,n);
+        }
+    }
+    if (FF_WWW_comp(u,one,n)==0)
+        FF_WWW_copy(r,x1,n);
+    else
+        FF_WWW_copy(r,x2,n);
+}
+
+/* nesidue mod m */
+static void FF_WWW_nres(BIG_XXX a[],BIG_XXX m[],int n)
+{
+#ifndef C99
+    BIG_XXX d[2*FFLEN_WWW];
+#else
+    BIG_XXX d[2*n];
+#endif
+    if (n==1)
+    {
+        BIG_XXX_dscopy(d[0],a[0]);
+        BIG_XXX_dshl(d[0],NLEN_XXX*BASEBITS_XXX);
+        BIG_XXX_dmod(a[0],d[0],m[0]);
+    }
+    else
+    {
+        FF_WWW_dsucopy(d,a,n);
+        FF_WWW_dmod(a,d,m,n);
+    }
+}
+
+static void FF_WWW_redc(BIG_XXX a[],BIG_XXX m[],BIG_XXX ND[],int n)
+{
+#ifndef C99
+    BIG_XXX d[2*FFLEN_WWW];
+#else
+    BIG_XXX d[2*n];
+#endif
+    if (n==1)
+    {
+        BIG_XXX_dzero(d[0]);
+        BIG_XXX_dscopy(d[0],a[0]);
+        BIG_XXX_monty(a[0],m[0],((chunk)1<<BASEBITS_XXX)-ND[0][0],d[0]);
+    }
+    else
+    {
+        FF_WWW_mod(a,m,n);
+        FF_WWW_dscopy(d,a,n);
+        FF_WWW_reduce(a,d,m,ND,n);
+        FF_WWW_mod(a,m,n);
+    }
+}
+
+/* U=1/a mod 2^m - Arazi & Qi */
+static void FF_WWW_invmod2m(BIG_XXX U[],BIG_XXX a[],int n)
+{
+    int i;
+#ifndef C99
+    BIG_XXX t1[FFLEN_WWW],b[FFLEN_WWW],c[FFLEN_WWW];
+#else
+    BIG_XXX t1[2*n],b[n],c[n];
+#endif
+
+    FF_WWW_zero(U,n);
+    FF_WWW_zero(b,n);
+    FF_WWW_zero(c,n);
+    FF_WWW_zero(t1,2*n);
+
+    BIG_XXX_copy(U[0],a[0]);
+    BIG_XXX_invmod2m(U[0]);
+    for (i=1; i<n; i<<=1)
+    {
+        FF_WWW_copy(b,a,i);
+        FF_WWW_mul(t1,U,b,i);
+        FF_WWW_shrw(t1,i); // top half to bottom half, top half=0
+
+        FF_WWW_copy(c,a,2*i);
+        FF_WWW_shrw(c,i); // top half of c
+        FF_WWW_lmul(b,U,c,i); // should set top half of b=0
+        FF_WWW_add(t1,t1,b,i);
+        FF_WWW_norm(t1,2*i);
+        FF_WWW_lmul(b,t1,U,i);
+        FF_WWW_copy(t1,b,i);
+        FF_WWW_one(b,i);
+        FF_WWW_shlw(b,i);
+        FF_WWW_sub(t1,b,t1,2*i);
+        FF_WWW_norm(t1,2*i);
+        FF_WWW_shlw(t1,i);
+        FF_WWW_add(U,U,t1,2*i);
+    }
+
+    FF_WWW_norm(U,n);
+}
+
+void FF_WWW_random(BIG_XXX x[],csprng *rng,int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+    {
+        BIG_XXX_random(x[i],rng);
+    }
+    /* make sure top bit is 1 */
+    while (BIG_XXX_nbits(x[n-1])<MODBYTES_XXX*8) BIG_XXX_random(x[n-1],rng);
+}
+
+/* generate random x mod p */
+void FF_WWW_randomnum(BIG_XXX x[],BIG_XXX p[],csprng *rng,int n)
+{
+    int i;
+#ifndef C99
+    BIG_XXX d[2*FFLEN_WWW];
+#else
+    BIG_XXX d[2*n];
+#endif
+    for (i=0; i<2*n; i++)
+    {
+        BIG_XXX_random(d[i],rng);
+    }
+    FF_WWW_dmod(x,d,p,n);
+}
+
+static void FF_WWW_modmul(BIG_XXX z[],BIG_XXX x[],BIG_XXX y[],BIG_XXX p[],BIG_XXX ND[],int n)
+{
+#ifndef C99
+    BIG_XXX d[2*FFLEN_WWW];
+#else
+    BIG_XXX d[2*n];
+#endif
+    chunk ex=P_EXCESS_WWW(x[n-1]);
+    chunk ey=P_EXCESS_WWW(y[n-1]);
+#ifdef dchunk
+    if ((dchunk)(ex+1)*(ey+1)>(dchunk)P_FEXCESS_WWW)
+#else
+    if ((ex+1)>P_FEXCESS_WWW/(ey+1))
+#endif
+    {
+#ifdef DEBUG_REDUCE
+        printf("Product too large - reducing it %d %d\n",ex,ey);
+#endif
+        FF_WWW_mod(x,p,n);
+    }
+
+    if (n==1)
+    {
+        BIG_XXX_mul(d[0],x[0],y[0]);
+        BIG_XXX_monty(z[0],p[0],((chunk)1<<BASEBITS_XXX)-ND[0][0],d[0]);
+    }
+    else
+    {
+        FF_WWW_mul(d,x,y,n);
+        FF_WWW_reduce(z,d,p,ND,n);
+    }
+}
+
+static void FF_WWW_modsqr(BIG_XXX z[],BIG_XXX x[],BIG_XXX p[],BIG_XXX ND[],int n)
+{
+#ifndef C99
+    BIG_XXX d[2*FFLEN_WWW];
+#else
+    BIG_XXX d[2*n];
+#endif
+    chunk ex=P_EXCESS_WWW(x[n-1]);
+#ifdef dchunk
+    if ((dchunk)(ex+1)*(ex+1)>(dchunk)P_FEXCESS_WWW)
+#else
+    if ((ex+1)>P_FEXCESS_WWW/(ex+1))
+#endif
+    {
+#ifdef DEBUG_REDUCE
+        printf("Product too large - reducing it %d\n",ex);
+#endif
+        FF_WWW_mod(x,p,n);
+    }
+    if (n==1)
+    {
+        BIG_XXX_sqr(d[0],x[0]);
+        BIG_XXX_monty(z[0],p[0],((chunk)1<<BASEBITS_XXX)-ND[0][0],d[0]);
+    }
+    else
+    {
+        FF_WWW_sqr(d,x,n);
+        FF_WWW_reduce(z,d,p,ND,n);
+    }
+}
+
+/* r=x^e mod p using side-channel resistant Montgomery Ladder, for large e */
+void FF_WWW_skpow(BIG_XXX r[],BIG_XXX x[],BIG_XXX e[],BIG_XXX p[],int n)
+{
+    int i,b;
+#ifndef C99
+    BIG_XXX R0[FFLEN_WWW],R1[FFLEN_WWW],ND[FFLEN_WWW];
+#else
+    BIG_XXX R0[n],R1[n],ND[n];
+#endif
+    FF_WWW_invmod2m(ND,p,n);
+
+    FF_WWW_one(R0,n);
+    FF_WWW_copy(R1,x,n);
+    FF_WWW_nres(R0,p,n);
+    FF_WWW_nres(R1,p,n);
+
+    for (i=8*MODBYTES_XXX*n-1; i>=0; i--)
+    {
+        b=BIG_XXX_bit(e[i/BIGBITS_XXX],i%BIGBITS_XXX);
+        FF_WWW_modmul(r,R0,R1,p,ND,n);
+
+        FF_WWW_cswap(R0,R1,b,n);
+        FF_WWW_modsqr(R0,R0,p,ND,n);
+
+        FF_WWW_copy(R1,r,n);
+        FF_WWW_cswap(R0,R1,b,n);
+    }
+    FF_WWW_copy(r,R0,n);
+    FF_WWW_redc(r,p,ND,n);
+}
+
+/* r=x^e mod p using side-channel resistant Montgomery Ladder, for short e */
+void FF_WWW_skspow(BIG_XXX r[],BIG_XXX x[],BIG_XXX e,BIG_XXX p[],int n)
+{
+    int i,b;
+#ifndef C99
+    BIG_XXX R0[FFLEN_WWW],R1[FFLEN_WWW],ND[FFLEN_WWW];
+#else
+    BIG_XXX R0[n],R1[n],ND[n];
+#endif
+    FF_WWW_invmod2m(ND,p,n);
+    FF_WWW_one(R0,n);
+    FF_WWW_copy(R1,x,n);
+    FF_WWW_nres(R0,p,n);
+    FF_WWW_nres(R1,p,n);
+    for (i=8*MODBYTES_XXX-1; i>=0; i--)
+    {
+        b=BIG_XXX_bit(e,i);
+        FF_WWW_modmul(r,R0,R1,p,ND,n);
+        FF_WWW_cswap(R0,R1,b,n);
+        FF_WWW_modsqr(R0,R0,p,ND,n);
+        FF_WWW_copy(R1,r,n);
+        FF_WWW_cswap(R0,R1,b,n);
+    }
+    FF_WWW_copy(r,R0,n);
+    FF_WWW_redc(r,p,ND,n);
+}
+
+/* raise to an integer power - right-to-left method */
+void FF_WWW_power(BIG_XXX r[],BIG_XXX x[],int e,BIG_XXX p[],int n)
+{
+    int f=1;
+#ifndef C99
+    BIG_XXX w[FFLEN_WWW],ND[FFLEN_WWW];
+#else
+    BIG_XXX w[n],ND[n];
+#endif
+    FF_WWW_invmod2m(ND,p,n);
+
+    FF_WWW_copy(w,x,n);
+    FF_WWW_nres(w,p,n);
+
+    if (e==2)
+    {
+        FF_WWW_modsqr(r,w,p,ND,n);
+    }
+    else for (;;)
+        {
+            if (e%2==1)
+            {
+                if (f) FF_WWW_copy(r,w,n);
+                else FF_WWW_modmul(r,r,w,p,ND,n);
+                f=0;
+            }
+            e>>=1;
+            if (e==0) break;
+            FF_WWW_modsqr(w,w,p,ND,n);
+        }
+
+    FF_WWW_redc(r,p,ND,n);
+}
+
+/* r=x^e mod p, faster but not side channel resistant */
+void FF_WWW_pow(BIG_XXX r[],BIG_XXX x[],BIG_XXX e[],BIG_XXX p[],int n)
+{
+    int i,b;
+#ifndef C99
+    BIG_XXX w[FFLEN_WWW],ND[FFLEN_WWW];
+#else
+    BIG_XXX w[n],ND[n];
+#endif
+    FF_WWW_invmod2m(ND,p,n);
+
+    FF_WWW_copy(w,x,n);
+    FF_WWW_one(r,n);
+    FF_WWW_nres(r,p,n);
+    FF_WWW_nres(w,p,n);
+
+    for (i=8*MODBYTES_XXX*n-1; i>=0; i--)
+    {
+        FF_WWW_modsqr(r,r,p,ND,n);
+        b=BIG_XXX_bit(e[i/BIGBITS_XXX],i%BIGBITS_XXX);
+        if (b==1) FF_WWW_modmul(r,r,w,p,ND,n);
+    }
+    FF_WWW_redc(r,p,ND,n);
+}
+
+/* double exponentiation r=x^e.y^f mod p */
+void FF_WWW_pow2(BIG_XXX r[],BIG_XXX x[],BIG_XXX e,BIG_XXX y[],BIG_XXX f,BIG_XXX p[],int n)
+{
+    int i,eb,fb;
+#ifndef C99
+    BIG_XXX xn[FFLEN_WWW],yn[FFLEN_WWW],xy[FFLEN_WWW],ND[FFLEN_WWW];
+#else
+    BIG_XXX xn[n],yn[n],xy[n],ND[n];
+#endif
+
+    FF_WWW_invmod2m(ND,p,n);
+
+    FF_WWW_copy(xn,x,n);
+    FF_WWW_copy(yn,y,n);
+    FF_WWW_nres(xn,p,n);
+    FF_WWW_nres(yn,p,n);
+    FF_WWW_modmul(xy,xn,yn,p,ND,n);
+    FF_WWW_one(r,n);
+    FF_WWW_nres(r,p,n);
+
+    for (i=8*MODBYTES_XXX-1; i>=0; i--)
+    {
+        eb=BIG_XXX_bit(e,i);
+        fb=BIG_XXX_bit(f,i);
+        FF_WWW_modsqr(r,r,p,ND,n);
+        if (eb==1)
+        {
+            if (fb==1) FF_WWW_modmul(r,r,xy,p,ND,n);
+            else FF_WWW_modmul(r,r,xn,p,ND,n);
+        }
+        else
+        {
+            if (fb==1) FF_WWW_modmul(r,r,yn,p,ND,n);
+        }
+    }
+    FF_WWW_redc(r,p,ND,n);
+}
+
+static sign32 igcd(sign32 x,sign32 y)
+{
+    /* integer GCD, returns GCD of x and y */
+    sign32 r;
+    if (y==0) return x;
+    while ((r=x%y)!=0)
+        x=y,y=r;
+    return y;
+}
+
+/* quick and dirty check for common factor with s */
+int FF_WWW_cfactor(BIG_XXX w[],sign32 s,int n)
+{
+    int r;
+    sign32 g;
+#ifndef C99
+    BIG_XXX x[FFLEN_WWW],y[FFLEN_WWW];
+#else
+    BIG_XXX x[n],y[n];
+#endif
+    FF_WWW_init(y,s,n);
+    FF_WWW_copy(x,w,n);
+    FF_WWW_norm(x,n);
+
+//	if (FF_parity(x)==0) return 1;
+    do
+    {
+        FF_WWW_sub(x,x,y,n);
+        FF_WWW_norm(x,n);
+        while (!FF_WWW_iszilch(x,n) && FF_WWW_parity(x)==0) FF_WWW_shr(x,n);
+    }
+    while (FF_WWW_comp(x,y,n)>0);
+#if CHUNK<32
+    g=x[0][0]+((sign32)(x[0][1])<<BASEBITS_XXX);
+#else
+    g=(sign32)x[0][0];
+#endif
+    r=igcd(s,g);
+    if (r>1) return 1;
+    return 0;
+}
+
+/* Miller-Rabin test for primality. Slow. */
+int FF_WWW_prime(BIG_XXX p[],csprng *rng,int n)
+{
+    int i,j,loop,s=0;
+#ifndef C99
+    BIG_XXX d[FFLEN_WWW],x[FFLEN_WWW],unity[FFLEN_WWW],nm1[FFLEN_WWW];
+#else
+    BIG_XXX d[n],x[n],unity[n],nm1[n];
+#endif
+    sign32 sf=4849845;/* 3*5*.. *19 */
+
+    FF_WWW_norm(p,n);
+
+    if (FF_WWW_cfactor(p,sf,n)) return 0;
+
+    FF_WWW_one(unity,n);
+    FF_WWW_sub(nm1,p,unity,n);
+    FF_WWW_norm(nm1,n);
+    FF_WWW_copy(d,nm1,n);
+    while (FF_WWW_parity(d)==0)
+    {
+        FF_WWW_shr(d,n);
+        s++;
+    }
+    if (s==0) return 0;
+
+    for (i=0; i<10; i++)
+    {
+        FF_WWW_randomnum(x,p,rng,n);
+        FF_WWW_pow(x,x,d,p,n);
+        if (FF_WWW_comp(x,unity,n)==0 || FF_WWW_comp(x,nm1,n)==0) continue;
+        loop=0;
+        for (j=1; j<s; j++)
+        {
+            FF_WWW_power(x,x,2,p,n);
+            if (FF_WWW_comp(x,unity,n)==0) return 0;
+            if (FF_WWW_comp(x,nm1,n)==0 )
+            {
+                loop=1;
+                break;
+            }
+        }
+        if (loop) continue;
+        return 0;
+    }
+
+    return 1;
+}
+
+/*
+BIG P[4]= {{0x1670957,0x1568CD3C,0x2595E5,0xEED4F38,0x1FC9A971,0x14EF7E62,0xA503883,0x9E1E05E,0xBF59E3},{0x1844C908,0x1B44A798,0x3A0B1E7,0xD1B5B4E,0x1836046F,0x87E94F9,0x1D34C537,0xF7183B0,0x46D07},{0x17813331,0x19E28A90,0x1473A4D6,0x1CACD01F,0x1EEA8838,0xAF2AE29,0x1F85292A,0x1632585E,0xD945E5},{0x919F5EF,0x1567B39F,0x19F6AD11,0x16CE47CF,0x9B36EB1,0x35B7D3,0x483B28C,0xCBEFA27,0xB5FC21}};
+
+int main()
+{
+	int i;
+	BIG p[4],e[4],x[4],r[4];
+	csprng rng;
+	char raw[100];
+	for (i=0;i<100;i++) raw[i]=i;
+    RAND_seed(&rng,100,raw);
+
+
+	FF_init(x,3,4);
+
+	FF_copy(p,P,4);
+	FF_copy(e,p,4);
+	FF_dec(e,1,4);
+	FF_norm(e,4);
+
+
+
+	printf("p= ");FF_output(p,4); printf("\n");
+	if (FF_prime(p,&rng,4)) printf("p is a prime\n");
+	printf("e= ");FF_output(e,4); printf("\n");
+
+	FF_skpow(r,x,e,p,4);
+	printf("r= ");FF_output(r,4); printf("\n");
+}
+
+*/
diff --git a/version3/c/ff.h b/version3/c/ff.h
new file mode 100644
index 0000000..a50e653
--- /dev/null
+++ b/version3/c/ff.h
@@ -0,0 +1,296 @@
+/*
+	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.
+*/
+
+/**
+ * @file ff.h
+ * @author Mike Scott
+ * @brief FF Header File
+ *
+ */
+
+#ifndef FF_WWW_H
+#define FF_WWW_H
+
+#include "big_XXX.h"
+#include "config_ff_WWW.h"
+
+#define HFLEN_WWW (FFLEN_WWW/2) /**< Useful for half-size RSA private key operations */
+#define P_MBITS_WWW (MODBYTES_XXX*8) /**< Number of bits in modulus */
+#define P_TBITS_WWW (P_MBITS_WWW%BASEBITS_XXX) /**< TODO  */
+#define P_EXCESS_WWW(a) (((a[NLEN_XXX-1])>>(P_TBITS_WWW))+1) /**< TODO */
+#define P_FEXCESS_WWW ((chunk)1<<(BASEBITS_XXX*NLEN_XXX-P_MBITS_WWW-1)) /**< TODO */
+
+
+/* Finite Field Prototypes */
+/**	@brief Copy one FF element of given length to another
+ *
+	@param x FF instance to be copied to, on exit = y
+	@param y FF instance to be copied from
+	@param n size of FF in BIGs
+
+ */
+extern void FF_WWW_copy(BIG_XXX *x,BIG_XXX *y,int n);
+/**	@brief Initialize an FF element of given length from a 32-bit integer m
+ *
+	@param x FF instance to be copied to, on exit = m
+	@param m integer
+	@param n size of FF in BIGs
+ */
+extern void FF_WWW_init(BIG_XXX *x,sign32 m,int n);
+/**	@brief Set FF element of given size to zero
+ *
+	@param x FF instance to be set to zero
+	@param n size of FF in BIGs
+ */
+extern void FF_WWW_zero(BIG_XXX *x,int n);
+/**	@brief Tests for FF element equal to zero
+ *
+	@param x FF number to be tested
+	@param n size of FF in BIGs
+	@return 1 if zero, else returns 0
+ */
+extern int FF_WWW_iszilch(BIG_XXX *x,int n);
+/**	@brief  return parity of an FF, that is the least significant bit
+ *
+	@param x FF number
+	@return 0 or 1
+ */
+extern int FF_WWW_parity(BIG_XXX *x);
+/**	@brief  return least significant m bits of an FF
+ *
+	@param x FF number
+	@param m number of bits to return. Assumed to be less than BASEBITS.
+	@return least significant n bits as an integer
+ */
+extern int FF_WWW_lastbits(BIG_XXX *x,int m);
+/**	@brief Set FF element of given size to unity
+ *
+	@param x FF instance to be set to unity
+	@param n size of FF in BIGs
+ */
+extern void FF_WWW_one(BIG_XXX *x,int n);
+/**	@brief Compares two FF numbers. Inputs must be normalised externally
+ *
+	@param x first FF number to be compared
+	@param y second FF number to be compared
+	@param n size of FF in BIGs
+	@return -1 is x<y, 0 if x=y, 1 if x>y
+ */
+extern int FF_WWW_comp(BIG_XXX *x,BIG_XXX *y,int n);
+/**	@brief addition of two FFs
+ *
+	@param x FF instance, on exit = y+z
+	@param y FF instance
+	@param z FF instance
+	@param n size of FF in BIGs
+ */
+extern void FF_WWW_add(BIG_XXX *x,BIG_XXX *y,BIG_XXX *z,int n);
+/**	@brief subtraction of two FFs
+ *
+	@param x FF instance, on exit = y-z
+	@param y FF instance
+	@param z FF instance
+	@param n size of FF in BIGs
+ */
+extern void FF_WWW_sub(BIG_XXX *x,BIG_XXX *y,BIG_XXX *z,int n);
+/**	@brief increment an FF by an integer,and normalise
+ *
+	@param x FF instance, on exit = x+m
+	@param m an integer to be added to x
+	@param n size of FF in BIGs
+ */
+extern void FF_WWW_inc(BIG_XXX *x,int m,int n);
+/**	@brief Decrement an FF by an integer,and normalise
+ *
+	@param x FF instance, on exit = x-m
+	@param m an integer to be subtracted from x
+	@param n size of FF in BIGs
+ */
+extern void FF_WWW_dec(BIG_XXX *x,int m,int n);
+/**	@brief Normalises the components of an FF
+ *
+	@param x FF instance to be normalised
+	@param n size of FF in BIGs
+ */
+extern void FF_WWW_norm(BIG_XXX *x,int n);
+/**	@brief Shift left an FF by 1 bit
+ *
+	@param x FF instance to be shifted left
+	@param n size of FF in BIGs
+ */
+extern void FF_WWW_shl(BIG_XXX *x,int n);
+/**	@brief Shift right an FF by 1 bit
+ *
+	@param x FF instance to be shifted right
+	@param n size of FF in BIGs
+ */
+extern void FF_WWW_shr(BIG_XXX *x,int n);
+/**	@brief Formats and outputs an FF to the console
+ *
+	@param x FF instance to be printed
+	@param n size of FF in BIGs
+ */
+extern void FF_WWW_output(BIG_XXX *x,int n);
+/**	@brief Formats and outputs an FF to the console, in raw form
+ *
+ 	@param x FF instance to be printed
+ 	@param n size of FF in BIGs
+ */
+extern void FF_WWW_rawoutput(BIG_XXX *x,int n);
+/**	@brief Formats and outputs an FF instance to an octet string
+ *
+	Converts an FF to big-endian base 256 form.
+	@param S output octet string
+	@param x FF instance to be converted to an octet string
+	@param n size of FF in BIGs
+ */
+extern void FF_WWW_toOctet(octet *S,BIG_XXX *x,int n);
+/**	@brief Populates an FF instance from an octet string
+ *
+	Creates FF from big-endian base 256 form.
+	@param x FF instance to be created from an octet string
+	@param S input octet string
+	@param n size of FF in BIGs
+ */
+extern void FF_WWW_fromOctet(BIG_XXX *x,octet *S,int n);
+/**	@brief Multiplication of two FFs
+ *
+	Uses Karatsuba method internally
+	@param x FF instance, on exit = y*z
+	@param y FF instance
+	@param z FF instance
+	@param n size of FF in BIGs
+ */
+extern void FF_WWW_mul(BIG_XXX *x,BIG_XXX *y,BIG_XXX *z,int n);
+/**	@brief Reduce FF mod a modulus
+ *
+	This is slow
+	@param x FF instance to be reduced mod m - on exit = x mod m
+	@param m FF modulus
+	@param n size of FF in BIGs
+ */
+extern void FF_WWW_mod(BIG_XXX *x,BIG_XXX *m,int n);
+/**	@brief Square an FF
+ *
+	Uses Karatsuba method internally
+	@param x FF instance, on exit = y^2
+	@param y FF instance to be squared
+	@param n size of FF in BIGs
+ */
+extern void FF_WWW_sqr(BIG_XXX *x,BIG_XXX *y,int n);
+/**	@brief Reduces a double-length FF with respect to a given modulus
+ *
+	This is slow
+	@param x FF instance, on exit = y mod z
+	@param y FF instance, of double length 2*n
+	@param z FF modulus
+	@param n size of FF in BIGs
+ */
+extern void FF_WWW_dmod(BIG_XXX *x,BIG_XXX *y,BIG_XXX *z,int n);
+/**	@brief Invert an FF mod a prime modulus
+ *
+	@param x FF instance, on exit = 1/y mod z
+	@param y FF instance
+	@param z FF prime modulus
+	@param n size of FF in BIGs
+ */
+extern void FF_WWW_invmodp(BIG_XXX *x,BIG_XXX *y,BIG_XXX *z,int n);
+/**	@brief Create an FF from a random number generator
+ *
+	@param x FF instance, on exit x is a random number of length n BIGs with most significant bit a 1
+	@param R an instance of a Cryptographically Secure Random Number Generator
+	@param n size of FF in BIGs
+ */
+extern void FF_WWW_random(BIG_XXX *x,csprng *R,int n);
+/**	@brief Create a random FF less than a given modulus from a random number generator
+ *
+	@param x FF instance, on exit x is a random number < y
+	@param y FF instance, the modulus
+	@param R an instance of a Cryptographically Secure Random Number Generator
+	@param n size of FF in BIGs
+ */
+extern void FF_WWW_randomnum(BIG_XXX *x,BIG_XXX *y,csprng *R,int n);
+/**	@brief Calculate r=x^e mod m, side channel resistant
+ *
+	@param r FF instance, on exit = x^e mod p
+	@param x FF instance
+	@param e FF exponent
+	@param m FF modulus
+	@param n size of FF in BIGs
+ */
+extern void FF_WWW_skpow(BIG_XXX *r,BIG_XXX *x,BIG_XXX * e,BIG_XXX *m,int n);
+/**	@brief Calculate r=x^e mod m, side channel resistant
+ *
+	For short BIG exponent
+	@param r FF instance, on exit = x^e mod p
+	@param x FF instance
+	@param e BIG exponent
+	@param m FF modulus
+	@param n size of FF in BIGs
+ */
+extern void FF_WWW_skspow(BIG_XXX *r,BIG_XXX *x,BIG_XXX e,BIG_XXX *m,int n);
+/**	@brief Calculate r=x^e mod m
+ *
+	For very short integer exponent
+	@param r FF instance, on exit = x^e mod p
+	@param x FF instance
+	@param e integer exponent
+	@param m FF modulus
+	@param n size of FF in BIGs
+ */
+extern void FF_WWW_power(BIG_XXX *r,BIG_XXX *x,int e,BIG_XXX *m,int n);
+/**	@brief Calculate r=x^e mod m
+ *
+	@param r FF instance, on exit = x^e mod p
+	@param x FF instance
+	@param e FF exponent
+	@param m FF modulus
+	@param n size of FF in BIGs
+ */
+extern void FF_WWW_pow(BIG_XXX *r,BIG_XXX *x,BIG_XXX *e,BIG_XXX *m,int n);
+/**	@brief Test if an FF has factor in common with integer s
+ *
+	@param x FF instance to be tested
+	@param s the supplied integer
+	@param n size of FF in BIGs
+	@return 1 if gcd(x,s)!=1, else return 0
+ */
+extern int FF_WWW_cfactor(BIG_XXX *x,sign32 s,int n);
+/**	@brief Test if an FF is prime
+ *
+	Uses Miller-Rabin Method
+	@param x FF instance to be tested
+	@param R an instance of a Cryptographically Secure Random Number Generator
+	@param n size of FF in BIGs
+	@return 1 if x is (almost certainly) prime, else return 0
+ */
+extern int FF_WWW_prime(BIG_XXX *x,csprng *R,int n);
+/**	@brief Calculate r=x^e.y^f mod m
+ *
+	@param r FF instance, on exit = x^e.y^f mod p
+	@param x FF instance
+	@param e BIG exponent
+	@param y FF instance
+	@param f BIG exponent
+	@param m FF modulus
+	@param n size of FF in BIGs
+ */
+extern void FF_WWW_pow2(BIG_XXX *r,BIG_XXX *x,BIG_XXX e,BIG_XXX *y,BIG_XXX f,BIG_XXX *m,int n);
+
+#endif
diff --git a/version3/c/fp.c b/version3/c/fp.c
new file mode 100644
index 0000000..0b60382
--- /dev/null
+++ b/version3/c/fp.c
@@ -0,0 +1,878 @@
+/*
+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.
+*/
+
+/* AMCL mod p functions */
+/* Small Finite Field arithmetic */
+/* SU=m, SU is Stack Usage (NOT_SPECIAL Modulus) */
+
+#include "fp_YYY.h"
+
+/* Fast Modular Reduction Methods */
+
+/* r=d mod m */
+/* d MUST be normalised */
+/* Products must be less than pR in all cases !!! */
+/* So when multiplying two numbers, their product *must* be less than MODBITS+BASEBITS*NLEN */
+/* Results *may* be one bit bigger than MODBITS */
+
+#if MODTYPE_YYY == PSEUDO_MERSENNE
+/* r=d mod m */
+
+/* Converts from BIG integer to residue form mod Modulus */
+void FP_YYY_nres(FP_YYY *y,BIG_XXX x)
+{
+    BIG_XXX_copy(y->g,x);
+    y->XES=1;
+}
+
+/* Converts from residue form back to BIG integer form */
+void FP_YYY_redc(BIG_XXX x,FP_YYY *y)
+{
+    BIG_XXX_copy(x,y->g);
+}
+
+/* reduce a DBIG to a BIG exploiting the special form of the modulus */
+void FP_YYY_mod(BIG_XXX r,DBIG_XXX d)
+{
+    BIG_XXX t,b;
+    chunk v,tw;
+    BIG_XXX_split(t,b,d,MODBITS_YYY);
+
+    /* Note that all of the excess gets pushed into t. So if squaring a value with a 4-bit excess, this results in
+       t getting all 8 bits of the excess product! So products must be less than pR which is Montgomery compatible */
+
+    if (MConst_YYY < NEXCESS_XXX)
+    {
+        BIG_XXX_imul(t,t,MConst_YYY);
+        BIG_XXX_norm(t);
+        BIG_XXX_add(r,t,b);
+        BIG_XXX_norm(r);
+        tw=r[NLEN_XXX-1];
+        r[NLEN_XXX-1]&=TMASK_YYY;
+        r[0]+=MConst_YYY*((tw>>TBITS_YYY));
+    }
+    else
+    {
+        v=BIG_XXX_pmul(t,t,MConst_YYY);
+        BIG_XXX_add(r,t,b);
+        BIG_XXX_norm(r);
+        tw=r[NLEN_XXX-1];
+        r[NLEN_XXX-1]&=TMASK_YYY;
+#if CHUNK == 16
+        r[1]+=muladd_XXX(MConst_YYY,((tw>>TBITS_YYY)+(v<<(BASEBITS_XXX-TBITS_YYY))),0,&r[0]);
+#else
+        r[0]+=MConst_YYY*((tw>>TBITS_YYY)+(v<<(BASEBITS_XXX-TBITS_YYY)));
+#endif
+    }
+    BIG_XXX_norm(r);
+}
+#endif
+
+/* This only applies to Curve C448, so specialised (for now) */
+#if MODTYPE_YYY == GENERALISED_MERSENNE
+
+void FP_YYY_nres(FP_YYY *y,BIG_XXX x)
+{
+    BIG_XXX_copy(y->g,x);
+    y->XES=1;
+}
+
+/* Converts from residue form back to BIG integer form */
+void FP_YYY_redc(BIG_XXX x,FP_YYY *y)
+{
+    BIG_XXX_copy(x,y->g);
+}
+
+/* reduce a DBIG to a BIG exploiting the special form of the modulus */
+void FP_YYY_mod(BIG_XXX r,DBIG_XXX d)
+{
+    BIG_XXX t,b;
+    chunk carry;
+    BIG_XXX_split(t,b,d,MBITS_YYY);
+
+    BIG_XXX_add(r,t,b);
+
+    BIG_XXX_dscopy(d,t);
+    BIG_XXX_dshl(d,MBITS_YYY/2);
+
+    BIG_XXX_split(t,b,d,MBITS_YYY);
+
+    BIG_XXX_add(r,r,t);
+    BIG_XXX_add(r,r,b);
+    BIG_XXX_norm(r);
+    BIG_XXX_shl(t,MBITS_YYY/2);
+
+    BIG_XXX_add(r,r,t);
+
+    carry=r[NLEN_XXX-1]>>TBITS_YYY;
+
+    r[NLEN_XXX-1]&=TMASK_YYY;
+    r[0]+=carry;
+
+    r[224/BASEBITS_XXX]+=carry<<(224%BASEBITS_XXX); /* need to check that this falls mid-word */
+    BIG_XXX_norm(r);
+}
+
+#endif
+
+#if MODTYPE_YYY == MONTGOMERY_FRIENDLY
+
+/* convert to Montgomery n-residue form */
+void FP_YYY_nres(FP_YYY *y,BIG_XXX x)
+{
+    DBIG_XXX d;
+    BIG_XXX r;
+    BIG_XXX_rcopy(r,R2modp_YYY);
+    BIG_XXX_mul(d,x,r);
+    FP_YYY_mod(y->g,d);
+    y->XES=2;
+}
+
+/* convert back to regular form */
+void FP_YYY_redc(BIG_XXX x,FP_YYY *y)
+{
+    DBIG_XXX d;
+    BIG_XXX_dzero(d);
+    BIG_XXX_dscopy(d,y->g);
+    FP_YYY_mod(x,d);
+}
+
+/* fast modular reduction from DBIG to BIG exploiting special form of the modulus */
+void FP_YYY_mod(BIG_XXX a,DBIG_XXX d)
+{
+    int i;
+
+    for (i=0; i<NLEN_XXX; i++)
+        d[NLEN_XXX+i]+=muladd_XXX(d[i],MConst_YYY-1,d[i],&d[NLEN_XXX+i-1]);
+
+    BIG_XXX_sducopy(a,d);
+    BIG_XXX_norm(a);
+}
+
+#endif
+
+#if MODTYPE_YYY == NOT_SPECIAL
+
+/* convert to Montgomery n-residue form */
+void FP_YYY_nres(FP_YYY *y,BIG_XXX x)
+{
+    DBIG_XXX d;
+    BIG_XXX r;
+    BIG_XXX_rcopy(r,R2modp_YYY);
+    BIG_XXX_mul(d,x,r);
+    FP_YYY_mod(y->g,d);
+    y->XES=2;
+}
+
+/* convert back to regular form */
+void FP_YYY_redc(BIG_XXX x,FP_YYY *y)
+{
+    DBIG_XXX d;
+    BIG_XXX_dzero(d);
+    BIG_XXX_dscopy(d,y->g);
+    FP_YYY_mod(x,d);
+}
+
+
+/* reduce a DBIG to a BIG using Montgomery's no trial division method */
+/* d is expected to be dnormed before entry */
+/* SU= 112 */
+void FP_YYY_mod(BIG_XXX a,DBIG_XXX d)
+{
+    BIG_XXX mdls;
+    BIG_XXX_rcopy(mdls,Modulus_YYY);
+    BIG_XXX_monty(a,mdls,MConst_YYY,d);
+}
+
+#endif
+
+/* test x==0 ? */
+/* SU= 48 */
+int FP_YYY_iszilch(FP_YYY *x)
+{
+    BIG_XXX m,t;
+    BIG_XXX_rcopy(m,Modulus_YYY);
+	BIG_XXX_copy(t,x->g);
+    BIG_XXX_mod(t,m);
+    return BIG_XXX_iszilch(t);
+}
+
+void FP_YYY_copy(FP_YYY *y,FP_YYY *x)
+{
+    BIG_XXX_copy(y->g,x->g);
+    y->XES=x->XES;
+}
+
+void FP_YYY_rcopy(FP_YYY *y, const BIG_XXX c)
+{
+    BIG_XXX b;
+    BIG_XXX_rcopy(b,c);
+    FP_YYY_nres(y,b);
+}
+
+/* Swap a and b if d=1 */
+void FP_YYY_cswap(FP_YYY *a,FP_YYY *b,int d)
+{
+    sign32 t,c=d;
+    BIG_XXX_cswap(a->g,b->g,d);
+
+    c=~(c-1);
+    t=c&((a->XES)^(b->XES));
+    a->XES^=t;
+    b->XES^=t;
+
+}
+
+/* Move b to a if d=1 */
+void FP_YYY_cmove(FP_YYY *a,FP_YYY *b,int d)
+{
+    sign32 c=-d;
+
+    BIG_XXX_cmove(a->g,b->g,d);
+    a->XES^=(a->XES^b->XES)&c;
+}
+
+void FP_YYY_zero(FP_YYY *x)
+{
+    BIG_XXX_zero(x->g);
+    x->XES=1;
+}
+
+int FP_YYY_equals(FP_YYY *x,FP_YYY *y)
+{
+	FP_YYY xg,yg;
+	FP_YYY_copy(&xg,x);
+	FP_YYY_copy(&yg,y);
+    FP_YYY_reduce(&xg);
+    FP_YYY_reduce(&yg);
+    if (BIG_XXX_comp(xg.g,yg.g)==0) return 1;
+    return 0;
+}
+
+/* output FP */
+/* SU= 48 */
+void FP_YYY_output(FP_YYY *r)
+{
+    BIG_XXX c;
+    FP_YYY_redc(c,r);
+    BIG_XXX_output(c);
+}
+
+void FP_YYY_rawoutput(FP_YYY *r)
+{
+    BIG_XXX_rawoutput(r->g);
+}
+
+#ifdef GET_STATS
+int tsqr=0,rsqr=0,tmul=0,rmul=0;
+int tadd=0,radd=0,tneg=0,rneg=0;
+int tdadd=0,rdadd=0,tdneg=0,rdneg=0;
+#endif
+
+#ifdef FUSED_MODMUL
+
+/* Insert fastest code here */
+
+#endif
+
+/* r=a*b mod Modulus */
+/* product must be less that p.R - and we need to know this in advance! */
+/* SU= 88 */
+void FP_YYY_mul(FP_YYY *r,FP_YYY *a,FP_YYY *b)
+{
+    DBIG_XXX d;
+//    chunk ea,eb;
+//    BIG_XXX_norm(a);
+//    BIG_XXX_norm(b);
+//    ea=EXCESS_YYY(a->g);
+//    eb=EXCESS_YYY(b->g);
+
+
+    if ((sign64)a->XES*b->XES>(sign64)FEXCESS_YYY)
+    {
+#ifdef DEBUG_REDUCE
+        printf("Product too large - reducing it\n");
+#endif
+        FP_YYY_reduce(a);  /* it is sufficient to fully reduce just one of them < p */
+    }
+
+#ifdef FUSED_MODMUL
+    FP_YYY_modmul(r->g,a->g,b->g);
+#else
+    BIG_XXX_mul(d,a->g,b->g);
+    FP_YYY_mod(r->g,d);
+#endif
+    r->XES=2;
+}
+
+
+/* multiplication by an integer, r=a*c */
+/* SU= 136 */
+void FP_YYY_imul(FP_YYY *r,FP_YYY *a,int c)
+{
+    int s=0;
+
+    if (c<0)
+    {
+        c=-c;
+        s=1;
+    }
+
+#if MODTYPE_YYY==PSEUDO_MERSENNE || MODTYPE_YYY==GENERALISED_MERSENNE
+    DBIG_XXX d;
+    BIG_XXX_pxmul(d,a->g,c);
+    FP_YYY_mod(r->g,d);
+    r->XES=2;
+
+#else
+    //Montgomery
+    BIG_XXX k;
+    FP_YYY f;
+    if (a->XES*c<=FEXCESS_YYY)
+    {
+        BIG_XXX_pmul(r->g,a->g,c);
+        r->XES=a->XES*c;    // careful here - XES jumps!
+    }
+    else
+    {
+        // don't want to do this - only a problem for Montgomery modulus and larger constants
+        BIG_XXX_zero(k);
+        BIG_XXX_inc(k,c);
+		BIG_XXX_norm(k);
+        FP_YYY_nres(&f,k);
+        FP_YYY_mul(r,a,&f);
+    }
+#endif
+    /*
+        if (c<=NEXCESS_XXX && a->XES*c <= FEXCESS_YYY)
+    	{
+            BIG_XXX_imul(r->g,a->g,c);
+    		r->XES=a->XES*c;
+    		FP_YYY_norm(r);
+    	}
+        else
+        {
+                BIG_XXX_pxmul(d,a->g,c);
+
+                BIG_XXX_rcopy(m,Modulus_YYY);
+    			BIG_XXX_dmod(r->g,d,m);
+                //FP_YYY_mod(r->g,d);                /// BIG problem here! Too slow for PM, How to do fast for Monty?
+    			r->XES=2;
+        }
+    */
+    if (s)
+    {
+        FP_YYY_neg(r,r);
+        FP_YYY_norm(r);
+    }
+}
+
+/* Set r=a^2 mod m */
+/* SU= 88 */
+void FP_YYY_sqr(FP_YYY *r,FP_YYY *a)
+{
+    DBIG_XXX d;
+//    chunk ea;
+//    BIG_XXX_norm(a);
+//    ea=EXCESS_YYY(a->g);
+
+
+    if ((sign64)a->XES*a->XES>(sign64)FEXCESS_YYY)
+    {
+#ifdef DEBUG_REDUCE
+        printf("Product too large - reducing it\n");
+#endif
+        FP_YYY_reduce(a);
+    }
+
+    BIG_XXX_sqr(d,a->g);
+    FP_YYY_mod(r->g,d);
+    r->XES=2;
+}
+
+/* SU= 16 */
+/* Set r=a+b */
+void FP_YYY_add(FP_YYY *r,FP_YYY *a,FP_YYY *b)
+{
+    BIG_XXX_add(r->g,a->g,b->g);
+    r->XES=a->XES+b->XES;
+    if (r->XES>FEXCESS_YYY)
+    {
+#ifdef DEBUG_REDUCE
+        printf("Sum too large - reducing it \n");
+#endif
+        FP_YYY_reduce(r);
+    }
+}
+
+/* Set r=a-b mod m */
+/* SU= 56 */
+void FP_YYY_sub(FP_YYY *r,FP_YYY *a,FP_YYY *b)
+{
+    FP_YYY n;
+//	BIG_XXX_norm(b);
+    FP_YYY_neg(&n,b);
+//	BIG_XXX_norm(n);
+    FP_YYY_add(r,a,&n);
+}
+
+// https://graphics.stanford.edu/~seander/bithacks.html
+// constant time log to base 2 (or number of bits in)
+
+static int logb2(unsign32 v)
+{
+    int r;
+    v |= v >> 1;
+    v |= v >> 2;
+    v |= v >> 4;
+    v |= v >> 8;
+    v |= v >> 16;
+
+    v = v - ((v >> 1) & 0x55555555);
+    v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
+    r = (((v + (v >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24;
+    return r;
+}
+
+// find appoximation to quotient of a/m
+// Out by at most 2.
+// Note that MAXXES is bounded to be 2-bits less than half a word
+static int quo(BIG_XXX n,BIG_XXX m)
+{
+	int sh;
+	chunk num,den;
+	int hb=CHUNK/2;
+	if (TBITS_YYY<hb)
+	{
+		sh=hb-TBITS_YYY;
+		num=(n[NLEN_XXX-1]<<sh)|(n[NLEN_XXX-2]>>(BASEBITS_XXX-sh));
+		den=(m[NLEN_XXX-1]<<sh)|(m[NLEN_XXX-2]>>(BASEBITS_XXX-sh));
+	}
+	else
+	{
+		num=n[NLEN_XXX-1];
+		den=m[NLEN_XXX-1];
+	}
+	return (int)(num/(den+1));
+}
+
+/* SU= 48 */
+/* Fully reduce a mod Modulus */
+void FP_YYY_reduce(FP_YYY *a)
+{
+    BIG_XXX m,r;
+	int sr,sb,q;
+	chunk carry;
+
+    BIG_XXX_rcopy(m,Modulus_YYY);
+
+	BIG_XXX_norm(a->g);
+
+	if (a->XES>16)
+	{
+		q=quo(a->g,m);
+		carry=BIG_XXX_pmul(r,m,q);
+		r[NLEN_XXX-1]+=(carry<<BASEBITS_XXX); // correction - put any carry out back in again
+		BIG_XXX_sub(a->g,a->g,r);
+		BIG_XXX_norm(a->g);
+		sb=2;
+	}
+	else sb=logb2(a->XES-1);  // sb does not depend on the actual data
+
+	BIG_XXX_fshl(m,sb);
+
+	while (sb>0)
+	{
+// constant time...
+		sr=BIG_XXX_ssn(r,a->g,m);  // optimized combined shift, subtract and norm
+		BIG_XXX_cmove(a->g,r,1-sr);
+		sb--;
+	}
+
+    //BIG_XXX_mod(a->g,m);
+    a->XES=1;
+}
+
+void FP_YYY_norm(FP_YYY *x)
+{
+    BIG_XXX_norm(x->g);
+}
+
+/* Set r=-a mod Modulus */
+/* SU= 64 */
+void FP_YYY_neg(FP_YYY *r,FP_YYY *a)
+{
+    int sb;
+    BIG_XXX m;
+
+    BIG_XXX_rcopy(m,Modulus_YYY);
+
+    sb=logb2(a->XES-1);
+    BIG_XXX_fshl(m,sb);
+    BIG_XXX_sub(r->g,m,a->g);
+    r->XES=((sign32)1<<sb)+1;
+
+    if (r->XES>FEXCESS_YYY)
+    {
+#ifdef DEBUG_REDUCE
+        printf("Negation too large -  reducing it \n");
+#endif
+        FP_YYY_reduce(r);
+    }
+
+}
+
+/* Set r=a/2. */
+/* SU= 56 */
+void FP_YYY_div2(FP_YYY *r,FP_YYY *a)
+{
+    BIG_XXX m;
+    BIG_XXX_rcopy(m,Modulus_YYY);
+    FP_YYY_copy(r,a);
+//    BIG_XXX_norm(a);
+    if (BIG_XXX_parity(a->g)==0)
+    {
+
+        BIG_XXX_fshr(r->g,1);
+    }
+    else
+    {
+        BIG_XXX_add(r->g,r->g,m);
+        BIG_XXX_norm(r->g);
+        BIG_XXX_fshr(r->g,1);
+    }
+}
+
+#if MODTYPE_YYY == PSEUDO_MERSENNE
+
+// See eprint paper "On inversion modulo pseudo-Mersenne primes"
+// If p=3 mod 4 r= x^{(p-3)/4}, if p=5 mod 8 r=x^{(p-5)/8}
+
+static void FP_YYY_fpow(FP_YYY *r,FP_YYY *x)
+{
+	int i,j,k,bw,w,c,nw,lo,m,n;
+	FP_YYY xp[11],t,key;
+	const int ac[]={1,2,3,6,12,15,30,60,120,240,255};
+// phase 1
+	FP_YYY_copy(&xp[0],x);	// 1 
+	FP_YYY_sqr(&xp[1],x); // 2
+	FP_YYY_mul(&xp[2],&xp[1],x);  //3
+	FP_YYY_sqr(&xp[3],&xp[2]);  // 6 
+	FP_YYY_sqr(&xp[4],&xp[3]); // 12
+	FP_YYY_mul(&xp[5],&xp[4],&xp[2]); // 15
+	FP_YYY_sqr(&xp[6],&xp[5]); // 30
+	FP_YYY_sqr(&xp[7],&xp[6]); // 60
+	FP_YYY_sqr(&xp[8],&xp[7]); // 120
+	FP_YYY_sqr(&xp[9],&xp[8]); // 240
+	FP_YYY_mul(&xp[10],&xp[9],&xp[5]); // 255
+
+	if (MOD8_YYY==5)
+    {
+		n=MODBITS_YYY-3;
+		c=(MConst_YYY+5)/8;
+	} else {
+		n=MODBITS_YYY-2;
+		c=(MConst_YYY+3)/4;
+	}
+
+	bw=0; w=1; while (w<c) {w*=2; bw+=1;}
+	k=w-c;
+
+	if (k!=0)
+	{
+		i=10; while (ac[i]>k) i--;
+		FP_YYY_copy(&key,&xp[i]); 
+		k-=ac[i];
+	}
+	while (k!=0)
+	{
+		i--;
+		if (ac[i]>k) continue;
+		FP_YYY_mul(&key,&key,&xp[i]);
+		k-=ac[i]; 
+	}
+
+// phase 2 
+	FP_YYY_copy(&xp[1],&xp[2]);
+	FP_YYY_copy(&xp[2],&xp[5]);
+	FP_YYY_copy(&xp[3],&xp[10]);
+
+	j=3; m=8;
+	nw=n-bw;
+	while (2*m<nw)
+	{
+		FP_YYY_copy(&t,&xp[j++]);
+		for (i=0;i<m;i++)
+			FP_YYY_sqr(&t,&t); 
+		FP_YYY_mul(&xp[j],&xp[j-1],&t); 
+		m*=2;
+	}
+
+	lo=nw-m;
+	FP_YYY_copy(r,&xp[j]);
+
+	while (lo!=0)
+	{
+		m/=2; j--;
+		if (lo<m) continue;
+		lo-=m;
+		FP_YYY_copy(&t,r);
+		for (i=0;i<m;i++)
+			FP_YYY_sqr(&t,&t);
+		FP_YYY_mul(r,&t,&xp[j]);
+	}
+// phase 3
+
+	for (i=0;i<bw;i++ )
+		FP_YYY_sqr(r,r);
+
+	if (w-c!=0)
+		FP_YYY_mul(r,r,&key); 
+}
+
+void FP_YYY_inv(FP_YYY *r,FP_YYY *x)
+{
+	FP_YYY y,t;
+	FP_YYY_fpow(&y,x);
+    if (MOD8_YYY==5)
+    { // r=x^3.y^8
+		FP_YYY_sqr(&t,x);
+		FP_YYY_mul(&t,&t,x);
+		FP_YYY_sqr(&y,&y);
+		FP_YYY_sqr(&y,&y);
+		FP_YYY_sqr(&y,&y);
+		FP_YYY_mul(r,&t,&y);
+	} else {
+		FP_YYY_sqr(&y,&y);
+		FP_YYY_sqr(&y,&y);
+		FP_YYY_mul(r,&y,x);
+	}
+}
+
+#else
+
+void FP_YYY_pow(FP_YYY *r,FP_YYY *a,BIG_XXX b)
+{
+	sign8 w[1+(NLEN_XXX*BASEBITS_XXX+3)/4];
+	FP_YYY tb[16];
+	BIG_XXX t;
+	int i,nb;
+
+	FP_YYY_norm(a);
+    BIG_XXX_norm(b);
+	BIG_XXX_copy(t,b);
+	nb=1+(BIG_XXX_nbits(t)+3)/4;
+    /* convert exponent to 4-bit window */
+    for (i=0; i<nb; i++)
+    {
+        w[i]=BIG_XXX_lastbits(t,4);
+        BIG_XXX_dec(t,w[i]);
+        BIG_XXX_norm(t);
+        BIG_XXX_fshr(t,4);
+    }	
+
+	FP_YYY_one(&tb[0]);
+	FP_YYY_copy(&tb[1],a);
+	for (i=2;i<16;i++)
+		FP_YYY_mul(&tb[i],&tb[i-1],a);
+	
+	FP_YYY_copy(r,&tb[w[nb-1]]);
+    for (i=nb-2; i>=0; i--)
+    {
+		FP_YYY_sqr(r,r);
+		FP_YYY_sqr(r,r);
+		FP_YYY_sqr(r,r);
+		FP_YYY_sqr(r,r);
+		FP_YYY_mul(r,r,&tb[w[i]]);
+	}
+    FP_YYY_reduce(r);
+}
+
+/* set w=1/x */
+void FP_YYY_inv(FP_YYY *w,FP_YYY *x)
+{
+
+	BIG_XXX m2;
+	BIG_XXX_rcopy(m2,Modulus_YYY);
+	BIG_XXX_dec(m2,2);
+	BIG_XXX_norm(m2);
+	FP_YYY_pow(w,x,m2);
+}
+#endif
+
+/* SU=8 */
+/* set n=1 */
+void FP_YYY_one(FP_YYY *n)
+{
+    BIG_XXX b;
+    BIG_XXX_one(b);
+    FP_YYY_nres(n,b);
+}
+
+/* Set r=a^b mod Modulus */
+/* SU= 136 */
+/*
+void FP_YYY_pow(FP_YYY *r,FP_YYY *a,BIG_XXX b)
+{
+    BIG_XXX z,zilch;
+    FP_YYY w;
+    int bt;
+    BIG_XXX_zero(zilch);
+
+    BIG_XXX_norm(b);
+    BIG_XXX_copy(z,b);
+    FP_YYY_copy(&w,a);
+    FP_YYY_one(r);
+    while(1)
+    {
+        bt=BIG_XXX_parity(z);
+        BIG_XXX_fshr(z,1);
+        if (bt) FP_YYY_mul(r,r,&w);
+        if (BIG_XXX_comp(z,zilch)==0) break;
+        FP_YYY_sqr(&w,&w);
+    }
+    FP_YYY_reduce(r);
+}
+*/
+
+
+
+/* is r a QR? */
+int FP_YYY_qr(FP_YYY *r)
+{
+    int j;
+    BIG_XXX m;
+    BIG_XXX b;
+    BIG_XXX_rcopy(m,Modulus_YYY);
+    FP_YYY_redc(b,r);
+    j=BIG_XXX_jacobi(b,m);
+    FP_YYY_nres(r,b);
+    if (j==1) return 1;
+    return 0;
+
+}
+
+/* Set a=sqrt(b) mod Modulus */
+/* SU= 160 */
+void FP_YYY_sqrt(FP_YYY *r,FP_YYY *a)
+{
+    FP_YYY v,i;
+    BIG_XXX b;
+    BIG_XXX m;
+    BIG_XXX_rcopy(m,Modulus_YYY);
+    BIG_XXX_mod(a->g,m);
+    BIG_XXX_copy(b,m);
+    if (MOD8_YYY==5)
+    {
+        FP_YYY_copy(&i,a); // i=x
+        BIG_XXX_fshl(i.g,1); // i=2x
+#if MODTYPE_YYY == PSEUDO_MERSENNE
+		FP_YYY_fpow(&v,&i);
+#else
+        BIG_XXX_dec(b,5);
+        BIG_XXX_norm(b);
+        BIG_XXX_fshr(b,3); // (p-5)/8 
+        FP_YYY_pow(&v,&i,b); // v=(2x)^(p-5)/8
+#endif
+        FP_YYY_mul(&i,&i,&v); // i=(2x)^(p+3)/8
+        FP_YYY_mul(&i,&i,&v); // i=(2x)^(p-1)/4
+        BIG_XXX_dec(i.g,1);  // i=(2x)^(p-1)/4 - 1
+        FP_YYY_mul(r,a,&v);  
+        FP_YYY_mul(r,r,&i);
+        FP_YYY_reduce(r);
+    }
+    if (MOD8_YYY==3 || MOD8_YYY==7)
+    {
+#if MODTYPE_YYY == PSEUDO_MERSENNE
+		FP_YYY_fpow(r,a);
+		FP_YYY_mul(r,r,a);
+#else
+        BIG_XXX_inc(b,1);
+        BIG_XXX_norm(b);
+        BIG_XXX_fshr(b,2); /* (p+1)/4 */
+        FP_YYY_pow(r,a,b);
+#endif
+    }
+}
+
+/*
+int main()
+{
+
+	BIG_XXX r;
+
+	FP_YYY_one(r);
+	FP_YYY_sqr(r,r);
+
+	BIG_XXX_output(r);
+
+	int i,carry;
+	DBIG_XXX c={0,0,0,0,0,0,0,0};
+	BIG_XXX a={1,2,3,4};
+	BIG_XXX b={3,4,5,6};
+	BIG_XXX r={11,12,13,14};
+	BIG_XXX s={23,24,25,15};
+	BIG_XXX w;
+
+//	printf("NEXCESS_XXX= %d\n",NEXCESS_XXX);
+//	printf("MConst_YYY= %d\n",MConst_YYY);
+
+	BIG_XXX_copy(b,Modulus_YYY);
+	BIG_XXX_dec(b,1);
+	BIG_XXX_norm(b);
+
+	BIG_XXX_randomnum(r); BIG_XXX_norm(r); BIG_XXX_mod(r,Modulus_YYY);
+//	BIG_XXX_randomnum(s); norm(s); BIG_XXX_mod(s,Modulus_YYY);
+
+//	BIG_XXX_output(r);
+//	BIG_XXX_output(s);
+
+	BIG_XXX_output(r);
+	FP_YYY_nres(r);
+	BIG_XXX_output(r);
+	BIG_XXX_copy(a,r);
+	FP_YYY_redc(r);
+	BIG_XXX_output(r);
+	BIG_XXX_dscopy(c,a);
+	FP_YYY_mod(r,c);
+	BIG_XXX_output(r);
+
+
+//	exit(0);
+
+//	copy(r,a);
+	printf("r=   "); BIG_XXX_output(r);
+	BIG_XXX_modsqr(r,r,Modulus_YYY);
+	printf("r^2= "); BIG_XXX_output(r);
+
+	FP_YYY_nres(r);
+	FP_YYY_sqrt(r,r);
+	FP_YYY_redc(r);
+	printf("r=   "); BIG_XXX_output(r);
+	BIG_XXX_modsqr(r,r,Modulus_YYY);
+	printf("r^2= "); BIG_XXX_output(r);
+
+
+//	for (i=0;i<100000;i++) FP_YYY_sqr(r,r);
+//	for (i=0;i<100000;i++)
+		FP_YYY_sqrt(r,r);
+
+	BIG_XXX_output(r);
+}
+*/
diff --git a/version3/c/fp.h b/version3/c/fp.h
new file mode 100644
index 0000000..a7883f2
--- /dev/null
+++ b/version3/c/fp.h
@@ -0,0 +1,245 @@
+/*
+	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.
+*/
+
+/**
+ * @file fp.h
+ * @author Mike Scott
+ * @brief FP Header File
+ *
+ */
+
+#ifndef FP_YYY_H
+#define FP_YYY_H
+
+#include "big_XXX.h"
+#include "config_field_YYY.h"
+
+
+/**
+	@brief FP Structure - quadratic extension field
+*/
+
+typedef struct
+{
+    BIG_XXX g;	/**< Big representation of field element */
+    sign32 XES;	/**< Excess */
+} FP_YYY;
+
+
+/* Field Params - see rom.c */
+extern const BIG_XXX Modulus_YYY;	/**< Actual Modulus set in romf_yyy.c */
+extern const BIG_XXX R2modp_YYY;	/**< Montgomery constant */
+extern const chunk MConst_YYY;		/**< Constant associated with Modulus - for Montgomery = 1/p mod 2^BASEBITS */
+
+
+#define MODBITS_YYY MBITS_YYY                        /**< Number of bits in Modulus for selected curve */
+#define TBITS_YYY (MBITS_YYY%BASEBITS_XXX)           /**< Number of active bits in top word */
+#define TMASK_YYY (((chunk)1<<TBITS_YYY)-1)          /**< Mask for active bits in top word */
+#define FEXCESS_YYY (((sign32)1<<MAXXES_YYY)-1)	     /**< 2^(BASEBITS*NLEN-MODBITS)-1 - normalised BIG can be multiplied by less than this before reduction */
+#define OMASK_YYY (-((chunk)(1)<<TBITS_YYY))         /**<  for masking out overflow bits */
+
+//#define FUSED_MODMUL
+//#define DEBUG_REDUCE
+
+/* FP prototypes */
+
+/**	@brief Tests for FP equal to zero mod Modulus
+ *
+	@param x BIG number to be tested
+	@return 1 if zero, else returns 0
+ */
+extern int FP_YYY_iszilch(FP_YYY *x);
+
+
+/**	@brief Set FP to zero
+ *
+	@param x FP number to be set to 0
+ */
+extern void FP_YYY_zero(FP_YYY *x);
+
+/**	@brief Copy an FP
+ *
+	@param y FP number to be copied to
+	@param x FP to be copied from
+ */
+extern void FP_YYY_copy(FP_YYY *y,FP_YYY *x);
+
+/**	@brief Copy from ROM to an FP
+ *
+	@param y FP number to be copied to
+	@param x BIG to be copied from ROM
+ */
+extern void FP_YYY_rcopy(FP_YYY *y,const BIG_XXX x);
+
+
+/**	@brief Compares two FPs
+ *
+	@param x FP number
+	@param y FP number
+	@return 1 if equal, else returns 0
+ */
+extern int FP_YYY_equals(FP_YYY *x,FP_YYY *y);
+
+
+/**	@brief Conditional constant time swap of two FP numbers
+ *
+	Conditionally swaps parameters in constant time (without branching)
+	@param x an FP number
+	@param y another FP number
+	@param s swap takes place if not equal to 0
+ */
+extern void FP_YYY_cswap(FP_YYY *x,FP_YYY *y,int s);
+/**	@brief Conditional copy of FP number
+ *
+	Conditionally copies second parameter to the first (without branching)
+	@param x an FP number
+	@param y another FP number
+	@param s copy takes place if not equal to 0
+ */
+extern void FP_YYY_cmove(FP_YYY *x,FP_YYY *y,int s);
+/**	@brief Converts from BIG integer to residue form mod Modulus
+ *
+	@param x BIG number to be converted
+	@param y FP result
+ */
+extern void FP_YYY_nres(FP_YYY *y,BIG_XXX x);
+/**	@brief Converts from residue form back to BIG integer form
+ *
+	@param y FP number to be converted to BIG
+	@param x BIG result
+ */
+extern void FP_YYY_redc(BIG_XXX x,FP_YYY *y);
+/**	@brief Sets FP to representation of unity in residue form
+ *
+	@param x FP number to be set equal to unity.
+ */
+extern void FP_YYY_one(FP_YYY *x);
+/**	@brief Reduces DBIG to BIG exploiting special form of the modulus
+ *
+	This function comes in different flavours depending on the form of Modulus that is currently in use.
+	@param r BIG number, on exit = d mod Modulus
+	@param d DBIG number to be reduced
+ */
+extern void FP_YYY_mod(BIG_XXX r,DBIG_XXX d);
+
+#ifdef FUSED_MODMUL
+extern void FP_YYY_modmul(BIG_XXX,BIG_XXX,BIG_XXX);
+#endif
+
+/**	@brief Fast Modular multiplication of two FPs, mod Modulus
+ *
+	Uses appropriate fast modular reduction method
+	@param x FP number, on exit the modular product = y*z mod Modulus
+	@param y FP number, the multiplicand
+	@param z FP number, the multiplier
+ */
+extern void FP_YYY_mul(FP_YYY *x,FP_YYY *y,FP_YYY *z);
+/**	@brief Fast Modular multiplication of an FP, by a small integer, mod Modulus
+ *
+	@param x FP number, on exit the modular product = y*i mod Modulus
+	@param y FP number, the multiplicand
+	@param i a small number, the multiplier
+ */
+extern void FP_YYY_imul(FP_YYY *x,FP_YYY *y,int i);
+/**	@brief Fast Modular squaring of an FP, mod Modulus
+ *
+	Uses appropriate fast modular reduction method
+	@param x FP number, on exit the modular product = y^2 mod Modulus
+	@param y FP number, the number to be squared
+
+ */
+extern void FP_YYY_sqr(FP_YYY *x,FP_YYY *y);
+/**	@brief Modular addition of two FPs, mod Modulus
+ *
+	@param x FP number, on exit the modular sum = y+z mod Modulus
+	@param y FP number
+	@param z FP number
+ */
+extern void FP_YYY_add(FP_YYY *x,FP_YYY *y,FP_YYY *z);
+/**	@brief Modular subtraction of two FPs, mod Modulus
+ *
+	@param x FP number, on exit the modular difference = y-z mod Modulus
+	@param y FP number
+	@param z FP number
+ */
+extern void FP_YYY_sub(FP_YYY *x,FP_YYY *y,FP_YYY *z);
+/**	@brief Modular division by 2 of an FP, mod Modulus
+ *
+	@param x FP number, on exit =y/2 mod Modulus
+	@param y FP number
+ */
+extern void FP_YYY_div2(FP_YYY *x,FP_YYY *y);
+/**	@brief Fast Modular exponentiation of an FP, to the power of a BIG, mod Modulus
+ *
+	@param x FP number, on exit  = y^z mod Modulus
+	@param y FP number
+	@param z BIG number exponent
+ */
+extern void FP_YYY_pow(FP_YYY *x,FP_YYY *y,BIG_XXX z);
+/**	@brief Fast Modular square root of a an FP, mod Modulus
+ *
+	@param x FP number, on exit  = sqrt(y) mod Modulus
+	@param y FP number, the number whose square root is calculated
+
+ */
+extern void FP_YYY_sqrt(FP_YYY *x,FP_YYY *y);
+/**	@brief Modular negation of a an FP, mod Modulus
+ *
+	@param x FP number, on exit = -y mod Modulus
+	@param y FP number
+ */
+extern void FP_YYY_neg(FP_YYY *x,FP_YYY *y);
+/**	@brief Outputs an FP number to the console
+ *
+	Converts from residue form before output
+	@param x an FP number
+ */
+extern void FP_YYY_output(FP_YYY *x);
+/**	@brief Outputs an FP number to the console, in raw form
+ *
+	@param x a BIG number
+ */
+extern void FP_YYY_rawoutput(FP_YYY *x);
+/**	@brief Reduces possibly unreduced FP mod Modulus
+ *
+	@param x FP number, on exit reduced mod Modulus
+ */
+extern void FP_YYY_reduce(FP_YYY *x);
+/**	@brief normalizes FP
+ *
+	@param x FP number, on exit normalized
+ */
+extern void FP_YYY_norm(FP_YYY *x);
+/**	@brief Tests for FP a quadratic residue mod Modulus
+ *
+	@param x FP number to be tested
+	@return 1 if quadratic residue, else returns 0 if quadratic non-residue
+ */
+extern int FP_YYY_qr(FP_YYY *x);
+/**	@brief Modular inverse of a an FP, mod Modulus
+ *
+	@param x FP number, on exit = 1/y mod Modulus
+	@param y FP number
+ */
+extern void FP_YYY_inv(FP_YYY *x,FP_YYY *y);
+
+
+
+
+#endif
diff --git a/version3/c/fp12.c b/version3/c/fp12.c
new file mode 100644
index 0000000..860fc12
--- /dev/null
+++ b/version3/c/fp12.c
@@ -0,0 +1,984 @@
+/*
+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.
+*/
+
+/* AMCL Fp^12 functions */
+/* SU=m, m is Stack Usage (no lazy )*/
+/* FP12 elements are of the form a+i.b+i^2.c */
+
+#include "fp12_YYY.h"
+
+/* return 1 if b==c, no branching */
+static int teq(sign32 b,sign32 c)
+{
+    sign32 x=b^c;
+    x-=1;  // if x=0, x now -1
+    return (int)((x>>31)&1);
+}
+
+
+/* Constant time select from pre-computed table */
+static void FP12_YYY_select(FP12_YYY *f,FP12_YYY g[],sign32 b)
+{
+    FP12_YYY invf;
+    sign32 m=b>>31;
+    sign32 babs=(b^m)-m;
+
+    babs=(babs-1)/2;
+
+    FP12_YYY_cmove(f,&g[0],teq(babs,0));  // conditional move
+    FP12_YYY_cmove(f,&g[1],teq(babs,1));
+    FP12_YYY_cmove(f,&g[2],teq(babs,2));
+    FP12_YYY_cmove(f,&g[3],teq(babs,3));
+    FP12_YYY_cmove(f,&g[4],teq(babs,4));
+    FP12_YYY_cmove(f,&g[5],teq(babs,5));
+    FP12_YYY_cmove(f,&g[6],teq(babs,6));
+    FP12_YYY_cmove(f,&g[7],teq(babs,7));
+
+    FP12_YYY_copy(&invf,f);
+    FP12_YYY_conj(&invf,&invf);  // 1/f
+    FP12_YYY_cmove(f,&invf,(int)(m&1));
+}
+
+
+
+/* test x==0 ? */
+/* SU= 8 */
+int FP12_YYY_iszilch(FP12_YYY *x)
+{
+    if (FP4_YYY_iszilch(&(x->a)) && FP4_YYY_iszilch(&(x->b)) && FP4_YYY_iszilch(&(x->c))) return 1;
+    return 0;
+}
+
+/* test x==1 ? */
+/* SU= 8 */
+int FP12_YYY_isunity(FP12_YYY *x)
+{
+    if (FP4_YYY_isunity(&(x->a)) && FP4_YYY_iszilch(&(x->b)) && FP4_YYY_iszilch(&(x->c))) return 1;
+    return 0;
+}
+
+/* FP12 copy w=x */
+/* SU= 16 */
+void FP12_YYY_copy(FP12_YYY *w,FP12_YYY *x)
+{
+    if (x==w) return;
+    FP4_YYY_copy(&(w->a),&(x->a));
+    FP4_YYY_copy(&(w->b),&(x->b));
+    FP4_YYY_copy(&(w->c),&(x->c));
+}
+
+/* FP12 w=1 */
+/* SU= 8 */
+void FP12_YYY_one(FP12_YYY *w)
+{
+    FP4_YYY_one(&(w->a));
+    FP4_YYY_zero(&(w->b));
+    FP4_YYY_zero(&(w->c));
+}
+
+/* return 1 if x==y, else 0 */
+/* SU= 16 */
+int FP12_YYY_equals(FP12_YYY *x,FP12_YYY *y)
+{
+    if (FP4_YYY_equals(&(x->a),&(y->a)) && FP4_YYY_equals(&(x->b),&(y->b)) && FP4_YYY_equals(&(x->b),&(y->b)))
+        return 1;
+    return 0;
+}
+
+/* Set w=conj(x) */
+/* SU= 8 */
+void FP12_YYY_conj(FP12_YYY *w,FP12_YYY *x)
+{
+    FP12_YYY_copy(w,x);
+    FP4_YYY_conj(&(w->a),&(w->a));
+    FP4_YYY_nconj(&(w->b),&(w->b));
+    FP4_YYY_conj(&(w->c),&(w->c));
+}
+
+/* Create FP12 from FP4 */
+/* SU= 8 */
+void FP12_YYY_from_FP4(FP12_YYY *w,FP4_YYY *a)
+{
+    FP4_YYY_copy(&(w->a),a);
+    FP4_YYY_zero(&(w->b));
+    FP4_YYY_zero(&(w->c));
+}
+
+/* Create FP12 from 3 FP4's */
+/* SU= 16 */
+void FP12_YYY_from_FP4s(FP12_YYY *w,FP4_YYY *a,FP4_YYY *b,FP4_YYY *c)
+{
+    FP4_YYY_copy(&(w->a),a);
+    FP4_YYY_copy(&(w->b),b);
+    FP4_YYY_copy(&(w->c),c);
+}
+
+/* Granger-Scott Unitary Squaring. This does not benefit from lazy reduction */
+/* SU= 600 */
+void FP12_YYY_usqr(FP12_YYY *w,FP12_YYY *x)
+{
+    FP4_YYY A,B,C,D;
+
+    FP4_YYY_copy(&A,&(x->a));
+
+    FP4_YYY_sqr(&(w->a),&(x->a));
+    FP4_YYY_add(&D,&(w->a),&(w->a));
+    FP4_YYY_add(&(w->a),&D,&(w->a));
+
+    FP4_YYY_norm(&(w->a));
+    FP4_YYY_nconj(&A,&A);
+
+    FP4_YYY_add(&A,&A,&A);
+    FP4_YYY_add(&(w->a),&(w->a),&A);
+    FP4_YYY_sqr(&B,&(x->c));
+    FP4_YYY_times_i(&B);
+
+    FP4_YYY_add(&D,&B,&B);
+    FP4_YYY_add(&B,&B,&D);
+    FP4_YYY_norm(&B);
+
+    FP4_YYY_sqr(&C,&(x->b));
+
+    FP4_YYY_add(&D,&C,&C);
+    FP4_YYY_add(&C,&C,&D);
+
+    FP4_YYY_norm(&C);
+    FP4_YYY_conj(&(w->b),&(x->b));
+    FP4_YYY_add(&(w->b),&(w->b),&(w->b));
+    FP4_YYY_nconj(&(w->c),&(x->c));
+
+    FP4_YYY_add(&(w->c),&(w->c),&(w->c));
+    FP4_YYY_add(&(w->b),&B,&(w->b));
+    FP4_YYY_add(&(w->c),&C,&(w->c));
+
+    FP12_YYY_reduce(w);	    /* reduce here as in pow function repeated squarings would trigger multiple reductions */
+}
+
+/* FP12 squaring w=x^2 */
+/* SU= 600 */
+void FP12_YYY_sqr(FP12_YYY *w,FP12_YYY *x)
+{
+    /* Use Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
+
+    FP4_YYY A,B,C,D;
+
+    FP4_YYY_sqr(&A,&(x->a));
+    FP4_YYY_mul(&B,&(x->b),&(x->c));
+    FP4_YYY_add(&B,&B,&B);
+    FP4_YYY_norm(&B);
+    FP4_YYY_sqr(&C,&(x->c));
+
+    FP4_YYY_mul(&D,&(x->a),&(x->b));
+    FP4_YYY_add(&D,&D,&D);
+    FP4_YYY_add(&(w->c),&(x->a),&(x->c));
+    FP4_YYY_add(&(w->c),&(x->b),&(w->c));
+    FP4_YYY_norm(&(w->c));
+
+    FP4_YYY_sqr(&(w->c),&(w->c));
+
+    FP4_YYY_copy(&(w->a),&A);
+    FP4_YYY_add(&A,&A,&B);
+
+    FP4_YYY_norm(&A);
+
+    FP4_YYY_add(&A,&A,&C);
+    FP4_YYY_add(&A,&A,&D);
+
+    FP4_YYY_norm(&A);
+    FP4_YYY_neg(&A,&A);
+    FP4_YYY_times_i(&B);
+    FP4_YYY_times_i(&C);
+
+    FP4_YYY_add(&(w->a),&(w->a),&B);
+    FP4_YYY_add(&(w->b),&C,&D);
+    FP4_YYY_add(&(w->c),&(w->c),&A);
+
+    FP12_YYY_norm(w);
+}
+
+/* FP12 full multiplication w=w*y */
+
+
+/* SU= 896 */
+/* FP12 full multiplication w=w*y */
+void FP12_YYY_mul(FP12_YYY *w,FP12_YYY *y)
+{
+    FP4_YYY z0,z1,z2,z3,t0,t1;
+
+    FP4_YYY_mul(&z0,&(w->a),&(y->a));
+    FP4_YYY_mul(&z2,&(w->b),&(y->b));  //
+
+    FP4_YYY_add(&t0,&(w->a),&(w->b));
+    FP4_YYY_add(&t1,&(y->a),&(y->b));  //
+
+    FP4_YYY_norm(&t0);
+    FP4_YYY_norm(&t1);
+
+    FP4_YYY_mul(&z1,&t0,&t1);
+    FP4_YYY_add(&t0,&(w->b),&(w->c));
+    FP4_YYY_add(&t1,&(y->b),&(y->c));  //
+
+    FP4_YYY_norm(&t0);
+    FP4_YYY_norm(&t1);
+
+    FP4_YYY_mul(&z3,&t0,&t1);
+
+    FP4_YYY_neg(&t0,&z0);
+    FP4_YYY_neg(&t1,&z2);
+
+    FP4_YYY_add(&z1,&z1,&t0);   // z1=z1-z0
+//    FP4_YYY_norm(&z1);
+    FP4_YYY_add(&(w->b),&z1,&t1);
+// z1=z1-z2
+    FP4_YYY_add(&z3,&z3,&t1);        // z3=z3-z2
+    FP4_YYY_add(&z2,&z2,&t0);        // z2=z2-z0
+
+    FP4_YYY_add(&t0,&(w->a),&(w->c));
+    FP4_YYY_add(&t1,&(y->a),&(y->c));
+
+    FP4_YYY_norm(&t0);
+    FP4_YYY_norm(&t1);
+
+    FP4_YYY_mul(&t0,&t1,&t0);
+    FP4_YYY_add(&z2,&z2,&t0);
+
+    FP4_YYY_mul(&t0,&(w->c),&(y->c));
+    FP4_YYY_neg(&t1,&t0);
+
+    FP4_YYY_add(&(w->c),&z2,&t1);
+    FP4_YYY_add(&z3,&z3,&t1);
+    FP4_YYY_times_i(&t0);
+    FP4_YYY_add(&(w->b),&(w->b),&t0);
+    FP4_YYY_norm(&z3);
+    FP4_YYY_times_i(&z3);
+    FP4_YYY_add(&(w->a),&z0,&z3);
+
+    FP12_YYY_norm(w);
+}
+
+/* FP12 multiplication w=w*y */
+/* SU= 744 */
+/* catering for special case that arises from special form of ATE pairing line function */
+void FP12_YYY_smul(FP12_YYY *w,FP12_YYY *y,int type)
+{
+    FP4_YYY z0,z1,z2,z3,t0,t1;
+
+    if (type==D_TYPE)
+    {
+        // y->c is 0
+
+        FP4_YYY_copy(&z3,&(w->b));
+        FP4_YYY_mul(&z0,&(w->a),&(y->a));
+
+        FP4_YYY_pmul(&z2,&(w->b),&(y->b).a);
+        FP4_YYY_add(&(w->b),&(w->a),&(w->b));
+        FP4_YYY_copy(&t1,&(y->a));
+        FP2_YYY_add(&t1.a,&t1.a,&(y->b).a);
+
+        FP4_YYY_norm(&t1);
+        FP4_YYY_norm(&(w->b));
+
+        FP4_YYY_mul(&(w->b),&(w->b),&t1);
+        FP4_YYY_add(&z3,&z3,&(w->c));
+        FP4_YYY_norm(&z3);
+        FP4_YYY_pmul(&z3,&z3,&(y->b).a);
+        FP4_YYY_neg(&t0,&z0);
+        FP4_YYY_neg(&t1,&z2);
+
+        FP4_YYY_add(&(w->b),&(w->b),&t0);   // z1=z1-z0
+//    FP4_YYY_norm(&(w->b));
+        FP4_YYY_add(&(w->b),&(w->b),&t1);   // z1=z1-z2
+
+        FP4_YYY_add(&z3,&z3,&t1);        // z3=z3-z2
+        FP4_YYY_add(&z2,&z2,&t0);        // z2=z2-z0
+
+        FP4_YYY_add(&t0,&(w->a),&(w->c));
+
+        FP4_YYY_norm(&t0);
+        FP4_YYY_norm(&z3);
+
+        FP4_YYY_mul(&t0,&(y->a),&t0);
+        FP4_YYY_add(&(w->c),&z2,&t0);
+
+        FP4_YYY_times_i(&z3);
+        FP4_YYY_add(&(w->a),&z0,&z3);
+    }
+
+    if (type==M_TYPE)
+    {
+        // y->b is zero
+        FP4_YYY_mul(&z0,&(w->a),&(y->a));
+        FP4_YYY_add(&t0,&(w->a),&(w->b));
+        FP4_YYY_norm(&t0);
+
+        FP4_YYY_mul(&z1,&t0,&(y->a));
+        FP4_YYY_add(&t0,&(w->b),&(w->c));
+        FP4_YYY_norm(&t0);
+
+        FP4_YYY_pmul(&z3,&t0,&(y->c).b);
+        FP4_YYY_times_i(&z3);
+
+        FP4_YYY_neg(&t0,&z0);
+        FP4_YYY_add(&z1,&z1,&t0);   // z1=z1-z0
+
+        FP4_YYY_copy(&(w->b),&z1);
+
+        FP4_YYY_copy(&z2,&t0);
+
+        FP4_YYY_add(&t0,&(w->a),&(w->c));
+        FP4_YYY_add(&t1,&(y->a),&(y->c));
+
+        FP4_YYY_norm(&t0);
+        FP4_YYY_norm(&t1);
+
+        FP4_YYY_mul(&t0,&t1,&t0);
+        FP4_YYY_add(&z2,&z2,&t0);
+
+        FP4_YYY_pmul(&t0,&(w->c),&(y->c).b);
+        FP4_YYY_times_i(&t0);
+        FP4_YYY_neg(&t1,&t0);
+        FP4_YYY_times_i(&t0);
+
+        FP4_YYY_add(&(w->c),&z2,&t1);
+        FP4_YYY_add(&z3,&z3,&t1);
+
+        FP4_YYY_add(&(w->b),&(w->b),&t0);
+        FP4_YYY_norm(&z3);
+        FP4_YYY_times_i(&z3);
+        FP4_YYY_add(&(w->a),&z0,&z3);
+    }
+    FP12_YYY_norm(w);
+}
+
+/* Set w=1/x */
+/* SU= 600 */
+void FP12_YYY_inv(FP12_YYY *w,FP12_YYY *x)
+{
+    FP4_YYY f0,f1,f2,f3;
+//    FP12_YYY_norm(x);
+
+    FP4_YYY_sqr(&f0,&(x->a));
+    FP4_YYY_mul(&f1,&(x->b),&(x->c));
+    FP4_YYY_times_i(&f1);
+    FP4_YYY_sub(&f0,&f0,&f1);  /* y.a */
+    FP4_YYY_norm(&f0);
+
+    FP4_YYY_sqr(&f1,&(x->c));
+    FP4_YYY_times_i(&f1);
+    FP4_YYY_mul(&f2,&(x->a),&(x->b));
+    FP4_YYY_sub(&f1,&f1,&f2);  /* y.b */
+    FP4_YYY_norm(&f1);
+
+    FP4_YYY_sqr(&f2,&(x->b));
+    FP4_YYY_mul(&f3,&(x->a),&(x->c));
+    FP4_YYY_sub(&f2,&f2,&f3);  /* y.c */
+    FP4_YYY_norm(&f2);
+
+    FP4_YYY_mul(&f3,&(x->b),&f2);
+    FP4_YYY_times_i(&f3);
+    FP4_YYY_mul(&(w->a),&f0,&(x->a));
+    FP4_YYY_add(&f3,&(w->a),&f3);
+    FP4_YYY_mul(&(w->c),&f1,&(x->c));
+    FP4_YYY_times_i(&(w->c));
+
+    FP4_YYY_add(&f3,&(w->c),&f3);
+    FP4_YYY_norm(&f3);
+
+    FP4_YYY_inv(&f3,&f3);
+
+    FP4_YYY_mul(&(w->a),&f0,&f3);
+    FP4_YYY_mul(&(w->b),&f1,&f3);
+    FP4_YYY_mul(&(w->c),&f2,&f3);
+
+}
+
+/* constant time powering by small integer of max length bts */
+
+void FP12_YYY_pinpow(FP12_YYY *r,int e,int bts)
+{
+    int i,b;
+    FP12_YYY R[2];
+
+    FP12_YYY_one(&R[0]);
+    FP12_YYY_copy(&R[1],r);
+
+    for (i=bts-1; i>=0; i--)
+    {
+        b=(e>>i)&1;
+        FP12_YYY_mul(&R[1-b],&R[b]);
+        FP12_YYY_usqr(&R[b],&R[b]);
+    }
+    FP12_YYY_copy(r,&R[0]);
+}
+
+/* Compressed powering of unitary elements y=x^(e mod r) */
+
+void FP12_YYY_compow(FP4_YYY *c,FP12_YYY *x,BIG_XXX e,BIG_XXX r)
+{
+    FP12_YYY g1,g2;
+    FP4_YYY cp,cpm1,cpm2;
+    FP2_YYY f;
+    BIG_XXX q,a,b,m;
+
+    BIG_XXX_rcopy(a,Fra_YYY);
+    BIG_XXX_rcopy(b,Frb_YYY);
+    FP2_YYY_from_BIGs(&f,a,b);
+
+    BIG_XXX_rcopy(q,Modulus_YYY);
+
+    FP12_YYY_copy(&g1,x);
+    FP12_YYY_copy(&g2,x);
+
+    BIG_XXX_copy(m,q);
+    BIG_XXX_mod(m,r);
+
+    BIG_XXX_copy(a,e);
+    BIG_XXX_mod(a,m);
+
+    BIG_XXX_copy(b,e);
+    BIG_XXX_sdiv(b,m);
+
+    FP12_YYY_trace(c,&g1);
+
+    if (BIG_XXX_iszilch(b))
+    {
+        FP4_YYY_xtr_pow(c,c,e);
+        return;
+    }
+
+
+    FP12_YYY_frob(&g2,&f);
+    FP12_YYY_trace(&cp,&g2);
+
+    FP12_YYY_conj(&g1,&g1);
+    FP12_YYY_mul(&g2,&g1);
+    FP12_YYY_trace(&cpm1,&g2);
+    FP12_YYY_mul(&g2,&g1);
+    FP12_YYY_trace(&cpm2,&g2);
+
+    FP4_YYY_xtr_pow2(c,&cp,c,&cpm1,&cpm2,a,b);
+
+}
+
+
+/* SU= 528 */
+/* set r=a^b */
+/* Note this is simple square and multiply, so not side-channel safe */
+
+void FP12_YYY_pow(FP12_YYY *r,FP12_YYY *a,BIG_XXX b)
+{
+    FP12_YYY w,sf;
+    BIG_XXX b1,b3;
+    int i,nb,bt;
+	BIG_XXX_copy(b1,b);
+    BIG_XXX_norm(b1);
+    BIG_XXX_pmul(b3,b1,3);
+    BIG_XXX_norm(b3);
+
+	FP12_YYY_copy(&sf,a);
+	FP12_YYY_norm(&sf);
+    FP12_YYY_copy(&w,&sf);
+
+
+    nb=BIG_XXX_nbits(b3);
+    for (i=nb-2; i>=1; i--)
+    {
+        FP12_YYY_usqr(&w,&w);
+        bt=BIG_XXX_bit(b3,i)-BIG_XXX_bit(b1,i);
+        if (bt==1)
+            FP12_YYY_mul(&w,&sf);
+        if (bt==-1)
+        {
+            FP12_YYY_conj(&sf,&sf);
+            FP12_YYY_mul(&w,&sf);
+            FP12_YYY_conj(&sf,&sf);
+        }
+    }
+
+    FP12_YYY_copy(r,&w);
+    FP12_YYY_reduce(r);
+
+    /*
+        while(1)
+        {
+            bt=BIG_XXX_parity(z);
+            BIG_XXX_shr(z,1);
+            if (bt)
+                FP12_YYY_mul(r,&w);
+            if (BIG_XXX_comp(z,zilch)==0) break;
+            FP12_YYY_usqr(&w,&w);
+        }
+
+        FP12_YYY_reduce(r); */
+}
+
+/* p=q0^u0.q1^u1.q2^u2.q3^u3 */
+/* Side channel attack secure */
+// Bos & Costello https://eprint.iacr.org/2013/458.pdf
+// Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
+
+void FP12_YYY_pow4(FP12_YYY *p,FP12_YYY *q,BIG_XXX u[4])
+{
+    int i,j,k,nb,pb,bt;
+	FP12_YYY g[8],r;
+	BIG_XXX t[4],mt;
+    sign8 w[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 s[NLEN_XXX*BASEBITS_XXX+1];
+
+    for (i=0; i<4; i++)
+        BIG_XXX_copy(t[i],u[i]);
+
+
+// Precomputed table
+    FP12_YYY_copy(&g[0],&q[0]); // q[0]
+    FP12_YYY_copy(&g[1],&g[0]);
+	FP12_YYY_mul(&g[1],&q[1]);	// q[0].q[1]
+    FP12_YYY_copy(&g[2],&g[0]);
+	FP12_YYY_mul(&g[2],&q[2]);	// q[0].q[2]
+	FP12_YYY_copy(&g[3],&g[1]);
+	FP12_YYY_mul(&g[3],&q[2]);	// q[0].q[1].q[2]
+	FP12_YYY_copy(&g[4],&g[0]);
+	FP12_YYY_mul(&g[4],&q[3]);  // q[0].q[3]
+	FP12_YYY_copy(&g[5],&g[1]);
+	FP12_YYY_mul(&g[5],&q[3]);	// q[0].q[1].q[3]
+	FP12_YYY_copy(&g[6],&g[2]);
+	FP12_YYY_mul(&g[6],&q[3]);	// q[0].q[2].q[3]
+	FP12_YYY_copy(&g[7],&g[3]);
+	FP12_YYY_mul(&g[7],&q[3]);	// q[0].q[1].q[2].q[3]
+
+// Make it odd
+	pb=1-BIG_XXX_parity(t[0]);
+	BIG_XXX_inc(t[0],pb);
+	BIG_XXX_norm(t[0]);
+
+// Number of bits
+    BIG_XXX_zero(mt);
+    for (i=0; i<4; i++)
+    {
+        BIG_XXX_or(mt,mt,t[i]);
+    }
+    nb=1+BIG_XXX_nbits(mt);
+
+// Sign pivot 
+	s[nb-1]=1;
+	for (i=0;i<nb-1;i++)
+	{
+        BIG_XXX_fshr(t[0],1);
+		s[i]=2*BIG_XXX_parity(t[0])-1;
+	}
+
+// Recoded exponent
+    for (i=0; i<nb; i++)
+    {
+		w[i]=0;
+		k=1;
+		for (j=1; j<4; j++)
+		{
+			bt=s[i]*BIG_XXX_parity(t[j]);
+			BIG_XXX_fshr(t[j],1);
+
+			BIG_XXX_dec(t[j],(bt>>1));
+			BIG_XXX_norm(t[j]);
+			w[i]+=bt*k;
+			k*=2;
+        }
+    }		
+
+// Main loop
+	FP12_YYY_select(p,g,2*w[nb-1]+1);
+    for (i=nb-2; i>=0; i--)
+    {
+        FP12_YYY_select(&r,g,2*w[i]+s[i]);
+		FP12_YYY_usqr(p,p);
+        FP12_YYY_mul(p,&r);
+    }
+// apply correction
+	FP12_YYY_conj(&r,&q[0]);   
+	FP12_YYY_mul(&r,p);
+	FP12_YYY_cmove(p,&r,pb);
+
+	FP12_YYY_reduce(p);
+}
+
+/* p=q0^u0.q1^u1.q2^u2.q3^u3 */
+/* Timing attack secure, but not cache attack secure */
+/*
+void FP12_YYY_pow4(FP12_YYY *p,FP12_YYY *q,BIG_XXX u[4])
+{
+    int i,j,a[4],nb,m;
+    FP12_YYY g[8],c,s[2];
+    BIG_XXX t[4],mt;
+    sign8 w[NLEN_XXX*BASEBITS_XXX+1];
+
+    for (i=0; i<4; i++)
+        BIG_XXX_copy(t[i],u[i]);
+
+    FP12_YYY_copy(&g[0],&q[0]);
+    FP12_YYY_conj(&s[0],&q[1]);
+    FP12_YYY_mul(&g[0],&s[0]);  // P/Q 
+    FP12_YYY_copy(&g[1],&g[0]);
+    FP12_YYY_copy(&g[2],&g[0]);
+    FP12_YYY_copy(&g[3],&g[0]);
+    FP12_YYY_copy(&g[4],&q[0]);
+    FP12_YYY_mul(&g[4],&q[1]);  // P*Q 
+    FP12_YYY_copy(&g[5],&g[4]);
+    FP12_YYY_copy(&g[6],&g[4]);
+    FP12_YYY_copy(&g[7],&g[4]);
+
+    FP12_YYY_copy(&s[1],&q[2]);
+    FP12_YYY_conj(&s[0],&q[3]);
+    FP12_YYY_mul(&s[1],&s[0]);       // R/S 
+    FP12_YYY_conj(&s[0],&s[1]);
+    FP12_YYY_mul(&g[1],&s[0]);
+    FP12_YYY_mul(&g[2],&s[1]);
+    FP12_YYY_mul(&g[5],&s[0]);
+    FP12_YYY_mul(&g[6],&s[1]);
+    FP12_YYY_copy(&s[1],&q[2]);
+    FP12_YYY_mul(&s[1],&q[3]);      // R*S 
+    FP12_YYY_conj(&s[0],&s[1]);
+    FP12_YYY_mul(&g[0],&s[0]);
+    FP12_YYY_mul(&g[3],&s[1]);
+    FP12_YYY_mul(&g[4],&s[0]);
+    FP12_YYY_mul(&g[7],&s[1]);
+
+    // if power is even add 1 to power, and add q to correction 
+    FP12_YYY_one(&c);
+
+    BIG_XXX_zero(mt);
+    for (i=0; i<4; i++)
+    {
+        if (BIG_XXX_parity(t[i])==0)
+        {
+            BIG_XXX_inc(t[i],1);
+            BIG_XXX_norm(t[i]);
+            FP12_YYY_mul(&c,&q[i]);
+        }
+        BIG_XXX_add(mt,mt,t[i]);
+        BIG_XXX_norm(mt);
+    }
+
+    FP12_YYY_conj(&c,&c);
+    nb=1+BIG_XXX_nbits(mt);
+
+    // convert exponent to signed 1-bit window 
+    for (j=0; j<nb; j++)
+    {
+        for (i=0; i<4; i++)
+        {
+            a[i]=BIG_XXX_lastbits(t[i],2)-2;
+            BIG_XXX_dec(t[i],a[i]);
+            BIG_XXX_norm(t[i]);
+            BIG_XXX_fshr(t[i],1);
+        }
+        w[j]=8*a[0]+4*a[1]+2*a[2]+a[3];
+    }
+    w[nb]=8*BIG_XXX_lastbits(t[0],2)+4*BIG_XXX_lastbits(t[1],2)+2*BIG_XXX_lastbits(t[2],2)+BIG_XXX_lastbits(t[3],2);
+    FP12_YYY_copy(p,&g[(w[nb]-1)/2]);
+
+    for (i=nb-1; i>=0; i--)
+    {
+        m=w[i]>>7;
+        j=(w[i]^m)-m;  // j=abs(w[i]) 
+        j=(j-1)/2;
+        FP12_YYY_copy(&s[0],&g[j]);
+        FP12_YYY_conj(&s[1],&g[j]);
+        FP12_YYY_usqr(p,p);
+        FP12_YYY_mul(p,&s[m&1]);
+    }
+    FP12_YYY_mul(p,&c); // apply correction 
+    FP12_YYY_reduce(p);
+}
+*/
+/* Set w=w^p using Frobenius */
+/* SU= 160 */
+void FP12_YYY_frob(FP12_YYY *w,FP2_YYY *f)
+{
+    FP2_YYY f2,f3;
+    FP2_YYY_sqr(&f2,f);     /* f2=f^2 */
+    FP2_YYY_mul(&f3,&f2,f); /* f3=f^3 */
+
+    FP4_YYY_frob(&(w->a),&f3);
+    FP4_YYY_frob(&(w->b),&f3);
+    FP4_YYY_frob(&(w->c),&f3);
+
+    FP4_YYY_pmul(&(w->b),&(w->b),f);
+    FP4_YYY_pmul(&(w->c),&(w->c),&f2);
+}
+
+/* SU= 8 */
+/* normalise all components of w */
+void FP12_YYY_norm(FP12_YYY *w)
+{
+    FP4_YYY_norm(&(w->a));
+    FP4_YYY_norm(&(w->b));
+    FP4_YYY_norm(&(w->c));
+}
+
+/* SU= 8 */
+/* reduce all components of w */
+void FP12_YYY_reduce(FP12_YYY *w)
+{
+    FP4_YYY_reduce(&(w->a));
+    FP4_YYY_reduce(&(w->b));
+    FP4_YYY_reduce(&(w->c));
+}
+
+/* trace function w=trace(x) */
+/* SU= 8 */
+void FP12_YYY_trace(FP4_YYY *w,FP12_YYY *x)
+{
+    FP4_YYY_imul(w,&(x->a),3);
+    FP4_YYY_reduce(w);
+}
+
+/* SU= 8 */
+/* Output w in hex */
+void FP12_YYY_output(FP12_YYY *w)
+{
+    printf("[");
+    FP4_YYY_output(&(w->a));
+    printf(",");
+    FP4_YYY_output(&(w->b));
+    printf(",");
+    FP4_YYY_output(&(w->c));
+    printf("]");
+}
+
+/* SU= 64 */
+/* Convert g to octet string w */
+void FP12_YYY_toOctet(octet *W,FP12_YYY *g)
+{
+    BIG_XXX a;
+    W->len=12*MODBYTES_XXX;
+
+    FP_YYY_redc(a,&(g->a.a.a));
+    BIG_XXX_toBytes(&(W->val[0]),a);
+    FP_YYY_redc(a,&(g->a.a.b));
+    BIG_XXX_toBytes(&(W->val[MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->a.b.a));
+    BIG_XXX_toBytes(&(W->val[2*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->a.b.b));
+    BIG_XXX_toBytes(&(W->val[3*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->b.a.a));
+    BIG_XXX_toBytes(&(W->val[4*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->b.a.b));
+    BIG_XXX_toBytes(&(W->val[5*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->b.b.a));
+    BIG_XXX_toBytes(&(W->val[6*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->b.b.b));
+    BIG_XXX_toBytes(&(W->val[7*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->c.a.a));
+    BIG_XXX_toBytes(&(W->val[8*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->c.a.b));
+    BIG_XXX_toBytes(&(W->val[9*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->c.b.a));
+    BIG_XXX_toBytes(&(W->val[10*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->c.b.b));
+    BIG_XXX_toBytes(&(W->val[11*MODBYTES_XXX]),a);
+}
+
+/* SU= 24 */
+/* Restore g from octet string w */
+void FP12_YYY_fromOctet(FP12_YYY *g,octet *W)
+{
+    BIG_XXX b;
+    BIG_XXX_fromBytes(b,&W->val[0]);
+    FP_YYY_nres(&(g->a.a.a),b);
+    BIG_XXX_fromBytes(b,&W->val[MODBYTES_XXX]);
+    FP_YYY_nres(&(g->a.a.b),b);
+    BIG_XXX_fromBytes(b,&W->val[2*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->a.b.a),b);
+    BIG_XXX_fromBytes(b,&W->val[3*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->a.b.b),b);
+    BIG_XXX_fromBytes(b,&W->val[4*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->b.a.a),b);
+    BIG_XXX_fromBytes(b,&W->val[5*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->b.a.b),b);
+    BIG_XXX_fromBytes(b,&W->val[6*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->b.b.a),b);
+    BIG_XXX_fromBytes(b,&W->val[7*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->b.b.b),b);
+    BIG_XXX_fromBytes(b,&W->val[8*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->c.a.a),b);
+    BIG_XXX_fromBytes(b,&W->val[9*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->c.a.b),b);
+    BIG_XXX_fromBytes(b,&W->val[10*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->c.b.a),b);
+    BIG_XXX_fromBytes(b,&W->val[11*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->c.b.b),b);
+}
+
+/* Move b to a if d=1 */
+void FP12_YYY_cmove(FP12_YYY *f,FP12_YYY *g,int d)
+{
+    FP4_YYY_cmove(&(f->a),&(g->a),d);
+    FP4_YYY_cmove(&(f->b),&(g->b),d);
+    FP4_YYY_cmove(&(f->c),&(g->c),d);
+}
+
+
+/*
+int main(){
+		FP2_YYY f,w0,w1;
+		FP4_YYY t0,t1,t2;
+		FP12_YYY w,t,lv;
+		BIG_XXX a,b;
+		BIG_XXX p;
+
+		//Test w^(P^4) = w mod p^2
+//		BIG_XXX_randomnum(a);
+//		BIG_XXX_randomnum(b);
+//		BIG_XXX_mod(a,Modulus); BIG_XXX_mod(b,Modulus);
+	BIG_XXX_zero(a); BIG_XXX_zero(b); BIG_XXX_inc(a,1); BIG_XXX_inc(b,2); FP_YYY_nres(a); FP_YYY_nres(b);
+		FP2_YYY_from_zps(&w0,a,b);
+
+//		BIG_XXX_randomnum(a); BIG_XXX_randomnum(b);
+//		BIG_XXX_mod(a,Modulus); BIG_XXX_mod(b,Modulus);
+	BIG_XXX_zero(a); BIG_XXX_zero(b); BIG_XXX_inc(a,3); BIG_XXX_inc(b,4); FP_YYY_nres(a); FP_YYY_nres(b);
+		FP2_YYY_from_zps(&w1,a,b);
+
+		FP4_YYY_from_FP2s(&t0,&w0,&w1);
+		FP4_YYY_reduce(&t0);
+
+//		BIG_XXX_randomnum(a);
+//		BIG_XXX_randomnum(b);
+//		BIG_XXX_mod(a,Modulus); BIG_XXX_mod(b,Modulus);
+		BIG_XXX_zero(a); BIG_XXX_zero(b); BIG_XXX_inc(a,5); BIG_XXX_inc(b,6); FP_YYY_nres(a); FP_YYY_nres(b);
+		FP2_YYY_from_zps(&w0,a,b);
+
+//		BIG_XXX_randomnum(a); BIG_XXX_randomnum(b);
+//		BIG_XXX_mod(a,Modulus); BIG_XXX_mod(b,Modulus);
+
+		BIG_XXX_zero(a); BIG_XXX_zero(b); BIG_XXX_inc(a,7); BIG_XXX_inc(b,8); FP_YYY_nres(a); FP_YYY_nres(b);
+		FP2_YYY_from_zps(&w1,a,b);
+
+		FP4_YYY_from_FP2s(&t1,&w0,&w1);
+		FP4_YYY_reduce(&t1);
+
+//		BIG_XXX_randomnum(a);
+//		BIG_XXX_randomnum(b);
+//		BIG_XXX_mod(a,Modulus); BIG_XXX_mod(b,Modulus);
+		BIG_XXX_zero(a); BIG_XXX_zero(b); BIG_XXX_inc(a,9); BIG_XXX_inc(b,10); FP_YYY_nres(a); FP_YYY_nres(b);
+		FP2_YYY_from_zps(&w0,a,b);
+
+//		BIG_XXX_randomnum(a); BIG_XXX_randomnum(b);
+//		BIG_XXX_mod(a,Modulus); BIG_XXX_mod(b,Modulus);
+		BIG_XXX_zero(a); BIG_XXX_zero(b); BIG_XXX_inc(a,11); BIG_XXX_inc(b,12); FP_YYY_nres(a); FP_YYY_nres(b);
+		FP2_YYY_from_zps(&w1,a,b);
+
+		FP4_YYY_from_FP2s(&t2,&w0,&w1);
+		FP4_YYY_reduce(&t2);
+
+		FP12_YYY_from_FP4s(&w,&t0,&t1,&t2);
+
+		FP12_YYY_copy(&t,&w);
+
+		printf("w= ");
+		FP12_YYY_output(&w);
+		printf("\n");
+
+		BIG_XXX_rcopy(p,Modulus);
+		//BIG_XXX_zero(p); BIG_XXX_inc(p,7);
+
+		FP12_YYY_pow(&w,&w,p);
+
+		printf("w^p= ");
+		FP12_YYY_output(&w);
+		printf("\n");
+
+		FP2_YYY_gfc(&f,12);
+		FP12_YYY_frob(&t,&f);
+		printf("w^p= ");
+		FP12_YYY_output(&t);
+		printf("\n");
+
+//exit(0);
+
+		FP12_YYY_pow(&w,&w,p);
+		//printf("w^p^2= ");
+		//FP12_YYY_output(&w);
+		//printf("\n");
+		FP12_YYY_pow(&w,&w,p);
+		//printf("w^p^3= ");
+		//FP12_YYY_output(&w);
+		//printf("\n");
+		FP12_YYY_pow(&w,&w,p);
+		FP12_YYY_pow(&w,&w,p);
+		FP12_YYY_pow(&w,&w,p);
+		printf("w^p^6= ");
+		FP12_YYY_output(&w);
+		printf("\n");
+		FP12_YYY_pow(&w,&w,p);
+		FP12_YYY_pow(&w,&w,p);
+		printf("w^p^8= ");
+		FP12_YYY_output(&w);
+		printf("\n");
+		FP12_YYY_pow(&w,&w,p);
+		FP12_YYY_pow(&w,&w,p);
+		FP12_YYY_pow(&w,&w,p);
+		printf("w^p^11= ");
+		FP12_YYY_output(&w);
+		printf("\n");
+
+	//	BIG_XXX_zero(p); BIG_XXX_inc(p,7); BIG_XXX_norm(p);
+		FP12_YYY_pow(&w,&w,p);
+
+		printf("w^p12= ");
+		FP12_YYY_output(&w);
+		printf("\n");
+//exit(0);
+
+		FP12_YYY_inv(&t,&w);
+		printf("1/w mod p^4 = ");
+		FP12_YYY_output(&t);
+		printf("\n");
+
+		FP12_YYY_inv(&w,&t);
+		printf("1/(1/w) mod p^4 = ");
+		FP12_YYY_output(&w);
+		printf("\n");
+
+
+
+	FP12_YYY_inv(&lv,&w);
+//printf("w= "); FP12_YYY_output(&w); printf("\n");
+	FP12_YYY_conj(&w,&w);
+//printf("w= "); FP12_YYY_output(&w); printf("\n");
+//exit(0);
+	FP12_YYY_mul(&w,&w,&lv);
+//printf("w= "); FP12_YYY_output(&w); printf("\n");
+	FP12_YYY_copy(&lv,&w);
+	FP12_YYY_frob(&w,&f);
+	FP12_YYY_frob(&w,&f);
+	FP12_YYY_mul(&w,&w,&lv);
+
+//printf("w= "); FP12_YYY_output(&w); printf("\n");
+//exit(0);
+
+w.unitary=0;
+FP12_YYY_conj(&lv,&w);
+	printf("rx= "); FP12_YYY_output(&lv); printf("\n");
+FP12_YYY_inv(&lv,&w);
+	printf("ry= "); FP12_YYY_output(&lv); printf("\n");
+
+
+		return 0;
+}
+
+*/
diff --git a/version3/c/fp12.h b/version3/c/fp12.h
new file mode 100644
index 0000000..99fed17
--- /dev/null
+++ b/version3/c/fp12.h
@@ -0,0 +1,216 @@
+/*
+	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.
+*/
+
+/**
+ * @file fp12.h
+ * @author Mike Scott
+ * @brief FP12 Header File
+ *
+ */
+
+#ifndef FP12_YYY_H
+#define FP12_YYY_H
+
+#include "fp4_YYY.h"
+
+/**
+	@brief FP12 Structure - towered over three FP4
+*/
+
+typedef struct
+{
+    FP4_YYY a; /**< first part of FP12 */
+    FP4_YYY b; /**< second part of FP12 */
+    FP4_YYY c; /**< third part of FP12 */
+} FP12_YYY;
+
+extern const BIG_XXX Fra_YYY; /**< real part of BN curve Frobenius Constant */
+extern const BIG_XXX Frb_YYY; /**< imaginary part of BN curve Frobenius Constant */
+
+/* FP12 prototypes */
+/**	@brief Tests for FP12 equal to zero
+ *
+	@param x FP12 number to be tested
+	@return 1 if zero, else returns 0
+ */
+extern int FP12_YYY_iszilch(FP12_YYY *x);
+/**	@brief Tests for FP12 equal to unity
+ *
+	@param x FP12 number to be tested
+	@return 1 if unity, else returns 0
+ */
+extern int FP12_YYY_isunity(FP12_YYY *x);
+/**	@brief Copy FP12 to another FP12
+ *
+	@param x FP12 instance, on exit = y
+	@param y FP12 instance to be copied
+ */
+extern void FP12_YYY_copy(FP12_YYY *x,FP12_YYY *y);
+/**	@brief Set FP12 to unity
+ *
+	@param x FP12 instance to be set to one
+ */
+extern void FP12_YYY_one(FP12_YYY *x);
+/**	@brief Tests for equality of two FP12s
+ *
+	@param x FP12 instance to be compared
+	@param y FP12 instance to be compared
+	@return 1 if x=y, else returns 0
+ */
+extern int FP12_YYY_equals(FP12_YYY *x,FP12_YYY *y);
+/**	@brief Conjugation of FP12
+ *
+	If y=(a,b,c) (where a,b,c are its three FP4 components) on exit x=(conj(a),-conj(b),conj(c))
+	@param x FP12 instance, on exit = conj(y)
+	@param y FP12 instance
+ */
+extern void FP12_YYY_conj(FP12_YYY *x,FP12_YYY *y);
+/**	@brief Initialise FP12 from single FP4
+ *
+	Sets first FP4 component of an FP12, other components set to zero
+	@param x FP12 instance to be initialised
+	@param a FP4 to form first part of FP4
+ */
+extern void FP12_YYY_from_FP4(FP12_YYY *x,FP4_YYY *a);
+/**	@brief Initialise FP12 from three FP4s
+ *
+	@param x FP12 instance to be initialised
+	@param a FP4 to form first part of FP12
+	@param b FP4 to form second part of FP12
+	@param c FP4 to form third part of FP12
+ */
+extern void FP12_YYY_from_FP4s(FP12_YYY *x,FP4_YYY *a,FP4_YYY* b,FP4_YYY *c);
+/**	@brief Fast Squaring of an FP12 in "unitary" form
+ *
+	@param x FP12 instance, on exit = y^2
+	@param y FP4 instance, must be unitary
+ */
+extern void FP12_YYY_usqr(FP12_YYY *x,FP12_YYY *y);
+/**	@brief Squaring an FP12
+ *
+	@param x FP12 instance, on exit = y^2
+	@param y FP12 instance
+ */
+extern void FP12_YYY_sqr(FP12_YYY *x,FP12_YYY *y);
+/**	@brief Fast multiplication of an FP12 by an FP12 that arises from an ATE pairing line function
+ *
+	Here the multiplier has a special form that can be exploited
+	@param x FP12 instance, on exit = x*y
+	@param y FP12 instance, of special form
+	@param t D_TYPE or M_TYPE twist
+ */
+extern void FP12_YYY_smul(FP12_YYY *x,FP12_YYY *y,int t);
+/**	@brief Multiplication of two FP12s
+ *
+	@param x FP12 instance, on exit = x*y
+	@param y FP12 instance, the multiplier
+ */
+extern void FP12_YYY_mul(FP12_YYY *x,FP12_YYY *y);
+/**	@brief Inverting an FP12
+ *
+	@param x FP12 instance, on exit = 1/y
+	@param y FP12 instance
+ */
+extern void FP12_YYY_inv(FP12_YYY *x,FP12_YYY *y);
+/**	@brief Raises an FP12 to the power of a BIG
+ *
+	@param r FP12 instance, on exit = y^b
+	@param x FP12 instance
+	@param b BIG number
+ */
+extern void FP12_YYY_pow(FP12_YYY *r,FP12_YYY *x,BIG_XXX b);
+/**	@brief Raises an FP12 instance x to a small integer power, side-channel resistant
+ *
+	@param x FP12 instance, on exit = x^i
+	@param i small integer exponent
+	@param b maximum number of bits in exponent
+ */
+extern void FP12_YYY_pinpow(FP12_YYY *x,int i,int b);
+
+/**	@brief Raises an FP12 instance x to a BIG power, compressed to FP4
+ *
+	@param c FP4 instance, on exit = x^(e mod r) as FP4
+	@param x FP12 input
+	@param e BIG exponent
+	@param r BIG group order
+ */
+extern void FP12_YYY_compow(FP4_YYY *c,FP12_YYY *x,BIG_XXX e,BIG_XXX r);
+
+/**	@brief Calculate x[0]^b[0].x[1]^b[1].x[2]^b[2].x[3]^b[3], side-channel resistant
+ *
+	@param r FP12 instance, on exit = x[0]^b[0].x[1]^b[1].x[2]^b[2].x[3]^b[3]
+	@param x FP12 array with 4 FP12s
+	@param b BIG array of 4 exponents
+ */
+extern void FP12_YYY_pow4(FP12_YYY *r,FP12_YYY *x,BIG_XXX *b);
+/**	@brief Raises an FP12 to the power of the internal modulus p, using the Frobenius
+ *
+	@param x FP12 instance, on exit = x^p
+	@param f FP2 precalculated Frobenius constant
+ */
+extern void FP12_YYY_frob(FP12_YYY *x,FP2_YYY *f);
+/**	@brief Reduces all components of possibly unreduced FP12 mod Modulus
+ *
+	@param x FP12 instance, on exit reduced mod Modulus
+ */
+extern void FP12_YYY_reduce(FP12_YYY *x);
+/**	@brief Normalises the components of an FP12
+ *
+	@param x FP12 instance to be normalised
+ */
+extern void FP12_YYY_norm(FP12_YYY *x);
+/**	@brief Formats and outputs an FP12 to the console
+ *
+	@param x FP12 instance to be printed
+ */
+extern void FP12_YYY_output(FP12_YYY *x);
+/**	@brief Formats and outputs an FP12 instance to an octet string
+ *
+	Serializes the components of an FP12 to big-endian base 256 form.
+	@param S output octet string
+	@param x FP12 instance to be converted to an octet string
+ */
+extern void FP12_YYY_toOctet(octet *S,FP12_YYY *x);
+/**	@brief Creates an FP12 instance from an octet string
+ *
+	De-serializes the components of an FP12 to create an FP12 from big-endian base 256 components.
+	@param x FP12 instance to be created from an octet string
+	@param S input octet string
+
+ */
+extern void FP12_YYY_fromOctet(FP12_YYY *x,octet *S);
+/**	@brief Calculate the trace of an FP12
+ *
+	@param t FP4 trace of x, on exit = tr(x)
+	@param x FP12 instance
+
+ */
+extern void FP12_YYY_trace(FP4_YYY *t,FP12_YYY *x);
+
+/**	@brief Conditional copy of FP12 number
+ *
+	Conditionally copies second parameter to the first (without branching)
+	@param x FP12 instance, set to y if s!=0
+	@param y another FP12 instance
+	@param s copy only takes place if not equal to 0
+ */
+extern void FP12_YYY_cmove(FP12_YYY *x,FP12_YYY *y,int s);
+
+
+#endif
diff --git a/version3/c/fp16.c b/version3/c/fp16.c
new file mode 100644
index 0000000..623e87b
--- /dev/null
+++ b/version3/c/fp16.c
@@ -0,0 +1,693 @@
+/*
+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.
+*/
+
+/* AMCL Fp^8 functions */
+
+/* FP16 elements are of the form a+ib, where i is sqrt(sqrt(-1+sqrt(-1))) */
+
+#include "fp16_YYY.h"
+
+
+/* test x==0 ? */
+int FP16_YYY_iszilch(FP16_YYY *x)
+{
+    if (FP8_YYY_iszilch(&(x->a)) && FP8_YYY_iszilch(&(x->b))) return 1;
+    return 0;
+}
+
+/* test x==1 ? */
+int FP16_YYY_isunity(FP16_YYY *x)
+{
+    if (FP8_YYY_isunity(&(x->a)) && FP8_YYY_iszilch(&(x->b))) return 1;
+    return 0;
+}
+
+/* test is w real? That is in a+ib test b is zero */
+int FP16_YYY_isreal(FP16_YYY *w)
+{
+    return FP8_YYY_iszilch(&(w->b));
+}
+
+/* return 1 if x==y, else 0 */
+int FP16_YYY_equals(FP16_YYY *x,FP16_YYY *y)
+{
+    if (FP8_YYY_equals(&(x->a),&(y->a)) && FP8_YYY_equals(&(x->b),&(y->b)))
+        return 1;
+    return 0;
+}
+
+/* set FP16 from two FP8s */
+void FP16_YYY_from_FP8s(FP16_YYY *w,FP8_YYY * x,FP8_YYY* y)
+{
+    FP8_YYY_copy(&(w->a), x);
+    FP8_YYY_copy(&(w->b), y);
+}
+
+/* set FP16 from FP8 */
+void FP16_YYY_from_FP8(FP16_YYY *w,FP8_YYY *x)
+{
+    FP8_YYY_copy(&(w->a), x);
+    FP8_YYY_zero(&(w->b));
+}
+
+/* set high part of FP16 from FP8 */
+void FP16_YYY_from_FP8H(FP16_YYY *w,FP8_YYY *x)
+{
+    FP8_YYY_copy(&(w->b), x);
+    FP8_YYY_zero(&(w->a));
+}
+
+/* FP16 copy w=x */
+void FP16_YYY_copy(FP16_YYY *w,FP16_YYY *x)
+{
+    if (w==x) return;
+    FP8_YYY_copy(&(w->a), &(x->a));
+    FP8_YYY_copy(&(w->b), &(x->b));
+}
+
+/* FP16 w=0 */
+void FP16_YYY_zero(FP16_YYY *w)
+{
+    FP8_YYY_zero(&(w->a));
+    FP8_YYY_zero(&(w->b));
+}
+
+/* FP16 w=1 */
+void FP16_YYY_one(FP16_YYY *w)
+{
+    FP8_YYY_one(&(w->a));
+    FP8_YYY_zero(&(w->b));
+}
+
+/* Set w=-x */
+void FP16_YYY_neg(FP16_YYY *w,FP16_YYY *x)
+{
+    /* Just one field neg */
+    FP8_YYY m,t;
+	FP16_YYY_norm(x);
+    FP8_YYY_add(&m,&(x->a),&(x->b));
+	FP8_YYY_norm(&m);
+    FP8_YYY_neg(&m,&m);
+    FP8_YYY_add(&t,&m,&(x->b));
+    FP8_YYY_add(&(w->b),&m,&(x->a));
+    FP8_YYY_copy(&(w->a),&t);
+	FP16_YYY_norm(w);
+}
+
+/* Set w=conj(x) */
+void FP16_YYY_conj(FP16_YYY *w,FP16_YYY *x)
+{
+    FP8_YYY_copy(&(w->a), &(x->a));
+    FP8_YYY_neg(&(w->b), &(x->b));
+	FP16_YYY_norm(w);
+}
+
+/* Set w=-conj(x) */
+void FP16_YYY_nconj(FP16_YYY *w,FP16_YYY *x)
+{
+    FP8_YYY_copy(&(w->b),&(x->b));
+    FP8_YYY_neg(&(w->a), &(x->a));
+	FP16_YYY_norm(w);
+}
+
+/* Set w=x+y */
+void FP16_YYY_add(FP16_YYY *w,FP16_YYY *x,FP16_YYY *y)
+{
+    FP8_YYY_add(&(w->a), &(x->a), &(y->a));
+    FP8_YYY_add(&(w->b), &(x->b), &(y->b));
+}
+
+/* Set w=x-y */
+/* Input y MUST be normed */
+void FP16_YYY_sub(FP16_YYY *w,FP16_YYY *x,FP16_YYY *y)
+{
+    FP16_YYY my;
+
+    FP16_YYY_neg(&my, y);
+    FP16_YYY_add(w, x, &my);
+
+}
+
+/* reduce all components of w mod Modulus */
+void FP16_YYY_reduce(FP16_YYY *w)
+{
+    FP8_YYY_reduce(&(w->a));
+    FP8_YYY_reduce(&(w->b));
+}
+
+/* normalise all elements of w */
+void FP16_YYY_norm(FP16_YYY *w)
+{
+    FP8_YYY_norm(&(w->a));
+    FP8_YYY_norm(&(w->b));
+}
+
+/* Set w=s*x, where s is FP8 */
+void FP16_YYY_pmul(FP16_YYY *w,FP16_YYY *x,FP8_YYY *s)
+{
+    FP8_YYY_mul(&(w->a),&(x->a),s);
+    FP8_YYY_mul(&(w->b),&(x->b),s);
+}
+
+/* Set w=s*x, where s is FP2 */
+void FP16_YYY_qmul(FP16_YYY *w,FP16_YYY *x,FP2_YYY *s)
+{
+    FP8_YYY_qmul(&(w->a),&(x->a),s);
+    FP8_YYY_qmul(&(w->b),&(x->b),s);
+}
+
+/* Set w=s*x, where s is int */
+void FP16_YYY_imul(FP16_YYY *w,FP16_YYY *x,int s)
+{
+    FP8_YYY_imul(&(w->a),&(x->a),s);
+    FP8_YYY_imul(&(w->b),&(x->b),s);
+}
+
+/* Set w=x^2 */
+/* Input MUST be normed  */
+void FP16_YYY_sqr(FP16_YYY *w,FP16_YYY *x)
+{
+    FP8_YYY t1,t2,t3;
+
+    FP8_YYY_mul(&t3,&(x->a),&(x->b)); /* norms x */
+    FP8_YYY_copy(&t2,&(x->b));
+    FP8_YYY_add(&t1,&(x->a),&(x->b));
+    FP8_YYY_times_i(&t2);
+
+    FP8_YYY_add(&t2,&(x->a),&t2);
+
+	FP8_YYY_norm(&t1);  // 2
+	FP8_YYY_norm(&t2);  // 2
+
+    FP8_YYY_mul(&(w->a),&t1,&t2);
+
+    FP8_YYY_copy(&t2,&t3);
+    FP8_YYY_times_i(&t2);
+
+    FP8_YYY_add(&t2,&t2,&t3);
+
+	FP8_YYY_norm(&t2);  // 2
+    FP8_YYY_neg(&t2,&t2);
+    FP8_YYY_add(&(w->a),&(w->a),&t2);  /* a=(a+b)(a+i^2.b)-i^2.ab-ab = a*a+ib*ib */
+    FP8_YYY_add(&(w->b),&t3,&t3);  /* b=2ab */
+
+    FP16_YYY_norm(w);
+}
+
+/* Set w=x*y */
+/* Inputs MUST be normed  */
+void FP16_YYY_mul(FP16_YYY *w,FP16_YYY *x,FP16_YYY *y)
+{
+
+    FP8_YYY t1,t2,t3,t4;
+    FP8_YYY_mul(&t1,&(x->a),&(y->a)); 
+    FP8_YYY_mul(&t2,&(x->b),&(y->b)); 
+
+    FP8_YYY_add(&t3,&(y->b),&(y->a));
+    FP8_YYY_add(&t4,&(x->b),&(x->a));
+
+	FP8_YYY_norm(&t4); // 2
+	FP8_YYY_norm(&t3); // 2
+
+    FP8_YYY_mul(&t4,&t4,&t3); /* (xa+xb)(ya+yb) */
+
+	FP8_YYY_neg(&t3,&t1);  // 1
+	FP8_YYY_add(&t4,&t4,&t3);  //t4E=3
+    FP8_YYY_norm(&t4);
+
+	FP8_YYY_neg(&t3,&t2);  // 1
+	FP8_YYY_add(&(w->b),&t4,&t3); //wbE=3
+
+    FP8_YYY_times_i(&t2);
+    FP8_YYY_add(&(w->a),&t2,&t1);
+
+    FP16_YYY_norm(w);
+}
+
+/* output FP16 in format [a,b] */
+void FP16_YYY_output(FP16_YYY *w)
+{
+    printf("[");
+    FP8_YYY_output(&(w->a));
+    printf(",");
+    FP8_YYY_output(&(w->b));
+    printf("]");
+}
+
+void FP16_YYY_rawoutput(FP16_YYY *w)
+{
+    printf("[");
+    FP8_YYY_rawoutput(&(w->a));
+    printf(",");
+    FP8_YYY_rawoutput(&(w->b));
+    printf("]");
+}
+
+/* Set w=1/x */
+void FP16_YYY_inv(FP16_YYY *w,FP16_YYY *x)
+{
+    FP8_YYY t1,t2;
+    FP8_YYY_sqr(&t1,&(x->a));
+    FP8_YYY_sqr(&t2,&(x->b));
+    FP8_YYY_times_i(&t2);
+	FP8_YYY_norm(&t2);
+
+    FP8_YYY_sub(&t1,&t1,&t2);
+	FP8_YYY_norm(&t1);
+
+    FP8_YYY_inv(&t1,&t1);
+
+    FP8_YYY_mul(&(w->a),&t1,&(x->a));
+    FP8_YYY_neg(&t1,&t1);
+	FP8_YYY_norm(&t1);
+    FP8_YYY_mul(&(w->b),&t1,&(x->b));
+}
+
+/* w*=i where i = sqrt(sqrt(-1+sqrt(-1))) */
+void FP16_YYY_times_i(FP16_YYY *w)
+{
+	FP8_YYY s,t;
+	FP8_YYY_copy(&s,&(w->b));
+	FP8_YYY_copy(&t,&(w->a));
+	FP8_YYY_times_i(&s);
+	FP8_YYY_copy(&(w->a),&s);
+	FP8_YYY_copy(&(w->b),&t);
+	FP16_YYY_norm(w);
+}
+
+void FP16_YYY_times_i2(FP16_YYY *w)
+{
+	FP8_YYY_times_i(&(w->a));
+	FP8_YYY_times_i(&(w->b));
+}
+
+void FP16_YYY_times_i4(FP16_YYY *w)
+{
+	FP8_YYY_times_i2(&(w->a));
+	FP8_YYY_times_i2(&(w->b));
+}
+
+/* Set w=w^p using Frobenius */
+void FP16_YYY_frob(FP16_YYY *w,FP2_YYY *f)
+{ // f=(i+1)^(p-3)/8
+	FP2_YYY ff;
+
+	FP2_YYY_sqr(&ff,f);  // (i+1)^(p-3)/4
+	FP2_YYY_norm(&ff);
+
+	FP8_YYY_frob(&(w->a),&ff);
+	FP8_YYY_frob(&(w->b),&ff);
+
+	FP8_YYY_qmul(&(w->b),&(w->b),f);  // times (1+i)^(p-3)/8
+	FP8_YYY_times_i(&(w->b));		// (i+1)^(p-1)/8
+}
+
+/* Set r=a^b mod m */
+void FP16_YYY_pow(FP16_YYY *r,FP16_YYY * a,BIG_XXX b)
+{
+    FP16_YYY w;
+    BIG_XXX z,zilch;
+    int bt;
+
+    BIG_XXX_zero(zilch);
+
+    BIG_XXX_copy(z,b);
+    FP16_YYY_copy(&w,a);
+    FP16_YYY_one(r);
+    BIG_XXX_norm(z);
+    while(1)
+    {
+        bt=BIG_XXX_parity(z);
+        BIG_XXX_shr(z,1);
+        if (bt) FP16_YYY_mul(r,r,&w);
+        if (BIG_XXX_comp(z,zilch)==0) break;
+        FP16_YYY_sqr(&w,&w);
+    }
+    FP16_YYY_reduce(r);
+}
+
+/* Move b to a if d=1 */
+void FP16_YYY_cmove(FP16_YYY *f,FP16_YYY *g,int d)
+{
+    FP8_YYY_cmove(&(f->a),&(g->a),d);
+    FP8_YYY_cmove(&(f->b),&(g->b),d);
+}
+
+#if CURVE_SECURITY_ZZZ == 256
+
+/* XTR xtr_a function */
+void FP16_YYY_xtr_A(FP16_YYY *r,FP16_YYY *w,FP16_YYY *x,FP16_YYY *y,FP16_YYY *z)
+{
+    FP16_YYY t1,t2;
+
+    FP16_YYY_copy(r,x);
+    FP16_YYY_sub(&t1,w,y);
+	FP16_YYY_norm(&t1);
+    FP16_YYY_pmul(&t1,&t1,&(r->a));
+    FP16_YYY_add(&t2,w,y);
+	FP16_YYY_norm(&t2);
+    FP16_YYY_pmul(&t2,&t2,&(r->b));
+    FP16_YYY_times_i(&t2);
+
+    FP16_YYY_add(r,&t1,&t2);
+    FP16_YYY_add(r,r,z);
+
+    FP16_YYY_reduce(r);
+}
+
+/* XTR xtr_d function */
+void FP16_YYY_xtr_D(FP16_YYY *r,FP16_YYY *x)
+{
+    FP16_YYY w;
+    FP16_YYY_copy(r,x);
+    FP16_YYY_conj(&w,r);
+    FP16_YYY_add(&w,&w,&w);
+    FP16_YYY_sqr(r,r);
+	FP16_YYY_norm(&w);
+    FP16_YYY_sub(r,r,&w);
+    FP16_YYY_reduce(r);    /* reduce here as multiple calls trigger automatic reductions */
+}
+
+/* r=x^n using XTR method on traces of FP12s */
+void FP16_YYY_xtr_pow(FP16_YYY *r,FP16_YYY *x,BIG_XXX n)
+{
+    int i,par,nb;
+    BIG_XXX v;
+    FP2_YYY w2;
+	FP4_YYY w4;
+	FP8_YYY w8;
+    FP16_YYY t,a,b,c,sf;
+
+    BIG_XXX_zero(v);
+    BIG_XXX_inc(v,3);
+	BIG_XXX_norm(v);
+    FP2_YYY_from_BIG(&w2,v);
+    FP4_YYY_from_FP2(&w4,&w2);
+	FP8_YYY_from_FP4(&w8,&w4);
+    FP16_YYY_from_FP8(&a,&w8);
+	FP16_YYY_copy(&sf,x);
+	FP16_YYY_norm(&sf);
+	FP16_YYY_copy(&b,&sf);
+    FP16_YYY_xtr_D(&c,&sf);
+
+
+    par=BIG_XXX_parity(n);
+    BIG_XXX_copy(v,n);
+    BIG_XXX_norm(v);
+    BIG_XXX_shr(v,1);
+    if (par==0)
+    {
+        BIG_XXX_dec(v,1);
+        BIG_XXX_norm(v);
+    }
+
+    nb=BIG_XXX_nbits(v);
+    for (i=nb-1; i>=0; i--)
+    {
+        if (!BIG_XXX_bit(v,i))
+        {
+            FP16_YYY_copy(&t,&b);
+            FP16_YYY_conj(&sf,&sf);
+            FP16_YYY_conj(&c,&c);
+            FP16_YYY_xtr_A(&b,&a,&b,&sf,&c);
+            FP16_YYY_conj(&sf,&sf);
+            FP16_YYY_xtr_D(&c,&t);
+            FP16_YYY_xtr_D(&a,&a);
+        }
+        else
+        {
+            FP16_YYY_conj(&t,&a);
+            FP16_YYY_xtr_D(&a,&b);
+            FP16_YYY_xtr_A(&b,&c,&b,&sf,&t);
+            FP16_YYY_xtr_D(&c,&c);
+        }
+    }
+
+    if (par==0) FP16_YYY_copy(r,&c);
+    else FP16_YYY_copy(r,&b);
+    FP16_YYY_reduce(r);
+}
+
+/* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */
+void FP16_YYY_xtr_pow2(FP16_YYY *r,FP16_YYY *ck,FP16_YYY *cl,FP16_YYY *ckml,FP16_YYY *ckm2l,BIG_XXX a,BIG_XXX b)
+{
+    int i,f2;
+    BIG_XXX d,e,w;
+    FP16_YYY t,cu,cv,cumv,cum2v;
+
+
+    BIG_XXX_copy(e,a);
+    BIG_XXX_copy(d,b);
+    BIG_XXX_norm(d);
+	BIG_XXX_norm(e);
+    FP16_YYY_copy(&cu,ck);
+    FP16_YYY_copy(&cv,cl);
+    FP16_YYY_copy(&cumv,ckml);
+    FP16_YYY_copy(&cum2v,ckm2l);
+
+    f2=0;
+    while (BIG_XXX_parity(d)==0 && BIG_XXX_parity(e)==0)
+    {
+        BIG_XXX_shr(d,1);
+        BIG_XXX_shr(e,1);
+        f2++;
+    }
+    while (BIG_XXX_comp(d,e)!=0)
+    {
+        if (BIG_XXX_comp(d,e)>0)
+        {
+            BIG_XXX_imul(w,e,4);
+            BIG_XXX_norm(w);
+            if (BIG_XXX_comp(d,w)<=0)
+            {
+                BIG_XXX_copy(w,d);
+                BIG_XXX_copy(d,e);
+                BIG_XXX_sub(e,w,e);
+                BIG_XXX_norm(e);
+                FP16_YYY_xtr_A(&t,&cu,&cv,&cumv,&cum2v);
+                FP16_YYY_conj(&cum2v,&cumv);
+                FP16_YYY_copy(&cumv,&cv);
+                FP16_YYY_copy(&cv,&cu);
+                FP16_YYY_copy(&cu,&t);
+            }
+            else if (BIG_XXX_parity(d)==0)
+            {
+                BIG_XXX_shr(d,1);
+                FP16_YYY_conj(r,&cum2v);
+                FP16_YYY_xtr_A(&t,&cu,&cumv,&cv,r);
+                FP16_YYY_xtr_D(&cum2v,&cumv);
+                FP16_YYY_copy(&cumv,&t);
+                FP16_YYY_xtr_D(&cu,&cu);
+            }
+            else if (BIG_XXX_parity(e)==1)
+            {
+                BIG_XXX_sub(d,d,e);
+                BIG_XXX_norm(d);
+                BIG_XXX_shr(d,1);
+                FP16_YYY_xtr_A(&t,&cu,&cv,&cumv,&cum2v);
+                FP16_YYY_xtr_D(&cu,&cu);
+                FP16_YYY_xtr_D(&cum2v,&cv);
+                FP16_YYY_conj(&cum2v,&cum2v);
+                FP16_YYY_copy(&cv,&t);
+            }
+            else
+            {
+                BIG_XXX_copy(w,d);
+                BIG_XXX_copy(d,e);
+                BIG_XXX_shr(d,1);
+                BIG_XXX_copy(e,w);
+                FP16_YYY_xtr_D(&t,&cumv);
+                FP16_YYY_conj(&cumv,&cum2v);
+                FP16_YYY_conj(&cum2v,&t);
+                FP16_YYY_xtr_D(&t,&cv);
+                FP16_YYY_copy(&cv,&cu);
+                FP16_YYY_copy(&cu,&t);
+            }
+        }
+        if (BIG_XXX_comp(d,e)<0)
+        {
+            BIG_XXX_imul(w,d,4);
+            BIG_XXX_norm(w);
+            if (BIG_XXX_comp(e,w)<=0)
+            {
+                BIG_XXX_sub(e,e,d);
+                BIG_XXX_norm(e);
+                FP16_YYY_xtr_A(&t,&cu,&cv,&cumv,&cum2v);
+                FP16_YYY_copy(&cum2v,&cumv);
+                FP16_YYY_copy(&cumv,&cu);
+                FP16_YYY_copy(&cu,&t);
+            }
+            else if (BIG_XXX_parity(e)==0)
+            {
+                BIG_XXX_copy(w,d);
+                BIG_XXX_copy(d,e);
+                BIG_XXX_shr(d,1);
+                BIG_XXX_copy(e,w);
+                FP16_YYY_xtr_D(&t,&cumv);
+                FP16_YYY_conj(&cumv,&cum2v);
+                FP16_YYY_conj(&cum2v,&t);
+                FP16_YYY_xtr_D(&t,&cv);
+                FP16_YYY_copy(&cv,&cu);
+                FP16_YYY_copy(&cu,&t);
+            }
+            else if (BIG_XXX_parity(d)==1)
+            {
+                BIG_XXX_copy(w,e);
+                BIG_XXX_copy(e,d);
+                BIG_XXX_sub(w,w,d);
+                BIG_XXX_norm(w);
+                BIG_XXX_copy(d,w);
+                BIG_XXX_shr(d,1);
+                FP16_YYY_xtr_A(&t,&cu,&cv,&cumv,&cum2v);
+                FP16_YYY_conj(&cumv,&cumv);
+                FP16_YYY_xtr_D(&cum2v,&cu);
+                FP16_YYY_conj(&cum2v,&cum2v);
+                FP16_YYY_xtr_D(&cu,&cv);
+                FP16_YYY_copy(&cv,&t);
+            }
+            else
+            {
+                BIG_XXX_shr(d,1);
+                FP16_YYY_conj(r,&cum2v);
+                FP16_YYY_xtr_A(&t,&cu,&cumv,&cv,r);
+                FP16_YYY_xtr_D(&cum2v,&cumv);
+                FP16_YYY_copy(&cumv,&t);
+                FP16_YYY_xtr_D(&cu,&cu);
+            }
+        }
+    }
+    FP16_YYY_xtr_A(r,&cu,&cv,&cumv,&cum2v);
+    for (i=0; i<f2; i++)	FP16_YYY_xtr_D(r,r);
+    FP16_YYY_xtr_pow(r,r,d);
+}
+
+#endif
+
+
+
+/*
+int main(){
+		FP2 w0,w1,f;
+		FP8 w,t;
+		FP8 c1,c2,c3,c4,cr;
+		BIG a,b;
+		BIG e,e1,e2;
+		BIG p,md;
+
+
+		BIG_rcopy(md,Modulus);
+		//Test w^(P^4) = w mod p^2
+		BIG_zero(a); BIG_inc(a,27);
+		BIG_zero(b); BIG_inc(b,45);
+		FP2_from_BIGs(&w0,a,b);
+
+		BIG_zero(a); BIG_inc(a,33);
+		BIG_zero(b); BIG_inc(b,54);
+		FP2_from_BIGs(&w1,a,b);
+
+		FP8_from_FP2s(&w,&w0,&w1);
+		FP8_reduce(&w);
+
+		printf("w= ");
+		FP8_output(&w);
+		printf("\n");
+
+
+		FP8_copy(&t,&w);
+
+
+		BIG_copy(p,md);
+		FP8_pow(&w,&w,p);
+
+		printf("w^p= ");
+		FP8_output(&w);
+		printf("\n");
+//exit(0);
+
+		BIG_rcopy(a,CURVE_Fra);
+		BIG_rcopy(b,CURVE_Frb);
+		FP2_from_BIGs(&f,a,b);
+
+		FP8_frob(&t,&f);
+		printf("w^p= ");
+		FP8_output(&t);
+		printf("\n");
+
+		FP8_pow(&w,&w,p);
+		FP8_pow(&w,&w,p);
+		FP8_pow(&w,&w,p);
+		printf("w^p4= ");
+		FP8_output(&w);
+		printf("\n");
+
+// Test 1/(1/x) = x mod p^4
+		FP8_from_FP2s(&w,&w0,&w1);
+		printf("Test Inversion \nw= ");
+		FP8_output(&w);
+		printf("\n");
+
+		FP8_inv(&w,&w);
+		printf("1/w mod p^4 = ");
+		FP8_output(&w);
+		printf("\n");
+
+		FP8_inv(&w,&w);
+		printf("1/(1/w) mod p^4 = ");
+		FP8_output(&w);
+		printf("\n");
+
+		BIG_zero(e); BIG_inc(e,12);
+
+
+
+	//	FP8_xtr_A(&w,&t,&w,&t,&t);
+		FP8_xtr_pow(&w,&w,e);
+
+		printf("w^e= ");
+		FP8_output(&w);
+		printf("\n");
+
+
+		BIG_zero(a); BIG_inc(a,37);
+		BIG_zero(b); BIG_inc(b,17);
+		FP2_from_BIGs(&w0,a,b);
+
+		BIG_zero(a); BIG_inc(a,49);
+		BIG_zero(b); BIG_inc(b,31);
+		FP2_from_BIGs(&w1,a,b);
+
+		FP8_from_FP2s(&c1,&w0,&w1);
+		FP8_from_FP2s(&c2,&w0,&w1);
+		FP8_from_FP2s(&c3,&w0,&w1);
+		FP8_from_FP2s(&c4,&w0,&w1);
+
+		BIG_zero(e1); BIG_inc(e1,3331);
+		BIG_zero(e2); BIG_inc(e2,3372);
+
+		FP8_xtr_pow2(&w,&c1,&w,&c2,&c3,e1,e2);
+
+		printf("c^e= ");
+		FP8_output(&w);
+		printf("\n");
+
+
+		return 0;
+}
+*/
+
diff --git a/version3/c/fp16.h b/version3/c/fp16.h
new file mode 100644
index 0000000..d2d87d3
--- /dev/null
+++ b/version3/c/fp16.h
@@ -0,0 +1,260 @@
+#ifndef FP16_YYY_H
+#define FP16_YYY_H
+
+#include "fp8_YYY.h"
+#include "config_curve_ZZZ.h"
+
+
+/**
+	@brief FP16 Structure - towered over two FP8
+*/
+
+typedef struct
+{
+    FP8_YYY a; /**< real part of FP16 */
+    FP8_YYY b; /**< imaginary part of FP16 */
+} FP16_YYY;
+
+
+/* FP16 prototypes */
+/**	@brief Tests for FP16 equal to zero
+ *
+	@param x FP16 number to be tested
+	@return 1 if zero, else returns 0
+ */
+extern int FP16_YYY_iszilch(FP16_YYY *x);
+/**	@brief Tests for FP16 equal to unity
+ *
+	@param x FP16 number to be tested
+	@return 1 if unity, else returns 0
+ */
+extern int FP16_YYY_isunity(FP16_YYY *x);
+/**	@brief Tests for equality of two FP16s
+ *
+	@param x FP16 instance to be compared
+	@param y FP16 instance to be compared
+	@return 1 if x=y, else returns 0
+ */
+extern int FP16_YYY_equals(FP16_YYY *x,FP16_YYY *y);
+/**	@brief Tests for FP16 having only a real part and no imaginary part
+ *
+	@param x FP16 number to be tested
+	@return 1 if real, else returns 0
+ */
+extern int FP16_YYY_isreal(FP16_YYY *x);
+/**	@brief Initialise FP16 from two FP8s
+ *
+	@param x FP16 instance to be initialised
+	@param a FP8 to form real part of FP16
+	@param b FP8 to form imaginary part of FP16
+ */
+extern void FP16_YYY_from_FP8s(FP16_YYY *x,FP8_YYY *a,FP8_YYY *b);
+/**	@brief Initialise FP16 from single FP8
+ *
+	Imaginary part is set to zero
+	@param x FP16 instance to be initialised
+	@param a FP8 to form real part of FP16
+ */
+extern void FP16_YYY_from_FP8(FP16_YYY *x,FP8_YYY *a);
+
+/**	@brief Initialise FP16 from single FP8
+ *
+	real part is set to zero
+	@param x FP16 instance to be initialised
+	@param a FP8 to form imaginary part of FP16
+ */
+extern void FP16_YYY_from_FP8H(FP16_YYY *x,FP8_YYY *a);
+
+
+/**	@brief Copy FP16 to another FP16
+ *
+	@param x FP16 instance, on exit = y
+	@param y FP16 instance to be copied
+ */
+extern void FP16_YYY_copy(FP16_YYY *x,FP16_YYY *y);
+/**	@brief Set FP16 to zero
+ *
+	@param x FP16 instance to be set to zero
+ */
+extern void FP16_YYY_zero(FP16_YYY *x);
+/**	@brief Set FP16 to unity
+ *
+	@param x FP16 instance to be set to one
+ */
+extern void FP16_YYY_one(FP16_YYY *x);
+/**	@brief Negation of FP16
+ *
+	@param x FP16 instance, on exit = -y
+	@param y FP16 instance
+ */
+extern void FP16_YYY_neg(FP16_YYY *x,FP16_YYY *y);
+/**	@brief Conjugation of FP16
+ *
+	If y=(a,b) on exit x=(a,-b)
+	@param x FP16 instance, on exit = conj(y)
+	@param y FP16 instance
+ */
+extern void FP16_YYY_conj(FP16_YYY *x,FP16_YYY *y);
+/**	@brief Negative conjugation of FP16
+ *
+	If y=(a,b) on exit x=(-a,b)
+	@param x FP16 instance, on exit = -conj(y)
+	@param y FP16 instance
+ */
+extern void FP16_YYY_nconj(FP16_YYY *x,FP16_YYY *y);
+/**	@brief addition of two FP16s
+ *
+	@param x FP16 instance, on exit = y+z
+	@param y FP16 instance
+	@param z FP16 instance
+ */
+extern void FP16_YYY_add(FP16_YYY *x,FP16_YYY *y,FP16_YYY *z);
+/**	@brief subtraction of two FP16s
+ *
+	@param x FP16 instance, on exit = y-z
+	@param y FP16 instance
+	@param z FP16 instance
+ */
+extern void FP16_YYY_sub(FP16_YYY *x,FP16_YYY *y,FP16_YYY *z);
+/**	@brief Multiplication of an FP16 by an FP8
+ *
+	@param x FP16 instance, on exit = y*a
+	@param y FP16 instance
+	@param a FP8 multiplier
+ */
+extern void FP16_YYY_pmul(FP16_YYY *x,FP16_YYY *y,FP8_YYY *a);
+
+/**	@brief Multiplication of an FP16 by an FP2
+ *
+	@param x FP16 instance, on exit = y*a
+	@param y FP16 instance
+	@param a FP2 multiplier
+ */
+extern void FP16_YYY_qmul(FP16_YYY *x,FP16_YYY *y,FP2_YYY *a);
+
+/**	@brief Multiplication of an FP16 by a small integer
+ *
+	@param x FP16 instance, on exit = y*i
+	@param y FP16 instance
+	@param i an integer
+ */
+extern void FP16_YYY_imul(FP16_YYY *x,FP16_YYY *y,int i);
+/**	@brief Squaring an FP16
+ *
+	@param x FP16 instance, on exit = y^2
+	@param y FP16 instance
+ */
+extern void FP16_YYY_sqr(FP16_YYY *x,FP16_YYY *y);
+/**	@brief Multiplication of two FP16s
+ *
+	@param x FP16 instance, on exit = y*z
+	@param y FP16 instance
+	@param z FP16 instance
+ */
+extern void FP16_YYY_mul(FP16_YYY *x,FP16_YYY *y,FP16_YYY *z);
+/**	@brief Inverting an FP16
+ *
+	@param x FP16 instance, on exit = 1/y
+	@param y FP16 instance
+ */
+extern void FP16_YYY_inv(FP16_YYY *x,FP16_YYY *y);
+/**	@brief Formats and outputs an FP16 to the console
+ *
+	@param x FP16 instance to be printed
+ */
+extern void FP16_YYY_output(FP16_YYY *x);
+/**	@brief Formats and outputs an FP16 to the console in raw form (for debugging)
+ *
+	@param x FP16 instance to be printed
+ */
+extern void FP16_YYY_rawoutput(FP16_YYY *x);
+/**	@brief multiplies an FP16 instance by irreducible polynomial sqrt(1+sqrt(-1))
+ *
+	@param x FP16 instance, on exit = sqrt(1+sqrt(-1)*x
+ */
+extern void FP16_YYY_times_i(FP16_YYY *x);
+/**	@brief multiplies an FP16 instance by irreducible polynomial (1+sqrt(-1))
+ *
+	@param x FP16 instance, on exit = sqrt(1+sqrt(-1))^2*x
+ */
+extern void FP16_YYY_times_i2(FP16_YYY *x);
+
+/**	@brief multiplies an FP16 instance by irreducible polynomial (1+sqrt(-1))
+ *
+	@param x FP16 instance, on exit = sqrt(1+sqrt(-1))^4*x
+ */
+extern void FP16_YYY_times_i4(FP16_YYY *x);
+
+
+/**	@brief Normalises the components of an FP16
+ *
+	@param x FP16 instance to be normalised
+ */
+extern void FP16_YYY_norm(FP16_YYY *x);
+/**	@brief Reduces all components of possibly unreduced FP16 mod Modulus
+ *
+	@param x FP16 instance, on exit reduced mod Modulus
+ */
+extern void FP16_YYY_reduce(FP16_YYY *x);
+/**	@brief Raises an FP16 to the power of a BIG
+ *
+	@param x FP16 instance, on exit = y^b
+	@param y FP16 instance
+	@param b BIG number
+ */
+extern void FP16_YYY_pow(FP16_YYY *x,FP16_YYY *y,BIG_XXX b);
+/**	@brief Raises an FP16 to the power of the internal modulus p, using the Frobenius
+ *
+	@param x FP16 instance, on exit = x^p
+	@param f FP2 precalculated Frobenius constant
+ */
+extern void FP16_YYY_frob(FP16_YYY *x,FP2_YYY *f);
+/**	@brief Calculates the XTR addition function r=w*x-conj(x)*y+z
+ *
+	@param r FP16 instance, on exit = w*x-conj(x)*y+z
+	@param w FP16 instance
+	@param x FP16 instance
+	@param y FP16 instance
+	@param z FP16 instance
+ */
+extern void FP16_YYY_xtr_A(FP16_YYY *r,FP16_YYY *w,FP16_YYY *x,FP16_YYY *y,FP16_YYY *z);
+/**	@brief Calculates the XTR doubling function r=x^2-2*conj(x)
+ *
+	@param r FP16 instance, on exit = x^2-2*conj(x)
+	@param x FP16 instance
+ */
+extern void FP16_YYY_xtr_D(FP16_YYY *r,FP16_YYY *x);
+/**	@brief Calculates FP16 trace of an FP12 raised to the power of a BIG number
+ *
+	XTR single exponentiation
+	@param r FP16 instance, on exit = trace(w^b)
+	@param x FP16 instance, trace of an FP12 w
+	@param b BIG number
+ */
+extern void FP16_YYY_xtr_pow(FP16_YYY *r,FP16_YYY *x,BIG_XXX b);
+/**	@brief Calculates FP16 trace of c^a.d^b, where c and d are derived from FP16 traces of FP12s
+ *
+	XTR double exponentiation
+	Assumes c=tr(x^m), d=tr(x^n), e=tr(x^(m-n)), f=tr(x^(m-2n))
+	@param r FP16 instance, on exit = trace(c^a.d^b)
+	@param c FP16 instance, trace of an FP12
+	@param d FP16 instance, trace of an FP12
+	@param e FP16 instance, trace of an FP12
+	@param f FP16 instance, trace of an FP12
+	@param a BIG number
+	@param b BIG number
+ */
+extern void FP16_YYY_xtr_pow2(FP16_YYY *r,FP16_YYY *c,FP16_YYY *d,FP16_YYY *e,FP16_YYY *f,BIG_XXX a,BIG_XXX b);
+
+/**	@brief Conditional copy of FP16 number
+ *
+	Conditionally copies second parameter to the first (without branching)
+	@param x FP16 instance, set to y if s!=0
+	@param y another FP16 instance
+	@param s copy only takes place if not equal to 0
+ */
+extern void FP16_YYY_cmove(FP16_YYY *x,FP16_YYY *y,int s);
+
+
+#endif
+
diff --git a/version3/c/fp2.c b/version3/c/fp2.c
new file mode 100644
index 0000000..d0c8e3f
--- /dev/null
+++ b/version3/c/fp2.c
@@ -0,0 +1,489 @@
+/*
+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.
+*/
+
+/* AMCL Fp^2 functions */
+/* SU=m, m is Stack Usage (no lazy )*/
+
+/* FP2 elements are of the form a+ib, where i is sqrt(-1) */
+
+#include "fp2_YYY.h"
+
+/* test x==0 ? */
+/* SU= 8 */
+int FP2_YYY_iszilch(FP2_YYY *x)
+{
+   // FP2_YYY_reduce(x);
+    if (FP_YYY_iszilch(&(x->a)) && FP_YYY_iszilch(&(x->b))) return 1;
+    return 0;
+}
+
+/* Move b to a if d=1 */
+void FP2_YYY_cmove(FP2_YYY *f,FP2_YYY *g,int d)
+{
+    FP_YYY_cmove(&(f->a),&(g->a),d);
+    FP_YYY_cmove(&(f->b),&(g->b),d);
+}
+
+/* test x==1 ? */
+/* SU= 48 */
+int FP2_YYY_isunity(FP2_YYY *x)
+{
+    FP_YYY one;
+    FP_YYY_one(&one);
+    //FP2_YYY_reduce(x);
+    if (FP_YYY_equals(&(x->a),&one) && FP_YYY_iszilch(&(x->b))) return 1;
+    return 0;
+}
+
+/* SU= 8 */
+/* Fully reduce a and b mod Modulus */
+void FP2_YYY_reduce(FP2_YYY *w)
+{
+    FP_YYY_reduce(&(w->a));
+    FP_YYY_reduce(&(w->b));
+}
+
+/* return 1 if x==y, else 0 */
+/* SU= 16 */
+int FP2_YYY_equals(FP2_YYY *x,FP2_YYY *y)
+{
+    if (FP_YYY_equals(&(x->a),&(y->a)) && FP_YYY_equals(&(x->b),&(y->b)))
+        return 1;
+    return 0;
+}
+
+/* Create FP2 from two FPs */
+/* SU= 16 */
+void FP2_YYY_from_FPs(FP2_YYY *w,FP_YYY *x,FP_YYY *y)
+{
+    FP_YYY_copy(&(w->a),x);
+    FP_YYY_copy(&(w->b),y);
+}
+
+/* Create FP2 from two BIGS */
+/* SU= 16 */
+void FP2_YYY_from_BIGs(FP2_YYY *w,BIG_XXX x,BIG_XXX y)
+{
+    FP_YYY_nres(&(w->a),x);
+    FP_YYY_nres(&(w->b),y);
+}
+
+/* Create FP2 from FP */
+/* SU= 8 */
+void FP2_YYY_from_FP(FP2_YYY *w,FP_YYY *x)
+{
+    FP_YYY_copy(&(w->a),x);
+    FP_YYY_zero(&(w->b));
+}
+
+/* Create FP2 from BIG */
+/* SU= 8 */
+void FP2_YYY_from_BIG(FP2_YYY *w,BIG_XXX x)
+{
+    FP_YYY_nres(&(w->a),x);
+    FP_YYY_zero(&(w->b));
+}
+
+/* FP2 copy w=x */
+/* SU= 16 */
+void FP2_YYY_copy(FP2_YYY *w,FP2_YYY *x)
+{
+    if (w==x) return;
+    FP_YYY_copy(&(w->a),&(x->a));
+    FP_YYY_copy(&(w->b),&(x->b));
+}
+
+/* FP2 set w=0 */
+/* SU= 8 */
+void FP2_YYY_zero(FP2_YYY *w)
+{
+    FP_YYY_zero(&(w->a));
+    FP_YYY_zero(&(w->b));
+}
+
+/* FP2 set w=1 */
+/* SU= 48 */
+void FP2_YYY_one(FP2_YYY *w)
+{
+    FP_YYY one;
+    FP_YYY_one(&one);
+    FP2_YYY_from_FP(w,&one);
+}
+
+/* Set w=-x */
+/* SU= 88 */
+void FP2_YYY_neg(FP2_YYY *w,FP2_YYY *x)
+{
+    /* Just one neg! */
+    FP_YYY m,t;
+//    FP2_YYY_norm(x);
+    FP_YYY_add(&m,&(x->a),&(x->b));
+    FP_YYY_neg(&m,&m);
+    FP_YYY_add(&t,&m,&(x->b));
+    FP_YYY_add(&(w->b),&m,&(x->a));
+    FP_YYY_copy(&(w->a),&t);
+
+}
+
+/* Set w=conj(x) */
+/* SU= 16 */
+void FP2_YYY_conj(FP2_YYY *w,FP2_YYY *x)
+{
+    FP_YYY_copy(&(w->a),&(x->a));
+//	BIG_XXX_norm(x->b);
+    FP_YYY_neg(&(w->b),&(x->b));
+    FP_YYY_norm(&(w->b));
+}
+
+/* Set w=x+y */
+/* SU= 16 */
+void FP2_YYY_add(FP2_YYY *w,FP2_YYY *x,FP2_YYY *y)
+{
+    FP_YYY_add(&(w->a),&(x->a),&(y->a));
+    FP_YYY_add(&(w->b),&(x->b),&(y->b));
+}
+
+/* Set w=x-y */
+/* Input y MUST be normed */
+void FP2_YYY_sub(FP2_YYY *w,FP2_YYY *x,FP2_YYY *y)
+{
+    FP2_YYY m;
+    FP2_YYY_neg(&m,y);
+    FP2_YYY_add(w,x,&m);
+}
+
+/* Set w=s*x, where s is FP */
+/* SU= 16 */
+void FP2_YYY_pmul(FP2_YYY *w,FP2_YYY *x,FP_YYY *s)
+{
+    FP_YYY_mul(&(w->a),&(x->a),s);
+    FP_YYY_mul(&(w->b),&(x->b),s);
+}
+
+/* SU= 16 */
+/* Set w=s*x, where s is int */
+void FP2_YYY_imul(FP2_YYY *w,FP2_YYY *x,int s)
+{
+    FP_YYY_imul(&(w->a),&(x->a),s);
+    FP_YYY_imul(&(w->b),&(x->b),s);
+}
+
+/* Set w=x^2 */
+/* SU= 128 */
+void FP2_YYY_sqr(FP2_YYY *w,FP2_YYY *x)
+{
+    FP_YYY w1,w3,mb;
+
+    FP_YYY_add(&w1,&(x->a),&(x->b));
+    FP_YYY_neg(&mb,&(x->b));
+
+    FP_YYY_add(&w3,&(x->a),&(x->a));
+    FP_YYY_norm(&w3);
+    FP_YYY_mul(&(w->b),&w3,&(x->b));
+
+    FP_YYY_add(&(w->a),&(x->a),&mb);
+
+    FP_YYY_norm(&w1);
+    FP_YYY_norm(&(w->a));
+
+    FP_YYY_mul(&(w->a),&w1,&(w->a));     /* w->a#2 w->a=1 w1&w2=6 w1*w2=2 */
+}
+
+
+/* Set w=x*y */
+/* Inputs MUST be normed  */
+/* Now uses Lazy reduction */
+void FP2_YYY_mul(FP2_YYY *w,FP2_YYY *x,FP2_YYY *y)
+{
+    DBIG_XXX A,B,E,F,pR;
+    BIG_XXX C,D,p;
+
+    BIG_XXX_rcopy(p,Modulus_YYY);
+    BIG_XXX_dsucopy(pR,p);
+
+// reduce excesses of a and b as required (so product < pR)
+
+    if ((sign64)(x->a.XES+x->b.XES)*(y->a.XES+y->b.XES)>(sign64)FEXCESS_YYY)
+    {
+#ifdef DEBUG_REDUCE
+        printf("FP2 Product too large - reducing it\n");
+#endif
+        if (x->a.XES>1) FP_YYY_reduce(&(x->a));
+        if (x->b.XES>1) FP_YYY_reduce(&(x->b));
+    }
+
+    BIG_XXX_mul(A,x->a.g,y->a.g);
+    BIG_XXX_mul(B,x->b.g,y->b.g);
+
+    BIG_XXX_add(C,x->a.g,x->b.g);
+    BIG_XXX_norm(C);
+    BIG_XXX_add(D,y->a.g,y->b.g);
+    BIG_XXX_norm(D);
+
+    BIG_XXX_mul(E,C,D);
+    BIG_XXX_dadd(F,A,B);
+    BIG_XXX_dsub(B,pR,B); //
+
+    BIG_XXX_dadd(A,A,B);    // A<pR? Not necessarily, but <2pR
+    BIG_XXX_dsub(E,E,F);    // E<pR ? Yes
+
+    BIG_XXX_dnorm(A);
+    FP_YYY_mod(w->a.g,A);
+    w->a.XES=3;// may drift above 2p...
+    BIG_XXX_dnorm(E);
+    FP_YYY_mod(w->b.g,E);
+    w->b.XES=2;
+
+}
+
+/* output FP2 in hex format [a,b] */
+/* SU= 16 */
+void FP2_YYY_output(FP2_YYY *w)
+{
+    BIG_XXX bx,by;
+    FP2_YYY_reduce(w);
+    FP_YYY_redc(bx,&(w->a));
+    FP_YYY_redc(by,&(w->b));
+    printf("[");
+    BIG_XXX_output(bx);
+    printf(",");
+    BIG_XXX_output(by);
+    printf("]");
+    FP_YYY_nres(&(w->a),bx);
+    FP_YYY_nres(&(w->b),by);
+}
+
+/* SU= 8 */
+void FP2_YYY_rawoutput(FP2_YYY *w)
+{
+    printf("[");
+    BIG_XXX_rawoutput(w->a.g);
+    printf(",");
+    BIG_XXX_rawoutput(w->b.g);
+    printf("]");
+}
+
+
+/* Set w=1/x */
+/* SU= 128 */
+void FP2_YYY_inv(FP2_YYY *w,FP2_YYY *x)
+{
+    BIG_XXX m,b;
+    FP_YYY w1,w2;
+
+    FP2_YYY_norm(x);
+    FP_YYY_sqr(&w1,&(x->a));
+    FP_YYY_sqr(&w2,&(x->b));
+    FP_YYY_add(&w1,&w1,&w2);
+
+	FP_YYY_inv(&w1,&w1);
+
+    FP_YYY_mul(&(w->a),&(x->a),&w1);
+    FP_YYY_neg(&w1,&w1);
+    FP_YYY_norm(&w1);
+    FP_YYY_mul(&(w->b),&(x->b),&w1);
+//	FP2_YYY_norm(w);
+}
+
+
+/* Set w=x/2 */
+/* SU= 16 */
+void FP2_YYY_div2(FP2_YYY *w,FP2_YYY *x)
+{
+    FP_YYY_div2(&(w->a),&(x->a));
+    FP_YYY_div2(&(w->b),&(x->b));
+}
+
+/* Set w*=(1+sqrt(-1)) */
+/* where X^2-(1+sqrt(-1)) is irreducible for FP4, assumes p=3 mod 8 */
+
+/* Input MUST be normed */
+void FP2_YYY_mul_ip(FP2_YYY *w)
+{
+    FP_YYY z;
+    FP2_YYY t;
+
+//   FP2_YYY_norm(w);
+    FP2_YYY_copy(&t,w);
+
+    FP_YYY_copy(&z,&(w->a));
+    FP_YYY_neg(&(w->a),&(w->b));
+    FP_YYY_copy(&(w->b),&z);
+
+    FP2_YYY_add(w,&t,w);
+//    Output NOT normed, so use with care
+}
+
+
+void FP2_YYY_div_ip2(FP2_YYY *w)
+{
+    FP2_YYY t;
+    FP2_YYY_norm(w);
+    FP_YYY_add(&(t.a),&(w->a),&(w->b));
+    FP_YYY_sub(&(t.b),&(w->b),&(w->a));
+    FP2_YYY_norm(&t);
+    FP2_YYY_copy(w,&t);
+}
+
+/* Set w/=(1+sqrt(-1)) */
+/* SU= 88 */
+void FP2_YYY_div_ip(FP2_YYY *w)
+{
+    FP2_YYY t;
+    FP2_YYY_norm(w);
+    FP_YYY_add(&t.a,&(w->a),&(w->b));
+    FP_YYY_sub(&t.b,&(w->b),&(w->a));
+    FP2_YYY_norm(&t);
+    FP2_YYY_div2(w,&t);
+}
+
+/* SU= 8 */
+/* normalise a and b components of w */
+void FP2_YYY_norm(FP2_YYY *w)
+{
+    FP_YYY_norm(&(w->a));
+    FP_YYY_norm(&(w->b));
+}
+
+/* Set w=a^b mod m */
+/* SU= 208 */
+void FP2_YYY_pow(FP2_YYY *r,FP2_YYY* a,BIG_XXX b)
+{
+    FP2_YYY w;
+    FP_YYY one;
+    BIG_XXX z,zilch;
+    int bt;
+
+    BIG_XXX_norm(b);
+    BIG_XXX_copy(z,b);
+    FP2_YYY_copy(&w,a);
+    FP_YYY_one(&one);
+    BIG_XXX_zero(zilch);
+    FP2_YYY_from_FP(r,&one);
+    while(1)
+    {
+        bt=BIG_XXX_parity(z);
+        BIG_XXX_shr(z,1);
+        if (bt) FP2_YYY_mul(r,r,&w);
+        if (BIG_XXX_comp(z,zilch)==0) break;
+        FP2_YYY_sqr(&w,&w);
+    }
+    FP2_YYY_reduce(r);
+}
+
+/* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */
+/* returns true if u is QR */
+
+int FP2_YYY_sqrt(FP2_YYY *w,FP2_YYY *u)
+{
+    BIG_XXX b;
+    FP_YYY w1,w2;
+    FP2_YYY_copy(w,u);
+    if (FP2_YYY_iszilch(w)) return 1;
+
+    FP_YYY_sqr(&w1,&(w->b));
+    FP_YYY_sqr(&w2,&(w->a));
+    FP_YYY_add(&w1,&w1,&w2);
+    if (!FP_YYY_qr(&w1))
+    {
+        FP2_YYY_zero(w);
+        return 0;
+    }
+    FP_YYY_sqrt(&w1,&w1);
+    FP_YYY_add(&w2,&(w->a),&w1);
+    FP_YYY_norm(&w2);
+    FP_YYY_div2(&w2,&w2);
+    if (!FP_YYY_qr(&w2))
+    {
+        FP_YYY_sub(&w2,&(w->a),&w1);
+        FP_YYY_norm(&w2);
+        FP_YYY_div2(&w2,&w2);
+        if (!FP_YYY_qr(&w2))
+        {
+            FP2_YYY_zero(w);
+            return 0;
+        }
+    }
+    FP_YYY_sqrt(&w2,&w2);
+    FP_YYY_copy(&(w->a),&w2);
+    FP_YYY_add(&w2,&w2,&w2);
+
+	FP_YYY_inv(&w2,&w2);
+
+    FP_YYY_mul(&(w->b),&(w->b),&w2);
+    return 1;
+}
+
+/* New stuff for ECp4 support */
+
+/* Input MUST be normed */
+void FP2_YYY_times_i(FP2_YYY *w)
+{
+    FP_YYY z;
+
+ //   FP2_norm(w);
+
+    FP_YYY_copy(&z,&(w->a));
+    FP_YYY_neg(&(w->a),&(w->b));
+    FP_YYY_copy(&(w->b),&z);
+
+//    Output NOT normed, so use with care
+}
+
+/*
+int main()
+{
+	int i;
+	FP2_YYY w,z;
+	BIG_XXX a,b,e;
+	BIG_XXX pp1,pm1;
+	BIG_XXX_unity(a); BIG_XXX_unity(b);
+	FP2_YYY_from_BIGs(&w,a,b);
+//	for (i=0;i<100;i++)
+//	{
+//		BIG_XXX_randomnum(a); BIG_XXX_randomnum(b);
+//		BIG_XXX_mod(a,Modulus_YYY); BIG_XXX_mod(b,Modulus_YYY);
+//		FP2_YYY_from_FPs(&w,a,b);
+//		FP2_YYY_output(&w);
+//		FP2_YYY_inv(&z,&w);
+//				FP2_YYY_output(&z);
+//		FP2_YYY_inv(&z,&z);
+//				FP2_YYY_output(&z);
+//				FP2_YYY_output(&w);
+//		if (FP2_YYY_comp(&w,&z)!=1) printf("error \n");
+//		else printf("OK \n");
+//	}
+//exit(0);
+	printf("w= "); FP2_YYY_output(&w); printf("\n");
+	BIG_XXX_zero(e); BIG_XXX_inc(e,27);
+	FP2_YYY_pow(&w,&w,e);
+	FP2_YYY_output(&w);
+exit(0);
+	BIG_XXX_rcopy(pp1,Modulus_YYY);
+	BIG_XXX_rcopy(pm1,Modulus_YYY);
+	BIG_XXX_inc(pp1,1);
+	BIG_XXX_dec(pm1,1);
+	BIG_XXX_norm(pp1);
+	BIG_XXX_norm(pm1);
+	FP2_YYY_pow(&w,&w,pp1);
+	FP2_YYY_pow(&w,&w,pm1);
+	FP2_YYY_output(&w);
+}
+
+*/
diff --git a/version3/c/fp2.h b/version3/c/fp2.h
new file mode 100644
index 0000000..6767685
--- /dev/null
+++ b/version3/c/fp2.h
@@ -0,0 +1,240 @@
+/*
+	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.
+*/
+
+/**
+ * @file fp2.h
+ * @author Mike Scott
+ * @brief FP2 Header File
+ *
+ */
+
+#ifndef FP2_YYY_H
+#define FP2_YYY_H
+
+#include "fp_YYY.h"
+
+/**
+	@brief FP2 Structure - quadratic extension field
+*/
+
+typedef struct
+{
+    FP_YYY a; /**< real part of FP2 */
+    FP_YYY b; /**< imaginary part of FP2 */
+} FP2_YYY;
+
+/* FP2 prototypes */
+
+/**	@brief Tests for FP2 equal to zero
+ *
+	@param x FP2 number to be tested
+	@return 1 if zero, else returns 0
+ */
+extern int FP2_YYY_iszilch(FP2_YYY *x);
+/**	@brief Conditional copy of FP2 number
+ *
+	Conditionally copies second parameter to the first (without branching)
+	@param x FP2 instance, set to y if s!=0
+	@param y another FP2 instance
+	@param s copy only takes place if not equal to 0
+ */
+extern void FP2_YYY_cmove(FP2_YYY *x,FP2_YYY *y,int s);
+/**	@brief Tests for FP2 equal to one
+ *
+	@param x FP2 instance to be tested
+	@return 1 if x=1, else returns 0
+ */
+extern int FP2_YYY_isunity(FP2_YYY *x);
+/**	@brief Tests for equality of two FP2s
+ *
+	@param x FP2 instance to be compared
+	@param y FP2 instance to be compared
+	@return 1 if x=y, else returns 0
+ */
+extern int FP2_YYY_equals(FP2_YYY *x,FP2_YYY *y);
+/**	@brief Initialise FP2 from two FP numbers
+ *
+	@param x FP2 instance to be initialised
+	@param a FP to form real part of FP2
+	@param b FP to form imaginary part of FP2
+ */
+extern void FP2_YYY_from_FPs(FP2_YYY *x,FP_YYY *a,FP_YYY *b);
+/**	@brief Initialise FP2 from two BIG integers
+ *
+	@param x FP2 instance to be initialised
+	@param a BIG to form real part of FP2
+	@param b BIG to form imaginary part of FP2
+ */
+extern void FP2_YYY_from_BIGs(FP2_YYY *x,BIG_XXX a,BIG_XXX b);
+/**	@brief Initialise FP2 from single FP
+ *
+	Imaginary part is set to zero
+	@param x FP2 instance to be initialised
+	@param a FP to form real part of FP2
+ */
+extern void FP2_YYY_from_FP(FP2_YYY *x,FP_YYY *a);
+/**	@brief Initialise FP2 from single BIG
+ *
+	Imaginary part is set to zero
+	@param x FP2 instance to be initialised
+	@param a BIG to form real part of FP2
+ */
+extern void FP2_YYY_from_BIG(FP2_YYY *x,BIG_XXX a);
+/**	@brief Copy FP2 to another FP2
+ *
+	@param x FP2 instance, on exit = y
+	@param y FP2 instance to be copied
+ */
+extern void FP2_YYY_copy(FP2_YYY *x,FP2_YYY *y);
+/**	@brief Set FP2 to zero
+ *
+	@param x FP2 instance to be set to zero
+ */
+extern void FP2_YYY_zero(FP2_YYY *x);
+/**	@brief Set FP2 to unity
+ *
+	@param x FP2 instance to be set to one
+ */
+extern void FP2_YYY_one(FP2_YYY *x);
+/**	@brief Negation of FP2
+ *
+	@param x FP2 instance, on exit = -y
+	@param y FP2 instance
+ */
+extern void FP2_YYY_neg(FP2_YYY *x,FP2_YYY *y);
+/**	@brief Conjugation of FP2
+ *
+	If y=(a,b) on exit x=(a,-b)
+	@param x FP2 instance, on exit = conj(y)
+	@param y FP2 instance
+ */
+extern void FP2_YYY_conj(FP2_YYY *x,FP2_YYY *y);
+/**	@brief addition of two FP2s
+ *
+	@param x FP2 instance, on exit = y+z
+	@param y FP2 instance
+	@param z FP2 instance
+ */
+extern void FP2_YYY_add(FP2_YYY *x,FP2_YYY *y,FP2_YYY *z);
+/**	@brief subtraction of two FP2s
+ *
+	@param x FP2 instance, on exit = y-z
+	@param y FP2 instance
+	@param z FP2 instance
+ */
+extern void FP2_YYY_sub(FP2_YYY *x,FP2_YYY *y,FP2_YYY *z);
+/**	@brief Multiplication of an FP2 by an FP
+ *
+	@param x FP2 instance, on exit = y*b
+	@param y FP2 instance
+	@param b FP residue
+ */
+extern void FP2_YYY_pmul(FP2_YYY *x,FP2_YYY *y,FP_YYY *b);
+/**	@brief Multiplication of an FP2 by a small integer
+ *
+	@param x FP2 instance, on exit = y*i
+	@param y FP2 instance
+	@param i an integer
+ */
+extern void FP2_YYY_imul(FP2_YYY *x,FP2_YYY *y,int i);
+/**	@brief Squaring an FP2
+ *
+	@param x FP2 instance, on exit = y^2
+	@param y FP2 instance
+ */
+extern void FP2_YYY_sqr(FP2_YYY *x,FP2_YYY *y);
+/**	@brief Multiplication of two FP2s
+ *
+	@param x FP2 instance, on exit = y*z
+	@param y FP2 instance
+	@param z FP2 instance
+ */
+extern void FP2_YYY_mul(FP2_YYY *x,FP2_YYY *y,FP2_YYY *z);
+/**	@brief Formats and outputs an FP2 to the console
+ *
+	@param x FP2 instance
+ */
+extern void FP2_YYY_output(FP2_YYY *x);
+/**	@brief Formats and outputs an FP2 to the console in raw form (for debugging)
+ *
+	@param x FP2 instance
+ */
+extern void FP2_YYY_rawoutput(FP2_YYY *x);
+/**	@brief Inverting an FP2
+ *
+	@param x FP2 instance, on exit = 1/y
+	@param y FP2 instance
+ */
+extern void FP2_YYY_inv(FP2_YYY *x,FP2_YYY *y);
+/**	@brief Divide an FP2 by 2
+ *
+	@param x FP2 instance, on exit = y/2
+	@param y FP2 instance
+ */
+extern void FP2_YYY_div2(FP2_YYY *x,FP2_YYY *y);
+/**	@brief Multiply an FP2 by (1+sqrt(-1))
+ *
+	Note that (1+sqrt(-1)) is irreducible for FP4
+	@param x FP2 instance, on exit = x*(1+sqrt(-1))
+ */
+extern void FP2_YYY_mul_ip(FP2_YYY *x);
+/**	@brief Divide an FP2 by (1+sqrt(-1))/2 -
+ *
+	Note that (1+sqrt(-1)) is irreducible for FP4
+	@param x FP2 instance, on exit = 2x/(1+sqrt(-1))
+ */
+extern void FP2_YYY_div_ip2(FP2_YYY *x);
+/**	@brief Divide an FP2 by (1+sqrt(-1))
+ *
+	Note that (1+sqrt(-1)) is irreducible for FP4
+	@param x FP2 instance, on exit = x/(1+sqrt(-1))
+ */
+extern void FP2_YYY_div_ip(FP2_YYY *x);
+/**	@brief Normalises the components of an FP2
+ *
+	@param x FP2 instance to be normalised
+ */
+extern void FP2_YYY_norm(FP2_YYY *x);
+/**	@brief Reduces all components of possibly unreduced FP2 mod Modulus
+ *
+	@param x FP2 instance, on exit reduced mod Modulus
+ */
+extern void FP2_YYY_reduce(FP2_YYY *x);
+/**	@brief Raises an FP2 to the power of a BIG
+ *
+	@param x FP2 instance, on exit = y^b
+	@param y FP2 instance
+	@param b BIG number
+ */
+extern void FP2_YYY_pow(FP2_YYY *x,FP2_YYY *y,BIG_XXX b);
+/**	@brief Square root of an FP2
+ *
+	@param x FP2 instance, on exit = sqrt(y)
+	@param y FP2 instance
+ */
+extern int FP2_YYY_sqrt(FP2_YYY *x,FP2_YYY *y);
+
+/**	@brief Multiply an FP2 by sqrt(-1)
+ *
+	Note that -1 is QNR
+	@param x FP2 instance, on exit = x*sqrt(-1)
+ */
+extern void FP2_YYY_times_i(FP2_YYY *x);
+
+#endif
diff --git a/version3/c/fp24.c b/version3/c/fp24.c
new file mode 100644
index 0000000..07a6525
--- /dev/null
+++ b/version3/c/fp24.c
@@ -0,0 +1,1123 @@
+/*
+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.
+*/
+
+/* AMCL Fp^12 functions */
+/* SU=m, m is Stack Usage (no lazy )*/
+/* FP24 elements are of the form a+i.b+i^2.c */
+
+#include "fp24_YYY.h"
+
+/* return 1 if b==c, no branching */
+static int teq(sign32 b,sign32 c)
+{
+    sign32 x=b^c;
+    x-=1;  // if x=0, x now -1
+    return (int)((x>>31)&1);
+}
+
+
+/* Constant time select from pre-computed table */
+static void FP24_YYY_select(FP24_YYY *f,FP24_YYY g[],sign32 b)
+{
+    FP24_YYY invf;
+    sign32 m=b>>31;
+    sign32 babs=(b^m)-m;
+
+    babs=(babs-1)/2;
+
+    FP24_YYY_cmove(f,&g[0],teq(babs,0));  // conditional move
+    FP24_YYY_cmove(f,&g[1],teq(babs,1));
+    FP24_YYY_cmove(f,&g[2],teq(babs,2));
+    FP24_YYY_cmove(f,&g[3],teq(babs,3));
+    FP24_YYY_cmove(f,&g[4],teq(babs,4));
+    FP24_YYY_cmove(f,&g[5],teq(babs,5));
+    FP24_YYY_cmove(f,&g[6],teq(babs,6));
+    FP24_YYY_cmove(f,&g[7],teq(babs,7));
+
+    FP24_YYY_copy(&invf,f);
+    FP24_YYY_conj(&invf,&invf);  // 1/f
+    FP24_YYY_cmove(f,&invf,(int)(m&1));
+}
+
+/* test x==0 ? */
+/* SU= 8 */
+int FP24_YYY_iszilch(FP24_YYY *x)
+{
+    if (FP8_YYY_iszilch(&(x->a)) && FP8_YYY_iszilch(&(x->b)) && FP8_YYY_iszilch(&(x->c))) return 1;
+    return 0;
+}
+
+/* test x==1 ? */
+/* SU= 8 */
+int FP24_YYY_isunity(FP24_YYY *x)
+{
+    if (FP8_YYY_isunity(&(x->a)) && FP8_YYY_iszilch(&(x->b)) && FP8_YYY_iszilch(&(x->c))) return 1;
+    return 0;
+}
+
+/* FP24 copy w=x */
+/* SU= 16 */
+void FP24_YYY_copy(FP24_YYY *w,FP24_YYY *x)
+{
+    if (x==w) return;
+    FP8_YYY_copy(&(w->a),&(x->a));
+    FP8_YYY_copy(&(w->b),&(x->b));
+    FP8_YYY_copy(&(w->c),&(x->c));
+}
+
+/* FP24 w=1 */
+/* SU= 8 */
+void FP24_YYY_one(FP24_YYY *w)
+{
+    FP8_YYY_one(&(w->a));
+    FP8_YYY_zero(&(w->b));
+    FP8_YYY_zero(&(w->c));
+}
+
+/* return 1 if x==y, else 0 */
+/* SU= 16 */
+int FP24_YYY_equals(FP24_YYY *x,FP24_YYY *y)
+{
+    if (FP8_YYY_equals(&(x->a),&(y->a)) && FP8_YYY_equals(&(x->b),&(y->b)) && FP8_YYY_equals(&(x->b),&(y->b)))
+        return 1;
+    return 0;
+}
+
+/* Set w=conj(x) */
+/* SU= 8 */
+void FP24_YYY_conj(FP24_YYY *w,FP24_YYY *x)
+{
+    FP24_YYY_copy(w,x);
+    FP8_YYY_conj(&(w->a),&(w->a));
+    FP8_YYY_nconj(&(w->b),&(w->b));
+    FP8_YYY_conj(&(w->c),&(w->c));
+}
+
+/* Create FP24 from FP8 */
+/* SU= 8 */
+void FP24_YYY_from_FP8(FP24_YYY *w,FP8_YYY *a)
+{
+    FP8_YYY_copy(&(w->a),a);
+    FP8_YYY_zero(&(w->b));
+    FP8_YYY_zero(&(w->c));
+}
+
+/* Create FP24 from 3 FP8's */
+/* SU= 16 */
+void FP24_YYY_from_FP8s(FP24_YYY *w,FP8_YYY *a,FP8_YYY *b,FP8_YYY *c)
+{
+    FP8_YYY_copy(&(w->a),a);
+    FP8_YYY_copy(&(w->b),b);
+    FP8_YYY_copy(&(w->c),c);
+}
+
+/* Granger-Scott Unitary Squaring. This does not benefit from lazy reduction */
+/* SU= 600 */
+void FP24_YYY_usqr(FP24_YYY *w,FP24_YYY *x)
+{
+    FP8_YYY A,B,C,D;
+
+    FP8_YYY_copy(&A,&(x->a));
+
+    FP8_YYY_sqr(&(w->a),&(x->a));
+    FP8_YYY_add(&D,&(w->a),&(w->a));
+    FP8_YYY_add(&(w->a),&D,&(w->a));
+
+    FP8_YYY_norm(&(w->a));
+    FP8_YYY_nconj(&A,&A);
+
+    FP8_YYY_add(&A,&A,&A);
+    FP8_YYY_add(&(w->a),&(w->a),&A);
+    FP8_YYY_sqr(&B,&(x->c));
+    FP8_YYY_times_i(&B);
+
+    FP8_YYY_add(&D,&B,&B);
+    FP8_YYY_add(&B,&B,&D);
+    FP8_YYY_norm(&B);
+
+    FP8_YYY_sqr(&C,&(x->b));
+
+    FP8_YYY_add(&D,&C,&C);
+    FP8_YYY_add(&C,&C,&D);
+
+    FP8_YYY_norm(&C);
+    FP8_YYY_conj(&(w->b),&(x->b));
+    FP8_YYY_add(&(w->b),&(w->b),&(w->b));
+    FP8_YYY_nconj(&(w->c),&(x->c));
+
+    FP8_YYY_add(&(w->c),&(w->c),&(w->c));
+    FP8_YYY_add(&(w->b),&B,&(w->b));
+    FP8_YYY_add(&(w->c),&C,&(w->c));
+
+    FP24_YYY_reduce(w);	    /* reduce here as in pow function repeated squarings would trigger multiple reductions */
+}
+
+/* FP24 squaring w=x^2 */
+/* SU= 600 */
+void FP24_YYY_sqr(FP24_YYY *w,FP24_YYY *x)
+{
+    /* Use Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
+
+    FP8_YYY A,B,C,D;
+
+    FP8_YYY_sqr(&A,&(x->a));
+    FP8_YYY_mul(&B,&(x->b),&(x->c));
+    FP8_YYY_add(&B,&B,&B);
+FP8_YYY_norm(&B);
+    FP8_YYY_sqr(&C,&(x->c));
+
+    FP8_YYY_mul(&D,&(x->a),&(x->b));
+    FP8_YYY_add(&D,&D,&D);
+
+    FP8_YYY_add(&(w->c),&(x->a),&(x->c));
+    FP8_YYY_add(&(w->c),&(x->b),&(w->c));
+FP8_YYY_norm(&(w->c));	
+
+    FP8_YYY_sqr(&(w->c),&(w->c));
+
+    FP8_YYY_copy(&(w->a),&A);
+    FP8_YYY_add(&A,&A,&B);
+
+    FP8_YYY_norm(&A);
+
+    FP8_YYY_add(&A,&A,&C);
+    FP8_YYY_add(&A,&A,&D);
+
+    FP8_YYY_norm(&A);
+
+    FP8_YYY_neg(&A,&A);
+    FP8_YYY_times_i(&B);
+    FP8_YYY_times_i(&C);
+
+    FP8_YYY_add(&(w->a),&(w->a),&B);
+    FP8_YYY_add(&(w->b),&C,&D);
+    FP8_YYY_add(&(w->c),&(w->c),&A);
+
+    FP24_YYY_norm(w);
+}
+
+/* FP24 full multiplication w=w*y */
+
+
+/* SU= 896 */
+/* FP24 full multiplication w=w*y */
+void FP24_YYY_mul(FP24_YYY *w,FP24_YYY *y)
+{
+    FP8_YYY z0,z1,z2,z3,t0,t1;
+
+    FP8_YYY_mul(&z0,&(w->a),&(y->a));
+    FP8_YYY_mul(&z2,&(w->b),&(y->b));  //
+
+    FP8_YYY_add(&t0,&(w->a),&(w->b));
+    FP8_YYY_add(&t1,&(y->a),&(y->b));  //
+
+FP8_YYY_norm(&t0);
+FP8_YYY_norm(&t1);
+
+    FP8_YYY_mul(&z1,&t0,&t1);
+    FP8_YYY_add(&t0,&(w->b),&(w->c));
+    FP8_YYY_add(&t1,&(y->b),&(y->c));  //
+
+FP8_YYY_norm(&t0);
+FP8_YYY_norm(&t1);
+
+    FP8_YYY_mul(&z3,&t0,&t1);
+
+    FP8_YYY_neg(&t0,&z0);
+    FP8_YYY_neg(&t1,&z2);
+
+    FP8_YYY_add(&z1,&z1,&t0);   // z1=z1-z0
+//    FP8_YYY_norm(&z1);
+    FP8_YYY_add(&(w->b),&z1,&t1);
+// z1=z1-z2
+    FP8_YYY_add(&z3,&z3,&t1);        // z3=z3-z2
+    FP8_YYY_add(&z2,&z2,&t0);        // z2=z2-z0
+
+    FP8_YYY_add(&t0,&(w->a),&(w->c));
+    FP8_YYY_add(&t1,&(y->a),&(y->c));
+
+FP8_YYY_norm(&t0);
+FP8_YYY_norm(&t1);
+
+    FP8_YYY_mul(&t0,&t1,&t0);
+    FP8_YYY_add(&z2,&z2,&t0);
+
+    FP8_YYY_mul(&t0,&(w->c),&(y->c));
+    FP8_YYY_neg(&t1,&t0);
+
+    FP8_YYY_add(&(w->c),&z2,&t1);
+    FP8_YYY_add(&z3,&z3,&t1);
+    FP8_YYY_times_i(&t0);
+    FP8_YYY_add(&(w->b),&(w->b),&t0);
+FP8_YYY_norm(&z3);
+    FP8_YYY_times_i(&z3);
+    FP8_YYY_add(&(w->a),&z0,&z3);
+
+    FP24_YYY_norm(w);
+}
+
+/* FP24 multiplication w=w*y */
+/* SU= 744 */
+/* catering for special case that arises from special form of ATE pairing line function */
+void FP24_YYY_smul(FP24_YYY *w,FP24_YYY *y,int type)
+{
+    FP8_YYY z0,z1,z2,z3,t0,t1;
+
+	if (type==D_TYPE)
+	{ // y->c is 0
+
+		FP8_YYY_copy(&z3,&(w->b));
+		FP8_YYY_mul(&z0,&(w->a),&(y->a));
+
+		FP8_YYY_pmul(&z2,&(w->b),&(y->b).a);
+		FP8_YYY_add(&(w->b),&(w->a),&(w->b));
+		FP8_YYY_copy(&t1,&(y->a));
+		FP4_YYY_add(&t1.a,&t1.a,&(y->b).a);
+
+		FP8_YYY_norm(&t1);
+		FP8_YYY_norm(&(w->b));
+
+		FP8_YYY_mul(&(w->b),&(w->b),&t1);
+		FP8_YYY_add(&z3,&z3,&(w->c));
+		FP8_YYY_norm(&z3);
+		FP8_YYY_pmul(&z3,&z3,&(y->b).a);
+		FP8_YYY_neg(&t0,&z0);
+		FP8_YYY_neg(&t1,&z2);
+
+		FP8_YYY_add(&(w->b),&(w->b),&t0);   // z1=z1-z0
+//    FP8_YYY_norm(&(w->b));
+		FP8_YYY_add(&(w->b),&(w->b),&t1);   // z1=z1-z2
+
+		FP8_YYY_add(&z3,&z3,&t1);        // z3=z3-z2
+		FP8_YYY_add(&z2,&z2,&t0);        // z2=z2-z0
+
+		FP8_YYY_add(&t0,&(w->a),&(w->c));
+
+		FP8_YYY_norm(&t0);
+		FP8_YYY_norm(&z3);
+
+		FP8_YYY_mul(&t0,&(y->a),&t0);
+		FP8_YYY_add(&(w->c),&z2,&t0);
+
+		FP8_YYY_times_i(&z3);
+		FP8_YYY_add(&(w->a),&z0,&z3);
+	}
+
+	if (type==M_TYPE)
+	{ // y->b is zero
+		FP8_YYY_mul(&z0,&(w->a),&(y->a));
+		FP8_YYY_add(&t0,&(w->a),&(w->b));
+		FP8_YYY_norm(&t0);
+
+		FP8_YYY_mul(&z1,&t0,&(y->a));
+		FP8_YYY_add(&t0,&(w->b),&(w->c));
+		FP8_YYY_norm(&t0);
+
+		FP8_YYY_pmul(&z3,&t0,&(y->c).b);
+		FP8_YYY_times_i(&z3);
+
+		FP8_YYY_neg(&t0,&z0);
+		FP8_YYY_add(&z1,&z1,&t0);   // z1=z1-z0
+
+		FP8_YYY_copy(&(w->b),&z1);
+
+		FP8_YYY_copy(&z2,&t0);
+
+		FP8_YYY_add(&t0,&(w->a),&(w->c));
+		FP8_YYY_add(&t1,&(y->a),&(y->c));
+
+		FP8_YYY_norm(&t0);
+		FP8_YYY_norm(&t1);
+
+		FP8_YYY_mul(&t0,&t1,&t0);
+		FP8_YYY_add(&z2,&z2,&t0);
+
+		FP8_YYY_pmul(&t0,&(w->c),&(y->c).b);
+		FP8_YYY_times_i(&t0);
+		FP8_YYY_neg(&t1,&t0);
+		FP8_YYY_times_i(&t0);
+
+		FP8_YYY_add(&(w->c),&z2,&t1);
+		FP8_YYY_add(&z3,&z3,&t1);
+
+		FP8_YYY_add(&(w->b),&(w->b),&t0);
+		FP8_YYY_norm(&z3);
+		FP8_YYY_times_i(&z3);
+		FP8_YYY_add(&(w->a),&z0,&z3);
+	}
+    FP24_YYY_norm(w);
+}
+
+/* Set w=1/x */
+/* SU= 600 */
+void FP24_YYY_inv(FP24_YYY *w,FP24_YYY *x)
+{
+    FP8_YYY f0,f1,f2,f3;
+//    FP24_norm(x);
+
+    FP8_YYY_sqr(&f0,&(x->a));
+    FP8_YYY_mul(&f1,&(x->b),&(x->c));
+    FP8_YYY_times_i(&f1);
+    FP8_YYY_sub(&f0,&f0,&f1);  /* y.a */
+	FP8_YYY_norm(&f0); 		
+
+    FP8_YYY_sqr(&f1,&(x->c));
+    FP8_YYY_times_i(&f1);
+    FP8_YYY_mul(&f2,&(x->a),&(x->b));
+    FP8_YYY_sub(&f1,&f1,&f2);  /* y.b */
+	FP8_YYY_norm(&f1); 
+
+    FP8_YYY_sqr(&f2,&(x->b));
+    FP8_YYY_mul(&f3,&(x->a),&(x->c));
+    FP8_YYY_sub(&f2,&f2,&f3);  /* y.c */
+	FP8_YYY_norm(&f2); 
+
+    FP8_YYY_mul(&f3,&(x->b),&f2);
+    FP8_YYY_times_i(&f3);
+    FP8_YYY_mul(&(w->a),&f0,&(x->a));
+    FP8_YYY_add(&f3,&(w->a),&f3);
+    FP8_YYY_mul(&(w->c),&f1,&(x->c));
+    FP8_YYY_times_i(&(w->c));
+
+
+
+    FP8_YYY_add(&f3,&(w->c),&f3);
+	FP8_YYY_norm(&f3);
+	
+    FP8_YYY_inv(&f3,&f3);
+    FP8_YYY_mul(&(w->a),&f0,&f3);
+    FP8_YYY_mul(&(w->b),&f1,&f3);
+    FP8_YYY_mul(&(w->c),&f2,&f3);
+
+}
+
+/* constant time powering by small integer of max length bts */
+
+void FP24_YYY_pinpow(FP24_YYY *r,int e,int bts)
+{
+    int i,b;
+    FP24_YYY R[2];
+
+    FP24_YYY_one(&R[0]);
+    FP24_YYY_copy(&R[1],r);
+
+    for (i=bts-1; i>=0; i--)
+    {
+        b=(e>>i)&1;
+        FP24_YYY_mul(&R[1-b],&R[b]);
+        FP24_YYY_usqr(&R[b],&R[b]);
+    }
+    FP24_YYY_copy(r,&R[0]);
+}
+
+/* Compressed powering of unitary elements y=x^(e mod r) */
+
+void FP24_YYY_compow(FP8_YYY *c,FP24_YYY *x,BIG_XXX e,BIG_XXX r)
+{
+    FP24_YYY g1,g2;
+	FP8_YYY cp,cpm1,cpm2;
+    FP2_YYY f;
+	BIG_XXX q,a,b,m;
+
+    BIG_XXX_rcopy(a,Fra_YYY);
+    BIG_XXX_rcopy(b,Frb_YYY);
+    FP2_YYY_from_BIGs(&f,a,b);
+
+    BIG_XXX_rcopy(q,Modulus_YYY);
+
+    FP24_YYY_copy(&g1,x);
+	FP24_YYY_copy(&g2,x);
+
+    BIG_XXX_copy(m,q);
+    BIG_XXX_mod(m,r);
+
+    BIG_XXX_copy(a,e);
+    BIG_XXX_mod(a,m);
+
+    BIG_XXX_copy(b,e);
+    BIG_XXX_sdiv(b,m);
+
+    FP24_YYY_trace(c,&g1);
+
+	if (BIG_XXX_iszilch(b))
+	{
+		FP8_YYY_xtr_pow(c,c,e);
+		return;
+	}
+
+    FP24_YYY_frob(&g2,&f,1);
+    FP24_YYY_trace(&cp,&g2);
+    FP24_YYY_conj(&g1,&g1);
+    FP24_YYY_mul(&g2,&g1);
+    FP24_YYY_trace(&cpm1,&g2);
+    FP24_YYY_mul(&g2,&g1);
+
+    FP24_YYY_trace(&cpm2,&g2);
+
+    FP8_YYY_xtr_pow2(c,&cp,c,&cpm1,&cpm2,a,b);
+
+}
+
+/* Note this is simple square and multiply, so not side-channel safe */
+
+void FP24_YYY_pow(FP24_YYY *r,FP24_YYY *a,BIG_XXX b)
+{
+    FP24_YYY w,sf;
+    BIG_XXX b1,b3;
+    int i,nb,bt;
+	BIG_XXX_copy(b1,b);
+    BIG_XXX_norm(b1);
+	BIG_XXX_pmul(b3,b1,3);
+	BIG_XXX_norm(b3);
+
+	FP24_YYY_copy(&sf,a);
+	FP24_YYY_norm(&sf);
+    FP24_YYY_copy(&w,&sf);
+
+
+	nb=BIG_XXX_nbits(b3);
+	for (i=nb-2;i>=1;i--)
+	{
+		FP24_YYY_usqr(&w,&w);
+		bt=BIG_XXX_bit(b3,i)-BIG_XXX_bit(b1,i);
+		if (bt==1)
+			FP24_YYY_mul(&w,&sf);
+		if (bt==-1)
+		{
+			FP24_YYY_conj(&sf,&sf);
+			FP24_YYY_mul(&w,&sf);
+			FP24_YYY_conj(&sf,&sf);
+		}
+	}
+
+	FP24_YYY_copy(r,&w);
+	FP24_YYY_reduce(r);
+}
+
+
+/* SU= 528 */
+/* set r=a^b */
+/* Note this is simple square and multiply, so not side-channel safe 
+
+void FP24_ppow(FP24 *r,FP24 *a,BIG_XXX b)
+{
+    FP24 w;
+    BIG_XXX z,zilch;
+    int bt;
+    BIG_XXX_zero(zilch);
+    BIG_XXX_norm(b);
+    BIG_XXX_copy(z,b);
+    FP24_copy(&w,a);
+    FP24_one(r);
+
+    while(1)
+    {
+        bt=BIG_XXX_parity(z);
+        BIG_XXX_shr(z,1);
+        if (bt)
+		{
+			//printf("In mul\n");
+            FP24_mul(r,&w);
+			//printf("Out of mul\n");
+		}
+        if (BIG_XXX_comp(z,zilch)==0) break;
+		//printf("In sqr\n");
+        FP24_sqr(&w,&w);
+		//printf("Out of sqr\n");
+    }
+
+    FP24_reduce(r);
+}  */
+
+
+/* p=q0^u0.q1^u1.q2^u2.q3^u3... */
+/* Side channel attack secure */
+// Bos & Costello https://eprint.iacr.org/2013/458.pdf
+// Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
+
+void FP24_YYY_pow8(FP24_YYY *p,FP24_YYY *q,BIG_XXX u[8])
+{
+    int i,j,k,nb,pb1,pb2,bt;
+	FP24_YYY g1[8],g2[8],r;
+	BIG_XXX t[8],mt;
+    sign8 w1[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 s1[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 w2[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 s2[NLEN_XXX*BASEBITS_XXX+1];
+    FP_YYY fx,fy;
+	FP2_YYY X;
+
+    FP_YYY_rcopy(&fx,Fra_YYY);
+    FP_YYY_rcopy(&fy,Frb_YYY);
+    FP2_YYY_from_FPs(&X,&fx,&fy);
+
+    for (i=0; i<8; i++)
+        BIG_XXX_copy(t[i],u[i]);
+
+// Precomputed table
+    FP24_YYY_copy(&g1[0],&q[0]); // q[0]
+    FP24_YYY_copy(&g1[1],&g1[0]);
+	FP24_YYY_mul(&g1[1],&q[1]);	// q[0].q[1]
+    FP24_YYY_copy(&g1[2],&g1[0]);
+	FP24_YYY_mul(&g1[2],&q[2]);	// q[0].q[2]
+	FP24_YYY_copy(&g1[3],&g1[1]);
+	FP24_YYY_mul(&g1[3],&q[2]);	// q[0].q[1].q[2]
+	FP24_YYY_copy(&g1[4],&g1[0]);
+	FP24_YYY_mul(&g1[4],&q[3]);  // q[0].q[3]
+	FP24_YYY_copy(&g1[5],&g1[1]);
+	FP24_YYY_mul(&g1[5],&q[3]);	// q[0].q[1].q[3]
+	FP24_YYY_copy(&g1[6],&g1[2]);
+	FP24_YYY_mul(&g1[6],&q[3]);	// q[0].q[2].q[3]
+	FP24_YYY_copy(&g1[7],&g1[3]);
+	FP24_YYY_mul(&g1[7],&q[3]);	// q[0].q[1].q[2].q[3]
+
+// Use Frobenius
+
+	for (i=0;i<8;i++)
+	{
+		FP24_YYY_copy(&g2[i],&g1[i]);
+		FP24_YYY_frob(&g2[i],&X,4);
+	}
+
+// Make it odd
+	pb1=1-BIG_XXX_parity(t[0]);
+	BIG_XXX_inc(t[0],pb1);
+	BIG_XXX_norm(t[0]);
+
+	pb2=1-BIG_XXX_parity(t[4]);
+	BIG_XXX_inc(t[4],pb2);
+	BIG_XXX_norm(t[4]);
+
+// Number of bits
+    BIG_XXX_zero(mt);
+    for (i=0; i<8; i++)
+    {
+        BIG_XXX_or(mt,mt,t[i]);
+    }
+    nb=1+BIG_XXX_nbits(mt);
+
+// Sign pivot 
+	s1[nb-1]=1;
+	s2[nb-1]=1;
+	for (i=0;i<nb-1;i++)
+	{
+        BIG_XXX_fshr(t[0],1);
+		s1[i]=2*BIG_XXX_parity(t[0])-1;
+        BIG_XXX_fshr(t[4],1);
+		s2[i]=2*BIG_XXX_parity(t[4])-1;
+	}
+
+// Recoded exponents
+    for (i=0; i<nb; i++)
+    {
+		w1[i]=0;
+		k=1;
+		for (j=1; j<4; j++)
+		{
+			bt=s1[i]*BIG_XXX_parity(t[j]);
+			BIG_XXX_fshr(t[j],1);
+
+			BIG_XXX_dec(t[j],(bt>>1));
+			BIG_XXX_norm(t[j]);
+			w1[i]+=bt*k;
+			k*=2;
+        }
+
+		w2[i]=0;
+		k=1;
+		for (j=5; j<8; j++)
+		{
+			bt=s2[i]*BIG_XXX_parity(t[j]);
+			BIG_XXX_fshr(t[j],1);
+
+			BIG_XXX_dec(t[j],(bt>>1));
+			BIG_XXX_norm(t[j]);
+			w2[i]+=bt*k;
+			k*=2;
+        }
+    }	
+
+// Main loop
+	FP24_YYY_select(p,g1,2*w1[nb-1]+1);
+	FP24_YYY_select(&r,g2,2*w2[nb-1]+1);
+	FP24_YYY_mul(p,&r);
+    for (i=nb-2; i>=0; i--)
+    {
+		FP24_YYY_usqr(p,p);
+        FP24_YYY_select(&r,g1,2*w1[i]+s1[i]);
+        FP24_YYY_mul(p,&r);
+        FP24_YYY_select(&r,g2,2*w2[i]+s2[i]);
+        FP24_YYY_mul(p,&r);
+    }
+
+// apply correction
+	FP24_YYY_conj(&r,&q[0]);   
+	FP24_YYY_mul(&r,p);
+	FP24_YYY_cmove(p,&r,pb1);
+	FP24_YYY_conj(&r,&q[4]);   
+	FP24_YYY_mul(&r,p);
+	FP24_YYY_cmove(p,&r,pb2);
+
+	FP24_YYY_reduce(p);
+}
+
+/*
+void FP24_YYY_pow8(FP24_YYY *p,FP24_YYY *q,BIG_XXX u[8])
+{
+    int i,j,a[4],nb,m;
+    FP24_YYY g[8],f[8],c,s[2];
+    BIG_XXX t[8],mt;
+    sign8 w[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 z[NLEN_XXX*BASEBITS_XXX+1];
+    FP fx,fy;
+	FP2 X;
+
+    FP_rcopy(&fx,Fra_YYY);
+    FP_rcopy(&fy,Frb_YYY);
+    FP2_from_FPs(&X,&fx,&fy);
+
+    for (i=0; i<8; i++)
+        BIG_XXX_copy(t[i],u[i]);
+
+    FP24_YYY_copy(&g[0],&q[0]);
+    FP24_YYY_conj(&s[0],&q[1]);
+    FP24_YYY_mul(&g[0],&s[0]);  // P/Q 
+    FP24_YYY_copy(&g[1],&g[0]);
+    FP24_YYY_copy(&g[2],&g[0]);
+    FP24_YYY_copy(&g[3],&g[0]);
+    FP24_YYY_copy(&g[4],&q[0]);
+    FP24_YYY_mul(&g[4],&q[1]);  // P*Q 
+    FP24_YYY_copy(&g[5],&g[4]);
+    FP24_YYY_copy(&g[6],&g[4]);
+    FP24_YYY_copy(&g[7],&g[4]);
+
+    FP24_YYY_copy(&s[1],&q[2]);
+    FP24_YYY_conj(&s[0],&q[3]);
+    FP24_YYY_mul(&s[1],&s[0]);       // R/S 
+    FP24_YYY_conj(&s[0],&s[1]);
+    FP24_YYY_mul(&g[1],&s[0]);
+    FP24_YYY_mul(&g[2],&s[1]);
+    FP24_YYY_mul(&g[5],&s[0]);
+    FP24_YYY_mul(&g[6],&s[1]);
+    FP24_YYY_copy(&s[1],&q[2]);
+    FP24_YYY_mul(&s[1],&q[3]);      // R*S 
+    FP24_YYY_conj(&s[0],&s[1]);
+    FP24_YYY_mul(&g[0],&s[0]);
+    FP24_YYY_mul(&g[3],&s[1]);
+    FP24_YYY_mul(&g[4],&s[0]);
+    FP24_YYY_mul(&g[7],&s[1]);
+
+// Use Frobenius
+
+	for (i=0;i<8;i++)
+	{
+		FP24_YYY_copy(&f[i],&g[i]);
+		FP24_YYY_frob(&f[i],&X,4);
+	}
+
+
+    // if power is even add 1 to power, and add q to correction 
+    FP24_YYY_one(&c);
+
+    BIG_XXX_zero(mt);
+    for (i=0; i<8; i++)
+    {
+        if (BIG_XXX_parity(t[i])==0)
+        {
+            BIG_XXX_inc(t[i],1);
+            BIG_XXX_norm(t[i]);
+            FP24_YYY_mul(&c,&q[i]);
+        }
+        BIG_XXX_add(mt,mt,t[i]);
+        BIG_XXX_norm(mt);
+    }
+
+    FP24_YYY_conj(&c,&c);
+    nb=1+BIG_XXX_nbits(mt);
+
+    // convert exponents to signed 1-bit windows 
+    for (j=0; j<nb; j++)
+    {
+        for (i=0; i<4; i++)
+        {
+            a[i]=BIG_XXX_lastbits(t[i],2)-2;
+            BIG_XXX_dec(t[i],a[i]);
+            BIG_XXX_norm(t[i]);
+            BIG_XXX_fshr(t[i],1);
+        }
+        w[j]=8*a[0]+4*a[1]+2*a[2]+a[3];
+    }
+    w[nb]=8*BIG_XXX_lastbits(t[0],2)+4*BIG_XXX_lastbits(t[1],2)+2*BIG_XXX_lastbits(t[2],2)+BIG_XXX_lastbits(t[3],2);
+
+
+    for (j=0; j<nb; j++)
+    {
+        for (i=0; i<4; i++)
+        {
+            a[i]=BIG_XXX_lastbits(t[i+4],2)-2;
+            BIG_XXX_dec(t[i+4],a[i]);
+            BIG_XXX_norm(t[i+4]);
+            BIG_XXX_fshr(t[i+4],1);
+        }
+        z[j]=8*a[0]+4*a[1]+2*a[2]+a[3];
+    }
+    z[nb]=8*BIG_XXX_lastbits(t[4],2)+4*BIG_XXX_lastbits(t[5],2)+2*BIG_XXX_lastbits(t[6],2)+BIG_XXX_lastbits(t[7],2);
+
+
+    FP24_YYY_copy(p,&g[(w[nb]-1)/2]);
+    FP24_YYY_mul(p,&f[(z[nb]-1)/2]);
+    for (i=nb-1; i>=0; i--)
+    {
+		FP24_YYY_usqr(p,p);
+
+        m=w[i]>>7;
+        j=(w[i]^m)-m;  // j=abs(w[i]) 
+        j=(j-1)/2;
+        FP24_YYY_copy(&s[0],&g[j]);
+        FP24_YYY_conj(&s[1],&g[j]);
+        FP24_YYY_mul(p,&s[m&1]);
+
+        m=z[i]>>7;
+        j=(z[i]^m)-m;  // j=abs(w[i]) 
+        j=(j-1)/2;
+        FP24_YYY_copy(&s[0],&f[j]);
+        FP24_YYY_conj(&s[1],&f[j]);
+        FP24_YYY_mul(p,&s[m&1]);
+
+    }
+    FP24_YYY_mul(p,&c); // apply correction 
+    FP24_YYY_reduce(p);
+}
+*/
+
+/* Set w=w^p using Frobenius */
+/* SU= 160 */
+void FP24_YYY_frob(FP24_YYY *w,FP2_YYY *f,int n)
+{
+	int i;
+	FP4_YYY X2,X4;
+    FP2_YYY f3,f2;				// f=(1+i)^(p-7)/12
+    FP2_YYY_sqr(&f2,f);     // 
+    FP2_YYY_mul(&f3,&f2,f); // f3=f^3=(1+i)^(p-7)/4
+
+	FP2_YYY_mul_ip(&f3);    // f3 = (1+i).f3 = (1+i)^(p-3)/4 
+	FP2_YYY_norm(&f3);
+
+	for (i=0;i<n;i++)
+	{
+		FP8_YYY_frob(&(w->a),&f3);   // a=a^p
+		FP8_YYY_frob(&(w->b),&f3);   // b=b^p
+		FP8_YYY_frob(&(w->c),&f3);   // c=c^p
+  
+		FP8_YYY_qmul(&(w->b),&(w->b),f); FP8_YYY_times_i2(&(w->b));
+		FP8_YYY_qmul(&(w->c),&(w->c),&f2); FP8_YYY_times_i2(&(w->c)); FP8_YYY_times_i2(&(w->c));
+	}
+}
+
+
+/* SU= 8 */
+/* normalise all components of w */
+void FP24_YYY_norm(FP24_YYY *w)
+{
+    FP8_YYY_norm(&(w->a));
+    FP8_YYY_norm(&(w->b));
+    FP8_YYY_norm(&(w->c));
+}
+
+/* SU= 8 */
+/* reduce all components of w */
+void FP24_YYY_reduce(FP24_YYY *w)
+{
+    FP8_YYY_reduce(&(w->a));
+    FP8_YYY_reduce(&(w->b));
+    FP8_YYY_reduce(&(w->c));
+}
+
+/* trace function w=trace(x) */
+/* SU= 8 */
+void FP24_YYY_trace(FP8_YYY *w,FP24_YYY *x)
+{
+    FP8_YYY_imul(w,&(x->a),3);
+    FP8_YYY_reduce(w);
+}
+
+/* SU= 8 */
+/* Output w in hex */
+void FP24_YYY_output(FP24_YYY *w)
+{
+    printf("[");
+    FP8_YYY_output(&(w->a));
+    printf(",");
+    FP8_YYY_output(&(w->b));
+    printf(",");
+    FP8_YYY_output(&(w->c));
+    printf("]");
+}
+
+/* SU= 64 */
+/* Convert g to octet string w */
+void FP24_YYY_toOctet(octet *W,FP24_YYY *g)
+{
+    BIG_XXX a;
+    W->len=24*MODBYTES_XXX;
+
+    FP_YYY_redc(a,&(g->a.a.a.a));
+    BIG_XXX_toBytes(&(W->val[0]),a);
+    FP_YYY_redc(a,&(g->a.a.a.b));
+    BIG_XXX_toBytes(&(W->val[MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->a.a.b.a));
+    BIG_XXX_toBytes(&(W->val[2*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->a.a.b.b));
+    BIG_XXX_toBytes(&(W->val[3*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->a.b.a.a));
+    BIG_XXX_toBytes(&(W->val[4*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->a.b.a.b));
+    BIG_XXX_toBytes(&(W->val[5*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->a.b.b.a));
+    BIG_XXX_toBytes(&(W->val[6*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->a.b.b.b));
+    BIG_XXX_toBytes(&(W->val[7*MODBYTES_XXX]),a);
+
+    FP_YYY_redc(a,&(g->b.a.a.a));
+    BIG_XXX_toBytes(&(W->val[8*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->b.a.a.b));
+    BIG_XXX_toBytes(&(W->val[9*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->b.a.b.a));
+    BIG_XXX_toBytes(&(W->val[10*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->b.a.b.b));
+    BIG_XXX_toBytes(&(W->val[11*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->b.b.a.a));
+    BIG_XXX_toBytes(&(W->val[12*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->b.b.a.b));
+    BIG_XXX_toBytes(&(W->val[13*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->b.b.b.a));
+    BIG_XXX_toBytes(&(W->val[14*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->b.b.b.b));
+    BIG_XXX_toBytes(&(W->val[15*MODBYTES_XXX]),a);
+
+    FP_YYY_redc(a,&(g->c.a.a.a));
+    BIG_XXX_toBytes(&(W->val[16*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->c.a.a.b));
+    BIG_XXX_toBytes(&(W->val[17*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->c.a.b.a));
+    BIG_XXX_toBytes(&(W->val[18*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->c.a.b.b));
+    BIG_XXX_toBytes(&(W->val[19*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->c.b.a.a));
+    BIG_XXX_toBytes(&(W->val[20*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->c.b.a.b));
+    BIG_XXX_toBytes(&(W->val[21*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->c.b.b.a));
+    BIG_XXX_toBytes(&(W->val[22*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->c.b.b.b));
+    BIG_XXX_toBytes(&(W->val[23*MODBYTES_XXX]),a);
+}
+
+/* SU= 24 */
+/* Restore g from octet string w */
+void FP24_YYY_fromOctet(FP24_YYY *g,octet *W)
+{
+	BIG_XXX b;
+
+    BIG_XXX_fromBytes(b,&W->val[0]);
+    FP_YYY_nres(&(g->a.a.a.a),b);
+    BIG_XXX_fromBytes(b,&W->val[MODBYTES_XXX]);
+    FP_YYY_nres(&(g->a.a.a.b),b);
+    BIG_XXX_fromBytes(b,&W->val[2*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->a.a.b.a),b);
+    BIG_XXX_fromBytes(b,&W->val[3*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->a.a.b.b),b);
+    BIG_XXX_fromBytes(b,&W->val[4*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->a.b.a.a),b);
+    BIG_XXX_fromBytes(b,&W->val[5*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->a.b.a.b),b);
+    BIG_XXX_fromBytes(b,&W->val[6*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->a.b.b.a),b);
+    BIG_XXX_fromBytes(b,&W->val[7*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->a.b.b.b),b);
+
+    BIG_XXX_fromBytes(b,&W->val[8*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->b.a.a.a),b);
+    BIG_XXX_fromBytes(b,&W->val[9*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->b.a.a.b),b);
+    BIG_XXX_fromBytes(b,&W->val[10*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->b.a.b.a),b);
+    BIG_XXX_fromBytes(b,&W->val[11*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->b.a.b.b),b);
+    BIG_XXX_fromBytes(b,&W->val[12*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->b.b.a.a),b);
+    BIG_XXX_fromBytes(b,&W->val[13*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->b.b.a.b),b);
+    BIG_XXX_fromBytes(b,&W->val[14*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->b.b.b.a),b);
+    BIG_XXX_fromBytes(b,&W->val[15*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->b.b.b.b),b);
+
+    BIG_XXX_fromBytes(b,&W->val[16*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->c.a.a.a),b);
+    BIG_XXX_fromBytes(b,&W->val[17*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->c.a.a.b),b);
+    BIG_XXX_fromBytes(b,&W->val[18*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->c.a.b.a),b);
+    BIG_XXX_fromBytes(b,&W->val[19*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->c.a.b.b),b);
+    BIG_XXX_fromBytes(b,&W->val[20*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->c.b.a.a),b);
+    BIG_XXX_fromBytes(b,&W->val[21*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->c.b.a.b),b);
+    BIG_XXX_fromBytes(b,&W->val[22*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->c.b.b.a),b);
+    BIG_XXX_fromBytes(b,&W->val[23*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->c.b.b.b),b);
+}
+
+/* Move b to a if d=1 */
+void FP24_YYY_cmove(FP24_YYY *f,FP24_YYY *g,int d)
+{
+    FP8_YYY_cmove(&(f->a),&(g->a),d);
+    FP8_YYY_cmove(&(f->b),&(g->b),d);
+    FP8_YYY_cmove(&(f->c),&(g->c),d);
+}
+
+/*
+using namespace YYY;
+
+int main() {
+	int i;
+	FP2 f,w0,w1,X;
+	FP4 f0,f1;
+	FP8 t0,t1,t2;
+	FP24 w,t,lv;
+	BIG a,b;
+	BIG p;
+
+
+	char raw[100];
+	csprng RNG;                // Crypto Strong RNG 
+
+	for (i=0; i<100; i++) raw[i]=i;
+
+	BIG_rcopy(a,Fra_YYY);
+    BIG_rcopy(b,Frb_YYY);
+	FP2_from_BIGs(&X,a,b);
+
+
+
+    RAND_seed(&RNG,100,raw);   // initialise strong RNG 
+
+	BIG_rcopy(p,Modulus);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w0,a,b);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w1,a,b);
+
+	FP4_from_FP2s(&f0,&w0,&w1);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w0,a,b);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w1,a,b);
+
+	FP4_from_FP2s(&f1,&w0,&w1);
+	FP8_from_FP4s(&t0,&f0,&f1);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w0,a,b);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w1,a,b);
+
+	FP4_from_FP2s(&f0,&w0,&w1);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w0,a,b);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w1,a,b);
+
+	FP4_from_FP2s(&f1,&w0,&w1);
+	FP8_from_FP4s(&t1,&f0,&f1);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w0,a,b);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w1,a,b);
+
+	FP4_from_FP2s(&f0,&w0,&w1);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w0,a,b);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w1,a,b);
+
+	FP4_from_FP2s(&f1,&w0,&w1);
+	FP8_from_FP4s(&t2,&f0,&f1);
+
+	FP24_from_FP8s(&w,&t0,&t1,&t2);
+
+
+	FP24_copy(&t,&w);
+
+	printf("w= ");
+	FP24_output(&w);
+	printf("\n");
+
+	FP24_norm(&w);
+
+	printf("w^p= ");
+	FP24_frob(&w,&X);
+	FP24_output(&w);
+	printf("\n");	
+
+//	printf("p.w= ");
+//	FP24_ppow(&t,&t,p);
+//	FP24_output(&t);
+//	printf("\n");	
+
+	printf("1/w= ");
+	FP24_inv(&t,&w);
+	FP24_output(&t);
+	printf("\n");	
+
+	printf("w= ");
+	FP24_inv(&w,&t);
+	FP24_output(&w);
+	printf("\n");	
+
+	return 0;
+}
+
+*/
diff --git a/version3/c/fp24.h b/version3/c/fp24.h
new file mode 100644
index 0000000..13ff25c
--- /dev/null
+++ b/version3/c/fp24.h
@@ -0,0 +1,196 @@
+#ifndef FP24_YYY_H
+#define FP24_YYY_H
+
+#include "fp8_YYY.h"
+
+/**
+	@brief FP12 Structure - towered over three FP8
+*/
+
+typedef struct
+{
+    FP8_YYY a; /**< first part of FP12 */
+    FP8_YYY b; /**< second part of FP12 */
+    FP8_YYY c; /**< third part of FP12 */
+} FP24_YYY;
+
+extern const BIG_XXX Fra_YYY; /**< real part of BN curve Frobenius Constant */
+extern const BIG_XXX Frb_YYY; /**< imaginary part of BN curve Frobenius Constant */
+
+/* FP24 prototypes */
+/**	@brief Tests for FP24 equal to zero
+ *
+	@param x FP24 number to be tested
+	@return 1 if zero, else returns 0
+ */
+extern int FP24_YYY_iszilch(FP24_YYY *x);
+/**	@brief Tests for FP24 equal to unity
+ *
+	@param x FP24 number to be tested
+	@return 1 if unity, else returns 0
+ */
+extern int FP24_YYY_isunity(FP24_YYY *x);
+/**	@brief Copy FP24 to another FP24
+ *
+	@param x FP24 instance, on exit = y
+	@param y FP24 instance to be copied
+ */
+extern void FP24_YYY_copy(FP24_YYY *x,FP24_YYY *y);
+/**	@brief Set FP24 to unity
+ *
+	@param x FP24 instance to be set to one
+ */
+extern void FP24_YYY_one(FP24_YYY *x);
+/**	@brief Tests for equality of two FP24s
+ *
+	@param x FP24 instance to be compared
+	@param y FP24 instance to be compared
+	@return 1 if x=y, else returns 0
+ */
+extern int FP24_YYY_equals(FP24_YYY *x,FP24_YYY *y);
+/**	@brief Conjugation of FP24
+ *
+	If y=(a,b,c) (where a,b,c are its three FP8 components) on exit x=(conj(a),-conj(b),conj(c))
+	@param x FP24 instance, on exit = conj(y)
+	@param y FP24 instance
+ */
+extern void FP24_YYY_conj(FP24_YYY *x,FP24_YYY *y);
+/**	@brief Initialise FP24 from single FP8
+ *
+	Sets first FP8 component of an FP24, other components set to zero
+	@param x FP24 instance to be initialised
+	@param a FP8 to form first part of FP8
+ */
+extern void FP24_YYY_from_FP8(FP24_YYY *x,FP8_YYY *a);
+/**	@brief Initialise FP24 from three FP8s
+ *
+	@param x FP24 instance to be initialised
+	@param a FP8 to form first part of FP24
+	@param b FP8 to form second part of FP24
+	@param c FP8 to form third part of FP24
+ */
+extern void FP24_YYY_from_FP8s(FP24_YYY *x,FP8_YYY *a,FP8_YYY* b,FP8_YYY *c);
+/**	@brief Fast Squaring of an FP24 in "unitary" form
+ *
+	@param x FP24 instance, on exit = y^2
+	@param y FP8 instance, must be unitary
+ */
+extern void FP24_YYY_usqr(FP24_YYY *x,FP24_YYY *y);
+/**	@brief Squaring an FP24
+ *
+	@param x FP24 instance, on exit = y^2
+	@param y FP24 instance
+ */
+extern void FP24_YYY_sqr(FP24_YYY *x,FP24_YYY *y);
+/**	@brief Fast multiplication of an FP24 by an FP24 that arises from an ATE pairing line function
+ *
+	Here the multiplier has a special form that can be exploited
+	@param x FP24 instance, on exit = x*y
+	@param y FP24 instance, of special form
+	@param t D_TYPE or M_TYPE twist
+ */
+extern void FP24_YYY_smul(FP24_YYY *x,FP24_YYY *y,int t);
+/**	@brief Multiplication of two FP24s
+ *
+	@param x FP24 instance, on exit = x*y
+	@param y FP24 instance, the multiplier
+ */
+extern void FP24_YYY_mul(FP24_YYY *x,FP24_YYY *y);
+/**	@brief Inverting an FP24
+ *
+	@param x FP24 instance, on exit = 1/y
+	@param y FP24 instance
+ */
+extern void FP24_YYY_inv(FP24_YYY *x,FP24_YYY *y);
+/**	@brief Raises an FP24 to the power of a BIG
+ *
+	@param r FP24 instance, on exit = y^b
+	@param x FP24 instance
+	@param b BIG number
+ */
+extern void FP24_YYY_pow(FP24_YYY *r,FP24_YYY *x,BIG_XXX b);
+
+//extern void FP24_ppow(FP24 *r,FP24 *x,BIG b);
+
+/**	@brief Raises an FP24 instance x to a small integer power, side-channel resistant
+ *
+	@param x FP24 instance, on exit = x^i
+	@param i small integer exponent
+	@param b maximum number of bits in exponent
+ */
+extern void FP24_YYY_pinpow(FP24_YYY *x,int i,int b);
+
+/**	@brief Raises an FP24 instance x to a BIG power, compressed to FP8 
+ *
+	@param c FP8 instance, on exit = x^(e mod r) as FP8
+	@param x FP24 input
+	@param e BIG exponent
+	@param r BIG group order
+ */
+extern void FP24_YYY_compow(FP8_YYY *c,FP24_YYY *x,BIG_XXX e,BIG_XXX r);
+
+/**	@brief Calculate Pi x[i]^b[i] for i=0 to 7, side-channel resistant
+ *
+	@param r FP24 instance, on exit = Pi x[i]^b[i] for i=0 to 7
+	@param x FP24 array with 4 FP24s
+	@param b BIG array of 4 exponents
+ */
+extern void FP24_YYY_pow8(FP24_YYY *r,FP24_YYY *x,BIG_XXX *b);
+
+
+/**	@brief Raises an FP24 to the power of the internal modulus p, using the Frobenius
+ *
+	@param x FP24 instance, on exit = x^p^n
+	@param f FP2 precalculated Frobenius constant
+	@param n power of p
+ */
+extern void FP24_YYY_frob(FP24_YYY *x,FP2_YYY *f,int n);
+
+/**	@brief Reduces all components of possibly unreduced FP24 mod Modulus
+ *
+	@param x FP24 instance, on exit reduced mod Modulus
+ */
+extern void FP24_YYY_reduce(FP24_YYY *x);
+/**	@brief Normalises the components of an FP24
+ *
+	@param x FP24 instance to be normalised
+ */
+extern void FP24_YYY_norm(FP24_YYY *x);
+/**	@brief Formats and outputs an FP24 to the console
+ *
+	@param x FP24 instance to be printed
+ */
+extern void FP24_YYY_output(FP24_YYY *x);
+/**	@brief Formats and outputs an FP24 instance to an octet string
+ *
+	Serializes the components of an FP24 to big-endian base 256 form.
+	@param S output octet string
+	@param x FP24 instance to be converted to an octet string
+ */
+extern void FP24_YYY_toOctet(octet *S,FP24_YYY *x);
+/**	@brief Creates an FP24 instance from an octet string
+ *
+	De-serializes the components of an FP24 to create an FP24 from big-endian base 256 components.
+	@param x FP24 instance to be created from an octet string
+	@param S input octet string
+
+ */
+extern void FP24_YYY_fromOctet(FP24_YYY *x,octet *S);
+/**	@brief Calculate the trace of an FP24
+ *
+	@param t FP8 trace of x, on exit = tr(x)
+	@param x FP24 instance
+
+ */
+extern void FP24_YYY_trace(FP8_YYY *t,FP24_YYY *x);
+
+/**	@brief Conditional copy of FP24_YYY number
+ *
+	Conditionally copies second parameter to the first (without branching)
+	@param x FP24_YYY instance, set to y if s!=0
+	@param y another FP24_YYY instance
+	@param s copy only takes place if not equal to 0
+ */
+extern void FP24_YYY_cmove(FP24_YYY *x,FP24_YYY *y,int s);
+
+#endif
diff --git a/version3/c/fp4.c b/version3/c/fp4.c
new file mode 100644
index 0000000..758ddf6
--- /dev/null
+++ b/version3/c/fp4.c
@@ -0,0 +1,800 @@
+/*
+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.
+*/
+
+/* AMCL Fp^4 functions */
+/* SU=m, m is Stack Usage (no lazy )*/
+
+/* FP4 elements are of the form a+ib, where i is sqrt(-1+sqrt(-1)) */
+
+#include "fp4_YYY.h"
+
+/* test x==0 ? */
+/* SU= 8 */
+int FP4_YYY_iszilch(FP4_YYY *x)
+{
+    if (FP2_YYY_iszilch(&(x->a)) && FP2_YYY_iszilch(&(x->b))) return 1;
+    return 0;
+}
+
+/* test x==1 ? */
+/* SU= 8 */
+int FP4_YYY_isunity(FP4_YYY *x)
+{
+    if (FP2_YYY_isunity(&(x->a)) && FP2_YYY_iszilch(&(x->b))) return 1;
+    return 0;
+}
+
+/* test is w real? That is in a+ib test b is zero */
+int FP4_YYY_isreal(FP4_YYY *w)
+{
+    return FP2_YYY_iszilch(&(w->b));
+}
+
+/* return 1 if x==y, else 0 */
+/* SU= 16 */
+int FP4_YYY_equals(FP4_YYY *x,FP4_YYY *y)
+{
+    if (FP2_YYY_equals(&(x->a),&(y->a)) && FP2_YYY_equals(&(x->b),&(y->b)))
+        return 1;
+    return 0;
+}
+
+/* set FP4 from two FP2s */
+/* SU= 16 */
+void FP4_YYY_from_FP2s(FP4_YYY *w,FP2_YYY * x,FP2_YYY* y)
+{
+    FP2_YYY_copy(&(w->a), x);
+    FP2_YYY_copy(&(w->b), y);
+}
+
+/* set FP4 from FP2 */
+/* SU= 8 */
+void FP4_YYY_from_FP2(FP4_YYY *w,FP2_YYY *x)
+{
+    FP2_YYY_copy(&(w->a), x);
+    FP2_YYY_zero(&(w->b));
+}
+
+/* set high part of FP4 from FP2 */
+/* SU= 8 */
+void FP4_YYY_from_FP2H(FP4_YYY *w,FP2_YYY *x)
+{
+    FP2_YYY_copy(&(w->b), x);
+    FP2_YYY_zero(&(w->a));
+}
+
+/* FP4 copy w=x */
+/* SU= 16 */
+void FP4_YYY_copy(FP4_YYY *w,FP4_YYY *x)
+{
+    if (w==x) return;
+    FP2_YYY_copy(&(w->a), &(x->a));
+    FP2_YYY_copy(&(w->b), &(x->b));
+}
+
+/* FP4 w=0 */
+/* SU= 8 */
+void FP4_YYY_zero(FP4_YYY *w)
+{
+    FP2_YYY_zero(&(w->a));
+    FP2_YYY_zero(&(w->b));
+}
+
+/* FP4 w=1 */
+/* SU= 8 */
+void FP4_YYY_one(FP4_YYY *w)
+{
+    FP2_YYY_one(&(w->a));
+    FP2_YYY_zero(&(w->b));
+}
+
+/* Set w=-x */
+/* SU= 160 */
+void FP4_YYY_neg(FP4_YYY *w,FP4_YYY *x)
+{
+    /* Just one field neg */
+    FP2_YYY m,t;
+	FP4_YYY_norm(x);
+    FP2_YYY_add(&m,&(x->a),&(x->b));
+//	FP2_YYY_norm(&m);
+    FP2_YYY_neg(&m,&m);
+//    FP2_YYY_norm(&m);
+    FP2_YYY_add(&t,&m,&(x->b));
+    FP2_YYY_add(&(w->b),&m,&(x->a));
+    FP2_YYY_copy(&(w->a),&t);
+    FP4_YYY_norm(w);
+}
+
+/* Set w=conj(x) */
+/* SU= 16 */
+void FP4_YYY_conj(FP4_YYY *w,FP4_YYY *x)
+{
+    FP2_YYY_copy(&(w->a), &(x->a));
+    FP2_YYY_neg(&(w->b), &(x->b));
+    FP4_YYY_norm(w);
+}
+
+/* Set w=-conj(x) */
+/* SU= 16 */
+void FP4_YYY_nconj(FP4_YYY *w,FP4_YYY *x)
+{
+    FP2_YYY_copy(&(w->b),&(x->b));
+    FP2_YYY_neg(&(w->a), &(x->a));
+    FP4_YYY_norm(w);
+}
+
+/* Set w=x+y */
+/* SU= 16 */
+void FP4_YYY_add(FP4_YYY *w,FP4_YYY *x,FP4_YYY *y)
+{
+    FP2_YYY_add(&(w->a), &(x->a), &(y->a));
+    FP2_YYY_add(&(w->b), &(x->b), &(y->b));
+}
+
+/* Set w=x-y */
+/* Input y MUST be normed */
+void FP4_YYY_sub(FP4_YYY *w,FP4_YYY *x,FP4_YYY *y)
+{
+    FP4_YYY my;
+
+    FP4_YYY_neg(&my, y);
+    FP4_YYY_add(w, x, &my);
+
+}
+/* SU= 8 */
+/* reduce all components of w mod Modulus */
+void FP4_YYY_reduce(FP4_YYY *w)
+{
+    FP2_YYY_reduce(&(w->a));
+    FP2_YYY_reduce(&(w->b));
+}
+
+/* SU= 8 */
+/* normalise all elements of w */
+void FP4_YYY_norm(FP4_YYY *w)
+{
+    FP2_YYY_norm(&(w->a));
+    FP2_YYY_norm(&(w->b));
+}
+
+/* Set w=s*x, where s is FP2 */
+/* SU= 16 */
+void FP4_YYY_pmul(FP4_YYY *w,FP4_YYY *x,FP2_YYY *s)
+{
+    FP2_YYY_mul(&(w->a),&(x->a),s);
+    FP2_YYY_mul(&(w->b),&(x->b),s);
+}
+
+/* Set w=s*x, where s is FP */
+void FP4_YYY_qmul(FP4_YYY *w,FP4_YYY *x,FP_YYY *s)
+{
+    FP2_YYY_pmul(&(w->a),&(x->a),s);
+    FP2_YYY_pmul(&(w->b),&(x->b),s);
+}
+
+/* SU= 16 */
+/* Set w=s*x, where s is int */
+void FP4_YYY_imul(FP4_YYY *w,FP4_YYY *x,int s)
+{
+    FP2_YYY_imul(&(w->a),&(x->a),s);
+    FP2_YYY_imul(&(w->b),&(x->b),s);
+}
+
+/* Set w=x^2 */
+/* Input MUST be normed  */
+void FP4_YYY_sqr(FP4_YYY *w,FP4_YYY *x)
+{
+    FP2_YYY t1,t2,t3;
+
+    FP2_YYY_mul(&t3,&(x->a),&(x->b)); /* norms x */
+    FP2_YYY_copy(&t2,&(x->b));
+    FP2_YYY_add(&t1,&(x->a),&(x->b));
+    FP2_YYY_mul_ip(&t2);
+
+    FP2_YYY_add(&t2,&(x->a),&t2);
+
+    FP2_YYY_norm(&t1);  // 2
+    FP2_YYY_norm(&t2);  // 2
+
+    FP2_YYY_mul(&(w->a),&t1,&t2);
+
+    FP2_YYY_copy(&t2,&t3);
+    FP2_YYY_mul_ip(&t2);
+
+    FP2_YYY_add(&t2,&t2,&t3);
+
+    FP2_YYY_norm(&t2);  // 2
+    FP2_YYY_neg(&t2,&t2);
+    FP2_YYY_add(&(w->a),&(w->a),&t2);  /* a=(a+b)(a+i^2.b)-i^2.ab-ab = a*a+ib*ib */
+    FP2_YYY_add(&(w->b),&t3,&t3);  /* b=2ab */
+
+    FP4_YYY_norm(w);
+}
+
+/* Set w=x*y */
+/* Inputs MUST be normed  */
+void FP4_YYY_mul(FP4_YYY *w,FP4_YYY *x,FP4_YYY *y)
+{
+
+    FP2_YYY t1,t2,t3,t4;
+    FP2_YYY_mul(&t1,&(x->a),&(y->a));
+    FP2_YYY_mul(&t2,&(x->b),&(y->b));
+
+    FP2_YYY_add(&t3,&(y->b),&(y->a));
+    FP2_YYY_add(&t4,&(x->b),&(x->a));
+
+    FP2_YYY_norm(&t4); // 2
+    FP2_YYY_norm(&t3); // 2
+
+    FP2_YYY_mul(&t4,&t4,&t3); /* (xa+xb)(ya+yb) */
+
+    FP2_YYY_neg(&t3,&t1);  // 1
+    FP2_YYY_add(&t4,&t4,&t3);  //t4E=3
+    FP2_YYY_norm(&t4);
+
+    FP2_YYY_neg(&t3,&t2);  // 1
+    FP2_YYY_add(&(w->b),&t4,&t3); //wbE=3
+
+    FP2_YYY_mul_ip(&t2);
+    FP2_YYY_add(&(w->a),&t2,&t1);
+
+    FP4_YYY_norm(w);
+}
+
+/* output FP4 in format [a,b] */
+/* SU= 8 */
+void FP4_YYY_output(FP4_YYY *w)
+{
+    printf("[");
+    FP2_YYY_output(&(w->a));
+    printf(",");
+    FP2_YYY_output(&(w->b));
+    printf("]");
+}
+
+/* SU= 8 */
+void FP4_YYY_rawoutput(FP4_YYY *w)
+{
+    printf("[");
+    FP2_YYY_rawoutput(&(w->a));
+    printf(",");
+    FP2_YYY_rawoutput(&(w->b));
+    printf("]");
+}
+
+/* Set w=1/x */
+/* SU= 160 */
+void FP4_YYY_inv(FP4_YYY *w,FP4_YYY *x)
+{
+    FP2_YYY t1,t2;
+    FP2_YYY_sqr(&t1,&(x->a));
+    FP2_YYY_sqr(&t2,&(x->b));
+    FP2_YYY_mul_ip(&t2);
+    FP2_YYY_norm(&t2);
+    FP2_YYY_sub(&t1,&t1,&t2);
+    FP2_YYY_inv(&t1,&t1);
+    FP2_YYY_mul(&(w->a),&t1,&(x->a));
+    FP2_YYY_neg(&t1,&t1);
+    FP2_YYY_norm(&t1);
+    FP2_YYY_mul(&(w->b),&t1,&(x->b));
+}
+
+/* w*=i where i = sqrt(-1+sqrt(-1)) */
+/* SU= 200 */
+void FP4_YYY_times_i(FP4_YYY *w)
+{
+    FP_YYY z;
+    FP2_YYY s,t;
+
+//    FP4_YYY_norm(w);
+    FP2_YYY_copy(&t,&(w->b));
+
+    FP2_YYY_copy(&s,&t);
+
+    FP_YYY_copy(&z,&(s.a));
+    FP_YYY_neg(&(s.a),&(s.b));
+    FP_YYY_copy(&(s.b),&z);
+
+    FP2_YYY_add(&t,&t,&s);
+
+    FP2_YYY_copy(&(w->b),&(w->a));
+    FP2_YYY_copy(&(w->a),&t);
+    FP4_YYY_norm(w);
+}
+
+/* Set w=w^p using Frobenius */
+/* SU= 16 */
+void FP4_YYY_frob(FP4_YYY *w,FP2_YYY *f)
+{
+    FP2_YYY_conj(&(w->a),&(w->a));
+    FP2_YYY_conj(&(w->b),&(w->b));
+    FP2_YYY_mul( &(w->b),f,&(w->b));
+}
+
+/* Set r=a^b mod m */
+/* SU= 240 */
+void FP4_YYY_pow(FP4_YYY *r,FP4_YYY* a,BIG_XXX b)
+{
+    FP4_YYY w;
+    BIG_XXX z,zilch;
+    int bt;
+
+    BIG_XXX_zero(zilch);
+
+    BIG_XXX_copy(z,b);
+    BIG_XXX_norm(z);
+    FP4_YYY_copy(&w,a);
+	FP4_YYY_norm(&w);
+    FP4_YYY_one(r);
+
+    while(1)
+    {
+        bt=BIG_XXX_parity(z);
+        BIG_XXX_shr(z,1);
+        if (bt) FP4_YYY_mul(r,r,&w);
+        if (BIG_XXX_comp(z,zilch)==0) break;
+        FP4_YYY_sqr(&w,&w);
+    }
+    FP4_YYY_reduce(r);
+}
+
+/* SU= 304 */
+/* XTR xtr_a function */
+void FP4_YYY_xtr_A(FP4_YYY *r,FP4_YYY *w,FP4_YYY *x,FP4_YYY *y,FP4_YYY *z)
+{
+    FP4_YYY t1,t2;
+
+    FP4_YYY_copy(r,x);
+//FP4_YYY_norm(y);
+    FP4_YYY_sub(&t1,w,y);
+    FP4_YYY_norm(&t1);
+    FP4_YYY_pmul(&t1,&t1,&(r->a));
+    FP4_YYY_add(&t2,w,y);
+    FP4_YYY_norm(&t2);
+    FP4_YYY_pmul(&t2,&t2,&(r->b));
+    FP4_YYY_times_i(&t2);
+
+    FP4_YYY_add(r,&t1,&t2);
+    FP4_YYY_add(r,r,z);
+
+    FP4_YYY_reduce(r);
+}
+
+/* SU= 152 */
+/* XTR xtr_d function */
+void FP4_YYY_xtr_D(FP4_YYY *r,FP4_YYY *x)
+{
+    FP4_YYY w;
+    FP4_YYY_copy(r,x);
+    FP4_YYY_conj(&w,r);
+    FP4_YYY_add(&w,&w,&w);
+    FP4_YYY_sqr(r,r);
+    FP4_YYY_norm(&w);
+    FP4_YYY_sub(r,r,&w);
+    FP4_YYY_reduce(r);    /* reduce here as multiple calls trigger automatic reductions */
+}
+
+/* SU= 728 */
+/* r=x^n using XTR method on traces of FP12s */
+void FP4_YYY_xtr_pow(FP4_YYY *r,FP4_YYY *x,BIG_XXX n)
+{
+    int i,par,nb;
+    BIG_XXX v;
+    FP2_YYY w;
+    FP4_YYY t,a,b,c,sf;
+
+    BIG_XXX_zero(v);
+    BIG_XXX_inc(v,3);
+    BIG_XXX_norm(v);
+    FP2_YYY_from_BIG(&w,v);
+    FP4_YYY_from_FP2(&a,&w);
+
+	FP4_YYY_copy(&sf,x);
+	FP4_YYY_norm(&sf);
+    FP4_YYY_copy(&b,&sf);
+    FP4_YYY_xtr_D(&c,&sf);
+
+    //BIG_XXX_norm(n);
+    par=BIG_XXX_parity(n);
+    BIG_XXX_copy(v,n);
+	BIG_XXX_norm(v);
+    BIG_XXX_shr(v,1);
+    if (par==0)
+    {
+        BIG_XXX_dec(v,1);
+        BIG_XXX_norm(v);
+    }
+
+    nb=BIG_XXX_nbits(v);
+    for (i=nb-1; i>=0; i--)
+    {
+        if (!BIG_XXX_bit(v,i))
+        {
+            FP4_YYY_copy(&t,&b);
+            FP4_YYY_conj(&sf,&sf);
+            FP4_YYY_conj(&c,&c);
+            FP4_YYY_xtr_A(&b,&a,&b,&sf,&c);
+            FP4_YYY_conj(&sf,&sf);
+            FP4_YYY_xtr_D(&c,&t);
+            FP4_YYY_xtr_D(&a,&a);
+        }
+        else
+        {
+            FP4_YYY_conj(&t,&a);
+            FP4_YYY_xtr_D(&a,&b);
+            FP4_YYY_xtr_A(&b,&c,&b,&sf,&t);
+            FP4_YYY_xtr_D(&c,&c);
+        }
+    }
+
+    if (par==0) FP4_YYY_copy(r,&c);
+    else FP4_YYY_copy(r,&b);
+    FP4_YYY_reduce(r);
+}
+
+/* SU= 872 */
+/* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */
+void FP4_YYY_xtr_pow2(FP4_YYY *r,FP4_YYY *ck,FP4_YYY *cl,FP4_YYY *ckml,FP4_YYY *ckm2l,BIG_XXX a,BIG_XXX b)
+{
+    int i,f2;
+    BIG_XXX d,e,w;
+    FP4_YYY t,cu,cv,cumv,cum2v;
+
+
+    BIG_XXX_copy(e,a);
+    BIG_XXX_copy(d,b);
+    BIG_XXX_norm(e);
+    BIG_XXX_norm(d);
+    FP4_YYY_copy(&cu,ck);
+    FP4_YYY_copy(&cv,cl);
+    FP4_YYY_copy(&cumv,ckml);
+    FP4_YYY_copy(&cum2v,ckm2l);
+
+    f2=0;
+    while (BIG_XXX_parity(d)==0 && BIG_XXX_parity(e)==0)
+    {
+        BIG_XXX_shr(d,1);
+        BIG_XXX_shr(e,1);
+        f2++;
+    }
+    while (BIG_XXX_comp(d,e)!=0)
+    {
+        if (BIG_XXX_comp(d,e)>0)
+        {
+            BIG_XXX_imul(w,e,4);
+            BIG_XXX_norm(w);
+            if (BIG_XXX_comp(d,w)<=0)
+            {
+                BIG_XXX_copy(w,d);
+                BIG_XXX_copy(d,e);
+                BIG_XXX_sub(e,w,e);
+                BIG_XXX_norm(e);
+                FP4_YYY_xtr_A(&t,&cu,&cv,&cumv,&cum2v);
+                FP4_YYY_conj(&cum2v,&cumv);
+                FP4_YYY_copy(&cumv,&cv);
+                FP4_YYY_copy(&cv,&cu);
+                FP4_YYY_copy(&cu,&t);
+            }
+            else if (BIG_XXX_parity(d)==0)
+            {
+                BIG_XXX_shr(d,1);
+                FP4_YYY_conj(r,&cum2v);
+                FP4_YYY_xtr_A(&t,&cu,&cumv,&cv,r);
+                FP4_YYY_xtr_D(&cum2v,&cumv);
+                FP4_YYY_copy(&cumv,&t);
+                FP4_YYY_xtr_D(&cu,&cu);
+            }
+            else if (BIG_XXX_parity(e)==1)
+            {
+                BIG_XXX_sub(d,d,e);
+                BIG_XXX_norm(d);
+                BIG_XXX_shr(d,1);
+                FP4_YYY_xtr_A(&t,&cu,&cv,&cumv,&cum2v);
+                FP4_YYY_xtr_D(&cu,&cu);
+                FP4_YYY_xtr_D(&cum2v,&cv);
+                FP4_YYY_conj(&cum2v,&cum2v);
+                FP4_YYY_copy(&cv,&t);
+            }
+            else
+            {
+                BIG_XXX_copy(w,d);
+                BIG_XXX_copy(d,e);
+                BIG_XXX_shr(d,1);
+                BIG_XXX_copy(e,w);
+                FP4_YYY_xtr_D(&t,&cumv);
+                FP4_YYY_conj(&cumv,&cum2v);
+                FP4_YYY_conj(&cum2v,&t);
+                FP4_YYY_xtr_D(&t,&cv);
+                FP4_YYY_copy(&cv,&cu);
+                FP4_YYY_copy(&cu,&t);
+            }
+        }
+        if (BIG_XXX_comp(d,e)<0)
+        {
+            BIG_XXX_imul(w,d,4);
+            BIG_XXX_norm(w);
+            if (BIG_XXX_comp(e,w)<=0)
+            {
+                BIG_XXX_sub(e,e,d);
+                BIG_XXX_norm(e);
+                FP4_YYY_xtr_A(&t,&cu,&cv,&cumv,&cum2v);
+                FP4_YYY_copy(&cum2v,&cumv);
+                FP4_YYY_copy(&cumv,&cu);
+                FP4_YYY_copy(&cu,&t);
+            }
+            else if (BIG_XXX_parity(e)==0)
+            {
+                BIG_XXX_copy(w,d);
+                BIG_XXX_copy(d,e);
+                BIG_XXX_shr(d,1);
+                BIG_XXX_copy(e,w);
+                FP4_YYY_xtr_D(&t,&cumv);
+                FP4_YYY_conj(&cumv,&cum2v);
+                FP4_YYY_conj(&cum2v,&t);
+                FP4_YYY_xtr_D(&t,&cv);
+                FP4_YYY_copy(&cv,&cu);
+                FP4_YYY_copy(&cu,&t);
+            }
+            else if (BIG_XXX_parity(d)==1)
+            {
+                BIG_XXX_copy(w,e);
+                BIG_XXX_copy(e,d);
+                BIG_XXX_sub(w,w,d);
+                BIG_XXX_norm(w);
+                BIG_XXX_copy(d,w);
+                BIG_XXX_shr(d,1);
+                FP4_YYY_xtr_A(&t,&cu,&cv,&cumv,&cum2v);
+                FP4_YYY_conj(&cumv,&cumv);
+                FP4_YYY_xtr_D(&cum2v,&cu);
+                FP4_YYY_conj(&cum2v,&cum2v);
+                FP4_YYY_xtr_D(&cu,&cv);
+                FP4_YYY_copy(&cv,&t);
+            }
+            else
+            {
+                BIG_XXX_shr(d,1);
+                FP4_YYY_conj(r,&cum2v);
+                FP4_YYY_xtr_A(&t,&cu,&cumv,&cv,r);
+                FP4_YYY_xtr_D(&cum2v,&cumv);
+                FP4_YYY_copy(&cumv,&t);
+                FP4_YYY_xtr_D(&cu,&cu);
+            }
+        }
+    }
+    FP4_YYY_xtr_A(r,&cu,&cv,&cumv,&cum2v);
+    for (i=0; i<f2; i++)	FP4_YYY_xtr_D(r,r);
+    FP4_YYY_xtr_pow(r,r,d);
+}
+
+/* Move b to a if d=1 */
+void FP4_YYY_cmove(FP4_YYY *f,FP4_YYY *g,int d)
+{
+    FP2_YYY_cmove(&(f->a),&(g->a),d);
+    FP2_YYY_cmove(&(f->b),&(g->b),d);
+}
+
+/* New stuff for ECp4 support */
+
+/* Set w=x/2 */
+void FP4_YYY_div2(FP4_YYY *w,FP4_YYY *x)
+{
+    FP2_YYY_div2(&(w->a),&(x->a));
+    FP2_YYY_div2(&(w->b),&(x->b));
+}
+
+#if CURVE_SECURITY_ZZZ >= 192
+
+/* sqrt(a+xb) = sqrt((a+sqrt(a*a-n*b*b))/2)+x.b/(2*sqrt((a+sqrt(a*a-n*b*b))/2)) */
+/* returns true if x is QR */
+int FP4_YYY_sqrt(FP4_YYY *r,FP4_YYY* x)
+{
+    FP2_YYY a,s,t;
+
+    FP4_YYY_copy(r,x);
+    if (FP4_YYY_iszilch(x))
+        return 1;
+    
+    FP2_YYY_copy(&a,&(x->a));
+    FP2_YYY_copy(&s,&(x->b));
+
+    if (FP2_YYY_iszilch(&s))
+    {
+        if (FP2_YYY_sqrt(&t,&a))
+        {
+            FP4_YYY_from_FP2(r,&t);
+        }
+        else
+        {
+            FP2_YYY_div_ip(&a);
+            FP2_YYY_sqrt(&t,&a);
+            FP4_YYY_from_FP2H(r,&t);
+        }
+        return 1;
+    }
+
+    FP2_YYY_sqr(&s,&s);  // s*=s
+    FP2_YYY_sqr(&a,&a);  // a*=a
+    FP2_YYY_mul_ip(&s);
+    FP2_YYY_norm(&s);
+    FP2_YYY_sub(&a,&a,&s); // a-=txx(s)
+
+    if (!FP2_YYY_sqrt(&s,&a)) return 0;
+
+    //FP2_YYY_sqr(&t,&s);
+
+
+    FP2_YYY_copy(&t,&(x->a));
+    FP2_YYY_add(&a,&t,&s);
+    FP2_YYY_norm(&a);
+    FP2_YYY_div2(&a,&a);
+
+    if (!FP2_YYY_sqrt(&a,&a))
+    {
+        FP2_YYY_sub(&a,&t,&s);
+        FP2_YYY_norm(&a);
+        FP2_YYY_div2(&a,&a);
+        if (!FP2_YYY_sqrt(&a,&a)) return 0;
+    }
+
+    FP2_YYY_copy(&t,&(x->b));
+    FP2_YYY_add(&s,&a,&a);
+    FP2_YYY_inv(&s,&s);
+
+    FP2_YYY_mul(&t,&t,&s);
+    FP4_YYY_from_FP2s(r,&a,&t);
+
+    return 1;
+
+}
+
+void FP4_YYY_div_i(FP4_YYY *f)
+{
+    FP2_YYY u,v;
+    FP2_YYY_copy(&u,&(f->a));
+    FP2_YYY_copy(&v,&(f->b));
+    FP2_YYY_div_ip(&u);
+    FP2_YYY_copy(&(f->a),&v);
+    FP2_YYY_copy(&(f->b),&u);
+}
+
+void FP4_YYY_div_2i(FP4_YYY *f)
+{
+	FP2_YYY u,v;
+	FP2_YYY_copy(&u,&(f->a));
+	FP2_YYY_copy(&v,&(f->b));
+	FP2_YYY_div_ip2(&u);
+	FP2_YYY_add(&v,&v,&v);
+	FP2_YYY_norm(&v);
+	FP2_YYY_copy(&(f->a),&v);
+	FP2_YYY_copy(&(f->b),&u);
+}
+
+#endif
+
+
+/*
+int main(){
+		FP2_YYY w0,w1,f;
+		FP4_YYY w,t;
+		FP4_YYY c1,c2,c3,c4,cr;
+		BIG_XXX a,b;
+		BIG_XXX e,e1,e2;
+		BIG_XXX p,md;
+
+
+		BIG_XXX_rcopy(md,Modulus);
+		//Test w^(P^4) = w mod p^2
+		BIG_XXX_zero(a); BIG_XXX_inc(a,27);
+		BIG_XXX_zero(b); BIG_XXX_inc(b,45);
+		FP2_YYY_from_BIGs(&w0,a,b);
+
+		BIG_XXX_zero(a); BIG_XXX_inc(a,33);
+		BIG_XXX_zero(b); BIG_XXX_inc(b,54);
+		FP2_YYY_from_BIGs(&w1,a,b);
+
+		FP4_YYY_from_FP2s(&w,&w0,&w1);
+		FP4_YYY_reduce(&w);
+
+		printf("w= ");
+		FP4_YYY_output(&w);
+		printf("\n");
+
+
+		FP4_YYY_copy(&t,&w);
+
+
+		BIG_XXX_copy(p,md);
+		FP4_YYY_pow(&w,&w,p);
+
+		printf("w^p= ");
+		FP4_YYY_output(&w);
+		printf("\n");
+//exit(0);
+
+		BIG_XXX_rcopy(a,CURVE_Fra);
+		BIG_XXX_rcopy(b,CURVE_Frb);
+		FP2_YYY_from_BIGs(&f,a,b);
+
+		FP4_YYY_frob(&t,&f);
+		printf("w^p= ");
+		FP4_YYY_output(&t);
+		printf("\n");
+
+		FP4_YYY_pow(&w,&w,p);
+		FP4_YYY_pow(&w,&w,p);
+		FP4_YYY_pow(&w,&w,p);
+		printf("w^p4= ");
+		FP4_YYY_output(&w);
+		printf("\n");
+
+// Test 1/(1/x) = x mod p^4
+		FP4_YYY_from_FP2s(&w,&w0,&w1);
+		printf("Test Inversion \nw= ");
+		FP4_YYY_output(&w);
+		printf("\n");
+
+		FP4_YYY_inv(&w,&w);
+		printf("1/w mod p^4 = ");
+		FP4_YYY_output(&w);
+		printf("\n");
+
+		FP4_YYY_inv(&w,&w);
+		printf("1/(1/w) mod p^4 = ");
+		FP4_YYY_output(&w);
+		printf("\n");
+
+		BIG_XXX_zero(e); BIG_XXX_inc(e,12);
+
+
+
+	//	FP4_YYY_xtr_A(&w,&t,&w,&t,&t);
+		FP4_YYY_xtr_pow(&w,&w,e);
+
+		printf("w^e= ");
+		FP4_YYY_output(&w);
+		printf("\n");
+
+
+		BIG_XXX_zero(a); BIG_XXX_inc(a,37);
+		BIG_XXX_zero(b); BIG_XXX_inc(b,17);
+		FP2_YYY_from_BIGs(&w0,a,b);
+
+		BIG_XXX_zero(a); BIG_XXX_inc(a,49);
+		BIG_XXX_zero(b); BIG_XXX_inc(b,31);
+		FP2_YYY_from_BIGs(&w1,a,b);
+
+		FP4_YYY_from_FP2s(&c1,&w0,&w1);
+		FP4_YYY_from_FP2s(&c2,&w0,&w1);
+		FP4_YYY_from_FP2s(&c3,&w0,&w1);
+		FP4_YYY_from_FP2s(&c4,&w0,&w1);
+
+		BIG_XXX_zero(e1); BIG_XXX_inc(e1,3331);
+		BIG_XXX_zero(e2); BIG_XXX_inc(e2,3372);
+
+		FP4_YYY_xtr_pow2(&w,&c1,&w,&c2,&c3,e1,e2);
+
+		printf("c^e= ");
+		FP4_YYY_output(&w);
+		printf("\n");
+
+
+		return 0;
+}
+*/
+
diff --git a/version3/c/fp4.h b/version3/c/fp4.h
new file mode 100644
index 0000000..451ab4a
--- /dev/null
+++ b/version3/c/fp4.h
@@ -0,0 +1,305 @@
+/*
+	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.
+*/
+
+/**
+ * @file fp4.h
+ * @author Mike Scott
+ * @brief FP4 Header File
+ *
+ */
+
+#ifndef FP4_YYY_H
+#define FP4_YYY_H
+
+#include "fp2_YYY.h"
+#include "config_curve_ZZZ.h"
+
+/**
+	@brief FP4 Structure - towered over two FP2
+*/
+
+typedef struct
+{
+    FP2_YYY a; /**< real part of FP4 */
+    FP2_YYY b; /**< imaginary part of FP4 */
+} FP4_YYY;
+
+
+/* FP4 prototypes */
+/**	@brief Tests for FP4 equal to zero
+ *
+	@param x FP4 number to be tested
+	@return 1 if zero, else returns 0
+ */
+extern int FP4_YYY_iszilch(FP4_YYY *x);
+/**	@brief Tests for FP4 equal to unity
+ *
+	@param x FP4 number to be tested
+	@return 1 if unity, else returns 0
+ */
+extern int FP4_YYY_isunity(FP4_YYY *x);
+/**	@brief Tests for equality of two FP4s
+ *
+	@param x FP4 instance to be compared
+	@param y FP4 instance to be compared
+	@return 1 if x=y, else returns 0
+ */
+extern int FP4_YYY_equals(FP4_YYY *x,FP4_YYY *y);
+/**	@brief Tests for FP4 having only a real part and no imaginary part
+ *
+	@param x FP4 number to be tested
+	@return 1 if real, else returns 0
+ */
+extern int FP4_YYY_isreal(FP4_YYY *x);
+/**	@brief Initialise FP4 from two FP2s
+ *
+	@param x FP4 instance to be initialised
+	@param a FP2 to form real part of FP4
+	@param b FP2 to form imaginary part of FP4
+ */
+extern void FP4_YYY_from_FP2s(FP4_YYY *x,FP2_YYY *a,FP2_YYY *b);
+/**	@brief Initialise FP4 from single FP2
+ *
+	Imaginary part is set to zero
+	@param x FP4 instance to be initialised
+	@param a FP2 to form real part of FP4
+ */
+extern void FP4_YYY_from_FP2(FP4_YYY *x,FP2_YYY *a);
+
+/**	@brief Initialise FP4 from single FP2
+ *
+	real part is set to zero
+	@param x FP4 instance to be initialised
+	@param a FP2 to form imaginary part of FP4
+ */
+extern void FP4_YYY_from_FP2H(FP4_YYY *x,FP2_YYY *a);
+
+
+/**	@brief Copy FP4 to another FP4
+ *
+	@param x FP4 instance, on exit = y
+	@param y FP4 instance to be copied
+ */
+extern void FP4_YYY_copy(FP4_YYY *x,FP4_YYY *y);
+/**	@brief Set FP4 to zero
+ *
+	@param x FP4 instance to be set to zero
+ */
+extern void FP4_YYY_zero(FP4_YYY *x);
+/**	@brief Set FP4 to unity
+ *
+	@param x FP4 instance to be set to one
+ */
+extern void FP4_YYY_one(FP4_YYY *x);
+/**	@brief Negation of FP4
+ *
+	@param x FP4 instance, on exit = -y
+	@param y FP4 instance
+ */
+extern void FP4_YYY_neg(FP4_YYY *x,FP4_YYY *y);
+/**	@brief Conjugation of FP4
+ *
+	If y=(a,b) on exit x=(a,-b)
+	@param x FP4 instance, on exit = conj(y)
+	@param y FP4 instance
+ */
+extern void FP4_YYY_conj(FP4_YYY *x,FP4_YYY *y);
+/**	@brief Negative conjugation of FP4
+ *
+	If y=(a,b) on exit x=(-a,b)
+	@param x FP4 instance, on exit = -conj(y)
+	@param y FP4 instance
+ */
+extern void FP4_YYY_nconj(FP4_YYY *x,FP4_YYY *y);
+/**	@brief addition of two FP4s
+ *
+	@param x FP4 instance, on exit = y+z
+	@param y FP4 instance
+	@param z FP4 instance
+ */
+extern void FP4_YYY_add(FP4_YYY *x,FP4_YYY *y,FP4_YYY *z);
+/**	@brief subtraction of two FP4s
+ *
+	@param x FP4 instance, on exit = y-z
+	@param y FP4 instance
+	@param z FP4 instance
+ */
+extern void FP4_YYY_sub(FP4_YYY *x,FP4_YYY *y,FP4_YYY *z);
+/**	@brief Multiplication of an FP4 by an FP2
+ *
+	@param x FP4 instance, on exit = y*a
+	@param y FP4 instance
+	@param a FP2 multiplier
+ */
+extern void FP4_YYY_pmul(FP4_YYY *x,FP4_YYY *y,FP2_YYY *a);
+
+/**	@brief Multiplication of an FP4 by an FP
+ *
+	@param x FP4 instance, on exit = y*a
+	@param y FP4 instance
+	@param a FP multiplier
+ */
+extern void FP4_YYY_qmul(FP4_YYY *x,FP4_YYY *y,FP_YYY *a);
+
+/**	@brief Multiplication of an FP4 by a small integer
+ *
+	@param x FP4 instance, on exit = y*i
+	@param y FP4 instance
+	@param i an integer
+ */
+extern void FP4_YYY_imul(FP4_YYY *x,FP4_YYY *y,int i);
+/**	@brief Squaring an FP4
+ *
+	@param x FP4 instance, on exit = y^2
+	@param y FP4 instance
+ */
+extern void FP4_YYY_sqr(FP4_YYY *x,FP4_YYY *y);
+/**	@brief Multiplication of two FP4s
+ *
+	@param x FP4 instance, on exit = y*z
+	@param y FP4 instance
+	@param z FP4 instance
+ */
+extern void FP4_YYY_mul(FP4_YYY *x,FP4_YYY *y,FP4_YYY *z);
+/**	@brief Inverting an FP4
+ *
+	@param x FP4 instance, on exit = 1/y
+	@param y FP4 instance
+ */
+extern void FP4_YYY_inv(FP4_YYY *x,FP4_YYY *y);
+/**	@brief Formats and outputs an FP4 to the console
+ *
+	@param x FP4 instance to be printed
+ */
+extern void FP4_YYY_output(FP4_YYY *x);
+/**	@brief Formats and outputs an FP4 to the console in raw form (for debugging)
+ *
+	@param x FP4 instance to be printed
+ */
+extern void FP4_YYY_rawoutput(FP4_YYY *x);
+/**	@brief multiplies an FP4 instance by irreducible polynomial sqrt(1+sqrt(-1))
+ *
+	@param x FP4 instance, on exit = sqrt(1+sqrt(-1)*x
+ */
+extern void FP4_YYY_times_i(FP4_YYY *x);
+/**	@brief Normalises the components of an FP4
+ *
+	@param x FP4 instance to be normalised
+ */
+extern void FP4_YYY_norm(FP4_YYY *x);
+/**	@brief Reduces all components of possibly unreduced FP4 mod Modulus
+ *
+	@param x FP4 instance, on exit reduced mod Modulus
+ */
+extern void FP4_YYY_reduce(FP4_YYY *x);
+/**	@brief Raises an FP4 to the power of a BIG
+ *
+	@param x FP4 instance, on exit = y^b
+	@param y FP4 instance
+	@param b BIG number
+ */
+extern void FP4_YYY_pow(FP4_YYY *x,FP4_YYY *y,BIG_XXX b);
+/**	@brief Raises an FP4 to the power of the internal modulus p, using the Frobenius
+ *
+	@param x FP4 instance, on exit = x^p
+	@param f FP2 precalculated Frobenius constant
+ */
+extern void FP4_YYY_frob(FP4_YYY *x,FP2_YYY *f);
+/**	@brief Calculates the XTR addition function r=w*x-conj(x)*y+z
+ *
+	@param r FP4 instance, on exit = w*x-conj(x)*y+z
+	@param w FP4 instance
+	@param x FP4 instance
+	@param y FP4 instance
+	@param z FP4 instance
+ */
+extern void FP4_YYY_xtr_A(FP4_YYY *r,FP4_YYY *w,FP4_YYY *x,FP4_YYY *y,FP4_YYY *z);
+/**	@brief Calculates the XTR doubling function r=x^2-2*conj(x)
+ *
+	@param r FP4 instance, on exit = x^2-2*conj(x)
+	@param x FP4 instance
+ */
+extern void FP4_YYY_xtr_D(FP4_YYY *r,FP4_YYY *x);
+/**	@brief Calculates FP4 trace of an FP12 raised to the power of a BIG number
+ *
+	XTR single exponentiation
+	@param r FP4 instance, on exit = trace(w^b)
+	@param x FP4 instance, trace of an FP12 w
+	@param b BIG number
+ */
+extern void FP4_YYY_xtr_pow(FP4_YYY *r,FP4_YYY *x,BIG_XXX b);
+/**	@brief Calculates FP4 trace of c^a.d^b, where c and d are derived from FP4 traces of FP12s
+ *
+	XTR double exponentiation
+	Assumes c=tr(x^m), d=tr(x^n), e=tr(x^(m-n)), f=tr(x^(m-2n))
+	@param r FP4 instance, on exit = trace(c^a.d^b)
+	@param c FP4 instance, trace of an FP12
+	@param d FP4 instance, trace of an FP12
+	@param e FP4 instance, trace of an FP12
+	@param f FP4 instance, trace of an FP12
+	@param a BIG number
+	@param b BIG number
+ */
+extern void FP4_YYY_xtr_pow2(FP4_YYY *r,FP4_YYY *c,FP4_YYY *d,FP4_YYY *e,FP4_YYY *f,BIG_XXX a,BIG_XXX b);
+
+/**	@brief Conditional copy of FP4 number
+ *
+	Conditionally copies second parameter to the first (without branching)
+	@param x FP4 instance, set to y if s!=0
+	@param y another FP4 instance
+	@param s copy only takes place if not equal to 0
+ */
+extern void FP4_YYY_cmove(FP4_YYY *x,FP4_YYY *y,int s);
+
+
+/**	@brief Calculate square root of an FP4
+ *
+	Square root
+	@param r FP4 instance, on exit = sqrt(x)
+	@param x FP4 instance
+	@return 1 x is a QR, otherwise 0
+ */
+extern int  FP4_YYY_sqrt(FP4_YYY *r,FP4_YYY *x);
+
+
+/**	@brief Divide FP4 number by QNR
+ *
+	Divide FP4 by the QNR
+	@param x FP4 instance
+ */
+extern void FP4_YYY_div_i(FP4_YYY *x);
+
+/**	@brief Divide an FP4 by QNR/2
+ *
+	Divide FP4 by the QNR/2
+	@param x FP4 instance
+ */
+extern void FP4_YYY_div_2i(FP4_YYY *x);
+
+
+
+/**	@brief Divide an FP4 by 2
+ *
+	@param x FP4 instance, on exit = y/2
+	@param y FP4 instance
+ */
+extern void FP4_YYY_div2(FP4_YYY *x,FP4_YYY *y);
+
+#endif
+
diff --git a/version3/c/fp48.c b/version3/c/fp48.c
new file mode 100644
index 0000000..b980903
--- /dev/null
+++ b/version3/c/fp48.c
@@ -0,0 +1,1385 @@
+/*
+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.
+*/
+
+/* AMCL Fp^48 functions */
+/* SU=m, m is Stack Usage (no lazy )*/
+/* FP48 elements are of the form a+i.b+i^2.c */
+
+#include "fp48_YYY.h"
+
+/* return 1 if b==c, no branching */
+static int teq(sign32 b,sign32 c)
+{
+    sign32 x=b^c;
+    x-=1;  // if x=0, x now -1
+    return (int)((x>>31)&1);
+}
+
+
+/* Constant time select from pre-computed table */
+static void FP48_YYY_select(FP48_YYY *f,FP48_YYY g[],sign32 b)
+{
+    FP48_YYY invf;
+    sign32 m=b>>31;
+    sign32 babs=(b^m)-m;
+
+    babs=(babs-1)/2;
+
+    FP48_YYY_cmove(f,&g[0],teq(babs,0));  // conditional move
+    FP48_YYY_cmove(f,&g[1],teq(babs,1));
+    FP48_YYY_cmove(f,&g[2],teq(babs,2));
+    FP48_YYY_cmove(f,&g[3],teq(babs,3));
+    FP48_YYY_cmove(f,&g[4],teq(babs,4));
+    FP48_YYY_cmove(f,&g[5],teq(babs,5));
+    FP48_YYY_cmove(f,&g[6],teq(babs,6));
+    FP48_YYY_cmove(f,&g[7],teq(babs,7));
+
+    FP48_YYY_copy(&invf,f);
+    FP48_YYY_conj(&invf,&invf);  // 1/f
+    FP48_YYY_cmove(f,&invf,(int)(m&1));
+}
+
+
+/* test x==0 ? */
+/* SU= 8 */
+int FP48_YYY_iszilch(FP48_YYY *x)
+{
+    if (FP16_YYY_iszilch(&(x->a)) && FP16_YYY_iszilch(&(x->b)) && FP16_YYY_iszilch(&(x->c))) return 1;
+    return 0;
+}
+
+/* test x==1 ? */
+/* SU= 8 */
+int FP48_YYY_isunity(FP48_YYY *x)
+{
+    if (FP16_YYY_isunity(&(x->a)) && FP16_YYY_iszilch(&(x->b)) && FP16_YYY_iszilch(&(x->c))) return 1;
+    return 0;
+}
+
+/* FP48 copy w=x */
+/* SU= 16 */
+void FP48_YYY_copy(FP48_YYY *w,FP48_YYY *x)
+{
+    if (x==w) return;
+    FP16_YYY_copy(&(w->a),&(x->a));
+    FP16_YYY_copy(&(w->b),&(x->b));
+    FP16_YYY_copy(&(w->c),&(x->c));
+}
+
+/* FP48 w=1 */
+/* SU= 8 */
+void FP48_YYY_one(FP48_YYY *w)
+{
+    FP16_YYY_one(&(w->a));
+    FP16_YYY_zero(&(w->b));
+    FP16_YYY_zero(&(w->c));
+}
+
+/* return 1 if x==y, else 0 */
+/* SU= 16 */
+int FP48_YYY_equals(FP48_YYY *x,FP48_YYY *y)
+{
+    if (FP16_YYY_equals(&(x->a),&(y->a)) && FP16_YYY_equals(&(x->b),&(y->b)) && FP16_YYY_equals(&(x->b),&(y->b)))
+        return 1;
+    return 0;
+}
+
+/* Set w=conj(x) */
+/* SU= 8 */
+void FP48_YYY_conj(FP48_YYY *w,FP48_YYY *x)
+{
+    FP48_YYY_copy(w,x);
+    FP16_YYY_conj(&(w->a),&(w->a));
+    FP16_YYY_nconj(&(w->b),&(w->b));
+    FP16_YYY_conj(&(w->c),&(w->c));
+}
+
+/* Create FP48 from FP16 */
+/* SU= 8 */
+void FP48_YYY_from_FP16(FP48_YYY *w,FP16_YYY *a)
+{
+    FP16_YYY_copy(&(w->a),a);
+    FP16_YYY_zero(&(w->b));
+    FP16_YYY_zero(&(w->c));
+}
+
+/* Create FP48 from 3 FP16's */
+/* SU= 16 */
+void FP48_YYY_from_FP16s(FP48_YYY *w,FP16_YYY *a,FP16_YYY *b,FP16_YYY *c)
+{
+    FP16_YYY_copy(&(w->a),a);
+    FP16_YYY_copy(&(w->b),b);
+    FP16_YYY_copy(&(w->c),c);
+}
+
+/* Granger-Scott Unitary Squaring. This does not benefit from lazy reduction */
+/* SU= 600 */
+void FP48_YYY_usqr(FP48_YYY *w,FP48_YYY *x)
+{
+    FP16_YYY A,B,C,D;
+
+    FP16_YYY_copy(&A,&(x->a));
+
+    FP16_YYY_sqr(&(w->a),&(x->a));
+    FP16_YYY_add(&D,&(w->a),&(w->a));
+    FP16_YYY_add(&(w->a),&D,&(w->a));
+
+    FP16_YYY_norm(&(w->a));
+    FP16_YYY_nconj(&A,&A);
+
+    FP16_YYY_add(&A,&A,&A);
+    FP16_YYY_add(&(w->a),&(w->a),&A);
+    FP16_YYY_sqr(&B,&(x->c));
+    FP16_YYY_times_i(&B);
+
+    FP16_YYY_add(&D,&B,&B);
+    FP16_YYY_add(&B,&B,&D);
+    FP16_YYY_norm(&B);
+
+    FP16_YYY_sqr(&C,&(x->b));
+
+    FP16_YYY_add(&D,&C,&C);
+    FP16_YYY_add(&C,&C,&D);
+
+    FP16_YYY_norm(&C);
+    FP16_YYY_conj(&(w->b),&(x->b));
+    FP16_YYY_add(&(w->b),&(w->b),&(w->b));
+    FP16_YYY_nconj(&(w->c),&(x->c));
+
+    FP16_YYY_add(&(w->c),&(w->c),&(w->c));
+    FP16_YYY_add(&(w->b),&B,&(w->b));
+    FP16_YYY_add(&(w->c),&C,&(w->c));
+
+    FP48_YYY_reduce(w);	    /* reduce here as in pow function repeated squarings would trigger multiple reductions */
+}
+
+/* FP48 squaring w=x^2 */
+/* SU= 600 */
+void FP48_YYY_sqr(FP48_YYY *w,FP48_YYY *x)
+{
+    /* Use Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
+
+    FP16_YYY A,B,C,D;
+
+    FP16_YYY_sqr(&A,&(x->a));
+    FP16_YYY_mul(&B,&(x->b),&(x->c));
+    FP16_YYY_add(&B,&B,&B);
+FP16_YYY_norm(&B);
+    FP16_YYY_sqr(&C,&(x->c));
+
+    FP16_YYY_mul(&D,&(x->a),&(x->b));
+    FP16_YYY_add(&D,&D,&D);
+
+    FP16_YYY_add(&(w->c),&(x->a),&(x->c));
+    FP16_YYY_add(&(w->c),&(x->b),&(w->c));
+FP16_YYY_norm(&(w->c));	
+
+    FP16_YYY_sqr(&(w->c),&(w->c));
+
+    FP16_YYY_copy(&(w->a),&A);
+    FP16_YYY_add(&A,&A,&B);
+
+    FP16_YYY_norm(&A);
+
+    FP16_YYY_add(&A,&A,&C);
+    FP16_YYY_add(&A,&A,&D);
+
+    FP16_YYY_norm(&A);
+
+    FP16_YYY_neg(&A,&A);
+    FP16_YYY_times_i(&B);
+    FP16_YYY_times_i(&C);
+
+    FP16_YYY_add(&(w->a),&(w->a),&B);
+    FP16_YYY_add(&(w->b),&C,&D);
+    FP16_YYY_add(&(w->c),&(w->c),&A);
+
+    FP48_YYY_norm(w);
+}
+
+/* FP48 full multiplication w=w*y */
+
+
+/* SU= 896 */
+/* FP48 full multiplication w=w*y */
+void FP48_YYY_mul(FP48_YYY *w,FP48_YYY *y)
+{
+    FP16_YYY z0,z1,z2,z3,t0,t1;
+
+    FP16_YYY_mul(&z0,&(w->a),&(y->a));
+    FP16_YYY_mul(&z2,&(w->b),&(y->b));  //
+
+    FP16_YYY_add(&t0,&(w->a),&(w->b));
+    FP16_YYY_add(&t1,&(y->a),&(y->b));  //
+
+FP16_YYY_norm(&t0);
+FP16_YYY_norm(&t1);
+
+    FP16_YYY_mul(&z1,&t0,&t1);
+    FP16_YYY_add(&t0,&(w->b),&(w->c));
+    FP16_YYY_add(&t1,&(y->b),&(y->c));  //
+
+FP16_YYY_norm(&t0);
+FP16_YYY_norm(&t1);
+
+    FP16_YYY_mul(&z3,&t0,&t1);
+
+    FP16_YYY_neg(&t0,&z0);
+    FP16_YYY_neg(&t1,&z2);
+
+    FP16_YYY_add(&z1,&z1,&t0);   // z1=z1-z0
+//    FP16_YYY_norm(&z1);
+    FP16_YYY_add(&(w->b),&z1,&t1);
+// z1=z1-z2
+    FP16_YYY_add(&z3,&z3,&t1);        // z3=z3-z2
+    FP16_YYY_add(&z2,&z2,&t0);        // z2=z2-z0
+
+    FP16_YYY_add(&t0,&(w->a),&(w->c));
+    FP16_YYY_add(&t1,&(y->a),&(y->c));
+
+FP16_YYY_norm(&t0);
+FP16_YYY_norm(&t1);
+
+    FP16_YYY_mul(&t0,&t1,&t0);
+    FP16_YYY_add(&z2,&z2,&t0);
+
+    FP16_YYY_mul(&t0,&(w->c),&(y->c));
+    FP16_YYY_neg(&t1,&t0);
+
+    FP16_YYY_add(&(w->c),&z2,&t1);
+    FP16_YYY_add(&z3,&z3,&t1);
+    FP16_YYY_times_i(&t0);
+    FP16_YYY_add(&(w->b),&(w->b),&t0);
+FP16_YYY_norm(&z3);
+    FP16_YYY_times_i(&z3);
+    FP16_YYY_add(&(w->a),&z0,&z3);
+
+    FP48_YYY_norm(w);
+}
+
+/* FP48 multiplication w=w*y */
+/* SU= 744 */
+/* catering for special case that arises from special form of ATE pairing line function */
+void FP48_YYY_smul(FP48_YYY *w,FP48_YYY *y,int type)
+{
+    FP16_YYY z0,z1,z2,z3,t0,t1;
+
+	if (type==D_TYPE)
+	{ // y->c is 0
+
+		FP16_YYY_copy(&z3,&(w->b));
+		FP16_YYY_mul(&z0,&(w->a),&(y->a));
+
+		FP16_YYY_pmul(&z2,&(w->b),&(y->b).a);
+		FP16_YYY_add(&(w->b),&(w->a),&(w->b));
+		FP16_YYY_copy(&t1,&(y->a));
+		FP8_YYY_add(&t1.a,&t1.a,&(y->b).a);
+
+		FP16_YYY_norm(&t1);
+		FP16_YYY_norm(&(w->b));
+
+		FP16_YYY_mul(&(w->b),&(w->b),&t1);
+		FP16_YYY_add(&z3,&z3,&(w->c));
+		FP16_YYY_norm(&z3);
+		FP16_YYY_pmul(&z3,&z3,&(y->b).a);
+		FP16_YYY_neg(&t0,&z0);
+		FP16_YYY_neg(&t1,&z2);
+
+		FP16_YYY_add(&(w->b),&(w->b),&t0);   // z1=z1-z0
+//    FP16_YYY_norm(&(w->b));
+		FP16_YYY_add(&(w->b),&(w->b),&t1);   // z1=z1-z2
+
+		FP16_YYY_add(&z3,&z3,&t1);        // z3=z3-z2
+		FP16_YYY_add(&z2,&z2,&t0);        // z2=z2-z0
+
+		FP16_YYY_add(&t0,&(w->a),&(w->c));
+
+		FP16_YYY_norm(&t0);
+		FP16_YYY_norm(&z3);
+
+		FP16_YYY_mul(&t0,&(y->a),&t0);
+		FP16_YYY_add(&(w->c),&z2,&t0);
+
+		FP16_YYY_times_i(&z3);
+		FP16_YYY_add(&(w->a),&z0,&z3);
+	}
+
+	if (type==M_TYPE)
+	{ // y->b is zero
+		FP16_YYY_mul(&z0,&(w->a),&(y->a));
+		FP16_YYY_add(&t0,&(w->a),&(w->b));
+		FP16_YYY_norm(&t0);
+
+		FP16_YYY_mul(&z1,&t0,&(y->a));
+		FP16_YYY_add(&t0,&(w->b),&(w->c));
+		FP16_YYY_norm(&t0);
+
+		FP16_YYY_pmul(&z3,&t0,&(y->c).b);
+		FP16_YYY_times_i(&z3);
+
+		FP16_YYY_neg(&t0,&z0);
+		FP16_YYY_add(&z1,&z1,&t0);   // z1=z1-z0
+
+		FP16_YYY_copy(&(w->b),&z1);
+
+		FP16_YYY_copy(&z2,&t0);
+
+		FP16_YYY_add(&t0,&(w->a),&(w->c));
+		FP16_YYY_add(&t1,&(y->a),&(y->c));
+
+		FP16_YYY_norm(&t0);
+		FP16_YYY_norm(&t1);
+
+		FP16_YYY_mul(&t0,&t1,&t0);
+		FP16_YYY_add(&z2,&z2,&t0);
+
+		FP16_YYY_pmul(&t0,&(w->c),&(y->c).b);
+		FP16_YYY_times_i(&t0);
+		FP16_YYY_neg(&t1,&t0);
+		FP16_YYY_times_i(&t0);
+
+		FP16_YYY_add(&(w->c),&z2,&t1);
+		FP16_YYY_add(&z3,&z3,&t1);
+
+		FP16_YYY_add(&(w->b),&(w->b),&t0);
+		FP16_YYY_norm(&z3);
+		FP16_YYY_times_i(&z3);
+		FP16_YYY_add(&(w->a),&z0,&z3);
+	}
+    FP48_YYY_norm(w);
+}
+
+/* Set w=1/x */
+/* SU= 600 */
+void FP48_YYY_inv(FP48_YYY *w,FP48_YYY *x)
+{
+    FP16_YYY f0,f1,f2,f3;
+//    FP48_YYY_norm(x);
+
+    FP16_YYY_sqr(&f0,&(x->a));
+    FP16_YYY_mul(&f1,&(x->b),&(x->c));
+    FP16_YYY_times_i(&f1);
+    FP16_YYY_sub(&f0,&f0,&f1);  /* y.a */
+	FP16_YYY_norm(&f0); 		
+
+    FP16_YYY_sqr(&f1,&(x->c));
+    FP16_YYY_times_i(&f1);
+    FP16_YYY_mul(&f2,&(x->a),&(x->b));
+    FP16_YYY_sub(&f1,&f1,&f2);  /* y.b */
+	FP16_YYY_norm(&f1); 
+
+    FP16_YYY_sqr(&f2,&(x->b));
+    FP16_YYY_mul(&f3,&(x->a),&(x->c));
+    FP16_YYY_sub(&f2,&f2,&f3);  /* y.c */
+	FP16_YYY_norm(&f2); 
+
+    FP16_YYY_mul(&f3,&(x->b),&f2);
+    FP16_YYY_times_i(&f3);
+    FP16_YYY_mul(&(w->a),&f0,&(x->a));
+    FP16_YYY_add(&f3,&(w->a),&f3);
+    FP16_YYY_mul(&(w->c),&f1,&(x->c));
+    FP16_YYY_times_i(&(w->c));
+
+
+
+    FP16_YYY_add(&f3,&(w->c),&f3);
+	FP16_YYY_norm(&f3);
+	
+    FP16_YYY_inv(&f3,&f3);
+    FP16_YYY_mul(&(w->a),&f0,&f3);
+    FP16_YYY_mul(&(w->b),&f1,&f3);
+    FP16_YYY_mul(&(w->c),&f2,&f3);
+
+}
+
+/* constant time powering by small integer of max length bts */
+
+void FP48_YYY_pinpow(FP48_YYY *r,int e,int bts)
+{
+    int i,b;
+    FP48_YYY R[2];
+
+    FP48_YYY_one(&R[0]);
+    FP48_YYY_copy(&R[1],r);
+
+    for (i=bts-1; i>=0; i--)
+    {
+        b=(e>>i)&1;
+        FP48_YYY_mul(&R[1-b],&R[b]);
+        FP48_YYY_usqr(&R[b],&R[b]);
+    }
+    FP48_YYY_copy(r,&R[0]);
+}
+
+/* Compressed powering of unitary elements y=x^(e mod r) */
+
+void FP48_YYY_compow(FP16_YYY *c,FP48_YYY *x,BIG_XXX e,BIG_XXX r)
+{
+    FP48_YYY g1,g2;
+	FP16_YYY cp,cpm1,cpm2;
+    FP2_YYY  f;
+	BIG_XXX q,a,b,m;
+
+    BIG_XXX_rcopy(a,Fra_YYY);
+    BIG_XXX_rcopy(b,Frb_YYY);
+    FP2_YYY_from_BIGs(&f,a,b);
+
+    BIG_XXX_rcopy(q,Modulus_YYY);
+
+    FP48_YYY_copy(&g1,x);
+	FP48_YYY_copy(&g2,x);
+
+    BIG_XXX_copy(m,q);
+    BIG_XXX_mod(m,r);
+
+    BIG_XXX_copy(a,e);
+    BIG_XXX_mod(a,m);
+
+    BIG_XXX_copy(b,e);
+    BIG_XXX_sdiv(b,m);
+
+    FP48_YYY_trace(c,&g1);
+
+	if (BIG_XXX_iszilch(b))
+	{
+		FP16_YYY_xtr_pow(c,c,e);
+		return;
+	}
+
+    FP48_YYY_frob(&g2,&f,1);
+    FP48_YYY_trace(&cp,&g2);
+    FP48_YYY_conj(&g1,&g1);
+    FP48_YYY_mul(&g2,&g1);
+    FP48_YYY_trace(&cpm1,&g2);
+    FP48_YYY_mul(&g2,&g1);
+
+    FP48_YYY_trace(&cpm2,&g2);
+
+    FP16_YYY_xtr_pow2(c,&cp,c,&cpm1,&cpm2,a,b);
+
+}
+
+/* Note this is simple square and multiply, so not side-channel safe */
+
+void FP48_YYY_pow(FP48_YYY *r,FP48_YYY *a,BIG_XXX b)
+{
+    FP48_YYY w,sf;
+    BIG_XXX b1,b3;
+    int i,nb,bt;
+	BIG_XXX_copy(b1,b);
+    BIG_XXX_norm(b1);
+	BIG_XXX_pmul(b3,b1,3);
+	BIG_XXX_norm(b3);
+
+	FP48_YYY_copy(&sf,a);
+	FP48_YYY_norm(&sf);
+    FP48_YYY_copy(&w,&sf);
+
+	nb=BIG_XXX_nbits(b3);
+	for (i=nb-2;i>=1;i--)
+	{
+		FP48_YYY_usqr(&w,&w);
+		bt=BIG_XXX_bit(b3,i)-BIG_XXX_bit(b1,i);
+		if (bt==1)
+			FP48_YYY_mul(&w,&sf);
+		if (bt==-1)
+		{
+			FP48_YYY_conj(&sf,&sf);
+			FP48_YYY_mul(&w,&sf);
+			FP48_YYY_conj(&sf,&sf);
+		}
+	}
+
+	FP48_YYY_copy(r,&w);
+	FP48_YYY_reduce(r);
+}
+
+
+/* SU= 528 */
+/* set r=a^b */
+/* Note this is simple square and multiply, so not side-channel safe 
+
+void FP48_YYY_ppow(FP48_YYY *r,FP48_YYY *a,BIG_XXX b)
+{
+    FP48_YYY w;
+    BIG_XXX z,zilch;
+    int bt;
+    BIG_XXX_zero(zilch);
+    BIG_XXX_norm(b);
+    BIG_XXX_copy(z,b);
+    FP48_YYY_copy(&w,a);
+    FP48_YYY_one(r);
+
+    while(1)
+    {
+        bt=BIG_XXX_parity(z);
+        BIG_XXX_shr(z,1);
+        if (bt)
+		{
+			//printf("In mul\n");
+            FP48_YYY_mul(r,&w);
+			//printf("Out of mul\n");
+		}
+        if (BIG_XXX_comp(z,zilch)==0) break;
+		//printf("In sqr\n");
+        FP48_YYY_sqr(&w,&w);
+		//printf("Out of sqr\n");
+    }
+
+    FP48_YYY_reduce(r);
+}  */
+
+/* p=q0^u0.q1^u1.q2^u2.q3^u3... */
+/* Side channel attack secure */
+// Bos & Costello https://eprint.iacr.org/2013/458.pdf
+// Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
+
+void FP48_YYY_pow16(FP48_YYY *p,FP48_YYY *q,BIG_XXX u[16])
+{
+    int i,j,k,nb,pb1,pb2,pb3,pb4,bt;
+	FP48_YYY g1[8],g2[8],g3[8],g4[8],r;
+	BIG_XXX t[16],mt;
+    sign8 w1[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 s1[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 w2[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 s2[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 w3[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 s3[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 w4[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 s4[NLEN_XXX*BASEBITS_XXX+1];
+    FP_YYY fx,fy;
+	FP2_YYY  X;
+
+    FP_YYY_rcopy(&fx,Fra_YYY);
+    FP_YYY_rcopy(&fy,Frb_YYY);
+    FP2_YYY_from_FPs(&X,&fx,&fy);
+
+    for (i=0; i<16; i++)
+        BIG_XXX_copy(t[i],u[i]);
+
+// Precomputed table
+    FP48_YYY_copy(&g1[0],&q[0]); // q[0]
+    FP48_YYY_copy(&g1[1],&g1[0]);
+	FP48_YYY_mul(&g1[1],&q[1]);	// q[0].q[1]
+    FP48_YYY_copy(&g1[2],&g1[0]);
+	FP48_YYY_mul(&g1[2],&q[2]);	// q[0].q[2]
+	FP48_YYY_copy(&g1[3],&g1[1]);
+	FP48_YYY_mul(&g1[3],&q[2]);	// q[0].q[1].q[2]
+	FP48_YYY_copy(&g1[4],&g1[0]);
+	FP48_YYY_mul(&g1[4],&q[3]);  // q[0].q[3]
+	FP48_YYY_copy(&g1[5],&g1[1]);
+	FP48_YYY_mul(&g1[5],&q[3]);	// q[0].q[1].q[3]
+	FP48_YYY_copy(&g1[6],&g1[2]);
+	FP48_YYY_mul(&g1[6],&q[3]);	// q[0].q[2].q[3]
+	FP48_YYY_copy(&g1[7],&g1[3]);
+	FP48_YYY_mul(&g1[7],&q[3]);	// q[0].q[1].q[2].q[3]
+
+// Use Frobenius
+
+	for (i=0;i<8;i++)
+	{
+		FP48_YYY_copy(&g2[i],&g1[i]);
+		FP48_YYY_frob(&g2[i],&X,4);
+
+		FP48_YYY_copy(&g3[i],&g2[i]);
+		FP48_YYY_frob(&g3[i],&X,4);
+
+		FP48_YYY_copy(&g4[i],&g3[i]);
+		FP48_YYY_frob(&g4[i],&X,4);
+	}
+
+// Make them odd
+	pb1=1-BIG_XXX_parity(t[0]);
+	BIG_XXX_inc(t[0],pb1);
+	BIG_XXX_norm(t[0]);
+
+	pb2=1-BIG_XXX_parity(t[4]);
+	BIG_XXX_inc(t[4],pb2);
+	BIG_XXX_norm(t[4]);
+
+	pb3=1-BIG_XXX_parity(t[8]);
+	BIG_XXX_inc(t[8],pb3);
+	BIG_XXX_norm(t[8]);
+
+	pb4=1-BIG_XXX_parity(t[12]);
+	BIG_XXX_inc(t[12],pb4);
+	BIG_XXX_norm(t[12]);
+
+// Number of bits
+    BIG_XXX_zero(mt);
+    for (i=0; i<16; i++)
+    {
+        BIG_XXX_or(mt,mt,t[i]);
+    }
+    nb=1+BIG_XXX_nbits(mt);
+
+// Sign pivot 
+	s1[nb-1]=1;
+	s2[nb-1]=1;
+	s3[nb-1]=1;
+	s4[nb-1]=1;
+	for (i=0;i<nb-1;i++)
+	{
+        BIG_XXX_fshr(t[0],1);
+		s1[i]=2*BIG_XXX_parity(t[0])-1;
+        BIG_XXX_fshr(t[4],1);
+		s2[i]=2*BIG_XXX_parity(t[4])-1;
+        BIG_XXX_fshr(t[8],1);
+		s3[i]=2*BIG_XXX_parity(t[8])-1;
+        BIG_XXX_fshr(t[12],1);
+		s4[i]=2*BIG_XXX_parity(t[12])-1;
+	}
+
+// Recoded exponents
+    for (i=0; i<nb; i++)
+    {
+		w1[i]=0;
+		k=1;
+		for (j=1; j<4; j++)
+		{
+			bt=s1[i]*BIG_XXX_parity(t[j]);
+			BIG_XXX_fshr(t[j],1);
+
+			BIG_XXX_dec(t[j],(bt>>1));
+			BIG_XXX_norm(t[j]);
+			w1[i]+=bt*k;
+			k*=2;
+        }
+
+		w2[i]=0;
+		k=1;
+		for (j=5; j<8; j++)
+		{
+			bt=s2[i]*BIG_XXX_parity(t[j]);
+			BIG_XXX_fshr(t[j],1);
+
+			BIG_XXX_dec(t[j],(bt>>1));
+			BIG_XXX_norm(t[j]);
+			w2[i]+=bt*k;
+			k*=2;
+        }
+
+		w3[i]=0;
+		k=1;
+		for (j=9; j<12; j++)
+		{
+			bt=s3[i]*BIG_XXX_parity(t[j]);
+			BIG_XXX_fshr(t[j],1);
+
+			BIG_XXX_dec(t[j],(bt>>1));
+			BIG_XXX_norm(t[j]);
+			w3[i]+=bt*k;
+			k*=2;
+        }
+
+		w4[i]=0;
+		k=1;
+		for (j=13; j<16; j++)
+		{
+			bt=s4[i]*BIG_XXX_parity(t[j]);
+			BIG_XXX_fshr(t[j],1);
+
+			BIG_XXX_dec(t[j],(bt>>1));
+			BIG_XXX_norm(t[j]);
+			w4[i]+=bt*k;
+			k*=2;
+        }
+    }	
+
+// Main loop
+	FP48_YYY_select(p,g1,2*w1[nb-1]+1);
+	FP48_YYY_select(&r,g2,2*w2[nb-1]+1);
+	FP48_YYY_mul(p,&r);
+	FP48_YYY_select(&r,g3,2*w3[nb-1]+1);
+	FP48_YYY_mul(p,&r);
+	FP48_YYY_select(&r,g4,2*w4[nb-1]+1);
+	FP48_YYY_mul(p,&r);
+    for (i=nb-2; i>=0; i--)
+    {
+		FP48_YYY_usqr(p,p);
+        FP48_YYY_select(&r,g1,2*w1[i]+s1[i]);
+        FP48_YYY_mul(p,&r);
+        FP48_YYY_select(&r,g2,2*w2[i]+s2[i]);
+        FP48_YYY_mul(p,&r);
+        FP48_YYY_select(&r,g3,2*w3[i]+s3[i]);
+        FP48_YYY_mul(p,&r);
+        FP48_YYY_select(&r,g4,2*w4[i]+s4[i]);
+        FP48_YYY_mul(p,&r);
+    }
+
+// apply correction
+	FP48_YYY_conj(&r,&q[0]);   
+	FP48_YYY_mul(&r,p);
+	FP48_YYY_cmove(p,&r,pb1);
+	FP48_YYY_conj(&r,&q[4]);   
+	FP48_YYY_mul(&r,p);
+	FP48_YYY_cmove(p,&r,pb2);
+
+	FP48_YYY_conj(&r,&q[8]);   
+	FP48_YYY_mul(&r,p);
+	FP48_YYY_cmove(p,&r,pb3);
+	FP48_YYY_conj(&r,&q[12]);   
+	FP48_YYY_mul(&r,p);
+	FP48_YYY_cmove(p,&r,pb4);
+
+	FP48_YYY_reduce(p);
+}
+
+/*
+void FP48_YYY_pow16(FP48_YYY *p,FP48_YYY *q,BIG_XXX u[16])
+{
+    int i,j,a[4],nb,m;
+    FP48_YYY g[8],f[8],gg[8],ff[8],c,s[2];
+    BIG_XXX t[16],mt;
+    sign8 w[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 z[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 ww[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 zz[NLEN_XXX*BASEBITS_XXX+1];
+
+    FP_YYY fx,fy;
+	FP2_YYY  X;
+
+    FP_YYY_rcopy(&fx,Fra_YYY);
+    FP_YYY_rcopy(&fy,Frb_YYY);
+    FP2_YYY _from_FPs(&X,&fx,&fy);
+
+    for (i=0; i<16; i++)
+        BIG_XXX_copy(t[i],u[i]);
+
+    FP48_YYY_copy(&g[0],&q[0]);
+    FP48_YYY_conj(&s[0],&q[1]);
+    FP48_YYY_mul(&g[0],&s[0]);  // P/Q 
+    FP48_YYY_copy(&g[1],&g[0]);
+    FP48_YYY_copy(&g[2],&g[0]);
+    FP48_YYY_copy(&g[3],&g[0]);
+    FP48_YYY_copy(&g[4],&q[0]);
+    FP48_YYY_mul(&g[4],&q[1]);  // P*Q 
+    FP48_YYY_copy(&g[5],&g[4]);
+    FP48_YYY_copy(&g[6],&g[4]);
+    FP48_YYY_copy(&g[7],&g[4]);
+
+    FP48_YYY_copy(&s[1],&q[2]);
+    FP48_YYY_conj(&s[0],&q[3]);
+    FP48_YYY_mul(&s[1],&s[0]);       // R/S 
+    FP48_YYY_conj(&s[0],&s[1]);
+    FP48_YYY_mul(&g[1],&s[0]);
+    FP48_YYY_mul(&g[2],&s[1]);
+    FP48_YYY_mul(&g[5],&s[0]);
+    FP48_YYY_mul(&g[6],&s[1]);
+    FP48_YYY_copy(&s[1],&q[2]);
+    FP48_YYY_mul(&s[1],&q[3]);      // R*S 
+    FP48_YYY_conj(&s[0],&s[1]);
+    FP48_YYY_mul(&g[0],&s[0]);
+    FP48_YYY_mul(&g[3],&s[1]);
+    FP48_YYY_mul(&g[4],&s[0]);
+    FP48_YYY_mul(&g[7],&s[1]);
+
+// Use Frobenius
+
+	for (i=0;i<8;i++)
+	{
+		FP48_YYY_copy(&f[i],&g[i]);
+		FP48_YYY_frob(&f[i],&X,4);
+	}
+
+	for (i=0;i<8;i++)
+	{
+		FP48_YYY_copy(&gg[i],&f[i]);
+		FP48_YYY_frob(&gg[i],&X,4);
+	}
+
+	for (i=0;i<8;i++)
+	{
+		FP48_YYY_copy(&ff[i],&gg[i]);
+		FP48_YYY_frob(&ff[i],&X,4);
+	}
+
+
+    // if power is even add 1 to power, and add q to correction 
+    FP48_YYY_one(&c);
+
+    BIG_XXX_zero(mt);
+    for (i=0; i<16; i++)
+    {
+        if (BIG_XXX_parity(t[i])==0)
+        {
+            BIG_XXX_inc(t[i],1);
+            BIG_XXX_norm(t[i]);
+            FP48_YYY_mul(&c,&q[i]);
+        }
+        BIG_XXX_add(mt,mt,t[i]);
+        BIG_XXX_norm(mt);
+    }
+
+    FP48_YYY_conj(&c,&c);
+    nb=1+BIG_XXX_nbits(mt);
+
+    // convert exponents to signed 1-bit windows 
+    for (j=0; j<nb; j++)
+    {
+        for (i=0; i<4; i++)
+        {
+            a[i]=BIG_XXX_lastbits(t[i],2)-2;
+            BIG_XXX_dec(t[i],a[i]);
+            BIG_XXX_norm(t[i]);
+            BIG_XXX_fshr(t[i],1);
+        }
+        w[j]=8*a[0]+4*a[1]+2*a[2]+a[3];
+    }
+    w[nb]=8*BIG_XXX_lastbits(t[0],2)+4*BIG_XXX_lastbits(t[1],2)+2*BIG_XXX_lastbits(t[2],2)+BIG_XXX_lastbits(t[3],2);
+
+
+    for (j=0; j<nb; j++)
+    {
+        for (i=0; i<4; i++)
+        {
+            a[i]=BIG_XXX_lastbits(t[i+4],2)-2;
+            BIG_XXX_dec(t[i+4],a[i]);
+            BIG_XXX_norm(t[i+4]);
+            BIG_XXX_fshr(t[i+4],1);
+        }
+        z[j]=8*a[0]+4*a[1]+2*a[2]+a[3];
+    }
+    z[nb]=8*BIG_XXX_lastbits(t[4],2)+4*BIG_XXX_lastbits(t[5],2)+2*BIG_XXX_lastbits(t[6],2)+BIG_XXX_lastbits(t[7],2);
+
+    for (j=0; j<nb; j++)
+    {
+        for (i=0; i<4; i++)
+        {
+            a[i]=BIG_XXX_lastbits(t[i+8],2)-2;
+            BIG_XXX_dec(t[i+8],a[i]);
+            BIG_XXX_norm(t[i+8]);
+            BIG_XXX_fshr(t[i+8],1);
+        }
+        ww[j]=8*a[0]+4*a[1]+2*a[2]+a[3];
+    }
+    ww[nb]=8*BIG_XXX_lastbits(t[8],2)+4*BIG_XXX_lastbits(t[9],2)+2*BIG_XXX_lastbits(t[10],2)+BIG_XXX_lastbits(t[11],2);
+
+    for (j=0; j<nb; j++)
+    {
+        for (i=0; i<4; i++)
+        {
+            a[i]=BIG_XXX_lastbits(t[i+12],2)-2;
+            BIG_XXX_dec(t[i+12],a[i]);
+            BIG_XXX_norm(t[i+12]);
+            BIG_XXX_fshr(t[i+12],1);
+        }
+        zz[j]=8*a[0]+4*a[1]+2*a[2]+a[3];
+    }
+    zz[nb]=8*BIG_XXX_lastbits(t[12],2)+4*BIG_XXX_lastbits(t[13],2)+2*BIG_XXX_lastbits(t[14],2)+BIG_XXX_lastbits(t[15],2);
+
+    FP48_YYY_copy(p,&g[(w[nb]-1)/2]);
+    FP48_YYY_mul(p,&f[(z[nb]-1)/2]);
+    FP48_YYY_mul(p,&gg[(ww[nb]-1)/2]);
+    FP48_YYY_mul(p,&ff[(zz[nb]-1)/2]);
+
+    for (i=nb-1; i>=0; i--)
+    {
+		FP48_YYY_usqr(p,p);
+
+        m=w[i]>>7;
+        j=(w[i]^m)-m;  // j=abs(w[i]) 
+        j=(j-1)/2;
+        FP48_YYY_copy(&s[0],&g[j]);
+        FP48_YYY_conj(&s[1],&g[j]);
+        FP48_YYY_mul(p,&s[m&1]);
+
+        m=z[i]>>7;
+        j=(z[i]^m)-m;  // j=abs(w[i]) 
+        j=(j-1)/2;
+        FP48_YYY_copy(&s[0],&f[j]);
+        FP48_YYY_conj(&s[1],&f[j]);
+        FP48_YYY_mul(p,&s[m&1]);
+
+        m=ww[i]>>7;
+        j=(ww[i]^m)-m;  // j=abs(w[i]) 
+        j=(j-1)/2;
+        FP48_YYY_copy(&s[0],&gg[j]);
+        FP48_YYY_conj(&s[1],&gg[j]);
+        FP48_YYY_mul(p,&s[m&1]);
+
+        m=zz[i]>>7;
+        j=(zz[i]^m)-m;  // j=abs(w[i]) 
+        j=(j-1)/2;
+        FP48_YYY_copy(&s[0],&ff[j]);
+        FP48_YYY_conj(&s[1],&ff[j]);
+        FP48_YYY_mul(p,&s[m&1]);
+
+    }
+    FP48_YYY_mul(p,&c); // apply correction 
+    FP48_YYY_reduce(p);
+}
+*/
+
+/* Set w=w^p using Frobenius */
+/* SU= 160 */
+void FP48_YYY_frob(FP48_YYY *w,FP2_YYY  *f,int n)
+{
+	int i;
+	FP8_YYY X2,X4;
+	FP4_YYY F;
+    FP2_YYY  f3,f2;				// f=(1+i)^(p-19)/24
+    FP2_YYY_sqr(&f2,f);     // 
+    FP2_YYY_mul(&f3,&f2,f); // f3=f^3=(1+i)^(p-19)/8
+
+	FP2_YYY_mul_ip(&f3);
+	FP2_YYY_norm(&f3);
+	FP2_YYY_mul_ip(&f3);    // f3 = (1+i)^16/8.(1+i)^(p-19)/8 = (1+i)^(p-3)/8 
+	FP2_YYY_norm(&f3);
+
+	for (i=0;i<n;i++)
+	{
+		FP16_YYY_frob(&(w->a),&f3);   // a=a^p
+		FP16_YYY_frob(&(w->b),&f3);   // b=b^p
+		FP16_YYY_frob(&(w->c),&f3);   // c=c^p
+  
+		FP16_YYY_qmul(&(w->b),&(w->b),f); FP16_YYY_times_i4(&(w->b)); FP16_YYY_times_i2(&(w->b)); 
+		FP16_YYY_qmul(&(w->c),&(w->c),&f2); FP16_YYY_times_i4(&(w->c)); FP16_YYY_times_i4(&(w->c)); FP16_YYY_times_i4(&(w->c)); 
+
+	}
+}
+
+/* SU= 8 */
+/* normalise all components of w */
+void FP48_YYY_norm(FP48_YYY *w)
+{
+    FP16_YYY_norm(&(w->a));
+    FP16_YYY_norm(&(w->b));
+    FP16_YYY_norm(&(w->c));
+}
+
+/* SU= 8 */
+/* reduce all components of w */
+void FP48_YYY_reduce(FP48_YYY *w)
+{
+    FP16_YYY_reduce(&(w->a));
+    FP16_YYY_reduce(&(w->b));
+    FP16_YYY_reduce(&(w->c));
+}
+
+/* trace function w=trace(x) */
+/* SU= 8 */
+void FP48_YYY_trace(FP16_YYY *w,FP48_YYY *x)
+{
+    FP16_YYY_imul(w,&(x->a),3);
+    FP16_YYY_reduce(w);
+}
+
+/* SU= 8 */
+/* Output w in hex */
+void FP48_YYY_output(FP48_YYY *w)
+{
+    printf("[");
+    FP16_YYY_output(&(w->a));
+    printf(",");
+    FP16_YYY_output(&(w->b));
+    printf(",");
+    FP16_YYY_output(&(w->c));
+    printf("]");
+}
+
+/* Convert g to octet string w */
+void FP48_YYY_toOctet(octet *W,FP48_YYY *g)
+{
+    BIG_XXX a;
+    W->len=48*MODBYTES_XXX;
+
+    FP_YYY_redc(a,&(g->a.a.a.a.a));
+    BIG_XXX_toBytes(&(W->val[0]),a);
+    FP_YYY_redc(a,&(g->a.a.a.a.b));
+    BIG_XXX_toBytes(&(W->val[MODBYTES_XXX]),a);
+    
+	FP_YYY_redc(a,&(g->a.a.a.b.a));
+    BIG_XXX_toBytes(&(W->val[2*MODBYTES_XXX]),a);
+	FP_YYY_redc(a,&(g->a.a.a.b.b));
+    BIG_XXX_toBytes(&(W->val[3*MODBYTES_XXX]),a);
+
+    FP_YYY_redc(a,&(g->a.a.b.a.a));
+    BIG_XXX_toBytes(&(W->val[4*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->a.a.b.a.b));
+    BIG_XXX_toBytes(&(W->val[5*MODBYTES_XXX]),a);
+
+    FP_YYY_redc(a,&(g->a.a.b.b.a));
+    BIG_XXX_toBytes(&(W->val[6*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->a.a.b.b.b));
+    BIG_XXX_toBytes(&(W->val[7*MODBYTES_XXX]),a);
+
+    FP_YYY_redc(a,&(g->a.b.a.a.a));
+    BIG_XXX_toBytes(&(W->val[8*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->a.b.a.a.b));
+    BIG_XXX_toBytes(&(W->val[9*MODBYTES_XXX]),a);
+
+    FP_YYY_redc(a,&(g->a.b.a.b.a));
+    BIG_XXX_toBytes(&(W->val[10*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->a.b.a.b.b));
+    BIG_XXX_toBytes(&(W->val[11*MODBYTES_XXX]),a);
+
+    FP_YYY_redc(a,&(g->a.b.b.a.a));
+    BIG_XXX_toBytes(&(W->val[12*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->a.b.b.a.b));
+    BIG_XXX_toBytes(&(W->val[13*MODBYTES_XXX]),a);
+
+    FP_YYY_redc(a,&(g->a.b.b.b.a));
+    BIG_XXX_toBytes(&(W->val[14*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->a.b.b.b.b));
+    BIG_XXX_toBytes(&(W->val[15*MODBYTES_XXX]),a);
+
+    FP_YYY_redc(a,&(g->b.a.a.a.a));
+    BIG_XXX_toBytes(&(W->val[16*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->b.a.a.a.b));
+    BIG_XXX_toBytes(&(W->val[17*MODBYTES_XXX]),a);
+
+    FP_YYY_redc(a,&(g->b.a.a.b.a));
+    BIG_XXX_toBytes(&(W->val[18*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->b.a.a.b.b));
+    BIG_XXX_toBytes(&(W->val[19*MODBYTES_XXX]),a);
+
+    FP_YYY_redc(a,&(g->b.a.b.a.a));
+    BIG_XXX_toBytes(&(W->val[20*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->b.a.b.a.b));
+    BIG_XXX_toBytes(&(W->val[21*MODBYTES_XXX]),a);
+
+    FP_YYY_redc(a,&(g->b.a.b.b.a));
+    BIG_XXX_toBytes(&(W->val[22*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->b.a.b.b.b));
+    BIG_XXX_toBytes(&(W->val[23*MODBYTES_XXX]),a);
+
+    FP_YYY_redc(a,&(g->b.b.a.a.a));
+    BIG_XXX_toBytes(&(W->val[24*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->b.b.a.a.b));
+    BIG_XXX_toBytes(&(W->val[25*MODBYTES_XXX]),a);
+
+    FP_YYY_redc(a,&(g->b.b.a.b.a));
+    BIG_XXX_toBytes(&(W->val[26*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->b.b.a.b.b));
+    BIG_XXX_toBytes(&(W->val[27*MODBYTES_XXX]),a);
+
+    FP_YYY_redc(a,&(g->b.b.b.a.a));
+    BIG_XXX_toBytes(&(W->val[28*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->b.b.b.a.b));
+    BIG_XXX_toBytes(&(W->val[29*MODBYTES_XXX]),a);
+
+    FP_YYY_redc(a,&(g->b.b.b.b.a));
+    BIG_XXX_toBytes(&(W->val[30*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->b.b.b.b.b));
+    BIG_XXX_toBytes(&(W->val[31*MODBYTES_XXX]),a);
+
+    FP_YYY_redc(a,&(g->c.a.a.a.a));
+    BIG_XXX_toBytes(&(W->val[32*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->c.a.a.a.b));
+    BIG_XXX_toBytes(&(W->val[33*MODBYTES_XXX]),a);
+
+    FP_YYY_redc(a,&(g->c.a.a.b.a));
+    BIG_XXX_toBytes(&(W->val[34*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->c.a.a.b.b));
+    BIG_XXX_toBytes(&(W->val[35*MODBYTES_XXX]),a);
+
+    FP_YYY_redc(a,&(g->c.a.b.a.a));
+    BIG_XXX_toBytes(&(W->val[36*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->c.a.b.a.b));
+    BIG_XXX_toBytes(&(W->val[37*MODBYTES_XXX]),a);
+
+    FP_YYY_redc(a,&(g->c.a.b.b.a));
+    BIG_XXX_toBytes(&(W->val[38*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->c.a.b.b.b));
+    BIG_XXX_toBytes(&(W->val[39*MODBYTES_XXX]),a);
+
+    FP_YYY_redc(a,&(g->c.b.a.a.a));
+    BIG_XXX_toBytes(&(W->val[40*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->c.b.a.a.b));
+    BIG_XXX_toBytes(&(W->val[41*MODBYTES_XXX]),a);
+
+    FP_YYY_redc(a,&(g->c.b.a.b.a));
+    BIG_XXX_toBytes(&(W->val[42*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->c.b.a.b.b));
+    BIG_XXX_toBytes(&(W->val[43*MODBYTES_XXX]),a);
+
+    FP_YYY_redc(a,&(g->c.b.b.a.a));
+    BIG_XXX_toBytes(&(W->val[44*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->c.b.b.a.b));
+    BIG_XXX_toBytes(&(W->val[45*MODBYTES_XXX]),a);
+
+    FP_YYY_redc(a,&(g->c.b.b.b.a));
+    BIG_XXX_toBytes(&(W->val[46*MODBYTES_XXX]),a);
+    FP_YYY_redc(a,&(g->c.b.b.b.b));
+    BIG_XXX_toBytes(&(W->val[47*MODBYTES_XXX]),a);
+
+}
+
+/* Restore g from octet string w */
+void FP48_YYY_fromOctet(FP48_YYY *g,octet *W)
+{
+	BIG_XXX b;
+
+    BIG_XXX_fromBytes(b,&W->val[0]);
+    FP_YYY_nres(&(g->a.a.a.a.a),b);
+    BIG_XXX_fromBytes(b,&W->val[MODBYTES_XXX]);
+    FP_YYY_nres(&(g->a.a.a.a.b),b);
+
+    BIG_XXX_fromBytes(b,&W->val[2*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->a.a.a.b.a),b);
+    BIG_XXX_fromBytes(b,&W->val[3*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->a.a.a.b.b),b);
+
+    BIG_XXX_fromBytes(b,&W->val[4*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->a.a.b.a.a),b);
+    BIG_XXX_fromBytes(b,&W->val[5*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->a.a.b.a.b),b);
+
+    BIG_XXX_fromBytes(b,&W->val[6*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->a.a.b.b.a),b);
+    BIG_XXX_fromBytes(b,&W->val[7*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->a.a.b.b.b),b);
+
+    BIG_XXX_fromBytes(b,&W->val[8*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->a.b.a.a.a),b);
+    BIG_XXX_fromBytes(b,&W->val[9*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->a.b.a.a.b),b);
+
+    BIG_XXX_fromBytes(b,&W->val[10*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->a.b.a.b.a),b);
+    BIG_XXX_fromBytes(b,&W->val[11*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->a.b.a.b.b),b);
+
+    BIG_XXX_fromBytes(b,&W->val[12*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->a.b.b.a.a),b);
+    BIG_XXX_fromBytes(b,&W->val[13*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->a.b.b.a.b),b);
+
+    BIG_XXX_fromBytes(b,&W->val[14*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->a.b.b.b.a),b);
+    BIG_XXX_fromBytes(b,&W->val[15*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->a.b.b.b.b),b);
+
+    BIG_XXX_fromBytes(b,&W->val[16*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->b.a.a.a.a),b);
+    BIG_XXX_fromBytes(b,&W->val[17*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->b.a.a.a.b),b);
+
+    BIG_XXX_fromBytes(b,&W->val[18*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->b.a.a.b.a),b);
+    BIG_XXX_fromBytes(b,&W->val[19*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->b.a.a.b.b),b);
+
+    BIG_XXX_fromBytes(b,&W->val[20*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->b.a.b.a.a),b);
+    BIG_XXX_fromBytes(b,&W->val[21*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->b.a.b.a.b),b);
+
+    BIG_XXX_fromBytes(b,&W->val[22*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->b.a.b.b.a),b);
+    BIG_XXX_fromBytes(b,&W->val[23*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->b.a.b.b.b),b);
+
+    BIG_XXX_fromBytes(b,&W->val[24*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->b.b.a.a.a),b);
+    BIG_XXX_fromBytes(b,&W->val[25*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->b.b.a.a.b),b);
+
+    BIG_XXX_fromBytes(b,&W->val[26*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->b.b.a.b.a),b);
+    BIG_XXX_fromBytes(b,&W->val[27*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->b.b.a.b.b),b);
+
+    BIG_XXX_fromBytes(b,&W->val[28*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->b.b.b.a.a),b);
+    BIG_XXX_fromBytes(b,&W->val[29*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->b.b.b.a.b),b);
+
+    BIG_XXX_fromBytes(b,&W->val[30*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->b.b.b.b.a),b);
+    BIG_XXX_fromBytes(b,&W->val[31*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->b.b.b.b.b),b);
+
+    BIG_XXX_fromBytes(b,&W->val[32*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->c.a.a.a.a),b);
+    BIG_XXX_fromBytes(b,&W->val[33*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->c.a.a.a.b),b);
+
+    BIG_XXX_fromBytes(b,&W->val[34*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->c.a.a.b.a),b);
+    BIG_XXX_fromBytes(b,&W->val[35*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->c.a.a.b.b),b);
+
+    BIG_XXX_fromBytes(b,&W->val[36*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->c.a.b.a.a),b);
+    BIG_XXX_fromBytes(b,&W->val[37*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->c.a.b.a.b),b);
+
+    BIG_XXX_fromBytes(b,&W->val[38*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->c.a.b.b.a),b);
+    BIG_XXX_fromBytes(b,&W->val[39*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->c.a.b.b.b),b);
+
+    BIG_XXX_fromBytes(b,&W->val[40*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->c.b.a.a.a),b);
+    BIG_XXX_fromBytes(b,&W->val[41*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->c.b.a.a.b),b);
+
+    BIG_XXX_fromBytes(b,&W->val[42*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->c.b.a.b.a),b);
+    BIG_XXX_fromBytes(b,&W->val[43*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->c.b.a.b.b),b);
+
+    BIG_XXX_fromBytes(b,&W->val[44*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->c.b.b.a.a),b);
+    BIG_XXX_fromBytes(b,&W->val[45*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->c.b.b.a.b),b);
+
+    BIG_XXX_fromBytes(b,&W->val[46*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->c.b.b.b.a),b);
+    BIG_XXX_fromBytes(b,&W->val[47*MODBYTES_XXX]);
+    FP_YYY_nres(&(g->c.b.b.b.b),b);
+
+}
+
+/* Move b to a if d=1 */
+void FP48_YYY_cmove(FP48_YYY *f,FP48_YYY *g,int d)
+{
+    FP16_YYY_cmove(&(f->a),&(g->a),d);
+    FP16_YYY_cmove(&(f->b),&(g->b),d);
+    FP16_YYY_cmove(&(f->c),&(g->c),d);
+}
+
+/*
+using namespace YYY;
+
+int main() {
+	int i;
+	FP2 f,w0,w1,X;
+	FP4 f0,f1;
+	FP16_YYY t0,t1,t2;
+	FP48 w,t,lv;
+	BIG a,b;
+	BIG p;
+
+
+	char raw[100];
+	csprng RNG;                // Crypto Strong RNG 
+
+	for (i=0; i<100; i++) raw[i]=i;
+
+	BIG_rcopy(a,Fra_YYY);
+    BIG_rcopy(b,Frb_YYY);
+	FP2_from_BIGs(&X,a,b);
+
+
+
+    RAND_seed(&RNG,100,raw);   // initialise strong RNG 
+
+	BIG_rcopy(p,Modulus);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w0,a,b);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w1,a,b);
+
+	FP4_from_FP2s(&f0,&w0,&w1);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w0,a,b);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w1,a,b);
+
+	FP4_from_FP2s(&f1,&w0,&w1);
+	FP16_YYY_from_FP4s(&t0,&f0,&f1);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w0,a,b);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w1,a,b);
+
+	FP4_from_FP2s(&f0,&w0,&w1);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w0,a,b);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w1,a,b);
+
+	FP4_from_FP2s(&f1,&w0,&w1);
+	FP16_YYY_from_FP4s(&t1,&f0,&f1);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w0,a,b);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w1,a,b);
+
+	FP4_from_FP2s(&f0,&w0,&w1);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w0,a,b);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w1,a,b);
+
+	FP4_from_FP2s(&f1,&w0,&w1);
+	FP16_YYY_from_FP4s(&t2,&f0,&f1);
+
+	FP48_from_FP16s(&w,&t0,&t1,&t2);
+
+
+	FP48_copy(&t,&w);
+
+	printf("w= ");
+	FP48_output(&w);
+	printf("\n");
+
+	FP48_norm(&w);
+
+	printf("w^p= ");
+	FP48_frob(&w,&X);
+	FP48_output(&w);
+	printf("\n");	
+
+//	printf("p.w= ");
+//	FP48_ppow(&t,&t,p);
+//	FP48_output(&t);
+//	printf("\n");	
+
+	printf("1/w= ");
+	FP48_inv(&t,&w);
+	FP48_output(&t);
+	printf("\n");	
+
+	printf("w= ");
+	FP48_inv(&w,&t);
+	FP48_output(&w);
+	printf("\n");	
+
+	return 0;
+}
+
+*/
diff --git a/version3/c/fp48.h b/version3/c/fp48.h
new file mode 100644
index 0000000..75065b5
--- /dev/null
+++ b/version3/c/fp48.h
@@ -0,0 +1,196 @@
+#ifndef FP48_YYY_H
+#define FP48_YYY_H
+
+#include "fp16_YYY.h"
+
+/**
+	@brief FP12 Structure - towered over three FP16
+*/
+
+typedef struct
+{
+    FP16_YYY a; /**< first part of FP12 */
+    FP16_YYY b; /**< second part of FP12 */
+    FP16_YYY c; /**< third part of FP12 */
+} FP48_YYY;
+
+extern const BIG_XXX Fra_YYY; /**< real part of BN curve Frobenius Constant */
+extern const BIG_XXX Frb_YYY; /**< imaginary part of BN curve Frobenius Constant */
+
+/* FP48 prototypes */
+/**	@brief Tests for FP48 equal to zero
+ *
+	@param x FP48 number to be tested
+	@return 1 if zero, else returns 0
+ */
+extern int FP48_YYY_iszilch(FP48_YYY *x);
+/**	@brief Tests for FP48 equal to unity
+ *
+	@param x FP48 number to be tested
+	@return 1 if unity, else returns 0
+ */
+extern int FP48_YYY_isunity(FP48_YYY *x);
+/**	@brief Copy FP48 to another FP48
+ *
+	@param x FP48 instance, on exit = y
+	@param y FP48 instance to be copied
+ */
+extern void FP48_YYY_copy(FP48_YYY *x,FP48_YYY *y);
+/**	@brief Set FP48 to unity
+ *
+	@param x FP48 instance to be set to one
+ */
+extern void FP48_YYY_one(FP48_YYY *x);
+/**	@brief Tests for equality of two FP48s
+ *
+	@param x FP48 instance to be compared
+	@param y FP48 instance to be compared
+	@return 1 if x=y, else returns 0
+ */
+extern int FP48_YYY_equals(FP48_YYY *x,FP48_YYY *y);
+/**	@brief Conjugation of FP48
+ *
+	If y=(a,b,c) (where a,b,c are its three FP16 components) on exit x=(conj(a),-conj(b),conj(c))
+	@param x FP48 instance, on exit = conj(y)
+	@param y FP48 instance
+ */
+extern void FP48_YYY_conj(FP48_YYY *x,FP48_YYY *y);
+/**	@brief Initialise FP48 from single FP16
+ *
+	Sets first FP16 component of an FP48, other components set to zero
+	@param x FP48 instance to be initialised
+	@param a FP16 to form first part of FP48
+ */
+extern void FP48_YYY_from_FP16(FP48_YYY *x,FP16_YYY *a);
+/**	@brief Initialise FP48 from three FP16s
+ *
+	@param x FP48 instance to be initialised
+	@param a FP16 to form first part of FP48
+	@param b FP16 to form second part of FP48
+	@param c FP16 to form third part of FP48
+ */
+extern void FP48_YYY_from_FP16s(FP48_YYY *x,FP16_YYY *a,FP16_YYY* b,FP16_YYY *c);
+/**	@brief Fast Squaring of an FP48 in "unitary" form
+ *
+	@param x FP48 instance, on exit = y^2
+	@param y FP16 instance, must be unitary
+ */
+extern void FP48_YYY_usqr(FP48_YYY *x,FP48_YYY *y);
+/**	@brief Squaring an FP48
+ *
+	@param x FP48 instance, on exit = y^2
+	@param y FP48 instance
+ */
+extern void FP48_YYY_sqr(FP48_YYY *x,FP48_YYY *y);
+/**	@brief Fast multiplication of an FP48 by an FP48 that arises from an ATE pairing line function
+ *
+	Here the multiplier has a special form that can be exploited
+	@param x FP48 instance, on exit = x*y
+	@param y FP48 instance, of special form
+	@param t D_TYPE or M_TYPE twist
+ */
+extern void FP48_YYY_smul(FP48_YYY *x,FP48_YYY *y,int t);
+/**	@brief Multiplication of two FP48s
+ *
+	@param x FP48 instance, on exit = x*y
+	@param y FP48 instance, the multiplier
+ */
+extern void FP48_YYY_mul(FP48_YYY *x,FP48_YYY *y);
+/**	@brief Inverting an FP48
+ *
+	@param x FP48 instance, on exit = 1/y
+	@param y FP48 instance
+ */
+extern void FP48_YYY_inv(FP48_YYY *x,FP48_YYY *y);
+/**	@brief Raises an FP48 to the power of a BIG
+ *
+	@param r FP48 instance, on exit = y^b
+	@param x FP48 instance
+	@param b BIG number
+ */
+extern void FP48_YYY_pow(FP48_YYY *r,FP48_YYY *x,BIG_XXX b);
+
+//extern void FP48_ppow(FP48 *r,FP48 *x,BIG b);
+
+/**	@brief Raises an FP48 instance x to a small integer power, side-channel resistant
+ *
+	@param x FP48 instance, on exit = x^i
+	@param i small integer exponent
+	@param b maximum number of bits in exponent
+ */
+extern void FP48_YYY_pinpow(FP48_YYY *x,int i,int b);
+
+/**	@brief Raises an FP48 instance x to a BIG_XXX power, compressed to FP16 
+ *
+	@param c FP16 instance, on exit = x^(e mod r) as FP16
+	@param x FP48 input
+	@param e BIG exponent
+	@param r BIG group order
+ */
+extern void FP48_YYY_compow(FP16_YYY *c,FP48_YYY *x,BIG_XXX e,BIG_XXX r);
+
+/**	@brief Calculate Pi x[i]^b[i] for i=0 to 15, side-channel resistant
+ *
+	@param r FP48 instance, on exit = Pi x[i]^b[i] for i=0 to 15
+	@param x FP48 array with 16 FP48s
+	@param b BIG array of 16 exponents
+ */
+extern void FP48_YYY_pow16(FP48_YYY *r,FP48_YYY *x,BIG_XXX *b);
+
+
+/**	@brief Raises an FP48 to the power of the internal modulus p, using the Frobenius
+ *
+	@param x FP48 instance, on exit = x^p^n
+	@param f FP2 precalculated Frobenius constant
+	@param n power of p
+ */
+extern void FP48_YYY_frob(FP48_YYY *x,FP2_YYY *f,int n);
+
+/**	@brief Reduces all components of possibly unreduced FP48 mod Modulus
+ *
+	@param x FP48 instance, on exit reduced mod Modulus
+ */
+extern void FP48_YYY_reduce(FP48_YYY *x);
+/**	@brief Normalises the components of an FP48
+ *
+	@param x FP48 instance to be normalised
+ */
+extern void FP48_YYY_norm(FP48_YYY *x);
+/**	@brief Formats and outputs an FP48 to the console
+ *
+	@param x FP48 instance to be printed
+ */
+extern void FP48_YYY_output(FP48_YYY *x);
+/**	@brief Formats and outputs an FP48 instance to an octet string
+ *
+	Serializes the components of an FP48 to big-endian base 256 form.
+	@param S output octet string
+	@param x FP48 instance to be converted to an octet string
+ */
+extern void FP48_YYY_toOctet(octet *S,FP48_YYY *x);
+/**	@brief Creates an FP48 instance from an octet string
+ *
+	De-serializes the components of an FP48 to create an FP48 from big-endian base 256 components.
+	@param x FP48 instance to be created from an octet string
+	@param S input octet string
+
+ */
+extern void FP48_YYY_fromOctet(FP48_YYY *x,octet *S);
+/**	@brief Calculate the trace of an FP48
+ *
+	@param t FP16 trace of x, on exit = tr(x)
+	@param x FP48 instance
+
+ */
+extern void FP48_YYY_trace(FP16_YYY *t,FP48_YYY *x);
+
+/**	@brief Conditional copy of FP48 number
+ *
+	Conditionally copies second parameter to the first (without branching)
+	@param x FP48 instance, set to y if s!=0
+	@param y another FP48 instance
+	@param s copy only takes place if not equal to 0
+ */
+extern void FP48_YYY_cmove(FP48_YYY *x,FP48_YYY *y,int s);
+
+#endif
diff --git a/version3/c/fp8.c b/version3/c/fp8.c
new file mode 100644
index 0000000..a2349c5
--- /dev/null
+++ b/version3/c/fp8.c
@@ -0,0 +1,795 @@
+/*
+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.
+*/
+
+/* AMCL Fp^8 functions */
+
+/* FP8 elements are of the form a+ib, where i is sqrt(sqrt(-1+sqrt(-1))) */
+
+#include "fp8_YYY.h"
+
+
+/* test x==0 ? */
+int FP8_YYY_iszilch(FP8_YYY *x)
+{
+    if (FP4_YYY_iszilch(&(x->a)) && FP4_YYY_iszilch(&(x->b))) return 1;
+    return 0;
+}
+
+/* test x==1 ? */
+int FP8_YYY_isunity(FP8_YYY *x)
+{
+    if (FP4_YYY_isunity(&(x->a)) && FP4_YYY_iszilch(&(x->b))) return 1;
+    return 0;
+}
+
+/* test is w real? That is in a+ib test b is zero */
+int FP8_YYY_isreal(FP8_YYY *w)
+{
+    return FP4_YYY_iszilch(&(w->b));
+}
+
+/* return 1 if x==y, else 0 */
+int FP8_YYY_equals(FP8_YYY *x,FP8_YYY *y)
+{
+    if (FP4_YYY_equals(&(x->a),&(y->a)) && FP4_YYY_equals(&(x->b),&(y->b)))
+        return 1;
+    return 0;
+}
+
+/* set FP8 from two FP4s */
+void FP8_YYY_from_FP4s(FP8_YYY *w,FP4_YYY * x,FP4_YYY* y)
+{
+    FP4_YYY_copy(&(w->a), x);
+    FP4_YYY_copy(&(w->b), y);
+}
+
+/* set FP8 from FP4 */
+void FP8_YYY_from_FP4(FP8_YYY *w,FP4_YYY *x)
+{
+    FP4_YYY_copy(&(w->a), x);
+    FP4_YYY_zero(&(w->b));
+}
+
+/* set high part of FP8 from FP4 */
+void FP8_YYY_from_FP4H(FP8_YYY *w,FP4_YYY *x)
+{
+    FP4_YYY_copy(&(w->b), x);
+    FP4_YYY_zero(&(w->a));
+}
+
+/* FP8 copy w=x */
+void FP8_YYY_copy(FP8_YYY *w,FP8_YYY *x)
+{
+    if (w==x) return;
+    FP4_YYY_copy(&(w->a), &(x->a));
+    FP4_YYY_copy(&(w->b), &(x->b));
+}
+
+/* FP8 w=0 */
+void FP8_YYY_zero(FP8_YYY *w)
+{
+    FP4_YYY_zero(&(w->a));
+    FP4_YYY_zero(&(w->b));
+}
+
+/* FP8 w=1 */
+void FP8_YYY_one(FP8_YYY *w)
+{
+    FP4_YYY_one(&(w->a));
+    FP4_YYY_zero(&(w->b));
+}
+
+/* Set w=-x */
+void FP8_YYY_neg(FP8_YYY *w,FP8_YYY *x)
+{
+    /* Just one field neg */
+    FP4_YYY m,t;
+	FP8_YYY_norm(x);
+//printf("Into neg 1\n");
+    FP4_YYY_add(&m,&(x->a),&(x->b));
+	FP4_YYY_norm(&m);
+//printf("Into neg 2\n");
+    FP4_YYY_neg(&m,&m);
+//printf("Into neg 3\n");
+    FP4_YYY_add(&t,&m,&(x->b));
+//printf("Into neg 4\n");
+    FP4_YYY_add(&(w->b),&m,&(x->a));
+//printf("Into neg 5\n");
+    FP4_YYY_copy(&(w->a),&t);
+	FP8_YYY_norm(w);
+}
+
+/* Set w=conj(x) */
+void FP8_YYY_conj(FP8_YYY *w,FP8_YYY *x)
+{
+    FP4_YYY_copy(&(w->a), &(x->a));
+    FP4_YYY_neg(&(w->b), &(x->b));
+	FP8_YYY_norm(w);
+}
+
+/* Set w=-conj(x) */
+void FP8_YYY_nconj(FP8_YYY *w,FP8_YYY *x)
+{
+    FP4_YYY_copy(&(w->b),&(x->b));
+    FP4_YYY_neg(&(w->a), &(x->a));
+	FP8_YYY_norm(w);
+}
+
+/* Set w=x+y */
+void FP8_YYY_add(FP8_YYY *w,FP8_YYY *x,FP8_YYY *y)
+{
+    FP4_YYY_add(&(w->a), &(x->a), &(y->a));
+    FP4_YYY_add(&(w->b), &(x->b), &(y->b));
+}
+
+/* Set w=x-y */
+/* Input y MUST be normed */
+void FP8_YYY_sub(FP8_YYY *w,FP8_YYY *x,FP8_YYY *y)
+{
+    FP8_YYY my;
+
+    FP8_YYY_neg(&my, y);
+    FP8_YYY_add(w, x, &my);
+
+}
+
+/* reduce all components of w mod Modulus */
+void FP8_YYY_reduce(FP8_YYY *w)
+{
+    FP4_YYY_reduce(&(w->a));
+    FP4_YYY_reduce(&(w->b));
+}
+
+/* normalise all elements of w */
+void FP8_YYY_norm(FP8_YYY *w)
+{
+    FP4_YYY_norm(&(w->a));
+    FP4_YYY_norm(&(w->b));
+}
+
+/* Set w=s*x, where s is FP4 */
+void FP8_YYY_pmul(FP8_YYY *w,FP8_YYY *x,FP4_YYY *s)
+{
+    FP4_YYY_mul(&(w->a),&(x->a),s);
+    FP4_YYY_mul(&(w->b),&(x->b),s);
+}
+
+/* Set w=s*x, where s is FP2 */
+void FP8_YYY_qmul(FP8_YYY *w,FP8_YYY *x,FP2_YYY *s)
+{
+    FP4_YYY_pmul(&(w->a),&(x->a),s);
+    FP4_YYY_pmul(&(w->b),&(x->b),s);
+}
+
+/* Set w=s*x, where s is FP2 */
+void FP8_YYY_tmul(FP8_YYY *w,FP8_YYY *x,FP_YYY *s)
+{
+    FP4_YYY_qmul(&(w->a),&(x->a),s);
+    FP4_YYY_qmul(&(w->b),&(x->b),s);
+}
+
+/* Set w=s*x, where s is int */
+void FP8_YYY_imul(FP8_YYY *w,FP8_YYY *x,int s)
+{
+    FP4_YYY_imul(&(w->a),&(x->a),s);
+    FP4_YYY_imul(&(w->b),&(x->b),s);
+}
+
+/* Set w=x^2 */
+/* Input MUST be normed  */
+void FP8_YYY_sqr(FP8_YYY *w,FP8_YYY *x)
+{
+    FP4_YYY t1,t2,t3;
+
+    FP4_YYY_mul(&t3,&(x->a),&(x->b)); /* norms x */
+    FP4_YYY_copy(&t2,&(x->b));
+    FP4_YYY_add(&t1,&(x->a),&(x->b));
+    FP4_YYY_times_i(&t2);
+
+    FP4_YYY_add(&t2,&(x->a),&t2);
+
+	FP4_YYY_norm(&t1);  // 2
+	FP4_YYY_norm(&t2);  // 2
+
+    FP4_YYY_mul(&(w->a),&t1,&t2);
+
+    FP4_YYY_copy(&t2,&t3);
+    FP4_YYY_times_i(&t2);
+
+    FP4_YYY_add(&t2,&t2,&t3);
+
+	FP4_YYY_norm(&t2);  // 2
+    FP4_YYY_neg(&t2,&t2);
+    FP4_YYY_add(&(w->a),&(w->a),&t2);  /* a=(a+b)(a+i^2.b)-i^2.ab-ab = a*a+ib*ib */
+    FP4_YYY_add(&(w->b),&t3,&t3);  /* b=2ab */
+
+    FP8_YYY_norm(w);
+}
+
+/* Set w=x*y */
+/* Inputs MUST be normed  */
+void FP8_YYY_mul(FP8_YYY *w,FP8_YYY *x,FP8_YYY *y)
+{
+
+    FP4_YYY t1,t2,t3,t4;
+    FP4_YYY_mul(&t1,&(x->a),&(y->a)); 
+    FP4_YYY_mul(&t2,&(x->b),&(y->b)); 
+
+    FP4_YYY_add(&t3,&(y->b),&(y->a));
+    FP4_YYY_add(&t4,&(x->b),&(x->a));
+
+	FP4_YYY_norm(&t4); // 2
+	FP4_YYY_norm(&t3); // 2
+
+    FP4_YYY_mul(&t4,&t4,&t3); /* (xa+xb)(ya+yb) */
+
+	FP4_YYY_neg(&t3,&t1);  // 1
+	FP4_YYY_add(&t4,&t4,&t3);  //t4E=3
+    FP4_YYY_norm(&t4);
+
+	FP4_YYY_neg(&t3,&t2);  // 1
+	FP4_YYY_add(&(w->b),&t4,&t3); //wbE=3
+
+    FP4_YYY_times_i(&t2);
+    FP4_YYY_add(&(w->a),&t2,&t1);
+
+    FP8_YYY_norm(w);
+}
+
+/* output FP8 in format [a,b] */
+void FP8_YYY_output(FP8_YYY *w)
+{
+    printf("[");
+    FP4_YYY_output(&(w->a));
+    printf(",");
+    FP4_YYY_output(&(w->b));
+    printf("]");
+}
+
+void FP8_YYY_rawoutput(FP8_YYY *w)
+{
+    printf("[");
+    FP4_YYY_rawoutput(&(w->a));
+    printf(",");
+    FP4_YYY_rawoutput(&(w->b));
+    printf("]");
+}
+
+/* Set w=1/x */
+void FP8_YYY_inv(FP8_YYY *w,FP8_YYY *x)
+{
+    FP4_YYY t1,t2;
+    FP4_YYY_sqr(&t1,&(x->a));
+    FP4_YYY_sqr(&t2,&(x->b));
+    FP4_YYY_times_i(&t2);
+	FP4_YYY_norm(&t2);
+
+    FP4_YYY_sub(&t1,&t1,&t2);
+	FP4_YYY_norm(&t1);
+//printf(" in mark 1\n");
+    FP4_YYY_inv(&t1,&t1);
+//printf(" in mark 2\n");
+    FP4_YYY_mul(&(w->a),&t1,&(x->a));
+    FP4_YYY_neg(&t1,&t1);
+	FP4_YYY_norm(&t1);
+    FP4_YYY_mul(&(w->b),&t1,&(x->b));
+}
+
+/* w*=i where i = sqrt(sqrt(-1+sqrt(-1))) */
+void FP8_YYY_times_i(FP8_YYY *w)
+{
+	FP4_YYY s,t;
+	FP4_YYY_copy(&s,&(w->b));
+	FP4_YYY_copy(&t,&(w->a));
+	FP4_YYY_times_i(&s);
+	FP4_YYY_copy(&(w->a),&s);
+	FP4_YYY_copy(&(w->b),&t);
+	FP8_YYY_norm(w);
+}
+
+void FP8_YYY_times_i2(FP8_YYY *w)
+{
+	FP4_YYY_times_i(&(w->a));
+	FP4_YYY_times_i(&(w->b));
+}
+
+/* Set w=w^p using Frobenius */
+void FP8_YYY_frob(FP8_YYY *w,FP2_YYY *f)
+{ // f=(i+1)^(p-3)/4
+	FP2_YYY ff;
+	FP2_YYY_sqr(&ff,f);  // (i+1)^(p-3)/2
+	FP2_YYY_mul_ip(&ff); // (i+1)^(p-1)/2
+	FP2_YYY_norm(&ff);
+//printf("in in here 1\n");
+	FP4_YYY_frob(&(w->a),&ff);
+	FP4_YYY_frob(&(w->b),&ff);
+//printf("in in here 2\n");
+	FP4_YYY_pmul(&(w->b),&(w->b),f);  // times (1+i)^(p-3)/4
+	FP4_YYY_times_i(&(w->b));		// (i+1)^(p-1)/4
+}
+
+/* Set r=a^b mod m */
+void FP8_YYY_pow(FP8_YYY *r,FP8_YYY* a,BIG_XXX b)
+{
+    FP8_YYY w;
+    BIG_XXX z,zilch;
+    int bt;
+
+    BIG_XXX_zero(zilch);
+
+    BIG_XXX_copy(z,b);
+    FP8_YYY_copy(&w,a);
+	FP8_YYY_norm(&w);
+    FP8_YYY_one(r);
+    BIG_XXX_norm(z);
+    while(1)
+    {
+        bt=BIG_XXX_parity(z);
+        BIG_XXX_shr(z,1);
+        if (bt) FP8_YYY_mul(r,r,&w);
+        if (BIG_XXX_comp(z,zilch)==0) break;
+        FP8_YYY_sqr(&w,&w);
+    }
+    FP8_YYY_reduce(r);
+}
+
+#if CURVE_SECURITY_ZZZ == 192
+
+/* XTR xtr_a function */
+void FP8_YYY_xtr_A(FP8_YYY *r,FP8_YYY *w,FP8_YYY *x,FP8_YYY *y,FP8_YYY *z)
+{
+    FP8_YYY t1,t2;
+
+    FP8_YYY_copy(r,x);
+    FP8_YYY_sub(&t1,w,y);
+	FP8_YYY_norm(&t1);
+    FP8_YYY_pmul(&t1,&t1,&(r->a));
+    FP8_YYY_add(&t2,w,y);
+	FP8_YYY_norm(&t2);
+    FP8_YYY_pmul(&t2,&t2,&(r->b));
+    FP8_YYY_times_i(&t2);
+
+    FP8_YYY_add(r,&t1,&t2);
+    FP8_YYY_add(r,r,z);
+
+    FP8_YYY_reduce(r);
+}
+
+/* XTR xtr_d function */
+void FP8_YYY_xtr_D(FP8_YYY *r,FP8_YYY *x)
+{
+    FP8_YYY w;
+    FP8_YYY_copy(r,x);
+    FP8_YYY_conj(&w,r);
+    FP8_YYY_add(&w,&w,&w);
+    FP8_YYY_sqr(r,r);
+	FP8_YYY_norm(&w);
+    FP8_YYY_sub(r,r,&w);
+    FP8_YYY_reduce(r);    /* reduce here as multiple calls trigger automatic reductions */
+}
+
+/* r=x^n using XTR method on traces of FP12s */
+void FP8_YYY_xtr_pow(FP8_YYY *r,FP8_YYY *x,BIG_XXX n)
+{
+    int i,par,nb;
+    BIG_XXX v;
+    FP2_YYY w2;
+	FP4_YYY w4;
+    FP8_YYY t,a,b,c,sf;
+
+    BIG_XXX_zero(v);
+    BIG_XXX_inc(v,3);
+	BIG_XXX_norm(v);
+    FP2_YYY_from_BIG(&w2,v);
+    FP4_YYY_from_FP2(&w4,&w2);
+    FP8_YYY_from_FP4(&a,&w4);
+	FP8_YYY_copy(&sf,x);
+	FP8_YYY_norm(&sf);
+	FP8_YYY_copy(&b,&sf);
+    FP8_YYY_xtr_D(&c,&sf);
+
+    par=BIG_XXX_parity(n);
+    BIG_XXX_copy(v,n);
+    BIG_XXX_norm(v);
+    BIG_XXX_shr(v,1);
+    if (par==0)
+    {
+        BIG_XXX_dec(v,1);
+        BIG_XXX_norm(v);
+    }
+
+    nb=BIG_XXX_nbits(v);
+    for (i=nb-1; i>=0; i--)
+    {
+        if (!BIG_XXX_bit(v,i))
+        {
+            FP8_YYY_copy(&t,&b);
+            FP8_YYY_conj(&sf,&sf);
+            FP8_YYY_conj(&c,&c);
+            FP8_YYY_xtr_A(&b,&a,&b,&sf,&c);
+            FP8_YYY_conj(&sf,&sf);
+            FP8_YYY_xtr_D(&c,&t);
+            FP8_YYY_xtr_D(&a,&a);
+        }
+        else
+        {
+            FP8_YYY_conj(&t,&a);
+            FP8_YYY_xtr_D(&a,&b);
+            FP8_YYY_xtr_A(&b,&c,&b,&sf,&t);
+            FP8_YYY_xtr_D(&c,&c);
+        }
+    }
+
+    if (par==0) FP8_YYY_copy(r,&c);
+    else FP8_YYY_copy(r,&b);
+    FP8_YYY_reduce(r);
+}
+
+/* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */
+void FP8_YYY_xtr_pow2(FP8_YYY *r,FP8_YYY *ck,FP8_YYY *cl,FP8_YYY *ckml,FP8_YYY *ckm2l,BIG_XXX a,BIG_XXX b)
+{
+    int i,f2;
+    BIG_XXX d,e,w;
+    FP8_YYY t,cu,cv,cumv,cum2v;
+
+
+    BIG_XXX_copy(e,a);
+    BIG_XXX_copy(d,b);
+    BIG_XXX_norm(e);
+	BIG_XXX_norm(d);
+    FP8_YYY_copy(&cu,ck);
+    FP8_YYY_copy(&cv,cl);
+    FP8_YYY_copy(&cumv,ckml);
+    FP8_YYY_copy(&cum2v,ckm2l);
+
+    f2=0;
+    while (BIG_XXX_parity(d)==0 && BIG_XXX_parity(e)==0)
+    {
+        BIG_XXX_shr(d,1);
+        BIG_XXX_shr(e,1);
+        f2++;
+    }
+    while (BIG_XXX_comp(d,e)!=0)
+    {
+        if (BIG_XXX_comp(d,e)>0)
+        {
+            BIG_XXX_imul(w,e,4);
+            BIG_XXX_norm(w);
+            if (BIG_XXX_comp(d,w)<=0)
+            {
+                BIG_XXX_copy(w,d);
+                BIG_XXX_copy(d,e);
+                BIG_XXX_sub(e,w,e);
+                BIG_XXX_norm(e);
+                FP8_YYY_xtr_A(&t,&cu,&cv,&cumv,&cum2v);
+                FP8_YYY_conj(&cum2v,&cumv);
+                FP8_YYY_copy(&cumv,&cv);
+                FP8_YYY_copy(&cv,&cu);
+                FP8_YYY_copy(&cu,&t);
+            }
+            else if (BIG_XXX_parity(d)==0)
+            {
+                BIG_XXX_shr(d,1);
+                FP8_YYY_conj(r,&cum2v);
+                FP8_YYY_xtr_A(&t,&cu,&cumv,&cv,r);
+                FP8_YYY_xtr_D(&cum2v,&cumv);
+                FP8_YYY_copy(&cumv,&t);
+                FP8_YYY_xtr_D(&cu,&cu);
+            }
+            else if (BIG_XXX_parity(e)==1)
+            {
+                BIG_XXX_sub(d,d,e);
+                BIG_XXX_norm(d);
+                BIG_XXX_shr(d,1);
+                FP8_YYY_xtr_A(&t,&cu,&cv,&cumv,&cum2v);
+                FP8_YYY_xtr_D(&cu,&cu);
+                FP8_YYY_xtr_D(&cum2v,&cv);
+                FP8_YYY_conj(&cum2v,&cum2v);
+                FP8_YYY_copy(&cv,&t);
+            }
+            else
+            {
+                BIG_XXX_copy(w,d);
+                BIG_XXX_copy(d,e);
+                BIG_XXX_shr(d,1);
+                BIG_XXX_copy(e,w);
+                FP8_YYY_xtr_D(&t,&cumv);
+                FP8_YYY_conj(&cumv,&cum2v);
+                FP8_YYY_conj(&cum2v,&t);
+                FP8_YYY_xtr_D(&t,&cv);
+                FP8_YYY_copy(&cv,&cu);
+                FP8_YYY_copy(&cu,&t);
+            }
+        }
+        if (BIG_XXX_comp(d,e)<0)
+        {
+            BIG_XXX_imul(w,d,4);
+            BIG_XXX_norm(w);
+            if (BIG_XXX_comp(e,w)<=0)
+            {
+                BIG_XXX_sub(e,e,d);
+                BIG_XXX_norm(e);
+                FP8_YYY_xtr_A(&t,&cu,&cv,&cumv,&cum2v);
+                FP8_YYY_copy(&cum2v,&cumv);
+                FP8_YYY_copy(&cumv,&cu);
+                FP8_YYY_copy(&cu,&t);
+            }
+            else if (BIG_XXX_parity(e)==0)
+            {
+                BIG_XXX_copy(w,d);
+                BIG_XXX_copy(d,e);
+                BIG_XXX_shr(d,1);
+                BIG_XXX_copy(e,w);
+                FP8_YYY_xtr_D(&t,&cumv);
+                FP8_YYY_conj(&cumv,&cum2v);
+                FP8_YYY_conj(&cum2v,&t);
+                FP8_YYY_xtr_D(&t,&cv);
+                FP8_YYY_copy(&cv,&cu);
+                FP8_YYY_copy(&cu,&t);
+            }
+            else if (BIG_XXX_parity(d)==1)
+            {
+                BIG_XXX_copy(w,e);
+                BIG_XXX_copy(e,d);
+                BIG_XXX_sub(w,w,d);
+                BIG_XXX_norm(w);
+                BIG_XXX_copy(d,w);
+                BIG_XXX_shr(d,1);
+                FP8_YYY_xtr_A(&t,&cu,&cv,&cumv,&cum2v);
+                FP8_YYY_conj(&cumv,&cumv);
+                FP8_YYY_xtr_D(&cum2v,&cu);
+                FP8_YYY_conj(&cum2v,&cum2v);
+                FP8_YYY_xtr_D(&cu,&cv);
+                FP8_YYY_copy(&cv,&t);
+            }
+            else
+            {
+                BIG_XXX_shr(d,1);
+                FP8_YYY_conj(r,&cum2v);
+                FP8_YYY_xtr_A(&t,&cu,&cumv,&cv,r);
+                FP8_YYY_xtr_D(&cum2v,&cumv);
+                FP8_YYY_copy(&cumv,&t);
+                FP8_YYY_xtr_D(&cu,&cu);
+            }
+        }
+    }
+    FP8_YYY_xtr_A(r,&cu,&cv,&cumv,&cum2v);
+    for (i=0; i<f2; i++)	FP8_YYY_xtr_D(r,r);
+    FP8_YYY_xtr_pow(r,r,d);
+}
+
+#endif
+
+
+/* New stuff for ECp8 support */
+
+/* Move b to a if d=1 */
+void FP8_YYY_cmove(FP8_YYY *f,FP8_YYY *g,int d)
+{
+    FP4_YYY_cmove(&(f->a),&(g->a),d);
+    FP4_YYY_cmove(&(f->b),&(g->b),d);
+}
+
+#if CURVE_SECURITY_ZZZ == 256
+
+/* sqrt(a+xb) = sqrt((a+sqrt(a*a-n*b*b))/2)+x.b/(2*sqrt((a+sqrt(a*a-n*b*b))/2)) */
+/* returns true if x is QR */
+int FP8_YYY_sqrt(FP8_YYY *r,FP8_YYY* x)
+{
+	FP4_YYY a,s,t;
+
+	FP8_YYY_copy(r,x);
+	if (FP8_YYY_iszilch(x))
+		return 1;
+	
+	FP4_YYY_copy(&a,&(x->a));
+	FP4_YYY_copy(&s,&(x->b));
+
+	if (FP4_YYY_iszilch(&s))
+	{
+		if (FP4_YYY_sqrt(&t,&a))
+		{
+			FP8_YYY_from_FP4(r,&t);
+		}
+		else
+		{
+			FP4_YYY_div_i(&a);
+			FP4_YYY_sqrt(&t,&a);
+			FP8_YYY_from_FP4H(r,&t);
+		}
+		return 1;
+	}
+
+	FP4_YYY_sqr(&s,&s);  // s*=s
+	FP4_YYY_sqr(&a,&a);  // a*=a
+	FP4_YYY_times_i(&s);
+	FP4_YYY_norm(&s);
+	FP4_YYY_sub(&a,&a,&s); // a-=txx(s)
+
+	if (!FP4_YYY_sqrt(&s,&a)) return 0;
+
+	FP4_YYY_sqr(&t,&s);
+
+
+	FP4_YYY_copy(&t,&(x->a));
+	FP4_YYY_add(&a,&t,&s);
+	FP4_YYY_norm(&a);
+	FP4_YYY_div2(&a,&a);
+
+	if (!FP4_YYY_sqrt(&a,&a))
+	{
+		FP4_YYY_sub(&a,&t,&s);
+		FP4_YYY_norm(&a);
+		FP4_YYY_div2(&a,&a);
+		if (!FP4_YYY_sqrt(&a,&a)) return 0;
+	}
+
+	FP4_YYY_copy(&t,&(x->b));
+	FP4_YYY_add(&s,&a,&a);
+	FP4_YYY_inv(&s,&s);
+
+	FP4_YYY_mul(&t,&t,&s);
+	FP8_YYY_from_FP4s(r,&a,&t);
+
+	return 1;
+
+}
+
+
+void FP8_YYY_div_i(FP8_YYY *f)
+{
+	FP4_YYY u,v;
+	FP4_YYY_copy(&u,&(f->a));
+	FP4_YYY_copy(&v,&(f->b));
+	FP4_YYY_div_i(&u);
+	FP4_YYY_copy(&(f->a),&v);
+	FP4_YYY_copy(&(f->b),&u);
+}
+
+void FP8_YYY_div_i2(FP8_YYY *f)
+{
+	FP4_YYY_div_i(&(f->a));
+	FP4_YYY_div_i(&(f->b));
+}
+
+
+void FP8_YYY_div_2i(FP8_YYY *f)
+{
+	FP4_YYY u,v;
+	FP4_YYY_copy(&u,&(f->a));
+	FP4_YYY_copy(&v,&(f->b));
+	FP4_YYY_div_2i(&u);
+	FP4_YYY_add(&v,&v,&v);
+	FP4_YYY_norm(&v);
+	FP4_YYY_copy(&(f->a),&v);
+	FP4_YYY_copy(&(f->b),&u);
+}
+
+#endif
+
+/*
+int main(){
+		FP2 w0,w1,f;
+		FP4 w,t;
+		FP4 c1,c2,c3,c4,cr;
+		BIG a,b;
+		BIG e,e1,e2;
+		BIG p,md;
+
+
+		BIG_rcopy(md,Modulus);
+		//Test w^(P^4) = w mod p^2
+		BIG_zero(a); BIG_inc(a,27);
+		BIG_zero(b); BIG_inc(b,45);
+		FP2_from_BIGs(&w0,a,b);
+
+		BIG_zero(a); BIG_inc(a,33);
+		BIG_zero(b); BIG_inc(b,54);
+		FP2_from_BIGs(&w1,a,b);
+
+		FP4_from_FP2s(&w,&w0,&w1);
+		FP4_reduce(&w);
+
+		printf("w= ");
+		FP4_output(&w);
+		printf("\n");
+
+
+		FP4_copy(&t,&w);
+
+
+		BIG_copy(p,md);
+		FP4_pow(&w,&w,p);
+
+		printf("w^p= ");
+		FP4_output(&w);
+		printf("\n");
+//exit(0);
+
+		BIG_rcopy(a,CURVE_Fra);
+		BIG_rcopy(b,CURVE_Frb);
+		FP2_from_BIGs(&f,a,b);
+
+		FP4_frob(&t,&f);
+		printf("w^p= ");
+		FP4_output(&t);
+		printf("\n");
+
+		FP4_pow(&w,&w,p);
+		FP4_pow(&w,&w,p);
+		FP4_pow(&w,&w,p);
+		printf("w^p4= ");
+		FP4_output(&w);
+		printf("\n");
+
+// Test 1/(1/x) = x mod p^4
+		FP4_from_FP2s(&w,&w0,&w1);
+		printf("Test Inversion \nw= ");
+		FP4_output(&w);
+		printf("\n");
+
+		FP4_inv(&w,&w);
+		printf("1/w mod p^4 = ");
+		FP4_output(&w);
+		printf("\n");
+
+		FP4_inv(&w,&w);
+		printf("1/(1/w) mod p^4 = ");
+		FP4_output(&w);
+		printf("\n");
+
+		BIG_zero(e); BIG_inc(e,12);
+
+
+
+	//	FP4_xtr_A(&w,&t,&w,&t,&t);
+		FP4_xtr_pow(&w,&w,e);
+
+		printf("w^e= ");
+		FP4_output(&w);
+		printf("\n");
+
+
+		BIG_zero(a); BIG_inc(a,37);
+		BIG_zero(b); BIG_inc(b,17);
+		FP2_from_BIGs(&w0,a,b);
+
+		BIG_zero(a); BIG_inc(a,49);
+		BIG_zero(b); BIG_inc(b,31);
+		FP2_from_BIGs(&w1,a,b);
+
+		FP4_from_FP2s(&c1,&w0,&w1);
+		FP4_from_FP2s(&c2,&w0,&w1);
+		FP4_from_FP2s(&c3,&w0,&w1);
+		FP4_from_FP2s(&c4,&w0,&w1);
+
+		BIG_zero(e1); BIG_inc(e1,3331);
+		BIG_zero(e2); BIG_inc(e2,3372);
+
+		FP4_xtr_pow2(&w,&c1,&w,&c2,&c3,e1,e2);
+
+		printf("c^e= ");
+		FP4_output(&w);
+		printf("\n");
+
+
+		return 0;
+}
+*/
+
diff --git a/version3/c/fp8.h b/version3/c/fp8.h
new file mode 100644
index 0000000..82b543d
--- /dev/null
+++ b/version3/c/fp8.h
@@ -0,0 +1,294 @@
+#ifndef FP8_YYY_H
+#define FP8_YYY_H
+
+#include "fp4_YYY.h"
+#include "config_curve_ZZZ.h"
+
+
+/**
+	@brief FP8 Structure - towered over two FP4
+*/
+
+typedef struct
+{
+    FP4_YYY a; /**< real part of FP8 */
+    FP4_YYY b; /**< imaginary part of FP8 */
+} FP8_YYY;
+
+
+/* FP8 prototypes */
+/**	@brief Tests for FP8 equal to zero
+ *
+	@param x FP8 number to be tested
+	@return 1 if zero, else returns 0
+ */
+extern int FP8_YYY_iszilch(FP8_YYY *x);
+/**	@brief Tests for FP8 equal to unity
+ *
+	@param x FP8 number to be tested
+	@return 1 if unity, else returns 0
+ */
+extern int FP8_YYY_isunity(FP8_YYY *x);
+/**	@brief Tests for equality of two FP8s
+ *
+	@param x FP8 instance to be compared
+	@param y FP8 instance to be compared
+	@return 1 if x=y, else returns 0
+ */
+extern int FP8_YYY_equals(FP8_YYY *x,FP8_YYY *y);
+/**	@brief Tests for FP8 having only a real part and no imaginary part
+ *
+	@param x FP8 number to be tested
+	@return 1 if real, else returns 0
+ */
+extern int FP8_YYY_isreal(FP8_YYY *x);
+/**	@brief Initialise FP8 from two FP4s
+ *
+	@param x FP8 instance to be initialised
+	@param a FP4 to form real part of FP8
+	@param b FP4 to form imaginary part of FP8
+ */
+extern void FP8_YYY_from_FP4s(FP8_YYY *x,FP4_YYY *a,FP4_YYY *b);
+/**	@brief Initialise FP8 from single FP4
+ *
+	Imaginary part is set to zero
+	@param x FP8 instance to be initialised
+	@param a FP4 to form real part of FP8
+ */
+extern void FP8_YYY_from_FP4(FP8_YYY *x,FP4_YYY *a);
+
+/**	@brief Initialise FP8 from single FP4
+ *
+	real part is set to zero
+	@param x FP8 instance to be initialised
+	@param a FP4 to form imaginary part of FP8
+ */
+extern void FP8_YYY_from_FP4H(FP8_YYY *x,FP4_YYY *a);
+
+
+/**	@brief Copy FP8 to another FP8
+ *
+	@param x FP8 instance, on exit = y
+	@param y FP8 instance to be copied
+ */
+extern void FP8_YYY_copy(FP8_YYY *x,FP8_YYY *y);
+/**	@brief Set FP8 to zero
+ *
+	@param x FP8 instance to be set to zero
+ */
+extern void FP8_YYY_zero(FP8_YYY *x);
+/**	@brief Set FP8 to unity
+ *
+	@param x FP8 instance to be set to one
+ */
+extern void FP8_YYY_one(FP8_YYY *x);
+/**	@brief Negation of FP8
+ *
+	@param x FP8 instance, on exit = -y
+	@param y FP8 instance
+ */
+extern void FP8_YYY_neg(FP8_YYY *x,FP8_YYY *y);
+/**	@brief Conjugation of FP8
+ *
+	If y=(a,b) on exit x=(a,-b)
+	@param x FP8 instance, on exit = conj(y)
+	@param y FP8 instance
+ */
+extern void FP8_YYY_conj(FP8_YYY *x,FP8_YYY *y);
+/**	@brief Negative conjugation of FP8
+ *
+	If y=(a,b) on exit x=(-a,b)
+	@param x FP8 instance, on exit = -conj(y)
+	@param y FP8 instance
+ */
+extern void FP8_YYY_nconj(FP8_YYY *x,FP8_YYY *y);
+/**	@brief addition of two FP8s
+ *
+	@param x FP8 instance, on exit = y+z
+	@param y FP8 instance
+	@param z FP8 instance
+ */
+extern void FP8_YYY_add(FP8_YYY *x,FP8_YYY *y,FP8_YYY *z);
+/**	@brief subtraction of two FP8s
+ *
+	@param x FP8 instance, on exit = y-z
+	@param y FP8 instance
+	@param z FP8 instance
+ */
+extern void FP8_YYY_sub(FP8_YYY *x,FP8_YYY *y,FP8_YYY *z);
+/**	@brief Multiplication of an FP8 by an FP4
+ *
+	@param x FP8 instance, on exit = y*a
+	@param y FP8 instance
+	@param a FP4 multiplier
+ */
+extern void FP8_YYY_pmul(FP8_YYY *x,FP8_YYY *y,FP4_YYY *a);
+
+/**	@brief Multiplication of an FP8 by an FP2
+ *
+	@param x FP8 instance, on exit = y*a
+	@param y FP8 instance
+	@param a FP2 multiplier
+ */
+extern void FP8_YYY_qmul(FP8_YYY *x,FP8_YYY *y,FP2_YYY *a);
+
+/**	@brief Multiplication of an FP8 by an FP
+ *
+	@param x FP8 instance, on exit = y*a
+	@param y FP8 instance
+	@param a FP multiplier
+ */
+extern void FP8_YYY_tmul(FP8_YYY *x,FP8_YYY *y,FP_YYY *a);
+
+/**	@brief Multiplication of an FP8 by a small integer
+ *
+	@param x FP8 instance, on exit = y*i
+	@param y FP8 instance
+	@param i an integer
+ */
+extern void FP8_YYY_imul(FP8_YYY *x,FP8_YYY *y,int i);
+/**	@brief Squaring an FP8
+ *
+	@param x FP8 instance, on exit = y^2
+	@param y FP8 instance
+ */
+extern void FP8_YYY_sqr(FP8_YYY *x,FP8_YYY *y);
+/**	@brief Multiplication of two FP8s
+ *
+	@param x FP8 instance, on exit = y*z
+	@param y FP8 instance
+	@param z FP8 instance
+ */
+extern void FP8_YYY_mul(FP8_YYY *x,FP8_YYY *y,FP8_YYY *z);
+/**	@brief Inverting an FP8
+ *
+	@param x FP8 instance, on exit = 1/y
+	@param y FP8 instance
+ */
+extern void FP8_YYY_inv(FP8_YYY *x,FP8_YYY *y);
+/**	@brief Formats and outputs an FP8 to the console
+ *
+	@param x FP8 instance to be printed
+ */
+extern void FP8_YYY_output(FP8_YYY *x);
+/**	@brief Formats and outputs an FP8 to the console in raw form (for debugging)
+ *
+	@param x FP8 instance to be printed
+ */
+extern void FP8_YYY_rawoutput(FP8_YYY *x);
+/**	@brief multiplies an FP8 instance by irreducible polynomial sqrt(1+sqrt(-1))
+ *
+	@param x FP8 instance, on exit = sqrt(1+sqrt(-1)*x
+ */
+extern void FP8_YYY_times_i(FP8_YYY *x);
+/**	@brief multiplies an FP8 instance by irreducible polynomial (1+sqrt(-1))
+ *
+	@param x FP8 instance, on exit = (1+sqrt(-1)*x
+ */
+extern void FP8_YYY_times_i2(FP8_YYY *x);
+
+/**	@brief Normalises the components of an FP8
+ *
+	@param x FP8 instance to be normalised
+ */
+extern void FP8_YYY_norm(FP8_YYY *x);
+/**	@brief Reduces all components of possibly unreduced FP8 mod Modulus
+ *
+	@param x FP8 instance, on exit reduced mod Modulus
+ */
+extern void FP8_YYY_reduce(FP8_YYY *x);
+/**	@brief Raises an FP8 to the power of a BIG
+ *
+	@param x FP8 instance, on exit = y^b
+	@param y FP8 instance
+	@param b BIG number
+ */
+extern void FP8_YYY_pow(FP8_YYY *x,FP8_YYY *y,BIG_XXX b);
+/**	@brief Raises an FP8 to the power of the internal modulus p, using the Frobenius
+ *
+	@param x FP8 instance, on exit = x^p
+	@param f FP2 precalculated Frobenius constant
+ */
+extern void FP8_YYY_frob(FP8_YYY *x,FP2_YYY *f);
+/**	@brief Calculates the XTR addition function r=w*x-conj(x)*y+z
+ *
+	@param r FP8 instance, on exit = w*x-conj(x)*y+z
+	@param w FP8 instance
+	@param x FP8 instance
+	@param y FP8 instance
+	@param z FP8 instance
+ */
+extern void FP8_YYY_xtr_A(FP8_YYY *r,FP8_YYY *w,FP8_YYY *x,FP8_YYY *y,FP8_YYY *z);
+/**	@brief Calculates the XTR doubling function r=x^2-2*conj(x)
+ *
+	@param r FP8 instance, on exit = x^2-2*conj(x)
+	@param x FP8 instance
+ */
+extern void FP8_YYY_xtr_D(FP8_YYY *r,FP8_YYY *x);
+/**	@brief Calculates FP8 trace of an FP12 raised to the power of a BIG number
+ *
+	XTR single exponentiation
+	@param r FP8 instance, on exit = trace(w^b)
+	@param x FP8 instance, trace of an FP12 w
+	@param b BIG number
+ */
+extern void FP8_YYY_xtr_pow(FP8_YYY *r,FP8_YYY *x,BIG_XXX b);
+/**	@brief Calculates FP8 trace of c^a.d^b, where c and d are derived from FP8 traces of FP12s
+ *
+	XTR double exponentiation
+	Assumes c=tr(x^m), d=tr(x^n), e=tr(x^(m-n)), f=tr(x^(m-2n))
+	@param r FP8 instance, on exit = trace(c^a.d^b)
+	@param c FP8 instance, trace of an FP12
+	@param d FP8 instance, trace of an FP12
+	@param e FP8 instance, trace of an FP12
+	@param f FP8 instance, trace of an FP12
+	@param a BIG number
+	@param b BIG number
+ */
+extern void FP8_YYY_xtr_pow2(FP8_YYY *r,FP8_YYY *c,FP8_YYY *d,FP8_YYY *e,FP8_YYY *f,BIG_XXX a,BIG_XXX b);
+
+
+/**	@brief Calculate square root of an FP8
+ *
+	Square root
+	@param r FP8 instance, on exit = sqrt(x)
+	@param x FP8 instance
+	@return 1 x is a QR, otherwise 0
+ */
+extern int  FP8_YYY_sqrt(FP8_YYY *r,FP8_YYY *x);
+
+
+/**	@brief Conditional copy of FP8 number
+ *
+	Conditionally copies second parameter to the first (without branching)
+	@param x FP8 instance, set to y if s!=0
+	@param y another FP8 instance
+	@param s copy only takes place if not equal to 0
+ */
+extern void FP8_YYY_cmove(FP8_YYY *x,FP8_YYY *y,int s);
+
+
+/**	@brief Divide FP8 number by QNR
+ *
+	Divide FP8 by the QNR
+	@param x FP8 instance
+ */
+extern void FP8_YYY_div_i(FP8_YYY *x);
+
+/**	@brief Divide FP8 number by QNR twice
+ *
+	Divide FP8 by the QNR twice
+	@param x FP8 instance
+ */
+extern void FP8_YYY_div_i2(FP8_YYY *x);
+
+/**	@brief Divide FP8 number by QNR/2
+ *
+	Divide FP8 by the QNR/2
+	@param x FP8 instance
+ */
+extern void FP8_YYY_div_2i(FP8_YYY *x);
+
+
+#endif
+
diff --git a/version3/c/gcm.c b/version3/c/gcm.c
new file mode 100644
index 0000000..3bd9b8d
--- /dev/null
+++ b/version3/c/gcm.c
@@ -0,0 +1,411 @@
+/*
+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.
+*/
+
+/*
+ * Implementation of the AES-GCM Encryption/Authentication
+ *
+ * Some restrictions..
+ * 1. Only for use with AES
+ * 2. Returned tag is always 128-bits. Truncate at your own risk.
+ * 3. The order of function calls must follow some rules
+ *
+ * Typical sequence of calls..
+ * 1. call GCM_init
+ * 2. call GCM_add_header any number of times, as long as length of header is multiple of 16 bytes (block size)
+ * 3. call GCM_add_header one last time with any length of header
+ * 4. call GCM_add_cipher any number of times, as long as length of cipher/plaintext is multiple of 16 bytes
+ * 5. call GCM_add_cipher one last time with any length of cipher/plaintext
+ * 6. call GCM_finish to extract the tag.
+ *
+ * See http://www.mindspring.com/~dmcgrew/gcm-nist-6.pdf
+ */
+/* SU=m, m is Stack Usage */
+
+#include <stdlib.h>
+#include <string.h>
+#include "arch.h"
+#include "amcl.h"
+
+#define NB 4
+#define MR_TOBYTE(x) ((uchar)((x)))
+
+static unsign32 pack(const uchar *b)
+{
+    /* pack bytes into a 32-bit Word */
+    return ((unsign32)b[0]<<24)|((unsign32)b[1]<<16)|((unsign32)b[2]<<8)|(unsign32)b[3];
+}
+
+static void unpack(unsign32 a,uchar *b)
+{
+    /* unpack bytes from a word */
+    b[3]=MR_TOBYTE(a);
+    b[2]=MR_TOBYTE(a>>8);
+    b[1]=MR_TOBYTE(a>>16);
+    b[0]=MR_TOBYTE(a>>24);
+}
+
+static void precompute(gcm *g,uchar *H)
+{
+    /* precompute small 2k bytes gf2m table of x^n.H */
+    int i,j;
+    unsign32 *last,*next,b;
+
+    for (i=j=0; i<NB; i++,j+=4) g->table[0][i]=pack((uchar *)&H[j]);
+
+    for (i=1; i<128; i++)
+    {
+        next=g->table[i];
+        last=g->table[i-1];
+        b=0;
+        for (j=0; j<NB; j++)
+        {
+            next[j]=b|(last[j])>>1;
+            b=last[j]<<31;
+        }
+        if (b) next[0]^=0xE1000000; /* irreducible polynomial */
+    }
+}
+
+/* SU= 32 */
+static void gf2mul(gcm *g)
+{
+    /* gf2m mul - Z=H*X mod 2^128 */
+    int i,j,m,k;
+    unsign32 P[4];
+    unsign32 b;
+
+    P[0]=P[1]=P[2]=P[3]=0;
+    j=8;
+    m=0;
+    for (i=0; i<128; i++)
+    {
+        b=(unsign32)(g->stateX[m]>>(--j))&1;
+        b=~b+1;
+        for (k=0; k<NB; k++) P[k]^=(g->table[i][k]&b);
+        if (j==0)
+        {
+            j=8;
+            m++;
+            if (m==16) break;
+        }
+    }
+    for (i=j=0; i<NB; i++,j+=4) unpack(P[i],(uchar *)&g->stateX[j]);
+}
+
+/* SU= 32 */
+static void GCM_wrap(gcm *g)
+{
+    /* Finish off GHASH */
+    int i,j;
+    unsign32 F[4];
+    uchar L[16];
+
+    /* convert lengths from bytes to bits */
+    F[0]=(g->lenA[0]<<3)|(g->lenA[1]&0xE0000000)>>29;
+    F[1]=g->lenA[1]<<3;
+    F[2]=(g->lenC[0]<<3)|(g->lenC[1]&0xE0000000)>>29;
+    F[3]=g->lenC[1]<<3;
+    for (i=j=0; i<NB; i++,j+=4) unpack(F[i],(uchar *)&L[j]);
+
+    for (i=0; i<16; i++) g->stateX[i]^=L[i];
+    gf2mul(g);
+}
+
+static int GCM_ghash(gcm *g,char *plain,int len)
+{
+    int i,j=0;
+    if (g->status==GCM_ACCEPTING_HEADER) g->status=GCM_ACCEPTING_CIPHER;
+    if (g->status!=GCM_ACCEPTING_CIPHER) return 0;
+
+    while (j<len)
+    {
+        for (i=0; i<16 && j<len; i++)
+        {
+            g->stateX[i]^=plain[j++];
+            g->lenC[1]++;
+            if (g->lenC[1]==0) g->lenC[0]++;
+        }
+        gf2mul(g);
+    }
+    if (len%16!=0) g->status=GCM_NOT_ACCEPTING_MORE;
+    return 1;
+}
+
+/* SU= 48 */
+/* Initialize GCM mode */
+void GCM_init(gcm* g,int nk,char *key,int niv,char *iv)
+{
+    /* iv size niv is usually 12 bytes (96 bits). AES key size nk can be 16,24 or 32 bytes */
+    int i;
+    uchar H[16];
+    for (i=0; i<16; i++)
+    {
+        H[i]=0;
+        g->stateX[i]=0;
+    }
+
+    AES_init(&(g->a),ECB,nk,key,iv);
+    AES_ecb_encrypt(&(g->a),H);     /* E(K,0) */
+    precompute(g,H);
+
+    g->lenA[0]=g->lenC[0]=g->lenA[1]=g->lenC[1]=0;
+    if (niv==12)
+    {
+        for (i=0; i<12; i++) g->a.f[i]=iv[i];
+        unpack((unsign32)1,(uchar *)&(g->a.f[12]));  /* initialise IV */
+        for (i=0; i<16; i++) g->Y_0[i]=g->a.f[i];
+    }
+    else
+    {
+        g->status=GCM_ACCEPTING_CIPHER;
+        GCM_ghash(g,iv,niv); /* GHASH(H,0,IV) */
+        GCM_wrap(g);
+        for (i=0; i<16; i++)
+        {
+            g->a.f[i]=g->stateX[i];
+            g->Y_0[i]=g->a.f[i];
+            g->stateX[i]=0;
+        }
+        g->lenA[0]=g->lenC[0]=g->lenA[1]=g->lenC[1]=0;
+    }
+    g->status=GCM_ACCEPTING_HEADER;
+}
+
+/* SU= 24 */
+/* Add Header data - included but not encrypted */
+int GCM_add_header(gcm* g,char *header,int len)
+{
+    /* Add some header. Won't be encrypted, but will be authenticated. len is length of header */
+    int i,j=0;
+    if (g->status!=GCM_ACCEPTING_HEADER) return 0;
+
+    while (j<len)
+    {
+        for (i=0; i<16 && j<len; i++)
+        {
+            g->stateX[i]^=header[j++];
+            g->lenA[1]++;
+            if (g->lenA[1]==0) g->lenA[0]++;
+        }
+        gf2mul(g);
+    }
+    if (len%16!=0) g->status=GCM_ACCEPTING_CIPHER;
+    return 1;
+}
+
+/* SU= 48 */
+/* Add Plaintext - included and encrypted */
+int GCM_add_plain(gcm *g,char *cipher,char *plain,int len)
+{
+    /* Add plaintext to extract ciphertext, len is length of plaintext.  */
+    int i,j=0;
+    unsign32 counter;
+    uchar B[16];
+    if (g->status==GCM_ACCEPTING_HEADER) g->status=GCM_ACCEPTING_CIPHER;
+    if (g->status!=GCM_ACCEPTING_CIPHER) return 0;
+
+    while (j<len)
+    {
+        counter=pack((uchar *)&(g->a.f[12]));
+        counter++;
+        unpack(counter,(uchar *)&(g->a.f[12]));  /* increment counter */
+        for (i=0; i<16; i++) B[i]=g->a.f[i];
+        AES_ecb_encrypt(&(g->a),B);        /* encrypt it  */
+
+        for (i=0; i<16 && j<len; i++)
+        {
+            cipher[j]=plain[j]^B[i];
+            g->stateX[i]^=cipher[j++];
+            g->lenC[1]++;
+            if (g->lenC[1]==0) g->lenC[0]++;
+        }
+        gf2mul(g);
+    }
+    if (len%16!=0) g->status=GCM_NOT_ACCEPTING_MORE;
+    return 1;
+}
+
+/* SU= 48 */
+/* Add Ciphertext - decrypts to plaintext */
+int GCM_add_cipher(gcm *g,char *plain,char *cipher,int len)
+{
+    /* Add ciphertext to extract plaintext, len is length of ciphertext. */
+    int i,j=0;
+    unsign32 counter;
+    char oc;
+    uchar B[16];
+    if (g->status==GCM_ACCEPTING_HEADER) g->status=GCM_ACCEPTING_CIPHER;
+    if (g->status!=GCM_ACCEPTING_CIPHER) return 0;
+
+    while (j<len)
+    {
+        counter=pack((uchar *)&(g->a.f[12]));
+        counter++;
+        unpack(counter,(uchar *)&(g->a.f[12]));  /* increment counter */
+        for (i=0; i<16; i++) B[i]=g->a.f[i];
+        AES_ecb_encrypt(&(g->a),B);        /* encrypt it  */
+        for (i=0; i<16 && j<len; i++)
+        {
+            oc=cipher[j];
+            plain[j]=cipher[j]^B[i];
+            g->stateX[i]^=oc;
+            j++;
+            g->lenC[1]++;
+            if (g->lenC[1]==0) g->lenC[0]++;
+        }
+        gf2mul(g);
+    }
+    if (len%16!=0) g->status=GCM_NOT_ACCEPTING_MORE;
+    return 1;
+}
+
+/* SU= 16 */
+/* Finish and extract Tag */
+void GCM_finish(gcm *g,char *tag)
+{
+    /* Finish off GHASH and extract tag (MAC) */
+    int i;
+
+    GCM_wrap(g);
+
+    /* extract tag */
+    if (tag!=NULL)
+    {
+        AES_ecb_encrypt(&(g->a),g->Y_0);        /* E(K,Y0) */
+        for (i=0; i<16; i++) g->Y_0[i]^=g->stateX[i];
+        for (i=0; i<16; i++)
+        {
+            tag[i]=g->Y_0[i];
+            g->Y_0[i]=g->stateX[i]=0;
+        }
+    }
+    g->status=GCM_FINISHED;
+    AES_end(&(g->a));
+}
+
+
+// Compile with
+// gcc -O2 gcm.c aes.c -o gcm.exe
+/* SU= 16
+*/
+
+/* static void hex2bytes(char *hex,char *bin) */
+/* { */
+/* 	int i; */
+/* 	char v; */
+/* 	int len=strlen(hex); */
+/* 	for (i = 0; i < len/2; i++) { */
+/*         char c = hex[2*i]; */
+/*         if (c >= '0' && c <= '9') { */
+/*             v = c - '0'; */
+/*         } else if (c >= 'A' && c <= 'F') { */
+/*             v = c - 'A' + 10; */
+/*         } else if (c >= 'a' && c <= 'f') { */
+/*             v = c - 'a' + 10; */
+/*         } else { */
+/*             v = 0; */
+/*         } */
+/*         v <<= 4; */
+/*         c = hex[2*i + 1]; */
+/*         if (c >= '0' && c <= '9') { */
+/*             v += c - '0'; */
+/*         } else if (c >= 'A' && c <= 'F') { */
+/*             v += c - 'A' + 10; */
+/*         } else if (c >= 'a' && c <= 'f') { */
+/*             v += c - 'a' + 10; */
+/*         } else { */
+/*             v = 0; */
+/*         } */
+/*         bin[i] = v; */
+/*     } */
+/* } */
+
+/*
+int main()
+{
+	int i;
+
+//	char* KT="feffe9928665731c6d6a8f9467308308";
+//	char* MT="d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39";
+//	char* HT="feedfacedeadbeeffeedfacedeadbeefabaddad2";
+//	char* NT="cafebabefacedbaddecaf888";
+// Tag should be 5bc94fbc3221a5db94fae95ae7121a47
+//	char* NT="9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b";
+// Tag should be 619cc5aefffe0bfa462af43c1699d050
+
+  char* KT="6dfb5dc68af6ae2f3242e9184f100918";
+  char* MT="47809d16c2c6ec685962c90e53fe1bba";
+  char* HT="dd0fa6e494031139d71ee45f00d56fa4";
+  char* NT="37d36f5c54d53479d4745dd1";
+
+
+	int len=strlen(MT)/2;
+	int lenH=strlen(HT)/2;
+	int lenK=strlen(KT)/2;
+	int lenIV=strlen(NT)/2;
+
+	char T[16];   // Tag
+	char K[16];   // AES Key
+	char H[64];   // Header - to be included in Authentication, but not encrypted
+	char N[100];   // IV - Initialisation vector
+	char M[100];  // Plaintext to be encrypted/authenticated
+	char C[100];  // Ciphertext
+	char P[100];  // Recovered Plaintext
+
+	gcm g;
+
+    hex2bytes(MT, M);
+    hex2bytes(HT, H);
+    hex2bytes(NT, N);
+	hex2bytes(KT, K);
+
+	printf("lenK= %d\n",lenK);
+
+ 	printf("Plaintext=\n");
+	for (i=0;i<len;i++) printf("%02x",(unsigned char)M[i]);
+	printf("\n");
+
+	GCM_init(&g,16,K,lenIV,N);
+	GCM_add_header(&g,H,lenH);
+	GCM_add_plain(&g,C,M,len);
+	GCM_finish(&g,T);
+
+	printf("Ciphertext=\n");
+	for (i=0;i<len;i++) printf("%02x",(unsigned char)C[i]);
+	printf("\n");
+
+	printf("Tag=\n");
+	for (i=0;i<16;i++) printf("%02x",(unsigned char)T[i]);
+	printf("\n");
+
+	GCM_init(&g,16,K,lenIV,N);
+	GCM_add_header(&g,H,lenH);
+	GCM_add_cipher(&g,P,C,len);
+	GCM_finish(&g,T);
+
+ 	printf("Plaintext=\n");
+	for (i=0;i<len;i++) printf("%02x",(unsigned char)P[i]);
+	printf("\n");
+
+	printf("Tag=\n");
+	for (i=0;i<16;i++) printf("%02x",(unsigned char)T[i]);
+	printf("\n");
+}
+
+*/
diff --git a/version3/c/hash.c b/version3/c/hash.c
new file mode 100644
index 0000000..b56123e
--- /dev/null
+++ b/version3/c/hash.c
@@ -0,0 +1,607 @@
+/*
+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.
+*/
+
+/*
+ * Implementation of the Secure Hashing Algorithm (SHA-256/384/512 and SHA3)
+ *
+ * Generates a message digest. It should be impossible to come
+ * come up with two messages that hash to the same value ("collision free").
+ *
+ * For use with byte-oriented messages only. Could/Should be speeded
+ * up by unwinding loops in HASH_transform(), and assembly patches.
+ */
+
+#include "arch.h"
+#include "amcl.h"
+
+
+#define H0_256 0x6A09E667L
+#define H1_256 0xBB67AE85L
+#define H2_256 0x3C6EF372L
+#define H3_256 0xA54FF53AL
+#define H4_256 0x510E527FL
+#define H5_256 0x9B05688CL
+#define H6_256 0x1F83D9ABL
+#define H7_256 0x5BE0CD19L
+
+static const unsign32 K_256[64]=
+{
+    0x428a2f98L,0x71374491L,0xb5c0fbcfL,0xe9b5dba5L,0x3956c25bL,0x59f111f1L,0x923f82a4L,0xab1c5ed5L,
+    0xd807aa98L,0x12835b01L,0x243185beL,0x550c7dc3L,0x72be5d74L,0x80deb1feL,0x9bdc06a7L,0xc19bf174L,
+    0xe49b69c1L,0xefbe4786L,0x0fc19dc6L,0x240ca1ccL,0x2de92c6fL,0x4a7484aaL,0x5cb0a9dcL,0x76f988daL,
+    0x983e5152L,0xa831c66dL,0xb00327c8L,0xbf597fc7L,0xc6e00bf3L,0xd5a79147L,0x06ca6351L,0x14292967L,
+    0x27b70a85L,0x2e1b2138L,0x4d2c6dfcL,0x53380d13L,0x650a7354L,0x766a0abbL,0x81c2c92eL,0x92722c85L,
+    0xa2bfe8a1L,0xa81a664bL,0xc24b8b70L,0xc76c51a3L,0xd192e819L,0xd6990624L,0xf40e3585L,0x106aa070L,
+    0x19a4c116L,0x1e376c08L,0x2748774cL,0x34b0bcb5L,0x391c0cb3L,0x4ed8aa4aL,0x5b9cca4fL,0x682e6ff3L,
+    0x748f82eeL,0x78a5636fL,0x84c87814L,0x8cc70208L,0x90befffaL,0xa4506cebL,0xbef9a3f7L,0xc67178f2L
+};
+
+#define PAD  0x80
+#define ZERO 0
+
+/* functions */
+
+#define S(m,n,x) (((x)>>n) | ((x)<<(m-n)))
+#define R(n,x) ((x)>>n)
+
+#define Ch(x,y,z)  ((x&y)^(~(x)&z))
+#define Maj(x,y,z) ((x&y)^(x&z)^(y&z))
+#define Sig0_256(x)    (S(32,2,x)^S(32,13,x)^S(32,22,x))
+#define Sig1_256(x)    (S(32,6,x)^S(32,11,x)^S(32,25,x))
+#define theta0_256(x)  (S(32,7,x)^S(32,18,x)^R(3,x))
+#define theta1_256(x)  (S(32,17,x)^S(32,19,x)^R(10,x))
+
+#define Sig0_512(x)    (S(64,28,x)^S(64,34,x)^S(64,39,x))
+#define Sig1_512(x)    (S(64,14,x)^S(64,18,x)^S(64,41,x))
+#define theta0_512(x)  (S(64,1,x)^S(64,8,x)^R(7,x))
+#define theta1_512(x)  (S(64,19,x)^S(64,61,x)^R(6,x))
+
+
+/* SU= 72 */
+static void HASH256_transform(hash256 *sh)
+{
+    /* basic transformation step */
+    unsign32 a,b,c,d,e,f,g,h,t1,t2;
+    int j;
+    for (j=16; j<64; j++)
+        sh->w[j]=theta1_256(sh->w[j-2])+sh->w[j-7]+theta0_256(sh->w[j-15])+sh->w[j-16];
+
+    a=sh->h[0];
+    b=sh->h[1];
+    c=sh->h[2];
+    d=sh->h[3];
+    e=sh->h[4];
+    f=sh->h[5];
+    g=sh->h[6];
+    h=sh->h[7];
+
+    for (j=0; j<64; j++)
+    {
+        /* 64 times - mush it up */
+        t1=h+Sig1_256(e)+Ch(e,f,g)+K_256[j]+sh->w[j];
+        t2=Sig0_256(a)+Maj(a,b,c);
+        h=g;
+        g=f;
+        f=e;
+        e=d+t1;
+        d=c;
+        c=b;
+        b=a;
+        a=t1+t2;
+    }
+
+    sh->h[0]+=a;
+    sh->h[1]+=b;
+    sh->h[2]+=c;
+    sh->h[3]+=d;
+    sh->h[4]+=e;
+    sh->h[5]+=f;
+    sh->h[6]+=g;
+    sh->h[7]+=h;
+}
+
+/* Initialise Hash function */
+void HASH256_init(hash256 *sh)
+{
+    /* re-initialise */
+    int i;
+    for (i=0; i<64; i++) sh->w[i]=0L;
+    sh->length[0]=sh->length[1]=0L;
+    sh->h[0]=H0_256;
+    sh->h[1]=H1_256;
+    sh->h[2]=H2_256;
+    sh->h[3]=H3_256;
+    sh->h[4]=H4_256;
+    sh->h[5]=H5_256;
+    sh->h[6]=H6_256;
+    sh->h[7]=H7_256;
+
+    sh->hlen=32;
+}
+
+/* process a single byte */
+void HASH256_process(hash256 *sh,int byt)
+{
+    /* process the next message byte */
+    int cnt;
+//printf("byte= %x\n",byt);
+    cnt=(int)((sh->length[0]/32)%16);
+
+    sh->w[cnt]<<=8;
+    sh->w[cnt]|=(unsign32)(byt&0xFF);
+
+    sh->length[0]+=8;
+    if (sh->length[0]==0L)
+    {
+        sh->length[1]++;
+        sh->length[0]=0L;
+    }
+    if ((sh->length[0]%512)==0) HASH256_transform(sh);
+}
+
+/* SU= 24 */
+/* Generate 32-byte Hash */
+void HASH256_hash(hash256 *sh,char *digest)
+{
+    /* pad message and finish - supply digest */
+    int i;
+    unsign32 len0,len1;
+    len0=sh->length[0];
+    len1=sh->length[1];
+    HASH256_process(sh,PAD);
+    while ((sh->length[0]%512)!=448) HASH256_process(sh,ZERO);
+    sh->w[14]=len1;
+    sh->w[15]=len0;
+    HASH256_transform(sh);
+    for (i=0; i<sh->hlen; i++)
+    {
+        /* convert to bytes */
+        digest[i]=(char)((sh->h[i/4]>>(8*(3-i%4))) & 0xffL);
+    }
+    HASH256_init(sh);
+}
+
+
+#define H0_512 0x6a09e667f3bcc908
+#define H1_512 0xbb67ae8584caa73b
+#define H2_512 0x3c6ef372fe94f82b
+#define H3_512 0xa54ff53a5f1d36f1
+#define H4_512 0x510e527fade682d1
+#define H5_512 0x9b05688c2b3e6c1f
+#define H6_512 0x1f83d9abfb41bd6b
+#define H7_512 0x5be0cd19137e2179
+
+#define H8_512 0xcbbb9d5dc1059ed8
+#define H9_512 0x629a292a367cd507
+#define HA_512 0x9159015a3070dd17
+#define HB_512 0x152fecd8f70e5939
+#define HC_512 0x67332667ffc00b31
+#define HD_512 0x8eb44a8768581511
+#define HE_512 0xdb0c2e0d64f98fa7
+#define HF_512 0x47b5481dbefa4fa4
+
+/* */
+
+static const unsign64 K_512[80]=
+{
+    0x428a2f98d728ae22,0x7137449123ef65cd,0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc,
+    0x3956c25bf348b538,0x59f111f1b605d019,0x923f82a4af194f9b,0xab1c5ed5da6d8118,
+    0xd807aa98a3030242,0x12835b0145706fbe,0x243185be4ee4b28c,0x550c7dc3d5ffb4e2,
+    0x72be5d74f27b896f,0x80deb1fe3b1696b1,0x9bdc06a725c71235,0xc19bf174cf692694,
+    0xe49b69c19ef14ad2,0xefbe4786384f25e3,0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65,
+    0x2de92c6f592b0275,0x4a7484aa6ea6e483,0x5cb0a9dcbd41fbd4,0x76f988da831153b5,
+    0x983e5152ee66dfab,0xa831c66d2db43210,0xb00327c898fb213f,0xbf597fc7beef0ee4,
+    0xc6e00bf33da88fc2,0xd5a79147930aa725,0x06ca6351e003826f,0x142929670a0e6e70,
+    0x27b70a8546d22ffc,0x2e1b21385c26c926,0x4d2c6dfc5ac42aed,0x53380d139d95b3df,
+    0x650a73548baf63de,0x766a0abb3c77b2a8,0x81c2c92e47edaee6,0x92722c851482353b,
+    0xa2bfe8a14cf10364,0xa81a664bbc423001,0xc24b8b70d0f89791,0xc76c51a30654be30,
+    0xd192e819d6ef5218,0xd69906245565a910,0xf40e35855771202a,0x106aa07032bbd1b8,
+    0x19a4c116b8d2d0c8,0x1e376c085141ab53,0x2748774cdf8eeb99,0x34b0bcb5e19b48a8,
+    0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb,0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3,
+    0x748f82ee5defb2fc,0x78a5636f43172f60,0x84c87814a1f0ab72,0x8cc702081a6439ec,
+    0x90befffa23631e28,0xa4506cebde82bde9,0xbef9a3f7b2c67915,0xc67178f2e372532b,
+    0xca273eceea26619c,0xd186b8c721c0c207,0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178,
+    0x06f067aa72176fba,0x0a637dc5a2c898a6,0x113f9804bef90dae,0x1b710b35131c471b,
+    0x28db77f523047d84,0x32caab7b40c72493,0x3c9ebe0a15c9bebc,0x431d67c49c100d4c,
+    0x4cc5d4becb3e42b6,0x597f299cfc657e2a,0x5fcb6fab3ad6faec,0x6c44198c4a475817
+};
+
+
+static void HASH512_transform(hash512 *sh)
+{
+    /* basic transformation step */
+    unsign64 a,b,c,d,e,f,g,h,t1,t2;
+    int j;
+    for (j=16; j<80; j++)
+        sh->w[j]=theta1_512(sh->w[j-2])+sh->w[j-7]+theta0_512(sh->w[j-15])+sh->w[j-16];
+
+    a=sh->h[0];
+    b=sh->h[1];
+    c=sh->h[2];
+    d=sh->h[3];
+    e=sh->h[4];
+    f=sh->h[5];
+    g=sh->h[6];
+    h=sh->h[7];
+
+    for (j=0; j<80; j++)
+    {
+        /* 80 times - mush it up */
+        t1=h+Sig1_512(e)+Ch(e,f,g)+K_512[j]+sh->w[j];
+        t2=Sig0_512(a)+Maj(a,b,c);
+        h=g;
+        g=f;
+        f=e;
+        e=d+t1;
+        d=c;
+        c=b;
+        b=a;
+        a=t1+t2;
+    }
+    sh->h[0]+=a;
+    sh->h[1]+=b;
+    sh->h[2]+=c;
+    sh->h[3]+=d;
+    sh->h[4]+=e;
+    sh->h[5]+=f;
+    sh->h[6]+=g;
+    sh->h[7]+=h;
+}
+
+void HASH384_init(hash384 *sh)
+{
+    /* re-initialise */
+    int i;
+    for (i=0; i<80; i++) sh->w[i]=0;
+    sh->length[0]=sh->length[1]=0;
+    sh->h[0]=H8_512;
+    sh->h[1]=H9_512;
+    sh->h[2]=HA_512;
+    sh->h[3]=HB_512;
+    sh->h[4]=HC_512;
+    sh->h[5]=HD_512;
+    sh->h[6]=HE_512;
+    sh->h[7]=HF_512;
+
+    sh->hlen=48;
+
+}
+
+void HASH384_process(hash384 *sh,int byt)
+{
+    /* process the next message byte */
+    HASH512_process(sh,byt);
+}
+
+void HASH384_hash(hash384 *sh,char *hash)
+{
+    /* pad message and finish - supply digest */
+    HASH512_hash(sh,hash);
+}
+
+void HASH512_init(hash512 *sh)
+{
+    /* re-initialise */
+    int i;
+
+    for (i=0; i<80; i++) sh->w[i]=0;
+    sh->length[0]=sh->length[1]=0;
+    sh->h[0]=H0_512;
+    sh->h[1]=H1_512;
+    sh->h[2]=H2_512;
+    sh->h[3]=H3_512;
+    sh->h[4]=H4_512;
+    sh->h[5]=H5_512;
+    sh->h[6]=H6_512;
+    sh->h[7]=H7_512;
+
+    sh->hlen=64;
+}
+
+void HASH512_process(hash512 *sh,int byt)
+{
+    /* process the next message byte */
+    int cnt;
+
+    cnt=(int)((sh->length[0]/64)%16);
+
+    sh->w[cnt]<<=8;
+    sh->w[cnt]|=(unsign64)(byt&0xFF);
+
+    sh->length[0]+=8;
+    if (sh->length[0]==0L)
+    {
+        sh->length[1]++;
+        sh->length[0]=0L;
+    }
+    if ((sh->length[0]%1024)==0) HASH512_transform(sh);
+}
+
+void HASH512_hash(hash512 *sh,char *hash)
+{
+    /* pad message and finish - supply digest */
+    int i;
+    unsign64 len0,len1;
+    len0=sh->length[0];
+    len1=sh->length[1];
+    HASH512_process(sh,PAD);
+    while ((sh->length[0]%1024)!=896) HASH512_process(sh,ZERO);
+    sh->w[14]=len1;
+    sh->w[15]=len0;
+    HASH512_transform(sh);
+    for (i=0; i<sh->hlen; i++)
+    {
+        /* convert to bytes */
+        hash[i]=(char)((sh->h[i/8]>>(8*(7-i%8))) & 0xffL);
+    }
+    HASH512_init(sh);
+}
+
+
+
+/* SHA3 */
+
+#define SHA3_ROUNDS 24
+#define rotl(x,n) (((x)<<n) | ((x)>>(64-n)))
+
+/* round constants */
+
+static const unsign64 RC[24]=
+{
+    0x0000000000000001UL,0x0000000000008082UL,0x800000000000808AUL,0x8000000080008000UL,
+    0x000000000000808BUL,0x0000000080000001UL,0x8000000080008081UL,0x8000000000008009UL,
+    0x000000000000008AUL,0x0000000000000088UL,0x0000000080008009UL,0x000000008000000AUL,
+    0x000000008000808BUL,0x800000000000008BUL,0x8000000000008089UL,0x8000000000008003UL,
+    0x8000000000008002UL,0x8000000000000080UL,0x000000000000800AUL,0x800000008000000AUL,
+    0x8000000080008081UL,0x8000000000008080UL,0x0000000080000001UL,0x8000000080008008UL
+};
+
+/* permutation */
+
+static void SHA3_transform(sha3 *sh)
+{
+    int i,j,k;
+    unsign64 C[5],D[5],B[5][5];
+
+    for (k=0; k<SHA3_ROUNDS; k++)
+    {
+        C[0]=sh->S[0][0]^sh->S[0][1]^sh->S[0][2]^sh->S[0][3]^sh->S[0][4];
+        C[1]=sh->S[1][0]^sh->S[1][1]^sh->S[1][2]^sh->S[1][3]^sh->S[1][4];
+        C[2]=sh->S[2][0]^sh->S[2][1]^sh->S[2][2]^sh->S[2][3]^sh->S[2][4];
+        C[3]=sh->S[3][0]^sh->S[3][1]^sh->S[3][2]^sh->S[3][3]^sh->S[3][4];
+        C[4]=sh->S[4][0]^sh->S[4][1]^sh->S[4][2]^sh->S[4][3]^sh->S[4][4];
+
+        D[0]=C[4]^rotl(C[1],1);
+        D[1]=C[0]^rotl(C[2],1);
+        D[2]=C[1]^rotl(C[3],1);
+        D[3]=C[2]^rotl(C[4],1);
+        D[4]=C[3]^rotl(C[0],1);
+
+        for (i=0; i<5; i++)
+            for (j=0; j<5; j++)
+                sh->S[i][j]^=D[i];  /* let the compiler unroll it! */
+
+        B[0][0]=sh->S[0][0];
+        B[1][3]=rotl(sh->S[0][1],36);
+        B[2][1]=rotl(sh->S[0][2],3);
+        B[3][4]=rotl(sh->S[0][3],41);
+        B[4][2]=rotl(sh->S[0][4],18);
+
+        B[0][2]=rotl(sh->S[1][0],1);
+        B[1][0]=rotl(sh->S[1][1],44);
+        B[2][3]=rotl(sh->S[1][2],10);
+        B[3][1]=rotl(sh->S[1][3],45);
+        B[4][4]=rotl(sh->S[1][4],2);
+
+        B[0][4]=rotl(sh->S[2][0],62);
+        B[1][2]=rotl(sh->S[2][1],6);
+        B[2][0]=rotl(sh->S[2][2],43);
+        B[3][3]=rotl(sh->S[2][3],15);
+        B[4][1]=rotl(sh->S[2][4],61);
+
+        B[0][1]=rotl(sh->S[3][0],28);
+        B[1][4]=rotl(sh->S[3][1],55);
+        B[2][2]=rotl(sh->S[3][2],25);
+        B[3][0]=rotl(sh->S[3][3],21);
+        B[4][3]=rotl(sh->S[3][4],56);
+
+        B[0][3]=rotl(sh->S[4][0],27);
+        B[1][1]=rotl(sh->S[4][1],20);
+        B[2][4]=rotl(sh->S[4][2],39);
+        B[3][2]=rotl(sh->S[4][3],8);
+        B[4][0]=rotl(sh->S[4][4],14);
+
+        for (i=0; i<5; i++)
+            for (j=0; j<5; j++)
+                sh->S[i][j]=B[i][j]^(~B[(i+1)%5][j]&B[(i+2)%5][j]);
+
+        sh->S[0][0]^=RC[k];
+    }
+}
+
+/* Re-Initialize. olen is output length in bytes -
+   should be 28, 32, 48 or 64 (224, 256, 384, 512 bits resp.) */
+
+void SHA3_init(sha3 *sh,int olen)
+{
+    int i,j;
+    for (i=0; i<5; i++)
+        for (j=0; j<5; j++)
+            sh->S[i][j]=0;    /* 5x5x8 bytes = 200 bytes of state */
+    sh->length=0;
+    sh->len=olen;
+    sh->rate=200-2*olen; /* number of bytes consumed in one gulp. Note that some bytes in the
+	                        state ("capacity") are not touched. Gulps are smaller for larger digests.
+							Important that olen<rate */
+}
+
+/* process a single byte */
+void SHA3_process(sha3 *sh,int byt)
+{
+    int cnt=(int)(sh->length%sh->rate);
+    int i,j,b=cnt%8;
+    cnt/=8;
+    i=cnt%5;
+    j=cnt/5;  /* process by columns! */
+    sh->S[i][j]^=((unsign64)byt<<(8*b));
+    sh->length++;
+    if (sh->length%sh->rate==0) SHA3_transform(sh);
+}
+
+/* squeeze the sponge */
+void SHA3_squeeze(sha3 *sh,char *buff,int len)
+{
+    int done,i,j,k,m=0;
+    unsign64 el;
+    /* extract by columns */
+    done=0;
+    for (;;)
+    {
+        for (j=0; j<5; j++)
+        {
+            for (i=0; i<5; i++)
+            {
+                el=sh->S[i][j];
+                for (k=0; k<8; k++)
+                {
+                    buff[m++]=(el&0xff);
+                    if (m>=len || m%sh->rate==0)
+                    {
+                        done=1;
+                        break;
+                    }
+                    el>>=8;
+                }
+                if (done) break;
+            }
+            if (done) break;
+        }
+        if (m>=len) break;
+        done=0;
+        SHA3_transform(sh);
+    }
+}
+
+void SHA3_hash(sha3 *sh,char *hash)
+{
+    /* generate a SHA3 hash of appropriate size */
+    int q=sh->rate-(sh->length%sh->rate);
+    if (q==1) SHA3_process(sh,0x86);
+    else
+    {
+        SHA3_process(sh,0x06);   /* 0x06 for SHA-3 */
+        while ((int)sh->length%sh->rate!=sh->rate-1) SHA3_process(sh,0x00);
+        SHA3_process(sh,0x80); /* this will force a final transform */
+    }
+    SHA3_squeeze(sh,hash,sh->len);
+}
+
+void SHA3_shake(sha3 *sh,char *buff,int len)
+{
+    /* SHAKE out a buffer of variable length len */
+    int q=sh->rate-(sh->length%sh->rate);
+    if (q==1) SHA3_process(sh,0x9f);
+    else
+    {
+        SHA3_process(sh,0x1f);   // 0x06 for SHA-3 !!!!
+        while ((int) sh->length%sh->rate!=sh->rate-1) SHA3_process(sh,0x00);
+        SHA3_process(sh,0x80); /* this will force a final transform */
+    }
+    SHA3_squeeze(sh,buff,len);
+}
+
+
+/* test program: should produce digest
+
+160 bit
+
+84983e44 1c3bd26e baae4aa1 f95129e5 e54670f1
+
+256 bit
+
+248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1
+
+512 bit
+
+8e959b75dae313da 8cf4f72814fc143f 8f7779c6eb9f7fa1 7299aeadb6889018
+501d289e4900f7e4 331b99dec4b5433a c7d329eeb6dd2654 5e96e55b874be909
+
+384 bit
+
+09330c33f71147e8 3d192fc782cd1b47 53111b173b3b05d2 2fa08086e3b0f712
+fcc7c71a557e2db9 66c3e9fa91746039
+*/
+/*
+#include <stdio.h>
+
+char test160[]="abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
+char test256[]="abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
+char test512[]="abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu";
+
+int main()
+{
+    char digest[100];
+    int i;
+
+    hash256 sh256;
+	hash384 sh384;
+	hash512 sh512;
+	sha3 SHA3;
+
+    HASH256_init(&sh256);
+    for (i=0;test256[i]!=0;i++) HASH256_process(&sh256,test256[i]);
+    HASH256_hash(&sh256,digest);
+    for (i=0;i<32;i++) printf("%02x",(unsigned char)digest[i]);
+    printf("\n");
+
+    HASH384_init(&sh384);
+    for (i=0;test512[i]!=0;i++) HASH384_process(&sh384,test512[i]);
+    HASH384_hash(&sh384,digest);
+    for (i=0;i<48;i++) printf("%02x",(unsigned char)digest[i]);
+    printf("\n");
+
+    HASH512_init(&sh512);
+    for (i=0;test512[i]!=0;i++) HASH512_process(&sh512,test512[i]);
+    HASH512_hash(&sh512,digest);
+    for (i=0;i<64;i++) printf("%02x",(unsigned char)digest[i]);
+    printf("\n");
+
+	SHA3_init(&SHA3,SHA3_HASH256);
+    for (i=0;test512[i]!=0;i++) SHA3_process(&SHA3,test512[i]);
+    SHA3_hash(&sh512,digest);
+    for (i=0;i<32;i++) printf("%02x",(unsigned char)digest[i]);
+    printf("\n");
+
+	SHA3_init(&SHA3,SHA3_HASH512);
+    for (i=0;test512[i]!=0;i++) SHA3_process(&SHA3,test512[i]);
+    SHA3_hash(&sh512,digest);
+    for (i=0;i<64;i++) printf("%02x",(unsigned char)digest[i]);
+    printf("\n");
+
+	SHA3_init(&SHA3,SHAKE256);
+    for (i=0;test512[i]!=0;i++) SHA3_process(&SHA3,test512[i]);
+    SHA3_shake(&sh512,digest,72);
+    for (i=0;i<72;i++) printf("%02x",(unsigned char)digest[i]);
+    printf("\n");
+
+
+    return 0;
+}
+
+*/
diff --git a/version3/c/mpin.c b/version3/c/mpin.c
new file mode 100644
index 0000000..cb6c04f
--- /dev/null
+++ b/version3/c/mpin.c
@@ -0,0 +1,995 @@
+/*
+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.
+*/
+
+/* MPIN Functions */
+
+/* Version 3.0 - supports Time Permits */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "mpin_ZZZ.h"
+
+#define ROUNDUP(a,b) ((a)-1)/(b)+1
+
+/* Special mpin hashing */
+static void mpin_hash(int sha,FP4_YYY *f, ECP_ZZZ *P,octet *w)
+{
+    int i;
+    BIG_XXX x,y;
+    char h[64];
+    hash256 sha256;
+    hash512 sha512;
+    char t[6*MODBYTES_XXX];  // to hold 6 BIGs
+    int hlen=sha;
+
+
+    FP_YYY_redc(x,&(f->a.a));
+    BIG_XXX_toBytes(&t[0],x);
+    FP_YYY_redc(x,&(f->a.b));
+    BIG_XXX_toBytes(&t[MODBYTES_XXX],x);
+    FP_YYY_redc(x,&(f->b.a));
+    BIG_XXX_toBytes(&t[2*MODBYTES_XXX],x);
+    FP_YYY_redc(x,&(f->b.b));
+    BIG_XXX_toBytes(&t[3*MODBYTES_XXX],x);
+    ECP_ZZZ_get(x,y,P);
+    BIG_XXX_toBytes(&t[4*MODBYTES_XXX],x);
+    BIG_XXX_toBytes(&t[5*MODBYTES_XXX],y);
+
+    OCT_empty(w);
+    switch (sha)
+    {
+    case SHA256:
+        HASH256_init(&sha256);
+        for (i=0; i<6*MODBYTES_XXX; i++) HASH256_process(&sha256,t[i]);
+        HASH256_hash(&sha256,h);
+        break;
+    case SHA384:
+        HASH384_init(&sha512);
+        for (i=0; i<6*MODBYTES_XXX; i++) HASH384_process(&sha512,t[i]);
+        HASH384_hash(&sha512,h);
+        break;
+    case SHA512:
+        HASH512_init(&sha512);
+        for (i=0; i<6*MODBYTES_XXX; i++) HASH512_process(&sha512,t[i]);
+        HASH512_hash(&sha512,h);
+        break;
+    }
+
+    OCT_jbytes(w,h,AESKEY_ZZZ);
+    for (i=0; i<hlen; i++) h[i]=0;
+}
+
+/* these next two functions help to implement elligator squared - http://eprint.iacr.org/2014/043 */
+/* maps a random u to a point on the curve */
+static void map(ECP_ZZZ *P,BIG_XXX u,int cb)
+{
+    BIG_XXX x,q;
+
+    BIG_XXX_rcopy(q,Modulus_YYY);
+    BIG_XXX_copy(x,u);
+    BIG_XXX_mod(x,q);
+
+    while (!ECP_ZZZ_setx(P,x,cb))
+    {
+        BIG_XXX_inc(x,1);
+        BIG_XXX_norm(x);
+    }
+}
+
+/* returns u derived from P. Random value in range 1 to return value should then be added to u */
+static int unmap(BIG_XXX u,int *cb,ECP_ZZZ *P)
+{
+    int s,r=0;
+    BIG_XXX x;
+
+    s=ECP_ZZZ_get(x,x,P);
+    BIG_XXX_copy(u,x);
+    do
+    {
+        BIG_XXX_dec(u,1);
+        BIG_XXX_norm(u);
+        r++;
+    }
+    while (!ECP_ZZZ_setx(P,u,s));
+    ECP_ZZZ_setx(P,x,s);
+
+    *cb=s;
+
+    return r;
+}
+
+/* these next two functions implement elligator squared - http://eprint.iacr.org/2014/043 */
+/* Elliptic curve point E in format (0x04,x,y} is converted to form {0x0-,u,v} */
+/* Note that u and v are indistinguisible from random strings */
+int MPIN_ZZZ_ENCODING(csprng *RNG,octet *E)
+{
+    int rn,m,su,sv,res=0;
+
+    BIG_XXX q,u,v;
+    ECP_ZZZ P,W;
+
+    if (!ECP_ZZZ_fromOctet(&P,E)) res=MPIN_INVALID_POINT;
+    if (res==0)
+    {
+        BIG_XXX_rcopy(q,Modulus_YYY);
+
+        BIG_XXX_randomnum(u,q,RNG);
+
+        su=RAND_byte(RNG);
+        if (su<0) su=-su;
+        su%=2;
+        map(&W,u,su);
+        ECP_ZZZ_sub(&P,&W); //ECP_ZZZ_affine(&P);
+
+        rn=unmap(v,&sv,&P);
+        m=RAND_byte(RNG);
+        if (m<0) m=-m;
+        m%=rn;
+        BIG_XXX_inc(v,m+1);
+        E->val[0]=su+2*sv;
+        BIG_XXX_toBytes(&(E->val[1]),u);
+        BIG_XXX_toBytes(&(E->val[PFS_ZZZ+1]),v);
+    }
+    return res;
+}
+
+int MPIN_ZZZ_DECODING(octet *D)
+{
+    int su,sv;
+    BIG_XXX u,v;
+    ECP_ZZZ P,W;
+    int res=0;
+
+    if ((D->val[0]&0x04)!=0) res=MPIN_INVALID_POINT;
+    if (res==0)
+    {
+
+        BIG_XXX_fromBytes(u,&(D->val[1]));
+        BIG_XXX_fromBytes(v,&(D->val[PFS_ZZZ+1]));
+
+        su=D->val[0]&1;
+        sv=(D->val[0]>>1)&1;
+        map(&W,u,su);
+        map(&P,v,sv);
+        ECP_ZZZ_add(&P,&W); //ECP_ZZZ_affine(&P);
+        ECP_ZZZ_toOctet(D,&P,false);
+    }
+
+    return res;
+}
+
+/* R=R1+R2 in group G1 */
+int MPIN_ZZZ_RECOMBINE_G1(octet *R1,octet *R2,octet *R)
+{
+    ECP_ZZZ P,T;
+    int res=0;
+    if (res==0)
+    {
+        if (!ECP_ZZZ_fromOctet(&P,R1)) res=MPIN_INVALID_POINT;
+        if (!ECP_ZZZ_fromOctet(&T,R2)) res=MPIN_INVALID_POINT;
+    }
+    if (res==0)
+    {
+        ECP_ZZZ_add(&P,&T); //ECP_ZZZ_affine(&P);
+        ECP_ZZZ_toOctet(R,&P,false);
+    }
+    return res;
+}
+
+/* W=W1+W2 in group G2 */
+int MPIN_ZZZ_RECOMBINE_G2(octet *W1,octet *W2,octet *W)
+{
+    ECP2_ZZZ Q,T;
+    int res=0;
+    if (!ECP2_ZZZ_fromOctet(&Q,W1)) res=MPIN_INVALID_POINT;
+    if (!ECP2_ZZZ_fromOctet(&T,W2)) res=MPIN_INVALID_POINT;
+    if (res==0)
+    {
+        ECP2_ZZZ_add(&Q,&T); //ECP2_ZZZ_affine(&Q);
+        ECP2_ZZZ_toOctet(W,&Q);
+    }
+    return res;
+}
+
+/* create random secret S */
+int MPIN_ZZZ_RANDOM_GENERATE(csprng *RNG,octet* S)
+{
+    BIG_XXX r,s;
+
+    BIG_XXX_rcopy(r,CURVE_Order_ZZZ);
+    BIG_XXX_randomnum(s,r,RNG);
+#ifdef AES_S
+    BIG_XXX_mod2m(s,2*AES_S);
+#endif
+    BIG_XXX_toBytes(S->val,s);
+    S->len=MODBYTES_XXX;
+    return 0;
+}
+
+/* Extract PIN from TOKEN for identity CID */
+int MPIN_ZZZ_EXTRACT_PIN(int sha,octet *CID,int pin,octet *TOKEN)
+{
+    pin%=MAXPIN;
+    return MPIN_ZZZ_EXTRACT_FACTOR(sha,CID,pin,PBLEN,TOKEN);
+}
+
+/* Extract a factor < 32 bits for identity CID */
+int MPIN_ZZZ_EXTRACT_FACTOR(int sha,octet *CID,int factor,int facbits,octet *TOKEN)
+{
+    ECP_ZZZ P,R;
+    int res=0;
+    char h[MODBYTES_XXX];
+    octet H= {0,sizeof(h),h};
+
+    if (!ECP_ZZZ_fromOctet(&P,TOKEN))  res=MPIN_INVALID_POINT;
+    if (res==0)
+    {
+        mhashit(sha,-1,CID,&H);
+        ECP_ZZZ_mapit(&R,&H);
+
+        ECP_ZZZ_pinmul(&R,factor,facbits);
+        ECP_ZZZ_sub(&P,&R); //ECP_ZZZ_affine(&P);
+
+        ECP_ZZZ_toOctet(TOKEN,&P,false);
+    }
+    return res;
+}
+
+/* Extract a factor < 32 bits for identity CID */
+int MPIN_ZZZ_RESTORE_FACTOR(int sha,octet *CID,int factor,int facbits,octet *TOKEN)
+{
+    ECP_ZZZ P,R;
+    int res=0;
+    char h[MODBYTES_XXX];
+    octet H= {0,sizeof(h),h};
+
+    if (!ECP_ZZZ_fromOctet(&P,TOKEN))  res=MPIN_INVALID_POINT;
+    if (res==0)
+    {
+        mhashit(sha,-1,CID,&H);
+        ECP_ZZZ_mapit(&R,&H);
+
+        ECP_ZZZ_pinmul(&R,factor,facbits);
+        ECP_ZZZ_add(&P,&R); //ECP_ZZZ_affine(&P);
+
+        ECP_ZZZ_toOctet(TOKEN,&P,false);
+    }
+    return res;
+}
+
+/* Implement step 2 on client side of MPin protocol - SEC=-(x+y)*SEC */
+int MPIN_ZZZ_CLIENT_2(octet *X,octet *Y,octet *SEC)
+{
+    BIG_XXX px,py,r;
+    ECP_ZZZ P;
+    int res=0;
+    BIG_XXX_rcopy(r,CURVE_Order_ZZZ);
+    if (!ECP_ZZZ_fromOctet(&P,SEC)) res=MPIN_INVALID_POINT;
+    if (res==0)
+    {
+        BIG_XXX_fromBytes(px,X->val);
+        BIG_XXX_fromBytes(py,Y->val);
+        BIG_XXX_add(px,px,py);
+        BIG_XXX_mod(px,r);
+        //	BIG_XXX_sub(px,r,px);
+        PAIR_ZZZ_G1mul(&P,px);
+        ECP_ZZZ_neg(&P);
+        ECP_ZZZ_toOctet(SEC,&P,false);
+    }
+    return res;
+}
+
+/*
+ W=x*H(G);
+ if RNG == NULL then X is passed in
+ if RNG != NULL the X is passed out
+ if type=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve
+*/
+
+int MPIN_ZZZ_GET_G1_MULTIPLE(csprng *RNG,int type,octet *X,octet *G,octet *W)
+{
+    ECP_ZZZ P;
+    BIG_XXX r,x;
+    int res=0;
+    if (RNG!=NULL)
+    {
+        BIG_XXX_rcopy(r,CURVE_Order_ZZZ);
+        BIG_XXX_randomnum(x,r,RNG);
+#ifdef AES_S
+        BIG_XXX_mod2m(x,2*AES_S);
+#endif
+        X->len=MODBYTES_XXX;
+        BIG_XXX_toBytes(X->val,x);
+    }
+    else
+        BIG_XXX_fromBytes(x,X->val);
+
+    if (type==0)
+    {
+        if (!ECP_ZZZ_fromOctet(&P,G)) res=MPIN_INVALID_POINT;
+    }
+    else
+    {
+        ECP_ZZZ_mapit(&P,G);
+    }
+
+    if (res==0)
+    {
+        PAIR_ZZZ_G1mul(&P,x);
+        ECP_ZZZ_toOctet(W,&P,false);
+    }
+    return res;
+}
+
+/*
+ if RNG == NULL then X is passed in
+ if RNG != NULL the X is passed out
+ W=x*G where G is point on the curve
+ if type==1 W=(x^-1)G
+*/
+
+int MPIN_ZZZ_GET_G2_MULTIPLE(csprng *RNG,int type,octet *X,octet *G,octet *W)
+{
+    ECP2_ZZZ P;
+    BIG_XXX r,x;
+    int res=0;
+    BIG_XXX_rcopy(r,CURVE_Order_ZZZ);
+    if (RNG!=NULL)
+    {
+        BIG_XXX_randomnum(x,r,RNG);
+#ifdef AES_S
+        BIG_XXX_mod2m(x,2*AES_S);
+#endif
+        X->len=MODBYTES_XXX;
+        BIG_XXX_toBytes(X->val,x);
+    }
+    else
+    {
+        BIG_XXX_fromBytes(x,X->val);
+        if (type==1) BIG_XXX_invmodp(x,x,r);
+    }
+
+    if (!ECP2_ZZZ_fromOctet(&P,G)) res=MPIN_INVALID_POINT;
+
+    if (res==0)
+    {
+        PAIR_ZZZ_G2mul(&P,x);
+        ECP2_ZZZ_toOctet(W,&P);
+    }
+    return res;
+}
+
+
+
+/* Client secret CST=s*H(CID) where CID is client ID and s is master secret */
+/* CID is hashed externally */
+int MPIN_ZZZ_GET_CLIENT_SECRET(octet *S,octet *CID,octet *CST)
+{
+    return MPIN_ZZZ_GET_G1_MULTIPLE(NULL,1,S,CID,CST);
+}
+
+/* Implement step 1 on client side of MPin protocol */
+int MPIN_ZZZ_CLIENT_1(int sha,int date,octet *CLIENT_ID,csprng *RNG,octet *X,int pin,octet *TOKEN,octet *SEC,octet *xID,octet *xCID,octet *PERMIT)
+{
+    BIG_XXX r,x;
+    ECP_ZZZ P,T,W;
+    int res=0;
+    char h[MODBYTES_XXX];
+    octet H= {0,sizeof(h),h};
+
+    BIG_XXX_rcopy(r,CURVE_Order_ZZZ);
+    if (RNG!=NULL)
+    {
+        BIG_XXX_randomnum(x,r,RNG);
+#ifdef AES_S
+        BIG_XXX_mod2m(x,2*AES_S);
+#endif
+        X->len=MODBYTES_XXX;
+        BIG_XXX_toBytes(X->val,x);
+    }
+    else
+        BIG_XXX_fromBytes(x,X->val);
+
+    mhashit(sha,-1,CLIENT_ID,&H);
+
+    ECP_ZZZ_mapit(&P,&H);
+
+    if (!ECP_ZZZ_fromOctet(&T,TOKEN)) res=MPIN_INVALID_POINT;
+
+    if (res==0)
+    {
+        pin%=MAXPIN;
+
+        ECP_ZZZ_copy(&W,&P);				// W=H(ID)
+        ECP_ZZZ_pinmul(&W,pin,PBLEN);			// W=alpha.H(ID)
+        ECP_ZZZ_add(&T,&W);					// T=Token+alpha.H(ID) = s.H(ID)
+
+        if (date)
+        {
+            if (PERMIT!=NULL)
+            {
+                if (!ECP_ZZZ_fromOctet(&W,PERMIT)) res=MPIN_INVALID_POINT;
+                ECP_ZZZ_add(&T,&W);					// SEC=s.H(ID)+s.H(T|ID)
+            }
+            mhashit(sha,date,&H,&H);
+
+            ECP_ZZZ_mapit(&W,&H);
+            if (xID!=NULL)
+            {
+                PAIR_ZZZ_G1mul(&P,x);				// P=x.H(ID)
+                ECP_ZZZ_toOctet(xID,&P,false);  // xID
+                PAIR_ZZZ_G1mul(&W,x);               // W=x.H(T|ID)
+                ECP_ZZZ_add(&P,&W); //ECP_ZZZ_affine(&P);
+            }
+            else
+            {
+                ECP_ZZZ_add(&P,&W); //ECP_ZZZ_affine(&P);
+                PAIR_ZZZ_G1mul(&P,x);
+            }
+            if (xCID!=NULL) ECP_ZZZ_toOctet(xCID,&P,false);  // U
+        }
+        else
+        {
+            if (xID!=NULL)
+            {
+                PAIR_ZZZ_G1mul(&P,x);				// P=x.H(ID)
+                ECP_ZZZ_toOctet(xID,&P,false);  // xID
+            }
+        }
+    }
+
+    if (res==0)
+	{
+		//ECP_ZZZ_affine(&T);
+        ECP_ZZZ_toOctet(SEC,&T,false);  // V
+	}
+    return res;
+}
+
+/* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */
+int MPIN_ZZZ_GET_SERVER_SECRET(octet *S,octet *SST)
+{
+    BIG_XXX r,s;
+    ECP2_ZZZ Q;
+    int res=0;
+
+    BIG_XXX_rcopy(r,CURVE_Order_ZZZ);
+
+	ECP2_ZZZ_generator(&Q);
+
+    if (res==0)
+    {
+
+        BIG_XXX_fromBytes(s,S->val);
+        PAIR_ZZZ_G2mul(&Q,s);
+        ECP2_ZZZ_toOctet(SST,&Q);
+    }
+
+    return res;
+}
+
+
+/* Time Permit CTT=s*H(date|H(CID)) where s is master secret */
+int MPIN_ZZZ_GET_CLIENT_PERMIT(int sha,int date,octet *S,octet *CID,octet *CTT)
+{
+    BIG_XXX s;
+    ECP_ZZZ P;
+    char h[MODBYTES_XXX];
+    octet H= {0,sizeof(h),h};
+
+    mhashit(sha,date,CID,&H);
+
+    ECP_ZZZ_mapit(&P,&H);
+
+//printf("P= "); ECP_ZZZ_output(&P); printf("\n");
+//exit(0);
+
+    BIG_XXX_fromBytes(s,S->val);
+
+
+
+//printf("s= "); BIG_XXX_output(s); printf("\n");
+    PAIR_ZZZ_G1mul(&P,s);
+//printf("OP= "); ECP_ZZZ_output(&P); printf("\n");
+//
+    ECP_ZZZ_toOctet(CTT,&P,false);
+    return 0;
+}
+
+// if date=0 only use HID, set HCID=NULL
+// if date and PE, use HID and HCID
+
+/* Outputs H(CID) and H(CID)+H(T|H(CID)) for time permits. If no time permits set HTID=NULL */
+void MPIN_ZZZ_SERVER_1(int sha,int date,octet *CID,octet *HID,octet *HTID)
+{
+    char h[MODBYTES_XXX];
+    octet H= {0,sizeof(h),h};
+    ECP_ZZZ P,R;
+
+#ifdef USE_ANONYMOUS
+    ECP_ZZZ_mapit(&P,CID);
+#else
+    mhashit(sha,-1,CID,&H);
+    ECP_ZZZ_mapit(&P,&H);
+#endif
+
+    ECP_ZZZ_toOctet(HID,&P,false);  // new
+
+    if (date)
+    {
+        //	if (HID!=NULL) ECP_ZZZ_toOctet(HID,&P,false);
+#ifdef USE_ANONYMOUS
+        mhashit(sha,date,CID,&H);
+#else
+        mhashit(sha,date,&H,&H);
+#endif
+        ECP_ZZZ_mapit(&R,&H);
+        ECP_ZZZ_add(&P,&R); //ECP_ZZZ_affine(&P);
+        ECP_ZZZ_toOctet(HTID,&P,false);
+    }
+    //else ECP_ZZZ_toOctet(HID,&P,false);
+
+}
+
+/* Implement M-Pin on server side */
+int MPIN_ZZZ_SERVER_2(int date,octet *HID,octet *HTID,octet *Y,octet *SST,octet *xID,octet *xCID,octet *mSEC,octet *E,octet *F,octet *Pa)
+{
+    BIG_XXX px,py,y;
+    FP12_YYY g;
+    ECP2_ZZZ Q,sQ;
+    ECP_ZZZ P,R;
+    int res=0;
+
+	ECP2_ZZZ_generator(&Q);
+
+    // key-escrow less scheme: use Pa instead of Q in pairing computation
+    // Q left for backward compatiblity
+    if (Pa!=NULL)
+    {
+        if (!ECP2_ZZZ_fromOctet(&Q, Pa)) res=MPIN_INVALID_POINT;
+    }
+
+    if (res==0)
+    {
+        if (!ECP2_ZZZ_fromOctet(&sQ,SST)) res=MPIN_INVALID_POINT;
+    }
+
+    if (res==0)
+    {
+        if (date)
+        {
+            //BIG_XXX_fromBytes(px,&(xCID->val[1]));
+            //BIG_XXX_fromBytes(py,&(xCID->val[PFS_ZZZ+1]));
+			if (!ECP_ZZZ_fromOctet(&R,xCID))  res=MPIN_INVALID_POINT;
+        }
+        else
+        {
+            //BIG_XXX_fromBytes(px,&(xID->val[1]));
+            //BIG_XXX_fromBytes(py,&(xID->val[PFS_ZZZ+1]));
+			if (!ECP_ZZZ_fromOctet(&R,xID))  res=MPIN_INVALID_POINT;
+        }
+        //if (!ECP_ZZZ_set(&R,px,py)) res=MPIN_INVALID_POINT; // x(A+AT)
+    }
+    if (res==0)
+    {
+        BIG_XXX_fromBytes(y,Y->val);
+        if (date)
+        {
+            if (!ECP_ZZZ_fromOctet(&P,HTID))  res=MPIN_INVALID_POINT;
+        }
+        else
+        {
+            if (!ECP_ZZZ_fromOctet(&P,HID))  res=MPIN_INVALID_POINT;
+        }
+    }
+    if (res==0)
+    {
+        PAIR_ZZZ_G1mul(&P,y);  // y(A+AT)
+        ECP_ZZZ_add(&P,&R); // x(A+AT)+y(A+T)
+        //ECP_ZZZ_affine(&P);
+        if (!ECP_ZZZ_fromOctet(&R,mSEC))  res=MPIN_INVALID_POINT; // V
+    }
+    if (res==0)
+    {
+
+        PAIR_ZZZ_double_ate(&g,&Q,&R,&sQ,&P);
+        PAIR_ZZZ_fexp(&g);
+
+        if (!FP12_YYY_isunity(&g))
+        {
+            if (HID!=NULL && xID!=NULL && E!=NULL && F !=NULL)
+            {
+                /* xID is set to NULL if there is no way to calculate PIN error */
+                FP12_YYY_toOctet(E,&g);
+
+                /* Note error is in the PIN, not in the time permit! Hence the need to exclude Time Permit from this check */
+
+                if (date)
+                {
+                    if (!ECP_ZZZ_fromOctet(&P,HID)) res=MPIN_INVALID_POINT;
+                    if (!ECP_ZZZ_fromOctet(&R,xID)) res=MPIN_INVALID_POINT; // U
+
+                    if (res==0)
+                    {
+                        PAIR_ZZZ_G1mul(&P,y);  // yA
+                        ECP_ZZZ_add(&P,&R); // yA+xA
+                        //ECP_ZZZ_affine(&P);
+                    }
+                }
+                if (res==0)
+                {
+                    PAIR_ZZZ_ate(&g,&Q,&P);
+                    PAIR_ZZZ_fexp(&g);
+                    FP12_YYY_toOctet(F,&g);
+                }
+            }
+            res=MPIN_BAD_PIN;
+        }
+    }
+
+    return res;
+}
+
+#if MAXPIN==10000
+#define MR_TS 10  /* 2^10/10 approx = sqrt(MAXPIN) */
+#define TRAP 200  /* 2*sqrt(MAXPIN) */
+#endif
+
+#if MAXPIN==1000000
+#define MR_TS 14
+#define TRAP 2000
+#endif
+
+/* Pollards kangaroos used to return PIN error */
+int MPIN_ZZZ_KANGAROO(octet *E,octet *F)
+{
+    int i,j,m,s,dn,dm,steps;
+    int distance[MR_TS];
+    FP12_YYY ge,gf,t,table[MR_TS];
+    int res=0;
+    // BIG_XXX w;
+
+    FP12_YYY_fromOctet(&ge,E);
+    FP12_YYY_fromOctet(&gf,F);
+
+    FP12_YYY_copy(&t,&gf);
+
+    for (s=1,m=0; m<MR_TS; m++)
+    {
+        distance[m]=s;
+        FP12_YYY_copy(&table[m],&t);
+        s*=2;
+        FP12_YYY_usqr(&t,&t);
+        FP12_YYY_reduce(&t);
+    }
+
+    FP12_YYY_one(&t);
+
+    for (dn=0,j=0; j<TRAP; j++)
+    {
+
+        //BIG_XXX_copy(w,t.a.a.a);
+        //FP_YYY_redc(w);
+        //i=BIG_XXX_lastbits(w,20)%MR_TS;
+
+        i=t.a.a.a.g[0]%MR_TS;
+
+        FP12_YYY_mul(&t,&table[i]);
+        FP12_YYY_reduce(&t);
+        dn+=distance[i];
+    }
+
+    FP12_YYY_conj(&gf,&t);
+    steps=0;
+    dm=0;
+    while (dm-dn<MAXPIN)
+    {
+        steps++;
+        if (steps>4*TRAP) break;
+
+        //BIG_XXX_copy(w,ge.a.a.a);
+        //FP_YYY_redc(w);
+        //i=BIG_XXX_lastbits(w,20)%MR_TS;
+
+        i=ge.a.a.a.g[0]%MR_TS;
+
+        FP12_YYY_mul(&ge,&table[i]);
+        FP12_YYY_reduce(&ge);
+        dm+=distance[i];
+        if (FP12_YYY_equals(&ge,&t))
+        {
+            res=dm-dn;
+            break;
+        }
+        if (FP12_YYY_equals(&ge,&gf))
+        {
+            res=dn-dm;
+            break;
+        }
+    }
+    if (steps>4*TRAP || dm-dn>=MAXPIN)
+    {
+        res=0;    /* Trap Failed  - probable invalid token */
+    }
+
+    return res;
+}
+
+/* Functions to support M-Pin Full */
+
+int MPIN_ZZZ_PRECOMPUTE(octet *TOKEN,octet *CID,octet *CP,octet *G1,octet *G2)
+{
+    ECP_ZZZ P,T;
+    ECP2_ZZZ Q;
+    FP12_YYY g;
+    int res=0;
+
+    if (!ECP_ZZZ_fromOctet(&T,TOKEN)) res=MPIN_INVALID_POINT;
+
+    if (res==0)
+    {
+        ECP_ZZZ_mapit(&P,CID);
+        if (CP!=NULL)
+        {
+            if (!ECP2_ZZZ_fromOctet(&Q,CP)) res=MPIN_INVALID_POINT;
+        }
+        else
+        {
+			ECP2_ZZZ_generator(&Q);
+        }
+    }
+    if (res==0)
+    {
+        PAIR_ZZZ_ate(&g,&Q,&T);
+        PAIR_ZZZ_fexp(&g);
+
+        FP12_YYY_toOctet(G1,&g);
+        if (G2!=NULL)
+        {
+            PAIR_ZZZ_ate(&g,&Q,&P);
+            PAIR_ZZZ_fexp(&g);
+            FP12_YYY_toOctet(G2,&g);
+        }
+    }
+    return res;
+}
+
+/* calculate common key on client side */
+/* wCID = w.(A+AT) */
+int MPIN_ZZZ_CLIENT_KEY(int sha,octet *G1,octet *G2,int pin,octet *R,octet *X,octet *H,octet *wCID,octet *CK)
+{
+    FP12_YYY g1,g2;
+    FP4_YYY c;//,cp,cpm1,cpm2;
+//    FP2_YYY f;
+    ECP_ZZZ W;
+    int res=0;
+    BIG_XXX r,z,x,h;//q,m,a,b;
+
+    FP12_YYY_fromOctet(&g1,G1);
+    FP12_YYY_fromOctet(&g2,G2);
+    BIG_XXX_fromBytes(z,R->val);
+    BIG_XXX_fromBytes(x,X->val);
+    BIG_XXX_fromBytes(h,H->val);
+
+    if (!ECP_ZZZ_fromOctet(&W,wCID)) res=MPIN_INVALID_POINT;
+
+    if (res==0)
+    {
+        BIG_XXX_rcopy(r,CURVE_Order_ZZZ);
+        BIG_XXX_add(z,z,h);    // new
+        BIG_XXX_mod(z,r);
+
+        FP12_YYY_pinpow(&g2,pin,PBLEN);
+        FP12_YYY_mul(&g1,&g2);
+
+        PAIR_ZZZ_G1mul(&W,x);
+
+        FP12_YYY_compow(&c,&g1,z,r);
+
+        /*       BIG_XXX_rcopy(a,Fra_YYY);
+               BIG_XXX_rcopy(b,Frb_YYY);
+               FP2_YYY_from_BIGs(&f,a,b);
+
+               BIG_XXX_rcopy(q,Modulus_YYY);
+               BIG_XXX_copy(m,q);
+               BIG_XXX_mod(m,r);
+
+               BIG_XXX_copy(a,z);
+               BIG_XXX_mod(a,m);
+
+               BIG_XXX_copy(b,z);
+               BIG_XXX_sdiv(b,m);
+
+
+               FP12_YYY_trace(&c,&g1);
+
+               FP12_YYY_copy(&g2,&g1);
+               FP12_YYY_frob(&g2,&f);
+               FP12_YYY_trace(&cp,&g2);
+
+               FP12_YYY_conj(&g1,&g1);
+               FP12_YYY_mul(&g2,&g1);
+               FP12_YYY_trace(&cpm1,&g2);
+               FP12_YYY_mul(&g2,&g1);
+               FP12_YYY_trace(&cpm2,&g2);
+
+               FP4_YYY_xtr_pow2(&c,&cp,&c,&cpm1,&cpm2,a,b);
+        */
+        mpin_hash(sha,&c,&W,CK);
+
+    }
+    return res;
+}
+
+/* calculate common key on server side */
+/* Z=r.A - no time permits involved */
+
+int MPIN_ZZZ_SERVER_KEY(int sha,octet *Z,octet *SST,octet *W,octet *H,octet *HID,octet *xID,octet *xCID,octet *SK)
+{
+    int res=0;
+    FP12_YYY g;
+    FP4_YYY c;
+    ECP_ZZZ R,U,A;
+    ECP2_ZZZ sQ;
+    BIG_XXX w,h;
+
+    if (!ECP2_ZZZ_fromOctet(&sQ,SST)) res=MPIN_INVALID_POINT;
+    if (!ECP_ZZZ_fromOctet(&R,Z)) res=MPIN_INVALID_POINT;
+
+
+    if (!ECP_ZZZ_fromOctet(&A,HID)) res=MPIN_INVALID_POINT;
+
+    // new
+    if (xCID!=NULL)
+    {
+        if (!ECP_ZZZ_fromOctet(&U,xCID)) res=MPIN_INVALID_POINT;
+    }
+    else
+    {
+        if (!ECP_ZZZ_fromOctet(&U,xID)) res=MPIN_INVALID_POINT;
+    }
+    BIG_XXX_fromBytes(w,W->val);
+    BIG_XXX_fromBytes(h,H->val);
+
+
+    PAIR_ZZZ_ate(&g,&sQ,&A);
+    PAIR_ZZZ_fexp(&g);
+
+    if (res==0)
+    {
+        PAIR_ZZZ_G1mul(&A,h);
+        ECP_ZZZ_add(&R,&A);  // new
+        //ECP_ZZZ_affine(&R);
+        PAIR_ZZZ_ate(&g,&sQ,&R);
+        PAIR_ZZZ_fexp(&g);
+        PAIR_ZZZ_G1mul(&U,w);
+        FP12_YYY_trace(&c,&g);
+        mpin_hash(sha,&c,&U,SK);
+    }
+    return res;
+}
+
+/* Generate Y = H(TimeValue, xCID/xID) */
+void MPIN_ZZZ_GET_Y(int sha,int TimeValue,octet *xCID,octet *Y)
+{
+    BIG_XXX q,y;
+    char h[MODBYTES_XXX];
+    octet H= {0,sizeof(h),h};
+
+    mhashit(sha,TimeValue,xCID,&H);
+    BIG_XXX_fromBytes(y,H.val);
+    BIG_XXX_rcopy(q,CURVE_Order_ZZZ);
+    BIG_XXX_mod(y,q);
+    BIG_XXX_toBytes(Y->val,y);
+    Y->len=PGS_ZZZ;
+}
+
+/* One pass MPIN Client */
+int MPIN_ZZZ_CLIENT(int sha,int date,octet *ID,csprng *RNG,octet *X,int pin,octet *TOKEN,octet *V,octet *U,octet *UT,octet *TP,octet *MESSAGE,int TimeValue,octet *Y)
+{
+    int rtn=0;
+    char m[M_SIZE_ZZZ];
+    octet M= {0,sizeof(m),m};
+
+    octet *pID;
+    if (date == 0)
+        pID = U;
+    else
+        pID = UT;
+
+    rtn = MPIN_ZZZ_CLIENT_1(sha,date,ID,RNG,X,pin,TOKEN,V,U,UT,TP);
+    if (rtn != 0)
+        return rtn;
+
+    OCT_joctet(&M,pID);
+    if (MESSAGE!=NULL)
+    {
+        OCT_joctet(&M,MESSAGE);
+    }
+
+    MPIN_ZZZ_GET_Y(sha,TimeValue,&M,Y);
+
+    rtn = MPIN_ZZZ_CLIENT_2(X,Y,V);
+    if (rtn != 0)
+        return rtn;
+
+    return 0;
+}
+
+/* One pass MPIN Server */
+int MPIN_ZZZ_SERVER(int sha,int date,octet *HID,octet *HTID,octet *Y,octet *sQ,octet *U,octet *UT,octet *V,octet *E,octet *F,octet *ID,octet *MESSAGE,int TimeValue, octet *Pa)
+{
+    int rtn=0;
+    char m[M_SIZE_ZZZ];
+    octet M= {0,sizeof(m),m};
+
+    octet *pU;
+    if (date == 0)
+        pU = U;
+    else
+        pU = UT;
+
+    MPIN_ZZZ_SERVER_1(sha,date,ID,HID,HTID);
+
+    OCT_joctet(&M,pU);
+    if (MESSAGE!=NULL)
+    {
+        OCT_joctet(&M,MESSAGE);
+    }
+
+    MPIN_ZZZ_GET_Y(sha,TimeValue,&M,Y);
+
+    rtn = MPIN_ZZZ_SERVER_2(date,HID,HTID,Y,sQ,U,UT,V,E,F,Pa);
+    if (rtn != 0)
+        return rtn;
+
+    return 0;
+}
+
+int MPIN_ZZZ_GET_DVS_KEYPAIR(csprng *R,octet *Z,octet *Pa)
+{
+    BIG_XXX z,r;
+    ECP2_ZZZ Q;
+    int res=0;
+
+    BIG_XXX_rcopy(r,CURVE_Order_ZZZ);
+
+    if (R!=NULL)
+    {
+        BIG_XXX_randomnum(z,r,R);
+        Z->len=MODBYTES_XXX;
+        BIG_XXX_toBytes(Z->val,z);
+    }
+    else
+        BIG_XXX_fromBytes(z,Z->val);
+
+    BIG_XXX_invmodp(z,z,r);
+
+	ECP2_ZZZ_generator(&Q);
+
+    if (res==0)
+    {
+        PAIR_ZZZ_G2mul(&Q,z);
+        ECP2_ZZZ_toOctet(Pa,&Q);
+    }
+
+    return res;
+}
diff --git a/version3/c/mpin.h b/version3/c/mpin.h
new file mode 100644
index 0000000..98c853c
--- /dev/null
+++ b/version3/c/mpin.h
@@ -0,0 +1,345 @@
+/*
+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.
+*/
+
+/**
+ * @file mpin.h
+ * @author Mike Scott
+ * @brief M-Pin Header file
+ *
+ *
+ */
+
+#ifndef MPIN_ZZZ_H
+#define MPIN_ZZZ_H
+
+#include "pair_ZZZ.h"
+#include "pbc_support.h"
+
+/* Field size is assumed to be greater than or equal to group size */
+
+#define PGS_ZZZ MODBYTES_XXX  /**< MPIN Group Size */
+#define PFS_ZZZ MODBYTES_XXX  /**< MPIN Field Size */
+//#define PAS_ZZZ 16            /**< MPIN Symmetric Key Size */
+
+#define MPIN_OK             0   /**< Function completed without error */
+#define MPIN_INVALID_POINT  -14	/**< Point is NOT on the curve */
+#define MPIN_BAD_PIN        -19 /**< Bad PIN number entered */
+
+#define MPIN_PAS 16          /**< MPIN Symmetric Key Size */
+#define MAXPIN 10000         /**< max PIN */
+#define PBLEN 14             /**< max length of PIN in bits */
+
+//#define HASH_TYPE_MPIN_ZZZ SHA256   /**< Choose Hash function */
+
+#define MESSAGE_SIZE 256        /**< Signature message size  */
+#define M_SIZE_ZZZ (MESSAGE_SIZE+2*PFS_ZZZ+1)   /**< Signature message size and G1 size */
+
+/* MPIN support functions */
+
+/* MPIN primitives */
+
+
+/**	@brief Generate Y=H(s,O), where s is epoch time, O is an octet, and H(.) is a hash function
+ *
+  	@param h is the hash type
+	@param t is epoch time in seconds
+	@param O is an input octet
+	@param Y is the output octet
+*/
+void MPIN_ZZZ_GET_Y(int h,int t,octet *O,octet *Y);
+
+/**	@brief Extract a PIN number from a client secret
+ *
+  	@param h is the hash type
+	@param ID is the input client identity
+	@param factor is an input factor
+	@param facbits is the number of bits in the factor
+	@param CS is the client secret from which the factor is to be extracted
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_EXTRACT_FACTOR(int h,octet *ID,int factor,int facbits,octet *CS);
+
+/**	@brief Extract a PIN number from a client secret
+ *
+  	@param h is the hash type
+	@param ID is the input client identity
+	@param factor is an input factor
+	@param facbits is the number of bits in the factor
+	@param CS is the client secret to which the factor is to be added
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_RESTORE_FACTOR(int h,octet *ID,int factor,int facbits,octet *CS);
+
+
+/**	@brief Extract a PIN number from a client secret
+ *
+  	@param h is the hash type
+	@param ID is the input client identity
+	@param pin is an input PIN number
+	@param CS is the client secret from which the PIN is to be extracted
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_EXTRACT_PIN(int h,octet *ID,int pin,octet *CS);
+
+
+
+/**	@brief Perform client side of the one-pass version of the M-Pin protocol
+ *
+	If Time Permits are disabled, set d = 0, and UT is not generated and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is OFF, U is not generated and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is ON, U and UT are both generated.
+ 	@param h is the hash type
+	@param d is input date, in days since the epoch. Set to 0 if Time permits disabled
+	@param ID is the input client identity
+	@param R is a pointer to a cryptographically secure random number generator
+	@param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input
+	@param pin is the input PIN number
+	@param T is the input M-Pin token (the client secret with PIN portion removed)
+	@param V is output = -(x+y)(CS+TP), where CS is the reconstructed client secret, and TP is the time permit
+	@param U is output = x.H(ID)
+	@param UT is output = x.(H(ID)+H(d|H(ID)))
+	@param TP is the input time permit
+	@param MESSAGE is the message to be signed
+	@param t is input epoch time in seconds - a timestamp
+	@param y is output H(t|U) or H(t|UT) if Time Permits enabled
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_CLIENT(int h,int d,octet *ID,csprng *R,octet *x,int pin,octet *T,octet *V,octet *U,octet *UT,octet *TP, octet* MESSAGE, int t, octet *y);
+/**	@brief Perform first pass of the client side of the 3-pass version of the M-Pin protocol
+ *
+	If Time Permits are disabled, set d = 0, and UT is not generated and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is OFF, U is not generated and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is ON, U and UT are both generated.
+ 	@param h is the hash type
+	@param d is input date, in days since the epoch. Set to 0 if Time permits disabled
+	@param ID is the input client identity
+	@param R is a pointer to a cryptographically secure random number generator
+	@param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input
+	@param pin is the input PIN number
+	@param T is the input M-Pin token (the client secret with PIN portion removed)
+	@param S is output = CS+TP, where CS=is the reconstructed client secret, and TP is the time permit
+	@param U is output = x.H(ID)
+	@param UT is output = x.(H(ID)+H(d|H(ID)))
+	@param TP is the input time permit
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_CLIENT_1(int h,int d,octet *ID,csprng *R,octet *x,int pin,octet *T,octet *S,octet *U,octet *UT,octet *TP);
+/**	@brief Generate a random group element
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param S is the output random octet
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_RANDOM_GENERATE(csprng *R,octet *S);
+/**	@brief Perform second pass of the client side of the 3-pass version of the M-Pin protocol
+ *
+	@param x an input, a locally generated random number
+	@param y an input random challenge from the server
+	@param V on output = -(x+y).V
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_CLIENT_2(octet *x,octet *y,octet *V);
+/**	@brief Perform server side of the one-pass version of the M-Pin protocol
+ *
+	If Time Permits are disabled, set d = 0, and UT and HTID are not generated and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is OFF, U and HID are not needed and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is ON, U, UT, HID and HTID are all required.
+ 	@param h is the hash type
+	@param d is input date, in days since the epoch. Set to 0 if Time permits disabled
+	@param HID is output H(ID), a hash of the client ID
+	@param HTID is output H(ID)+H(d|H(ID))
+	@param y is output H(t|U) or H(t|UT) if Time Permits enabled
+	@param SS is the input server secret
+	@param U is input from the client = x.H(ID)
+	@param UT is input from the client= x.(H(ID)+H(d|H(ID)))
+	@param V is an input from the client
+	@param E is an output to help the Kangaroos to find the PIN error, or NULL if not required
+	@param F is an output to help the Kangaroos to find the PIN error, or NULL if not required
+	@param ID is the input claimed client identity
+	@param MESSAGE is the message to be signed
+	@param t is input epoch time in seconds - a timestamp
+	@param Pa is input from the client z.Q or NULL if the key-escrow less scheme is not used
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_SERVER(int h,int d,octet *HID,octet *HTID,octet *y,octet *SS,octet *U,octet *UT,octet *V,octet *E,octet *F,octet *ID,octet *MESSAGE, int t, octet *Pa);
+/**	@brief Perform first pass of the server side of the 3-pass version of the M-Pin protocol
+ *
+ 	@param h is the hash type
+	@param d is input date, in days since the epoch. Set to 0 if Time permits disabled
+	@param ID is the input claimed client identity
+	@param HID is output H(ID), a hash of the client ID
+	@param HTID is output H(ID)+H(d|H(ID))
+	@return 0 or an error code
+ */
+void MPIN_ZZZ_SERVER_1(int h,int d,octet *ID,octet *HID,octet *HTID);
+/**	@brief Perform third pass on the server side of the 3-pass version of the M-Pin protocol
+ *
+	If Time Permits are disabled, set d = 0, and UT and HTID are not needed and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is OFF, U and HID are not needed and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is ON, U, UT, HID and HTID are all required.
+	@param d is input date, in days since the epoch. Set to 0 if Time permits disabled
+	@param HID is input H(ID), a hash of the client ID
+	@param HTID is input H(ID)+H(d|H(ID))
+	@param y is the input server's randomly generated challenge
+	@param SS is the input server secret
+	@param U is input from the client = x.H(ID)
+	@param UT is input from the client= x.(H(ID)+H(d|H(ID)))
+	@param V is an input from the client
+	@param E is an output to help the Kangaroos to find the PIN error, or NULL if not required
+	@param F is an output to help the Kangaroos to find the PIN error, or NULL if not required
+	@param Pa is the input public key from the client, z.Q or NULL if the client uses regular mpin
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_SERVER_2(int d,octet *HID,octet *HTID,octet *y,octet *SS,octet *U,octet *UT,octet *V,octet *E,octet *F,octet *Pa);
+/**	@brief Add two members from the group G1
+ *
+	@param Q1 an input member of G1
+	@param Q2 an input member of G1
+	@param Q an output member of G1 = Q1+Q2
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_RECOMBINE_G1(octet *Q1,octet *Q2,octet *Q);
+/**	@brief Add two members from the group G2
+ *
+	@param P1 an input member of G2
+	@param P2 an input member of G2
+	@param P an output member of G2 = P1+P2
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_RECOMBINE_G2(octet *P1,octet *P2,octet *P);
+/**	@brief Use Kangaroos to find PIN error
+ *
+	@param E a member of the group GT
+	@param F a member of the group GT =  E^e
+	@return 0 if Kangaroos failed, or the PIN error e
+ */
+int MPIN_ZZZ_KANGAROO(octet *E,octet *F);
+/**	@brief Encoding of a Time Permit to make it indistinguishable from a random string
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param TP is the input time permit, obfuscated on output
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_ENCODING(csprng *R,octet *TP);
+/**	@brief Encoding of an obfuscated Time Permit
+ *
+	@param TP is the input obfuscated time permit, restored on output
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_DECODING(octet *TP);
+
+/**	@brief Find a random multiple of a point in G1
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param type determines type of action to be taken
+	@param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input
+	@param G if type=0 a point in G1, else an octet to be mapped to G1
+	@param W the output =x.G or x.M(G), where M(.) is a mapping
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_GET_G1_MULTIPLE(csprng *R,int type,octet *x,octet *G,octet *W);
+/**	@brief Find a random multiple of a point in G1
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param type determines type of action to betaken
+	@param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input
+	@param G a point in G2
+	@param W the output =x.G or (1/x).G
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_GET_G2_MULTIPLE(csprng *R,int type,octet *x,octet *G,octet *W);
+
+/**	@brief Create a client secret in G1 from a master secret and the client ID
+ *
+	@param S is an input master secret
+	@param ID is the input client identity
+	@param CS is the full client secret = s.H(ID)
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_GET_CLIENT_SECRET(octet *S,octet *ID,octet *CS);
+/**	@brief Create a Time Permit in G1 from a master secret and the client ID
+ *
+  	@param h is the hash type
+	@param d is input date, in days since the epoch.
+	@param S is an input master secret
+	@param ID is the input client identity
+	@param TP is a Time Permit for the given date = s.H(d|H(ID))
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_GET_CLIENT_PERMIT(int h,int d,octet *S,octet *ID,octet *TP);
+/**	@brief Create a server secret in G2 from a master secret
+ *
+	@param S is an input master secret
+	@param SS is the server secret = s.Q where Q is a fixed generator of G2
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_GET_SERVER_SECRET(octet *S,octet *SS);
+/* int MPIN_TEST_PAIRING(octet *,octet *); */
+
+/* For M-Pin Full */
+/**	@brief Precompute values for use by the client side of M-Pin Full
+ *
+	@param T is the input M-Pin token (the client secret with PIN portion removed)
+	@param ID is the input client identity
+	@param CP is Public Key (or NULL)
+	@param g1 precomputed output
+	@param g2 precomputed output
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_PRECOMPUTE(octet *T,octet *ID,octet *CP,octet *g1,octet *g2);
+/**	@brief Calculate Key on Server side for M-Pin Full
+ *
+	Uses UT internally for the key calculation, unless not available in which case U is used
+ 	@param h is the hash type
+	@param Z is the input Client-side Diffie-Hellman component
+	@param SS is the input server secret
+	@param w is an input random number generated by the server
+	@param p is an input, hash of the protocol transcript
+	@param I is the hashed input client ID = H(ID)
+	@param U is input from the client = x.H(ID)
+	@param UT is input from the client= x.(H(ID)+H(d|H(ID)))
+	@param K is the output calculated shared key
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_SERVER_KEY(int h,octet *Z,octet *SS,octet *w,octet *p,octet *I,octet *U,octet *UT,octet *K);
+/**	@brief Calculate Key on Client side for M-Pin Full
+ *
+  	@param h is the hash type
+	@param g1 precomputed input
+	@param g2 precomputed input
+	@param pin is the input PIN number
+	@param r is an input, a locally generated random number
+	@param x is an input, a locally generated random number
+	@param p is an input, hash of the protocol transcript
+	@param T is the input Server-side Diffie-Hellman component
+	@param K is the output calculated shared key
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_CLIENT_KEY(int h,octet *g1,octet *g2,int pin,octet *r,octet *x,octet *p,octet *T,octet *K);
+
+/** @brief Generates a random public key for the client z.Q
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param Z an output internally randomly generated if R!=NULL, otherwise it must be provided as an input
+	@param Pa the output public key for the client
+ */
+int MPIN_ZZZ_GET_DVS_KEYPAIR(csprng *R,octet *Z,octet *Pa);
+
+#endif
+
diff --git a/version3/c/mpin192.c b/version3/c/mpin192.c
new file mode 100644
index 0000000..e1f3bce
--- /dev/null
+++ b/version3/c/mpin192.c
@@ -0,0 +1,975 @@
+/*
+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.
+*/
+
+/* MPIN Functions */
+
+/* Version 3.0 - supports Time Permits */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "mpin192_ZZZ.h"
+
+#define ROUNDUP(a,b) ((a)-1)/(b)+1
+
+/* Special mpin hashing */
+static void mpin_hash(int sha,FP8_YYY *f, ECP_ZZZ *P,octet *w)
+{
+    int i;
+    BIG_XXX x,y;
+    char h[64];
+    hash256 sha256;
+    hash512 sha512;
+    char t[10*MODBYTES_XXX];  // to hold 10 BIGs
+    int hlen=sha;
+
+
+	FP_YYY_redc(x,&(f->a.a.a));
+    BIG_XXX_toBytes(&t[0],x);
+    FP_YYY_redc(x,&(f->a.a.b));
+    BIG_XXX_toBytes(&t[MODBYTES_XXX],x);
+    FP_YYY_redc(x,&(f->a.b.a));
+    BIG_XXX_toBytes(&t[2*MODBYTES_XXX],x);
+    FP_YYY_redc(x,&(f->a.b.b));
+    BIG_XXX_toBytes(&t[3*MODBYTES_XXX],x);
+
+	FP_YYY_redc(x,&(f->b.a.a));
+    BIG_XXX_toBytes(&t[4*MODBYTES_XXX],x);
+    FP_YYY_redc(x,&(f->b.a.b));
+    BIG_XXX_toBytes(&t[5*MODBYTES_XXX],x);
+    FP_YYY_redc(x,&(f->b.b.a));
+    BIG_XXX_toBytes(&t[6*MODBYTES_XXX],x);
+    FP_YYY_redc(x,&(f->b.b.b));
+    BIG_XXX_toBytes(&t[7*MODBYTES_XXX],x);
+
+    ECP_ZZZ_get(x,y,P);
+    BIG_XXX_toBytes(&t[8*MODBYTES_XXX],x);
+    BIG_XXX_toBytes(&t[9*MODBYTES_XXX],y);
+
+    OCT_empty(w);
+    switch (sha)
+    {
+    case SHA256:
+        HASH256_init(&sha256);
+        for (i=0; i<10*MODBYTES_XXX; i++) HASH256_process(&sha256,t[i]);
+        HASH256_hash(&sha256,h);
+        break;
+    case SHA384:
+        HASH384_init(&sha512);
+        for (i=0; i<10*MODBYTES_XXX; i++) HASH384_process(&sha512,t[i]);
+        HASH384_hash(&sha512,h);
+        break;
+    case SHA512:
+        HASH512_init(&sha512);
+        for (i=0; i<10*MODBYTES_XXX; i++) HASH512_process(&sha512,t[i]);
+        HASH512_hash(&sha512,h);
+        break;
+    }
+
+    OCT_jbytes(w,h,AESKEY_ZZZ);
+    for (i=0; i<hlen; i++) h[i]=0;
+}
+
+/* these next two functions help to implement elligator squared - http://eprint.iacr.org/2014/043 */
+/* maps a random u to a point on the curve */
+static void map(ECP_ZZZ *P,BIG_XXX u,int cb)
+{
+    BIG_XXX x,q;
+
+    BIG_XXX_rcopy(q,Modulus_YYY);
+    BIG_XXX_copy(x,u);
+    BIG_XXX_mod(x,q);
+
+    while (!ECP_ZZZ_setx(P,x,cb))
+	{
+        BIG_XXX_inc(x,1); BIG_XXX_norm(x);
+	}
+}
+
+/* returns u derived from P. Random value in range 1 to return value should then be added to u */
+static int unmap(BIG_XXX u,int *cb,ECP_ZZZ *P)
+{
+    int s,r=0;
+    BIG_XXX x;
+
+    s=ECP_ZZZ_get(x,x,P);
+    BIG_XXX_copy(u,x);
+    do
+    {
+        BIG_XXX_dec(u,1); BIG_XXX_norm(u);
+        r++;
+    }
+    while (!ECP_ZZZ_setx(P,u,s));
+    ECP_ZZZ_setx(P,x,s);
+
+    *cb=s;
+
+    return r;
+}
+
+/* these next two functions implement elligator squared - http://eprint.iacr.org/2014/043 */
+/* Elliptic curve point E in format (0x04,x,y} is converted to form {0x0-,u,v} */
+/* Note that u and v are indistinguisible from random strings */
+int MPIN_ZZZ_ENCODING(csprng *RNG,octet *E)
+{
+    int rn,m,su,sv,res=0;
+
+    BIG_XXX q,u,v;
+    ECP_ZZZ P,W;
+
+    if (!ECP_ZZZ_fromOctet(&P,E)) res=MPIN_INVALID_POINT;
+    if (res==0)
+    {
+        BIG_XXX_rcopy(q,Modulus_YYY);
+
+        BIG_XXX_randomnum(u,q,RNG);
+
+        su=RAND_byte(RNG);
+        if (su<0) su=-su;
+        su%=2;
+        map(&W,u,su);
+        ECP_ZZZ_sub(&P,&W); //ECP_ZZZ_affine(&P);
+
+        rn=unmap(v,&sv,&P);
+        m=RAND_byte(RNG);
+        if (m<0) m=-m;
+        m%=rn;
+        BIG_XXX_inc(v,m+1);
+        E->val[0]=su+2*sv;
+        BIG_XXX_toBytes(&(E->val[1]),u);
+        BIG_XXX_toBytes(&(E->val[PFS_ZZZ+1]),v);
+    }
+    return res;
+}
+
+int MPIN_ZZZ_DECODING(octet *D)
+{
+    int su,sv;
+    BIG_XXX u,v;
+    ECP_ZZZ P,W;
+    int res=0;
+
+    if ((D->val[0]&0x04)!=0) res=MPIN_INVALID_POINT;
+    if (res==0)
+    {
+
+        BIG_XXX_fromBytes(u,&(D->val[1]));
+        BIG_XXX_fromBytes(v,&(D->val[PFS_ZZZ+1]));
+
+        su=D->val[0]&1;
+        sv=(D->val[0]>>1)&1;
+        map(&W,u,su);
+        map(&P,v,sv);
+        ECP_ZZZ_add(&P,&W); //ECP_ZZZ_affine(&P);
+        ECP_ZZZ_toOctet(D,&P,false);
+    }
+
+    return res;
+}
+
+/* R=R1+R2 in group G1 */
+int MPIN_ZZZ_RECOMBINE_G1(octet *R1,octet *R2,octet *R)
+{
+    ECP_ZZZ P,T;
+    int res=0;
+    if (res==0)
+    {
+        if (!ECP_ZZZ_fromOctet(&P,R1)) res=MPIN_INVALID_POINT;
+        if (!ECP_ZZZ_fromOctet(&T,R2)) res=MPIN_INVALID_POINT;
+    }
+    if (res==0)
+    {
+        ECP_ZZZ_add(&P,&T); //ECP_ZZZ_affine(&P);
+        ECP_ZZZ_toOctet(R,&P,false);
+    }
+    return res;
+}
+
+/* W=W1+W2 in group G2 */
+int MPIN_ZZZ_RECOMBINE_G2(octet *W1,octet *W2,octet *W)
+{
+    ECP4_ZZZ Q,T;
+    int res=0;
+    if (!ECP4_ZZZ_fromOctet(&Q,W1)) res=MPIN_INVALID_POINT;
+    if (!ECP4_ZZZ_fromOctet(&T,W2)) res=MPIN_INVALID_POINT;
+    if (res==0)
+    {
+        ECP4_ZZZ_add(&Q,&T); //ECP4_ZZZ_affine(&Q);
+        ECP4_ZZZ_toOctet(W,&Q);
+    }
+    return res;
+}
+
+/* create random secret S */
+int MPIN_ZZZ_RANDOM_GENERATE(csprng *RNG,octet* S)
+{
+    BIG_XXX r,s;
+
+    BIG_XXX_rcopy(r,CURVE_Order_ZZZ);
+    BIG_XXX_randomnum(s,r,RNG);
+#ifdef AES_S
+    BIG_XXX_mod2m(s,2*AES_S);
+#endif
+    BIG_XXX_toBytes(S->val,s);
+    S->len=MODBYTES_XXX;
+    return 0;
+}
+
+/* Extract PIN from TOKEN for identity CID */
+int MPIN_ZZZ_EXTRACT_PIN(int sha,octet *CID,int pin,octet *TOKEN)
+{
+	pin%=MAXPIN;
+	return MPIN_ZZZ_EXTRACT_FACTOR(sha,CID,pin,PBLEN,TOKEN);
+}
+
+/* Extract a factor < 32 bits for identity CID */
+int MPIN_ZZZ_EXTRACT_FACTOR(int sha,octet *CID,int factor,int facbits,octet *TOKEN)
+{
+    ECP_ZZZ P,R;
+    int res=0;
+    char h[MODBYTES_XXX];
+    octet H= {0,sizeof(h),h};
+
+    if (!ECP_ZZZ_fromOctet(&P,TOKEN))  res=MPIN_INVALID_POINT;
+    if (res==0)
+    {
+        mhashit(sha,-1,CID,&H);
+        ECP_ZZZ_mapit(&R,&H);
+
+        ECP_ZZZ_pinmul(&R,factor,facbits);
+        ECP_ZZZ_sub(&P,&R); //ECP_ZZZ_affine(&P);
+
+        ECP_ZZZ_toOctet(TOKEN,&P,false);
+    }
+    return res;
+}
+
+/* Extract a factor < 32 bits for identity CID */
+int MPIN_ZZZ_RESTORE_FACTOR(int sha,octet *CID,int factor,int facbits,octet *TOKEN)
+{
+    ECP_ZZZ P,R;
+    int res=0;
+    char h[MODBYTES_XXX];
+    octet H= {0,sizeof(h),h};
+
+    if (!ECP_ZZZ_fromOctet(&P,TOKEN))  res=MPIN_INVALID_POINT;
+    if (res==0)
+    {
+        mhashit(sha,-1,CID,&H);
+        ECP_ZZZ_mapit(&R,&H);
+
+        ECP_ZZZ_pinmul(&R,factor,facbits);
+        ECP_ZZZ_add(&P,&R); //ECP_ZZZ_affine(&P);
+
+        ECP_ZZZ_toOctet(TOKEN,&P,false);
+    }
+    return res;
+}
+
+/* Implement step 2 on client side of MPin protocol - SEC=-(x+y)*SEC */
+int MPIN_ZZZ_CLIENT_2(octet *X,octet *Y,octet *SEC)
+{
+    BIG_XXX px,py,r;
+    ECP_ZZZ P;
+    int res=0;
+    BIG_XXX_rcopy(r,CURVE_Order_ZZZ);
+    if (!ECP_ZZZ_fromOctet(&P,SEC)) res=MPIN_INVALID_POINT;
+    if (res==0)
+    {
+        BIG_XXX_fromBytes(px,X->val);
+        BIG_XXX_fromBytes(py,Y->val);
+        BIG_XXX_add(px,px,py);
+        BIG_XXX_mod(px,r);
+        //	BIG_XXX_sub(px,r,px);
+        PAIR_ZZZ_G1mul(&P,px);
+        ECP_ZZZ_neg(&P);
+        ECP_ZZZ_toOctet(SEC,&P,false);
+    }
+    return res;
+}
+
+/*
+ W=x*H(G);
+ if RNG == NULL then X is passed in
+ if RNG != NULL the X is passed out
+ if type=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve
+*/
+
+int MPIN_ZZZ_GET_G1_MULTIPLE(csprng *RNG,int type,octet *X,octet *G,octet *W)
+{
+    ECP_ZZZ P;
+    BIG_XXX r,x;
+    int res=0;
+    if (RNG!=NULL)
+    {
+        BIG_XXX_rcopy(r,CURVE_Order_ZZZ);
+        BIG_XXX_randomnum(x,r,RNG);
+#ifdef AES_S
+        BIG_XXX_mod2m(x,2*AES_S);
+#endif
+        X->len=MODBYTES_XXX;
+        BIG_XXX_toBytes(X->val,x);
+    }
+    else
+        BIG_XXX_fromBytes(x,X->val);
+
+    if (type==0)
+    {
+        if (!ECP_ZZZ_fromOctet(&P,G)) res=MPIN_INVALID_POINT;
+    }
+    else 
+	{
+		ECP_ZZZ_mapit(&P,G);
+	}
+
+    if (res==0)
+    {
+        PAIR_ZZZ_G1mul(&P,x);
+        ECP_ZZZ_toOctet(W,&P,false);
+    }
+    return res;
+}
+
+/*
+ if RNG == NULL then X is passed in
+ if RNG != NULL the X is passed out
+ W=x*G where G is point on the curve
+ if type==1 W=(x^-1)G
+*/
+
+int MPIN_ZZZ_GET_G2_MULTIPLE(csprng *RNG,int type,octet *X,octet *G,octet *W)
+{
+    ECP4_ZZZ P;
+    BIG_XXX r,x;
+    int res=0;
+    BIG_XXX_rcopy(r,CURVE_Order_ZZZ);
+    if (RNG!=NULL)
+    {
+        BIG_XXX_randomnum(x,r,RNG);
+#ifdef AES_S
+        BIG_XXX_mod2m(x,2*AES_S);
+#endif
+        X->len=MODBYTES_XXX;
+        BIG_XXX_toBytes(X->val,x);
+    }
+    else
+    {
+        BIG_XXX_fromBytes(x,X->val);
+        if (type==1) BIG_XXX_invmodp(x,x,r);
+    }
+
+    if (!ECP4_ZZZ_fromOctet(&P,G)) res=MPIN_INVALID_POINT;
+
+    if (res==0)
+    {
+        PAIR_ZZZ_G2mul(&P,x);
+        ECP4_ZZZ_toOctet(W,&P);
+    }
+    return res;
+}
+
+
+
+/* Client secret CST=s*H(CID) where CID is client ID and s is master secret */
+/* CID is hashed externally */
+int MPIN_ZZZ_GET_CLIENT_SECRET(octet *S,octet *CID,octet *CST)
+{
+    return MPIN_ZZZ_GET_G1_MULTIPLE(NULL,1,S,CID,CST);
+}
+
+/* Implement step 1 on client side of MPin protocol */
+int MPIN_ZZZ_CLIENT_1(int sha,int date,octet *CLIENT_ID,csprng *RNG,octet *X,int pin,octet *TOKEN,octet *SEC,octet *xID,octet *xCID,octet *PERMIT)
+{
+    BIG_XXX r,x;
+    ECP_ZZZ P,T,W;
+    int res=0;
+    char h[MODBYTES_XXX];
+    octet H= {0,sizeof(h),h};
+
+    BIG_XXX_rcopy(r,CURVE_Order_ZZZ);
+    if (RNG!=NULL)
+    {
+        BIG_XXX_randomnum(x,r,RNG);
+#ifdef AES_S
+        BIG_XXX_mod2m(x,2*AES_S);
+#endif
+        X->len=MODBYTES_XXX;
+        BIG_XXX_toBytes(X->val,x);
+    }
+    else
+        BIG_XXX_fromBytes(x,X->val);
+
+    mhashit(sha,-1,CLIENT_ID,&H);
+
+    ECP_ZZZ_mapit(&P,&H);
+
+    if (!ECP_ZZZ_fromOctet(&T,TOKEN)) res=MPIN_INVALID_POINT;
+
+    if (res==0)
+    {
+        pin%=MAXPIN;
+
+        ECP_ZZZ_copy(&W,&P);				// W=H(ID)
+        ECP_ZZZ_pinmul(&W,pin,PBLEN);			// W=alpha.H(ID)
+        ECP_ZZZ_add(&T,&W);					// T=Token+alpha.H(ID) = s.H(ID)
+
+        if (date)
+        {
+            if (PERMIT!=NULL)
+            {
+                if (!ECP_ZZZ_fromOctet(&W,PERMIT)) res=MPIN_INVALID_POINT;
+                ECP_ZZZ_add(&T,&W);					// SEC=s.H(ID)+s.H(T|ID)
+            }
+            mhashit(sha,date,&H,&H);
+
+            ECP_ZZZ_mapit(&W,&H);
+            if (xID!=NULL)
+            {
+                PAIR_ZZZ_G1mul(&P,x);				// P=x.H(ID)
+                ECP_ZZZ_toOctet(xID,&P,false);  // xID
+                PAIR_ZZZ_G1mul(&W,x);               // W=x.H(T|ID)
+                ECP_ZZZ_add(&P,&W); //ECP_ZZZ_affine(&P);
+            }
+            else
+            {
+                ECP_ZZZ_add(&P,&W); //ECP_ZZZ_affine(&P);
+                PAIR_ZZZ_G1mul(&P,x);
+            }
+            if (xCID!=NULL) ECP_ZZZ_toOctet(xCID,&P,false);  // U
+        }
+        else
+        {
+            if (xID!=NULL)
+            {
+                PAIR_ZZZ_G1mul(&P,x);				// P=x.H(ID)
+                ECP_ZZZ_toOctet(xID,&P,false);  // xID
+            }
+        }
+    }
+
+    if (res==0)
+	{
+		//ECP_ZZZ_affine(&T);
+        ECP_ZZZ_toOctet(SEC,&T,false);  // V
+	}
+    return res;
+}
+
+/* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */
+int MPIN_ZZZ_GET_SERVER_SECRET(octet *S,octet *SST)
+{
+    BIG_XXX r,s;
+    ECP4_ZZZ Q;
+    int res=0;
+
+    BIG_XXX_rcopy(r,CURVE_Order_ZZZ);
+
+	ECP4_ZZZ_generator(&Q);
+
+    if (res==0)
+    {
+        BIG_XXX_fromBytes(s,S->val);
+        PAIR_ZZZ_G2mul(&Q,s);
+        ECP4_ZZZ_toOctet(SST,&Q);
+    }
+
+    return res;
+}
+
+
+/* Time Permit CTT=s*H(date|H(CID)) where s is master secret */
+int MPIN_ZZZ_GET_CLIENT_PERMIT(int sha,int date,octet *S,octet *CID,octet *CTT)
+{
+    BIG_XXX s;
+    ECP_ZZZ P;
+    char h[MODBYTES_XXX];
+    octet H= {0,sizeof(h),h};
+
+    mhashit(sha,date,CID,&H);
+
+    ECP_ZZZ_mapit(&P,&H);
+
+//printf("P= "); ECP_ZZZ_output(&P); printf("\n");
+//exit(0);
+
+    BIG_XXX_fromBytes(s,S->val);
+
+
+
+//printf("s= "); BIG_XXX_output(s); printf("\n");
+    PAIR_ZZZ_G1mul(&P,s);
+//printf("OP= "); ECP_ZZZ_output(&P); printf("\n");
+//
+    ECP_ZZZ_toOctet(CTT,&P,false);
+    return 0;
+}
+
+// if date=0 only use HID, set HCID=NULL
+// if date and PE, use HID and HCID
+
+/* Outputs H(CID) and H(CID)+H(T|H(CID)) for time permits. If no time permits set HTID=NULL */
+void MPIN_ZZZ_SERVER_1(int sha,int date,octet *CID,octet *HID,octet *HTID)
+{
+    char h[MODBYTES_XXX];
+    octet H= {0,sizeof(h),h};
+    ECP_ZZZ P,R;
+	BIG_XXX x;
+
+#ifdef USE_ANONYMOUS
+    ECP_ZZZ_mapit(&P,CID);
+#else
+    mhashit(sha,-1,CID,&H);
+    ECP_ZZZ_mapit(&P,&H);
+#endif
+
+    ECP_ZZZ_toOctet(HID,&P,false);  // new
+
+    if (date)
+    {
+        //	if (HID!=NULL) ECP_ZZZ_toOctet(HID,&P,false);
+#ifdef USE_ANONYMOUS
+        mhashit(sha,date,CID,&H);
+#else
+        mhashit(sha,date,&H,&H);
+#endif
+        ECP_ZZZ_mapit(&R,&H);
+        ECP_ZZZ_add(&P,&R); //ECP_ZZZ_affine(&P);
+        ECP_ZZZ_toOctet(HTID,&P,false);
+    }
+    //else ECP_ZZZ_toOctet(HID,&P,false);
+
+}
+
+/* Implement M-Pin on server side */
+int MPIN_ZZZ_SERVER_2(int date,octet *HID,octet *HTID,octet *Y,octet *SST,octet *xID,octet *xCID,octet *mSEC,octet *E,octet *F,octet *Pa)
+{
+    BIG_XXX px,py,y;
+    FP24_YYY g;
+    ECP4_ZZZ Q,sQ;
+    ECP_ZZZ P,R;
+    int res=0;
+
+	ECP4_ZZZ_generator(&Q);
+
+    // key-escrow less scheme: use Pa instead of Q in pairing computation
+    // Q left for backward compatiblity
+    if (Pa!=NULL)
+    {
+        if (!ECP4_ZZZ_fromOctet(&Q, Pa)) res=MPIN_INVALID_POINT;
+    }
+
+
+    if (res==0)
+    {
+        if (!ECP4_ZZZ_fromOctet(&sQ,SST)) res=MPIN_INVALID_POINT;
+    }
+
+    if (res==0)
+    {
+       if (date)
+        {
+            //BIG_XXX_fromBytes(px,&(xCID->val[1]));
+            //BIG_XXX_fromBytes(py,&(xCID->val[PFS_ZZZ+1]));
+			if (!ECP_ZZZ_fromOctet(&R,xCID))  res=MPIN_INVALID_POINT;
+        }
+        else
+        {
+            //BIG_XXX_fromBytes(px,&(xID->val[1]));
+            //BIG_XXX_fromBytes(py,&(xID->val[PFS_ZZZ+1]));
+			if (!ECP_ZZZ_fromOctet(&R,xID))  res=MPIN_INVALID_POINT;
+        }
+        //if (!ECP_ZZZ_set(&R,px,py)) res=MPIN_INVALID_POINT; // x(A+AT)
+    }
+    if (res==0)
+    {
+        BIG_XXX_fromBytes(y,Y->val);
+        if (date)
+        {
+            if (!ECP_ZZZ_fromOctet(&P,HTID))  res=MPIN_INVALID_POINT;
+        }
+        else
+        {
+            if (!ECP_ZZZ_fromOctet(&P,HID))  res=MPIN_INVALID_POINT;
+        }
+    }
+    if (res==0)
+    {
+        PAIR_ZZZ_G1mul(&P,y);  // y(A+AT)
+        ECP_ZZZ_add(&P,&R); // x(A+AT)+y(A+T)
+		//ECP_ZZZ_affine(&P);
+        if (!ECP_ZZZ_fromOctet(&R,mSEC))  res=MPIN_INVALID_POINT; // V
+    }
+    if (res==0)
+    {
+
+        PAIR_ZZZ_double_ate(&g,&Q,&R,&sQ,&P);
+        PAIR_ZZZ_fexp(&g);
+
+        if (!FP24_YYY_isunity(&g))
+        {
+            if (HID!=NULL && xID!=NULL && E!=NULL && F !=NULL)
+            {
+                /* xID is set to NULL if there is no way to calculate PIN error */
+                FP24_YYY_toOctet(E,&g);
+
+                /* Note error is in the PIN, not in the time permit! Hence the need to exclude Time Permit from this check */
+
+                if (date)
+                {
+                    if (!ECP_ZZZ_fromOctet(&P,HID)) res=MPIN_INVALID_POINT;
+                    if (!ECP_ZZZ_fromOctet(&R,xID)) res=MPIN_INVALID_POINT; // U
+
+                    if (res==0)
+                    {
+                        PAIR_ZZZ_G1mul(&P,y);  // yA
+                        ECP_ZZZ_add(&P,&R); // yA+xA
+						//ECP_ZZZ_affine(&P);
+                    }
+                }
+                if (res==0)
+                {
+                    PAIR_ZZZ_ate(&g,&Q,&P);
+                    PAIR_ZZZ_fexp(&g);
+                    FP24_YYY_toOctet(F,&g);
+                }
+            }
+            res=MPIN_BAD_PIN;
+        }
+    }
+
+    return res;
+}
+
+#if MAXPIN==10000
+#define MR_TS 10  /* 2^10/10 approx = sqrt(MAXPIN) */
+#define TRAP 200  /* 2*sqrt(MAXPIN) */
+#endif
+
+#if MAXPIN==1000000
+#define MR_TS 14
+#define TRAP 2000
+#endif
+
+/* Pollards kangaroos used to return PIN error */
+int MPIN_ZZZ_KANGAROO(octet *E,octet *F)
+{
+    int i,j,m,s,dn,dm,steps;
+    int distance[MR_TS];
+    FP24_YYY ge,gf,t,table[MR_TS];
+    int res=0;
+    // BIG_XXX w;
+
+    FP24_YYY_fromOctet(&ge,E);
+    FP24_YYY_fromOctet(&gf,F);
+
+    FP24_YYY_copy(&t,&gf);
+
+    for (s=1,m=0; m<MR_TS; m++)
+    {
+        distance[m]=s;
+        FP24_YYY_copy(&table[m],&t);
+        s*=2;
+        FP24_YYY_usqr(&t,&t);
+        FP24_YYY_reduce(&t);
+    }
+
+    FP24_YYY_one(&t);
+
+    for (dn=0,j=0; j<TRAP; j++)
+    {
+
+        //BIG_XXX_copy(w,t.a.a.a);
+        //FP_YYY_redc(w);
+        //i=BIG_XXX_lastbits(w,20)%MR_TS;
+
+        i=t.a.a.a.a.g[0]%MR_TS;
+
+        FP24_YYY_mul(&t,&table[i]);
+        FP24_YYY_reduce(&t);
+        dn+=distance[i];
+    }
+
+    FP24_YYY_conj(&gf,&t);
+    steps=0;
+    dm=0;
+    while (dm-dn<MAXPIN)
+    {
+        steps++;
+        if (steps>4*TRAP) break;
+
+        //BIG_XXX_copy(w,ge.a.a.a);
+        //FP_YYY_redc(w);
+        //i=BIG_XXX_lastbits(w,20)%MR_TS;
+
+        i=ge.a.a.a.a.g[0]%MR_TS;
+
+        FP24_YYY_mul(&ge,&table[i]);
+        FP24_YYY_reduce(&ge);
+        dm+=distance[i];
+        if (FP24_YYY_equals(&ge,&t))
+        {
+            res=dm-dn;
+            break;
+        }
+        if (FP24_YYY_equals(&ge,&gf))
+        {
+            res=dn-dm;
+            break;
+        }
+    }
+    if (steps>4*TRAP || dm-dn>=MAXPIN)
+    {
+        res=0;    /* Trap Failed  - probable invalid token */
+    }
+
+    return res;
+}
+
+/* Functions to support M-Pin Full */
+
+int MPIN_ZZZ_PRECOMPUTE(octet *TOKEN,octet *CID,octet *CP,octet *G1,octet *G2)
+{
+    ECP_ZZZ P,T;
+    ECP4_ZZZ Q;
+    FP24_YYY g;
+	BIG_XXX x;
+    int res=0;
+
+    if (!ECP_ZZZ_fromOctet(&T,TOKEN)) res=MPIN_INVALID_POINT;
+
+    if (res==0)
+    {
+        ECP_ZZZ_mapit(&P,CID);
+        if (CP!=NULL)
+        {
+            if (!ECP4_ZZZ_fromOctet(&Q,CP)) res=MPIN_INVALID_POINT;
+        }
+        else
+        {
+			ECP4_ZZZ_generator(&Q);
+        }
+    }
+    if (res==0)
+    {
+        PAIR_ZZZ_ate(&g,&Q,&T);
+        PAIR_ZZZ_fexp(&g);
+
+        FP24_YYY_toOctet(G1,&g);
+        if (G2!=NULL)
+        {
+            PAIR_ZZZ_ate(&g,&Q,&P);
+            PAIR_ZZZ_fexp(&g);
+            FP24_YYY_toOctet(G2,&g);
+        }
+    }
+    return res;
+}
+
+/* calculate common key on client side */
+/* wCID = w.(A+AT) */
+int MPIN_ZZZ_CLIENT_KEY(int sha,octet *G1,octet *G2,int pin,octet *R,octet *X,octet *H,octet *wCID,octet *CK)
+{
+    FP24_YYY g1,g2;
+	FP8_YYY c;//,cp,cpm1,cpm2;
+
+    ECP_ZZZ W;
+    int res=0;
+    BIG_XXX r,z,x,h;//q,m,a,b;
+
+    FP24_YYY_fromOctet(&g1,G1);
+    FP24_YYY_fromOctet(&g2,G2);
+    BIG_XXX_fromBytes(z,R->val);
+    BIG_XXX_fromBytes(x,X->val);
+    BIG_XXX_fromBytes(h,H->val);
+
+    if (!ECP_ZZZ_fromOctet(&W,wCID)) res=MPIN_INVALID_POINT;
+
+    if (res==0)
+    {
+        BIG_XXX_rcopy(r,CURVE_Order_ZZZ);
+        BIG_XXX_add(z,z,h);    // new
+        BIG_XXX_mod(z,r);
+
+        FP24_YYY_pinpow(&g2,pin,PBLEN);
+        FP24_YYY_mul(&g1,&g2);
+
+		PAIR_ZZZ_G1mul(&W,x);
+
+		FP24_YYY_compow(&c,&g1,z,r);
+		mpin_hash(sha,&c,&W,CK);
+
+    }
+    return res;
+}
+
+/* calculate common key on server side */
+/* Z=r.A - no time permits involved */
+
+int MPIN_ZZZ_SERVER_KEY(int sha,octet *Z,octet *SST,octet *W,octet *H,octet *HID,octet *xID,octet *xCID,octet *SK)
+{
+    int res=0;
+    FP24_YYY g;
+    FP8_YYY c;
+    ECP_ZZZ R,U,A;
+    ECP4_ZZZ sQ;
+    BIG_XXX w,h;
+
+    if (!ECP4_ZZZ_fromOctet(&sQ,SST)) res=MPIN_INVALID_POINT;
+    if (!ECP_ZZZ_fromOctet(&R,Z)) res=MPIN_INVALID_POINT;
+
+
+    if (!ECP_ZZZ_fromOctet(&A,HID)) res=MPIN_INVALID_POINT;
+
+    // new
+    if (xCID!=NULL)
+    {
+        if (!ECP_ZZZ_fromOctet(&U,xCID)) res=MPIN_INVALID_POINT;
+    }
+    else
+    {
+        if (!ECP_ZZZ_fromOctet(&U,xID)) res=MPIN_INVALID_POINT;
+    }
+    BIG_XXX_fromBytes(w,W->val);
+    BIG_XXX_fromBytes(h,H->val);
+
+
+    PAIR_ZZZ_ate(&g,&sQ,&A);
+    PAIR_ZZZ_fexp(&g);
+
+    if (res==0)
+    {
+        PAIR_ZZZ_G1mul(&A,h);
+        ECP_ZZZ_add(&R,&A);  // new
+		//ECP_ZZZ_affine(&R);
+        PAIR_ZZZ_ate(&g,&sQ,&R);
+        PAIR_ZZZ_fexp(&g);
+        PAIR_ZZZ_G1mul(&U,w);
+        FP24_YYY_trace(&c,&g);
+        mpin_hash(sha,&c,&U,SK);
+    }
+    return res;
+}
+
+/* Generate Y = H(TimeValue, xCID/xID) */
+void MPIN_ZZZ_GET_Y(int sha,int TimeValue,octet *xCID,octet *Y)
+{
+    BIG_XXX q,y;
+    char h[MODBYTES_XXX];
+    octet H= {0,sizeof(h),h};
+
+    mhashit(sha,TimeValue,xCID,&H);
+    BIG_XXX_fromBytes(y,H.val);
+    BIG_XXX_rcopy(q,CURVE_Order_ZZZ);
+    BIG_XXX_mod(y,q);
+    BIG_XXX_toBytes(Y->val,y);
+    Y->len=PGS_ZZZ;
+}
+
+/* One pass MPIN Client */
+int MPIN_ZZZ_CLIENT(int sha,int date,octet *ID,csprng *RNG,octet *X,int pin,octet *TOKEN,octet *V,octet *U,octet *UT,octet *TP,octet *MESSAGE,int TimeValue,octet *Y)
+{
+    int rtn=0;
+    char m[M_SIZE_ZZZ];
+    octet M= {0,sizeof(m),m};
+
+    octet *pID;
+    if (date == 0)
+        pID = U;
+    else
+        pID = UT;
+
+    rtn = MPIN_ZZZ_CLIENT_1(sha,date,ID,RNG,X,pin,TOKEN,V,U,UT,TP);
+    if (rtn != 0)
+        return rtn;
+
+    OCT_joctet(&M,pID);
+   if (MESSAGE!=NULL)
+   {
+       OCT_joctet(&M,MESSAGE);
+   }
+
+    MPIN_ZZZ_GET_Y(sha,TimeValue,&M,Y);
+
+    rtn = MPIN_ZZZ_CLIENT_2(X,Y,V);
+    if (rtn != 0)
+        return rtn;
+
+    return 0;
+}
+
+/* One pass MPIN Server */
+int MPIN_ZZZ_SERVER(int sha,int date,octet *HID,octet *HTID,octet *Y,octet *sQ,octet *U,octet *UT,octet *V,octet *E,octet *F,octet *ID,octet *MESSAGE,int TimeValue, octet *Pa)
+{
+    int rtn=0;
+    char m[M_SIZE_ZZZ];
+    octet M= {0,sizeof(m),m};
+
+    octet *pU;
+    if (date == 0)
+        pU = U;
+    else
+        pU = UT;
+
+    MPIN_ZZZ_SERVER_1(sha,date,ID,HID,HTID);
+
+    OCT_joctet(&M,pU);
+   if (MESSAGE!=NULL)
+   {
+       OCT_joctet(&M,MESSAGE);
+   }
+
+    MPIN_ZZZ_GET_Y(sha,TimeValue,&M,Y);
+
+    rtn = MPIN_ZZZ_SERVER_2(date,HID,HTID,Y,sQ,U,UT,V,E,F,Pa);
+    if (rtn != 0)
+        return rtn;
+
+    return 0;
+}
+
+int MPIN_ZZZ_GET_DVS_KEYPAIR(csprng *R,octet *Z,octet *Pa)
+{
+    BIG_XXX z,r;
+    ECP4_ZZZ Q;
+    int res=0;
+
+    BIG_XXX_rcopy(r,CURVE_Order_ZZZ);
+
+    if (R!=NULL)
+    {
+        BIG_XXX_randomnum(z,r,R);
+        Z->len=MODBYTES_XXX;
+        BIG_XXX_toBytes(Z->val,z);
+    }
+    else
+        BIG_XXX_fromBytes(z,Z->val);
+
+    BIG_XXX_invmodp(z,z,r);
+
+	ECP4_ZZZ_generator(&Q);
+
+    if (res==0)
+    {
+        PAIR_ZZZ_G2mul(&Q,z);
+        ECP4_ZZZ_toOctet(Pa,&Q);
+    }
+
+    return res;
+}
\ No newline at end of file
diff --git a/version3/c/mpin192.h b/version3/c/mpin192.h
new file mode 100644
index 0000000..79f562c
--- /dev/null
+++ b/version3/c/mpin192.h
@@ -0,0 +1,339 @@
+/*
+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.
+*/
+
+/**
+ * @file mpin.h
+ * @author Mike Scott and Kealan McCusker
+ * @date 2nd June 2015
+ * @brief M-Pin Header file
+ *
+ * Allows some user configuration
+ * defines structures
+ * declares functions
+ *
+ */
+
+#ifndef MPIN_ZZZ_H
+#define MPIN_ZZZ_H
+
+#include "pair192_ZZZ.h"
+#include "pbc_support.h"
+
+/* Field size is assumed to be greater than or equal to group size */
+
+#define PGS_ZZZ MODBYTES_XXX  /**< MPIN Group Size */
+#define PFS_ZZZ MODBYTES_XXX  /**< MPIN Field Size */
+
+#define MPIN_OK             0   /**< Function completed without error */
+#define MPIN_INVALID_POINT  -14	/**< Point is NOT on the curve */
+#define MPIN_BAD_PIN        -19 /**< Bad PIN number entered */
+
+#define MAXPIN 10000         /**< max PIN */
+#define PBLEN 14             /**< max length of PIN in bits */
+
+//#define PAS_ZZZ 24        /**< MPIN Symmetric Key Size 192 bits  */
+//#define HASH_TYPE_MPIN_ZZZ SHA384   /**< Choose Hash function */
+
+#define MESSAGE_SIZE 256        /**< Signature message size  */
+#define M_SIZE_ZZZ (MESSAGE_SIZE+2*PFS_ZZZ+1)   /**< Signature message size and G1 size */
+
+
+/* MPIN support functions */
+
+/* MPIN primitives */
+
+
+void MPIN_ZZZ_GET_Y(int h,int t,octet *O,octet *Y);
+/**	@brief Extract a PIN number from a client secret
+ *
+  	@param h is the hash type
+	@param ID is the input client identity
+	@param factor is an input factor
+	@param facbits is the number of bits in the factor
+	@param CS is the client secret from which the factor is to be extracted
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_EXTRACT_FACTOR(int h,octet *ID,int factor,int facbits,octet *CS);
+
+/**	@brief Extract a PIN number from a client secret
+ *
+  	@param h is the hash type
+	@param ID is the input client identity
+	@param factor is an input factor
+	@param facbits is the number of bits in the factor
+	@param CS is the client secret to which the factor is to be added
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_RESTORE_FACTOR(int h,octet *ID,int factor,int facbits,octet *CS);
+
+
+/**	@brief Extract a PIN number from a client secret
+ *
+  	@param h is the hash type
+	@param ID is the input client identity
+	@param pin is an input PIN number
+	@param CS is the client secret from which the PIN is to be extracted
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_EXTRACT_PIN(int h,octet *ID,int pin,octet *CS);
+
+/**	@brief Perform client side of the one-pass version of the M-Pin protocol
+ *
+	If Time Permits are disabled, set d = 0, and UT is not generated and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is OFF, U is not generated and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is ON, U and UT are both generated.
+ 	@param h is the hash type
+	@param d is input date, in days since the epoch. Set to 0 if Time permits disabled
+	@param ID is the input client identity
+	@param R is a pointer to a cryptographically secure random number generator
+	@param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input
+	@param pin is the input PIN number
+	@param T is the input M-Pin token (the client secret with PIN portion removed)
+	@param V is output = -(x+y)(CS+TP), where CS is the reconstructed client secret, and TP is the time permit
+	@param U is output = x.H(ID)
+	@param UT is output = x.(H(ID)+H(d|H(ID)))
+	@param TP is the input time permit
+	@param MESSAGE is the message to be signed
+	@param t is input epoch time in seconds - a timestamp
+	@param y is output H(t|U) or H(t|UT) if Time Permits enabled
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_CLIENT(int h,int d,octet *ID,csprng *R,octet *x,int pin,octet *T,octet *V,octet *U,octet *UT,octet *TP, octet* MESSAGE, int t, octet *y);
+/**	@brief Perform first pass of the client side of the 3-pass version of the M-Pin protocol
+ *
+	If Time Permits are disabled, set d = 0, and UT is not generated and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is OFF, U is not generated and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is ON, U and UT are both generated.
+ 	@param h is the hash type
+	@param d is input date, in days since the epoch. Set to 0 if Time permits disabled
+	@param ID is the input client identity
+	@param R is a pointer to a cryptographically secure random number generator
+	@param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input
+	@param pin is the input PIN number
+	@param T is the input M-Pin token (the client secret with PIN portion removed)
+	@param S is output = CS+TP, where CS=is the reconstructed client secret, and TP is the time permit
+	@param U is output = x.H(ID)
+	@param UT is output = x.(H(ID)+H(d|H(ID)))
+	@param TP is the input time permit
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_CLIENT_1(int h,int d,octet *ID,csprng *R,octet *x,int pin,octet *T,octet *S,octet *U,octet *UT,octet *TP);
+/**	@brief Generate a random group element
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param S is the output random octet
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_RANDOM_GENERATE(csprng *R,octet *S);
+/**	@brief Perform second pass of the client side of the 3-pass version of the M-Pin protocol
+ *
+	@param x an input, a locally generated random number
+	@param y an input random challenge from the server
+	@param V on output = -(x+y).V
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_CLIENT_2(octet *x,octet *y,octet *V);
+/**	@brief Perform server side of the one-pass version of the M-Pin protocol
+ *
+	If Time Permits are disabled, set d = 0, and UT and HTID are not generated and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is OFF, U and HID are not needed and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is ON, U, UT, HID and HTID are all required.
+ 	@param h is the hash type
+	@param d is input date, in days since the epoch. Set to 0 if Time permits disabled
+	@param HID is output H(ID), a hash of the client ID
+	@param HTID is output H(ID)+H(d|H(ID))
+	@param y is output H(t|U) or H(t|UT) if Time Permits enabled
+	@param SS is the input server secret
+	@param U is input from the client = x.H(ID)
+	@param UT is input from the client= x.(H(ID)+H(d|H(ID)))
+	@param V is an input from the client
+	@param E is an output to help the Kangaroos to find the PIN error, or NULL if not required
+	@param F is an output to help the Kangaroos to find the PIN error, or NULL if not required
+	@param ID is the input claimed client identity
+	@param MESSAGE is the message to be signed
+	@param t is input epoch time in seconds - a timestamp
+	@param Pa is input from the client z.Q or NULL if the key-escrow less scheme is not used
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_SERVER(int h,int d,octet *HID,octet *HTID,octet *y,octet *SS,octet *U,octet *UT,octet *V,octet *E,octet *F,octet *ID,octet *MESSAGE, int t, octet *Pa);
+/**	@brief Perform first pass of the server side of the 3-pass version of the M-Pin protocol
+ *
+ 	@param h is the hash type
+	@param d is input date, in days since the epoch. Set to 0 if Time permits disabled
+	@param ID is the input claimed client identity
+	@param HID is output H(ID), a hash of the client ID
+	@param HTID is output H(ID)+H(d|H(ID))
+	@return 0 or an error code
+ */
+void MPIN_ZZZ_SERVER_1(int h,int d,octet *ID,octet *HID,octet *HTID);
+/**	@brief Perform third pass on the server side of the 3-pass version of the M-Pin protocol
+ *
+	If Time Permits are disabled, set d = 0, and UT and HTID are not needed and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is OFF, U and HID are not needed and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is ON, U, UT, HID and HTID are all required.
+	@param d is input date, in days since the epoch. Set to 0 if Time permits disabled
+	@param HID is input H(ID), a hash of the client ID
+	@param HTID is input H(ID)+H(d|H(ID))
+	@param y is the input server's randomly generated challenge
+	@param SS is the input server secret
+	@param U is input from the client = x.H(ID)
+	@param UT is input from the client= x.(H(ID)+H(d|H(ID)))
+	@param V is an input from the client
+	@param E is an output to help the Kangaroos to find the PIN error, or NULL if not required
+	@param F is an output to help the Kangaroos to find the PIN error, or NULL if not required
+	@param Pa is the input public key from the client, z.Q or NULL if the client uses regular mpin
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_SERVER_2(int d,octet *HID,octet *HTID,octet *y,octet *SS,octet *U,octet *UT,octet *V,octet *E,octet *F,octet *Pa);
+/**	@brief Add two members from the group G1
+ *
+	@param Q1 an input member of G1
+	@param Q2 an input member of G1
+	@param Q an output member of G1 = Q1+Q2
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_RECOMBINE_G1(octet *Q1,octet *Q2,octet *Q);
+/**	@brief Add two members from the group G2
+ *
+	@param P1 an input member of G2
+	@param P2 an input member of G2
+	@param P an output member of G2 = P1+P2
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_RECOMBINE_G2(octet *P1,octet *P2,octet *P);
+/**	@brief Use Kangaroos to find PIN error
+ *
+	@param E a member of the group GT
+	@param F a member of the group GT =  E^e
+	@return 0 if Kangaroos failed, or the PIN error e
+ */
+int MPIN_ZZZ_KANGAROO(octet *E,octet *F);
+/**	@brief Encoding of a Time Permit to make it indistinguishable from a random string
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param TP is the input time permit, obfuscated on output
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_ENCODING(csprng *R,octet *TP);
+/**	@brief Encoding of an obfuscated Time Permit
+ *
+	@param TP is the input obfuscated time permit, restored on output
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_DECODING(octet *TP);
+
+/**	@brief Find a random multiple of a point in G1
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param type determines type of action to be taken
+	@param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input
+	@param G if type=0 a point in G1, else an octet to be mapped to G1
+	@param W the output =x.G or x.M(G), where M(.) is a mapping
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_GET_G1_MULTIPLE(csprng *R,int type,octet *x,octet *G,octet *W);
+/**	@brief Find a random multiple of a point in G1
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param type determines type of action to betaken
+	@param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input
+	@param G a point in G2
+	@param W the output =x.G or (1/x).G
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_GET_G2_MULTIPLE(csprng *R,int type,octet *x,octet *G,octet *W);
+
+/**	@brief Create a client secret in G1 from a master secret and the client ID
+ *
+	@param S is an input master secret
+	@param ID is the input client identity
+	@param CS is the full client secret = s.H(ID)
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_GET_CLIENT_SECRET(octet *S,octet *ID,octet *CS);
+/**	@brief Create a Time Permit in G1 from a master secret and the client ID
+ *
+  	@param h is the hash type
+	@param d is input date, in days since the epoch.
+	@param S is an input master secret
+	@param ID is the input client identity
+	@param TP is a Time Permit for the given date = s.H(d|H(ID))
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_GET_CLIENT_PERMIT(int h,int d,octet *S,octet *ID,octet *TP);
+/**	@brief Create a server secret in G2 from a master secret
+ *
+	@param S is an input master secret
+	@param SS is the server secret = s.Q where Q is a fixed generator of G2
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_GET_SERVER_SECRET(octet *S,octet *SS);
+/* int MPIN_TEST_PAIRING(octet *,octet *); */
+
+/* For M-Pin Full */
+/**	@brief Precompute values for use by the client side of M-Pin Full
+ *
+	@param T is the input M-Pin token (the client secret with PIN portion removed)
+	@param ID is the input client identity
+	@param CP is Public Key (or NULL)
+	@param g1 precomputed output
+	@param g2 precomputed output
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_PRECOMPUTE(octet *T,octet *ID,octet *CP,octet *g1,octet *g2);
+/**	@brief Calculate Key on Server side for M-Pin Full
+ *
+	Uses UT internally for the key calculation, unless not available in which case U is used
+ 	@param h is the hash type
+	@param Z is the input Client-side Diffie-Hellman component
+	@param SS is the input server secret
+	@param w is an input random number generated by the server
+	@param p is an input, hash of the protocol transcript
+	@param I is the hashed input client ID = H(ID)
+	@param U is input from the client = x.H(ID)
+	@param UT is input from the client= x.(H(ID)+H(d|H(ID)))
+	@param K is the output calculated shared key
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_SERVER_KEY(int h,octet *Z,octet *SS,octet *w,octet *p,octet *I,octet *U,octet *UT,octet *K);
+/**	@brief Calculate Key on Client side for M-Pin Full
+ *
+  	@param h is the hash type
+	@param g1 precomputed input
+	@param g2 precomputed input
+	@param pin is the input PIN number
+	@param r is an input, a locally generated random number
+	@param x is an input, a locally generated random number
+	@param p is an input, hash of the protocol transcript
+	@param T is the input Server-side Diffie-Hellman component
+	@param K is the output calculated shared key
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_CLIENT_KEY(int h,octet *g1,octet *g2,int pin,octet *r,octet *x,octet *p,octet *T,octet *K);
+
+/** @brief Generates a random public key for the client z.Q
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param Z an output internally randomly generated if R!=NULL, otherwise it must be provided as an input
+	@param Pa the output public key for the client
+ */
+int MPIN_ZZZ_GET_DVS_KEYPAIR(csprng *R,octet *Z,octet *Pa);
+
+#endif
+
diff --git a/version3/c/mpin256.c b/version3/c/mpin256.c
new file mode 100644
index 0000000..47c88d3
--- /dev/null
+++ b/version3/c/mpin256.c
@@ -0,0 +1,998 @@
+/*
+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.
+*/
+
+/* MPIN Functions */
+
+/* Version 3.0 - supports Time Permits */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "mpin256_ZZZ.h"
+
+
+#define ROUNDUP(a,b) ((a)-1)/(b)+1
+
+
+/* Special mpin hashing */
+static void mpin_hash(int sha,FP16_YYY *f, ECP_ZZZ *P,octet *w)
+{
+    int i;
+    BIG_XXX x,y;
+    char h[64];
+    hash256 sha256;
+    hash512 sha512;
+    char t[18*MODBYTES_XXX];  // to hold 10 BIGs
+    int hlen=sha;
+
+	FP_YYY_redc(x,&(f->a.a.a.a));
+    BIG_XXX_toBytes(&t[0],x);
+	FP_YYY_redc(x,&(f->a.a.a.b));
+    BIG_XXX_toBytes(&t[MODBYTES_XXX],x);
+
+    FP_YYY_redc(x,&(f->a.a.b.a));
+    BIG_XXX_toBytes(&t[2*MODBYTES_XXX],x);
+    FP_YYY_redc(x,&(f->a.a.b.b));
+    BIG_XXX_toBytes(&t[3*MODBYTES_XXX],x);
+
+    FP_YYY_redc(x,&(f->a.b.a.a));
+    BIG_XXX_toBytes(&t[4*MODBYTES_XXX],x);
+    FP_YYY_redc(x,&(f->a.b.a.b));
+    BIG_XXX_toBytes(&t[5*MODBYTES_XXX],x);
+
+    FP_YYY_redc(x,&(f->a.b.b.a));
+    BIG_XXX_toBytes(&t[6*MODBYTES_XXX],x);
+    FP_YYY_redc(x,&(f->a.b.b.b));
+    BIG_XXX_toBytes(&t[7*MODBYTES_XXX],x);
+
+	FP_YYY_redc(x,&(f->b.a.a.a));
+    BIG_XXX_toBytes(&t[8*MODBYTES_XXX],x);
+	FP_YYY_redc(x,&(f->b.a.a.b));
+    BIG_XXX_toBytes(&t[9*MODBYTES_XXX],x);
+
+    FP_YYY_redc(x,&(f->b.a.b.a));
+    BIG_XXX_toBytes(&t[10*MODBYTES_XXX],x);
+	FP_YYY_redc(x,&(f->b.a.b.b));
+    BIG_XXX_toBytes(&t[11*MODBYTES_XXX],x);
+
+    FP_YYY_redc(x,&(f->b.b.a.a));
+    BIG_XXX_toBytes(&t[12*MODBYTES_XXX],x);
+    FP_YYY_redc(x,&(f->b.b.a.b));
+    BIG_XXX_toBytes(&t[13*MODBYTES_XXX],x);
+
+    FP_YYY_redc(x,&(f->b.b.b.a));
+    BIG_XXX_toBytes(&t[14*MODBYTES_XXX],x);
+    FP_YYY_redc(x,&(f->b.b.b.b));
+    BIG_XXX_toBytes(&t[15*MODBYTES_XXX],x);
+
+    ECP_ZZZ_get(x,y,P);
+    BIG_XXX_toBytes(&t[16*MODBYTES_XXX],x);
+    BIG_XXX_toBytes(&t[17*MODBYTES_XXX],y);
+
+    OCT_empty(w);
+    switch (sha)
+    {
+    case SHA256:
+        HASH256_init(&sha256);
+        for (i=0; i<18*MODBYTES_XXX; i++) HASH256_process(&sha256,t[i]);
+        HASH256_hash(&sha256,h);
+        break;
+    case SHA384:
+        HASH384_init(&sha512);
+        for (i=0; i<18*MODBYTES_XXX; i++) HASH384_process(&sha512,t[i]);
+        HASH384_hash(&sha512,h);
+        break;
+    case SHA512:
+        HASH512_init(&sha512);
+        for (i=0; i<18*MODBYTES_XXX; i++) HASH512_process(&sha512,t[i]);
+        HASH512_hash(&sha512,h);
+        break;
+    }
+
+    OCT_jbytes(w,h,AESKEY_ZZZ);
+    for (i=0; i<hlen; i++) h[i]=0;
+}
+
+/* these next two functions help to implement elligator squared - http://eprint.iacr.org/2014/043 */
+/* maps a random u to a point on the curve */
+static void map(ECP_ZZZ *P,BIG_XXX u,int cb)
+{
+    BIG_XXX x,q;
+
+    BIG_XXX_rcopy(q,Modulus_YYY);
+    BIG_XXX_copy(x,u);
+    BIG_XXX_mod(x,q);
+
+    while (!ECP_ZZZ_setx(P,x,cb))
+	{
+        BIG_XXX_inc(x,1); BIG_XXX_norm(x);
+	}
+}
+
+/* returns u derived from P. Random value in range 1 to return value should then be added to u */
+static int unmap(BIG_XXX u,int *cb,ECP_ZZZ *P)
+{
+    int s,r=0;
+    BIG_XXX x;
+
+    s=ECP_ZZZ_get(x,x,P);
+    BIG_XXX_copy(u,x);
+    do
+    {
+        BIG_XXX_dec(u,1); BIG_XXX_norm(u);
+        r++;
+    }
+    while (!ECP_ZZZ_setx(P,u,s));
+    ECP_ZZZ_setx(P,x,s);
+
+    *cb=s;
+
+    return r;
+}
+
+/* these next two functions implement elligator squared - http://eprint.iacr.org/2014/043 */
+/* Elliptic curve point E in format (0x04,x,y} is converted to form {0x0-,u,v} */
+/* Note that u and v are indistinguisible from random strings */
+int MPIN_ZZZ_ENCODING(csprng *RNG,octet *E)
+{
+    int rn,m,su,sv,res=0;
+
+    BIG_XXX q,u,v;
+    ECP_ZZZ P,W;
+
+    if (!ECP_ZZZ_fromOctet(&P,E)) res=MPIN_INVALID_POINT;
+    if (res==0)
+    {
+        BIG_XXX_rcopy(q,Modulus_YYY);
+
+        BIG_XXX_randomnum(u,q,RNG);
+
+        su=RAND_byte(RNG);
+        if (su<0) su=-su;
+        su%=2;
+        map(&W,u,su);
+        ECP_ZZZ_sub(&P,&W); //ECP_ZZZ_affine(&P);
+
+        rn=unmap(v,&sv,&P);
+        m=RAND_byte(RNG);
+        if (m<0) m=-m;
+        m%=rn;
+        BIG_XXX_inc(v,m+1);
+        E->val[0]=su+2*sv;
+        BIG_XXX_toBytes(&(E->val[1]),u);
+        BIG_XXX_toBytes(&(E->val[PFS_ZZZ+1]),v);
+    }
+    return res;
+}
+
+int MPIN_ZZZ_DECODING(octet *D)
+{
+    int su,sv;
+    BIG_XXX u,v;
+    ECP_ZZZ P,W;
+    int res=0;
+
+    if ((D->val[0]&0x04)!=0) res=MPIN_INVALID_POINT;
+    if (res==0)
+    {
+
+        BIG_XXX_fromBytes(u,&(D->val[1]));
+        BIG_XXX_fromBytes(v,&(D->val[PFS_ZZZ+1]));
+
+        su=D->val[0]&1;
+        sv=(D->val[0]>>1)&1;
+        map(&W,u,su);
+        map(&P,v,sv);
+        ECP_ZZZ_add(&P,&W); //ECP_ZZZ_affine(&P);
+        ECP_ZZZ_toOctet(D,&P,false);
+    }
+
+    return res;
+}
+
+/* R=R1+R2 in group G1 */
+int MPIN_ZZZ_RECOMBINE_G1(octet *R1,octet *R2,octet *R)
+{
+    ECP_ZZZ P,T;
+    int res=0;
+    if (res==0)
+    {
+        if (!ECP_ZZZ_fromOctet(&P,R1)) res=MPIN_INVALID_POINT;
+        if (!ECP_ZZZ_fromOctet(&T,R2)) res=MPIN_INVALID_POINT;
+    }
+    if (res==0)
+    {
+        ECP_ZZZ_add(&P,&T); //ECP_ZZZ_affine(&P);
+        ECP_ZZZ_toOctet(R,&P,false);
+    }
+    return res;
+}
+
+/* W=W1+W2 in group G2 */
+int MPIN_ZZZ_RECOMBINE_G2(octet *W1,octet *W2,octet *W)
+{
+    ECP8_ZZZ Q,T;
+    int res=0;
+    if (!ECP8_ZZZ_fromOctet(&Q,W1)) res=MPIN_INVALID_POINT;
+    if (!ECP8_ZZZ_fromOctet(&T,W2)) res=MPIN_INVALID_POINT;
+    if (res==0)
+    {
+        ECP8_ZZZ_add(&Q,&T); //ECP8_ZZZ_affine(&Q);
+        ECP8_ZZZ_toOctet(W,&Q);
+    }
+    return res;
+}
+
+/* create random secret S */
+int MPIN_ZZZ_RANDOM_GENERATE(csprng *RNG,octet* S)
+{
+    BIG_XXX r,s;
+
+    BIG_XXX_rcopy(r,CURVE_Order_ZZZ);
+    BIG_XXX_randomnum(s,r,RNG);
+#ifdef AES_S
+    BIG_XXX_mod2m(s,2*AES_S);
+#endif
+    BIG_XXX_toBytes(S->val,s);
+    S->len=MODBYTES_XXX;
+    return 0;
+}
+
+/* Extract PIN from TOKEN for identity CID */
+int MPIN_ZZZ_EXTRACT_PIN(int sha,octet *CID,int pin,octet *TOKEN)
+{
+	pin%=MAXPIN;
+	return MPIN_ZZZ_EXTRACT_FACTOR(sha,CID,pin,PBLEN,TOKEN);
+}
+
+/* Extract a factor < 32 bits for identity CID */
+int MPIN_ZZZ_EXTRACT_FACTOR(int sha,octet *CID,int factor,int facbits,octet *TOKEN)
+{
+    ECP_ZZZ P,R;
+    int res=0;
+    char h[MODBYTES_XXX];
+    octet H= {0,sizeof(h),h};
+
+    if (!ECP_ZZZ_fromOctet(&P,TOKEN))  res=MPIN_INVALID_POINT;
+    if (res==0)
+    {
+        mhashit(sha,-1,CID,&H);
+        ECP_ZZZ_mapit(&R,&H);
+
+        ECP_ZZZ_pinmul(&R,factor,facbits);
+        ECP_ZZZ_sub(&P,&R); //ECP_ZZZ_affine(&P);
+
+        ECP_ZZZ_toOctet(TOKEN,&P,false);
+    }
+    return res;
+}
+
+/* Extract a factor < 32 bits for identity CID */
+int MPIN_ZZZ_RESTORE_FACTOR(int sha,octet *CID,int factor,int facbits,octet *TOKEN)
+{
+    ECP_ZZZ P,R;
+    int res=0;
+    char h[MODBYTES_XXX];
+    octet H= {0,sizeof(h),h};
+
+    if (!ECP_ZZZ_fromOctet(&P,TOKEN))  res=MPIN_INVALID_POINT;
+    if (res==0)
+    {
+        mhashit(sha,-1,CID,&H);
+        ECP_ZZZ_mapit(&R,&H);
+
+        ECP_ZZZ_pinmul(&R,factor,facbits);
+        ECP_ZZZ_add(&P,&R); //ECP_ZZZ_affine(&P);
+
+        ECP_ZZZ_toOctet(TOKEN,&P,false);
+    }
+    return res;
+}
+
+/* Implement step 2 on client side of MPin protocol - SEC=-(x+y)*SEC */
+int MPIN_ZZZ_CLIENT_2(octet *X,octet *Y,octet *SEC)
+{
+    BIG_XXX px,py,r;
+    ECP_ZZZ P;
+    int res=0;
+    BIG_XXX_rcopy(r,CURVE_Order_ZZZ);
+    if (!ECP_ZZZ_fromOctet(&P,SEC)) res=MPIN_INVALID_POINT;
+    if (res==0)
+    {
+        BIG_XXX_fromBytes(px,X->val);
+        BIG_XXX_fromBytes(py,Y->val);
+        BIG_XXX_add(px,px,py);
+        BIG_XXX_mod(px,r);
+        //	BIG_XXX_sub(px,r,px);
+        PAIR_ZZZ_G1mul(&P,px);
+        ECP_ZZZ_neg(&P);
+        ECP_ZZZ_toOctet(SEC,&P,false);
+    }
+    return res;
+}
+
+/*
+ W=x*H(G);
+ if RNG == NULL then X is passed in
+ if RNG != NULL the X is passed out
+ if type=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve
+*/
+
+int MPIN_ZZZ_GET_G1_MULTIPLE(csprng *RNG,int type,octet *X,octet *G,octet *W)
+{
+    ECP_ZZZ P;
+    BIG_XXX r,x;
+    int res=0;
+    if (RNG!=NULL)
+    {
+        BIG_XXX_rcopy(r,CURVE_Order_ZZZ);
+        BIG_XXX_randomnum(x,r,RNG);
+#ifdef AES_S
+        BIG_XXX_mod2m(x,2*AES_S);
+#endif
+        X->len=MODBYTES_XXX;
+        BIG_XXX_toBytes(X->val,x);
+    }
+    else
+        BIG_XXX_fromBytes(x,X->val);
+
+    if (type==0)
+    {
+        if (!ECP_ZZZ_fromOctet(&P,G)) res=MPIN_INVALID_POINT;
+    }
+    else 
+	{
+		ECP_ZZZ_mapit(&P,G);
+	}
+
+    if (res==0)
+    {
+        PAIR_ZZZ_G1mul(&P,x);
+        ECP_ZZZ_toOctet(W,&P,false);
+    }
+    return res;
+}
+
+/*
+ if RNG == NULL then X is passed in
+ if RNG != NULL the X is passed out
+ W=x*G where G is point on the curve
+ if type==1 W=(x^-1)G
+*/
+
+int MPIN_ZZZ_GET_G2_MULTIPLE(csprng *RNG,int type,octet *X,octet *G,octet *W)
+{
+    ECP8_ZZZ P;
+    BIG_XXX r,x;
+    int res=0;
+    BIG_XXX_rcopy(r,CURVE_Order_ZZZ);
+    if (RNG!=NULL)
+    {
+        BIG_XXX_randomnum(x,r,RNG);
+#ifdef AES_S
+        BIG_XXX_mod2m(x,2*AES_S);
+#endif
+        X->len=MODBYTES_XXX;
+        BIG_XXX_toBytes(X->val,x);
+    }
+    else
+    {
+        BIG_XXX_fromBytes(x,X->val);
+        if (type==1) BIG_XXX_invmodp(x,x,r);
+    }
+
+    if (!ECP8_ZZZ_fromOctet(&P,G)) res=MPIN_INVALID_POINT;
+
+    if (res==0)
+    {
+        PAIR_ZZZ_G2mul(&P,x);
+        ECP8_ZZZ_toOctet(W,&P);
+    }
+    return res;
+}
+
+
+
+/* Client secret CST=s*H(CID) where CID is client ID and s is master secret */
+/* CID is hashed externally */
+int MPIN_ZZZ_GET_CLIENT_SECRET(octet *S,octet *CID,octet *CST)
+{
+    return MPIN_ZZZ_GET_G1_MULTIPLE(NULL,1,S,CID,CST);
+}
+
+/* Implement step 1 on client side of MPin protocol */
+int MPIN_ZZZ_CLIENT_1(int sha,int date,octet *CLIENT_ID,csprng *RNG,octet *X,int pin,octet *TOKEN,octet *SEC,octet *xID,octet *xCID,octet *PERMIT)
+{
+    BIG_XXX r,x;
+    ECP_ZZZ P,T,W;
+    int res=0;
+    char h[MODBYTES_XXX];
+    octet H= {0,sizeof(h),h};
+
+    BIG_XXX_rcopy(r,CURVE_Order_ZZZ);
+    if (RNG!=NULL)
+    {
+        BIG_XXX_randomnum(x,r,RNG);
+#ifdef AES_S
+        BIG_XXX_mod2m(x,2*AES_S);
+#endif
+        X->len=MODBYTES_XXX;
+        BIG_XXX_toBytes(X->val,x);
+    }
+    else
+        BIG_XXX_fromBytes(x,X->val);
+
+    mhashit(sha,-1,CLIENT_ID,&H);
+
+    ECP_ZZZ_mapit(&P,&H);
+
+    if (!ECP_ZZZ_fromOctet(&T,TOKEN)) res=MPIN_INVALID_POINT;
+
+    if (res==0)
+    {
+        pin%=MAXPIN;
+
+        ECP_ZZZ_copy(&W,&P);				// W=H(ID)
+        ECP_ZZZ_pinmul(&W,pin,PBLEN);			// W=alpha.H(ID)
+        ECP_ZZZ_add(&T,&W);					// T=Token+alpha.H(ID) = s.H(ID)
+
+        if (date)
+        {
+            if (PERMIT!=NULL)
+            {
+                if (!ECP_ZZZ_fromOctet(&W,PERMIT)) res=MPIN_INVALID_POINT;
+                ECP_ZZZ_add(&T,&W);					// SEC=s.H(ID)+s.H(T|ID)
+            }
+            mhashit(sha,date,&H,&H);
+
+            ECP_ZZZ_mapit(&W,&H);
+            if (xID!=NULL)
+            {
+                PAIR_ZZZ_G1mul(&P,x);				// P=x.H(ID)
+                ECP_ZZZ_toOctet(xID,&P,false);  // xID
+                PAIR_ZZZ_G1mul(&W,x);               // W=x.H(T|ID)
+                ECP_ZZZ_add(&P,&W); //ECP_ZZZ_affine(&P);
+            }
+            else
+            {
+                ECP_ZZZ_add(&P,&W); //ECP_ZZZ_affine(&P);
+                PAIR_ZZZ_G1mul(&P,x);
+            }
+            if (xCID!=NULL) ECP_ZZZ_toOctet(xCID,&P,false);  // U
+        }
+        else
+        {
+            if (xID!=NULL)
+            {
+                PAIR_ZZZ_G1mul(&P,x);				// P=x.H(ID)
+                ECP_ZZZ_toOctet(xID,&P,false);  // xID
+            }
+        }
+    }
+
+    if (res==0)
+	{
+		//ECP_ZZZ_affine(&T);
+        ECP_ZZZ_toOctet(SEC,&T,false);  // V
+	}
+    return res;
+}
+
+/* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */
+int MPIN_ZZZ_GET_SERVER_SECRET(octet *S,octet *SST)
+{
+    BIG_XXX r,s;
+    ECP8_ZZZ Q;
+    int res=0;
+
+    BIG_XXX_rcopy(r,CURVE_Order_ZZZ);
+
+	ECP8_ZZZ_generator(&Q);
+
+    if (res==0)
+    {
+        BIG_XXX_fromBytes(s,S->val);
+        PAIR_ZZZ_G2mul(&Q,s);
+        ECP8_ZZZ_toOctet(SST,&Q);
+    }
+
+    return res;
+}
+
+
+/* Time Permit CTT=s*H(date|H(CID)) where s is master secret */
+int MPIN_ZZZ_GET_CLIENT_PERMIT(int sha,int date,octet *S,octet *CID,octet *CTT)
+{
+    BIG_XXX s;
+    ECP_ZZZ P;
+    char h[MODBYTES_XXX];
+    octet H= {0,sizeof(h),h};
+
+    mhashit(sha,date,CID,&H);
+
+    ECP_ZZZ_mapit(&P,&H);
+
+//printf("P= "); ECP_ZZZ_output(&P); printf("\n");
+//exit(0);
+
+    BIG_XXX_fromBytes(s,S->val);
+
+
+
+//printf("s= "); BIG_XXX_output(s); printf("\n");
+    PAIR_ZZZ_G1mul(&P,s);
+//printf("OP= "); ECP_ZZZ_output(&P); printf("\n");
+//
+    ECP_ZZZ_toOctet(CTT,&P,false);
+    return 0;
+}
+
+// if date=0 only use HID, set HCID=NULL
+// if date and PE, use HID and HCID
+
+/* Outputs H(CID) and H(CID)+H(T|H(CID)) for time permits. If no time permits set HTID=NULL */
+void MPIN_ZZZ_SERVER_1(int sha,int date,octet *CID,octet *HID,octet *HTID)
+{
+    char h[MODBYTES_XXX];
+    octet H= {0,sizeof(h),h};
+    ECP_ZZZ P,R;
+	BIG_XXX x;
+
+#ifdef USE_ANONYMOUS
+    ECP_ZZZ_mapit(&P,CID);
+#else
+    mhashit(sha,-1,CID,&H);
+    ECP_ZZZ_mapit(&P,&H);
+#endif
+
+    ECP_ZZZ_toOctet(HID,&P,false);  // new
+
+    if (date)
+    {
+        //	if (HID!=NULL) ECP_ZZZ_toOctet(HID,&P,false);
+#ifdef USE_ANONYMOUS
+        mhashit(sha,date,CID,&H);
+#else
+        mhashit(sha,date,&H,&H);
+#endif
+        ECP_ZZZ_mapit(&R,&H);
+        ECP_ZZZ_add(&P,&R); //ECP_ZZZ_affine(&P);
+        ECP_ZZZ_toOctet(HTID,&P,false);
+    }
+    //else ECP_ZZZ_toOctet(HID,&P,false);
+
+}
+
+/* Implement M-Pin on server side */
+int MPIN_ZZZ_SERVER_2(int date,octet *HID,octet *HTID,octet *Y,octet *SST,octet *xID,octet *xCID,octet *mSEC,octet *E,octet *F,octet *Pa)
+{
+    BIG_XXX px,py,y;
+    FP48_YYY g;
+    ECP8_ZZZ Q,sQ;
+    ECP_ZZZ P,R;
+    int res=0;
+
+	ECP8_ZZZ_generator(&Q);
+
+    // key-escrow less scheme: use Pa instead of Q in pairing computation
+    // Q left for backward compatiblity
+    if (Pa!=NULL)
+    {
+        if (!ECP8_ZZZ_fromOctet(&Q, Pa)) res=MPIN_INVALID_POINT;
+    }
+
+
+    if (res==0)
+    {
+        if (!ECP8_ZZZ_fromOctet(&sQ,SST)) res=MPIN_INVALID_POINT;
+    }
+
+    if (res==0)
+    {
+       if (date)
+        {
+            //BIG_XXX_fromBytes(px,&(xCID->val[1]));
+            //BIG_XXX_fromBytes(py,&(xCID->val[PFS_ZZZ+1]));
+			if (!ECP_ZZZ_fromOctet(&R,xCID))  res=MPIN_INVALID_POINT;
+        }
+        else
+        {
+            //BIG_XXX_fromBytes(px,&(xID->val[1]));
+            //BIG_XXX_fromBytes(py,&(xID->val[PFS_ZZZ+1]));
+			if (!ECP_ZZZ_fromOctet(&R,xID))  res=MPIN_INVALID_POINT;
+        }
+        //if (!ECP_ZZZ_set(&R,px,py)) res=MPIN_INVALID_POINT; // x(A+AT)
+    }
+    if (res==0)
+    {
+        BIG_XXX_fromBytes(y,Y->val);
+        if (date)
+        {
+            if (!ECP_ZZZ_fromOctet(&P,HTID))  res=MPIN_INVALID_POINT;
+        }
+        else
+        {
+            if (!ECP_ZZZ_fromOctet(&P,HID))  res=MPIN_INVALID_POINT;
+        }
+    }
+    if (res==0)
+    {
+        PAIR_ZZZ_G1mul(&P,y);  // y(A+AT)
+        ECP_ZZZ_add(&P,&R); // x(A+AT)+y(A+T)
+		//ECP_ZZZ_affine(&P);
+        if (!ECP_ZZZ_fromOctet(&R,mSEC))  res=MPIN_INVALID_POINT; // V
+    }
+    if (res==0)
+    {
+
+        PAIR_ZZZ_double_ate(&g,&Q,&R,&sQ,&P);
+        PAIR_ZZZ_fexp(&g);
+
+        if (!FP48_YYY_isunity(&g))
+        {
+            if (HID!=NULL && xID!=NULL && E!=NULL && F !=NULL)
+            {
+                /* xID is set to NULL if there is no way to calculate PIN error */
+                FP48_YYY_toOctet(E,&g);
+
+                /* Note error is in the PIN, not in the time permit! Hence the need to exclude Time Permit from this check */
+
+                if (date)
+                {
+                    if (!ECP_ZZZ_fromOctet(&P,HID)) res=MPIN_INVALID_POINT;
+                    if (!ECP_ZZZ_fromOctet(&R,xID)) res=MPIN_INVALID_POINT; // U
+
+                    if (res==0)
+                    {
+                        PAIR_ZZZ_G1mul(&P,y);  // yA
+                        ECP_ZZZ_add(&P,&R); // yA+xA
+						//ECP_ZZZ_affine(&P);
+                    }
+                }
+                if (res==0)
+                {
+                    PAIR_ZZZ_ate(&g,&Q,&P);
+                    PAIR_ZZZ_fexp(&g);
+                    FP48_YYY_toOctet(F,&g);
+                }
+            }
+            res=MPIN_BAD_PIN;
+        }
+    }
+
+    return res;
+}
+
+#if MAXPIN==10000
+#define MR_TS 10  /* 2^10/10 approx = sqrt(MAXPIN) */
+#define TRAP 200  /* 2*sqrt(MAXPIN) */
+#endif
+
+#if MAXPIN==1000000
+#define MR_TS 14
+#define TRAP 2000
+#endif
+
+/* Pollards kangaroos used to return PIN error */
+int MPIN_ZZZ_KANGAROO(octet *E,octet *F)
+{
+    int i,j,m,s,dn,dm,steps;
+    int distance[MR_TS];
+    FP48_YYY ge,gf,t,table[MR_TS];
+    int res=0;
+    // BIG_XXX w;
+
+    FP48_YYY_fromOctet(&ge,E);
+    FP48_YYY_fromOctet(&gf,F);
+
+    FP48_YYY_copy(&t,&gf);
+
+    for (s=1,m=0; m<MR_TS; m++)
+    {
+        distance[m]=s;
+        FP48_YYY_copy(&table[m],&t);
+        s*=2;
+        FP48_YYY_usqr(&t,&t);
+        FP48_YYY_reduce(&t);
+    }
+
+    FP48_YYY_one(&t);
+
+    for (dn=0,j=0; j<TRAP; j++)
+    {
+
+        //BIG_XXX_copy(w,t.a.a.a);
+        //FP_YYY_redc(w);
+        //i=BIG_XXX_lastbits(w,20)%MR_TS;
+
+        i=t.a.a.a.a.a.g[0]%MR_TS;
+
+        FP48_YYY_mul(&t,&table[i]);
+        FP48_YYY_reduce(&t);
+        dn+=distance[i];
+    }
+
+    FP48_YYY_conj(&gf,&t);
+    steps=0;
+    dm=0;
+    while (dm-dn<MAXPIN)
+    {
+        steps++;
+        if (steps>4*TRAP) break;
+
+        //BIG_XXX_copy(w,ge.a.a.a);
+        //FP_YYY_redc(w);
+        //i=BIG_XXX_lastbits(w,20)%MR_TS;
+
+        i=ge.a.a.a.a.a.g[0]%MR_TS;
+
+        FP48_YYY_mul(&ge,&table[i]);
+        FP48_YYY_reduce(&ge);
+        dm+=distance[i];
+        if (FP48_YYY_equals(&ge,&t))
+        {
+            res=dm-dn;
+            break;
+        }
+        if (FP48_YYY_equals(&ge,&gf))
+        {
+            res=dn-dm;
+            break;
+        }
+    }
+    if (steps>4*TRAP || dm-dn>=MAXPIN)
+    {
+        res=0;    /* Trap Failed  - probable invalid token */
+    }
+
+    return res;
+}
+
+/* Functions to support M-Pin Full */
+
+int MPIN_ZZZ_PRECOMPUTE(octet *TOKEN,octet *CID,octet *CP,octet *G1,octet *G2)
+{
+    ECP_ZZZ P,T;
+    ECP8_ZZZ Q;
+    FP48_YYY g;
+	BIG_XXX x;
+    int res=0;
+
+    if (!ECP_ZZZ_fromOctet(&T,TOKEN)) res=MPIN_INVALID_POINT;
+
+    if (res==0)
+    {
+        ECP_ZZZ_mapit(&P,CID);
+        if (CP!=NULL)
+        {
+            if (!ECP8_ZZZ_fromOctet(&Q,CP)) res=MPIN_INVALID_POINT;
+        }
+        else
+        {
+			ECP8_ZZZ_generator(&Q);
+        }
+    }
+    if (res==0)
+    {
+        PAIR_ZZZ_ate(&g,&Q,&T);
+        PAIR_ZZZ_fexp(&g);
+
+        FP48_YYY_toOctet(G1,&g);
+        if (G2!=NULL)
+        {
+            PAIR_ZZZ_ate(&g,&Q,&P);
+            PAIR_ZZZ_fexp(&g);
+            FP48_YYY_toOctet(G2,&g);
+        }
+    }
+    return res;
+}
+
+/* calculate common key on client side */
+/* wCID = w.(A+AT) */
+int MPIN_ZZZ_CLIENT_KEY(int sha,octet *G1,octet *G2,int pin,octet *R,octet *X,octet *H,octet *wCID,octet *CK)
+{
+    FP48_YYY g1,g2;
+	FP16_YYY c;//,cp,cpm1,cpm2;
+
+    ECP_ZZZ W;
+    int res=0;
+    BIG_XXX r,z,x,h;//q,m,a,b;
+
+    FP48_YYY_fromOctet(&g1,G1);
+    FP48_YYY_fromOctet(&g2,G2);
+    BIG_XXX_fromBytes(z,R->val);
+    BIG_XXX_fromBytes(x,X->val);
+    BIG_XXX_fromBytes(h,H->val);
+
+    if (!ECP_ZZZ_fromOctet(&W,wCID)) res=MPIN_INVALID_POINT;
+
+    if (res==0)
+    {
+        BIG_XXX_rcopy(r,CURVE_Order_ZZZ);
+        BIG_XXX_add(z,z,h);    // new
+        BIG_XXX_mod(z,r);
+
+        FP48_YYY_pinpow(&g2,pin,PBLEN);
+        FP48_YYY_mul(&g1,&g2);
+
+		PAIR_ZZZ_G1mul(&W,x);
+
+		FP48_YYY_compow(&c,&g1,z,r);
+		mpin_hash(sha,&c,&W,CK);
+
+    }
+    return res;
+}
+
+/* calculate common key on server side */
+/* Z=r.A - no time permits involved */
+
+int MPIN_ZZZ_SERVER_KEY(int sha,octet *Z,octet *SST,octet *W,octet *H,octet *HID,octet *xID,octet *xCID,octet *SK)
+{
+    int res=0;
+    FP48_YYY g;
+    FP16_YYY c;
+    ECP_ZZZ R,U,A;
+    ECP8_ZZZ sQ;
+    BIG_XXX w,h;
+
+    if (!ECP8_ZZZ_fromOctet(&sQ,SST)) res=MPIN_INVALID_POINT;
+    if (!ECP_ZZZ_fromOctet(&R,Z)) res=MPIN_INVALID_POINT;
+
+
+    if (!ECP_ZZZ_fromOctet(&A,HID)) res=MPIN_INVALID_POINT;
+
+    // new
+    if (xCID!=NULL)
+    {
+        if (!ECP_ZZZ_fromOctet(&U,xCID)) res=MPIN_INVALID_POINT;
+    }
+    else
+    {
+        if (!ECP_ZZZ_fromOctet(&U,xID)) res=MPIN_INVALID_POINT;
+    }
+    BIG_XXX_fromBytes(w,W->val);
+    BIG_XXX_fromBytes(h,H->val);
+
+
+    PAIR_ZZZ_ate(&g,&sQ,&A);
+    PAIR_ZZZ_fexp(&g);
+
+    if (res==0)
+    {
+        PAIR_ZZZ_G1mul(&A,h);
+        ECP_ZZZ_add(&R,&A);  // new
+		//ECP_ZZZ_affine(&R);
+        PAIR_ZZZ_ate(&g,&sQ,&R);
+        PAIR_ZZZ_fexp(&g);
+        PAIR_ZZZ_G1mul(&U,w);
+        FP48_YYY_trace(&c,&g);
+        mpin_hash(sha,&c,&U,SK);
+    }
+    return res;
+}
+
+/* Generate Y = H(TimeValue, xCID/xID) */
+void MPIN_ZZZ_GET_Y(int sha,int TimeValue,octet *xCID,octet *Y)
+{
+    BIG_XXX q,y;
+    char h[MODBYTES_XXX];
+    octet H= {0,sizeof(h),h};
+
+    mhashit(sha,TimeValue,xCID,&H);
+    BIG_XXX_fromBytes(y,H.val);
+    BIG_XXX_rcopy(q,CURVE_Order_ZZZ);
+    BIG_XXX_mod(y,q);
+    BIG_XXX_toBytes(Y->val,y);
+    Y->len=PGS_ZZZ;
+}
+
+/* One pass MPIN Client */
+int MPIN_ZZZ_CLIENT(int sha,int date,octet *ID,csprng *RNG,octet *X,int pin,octet *TOKEN,octet *V,octet *U,octet *UT,octet *TP,octet *MESSAGE,int TimeValue,octet *Y)
+{
+    int rtn=0;
+    char m[M_SIZE_ZZZ];
+    octet M= {0,sizeof(m),m};
+
+    octet *pID;
+    if (date == 0)
+        pID = U;
+    else
+        pID = UT;
+
+    rtn = MPIN_ZZZ_CLIENT_1(sha,date,ID,RNG,X,pin,TOKEN,V,U,UT,TP);
+    if (rtn != 0)
+        return rtn;
+
+    OCT_joctet(&M,pID);
+   if (MESSAGE!=NULL)
+   {
+       OCT_joctet(&M,MESSAGE);
+   }
+
+    MPIN_ZZZ_GET_Y(sha,TimeValue,&M,Y);
+
+    rtn = MPIN_ZZZ_CLIENT_2(X,Y,V);
+    if (rtn != 0)
+        return rtn;
+
+    return 0;
+}
+
+/* One pass MPIN Server */
+int MPIN_ZZZ_SERVER(int sha,int date,octet *HID,octet *HTID,octet *Y,octet *sQ,octet *U,octet *UT,octet *V,octet *E,octet *F,octet *ID,octet *MESSAGE,int TimeValue, octet *Pa)
+{
+    int rtn=0;
+    char m[M_SIZE_ZZZ];
+    octet M= {0,sizeof(m),m};
+
+    octet *pU;
+    if (date == 0)
+        pU = U;
+    else
+        pU = UT;
+
+    MPIN_ZZZ_SERVER_1(sha,date,ID,HID,HTID);
+
+    OCT_joctet(&M,pU);
+   if (MESSAGE!=NULL)
+   {
+       OCT_joctet(&M,MESSAGE);
+   }
+
+    MPIN_ZZZ_GET_Y(sha,TimeValue,&M,Y);
+
+    rtn = MPIN_ZZZ_SERVER_2(date,HID,HTID,Y,sQ,U,UT,V,E,F,Pa);
+    if (rtn != 0)
+        return rtn;
+
+    return 0;
+}
+
+int MPIN_ZZZ_GET_DVS_KEYPAIR(csprng *R,octet *Z,octet *Pa)
+{
+    BIG_XXX z,r;
+    ECP8_ZZZ Q;
+    int res=0;
+
+    BIG_XXX_rcopy(r,CURVE_Order_ZZZ);
+
+    if (R!=NULL)
+    {
+        BIG_XXX_randomnum(z,r,R);
+        Z->len=MODBYTES_XXX;
+        BIG_XXX_toBytes(Z->val,z);
+    }
+    else
+        BIG_XXX_fromBytes(z,Z->val);
+
+    BIG_XXX_invmodp(z,z,r);
+
+	ECP8_ZZZ_generator(&Q);
+
+    if (res==0)
+    {
+        PAIR_ZZZ_G2mul(&Q,z);
+        ECP8_ZZZ_toOctet(Pa,&Q);
+    }
+
+    return res;
+}
diff --git a/version3/c/mpin256.h b/version3/c/mpin256.h
new file mode 100644
index 0000000..46ba21a
--- /dev/null
+++ b/version3/c/mpin256.h
@@ -0,0 +1,339 @@
+/*
+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.
+*/
+
+/**
+ * @file mpin.h
+ * @author Mike Scott and Kealan McCusker
+ * @date 2nd June 2015
+ * @brief M-Pin Header file
+ *
+ * Allows some user configuration
+ * defines structures
+ * declares functions
+ *
+ */
+
+#ifndef MPIN_ZZZ_H
+#define MPIN_ZZZ_H
+
+#include "pair256_ZZZ.h"
+#include "pbc_support.h"
+
+
+/* Field size is assumed to be greater than or equal to group size */
+
+#define PGS_ZZZ MODBYTES_XXX  /**< MPIN Group Size */
+#define PFS_ZZZ MODBYTES_XXX  /**< MPIN Field Size */
+
+#define MPIN_OK             0   /**< Function completed without error */
+#define MPIN_INVALID_POINT  -14	/**< Point is NOT on the curve */
+#define MPIN_BAD_PIN        -19 /**< Bad PIN number entered */
+
+#define MAXPIN 10000         /**< max PIN */
+#define PBLEN 14             /**< max length of PIN in bits */
+
+//#define PAS_ZZZ 24        /**< MPIN Symmetric Key Size 192 bits  */
+//#define HASH_TYPE_MPIN_ZZZ SHA384   /**< Choose Hash function */
+
+#define MESSAGE_SIZE 256        /**< Signature message size  */
+#define M_SIZE_ZZZ (MESSAGE_SIZE+2*PFS_ZZZ+1)   /**< Signature message size and G1 size */
+
+/* MPIN support functions */
+
+/* MPIN primitives */
+
+
+void MPIN_ZZZ_GET_Y(int h,int t,octet *O,octet *Y);
+/**	@brief Extract a PIN number from a client secret
+ *
+  	@param h is the hash type
+	@param ID is the input client identity
+	@param factor is an input factor
+	@param facbits is the number of bits in the factor
+	@param CS is the client secret from which the factor is to be extracted
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_EXTRACT_FACTOR(int h,octet *ID,int factor,int facbits,octet *CS);
+
+/**	@brief Extract a PIN number from a client secret
+ *
+  	@param h is the hash type
+	@param ID is the input client identity
+	@param factor is an input factor
+	@param facbits is the number of bits in the factor
+	@param CS is the client secret to which the factor is to be added
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_RESTORE_FACTOR(int h,octet *ID,int factor,int facbits,octet *CS);
+
+
+/**	@brief Extract a PIN number from a client secret
+ *
+  	@param h is the hash type
+	@param ID is the input client identity
+	@param pin is an input PIN number
+	@param CS is the client secret from which the PIN is to be extracted
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_EXTRACT_PIN(int h,octet *ID,int pin,octet *CS);
+
+/**	@brief Perform client side of the one-pass version of the M-Pin protocol
+ *
+	If Time Permits are disabled, set d = 0, and UT is not generated and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is OFF, U is not generated and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is ON, U and UT are both generated.
+ 	@param h is the hash type
+	@param d is input date, in days since the epoch. Set to 0 if Time permits disabled
+	@param ID is the input client identity
+	@param R is a pointer to a cryptographically secure random number generator
+	@param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input
+	@param pin is the input PIN number
+	@param T is the input M-Pin token (the client secret with PIN portion removed)
+	@param V is output = -(x+y)(CS+TP), where CS is the reconstructed client secret, and TP is the time permit
+	@param U is output = x.H(ID)
+	@param UT is output = x.(H(ID)+H(d|H(ID)))
+	@param TP is the input time permit
+	@param MESSAGE is the message to be signed
+	@param t is input epoch time in seconds - a timestamp
+	@param y is output H(t|U) or H(t|UT) if Time Permits enabled
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_CLIENT(int h,int d,octet *ID,csprng *R,octet *x,int pin,octet *T,octet *V,octet *U,octet *UT,octet *TP, octet* MESSAGE, int t, octet *y);
+/**	@brief Perform first pass of the client side of the 3-pass version of the M-Pin protocol
+ *
+	If Time Permits are disabled, set d = 0, and UT is not generated and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is OFF, U is not generated and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is ON, U and UT are both generated.
+ 	@param h is the hash type
+	@param d is input date, in days since the epoch. Set to 0 if Time permits disabled
+	@param ID is the input client identity
+	@param R is a pointer to a cryptographically secure random number generator
+	@param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input
+	@param pin is the input PIN number
+	@param T is the input M-Pin token (the client secret with PIN portion removed)
+	@param S is output = CS+TP, where CS=is the reconstructed client secret, and TP is the time permit
+	@param U is output = x.H(ID)
+	@param UT is output = x.(H(ID)+H(d|H(ID)))
+	@param TP is the input time permit
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_CLIENT_1(int h,int d,octet *ID,csprng *R,octet *x,int pin,octet *T,octet *S,octet *U,octet *UT,octet *TP);
+/**	@brief Generate a random group element
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param S is the output random octet
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_RANDOM_GENERATE(csprng *R,octet *S);
+/**	@brief Perform second pass of the client side of the 3-pass version of the M-Pin protocol
+ *
+	@param x an input, a locally generated random number
+	@param y an input random challenge from the server
+	@param V on output = -(x+y).V
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_CLIENT_2(octet *x,octet *y,octet *V);
+/**	@brief Perform server side of the one-pass version of the M-Pin protocol
+ *
+	If Time Permits are disabled, set d = 0, and UT and HTID are not generated and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is OFF, U and HID are not needed and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is ON, U, UT, HID and HTID are all required.
+ 	@param h is the hash type
+	@param d is input date, in days since the epoch. Set to 0 if Time permits disabled
+	@param HID is output H(ID), a hash of the client ID
+	@param HTID is output H(ID)+H(d|H(ID))
+	@param y is output H(t|U) or H(t|UT) if Time Permits enabled
+	@param SS is the input server secret
+	@param U is input from the client = x.H(ID)
+	@param UT is input from the client= x.(H(ID)+H(d|H(ID)))
+	@param V is an input from the client
+	@param E is an output to help the Kangaroos to find the PIN error, or NULL if not required
+	@param F is an output to help the Kangaroos to find the PIN error, or NULL if not required
+	@param ID is the input claimed client identity
+	@param MESSAGE is the message to be signed
+	@param t is input epoch time in seconds - a timestamp
+	@param Pa is input from the client z.Q or NULL if the key-escrow less scheme is not used
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_SERVER(int h,int d,octet *HID,octet *HTID,octet *y,octet *SS,octet *U,octet *UT,octet *V,octet *E,octet *F,octet *ID,octet *MESSAGE, int t, octet *Pa);
+/**	@brief Perform first pass of the server side of the 3-pass version of the M-Pin protocol
+ *
+ 	@param h is the hash type
+	@param d is input date, in days since the epoch. Set to 0 if Time permits disabled
+	@param ID is the input claimed client identity
+	@param HID is output H(ID), a hash of the client ID
+	@param HTID is output H(ID)+H(d|H(ID))
+	@return 0 or an error code
+ */
+void MPIN_ZZZ_SERVER_1(int h,int d,octet *ID,octet *HID,octet *HTID);
+/**	@brief Perform third pass on the server side of the 3-pass version of the M-Pin protocol
+ *
+	If Time Permits are disabled, set d = 0, and UT and HTID are not needed and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is OFF, U and HID are not needed and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is ON, U, UT, HID and HTID are all required.
+	@param d is input date, in days since the epoch. Set to 0 if Time permits disabled
+	@param HID is input H(ID), a hash of the client ID
+	@param HTID is input H(ID)+H(d|H(ID))
+	@param y is the input server's randomly generated challenge
+	@param SS is the input server secret
+	@param U is input from the client = x.H(ID)
+	@param UT is input from the client= x.(H(ID)+H(d|H(ID)))
+	@param V is an input from the client
+	@param E is an output to help the Kangaroos to find the PIN error, or NULL if not required
+	@param F is an output to help the Kangaroos to find the PIN error, or NULL if not required
+	@param Pa is the input public key from the client, z.Q or NULL if the client uses regular mpin
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_SERVER_2(int d,octet *HID,octet *HTID,octet *y,octet *SS,octet *U,octet *UT,octet *V,octet *E,octet *F,octet *Pa);
+/**	@brief Add two members from the group G1
+ *
+	@param Q1 an input member of G1
+	@param Q2 an input member of G1
+	@param Q an output member of G1 = Q1+Q2
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_RECOMBINE_G1(octet *Q1,octet *Q2,octet *Q);
+/**	@brief Add two members from the group G2
+ *
+	@param P1 an input member of G2
+	@param P2 an input member of G2
+	@param P an output member of G2 = P1+P2
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_RECOMBINE_G2(octet *P1,octet *P2,octet *P);
+/**	@brief Use Kangaroos to find PIN error
+ *
+	@param E a member of the group GT
+	@param F a member of the group GT =  E^e
+	@return 0 if Kangaroos failed, or the PIN error e
+ */
+int MPIN_ZZZ_KANGAROO(octet *E,octet *F);
+/**	@brief Encoding of a Time Permit to make it indistinguishable from a random string
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param TP is the input time permit, obfuscated on output
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_ENCODING(csprng *R,octet *TP);
+/**	@brief Encoding of an obfuscated Time Permit
+ *
+	@param TP is the input obfuscated time permit, restored on output
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_DECODING(octet *TP);
+
+/**	@brief Find a random multiple of a point in G1
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param type determines type of action to be taken
+	@param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input
+	@param G if type=0 a point in G1, else an octet to be mapped to G1
+	@param W the output =x.G or x.M(G), where M(.) is a mapping
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_GET_G1_MULTIPLE(csprng *R,int type,octet *x,octet *G,octet *W);
+/**	@brief Find a random multiple of a point in G1
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param type determines type of action to betaken
+	@param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input
+	@param G a point in G2
+	@param W the output =x.G or (1/x).G
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_GET_G2_MULTIPLE(csprng *R,int type,octet *x,octet *G,octet *W);
+
+/**	@brief Create a client secret in G1 from a master secret and the client ID
+ *
+	@param S is an input master secret
+	@param ID is the input client identity
+	@param CS is the full client secret = s.H(ID)
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_GET_CLIENT_SECRET(octet *S,octet *ID,octet *CS);
+/**	@brief Create a Time Permit in G1 from a master secret and the client ID
+ *
+  	@param h is the hash type
+	@param d is input date, in days since the epoch.
+	@param S is an input master secret
+	@param ID is the input client identity
+	@param TP is a Time Permit for the given date = s.H(d|H(ID))
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_GET_CLIENT_PERMIT(int h,int d,octet *S,octet *ID,octet *TP);
+/**	@brief Create a server secret in G2 from a master secret
+ *
+	@param S is an input master secret
+	@param SS is the server secret = s.Q where Q is a fixed generator of G2
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_GET_SERVER_SECRET(octet *S,octet *SS);
+/* int MPIN_TEST_PAIRING(octet *,octet *); */
+
+/* For M-Pin Full */
+/**	@brief Precompute values for use by the client side of M-Pin Full
+ *
+	@param T is the input M-Pin token (the client secret with PIN portion removed)
+	@param ID is the input client identity
+	@param CP is Public Key (or NULL)
+	@param g1 precomputed output
+	@param g2 precomputed output
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_PRECOMPUTE(octet *T,octet *ID,octet *CP,octet *g1,octet *g2);
+/**	@brief Calculate Key on Server side for M-Pin Full
+ *
+	Uses UT internally for the key calculation, unless not available in which case U is used
+ 	@param h is the hash type
+	@param Z is the input Client-side Diffie-Hellman component
+	@param SS is the input server secret
+	@param w is an input random number generated by the server
+	@param p is an input, hash of the protocol transcript
+	@param I is the hashed input client ID = H(ID)
+	@param U is input from the client = x.H(ID)
+	@param UT is input from the client= x.(H(ID)+H(d|H(ID)))
+	@param K is the output calculated shared key
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_SERVER_KEY(int h,octet *Z,octet *SS,octet *w,octet *p,octet *I,octet *U,octet *UT,octet *K);
+/**	@brief Calculate Key on Client side for M-Pin Full
+ *
+  	@param h is the hash type
+	@param g1 precomputed input
+	@param g2 precomputed input
+	@param pin is the input PIN number
+	@param r is an input, a locally generated random number
+	@param x is an input, a locally generated random number
+	@param p is an input, hash of the protocol transcript
+	@param T is the input Server-side Diffie-Hellman component
+	@param K is the output calculated shared key
+	@return 0 or an error code
+ */
+int MPIN_ZZZ_CLIENT_KEY(int h,octet *g1,octet *g2,int pin,octet *r,octet *x,octet *p,octet *T,octet *K);
+
+/** @brief Generates a random public key for the client z.Q
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param Z an output internally randomly generated if R!=NULL, otherwise it must be provided as an input
+	@param Pa the output public key for the client
+ */
+int MPIN_ZZZ_GET_DVS_KEYPAIR(csprng *R,octet *Z,octet *Pa);
+
+#endif
+
diff --git a/version3/c/newhope.c b/version3/c/newhope.c
new file mode 100644
index 0000000..2203648
--- /dev/null
+++ b/version3/c/newhope.c
@@ -0,0 +1,513 @@
+/*
+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.
+*/
+
+/* NewHope API implementation. Constant time.
+
+	LOOK - no if statements!
+
+   M.Scott 21/07/2017
+*/
+
+#include "newhope.h"
+
+const sign16 roots[] ={0x2ac8,0x2baf,0x299b,0x685,0x2f04,0x158d,0x2d49,0x24b5,0x1edc,0xab3,0x2a95,0x24d,0x3cb,0x6a8,0x12f9,0x15ba,0x1861,0x2a89,0x1c5c,0xbe6,0xc1e,0x2024,0x207,0x19ce,0x2710,0x1744,0x18bc,0x2cd7,0x396,0x18d5,0x1c45,0xc4,0x21a6,0xe03,0x2b3c,0x2d91,0xc5d,0x432,0x1fbc,0xcae,0x2512,0x2979,0x3b2,0x714,0xb2e,0x1a97,0x1a03,0x1bcd,0x2216,0x2701,0xa,0x263c,0x1179,0x200c,0x2d08,0x1c34,0x291,0x2c99,0x2a5a,0x723,0xb1d,0x1ccc,0x1fb6,0x2f58,0x2bfe,0x1cda,0x2a0,0x5f1,0x2de,0x1fc7,0x1ea8,0x1719,0x2fa7,0x27ec,0x20ff,0x12c0,0x1ac1,0x2232,0x2f9b,0xd3e,0x2aed,0x15f0,0x11e8,0xed0,0x26a,0x1de5,0xa3f,0xf43,0xebf,0x204e,0xac7,0x2d9c,0x5ea,0x25d1,0xb6,0x49c,0x995,0x2555,0x26e2,0x100,0x1878,0x5aa,0x2e10,0x271c,0xcb,0x1b4c,0x2fb8,0x25b7,0x1543,0x2c7b,0x241a,0x2223,0x20ca,0x24ed,0x137,0x1b65,0x1dc2,0x7c7,0x2ec3,0xd0c,0x1169,0x1c7a,0x1ea1,0xf89,0x2199,0x291d,0x1088,0x2046,0x256d,0x2bc7,0x2e9b,0x41f,0x1b55,0x2b38,0xd0,0x2e6a,0x1755,0x6bc,0x2724,0x3ba,0x222e,0x2c5c,0x2da5,0x213c,0x10fe,0x169a,0x1552,0x5d3,0x300,0x1b5d,0x1342,0x2004,0x256f,0x2039,0x667,0x23b5,0x1123,0xdb,0x2da0,0xe1e,0x2f54,0x2767,0x154a,0x40a,0x11d3,0x2821,0xc09,0x974,0x694,0xfbf,0x27ba,0x132,0x83f,0x2d06,0x10e,0x183f,0x29ae,0x28c3,0x2dc9,0x1144,0x2c70,0x2a4a,0xf3c,0x1e32,0x1171,0x1e43,0xdd4,0x2ddf,0x28d2,0xfac,0x3c4,0x2f19,0x10a6,0x2f7,0xe1d,0x828,0x138f,0x1332,0xfab,0xcf6,0x13f8,0x24a0,0x112d,0x2717,0x6e7,0x1044,0x36e,0xfe8,0x6a,0xba7,0x1d69,0x29ec,0x23b2,0xaee,0x16df,0x1068,0x1a7e,0x253f,0x24c,0xb33,0x2683,0x15ce,0x1ad3,0x1a36,0xc96,0xaea,0x260a,0xce,0x28b1,0xe4f,0x2b11,0x5f8,0x1fc4,0xe77,0x2366,0x11f9,0x153c,0x24eb,0x20cd,0x1398,0x22,0x2b97,0x249b,0x8eb,0x12b2,0x2fe3,0x29c1,0x1b00,0x2663,0xeaa,0x2e06,0xe0,0x1569,0x10f5,0x284e,0xa38,0x201d,0x1c53,0x1681,0x1f6f,0x2f95,0x2fe8,0xacb,0x1680,0x17fd,0x2c39,0x165a,0x10bb,0x29d8,0x2622,0x1196,0x884,0x2a79,0x140e,0x2d80,0x6fa,0x11b2,0x26c4,0x355,0x1054,0x29e9,0x23ed,0xbe3,0x24fa,0x1fb3,0x10ac,0x2919,0x2584,0x10a4,0xe85,0x650,0x1893,0x1dc1,0xd8e,0x12dc,0x2d42,0x284d,0xfff,0x250f,0xacd,0x13c3,0x6cc,0x1a79,0x1221,0x2614,0x270a,0x1ea,0x155,0x2818,0x222c,0x2e5b,0x25d8,0x1dbf,0x191c,0xb0f,0xdac,0x1082,0x12ef,0x11b6,0xfa8,0x2b72,0x159d,0x209e,0x31b,0x2c7c,0x14f7,0xe09,0x1bb2,0x1ec7,0x2404,0x20ae,0x6ad,0xed6,0x2b70,0x1c7b,0x18d1,0x2732,0x12da,0xd56,0x5c1,0x1648,0x18b7,0x1605,0x1bc4,0x280,0x2ece,0xc,0x1aae,0x1c4,0x1cdb,0x22d6,0x21d8,0x257c,0x51f,0x211b,0xff,0x2ee0,0x2585,0xe1,0x2c35,0x26db,0x2971,0x2208,0x17e1,0x21be,0x135e,0x28d6,0x2891,0x1689,0x2138,0xb86,0x2e3a,0x1204,0x2d10,0x2324,0xf3f,0x2508,0x33d,0xcb2,0x292a,0xe27,0x2e64,0x29f8,0x2d46,0x9b7,0x20eb,0x1b7c,0x9eb,0x2b2a,0x58c,0x27d0,0x121b,0x272e,0x29f6,0x2dbd,0x2697,0x2aac,0xd6f,0x1c67,0x2c5b,0x108d,0x363,0x249d,0x2d5e,0x2fd,0x2cb2,0x1f8f,0x20a4,0xa19,0x2ac9,0x19b1,0x1581,0x17a2,0x29eb,0x1b72,0x13b0,0xee4,0xa8f,0x2315,0x5e6,0x951,0x2e29,0xdad,0x1f2b,0x224e,0x37f,0x1a72,0xa91,0x1407,0x2df9,0x3ad,0x23f7,0x1a24,0x1d2a,0x234b,0x1df3,0x1143,0x7ff,0x1a6d,0x2774,0x2690,0x2ab5,0x586,0x2781,0x2009,0x2fdd,0x2881,0x399,0x2fb6,0x144,0x137f,0xfa0,0x2e4c,0x1c7f,0x2fac,0xb09,0x1264,0x127b,0x198c,0x2b40,0x230,0x1cf4,0x180b,0xb58,0x144a,0x2aec,0xfb,0x2602,0x14ee,0x783,0x1098,0x23d8,0x203,0xe9,0x108a,0x14b8,0xeec,0xc58,0x1248,0x243c,0x28aa,0x6bf,0x27c4,0x276e,0x19b8,0x1d11,0x2e16,0x472,0x1464,0x24b9,0x662,0x1097,0x2067,0x20d6,0x171c,0x4,0x682,0x17bb,0x1186,0x4f2,0x3ff,0x2a43,0x1dc7,0x1ae5,0x8cc,0x2e7c,0x2ef8,0x2ae0,0x2904,0xed4,0x6c5,0x14ae,0xb72,0x11c3,0x337,0x2da3,0x2916,0x6d8,0x1cf9,0x10ee,0x1800,0x1ae4,0xa0d,0x101b,0x1a8d,0x2e98,0x24cd,0x813,0x1aa4,0x9b9,0x680,0x2349,0x24d1,0x20f8,0xe31,0x249f,0x216b,0x12d9,0x1d21,0x19db,0x191a,0x1dd0,0x5df,0x55c,0x2b86,0x213,0xe9e,0x1ef1,0x268a,0x1d5e,0x1e20,0x28c1,0x1379,0x249,0x19de,0x18b,0x1e41,0x2a1e,0x2612,0x297,0x2e96,0x2102,0x46,0x1b9f,0x1a4d,0x2050,0x1b32,0x568,0x11f7,0x1829,0x870,0x1f4,0x1dca,0x990,0x1df6,0x2b62,0x13ec,0x9f2,0x1260,0x2997,0x1412,0x1e6d,0x1694,0x11ac,0x2d8b,0x276f,0x26f5,0x233e,0x2b44,0x2f5a,0x2d37,0x2cb1,0xc75,0x98d,0x1d56,0x7ae,0x10e6,0x113f,0x17b8,0xad3,0x737,0x221e,0x1b70,0x1f3e,0x2966,0x18b2,0x4fa,0x2044,0x1312,0x154e,0x2029,0x700,0x1b45,0x27a6,0x226a,0x21bf,0x58d,0x2f11,0x2e02,0x17fc,0x4d2,0x1757,0xcb1,0x2ef1,0x2582,0x1276,0x881,0x2fc0,0x104a,0x670,0x274f,0x2b53,0x19dd,0x752,0x1663,0xcbd,0x2b2b,0x2fc6,0x13b6,0x21e6,0x15f6,0x126b,0x2637,0x1cd9,0x2f50,0xe82,0x5b0,0x24e0,0x1350,0x2f24,0x21f7,0x1a16,0x2f3e,0x167e,0x1f7d,0x28a0,0x16f0,0xe33,0x53b,0x28c5,0x1500,0x2f88,0x26cc,0x2018,0x1604,0x218b,0x2cd1,0x9ee,0x17f3,0x5fd,0x1f5a,0x2d0,0x2b46,0x23cc,0x503,0x1c46,0x1cc3,0x28e2,0x243e,0x122b,0x2e0c,0xe37,0x2611,0x85e,0x9b8,0x1b24,0x762,0x19b6,0x3bc,0x2d50,0x2079,0x18da,0x170a,0x800,0xaa2,0x135a,0x1a15,0x13d1,0xca,0x2113,0x2db9,0xdb2,0x1a5c,0x29a9,0x1488,0x14c1,0x2c9,0x917,0x28e7,0x265c,0xdab,0x2ab9,0x2bc6,0x105b,0x1839,0x219c,0x50,0x11da,0x1802,0xf56,0x2e6,0x2190,0xddb,0x56e,0x9d9,0x1c81,0x1016,0x12d6,0x296f,0x14b4,0x1014,0x1e64,0x1d90,0x89f,0x2bc2,0x2777,0x2819,0x1c65,0x1a41,0x5a2,0x2cd2,0x427,0xd71,0x29c8,0x1e58,0x53f,0x7c5,0x1dcd,0x4a1,0x1268,0x2597,0x2926,0xee,0x111b,0x1038,0xe6c,0x22dc,0x2f2f,0x441,0x2cfd,0x1cb0,0x6a4,0x2224,0x620,0x5dc,0x16b1,0x2a1d,0x1787,0x20c7,0x641,0xd84,0x1c05,0x2d0d,0x2f52,0x1b8c,0xd7d,0x17e8,0x1589,0xc73,0x151b,0x4e2,0x1ae9,0x1b18,0xb9b,0x949,0x2c60,0x1e7a,0xd5,0x1bdc,0x1f57,0x1753,0x124a,0x559,0xb76,0x2334,0x12d1,0x1de1,0x14b2,0x2faa,0x1697,0x147a,0x5a1,0x2c30,0x1c02,0x1043,0x2ee1,0x2402,0x1cc8,0x2a16,0xff7,0x1364,0x1b9a,0x2a53,0x2f94,0x294c,0x1ee5,0x1a87,0x2141,0xd66,0x953,0x28a3,0x2f30,0x2477,0x18e3,0x1035,0x1fc1,0x1d68,0x2fb3,0x138c,0x2487,0x1bf8,0xd96,0x1018,0x748,0x244e,0x15bd,0x175e,0x2be,0x23d,0x1da,0x176d,0xc17,0x24be,0x2ebb,0x7d8,0x100a,0x759,0x1db4,0x2259,0x23f4,0x2d59,0x2847,0xbf5,0x1cfe,0xa20,0x258,0x1180,0x279c,0x54,0x2abf,0xc5c,0x9f9,0x3d5,0x2ce4,0x165f,0x23d9,0x27b9,0x6f9,0x281a,0x169e,0x627,0x156d,0x1ff8,0x211,0x2e34,0x1724,0x2c2e,0x2790,0x2dd5,0x2bf2,0xdbc,0x2884,0x20a9,0x2390,0x1e1a,0x1b6a,0x5f7,0xab7,0x1333,0x16ab,0x28dd,0x20,0x30f,0x24b6,0x5c2,0x1ce4,0x1400,0x2669,0x60,0x156c,0xe20,0x26d4,0x26ab,0x1ebb,0x223d,0x5b4,0x2025,0x1e1c,0xaae,0x2e08,0x6cd,0x1677,0x13d9,0x17b5,0x1046,0x1d8c,0x14eb,0x18d8,0x1ce5,0x2478,0x16ae,0xb79,0x23d4,0x684,0x156b,0x567,0x1a,0x29ce,0x83a,0x19e8,0x58e,0x294a,0x1136,0x2319,0x2fba,0x1a29,0x1d,0x1879,0x291b,0x19f6,0x2c2f,0x21c9,0x19bb,0xbbc,0x26f9,0xc22,0x708,0x11a1,0x18d3,0x7f8,0x28f8,0x2427,0x1deb,0xaed,0x26aa,0x2482,0x203b,0x2f05,0x2b82,0x192f,0x2df4,0x8dc,0x2877,0xd5e,0x240e,0x775,0x2dae,0x1d3e,0x20ba,0x215b,0x22d1,0xeba,0xf50,0xaa8,0x184a,0x1f67,0x2e04,0xc6e,0x6dd,0x1a09,0x27f,0x494,0x1426,0xae3,0xe15,0x65f,0x13c4,0x105,0x872,0x2667,0x1ff6,0xd9f,0x2ca1,0x2f39,0x2657,0x23fd,0x2405,0xb73,0x2294,0x1f1e,0x2eba,0x110a,0x2cae,0x141f,0x22cd,0x25d6,0x11c1,0x1c,0x2d8e,0x161a,0x1aa8,0x229e,0x1bf9,0x7cf,0x106d,0x2c40,0xd93,0x255e,0x28c2,0xc1a,0x2f17,0x7ca,0x2f63,0xbf};
+const sign16 iroots[]= {0x2ac8,0x452,0x297c,0x666,0xb4c,0x2b8,0x1a74,0xfd,0x1a47,0x1d08,0x2959,0x2c36,0x2db4,0x56c,0x254e,0x1125,0x2f3d,0x13bc,0x172c,0x2c6b,0x32a,0x1745,0x18bd,0x8f1,0x1633,0x2dfa,0xfdd,0x23e3,0x241b,0x13a5,0x578,0x17a0,0xa9,0x104b,0x1335,0x24e4,0x28de,0x5a7,0x368,0x2d70,0x13cd,0x2f9,0xff5,0x1e88,0x9c5,0x2ff7,0x900,0xdeb,0x1434,0x15fe,0x156a,0x24d3,0x28ed,0x2c4f,0x688,0xaef,0x2353,0x1045,0x2bcf,0x23a4,0x270,0x4c5,0x21fe,0xe5b,0xfbb,0x1f79,0x6e4,0xe68,0x2078,0x1160,0x1387,0x1e98,0x22f5,0x13e,0x283a,0x123f,0x149c,0x2eca,0xb14,0xf37,0xdde,0xbe7,0x386,0x1abe,0xa4a,0x49,0x14b5,0x2f36,0x8e5,0x1f1,0x2a57,0x1789,0x2f01,0x91f,0xaac,0x266c,0x2b65,0x2f4b,0xa30,0x2a17,0x265,0x253a,0xfb3,0x2142,0x20be,0x25c2,0x121c,0x2d97,0x2131,0x1e19,0x1a11,0x514,0x22c3,0x66,0xdcf,0x1540,0x1d41,0xf02,0x815,0x5a,0x18e8,0x1159,0x103a,0x2d23,0x2a10,0x2d61,0x1327,0x403,0x25c9,0x7b3,0x1f0c,0x1a98,0x2f21,0x1fb,0x2157,0x99e,0x1501,0x640,0x1e,0x1d4f,0x2716,0xb66,0x46a,0x2fdf,0x1c69,0xf34,0xb16,0x1ac5,0x1e08,0xc9b,0x218a,0x103d,0x2a09,0x4f0,0x21b2,0x750,0x2f33,0x9f7,0x2517,0x236b,0x15cb,0x152e,0x1a33,0x97e,0x24ce,0x2db5,0xac2,0x1583,0x1f99,0x1922,0x2513,0xc4f,0x615,0x1298,0x245a,0x2f97,0x2019,0x2c93,0x1fbd,0x291a,0x8ea,0x1ed4,0xb61,0x1c09,0x230b,0x2056,0x1ccf,0x1c72,0x27d9,0x21e4,0x2d0a,0x1f5b,0xe8,0x2c3d,0x2055,0x72f,0x222,0x222d,0x11be,0x1e90,0x11cf,0x20c5,0x5b7,0x391,0x1ebd,0x238,0x73e,0x653,0x17c2,0x2ef3,0x2fb,0x27c2,0x2ecf,0x847,0x2042,0x296d,0x268d,0x23f8,0x7e0,0x1e2e,0x2bf7,0x1ab7,0x89a,0xad,0x21e3,0x261,0x2f26,0x1ede,0xc4c,0x299a,0xfc8,0xa92,0xffd,0x1cbf,0x14a4,0x2d01,0x2a2e,0x1aaf,0x1967,0x1f03,0xec5,0x25c,0x3a5,0xdd3,0x2c47,0x8dd,0x2945,0x18ac,0x197,0x2f31,0x4c9,0x14ac,0x2be2,0x166,0x43a,0xa94,0x1b53,0x293c,0x212d,0x6fd,0x521,0x109,0x185,0x2735,0x151c,0x123a,0x5be,0x2c02,0x2b0f,0x1e7b,0x1846,0x297f,0x2ffd,0x18e5,0xf2b,0xf9a,0x1f6a,0x299f,0xb48,0x1b9d,0x2b8f,0x1eb,0x12f0,0x1649,0x893,0x83d,0x2942,0x757,0xbc5,0x1db9,0x23a9,0x2115,0x1b49,0x1f77,0x2f18,0x2dfe,0xc29,0x1f69,0x287e,0x1b13,0x9ff,0x2f06,0x515,0x1bb7,0x24a9,0x17f6,0x130d,0x2dd1,0x4c1,0x1675,0x1d86,0x1d9d,0x24f8,0x55,0x1382,0x1b5,0x2061,0x1c82,0x2ebd,0x4b,0x2c68,0x780,0x24,0xff8,0x880,0x2a7b,0x54c,0x971,0x88d,0x1594,0x2802,0x1ebe,0x120e,0xcb6,0x12d7,0x15dd,0xc0a,0x2c54,0x208,0x1bfa,0x2570,0x158f,0x2c82,0xdb3,0x10d6,0x2254,0x1d8,0x26b0,0x2a1b,0xcec,0x2572,0x211d,0x1c51,0x148f,0x616,0x185f,0x1a80,0x1650,0x538,0x25e8,0xf5d,0x1072,0x34f,0x2d04,0x2a3,0xb64,0x2c9e,0x1f74,0x3a6,0x139a,0x2292,0x555,0x96a,0x244,0x60b,0x8d3,0x1de6,0x831,0x2a75,0x4d7,0x2616,0x1485,0xf16,0x264a,0x2bb,0x609,0x19d,0x21da,0x6d7,0x234f,0x2cc4,0xaf9,0x20c2,0xcdd,0x2f1,0x1dfd,0x1c7,0x247b,0xec9,0x1978,0x770,0x72b,0x1ca3,0xe43,0x1820,0xdf9,0x690,0x926,0x3cc,0x2f20,0xa7c,0x121,0x2f02,0xee6,0x2ae2,0xa85,0xe29,0xd2b,0x1326,0x2e3d,0x1553,0x2ff5,0x133,0x2d81,0x143d,0x19fc,0x174a,0x19b9,0x2a40,0x22ab,0x1d27,0x8cf,0x1730,0x1386,0x491,0x212b,0x2954,0xf53,0xbfd,0x113a,0x144f,0x21f8,0x1b0a,0x385,0x2ce6,0xf63,0x1a64,0x48f,0x2059,0x1e4b,0x1d12,0x1f7f,0x2255,0x24f2,0x16e5,0x1242,0xa29,0x1a6,0xdd5,0x7e9,0x2eac,0x2e17,0x8f7,0x9ed,0x1de0,0x1588,0x2935,0x1c3e,0x2534,0xaf2,0x2002,0x7b4,0x2bf,0x1d25,0x2273,0x1240,0x176e,0x29b1,0x217c,0x1f5d,0xa7d,0x6e8,0x1f55,0x104e,0xb07,0x241e,0xc14,0x618,0x1fad,0x2cac,0x93d,0x1e4f,0x2907,0x281,0x1bf3,0x588,0x277d,0x1e6b,0x9df,0x629,0x1f46,0x19a7,0x3c8,0x1804,0x1981,0x2536,0x19,0x6c,0x1092,0x1980,0x13ae,0xfe4,0x2f42,0x9e,0x2837,0xea,0x23e7,0x73f,0xaa3,0x226e,0x3c1,0x1f94,0x2832,0x1408,0xd63,0x1559,0x19e7,0x273,0x2fe5,0x1e40,0xa2b,0xd34,0x1be2,0x353,0x1ef7,0x147,0x10e3,0xd6d,0x248e,0xbfc,0xc04,0x9aa,0xc8,0x360,0x2262,0x100b,0x99a,0x278f,0x2efc,0x1c3d,0x29a2,0x21ec,0x251e,0x1bdb,0x2b6d,0x2d82,0x15f8,0x2924,0x2393,0x1fd,0x109a,0x17b7,0x2559,0x20b1,0x2147,0xd30,0xea6,0xf47,0x12c3,0x253,0x288c,0xbf3,0x22a3,0x78a,0x2725,0x20d,0x16d2,0x47f,0xfc,0xfc6,0xb7f,0x957,0x2514,0x1216,0xbda,0x709,0x2809,0x172e,0x1e60,0x28f9,0x23df,0x908,0x2445,0x1646,0xe38,0x3d2,0x160b,0x6e6,0x1788,0x2fe4,0x15d8,0x47,0xce8,0x1ecb,0x6b7,0x2a73,0x1619,0x27c7,0x633,0x2fe7,0x2a9a,0x1a96,0x297d,0xc2d,0x2488,0x1953,0xb89,0x131c,0x1729,0x1b16,0x1275,0x1fbb,0x184c,0x1c28,0x198a,0x2934,0x1f9,0x2553,0x11e5,0xfdc,0x2a4d,0xdc4,0x1146,0x956,0x92d,0x21e1,0x1a95,0x2fa1,0x998,0x1c01,0x131d,0x2a3f,0xb4b,0x2cf2,0x2fe1,0x724,0x1956,0x1cce,0x254a,0x2a0a,0x1497,0x11e7,0xc71,0xf58,0x77d,0x2245,0x40f,0x22c,0x871,0x3d3,0x18dd,0x1cd,0x2df0,0x1009,0x1a94,0x29da,0x1963,0x7e7,0x2908,0x848,0xc28,0x19a2,0x31d,0x2c2c,0x2608,0x23a5,0x542,0x2fad,0x865,0x1e81,0x2da9,0x25e1,0x1303,0x240c,0x7ba,0x2a8,0xc0d,0xda8,0x124d,0x28a8,0x1ff7,0x2829,0x146,0xb43,0x23ea,0x1894,0x2e27,0x2dc4,0x2d43,0x18a3,0x1a44,0xbb3,0x28b9,0x1fe9,0x226b,0x1409,0xb7a,0x1c75,0x4e,0x1299,0x1040,0x1fcc,0x171e,0xb8a,0xd1,0x75e,0x26ae,0x229b,0xec0,0x157a,0x111c,0x6b5,0x6d,0x5ae,0x1467,0x1c9d,0x200a,0x5eb,0x1339,0xbff,0x120,0x1fbe,0x13ff,0x3d1,0x2a60,0x1b87,0x196a,0x57,0x1b4f,0x1220,0x1d30,0xccd,0x248b,0x2aa8,0x1db7,0x18ae,0x10aa,0x1425,0x2f2c,0x1187,0x3a1,0x26b8,0x2466,0x14e9,0x1518,0x2b1f,0x1ae6,0x238e,0x1a78,0x1819,0x2284,0x1475,0xaf,0x2f4,0x13fc,0x227d,0x29c0,0xf3a,0x187a,0x5e4,0x1950,0x2a25,0x29e1,0xddd,0x295d,0x1351,0x304,0x2bc0,0xd2,0xd25,0x2195,0x1fc9,0x1ee6,0x2f13,0x6db,0xa6a,0x1d99,0x2b60,0x1234,0x283c,0x2ac2,0x11a9,0x639,0x2290,0x2bda,0x32f,0x2a5f,0x15c0,0x139c,0x7e8,0x88a,0x43f,0x2762,0x1271,0x119d,0x1fed,0x1b4d,0x692,0x1d2b,0x1feb,0x1380,0x2628,0x2a93,0x2226,0xe71,0x2d1b,0x20ab,0x17ff,0x1e27,0x2fb1,0xe65,0x17c8,0x1fa6,0x43b,0x548,0x2256,0x9a5,0x71a,0x26ea,0x2d38,0x1b40,0x1b79,0x658,0x15a5,0x224f,0x248,0xeee,0x2f37,0x1c30,0x15ec,0x1ca7,0x255f,0x2801,0x18f7,0x1727,0xf88,0x2b1,0x2c45,0x164b,0x289f,0x14dd,0x2649,0x27a3,0x9f0,0x21ca,0x1f5,0x1dd6,0xbc3,0x71f,0x133e,0x13bb,0x2afe,0xc35,0x4bb,0x2d31,0x10a7,0x2a04,0x180e,0x2613,0x330,0xe76,0x19fd,0xfe9,0x935,0x79,0x1b01,0x73c,0x2ac6,0x21ce,0x1911,0x761,0x1084,0x1983,0xc3,0x15eb,0xe0a,0xdd,0x1cb1,0xb21,0x2a51,0x217f,0xb1,0x1328,0x9ca,0x1d96,0x1a0b,0xe1b,0x1c4b,0x3b,0x4d6,0x2344,0x199e,0x28af,0x1624,0x4ae,0x8b2,0x2991,0x1fb7,0x41,0x2780,0x1d8b,0xa7f,0x110,0x2350,0x18aa,0x2b2f,0x1805,0x1ff,0xf0,0x2a74,0xe42,0xd97,0x85b,0x14bc,0x2901,0xfd8,0x1ab3,0x1cef,0xfbd,0x2b07,0x174f,0x69b,0x10c3,0x1491,0xde3,0x28ca,0x252e,0x1849,0x1ec2,0x1f1b,0x2853,0x12ab,0x2674,0x238c,0x350,0x2ca,0xa7,0x4bd,0xcc3,0x90c,0x892,0x276,0x1e55,0x196d,0x1194,0x1bef,0x66a,0x1da1,0x260f,0x1c15,0x49f,0x120b,0x2671,0x1237,0x2e0d,0x2791,0x17d8,0x1e0a,0x2a99,0x14cf,0xfb1,0x15b4,0x1462,0x2fbb,0xeff,0x16b,0x2d6a,0x9ef,0x5e3,0x11c0,0x2e76,0x1623,0x2db8,0x1c88,0x740,0x11e1,0x12a3,0x977,0x1110,0x2163,0x2dee,0x47b,0x2aa5,0x2a22,0x1231,0x16e7,0x1626,0x12e0,0x1d28,0xe96,0xb62,0x21d0,0xf09,0xb30,0xcb8,0x2981,0x2648,0x155d,0x27ee,0xb34,0x169,0x1574,0x1fe6,0x25f4,0x151d,0x1801,0x1f13,0x1308,0x2929,0x6eb,0x25e,0x2cca,0x1e3e,0x248f};
+const sign16 inv= 0xeab;
+const sign16 invpr= 0x2c2a;
+
+#define DEGREE (1<<RLWE_LGN)
+#define WL 32
+
+#define round(a,b) (((a)+((b)/2))/(b))
+
+/* constant time absolute vaue */
+static sign32 nabs(sign32 x)
+{
+	sign32 mask=(x>>31);
+	return (x+mask)^mask;
+}
+
+/* Montgomery stuff */
+
+static sign32 redc(unsign64 T)
+{
+	unsign32 m=(unsign32)T*(unsign32)RLWE_ND;
+	return ((unsign64)m*RLWE_PRIME+T)>>WL;
+}
+
+static sign32 nres(unsign32 x)
+{
+	return redc((unsign64)x*RLWE_R2MODP);
+}
+
+static sign32 modmul(unsign32 a,unsign32 b)
+{
+	return redc((unsign64)a*b);
+}
+
+/* NTT code */
+/* Cooley-Tukey NTT */
+
+static void ntt(sign32 *x)
+{
+	int m,i,j,k,t=DEGREE/2;
+	sign32 S,U,V,W,q=RLWE_PRIME;
+
+/* Convert to Montgomery form */
+	for (j=0;j<DEGREE;j++)
+		x[j]=nres(x[j]);
+
+	m=1;
+	while (m<DEGREE)
+	{
+		k=0;
+		for (i=0;i<m;i++)
+		{
+			S=roots[m+i];
+			for (j=k;j<k+t;j++)
+			{
+				U=x[j];   
+				V=modmul(x[j+t],S);
+				x[j]=U+V;
+				x[j+t]=U+2*q-V;
+			}
+			k+=2*t;
+		}
+		t/=2;
+		m*=2;
+	}
+}
+
+/* Gentleman-Sande INTT */
+
+static void intt(sign32 *x)
+{
+	int m,i,j,k,t=1;
+	sign32 S,U,V,W,q=RLWE_PRIME;
+
+	m=DEGREE/2;
+	while (m>1)
+	{
+		k=0;
+		for (i=0;i<m;i++)
+		{
+			S=iroots[m+i];
+			for (j=k;j<k+t;j++)
+			{	
+				U=x[j]; 
+				V=x[j+t];
+				x[j]=U+V;	
+				W=U+DEGREE*q-V; 
+				x[j+t]=modmul(W,S); 
+			}
+			k+=2*t;
+		}
+		t*=2;
+		m/=2;
+	}
+
+/* Last iteration merged with n^-1 */
+
+	t=DEGREE/2;
+	for (j=0;j<t;j++)
+	{
+		U=x[j];
+		V=x[j+t];
+		W=U+DEGREE*q-V; 
+		x[j+t]=modmul(W,(sign32)invpr); 
+		x[j]=modmul(U+V,(sign32)inv);
+	}
+/* convert back from Montgomery to "normal" form */
+	for (j=0;j<DEGREE;j++)
+	{
+		x[j]=redc(x[j]);  
+		x[j]-=q;
+		x[j]+=(x[j]>>(WL-1))&q;
+	} 
+}
+
+/* See https://eprint.iacr.org/2016/1157.pdf */ 
+
+static void NHSEncode(byte *key,sign32 *poly)
+{
+	int i,j,b,k,kj,q2;
+
+	q2=RLWE_PRIME/2;
+	for (i=j=0;i<256;)
+	{
+		kj=key[j++];
+		for (k=0;k<8;k++)
+		{
+			b=kj&1;
+			poly[i]=b*q2;
+			poly[i+256]=b*q2;
+			poly[i+512]=b*q2;
+			poly[i+768]=b*q2;
+			kj>>=1;
+			i++;
+		}
+	}		
+}
+
+static void NHSDecode(sign32 *poly,byte *key)
+{
+	int i,j,k;
+	sign32 b,t,q2;
+	q2=RLWE_PRIME/2;
+	for (i=0;i<32;i++)
+		key[i]=0;
+
+	for (i=j=0;i<256;)
+	{
+		for (k=0;k<8;k++)
+		{
+			t=nabs(poly[i]-q2)+nabs(poly[i+256]-q2)+nabs(poly[i+512]-q2)+nabs(poly[i+768]-q2);
+
+			b=t-RLWE_PRIME;
+			b=(b>>31)&1;
+			key[j]=(key[j]>>1)+(b<<7);
+			i++;
+		}
+		j++;
+	}
+}
+
+/* convert 32-byte seed to random polynomial */
+
+static void parse(byte *seed,sign32 *poly)
+{
+	int i,j;
+	sign32 n;
+	byte hash[4*DEGREE];
+	sha3 sh;
+
+	SHA3_init(&sh,SHAKE128);
+	for (i=0;i<32;i++)
+		SHA3_process(&sh,seed[i]);
+	SHA3_shake(&sh,(char *)hash,4*DEGREE);
+
+	for (i=j=0;i<DEGREE;i++)
+	{
+
+		n=hash[j]&0x7f; n<<=8;
+		n+=hash[j+1]; n<<=8;
+		n+=hash[j+2]; n<<=8;
+		n+=hash[j+3]; j+=4;
+		poly[i]=nres(n);
+		//poly[i]=modmul(n,RLWE_ONE); // reduce 31-bit random number mod q
+	}
+} 
+
+/* Compress 14 bits polynomial coefficients into byte array */
+/* 7 bytes is 3x14 */
+
+static void NHSpack(sign32 *poly,byte *array)
+{
+	int i,j;
+	sign32 a,b,c,d;
+
+	for (i=j=0;i<DEGREE; )
+	{
+		a=poly[i++]; b=poly[i++]; c=poly[i++]; d=poly[i++];
+		array[j++]=(byte)(a&0xff);
+		array[j++]=(byte)(((a>>8)|(b<<6))&0xff);
+		array[j++]=(byte)((b>>2)&0xff);
+		array[j++]=(byte)(((b>>10)|(c<<4))&0xff);
+		array[j++]=(byte)((c>>4)&0xff);
+		array[j++]=(byte)(((c>>12)|(d<<2))&0xff);
+		array[j++]=(byte)(d>>6);
+	}
+}
+
+static void NHSunpack(byte *array,sign32 *poly)
+{
+	int i,j;
+	sign32 a,b,c,d,e,f,g;
+
+	for (i=j=0;i<DEGREE; )
+	{
+		a=((sign32)array[j++])&0xff; b=((sign32)array[j++])&0xff; c=((sign32)array[j++])&0xff; d=((sign32)array[j++])&0xff; e=((sign32)array[j++])&0xff; f=((sign32)array[j++])&0xff; g=((sign32)array[j++])&0xff;
+		poly[i++]=a|((b&0x3f)<<8);
+		poly[i++]=(b>>6)|(c<<2)|((d&0xf)<<10);
+		poly[i++]=(d>>4)|(e<<4)|((f&3)<<12);
+		poly[i++]=(f>>2)|(g<<6);
+	}
+}
+
+
+
+/* See https://eprint.iacr.org/2016/1157.pdf */ 
+
+static void NHSCompress(sign32 *poly,byte *array)
+{
+	int i,j,k,b;
+	unsign32 col=0;
+
+	for (i=j=0;i<DEGREE;)
+	{
+		for (k=0;k<8;k++)
+		{
+			b=round((poly[i]*8),RLWE_PRIME)&7; 
+			col=(col<<3)+b;
+			i++;
+		}
+		array[j]=col&0xff;
+		array[j+1]=(col>>8)&0xff;
+		array[j+2]=(col>>16)&0xff;
+		j+=3; col=0;
+	}
+}
+
+static void NHSDecompress(byte *array,sign32 *poly)
+{
+	int i,j,k,b;
+	unsign32 col=0;
+
+	for (i=j=0;i<DEGREE;)
+	{
+		col=array[j+2];
+		col=(col<<8)+array[j+1];
+		col=(col<<8)+array[j];
+		j+=3;
+		for (k=0;k<8;k++)
+		{
+			b=(col&0xe00000)>>21; col<<=3;
+			poly[i]=round((b*RLWE_PRIME),8);
+			i++;
+		}
+	}
+}
+
+/* generate centered binomial distribution */ 
+
+static void NHSError(csprng *RNG,sign32 *poly)
+{
+	int i,j;
+	sign32 n1,n2,r;
+	for (i=0;i<DEGREE;i++)
+	{
+		n1=RAND_byte(RNG)+(RAND_byte(RNG)<<8);
+		n2=RAND_byte(RNG)+(RAND_byte(RNG)<<8);
+		r=0;
+		for (j=0;j<16;j++)
+		{
+			r+=(n1&1)-(n2&1);
+			n1>>=1; n2>>=1;
+		}
+		poly[i]=(r+RLWE_PRIME);
+	}
+}
+
+static void redc_it(sign32 *p)
+{
+	int i;
+	for (i=0;i<DEGREE;i++)
+		p[i]=redc(p[i]);
+}
+
+static void nres_it(sign32 *p)
+{
+	int i;
+	for (i=0;i<DEGREE;i++)
+		p[i]=nres(p[i]);
+}
+
+static void poly_mul(sign32 *p1,sign32 *p2,sign32 *p3)
+{
+	int i;
+	for (i=0;i<DEGREE;i++)
+		p1[i]=modmul(p2[i],p3[i]);
+}
+
+static void poly_add(sign32 *p1,sign32 *p2,sign32 *p3)
+{
+	int i;
+	for (i=0;i<DEGREE;i++)
+		p1[i]=(p2[i]+p3[i]);
+}
+
+static void poly_sub(sign32 *p1,sign32 *p2,sign32 *p3)
+{
+	int i;
+	for (i=0;i<DEGREE;i++)
+		p1[i]=(p2[i]+RLWE_PRIME-p3[i]);
+}
+
+/* reduces inputs < 2q */
+static void poly_soft_reduce(sign32 *poly)
+{
+	int i;
+	sign32 e;
+	for (i=0;i<DEGREE;i++)
+	{
+		e=poly[i]-RLWE_PRIME;
+		poly[i]=e+((e>>(WL-1))&RLWE_PRIME);
+	}
+}
+
+/* fully reduces modulo q */
+static void poly_hard_reduce(sign32 *poly)
+{
+	int i;
+	sign32 e;
+	for (i=0;i<DEGREE;i++)
+	{
+		e=modmul(poly[i],RLWE_ONE);
+		e=e-RLWE_PRIME;
+		poly[i]=e+((e>>(WL-1))&RLWE_PRIME);
+	}
+}
+
+/* API files */
+
+void NHS_SERVER_1(csprng *RNG,octet *SB,octet *S)
+{
+	int i;
+	byte seed[32],array[1792];
+	sign32 s[DEGREE],e[DEGREE],b[DEGREE];
+
+	for (i=0;i<32;i++)
+		seed[i]=RAND_byte(RNG);
+
+	parse(seed,b);
+	
+	NHSError(RNG,e);
+	NHSError(RNG,s);
+
+	ntt(s);
+	ntt(e);
+	poly_mul(b,b,s);
+	poly_add(b,b,e);
+	poly_hard_reduce(b);
+
+	redc_it(b);
+	NHSpack(b,array);
+
+	OCT_empty(SB);
+	OCT_jbytes(SB,(char *)seed,32);
+	OCT_jbytes(SB,(char *)array,1792);
+
+	poly_hard_reduce(s);
+
+	NHSpack(s,array);
+	OCT_empty(S);
+	OCT_jbytes(S,(char *)array,1792);
+
+}
+
+void NHS_CLIENT(csprng *RNG,octet *SB,octet *UC,octet *KEY)
+{
+	int i;
+	sha3 sh;
+	byte seed[32],array[1792],key[32],cc[384];
+	sign32 sd[DEGREE],ed[DEGREE],u[DEGREE],k[DEGREE],c[DEGREE];
+	NHSError(RNG,sd);
+	NHSError(RNG,ed);
+
+	ntt(sd);
+	ntt(ed);
+
+	for (i=0;i<32;i++)
+		seed[i]=SB->val[i];
+
+	for (i=0;i<1792;i++)
+		array[i]=SB->val[i+32];
+
+	parse(seed,u);
+
+	poly_mul(u,u,sd);
+	poly_add(u,u,ed);
+	poly_hard_reduce(u);
+
+	for (i=0;i<32;i++)
+		key[i]=RAND_byte(RNG);
+
+	SHA3_init(&sh,SHA3_HASH256);
+	for (i=0;i<32;i++)
+		SHA3_process(&sh,key[i]);
+	SHA3_hash(&sh,(char *)key);
+
+	NHSEncode(key,k);
+
+	NHSunpack(array,c);
+	nres_it(c);
+
+	poly_mul(c,c,sd);
+	intt(c);
+	NHSError(RNG,ed);
+	poly_add(c,c,ed);
+	poly_add(c,c,k);
+
+	NHSCompress(c,cc);
+
+	SHA3_init(&sh,SHA3_HASH256);
+	for (i=0;i<32;i++)
+		SHA3_process(&sh,key[i]);
+	SHA3_hash(&sh,(char *)key);
+
+	OCT_empty(KEY);
+	OCT_jbytes(KEY,(char *)key,32);
+
+	redc_it(u);
+	NHSpack(u,array);
+
+	OCT_empty(UC);
+	OCT_jbytes(UC,(char *)array,1792);
+	OCT_jbytes(UC,(char *)cc,384);
+}
+
+void NHS_SERVER_2(octet *S,octet *UC,octet *KEY)
+{
+	int i;
+	sha3 sh;
+	sign32 c[DEGREE],s[DEGREE],k[DEGREE];
+	byte array[1792],key[32],cc[384];
+
+	for (i=0;i<1792;i++)
+		array[i]=UC->val[i];
+
+	NHSunpack(array,k);
+	nres_it(k);
+
+	for (i=0;i<384;i++)
+		cc[i]=UC->val[i+1792];
+
+	NHSDecompress(cc,c);
+
+	for (i=0;i<1792;i++)
+		array[i]=S->val[i];
+
+	NHSunpack(array,s);
+
+	poly_mul(k,k,s);
+	intt(k);
+	poly_sub(k,c,k);
+	poly_soft_reduce(k);
+
+	NHSDecode(k,key);
+
+	SHA3_init(&sh,SHA3_HASH256);
+	for (i=0;i<32;i++)
+		SHA3_process(&sh,key[i]);
+	SHA3_hash(&sh,(char *)key);
+
+	OCT_empty(KEY);
+	OCT_jbytes(KEY,(char *)key,32);
+}
+
diff --git a/version3/c/newhope.h b/version3/c/newhope.h
new file mode 100644
index 0000000..8e18a9a
--- /dev/null
+++ b/version3/c/newhope.h
@@ -0,0 +1,51 @@
+/*
+	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.
+*/
+
+/* NewHope Simple API */
+
+#ifndef NHS_H
+#define NHS_H
+
+#include "amcl.h"
+
+/**	@brief NHS server first pass
+ *
+	@param RNG Random Number Generator handle
+	@param SB seed and polynomial B concatenated - output
+	@param S server secret - output
+	
+ */
+extern void NHS_SERVER_1(csprng *RNG,octet *SB,octet *S);
+/**	@brief NHS client pass
+ *
+	@param RNG Random Number Generator handle
+	@param SB seed and polynomial B concatenated - input
+	@param UC polynomial U and compressed polynomial c - output
+	@param KEY client key
+ */
+extern void NHS_CLIENT(csprng *RNG,octet *SB,octet *UC,octet *KEY);
+/**	@brief NHS server second pass
+ *
+	@param S server secret - input
+	@param UC polynomial U and compressed polynomial c - input
+	@param KEY server key
+ */
+extern void NHS_SERVER_2(octet *S,octet *UC,octet *KEY);
+
+#endif
\ No newline at end of file
diff --git a/version3/c/oct.c b/version3/c/oct.c
new file mode 100644
index 0000000..545f140
--- /dev/null
+++ b/version3/c/oct.c
@@ -0,0 +1,429 @@
+/*
+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.
+*/
+
+/*** Basic Octet string maintainance routines  ***/
+/* SU=m, m is Stack Usage */
+
+#include <string.h>
+#include "amcl.h"
+
+/* Output an octet string (Debug Only) */
+
+/* SU= 16 */
+/* output octet */
+void OCT_output(octet *w)
+{
+    int i;
+    unsigned char ch;
+    for (i=0; i<w->len; i++)
+    {
+        ch=w->val[i];
+        printf("%02x",ch);
+    }
+    printf("\n");
+}
+
+/* SU= 16 */
+void OCT_output_string(octet *w)
+{
+    int i;
+    unsigned char ch;
+    for (i=0; i<w->len; i++)
+    {
+        ch=w->val[i];
+        printf("%c",ch);
+    }
+    /*  printf("\n"); */
+}
+
+/* Convert C string to octet format - truncates if no room  */
+void OCT_jstring(octet *y,char *s)
+{
+    int i,j;
+    i=y->len;
+    j=0;
+    while (s[j]!=0 && i<y->max)
+    {
+        y->val[i]=s[j];
+        y->len++;
+        i++;
+        j++;
+    }
+}
+
+/* compare 2 octet strings.
+ * If x==y return TRUE, else return FALSE */
+/* SU= 8 */
+int OCT_comp(octet *x,octet *y)
+{
+    int i;
+    if (x->len>y->len) return 0;
+    if (x->len<y->len) return 0;
+    for (i=0; i<x->len; i++)
+    {
+        if (x->val[i]!=y->val[i]) return 0;
+    }
+    return 1;
+}
+
+/* check are first n bytes the same (in constant time) */
+
+int OCT_ncomp(octet *x,octet *y,int n)
+{
+    int i,res=0;
+    if (n>y->len || n>x->len) return 0;
+    for (i=0; i<n; i++)
+    {
+        res|=(int)(x->val[i]^y->val[i]);
+    }
+    if (res==0) return 1;
+	return 0;
+}
+
+/* Shift octet to the left by n bytes. Leftmost bytes disappear  */
+void OCT_shl(octet *x,int n)
+{
+    int i;
+    if (n>=x->len)
+    {
+        x->len=0;
+        return;
+    }
+    x->len-=n;
+    for (i=0; i<x->len; i++)
+        x->val[i]=x->val[i+n];
+}
+
+/* Append binary string to octet - truncates if no room */
+/* SU= 12 */
+void OCT_jbytes(octet *y,char *b,int len)
+{
+    int i,j;
+    i=y->len;
+    for (j=0; j<len && i<y->max; j++)
+    {
+        y->val[i]=b[j];
+        y->len++;
+        i++;
+    }
+}
+
+/* Concatenates two octet strings */
+/* SU= 8 */
+void OCT_joctet(octet *y,octet *x)
+{
+    /* y=y || x */
+    int i,j;
+    if (x==NULL) return;
+
+    for (i=0; i<x->len; i++)
+    {
+        j=y->len+i;
+        if (j>=y->max)
+        {
+            y->len=y->max;
+            return;
+        }
+        y->val[j]=x->val[i];
+    }
+    y->len+=x->len;
+}
+
+/* Append byte to octet rep times */
+/* SU= 8 */
+void OCT_jbyte(octet *y,int ch,int rep)
+{
+    int i,j;
+    i=y->len;
+    for (j=0; j<rep && i<y->max; j++)
+    {
+        y->val[i]=ch;
+        y->len++;
+        i++;
+    }
+}
+
+/* XOR common bytes of x with y */
+/* SU= 8 */
+void OCT_xor(octet *y,octet *x)
+{
+    /* xor first x->len bytes of y */
+
+    int i;
+    for (i=0; i<x->len && i<y->len; i++)
+    {
+        y->val[i]^=x->val[i];
+    }
+}
+
+/* clear an octet */
+void OCT_empty(octet *w)
+{
+    w->len=0;
+}
+
+/* Kill an octet string - Zeroise it for security */
+void OCT_clear(octet *w)
+{
+    int i;
+    for (i=0; i<w->max; i++) w->val[i]=0;
+    w->len=0;
+}
+
+/* appends int x of length len bytes to OCTET string */
+/* SU= 8 */
+void OCT_jint(octet *y,int x,int len)
+{
+    int i,n;
+    n=y->len+len;
+    if (n>y->max || len<=0) return;
+    for (i=y->len; i<n; i++) y->val[i]=0;
+    y->len=n;
+
+    i=y->len;
+    while (x>0 && i>0)
+    {
+        i--;
+        y->val[i]=x%256;
+        x/=256;
+    }
+}
+
+/* Pad an octet to a given length */
+/* SU= 8 */
+int OCT_pad(octet *w,int n)
+{
+    int i,d;
+    if (w->len>n || n>w->max) return 0;
+    if (n==w->len) return 1;
+    d=n-w->len;
+    for (i=n-1; i>=d; i--)
+        w->val[i]=w->val[i-d];
+    for (i=d-1; i>=0; i--)
+        w->val[i]=0;
+    w->len=n;
+    return 1;
+}
+
+
+/* Convert an octet string to base64 string */
+/* SU= 56 */
+void OCT_tobase64(char *b,octet *w)
+{
+    int i,j,k,rem,last;
+    int c,ch[4];
+    unsigned char ptr[3];
+    rem=w->len%3;
+    j=k=0;
+    last=4;
+    while (j<w->len)
+    {
+        for (i=0; i<3; i++)
+        {
+            if (j<w->len) ptr[i]=w->val[j++];
+            else
+            {
+                ptr[i]=0;
+                last--;
+            }
+        }
+        ch[0]=(ptr[0]>>2)&0x3f;
+        ch[1]=((ptr[0]<<4)|(ptr[1]>>4))&0x3f;
+        ch[2]=((ptr[1]<<2)|(ptr[2]>>6))&0x3f;
+        ch[3]=ptr[2]&0x3f;
+        for (i=0; i<last; i++)
+        {
+            c=ch[i];
+            if (c<26) c+=65;
+            if (c>=26 && c<52) c+=71;
+            if (c>=52 && c<62) c-=4;
+            if (c==62) c='+';
+            if (c==63) c='/';
+            b[k++]=c;
+        }
+    }
+    if (rem>0) for (i=rem; i<3; i++) b[k++]='=';
+    b[k]='\0';  /* dangerous! */
+}
+
+/* SU= 56 */
+void OCT_frombase64(octet *w,char *b)
+{
+    int i,j,k,pads,len=(int)strlen(b);
+    int c,ch[4],ptr[3];
+    /* int lead=1; */
+    j=k=0;
+    while (j<len && k<w->max)
+    {
+        pads=0;
+        for (i=0; i<4; i++)
+        {
+            c=80+b[j++];
+            if (c<=112) continue; /* ignore white space */
+            if (c>144 && c<171) c-=145;
+            if (c>176 && c<203) c-=151;
+            if (c>127 && c<138) c-=76;
+            if (c==123) c=62;
+            if (c==127) c=63;
+            if (c==141)
+            {
+                pads++;    /* ignore pads '=' */
+                continue;
+            }
+            ch[i]=c;
+        }
+        ptr[0]=(ch[0]<<2)|(ch[1]>>4);
+        ptr[1]=(ch[1]<<4)|(ch[2]>>2);
+        ptr[2]=(ch[2]<<6)|ch[3];
+        for (i=0; i<3-pads && k<w->max; i++)
+        {
+            /* don't put in leading zeros */
+            /* if (lead && ptr[i]==0) continue; */
+            w->val[k++]=ptr[i];
+            /* lead=0; */
+        }
+
+    }
+    w->len=k;
+}
+
+/* copy an octet string - truncates if no room */
+/* SU= 16 */
+void OCT_copy(octet *y,octet *x)
+{
+    int i;
+    OCT_clear(y);
+    y->len=x->len;
+    if (y->len>y->max) y->len=y->max;
+
+    for (i=0; i<y->len; i++)
+        y->val[i]=x->val[i];
+}
+
+/* XOR m with all of x */
+void OCT_xorbyte(octet *x,int m)
+{
+    int i;
+    for (i=0; i<x->len; i++) x->val[i]^=m;
+}
+
+/* truncates x to n bytes and places the rest in y (if y is not NULL) */
+/* SU= 8 */
+void OCT_chop(octet *x,octet *y,int n)
+{
+    int i;
+    if (n>=x->len)
+    {
+        if (y!=NULL) y->len=0;
+        return;
+    }
+    if (y!=NULL) y->len=x->len-n;
+    x->len=n;
+
+    if (y!=NULL)
+    {
+        for (i=0; i<y->len && i<y->max; i++) y->val[i]=x->val[i+n];
+    }
+}
+
+/* set x to len random bytes */
+void OCT_rand(octet *x,csprng *RNG,int len)
+{
+    int i;
+    if (len>x->max) len=x->max;
+    x->len=len;
+
+    for (i=0; i<len; i++) x->val[i]=RAND_byte(RNG);
+}
+
+/* Convert an octet to a hex string */
+void OCT_toHex(octet *src,char *dst)
+{
+    int i;
+    unsigned char ch;
+    for (i=0; i<src->len; i++)
+    {
+        ch=src->val[i];
+        sprintf(&dst[i*2],"%02x", ch);
+    }
+}
+
+static int char2int(char input)
+{
+    if(input >= '0' && input <= '9')
+        return input - '0';
+    if(input >= 'A' && input <= 'F')
+        return input - 'A' + 10;
+    if(input >= 'a' && input <= 'f')
+        return input - 'a' + 10;
+    return 0;
+}
+
+/* Convert from a hex string */
+void OCT_fromHex(octet *dst,char *src)
+{
+    int i=0;
+    int j=0;
+    OCT_clear(dst);
+
+    while(src[j]!=0)
+    {
+        dst->val[i++] = char2int(src[j])*16 + char2int(src[j+1]);
+        j += 2;
+    }
+    dst->len=i;
+}
+
+
+/* Convert an octet to a string */
+void OCT_toStr(octet *src,char *dst)
+{
+    int i;
+    unsigned char ch;
+    for (i=0; i<src->len; i++)
+    {
+        ch=src->val[i];
+        sprintf(&dst[i],"%c", ch);
+    }
+}
+
+/* Test program
+#include <stdio.h>
+#include "amcl.h"
+
+char test[]="abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
+
+int main()
+{
+	char gm[100],gn[100],t[100];
+    octet m={0,sizeof(gm),gm};
+    octet n={0,sizeof(gn),gn};
+
+	OCT_jbytes(&m,test,strlen(test));
+	OCT_output(&m);
+
+	OCT_tobase64(t,&m);
+	printf(t); printf("\n");
+
+	OCT_frombase64(&n,t);
+	OCT_output(&n);
+
+    return 0;
+}
+*/
diff --git a/version3/c/pair.c b/version3/c/pair.c
new file mode 100644
index 0000000..45af60a
--- /dev/null
+++ b/version3/c/pair.c
@@ -0,0 +1,1027 @@
+/*
+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.
+*/
+
+/* AMCL BN Curve pairing functions */
+
+//#define HAS_MAIN
+
+#include "pair_ZZZ.h"
+
+/* Line function */
+static void PAIR_ZZZ_line(FP12_YYY *v,ECP2_ZZZ *A,ECP2_ZZZ *B,FP_YYY *Qx,FP_YYY *Qy)
+{
+    FP2_YYY X1,Y1,T1,T2;
+    FP2_YYY XX,YY,ZZ,YZ;
+    FP4_YYY a,b,c;
+
+    if (A==B)
+    {
+        /* doubling */
+        FP2_YYY_copy(&XX,&(A->x));	//FP2 XX=new FP2(A.getx());  //X
+        FP2_YYY_copy(&YY,&(A->y));	//FP2 YY=new FP2(A.gety());  //Y
+        FP2_YYY_copy(&ZZ,&(A->z));	//FP2 ZZ=new FP2(A.getz());  //Z
+
+
+        FP2_YYY_copy(&YZ,&YY);		//FP2 YZ=new FP2(YY);        //Y
+        FP2_YYY_mul(&YZ,&YZ,&ZZ);		//YZ.mul(ZZ);                //YZ
+        FP2_YYY_sqr(&XX,&XX);		//XX.sqr();	               //X^2
+        FP2_YYY_sqr(&YY,&YY);		//YY.sqr();	               //Y^2
+        FP2_YYY_sqr(&ZZ,&ZZ);		//ZZ.sqr();			       //Z^2
+
+        FP2_YYY_imul(&YZ,&YZ,4);	//YZ.imul(4);
+        FP2_YYY_neg(&YZ,&YZ);		//YZ.neg();
+        FP2_YYY_norm(&YZ);			//YZ.norm();       //-4YZ
+
+        FP2_YYY_imul(&XX,&XX,6);					//6X^2
+        FP2_YYY_pmul(&XX,&XX,Qx);	               //6X^2.Xs
+
+        FP2_YYY_imul(&ZZ,&ZZ,3*CURVE_B_I_ZZZ);	//3Bz^2
+
+        FP2_YYY_pmul(&YZ,&YZ,Qy);	//-4YZ.Ys
+
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+        FP2_YYY_div_ip2(&ZZ);		//6(b/i)z^2
+#endif
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+        FP2_YYY_mul_ip(&ZZ);
+        FP2_YYY_add(&ZZ,&ZZ,&ZZ);  // 6biz^2
+        FP2_YYY_mul_ip(&YZ);
+        FP2_YYY_norm(&YZ);
+#endif
+        FP2_YYY_norm(&ZZ);			// 6bi.Z^2
+
+        FP2_YYY_add(&YY,&YY,&YY);	// 2y^2
+        FP2_YYY_sub(&ZZ,&ZZ,&YY);	//
+        FP2_YYY_norm(&ZZ);			// 6b.Z^2-2Y^2
+
+        FP4_YYY_from_FP2s(&a,&YZ,&ZZ); // -4YZ.Ys | 6b.Z^2-2Y^2 | 6X^2.Xs
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+        FP4_YYY_from_FP2(&b,&XX);
+        FP4_YYY_zero(&c);
+#endif
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+        FP4_YYY_zero(&b);
+        FP4_YYY_from_FP2H(&c,&XX);
+#endif
+
+        ECP2_ZZZ_dbl(A);				//A.dbl();
+    }
+    else
+    {
+        /* addition */
+
+        FP2_YYY_copy(&X1,&(A->x));		//FP2 X1=new FP2(A.getx());    // X1
+        FP2_YYY_copy(&Y1,&(A->y));		//FP2 Y1=new FP2(A.gety());    // Y1
+        FP2_YYY_copy(&T1,&(A->z));		//FP2 T1=new FP2(A.getz());    // Z1
+
+        FP2_YYY_copy(&T2,&T1);		//FP2 T2=new FP2(A.getz());    // Z1
+
+        FP2_YYY_mul(&T1,&T1,&(B->y));	//T1.mul(B.gety());    // T1=Z1.Y2
+        FP2_YYY_mul(&T2,&T2,&(B->x));	//T2.mul(B.getx());    // T2=Z1.X2
+
+        FP2_YYY_sub(&X1,&X1,&T2);		//X1.sub(T2);
+        FP2_YYY_norm(&X1);				//X1.norm();  // X1=X1-Z1.X2
+        FP2_YYY_sub(&Y1,&Y1,&T1);		//Y1.sub(T1);
+        FP2_YYY_norm(&Y1);				//Y1.norm();  // Y1=Y1-Z1.Y2
+
+        FP2_YYY_copy(&T1,&X1);			//T1.copy(X1);            // T1=X1-Z1.X2
+
+        FP2_YYY_pmul(&X1,&X1,Qy);		//X1.pmul(Qy);            // X1=(X1-Z1.X2).Ys
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+        FP2_YYY_mul_ip(&X1);
+        FP2_YYY_norm(&X1);
+#endif
+
+        FP2_YYY_mul(&T1,&T1,&(B->y));	//T1.mul(B.gety());       // T1=(X1-Z1.X2).Y2
+
+        FP2_YYY_copy(&T2,&Y1);			//T2.copy(Y1);            // T2=Y1-Z1.Y2
+        FP2_YYY_mul(&T2,&T2,&(B->x));	//T2.mul(B.getx());       // T2=(Y1-Z1.Y2).X2
+        FP2_YYY_sub(&T2,&T2,&T1);		//T2.sub(T1);
+        FP2_YYY_norm(&T2);				//T2.norm();          // T2=(Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2
+        FP2_YYY_pmul(&Y1,&Y1,Qx);		//Y1.pmul(Qx);
+        FP2_YYY_neg(&Y1,&Y1);			//Y1.neg();
+        FP2_YYY_norm(&Y1);				//Y1.norm(); // Y1=-(Y1-Z1.Y2).Xs
+
+        FP4_YYY_from_FP2s(&a,&X1,&T2);	// (X1-Z1.X2).Ys  |  (Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2  | - (Y1-Z1.Y2).Xs
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+        FP4_YYY_from_FP2(&b,&Y1);		//b=new FP4(Y1);
+        FP4_YYY_zero(&c);
+#endif
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+        FP4_YYY_zero(&b);
+        FP4_YYY_from_FP2H(&c,&Y1);		//b=new FP4(Y1);
+#endif
+        ECP2_ZZZ_add(A,B);			//A.add(B);
+    }
+
+    FP12_YYY_from_FP4s(v,&a,&b,&c);
+//	FP12_YYY_norm(v);
+}
+
+/* Optimal R-ate pairing r=e(P,Q) */
+void PAIR_ZZZ_ate(FP12_YYY *r,ECP2_ZZZ *P1,ECP_ZZZ *Q1)
+{
+
+    BIG_XXX x,n,n3;
+    FP_YYY Qx,Qy;
+    int i,nb,bt;
+    ECP2_ZZZ A,NP,P;
+	ECP_ZZZ Q;
+    FP12_YYY lv;
+#if PAIRING_FRIENDLY_ZZZ==BN
+    ECP2_ZZZ KA;
+    FP2_YYY X;
+
+    FP_YYY_rcopy(&Qx,Fra_YYY);
+    FP_YYY_rcopy(&Qy,Frb_YYY);
+    FP2_YYY_from_FPs(&X,&Qx,&Qy);
+
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+    FP2_YYY_inv(&X,&X);
+    FP2_YYY_norm(&X);
+#endif
+#endif
+
+    BIG_XXX_rcopy(x,CURVE_Bnx_ZZZ);
+
+#if PAIRING_FRIENDLY_ZZZ==BN
+    BIG_XXX_pmul(n,x,6);
+#if SIGN_OF_X_ZZZ==POSITIVEX
+    BIG_XXX_inc(n,2);
+#else
+    BIG_XXX_dec(n,2);
+#endif
+#else
+    BIG_XXX_copy(n,x);
+#endif
+
+    BIG_XXX_norm(n);
+    BIG_XXX_pmul(n3,n,3);
+    BIG_XXX_norm(n3);
+
+//    ECP2_ZZZ_affine(P);
+//    ECP_ZZZ_affine(Q);
+
+	ECP2_ZZZ_copy(&P,P1);
+	ECP_ZZZ_copy(&Q,Q1);
+
+	ECP2_ZZZ_affine(&P);
+	ECP_ZZZ_affine(&Q);
+
+    FP_YYY_copy(&Qx,&(Q.x));
+    FP_YYY_copy(&Qy,&(Q.y));
+
+    ECP2_ZZZ_copy(&A,&P);
+	ECP2_ZZZ_copy(&NP,&P); ECP2_ZZZ_neg(&NP);
+
+    FP12_YYY_one(r);
+    nb=BIG_XXX_nbits(n3);  //n
+
+    /* Main Miller Loop */
+    for (i=nb-2; i>=1; i--)   //0
+    {
+        FP12_YYY_sqr(r,r);
+        PAIR_ZZZ_line(&lv,&A,&A,&Qx,&Qy);
+        FP12_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+        //bt=BIG_XXX_bit(n,i);
+        bt=BIG_XXX_bit(n3,i)-BIG_XXX_bit(n,i);
+        if (bt==1)
+        {
+
+            PAIR_ZZZ_line(&lv,&A,&P,&Qx,&Qy);
+            FP12_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+        }
+        if (bt==-1)
+        {
+            //ECP2_ZZZ_neg(P);
+            PAIR_ZZZ_line(&lv,&A,&NP,&Qx,&Qy);
+            FP12_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+            //ECP2_ZZZ_neg(P);
+        }
+
+//       FP12_YYY_sqr(r,r);
+    }
+
+//    PAIR_ZZZ_line(&lv,&A,&A,&Qx,&Qy);
+//    FP12_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+
+//   if (BIG_XXX_parity(n))
+//   {
+    //      PAIR_ZZZ_line(&lv,&A,P,&Qx,&Qy);
+    //     FP12_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+    //}
+
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP12_YYY_conj(r,r);
+#endif
+
+    /* R-ate fixup required for BN curves */
+#if PAIRING_FRIENDLY_ZZZ==BN
+    ECP2_ZZZ_copy(&KA,&P);
+    ECP2_ZZZ_frob(&KA,&X);
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+    ECP2_ZZZ_neg(&A);
+//    FP12_YYY_conj(r,r);
+#endif
+    PAIR_ZZZ_line(&lv,&A,&KA,&Qx,&Qy);
+    FP12_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+    ECP2_ZZZ_frob(&KA,&X);
+    ECP2_ZZZ_neg(&KA);
+    PAIR_ZZZ_line(&lv,&A,&KA,&Qx,&Qy);
+    FP12_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+#endif
+}
+
+/* Optimal R-ate double pairing e(P,Q).e(R,S) */
+void PAIR_ZZZ_double_ate(FP12_YYY *r,ECP2_ZZZ *P1,ECP_ZZZ *Q1,ECP2_ZZZ *R1,ECP_ZZZ *S1)
+{
+    BIG_XXX x,n,n3;
+    FP_YYY Qx,Qy,Sx,Sy;
+    int i,nb,bt;
+    ECP2_ZZZ A,B,NP,NR,P,R;
+	ECP_ZZZ Q,S;
+    FP12_YYY lv;
+#if PAIRING_FRIENDLY_ZZZ==BN
+    FP2_YYY X;
+    ECP2_ZZZ K;
+
+    FP_YYY_rcopy(&Qx,Fra_YYY);
+    FP_YYY_rcopy(&Qy,Frb_YYY);
+    FP2_YYY_from_FPs(&X,&Qx,&Qy);
+
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+    FP2_YYY_inv(&X,&X);
+    FP2_YYY_norm(&X);
+#endif
+#endif
+
+    BIG_XXX_rcopy(x,CURVE_Bnx_ZZZ);
+
+#if PAIRING_FRIENDLY_ZZZ==BN
+    BIG_XXX_pmul(n,x,6);
+#if SIGN_OF_X_ZZZ==POSITIVEX
+    BIG_XXX_inc(n,2);
+#else
+    BIG_XXX_dec(n,2);
+#endif
+#else
+    BIG_XXX_copy(n,x);
+#endif
+
+    BIG_XXX_norm(n);
+    BIG_XXX_pmul(n3,n,3);
+    BIG_XXX_norm(n3);
+
+	ECP2_ZZZ_copy(&P,P1);
+	ECP_ZZZ_copy(&Q,Q1);
+
+	ECP2_ZZZ_affine(&P);
+	ECP_ZZZ_affine(&Q);
+
+	ECP2_ZZZ_copy(&R,R1);
+	ECP_ZZZ_copy(&S,S1);
+
+	ECP2_ZZZ_affine(&R);
+	ECP_ZZZ_affine(&S);
+
+    FP_YYY_copy(&Qx,&(Q.x));
+    FP_YYY_copy(&Qy,&(Q.y));
+
+    FP_YYY_copy(&Sx,&(S.x));
+    FP_YYY_copy(&Sy,&(S.y));
+
+    ECP2_ZZZ_copy(&A,&P);
+    ECP2_ZZZ_copy(&B,&R);
+
+	ECP2_ZZZ_copy(&NP,&P); ECP2_ZZZ_neg(&NP);
+	ECP2_ZZZ_copy(&NR,&R); ECP2_ZZZ_neg(&NR);
+
+
+    FP12_YYY_one(r);
+    nb=BIG_XXX_nbits(n3);
+
+    /* Main Miller Loop */
+    for (i=nb-2; i>=1; i--)
+    {
+        FP12_YYY_sqr(r,r);
+        PAIR_ZZZ_line(&lv,&A,&A,&Qx,&Qy);
+        FP12_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+
+        PAIR_ZZZ_line(&lv,&B,&B,&Sx,&Sy);
+        FP12_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+
+        bt=BIG_XXX_bit(n3,i)-BIG_XXX_bit(n,i);
+        //bt=BIG_XXX_bit(n,i);
+        if (bt==1)
+        {
+            PAIR_ZZZ_line(&lv,&A,&P,&Qx,&Qy);
+            FP12_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+
+            PAIR_ZZZ_line(&lv,&B,&R,&Sx,&Sy);
+            FP12_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+        }
+
+        if (bt==-1)
+        {
+            //ECP2_ZZZ_neg(P);
+            PAIR_ZZZ_line(&lv,&A,&NP,&Qx,&Qy);
+            FP12_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+            //ECP2_ZZZ_neg(P);
+
+            //ECP2_ZZZ_neg(R);
+            PAIR_ZZZ_line(&lv,&B,&NR,&Sx,&Sy);
+            FP12_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+            //ECP2_ZZZ_neg(R);
+        }
+
+        //FP12_YYY_sqr(r,r);
+
+    }
+
+    // PAIR_ZZZ_line(&lv,&A,&A,&Qx,&Qy);
+    // FP12_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+
+    // PAIR_ZZZ_line(&lv,&B,&B,&Sx,&Sy);
+    // FP12_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+
+    // if (BIG_XXX_parity(n))
+    // {
+    //     PAIR_ZZZ_line(&lv,&A,P,&Qx,&Qy);
+    //     FP12_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+
+    //     PAIR_ZZZ_line(&lv,&B,R,&Sx,&Sy);
+    //     FP12_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+    // }
+
+    /* R-ate fixup required for BN curves */
+
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP12_YYY_conj(r,r);
+#endif
+
+#if PAIRING_FRIENDLY_ZZZ==BN
+
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+    //FP12_YYY_conj(r,r);
+    ECP2_ZZZ_neg(&A);
+    ECP2_ZZZ_neg(&B);
+#endif
+
+    ECP2_ZZZ_copy(&K,&P);
+    ECP2_ZZZ_frob(&K,&X);
+
+    PAIR_ZZZ_line(&lv,&A,&K,&Qx,&Qy);
+    FP12_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+    ECP2_ZZZ_frob(&K,&X);
+    ECP2_ZZZ_neg(&K);
+    PAIR_ZZZ_line(&lv,&A,&K,&Qx,&Qy);
+    FP12_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+
+    ECP2_ZZZ_copy(&K,&R);
+    ECP2_ZZZ_frob(&K,&X);
+
+    PAIR_ZZZ_line(&lv,&B,&K,&Sx,&Sy);
+    FP12_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+    ECP2_ZZZ_frob(&K,&X);
+    ECP2_ZZZ_neg(&K);
+    PAIR_ZZZ_line(&lv,&B,&K,&Sx,&Sy);
+    FP12_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+
+#endif
+}
+
+/* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */
+void PAIR_ZZZ_fexp(FP12_YYY *r)
+{
+    FP2_YYY X;
+    BIG_XXX x;
+    FP_YYY a,b;
+    FP12_YYY t0,y0,y1,y2,y3;
+
+    BIG_XXX_rcopy(x,CURVE_Bnx_ZZZ);
+    FP_YYY_rcopy(&a,Fra_YYY);
+    FP_YYY_rcopy(&b,Frb_YYY);
+    FP2_YYY_from_FPs(&X,&a,&b);
+
+    /* Easy part of final exp */
+
+    FP12_YYY_inv(&t0,r);
+    FP12_YYY_conj(r,r);
+
+    FP12_YYY_mul(r,&t0);
+    FP12_YYY_copy(&t0,r);
+
+    FP12_YYY_frob(r,&X);
+    FP12_YYY_frob(r,&X);
+    FP12_YYY_mul(r,&t0);
+
+    /* Hard part of final exp - see Duquesne & Ghamman eprint 2015/192.pdf */
+#if PAIRING_FRIENDLY_ZZZ==BN
+    FP12_YYY_pow(&t0,r,x); // t0=f^-u
+#if SIGN_OF_X_ZZZ==POSITIVEX
+    FP12_YYY_conj(&t0,&t0);
+#endif
+    FP12_YYY_usqr(&y3,&t0); // y3=t0^2
+    FP12_YYY_copy(&y0,&t0);
+    FP12_YYY_mul(&y0,&y3); // y0=t0*y3
+    FP12_YYY_copy(&y2,&y3);
+    FP12_YYY_frob(&y2,&X); // y2=y3^p
+    FP12_YYY_mul(&y2,&y3); //y2=y2*y3
+    FP12_YYY_usqr(&y2,&y2); //y2=y2^2
+    FP12_YYY_mul(&y2,&y3); // y2=y2*y3
+
+    FP12_YYY_pow(&t0,&y0,x);  //t0=y0^-u
+#if SIGN_OF_X_ZZZ==POSITIVEX
+    FP12_YYY_conj(&t0,&t0);
+#endif
+    FP12_YYY_conj(&y0,r);     //y0=~r
+    FP12_YYY_copy(&y1,&t0);
+    FP12_YYY_frob(&y1,&X);
+    FP12_YYY_frob(&y1,&X); //y1=t0^p^2
+    FP12_YYY_mul(&y1,&y0); // y1=y0*y1
+    FP12_YYY_conj(&t0,&t0); // t0=~t0
+    FP12_YYY_copy(&y3,&t0);
+    FP12_YYY_frob(&y3,&X); //y3=t0^p
+    FP12_YYY_mul(&y3,&t0); // y3=t0*y3
+    FP12_YYY_usqr(&t0,&t0); // t0=t0^2
+    FP12_YYY_mul(&y1,&t0); // y1=t0*y1
+
+    FP12_YYY_pow(&t0,&y3,x); // t0=y3^-u
+#if SIGN_OF_X_ZZZ==POSITIVEX
+    FP12_YYY_conj(&t0,&t0);
+#endif
+    FP12_YYY_usqr(&t0,&t0); //t0=t0^2
+    FP12_YYY_conj(&t0,&t0); //t0=~t0
+    FP12_YYY_mul(&y3,&t0); // y3=t0*y3
+
+    FP12_YYY_frob(r,&X);
+    FP12_YYY_copy(&y0,r);
+    FP12_YYY_frob(r,&X);
+    FP12_YYY_mul(&y0,r);
+    FP12_YYY_frob(r,&X);
+    FP12_YYY_mul(&y0,r);
+
+    FP12_YYY_usqr(r,&y3);  //r=y3^2
+    FP12_YYY_mul(r,&y2);   //r=y2*r
+    FP12_YYY_copy(&y3,r);
+    FP12_YYY_mul(&y3,&y0); // y3=r*y0
+    FP12_YYY_mul(r,&y1); // r=r*y1
+    FP12_YYY_usqr(r,r); // r=r^2
+    FP12_YYY_mul(r,&y3); // r=r*y3
+    FP12_YYY_reduce(r);
+#else
+// Ghamman & Fouotsa Method
+
+    FP12_YYY_usqr(&y0,r);
+    FP12_YYY_pow(&y1,&y0,x);
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+    FP12_YYY_conj(&y1,&y1);
+#endif
+
+
+    BIG_XXX_fshr(x,1);
+    FP12_YYY_pow(&y2,&y1,x);
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+    FP12_YYY_conj(&y2,&y2);
+#endif
+
+
+    BIG_XXX_fshl(x,1); // x must be even
+    FP12_YYY_conj(&y3,r);
+    FP12_YYY_mul(&y1,&y3);
+
+    FP12_YYY_conj(&y1,&y1);
+    FP12_YYY_mul(&y1,&y2);
+
+    FP12_YYY_pow(&y2,&y1,x);
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+    FP12_YYY_conj(&y2,&y2);
+#endif
+
+    FP12_YYY_pow(&y3,&y2,x);
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+    FP12_YYY_conj(&y3,&y3);
+#endif
+    FP12_YYY_conj(&y1,&y1);
+    FP12_YYY_mul(&y3,&y1);
+
+    FP12_YYY_conj(&y1,&y1);
+    FP12_YYY_frob(&y1,&X);
+    FP12_YYY_frob(&y1,&X);
+    FP12_YYY_frob(&y1,&X);
+    FP12_YYY_frob(&y2,&X);
+    FP12_YYY_frob(&y2,&X);
+    FP12_YYY_mul(&y1,&y2);
+
+    FP12_YYY_pow(&y2,&y3,x);
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+    FP12_YYY_conj(&y2,&y2);
+#endif
+    FP12_YYY_mul(&y2,&y0);
+    FP12_YYY_mul(&y2,r);
+
+    FP12_YYY_mul(&y1,&y2);
+    FP12_YYY_copy(&y2,&y3);
+    FP12_YYY_frob(&y2,&X);
+    FP12_YYY_mul(&y1,&y2);
+    FP12_YYY_copy(r,&y1);
+    FP12_YYY_reduce(r);
+
+// Aranha et al method as described by Ghamman & Fouotsa
+    /*
+    	FP12_YYY_usqr(&y0,r);  // t0=f^2
+    	FP12_YYY_conj(&y3,&y0); // t0=f^-2
+    	FP12_YYY_pow(&t0,r,x); // t5=f^u
+    	FP12_YYY_usqr(&y1,&t0); // t1=t5^2
+    	FP12_YYY_mul(&y3,&t0); // t3=t0*t5
+
+    	FP12_YYY_pow(&y0,&y3,x);
+
+    	FP12_YYY_pow(&y2,&y0,x);
+
+    	FP12_YYY_pow(&y4,&y2,x);
+
+    	FP12_YYY_mul(&y4,&y1);
+    	FP12_YYY_pow(&y1,&y4,x);
+    	FP12_YYY_conj(&y3,&y3);
+    	FP12_YYY_mul(&y1,&y3);
+    	FP12_YYY_mul(&y1,r);
+
+    	FP12_YYY_conj(&y3,r);
+    	FP12_YYY_mul(&y0,r);
+    	FP12_YYY_frob(&y0,&X); FP12_YYY_frob(&y0,&X); FP12_YYY_frob(&y0,&X);
+
+    	FP12_YYY_mul(&y4,&y3);
+    	FP12_YYY_frob(&y4,&X);
+
+    	FP12_YYY_mul(&t0,&y2);
+    	FP12_YYY_frob(&t0,&X); FP12_YYY_frob(&t0,&X);
+
+    	FP12_YYY_mul(&t0,&y0);
+    	FP12_YYY_mul(&t0,&y4);
+    	FP12_YYY_mul(&t0,&y1);
+    	FP12_YYY_copy(r,&t0);
+    	FP12_YYY_reduce(r);*/
+
+//-----------------------------------
+    /*
+    	FP12_YYY_copy(&y0,r);						// y0=r;
+    	FP12_YYY_copy(&y1,r);						// y1=r;
+    	FP12_YYY_copy(&t0,r); FP12_YYY_frob(&t0,&X);	// t0=Frobenius(r,X,1);
+    	FP12_YYY_conj(&y3,&t0); FP12_YYY_mul(&y1,&y3);	// y1*=inverse(t0);
+    	FP12_YYY_frob(&t0,&X); FP12_YYY_frob(&t0,&X);	// t0=Frobenius(t0,X,2);
+    	FP12_YYY_mul(&y1,&t0);						// y1*=t0;
+
+    	FP12_YYY_pow(r,r,x);						// r=pow(r,x);
+    	FP12_YYY_conj(&y3,r); FP12_YYY_mul(&y1,&y3);	// y1*=inverse(r);
+    	FP12_YYY_copy(&t0,r); FP12_YYY_frob(&t0,&X);	// t0=Frobenius(r,X,1);
+    	FP12_YYY_mul(&y0,&t0);						// y0*=t0;
+    	FP12_YYY_frob(&t0,&X);						// t0=Frobenius(t0,X,1);
+    	FP12_YYY_mul(&y1,&t0);						// y1*=t0;
+    	FP12_YYY_frob(&t0,&X);						// t0=Frobenius(t0,X,1);
+    	FP12_YYY_conj(&y3,&t0); FP12_YYY_mul(&y0,&y3);	// y0*=inverse(t0);
+
+    	FP12_YYY_pow(r,r,x);						// r=pow(r,x);
+    	FP12_YYY_mul(&y0,r);						// y0*=r;
+    	FP12_YYY_copy(&t0,r); FP12_YYY_frob(&t0,&X); FP12_YYY_frob(&t0,&X); // t0=Frobenius(r,X,2);
+    	FP12_YYY_conj(&y3,&t0); FP12_YYY_mul(&y0,&y3);	// y0*=inverse(t0);
+    	FP12_YYY_frob(&t0,&X);						// t0=Frobenius(t0,X,1);
+    	FP12_YYY_mul(&y1,&t0);						// y1*=t0;
+
+    	FP12_YYY_pow(r,r,x);						// r=pow(r,x);			// r^x3
+    	FP12_YYY_copy(&t0,r); FP12_YYY_frob(&t0,&X);	// t0=Frobenius(r,X,1);
+    	FP12_YYY_conj(&y3,&t0); FP12_YYY_mul(&y0,&y3);	// y0*=inverse(t0);
+    	FP12_YYY_frob(&t0,&X);						// t0=Frobenius(t0,X,1);
+    	FP12_YYY_mul(&y1,&t0);						// y1*=t0;
+
+    	FP12_YYY_pow(r,r,x);						// r=pow(r,x);			// r^x4
+    	FP12_YYY_conj(&y3,r); FP12_YYY_mul(&y0,&y3);	// y0*=inverse(r);
+    	FP12_YYY_copy(&t0,r); FP12_YYY_frob(&t0,&X);	// t0=Frobenius(r,X,1);
+    	FP12_YYY_mul(&y1,&t0);						//y1*=t0;
+
+    	FP12_YYY_pow(r,r,x);						// r=pow(r,x);			// r^x5
+    	FP12_YYY_mul(&y1,r);						// y1*=r;
+
+    	FP12_YYY_usqr(&y0,&y0);						// r=y0*y0*y1;
+    	FP12_YYY_mul(&y0,&y1);
+    	FP12_YYY_copy(r,&y0);
+    	FP12_YYY_reduce(r); */
+#endif
+}
+
+#ifdef USE_GLV_ZZZ
+/* GLV method */
+static void glv(BIG_XXX u[2],BIG_XXX e)
+{
+#if PAIRING_FRIENDLY_ZZZ==BN
+    int i,j;
+    BIG_XXX v[2],t,q;
+    DBIG_XXX d;
+    BIG_XXX_rcopy(q,CURVE_Order_ZZZ);
+    for (i=0; i<2; i++)
+    {
+        BIG_XXX_rcopy(t,CURVE_W_ZZZ[i]);
+//BIG_XXX_norm(t); BIG_XXX_norm(e);
+        BIG_XXX_mul(d,t,e);
+        BIG_XXX_ddiv(v[i],d,q);
+        BIG_XXX_zero(u[i]);
+    }
+    BIG_XXX_copy(u[0],e);
+    for (i=0; i<2; i++)
+        for (j=0; j<2; j++)
+        {
+            BIG_XXX_rcopy(t,CURVE_SB_ZZZ[j][i]);
+            BIG_XXX_modmul(t,v[j],t,q);
+            BIG_XXX_add(u[i],u[i],q);
+            BIG_XXX_sub(u[i],u[i],t);
+            BIG_XXX_mod(u[i],q);
+        }
+
+#else
+// -(x^2).P = (Beta.x,y)
+
+    BIG_XXX x,x2,q;
+    BIG_XXX_rcopy(x,CURVE_Bnx_ZZZ);
+    BIG_XXX_smul(x2,x,x);
+    BIG_XXX_copy(u[0],e);
+    BIG_XXX_mod(u[0],x2);
+    BIG_XXX_copy(u[1],e);
+    BIG_XXX_sdiv(u[1],x2);
+
+    BIG_XXX_rcopy(q,CURVE_Order_ZZZ);
+    BIG_XXX_sub(u[1],q,u[1]);
+
+#endif
+
+    return;
+}
+#endif // USE_GLV
+
+/* Galbraith & Scott Method */
+static void gs(BIG_XXX u[4],BIG_XXX e)
+{
+    int i;
+#if PAIRING_FRIENDLY_ZZZ==BN
+    int j;
+    BIG_XXX v[4],t,q;
+    DBIG_XXX d;
+    BIG_XXX_rcopy(q,CURVE_Order_ZZZ);
+    for (i=0; i<4; i++)
+    {
+        BIG_XXX_rcopy(t,CURVE_WB_ZZZ[i]);
+//BIG_XXX_norm(t); BIG_XXX_norm(e);
+        BIG_XXX_mul(d,t,e);
+        BIG_XXX_ddiv(v[i],d,q);
+        BIG_XXX_zero(u[i]);
+    }
+
+    BIG_XXX_copy(u[0],e);
+    for (i=0; i<4; i++)
+        for (j=0; j<4; j++)
+        {
+            BIG_XXX_rcopy(t,CURVE_BB_ZZZ[j][i]);
+            BIG_XXX_modmul(t,v[j],t,q);
+            BIG_XXX_add(u[i],u[i],q);
+            BIG_XXX_sub(u[i],u[i],t);
+            BIG_XXX_mod(u[i],q);
+        }
+
+#else
+
+    BIG_XXX x,w,q;
+    BIG_XXX_rcopy(q,CURVE_Order_ZZZ);
+    BIG_XXX_rcopy(x,CURVE_Bnx_ZZZ);
+    BIG_XXX_copy(w,e);
+
+    for (i=0; i<3; i++)
+    {
+        BIG_XXX_copy(u[i],w);
+        BIG_XXX_mod(u[i],x);
+        BIG_XXX_sdiv(w,x);
+    }
+    BIG_XXX_copy(u[3],w);
+
+    /*  */
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+    BIG_XXX_modneg(u[1],u[1],q);
+    BIG_XXX_modneg(u[3],u[3],q);
+#endif
+
+#endif
+
+
+
+    return;
+}
+
+/* Multiply P by e in group G1 */
+void PAIR_ZZZ_G1mul(ECP_ZZZ *P,BIG_XXX e)
+{
+#ifdef USE_GLV_ZZZ   /* Note this method is patented */
+    int np,nn;
+    ECP_ZZZ Q;
+    FP_YYY cru;
+    BIG_XXX t,q;
+    BIG_XXX u[2];
+
+    BIG_XXX_rcopy(q,CURVE_Order_ZZZ);
+    glv(u,e);
+
+    //ECP_ZZZ_affine(P);
+    ECP_ZZZ_copy(&Q,P); ECP_ZZZ_affine(&Q);
+    FP_YYY_rcopy(&cru,CURVE_Cru_ZZZ);
+    FP_YYY_mul(&(Q.x),&(Q.x),&cru);
+
+    /* note that -a.B = a.(-B). Use a or -a depending on which is smaller */
+
+    np=BIG_XXX_nbits(u[0]);
+    BIG_XXX_modneg(t,u[0],q);
+    nn=BIG_XXX_nbits(t);
+    if (nn<np)
+    {
+        BIG_XXX_copy(u[0],t);
+        ECP_ZZZ_neg(P);
+    }
+
+    np=BIG_XXX_nbits(u[1]);
+    BIG_XXX_modneg(t,u[1],q);
+    nn=BIG_XXX_nbits(t);
+    if (nn<np)
+    {
+        BIG_XXX_copy(u[1],t);
+        ECP_ZZZ_neg(&Q);
+    }
+    BIG_XXX_norm(u[0]);
+    BIG_XXX_norm(u[1]);
+    ECP_ZZZ_mul2(P,&Q,u[0],u[1]);
+
+#else
+    ECP_ZZZ_mul(P,e);
+#endif
+}
+
+/* Multiply P by e in group G2 */
+void PAIR_ZZZ_G2mul(ECP2_ZZZ *P,BIG_XXX e)
+{
+#ifdef USE_GS_G2_ZZZ   /* Well I didn't patent it :) */
+    int i,np,nn;
+    ECP2_ZZZ Q[4];
+    FP2_YYY X;
+    FP_YYY fx,fy;
+    BIG_XXX x,y,u[4];
+
+    FP_YYY_rcopy(&fx,Fra_YYY);
+    FP_YYY_rcopy(&fy,Frb_YYY);
+    FP2_YYY_from_FPs(&X,&fx,&fy);
+
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+    FP2_YYY_inv(&X,&X);
+    FP2_YYY_norm(&X);
+#endif
+
+    BIG_XXX_rcopy(y,CURVE_Order_ZZZ);
+    gs(u,e);
+
+
+    //ECP2_ZZZ_affine(P);
+
+//printf("PPz= "); FP2_YYY_output(&(P->z)); printf("\n");
+
+//printf("f= "); FP2_YYY_output(&X); printf("\n");
+
+    ECP2_ZZZ_copy(&Q[0],P);
+    for (i=1; i<4; i++)
+    {
+        ECP2_ZZZ_copy(&Q[i],&Q[i-1]);
+        ECP2_ZZZ_frob(&Q[i],&X);
+    }
+//printf("Q[0]= "); ECP2_ZZZ_output(&Q[0]); printf("\n");
+//printf("Q[1]= "); ECP2_ZZZ_output(&Q[1]); printf("\n");
+    for (i=0; i<4; i++)
+    {
+        np=BIG_XXX_nbits(u[i]);
+        BIG_XXX_modneg(x,u[i],y);
+        nn=BIG_XXX_nbits(x);
+        if (nn<np)
+        {
+            BIG_XXX_copy(u[i],x);
+            ECP2_ZZZ_neg(&Q[i]);
+        }
+        BIG_XXX_norm(u[i]);    
+		//ECP2_ZZZ_affine(&Q[i]);
+    }
+
+
+//printf("Q[2]= "); ECP2_ZZZ_output(&Q[2]); printf("\n");
+//printf("Q[3]= "); ECP2_ZZZ_output(&Q[3]); printf("\n");
+//exit(0);
+
+    ECP2_ZZZ_mul4(P,Q,u);
+
+#else
+    ECP2_ZZZ_mul(P,e);
+#endif
+}
+
+/* f=f^e */
+void PAIR_ZZZ_GTpow(FP12_YYY *f,BIG_XXX e)
+{
+#ifdef USE_GS_GT_ZZZ   /* Note that this option requires a lot of RAM! Maybe better to use compressed XTR method, see fp4.c */
+    int i,np,nn;
+    FP12_YYY g[4];
+    FP2_YYY X;
+    BIG_XXX t,q;
+    FP_YYY fx,fy;
+    BIG_XXX u[4];
+
+    FP_YYY_rcopy(&fx,Fra_YYY);
+    FP_YYY_rcopy(&fy,Frb_YYY);
+    FP2_YYY_from_FPs(&X,&fx,&fy);
+
+    BIG_XXX_rcopy(q,CURVE_Order_ZZZ);
+    gs(u,e);
+
+    FP12_YYY_copy(&g[0],f);
+    for (i=1; i<4; i++)
+    {
+        FP12_YYY_copy(&g[i],&g[i-1]);
+        FP12_YYY_frob(&g[i],&X);
+    }
+
+    for (i=0; i<4; i++)
+    {
+        np=BIG_XXX_nbits(u[i]);
+        BIG_XXX_modneg(t,u[i],q);
+        nn=BIG_XXX_nbits(t);
+        if (nn<np)
+        {
+            BIG_XXX_copy(u[i],t);
+            FP12_YYY_conj(&g[i],&g[i]);
+        }
+        BIG_XXX_norm(u[i]);
+    }
+    FP12_YYY_pow4(f,g,u);
+
+#else
+    FP12_YYY_pow(f,f,e);
+#endif
+}
+
+/* test group membership test - no longer needed */
+/* with GT-Strong curve, now only check that m!=1, conj(m)*m==1, and m.m^{p^4}=m^{p^2} */
+
+/*
+int PAIR_ZZZ_GTmember(FP12_YYY *m)
+{
+	BIG_XXX a,b;
+	FP2_YYY X;
+	FP12_YYY r,w;
+	if (FP12_YYY_isunity(m)) return 0;
+	FP12_YYY_conj(&r,m);
+	FP12_YYY_mul(&r,m);
+	if (!FP12_YYY_isunity(&r)) return 0;
+
+	BIG_XXX_rcopy(a,CURVE_Fra);
+	BIG_XXX_rcopy(b,CURVE_Frb);
+	FP2_YYY_from_BIGs(&X,a,b);
+
+
+	FP12_YYY_copy(&r,m); FP12_YYY_frob(&r,&X); FP12_YYY_frob(&r,&X);
+	FP12_YYY_copy(&w,&r); FP12_YYY_frob(&w,&X); FP12_YYY_frob(&w,&X);
+	FP12_YYY_mul(&w,m);
+
+
+#ifndef GT_STRONG
+	if (!FP12_YYY_equals(&w,&r)) return 0;
+
+	BIG_XXX_rcopy(a,CURVE_Bnx);
+
+	FP12_YYY_copy(&r,m); FP12_YYY_pow(&w,&r,a); FP12_YYY_pow(&w,&w,a);
+	FP12_YYY_sqr(&r,&w); FP12_YYY_mul(&r,&w); FP12_YYY_sqr(&r,&r);
+
+	FP12_YYY_copy(&w,m); FP12_YYY_frob(&w,&X);
+ #endif
+
+	return FP12_YYY_equals(&w,&r);
+}
+
+*/
+
+
+#ifdef HAS_MAIN
+/*
+#if CHOICE==BN254_T
+
+const BIG_XXX TEST_Gx={0x18AFF11A,0xF2EF406,0xAF68220,0x171F2E27,0x6BA0959,0x124C50E0,0x450BE27,0x7003EA8,0x8A914};
+const BIG_XXX TEST_Gy={0x6E010F4,0xA71D07E,0x7ECADA8,0x8260E8E,0x1F79C328,0x17A09412,0xBFAE690,0x1C57CBD1,0x17DF54};
+
+const BIG_XXX TEST_Pxa={0x1047D566,0xD83CD71,0x10322E9D,0x991FA93,0xA282C48,0x18AEBEC8,0xCB05850,0x13B4F669,0x21794A};
+const BIG_XXX TEST_Pxb={0x1E305936,0x16885BF1,0x327060,0xE26F794,0x1547D870,0x1963E5B2,0x1BEBB96C,0x988A33C,0x1A9B47};
+const BIG_XXX TEST_Pya={0x20FF876,0x4427E67,0x18732211,0xE88E45E,0x174D1A7E,0x17D877ED,0x343AB37,0x97EB453,0xB00D5};
+const BIG_XXX TEST_Pyb={0x1D746B7B,0x732F4C2,0x122A49B0,0x16267985,0x235DF56,0x10B1E4D,0x14D8F210,0x17A05C3E,0x5ECF8};
+
+#endif
+
+#if CHOICE==BN254_T2
+
+const BIG_XXX TEST_Gx={0x15488765,0x46790D7,0xD9900A,0x1DFB43F,0x9F2D307,0xC4724E8,0x5678E51,0x15C3E3A7,0x1BEC8E};
+const BIG_XXX TEST_Gy={0x3D3273C,0x1AFA5FF,0x1880A139,0xACD34DF,0x17493067,0x10FA4103,0x1D4C9766,0x1A73F3DB,0x2D148};
+
+const BIG_XXX TEST_Pxa={0xF8DC275,0xAC27FA,0x11815151,0x152691C8,0x5CDEBF1,0x7D5A965,0x1BF70CE3,0x679A1C8,0xD62CF};
+const BIG_XXX TEST_Pxb={0x1D17D7A8,0x6B28DF4,0x174A0389,0xFE67E5F,0x1FA97A3C,0x7F5F473,0xFFB5146,0x4BC19A5,0x227010};
+const BIG_XXX TEST_Pya={0x16CC1F90,0x5284627,0x171B91AB,0x11F843B9,0x1D468755,0x67E279C,0x19FE0EF8,0x1A0CAA6B,0x1CC6CB};
+const BIG_XXX TEST_Pyb={0x1FF0CF2A,0xBC83255,0x6DD6EE8,0xB8B752F,0x13E484EC,0x1809BE81,0x1A648AA1,0x8CEF3F3,0x86EE};
+
+
+#endif
+
+#if CHOICE==BN254
+
+const BIG_XXX TEST_Gx={0x14BEC4670E4EB7,0xEA2973860F6861,0x35C14B2FC3C28F,0x4402A0B63B9473,0x2074A81D};
+const BIG_XXX TEST_Gy={0xC284846631CBEB,0x34A6E8D871B3B,0x89FB94A82B2006,0x87B20038771FC,0x6A41108};
+
+const BIG_XXX TEST_Pxa={0xE4A00F52183C77,0x554E02DF4F8354,0xB65EB5CF1C2F89,0x8B71A87BFCFC9,0x49EEDB1};
+const BIG_XXX TEST_Pxb={0xCFB8FA9AA8845D,0x8A9CC76D966697,0x185BA05BF5EC08,0x76140E87D97226,0x1FB93AB6};
+const BIG_XXX TEST_Pya={0x3644CC1EDF208A,0xA637FB3FF8E257,0x4453DA2BB9E686,0xD14AD3CDF6A1FE,0xCD04A1E};
+const BIG_XXX TEST_Pyb={0x71BD7630A43C14,0x1CAA9F14EA264E,0x3C3C2DFC765DEF,0xCF59D1A1A7D6EE,0x11FF7795};
+
+
+#endif
+*/
+int main()
+{
+    int i;
+    char byt[32];
+    csprng rng;
+    BIG_XXX xa,xb,ya,yb,w,a,b,t1,q,u[2],v[4],m,r;
+    ECP2_ZZZ P,G;
+    ECP_ZZZ Q,R;
+    FP12_YYY g,gp;
+    FP4_YYY t,c,cp,cpm1,cpm2;
+    FP2_YYY x,y,X;
+
+
+    BIG_XXX_rcopy(a,CURVE_Fra);
+    BIG_XXX_rcopy(b,CURVE_Frb);
+    FP2_YYY_from_BIGs(&X,a,b);
+
+    BIG_XXX_rcopy(xa,CURVE_Gx);
+    BIG_XXX_rcopy(ya,CURVE_Gy);
+
+    ECP_ZZZ_set(&Q,xa,ya);
+    if (Q.inf) printf("Failed to set - point not on curve\n");
+    else printf("G1 set success\n");
+
+    printf("Q= ");
+    ECP_ZZZ_output(&Q);
+    printf("\n");
+
+//	BIG_XXX_rcopy(r,CURVE_Order); BIG_XXX_dec(r,7); BIG_XXX_norm(r);
+    BIG_XXX_rcopy(xa,CURVE_Pxa);
+    BIG_XXX_rcopy(xb,CURVE_Pxb);
+    BIG_XXX_rcopy(ya,CURVE_Pya);
+    BIG_XXX_rcopy(yb,CURVE_Pyb);
+
+    FP2_YYY_from_BIGs(&x,xa,xb);
+    FP2_YYY_from_BIGs(&y,ya,yb);
+
+    ECP2_ZZZ_set(&P,&x,&y);
+    if (P.inf) printf("Failed to set - point not on curve\n");
+    else printf("G2 set success\n");
+
+    printf("P= ");
+    ECP2_ZZZ_output(&P);
+    printf("\n");
+
+    for (i=0; i<1000; i++ )
+    {
+
+        PAIR_ZZZ_ate(&g,&P,&Q);
+        PAIR_ZZZ_fexp(&g);
+
+//	PAIR_ZZZ_GTpow(&g,xa);
+
+    }
+    printf("g= ");
+    FP12_YYY_output(&g);
+    printf("\n");
+
+}
+
+#endif
diff --git a/version3/c/pair.h b/version3/c/pair.h
new file mode 100644
index 0000000..81b710c
--- /dev/null
+++ b/version3/c/pair.h
@@ -0,0 +1,103 @@
+/*
+	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.
+*/
+
+/**
+ * @file pair.h
+ * @author Mike Scott
+ * @brief PAIR Header File
+ *
+ */
+
+#ifndef PAIR_ZZZ_H
+#define PAIR_ZZZ_H
+
+#include "fp12_YYY.h"
+#include "ecp2_ZZZ.h"
+#include "ecp_ZZZ.h"
+
+/* Pairing constants */
+
+extern const BIG_XXX CURVE_Bnx_ZZZ; /**< BN curve x parameter */
+extern const BIG_XXX CURVE_Cru_ZZZ; /**< BN curve Cube Root of Unity */
+
+extern const BIG_XXX CURVE_W_ZZZ[2];	 /**< BN curve constant for GLV decomposition */
+extern const BIG_XXX CURVE_SB_ZZZ[2][2]; /**< BN curve constant for GLV decomposition */
+extern const BIG_XXX CURVE_WB_ZZZ[4];	 /**< BN curve constant for GS decomposition */
+extern const BIG_XXX CURVE_BB_ZZZ[4][4]; /**< BN curve constant for GS decomposition */
+
+/* Pairing function prototypes */
+/**	@brief Calculate Miller loop for Optimal ATE pairing e(P,Q)
+ *
+	@param r FP12 result of the pairing calculation e(P,Q)
+	@param P ECP2 instance, an element of G2
+	@param Q ECP instance, an element of G1
+
+ */
+extern void PAIR_ZZZ_ate(FP12_YYY *r,ECP2_ZZZ *P,ECP_ZZZ *Q);
+/**	@brief Calculate Miller loop for Optimal ATE double-pairing e(P,Q).e(R,S)
+ *
+	Faster than calculating two separate pairings
+	@param r FP12 result of the pairing calculation e(P,Q).e(R,S), an element of GT
+	@param P ECP2 instance, an element of G2
+	@param Q ECP instance, an element of G1
+	@param R ECP2 instance, an element of G2
+	@param S ECP instance, an element of G1
+ */
+extern void PAIR_ZZZ_double_ate(FP12_YYY *r,ECP2_ZZZ *P,ECP_ZZZ *Q,ECP2_ZZZ *R,ECP_ZZZ *S);
+/**	@brief Final exponentiation of pairing, converts output of Miller loop to element in GT
+ *
+	Here p is the internal modulus, and r is the group order
+	@param x FP12, on exit = x^((p^12-1)/r)
+ */
+extern void PAIR_ZZZ_fexp(FP12_YYY *x);
+/**	@brief Fast point multiplication of a member of the group G1 by a BIG number
+ *
+	May exploit endomorphism for speed.
+	@param Q ECP member of G1.
+	@param b BIG multiplier
+
+ */
+extern void PAIR_ZZZ_G1mul(ECP_ZZZ *Q,BIG_XXX b);
+/**	@brief Fast point multiplication of a member of the group G2 by a BIG number
+ *
+	May exploit endomorphism for speed.
+	@param P ECP2 member of G1.
+	@param b BIG multiplier
+
+ */
+extern void PAIR_ZZZ_G2mul(ECP2_ZZZ *P,BIG_XXX b);
+/**	@brief Fast raising of a member of GT to a BIG power
+ *
+	May exploit endomorphism for speed.
+	@param x FP12 member of GT.
+	@param b BIG exponent
+
+ */
+extern void PAIR_ZZZ_GTpow(FP12_YYY *x,BIG_XXX b);
+/**	@brief Tests FP12 for membership of GT
+ *
+	@param x FP12 instance
+	@return 1 if x is in GT, else return 0
+
+ */
+extern int PAIR_ZZZ_GTmember(FP12_YYY *x);
+
+
+
+#endif
diff --git a/version3/c/pair192.c b/version3/c/pair192.c
new file mode 100644
index 0000000..55cbfe7
--- /dev/null
+++ b/version3/c/pair192.c
@@ -0,0 +1,752 @@
+/*
+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.
+*/
+
+/* AMCL BLS Curve pairing functions */
+
+//#define HAS_MAIN
+
+#include "pair192_ZZZ.h"
+
+
+/* Line function */
+static void PAIR_ZZZ_line(FP24_YYY *v,ECP4_ZZZ *A,ECP4_ZZZ *B,FP_YYY *Qx,FP_YYY *Qy)
+{
+	FP4_YYY X1,Y1,T1,T2;
+	FP4_YYY XX,YY,ZZ,YZ;
+    FP8_YYY a,b,c;
+
+	if (A==B)
+    {
+        /* doubling */
+ 		FP4_YYY_copy(&XX,&(A->x));	//FP4_YYY XX=new FP4_YYY(A.getx());  //X
+		FP4_YYY_copy(&YY,&(A->y));	//FP4_YYY YY=new FP4_YYY(A.gety());  //Y
+		FP4_YYY_copy(&ZZ,&(A->z));	//FP4_YYY ZZ=new FP4_YYY(A.getz());  //Z
+
+
+		FP4_YYY_copy(&YZ,&YY);		//FP4_YYY YZ=new FP4_YYY(YY);        //Y 
+		FP4_YYY_mul(&YZ,&YZ,&ZZ);		//YZ.mul(ZZ);                //YZ
+		FP4_YYY_sqr(&XX,&XX);		//XX.sqr();	               //X^2
+		FP4_YYY_sqr(&YY,&YY);		//YY.sqr();	               //Y^2
+		FP4_YYY_sqr(&ZZ,&ZZ);		//ZZ.sqr();			       //Z^2
+			
+		FP4_YYY_imul(&YZ,&YZ,4);	//YZ.imul(4);
+		FP4_YYY_neg(&YZ,&YZ);		//YZ.neg(); 
+		FP4_YYY_norm(&YZ);			//YZ.norm();       //-4YZ
+
+		FP4_YYY_imul(&XX,&XX,6);					//6X^2
+		FP4_YYY_qmul(&XX,&XX,Qx);	               //6X^2.Xs
+
+		FP4_YYY_imul(&ZZ,&ZZ,3*CURVE_B_I_ZZZ);	//3Bz^2 
+
+		FP4_YYY_qmul(&YZ,&YZ,Qy);	//-4YZ.Ys
+
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+		FP4_YYY_div_2i(&ZZ);		//6(b/i)z^2
+#endif
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+		FP4_YYY_times_i(&ZZ);
+		FP4_YYY_add(&ZZ,&ZZ,&ZZ);  // 6biz^2
+		FP4_YYY_times_i(&YZ);
+		FP4_YYY_norm(&YZ);	
+#endif
+		FP4_YYY_norm(&ZZ);			// 6bi.Z^2 
+
+		FP4_YYY_add(&YY,&YY,&YY);	// 2y^2
+		FP4_YYY_sub(&ZZ,&ZZ,&YY);	// 
+		FP4_YYY_norm(&ZZ);			// 6b.Z^2-2Y^2
+
+		FP8_YYY_from_FP4s(&a,&YZ,&ZZ); // -4YZ.Ys | 6b.Z^2-2Y^2 | 6X^2.Xs 
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+		FP8_YYY_from_FP4(&b,&XX);	
+		FP8_YYY_zero(&c);
+#endif
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+		FP8_YYY_zero(&b);
+		FP8_YYY_from_FP4H(&c,&XX);
+#endif
+
+		ECP4_ZZZ_dbl(A);				//A.dbl();
+    }
+    else
+    {
+        /* addition */
+
+		FP4_YYY_copy(&X1,&(A->x));		//FP4_YYY X1=new FP4_YYY(A.getx());    // X1
+		FP4_YYY_copy(&Y1,&(A->y));		//FP4_YYY Y1=new FP4_YYY(A.gety());    // Y1
+		FP4_YYY_copy(&T1,&(A->z));		//FP4_YYY T1=new FP4_YYY(A.getz());    // Z1
+			
+		FP4_YYY_copy(&T2,&T1);		//FP4_YYY T2=new FP4_YYY(A.getz());    // Z1
+
+		FP4_YYY_mul(&T1,&T1,&(B->y));	//T1.mul(B.gety());    // T1=Z1.Y2 
+		FP4_YYY_mul(&T2,&T2,&(B->x));	//T2.mul(B.getx());    // T2=Z1.X2
+
+		FP4_YYY_sub(&X1,&X1,&T2);		//X1.sub(T2); 
+		FP4_YYY_norm(&X1);				//X1.norm();  // X1=X1-Z1.X2
+		FP4_YYY_sub(&Y1,&Y1,&T1);		//Y1.sub(T1); 
+		FP4_YYY_norm(&Y1);				//Y1.norm();  // Y1=Y1-Z1.Y2
+
+		FP4_YYY_copy(&T1,&X1);			//T1.copy(X1);            // T1=X1-Z1.X2
+
+		FP4_YYY_qmul(&X1,&X1,Qy);		//X1.pmul(Qy);            // X1=(X1-Z1.X2).Ys
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+		FP4_YYY_times_i(&X1);
+		FP4_YYY_norm(&X1);
+#endif
+
+		FP4_YYY_mul(&T1,&T1,&(B->y));	//T1.mul(B.gety());       // T1=(X1-Z1.X2).Y2
+
+		FP4_YYY_copy(&T2,&Y1);			//T2.copy(Y1);            // T2=Y1-Z1.Y2
+		FP4_YYY_mul(&T2,&T2,&(B->x));	//T2.mul(B.getx());       // T2=(Y1-Z1.Y2).X2
+		FP4_YYY_sub(&T2,&T2,&T1);		//T2.sub(T1); 
+		FP4_YYY_norm(&T2);				//T2.norm();          // T2=(Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2
+		FP4_YYY_qmul(&Y1,&Y1,Qx);		//Y1.pmul(Qx);  
+		FP4_YYY_neg(&Y1,&Y1);			//Y1.neg(); 
+		FP4_YYY_norm(&Y1);				//Y1.norm(); // Y1=-(Y1-Z1.Y2).Xs
+
+		FP8_YYY_from_FP4s(&a,&X1,&T2);	// (X1-Z1.X2).Ys  |  (Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2  | - (Y1-Z1.Y2).Xs
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+		FP8_YYY_from_FP4(&b,&Y1);		//b=new FP4(Y1);
+		FP8_YYY_zero(&c);
+#endif
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+		FP8_YYY_zero(&b);
+		FP8_YYY_from_FP4H(&c,&Y1);		//b=new FP4(Y1);
+#endif
+		ECP4_ZZZ_add(A,B);			//A.add(B);
+    }
+
+    FP24_YYY_from_FP8s(v,&a,&b,&c);
+}
+
+/* Optimal R-ate pairing r=e(P,Q) */
+void PAIR_ZZZ_ate(FP24_YYY *r,ECP4_ZZZ *P1,ECP_ZZZ *Q1)
+{
+    BIG_XXX x,n,n3;
+	FP_YYY Qx,Qy;
+    int i,j,nb,bt;
+    ECP4_ZZZ A,NP,P;
+	ECP_ZZZ Q;
+    FP24_YYY lv;
+
+    BIG_XXX_rcopy(x,CURVE_Bnx_ZZZ);
+
+    BIG_XXX_copy(n,x);
+
+    //BIG_XXX_norm(n);
+	BIG_XXX_pmul(n3,n,3);
+	BIG_XXX_norm(n3);
+
+	ECP4_ZZZ_copy(&P,P1);
+	ECP_ZZZ_copy(&Q,Q1);
+
+	ECP4_ZZZ_affine(&P);
+	ECP_ZZZ_affine(&Q);
+
+
+    FP_YYY_copy(&Qx,&(Q.x));
+    FP_YYY_copy(&Qy,&(Q.y));
+
+    ECP4_ZZZ_copy(&A,&P);
+	ECP4_ZZZ_copy(&NP,&P); ECP4_ZZZ_neg(&NP);
+
+    FP24_YYY_one(r);
+    nb=BIG_XXX_nbits(n3);  // n3
+
+	j=0;
+    /* Main Miller Loop */
+    for (i=nb-2; i>=1; i--)
+    {
+		j++;
+		FP24_YYY_sqr(r,r);
+        PAIR_ZZZ_line(&lv,&A,&A,&Qx,&Qy);
+        FP24_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+//printf("r= "); FP24_YYY_output(r); printf("\n");
+//if (j>3) exit(0);
+		bt= BIG_XXX_bit(n3,i)-BIG_XXX_bit(n,i);  // BIG_XXX_bit(n,i); 
+        if (bt==1)
+        {
+//printf("bt=1\n");
+            PAIR_ZZZ_line(&lv,&A,&P,&Qx,&Qy);
+            FP24_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+        }
+		if (bt==-1)
+		{
+//printf("bt=-1\n");
+			//ECP4_ZZZ_neg(P);
+            PAIR_ZZZ_line(&lv,&A,&NP,&Qx,&Qy);
+            FP24_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+			//ECP4_ZZZ_neg(P);
+		}
+
+    }
+
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+    FP24_YYY_conj(r,r);
+#endif
+
+}
+
+/* Optimal R-ate double pairing e(P,Q).e(R,S) */
+void PAIR_ZZZ_double_ate(FP24_YYY *r,ECP4_ZZZ *P1,ECP_ZZZ *Q1,ECP4_ZZZ *R1,ECP_ZZZ *S1)
+{
+    BIG_XXX x,n,n3;
+	FP_YYY Qx,Qy,Sx,Sy;
+    int i,nb,bt;
+    ECP4_ZZZ A,B,NP,NR,P,R;
+	ECP_ZZZ Q,S;
+    FP24_YYY lv;
+
+    BIG_XXX_rcopy(x,CURVE_Bnx_ZZZ);
+    BIG_XXX_copy(n,x);
+
+    //BIG_XXX_norm(n);
+	BIG_XXX_pmul(n3,n,3);
+	BIG_XXX_norm(n3);
+
+	ECP4_ZZZ_copy(&P,P1);
+	ECP_ZZZ_copy(&Q,Q1);
+
+	ECP4_ZZZ_affine(&P);
+	ECP_ZZZ_affine(&Q);
+
+	ECP4_ZZZ_copy(&R,R1);
+	ECP_ZZZ_copy(&S,S1);
+
+	ECP4_ZZZ_affine(&R);
+	ECP_ZZZ_affine(&S);
+
+
+    FP_YYY_copy(&Qx,&(Q.x));
+    FP_YYY_copy(&Qy,&(Q.y));
+
+    FP_YYY_copy(&Sx,&(S.x));
+    FP_YYY_copy(&Sy,&(S.y));
+
+    ECP4_ZZZ_copy(&A,&P);
+    ECP4_ZZZ_copy(&B,&R);
+	ECP4_ZZZ_copy(&NP,&P); ECP4_ZZZ_neg(&NP);
+	ECP4_ZZZ_copy(&NR,&R); ECP4_ZZZ_neg(&NR);
+
+
+    FP24_YYY_one(r);
+    nb=BIG_XXX_nbits(n3);
+
+    /* Main Miller Loop */
+    for (i=nb-2; i>=1; i--)
+    {
+        FP24_YYY_sqr(r,r);
+        PAIR_ZZZ_line(&lv,&A,&A,&Qx,&Qy);
+        FP24_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+
+        PAIR_ZZZ_line(&lv,&B,&B,&Sx,&Sy);
+        FP24_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+
+		bt=BIG_XXX_bit(n3,i)-BIG_XXX_bit(n,i); // bt=BIG_XXX_bit(n,i);
+        if (bt==1)
+        {
+            PAIR_ZZZ_line(&lv,&A,&P,&Qx,&Qy);
+            FP24_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+
+            PAIR_ZZZ_line(&lv,&B,&R,&Sx,&Sy);
+            FP24_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+        }
+		if (bt==-1)
+		{
+			//ECP4_ZZZ_neg(P); 
+            PAIR_ZZZ_line(&lv,&A,&NP,&Qx,&Qy);
+            FP24_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+			//ECP4_ZZZ_neg(P); 
+			//ECP4_ZZZ_neg(R);
+            PAIR_ZZZ_line(&lv,&B,&NR,&Sx,&Sy);
+            FP24_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+			//ECP4_ZZZ_neg(R);
+		}
+	}
+
+
+
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+    FP24_YYY_conj(r,r);
+#endif
+
+}
+
+/* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */
+
+void PAIR_ZZZ_fexp(FP24_YYY *r)
+{
+    FP2_YYY X;
+    BIG_XXX x;
+	FP_YYY a,b;
+    FP24_YYY t0,t1,t2,t3,t4,t5,t6,t7;  // could lose one of these - r=t3
+
+    BIG_XXX_rcopy(x,CURVE_Bnx_ZZZ);
+    FP_YYY_rcopy(&a,Fra_YYY);
+    FP_YYY_rcopy(&b,Frb_YYY);
+    FP2_YYY_from_FPs(&X,&a,&b);
+
+    /* Easy part of final exp - r^(p^12-1)(p^4+1)*/
+
+    FP24_YYY_inv(&t0,r);
+    FP24_YYY_conj(r,r);
+
+    FP24_YYY_mul(r,&t0);
+    FP24_YYY_copy(&t0,r);
+
+    FP24_YYY_frob(r,&X,4);
+
+    FP24_YYY_mul(r,&t0);
+
+// Ghamman & Fouotsa Method - (completely garbled in  https://eprint.iacr.org/2016/130)
+
+	FP24_YYY_usqr(&t7,r);			// t7=f^2
+	FP24_YYY_pow(&t1,&t7,x);		// t1=t7^u
+
+	BIG_XXX_fshr(x,1);
+	FP24_YYY_pow(&t2,&t1,x);		// t2=t1^(u/2)
+	BIG_XXX_fshl(x,1);  // x must be even
+
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP24_YYY_conj(&t1,&t1);
+#endif
+
+	FP24_YYY_conj(&t3,&t1);		// t3=1/t1
+	FP24_YYY_mul(&t2,&t3);		// t2=t1*t3
+	FP24_YYY_mul(&t2,r);		// t2=t2*f
+
+
+	FP24_YYY_pow(&t3,&t2,x);		// t3=t2^u
+	FP24_YYY_pow(&t4,&t3,x);		// t4=t3^u
+	FP24_YYY_pow(&t5,&t4,x);		// t5=t4^u
+
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP24_YYY_conj(&t3,&t3);
+	FP24_YYY_conj(&t5,&t5);
+#endif
+
+	FP24_YYY_frob(&t3,&X,6);
+	FP24_YYY_frob(&t4,&X,5);
+
+	FP24_YYY_mul(&t3,&t4);		// t3=t3.t4
+
+
+	FP24_YYY_pow(&t6,&t5,x);		// t6=t5^u
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP24_YYY_conj(&t6,&t6);
+#endif
+
+
+	FP24_YYY_frob(&t5,&X,4); 
+	FP24_YYY_mul(&t3,&t5); // ??
+
+
+	FP24_YYY_conj(&t0,&t2);			// t0=1/t2
+	FP24_YYY_mul(&t6,&t0);		// t6=t6*t0
+
+	FP24_YYY_copy(&t5,&t6);
+	FP24_YYY_frob(&t5,&X,3); 
+
+	FP24_YYY_mul(&t3,&t5);		// t3=t3*t5
+	FP24_YYY_pow(&t5,&t6,x);	// t5=t6^x
+	FP24_YYY_pow(&t6,&t5,x);	// t6=t5^x
+
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP24_YYY_conj(&t5,&t5);
+#endif
+
+	FP24_YYY_copy(&t0,&t5);	
+	FP24_YYY_frob(&t0,&X,2); 
+	FP24_YYY_mul(&t3,&t0);		// t3=t3*t0
+	FP24_YYY_copy(&t0,&t6);     // 
+	FP24_YYY_frob(&t0,&X,1);
+
+	FP24_YYY_mul(&t3,&t0);		// t3=t3*t0
+	FP24_YYY_pow(&t5,&t6,x);    // t5=t6*x
+
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP24_YYY_conj(&t5,&t5);
+#endif
+
+	FP24_YYY_frob(&t2,&X,7); 
+
+	FP24_YYY_mul(&t5,&t7);		// t5=t5*t7
+	FP24_YYY_mul(&t3,&t2);		// t3=t3*t2
+	FP24_YYY_mul(&t3,&t5);		// t3=t3*t5
+
+	FP24_YYY_mul(r,&t3);
+	FP24_YYY_reduce(r);
+
+}
+
+#ifdef USE_GLV_ZZZ
+/* GLV method */
+static void glv(BIG_XXX u[2],BIG_XXX e)
+{
+
+// -(x^4).P = (Beta.x,y)
+
+    BIG_XXX x,x2,q;
+    BIG_XXX_rcopy(x,CURVE_Bnx_ZZZ);
+    BIG_XXX_smul(x2,x,x);
+	BIG_XXX_smul(x,x2,x2);
+    BIG_XXX_copy(u[0],e);
+    BIG_XXX_mod(u[0],x);
+    BIG_XXX_copy(u[1],e);
+    BIG_XXX_sdiv(u[1],x);
+
+    BIG_XXX_rcopy(q,CURVE_Order_ZZZ);
+    BIG_XXX_sub(u[1],q,u[1]);
+
+
+    return;
+}
+#endif // USE_GLV
+
+/* Galbraith & Scott Method */
+static void gs(BIG_XXX u[8],BIG_XXX e)
+{
+    int i;
+
+    BIG_XXX x,w,q;
+	BIG_XXX_rcopy(q,CURVE_Order_ZZZ);
+    BIG_XXX_rcopy(x,CURVE_Bnx_ZZZ);
+    BIG_XXX_copy(w,e);
+
+    for (i=0; i<7; i++)
+    {
+        BIG_XXX_copy(u[i],w);
+        BIG_XXX_mod(u[i],x);
+        BIG_XXX_sdiv(w,x);
+    }
+	BIG_XXX_copy(u[7],w);
+
+/*  */
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	BIG_XXX_modneg(u[1],u[1],q);
+	BIG_XXX_modneg(u[3],u[3],q);
+	BIG_XXX_modneg(u[5],u[5],q);
+	BIG_XXX_modneg(u[7],u[7],q);
+#endif
+
+
+    return;
+}
+
+/* Multiply P by e in group G1 */
+void PAIR_ZZZ_G1mul(ECP_ZZZ *P,BIG_XXX e)
+{
+#ifdef USE_GLV_ZZZ   /* Note this method is patented */
+    int np,nn;
+    ECP_ZZZ Q;
+	FP_YYY cru;
+    BIG_XXX t,q;
+    BIG_XXX u[2];
+
+    BIG_XXX_rcopy(q,CURVE_Order_ZZZ);
+    glv(u,e);
+
+   // ECP_ZZZ_affine(P);
+    ECP_ZZZ_copy(&Q,P); ECP_ZZZ_affine(&Q);
+    FP_YYY_rcopy(&cru,CURVE_Cru_ZZZ);
+    FP_YYY_mul(&(Q.x),&(Q.x),&cru);
+
+    /* note that -a.B = a.(-B). Use a or -a depending on which is smaller */
+
+    np=BIG_XXX_nbits(u[0]);
+    BIG_XXX_modneg(t,u[0],q);
+    nn=BIG_XXX_nbits(t);
+    if (nn<np)
+    {
+        BIG_XXX_copy(u[0],t);
+        ECP_ZZZ_neg(P);
+    }
+
+    np=BIG_XXX_nbits(u[1]);
+    BIG_XXX_modneg(t,u[1],q);
+    nn=BIG_XXX_nbits(t);
+    if (nn<np)
+    {
+        BIG_XXX_copy(u[1],t);
+        ECP_ZZZ_neg(&Q);
+    }
+    BIG_XXX_norm(u[0]);
+    BIG_XXX_norm(u[1]);    
+    ECP_ZZZ_mul2(P,&Q,u[0],u[1]);
+
+#else
+    ECP_ZZZ_mul(P,e);
+#endif
+}
+
+/* Multiply P by e in group G2 */
+void PAIR_ZZZ_G2mul(ECP4_ZZZ *P,BIG_XXX e)
+{
+#ifdef USE_GS_G2_ZZZ   /* Well I didn't patent it :) */
+    int i,np,nn;
+    ECP4_ZZZ Q[8];
+    FP2_YYY X[3];
+    BIG_XXX x,y,u[8];
+
+	ECP4_ZZZ_frob_constants(X);
+
+    BIG_XXX_rcopy(y,CURVE_Order_ZZZ);
+    gs(u,e);
+
+    //ECP4_ZZZ_affine(P);
+
+    ECP4_ZZZ_copy(&Q[0],P);
+    for (i=1; i<8; i++)
+    {
+        ECP4_ZZZ_copy(&Q[i],&Q[i-1]);
+        ECP4_ZZZ_frob(&Q[i],X,1);
+    }
+
+    for (i=0; i<8; i++)
+    {
+        np=BIG_XXX_nbits(u[i]);
+        BIG_XXX_modneg(x,u[i],y);
+        nn=BIG_XXX_nbits(x);
+        if (nn<np)
+        {
+            BIG_XXX_copy(u[i],x);
+            ECP4_ZZZ_neg(&Q[i]);
+        }
+        BIG_XXX_norm(u[i]);   
+		//ECP4_ZZZ_affine(&Q[i]);
+    }
+
+    ECP4_ZZZ_mul8(P,Q,u);
+
+#else
+    ECP4_ZZZ_mul(P,e);
+#endif
+}
+
+/* f=f^e */
+void PAIR_ZZZ_GTpow(FP24_YYY *f,BIG_XXX e)
+{
+#ifdef USE_GS_GT_ZZZ   /* Note that this option requires a lot of RAM! Maybe better to use compressed XTR method, see FP8.c */
+    int i,np,nn;
+    FP24_YYY g[8];
+    FP2_YYY X;
+    BIG_XXX t,q;
+	FP_YYY fx,fy;
+    BIG_XXX u[8];
+
+    FP_YYY_rcopy(&fx,Fra_YYY);
+    FP_YYY_rcopy(&fy,Frb_YYY);
+    FP2_YYY_from_FPs(&X,&fx,&fy);
+
+    BIG_XXX_rcopy(q,CURVE_Order_ZZZ);
+    gs(u,e);
+
+    FP24_YYY_copy(&g[0],f);
+    for (i=1; i<8; i++)
+    {
+        FP24_YYY_copy(&g[i],&g[i-1]);
+        FP24_YYY_frob(&g[i],&X,1);
+    }
+
+    for (i=0; i<8; i++)
+    {
+        np=BIG_XXX_nbits(u[i]);
+        BIG_XXX_modneg(t,u[i],q);
+        nn=BIG_XXX_nbits(t);
+        if (nn<np)
+        {
+            BIG_XXX_copy(u[i],t);
+            FP24_YYY_conj(&g[i],&g[i]);
+        }
+        BIG_XXX_norm(u[i]);        
+    }
+    FP24_YYY_pow8(f,g,u);
+
+#else
+    FP24_YYY_pow(f,f,e);
+#endif
+}
+
+/* test group membership test - no longer needed */
+/* with GT-Strong curve, now only check that m!=1, conj(m)*m==1, and m.m^{p^4}=m^{p^2} */
+
+/*
+int PAIR_GTmember(FP24_YYY *m)
+{
+	BIG_XXX a,b;
+	FP2_YYY X;
+	FP24_YYY r,w;
+	if (FP24_YYY_isunity(m)) return 0;
+	FP24_YYY_conj(&r,m);
+	FP24_YYY_mul(&r,m);
+	if (!FP24_YYY_isunity(&r)) return 0;
+
+	BIG_XXX_rcopy(a,CURVE_Fra);
+	BIG_XXX_rcopy(b,CURVE_Frb);
+	FP2_YYY from_BIGs(&X,a,b);
+
+
+	FP24_YYY_copy(&r,m); FP24_YYY_frob(&r,&X); FP24_YYY_frob(&r,&X);
+	FP24_YYY_copy(&w,&r); FP24_YYY_frob(&w,&X); FP24_YYY_frob(&w,&X);
+	FP24_YYY_mul(&w,m);
+
+
+#ifndef GT_STRONG
+	if (!FP24_YYY_equals(&w,&r)) return 0;
+
+	BIG_XXX_rcopy(a,CURVE_Bnx);
+
+	FP24_YYY_copy(&r,m); FP24_YYY_pow(&w,&r,a); FP24_YYY_pow(&w,&w,a);
+	FP24_YYY_sqr(&r,&w); FP24_YYY_mul(&r,&w); FP24_YYY_sqr(&r,&r);
+
+	FP24_YYY_copy(&w,m); FP24_YYY_frob(&w,&X);
+ #endif
+
+	return FP24_YYY_equals(&w,&r);
+}
+
+*/
+
+
+#ifdef HAS_MAIN
+
+using namespace std;
+using namespace ZZZ;
+
+
+// g++ -O2 pair192_BLS24.cpp ecp4_BLS24.cpp fp24_BLS24.cpp fp8_BLS24.cpp fp4_BLS24.cpp fp2_BLS24.cpp ecp_BLS24.cpp fp_BLS24.cpp big_XXX.cpp rom_curve_BLS24.cpp rom_field_BLS24.cpp rand.cpp hash.cpp oct.cpp -o pair192_BLS24.exe
+
+int main()
+{
+    int i;
+    char byt[32];
+    csprng rng;
+    BIG_XXX xa,xb,ya,yb,w,a,b,t1,q,u[2],v[4],m,r,xx,x2,x4,p;
+    ECP4_ZZZ P,G;
+    ECP_ZZZ Q,R;
+    FP24 g,gp;
+    FP8_YYY t,c,cp,cpm1,cpm2;
+	FP4_YYY X,Y;
+    FP2_YYY x,y,f,Aa,Bb;
+	FP_YYY cru;
+
+	for (i=0;i<32;i++)
+		byt[i]=i+9;
+	RAND_seed(&rng,32,byt);
+
+	BIG_XXX_rcopy(r,CURVE_Order);
+	BIG_XXX_rcopy(p,Modulus);
+
+
+    BIG_XXX_rcopy(xa,CURVE_Gx);
+    BIG_XXX_rcopy(ya,CURVE_Gy);
+
+    ECP_set(&Q,xa,ya);
+    if (Q.inf) printf("Failed to set - point not on curve\n");
+    else printf("G1 set success\n");
+
+    printf("Q= ");
+    ECP_output(&Q);
+    printf("\n");
+
+	ECP4_ZZZ_generator(&P);
+
+    if (P.inf) printf("Failed to set - point not on curve\n");
+    else printf("G2 set success\n");
+
+    BIG_XXX_rcopy(a,Fra);
+    BIG_XXX_rcopy(b,Frb);
+    FP2_YYY from_BIGs(&f,a,b);
+
+
+//exit(0);
+
+    PAIR_ate(&g,&P,&Q);
+
+	printf("gb= ");
+    FP24_output(&g);
+    printf("\n");
+    PAIR_fexp(&g);
+
+    printf("g= ");
+    FP24_output(&g);
+    printf("\n");
+
+	//FP24_pow(&g,&g,r);
+
+   // printf("g^r= ");
+    //FP24_output(&g);
+    //printf("\n");
+
+	ECP_copy(&R,&Q);
+	ECP4_ZZZ_copy(&G,&P);
+
+	ECP4_ZZZ_dbl(&G);
+	ECP_dbl(&R);
+	ECP_affine(&R);
+
+    PAIR_ate(&g,&G,&Q);
+    PAIR_fexp(&g);
+
+    printf("g1= ");
+    FP24_output(&g);
+    printf("\n");
+
+    PAIR_ate(&g,&P,&R);
+    PAIR_fexp(&g);
+
+    printf("g2= ");
+    FP24_output(&g);
+    printf("\n");
+
+
+	PAIR_G1mul(&Q,r);
+	printf("rQ= ");ECP_output(&Q); printf("\n");
+
+	PAIR_G2mul(&P,r);
+	printf("rP= ");ECP4_ZZZ_output(&P); printf("\n");
+
+	//PAIR_GTpow(&g,r);
+	//printf("g^r= ");FP24_output(&g); printf("\n");
+
+
+	BIG_XXX_randomnum(w,r,&rng);
+
+	FP24_copy(&gp,&g);
+
+	PAIR_GTpow(&g,w);
+
+	FP24_trace(&t,&g);
+
+	printf("g^r=  ");FP8_output(&t); printf("\n");
+
+	FP24_compow(&t,&gp,w,r);
+
+	printf("t(g)= "); FP8_output(&t); printf("\n");
+
+//    PAIR_ate(&g,&P,&R);
+//    PAIR_fexp(&g);
+
+//    printf("g= ");
+//    FP24_output(&g);
+//    printf("\n");
+
+//	PAIR_GTpow(&g,xa);
+}
+
+#endif
diff --git a/version3/c/pair192.h b/version3/c/pair192.h
new file mode 100644
index 0000000..2e50d51
--- /dev/null
+++ b/version3/c/pair192.h
@@ -0,0 +1,77 @@
+#ifndef PAIR192_ZZZ_H
+#define PAIR192_ZZZ_H
+
+#include "fp24_YYY.h"
+#include "ecp4_ZZZ.h"
+#include "ecp_ZZZ.h"
+
+
+/* Pairing constants */
+
+extern const BIG_XXX CURVE_Bnx_ZZZ; /**< BN curve x parameter */
+extern const BIG_XXX CURVE_Cru_ZZZ; /**< BN curve Cube Root of Unity */
+
+extern const BIG_XXX CURVE_W_ZZZ[2];	 /**< BN curve constant for GLV decomposition */
+extern const BIG_XXX CURVE_SB_ZZZ[2][2]; /**< BN curve constant for GLV decomposition */
+extern const BIG_XXX CURVE_WB_ZZZ[4];	 /**< BN curve constant for GS decomposition */
+extern const BIG_XXX CURVE_BB_ZZZ[4][4]; /**< BN curve constant for GS decomposition */
+
+/* Pairing function prototypes */
+/**	@brief Calculate Miller loop for Optimal ATE pairing e(P,Q)
+ *
+	@param r FP24 result of the pairing calculation e(P,Q)
+	@param P ECP4 instance, an element of G2
+	@param Q ECP instance, an element of G1
+
+ */
+extern void PAIR_ZZZ_ate(FP24_YYY *r,ECP4_ZZZ *P,ECP_ZZZ *Q);
+/**	@brief Calculate Miller loop for Optimal ATE double-pairing e(P,Q).e(R,S)
+ *
+	Faster than calculating two separate pairings
+	@param r FP24 result of the pairing calculation e(P,Q).e(R,S), an element of GT
+	@param P ECP4 instance, an element of G2
+	@param Q ECP instance, an element of G1
+	@param R ECP4 instance, an element of G2
+	@param S ECP instance, an element of G1
+ */
+extern void PAIR_ZZZ_double_ate(FP24_YYY *r,ECP4_ZZZ *P,ECP_ZZZ *Q,ECP4_ZZZ *R,ECP_ZZZ *S);
+/**	@brief Final exponentiation of pairing, converts output of Miller loop to element in GT
+ *
+	Here p is the internal modulus, and r is the group order
+	@param x FP24, on exit = x^((p^12-1)/r)
+ */
+extern void PAIR_ZZZ_fexp(FP24_YYY *x);
+/**	@brief Fast point multiplication of a member of the group G1 by a BIG number
+ *
+	May exploit endomorphism for speed.
+	@param Q ECP member of G1.
+	@param b BIG multiplier
+
+ */
+extern void PAIR_ZZZ_G1mul(ECP_ZZZ *Q,BIG_XXX b);
+/**	@brief Fast point multiplication of a member of the group G2 by a BIG number
+ *
+	May exploit endomorphism for speed.
+	@param P ECP4 member of G1.
+	@param b BIG multiplier
+
+ */
+extern void PAIR_ZZZ_G2mul(ECP4_ZZZ *P,BIG_XXX b);
+/**	@brief Fast raising of a member of GT to a BIG power
+ *
+	May exploit endomorphism for speed.
+	@param x FP24 member of GT.
+	@param b BIG exponent
+
+ */
+extern void PAIR_ZZZ_GTpow(FP24_YYY *x,BIG_XXX b);
+/**	@brief Tests FP24 for membership of GT
+ *
+	@param x FP24 instance
+	@return 1 if x is in GT, else return 0
+
+ */
+extern int PAIR_ZZZ_GTmember(FP24_YYY *x);
+
+
+#endif
diff --git a/version3/c/pair256.c b/version3/c/pair256.c
new file mode 100644
index 0000000..5608372
--- /dev/null
+++ b/version3/c/pair256.c
@@ -0,0 +1,864 @@
+/*
+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.
+*/
+
+/* AMCL BLS Curve pairing functions */
+
+//#define HAS_MAIN
+
+#include "pair256_ZZZ.h"
+
+/* Line function */
+static void PAIR_ZZZ_line(FP48_YYY *v,ECP8_ZZZ *A,ECP8_ZZZ *B,FP_YYY *Qx,FP_YYY *Qy)
+{
+	//FP2_YYY t;
+
+	FP8_YYY X1,Y1,T1,T2;
+	FP8_YYY XX,YY,ZZ,YZ;
+    FP16_YYY a,b,c;
+
+	if (A==B)
+    {
+        /* doubling */
+ 		FP8_YYY_copy(&XX,&(A->x));	//FP8_YYY XX=new FP8_YYY(A.getx());  //X
+		FP8_YYY_copy(&YY,&(A->y));	//FP8_YYY YY=new FP8_YYY(A.gety());  //Y
+		FP8_YYY_copy(&ZZ,&(A->z));	//FP8_YYY ZZ=new FP8_YYY(A.getz());  //Z
+
+
+		FP8_YYY_copy(&YZ,&YY);		//FP8_YYY YZ=new FP8_YYY(YY);        //Y 
+		FP8_YYY_mul(&YZ,&YZ,&ZZ);		//YZ.mul(ZZ);                //YZ
+		FP8_YYY_sqr(&XX,&XX);		//XX.sqr();	               //X^2
+		FP8_YYY_sqr(&YY,&YY);		//YY.sqr();	               //Y^2
+		FP8_YYY_sqr(&ZZ,&ZZ);		//ZZ.sqr();			       //Z^2
+			
+		FP8_YYY_imul(&YZ,&YZ,4);	//YZ.imul(4);
+		FP8_YYY_neg(&YZ,&YZ);		//YZ.neg(); 
+		FP8_YYY_norm(&YZ);			//YZ.norm();       //-4YZ
+
+		FP8_YYY_imul(&XX,&XX,6);					//6X^2
+		//FP2_YYY_from_FP(&t,Qx);
+		FP8_YYY_tmul(&XX,&XX,Qx);	               //6X^2.Xs
+
+		FP8_YYY_imul(&ZZ,&ZZ,3*CURVE_B_I_ZZZ);	//3Bz^2 
+		//FP2_YYY_from_FP(&t,Qy);
+		FP8_YYY_tmul(&YZ,&YZ,Qy);	//-4YZ.Ys
+
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+		FP8_YYY_div_2i(&ZZ);		//6(b/i)z^2
+#endif
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+		FP8_YYY_times_i(&ZZ);
+		FP8_YYY_add(&ZZ,&ZZ,&ZZ);  // 6biz^2
+		FP8_YYY_times_i(&YZ);
+		FP8_YYY_norm(&YZ);	
+#endif
+		FP8_YYY_norm(&ZZ);			// 6bi.Z^2 
+
+		FP8_YYY_add(&YY,&YY,&YY);	// 2y^2
+		FP8_YYY_sub(&ZZ,&ZZ,&YY);	// 
+		FP8_YYY_norm(&ZZ);			// 6b.Z^2-2Y^2
+
+		FP16_YYY_from_FP8s(&a,&YZ,&ZZ); // -4YZ.Ys | 6b.Z^2-2Y^2 | 6X^2.Xs 
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+		FP16_YYY_from_FP8(&b,&XX);	
+		FP16_YYY_zero(&c);
+#endif
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+		FP16_YYY_zero(&b);
+		FP16_YYY_from_FP8H(&c,&XX);
+#endif
+
+		ECP8_ZZZ_dbl(A);				//A.dbl();
+    }
+    else
+    {
+        /* addition */
+
+		FP8_YYY_copy(&X1,&(A->x));		//FP8_YYY X1=new FP8_YYY(A.getx());    // X1
+		FP8_YYY_copy(&Y1,&(A->y));		//FP8_YYY Y1=new FP8_YYY(A.gety());    // Y1
+		FP8_YYY_copy(&T1,&(A->z));		//FP8_YYY T1=new FP8_YYY(A.getz());    // Z1
+			
+		FP8_YYY_copy(&T2,&T1);		//FP8_YYY T2=new FP8_YYY(A.getz());    // Z1
+
+		FP8_YYY_mul(&T1,&T1,&(B->y));	//T1.mul(B.gety());    // T1=Z1.Y2 
+		FP8_YYY_mul(&T2,&T2,&(B->x));	//T2.mul(B.getx());    // T2=Z1.X2
+
+		FP8_YYY_sub(&X1,&X1,&T2);		//X1.sub(T2); 
+		FP8_YYY_norm(&X1);				//X1.norm();  // X1=X1-Z1.X2
+		FP8_YYY_sub(&Y1,&Y1,&T1);		//Y1.sub(T1); 
+		FP8_YYY_norm(&Y1);				//Y1.norm();  // Y1=Y1-Z1.Y2
+
+		FP8_YYY_copy(&T1,&X1);			//T1.copy(X1);            // T1=X1-Z1.X2
+		//FP2_YYY_from_FP(&t,Qy);
+		FP8_YYY_tmul(&X1,&X1,Qy);		//X1.pmul(Qy);            // X1=(X1-Z1.X2).Ys
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+		FP8_YYY_times_i(&X1);
+		FP8_YYY_norm(&X1);
+#endif
+
+		FP8_YYY_mul(&T1,&T1,&(B->y));	//T1.mul(B.gety());       // T1=(X1-Z1.X2).Y2
+
+		FP8_YYY_copy(&T2,&Y1);			//T2.copy(Y1);            // T2=Y1-Z1.Y2
+		FP8_YYY_mul(&T2,&T2,&(B->x));	//T2.mul(B.getx());       // T2=(Y1-Z1.Y2).X2
+		FP8_YYY_sub(&T2,&T2,&T1);		//T2.sub(T1); 
+		FP8_YYY_norm(&T2);				//T2.norm();          // T2=(Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2
+		//FP2_YYY_from_FP(&t,Qx);
+		FP8_YYY_tmul(&Y1,&Y1,Qx);		//Y1.pmul(Qx);  
+		FP8_YYY_neg(&Y1,&Y1);			//Y1.neg(); 
+		FP8_YYY_norm(&Y1);				//Y1.norm(); // Y1=-(Y1-Z1.Y2).Xs
+
+		FP16_YYY_from_FP8s(&a,&X1,&T2);	// (X1-Z1.X2).Ys  |  (Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2  | - (Y1-Z1.Y2).Xs
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+		FP16_YYY_from_FP8(&b,&Y1);		//b=new FP4(Y1);
+		FP16_YYY_zero(&c);
+#endif
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+		FP16_YYY_zero(&b);
+		FP16_YYY_from_FP8H(&c,&Y1);		//b=new FP4(Y1);
+#endif
+		ECP8_ZZZ_add(A,B);			// A.add(B);
+    }
+
+    FP48_YYY_from_FP16s(v,&a,&b,&c);
+}
+
+/* Optimal R-ate pairing r=e(P,Q) */
+void PAIR_ZZZ_ate(FP48_YYY *r,ECP8_ZZZ *P1,ECP_ZZZ *Q1)
+{
+    BIG_XXX x,n,n3;
+	FP_YYY Qx,Qy;
+    int i,j,nb,bt;
+    ECP8_ZZZ A,NP,P;
+	ECP_ZZZ Q;
+    FP48_YYY lv;
+
+    BIG_XXX_rcopy(x,CURVE_Bnx_ZZZ);
+
+    BIG_XXX_copy(n,x);
+
+    //BIG_XXX_norm(n);
+	BIG_XXX_pmul(n3,n,3);
+	BIG_XXX_norm(n3);
+
+	ECP8_ZZZ_copy(&P,P1);
+	ECP_ZZZ_copy(&Q,Q1);
+
+	ECP8_ZZZ_affine(&P);
+	ECP_ZZZ_affine(&Q);
+
+
+    FP_YYY_copy(&Qx,&(Q.x));
+    FP_YYY_copy(&Qy,&(Q.y));
+
+    ECP8_ZZZ_copy(&A,&P);
+	ECP8_ZZZ_copy(&NP,&P); ECP8_ZZZ_neg(&NP);
+
+    FP48_YYY_one(r);
+    nb=BIG_XXX_nbits(n3);  // n3
+
+	j=0;
+    /* Main Miller Loop */
+    for (i=nb-2; i>=1; i--)
+    {
+		j++;
+		FP48_YYY_sqr(r,r);
+        PAIR_ZZZ_line(&lv,&A,&A,&Qx,&Qy);
+        FP48_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+//printf("r= "); FP48_YYY_output(r); printf("\n");
+//if (j>3) exit(0);
+		bt= BIG_XXX_bit(n3,i)-BIG_XXX_bit(n,i);  // BIG_XXX_bit(n,i); 
+        if (bt==1)
+        {
+//printf("bt=1\n");
+            PAIR_ZZZ_line(&lv,&A,&P,&Qx,&Qy);
+            FP48_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+        }
+		if (bt==-1)
+		{
+//printf("bt=-1\n");
+			//ECP8_ZZZ_neg(P);
+            PAIR_ZZZ_line(&lv,&A,&NP,&Qx,&Qy);
+            FP48_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+			//ECP8_ZZZ_neg(P);
+		}
+
+    }
+
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+    FP48_YYY_conj(r,r);
+#endif
+
+}
+
+/* Optimal R-ate double pairing e(P,Q).e(R,S) */
+void PAIR_ZZZ_double_ate(FP48_YYY *r,ECP8_ZZZ *P1,ECP_ZZZ *Q1,ECP8_ZZZ *R1,ECP_ZZZ *S1)
+{
+    BIG_XXX x,n,n3;
+	FP_YYY Qx,Qy,Sx,Sy;
+    int i,nb,bt;
+    ECP8_ZZZ A,B,NP,NR,P,R;
+	ECP_ZZZ Q,S;
+    FP48_YYY lv;
+
+    BIG_XXX_rcopy(x,CURVE_Bnx_ZZZ);
+    BIG_XXX_copy(n,x);
+
+    //BIG_XXX_norm(n);
+	BIG_XXX_pmul(n3,n,3);
+	BIG_XXX_norm(n3);
+
+	ECP8_ZZZ_copy(&P,P1);
+	ECP_ZZZ_copy(&Q,Q1);
+
+	ECP8_ZZZ_affine(&P);
+	ECP_ZZZ_affine(&Q);
+
+	ECP8_ZZZ_copy(&R,R1);
+	ECP_ZZZ_copy(&S,S1);
+
+	ECP8_ZZZ_affine(&R);
+	ECP_ZZZ_affine(&S);
+
+    FP_YYY_copy(&Qx,&(Q.x));
+    FP_YYY_copy(&Qy,&(Q.y));
+
+    FP_YYY_copy(&Sx,&(S.x));
+    FP_YYY_copy(&Sy,&(S.y));
+
+    ECP8_ZZZ_copy(&A,&P);
+    ECP8_ZZZ_copy(&B,&R);
+	ECP8_ZZZ_copy(&NP,&P); ECP8_ZZZ_neg(&NP);
+	ECP8_ZZZ_copy(&NR,&R); ECP8_ZZZ_neg(&NR);
+
+
+    FP48_YYY_one(r);
+    nb=BIG_XXX_nbits(n3);
+
+    /* Main Miller Loop */
+    for (i=nb-2; i>=1; i--)
+    {
+        FP48_YYY_sqr(r,r);
+        PAIR_ZZZ_line(&lv,&A,&A,&Qx,&Qy);
+        FP48_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+
+        PAIR_ZZZ_line(&lv,&B,&B,&Sx,&Sy);
+        FP48_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+
+		bt=BIG_XXX_bit(n3,i)-BIG_XXX_bit(n,i); // bt=BIG_XXX_bit(n,i);
+        if (bt==1)
+        {
+            PAIR_ZZZ_line(&lv,&A,&P,&Qx,&Qy);
+            FP48_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+
+            PAIR_ZZZ_line(&lv,&B,&R,&Sx,&Sy);
+            FP48_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+        }
+		if (bt==-1)
+		{
+			//ECP8_ZZZ_neg(P); 
+            PAIR_ZZZ_line(&lv,&A,&NP,&Qx,&Qy);
+            FP48_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+			//ECP8_ZZZ_neg(P); 
+			//ECP8_ZZZ_neg(R);
+            PAIR_ZZZ_line(&lv,&B,&NR,&Sx,&Sy);
+            FP48_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+			//ECP8_ZZZ_neg(R);
+		}
+	}
+
+
+
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+    FP48_YYY_conj(r,r);
+#endif
+
+}
+
+/* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */
+
+void PAIR_ZZZ_fexp(FP48_YYY *r)
+{
+    FP2_YYY X;
+    BIG_XXX x;
+	FP_YYY a,b;
+    FP48_YYY t1,t2,t3,t7;  
+
+    BIG_XXX_rcopy(x,CURVE_Bnx_ZZZ);
+    FP_YYY_rcopy(&a,Fra_YYY);
+    FP_YYY_rcopy(&b,Frb_YYY);
+    FP2_YYY_from_FPs(&X,&a,&b);
+
+    /* Easy part of final exp - r^(p^24-1)(p^8+1)*/
+
+    FP48_YYY_inv(&t7,r);
+    FP48_YYY_conj(r,r);
+
+    FP48_YYY_mul(r,&t7);
+    FP48_YYY_copy(&t7,r);
+
+    FP48_YYY_frob(r,&X,8);
+
+    FP48_YYY_mul(r,&t7);
+
+// Ghamman & Fouotsa Method for hard part of fexp - r^e1 . r^p^e2 . r^p^2^e3 ..
+
+// e0 = u^17 - 2*u^16 + u^15 - u^9 + 2*u^8 - u^7 + 3	// .p^0
+// e1 = u^16 - 2*u^15 + u^14 - u^8 + 2*u^7 - u^6		// .p^1
+// e2 = u^15 - 2*u^14 + u^13 - u^7 + 2*u^6 - u^5
+// e3 = u^14 - 2*u^13 + u^12 - u^6 + 2*u^5 - u^4
+// e4 = u^13 - 2*u^12 + u^11 - u^5 + 2*u^4 - u^3
+// e5 = u^12 - 2*u^11 + u^10 - u^4 + 2*u^3 - u^2
+// e6 = u^11 - 2*u^10 + u^9 - u^3 + 2*u^2 - u
+// e7 =  u^10 - 2*u^9 + u^8 - u^2 + 2*u - 1
+// e8 =  u^9 - 2*u^8 + u^7
+// e9 =  u^8 - 2*u^7 + u^6
+// e10 = u^7 - 2*u^6 + u^5
+// e11 = u^6 - 2*u^5 + u^4
+// e12 = u^5 - 2*u^4 + u^3
+// e13 = u^4 - 2*u^3 + u^2
+// e14 = u^3 - 2*u^2 + u
+// e15 = u^2 - 2*u + 1
+
+// e15 = u^2-2*u+1
+// e14 = u.e15
+// e13 = u.e14
+// e12 = u.e13
+// e11 = u.e12
+// e10 = u.e11
+// e9 =  u.e10
+// e8 =  u.e9
+// e7 =  u.e8 - e15
+// e6 =  u.e7
+// e5 =  u.e6
+// e4 =  u.e5
+// e3 =  u.e4
+// e2 =  u.e3
+// e1 =  u.e2
+// e0 =  u.e1 + 3
+
+// f^e0.f^e1^p.f^e2^p^2.. .. f^e14^p^14.f^e15^p^15
+
+	FP48_YYY_usqr(&t7,r);			// t7=f^2
+	FP48_YYY_pow(&t1,&t7,x);		// t1=f^2u
+
+	BIG_XXX_fshr(x,1);
+	FP48_YYY_pow(&t2,&t1,x);		// t2=f^2u^(u/2) =  f^u^2
+	BIG_XXX_fshl(x,1);				// x must be even
+
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP48_YYY_conj(&t1,&t1);
+#endif
+
+	FP48_YYY_conj(&t3,&t1);		// t3=f^-2u
+	FP48_YYY_mul(&t2,&t3);		// t2=f^u^2.f^-2u
+	FP48_YYY_mul(&t2,r);		// t2=f^u^2.f^-2u.f = f^(u^2-2u+1) = f^e15
+
+	FP48_YYY_mul(r,&t7);		// f^3
+
+	FP48_YYY_pow(&t1,&t2,x);	// f^e15^u = f^(u.e15) = f^(u^3-2u^2+u) = f^(e14)
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP48_YYY_conj(&t1,&t1);
+#endif
+	FP48_YYY_copy(&t3,&t1);
+	FP48_YYY_frob(&t3,&X,14);	// f^(u^3-2u^2+u)^p^14
+	FP48_YYY_mul(r,&t3);		// f^3.f^(u^3-2u^2+u)^p^14
+
+	FP48_YYY_pow(&t1,&t1,x);	// f^(u.e14) = f^(u^4-2u^3+u^2) =  f^(e13)
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP48_YYY_conj(&t1,&t1);
+#endif
+	FP48_YYY_copy(&t3,&t1);
+	FP48_YYY_frob(&t3,&X,13);	// f^(e13)^p^13
+	FP48_YYY_mul(r,&t3);		// f^3.f^(u^3-2u^2+u)^p^14.f^(u^4-2u^3+u^2)^p^13
+
+	FP48_YYY_pow(&t1,&t1,x);	// f^(u.e13)
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP48_YYY_conj(&t1,&t1);
+#endif
+	FP48_YYY_copy(&t3,&t1);
+	FP48_YYY_frob(&t3,&X,12);	// f^(e12)^p^12
+	FP48_YYY_mul(r,&t3);		
+
+	FP48_YYY_pow(&t1,&t1,x);	// f^(u.e12)
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP48_YYY_conj(&t1,&t1);
+#endif
+	FP48_YYY_copy(&t3,&t1);
+	FP48_YYY_frob(&t3,&X,11);	// f^(e11)^p^11
+	FP48_YYY_mul(r,&t3);		
+
+	FP48_YYY_pow(&t1,&t1,x);	// f^(u.e11)
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP48_YYY_conj(&t1,&t1);
+#endif
+	FP48_YYY_copy(&t3,&t1);
+	FP48_YYY_frob(&t3,&X,10);	// f^(e10)^p^10
+	FP48_YYY_mul(r,&t3);		
+
+	FP48_YYY_pow(&t1,&t1,x);	// f^(u.e10)
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP48_YYY_conj(&t1,&t1);
+#endif
+	FP48_YYY_copy(&t3,&t1);
+	FP48_YYY_frob(&t3,&X,9);	// f^(e9)^p^9
+	FP48_YYY_mul(r,&t3);		
+
+	FP48_YYY_pow(&t1,&t1,x);	// f^(u.e9)
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP48_YYY_conj(&t1,&t1);
+#endif
+	FP48_YYY_copy(&t3,&t1);
+	FP48_YYY_frob(&t3,&X,8);	// f^(e8)^p^8
+	FP48_YYY_mul(r,&t3);		
+
+	FP48_YYY_pow(&t1,&t1,x);	// f^(u.e8)
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP48_YYY_conj(&t1,&t1);
+#endif
+	FP48_YYY_conj(&t3,&t2);
+	FP48_YYY_mul(&t1,&t3);  // f^(u.e8).f^-e15
+	FP48_YYY_copy(&t3,&t1);
+	FP48_YYY_frob(&t3,&X,7);	// f^(e7)^p^7
+	FP48_YYY_mul(r,&t3);		
+
+	FP48_YYY_pow(&t1,&t1,x);	// f^(u.e7)
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP48_YYY_conj(&t1,&t1);
+#endif
+	FP48_YYY_copy(&t3,&t1);
+	FP48_YYY_frob(&t3,&X,6);	// f^(e6)^p^6
+	FP48_YYY_mul(r,&t3);		
+
+	FP48_YYY_pow(&t1,&t1,x);	// f^(u.e6)
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP48_YYY_conj(&t1,&t1);
+#endif
+	FP48_YYY_copy(&t3,&t1);
+	FP48_YYY_frob(&t3,&X,5);	// f^(e5)^p^5
+	FP48_YYY_mul(r,&t3);		
+
+	FP48_YYY_pow(&t1,&t1,x);	// f^(u.e5)
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP48_YYY_conj(&t1,&t1);
+#endif
+	FP48_YYY_copy(&t3,&t1);
+	FP48_YYY_frob(&t3,&X,4);	// f^(e4)^p^4
+	FP48_YYY_mul(r,&t3);		
+
+	FP48_YYY_pow(&t1,&t1,x);	// f^(u.e4)
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP48_YYY_conj(&t1,&t1);
+#endif
+	FP48_YYY_copy(&t3,&t1);
+	FP48_YYY_frob(&t3,&X,3);	// f^(e3)^p^3
+	FP48_YYY_mul(r,&t3);		
+
+	FP48_YYY_pow(&t1,&t1,x);	// f^(u.e3)
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP48_YYY_conj(&t1,&t1);
+#endif
+	FP48_YYY_copy(&t3,&t1);
+	FP48_YYY_frob(&t3,&X,2);	// f^(e2)^p^2
+	FP48_YYY_mul(r,&t3);		
+
+	FP48_YYY_pow(&t1,&t1,x);	// f^(u.e2)
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP48_YYY_conj(&t1,&t1);
+#endif
+	FP48_YYY_copy(&t3,&t1);
+	FP48_YYY_frob(&t3,&X,1);	// f^(e1)^p^1
+	FP48_YYY_mul(r,&t3);		
+
+	FP48_YYY_pow(&t1,&t1,x);	// f^(u.e1)
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP48_YYY_conj(&t1,&t1);
+#endif
+	FP48_YYY_mul(r,&t1);		// r.f^e0		
+
+	FP48_YYY_frob(&t2,&X,15);	// f^(e15.p^15)
+	FP48_YYY_mul(r,&t2);
+
+
+	FP48_YYY_reduce(r);
+
+}
+
+#ifdef USE_GLV_ZZZ
+/* GLV method */
+static void glv(BIG_XXX u[2],BIG_XXX e)
+{
+
+// -(x^8).P = (Beta.x,y)
+
+    BIG_XXX x,x2,q;
+    BIG_XXX_rcopy(x,CURVE_Bnx_ZZZ);
+    
+	BIG_XXX_smul(x2,x,x);
+	BIG_XXX_smul(x,x2,x2);
+	BIG_XXX_smul(x2,x,x);
+
+    BIG_XXX_copy(u[0],e);
+    BIG_XXX_mod(u[0],x2);
+    BIG_XXX_copy(u[1],e);
+    BIG_XXX_sdiv(u[1],x2);
+
+    BIG_XXX_rcopy(q,CURVE_Order_ZZZ);
+    BIG_XXX_sub(u[1],q,u[1]);
+
+
+    return;
+}
+#endif // USE_GLV
+
+/* Galbraith & Scott Method */
+static void gs(BIG_XXX u[16],BIG_XXX e)
+{
+    int i;
+
+    BIG_XXX x,w,q;
+	BIG_XXX_rcopy(q,CURVE_Order_ZZZ);
+    BIG_XXX_rcopy(x,CURVE_Bnx_ZZZ);
+    BIG_XXX_copy(w,e);
+
+    for (i=0; i<15; i++)
+    {
+        BIG_XXX_copy(u[i],w);
+        BIG_XXX_mod(u[i],x);
+        BIG_XXX_sdiv(w,x);
+    }
+	BIG_XXX_copy(u[15],w);
+
+/*  */
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	BIG_XXX_modneg(u[1],u[1],q);
+	BIG_XXX_modneg(u[3],u[3],q);
+	BIG_XXX_modneg(u[5],u[5],q);
+	BIG_XXX_modneg(u[7],u[7],q);
+	BIG_XXX_modneg(u[9],u[9],q);
+	BIG_XXX_modneg(u[11],u[11],q);
+	BIG_XXX_modneg(u[13],u[13],q);
+	BIG_XXX_modneg(u[15],u[15],q);
+#endif
+
+
+    return;
+}
+
+/* Multiply P by e in group G1 */
+void PAIR_ZZZ_G1mul(ECP_ZZZ *P,BIG_XXX e)
+{
+#ifdef USE_GLV_ZZZ   /* Note this method is patented */
+    int np,nn;
+    ECP_ZZZ Q;
+	FP_YYY cru;
+    BIG_XXX t,q;
+    BIG_XXX u[2];
+
+    BIG_XXX_rcopy(q,CURVE_Order_ZZZ);
+    glv(u,e);
+
+    //ECP_ZZZ_affine(P);
+    ECP_ZZZ_copy(&Q,P); ECP_ZZZ_affine(&Q);
+    FP_YYY_rcopy(&cru,CURVE_Cru_ZZZ);
+    FP_YYY_mul(&(Q.x),&(Q.x),&cru);
+
+    /* note that -a.B = a.(-B). Use a or -a depending on which is smaller */
+
+    np=BIG_XXX_nbits(u[0]);
+    BIG_XXX_modneg(t,u[0],q);
+    nn=BIG_XXX_nbits(t);
+    if (nn<np)
+    {
+        BIG_XXX_copy(u[0],t);
+        ECP_ZZZ_neg(P);
+    }
+
+    np=BIG_XXX_nbits(u[1]);
+    BIG_XXX_modneg(t,u[1],q);
+    nn=BIG_XXX_nbits(t);
+    if (nn<np)
+    {
+        BIG_XXX_copy(u[1],t);
+        ECP_ZZZ_neg(&Q);
+    }
+    BIG_XXX_norm(u[0]);
+    BIG_XXX_norm(u[1]);    
+    ECP_ZZZ_mul2(P,&Q,u[0],u[1]);
+
+#else
+    ECP_ZZZ_mul(P,e);
+#endif
+}
+
+/* Multiply P by e in group G2 */
+void PAIR_ZZZ_G2mul(ECP8_ZZZ *P,BIG_XXX e)
+{
+#ifdef USE_GS_G2_ZZZ   /* Well I didn't patent it :) */
+    int i,np,nn;
+    ECP8_ZZZ Q[16];
+    FP2_YYY X[3];
+    BIG_XXX x,y,u[16];
+
+	ECP8_ZZZ_frob_constants(X);
+
+    BIG_XXX_rcopy(y,CURVE_Order_ZZZ);
+    gs(u,e);
+
+    //ECP8_ZZZ_affine(P);
+
+    ECP8_ZZZ_copy(&Q[0],P);
+    for (i=1; i<16; i++)
+    {
+        ECP8_ZZZ_copy(&Q[i],&Q[i-1]);
+        ECP8_ZZZ_frob(&Q[i],X,1);
+    }
+
+    for (i=0; i<16; i++)
+    {
+        np=BIG_XXX_nbits(u[i]);
+        BIG_XXX_modneg(x,u[i],y);
+        nn=BIG_XXX_nbits(x);
+        if (nn<np)
+        {
+            BIG_XXX_copy(u[i],x);
+            ECP8_ZZZ_neg(&Q[i]);
+        }
+        BIG_XXX_norm(u[i]);  
+		//ECP8_ZZZ_affine(&Q[i]);
+    }
+
+    ECP8_ZZZ_mul16(P,Q,u);
+
+#else
+    ECP8_ZZZ_mul(P,e);
+#endif
+}
+
+/* f=f^e */
+void PAIR_ZZZ_GTpow(FP48_YYY *f,BIG_XXX e)
+{
+#ifdef USE_GS_GT_ZZZ   /* Note that this option requires a lot of RAM! Maybe better to use compressed XTR method, see FP16.cpp */
+    int i,np,nn;
+    FP48_YYY g[16];
+    FP2_YYY X;
+    BIG_XXX t,q;
+	FP_YYY fx,fy;
+    BIG_XXX u[16];
+
+    FP_YYY_rcopy(&fx,Fra_YYY);
+    FP_YYY_rcopy(&fy,Frb_YYY);
+    FP2_YYY_from_FPs(&X,&fx,&fy);
+
+    BIG_XXX_rcopy(q,CURVE_Order_ZZZ);
+    gs(u,e);
+
+    FP48_YYY_copy(&g[0],f);
+    for (i=1; i<16; i++)
+    {
+        FP48_YYY_copy(&g[i],&g[i-1]);
+        FP48_YYY_frob(&g[i],&X,1);
+    }
+
+    for (i=0; i<16; i++)
+    {
+        np=BIG_XXX_nbits(u[i]);
+        BIG_XXX_modneg(t,u[i],q);
+        nn=BIG_XXX_nbits(t);
+        if (nn<np)
+        {
+            BIG_XXX_copy(u[i],t);
+            FP48_YYY_conj(&g[i],&g[i]);
+        }
+        BIG_XXX_norm(u[i]);
+    }
+    FP48_YYY_pow16(f,g,u);
+
+#else
+    FP48_YYY_pow(f,f,e);
+#endif
+}
+
+/* test group membership test - no longer needed */
+/* with GT-Strong curve, now only check that m!=1, conj(m)*m==1, and m.m^{p^4}=m^{p^2} */
+
+/*
+int PAIR_ZZZ_GTmember(FP48_YYY *m)
+{
+	BIG_XXX a,b;
+	FP2_YYY X;
+	FP48_YYY r,w;
+	if (FP48_YYY_isunity(m)) return 0;
+	FP48_YYY_conj(&r,m);
+	FP48_YYY_mul(&r,m);
+	if (!FP48_YYY_isunity(&r)) return 0;
+
+	BIG_XXX_rcopy(a,CURVE_Fra);
+	BIG_XXX_rcopy(b,CURVE_Frb);
+	FP2_YYY_from_BIG_XXXs(&X,a,b);
+
+
+	FP48_YYY_copy(&r,m); FP48_YYY_frob(&r,&X); FP48_YYY_frob(&r,&X);
+	FP48_YYY_copy(&w,&r); FP48_YYY_frob(&w,&X); FP48_YYY_frob(&w,&X);
+	FP48_YYY_mul(&w,m);
+
+
+#ifndef GT_STRONG
+	if (!FP48_YYY_equals(&w,&r)) return 0;
+
+	BIG_XXX_rcopy(a,CURVE_Bnx);
+
+	FP48_YYY_copy(&r,m); FP48_YYY_pow(&w,&r,a); FP48_YYY_pow(&w,&w,a);
+	FP48_YYY_sqr(&r,&w); FP48_YYY_mul(&r,&w); FP48_YYY_sqr(&r,&r);
+
+	FP48_YYY_copy(&w,m); FP48_YYY_frob(&w,&X);
+ #endif
+
+	return FP48_YYY_equals(&w,&r);
+}
+
+*/
+
+
+#ifdef HAS_MAIN
+
+using namespace std;
+using namespace ZZZ;
+
+
+// g++ -O2 pair256_BLS48.cpp ecp8_BLS48.cpp fp48_BLS48.cpp fp16_BLS48.cpp fp8_BLS48.cpp fp4_BLS48.cpp fp2_BLS48.cpp ecp_BLS48.cpp fp_BLS48.cpp big_B560_29.cpp rom_curve_BLS48.cpp rom_field_BLS48.cpp rand.cpp hash.cpp oct.cpp -o pair256_BLS48.exe
+
+int main()
+{
+    int i;
+    char byt[32];
+    csprng rng;
+    BIG xa,xb,ya,yb,w,a,b,t1,q,u[2],v[4],m,r,xx,x2,x4,p;
+    ECP8 P,G;
+    ECP Q,R;
+    FP48 g,gp;
+    FP16 t,c,cp,cpm1,cpm2;
+	FP8 X,Y;
+    FP2 x,y,f,Aa,Bb;
+	FP cru;
+
+	for (i=0;i<32;i++)
+		byt[i]=i+9;
+	RAND_seed(&rng,32,byt);
+
+	BIG_rcopy(r,CURVE_Order);
+	BIG_rcopy(p,Modulus);
+
+
+    BIG_rcopy(xa,CURVE_Gx_ZZZ);
+    BIG_rcopy(ya,CURVE_Gy_ZZZ);
+
+    ECP_ZZZ_set(&Q,xa,ya);
+    if (Q.inf) printf("Failed to set - point not on curve\n");
+    else printf("G1 set success\n");
+
+    printf("Q= ");
+    ECP_ZZZ_output(&Q);
+    printf("\n");
+
+	ECP8_generator(&P);
+
+    if (P.inf) printf("Failed to set - point not on curve\n");
+    else printf("G2 set success\n");
+
+    BIG_rcopy(a,Fra);
+    BIG_rcopy(b,Frb);
+    FP2_from_BIGs(&f,a,b);
+
+
+//exit(0);
+
+    PAIR_ZZZ_ate(&g,&P,&Q);
+
+	printf("gb= ");
+    FP48_output(&g);
+    printf("\n");
+    PAIR_ZZZ_fexp(&g);
+
+    printf("g= ");
+    FP48_output(&g);
+    printf("\n");
+
+	//FP48_pow(&g,&g,r);
+
+   // printf("g^r= ");
+    //FP48_output(&g);
+    //printf("\n");
+
+	ECP_ZZZ_copy(&R,&Q);
+	ECP8_copy(&G,&P);
+
+	ECP8_dbl(&G);
+	ECP_dbl(&R);
+	ECP_affine(&R);
+
+    PAIR_ZZZ_ate(&g,&G,&Q);
+    PAIR_ZZZ_fexp(&g);
+
+    printf("g1= ");
+    FP48_output(&g);
+    printf("\n");
+
+    PAIR_ZZZ_ate(&g,&P,&R);
+    PAIR_ZZZ_fexp(&g);
+
+    printf("g2= ");
+    FP48_output(&g);
+    printf("\n");
+
+
+	PAIR_ZZZ_G1mul(&Q,r);
+	printf("rQ= ");ECP_output(&Q); printf("\n");
+
+	PAIR_ZZZ_G2mul(&P,r);
+	printf("rP= ");ECP8_output(&P); printf("\n");
+
+	//FP48_pow(&g,&g,r);
+	PAIR_ZZZ_GTpow(&g,r);
+	printf("g^r= ");FP48_output(&g); printf("\n");
+
+
+	BIG_randomnum(w,r,&rng);
+
+	FP48_copy(&gp,&g);
+
+	PAIR_ZZZ_GTpow(&g,w);
+
+	FP48_trace(&t,&g);
+
+	printf("g^r=  ");FP16_output(&t); printf("\n");
+
+	FP48_compow(&t,&gp,w,r);
+
+	printf("t(g)= "); FP16_output(&t); printf("\n");
+
+//    PAIR_ZZZ_ate(&g,&P,&R);
+//    PAIR_ZZZ_fexp(&g);
+
+//    printf("g= ");
+//    FP48_output(&g);
+//    printf("\n");
+
+//	PAIR_ZZZ_GTpow(&g,xa);
+}
+
+#endif
diff --git a/version3/c/pair256.h b/version3/c/pair256.h
new file mode 100644
index 0000000..d270f76
--- /dev/null
+++ b/version3/c/pair256.h
@@ -0,0 +1,77 @@
+#ifndef PAIR256_ZZZ_H
+#define PAIR256_ZZZ_H
+
+#include "fp48_YYY.h"
+#include "ecp8_ZZZ.h"
+#include "ecp_ZZZ.h"
+
+
+/* Pairing constants */
+
+extern const BIG_XXX CURVE_Bnx_ZZZ; /**< BN curve x parameter */
+extern const BIG_XXX CURVE_Cru_ZZZ; /**< BN curve Cube Root of Unity */
+
+extern const BIG_XXX CURVE_W_ZZZ[2];	 /**< BN curve constant for GLV decomposition */
+extern const BIG_XXX CURVE_SB_ZZZ[2][2]; /**< BN curve constant for GLV decomposition */
+extern const BIG_XXX CURVE_WB_ZZZ[4];	 /**< BN curve constant for GS decomposition */
+extern const BIG_XXX CURVE_BB_ZZZ[4][4]; /**< BN curve constant for GS decomposition */
+
+/* Pairing function prototypes */
+/**	@brief Calculate Miller loop for Optimal ATE pairing e(P,Q)
+ *
+	@param r FP48 result of the pairing calculation e(P,Q)
+	@param P ECP8 instance, an element of G2
+	@param Q ECP instance, an element of G1
+
+ */
+extern void PAIR_ZZZ_ate(FP48_YYY *r,ECP8_ZZZ *P,ECP_ZZZ *Q);
+/**	@brief Calculate Miller loop for Optimal ATE double-pairing e(P,Q).e(R,S)
+ *
+	Faster than calculating two separate pairings
+	@param r FP48 result of the pairing calculation e(P,Q).e(R,S), an element of GT
+	@param P ECP8 instance, an element of G2
+	@param Q ECP instance, an element of G1
+	@param R ECP8 instance, an element of G2
+	@param S ECP instance, an element of G1
+ */
+extern void PAIR_ZZZ_double_ate(FP48_YYY *r,ECP8_ZZZ *P,ECP_ZZZ *Q,ECP8_ZZZ *R,ECP_ZZZ *S);
+/**	@brief Final exponentiation of pairing, converts output of Miller loop to element in GT
+ *
+	Here p is the internal modulus, and r is the group order
+	@param x FP48, on exit = x^((p^12-1)/r)
+ */
+extern void PAIR_ZZZ_fexp(FP48_YYY *x);
+/**	@brief Fast point multiplication of a member of the group G1 by a BIG number
+ *
+	May exploit endomorphism for speed.
+	@param Q ECP member of G1.
+	@param b BIG multiplier
+
+ */
+extern void PAIR_ZZZ_G1mul(ECP_ZZZ *Q,BIG_XXX b);
+/**	@brief Fast point multiplication of a member of the group G2 by a BIG number
+ *
+	May exploit endomorphism for speed.
+	@param P ECP8 member of G1.
+	@param b BIG multiplier
+
+ */
+extern void PAIR_ZZZ_G2mul(ECP8_ZZZ *P,BIG_XXX b);
+/**	@brief Fast raising of a member of GT to a BIG power
+ *
+	May exploit endomorphism for speed.
+	@param x FP48 member of GT.
+	@param b BIG exponent
+
+ */
+extern void PAIR_ZZZ_GTpow(FP48_YYY *x,BIG_XXX b);
+/**	@brief Tests FP48 for membership of GT
+ *
+	@param x FP48 instance
+	@return 1 if x is in GT, else return 0
+
+ */
+extern int PAIR_ZZZ_GTmember(FP48_YYY *x);
+
+
+#endif
diff --git a/version3/c/pbc_support.c b/version3/c/pbc_support.c
new file mode 100644
index 0000000..3639fb7
--- /dev/null
+++ b/version3/c/pbc_support.c
@@ -0,0 +1,180 @@
+/*
+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.
+*/
+
+/* Symmetric crypto support functions Functions  */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "pbc_support.h"
+
+/* general purpose hash function w=hash(p|n|x|y) */
+void mhashit(int sha,int n,octet *x,octet *w)
+{
+    int i,c[4],hlen;
+    hash256 sha256;
+    hash512 sha512;
+    char hh[64];
+
+    switch (sha)
+    {
+    case SHA256:
+        HASH256_init(&sha256);
+        break;
+    case SHA384:
+        HASH384_init(&sha512);
+        break;
+    case SHA512:
+        HASH512_init(&sha512);
+        break;
+    }
+
+    hlen=sha;
+
+    if (n>0)
+    {
+        c[0]=(n>>24)&0xff;
+        c[1]=(n>>16)&0xff;
+        c[2]=(n>>8)&0xff;
+        c[3]=(n)&0xff;
+        for (i=0; i<4; i++)
+        {
+            switch(sha)
+            {
+            case SHA256:
+                HASH256_process(&sha256,c[i]);
+                break;
+            case SHA384:
+                HASH384_process(&sha512,c[i]);
+                break;
+            case SHA512:
+                HASH512_process(&sha512,c[i]);
+                break;
+            }
+        }
+    }
+
+    if (x!=NULL) for (i=0; i<x->len; i++)
+        {
+            switch(sha)
+            {
+            case SHA256:
+                HASH256_process(&sha256,x->val[i]);
+
+                break;
+            case SHA384:
+                HASH384_process(&sha512,x->val[i]);
+                break;
+            case SHA512:
+                HASH512_process(&sha512,x->val[i]);
+                break;
+            }
+        }
+
+    for (i=0; i<hlen; i++) hh[i]=0;
+    switch (sha)
+    {
+    case SHA256:
+        HASH256_hash(&sha256,hh);
+        break;
+    case SHA384:
+        HASH384_hash(&sha512,hh);
+        break;
+    case SHA512:
+        HASH512_hash(&sha512,hh);
+        break;
+    }
+
+    OCT_empty(w);
+
+    if (hlen>=w->max)
+        OCT_jbytes(w,hh,w->max);
+    else
+    {
+        OCT_jbyte(w,0,w->max-hlen);
+        OCT_jbytes(w,hh,hlen);
+
+//        OCT_jbytes(w,hh,hlen);
+//        OCT_jbyte(w,0,w->max-hlen);
+    }
+}
+
+unsign32 today(void)
+{
+    /* return time in slots since epoch */
+    unsign32 ti=(unsign32)time(NULL);
+    return (uint32_t)(ti/(60*TIME_SLOT_MINUTES));
+}
+
+/* Hash the M-Pin transcript - new */
+
+void HASH_ALL(int sha,octet *HID,octet *xID,octet *xCID,octet *SEC,octet *Y,octet *R,octet *W,octet *H)
+{
+    char t[1284];   // assumes max modulus of 1024-bits
+    octet T= {0,sizeof(t),t};
+
+    OCT_joctet(&T,HID);
+    if (xCID!=NULL) OCT_joctet(&T,xCID);
+    else OCT_joctet(&T,xID);
+    OCT_joctet(&T,SEC);
+    OCT_joctet(&T,Y);
+    OCT_joctet(&T,R);
+    OCT_joctet(&T,W);
+
+    mhashit(sha,0,&T,H);
+}
+
+void HASH_ID(int sha,octet *ID,octet *HID)
+{
+    mhashit(sha,0,ID,HID);
+}
+
+unsign32 GET_TIME(void)
+{
+    return (unsign32)time(NULL);
+}
+
+/* AES-GCM Encryption of octets, K is key, H is header,
+   P is plaintext, C is ciphertext, T is authentication tag */
+void AES_GCM_ENCRYPT(octet *K,octet *IV,octet *H,octet *P,octet *C,octet *T)
+{
+    gcm g;
+    GCM_init(&g,K->len,K->val,IV->len,IV->val);
+    GCM_add_header(&g,H->val,H->len);
+    GCM_add_plain(&g,C->val,P->val,P->len);
+    C->len=P->len;
+    GCM_finish(&g,T->val);
+    T->len=16;
+}
+
+/* AES-GCM Decryption of octets, K is key, H is header,
+   P is plaintext, C is ciphertext, T is authentication tag */
+void AES_GCM_DECRYPT(octet *K,octet *IV,octet *H,octet *C,octet *P,octet *T)
+{
+    gcm g;
+    GCM_init(&g,K->len,K->val,IV->len,IV->val);
+    GCM_add_header(&g,H->val,H->len);
+    GCM_add_cipher(&g,P->val,C->val,C->len);
+    P->len=C->len;
+    GCM_finish(&g,T->val);
+    T->len=16;
+}
+
diff --git a/version3/c/pbc_support.h b/version3/c/pbc_support.h
new file mode 100644
index 0000000..4fe82d9
--- /dev/null
+++ b/version3/c/pbc_support.h
@@ -0,0 +1,96 @@
+/*
+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.
+*/
+
+/**
+ * @file pbc_support.h
+ * @author Mike Scott
+ * @brief Auxiliary functions for Pairing-based protocols
+ *
+ *
+ */
+
+#ifndef PBC_SUPPORT_H
+#define PBC_SUPPORT_H
+
+#include "amcl.h"
+
+#define TIME_SLOT_MINUTES 1440  /**< Time Slot = 1 day */
+
+/** @brief general purpose hash function w=hash(n|x)
+ *
+	@param sha is the hash type
+	@param n integer involved in the hash
+	@param x octect involved in the h ash
+	@param w output
+ */
+extern void mhashit(int sha,int n,octet *x,octet *w);
+
+/**	@brief Supply today's date as days from the epoch
+ *
+	@return today's date, as number of days elapsed since the epoch
+ */
+unsign32 today(void);
+/** @brief Hash the session transcript
+ 	@param h is the hash type
+	@param I is the hashed input client ID = H(ID)
+	@param U is the client output = x.H(ID)
+	@param CU is the client output = x.(H(ID)+H(T|H(ID)))
+	@param Y is the server challenge
+	@param V is the client part response
+	@param R is the client part response
+	@param W is the server part response
+	@param H the output is the hash of all of the above that apply
+*/
+void HASH_ALL(int h,octet *I,octet *U,octet *CU,octet *Y,octet *V,octet *R,octet *W,octet *H);
+/**	@brief Hash an M-Pin Identity to an octet string
+ *
+ 	@param h is the hash type
+	@param ID an octet containing the identity
+	@param HID an octet containing the hashed identity
+ */
+void HASH_ID(int h,octet *ID,octet *HID);
+/**	@brief Get epoch time as unsigned integer
+ *
+	@return current epoch time in seconds
+ */
+unsign32 GET_TIME(void);
+/**	@brief AES-GCM Encryption
+ *
+	@param K  AES key
+	@param IV Initialization vector
+	@param H Header
+	@param P Plaintext
+	@param C Ciphertext
+	@param T Checksum
+ */
+void AES_GCM_ENCRYPT(octet *K,octet *IV,octet *H,octet *P,octet *C,octet *T);
+
+/**	@brief AES-GCM Decryption
+ *
+	@param K  AES key
+	@param IV Initialization vector
+	@param H Header
+	@param P Plaintext
+	@param C Ciphertext
+	@param T Checksum
+ */
+void AES_GCM_DECRYPT(octet *K,octet *IV,octet *H,octet *C,octet *P,octet *T);
+
+
+#endif
diff --git a/version3/c/rand.c b/version3/c/rand.c
new file mode 100644
index 0000000..4a2cd0a
--- /dev/null
+++ b/version3/c/rand.c
@@ -0,0 +1,172 @@
+/*
+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.
+*/
+
+/*
+ *   Cryptographic strong random number generator
+ *
+ *   Unguessable seed -> SHA -> PRNG internal state -> SHA -> random numbers
+ *   Slow - but secure
+ *
+ *   See ftp://ftp.rsasecurity.com/pub/pdfs/bull-1.pdf for a justification
+ */
+/* SU=m, m is Stack Usage */
+
+#include "amcl.h"
+
+/* SU= 20 */
+static unsign32 sbrand(csprng *rng)
+{
+    /* Marsaglia & Zaman random number generator */
+    int i,k;
+    unsign32 pdiff,t;
+    rng->rndptr++;
+    if (rng->rndptr<NK) return rng->ira[rng->rndptr];
+    rng->rndptr=0;
+    for (i=0,k=NK-NJ; i<NK; i++,k++)
+    {
+        /* calculate next NK values */
+        if (k==NK) k=0;
+        t=rng->ira[k];
+        pdiff=t - rng->ira[i] - rng->borrow;
+
+        if (pdiff<t) rng->borrow=0;
+        if (pdiff>t) rng->borrow=1;
+        rng->ira[i]=pdiff;
+    }
+    return rng->ira[0];
+}
+
+/* SU= 20 */
+static void sirand(csprng* rng,unsign32 seed)
+{
+    /* initialise random number system */
+    /* modified so that a subsequent call "stirs" in another seed value */
+    /* in this way as many seed bits as desired may be used */
+    int i,in;
+    unsign32 t,m=1;
+    rng->borrow=0L;
+    rng->rndptr=0;
+    rng->ira[0]^=seed;
+    for (i=1; i<NK; i++)
+    {
+        /* fill initialisation vector */
+        in=(NV*i)%NK;
+        rng->ira[in]^=m;      /* note XOR */
+        t=m;
+        m=seed-m;
+        seed=t;
+    }
+    for (i=0; i<10000; i++) sbrand(rng ); /* "warm-up" & stir the generator */
+}
+
+/* SU= 312 */
+static void fill_pool(csprng *rng)
+{
+    /* hash down output of RNG to re-fill the pool */
+    int i;
+    hash256 sh;
+    HASH256_init(&sh);
+    for (i=0; i<128; i++) HASH256_process(&sh,sbrand(rng));
+    HASH256_hash(&sh,rng->pool);
+    rng->pool_ptr=0;
+}
+
+static unsign32 pack(const uchar *b)
+{
+    /* pack bytes into a 32-bit Word */
+    return ((unsign32)b[3]<<24)|((unsign32)b[2]<<16)|((unsign32)b[1]<<8)|(unsign32)b[0];
+}
+
+/* SU= 360 */
+/* Initialize RNG with some real entropy from some external source */
+void RAND_seed(csprng *rng,int rawlen,char *raw)
+{
+    /* initialise from at least 128 byte string of raw  *
+     * random (keyboard?) input, and 32-bit time-of-day */
+    int i;
+    char digest[32];
+    uchar b[4];
+    hash256 sh;
+    rng->pool_ptr=0;
+    for (i=0; i<NK; i++) rng->ira[i]=0;
+    if (rawlen>0)
+    {
+        HASH256_init(&sh);
+        for (i=0; i<rawlen; i++)
+            HASH256_process(&sh,raw[i]);
+        HASH256_hash(&sh,digest);
+
+        /* initialise PRNG from distilled randomness */
+
+        for (i=0; i<8; i++)
+        {
+            b[0]=digest[4*i];
+            b[1]=digest[4*i+1];
+            b[2]=digest[4*i+2];
+            b[3]=digest[4*i+3];
+            //	printf("%08x\n",pack(b));
+            sirand(rng,pack(b));
+        }
+    }
+    fill_pool(rng);
+}
+
+/* Terminate and clean up */
+void RAND_clean(csprng *rng)
+{
+    /* kill internal state */
+    int i;
+    rng->pool_ptr=rng->rndptr=0;
+    for (i=0; i<32; i++) rng->pool[i]=0;
+    for (i=0; i<NK; i++) rng->ira[i]=0;
+    rng->borrow=0;
+}
+
+/* get random byte */
+/* SU= 8 */
+int RAND_byte(csprng *rng)
+{
+    int r;
+    r=rng->pool[rng->pool_ptr++];
+    if (rng->pool_ptr>=32) fill_pool(rng);
+    return (r&0xff);
+}
+
+/* test main program */
+/*
+#include <stdio.h>
+#include <string.h>
+
+void main()
+{
+    int i;
+    char raw[256];
+    csprng rng;
+
+	RAND_clean(&rng);
+
+
+	for (i=0;i<256;i++) raw[i]=(char)i;
+    RAND_seed(&rng,256,raw);
+
+	for (i=0;i<1000;i++)
+		printf("%02x ",(unsigned char)RAND_byte(&rng));
+}
+
+*/
diff --git a/version3/c/randapi.c b/version3/c/randapi.c
new file mode 100644
index 0000000..9b32efb
--- /dev/null
+++ b/version3/c/randapi.c
@@ -0,0 +1,15 @@
+#include "randapi.h"
+
+/* Initialise a Cryptographically Strong Random Number Generator from
+   an octet of raw random data */
+
+void CREATE_CSPRNG(csprng *RNG,octet *RAW)
+{
+    RAND_seed(RNG,RAW->len,RAW->val);
+}
+
+void KILL_CSPRNG(csprng *RNG)
+{
+    RAND_clean(RNG);
+}
+
diff --git a/version3/c/randapi.h b/version3/c/randapi.h
new file mode 100644
index 0000000..9a6807e
--- /dev/null
+++ b/version3/c/randapi.h
@@ -0,0 +1,46 @@
+/*
+	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.
+*/
+
+/**
+ * @file randapi.h
+ * @author Mike Scott
+ * @brief PRNG API File
+ *
+ */
+
+#ifndef RANDOM_H
+#define RANDOM_H
+
+#include "amcl.h"
+
+/**	@brief Initialise a random number generator
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param S is an input truly random seed value
+ */
+extern void CREATE_CSPRNG(csprng *R,octet *S);
+/**	@brief Kill a random number generator
+ *
+	Deletes all internal state
+	@param R is a pointer to a cryptographically secure random number generator
+ */
+extern void KILL_CSPRNG(csprng *R);
+
+#endif
+
diff --git a/version3/c/readme.txt b/version3/c/readme.txt
new file mode 100644
index 0000000..3d0dc01
--- /dev/null
+++ b/version3/c/readme.txt
@@ -0,0 +1,75 @@
+Namespaces are sinulated to separate different curves.
+
+To this end the BIG type is renamed to BIG_XXX, where XXX can be changed to 
+describe the size and layout of the BIG variable. Similarily the FP type 
+is renamed FP_YYY, where YYY reflects the modulus used. Also the ECP type 
+is renamed ECP_ZZZ, where ZZZ describes the actual curve. Function names 
+are also decorated in the same way.
+
+So for example to support both ED25519 and the NIST P256 curve on a 64-bit 
+processor, we would need to create BIG_256_56, FP_25519, ECP_ED25519 and 
+BIG_256_56, FP_NIST256, ECP_NIST256. Note that both curves could be built 
+on top of BIG_256_56, as both require support for 256-bit numbers using 
+an internal number base of 2^56.
+
+Separate ROM files provide the constants required for each curve. The
+associated header files (big.h, fp.h and ecp.h) also specify 
+certain constants that must be set for the particular curve.
+
+--------------------------------------
+
+To build the library and see it in action, copy all of the files in this 
+directory to a fresh directory. Then execute the python3 script config32.py 
+for a 32-bit build, or config64.py for a 64-bit build, and select the curves 
+that you wish to support. Note that support for 16-bit builds is currently 
+somewhat limited - see config16.py. A library is built automatically 
+including all of the modules that you will need.
+
+The configuration files assume the gcc compiler. For clang edit the
+config32.py and config64.py files and substitute "clang" for "gcc".
+Note that clang is about 10-15% faster.*
+
+NOTE: In the file config_curve.h a couple of methods with possible IP issues 
+are commented out. For faster pairing code, edit this file.
+
+As a quick example execute
+
+py config32.py
+
+or
+
+python3 config32.py
+
+Then select options 1, 3, 7, 18, 20, 25, 26 and 27, which are fixed for the example 
+program. (For a 16-bit build select 1,3 and 5). Select 0 then to exit.
+
+Then compile
+
+gcc -O2 -std=c99 testall.c amcl.a -o testall.exe
+
+if using MINGW in Windows. Or for Linux
+
+gcc -O2 -std=c99 testall.c amcl.a -o testall
+
+The test program exercises 3 different ordinary elliptic curves, a 
+pairing friendly curve and RSA, all in the one binary.
+
+The correct PIN is 1234
+
+
+Next compile 
+
+
+gcc -O2 -std=c99 benchtest_all.c amcl.a -o benchtest_all.exe
+
+if using MINGW in Windows. Or for Linux
+
+gcc -O2 -std=c99 benchtest_all.c amcl.a -o benchtest_all
+
+This program provides some timings.
+
+*Using clang on Windows
+Download latest clang from http://releases.llvm.org/download.html
+Choose Clang for Windows (64-bit) (.sig) 
+Install a free version of Microsoft Visual C++ https://www.visualstudio.com/downloads/
+Now use "clang" wherever "gcc" was used before.
diff --git a/version3/c/rom_curve_ANSSI.c b/version3/c/rom_curve_ANSSI.c
new file mode 100644
index 0000000..535a697
--- /dev/null
+++ b/version3/c/rom_curve_ANSSI.c
@@ -0,0 +1,33 @@
+#include "arch.h"
+#include "ecp_ANSSI.h"
+
+/* ANSSI Curve */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+const int CURVE_Cof_I_ANNSI= 1;
+const BIG_256_28 CURVE_Cof_ANSSI= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const int CURVE_A_ANSSI= -3;
+const int CURVE_B_I_ANSSI= 0;
+const BIG_256_28 CURVE_B_ANSSI= {0xB7BB73F,0x75ED967,0x1A18030,0xC9AE4B,0xFDFEC,0x754A44C,0xD4ABA,0x5428A93,0xE353FCA,0xE};
+const BIG_256_28 CURVE_Order_ANSSI= {0x6D655E1,0xFDD459C,0x2BF941F,0x67E140D,0x35B53DC,0xE8CE424,0xF10126D,0xB3AD58,0x1FD178C,0xF};
+const BIG_256_28 CURVE_Gx_ANSSI= {0x98F5CFF,0xC97A2DD,0x8B70164,0xD2DCAF9,0x3958C27,0x4749D42,0xB31183D,0x56C139E,0x6B3D4C3,0xB};
+const BIG_256_28 CURVE_Gy_ANSSI= {0x4062CFB,0x115A155,0x4C9E183,0xC307E8E,0xF8C2701,0xF0F3ECE,0x11F9271,0xC8B2049,0x142E0F7,0x6};
+#endif
+
+#if CHUNK==64
+const int CURVE_Cof_I_ANNSI= 1;
+const BIG_256_56 CURVE_Cof_ANSSI= {0x1L,0x0L,0x0L,0x0L,0x0L};
+const int CURVE_A_ANSSI= -3;
+const int CURVE_B_I_ANSSI= 0;
+const BIG_256_56 CURVE_B_ANSSI= {0x75ED967B7BB73FL,0xC9AE4B1A18030L,0x754A44C00FDFECL,0x5428A9300D4ABAL,0xEE353FCAL};
+const BIG_256_56 CURVE_Order_ANSSI= {0xFDD459C6D655E1L,0x67E140D2BF941FL,0xE8CE42435B53DCL,0xB3AD58F10126DL,0xF1FD178CL};
+const BIG_256_56 CURVE_Gx_ANSSI= {0xC97A2DD98F5CFFL,0xD2DCAF98B70164L,0x4749D423958C27L,0x56C139EB31183DL,0xB6B3D4C3L};
+const BIG_256_56 CURVE_Gy_ANSSI= {0x115A1554062CFBL,0xC307E8E4C9E183L,0xF0F3ECEF8C2701L,0xC8B204911F9271L,0x6142E0F7L};
+#endif
+
diff --git a/version3/c/rom_curve_BLS24.c b/version3/c/rom_curve_BLS24.c
new file mode 100644
index 0000000..6f55314
--- /dev/null
+++ b/version3/c/rom_curve_BLS24.c
@@ -0,0 +1,67 @@
+#include "arch.h"
+#include "ecp_BLS24.h"
+
+/* Curve BLS24 - Pairing friendly BLS24 curve */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+// Base Bits= 29
+
+const int CURVE_Cof_I_BLS24= 0;
+const int CURVE_A_BLS24= 0;
+const int CURVE_B_I_BLS24= 19;
+const BIG_480_29 CURVE_B_BLS24= {0x13,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG_480_29 CURVE_Order_BLS24= {0x10000001,0xD047FF,0x1FD54464,0x1E3CE067,0xE322DDA,0x1D356F3F,0x7433B44,0x49091F9,0x1729CC2,0x250286C,0x16E62ED,0xB403E1E,0x1001000,0x80,0x0,0x0,0x0};
+const BIG_480_29 CURVE_Gx_BLS24= {0xBE3CCD4,0x33B07AF,0x1B67D159,0x3DFC5B5,0xEBA1FCC,0x1A3C1F84,0x56BE204,0xEF8DF1B,0x11AE2D84,0x5FEE546,0x161B3BF9,0x183B20EE,0x1EA5D99B,0x14F0C5BF,0xBE521B7,0x17C682F9,0x1AB2};
+const BIG_480_29 CURVE_Gy_BLS24= {0x121E5245,0x65D2E56,0x11577DB1,0x16DACC11,0x14F39746,0x459F694,0x12483FCF,0xC828B04,0xFD63E5A,0x7B1D52,0xAFDE738,0xF349254,0x1A4529FF,0x10E53353,0xF91DEE1,0x16E18D8A,0x47FC};
+
+const BIG_480_29 CURVE_Bnx_BLS24= {0x11FF80,0x80010,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG_480_29 CURVE_Cof_BLS24= {0x19F415AB,0x1E0FFDFF,0x15AAADFF,0xAA,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG_480_29 CURVE_Cru_BLS24= {0xDD794A9,0x1DE138A3,0x2BCCE90,0xC746127,0x15223DDC,0x1DD8890B,0xED08DB7,0xE24B9F,0xE379CE6,0x37011AC,0x11BAC820,0x1EEFAD01,0x200860F,0x147218A6,0xF16A209,0xF0079,0x555C};
+const BIG_480_29 CURVE_Pxaa_BLS24= {0x14E24678,0x1F149A9B,0x9609022,0x1C186868,0xCDEFC69,0x1C87BB2E,0x14A2235F,0x7586755,0x5896747,0x159BFE92,0x3B5572E,0x1710A521,0x71EB14A,0xC643C33,0x12581DE5,0x1BCA747D,0x959};
+const BIG_480_29 CURVE_Pxab_BLS24= {0x1FB099B8,0x3FCF5D7,0x4A91C0E,0xC6EEB40,0x11FC2385,0x11B5AE8D,0x1A9CC3E7,0x194FE144,0x185DB2A5,0x930E1C7,0x14F85F9A,0x1F2ED4E,0x1D1BE5AD,0xF26169C,0xCF7F194,0x1DA1062E,0x3B0D};
+const BIG_480_29 CURVE_Pxba_BLS24= {0x11AD15D3,0xD0E6F38,0x17DB85BB,0x30A62F1,0x1EA3E09A,0x17B25FA1,0x1B7959AC,0x1165B19A,0x6C74FDB,0x18F790E1,0x12278FDA,0x1E008F79,0x103F329,0x14619FF1,0x1EBCAA8,0xFF5A9CA,0x3EC2};
+const BIG_480_29 CURVE_Pxbb_BLS24= {0x1EE0F480,0x3D5943A,0xF5B12E3,0x128AADC8,0x180E1CB9,0x1EFD916F,0x48BC7F,0x1D5EE1FA,0x5698EF5,0x11D6AED9,0x1386BC6E,0x196E900B,0x1CE2E465,0xC2A8ED3,0x1E67DF99,0x71B7940,0xA5B};
+const BIG_480_29 CURVE_Pyaa_BLS24= {0x14781AA0,0xC324C98,0xEDC2AC,0x16C13B46,0x145FC44B,0x12529530,0x1310A8C4,0x1768C5C0,0xE19AE68,0x56E1C1D,0x13DAF93F,0x17E94366,0xF901AD0,0x76800CC,0x10250D8B,0x1E6BAE6D,0x5057};
+const BIG_480_29 CURVE_Pyab_BLS24= {0xEAE08FA,0xDDF62BF,0xA97E5AB,0xF0EE97,0x99A42CA,0x1C326578,0xF33DC11,0x8B913F7,0xFEF8552,0x19F35B90,0x58DDBDE,0xFC32FF2,0x1587B5DF,0xB5EB07A,0x1A258DE0,0x1692CC3D,0x2CE2};
+const BIG_480_29 CURVE_Pyba_BLS24= {0x5F0CC41,0xB9813B5,0x14C2A87D,0xFF1264A,0x19AF8A14,0x6CE6C3,0x2A7F8A2,0x121DCA7D,0x7D37153,0x19D21078,0x15466DC7,0x1362982B,0x1DD3CB5B,0x1CFC0D1C,0x18C69AF8,0x8CC7DC,0x1807};
+const BIG_480_29 CURVE_Pybb_BLS24= {0x115C1CAE,0x78D9732,0x16C26237,0x5A81A6A,0x1C38A777,0x56121FE,0x4DAD9D7,0x1BEBA670,0xA1D72FC,0xD60B274,0x19734258,0x1D621775,0x4691771,0x14206B68,0x17B22DE4,0x29D5B37,0x499D};
+const BIG_480_29 CURVE_W_BLS24[2]= {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+const BIG_480_29 CURVE_SB_BLS24[2][2]= {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+const BIG_480_29 CURVE_WB_BLS24[4]= {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+const BIG_480_29 CURVE_BB_BLS24[4][4]= {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+#endif
+
+#if CHUNK==64
+// Base Bits= 56
+
+const int CURVE_Cof_I_BLS24= 0;
+const int CURVE_A_BLS24= 0;
+const int CURVE_B_I_BLS24= 19;
+const BIG_480_56 CURVE_B_BLS24= {0x13L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG_480_56 CURVE_Order_BLS24= {0x1A08FFF0000001L,0x1E7033FF551190L,0x6ADE7EE322DDAFL,0x848FC9D0CED13AL,0x50D81729CC224L,0x1F0F05B98BB44AL,0x10010010005A0L,0x0L,0x0L};
+const BIG_480_56 CURVE_Gx_BLS24= {0x6760F5EBE3CCD4L,0xEFE2DAED9F4564L,0x783F08EBA1FCC1L,0xC6F8D95AF88134L,0xDCA8D1AE2D8477L,0x9077586CEFE4BFL,0x8B7FEA5D99BC1DL,0x17CAF9486DE9E1L,0x1AB2BE34L};
+const BIG_480_56 CURVE_Gy_BLS24= {0xCBA5CAD21E5245L,0x6D6608C55DF6C4L,0xB3ED294F39746BL,0x145824920FF3C8L,0x63AA4FD63E5A64L,0x492A2BF79CE00FL,0x66A7A4529FF79AL,0x6C53E477B861CAL,0x47FCB70CL};
+
+const BIG_480_56 CURVE_Bnx_BLS24= {0x100020011FF80L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG_480_56 CURVE_Cof_BLS24= {0xC1FFBFF9F415ABL,0x5556AAB7FFL,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG_480_56 CURVE_Cru_BLS24= {0xBC27146DD794A9L,0x3A30938AF33A43L,0xB112175223DDC6L,0x125CFBB4236DFBL,0x2358E379CE607L,0xD680C6EB20806EL,0x314C200860FF77L,0x3CBC5A88268E4L,0x555C0078L};
+const BIG_480_56 CURVE_Pxaa_BLS24= {0xE2935374E24678L,0xC34342582408BL,0xF765CCDEFC69EL,0xC33AAD2888D7F9L,0x7FD2458967473AL,0x52908ED55CBAB3L,0x786671EB14AB88L,0xA3EC96077958C8L,0x959DE53L};
+const BIG_480_56 CURVE_Pxab_BLS24= {0x7F9EBAFFB099B8L,0x3775A012A47038L,0x6B5D1B1FC23856L,0x7F0A26A730F9E3L,0x1C38F85DB2A5CAL,0x76A753E17E6926L,0x2D39D1BE5AD0F9L,0x31733DFC651E4CL,0x3B0DED08L};
+const BIG_480_56 CURVE_Pxba_BLS24= {0xA1CDE711AD15D3L,0x853178DF6E16EDL,0x64BF43EA3E09A1L,0x2D8CD6DE566B2FL,0xF21C26C74FDB8BL,0x47BCC89E3F6B1EL,0x3FE2103F329F00L,0x4E507AF2AA28C3L,0x3EC27FADL};
+const BIG_480_56 CURVE_Pxbb_BLS24= {0x7AB2875EE0F480L,0x4556E43D6C4B8CL,0xFB22DF80E1CB99L,0xF70FD0122F1FFDL,0xD5DB25698EF5EAL,0x4805CE1AF1BA3AL,0x1DA7CE2E465CB7L,0xCA0799F7E65855L,0xA5B38DBL};
+const BIG_480_56 CURVE_Pyaa_BLS24= {0x86499314781AA0L,0x609DA303B70AB1L,0xA52A6145FC44BBL,0x462E04C42A3124L,0xC383AE19AE68BBL,0xA1B34F6BE4FCADL,0x198F901AD0BF4L,0x736C094362CED0L,0x5057F35DL};
+const BIG_480_56 CURVE_Pyab_BLS24= {0xBBEC57EEAE08FAL,0x78774BAA5F96ADL,0x64CAF099A42CA0L,0xC89FBBCCF70478L,0x6B720FEF855245L,0x97F916376F7B3EL,0x60F5587B5DF7E1L,0x61EE89637816BDL,0x2CE2B496L};
+const BIG_480_56 CURVE_Pyba_BLS24= {0x730276A5F0CC41L,0xF89325530AA1F5L,0xD9CD879AF8A147L,0xEE53E8A9FE2880L,0x420F07D3715390L,0x4C15D519B71F3AL,0x1A39DD3CB5B9B1L,0x3EE631A6BE39F8L,0x18070466L};
+const BIG_480_56 CURVE_Pybb_BLS24= {0xF1B2E6515C1CAEL,0xD40D355B0988DCL,0xC243FDC38A7772L,0x5D338136B675CAL,0x164E8A1D72FCDFL,0xBBAE5CD0961ACL,0xD6D04691771EB1L,0xD9BDEC8B792840L,0x499D14EAL};
+const BIG_480_56 CURVE_W_BLS24[2]= {{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}};
+const BIG_480_56 CURVE_SB_BLS24[2][2]= {{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}}};
+const BIG_480_56 CURVE_WB_BLS24[4]= {{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}};
+const BIG_480_56 CURVE_BB_BLS24[4][4]= {{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}}};
+
+#endif
\ No newline at end of file
diff --git a/version3/c/rom_curve_BLS381.c b/version3/c/rom_curve_BLS381.c
new file mode 100644
index 0000000..c4f019e
--- /dev/null
+++ b/version3/c/rom_curve_BLS381.c
@@ -0,0 +1,62 @@
+#include "arch.h"
+#include "ecp_BLS381.h"
+
+/* Curve BLS381 - Pairing friendly BLS curve */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+const int CURVE_Cof_I_BLS381= 0;
+const int CURVE_A_BLS381= 0;
+const int CURVE_B_I_BLS381= 4;
+const BIG_384_29 CURVE_B_BLS381= {0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG_384_29 CURVE_Order_BLS381= {0x1,0x1FFFFFF8,0x1F96FFBF,0x1B4805FF,0x1D80553B,0xC0404D0,0x1520CCE7,0xA6533AF,0x73EDA7,0x0,0x0,0x0,0x0,0x0};
+const BIG_384_29 CURVE_Gx_BLS381= {0x1B22C6BB,0x19D78056,0x1E86BBFE,0xBD07FF2,0x1AC586C5,0x1D1F8B8D,0x4168538,0x9F2EE97,0xFC3688C,0x27D4D60,0x9A558E3,0x32FAF28,0x1F1D3A73,0xB};
+const BIG_384_29 CURVE_Gy_BLS381= {0x6C5E7E1,0x551194A,0x222B903,0x198E8945,0xB3EDD03,0xC659602,0xBD8036C,0x12BABA01,0x4FCF5E0,0xBA0EC57,0x8278C3B,0x75541E3,0xB3F481E,0x4};
+
+
+const BIG_384_29 CURVE_Bnx_BLS381= {0x10000,0x10080000,0x34,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG_384_29 CURVE_Cof_BLS381= {0xAAAB,0x55558,0x157855A3,0x191800AA,0x396,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG_384_29 CURVE_Cru_BLS381= {0x1FFEFFFE,0x100FFFFF,0x280008B,0xFB026C4,0x9688DE1,0x149DF37C,0x1FAB76CE,0xED41EE,0x11BA69C6,0x1EFBB672,0x17C659CB,0x0,0x0,0x0};
+
+const BIG_384_29 CURVE_Pxa_BLS381= {0x121BDB8,0x402B646,0x16EFBF5,0x18064D50,0x1D1770BA,0x5B23D71,0xC0AD144,0x1A9F4807,0x11C6E47A,0x196E2882,0x9820149,0x11E1522,0x4AA2B2F,0x1};
+const BIG_384_29 CURVE_Pxb_BLS381= {0x1D042B7E,0xD63E82A,0x51755F9,0x19E22427,0x15049334,0x10DDEE3F,0x186AD769,0x1A132416,0x5596BD0,0x4413A7B,0x1F6B34E8,0x4E33EC0,0x1E02B605,0x9};
+const BIG_384_29 CURVE_Pya_BLS381= {0x8B82801,0xC9AA430,0xB28A278,0x15939877,0xD12C923,0xD34A8B0,0xE9DB50A,0x155197BA,0x1AADFD9B,0x16D171A8,0x3327371,0x4FADC23,0xE5D5277,0x6};
+const BIG_384_29 CURVE_Pyb_BLS381= {0x105F79BE,0x15483AFF,0x1B07686A,0xE1A4EB9,0x99AB3F3,0x955AB97,0xEBC99D2,0xFD0B4EC,0x19CB3E28,0x15E145C,0xCAB34AC,0x1D4E6998,0x6C4A02,0x3};
+const BIG_384_29 CURVE_W_BLS381[2]= {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+const BIG_384_29 CURVE_SB_BLS381[2][2]= {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+const BIG_384_29 CURVE_WB_BLS381[4]= {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+const BIG_384_29 CURVE_BB_BLS381[4][4]= {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+
+
+#endif
+
+#if CHUNK==64
+
+const int CURVE_Cof_I_BLS381= 0;
+const int CURVE_A_BLS381= 0;
+const int CURVE_B_I_BLS381= 4;
+const BIG_384_58 CURVE_B_BLS381= {0x4L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG_384_58 CURVE_Order_BLS381= {0x3FFFFFF00000001L,0x36900BFFF96FFBFL,0x180809A1D80553BL,0x14CA675F520CCE7L,0x73EDA7L,0x0L,0x0L};
+const BIG_384_58 CURVE_Gx_BLS381= {0x33AF00ADB22C6BBL,0x17A0FFE5E86BBFEL,0x3A3F171BAC586C5L,0x13E5DD2E4168538L,0x4FA9AC0FC3688CL,0x65F5E509A558E3L,0x17F1D3A73L};
+const BIG_384_58 CURVE_Gy_BLS381= {0xAA232946C5E7E1L,0x331D128A222B903L,0x18CB2C04B3EDD03L,0x25757402BD8036CL,0x1741D8AE4FCF5E0L,0xEAA83C68278C3BL,0x8B3F481EL};
+
+const BIG_384_58 CURVE_Bnx_BLS381= {0x201000000010000L,0x34L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG_384_58 CURVE_Cof_BLS381= {0xAAAB0000AAABL,0x3230015557855A3L,0x396L,0x0L,0x0L,0x0L,0x0L};
+const BIG_384_58 CURVE_Cru_BLS381= {0x201FFFFFFFEFFFEL,0x1F604D88280008BL,0x293BE6F89688DE1L,0x1DA83DDFAB76CEL,0x3DF76CE51BA69C6L,0x17C659CBL,0x0L};
+
+const BIG_384_58 CURVE_Pxa_BLS381= {0x8056C8C121BDB8L,0x300C9AA016EFBF5L,0xB647AE3D1770BAL,0x353E900EC0AD144L,0x32DC51051C6E47AL,0x23C2A449820149L,0x24AA2B2FL};
+const BIG_384_58 CURVE_Pxb_BLS381= {0x1AC7D055D042B7EL,0x33C4484E51755F9L,0x21BBDC7F5049334L,0x3426482D86AD769L,0x88274F65596BD0L,0x9C67D81F6B34E8L,0x13E02B605L};
+const BIG_384_58 CURVE_Pya_BLS381= {0x193548608B82801L,0x2B2730EEB28A278L,0x1A695160D12C923L,0x2AA32F74E9DB50AL,0x2DA2E351AADFD9BL,0x9F5B8463327371L,0xCE5D5277L};
+const BIG_384_58 CURVE_Pyb_BLS381= {0x2A9075FF05F79BEL,0x1C349D73B07686AL,0x12AB572E99AB3F3L,0x1FA169D8EBC99D2L,0x2BC28B99CB3E28L,0x3A9CD330CAB34ACL,0x606C4A02L};
+const BIG_384_58 CURVE_W_BLS381[2]= {{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}};
+const BIG_384_58 CURVE_SB_BLS381[2][2]= {{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}}};
+const BIG_384_58 CURVE_WB_BLS381[4]= {{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}};
+const BIG_384_58 CURVE_BB_BLS381[4][4]= {{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}}};
+
+#endif
diff --git a/version3/c/rom_curve_BLS383.c b/version3/c/rom_curve_BLS383.c
new file mode 100644
index 0000000..9b870e6
--- /dev/null
+++ b/version3/c/rom_curve_BLS383.c
@@ -0,0 +1,62 @@
+#include "arch.h"
+#include "ecp_BLS383.h"
+
+/* Curve BLS383 - Pairing friendly BLS curve */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+// Base Bits= 29
+
+const int CURVE_A_BLS383= 0;
+const int CURVE_Cof_I_BLS383= 0;
+const BIG_384_29 CURVE_Cof_BLS383= {0x15169EAB,0xA82AB0A,0xAAEFFED,0x15558001,0x555,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const int CURVE_B_I_BLS383= 15;
+const BIG_384_29 CURVE_B_BLS383= {0xF,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG_384_29 CURVE_Order_BLS383= {0x1EBC0001,0x1904CF5F,0x834E5CE,0xBE12B42,0xB381DE0,0xE40B4C,0x270110,0x10018017,0x1002001,0x0,0x0,0x0,0x0,0x0};
+const BIG_384_29 CURVE_Gx_BLS383= {0x8734573,0x623B9C8,0x1D1DC11E,0xBB7E107,0x1E3445C5,0x1D6C2578,0x10B0BE1E,0xED6103E,0x10F31D9F,0x296ED82,0x18E0D7D0,0x12F3D9C9,0x1FCBA55B,0x20};
+const BIG_384_29 CURVE_Gy_BLS383= {0x3F224,0x968B2F4,0x1FE63F48,0xFA93D90,0x14D2DDE5,0x54A56F5,0x12441D4C,0x18CD76C8,0x199D0DAD,0xE18E236,0x92BA73,0x99F6600,0x8F16727,0x3};
+
+const BIG_384_29 CURVE_Bnx_BLS383= {0x1001200,0x400000,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG_384_29 CURVE_Cru_BLS383= {0xEAAC2A9,0x61B3A81,0x17D974B7,0xBED0345,0xA341BC2,0x17A51A6F,0x5738948,0x69B7BAE,0x14605445,0x374A43,0x8116AD1,0x956DD69,0x16556956,0x2A};
+const BIG_384_29 CURVE_Pxa_BLS383= {0xD7F2D86,0x1E59DB1,0x17474F85,0x1FB56CF2,0x572EE81,0xE487AB1,0x96F51FC,0x190A5AAE,0x6432501,0x13E58F3A,0x101E6425,0xFD807D1,0x34D2240,0x3};
+const BIG_384_29 CURVE_Pxb_BLS383= {0x452DE15,0x1ECF20F6,0x1FF9837B,0x95651AA,0xD5D75B5,0x5D44749,0x12277F66,0x1DB3A0B9,0x1D24F498,0x19441B0E,0x1CDE9DC5,0x2C975,0xD78006,0x18};
+const BIG_384_29 CURVE_Pya_BLS383= {0x1408CB41,0x34785DC,0x3586597,0x13DBC9E4,0x1A2E75B4,0x1D65489,0xCF9A25E,0x1ACE7933,0x1B6E990E,0x19FF31A3,0x12527615,0x1A44A68F,0x1792CF93,0x19};
+const BIG_384_29 CURVE_Pyb_BLS383= {0x1F479093,0x16C2321B,0x1889218E,0x87961BC,0x1BC98B01,0x197A24FB,0xA3DEBC2,0x88D67DF,0x1CE0D,0x1E8AD3D7,0x93B9EE9,0x59B18D6,0xE5247DD,0x10};
+const BIG_384_29 CURVE_W_BLS383[2]= {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+const BIG_384_29 CURVE_SB_BLS383[2][2]= {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+const BIG_384_29 CURVE_WB_BLS383[4]= {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+const BIG_384_29 CURVE_BB_BLS383[4][4]= {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+
+#endif
+
+#if CHUNK==64
+
+// Base Bits= 58
+
+const int CURVE_A_BLS383= 0;
+const int CURVE_Cof_I_BLS383= 0;
+const BIG_384_58 CURVE_Cof_BLS383= {0x150556155169EABL,0x2AAB0002AAEFFEDL,0x555L,0x0L,0x0L,0x0L,0x0L};
+const int CURVE_B_I_BLS383= 15;
+const BIG_384_58 CURVE_B_BLS383= {0xFL,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG_384_58 CURVE_Order_BLS383= {0x32099EBFEBC0001L,0x17C25684834E5CEL,0x1C81698B381DE0L,0x2003002E0270110L,0x1002001L,0x0L,0x0L};
+const BIG_384_58 CURVE_Gx_BLS383= {0xC4773908734573L,0x176FC20FD1DC11EL,0x3AD84AF1E3445C5L,0x1DAC207D0B0BE1EL,0x52DDB050F31D9FL,0x25E7B3938E0D7D0L,0x41FCBA55BL};
+const BIG_384_58 CURVE_Gy_BLS383= {0x12D165E8003F224L,0x1F527B21FE63F48L,0xA94ADEB4D2DDE5L,0x319AED912441D4CL,0x1C31C46D99D0DADL,0x133ECC00092BA73L,0x68F16727L};
+
+const BIG_384_58 CURVE_Bnx_BLS383= {0x8000001001200L,0x40L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG_384_58 CURVE_Cru_BLS383= {0xC367502EAAC2A9L,0x17DA068B7D974B7L,0x2F4A34DEA341BC2L,0xD36F75C5738948L,0x6E94874605445L,0x12ADBAD28116AD1L,0x556556956L};
+const BIG_384_58 CURVE_Pxa_BLS383= {0x3CB3B62D7F2D86L,0x3F6AD9E57474F85L,0x1C90F562572EE81L,0x3214B55C96F51FCL,0x27CB1E746432501L,0x1FB00FA301E6425L,0x634D2240L};
+const BIG_384_58 CURVE_Pxb_BLS383= {0x3D9E41EC452DE15L,0x12ACA355FF9837BL,0xBA88E92D5D75B5L,0x3B6741732277F66L,0x3288361DD24F498L,0x592EBCDE9DC5L,0x300D78006L};
+const BIG_384_58 CURVE_Pya_BLS383= {0x68F0BB9408CB41L,0x27B793C83586597L,0x3ACA913A2E75B4L,0x359CF266CF9A25EL,0x33FE6347B6E990EL,0x34894D1F2527615L,0x33792CF93L};
+const BIG_384_58 CURVE_Pyb_BLS383= {0x2D846437F479093L,0x10F2C379889218EL,0x32F449F7BC98B01L,0x111ACFBEA3DEBC2L,0x3D15A7AE001CE0DL,0xB3631AC93B9EE9L,0x20E5247DDL};
+const BIG_384_58 CURVE_W_BLS383[2]= {{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}};
+const BIG_384_58 CURVE_SB_BLS383[2][2]= {{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}}};
+const BIG_384_58 CURVE_WB_BLS383[4]= {{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}};
+const BIG_384_58 CURVE_BB_BLS383[4][4]= {{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}}};
+
+#endif
\ No newline at end of file
diff --git a/version3/c/rom_curve_BLS461.c b/version3/c/rom_curve_BLS461.c
new file mode 100644
index 0000000..37180e7
--- /dev/null
+++ b/version3/c/rom_curve_BLS461.c
@@ -0,0 +1,59 @@
+#include "arch.h"
+#include "ecp_BLS461.h"
+
+/* Curve BLS383 - Pairing friendly BLS curve */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+const int CURVE_Cof_I_BLS461= 0;
+const int CURVE_A_BLS461= 0;
+const int CURVE_B_I_BLS461= 9;
+const BIG_464_28 CURVE_B_BLS461= {0x9,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG_464_28 CURVE_Order_BLS461= {0x1,0x0,0xFFFFC00,0x7FEFFFE,0x110000,0x7FFC800,0x801FC01,0x5FD000E,0x17FE0,0xFFFC018,0xFFFFFF7,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG_464_28 CURVE_Gx_BLS461= {0xADEE93D,0x4D026A8,0x74B7411,0xD9C00EE,0x31AC7F2,0xC3981B5,0x9218229,0xD3564DC,0xA096650,0x6F7C292,0x9743616,0xBE922B1,0x12CF668,0xC81327,0x463B73A,0xE74E99B,0xAD0};
+const BIG_464_28 CURVE_Gy_BLS461= {0xAD1D465,0xF763157,0xC4FF470,0x17884C8,0xB8D215D,0xA819E66,0xF4959D0,0xE5C3245,0xB84910A,0xB8BFA40,0xBE96EEC,0x8BF9F8C,0xF277ACC,0x5F1C3F2,0x5F68C9,0xCDB14B3,0x77B};
+
+const BIG_464_28 CURVE_Bnx_BLS461= {0x0,0xFBFFFE0,0x1FFFFF,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG_464_28 CURVE_Cof_BLS461= {0xAAAAAAB,0xA7FFFEA,0x1556AA,0xD55AAAB,0x554FFFF,0x1555,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG_464_28 CURVE_Cru_BLS461= {0xFFFFFFE,0x40001F,0xFE00000,0xFFE7FFF,0xF0FFF6F,0x7200C47,0x7BCC604,0x15796DB,0xCF47771,0x9875433,0x613F0E8,0x5000502,0xEBFFF60,0x1FFFFF,0x0,0x0,0x0};
+const BIG_464_28 CURVE_Pxa_BLS461= {0x6D0A37C,0x5B50318,0x75DCC46,0xC2E492E,0xD6878A9,0xE01F919,0xF92F564,0x86DB74F,0x66803F0,0x46D581A,0x7ED78D,0x2F97C29,0xC270C89,0xF679453,0x6A50A9A,0x54138A0,0x10CC};
+const BIG_464_28 CURVE_Pxb_BLS461= {0x2C1C0AD,0xF85CA8C,0x25CADE9,0x6CD66C4,0xA289609,0xC612951,0xEE2401A,0x529ABEB,0xF65B17D,0xBA09D33,0xD4C5AF5,0x4D4371E,0x46A672E,0xA279D22,0xACEA37C,0x1FB4FE5,0x95C};
+const BIG_464_28 CURVE_Pya_BLS461= {0x2FB006,0xCCD0C1B,0xA12A337,0x3D194A4,0xC92C895,0x4960CFC,0x39FC68B,0x3A9B00F,0xED1BA0F,0xA7DBBC5,0xA9CDFD8,0x27CC2F7,0x4E73ED2,0x6070F4F,0xEBA7E67,0xAC848E7,0x226};
+const BIG_464_28 CURVE_Pyb_BLS461= {0xDF1457C,0xA506ADF,0x4C20A8,0xD6A31DC,0x36E3FB4,0xEA9A8F1,0x92F5668,0x3C3BE44,0x67A1297,0x74BEABA,0x56A20BE,0x4C42E38,0x45157F0,0x2AB1D00,0xBB402EA,0x101B4FA,0xE38};
+const BIG_464_28 CURVE_W_BLS461[2]= {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+const BIG_464_28 CURVE_SB_BLS461[2][2]= {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+const BIG_464_28 CURVE_WB_BLS461[4]= {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+const BIG_464_28 CURVE_BB_BLS461[4][4]= {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+
+#endif
+
+#if CHUNK==64
+
+const int CURVE_Cof_I_BLS461= 0;
+const int CURVE_A_BLS461= 0;
+const int CURVE_B_I_BLS461= 9;
+const BIG_464_60 CURVE_B_BLS461= {0x9L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG_464_60 CURVE_Order_BLS461= {0x1L,0x7FEFFFEFFFFC0L,0xC017FFC80001100L,0x7FE05FD000E801FL,0xFFFF7FFFC018001L,0xFFL,0x0L,0x0L};
+const BIG_464_60 CURVE_Gx_BLS461= {0x14D026A8ADEE93DL,0xF2D9C00EE74B741L,0x229C3981B531AC7L,0x6650D3564DC9218L,0x436166F7C292A09L,0x2CF668BE922B197L,0x463B73A0C813271L,0xAD0E74E99BL};
+const BIG_464_60 CURVE_Gy_BLS461= {0xF763157AD1D465L,0x5D17884C8C4FF47L,0x9D0A819E66B8D21L,0x910AE5C3245F495L,0x96EECB8BFA40B84L,0x277ACC8BF9F8CBEL,0x5F68C95F1C3F2FL,0x77BCDB14B3L};
+
+const BIG_464_60 CURVE_Bnx_BLS461= {0xFFBFFFE00000000L,0x1FFFFL,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG_464_60 CURVE_Cof_BLS461= {0xAA7FFFEAAAAAAABL,0xFFD55AAAB01556AL,0x1555554FFL,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG_464_60 CURVE_Cru_BLS461= {0x40001FFFFFFFEL,0x6FFFE7FFFFE0000L,0x6047200C47F0FFFL,0x777115796DB7BCCL,0x3F0E89875433CF4L,0xBFFF60500050261L,0x1FFFFFEL,0x0L};
+const BIG_464_60 CURVE_Pxa_BLS461= {0x65B503186D0A37CL,0xA9C2E492E75DCC4L,0x564E01F919D6878L,0x3F086DB74FF92FL,0xED78D46D581A668L,0x270C892F97C2907L,0x6A50A9AF679453CL,0x10CC54138A0L};
+const BIG_464_60 CURVE_Pxb_BLS461= {0x9F85CA8C2C1C0ADL,0x96CD66C425CADEL,0x1AC612951A2896L,0xB17D529ABEBEE24L,0xC5AF5BA09D33F65L,0x6A672E4D4371ED4L,0xACEA37CA279D224L,0x95C1FB4FE5L};
+const BIG_464_60 CURVE_Pya_BLS461= {0x7CCD0C1B02FB006L,0x953D194A4A12A33L,0x68B4960CFCC92C8L,0xBA0F3A9B00F39FCL,0xCDFD8A7DBBC5ED1L,0xE73ED227CC2F7A9L,0xEBA7E676070F4F4L,0x226AC848E7L};
+const BIG_464_60 CURVE_Pyb_BLS461= {0x8A506ADFDF1457CL,0xB4D6A31DC04C20AL,0x668EA9A8F136E3FL,0x12973C3BE4492F5L,0xA20BE74BEABA67AL,0x5157F04C42E3856L,0xBB402EA2AB1D004L,0xE38101B4FAL};
+const BIG_464_60 CURVE_W_BLS461[2]= {{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}};
+const BIG_464_60 CURVE_SB_BLS461[2][2]= {{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}}};
+const BIG_464_60 CURVE_WB_BLS461[4]= {{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}};
+const BIG_464_60 CURVE_BB_BLS461[4][4]= {{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}}};
+
+
+#endif
\ No newline at end of file
diff --git a/version3/c/rom_curve_BLS48.c b/version3/c/rom_curve_BLS48.c
new file mode 100644
index 0000000..ba97dc0
--- /dev/null
+++ b/version3/c/rom_curve_BLS48.c
@@ -0,0 +1,88 @@
+#include "arch.h"
+#include "ecp_BLS48.h"
+
+/* Curve BLS48 - Pairing friendly BLS48 curve */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+// Base Bits= 29
+
+const int CURVE_Cof_I_BLS48= 0;
+const int CURVE_A_BLS48= 0;
+const int CURVE_B_I_BLS48= 17;
+const BIG_560_29 CURVE_B_BLS48= {0x11,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG_560_29 CURVE_Order_BLS48= {0x1,0x17FFF800,0xA769C21,0x8AA813C,0x2029C21,0xA68F58B,0xB6307F4,0x1184DA51,0x6DFED78,0x1A3C85E9,0x571037B,0x1637F1F9,0x1C465FB0,0x98354B9,0x118DF17A,0x1422355D,0x43BF73E,0x6,0x0,0x0};
+const BIG_560_29 CURVE_Gx_BLS48= {0x5D71D33,0x1943697B,0x18CB783F,0x1B00AA9F,0x1711EE0B,0x7F80B23,0x129FD8CC,0x1345E03F,0x9A80F66,0x7038173,0xC056511,0x142801F5,0x42B2C3A,0x1AF09869,0x7924166,0x8381264,0x957EDD7,0xBACAEDC,0xA27A4A1,0x13};
+const BIG_560_29 CURVE_Gy_BLS48= {0xA6ED83A,0x14D2D9FF,0xA29C33D,0x1B8972A9,0x6958677,0x19C8F547,0x1DED7E3E,0x14F9E3DC,0x18FB7229,0x27171C0,0x1551E32D,0xE6184CC,0x6260E3C,0x733D204,0x579C437,0x1534665C,0x2B3349D,0x3162FD7,0xB634253,0x1};
+
+const BIG_560_29 CURVE_Bnx_BLS48= {0x1DE40020,0x3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG_560_29 CURVE_Cof_BLS48= {0x1F12ABEB,0x516887B,0x5,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG_560_29 CURVE_Cru_BLS48= {0xCBBA429,0x1B273F3,0xD3DD160,0x19C61452,0x308093A,0x146E1E34,0xAE0E768,0x1185948,0x1B73BC2D,0x93D855C,0x1B1A639C,0x118C919B,0xFF04AE3,0xF1CCD77,0x91318E5,0x10644780,0x3A79F7,0x1BE77919,0x145F60F3,0x1F};
+const BIG_560_29 CURVE_Pxaaa_BLS48= {0x923CE4A,0x14697474,0xAE04F4A,0x17AE205A,0x1313A20C,0x10B2EC50,0x18DF074F,0x15FE3FE8,0x7C90B98,0x959BF85,0xE57BD37,0x14376C96,0xBF57375,0xE20B625,0x12EE2172,0x1CBBCE85,0x1A5D9487,0xD0E024B,0x195E3602,0x1C};
+const BIG_560_29 CURVE_Pxaab_BLS48= {0xC0A1BE1,0x138E6E2D,0x1DF5FDC,0x151FC760,0x33972C5,0x56AA3C2,0x2491D8C,0x115B9FD7,0x140A11FA,0x1873AE35,0x1F259C26,0x74B0647,0x12D18B04,0x4672431,0x1C27F419,0x1CAA4D35,0x18DB48B6,0x13A54BDA,0x5080497,0x5};
+const BIG_560_29 CURVE_Pxaba_BLS48= {0x170C5DC4,0x11D39263,0x16B3BCB6,0x152C95BB,0x19BEC736,0x8849A12,0x49AB2A8,0xC7162D3,0xC58CD55,0x15C2659,0x11EE8B90,0xB40CAFC,0xE233167,0x7BEC8BE,0x129335BD,0x151C7DBB,0x78B689B,0x1B6B8EED,0x14BFBE3D,0x16};
+const BIG_560_29 CURVE_Pxabb_BLS48= {0x1A64B740,0x6B14B34,0x12481578,0x23FA931,0x323ADD1,0x206B82A,0xD789E1B,0x1FCFA666,0x1F4EEA7,0xF1E39E2,0x1968610,0xAF3EBD3,0x590D3B,0xDA0C35A,0x17306AAF,0xCF9DD2B,0x3F63B1A,0x96FF2F9,0xE102A76,0x12};
+const BIG_560_29 CURVE_Pxbaa_BLS48= {0x12F1E01F,0xDD8630B,0x12C29802,0x186239A6,0x19218788,0x4C87D1,0x16AE2501,0x775C076,0x870C80B,0x1A394429,0x1637D478,0x4A420E8,0x1C3AD4D4,0x10E5E713,0x111E6AD5,0x514FCF0,0x7CC49D3,0xC678A2,0x1787BDFD,0x1B};
+const BIG_560_29 CURVE_Pxbab_BLS48= {0x637383D,0x1851C11C,0x661F866,0x14404A7F,0x15D3D212,0x9AE28F6,0x8051F25,0x1E1CE2BF,0x137D882F,0xB231CEB,0xA8DB8FC,0x18957645,0x5E54DA8,0x1FF41C44,0x1A297414,0x17E1CBC5,0x1014F91F,0x4282AB7,0xB6CE9E3,0x10};
+const BIG_560_29 CURVE_Pxbba_BLS48= {0x1711939C,0xB41ED9E,0x69066BA,0x137CA3AD,0xCF2F6C0,0x5E6DAB9,0x2CE1323,0x946E448,0xF353D1C,0x14D9919F,0x46B7046,0x1A12015,0x3D6070,0x18C3E8D2,0x1F23BA45,0x1F1A337C,0x435A9CC,0x6CA1DF1,0x8A9CE1,0x15};
+const BIG_560_29 CURVE_Pxbbb_BLS48= {0x56F4899,0x196A0854,0xA959750,0x38A3D72,0x190BC9BC,0x145752BC,0x1E9E26DA,0x1403F88,0x71895E3,0x14162F5D,0x19FEC5FF,0x14190B16,0x7597C,0x19A3CF18,0x26A4B00,0x113D1BB6,0x7857A32,0xE0B78AB,0x1DD51E0F,0x1B};
+const BIG_560_29 CURVE_Pyaaa_BLS48= {0x14137844,0x1704BE7D,0x1FD3CCDD,0x189D8C93,0x1C768851,0xF5C37D5,0xE29C659,0x20AB1C1,0xF8896E0,0x1E08663E,0x1D1D539C,0x117E1C47,0x156CDD39,0x161F1017,0x143E8C72,0x174B22FD,0x18706190,0x49AA47E,0x19BB42E1,0xE};
+const BIG_560_29 CURVE_Pyaab_BLS48= {0xDC83190,0x12F19247,0x1AA26424,0x15D55E88,0xC418D32,0xB0E91DD,0x47CBFF7,0x2D992C1,0xDE03C1F,0x7694AE5,0x5C741A2,0x1D423AC6,0x5E02B9E,0x1E903F10,0x4EA6513,0x433A1F1,0x8EFA1C4,0xED54713,0x1E72CE4F,0x4};
+const BIG_560_29 CURVE_Pyaba_BLS48= {0x1985C0D,0xEE2FE82,0x64770FA,0x11A809B4,0x1483ACE9,0x18BCD2FA,0x171F32C,0x1612D58D,0x1E658341,0x1CBE2201,0x186E971,0x73F0E1,0xB0A5F40,0xAC90FB0,0x1635E008,0x237498B,0x1F3140D6,0xBF789A9,0x1166F259,0x1A};
+const BIG_560_29 CURVE_Pyabb_BLS48= {0x159D42F8,0x1B7F0540,0x45895D7,0x14875FA2,0x1E9E7F2B,0x10139D87,0x10F3FD7D,0x11D3717F,0x69E5006,0xF9BB3C4,0x13C9ED8D,0x16516DA,0x102F51DE,0x2725FEC,0x1F125B66,0xFFC324,0x1ED80731,0x1C16C4D,0x383AAA8,0x14};
+const BIG_560_29 CURVE_Pybaa_BLS48= {0x1F38039F,0x6A8959C,0x13C68984,0x11DD12AF,0x58093CF,0x1C8550A0,0xFFA1622,0xFF85979,0x1F2ABB75,0x18862E62,0x1EB6A2C9,0x1EC80B64,0x8EC2F18,0xE7BF713,0xC36B65A,0x19C5DD89,0x18A1D1AB,0xF772C8D,0xC11927C,0x5};
+const BIG_560_29 CURVE_Pybab_BLS48= {0x95F7865,0x134F0379,0x1CE9A0E,0x17E0EADD,0x1DACADD7,0x1B18F9F8,0x181D3943,0x186679A,0x2505BB0,0x1FDF1DC8,0x11B36A49,0x11E254E9,0xA438576,0x102B09AE,0x139984F4,0x15BC0233,0x1B6F180E,0x960562B,0x48CA65B,0x6};
+const BIG_560_29 CURVE_Pybba_BLS48= {0x7CC1979,0xEC1D4FB,0x1D89E6F0,0x955F38E,0x1635FDA9,0x123D8E10,0x10076209,0x494404A,0xD733D7,0x17678BCF,0x153841F9,0x10696FFD,0x5BC9FE8,0x1A20D8B2,0xE22EC9D,0x18449116,0x108C86C5,0x1B4CD720,0x34967,0x19};
+const BIG_560_29 CURVE_Pybbb_BLS48= {0xFC9F25B,0x7E44AB1,0xE9AB5D3,0x589F00D,0x1C9D264F,0xC7478B4,0x16B24A13,0x1D2C146B,0xEF84D9A,0xF47ECDE,0x1BFEE16A,0x1B69071E,0x11AB4C1C,0xBE9D9EF,0x390F005,0x78C8288,0x1B9BF549,0x9320730,0x3D84D97,0x14};
+const BIG_560_29 CURVE_W_BLS48[2]= {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+const BIG_560_29 CURVE_SB_BLS48[2][2]= {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+const BIG_560_29 CURVE_WB_BLS48[4]= {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+const BIG_560_29 CURVE_BB_BLS48[4][4]= {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+
+
+#endif
+
+#if CHUNK==64
+
+// Base Bits= 58
+
+const int CURVE_Cof_I_BLS48= 0;
+const int CURVE_A_BLS48= 0;
+const int CURVE_B_I_BLS48= 17;
+const BIG_560_58 CURVE_B_BLS48= {0x11L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG_560_58 CURVE_Order_BLS48= {0x2FFFF0000000001L,0x11550278A769C21L,0x14D1EB162029C21L,0x2309B4A2B6307F4L,0x34790BD26DFED78L,0x2C6FE3F2571037BL,0x1306A973C465FB0L,0x28446ABB18DF17AL,0xC43BF73EL,0x0L};
+const BIG_560_58 CURVE_Gx_BLS48= {0x3286D2F65D71D33L,0x3601553F8CB783FL,0xFF01647711EE0BL,0x268BC07F29FD8CCL,0xE0702E69A80F66L,0x285003EAC056511L,0x35E130D242B2C3AL,0x107024C87924166L,0x17595DB8957EDD7L,0x26A27A4A1L};
+const BIG_560_58 CURVE_Gy_BLS48= {0x29A5B3FEA6ED83AL,0x3712E552A29C33DL,0x3391EA8E6958677L,0x29F3C7B9DED7E3EL,0x4E2E3818FB7229L,0x1CC30999551E32DL,0xE67A4086260E3CL,0x2A68CCB8579C437L,0x62C5FAE2B3349DL,0x2B634253L};
+
+const BIG_560_58 CURVE_Bnx_BLS48= {0x7DE40020L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG_560_58 CURVE_Cof_BLS48= {0xA2D10F7F12ABEBL,0x5L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG_560_58 CURVE_Cru_BLS48= {0x364E7E6CBBA429L,0x338C28A4D3DD160L,0x28DC3C68308093AL,0x230B290AE0E768L,0x127B0AB9B73BC2DL,0x23192337B1A639CL,0x1E399AEEFF04AE3L,0x20C88F0091318E5L,0x37CEF23203A79F7L,0x3F45F60F3L};
+const BIG_560_58 CURVE_Pxaaa_BLS48= {0x28D2E8E8923CE4AL,0x2F5C40B4AE04F4AL,0x2165D8A1313A20CL,0x2BFC7FD18DF074FL,0x12B37F0A7C90B98L,0x286ED92CE57BD37L,0x1C416C4ABF57375L,0x39779D0B2EE2172L,0x1A1C0497A5D9487L,0x3995E3602L};
+const BIG_560_58 CURVE_Pxaab_BLS48= {0x271CDC5AC0A1BE1L,0x2A3F8EC01DF5FDCL,0xAD5478433972C5L,0x22B73FAE2491D8CL,0x30E75C6B40A11FAL,0xE960C8FF259C26L,0x8CE48632D18B04L,0x39549A6BC27F419L,0x274A97B58DB48B6L,0xA5080497L};
+const BIG_560_58 CURVE_Pxaba_BLS48= {0x23A724C770C5DC4L,0x2A592B776B3BCB6L,0x110934259BEC736L,0x18E2C5A649AB2A8L,0x2B84CB2C58CD55L,0x168195F91EE8B90L,0xF7D917CE233167L,0x2A38FB7729335BDL,0x36D71DDA78B689BL,0x2D4BFBE3DL};
+const BIG_560_58 CURVE_Pxabb_BLS48= {0xD629669A64B740L,0x47F52632481578L,0x40D7054323ADD1L,0x3F9F4CCCD789E1BL,0x1E3C73C41F4EEA7L,0x15E7D7A61968610L,0x1B4186B40590D3BL,0x19F3BA577306AAFL,0x12DFE5F23F63B1AL,0x24E102A76L};
+const BIG_560_58 CURVE_Pxbaa_BLS48= {0x1BB0C6172F1E01FL,0x30C4734D2C29802L,0x990FA39218788L,0xEEB80ED6AE2501L,0x34728852870C80BL,0x94841D1637D478L,0x21CBCE27C3AD4D4L,0xA29F9E111E6AD5L,0x18CF1447CC49D3L,0x37787BDFDL};
+const BIG_560_58 CURVE_Pxbab_BLS48= {0x30A38238637383DL,0x288094FE661F866L,0x135C51ED5D3D212L,0x3C39C57E8051F25L,0x164639D737D882FL,0x312AEC8AA8DB8FCL,0x3FE838885E54DA8L,0x2FC3978BA297414L,0x850556F014F91FL,0x20B6CE9E3L};
+const BIG_560_58 CURVE_Pxbba_BLS48= {0x1683DB3D711939CL,0x26F9475A69066BAL,0xBCDB572CF2F6C0L,0x128DC8902CE1323L,0x29B3233EF353D1CL,0x342402A46B7046L,0x3187D1A403D6070L,0x3E3466F9F23BA45L,0xD943BE2435A9CCL,0x2A08A9CE1L};
+const BIG_560_58 CURVE_Pxbbb_BLS48= {0x32D410A856F4899L,0x7147AE4A959750L,0x28AEA57990BC9BCL,0x2807F11E9E26DAL,0x282C5EBA71895E3L,0x2832162D9FEC5FFL,0x33479E30007597CL,0x227A376C26A4B00L,0x1C16F1567857A32L,0x37DD51E0FL};
+const BIG_560_58 CURVE_Pyaaa_BLS48= {0x2E097CFB4137844L,0x313B1927FD3CCDDL,0x1EB86FABC768851L,0x4156382E29C659L,0x3C10CC7CF8896E0L,0x22FC388FD1D539CL,0x2C3E202F56CDD39L,0x2E9645FB43E8C72L,0x93548FD8706190L,0x1D9BB42E1L};
+const BIG_560_58 CURVE_Pyaab_BLS48= {0x25E3248EDC83190L,0x2BAABD11AA26424L,0x161D23BAC418D32L,0x5B3258247CBFF7L,0xED295CADE03C1FL,0x3A84758C5C741A2L,0x3D207E205E02B9EL,0x86743E24EA6513L,0x1DAA8E268EFA1C4L,0x9E72CE4FL};
+const BIG_560_58 CURVE_Pyaba_BLS48= {0x1DC5FD041985C0DL,0x2350136864770FAL,0x3179A5F5483ACE9L,0x2C25AB1A171F32CL,0x397C4403E658341L,0xE7E1C2186E971L,0x15921F60B0A5F40L,0x46E9317635E008L,0x17EF1353F3140D6L,0x35166F259L};
+const BIG_560_58 CURVE_Pyabb_BLS48= {0x36FE0A8159D42F8L,0x290EBF4445895D7L,0x20273B0FE9E7F2BL,0x23A6E2FF0F3FD7DL,0x1F37678869E5006L,0x2CA2DB53C9ED8DL,0x4E4BFD902F51DEL,0x1FF8649F125B66L,0x382D89BED80731L,0x28383AAA8L};
+const BIG_560_58 CURVE_Pybaa_BLS48= {0xD512B39F38039FL,0x23BA255F3C68984L,0x390AA14058093CFL,0x1FF0B2F2FFA1622L,0x310C5CC5F2ABB75L,0x3D9016C9EB6A2C9L,0x1CF7EE268EC2F18L,0x338BBB12C36B65AL,0x1EEE591B8A1D1ABL,0xAC11927CL};
+const BIG_560_58 CURVE_Pybab_BLS48= {0x269E06F295F7865L,0x2FC1D5BA1CE9A0EL,0x3631F3F1DACADD7L,0x30CCF3581D3943L,0x3FBE3B902505BB0L,0x23C4A9D31B36A49L,0x2056135CA438576L,0x2B78046739984F4L,0x12C0AC57B6F180EL,0xC48CA65BL};
+const BIG_560_58 CURVE_Pybba_BLS48= {0x1D83A9F67CC1979L,0x12ABE71DD89E6F0L,0x247B1C21635FDA9L,0x92880950076209L,0x2ECF179E0D733D7L,0x20D2DFFB53841F9L,0x3441B1645BC9FE8L,0x3089222CE22EC9DL,0x3699AE4108C86C5L,0x320034967L};
+const BIG_560_58 CURVE_Pybbb_BLS48= {0xFC89562FC9F25BL,0xB13E01AE9AB5D3L,0x18E8F169C9D264FL,0x3A5828D76B24A13L,0x1E8FD9BCEF84D9AL,0x36D20E3DBFEE16AL,0x17D3B3DF1AB4C1CL,0xF190510390F005L,0x12640E61B9BF549L,0x283D84D97L};
+const BIG_560_58 CURVE_W_BLS48[2]= {{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}};
+const BIG_560_58 CURVE_SB_BLS48[2][2]= {{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}}};
+const BIG_560_58 CURVE_WB_BLS48[4]= {{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}};
+const BIG_560_58 CURVE_BB_BLS48[4][4]= {{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}}};
+
+
+#endif
\ No newline at end of file
diff --git a/version3/c/rom_curve_BN254.c b/version3/c/rom_curve_BN254.c
new file mode 100644
index 0000000..ea5073d
--- /dev/null
+++ b/version3/c/rom_curve_BN254.c
@@ -0,0 +1,80 @@
+#include "arch.h"
+#include "ecp_BN254.h"
+
+/* Curve BN254 - Pairing friendly BN curve */
+
+/* Nogami's fast curve */
+
+#if CHUNK==16
+
+const int CURVE_Cof_I_BN254= 1;
+const int CURVE_A_BN254= 0;
+const int CURVE_B_I_BN254= 2;
+const BIG_256_13 CURVE_B_BN254= {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG_256_13 CURVE_Order_BN254= {0xD,0x0,0x0,0x0,0xA10,0x8,0x0,0x0,0x1F80,0x1FFC,0x1,0x0,0x1800,0x1A26,0x6E8,0x0,0x0,0x412,0x8D9,0x4A};
+const BIG_256_13 CURVE_Gx_BN254= {0x12,0x0,0x0,0x0,0x1A70,0x9,0x0,0x0,0x100,0x309,0x2,0x0,0x1800,0x1A26,0x6E8,0x0,0x0,0x412,0x8D9,0x4A};
+const BIG_256_13 CURVE_Gy_BN254= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+
+const BIG_256_13 CURVE_Bnx_BN254= {0x1,0x0,0x0,0x0,0x408,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG_256_13 CURVE_Cof_BN254= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG_256_13 CURVE_Cru_BN254= {0x7,0x0,0x0,0x0,0xCD8,0x3,0x0,0x0,0x900,0x1248,0x0,0x0,0x400,0x19B1,0x126,0x0,0x0,0x0,0x0,0x0};
+const BIG_256_13 CURVE_Pxa_BN254= {0x1B2B,0x1F,0x932,0x1C84,0x191E,0x1F86,0x262,0x1769,0x48B,0x1523,0x1B6D,0x18C3,0x7E8,0x6C6,0x1FAE,0x16C5,0x119E,0x5DA,0x684,0xC};
+const BIG_256_13 CURVE_Pxb_BN254= {0xCF3,0x1EAA,0x1079,0x1869,0x10D8,0x25B,0x18DE,0xD75,0xD74,0x18FA,0xA96,0x1305,0x18C5,0x553,0xCC4,0xF06,0x1A73,0x17CD,0x5AA,0xA};
+const BIG_256_13 CURVE_Pya_BN254= {0xB9A,0xE69,0x1E24,0x1C0,0x119F,0x4DE,0x16F8,0x1CD7,0x1D0A,0x194D,0x88,0x1319,0x966,0x870,0xE6A,0x1268,0xBAF,0x1D03,0x625,0x4};
+const BIG_256_13 CURVE_Pyb_BN254= {0xE9B,0x19D6,0x1B1A,0x1A35,0x18A2,0x4AB,0x1CE7,0x1FFA,0x1006,0x1D84,0x34D,0xBE7,0x56F,0x16A2,0x1A3D,0x2A4,0x1C8B,0x1873,0xECA,0x1D};
+const BIG_256_13 CURVE_W_BN254[2]= {{0x3,0x0,0x0,0x0,0x40,0x1,0x0,0x0,0x180,0x30C,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x0,0x0,0x0,0x810,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+const BIG_256_13 CURVE_SB_BN254[2][2]= {{{0x4,0x0,0x0,0x0,0x850,0x1,0x0,0x0,0x180,0x30C,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x0,0x0,0x0,0x810,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x1,0x0,0x0,0x0,0x810,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xA,0x0,0x0,0x0,0x9D0,0x7,0x0,0x0,0x1E00,0x1CF0,0x1,0x0,0x1800,0x1A26,0x6E8,0x0,0x0,0x412,0x8D9,0x4A}}};
+const BIG_256_13 CURVE_WB_BN254[4]= {{0x0,0x0,0x0,0x0,0x408,0x0,0x0,0x0,0x80,0x104,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x5,0x0,0x0,0x0,0x14A8,0x2,0x0,0x0,0x700,0xE38,0x0,0x0,0x1800,0x1120,0xC4,0x0,0x0,0x0,0x0,0x0},{0x3,0x0,0x0,0x0,0xC58,0x1,0x0,0x0,0x380,0x71C,0x0,0x0,0xC00,0x890,0x62,0x0,0x0,0x0,0x0,0x0},{0x1,0x0,0x0,0x0,0xC18,0x0,0x0,0x0,0x80,0x104,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+const BIG_256_13 CURVE_BB_BN254[4][4]= {{{0xD,0x0,0x0,0x0,0x608,0x8,0x0,0x0,0x1F80,0x1FFC,0x1,0x0,0x1800,0x1A26,0x6E8,0x0,0x0,0x412,0x8D9,0x4A},{0xC,0x0,0x0,0x0,0x608,0x8,0x0,0x0,0x1F80,0x1FFC,0x1,0x0,0x1800,0x1A26,0x6E8,0x0,0x0,0x412,0x8D9,0x4A},{0xC,0x0,0x0,0x0,0x608,0x8,0x0,0x0,0x1F80,0x1FFC,0x1,0x0,0x1800,0x1A26,0x6E8,0x0,0x0,0x412,0x8D9,0x4A},{0x2,0x0,0x0,0x0,0x810,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x1,0x0,0x0,0x0,0x810,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xC,0x0,0x0,0x0,0x608,0x8,0x0,0x0,0x1F80,0x1FFC,0x1,0x0,0x1800,0x1A26,0x6E8,0x0,0x0,0x412,0x8D9,0x4A},{0xD,0x0,0x0,0x0,0x608,0x8,0x0,0x0,0x1F80,0x1FFC,0x1,0x0,0x1800,0x1A26,0x6E8,0x0,0x0,0x412,0x8D9,0x4A},{0xC,0x0,0x0,0x0,0x608,0x8,0x0,0x0,0x1F80,0x1FFC,0x1,0x0,0x1800,0x1A26,0x6E8,0x0,0x0,0x412,0x8D9,0x4A}},{{0x2,0x0,0x0,0x0,0x810,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x0,0x0,0x0,0x810,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x0,0x0,0x0,0x810,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x0,0x0,0x0,0x810,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x2,0x0,0x0,0x0,0x408,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x2,0x0,0x0,0x0,0x1020,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xA,0x0,0x0,0x0,0x200,0x8,0x0,0x0,0x1F80,0x1FFC,0x1,0x0,0x1800,0x1A26,0x6E8,0x0,0x0,0x412,0x8D9,0x4A},{0x2,0x0,0x0,0x0,0x408,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+
+
+#endif
+
+#if CHUNK==32
+
+const int CURVE_Cof_I_BN254= 1;
+const int CURVE_A_BN254= 0;
+const int CURVE_B_I_BN254= 2;
+const BIG_256_28 CURVE_B_BN254= {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG_256_28 CURVE_Order_BN254= {0xD,0x0,0x10A1,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2};
+const BIG_256_28 CURVE_Gx_BN254= {0x12,0x0,0x13A7,0x0,0x86121,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2};
+const BIG_256_28 CURVE_Gy_BN254= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+
+const BIG_256_28 CURVE_Bnx_BN254= {0x1,0x8000000,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG_256_28 CURVE_Cof_BN254= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG_256_28 CURVE_Cru_BN254= {0x7,0x8000000,0x6CD,0x0,0x24909,0x4000000,0x49B362,0x0,0x0,0x0};
+const BIG_256_28 CURVE_Pxa_BN254= {0x803FB2B,0xEE4224C,0x8BF0D91,0x8BBB489,0xDB6A464,0x7E8C61E,0xFEB8D8C,0x519EB62,0x61A10BB,0x0};
+const BIG_256_28 CURVE_Pxb_BN254= {0x7D54CF3,0x8C34C1E,0x784B70D,0x746BAE3,0xA5B1F4D,0x8C5982A,0x3310AA7,0xBA73783,0x516AAF9,0x0};
+const BIG_256_28 CURVE_Pya_BN254= {0x1CD2B9A,0xF0E0789,0xE09BD19,0xAE6BDB,0x22329BD,0x96698C8,0x39A90E0,0x6BAF934,0x21897A0,0x0};
+const BIG_256_28 CURVE_Pyb_BN254= {0xB3ACE9B,0x2D1AEC6,0x9C9578A,0x6FFD73,0xD37B090,0x56F5F38,0x68F6D44,0x7C8B152,0xEBB2B0E,0x0};
+const BIG_256_28 CURVE_W_BN254[2]= {{0x3,0x0,0x204,0x8000000,0x6181,0x0,0x0,0x0,0x0,0x0},{0x1,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+const BIG_256_28 CURVE_SB_BN254[2][2]= {{{0x4,0x0,0x285,0x8000000,0x6181,0x0,0x0,0x0,0x0,0x0},{0x1,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x1,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xA,0x0,0xE9D,0x0,0x79E1E,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2}}};
+const BIG_256_28 CURVE_WB_BN254[4]= {{0x0,0x8000000,0x40,0x8000000,0x2080,0x0,0x0,0x0,0x0,0x0},{0x5,0x8000000,0x54A,0x0,0x1C707,0x8000000,0x312241,0x0,0x0,0x0},{0x3,0x8000000,0x2C5,0x8000000,0xE383,0xC000000,0x189120,0x0,0x0,0x0},{0x1,0x8000000,0xC1,0x8000000,0x2080,0x0,0x0,0x0,0x0,0x0}};
+const BIG_256_28 CURVE_BB_BN254[4][4]= {{{0xD,0x8000000,0x1060,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2},{0xC,0x8000000,0x1060,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2},{0xC,0x8000000,0x1060,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2},{0x2,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x1,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xC,0x8000000,0x1060,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2},{0xD,0x8000000,0x1060,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2},{0xC,0x8000000,0x1060,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2}},{{0x2,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x2,0x8000000,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x2,0x0,0x102,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xA,0x0,0x1020,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2},{0x2,0x8000000,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+#endif
+
+#if CHUNK==64
+
+const int CURVE_Cof_I_BN254= 1;
+const int CURVE_A_BN254= 0;
+const int CURVE_B_I_BN254= 2;
+const BIG_256_56 CURVE_B_BN254= {0x2L,0x0L,0x0L,0x0L,0x0L};
+const BIG_256_56 CURVE_Order_BN254= {0xDL,0x800000000010A1L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L};
+const BIG_256_56 CURVE_Gx_BN254= {0x12L,0x13A7L,0x80000000086121L,0x40000001BA344DL,0x25236482L};
+const BIG_256_56 CURVE_Gy_BN254= {0x1L,0x0L,0x0L,0x0L,0x0L};
+
+const BIG_256_56 CURVE_Bnx_BN254= {0x80000000000001L,0x40L,0x0L,0x0L,0x0L};
+const BIG_256_56 CURVE_Cof_BN254= {0x1L,0x0L,0x0L,0x0L,0x0L};
+const BIG_256_56 CURVE_Cru_BN254= {0x80000000000007L,0x6CDL,0x40000000024909L,0x49B362L,0x0L};
+const BIG_256_56 CURVE_Pxa_BN254= {0xEE4224C803FB2BL,0x8BBB4898BF0D91L,0x7E8C61EDB6A464L,0x519EB62FEB8D8CL,0x61A10BBL};
+const BIG_256_56 CURVE_Pxb_BN254= {0x8C34C1E7D54CF3L,0x746BAE3784B70DL,0x8C5982AA5B1F4DL,0xBA737833310AA7L,0x516AAF9L};
+const BIG_256_56 CURVE_Pya_BN254= {0xF0E07891CD2B9AL,0xAE6BDBE09BD19L,0x96698C822329BDL,0x6BAF93439A90E0L,0x21897A0L};
+const BIG_256_56 CURVE_Pyb_BN254= {0x2D1AEC6B3ACE9BL,0x6FFD739C9578AL,0x56F5F38D37B090L,0x7C8B15268F6D44L,0xEBB2B0EL};
+const BIG_256_56 CURVE_W_BN254[2]= {{0x3L,0x80000000000204L,0x6181L,0x0L,0x0L},{0x1L,0x81L,0x0L,0x0L,0x0L}};
+const BIG_256_56 CURVE_SB_BN254[2][2]= {{{0x4L,0x80000000000285L,0x6181L,0x0L,0x0L},{0x1L,0x81L,0x0L,0x0L,0x0L}},{{0x1L,0x81L,0x0L,0x0L,0x0L},{0xAL,0xE9DL,0x80000000079E1EL,0x40000001BA344DL,0x25236482L}}};
+const BIG_256_56 CURVE_WB_BN254[4]= {{0x80000000000000L,0x80000000000040L,0x2080L,0x0L,0x0L},{0x80000000000005L,0x54AL,0x8000000001C707L,0x312241L,0x0L},{0x80000000000003L,0x800000000002C5L,0xC000000000E383L,0x189120L,0x0L},{0x80000000000001L,0x800000000000C1L,0x2080L,0x0L,0x0L}};
+const BIG_256_56 CURVE_BB_BN254[4][4]= {{{0x8000000000000DL,0x80000000001060L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L},{0x8000000000000CL,0x80000000001060L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L},{0x8000000000000CL,0x80000000001060L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L},{0x2L,0x81L,0x0L,0x0L,0x0L}},{{0x1L,0x81L,0x0L,0x0L,0x0L},{0x8000000000000CL,0x80000000001060L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L},{0x8000000000000DL,0x80000000001060L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L},{0x8000000000000CL,0x80000000001060L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L}},{{0x2L,0x81L,0x0L,0x0L,0x0L},{0x1L,0x81L,0x0L,0x0L,0x0L},{0x1L,0x81L,0x0L,0x0L,0x0L},{0x1L,0x81L,0x0L,0x0L,0x0L}},{{0x80000000000002L,0x40L,0x0L,0x0L,0x0L},{0x2L,0x102L,0x0L,0x0L,0x0L},{0xAL,0x80000000001020L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L},{0x80000000000002L,0x40L,0x0L,0x0L,0x0L}}};
+
+
+#endif
+
diff --git a/version3/c/rom_curve_BN254CX.c b/version3/c/rom_curve_BN254CX.c
new file mode 100644
index 0000000..4b85d21
--- /dev/null
+++ b/version3/c/rom_curve_BN254CX.c
@@ -0,0 +1,81 @@
+#include "arch.h"
+#include "ecp_BN254CX.h"
+
+/* Curve BN254CX - Pairing friendly BN curve */
+
+/* CertiVox BN curve/field  */
+
+
+#if CHUNK==16
+
+const int CURVE_Cof_I_BN254CX= 1;
+const int CURVE_A_BN254CX= 0;
+const int CURVE_B_I_BN254CX= 2;
+const BIG_256_13 CURVE_B_BN254CX= {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG_256_13 CURVE_Order_BN254CX= {0x1F6D,0x1758,0x98D,0x381,0xBE1,0x367,0x1324,0x1DC1,0x1FD6,0x1621,0x19B4,0x14C6,0x1647,0x1EEF,0x16C2,0x541,0x870,0x0,0x0,0x48};
+const BIG_256_13 CURVE_Gx_BN254CX= {0x15B2,0xDA,0x1BD7,0xC47,0x1BE6,0x1F70,0x24,0x1DC3,0x1FD6,0x1921,0x19B4,0x14C6,0x1647,0x1EEF,0x16C2,0x541,0x870,0x0,0x0,0x48};
+const BIG_256_13 CURVE_Gy_BN254CX= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG_256_13 CURVE_Bnx_BN254CX= {0x12B1,0x1E00,0x0,0x0,0x400,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG_256_13 CURVE_Cof_BN254CX= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG_256_13 CURVE_Cru_BN254CX= {0x1C97,0x11A,0x5E5,0x126,0x31E,0x3AB,0x7BE,0xC8E,0x1DDF,0x205,0xFC5,0x1950,0x0,0x0,0x120,0x0,0x0,0x0,0x0,0x0};
+
+const BIG_256_13 CURVE_Pxa_BN254CX= {0xC74,0x697,0x1BB9,0xA39,0xC08,0x1393,0xF8,0x17F4,0x1C85,0x1C83,0x12EE,0xB86,0x100F,0x592,0x18D6,0x164A,0x1053,0x963,0x1A0B,0x32};
+const BIG_256_13 CURVE_Pxb_BN254CX= {0xFE1,0x114E,0x2CB,0xB1D,0x147A,0x187,0x827,0x1618,0x1B97,0x1FC0,0x5D0,0x11D3,0x137A,0x8E4,0xA80,0x1EC9,0x1E19,0xF61,0x19AE,0x28};
+const BIG_256_13 CURVE_Pya_BN254CX= {0x9F,0x185F,0x1AF3,0x17F9,0x10CF,0xD9,0x11FB,0x7B0,0x1B3,0xB1B,0x1882,0x1B5D,0x157,0xF11,0x1760,0x571,0x1233,0xECB,0x1E7B,0x14};
+const BIG_256_13 CURVE_Pyb_BN254CX= {0xE9D,0x4C7,0x8A2,0x96,0x1ED9,0x16F5,0x74B,0x14AD,0x64E,0xE14,0xD18,0x1B1A,0x512,0x372,0xD7,0x1812,0xCC4,0x1CF,0x583,0xC};
+
+const BIG_256_13 CURVE_W_BN254CX[2]= {{0xB83,0x117F,0x1245,0x8C6,0x5,0x1C09,0xD00,0x1,0x0,0x300,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x561,0x1C01,0x1,0x0,0x800,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+const BIG_256_13 CURVE_SB_BN254CX[2][2]= {{{0x10E4,0xD80,0x1247,0x8C6,0x805,0x1C09,0xD00,0x1,0x0,0x300,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x561,0x1C01,0x1,0x0,0x800,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x561,0x1C01,0x1,0x0,0x800,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x13EA,0x5D9,0x1748,0x1ABA,0xBDB,0x75E,0x623,0x1DC0,0x1FD6,0x1321,0x19B4,0x14C6,0x1647,0x1EEF,0x16C2,0x541,0x870,0x0,0x0,0x48}}};
+const BIG_256_13 CURVE_WB_BN254CX[4]= {{0x4B0,0x13D4,0x615,0x1842,0x401,0x958,0xF00,0x0,0x0,0x100,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x475,0x1110,0x56F,0x1BF3,0x36C,0x1FCD,0x329,0x1DB5,0x1E94,0xE03,0xA83,0x10E0,0x0,0x0,0xC0,0x0,0x0,0x0,0x0,0x0},{0xB93,0x788,0x12B8,0xDF9,0x13B6,0x1FE6,0x1194,0xEDA,0x1F4A,0x1701,0x541,0x870,0x0,0x0,0x60,0x0,0x0,0x0,0x0,0x0},{0xA11,0xFD5,0x617,0x1842,0xC01,0x958,0xF00,0x0,0x0,0x100,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+const BIG_256_13 CURVE_BB_BN254CX[4][4]= {{{0xCBD,0x1958,0x98C,0x381,0x7E1,0x367,0x1324,0x1DC1,0x1FD6,0x1621,0x19B4,0x14C6,0x1647,0x1EEF,0x16C2,0x541,0x870,0x0,0x0,0x48},{0xCBC,0x1958,0x98C,0x381,0x7E1,0x367,0x1324,0x1DC1,0x1FD6,0x1621,0x19B4,0x14C6,0x1647,0x1EEF,0x16C2,0x541,0x870,0x0,0x0,0x48},{0xCBC,0x1958,0x98C,0x381,0x7E1,0x367,0x1324,0x1DC1,0x1FD6,0x1621,0x19B4,0x14C6,0x1647,0x1EEF,0x16C2,0x541,0x870,0x0,0x0,0x48},{0x562,0x1C01,0x1,0x0,0x800,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x561,0x1C01,0x1,0x0,0x800,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xCBC,0x1958,0x98C,0x381,0x7E1,0x367,0x1324,0x1DC1,0x1FD6,0x1621,0x19B4,0x14C6,0x1647,0x1EEF,0x16C2,0x541,0x870,0x0,0x0,0x48},{0xCBD,0x1958,0x98C,0x381,0x7E1,0x367,0x1324,0x1DC1,0x1FD6,0x1621,0x19B4,0x14C6,0x1647,0x1EEF,0x16C2,0x541,0x870,0x0,0x0,0x48},{0xCBC,0x1958,0x98C,0x381,0x7E1,0x367,0x1324,0x1DC1,0x1FD6,0x1621,0x19B4,0x14C6,0x1647,0x1EEF,0x16C2,0x541,0x870,0x0,0x0,0x48}},{{0x562,0x1C01,0x1,0x0,0x800,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x561,0x1C01,0x1,0x0,0x800,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x561,0x1C01,0x1,0x0,0x800,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x561,0x1C01,0x1,0x0,0x800,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x12B2,0x1E00,0x0,0x0,0x400,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xAC2,0x1802,0x3,0x0,0x1000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1A0A,0x1B57,0x98B,0x381,0x3E1,0x367,0x1324,0x1DC1,0x1FD6,0x1621,0x19B4,0x14C6,0x1647,0x1EEF,0x16C2,0x541,0x870,0x0,0x0,0x48},{0x12B2,0x1E00,0x0,0x0,0x400,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+#endif
+
+#if CHUNK==32
+
+const int CURVE_Cof_I_BN254CX= 1;
+const int CURVE_A_BN254CX= 0;
+const int CURVE_B_I_BN254CX= 2;
+const BIG_256_28 CURVE_B_BN254CX= {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG_256_28 CURVE_Order_BN254CX= {0x6EB1F6D,0x11C0A63,0x906CEBE,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2};
+const BIG_256_28 CURVE_Gx_BN254CX= {0xC1B55B2,0x6623EF5,0x93EE1BE,0xD6EE180,0x6D3243F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2};
+const BIG_256_28 CURVE_Gy_BN254CX= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG_256_28 CURVE_Bnx_BN254CX= {0x3C012B1,0x0,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG_256_28 CURVE_Cof_BN254CX= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG_256_28 CURVE_Cru_BN254CX= {0x4235C97,0xE093179,0xF875631,0xDF6471E,0xF1440BD,0xCA83,0x480000,0x0,0x0,0x0};
+
+const BIG_256_28 CURVE_Pxa_BN254CX= {0x4D2EC74,0x851CEEE,0xE2726C0,0x85BFA03,0xBBB907C,0xF5C34,0x6358B25,0x7053B25,0x9682D2C,0x1};
+const BIG_256_28 CURVE_Pxb_BN254CX= {0xE29CFE1,0xA58E8B2,0x9C30F47,0x97B0C20,0x743F81B,0x37A8E99,0xAA011C9,0x3E19F64,0x466B9EC,0x1};
+const BIG_256_28 CURVE_Pya_BN254CX= {0xF0BE09F,0xFBFCEBC,0xEC1B30C,0xB33D847,0x2096361,0x157DAEE,0xDD81E22,0x72332B8,0xA79EDD9,0x0};
+const BIG_256_28 CURVE_Pyb_BN254CX= {0x898EE9D,0x904B228,0x2EDEBED,0x4EA569D,0x461C286,0x512D8D3,0x35C6E4,0xECC4C09,0x6160C39,0x0};
+
+
+const BIG_256_28 CURVE_W_BN254CX[2]= {{0x62FEB83,0x5463491,0x381200,0xB4,0x6000,0x0,0x0,0x0,0x0,0x0},{0x7802561,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+const BIG_256_28 CURVE_SB_BN254CX[2][2]= {{{0xDB010E4,0x5463491,0x381280,0xB4,0x6000,0x0,0x0,0x0,0x0,0x0},{0x7802561,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x7802561,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xBB33EA,0xBD5D5D2,0x8CEBCBD,0xD6EE018,0x6D2643F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2}}};
+const BIG_256_28 CURVE_WB_BN254CX[4]= {{0x67A84B0,0x1C21185,0x12B040,0x3C,0x2000,0x0,0x0,0x0,0x0,0x0},{0xE220475,0xCDF995B,0xA7F9A36,0x94EDA8C,0xA0DC07E,0x8702,0x300000,0x0,0x0,0x0},{0xF10B93,0x66FCCAE,0x53FCD3B,0x4A76D46,0x506E03F,0x4381,0x180000,0x0,0x0,0x0},{0xDFAAA11,0x1C21185,0x12B0C0,0x3C,0x2000,0x0,0x0,0x0,0x0,0x0}};
+const BIG_256_28 CURVE_BB_BN254CX[4][4]= {{{0x32B0CBD,0x11C0A63,0x906CE7E,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2},{0x32B0CBC,0x11C0A63,0x906CE7E,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2},{0x32B0CBC,0x11C0A63,0x906CE7E,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2},{0x7802562,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x7802561,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x32B0CBC,0x11C0A63,0x906CE7E,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2},{0x32B0CBD,0x11C0A63,0x906CE7E,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2},{0x32B0CBC,0x11C0A63,0x906CE7E,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2}},{{0x7802562,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x7802561,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x7802561,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x7802561,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x3C012B2,0x0,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xF004AC2,0x0,0x100,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xF6AFA0A,0x11C0A62,0x906CE3E,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2},{0x3C012B2,0x0,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+#endif
+
+#if CHUNK==64
+
+const int CURVE_Cof_I_BN254CX= 1;
+const int CURVE_A_BN254CX= 1;
+const int CURVE_B_I_BN254CX= 2;
+const BIG_256_56 CURVE_B_BN254CX= {0x2L,0x0L,0x0L,0x0L,0x0L};
+const BIG_256_56 CURVE_Order_BN254CX= {0x11C0A636EB1F6DL,0xD6EE0CC906CEBEL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L};
+const BIG_256_56 CURVE_Gx_BN254CX= {0x6623EF5C1B55B2L,0xD6EE18093EE1BEL,0x647A6366D3243FL,0x8702A0DB0BDDFL,0x24000000L};
+const BIG_256_56 CURVE_Gy_BN254CX= {0x1L,0x0L,0x0L,0x0L,0x0L};
+const BIG_256_56 CURVE_Bnx_BN254CX= {0x3C012B1L,0x40L,0x0L,0x0L,0x0L};
+const BIG_256_56 CURVE_Cof_BN254CX= {0x1L,0x0L,0x0L,0x0L,0x0L};
+const BIG_256_56 CURVE_Cru_BN254CX= {0xE0931794235C97L,0xDF6471EF875631L,0xCA83F1440BDL,0x480000L,0x0L};
+
+const BIG_256_56 CURVE_Pxa_BN254CX= {0x851CEEE4D2EC74L,0x85BFA03E2726C0L,0xF5C34BBB907CL,0x7053B256358B25L,0x19682D2CL};
+const BIG_256_56 CURVE_Pxb_BN254CX= {0xA58E8B2E29CFE1L,0x97B0C209C30F47L,0x37A8E99743F81BL,0x3E19F64AA011C9L,0x1466B9ECL};
+const BIG_256_56 CURVE_Pya_BN254CX= {0xFBFCEBCF0BE09FL,0xB33D847EC1B30CL,0x157DAEE2096361L,0x72332B8DD81E22L,0xA79EDD9L};
+const BIG_256_56 CURVE_Pyb_BN254CX= {0x904B228898EE9DL,0x4EA569D2EDEBEDL,0x512D8D3461C286L,0xECC4C09035C6E4L,0x6160C39L};
+
+
+const BIG_256_56 CURVE_W_BN254CX[2]= {{0x546349162FEB83L,0xB40381200L,0x6000L,0x0L,0x0L},{0x7802561L,0x80L,0x0L,0x0L,0x0L}};
+const BIG_256_56 CURVE_SB_BN254CX[2][2]= {{{0x5463491DB010E4L,0xB40381280L,0x6000L,0x0L,0x0L},{0x7802561L,0x80L,0x0L,0x0L,0x0L}},{{0x7802561L,0x80L,0x0L,0x0L,0x0L},{0xBD5D5D20BB33EAL,0xD6EE0188CEBCBDL,0x647A6366D2643FL,0x8702A0DB0BDDFL,0x24000000L}}};
+const BIG_256_56 CURVE_WB_BN254CX[4]= {{0x1C2118567A84B0L,0x3C012B040L,0x2000L,0x0L,0x0L},{0xCDF995BE220475L,0x94EDA8CA7F9A36L,0x8702A0DC07EL,0x300000L,0x0L},{0x66FCCAE0F10B93L,0x4A76D4653FCD3BL,0x4381506E03FL,0x180000L,0x0L},{0x1C21185DFAAA11L,0x3C012B0C0L,0x2000L,0x0L,0x0L}};
+const BIG_256_56 CURVE_BB_BN254CX[4][4]= {{{0x11C0A6332B0CBDL,0xD6EE0CC906CE7EL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L},{0x11C0A6332B0CBCL,0xD6EE0CC906CE7EL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L},{0x11C0A6332B0CBCL,0xD6EE0CC906CE7EL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L},{0x7802562L,0x80L,0x0L,0x0L,0x0L}},{{0x7802561L,0x80L,0x0L,0x0L,0x0L},{0x11C0A6332B0CBCL,0xD6EE0CC906CE7EL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L},{0x11C0A6332B0CBDL,0xD6EE0CC906CE7EL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L},{0x11C0A6332B0CBCL,0xD6EE0CC906CE7EL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L}},{{0x7802562L,0x80L,0x0L,0x0L,0x0L},{0x7802561L,0x80L,0x0L,0x0L,0x0L},{0x7802561L,0x80L,0x0L,0x0L,0x0L},{0x7802561L,0x80L,0x0L,0x0L,0x0L}},{{0x3C012B2L,0x40L,0x0L,0x0L,0x0L},{0xF004AC2L,0x100L,0x0L,0x0L,0x0L},{0x11C0A62F6AFA0AL,0xD6EE0CC906CE3EL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L},{0x3C012B2L,0x40L,0x0L,0x0L,0x0L}}};
+#endif
diff --git a/version3/c/rom_curve_BRAINPOOL.c b/version3/c/rom_curve_BRAINPOOL.c
new file mode 100644
index 0000000..ef8bea7
--- /dev/null
+++ b/version3/c/rom_curve_BRAINPOOL.c
@@ -0,0 +1,36 @@
+#include "arch.h"
+#include "ecp_BRAINPOOL.h"
+
+/* Brainpool Curve  */
+/* Note that the original curve has been transformed to an isomorphic curve with A=-3 */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+const int CURVE_Cof_I_BRAINPOOL= 1;
+const BIG_256_28 CURVE_Cof_BRAINPOOL= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const int CURVE_A_BRAINPOOL= -3;
+const int CURVE_B_I_BRAINPOOL= 0;
+const BIG_256_28 CURVE_B_BRAINPOOL= {0xEE92B04,0xE58101F,0xF49256A,0xEBC4AF2,0x6B7BF93,0x733D0B7,0x4FE66A7,0x30D84EA,0x62C61C4,0x6};
+const BIG_256_28 CURVE_Order_BRAINPOOL= {0x74856A7,0x1E0E829,0x1A6F790,0x7AA3B56,0xD718C39,0x909D838,0xC3E660A,0xA1EEA9B,0x9FB57DB,0xA};
+const BIG_256_28 CURVE_Gx_BRAINPOOL= {0xE1305F4,0xA191562,0xFBC2B79,0x42C47AA,0x149AFA1,0xB23A656,0x7732213,0xC1CFE7B,0x3E8EB3C,0xA};
+const BIG_256_28 CURVE_Gy_BRAINPOOL= {0xB25C9BE,0xABE8F35,0x27001D,0xB6DE39D,0x17E69BC,0xE146444,0xD7F7B22,0x3439C56,0xD996C82,0x2};
+#endif
+
+#if CHUNK==64
+
+const int CURVE_Cof_I_BRAINPOOL= 1;
+const BIG_256_56 CURVE_Cof_BRAINPOOL= {0x1L,0x0L,0x0L,0x0L,0x0L};
+const int CURVE_A_BRAINPOOL= -3;
+const int CURVE_B_I_BRAINPOOL= 0;
+const BIG_256_56 CURVE_B_BRAINPOOL= {0xE58101FEE92B04L,0xEBC4AF2F49256AL,0x733D0B76B7BF93L,0x30D84EA4FE66A7L,0x662C61C4L};
+const BIG_256_56 CURVE_Order_BRAINPOOL= {0x1E0E82974856A7L,0x7AA3B561A6F790L,0x909D838D718C39L,0xA1EEA9BC3E660AL,0xA9FB57DBL};
+const BIG_256_56 CURVE_Gx_BRAINPOOL= {0xA191562E1305F4L,0x42C47AAFBC2B79L,0xB23A656149AFA1L,0xC1CFE7B7732213L,0xA3E8EB3CL};
+const BIG_256_56 CURVE_Gy_BRAINPOOL= {0xABE8F35B25C9BEL,0xB6DE39D027001DL,0xE14644417E69BCL,0x3439C56D7F7B22L,0x2D996C82L};
+#endif
+
diff --git a/version3/c/rom_curve_C25519.c b/version3/c/rom_curve_C25519.c
new file mode 100644
index 0000000..1841bd6
--- /dev/null
+++ b/version3/c/rom_curve_C25519.c
@@ -0,0 +1,27 @@
+#include "arch.h"
+#include "ecp_C25519.h"
+
+/* Curve 25519 */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+const int CURVE_Cof_I_C25519=8;
+const BIG_256_29 CURVE_Cof_C25519= {0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const int CURVE_A_C25519=486662;
+const BIG_256_29 CURVE_Order_C25519= {0x1CF5D3ED,0x9318D2,0x1DE73596,0x1DF3BD45,0x14D,0x0,0x0,0x0,0x100000};
+const BIG_256_29 CURVE_Gx_C25519= {0x9};
+#endif
+
+#if CHUNK==64
+const int CURVE_Cof_I_C25519=8;
+const BIG_256_56 CURVE_Cof_C25519= {0x8,0x0,0x0,0x0,0x0};
+const int CURVE_A_C25519=486662;
+const BIG_256_56 CURVE_Order_C25519= {0x12631A5CF5D3ED,0xF9DEA2F79CD658,0x14DE,0x0,0x10000000};
+const BIG_256_56 CURVE_Gx_C25519= {0x9};
+#endif
+
diff --git a/version3/c/rom_curve_C41417.c b/version3/c/rom_curve_C41417.c
new file mode 100644
index 0000000..457a433
--- /dev/null
+++ b/version3/c/rom_curve_C41417.c
@@ -0,0 +1,35 @@
+#include "arch.h"
+#include "ecp_C41417.h"
+
+/* Curve C41417 */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+const int CURVE_Cof_I_C41417= 8;
+const BIG_416_29 CURVE_Cof_C41417= {0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const int CURVE_A_C41417= 1;
+const int CURVE_B_I_C41417= 3617;
+const BIG_416_29 CURVE_B_C41417= {0xE21,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG_416_29 CURVE_Order_C41417= {0x106AF79,0x18738D2F,0x18F3C606,0x1806715A,0x22B36F1,0xA67B830,0xCF32490,0x1FFFFFFD,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1F};
+const BIG_416_29 CURVE_Gx_C41417= {0x13CBC595,0x7E9C097,0x14DF1931,0x14E7F550,0x1A111301,0x15A6B6B5,0xD526292,0x18FEAFFE,0x1F44C03E,0x1E6A31B4,0x70C9B97,0x43180C6,0x1443300,0x19A4828A,0x68};
+const BIG_416_29 CURVE_Gy_C41417= {0x22,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+#endif
+
+#if CHUNK==64
+
+const int CURVE_Cof_I_C41417= 8;
+const BIG_416_60 CURVE_Cof_C41417= {0x8L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const int CURVE_A_C41417= 1;
+const int CURVE_B_I_C41417= 3617;
+const BIG_416_60 CURVE_B_C41417= {0xE21L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG_416_60 CURVE_Order_C41417= {0xB0E71A5E106AF79L,0x1C0338AD63CF181L,0x414CF706022B36FL,0xFFFFFFFFEB3CC92L,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0x7FFFFFFFFFFFFL};
+const BIG_416_60 CURVE_Gx_C41417= {0x4FD3812F3CBC595L,0x1A73FAA8537C64CL,0x4AB4D6D6BA11130L,0x3EC7F57FF35498AL,0xE5FCD46369F44C0L,0x300218C0631C326L,0x1A334905141443L};
+const BIG_416_60 CURVE_Gy_C41417= {0x22L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+#endif
+
diff --git a/version3/c/rom_curve_ED25519.c b/version3/c/rom_curve_ED25519.c
new file mode 100644
index 0000000..9cda673
--- /dev/null
+++ b/version3/c/rom_curve_ED25519.c
@@ -0,0 +1,45 @@
+#include "arch.h"
+#include "ecp_ED25519.h"
+
+/* ED25519 */
+
+#if CHUNK==16
+/* Ed25519 Curve */
+
+const int CURVE_Cof_I_ED25519= 8;
+const BIG_256_13 CURVE_Cof_ED25519= {0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const int CURVE_A_ED25519= -1;
+const int CURVE_B_I_ED25519= 0;
+const BIG_256_13 CURVE_B_ED25519= {0x18A3,0x1ACB,0x1284,0x169B,0x175E,0xC55,0x507,0x9A8,0x100A,0x3,0x1A26,0xEF3,0x797,0x3A0,0xE33,0x1FCE,0xB6F,0x771,0xDB,0xA4};
+const BIG_256_13 CURVE_Order_ED25519= {0x13ED,0x7AE,0x697,0x4C6,0x581,0xE6B,0xBDE,0x1BD4,0x1EF9,0xA6,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20};
+const BIG_256_13 CURVE_Gx_ED25519= {0x151A,0x192E,0x1823,0xC5A,0xC95,0x13D9,0x1496,0xC12,0xCC7,0x349,0x1717,0x1BAD,0x31F,0x1271,0x1B02,0xA7F,0xD6E,0x169E,0x1A4D,0x42};
+const BIG_256_13 CURVE_Gy_ED25519= {0x658,0x1333,0x1999,0xCCC,0x666,0x1333,0x1999,0xCCC,0x666,0x1333,0x1999,0xCCC,0x666,0x1333,0x1999,0xCCC,0x666,0x1333,0x1999,0xCC};
+#endif
+
+#if CHUNK==32
+
+const int CURVE_Cof_I_ED25519= 8;
+const BIG_256_29 CURVE_Cof_ED25519= {0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const int CURVE_A_ED25519= -1;
+const int CURVE_B_I_ED25519= 0;
+const BIG_256_29 CURVE_B_ED25519= {0x135978A3,0xF5A6E50,0x10762ADD,0x149A82,0x1E898007,0x3CBBBC,0x19CE331D,0x1DC56DFF,0x52036C};
+const BIG_256_29 CURVE_Order_ED25519= {0x1CF5D3ED,0x9318D2,0x1DE73596,0x1DF3BD45,0x14D,0x0,0x0,0x0,0x100000};
+const BIG_256_29 CURVE_Gx_ED25519= {0xF25D51A,0xAB16B04,0x969ECB2,0x198EC12A,0xDC5C692,0x1118FEEB,0xFFB0293,0x1A79ADCA,0x216936};
+const BIG_256_29 CURVE_Gy_ED25519= {0x6666658,0x13333333,0x19999999,0xCCCCCCC,0x6666666,0x13333333,0x19999999,0xCCCCCCC,0x666666};
+
+
+#endif
+
+#if CHUNK==64
+
+const int CURVE_Cof_I_ED25519= 8;
+const BIG_256_56 CURVE_Cof_ED25519= {0x8L,0x0L,0x0L,0x0L,0x0L};
+const int CURVE_A_ED25519= -1;
+const int CURVE_B_I_ED25519= 0;
+const BIG_256_56 CURVE_B_ED25519= {0xEB4DCA135978A3L,0xA4D4141D8AB75L,0x797779E8980070L,0x2B6FFE738CC740L,0x52036CEEL};
+const BIG_256_56 CURVE_Order_ED25519= {0x12631A5CF5D3EDL,0xF9DEA2F79CD658L,0x14DEL,0x0L,0x10000000L};
+const BIG_256_56 CURVE_Gx_ED25519= {0x562D608F25D51AL,0xC7609525A7B2C9L,0x31FDD6DC5C692CL,0xCD6E53FEC0A4E2L,0x216936D3L};
+const BIG_256_56 CURVE_Gy_ED25519= {0x66666666666658L,0x66666666666666L,0x66666666666666L,0x66666666666666L,0x66666666L};
+
+#endif
+
diff --git a/version3/c/rom_curve_FP256BN.c b/version3/c/rom_curve_FP256BN.c
new file mode 100644
index 0000000..cf55157
--- /dev/null
+++ b/version3/c/rom_curve_FP256BN.c
@@ -0,0 +1,86 @@
+#include "arch.h"
+#include "ecp_FP256BN.h"
+
+/* Curve FP256BN - Pairing friendly BN curve */
+
+/* ISO curve */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+const int CURVE_Cof_I_FP256BN= 1;
+const int CURVE_A_FP256BN= 0;
+const int CURVE_B_I_FP256BN= 3;
+const BIG_256_28 CURVE_B_FP256BN= {0x3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG_256_28 CURVE_Order_FP256BN= {0x10B500D,0x2D536CD,0x9921AF6,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF};
+const BIG_256_28 CURVE_Gx_FP256BN= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG_256_28 CURVE_Gy_FP256BN= {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+
+const BIG_256_28 CURVE_Bnx_FP256BN= {0xB0A801,0x82F5C03,0x68,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG_256_28 CURVE_Cof_FP256BN= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG_256_28 CURVE_Cru_FP256BN= {0x3A1B807,0x1C0A24A,0x32D1EDB,0xD79DF19,0x8659BCD,0x4092101,0x13988E1,0x0,0x0,0x0};
+const BIG_256_28 CURVE_Pxa_FP256BN= {0x9C09EFB,0x2616B68,0xF843CD2,0x539A12B,0x13ACE1C,0x577C289,0x28560F,0xB4C96C2,0xE0C3350,0xF};
+const BIG_256_28 CURVE_Pxb_FP256BN= {0x37E6A2B,0x69ED34A,0x3589D2,0x78E287D,0x3B924DD,0xC637D81,0x4DB5AE1,0x738AC05,0xEA66057,0x4};
+const BIG_256_28 CURVE_Pya_FP256BN= {0xEDC27FF,0x9B481B,0x15848E9,0x24758D6,0xE51EFCB,0x75124E3,0x376770D,0xC542A3B,0x2046E7,0x7};
+const BIG_256_28 CURVE_Pyb_FP256BN= {0xAAD049B,0x1281114,0xA98B3E0,0xBE80821,0x29F8B4C,0x49297EB,0x42EEA6,0xD388C29,0x554E3BC,0x0};
+const BIG_256_28 CURVE_W_FP256BN[2]= {{0xB054003,0xF0036E1,0xE78663A,0xFFFFFFF,0xFFFF,0x0,0x0,0x0,0x0,0x0},{0x1615001,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+const BIG_256_28 CURVE_SB_FP256BN[2][2]= {{{0xC669004,0xF5EEEE7,0xE78670B,0xFFFFFFF,0xFFFF,0x0,0x0,0x0,0x0,0x0},{0x1615001,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x1615001,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x606100A,0x3D4FFEB,0xB19B4BB,0x65FB129,0x49D0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF}}};
+const BIG_256_28 CURVE_WB_FP256BN[4]= {{0xD30A800,0x20678F0,0x4D2CC10,0x5555555,0x5555,0x0,0x0,0x0,0x0,0x0},{0xD7DC805,0xD6764C0,0xBC3AD1A,0x8FBEA10,0x4467DE,0x8061601,0xD105EB,0x0,0x0,0x0},{0xF173803,0xACB6061,0x5E1D6C1,0x47DF508,0x82233EF,0xC030B00,0x6882F5,0x0,0x0,0x0},{0xE91F801,0x26530F6,0x4D2CCE1,0x5555555,0x5555,0x0,0x0,0x0,0x0,0x0}};
+const BIG_256_28 CURVE_BB_FP256BN[4][4]= {{{0x5AA80D,0xAA5DACA,0x9921A8D,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF},
+        {0x5AA80C,0xAA5DACA,0x9921A8D,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF},
+        {0x5AA80C,0xAA5DACA,0x9921A8D,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF},
+        {0x1615002,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+    },
+    {   {0x1615001,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
+        {0x5AA80C,0xAA5DACA,0x9921A8D,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF},
+        {0x5AA80D,0xAA5DACA,0x9921A8D,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF},
+        {0x5AA80C,0xAA5DACA,0x9921A8D,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF}
+    },
+    {   {0x1615002,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
+        {0x1615001,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
+        {0x1615001,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
+        {0x1615001,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+    },
+    {   {0xB0A802,0x82F5C03,0x68,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
+        {0x2C2A002,0xBD700C,0x1A2,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
+        {0xFAA000A,0x2767EC6,0x9921A25,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF},
+        {0xB0A802,0x82F5C03,0x68,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+    }
+};
+
+
+
+
+#endif
+
+#if CHUNK==64
+
+const int CURVE_Cof_I_FP256BN= 1;
+const int CURVE_A_FP256BN= 0;
+const int CURVE_B_I_FP256BN= 3;
+const BIG_256_56 CURVE_B_FP256BN= {0x3L,0x0L,0x0L,0x0L,0x0L};
+const BIG_256_56 CURVE_Order_FP256BN= {0x2D536CD10B500DL,0x65FB1299921AF6L,0x5EEE71A49E0CDCL,0xFFFCF0CD46E5F2L,0xFFFFFFFFL};
+const BIG_256_56 CURVE_Gx_FP256BN= {0x1L,0x0L,0x0L,0x0L,0x0L};
+const BIG_256_56 CURVE_Gy_FP256BN= {0x2L,0x0L,0x0L,0x0L,0x0L};
+
+const BIG_256_56 CURVE_Bnx_FP256BN= {0x82F5C030B0A801L,0x68L,0x0L,0x0L,0x0L};
+const BIG_256_56 CURVE_Cof_FP256BN= {0x1L,0x0L,0x0L,0x0L,0x0L};
+const BIG_256_56 CURVE_Cru_FP256BN= {0x1C0A24A3A1B807L,0xD79DF1932D1EDBL,0x40921018659BCDL,0x13988E1L,0x0L};
+const BIG_256_56 CURVE_Pxa_FP256BN= {0x2616B689C09EFBL,0x539A12BF843CD2L,0x577C28913ACE1CL,0xB4C96C2028560FL,0xFE0C3350L};
+const BIG_256_56 CURVE_Pxb_FP256BN= {0x69ED34A37E6A2BL,0x78E287D03589D2L,0xC637D813B924DDL,0x738AC054DB5AE1L,0x4EA66057L};
+const BIG_256_56 CURVE_Pya_FP256BN= {0x9B481BEDC27FFL,0x24758D615848E9L,0x75124E3E51EFCBL,0xC542A3B376770DL,0x702046E7L};
+const BIG_256_56 CURVE_Pyb_FP256BN= {0x1281114AAD049BL,0xBE80821A98B3E0L,0x49297EB29F8B4CL,0xD388C29042EEA6L,0x554E3BCL};
+const BIG_256_56 CURVE_W_FP256BN[2]= {{0xF0036E1B054003L,0xFFFFFFFE78663AL,0xFFFFL,0x0L,0x0L},{0x5EB8061615001L,0xD1L,0x0L,0x0L,0x0L}};
+const BIG_256_56 CURVE_SB_FP256BN[2][2]= {{{0xF5EEEE7C669004L,0xFFFFFFFE78670BL,0xFFFFL,0x0L,0x0L},{0x5EB8061615001L,0xD1L,0x0L,0x0L,0x0L}},{{0x5EB8061615001L,0xD1L,0x0L,0x0L,0x0L},{0x3D4FFEB606100AL,0x65FB129B19B4BBL,0x5EEE71A49D0CDCL,0xFFFCF0CD46E5F2L,0xFFFFFFFFL}}};
+const BIG_256_56 CURVE_WB_FP256BN[4]= {{0x20678F0D30A800L,0x55555554D2CC10L,0x5555L,0x0L,0x0L},{0xD6764C0D7DC805L,0x8FBEA10BC3AD1AL,0x806160104467DEL,0xD105EBL,0x0L},{0xACB6061F173803L,0x47DF5085E1D6C1L,0xC030B0082233EFL,0x6882F5L,0x0L},{0x26530F6E91F801L,0x55555554D2CCE1L,0x5555L,0x0L,0x0L}};
+const BIG_256_56 CURVE_BB_FP256BN[4][4]= {{{0xAA5DACA05AA80DL,0x65FB1299921A8DL,0x5EEE71A49E0CDCL,0xFFFCF0CD46E5F2L,0xFFFFFFFFL},{0xAA5DACA05AA80CL,0x65FB1299921A8DL,0x5EEE71A49E0CDCL,0xFFFCF0CD46E5F2L,0xFFFFFFFFL},{0xAA5DACA05AA80CL,0x65FB1299921A8DL,0x5EEE71A49E0CDCL,0xFFFCF0CD46E5F2L,0xFFFFFFFFL},{0x5EB8061615002L,0xD1L,0x0L,0x0L,0x0L}},{{0x5EB8061615001L,0xD1L,0x0L,0x0L,0x0L},{0xAA5DACA05AA80CL,0x65FB1299921A8DL,0x5EEE71A49E0CDCL,0xFFFCF0CD46E5F2L,0xFFFFFFFFL},{0xAA5DACA05AA80DL,0x65FB1299921A8DL,0x5EEE71A49E0CDCL,0xFFFCF0CD46E5F2L,0xFFFFFFFFL},{0xAA5DACA05AA80CL,0x65FB1299921A8DL,0x5EEE71A49E0CDCL,0xFFFCF0CD46E5F2L,0xFFFFFFFFL}},{{0x5EB8061615002L,0xD1L,0x0L,0x0L,0x0L},{0x5EB8061615001L,0xD1L,0x0L,0x0L,0x0L},{0x5EB8061615001L,0xD1L,0x0L,0x0L,0x0L},{0x5EB8061615001L,0xD1L,0x0L,0x0L,0x0L}},{{0x82F5C030B0A802L,0x68L,0x0L,0x0L,0x0L},{0xBD700C2C2A002L,0x1A2L,0x0L,0x0L,0x0L},{0x2767EC6FAA000AL,0x65FB1299921A25L,0x5EEE71A49E0CDCL,0xFFFCF0CD46E5F2L,0xFFFFFFFFL},{0x82F5C030B0A802L,0x68L,0x0L,0x0L,0x0L}}};
+
+
+
+#endif
+
diff --git a/version3/c/rom_curve_FP512BN.c b/version3/c/rom_curve_FP512BN.c
new file mode 100644
index 0000000..fa29e20
--- /dev/null
+++ b/version3/c/rom_curve_FP512BN.c
@@ -0,0 +1,87 @@
+#include "arch.h"
+#include "ecp_FP512BN.h"
+
+/* Curve FP512BN - Pairing friendly BN curve */
+
+/* ISO curve */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+const int CURVE_Cof_I_FP512BN= 1;
+const int CURVE_A_FP512BN= 0;
+const int CURVE_B_I_FP512BN= 3;
+const BIG_512_29 CURVE_B_FP512BN= {0x3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG_512_29 CURVE_Order_FP512BN= {0x119A09ED,0x153252FA,0x1E68AD01,0x627C09,0x79A34A1,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF};
+const BIG_512_29 CURVE_Gx_FP512BN= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG_512_29 CURVE_Gy_FP512BN= {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+
+const BIG_512_29 CURVE_Bnx_FP512BN= {0x1E1BD80F,0x59835DA,0xC3DFC04,0x5EB8061,0x688,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG_512_29 CURVE_Cof_FP512BN= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+
+const BIG_512_29 CURVE_Cru_FP512BN= {0x1C79298A,0x1838B104,0x2C5F052,0x1DCCF337,0x6092AEC,0x4B35F29,0x1EB361E,0x11384EA,0x3074B20,0x17BB08FD,0x3A8B3E3,0xD70D66F,0x3D2A614,0x1CF63EE4,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF};
+
+const BIG_512_29 CURVE_Pxa_FP512BN= {0xDB646B5,0x183D4B70,0x1CBFFA3,0x11F0E632,0x1C78F221,0x1F10DE5D,0x171B715E,0xF0C6A29,0x10B02453,0xBE63C66,0xE6D5F69,0x166B1E1B,0x4BBBD29,0x179E750F,0x6E9D04,0xC912B10,0x1339E138,0x1D8B2};
+const BIG_512_29 CURVE_Pxb_FP512BN= {0x1A8AE0E9,0xDAE5F7E,0x22446CF,0x1948239B,0x15ADCE40,0xB709C1E,0x18357943,0xE50AA4D,0x19781E22,0x12B35CA6,0x11DAA2C0,0x18D8DDE4,0x5EA656D,0x15F45A41,0xD311A02,0xCFCD913,0x13CBF850,0x240E0};
+const BIG_512_29 CURVE_Pya_FP512BN= {0xDDE67A1,0x12401895,0x17BEE178,0x142F5AC2,0xB7BC5CD,0x92A1404,0x1A3B748C,0x17BD82A7,0x14B6CD18,0xAC34CE,0x1740FB97,0x1ECC15F9,0x17085B1D,0x1D1BA793,0x1BD6AC32,0x18F70525,0xC84C827,0x3780F};
+const BIG_512_29 CURVE_Pyb_FP512BN= {0x84F8E8B,0xC5B8C36,0xFDD85A1,0xB84449,0x19C08DFF,0x56BF713,0x1C5290C4,0x187C5CA0,0x1DA2897F,0x24B0CA0,0x326D8F4,0x2310CF6,0x1021438C,0xFBAEC8F,0xD9030C5,0x1CF06358,0x1CEC8B04,0x28D1D};
+const BIG_512_29 CURVE_W_FP512BN[2]= {{0x9834583,0x887C4BA,0x5A85CFC,0xBF7223A,0xF63FE96,0x1FFFFFFE,0x1FFFFFFF,0x1FFFFFFF,0xFFFFFF,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1C37B01F,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+const BIG_512_29 CURVE_SB_FP512BN[2][2]= {{{0xD4B9564,0x1D575904,0xD2C64F3,0x202177,0xF63F186,0x1FFFFFFE,0x1FFFFFFF,0x1FFFFFFF,0xFFFFFF,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x156259CE,0xA01E744,0x5ECB4F9,0x148B7B47,0x79A2790,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF}},{{0x1C37B01F,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x9834583,0x887C4BA,0x5A85CFC,0xBF7223A,0xF63FE96,0x1FFFFFFE,0x1FFFFFFF,0x1FFFFFFF,0xFFFFFF,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+const BIG_512_29 CURVE_WB_FP512BN[4]= {{0x155A29F0,0x16D59B55,0xF4C305,0x18858C0B,0x5215FBF,0xAAAAAAA,0x15555555,0xAAAAAAA,0x555555,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x2355D4B,0x1758095D,0x1FE13C5F,0x41F83FA,0xBB5E5CF,0x97D4EF1,0xB503D62,0x172C0C9B,0x16315274,0x15E1A9A8,0x859835D,0x2C3DFC0,0x105EB806,0x68,0x0,0x0,0x0,0x0},{0x289AAD,0x1E781F9C,0x60F9C31,0x1505822E,0x15DAF62B,0x4BEA778,0x15A81EB1,0xB96064D,0xB18A93A,0x1AF0D4D4,0x42CC1AE,0x161EFE0,0x82F5C03,0x34,0x0,0x0,0x0,0x0},{0x192279D1,0xBA52F9F,0x878CAFD,0xCAE8B48,0x52152AF,0xAAAAAAA,0x15555555,0xAAAAAAA,0x555555,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+const BIG_512_29 CURVE_BB_FP512BN[4][4]= {{{0x1E1BD810,0x59835DA,0xC3DFC04,0x5EB8061,0x688,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
+        {0x1E1BD80F,0x59835DA,0xC3DFC04,0x5EB8061,0x688,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
+        {0x1E1BD80F,0x59835DA,0xC3DFC04,0x5EB8061,0x688,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
+        {0x156259CF,0xA01E744,0x5ECB4F9,0x148B7B47,0x79A2790,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF}
+    },
+    {   {0x1C37B01F,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
+        {0x137E31DE,0xF9A1D1F,0x122AB0FD,0x1A76FBA8,0x79A2E18,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF},
+        {0x137E31DD,0xF9A1D1F,0x122AB0FD,0x1A76FBA8,0x79A2E18,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF},
+        {0x137E31DE,0xF9A1D1F,0x122AB0FD,0x1A76FBA8,0x79A2E18,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF}
+    },
+    {   {0x1C37B01E,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
+        {0x1C37B01F,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
+        {0x1C37B01F,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
+        {0x1C37B01F,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+    },
+    {   {0x137E31DF,0xF9A1D1F,0x122AB0FD,0x1A76FBA8,0x79A2E18,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF},
+        {0x192AA9AF,0x1ED17B8E,0xD70BCF0,0x8B47A84,0x79A1A80,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF},
+        {0x1C37B01D,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
+        {0x137E31DF,0xF9A1D1F,0x122AB0FD,0x1A76FBA8,0x79A2E18,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF}
+    }
+};
+
+
+#endif
+
+#if CHUNK==64
+
+const int CURVE_Cof_I_FP512BN= 1;
+const int CURVE_A_FP512BN= 0;
+const int CURVE_B_I_FP512BN= 3;
+const BIG_512_60 CURVE_B_FP512BN= {0x3L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG_512_60 CURVE_Order_FP512BN= {0x6A64A5F519A09EDL,0x10313E04F9A2B40L,0xC65DEAB2679A34AL,0xCF1EACBE98B8E48L,0x3C111B0EF445146L,0xA1D8CB5307C0BBEL,0xFFFF9EC7F01C60BL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFL};
+const BIG_512_60 CURVE_Gx_FP512BN= {0x1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG_512_60 CURVE_Gy_FP512BN= {0x2L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+
+const BIG_512_60 CURVE_Bnx_FP512BN= {0xB306BB5E1BD80FL,0x82F5C030B0F7F01L,0x68L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG_512_60 CURVE_Cof_FP512BN= {0x1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+
+const BIG_512_60 CURVE_Cru_FP512BN= {0xB0716209C79298AL,0xCEE6799B8B17C14L,0x78966BE526092AEL,0x20089C27507ACD8L,0xF8EF7611FA3074BL,0x6146B86B378EA2CL,0xFFFF9EC7DC83D2AL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFL};
+
+const BIG_512_60 CURVE_Pxa_FP512BN= {0xF07A96E0DB646B5L,0x18F87319072FFE8L,0x7BE21BCBBC78F22L,0x537863514DC6DC5L,0xDA57CC78CD0B024L,0xD29B358F0DB9B57L,0x7412F3CEA1E4BBBL,0xE138648958801BAL,0x3B165339L};
+const BIG_512_60 CURVE_Pxb_FP512BN= {0xDB5CBEFDA8AE0E9L,0xCA411CD88911B3L,0xD6E1383D5ADCE4L,0x227285526E0D5E5L,0xB02566B94D9781EL,0x56DC6C6EF2476A8L,0x680ABE8B4825EA6L,0xF85067E6C89B4C4L,0x481C13CBL};
+const BIG_512_60 CURVE_Pya_FP512BN= {0x2480312ADDE67A1L,0xDA17AD615EFB85EL,0x312542808B7BC5CL,0x18BDEC153E8EDD2L,0xE5C158699D4B6CDL,0xB1DF660AFCDD03EL,0xB0CBA374F277085L,0xC827C7B8292EF5AL,0x6F01EC84L};
+const BIG_512_60 CURVE_Pyb_FP512BN= {0x58B7186C84F8E8BL,0xF05C2224BF76168L,0x10AD7EE279C08DFL,0x7FC3E2E50714A43L,0x3D04961941DA289L,0x38C118867B0C9B6L,0xC315F75D91F0214L,0x8B04E7831AC3640L,0x51A3BCECL};
+const BIG_512_60 CURVE_W_FP512BN[2]= {{0x110F89749834583L,0x65FB911D16A173FL,0xFFFFFFFFCF63FE9L,0xFFFFFFFFFFFFFFFL,0xFFFFL,0x0L,0x0L,0x0L,0x0L},{0x1660D76BC37B01FL,0x5EB806161EFE02L,0xD1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}};
+const BIG_512_60 CURVE_SB_FP512BN[2][2]= {{{0xFAAEB208D4B9564L,0x601010BBB4B193CL,0xFFFFFFFFCF63F18L,0xFFFFFFFFFFFFFFFL,0xFFFFL,0x0L,0x0L,0x0L,0x0L},{0x5403CE8956259CEL,0xA45BDA397B2D3EL,0xC65DEAB2679A279L,0xCF1EACBE98B8E48L,0x3C111B0EF445146L,0xA1D8CB5307C0BBEL,0xFFFF9EC7F01C60BL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFL}},{{0x1660D76BC37B01FL,0x5EB806161EFE02L,0xD1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x110F89749834583L,0x65FB911D16A173FL,0xFFFFFFFFCF63FE9L,0xFFFFFFFFFFFFFFFL,0xFFFFL,0x0L,0x0L,0x0L,0x0L}}};
+const BIG_512_60 CURVE_WB_FP512BN[4]= {{0x6DAB36AB55A29F0L,0xFC42C60583D30C1L,0x5555555545215FBL,0x555555555555555L,0x5555L,0x0L,0x0L,0x0L,0x0L},{0xEEB012BA2355D4BL,0xF20FC1FD7F84F17L,0x892FA9DE2BB5E5CL,0x74B96064DAD40F5L,0xD76BC3535163152L,0x806161EFE021660L,0xD105EBL,0x0L,0x0L},{0x7CF03F380289AADL,0xBA82C117183E70CL,0xC497D4EF15DAF62L,0x3A5CB0326D6A07AL,0x6BB5E1A9A8B18A9L,0xC030B0F7F010B30L,0x6882F5L,0x0L,0x0L},{0x574A5F3F92279D1L,0xF65745A421E32BFL,0x55555555452152AL,0x555555555555555L,0x5555L,0x0L,0x0L,0x0L,0x0L}};
+const BIG_512_60 CURVE_BB_FP512BN[4][4]= {{{0xB306BB5E1BD810L,0x82F5C030B0F7F01L,0x68L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0xB306BB5E1BD80FL,0x82F5C030B0F7F01L,0x68L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0xB306BB5E1BD80FL,0x82F5C030B0F7F01L,0x68L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x5403CE8956259CFL,0xA45BDA397B2D3EL,0xC65DEAB2679A279L,0xCF1EACBE98B8E48L,0x3C111B0EF445146L,0xA1D8CB5307C0BBEL,0xFFFF9EC7F01C60BL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFL}},{{0x1660D76BC37B01FL,0x5EB806161EFE02L,0xD1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x5F343A3F37E31DEL,0x8D3B7DD448AAC3FL,0xC65DEAB2679A2E1L,0xCF1EACBE98B8E48L,0x3C111B0EF445146L,0xA1D8CB5307C0BBEL,0xFFFF9EC7F01C60BL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFL},{0x5F343A3F37E31DDL,0x8D3B7DD448AAC3FL,0xC65DEAB2679A2E1L,0xCF1EACBE98B8E48L,0x3C111B0EF445146L,0xA1D8CB5307C0BBEL,0xFFFF9EC7F01C60BL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFL},{0x5F343A3F37E31DEL,0x8D3B7DD448AAC3FL,0xC65DEAB2679A2E1L,0xCF1EACBE98B8E48L,0x3C111B0EF445146L,0xA1D8CB5307C0BBEL,0xFFFF9EC7F01C60BL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFL}},{{0x1660D76BC37B01EL,0x5EB806161EFE02L,0xD1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x1660D76BC37B01FL,0x5EB806161EFE02L,0xD1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x1660D76BC37B01FL,0x5EB806161EFE02L,0xD1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x1660D76BC37B01FL,0x5EB806161EFE02L,0xD1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x5F343A3F37E31DFL,0x8D3B7DD448AAC3FL,0xC65DEAB2679A2E1L,0xCF1EACBE98B8E48L,0x3C111B0EF445146L,0xA1D8CB5307C0BBEL,0xFFFF9EC7F01C60BL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFL},{0x3DA2F71D92AA9AFL,0x45A3D4235C2F3CL,0xC65DEAB2679A1A8L,0xCF1EACBE98B8E48L,0x3C111B0EF445146L,0xA1D8CB5307C0BBEL,0xFFFF9EC7F01C60BL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFL},{0x1660D76BC37B01DL,0x5EB806161EFE02L,0xD1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x5F343A3F37E31DFL,0x8D3B7DD448AAC3FL,0xC65DEAB2679A2E1L,0xCF1EACBE98B8E48L,0x3C111B0EF445146L,0xA1D8CB5307C0BBEL,0xFFFF9EC7F01C60BL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFL}}};
+
+
+#endif
+
diff --git a/version3/c/rom_curve_GOLDILOCKS.c b/version3/c/rom_curve_GOLDILOCKS.c
new file mode 100644
index 0000000..3b168c8
--- /dev/null
+++ b/version3/c/rom_curve_GOLDILOCKS.c
@@ -0,0 +1,37 @@
+#include "arch.h"
+#include "ecp_GOLDILOCKS.h"
+
+/* Curve GOLDILOCKS */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+const int CURVE_Cof_I_GOLDILOCKS= 4;
+const BIG_448_29 CURVE_Cof_GOLDILOCKS= {0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const int CURVE_A_GOLDILOCKS= 1;
+const int CURVE_B_I_GOLDILOCKS= -39081;
+const BIG_448_29 CURVE_B_GOLDILOCKS= {0x1FFF6756,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FDFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFF};
+const BIG_448_29 CURVE_Order_GOLDILOCKS= {0xB5844F3,0x1BC61495,0x1163D548,0x1984E51B,0x3690216,0xDA4D76B,0xFA7113B,0x1FEF9944,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FF};
+const BIG_448_29 CURVE_Gx_GOLDILOCKS= {0x15555555,0xAAAAAAA,0x15555555,0xAAAAAAA,0x15555555,0xAAAAAAA,0x15555555,0x152AAAAA,0xAAAAAAA,0x15555555,0xAAAAAAA,0x15555555,0xAAAAAAA,0x15555555,0xAAAAAAA,0x1555};
+const BIG_448_29 CURVE_Gy_GOLDILOCKS= {0xA9386ED,0x1757DE6F,0x13681AF6,0x19657DA3,0x3098BBB,0x12C19D15,0x12E03595,0xE515B18,0x17B7E36D,0x1AC426E,0xDBB5E8,0x10D8560,0x159D6205,0xB8246D9,0x17A58D2B,0x15C0};
+
+#endif
+
+#if CHUNK==64
+
+const int CURVE_Cof_I_GOLDILOCKS= 4;
+const BIG_448_58 CURVE_Cof_GOLDILOCKS= {0x4L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const int CURVE_A_GOLDILOCKS= 1;
+const int CURVE_B_I_GOLDILOCKS= -39081;
+const BIG_448_58 CURVE_B_GOLDILOCKS= {0x3FFFFFFFFFF6756L,0x3FFFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFFL,0x3FBFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFFL,0x3FFFFFFFFFFL};
+const BIG_448_58 CURVE_Order_GOLDILOCKS= {0x378C292AB5844F3L,0x3309CA37163D548L,0x1B49AED63690216L,0x3FDF3288FA7113BL,0x3FFFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFFL,0xFFFFFFFFFFL};
+const BIG_448_58 CURVE_Gx_GOLDILOCKS= {0x155555555555555L,0x155555555555555L,0x155555555555555L,0x2A5555555555555L,0x2AAAAAAAAAAAAAAL,0x2AAAAAAAAAAAAAAL,0x2AAAAAAAAAAAAAAL,0x2AAAAAAAAAAL};
+const BIG_448_58 CURVE_Gy_GOLDILOCKS= {0x2EAFBCDEA9386EDL,0x32CAFB473681AF6L,0x25833A2A3098BBBL,0x1CA2B6312E03595L,0x35884DD7B7E36DL,0x21B0AC00DBB5E8L,0x17048DB359D6205L,0x2B817A58D2BL};
+#endif
+
+
diff --git a/version3/c/rom_curve_HIFIVE.c b/version3/c/rom_curve_HIFIVE.c
new file mode 100644
index 0000000..20a25e5
--- /dev/null
+++ b/version3/c/rom_curve_HIFIVE.c
@@ -0,0 +1,37 @@
+#include "arch.h"
+#include "ecp_HIFIVE.h"
+
+/* Curve HIFIVE */
+
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+const int CURVE_Cof_I_HIFIVE= 8;
+const BIG_336_29 CURVE_Cof_HIFIVE= {0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const int CURVE_A_HIFIVE= 1;
+const int CURVE_B_I_HIFIVE= 11111;
+const BIG_336_29 CURVE_B_HIFIVE= {0x2B67,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG_336_29 CURVE_Order_HIFIVE= {0x1E9FA805,0x197CACB9,0x1E4EEA9E,0x17AD70F,0x1FA9850C,0x38A0A,0x0,0x0,0x0,0x0,0x0,0x4000};
+const BIG_336_29 CURVE_Gx_HIFIVE= {0xC,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG_336_29 CURVE_Gy_HIFIVE= {0x5FE8632,0x15F63428,0xD976C4,0x1AACA194,0x35B6DB5,0x8E3F7A,0x52D1B0E,0xF0A7A36,0x1C161D00,0x8170C70,0x1185AD59,0x181B};
+#endif
+
+#if CHUNK==64
+
+const int CURVE_Cof_I_HIFIVE= 8;
+const BIG_336_60 CURVE_Cof_HIFIVE= {0x8L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const int CURVE_A_HIFIVE= 1;
+const int CURVE_B_I_HIFIVE= 11111;
+const BIG_336_60 CURVE_B_HIFIVE= {0x2B67L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG_336_60 CURVE_Order_HIFIVE= {0xB2F95973E9FA805L,0xC0BD6B87F93BAA7L,0x71415FA9850L,0x0L,0x0L,0x200000000L};
+const BIG_336_60 CURVE_Gx_HIFIVE= {0xCL,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG_336_60 CURVE_Gy_HIFIVE= {0x2BEC68505FE8632L,0x5D5650CA0365DB1L,0x3811C7EF435B6DBL,0x7853D1B14B46CL,0x56502E18E1C161DL,0xC0DC616BL};
+#endif
+
+
diff --git a/version3/c/rom_curve_NIST256.c b/version3/c/rom_curve_NIST256.c
new file mode 100644
index 0000000..2915b4d
--- /dev/null
+++ b/version3/c/rom_curve_NIST256.c
@@ -0,0 +1,37 @@
+#include "arch.h"
+#include "ecp_NIST256.h"
+
+/* Curve NIST256 */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+const int CURVE_Cof_I_NIST256= 1;
+const BIG_256_28 CURVE_Cof_NIST256= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const int CURVE_A_NIST256= -3;
+const int CURVE_B_I_NIST256= 0;
+const BIG_256_28 CURVE_B_NIST256= {0x7D2604B,0xCE3C3E2,0x3B0F63B,0x6B0CC5,0x6BC651D,0x5576988,0x7B3EBBD,0xAA3A93E,0xAC635D8,0x5};
+const BIG_256_28 CURVE_Order_NIST256= {0xC632551,0xB9CAC2F,0x79E84F3,0xFAADA71,0xFFFBCE6,0xFFFFFFF,0xFFFFFF,0x0,0xFFFFFFF,0xF};
+const BIG_256_28 CURVE_Gx_NIST256= {0x898C296,0xA13945D,0xB33A0F4,0x7D812DE,0xF27703,0xE563A44,0x7F8BCE6,0xE12C424,0xB17D1F2,0x6};
+const BIG_256_28 CURVE_Gy_NIST256= {0x7BF51F5,0xB640683,0x15ECECB,0x33576B3,0xE162BCE,0x4A7C0F9,0xB8EE7EB,0xFE1A7F9,0xFE342E2,0x4};
+
+
+#endif
+
+#if CHUNK==64
+
+const int CURVE_Cof_I_NIST256= 1;
+const BIG_256_56 CURVE_Cof_NIST256= {0x1L,0x0L,0x0L,0x0L,0x0L};
+const int CURVE_A_NIST256= -3;
+const int CURVE_B_I_NIST256= 0;
+const BIG_256_56 CURVE_B_NIST256= {0xCE3C3E27D2604BL,0x6B0CC53B0F63BL,0x55769886BC651DL,0xAA3A93E7B3EBBDL,0x5AC635D8L};
+const BIG_256_56 CURVE_Order_NIST256= {0xB9CAC2FC632551L,0xFAADA7179E84F3L,0xFFFFFFFFFFBCE6L,0xFFFFFFL,0xFFFFFFFFL};
+const BIG_256_56 CURVE_Gx_NIST256= {0xA13945D898C296L,0x7D812DEB33A0F4L,0xE563A440F27703L,0xE12C4247F8BCE6L,0x6B17D1F2L};
+const BIG_256_56 CURVE_Gy_NIST256= {0xB6406837BF51F5L,0x33576B315ECECBL,0x4A7C0F9E162BCEL,0xFE1A7F9B8EE7EBL,0x4FE342E2L};
+#endif
+
diff --git a/version3/c/rom_curve_NIST384.c b/version3/c/rom_curve_NIST384.c
new file mode 100644
index 0000000..d246ec1
--- /dev/null
+++ b/version3/c/rom_curve_NIST384.c
@@ -0,0 +1,36 @@
+#include "arch.h"
+#include "ecp_NIST384.h"
+
+/* Curve NIST384 */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+const int CURVE_Cof_I_NIST384= 1;
+const BIG_384_29 CURVE_Cof_NIST384= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const int CURVE_A_NIST384= -3;
+const int CURVE_B_I_NIST384= 0;
+const BIG_384_29 CURVE_B_NIST384= {0x13EC2AEF,0x142E476E,0xBB4674A,0xC731B14,0x1875AC65,0x447A809,0x4480C50,0xDDFD028,0x19181D9C,0x1F1FC168,0x623815A,0x47DCFC9,0x1312FA7E,0x59};
+const BIG_384_29 CURVE_Order_NIST384= {0xCC52973,0x760CB56,0xC29DEBB,0x141B6491,0x12DDF581,0x6C0FA1B,0x1FFF1D8D,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F};
+const BIG_384_29 CURVE_Gx_NIST384= {0x12760AB7,0x12A2F1C3,0x154A5B0E,0x5E4BB7E,0x2A38550,0xF0412A,0xE6167DD,0xC5174F3,0x146E1D3B,0x1799056B,0x3AC71C7,0x1D160A6F,0x87CA22B,0x55};
+const BIG_384_29 CURVE_Gy_NIST384= {0x10EA0E5F,0x1218EBE4,0x1FA0675E,0x1639C3A,0xB8C00A6,0x1889DAF8,0x11F3A768,0x17A51342,0x9F8F41D,0x1C9496E1,0x1767A62F,0xC4C58DE,0x17DE4A9,0x1B};
+#endif
+
+#if CHUNK==64
+
+const int CURVE_Cof_I_NIST384= 1;
+const BIG_384_56 CURVE_Cof_NIST384= {0x1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const int CURVE_A_NIST384= -3;
+const int CURVE_B_I_NIST384= 0;
+const BIG_384_56 CURVE_B_NIST384= {0x85C8EDD3EC2AEFL,0x398D8A2ED19D2AL,0x8F5013875AC656L,0xFE814112031408L,0xF82D19181D9C6EL,0xE7E4988E056BE3L,0xB3312FA7E23EL};
+const BIG_384_56 CURVE_Order_NIST384= {0xEC196ACCC52973L,0xDB248B0A77AECL,0x81F4372DDF581AL,0xFFFFFFFFC7634DL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFL};
+const BIG_384_56 CURVE_Gx_NIST384= {0x545E3872760AB7L,0xF25DBF55296C3AL,0xE082542A385502L,0x8BA79B9859F741L,0x20AD746E1D3B62L,0x5378EB1C71EF3L,0xAA87CA22BE8BL};
+const BIG_384_56 CURVE_Gy_NIST384= {0x431D7C90EA0E5FL,0xB1CE1D7E819D7AL,0x13B5F0B8C00A60L,0x289A147CE9DA31L,0x92DC29F8F41DBDL,0x2C6F5D9E98BF92L,0x3617DE4A9626L};
+#endif
+
+
diff --git a/version3/c/rom_curve_NIST521.c b/version3/c/rom_curve_NIST521.c
new file mode 100644
index 0000000..0262632
--- /dev/null
+++ b/version3/c/rom_curve_NIST521.c
@@ -0,0 +1,35 @@
+#include "arch.h"
+#include "ecp_NIST521.h"
+
+/* Curve NIST521 */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+const int CURVE_Cof_I_NIST521= 1;
+const BIG_528_28 CURVE_Cof_NIST521= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const int CURVE_A_NIST521= -3;
+const int CURVE_B_I_NIST521= 0;
+const BIG_528_28 CURVE_B_NIST521= {0xB503F00,0x451FD46,0xC34F1EF,0xDF883D2,0xF073573,0xBD3BB1B,0xB1652C0,0xEC7E937,0x6193951,0xF109E15,0x489918E,0x15F3B8B,0x25B99B3,0xEEA2DA7,0xB68540,0x929A21A,0xE1C9A1F,0x3EB9618,0x5195};
+const BIG_528_28 CURVE_Order_NIST521= {0x1386409,0x6FB71E9,0xC47AEBB,0xC9B8899,0x5D03BB5,0x48F709A,0xB7FCC01,0xBF2F966,0x1868783,0xFFFFFA5,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0x1FFFF};
+const BIG_528_28 CURVE_Gx_NIST521= {0x2E5BD66,0x7E7E31C,0xA429BF9,0xB3C1856,0x8DE3348,0x27A2FFA,0x8FE1DC1,0xEFE7592,0x14B5E77,0x4D3DBAA,0x8AF606B,0xB521F82,0x139053F,0x429C648,0x62395B4,0x9E3ECB6,0x404E9CD,0x8E06B70,0xC685};
+const BIG_528_28 CURVE_Gy_NIST521= {0xFD16650,0xBE94769,0x2C24088,0x7086A27,0x761353C,0x13FAD0,0xC550B9,0x5EF4264,0x7EE7299,0x3E662C9,0xFBD1727,0x446817A,0x449579B,0xD998F54,0x42C7D1B,0x5C8A5FB,0xA3BC004,0x296A789,0x11839};
+#endif
+
+#if CHUNK==64
+
+const int CURVE_Cof_I_NIST521= 1;
+const BIG_528_60 CURVE_Cof_NIST521= {0x1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const int CURVE_A_NIST521= -3;
+const int CURVE_B_I_NIST521= 0;
+const BIG_528_60 CURVE_B_NIST521= {0xF451FD46B503F00L,0x73DF883D2C34F1EL,0x2C0BD3BB1BF0735L,0x3951EC7E937B165L,0x9918EF109E15619L,0x5B99B315F3B8B48L,0xB68540EEA2DA72L,0x8E1C9A1F929A21AL,0x51953EB961L};
+const BIG_528_60 CURVE_Order_NIST521= {0xB6FB71E91386409L,0xB5C9B8899C47AEBL,0xC0148F709A5D03BL,0x8783BF2F966B7FCL,0xFFFFFFFFFFA5186L,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0x1FFFFFFFFFFL};
+const BIG_528_60 CURVE_Gx_NIST521= {0x97E7E31C2E5BD66L,0x48B3C1856A429BFL,0xDC127A2FFA8DE33L,0x5E77EFE75928FE1L,0xF606B4D3DBAA14BL,0x39053FB521F828AL,0x62395B4429C6481L,0x404E9CD9E3ECB6L,0xC6858E06B7L};
+const BIG_528_60 CURVE_Gy_NIST521= {0x8BE94769FD16650L,0x3C7086A272C2408L,0xB9013FAD076135L,0x72995EF42640C55L,0xD17273E662C97EEL,0x49579B446817AFBL,0x42C7D1BD998F544L,0x9A3BC0045C8A5FBL,0x11839296A78L};
+#endif
+
diff --git a/version3/c/rom_curve_NUMS256E.c b/version3/c/rom_curve_NUMS256E.c
new file mode 100644
index 0000000..3f040ac
--- /dev/null
+++ b/version3/c/rom_curve_NUMS256E.c
@@ -0,0 +1,43 @@
+#include "arch.h"
+#include "ecp_NUMS256E.h"
+
+/*  NUMS 256-bit Curve - Edwards */
+
+#if CHUNK==16
+
+const int CURVE_Cof_I_NUMS256E= 4;
+const BIG_256_13 CURVE_Cof_NUMS256E= {0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const int CURVE_A_NUMS256E= 1;
+const int CURVE_B_I_NUMS256E= -15342;
+const BIG_256_13 CURVE_B_NUMS256E= {0x355,0x1FFE,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FF};
+const BIG_256_13 CURVE_Order_NUMS256E= {0xAF5,0x16EA,0x43B,0xF63,0x11A4,0x1CD,0x1D65,0x14A5,0x155A,0x20C,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x80};
+const BIG_256_13 CURVE_Gx_NUMS256E= {0x13DA,0x1768,0x40B,0x1D81,0xA0D,0x1AC3,0xC20,0x1DC,0x198A,0x1061,0x6F5,0x1241,0x15F6,0xF1E,0x1734,0x46F,0xAEA,0x7DB,0x1D45,0x114};
+const BIG_256_13 CURVE_Gy_NUMS256E= {0x9E6,0xC54,0x19DE,0xC2D,0x12FA,0x1769,0x215,0x1B02,0x1F61,0x38A,0x4,0xC97,0x1D9A,0xB32,0x1F3A,0x4B8,0x19D9,0x14FE,0x154F,0x89};
+
+#endif
+
+#if CHUNK==32
+
+const int CURVE_Cof_I_NUMS256E= 4;
+const BIG_256_29 CURVE_Cof_NUMS256E= {0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const int CURVE_A_NUMS256E= 1;
+const int CURVE_B_I_NUMS256E= -15342;
+const BIG_256_29 CURVE_B_NUMS256E= {0x1FFFC355,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFFFFFF};
+const BIG_256_29 CURVE_Order_NUMS256E= {0xEDD4AF5,0x123D8C87,0x1650E6C6,0xAB54A5E,0x419,0x0,0x0,0x0,0x400000};
+const BIG_256_29 CURVE_Gx_NUMS256E= {0xEED13DA,0x6F60481,0x20D61A8,0x13141DC6,0x9BD60C3,0x1EAFB490,0xDF73478,0x1F6D5D44,0x8A7514};
+const BIG_256_29 CURVE_Gy_NUMS256E= {0x198A89E6,0x1D30B73B,0x15BB4CB,0x1EC3B021,0x18010715,0x12ECD325,0x171F3A59,0x13FB3B24,0x44D53E};
+
+#endif
+
+#if CHUNK==64
+
+const int CURVE_Cof_I_NUMS256E= 4;
+const BIG_256_56 CURVE_Cof_NUMS256E= {0x4L,0x0L,0x0L,0x0L,0x0L};
+const int CURVE_A_NUMS256E= 1;
+const int CURVE_B_I_NUMS256E= -15342;
+const BIG_256_56 CURVE_B_NUMS256E= {0xFFFFFFFFFFC355L,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFL};
+const BIG_256_56 CURVE_Order_NUMS256E= {0x47B190EEDD4AF5L,0x5AA52F59439B1AL,0x4195L,0x0L,0x40000000L};
+const BIG_256_56 CURVE_Gx_NUMS256E= {0xDEC0902EED13DAL,0x8A0EE3083586A0L,0x5F69209BD60C39L,0x6AEA237DCD1E3DL,0x8A7514FBL};
+const BIG_256_56 CURVE_Gy_NUMS256E= {0xA616E7798A89E6L,0x61D810856ED32FL,0xD9A64B8010715FL,0xD9D925C7CE9665L,0x44D53E9FL};
+
+#endif
\ No newline at end of file
diff --git a/version3/c/rom_curve_NUMS256W.c b/version3/c/rom_curve_NUMS256W.c
new file mode 100644
index 0000000..941d6a5
--- /dev/null
+++ b/version3/c/rom_curve_NUMS256W.c
@@ -0,0 +1,34 @@
+#include "arch.h"
+#include "ecp_NUMS256W.h"
+
+/*  NUMS 256-bit Curve - Weierstrass */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+const int CURVE_Cof_I_NUMS256W= 1;
+const BIG_256_28 CURVE_Cof_NUMS256W= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const int CURVE_A_NUMS256W= -3;
+const int CURVE_B_I_NUMS256W= 152961;
+const BIG_256_28 CURVE_B_NUMS256W= {0x25581,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG_256_28 CURVE_Order_NUMS256W= {0x751A825,0xAB20294,0x65C6020,0x8275EA2,0xFFFE43C,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xF};
+const BIG_256_28 CURVE_Gx_NUMS256W= {0x21AACB1,0x52EE1EB,0x4C73ABC,0x9B0903D,0xB098357,0xA04F42C,0x1297A95,0x5AAADB6,0xC9ED6B6,0xB};
+const BIG_256_28 CURVE_Gy_NUMS256W= {0x184DE9F,0xB5B9CB2,0x10FBB80,0xC3D1153,0x35C955,0xF77E04E,0x673448B,0x3399B6A,0x8FC0F1,0xD};
+
+#endif
+
+#if CHUNK==64
+const int CURVE_Cof_I_NUMS256W= 1;
+const BIG_256_56 CURVE_Cof_NUMS256W= {0x1L,0x0L,0x0L,0x0L,0x0L};
+const int CURVE_A_NUMS256W= -3;
+const int CURVE_B_I_NUMS256W= 152961;
+const BIG_256_56 CURVE_B_NUMS256W= {0x25581L,0x0L,0x0L,0x0L,0x0L};
+const BIG_256_56 CURVE_Order_NUMS256W= {0xAB20294751A825L,0x8275EA265C6020L,0xFFFFFFFFFFE43CL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFL};
+const BIG_256_56 CURVE_Gx_NUMS256W= {0x52EE1EB21AACB1L,0x9B0903D4C73ABCL,0xA04F42CB098357L,0x5AAADB61297A95L,0xBC9ED6B6L};
+const BIG_256_56 CURVE_Gy_NUMS256W= {0xB5B9CB2184DE9FL,0xC3D115310FBB80L,0xF77E04E035C955L,0x3399B6A673448BL,0xD08FC0F1L};
+
+#endif
\ No newline at end of file
diff --git a/version3/c/rom_curve_NUMS384E.c b/version3/c/rom_curve_NUMS384E.c
new file mode 100644
index 0000000..4d9d249
--- /dev/null
+++ b/version3/c/rom_curve_NUMS384E.c
@@ -0,0 +1,34 @@
+#include "arch.h"
+#include "ecp_NUMS384E.h"
+
+/*  NUMS 384-bit Curve - Edwards */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+const int CURVE_Cof_I_NUMS384E= 4;
+const BIG_384_29 CURVE_Cof_NUMS384E= {0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const int CURVE_A_NUMS384E= 1;
+const int CURVE_B_I_NUMS384E= -11556;
+const BIG_384_29 CURVE_B_NUMS384E= {0x1FFFD19F,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F};
+const BIG_384_29 CURVE_Order_NUMS384E= {0x6A3897D,0x5CEE627,0xD721E48,0x8AAB556,0x1E1CF61E,0xD0E5A35,0x1FFF891C,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1F};
+const BIG_384_29 CURVE_Gx_NUMS384E= {0xC206BDE,0x6AA0723,0x116504D4,0x52562CA,0x163406FF,0x1FD47998,0x10015D8F,0x8DCB7C9,0x15B30BF4,0x14D72AED,0x102DA884,0xB524CD9,0x1B111FB4,0x30};
+const BIG_384_29 CURVE_Gy_NUMS384E= {0x10729392,0xC681F0F,0x1B123727,0x561F28D,0x1964B007,0xC7BFB22,0x1D5A0C3E,0xE9E284B,0x1716AD82,0x11D886E,0x1CE2C69,0x134DDD61,0x983E67B,0x41};
+#endif
+
+#if CHUNK==64
+
+const int CURVE_Cof_I_NUMS384E= 4;
+const BIG_384_56 CURVE_Cof_NUMS384E= {0x4L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const int CURVE_A_NUMS384E= 1;
+const int CURVE_B_I_NUMS384E= -11556;
+const BIG_384_56 CURVE_B_NUMS384E= {0xFFFFFFFFFFD19FL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFL};
+const BIG_384_56 CURVE_Order_NUMS384E= {0xB9DCC4E6A3897DL,0x555AAB35C87920L,0x1CB46BE1CF61E4L,0xFFFFFFFFE2471AL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0x3FFFFFFFFFFFL};
+const BIG_384_56 CURVE_Gx_NUMS384E= {0xD540E46C206BDEL,0x92B16545941350L,0xA8F33163406FF2L,0xE5BE4C005763FFL,0xE55DB5B30BF446L,0x266CC0B6A2129AL,0x61B111FB45A9L};
+const BIG_384_56 CURVE_Gy_NUMS384E= {0x8D03E1F0729392L,0xB0F946EC48DC9DL,0xF7F645964B0072L,0xF1425F56830F98L,0xB10DD716AD8274L,0xEEB08738B1A423L,0x82983E67B9A6L};
+#endif
\ No newline at end of file
diff --git a/version3/c/rom_curve_NUMS384W.c b/version3/c/rom_curve_NUMS384W.c
new file mode 100644
index 0000000..5d04877
--- /dev/null
+++ b/version3/c/rom_curve_NUMS384W.c
@@ -0,0 +1,34 @@
+#include "arch.h"
+#include "ecp_NUMS384W.h"
+
+/*  NUMS 384-bit Curve - Weierstrass */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+const int CURVE_Cof_I_NUMS384W= 1;
+const BIG_384_29 CURVE_Cof_NUMS384W= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const int CURVE_A_NUMS384W= -3;
+const int CURVE_B_I_NUMS384W= -34568;
+const BIG_384_29 CURVE_B_NUMS384W= {0x1FFF77BB,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F};
+const BIG_384_29 CURVE_Order_NUMS384W= {0x1B0E61B9,0x26C0FB3,0xDF89E98,0x153A7A98,0x16881BED,0x178F75AE,0x1FFF587A,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F};
+const BIG_384_29 CURVE_Gx_NUMS384W= {0x98152A,0x1CE5D021,0x18711EFA,0x1DDA201E,0xC742522,0x148D9536,0x7D3CEF4,0x19BF703F,0x60225C1,0x12082F8D,0x12203288,0x2DE3038,0x17956F0B,0x3A};
+const BIG_384_29 CURVE_Gy_NUMS384W= {0x6180716,0x3A5C763,0x1D2B4997,0xD69B77F,0x837EBCD,0x1BE890D,0xE72E482,0xEFF0FEE,0x1EB00469,0x2C267B,0x15F8CF4C,0x3371C71,0xDEE368E,0x56};
+#endif
+
+#if CHUNK==64
+
+const int CURVE_Cof_I_NUMS384W= 1;
+const BIG_384_56 CURVE_Cof_NUMS384W= {0x1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const int CURVE_A_NUMS384W= -3;
+const int CURVE_B_I_NUMS384W= -34568;
+const BIG_384_56 CURVE_B_NUMS384W= {0xFFFFFFFFFF77BBL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFL};
+const BIG_384_56 CURVE_Order_NUMS384W= {0x4D81F67B0E61B9L,0x9D3D4C37E27A60L,0x1EEB5D6881BEDAL,0xFFFFFFFFD61EAFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFL};
+const BIG_384_56 CURVE_Gx_NUMS384W= {0x9CBA042098152AL,0xED100F61C47BEBL,0x1B2A6CC742522EL,0xFB81F9F4F3BD29L,0x5F1A60225C1CDL,0x181C4880CA2241L,0x757956F0B16FL};
+const BIG_384_56 CURVE_Gy_NUMS384W= {0x74B8EC66180716L,0xB4DBBFF4AD265CL,0x7D121A837EBCD6L,0xF87F739CB92083L,0x84CF7EB0046977L,0x8E38D7E33D3005L,0xACDEE368E19BL};
+#endif
\ No newline at end of file
diff --git a/version3/c/rom_curve_NUMS512E.c b/version3/c/rom_curve_NUMS512E.c
new file mode 100644
index 0000000..b31b6b5
--- /dev/null
+++ b/version3/c/rom_curve_NUMS512E.c
@@ -0,0 +1,33 @@
+#include "arch.h"
+#include "ecp_NUMS512E.h"
+
+/*  NUMS 512-bit Curve - Edwards */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+const int CURVE_Cof_I_NUMS512E= 4;
+const BIG_512_29 CURVE_Cof_NUMS512E= {0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const int CURVE_A_NUMS512E= 1;
+const int CURVE_B_I_NUMS512E= -78296;
+const BIG_512_29 CURVE_B_NUMS512E= {0x1FFECBEF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF};
+const BIG_512_29 CURVE_Order_NUMS512E= {0x1BEED46D,0x1A3467A8,0x1BFB3FD9,0xC0AF0DB,0x86F52A4,0xC64B85B,0x6EA78FF,0xDA5F9F2,0x1FB4F063,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFF};
+const BIG_512_29 CURVE_Gx_NUMS512E= {0x19EC57FE,0xDCD594C,0x113C0571,0xA4A84F9,0x104AD0FE,0x4C92B44,0xC3DE2F7,0x9DDC8CE,0x74621C1,0x1139DC0A,0x9E85FAF,0x1B894704,0x1D1E79F4,0x9E29997,0x32DE223,0x16D38F43,0x116D128D,0x6FC71};
+const BIG_512_29 CURVE_Gy_NUMS512E= {0x1E2F5E1,0x136EF606,0x1C7407CC,0xDA71537,0xC1FD026,0x3431576,0x15898068,0x1E5D32C6,0x120CA53,0xC84F41A,0xA4ADAE5,0x104B3A45,0x76F726D,0x1512B772,0x3D5DEA0,0x194E3316,0x1FF39D49,0x3684D};
+#endif
+
+#if CHUNK==64
+
+const int CURVE_Cof_I_NUMS512E= 4;
+const BIG_512_56 CURVE_Cof_NUMS512E= {0x4L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const int CURVE_A_NUMS512E= 1;
+const int CURVE_B_I_NUMS512E= -78296;
+const BIG_512_56 CURVE_B_NUMS512E= {0xFFFFFFFFFECBEFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFL};
+const BIG_512_56 CURVE_Order_NUMS512E= {0x468CF51BEED46DL,0x5786DEFECFF67L,0xC970B686F52A46L,0x2FCF91BA9E3FD8L,0xFFFFFFB4F0636DL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0x3FL};
+const BIG_512_56 CURVE_Gx_NUMS512E= {0xB9AB2999EC57FEL,0x25427CC4F015C5L,0x92568904AD0FE5L,0xEE46730F78BDC9L,0x3B81474621C14EL,0xA38227A17EBE27L,0x332FD1E79F4DC4L,0x7A18CB7888D3C5L,0x8E316D128DB69CL,0xDFL};
+const BIG_512_56 CURVE_Gy_NUMS512E= {0x6DDEC0C1E2F5E1L,0xD38A9BF1D01F32L,0x862AECC1FD0266L,0xE9963562601A06L,0x9E834120CA53F2L,0x9D22A92B6B9590L,0x6EE476F726D825L,0x98B0F577A82A25L,0x9BFF39D49CA71L,0x6DL};
+#endif
diff --git a/version3/c/rom_curve_NUMS512W.c b/version3/c/rom_curve_NUMS512W.c
new file mode 100644
index 0000000..f222aa7
--- /dev/null
+++ b/version3/c/rom_curve_NUMS512W.c
@@ -0,0 +1,34 @@
+#include "arch.h"
+#include "ecp_NUMS512W.h"
+
+/*  NUMS 512-bit Curve - Weierstrass */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+const int CURVE_Cof_I_NUMS512W= 1;
+const BIG_512_29 CURVE_Cof_NUMS512W= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const int CURVE_A_NUMS512W= -3;
+const int CURVE_B_I_NUMS512W= 121243;
+const BIG_512_29 CURVE_B_NUMS512W= {0x1D99B,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG_512_29 CURVE_Order_NUMS512W= {0x433555D,0x10A9F9C8,0x1F3490F3,0xD166CC0,0xBDC63B5,0xC76CBE8,0xC6D3F09,0x1F729CF0,0x1F5B3CA4,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF};
+const BIG_512_29 CURVE_Gx_NUMS512W= {0xCABAE57,0x4143CAC,0x1BD778B7,0x1AC026FA,0x15831D5,0x14312AB,0x167A4DE5,0xA20ED66,0x195021A1,0x129836CF,0x1141B830,0xA03ED0A,0xCAD83BB,0x1E9DA94C,0xDC00A80,0x1527B45,0x1447141D,0x1D601};
+const BIG_512_29 CURVE_Gy_NUMS512W= {0x183527A6,0x1D043B01,0x1F43FA48,0x16B83C99,0x5602CF2,0x1420592D,0x17A70486,0x1B5161DD,0x14A28415,0x3DE8A78,0x3D2C983,0x17797719,0x197DBDEA,0x15D88025,0x1BBB718F,0xAD679C1,0x14CA29AD,0x4A1D2};
+#endif
+
+#if CHUNK==64
+
+const int CURVE_Cof_I_NUMS512W= 1;
+const BIG_512_56 CURVE_Cof_NUMS512W= {0x1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const int CURVE_A_NUMS512W= -3;
+const int CURVE_B_I_NUMS512W= 121243;
+const BIG_512_56 CURVE_B_NUMS512W= {0x1D99BL,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG_512_56 CURVE_Order_NUMS512W= {0x153F390433555DL,0x8B36607CD243CEL,0xED97D0BDC63B56L,0x94E7831B4FC258L,0xFFFFFF5B3CA4FBL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFL};
+const BIG_512_56 CURVE_Gx_NUMS512W= {0x8287958CABAE57L,0x60137D6F5DE2DCL,0x86255615831D5DL,0x76B359E937942L,0x6D9F95021A151L,0xF6854506E0C253L,0x5298CAD83BB501L,0xDA2B7002A03D3BL,0xC03447141D0A93L,0x3AL};
+const BIG_512_56 CURVE_Gy_NUMS512W= {0xA08760383527A6L,0x5C1E4CFD0FE923L,0x40B25A5602CF2BL,0x8B0EEDE9C121A8L,0xD14F14A28415DAL,0xBB8C8F4B260C7BL,0x4B97DBDEABBCL,0xCE0EEEDC63EBB1L,0x3A54CA29AD56B3L,0x94L};
+#endif
diff --git a/version3/c/rom_curve_SECP256K1.c b/version3/c/rom_curve_SECP256K1.c
new file mode 100644
index 0000000..df6c3f0
--- /dev/null
+++ b/version3/c/rom_curve_SECP256K1.c
@@ -0,0 +1,39 @@
+#include "arch.h"
+#include "ecp_SECP256K1.h"
+
+/* Curve SECP256K1 */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+const int CURVE_Cof_I_SECP256K1= 1;
+const BIG_256_28 CURVE_Cof_SECP256K1= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const int CURVE_A_SECP256K1= 0;
+const int CURVE_B_I_SECP256K1= 7;
+const BIG_256_28 CURVE_B_SECP256K1= {0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG_256_28 CURVE_Order_SECP256K1= {0x364141,0xD25E8CD,0x8A03BBF,0xDCE6AF4,0xFFEBAAE,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xF};
+const BIG_256_28 CURVE_Gx_SECP256K1= {0x6F81798,0xF2815B1,0xE28D959,0xFCDB2DC,0xB07029B,0x95CE870,0xC55A062,0xF9DCBBA,0x9BE667E,0x7};
+const BIG_256_28 CURVE_Gy_SECP256K1= {0xB10D4B8,0x47D08FF,0x554199C,0xB448A68,0x8A8FD17,0xFC0E110,0x55DA4FB,0x26A3C46,0x83ADA77,0x4};
+
+
+
+#endif
+
+#if CHUNK==64
+
+const int CURVE_Cof_I_SECP256K1= 1;
+const BIG_256_56 CURVE_Cof_SECP256K1= {0x1L,0x0L,0x0L,0x0L,0x0L};
+const int CURVE_A_SECP256K1= 0;
+const int CURVE_B_I_SECP256K1= 7;
+const BIG_256_56 CURVE_B_SECP256K1= {0x7L,0x0L,0x0L,0x0L,0x0L};
+const BIG_256_56 CURVE_Order_SECP256K1= {0xD25E8CD0364141L,0xDCE6AF48A03BBFL,0xFFFFFFFFFEBAAEL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFL};
+const BIG_256_56 CURVE_Gx_SECP256K1= {0xF2815B16F81798L,0xFCDB2DCE28D959L,0x95CE870B07029BL,0xF9DCBBAC55A062L,0x79BE667EL};
+const BIG_256_56 CURVE_Gy_SECP256K1= {0x47D08FFB10D4B8L,0xB448A68554199CL,0xFC0E1108A8FD17L,0x26A3C4655DA4FBL,0x483ADA77L};
+
+#endif
+
diff --git a/version3/c/rom_field_25519.c b/version3/c/rom_field_25519.c
new file mode 100644
index 0000000..475a743
--- /dev/null
+++ b/version3/c/rom_field_25519.c
@@ -0,0 +1,33 @@
+#include "arch.h"
+#include "fp_25519.h"
+
+/* Curve 25519 */
+
+#if CHUNK==16
+
+// Base Bits= 13
+const BIG_256_13 Modulus_25519= {0x1FED,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0xFF};
+const BIG_256_13 R2modp_25519= {0x400,0x2D,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const chunk MConst_25519= 0x13;
+
+#endif
+
+#if CHUNK==32
+
+// Base Bits= 29
+const BIG_256_29 Modulus_25519= {0x1FFFFFED,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFFF};
+const BIG_256_29 R2modp_25519= {0x169000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const chunk MConst_25519= 0x13;
+
+
+#endif
+
+#if CHUNK==64
+// Base Bits= 56
+const BIG_256_56 Modulus_25519= {0xFFFFFFFFFFFFEDL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0x7FFFFFFFL};
+const BIG_256_56 R2modp_25519= {0xA4000000000000L,0x5L,0x0L,0x0L,0x0L};
+const chunk MConst_25519= 0x13L;
+
+
+#endif
+
diff --git a/version3/c/rom_field_256PME.c b/version3/c/rom_field_256PME.c
new file mode 100644
index 0000000..cf31ee1
--- /dev/null
+++ b/version3/c/rom_field_256PME.c
@@ -0,0 +1,28 @@
+#include "arch.h"
+#include "fp_256PME.h"
+
+/* NUMS 256-bit modulus */
+
+
+#if CHUNK==16
+// Base Bits= 13
+const BIG_256_13 Modulus_256PME= {0x1F43,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FF};
+const BIG_256_13 R2modp_256PME= {0x900,0x45C,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const chunk MConst_256PME= 0xBD;
+#endif
+
+#if CHUNK==32
+// Base Bits= 29
+const BIG_256_29 Modulus_256PME= {0x1FFFFF43,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFFFFFF};
+const BIG_256_29 R2modp_256PME= {0x22E2400,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const chunk MConst_256PME= 0xBD;
+
+#endif
+
+#if CHUNK==64
+// Base Bits= 56
+const BIG_256_56 Modulus_256PME= {0xFFFFFFFFFFFF43L,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFL};
+const BIG_256_56 R2modp_256PME= {0x89000000000000L,0x8BL,0x0L,0x0L,0x0L};
+const chunk MConst_256PME= 0xBDL;
+
+#endif
\ No newline at end of file
diff --git a/version3/c/rom_field_256PMW.c b/version3/c/rom_field_256PMW.c
new file mode 100644
index 0000000..2775033
--- /dev/null
+++ b/version3/c/rom_field_256PMW.c
@@ -0,0 +1,26 @@
+#include "arch.h"
+#include "fp_256PMW.h"
+
+/* NUMS 256-bit modulus */
+
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+// Base Bits= 28
+const BIG_256_28 Modulus_256PMW= {0xFFFFF43,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xF};
+const BIG_256_28 R2modp_256PMW= {0x0,0x8900000,0x8B,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const chunk MConst_256PMW= 0xBD;
+#endif
+
+#if CHUNK==64
+// Base Bits= 56
+const BIG_256_56 Modulus_256PMW= {0xFFFFFFFFFFFF43L,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFL};
+const BIG_256_56 R2modp_256PMW= {0x89000000000000L,0x8BL,0x0L,0x0L,0x0L};
+const chunk MConst_256PMW= 0xBDL;
+
+#endif
\ No newline at end of file
diff --git a/version3/c/rom_field_384PM.c b/version3/c/rom_field_384PM.c
new file mode 100644
index 0000000..e692b56
--- /dev/null
+++ b/version3/c/rom_field_384PM.c
@@ -0,0 +1,25 @@
+#include "arch.h"
+#include "fp_384PM.h"
+
+/* NUMS 384-bit modulus */
+
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+// Base Bits= 29
+const BIG_384_29 Modulus_384PM= {0x1FFFFEC3,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F};
+const BIG_384_29 R2modp_384PM= {0x0,0x4448000,0x6,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const chunk MConst_384PM= 0x13D;
+#endif
+
+#if CHUNK==64
+// Base Bits= 56
+const BIG_384_56 Modulus_384PM= {0xFFFFFFFFFFFEC3L,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFL};
+const BIG_384_56 R2modp_384PM= {0x188890000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const chunk MConst_384PM= 0x13DL;
+#endif
\ No newline at end of file
diff --git a/version3/c/rom_field_512PM.c b/version3/c/rom_field_512PM.c
new file mode 100644
index 0000000..d305f50
--- /dev/null
+++ b/version3/c/rom_field_512PM.c
@@ -0,0 +1,25 @@
+#include "arch.h"
+#include "fp_512PM.h"
+
+/* NUMS 512-bit modulus */
+
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+// Base Bits= 29
+const BIG_512_29 Modulus_512PM= {0x1FFFFDC7,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF};
+const BIG_512_29 R2modp_512PM= {0xB100000,0x278,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const chunk MConst_512PM= 0x239;
+#endif
+
+#if CHUNK==64
+// Base Bits= 56
+const BIG_512_56 Modulus_512PM= {0xFFFFFFFFFFFDC7L,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFL};
+const BIG_512_56 R2modp_512PM= {0x0L,0xF0B10000000000L,0x4L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const chunk MConst_512PM= 0x239L;
+#endif
\ No newline at end of file
diff --git a/version3/c/rom_field_ANSSI.c b/version3/c/rom_field_ANSSI.c
new file mode 100644
index 0000000..be52634
--- /dev/null
+++ b/version3/c/rom_field_ANSSI.c
@@ -0,0 +1,25 @@
+#include "arch.h"
+#include "fp_ANSSI.h"
+
+/* ANNSI Curve */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+// Base Bits= 28
+const BIG_256_28 Modulus_ANSSI= {0x86E9C03,0xFCF353D,0x8CA6DE8,0xADBCABC,0x35B3961,0xE8CE424,0xF10126D,0xB3AD58,0x1FD178C,0xF};
+const BIG_256_28 R2modp_ANSSI= {0x288CC9C,0x18D2374,0x646BD2B,0x4929E67,0xD6F7F2D,0x220E6C1,0xABCE02E,0x751B1FD,0x7401B78,0xE};
+const chunk MConst_ANSSI= 0x64E1155;
+#endif
+
+#if CHUNK==64
+// Base Bits= 56
+const BIG_256_56 Modulus_ANSSI= {0xFCF353D86E9C03L,0xADBCABC8CA6DE8L,0xE8CE42435B3961L,0xB3AD58F10126DL,0xF1FD178CL};
+const BIG_256_56 R2modp_ANSSI= {0x18D2374288CC9CL,0x4929E67646BD2BL,0x220E6C1D6F7F2DL,0x751B1FDABCE02EL,0xE7401B78L};
+const chunk MConst_ANSSI= 0x97483A164E1155L;
+#endif
+
diff --git a/version3/c/rom_field_BLS24.c b/version3/c/rom_field_BLS24.c
new file mode 100644
index 0000000..efc25e9
--- /dev/null
+++ b/version3/c/rom_field_BLS24.c
@@ -0,0 +1,32 @@
+#include "arch.h"
+#include "fp_BLS24.h"
+
+/* Curve BLS24 - Pairing friendly BLS24 curve */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+// Base Bits= 29
+// Base Bits= 29
+const BIG_480_29 Modulus_BLS24= {0xA06152B,0x2260B3A,0xB4C36BE,0x5FFC5D0,0xBDB6A64,0x5B78E2E,0x1C1A28CA,0x10E6441B,0x1F244061,0xB4704F0,0x141E5CCD,0x9837504,0x3F2E77E,0xD763740,0x1316EA0E,0xF0079,0x555C};
+const BIG_480_29 R2modp_BLS24= {0x8533EA9,0x6A02789,0x183B24DE,0x1E45ECF8,0xC8F8F37,0x10CAD209,0x4C0C4B8,0x9B1FABD,0xDEBE4C0,0xDC353F9,0x18A18E26,0x10F489BB,0x31206A5,0x19673BBF,0x6BE69F9,0xB091169,0x9CD};
+const chunk MConst_BLS24= 0x95FE7D;
+const BIG_480_29 Fra_BLS24= {0x1BF96F1D,0xAE53A55,0x31BFEEB,0x183FF17A,0x6237469,0x12A4F4F1,0x12101FE3,0x16E79D94,0xFF59267,0x5EB4EB4,0x78CC49F,0x274BA33,0x149184F3,0x16C6DCBA,0x1C90B694,0x10F729CE,0x4BBC};
+const BIG_480_29 Frb_BLS24= {0xE0CA60E,0x1740D0E4,0x83037D2,0xDBFD456,0x5B7F5FA,0x1312993D,0xA0A08E6,0x19FEA687,0xF2EADF9,0x55BB63C,0xC91982E,0x70EBAD1,0xF61628B,0x16AF5A85,0x16863379,0xF17D6AA,0x99F};
+
+#endif
+
+#if CHUNK==64
+// Base Bits= 56
+const BIG_480_56 Modulus_BLS24= {0x44C1674A06152BL,0xFFE2E82D30DAF8L,0x6F1C5CBDB6A642L,0x3220DF068A328BL,0xE09E1F24406187L,0xBA825079733568L,0x6E803F2E77E4C1L,0x3CCC5BA839AECL,0x555C0078L};
+const BIG_480_56 R2modp_BLS24= {0x6A4A1FE013DF5BL,0xE8E46D4D1BDE65L,0x1F841391F45C67L,0x9148A4516FB28L,0x4398524EDF4C88L,0x41C0E241B6DCE8L,0xE42C208C19411L,0xA7FE6FD73A7B1CL,0xFCCCA76L};
+const chunk MConst_BLS24= 0xBD5D7D8095FE7DL;
+const BIG_480_56 Fra_BLS24= {0x5CA74ABBF96F1DL,0x1FF8BD0C6FFBADL,0x49E9E26237469CL,0x3CECA48407F8E5L,0x69D68FF59267B7L,0x5D199E33127CBDL,0xB97549184F313AL,0x4E77242DA52D8DL,0x4BBC87B9L};
+const BIG_480_56 Frb_BLS24= {0xE81A1C8E0CA60EL,0xDFEA2B20C0DF4AL,0x25327A5B7F5FA6L,0xF5343A828239A6L,0x76C78F2EADF9CFL,0x5D68B24660B8ABL,0xB50AF61628B387L,0xB555A18CDE6D5EL,0x99F78BEL};
+
+
+#endif
\ No newline at end of file
diff --git a/version3/c/rom_field_BLS381.c b/version3/c/rom_field_BLS381.c
new file mode 100644
index 0000000..39d22e2
--- /dev/null
+++ b/version3/c/rom_field_BLS381.c
@@ -0,0 +1,30 @@
+#include "arch.h"
+#include "fp_BLS381.h"
+
+/* Curve BLS381 - Pairing friendly BLS curve */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+// Base Bits= 29
+const BIG_384_29 Modulus_BLS381= {0x1FFFAAAB,0xFF7FFFF,0x14FFFFEE,0x17FFFD62,0xF6241EA,0x9507B58,0xAFD9CC3,0x109E70A2,0x1764774B,0x121A5D66,0x12C6E9ED,0x12FFCD34,0x111EA3,0xD};
+const BIG_384_29 R2modp_BLS381= {0x15BEF7AE,0x1031CD0E,0x2DD93E8,0x9226323,0xE6E2CD2,0x11684DAA,0x1170E5DB,0x88E25B1,0x1B366399,0x1C536F47,0xD1F9CBC,0x278B67F,0x1EA66A2B,0xC};
+const chunk MConst_BLS381= 0x1FFCFFFD;
+const BIG_384_29 Fra_BLS381= {0x12235FB8,0x83BAF6C,0x19E04F63,0x1D4A7AC7,0xB9C4F67,0x1EBC25D,0x1D3DEC91,0x1FA797AB,0x1F0FD603,0x1016068,0x108C6FAD,0x5760CCF,0x104D3BF0,0xC};
+const BIG_384_29 Frb_BLS381= {0xDDC4AF3,0x7BC5093,0x1B1FB08B,0x1AB5829A,0x3C5F282,0x764B8FB,0xDBFB032,0x10F6D8F6,0x1854A147,0x1118FCFD,0x23A7A40,0xD89C065,0xFC3E2B3,0x0};
+
+#endif
+
+#if CHUNK==64
+// Base Bits= 58
+const BIG_384_58 Modulus_BLS381= {0x1FEFFFFFFFFAAABL,0x2FFFFAC54FFFFEEL,0x12A0F6B0F6241EAL,0x213CE144AFD9CC3L,0x2434BACD764774BL,0x25FF9A692C6E9EDL,0x1A0111EA3L};
+const BIG_384_58 R2modp_BLS381= {0x20639A1D5BEF7AEL,0x1244C6462DD93E8L,0x22D09B54E6E2CD2L,0x111C4B63170E5DBL,0x38A6DE8FB366399L,0x4F16CFED1F9CBCL,0x19EA66A2BL};
+const chunk MConst_BLS381= 0x1F3FFFCFFFCFFFDL;
+const BIG_384_58 Fra_BLS381= {0x10775ED92235FB8L,0x3A94F58F9E04F63L,0x3D784BAB9C4F67L,0x3F4F2F57D3DEC91L,0x202C0D1F0FD603L,0xAEC199F08C6FADL,0x1904D3BF0L};
+const BIG_384_58 Frb_BLS381= {0xF78A126DDC4AF3L,0x356B0535B1FB08BL,0xEC971F63C5F282L,0x21EDB1ECDBFB032L,0x2231F9FB854A147L,0x1B1380CA23A7A40L,0xFC3E2B3L};
+
+#endif
diff --git a/version3/c/rom_field_BLS383.c b/version3/c/rom_field_BLS383.c
new file mode 100644
index 0000000..b197120
--- /dev/null
+++ b/version3/c/rom_field_BLS383.c
@@ -0,0 +1,30 @@
+#include "arch.h"
+#include "fp_BLS383.h"
+
+/* Curve BLS383 - Pairing friendly BLS curve */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+// Base Bits= 29
+const BIG_384_29 Modulus_BLS383= {0x5AAB0AB,0x11B8EB24,0x19214AF6,0x187E5314,0x124F47A8,0x1C00B4B0,0x1446B0C6,0x59E6CB4,0x4A0AD46,0xFF5494,0x81B6B71,0x956DD6B,0x16556956,0x2A};
+const BIG_384_29 R2modp_BLS383= {0x116907F4,0x405B700,0x1752AC11,0x67A9E7C,0x1941C581,0x1AEA38C4,0xB1E4D22,0xCE841AE,0xA0FC49B,0xB4B1F48,0x13852312,0x1B3FDCED,0x1FECE397,0x26};
+const chunk MConst_BLS383= 0x73435FD;
+const BIG_384_29 Fra_BLS383= {0x1311DAC1,0x296B969,0x19DCF806,0x126901FC,0xD8C8A36,0x1A2572A8,0xA1A0959,0x1A47F743,0x110E4C6C,0x1608DA97,0xCE2E7F0,0x4FED178,0xACD5BF0,0x11};
+const BIG_384_29 Frb_BLS383= {0x1298D5EA,0xF2231BA,0x1F4452F0,0x6155117,0x4C2BD72,0x1DB4208,0xA2CA76D,0xB567571,0x139260D9,0xAF679FC,0x1B388380,0x4580BF2,0xB880D66,0x19};
+
+#endif
+
+#if CHUNK==64
+// Base Bits= 58
+const BIG_384_58 Modulus_BLS383= {0x2371D6485AAB0ABL,0x30FCA6299214AF6L,0x3801696124F47A8L,0xB3CD969446B0C6L,0x1FEA9284A0AD46L,0x12ADBAD681B6B71L,0x556556956L};
+const BIG_384_58 R2modp_BLS383= {0x80B6E0116907F4L,0xCF53CF9752AC11L,0x35D47189941C581L,0x19D0835CB1E4D22L,0x16963E90A0FC49BL,0x367FB9DB3852312L,0x4DFECE397L};
+const chunk MConst_BLS383= 0x1BC0571073435FDL;
+const BIG_384_58 Fra_BLS383= {0x52D72D3311DAC1L,0x24D203F99DCF806L,0x344AE550D8C8A36L,0x348FEE86A1A0959L,0x2C11B52F10E4C6CL,0x9FDA2F0CE2E7F0L,0x22ACD5BF0L};
+const BIG_384_58 Frb_BLS383= {0x1E446375298D5EAL,0xC2AA22FF4452F0L,0x3B684104C2BD72L,0x16ACEAE2A2CA76DL,0x15ECF3F939260D9L,0x8B017E5B388380L,0x32B880D66L};
+
+#endif
\ No newline at end of file
diff --git a/version3/c/rom_field_BLS461.c b/version3/c/rom_field_BLS461.c
new file mode 100644
index 0000000..c2e561a
--- /dev/null
+++ b/version3/c/rom_field_BLS461.c
@@ -0,0 +1,31 @@
+#include "arch.h"
+#include "fp_BLS461.h"
+
+/* Curve BLS461 - Pairing friendly BLS curve */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+// Base Bits= 28
+const BIG_464_28 Modulus_BLS461= {0xAAAAAAB,0xAC0000A,0x54AAAAA,0x5555,0x400020,0x91557F0,0xF26AA,0xFA5C1CC,0xB42A8DF,0x7B14848,0x8BACCA4,0x6F1E32D,0x4935FBD,0x55D6941,0xD5A555A,0x5545554,0x1555};
+const BIG_464_28 R2modp_BLS461= {0xC9B6A33,0x2ECD087,0x3CCB2B1,0xCD461FE,0x8CB5AB2,0xC5B9635,0x5312E92,0xB659F64,0x3B596FA,0x8679006,0xA92E2B3,0x3CE05E3,0x363550F,0x7C07A8E,0x382C083,0x6347FEA,0xBD};
+const chunk MConst_BLS461= 0xFFFFFFD;
+const BIG_464_28 Fra_BLS461= {0xB812A3A,0x7117BF9,0x99C400F,0xC6308A5,0x5BF8A1,0x510E075,0x45FA5A6,0xCE4858D,0x770B31A,0xBC2CB04,0xE2FC61E,0xD073588,0x4366190,0x4DFEFA8,0x69E55E2,0x504B7F,0x12E4};
+const BIG_464_28 Frb_BLS461= {0xF298071,0x3AE8410,0xBAE6A9B,0x39D4CAF,0xFE4077E,0x404777A,0xBAF8104,0x2C13C3E,0x3D1F5C5,0xBEE7D44,0xA8B0685,0x9EAADA4,0x5CFE2C,0x7D7999,0x6BBFF78,0x50409D5,0x271};
+
+#endif
+
+#if CHUNK==64
+// Base Bits=60
+const BIG_464_60 Modulus_BLS461= {0xAAC0000AAAAAAABL,0x20000555554AAAAL,0x6AA91557F004000L,0xA8DFFA5C1CC00F2L,0xACCA47B14848B42L,0x935FBD6F1E32D8BL,0xD5A555A55D69414L,0x15555545554L};
+const BIG_464_60 R2modp_BLS461= {0x96D08774614DDA8L,0xCD45F539225D5BDL,0xD712EB760C95AB1L,0xB3B687155F30B55L,0xC4E62A05C3F5B81L,0xBA1151676CA3CD0L,0x7EDD8A958F442BEL,0x12B89DD3F91L};
+const chunk MConst_BLS461= 0xC0005FFFFFFFDL;
+const BIG_464_60 Fra_BLS461= {0xF7117BF9B812A3AL,0xA1C6308A599C400L,0x5A6510E07505BF8L,0xB31ACE4858D45FAL,0xFC61EBC2CB04770L,0x366190D073588E2L,0x69E55E24DFEFA84L,0x12E40504B7FL};
+const BIG_464_60 Frb_BLS461= {0xB3AE8410F298071L,0x7E39D4CAFBAE6A9L,0x104404777AFE407L,0xF5C52C13C3EBAF8L,0xB0685BEE7D443D1L,0x5CFE2C9EAADA4A8L,0x6BBFF7807D79990L,0x27150409D5L};
+
+
+#endif
\ No newline at end of file
diff --git a/version3/c/rom_field_BLS48.c b/version3/c/rom_field_BLS48.c
new file mode 100644
index 0000000..5bf4488
--- /dev/null
+++ b/version3/c/rom_field_BLS48.c
@@ -0,0 +1,32 @@
+#include "arch.h"
+#include "fp_BLS48.h"
+
+/* Curve BLS48 - Pairing friendly BLS48 curve */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+// Base Bits= 29
+const BIG_560_29 Modulus_BLS48= {0x1CF6AC0B,0x17B7307F,0x19877E7B,0x12CE0134,0x14228402,0x1BD4C386,0x1DACBB04,0x40410D0,0x25A415,0x980B53E,0xDE6E250,0x15D9AAD6,0x5DA950,0x1029B7A,0x54AB351,0x14AD90CE,0x3729047,0x1FE7E2D9,0x145F610B,0x1F};
+const BIG_560_29 R2modp_BLS48= {0xD59D0FA,0x12F01FD0,0xDE8FD41,0x35AAEE1,0xB937F48,0x50700E8,0x1F50EFCE,0x1019B13C,0x3470A2F,0x11094115,0xF9FB72D,0x6AD10E2,0x1CFD9F8,0x44F4785,0x2B48793,0x1148ED3,0xF609E61,0x1EE34BC7,0x1735D29E,0x0};
+const chunk MConst_BLS48= 0x9DA805D;
+const BIG_560_29 Fra_BLS48= {0x1325BF89,0x1311E7EC,0xCD0A56F,0x1A0FD46E,0xE83BCCA,0xCA97DD0,0x18D1D297,0x5F1E137,0x7AB9F2C,0x13FC255F,0x1C9DECEB,0x9DEF4A2,0x3C0F60B,0x1D9909E4,0x1FF27FF7,0x1DBF8208,0x89BB36C,0x40044E0,0x62E01EE,0x5};
+const BIG_560_29 Frb_BLS48= {0x1325BF89,0x1311E7EC,0xCD0A56F,0x1A0FD46E,0xE83BCCA,0xCA97DD0,0x18D1D297,0x5F1E137,0x7AB9F2C,0x13FC255F,0x1C9DECEB,0x9DEF4A2,0x3C0F60B,0x1D9909E4,0x1FF27FF7,0x1DBF8208,0x89BB36C,0x40044E0,0x62E01EE,0x5};
+
+#endif
+
+#if CHUNK==64
+
+// Base Bits= 58
+const BIG_560_58 Modulus_BLS48= {0x2F6E60FFCF6AC0BL,0x259C02699877E7BL,0x37A9870D4228402L,0x80821A1DACBB04L,0x13016A7C025A415L,0x2BB355ACDE6E250L,0x20536F405DA950L,0x295B219C54AB351L,0x3FCFC5B23729047L,0x3F45F610BL};
+const BIG_560_58 R2modp_BLS48= {0x25E03FA0D59D0FAL,0x6B55DC2DE8FD41L,0xA0E01D0B937F48L,0x20336279F50EFCEL,0x2212822A3470A2FL,0xD5A21C4F9FB72DL,0x89E8F0A1CFD9F8L,0x2291DA62B48793L,0x3DC6978EF609E61L,0x1735D29EL};
+const chunk MConst_BLS48= 0x21BFCBCA9DA805DL;
+const BIG_560_58 Fra_BLS48= {0x2623CFD9325BF89L,0x341FA8DCCD0A56FL,0x1952FBA0E83BCCAL,0xBE3C26F8D1D297L,0x27F84ABE7AB9F2CL,0x13BDE945C9DECEBL,0x3B3213C83C0F60BL,0x3B7F0411FF27FF7L,0x80089C089BB36CL,0xA62E01EEL};
+const BIG_560_58 Frb_BLS48= {0x2623CFD9325BF89L,0x341FA8DCCD0A56FL,0x1952FBA0E83BCCAL,0xBE3C26F8D1D297L,0x27F84ABE7AB9F2CL,0x13BDE945C9DECEBL,0x3B3213C83C0F60BL,0x3B7F0411FF27FF7L,0x80089C089BB36CL,0xA62E01EEL};
+
+#endif
\ No newline at end of file
diff --git a/version3/c/rom_field_BN254.c b/version3/c/rom_field_BN254.c
new file mode 100644
index 0000000..c244a87
--- /dev/null
+++ b/version3/c/rom_field_BN254.c
@@ -0,0 +1,37 @@
+#include "arch.h"
+#include "fp_BN254.h"
+
+/* Curve BN254 - Pairing friendly BN curve */
+
+/* Nogami's fast curve */
+
+#if CHUNK==16
+
+// Base Bits= 13
+const BIG_256_13 Modulus_BN254= {0x13,0x0,0x0,0x0,0x1A70,0x9,0x0,0x0,0x100,0x309,0x2,0x0,0x1800,0x1A26,0x6E8,0x0,0x0,0x412,0x8D9,0x4A};
+const BIG_256_13 R2modp_BN254= {0xF32,0x239,0x14DC,0xCE8,0x928,0x11B6,0x130F,0x1183,0x56E,0x1AEE,0x124F,0xD2A,0x7F8,0x1CE6,0x1B50,0x77C,0x3A,0x1A9E,0x1EFD,0x1C};
+const chunk MConst_BN254= 0x15E5;
+const BIG_256_13 Fra_BN254= {0xDE9,0x1953,0x101B,0x1BCD,0xE17,0x1BE1,0x14FD,0x1249,0x974,0x1C28,0x54F,0x108D,0x150A,0x4CD,0x12D9,0xF91,0x12E,0x10C9,0xDDD,0x36};
+const BIG_256_13 Frb_BN254= {0x122A,0x6AC,0xFE4,0x432,0xC58,0x428,0xB02,0xDB6,0x178B,0x6E0,0x1AB2,0xF72,0x2F5,0x1559,0x140F,0x106E,0x1ED1,0x1348,0x1AFB,0x13};
+
+#endif
+
+#if CHUNK==32
+// Base Bits= 28
+const BIG_256_28 Modulus_BN254= {0x13,0x0,0x13A7,0x0,0x86121,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2};
+const BIG_256_28 R2modp_BN254= {0xF5E7E39,0x2F2A96F,0xB96F13C,0x64E8642,0xC7146,0x9926F7B,0x4DACD24,0x8321E7B,0xD127A2E,0x1};
+const chunk MConst_BN254= 0x79435E5;
+const BIG_256_28 Fra_BN254= {0xF2A6DE9,0x7DE6C06,0xF77C2E1,0x74924D3,0x53F8509,0x50A8469,0xCB6499B,0x212E7C8,0xB377619,0x1};
+const BIG_256_28 Frb_BN254= {0xD5922A,0x82193F9,0x8850C5,0x8B6DB2C,0xAC8DC17,0x2F57B96,0x503EAB2,0x1ED1837,0x9EBEE69,0x0};
+
+#endif
+
+#if CHUNK==64
+// Base Bits= 56
+const BIG_256_56 Modulus_BN254= {0x13L,0x13A7L,0x80000000086121L,0x40000001BA344DL,0x25236482L};
+const BIG_256_56 R2modp_BN254= {0x2F2A96FF5E7E39L,0x64E8642B96F13CL,0x9926F7B00C7146L,0x8321E7B4DACD24L,0x1D127A2EL};
+const chunk MConst_BN254= 0x435E50D79435E5L;
+const BIG_256_56 Fra_BN254= {0x7DE6C06F2A6DE9L,0x74924D3F77C2E1L,0x50A846953F8509L,0x212E7C8CB6499BL,0x1B377619L};
+const BIG_256_56 Frb_BN254= {0x82193F90D5922AL,0x8B6DB2C08850C5L,0x2F57B96AC8DC17L,0x1ED1837503EAB2L,0x9EBEE69L};
+#endif
+
diff --git a/version3/c/rom_field_BN254CX.c b/version3/c/rom_field_BN254CX.c
new file mode 100644
index 0000000..1209f0c
--- /dev/null
+++ b/version3/c/rom_field_BN254CX.c
@@ -0,0 +1,38 @@
+#include "arch.h"
+#include "fp_BN254CX.h"
+
+/* Curve BN254CX - Pairing friendly BN curve */
+
+/* CertiVox BN curve/field  */
+
+#if CHUNK==16
+
+// Base Bits= 13
+const BIG_256_13 Modulus_BN254CX= {0x15B3,0xDA,0x1BD7,0xC47,0x1BE6,0x1F70,0x24,0x1DC3,0x1FD6,0x1921,0x19B4,0x14C6,0x1647,0x1EEF,0x16C2,0x541,0x870,0x0,0x0,0x48};
+const BIG_256_13 R2modp_BN254CX= {0x1527,0x146B,0x12A7,0x1A60,0x1E0A,0x1382,0x2BC,0x1D3F,0xB30,0xA8,0xD19,0x11AB,0x1D40,0x1965,0xD6D,0x643,0x10FF,0x1BC7,0x1E61,0x31};
+const chunk MConst_BN254CX= 0x1E85;
+const BIG_256_13 Fra_BN254CX= {0xEA3,0xE40,0xCD5,0x1210,0x15BD,0x1C10,0x5CF,0x4DE,0x773,0x343,0x626,0x194E,0x18AA,0x10C5,0x12BF,0x2C,0x63A,0x17D,0x1642,0x26};
+const BIG_256_13 Frb_BN254CX= {0x710,0x129A,0xF01,0x1A37,0x628,0x360,0x1A55,0x18E4,0x1863,0x15DE,0x138E,0x1B78,0x1D9C,0xE29,0x403,0x515,0x236,0x1E83,0x9BD,0x21};
+
+
+#endif
+
+#if CHUNK==32
+// Base Bits= 28
+const BIG_256_28 Modulus_BN254CX= {0xC1B55B3,0x6623EF5,0x93EE1BE,0xD6EE180,0x6D3243F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2};
+const BIG_256_28 R2modp_BN254CX= {0x8A0800A,0x466A061,0x43056A3,0x2B3A225,0x9C6600,0x148515B,0x6BDF50,0xEC9EA56,0xC992E66,0x1};
+const chunk MConst_BN254CX= 0x9789E85;
+const BIG_256_28 Fra_BN254CX= {0x5C80EA3,0xD908335,0x3F8215B,0x7326F17,0x8986867,0x8AACA71,0x4AFE18B,0xA63A016,0x359082F,0x1};
+const BIG_256_28 Frb_BN254CX= {0x6534710,0x8D1BBC0,0x546C062,0x63C7269,0xE3ABBD8,0xD9CDBC4,0x900DC53,0x623628A,0xA6F7D0,0x1};
+
+#endif
+
+#if CHUNK==64
+// Base Bits= 56
+const BIG_256_56 Modulus_BN254CX= {0x6623EF5C1B55B3L,0xD6EE18093EE1BEL,0x647A6366D3243FL,0x8702A0DB0BDDFL,0x24000000L};
+const BIG_256_56 R2modp_BN254CX= {0x466A0618A0800AL,0x2B3A22543056A3L,0x148515B09C6600L,0xEC9EA5606BDF50L,0x1C992E66L};
+const chunk MConst_BN254CX= 0x4E205BF9789E85L;
+const BIG_256_56 Fra_BN254CX= {0xD9083355C80EA3L,0x7326F173F8215BL,0x8AACA718986867L,0xA63A0164AFE18BL,0x1359082FL};
+const BIG_256_56 Frb_BN254CX= {0x8D1BBC06534710L,0x63C7269546C062L,0xD9CDBC4E3ABBD8L,0x623628A900DC53L,0x10A6F7D0L};
+#endif
+
diff --git a/version3/c/rom_field_BRAINPOOL.c b/version3/c/rom_field_BRAINPOOL.c
new file mode 100644
index 0000000..bc73330
--- /dev/null
+++ b/version3/c/rom_field_BRAINPOOL.c
@@ -0,0 +1,25 @@
+#include "arch.h"
+#include "fp_BRAINPOOL.h"
+
+/* Brainpool Modulus  */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+// Base Bits= 28
+const BIG_256_28 Modulus_BRAINPOOL= {0xF6E5377,0x13481D1,0x6202820,0xF623D52,0xD726E3B,0x909D838,0xC3E660A,0xA1EEA9B,0x9FB57DB,0xA};
+const BIG_256_28 R2modp_BRAINPOOL= {0xB9A3787,0x9E04F49,0x8F3CF49,0x2931721,0xF1DBC89,0x54E8C3C,0xF7559CA,0xBB411A3,0x773E15F,0x9};
+const chunk MConst_BRAINPOOL= 0xEFD89B9;
+#endif
+
+#if CHUNK==64
+// Base Bits= 56
+const BIG_256_56 Modulus_BRAINPOOL= {0x13481D1F6E5377L,0xF623D526202820L,0x909D838D726E3BL,0xA1EEA9BC3E660AL,0xA9FB57DBL};
+const BIG_256_56 R2modp_BRAINPOOL= {0x9E04F49B9A3787L,0x29317218F3CF49L,0x54E8C3CF1DBC89L,0xBB411A3F7559CAL,0x9773E15FL};
+const chunk MConst_BRAINPOOL= 0xA75590CEFD89B9L;
+#endif
+
diff --git a/version3/c/rom_field_C41417.c b/version3/c/rom_field_C41417.c
new file mode 100644
index 0000000..e28f42c
--- /dev/null
+++ b/version3/c/rom_field_C41417.c
@@ -0,0 +1,25 @@
+#include "arch.h"
+#include "fp_C41417.h"
+
+/* Curve C41417 */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+// Base Bits= 29
+const BIG_416_29 Modulus_C41417= {0x1FFFFFEF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFF};
+const BIG_416_29 R2modp_C41417= {0x0,0x242000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const chunk MConst_C41417= 0x11;
+#endif
+
+#if CHUNK==64
+// Base Bits= 60
+const BIG_416_60 Modulus_C41417= {0xFFFFFFFFFFFFFEFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFL};
+const BIG_416_60 R2modp_C41417= {0x121000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const chunk MConst_C41417= 0x11L;
+#endif
+
diff --git a/version3/c/rom_field_FP256BN.c b/version3/c/rom_field_FP256BN.c
new file mode 100644
index 0000000..8174955
--- /dev/null
+++ b/version3/c/rom_field_FP256BN.c
@@ -0,0 +1,36 @@
+#include "arch.h"
+#include "fp_FP256BN.h"
+
+/* Curve FP256BN - Pairing friendly BN curve */
+
+/* ISO fast curve */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+// Base Bits= 28
+
+const BIG_256_28 Modulus_FP256BN= {0xED33013,0x292DDBA,0x80A82D3,0x65FB129,0x49F0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF};
+const BIG_256_28 R2modp_FP256BN= {0x3B9F8B,0xEDE3363,0xFEC54E8,0x92FFEE9,0x3C55F79,0x13C1C06,0xC0123FA,0xA12F2EA,0xE559B2A,0x8};
+const chunk MConst_FP256BN= 0x537E5E5;
+const BIG_256_28 Fra_FP256BN= {0xF943106,0x760328A,0xAB28F74,0x71511E3,0x7CF39A1,0x8DDB086,0x52D1A6E,0xCA786F3,0xD617662,0x3};
+const BIG_256_28 Frb_FP256BN= {0xF3EFF0D,0xB32AB2F,0xD57F35E,0xF4A9F45,0xCCFD33A,0xD113693,0x819CB83,0x3584819,0x29E899D,0xC};
+
+
+#endif
+
+#if CHUNK==64
+// Base Bits= 56
+const BIG_256_56 Modulus_FP256BN= {0x292DDBAED33013L,0x65FB12980A82D3L,0x5EEE71A49F0CDCL,0xFFFCF0CD46E5F2L,0xFFFFFFFFL};
+const BIG_256_56 R2modp_FP256BN= {0xEDE336303B9F8BL,0x92FFEE9FEC54E8L,0x13C1C063C55F79L,0xA12F2EAC0123FAL,0x8E559B2AL};
+const chunk MConst_FP256BN= 0x6C964E0537E5E5L;
+const BIG_256_56 Fra_FP256BN= {0x760328AF943106L,0x71511E3AB28F74L,0x8DDB0867CF39A1L,0xCA786F352D1A6EL,0x3D617662L};
+const BIG_256_56 Frb_FP256BN= {0xB32AB2FF3EFF0DL,0xF4A9F45D57F35EL,0xD113693CCFD33AL,0x3584819819CB83L,0xC29E899DL};
+
+
+#endif
+
diff --git a/version3/c/rom_field_FP512BN.c b/version3/c/rom_field_FP512BN.c
new file mode 100644
index 0000000..e88f66a
--- /dev/null
+++ b/version3/c/rom_field_FP512BN.c
@@ -0,0 +1,38 @@
+#include "arch.h"
+#include "fp_FP512BN.h"
+
+/* Curve FP512BN - Pairing friendly BN curve */
+
+/* ISO fast curve */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+// Base Bits= 29
+
+const BIG_512_29 Modulus_FP512BN= {0x2ADEF33,0x7594049,0x131919ED,0x14AB9CBE,0x16FE1916,0x12EF5591,0x2E39231,0x3D597D3,0x55146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF};
+const BIG_512_29 R2modp_FP512BN= {0xFD68B47,0xFCF5D2C,0x437675A,0x1BBC3FBF,0x1411E413,0x13453559,0x10B5639,0x1C34CE79,0x6D476BF,0xFD05F2B,0x15D17C28,0x6C9F76E,0x1C2375B3,0x78CCE9B,0x15F0AB33,0x1960F32E,0x1A8D44E,0x57A38};
+const chunk MConst_FP512BN= 0x1CCC5C05;
+const BIG_512_29 Fra_FP512BN= {0x14B73AB2,0x4B0BD8F,0xABB47D,0x2A29EC4,0x18681E17,0x104069DE,0x12EED67D,0x1553D0A5,0x398E9F8,0x7971034,0xAC9AF23,0x52DEF23,0x14EA18A5,0x1463E345,0x6DE465A,0x17F212B4,0x1AA9CF5B,0xF7B8};
+const BIG_512_29 Frb_FP512BN= {0xDF6B481,0x2A882B9,0x126D6570,0x1208FDFA,0x1E95FAFF,0x2AEEBB2,0xFF4BBB4,0xE81C72D,0x1B85CD6,0xF67746,0x56549CD,0xC68B6EC,0x776A178,0x8925C3B,0x1921B9A5,0x80DED4B,0x55630A4,0x70847};
+
+
+
+#endif
+
+#if CHUNK==64
+// Base Bits= 60
+
+const BIG_512_60 Modulus_FP512BN= {0x4EB280922ADEF33L,0x6A55CE5F4C6467BL,0xC65DEAB236FE191L,0xCF1EACBE98B8E48L,0x3C111B0EF455146L,0xA1D8CB5307C0BBEL,0xFFFF9EC7F01C60BL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFL};
+const BIG_512_60 R2modp_FP512BN= {0x1FA6DCEF99812E9L,0xAB3452895A0B74EL,0xC53EA988C079E1EL,0x1E90E033BA630B9L,0xF1EA41C0714D8B0L,0xE72785387509E28L,0xD86794F834DAB00L,0x9757C2ACCD342A1L,0x44ECB079L};
+const chunk MConst_FP512BN= 0x692A189FCCC5C05L;
+const BIG_512_60 Fra_FP512BN= {0x49617B1F4B73AB2L,0x71514F6202AED1FL,0xF6080D3BD8681E1L,0xF8AA9E852CBBB59L,0xC8CF2E2068398E9L,0x8A5296F791AB26BL,0x196A8C7C68B4EA1L,0xCF5BBF9095A1B79L,0x1EF71AA9L};
+const BIG_512_60 Frb_FP512BN= {0x5510572DF6B481L,0xF9047EFD49B595CL,0xD055DD765E95FAFL,0xD6740E396BFD2EEL,0x7341ECEE8C1B85CL,0x1786345B7615952L,0xE695124B876776AL,0x30A4406F6A5E486L,0xE108E556L};
+
+
+#endif
+
diff --git a/version3/c/rom_field_GOLDILOCKS.c b/version3/c/rom_field_GOLDILOCKS.c
new file mode 100644
index 0000000..2a1785e
--- /dev/null
+++ b/version3/c/rom_field_GOLDILOCKS.c
@@ -0,0 +1,30 @@
+#include "arch.h"
+#include "fp_GOLDILOCKS.h"
+
+/* Curve GOLDILOCKS */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+// Base Bits= 29
+const BIG_448_29 Modulus_GOLDILOCKS= {0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FDFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFF};
+const BIG_448_29 R2modp_GOLDILOCKS= {0x0,0x10,0x0,0x0,0x0,0x0,0x0,0x0,0x3000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const chunk MConst_GOLDILOCKS= 0x1;
+
+#endif
+
+#if CHUNK==64
+// Base Bits= 58
+const BIG_448_58 Modulus_GOLDILOCKS= {0x3FFFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFFL,0x3FBFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFFL,0x3FFFFFFFFFFL};
+const BIG_448_58 R2modp_GOLDILOCKS= {0x200000000L,0x0L,0x0L,0x0L,0x3000000L,0x0L,0x0L,0x0L};
+const chunk MConst_GOLDILOCKS= 0x1L;
+
+
+#endif
+
+
diff --git a/version3/c/rom_field_HIFIVE.c b/version3/c/rom_field_HIFIVE.c
new file mode 100644
index 0000000..097dcec
--- /dev/null
+++ b/version3/c/rom_field_HIFIVE.c
@@ -0,0 +1,27 @@
+#include "arch.h"
+#include "fp_HIFIVE.h"
+
+/* Curve HIFIVE */
+
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+// Base Bits= 29
+const BIG_336_29 Modulus_HIFIVE= {0x1FFFFFFD,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFF};
+const BIG_336_29 R2modp_HIFIVE= {0x9000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const chunk MConst_HIFIVE= 0x3;
+#endif
+
+#if CHUNK==64
+// Base Bits= 60
+const BIG_336_60 Modulus_HIFIVE= {0xFFFFFFFFFFFFFFDL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFL};
+const BIG_336_60 R2modp_HIFIVE= {0x9000000000000L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const chunk MConst_HIFIVE= 0x3L;
+#endif
+
+
diff --git a/version3/c/rom_field_NIST256.c b/version3/c/rom_field_NIST256.c
new file mode 100644
index 0000000..b5a7187
--- /dev/null
+++ b/version3/c/rom_field_NIST256.c
@@ -0,0 +1,27 @@
+#include "arch.h"
+#include "fp_NIST256.h"
+
+/* Curve NIST256 */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+// Base Bits= 28
+const BIG_256_28 Modulus_NIST256= {0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFF,0x0,0x0,0x1000000,0x0,0xFFFFFFF,0xF};
+const BIG_256_28 R2modp_NIST256= {0x50000,0x300000,0x0,0x0,0xFFFFFFA,0xFFFFFBF,0xFFFFEFF,0xFFFAFFF,0x2FFFF,0x0};
+const chunk MConst_NIST256= 0x1;
+#endif
+
+#if CHUNK==64
+
+// Base Bits= 56
+const BIG_256_56 Modulus_NIST256= {0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFL,0x0L,0x1000000L,0xFFFFFFFFL};
+const BIG_256_56 R2modp_NIST256= {0x3000000050000L,0x0L,0xFFFFFBFFFFFFFAL,0xFFFAFFFFFFFEFFL,0x2FFFFL};
+const chunk MConst_NIST256= 0x1L;
+
+#endif
+
diff --git a/version3/c/rom_field_NIST384.c b/version3/c/rom_field_NIST384.c
new file mode 100644
index 0000000..a739ae3
--- /dev/null
+++ b/version3/c/rom_field_NIST384.c
@@ -0,0 +1,27 @@
+#include "arch.h"
+#include "fp_NIST384.h"
+
+/* Curve NIST384 */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+// Base Bits= 29
+const BIG_384_29 Modulus_NIST384= {0x1FFFFFFF,0x7,0x0,0x1FFFFE00,0x1FFFEFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F};
+const BIG_384_29 R2modp_NIST384= {0x0,0x8000,0x1FF80000,0x1FFFFF,0x2000000,0x0,0x0,0x1FFFFFFC,0xF,0x100,0x400,0x0,0x0,0x0};
+const chunk MConst_NIST384= 0x1;
+#endif
+
+#if CHUNK==64
+// Base Bits= 56
+const BIG_384_56 Modulus_NIST384= {0xFFFFFFFFL,0xFFFF0000000000L,0xFFFFFFFFFEFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFL};
+const BIG_384_56 R2modp_NIST384= {0xFE000000010000L,0xFFFFFFL,0x2L,0xFFFFFFFE00L,0x1000000020000L,0x0L,0x0L};
+const chunk MConst_NIST384= 0x100000001L;
+
+#endif
+
+
diff --git a/version3/c/rom_field_NIST521.c b/version3/c/rom_field_NIST521.c
new file mode 100644
index 0000000..048f9ac
--- /dev/null
+++ b/version3/c/rom_field_NIST521.c
@@ -0,0 +1,25 @@
+#include "arch.h"
+#include "fp_NIST521.h"
+
+/* Curve NIST521 */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+// Base Bits= 28
+const BIG_528_28 Modulus_NIST521= {0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0x1FFFF};
+const BIG_528_28 R2modp_NIST521= {0x400000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const chunk MConst_NIST521= 0x1;
+#endif
+
+#if CHUNK==64
+// Base Bits= 60
+const BIG_528_60 Modulus_NIST521= {0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0x1FFFFFFFFFFL};
+const BIG_528_60 R2modp_NIST521= {0x4000000000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const chunk MConst_NIST521= 0x1L;
+#endif
+
diff --git a/version3/c/rom_field_SECP256K1.c b/version3/c/rom_field_SECP256K1.c
new file mode 100644
index 0000000..4f80178
--- /dev/null
+++ b/version3/c/rom_field_SECP256K1.c
@@ -0,0 +1,28 @@
+#include "arch.h"
+#include "fp_SECP256K1.h"
+
+/* Curve SECP256K1 */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+// Base Bits= 28
+const BIG_256_28 Modulus_SECP256K1= {0xFFFFC2F,0xFFFFFEF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xF};
+const BIG_256_28 R2modp_SECP256K1= {0x0,0xA100000,0x2000E90,0x7A,0x1,0x0,0x0,0x0,0x0,0x0};
+const chunk MConst_SECP256K1= 0x2253531;
+
+#endif
+
+#if CHUNK==64
+
+// Base Bits= 56
+const BIG_256_56 Modulus_SECP256K1= {0xFFFFFEFFFFFC2FL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFL};
+const BIG_256_56 R2modp_SECP256K1= {0xA1000000000000L,0x7A2000E90L,0x1L,0x0L,0x0L};
+const chunk MConst_SECP256K1= 0x38091DD2253531L;
+
+#endif
+
diff --git a/version3/c/rsa.c b/version3/c/rsa.c
new file mode 100644
index 0000000..bbe41b2
--- /dev/null
+++ b/version3/c/rsa.c
@@ -0,0 +1,162 @@
+/*
+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.
+*/
+
+/* RSA Functions - see main program below */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "rsa_WWW.h"
+#include "rsa_support.h"
+
+/* generate an RSA key pair */
+void RSA_WWW_KEY_PAIR(csprng *RNG,sign32 e,rsa_private_key_WWW *PRIV,rsa_public_key_WWW *PUB,octet *P, octet* Q)
+{
+    /* IEEE1363 A16.11/A16.12 more or less */
+    BIG_XXX t[HFLEN_WWW],p1[HFLEN_WWW],q1[HFLEN_WWW];
+
+    if (RNG!=NULL)
+    {
+
+        for (;;)
+        {
+
+            FF_WWW_random(PRIV->p,RNG,HFLEN_WWW);
+            while (FF_WWW_lastbits(PRIV->p,2)!=3) FF_WWW_inc(PRIV->p,1,HFLEN_WWW);
+            while (!FF_WWW_prime(PRIV->p,RNG,HFLEN_WWW))
+                FF_WWW_inc(PRIV->p,4,HFLEN_WWW);
+
+            FF_WWW_copy(p1,PRIV->p,HFLEN_WWW);
+            FF_WWW_dec(p1,1,HFLEN_WWW);
+
+            if (FF_WWW_cfactor(p1,e,HFLEN_WWW)) continue;
+            break;
+        }
+
+        for (;;)
+        {
+            FF_WWW_random(PRIV->q,RNG,HFLEN_WWW);
+            while (FF_WWW_lastbits(PRIV->q,2)!=3) FF_WWW_inc(PRIV->q,1,HFLEN_WWW);
+            while (!FF_WWW_prime(PRIV->q,RNG,HFLEN_WWW))
+                FF_WWW_inc(PRIV->q,4,HFLEN_WWW);
+
+            FF_WWW_copy(q1,PRIV->q,HFLEN_WWW);
+            FF_WWW_dec(q1,1,HFLEN_WWW);
+            if (FF_WWW_cfactor(q1,e,HFLEN_WWW)) continue;
+
+            break;
+        }
+
+    }
+    else
+    {
+        FF_WWW_fromOctet(PRIV->p,P,HFLEN_WWW);
+        FF_WWW_fromOctet(PRIV->q,Q,HFLEN_WWW);
+
+        FF_WWW_copy(p1,PRIV->p,HFLEN_WWW);
+        FF_WWW_dec(p1,1,HFLEN_WWW);
+
+        FF_WWW_copy(q1,PRIV->q,HFLEN_WWW);
+        FF_WWW_dec(q1,1,HFLEN_WWW);
+    }
+
+    FF_WWW_mul(PUB->n,PRIV->p,PRIV->q,HFLEN_WWW);
+    PUB->e=e;
+
+    FF_WWW_copy(t,p1,HFLEN_WWW);
+    FF_WWW_shr(t,HFLEN_WWW);
+    FF_WWW_init(PRIV->dp,e,HFLEN_WWW);
+    FF_WWW_invmodp(PRIV->dp,PRIV->dp,t,HFLEN_WWW);
+    if (FF_WWW_parity(PRIV->dp)==0) FF_WWW_add(PRIV->dp,PRIV->dp,t,HFLEN_WWW);
+    FF_WWW_norm(PRIV->dp,HFLEN_WWW);
+
+    FF_WWW_copy(t,q1,HFLEN_WWW);
+    FF_WWW_shr(t,HFLEN_WWW);
+    FF_WWW_init(PRIV->dq,e,HFLEN_WWW);
+    FF_WWW_invmodp(PRIV->dq,PRIV->dq,t,HFLEN_WWW);
+    if (FF_WWW_parity(PRIV->dq)==0) FF_WWW_add(PRIV->dq,PRIV->dq,t,HFLEN_WWW);
+    FF_WWW_norm(PRIV->dq,HFLEN_WWW);
+
+    FF_WWW_invmodp(PRIV->c,PRIV->p,PRIV->q,HFLEN_WWW);
+
+    return;
+}
+
+/* destroy the Private Key structure */
+void RSA_WWW_PRIVATE_KEY_KILL(rsa_private_key_WWW *PRIV)
+{
+    FF_WWW_zero(PRIV->p,HFLEN_WWW);
+    FF_WWW_zero(PRIV->q,HFLEN_WWW);
+    FF_WWW_zero(PRIV->dp,HFLEN_WWW);
+    FF_WWW_zero(PRIV->dq,HFLEN_WWW);
+    FF_WWW_zero(PRIV->c,HFLEN_WWW);
+}
+
+void RSA_WWW_fromOctet(BIG_XXX x[],octet *w)
+{
+    FF_WWW_fromOctet(x,w,FFLEN_WWW);
+}
+
+/* RSA encryption with the public key */
+void RSA_WWW_ENCRYPT(rsa_public_key_WWW *PUB,octet *F,octet *G)
+{
+    BIG_XXX f[FFLEN_WWW];
+    FF_WWW_fromOctet(f,F,FFLEN_WWW);
+
+    FF_WWW_power(f,f,PUB->e,PUB->n,FFLEN_WWW);
+
+    FF_WWW_toOctet(G,f,FFLEN_WWW);
+}
+
+/* RSA decryption with the private key */
+void RSA_WWW_DECRYPT(rsa_private_key_WWW *PRIV,octet *G,octet *F)
+{
+    BIG_XXX g[FFLEN_WWW],t[FFLEN_WWW],jp[HFLEN_WWW],jq[HFLEN_WWW];
+
+    FF_WWW_fromOctet(g,G,FFLEN_WWW);
+
+    FF_WWW_dmod(jp,g,PRIV->p,HFLEN_WWW);
+    FF_WWW_dmod(jq,g,PRIV->q,HFLEN_WWW);
+
+    FF_WWW_skpow(jp,jp,PRIV->dp,PRIV->p,HFLEN_WWW);
+    FF_WWW_skpow(jq,jq,PRIV->dq,PRIV->q,HFLEN_WWW);
+
+
+    FF_WWW_zero(g,FFLEN_WWW);
+    FF_WWW_copy(g,jp,HFLEN_WWW);
+    FF_WWW_mod(jp,PRIV->q,HFLEN_WWW);
+    if (FF_WWW_comp(jp,jq,HFLEN_WWW)>0)
+        FF_WWW_add(jq,jq,PRIV->q,HFLEN_WWW);
+    FF_WWW_sub(jq,jq,jp,HFLEN_WWW);
+    FF_WWW_norm(jq,HFLEN_WWW);
+
+    FF_WWW_mul(t,PRIV->c,jq,HFLEN_WWW);
+    FF_WWW_dmod(jq,t,PRIV->q,HFLEN_WWW);
+
+    FF_WWW_mul(t,jq,PRIV->p,HFLEN_WWW);
+    FF_WWW_add(g,t,g,FFLEN_WWW);
+    FF_WWW_norm(g,FFLEN_WWW);
+
+    FF_WWW_toOctet(F,g,FFLEN_WWW);
+
+    return;
+}
+
diff --git a/version3/c/rsa.h b/version3/c/rsa.h
new file mode 100644
index 0000000..4d4c3c1
--- /dev/null
+++ b/version3/c/rsa.h
@@ -0,0 +1,110 @@
+/*
+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.
+*/
+
+/**
+ * @file rsa.h
+ * @author Mike Scott
+ * @brief RSA Header file for implementation of RSA protocol
+ *
+ * declares functions
+ *
+ */
+
+#ifndef RSA_WWW_H
+#define RSA_WWW_H
+
+#include "ff_WWW.h"
+#include "rsa_support.h"
+
+/*** START OF USER CONFIGURABLE SECTION -  ***/
+
+#define HASH_TYPE_RSA_WWW SHA256 /**< Chosen Hash algorithm */
+
+/*** END OF USER CONFIGURABLE SECTION ***/
+
+#define RFS_WWW MODBYTES_XXX*FFLEN_WWW /**< RSA Public Key Size in bytes */
+
+
+/**
+	@brief Integer Factorisation Public Key
+*/
+
+typedef struct
+{
+    sign32 e;     /**< RSA exponent (typically 65537) */
+    BIG_XXX n[FFLEN_WWW]; /**< An array of BIGs to store public key */
+} rsa_public_key_WWW;
+
+/**
+	@brief Integer Factorisation Private Key
+*/
+
+typedef struct
+{
+    BIG_XXX p[FFLEN_WWW/2];  /**< secret prime p  */
+    BIG_XXX q[FFLEN_WWW/2];  /**< secret prime q  */
+    BIG_XXX dp[FFLEN_WWW/2]; /**< decrypting exponent mod (p-1)  */
+    BIG_XXX dq[FFLEN_WWW/2]; /**< decrypting exponent mod (q-1)  */
+    BIG_XXX c[FFLEN_WWW/2];  /**< 1/p mod q */
+} rsa_private_key_WWW;
+
+/* RSA Auxiliary Functions */
+
+/**	@brief RSA Key Pair Generator
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param e the encryption exponent
+	@param PRIV the output RSA private key
+	@param PUB the output RSA public key
+        @param P Input prime number. Used when R is equal to NULL for testing
+        @param Q Inpuy prime number. Used when R is equal to NULL for testing
+ */
+extern void RSA_WWW_KEY_PAIR(csprng *R,sign32 e,rsa_private_key_WWW* PRIV,rsa_public_key_WWW* PUB,octet *P, octet* Q);
+
+/**	@brief RSA encryption of suitably padded plaintext
+ *
+	@param PUB the input RSA public key
+	@param F is input padded message
+	@param G is the output ciphertext
+ */
+extern void RSA_WWW_ENCRYPT(rsa_public_key_WWW* PUB,octet *F,octet *G);
+/**	@brief RSA decryption of ciphertext
+ *
+	@param PRIV the input RSA private key
+	@param G is the input ciphertext
+	@param F is output plaintext (requires unpadding)
+
+ */
+extern void RSA_WWW_DECRYPT(rsa_private_key_WWW* PRIV,octet *G,octet *F);
+/**	@brief Destroy an RSA private Key
+ *
+	@param PRIV the input RSA private key. Destroyed on output.
+ */
+extern void RSA_WWW_PRIVATE_KEY_KILL(rsa_private_key_WWW *PRIV);
+/**	@brief Populates an RSA public key from an octet string
+ *
+	Creates RSA public key from big-endian base 256 form.
+	@param x FF instance to be created from an octet string
+	@param S input octet string
+ */
+extern void RSA_WWW_fromOctet(BIG_XXX *x,octet *S);
+
+
+
+#endif
diff --git a/version3/c/rsa_support.c b/version3/c/rsa_support.c
new file mode 100644
index 0000000..a4cfdca
--- /dev/null
+++ b/version3/c/rsa_support.c
@@ -0,0 +1,237 @@
+#include "rsa_support.h"
+
+#define ROUNDUP(a,b) ((a)-1)/(b)+1
+
+/* general purpose hash function w=hash(p|n|x|y) */
+int hashit(int sha,octet *p,int n,octet *w)
+{
+    int i,c[4],hlen;
+    hash256 sha256;
+    hash512 sha512;
+    char hh[64];
+
+    switch (sha)
+    {
+    case SHA256:
+        HASH256_init(&sha256);
+        break;
+    case SHA384:
+        HASH384_init(&sha512);
+        break;
+    case SHA512:
+        HASH512_init(&sha512);
+        break;
+    }
+
+    hlen=sha;
+
+    if (p!=NULL) for (i=0; i<p->len; i++)
+        {
+            switch(sha)
+            {
+            case SHA256:
+                HASH256_process(&sha256,p->val[i]);
+                break;
+            case SHA384:
+                HASH384_process(&sha512,p->val[i]);
+                break;
+            case SHA512:
+                HASH512_process(&sha512,p->val[i]);
+                break;
+            }
+        }
+    if (n>=0)
+    {
+        c[0]=(n>>24)&0xff;
+        c[1]=(n>>16)&0xff;
+        c[2]=(n>>8)&0xff;
+        c[3]=(n)&0xff;
+        for (i=0; i<4; i++)
+        {
+            switch(sha)
+            {
+            case SHA256:
+                HASH256_process(&sha256,c[i]);
+                break;
+            case SHA384:
+                HASH384_process(&sha512,c[i]);
+                break;
+            case SHA512:
+                HASH512_process(&sha512,c[i]);
+                break;
+            }
+        }
+    }
+
+    switch (sha)
+    {
+    case SHA256:
+        HASH256_hash(&sha256,hh);
+        break;
+    case SHA384:
+        HASH384_hash(&sha512,hh);
+        break;
+    case SHA512:
+        HASH512_hash(&sha512,hh);
+        break;
+    }
+
+    OCT_empty(w);
+    OCT_jbytes(w,hh,hlen);
+    for (i=0; i<hlen; i++) hh[i]=0;
+
+    return hlen;
+}
+
+/* Mask Generation Function */
+
+static void MGF1(int sha,octet *z,int olen,octet *mask)
+{
+    char h[64];
+    octet H= {0,sizeof(h),h};
+    int hlen=sha;
+    int counter,cthreshold;
+
+    OCT_empty(mask);
+
+    cthreshold=ROUNDUP(olen,hlen);
+    for (counter=0; counter<cthreshold; counter++)
+    {
+        hashit(sha,z,counter,&H);
+        if (mask->len+hlen>olen) OCT_jbytes(mask,H.val,olen%hlen);
+        else                     OCT_joctet(mask,&H);
+    }
+    OCT_clear(&H);
+}
+
+/* SHAXXX identifier strings */
+const unsigned char SHA256ID[]= {0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20};
+const unsigned char SHA384ID[]= {0x30,0x41,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00,0x04,0x30};
+const unsigned char SHA512ID[]= {0x30,0x51,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0x04,0x40};
+
+/* PKCS 1.5 padding of a message to be signed */
+
+int PKCS15(int sha,octet *m,octet *w)
+{
+    int olen=w->max;
+    int hlen=sha;
+    int idlen=19;
+    char h[64];
+    octet H= {0,sizeof(h),h};
+
+    if (olen<idlen+hlen+10) return 1;
+    hashit(sha,m,-1,&H);
+
+    OCT_empty(w);
+    OCT_jbyte(w,0x00,1);
+    OCT_jbyte(w,0x01,1);
+    OCT_jbyte(w,0xff,olen-idlen-hlen-3);
+    OCT_jbyte(w,0x00,1);
+
+    if (hlen==32) OCT_jbytes(w,(char *)SHA256ID,idlen);
+    if (hlen==48) OCT_jbytes(w,(char *)SHA384ID,idlen);
+    if (hlen==64) OCT_jbytes(w,(char *)SHA512ID,idlen);
+
+    OCT_joctet(w,&H);
+
+    return 0;
+}
+
+/* OAEP Message Encoding for Encryption */
+
+int OAEP_ENCODE(int sha,octet *m,csprng *RNG,octet *p,octet *f)
+{
+    int slen,olen=f->max-1;
+    int mlen=m->len;
+    int hlen,seedlen;
+    char dbmask[MAX_RSA_BYTES],seed[64];
+    octet DBMASK= {0,sizeof(dbmask),dbmask};
+    octet SEED= {0,sizeof(seed),seed};
+
+    hlen=seedlen=sha;
+    if (mlen>olen-hlen-seedlen-1) return 1;
+    if (m==f) return 1;  /* must be distinct octets */
+
+    hashit(sha,p,-1,f);
+
+    slen=olen-mlen-hlen-seedlen-1;
+
+    OCT_jbyte(f,0,slen);
+    OCT_jbyte(f,0x1,1);
+    OCT_joctet(f,m);
+
+    OCT_rand(&SEED,RNG,seedlen);
+
+    MGF1(sha,&SEED,olen-seedlen,&DBMASK);
+
+    OCT_xor(&DBMASK,f);
+    MGF1(sha,&DBMASK,seedlen,f);
+
+    OCT_xor(f,&SEED);
+
+    OCT_joctet(f,&DBMASK);
+
+    OCT_pad(f,f->max);
+    OCT_clear(&SEED);
+    OCT_clear(&DBMASK);
+
+    return 0;
+}
+
+/* OAEP Message Decoding for Decryption */
+
+int OAEP_DECODE(int sha,octet *p,octet *f)
+{
+    int comp,x,t;
+    int i,k,olen=f->max-1;
+    int hlen,seedlen;
+    char dbmask[MAX_RSA_BYTES],seed[64],chash[64];
+    octet DBMASK= {0,sizeof(dbmask),dbmask};
+    octet SEED= {0,sizeof(seed),seed};
+    octet CHASH= {0,sizeof(chash),chash};
+
+    seedlen=hlen=sha;
+    if (olen<seedlen+hlen+1) return 1;
+    if (!OCT_pad(f,olen+1)) return 1;
+    hashit(sha,p,-1,&CHASH);
+
+    x=f->val[0];
+    for (i=seedlen; i<olen; i++)
+        DBMASK.val[i-seedlen]=f->val[i+1];
+    DBMASK.len=olen-seedlen;
+
+    MGF1(sha,&DBMASK,seedlen,&SEED);
+    for (i=0; i<seedlen; i++) SEED.val[i]^=f->val[i+1];
+    MGF1(sha,&SEED,olen-seedlen,f);
+    OCT_xor(&DBMASK,f);
+
+    comp=OCT_ncomp(&CHASH,&DBMASK,hlen);
+
+    OCT_shl(&DBMASK,hlen);
+
+    OCT_clear(&SEED);
+    OCT_clear(&CHASH);
+
+    for (k=0;; k++)
+    {
+        if (k>=DBMASK.len)
+        {
+            OCT_clear(&DBMASK);
+            return 1;
+        }
+        if (DBMASK.val[k]!=0) break;
+    }
+
+    t=DBMASK.val[k];
+    if (!comp || x!=0 || t!=0x01)
+    {
+        OCT_clear(&DBMASK);
+        return 1;
+    }
+
+    OCT_shl(&DBMASK,k+1);
+    OCT_copy(f,&DBMASK);
+    OCT_clear(&DBMASK);
+
+    return 0;
+}
diff --git a/version3/c/rsa_support.h b/version3/c/rsa_support.h
new file mode 100644
index 0000000..3bd495f
--- /dev/null
+++ b/version3/c/rsa_support.h
@@ -0,0 +1,62 @@
+/*
+	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.
+*/
+
+/**
+ * @file rsa_support.h
+ * @author Mike Scott
+ * @brief RSA Support  Header File
+ *
+ */
+
+#ifndef RSA_SUPPORT_H
+#define RSA_SUPPORT_H
+
+#include "amcl.h"
+
+#define MAX_RSA_BYTES 512 /**< Maximum of 4096 */
+
+/**	@brief PKCS V1.5 padding of a message prior to RSA signature
+ *
+	@param h is the hash type
+	@param M is the input message
+	@param W is the output encoding, ready for RSA signature
+	@return 1 if OK, else 0
+ */
+extern int PKCS15(int h,octet *M,octet *W);
+/**	@brief OAEP padding of a message prior to RSA encryption
+ *
+	@param h is the hash type
+	@param M is the input message
+	@param R is a pointer to a cryptographically secure random number generator
+	@param P are input encoding parameter string (could be NULL)
+	@param F is the output encoding, ready for RSA encryption
+	@return 1 if OK, else 0
+ */
+extern int	OAEP_ENCODE(int h,octet *M,csprng *R,octet *P,octet *F);
+/**	@brief OAEP unpadding of a message after RSA decryption
+ *
+	Unpadding is done in-place
+	@param h is the hash type
+	@param P are input encoding parameter string (could be NULL)
+	@param F is input padded message, unpadded on output
+	@return 1 if OK, else 0
+ */
+extern int  OAEP_DECODE(int h,octet *P,octet *F);
+
+#endif
diff --git a/version3/c/testall.c b/version3/c/testall.c
new file mode 100644
index 0000000..46b5a96
--- /dev/null
+++ b/version3/c/testall.c
@@ -0,0 +1,1627 @@
+/*
+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.
+*/
+
+/* test driver and function exerciser for ECDH/ECIES/ECDSA API Functions */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "ecdh_ED25519.h"
+#include "mpin_BN254.h"
+#include "rsa_2048.h"
+#include "randapi.h"
+
+#if CHUNK==32 || CHUNK==64
+#include "ecdh_NIST256.h"
+#include "ecdh_GOLDILOCKS.h"
+#include "mpin_BLS383.h"
+#include "mpin192_BLS24.h"
+#include "mpin256_BLS48.h"
+#endif
+
+int ecdh_ED25519(csprng *RNG)
+{
+    int i,res;
+    unsigned long ran;
+    char *pp="M0ng00se";
+    // These octets are automatically protected against buffer overflow attacks 
+    // Note salt must be big enough to include an appended word 
+    // Note ECIES ciphertext C must be big enough to include at least 1 appended block 
+    // Recall EFS_ED25519 is field size in bytes. So EFS_ED25519=32 for 256-bit curve 
+    char s0[2*EGS_ED25519],s1[EGS_ED25519],w0[2*EFS_ED25519+1],w1[2*EFS_ED25519+1],z0[EFS_ED25519],z1[EFS_ED25519],key[AESKEY_ED25519],salt[40],pw[40];
+    octet S0= {0,sizeof(s0),s0};
+    octet S1= {0,sizeof(s1),s1};
+    octet W0= {0,sizeof(w0),w0};
+    octet W1= {0,sizeof(w1),w1};
+    octet Z0= {0,sizeof(z0),z0};
+    octet Z1= {0,sizeof(z1),z1};
+    octet KEY= {0,sizeof(key),key};
+    octet SALT= {0,sizeof(salt),salt};
+    octet PW= {0,sizeof(pw),pw};
+
+    SALT.len=8;
+    for (i=0; i<8; i++) SALT.val[i]=i+1; // set Salt
+
+    printf("Alice's Passphrase= %s\n",pp);
+
+    OCT_empty(&PW);
+    OCT_jstring(&PW,pp);   // set Password from string
+
+    // private key S0 of size EGS_ED25519 bytes derived from Password and Salt 
+
+    PBKDF2(HASH_TYPE_ED25519,&PW,&SALT,1000,EGS_ED25519,&S0);
+
+    printf("Alices private key= 0x");
+    OCT_output(&S0);
+
+    // Generate Key pair S/W 
+
+    ECP_ED25519_KEY_PAIR_GENERATE(NULL,&S0,&W0);
+    printf("Alices public key= 0x");
+    OCT_output(&W0);
+
+    res=ECP_ED25519_PUBLIC_KEY_VALIDATE(&W0);
+    if (res!=0)
+    {
+        printf("ECP Public Key is invalid!\n");
+        return 0;
+    }
+
+    // Random private key for other party 
+    ECP_ED25519_KEY_PAIR_GENERATE(RNG,&S1,&W1);
+    res=ECP_ED25519_PUBLIC_KEY_VALIDATE(&W1);
+    if (res!=0)
+    {
+        printf("ECP Public Key is invalid!\n");
+        return 0;
+    }
+    printf("Servers private key= 0x");
+    OCT_output(&S1);
+    printf("Servers public key= 0x");
+    OCT_output(&W1);
+
+    // Calculate common key using DH - IEEE 1363 method 
+
+    ECP_ED25519_SVDP_DH(&S0,&W1,&Z0);
+    ECP_ED25519_SVDP_DH(&S1,&W0,&Z1);
+
+    if (!OCT_comp(&Z0,&Z1))
+    {
+        printf("*** ECPSVDP-DH Failed\n");
+        return 0;
+    }
+
+    KDF2(HASH_TYPE_ED25519,&Z0,NULL,AESKEY_ED25519,&KEY);
+
+    printf("Alice's DH Key=  0x");
+    OCT_output(&KEY);
+    printf("Servers DH Key=  0x");
+    OCT_output(&KEY);
+
+#if CURVETYPE_ED25519 != MONTGOMERY
+
+    char ds[EGS_ED25519],p1[30],p2[30],v[2*EFS_ED25519+1],m[32],c[64],t[32],cs[EGS_ED25519];
+    octet DS= {0,sizeof(ds),ds};
+    octet CS= {0,sizeof(cs),cs};
+    octet P1= {0,sizeof(p1),p1};
+    octet P2= {0,sizeof(p2),p2};
+    octet V= {0,sizeof(v),v};
+    octet M= {0,sizeof(m),m};
+    octet C= {0,sizeof(c),c};
+    octet T= {0,sizeof(t),t};
+
+    printf("Testing ECIES\n");
+
+    P1.len=3;
+    P1.val[0]=0x0;
+    P1.val[1]=0x1;
+    P1.val[2]=0x2;
+    P2.len=4;
+    P2.val[0]=0x0;
+    P2.val[1]=0x1;
+    P2.val[2]=0x2;
+    P2.val[3]=0x3;
+
+    M.len=17;
+    for (i=0; i<=16; i++) M.val[i]=i;
+
+    ECP_ED25519_ECIES_ENCRYPT(HASH_TYPE_ED25519,&P1,&P2,RNG,&W1,&M,12,&V,&C,&T);
+
+    printf("Ciphertext= \n");
+    printf("V= 0x");
+    OCT_output(&V);
+    printf("C= 0x");
+    OCT_output(&C);
+    printf("T= 0x");
+    OCT_output(&T);
+
+    if (!ECP_ED25519_ECIES_DECRYPT(HASH_TYPE_ED25519,&P1,&P2,&V,&C,&T,&S1,&M))
+    {
+        printf("*** ECIES Decryption Failed\n");
+        return 0;
+    }
+    else printf("Decryption succeeded\n");
+
+    printf("Message is 0x");
+    OCT_output(&M);
+
+
+    printf("Testing ECDSA\n");
+
+    if (ECP_ED25519_SP_DSA(HASH_TYPE_ED25519,RNG,NULL,&S0,&M,&CS,&DS)!=0)
+    {
+        printf("***ECDSA Signature Failed\n");
+        return 0;
+    }
+
+    printf("Signature C = 0x");
+    OCT_output(&CS);
+    printf("Signature D = 0x");
+    OCT_output(&DS);
+
+    if (ECP_ED25519_VP_DSA(HASH_TYPE_ED25519,&W0,&M,&CS,&DS)!=0)
+    {
+        printf("***ECDSA Verification Failed\n");
+        return 0;
+    }
+    else 
+    {
+      printf("ECDSA Signature/Verification succeeded\n");
+    }
+
+#endif
+
+    return 0;
+}
+
+#if CHUNK==32 || CHUNK==64
+int ecdh_NIST256(csprng *RNG)
+{
+    int i,res;
+    unsigned long ran;
+    char *pp="M0ng00se";
+    // These octets are automatically protected against buffer overflow attacks 
+    // Note salt must be big enough to include an appended word 
+    // Note ECIES ciphertext C must be big enough to include at least 1 appended block 
+    // Recall EFS_NIST256 is field size in bytes. So EFS_NIST256=32 for 256-bit curve 
+    char s0[2*EGS_NIST256],s1[EGS_NIST256],w0[2*EFS_NIST256+1],w1[2*EFS_NIST256+1],z0[EFS_NIST256],z1[EFS_NIST256],key[AESKEY_NIST256],salt[40],pw[40];
+    octet S0= {0,sizeof(s0),s0};
+    octet S1= {0,sizeof(s1),s1};
+    octet W0= {0,sizeof(w0),w0};
+    octet W1= {0,sizeof(w1),w1};
+    octet Z0= {0,sizeof(z0),z0};
+    octet Z1= {0,sizeof(z1),z1};
+    octet KEY= {0,sizeof(key),key};
+    octet SALT= {0,sizeof(salt),salt};
+    octet PW= {0,sizeof(pw),pw};
+
+    SALT.len=8;
+    for (i=0; i<8; i++) SALT.val[i]=i+1; // set Salt
+
+    printf("Alice's Passphrase= %s\n",pp);
+
+    OCT_empty(&PW);
+    OCT_jstring(&PW,pp);   // set Password from string
+
+    // private key S0 of size EGS_NIST256 bytes derived from Password and Salt 
+
+    PBKDF2(HASH_TYPE_NIST256,&PW,&SALT,1000,EGS_NIST256,&S0);
+
+    printf("Alices private key= 0x");
+    OCT_output(&S0);
+
+    // Generate Key pair S/W 
+
+    ECP_NIST256_KEY_PAIR_GENERATE(NULL,&S0,&W0);
+    printf("Alices public key= 0x");
+    OCT_output(&W0);
+
+    res=ECP_NIST256_PUBLIC_KEY_VALIDATE(&W0);
+    if (res!=0)
+    {
+        printf("ECP Public Key is invalid!\n");
+        return 0;
+    }
+
+    // Random private key for other party 
+    ECP_NIST256_KEY_PAIR_GENERATE(RNG,&S1,&W1);
+    res=ECP_NIST256_PUBLIC_KEY_VALIDATE(&W1);
+    if (res!=0)
+    {
+        printf("ECP Public Key is invalid!\n");
+        return 0;
+    }
+    printf("Servers private key= 0x");
+    OCT_output(&S1);
+    printf("Servers public key= 0x");
+    OCT_output(&W1);
+
+    // Calculate common key using DH - IEEE 1363 method 
+
+    ECP_NIST256_SVDP_DH(&S0,&W1,&Z0);
+    ECP_NIST256_SVDP_DH(&S1,&W0,&Z1);
+
+    if (!OCT_comp(&Z0,&Z1))
+    {
+        printf("*** ECPSVDP-DH Failed\n");
+        return 0;
+    }
+
+    KDF2(HASH_TYPE_NIST256,&Z0,NULL,AESKEY_NIST256,&KEY);
+
+    printf("Alice's DH Key=  0x");
+    OCT_output(&KEY);
+    printf("Servers DH Key=  0x");
+    OCT_output(&KEY);
+
+#if CURVETYPE_NIST256 != MONTGOMERY
+
+    char ds[EGS_NIST256],p1[30],p2[30],v[2*EFS_NIST256+1],m[32],c[64],t[32],cs[EGS_NIST256];
+    octet DS= {0,sizeof(ds),ds};
+    octet CS= {0,sizeof(cs),cs};
+    octet P1= {0,sizeof(p1),p1};
+    octet P2= {0,sizeof(p2),p2};
+    octet V= {0,sizeof(v),v};
+    octet M= {0,sizeof(m),m};
+    octet C= {0,sizeof(c),c};
+    octet T= {0,sizeof(t),t};
+
+    printf("Testing ECIES\n");
+
+    P1.len=3;
+    P1.val[0]=0x0;
+    P1.val[1]=0x1;
+    P1.val[2]=0x2;
+    P2.len=4;
+    P2.val[0]=0x0;
+    P2.val[1]=0x1;
+    P2.val[2]=0x2;
+    P2.val[3]=0x3;
+
+    M.len=17;
+    for (i=0; i<=16; i++) M.val[i]=i;
+
+    ECP_NIST256_ECIES_ENCRYPT(HASH_TYPE_NIST256,&P1,&P2,RNG,&W1,&M,12,&V,&C,&T);
+
+    printf("Ciphertext= \n");
+    printf("V= 0x");
+    OCT_output(&V);
+    printf("C= 0x");
+    OCT_output(&C);
+    printf("T= 0x");
+    OCT_output(&T);
+
+    if (!ECP_NIST256_ECIES_DECRYPT(HASH_TYPE_NIST256,&P1,&P2,&V,&C,&T,&S1,&M))
+    {
+        printf("*** ECIES Decryption Failed\n");
+        return 0;
+    }
+    else printf("Decryption succeeded\n");
+
+    printf("Message is 0x");
+    OCT_output(&M);
+
+
+    printf("Testing ECDSA\n");
+
+    if (ECP_NIST256_SP_DSA(HASH_TYPE_NIST256,RNG,NULL,&S0,&M,&CS,&DS)!=0)
+    {
+        printf("***ECDSA Signature Failed\n");
+        return 0;
+    }
+
+    printf("Signature C = 0x");
+    OCT_output(&CS);
+    printf("Signature D = 0x");
+    OCT_output(&DS);
+
+    if (ECP_NIST256_VP_DSA(HASH_TYPE_NIST256,&W0,&M,&CS,&DS)!=0)
+    {
+        printf("***ECDSA Verification Failed\n");
+        return 0;
+    }
+    else 
+    {
+      printf("ECDSA Signature/Verification succeeded\n");
+    }
+
+#endif
+
+    return 0;
+}
+
+int ecdh_GOLDILOCKS(csprng *RNG)
+{
+    int i,res;
+    unsigned long ran;
+    char *pp="M0ng00se";
+    // These octets are automatically protected against buffer overflow attacks 
+    // Note salt must be big enough to include an appended word 
+    // Note ECIES ciphertext C must be big enough to include at least 1 appended block 
+    // Recall EFS_GOLDILOCKS is field size in bytes. So EFS_GOLDILOCKS=32 for 256-bit curve 
+    char s0[2*EGS_GOLDILOCKS],s1[EGS_GOLDILOCKS],w0[2*EFS_GOLDILOCKS+1],w1[2*EFS_GOLDILOCKS+1],z0[EFS_GOLDILOCKS],z1[EFS_GOLDILOCKS],key[AESKEY_GOLDILOCKS],salt[40],pw[40];
+    octet S0= {0,sizeof(s0),s0};
+    octet S1= {0,sizeof(s1),s1};
+    octet W0= {0,sizeof(w0),w0};
+    octet W1= {0,sizeof(w1),w1};
+    octet Z0= {0,sizeof(z0),z0};
+    octet Z1= {0,sizeof(z1),z1};
+    octet KEY= {0,sizeof(key),key};
+    octet SALT= {0,sizeof(salt),salt};
+    octet PW= {0,sizeof(pw),pw};
+
+    SALT.len=8;
+    for (i=0; i<8; i++) SALT.val[i]=i+1; // set Salt
+
+    printf("Alice's Passphrase= %s\n",pp);
+
+    OCT_empty(&PW);
+    OCT_jstring(&PW,pp);   // set Password from string
+
+    // private key S0 of size EGS_GOLDILOCKS bytes derived from Password and Salt 
+
+    PBKDF2(HASH_TYPE_GOLDILOCKS,&PW,&SALT,1000,EGS_GOLDILOCKS,&S0);
+
+    printf("Alices private key= 0x");
+    OCT_output(&S0);
+
+    // Generate Key pair S/W 
+
+    ECP_GOLDILOCKS_KEY_PAIR_GENERATE(NULL,&S0,&W0);
+    printf("Alices public key= 0x");
+    OCT_output(&W0);
+
+    res=ECP_GOLDILOCKS_PUBLIC_KEY_VALIDATE(&W0);
+    if (res!=0)
+    {
+        printf("ECP Public Key is invalid!\n");
+        return 0;
+    }
+
+    // Random private key for other party 
+    ECP_GOLDILOCKS_KEY_PAIR_GENERATE(RNG,&S1,&W1);
+    res=ECP_GOLDILOCKS_PUBLIC_KEY_VALIDATE(&W1);
+    if (res!=0)
+    {
+        printf("ECP Public Key is invalid!\n");
+        return 0;
+    }
+    printf("Servers private key= 0x");
+    OCT_output(&S1);
+    printf("Servers public key= 0x");
+    OCT_output(&W1);
+
+    // Calculate common key using DH - IEEE 1363 method 
+
+    ECP_GOLDILOCKS_SVDP_DH(&S0,&W1,&Z0);
+    ECP_GOLDILOCKS_SVDP_DH(&S1,&W0,&Z1);
+
+    if (!OCT_comp(&Z0,&Z1))
+    {
+        printf("*** ECPSVDP-DH Failed\n");
+        return 0;
+    }
+
+    KDF2(HASH_TYPE_GOLDILOCKS,&Z0,NULL,AESKEY_GOLDILOCKS,&KEY);
+
+    printf("Alice's DH Key=  0x");
+    OCT_output(&KEY);
+    printf("Servers DH Key=  0x");
+    OCT_output(&KEY);
+
+#if CURVETYPE_GOLDILOCKS != MONTGOMERY
+
+    char ds[EGS_GOLDILOCKS],p1[30],p2[30],v[2*EFS_GOLDILOCKS+1],m[32],c[64],t[32],cs[EGS_GOLDILOCKS];
+    octet DS= {0,sizeof(ds),ds};
+    octet CS= {0,sizeof(cs),cs};
+    octet P1= {0,sizeof(p1),p1};
+    octet P2= {0,sizeof(p2),p2};
+    octet V= {0,sizeof(v),v};
+    octet M= {0,sizeof(m),m};
+    octet C= {0,sizeof(c),c};
+    octet T= {0,sizeof(t),t};
+
+    printf("Testing ECIES\n");
+
+    P1.len=3;
+    P1.val[0]=0x0;
+    P1.val[1]=0x1;
+    P1.val[2]=0x2;
+    P2.len=4;
+    P2.val[0]=0x0;
+    P2.val[1]=0x1;
+    P2.val[2]=0x2;
+    P2.val[3]=0x3;
+
+    M.len=17;
+    for (i=0; i<=16; i++) M.val[i]=i;
+
+    ECP_GOLDILOCKS_ECIES_ENCRYPT(HASH_TYPE_GOLDILOCKS,&P1,&P2,RNG,&W1,&M,12,&V,&C,&T);
+
+    printf("Ciphertext= \n");
+    printf("V= 0x");
+    OCT_output(&V);
+    printf("C= 0x");
+    OCT_output(&C);
+    printf("T= 0x");
+    OCT_output(&T);
+
+    if (!ECP_GOLDILOCKS_ECIES_DECRYPT(HASH_TYPE_GOLDILOCKS,&P1,&P2,&V,&C,&T,&S1,&M))
+    {
+        printf("*** ECIES Decryption Failed\n");
+        return 0;
+    }
+    else printf("Decryption succeeded\n");
+
+    printf("Message is 0x");
+    OCT_output(&M);
+
+
+    printf("Testing ECDSA\n");
+
+    if (ECP_GOLDILOCKS_SP_DSA(HASH_TYPE_GOLDILOCKS,RNG,NULL,&S0,&M,&CS,&DS)!=0)
+    {
+        printf("***ECDSA Signature Failed\n");
+        return 0;
+    }
+
+    printf("Signature C = 0x");
+    OCT_output(&CS);
+    printf("Signature D = 0x");
+    OCT_output(&DS);
+
+    if (ECP_GOLDILOCKS_VP_DSA(HASH_TYPE_GOLDILOCKS,&W0,&M,&CS,&DS)!=0)
+    {
+        printf("***ECDSA Verification Failed\n");
+        return 0;
+    }
+    else 
+    {
+      printf("ECDSA Signature/Verification succeeded\n");
+    }
+
+#endif
+
+    return 0;
+}
+#endif
+
+#define PERMITS  // for time permits ON or OFF 
+#define PINERROR // For PIN ERROR detection ON or OFF 
+#define FULL     // for M-Pin Full or M-Pin regular 
+
+int mpin_BN254(csprng *RNG)
+{
+    int i,pin,rtn,err;
+#ifdef PERMITS
+    int date=today();
+#else
+    int date=0;
+#endif
+    unsigned long ran;
+    char x[PGS_BN254],s[PGS_BN254],y[PGS_BN254],client_id[100],sst[4*PFS_BN254],token[2*PFS_BN254+1],sec[2*PFS_BN254+1],permit[2*PFS_BN254+1],xcid[2*PFS_BN254+1],xid[2*PFS_BN254+1],e[12*PFS_BN254],f[12*PFS_BN254];
+    char hcid[PFS_BN254],hsid[PFS_BN254],hid[2*PFS_BN254+1],htid[2*PFS_BN254+1],h[PGS_BN254];
+#ifdef FULL
+    char r[PGS_BN254],z[2*PFS_BN254+1],w[PGS_BN254],t[2*PFS_BN254+1];
+    char g1[12*PFS_BN254],g2[12*PFS_BN254];
+    char ck[AESKEY_BN254],sk[AESKEY_BN254];
+#endif
+    octet S= {0,sizeof(s),s};
+    octet X= {0,sizeof(x),x};
+    octet Y= {0,sizeof(y),y};
+    octet H= {0,sizeof(h),h};
+    octet CLIENT_ID= {0,sizeof(client_id),client_id};
+    octet SST= {0,sizeof(sst),sst};
+    octet TOKEN= {0,sizeof(token),token};
+    octet SEC= {0,sizeof(sec),sec};
+    octet PERMIT= {0,sizeof(permit),permit};
+    octet xCID= {0,sizeof(xcid),xcid};
+    octet xID= {0,sizeof(xid),xid};
+    octet HCID= {0,sizeof(hcid),hcid};
+    octet HSID= {0,sizeof(hsid),hsid};
+    octet HID= {0,sizeof(hid),hid};
+    octet HTID= {0,sizeof(htid),htid};
+    octet E= {0,sizeof(e),e};
+    octet F= {0,sizeof(f),f};
+#ifdef FULL
+    octet R= {0,sizeof(r),r};
+    octet Z= {0,sizeof(z),z};
+    octet W= {0,sizeof(w),w};
+    octet T= {0,sizeof(t),t};
+    octet G1= {0,sizeof(g1),g1};
+    octet G2= {0,sizeof(g2),g2};
+    octet SK= {0,sizeof(sk),sk};
+    octet CK= {0,sizeof(ck),ck};
+#endif
+    octet *pxID,*pxCID,*pHID,*pHTID,*pE,*pF,*pPERMIT,*prHID;
+    char idhex[100];
+
+    // Trusted Authority set-up 
+    MPIN_BN254_RANDOM_GENERATE(RNG,&S);
+    printf("Master Secret= ");
+    OCT_output(&S);
+
+    // Create Client Identity 
+    OCT_jstring(&CLIENT_ID,"testUser@miracl.com");
+    HASH_ID(HASH_TYPE_BN254,&CLIENT_ID,&HCID);  // Either Client or TA calculates Hash(ID) - you decide! 
+
+    printf("Client ID Hash= ");
+    OCT_output(&HCID);
+    printf("\n");
+
+    OCT_toHex(&CLIENT_ID,idhex);
+    printf("Client ID= %s\n",idhex);// OCT_toHex(&CLIENT_ID); printf("\n");
+
+    MPIN_BN254_GET_CLIENT_SECRET(&S,&HCID,&TOKEN);
+    printf("Client Secret= ");
+    OCT_output(&TOKEN);
+
+// Client and Server are issued secrets by DTA 
+    MPIN_BN254_GET_SERVER_SECRET(&S,&SST);
+    printf("Server Secret= ");
+    OCT_output(&SST);
+
+
+
+    // Client extracts PIN from secret to create Token 
+    pin=1234;
+    printf("Client extracts PIN= %d\n",pin);
+    MPIN_BN254_EXTRACT_PIN(HASH_TYPE_BN254,&CLIENT_ID,pin,&TOKEN);
+    printf("Client Token= ");
+    OCT_output(&TOKEN);
+
+#ifdef FULL
+    MPIN_BN254_PRECOMPUTE(&TOKEN,&HCID,NULL,&G1,&G2);
+#endif
+
+#ifdef PERMITS
+    // Client gets "Time Permit" from DTA 
+    printf("Client gets Time Permit\n");
+
+    MPIN_BN254_GET_CLIENT_PERMIT(HASH_TYPE_BN254,date,&S,&HCID,&PERMIT);
+    printf("Time Permit= ");
+    OCT_output(&PERMIT);
+
+    // This encoding makes Time permit look random 
+    if (MPIN_BN254_ENCODING(RNG,&PERMIT)!=0) printf("Encoding error\n");
+    // printf("Encoded Time Permit= "); OCT_output(&PERMIT); 
+    if (MPIN_BN254_DECODING(&PERMIT)!=0) printf("Decoding error\n");
+    // printf("Decoded Time Permit= "); OCT_output(&PERMIT); 
+#endif
+
+    // MPin Protocol 
+
+    // Client enters PIN 
+    printf("\nPIN= ");
+    if(scanf("%d",&pin)) {};
+    // to avoid silly compile error 
+    getchar();
+
+    // 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
+
+   // HSID - hashed client ID as calculated by the server
+   // HCID - hashed client ID as calculated by the client
+
+   // 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.
+
+    
+
+    pxID=&xID;
+    pxCID=&xCID;
+    pHID=&HID;
+    pHTID=&HTID;
+    pE=&E;
+    pF=&F;
+    pPERMIT=&PERMIT;
+
+#ifdef PERMITS
+    prHID=pHTID;
+#ifndef PINERROR
+    pxID=NULL;
+//   pHID=NULL;  //new
+#endif
+#else
+    prHID=pHID;
+    pPERMIT=NULL;
+    pxCID=NULL;
+    pHTID=NULL;
+#endif
+#ifndef PINERROR
+    pE=NULL;
+    pF=NULL;
+#endif
+
+    // When set only send hashed IDs to server 
+    octet *pID;
+#ifdef USE_ANONYMOUS
+    pID = &HCID;
+#else
+    pID = &CLIENT_ID;
+#endif
+
+#ifdef SINGLE_PASS
+    int timeValue;
+    printf("MPIN Single Pass\n");
+    timeValue = MPIN_BN254_GET_TIME();
+
+    rtn=MPIN_BN254_CLIENT(HASH_TYPE_BN254,date,&CLIENT_ID,RNG,&X,pin,&TOKEN,&SEC,pxID,pxCID,pPERMIT,NULL,timeValue,&Y);
+
+    if (rtn != 0)
+    {
+        printf("MPIN_BN254_CLIENT ERROR %d\n", rtn);
+        return 1;
+    }
+
+#ifdef FULL
+    MPIN_BN254_GET_G1_MULTIPLE(RNG,1,&R,&HCID,&Z);  // Also Send Z=r.ID to Server, remember random r 
+#endif
+
+
+    rtn=MPIN_BN254_SERVER(HASH_TYPE_BN254,date,pHID,pHTID,&Y,&SST,pxID,pxCID,&SEC,pE,pF,pID,NULL,timeValue,NULL);
+
+#ifdef FULL
+    HASH_ID(HASH_TYPE_BN254,&CLIENT_ID,&HSID);  // new
+    MPIN_BN254_GET_G1_MULTIPLE(RNG,0,&W,prHID,&T);  // Also send T=w.ID to client, remember random w  
+#endif
+
+#else // SINGLE_PASS
+    printf("MPIN Multi Pass\n");
+    if (MPIN_BN254_CLIENT_1(HASH_TYPE_BN254,date,&CLIENT_ID,RNG,&X,pin,&TOKEN,&SEC,pxID,pxCID,pPERMIT)!=0)
+    {
+        printf("Error from Client side - First Pass\n");
+        return 0;
+    }
+
+    // Send U=x.ID to server, and recreate secret from token and pin 
+
+#ifdef FULL
+    HASH_ID(HASH_TYPE_BN254,&CLIENT_ID,&HCID);
+    MPIN_BN254_GET_G1_MULTIPLE(RNG,1,&R,&HCID,&Z);  // Also Send Z=r.ID to Server, remember random r, DH component 
+#endif
+
+    // Server calculates H(ID) and H(ID)+H(T|H(ID)) (if time permits enabled), and maps them to points on the curve HID and HTID resp. 
+    MPIN_BN254_SERVER_1(HASH_TYPE_BN254,date,pID,pHID,pHTID);
+
+    // Server generates Random number Y and sends it to Client 
+    MPIN_BN254_RANDOM_GENERATE(RNG,&Y);
+
+#ifdef FULL
+    HASH_ID(HASH_TYPE_BN254,&CLIENT_ID,&HSID); //new
+    MPIN_BN254_GET_G1_MULTIPLE(RNG,0,&W,prHID,&T);  // Also send T=w.ID to client, remember random w, DH component  
+#endif
+
+    // Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC 
+    if (MPIN_BN254_CLIENT_2(&X,&Y,&SEC)!=0)
+    {
+        printf("Error from Client side - Second Pass\n");
+        return 1;
+    }
+
+    // Server Second phase. 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=MPIN_BN254_SERVER_2(date,pHID,pHTID,&Y,&SST,pxID,pxCID,&SEC,pE,pF,NULL);
+#endif // SINGLE_PASS
+
+    if (rtn!=0)
+    {
+        printf("Server says - Bad Pin.\n");
+#ifdef PINERROR
+
+        err=MPIN_BN254_KANGAROO(&E,&F);
+        if (err) printf("(Client PIN is out by %d)\n",err);
+
+#endif
+        return 1;
+    }
+    else
+    {
+        printf("Server says - PIN is good! You really are ");
+        OCT_output_string(&CLIENT_ID);
+        printf(".\n");
+    }
+
+#ifdef FULL
+
+    HASH_ALL(HASH_TYPE_BN254,&HCID,pxID,pxCID,&SEC,&Y,&Z,&T,&H);  // new
+    MPIN_BN254_CLIENT_KEY(HASH_TYPE_BN254,&G1,&G2,pin,&R,&X,&H,&T,&CK);      // new H
+    printf("Client Key = ");
+    OCT_output(&CK);
+
+    HASH_ALL(HASH_TYPE_BN254,&HSID,pxID,pxCID,&SEC,&Y,&Z,&T,&H);
+    MPIN_BN254_SERVER_KEY(HASH_TYPE_BN254,&Z,&SST,&W,&H,pHID,pxID,pxCID,&SK); // new H,pHID
+    printf("Server Key = ");
+    OCT_output(&SK);
+#endif
+    return 0;
+}
+
+#if CHUNK==32 || CHUNK==64
+
+int mpin_BLS383(csprng *RNG)
+{
+    int i,pin,rtn,err;
+#ifdef PERMITS
+    int date=today();
+#else
+    int date=0;
+#endif
+    unsigned long ran;
+    char x[PGS_BLS383],s[PGS_BLS383],y[PGS_BLS383],client_id[100],sst[4*PFS_BLS383],token[2*PFS_BLS383+1],sec[2*PFS_BLS383+1],permit[2*PFS_BLS383+1],xcid[2*PFS_BLS383+1],xid[2*PFS_BLS383+1],e[12*PFS_BLS383],f[12*PFS_BLS383];
+    char hcid[PFS_BLS383],hsid[PFS_BLS383],hid[2*PFS_BLS383+1],htid[2*PFS_BLS383+1],h[PGS_BLS383];
+#ifdef FULL
+    char r[PGS_BLS383],z[2*PFS_BLS383+1],w[PGS_BLS383],t[2*PFS_BLS383+1];
+    char g1[12*PFS_BLS383],g2[12*PFS_BLS383];
+    char ck[AESKEY_BLS383],sk[AESKEY_BLS383];
+#endif
+    octet S= {0,sizeof(s),s};
+    octet X= {0,sizeof(x),x};
+    octet Y= {0,sizeof(y),y};
+    octet H= {0,sizeof(h),h};
+    octet CLIENT_ID= {0,sizeof(client_id),client_id};
+    octet SST= {0,sizeof(sst),sst};
+    octet TOKEN= {0,sizeof(token),token};
+    octet SEC= {0,sizeof(sec),sec};
+    octet PERMIT= {0,sizeof(permit),permit};
+    octet xCID= {0,sizeof(xcid),xcid};
+    octet xID= {0,sizeof(xid),xid};
+    octet HCID= {0,sizeof(hcid),hcid};
+    octet HSID= {0,sizeof(hsid),hsid};
+    octet HID= {0,sizeof(hid),hid};
+    octet HTID= {0,sizeof(htid),htid};
+    octet E= {0,sizeof(e),e};
+    octet F= {0,sizeof(f),f};
+#ifdef FULL
+    octet R= {0,sizeof(r),r};
+    octet Z= {0,sizeof(z),z};
+    octet W= {0,sizeof(w),w};
+    octet T= {0,sizeof(t),t};
+    octet G1= {0,sizeof(g1),g1};
+    octet G2= {0,sizeof(g2),g2};
+    octet SK= {0,sizeof(sk),sk};
+    octet CK= {0,sizeof(ck),ck};
+#endif
+    octet *pxID,*pxCID,*pHID,*pHTID,*pE,*pF,*pPERMIT,*prHID;
+    char idhex[100];
+
+    // Trusted Authority set-up 
+    MPIN_BLS383_RANDOM_GENERATE(RNG,&S);
+    printf("Master Secret= ");
+    OCT_output(&S);
+
+    // Create Client Identity 
+    OCT_jstring(&CLIENT_ID,"testUser@miracl.com");
+    HASH_ID(HASH_TYPE_BLS383,&CLIENT_ID,&HCID);  // Either Client or TA calculates Hash(ID) - you decide! 
+
+    printf("Client ID Hash= ");
+    OCT_output(&HCID);
+    printf("\n");
+
+    OCT_toHex(&CLIENT_ID,idhex);
+    printf("Client ID= %s\n",idhex);// OCT_toHex(&CLIENT_ID); printf("\n");
+
+    MPIN_BLS383_GET_CLIENT_SECRET(&S,&HCID,&TOKEN);
+    printf("Client Secret= ");
+    OCT_output(&TOKEN);
+
+// Client and Server are issued secrets by DTA 
+    MPIN_BLS383_GET_SERVER_SECRET(&S,&SST);
+    printf("Server Secret= ");
+    OCT_output(&SST);
+
+
+
+    // Client extracts PIN from secret to create Token 
+    pin=1234;
+    printf("Client extracts PIN= %d\n",pin);
+    MPIN_BLS383_EXTRACT_PIN(HASH_TYPE_BLS383,&CLIENT_ID,pin,&TOKEN);
+    printf("Client Token= ");
+    OCT_output(&TOKEN);
+
+#ifdef FULL
+    MPIN_BLS383_PRECOMPUTE(&TOKEN,&HCID,NULL,&G1,&G2);
+#endif
+
+#ifdef PERMITS
+    // Client gets "Time Permit" from DTA 
+    printf("Client gets Time Permit\n");
+
+    MPIN_BLS383_GET_CLIENT_PERMIT(HASH_TYPE_BLS383,date,&S,&HCID,&PERMIT);
+    printf("Time Permit= ");
+    OCT_output(&PERMIT);
+
+    // This encoding makes Time permit look random 
+    if (MPIN_BLS383_ENCODING(RNG,&PERMIT)!=0) printf("Encoding error\n");
+    // printf("Encoded Time Permit= "); OCT_output(&PERMIT); 
+    if (MPIN_BLS383_DECODING(&PERMIT)!=0) printf("Decoding error\n");
+    // printf("Decoded Time Permit= "); OCT_output(&PERMIT); 
+#endif
+
+    // MPin Protocol 
+
+    // Client enters PIN 
+    printf("\nPIN= ");
+    if(scanf("%d",&pin)) {};
+    // to avoid silly compile error 
+    getchar();
+
+    // 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
+
+   // HSID - hashed client ID as calculated by the server
+   // HCID - hashed client ID as calculated by the client
+
+   // 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.
+
+    
+
+    pxID=&xID;
+    pxCID=&xCID;
+    pHID=&HID;
+    pHTID=&HTID;
+    pE=&E;
+    pF=&F;
+    pPERMIT=&PERMIT;
+
+#ifdef PERMITS
+    prHID=pHTID;
+#ifndef PINERROR
+    pxID=NULL;
+//   pHID=NULL;  //new
+#endif
+#else
+    prHID=pHID;
+    pPERMIT=NULL;
+    pxCID=NULL;
+    pHTID=NULL;
+#endif
+#ifndef PINERROR
+    pE=NULL;
+    pF=NULL;
+#endif
+
+    // When set only send hashed IDs to server 
+    octet *pID;
+#ifdef USE_ANONYMOUS
+    pID = &HCID;
+#else
+    pID = &CLIENT_ID;
+#endif
+
+#ifdef SINGLE_PASS
+    int timeValue;
+    printf("MPIN Single Pass\n");
+    timeValue = MPIN_BLS383_GET_TIME();
+
+    rtn=MPIN_BLS383_CLIENT(HASH_TYPE_BLS383,date,&CLIENT_ID,RNG,&X,pin,&TOKEN,&SEC,pxID,pxCID,pPERMIT,NULL,timeValue,&Y);
+
+    if (rtn != 0)
+    {
+        printf("MPIN_BLS383_CLIENT ERROR %d\n", rtn);
+        return 1;
+    }
+
+#ifdef FULL
+    MPIN_BLS383_GET_G1_MULTIPLE(RNG,1,&R,&HCID,&Z);  // Also Send Z=r.ID to Server, remember random r 
+#endif
+
+
+    rtn=MPIN_BLS383_SERVER(HASH_TYPE_BLS383,date,pHID,pHTID,&Y,&SST,pxID,pxCID,&SEC,pE,pF,pID,NULL,timeValue,NULL);
+
+#ifdef FULL
+    HASH_ID(HASH_TYPE_BLS383,&CLIENT_ID,&HSID);  // new
+    MPIN_BLS383_GET_G1_MULTIPLE(RNG,0,&W,prHID,&T);  // Also send T=w.ID to client, remember random w  
+#endif
+
+#else // SINGLE_PASS
+    printf("MPIN Multi Pass\n");
+    if (MPIN_BLS383_CLIENT_1(HASH_TYPE_BLS383,date,&CLIENT_ID,RNG,&X,pin,&TOKEN,&SEC,pxID,pxCID,pPERMIT)!=0)
+    {
+        printf("Error from Client side - First Pass\n");
+        return 0;
+    }
+
+    // Send U=x.ID to server, and recreate secret from token and pin 
+
+#ifdef FULL
+    HASH_ID(HASH_TYPE_BLS383,&CLIENT_ID,&HCID);
+    MPIN_BLS383_GET_G1_MULTIPLE(RNG,1,&R,&HCID,&Z);  // Also Send Z=r.ID to Server, remember random r, DH component 
+#endif
+
+    // Server calculates H(ID) and H(ID)+H(T|H(ID)) (if time permits enabled), and maps them to points on the curve HID and HTID resp. 
+    MPIN_BLS383_SERVER_1(HASH_TYPE_BLS383,date,pID,pHID,pHTID);
+
+    // Server generates Random number Y and sends it to Client 
+    MPIN_BLS383_RANDOM_GENERATE(RNG,&Y);
+
+#ifdef FULL
+    HASH_ID(HASH_TYPE_BLS383,&CLIENT_ID,&HSID); //new
+    MPIN_BLS383_GET_G1_MULTIPLE(RNG,0,&W,prHID,&T);  // Also send T=w.ID to client, remember random w, DH component  
+#endif
+
+    // Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC 
+    if (MPIN_BLS383_CLIENT_2(&X,&Y,&SEC)!=0)
+    {
+        printf("Error from Client side - Second Pass\n");
+        return 1;
+    }
+
+    // Server Second phase. 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=MPIN_BLS383_SERVER_2(date,pHID,pHTID,&Y,&SST,pxID,pxCID,&SEC,pE,pF,NULL);
+#endif // SINGLE_PASS
+
+    if (rtn!=0)
+    {
+        printf("Server says - Bad Pin.\n");
+#ifdef PINERROR
+
+        err=MPIN_BLS383_KANGAROO(&E,&F);
+        if (err) printf("(Client PIN is out by %d)\n",err);
+
+#endif
+        return 1;
+    }
+    else
+    {
+        printf("Server says - PIN is good! You really are ");
+        OCT_output_string(&CLIENT_ID);
+        printf(".\n");
+    }
+
+#ifdef FULL
+
+    HASH_ALL(HASH_TYPE_BLS383,&HCID,pxID,pxCID,&SEC,&Y,&Z,&T,&H);  // new
+    MPIN_BLS383_CLIENT_KEY(HASH_TYPE_BLS383,&G1,&G2,pin,&R,&X,&H,&T,&CK);      // new H
+    printf("Client Key = ");
+    OCT_output(&CK);
+
+    HASH_ALL(HASH_TYPE_BLS383,&HSID,pxID,pxCID,&SEC,&Y,&Z,&T,&H);
+    MPIN_BLS383_SERVER_KEY(HASH_TYPE_BLS383,&Z,&SST,&W,&H,pHID,pxID,pxCID,&SK); // new H,pHID
+    printf("Server Key = ");
+    OCT_output(&SK);
+#endif
+    return 0;
+}
+
+
+int mpin192_BLS24(csprng *RNG)
+{
+    int i,pin,rtn,err;
+#ifdef PERMITS
+    int date=today();
+#else
+    int date=0;
+#endif
+    unsigned long ran;
+    char x[PGS_BLS24],s[PGS_BLS24],y[PGS_BLS24],client_id[100],sst[8*PFS_BLS24],token[2*PFS_BLS24+1],sec[2*PFS_BLS24+1],permit[2*PFS_BLS24+1],xcid[2*PFS_BLS24+1],xid[2*PFS_BLS24+1],e[24*PFS_BLS24],f[24*PFS_BLS24];
+    char hcid[PFS_BLS24],hsid[PFS_BLS24],hid[2*PFS_BLS24+1],htid[2*PFS_BLS24+1],h[PGS_BLS24];
+#ifdef FULL
+    char r[PGS_BLS24],z[2*PFS_BLS24+1],w[PGS_BLS24],t[2*PFS_BLS24+1];
+    char g1[24*PFS_BLS24],g2[24*PFS_BLS24];
+    char ck[AESKEY_BLS24],sk[AESKEY_BLS24];
+#endif
+    octet S= {0,sizeof(s),s};
+    octet X= {0,sizeof(x),x};
+    octet Y= {0,sizeof(y),y};
+    octet H= {0,sizeof(h),h};
+    octet CLIENT_ID= {0,sizeof(client_id),client_id};
+    octet SST= {0,sizeof(sst),sst};
+    octet TOKEN= {0,sizeof(token),token};
+    octet SEC= {0,sizeof(sec),sec};
+    octet PERMIT= {0,sizeof(permit),permit};
+    octet xCID= {0,sizeof(xcid),xcid};
+    octet xID= {0,sizeof(xid),xid};
+    octet HCID= {0,sizeof(hcid),hcid};
+    octet HSID= {0,sizeof(hsid),hsid};
+    octet HID= {0,sizeof(hid),hid};
+    octet HTID= {0,sizeof(htid),htid};
+    octet E= {0,sizeof(e),e};
+    octet F= {0,sizeof(f),f};
+#ifdef FULL
+    octet R= {0,sizeof(r),r};
+    octet Z= {0,sizeof(z),z};
+    octet W= {0,sizeof(w),w};
+    octet T= {0,sizeof(t),t};
+    octet G1= {0,sizeof(g1),g1};
+    octet G2= {0,sizeof(g2),g2};
+    octet SK= {0,sizeof(sk),sk};
+    octet CK= {0,sizeof(ck),ck};
+#endif
+    octet *pxID,*pxCID,*pHID,*pHTID,*pE,*pF,*pPERMIT,*prHID;
+    char idhex[100];
+
+    // Trusted Authority set-up 
+    MPIN_BLS24_RANDOM_GENERATE(RNG,&S);
+    printf("Master Secret= ");
+    OCT_output(&S);
+
+    // Create Client Identity 
+    OCT_jstring(&CLIENT_ID,"testUser@miracl.com");
+    HASH_ID(HASH_TYPE_BLS24,&CLIENT_ID,&HCID);  // Either Client or TA calculates Hash(ID) - you decide! 
+
+    printf("Client ID Hash= ");
+    OCT_output(&HCID);
+    printf("\n");
+
+    OCT_toHex(&CLIENT_ID,idhex);
+    printf("Client ID= %s\n",idhex);// OCT_toHex(&CLIENT_ID); printf("\n");
+
+    MPIN_BLS24_GET_CLIENT_SECRET(&S,&HCID,&TOKEN);
+    printf("Client Secret= ");
+    OCT_output(&TOKEN);
+
+// Client and Server are issued secrets by DTA 
+    MPIN_BLS24_GET_SERVER_SECRET(&S,&SST);
+    printf("Server Secret= ");
+    OCT_output(&SST);
+
+
+
+    // Client extracts PIN from secret to create Token 
+    pin=1234;
+    printf("Client extracts PIN= %d\n",pin);
+    MPIN_BLS24_EXTRACT_PIN(HASH_TYPE_BLS24,&CLIENT_ID,pin,&TOKEN);
+    printf("Client Token= ");
+    OCT_output(&TOKEN);
+
+#ifdef FULL
+    MPIN_BLS24_PRECOMPUTE(&TOKEN,&HCID,NULL,&G1,&G2);
+#endif
+
+#ifdef PERMITS
+    // Client gets "Time Permit" from DTA 
+    printf("Client gets Time Permit\n");
+
+    MPIN_BLS24_GET_CLIENT_PERMIT(HASH_TYPE_BLS24,date,&S,&HCID,&PERMIT);
+    printf("Time Permit= ");
+    OCT_output(&PERMIT);
+
+    // This encoding makes Time permit look random 
+    if (MPIN_BLS24_ENCODING(RNG,&PERMIT)!=0) printf("Encoding error\n");
+    // printf("Encoded Time Permit= "); OCT_output(&PERMIT); 
+    if (MPIN_BLS24_DECODING(&PERMIT)!=0) printf("Decoding error\n");
+    // printf("Decoded Time Permit= "); OCT_output(&PERMIT); 
+#endif
+
+    // MPin Protocol 
+
+    // Client enters PIN 
+    printf("\nPIN= ");
+    if(scanf("%d",&pin)) {};
+    // to avoid silly compile error 
+    getchar();
+
+    // 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
+
+   // HSID - hashed client ID as calculated by the server
+   // HCID - hashed client ID as calculated by the client
+
+   // 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.
+
+    
+
+    pxID=&xID;
+    pxCID=&xCID;
+    pHID=&HID;
+    pHTID=&HTID;
+    pE=&E;
+    pF=&F;
+    pPERMIT=&PERMIT;
+
+#ifdef PERMITS
+    prHID=pHTID;
+#ifndef PINERROR
+    pxID=NULL;
+//   pHID=NULL;  //new
+#endif
+#else
+    prHID=pHID;
+    pPERMIT=NULL;
+    pxCID=NULL;
+    pHTID=NULL;
+#endif
+#ifndef PINERROR
+    pE=NULL;
+    pF=NULL;
+#endif
+
+    // When set only send hashed IDs to server 
+    octet *pID;
+#ifdef USE_ANONYMOUS
+    pID = &HCID;
+#else
+    pID = &CLIENT_ID;
+#endif
+
+#ifdef SINGLE_PASS
+    int timeValue;
+    printf("MPIN Single Pass\n");
+    timeValue = MPIN_BLS24_GET_TIME();
+
+    rtn=MPIN_BLS24_CLIENT(HASH_TYPE_BLS24,date,&CLIENT_ID,RNG,&X,pin,&TOKEN,&SEC,pxID,pxCID,pPERMIT,NULL,timeValue,&Y);
+
+    if (rtn != 0)
+    {
+        printf("MPIN_BLS24_CLIENT ERROR %d\n", rtn);
+        return 1;
+    }
+
+#ifdef FULL
+    MPIN_BLS24_GET_G1_MULTIPLE(RNG,1,&R,&HCID,&Z);  // Also Send Z=r.ID to Server, remember random r 
+#endif
+
+
+    rtn=MPIN_BLS24_SERVER(HASH_TYPE_BLS24,date,pHID,pHTID,&Y,&SST,pxID,pxCID,&SEC,pE,pF,pID,NULL,timeValue,NULL);
+
+#ifdef FULL
+    HASH_ID(HASH_TYPE_BLS24,&CLIENT_ID,&HSID);  // new
+    MPIN_BLS24_GET_G1_MULTIPLE(RNG,0,&W,prHID,&T);  // Also send T=w.ID to client, remember random w  
+#endif
+
+#else // SINGLE_PASS
+    printf("MPIN Multi Pass\n");
+    if (MPIN_BLS24_CLIENT_1(HASH_TYPE_BLS24,date,&CLIENT_ID,RNG,&X,pin,&TOKEN,&SEC,pxID,pxCID,pPERMIT)!=0)
+    {
+        printf("Error from Client side - First Pass\n");
+        return 0;
+    }
+
+    // Send U=x.ID to server, and recreate secret from token and pin 
+
+#ifdef FULL
+    HASH_ID(HASH_TYPE_BLS24,&CLIENT_ID,&HCID);
+    MPIN_BLS24_GET_G1_MULTIPLE(RNG,1,&R,&HCID,&Z);  // Also Send Z=r.ID to Server, remember random r, DH component 
+#endif
+
+    // Server calculates H(ID) and H(ID)+H(T|H(ID)) (if time permits enabled), and maps them to points on the curve HID and HTID resp. 
+    MPIN_BLS24_SERVER_1(HASH_TYPE_BLS24,date,pID,pHID,pHTID);
+
+    // Server generates Random number Y and sends it to Client 
+    MPIN_BLS24_RANDOM_GENERATE(RNG,&Y);
+
+#ifdef FULL
+    HASH_ID(HASH_TYPE_BLS24,&CLIENT_ID,&HSID); //new
+    MPIN_BLS24_GET_G1_MULTIPLE(RNG,0,&W,prHID,&T);  // Also send T=w.ID to client, remember random w, DH component  
+#endif
+
+    // Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC 
+    if (MPIN_BLS24_CLIENT_2(&X,&Y,&SEC)!=0)
+    {
+        printf("Error from Client side - Second Pass\n");
+        return 1;
+    }
+
+    // Server Second phase. 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=MPIN_BLS24_SERVER_2(date,pHID,pHTID,&Y,&SST,pxID,pxCID,&SEC,pE,pF,NULL);
+#endif // SINGLE_PASS
+
+    if (rtn!=0)
+    {
+        printf("Server says - Bad Pin.\n");
+#ifdef PINERROR
+
+        err=MPIN_BLS24_KANGAROO(&E,&F);
+        if (err) printf("(Client PIN is out by %d)\n",err);
+
+#endif
+        return 1;
+    }
+    else
+    {
+        printf("Server says - PIN is good! You really are ");
+        OCT_output_string(&CLIENT_ID);
+        printf(".\n");
+    }
+
+#ifdef FULL
+
+    HASH_ALL(HASH_TYPE_BLS24,&HCID,pxID,pxCID,&SEC,&Y,&Z,&T,&H);  // new
+    MPIN_BLS24_CLIENT_KEY(HASH_TYPE_BLS24,&G1,&G2,pin,&R,&X,&H,&T,&CK);      // new H
+    printf("Client Key = ");
+    OCT_output(&CK);
+
+    HASH_ALL(HASH_TYPE_BLS24,&HSID,pxID,pxCID,&SEC,&Y,&Z,&T,&H);
+    MPIN_BLS24_SERVER_KEY(HASH_TYPE_BLS24,&Z,&SST,&W,&H,pHID,pxID,pxCID,&SK); // new H,pHID
+    printf("Server Key = ");
+    OCT_output(&SK);
+#endif
+    return 0;
+}
+
+
+int mpin256_BLS48(csprng *RNG)
+{
+    int i,pin,rtn,err;
+#ifdef PERMITS
+    int date=today();
+#else
+    int date=0;
+#endif
+    unsigned long ran;
+    char x[PGS_BLS48],s[PGS_BLS48],y[PGS_BLS48],client_id[100],sst[16*PFS_BLS48],token[2*PFS_BLS48+1],sec[2*PFS_BLS48+1],permit[2*PFS_BLS48+1],xcid[2*PFS_BLS48+1],xid[2*PFS_BLS48+1],e[48*PFS_BLS48],f[48*PFS_BLS48];
+    char hcid[PFS_BLS48],hsid[PFS_BLS48],hid[2*PFS_BLS48+1],htid[2*PFS_BLS48+1],h[PGS_BLS48];
+#ifdef FULL
+    char r[PGS_BLS48],z[2*PFS_BLS48+1],w[PGS_BLS48],t[2*PFS_BLS48+1];
+    char g1[48*PFS_BLS48],g2[48*PFS_BLS48];
+    char ck[AESKEY_BLS48],sk[AESKEY_BLS48];
+#endif
+    octet S= {0,sizeof(s),s};
+    octet X= {0,sizeof(x),x};
+    octet Y= {0,sizeof(y),y};
+    octet H= {0,sizeof(h),h};
+    octet CLIENT_ID= {0,sizeof(client_id),client_id};
+    octet SST= {0,sizeof(sst),sst};
+    octet TOKEN= {0,sizeof(token),token};
+    octet SEC= {0,sizeof(sec),sec};
+    octet PERMIT= {0,sizeof(permit),permit};
+    octet xCID= {0,sizeof(xcid),xcid};
+    octet xID= {0,sizeof(xid),xid};
+    octet HCID= {0,sizeof(hcid),hcid};
+    octet HSID= {0,sizeof(hsid),hsid};
+    octet HID= {0,sizeof(hid),hid};
+    octet HTID= {0,sizeof(htid),htid};
+    octet E= {0,sizeof(e),e};
+    octet F= {0,sizeof(f),f};
+#ifdef FULL
+    octet R= {0,sizeof(r),r};
+    octet Z= {0,sizeof(z),z};
+    octet W= {0,sizeof(w),w};
+    octet T= {0,sizeof(t),t};
+    octet G1= {0,sizeof(g1),g1};
+    octet G2= {0,sizeof(g2),g2};
+    octet SK= {0,sizeof(sk),sk};
+    octet CK= {0,sizeof(ck),ck};
+#endif
+    octet *pxID,*pxCID,*pHID,*pHTID,*pE,*pF,*pPERMIT,*prHID;
+    char idhex[100];
+
+    // Trusted Authority set-up 
+    MPIN_BLS48_RANDOM_GENERATE(RNG,&S);
+    printf("Master Secret= ");
+    OCT_output(&S);
+
+    // Create Client Identity 
+    OCT_jstring(&CLIENT_ID,"testUser@miracl.com");
+    HASH_ID(HASH_TYPE_BLS48,&CLIENT_ID,&HCID);  // Either Client or TA calculates Hash(ID) - you decide! 
+
+    printf("Client ID Hash= ");
+    OCT_output(&HCID);
+    printf("\n");
+
+    OCT_toHex(&CLIENT_ID,idhex);
+    printf("Client ID= %s\n",idhex);// OCT_toHex(&CLIENT_ID); printf("\n");
+
+    MPIN_BLS48_GET_CLIENT_SECRET(&S,&HCID,&TOKEN);
+    printf("Client Secret= ");
+    OCT_output(&TOKEN);
+
+// Client and Server are issued secrets by DTA 
+    MPIN_BLS48_GET_SERVER_SECRET(&S,&SST);
+    printf("Server Secret= ");
+    OCT_output(&SST);
+
+
+
+    // Client extracts PIN from secret to create Token 
+    pin=1234;
+    printf("Client extracts PIN= %d\n",pin);
+    MPIN_BLS48_EXTRACT_PIN(HASH_TYPE_BLS48,&CLIENT_ID,pin,&TOKEN);
+    printf("Client Token= ");
+    OCT_output(&TOKEN);
+
+#ifdef FULL
+    MPIN_BLS48_PRECOMPUTE(&TOKEN,&HCID,NULL,&G1,&G2);
+#endif
+
+#ifdef PERMITS
+    // Client gets "Time Permit" from DTA 
+    printf("Client gets Time Permit\n");
+
+    MPIN_BLS48_GET_CLIENT_PERMIT(HASH_TYPE_BLS48,date,&S,&HCID,&PERMIT);
+    printf("Time Permit= ");
+    OCT_output(&PERMIT);
+
+    // This encoding makes Time permit look random 
+    if (MPIN_BLS48_ENCODING(RNG,&PERMIT)!=0) printf("Encoding error\n");
+    // printf("Encoded Time Permit= "); OCT_output(&PERMIT); 
+    if (MPIN_BLS48_DECODING(&PERMIT)!=0) printf("Decoding error\n");
+    // printf("Decoded Time Permit= "); OCT_output(&PERMIT); 
+#endif
+
+    // MPin Protocol 
+
+    // Client enters PIN 
+    printf("\nPIN= ");
+    if(scanf("%d",&pin)) {};
+    // to avoid silly compile error 
+    getchar();
+
+    // 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
+
+   // HSID - hashed client ID as calculated by the server
+   // HCID - hashed client ID as calculated by the client
+
+   // 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.
+
+    
+
+    pxID=&xID;
+    pxCID=&xCID;
+    pHID=&HID;
+    pHTID=&HTID;
+    pE=&E;
+    pF=&F;
+    pPERMIT=&PERMIT;
+
+#ifdef PERMITS
+    prHID=pHTID;
+#ifndef PINERROR
+    pxID=NULL;
+//   pHID=NULL;  //new
+#endif
+#else
+    prHID=pHID;
+    pPERMIT=NULL;
+    pxCID=NULL;
+    pHTID=NULL;
+#endif
+#ifndef PINERROR
+    pE=NULL;
+    pF=NULL;
+#endif
+
+    // When set only send hashed IDs to server 
+    octet *pID;
+#ifdef USE_ANONYMOUS
+    pID = &HCID;
+#else
+    pID = &CLIENT_ID;
+#endif
+
+#ifdef SINGLE_PASS
+    int timeValue;
+    printf("MPIN Single Pass\n");
+    timeValue = MPIN_BLS48_GET_TIME();
+
+    rtn=MPIN_BLS48_CLIENT(HASH_TYPE_BLS48,date,&CLIENT_ID,RNG,&X,pin,&TOKEN,&SEC,pxID,pxCID,pPERMIT,NULL,timeValue,&Y);
+
+    if (rtn != 0)
+    {
+        printf("MPIN_BLS48_CLIENT ERROR %d\n", rtn);
+        return 1;
+    }
+
+#ifdef FULL
+    MPIN_BLS48_GET_G1_MULTIPLE(RNG,1,&R,&HCID,&Z);  // Also Send Z=r.ID to Server, remember random r 
+#endif
+
+
+    rtn=MPIN_BLS48_SERVER(HASH_TYPE_BLS48,date,pHID,pHTID,&Y,&SST,pxID,pxCID,&SEC,pE,pF,pID,NULL,timeValue,NULL);
+
+#ifdef FULL
+    HASH_ID(HASH_TYPE_BLS48,&CLIENT_ID,&HSID);  // new
+    MPIN_BLS48_GET_G1_MULTIPLE(RNG,0,&W,prHID,&T);  // Also send T=w.ID to client, remember random w  
+#endif
+
+#else // SINGLE_PASS
+    printf("MPIN Multi Pass\n");
+    if (MPIN_BLS48_CLIENT_1(HASH_TYPE_BLS48,date,&CLIENT_ID,RNG,&X,pin,&TOKEN,&SEC,pxID,pxCID,pPERMIT)!=0)
+    {
+        printf("Error from Client side - First Pass\n");
+        return 0;
+    }
+
+    // Send U=x.ID to server, and recreate secret from token and pin 
+
+#ifdef FULL
+    HASH_ID(HASH_TYPE_BLS48,&CLIENT_ID,&HCID);
+    MPIN_BLS48_GET_G1_MULTIPLE(RNG,1,&R,&HCID,&Z);  // Also Send Z=r.ID to Server, remember random r, DH component 
+#endif
+
+    // Server calculates H(ID) and H(ID)+H(T|H(ID)) (if time permits enabled), and maps them to points on the curve HID and HTID resp. 
+    MPIN_BLS48_SERVER_1(HASH_TYPE_BLS48,date,pID,pHID,pHTID);
+
+    // Server generates Random number Y and sends it to Client 
+    MPIN_BLS48_RANDOM_GENERATE(RNG,&Y);
+
+#ifdef FULL
+    HASH_ID(HASH_TYPE_BLS48,&CLIENT_ID,&HSID); //new
+    MPIN_BLS48_GET_G1_MULTIPLE(RNG,0,&W,prHID,&T);  // Also send T=w.ID to client, remember random w, DH component  
+#endif
+
+    // Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC 
+    if (MPIN_BLS48_CLIENT_2(&X,&Y,&SEC)!=0)
+    {
+        printf("Error from Client side - Second Pass\n");
+        return 1;
+    }
+
+    // Server Second phase. 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=MPIN_BLS48_SERVER_2(date,pHID,pHTID,&Y,&SST,pxID,pxCID,&SEC,pE,pF,NULL);
+#endif // SINGLE_PASS
+
+    if (rtn!=0)
+    {
+        printf("Server says - Bad Pin.\n");
+#ifdef PINERROR
+
+        err=MPIN_BLS48_KANGAROO(&E,&F);
+        if (err) printf("(Client PIN is out by %d)\n",err);
+
+#endif
+        return 1;
+    }
+    else
+    {
+        printf("Server says - PIN is good! You really are ");
+        OCT_output_string(&CLIENT_ID);
+        printf(".\n");
+    }
+
+#ifdef FULL
+
+    HASH_ALL(HASH_TYPE_BLS48,&HCID,pxID,pxCID,&SEC,&Y,&Z,&T,&H);  // new
+    MPIN_BLS48_CLIENT_KEY(HASH_TYPE_BLS48,&G1,&G2,pin,&R,&X,&H,&T,&CK);      // new H
+    printf("Client Key = ");
+    OCT_output(&CK);
+
+    HASH_ALL(HASH_TYPE_BLS48,&HSID,pxID,pxCID,&SEC,&Y,&Z,&T,&H);
+    MPIN_BLS48_SERVER_KEY(HASH_TYPE_BLS48,&Z,&SST,&W,&H,pHID,pxID,pxCID,&SK); // new H,pHID
+    printf("Server Key = ");
+    OCT_output(&SK);
+#endif
+    return 0;
+}
+
+
+#endif
+
+int rsa_2048(csprng *RNG)
+{
+    int i;
+    unsigned long ran;
+    char m[RFS_2048],ml[RFS_2048],c[RFS_2048],e[RFS_2048],s[RFS_2048];
+    rsa_public_key_2048 pub;
+    rsa_private_key_2048 priv;
+    
+    octet M= {0,sizeof(m),m};
+    octet ML= {0,sizeof(ml),ml};
+    octet C= {0,sizeof(c),c};
+    octet E= {0,sizeof(e),e};
+    octet S= {0,sizeof(s),s};
+
+    printf("Generating public/private key pair\n");
+    RSA_2048_KEY_PAIR(RNG,65537,&priv,&pub,NULL,NULL);
+
+    printf("Encrypting test string\n");
+    OCT_jstring(&M,(char *)"Hello World\n");
+
+    OAEP_ENCODE(HASH_TYPE_RSA_2048,&M,RNG,NULL,&E); // OAEP encode message m to e  
+
+    RSA_2048_ENCRYPT(&pub,&E,&C);     // encrypt encoded message 
+    printf("Ciphertext= ");
+    OCT_output(&C);
+
+    printf("Decrypting test string\n");
+    RSA_2048_DECRYPT(&priv,&C,&ML);   // ... and then decrypt it 
+
+    OAEP_DECODE(HASH_TYPE_RSA_2048,NULL,&ML);    // decode it 
+    OCT_output_string(&ML);
+
+    printf("Signing message\n");
+    PKCS15(HASH_TYPE_RSA_2048,&M,&C);
+
+    RSA_2048_DECRYPT(&priv,&C,&S); // create signature in S 
+
+    printf("Signature= ");
+    OCT_output(&S);
+
+    RSA_2048_ENCRYPT(&pub,&S,&ML);
+
+    if (OCT_comp(&C,&ML)) printf("Signature is valid\n");
+    else printf("Signature is INVALID\n");
+
+    RSA_2048_PRIVATE_KEY_KILL(&priv);
+
+    OCT_clear(&M);
+    OCT_clear(&ML);   // clean up afterwards 
+    OCT_clear(&C);
+    OCT_clear(&E);
+
+    return 0;
+}
+
+
+int main()
+{
+    int i,res;
+    unsigned long ran;
+
+	char raw[100];
+    octet RAW= {0,sizeof(raw),raw};
+    csprng RNG;                // Crypto Strong RNG 
+
+    time((time_t *)&ran);
+
+    RAW.len=100;				// fake random seed source 
+    RAW.val[0]=ran;
+    RAW.val[1]=ran>>8;
+    RAW.val[2]=ran>>16;
+    RAW.val[3]=ran>>24;
+    for (i=0; i<100; i++) RAW.val[i]=i;
+
+    CREATE_CSPRNG(&RNG,&RAW);   // initialise strong RNG 
+
+	printf("\nTesting MPIN protocols for curve BN254\n");
+	mpin_BN254(&RNG);
+
+#if CHUNK!=16
+    printf("\nTesting MPIN protocols for curve BLS383\n");
+    mpin_BLS383(&RNG);
+    printf("\nTesting MPIN protocols for curve BLS24\n");
+    mpin192_BLS24(&RNG);
+    printf("\nTesting MPIN protocols for curve BLS48\n");
+    mpin256_BLS48(&RNG);
+#endif
+
+
+	printf("\nTesting ECDH protocols for curve ED25519\n");
+	ecdh_ED25519(&RNG);
+#if CHUNK!=16
+	printf("\nTesting ECDH protocols for curve NIST256\n");
+	ecdh_NIST256(&RNG);
+	printf("\nTesting ECDH protocols for curve GOLDILOCKS\n");
+	ecdh_GOLDILOCKS(&RNG);
+#endif
+	printf("\nTesting RSA protocols for 2048-bit RSA\n");
+	rsa_2048(&RNG);
+
+	KILL_CSPRNG(&RNG);
+}
+
diff --git a/version3/c/testnhs.c b/version3/c/testnhs.c
new file mode 100644
index 0000000..dca7925
--- /dev/null
+++ b/version3/c/testnhs.c
@@ -0,0 +1,71 @@
+/*
+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.
+*/
+
+/* test driver and function exerciser for NewHope Functions */
+
+// See https://eprint.iacr.org/2016/1157 (Alkim, Ducas, Popplemann and Schwabe)
+
+/* gcc -O2 testnhs.c amcl.a -o testnhs.exe */
+
+#include <stdio.h>
+#include <time.h>
+#include "newhope.h"
+
+int main()
+{
+	int i,ii,j,err;
+    unsigned long ran;
+	char raw[100];
+	csprng SRNG,CRNG;
+	RAND_clean(&SRNG); RAND_clean(&CRNG);
+	char s[1792],sb[1824],uc[2176],keyA[32],keyB[32];
+
+	octet S= {0,sizeof(s),s};
+	octet SB= {0,sizeof(sb),sb};
+	octet UC= {0,sizeof(uc),uc};
+	octet KEYA={0,sizeof(keyA),keyA};
+	octet KEYB={0,sizeof(keyB),keyB};
+
+// initialise random number generators
+    time((time_t *)&ran);
+
+    raw[0]=ran;
+    raw[1]=ran>>8;
+    raw[2]=ran>>16;
+    raw[3]=ran>>24;
+
+	for (i=4;i<100;i++) raw[i]=i+1;
+	RAND_seed(&SRNG,100,raw);
+										for (i=4;i<100;i++) raw[i]=i+2;
+										RAND_seed(&CRNG,100,raw);
+// NewHope Simple key exchange
+
+	NHS_SERVER_1(&SRNG,&SB,&S);
+										NHS_CLIENT(&CRNG,&SB,&UC,&KEYB);
+	NHS_SERVER_2(&S,&UC,&KEYA);
+
+    printf("Alice key= 0x");
+    OCT_output(&KEYA);
+										printf("Bob's key= 0x");
+										OCT_output(&KEYB);
+
+	return 0;
+}
+
+
diff --git a/version3/c/x509.c b/version3/c/x509.c
new file mode 100644
index 0000000..84f6c53
--- /dev/null
+++ b/version3/c/x509.c
@@ -0,0 +1,1097 @@
+/*
+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.
+*/
+
+/* AMCL X.509 Functions */
+
+// To run test program, define HAS_MAIN
+// gcc -std=c99 x509.c  amcl.a -o x509.exe
+
+//#define HAS_MAIN
+
+#include <stdio.h>
+#include "amcl.h"  // for octet support only
+#include "x509.h"
+
+// ASN.1 tags
+
+#define ANY 0x00
+#define SEQ 0x30
+#define OID 0x06
+#define INT 0x02
+#define NUL 0x05
+#define ZER 0x00
+#define UTF 0x0C
+#define UTC 0x17
+#define LOG 0x01
+#define BIT 0x03
+#define OCT 0x04
+#define STR 0x13
+#define SET 0x31
+#define IA5 0x16
+
+// Supported Encryption Methods
+
+#define ECC 1
+#define RSA 2
+
+// Supported Hash functions
+
+#define H256 2
+#define H384 3
+#define H512 4
+
+// Supported Curves
+
+#define NIST256 0    /**< For the NIST 256-bit standard curve - WEIERSTRASS only */
+#define C25519 1     /**< Bernstein's Modulus 2^255-19 - EDWARDS or MONTGOMERY only */
+#define BRAINPOOL 2  /**< For Brainpool 256-bit curve - WEIERSTRASS only */
+#define ANSSI 3      /**< For French 256-bit standard curve - WEIERSTRASS only */
+#define NIST384 10   /**< For the NIST 384-bit standard curve - WEIERSTRASS only */
+#define NIST521 12   /**< For the NIST 521-bit standard curve - WEIERSTRASS only */
+
+
+// Define some OIDs
+
+// Elliptic Curve with SHA256
+static unsigned char eccsha256[8]= {0x2a,0x86,0x48,0xce,0x3d,0x04,0x03,0x02};
+static octet ECCSHA256= {8,sizeof(eccsha256),(char *)eccsha256};
+
+// Elliptic Curve with SHA384
+static unsigned char eccsha384[8]= {0x2a,0x86,0x48,0xce,0x3d,0x04,0x03,0x03};
+static octet ECCSHA384= {8,sizeof(eccsha384),(char *)eccsha384};
+
+// Elliptic Curve with SHA512
+static unsigned char eccsha512[8]= {0x2a,0x86,0x48,0xce,0x3d,0x04,0x03,0x04};
+static octet ECCSHA512= {8,sizeof(eccsha512),(char *)eccsha512};
+
+// EC Public Key
+static unsigned char ecpk[7]= {0x2a,0x86,0x48,0xce,0x3d,0x02,0x01};
+static octet ECPK= {7,sizeof(ecpk),(char *)ecpk};
+
+// C25519 curve
+static unsigned char prime25519[9]= {0x2B,0x06,0x01,0x04,0x01,0xDA,0x47,0x0F,0x01}; /*****/
+static octet PRIME25519= {9,sizeof(prime25519),(char *)prime25519};
+
+// NIST256 curve
+static unsigned char prime256v1[8]= {0x2a,0x86,0x48,0xce,0x3d,0x03,0x01,0x07};
+static octet PRIME256V1= {8,sizeof(prime256v1),(char *)prime256v1};
+
+// NIST384 curve
+static unsigned char secp384r1[5]= {0x2B,0x81,0x04,0x00,0x22};
+static octet SECP384R1= {5,sizeof(secp384r1),(char *)secp384r1};
+
+// NIST521 curve
+static unsigned char secp521r1[5]= {0x2B,0x81,0x04,0x00,0x23};
+static octet SECP521R1= {5,sizeof(secp521r1),(char *)secp521r1};
+
+// RSA Public Key
+static unsigned char rsapk[9]= {0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01};
+static octet RSAPK= {9,sizeof(rsapk),(char *)rsapk};
+
+// RSA with SHA256
+static unsigned char rsasha256[9]= {0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b};
+static octet RSASHA256= {9,sizeof(rsasha256),(char *)rsasha256};
+
+// RSA with SHA384
+static unsigned char rsasha384[9]= {0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0c};
+static octet RSASHA384= {9,sizeof(rsasha384),(char *)rsasha384};
+
+// RSA with SHA512
+static unsigned char rsasha512[9]= {0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0d};
+static octet RSASHA512= {9,sizeof(rsasha512),(char *)rsasha512};
+
+#ifdef HAS_MAIN
+// countryName
+static unsigned char cn[3]= {0x55,0x04,0x06};
+static octet CN= {3,sizeof(cn),(char *)cn};
+
+// stateName
+// static char sn[3]= {0x55,0x04,0x08};
+// static octet SN= {3,sizeof(sn),sn};
+
+// localName
+// static char ln[3]= {0x55,0x04,0x07};
+// static octet LN= {3,sizeof(ln),ln};
+
+// orgName
+static unsigned char on[3]= {0x55,0x04,0x0A};
+static octet ON= {3,sizeof(on),(char *)on};
+
+// unitName
+// static char un[3]= {0x55,0x04,0x0B};
+// static octet UN= {3,sizeof(un),un};
+
+// myName
+// static char mn[3]= {0x55,0x04,0x03};
+// static octet MN= {3,sizeof(mn),mn};
+
+// emailName
+static unsigned char en[9]= {0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x09,0x01};
+static octet EN= {9,sizeof(en),(char *)en};
+#endif // HAS_MAIN
+
+/* Check expected TAG and return ASN.1 field length. If tag=0 skip check. */
+static int getalen(int tag,char *b,int j)
+{
+    int len;
+
+    if (tag!=0 && (unsigned char)b[j]!=tag) return -1; // not a valid tag
+    j++;
+
+    if ((unsigned char)b[j]==0x81)
+    {
+        j++;
+        len=(unsigned char)b[j];
+    }
+    else if ((unsigned char)b[j]==0x82)
+    {
+        j++;
+        len=256*b[j++];
+        len+=(unsigned char)b[j];
+    }
+    else
+    {
+        len=(unsigned char)b[j];
+        if (len>127) return -1;
+    }
+    return len;
+}
+
+/* jump over length field */
+static int skip(int len)
+{
+    if (len<128) return 2;
+    if (len>=128 && len<256) return 3;
+    return 4;
+}
+
+/* round length up to nearest 8-byte length */
+static int bround(int len)
+{
+    if (len%8==0) return len;
+    return len+(8-len%8);
+
+}
+
+//	Input signed cert as octet, and extract signature
+//	Return 0 for failure, ECC for Elliptic Curve signature, RSA for RSA signature
+//  Note that signature type is not provided here - its the type of the public key that
+//  is used to verify it that matters, and which determines for example the curve to be used!
+
+pktype X509_extract_cert_sig(octet *sc,octet *sig)
+{
+    int i,j,k,fin,len,rlen,sj,ex;
+    char soid[9];
+    octet SOID= {0,sizeof(soid),soid};
+    pktype ret;
+
+    ret.type=0;
+    ret.hash=0;
+
+    j=0;
+
+    len=getalen(SEQ,sc->val,j);		// Check for expected SEQ clause, and get length
+    if (len<0) return ret;			// if not a SEQ clause, there is a problem, exit
+    j+=skip(len);					// skip over length to clause contents. Add len to skip clause
+
+    if (len+j!=sc->len) return ret;
+
+    len=getalen(SEQ,sc->val,j);
+    if (len<0) return ret;
+    j+=skip(len)+len; // jump over cert to signature OID
+
+    len=getalen(SEQ,sc->val,j);
+    if (len<0) return ret;
+    j+=skip(len);
+
+    sj=j+len; // Needed to jump over signature OID
+
+// dive in to extract OID
+    len=getalen(OID,sc->val,j);
+    if (len<0) return ret;
+    j+=skip(len);
+
+    fin=j+len;
+    SOID.len=len;
+    for (i=0; j<fin; j++)
+        SOID.val[i++]= sc->val[j];
+
+    // check OID here..
+
+    if (OCT_comp(&ECCSHA256,&SOID))
+    {
+        ret.type=ECC;
+        ret.hash=H256;
+    }
+    if (OCT_comp(&ECCSHA384,&SOID))
+    {
+        ret.type=ECC;
+        ret.hash=H384;
+    }
+    if (OCT_comp(&ECCSHA512,&SOID))
+    {
+        ret.type=ECC;
+        ret.hash=H512;
+    }
+    if (OCT_comp(&RSASHA256,&SOID))
+    {
+        ret.type=RSA;
+        ret.hash=H256;
+    }
+    if (OCT_comp(&RSASHA384,&SOID))
+    {
+        ret.type=RSA;
+        ret.hash=H384;
+    }
+    if (OCT_comp(&RSASHA512,&SOID))
+    {
+        ret.type=RSA;
+        ret.hash=H512;
+    }
+
+    if (ret.type==0) return ret; // unsupported type
+
+    j=sj;  // jump out to signature
+
+    len=getalen(BIT,sc->val,j);
+    if (len<0)
+    {
+        ret.type=0;
+        return ret;
+    }
+    j+=skip(len);
+    j++;
+    len--; // skip bit shift (hopefully 0!)
+
+    if (ret.type==ECC)
+    {
+        // signature in the form (r,s)
+        len=getalen(SEQ,sc->val,j);
+        if (len<0)
+        {
+            ret.type=0;
+            return ret;
+        }
+        j+=skip(len);
+
+        // pick up r part of signature
+        len=getalen(INT,sc->val,j);
+        if (len<0)
+        {
+            ret.type=0;
+            return ret;
+        }
+        j+=skip(len);
+
+        if (sc->val[j]==0)
+        {
+            // skip leading zero
+            j++;
+            len--;
+        }
+        rlen=bround(len);
+
+        ex=rlen-len;
+        sig->len=2*rlen;
+
+        i=0;
+        for (k=0; k<ex; k++)
+            sig->val[i++]=0;
+
+        fin=j+len;
+        for (; j<fin; j++)
+            sig->val[i++]= sc->val[j];
+
+        // pick up s part of signature
+        len=getalen(INT,sc->val,j);
+        if (len<0)
+        {
+            ret.type=0;
+            return ret;
+        }
+        j+=skip(len);
+
+        if (sc->val[j]==0)
+        {
+            // skip leading zeros
+            j++;
+            len--;
+        }
+        rlen=bround(len);
+        ex=rlen-len;
+        for (k=0; k<ex; k++)
+            sig->val[i++]=0;
+
+        fin=j+len;
+        for (; j<fin; j++)
+            sig->val[i++]= sc->val[j];
+
+    }
+    if (ret.type==RSA)
+    {
+        rlen=bround(len);
+        ex=rlen-len;
+
+        sig->len=rlen;
+        i=0;
+        for (k=0; k<ex; k++)
+            sig->val[i++]=0;
+
+        fin=j+len;
+        for (; j<fin; j++)
+            sig->val[i++]= sc->val[j];
+
+    }
+    if (ret.hash==H256) ret.curve=NIST256;
+    if (ret.hash==H384) ret.curve=NIST384;
+    if (ret.hash==H512) ret.curve=NIST521;
+
+    return ret;
+}
+
+// Extract certificate from signed cert
+int X509_extract_cert(octet *sc,octet *cert)
+{
+    int i,j,fin,len,k;
+
+    j=0;
+    len=getalen(SEQ,sc->val,j);
+
+    if (len<0) return 0;
+    j+=skip(len);
+
+    k=j;
+
+    len=getalen(SEQ,sc->val,j);
+    if (len<0) return 0;
+    j+=skip(len);
+
+    fin=j+len;
+    cert->len=fin-k;
+    for (i=k; i<fin; i++) cert->val[i-k]=sc->val[i];
+
+    return 1;
+}
+
+// Extract Public Key from inside Certificate
+pktype X509_extract_public_key(octet *c,octet *key)
+{
+    int i,j,fin,len,sj;
+    char koid[12];     /*****/
+    octet KOID= {0,sizeof(koid),koid};
+    pktype ret;
+
+    ret.type=ret.hash=0;
+    ret.curve=-1;
+
+    j=0;
+
+    len=getalen(SEQ,c->val,j);
+    if (len<0) return ret;
+    j+=skip(len);
+
+    if (len+j!=c->len) return ret;
+
+    len=getalen(0,c->val,j);
+    if (len<0) return ret;
+    j+=skip(len)+len; //jump over version clause
+
+    len=getalen(INT,c->val,j);
+
+    if (len>0) j+=skip(len)+len; // jump over serial number clause (if there is one)
+
+    len=getalen(SEQ,c->val,j);
+    if (len<0) return ret;
+    j+=skip(len)+len;  // jump over signature algorithm
+
+    len=getalen(SEQ,c->val,j);
+    if (len<0) return ret;
+    j+=skip(len)+len; // skip issuer
+
+    len=getalen(SEQ,c->val,j);
+    if (len<0) return ret;
+    j+=skip(len)+len; // skip validity
+
+    len=getalen(SEQ,c->val,j);
+    if (len<0) return ret;
+    j+=skip(len)+len; // skip subject
+
+    len=getalen(SEQ,c->val,j);
+    if (len<0) return ret;
+    j+=skip(len); //
+
+    len=getalen(SEQ,c->val,j);
+    if (len<0) return ret;
+    j+=skip(len);
+
+// ** Maybe dive in and check Public Key OIDs here?
+// ecpublicKey & prime256v1, secp384r1 or secp521r1 for ECC
+// rsapublicKey for RSA
+
+    sj=j+len;
+
+    len=getalen(OID,c->val,j);
+    if (len<0) return ret;
+    j+=skip(len);
+
+    fin=j+len;
+    KOID.len=len;
+    for (i=0; j<fin; j++)
+        KOID.val[i++]= c->val[j];
+
+    ret.type=0;
+    if (OCT_comp(&ECPK,&KOID)) ret.type=ECC;
+    if (OCT_comp(&RSAPK,&KOID)) ret.type=RSA;
+
+    if (ret.type==0) return ret;
+
+    if (ret.type==ECC)
+    {
+        // which elliptic curve?
+        len=getalen(OID,c->val,j);
+        if (len<0)
+        {
+            ret.type=0;
+            return ret;
+        }
+        j+=skip(len);
+
+        fin=j+len;
+        KOID.len=len;
+        for (i=0; j<fin; j++)
+            KOID.val[i++]= c->val[j];
+
+        if (OCT_comp(&PRIME25519,&KOID)) ret.curve=C25519;   /*****/
+        if (OCT_comp(&PRIME256V1,&KOID)) ret.curve=NIST256;
+        if (OCT_comp(&SECP384R1,&KOID)) ret.curve=NIST384;
+        if (OCT_comp(&SECP521R1,&KOID)) ret.curve=NIST521;
+    }
+
+    j=sj; // skip to actual Public Key
+
+    len=getalen(BIT,c->val,j);
+    if (len<0)
+    {
+        ret.type=0;
+        return ret;
+    }
+    j+=skip(len); //
+    j++;
+    len--; // skip bit shift (hopefully 0!)
+
+// extract key
+    if (ret.type==ECC)
+    {
+        key->len=len;
+        fin=j+len;
+        for (i=0; j<fin; j++)
+            key->val[i++]= c->val[j];
+
+    }
+    if (ret.type==RSA)
+    {
+        // Key is (modulus,exponent) - assume exponent is 65537
+        len=getalen(SEQ,c->val,j);
+        if (len<0)
+        {
+            ret.type=0;
+            return ret;
+        }
+        j+=skip(len); //
+
+        len=getalen(INT,c->val,j); // get modulus
+        if (len<0)
+        {
+            ret.type=0;
+            return ret;
+        }
+        j+=skip(len); //
+        if (c->val[j]==0)
+        {
+            j++;
+            len--; // remove leading zero
+        }
+
+        key->len=len;
+        fin=j+len;
+        for (i=0; j<fin; j++)
+            key->val[i++]= c->val[j];
+
+        ret.curve=8*len;
+    }
+    return ret;
+}
+
+// Find pointer to main sections of cert, before extracting individual field
+// Find index to issuer in cert
+int X509_find_issuer(octet *c)
+{
+    int j,len;
+    j=0;
+    len=getalen(SEQ,c->val,j);
+    if (len<0) return 0;
+    j+=skip(len);
+
+    if (len+j!=c->len) return 0;
+
+    len=getalen(0,c->val,j);
+    if (len<0) return 0;
+    j+=skip(len)+len; //jump over version clause
+
+    len=getalen(INT,c->val,j);
+
+    if (len>0) j+=skip(len)+len; // jump over serial number clause (if there is one)
+
+    len=getalen(SEQ,c->val,j);
+    if (len<0) return 0;
+    j+=skip(len)+len;  // jump over signature algorithm
+
+    return j;
+}
+
+// Find index to validity period
+int X509_find_validity(octet *c)
+{
+    int j,len;
+    j=X509_find_issuer(c);
+
+    len=getalen(SEQ,c->val,j);
+    if (len<0) return 0;
+    j+=skip(len)+len; // skip issuer
+
+    return j;
+}
+
+// Find index to subject in cert
+int X509_find_subject(octet *c)
+{
+    int j,len;
+    j=X509_find_validity(c);
+
+    len=getalen(SEQ,c->val,j);
+    if (len<0) return 0;
+    j+=skip(len)+len; // skip validity
+
+    return j;
+}
+
+// NOTE: When extracting cert information, we actually return just an index to the data inside the cert, and maybe its length
+// So no memory is assigned to store cert info. It is the callers responsibility to allocate such memory if required, and copy
+// cert information into it.
+
+// Find entity property indicated by SOID, given start of issuer or subject field. Return index in cert, flen=length of field
+
+int X509_find_entity_property(octet *c,octet *SOID,int start,int *flen)
+{
+    int i,j,k,fin,len,tlen;
+    char foid[50];  /*****/
+    octet FOID= {0,sizeof(foid),foid};
+
+    j=start;
+
+    tlen=getalen(SEQ,c->val,j);
+    if (tlen<0) return 0;
+    j+=skip(tlen);
+
+    for (k=j; j<k+tlen;)
+    {
+        // search for Owner OID
+        len=getalen(SET,c->val,j);
+        if (len<0) return 0;
+        j+=skip(len);
+        len=getalen(SEQ,c->val,j);
+        if (len<0) return 0;
+        j+=skip(len);
+        len=getalen(OID,c->val,j);
+        if (len<0) return 0;
+        j+=skip(len);
+        fin=j+len;  // extract OID
+        FOID.len=len;
+        for (i=0; j<fin; j++)
+            FOID.val[i++]= c->val[j];
+        len=getalen(ANY,c->val,j);  // get text, could be any type
+        if (len<0) return 0;
+
+        j+=skip(len);
+        if (OCT_comp(&FOID,SOID))
+        {
+            // if its the right one return
+            *flen=len;
+            return j;
+        }
+        j+=len;  // skip over it
+    }
+    *flen=0; /*****/
+    return 0;
+}
+
+// Find start date of certificate validity period
+int X509_find_start_date(octet *c,int start)
+{
+    int j,len;
+    j=start;
+
+    len=getalen(SEQ,c->val,j);
+    if (len<0) return 0;
+    j+=skip(len);
+
+    len=getalen(UTC,c->val,j);
+    if (len<0) return 0;
+    j+=skip(len);
+    return j;
+}
+
+// Find expiry date of certificate validity period
+int X509_find_expiry_date(octet *c,int start)
+{
+    int j,len;
+    j=start;
+
+    len=getalen(SEQ,c->val,j);
+    if (len<0) return 0;
+    j+=skip(len);
+
+    len=getalen(UTC,c->val,j);
+    if (len<0) return 0;
+    j+=skip(len)+len;
+
+    len=getalen(UTC,c->val,j);
+    if (len<0) return 0;
+    j+=skip(len);
+
+    return j;
+}
+
+void print_out(char *des,octet *c,int index,int len)
+{
+    int i;
+    printf("%s [",des);
+    for (i=0; i<len; i++)
+        printf("%c",c->val[index+i]);
+    printf("]\n");
+}
+
+void print_date(char *des,octet *c,int index)
+{
+    int i=index;
+    printf("%s [",des);
+    if (i==0) printf("]\n");
+    else printf("20%c%c-%c%c-%c%c %c%c:%c%c:%c%c]\n",c->val[i],c->val[i+1],c->val[i+2],c->val[i+3],c->val[i+4],c->val[i+5],c->val[i+6],c->val[i+7],c->val[i+8],c->val[i+9],c->val[i+10],c->val[i+11]);
+}
+
+
+#ifdef HAS_MAIN
+
+/* This simple driver program is hard-wired to support just one elliptic curve and one
+   RSA bit length. To change replace the text string NIST256 in the main program to
+   another curve and 2048 to some other value, where the curve and the RSA bit length
+   are suppported by the library. Of course a more elaborate program could support
+   muliple curves simultaneously */
+
+#define CHOICE NIST256
+
+
+
+/* test driver program */
+// Sample Certs. Uncomment one CA cert and one example cert. Note that AMCL library must be built to support given curve.
+// Sample Certs all created using OpenSSL - see http://blog.didierstevens.com/2008/12/30/howto-make-your-own-cert-with-openssl/
+// Note - SSL currently only supports NIST curves. Howevever version 1.1.0 of OpenSSL now supports C25519
+
+#if CHOICE==NIST256
+
+#include "ecdh_NIST256.h"
+#include "rsa_2048.h"
+
+// ** CA is RSA 2048-bit based - for use with NIST256 build of library - assumes use of SHA256 in Certs
+// RSA 2048 Self-Signed CA cert
+char ca_b64[]="MIIDuzCCAqOgAwIBAgIJAP44jcM1MOROMA0GCSqGSIb3DQEBCwUAMHQxCzAJBgNVBAYTAklFMRAwDgYDVQQIDAdJcmVsYW5kMQ8wDQYDVQQHDAZEdWJsaW4xITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEfMB0GCSqGSIb3DQEJARYQbXNjb3R0QGluZGlnby5pZTAeFw0xNTExMjYwOTUwMzlaFw0yMDExMjUwOTUwMzlaMHQxCzAJBgNVBAYTAklFMRAwDgYDVQQIDAdJcmVsYW5kMQ8wDQYDVQQHDAZEdWJsaW4xITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEfMB0GCSqGSIb3DQEJARYQbXNjb3R0QGluZGlnby5pZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANUs7/nri9J8zw8rW8JVszXP0ZqeLoQJaq2X28ebm8x5VT3okr9rnBjFjpx0YKQCAFQf8iSOOYuNpDvtZ/YpsjPbk2rg5sLY9G0eUMqrTuZ7moPSxnrXS5evizjD9Z9HqaqeNEYD3sPouPg+lhU1oAUQjUTJVFhEr1x0EnSEYbbrWtY9ZDSuZv+d4NIeqqPOYFd1yZc+LYZyQbAAQqwRLNPZH/rnIykLa6I7w7mGT7H6SBz2O09BtgpTHhalL40ecXa4ZOEze0xwzlc+mEFIrnmdadg3vQrJt42RVbo3LN6RfDIqUZOMOtQW/53pUR1lIpCwVWJTiOpmSEIEqhhjFq0CAwEAAaNQME4wHQYDVR0OBBYEFJrz6LHeT6FcjRahpUC3hAMxKRTCMB8GA1UdIwQYMBaAFJrz6LHeT6FcjRahpUC3hAMxKRTCMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBADqkqCYVa3X8XO9Ufu6XIUoZafFPRjSeJXvEIWqlbm7ixJZ2FPOvf2eMc5RCZYigNKhsxru5Ojw0lPcpa8DDmEsdZDf7p0vlmf7T7xH9gtoInh4DzgI8HRHFc8R/z2/jLX7nlLoopKX5yp7F1gRACg0pd4tGpQ6EnBNcYZZghFH9UIRDmx+vDlwDCu8vyRPt35orrEiI4XGq/QkvxxAb5YWxQ4i06064ULfyCI7suu3KoobdM1aAaA8zhpOOBXKbq+Wi9IGFe/wiEMHLmfHdt9CBTjIWb//IHji4RT05kCmTVrx97pb7EHafuL3L10mM5cpTyBWKnb4kMFtx9yw+S2U=";
+// an RSA 2048 CA-signed cert
+//char cert_b64[]="MIIDcjCCAloCAQEwDQYJKoZIhvcNAQELBQAwdDELMAkGA1UEBhMCSUUxEDAOBgNVBAgMB0lyZWxhbmQxDzANBgNVBAcMBkR1YmxpbjEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMR8wHQYJKoZIhvcNAQkBFhBtc2NvdHRAaW5kaWdvLmllMB4XDTE1MTEyNjEwMzQzMFoXDTE3MTEyNTEwMzQzMFowgYkxCzAJBgNVBAYTAklFMRAwDgYDVQQIDAdJcmVsYW5kMQ8wDQYDVQQHDAZEdWJsaW4xETAPBgNVBAoMCENlcnRpVm94MQ0wCwYDVQQLDARMYWJzMQ0wCwYDVQQDDARNSUtFMSYwJAYJKoZIhvcNAQkBFhdtaWtlLnNjb3R0QGNlcnRpdm94LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMIoxaQHFQzfyNChrw+3i7FjRFMHZ4zspkjkAcJW21LdBCqrxU+sdjyBoSFlrlafQOHshbrEP93AKX1bfaYbuV4fzq7OlRaLxaK+b+xrOJdewMI2WZ5OwEzj3onZATISogIoB6dTdzJ41NuxuMqQ/DqOnVrRA0SoIespbQhB8FGHBLw0hJATBzUk+bqOIt0HmnMp2EbYgtuG4lYINU/lD3Qt16SunUukWRLtxqJkioie+dkhP2zm+bOlSVmeQb4Wp8AI14OKkTfkdYC8qCxb5eabg90Q33rQUhNwRQHhHwopZwD/BgodasoSrPfwUlj0awh6y87eMGcik5Q/mjkCk5MCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAFrd7R/67ClkbLhpiX++6QTOa47siUAB9v+Qil9hZfhPNeeM589ixYkD4zH5pOK2B0ea+CXEKkanQ6lXx9KV86yS7fq6Yww7wO0diecusHd0+P82i46Tq0nm8nlsnAuhYoFRUGa2m2DkB1HSsB0ts8DjzFLySonFjSSLHDU0ox9/uFbJMzipy3ijAA4XM0N4jRrUfrmxpA7DOOsbEbGkvvB7VK9+s9PHE/4dJTwhSteplUnhxVFkkDo/JwaLx4/IEQRlCF3KEQ5s3AwRHnbrIjOY2yONxHBtJEp7QN5aOHruwvMNRNheCBPiQJyLitUsFGr4voANmobkrFgYtu0tRMQ==";
+// an ECC 256 CA-signed cert
+char cert_b64[]="MIICojCCAYoCAQMwDQYJKoZIhvcNAQELBQAwdDELMAkGA1UEBhMCSUUxEDAOBgNVBAgMB0lyZWxhbmQxDzANBgNVBAcMBkR1YmxpbjEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMR8wHQYJKoZIhvcNAQkBFhBtc2NvdHRAaW5kaWdvLmllMB4XDTE1MTEyNjEzNDcyOVoXDTE3MTEyNTEzNDcyOVowgYQxCzAJBgNVBAYTAklFMRAwDgYDVQQIDAdJcmVsYW5kMQ8wDQYDVQQHDAZEdWJsaW4xETAPBgNVBAoMCENlcnRpdm94MQ0wCwYDVQQLDARMYWJzMQ8wDQYDVQQDDAZtc2NvdHQxHzAdBgkqhkiG9w0BCQEWEG1zY290dEBpbmRpZ28uaWUwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATO2iZiQZsXxzwBKnufKfZcsctNXZ4PmfJm638PmX9DQ3Xdb+nD5VxiOakNcB9xf5im8CriiOF5Z/7yPGyzUMbdMA0GCSqGSIb3DQEBCwUAA4IBAQAK5fMgGCCiPts8hMUZvYDpu8hd7qtPKPBc10QUccHb7PGrhqf/Ex2Gpj1aaURmx7SGZG0HX97LtkdW8KQpEoyaa60r7cjVA589TznxXKSGg5ggVoFJNpuZUm7VcolLjwIgTxtGbPzrvVMiZ4cl4PwFePXVKTl4f8XkOFX5gLmVSuCf729lEBmpx3IzqGmTjmnBixaApUElOKVeL7hiUKP3TqMUxZN+QNJBq4Mh9K9h4Sks2oneLwBwhMqQvpmcOb/7SucJn5N0IgJoGaMbfX0oCJJID1NSbagUSbFD1XciR2Ng9VtvnRP+htmEQ7jtww8phFdrWt5M5zPGOHUppqDx";
+
+// ** CA is ECC 256 based  - for use with NIST256 build of library
+// ECC 256 Self-Signed CA cert
+//char ca_b64[]="MIIB7TCCAZOgAwIBAgIJANp4nGS/VYj2MAoGCCqGSM49BAMCMFMxCzAJBgNVBAYTAklFMRAwDgYDVQQIDAdJcmVsYW5kMQ8wDQYDVQQHDAZEdWJsaW4xITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0xNTExMjYxMzI0MTBaFw0yMDExMjUxMzI0MTBaMFMxCzAJBgNVBAYTAklFMRAwDgYDVQQIDAdJcmVsYW5kMQ8wDQYDVQQHDAZEdWJsaW4xITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABPb6IjYNKyfbEtL1aafzW1jrn6ALn3PnGm7AyX+pcvwG0GKmb3Z/uHzhT4GysNE0/GB1n4Y/mrORQIm2X98rRs6jUDBOMB0GA1UdDgQWBBSfXUNkgJVklIhuXq4DCnVYhsdzwDAfBgNVHSMEGDAWgBSfXUNkgJVklIhuXq4DCnVYhsdzwDAMBgNVHRMEBTADAQH/MAoGCCqGSM49BAMCA0gAMEUCIQDrZJ1tshwTl/jabU2i49EOgbWe0ZgE3QZywJclf5IVwwIgVmz79AAf7e098lyrOKYAqbwjHVyMZGfmkNNGIuIhp/Q=";
+// an ECC 256 CA-signed cert
+//char cert_b64[]="MIIBvjCCAWQCAQEwCgYIKoZIzj0EAwIwUzELMAkGA1UEBhMCSUUxEDAOBgNVBAgMB0lyZWxhbmQxDzANBgNVBAcMBkR1YmxpbjEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMB4XDTE1MTEyNjEzMjc1N1oXDTE3MTEyNTEzMjc1N1owgYIxCzAJBgNVBAYTAklFMRAwDgYDVQQIDAdJcmVsYW5kMQ8wDQYDVQQHDAZEdWJsaW4xETAPBgNVBAoMCENlcnRpdm94MQ0wCwYDVQQLDARMYWJzMQ0wCwYDVQQDDARtaWtlMR8wHQYJKoZIhvcNAQkBFhBtc2NvdHRAaW5kaWdvLmllMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEY42H52TfWMLueKB1o2Sq8uKaKErbHJ2GRAxrnJdNxex0hxZF5FUx7664BbPUolKhpvKTnJxDq5/gMqXzpKgR6DAKBggqhkjOPQQDAgNIADBFAiEA0ew08Xg32g7BwheslVKwXo9XRRx4kygYha1+cn0tvaUCIEKCEwnosZlAckjcZt8aHN5zslE9K9Y7XxTErTstthKc";
+// an RSA 2048 CA-signed cert
+//char cert_b64[]="MIICiDCCAi4CAQIwCgYIKoZIzj0EAwIwUzELMAkGA1UEBhMCSUUxEDAOBgNVBAgMB0lyZWxhbmQxDzANBgNVBAcMBkR1YmxpbjEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMB4XDTE1MTEyNjEzMzcwNVoXDTE3MTEyNTEzMzcwNVowgYExCzAJBgNVBAYTAklFMQ8wDQYDVQQIDAZJZWxhbmQxDzANBgNVBAcMBkR1YmxpbjERMA8GA1UECgwIQ2VydGl2b3gxDTALBgNVBAsMBExhYnMxDTALBgNVBAMMBE1pa2UxHzAdBgkqhkiG9w0BCQEWEG1zY290dEBpbmRpZ28uaWUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCjPBVwmPg8Gwx0+8xekmomptA0BDwS7NUfBetqDqNMNyji0bSe8LAfpciU7NW/HWfUE1lndCqSDDwnMJmwC5e3GAl/Bus+a+z8ruEhWGbn95xrHXFkOawbRlXuS7UcEQCvPr8KQHhNsg4cyV7Hn527CPUl27n+WN8/pANo01cTN/dQaK87naU0Mid09vktlMKSN0zyJOnc5CsaTLs+vCRKJ9sUL3d4IQIA2y7gvrTe+iY/QI26nqhGpNWYyFkAdy9PdHUEnDI6JsfF7jFh37yG7XEgDDA3asp/oi1T1+ZoASj2boL++opdqCzDndeWwzDWAWuvJ9wULd80ti6x737ZAgMBAAEwCgYIKoZIzj0EAwIDSAAwRQIgCDwgl98+9moBo+etaLt8MvB/z5Ti6i9neRTZkvoFl7YCIQDq//M3OB757fepErRzIQo3aFAFYjOooi6WdSqP3XqGIg==";
+
+#endif
+
+#if CHOICE==NIST384
+
+#include "ecdh_NIST384.h"
+#include "rsa_3072.h"
+
+// ** CA is RSA 3072-bit based  - for use with NIST384 build of library - assumes use of SHA384 in Certs
+// RSA 3072 Self-Signed CA cert
+char ca_b64[]="MIIElzCCAv+gAwIBAgIJAJA+8OyEeK4FMA0GCSqGSIb3DQEBDAUAMGIxCzAJBgNVBAYTAklFMRAwDgYDVQQIDAdJcmVsYW5kMQ8wDQYDVQQHDAZEdWJsaW4xITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDENMAsGA1UEAwwETWlrZTAeFw0xNTExMjYxNDQ0MDBaFw0yMDExMjUxNDQ0MDBaMGIxCzAJBgNVBAYTAklFMRAwDgYDVQQIDAdJcmVsYW5kMQ8wDQYDVQQHDAZEdWJsaW4xITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDENMAsGA1UEAwwETWlrZTCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBANvNO8ahsanxzqwkp3A3bujwObJoP3xpOiAAxwGbW867wx4EqBjPRZP+Wcm9Du6e4Fx9U7tHrOLocIUUBcRrmxUJ7Z375hX0cV9yuoYPNv0o2klJhB8+i4YXddkOrSmDLV4r46Ytt1/gjImziat6ZJALdd/uIuhaXwjzy1fFqSEBpkzhrFwFP9MG+5CgbRQed+YxZ10l/rjk+h3LKq9UFsxRCMPYhBFgmEKAVTMnbTfNNxawTRCKtK7nxxruGvAEM+k0ge5rvybERQ0NxtizefBSsB3Q6QVZOsRJiyC0HQhE6ZBHn4h3A5nHUZwPeh71KShw3uMPPB3Kp1pb/1Euq8azyXSshEMPivvgcGJSlm2b/xqsyrT1tie82MqB0APYAtbx3i5q8p+rD143NiNO8fzCq/J+EV82rVyvqDxf7AaTdJqDbZmnFRbIcrLcQdigWZdSjc+WxrCeOtebRmRknuUmetsCUPVzGv71PLMUNQ2qEiq8KGWmnMBJYVMl96bPxwIDAQABo1AwTjAdBgNVHQ4EFgQUsSjrHeZ5TNI2tMcQd6wUnFpU8DcwHwYDVR0jBBgwFoAUsSjrHeZ5TNI2tMcQd6wUnFpU8DcwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQwFAAOCAYEADlnC1gYIHpVf4uSuBpYNHMO324hhGajHNraHYQAoYc0bW4OcKi0732ib5CHDrV3LCxjxF4lxZVo61gatg5LnfJYldXc0vP0GQRcaqC6lXlLb8ZJ0O3oPgZkAqpzc+AQxYW1wFxbzX8EJU0stSwAuxkgs9bwg8tTxIhDutrcjQl3osnAqGDyM+7VAG5QLRMzxiZumyD7s/xBUOa+L6OKXf4QRr/SH/rPU8H+ENaNkv4PApSVzCgTBPOFBIzqEuO4hcQI0laUopsp2kK1w6wYB5oY/rR/O6lNNfB2WEtfdIhdbQru4cUE3boKerM8Mjd21RuerAuK4X8cbDudHIFsaopGSNuzZwPo/bu0OsmZkORxvdjahHJ0G3/6jM6nEDoIy6mXUCGOUOMhGQKCa8TYlZdPKz29QIxk6HA1wCA38MxUo/29Z7oYw27Mx3x8Gcr+UA4vc+oBN3IEzRmhRZKAYQ10MhYPx3NmYGZBDqHvT06oG5hysTCtlVzx0Tm+o01JQ";
+// an RSA 3072 CA-signed cert
+//char cert_b64[]="MIIEWzCCAsMCAQYwDQYJKoZIhvcNAQEMBQAwYjELMAkGA1UEBhMCSUUxEDAOBgNVBAgMB0lyZWxhbmQxDzANBgNVBAcMBkR1YmxpbjEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMQ0wCwYDVQQDDARNaWtlMB4XDTE1MTEyNjE0NDY0MloXDTE3MTEyNTE0NDY0MlowgYQxCzAJBgNVBAYTAklFMRAwDgYDVQQIDAdJcmVsYW5kMQ8wDQYDVQQHDAZEdWJsaW4xETAPBgNVBAoMCENlcnRpdm94MQ0wCwYDVQQLDARMYWJzMQ8wDQYDVQQDDAZtc2NvdHQxHzAdBgkqhkiG9w0BCQEWEG1zY290dEBpbmRpZ28uaWUwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQC6SrDiE4BpTEks1YpX209q8iH0dfvhGO8hi1rGYFYnz+eeiOvPdXiCdIPVPbGwxQGMEnZQV1X0KupYJw3LR2EsXhN4LZBxnQZmDvUXsTU+Ft/CKZUxVoXpNMxzwl70RC6XeUpPxvdPXa78AnfLL/DsOKsxCfNaKYZZ6G53L6Y69+HrCbyM7g2KrZ9/K/FXS1veMpRj9EbA6Mcdv1TUDNK2fTDV952AQO3kC3+PqywdVgPvntraAoQomrni+tcFW7UXe2Sk7DRcF/acBSuo2UtP3m9UWNL+8HOXvtRqmhns55Vj4DxKuPln759UBS7WZ11apCvC3BvCHR/k3WRf9PQWnW2cmT73/kEShvTRi8h7F9RWvYTEF1MuwSVy+l51q8O3rJU4XxnLm/YbtIGXZUf5Rqb0985zQkA+6rip/OSc8X5a3OV3kp38U7tXJ5sqBMg9RdIIz42cmiRLG5NYSj0/T6zjYEdwj3SYEBoPN/7UGSmhu8fdxS7JYPNpOsgeiu8CAwEAATANBgkqhkiG9w0BAQwFAAOCAYEAyxxEg0hWLFuN2fiukX6vqzSDx5Ac8w1JI4W/bamRd7iDZfHQYqyPDZi9s07I2PcGbByj2oqoyGiIEBLbsljdIEF4D229h2kisn1gA9O+0IM44EgjhBTUoNDgC+SbfJrXlU2GZ1XI3OWjbK7+1wiv0NaBShbbiPgSdjQBP8S+9W7lyyIrZEM1J7maBdepie1BS//DUDmpQzEi0UlB1J+HmQpyZsnT97J9uIPKsK4t2/+iOiknl6iS4GzAQKMLqj2yIBRf/O44ZZ6UZIKLtI4PCVS/8H5Lrg3AC0kr4ZkPAXzefUiTwyLVkqYSxSSTvtb3BpgOxIbmA6juFid0rvUyjN4fuDQkxl3PZyQwIHjpz33HyKrmo4BZ8Dg4JT8LCsQgd0AaD3r0QOS5FdLhkb+rD8EMSsCoOCEtPI6lqLJCrGOQWj7zbcUdPOEsczWMI9hSfK3u/P9+gOUBUFkb0gBIn3WvNuHifIHpsZ5bzbR+SGtu5Tgc7CCCPyNgz1Beb247";
+// an ECC 384 CA-signed cert
+char cert_b64[]="MIIDCDCCAXACAQcwDQYJKoZIhvcNAQEMBQAwYjELMAkGA1UEBhMCSUUxEDAOBgNVBAgMB0lyZWxhbmQxDzANBgNVBAcMBkR1YmxpbjEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMQ0wCwYDVQQDDARNaWtlMB4XDTE1MTEyNjE1MzU1M1oXDTE3MTEyNTE1MzU1M1owYDELMAkGA1UEBhMCSUUxEDAOBgNVBAgMB0lyZWxhbmQxDzANBgNVBAcMBkR1YmxpbjEQMA4GA1UECgwHQ2VydGl2bzENMAsGA1UECwwETGFiczENMAsGA1UEAwwEbWlrZTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJ1J+FT5mxxYEM4aYKM0CvZHmh8JFXzoBmzibabrvyTz79+1QOrR+6MEEsKtmJIYPJi+GsQ0PmjF2HmJncM1zeQh7DQYJf2Xc8p5Vjd8//6YREBVfN3UIyrl87MSucy+mjANBgkqhkiG9w0BAQwFAAOCAYEAmuwa64+K1qlCELpcnCyWwMhSb+Zsw0Hh6q/BfxalZhsX1UFEwE9nHoVJcokaEEYF4u4AYXU5rdysRHxYBfgMbohguTT7sJwCfve2JqpqvhQOkGDG1DB4Ho4y7NPPYB2+UMd7JMD0TOcHXdgQ8FtAE0ClD8VkW0gAC0lCrbQbynfLoUjIWqg3w2g79hvdZPgRt208nFiHuezynOaEFePoXl8CxHInsxAnMaJn2fEs5/QH67pwD65mPdNFsvlr0zdzYcceqEmEHpRAXFOQAJtffGjWAGGX/CsghLuqlpdCiTGA1B53XoXKJvArr/kHpTNMsU1NnkQIHZ5n4USCo4QgL6n9nwem7U2mYBYjmxPi5Y3JJnTZz4zUnv0bD0vSwoivnFZox9H6qTAkeIX1ojJ2ujxWHNOMvOFb6nU2gqNZj2vYcO38OIrK9gwM9lm4FF20YBufh+WOzQthrHJv0YuQt3NuDQEMkvz+23YvzZlr+e2XqDlMhyR01Kk0MXeLGGcv";
+
+// ** CA is ECC 384 based - - for use with NIST384 build of library - assumes use of SHA384 in Certs
+// ECC 384 Self-Signed CA Cert
+//char ca_b64[]="MIICSTCCAc6gAwIBAgIJAIwHpOFSZLXnMAoGCCqGSM49BAMDMGIxCzAJBgNVBAYTAklFMRAwDgYDVQQIDAdJcmVsYW5kMQ8wDQYDVQQHDAZEdWJsaW4xITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDENMAsGA1UEAwwEbWlrZTAeFw0xNTExMjYxNTQ0NTlaFw0yMDExMjUxNTQ0NTlaMGIxCzAJBgNVBAYTAklFMRAwDgYDVQQIDAdJcmVsYW5kMQ8wDQYDVQQHDAZEdWJsaW4xITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDENMAsGA1UEAwwEbWlrZTB2MBAGByqGSM49AgEGBSuBBAAiA2IABOEPMYBqzIn1hJAMZ0aEVxQ08gBF2aSfWtEJtmKj64014w7VfWdeFQSIMP9SjmhatFbAvxep8xgcwbeAobGTqCgUp+0EdFZR1ktKSND/S+UDU1YSNCFRvlNTJ6YmXUkW36NQME4wHQYDVR0OBBYEFDQxIZoKNniNuW91UMJ1KWEjs045MB8GA1UdIwQYMBaAFDQxIZoKNniNuW91UMJ1KWEjs045MAwGA1UdEwQFMAMBAf8wCgYIKoZIzj0EAwMDaQAwZgIxANbml6sp5A92qQiCM/OtBf+TbXpSpIO83TuNP9V2lsphp0CEX3KwAuqBXB95m9/xWAIxAOXAT2LqieSbUh4fpxcdaeY01RoGtD2AQch1a6BuIugcQqTfqLcXy7D51R70R729sA==";
+// an ECC 384 CA-signed cert
+//char cert_b64[]="MIICCjCCAZACAQgwCgYIKoZIzj0EAwMwYjELMAkGA1UEBhMCSUUxEDAOBgNVBAgMB0lyZWxhbmQxDzANBgNVBAcMBkR1YmxpbjEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMQ0wCwYDVQQDDARtaWtlMB4XDTE1MTEyNjE1NTIxMFoXDTE3MTEyNTE1NTIxMFowgYIxCzAJBgNVBAYTAklFMRAwDgYDVQQIDAdJcmVsYW5kMQ8wDQYDVQQHDAZEdWJsaW4xETAPBgNVBAoMCENlcnRpdm94MQ0wCwYDVQQLDARMYWJzMQ0wCwYDVQQDDARtaWtlMR8wHQYJKoZIhvcNAQkBFhBtc2NvdHRAaW5kaWdvLmllMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEf2Qm6jH2U+vhAApsMqH9gzGCH8rk+mUwFSD3Uud4NiyPBqrJRC1eetVvr3cYb6ucDTa15km6QKvZZrsRW+Z4ZpryoEE6esmD4XPLrtrOtoxtxFNRhiMmT/M9zcrfMJC5MAoGCCqGSM49BAMDA2gAMGUCMF0x6PAvvnJR3riZdUPC4OWFC2K3eiz3QuLCdFOZVIqX7mkLftdS8BtzusXWMMgFCQIxALJNMKLs39P9wYQHu1C+v9ieltQr20C+WVYxqUvgL/KTdxd9dzc3wseZRDT1CydqOA==";
+// an RSA 3072 CA-signed cert
+//char cert_b64[]="MIIDFjCCAp4CAQkwCgYIKoZIzj0EAwMwYjELMAkGA1UEBhMCSUUxEDAOBgNVBAgMB0lyZWxhbmQxDzANBgNVBAcMBkR1YmxpbjEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMQ0wCwYDVQQDDARtaWtlMB4XDTE1MTEyNjE2MTYwNloXDTE3MTEyNTE2MTYwNlowYzELMAkGA1UEBhMCSUUxEDAOBgNVBAgMB0lyZWxhbmQxDzANBgNVBAcMBkR1YmxpbjERMA8GA1UECgwIQ2VydGl2b3gxDTALBgNVBAsMBGxhYnMxDzANBgNVBAMMBmtlYWxhbjCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAK5QhVjR+UGt3ZWPSGicpviqaOhxXmmvOepdl5Seqr+Iweb3IuEDgtHGwrw/EEgWlKPfS/2LW9ncptdNbVQh7+2rojj7ZtedrAK5p7I9b22f2U3sSHIqjtTT0BjqzL0qEwy/ATqbf93Tcr3yT0Ygh3yzbvn4zodrWQZK8kkN3PQKkiHBCuIxo+8MlTs8d99dl1hbJ84MYZuPmhrkB4oLEAt8+srtL+a4Yd0wPhuCYrLjBnYkD9TlcWLWWh8/iwXiznrY8gQsXSveQNzQjcmHilZrTlTL2dnyI2v7BAXXHSwo6UeES0n064fnYTr3JB0GArMcty6RD3E7xr64HNzzTE2+8cDxufNvU0tq2Z72oZ9cAReHUL5P6mLfORI+AhtCHrXGJch/F07ZX9h8UFpzok8NK5++Q7lHKuezTYRRPlDL5hDB3BUpBwvILdqujcbNil04cuLRBNT/WgqRXEBRjlHLgZaLChFV2VSJ9Z1Uke2lfm5X2O0XPQLhjMSiuvr4HwIDAQABMAoGCCqGSM49BAMDA2YAMGMCLxHSQAYP2EsuIpR4TzDDSIlsw4BBsD7W0ZfH91v9J0j5UWQJD/yNjMtyA2Qlkq/0AjB+SJQbLgycNJH5SnR/X5wx26/62ln9s0swUtlCYVtNzyEQ3YRHSZbmTbh16RUT7Ak=";
+
+#endif
+
+#if CHOICE==NIST521
+
+#include "ecdh_NIST521.h"
+#include "rsa_4096.h"
+
+// ** CA is ECC 521 based - - for use with NIST521 build of library - assumes use of SHA512 in Certs
+// ECC 521 Self-Signed CA Cert
+char ca_b64[]="MIIC+TCCAlqgAwIBAgIJAKlppiHsRpY8MAoGCCqGSM49BAMEMIGUMQswCQYDVQQGEwJJRTEQMA4GA1UECAwHSXJlbGFuZDEPMA0GA1UEBwwGRHVibGluMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxDTALBgNVBAsMBExhYnMxDzANBgNVBAMMBm1zY290dDEfMB0GCSqGSIb3DQEJARYQbXNjb3R0QGluZGlnby5pZTAeFw0xNTEyMDExMzE5MjZaFw0yMDExMzAxMzE5MjZaMIGUMQswCQYDVQQGEwJJRTEQMA4GA1UECAwHSXJlbGFuZDEPMA0GA1UEBwwGRHVibGluMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxDTALBgNVBAsMBExhYnMxDzANBgNVBAMMBm1zY290dDEfMB0GCSqGSIb3DQEJARYQbXNjb3R0QGluZGlnby5pZTCBmzAQBgcqhkjOPQIBBgUrgQQAIwOBhgAEAKUj6Qa4Vr1vyango8XHlLIIEzY9IVppdpGUrMlNfo0Spu+AXGhnluwJTZXOYLi8jSIPEAL7vuwS5H6uPPIz1QWXALRETVYAQfK0pIfPHq+edTHVTXMcAUpdNla2d4LwYO7HpkSQFHd7aaDN3yVhSL2J0LBLgy0wGkEHuyK1O2r0xNu6o1AwTjAdBgNVHQ4EFgQU966PLshKffU/NRCivMmNq8RiRkAwHwYDVR0jBBgwFoAU966PLshKffU/NRCivMmNq8RiRkAwDAYDVR0TBAUwAwEB/zAKBggqhkjOPQQDBAOBjAAwgYgCQgHkLczeTWXq5BfY0bsTOSNU8bYy39OhiQ8wr5rlXY0zOg0fDyokueL4dhkXp8FjbIyUfQBY5OMxjtcn2p+cXU+6MwJCAci61REgxZvjpf1X8pGeSsOKa7GhfsfVnbQm+LQmjVmhMHbVRkQ4h93CENN4MH/86XNozO9USh+ydTislAcXvCb0";
+// an ECC 521 CA-signed cert
+char cert_b64[]="MIICZjCCAccCAQMwCgYIKoZIzj0EAwQwgZQxCzAJBgNVBAYTAklFMRAwDgYDVQQIDAdJcmVsYW5kMQ8wDQYDVQQHDAZEdWJsaW4xITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDENMAsGA1UECwwETGFiczEPMA0GA1UEAwwGbXNjb3R0MR8wHQYJKoZIhvcNAQkBFhBtc2NvdHRAaW5kaWdvLmllMB4XDTE1MTIwMTEzMjkxN1oXDTE3MTEzMDEzMjkxN1owYTELMAkGA1UEBhMCSUUxEDAOBgNVBAgMB0lyZWxhbmQxDzANBgNVBAcMBkR1YmxpbjERMA8GA1UECgwIQ2VydGlWb3gxDTALBgNVBAsMBExhYnMxDTALBgNVBAMMBE1pa2UwgZswEAYHKoZIzj0CAQYFK4EEACMDgYYABAAva/N4kP2LMSGJZ5tvULlfdNx2M/+xYeCrQkuFmY8sG+mdcUAaSx819fztn2jz1nfdTJnuj79AhfUOL8hlTW14BwErp3DnqWa7Y/rpSJP+AsnJ2bZg4yGUDfVy/Q0AQychSzJm2oGRfdliyBIc+2SoQJ/Rf0ZVKVJ5FfRbWUUiKqYUqjAKBggqhkjOPQQDBAOBjAAwgYgCQgFE1Y7d9aBdxpZqROtkdVNG8XBCTSlMX0fISWkSM8ZEiQfYf7YgXzLjk8wHnv04Mv6kmAuV0V1AHs2M0/753CYEfAJCAPZo801McsGe+3jYALrFFw9Wj7KQC/sFEJ7/I+PYyJtrlfTTqmV0IFKdJzjEsk7ic+Gd4Nbs6kIe1GyYbrcyC4wT";
+
+#endif
+
+char io[5000];
+octet IO= {0,sizeof(io),io};
+
+#define MAXMODBYTES 72
+#define MAXFFLEN 16
+
+char sig[MAXMODBYTES*MAXFFLEN];
+octet SIG= {0,sizeof(sig),sig};
+
+char r[MAXMODBYTES];
+octet R= {0,sizeof(r),r};
+
+char s[MAXMODBYTES];
+octet S= {0,sizeof(s),s};
+
+char cakey[MAXMODBYTES*MAXFFLEN];
+octet CAKEY= {0,sizeof(cakey),cakey};
+
+char certkey[MAXMODBYTES*MAXFFLEN];
+octet CERTKEY= {0,sizeof(certkey),certkey};
+
+char h[5000];
+octet H= {0,sizeof(h),h};
+
+char hh[5000];
+octet HH= {0,sizeof(hh),hh};
+
+char hp[RFS_2048];
+octet HP= {0,sizeof(hp),hp};
+
+
+int main()
+{
+    int res,len,sha;
+    int c,ic;
+    rsa_public_key_2048 PK;
+    pktype st,ca,pt;
+
+    printf("First check signature on self-signed cert and extract CA public key\n");
+    OCT_frombase64(&IO,ca_b64);
+    printf("CA Self-Signed Cert= \n");
+    OCT_output(&IO);
+    printf("\n");
+
+    st=X509_extract_cert_sig(&IO,&SIG); // returns signature type
+
+    if (st.type==0)
+    {
+        printf("Unable to extract cert signature\n");
+        return 0;
+    }
+
+    if (st.type==ECC)
+    {
+        OCT_chop(&SIG,&S,SIG.len/2);
+        OCT_copy(&R,&SIG);
+        printf("ECC SIG= \n");
+        OCT_output(&R);
+        OCT_output(&S);
+        printf("\n");
+    }
+
+    if (st.type==RSA)
+    {
+        printf("RSA SIG= \n");
+        OCT_output(&SIG);
+        printf("\n");
+    }
+
+    if (st.hash==H256) printf("Hashed with SHA256\n");
+    if (st.hash==H384) printf("Hashed with SHA384\n");
+    if (st.hash==H512) printf("Hashed with SHA512\n");
+
+// Extract Cert from signed Cert
+
+    c=X509_extract_cert(&IO,&H);
+
+    printf("\nCert= \n");
+    OCT_output(&H);
+    printf("\n");
+
+// show some details
+    printf("Issuer Details\n");
+    ic=X509_find_issuer(&H);
+    c=X509_find_entity_property(&H,&ON,ic,&len);
+    print_out("owner=",&H,c,len);
+    c=X509_find_entity_property(&H,&CN,ic,&len);
+    print_out("country=",&H,c,len);
+    c=X509_find_entity_property(&H,&EN,ic,&len);
+    print_out("email=",&H,c,len);
+    printf("\n");
+
+    ca=X509_extract_public_key(&H,&CAKEY);
+
+    if (ca.type==0)
+    {
+        printf("Not supported by library\n");
+        return 0;
+    }
+    if (ca.type!=st.type)
+    {
+        printf("Not self-signed\n");
+    }
+
+    if (ca.type==ECC)
+    {
+        printf("EXTRACTED ECC PUBLIC KEY= \n");
+        OCT_output(&CAKEY);
+    }
+    if (ca.type==RSA)
+    {
+        printf("EXTRACTED RSA PUBLIC KEY= \n");
+        OCT_output(&CAKEY);
+    }
+    printf("\n");
+
+// Cert is self-signed - so check signature
+
+    printf("Checking Self-Signed Signature\n");
+    if (ca.type==ECC)
+    {
+        if (ca.curve!=CHOICE)
+        {
+            printf("Curve is not supported\n");
+            return 0;
+        }
+        res=ECP_NIST256_PUBLIC_KEY_VALIDATE(1,&CAKEY);
+        if (res!=0)
+        {
+            printf("ECP Public Key is invalid!\n");
+            return 0;
+        }
+        else printf("ECP Public Key is Valid\n");
+
+        sha=0;
+
+        if (st.hash==H256) sha=SHA256;
+        if (st.hash==H384) sha=SHA384;
+        if (st.hash==H512) sha=SHA512;
+        if (st.hash==0)
+        {
+            printf("Hash Function not supported\n");
+            return 0;
+        }
+
+        if (ECP_NIST256_VP_DSA(sha,&CAKEY,&H,&R,&S)!=0)
+        {
+            printf("***ECDSA Verification Failed\n");
+            return 0;
+        }
+        else
+            printf("ECDSA Signature/Verification succeeded \n");
+    }
+
+    if (ca.type==RSA)
+    {
+        if (ca.curve!=2048)
+        {
+            printf("RSA bit size is not supported\n");
+            return 0;
+        }
+        PK.e=65537; // assuming this!
+        RSA_2048_fromOctet(PK.n,&CAKEY);
+
+        sha=0;
+
+        if (st.hash==H256) sha=SHA256;
+        if (st.hash==H384) sha=SHA384;
+        if (st.hash==H512) sha=SHA512;
+        if (st.hash==0)
+        {
+            printf("Hash Function not supported\n");
+            return 0;
+        }
+        PKCS15(sha,&H,&HP);
+
+        RSA_2048_ENCRYPT(&PK,&SIG,&HH);
+
+        if (OCT_comp(&HP,&HH))
+            printf("RSA Signature/Verification succeeded \n");
+        else
+        {
+            printf("***RSA Verification Failed\n");
+            return 0;
+        }
+    }
+
+    printf("\nNext check CA signature on cert, and extract public key\n");
+
+    OCT_frombase64(&IO,cert_b64);
+    printf("Example Cert= \n");
+    OCT_output(&IO);
+    printf("\n");
+
+    st=X509_extract_cert_sig(&IO,&SIG);
+
+    if (st.type==0)
+    {
+        printf("Unable to check cert signature\n");
+        return 0;
+    }
+
+    if (st.type==ECC)
+    {
+        OCT_chop(&SIG,&S,SIG.len/2);
+        OCT_copy(&R,&SIG);
+        printf("SIG= \n");
+        OCT_output(&R);
+
+        OCT_output(&S);
+
+        printf("\n");
+    }
+
+    if (st.type==RSA)
+    {
+        printf("SIG= \n");
+        OCT_output(&SIG);
+        printf("\n");
+    }
+
+    c=X509_extract_cert(&IO,&H);
+
+    printf("Cert= \n");
+    OCT_output(&H);
+    printf("\n");
+
+    printf("Subject Details\n");
+    ic=X509_find_subject(&H);
+    c=X509_find_entity_property(&H,&ON,ic,&len);
+    print_out("owner=",&H,c,len);
+    c=X509_find_entity_property(&H,&CN,ic,&len);
+    print_out("country=",&H,c,len);
+    c=X509_find_entity_property(&H,&EN,ic,&len);
+    print_out("email=",&H,c,len);
+    printf("\n");
+
+    ic=X509_find_validity(&H);
+    c=X509_find_start_date(&H,ic);
+    print_date("start date= ",&H,c);
+    c=X509_find_expiry_date(&H,ic);
+    print_date("expiry date=",&H,c);
+    printf("\n");
+
+    pt=X509_extract_public_key(&H,&CERTKEY);
+
+    if (pt.type==0)
+    {
+        printf("Not supported by library\n");
+        return 0;
+    }
+
+    if (pt.type==ECC)
+    {
+        printf("EXTRACTED ECC PUBLIC KEY= \n");
+        OCT_output(&CERTKEY);
+    }
+    if (pt.type==RSA)
+    {
+        printf("EXTRACTED RSA PUBLIC KEY= \n");
+        OCT_output(&CERTKEY);
+    }
+
+    printf("\n");
+
+    /* Check CA signature */
+
+    if (ca.type==ECC)
+    {
+        printf("Checking CA's ECC Signature on Cert\n");
+        res=ECP_NIST256_PUBLIC_KEY_VALIDATE(1,&CAKEY);
+        if (res!=0)
+            printf("ECP Public Key is invalid!\n");
+        else printf("ECP Public Key is Valid\n");
+
+        sha=0;
+
+        if (st.hash==H256) sha=SHA256;
+        if (st.hash==H384) sha=SHA384;
+        if (st.hash==H512) sha=SHA512;
+        if (st.hash==0)
+        {
+            printf("Hash Function not supported\n");
+            return 0;
+        }
+
+        if (ECP_NIST256_VP_DSA(sha,&CAKEY,&H,&R,&S)!=0)
+            printf("***ECDSA Verification Failed\n");
+        else
+            printf("ECDSA Signature/Verification succeeded \n");
+    }
+
+    if (ca.type==RSA)
+    {
+        printf("Checking CA's RSA Signature on Cert\n");
+        PK.e=65537; // assuming this!
+        RSA_2048_fromOctet(PK.n,&CAKEY);
+
+        sha=0;
+
+        if (st.hash==H256) sha=SHA256;
+        if (st.hash==H384) sha=SHA384;
+        if (st.hash==H512) sha=SHA512;
+        if (st.hash==0)
+        {
+            printf("Hash Function not supported\n");
+            return 0;
+        }
+        PKCS15(sha,&H,&HP);
+
+        RSA_2048_ENCRYPT(&PK,&SIG,&HH);
+
+        if (OCT_comp(&HP,&HH))
+            printf("RSA Signature/Verification succeeded \n");
+        else
+            printf("***RSA Verification Failed\n");
+
+    }
+
+    return 0;
+}
+
+#endif
diff --git a/version3/c/x509.h b/version3/c/x509.h
new file mode 100644
index 0000000..2c4a7b9
--- /dev/null
+++ b/version3/c/x509.h
@@ -0,0 +1,109 @@
+/*
+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.
+*/
+
+/* AMCL x509 header file */
+
+/**
+ * @file x509.h
+ * @author Mike Scott
+ * @brief X509 function Header File
+ *
+ */
+
+#ifndef X509_H
+#define X509_H
+
+/**
+ * @brief Public key type
+ */
+typedef struct
+{
+    int type;  /**< signature type (ECC or RSA) */
+    int hash;  /**< hash type */
+    int curve; /**< elliptic curve used or RSA key length in bits  */
+} pktype;
+
+
+/* X.509 functions */
+/** @brief Extract certificate signature
+ *
+	@param c an X.509 certificate
+	@param s the extracted signature
+	@return 0 on failure, or indicator of signature type (ECC or RSA)
+
+*/
+extern pktype X509_extract_cert_sig(octet *c,octet *s);
+/** @brief
+ *
+	@param sc a signed certificate
+	@param c the extracted certificate
+	@return 0 on failure
+*/
+extern int X509_extract_cert(octet *sc,octet *c);
+/** @brief
+ *
+	@param c an X.509 certificate
+	@param k the extracted key
+	@return 0 on failure, or indicator of public key type (ECC or RSA)
+*/
+extern pktype X509_extract_public_key(octet *c,octet *k);
+/** @brief
+ *
+	@param c an X.509 certificate
+	@return 0 on failure, or pointer to issuer field in cert
+*/
+extern int X509_find_issuer(octet *c);
+/** @brief
+ *
+	@param c an X.509 certificate
+	@return 0 on failure, or pointer to validity field in cert
+*/
+extern int X509_find_validity(octet *c);
+/** @brief
+ *
+	@param c an X.509 certificate
+	@return 0 on failure, or pointer to subject field in cert
+*/
+extern int X509_find_subject(octet *c);
+/** @brief
+ *
+	@param c an X.509 certificate
+	@param S is OID of property we are looking for
+	@param s is a pointer to the section of interest in the cert
+	@param f is pointer to the length of the property
+	@return 0 on failure, or pointer to the property
+*/
+extern int X509_find_entity_property(octet *c,octet *S,int s,int *f);
+/** @brief
+ *
+	@param c an X.509 certificate
+	@param s is a pointer to the start of the validity field
+	@return 0 on failure, or pointer to the start date
+*/
+extern int X509_find_start_date(octet *c,int s);
+/** @brief
+ *
+	@param c an X.509 certificate
+	@param s is a pointer to the start of the validity field
+	@return 0 on failure, or pointer to the expiry date
+*/
+extern int X509_find_expiry_date(octet *c,int s);
+
+
+#endif
diff --git a/version3/check.cpp b/version3/check.cpp
new file mode 100644
index 0000000..5835644
--- /dev/null
+++ b/version3/check.cpp
@@ -0,0 +1,108 @@
+/*
+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.
+*/
+
+/* Utility to recommend best choice for BASEBITS 
+
+(MINGW build)
+
+g++ -O2 check.cpp big.cpp miracl.a -o check.exe */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "big.h"
+
+using namespace std;
+
+Miracl precision=20;
+
+// calculate maximum excess given base, length in words, length in bits
+int maxxes(int b,int n,int m)
+{
+	int mx=n*b-m;
+	int tp=m%b;
+	if (mx >= tp)
+		mx=tp-1;
+	return mx;
+}
+
+int main(int argc, char *argv[])
+{
+	int p,w,b,n,s,t,e,ex,mx;
+	Big lhs,rhs;
+
+	argc--; argv++;
+
+    if (argc!=2)
+    {
+       printf("Bad arguments\n");
+       printf("check wordlength modulus-length\n");
+	   printf("Wordlength can be 16, 32 or 64 (or 26 for Javascript)\n");
+       printf("Example:\n");
+       printf("check 32 256\n");
+	   printf("Outputs choices for BASEBITS, number of words per Big, and number of spare bits\n");
+	   printf("Normally choose for minimum words per Big, and maximum excess bits\n");
+	   printf("Ideally >=5 excess bits for Edwards curves\n");
+	   printf("Ideally >=10 excess bits for Weierstrass curves\n");
+	   printf("Ideally >=23 excess bits for pairings\n");
+       exit(0);
+    }
+
+    n=atoi(argv[0]);
+	p=atoi(argv[1]); // Number of bits in prime modulus
+
+	if (n!=16 && n!=26 && n!=32 && n!=64)
+	{
+		printf("wordlength must be 16, 32 or 64 (or 26 for Javascript)\n");
+		return 0;
+	}
+
+	rhs=pow((Big)2,2*n-1);
+	e=3;            // need at least 3 bits to allow adds and subtracts without normalisation
+	if (n==26)
+	{
+		rhs*=2;	// no sign bit to worry about in Javascript
+		e=1;	// not an issue for Javascript
+	}
+
+	for (b=n-e;b>=n-8;b--)
+	{
+		if (n==64 && b%2!=0) continue; // insist on even values for 64-bit builds 
+		w=p/b; if (p%b!=0) w++;
+		s=w*b-p;
+
+		lhs=(w+2)*pow((Big)2,2*b);  // sum of products plus carry plus one for redc
+
+		if (lhs>=rhs)    {printf("Stability violation for BASEBITS= %d\n",b); continue;}
+
+		mx=s;
+		if (mx>(n-4)/2)
+			mx=(n-4)/2;
+
+// At least 4 bits spare needed for field excess.  
+		if (mx<4) {printf("Not enough Fp excess for BASEBITS= %d\n",b); continue;}
+// At least 2 spare bits needed for FF excess 
+		t=b*(1+(p-1)/b) - 8*(1+(p-1)/8);
+		if (t<2 || t>=b) {printf("Not enough FF excess for BASEBITS= %d\n",b);}
+
+		printf("Solution for BASEBITS= %d, Words Per Big=%d, Max excess= %d\n",b,w,mx);
+	}
+	
+	return 0;
+}
diff --git a/version3/cpp/aes.cpp b/version3/cpp/aes.cpp
new file mode 100644
index 0000000..4d4c325
--- /dev/null
+++ b/version3/cpp/aes.cpp
@@ -0,0 +1,706 @@
+/*
+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.
+*/
+
+
+/*
+ * Implementation of the NIST Advanced Ecryption Standard
+ *
+ * SU=m, SU is Stack Usage
+ */
+
+#include <stdlib.h>
+
+
+#include "arch.h"
+#include "amcl.h"
+
+/* this is fixed */
+#define NB 4
+
+/* Rotates 32-bit word left by 1, 2 or 3 byte  */
+
+#define ROTL8(x) (((x)<<8)|((x)>>24))
+#define ROTL16(x) (((x)<<16)|((x)>>16))
+#define ROTL24(x) (((x)<<24)|((x)>>8))
+
+static const uchar InCo[4]= {0xB,0xD,0x9,0xE}; /* Inverse Coefficients */
+
+static const uchar ptab[]=
+{
+    1,3,5,15,17,51,85,255,26,46,114,150,161,248,19,53,
+    95,225,56,72,216,115,149,164,247,2,6,10,30,34,102,170,
+    229,52,92,228,55,89,235,38,106,190,217,112,144,171,230,49,
+    83,245,4,12,20,60,68,204,79,209,104,184,211,110,178,205,
+    76,212,103,169,224,59,77,215,98,166,241,8,24,40,120,136,
+    131,158,185,208,107,189,220,127,129,152,179,206,73,219,118,154,
+    181,196,87,249,16,48,80,240,11,29,39,105,187,214,97,163,
+    254,25,43,125,135,146,173,236,47,113,147,174,233,32,96,160,
+    251,22,58,78,210,109,183,194,93,231,50,86,250,21,63,65,
+    195,94,226,61,71,201,64,192,91,237,44,116,156,191,218,117,
+    159,186,213,100,172,239,42,126,130,157,188,223,122,142,137,128,
+    155,182,193,88,232,35,101,175,234,37,111,177,200,67,197,84,
+    252,31,33,99,165,244,7,9,27,45,119,153,176,203,70,202,
+    69,207,74,222,121,139,134,145,168,227,62,66,198,81,243,14,
+    18,54,90,238,41,123,141,140,143,138,133,148,167,242,13,23,
+    57,75,221,124,132,151,162,253,28,36,108,180,199,82,246,1
+};
+
+static const uchar ltab[]=
+{
+    0,255,25,1,50,2,26,198,75,199,27,104,51,238,223,3,
+    100,4,224,14,52,141,129,239,76,113,8,200,248,105,28,193,
+    125,194,29,181,249,185,39,106,77,228,166,114,154,201,9,120,
+    101,47,138,5,33,15,225,36,18,240,130,69,53,147,218,142,
+    150,143,219,189,54,208,206,148,19,92,210,241,64,70,131,56,
+    102,221,253,48,191,6,139,98,179,37,226,152,34,136,145,16,
+    126,110,72,195,163,182,30,66,58,107,40,84,250,133,61,186,
+    43,121,10,21,155,159,94,202,78,212,172,229,243,115,167,87,
+    175,88,168,80,244,234,214,116,79,174,233,213,231,230,173,232,
+    44,215,117,122,235,22,11,245,89,203,95,176,156,169,81,160,
+    127,12,246,111,23,196,73,236,216,67,31,45,164,118,123,183,
+    204,187,62,90,251,96,177,134,59,82,161,108,170,85,41,157,
+    151,178,135,144,97,190,220,252,188,149,207,205,55,63,91,209,
+    83,57,132,60,65,162,109,71,20,42,158,93,86,242,211,171,
+    68,17,146,217,35,32,46,137,180,124,184,38,119,153,227,165,
+    103,74,237,222,197,49,254,24,13,99,140,128,192,247,112,7
+};
+
+static const uchar fbsub[]=
+{
+    99,124,119,123,242,107,111,197,48,1,103,43,254,215,171,118,
+    202,130,201,125,250,89,71,240,173,212,162,175,156,164,114,192,
+    183,253,147,38,54,63,247,204,52,165,229,241,113,216,49,21,
+    4,199,35,195,24,150,5,154,7,18,128,226,235,39,178,117,
+    9,131,44,26,27,110,90,160,82,59,214,179,41,227,47,132,
+    83,209,0,237,32,252,177,91,106,203,190,57,74,76,88,207,
+    208,239,170,251,67,77,51,133,69,249,2,127,80,60,159,168,
+    81,163,64,143,146,157,56,245,188,182,218,33,16,255,243,210,
+    205,12,19,236,95,151,68,23,196,167,126,61,100,93,25,115,
+    96,129,79,220,34,42,144,136,70,238,184,20,222,94,11,219,
+    224,50,58,10,73,6,36,92,194,211,172,98,145,149,228,121,
+    231,200,55,109,141,213,78,169,108,86,244,234,101,122,174,8,
+    186,120,37,46,28,166,180,198,232,221,116,31,75,189,139,138,
+    112,62,181,102,72,3,246,14,97,53,87,185,134,193,29,158,
+    225,248,152,17,105,217,142,148,155,30,135,233,206,85,40,223,
+    140,161,137,13,191,230,66,104,65,153,45,15,176,84,187,22
+};
+
+static const uchar rbsub[]=
+{
+    82,9,106,213,48,54,165,56,191,64,163,158,129,243,215,251,
+    124,227,57,130,155,47,255,135,52,142,67,68,196,222,233,203,
+    84,123,148,50,166,194,35,61,238,76,149,11,66,250,195,78,
+    8,46,161,102,40,217,36,178,118,91,162,73,109,139,209,37,
+    114,248,246,100,134,104,152,22,212,164,92,204,93,101,182,146,
+    108,112,72,80,253,237,185,218,94,21,70,87,167,141,157,132,
+    144,216,171,0,140,188,211,10,247,228,88,5,184,179,69,6,
+    208,44,30,143,202,63,15,2,193,175,189,3,1,19,138,107,
+    58,145,17,65,79,103,220,234,151,242,207,206,240,180,230,115,
+    150,172,116,34,231,173,53,133,226,249,55,232,28,117,223,110,
+    71,241,26,113,29,41,197,137,111,183,98,14,170,24,190,27,
+    252,86,62,75,198,210,121,32,154,219,192,254,120,205,90,244,
+    31,221,168,51,136,7,199,49,177,18,16,89,39,128,236,95,
+    96,81,127,169,25,181,74,13,45,229,122,159,147,201,156,239,
+    160,224,59,77,174,42,245,176,200,235,187,60,131,83,153,97,
+    23,43,4,126,186,119,214,38,225,105,20,99,85,33,12,125
+};
+
+static const unsign32 rco[]=
+{1,2,4,8,16,32,64,128,27,54,108,216,171,77,154,47};
+
+static const unsign32 ftable[]=
+{
+    0xa56363c6,0x847c7cf8,0x997777ee,0x8d7b7bf6,0xdf2f2ff,0xbd6b6bd6,
+    0xb16f6fde,0x54c5c591,0x50303060,0x3010102,0xa96767ce,0x7d2b2b56,
+    0x19fefee7,0x62d7d7b5,0xe6abab4d,0x9a7676ec,0x45caca8f,0x9d82821f,
+    0x40c9c989,0x877d7dfa,0x15fafaef,0xeb5959b2,0xc947478e,0xbf0f0fb,
+    0xecadad41,0x67d4d4b3,0xfda2a25f,0xeaafaf45,0xbf9c9c23,0xf7a4a453,
+    0x967272e4,0x5bc0c09b,0xc2b7b775,0x1cfdfde1,0xae93933d,0x6a26264c,
+    0x5a36366c,0x413f3f7e,0x2f7f7f5,0x4fcccc83,0x5c343468,0xf4a5a551,
+    0x34e5e5d1,0x8f1f1f9,0x937171e2,0x73d8d8ab,0x53313162,0x3f15152a,
+    0xc040408,0x52c7c795,0x65232346,0x5ec3c39d,0x28181830,0xa1969637,
+    0xf05050a,0xb59a9a2f,0x907070e,0x36121224,0x9b80801b,0x3de2e2df,
+    0x26ebebcd,0x6927274e,0xcdb2b27f,0x9f7575ea,0x1b090912,0x9e83831d,
+    0x742c2c58,0x2e1a1a34,0x2d1b1b36,0xb26e6edc,0xee5a5ab4,0xfba0a05b,
+    0xf65252a4,0x4d3b3b76,0x61d6d6b7,0xceb3b37d,0x7b292952,0x3ee3e3dd,
+    0x712f2f5e,0x97848413,0xf55353a6,0x68d1d1b9,0x0,0x2cededc1,
+    0x60202040,0x1ffcfce3,0xc8b1b179,0xed5b5bb6,0xbe6a6ad4,0x46cbcb8d,
+    0xd9bebe67,0x4b393972,0xde4a4a94,0xd44c4c98,0xe85858b0,0x4acfcf85,
+    0x6bd0d0bb,0x2aefefc5,0xe5aaaa4f,0x16fbfbed,0xc5434386,0xd74d4d9a,
+    0x55333366,0x94858511,0xcf45458a,0x10f9f9e9,0x6020204,0x817f7ffe,
+    0xf05050a0,0x443c3c78,0xba9f9f25,0xe3a8a84b,0xf35151a2,0xfea3a35d,
+    0xc0404080,0x8a8f8f05,0xad92923f,0xbc9d9d21,0x48383870,0x4f5f5f1,
+    0xdfbcbc63,0xc1b6b677,0x75dadaaf,0x63212142,0x30101020,0x1affffe5,
+    0xef3f3fd,0x6dd2d2bf,0x4ccdcd81,0x140c0c18,0x35131326,0x2fececc3,
+    0xe15f5fbe,0xa2979735,0xcc444488,0x3917172e,0x57c4c493,0xf2a7a755,
+    0x827e7efc,0x473d3d7a,0xac6464c8,0xe75d5dba,0x2b191932,0x957373e6,
+    0xa06060c0,0x98818119,0xd14f4f9e,0x7fdcdca3,0x66222244,0x7e2a2a54,
+    0xab90903b,0x8388880b,0xca46468c,0x29eeeec7,0xd3b8b86b,0x3c141428,
+    0x79dedea7,0xe25e5ebc,0x1d0b0b16,0x76dbdbad,0x3be0e0db,0x56323264,
+    0x4e3a3a74,0x1e0a0a14,0xdb494992,0xa06060c,0x6c242448,0xe45c5cb8,
+    0x5dc2c29f,0x6ed3d3bd,0xefacac43,0xa66262c4,0xa8919139,0xa4959531,
+    0x37e4e4d3,0x8b7979f2,0x32e7e7d5,0x43c8c88b,0x5937376e,0xb76d6dda,
+    0x8c8d8d01,0x64d5d5b1,0xd24e4e9c,0xe0a9a949,0xb46c6cd8,0xfa5656ac,
+    0x7f4f4f3,0x25eaeacf,0xaf6565ca,0x8e7a7af4,0xe9aeae47,0x18080810,
+    0xd5baba6f,0x887878f0,0x6f25254a,0x722e2e5c,0x241c1c38,0xf1a6a657,
+    0xc7b4b473,0x51c6c697,0x23e8e8cb,0x7cdddda1,0x9c7474e8,0x211f1f3e,
+    0xdd4b4b96,0xdcbdbd61,0x868b8b0d,0x858a8a0f,0x907070e0,0x423e3e7c,
+    0xc4b5b571,0xaa6666cc,0xd8484890,0x5030306,0x1f6f6f7,0x120e0e1c,
+    0xa36161c2,0x5f35356a,0xf95757ae,0xd0b9b969,0x91868617,0x58c1c199,
+    0x271d1d3a,0xb99e9e27,0x38e1e1d9,0x13f8f8eb,0xb398982b,0x33111122,
+    0xbb6969d2,0x70d9d9a9,0x898e8e07,0xa7949433,0xb69b9b2d,0x221e1e3c,
+    0x92878715,0x20e9e9c9,0x49cece87,0xff5555aa,0x78282850,0x7adfdfa5,
+    0x8f8c8c03,0xf8a1a159,0x80898909,0x170d0d1a,0xdabfbf65,0x31e6e6d7,
+    0xc6424284,0xb86868d0,0xc3414182,0xb0999929,0x772d2d5a,0x110f0f1e,
+    0xcbb0b07b,0xfc5454a8,0xd6bbbb6d,0x3a16162c
+};
+
+static const unsign32 rtable[]=
+{
+    0x50a7f451,0x5365417e,0xc3a4171a,0x965e273a,0xcb6bab3b,0xf1459d1f,
+    0xab58faac,0x9303e34b,0x55fa3020,0xf66d76ad,0x9176cc88,0x254c02f5,
+    0xfcd7e54f,0xd7cb2ac5,0x80443526,0x8fa362b5,0x495ab1de,0x671bba25,
+    0x980eea45,0xe1c0fe5d,0x2752fc3,0x12f04c81,0xa397468d,0xc6f9d36b,
+    0xe75f8f03,0x959c9215,0xeb7a6dbf,0xda595295,0x2d83bed4,0xd3217458,
+    0x2969e049,0x44c8c98e,0x6a89c275,0x78798ef4,0x6b3e5899,0xdd71b927,
+    0xb64fe1be,0x17ad88f0,0x66ac20c9,0xb43ace7d,0x184adf63,0x82311ae5,
+    0x60335197,0x457f5362,0xe07764b1,0x84ae6bbb,0x1ca081fe,0x942b08f9,
+    0x58684870,0x19fd458f,0x876cde94,0xb7f87b52,0x23d373ab,0xe2024b72,
+    0x578f1fe3,0x2aab5566,0x728ebb2,0x3c2b52f,0x9a7bc586,0xa50837d3,
+    0xf2872830,0xb2a5bf23,0xba6a0302,0x5c8216ed,0x2b1ccf8a,0x92b479a7,
+    0xf0f207f3,0xa1e2694e,0xcdf4da65,0xd5be0506,0x1f6234d1,0x8afea6c4,
+    0x9d532e34,0xa055f3a2,0x32e18a05,0x75ebf6a4,0x39ec830b,0xaaef6040,
+    0x69f715e,0x51106ebd,0xf98a213e,0x3d06dd96,0xae053edd,0x46bde64d,
+    0xb58d5491,0x55dc471,0x6fd40604,0xff155060,0x24fb9819,0x97e9bdd6,
+    0xcc434089,0x779ed967,0xbd42e8b0,0x888b8907,0x385b19e7,0xdbeec879,
+    0x470a7ca1,0xe90f427c,0xc91e84f8,0x0,0x83868009,0x48ed2b32,
+    0xac70111e,0x4e725a6c,0xfbff0efd,0x5638850f,0x1ed5ae3d,0x27392d36,
+    0x64d90f0a,0x21a65c68,0xd1545b9b,0x3a2e3624,0xb1670a0c,0xfe75793,
+    0xd296eeb4,0x9e919b1b,0x4fc5c080,0xa220dc61,0x694b775a,0x161a121c,
+    0xaba93e2,0xe52aa0c0,0x43e0223c,0x1d171b12,0xb0d090e,0xadc78bf2,
+    0xb9a8b62d,0xc8a91e14,0x8519f157,0x4c0775af,0xbbdd99ee,0xfd607fa3,
+    0x9f2601f7,0xbcf5725c,0xc53b6644,0x347efb5b,0x7629438b,0xdcc623cb,
+    0x68fcedb6,0x63f1e4b8,0xcadc31d7,0x10856342,0x40229713,0x2011c684,
+    0x7d244a85,0xf83dbbd2,0x1132f9ae,0x6da129c7,0x4b2f9e1d,0xf330b2dc,
+    0xec52860d,0xd0e3c177,0x6c16b32b,0x99b970a9,0xfa489411,0x2264e947,
+    0xc48cfca8,0x1a3ff0a0,0xd82c7d56,0xef903322,0xc74e4987,0xc1d138d9,
+    0xfea2ca8c,0x360bd498,0xcf81f5a6,0x28de7aa5,0x268eb7da,0xa4bfad3f,
+    0xe49d3a2c,0xd927850,0x9bcc5f6a,0x62467e54,0xc2138df6,0xe8b8d890,
+    0x5ef7392e,0xf5afc382,0xbe805d9f,0x7c93d069,0xa92dd56f,0xb31225cf,
+    0x3b99acc8,0xa77d1810,0x6e639ce8,0x7bbb3bdb,0x97826cd,0xf418596e,
+    0x1b79aec,0xa89a4f83,0x656e95e6,0x7ee6ffaa,0x8cfbc21,0xe6e815ef,
+    0xd99be7ba,0xce366f4a,0xd4099fea,0xd67cb029,0xafb2a431,0x31233f2a,
+    0x3094a5c6,0xc066a235,0x37bc4e74,0xa6ca82fc,0xb0d090e0,0x15d8a733,
+    0x4a9804f1,0xf7daec41,0xe50cd7f,0x2ff69117,0x8dd64d76,0x4db0ef43,
+    0x544daacc,0xdf0496e4,0xe3b5d19e,0x1b886a4c,0xb81f2cc1,0x7f516546,
+    0x4ea5e9d,0x5d358c01,0x737487fa,0x2e410bfb,0x5a1d67b3,0x52d2db92,
+    0x335610e9,0x1347d66d,0x8c61d79a,0x7a0ca137,0x8e14f859,0x893c13eb,
+    0xee27a9ce,0x35c961b7,0xede51ce1,0x3cb1477a,0x59dfd29c,0x3f73f255,
+    0x79ce1418,0xbf37c773,0xeacdf753,0x5baafd5f,0x146f3ddf,0x86db4478,
+    0x81f3afca,0x3ec468b9,0x2c342438,0x5f40a3c2,0x72c31d16,0xc25e2bc,
+    0x8b493c28,0x41950dff,0x7101a839,0xdeb30c08,0x9ce4b4d8,0x90c15664,
+    0x6184cb7b,0x70b632d5,0x745c6c48,0x4257b8d0
+};
+
+#define MR_TOBYTE(x) ((uchar)((x)))
+
+static unsign32 pack(const uchar *b)
+{
+    /* pack bytes into a 32-bit Word */
+    return ((unsign32)b[3]<<24)|((unsign32)b[2]<<16)|((unsign32)b[1]<<8)|(unsign32)b[0];
+}
+
+static void unpack(unsign32 a,uchar *b)
+{
+    /* unpack bytes from a word */
+    b[0]=MR_TOBYTE(a);
+    b[1]=MR_TOBYTE(a>>8);
+    b[2]=MR_TOBYTE(a>>16);
+    b[3]=MR_TOBYTE(a>>24);
+}
+
+/* SU= 8 */
+static uchar bmul(uchar x,uchar y)
+{
+    /* x.y= AntiLog(Log(x) + Log(y)) */
+    if (x && y) return ptab[(ltab[x]+ltab[y])%255];
+    else return 0;
+}
+
+static unsign32 SubByte(unsign32 a)
+{
+    uchar b[4];
+    unpack(a,b);
+    b[0]=fbsub[b[0]];
+    b[1]=fbsub[b[1]];
+    b[2]=fbsub[b[2]];
+    b[3]=fbsub[b[3]];
+    return pack(b);
+}
+
+/* SU= 16 */
+static uchar product(unsign32 x,unsign32 y)
+{
+    /* dot product of two 4-byte arrays */
+    uchar xb[4],yb[4];
+    unpack(x,xb);
+    unpack(y,yb);
+    return bmul(xb[0],yb[0])^bmul(xb[1],yb[1])^bmul(xb[2],yb[2])^bmul(xb[3],yb[3]);
+}
+
+static unsign32 InvMixCol(unsign32 x)
+{
+    /* matrix Multiplication */
+    unsign32 y,m;
+    uchar b[4];
+
+    m=pack(InCo);
+    b[3]=product(m,x);
+    m=ROTL24(m);
+    b[2]=product(m,x);
+    m=ROTL24(m);
+    b[1]=product(m,x);
+    m=ROTL24(m);
+    b[0]=product(m,x);
+    y=pack(b);
+    return y;
+}
+
+/* SU= 8 */
+/* reset cipher */
+void amcl::AES_reset(amcl::aes *a,int mode,char *iv)
+{
+    /* reset mode, or reset iv */
+    int i;
+    a->mode=mode;
+    for (i=0; i<4*NB; i++)
+        a->f[i]=0;
+    if (mode!=ECB && iv!=NULL)
+    {
+        for (i=0; i<4*NB; i++)
+            a->f[i]=iv[i];
+    }
+}
+
+void amcl::AES_getreg(amcl::aes *a,char *ir)
+{
+    int i;
+    for (i=0; i<4*NB; i++) ir[i]=a->f[i];
+}
+
+/* SU= 72 */
+/* Initialise cipher */
+int amcl::AES_init(amcl::aes* a,int mode,int nk,char *key,char *iv)
+{
+    /* Key length Nk=16, 24 or 32 bytes */
+    /* Key Scheduler. Create expanded encryption key */
+    int i,j,k,N,nr;
+    unsign32 CipherKey[8];
+
+    nk/=4;
+
+    if (nk!=4 && nk!=6 && nk!=8) return 0;
+
+    nr=6+nk;
+
+    a->Nk=nk;
+    a->Nr=nr;
+
+    AES_reset(a,mode,iv);
+
+    N=NB*(nr+1);
+
+    for (i=j=0; i<nk; i++,j+=4)
+    {
+        CipherKey[i]=pack((uchar *)&key[j]);
+    }
+    for (i=0; i<nk; i++) a->fkey[i]=CipherKey[i];
+    for (j=nk,k=0; j<N; j+=nk,k++)
+    {
+        a->fkey[j]=a->fkey[j-nk]^SubByte(ROTL24(a->fkey[j-1]))^rco[k];
+        if (nk<=6)
+        {
+            for (i=1; i<nk && (i+j)<N; i++)
+                a->fkey[i+j]=a->fkey[i+j-nk]^a->fkey[i+j-1];
+        }
+        else
+        {
+            for (i=1; i<4 && (i+j)<N; i++)
+                a->fkey[i+j]=a->fkey[i+j-nk]^a->fkey[i+j-1];
+            if ((j+4)<N) a->fkey[j+4]=a->fkey[j+4-nk]^SubByte(a->fkey[j+3]);
+            for (i=5; i<nk && (i+j)<N; i++)
+                a->fkey[i+j]=a->fkey[i+j-nk]^a->fkey[i+j-1];
+        }
+
+    }
+    /* now for the expanded decrypt key in reverse order */
+
+    for (j=0; j<NB; j++) a->rkey[j+N-NB]=a->fkey[j];
+    for (i=NB; i<N-NB; i+=NB)
+    {
+        k=N-NB-i;
+        for (j=0; j<NB; j++) a->rkey[k+j]=InvMixCol(a->fkey[i+j]);
+    }
+    for (j=N-NB; j<N; j++) a->rkey[j-N+NB]=a->fkey[j];
+    return 1;
+}
+
+/* SU= 80 */
+/* Encrypt a single block */
+void amcl::AES_ecb_encrypt(amcl::aes *a,uchar *buff)
+{
+    int i,j,k;
+    unsign32 p[4],q[4],*x,*y,*t;
+
+    for (i=j=0; i<NB; i++,j+=4)
+    {
+        p[i]=pack((uchar *)&buff[j]);
+        p[i]^=a->fkey[i];
+    }
+
+    k=NB;
+    x=p;
+    y=q;
+
+    /* State alternates between x and y */
+    for (i=1; i<a->Nr; i++)
+    {
+
+        y[0]=a->fkey[k]^ftable[MR_TOBYTE(x[0])]^
+             ROTL8(ftable[MR_TOBYTE(x[1]>>8)])^
+             ROTL16(ftable[MR_TOBYTE(x[2]>>16)])^
+             ROTL24(ftable[x[3]>>24]);
+        y[1]=a->fkey[k+1]^ftable[MR_TOBYTE(x[1])]^
+             ROTL8(ftable[MR_TOBYTE(x[2]>>8)])^
+             ROTL16(ftable[MR_TOBYTE(x[3]>>16)])^
+             ROTL24(ftable[x[0]>>24]);
+        y[2]=a->fkey[k+2]^ftable[MR_TOBYTE(x[2])]^
+             ROTL8(ftable[MR_TOBYTE(x[3]>>8)])^
+             ROTL16(ftable[MR_TOBYTE(x[0]>>16)])^
+             ROTL24(ftable[x[1]>>24]);
+        y[3]=a->fkey[k+3]^ftable[MR_TOBYTE(x[3])]^
+             ROTL8(ftable[MR_TOBYTE(x[0]>>8)])^
+             ROTL16(ftable[MR_TOBYTE(x[1]>>16)])^
+             ROTL24(ftable[x[2]>>24]);
+
+        k+=4;
+        t=x;
+        x=y;
+        y=t;      /* swap pointers */
+    }
+
+    /* Last Round */
+
+    y[0]=a->fkey[k]^(unsign32)fbsub[MR_TOBYTE(x[0])]^
+         ROTL8((unsign32)fbsub[MR_TOBYTE(x[1]>>8)])^
+         ROTL16((unsign32)fbsub[MR_TOBYTE(x[2]>>16)])^
+         ROTL24((unsign32)fbsub[x[3]>>24]);
+    y[1]=a->fkey[k+1]^(unsign32)fbsub[MR_TOBYTE(x[1])]^
+         ROTL8((unsign32)fbsub[MR_TOBYTE(x[2]>>8)])^
+         ROTL16((unsign32)fbsub[MR_TOBYTE(x[3]>>16)])^
+         ROTL24((unsign32)fbsub[x[0]>>24]);
+    y[2]=a->fkey[k+2]^(unsign32)fbsub[MR_TOBYTE(x[2])]^
+         ROTL8((unsign32)fbsub[MR_TOBYTE(x[3]>>8)])^
+         ROTL16((unsign32)fbsub[MR_TOBYTE(x[0]>>16)])^
+         ROTL24((unsign32)fbsub[x[1]>>24]);
+    y[3]=a->fkey[k+3]^(unsign32)fbsub[MR_TOBYTE(x[3])]^
+         ROTL8((unsign32)fbsub[MR_TOBYTE(x[0]>>8)])^
+         ROTL16((unsign32)fbsub[MR_TOBYTE(x[1]>>16)])^
+         ROTL24((unsign32)fbsub[x[2]>>24]);
+
+    for (i=j=0; i<NB; i++,j+=4)
+    {
+        unpack(y[i],(uchar *)&buff[j]);
+        x[i]=y[i]=0;   /* clean up stack */
+    }
+}
+
+/* SU= 80 */
+/* Decrypt a single block */
+void amcl::AES_ecb_decrypt(amcl::aes *a,uchar *buff)
+{
+    int i,j,k;
+    unsign32 p[4],q[4],*x,*y,*t;
+
+    for (i=j=0; i<NB; i++,j+=4)
+    {
+        p[i]=pack((uchar *)&buff[j]);
+        p[i]^=a->rkey[i];
+    }
+
+    k=NB;
+    x=p;
+    y=q;
+
+    /* State alternates between x and y */
+    for (i=1; i<a->Nr; i++)
+    {
+        /* Nr is number of rounds. May be odd. */
+
+        y[0]=a->rkey[k]^rtable[MR_TOBYTE(x[0])]^
+             ROTL8(rtable[MR_TOBYTE(x[3]>>8)])^
+             ROTL16(rtable[MR_TOBYTE(x[2]>>16)])^
+             ROTL24(rtable[x[1]>>24]);
+        y[1]=a->rkey[k+1]^rtable[MR_TOBYTE(x[1])]^
+             ROTL8(rtable[MR_TOBYTE(x[0]>>8)])^
+             ROTL16(rtable[MR_TOBYTE(x[3]>>16)])^
+             ROTL24(rtable[x[2]>>24]);
+        y[2]=a->rkey[k+2]^rtable[MR_TOBYTE(x[2])]^
+             ROTL8(rtable[MR_TOBYTE(x[1]>>8)])^
+             ROTL16(rtable[MR_TOBYTE(x[0]>>16)])^
+             ROTL24(rtable[x[3]>>24]);
+        y[3]=a->rkey[k+3]^rtable[MR_TOBYTE(x[3])]^
+             ROTL8(rtable[MR_TOBYTE(x[2]>>8)])^
+             ROTL16(rtable[MR_TOBYTE(x[1]>>16)])^
+             ROTL24(rtable[x[0]>>24]);
+
+        k+=4;
+        t=x;
+        x=y;
+        y=t;      /* swap pointers */
+    }
+
+
+    /* Last Round */
+    y[0]=a->rkey[k]^(unsign32)rbsub[MR_TOBYTE(x[0])]^
+         ROTL8((unsign32)rbsub[MR_TOBYTE(x[3]>>8)])^
+         ROTL16((unsign32)rbsub[MR_TOBYTE(x[2]>>16)])^
+         ROTL24((unsign32)rbsub[x[1]>>24]);
+    y[1]=a->rkey[k+1]^(unsign32)rbsub[MR_TOBYTE(x[1])]^
+         ROTL8((unsign32)rbsub[MR_TOBYTE(x[0]>>8)])^
+         ROTL16((unsign32)rbsub[MR_TOBYTE(x[3]>>16)])^
+         ROTL24((unsign32)rbsub[x[2]>>24]);
+    y[2]=a->rkey[k+2]^(unsign32)rbsub[MR_TOBYTE(x[2])]^
+         ROTL8((unsign32)rbsub[MR_TOBYTE(x[1]>>8)])^
+         ROTL16((unsign32)rbsub[MR_TOBYTE(x[0]>>16)])^
+         ROTL24((unsign32)rbsub[x[3]>>24]);
+    y[3]=a->rkey[k+3]^(unsign32)rbsub[MR_TOBYTE(x[3])]^
+         ROTL8((unsign32)rbsub[MR_TOBYTE(x[2]>>8)])^
+         ROTL16((unsign32)rbsub[MR_TOBYTE(x[1]>>16)])^
+         ROTL24((unsign32)rbsub[x[0]>>24]);
+
+    for (i=j=0; i<NB; i++,j+=4)
+    {
+        unpack(y[i],(uchar *)&buff[j]);
+        x[i]=y[i]=0;   /* clean up stack */
+    }
+
+}
+
+/* simple default increment function */
+static void increment(char *f)
+{
+    int i;
+    for (i=0; i<16; i++)
+    {
+        f[i]++;
+        if (f[i]!=0) break;
+    }
+}
+
+/* SU= 40 */
+/* Encrypt using selected mode of operation */
+unsign32 amcl::AES_encrypt(amcl::aes* a,char *buff)
+{
+    int j,bytes;
+    char st[16];
+    unsign32 fell_off;
+
+    /* Supported Modes of Operation */
+
+    fell_off=0;
+    switch (a->mode)
+    {
+    case ECB:
+        AES_ecb_encrypt(a,(uchar *)buff);
+        return 0;
+    case CBC:
+        for (j=0; j<4*NB; j++) buff[j]^=a->f[j];
+        AES_ecb_encrypt(a,(uchar *)buff);
+        for (j=0; j<4*NB; j++) a->f[j]=buff[j];
+        return 0;
+
+    case CFB1:
+    case CFB2:
+    case CFB4:
+        bytes=a->mode-CFB1+1;
+        for (j=0; j<bytes; j++) fell_off=(fell_off<<8)|a->f[j];
+        for (j=0; j<4*NB; j++) st[j]=a->f[j];
+        for (j=bytes; j<4*NB; j++) a->f[j-bytes]=a->f[j];
+        AES_ecb_encrypt(a,(uchar *)st);
+        for (j=0; j<bytes; j++)
+        {
+            buff[j]^=st[j];
+            a->f[16-bytes+j]=buff[j];
+        }
+        return fell_off;
+
+    case OFB1:
+    case OFB2:
+    case OFB4:
+    case OFB8:
+    case OFB16:
+
+        bytes=a->mode-OFB1+1;
+        AES_ecb_encrypt(a,(uchar *)(a->f));
+        for (j=0; j<bytes; j++) buff[j]^=a->f[j];
+        return 0;
+
+    case CTR1:
+    case CTR2:
+    case CTR4:
+    case CTR8:
+    case CTR16:
+
+        bytes=a->mode-CTR1+1;
+        for (j=0; j<4*NB; j++) st[j]=a->f[j];
+        AES_ecb_encrypt(a,(uchar *)st);
+        for (j=0; j<bytes; j++) buff[j]^=st[j];
+        increment(a->f);
+		return 0;
+
+    default:
+        return 0;
+    }
+}
+
+/* SU= 40 */
+/* Decrypt using selected mode of operation */
+unsign32 amcl::AES_decrypt(amcl::aes *a,char *buff)
+{
+    int j,bytes;
+    char st[16];
+    unsign32 fell_off;
+
+    /* Supported modes of operation */
+    fell_off=0;
+    switch (a->mode)
+    {
+    case ECB:
+        AES_ecb_decrypt(a,(uchar *)buff);
+        return 0;
+    case CBC:
+        for (j=0; j<4*NB; j++)
+        {
+            st[j]=a->f[j];
+            a->f[j]=buff[j];
+        }
+        AES_ecb_decrypt(a,(uchar *)buff);
+        for (j=0; j<4*NB; j++)
+        {
+            buff[j]^=st[j];
+            st[j]=0;
+        }
+        return 0;
+    case CFB1:
+    case CFB2:
+    case CFB4:
+        bytes=a->mode-CFB1+1;
+        for (j=0; j<bytes; j++) fell_off=(fell_off<<8)|a->f[j];
+        for (j=0; j<4*NB; j++) st[j]=a->f[j];
+        for (j=bytes; j<4*NB; j++) a->f[j-bytes]=a->f[j];
+        AES_ecb_encrypt(a,(uchar *)st);
+        for (j=0; j<bytes; j++)
+        {
+            a->f[16-bytes+j]=buff[j];
+            buff[j]^=st[j];
+        }
+        return fell_off;
+    case OFB1:
+    case OFB2:
+    case OFB4:
+    case OFB8:
+    case OFB16:
+        bytes=a->mode-OFB1+1;
+        AES_ecb_encrypt(a,(uchar *)(a->f));
+        for (j=0; j<bytes; j++) buff[j]^=a->f[j];
+        return 0;
+
+    case CTR1:
+    case CTR2:
+    case CTR4:
+    case CTR8:
+    case CTR16:
+
+        bytes=a->mode-CTR1+1;
+        for (j=0; j<4*NB; j++) st[j]=a->f[j];
+        AES_ecb_encrypt(a,(uchar *)st);
+        for (j=0; j<bytes; j++) buff[j]^=st[j];
+        increment(a->f);
+		return 0;
+
+    default:
+        return 0;
+    }
+}
+
+/* Clean up and delete left-overs */
+void amcl::AES_end(amcl::aes *a)
+{
+    /* clean up */
+    int i;
+    for (i=0; i<NB*(a->Nr+1); i++)
+        a->fkey[i]=a->rkey[i]=0;
+    for (i=0; i<4*NB; i++)
+        a->f[i]=0;
+}
+
+
+/*
+#include <stdio.h>
+
+#define KK 32
+
+int main()
+{
+    int i;
+    aes a;
+	unsign32 t;
+	uchar x,y;
+
+    char key[KK];
+    char block[16];
+    char iv[16];
+    for (i=0;i<KK;i++) key[i]=5;
+    key[0]=1;
+    for (i=0;i<16;i++) iv[i]=i;
+    for (i=0;i<16;i++) block[i]=i;
+
+    AES_init(&a,CTR16,KK,key,iv);
+
+    printf("Plain=   ");
+    for (i=0;i<16;i++) printf("%02x",block[i]);
+    printf("\n");
+    AES_encrypt(&a,block);
+    printf("Encrypt= ");
+    for (i=0;i<16;i++) printf("%02x",(uchar)block[i]);
+    printf("\n");
+    AES_reset(&a,CTR16,iv);
+    AES_decrypt(&a,block);
+    printf("Decrypt= ");
+    for (i=0;i<16;i++) printf("%02x",(uchar)block[i]);
+    printf("\n");
+
+    AES_end(&a);
+
+    return 0;
+}
+
+*/
+
diff --git a/version3/cpp/amcl.h b/version3/cpp/amcl.h
new file mode 100644
index 0000000..4b88f07
--- /dev/null
+++ b/version3/cpp/amcl.h
@@ -0,0 +1,585 @@
+/*
+	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.
+*/
+
+
+#ifndef AMCL_H
+#define AMCL_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <inttypes.h>
+#include "arch.h"
+
+namespace amcl {
+
+/* modulus types */
+
+#define NOT_SPECIAL 0	       /**< Modulus of no exploitable form */
+#define PSEUDO_MERSENNE 1      /**< Pseudo-mersenne modulus of form $2^n-c$  */
+#define MONTGOMERY_FRIENDLY 3  /**< Montgomery Friendly modulus of form $2^a(2^b-c)-1$  */
+#define GENERALISED_MERSENNE 2 /**< Generalised-mersenne modulus of form $2^n-2^m-1$, GOLDILOCKS only */
+
+
+/* Curve types */
+
+#define WEIERSTRASS 0 /**< Short Weierstrass form curve  */
+#define EDWARDS 1     /**< Edwards or Twisted Edwards curve  */
+#define MONTGOMERY 2  /**< Montgomery form curve  */
+
+/* Pairing-Friendly types */
+
+#define NOT 0
+#define BN 1
+#define BLS 2
+
+#define D_TYPE 0
+#define M_TYPE 1
+
+/**
+ * @brief SHA256 hash function instance */
+typedef struct
+{
+    unsign32 length[2]; /**< 64-bit input length */
+    unsign32 h[8];      /**< Internal state */
+    unsign32 w[80];	/**< Internal state */
+    int hlen;		/**< Hash length in bytes */
+} hash256;
+
+/**
+ * @brief SHA384-512 hash function instance */
+typedef struct
+{
+    unsign64 length[2]; /**< 64-bit input length */
+    unsign64 h[8];      /**< Internal state */
+    unsign64 w[80];	/**< Internal state */
+    int hlen;           /**< Hash length in bytes */
+} hash512;
+
+/**
+ * @brief SHA384 hash function instance */
+typedef hash512 hash384;
+
+/**
+ * @brief SHA3 hash function instance */
+typedef struct {
+	unsign64 length;
+	unsign64 S[5][5];
+	int rate,len;
+} sha3;
+
+#define SHA256 32 /**< SHA-256 hashing */
+#define SHA384 48 /**< SHA-384 hashing */
+#define SHA512 64 /**< SHA-512 hashing */
+
+#define SHA3_HASH224 28 /**< SHA3 224 bit hash */
+#define SHA3_HASH256 32 /**< SHA3 256 bit hash */
+#define SHA3_HASH384 48 /**< SHA3 384 bit hash */
+#define SHA3_HASH512 64 /**< SHA3 512 bit hash */
+
+#define SHAKE128 16 /**< SHAKE128   hash */
+#define SHAKE256 32 /**< SHAKE256 hash */
+
+
+/* NewHope parameters */
+
+//q= 12289
+
+#define RLWE_PRIME 0x3001	// q in Hex
+#define RLWE_LGN 10			// Degree n=2^LGN
+#define RLWE_ND 0xF7002FFF	// 1/(R-q) mod R
+#define RLWE_ONE 0x2AC8		// R mod q
+#define RLWE_R2MODP 0x1620	// R^2 mod q
+
+/* Symmetric Encryption AES structure */
+
+#define ECB   0  /**< Electronic Code Book */
+#define CBC   1  /**< Cipher Block Chaining */
+#define CFB1  2  /**< Cipher Feedback - 1 byte */
+#define CFB2  3  /**< Cipher Feedback - 2 bytes */
+#define CFB4  5  /**< Cipher Feedback - 4 bytes */
+#define OFB1  14 /**< Output Feedback - 1 byte */
+#define OFB2  15 /**< Output Feedback - 2 bytes */
+#define OFB4  17 /**< Output Feedback - 4 bytes */
+#define OFB8  21 /**< Output Feedback - 8 bytes */
+#define OFB16 29 /**< Output Feedback - 16 bytes */
+#define CTR1  30 /**< Counter Mode - 1 byte */
+#define CTR2  31 /**< Counter Mode - 2 bytes */
+#define CTR4  33 /**< Counter Mode - 4 bytes */
+#define CTR8  37 /**< Counter Mode - 8 bytes */
+#define CTR16 45 /**< Counter Mode - 16 bytes */
+
+#define uchar unsigned char  /**<  Unsigned char */
+
+/**
+	@brief AES instance
+*/
+
+
+typedef struct
+{
+    int Nk;            /**< AES Key Length */
+    int Nr;            /**< AES Number of rounds */
+    int mode;          /**< AES mode of operation */
+    unsign32 fkey[60]; /**< subkeys for encrypton */
+    unsign32 rkey[60]; /**< subkeys for decrypton */
+    char f[16];        /**< buffer for chaining vector */
+} aes;
+
+/* AES-GCM suppport.  */
+
+#define GCM_ACCEPTING_HEADER 0   /**< GCM status */
+#define GCM_ACCEPTING_CIPHER 1   /**< GCM status */
+#define GCM_NOT_ACCEPTING_MORE 2 /**< GCM status */
+#define GCM_FINISHED 3           /**< GCM status */
+#define GCM_ENCRYPTING 0         /**< GCM mode */
+#define GCM_DECRYPTING 1         /**< GCM mode */
+
+
+/**
+	@brief GCM mode instance, using AES internally
+*/
+
+typedef struct
+{
+    unsign32 table[128][4]; /**< 2k byte table */
+    uchar stateX[16];	    /**< GCM Internal State */
+    uchar Y_0[16];	    /**< GCM Internal State */
+    unsign32 lenA[2];	    /**< GCM 64-bit length of header */
+    unsign32 lenC[2];	    /**< GCM 64-bit length of ciphertext */
+    int status;		    /**< GCM Status */
+    aes a;		    /**< Internal Instance of aes cipher */
+} gcm;
+
+/* Marsaglia & Zaman Random number generator constants */
+
+#define NK   21 /**< PRNG constant */
+#define NJ   6  /**< PRNG constant */
+#define NV   8  /**< PRNG constant */
+
+
+/**
+	@brief Cryptographically secure pseudo-random number generator instance
+*/
+
+typedef struct
+{
+    unsign32 ira[NK]; /**< random number array   */
+    int      rndptr;  /**< pointer into array */
+    unsign32 borrow;  /**<  borrow as a result of subtraction */
+    int pool_ptr;     /**< pointer into random pool */
+    char pool[32];    /**< random pool */
+} csprng;
+
+
+/**
+	@brief Portable representation of a big positive number
+*/
+
+typedef struct
+{
+    int len;   /**< length in bytes  */
+    int max;   /**< max length allowed - enforce truncation  */
+    char *val; /**< byte array  */
+} octet;
+
+
+/* Octet string handlers */
+/**	@brief Formats and outputs an octet to the console in hex
+ *
+	@param O Octet to be output
+ */
+extern void OCT_output(octet *O);
+/**	@brief Formats and outputs an octet to the console as a character string
+ *
+	@param O Octet to be output
+ */
+extern void OCT_output_string(octet *O);
+/**	@brief Wipe clean an octet
+ *
+	@param O Octet to be cleaned
+ */
+extern void OCT_clear(octet *O);
+/**	@brief Compare two octets
+ *
+	@param O first Octet to be compared
+	@param P second Octet to be compared
+	@return 1 if equal, else 0
+ */
+extern int  OCT_comp(octet *O,octet *P);
+
+
+/**	@brief Compare first n bytes of two octets
+ *
+	@param O first Octet to be compared
+	@param P second Octet to be compared
+	@param n number of bytes to compare
+	@return 1 if equal, else 0
+ */
+extern int  OCT_ncomp(octet *O,octet *P,int n);
+/**	@brief Join from a C string to end of an octet
+ *
+	Truncates if there is no room
+	@param O Octet to be written to
+	@param s zero terminated string to be joined to octet
+ */
+extern void OCT_jstring(octet *O,char *s);
+/**	@brief Join bytes to end of an octet
+ *
+	Truncates if there is no room
+	@param O Octet to be written to
+	@param s bytes to be joined to end of octet
+	@param n number of bytes to join
+ */
+extern void OCT_jbytes(octet *O,char *s,int n);
+/**	@brief Join single byte to end of an octet, repeated n times
+ *
+	Truncates if there is no room
+	@param O Octet to be written to
+	@param b byte to be joined to end of octet
+	@param n number of times b is to be joined
+ */
+extern void OCT_jbyte(octet *O,int b,int n);
+/**	@brief Join one octet to the end of another
+ *
+	Truncates if there is no room
+	@param O Octet to be written to
+	@param P Octet to be joined to the end of O
+ */
+extern void OCT_joctet(octet *O,octet *P);
+/**	@brief XOR common bytes of a pair of Octets
+ *
+	@param O Octet - on exit = O xor P
+	@param P Octet to be xored into O
+ */
+extern void OCT_xor(octet *O,octet *P);
+/**	@brief reset Octet to zero length
+ *
+	@param O Octet to be emptied
+ */
+extern void OCT_empty(octet *O);
+/**	@brief Pad out an Octet to the given length
+ *
+	Padding is done by inserting leading zeros, so abcd becomes 00abcd
+	@param O Octet to be padded
+	@param n new length of Octet
+ */
+extern int OCT_pad(octet *O,int n);
+/**	@brief Convert an Octet to printable base64 number
+ *
+	@param b zero terminated byte array to take base64 conversion
+	@param O Octet to be converted
+ */
+extern void OCT_tobase64(char *b,octet *O);
+/**	@brief Populate an Octet from base64 number
+ *
+ 	@param O Octet to be populated
+	@param b zero terminated base64 string
+
+ */
+extern void OCT_frombase64(octet *O,char *b);
+/**	@brief Copy one Octet into another
+ *
+ 	@param O Octet to be copied to
+	@param P Octet to be copied from
+
+ */
+extern void OCT_copy(octet *O,octet *P);
+/**	@brief XOR every byte of an octet with input m
+ *
+ 	@param O Octet
+	@param m byte to be XORed with every byte of O
+
+ */
+extern void OCT_xorbyte(octet *O,int m);
+/**	@brief Chops Octet into two, leaving first n bytes in O, moving the rest to P
+ *
+ 	@param O Octet to be chopped
+	@param P new Octet to be created
+	@param n number of bytes to chop off O
+
+ */
+extern void OCT_chop(octet *O,octet *P,int n);
+/**	@brief Join n bytes of integer m to end of Octet O (big endian)
+ *
+	Typically n is 4 for a 32-bit integer
+ 	@param O Octet to be appended to
+	@param m integer to be appended to O
+	@param n number of bytes in m
+
+ */
+extern void OCT_jint(octet *O,int m,int n);
+/**	@brief Create an Octet from bytes taken from a random number generator
+ *
+	Truncates if there is no room
+ 	@param O Octet to be populated
+	@param R an instance of a Cryptographically Secure Random Number Generator
+	@param n number of bytes to extracted from R
+
+ */
+extern void OCT_rand(octet *O,csprng *R,int n);
+/**	@brief Shifts Octet left by n bytes
+ *
+	Leftmost bytes disappear
+ 	@param O Octet to be shifted
+	@param n number of bytes to shift
+
+ */
+extern void OCT_shl(octet *O,int n);
+/**	@brief Convert a hex number to an Octet
+ *
+	@param dst Octet
+	@param src Hex string to be converted
+ */
+extern void OCT_fromHex(octet *dst,char *src);
+/**	@brief Convert an Octet to printable hex number
+ *
+	@param dst hex value
+	@param src Octet to be converted
+ */
+extern void OCT_toHex(octet *src,char *dst);
+/**	@brief Convert an Octet to string
+ *
+	@param dst string value
+	@param src Octet to be converted
+ */
+extern void OCT_toStr(octet *src,char *dst);
+
+
+
+/* Hash function */
+/**	@brief Initialise an instance of SHA256
+ *
+	@param H an instance SHA256
+ */
+extern void HASH256_init(hash256 *H);
+/**	@brief Add a byte to the hash
+ *
+	@param H an instance SHA256
+	@param b byte to be included in hash
+ */
+extern void HASH256_process(hash256 *H,int b);
+/**	@brief Generate 32-byte hash
+ *
+	@param H an instance SHA256
+	@param h is the output 32-byte hash
+ */
+extern void HASH256_hash(hash256 *H,char *h);
+
+
+/**	@brief Initialise an instance of SHA384
+ *
+	@param H an instance SHA384
+ */
+extern void HASH384_init(hash384 *H);
+/**	@brief Add a byte to the hash
+ *
+	@param H an instance SHA384
+	@param b byte to be included in hash
+ */
+extern void HASH384_process(hash384 *H,int b);
+/**	@brief Generate 48-byte hash
+ *
+	@param H an instance SHA384
+	@param h is the output 48-byte hash
+ */
+extern void HASH384_hash(hash384 *H,char *h);
+
+
+/**	@brief Initialise an instance of SHA512
+ *
+	@param H an instance SHA512
+ */
+extern void HASH512_init(hash512 *H);
+/**	@brief Add a byte to the hash
+ *
+	@param H an instance SHA512
+	@param b byte to be included in hash
+ */
+extern void HASH512_process(hash512 *H,int b);
+/**	@brief Generate 64-byte hash
+ *
+	@param H an instance SHA512
+	@param h is the output 64-byte hash
+ */
+extern void HASH512_hash(hash512 *H,char *h);
+
+
+/**	@brief Initialise an instance of SHA3
+ *
+	@param H an instance SHA3
+	@param t the instance type
+ */
+extern void  SHA3_init(sha3 *H,int t);
+/**	@brief process a byte for SHA3
+ *
+	@param H an instance SHA3
+	@param b a byte of date to be processed
+ */
+extern void  SHA3_process(sha3 *H,int b);
+/**	@brief create fixed length hash output of SHA3
+ *
+	@param H an instance SHA3
+	@param h a byte array to take hash
+ */
+extern void  SHA3_hash(sha3 *H,char *h);
+/**	@brief create variable length hash output of SHA3
+ *
+	@param H an instance SHA3
+	@param h a byte array to take hash
+	@param len is the length of the hash
+ */
+extern void  SHA3_shake(sha3 *H,char *h,int len);
+/**	@brief generate further hash output of SHA3
+ *
+	@param H an instance SHA3
+	@param h a byte array to take hash
+	@param len is the length of the hash
+ */
+extern void  SHA3_squeeze(sha3 *H,char *h,int len);
+
+
+
+/* AES functions */
+/**	@brief Reset AES mode or IV
+ *
+	@param A an instance of the aes
+	@param m is the new active mode of operation (ECB, CBC, OFB, CFB etc)
+	@param iv the new Initialisation Vector
+ */
+extern void AES_reset(aes *A,int m,char *iv);
+/**	@brief Extract chaining vector from aes instance
+ *
+	@param A an instance of the aes
+	@param f the extracted chaining vector
+ */
+extern void AES_getreg(aes *A,char * f);
+/**	@brief Initialise an instance of aes and its mode of operation
+ *
+	@param A an instance aes
+	@param m is the active mode of operation (ECB, CBC, OFB, CFB etc)
+	@param n is the key length in bytes, 16, 24 or 32
+	@param k the AES key as an array of 16 bytes
+	@param iv the Initialisation Vector
+	@return 0 for invalid n
+ */
+extern int AES_init(aes *A,int m,int n,char *k,char *iv);
+/**	@brief Encrypt a single 16 byte block in ECB mode
+ *
+	@param A an instance of the aes
+	@param b is an array of 16 plaintext bytes, on exit becomes ciphertext
+ */
+extern void AES_ecb_encrypt(aes *A,uchar * b);
+/**	@brief Decrypt a single 16 byte block in ECB mode
+ *
+	@param A an instance of the aes
+	@param b is an array of 16 cipherext bytes, on exit becomes plaintext
+ */
+extern void AES_ecb_decrypt(aes *A,uchar * b);
+/**	@brief Encrypt a single 16 byte block in active mode
+ *
+	@param A an instance of the aes
+	@param b is an array of 16 plaintext bytes, on exit becomes ciphertext
+	@return 0, or overflow bytes from CFB mode
+ */
+extern unsign32 AES_encrypt(aes *A,char *b );
+/**	@brief Decrypt a single 16 byte block in active mode
+ *
+	@param A an instance of the aes
+	@param b is an array of 16 ciphertext bytes, on exit becomes plaintext
+	@return 0, or overflow bytes from CFB mode
+ */
+extern unsign32 AES_decrypt(aes *A,char *b);
+/**	@brief Clean up after application of AES
+ *
+	@param A an instance of the aes
+ */
+extern void AES_end(aes *A);
+
+
+/* AES-GCM functions */
+/**	@brief Initialise an instance of AES-GCM mode
+ *
+	@param G an instance AES-GCM
+	@param nk is the key length in bytes, 16, 24 or 32
+	@param k the AES key as an array of 16 bytes
+	@param n the number of bytes in the Initialisation Vector (IV)
+	@param iv the IV
+ */
+extern void GCM_init(gcm *G,int nk,char *k,int n,char *iv);
+/**	@brief Add header (material to be authenticated but not encrypted)
+ *
+	Note that this function can be called any number of times with n a multiple of 16, and then one last time with any value for n
+	@param G an instance AES-GCM
+	@param b is the header material to be added
+	@param n the number of bytes in the header
+ */
+extern int GCM_add_header(gcm *G,char *b,int n);
+/**	@brief Add plaintext and extract ciphertext
+ *
+	Note that this function can be called any number of times with n a multiple of 16, and then one last time with any value for n
+	@param G an instance AES-GCM
+	@param c is the ciphertext generated
+	@param p is the plaintext material to be added
+	@param n the number of bytes in the plaintext
+ */
+extern int GCM_add_plain(gcm *G,char *c,char *p,int n);
+/**	@brief Add ciphertext and extract plaintext
+ *
+	Note that this function can be called any number of times with n a multiple of 16, and then one last time with any value for n
+	@param G an instance AES-GCM
+	@param p is the plaintext generated
+	@param c is the ciphertext material to be added
+	@param n the number of bytes in the ciphertext
+ */
+extern int GCM_add_cipher(gcm *G,char *p,char *c,int n);
+/**	@brief Finish off and extract authentication tag (HMAC)
+ *
+	@param G is an active instance AES-GCM
+	@param t is the output 16 byte authentication tag
+ */
+extern void GCM_finish(gcm *G,char *t);
+
+
+
+/* random numbers */
+/**	@brief Seed a random number generator from an array of bytes
+ *
+	The provided seed should be truly random
+	@param R an instance of a Cryptographically Secure Random Number Generator
+	@param n the number of seed bytes provided
+	@param b an array of seed bytes
+
+ */
+extern void RAND_seed(csprng *R,int n,char *b);
+/**	@brief Delete all internal state of a random number generator
+ *
+	@param R an instance of a Cryptographically Secure Random Number Generator
+ */
+extern void RAND_clean(csprng *R);
+/**	@brief Return a random byte from a random number generator
+ *
+	@param R an instance of a Cryptographically Secure Random Number Generator
+	@return a random byte
+ */
+extern int RAND_byte(csprng *R);
+
+}
+
+#endif
diff --git a/version3/cpp/arch.h b/version3/cpp/arch.h
new file mode 100644
index 0000000..d21d0cd
--- /dev/null
+++ b/version3/cpp/arch.h
@@ -0,0 +1,98 @@
+/*
+	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.
+*/
+
+/* Architecture definition header file */
+
+/**
+ * @file arch.h
+ * @author Mike Scott
+ * @date 23rd February 2016
+ * @brief Architecture Header File
+ *
+ * Specify Processor Architecture
+ *
+ */
+
+/* NOTE: There is only one user configurable section in this header - see below */
+
+#ifndef ARCH_H
+#define ARCH_H
+#include <stdint.h>
+
+namespace amcl {
+
+/*** START OF USER CONFIGURABLE SECTION - set architecture ***/
+
+#define CHUNK @WL@		/**< size of chunk in bits = wordlength of computer = 16, 32 or 64. Note not all curve options are supported on 16-bit processors - see rom.c */
+
+/*** END OF USER CONFIGURABLE SECTION ***/
+
+/* Create Integer types */
+/* Support for C99?  Note for GCC need to explicitly include -std=c99 in command line */
+
+
+#define byte uint8_t			/**< 8-bit unsigned integer */
+#define sign8 int8_t			/**< 8-bit signed integer */
+#define sign16 int16_t			/**< 16-bit signed integer */
+#define sign32 int32_t			/**< 32-bit signed integer */
+#define sign64 int64_t			/**< 64-bit signed integer */
+#define unsign32 uint32_t		/**< 32-bit unsigned integer */
+#define unsign64 uint64_t		/**< 64-bit unsigned integer */
+
+#define uchar unsigned char  /**<  Unsigned char */
+
+/* Don't mess with anything below this line unless you know what you are doing */
+/* This next is probably OK, but may need changing for non-C99-standard environments */
+
+/* This next is probably OK, but may need changing for non-C99-standard environments */
+
+#if CHUNK==16
+
+#define chunk int16_t		/**< C type corresponding to word length */
+#define dchunk int32_t		/**< Always define double length chunk type if available */
+
+#endif
+
+#if CHUNK == 32
+
+#define chunk int32_t		/**< C type corresponding to word length */
+#define dchunk int64_t		/**< Always define double length chunk type if available */
+
+#endif
+
+#if CHUNK == 64
+
+    #define chunk int64_t		/**< C type corresponding to word length */
+    #ifdef __GNUC__
+       #define dchunk __int128		/**< Always define double length chunk type if available - GCC supports 128 bit type  ??? */
+    #endif
+
+    #ifdef __clang__
+       #define dchunk __int128
+    #endif
+
+#endif
+
+#ifdef dchunk
+#define COMBA      /**< Use COMBA method for faster muls, sqrs and reductions */
+#endif
+
+}
+
+#endif
diff --git a/version3/cpp/benchtest_all.cpp b/version3/cpp/benchtest_all.cpp
new file mode 100644
index 0000000..28d1d33
--- /dev/null
+++ b/version3/cpp/benchtest_all.cpp
@@ -0,0 +1,973 @@
+/* Test and benchmark elliptic curve and RSA functions
+	First build amcl.a from build_ec batch file
+	gcc -O3 benchtest_ec.c amcl.a -o benchtest_ec.exe
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "rsa_RSA2048.h"
+#include "ecp_ED25519.h"
+#include "pair_BN254.h"
+
+#if CHUNK==32 || CHUNK==64
+#include "ecp_NIST256.h"
+#include "ecp_GOLDILOCKS.h"
+#include "pair_BLS383.h"
+#include "pair192_BLS24.h"
+#include "pair256_BLS48.h"
+#endif
+
+#define MIN_TIME 10.0
+#define MIN_ITERS 10 
+
+using namespace amcl;
+
+int ED_25519(csprng *RNG)
+{
+	using namespace ED25519;
+	using namespace ED25519_BIG;
+
+    int i,iterations;
+    clock_t start;
+    double elapsed;
+	ECP EP,EG;
+	BIG s,r,x,y;
+	printf("\nTesting/Timing ED25519 ECC\n");
+
+#if CURVETYPE_ED25519==WEIERSTRASS
+	printf("Weierstrass parameterization\n");
+#endif
+#if CURVETYPE_ED25519==EDWARDS
+	printf("Edwards parameterization\n");
+#endif
+#if CURVETYPE_ED25519==MONTGOMERY
+	printf("Montgomery parameterization\n");
+#endif
+
+#if CHUNK==16
+	printf("16-bit Build\n");
+#endif
+#if CHUNK==32
+	printf("32-bit Build\n");
+#endif
+#if CHUNK==64
+	printf("64-bit Build\n");
+#endif
+
+	ECP_generator(&EG);
+
+	BIG_rcopy(r,CURVE_Order);
+	BIG_randomnum(s,r,RNG);
+	ECP_copy(&EP,&EG);
+    ECP_mul(&EP,r);
+
+	if (!ECP_isinf(&EP))
+	{
+		printf("FAILURE - rG!=O\n");
+		return 0;
+	}
+
+	iterations=0;
+    start=clock();
+    do {
+		ECP_copy(&EP,&EG);
+		ECP_mul(&EP,s);
+
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("EC  mul - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	return 0;
+}
+
+#if CHUNK==32 || CHUNK==64
+int NIST_256(csprng *RNG)
+{
+	using namespace NIST256;
+	using namespace NIST256_BIG;
+
+    int i,iterations;
+    clock_t start;
+    double elapsed;
+	ECP EP,EG;
+	BIG s,r,x,y;
+	printf("\nTesting/Timing NIST256 ECC\n");
+
+#if CURVETYPE_NIST256==WEIERSTRASS
+	printf("Weierstrass parameterization\n");
+#endif
+#if CURVETYPE_NIST256==EDWARDS
+	printf("Edwards parameterization\n");
+#endif
+#if CURVETYPE_NIST256==MONTGOMERY
+	printf("Montgomery parameterization\n");
+#endif
+
+#if CHUNK==16
+	printf("16-bit Build\n");
+#endif
+#if CHUNK==32
+	printf("32-bit Build\n");
+#endif
+#if CHUNK==64
+	printf("64-bit Build\n");
+#endif
+
+	ECP_generator(&EG);
+
+	BIG_rcopy(r,CURVE_Order);
+	BIG_randomnum(s,r,RNG);
+	ECP_copy(&EP,&EG);
+    ECP_mul(&EP,r);
+
+	if (!ECP_isinf(&EP))
+	{
+		printf("FAILURE - rG!=O\n");
+		return 0;
+	}
+
+	iterations=0;
+    start=clock();
+    do {
+		ECP_copy(&EP,&EG);
+		ECP_mul(&EP,s);
+
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("EC  mul - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	return 0;
+}
+
+int GOLDI_LOCKS(csprng *RNG)
+{
+	using namespace GOLDILOCKS;
+	using namespace GOLDILOCKS_BIG;
+
+    int i,iterations;
+    clock_t start;
+    double elapsed;
+	ECP EP,EG;
+	BIG s,r,x,y;
+	printf("\nTesting/Timing GOLDILOCKS ECC\n");
+
+#if CURVETYPE_GOLDILOCKS==WEIERSTRASS
+	printf("Weierstrass parameterization\n");
+#endif
+#if CURVETYPE_GOLDILOCKS==EDWARDS
+	printf("Edwards parameterization\n");
+#endif
+#if CURVETYPE_GOLDILOCKS==MONTGOMERY
+	printf("Montgomery parameterization\n");
+#endif
+
+#if CHUNK==16
+	printf("16-bit Build\n");
+#endif
+#if CHUNK==32
+	printf("32-bit Build\n");
+#endif
+#if CHUNK==64
+	printf("64-bit Build\n");
+#endif
+
+	ECP_generator(&EG);
+
+	BIG_rcopy(r,CURVE_Order);
+	BIG_randomnum(s,r,RNG);
+	ECP_copy(&EP,&EG);
+    ECP_mul(&EP,r);
+
+	if (!ECP_isinf(&EP))
+	{
+		printf("FAILURE - rG!=O\n");
+		return 0;
+	}
+
+	iterations=0;
+    start=clock();
+    do {
+		ECP_copy(&EP,&EG);
+		ECP_mul(&EP,s);
+
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("EC  mul - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	return 0;
+}
+#endif
+
+int BN_254(csprng *RNG)
+{
+	using namespace BN254;
+	using namespace BN254_FP;
+	using namespace BN254_BIG;
+
+    int i,iterations;
+    clock_t start;
+    double elapsed;
+
+	ECP P,G;
+	ECP2 Q,W;
+	FP12 g,w;
+	FP4 cm;
+	FP2 wx,wy;
+
+	BIG s,r,x,y;
+	printf("\nTesting/Timing BN254 Pairings\n");
+
+	ECP_generator(&G);
+	
+	BIG_rcopy(r,CURVE_Order);
+	BIG_randomnum(s,r,RNG);
+	ECP_copy(&P,&G);
+    PAIR_G1mul(&P,r);
+
+	if (!ECP_isinf(&P))
+	{
+		printf("FAILURE - rG!=O\n");
+		return 0;
+	}
+	
+	iterations=0;
+    start=clock();
+    do {
+		ECP_copy(&P,&G);
+		PAIR_G1mul(&P,s);
+
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("G1 mul              - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+    ECP2_generator(&W);
+
+	ECP2_copy(&Q,&W);
+    ECP2_mul(&Q,r);
+
+	if (!ECP2_isinf(&Q))
+	{
+		printf("FAILURE - rQ!=O\n");
+		return 0;
+	}
+
+	iterations=0;
+    start=clock();
+    do {
+		ECP2_copy(&Q,&W);
+		PAIR_G2mul(&Q,s);
+
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("G2 mul              - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	PAIR_ate(&w,&Q,&P);
+	PAIR_fexp(&w);
+
+	FP12_copy(&g,&w);
+
+	PAIR_GTpow(&g,r);
+
+	if (!FP12_isunity(&g))
+	{
+		printf("FAILURE - g^r!=1\n");
+		return 0;
+	}
+
+	iterations=0;
+    start=clock();
+    do {
+		FP12_copy(&g,&w);
+		PAIR_GTpow(&g,s);
+
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("GT pow              - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	FP12_copy(&g,&w);
+
+	iterations=0;
+    start=clock();
+    do {
+		FP12_compow(&cm,&g,s,r);
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("GT pow (compressed) - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	iterations=0;
+    start=clock();
+    do {
+		PAIR_ate(&w,&Q,&P);
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("PAIRing ATE         - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	iterations=0;
+    start=clock();
+    do {
+		FP12_copy(&g,&w);
+		PAIR_fexp(&g);
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("PAIRing FEXP        - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	ECP_copy(&P,&G);	
+	ECP2_copy(&Q,&W);
+
+	PAIR_G1mul(&P,s);
+	PAIR_ate(&g,&Q,&P);
+	PAIR_fexp(&g);
+
+	ECP_copy(&P,&G);
+
+	PAIR_G2mul(&Q,s);
+	PAIR_ate(&w,&Q,&P);
+	PAIR_fexp(&w);
+
+	if (!FP12_equals(&g,&w))
+	{
+		printf("FAILURE - e(sQ,p)!=e(Q,sP) \n");
+		return 0;
+	}
+
+	ECP2_copy(&Q,&W);
+	PAIR_ate(&g,&Q,&P);
+	PAIR_fexp(&g);
+
+	PAIR_GTpow(&g,s);
+
+	if (!FP12_equals(&g,&w))
+	{
+		printf("FAILURE - e(sQ,p)!=e(Q,P)^s \n");
+		return 0;
+	}
+	return 0;
+}
+
+#if CHUNK==32 || CHUNK==64
+int BLS_383(csprng *RNG)
+{
+	using namespace BLS383;
+	using namespace BLS383_FP;
+	using namespace BLS383_BIG;
+
+    int i,iterations;
+    clock_t start;
+    double elapsed;
+
+	ECP P,G;
+	ECP2 Q,W;
+	FP12 g,w;
+	FP4 cm;
+	FP2 wx,wy;
+
+	BIG s,r,x,y;
+	printf("\nTesting/Timing BLS383 Pairings\n");
+
+	ECP_generator(&G);
+	
+	BIG_rcopy(r,CURVE_Order);
+	BIG_randomnum(s,r,RNG);
+	ECP_copy(&P,&G);
+    PAIR_G1mul(&P,r);
+
+	if (!ECP_isinf(&P))
+	{
+		printf("FAILURE - rG!=O\n");
+		return 0;
+	}
+	
+	iterations=0;
+    start=clock();
+    do {
+		ECP_copy(&P,&G);
+		PAIR_G1mul(&P,s);
+
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("G1 mul              - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+    ECP2_generator(&W);
+
+	ECP2_copy(&Q,&W);
+    ECP2_mul(&Q,r);
+
+	if (!ECP2_isinf(&Q))
+	{
+		printf("FAILURE - rQ!=O\n");
+		return 0;
+	}
+
+	iterations=0;
+    start=clock();
+    do {
+		ECP2_copy(&Q,&W);
+		PAIR_G2mul(&Q,s);
+
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("G2 mul              - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	PAIR_ate(&w,&Q,&P);
+	PAIR_fexp(&w);
+
+	FP12_copy(&g,&w);
+
+	PAIR_GTpow(&g,r);
+
+	if (!FP12_isunity(&g))
+	{
+		printf("FAILURE - g^r!=1\n");
+		return 0;
+	}
+
+	iterations=0;
+    start=clock();
+    do {
+		FP12_copy(&g,&w);
+		PAIR_GTpow(&g,s);
+
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("GT pow              - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	FP12_copy(&g,&w);
+
+	iterations=0;
+    start=clock();
+    do {
+		FP12_compow(&cm,&g,s,r);
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("GT pow (compressed) - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	iterations=0;
+    start=clock();
+    do {
+		PAIR_ate(&w,&Q,&P);
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("PAIRing ATE         - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	iterations=0;
+    start=clock();
+    do {
+		FP12_copy(&g,&w);
+		PAIR_fexp(&g);
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("PAIRing FEXP        - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	ECP_copy(&P,&G);	
+	ECP2_copy(&Q,&W);
+
+	PAIR_G1mul(&P,s);
+	PAIR_ate(&g,&Q,&P);
+	PAIR_fexp(&g);
+
+	ECP_copy(&P,&G);
+
+	PAIR_G2mul(&Q,s);
+	PAIR_ate(&w,&Q,&P);
+	PAIR_fexp(&w);
+
+	if (!FP12_equals(&g,&w))
+	{
+		printf("FAILURE - e(sQ,p)!=e(Q,sP) \n");
+		return 0;
+	}
+
+	ECP2_copy(&Q,&W);
+	PAIR_ate(&g,&Q,&P);
+	PAIR_fexp(&g);
+
+	PAIR_GTpow(&g,s);
+
+	if (!FP12_equals(&g,&w))
+	{
+		printf("FAILURE - e(sQ,p)!=e(Q,P)^s \n");
+		return 0;
+	}
+	return 0;
+}
+
+int BLS_24(csprng *RNG)
+{
+	using namespace BLS24;
+	using namespace BLS24_FP;
+	using namespace BLS24_BIG;
+
+    int i,iterations;
+    clock_t start;
+    double elapsed;
+
+	ECP P,G;
+	ECP4 Q,W;
+	FP24 g,w;
+
+	FP8 cm;
+	BIG a,b,s,r;
+
+	printf("\nTesting/Timing BLS24 Pairings\n");
+
+	ECP_generator(&G);
+	
+	BIG_rcopy(r,CURVE_Order);
+	BIG_randomnum(s,r,RNG);
+	ECP_copy(&P,&G);
+    PAIR_G1mul(&P,r);
+
+	if (!ECP_isinf(&P))
+	{
+		printf("FAILURE - rG!=O\n");
+		return 0;
+	}
+	
+	iterations=0;
+    start=clock();
+    do {
+		ECP_copy(&P,&G);
+		PAIR_G1mul(&P,s);
+
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("G1 mul              - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	ECP4_generator(&W);
+
+	ECP4_copy(&Q,&W);
+    ECP4_mul(&Q,r);
+
+	if (!ECP4_isinf(&Q))
+	{
+		printf("FAILURE - rQ!=O\n");
+		return 0;
+	}
+
+	iterations=0;
+    start=clock();
+    do {
+		ECP4_copy(&Q,&W);
+		PAIR_G2mul(&Q,s);
+
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("G2 mul              - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	PAIR_ate(&w,&Q,&P);
+	PAIR_fexp(&w);
+
+	FP24_copy(&g,&w);
+
+	PAIR_GTpow(&g,r);
+
+	if (!FP24_isunity(&g))
+	{
+		printf("FAILURE - g^r!=1\n");
+		return 0;
+	}
+
+	iterations=0;
+    start=clock();
+    do {
+		FP24_copy(&g,&w);
+		PAIR_GTpow(&g,s);
+
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("GT pow              - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	FP24_copy(&g,&w);
+
+	iterations=0;
+    start=clock();
+    do {
+		FP24_compow(&cm,&g,s,r);
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("GT pow (compressed) - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	iterations=0;
+    start=clock();
+    do {
+		PAIR_ate(&w,&Q,&P);
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("PAIRing ATE         - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	iterations=0;
+    start=clock();
+    do {
+		FP24_copy(&g,&w);
+		PAIR_fexp(&g);
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("PAIRing FEXP        - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	ECP_copy(&P,&G);	
+	ECP4_copy(&Q,&W);
+
+	PAIR_G1mul(&P,s);
+	PAIR_ate(&g,&Q,&P);
+	PAIR_fexp(&g);
+
+	ECP_copy(&P,&G);
+
+	PAIR_G2mul(&Q,s);
+	PAIR_ate(&w,&Q,&P);
+	PAIR_fexp(&w);
+
+	if (!FP24_equals(&g,&w))
+	{
+		printf("FAILURE - e(sQ,p)!=e(Q,sP) \n");
+		return 0;
+	}
+
+	ECP4_copy(&Q,&W);
+	PAIR_ate(&g,&Q,&P);
+	PAIR_fexp(&g);
+
+	PAIR_GTpow(&g,s);
+
+	if (!FP24_equals(&g,&w))
+	{
+		printf("FAILURE - e(sQ,p)!=e(Q,P)^s \n");
+		return 0;
+	}
+	return 0;
+}
+
+
+
+int BLS_48(csprng *RNG)
+{
+	using namespace BLS48;
+	using namespace BLS48_FP;
+	using namespace BLS48_BIG;
+
+    int i,iterations;
+    clock_t start;
+    double elapsed;
+
+	ECP P,G;
+	ECP8 Q,W;
+	FP48 g,w;
+
+	FP16 cm;
+	BIG a,b,s,r;
+
+	printf("\nTesting/Timing BLS48 Pairings\n");
+
+	ECP_generator(&G);
+	
+	BIG_rcopy(r,CURVE_Order);
+	BIG_randomnum(s,r,RNG);
+	ECP_copy(&P,&G);
+    PAIR_G1mul(&P,r);
+
+	if (!ECP_isinf(&P))
+	{
+		printf("FAILURE - rG!=O\n");
+		return 0;
+	}
+	
+	iterations=0;
+    start=clock();
+    do {
+		ECP_copy(&P,&G);
+		PAIR_G1mul(&P,s);
+
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("G1 mul              - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+
+	ECP8_generator(&W);
+
+	ECP8_copy(&Q,&W);
+    ECP8_mul(&Q,r);
+
+	if (!ECP8_isinf(&Q))
+	{
+		printf("FAILURE - rQ!=O\n");
+		return 0;
+	}
+
+	iterations=0;
+    start=clock();
+    do {
+		ECP8_copy(&Q,&W);
+		PAIR_G2mul(&Q,s);
+
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("G2 mul              - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+
+	PAIR_ate(&w,&Q,&P);
+	PAIR_fexp(&w);
+
+	FP48_copy(&g,&w);
+
+	PAIR_GTpow(&g,r);
+
+	if (!FP48_isunity(&g))
+	{
+		printf("FAILURE - g^r!=1\n");
+		return 0;
+	}
+
+	iterations=0;
+    start=clock();
+    do {
+		FP48_copy(&g,&w);
+		PAIR_GTpow(&g,s);
+
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("GT pow              - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	FP48_copy(&g,&w);
+
+	iterations=0;
+    start=clock();
+    do {
+		FP48_compow(&cm,&g,s,r);
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("GT pow (compressed) - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	iterations=0;
+    start=clock();
+    do {
+		PAIR_ate(&w,&Q,&P);
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("PAIRing ATE         - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	iterations=0;
+    start=clock();
+    do {
+		FP48_copy(&g,&w);
+		PAIR_fexp(&g);
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("PAIRing FEXP        - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	ECP_copy(&P,&G);	
+	ECP8_copy(&Q,&W);
+
+	PAIR_G1mul(&P,s);
+	PAIR_ate(&g,&Q,&P);
+	PAIR_fexp(&g);
+
+	ECP_copy(&P,&G);
+
+	PAIR_G2mul(&Q,s);
+	PAIR_ate(&w,&Q,&P);
+	PAIR_fexp(&w);
+
+	if (!FP48_equals(&g,&w))
+	{
+		printf("FAILURE - e(sQ,p)!=e(Q,sP) \n");
+		return 0;
+	}
+
+	ECP8_copy(&Q,&W);
+	PAIR_ate(&g,&Q,&P);
+	PAIR_fexp(&g);
+
+	PAIR_GTpow(&g,s);
+
+	if (!FP48_equals(&g,&w))
+	{
+		printf("FAILURE - e(sQ,p)!=e(Q,P)^s \n");
+		return 0;
+	}
+	return 0;
+}
+#endif
+
+
+int RSA_2048(csprng *RNG)
+{
+	using namespace RSA2048;
+
+    rsa_public_key pub;
+    rsa_private_key priv;
+
+    int i,iterations;
+    clock_t start;
+    double elapsed;
+
+    char m[RFS_RSA2048],d[RFS_RSA2048],c[RFS_RSA2048];
+    octet M= {0,sizeof(m),m};
+    octet D= {0,sizeof(d),d};
+    octet C= {0,sizeof(c),c};
+
+	printf("\nTesting/Timing 2048-bit RSA\n");
+
+	printf("Generating 2048-bit RSA public/private key pair\n");
+
+	iterations=0;
+    start=clock();
+    do {
+		RSA_KEY_PAIR(RNG,65537,&priv,&pub,NULL,NULL);
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("RSA gen - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	M.len=RFS_RSA2048;
+	for (i=0;i<RFS_RSA2048;i++) M.val[i]=i%128;
+
+	iterations=0;
+    start=clock();
+    do {
+		RSA_ENCRYPT(&pub,&M,&C);
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("RSA enc - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	iterations=0;
+    start=clock();
+    do {
+		RSA_DECRYPT(&priv,&C,&D);
+		iterations++;
+		elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+    } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("RSA dec - %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+	for (i=0;i<RFS_RSA2048;i++)
+	{
+		if (M.val[i]!=D.val[i])
+		{
+			printf("FAILURE - RSA decryption\n");
+			return 0;
+		}
+	}
+
+	printf("All tests pass\n");
+
+	return 0;
+}
+
+int main()
+{
+    csprng RNG;
+	int i;
+	char pr[10];
+	unsigned long ran;
+
+	time((time_t *)&ran);
+	pr[0]=ran;
+	pr[1]=ran>>8;
+	pr[2]=ran>>16;
+	pr[3]=ran>>24;
+	for (i=0;i<10;i++) pr[i]=i;    /*****4****/
+    RAND_seed(&RNG,10,pr);
+
+	ED_25519(&RNG);
+#if CHUNK==32 || CHUNK==64	
+	NIST_256(&RNG);
+	GOLDI_LOCKS(&RNG);
+#endif	
+	BN_254(&RNG);
+#if CHUNK==32 || CHUNK==64	
+	BLS_383(&RNG);
+	BLS_24(&RNG);
+	BLS_48(&RNG);
+#endif
+	RSA_2048(&RNG);
+	
+}
diff --git a/version3/cpp/big.cpp b/version3/cpp/big.cpp
new file mode 100644
index 0000000..0da0de8
--- /dev/null
+++ b/version3/cpp/big.cpp
@@ -0,0 +1,1508 @@
+/*
+	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.
+*/
+
+/* AMCL basic functions for BIG type */
+/* SU=m, SU is Stack Usage */
+
+#include "big_XXX.h"
+
+/* test a=0? */
+int XXX::BIG_iszilch(BIG a)
+{
+    int i;
+    for (i=0; i<NLEN_XXX; i++)
+        if (a[i]!=0) return 0;
+    return 1;
+}
+
+/* test a=1? */
+int XXX::BIG_isunity(BIG a)
+{
+    int i;
+    for (i=1; i<NLEN_XXX; i++)
+        if (a[i]!=0) return 0;
+	if (a[0]!=1) return 0;
+    return 1;
+}
+
+/* test a=0? */
+int XXX::BIG_diszilch(DBIG a)
+{
+    int i;
+    for (i=0; i<DNLEN_XXX; i++)
+        if (a[i]!=0) return 0;
+    return 1;
+}
+
+/* SU= 56 */
+/* output a */
+void XXX::BIG_output(BIG a)
+{
+    BIG b;
+    int i,len;
+    len=BIG_nbits(a);
+    if (len%4==0) len/=4;
+    else
+    {
+        len/=4;
+        len++;
+    }
+    if (len<MODBYTES_XXX*2) len=MODBYTES_XXX*2;
+
+    for (i=len-1; i>=0; i--)
+    {
+        BIG_copy(b,a);
+        BIG_shr(b,i*4);
+        printf("%01x",(unsigned int) b[0]&15);
+    }
+}
+
+/* SU= 16 */
+void XXX::BIG_rawoutput(BIG a)
+{
+    int i;
+    printf("(");
+    for (i=0; i<NLEN_XXX-1; i++)
+#if CHUNK==64
+        printf("%jx,",(uintmax_t) a[i]);
+    printf("%jx)",(uintmax_t) a[NLEN_XXX-1]);
+#else
+        printf("%x,",(unsigned int) a[i]);
+    printf("%x)",(unsigned int) a[NLEN_XXX-1]);
+#endif
+}
+
+/* Swap a and b if d=1 */
+void XXX::BIG_cswap(BIG a,BIG b,int d)
+{
+    int i;
+    chunk t,c=d;
+    c=~(c-1);
+#ifdef DEBUG_NORM
+    for (i=0; i<NLEN_XXX+2; i++)
+#else
+    for (i=0; i<NLEN_XXX; i++)
+#endif
+    {
+        t=c&(a[i]^b[i]);
+        a[i]^=t;
+        b[i]^=t;
+    }
+}
+
+/* Move b to a if d=1 */
+void XXX::BIG_cmove(BIG f,BIG g,int d)
+{
+    int i;
+    chunk b=(chunk)-d;
+#ifdef DEBUG_NORM
+    for (i=0; i<NLEN_XXX+2; i++)
+#else
+    for (i=0; i<NLEN_XXX; i++)
+#endif
+    {
+        f[i]^=(f[i]^g[i])&b;
+    }
+}
+
+/* Move g to f if d=1 */
+void XXX::BIG_dcmove(DBIG f,DBIG g,int d)
+{
+    int i;
+    chunk b=(chunk)-d;
+#ifdef DEBUG_NORM
+    for (i=0; i<DNLEN_XXX+2; i++)
+#else
+    for (i=0; i<DNLEN_XXX; i++)
+#endif
+    {
+        f[i]^=(f[i]^g[i])&b;
+    }
+}
+
+/* convert BIG to/from bytes */
+/* SU= 64 */
+void XXX::BIG_toBytes(char *b,BIG a)
+{
+    int i;
+    BIG c;
+    //BIG_norm(a);
+    BIG_copy(c,a);
+	BIG_norm(c);
+    for (i=MODBYTES_XXX-1; i>=0; i--)
+    {
+        b[i]=c[0]&0xff;
+        BIG_fshr(c,8);
+    }
+}
+
+/* SU= 16 */
+void XXX::BIG_fromBytes(BIG a,char *b)
+{
+    int i;
+    BIG_zero(a);
+    for (i=0; i<MODBYTES_XXX; i++)
+    {
+        BIG_fshl(a,8);
+        a[0]+=(int)(unsigned char)b[i];
+        //BIG_inc(a,(int)(unsigned char)b[i]); BIG_norm(a);
+    }
+#ifdef DEBUG_NORM
+	a[MPV_XXX]=1; a[MNV_XXX]=0;
+#endif
+}
+
+void XXX::BIG_fromBytesLen(BIG a,char *b,int s)
+{
+    int i,len=s;
+    BIG_zero(a);
+
+    if (len>MODBYTES_XXX) len=MODBYTES_XXX;
+    for (i=0; i<len; i++)
+    {
+        BIG_fshl(a,8);
+        a[0]+=(int)(unsigned char)b[i];
+    }
+#ifdef DEBUG_NORM
+	a[MPV_XXX]=1; a[MNV_XXX]=0;
+#endif
+}
+
+
+
+/* SU= 88 */
+void XXX::BIG_doutput(DBIG a)
+{
+    DBIG b;
+    int i,len;
+    BIG_dnorm(a);
+    len=BIG_dnbits(a);
+    if (len%4==0) len/=4;
+    else
+    {
+        len/=4;
+        len++;
+    }
+
+    for (i=len-1; i>=0; i--)
+    {
+        BIG_dcopy(b,a);
+        BIG_dshr(b,i*4);
+        printf("%01x",(unsigned int) b[0]&15);
+    }
+}
+
+
+void XXX::BIG_drawoutput(DBIG a)
+{
+    int i;
+    printf("(");
+    for (i=0; i<DNLEN_XXX-1; i++)
+#if CHUNK==64
+        printf("%jx,",(uintmax_t) a[i]);
+    printf("%jx)",(uintmax_t) a[DNLEN_XXX-1]);
+#else
+        printf("%x,",(unsigned int) a[i]);
+    printf("%x)",(unsigned int) a[DNLEN_XXX-1]);
+#endif
+}
+
+/* Copy b=a */
+void XXX::BIG_copy(BIG b,BIG a)
+{
+    int i;
+    for (i=0; i<NLEN_XXX; i++)
+        b[i]=a[i];
+#ifdef DEBUG_NORM
+	b[MPV_XXX]=a[MPV_XXX];
+	b[MNV_XXX]=a[MNV_XXX];
+#endif
+}
+
+/* Copy from ROM b=a */
+void XXX::BIG_rcopy(BIG b,const BIG a)
+{
+    int i;
+    for (i=0; i<NLEN_XXX; i++)
+        b[i]=a[i];
+#ifdef DEBUG_NORM
+	b[MPV_XXX]=1; b[MNV_XXX]=0;
+#endif
+}
+
+/* double length DBIG copy b=a */
+void XXX::BIG_dcopy(DBIG b,DBIG a)
+{
+    int i;
+    for (i=0; i<DNLEN_XXX; i++)
+        b[i]=a[i];
+#ifdef DEBUG_NORM
+	b[DMPV_XXX]=a[DMPV_XXX];
+	b[DMNV_XXX]=a[DMNV_XXX];
+#endif
+}
+
+/* Copy BIG to bottom half of DBIG */
+void XXX::BIG_dscopy(DBIG b,BIG a)
+{
+    int i;
+    for (i=0; i<NLEN_XXX-1; i++)
+        b[i]=a[i];
+
+    b[NLEN_XXX-1]=a[NLEN_XXX-1]&BMASK_XXX; /* top word normalized */
+    b[NLEN_XXX]=a[NLEN_XXX-1]>>BASEBITS_XXX;
+
+    for (i=NLEN_XXX+1; i<DNLEN_XXX; i++) b[i]=0;
+#ifdef DEBUG_NORM
+	b[DMPV_XXX]=a[MPV_XXX];
+	b[DMNV_XXX]=a[MNV_XXX];
+#endif
+}
+
+/* Copy BIG to top half of DBIG */
+void XXX::BIG_dsucopy(DBIG b,BIG a)
+{
+    int i;
+    for (i=0; i<NLEN_XXX; i++)
+        b[i]=0;
+    for (i=NLEN_XXX; i<DNLEN_XXX; i++)
+        b[i]=a[i-NLEN_XXX];
+#ifdef DEBUG_NORM
+	b[DMPV_XXX]=a[MPV_XXX];
+	b[DMNV_XXX]=a[MNV_XXX];
+#endif
+}
+
+/* Copy bottom half of DBIG to BIG */
+void XXX::BIG_sdcopy(BIG b,DBIG a)
+{
+    int i;
+    for (i=0; i<NLEN_XXX; i++)
+        b[i]=a[i];
+#ifdef DEBUG_NORM
+	b[MPV_XXX]=a[DMPV_XXX];
+	b[MNV_XXX]=a[DMNV_XXX];
+#endif
+}
+
+/* Copy top half of DBIG to BIG */
+void XXX::BIG_sducopy(BIG b,DBIG a)
+{
+    int i;
+    for (i=0; i<NLEN_XXX; i++)
+        b[i]=a[i+NLEN_XXX];
+#ifdef DEBUG_NORM
+	b[MPV_XXX]=a[DMPV_XXX];
+	b[MNV_XXX]=a[DMNV_XXX];
+
+#endif
+}
+
+/* Set a=0 */
+void XXX::BIG_zero(BIG a)
+{
+    int i;
+    for (i=0; i<NLEN_XXX; i++)
+        a[i]=0;
+#ifdef DEBUG_NORM
+	a[MPV_XXX]=a[MNV_XXX]=0;
+#endif
+}
+
+void XXX::BIG_dzero(DBIG a)
+{
+    int i;
+    for (i=0; i<DNLEN_XXX; i++)
+        a[i]=0;
+#ifdef DEBUG_NORM
+	a[DMPV_XXX]=a[DMNV_XXX]=0;
+#endif
+}
+
+/* set a=1 */
+void XXX::BIG_one(BIG a)
+{
+    int i;
+    a[0]=1;
+    for (i=1; i<NLEN_XXX; i++)
+        a[i]=0;
+#ifdef DEBUG_NORM
+	a[MPV_XXX]=1;
+	a[MNV_XXX]=0;
+#endif
+}
+
+
+
+/* Set c=a+b */
+/* SU= 8 */
+void XXX::BIG_add(BIG c,BIG a,BIG b)
+{
+    int i;
+    for (i=0; i<NLEN_XXX; i++)
+        c[i]=a[i]+b[i];
+#ifdef DEBUG_NORM
+	c[MPV_XXX]=a[MPV_XXX]+b[MPV_XXX];
+	c[MNV_XXX]=a[MNV_XXX]+b[MNV_XXX];
+	if (c[MPV_XXX]>NEXCESS_XXX)  printf("add problem - positive digit overflow %d\n",c[MPV_XXX]);
+	if (c[MNV_XXX]>NEXCESS_XXX)  printf("add problem - negative digit overflow %d\n",c[MNV_XXX]);
+
+#endif
+}
+
+/* Set c=a or b */
+/* SU= 8 */
+void XXX::BIG_or(BIG c,BIG a,BIG b)
+{
+    int i;
+	BIG_norm(a);
+	BIG_norm(b);
+    for (i=0; i<NLEN_XXX; i++)
+        c[i]=a[i]|b[i];
+#ifdef DEBUG_NORM
+	c[MPV_XXX]=1;
+	c[MNV_XXX]=0;
+#endif
+
+}
+
+
+/* Set c=c+d */
+void XXX::BIG_inc(BIG c,int d)
+{
+    BIG_norm(c);
+    c[0]+=(chunk)d;
+#ifdef DEBUG_NORM
+	c[MPV_XXX]+=1;
+#endif
+}
+
+/* Set c=a-b */
+/* SU= 8 */
+void XXX::BIG_sub(BIG c,BIG a,BIG b)
+{
+    int i;
+    for (i=0; i<NLEN_XXX; i++)
+        c[i]=a[i]-b[i];
+#ifdef DEBUG_NORM
+	c[MPV_XXX]=a[MPV_XXX]+b[MNV_XXX];
+	c[MNV_XXX]=a[MNV_XXX]+b[MPV_XXX];
+	if (c[MPV_XXX]>NEXCESS_XXX)  printf("sub problem - positive digit overflow %d\n",c[MPV_XXX]);
+	if (c[MNV_XXX]>NEXCESS_XXX)  printf("sub problem - negative digit overflow %d\n",c[MNV_XXX]);
+
+#endif
+}
+
+/* SU= 8 */
+
+void XXX::BIG_dsub(DBIG c,DBIG a,DBIG b)
+{
+    int i;
+    for (i=0; i<DNLEN_XXX; i++)
+        c[i]=a[i]-b[i];
+#ifdef DEBUG_NORM
+	c[DMPV_XXX]=a[DMPV_XXX]+b[DMNV_XXX];
+	c[DMNV_XXX]=a[DMNV_XXX]+b[DMPV_XXX];
+	if (c[DMPV_XXX]>NEXCESS_XXX)  printf("double sub problem - positive digit overflow %d\n",c[DMPV_XXX]);
+	if (c[DMNV_XXX]>NEXCESS_XXX)  printf("double sub problem - negative digit overflow %d\n",c[DMNV_XXX]);
+#endif
+}
+
+void XXX::BIG_dadd(DBIG c,DBIG a,DBIG b)
+{
+    int i;
+    for (i=0; i<DNLEN_XXX; i++)
+        c[i]=a[i]+b[i];
+#ifdef DEBUG_NORM
+	c[DMPV_XXX]=a[DMPV_XXX]+b[DMNV_XXX];
+	c[DMNV_XXX]=a[DMNV_XXX]+b[DMPV_XXX];
+	if (c[DMPV_XXX]>NEXCESS_XXX)  printf("double add problem - positive digit overflow %d\n",c[DMPV_XXX]);
+	if (c[DMNV_XXX]>NEXCESS_XXX)  printf("double add problem - negative digit overflow %d\n",c[DMNV_XXX]);
+#endif
+}
+
+/* Set c=c-1 */
+void XXX::BIG_dec(BIG c,int d)
+{
+    BIG_norm(c);
+    c[0]-=(chunk)d;
+#ifdef DEBUG_NORM
+	c[MNV_XXX]+=1;
+#endif
+}
+
+/* multiplication r=a*c by c<=NEXCESS_XXX */
+void XXX::BIG_imul(BIG r,BIG a,int c)
+{
+    int i;
+    for (i=0; i<NLEN_XXX; i++) r[i]=a[i]*c;
+#ifdef DEBUG_NORM
+	r[MPV_XXX]=a[MPV_XXX]*c;
+	r[MNV_XXX]=a[MNV_XXX]*c;
+	if (r[MPV_XXX]>NEXCESS_XXX)  printf("int mul problem - positive digit overflow %d\n",r[MPV_XXX]);
+	if (r[MNV_XXX]>NEXCESS_XXX)  printf("int mul problem - negative digit overflow %d\n",r[MNV_XXX]);
+
+#endif
+}
+
+/* multiplication r=a*c by larger integer - c<=FEXCESS */
+/* SU= 24 */
+chunk XXX::BIG_pmul(BIG r,BIG a,int c)
+{
+    int i;
+    chunk ak,carry=0;
+//    BIG_norm(a);
+    for (i=0; i<NLEN_XXX; i++)
+    {
+        ak=a[i];
+        r[i]=0;
+        carry=muladd(ak,(chunk)c,carry,&r[i]);
+    }
+#ifdef DEBUG_NORM
+	r[MPV_XXX]=1;
+	r[MNV_XXX]=0;
+#endif
+    return carry;
+}
+
+/* r/=3 */
+/* SU= 16 */
+int XXX::BIG_div3(BIG r)
+{
+    int i;
+    chunk ak,base,carry=0;
+    BIG_norm(r);
+    base=((chunk)1<<BASEBITS_XXX);
+    for (i=NLEN_XXX-1; i>=0; i--)
+    {
+        ak=(carry*base+r[i]);
+        r[i]=ak/3;
+        carry=ak%3;
+    }
+    return (int)carry;
+}
+
+/* multiplication c=a*b by even larger integer b>FEXCESS, resulting in DBIG */
+/* SU= 24 */
+void XXX::BIG_pxmul(DBIG c,BIG a,int b)
+{
+    int j;
+    chunk carry;
+    BIG_dzero(c);
+    carry=0;
+    for (j=0; j<NLEN_XXX; j++)
+        carry=muladd(a[j],(chunk)b,carry,&c[j]);
+    c[NLEN_XXX]=carry;
+#ifdef DEBUG_NORM
+	c[DMPV_XXX]=1;
+	c[DMNV_XXX]=0;
+#endif
+}
+
+/* .. if you know the result will fit in a BIG, c must be distinct from a and b */
+/* SU= 40 */
+void XXX::BIG_smul(BIG c,BIG a,BIG b)
+{
+    int i,j;
+    chunk carry;
+//    BIG_norm(a);
+//    BIG_norm(b);
+
+    BIG_zero(c);
+    for (i=0; i<NLEN_XXX; i++)
+    {
+        carry=0;
+        for (j=0; j<NLEN_XXX; j++)
+        {
+            if (i+j<NLEN_XXX)
+                carry=muladd(a[i],b[j],carry,&c[i+j]);
+        }
+    }
+#ifdef DEBUG_NORM
+	c[MPV_XXX]=1;
+	c[MNV_XXX]=0;
+#endif
+
+}
+
+/* Set c=a*b */
+/* SU= 72 */
+void XXX::BIG_mul(DBIG c,BIG a,BIG b)
+{
+    int i;
+#ifdef dchunk
+    dchunk t,co;
+    dchunk s;
+    dchunk d[NLEN_XXX];
+    int k;
+#endif
+
+#ifdef DEBUG_NORM
+	if ((a[MPV_XXX]!=1 && a[MPV_XXX]!=0) || a[MNV_XXX]!=0) printf("First input to mul not normed\n");
+	if ((b[MPV_XXX]!=1 && b[MPV_XXX]!=0) || b[MNV_XXX]!=0) printf("Second input to mul not normed\n");
+#endif
+
+    /* Faster to Combafy it.. Let the compiler unroll the loops! */
+
+#ifdef COMBA
+
+    /* faster psuedo-Karatsuba method */
+#ifdef UNWOUND
+
+    /* Insert output of faster.c here */
+
+#else
+    for (i=0; i<NLEN_XXX; i++)
+        d[i]=(dchunk)a[i]*b[i];
+
+    s=d[0];
+    t=s;
+    c[0]=(chunk)t&BMASK_XXX;
+    co=t>>BASEBITS_XXX;
+
+    for (k=1; k<NLEN_XXX; k++)
+    {
+        s+=d[k];
+        t=co+s;
+        for (i=k; i>=1+k/2; i--) t+=(dchunk)(a[i]-a[k-i])*(b[k-i]-b[i]);
+        c[k]=(chunk)t&BMASK_XXX;
+        co=t>>BASEBITS_XXX;
+    }
+    for (k=NLEN_XXX; k<2*NLEN_XXX-1; k++)
+    {
+        s-=d[k-NLEN_XXX];
+        t=co+s;
+        for (i=NLEN_XXX-1; i>=1+k/2; i--) t+=(dchunk)(a[i]-a[k-i])*(b[k-i]-b[i]);
+        c[k]=(chunk)t&BMASK_XXX;
+        co=t>>BASEBITS_XXX;
+    }
+    c[2*NLEN_XXX-1]=(chunk)co;
+
+#endif
+
+#else
+    int j;
+    chunk carry;
+    BIG_dzero(c);
+    for (i=0; i<NLEN_XXX; i++)
+    {
+        carry=0;
+        for (j=0; j<NLEN_XXX; j++)
+            carry=muladd(a[i],b[j],carry,&c[i+j]);
+
+        c[NLEN_XXX+i]=carry;
+    }
+
+#endif
+
+#ifdef DEBUG_NORM
+	c[DMPV_XXX]=1;
+	c[DMNV_XXX]=0;
+#endif
+}
+
+/* Set c=a*a */
+/* SU= 80 */
+void XXX::BIG_sqr(DBIG c,BIG a)
+{
+    int i,j,last;
+#ifdef dchunk
+    dchunk t,co;
+#endif
+
+#ifdef DEBUG_NORM
+	if ((a[MPV_XXX]!=1 && a[MPV_XXX]!=0) || a[MNV_XXX]!=0) printf("Input to sqr not normed\n");
+#endif
+    /* Note 2*a[i] in loop below and extra addition */
+
+#ifdef COMBA
+
+#ifdef UNWOUND
+
+    /* Insert output of faster.c here */
+
+#else
+
+
+    t=(dchunk)a[0]*a[0]; 
+    c[0]=(chunk)t&BMASK_XXX;
+    co=t>>BASEBITS_XXX;
+
+	for (j=1;j<NLEN_XXX-1; )
+	{
+        t=(dchunk)a[j]*a[0]; 
+        for (i=1; i<(j+1)/2; i++) {t+=(dchunk)a[j-i]*a[i]; }
+        t+=t; t+=co; 
+        c[j]=(chunk)t&BMASK_XXX;
+        co=t>>BASEBITS_XXX;
+		j++;
+        t=(dchunk)a[j]*a[0]; 
+        for (i=1; i<(j+1)/2; i++) {t+=(dchunk)a[j-i]*a[i]; }
+        t+=t; t+=co; 
+        t+=(dchunk)a[j/2]*a[j/2]; 
+        c[j]=(chunk)t&BMASK_XXX;
+        co=t>>BASEBITS_XXX;
+		j++;
+	}
+
+	for (j=NLEN_XXX-1+NLEN_XXX%2;j<DNLEN_XXX-3; )
+	{
+        t=(dchunk)a[NLEN_XXX-1]*a[j-NLEN_XXX+1]; 
+        for (i=j-NLEN_XXX+2; i<(j+1)/2; i++) {t+=(dchunk)a[j-i]*a[i];  }
+        t+=t; t+=co; 
+        c[j]=(chunk)t&BMASK_XXX;
+        co=t>>BASEBITS_XXX;
+		j++;
+        t=(dchunk)a[NLEN_XXX-1]*a[j-NLEN_XXX+1]; 
+        for (i=j-NLEN_XXX+2; i<(j+1)/2; i++) {t+=(dchunk)a[j-i]*a[i];  }
+        t+=t; t+=co; 
+        t+=(dchunk)a[j/2]*a[j/2]; 
+        c[j]=(chunk)t&BMASK_XXX;
+        co=t>>BASEBITS_XXX;
+		j++;
+	}
+
+	t=(dchunk)a[NLEN_XXX-2]*a[NLEN_XXX-1];
+	t+=t; t+=co;
+	c[DNLEN_XXX-3]=(chunk)t&BMASK_XXX;
+    co=t>>BASEBITS_XXX;
+	
+    t=(dchunk)a[NLEN_XXX-1]*a[NLEN_XXX-1]+co; 
+    c[DNLEN_XXX-2]=(chunk)t&BMASK_XXX;
+    co=t>>BASEBITS_XXX;
+    c[DNLEN_XXX-1]=(chunk)co;
+
+
+#endif
+
+#else
+    chunk carry;
+    BIG_dzero(c);
+    for (i=0; i<NLEN_XXX; i++)
+    {
+        carry=0;
+        for (j=i+1; j<NLEN_XXX; j++)
+            carry=muladd(a[i],a[j],carry,&c[i+j]);
+        c[NLEN_XXX+i]=carry;
+    }
+
+    for (i=0; i<DNLEN_XXX; i++) c[i]*=2;
+
+    for (i=0; i<NLEN_XXX; i++)
+        c[2*i+1]+=muladd(a[i],a[i],0,&c[2*i]);
+
+    BIG_dnorm(c);
+#endif
+
+
+#ifdef DEBUG_NORM
+	c[DMPV_XXX]=1;
+	c[DMNV_XXX]=0;
+#endif
+
+}
+
+/* Montgomery reduction */
+void XXX::BIG_monty(BIG a,BIG md,chunk MC,DBIG d)
+{
+    int i,k;
+
+#ifdef dchunk
+    dchunk t,c,s;
+    dchunk dd[NLEN_XXX];
+    chunk v[NLEN_XXX];
+#endif
+
+#ifdef COMBA
+
+#ifdef UNWOUND
+
+    /* Insert output of faster.c here */
+
+#else
+
+    t=d[0];
+    v[0]=((chunk)t*MC)&BMASK_XXX;
+    t+=(dchunk)v[0]*md[0];
+    c=(t>>BASEBITS_XXX)+d[1];
+    s=0;
+
+    for (k=1; k<NLEN_XXX; k++)
+    {
+        t=c+s+(dchunk)v[0]*md[k];
+        for (i=k-1; i>k/2; i--) t+=(dchunk)(v[k-i]-v[i])*(md[i]-md[k-i]);
+        v[k]=((chunk)t*MC)&BMASK_XXX;
+        t+=(dchunk)v[k]*md[0];
+        c=(t>>BASEBITS_XXX)+d[k+1];
+        dd[k]=(dchunk)v[k]*md[k];
+        s+=dd[k];
+    }
+    for (k=NLEN_XXX; k<2*NLEN_XXX-1; k++)
+    {
+        t=c+s;
+        for (i=NLEN_XXX-1; i>=1+k/2; i--) t+=(dchunk)(v[k-i]-v[i])*(md[i]-md[k-i]);
+        a[k-NLEN_XXX]=(chunk)t&BMASK_XXX;
+        c=(t>>BASEBITS_XXX)+d[k+1];
+        s-=dd[k-NLEN_XXX+1];
+    }
+    a[NLEN_XXX-1]=(chunk)c&BMASK_XXX;
+
+#endif
+
+
+
+#else
+    int j;
+    chunk m,carry;
+    for (i=0; i<NLEN_XXX; i++)
+    {
+        if (MC==-1) m=(-d[i])&BMASK_XXX;
+        else
+        {
+            if (MC==1) m=d[i];
+            else m=(MC*d[i])&BMASK_XXX;
+        }
+        carry=0;
+        for (j=0; j<NLEN_XXX; j++)
+            carry=muladd(m,md[j],carry,&d[i+j]);
+        d[NLEN_XXX+i]+=carry;
+    }
+    BIG_sducopy(a,d);
+    BIG_norm(a);
+
+#endif
+
+#ifdef DEBUG_NORM
+	a[MPV_XXX]=1;  a[MNV_XXX]=0;
+#endif
+}
+
+/* General shift left of a by n bits */
+/* a MUST be normalised */
+/* SU= 32 */
+void XXX::BIG_shl(BIG a,int k)
+{
+    int i;
+    int n=k%BASEBITS_XXX;
+    int m=k/BASEBITS_XXX;
+
+    a[NLEN_XXX-1]=((a[NLEN_XXX-1-m]<<n));
+    if (NLEN_XXX>=m+2) a[NLEN_XXX-1]|=(a[NLEN_XXX-m-2]>>(BASEBITS_XXX-n));
+
+    for (i=NLEN_XXX-2; i>m; i--)
+        a[i]=((a[i-m]<<n)&BMASK_XXX)|(a[i-m-1]>>(BASEBITS_XXX-n));
+    a[m]=(a[0]<<n)&BMASK_XXX;
+    for (i=0; i<m; i++) a[i]=0;
+
+}
+
+/* Fast shift left of a by n bits, where n less than a word, Return excess (but store it as well) */
+/* a MUST be normalised */
+/* SU= 16 */
+int XXX::BIG_fshl(BIG a,int n)
+{
+    int i;
+
+    a[NLEN_XXX-1]=((a[NLEN_XXX-1]<<n))|(a[NLEN_XXX-2]>>(BASEBITS_XXX-n)); /* top word not masked */
+    for (i=NLEN_XXX-2; i>0; i--)
+        a[i]=((a[i]<<n)&BMASK_XXX)|(a[i-1]>>(BASEBITS_XXX-n));
+    a[0]=(a[0]<<n)&BMASK_XXX;
+
+    return (int)(a[NLEN_XXX-1]>>((8*MODBYTES_XXX)%BASEBITS_XXX)); /* return excess - only used in ff.c */
+}
+
+/* double length left shift of a by k bits - k can be > BASEBITS_XXX , a MUST be normalised */
+/* SU= 32 */
+void XXX::BIG_dshl(DBIG a,int k)
+{
+    int i;
+    int n=k%BASEBITS_XXX;
+    int m=k/BASEBITS_XXX;
+
+    a[DNLEN_XXX-1]=((a[DNLEN_XXX-1-m]<<n))|(a[DNLEN_XXX-m-2]>>(BASEBITS_XXX-n));
+
+    for (i=DNLEN_XXX-2; i>m; i--)
+        a[i]=((a[i-m]<<n)&BMASK_XXX)|(a[i-m-1]>>(BASEBITS_XXX-n));
+    a[m]=(a[0]<<n)&BMASK_XXX;
+    for (i=0; i<m; i++) a[i]=0;
+
+}
+
+/* General shift rightof a by k bits */
+/* a MUST be normalised */
+/* SU= 32 */
+void XXX::BIG_shr(BIG a,int k)
+{
+    int i;
+    int n=k%BASEBITS_XXX;
+    int m=k/BASEBITS_XXX;
+    for (i=0; i<NLEN_XXX-m-1; i++)
+        a[i]=(a[m+i]>>n)|((a[m+i+1]<<(BASEBITS_XXX-n))&BMASK_XXX);
+    if (NLEN_XXX>m)  a[NLEN_XXX-m-1]=a[NLEN_XXX-1]>>n;
+    for (i=NLEN_XXX-m; i<NLEN_XXX; i++) a[i]=0;
+
+}
+
+/* Fast combined shift, subtract and norm. Return sign of result */
+int XXX::BIG_ssn(BIG r,BIG a,BIG m)
+{
+	int i,n=NLEN_XXX-1;
+	chunk carry;
+	m[0]=(m[0]>>1)|((m[1]<<(BASEBITS_XXX-1))&BMASK_XXX);
+	r[0]=a[0]-m[0];
+    carry=r[0]>>BASEBITS_XXX;
+    r[0]&=BMASK_XXX;
+    
+	for (i=1;i<n;i++)
+	{
+		m[i]=(m[i]>>1)|((m[i+1]<<(BASEBITS_XXX-1))&BMASK_XXX);
+		r[i]=a[i]-m[i]+carry;
+		carry=r[i]>>BASEBITS_XXX;
+		r[i]&=BMASK_XXX;
+	}
+	
+	m[n]>>=1;
+	r[n]=a[n]-m[n]+carry;
+#ifdef DEBUG_NORM
+	r[MPV_XXX]=1; r[MNV_XXX]=0;
+#endif
+	return ((r[n]>>(CHUNK-1))&1);
+}
+
+/* Faster shift right of a by k bits. Return shifted out part */
+/* a MUST be normalised */
+/* SU= 16 */
+int XXX::BIG_fshr(BIG a,int k)
+{
+    int i;
+    chunk r=a[0]&(((chunk)1<<k)-1); /* shifted out part */
+    for (i=0; i<NLEN_XXX-1; i++)
+        a[i]=(a[i]>>k)|((a[i+1]<<(BASEBITS_XXX-k))&BMASK_XXX);
+    a[NLEN_XXX-1]=a[NLEN_XXX-1]>>k;
+    return (int)r;
+}
+
+/* double length right shift of a by k bits - can be > BASEBITS_XXX */
+/* SU= 32 */
+void XXX::BIG_dshr(DBIG a,int k)
+{
+    int i;
+    int n=k%BASEBITS_XXX;
+    int m=k/BASEBITS_XXX;
+    for (i=0; i<DNLEN_XXX-m-1; i++)
+        a[i]=(a[m+i]>>n)|((a[m+i+1]<<(BASEBITS_XXX-n))&BMASK_XXX);
+    a[DNLEN_XXX-m-1]=a[DNLEN_XXX-1]>>n;
+    for (i=DNLEN_XXX-m; i<DNLEN_XXX; i++ ) a[i]=0;
+}
+
+/* Split DBIG d into two BIGs t|b. Split happens at n bits, where n falls into NLEN_XXX word */
+/* d MUST be normalised */
+/* SU= 24 */
+chunk XXX::BIG_split(BIG t,BIG b,DBIG d,int n)
+{
+    int i;
+    chunk nw,carry=0;
+    int m=n%BASEBITS_XXX;
+//	BIG_dnorm(d);
+
+    if (m==0)
+    {
+        for (i=0; i<NLEN_XXX; i++) b[i]=d[i];
+        if (t!=b)
+        {
+            for (i=NLEN_XXX; i<2*NLEN_XXX; i++) t[i-NLEN_XXX]=d[i];
+            carry=t[NLEN_XXX-1]>>BASEBITS_XXX;
+            t[NLEN_XXX-1]=t[NLEN_XXX-1]&BMASK_XXX; /* top word normalized */
+        }
+        return carry;
+    }
+
+    for (i=0; i<NLEN_XXX-1; i++) b[i]=d[i];
+
+    b[NLEN_XXX-1]=d[NLEN_XXX-1]&(((chunk)1<<m)-1);
+
+    if (t!=b)
+    {
+        carry=(d[DNLEN_XXX-1]<<(BASEBITS_XXX-m));
+        for (i=DNLEN_XXX-2; i>=NLEN_XXX-1; i--)
+        {
+            nw=(d[i]>>m)|carry;
+            carry=(d[i]<<(BASEBITS_XXX-m))&BMASK_XXX;
+            t[i-NLEN_XXX+1]=nw;
+        }
+    }
+#ifdef DEBUG_NORM
+    t[MPV_XXX]=1; t[MNV_XXX]=0;
+    b[MPV_XXX]=1; b[MNV_XXX]=0;
+#endif
+    return carry;
+}
+
+/* you gotta keep the sign of carry! Look - no branching! */
+/* Note that sign bit is needed to disambiguate between +ve and -ve values */
+/* normalise BIG - force all digits < 2^BASEBITS_XXX */
+chunk XXX::BIG_norm(BIG a)
+{
+    int i;
+    chunk d,carry=0;
+    for (i=0; i<NLEN_XXX-1; i++)
+    {
+        d=a[i]+carry;
+        a[i]=d&BMASK_XXX;
+        carry=d>>BASEBITS_XXX;
+    }
+    a[NLEN_XXX-1]=(a[NLEN_XXX-1]+carry);
+
+#ifdef DEBUG_NORM
+	a[MPV_XXX]=1; a[MNV_XXX]=0;
+#endif
+    return (a[NLEN_XXX-1]>>((8*MODBYTES_XXX)%BASEBITS_XXX));  /* only used in ff.c */
+}
+
+void XXX::BIG_dnorm(DBIG a)
+{
+    int i;
+    chunk d,carry=0;
+    for (i=0; i<DNLEN_XXX-1; i++)
+    {
+        d=a[i]+carry;
+        a[i]=d&BMASK_XXX;
+        carry=d>>BASEBITS_XXX;
+    }
+    a[DNLEN_XXX-1]=(a[DNLEN_XXX-1]+carry);
+#ifdef DEBUG_NORM
+	a[DMPV_XXX]=1; a[DMNV_XXX]=0;
+#endif
+}
+
+/* Compare a and b. Return 1 for a>b, -1 for a<b, 0 for a==b */
+/* a and b MUST be normalised before call */
+int XXX::BIG_comp(BIG a,BIG b)
+{
+    int i;
+    for (i=NLEN_XXX-1; i>=0; i--)
+    {
+        if (a[i]==b[i]) continue;
+        if (a[i]>b[i]) return 1;
+        else  return -1;
+    }
+    return 0;
+}
+
+int XXX::BIG_dcomp(DBIG a,DBIG b)
+{
+    int i;
+    for (i=DNLEN_XXX-1; i>=0; i--)
+    {
+        if (a[i]==b[i]) continue;
+        if (a[i]>b[i]) return 1;
+        else  return -1;
+    }
+    return 0;
+}
+
+/* return number of bits in a */
+/* SU= 8 */
+int XXX::BIG_nbits(BIG a)
+{
+    int bts,k=NLEN_XXX-1;
+	BIG t;
+    chunk c;
+	BIG_copy(t,a);
+    BIG_norm(t);
+    while (k>=0 && t[k]==0) k--;
+    if (k<0) return 0;
+    bts=BASEBITS_XXX*k;
+    c=t[k];
+    while (c!=0)
+    {
+        c/=2;
+        bts++;
+    }
+    return bts;
+}
+
+/* SU= 8, Calculate number of bits in a DBIG - output normalised */
+int XXX::BIG_dnbits(DBIG a)
+{
+    int bts,k=DNLEN_XXX-1;
+	DBIG t;
+    chunk c;
+	BIG_dcopy(t,a);
+    BIG_dnorm(t);
+    while (k>=0 && t[k]==0) k--;
+    if (k<0) return 0;
+    bts=BASEBITS_XXX*k;
+    c=t[k];
+    while (c!=0)
+    {
+        c/=2;
+        bts++;
+    }
+    return bts;
+}
+
+
+/* Set b=b mod c */
+/* SU= 16 */
+void XXX::BIG_mod(BIG b,BIG c1)
+{
+    int k=0;
+    BIG r; /**/
+	BIG c;
+	BIG_copy(c,c1);
+
+    BIG_norm(b);
+    if (BIG_comp(b,c)<0)
+        return;
+    do
+    {
+        BIG_fshl(c,1);
+        k++;
+    }
+    while (BIG_comp(b,c)>=0);
+
+    while (k>0)
+    {
+        BIG_fshr(c,1);
+
+// constant time...
+        BIG_sub(r,b,c);
+        BIG_norm(r);
+        BIG_cmove(b,r,1-((r[NLEN_XXX-1]>>(CHUNK-1))&1));
+        k--;
+    }
+}
+
+/* Set a=b mod c, b is destroyed. Slow but rarely used. */
+/* SU= 96 */
+void XXX::BIG_dmod(BIG a,DBIG b,BIG c)
+{
+    int k=0;
+    DBIG m,r;
+    BIG_dnorm(b);
+    BIG_dscopy(m,c);
+
+    if (BIG_dcomp(b,m)<0)
+    {
+        BIG_sdcopy(a,b);
+        return;
+    }
+
+    do
+    {
+        BIG_dshl(m,1);
+        k++;
+    }
+    while (BIG_dcomp(b,m)>=0);
+
+    while (k>0)
+    {
+        BIG_dshr(m,1);
+// constant time...
+        BIG_dsub(r,b,m);
+        BIG_dnorm(r);
+        BIG_dcmove(b,r,1-((r[DNLEN_XXX-1]>>(CHUNK-1))&1));
+
+        k--;
+    }
+    BIG_sdcopy(a,b);
+}
+
+/* Set a=b/c,  b is destroyed. Slow but rarely used. */
+/* SU= 136 */
+
+void XXX::BIG_ddiv(BIG a,DBIG b,BIG c)
+{
+    int d,k=0;
+    DBIG m,dr;
+    BIG e,r;
+    BIG_dnorm(b);
+    BIG_dscopy(m,c);
+
+    BIG_zero(a);
+    BIG_zero(e);
+    BIG_inc(e,1);
+
+    while (BIG_dcomp(b,m)>=0)
+    {
+        BIG_fshl(e,1);
+        BIG_dshl(m,1);
+        k++;
+    }
+
+    while (k>0)
+    {
+        BIG_dshr(m,1);
+        BIG_fshr(e,1);
+
+        BIG_dsub(dr,b,m);
+        BIG_dnorm(dr);
+        d=1-((dr[DNLEN_XXX-1]>>(CHUNK-1))&1);
+        BIG_dcmove(b,dr,d);
+
+        BIG_add(r,a,e);
+        BIG_norm(r);
+        BIG_cmove(a,r,d);
+
+        k--;
+    }
+}
+
+/* SU= 136 */
+
+void XXX::BIG_sdiv(BIG a,BIG c)
+{
+    int d,k=0;
+    BIG m,e,b,r;
+    BIG_norm(a);
+    BIG_copy(b,a);
+    BIG_copy(m,c);
+
+    BIG_zero(a);
+    BIG_zero(e);
+    BIG_inc(e,1);
+
+    while (BIG_comp(b,m)>=0)
+    {
+        BIG_fshl(e,1);
+        BIG_fshl(m,1);
+        k++;
+    }
+
+    while (k>0)
+    {
+        BIG_fshr(m,1);
+        BIG_fshr(e,1);
+
+        BIG_sub(r,b,m);
+        BIG_norm(r);
+        d=1-((r[NLEN_XXX-1]>>(CHUNK-1))&1);
+        BIG_cmove(b,r,d);
+
+        BIG_add(r,a,e);
+        BIG_norm(r);
+        BIG_cmove(a,r,d);
+        k--;
+    }
+}
+
+/* return LSB of a */
+int XXX::BIG_parity(BIG a)
+{
+    return a[0]%2;
+}
+
+/* return n-th bit of a */
+/* SU= 16 */
+int XXX::BIG_bit(BIG a,int n)
+{
+    if (a[n/BASEBITS_XXX]&((chunk)1<<(n%BASEBITS_XXX))) return 1;
+    else return 0;
+}
+
+/* return NAF value as +/- 1, 3 or 5. x and x3 should be normed.
+nbs is number of bits processed, and nzs is number of trailing 0s detected */
+/* SU= 32 */
+/*
+int BIG_nafbits(BIG x,BIG x3,int i,int *nbs,int *nzs)
+{
+	int j,r,nb;
+
+	nb=BIG_bit(x3,i)-BIG_bit(x,i);
+	*nbs=1;
+	*nzs=0;
+	if (nb==0) return 0;
+	if (i==0) return nb;
+
+    if (nb>0) r=1;
+    else      r=(-1);
+
+    for (j=i-1;j>0;j--)
+    {
+        (*nbs)++;
+        r*=2;
+        nb=BIG_bit(x3,j)-BIG_bit(x,j);
+        if (nb>0) r+=1;
+        if (nb<0) r-=1;
+        if (abs(r)>5) break;
+    }
+
+	if (r%2!=0 && j!=0)
+    { // backtrack
+        if (nb>0) r=(r-1)/2;
+        if (nb<0) r=(r+1)/2;
+        (*nbs)--;
+    }
+
+    while (r%2==0)
+    { // remove trailing zeros
+        r/=2;
+        (*nzs)++;
+        (*nbs)--;
+    }
+    return r;
+}
+*/
+
+/* return last n bits of a, where n is small < BASEBITS_XXX */
+/* SU= 16 */
+int XXX::BIG_lastbits(BIG a,int n)
+{
+    int msk=(1<<n)-1;
+    BIG_norm(a);
+    return ((int)a[0])&msk;
+}
+
+/* get 8*MODBYTES_XXX size random number */
+void XXX::BIG_random(BIG m,csprng *rng)
+{
+    int i,b,j=0,r=0;
+    int len=8*MODBYTES_XXX;
+
+    BIG_zero(m);
+    /* generate random BIG */
+    for (i=0; i<len; i++)
+    {
+        if (j==0) r=RAND_byte(rng);
+        else r>>=1;
+        b=r&1;
+        BIG_shl(m,1);
+        m[0]+=b;
+        j++;
+        j&=7;
+    }
+
+#ifdef DEBUG_NORM
+	m[MPV_XXX]=1; m[MNV_XXX]=0;
+#endif
+}
+
+/* get random BIG from rng, modulo q. Done one bit at a time, so its portable */
+
+void XXX::BIG_randomnum(BIG m,BIG q,csprng *rng)
+{
+    int i,b,j=0,r=0;
+    DBIG d;
+    BIG_dzero(d);
+    /* generate random DBIG */
+    for (i=0; i<2*BIG_nbits(q); i++)
+    {
+        if (j==0) r=RAND_byte(rng);
+        else r>>=1;
+        b=r&1;
+        BIG_dshl(d,1);
+        d[0]+=b;
+        j++;
+        j&=7;
+    }
+    /* reduce modulo a BIG. Removes bias */
+    BIG_dmod(m,d,q);
+#ifdef DEBUG_NORM
+	m[MPV_XXX]=1; m[MNV_XXX]=0;
+#endif
+}
+
+/* Set r=a*b mod m */
+/* SU= 96 */
+void XXX::BIG_modmul(BIG r,BIG a1,BIG b1,BIG m)
+{
+    DBIG d;
+	BIG a,b;
+	BIG_copy(a,a1);
+	BIG_copy(b,b1);
+    BIG_mod(a,m);
+    BIG_mod(b,m);
+
+    BIG_mul(d,a,b);
+    BIG_dmod(r,d,m);
+}
+
+/* Set a=a*a mod m */
+/* SU= 88 */
+void XXX::BIG_modsqr(BIG r,BIG a1,BIG m)
+{
+    DBIG d;
+	BIG a;
+	BIG_copy(a,a1);
+    BIG_mod(a,m);
+    BIG_sqr(d,a);
+    BIG_dmod(r,d,m);
+}
+
+/* Set r=-a mod m */
+/* SU= 16 */
+void XXX::BIG_modneg(BIG r,BIG a1,BIG m)
+{
+	BIG a;
+	BIG_copy(a,a1);
+    BIG_mod(a,m);
+    BIG_sub(r,m,a);
+//    BIG_mod(r,m);
+}
+
+/* Set a=a/b mod m */
+/* SU= 136 */
+void XXX::BIG_moddiv(BIG r,BIG a1,BIG b1,BIG m)
+{
+    DBIG d;
+    BIG z;
+	BIG a,b;
+	BIG_copy(a,a1);
+	BIG_copy(b,b1);
+    BIG_mod(a,m);
+    BIG_invmodp(z,b,m);
+
+    BIG_mul(d,a,z);
+    BIG_dmod(r,d,m);
+}
+
+/* Get jacobi Symbol (a/p). Returns 0, 1 or -1 */
+/* SU= 216 */
+int XXX::BIG_jacobi(BIG a,BIG p)
+{
+    int n8,k,m=0;
+    BIG t,x,n,zilch,one;
+    BIG_one(one);
+    BIG_zero(zilch);
+    if (BIG_parity(p)==0 || BIG_comp(a,zilch)==0 || BIG_comp(p,one)<=0) return 0;
+    BIG_norm(a);
+    BIG_copy(x,a);
+    BIG_copy(n,p);
+    BIG_mod(x,p);
+
+    while (BIG_comp(n,one)>0)
+    {
+        if (BIG_comp(x,zilch)==0) return 0;
+        n8=BIG_lastbits(n,3);
+        k=0;
+        while (BIG_parity(x)==0)
+        {
+            k++;
+            BIG_shr(x,1);
+        }
+        if (k%2==1) m+=(n8*n8-1)/8;
+        m+=(n8-1)*(BIG_lastbits(x,2)-1)/4;
+        BIG_copy(t,n);
+
+        BIG_mod(t,x);
+        BIG_copy(n,x);
+        BIG_copy(x,t);
+        m%=2;
+
+    }
+    if (m==0) return 1;
+    else return -1;
+}
+
+/* Set r=1/a mod p. Binary method */
+/* SU= 240 */
+void XXX::BIG_invmodp(BIG r,BIG a,BIG p)
+{
+    BIG u,v,x1,x2,t,one;
+    BIG_mod(a,p);
+    BIG_copy(u,a);
+    BIG_copy(v,p);
+    BIG_one(one);
+    BIG_copy(x1,one);
+    BIG_zero(x2);
+
+    while (BIG_comp(u,one)!=0 && BIG_comp(v,one)!=0)
+    {
+        while (BIG_parity(u)==0)
+        {
+            BIG_fshr(u,1);
+            if (BIG_parity(x1)!=0)
+            {
+                BIG_add(x1,p,x1);
+                BIG_norm(x1);
+            }
+            BIG_fshr(x1,1);
+        }
+        while (BIG_parity(v)==0)
+        {
+            BIG_fshr(v,1);
+            if (BIG_parity(x2)!=0)
+            {
+                BIG_add(x2,p,x2);
+                BIG_norm(x2);
+            }
+            BIG_fshr(x2,1);
+        }
+        if (BIG_comp(u,v)>=0)
+        {
+            BIG_sub(u,u,v);
+            BIG_norm(u);
+            if (BIG_comp(x1,x2)>=0) BIG_sub(x1,x1,x2);
+            else
+            {
+                BIG_sub(t,p,x2);
+                BIG_add(x1,x1,t);
+            }
+            BIG_norm(x1);
+        }
+        else
+        {
+            BIG_sub(v,v,u);
+            BIG_norm(v);
+            if (BIG_comp(x2,x1)>=0) BIG_sub(x2,x2,x1);
+            else
+            {
+                BIG_sub(t,p,x1);
+                BIG_add(x2,x2,t);
+            }
+            BIG_norm(x2);
+        }
+    }
+    if (BIG_comp(u,one)==0)
+        BIG_copy(r,x1);
+    else
+        BIG_copy(r,x2);
+}
+
+/* set x = x mod 2^m */
+void XXX::BIG_mod2m(BIG x,int m)
+{
+    int i,wd,bt;
+    chunk msk;
+	BIG_norm(x);
+//	if (m>=MODBITS) return;
+    wd=m/BASEBITS_XXX;
+    bt=m%BASEBITS_XXX;
+    msk=((chunk)1<<bt)-1;
+    x[wd]&=msk;
+    for (i=wd+1; i<NLEN_XXX; i++) x[i]=0;
+}
+
+// new
+/* Convert to DBIG number from byte array of given length */
+void XXX::BIG_dfromBytesLen(DBIG a,char *b,int s)
+{
+    int i,len=s;
+    BIG_dzero(a);
+
+    for (i=0; i<len; i++)
+    {
+        BIG_dshl(a,8);
+        a[0]+=(int)(unsigned char)b[i];
+    }
+#ifdef DEBUG_NORM
+	a[DMPV_XXX]=1; a[DMNV_XXX]=0;
+#endif
+}
diff --git a/version3/cpp/big.h b/version3/cpp/big.h
new file mode 100644
index 0000000..1f4f451
--- /dev/null
+++ b/version3/cpp/big.h
@@ -0,0 +1,595 @@
+#ifndef BIG_XXX_H
+#define BIG_XXX_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include "arch.h"
+#include "amcl.h"
+#include "config_big_XXX.h"
+
+using namespace amcl;
+
+
+//#define UNWOUND
+
+#define BIGBITS_XXX (8*MODBYTES_XXX)
+#define NLEN_XXX (1+((8*MODBYTES_XXX-1)/BASEBITS_XXX))
+#define DNLEN_XXX 2*NLEN_XXX
+#define BMASK_XXX (((chunk)1<<BASEBITS_XXX)-1) /**< Mask = 2^BASEBITS-1 */
+#define NEXCESS_XXX (1<<(CHUNK-BASEBITS_XXX-1))           /**< 2^(CHUNK-BASEBITS-1) - digit cannot be multiplied by more than this before normalisation */
+
+#define HBITS_XXX (BASEBITS_XXX/2)      /**< Number of bits in number base divided by 2 */
+#define HMASK_XXX (((chunk)1<<HBITS_XXX)-1)    /**< Mask = 2^HBITS-1 */
+
+//#define DEBUG_NORM
+
+#ifdef DEBUG_NORM  /* Add an extra location to track chunk extension */
+#define MPV_XXX NLEN_XXX
+#define MNV_XXX (NLEN_XXX+1)
+#define DMPV_XXX DNLEN_XXX
+#define DMNV_XXX (DNLEN_XXX+1)
+
+#endif
+
+namespace XXX {
+
+#ifdef DEBUG_NORM 
+typedef chunk BIG[NLEN_XXX+2];   /**< Define type BIG as array of chunks */
+typedef chunk DBIG[DNLEN_XXX+2]; /**< Define type DBIG as array of chunks */
+#else
+typedef chunk BIG[NLEN_XXX];     /**< Define type BIG as array of chunks */
+typedef chunk DBIG[DNLEN_XXX];   /**< Define type DBIG as array of chunks */
+#endif
+
+/* BIG number prototypes */
+
+/**	@brief Tests for BIG equal to zero
+ *
+	@param x a BIG number
+	@return 1 if zero, else returns 0
+ */
+extern int BIG_iszilch(BIG x);
+/**	@brief Tests for BIG equal to one
+ *
+	@param x a BIG number
+	@return 1 if one, else returns 0
+ */
+extern int BIG_isunity(BIG x);
+/**	@brief Tests for DBIG equal to zero
+ *
+	@param x a DBIG number
+	@return 1 if zero, else returns 0
+ */
+extern int BIG_diszilch(DBIG x);
+/**	@brief Outputs a BIG number to the console
+ *
+	@param x a BIG number
+ */
+extern void BIG_output(BIG x);
+/**	@brief Outputs a BIG number to the console in raw form (for debugging)
+ *
+	@param x a BIG number
+ */
+extern void BIG_rawoutput(BIG x);
+/**	@brief Conditional constant time swap of two BIG numbers
+ *
+	Conditionally swaps parameters in constant time (without branching)
+	@param x a BIG number
+	@param y another BIG number
+	@param s swap takes place if not equal to 0
+ */
+extern void BIG_cswap(BIG x,BIG y,int s);
+/**	@brief Conditional copy of BIG number
+ *
+	Conditionally copies second parameter to the first (without branching)
+	@param x a BIG number
+	@param y another BIG number
+	@param s copy takes place if not equal to 0
+ */
+extern void BIG_cmove(BIG x,BIG y,int s);
+/**	@brief Conditional copy of DBIG number
+ *
+	Conditionally copies second parameter to the first (without branching)
+	@param x a DBIG number
+	@param y another DBIG number
+	@param s copy takes place if not equal to 0
+ */
+extern void BIG_dcmove(BIG x,BIG y,int s);
+/**	@brief Convert from BIG number to byte array
+ *
+	@param a byte array
+	@param x BIG number
+ */
+extern void BIG_toBytes(char *a,BIG x);
+/**	@brief Convert to BIG number from byte array
+ *
+	@param x BIG number
+	@param a byte array
+ */
+extern void BIG_fromBytes(BIG x,char *a);
+/**	@brief Convert to BIG number from byte array of given length
+ *
+	@param x BIG number
+	@param a byte array
+	@param s byte array length
+ */
+extern void BIG_fromBytesLen(BIG x,char *a,int s);
+/**@brief Convert to DBIG number from byte array of given length
+ *
+   @param x DBIG number
+   @param a byte array
+   @param s byte array length
+ */
+extern void BIG_dfromBytesLen(DBIG x,char *a,int s);
+/**	@brief Outputs a DBIG number to the console
+ *
+	@param x a DBIG number
+ */
+extern void BIG_doutput(DBIG x);
+
+/**	@brief Outputs a DBIG number to the console
+ *
+	@param x a DBIG number
+ */
+extern void BIG_drawoutput(DBIG x);
+
+/**	@brief Copy BIG from Read-Only Memory to a BIG
+ *
+	@param x BIG number
+	@param y BIG number in ROM
+ */
+extern void BIG_rcopy(BIG x,const BIG y);
+/**	@brief Copy BIG to another BIG
+ *
+	@param x BIG number
+	@param y BIG number to be copied
+ */
+extern void BIG_copy(BIG x,BIG y);
+/**	@brief Copy DBIG to another DBIG
+ *
+	@param x DBIG number
+	@param y DBIG number to be copied
+ */
+extern void BIG_dcopy(DBIG x,DBIG y);
+/**	@brief Copy BIG to upper half of DBIG
+ *
+	@param x DBIG number
+	@param y BIG number to be copied
+ */
+extern void BIG_dsucopy(DBIG x,BIG y);
+/**	@brief Copy BIG to lower half of DBIG
+ *
+	@param x DBIG number
+	@param y BIG number to be copied
+ */
+extern void BIG_dscopy(DBIG x,BIG y);
+/**	@brief Copy lower half of DBIG to a BIG
+ *
+	@param x BIG number
+	@param y DBIG number to be copied
+ */
+extern void BIG_sdcopy(BIG x,DBIG y);
+/**	@brief Copy upper half of DBIG to a BIG
+ *
+	@param x BIG number
+	@param y DBIG number to be copied
+ */
+extern void BIG_sducopy(BIG x,DBIG y);
+/**	@brief Set BIG to zero
+ *
+	@param x BIG number to be set to zero
+ */
+extern void BIG_zero(BIG x);
+/**	@brief Set DBIG to zero
+ *
+	@param x DBIG number to be set to zero
+ */
+extern void BIG_dzero(DBIG x);
+/**	@brief Set BIG to one (unity)
+ *
+	@param x BIG number to be set to one.
+ */
+extern void BIG_one(BIG x);
+/**	@brief Set BIG to inverse mod 2^256
+ *
+	@param x BIG number to be inverted
+ */
+extern void BIG_invmod2m(BIG x);
+/**	@brief Set BIG to sum of two BIGs - output not normalised
+ *
+	@param x BIG number, sum of other two
+	@param y BIG number
+	@param z BIG number
+ */
+extern void BIG_add(BIG x,BIG y,BIG z);
+
+/**	@brief Set BIG to logical or of two BIGs - output normalised
+ *
+	@param x BIG number, or of other two
+	@param y BIG number
+	@param z BIG number
+ */
+extern void BIG_or(BIG x,BIG y,BIG z);
+
+/**	@brief Increment BIG by a small integer - output not normalised
+ *
+	@param x BIG number to be incremented
+	@param i integer
+ */
+extern void BIG_inc(BIG x,int i);
+/**	@brief Set BIG to difference of two BIGs
+ *
+	@param x BIG number, difference of other two - output not normalised
+	@param y BIG number
+	@param z BIG number
+ */
+extern void BIG_sub(BIG x,BIG y,BIG z);
+/**	@brief Decrement BIG by a small integer - output not normalised
+ *
+	@param x BIG number to be decremented
+	@param i integer
+ */
+extern void BIG_dec(BIG x,int i);
+/**	@brief Set DBIG to sum of two DBIGs
+ *
+	@param x DBIG number, sum of other two - output not normalised
+	@param y DBIG number
+	@param z DBIG number
+ */
+extern void BIG_dadd(DBIG x,DBIG y,DBIG z);
+/**	@brief Set DBIG to difference of two DBIGs
+ *
+	@param x DBIG number, difference of other two - output not normalised
+	@param y DBIG number
+	@param z DBIG number
+ */
+extern void BIG_dsub(DBIG x,DBIG y,DBIG z);
+/**	@brief Multiply BIG by a small integer - output not normalised
+ *
+	@param x BIG number, product of other two
+	@param y BIG number
+	@param i small integer
+ */
+extern void BIG_imul(BIG x,BIG y,int i);
+/**	@brief Multiply BIG by not-so-small small integer - output normalised
+ *
+	@param x BIG number, product of other two
+	@param y BIG number
+	@param i small integer
+	@return Overflowing bits
+ */
+extern chunk BIG_pmul(BIG x,BIG y,int i);
+/**	@brief Divide BIG by 3 - output normalised
+ *
+	@param x BIG number
+	@return Remainder
+ */
+extern int BIG_div3(BIG x);
+/**	@brief Multiply BIG by even bigger small integer resulting in a DBIG - output normalised
+ *
+	@param x DBIG number, product of other two
+	@param y BIG number
+	@param i small integer
+ */
+extern void BIG_pxmul(DBIG x,BIG y,int i);
+/**	@brief Multiply BIG by another BIG resulting in DBIG - inputs normalised and output normalised
+ *
+	@param x DBIG number, product of other two
+	@param y BIG number
+	@param z BIG number
+ */
+extern void BIG_mul(DBIG x,BIG y,BIG z);
+/**	@brief Multiply BIG by another BIG resulting in another BIG - inputs normalised and output normalised
+ *
+	Note that the product must fit into a BIG, and x must be distinct from y and z
+	@param x BIG number, product of other two
+	@param y BIG number
+	@param z BIG number
+ */
+extern void BIG_smul(BIG x,BIG y,BIG z);
+/**	@brief Square BIG resulting in a DBIG - input normalised and output normalised
+ *
+	@param x DBIG number, square of a BIG
+	@param y BIG number to be squared
+ */
+extern void BIG_sqr(DBIG x,BIG y);
+
+/**	@brief Montgomery reduction of a DBIG to a BIG  - input normalised and output normalised
+ *
+	@param a BIG number, reduction of a BIG
+	@param md BIG number, the modulus
+	@param MC the Montgomery Constant
+	@param d DBIG number to be reduced
+ */
+extern void BIG_monty(BIG a,BIG md,chunk MC,DBIG d);
+
+/**	@brief Shifts a BIG left by any number of bits - input must be normalised, output normalised
+ *
+	@param x BIG number to be shifted
+	@param s Number of bits to shift
+ */
+extern void BIG_shl(BIG x,int s);
+/**	@brief Fast shifts a BIG left by a small number of bits - input must be normalised, output will be normalised
+ *
+	The number of bits to be shifted must be less than BASEBITS
+	@param x BIG number to be shifted
+	@param s Number of bits to shift
+	@return Overflow bits
+ */
+extern int BIG_fshl(BIG x,int s);
+/**	@brief Shifts a DBIG left by any number of bits - input must be normalised, output normalised
+ *
+	@param x DBIG number to be shifted
+	@param s Number of bits to shift
+ */
+extern void BIG_dshl(DBIG x,int s);
+/**	@brief Shifts a BIG right by any number of bits - input must be normalised, output normalised
+ *
+	@param x BIG number to be shifted
+	@param s Number of bits to shift
+ */
+extern void BIG_shr(BIG x,int s);
+
+
+/**	@brief Fast time-critical combined shift by 1 bit, subtract and normalise
+ *
+	@param r BIG number normalised output
+	@param a BIG number to be subtracted from
+	@param m BIG number to be shifted and subtracted
+	@return sign of r
+ */
+extern int BIG_ssn(BIG r,BIG a, BIG m);
+
+/**	@brief Fast shifts a BIG right by a small number of bits - input must be normalised, output will be normalised
+ *
+	The number of bits to be shifted must be less than BASEBITS
+	@param x BIG number to be shifted
+	@param s Number of bits to shift
+	@return Shifted out bits
+ */
+extern int BIG_fshr(BIG x,int s);
+/**	@brief Shifts a DBIG right by any number of bits - input must be normalised, output normalised
+ *
+	@param x DBIG number to be shifted
+	@param s Number of bits to shift
+ */
+extern void BIG_dshr(DBIG x,int s);
+/**	@brief Splits a DBIG into two BIGs - input must be normalised, outputs normalised
+ *
+	Internal function. The value of s must be approximately in the middle of the DBIG.
+	Typically used to extract z mod 2^MODBITS and z/2^MODBITS
+	@param x BIG number, top half of z
+	@param y BIG number, bottom half of z
+	@param z DBIG number to be split in two.
+	@param s Bit position at which to split
+	@return carry-out from top half
+ */
+extern chunk BIG_split(BIG x,BIG y,DBIG z,int s);
+/**	@brief Normalizes a BIG number - output normalised
+ *
+	All digits of the input BIG are reduced mod 2^BASEBITS
+	@param x BIG number to be normalised
+ */
+extern chunk BIG_norm(BIG x);
+/**	@brief Normalizes a DBIG number - output normalised
+ *
+	All digits of the input DBIG are reduced mod 2^BASEBITS
+	@param x DBIG number to be normalised
+ */
+extern void BIG_dnorm(DBIG x);
+/**	@brief Compares two BIG numbers. Inputs must be normalised externally
+ *
+	@param x first BIG number to be compared
+	@param y second BIG number to be compared
+	@return -1 is x<y, 0 if x=y, 1 if x>y
+ */
+extern int BIG_comp(BIG x,BIG y);
+/**	@brief Compares two DBIG numbers. Inputs must be normalised externally
+ *
+	@param x first DBIG number to be compared
+	@param y second DBIG number to be compared
+	@return -1 is x<y, 0 if x=y, 1 if x>y
+ */
+extern int BIG_dcomp(DBIG x,DBIG y);
+/**	@brief Calculate number of bits in a BIG - output normalised
+ *
+	@param x BIG number
+	@return Number of bits in x
+ */
+extern int BIG_nbits(BIG x);
+/**	@brief Calculate number of bits in a DBIG - output normalised
+ *
+	@param x DBIG number
+	@return Number of bits in x
+ */
+extern int BIG_dnbits(DBIG x);
+/**	@brief Reduce x mod n - input and output normalised
+ *
+	Slow but rarely used
+	@param x BIG number to be reduced mod n
+	@param n The modulus
+ */
+extern void BIG_mod(BIG x,BIG n);
+/**	@brief Divide x by n - output normalised
+ *
+	Slow but rarely used
+	@param x BIG number to be divided by n
+	@param n The Divisor
+ */
+extern void BIG_sdiv(BIG x,BIG n);
+/**	@brief  x=y mod n - output normalised
+ *
+	Slow but rarely used. y is destroyed.
+	@param x BIG number, on exit = y mod n
+	@param y DBIG number
+	@param n Modulus
+ */
+extern void BIG_dmod(BIG x,DBIG y,BIG n);
+/**	@brief  x=y/n - output normalised
+ *
+	Slow but rarely used. y is destroyed.
+	@param x BIG number, on exit = y/n
+	@param y DBIG number
+	@param n Modulus
+ */
+extern void BIG_ddiv(BIG x,DBIG y,BIG n);
+/**	@brief  return parity of BIG, that is the least significant bit
+ *
+	@param x BIG number
+	@return 0 or 1
+ */
+extern int BIG_parity(BIG x);
+/**	@brief  return i-th of BIG
+ *
+	@param x BIG number
+	@param i the bit of x to be returned
+	@return 0 or 1
+ */
+extern int BIG_bit(BIG x,int i);
+/**	@brief  return least significant bits of a BIG
+ *
+	@param x BIG number
+	@param n number of bits to return. Assumed to be less than BASEBITS.
+	@return least significant n bits as an integer
+ */
+extern int BIG_lastbits(BIG x,int n);
+/**	@brief  Create a random BIG from a random number generator
+ *
+	Assumes that the random number generator has been suitably initialised
+	@param x BIG number, on exit a random number
+	@param r A pointer to a Cryptographically Secure Random Number Generator
+ */
+extern void BIG_random(BIG x,csprng *r);
+/**	@brief  Create an unbiased random BIG from a random number generator, reduced with respect to a modulus
+ *
+	Assumes that the random number generator has been suitably initialised
+	@param x BIG number, on exit a random number
+	@param n The modulus
+	@param r A pointer to a Cryptographically Secure Random Number Generator
+ */
+extern void BIG_randomnum(BIG x,BIG n,csprng *r);
+/**	brief  return NAF (Non-Adjacent-Form) value as +/- 1, 3 or 5, inputs must be normalised
+ *
+	Given x and 3*x extracts NAF value from given bit position, and returns number of bits processed, and number of trailing zeros detected if any
+	param x BIG number
+	param x3 BIG number, three times x
+	param i bit position
+	param nbs pointer to integer returning number of bits processed
+	param nzs pointer to integer returning number of trailing 0s
+	return + or - 1, 3 or 5
+*/
+
+/**	@brief  Calculate x=y*z mod n
+ *
+	Slow method for modular multiplication
+	@param x BIG number, on exit = y*z mod n
+	@param y BIG number
+	@param z BIG number
+	@param n The BIG Modulus
+ */
+extern void BIG_modmul(BIG x,BIG y,BIG z,BIG n);
+/**	@brief  Calculate x=y/z mod n
+ *
+	Slow method for modular division
+	@param x BIG number, on exit = y/z mod n
+	@param y BIG number
+	@param z BIG number
+	@param n The BIG Modulus
+ */
+extern void BIG_moddiv(BIG x,BIG y,BIG z,BIG n);
+/**	@brief  Calculate x=y^2 mod n
+ *
+	Slow method for modular squaring
+	@param x BIG number, on exit = y^2 mod n
+	@param y BIG number
+	@param n The BIG Modulus
+ */
+extern void BIG_modsqr(BIG x,BIG y,BIG n);
+/**	@brief  Calculate x=-y mod n
+ *
+	Modular negation
+	@param x BIG number, on exit = -y mod n
+	@param y BIG number
+	@param n The BIG Modulus
+ */
+extern void BIG_modneg(BIG x,BIG y,BIG n);
+/**	@brief  Calculate jacobi Symbol (x/y)
+ *
+	@param x BIG number
+	@param y BIG number
+	@return Jacobi symbol, -1,0 or 1
+ */
+extern int BIG_jacobi(BIG x,BIG y);
+/**	@brief  Calculate x=1/y mod n
+ *
+	Modular Inversion - This is slow. Uses binary method.
+	@param x BIG number, on exit = 1/y mod n
+	@param y BIG number
+	@param n The BIG Modulus
+ */
+extern void BIG_invmodp(BIG x,BIG y,BIG n);
+/** @brief Calculate x=x mod 2^m
+ *
+	Truncation
+	@param x BIG number, on reduced mod 2^m
+	@param m new truncated size
+*/
+extern void BIG_mod2m(BIG x,int m);
+
+/**	@brief Calculates a*b+c+*d
+ *
+	Calculate partial product of a.b, add in carry c, and add total to d
+	@param a multiplier
+	@param b multiplicand
+	@param c carry
+	@param d pointer to accumulated bottom half of result
+	@return top half of result
+ */
+
+#ifdef dchunk
+
+/* Method required to calculate x*y+c+r, bottom half in r, top half returned */
+inline chunk muladd(chunk x,chunk y,chunk c,chunk *r)
+{
+    dchunk prod=(dchunk)x*y+c+*r;
+    *r=(chunk)prod&BMASK_XXX;
+    return (chunk)(prod>>BASEBITS_XXX);
+}
+
+#else
+
+/* No integer type available that can store double the wordlength */
+/* accumulate partial products */
+
+inline chunk muladd(chunk x,chunk y,chunk c,chunk *r)
+{
+    chunk x0,x1,y0,y1;
+    chunk bot,top,mid,carry;
+    x0=x&HMASK;
+    x1=(x>>HBITS_XXX);
+    y0=y&HMASK_XXX;
+    y1=(y>>HBITS_XXX);
+    bot=x0*y0;
+    top=x1*y1;
+    mid=x0*y1+x1*y0;
+    x0=mid&HMASK_XXX;
+    x1=(mid>>HBITS_XXX);
+    bot+=x0<<HBITS_XXX;
+    bot+=*r;
+    bot+=c;
+
+    top+=x1;
+    carry=bot>>BASEBITS_XXX;
+    bot&=BMASK_XXX;
+    top+=carry;
+
+    *r=bot;
+    return top;
+}
+
+#endif
+
+}
+
+#endif
\ No newline at end of file
diff --git a/version3/cpp/config16.py b/version3/cpp/config16.py
new file mode 100644
index 0000000..d22a76a
--- /dev/null
+++ b/version3/cpp/config16.py
@@ -0,0 +1,370 @@
+import os
+import sys
+
+deltext=""
+if sys.platform.startswith("linux")  :
+	deltext="rm"
+	copytext="cp"
+if sys.platform.startswith("darwin")  :
+	deltext="rm"
+	copytext="cp"
+if sys.platform.startswith("win") :
+	deltext="del"
+	copytext="copy"
+
+def replace(namefile,oldtext,newtext):
+	f = open(namefile,'r')
+	filedata = f.read()
+	f.close()
+
+	newdata = filedata.replace(oldtext,newtext)
+
+	f = open(namefile,'w')
+	f.write(newdata)
+	f.close()
+
+
+def rsaset(tb,tff,nb,base,ml) :
+	bd="B"+tb+"_"+base
+	fnameh="config_big_"+bd+".h"
+	os.system(copytext+" config_big.h "+fnameh)
+	replace(fnameh,"XXX",bd)
+	replace(fnameh,"@NB@",nb)
+	replace(fnameh,"@BASE@",base)
+
+	fnameh="config_ff_"+tff+".h"
+	os.system(copytext+" config_ff.h "+fnameh)
+	replace(fnameh,"XXX",bd)
+	replace(fnameh,"WWW",tff)
+	replace(fnameh,"@ML@",ml)
+
+	fnamec="big_"+bd+".cpp"
+	fnameh="big_"+bd+".h"
+
+	os.system(copytext+" big.cpp "+fnamec)
+	os.system(copytext+" big.h "+fnameh)
+
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"XXX",bd)
+	os.system("g++ -O3 -c "+fnamec)
+
+	fnamec="ff_"+tff+".cpp"
+	fnameh="ff_"+tff+".h"
+
+	os.system(copytext+" ff.cpp "+fnamec)
+	os.system(copytext+" ff.h "+fnameh)
+
+	replace(fnamec,"WWW",tff)
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"WWW",tff)
+	replace(fnameh,"XXX",bd)
+	os.system("g++ -O3 -c "+fnamec)
+
+	fnamec="rsa_"+tff+".cpp"
+	fnameh="rsa_"+tff+".h"
+
+	os.system(copytext+" rsa.cpp "+fnamec)
+	os.system(copytext+" rsa.h "+fnameh)
+
+	replace(fnamec,"WWW",tff)
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"WWW",tff)
+	replace(fnameh,"XXX",bd)
+	os.system("g++ -O3 -c "+fnamec)
+
+def curveset(tb,tf,tc,nb,base,nbt,m8,mt,ct,pf,stw,sx,cs) :
+	bd="B"+tb+"_"+base
+	fnameh="config_big_"+bd+".h"
+	os.system(copytext+" config_big.h "+fnameh)
+	replace(fnameh,"XXX",bd)
+	replace(fnameh,"@NB@",nb)
+	replace(fnameh,"@BASE@",base)
+
+	fnameh="config_field_"+tf+".h"
+	os.system(copytext+" config_field.h "+fnameh)
+	replace(fnameh,"XXX",bd)
+	replace(fnameh,"YYY",tf)
+	replace(fnameh,"@NBT@",nbt)
+	replace(fnameh,"@M8@",m8)
+	replace(fnameh,"@MT@",mt)
+
+	ib=int(base)
+	inb=int(nb)
+	inbt=int(nbt)
+	sh=ib*(1+((8*inb-1)//ib))-inbt
+
+	if sh > 6 :
+		sh=6
+	replace(fnameh,"@SH@",str(sh))
+
+	fnameh="config_curve_"+tc+".h"	
+	os.system(copytext+" config_curve.h "+fnameh)
+	replace(fnameh,"XXX",bd)
+	replace(fnameh,"YYY",tf)
+	replace(fnameh,"ZZZ",tc)
+	replace(fnameh,"@CT@",ct)
+	replace(fnameh,"@PF@",pf)
+
+	replace(fnameh,"@ST@",stw)
+	replace(fnameh,"@SX@",sx)
+	replace(fnameh,"@CS@",cs)
+
+
+	fnamec="big_"+bd+".cpp"
+	fnameh="big_"+bd+".h"
+
+	os.system(copytext+" big.cpp "+fnamec)
+	os.system(copytext+" big.h "+fnameh)
+
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"XXX",bd)
+	os.system("g++ -O3 -c "+fnamec)
+
+	fnamec="fp_"+tf+".cpp"
+	fnameh="fp_"+tf+".h"
+
+	os.system(copytext+" fp.cpp "+fnamec)
+	os.system(copytext+" fp.h "+fnameh)
+
+	replace(fnamec,"YYY",tf)
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"YYY",tf)
+	replace(fnameh,"XXX",bd)
+	os.system("g++ -O3 -c "+fnamec)
+
+	os.system("g++ -O3 -c rom_field_"+tf+".cpp")
+
+	fnamec="ecp_"+tc+".cpp"
+	fnameh="ecp_"+tc+".h"
+
+	os.system(copytext+" ecp.cpp "+fnamec)
+	os.system(copytext+" ecp.h "+fnameh)
+
+	replace(fnamec,"ZZZ",tc)
+	replace(fnamec,"YYY",tf)
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"ZZZ",tc)
+	replace(fnameh,"YYY",tf)
+	replace(fnameh,"XXX",bd)
+	os.system("g++ -O3 -c "+fnamec)
+
+	fnamec="ecdh_"+tc+".cpp"
+	fnameh="ecdh_"+tc+".h"
+
+	os.system(copytext+" ecdh.cpp "+fnamec)
+	os.system(copytext+" ecdh.h "+fnameh)
+
+	replace(fnamec,"ZZZ",tc)
+	replace(fnamec,"YYY",tf)
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"ZZZ",tc)
+	replace(fnameh,"YYY",tf)
+	replace(fnameh,"XXX",bd)
+	os.system("g++ -O3 -c "+fnamec)
+
+	os.system("g++ -O3 -c rom_curve_"+tc+".cpp")
+
+	if pf != "NOT" :
+		fnamec="fp2_"+tf+".cpp"
+		fnameh="fp2_"+tf+".h"
+
+		os.system(copytext+" fp2.cpp "+fnamec)
+		os.system(copytext+" fp2.h "+fnameh)
+		replace(fnamec,"YYY",tf)
+		replace(fnamec,"XXX",bd)
+		replace(fnameh,"YYY",tf)
+		replace(fnameh,"XXX",bd)
+		os.system("g++ -O3 -c "+fnamec)
+
+		fnamec="fp4_"+tf+".cpp"
+		fnameh="fp4_"+tf+".h"
+
+		os.system(copytext+" fp4.cpp "+fnamec)
+		os.system(copytext+" fp4.h "+fnameh)
+		replace(fnamec,"YYY",tf)
+		replace(fnamec,"XXX",bd)
+		replace(fnamec,"ZZZ",tc)
+		replace(fnameh,"YYY",tf)
+		replace(fnameh,"XXX",bd)
+		replace(fnameh,"ZZZ",tc)
+		os.system("g++ -O3 -c "+fnamec)
+
+		fnamec="fp12_"+tf+".cpp"
+		fnameh="fp12_"+tf+".h"
+
+		os.system(copytext+" fp12.cpp "+fnamec)
+		os.system(copytext+" fp12.h "+fnameh)
+		replace(fnamec,"YYY",tf)
+		replace(fnamec,"XXX",bd)
+		replace(fnameh,"YYY",tf)
+		replace(fnameh,"XXX",bd)
+		os.system("g++ -O3 -c "+fnamec)
+
+		fnamec="ecp2_"+tc+".cpp"
+		fnameh="ecp2_"+tc+".h"
+
+		os.system(copytext+" ecp2.cpp "+fnamec)
+		os.system(copytext+" ecp2.h "+fnameh)
+		replace(fnamec,"ZZZ",tc)
+		replace(fnamec,"YYY",tf)
+		replace(fnamec,"XXX",bd)
+		replace(fnameh,"ZZZ",tc)
+		replace(fnameh,"YYY",tf)
+		replace(fnameh,"XXX",bd)
+		os.system("g++ -O3 -c "+fnamec)
+
+		fnamec="pair_"+tc+".cpp"
+		fnameh="pair_"+tc+".h"
+
+		os.system(copytext+" pair.cpp "+fnamec)
+		os.system(copytext+" pair.h "+fnameh)
+		replace(fnamec,"ZZZ",tc)
+		replace(fnamec,"YYY",tf)
+		replace(fnamec,"XXX",bd)
+		replace(fnameh,"ZZZ",tc)
+		replace(fnameh,"YYY",tf)
+		replace(fnameh,"XXX",bd)
+		os.system("g++ -O3 -c "+fnamec)
+
+		fnamec="mpin_"+tc+".cpp"
+		fnameh="mpin_"+tc+".h"
+
+		os.system(copytext+" mpin.cpp "+fnamec)
+		os.system(copytext+" mpin.h "+fnameh)
+		replace(fnamec,"ZZZ",tc)
+		replace(fnamec,"YYY",tf)
+		replace(fnamec,"XXX",bd)
+		replace(fnameh,"ZZZ",tc)
+		replace(fnameh,"YYY",tf)
+		replace(fnameh,"XXX",bd)
+		os.system("g++ -O3 -c "+fnamec)
+
+replace("arch.h","@WL@","16")
+print("Elliptic Curves")
+print("1. ED25519")
+print("2. NUMS256E")
+
+print("Pairing-Friendly Elliptic Curves")
+print("3. BN254")
+print("4. BN254CX")
+
+print("RSA")
+print("5. RSA2048")
+
+
+selection=[]
+ptr=0
+max=6
+
+curve_selected=False
+pfcurve_selected=False
+rsa_selected=False
+
+while ptr<max:
+	x=int(input("Choose a Scheme to support - 0 to finish: "))
+	if x == 0:
+		break
+#	print("Choice= ",x)
+	already=False
+	for i in range(0,ptr):
+		if x==selection[i]:
+			already=True
+			break
+	if already:
+		continue
+	
+	selection.append(x)
+	ptr=ptr+1
+
+# curveset(big,field,curve,big_length_bytes,bits_in_base,modulus_bits,modulus_mod_8,modulus_type,curve_type,pairing_friendly)
+# for each curve give names for big, field and curve. In many cases the latter two will be the same. 
+# Typically "big" is the size in bits, always a multiple of 8, "field" describes the modulus, and "curve" is the common name for the elliptic curve   
+# big_length_bytes is "big" divided by 8
+# Next give the number base used for 16 bit architectures, as n where the base is 2^n (note that these must be fixed for the same "big" name, if is ever re-used for another curve)
+# modulus_bits is the bit length of the modulus, typically the same or slightly smaller than "big"
+# modulus_mod_8 is the remainder when the modulus is divided by 8
+# modulus_type is NOT_SPECIAL, or PSEUDO_MERSENNE, or MONTGOMERY_Friendly, or GENERALISED_MERSENNE (supported for GOLDILOCKS only)
+# curve_type is WEIERSTRASS, EDWARDS or MONTGOMERY
+# pairing_friendly is BN, BLS or NOT (if not pairing friendly)
+# if pairing friendly. M or D type twist, and sign of the family parameter x
+
+
+	if x==1:
+		curveset("256","F25519","ED25519","32","13","255","5","PSEUDO_MERSENNE","EDWARDS","NOT","","","128")
+		curve_selected=True
+	if x==2:
+		curveset("256","F256PME","NUMS256E","32","13","256","3","PSEUDO_MERSENNE","EDWARDS","NOT","","","128")
+		curve_selected=True
+
+
+	if x==3:
+		curveset("256","BN254","BN254","32","13","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+	if x==4:
+		curveset("256","BN254CX","BN254CX","32","13","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+
+# rsaset(big,ring,big_length_bytes,bits_in_base,multiplier)
+# for each choice give distinct names for "big" and "ring".
+# Typically "big" is the length in bits of the underlying big number type
+# "ring" is the RSA modulus size = "big" times 2^m
+# big_length_bytes is "big" divided by 8
+# Next give the number base used for 16 bit architectures, as n where the base is 2^n
+# multiplier is 2^m (see above)
+
+# There are choices here, different ways of getting the same result, but some faster than others
+	if x==5:
+		#256 is slower but may allow reuse of 256-bit BIGs used for elliptic curve
+		#512 is faster.. but best is 1024
+		rsaset("256","RSA2048","32","13","8")
+		rsa_selected=True
+
+
+os.system(deltext+" big.*")
+os.system(deltext+" fp.*")
+os.system(deltext+" ecp.*")
+os.system(deltext+" ecdh.*")
+os.system(deltext+" ff.*")
+os.system(deltext+" rsa.*")
+os.system(deltext+" config_big.h")
+os.system(deltext+" config_field.h")
+os.system(deltext+" config_curve.h")
+os.system(deltext+" config_ff.h")
+os.system(deltext+" fp2.*")
+os.system(deltext+" fp4.*")
+os.system(deltext+" fp12.*")
+os.system(deltext+" ecp2.*")
+os.system(deltext+" pair.*")
+os.system(deltext+" mpin.*")
+
+# create library
+os.system("g++ -O3 -c randapi.cpp")
+if curve_selected :
+	os.system("g++ -O3 -c ecdh_support.cpp")
+if rsa_selected :
+	os.system("g++ -O3 -c rsa_support.cpp")
+if pfcurve_selected :
+	os.system("g++ -O3 -c pbc_support.cpp")
+
+os.system("g++ -O3 -c hash.cpp")
+os.system("g++ -O3 -c rand.cpp")
+os.system("g++ -O3 -c oct.cpp")
+os.system("g++ -O3 -c aes.cpp")
+os.system("g++ -O3 -c gcm.cpp")
+os.system("g++ -O3 -c newhope.cpp")
+
+if sys.platform.startswith("win") :
+	os.system("for %i in (*.o) do @echo %~nxi >> f.list")
+	os.system("ar rc amcl.a @f.list")
+	os.system(deltext+" f.list")
+
+else :
+	os.system("ar rc amcl.a *.o")
+
+os.system(deltext+" *.o")
+
+
+#print("Your section was ")
+#for i in range(0,ptr):
+#	print (selection[i])
+
diff --git a/version3/cpp/config32.py b/version3/cpp/config32.py
new file mode 100644
index 0000000..b2ab9b0
--- /dev/null
+++ b/version3/cpp/config32.py
@@ -0,0 +1,641 @@
+import os
+import sys
+
+deltext=""
+if sys.platform.startswith("linux")  :
+	deltext="rm"
+	copytext="cp"
+if sys.platform.startswith("darwin")  :
+	deltext="rm"
+	copytext="cp"
+if sys.platform.startswith("win") :
+	deltext="del"
+	copytext="copy"
+
+def replace(namefile,oldtext,newtext):
+	f = open(namefile,'r')
+	filedata = f.read()
+	f.close()
+
+	newdata = filedata.replace(oldtext,newtext)
+
+	f = open(namefile,'w')
+	f.write(newdata)
+	f.close()
+
+
+def rsaset(tb,tff,nb,base,ml) :
+	bd="B"+tb+"_"+base
+	fnameh="config_big_"+bd+".h"
+	os.system(copytext+" config_big.h "+fnameh)
+	replace(fnameh,"XXX",bd)
+	replace(fnameh,"@NB@",nb)
+	replace(fnameh,"@BASE@",base)
+
+	fnameh="config_ff_"+tff+".h"
+	os.system(copytext+" config_ff.h "+fnameh)
+	replace(fnameh,"XXX",bd)
+	replace(fnameh,"WWW",tff)
+	replace(fnameh,"@ML@",ml)
+
+	fnamec="big_"+bd+".cpp"
+	fnameh="big_"+bd+".h"
+
+	os.system(copytext+" big.cpp "+fnamec)
+	os.system(copytext+" big.h "+fnameh)
+
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"XXX",bd)
+	os.system("g++ -O3 -c "+fnamec)
+
+	fnamec="ff_"+tff+".cpp"
+	fnameh="ff_"+tff+".h"
+
+	os.system(copytext+" ff.cpp "+fnamec)
+	os.system(copytext+" ff.h "+fnameh)
+
+	replace(fnamec,"WWW",tff)
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"WWW",tff)
+	replace(fnameh,"XXX",bd)
+	os.system("g++ -O3 -c "+fnamec)
+
+	fnamec="rsa_"+tff+".cpp"
+	fnameh="rsa_"+tff+".h"
+
+	os.system(copytext+" rsa.cpp "+fnamec)
+	os.system(copytext+" rsa.h "+fnameh)
+
+	replace(fnamec,"WWW",tff)
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"WWW",tff)
+	replace(fnameh,"XXX",bd)
+	os.system("g++ -O3 -c "+fnamec)
+
+def curveset(tb,tf,tc,nb,base,nbt,m8,mt,ct,pf,stw,sx,cs) :
+	bd="B"+tb+"_"+base
+	fnameh="config_big_"+bd+".h"
+	os.system(copytext+" config_big.h "+fnameh)
+	replace(fnameh,"XXX",bd)
+	replace(fnameh,"@NB@",nb)
+	replace(fnameh,"@BASE@",base)
+
+	fnameh="config_field_"+tf+".h"
+	os.system(copytext+" config_field.h "+fnameh)
+	replace(fnameh,"XXX",bd)
+	replace(fnameh,"YYY",tf)
+	replace(fnameh,"@NBT@",nbt)
+	replace(fnameh,"@M8@",m8)
+	replace(fnameh,"@MT@",mt)
+
+	ib=int(base)
+	inb=int(nb)
+	inbt=int(nbt)
+	sh=ib*(1+((8*inb-1)//ib))-inbt
+
+	if sh > 14 :
+		sh=14
+	replace(fnameh,"@SH@",str(sh))
+
+	fnameh="config_curve_"+tc+".h"	
+	os.system(copytext+" config_curve.h "+fnameh)
+	replace(fnameh,"XXX",bd)
+	replace(fnameh,"YYY",tf)
+	replace(fnameh,"ZZZ",tc)
+	replace(fnameh,"@CT@",ct)
+	replace(fnameh,"@PF@",pf)
+
+	replace(fnameh,"@ST@",stw)
+	replace(fnameh,"@SX@",sx)
+	replace(fnameh,"@CS@",cs)
+
+	fnamec="big_"+bd+".cpp"
+	fnameh="big_"+bd+".h"
+
+	os.system(copytext+" big.cpp "+fnamec)
+	os.system(copytext+" big.h "+fnameh)
+
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"XXX",bd)
+	os.system("g++ -O3 -c "+fnamec)
+
+	fnamec="fp_"+tf+".cpp"
+	fnameh="fp_"+tf+".h"
+
+	os.system(copytext+" fp.cpp "+fnamec)
+	os.system(copytext+" fp.h "+fnameh)
+
+	replace(fnamec,"YYY",tf)
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"YYY",tf)
+	replace(fnameh,"XXX",bd)
+	os.system("g++ -O3 -c "+fnamec)
+
+	os.system("g++ -O3 -c rom_field_"+tf+".cpp")
+
+	fnamec="ecp_"+tc+".cpp"
+	fnameh="ecp_"+tc+".h"
+
+	os.system(copytext+" ecp.cpp "+fnamec)
+	os.system(copytext+" ecp.h "+fnameh)
+
+	replace(fnamec,"ZZZ",tc)
+	replace(fnamec,"YYY",tf)
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"ZZZ",tc)
+	replace(fnameh,"YYY",tf)
+	replace(fnameh,"XXX",bd)
+	os.system("g++ -O3 -c "+fnamec)
+
+	fnamec="ecdh_"+tc+".cpp"
+	fnameh="ecdh_"+tc+".h"
+
+	os.system(copytext+" ecdh.cpp "+fnamec)
+	os.system(copytext+" ecdh.h "+fnameh)
+
+	replace(fnamec,"ZZZ",tc)
+	replace(fnamec,"YYY",tf)
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"ZZZ",tc)
+	replace(fnameh,"YYY",tf)
+	replace(fnameh,"XXX",bd)
+	os.system("g++ -O3 -c "+fnamec)
+
+	os.system("g++ -O3 -c rom_curve_"+tc+".cpp")
+
+	if pf != "NOT" :
+		fnamec="fp2_"+tf+".cpp"
+		fnameh="fp2_"+tf+".h"
+
+		os.system(copytext+" fp2.cpp "+fnamec)
+		os.system(copytext+" fp2.h "+fnameh)
+		replace(fnamec,"YYY",tf)
+		replace(fnamec,"XXX",bd)
+		replace(fnameh,"YYY",tf)
+		replace(fnameh,"XXX",bd)
+		os.system("g++ -O3 -c "+fnamec)
+
+		fnamec="fp4_"+tf+".cpp"
+		fnameh="fp4_"+tf+".h"
+
+		os.system(copytext+" fp4.cpp "+fnamec)
+		os.system(copytext+" fp4.h "+fnameh)
+		replace(fnamec,"YYY",tf)
+		replace(fnamec,"XXX",bd)
+		replace(fnamec,"ZZZ",tc)
+		replace(fnameh,"YYY",tf)
+		replace(fnameh,"XXX",bd)
+		replace(fnameh,"ZZZ",tc)
+		os.system("g++ -O3 -c "+fnamec)
+
+		if cs == "128" :
+			fnamec="fp12_"+tf+".cpp"
+			fnameh="fp12_"+tf+".h"
+
+			os.system(copytext+" fp12.cpp "+fnamec)
+			os.system(copytext+" fp12.h "+fnameh)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("g++ -O3 -c "+fnamec)
+
+			fnamec="ecp2_"+tc+".cpp"
+			fnameh="ecp2_"+tc+".h"
+
+			os.system(copytext+" ecp2.cpp "+fnamec)
+			os.system(copytext+" ecp2.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("g++ -O3 -c "+fnamec)
+
+			fnamec="pair_"+tc+".cpp"
+			fnameh="pair_"+tc+".h"
+
+			os.system(copytext+" pair.cpp "+fnamec)
+			os.system(copytext+" pair.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("g++ -O3 -c "+fnamec)
+
+			fnamec="mpin_"+tc+".cpp"
+			fnameh="mpin_"+tc+".h"
+
+			os.system(copytext+" mpin.cpp "+fnamec)
+			os.system(copytext+" mpin.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("g++ -O3 -c "+fnamec)
+
+		if cs == "192" :
+			fnamec="fp8_"+tf+".cpp"
+			fnameh="fp8_"+tf+".h"
+
+			os.system(copytext+" fp8.cpp "+fnamec)
+			os.system(copytext+" fp8.h "+fnameh)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			os.system("g++ -O3 -c "+fnamec)
+
+
+			fnamec="fp24_"+tf+".cpp"
+			fnameh="fp24_"+tf+".h"
+
+			os.system(copytext+" fp24.cpp "+fnamec)
+			os.system(copytext+" fp24.h "+fnameh)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("g++ -O3 -c "+fnamec)
+
+			fnamec="ecp4_"+tc+".cpp"
+			fnameh="ecp4_"+tc+".h"
+
+			os.system(copytext+" ecp4.cpp "+fnamec)
+			os.system(copytext+" ecp4.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("g++ -O3 -c "+fnamec)
+
+			fnamec="pair192_"+tc+".cpp"
+			fnameh="pair192_"+tc+".h"
+
+			os.system(copytext+" pair192.cpp "+fnamec)
+			os.system(copytext+" pair192.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("g++ -O3 -c "+fnamec)
+
+			fnamec="mpin192_"+tc+".cpp"
+			fnameh="mpin192_"+tc+".h"
+
+			os.system(copytext+" mpin192.cpp "+fnamec)
+			os.system(copytext+" mpin192.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("g++ -O3 -c "+fnamec)
+
+		if cs == "256" :
+
+			fnamec="fp8_"+tf+".cpp"
+			fnameh="fp8_"+tf+".h"
+
+			os.system(copytext+" fp8.cpp "+fnamec)
+			os.system(copytext+" fp8.h "+fnameh)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			os.system("g++ -O3 -c "+fnamec)
+
+
+			fnamec="ecp8_"+tc+".cpp"
+			fnameh="ecp8_"+tc+".h"
+
+			os.system(copytext+" ecp8.cpp "+fnamec)
+			os.system(copytext+" ecp8.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("g++ -O3 -c "+fnamec)
+
+
+			fnamec="fp16_"+tf+".cpp"
+			fnameh="fp16_"+tf+".h"
+
+			os.system(copytext+" fp16.cpp "+fnamec)
+			os.system(copytext+" fp16.h "+fnameh)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			os.system("g++ -O3 -c "+fnamec)
+
+
+			fnamec="fp48_"+tf+".cpp"
+			fnameh="fp48_"+tf+".h"
+
+			os.system(copytext+" fp48.cpp "+fnamec)
+			os.system(copytext+" fp48.h "+fnameh)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("g++ -O3 -c "+fnamec)
+
+
+			fnamec="pair256_"+tc+".cpp"
+			fnameh="pair256_"+tc+".h"
+
+			os.system(copytext+" pair256.cpp "+fnamec)
+			os.system(copytext+" pair256.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("g++ -O3 -c "+fnamec)
+
+			fnamec="mpin256_"+tc+".cpp"
+			fnameh="mpin256_"+tc+".h"
+
+			os.system(copytext+" mpin256.cpp "+fnamec)
+			os.system(copytext+" mpin256.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("g++ -O3 -c "+fnamec)
+
+replace("arch.h","@WL@","32")
+print("Elliptic Curves")
+print("1. ED25519")
+print("2. C25519")
+print("3. NIST256")
+print("4. BRAINPOOL")
+print("5. ANSSI")
+print("6. HIFIVE")
+print("7. GOLDILOCKS")
+print("8. NIST384")
+print("9. C41417")
+print("10. NIST521\n")
+print("11. NUMS256W")
+print("12. NUMS256E")
+print("13. NUMS384W")
+print("14. NUMS384E")
+print("15. NUMS512W")
+print("16. NUMS512E")
+print("17. SECP256K1\n")
+
+print("Pairing-Friendly Elliptic Curves")
+print("18. BN254")
+print("19. BN254CX")
+print("20. BLS383")
+print("21. BLS381")
+print("22. FP256BN")
+print("23. FP512BN")
+print("24. BLS461\n")
+print("25. BLS24")
+print("26. BLS48\n")
+
+print("RSA")
+print("27. RSA2048")
+print("28. RSA3072")
+print("29. RSA4096")
+
+selection=[]
+ptr=0
+max=30
+
+
+curve_selected=False
+pfcurve_selected=False
+rsa_selected=False
+
+while ptr<max:
+	x=int(input("Choose a Scheme to support - 0 to finish: "))
+	if x == 0:
+		break
+#	print("Choice= ",x)
+	already=False
+	for i in range(0,ptr):
+		if x==selection[i]:
+			already=True
+			break
+	if already:
+		continue
+	
+	selection.append(x)
+	ptr=ptr+1
+
+# curveset(big,field,curve,big_length_bytes,bits_in_base,modulus_bits,modulus_mod_8,modulus_type,curve_type,pairing_friendly,sextic twist,sign of x,curve security)
+# for each curve give names for big, field and curve. In many cases the latter two will be the same. 
+# Typically "big" is the size in bits, always a multiple of 8, "field" describes the modulus, and "curve" is the common name for the elliptic curve   
+# big_length_bytes is "big" divided by 8
+# Next give the number base used for 32 bit architecture, as n where the base is 2^n (note that these must be fixed for the same "big" name, if is ever re-used for another curve)
+# modulus_bits is the bit length of the modulus, typically the same or slightly smaller than "big"
+# modulus_mod_8 is the remainder when the modulus is divided by 8
+# modulus_type is NOT_SPECIAL, or PSEUDO_MERSENNE, or MONTGOMERY_Friendly, or GENERALISED_MERSENNE (supported for GOLDILOCKS only)
+# curve_type is WEIERSTRASS, EDWARDS or MONTGOMERY
+# pairing_friendly is BN, BLS or NOT (if not pairing friendly)
+# if pairing friendly. M or D type twist, and sign of the family parameter x
+# curve security is AES equiavlent, rounded up.
+
+	if x==1:
+		curveset("256","F25519","ED25519","32","29","255","5","PSEUDO_MERSENNE","EDWARDS","NOT","","","128")
+		curve_selected=True
+	if x==2:
+		curveset("256","F25519","C25519","32","29","255","5","PSEUDO_MERSENNE","MONTGOMERY","NOT","","","128")
+		curve_selected=True
+	if x==3:
+		curveset("256","NIST256","NIST256","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","128")
+		curve_selected=True
+	if x==4:
+		curveset("256","BRAINPOOL","BRAINPOOL","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","128")
+		curve_selected=True
+	if x==5:
+		curveset("256","ANSSI","ANSSI","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","128")
+		curve_selected=True
+
+	if x==6:
+		curveset("336","HIFIVE","HIFIVE","42","29","336","5","PSEUDO_MERSENNE","EDWARDS","NOT","","","192")
+		curve_selected=True
+	if x==7:
+		curveset("448","GOLDILOCKS","GOLDILOCKS","56","29","448","7","GENERALISED_MERSENNE","EDWARDS","NOT","","","256")
+		curve_selected=True
+	if x==8:
+		curveset("384","NIST384","NIST384","48","29","384","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","192")
+		curve_selected=True
+	if x==9:
+		curveset("416","C41417","C41417","52","29","414","7","PSEUDO_MERSENNE","EDWARDS","NOT","","","256")
+		curve_selected=True
+	if x==10:
+		curveset("528","NIST521","NIST521","66","28","521","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","256")
+		curve_selected=True
+
+	if x==11:
+		curveset("256","F256PMW","NUMS256W","32","28","256","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","128")
+		curve_selected=True
+	if x==12:
+		curveset("256","F256PME","NUMS256E","32","29","256","3","PSEUDO_MERSENNE","EDWARDS","NOT","","","128")
+		curve_selected=True
+	if x==13:
+		curveset("384","F384PM","NUMS384W","48","29","384","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","192")
+		curve_selected=True
+	if x==14:
+		curveset("384","F384PM","NUMS384E","48","29","384","3","PSEUDO_MERSENNE","EDWARDS","NOT","","","192")
+		curve_selected=True
+	if x==15:
+		curveset("512","F512PM","NUMS512W","64","29","512","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","256")
+		curve_selected=True
+	if x==16:
+		curveset("512","F512PM","NUMS512E","64","29","512","7","PSEUDO_MERSENNE","EDWARDS","NOT","","","256")
+		curve_selected=True
+
+	if x==17:
+		curveset("256","SECP256K1","SECP256K1","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","128")
+		curve_selected=True
+
+	if x==18:
+		curveset("256","BN254","BN254","32","28","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+	if x==19:
+		curveset("256","BN254CX","BN254CX","32","28","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+	if x==20:
+		curveset("384","BLS383","BLS383","48","29","383","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","128")
+		pfcurve_selected=True
+
+	if x==21:
+		curveset("384","BLS381","BLS381","48","29","381","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+
+
+	if x==22:
+		curveset("256","FP256BN","FP256BN","32","28","256","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+	if x==23:
+		curveset("512","FP512BN","FP512BN","64","29","512","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","POSITIVEX","128")
+		pfcurve_selected=True
+# https://eprint.iacr.org/2017/334.pdf
+	if x==24:
+		curveset("464","BLS461","BLS461","58","28","461","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+
+	if x==25:
+		curveset("480","BLS24","BLS24","60","29","479","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","192")
+		pfcurve_selected=True
+
+
+	if x==26:
+		curveset("560","BLS48","BLS48","70","29","556","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","256")
+		pfcurve_selected=True
+
+
+# rsaset(big,ring,big_length_bytes,bit_bits_in_base,multiplier)
+# for each choice give distinct names for "big" and "ring".
+# Typically "big" is the length in bits of the underlying big number type
+# "ring" is the RSA modulus size = "big" times 2^m
+# big_length_bytes is "big" divided by 8
+# Next give the number base used for 32 bit architectures, as n where the base is 2^n
+# multiplier is 2^m (see above)
+
+# There are choices here, different ways of getting the same result, but some faster than others
+	if x==27:
+		#256 is slower but may allow reuse of 256-bit BIGs used for elliptic curve
+		#512 is faster.. but best is 1024
+		rsaset("1024","RSA2048","128","28","2")
+		#rsaset("512","RSA2048","64","29","4")
+		#rsaset("256","RSA2048","32","29","8")
+		rsa_selected=True
+	if x==28:
+		rsaset("384","RSA3072","48","28","8")
+		rsa_selected=True
+	if x==29:
+		#rsaset("256","RSA4096","32","29","16")
+		rsaset("512","RSA4096","64","29","8")
+		rsa_selected=True
+
+
+os.system(deltext+" big.*")
+os.system(deltext+" fp.*")
+os.system(deltext+" ecp.*")
+os.system(deltext+" ecdh.*")
+os.system(deltext+" ff.*")
+os.system(deltext+" rsa.*")
+os.system(deltext+" config_big.h")
+os.system(deltext+" config_field.h")
+os.system(deltext+" config_curve.h")
+os.system(deltext+" config_ff.h")
+os.system(deltext+" fp2.*")
+os.system(deltext+" fp4.*")
+os.system(deltext+" fp8.*")
+os.system(deltext+" fp16.*")
+
+os.system(deltext+" fp12.*")
+os.system(deltext+" fp24.*")
+os.system(deltext+" fp48.*")
+
+os.system(deltext+" ecp2.*")
+os.system(deltext+" ecp4.*")
+os.system(deltext+" ecp8.*")
+
+os.system(deltext+" pair.*")
+os.system(deltext+" mpin.*")
+
+os.system(deltext+" pair192.*")
+os.system(deltext+" mpin192.*")
+
+os.system(deltext+" pair256.*")
+os.system(deltext+" mpin256.*")
+
+# create library
+os.system("g++ -O3 -c randapi.cpp")
+if curve_selected :
+	os.system("g++ -O3 -c ecdh_support.cpp")
+if rsa_selected :
+	os.system("g++ -O3 -c rsa_support.cpp")
+if pfcurve_selected :
+	os.system("g++ -O3 -c pbc_support.cpp")
+
+os.system("g++ -O3 -c hash.cpp")
+os.system("g++ -O3 -c rand.cpp")
+os.system("g++ -O3 -c oct.cpp")
+os.system("g++ -O3 -c aes.cpp")
+os.system("g++ -O3 -c gcm.cpp")
+os.system("g++ -O3 -c newhope.cpp")
+
+if sys.platform.startswith("win") :
+	os.system("for %i in (*.o) do @echo %~nxi >> f.list")
+	os.system("ar rc amcl.a @f.list")
+	os.system(deltext+" f.list")
+
+else :
+	os.system("ar rc amcl.a *.o")
+
+os.system(deltext+" *.o")
+
+
+#print("Your section was ")
+#for i in range(0,ptr):
+#	print (selection[i])
+
diff --git a/version3/cpp/config64.py b/version3/cpp/config64.py
new file mode 100644
index 0000000..faa6a90
--- /dev/null
+++ b/version3/cpp/config64.py
@@ -0,0 +1,641 @@
+import os
+import sys
+
+deltext=""
+if sys.platform.startswith("linux")  :
+	deltext="rm"
+	copytext="cp"
+if sys.platform.startswith("darwin")  :
+	deltext="rm"
+	copytext="cp"
+if sys.platform.startswith("win") :
+	deltext="del"
+	copytext="copy"
+
+def replace(namefile,oldtext,newtext):
+	f = open(namefile,'r')
+	filedata = f.read()
+	f.close()
+
+	newdata = filedata.replace(oldtext,newtext)
+
+	f = open(namefile,'w')
+	f.write(newdata)
+	f.close()
+
+
+def rsaset(tb,tff,nb,base,ml) :
+	bd="B"+tb+"_"+base
+	fnameh="config_big_"+bd+".h"
+	os.system(copytext+" config_big.h "+fnameh)
+	replace(fnameh,"XXX",bd)
+	replace(fnameh,"@NB@",nb)
+	replace(fnameh,"@BASE@",base)
+
+	fnameh="config_ff_"+tff+".h"
+	os.system(copytext+" config_ff.h "+fnameh)
+	replace(fnameh,"XXX",bd)
+	replace(fnameh,"WWW",tff)
+	replace(fnameh,"@ML@",ml)
+
+	fnamec="big_"+bd+".cpp"
+	fnameh="big_"+bd+".h"
+
+	os.system(copytext+" big.cpp "+fnamec)
+	os.system(copytext+" big.h "+fnameh)
+
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"XXX",bd)
+	os.system("g++ -O3 -c "+fnamec)
+
+	fnamec="ff_"+tff+".cpp"
+	fnameh="ff_"+tff+".h"
+
+	os.system(copytext+" ff.cpp "+fnamec)
+	os.system(copytext+" ff.h "+fnameh)
+
+	replace(fnamec,"WWW",tff)
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"WWW",tff)
+	replace(fnameh,"XXX",bd)
+	os.system("g++ -O3 -c "+fnamec)
+
+	fnamec="rsa_"+tff+".cpp"
+	fnameh="rsa_"+tff+".h"
+
+	os.system(copytext+" rsa.cpp "+fnamec)
+	os.system(copytext+" rsa.h "+fnameh)
+
+	replace(fnamec,"WWW",tff)
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"WWW",tff)
+	replace(fnameh,"XXX",bd)
+	os.system("g++ -O3 -c "+fnamec)
+
+def curveset(tb,tf,tc,nb,base,nbt,m8,mt,ct,pf,stw,sx,cs) :
+	bd="B"+tb+"_"+base
+	fnameh="config_big_"+bd+".h"
+	os.system(copytext+" config_big.h "+fnameh)
+	replace(fnameh,"XXX",bd)
+	replace(fnameh,"@NB@",nb)
+	replace(fnameh,"@BASE@",base)
+
+	fnameh="config_field_"+tf+".h"
+	os.system(copytext+" config_field.h "+fnameh)
+	replace(fnameh,"XXX",bd)
+	replace(fnameh,"YYY",tf)
+	replace(fnameh,"@NBT@",nbt)
+	replace(fnameh,"@M8@",m8)
+	replace(fnameh,"@MT@",mt)
+
+	ib=int(base)
+	inb=int(nb)
+	inbt=int(nbt)
+	sh=ib*(1+((8*inb-1)//ib))-inbt
+
+	if sh > 30 :
+		sh=30
+	replace(fnameh,"@SH@",str(sh))
+
+	fnameh="config_curve_"+tc+".h"	
+	os.system(copytext+" config_curve.h "+fnameh)
+	replace(fnameh,"XXX",bd)
+	replace(fnameh,"YYY",tf)
+	replace(fnameh,"ZZZ",tc)
+	replace(fnameh,"@CT@",ct)
+	replace(fnameh,"@PF@",pf)
+
+	replace(fnameh,"@ST@",stw)
+	replace(fnameh,"@SX@",sx)
+	replace(fnameh,"@CS@",cs)
+
+
+	fnamec="big_"+bd+".cpp"
+	fnameh="big_"+bd+".h"
+
+	os.system(copytext+" big.cpp "+fnamec)
+	os.system(copytext+" big.h "+fnameh)
+
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"XXX",bd)
+	os.system("g++ -O3 -c "+fnamec)
+
+	fnamec="fp_"+tf+".cpp"
+	fnameh="fp_"+tf+".h"
+
+	os.system(copytext+" fp.cpp "+fnamec)
+	os.system(copytext+" fp.h "+fnameh)
+
+	replace(fnamec,"YYY",tf)
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"YYY",tf)
+	replace(fnameh,"XXX",bd)
+	os.system("g++ -O3 -c "+fnamec)
+
+	os.system("g++ -O3 -c rom_field_"+tf+".cpp")
+
+	fnamec="ecp_"+tc+".cpp"
+	fnameh="ecp_"+tc+".h"
+
+	os.system(copytext+" ecp.cpp "+fnamec)
+	os.system(copytext+" ecp.h "+fnameh)
+
+	replace(fnamec,"ZZZ",tc)
+	replace(fnamec,"YYY",tf)
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"ZZZ",tc)
+	replace(fnameh,"YYY",tf)
+	replace(fnameh,"XXX",bd)
+	os.system("g++ -O3 -c "+fnamec)
+
+	fnamec="ecdh_"+tc+".cpp"
+	fnameh="ecdh_"+tc+".h"
+
+	os.system(copytext+" ecdh.cpp "+fnamec)
+	os.system(copytext+" ecdh.h "+fnameh)
+
+	replace(fnamec,"ZZZ",tc)
+	replace(fnamec,"YYY",tf)
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"ZZZ",tc)
+	replace(fnameh,"YYY",tf)
+	replace(fnameh,"XXX",bd)
+	os.system("g++ -O3 -c "+fnamec)
+
+	os.system("g++ -O3 -c rom_curve_"+tc+".cpp")
+
+	if pf != "NOT" :
+		fnamec="fp2_"+tf+".cpp"
+		fnameh="fp2_"+tf+".h"
+
+		os.system(copytext+" fp2.cpp "+fnamec)
+		os.system(copytext+" fp2.h "+fnameh)
+		replace(fnamec,"YYY",tf)
+		replace(fnamec,"XXX",bd)
+		replace(fnameh,"YYY",tf)
+		replace(fnameh,"XXX",bd)
+		os.system("g++ -O3 -c "+fnamec)
+
+		fnamec="fp4_"+tf+".cpp"
+		fnameh="fp4_"+tf+".h"
+
+		os.system(copytext+" fp4.cpp "+fnamec)
+		os.system(copytext+" fp4.h "+fnameh)
+		replace(fnamec,"YYY",tf)
+		replace(fnamec,"XXX",bd)
+		replace(fnamec,"ZZZ",tc)
+		replace(fnameh,"YYY",tf)
+		replace(fnameh,"XXX",bd)
+		replace(fnameh,"ZZZ",tc)
+		os.system("g++ -O3 -c "+fnamec)
+
+		if cs == "128" :
+			fnamec="fp12_"+tf+".cpp"
+			fnameh="fp12_"+tf+".h"
+
+			os.system(copytext+" fp12.cpp "+fnamec)
+			os.system(copytext+" fp12.h "+fnameh)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("g++ -O3 -c "+fnamec)
+
+			fnamec="ecp2_"+tc+".cpp"
+			fnameh="ecp2_"+tc+".h"
+
+			os.system(copytext+" ecp2.cpp "+fnamec)
+			os.system(copytext+" ecp2.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("g++ -O3 -c "+fnamec)
+
+			fnamec="pair_"+tc+".cpp"
+			fnameh="pair_"+tc+".h"
+
+			os.system(copytext+" pair.cpp "+fnamec)
+			os.system(copytext+" pair.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("g++ -O3 -c "+fnamec)
+
+			fnamec="mpin_"+tc+".cpp"
+			fnameh="mpin_"+tc+".h"
+
+			os.system(copytext+" mpin.cpp "+fnamec)
+			os.system(copytext+" mpin.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("g++ -O3 -c "+fnamec)
+
+		if cs == "192" :
+			fnamec="fp8_"+tf+".cpp"
+			fnameh="fp8_"+tf+".h"
+
+			os.system(copytext+" fp8.cpp "+fnamec)
+			os.system(copytext+" fp8.h "+fnameh)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			os.system("g++ -O3 -c "+fnamec)
+
+
+			fnamec="fp24_"+tf+".cpp"
+			fnameh="fp24_"+tf+".h"
+
+			os.system(copytext+" fp24.cpp "+fnamec)
+			os.system(copytext+" fp24.h "+fnameh)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("g++ -O3 -c "+fnamec)
+
+			fnamec="ecp4_"+tc+".cpp"
+			fnameh="ecp4_"+tc+".h"
+
+			os.system(copytext+" ecp4.cpp "+fnamec)
+			os.system(copytext+" ecp4.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("g++ -O3 -c "+fnamec)
+
+			fnamec="pair192_"+tc+".cpp"
+			fnameh="pair192_"+tc+".h"
+
+			os.system(copytext+" pair192.cpp "+fnamec)
+			os.system(copytext+" pair192.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("g++ -O3 -c "+fnamec)
+
+			fnamec="mpin192_"+tc+".cpp"
+			fnameh="mpin192_"+tc+".h"
+
+			os.system(copytext+" mpin192.cpp "+fnamec)
+			os.system(copytext+" mpin192.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("g++ -O3 -c "+fnamec)
+
+		if cs == "256" :
+
+			fnamec="fp8_"+tf+".cpp"
+			fnameh="fp8_"+tf+".h"
+
+			os.system(copytext+" fp8.cpp "+fnamec)
+			os.system(copytext+" fp8.h "+fnameh)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			os.system("g++ -O3 -c "+fnamec)
+
+
+			fnamec="ecp8_"+tc+".cpp"
+			fnameh="ecp8_"+tc+".h"
+
+			os.system(copytext+" ecp8.cpp "+fnamec)
+			os.system(copytext+" ecp8.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("g++ -O3 -c "+fnamec)
+
+
+			fnamec="fp16_"+tf+".cpp"
+			fnameh="fp16_"+tf+".h"
+
+			os.system(copytext+" fp16.cpp "+fnamec)
+			os.system(copytext+" fp16.h "+fnameh)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			os.system("g++ -O3 -c "+fnamec)
+
+
+			fnamec="fp48_"+tf+".cpp"
+			fnameh="fp48_"+tf+".h"
+
+			os.system(copytext+" fp48.cpp "+fnamec)
+			os.system(copytext+" fp48.h "+fnameh)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("g++ -O3 -c "+fnamec)
+
+
+			fnamec="pair256_"+tc+".cpp"
+			fnameh="pair256_"+tc+".h"
+
+			os.system(copytext+" pair256.cpp "+fnamec)
+			os.system(copytext+" pair256.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("g++ -O3 -c "+fnamec)
+
+			fnamec="mpin256_"+tc+".cpp"
+			fnameh="mpin256_"+tc+".h"
+
+			os.system(copytext+" mpin256.cpp "+fnamec)
+			os.system(copytext+" mpin256.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("g++ -O3 -c "+fnamec)
+
+replace("arch.h","@WL@","64")
+print("Elliptic Curves")
+print("1. ED25519")
+print("2. C25519")
+print("3. NIST256")
+print("4. BRAINPOOL")
+print("5. ANSSI")
+print("6. HIFIVE")
+print("7. GOLDILOCKS")
+print("8. NIST384")
+print("9. C41417")
+print("10. NIST521\n")
+print("11. NUMS256W")
+print("12. NUMS256E")
+print("13. NUMS384W")
+print("14. NUMS384E")
+print("15. NUMS512W")
+print("16. NUMS512E")
+print("17. SECP256K1\n")
+
+print("Pairing-Friendly Elliptic Curves")
+print("18. BN254")
+print("19. BN254CX")
+print("20. BLS383")
+print("21. BLS381")
+print("22. FP256BN")
+print("23. FP512BN")
+print("24. BLS461\n")
+print("25. BLS24")
+print("26. BLS48\n")
+
+print("RSA")
+print("27. RSA2048")
+print("28. RSA3072")
+print("29. RSA4096")
+
+selection=[]
+ptr=0
+max=30
+
+curve_selected=False
+pfcurve_selected=False
+rsa_selected=False
+
+while ptr<max:
+	x=int(input("Choose a Scheme to support - 0 to finish: "))
+	if x == 0:
+		break
+#	print("Choice= ",x)
+	already=False
+	for i in range(0,ptr):
+		if x==selection[i]:
+			already=True
+			break
+	if already:
+		continue
+	
+	selection.append(x)
+	ptr=ptr+1
+
+# curveset(big,field,curve,big_length_bytes,bits_in_base,modulus_bits,modulus_mod_8,modulus_type,curve_type,pairing_friendly,sextic twist,sign of x,curve security)
+# for each curve give names for big, field and curve. In many cases the latter two will be the same. 
+# Typically "big" is the size in bits, always a multiple of 8, "field" describes the modulus, and "curve" is the common name for the elliptic curve   
+# big_length_bytes is "big" divided by 8
+# Next give the number base used for 64 bit architectures, as n where the base is 2^n (note that these must be fixed for the same "big" name, if is ever re-used for another curve)
+# modulus_bits is the bit length of the modulus, typically the same or slightly smaller than "big"
+# modulus_mod_8 is the remainder when the modulus is divided by 8
+# modulus_type is NOT_SPECIAL, or PSEUDO_MERSENNE, or MONTGOMERY_Friendly, or GENERALISED_MERSENNE (supported for GOLDILOCKS only)
+# curve_type is WEIERSTRASS, EDWARDS or MONTGOMERY
+# pairing_friendly is BN, BLS or NOT (if not pairing friendly)
+# if pairing friendly. M or D type twist, and sign of the family parameter x
+# curve security is AES equiavlent, rounded up.
+
+
+	if x==1:
+		curveset("256","F25519","ED25519","32","56","255","5","PSEUDO_MERSENNE","EDWARDS","NOT","","","128")
+		curve_selected=True
+	if x==2:
+		curveset("256","F25519","C25519","32","56","255","5","PSEUDO_MERSENNE","MONTGOMERY","NOT","","","128")
+		curve_selected=True
+	if x==3:
+		curveset("256","NIST256","NIST256","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","128")
+		curve_selected=True
+	if x==4:
+		curveset("256","BRAINPOOL","BRAINPOOL","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","128")
+		curve_selected=True
+	if x==5:
+		curveset("256","ANSSI","ANSSI","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","128")
+		curve_selected=True
+
+	if x==6:
+		curveset("336","HIFIVE","HIFIVE","42","60","336","5","PSEUDO_MERSENNE","EDWARDS","NOT","","","192")
+		curve_selected=True
+	if x==7:
+		curveset("448","GOLDILOCKS","GOLDILOCKS","56","58","448","7","GENERALISED_MERSENNE","EDWARDS","NOT","","","256")
+		curve_selected=True
+	if x==8:
+		curveset("384","NIST384","NIST384","48","56","384","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","192")
+		curve_selected=True
+	if x==9:
+		curveset("416","C41417","C41417","52","60","414","7","PSEUDO_MERSENNE","EDWARDS","NOT","","","256")
+		curve_selected=True
+	if x==10:
+		curveset("528","NIST521","NIST521","66","60","521","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","256")
+		curve_selected=True
+
+	if x==11:
+		curveset("256","F256PMW","NUMS256W","32","56","256","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","128")
+		curve_selected=True
+	if x==12:
+		curveset("256","F256PME","NUMS256E","32","56","256","3","PSEUDO_MERSENNE","EDWARDS","NOT","","","128")
+		curve_selected=True
+	if x==13:
+		curveset("384","F384PM","NUMS384W","48","56","384","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","192")
+		curve_selected=True
+	if x==14:
+		curveset("384","F384PM","NUMS384E","48","56","384","3","PSEUDO_MERSENNE","EDWARDS","NOT","","","192")
+		curve_selected=True
+	if x==15:
+		curveset("512","F512PM","NUMS512W","64","56","512","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","256")
+		curve_selected=True
+	if x==16:
+		curveset("512","F512PM","NUMS512E","64","56","512","7","PSEUDO_MERSENNE","EDWARDS","NOT","","","256")
+		curve_selected=True
+
+	if x==17:
+		curveset("256","SECP256K1","SECP256K1","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","128")
+		curve_selected=True
+
+	if x==18:
+		curveset("256","BN254","BN254","32","56","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+	if x==19:
+		curveset("256","BN254CX","BN254CX","32","56","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+	if x==20:
+		curveset("384","BLS383","BLS383","48","58","383","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","128")
+		pfcurve_selected=True
+
+	if x==21:
+		curveset("384","BLS381","BLS381","48","58","381","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+
+	if x==22:
+		curveset("256","FP256BN","FP256BN","32","56","256","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+	if x==23:
+		curveset("512","FP512BN","FP512BN","64","60","512","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","POSITIVEX","128")
+		pfcurve_selected=True
+# https://eprint.iacr.org/2017/334.pdf
+	if x==24:
+		curveset("464","BLS461","BLS461","58","60","461","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+
+	if x==25:
+		curveset("480","BLS24","BLS24","60","56","479","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","192")
+		pfcurve_selected=True
+
+	if x==26:
+		curveset("560","BLS48","BLS48","70","58","556","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","256")
+		pfcurve_selected=True
+
+
+# rsaset(big,ring,big_length_bytes,bits_in_base,multiplier)
+# for each choice give distinct names for "big" and "ring".
+# Typically "big" is the length in bits of the underlying big number type
+# "ring" is the RSA modulus size = "big" times 2^m
+# big_length_bytes is "big" divided by 8
+# Next give the number base used for 64 bit architectures, as n where the base is 2^n
+# multiplier is 2^m (see above)
+
+# There are choices here, different ways of getting the same result, but some faster than others
+	if x==27:
+		#256 is slower but may allow reuse of 256-bit BIGs used for elliptic curve
+		#512 is faster.. but best is 1024
+		rsaset("1024","RSA2048","128","58","2")
+		#rsaset("512","RSA2048","64","60","4")
+		#rsaset("256","RSA2048","32","56","8")
+		rsa_selected=True
+	if x==28:
+		rsaset("384","RSA3072","48","56","8")
+		rsa_selected=True
+	if x==29:
+		#rsaset("256","RSA4096","32","56","16")
+		rsaset("512","RSA4096","64","60","8")
+		rsa_selected=True
+
+
+os.system(deltext+" big.*")
+os.system(deltext+" fp.*")
+os.system(deltext+" ecp.*")
+os.system(deltext+" ecdh.*")
+os.system(deltext+" ff.*")
+os.system(deltext+" rsa.*")
+os.system(deltext+" config_big.h")
+os.system(deltext+" config_field.h")
+os.system(deltext+" config_curve.h")
+os.system(deltext+" config_ff.h")
+os.system(deltext+" fp2.*")
+os.system(deltext+" fp4.*")
+os.system(deltext+" fp8.*")
+os.system(deltext+" fp16.*")
+
+os.system(deltext+" fp12.*")
+os.system(deltext+" fp24.*")
+os.system(deltext+" fp48.*")
+
+os.system(deltext+" ecp2.*")
+os.system(deltext+" ecp4.*")
+os.system(deltext+" ecp8.*")
+
+os.system(deltext+" pair.*")
+os.system(deltext+" mpin.*")
+
+os.system(deltext+" pair192.*")
+os.system(deltext+" mpin192.*")
+
+os.system(deltext+" pair256.*")
+os.system(deltext+" mpin256.*")
+
+
+# create library
+os.system("g++ -O3 -c randapi.cpp")
+if curve_selected :
+	os.system("g++ -O3 -c ecdh_support.cpp")
+if rsa_selected :
+	os.system("g++ -O3 -c rsa_support.cpp")
+if pfcurve_selected :
+	os.system("g++ -O3 -c pbc_support.cpp")
+
+os.system("g++ -O3 -c hash.cpp")
+os.system("g++ -O3 -c rand.cpp")
+os.system("g++ -O3 -c oct.cpp")
+os.system("g++ -O3 -c aes.cpp")
+os.system("g++ -O3 -c gcm.cpp")
+os.system("g++ -O3 -c newhope.cpp")
+
+if sys.platform.startswith("win") :
+	os.system("for %i in (*.o) do @echo %~nxi >> f.list")
+	os.system("ar rc amcl.a @f.list")
+	os.system(deltext+" f.list")
+
+else :
+	os.system("ar rc amcl.a *.o")
+
+os.system(deltext+" *.o")
+
+
+#print("Your section was ")
+#for i in range(0,ptr):
+#	print (selection[i])
+
diff --git a/version3/cpp/config_big.h b/version3/cpp/config_big.h
new file mode 100644
index 0000000..6d12010
--- /dev/null
+++ b/version3/cpp/config_big.h
@@ -0,0 +1,12 @@
+#ifndef CONFIG_BIG_XXX_H
+#define CONFIG_BIG_XXX_H
+
+#include"amcl.h"
+
+// BIG stuff
+
+#define MODBYTES_XXX @NB@  
+#define BASEBITS_XXX @BASE@ 
+
+
+#endif
diff --git a/version3/cpp/config_curve.h b/version3/cpp/config_curve.h
new file mode 100644
index 0000000..4f905d5
--- /dev/null
+++ b/version3/cpp/config_curve.h
@@ -0,0 +1,47 @@
+#ifndef CONFIG_CURVE_ZZZ_H
+#define CONFIG_CURVE_ZZZ_H
+
+#include"amcl.h"
+#include"config_field_YYY.h"
+
+// ECP stuff
+
+#define CURVETYPE_ZZZ @CT@  
+#define PAIRING_FRIENDLY_ZZZ @PF@
+#define CURVE_SECURITY_ZZZ @CS@
+
+#if PAIRING_FRIENDLY_ZZZ != NOT
+#define USE_GLV_ZZZ	  /**< Note this method is patented (GLV), so maybe you want to comment this out */
+#define USE_GS_G2_ZZZ /**< Well we didn't patent it :) But may be covered by GLV patent :( */
+#define USE_GS_GT_ZZZ /**< Not patented, so probably safe to always use this */
+
+#define POSITIVEX 0
+#define NEGATIVEX 1
+
+#define SEXTIC_TWIST_ZZZ @ST@
+#define SIGN_OF_X_ZZZ @SX@ 
+
+#endif
+
+
+#if CURVE_SECURITY_ZZZ == 128
+#define AESKEY_ZZZ 16 /**< Symmetric Key size - 128 bits */
+#define HASH_TYPE_ZZZ SHA256  /**< Hash type */
+#endif
+
+#if CURVE_SECURITY_ZZZ == 192
+#define AESKEY_ZZZ 24 /**< Symmetric Key size - 192 bits */
+#define HASH_TYPE_ZZZ SHA384  /**< Hash type */
+#endif
+
+#if CURVE_SECURITY_ZZZ == 256
+#define AESKEY_ZZZ 32 /**< Symmetric Key size - 256 bits */
+#define HASH_TYPE_ZZZ SHA512  /**< Hash type */
+#endif
+
+
+
+namespace ZZZ_BIG=XXX;
+namespace ZZZ_FP=YYY;
+
+#endif
\ No newline at end of file
diff --git a/version3/cpp/config_ff.h b/version3/cpp/config_ff.h
new file mode 100644
index 0000000..33cb95a
--- /dev/null
+++ b/version3/cpp/config_ff.h
@@ -0,0 +1,13 @@
+#ifndef CONFIG_RSA_WWW_H
+#define CONFIG_RSA_WWW_H
+
+#include "amcl.h"
+#include "config_big_XXX.h"
+
+// FF stuff
+
+#define FFLEN_WWW @ML@ /**< 2^n multiplier of BIGBITS to specify supported Finite Field size, e.g 2048=256*2^3 where BIGBITS=256 */
+
+namespace WWW_BIG=XXX;
+
+#endif
\ No newline at end of file
diff --git a/version3/cpp/config_field.h b/version3/cpp/config_field.h
new file mode 100644
index 0000000..ab86941
--- /dev/null
+++ b/version3/cpp/config_field.h
@@ -0,0 +1,15 @@
+#ifndef CONFIG_FIELD_YYY_H
+#define CONFIG_FIELD_YYY_H
+
+#include"amcl.h"
+#include "config_big_XXX.h"
+
+// FP stuff
+
+#define MBITS_YYY @NBT@	        
+#define MOD8_YYY @M8@	 
+#define MODTYPE_YYY @MT@
+#define MAXXES_YYY @SH@
+
+
+#endif
\ No newline at end of file
diff --git a/version3/cpp/ecdh.cpp b/version3/cpp/ecdh.cpp
new file mode 100644
index 0000000..d088b4d
--- /dev/null
+++ b/version3/cpp/ecdh.cpp
@@ -0,0 +1,435 @@
+/*
+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.
+*/
+
+/* ECDH/ECIES/ECDSA Functions - see main program below */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "ecdh_ZZZ.h"
+
+using namespace XXX;
+using namespace YYY;
+
+/* Calculate a public/private EC GF(p) key pair. W=S.G mod EC(p),
+ * where S is the secret key and W is the public key
+ * and G is fixed generator.
+ * If RNG is NULL then the private key is provided externally in S
+ * otherwise it is generated randomly internally */
+int ZZZ::ECP_KEY_PAIR_GENERATE(csprng *RNG,octet* S,octet *W)
+{
+    BIG r,gx,gy,s;
+    ECP G;
+    int res=0;
+
+	ECP_generator(&G);
+
+    BIG_rcopy(r,CURVE_Order);
+    if (RNG!=NULL)
+    {
+        BIG_randomnum(s,r,RNG);
+    }
+    else
+    {
+        BIG_fromBytes(s,S->val);
+        BIG_mod(s,r);
+    }
+
+#ifdef AES_S
+    BIG_mod2m(s,2*AES_S);
+//	BIG_toBytes(S->val,s);
+#endif
+
+    S->len=EGS_ZZZ;
+    BIG_toBytes(S->val,s);
+
+
+    ECP_mul(&G,s);
+
+	ECP_toOctet(W,&G,false);	// To use point compression on public keys, change to true 
+
+/*
+
+#if CURVETYPE_ZZZ!=MONTGOMERY
+    ECP_get(gx,gy,&G);
+#else
+    ECP_get(gx,&G);
+
+#endif
+
+
+
+#if CURVETYPE_ZZZ!=MONTGOMERY
+    W->len=2*EFS_ZZZ+1;
+    W->val[0]=4;
+    BIG_toBytes(&(W->val[1]),gx);
+    BIG_toBytes(&(W->val[EFS_ZZZ+1]),gy);
+#else
+    W->len=EFS_ZZZ+1;
+    W->val[0]=2;
+    BIG_toBytes(&(W->val[1]),gx);
+#endif
+*/
+
+    return res;
+}
+
+/* Validate public key */
+int ZZZ::ECP_PUBLIC_KEY_VALIDATE(octet *W)
+{
+    BIG q,r,wx,k;
+    ECP WP;
+    int valid,nb;
+    int res=0;
+
+    BIG_rcopy(q,Modulus);
+    BIG_rcopy(r,CURVE_Order);
+
+	valid=ECP_fromOctet(&WP,W);
+	if (!valid) res=ECDH_INVALID_PUBLIC_KEY;
+
+/*
+    BIG_fromBytes(wx,&(W->val[1]));
+    if (BIG_comp(wx,q)>=0) res=ECDH_INVALID_PUBLIC_KEY;
+#if CURVETYPE_ZZZ!=MONTGOMERY
+    BIG wy;
+    BIG_fromBytes(wy,&(W->val[EFS_ZZZ+1]));
+    if (BIG_comp(wy,q)>=0) res=ECDH_INVALID_PUBLIC_KEY;
+#endif
+*/
+    if (res==0)
+    {
+
+//#if CURVETYPE_ZZZ!=MONTGOMERY
+//        valid=ECP_set(&WP,wx,wy);
+//#else
+//        valid=ECP_set(&WP,wx);
+//#endif
+//        if (!valid || ECP_isinf(&WP)) res=ECDH_INVALID_PUBLIC_KEY;
+//        if (res==0 )
+//        {/* Check point is not in wrong group */
+			nb=BIG_nbits(q);
+			BIG_one(k);
+			BIG_shl(k,(nb+4)/2);
+			BIG_add(k,q,k);
+			BIG_sdiv(k,r); /* get co-factor */
+
+			while (BIG_parity(k)==0)
+			{
+				ECP_dbl(&WP);
+				BIG_fshr(k,1);
+			}
+
+			if (!BIG_isunity(k)) ECP_mul(&WP,k);
+			if (ECP_isinf(&WP)) res=ECDH_INVALID_PUBLIC_KEY;
+//        }
+    }
+
+    return res;
+}
+
+/* IEEE-1363 Diffie-Hellman online calculation Z=S.WD */
+int ZZZ::ECP_SVDP_DH(octet *S,octet *WD,octet *Z)
+{
+    BIG r,s,wx;
+    int valid;
+    ECP W;
+    int res=0;
+
+    BIG_fromBytes(s,S->val);
+
+	valid=ECP_fromOctet(&W,WD);
+/*
+    BIG_fromBytes(wx,&(WD->val[1]));
+#if CURVETYPE_ZZZ!=MONTGOMERY
+    BIG wy;
+    BIG_fromBytes(wy,&(WD->val[EFS_ZZZ+1]));
+    valid=ECP_set(&W,wx,wy);
+#else
+    valid=ECP_set(&W,wx);
+#endif
+*/
+    if (!valid) res=ECDH_ERROR;
+    if (res==0)
+    {
+        BIG_rcopy(r,CURVE_Order);
+        BIG_mod(s,r);
+
+        ECP_mul(&W,s);
+        if (ECP_isinf(&W)) res=ECDH_ERROR;
+        else
+        {
+#if CURVETYPE_ZZZ!=MONTGOMERY
+            ECP_get(wx,wx,&W);
+#else
+            ECP_get(wx,&W);
+#endif
+            Z->len=MODBYTES_XXX;
+            BIG_toBytes(Z->val,wx);
+        }
+    }
+    return res;
+}
+
+#if CURVETYPE_ZZZ!=MONTGOMERY
+
+/* IEEE ECDSA Signature, C and D are signature on F using private key S */
+int ZZZ::ECP_SP_DSA(int sha,csprng *RNG,octet *K,octet *S,octet *F,octet *C,octet *D)
+{
+    char h[128];
+    octet H= {0,sizeof(h),h};
+
+    BIG r,s,f,c,d,u,vx,w;
+    ECP G,V;
+
+    ehashit(sha,F,-1,NULL,&H,sha);
+
+	ECP_generator(&G);
+
+	BIG_rcopy(r,CURVE_Order);
+
+    BIG_fromBytes(s,S->val);
+
+    int hlen=H.len;
+    if (H.len>MODBYTES_XXX) hlen=MODBYTES_XXX;
+    BIG_fromBytesLen(f,H.val,hlen);
+
+
+	if (RNG!=NULL)
+	{
+
+		do
+		{
+		
+            BIG_randomnum(u,r,RNG);
+            BIG_randomnum(w,r,RNG); /* side channel masking */
+       
+#ifdef AES_S
+			BIG_mod2m(u,2*AES_S);
+#endif
+			ECP_copy(&V,&G);
+			ECP_mul(&V,u);
+
+			ECP_get(vx,vx,&V);
+
+			BIG_copy(c,vx);
+			BIG_mod(c,r);
+			if (BIG_iszilch(c)) continue;
+        
+            BIG_modmul(u,u,w,r);
+        
+
+			BIG_invmodp(u,u,r);
+			BIG_modmul(d,s,c,r);
+
+			BIG_add(d,f,d);
+        
+            BIG_modmul(d,d,w,r);
+       
+			BIG_modmul(d,u,d,r);
+
+		}
+		while (BIG_iszilch(d));
+	}
+	else
+	{
+		BIG_fromBytes(u,K->val);
+		BIG_mod(u,r);
+
+#ifdef AES_S
+		BIG_mod2m(u,2*AES_S);
+#endif
+		ECP_copy(&V,&G);
+		ECP_mul(&V,u);
+
+		ECP_get(vx,vx,&V);
+
+		BIG_copy(c,vx);
+		BIG_mod(c,r);
+		if (BIG_iszilch(c)) return ECDH_ERROR;
+        
+		BIG_invmodp(u,u,r);
+		BIG_modmul(d,s,c,r);
+
+		BIG_add(d,f,d);
+  
+		BIG_modmul(d,u,d,r);
+		if (BIG_iszilch(d)) return ECDH_ERROR;
+
+    }
+
+    C->len=D->len=EGS_ZZZ;
+
+    BIG_toBytes(C->val,c);
+    BIG_toBytes(D->val,d);
+
+    return 0;
+}
+
+/* IEEE1363 ECDSA Signature Verification. Signature C and D on F is verified using public key W */
+int ZZZ::ECP_VP_DSA(int sha,octet *W,octet *F, octet *C,octet *D)
+{
+    char h[128];
+    octet H= {0,sizeof(h),h};
+
+    BIG r,wx,wy,f,c,d,h2;
+    int res=0;
+    ECP G,WP;
+    int valid;
+
+    ehashit(sha,F,-1,NULL,&H,sha);
+
+	ECP_generator(&G);
+
+    BIG_rcopy(r,CURVE_Order);
+
+    OCT_shl(C,C->len-MODBYTES_XXX);
+    OCT_shl(D,D->len-MODBYTES_XXX);
+
+    BIG_fromBytes(c,C->val);
+    BIG_fromBytes(d,D->val);
+
+    int hlen=H.len;
+    if (hlen>MODBYTES_XXX) hlen=MODBYTES_XXX;
+
+    BIG_fromBytesLen(f,H.val,hlen);
+
+    //BIG_fromBytes(f,H.val);
+
+    if (BIG_iszilch(c) || BIG_comp(c,r)>=0 || BIG_iszilch(d) || BIG_comp(d,r)>=0)
+        res=ECDH_INVALID;
+
+    if (res==0)
+    {
+        BIG_invmodp(d,d,r);
+        BIG_modmul(f,f,d,r);
+        BIG_modmul(h2,c,d,r);
+
+		valid=ECP_fromOctet(&WP,W);
+/*
+        BIG_fromBytes(wx,&(W->val[1]));
+        BIG_fromBytes(wy,&(W->val[EFS_ZZZ+1]));
+
+        valid=ECP_set(&WP,wx,wy);
+*/
+        if (!valid) res=ECDH_ERROR;
+        else
+        {
+            ECP_mul2(&WP,&G,h2,f);
+
+            if (ECP_isinf(&WP)) res=ECDH_INVALID;
+            else
+            {
+                ECP_get(d,d,&WP);
+                BIG_mod(d,r);
+                if (BIG_comp(d,c)!=0) res=ECDH_INVALID;
+            }
+        }
+    }
+
+    return res;
+}
+
+/* IEEE1363 ECIES encryption. Encryption of plaintext M uses public key W and produces ciphertext V,C,T */
+void ZZZ::ECP_ECIES_ENCRYPT(int sha,octet *P1,octet *P2,csprng *RNG,octet *W,octet *M,int tlen,octet *V,octet *C,octet *T)
+{
+
+    int i,len;
+    char z[EFS_ZZZ],vz[3*EFS_ZZZ+1],k[2*AESKEY_ZZZ],k1[AESKEY_ZZZ],k2[AESKEY_ZZZ],l2[8],u[EFS_ZZZ];
+    octet Z= {0,sizeof(z),z};
+    octet VZ= {0,sizeof(vz),vz};
+    octet K= {0,sizeof(k),k};
+    octet K1= {0,sizeof(k1),k1};
+    octet K2= {0,sizeof(k2),k2};
+    octet L2= {0,sizeof(l2),l2};
+    octet U= {0,sizeof(u),u};
+
+    if (ECP_KEY_PAIR_GENERATE(RNG,&U,V)!=0) return;
+    if (ECP_SVDP_DH(&U,W,&Z)!=0) return;
+
+    OCT_copy(&VZ,V);
+    OCT_joctet(&VZ,&Z);
+
+    KDF2(sha,&VZ,P1,2*AESKEY_ZZZ,&K);
+
+    K1.len=K2.len=AESKEY_ZZZ;
+    for (i=0; i<AESKEY_ZZZ; i++)
+    {
+        K1.val[i]=K.val[i];
+        K2.val[i]=K.val[AESKEY_ZZZ+i];
+    }
+
+    AES_CBC_IV0_ENCRYPT(&K1,M,C);
+
+    OCT_jint(&L2,P2->len,8);
+
+    len=C->len;
+    OCT_joctet(C,P2);
+    OCT_joctet(C,&L2);
+    HMAC(sha,C,&K2,tlen,T);
+    C->len=len;
+}
+
+/* IEEE1363 ECIES decryption. Decryption of ciphertext V,C,T using private key U outputs plaintext M */
+int ZZZ::ECP_ECIES_DECRYPT(int sha,octet *P1,octet *P2,octet *V,octet *C,octet *T,octet *U,octet *M)
+{
+
+    int i,len;
+    char z[EFS_ZZZ],vz[3*EFS_ZZZ+1],k[2*AESKEY_ZZZ],k1[AESKEY_ZZZ],k2[AESKEY_ZZZ],l2[8],tag[32];
+    octet Z= {0,sizeof(z),z};
+    octet VZ= {0,sizeof(vz),vz};
+    octet K= {0,sizeof(k),k};
+    octet K1= {0,sizeof(k1),k1};
+    octet K2= {0,sizeof(k2),k2};
+    octet L2= {0,sizeof(l2),l2};
+    octet TAG= {0,sizeof(tag),tag};
+
+    if (ECP_SVDP_DH(U,V,&Z)!=0) return 0;
+
+    OCT_copy(&VZ,V);
+    OCT_joctet(&VZ,&Z);
+
+    KDF2(sha,&VZ,P1,2*AESKEY_ZZZ,&K);
+
+    K1.len=K2.len=AESKEY_ZZZ;
+    for (i=0; i<AESKEY_ZZZ; i++)
+    {
+        K1.val[i]=K.val[i];
+        K2.val[i]=K.val[AESKEY_ZZZ+i];
+    }
+
+    if (!AES_CBC_IV0_DECRYPT(&K1,C,M)) return 0;
+
+    OCT_jint(&L2,P2->len,8);
+
+    len=C->len;
+    OCT_joctet(C,P2);
+    OCT_joctet(C,&L2);
+    HMAC(sha,C,&K2,T->len,&TAG);
+    C->len=len;
+
+    if (!OCT_ncomp(T,&TAG,T->len)) return 0;
+
+    return 1;
+
+}
+
+#endif
diff --git a/version3/cpp/ecdh.h b/version3/cpp/ecdh.h
new file mode 100644
index 0000000..f1f1873
--- /dev/null
+++ b/version3/cpp/ecdh.h
@@ -0,0 +1,154 @@
+/*
+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.
+*/
+
+/**
+ * @file ecdh.h
+ * @author Mike Scott and Kealan McCusker
+ * @date 2nd June 2015
+ * @brief ECDH Header file for implementation of standard EC protocols
+ *
+ * declares functions
+ *
+ */
+
+#ifndef ECDH_ZZZ_H
+#define ECDH_ZZZ_H
+
+#include "ecp_ZZZ.h"
+#include "ecdh_support.h"
+
+using namespace amcl;
+
+
+/*** START OF USER CONFIGURABLE SECTION -  ***/
+
+/*** START OF USER CONFIGURABLE SECTION -  ***/
+
+
+/*** END OF USER CONFIGURABLE SECTION ***/
+
+#define EGS_ZZZ MODBYTES_XXX  /**< ECC Group Size in bytes */
+#define EFS_ZZZ MODBYTES_XXX  /**< ECC Field Size in bytes */
+
+#define ECDH_OK                     0     /**< Function completed without error */
+/*#define ECDH_DOMAIN_ERROR          -1*/
+#define ECDH_INVALID_PUBLIC_KEY    -2	/**< Public Key is Invalid */
+#define ECDH_ERROR                 -3	/**< ECDH Internal Error */
+#define ECDH_INVALID               -4	/**< ECDH Internal Error */
+/*#define ECDH_DOMAIN_NOT_FOUND      -5
+#define ECDH_OUT_OF_MEMORY         -6
+#define ECDH_DIV_BY_ZERO           -7
+#define ECDH_BAD_ASSUMPTION        -8*/
+
+
+namespace ZZZ {
+
+/* ECDH primitives */
+/**	@brief Generate an ECC public/private key pair
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param s the private key, an output internally randomly generated if R!=NULL, otherwise must be provided as an input
+	@param W the output public key, which is s.G, where G is a fixed generator
+	@return 0 or an error code
+ */
+extern int  ECP_KEY_PAIR_GENERATE(csprng *R,octet *s,octet *W);
+/**	@brief Validate an ECC public key
+ *
+	@param W the input public key to be validated
+	@return 0 if public key is OK, or an error code
+ */
+extern int  ECP_PUBLIC_KEY_VALIDATE(octet *W);
+
+/* ECDH primitives */
+
+/**	@brief Generate Diffie-Hellman shared key
+ *
+	IEEE-1363 Diffie-Hellman shared secret calculation
+	@param s is the input private key,
+	@param W the input public key of the other party
+	@param K the output shared key, in fact the x-coordinate of s.W
+	@return 0 or an error code
+ */
+extern int ECP_SVDP_DH(octet *s,octet *W,octet *K);
+/*extern int ECPSVDP_DHC(octet *,octet *,int,octet *);*/
+
+/*#if CURVETYPE!=MONTGOMERY */
+/* ECIES functions */
+/*#if CURVETYPE!=MONTGOMERY */
+/* ECIES functions */
+/**	@brief ECIES Encryption
+ *
+	IEEE-1363 ECIES Encryption
+	@param h is the hash type
+	@param P1 input Key Derivation parameters
+	@param P2 input Encoding parameters
+	@param R is a pointer to a cryptographically secure random number generator
+	@param W the input public key of the recieving party
+	@param M is the plaintext message to be encrypted
+	@param len the length of the HMAC tag
+	@param V component of the output ciphertext
+	@param C the output ciphertext
+	@param T the output HMAC tag, part of the ciphertext
+ */
+extern void ECP_ECIES_ENCRYPT(int h,octet *P1,octet *P2,csprng *R,octet *W,octet *M,int len,octet *V,octet *C,octet *T);
+/**	@brief ECIES Decryption
+ *
+	IEEE-1363 ECIES Decryption
+	@param h is the hash type
+	@param P1 input Key Derivation parameters
+	@param P2 input Encoding parameters
+	@param V component of the input ciphertext
+	@param C the input ciphertext
+	@param T the input HMAC tag, part of the ciphertext
+	@param U the input private key for decryption
+	@param M the output plaintext message
+	@return 1 if successful, else 0
+ */
+extern int ECP_ECIES_DECRYPT(int h,octet *P1,octet *P2,octet *V,octet *C,octet *T,octet *U,octet *M);
+
+/* ECDSA functions */
+/**	@brief ECDSA Signature
+ *
+	IEEE-1363 ECDSA Signature
+	@param h is the hash type
+	@param R is a pointer to a cryptographically secure random number generator
+        @param k Ephemeral key. This value is used when R=NULL
+	@param s the input private signing key
+	@param M the input message to be signed
+	@param c component of the output signature
+	@param d component of the output signature
+
+ */
+extern int ECP_SP_DSA(int h,csprng *R,octet *k,octet *s,octet *M,octet *c,octet *d);
+/**	@brief ECDSA Signature Verification
+ *
+	IEEE-1363 ECDSA Signature Verification
+	@param h is the hash type
+	@param W the input public key
+	@param M the input message
+	@param c component of the input signature
+	@param d component of the input signature
+	@return 0 or an error code
+ */
+extern int ECP_VP_DSA(int h,octet *W,octet *M,octet *c,octet *d);
+/*#endif*/
+}
+
+#endif
+
diff --git a/version3/cpp/ecdh_support.cpp b/version3/cpp/ecdh_support.cpp
new file mode 100644
index 0000000..63435ec
--- /dev/null
+++ b/version3/cpp/ecdh_support.cpp
@@ -0,0 +1,351 @@
+/*
+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.
+*/
+
+/* Symmetric crypto support functions Functions  */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "ecdh_support.h"
+
+using namespace amcl;
+
+#define ROUNDUP(a,b) ((a)-1)/(b)+1
+
+/* general purpose hash function w=hash(p|n|x|y) */
+/* pad or truncate ouput to length pad if pad!=0 */
+void amcl::ehashit(int sha,octet *p,int n,octet *x,octet *w,int pad)
+{
+    int i,c[4],hlen;
+    hash256 sha256;
+    hash512 sha512;
+    char hh[64];
+
+    switch (sha)
+    {
+    case SHA256:
+        HASH256_init(&sha256);
+        break;
+    case SHA384:
+        HASH384_init(&sha512);
+        break;
+    case SHA512:
+        HASH512_init(&sha512);
+        break;
+    }
+
+    hlen=sha;
+
+    for (i=0; i<p->len; i++)
+    {
+        switch(sha)
+        {
+        case SHA256:
+            HASH256_process(&sha256,p->val[i]);
+            break;
+        case SHA384:
+            HASH384_process(&sha512,p->val[i]);
+            break;
+        case SHA512:
+            HASH512_process(&sha512,p->val[i]);
+            break;
+        }
+    }
+    if (n>0)
+    {
+        c[0]=(n>>24)&0xff;
+        c[1]=(n>>16)&0xff;
+        c[2]=(n>>8)&0xff;
+        c[3]=(n)&0xff;
+        for (i=0; i<4; i++)
+        {
+            switch(sha)
+            {
+            case SHA256:
+                HASH256_process(&sha256,c[i]);
+                break;
+            case SHA384:
+                HASH384_process(&sha512,c[i]);
+                break;
+            case SHA512:
+                HASH512_process(&sha512,c[i]);
+                break;
+            }
+        }
+    }
+    if (x!=NULL) for (i=0; i<x->len; i++)
+        {
+            switch(sha)
+            {
+            case SHA256:
+                HASH256_process(&sha256,x->val[i]);
+                break;
+            case SHA384:
+                HASH384_process(&sha512,x->val[i]);
+                break;
+            case SHA512:
+                HASH512_process(&sha512,x->val[i]);
+                break;
+            }
+        }
+
+    switch (sha)
+    {
+    case SHA256:
+        HASH256_hash(&sha256,hh);
+        break;
+    case SHA384:
+        HASH384_hash(&sha512,hh);
+        break;
+    case SHA512:
+        HASH512_hash(&sha512,hh);
+        break;
+    }
+
+    OCT_empty(w);
+    if (!pad)
+        OCT_jbytes(w,hh,hlen);
+    else
+    {
+        if (pad<=hlen)
+            OCT_jbytes(w,hh,pad);
+        else
+        {
+           OCT_jbyte(w,0,pad-hlen);
+           OCT_jbytes(w,hh,hlen);
+        }
+    }
+    return;
+}
+
+/* Hash octet p to octet w */
+void amcl::HASH(int sha,octet *p,octet *w)
+{
+    ehashit(sha,p,-1,NULL,w,0);
+}
+
+/* Calculate HMAC of m using key k. HMAC is tag of length olen */
+int amcl::HMAC(int sha,octet *m,octet *k,int olen,octet *tag)
+{
+    /* Input is from an octet m        *
+     * olen is requested output length in bytes. k is the key  *
+     * The output is the calculated tag */
+    int hlen,b;
+    char h[128],k0[128];
+    octet H= {0,sizeof(h),h};
+    octet K0= {0,sizeof(k0),k0};
+
+    hlen=sha;
+    if (hlen>32) b=128;
+    else b=64;
+
+    if (olen<4 /*|| olen>hlen*/) return 0;
+
+    if (k->len > b) ehashit(sha,k,-1,NULL,&K0,0);
+    else            OCT_copy(&K0,k);
+
+    OCT_jbyte(&K0,0,b-K0.len);
+
+    OCT_xorbyte(&K0,0x36);
+
+    ehashit(sha,&K0,-1,m,&H,0);
+
+    OCT_xorbyte(&K0,0x6a);   /* 0x6a = 0x36 ^ 0x5c */
+    ehashit(sha,&K0,-1,&H,&H,olen);
+
+    OCT_empty(tag);
+
+    OCT_jbytes(tag,H.val,olen);
+
+    return 1;
+}
+
+/* Key Derivation Functions */
+/* Input octet z */
+/* Output key of length olen */
+/*
+void KDF1(octet *z,int olen,octet *key)
+{
+    char h[32];
+	octet H={0,sizeof(h),h};
+    int counter,cthreshold;
+    int hlen=32;
+
+    OCT_empty(key);
+
+    cthreshold=ROUNDUP(olen,hlen);
+
+    for (counter=0;counter<cthreshold;counter++)
+    {
+        ehashit(z,counter,NULL,NULL,&H);
+        if (key->len+hlen>olen) OCT_jbytes(key,H.val,olen%hlen);
+        else                    OCT_joctet(key,&H);
+    }
+}
+*/
+void amcl::KDF2(int sha,octet *z,octet *p,int olen,octet *key)
+{
+    /* NOTE: the parameter olen is the length of the output k in bytes */
+    char h[64];
+    octet H= {0,sizeof(h),h};
+    int counter,cthreshold;
+    int hlen=sha;
+
+    OCT_empty(key);
+
+    cthreshold=ROUNDUP(olen,hlen);
+
+    for (counter=1; counter<=cthreshold; counter++)
+    {
+        ehashit(sha,z,counter,p,&H,0);
+        if (key->len+hlen>olen)  OCT_jbytes(key,H.val,olen%hlen);
+        else                     OCT_joctet(key,&H);
+    }
+
+}
+
+/* Password based Key Derivation Function */
+/* Input password p, salt s, and repeat count */
+/* Output key of length olen */
+void amcl::PBKDF2(int sha,octet *p,octet *s,int rep,int olen,octet *key)
+{
+    int i,j,len,d=ROUNDUP(olen,sha);
+    char f[64],u[64];
+    octet F= {0,sizeof(f),f};
+    octet U= {0,sizeof(u),u};
+    OCT_empty(key);
+
+    for (i=1; i<=d; i++)
+    {
+        len=s->len;
+        OCT_jint(s,i,4);
+
+        HMAC(sha,s,p,sha,&F);
+
+        s->len=len;
+        OCT_copy(&U,&F);
+        for (j=2; j<=rep; j++)
+        {
+            HMAC(sha,&U,p,sha,&U);
+            OCT_xor(&F,&U);
+        }
+
+        OCT_joctet(key,&F);
+    }
+
+    OCT_chop(key,NULL,olen);
+}
+
+/* AES encryption/decryption. Encrypt byte array M using key K and returns ciphertext */
+void amcl::AES_CBC_IV0_ENCRYPT(octet *k,octet *m,octet *c)
+{
+    /* AES CBC encryption, with Null IV and key k */
+    /* Input is from an octet string m, output is to an octet string c */
+    /* Input is padded as necessary to make up a full final block */
+    aes a;
+    int fin;
+    int i,j,ipt,opt;
+    char buff[16];
+    int padlen;
+
+    OCT_clear(c);
+    if (m->len==0) return;
+    AES_init(&a,CBC,k->len,k->val,NULL);
+
+    ipt=opt=0;
+    fin=0;
+    for(;;)
+    {
+        for (i=0; i<16; i++)
+        {
+            if (ipt<m->len) buff[i]=m->val[ipt++];
+            else
+            {
+                fin=1;
+                break;
+            }
+        }
+        if (fin) break;
+        AES_encrypt(&a,buff);
+        for (i=0; i<16; i++)
+            if (opt<c->max) c->val[opt++]=buff[i];
+    }
+
+    /* last block, filled up to i-th index */
+
+    padlen=16-i;
+    for (j=i; j<16; j++) buff[j]=padlen;
+    AES_encrypt(&a,buff);
+    for (i=0; i<16; i++)
+        if (opt<c->max) c->val[opt++]=buff[i];
+    AES_end(&a);
+    c->len=opt;
+}
+
+/* decrypts and returns TRUE if all consistent, else returns FALSE */
+int amcl::AES_CBC_IV0_DECRYPT(octet *k,octet *c,octet *m)
+{
+    /* padding is removed */
+    aes a;
+    int i,ipt,opt,ch;
+    char buff[16];
+    int fin,bad;
+    int padlen;
+    ipt=opt=0;
+
+    OCT_clear(m);
+    if (c->len==0) return 1;
+    ch=c->val[ipt++];
+
+    AES_init(&a,CBC,k->len,k->val,NULL);
+    fin=0;
+
+    for(;;)
+    {
+        for (i=0; i<16; i++)
+        {
+            buff[i]=ch;
+            if (ipt>=c->len)
+            {
+                fin=1;
+                break;
+            }
+            else ch=c->val[ipt++];
+        }
+        AES_decrypt(&a,buff);
+        if (fin) break;
+        for (i=0; i<16; i++)
+            if (opt<m->max) m->val[opt++]=buff[i];
+    }
+    AES_end(&a);
+    bad=0;
+    padlen=buff[15];
+    if (i!=15 || padlen<1 || padlen>16) bad=1;
+    if (padlen>=2 && padlen<=16)
+        for (i=16-padlen; i<16; i++) if (buff[i]!=padlen) bad=1;
+
+    if (!bad) for (i=0; i<16-padlen; i++)
+            if (opt<m->max) m->val[opt++]=buff[i];
+
+    m->len=opt;
+    if (bad) return 0;
+    return 1;
+}
diff --git a/version3/cpp/ecdh_support.h b/version3/cpp/ecdh_support.h
new file mode 100644
index 0000000..65538e1
--- /dev/null
+++ b/version3/cpp/ecdh_support.h
@@ -0,0 +1,84 @@
+#ifndef ECC_SUPPORT_H
+#define ECC_SUPPORT_H
+
+#include "amcl.h"
+
+namespace amcl {
+
+/* Auxiliary Functions */
+
+
+extern void ehashit(int ,octet *,int ,octet *,octet *,int);
+
+/**	@brief hash an octet into another octet
+ *
+ 	@param h is the hash type
+	@param I input octet
+	@param O output octet - H(I)
+ */
+extern void HASH(int h,octet *I,octet *O);
+/**	@brief HMAC of message M using key K to create tag of length len in octet tag
+ *
+	IEEE-1363 MAC1 function. Uses SHA256 internally.
+	@param h is the hash type
+	@param M input message octet
+	@param K input encryption key
+	@param len is output desired length of HMAC tag
+	@param tag is the output HMAC
+	@return 0 for bad parameters, else 1
+ */
+extern int HMAC(int h,octet *M,octet *K,int len,octet *tag);
+
+/*extern void KDF1(octet *,int,octet *);*/
+
+/**	@brief Key Derivation Function - generates key K from inputs Z and P
+ *
+	IEEE-1363 KDF2 Key Derivation Function. Uses SHA256 internally.
+	@param h is the hash type
+	@param Z input octet
+	@param P input key derivation parameters - can be NULL
+	@param len is output desired length of key
+	@param K is the derived key
+ */
+extern void KDF2(int h,octet *Z,octet *P,int len,octet *K);
+/**	@brief Password Based Key Derivation Function - generates key K from password, salt and repeat counter
+ *
+	PBKDF2 Password Based Key Derivation Function. Uses SHA256 internally.
+	@param h is the hash type
+	@param P input password
+	@param S input salt
+	@param rep Number of times to be iterated.
+	@param len is output desired length
+	@param K is the derived key
+ */
+extern void PBKDF2(int h,octet *P,octet *S,int rep,int len,octet *K);
+/**	@brief AES encrypts a plaintext to a ciphtertext
+ *
+	IEEE-1363 AES_CBC_IV0_ENCRYPT function. Encrypts in CBC mode with a zero IV, padding as necessary to create a full final block.
+	@param K AES key
+	@param P input plaintext octet
+	@param C output ciphertext octet
+ */
+extern void AES_CBC_IV0_ENCRYPT(octet *K,octet *P,octet *C);
+/**	@brief AES encrypts a plaintext to a ciphtertext
+ *
+	IEEE-1363 AES_CBC_IV0_DECRYPT function. Decrypts in CBC mode with a zero IV.
+	@param K AES key
+	@param C input ciphertext octet
+	@param P output plaintext octet
+	@return 0 if bad input, else 1
+ */
+extern int AES_CBC_IV0_DECRYPT(octet *K,octet *C,octet *P);
+
+/* ECDH primitives - support functions */
+/**	@brief Generate an ECC public/private key pair
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param s the private key, an output internally randomly generated if R!=NULL, otherwise must be provided as an input
+	@param W the output public key, which is s.G, where G is a fixed generator
+	@return 0 or an error code
+ */
+
+}
+
+ #endif
diff --git a/version3/cpp/ecp.cpp b/version3/cpp/ecp.cpp
new file mode 100644
index 0000000..a9f9309
--- /dev/null
+++ b/version3/cpp/ecp.cpp
@@ -0,0 +1,1467 @@
+/*
+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.
+*/
+
+/* AMCL Elliptic Curve Functions */
+/* SU=m, SU is Stack Usage (Weierstrass Curves) */
+
+//#define HAS_MAIN
+
+#include "ecp_ZZZ.h"
+
+using namespace XXX;
+using namespace YYY;
+
+/* test for P=O point-at-infinity */
+int ZZZ::ECP_isinf(ECP *P)
+{
+//	if (P->inf) return 1;
+//    FP_reduce(&(P->x));     FP_reduce(&(P->z));
+#if CURVETYPE_ZZZ==EDWARDS
+//    FP_reduce(&(P->y));
+    return (FP_iszilch(&(P->x)) && FP_equals(&(P->y),&(P->z)));
+#endif
+#if CURVETYPE_ZZZ==WEIERSTRASS
+//    FP_reduce(&(P->y));
+    return (FP_iszilch(&(P->x)) && FP_iszilch(&(P->z)));
+#endif
+#if CURVETYPE_ZZZ==MONTGOMERY
+    return FP_iszilch(&(P->z));
+#endif
+//	return P->inf;
+
+}
+
+/* Conditional swap of P and Q dependant on d */
+static void ECP_cswap(ZZZ::ECP *P,ZZZ::ECP *Q,int d)
+{
+    FP_cswap(&(P->x),&(Q->x),d);
+#if CURVETYPE_ZZZ!=MONTGOMERY
+    FP_cswap(&(P->y),&(Q->y),d);
+#endif
+    FP_cswap(&(P->z),&(Q->z),d);
+/*
+    d=~(d-1);
+    d=d&(P->inf^Q->inf);
+    P->inf^=d;
+    Q->inf^=d;
+*/
+}
+
+#if CURVETYPE_ZZZ!=MONTGOMERY
+/* Conditional move Q to P dependant on d */
+static void ECP_cmove(ZZZ::ECP *P,ZZZ::ECP *Q,int d)
+{
+    FP_cmove(&(P->x),&(Q->x),d);
+#if CURVETYPE_ZZZ!=MONTGOMERY
+    FP_cmove(&(P->y),&(Q->y),d);
+#endif
+    FP_cmove(&(P->z),&(Q->z),d);
+/*
+    d=~(d-1);
+    P->inf^=(P->inf^Q->inf)&d;
+*/
+}
+
+/* return 1 if b==c, no branching */
+static int teq(sign32 b,sign32 c)
+{
+    sign32 x=b^c;
+    x-=1;  // if x=0, x now -1
+    return (int)((x>>31)&1);
+}
+#endif // CURVETYPE_ZZZ!=MONTGOMERY
+
+#if CURVETYPE_ZZZ!=MONTGOMERY
+/* Constant time select from pre-computed table */
+static void ECP_select(ZZZ::ECP *P,ZZZ::ECP W[],sign32 b)
+{
+    ZZZ::ECP MP;
+    sign32 m=b>>31;
+    sign32 babs=(b^m)-m;
+
+    babs=(babs-1)/2;
+
+    ECP_cmove(P,&W[0],teq(babs,0));  // conditional move
+    ECP_cmove(P,&W[1],teq(babs,1));
+    ECP_cmove(P,&W[2],teq(babs,2));
+    ECP_cmove(P,&W[3],teq(babs,3));
+    ECP_cmove(P,&W[4],teq(babs,4));
+    ECP_cmove(P,&W[5],teq(babs,5));
+    ECP_cmove(P,&W[6],teq(babs,6));
+    ECP_cmove(P,&W[7],teq(babs,7));
+
+    ECP_copy(&MP,P);
+    ECP_neg(&MP);  // minus P
+    ECP_cmove(P,&MP,(int)(m&1));
+}
+#endif
+
+/* Test P == Q */
+/* SU=168 */
+int ZZZ::ECP_equals(ECP *P,ECP *Q)
+{
+    FP a,b;
+//    if (ECP_isinf(P) && ECP_isinf(Q)) return 1;
+//    if (ECP_isinf(P) || ECP_isinf(Q)) return 0;
+
+
+    FP_mul(&a,&(P->x),&(Q->z));
+    FP_mul(&b,&(Q->x),&(P->z));
+    if (!FP_equals(&a,&b)) return 0;
+
+#if CURVETYPE_ZZZ!=MONTGOMERY
+    FP_mul(&a,&(P->y),&(Q->z));
+    FP_mul(&b,&(Q->y),&(P->z));
+    if (!FP_equals(&a,&b)) return 0;
+#endif
+
+    return 1;
+
+}
+
+/* Set P=Q */
+/* SU=16 */
+void ZZZ::ECP_copy(ECP *P,ECP *Q)
+{
+//    P->inf=Q->inf;
+    FP_copy(&(P->x),&(Q->x));
+#if CURVETYPE_ZZZ!=MONTGOMERY
+    FP_copy(&(P->y),&(Q->y));
+#endif
+    FP_copy(&(P->z),&(Q->z));
+}
+
+/* Set P=-Q */
+#if CURVETYPE_ZZZ!=MONTGOMERY
+/* SU=8 */
+void ZZZ::ECP_neg(ECP *P)
+{
+//    if (ECP_isinf(P)) return;
+#if CURVETYPE_ZZZ==WEIERSTRASS
+    FP_neg(&(P->y),&(P->y));
+    FP_norm(&(P->y));
+#else
+    FP_neg(&(P->x),&(P->x));
+    FP_norm(&(P->x));
+#endif
+
+}
+#endif
+
+/* Set P=O */
+void ZZZ::ECP_inf(ECP *P)
+{
+    FP_zero(&(P->x));
+#if CURVETYPE_ZZZ!=MONTGOMERY
+    FP_one(&(P->y));
+#endif
+#if CURVETYPE_ZZZ!=EDWARDS
+    FP_zero(&(P->z));
+#else
+	FP_one(&(P->z));
+#endif
+//    P->inf=1;
+}
+
+/* Calculate right Hand Side of curve equation y^2=RHS */
+/* SU=56 */
+void ZZZ::ECP_rhs(FP *v,FP *x)
+{
+#if CURVETYPE_ZZZ==WEIERSTRASS
+    /* x^3+Ax+B */
+    FP t;
+    FP_sqr(&t,x);
+    FP_mul(&t,&t,x);
+
+    if (CURVE_A==-3)
+    {
+        FP_neg(v,x);
+        FP_norm(v);
+        FP_imul(v,v,-CURVE_A);
+        FP_norm(v);
+        FP_add(v,&t,v);
+    }
+    else FP_copy(v,&t);
+
+    FP_rcopy(&t,CURVE_B);
+
+    FP_add(v,&t,v);
+    FP_reduce(v);
+#endif
+
+#if CURVETYPE_ZZZ==EDWARDS
+    /* (Ax^2-1)/(Bx^2-1) */
+	FP t,one;
+    FP_sqr(v,x);
+    FP_one(&one);
+    FP_rcopy(&t,CURVE_B);
+    
+    FP_mul(&t,v,&t);
+    FP_sub(&t,&t,&one);
+	FP_norm(&t);
+    if (CURVE_A==1) FP_sub(v,v,&one);
+
+    if (CURVE_A==-1)
+    {
+        FP_add(v,v,&one);
+		FP_norm(v);
+        FP_neg(v,v);
+    }
+	FP_norm(v);
+	FP_inv(&t,&t);
+	FP_mul(v,v,&t);
+	FP_reduce(v);
+#endif
+
+#if CURVETYPE_ZZZ==MONTGOMERY
+    /* x^3+Ax^2+x */
+    FP x2,x3;
+    FP_sqr(&x2,x);
+    FP_mul(&x3,&x2,x);
+    FP_copy(v,x);
+    FP_imul(&x2,&x2,CURVE_A);
+    FP_add(v,v,&x2);
+    FP_add(v,v,&x3);
+    FP_reduce(v);
+#endif
+}
+
+/* Set P=(x,y) */
+
+#if CURVETYPE_ZZZ==MONTGOMERY
+
+/* Set P=(x,{y}) */
+
+int ZZZ::ECP_set(ECP *P,BIG x)
+{
+    BIG m,b;
+	FP rhs;
+    BIG_rcopy(m,Modulus);
+
+	FP_nres(&rhs,x);
+
+    ECP_rhs(&rhs,&rhs);
+    FP_redc(b,&rhs);
+
+    if (BIG_jacobi(b,m)!=1)
+    {
+        ECP_inf(P);
+        return 0;
+    }
+    //P->inf=0;
+    FP_nres(&(P->x),x);
+    FP_one(&(P->z));
+    return 1;
+}
+
+/* Extract x coordinate as BIG */
+int ZZZ::ECP_get(BIG x,ECP *P)
+{
+	ECP W;
+	ECP_copy(&W,P);
+	ECP_affine(W);
+    if (ECP_isinf(&W)) return -1;
+    //ECP_affine(P);
+    FP_redc(x,&(W.x));
+    return 0;
+}
+
+
+#else
+/* Extract (x,y) and return sign of y. If x and y are the same return only x */
+/* SU=16 */
+int ZZZ::ECP_get(BIG x,BIG y,ECP *P)
+{
+    int s;
+	ECP W;
+	ECP_copy(&W,P);
+	ECP_affine(&W);
+    if (ECP_isinf(&W)) return -1;
+
+    FP_redc(y,&(W.y));
+    s=BIG_parity(y);
+
+    FP_redc(x,&(W.x));
+
+    return s;
+}
+
+/* Set P=(x,{y}) */
+/* SU=96 */
+int ZZZ::ECP_set(ECP *P,BIG x,BIG y)
+{
+    FP rhs,y2;
+
+    FP_nres(&y2,y);
+    FP_sqr(&y2,&y2);
+    FP_reduce(&y2);
+
+    FP_nres(&rhs,x);
+    ECP_rhs(&rhs,&rhs);
+
+    if (!FP_equals(&y2,&rhs))
+    {
+        ECP_inf(P);
+        return 0;
+    }
+
+  //  P->inf=0;
+
+    FP_nres(&(P->x),x);
+    FP_nres(&(P->y),y);
+    FP_one(&(P->z));
+    return 1;
+}
+
+/* Set P=(x,y), where y is calculated from x with sign s */
+/* SU=136 */
+int ZZZ::ECP_setx(ECP *P,BIG x,int s)
+{
+    FP rhs;
+	BIG t,m;
+    BIG_rcopy(m,Modulus);
+
+    FP_nres(&rhs,x);
+
+    ECP_rhs(&rhs,&rhs);
+ 
+    FP_redc(t,&rhs);
+    if (BIG_jacobi(t,m)!=1)
+    {
+        ECP_inf(P);
+        return 0;
+    }
+
+   // P->inf=0;
+
+    FP_nres(&(P->x),x);
+    FP_sqrt(&(P->y),&rhs);
+
+//printf("SR= "); FP_output(&(P->y)); printf("\n");
+
+    FP_redc(t,&(P->y));
+
+//printf("t= "); BIG_output(t); printf("\n");
+
+    if (BIG_parity(t)!=s)
+        FP_neg(&(P->y),&(P->y));
+    FP_reduce(&(P->y));
+    FP_one(&(P->z));
+    return 1;
+}
+
+#endif
+
+/* Convert P to Affine, from (x,y,z) to (x,y) */
+/* SU=160 */
+void ZZZ::ECP_affine(ECP *P)
+{
+    FP one,iz;
+	BIG b;
+    if (ECP_isinf(P)) return;
+    FP_one(&one);
+    if (FP_equals(&(P->z),&one)) return;
+
+	FP_inv(&iz,&(P->z));
+    FP_mul(&(P->x),&(P->x),&iz);
+
+#if CURVETYPE_ZZZ==EDWARDS || CURVETYPE_ZZZ==WEIERSTRASS
+
+    FP_mul(&(P->y),&(P->y),&iz);
+    FP_reduce(&(P->y));
+
+#endif
+
+    FP_reduce(&(P->x));
+    FP_copy(&(P->z),&one);
+}
+
+/* SU=120 */
+void ZZZ::ECP_outputxyz(ECP *P)
+{
+    BIG x,z;
+    if (ECP_isinf(P))
+    {
+        printf("Infinity\n");
+        return;
+    }
+    FP_reduce(&(P->x));
+    FP_redc(x,&(P->x));
+    FP_reduce(&(P->z));
+    FP_redc(z,&(P->z));
+
+#if CURVETYPE_ZZZ!=MONTGOMERY
+    BIG y;
+    FP_reduce(&(P->y));
+    FP_redc(y,&(P->y));
+    printf("(");
+    BIG_output(x);
+    printf(",");
+    BIG_output(y);
+    printf(",");
+    BIG_output(z);
+    printf(")\n");
+
+#else
+    printf("(");
+    BIG_output(x);
+    printf(",");
+    BIG_output(z);
+    printf(")\n");
+#endif
+}
+
+/* SU=16 */
+/* Output point P */
+void ZZZ::ECP_output(ECP *P)
+{
+	BIG x,y;
+    if (ECP_isinf(P))
+    {
+        printf("Infinity\n");
+        return;
+    }
+    ECP_affine(P);
+#if CURVETYPE_ZZZ!=MONTGOMERY
+    FP_redc(x,&(P->x));
+    FP_redc(y,&(P->y));
+    printf("(");
+    BIG_output(x);
+    printf(",");
+    BIG_output(y);
+    printf(")\n");
+#else
+    FP_redc(x,&(P->x));
+    printf("(");
+    BIG_output(x);
+    printf(")\n");
+#endif
+}
+
+/* SU=16 */
+/* Output point P */
+void ZZZ::ECP_rawoutput(ECP *P)
+{
+	BIG x,y,z;
+//   if (ECP_isinf(P))
+ //   {
+ //       printf("Infinity\n");
+ //       return;
+ //   }
+//    ECP_affine(P);
+#if CURVETYPE_ZZZ!=MONTGOMERY
+    FP_redc(x,&(P->x));
+    FP_redc(y,&(P->y));
+    FP_redc(z,&(P->z));
+    printf("(");
+    BIG_output(x);
+    printf(",");
+    BIG_output(y);
+    printf(",");
+    BIG_output(z);
+    printf(")\n");
+#else
+    FP_redc(x,&(P->x));
+    FP_redc(z,&(P->z));
+    printf("(");
+    BIG_output(x);
+	printf(",");
+	BIG_output(z);
+    printf(")\n");
+#endif
+}
+
+/* SU=88 */
+/* Convert P to octet string, compressing if desired */
+void ZZZ::ECP_toOctet(octet *W,ECP *P,bool compress)
+{
+#if CURVETYPE_ZZZ==MONTGOMERY
+    BIG x;
+    ECP_get(x,P);
+    W->len=MODBYTES_XXX+1;
+    W->val[0]=0x06;
+    BIG_toBytes(&(W->val[1]),x);
+#else
+    BIG x,y;
+    ECP_get(x,y,P);
+	if (compress)
+	{
+		W->val[0]=0x02;
+		if (BIG_parity(y)==1) W->val[0]=0x03;
+		W->len=MODBYTES_XXX+1;
+		BIG_toBytes(&(W->val[1]),x);
+	}
+	else
+	{
+		W->val[0]=0x04;
+		W->len=2*MODBYTES_XXX+1;
+		BIG_toBytes(&(W->val[1]),x);
+		BIG_toBytes(&(W->val[MODBYTES_XXX+1]),y);
+	}
+#endif
+}
+
+/* SU=88 */
+/* Restore P from octet string */
+int ZZZ::ECP_fromOctet(ECP *P,octet *W)
+{
+#if CURVETYPE_ZZZ==MONTGOMERY
+    BIG x;
+    BIG_fromBytes(x,&(W->val[1]));
+    if (ECP_set(P,x)) return 1;
+    return 0;
+#else
+    BIG x,y;
+	int typ=W->val[0];
+    BIG_fromBytes(x,&(W->val[1]));
+
+    if (typ==0x04)
+	{
+		BIG_fromBytes(y,&(W->val[MODBYTES_XXX+1]));
+		if (ECP_set(P,x,y)) return 1;
+	}
+	if (typ==0x02 || typ==0x03)
+	{
+		if (ECP_setx(P,x,typ&1)) return 1;
+	}
+    return 0;
+#endif
+}
+
+
+/* Set P=2P */
+/* SU=272 */
+void ZZZ::ECP_dbl(ECP *P)
+{
+#if CURVETYPE_ZZZ==WEIERSTRASS
+    FP t0,t1,t2,t3,x3,y3,z3,b;
+
+//    if (ECP_isinf(P)) return;
+
+	if (CURVE_A==0)
+	{
+		//FP_copy(&t0,&(P->y));				//FP t0=new FP(y);     
+		FP_sqr(&t0,&(P->y));					//t0.sqr();
+		//FP_copy(&t1,&(P->y));				//FP t1=new FP(y);
+		FP_mul(&t1,&(P->y),&(P->z));			//t1.mul(z);
+
+		//FP_copy(&t2,&(P->z));				//FP t2=new FP(z);
+		FP_sqr(&t2,&(P->z));					//t2.sqr();
+
+		//FP_copy(&(P->z),&t0);				//z.copy(t0);
+		FP_add(&(P->z),&t0,&t0);		//z.add(t0); 
+		FP_norm(&(P->z));					//z.norm(); 
+		FP_add(&(P->z),&(P->z),&(P->z));	//z.add(z);  
+		FP_add(&(P->z),&(P->z),&(P->z));	//z.add(z);
+		FP_norm(&(P->z));					//z.norm();
+
+		FP_imul(&t2,&t2,3*CURVE_B_I);		//t2.imul(3*ROM.CURVE_B_I);
+		//FP_copy(&x3,&t2);					//FP x3=new FP(t2);
+		FP_mul(&x3,&t2,&(P->z));			//x3.mul(z);
+
+		//FP_copy(&y3,&t0);					//FP y3=new FP(t0);
+		FP_add(&y3,&t0,&t2);				//y3.add(t2); 
+		FP_norm(&y3);						//y3.norm();
+		FP_mul(&(P->z),&(P->z),&t1);		//z.mul(t1); 
+
+		//FP_copy(&t1,&t2);					//t1.copy(t2);
+		FP_add(&t1,&t2,&t2);				//t1.add(t2);
+		FP_add(&t2,&t2,&t1);				//t2.add(t1);
+		FP_sub(&t0,&t0,&t2);				//t0.sub(t2);
+		FP_norm(&t0);						//t0.norm();
+		FP_mul(&y3,&y3,&t0);				//y3.mul(t0);
+		FP_add(&y3,&y3,&x3);				//y3.add(x3);
+		//FP_copy(&t1,&(P->x));				//t1.copy(x);                *** optimization possible
+		FP_mul(&t1,&(P->x),&(P->y));			//t1.mul(y); 
+		//FP_copy(&(P->x),&t0);				//x.copy(t0);
+		FP_norm(&t0);					//x.norm();
+		FP_mul(&(P->x),&t0,&t1);		//x.mul(t1);
+		FP_add(&(P->x),&(P->x),&(P->x));	//x.add(x);
+		FP_norm(&(P->x));					//x.norm(); 
+		FP_copy(&(P->y),&y3);				//y.copy(y3);
+		FP_norm(&(P->y));					//y.norm();
+	}
+	else // its -3
+	{
+		//FP_copy(&t0,&(P->x));				//FP t0=new FP(x);
+		//FP_copy(&t1,&(P->y));				//FP t1=new FP(y);
+		//FP_copy(&t2,&(P->z));				//FP t2=new FP(z);
+		//FP_copy(&t3,&(P->x));				//FP t3=new FP(x);
+		//FP_copy(&z3,&(P->z));				//FP z3=new FP(z);
+
+		if (CURVE_B_I==0)					//if (ROM.CURVE_B_I==0)
+			FP_rcopy(&b,CURVE_B);		//b.copy(new FP(new BIG(ROM.CURVE_B)));
+
+		FP_sqr(&t0,&(P->x));					//t0.sqr();  //1    x^2
+		FP_sqr(&t1,&(P->y));					//t1.sqr();  //2    y^2
+		FP_sqr(&t2,&(P->z));					//t2.sqr();  //3
+
+		FP_mul(&t3,&(P->x),&(P->y));			//t3.mul(y); //4
+		FP_add(&t3,&t3,&t3);				//t3.add(t3); 
+		FP_norm(&t3);						//t3.norm();//5
+
+		FP_mul(&z3,&(P->z),&(P->x));			//z3.mul(x);   //6
+		FP_add(&z3,&z3,&z3);				//z3.add(z3);  
+		FP_norm(&z3);						//z3.norm();//7
+		//FP_copy(&y3,&t2);					//y3.copy(t2); 
+				
+		if (CURVE_B_I==0)						//if (ROM.CURVE_B_I==0)
+			FP_mul(&y3,&t2,&b);				//y3.mul(b); //8
+		else
+			FP_imul(&y3,&t2,CURVE_B_I);	//y3.imul(ROM.CURVE_B_I);
+				
+		FP_sub(&y3,&y3,&z3);				//y3.sub(z3); //y3.norm(); //9  ***
+		//FP_copy(&x3,&y3);					//x3.copy(y3); 
+		FP_add(&x3,&y3,&y3);				//x3.add(y3); 
+		FP_norm(&x3);						//x3.norm();//10
+
+		FP_add(&y3,&y3,&x3);				//y3.add(x3); //y3.norm();//11
+		//FP_copy(&x3,&t1);					//x3.copy(t1); 
+		FP_sub(&x3,&t1,&y3);				//x3.sub(y3); 
+		FP_norm(&x3);						//x3.norm();//12
+		FP_add(&y3,&y3,&t1);				//y3.add(t1); 
+		FP_norm(&y3);						//y3.norm();//13
+		FP_mul(&y3,&y3,&x3);				//y3.mul(x3); //14
+		FP_mul(&x3,&x3,&t3);				//x3.mul(t3); //15
+		//FP_copy(&t3,&t2);					//t3.copy(t2); 
+		FP_add(&t3,&t2,&t2);				//t3.add(t2);  //16
+		FP_add(&t2,&t2,&t3);				//t2.add(t3); //17
+
+		if (CURVE_B_I==0)					//if (ROM.CURVE_B_I==0)
+			FP_mul(&z3,&z3,&b);				//z3.mul(b); //18
+		else
+			FP_imul(&z3,&z3,CURVE_B_I);	//z3.imul(ROM.CURVE_B_I);
+
+		FP_sub(&z3,&z3,&t2);				//z3.sub(t2); //z3.norm();//19
+		FP_sub(&z3,&z3,&t0);				//z3.sub(t0); 
+		FP_norm(&z3);						//z3.norm();//20  ***
+		//FP_copy(&t3,&z3);					//t3.copy(z3); 
+		FP_add(&t3,&z3,&z3);				//t3.add(z3); //t3.norm();//21
+
+		FP_add(&z3,&z3,&t3);				//z3.add(t3); 
+		FP_norm(&z3);						//z3.norm(); //22
+		//FP_copy(&t3,&t0);					//t3.copy(t0); 
+		FP_add(&t3,&t0,&t0);				//t3.add(t0); //t3.norm(); //23
+		FP_add(&t0,&t0,&t3);				//t0.add(t3); //t0.norm();//24
+		FP_sub(&t0,&t0,&t2);				//t0.sub(t2); 
+		FP_norm(&t0);						//t0.norm();//25
+
+		FP_mul(&t0,&t0,&z3);				//t0.mul(z3);//26
+		FP_add(&y3,&y3,&t0);				//y3.add(t0); //y3.norm();//27
+		//FP_copy(&t0,&(P->y));				//t0.copy(y); 
+		FP_mul(&t0,&(P->y),&(P->z));			//t0.mul(z);//28
+		FP_add(&t0,&t0,&t0);				//t0.add(t0); 
+		FP_norm(&t0);						//t0.norm(); //29
+		FP_mul(&z3,&z3,&t0);				//z3.mul(t0);//30
+		FP_sub(&(P->x),&x3,&z3);				//x3.sub(z3); //x3.norm();//31
+		FP_add(&t0,&t0,&t0);				//t0.add(t0); 
+		FP_norm(&t0);						//t0.norm();//32
+		FP_add(&t1,&t1,&t1);				//t1.add(t1); 
+		FP_norm(&t1);						//t1.norm();//33
+		//FP_copy(&z3,&t0);					//z3.copy(t0); 
+		FP_mul(&(P->z),&t0,&t1);				//z3.mul(t1);//34
+
+		//FP_copy(&(P->x),&x3);				//x.copy(x3); 
+		FP_norm(&(P->x));					//x.norm(); 
+		FP_copy(&(P->y),&y3);				//y.copy(y3); 
+		FP_norm(&(P->y));					//y.norm();
+		//FP_copy(&(P->z),&z3);				//z.copy(z3); 
+		FP_norm(&(P->z));					//z.norm();
+	}
+#endif
+
+#if CURVETYPE_ZZZ==EDWARDS
+    /* Not using square for multiplication swap, as (1) it needs more adds, and (2) it triggers more reductions */
+
+	FP C,D,H,J;
+
+//	if (ECP_isinf(P)) return;
+
+	//FP_copy(&C,&(P->x));			//FP C=new FP(x);
+	FP_sqr(&C,&(P->x));							//C.sqr();
+	//FP_copy(&D,&(P->y));			//FP D=new FP(y);
+	//FP_copy(&H,&(P->z));			//FP H=new FP(z);
+
+	FP_mul(&(P->x),&(P->x),&(P->y));		//x.mul(y); 
+	FP_add(&(P->x),&(P->x),&(P->x));		//x.add(x); 
+	FP_norm(&(P->x));						//x.norm();
+	
+	FP_sqr(&D,&(P->y));							//D.sqr();
+
+	if (CURVE_A==-1)				//if (ROM.CURVE_A==-1) 
+		FP_neg(&C,&C);				//	C.neg();	
+
+	//FP_copy(&(P->y),&C);			//y.copy(C); 
+	FP_add(&(P->y),&C,&D);		//y.add(D); 
+	FP_norm(&(P->y));				//y.norm();
+	FP_sqr(&H,&(P->z));					//H.sqr(); 
+	FP_add(&H,&H,&H);				//H.add(H);
+
+
+	//FP_copy(&(P->z),&(P->y));		//z.copy(y);
+	//FP_copy(&J,&(P->y));			//J.copy(y); 
+
+	FP_sub(&J,&(P->y),&H);				//J.sub(H); 
+	FP_norm(&J);					//J.norm();
+
+	FP_mul(&(P->x),&(P->x),&J);		//x.mul(J);
+	FP_sub(&C,&C,&D);				//C.sub(D); 
+	FP_norm(&C);					//C.norm();
+	FP_mul(&(P->z),&(P->y),&J);		//z.mul(J);
+	FP_mul(&(P->y),&(P->y),&C);		//y.mul(C);
+
+
+#endif
+
+#if CURVETYPE_ZZZ==MONTGOMERY
+	FP A,B,AA,BB,C;
+
+//    if (ECP_isinf(P)) return;
+
+	//FP_copy(&A,&(P->x));			//FP A=new FP(x);
+	//FP_copy(&B,&(P->x));			//FP B=new FP(x);		
+			
+	FP_add(&A,&(P->x),&(P->z));			//A.add(z); 
+	FP_norm(&A);					//A.norm();
+	//FP_copy(&AA,&A);				//AA.copy(A); 
+	FP_sqr(&AA,&A);				//AA.sqr();
+	FP_sub(&B,&(P->x),&(P->z));			//B.sub(z); 
+	FP_norm(&B);					//B.norm();
+	//FP_copy(&BB,&B);				//BB.copy(B); 
+	FP_sqr(&BB,&B);				//BB.sqr();
+	//FP_copy(&C,&AA);				//C.copy(AA); 
+	FP_sub(&C,&AA,&BB);				//C.sub(BB); 
+	FP_norm(&C);					//C.norm();
+	//FP_copy(&(P->x),&AA);			//x.copy(AA); 
+	FP_mul(&(P->x),&AA,&BB);	//x.mul(BB);
+
+	//FP_copy(&A,&C);					//A.copy(C); 
+	FP_imul(&A,&C,(CURVE_A+2)/4);	//A.imul((ROM.CURVE_A+2)/4);
+
+	FP_add(&BB,&BB,&A);				//BB.add(A); 
+	FP_norm(&BB);					//BB.norm();
+	//FP_copy(&(P->z),&BB);			//z.copy(BB); 
+	FP_mul(&(P->z),&BB,&C);		//z.mul(C);
+
+#endif
+}
+
+#if CURVETYPE_ZZZ==MONTGOMERY
+
+/* Set P+=Q. W is difference between P and Q and is affine */
+void ZZZ::ECP_add(ECP *P,ECP *Q,ECP *W)
+{
+	FP A,B,C,D,DA,CB;
+
+	//FP_copy(&A,&(P->x));	//FP A=new FP(x);
+	//FP_copy(&B,&(P->x));	//FP B=new FP(x);
+	//FP_copy(&C,&(Q->x));	//FP C=new FP(Q.x);
+	//FP_copy(&D,&(Q->x));	//FP D=new FP(Q.x);
+			
+	FP_add(&A,&(P->x),&(P->z));	//A.add(z); 
+	FP_sub(&B,&(P->x),&(P->z));	//B.sub(z); 
+
+	FP_add(&C,&(Q->x),&(Q->z));	//C.add(Q.z);
+
+	FP_sub(&D,&(Q->x),&(Q->z));	//D.sub(Q.z);
+	FP_norm(&A);			//A.norm();
+
+	FP_norm(&D);			//D.norm();
+	//FP_copy(&DA,&D);			//DA.copy(D); 
+	FP_mul(&DA,&D,&A);			//DA.mul(A);
+
+
+
+	FP_norm(&C);			//C.norm();
+	FP_norm(&B);			//B.norm();
+	//FP_copy(&CB,&C);		//CB.copy(C); 
+	FP_mul(&CB,&C,&B);		//CB.mul(B);
+
+	//FP_copy(&A,&DA);		//A.copy(DA); 
+	FP_add(&A,&DA,&CB);		//A.add(CB); 
+	FP_norm(&A);			//A.norm(); 
+	FP_sqr(&(P->x),&A);			//A.sqr();
+	//FP_copy(&B,&DA);		//B.copy(DA); 
+	FP_sub(&B,&DA,&CB);		//B.sub(CB); 
+	FP_norm(&B);			//B.norm(); 
+	FP_sqr(&B,&B);			//B.sqr();
+
+	//FP_copy(&(P->x),&A);	//x.copy(A);
+	//FP_copy(&(P->z),&(W->x));//z.copy(W.x); 
+	FP_mul(&(P->z),&(W->x),&B);	//z.mul(B);
+
+}
+
+#else
+
+/* Set P+=Q */
+/* SU=248 */
+void ZZZ::ECP_add(ECP *P,ECP *Q)
+{
+#if CURVETYPE_ZZZ==WEIERSTRASS
+
+	int b3;
+	FP t0,t1,t2,t3,t4,x3,y3,z3,b;
+/*
+    if (ECP_isinf(Q)) return;
+    if (ECP_isinf(P))
+    {
+        ECP_copy(P,Q);
+        return;
+    }
+*/
+	if (CURVE_A==0)
+	{
+		b3=3*CURVE_B_I;					//int b=3*ROM.CURVE_B_I;
+		//FP_copy(&t0,&(P->x));			//FP t0=new FP(x);
+		FP_mul(&t0,&(P->x),&(Q->x));		//t0.mul(Q.x);
+		//FP_copy(&t1,&(P->y));			//FP t1=new FP(y);
+		FP_mul(&t1,&(P->y),&(Q->y));		//t1.mul(Q.y);
+		//FP_copy(&t2,&(P->z));			//FP t2=new FP(z);
+		FP_mul(&t2,&(P->z),&(Q->z));		//t2.mul(Q.z);
+		//FP_copy(&t3,&(P->x));			//FP t3=new FP(x);
+		FP_add(&t3,&(P->x),&(P->y));		//t3.add(y); 
+		FP_norm(&t3);					//t3.norm();
+		//FP_copy(&t4,&(Q->x));			//FP t4=new FP(Q.x);
+		FP_add(&t4,&(Q->x),&(Q->y));		//t4.add(Q.y); 
+		FP_norm(&t4);					//t4.norm();
+		FP_mul(&t3,&t3,&t4);			//t3.mul(t4);
+		//FP_copy(&t4,&t0);				//t4.copy(t0); 
+		FP_add(&t4,&t0,&t1);			//t4.add(t1);
+
+		FP_sub(&t3,&t3,&t4);			//t3.sub(t4); 
+		FP_norm(&t3);					//t3.norm();
+		//FP_copy(&t4,&(P->y));			//t4.copy(y);
+		FP_add(&t4,&(P->y),&(P->z));		//t4.add(z); 
+		FP_norm(&t4);					//t4.norm();
+		//FP_copy(&x3,&(Q->y));			//FP x3=new FP(Q.y);
+		FP_add(&x3,&(Q->y),&(Q->z));		//x3.add(Q.z); 
+		FP_norm(&x3);					//x3.norm();
+
+		FP_mul(&t4,&t4,&x3);			//t4.mul(x3);
+		//FP_copy(&x3,&t1);				//x3.copy(t1);
+		FP_add(&x3,&t1,&t2);			//x3.add(t2);
+
+		FP_sub(&t4,&t4,&x3);			//t4.sub(x3); 
+		FP_norm(&t4);					//t4.norm();
+		//FP_copy(&x3,&(P->x));			//x3.copy(x); 
+		FP_add(&x3,&(P->x),&(P->z));		//x3.add(z); 
+		FP_norm(&x3);					//x3.norm();
+		//FP_copy(&y3,&(Q->x));			//FP y3=new FP(Q.x);
+		FP_add(&y3,&(Q->x),&(Q->z));		//y3.add(Q.z); 
+		FP_norm(&y3);					//y3.norm();
+		FP_mul(&x3,&x3,&y3);			//x3.mul(y3);
+		//FP_copy(&y3,&t0);				//y3.copy(t0);
+		FP_add(&y3,&t0,&t2);			//y3.add(t2);
+		FP_sub(&y3,&x3,&y3);			//y3.rsub(x3); 
+		FP_norm(&y3);					//y3.norm();
+		//FP_copy(&x3,&t0);				//x3.copy(t0); 
+		FP_add(&x3,&t0,&t0);			//x3.add(t0); 
+		FP_add(&t0,&t0,&x3);			//t0.add(x3); 
+		FP_norm(&t0);					//t0.norm();
+		FP_imul(&t2,&t2,b3);				//t2.imul(b);
+
+		//FP_copy(&z3,&t1);				//FP z3=new FP(t1); 
+		FP_add(&z3,&t1,&t2);			//z3.add(t2); 
+		FP_norm(&z3);					//z3.norm();
+		FP_sub(&t1,&t1,&t2);			//t1.sub(t2); 
+		FP_norm(&t1);					//t1.norm(); 
+		FP_imul(&y3,&y3,b3);				//y3.imul(b);
+	
+		//FP_copy(&x3,&y3);				//x3.copy(y3); 
+		FP_mul(&x3,&y3,&t4);			//x3.mul(t4); 
+		//FP_copy(&t2,&t3);				//t2.copy(t3); 
+		FP_mul(&t2,&t3,&t1);			//t2.mul(t1); 
+		FP_sub(&(P->x),&t2,&x3);			//x3.rsub(t2);
+		FP_mul(&y3,&y3,&t0);			//y3.mul(t0); 
+		FP_mul(&t1,&t1,&z3);			//t1.mul(z3); 
+		FP_add(&(P->y),&y3,&t1);			//y3.add(t1);
+		FP_mul(&t0,&t0,&t3);			//t0.mul(t3); 
+		FP_mul(&z3,&z3,&t4);			//z3.mul(t4); 
+		FP_add(&(P->z),&z3,&t0);			//z3.add(t0);
+
+		//FP_copy(&(P->x),&x3);			//x.copy(x3); 
+		FP_norm(&(P->x));				//x.norm(); 
+		//FP_copy(&(P->y),&y3);			//y.copy(y3); 
+		FP_norm(&(P->y));				//y.norm();
+		//FP_copy(&(P->z),&z3);			//z.copy(z3); 
+		FP_norm(&(P->z));				//z.norm();
+	}
+	else
+	{
+		//FP_copy(&t0,&(P->x));			//FP t0=new FP(x);
+		//FP_copy(&t1,&(P->y));			//FP t1=new FP(y);
+		//FP_copy(&t2,&(P->z));			//FP t2=new FP(z);
+		//FP_copy(&t3,&(P->x));			//FP t3=new FP(x);
+		//FP_copy(&t4,&(Q->x));			//FP t4=new FP(Q.x);
+
+		//FP_copy(&y3,&(Q->x));			//FP y3=new FP(Q.x);
+		//FP_copy(&x3,&(Q->y));			//FP x3=new FP(Q.y);
+
+		if (CURVE_B_I==0)				//if (ROM.CURVE_B_I==0)
+			FP_rcopy(&b,CURVE_B);	//b.copy(new FP(new BIG(ROM.CURVE_B)));
+
+		FP_mul(&t0,&(P->x),&(Q->x));		//t0.mul(Q.x); //1
+		FP_mul(&t1,&(P->y),&(Q->y));		//t1.mul(Q.y); //2
+		FP_mul(&t2,&(P->z),&(Q->z));		//t2.mul(Q.z); //3
+
+		FP_add(&t3,&(P->x),&(P->y));		//t3.add(y); 
+		FP_norm(&t3);					//t3.norm(); //4
+		FP_add(&t4,&(Q->x),&(Q->y));		//t4.add(Q.y); 
+		FP_norm(&t4);					//t4.norm();//5
+		FP_mul(&t3,&t3,&t4);			//t3.mul(t4);//6
+		//FP_copy(&t4,&t0);				//t4.copy(t0); 
+		FP_add(&t4,&t0,&t1);			//t4.add(t1); //t4.norm(); //7
+		FP_sub(&t3,&t3,&t4);			//t3.sub(t4); 
+		FP_norm(&t3);					//t3.norm(); //8
+		//FP_copy(&t4,&(P->y));			//t4.copy(y); 
+		FP_add(&t4,&(P->y),&(P->z));		//t4.add(z); 
+		FP_norm(&t4);					//t4.norm();//9
+		FP_add(&x3,&(Q->y),&(Q->z));		//x3.add(Q.z); 
+		FP_norm(&x3);					//x3.norm();//10
+		FP_mul(&t4,&t4,&x3);			//t4.mul(x3); //11
+		//FP_copy(&x3,&t1);				//x3.copy(t1); 
+		FP_add(&x3,&t1,&t2);			//x3.add(t2); //x3.norm();//12
+
+		FP_sub(&t4,&t4,&x3);			//t4.sub(x3); 
+		FP_norm(&t4);					//t4.norm();//13
+		//FP_copy(&x3,&(P->x));			//x3.copy(x); 
+		FP_add(&x3,&(P->x),&(P->z));		//x3.add(z); 
+		FP_norm(&x3);					//x3.norm(); //14
+		FP_add(&y3,&(Q->x),&(Q->z));		//y3.add(Q.z); 
+		FP_norm(&y3);					//y3.norm();//15
+
+		FP_mul(&x3,&x3,&y3);			//x3.mul(y3); //16
+		//FP_copy(&y3,&t0);				//y3.copy(t0); 
+		FP_add(&y3,&t0,&t2);			//y3.add(t2); //y3.norm();//17
+
+		FP_sub(&y3,&x3,&y3);			//y3.rsub(x3); 
+		FP_norm(&y3);					//y3.norm(); //18
+		//FP_copy(&z3,&t2);				//z3.copy(t2); 		
+
+		if (CURVE_B_I==0)				//if (ROM.CURVE_B_I==0)
+			FP_mul(&z3,&t2,&b);			//z3.mul(b); //18
+		else
+			FP_imul(&z3,&t2,CURVE_B_I);	//z3.imul(ROM.CURVE_B_I);
+				
+		//FP_copy(&x3,&y3);				//x3.copy(y3); 
+		FP_sub(&x3,&y3,&z3);			//x3.sub(z3); 
+		FP_norm(&x3);					//x3.norm(); //20
+		//FP_copy(&z3,&x3);				//z3.copy(x3); 
+		FP_add(&z3,&x3,&x3);			//z3.add(x3); //z3.norm(); //21
+
+		FP_add(&x3,&x3,&z3);			//x3.add(z3); //x3.norm(); //22
+		//FP_copy(&z3,&t1);				//z3.copy(t1); 
+		FP_sub(&z3,&t1,&x3);			//z3.sub(x3); 
+		FP_norm(&z3);					//z3.norm(); //23
+		FP_add(&x3,&x3,&t1);			//x3.add(t1); 
+		FP_norm(&x3);					//x3.norm(); //24
+
+		if (CURVE_B_I==0)				//if (ROM.CURVE_B_I==0)
+			FP_mul(&y3,&y3,&b);			//y3.mul(b); //18
+		else
+			FP_imul(&y3,&y3,CURVE_B_I);	//y3.imul(ROM.CURVE_B_I);
+
+		//FP_copy(&t1,&t2);				//t1.copy(t2); 
+		FP_add(&t1,&t2,&t2);			//t1.add(t2); //t1.norm();//26
+		FP_add(&t2,&t2,&t1);			//t2.add(t1); //t2.norm();//27
+
+		FP_sub(&y3,&y3,&t2);			//y3.sub(t2); //y3.norm(); //28
+
+		FP_sub(&y3,&y3,&t0);			//y3.sub(t0); 
+		FP_norm(&y3);					//y3.norm(); //29
+		//FP_copy(&t1,&y3);				//t1.copy(y3); 
+		FP_add(&t1,&y3,&y3);			//t1.add(y3); //t1.norm();//30
+		FP_add(&y3,&y3,&t1);			//y3.add(t1); 
+		FP_norm(&y3);					//y3.norm(); //31
+
+		//FP_copy(&t1,&t0);				//t1.copy(t0); 
+		FP_add(&t1,&t0,&t0);			//t1.add(t0); //t1.norm(); //32
+		FP_add(&t0,&t0,&t1);			//t0.add(t1); //t0.norm();//33
+		FP_sub(&t0,&t0,&t2);			//t0.sub(t2); 
+		FP_norm(&t0);					//t0.norm();//34
+		//FP_copy(&t1,&t4);				//t1.copy(t4); 
+		FP_mul(&t1,&t4,&y3);			//t1.mul(y3);//35
+		//FP_copy(&t2,&t0);				//t2.copy(t0); 
+		FP_mul(&t2,&t0,&y3);			//t2.mul(y3);//36
+		//FP_copy(&y3,&x3);				//y3.copy(x3); 
+		FP_mul(&y3,&x3,&z3);			//y3.mul(z3);//37
+		FP_add(&(P->y),&y3,&t2);			//y3.add(t2); //y3.norm();//38
+		FP_mul(&x3,&x3,&t3);			//x3.mul(t3);//39
+		FP_sub(&(P->x),&x3,&t1);			//x3.sub(t1);//40
+		FP_mul(&z3,&z3,&t4);			//z3.mul(t4);//41
+		//FP_copy(&t1,&t3);				//t1.copy(t3); 
+		FP_mul(&t1,&t3,&t0);			//t1.mul(t0);//42
+		FP_add(&(P->z),&z3,&t1);			//z3.add(t1); 
+		//FP_copy(&(P->x),&x3);			//x.copy(x3); 
+		FP_norm(&(P->x));				//x.norm(); 
+		//FP_copy(&(P->y),&y3);			//y.copy(y3); 
+		FP_norm(&(P->y));				//y.norm();
+		//FP_copy(&(P->z),&z3);			//z.copy(z3); 
+		FP_norm(&(P->z));				//z.norm();
+	}
+
+#else
+	FP A,B,C,D,E,F,G,b;
+
+/*		
+    if (ECP_isinf(Q)) return;
+    if (ECP_isinf(P))
+    {
+        ECP_copy(P,Q);
+        return;
+    }
+*/
+
+	//FP_copy(&A,&(P->z));		//FP A=new FP(z);
+	//FP_copy(&C,&(P->x));		//FP C=new FP(x);
+	//FP_copy(&D,&(P->y));		//FP D=new FP(y);
+
+	FP_mul(&A,&(P->z),&(Q->z));		//A.mul(Q.z);   
+	//FP_copy(&B,&A);				//B.copy(A); 
+	FP_sqr(&B,&A);				//B.sqr();    
+	FP_mul(&C,&(P->x),&(Q->x));		//C.mul(Q.x);      
+	FP_mul(&D,&(P->y),&(Q->y));		//D.mul(Q.y); 
+
+	//FP_copy(&E,&C);				//E.copy(C); 
+	FP_mul(&E,&C,&D);			//E.mul(D);  
+		
+	if (CURVE_B_I==0)			//if (ROM.CURVE_B_I==0)
+	{
+		FP_rcopy(&b,CURVE_B);	//FP b=new FP(new BIG(ROM.CURVE_B));
+		FP_mul(&E,&E,&b);			//E.mul(b);
+	}
+	else
+		FP_imul(&E,&E,CURVE_B_I);	//E.imul(ROM.CURVE_B_I); 
+
+	//FP_copy(&F,&B);				//F.copy(B); 
+	FP_sub(&F,&B,&E);			//F.sub(E);      
+	//FP_copy(&G,&B);				//G.copy(B); 
+	FP_add(&G,&B,&E);			//G.add(E);       
+
+	if (CURVE_A==1)				//if (ROM.CURVE_A==1)
+	{
+		//FP_copy(&E,&D);			//E.copy(D); 
+		FP_sub(&E,&D,&C);		//E.sub(C);
+	}
+	FP_add(&C,&C,&D);			//C.add(D); 
+
+	//FP_copy(&B,&(P->x));		//B.copy(x); 
+	FP_add(&B,&(P->x),&(P->y));		//B.add(y);    
+	//FP_copy(&D,&(Q->x));		//D.copy(Q.x); 
+	FP_add(&D,&(Q->x),&(Q->y));		//D.add(Q.y); 
+	FP_norm(&B);				//B.norm(); 
+	FP_norm(&D);				//D.norm(); 
+	FP_mul(&B,&B,&D);			//B.mul(D);                   
+	FP_sub(&B,&B,&C);			//B.sub(C); 
+	FP_norm(&B);				//B.norm(); 
+	FP_norm(&F);				//F.norm(); 
+	FP_mul(&B,&B,&F);			//B.mul(F);                     
+	//FP_copy(&(P->x),&A);		//x.copy(A); 
+	FP_mul(&(P->x),&A,&B); //x.mul(B); 
+	FP_norm(&G);				//G.norm();  
+			
+	if (CURVE_A==1)				//if (ROM.CURVE_A==1)
+	{
+		FP_norm(&E);			//E.norm(); 
+		//FP_copy(&C,&E);			//C.copy(E); 
+		FP_mul(&C,&E,&G);		//C.mul(G);  
+	}
+	if (CURVE_A==-1)			//if (ROM.CURVE_A==-1)
+	{
+		FP_norm(&C);			//C.norm(); 
+		FP_mul(&C,&C,&G);		//C.mul(G);
+	}
+	//FP_copy(&(P->y),&A);		//y.copy(A); 
+	FP_mul(&(P->y),&A,&C);	//y.mul(C);     
+
+	//FP_copy(&(P->z),&F);		//z.copy(F);	
+	FP_mul(&(P->z),&F,&G);	//z.mul(G);
+
+#endif
+}
+
+/* Set P-=Q */
+/* SU=16 */
+void  ZZZ::ECP_sub(ECP *P,ECP *Q)
+{
+	ECP NQ;
+	ECP_copy(&NQ,Q);
+	ECP_neg(&NQ);
+    //ECP_neg(Q);
+    ECP_add(P,&NQ);
+    //ECP_neg(Q);
+}
+
+#endif
+
+#if CURVETYPE_ZZZ!=MONTGOMERY
+/* constant time multiply by small integer of length bts - use ladder */
+void ZZZ::ECP_pinmul(ECP *P,int e,int bts)
+{
+    int i,b;
+    ECP R0,R1;
+
+    ECP_affine(P);
+    ECP_inf(&R0);
+    ECP_copy(&R1,P);
+
+    for (i=bts-1; i>=0; i--)
+    {
+        b=(e>>i)&1;
+        ECP_copy(P,&R1);
+        ECP_add(P,&R0);
+        ECP_cswap(&R0,&R1,b);
+        ECP_copy(&R1,P);
+        ECP_dbl(&R0);
+        ECP_cswap(&R0,&R1,b);
+    }
+    ECP_copy(P,&R0);
+    ECP_affine(P);
+}
+#endif
+
+/* Set P=r*P */
+/* SU=424 */
+void ZZZ::ECP_mul(ECP *P,BIG e)
+{
+#if CURVETYPE_ZZZ==MONTGOMERY
+    /* Montgomery ladder */
+    int nb,i,b;
+    ECP R0,R1,D;
+    if (ECP_isinf(P)) return;
+    if (BIG_iszilch(e))
+    {
+        ECP_inf(P);
+        return;
+    }
+    //ECP_affine(P);
+
+    ECP_copy(&R0,P);
+    ECP_copy(&R1,P);
+    ECP_dbl(&R1);
+
+    ECP_copy(&D,P); ECP_affine(&D);
+
+    nb=BIG_nbits(e);
+    for (i=nb-2; i>=0; i--)
+    {
+        b=BIG_bit(e,i);
+        ECP_copy(P,&R1);
+        ECP_add(P,&R0,&D);
+        ECP_cswap(&R0,&R1,b);
+        ECP_copy(&R1,P);
+        ECP_dbl(&R0);
+
+        ECP_cswap(&R0,&R1,b);
+    }
+
+    ECP_copy(P,&R0);
+
+#else
+    /* fixed size windows */
+    int i,nb,s,ns;
+    BIG mt,t;
+    ECP Q,W[8],C;
+    sign8 w[1+(NLEN_XXX*BASEBITS_XXX+3)/4];
+
+    if (ECP_isinf(P)) return;
+    if (BIG_iszilch(e))
+    {
+        ECP_inf(P);
+        return;
+    }
+
+    //ECP_affine(P);
+
+    /* precompute table */
+
+    ECP_copy(&Q,P);
+    ECP_dbl(&Q);
+
+    ECP_copy(&W[0],P);
+
+    for (i=1; i<8; i++)
+    {
+        ECP_copy(&W[i],&W[i-1]);
+        ECP_add(&W[i],&Q);
+    }
+
+//printf("W[1]= ");ECP_output(&W[1]); printf("\n");
+
+    /* make exponent odd - add 2P if even, P if odd */
+    BIG_copy(t,e);
+    s=BIG_parity(t);
+    BIG_inc(t,1);
+    BIG_norm(t);
+    ns=BIG_parity(t);
+    BIG_copy(mt,t);
+    BIG_inc(mt,1);
+    BIG_norm(mt);
+    BIG_cmove(t,mt,s);
+    ECP_cmove(&Q,P,ns);
+    ECP_copy(&C,&Q);
+
+    nb=1+(BIG_nbits(t)+3)/4;
+
+    /* convert exponent to signed 4-bit window */
+    for (i=0; i<nb; i++)
+    {
+        w[i]=BIG_lastbits(t,5)-16;
+        BIG_dec(t,w[i]);
+        BIG_norm(t);
+        BIG_fshr(t,4);
+    }
+    w[nb]=BIG_lastbits(t,5);
+
+    ECP_copy(P,&W[(w[nb]-1)/2]);
+    for (i=nb-1; i>=0; i--)
+    {
+        ECP_select(&Q,W,w[i]);
+        ECP_dbl(P);
+        ECP_dbl(P);
+        ECP_dbl(P);
+        ECP_dbl(P);
+        ECP_add(P,&Q);
+    }
+    ECP_sub(P,&C); /* apply correction */
+#endif
+    ECP_affine(P);
+}
+
+#if CURVETYPE_ZZZ!=MONTGOMERY
+/* Set P=eP+fQ double multiplication */
+/* constant time - as useful for GLV method in pairings */
+/* SU=456 */
+
+void ZZZ::ECP_mul2(ECP *P,ECP *Q,BIG e,BIG f)
+{
+    BIG te,tf,mt;
+    ECP S,T,W[8],C;
+    sign8 w[1+(NLEN_XXX*BASEBITS_XXX+1)/2];
+    int i,a,b,s,ns,nb;
+
+    //ECP_affine(P);
+    //ECP_affine(Q);
+
+    BIG_copy(te,e);
+    BIG_copy(tf,f);
+
+    /* precompute table */
+    ECP_copy(&W[1],P);
+    ECP_sub(&W[1],Q);  /* P+Q */
+    ECP_copy(&W[2],P);
+    ECP_add(&W[2],Q);  /* P-Q */
+    ECP_copy(&S,Q);
+    ECP_dbl(&S);  /* S=2Q */
+    ECP_copy(&W[0],&W[1]);
+    ECP_sub(&W[0],&S);
+    ECP_copy(&W[3],&W[2]);
+    ECP_add(&W[3],&S);
+    ECP_copy(&T,P);
+    ECP_dbl(&T); /* T=2P */
+    ECP_copy(&W[5],&W[1]);
+    ECP_add(&W[5],&T);
+    ECP_copy(&W[6],&W[2]);
+    ECP_add(&W[6],&T);
+    ECP_copy(&W[4],&W[5]);
+    ECP_sub(&W[4],&S);
+    ECP_copy(&W[7],&W[6]);
+    ECP_add(&W[7],&S);
+
+    /* if multiplier is odd, add 2, else add 1 to multiplier, and add 2P or P to correction */
+
+    s=BIG_parity(te);
+    BIG_inc(te,1);
+    BIG_norm(te);
+    ns=BIG_parity(te);
+    BIG_copy(mt,te);
+    BIG_inc(mt,1);
+    BIG_norm(mt);
+    BIG_cmove(te,mt,s);
+    ECP_cmove(&T,P,ns);
+    ECP_copy(&C,&T);
+
+    s=BIG_parity(tf);
+    BIG_inc(tf,1);
+    BIG_norm(tf);
+    ns=BIG_parity(tf);
+    BIG_copy(mt,tf);
+    BIG_inc(mt,1);
+    BIG_norm(mt);
+    BIG_cmove(tf,mt,s);
+    ECP_cmove(&S,Q,ns);
+    ECP_add(&C,&S);
+
+    BIG_add(mt,te,tf);
+    BIG_norm(mt);
+    nb=1+(BIG_nbits(mt)+1)/2;
+
+    /* convert exponent to signed 2-bit window */
+    for (i=0; i<nb; i++)
+    {
+        a=BIG_lastbits(te,3)-4;
+        BIG_dec(te,a);
+        BIG_norm(te);
+        BIG_fshr(te,2);
+        b=BIG_lastbits(tf,3)-4;
+        BIG_dec(tf,b);
+        BIG_norm(tf);
+        BIG_fshr(tf,2);
+        w[i]=4*a+b;
+    }
+    w[nb]=(4*BIG_lastbits(te,3)+BIG_lastbits(tf,3));
+
+    ECP_copy(P,&W[(w[nb]-1)/2]);
+    for (i=nb-1; i>=0; i--)
+    {
+        ECP_select(&T,W,w[i]);
+        ECP_dbl(P);
+        ECP_dbl(P);
+        ECP_add(P,&T);
+    }
+    ECP_sub(P,&C); /* apply correction */
+    ECP_affine(P);
+}
+
+#endif
+
+void ZZZ::ECP_cfp(ECP *P)
+{ /* multiply point by curves cofactor */
+	BIG c;
+	int cf=CURVE_Cof_I;
+	if (cf==1) return;
+	if (cf==4)
+	{
+		ECP_dbl(P);
+		ECP_dbl(P);
+		//ECP_affine(P);
+		return;
+	}
+	if (cf==8)
+	{
+		ECP_dbl(P);
+		ECP_dbl(P);
+		ECP_dbl(P);
+		//ECP_affine(P);
+		return;
+	}
+	BIG_rcopy(c,CURVE_Cof);
+	ECP_mul(P,c);
+	return;
+}
+
+/* map BIG to point on curve of correct order */
+/* The BIG should be the output of some hash function */
+
+void ZZZ::ECP_mapit(ECP *P,octet *W)
+{
+    BIG q,x;
+	BIG_fromBytes(x,W->val);
+    BIG_rcopy(q,Modulus);
+    BIG_mod(x,q);
+
+	for (;;)
+	{
+		for (;;)
+		{
+#if CURVETYPE_ZZZ!=MONTGOMERY
+			ECP_setx(P,x,0);
+#else
+			ECP_set(P,x);
+#endif
+			BIG_inc(x,1); BIG_norm(x);
+			if (!ECP_isinf(P)) break;
+		}
+		ECP_cfp(P);
+		if (!ECP_isinf(P)) break;
+	}
+}
+
+void ZZZ::ECP_generator(ECP *G)
+{
+	BIG x,y;
+	BIG_rcopy(x,CURVE_Gx);
+#if CURVETYPE_ZZZ!=MONTGOMERY
+	BIG_rcopy(y,CURVE_Gy);
+    ECP_set(G,x,y);
+#else
+    ECP_set(G,x);
+#endif
+}
+
+#ifdef HAS_MAIN
+
+using namespace ZZZ;
+
+int main()
+{
+    int i;
+    ECP G,P;
+    csprng RNG;
+    BIG r,s,x,y,b,m,w,q;
+    BIG_rcopy(x,CURVE_Gx);
+#if CURVETYPE_ZZZ!=MONTGOMERY
+    BIG_rcopy(y,CURVE_Gy);
+#endif
+    BIG_rcopy(m,Modulus);
+
+    printf("x= ");
+    BIG_output(x);
+    printf("\n");
+#if CURVETYPE_ZZZ!=MONTGOMERY
+    printf("y= ");
+    BIG_output(y);
+    printf("\n");
+#endif
+    RNG_seed(&RNG,3,"abc");
+
+#if CURVETYPE_ZZZ!=MONTGOMERY
+    ECP_set(&G,x,y);
+#else
+    ECP_set(&G,x);
+#endif
+    if (ECP_isinf(&G)) printf("Failed to set - point not on curve\n");
+    else printf("set success\n");
+
+    ECP_output(&G);
+
+    BIG_rcopy(r,CURVE_Order); //BIG_dec(r,7);
+    printf("r= ");
+    BIG_output(r);
+    printf("\n");
+
+    ECP_copy(&P,&G);
+
+    ECP_mul(&P,r);
+
+    ECP_output(&P);
+//exit(0);
+    BIG_randomnum(w,&RNG);
+    BIG_mod(w,r);
+
+    ECP_copy(&P,&G);
+    ECP_mul(&P,w);
+
+    ECP_output(&P);
+
+    return 0;
+}
+
+#endif
diff --git a/version3/cpp/ecp.h b/version3/cpp/ecp.h
new file mode 100644
index 0000000..fc7c901
--- /dev/null
+++ b/version3/cpp/ecp.h
@@ -0,0 +1,293 @@
+#ifndef ECP_ZZZ_H
+#define ECP_ZZZ_H
+
+#include "fp_YYY.h"
+#include "config_curve_ZZZ.h"
+
+using namespace amcl;
+
+namespace ZZZ {
+
+/* Curve Params - see rom.c */
+extern const int CURVE_A;     /**< Elliptic curve A parameter */
+extern const int CURVE_B_I;
+extern const int CURVE_Cof_I;
+extern const XXX::BIG CURVE_B;     /**< Elliptic curve B parameter */
+extern const XXX::BIG CURVE_Order; /**< Elliptic curve group order */
+extern const XXX::BIG CURVE_Cof;   /**< Elliptic curve cofactor */
+
+/* Generator point on G1 */
+extern const XXX::BIG CURVE_Gx; /**< x-coordinate of generator point in group G1  */
+extern const XXX::BIG CURVE_Gy; /**< y-coordinate of generator point in group G1  */
+
+
+/* For Pairings only */
+
+/* Generator point on G2 */
+extern const XXX::BIG CURVE_Pxa; /**< real part of x-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pxb; /**< imaginary part of x-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pya; /**< real part of y-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pyb; /**< imaginary part of y-coordinate of generator point in group G2 */
+
+/*** needed for BLS24 curves ***/
+
+extern const XXX::BIG CURVE_Pxaa; /**< real part of x-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pxab; /**< imaginary part of x-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pxba; /**< real part of x-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pxbb; /**< imaginary part of x-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pyaa; /**< real part of y-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pyab; /**< imaginary part of y-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pyba; /**< real part of y-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pybb; /**< imaginary part of y-coordinate of generator point in group G2 */
+
+/*** needed for BLS48 curves ***/
+
+extern const XXX::BIG CURVE_Pxaaa; /**< real part of x-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pxaab; /**< imaginary part of x-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pxaba; /**< real part of x-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pxabb; /**< imaginary part of x-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pxbaa; /**< real part of x-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pxbab; /**< imaginary part of x-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pxbba; /**< real part of x-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pxbbb; /**< imaginary part of x-coordinate of generator point in group G2 */
+
+extern const XXX::BIG CURVE_Pyaaa; /**< real part of y-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pyaab; /**< imaginary part of y-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pyaba; /**< real part of y-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pyabb; /**< imaginary part of y-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pybaa; /**< real part of y-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pybab; /**< imaginary part of y-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pybba; /**< real part of y-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pybbb; /**< imaginary part of y-coordinate of generator point in group G2 */
+
+
+
+extern const XXX::BIG CURVE_Bnx; /**< BN curve x parameter */
+
+extern const XXX::BIG CURVE_Cru; /**< BN curve Cube Root of Unity */
+
+extern const XXX::BIG Fra; /**< real part of BN curve Frobenius Constant */
+extern const XXX::BIG Frb; /**< imaginary part of BN curve Frobenius Constant */
+
+
+extern const XXX::BIG CURVE_W[2];	 /**< BN curve constant for GLV decomposition */
+extern const XXX::BIG CURVE_SB[2][2]; /**< BN curve constant for GLV decomposition */
+extern const XXX::BIG CURVE_WB[4];	 /**< BN curve constant for GS decomposition */
+extern const XXX::BIG CURVE_BB[4][4]; /**< BN curve constant for GS decomposition */
+
+
+/**
+	@brief ECP structure - Elliptic Curve Point over base field
+*/
+
+typedef struct
+{
+//    int inf; /**< Infinity Flag - not needed for Edwards representation */
+
+    YYY::FP x; /**< x-coordinate of point */
+#if CURVETYPE_ZZZ!=MONTGOMERY
+    YYY::FP y; /**< y-coordinate of point. Not needed for Montgomery representation */
+#endif
+    YYY::FP z;/**< z-coordinate of point */
+} ECP;
+
+
+/* ECP E(Fp) prototypes */
+/**	@brief Tests for ECP point equal to infinity
+ *
+	@param P ECP point to be tested
+	@return 1 if infinity, else returns 0
+ */
+extern int ECP_isinf(ECP *P);
+/**	@brief Tests for equality of two ECPs
+ *
+	@param P ECP instance to be compared
+	@param Q ECP instance to be compared
+	@return 1 if P=Q, else returns 0
+ */
+extern int ECP_equals(ECP *P,ECP *Q);
+/**	@brief Copy ECP point to another ECP point
+ *
+	@param P ECP instance, on exit = Q
+	@param Q ECP instance to be copied
+ */
+extern void ECP_copy(ECP *P,ECP *Q);
+/**	@brief Negation of an ECP point
+ *
+	@param P ECP instance, on exit = -P
+ */
+extern void ECP_neg(ECP *P);
+/**	@brief Set ECP to point-at-infinity
+ *
+	@param P ECP instance to be set to infinity
+ */
+extern void ECP_inf(ECP *P);
+/**	@brief Calculate Right Hand Side of curve equation y^2=f(x)
+ *
+	Function f(x) depends on form of elliptic curve, Weierstrass, Edwards or Montgomery.
+	Used internally.
+	@param r BIG n-residue value of f(x)
+	@param x BIG n-residue x
+ */
+extern void ECP_rhs(YYY::FP *r,YYY::FP *x);
+/**	@brief Set ECP to point(x,y) given just x and sign of y
+ *
+	Point P set to infinity if no such point on the curve. If x is on the curve then y is calculated from the curve equation.
+	The correct y value (plus or minus) is selected given its sign s.
+	@param P ECP instance to be set (x,[y])
+	@param x BIG x coordinate of point
+	@param s an integer representing the "sign" of y, in fact its least significant bit.
+ */
+extern int ECP_setx(ECP *P,XXX::BIG x,int s);
+
+#if CURVETYPE_ZZZ==MONTGOMERY
+/**	@brief Set ECP to point(x,[y]) given x
+ *
+	Point P set to infinity if no such point on the curve. Note that y coordinate is not needed.
+	@param P ECP instance to be set (x,[y])
+	@param x BIG x coordinate of point
+	@return 1 if point exists, else 0
+ */
+extern int ECP_set(ECP *P,XXX::BIG x);
+/**	@brief Extract x coordinate of an ECP point P
+ *
+	@param x BIG on exit = x coordinate of point
+	@param P ECP instance (x,[y])
+	@return -1 if P is point-at-infinity, else 0
+ */
+extern int ECP_get(XXX::BIG x,ECP *P);
+/**	@brief Adds ECP instance Q to ECP instance P, given difference D=P-Q
+ *
+	Differential addition of points on a Montgomery curve
+	@param P ECP instance, on exit =P+Q
+	@param Q ECP instance to be added to P
+	@param D Difference between P and Q
+ */
+extern void ECP_add(ECP *P,ECP *Q,ECP *D);
+#else
+/**	@brief Set ECP to point(x,y) given x and y
+ *
+	Point P set to infinity if no such point on the curve.
+	@param P ECP instance to be set (x,y)
+	@param x BIG x coordinate of point
+	@param y BIG y coordinate of point
+	@return 1 if point exists, else 0
+ */
+extern int ECP_set(ECP *P,XXX::BIG x,XXX::BIG y);
+/**	@brief Extract x and y coordinates of an ECP point P
+ *
+	If x=y, returns only x
+	@param x BIG on exit = x coordinate of point
+	@param y BIG on exit = y coordinate of point (unless x=y)
+	@param P ECP instance (x,y)
+	@return sign of y, or -1 if P is point-at-infinity
+ */
+extern int ECP_get(XXX::BIG x,XXX::BIG y,ECP *P);
+/**	@brief Adds ECP instance Q to ECP instance P
+ *
+	@param P ECP instance, on exit =P+Q
+	@param Q ECP instance to be added to P
+ */
+extern void ECP_add(ECP *P,ECP *Q);
+/**	@brief Subtracts ECP instance Q from ECP instance P
+ *
+	@param P ECP instance, on exit =P-Q
+	@param Q ECP instance to be subtracted from P
+ */
+extern void ECP_sub(ECP *P,ECP *Q);
+#endif
+/**	@brief Converts an ECP point from Projective (x,y,z) coordinates to affine (x,y) coordinates
+ *
+	@param P ECP instance to be converted to affine form
+ */
+extern void ECP_affine(ECP *P);
+/**	@brief Formats and outputs an ECP point to the console, in projective coordinates
+ *
+	@param P ECP instance to be printed
+ */
+extern void ECP_outputxyz(ECP *P);
+/**	@brief Formats and outputs an ECP point to the console, converted to affine coordinates
+ *
+	@param P ECP instance to be printed
+ */
+extern void ECP_output(ECP * P);
+
+/**	@brief Formats and outputs an ECP point to the console
+ *
+	@param P ECP instance to be printed
+ */
+extern void ECP_rawoutput(ECP * P);
+
+/**	@brief Formats and outputs an ECP point to an octet string
+ *
+	The octet string is normally in the standard form 0x04|x|y
+	Here x (and y) are the x and y coordinates in left justified big-endian base 256 form.
+	For Montgomery curve it is 0x06|x
+	If c is true, only the x coordinate is provided as in 0x2|x if y is even, or 0x3|x if y is odd
+	@param c compression required, true or false
+	@param S output octet string
+	@param P ECP instance to be converted to an octet string
+ */
+extern void ECP_toOctet(octet *S,ECP *P,bool c);
+/**	@brief Creates an ECP point from an octet string
+ *
+	The octet string is normally in the standard form 0x04|x|y
+	Here x (and y) are the x and y coordinates in left justified big-endian base 256 form.
+	For Montgomery curve it is 0x06|x
+	If in compressed form only the x coordinate is provided as in 0x2|x if y is even, or 0x3|x if y is odd
+	@param P ECP instance to be created from the octet string
+	@param S input octet string
+	return 1 if octet string corresponds to a point on the curve, else 0
+ */
+extern int ECP_fromOctet(ECP *P,octet *S);
+/**	@brief Doubles an ECP instance P
+ *
+	@param P ECP instance, on exit =2*P
+ */
+extern void ECP_dbl(ECP *P);
+/**	@brief Multiplies an ECP instance P by a small integer, side-channel resistant
+ *
+	@param P ECP instance, on exit =i*P
+	@param i small integer multiplier
+	@param b maximum number of bits in multiplier
+ */
+extern void ECP_pinmul(ECP *P,int i,int b);
+/**	@brief Multiplies an ECP instance P by a BIG, side-channel resistant
+ *
+	Uses Montgomery ladder for Montgomery curves, otherwise fixed sized windows.
+	@param P ECP instance, on exit =b*P
+	@param b BIG number multiplier
+
+ */
+extern void ECP_mul(ECP *P,XXX::BIG b);
+/**	@brief Calculates double multiplication P=e*P+f*Q, side-channel resistant
+ *
+	@param P ECP instance, on exit =e*P+f*Q
+	@param Q ECP instance
+	@param e BIG number multiplier
+	@param f BIG number multiplier
+ */
+extern void ECP_mul2(ECP *P,ECP *Q,XXX::BIG e,XXX::BIG f);
+
+/**	@brief Multiplies random point by co-factor
+ *
+	@param Q ECP multiplied by co-factor
+ */
+extern void ECP_cfp(ECP *Q);
+
+/**	@brief Maps random BIG to curve point of correct order
+ *
+	@param Q ECP instance of correct order
+	@param w OCTET byte array to be mapped
+ */
+extern void ECP_mapit(ECP *Q,octet *w);
+
+/**	@brief Get Group Generator from ROM
+ *
+	@param G ECP instance
+ */
+extern void ECP_generator(ECP *G);
+
+}
+
+#endif
diff --git a/version3/cpp/ecp2.cpp b/version3/cpp/ecp2.cpp
new file mode 100644
index 0000000..9915d17
--- /dev/null
+++ b/version3/cpp/ecp2.cpp
@@ -0,0 +1,922 @@
+/*
+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.
+*/
+
+/* AMCL Weierstrass elliptic curve functions over FP2 */
+/* SU=m, m is Stack Usage */
+
+#include "ecp2_ZZZ.h"
+
+using namespace XXX;
+using namespace YYY;
+
+int ZZZ::ECP2_isinf(ECP2 *P)
+{
+//	if (P->inf) return 1;
+	return (FP2_iszilch(&(P->x)) & FP2_iszilch(&(P->z)));
+}
+
+/* Set P=Q */
+/* SU= 16 */
+void ZZZ::ECP2_copy(ECP2 *P,ECP2 *Q)
+{
+//    P->inf=Q->inf;
+    FP2_copy(&(P->x),&(Q->x));
+    FP2_copy(&(P->y),&(Q->y));
+    FP2_copy(&(P->z),&(Q->z));
+}
+
+/* set P to Infinity */
+/* SU= 8 */
+void ZZZ::ECP2_inf(ECP2 *P)
+{
+//    P->inf=1;
+    FP2_zero(&(P->x));
+    FP2_one(&(P->y));
+    FP2_zero(&(P->z));
+}
+
+/* Conditional move Q to P dependant on d */
+static void ECP2_cmove(ZZZ::ECP2 *P,ZZZ::ECP2 *Q,int d)
+{
+    FP2_cmove(&(P->x),&(Q->x),d);
+    FP2_cmove(&(P->y),&(Q->y),d);
+    FP2_cmove(&(P->z),&(Q->z),d);
+//    d=~(d-1);
+//    P->inf^=(P->inf^Q->inf)&d;
+}
+
+/* return 1 if b==c, no branching */
+static int teq(sign32 b,sign32 c)
+{
+    sign32 x=b^c;
+    x-=1;  // if x=0, x now -1
+    return (int)((x>>31)&1);
+}
+
+/* Constant time select from pre-computed table */
+static void ECP2_select(ZZZ::ECP2 *P,ZZZ::ECP2 W[],sign32 b)
+{
+    ZZZ::ECP2 MP;
+    sign32 m=b>>31;
+    sign32 babs=(b^m)-m;
+
+    babs=(babs-1)/2;
+
+    ECP2_cmove(P,&W[0],teq(babs,0));  // conditional move
+    ECP2_cmove(P,&W[1],teq(babs,1));
+    ECP2_cmove(P,&W[2],teq(babs,2));
+    ECP2_cmove(P,&W[3],teq(babs,3));
+    ECP2_cmove(P,&W[4],teq(babs,4));
+    ECP2_cmove(P,&W[5],teq(babs,5));
+    ECP2_cmove(P,&W[6],teq(babs,6));
+    ECP2_cmove(P,&W[7],teq(babs,7));
+
+    ECP2_copy(&MP,P);
+    ECP2_neg(&MP);  // minus P
+    ECP2_cmove(P,&MP,(int)(m&1));
+}
+
+/* return 1 if P==Q, else 0 */
+/* SU= 312 */
+int ZZZ::ECP2_equals(ECP2 *P,ECP2 *Q)
+{
+    FP2 a,b;
+//    if (ECP2_isinf(P) && ECP2_isinf(Q)) return 1;
+//    if (ECP2_isinf(P) || ECP2_isinf(Q)) return 0;
+
+    FP2_mul(&a,&(P->x),&(Q->z));
+    FP2_mul(&b,&(Q->x),&(P->z));
+    if (!FP2_equals(&a,&b)) return 0;
+
+    FP2_mul(&a,&(P->y),&(Q->z));
+    FP2_mul(&b,&(Q->y),&(P->z));
+    if (!FP2_equals(&a,&b)) return 0;
+    return 1;
+}
+
+/* Make P affine (so z=1) */
+/* SU= 232 */
+void ZZZ::ECP2_affine(ECP2 *P)
+{
+    FP2 one,iz;
+    if (ECP2_isinf(P)) return;
+
+    FP2_one(&one);
+    if (FP2_isunity(&(P->z)))
+    {
+        FP2_reduce(&(P->x));
+        FP2_reduce(&(P->y));
+        return;
+    }
+
+    FP2_inv(&iz,&(P->z));
+    FP2_mul(&(P->x),&(P->x),&iz);
+    FP2_mul(&(P->y),&(P->y),&iz);
+
+    FP2_reduce(&(P->x));
+    FP2_reduce(&(P->y));
+    FP2_copy(&(P->z),&one);
+}
+
+/* extract x, y from point P */
+/* SU= 16 */
+int ZZZ::ECP2_get(FP2 *x,FP2 *y,ECP2 *P)
+{
+	ECP2 W;
+	ECP2_copy(&W,P);
+	ECP2_affine(&W);
+	if (ECP2_isinf(&W)) return -1;
+//    if (P->inf) return -1;
+    //ECP2_affine(P);
+    FP2_copy(y,&(W.y));
+    FP2_copy(x,&(W.x));
+    return 0;
+}
+
+/* SU= 152 */
+/* Output point P */
+void ZZZ::ECP2_output(ECP2 *P)
+{
+    FP2 x,y;
+    if (ECP2_isinf(P))
+    {
+        printf("Infinity\n");
+        return;
+    }
+    ECP2_get(&x,&y,P);
+    printf("(");
+    FP2_output(&x);
+    printf(",");
+    FP2_output(&y);
+    printf(")\n");
+}
+
+/* SU= 232 */
+void ZZZ::ECP2_outputxyz(ECP2 *P)
+{
+    ECP2 Q;
+    if (ECP2_isinf(P))
+    {
+        printf("Infinity\n");
+        return;
+    }
+    ECP2_copy(&Q,P);
+    printf("(");
+    FP2_output(&(Q.x));
+    printf(",");
+    FP2_output(&(Q.y));
+    printf(",");
+    FP2_output(&(Q.z));
+    printf(")\n");
+}
+
+/* SU= 168 */
+/* Convert Q to octet string */
+void ZZZ::ECP2_toOctet(octet *W,ECP2 *Q)
+{
+	BIG b;
+	FP2 qx,qy;
+    ECP2_get(&qx,&qy,Q);
+
+	FP_redc(b,&(qx.a));
+    BIG_toBytes(&(W->val[0]),b);
+    FP_redc(b,&(qx.b));
+    BIG_toBytes(&(W->val[MODBYTES_XXX]),b);
+    FP_redc(b,&(qy.a));
+    BIG_toBytes(&(W->val[2*MODBYTES_XXX]),b);
+    FP_redc(b,&(qy.b));
+    BIG_toBytes(&(W->val[3*MODBYTES_XXX]),b);
+
+    W->len=4*MODBYTES_XXX;
+
+}
+
+/* SU= 176 */
+/* restore Q from octet string */
+int ZZZ::ECP2_fromOctet(ECP2 *Q,octet *W)
+{
+	BIG b;
+    FP2 qx,qy;
+    BIG_fromBytes(b,&(W->val[0]));
+	FP_nres(&(qx.a),b);
+    BIG_fromBytes(b,&(W->val[MODBYTES_XXX]));
+    FP_nres(&(qx.b),b);
+    BIG_fromBytes(b,&(W->val[2*MODBYTES_XXX]));
+    FP_nres(&(qy.a),b);
+    BIG_fromBytes(b,&(W->val[3*MODBYTES_XXX]));
+    FP_nres(&(qy.b),b);
+
+    if (ECP2_set(Q,&qx,&qy)) return 1;
+    return 0;
+}
+
+/* SU= 128 */
+/* Calculate RHS of twisted curve equation x^3+B/i or x^3+Bi*/
+void ZZZ::ECP2_rhs(FP2 *rhs,FP2 *x)
+{
+    /* calculate RHS of elliptic curve equation */
+    FP2 t;
+    BIG b;
+    FP2_sqr(&t,x);
+
+    FP2_mul(rhs,&t,x);
+
+    /* Assuming CURVE_A=0 */
+
+    BIG_rcopy(b,CURVE_B);
+
+    FP2_from_BIG(&t,b);
+
+#if SEXTIC_TWIST_ZZZ == D_TYPE	
+    FP2_div_ip(&t);   /* IMPORTANT - here we use the correct SEXTIC twist of the curve */
+#endif
+
+#if SEXTIC_TWIST_ZZZ == M_TYPE	
+	FP2_norm(&t);
+    FP2_mul_ip(&t);   /* IMPORTANT - here we use the correct SEXTIC twist of the curve */
+	FP2_norm(&t);
+
+#endif
+
+
+    FP2_add(rhs,&t,rhs);
+    FP2_reduce(rhs);
+}
+
+
+/* Set P=(x,y). Return 1 if (x,y) is on the curve, else return 0*/
+/* SU= 232 */
+int ZZZ::ECP2_set(ECP2 *P,FP2 *x,FP2 *y)
+{
+    FP2 rhs,y2;
+
+    FP2_sqr(&y2,y);
+    ECP2_rhs(&rhs,x);
+
+    if (!FP2_equals(&y2,&rhs))
+    {
+		ECP2_inf(P);
+        return 0;
+    }
+
+   // P->inf=0;
+    FP2_copy(&(P->x),x);
+    FP2_copy(&(P->y),y);
+
+    FP2_one(&(P->z));
+    return 1;
+}
+
+/* Set P=(x,y). Return 1 if (x,.) is on the curve, else return 0 */
+/* SU= 232 */
+int ZZZ::ECP2_setx(ECP2 *P,FP2 *x)
+{
+    FP2 y;
+    ECP2_rhs(&y,x);
+
+    if (!FP2_sqrt(&y,&y))
+    {
+		ECP2_inf(P);
+        return 0;
+    }
+
+//    P->inf=0;
+    FP2_copy(&(P->x),x);
+    FP2_copy(&(P->y),&y);
+    FP2_one(&(P->z));
+    return 1;
+}
+
+/* Set P=-P */
+/* SU= 8 */
+void ZZZ::ECP2_neg(ECP2 *P)
+{
+//	if (ECP2_isinf(P)) return;
+	FP2_norm(&(P->y));
+    FP2_neg(&(P->y),&(P->y));
+    FP2_norm(&(P->y));
+}
+
+/* R+=R */
+/* return -1 for Infinity, 0 for addition, 1 for doubling */
+/* SU= 448 */
+int ZZZ::ECP2_dbl(ECP2 *P)
+{
+    FP2 t0,t1,t2,t3,iy,x3,y3;
+//    if (P->inf) return -1;
+
+	FP2_copy(&iy,&(P->y));		//FP2 iy=new FP2(y);
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+	FP2_mul_ip(&iy);			//iy.mul_ip(); 
+	FP2_norm(&iy);				//iy.norm();
+#endif
+	//FP2_copy(&t0,&(P->y));		//FP2 t0=new FP2(y);                  //***** Change 
+	FP2_sqr(&t0,&(P->y));			//t0.sqr();   
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+	FP2_mul_ip(&t0);			//t0.mul_ip(); 
+#endif
+	//FP2_copy(&t1,&iy);				//FP2 t1=new FP2(iy);  
+	FP2_mul(&t1,&iy,&(P->z));	//t1.mul(z);
+	//FP2_copy(&t2,&(P->z));		//FP2 t2=new FP2(z);
+	FP2_sqr(&t2,&(P->z));				//t2.sqr();
+
+	//FP2_copy(&(P->z),&t0);		//z.copy(t0);
+	FP2_add(&(P->z),&t0,&t0);	//z.add(t0); 
+	FP2_norm(&(P->z));				//z.norm(); 
+	FP2_add(&(P->z),&(P->z),&(P->z));	//z.add(z); 
+	FP2_add(&(P->z),&(P->z),&(P->z));	//z.add(z); 
+	FP2_norm(&(P->z));			//z.norm();  
+
+	FP2_imul(&t2,&t2,3*CURVE_B_I);	//t2.imul(3*ROM.CURVE_B_I); 
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+	FP2_mul_ip(&t2);
+	FP2_norm(&t2);
+#endif
+
+	//FP2_copy(&x3,&t2);			//FP2 x3=new FP2(t2);
+	FP2_mul(&x3,&t2,&(P->z));	//x3.mul(z); 
+
+	//FP2_copy(&y3,&t0);			//FP2 y3=new FP2(t0);   
+
+	FP2_add(&y3,&t0,&t2);		//y3.add(t2); 
+	FP2_norm(&y3);				//y3.norm();
+	FP2_mul(&(P->z),&(P->z),&t1);	//z.mul(t1);
+
+	//FP2_copy(&t1,&t2);			//t1.copy(t2); 
+	FP2_add(&t1,&t2,&t2);		//t1.add(t2); 
+	FP2_add(&t2,&t2,&t1);		//t2.add(t1); 
+	FP2_norm(&t2);				//t2.norm();  
+	FP2_sub(&t0,&t0,&t2);		//t0.sub(t2); 
+	FP2_norm(&t0);				//t0.norm();                           //y^2-9bz^2
+	FP2_mul(&y3,&y3,&t0);		//y3.mul(t0); 
+	FP2_add(&(P->y),&y3,&x3);		//y3.add(x3);                          //(y^2+3z*2)(y^2-9z^2)+3b.z^2.8y^2
+	//FP2_copy(&t1,&(P->x));		//t1.copy(x); 
+	FP2_mul(&t1,&(P->x),&iy);		//t1.mul(iy);						//
+	//FP2_copy(&(P->x),&t0);		//x.copy(t0); 
+	FP2_norm(&t0);			//x.norm(); 
+	FP2_mul(&(P->x),&t0,&t1);	//x.mul(t1); 
+	FP2_add(&(P->x),&(P->x),&(P->x));	//x.add(x);       //(y^2-9bz^2)xy2
+
+	FP2_norm(&(P->x));			//x.norm(); 
+	//FP2_copy(&(P->y),&y3);		//y.copy(y3); 
+	FP2_norm(&(P->y));			//y.norm();
+
+    return 1;
+}
+
+/* Set P+=Q */
+/* SU= 400 */
+int ZZZ::ECP2_add(ECP2 *P,ECP2 *Q)
+{
+    FP2 t0,t1,t2,t3,t4,x3,y3,z3;
+	int b3=3*CURVE_B_I;
+/*    if (Q->inf) return 0;
+    if (P->inf)
+    {
+        ECP2_copy(P,Q);
+        return 0;
+    }
+*/
+
+
+	//FP2_copy(&t0,&(P->x));		//FP2 t0=new FP2(x);
+	FP2_mul(&t0,&(P->x),&(Q->x));	//t0.mul(Q.x);         // x.Q.x
+	//FP2_copy(&t1,&(P->y));		//FP2 t1=new FP2(y);
+	FP2_mul(&t1,&(P->y),&(Q->y));	//t1.mul(Q.y);		 // y.Q.y
+
+	//FP2_copy(&t2,&(P->z));		//FP2 t2=new FP2(z);
+	FP2_mul(&t2,&(P->z),&(Q->z));	//t2.mul(Q.z);
+	//FP2_copy(&t3,&(P->x));		//FP2 t3=new FP2(x);
+
+	FP2_add(&t3,&(P->x),&(P->y));	//t3.add(y); 
+	FP2_norm(&t3);				//t3.norm();          //t3=X1+Y1
+	//FP2_copy(&t4,&(Q->x));		//FP2 t4=new FP2(Q.x);            
+	FP2_add(&t4,&(Q->x),&(Q->y));	//t4.add(Q.y); 
+	FP2_norm(&t4);				//t4.norm();			//t4=X2+Y2
+	FP2_mul(&t3,&t3,&t4);		//t3.mul(t4);						//t3=(X1+Y1)(X2+Y2)
+
+	//FP2_copy(&t4,&t0);			//t4.copy(t0); 
+	FP2_add(&t4,&t0,&t1);		//t4.add(t1);		//t4=X1.X2+Y1.Y2
+
+	FP2_sub(&t3,&t3,&t4);		//t3.sub(t4); 
+	FP2_norm(&t3);				//t3.norm(); 
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+	FP2_mul_ip(&t3);			//t3.mul_ip();  
+	FP2_norm(&t3);				//t3.norm();         //t3=(X1+Y1)(X2+Y2)-(X1.X2+Y1.Y2) = X1.Y2+X2.Y1
+#endif
+	//FP2_copy(&t4,&(P->y));		//t4.copy(y);                    
+	FP2_add(&t4,&(P->y),&(P->z));	//t4.add(z); 
+	FP2_norm(&t4);				//t4.norm();			//t4=Y1+Z1
+	//FP2_copy(&x3,&(Q->y));		//FP2 x3=new FP2(Q.y);
+	FP2_add(&x3,&(Q->y),&(Q->z));	//x3.add(Q.z); 
+	FP2_norm(&x3);				//x3.norm();			//x3=Y2+Z2
+
+	FP2_mul(&t4,&t4,&x3);		//t4.mul(x3);						//t4=(Y1+Z1)(Y2+Z2)
+	//FP2_copy(&x3,&t1);			//x3.copy(t1);					//
+	FP2_add(&x3,&t1,&t2);		//x3.add(t2);						//X3=Y1.Y2+Z1.Z2
+	
+	FP2_sub(&t4,&t4,&x3);		//t4.sub(x3); 
+	FP2_norm(&t4);				//t4.norm(); 
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+	FP2_mul_ip(&t4);			//t4.mul_ip(); 
+	FP2_norm(&t4);				//t4.norm();          //t4=(Y1+Z1)(Y2+Z2) - (Y1.Y2+Z1.Z2) = Y1.Z2+Y2.Z1
+#endif
+	//FP2_copy(&x3,&(P->x));		//x3.copy(x); 
+	FP2_add(&x3,&(P->x),&(P->z));	//x3.add(z); 
+	FP2_norm(&x3);				//x3.norm();	// x3=X1+Z1
+	//FP2_copy(&y3,&(Q->x));		//FP2 y3=new FP2(Q.x);				
+	FP2_add(&y3,&(Q->x),&(Q->z));	//y3.add(Q.z); 
+	FP2_norm(&y3);				//y3.norm();				// y3=X2+Z2
+	FP2_mul(&x3,&x3,&y3);		//x3.mul(y3);							// x3=(X1+Z1)(X2+Z2)
+	//FP2_copy(&y3,&t0);			//y3.copy(t0);
+	FP2_add(&y3,&t0,&t2);		//y3.add(t2);							// y3=X1.X2+Z1+Z2
+	FP2_sub(&y3,&x3,&y3);		//y3.rsub(x3); 
+	FP2_norm(&y3);				//y3.norm();				// y3=(X1+Z1)(X2+Z2) - (X1.X2+Z1.Z2) = X1.Z2+X2.Z1
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+	FP2_mul_ip(&t0);			//t0.mul_ip(); 
+	FP2_norm(&t0);				//t0.norm(); // x.Q.x
+	FP2_mul_ip(&t1);			//t1.mul_ip(); 
+	FP2_norm(&t1);				//t1.norm(); // y.Q.y
+#endif
+
+	//FP2_copy(&x3,&t0);			//x3.copy(t0); 
+	FP2_add(&x3,&t0,&t0);		//x3.add(t0); 
+	FP2_add(&t0,&t0,&x3);		//t0.add(x3); 
+	FP2_norm(&t0);				//t0.norm();
+	FP2_imul(&t2,&t2,b3);		//t2.imul(b); 	
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+	FP2_mul_ip(&t2);
+	FP2_norm(&t2);
+#endif
+
+	//FP2_copy(&z3,&t1);			//FP2 z3=new FP2(t1); 
+	FP2_add(&z3,&t1,&t2);		//z3.add(t2); 
+	FP2_norm(&z3);				//z3.norm();
+	FP2_sub(&t1,&t1,&t2);		//t1.sub(t2); 
+	FP2_norm(&t1);				//t1.norm(); 
+
+	FP2_imul(&y3,&y3,b3);		//y3.imul(b); 
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+	FP2_mul_ip(&y3);
+	FP2_norm(&y3);
+#endif
+
+	//FP2_copy(&x3,&y3);			//x3.copy(y3); 
+	FP2_mul(&x3,&y3,&t4);		//x3.mul(t4); 
+	//FP2_copy(&t2,&t3);			//t2.copy(t3); 
+	FP2_mul(&t2,&t3,&t1);		//t2.mul(t1); 
+	FP2_sub(&(P->x),&t2,&x3);		//x3.rsub(t2);
+	FP2_mul(&y3,&y3,&t0);		//y3.mul(t0); 
+	FP2_mul(&t1,&t1,&z3);		//t1.mul(z3); 
+	FP2_add(&(P->y),&y3,&t1);		//y3.add(t1);
+
+	FP2_mul(&t0,&t0,&t3);		//t0.mul(t3); 
+	FP2_mul(&z3,&z3,&t4);		//z3.mul(t4); 
+	FP2_add(&(P->z),&z3,&t0);		//z3.add(t0);
+
+	//FP2_copy(&(P->x),&x3);		//x.copy(x3); 
+	FP2_norm(&(P->x));			//x.norm(); 
+	//FP2_copy(&(P->y),&y3);		//y.copy(y3); 
+	FP2_norm(&(P->y));			//y.norm();
+	//FP2_copy(&(P->z),&z3);		//z.copy(z3); 
+	FP2_norm(&(P->z));			//z.norm();
+
+    return 0;
+}
+
+/* Set P-=Q */
+/* SU= 16 */
+void ZZZ::ECP2_sub(ECP2 *P,ECP2 *Q)
+{
+	ECP2 NQ;
+	ECP2_copy(&NQ,Q);
+	ECP2_neg(&NQ);
+    //ECP2_neg(Q);
+    ECP2_add(P,&NQ);
+    //ECP2_neg(Q);
+}
+
+/* P*=e */
+/* SU= 280 */
+void ZZZ::ECP2_mul(ECP2 *P,BIG e)
+{
+    /* fixed size windows */
+    int i,nb,s,ns;
+    BIG mt,t;
+    ECP2 Q,W[8],C;
+    sign8 w[1+(NLEN_XXX*BASEBITS_XXX+3)/4];
+
+    if (ECP2_isinf(P)) return;
+    //ECP2_affine(P);
+
+
+    /* precompute table */
+
+    ECP2_copy(&Q,P);
+    ECP2_dbl(&Q);
+    ECP2_copy(&W[0],P);
+
+    for (i=1; i<8; i++)
+    {
+        ECP2_copy(&W[i],&W[i-1]);
+        ECP2_add(&W[i],&Q);
+    }
+
+    /* make exponent odd - add 2P if even, P if odd */
+    BIG_copy(t,e);
+    s=BIG_parity(t);
+    BIG_inc(t,1);
+    BIG_norm(t);
+    ns=BIG_parity(t);
+    BIG_copy(mt,t);
+    BIG_inc(mt,1);
+    BIG_norm(mt);
+    BIG_cmove(t,mt,s);
+    ECP2_cmove(&Q,P,ns);
+    ECP2_copy(&C,&Q);
+
+    nb=1+(BIG_nbits(t)+3)/4;
+
+    /* convert exponent to signed 4-bit window */
+    for (i=0; i<nb; i++)
+    {
+        w[i]=BIG_lastbits(t,5)-16;
+        BIG_dec(t,w[i]);
+        BIG_norm(t);
+        BIG_fshr(t,4);
+    }
+    w[nb]=BIG_lastbits(t,5);
+
+    ECP2_copy(P,&W[(w[nb]-1)/2]);
+    for (i=nb-1; i>=0; i--)
+    {
+        ECP2_select(&Q,W,w[i]);
+        ECP2_dbl(P);
+        ECP2_dbl(P);
+        ECP2_dbl(P);
+        ECP2_dbl(P);
+        ECP2_add(P,&Q);
+    }
+    ECP2_sub(P,&C); /* apply correction */
+    ECP2_affine(P);
+}
+
+/* Calculates q.P using Frobenius constant X */
+/* SU= 96 */
+void ZZZ::ECP2_frob(ECP2 *P,FP2 *X)
+{
+    FP2 X2;
+    FP2_sqr(&X2,X);
+//printf("Into frob  %d\n",(P->z).b.XES);
+    FP2_conj(&(P->x),&(P->x));
+//printf("x\n");
+    FP2_conj(&(P->y),&(P->y));
+//printf("za = %d zb= %d\n",(P->z).a.g[MPV_XXX],(P->z).b.g[MPV_XXX]);
+    FP2_conj(&(P->z),&(P->z));
+//printf("Into frob  %d\n",(P->z).b.XES);
+    FP2_reduce(&(P->z));
+    FP2_mul(&(P->x),&X2,&(P->x));
+    FP2_mul(&(P->y),&X2,&(P->y));
+    FP2_mul(&(P->y),X,&(P->y));
+}
+
+// Bos & Costello https://eprint.iacr.org/2013/458.pdf
+// Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
+// Side channel attack secure 
+
+void ZZZ::ECP2_mul4(ECP2 *P,ECP2 Q[4],BIG u[4])
+{
+    int i,j,k,nb,pb,bt;
+	ECP2 T[8],W;
+    BIG t[4],mt;
+	sign8 w[NLEN_XXX*BASEBITS_XXX+1];
+	sign8 s[NLEN_XXX*BASEBITS_XXX+1];
+
+    for (i=0; i<4; i++)
+    {
+        BIG_copy(t[i],u[i]);
+        //ECP2_affine(&Q[i]);
+    }
+
+// Precomputed table
+    ECP2_copy(&T[0],&Q[0]); // Q[0]
+    ECP2_copy(&T[1],&T[0]);
+	ECP2_add(&T[1],&Q[1]);	// Q[0]+Q[1]
+    ECP2_copy(&T[2],&T[0]);
+	ECP2_add(&T[2],&Q[2]);	// Q[0]+Q[2]
+	ECP2_copy(&T[3],&T[1]);
+	ECP2_add(&T[3],&Q[2]);	// Q[0]+Q[1]+Q[2]
+	ECP2_copy(&T[4],&T[0]);
+	ECP2_add(&T[4],&Q[3]);  // Q[0]+Q[3]
+	ECP2_copy(&T[5],&T[1]);
+	ECP2_add(&T[5],&Q[3]);	// Q[0]+Q[1]+Q[3]
+	ECP2_copy(&T[6],&T[2]);
+	ECP2_add(&T[6],&Q[3]);	// Q[0]+Q[2]+Q[3]
+	ECP2_copy(&T[7],&T[3]);
+	ECP2_add(&T[7],&Q[3]);	// Q[0]+Q[1]+Q[2]+Q[3]
+
+// Make it odd
+	pb=1-BIG_parity(t[0]);
+	BIG_inc(t[0],pb);
+	BIG_norm(t[0]);
+
+// Number of bits
+    BIG_zero(mt);
+    for (i=0; i<4; i++)
+    {
+        BIG_or(mt,mt,t[i]);
+    }
+    nb=1+BIG_nbits(mt);
+
+// Sign pivot 
+	s[nb-1]=1;
+	for (i=0;i<nb-1;i++)
+	{
+        BIG_fshr(t[0],1);
+		s[i]=2*BIG_parity(t[0])-1;
+	}
+
+// Recoded exponent
+    for (i=0; i<nb; i++)
+    {
+		w[i]=0;
+		k=1;
+		for (j=1; j<4; j++)
+		{
+			bt=s[i]*BIG_parity(t[j]);
+			BIG_fshr(t[j],1);
+
+			BIG_dec(t[j],(bt>>1));
+			BIG_norm(t[j]);
+			w[i]+=bt*k;
+			k*=2;
+        }
+    }		
+
+// Main loop
+	ECP2_select(P,T,2*w[nb-1]+1);
+    for (i=nb-2; i>=0; i--)
+    {
+        ECP2_select(&W,T,2*w[i]+s[i]);
+        ECP2_dbl(P);
+        ECP2_add(P,&W);
+    }
+
+// apply correction
+	ECP2_copy(&W,P);   
+	ECP2_sub(&W,&Q[0]);
+	ECP2_cmove(P,&W,pb);
+
+    ECP2_affine(P);
+}
+
+/*
+void ZZZ::ECP2_mul4(ECP2 *P,ECP2 Q[4],BIG u[4])
+{
+    int i,j,a[4],nb,pb;
+    ECP2 W[8],T,C;
+    BIG mt,t[4];
+  
+    sign8 w[NLEN_XXX*BASEBITS_XXX+1];
+
+    for (i=0; i<4; i++)
+    {
+        BIG_copy(t[i],u[i]);
+        ECP2_affine(&Q[i]);
+    }
+
+    // precompute table 
+
+    ECP2_copy(&W[0],&Q[0]);
+    ECP2_sub(&W[0],&Q[1]);  // P-Q 
+    ECP2_copy(&W[1],&W[0]);
+    ECP2_copy(&W[2],&W[0]);
+    ECP2_copy(&W[3],&W[0]);
+    ECP2_copy(&W[4],&Q[0]);
+    ECP2_add(&W[4],&Q[1]);  // P+Q 
+    ECP2_copy(&W[5],&W[4]);
+    ECP2_copy(&W[6],&W[4]);
+    ECP2_copy(&W[7],&W[4]);
+
+    ECP2_copy(&T,&Q[2]);
+    ECP2_sub(&T,&Q[3]);       // R-S 
+    ECP2_sub(&W[1],&T);
+    ECP2_add(&W[2],&T);
+    ECP2_sub(&W[5],&T);
+    ECP2_add(&W[6],&T);
+    ECP2_copy(&T,&Q[2]);
+    ECP2_add(&T,&Q[3]);      // R+S 
+    ECP2_sub(&W[0],&T);
+    ECP2_add(&W[3],&T);
+    ECP2_sub(&W[4],&T);
+    ECP2_add(&W[7],&T);
+
+    // if a multiplier u[i] is even add 1 to multiplier, and add Q[i] to correction 
+    ECP2_inf(&C);
+
+    BIG_zero(mt);
+    for (i=0; i<4; i++)
+    {
+
+		pb=BIG_parity(t[i]);
+		BIG_inc(t[i],1-pb);
+		BIG_norm(t[i]);
+		ECP2_copy(&T,&C);
+		ECP2_add(&T,&Q[i]);
+		ECP2_cmove(&C,&T,1-pb);
+
+        BIG_add(mt,mt,t[i]);
+        BIG_norm(mt);
+    }
+
+    nb=1+BIG_nbits(mt);
+
+    // convert exponent to signed 1-bit window 
+    for (j=0; j<nb; j++)
+    {
+        for (i=0; i<4; i++)
+        {
+            a[i]=BIG_lastbits(t[i],2)-2;
+            BIG_dec(t[i],a[i]);
+            BIG_norm(t[i]);
+            BIG_fshr(t[i],1);
+        }
+        w[j]=8*a[0]+4*a[1]+2*a[2]+a[3];
+    }
+    w[nb]=8*BIG_lastbits(t[0],2)+4*BIG_lastbits(t[1],2)+2*BIG_lastbits(t[2],2)+BIG_lastbits(t[3],2);
+
+    ECP2_copy(P,&W[(w[nb]-1)/2]);
+    for (i=nb-1; i>=0; i--)
+    {
+        ECP2_select(&T,W,w[i]);
+        ECP2_dbl(P);
+        ECP2_add(P,&T);
+    }
+    ECP2_sub(P,&C); // apply correction 
+
+    ECP2_affine(P);
+}
+
+*/
+
+/* Map to hash value to point on G2 from random BIG */
+
+void ZZZ::ECP2_mapit(ECP2 *Q,octet *W)
+{
+    BIG q,one,x,hv;
+	FP Fx,Fy;
+    FP2 X;
+#if (PAIRING_FRIENDLY_ZZZ == BN)
+    ECP2 T,K;
+#elif (PAIRING_FRIENDLY_ZZZ == BLS)
+    ECP2 xQ, x2Q;
+#endif
+	BIG_fromBytes(hv,W->val);
+    BIG_rcopy(q,Modulus);
+    BIG_one(one);
+    BIG_mod(hv,q);
+
+    for (;;)
+    {
+        FP2_from_BIGs(&X,one,hv);
+        if (ECP2_setx(Q,&X)) break;
+        BIG_inc(hv,1);
+    }
+
+    FP_rcopy(&Fx,Fra);
+    FP_rcopy(&Fy,Frb);
+    FP2_from_FPs(&X,&Fx,&Fy);
+
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+	FP2_inv(&X,&X);
+	FP2_norm(&X);
+#endif
+
+    BIG_rcopy(x,CURVE_Bnx);
+
+#if (PAIRING_FRIENDLY_ZZZ == BN)
+
+    // Faster Hashing to G2 - Fuentes-Castaneda, Knapp and Rodriguez-Henriquez 
+    // Q -> xQ + F(3xQ) + F(F(xQ)) + F(F(F(Q))). 
+    ECP2_copy(&T,Q);
+    ECP2_mul(&T,x);
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+    ECP2_neg(&T);   // our x is negative
+#endif
+    ECP2_copy(&K,&T);
+    ECP2_dbl(&K);
+    ECP2_add(&K,&T);
+    //ECP2_affine(&K);
+
+    ECP2_frob(&K,&X);
+    ECP2_frob(Q,&X);
+    ECP2_frob(Q,&X);
+    ECP2_frob(Q,&X);
+    ECP2_add(Q,&T);
+    ECP2_add(Q,&K);
+    ECP2_frob(&T,&X);
+    ECP2_frob(&T,&X);
+    ECP2_add(Q,&T);
+    ECP2_affine(Q);
+
+#elif (PAIRING_FRIENDLY_ZZZ == BLS)
+
+    // Efficient hash maps to G2 on BLS curves - Budroni, Pintore 
+    // Q -> x2Q -xQ -Q +F(xQ -Q) +F(F(2Q)) 
+
+    ECP2_copy(&xQ,Q);
+    ECP2_mul(&xQ,x);
+    ECP2_copy(&x2Q,&xQ);
+    ECP2_mul(&x2Q,x);
+
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	ECP2_neg(&xQ);
+#endif
+
+    ECP2_sub(&x2Q,&xQ);
+    ECP2_sub(&x2Q,Q);
+
+    ECP2_sub(&xQ,Q);
+    ECP2_frob(&xQ,&X);
+
+    ECP2_dbl(Q);
+    ECP2_frob(Q,&X);
+    ECP2_frob(Q,&X);
+
+    ECP2_add(Q,&x2Q);
+    ECP2_add(Q,&xQ);
+
+    ECP2_affine(Q);
+
+#endif
+}
+
+void ZZZ::ECP2_generator(ECP2 *G)
+{
+	FP2 wx,wy;
+
+    FP_rcopy(&(wx.a),CURVE_Pxa); 
+    FP_rcopy(&(wx.b),CURVE_Pxb); 
+    FP_rcopy(&(wy.a),CURVE_Pya); 
+    FP_rcopy(&(wy.b),CURVE_Pyb);     
+	ECP2_set(G,&wx,&wy);
+}
+
+/*
+
+int main()
+{
+	int i;
+	ECP2 G,P;
+	ECP2 *W;
+	FP2 x,y,w,z,f;
+	BIG r,xa,xb,ya,yb;
+
+	BIG_rcopy(xa,CURVE_Pxa);
+	BIG_rcopy(xb,CURVE_Pxb);
+	BIG_rcopy(ya,CURVE_Pya);
+	BIG_rcopy(yb,CURVE_Pyb);
+
+	FP2_from_BIGs(&x,xa,xb);
+	FP2_from_BIGs(&y,ya,yb);
+	ECP2_set(&G,&x,&y);
+	if (G.inf) printf("Failed to set - point not on curve\n");
+	else printf("set success\n");
+
+	ECP2_output(&G);
+
+//	BIG_copy(r,CURVE_Order);
+	BIG_rcopy(r,Modulus);
+
+	ECP2_copy(&P,&G);
+
+	ECP2_mul(&P,r);
+
+	ECP2_output(&P);
+
+	FP2_gfc(&f,12);
+
+	ECP2_frob(&G,&f);
+
+	ECP2_output(&G);
+
+	return 0;
+}
+
+*/
diff --git a/version3/cpp/ecp2.h b/version3/cpp/ecp2.h
new file mode 100644
index 0000000..9cb5739
--- /dev/null
+++ b/version3/cpp/ecp2.h
@@ -0,0 +1,203 @@
+#ifndef ECP2_ZZZ_H
+#define ECP2_ZZZ_H
+
+#include "fp2_YYY.h"
+#include "config_curve_ZZZ.h"
+
+using namespace amcl;
+
+
+namespace YYY {
+
+extern const XXX::BIG Fra; /**< real part of BN curve Frobenius Constant */
+extern const XXX::BIG Frb; /**< imaginary part of BN curve Frobenius Constant */
+
+}
+
+namespace ZZZ {
+
+/**
+	@brief ECP2 Structure - Elliptic Curve Point over quadratic extension field
+*/
+
+typedef struct
+{
+//    int inf; /**< Infinity Flag */
+    YYY::FP2 x;   /**< x-coordinate of point */
+    YYY::FP2 y;   /**< y-coordinate of point */
+    YYY::FP2 z;   /**< z-coordinate of point */
+} ECP2;
+
+
+/* Curve Params - see rom.c */
+extern const int CURVE_A;		/**< Elliptic curve A parameter */
+extern const int CURVE_B_I;		/**< Elliptic curve B parameter */
+extern const XXX::BIG CURVE_B;     /**< Elliptic curve B parameter */
+extern const XXX::BIG CURVE_Order; /**< Elliptic curve group order */
+extern const XXX::BIG CURVE_Cof;   /**< Elliptic curve cofactor */
+extern const XXX::BIG CURVE_Bnx;   /**< Elliptic curve parameter */
+
+
+/* Generator point on G1 */
+extern const XXX::BIG CURVE_Gx; /**< x-coordinate of generator point in group G1  */
+extern const XXX::BIG CURVE_Gy; /**< y-coordinate of generator point in group G1  */
+
+/* For Pairings only */
+
+/* Generator point on G2 */
+extern const XXX::BIG CURVE_Pxa; /**< real part of x-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pxb; /**< imaginary part of x-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pya; /**< real part of y-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pyb; /**< imaginary part of y-coordinate of generator point in group G2 */
+
+/* ECP2 E(Fp2) prototypes */
+/**	@brief Tests for ECP2 point equal to infinity
+ *
+	@param P ECP2 point to be tested
+	@return 1 if infinity, else returns 0
+ */
+extern int ECP2_isinf(ECP2 *P);
+/**	@brief Copy ECP2 point to another ECP2 point
+ *
+	@param P ECP2 instance, on exit = Q
+	@param Q ECP2 instance to be copied
+ */
+extern void ECP2_copy(ECP2 *P,ECP2 *Q);
+/**	@brief Set ECP2 to point-at-infinity
+ *
+	@param P ECP2 instance to be set to infinity
+ */
+extern void ECP2_inf(ECP2 *P);
+/**	@brief Tests for equality of two ECP2s
+ *
+	@param P ECP2 instance to be compared
+	@param Q ECP2 instance to be compared
+	@return 1 if P=Q, else returns 0
+ */
+extern int ECP2_equals(ECP2 *P,ECP2 *Q);
+/**	@brief Converts an ECP2 point from Projective (x,y,z) coordinates to affine (x,y) coordinates
+ *
+	@param P ECP2 instance to be converted to affine form
+ */
+extern void ECP2_affine(ECP2 *P);
+/**	@brief Extract x and y coordinates of an ECP2 point P
+ *
+	If x=y, returns only x
+	@param x FP2 on exit = x coordinate of point
+	@param y FP2 on exit = y coordinate of point (unless x=y)
+	@param P ECP2 instance (x,y)
+	@return -1 if P is point-at-infinity, else 0
+ */
+extern int ECP2_get(YYY::FP2 *x,YYY::FP2 *y,ECP2 *P);
+/**	@brief Formats and outputs an ECP2 point to the console, converted to affine coordinates
+ *
+	@param P ECP2 instance to be printed
+ */
+extern void ECP2_output(ECP2 *P);
+/**	@brief Formats and outputs an ECP2 point to the console, in projective coordinates
+ *
+	@param P ECP2 instance to be printed
+ */
+extern void ECP2_outputxyz(ECP2 *P);
+/**	@brief Formats and outputs an ECP2 point to an octet string
+ *
+	The octet string is created in the form x|y.
+	Convert the real and imaginary parts of the x and y coordinates to big-endian base 256 form.
+	@param S output octet string
+	@param P ECP2 instance to be converted to an octet string
+ */
+extern void ECP2_toOctet(octet *S,ECP2 *P);
+/**	@brief Creates an ECP2 point from an octet string
+ *
+	The octet string is in the form x|y
+	The real and imaginary parts of the x and y coordinates are in big-endian base 256 form.
+	@param P ECP2 instance to be created from the octet string
+	@param S input octet string
+	return 1 if octet string corresponds to a point on the curve, else 0
+ */
+extern int ECP2_fromOctet(ECP2 *P,octet *S);
+/**	@brief Calculate Right Hand Side of curve equation y^2=f(x)
+ *
+	Function f(x)=x^3+Ax+B
+	Used internally.
+	@param r FP2 value of f(x)
+	@param x FP2 instance
+ */
+extern void ECP2_rhs(YYY::FP2 *r,YYY::FP2 *x);
+/**	@brief Set ECP2 to point(x,y) given x and y
+ *
+	Point P set to infinity if no such point on the curve.
+	@param P ECP2 instance to be set (x,y)
+	@param x FP2 x coordinate of point
+	@param y FP2 y coordinate of point
+	@return 1 if point exists, else 0
+ */
+extern int ECP2_set(ECP2 *P,YYY::FP2 *x,YYY::FP2 *y);
+/**	@brief Set ECP to point(x,[y]) given x
+ *
+	Point P set to infinity if no such point on the curve. Otherwise y coordinate is calculated from x.
+	@param P ECP instance to be set (x,[y])
+	@param x BIG x coordinate of point
+	@return 1 if point exists, else 0
+ */
+extern int ECP2_setx(ECP2 *P,YYY::FP2 *x);
+/**	@brief Negation of an ECP2 point
+ *
+	@param P ECP2 instance, on exit = -P
+ */
+extern void ECP2_neg(ECP2 *P);
+/**	@brief Doubles an ECP2 instance P
+ *
+	@param P ECP2 instance, on exit =2*P
+ */
+extern int ECP2_dbl(ECP2 *P);
+/**	@brief Adds ECP2 instance Q to ECP2 instance P
+ *
+	@param P ECP2 instance, on exit =P+Q
+	@param Q ECP2 instance to be added to P
+ */
+extern int ECP2_add(ECP2 *P,ECP2 *Q);
+/**	@brief Subtracts ECP instance Q from ECP2 instance P
+ *
+	@param P ECP2 instance, on exit =P-Q
+	@param Q ECP2 instance to be subtracted from P
+ */
+extern void ECP2_sub(ECP2 *P,ECP2 *Q);
+/**	@brief Multiplies an ECP2 instance P by a BIG, side-channel resistant
+ *
+	Uses fixed sized windows.
+	@param P ECP2 instance, on exit =b*P
+	@param b BIG number multiplier
+
+ */
+extern void ECP2_mul(ECP2 *P,XXX::BIG b);
+/**	@brief Multiplies an ECP2 instance P by the internal modulus p, using precalculated Frobenius constant f
+ *
+	Fast point multiplication using Frobenius
+	@param P ECP2 instance, on exit = p*P
+	@param f FP2 precalculated Frobenius constant
+
+ */
+extern void ECP2_frob(ECP2 *P,YYY::FP2 *f);
+/**	@brief Calculates P=b[0]*Q[0]+b[1]*Q[1]+b[2]*Q[2]+b[3]*Q[3]
+ *
+	@param P ECP2 instance, on exit = b[0]*Q[0]+b[1]*Q[1]+b[2]*Q[2]+b[3]*Q[3]
+	@param Q ECP2 array of 4 points
+	@param b BIG array of 4 multipliers
+ */
+extern void ECP2_mul4(ECP2 *P,ECP2 *Q,XXX::BIG *b);
+
+/**	@brief Maps random BIG to curve point of correct order
+ *
+	@param P ECP2 instance of correct order
+	@param W OCTET byte array to be mapped
+ */
+extern void ECP2_mapit(ECP2 *P,octet *w);
+/**	@brief Get Group Generator from ROM
+ *
+	@param G ECP2 instance
+ */
+extern void ECP2_generator(ECP2 *G);
+}
+
+#endif
\ No newline at end of file
diff --git a/version3/cpp/ecp4.cpp b/version3/cpp/ecp4.cpp
new file mode 100644
index 0000000..33c60d1
--- /dev/null
+++ b/version3/cpp/ecp4.cpp
@@ -0,0 +1,1074 @@
+/*
+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.
+*/
+
+/* AMCL Weierstrass elliptic curve functions over FP2 */
+
+//#include <iostream>
+#include "ecp4_ZZZ.h"
+
+using namespace std;
+using namespace XXX;
+using namespace YYY;
+
+int ZZZ::ECP4_isinf(ECP4 *P)
+{
+//	if (P->inf) return 1;
+	return (FP4_iszilch(&(P->x)) & FP4_iszilch(&(P->z)));
+}
+
+/* Set P=Q */
+void ZZZ::ECP4_copy(ECP4 *P,ECP4 *Q)
+{
+//    P->inf=Q->inf;
+    FP4_copy(&(P->x),&(Q->x));
+    FP4_copy(&(P->y),&(Q->y));
+    FP4_copy(&(P->z),&(Q->z));
+}
+
+/* set P to Infinity */
+void ZZZ::ECP4_inf(ECP4 *P)
+{
+//    P->inf=1;
+    FP4_zero(&(P->x));
+    FP4_one(&(P->y));
+    FP4_zero(&(P->z));
+}
+
+/* Conditional move Q to P dependant on d */
+static void ECP4_cmove(ZZZ::ECP4 *P,ZZZ::ECP4 *Q,int d)
+{
+    FP4_cmove(&(P->x),&(Q->x),d);
+    FP4_cmove(&(P->y),&(Q->y),d);
+    FP4_cmove(&(P->z),&(Q->z),d);
+//    d=~(d-1);
+//    P->inf^=(P->inf^Q->inf)&d;
+}
+
+/* return 1 if b==c, no branching */
+static int teq(sign32 b,sign32 c)
+{
+    sign32 x=b^c;
+    x-=1;  // if x=0, x now -1
+    return (int)((x>>31)&1);
+}
+
+/* Constant time select from pre-computed table */
+static void ECP4_select(ZZZ::ECP4 *P,ZZZ::ECP4 W[],sign32 b)
+{
+    ZZZ::ECP4 MP;
+    sign32 m=b>>31;
+    sign32 babs=(b^m)-m;
+
+    babs=(babs-1)/2;
+
+    ECP4_cmove(P,&W[0],teq(babs,0));  // conditional move
+    ECP4_cmove(P,&W[1],teq(babs,1));
+    ECP4_cmove(P,&W[2],teq(babs,2));
+    ECP4_cmove(P,&W[3],teq(babs,3));
+    ECP4_cmove(P,&W[4],teq(babs,4));
+    ECP4_cmove(P,&W[5],teq(babs,5));
+    ECP4_cmove(P,&W[6],teq(babs,6));
+    ECP4_cmove(P,&W[7],teq(babs,7));
+
+    ECP4_copy(&MP,P);
+    ECP4_neg(&MP);  // minus P
+    ECP4_cmove(P,&MP,(int)(m&1));
+}
+
+/* Make P affine (so z=1) */
+void ZZZ::ECP4_affine(ECP4 *P)
+{
+    FP4 one,iz;
+    if (ECP4_isinf(P)) return;
+
+    FP4_one(&one);
+    if (FP4_isunity(&(P->z)))
+    {
+        FP4_reduce(&(P->x));
+        FP4_reduce(&(P->y));
+        return;
+    }
+
+    FP4_inv(&iz,&(P->z));
+    FP4_mul(&(P->x),&(P->x),&iz);
+    FP4_mul(&(P->y),&(P->y),&iz);
+
+    FP4_reduce(&(P->x));
+    FP4_reduce(&(P->y));
+    FP4_copy(&(P->z),&one);
+}
+
+/* return 1 if P==Q, else 0 */
+/* SU= 312 */
+int ZZZ::ECP4_equals(ECP4 *P,ECP4 *Q)
+{
+    FP4 a,b;
+ //   if (ECP4_isinf(P) && ECP4_isinf(Q)) return 1;
+ //   if (ECP4_isinf(P) || ECP4_isinf(Q)) return 0;
+
+    FP4_mul(&a,&(P->x),&(Q->z));
+    FP4_mul(&b,&(Q->x),&(P->z));
+    if (!FP4_equals(&a,&b)) return 0;
+
+    FP4_mul(&a,&(P->y),&(Q->z));
+    FP4_mul(&b,&(Q->y),&(P->z));
+    if (!FP4_equals(&a,&b)) return 0;
+    return 1;
+
+}
+
+/* extract x, y from point P */
+int ZZZ::ECP4_get(FP4 *x,FP4 *y,ECP4 *P)
+{
+	ECP4 W;
+	ECP4_copy(&W,P);
+	ECP4_affine(&W);
+    if (ECP4_isinf(&W)) return -1;
+	//ECP4_affine(P);
+    FP4_copy(y,&(W.y));
+    FP4_copy(x,&(W.x));
+    return 0;
+}
+
+/* Output point P */
+void ZZZ::ECP4_output(ECP4 *P)
+{
+    FP4 x,y;
+    if (ECP4_isinf(P))
+    {
+        printf("Infinity\n");
+        return;
+    }
+    ECP4_get(&x,&y,P);
+    printf("(");
+    FP4_output(&x);
+    printf(",");
+    FP4_output(&y);
+    printf(")\n");
+}
+
+/* Convert Q to octet string */
+void ZZZ::ECP4_toOctet(octet *W,ECP4 *Q)
+{
+	BIG b;
+	FP4 qx,qy;
+	FP2 pa,pb;
+
+    ECP4_get(&qx,&qy,Q);
+
+	FP2_copy(&pa,&(qx.a));
+	FP2_copy(&pb,&(qx.b));
+
+	FP_redc(b,&(pa.a));
+    BIG_toBytes(&(W->val[0]),b);
+    FP_redc(b,&(pa.b));
+    BIG_toBytes(&(W->val[MODBYTES_XXX]),b);
+    FP_redc(b,&(pb.a));
+    BIG_toBytes(&(W->val[2*MODBYTES_XXX]),b);
+    FP_redc(b,&(pb.b));
+    BIG_toBytes(&(W->val[3*MODBYTES_XXX]),b);
+
+	FP2_copy(&pa,&(qy.a));
+	FP2_copy(&pb,&(qy.b));
+	
+	FP_redc(b,&(pa.a));
+    BIG_toBytes(&(W->val[4*MODBYTES_XXX]),b);
+    FP_redc(b,&(pa.b));
+    BIG_toBytes(&(W->val[5*MODBYTES_XXX]),b);
+    FP_redc(b,&(pb.a));
+    BIG_toBytes(&(W->val[6*MODBYTES_XXX]),b);
+    FP_redc(b,&(pb.b));
+    BIG_toBytes(&(W->val[7*MODBYTES_XXX]),b);
+
+    W->len=8*MODBYTES_XXX;
+}
+
+/* restore Q from octet string */
+int ZZZ::ECP4_fromOctet(ECP4 *Q,octet *W)
+{
+	BIG b;
+    FP4 qx,qy;
+	FP2 pa,pb;
+
+    BIG_fromBytes(b,&(W->val[0]));
+	FP_nres(&(pa.a),b);
+    BIG_fromBytes(b,&(W->val[MODBYTES_XXX]));
+    FP_nres(&(pa.b),b);
+    BIG_fromBytes(b,&(W->val[2*MODBYTES_XXX]));
+    FP_nres(&(pb.a),b);
+    BIG_fromBytes(b,&(W->val[3*MODBYTES_XXX]));
+    FP_nres(&(pb.b),b);
+
+	FP2_copy(&(qx.a),&pa);
+	FP2_copy(&(qx.b),&pb);
+
+    BIG_fromBytes(b,&(W->val[4*MODBYTES_XXX]));
+	FP_nres(&(pa.a),b);
+    BIG_fromBytes(b,&(W->val[5*MODBYTES_XXX]));
+    FP_nres(&(pa.b),b);
+    BIG_fromBytes(b,&(W->val[6*MODBYTES_XXX]));
+    FP_nres(&(pb.a),b);
+    BIG_fromBytes(b,&(W->val[7*MODBYTES_XXX]));
+    FP_nres(&(pb.b),b);
+
+	FP2_copy(&(qy.a),&pa);
+	FP2_copy(&(qy.b),&pb);
+
+
+    if (ECP4_set(Q,&qx,&qy)) return 1;
+    return 0;
+}
+
+/* Calculate RHS of twisted curve equation x^3+B/i or x^3+Bi*/
+void ZZZ::ECP4_rhs(FP4 *rhs,FP4 *x)
+{
+    /* calculate RHS of elliptic curve equation */
+    FP4 t;
+	FP2 t2;
+    BIG b;
+    FP4_sqr(&t,x);
+
+    FP4_mul(rhs,&t,x);
+
+    /* Assuming CURVE_A=0 */
+
+    BIG_rcopy(b,CURVE_B);
+
+    FP2_from_BIG(&t2,b);
+	FP4_from_FP2(&t,&t2);
+
+#if SEXTIC_TWIST_ZZZ == D_TYPE	
+    FP4_div_i(&t);   /* IMPORTANT - here we use the correct SEXTIC twist of the curve */
+#endif
+
+#if SEXTIC_TWIST_ZZZ == M_TYPE	
+    FP4_times_i(&t);   /* IMPORTANT - here we use the correct SEXTIC twist of the curve */
+#endif
+
+    FP4_add(rhs,&t,rhs);
+    FP4_reduce(rhs);
+}
+
+/* Set P=(x,y). Return 1 if (x,y) is on the curve, else return 0*/
+/* SU= 232 */
+int ZZZ::ECP4_set(ECP4 *P,FP4 *x,FP4 *y)
+{
+    FP4 rhs,y2;
+
+    FP4_sqr(&y2,y);
+    ECP4_rhs(&rhs,x);
+
+//cout << "y2= ";
+//FP4_output(&y2);
+//cout << endl;
+//cout << "rhs= ";
+//FP4_output(&rhs);
+//cout << endl;
+
+    if (!FP4_equals(&y2,&rhs))
+    {
+		ECP4_inf(P);
+        //P->inf=1;
+        return 0;
+    }
+
+    //P->inf=0;
+    FP4_copy(&(P->x),x);
+    FP4_copy(&(P->y),y);
+
+    FP4_one(&(P->z));
+    return 1;
+}
+
+/* Set P=(x,y). Return 1 if (x,.) is on the curve, else return 0 */
+/* SU= 232 */
+int ZZZ::ECP4_setx(ECP4 *P,FP4 *x)
+{
+    FP4 y;
+    ECP4_rhs(&y,x);
+
+    if (!FP4_sqrt(&y,&y))
+    {
+		ECP4_inf(P);
+   //     P->inf=1;
+        return 0;
+    }
+
+    //P->inf=0;
+    FP4_copy(&(P->x),x);
+    FP4_copy(&(P->y),&y);
+    FP4_one(&(P->z));
+    return 1;
+}
+
+/* Set P=-P */
+/* SU= 8 */
+void ZZZ::ECP4_neg(ECP4 *P)
+{
+//	if (ECP4_isinf(P)) return;
+	FP4_norm(&(P->y));
+    FP4_neg(&(P->y),&(P->y));
+    FP4_norm(&(P->y));
+}
+
+/* R+=R */
+/* return -1 for Infinity, 0 for addition, 1 for doubling */
+int ZZZ::ECP4_dbl(ECP4 *P)
+{
+    FP4 t0,t1,t2,t3,iy,x3,y3;
+//    if (P->inf) return -1;
+
+	FP4_copy(&iy,&(P->y));		//FP4 iy=new FP4(y);
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+	FP4_times_i(&iy);			//iy.mul_ip(); 
+	//FP4_norm(&iy);				//iy.norm();
+#endif
+
+	FP4_sqr(&t0,&(P->y));			//t0.sqr();   
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+	FP4_times_i(&t0);			//t0.mul_ip(); 
+#endif
+
+	FP4_mul(&t1,&iy,&(P->z));	//t1.mul(z);
+	FP4_sqr(&t2,&(P->z));				//t2.sqr();
+
+	FP4_add(&(P->z),&t0,&t0);	//z.add(t0); 
+	FP4_norm(&(P->z));				//z.norm(); 
+	FP4_add(&(P->z),&(P->z),&(P->z));	//z.add(z); 
+	FP4_add(&(P->z),&(P->z),&(P->z));	//z.add(z); 
+	FP4_norm(&(P->z));			//z.norm();  
+
+	FP4_imul(&t2,&t2,3*CURVE_B_I);	//t2.imul(3*ROM.CURVE_B_I); 
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+	FP4_times_i(&t2);
+	//FP4_norm(&t2);
+#endif
+
+	FP4_mul(&x3,&t2,&(P->z));	//x3.mul(z); 
+
+	FP4_add(&y3,&t0,&t2);		//y3.add(t2); 
+	FP4_norm(&y3);				//y3.norm();
+	FP4_mul(&(P->z),&(P->z),&t1);	//z.mul(t1);
+
+	FP4_add(&t1,&t2,&t2);		//t1.add(t2); 
+	FP4_add(&t2,&t2,&t1);		//t2.add(t1); 
+	FP4_norm(&t2);				//t2.norm();  
+	FP4_sub(&t0,&t0,&t2);		//t0.sub(t2); 
+	FP4_norm(&t0);				//t0.norm();                           //y^2-9bz^2
+	FP4_mul(&y3,&y3,&t0);		//y3.mul(t0); 
+	FP4_add(&(P->y),&y3,&x3);		//y3.add(x3);                          //(y^2+3z*2)(y^2-9z^2)+3b.z^2.8y^2
+
+	FP4_mul(&t1,&(P->x),&iy);		//t1.mul(iy);						//
+
+	FP4_norm(&t0);			//x.norm(); 
+	FP4_mul(&(P->x),&t0,&t1);	//x.mul(t1); 
+	FP4_add(&(P->x),&(P->x),&(P->x));	//x.add(x);       //(y^2-9bz^2)xy2
+
+	FP4_norm(&(P->x));			//x.norm(); 
+
+	FP4_norm(&(P->y));			//y.norm();
+
+    return 1;
+}
+
+/* Set P+=Q */
+
+int ZZZ::ECP4_add(ECP4 *P,ECP4 *Q)
+{
+    FP4 t0,t1,t2,t3,t4,x3,y3,z3;
+	int b3=3*CURVE_B_I;
+/*    if (Q->inf) return 0;
+    if (P->inf)
+    {
+        ECP4_copy(P,Q);
+        return 0;
+    }
+*/
+	FP4_mul(&t0,&(P->x),&(Q->x));	//t0.mul(Q.x);         // x.Q.x
+	FP4_mul(&t1,&(P->y),&(Q->y));	//t1.mul(Q.y);		 // y.Q.y
+
+	FP4_mul(&t2,&(P->z),&(Q->z));	//t2.mul(Q.z);
+	FP4_add(&t3,&(P->x),&(P->y));	//t3.add(y); 
+	FP4_norm(&t3);				//t3.norm();          //t3=X1+Y1         
+	FP4_add(&t4,&(Q->x),&(Q->y));	//t4.add(Q.y); 
+	FP4_norm(&t4);				//t4.norm();			//t4=X2+Y2
+	FP4_mul(&t3,&t3,&t4);		//t3.mul(t4);						//t3=(X1+Y1)(X2+Y2)
+	FP4_add(&t4,&t0,&t1);		//t4.add(t1);		//t4=X1.X2+Y1.Y2
+
+	FP4_sub(&t3,&t3,&t4);		//t3.sub(t4); 
+	FP4_norm(&t3);				//t3.norm(); 
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+	FP4_times_i(&t3);			//t3.mul_ip();  
+	//FP4_norm(&t3);				//t3.norm();         //t3=(X1+Y1)(X2+Y2)-(X1.X2+Y1.Y2) = X1.Y2+X2.Y1
+#endif
+                   
+	FP4_add(&t4,&(P->y),&(P->z));	//t4.add(z); 
+	FP4_norm(&t4);				//t4.norm();			//t4=Y1+Z1
+
+	FP4_add(&x3,&(Q->y),&(Q->z));	//x3.add(Q.z); 
+	FP4_norm(&x3);				//x3.norm();			//x3=Y2+Z2
+
+	FP4_mul(&t4,&t4,&x3);		//t4.mul(x3);						//t4=(Y1+Z1)(Y2+Z2)
+
+	FP4_add(&x3,&t1,&t2);		//x3.add(t2);						//X3=Y1.Y2+Z1.Z2
+	
+	FP4_sub(&t4,&t4,&x3);		//t4.sub(x3); 
+	FP4_norm(&t4);				//t4.norm(); 
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+	FP4_times_i(&t4);			//t4.mul_ip(); 
+	//FP4_norm(&t4);				//t4.norm();          //t4=(Y1+Z1)(Y2+Z2) - (Y1.Y2+Z1.Z2) = Y1.Z2+Y2.Z1
+#endif
+
+	FP4_add(&x3,&(P->x),&(P->z));	//x3.add(z); 
+	FP4_norm(&x3);				//x3.norm();	// x3=X1+Z1
+		
+	FP4_add(&y3,&(Q->x),&(Q->z));	//y3.add(Q.z); 
+	FP4_norm(&y3);				//y3.norm();				// y3=X2+Z2
+	FP4_mul(&x3,&x3,&y3);		//x3.mul(y3);							// x3=(X1+Z1)(X2+Z2)
+
+	FP4_add(&y3,&t0,&t2);		//y3.add(t2);							// y3=X1.X2+Z1+Z2
+	FP4_sub(&y3,&x3,&y3);		//y3.rsub(x3); 
+	FP4_norm(&y3);				//y3.norm();				// y3=(X1+Z1)(X2+Z2) - (X1.X2+Z1.Z2) = X1.Z2+X2.Z1
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+	FP4_times_i(&t0);			//t0.mul_ip(); 
+	//FP4_norm(&t0);				//t0.norm(); // x.Q.x
+	FP4_times_i(&t1);			//t1.mul_ip(); 
+	//FP4_norm(&t1);				//t1.norm(); // y.Q.y
+#endif
+
+	FP4_add(&x3,&t0,&t0);		//x3.add(t0); 
+	FP4_add(&t0,&t0,&x3);		//t0.add(x3); 
+	FP4_norm(&t0);				//t0.norm();
+	FP4_imul(&t2,&t2,b3);		//t2.imul(b); 	
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+	FP4_times_i(&t2);
+#endif
+
+	FP4_add(&z3,&t1,&t2);		//z3.add(t2); 
+	FP4_norm(&z3);				//z3.norm();
+	FP4_sub(&t1,&t1,&t2);		//t1.sub(t2); 
+	FP4_norm(&t1);				//t1.norm(); 
+	FP4_imul(&y3,&y3,b3);		//y3.imul(b); 
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+	FP4_times_i(&y3);
+	//FP4_norm(&y3);
+#endif
+
+	FP4_mul(&x3,&y3,&t4);		//x3.mul(t4); 
+
+	FP4_mul(&t2,&t3,&t1);		//t2.mul(t1); 
+	FP4_sub(&(P->x),&t2,&x3);		//x3.rsub(t2);
+	FP4_mul(&y3,&y3,&t0);		//y3.mul(t0); 
+	FP4_mul(&t1,&t1,&z3);		//t1.mul(z3); 
+	FP4_add(&(P->y),&y3,&t1);		//y3.add(t1);
+	FP4_mul(&t0,&t0,&t3);		//t0.mul(t3); 
+	FP4_mul(&z3,&z3,&t4);		//z3.mul(t4); 
+	FP4_add(&(P->z),&z3,&t0);		//z3.add(t0);
+
+
+	FP4_norm(&(P->x));			//x.norm(); 
+	FP4_norm(&(P->y));			//y.norm();
+	FP4_norm(&(P->z));			//z.norm();
+
+    return 0;
+}
+
+/* Set P-=Q */
+/* SU= 16 */
+void ZZZ::ECP4_sub(ECP4 *P,ECP4 *Q)
+{
+	ECP4 NQ;
+	ECP4_copy(&NQ,Q);
+	ECP4_neg(&NQ);
+    //ECP4_neg(Q);
+    ECP4_add(P,&NQ);
+    //ECP4_neg(Q);
+}
+
+
+void ZZZ::ECP4_reduce(ECP4 *P)
+{
+	FP4_reduce(&(P->x));
+	FP4_reduce(&(P->y));
+	FP4_reduce(&(P->z));
+}
+
+/* P*=e */
+/* SU= 280 */
+void ZZZ::ECP4_mul(ECP4 *P,BIG e)
+{
+    /* fixed size windows */
+    int i,nb,s,ns;
+    BIG mt,t;
+    ECP4 Q,W[8],C;
+    sign8 w[1+(NLEN_XXX*BASEBITS_XXX+3)/4];
+
+    if (ECP4_isinf(P)) return;
+    //ECP4_affine(P);
+
+    /* precompute table */
+
+    ECP4_copy(&Q,P);
+    ECP4_dbl(&Q);
+    ECP4_copy(&W[0],P);
+
+    for (i=1; i<8; i++)
+    {
+        ECP4_copy(&W[i],&W[i-1]);
+        ECP4_add(&W[i],&Q);
+    }
+
+    /* make exponent odd - add 2P if even, P if odd */
+    BIG_copy(t,e);
+    s=BIG_parity(t);
+    BIG_inc(t,1);
+    BIG_norm(t);
+    ns=BIG_parity(t);
+    BIG_copy(mt,t);
+    BIG_inc(mt,1);
+    BIG_norm(mt);
+    BIG_cmove(t,mt,s);
+    ECP4_cmove(&Q,P,ns);
+    ECP4_copy(&C,&Q);
+
+    nb=1+(BIG_nbits(t)+3)/4;
+
+    /* convert exponent to signed 4-bit window */
+    for (i=0; i<nb; i++)
+    {
+        w[i]=BIG_lastbits(t,5)-16;
+        BIG_dec(t,w[i]);
+        BIG_norm(t);
+        BIG_fshr(t,4);
+    }
+    w[nb]=BIG_lastbits(t,5);
+
+    ECP4_copy(P,&W[(w[nb]-1)/2]);
+    for (i=nb-1; i>=0; i--)
+    {
+        ECP4_select(&Q,W,w[i]);
+        ECP4_dbl(P);
+        ECP4_dbl(P);
+        ECP4_dbl(P);
+        ECP4_dbl(P);
+        ECP4_add(P,&Q);
+    }
+    ECP4_sub(P,&C); /* apply correction */
+	ECP4_affine(P);
+}
+
+// calculate frobenius constants 
+void ZZZ::ECP4_frob_constants(FP2 F[3])
+{
+    FP fx,fy;
+	FP2 X;
+
+    FP_rcopy(&fx,Fra);
+    FP_rcopy(&fy,Frb);
+    FP2_from_FPs(&X,&fx,&fy);
+
+	FP2_sqr(&F[0],&X);		// FF=F^2=(1+i)^(p-7)/6
+	FP2_copy(&F[2],&F[0]);
+	FP2_mul_ip(&F[2]);		// W=(1+i)^6/6.(1+i)^(p-7)/6 = (1+i)^(p-1)/6
+	FP2_norm(&F[2]);
+	FP2_sqr(&F[1],&F[2]);
+	FP2_mul(&F[2],&F[2],&F[1]);  // W=(1+i)^(p-1)/2
+
+	FP2_copy(&F[1],&X);
+
+#if SEXTIC_TWIST_ZZZ == M_TYPE	
+	FP2_mul_ip(&F[1]);		// (1+i)^12/12.(1+i)^(p-7)/12 = (1+i)^(p+5)/12
+	FP2_inv(&F[1],&F[1]);		// (1+i)^-(p+5)/12
+	FP2_sqr(&F[0],&F[1]);		// (1+i)^-(p+5)/6
+#endif
+
+	FP2_mul_ip(&F[0]);		// FF=(1+i)^(p-7)/6.(1+i) = (1+i)^(p-1)/6					// (1+i)^6/6.(1+i)^-(p+5)/6 = (1+i)^-(p-1)/6
+	FP2_norm(&F[0]);
+	FP2_mul(&F[1],&F[1],&F[0]);  // FFF = (1+i)^(p-7)/12 . (1+i)^(p-1)/6 = (1+i)^(p-3)/4	// (1+i)^-(p+5)/12 . (1+i)^-(p-1)/6 = (1+i)^-(p+1)/4
+
+}
+
+/* Calculates q^n.P using Frobenius constants */
+void ZZZ::ECP4_frob(ECP4 *P,FP2 F[3],int n)
+{
+	int i;
+	FP4 X,Y,Z;
+//    if (P->inf) return;
+
+	//ECP4_get(&X,&Y,P);		// F=(1+i)^(p-7)/12
+
+	FP4_copy(&X,&(P->x));
+	FP4_copy(&Y,&(P->y));
+	FP4_copy(&Z,&(P->z));
+
+	for (i=0;i<n;i++)
+	{
+		FP4_frob(&X,&F[2]);		// X^p
+		FP4_pmul(&X,&X,&F[0]);	// X^p.(1+i)^(p-1)/6									// X^p.(1+i)^-(p-1)/6
+		
+		FP4_frob(&Y,&F[2]);		// Y^p
+		FP4_pmul(&Y,&Y,&F[1]);
+		FP4_times_i(&Y);		// Y.p.(1+i)^(p-3)/4.(1+i)^(2/4) = Y^p.(1+i)^(p-1)/4	// (1+i)^-(p+1)/4 .(1+i)^2/4 = Y^p.(1+i)^-(p-1)/4
+
+		FP4_frob(&Z,&F[2]);
+	}
+
+	FP4_copy(&(P->x),&X);
+	FP4_copy(&(P->y),&Y);
+	FP4_copy(&(P->z),&Z);
+	
+
+	//ECP4_set(P,&X,&Y);
+}
+
+/* Side channel attack secure */
+// Bos & Costello https://eprint.iacr.org/2013/458.pdf
+// Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
+
+void ZZZ::ECP4_mul8(ECP4 *P,ECP4 Q[8],BIG u[8])
+{
+    int i,j,k,nb,pb1,pb2,bt;
+	ECP4 T1[8],T2[8],W;
+    BIG mt,t[8];
+    sign8 w1[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 s1[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 w2[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 s2[NLEN_XXX*BASEBITS_XXX+1];	
+	FP2 X[3];
+
+	ECP4_frob_constants(X);
+
+    for (i=0; i<8; i++)
+	{
+        //ECP4_affine(&Q[i]);
+        BIG_copy(t[i],u[i]);
+	}
+// Precomputed table
+    ECP4_copy(&T1[0],&Q[0]); // Q[0]
+    ECP4_copy(&T1[1],&T1[0]);
+	ECP4_add(&T1[1],&Q[1]);	// Q[0]+Q[1]
+    ECP4_copy(&T1[2],&T1[0]);
+	ECP4_add(&T1[2],&Q[2]);	// Q[0]+Q[2]
+	ECP4_copy(&T1[3],&T1[1]);
+	ECP4_add(&T1[3],&Q[2]);	// Q[0]+Q[1]+Q[2]
+	ECP4_copy(&T1[4],&T1[0]);
+	ECP4_add(&T1[4],&Q[3]);  // Q[0]+Q[3]
+	ECP4_copy(&T1[5],&T1[1]);
+	ECP4_add(&T1[5],&Q[3]);	// Q[0]+Q[1]+Q[3]
+	ECP4_copy(&T1[6],&T1[2]);
+	ECP4_add(&T1[6],&Q[3]);	// Q[0]+Q[2]+Q[3]
+	ECP4_copy(&T1[7],&T1[3]);
+	ECP4_add(&T1[7],&Q[3]);	// Q[0]+Q[1]+Q[2]+Q[3]
+
+//  Use Frobenius 
+
+	for (i=0;i<8;i++)
+	{
+		ECP4_copy(&T2[i],&T1[i]);
+		ECP4_frob(&T2[i],X,4);
+	}
+
+// Make them odd
+	pb1=1-BIG_parity(t[0]);
+	BIG_inc(t[0],pb1);
+	BIG_norm(t[0]);
+
+	pb2=1-BIG_parity(t[4]);
+	BIG_inc(t[4],pb2);
+	BIG_norm(t[4]);
+
+// Number of bits
+    BIG_zero(mt);
+    for (i=0; i<8; i++)
+    {
+        BIG_or(mt,mt,t[i]);
+    }
+    nb=1+BIG_nbits(mt);
+
+// Sign pivot 
+	s1[nb-1]=1;
+	s2[nb-1]=1;
+	for (i=0;i<nb-1;i++)
+	{
+        BIG_fshr(t[0],1);
+		s1[i]=2*BIG_parity(t[0])-1;
+        BIG_fshr(t[4],1);
+		s2[i]=2*BIG_parity(t[4])-1;
+	}
+
+
+// Recoded exponents
+    for (i=0; i<nb; i++)
+    {
+		w1[i]=0;
+		k=1;
+		for (j=1; j<4; j++)
+		{
+			bt=s1[i]*BIG_parity(t[j]);
+			BIG_fshr(t[j],1);
+
+			BIG_dec(t[j],(bt>>1));
+			BIG_norm(t[j]);
+			w1[i]+=bt*k;
+			k*=2;
+        }
+
+		w2[i]=0;
+		k=1;
+		for (j=5; j<8; j++)
+		{
+			bt=s2[i]*BIG_parity(t[j]);
+			BIG_fshr(t[j],1);
+
+			BIG_dec(t[j],(bt>>1));
+			BIG_norm(t[j]);
+			w2[i]+=bt*k;
+			k*=2;
+        }
+    }	
+
+// Main loop
+	ECP4_select(P,T1,2*w1[nb-1]+1);
+	ECP4_select(&W,T2,2*w2[nb-1]+1);
+	ECP4_add(P,&W);
+    for (i=nb-2; i>=0; i--)
+    {
+        ECP4_dbl(P);
+        ECP4_select(&W,T1,2*w1[i]+s1[i]);
+        ECP4_add(P,&W);
+        ECP4_select(&W,T2,2*w2[i]+s2[i]);
+        ECP4_add(P,&W);
+    }
+
+// apply corrections
+	ECP4_copy(&W,P);   
+	ECP4_sub(&W,&Q[0]);
+	ECP4_cmove(P,&W,pb1);
+	ECP4_copy(&W,P);   
+	ECP4_sub(&W,&Q[4]);
+	ECP4_cmove(P,&W,pb2);
+
+	ECP4_affine(P);
+}
+/*
+void ZZZ::ECP4_mul8(ECP4 *P,ECP4 Q[8],BIG u[8])
+{
+    int i,j,a[4],nb,pb;
+    ECP4 W[8],Z[8],T,C;
+    BIG mt,t[8];
+    sign8 w[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 z[NLEN_XXX*BASEBITS_XXX+1];
+    FP fx,fy;
+	FP2 X;
+
+    FP_rcopy(&fx,Fra);
+    FP_rcopy(&fy,Frb);
+    FP2_from_FPs(&X,&fx,&fy);
+
+    for (i=0; i<8; i++)
+        BIG_copy(t[i],u[i]);
+
+    // precompute tables 
+
+// 12 add/subs 
+
+    ECP4_copy(&W[0],&Q[0]);
+    ECP4_sub(&W[0],&Q[1]);  // P-Q 
+    ECP4_copy(&W[1],&W[0]);
+    ECP4_copy(&W[2],&W[0]);
+    ECP4_copy(&W[3],&W[0]);
+    ECP4_copy(&W[4],&Q[0]);
+    ECP4_add(&W[4],&Q[1]);  // P+Q 
+    ECP4_copy(&W[5],&W[4]);
+    ECP4_copy(&W[6],&W[4]);
+    ECP4_copy(&W[7],&W[4]);
+
+    ECP4_copy(&T,&Q[2]);
+    ECP4_sub(&T,&Q[3]);       // R-S 
+    ECP4_sub(&W[1],&T);
+    ECP4_add(&W[2],&T);
+    ECP4_sub(&W[5],&T);
+    ECP4_add(&W[6],&T);
+    ECP4_copy(&T,&Q[2]);
+    ECP4_add(&T,&Q[3]);      // R+S 
+    ECP4_sub(&W[0],&T);
+    ECP4_add(&W[3],&T);
+    ECP4_sub(&W[4],&T);
+    ECP4_add(&W[7],&T);
+
+
+// Use Frobenius 
+
+	for (i=0;i<8;i++)
+	{
+		ECP4_copy(&Z[i],&W[i]);
+		ECP4_frob(&Z[i],&X,4);
+	}
+
+    // if multiplier is even add 1 to multiplier, and add P to correction 
+    ECP4_inf(&C);
+
+    BIG_zero(mt);
+    for (i=0; i<8; i++)
+    {
+		pb=BIG_parity(t[i]);
+		BIG_inc(t[i],1-pb);
+		BIG_norm(t[i]);
+		ECP4_copy(&T,&C);
+		ECP4_add(&T,&Q[i]);
+		ECP4_cmove(&C,&T,1-pb);
+
+
+        BIG_add(mt,mt,t[i]);
+        BIG_norm(mt);
+    }
+
+    nb=1+BIG_nbits(mt);
+
+    // convert exponents to signed 1-bit windows 
+    for (j=0; j<nb; j++)
+    {
+        for (i=0; i<4; i++)
+        {
+            a[i]=BIG_lastbits(t[i],2)-2;
+            BIG_dec(t[i],a[i]);
+            BIG_norm(t[i]);
+            BIG_fshr(t[i],1);
+        }
+        w[j]=8*a[0]+4*a[1]+2*a[2]+a[3];
+    }
+    w[nb]=8*BIG_lastbits(t[0],2)+4*BIG_lastbits(t[1],2)+2*BIG_lastbits(t[2],2)+BIG_lastbits(t[3],2);
+
+
+    for (j=0; j<nb; j++)
+    {
+        for (i=0; i<4; i++)
+        {
+            a[i]=BIG_lastbits(t[i+4],2)-2;
+            BIG_dec(t[i+4],a[i]);
+            BIG_norm(t[i+4]);
+            BIG_fshr(t[i+4],1);
+        }
+        z[j]=8*a[0]+4*a[1]+2*a[2]+a[3];
+    }
+    z[nb]=8*BIG_lastbits(t[4],2)+4*BIG_lastbits(t[5],2)+2*BIG_lastbits(t[6],2)+BIG_lastbits(t[7],2);
+
+
+    ECP4_copy(P,&W[(w[nb]-1)/2]);
+	ECP4_add(P,&Z[(z[nb]-1)/2]);
+    for (i=nb-1; i>=0; i--)
+    {
+		ECP4_dbl(P);
+        ECP4_select(&T,W,w[i]);
+        ECP4_add(P,&T);
+        ECP4_select(&T,Z,z[i]);
+        ECP4_add(P,&T);
+    }
+    ECP4_sub(P,&C); // apply correction 
+	ECP4_reduce(P);
+}
+*/
+/* Map to hash value to point on G2 from random BIG */
+
+void ZZZ::ECP4_mapit(ECP4 *Q,octet *W)
+{
+    BIG q,one,x,hv;
+    FP2 X[3],T;
+	FP4 X4,Y4;
+
+    ECP4 xQ, x2Q, x3Q, x4Q;
+
+	BIG_fromBytes(hv,W->val);
+    BIG_rcopy(q,Modulus);
+    BIG_one(one);
+    BIG_mod(hv,q);
+
+    for (;;)
+    {
+        FP2_from_BIGs(&T,one,hv);  /*******/
+		FP4_from_FP2(&X4,&T);
+        if (ECP4_setx(Q,&X4)) break;
+        BIG_inc(hv,1);
+    }
+
+	ECP4_frob_constants(X);
+
+    BIG_rcopy(x,CURVE_Bnx);
+
+    // Efficient hash maps to G2 on BLS24 curves - Budroni, Pintore 
+	// Q -> x4Q -x3Q -Q + F(x3Q-x2Q) + F(F(x2Q-xQ)) + F(F(F(xQ-Q))) +F(F(F(F(2Q))))
+
+	ECP4_copy(&xQ,Q);
+	ECP4_mul(&xQ,x);
+	ECP4_copy(&x2Q,&xQ);
+	ECP4_mul(&x2Q,x);
+	ECP4_copy(&x3Q,&x2Q);
+	ECP4_mul(&x3Q,x);
+	ECP4_copy(&x4Q,&x3Q);
+	ECP4_mul(&x4Q,x);
+
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	ECP4_neg(&xQ);
+	ECP4_neg(&x3Q);
+#endif
+
+	ECP4_sub(&x4Q,&x3Q);
+	ECP4_sub(&x4Q,Q);
+
+	ECP4_sub(&x3Q,&x2Q);
+	ECP4_frob(&x3Q,X,1);
+
+	ECP4_sub(&x2Q,&xQ);
+	ECP4_frob(&x2Q,X,2);
+
+	ECP4_sub(&xQ,Q);
+	ECP4_frob(&xQ,X,3);
+
+	ECP4_dbl(Q);
+	ECP4_frob(Q,X,4);
+
+	ECP4_add(Q,&x4Q);
+	ECP4_add(Q,&x3Q);
+	ECP4_add(Q,&x2Q);
+	ECP4_add(Q,&xQ);
+
+	ECP4_affine(Q);
+
+}
+
+// ECP$ Get Group Generator
+
+void ZZZ::ECP4_generator(ECP4 *G)
+{
+	BIG a,b;
+	FP2 Aa,Bb;
+	FP4 X,Y;
+
+	BIG_rcopy(a,CURVE_Pxaa);
+	BIG_rcopy(b,CURVE_Pxab);
+	FP2_from_BIGs(&Aa,a,b);
+
+	BIG_rcopy(a,CURVE_Pxba);
+	BIG_rcopy(b,CURVE_Pxbb);
+	FP2_from_BIGs(&Bb,a,b);
+
+	FP4_from_FP2s(&X,&Aa,&Bb);
+
+	BIG_rcopy(a,CURVE_Pyaa);
+	BIG_rcopy(b,CURVE_Pyab);
+	FP2_from_BIGs(&Aa,a,b);
+
+	BIG_rcopy(a,CURVE_Pyba);
+	BIG_rcopy(b,CURVE_Pybb);
+	FP2_from_BIGs(&Bb,a,b);
+
+	FP4_from_FP2s(&Y,&Aa,&Bb);
+
+	ECP4_set(G,&X,&Y);
+}
+
+
+// g++ -O2 ecp4_BLS24.cpp fp4_BLS24.cpp fp2_BLS24.cpp fp_BLS24.cpp big_XXX.cpp rand.cpp hash.cpp rom_field_BLS24.cpp rom_curve_BLS24.cpp oct.cpp -o ecp4_BLS24.exe
+/*
+int main()
+{
+	int i;
+	ECP4 G,P;
+	FP2 Aa,Bb,f;
+	FP4 X,Y;
+	BIG a,b,r,p;
+	char w[100];
+	octet W= {0,sizeof(w),w};
+
+	ECP4_ggg(&G);
+
+	BIG_rcopy(a,Fra);
+    BIG_rcopy(b,Frb);
+	FP2_from_BIGs(&f,a,b);
+
+	
+	if (G.inf) cout << "Failed to set - point not on curve" << endl;
+	else cout << "set success" << endl;
+
+	ECP4_output(&G);
+	ECP4_copy(&P,&G);
+
+	//ECP4_reduce(&G);
+	//ECP4_reduce(&P);
+
+	BIG_rcopy(r,CURVE_Order);
+	BIG_rcopy(p,Modulus);
+
+	BIG_output(r);
+	cout << endl;
+
+	ECP4_mul(&G,r);
+	ECP4_output(&G);
+	cout << endl;
+
+	ECP4_copy(&G,&P);
+
+	cout << "pG = ";
+	ECP4_mul(&G,p);
+	ECP4_output(&G);
+	cout << endl;
+
+	cout << "G^p= ";
+	ECP4_frob(&P,&f,1);
+	ECP4_output(&P);
+	cout << endl;
+
+
+	for (i=0;i<MODBYTES_XXX;i++)
+	{
+		W.val[i]=i+11;
+	}
+	W.len=MODBYTES_XXX;
+
+	printf("W= ");
+	OCT_output(&W);
+	printf("\n");
+
+	ECP4_mapit(&P,&W);
+
+	cout << "Hash to P= ";
+	ECP4_output(&P);
+	cout << endl;
+
+	ECP4_mul(&P,r);
+
+	cout << "rP= ";
+	ECP4_output(&P);
+	cout << endl;
+
+
+
+//	ECP4_dbl(&G);
+//	ECP4_output(&G);
+//	ECP4_reduce(&G);
+//	cout << endl;
+//	ECP4_add(&G,&P);
+//	ECP4_output(&G);
+//	cout << endl;
+
+
+	return 0;
+}
+*/
+
diff --git a/version3/cpp/ecp4.h b/version3/cpp/ecp4.h
new file mode 100644
index 0000000..98b383b
--- /dev/null
+++ b/version3/cpp/ecp4.h
@@ -0,0 +1,243 @@
+#ifndef ECP4_ZZZ_H
+#define ECP4_ZZZ_H
+
+#include "fp4_YYY.h"
+#include "config_curve_ZZZ.h"
+
+using namespace amcl;
+
+namespace YYY {
+
+extern const XXX::BIG Fra; /**< real part of BN curve Frobenius Constant */
+extern const XXX::BIG Frb; /**< imaginary part of BN curve Frobenius Constant */
+
+}
+
+namespace ZZZ {
+
+/**
+	@brief ECP4 Structure - Elliptic Curve Point over quadratic extension field
+*/
+
+typedef struct
+{
+//    int inf; /**< Infinity Flag */
+    YYY::FP4 x;   /**< x-coordinate of point */
+    YYY::FP4 y;   /**< y-coordinate of point */
+    YYY::FP4 z;   /**< z-coordinate of point */
+} ECP4;
+
+
+/* Curve Params - see rom.c */
+extern const int CURVE_A;		/**< Elliptic curve A parameter */
+extern const int CURVE_B_I;		/**< Elliptic curve B parameter */
+extern const XXX::BIG CURVE_B;     /**< Elliptic curve B parameter */
+extern const XXX::BIG CURVE_Order; /**< Elliptic curve group order */
+extern const XXX::BIG CURVE_Cof;   /**< Elliptic curve cofactor */
+extern const XXX::BIG CURVE_Bnx;   /**< Elliptic curve parameter */
+
+
+/* Generator point on G1 */
+extern const XXX::BIG CURVE_Gx; /**< x-coordinate of generator point in group G1  */
+extern const XXX::BIG CURVE_Gy; /**< y-coordinate of generator point in group G1  */
+
+/* For Pairings only */
+
+/* Generator point on G2 */
+extern const XXX::BIG CURVE_Pxaa; /**< real part of x-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pxab; /**< imaginary part of x-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pxba; /**< real part of x-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pxbb; /**< imaginary part of x-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pyaa; /**< real part of y-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pyab; /**< imaginary part of y-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pyba; /**< real part of y-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pybb; /**< imaginary part of y-coordinate of generator point in group G2 */
+
+/* ECP4 E(FP4) prototypes */
+/**	@brief Tests for ECP4 point equal to infinity
+ *
+	@param P ECP4 point to be tested
+	@return 1 if infinity, else returns 0
+ */
+extern int ECP4_isinf(ECP4 *P);
+/**	@brief Copy ECP4 point to another ECP4 point
+ *
+	@param P ECP4 instance, on exit = Q
+	@param Q ECP4 instance to be copied
+ */
+extern void ECP4_copy(ECP4 *P,ECP4 *Q);
+/**	@brief Set ECP4 to point-at-infinity
+ *
+	@param P ECP4 instance to be set to infinity
+ */
+extern void ECP4_inf(ECP4 *P);
+/**	@brief Tests for equality of two ECP4s
+ *
+	@param P ECP4 instance to be compared
+	@param Q ECP4 instance to be compared
+	@return 1 if P=Q, else returns 0
+ */
+extern int ECP4_equals(ECP4 *P,ECP4 *Q);
+
+/**	@brief Converts an ECP4 point from Projective (x,y,z) coordinates to affine (x,y) coordinates
+ *
+	@param P ECP4 instance to be converted to affine form
+ */
+extern void ECP4_affine(ECP4 *P);
+
+
+/**	@brief Extract x and y coordinates of an ECP4 point P
+ *
+	If x=y, returns only x
+	@param x FP4 on exit = x coordinate of point
+	@param y FP4 on exit = y coordinate of point (unless x=y)
+	@param P ECP4 instance (x,y)
+	@return -1 if P is point-at-infinity, else 0
+ */
+extern int ECP4_get(YYY::FP4 *x,YYY::FP4 *y,ECP4 *P);
+/**	@brief Formats and outputs an ECP4 point to the console, converted to affine coordinates
+ *
+	@param P ECP4 instance to be printed
+ */
+extern void ECP4_output(ECP4 *P);
+
+/**	@brief Formats and outputs an ECP4 point to an octet string
+ *
+	The octet string is created in the form x|y.
+	Convert the real and imaginary parts of the x and y coordinates to big-endian base 256 form.
+	@param S output octet string
+	@param P ECP4 instance to be converted to an octet string
+ */
+extern void ECP4_toOctet(octet *S,ECP4 *P);
+/**	@brief Creates an ECP4 point from an octet string
+ *
+	The octet string is in the form x|y
+	The real and imaginary parts of the x and y coordinates are in big-endian base 256 form.
+	@param P ECP4 instance to be created from the octet string
+	@param S input octet string
+	return 1 if octet string corresponds to a point on the curve, else 0
+ */
+extern int ECP4_fromOctet(ECP4 *P,octet *S);
+/**	@brief Calculate Right Hand Side of curve equation y^2=f(x)
+ *
+	Function f(x)=x^3+Ax+B
+	Used internally.
+	@param r FP4 value of f(x)
+	@param x FP4 instance
+ */
+extern void ECP4_rhs(YYY::FP4 *r,YYY::FP4 *x);
+/**	@brief Set ECP4 to point(x,y) given x and y
+ *
+	Point P set to infinity if no such point on the curve.
+	@param P ECP4 instance to be set (x,y)
+	@param x FP4 x coordinate of point
+	@param y FP4 y coordinate of point
+	@return 1 if point exists, else 0
+ */
+extern int ECP4_set(ECP4 *P,YYY::FP4 *x,YYY::FP4 *y);
+/**	@brief Set ECP to point(x,[y]) given x
+ *
+	Point P set to infinity if no such point on the curve. Otherwise y coordinate is calculated from x.
+	@param P ECP instance to be set (x,[y])
+	@param x BIG x coordinate of point
+	@return 1 if point exists, else 0
+ */
+extern int ECP4_setx(ECP4 *P,YYY::FP4 *x);
+/**	@brief Negation of an ECP4 point
+ *
+	@param P ECP4 instance, on exit = -P
+ */
+extern void ECP4_neg(ECP4 *P);
+
+/**	@brief Reduction of an ECP4 point
+ *
+	@param P ECP4 instance, on exit (x,y) are reduced wrt the modulus
+ */
+extern void ECP4_reduce(ECP4 *P);
+
+
+/**	@brief Doubles an ECP4 instance P and returns slope
+ *
+	@param P ECP4 instance, on exit =2*P
+	@param lam FP4 instance, slope of line
+ */
+//extern int ECP4_sdbl(ECP4 *P,FP4 *lam);
+/**	@brief Adds ECP4 instance Q to ECP4 instance P and returns slope
+ *
+	@param P ECP4 instance, on exit =P+Q
+	@param Q ECP4 instance to be added to P
+	@param lam FP4 instance, slope of line
+ */
+//extern int ECP4_sadd(ECP4 *P,ECP4 *Q,FP4 *lam);
+
+
+/**	@brief Doubles an ECP4 instance P
+ *
+	@param P ECP4 instance, on exit =2*P
+ */
+extern int ECP4_dbl(ECP4 *P);
+/**	@brief Adds ECP4 instance Q to ECP4 instance P
+ *
+	@param P ECP4 instance, on exit =P+Q
+	@param Q ECP4 instance to be added to P
+ */
+extern int ECP4_add(ECP4 *P,ECP4 *Q);
+/**	@brief Subtracts ECP instance Q from ECP4 instance P
+ *
+	@param P ECP4 instance, on exit =P-Q
+	@param Q ECP4 instance to be subtracted from P
+ */
+extern void ECP4_sub(ECP4 *P,ECP4 *Q);
+/**	@brief Multiplies an ECP4 instance P by a BIG, side-channel resistant
+ *
+	Uses fixed sized windows.
+	@param P ECP4 instance, on exit =b*P
+	@param b BIG number multiplier
+
+ */
+extern void ECP4_mul(ECP4 *P,XXX::BIG b);
+
+/**	@brief Calculates required Frobenius constants
+ *
+	Calculate Frobenius constants
+	@param F array of FP2 precalculated constants
+
+ */
+extern void ECP4_frob_constants(YYY::FP2 F[3]);
+
+/**	@brief Multiplies an ECP4 instance P by the internal modulus p^n, using precalculated Frobenius constants
+ *
+	Fast point multiplication using Frobenius
+	@param P ECP4 instance, on exit = p^n*P
+	@param F array of FP2 precalculated Frobenius constant
+	@param n power of prime
+
+ */
+extern void ECP4_frob(ECP4 *P,YYY::FP2 F[3],int n);
+
+/**	@brief Calculates P=Sigma b[i]*Q[i] for i=0 to 7
+ *
+	@param P ECP4 instance, on exit = Sigma b[i]*Q[i] for i=0 to 7
+	@param Q ECP4 array of 4 points
+	@param b BIG array of 4 multipliers
+ */
+extern void ECP4_mul8(ECP4 *P,ECP4 *Q,XXX::BIG *b);
+
+
+/**	@brief Maps random BIG to curve point of correct order
+ *
+	@param P ECP4 instance of correct order
+	@param W OCTET byte array to be mapped
+ */
+extern void ECP4_mapit(ECP4 *P,octet *w);
+
+/**	@brief Get Group Generator from ROM
+ *
+	@param G ECP4 instance
+ */
+extern void ECP4_generator(ECP4 *G);
+
+
+}
+
+#endif
\ No newline at end of file
diff --git a/version3/cpp/ecp8.cpp b/version3/cpp/ecp8.cpp
new file mode 100644
index 0000000..48a76c8
--- /dev/null
+++ b/version3/cpp/ecp8.cpp
@@ -0,0 +1,1318 @@
+/*
+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.
+*/
+
+/* AMCL Weierstrass elliptic curve functions over FP2 */
+
+//#include <iostream>
+#include "ecp8_ZZZ.h"
+
+using namespace std;
+using namespace XXX;
+using namespace YYY;
+
+int ZZZ::ECP8_isinf(ECP8 *P)
+{
+//	if (P->inf) return 1;
+	return (FP8_iszilch(&(P->x)) & FP8_iszilch(&(P->z)));
+}
+
+/* Set P=Q */
+void ZZZ::ECP8_copy(ECP8 *P,ECP8 *Q)
+{
+//    P->inf=Q->inf;
+    FP8_copy(&(P->x),&(Q->x));
+    FP8_copy(&(P->y),&(Q->y));
+    FP8_copy(&(P->z),&(Q->z));
+}
+
+/* set P to Infinity */
+void ZZZ::ECP8_inf(ECP8 *P)
+{
+//    P->inf=1;
+    FP8_zero(&(P->x));
+    FP8_one(&(P->y));
+    FP8_zero(&(P->z));
+}
+
+/* Conditional move Q to P dependant on d */
+static void ECP8_cmove(ZZZ::ECP8 *P,ZZZ::ECP8 *Q,int d)
+{
+    FP8_cmove(&(P->x),&(Q->x),d);
+    FP8_cmove(&(P->y),&(Q->y),d);
+    FP8_cmove(&(P->z),&(Q->z),d);
+//    d=~(d-1);
+//    P->inf^=(P->inf^Q->inf)&d;
+}
+
+/* return 1 if b==c, no branching */
+static int teq(sign32 b,sign32 c)
+{
+    sign32 x=b^c;
+    x-=1;  // if x=0, x now -1
+    return (int)((x>>31)&1);
+}
+
+/* Constant time select from pre-computed table */
+static void ECP8_select(ZZZ::ECP8 *P,ZZZ::ECP8 W[],sign32 b)
+{
+    ZZZ::ECP8 MP;
+    sign32 m=b>>31;
+    sign32 babs=(b^m)-m;
+
+    babs=(babs-1)/2;
+
+    ECP8_cmove(P,&W[0],teq(babs,0));  // conditional move
+    ECP8_cmove(P,&W[1],teq(babs,1));
+    ECP8_cmove(P,&W[2],teq(babs,2));
+    ECP8_cmove(P,&W[3],teq(babs,3));
+    ECP8_cmove(P,&W[4],teq(babs,4));
+    ECP8_cmove(P,&W[5],teq(babs,5));
+    ECP8_cmove(P,&W[6],teq(babs,6));
+    ECP8_cmove(P,&W[7],teq(babs,7));
+
+    ECP8_copy(&MP,P);
+    ECP8_neg(&MP);  // minus P
+    ECP8_cmove(P,&MP,(int)(m&1));
+}
+
+/* Make P affine (so z=1) */
+void ZZZ::ECP8_affine(ECP8 *P)
+{
+    FP8 one,iz;
+    if (ECP8_isinf(P)) return;
+
+    FP8_one(&one);
+    if (FP8_isunity(&(P->z)))
+    {
+        FP8_reduce(&(P->x));
+        FP8_reduce(&(P->y));
+        return;
+    }
+
+    FP8_inv(&iz,&(P->z));
+    FP8_mul(&(P->x),&(P->x),&iz);
+    FP8_mul(&(P->y),&(P->y),&iz);
+
+    FP8_reduce(&(P->x));
+    FP8_reduce(&(P->y));
+    FP8_copy(&(P->z),&one);
+}
+
+/* return 1 if P==Q, else 0 */
+/* SU= 312 */
+int ZZZ::ECP8_equals(ECP8 *P,ECP8 *Q)
+{
+    FP8 a,b;
+//    if (ECP8_isinf(P) && ECP8_isinf(Q)) return 1;
+//    if (ECP8_isinf(P) || ECP8_isinf(Q)) return 0;
+
+    FP8_mul(&a,&(P->x),&(Q->z));
+    FP8_mul(&b,&(Q->x),&(P->z));
+    if (!FP8_equals(&a,&b)) return 0;
+
+    FP8_mul(&a,&(P->y),&(Q->z));
+    FP8_mul(&b,&(Q->y),&(P->z));
+    if (!FP8_equals(&a,&b)) return 0;
+    return 1;
+}
+
+/* extract x, y from point P */
+int ZZZ::ECP8_get(FP8 *x,FP8 *y,ECP8 *P)
+{
+	ECP8 W;
+	ECP8_copy(&W,P);
+	ECP8_affine(&W);
+    if (ECP8_isinf(&W)) return -1;
+	//ECP8_affine(P);
+    FP8_copy(y,&(W.y));
+    FP8_copy(x,&(W.x));
+    return 0;
+}
+
+/* Output point P */
+void ZZZ::ECP8_output(ECP8 *P)
+{
+    FP8 x,y;
+    if (ECP8_isinf(P))
+    {
+        printf("Infinity\n");
+        return;
+    }
+    ECP8_get(&x,&y,P);
+    printf("(");
+    FP8_output(&x);
+    printf(",");
+    FP8_output(&y);
+    printf(")\n");
+}
+
+/* Convert Q to octet string */
+void ZZZ::ECP8_toOctet(octet *W,ECP8 *Q)
+{
+	BIG b;
+	FP8 qx,qy;
+	FP4 qa,qb;
+	FP2 pa,pb;
+
+    ECP8_get(&qx,&qy,Q);
+
+	FP4_copy(&qa,&(qx.a));
+	FP4_copy(&qb,&(qx.b));
+
+	FP2_copy(&pa,&(qa.a));
+	FP2_copy(&pb,&(qa.b));
+
+	FP_redc(b,&(pa.a));
+    BIG_toBytes(&(W->val[0]),b);
+    FP_redc(b,&(pa.b));
+    BIG_toBytes(&(W->val[MODBYTES_XXX]),b);
+    FP_redc(b,&(pb.a));
+    BIG_toBytes(&(W->val[2*MODBYTES_XXX]),b);
+    FP_redc(b,&(pb.b));
+    BIG_toBytes(&(W->val[3*MODBYTES_XXX]),b);
+
+	FP2_copy(&pa,&(qb.a));
+	FP2_copy(&pb,&(qb.b));
+
+	FP_redc(b,&(pa.a));
+    BIG_toBytes(&(W->val[4*MODBYTES_XXX]),b);
+    FP_redc(b,&(pa.b));
+    BIG_toBytes(&(W->val[5*MODBYTES_XXX]),b);
+    FP_redc(b,&(pb.a));
+    BIG_toBytes(&(W->val[6*MODBYTES_XXX]),b);
+    FP_redc(b,&(pb.b));
+    BIG_toBytes(&(W->val[7*MODBYTES_XXX]),b);
+
+
+	FP4_copy(&qa,&(qy.a));
+	FP4_copy(&qb,&(qy.b));
+
+	FP2_copy(&pa,&(qa.a));
+	FP2_copy(&pb,&(qa.b));
+
+	FP_redc(b,&(pa.a));
+    BIG_toBytes(&(W->val[8*MODBYTES_XXX]),b);
+    FP_redc(b,&(pa.b));
+    BIG_toBytes(&(W->val[9*MODBYTES_XXX]),b);
+    FP_redc(b,&(pb.a));
+    BIG_toBytes(&(W->val[10*MODBYTES_XXX]),b);
+    FP_redc(b,&(pb.b));
+    BIG_toBytes(&(W->val[11*MODBYTES_XXX]),b);
+
+	FP2_copy(&pa,&(qb.a));
+	FP2_copy(&pb,&(qb.b));
+
+	FP_redc(b,&(pa.a));
+    BIG_toBytes(&(W->val[12*MODBYTES_XXX]),b);
+    FP_redc(b,&(pa.b));
+    BIG_toBytes(&(W->val[13*MODBYTES_XXX]),b);
+    FP_redc(b,&(pb.a));
+    BIG_toBytes(&(W->val[14*MODBYTES_XXX]),b);
+    FP_redc(b,&(pb.b));
+    BIG_toBytes(&(W->val[15*MODBYTES_XXX]),b);
+
+
+    W->len=16*MODBYTES_XXX;
+}
+
+/* restore Q from octet string */
+int ZZZ::ECP8_fromOctet(ECP8 *Q,octet *W)
+{
+	BIG b;
+    FP8 qx,qy;
+	FP4 qa,qb;
+	FP2 pa,pb;
+
+    BIG_fromBytes(b,&(W->val[0]));
+	FP_nres(&(pa.a),b);
+    BIG_fromBytes(b,&(W->val[MODBYTES_XXX]));
+    FP_nres(&(pa.b),b);
+    BIG_fromBytes(b,&(W->val[2*MODBYTES_XXX]));
+    FP_nres(&(pb.a),b);
+    BIG_fromBytes(b,&(W->val[3*MODBYTES_XXX]));
+    FP_nres(&(pb.b),b);
+
+	FP2_copy(&(qa.a),&pa);
+	FP2_copy(&(qa.b),&pb);
+
+    BIG_fromBytes(b,&(W->val[4*MODBYTES_XXX]));
+	FP_nres(&(pa.a),b);
+    BIG_fromBytes(b,&(W->val[5*MODBYTES_XXX]));
+    FP_nres(&(pa.b),b);
+    BIG_fromBytes(b,&(W->val[6*MODBYTES_XXX]));
+    FP_nres(&(pb.a),b);
+    BIG_fromBytes(b,&(W->val[7*MODBYTES_XXX]));
+    FP_nres(&(pb.b),b);
+
+	FP2_copy(&(qb.a),&pa);
+	FP2_copy(&(qb.b),&pb);
+
+	FP4_copy(&(qx.a),&qa);
+	FP4_copy(&(qx.b),&qb);
+
+
+    BIG_fromBytes(b,&(W->val[8*MODBYTES_XXX]));
+	FP_nres(&(pa.a),b);
+    BIG_fromBytes(b,&(W->val[9*MODBYTES_XXX]));
+    FP_nres(&(pa.b),b);
+    BIG_fromBytes(b,&(W->val[10*MODBYTES_XXX]));
+    FP_nres(&(pb.a),b);
+    BIG_fromBytes(b,&(W->val[11*MODBYTES_XXX]));
+    FP_nres(&(pb.b),b);
+
+	FP2_copy(&(qa.a),&pa);
+	FP2_copy(&(qa.b),&pb);
+
+    BIG_fromBytes(b,&(W->val[12*MODBYTES_XXX]));
+	FP_nres(&(pa.a),b);
+    BIG_fromBytes(b,&(W->val[13*MODBYTES_XXX]));
+    FP_nres(&(pa.b),b);
+    BIG_fromBytes(b,&(W->val[14*MODBYTES_XXX]));
+    FP_nres(&(pb.a),b);
+    BIG_fromBytes(b,&(W->val[15*MODBYTES_XXX]));
+    FP_nres(&(pb.b),b);
+
+	FP2_copy(&(qb.a),&pa);
+	FP2_copy(&(qb.b),&pb);
+
+	FP4_copy(&(qy.a),&qa);
+	FP4_copy(&(qy.b),&qb);
+
+
+    if (ECP8_set(Q,&qx,&qy)) return 1;
+    return 0;
+}
+
+/* Calculate RHS of twisted curve equation x^3+B/i or x^3+Bi*/
+void ZZZ::ECP8_rhs(FP8 *rhs,FP8 *x)
+{
+    /* calculate RHS of elliptic curve equation */
+    FP8 t;
+	FP4 t4;
+	FP2 t2;
+    BIG b;
+    FP8_sqr(&t,x);
+
+    FP8_mul(rhs,&t,x);
+
+    /* Assuming CURVE_A=0 */
+
+    BIG_rcopy(b,CURVE_B);
+
+    FP2_from_BIG(&t2,b);
+	FP4_from_FP2(&t4,&t2);
+	FP8_from_FP4(&t,&t4);
+
+#if SEXTIC_TWIST_ZZZ == D_TYPE	
+    FP8_div_i(&t);   /* IMPORTANT - here we use the correct SEXTIC twist of the curve */
+#endif
+
+#if SEXTIC_TWIST_ZZZ == M_TYPE	
+    FP8_times_i(&t);   /* IMPORTANT - here we use the correct SEXTIC twist of the curve */
+#endif
+
+    FP8_add(rhs,&t,rhs);
+    FP8_reduce(rhs);
+}
+
+/* Set P=(x,y). Return 1 if (x,y) is on the curve, else return 0*/
+/* SU= 232 */
+int ZZZ::ECP8_set(ECP8 *P,FP8 *x,FP8 *y)
+{
+    FP8 rhs,y2;
+
+    FP8_sqr(&y2,y);
+    ECP8_rhs(&rhs,x);
+
+    if (!FP8_equals(&y2,&rhs))
+    {
+		ECP8_inf(P);
+        //P->inf=1;
+        return 0;
+    }
+
+  //  P->inf=0;
+    FP8_copy(&(P->x),x);
+    FP8_copy(&(P->y),y);
+    FP8_one(&(P->z));
+    return 1;
+}
+
+/* Set P=(x,y). Return 1 if (x,.) is on the curve, else return 0 */
+/* SU= 232 */
+int ZZZ::ECP8_setx(ECP8 *P,FP8 *x)
+{
+    FP8 y;
+    ECP8_rhs(&y,x);
+
+    if (!FP8_sqrt(&y,&y))
+    {
+		ECP8_inf(P);
+       // P->inf=1;
+        return 0;
+    }
+
+//    P->inf=0;
+    FP8_copy(&(P->x),x);
+    FP8_copy(&(P->y),&y);
+    FP8_one(&(P->z));
+
+    return 1;
+}
+
+/* Set P=-P */
+/* SU= 8 */
+void ZZZ::ECP8_neg(ECP8 *P)
+{
+//	if (ECP8_isinf(P)) return;
+	FP8_norm(&(P->y));
+    FP8_neg(&(P->y),&(P->y));
+    FP8_norm(&(P->y));
+}
+
+
+/* R+=R */
+/* return -1 for Infinity, 0 for addition, 1 for doubling */
+int ZZZ::ECP8_dbl(ECP8 *P)
+{
+    FP8 t0,t1,t2,t3,iy,x3,y3;
+//    if (P->inf) return -1;
+
+	FP8_copy(&iy,&(P->y));		//FP8 iy=new FP8(y);
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+	FP8_times_i(&iy);			//iy.mul_ip(); 
+	//FP8_norm(&iy);				//iy.norm();
+#endif
+
+	FP8_sqr(&t0,&(P->y));			//t0.sqr();   
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+	FP8_times_i(&t0);			//t0.mul_ip(); 
+#endif
+
+	FP8_mul(&t1,&iy,&(P->z));	//t1.mul(z);
+	FP8_sqr(&t2,&(P->z));				//t2.sqr();
+
+	FP8_add(&(P->z),&t0,&t0);	//z.add(t0); 
+	FP8_norm(&(P->z));				//z.norm(); 
+	FP8_add(&(P->z),&(P->z),&(P->z));	//z.add(z); 
+	FP8_add(&(P->z),&(P->z),&(P->z));	//z.add(z); 
+	FP8_norm(&(P->z));			//z.norm();  
+
+	FP8_imul(&t2,&t2,3*CURVE_B_I);	//t2.imul(3*ROM.CURVE_B_I); 
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+	FP8_times_i(&t2);
+	//FP8_norm(&t2);
+#endif
+
+	FP8_mul(&x3,&t2,&(P->z));	//x3.mul(z); 
+
+	FP8_add(&y3,&t0,&t2);		//y3.add(t2); 
+	FP8_norm(&y3);				//y3.norm();
+	FP8_mul(&(P->z),&(P->z),&t1);	//z.mul(t1);
+
+	FP8_add(&t1,&t2,&t2);		//t1.add(t2); 
+	FP8_add(&t2,&t2,&t1);		//t2.add(t1); 
+	FP8_norm(&t2);				//t2.norm();  
+	FP8_sub(&t0,&t0,&t2);		//t0.sub(t2); 
+	FP8_norm(&t0);				//t0.norm();                           //y^2-9bz^2
+	FP8_mul(&y3,&y3,&t0);		//y3.mul(t0); 
+	FP8_add(&(P->y),&y3,&x3);		//y3.add(x3);                          //(y^2+3z*2)(y^2-9z^2)+3b.z^2.8y^2
+
+	FP8_mul(&t1,&(P->x),&iy);		//t1.mul(iy);						//
+
+	FP8_norm(&t0);			//x.norm(); 
+	FP8_mul(&(P->x),&t0,&t1);	//x.mul(t1); 
+	FP8_add(&(P->x),&(P->x),&(P->x));	//x.add(x);       //(y^2-9bz^2)xy2
+
+	FP8_norm(&(P->x));			//x.norm(); 
+
+	FP8_norm(&(P->y));			//y.norm();
+
+    return 1;
+}
+
+/* Set P+=Q */
+
+int ZZZ::ECP8_add(ECP8 *P,ECP8 *Q)
+{
+    FP8 t0,t1,t2,t3,t4,x3,y3,z3;
+	int b3=3*CURVE_B_I;
+/*    if (Q->inf) return 0;
+    if (P->inf)
+    {
+        ECP8_copy(P,Q);
+        return 0;
+    }*/
+
+	FP8_mul(&t0,&(P->x),&(Q->x));	//t0.mul(Q.x);         // x.Q.x
+	FP8_mul(&t1,&(P->y),&(Q->y));	//t1.mul(Q.y);		 // y.Q.y
+
+	FP8_mul(&t2,&(P->z),&(Q->z));	//t2.mul(Q.z);
+	FP8_add(&t3,&(P->x),&(P->y));	//t3.add(y); 
+	FP8_norm(&t3);				//t3.norm();          //t3=X1+Y1         
+	FP8_add(&t4,&(Q->x),&(Q->y));	//t4.add(Q.y); 
+	FP8_norm(&t4);				//t4.norm();			//t4=X2+Y2
+	FP8_mul(&t3,&t3,&t4);		//t3.mul(t4);						//t3=(X1+Y1)(X2+Y2)
+	FP8_add(&t4,&t0,&t1);		//t4.add(t1);		//t4=X1.X2+Y1.Y2
+
+	FP8_sub(&t3,&t3,&t4);		//t3.sub(t4); 
+	FP8_norm(&t3);				//t3.norm(); 
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+	FP8_times_i(&t3);			//t3.mul_ip();  
+	//FP8_norm(&t3);				//t3.norm();         //t3=(X1+Y1)(X2+Y2)-(X1.X2+Y1.Y2) = X1.Y2+X2.Y1
+#endif
+                   
+	FP8_add(&t4,&(P->y),&(P->z));	//t4.add(z); 
+	FP8_norm(&t4);				//t4.norm();			//t4=Y1+Z1
+
+	FP8_add(&x3,&(Q->y),&(Q->z));	//x3.add(Q.z); 
+	FP8_norm(&x3);				//x3.norm();			//x3=Y2+Z2
+
+	FP8_mul(&t4,&t4,&x3);		//t4.mul(x3);						//t4=(Y1+Z1)(Y2+Z2)
+
+	FP8_add(&x3,&t1,&t2);		//x3.add(t2);						//X3=Y1.Y2+Z1.Z2
+	
+	FP8_sub(&t4,&t4,&x3);		//t4.sub(x3); 
+	FP8_norm(&t4);				//t4.norm(); 
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+	FP8_times_i(&t4);			//t4.mul_ip(); 
+	//FP8_norm(&t4);				//t4.norm();          //t4=(Y1+Z1)(Y2+Z2) - (Y1.Y2+Z1.Z2) = Y1.Z2+Y2.Z1
+#endif
+
+	FP8_add(&x3,&(P->x),&(P->z));	//x3.add(z); 
+	FP8_norm(&x3);				//x3.norm();	// x3=X1+Z1
+		
+	FP8_add(&y3,&(Q->x),&(Q->z));	//y3.add(Q.z); 
+	FP8_norm(&y3);				//y3.norm();				// y3=X2+Z2
+	FP8_mul(&x3,&x3,&y3);		//x3.mul(y3);							// x3=(X1+Z1)(X2+Z2)
+
+	FP8_add(&y3,&t0,&t2);		//y3.add(t2);							// y3=X1.X2+Z1+Z2
+	FP8_sub(&y3,&x3,&y3);		//y3.rsub(x3); 
+	FP8_norm(&y3);				//y3.norm();				// y3=(X1+Z1)(X2+Z2) - (X1.X2+Z1.Z2) = X1.Z2+X2.Z1
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+	FP8_times_i(&t0);			//t0.mul_ip(); 
+	//FP8_norm(&t0);				//t0.norm(); // x.Q.x
+	FP8_times_i(&t1);			//t1.mul_ip(); 
+	//FP8_norm(&t1);				//t1.norm(); // y.Q.y
+#endif
+
+	FP8_add(&x3,&t0,&t0);		//x3.add(t0); 
+	FP8_add(&t0,&t0,&x3);		//t0.add(x3); 
+	FP8_norm(&t0);				//t0.norm();
+	FP8_imul(&t2,&t2,b3);		//t2.imul(b); 	
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+	FP8_times_i(&t2);
+#endif
+
+	FP8_add(&z3,&t1,&t2);		//z3.add(t2); 
+	FP8_norm(&z3);				//z3.norm();
+	FP8_sub(&t1,&t1,&t2);		//t1.sub(t2); 
+	FP8_norm(&t1);				//t1.norm(); 
+	FP8_imul(&y3,&y3,b3);		//y3.imul(b); 
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+	FP8_times_i(&y3);
+	//FP8_norm(&y3);
+#endif
+
+	FP8_mul(&x3,&y3,&t4);		//x3.mul(t4); 
+
+	FP8_mul(&t2,&t3,&t1);		//t2.mul(t1); 
+	FP8_sub(&(P->x),&t2,&x3);		//x3.rsub(t2);
+	FP8_mul(&y3,&y3,&t0);		//y3.mul(t0); 
+	FP8_mul(&t1,&t1,&z3);		//t1.mul(z3); 
+	FP8_add(&(P->y),&y3,&t1);		//y3.add(t1);
+	FP8_mul(&t0,&t0,&t3);		//t0.mul(t3); 
+	FP8_mul(&z3,&z3,&t4);		//z3.mul(t4); 
+	FP8_add(&(P->z),&z3,&t0);		//z3.add(t0);
+
+
+	FP8_norm(&(P->x));			//x.norm(); 
+	FP8_norm(&(P->y));			//y.norm();
+	FP8_norm(&(P->z));			//z.norm();
+
+    return 0;
+}
+
+/* Set P-=Q */
+/* SU= 16 */
+void ZZZ::ECP8_sub(ECP8 *P,ECP8 *Q)
+{
+	ECP8 NQ;
+	ECP8_copy(&NQ,Q);
+	ECP8_neg(&NQ);
+    //ECP8_neg(Q);
+    ECP8_add(P,&NQ);
+    //ECP8_neg(Q);
+}
+
+
+void ZZZ::ECP8_reduce(ECP8 *P)
+{
+	FP8_reduce(&(P->x));
+	FP8_reduce(&(P->y));
+}
+
+/* P*=e */
+/* SU= 280 */
+void ZZZ::ECP8_mul(ECP8 *P,BIG e)
+{
+    /* fixed size windows */
+    int i,nb,s,ns;
+    BIG mt,t;
+    ECP8 Q,W[8],C;
+    sign8 w[1+(NLEN_XXX*BASEBITS_XXX+3)/4];
+
+    if (ECP8_isinf(P)) return;
+    //ECP8_affine(P);
+
+    /* precompute table */
+
+    ECP8_copy(&Q,P);
+    ECP8_dbl(&Q);
+    ECP8_copy(&W[0],P);
+
+    for (i=1; i<8; i++)
+    {
+        ECP8_copy(&W[i],&W[i-1]);
+        ECP8_add(&W[i],&Q);
+    }
+
+    /* make exponent odd - add 2P if even, P if odd */
+    BIG_copy(t,e);
+    s=BIG_parity(t);
+    BIG_inc(t,1);
+    BIG_norm(t);
+    ns=BIG_parity(t);
+    BIG_copy(mt,t);
+    BIG_inc(mt,1);
+    BIG_norm(mt);
+    BIG_cmove(t,mt,s);
+    ECP8_cmove(&Q,P,ns);
+    ECP8_copy(&C,&Q);
+
+    nb=1+(BIG_nbits(t)+3)/4;
+
+    /* convert exponent to signed 4-bit window */
+    for (i=0; i<nb; i++)
+    {
+        w[i]=BIG_lastbits(t,5)-16;
+        BIG_dec(t,w[i]);
+        BIG_norm(t);
+        BIG_fshr(t,4);
+    }
+    w[nb]=BIG_lastbits(t,5);
+
+    ECP8_copy(P,&W[(w[nb]-1)/2]);
+    for (i=nb-1; i>=0; i--)
+    {
+        ECP8_select(&Q,W,w[i]);
+        ECP8_dbl(P);
+        ECP8_dbl(P);
+        ECP8_dbl(P);
+        ECP8_dbl(P);
+        ECP8_add(P,&Q);
+    }
+    ECP8_sub(P,&C); /* apply correction */
+	ECP8_affine(P);
+}
+
+void ZZZ::ECP8_frob_constants(FP2 F[3])
+{
+    FP fx,fy;
+	FP2 X;
+
+    FP_rcopy(&fx,Fra);
+    FP_rcopy(&fy,Frb);
+    FP2_from_FPs(&X,&fx,&fy);
+
+
+	FP2_sqr(&F[0],&X);			// FF=F^2=(1+i)^(p-19)/12
+	FP2_copy(&F[2],&F[0]);
+	FP2_mul_ip(&F[2]);			// W=(1+i)^12/12.(1+i)^(p-19)/12 = (1+i)^(p-7)/12
+	FP2_norm(&F[2]);
+	FP2_sqr(&F[1],&F[2]);
+	FP2_mul(&F[2],&F[2],&F[1]);	// W=(1+i)^(p-7)/4
+
+	FP2_mul_ip(&F[2]);			// W=(1+i)^4/4.W=(1+i)^(p-7)/4 = (1+i)^(p-3)/4
+	FP2_norm(&F[2]);
+
+	FP2_copy(&F[1],&X);
+
+#if SEXTIC_TWIST_ZZZ == M_TYPE	
+	FP2_mul_ip(&F[1]);		// (1+i)^24/24.(1+i)^(p-19)/24 = (1+i)^(p+5)/24
+	FP2_inv(&F[1],&F[1]);		// (1+i)^-(p+5)/24
+	FP2_sqr(&F[0],&F[1]);		// (1+i)^-(p+5)/12
+#endif
+
+
+	FP2_mul_ip(&F[0]);		// FF=(1+i)^(p-19)/12.(1+i)^12/12 = (1+i)^(p-7)/12					// FF=(1+i)^12/12.(1+i)^-(p+5)/12 = (1+i)^-(p-7)/12
+	FP2_norm(&F[0]);
+
+	FP2_mul(&F[1],&F[1],&F[0]);  // (1+i)^(p-7)/12 . (1+i)^(p-19)/24 = (1+i)^(p-11)/8				// (1+i)^-(p-7)/12 . (1+i)^-(p+5)/24 = (1+i)^-(p-3)/8
+
+}
+
+/* Calculates q^n.P using Frobenius constant X */
+void ZZZ::ECP8_frob(ECP8 *P,FP2 F[3],int n)
+{
+	int i;
+	FP8 X,Y,Z;
+
+    //if (P->inf) return;
+
+	//ECP8_get(&X,&Y,P);		// F=(1+i)^(p-19)/24
+
+	FP8_copy(&X,&(P->x));
+	FP8_copy(&Y,&(P->y));
+	FP8_copy(&Z,&(P->z));
+
+	for (i=0;i<n;i++)
+	{
+		FP8_frob(&X,&F[2]);		// X^p		
+		FP8_qmul(&X,&X,&F[0]); 
+#if SEXTIC_TWIST_ZZZ == M_TYPE			
+		FP8_div_i2(&X);			// X^p.(1+i)^-(p-1)/12
+#endif
+#if SEXTIC_TWIST_ZZZ == D_TYPE			
+		FP8_times_i2(&X);		// X^p.(1+i)^(p-1)/12
+#endif
+
+		FP8_frob(&Y,&F[2]);		// Y^p
+		FP8_qmul(&Y,&Y,&F[1]); 
+#if SEXTIC_TWIST_ZZZ == M_TYPE		
+		FP8_div_i(&Y);			// Y^p.(1+i)^-(p-1)/8
+#endif
+#if SEXTIC_TWIST_ZZZ == D_TYPE
+		FP8_times_i2(&Y); FP8_times_i2(&Y); FP8_times_i(&Y);  // Y^p.(1+i)^(p-1)/8
+#endif
+		FP8_frob(&Z,&F[2]);
+	}
+
+	FP8_copy(&(P->x),&X);
+	FP8_copy(&(P->y),&Y);
+	FP8_copy(&(P->z),&Z);
+
+
+//	ECP8_set(P,&X,&Y);
+}
+
+/* Side channel attack secure */
+// Bos & Costello https://eprint.iacr.org/2013/458.pdf
+// Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
+
+void ZZZ::ECP8_mul16(ECP8 *P,ECP8 Q[16],BIG u[16])
+{
+    int i,j,k,nb,pb1,pb2,pb3,pb4,bt;
+	ECP8 T1[8],T2[8],T3[8],T4[8],W;
+    BIG mt,t[16];
+    sign8 w1[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 s1[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 w2[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 s2[NLEN_XXX*BASEBITS_XXX+1];	
+    sign8 w3[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 s3[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 w4[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 s4[NLEN_XXX*BASEBITS_XXX+1];	
+
+	FP2 X[3];
+	ECP8_frob_constants(X);
+
+    for (i=0; i<16; i++)
+	{
+        //ECP8_affine(&Q[i]);
+        BIG_copy(t[i],u[i]);
+	}
+// Precomputed table
+    ECP8_copy(&T1[0],&Q[0]); // Q[0]
+    ECP8_copy(&T1[1],&T1[0]);
+	ECP8_add(&T1[1],&Q[1]);	// Q[0]+Q[1]
+    ECP8_copy(&T1[2],&T1[0]);
+	ECP8_add(&T1[2],&Q[2]);	// Q[0]+Q[2]
+	ECP8_copy(&T1[3],&T1[1]);
+	ECP8_add(&T1[3],&Q[2]);	// Q[0]+Q[1]+Q[2]
+	ECP8_copy(&T1[4],&T1[0]);
+	ECP8_add(&T1[4],&Q[3]);  // Q[0]+Q[3]
+	ECP8_copy(&T1[5],&T1[1]);
+	ECP8_add(&T1[5],&Q[3]);	// Q[0]+Q[1]+Q[3]
+	ECP8_copy(&T1[6],&T1[2]);
+	ECP8_add(&T1[6],&Q[3]);	// Q[0]+Q[2]+Q[3]
+	ECP8_copy(&T1[7],&T1[3]);
+	ECP8_add(&T1[7],&Q[3]);	// Q[0]+Q[1]+Q[2]+Q[3]
+
+//  Use Frobenius 
+
+	for (i=0;i<8;i++)
+	{
+		ECP8_copy(&T2[i],&T1[i]);
+		ECP8_frob(&T2[i],X,4);
+
+		ECP8_copy(&T3[i],&T2[i]);
+		ECP8_frob(&T3[i],X,4);
+
+		ECP8_copy(&T4[i],&T3[i]);
+		ECP8_frob(&T4[i],X,4);
+	}
+
+// Make them odd
+	pb1=1-BIG_parity(t[0]);
+	BIG_inc(t[0],pb1);
+	BIG_norm(t[0]);
+
+	pb2=1-BIG_parity(t[4]);
+	BIG_inc(t[4],pb2);
+	BIG_norm(t[4]);
+
+	pb3=1-BIG_parity(t[8]);
+	BIG_inc(t[8],pb3);
+	BIG_norm(t[8]);
+
+	pb4=1-BIG_parity(t[12]);
+	BIG_inc(t[12],pb4);
+	BIG_norm(t[12]);
+
+// Number of bits
+    BIG_zero(mt);
+    for (i=0; i<16; i++)
+    {
+        BIG_or(mt,mt,t[i]);
+    }
+    nb=1+BIG_nbits(mt);
+
+// Sign pivot 
+	s1[nb-1]=1;
+	s2[nb-1]=1;
+	s3[nb-1]=1;
+	s4[nb-1]=1;
+	for (i=0;i<nb-1;i++)
+	{
+        BIG_fshr(t[0],1);
+		s1[i]=2*BIG_parity(t[0])-1;
+        BIG_fshr(t[4],1);
+		s2[i]=2*BIG_parity(t[4])-1;
+        BIG_fshr(t[8],1);
+		s3[i]=2*BIG_parity(t[8])-1;
+        BIG_fshr(t[12],1);
+		s4[i]=2*BIG_parity(t[12])-1;
+	}
+
+
+// Recoded exponents
+    for (i=0; i<nb; i++)
+    {
+		w1[i]=0;
+		k=1;
+		for (j=1; j<4; j++)
+		{
+			bt=s1[i]*BIG_parity(t[j]);
+			BIG_fshr(t[j],1);
+
+			BIG_dec(t[j],(bt>>1));
+			BIG_norm(t[j]);
+			w1[i]+=bt*k;
+			k*=2;
+        }
+
+		w2[i]=0;
+		k=1;
+		for (j=5; j<8; j++)
+		{
+			bt=s2[i]*BIG_parity(t[j]);
+			BIG_fshr(t[j],1);
+
+			BIG_dec(t[j],(bt>>1));
+			BIG_norm(t[j]);
+			w2[i]+=bt*k;
+			k*=2;
+        }
+
+		w3[i]=0;
+		k=1;
+		for (j=9; j<12; j++)
+		{
+			bt=s3[i]*BIG_parity(t[j]);
+			BIG_fshr(t[j],1);
+
+			BIG_dec(t[j],(bt>>1));
+			BIG_norm(t[j]);
+			w3[i]+=bt*k;
+			k*=2;
+        }
+
+		w4[i]=0;
+		k=1;
+		for (j=13; j<16; j++)
+		{
+			bt=s4[i]*BIG_parity(t[j]);
+			BIG_fshr(t[j],1);
+
+			BIG_dec(t[j],(bt>>1));
+			BIG_norm(t[j]);
+			w4[i]+=bt*k;
+			k*=2;
+        }
+    }	
+
+// Main loop
+	ECP8_select(P,T1,2*w1[nb-1]+1);
+	ECP8_select(&W,T2,2*w2[nb-1]+1);
+	ECP8_add(P,&W);
+	ECP8_select(&W,T3,2*w3[nb-1]+1);
+	ECP8_add(P,&W);
+	ECP8_select(&W,T4,2*w4[nb-1]+1);
+	ECP8_add(P,&W);
+
+    for (i=nb-2; i>=0; i--)
+    {
+        ECP8_dbl(P);
+        ECP8_select(&W,T1,2*w1[i]+s1[i]);
+        ECP8_add(P,&W);
+        ECP8_select(&W,T2,2*w2[i]+s2[i]);
+        ECP8_add(P,&W);
+        ECP8_select(&W,T3,2*w3[i]+s3[i]);
+        ECP8_add(P,&W);
+        ECP8_select(&W,T4,2*w4[i]+s4[i]);
+        ECP8_add(P,&W);
+    }
+
+// apply corrections
+	ECP8_copy(&W,P);   
+	ECP8_sub(&W,&Q[0]);
+	ECP8_cmove(P,&W,pb1);
+	ECP8_copy(&W,P);   
+	ECP8_sub(&W,&Q[4]);
+	ECP8_cmove(P,&W,pb2);
+
+	ECP8_copy(&W,P);   
+	ECP8_sub(&W,&Q[8]);
+	ECP8_cmove(P,&W,pb3);
+	ECP8_copy(&W,P);   
+	ECP8_sub(&W,&Q[12]);
+	ECP8_cmove(P,&W,pb4);
+
+	ECP8_affine(P);
+}
+
+/*
+void ZZZ::ECP8_mul16(ECP8 *P,ECP8 Q[16],BIG u[16])
+{
+    int i,j,a[4],nb,pb;
+    ECP8 W[8],Z[8],WW[8],ZZ[8],T,C;
+    BIG mt,t[16];
+    sign8 w[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 z[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 ww[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 zz[NLEN_XXX*BASEBITS_XXX+1];
+
+    FP fx,fy;
+	FP2 X;
+
+    FP_rcopy(&fx,Fra);
+    FP_rcopy(&fy,Frb);
+    FP2_from_FPs(&X,&fx,&fy);
+
+
+    for (i=0; i<16; i++)
+        BIG_copy(t[i],u[i]);
+
+    // precompute tables 
+
+// 12 add/subs 
+
+    ECP8_copy(&W[0],&Q[0]);
+    ECP8_sub(&W[0],&Q[1]);  // P-Q
+    ECP8_copy(&W[1],&W[0]);
+    ECP8_copy(&W[2],&W[0]);
+    ECP8_copy(&W[3],&W[0]);
+    ECP8_copy(&W[4],&Q[0]);
+    ECP8_add(&W[4],&Q[1]);  // P+Q 
+    ECP8_copy(&W[5],&W[4]);
+    ECP8_copy(&W[6],&W[4]);
+    ECP8_copy(&W[7],&W[4]);
+
+    ECP8_copy(&T,&Q[2]);
+    ECP8_sub(&T,&Q[3]);       // R-S 
+    ECP8_sub(&W[1],&T);
+    ECP8_add(&W[2],&T);
+    ECP8_sub(&W[5],&T);
+    ECP8_add(&W[6],&T);
+    ECP8_copy(&T,&Q[2]);
+    ECP8_add(&T,&Q[3]);      // R+S 
+    ECP8_sub(&W[0],&T);
+    ECP8_add(&W[3],&T);
+    ECP8_sub(&W[4],&T);
+    ECP8_add(&W[7],&T);
+
+
+// Use Frobenius 
+
+	for (i=0;i<8;i++)
+	{
+		ECP8_copy(&Z[i],&W[i]);
+		ECP8_frob(&Z[i],&X,4);
+	}
+
+	for (i=0;i<8;i++)
+	{
+		ECP8_copy(&WW[i],&Z[i]);
+		ECP8_frob(&WW[i],&X,4);
+	}
+
+	for (i=0;i<8;i++)
+	{
+		ECP8_copy(&ZZ[i],&WW[i]);
+		ECP8_frob(&ZZ[i],&X,4);
+	}
+
+    // if multiplier is even add 1 to multiplier, and add P to correction 
+    ECP8_inf(&C);
+
+    BIG_zero(mt);
+    for (i=0; i<16; i++)
+    {
+		pb=BIG_parity(t[i]);
+		BIG_inc(t[i],1-pb);
+		BIG_norm(t[i]);
+		ECP8_copy(&T,&C);
+		ECP8_add(&T,&Q[i]);
+		ECP8_cmove(&C,&T,1-pb);
+
+
+        BIG_add(mt,mt,t[i]);
+        BIG_norm(mt);
+    }
+
+    nb=1+BIG_nbits(mt);
+
+    // convert exponents to signed 1-bit windows 
+    for (j=0; j<nb; j++)
+    {
+        for (i=0; i<4; i++)
+        {
+            a[i]=BIG_lastbits(t[i],2)-2;
+            BIG_dec(t[i],a[i]);
+            BIG_norm(t[i]);
+            BIG_fshr(t[i],1);
+        }
+        w[j]=8*a[0]+4*a[1]+2*a[2]+a[3];
+    }
+    w[nb]=8*BIG_lastbits(t[0],2)+4*BIG_lastbits(t[1],2)+2*BIG_lastbits(t[2],2)+BIG_lastbits(t[3],2);
+
+
+    for (j=0; j<nb; j++)
+    {
+        for (i=0; i<4; i++)
+        {
+            a[i]=BIG_lastbits(t[i+4],2)-2;
+            BIG_dec(t[i+4],a[i]);
+            BIG_norm(t[i+4]);
+            BIG_fshr(t[i+4],1);
+        }
+        z[j]=8*a[0]+4*a[1]+2*a[2]+a[3];
+    }
+    z[nb]=8*BIG_lastbits(t[4],2)+4*BIG_lastbits(t[5],2)+2*BIG_lastbits(t[6],2)+BIG_lastbits(t[7],2);
+
+
+    for (j=0; j<nb; j++)
+    {
+        for (i=0; i<4; i++)
+        {
+            a[i]=BIG_lastbits(t[i+8],2)-2;
+            BIG_dec(t[i+8],a[i]);
+            BIG_norm(t[i+8]);
+            BIG_fshr(t[i+8],1);
+        }
+        ww[j]=8*a[0]+4*a[1]+2*a[2]+a[3];
+    }
+    ww[nb]=8*BIG_lastbits(t[8],2)+4*BIG_lastbits(t[9],2)+2*BIG_lastbits(t[10],2)+BIG_lastbits(t[11],2);
+
+    for (j=0; j<nb; j++)
+    {
+        for (i=0; i<4; i++)
+        {
+            a[i]=BIG_lastbits(t[i+12],2)-2;
+            BIG_dec(t[i+12],a[i]);
+            BIG_norm(t[i+12]);
+            BIG_fshr(t[i+12],1);
+        }
+        zz[j]=8*a[0]+4*a[1]+2*a[2]+a[3];
+    }
+    zz[nb]=8*BIG_lastbits(t[12],2)+4*BIG_lastbits(t[13],2)+2*BIG_lastbits(t[14],2)+BIG_lastbits(t[15],2);
+
+    ECP8_copy(P,&W[(w[nb]-1)/2]);
+	ECP8_add(P,&Z[(z[nb]-1)/2]);
+	ECP8_add(P,&WW[(ww[nb]-1)/2]);
+	ECP8_add(P,&ZZ[(zz[nb]-1)/2]);
+    for (i=nb-1; i>=0; i--)
+    {
+		ECP8_dbl(P);
+        ECP8_select(&T,W,w[i]);
+        ECP8_add(P,&T);
+        ECP8_select(&T,Z,z[i]);
+        ECP8_add(P,&T);
+        ECP8_select(&T,WW,ww[i]);
+        ECP8_add(P,&T);
+        ECP8_select(&T,ZZ,zz[i]);
+        ECP8_add(P,&T);
+
+    }
+    ECP8_sub(P,&C); // apply correction 
+	ECP8_reduce(P);
+}
+*/
+/* Map to hash value to point on G2 from random BIG */
+
+void ZZZ::ECP8_mapit(ECP8 *Q,octet *W)
+{
+    BIG q,one,x,hv;
+	FP Fx,Fy;
+    FP2 T,X[3];
+	FP4 X4;
+	FP8 X8;
+
+    ECP8 xQ, x2Q, x3Q, x4Q , x5Q, x6Q, x7Q, x8Q;
+
+	BIG_fromBytes(hv,W->val);
+    BIG_rcopy(q,Modulus);
+    BIG_one(one);
+    BIG_mod(hv,q);
+
+    for (;;)
+    {
+        FP2_from_BIGs(&T,one,hv);  /*******/
+		FP4_from_FP2(&X4,&T);
+		FP8_from_FP4(&X8,&X4);
+        if (ECP8_setx(Q,&X8)) break;
+        BIG_inc(hv,1);
+    }
+
+	ECP8_frob_constants(X);
+
+    BIG_rcopy(x,CURVE_Bnx);
+
+    // Efficient hash maps to G2 on BLS48 curves - Budroni, Pintore 
+	// Q -> x8Q -x7Q -Q +  F(x7Q-x6Q) + F(F(x6Q-x5Q)) +F(F(F(x5Q-x4Q))) +F(F(F(F(x4Q-x3Q)))) + F(F(F(F(F(x3Q-x2Q))))) + F(F(F(F(F(F(x2Q-xQ)))))) + F(F(F(F(F(F(F(xQ-Q))))))) +F(F(F(F(F(F(F(F(2Q))))))))
+
+	ECP8_copy(&xQ,Q);
+	ECP8_mul(&xQ,x);
+	ECP8_copy(&x2Q,&xQ);
+	ECP8_mul(&x2Q,x);
+	ECP8_copy(&x3Q,&x2Q);
+	ECP8_mul(&x3Q,x);
+	ECP8_copy(&x4Q,&x3Q);
+
+	ECP8_mul(&x4Q,x);
+	ECP8_copy(&x5Q,&x4Q);
+	ECP8_mul(&x5Q,x);
+	ECP8_copy(&x6Q,&x5Q);
+	ECP8_mul(&x6Q,x);
+	ECP8_copy(&x7Q,&x6Q);
+	ECP8_mul(&x7Q,x);
+	ECP8_copy(&x8Q,&x7Q);
+	ECP8_mul(&x8Q,x);
+
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	ECP8_neg(&xQ);
+	ECP8_neg(&x3Q);
+	ECP8_neg(&x5Q);
+	ECP8_neg(&x7Q);
+#endif
+
+	ECP8_sub(&x8Q,&x7Q);
+	ECP8_sub(&x8Q,Q);
+
+	ECP8_sub(&x7Q,&x6Q);
+	ECP8_frob(&x7Q,X,1);
+
+	ECP8_sub(&x6Q,&x5Q);
+	ECP8_frob(&x6Q,X,2);
+	
+	ECP8_sub(&x5Q,&x4Q);
+	ECP8_frob(&x5Q,X,3);
+	
+	ECP8_sub(&x4Q,&x3Q);
+	ECP8_frob(&x4Q,X,4);
+
+	ECP8_sub(&x3Q,&x2Q);
+	ECP8_frob(&x3Q,X,5);
+
+	ECP8_sub(&x2Q,&xQ);
+	ECP8_frob(&x2Q,X,6);
+
+	ECP8_sub(&xQ,Q);
+	ECP8_frob(&xQ,X,7);
+
+	ECP8_dbl(Q);
+	ECP8_frob(Q,X,8);
+
+
+	ECP8_add(Q,&x8Q);
+	ECP8_add(Q,&x7Q);
+	ECP8_add(Q,&x6Q);
+	ECP8_add(Q,&x5Q);
+
+	ECP8_add(Q,&x4Q);
+	ECP8_add(Q,&x3Q);
+	ECP8_add(Q,&x2Q);
+	ECP8_add(Q,&xQ);
+
+	ECP8_affine(Q);
+
+}
+
+// ECP$ Get Group Generator
+
+void ZZZ::ECP8_generator(ECP8 *G)
+{
+	BIG a,b;
+	FP2 Aa,Bb;
+	FP4 A,B;
+	FP8 X,Y;
+
+	BIG_rcopy(a,CURVE_Pxaaa);
+	BIG_rcopy(b,CURVE_Pxaab);
+	FP2_from_BIGs(&Aa,a,b);
+
+	BIG_rcopy(a,CURVE_Pxaba);
+	BIG_rcopy(b,CURVE_Pxabb);
+	FP2_from_BIGs(&Bb,a,b);
+
+	FP4_from_FP2s(&A,&Aa,&Bb);
+
+	BIG_rcopy(a,CURVE_Pxbaa);
+	BIG_rcopy(b,CURVE_Pxbab);
+	FP2_from_BIGs(&Aa,a,b);
+
+	BIG_rcopy(a,CURVE_Pxbba);
+	BIG_rcopy(b,CURVE_Pxbbb);
+	FP2_from_BIGs(&Bb,a,b);
+
+	FP4_from_FP2s(&B,&Aa,&Bb);
+
+	FP8_from_FP4s(&X,&A,&B);
+
+	BIG_rcopy(a,CURVE_Pyaaa);
+	BIG_rcopy(b,CURVE_Pyaab);
+	FP2_from_BIGs(&Aa,a,b);
+
+	BIG_rcopy(a,CURVE_Pyaba);
+	BIG_rcopy(b,CURVE_Pyabb);
+	FP2_from_BIGs(&Bb,a,b);
+
+	FP4_from_FP2s(&A,&Aa,&Bb);
+
+	BIG_rcopy(a,CURVE_Pybaa);
+	BIG_rcopy(b,CURVE_Pybab);
+	FP2_from_BIGs(&Aa,a,b);
+
+	BIG_rcopy(a,CURVE_Pybba);
+	BIG_rcopy(b,CURVE_Pybbb);
+	FP2_from_BIGs(&Bb,a,b);
+
+	FP4_from_FP2s(&B,&Aa,&Bb);
+
+	FP8_from_FP4s(&Y,&A,&B);
+
+	ECP8_set(G,&X,&Y);
+}
+
+
+// g++ -O2 ecp8_BLS48.cpp fp8_BLS48.cpp fp4_BLS48.cpp fp2_BLS48.cpp fp_BLS48.cpp big_B560_29.cpp rand.cpp hash.cpp rom_field_BLS48.cpp rom_curve_BLS48.cpp oct.cpp -o ecp8_BLS48.exe
+/*
+int main()
+{
+	int i;
+	ECP8 G,P;
+	FP2 Aa,Bb,f;
+	FP8 X,Y;
+	BIG a,b,r,p;
+	char w[100];
+	octet W= {0,sizeof(w),w};
+
+	ECP8_generator(&G);
+
+	BIG_rcopy(a,Fra);
+    BIG_rcopy(b,Frb);
+	FP2_from_BIGs(&f,a,b);
+
+	if (G.inf) cout << "Failed to set - point not on curve" << endl;
+	else cout << "set success" << endl;
+
+	ECP8_output(&G);
+	ECP8_copy(&P,&G);
+
+	BIG_rcopy(r,CURVE_Order);
+	BIG_rcopy(p,Modulus);
+
+	BIG_output(r);
+	cout << endl;
+
+	ECP8_mul(&G,r);
+	ECP8_output(&G);
+	cout << endl;
+
+	ECP8_copy(&G,&P);
+
+	cout << "pG = ";
+	ECP8_mul(&G,p);
+	ECP8_output(&G);
+	cout << endl;
+
+	cout << "G^p= ";
+	ECP8_frob(&P,&f,1);
+	ECP8_output(&P);
+	cout << endl;
+
+
+	for (i=0;i<MODBYTES_XXX;i++)
+	{
+		W.val[i]=i+11;
+	}
+	W.len=MODBYTES_XXX;
+
+	printf("W= ");
+	OCT_output(&W);
+	printf("\n");
+
+	ECP8_mapit(&P,&W);
+
+	cout << "Hash to P= ";
+	ECP8_output(&P);
+	cout << endl;
+
+	ECP8_mul(&P,r);
+
+	cout << "rP= ";
+	ECP8_output(&P);
+	cout << endl;
+
+
+
+//	ECP8_dbl(&G);
+//	ECP8_output(&G);
+//	ECP8_reduce(&G);
+//	cout << endl;
+//	ECP8_add(&G,&P);
+//	ECP8_output(&G);
+//	cout << endl;
+
+
+	return 0;
+}
+*/
+
diff --git a/version3/cpp/ecp8.h b/version3/cpp/ecp8.h
new file mode 100644
index 0000000..681f199
--- /dev/null
+++ b/version3/cpp/ecp8.h
@@ -0,0 +1,253 @@
+#ifndef ECP8_ZZZ_H
+#define ECP8_ZZZ_H
+
+#include "fp8_YYY.h"
+#include "config_curve_ZZZ.h"
+
+using namespace amcl;
+
+namespace YYY {
+
+extern const XXX::BIG Fra; /**< real part of BN curve Frobenius Constant */
+extern const XXX::BIG Frb; /**< imaginary part of BN curve Frobenius Constant */
+
+}
+
+namespace ZZZ {
+
+/**
+	@brief ECP8 Structure - Elliptic Curve Point over quadratic extension field
+*/
+
+typedef struct
+{
+//    int inf; /**< Infinity Flag */
+    YYY::FP8 x;   /**< x-coordinate of point */
+    YYY::FP8 y;   /**< y-coordinate of point */
+    YYY::FP8 z;   /**< z-coordinate of point */
+} ECP8;
+
+
+/* Curve Params - see rom.c */
+extern const int CURVE_A;		/**< Elliptic curve A parameter */
+extern const int CURVE_B_I;		/**< Elliptic curve B parameter */
+extern const XXX::BIG CURVE_B;     /**< Elliptic curve B parameter */
+extern const XXX::BIG CURVE_Order; /**< Elliptic curve group order */
+extern const XXX::BIG CURVE_Cof;   /**< Elliptic curve cofactor */
+extern const XXX::BIG CURVE_Bnx;   /**< Elliptic curve parameter */
+
+
+/* Generator point on G1 */
+extern const XXX::BIG CURVE_Gx; /**< x-coordinate of generator point in group G1  */
+extern const XXX::BIG CURVE_Gy; /**< y-coordinate of generator point in group G1  */
+
+/* For Pairings only */
+
+/* Generator point on G2 */
+extern const XXX::BIG CURVE_Pxaaa; /**< real part of x-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pxaab; /**< imaginary part of x-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pxaba; /**< real part of x-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pxabb; /**< imaginary part of x-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pxbaa; /**< real part of x-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pxbab; /**< imaginary part of x-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pxbba; /**< real part of x-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pxbbb; /**< imaginary part of x-coordinate of generator point in group G2 */
+
+extern const XXX::BIG CURVE_Pyaaa; /**< real part of y-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pyaab; /**< imaginary part of y-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pyaba; /**< real part of y-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pyabb; /**< imaginary part of y-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pybaa; /**< real part of y-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pybab; /**< imaginary part of y-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pybba; /**< real part of y-coordinate of generator point in group G2 */
+extern const XXX::BIG CURVE_Pybbb; /**< imaginary part of y-coordinate of generator point in group G2 */
+
+
+/* ECP8 E(FP8) prototypes */
+/**	@brief Tests for ECP8 point equal to infinity
+ *
+	@param P ECP8 point to be tested
+	@return 1 if infinity, else returns 0
+ */
+extern int ECP8_isinf(ECP8 *P);
+/**	@brief Copy ECP8 point to another ECP8 point
+ *
+	@param P ECP8 instance, on exit = Q
+	@param Q ECP8 instance to be copied
+ */
+extern void ECP8_copy(ECP8 *P,ECP8 *Q);
+/**	@brief Set ECP8 to point-at-infinity
+ *
+	@param P ECP8 instance to be set to infinity
+ */
+extern void ECP8_inf(ECP8 *P);
+/**	@brief Tests for equality of two ECP8s
+ *
+	@param P ECP8 instance to be compared
+	@param Q ECP8 instance to be compared
+	@return 1 if P=Q, else returns 0
+ */
+extern int ECP8_equals(ECP8 *P,ECP8 *Q);
+
+/**	@brief Converts an ECP8 point from Projective (x,y,z) coordinates to affine (x,y) coordinates
+ *
+	@param P ECP8 instance to be converted to affine form
+ */
+extern void ECP8_affine(ECP8 *P);
+
+
+/**	@brief Extract x and y coordinates of an ECP8 point P
+ *
+	If x=y, returns only x
+	@param x FP8 on exit = x coordinate of point
+	@param y FP8 on exit = y coordinate of point (unless x=y)
+	@param P ECP8 instance (x,y)
+	@return -1 if P is point-at-infinity, else 0
+ */
+extern int ECP8_get(YYY::FP8 *x,YYY::FP8 *y,ECP8 *P);
+/**	@brief Formats and outputs an ECP8 point to the console, converted to affine coordinates
+ *
+	@param P ECP8 instance to be printed
+ */
+extern void ECP8_output(ECP8 *P);
+
+/**	@brief Formats and outputs an ECP8 point to an octet string
+ *
+	The octet string is created in the form x|y.
+	Convert the real and imaginary parts of the x and y coordinates to big-endian base 256 form.
+	@param S output octet string
+	@param P ECP8 instance to be converted to an octet string
+ */
+extern void ECP8_toOctet(octet *S,ECP8 *P);
+/**	@brief Creates an ECP8 point from an octet string
+ *
+	The octet string is in the form x|y
+	The real and imaginary parts of the x and y coordinates are in big-endian base 256 form.
+	@param P ECP8 instance to be created from the octet string
+	@param S input octet string
+	return 1 if octet string corresponds to a point on the curve, else 0
+ */
+extern int ECP8_fromOctet(ECP8 *P,octet *S);
+/**	@brief Calculate Right Hand Side of curve equation y^2=f(x)
+ *
+	Function f(x)=x^3+Ax+B
+	Used internally.
+	@param r FP8 value of f(x)
+	@param x FP8 instance
+ */
+extern void ECP8_rhs(YYY::FP8 *r,YYY::FP8 *x);
+/**	@brief Set ECP8 to point(x,y) given x and y
+ *
+	Point P set to infinity if no such point on the curve.
+	@param P ECP8 instance to be set (x,y)
+	@param x FP8 x coordinate of point
+	@param y FP8 y coordinate of point
+	@return 1 if point exists, else 0
+ */
+extern int ECP8_set(ECP8 *P,YYY::FP8 *x,YYY::FP8 *y);
+/**	@brief Set ECP to point(x,[y]) given x
+ *
+	Point P set to infinity if no such point on the curve. Otherwise y coordinate is calculated from x.
+	@param P ECP instance to be set (x,[y])
+	@param x BIG x coordinate of point
+	@return 1 if point exists, else 0
+ */
+extern int ECP8_setx(ECP8 *P,YYY::FP8 *x);
+/**	@brief Negation of an ECP8 point
+ *
+	@param P ECP8 instance, on exit = -P
+ */
+extern void ECP8_neg(ECP8 *P);
+
+/**	@brief Reduction of an ECP8 point
+ *
+	@param P ECP8 instance, on exit (x,y) are reduced wrt the modulus
+ */
+extern void ECP8_reduce(ECP8 *P);
+
+
+/**	@brief Doubles an ECP8 instance P and returns slope
+ *
+	@param P ECP8 instance, on exit =2*P
+	@param lam FP8 instance, slope of line
+ */
+//extern int ECP8_sdbl(ECP8 *P,FP8 *lam);
+/**	@brief Adds ECP8 instance Q to ECP8 instance P and returns slope
+ *
+	@param P ECP8 instance, on exit =P+Q
+	@param Q ECP8 instance to be added to P
+	@param lam FP8 instance, slope of line
+ */
+//extern int ECP8_sadd(ECP8 *P,ECP8 *Q,FP8 *lam);
+
+
+/**	@brief Doubles an ECP8 instance P
+ *
+	@param P ECP8 instance, on exit =2*P
+ */
+extern int ECP8_dbl(ECP8 *P);
+/**	@brief Adds ECP8 instance Q to ECP8 instance P
+ *
+	@param P ECP8 instance, on exit =P+Q
+	@param Q ECP8 instance to be added to P
+ */
+extern int ECP8_add(ECP8 *P,ECP8 *Q);
+/**	@brief Subtracts ECP instance Q from ECP8 instance P
+ *
+	@param P ECP8 instance, on exit =P-Q
+	@param Q ECP8 instance to be subtracted from P
+ */
+extern void ECP8_sub(ECP8 *P,ECP8 *Q);
+/**	@brief Multiplies an ECP8 instance P by a BIG, side-channel resistant
+ *
+	Uses fixed sized windows.
+	@param P ECP8 instance, on exit =b*P
+	@param b BIG number multiplier
+
+ */
+extern void ECP8_mul(ECP8 *P,XXX::BIG b);
+
+/**	@brief Calculates required Frobenius constants
+ *
+	Calculate Frobenius constants
+	@param F array of FP2 precalculated constants
+
+ */
+extern void ECP8_frob_constants(YYY::FP2 F[3]);
+
+/**	@brief Multiplies an ECP8 instance P by the internal modulus p^n, using precalculated Frobenius constants
+ *
+	Fast point multiplication using Frobenius
+	@param P ECP8 instance, on exit = p^n*P
+	@param F array of FP2 precalculated Frobenius constant
+	@param n power of prime
+
+ */
+extern void ECP8_frob(ECP8 *P,YYY::FP2 F[3],int n);
+
+/**	@brief Calculates P=Sigma b[i]*Q[i] for i=0 to 7
+ *
+	@param P ECP8 instance, on exit = Sigma b[i]*Q[i] for i=0 to 7
+	@param Q ECP8 array of 4 points
+	@param b BIG array of 4 multipliers
+ */
+extern void ECP8_mul16(ECP8 *P,ECP8 *Q,XXX::BIG *b);
+
+
+/**	@brief Maps random BIG to curve point of correct order
+ *
+	@param P ECP8 instance of correct order
+	@param W OCTET byte array to be mapped
+ */
+extern void ECP8_mapit(ECP8 *P,octet *w);
+
+/**	@brief Get Group Generator from ROM
+ *
+	@param G ECP8 instance
+ */
+extern void ECP8_generator(ECP8 *G);
+
+
+}
+
+#endif
\ No newline at end of file
diff --git a/version3/cpp/ff.cpp b/version3/cpp/ff.cpp
new file mode 100644
index 0000000..ff6f192
--- /dev/null
+++ b/version3/cpp/ff.cpp
@@ -0,0 +1,1181 @@
+/*
+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.
+*/
+
+/* AMCL basic functions for Large Finite Field support */
+
+#include "ff_WWW.h"
+
+using namespace XXX; 
+
+namespace WWW {
+	static void FF_dsucopy(BIG x[],BIG y[],int);
+	static void FF_dscopy(BIG x[],BIG y[],int);
+	static void FF_sducopy(BIG x[],BIG y[],int);
+	static void FF_shrw(BIG a[],int);
+	static void FF_shlw(BIG a[],int);
+	static void FF_radd(BIG z[],int,BIG x[],int,BIG y[],int,int);
+	static void FF_rinc(BIG z[],int,BIG y[],int,int);
+	static void FF_rdec(BIG z[],int,BIG y[],int,int);
+	static void FF_rnorm(BIG z[],int,int);
+	static void FF_cswap(BIG a[],BIG b[],int,int);
+	static void FF_karmul(BIG z[],int,BIG x[],int,BIG y[],int,BIG t[],int,int);
+	static void FF_karsqr(BIG z[],int,BIG x[],int,BIG t[],int,int);
+	static void FF_karmul_lower(BIG z[],int,BIG x[],int,BIG y[],int,BIG t[],int,int);
+	static void FF_karmul_upper(BIG z[],BIG x[],BIG y[],BIG t[],int);
+	static void FF_lmul(BIG z[],BIG x[],BIG y[],int);
+	static void FF_reduce(BIG r[],BIG T[],BIG N[],BIG ND[],int);
+	static void FF_nres(BIG a[],BIG m[],int);
+	static void FF_redc(BIG a[],BIG m[],BIG ND[],int);
+	static void FF_invmod2m(BIG U[],BIG a[],int);
+	static void FF_modmul(BIG z[],BIG x[],BIG y[],BIG p[],BIG ND[],int);
+	static void FF_modsqr(BIG z[],BIG x[],BIG p[],BIG ND[],int);
+}
+
+/* Arazi and Qi inversion mod 256 */
+static int invmod256(int a)
+{
+    int U,t1,t2,b,c;
+    t1=0;
+    c=(a>>1)&1;
+    t1+=c;
+    t1&=1;
+    t1=2-t1;
+    t1<<=1;
+    U=t1+1;
+
+// i=2
+    b=a&3;
+    t1=U*b;
+    t1>>=2;
+    c=(a>>2)&3;
+    t2=(U*c)&3;
+    t1+=t2;
+    t1*=U;
+    t1&=3;
+    t1=4-t1;
+    t1<<=2;
+    U+=t1;
+
+// i=4
+    b=a&15;
+    t1=U*b;
+    t1>>=4;
+    c=(a>>4)&15;
+    t2=(U*c)&15;
+    t1+=t2;
+    t1*=U;
+    t1&=15;
+    t1=16-t1;
+    t1<<=4;
+    U+=t1;
+
+    return U;
+}
+
+/* a=1/a mod 2^BIGBITS_XXX. This is very fast! */
+void XXX::BIG_invmod2m(BIG a)
+{
+    int i;
+    BIG U,t1,b,c;
+    BIG_zero(U);
+    BIG_inc(U,invmod256(BIG_lastbits(a,8)));
+    for (i=8; i<BIGBITS_XXX; i<<=1)
+    {
+		BIG_norm(U);
+        BIG_copy(b,a);
+        BIG_mod2m(b,i);   // bottom i bits of a
+
+        BIG_smul(t1,U,b);
+        BIG_shr(t1,i); // top i bits of U*b
+
+        BIG_copy(c,a);
+        BIG_shr(c,i);
+        BIG_mod2m(c,i); // top i bits of a
+
+        BIG_smul(b,U,c);
+        BIG_mod2m(b,i);  // bottom i bits of U*c
+
+        BIG_add(t1,t1,b);
+		BIG_norm(t1);
+        BIG_smul(b,t1,U);
+        BIG_copy(t1,b);  // (t1+b)*U
+        BIG_mod2m(t1,i);				// bottom i bits of (t1+b)*U
+
+        BIG_one(b);
+        BIG_shl(b,i);
+        BIG_sub(t1,b,t1);
+        BIG_norm(t1);
+
+        BIG_shl(t1,i);
+
+        BIG_add(U,U,t1);
+    }
+    BIG_copy(a,U);
+    BIG_norm(a);
+    BIG_mod2m(a,BIGBITS_XXX);
+}
+
+/*
+void FF_rcopy(BIG x[],const BIG y[],int n)
+{
+	int i;
+	for (i=0;i<n;i++)
+		BIG_rcopy(x[i],y[i]);
+}
+*/
+
+/* x=y */
+void WWW::FF_copy(BIG x[],BIG y[],int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+        BIG_copy(x[i],y[i]);
+}
+
+/* x=y<<n */
+static void WWW::FF_dsucopy(BIG x[],BIG y[],int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+    {
+        BIG_copy(x[n+i],y[i]);
+        BIG_zero(x[i]);
+    }
+}
+
+/* x=y */
+static void WWW::FF_dscopy(BIG x[],BIG y[],int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+    {
+        BIG_copy(x[i],y[i]);
+        BIG_zero(x[n+i]);
+    }
+}
+
+/* x=y>>n */
+static void WWW::FF_sducopy(BIG x[],BIG y[],int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+        BIG_copy(x[i],y[n+i]);
+}
+
+/* set to zero */
+void WWW::FF_zero(BIG x[],int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+        BIG_zero(x[i]);
+}
+
+/* test equals 0 */
+int WWW::FF_iszilch(BIG x[],int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+        if (!BIG_iszilch(x[i])) return 0;
+    return 1;
+}
+
+/* shift right by BIGBITS_XXX-bit words */
+static void WWW::FF_shrw(BIG a[],int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+    {
+        BIG_copy(a[i],a[i+n]);
+        BIG_zero(a[i+n]);
+    }
+}
+
+/* shift left by BIGBITS_XXX-bit words */
+static void WWW::FF_shlw(BIG a[],int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+    {
+        BIG_copy(a[i+n],a[i]);
+        BIG_zero(a[i]);
+    }
+}
+
+/* extract last bit */
+int WWW::FF_parity(BIG x[])
+{
+    return BIG_parity(x[0]);
+}
+
+/* extract last m bits */
+int WWW::FF_lastbits(BIG x[],int m)
+{
+    return BIG_lastbits(x[0],m);
+}
+
+/* x=1 */
+void WWW::FF_one(BIG x[],int n)
+{
+    int i;
+    BIG_one(x[0]);
+    for (i=1; i<n; i++)
+        BIG_zero(x[i]);
+}
+
+/* x=m, where m is 32-bit int */
+void WWW::FF_init(BIG x[],sign32 m,int n)
+{
+    int i;
+    BIG_zero(x[0]);
+#if CHUNK<64
+    x[0][0]=(chunk)(m&BMASK_XXX);
+    x[0][1]=(chunk)(m>>BASEBITS_XXX);
+#else
+    x[0][0]=(chunk)m;
+#endif
+    for (i=1; i<n; i++)
+        BIG_zero(x[i]);
+}
+
+/* compare x and y - must be normalised */
+int WWW::FF_comp(BIG x[],BIG y[],int n)
+{
+    int i,j;
+    for (i=n-1; i>=0; i--)
+    {
+        j=BIG_comp(x[i],y[i]);
+        if (j!=0) return j;
+    }
+    return 0;
+}
+
+/* recursive add */
+static void WWW::FF_radd(BIG z[],int zp,BIG x[],int xp,BIG y[],int yp,int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+        BIG_add(z[zp+i],x[xp+i],y[yp+i]);
+}
+
+/* recursive inc */
+static void WWW::FF_rinc(BIG z[],int zp,BIG y[],int yp,int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+        BIG_add(z[zp+i],z[zp+i],y[yp+i]);
+}
+
+/* recursive sub */
+/*
+static void FF_rsub(BIG z[],int zp,BIG x[],int xp,BIG y[],int yp,int n)
+{
+	int i;
+	for (i=0;i<n;i++)
+		BIG_sub(z[zp+i],x[xp+i],y[yp+i]);
+}
+*/
+
+/* recursive dec */
+static void WWW::FF_rdec(BIG z[],int zp,BIG y[],int yp,int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+        BIG_sub(z[zp+i],z[zp+i],y[yp+i]);
+}
+
+/* simple add */
+void WWW::FF_add(BIG z[],BIG x[],BIG y[],int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+        BIG_add(z[i],x[i],y[i]);
+}
+
+/* simple sub */
+void WWW::FF_sub(BIG z[],BIG x[],BIG y[],int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+        BIG_sub(z[i],x[i],y[i]);
+}
+
+/* increment/decrement by a small integer */
+void WWW::FF_inc(BIG x[],int m,int n)
+{
+    BIG_inc(x[0],m);
+    FF_norm(x,n);
+}
+
+void WWW::FF_dec(BIG x[],int m,int n)
+{
+    BIG_dec(x[0],m);
+    FF_norm(x,n);
+}
+
+/* normalise - but hold any overflow in top part unless n<0 */
+static void WWW::FF_rnorm(BIG z[],int zp,int n)
+{
+    int i,trunc=0;
+    chunk carry;
+    if (n<0)
+    {
+        /* -v n signals to do truncation */
+        n=-n;
+        trunc=1;
+    }
+    for (i=0; i<n-1; i++)
+    {
+        carry=BIG_norm(z[zp+i]);
+
+        z[zp+i][NLEN_XXX-1]^=carry<<P_TBITS_WWW; /* remove it */
+        z[zp+i+1][0]+=carry;
+    }
+    carry=BIG_norm(z[zp+n-1]);
+    if (trunc) z[zp+n-1][NLEN_XXX-1]^=carry<<P_TBITS_WWW;
+}
+
+void WWW::FF_norm(BIG z[],int n)
+{
+    FF_rnorm(z,0,n);
+}
+
+/* shift left by one bit */
+void WWW::FF_shl(BIG x[],int n)
+{
+    int i;
+    int carry,delay_carry=0;
+    for (i=0; i<n-1; i++)
+    {
+        carry=BIG_fshl(x[i],1);
+        x[i][0]|=delay_carry;
+        x[i][NLEN_XXX-1]^=(chunk)carry<<P_TBITS_WWW;
+        delay_carry=carry;
+    }
+    BIG_fshl(x[n-1],1);
+    x[n-1][0]|=delay_carry;
+}
+
+/* shift right by one bit */
+void WWW::FF_shr(BIG x[],int n)
+{
+    int i;
+    int carry;
+    for (i=n-1; i>0; i--)
+    {
+        carry=BIG_fshr(x[i],1);
+        x[i-1][NLEN_XXX-1]|=(chunk)carry<<P_TBITS_WWW;
+    }
+    BIG_fshr(x[0],1);
+}
+
+void WWW::FF_output(BIG x[],int n)
+{
+    int i;
+    FF_norm(x,n);
+    for (i=n-1; i>=0; i--)
+    {
+        BIG_output(x[i]);
+        printf(" ");
+    }
+}
+
+void WWW::FF_rawoutput(BIG x[],int n)
+{
+    int i;
+    for (i=n-1; i>=0; i--)
+    {
+        BIG_rawoutput(x[i]);
+        printf(" ");
+    }
+}
+
+/* Convert FFs to/from octet strings */
+void WWW::FF_toOctet(octet *w,BIG x[],int n)
+{
+    int i;
+    w->len=n*MODBYTES_XXX;
+    for (i=0; i<n; i++)
+    {
+        BIG_toBytes(&(w->val[(n-i-1)*MODBYTES_XXX]),x[i]);
+    }
+}
+
+void WWW::FF_fromOctet(BIG x[],octet *w,int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+    {
+        BIG_fromBytes(x[i],&(w->val[(n-i-1)*MODBYTES_XXX]));
+    }
+}
+
+/* in-place swapping using xor - side channel resistant */
+static void WWW::FF_cswap(BIG a[],BIG b[],int d,int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+        BIG_cswap(a[i],b[i],d);
+    return;
+}
+
+/* z=x*y, t is workspace */
+static void WWW::FF_karmul(BIG z[],int zp,BIG x[],int xp,BIG y[],int yp,BIG t[],int tp,int n)
+{
+    int nd2;
+    if (n==1)
+    {
+		BIG_norm(x[xp]);
+		BIG_norm(y[yp]);
+        BIG_mul(t[tp],x[xp],y[yp]);
+        BIG_split(z[zp+1],z[zp],t[tp],BIGBITS_XXX);
+        return;
+    }
+
+    nd2=n/2;
+    FF_radd(z,zp,x,xp,x,xp+nd2,nd2);
+    FF_rnorm(z,zp,nd2);  /* needs this if recursion level too deep */
+
+    FF_radd(z,zp+nd2,y,yp,y,yp+nd2,nd2);
+    FF_rnorm(z,zp+nd2,nd2);
+    FF_karmul(t,tp,z,zp,z,zp+nd2,t,tp+n,nd2);
+    FF_karmul(z,zp,x,xp,y,yp,t,tp+n,nd2);
+    FF_karmul(z,zp+n,x,xp+nd2,y,yp+nd2,t,tp+n,nd2);
+    FF_rdec(t,tp,z,zp,n);
+    FF_rdec(t,tp,z,zp+n,n);
+    FF_rinc(z,zp+nd2,t,tp,n);
+    FF_rnorm(z,zp,2*n);
+}
+
+static void WWW::FF_karsqr(BIG z[],int zp,BIG x[],int xp,BIG t[],int tp,int n)
+{
+    int nd2;
+    if (n==1)
+    {
+		BIG_norm(x[xp]);
+        BIG_sqr(t[tp],x[xp]);
+        BIG_split(z[zp+1],z[zp],t[tp],BIGBITS_XXX);
+        return;
+    }
+    nd2=n/2;
+    FF_karsqr(z,zp,x,xp,t,tp+n,nd2);
+    FF_karsqr(z,zp+n,x,xp+nd2,t,tp+n,nd2);
+    FF_karmul(t,tp,x,xp,x,xp+nd2,t,tp+n,nd2);
+    FF_rinc(z,zp+nd2,t,tp,n);
+    FF_rinc(z,zp+nd2,t,tp,n);
+
+    FF_rnorm(z,zp+nd2,n);  /* was FF_rnorm(z,zp,2*n)  */
+}
+
+static void WWW::FF_karmul_lower(BIG z[],int zp,BIG x[],int xp,BIG y[],int yp,BIG t[],int tp,int n)
+{
+    /* Calculates Least Significant bottom half of x*y */
+    int nd2;
+    if (n==1)
+    {
+        /* only calculate bottom half of product */
+		BIG_norm(x[xp]);
+		BIG_norm(y[yp]);
+        BIG_smul(z[zp],x[xp],y[yp]);
+        return;
+    }
+    nd2=n/2;
+    FF_karmul(z,zp,x,xp,y,yp,t,tp+n,nd2);
+    FF_karmul_lower(t,tp,x,xp+nd2,y,yp,t,tp+n,nd2);
+    FF_rinc(z,zp+nd2,t,tp,nd2);
+    FF_karmul_lower(t,tp,x,xp,y,yp+nd2,t,tp+n,nd2);
+    FF_rinc(z,zp+nd2,t,tp,nd2);
+    FF_rnorm(z,zp+nd2,-nd2);  /* truncate it */
+}
+
+static void WWW::FF_karmul_upper(BIG z[],BIG x[],BIG y[],BIG t[],int n)
+{
+    /* Calculates Most Significant upper half of x*y, given lower part */
+    int nd2;
+
+    nd2=n/2;
+    FF_radd(z,n,x,0,x,nd2,nd2);
+    FF_radd(z,n+nd2,y,0,y,nd2,nd2);
+    FF_rnorm(z,n,nd2);
+    FF_rnorm(z,n+nd2,nd2);
+
+    FF_karmul(t,0,z,n+nd2,z,n,t,n,nd2);  /* t = (a0+a1)(b0+b1) */
+    FF_karmul(z,n,x,nd2,y,nd2,t,n,nd2); /* z[n]= a1*b1 */
+    /* z[0-nd2]=l(a0b0) z[nd2-n]= h(a0b0)+l(t)-l(a0b0)-l(a1b1) */
+    FF_rdec(t,0,z,n,n);              /* t=t-a1b1  */
+    FF_rinc(z,nd2,z,0,nd2);   /* z[nd2-n]+=l(a0b0) = h(a0b0)+l(t)-l(a1b1)  */
+    FF_rdec(z,nd2,t,0,nd2);   /* z[nd2-n]=h(a0b0)+l(t)-l(a1b1)-l(t-a1b1)=h(a0b0) */
+    FF_rnorm(z,0,-n);					/* a0b0 now in z - truncate it */
+    FF_rdec(t,0,z,0,n);         /* (a0+a1)(b0+b1) - a0b0 */
+    FF_rinc(z,nd2,t,0,n);
+
+    FF_rnorm(z,nd2,n);
+}
+
+/* z=x*y */
+void WWW::FF_mul(BIG z[],BIG x[],BIG y[],int n)
+{
+#ifndef C99
+    BIG t[2*FFLEN_WWW];
+#else
+    BIG t[2*n];
+#endif
+//	FF_norm(x,n); /* change here */
+//	FF_norm(y,n); /* change here */
+    FF_karmul(z,0,x,0,y,0,t,0,n);
+}
+
+/* return low part of product */
+static void WWW::FF_lmul(BIG z[],BIG x[],BIG y[],int n)
+{
+#ifndef C99
+    BIG t[2*FFLEN_WWW];
+#else
+    BIG t[2*n];
+#endif
+//	FF_norm(x,n); /* change here */
+//	FF_norm(y,n); /* change here */
+    FF_karmul_lower(z,0,x,0,y,0,t,0,n);
+}
+
+/* Set b=b mod c */
+void WWW::FF_mod(BIG b[],BIG c[],int n)
+{
+    int k=0;
+
+    FF_norm(b,n);
+    if (FF_comp(b,c,n)<0)
+        return;
+    do
+    {
+        FF_shl(c,n);
+        k++;
+    }
+    while (FF_comp(b,c,n)>=0);
+
+    while (k>0)
+    {
+        FF_shr(c,n);
+        if (FF_comp(b,c,n)>=0)
+        {
+            FF_sub(b,b,c,n);
+            FF_norm(b,n);
+        }
+        k--;
+    }
+}
+
+/* z=x^2 */
+void WWW::FF_sqr(BIG z[],BIG x[],int n)
+{
+#ifndef C99
+    BIG t[2*FFLEN_WWW];
+#else
+    BIG t[2*n];
+#endif
+//	FF_norm(x,n); /* change here */
+    FF_karsqr(z,0,x,0,t,0,n);
+}
+
+/* r=t mod modulus, N is modulus, ND is Montgomery Constant */
+static void WWW::FF_reduce(BIG r[],BIG T[],BIG N[],BIG ND[],int n)
+{
+    /* fast karatsuba Montgomery reduction */
+#ifndef C99
+    BIG t[2*FFLEN_WWW];
+    BIG m[FFLEN_WWW];
+#else
+    BIG t[2*n];
+    BIG m[n];
+#endif
+    WWW::FF_sducopy(r,T,n);  /* keep top half of T */
+    //FF_norm(T,n); /* change here */
+    FF_karmul_lower(m,0,T,0,ND,0,t,0,n);  /* m=T.(1/N) mod R */
+
+    //FF_norm(N,n);  /* change here */
+    FF_karmul_upper(T,N,m,t,n);  /* T=mN */
+    FF_sducopy(m,T,n);
+
+    FF_add(r,r,N,n);
+    FF_sub(r,r,m,n);
+    FF_norm(r,n);
+}
+
+
+/* Set r=a mod b */
+/* a is of length - 2*n */
+/* r,b is of length - n */
+void WWW::FF_dmod(BIG r[],BIG a[],BIG b[],int n)
+{
+    int k;
+#ifndef C99
+    BIG m[2*FFLEN_WWW];
+    BIG x[2*FFLEN_WWW];
+#else
+    BIG m[2*n];
+    BIG x[2*n];
+#endif
+    FF_copy(x,a,2*n);
+    FF_norm(x,2*n);
+    FF_dsucopy(m,b,n);
+    k=BIGBITS_XXX*n;
+
+    while (FF_comp(x,m,2*n)>=0)
+    {
+        FF_sub(x,x,m,2*n);
+        FF_norm(x,2*n);
+    }
+
+    while (k>0)
+    {
+        FF_shr(m,2*n);
+
+        if (FF_comp(x,m,2*n)>=0)
+        {
+            FF_sub(x,x,m,2*n);
+            FF_norm(x,2*n);
+        }
+
+        k--;
+    }
+    FF_copy(r,x,n);
+    FF_mod(r,b,n);
+}
+
+/* Set r=1/a mod p. Binary method - a<p on entry */
+
+void WWW::FF_invmodp(BIG r[],BIG a[],BIG p[],int n)
+{
+#ifndef C99
+    BIG u[FFLEN_WWW],v[FFLEN_WWW],x1[FFLEN_WWW],x2[FFLEN_WWW],t[FFLEN_WWW],one[FFLEN_WWW];
+#else
+    BIG u[n],v[n],x1[n],x2[n],t[n],one[n];
+#endif
+    FF_copy(u,a,n);
+    FF_copy(v,p,n);
+    FF_one(one,n);
+    FF_copy(x1,one,n);
+    FF_zero(x2,n);
+
+// reduce n in here as well!
+    while (FF_comp(u,one,n)!=0 && FF_comp(v,one,n)!=0)
+    {
+        while (FF_parity(u)==0)
+        {
+            FF_shr(u,n);
+            if (FF_parity(x1)!=0)
+            {
+                FF_add(x1,p,x1,n);
+                FF_norm(x1,n);
+            }
+            FF_shr(x1,n);
+        }
+        while (FF_parity(v)==0)
+        {
+            FF_shr(v,n);
+            if (FF_parity(x2)!=0)
+            {
+                FF_add(x2,p,x2,n);
+                FF_norm(x2,n);
+            }
+            FF_shr(x2,n);
+        }
+        if (FF_comp(u,v,n)>=0)
+        {
+
+            FF_sub(u,u,v,n);
+            FF_norm(u,n);
+            if (FF_comp(x1,x2,n)>=0) FF_sub(x1,x1,x2,n);
+            else
+            {
+                FF_sub(t,p,x2,n);
+                FF_add(x1,x1,t,n);
+            }
+            FF_norm(x1,n);
+        }
+        else
+        {
+            FF_sub(v,v,u,n);
+            FF_norm(v,n);
+            if (FF_comp(x2,x1,n)>=0) FF_sub(x2,x2,x1,n);
+            else
+            {
+                FF_sub(t,p,x1,n);
+                FF_add(x2,x2,t,n);
+            }
+            FF_norm(x2,n);
+        }
+    }
+    if (FF_comp(u,one,n)==0)
+        FF_copy(r,x1,n);
+    else
+        FF_copy(r,x2,n);
+}
+
+/* nesidue mod m */
+static void WWW::FF_nres(BIG a[],BIG m[],int n)
+{
+#ifndef C99
+    BIG d[2*FFLEN_WWW];
+#else
+    BIG d[2*n];
+#endif
+	if (n==1)
+	{
+		BIG_dscopy(d[0],a[0]);
+		BIG_dshl(d[0],NLEN_XXX*BASEBITS_XXX);
+		BIG_dmod(a[0],d[0],m[0]);
+	}
+	else
+	{
+		FF_dsucopy(d,a,n);
+		FF_dmod(a,d,m,n);
+	}
+}
+
+static void WWW::FF_redc(BIG a[],BIG m[],BIG ND[],int n)
+{
+#ifndef C99
+    BIG d[2*FFLEN_WWW];
+#else
+    BIG d[2*n];
+#endif
+	if (n==1)
+	{
+		BIG_dzero(d[0]);
+		BIG_dscopy(d[0],a[0]);
+		BIG_monty(a[0],m[0],((chunk)1<<BASEBITS_XXX)-ND[0][0],d[0]);
+	}
+	else
+	{
+		FF_mod(a,m,n);
+		FF_dscopy(d,a,n);
+		FF_reduce(a,d,m,ND,n);
+		FF_mod(a,m,n);
+	}
+}
+
+/* U=1/a mod 2^m - Arazi & Qi */
+static void WWW::FF_invmod2m(BIG U[],BIG a[],int n)
+{
+    int i;
+#ifndef C99
+    BIG t1[FFLEN_WWW],b[FFLEN_WWW],c[FFLEN_WWW];
+#else
+    BIG t1[2*n],b[n],c[n];
+#endif
+
+    FF_zero(U,n);
+    FF_zero(b,n);
+    FF_zero(c,n);
+    FF_zero(t1,2*n);
+
+    BIG_copy(U[0],a[0]);
+    BIG_invmod2m(U[0]);
+    for (i=1; i<n; i<<=1)
+    {
+        FF_copy(b,a,i);
+        FF_mul(t1,U,b,i);
+        FF_shrw(t1,i); // top half to bottom half, top half=0
+
+        FF_copy(c,a,2*i);
+        FF_shrw(c,i); // top half of c
+        FF_lmul(b,U,c,i); // should set top half of b=0
+        FF_add(t1,t1,b,i);
+        FF_norm(t1,2*i);
+        FF_lmul(b,t1,U,i);
+        FF_copy(t1,b,i);
+        FF_one(b,i);
+        FF_shlw(b,i);
+        FF_sub(t1,b,t1,2*i);
+        FF_norm(t1,2*i);
+        FF_shlw(t1,i);
+        FF_add(U,U,t1,2*i);
+    }
+
+    FF_norm(U,n);
+}
+
+void WWW::FF_random(BIG x[],csprng *rng,int n)
+{
+    int i;
+    for (i=0; i<n; i++)
+    {
+        BIG_random(x[i],rng);
+    }
+    /* make sure top bit is 1 */
+    while (BIG_nbits(x[n-1])<MODBYTES_XXX*8) BIG_random(x[n-1],rng);
+}
+
+/* generate random x mod p */
+void WWW::FF_randomnum(BIG x[],BIG p[],csprng *rng,int n)
+{
+    int i;
+#ifndef C99
+    BIG d[2*FFLEN_WWW];
+#else
+    BIG d[2*n];
+#endif
+    for (i=0; i<2*n; i++)
+    {
+        BIG_random(d[i],rng);
+    }
+    FF_dmod(x,d,p,n);
+}
+
+static void WWW::FF_modmul(BIG z[],BIG x[],BIG y[],BIG p[],BIG ND[],int n)
+{
+#ifndef C99
+    BIG d[2*FFLEN_WWW];
+#else
+    BIG d[2*n];
+#endif
+    chunk ex=P_EXCESS_WWW(x[n-1]);
+    chunk ey=P_EXCESS_WWW(y[n-1]);
+#ifdef dchunk
+    if ((dchunk)(ex+1)*(ey+1)>(dchunk)P_FEXCESS_WWW)
+#else
+    if ((ex+1)>P_FEXCESS_WWW/(ey+1))
+#endif
+    {
+#ifdef DEBUG_REDUCE
+        printf("Product too large - reducing it %d %d\n",ex,ey);
+#endif
+        FF_mod(x,p,n);
+    }
+
+	if (n==1)
+	{
+		BIG_mul(d[0],x[0],y[0]);
+		BIG_monty(z[0],p[0],((chunk)1<<BASEBITS_XXX)-ND[0][0],d[0]);
+	}
+	else
+	{
+		FF_mul(d,x,y,n);
+		FF_reduce(z,d,p,ND,n);
+	}
+}
+
+static void WWW::FF_modsqr(BIG z[],BIG x[],BIG p[],BIG ND[],int n)
+{
+#ifndef C99
+    BIG d[2*FFLEN_WWW];
+#else
+    BIG d[2*n];
+#endif
+    chunk ex=P_EXCESS_WWW(x[n-1]);
+#ifdef dchunk
+    if ((dchunk)(ex+1)*(ex+1)>(dchunk)P_FEXCESS_WWW)
+#else
+    if ((ex+1)>P_FEXCESS_WWW/(ex+1))
+#endif
+    {
+#ifdef DEBUG_REDUCE
+        printf("Product too large - reducing it %d\n",ex);
+#endif
+        FF_mod(x,p,n);
+    }
+	if (n==1)
+	{
+		BIG_sqr(d[0],x[0]);
+		BIG_monty(z[0],p[0],((chunk)1<<BASEBITS_XXX)-ND[0][0],d[0]);
+	}
+	else
+	{
+		FF_sqr(d,x,n);
+		FF_reduce(z,d,p,ND,n);
+	}
+}
+
+/* r=x^e mod p using side-channel resistant Montgomery Ladder, for large e */
+void WWW::FF_skpow(BIG r[],BIG x[],BIG e[],BIG p[],int n)
+{
+    int i,b;
+#ifndef C99
+    BIG R0[FFLEN_WWW],R1[FFLEN_WWW],ND[FFLEN_WWW];
+#else
+    BIG R0[n],R1[n],ND[n];
+#endif
+    FF_invmod2m(ND,p,n);
+
+    FF_one(R0,n);
+    FF_copy(R1,x,n);
+    FF_nres(R0,p,n);
+    FF_nres(R1,p,n);
+
+    for (i=8*MODBYTES_XXX*n-1; i>=0; i--)
+    {
+        b=BIG_bit(e[i/BIGBITS_XXX],i%BIGBITS_XXX);
+        FF_modmul(r,R0,R1,p,ND,n);
+
+        FF_cswap(R0,R1,b,n);
+        FF_modsqr(R0,R0,p,ND,n);
+
+        FF_copy(R1,r,n);
+        FF_cswap(R0,R1,b,n);
+    }
+    FF_copy(r,R0,n);
+    FF_redc(r,p,ND,n);
+}
+
+/* r=x^e mod p using side-channel resistant Montgomery Ladder, for short e */
+void WWW::FF_skspow(BIG r[],BIG x[],BIG e,BIG p[],int n)
+{
+    int i,b;
+#ifndef C99
+    BIG R0[FFLEN_WWW],R1[FFLEN_WWW],ND[FFLEN_WWW];
+#else
+    BIG R0[n],R1[n],ND[n];
+#endif
+    FF_invmod2m(ND,p,n);
+    FF_one(R0,n);
+    FF_copy(R1,x,n);
+    FF_nres(R0,p,n);
+    FF_nres(R1,p,n);
+    for (i=8*MODBYTES_XXX-1; i>=0; i--)
+    {
+        b=BIG_bit(e,i);
+        FF_modmul(r,R0,R1,p,ND,n);
+        FF_cswap(R0,R1,b,n);
+        FF_modsqr(R0,R0,p,ND,n);
+        FF_copy(R1,r,n);
+        FF_cswap(R0,R1,b,n);
+    }
+    FF_copy(r,R0,n);
+    FF_redc(r,p,ND,n);
+}
+
+/* raise to an integer power - right-to-left method */
+void WWW::FF_power(BIG r[],BIG x[],int e,BIG p[],int n)
+{
+    int f=1;
+#ifndef C99
+    BIG w[FFLEN_WWW],ND[FFLEN_WWW];
+#else
+    BIG w[n],ND[n];
+#endif
+    FF_invmod2m(ND,p,n);
+
+    FF_copy(w,x,n);
+    FF_nres(w,p,n);
+
+    if (e==2)
+    {
+        FF_modsqr(r,w,p,ND,n);
+    }
+    else for (;;)
+        {
+            if (e%2==1)
+            {
+                if (f) FF_copy(r,w,n);
+                else FF_modmul(r,r,w,p,ND,n);
+                f=0;
+            }
+            e>>=1;
+            if (e==0) break;
+            FF_modsqr(w,w,p,ND,n);
+        }
+
+    FF_redc(r,p,ND,n);
+}
+
+/* r=x^e mod p, faster but not side channel resistant */
+void WWW::FF_pow(BIG r[],BIG x[],BIG e[],BIG p[],int n)
+{
+    int i,b;
+#ifndef C99
+    BIG w[FFLEN_WWW],ND[FFLEN_WWW];
+#else
+    BIG w[n],ND[n];
+#endif
+    FF_invmod2m(ND,p,n);
+
+    FF_copy(w,x,n);
+    FF_one(r,n);
+    FF_nres(r,p,n);
+    FF_nres(w,p,n);
+
+    for (i=8*MODBYTES_XXX*n-1; i>=0; i--)
+    {
+        FF_modsqr(r,r,p,ND,n);
+        b=BIG_bit(e[i/BIGBITS_XXX],i%BIGBITS_XXX);
+        if (b==1) FF_modmul(r,r,w,p,ND,n);
+    }
+    FF_redc(r,p,ND,n);
+}
+
+/* double exponentiation r=x^e.y^f mod p */
+void WWW::FF_pow2(BIG r[],BIG x[],BIG e,BIG y[],BIG f,BIG p[],int n)
+{
+    int i,eb,fb;
+#ifndef C99
+    BIG xn[FFLEN_WWW],yn[FFLEN_WWW],xy[FFLEN_WWW],ND[FFLEN_WWW];
+#else
+    BIG xn[n],yn[n],xy[n],ND[n];
+#endif
+
+    FF_invmod2m(ND,p,n);
+
+    FF_copy(xn,x,n);
+    FF_copy(yn,y,n);
+    FF_nres(xn,p,n);
+    FF_nres(yn,p,n);
+    FF_modmul(xy,xn,yn,p,ND,n);
+    FF_one(r,n);
+    FF_nres(r,p,n);
+
+    for (i=8*MODBYTES_XXX-1; i>=0; i--)
+    {
+        eb=BIG_bit(e,i);
+        fb=BIG_bit(f,i);
+        FF_modsqr(r,r,p,ND,n);
+        if (eb==1)
+        {
+            if (fb==1) FF_modmul(r,r,xy,p,ND,n);
+            else FF_modmul(r,r,xn,p,ND,n);
+        }
+        else
+        {
+            if (fb==1) FF_modmul(r,r,yn,p,ND,n);
+        }
+    }
+    FF_redc(r,p,ND,n);
+}
+
+static sign32 igcd(sign32 x,sign32 y)
+{
+    /* integer GCD, returns GCD of x and y */
+    sign32 r;
+    if (y==0) return x;
+    while ((r=x%y)!=0)
+        x=y,y=r;
+    return y;
+}
+
+/* quick and dirty check for common factor with s */
+int WWW::FF_cfactor(BIG w[],sign32 s,int n)
+{
+    int r;
+    sign32 g;
+#ifndef C99
+    BIG x[FFLEN_WWW],y[FFLEN_WWW];
+#else
+    BIG x[n],y[n];
+#endif
+    FF_init(y,s,n);
+    FF_copy(x,w,n);
+    FF_norm(x,n);
+
+//	if (FF_parity(x)==0) return 1;
+    do
+    {
+        FF_sub(x,x,y,n);
+        FF_norm(x,n);
+        while (!FF_iszilch(x,n) && FF_parity(x)==0) FF_shr(x,n);
+    }
+    while (FF_comp(x,y,n)>0);
+#if CHUNK<32
+    g=x[0][0]+((sign32)(x[0][1])<<BASEBITS_XXX);
+#else
+    g=(sign32)x[0][0];
+#endif
+    r=igcd(s,g);
+    if (r>1) return 1;
+    return 0;
+}
+
+/* Miller-Rabin test for primality. Slow. */
+int WWW::FF_prime(BIG p[],csprng *rng,int n)
+{
+    int i,j,loop,s=0;
+#ifndef C99
+    BIG d[FFLEN_WWW],x[FFLEN_WWW],unity[FFLEN_WWW],nm1[FFLEN_WWW];
+#else
+    BIG d[n],x[n],unity[n],nm1[n];
+#endif
+    sign32 sf=4849845;/* 3*5*.. *19 */
+
+    FF_norm(p,n);
+
+    if (FF_cfactor(p,sf,n)) return 0;
+
+    FF_one(unity,n);
+    FF_sub(nm1,p,unity,n);
+    FF_norm(nm1,n);
+    FF_copy(d,nm1,n);
+    while (FF_parity(d)==0)
+    {
+        FF_shr(d,n);
+        s++;
+    }
+    if (s==0) return 0;
+
+    for (i=0; i<10; i++)
+    {
+        FF_randomnum(x,p,rng,n);
+        FF_pow(x,x,d,p,n);
+        if (FF_comp(x,unity,n)==0 || FF_comp(x,nm1,n)==0) continue;
+        loop=0;
+        for (j=1; j<s; j++)
+        {
+            FF_power(x,x,2,p,n);
+            if (FF_comp(x,unity,n)==0) return 0;
+            if (FF_comp(x,nm1,n)==0 )
+            {
+                loop=1;
+                break;
+            }
+        }
+        if (loop) continue;
+        return 0;
+    }
+
+    return 1;
+}
+
+/*
+BIG P[4]= {{0x1670957,0x1568CD3C,0x2595E5,0xEED4F38,0x1FC9A971,0x14EF7E62,0xA503883,0x9E1E05E,0xBF59E3},{0x1844C908,0x1B44A798,0x3A0B1E7,0xD1B5B4E,0x1836046F,0x87E94F9,0x1D34C537,0xF7183B0,0x46D07},{0x17813331,0x19E28A90,0x1473A4D6,0x1CACD01F,0x1EEA8838,0xAF2AE29,0x1F85292A,0x1632585E,0xD945E5},{0x919F5EF,0x1567B39F,0x19F6AD11,0x16CE47CF,0x9B36EB1,0x35B7D3,0x483B28C,0xCBEFA27,0xB5FC21}};
+
+int main()
+{
+	int i;
+	BIG p[4],e[4],x[4],r[4];
+	csprng rng;
+	char raw[100];
+	for (i=0;i<100;i++) raw[i]=i;
+    RAND_seed(&rng,100,raw);
+
+
+	FF_init(x,3,4);
+
+	FF_copy(p,P,4);
+	FF_copy(e,p,4);
+	FF_dec(e,1,4);
+	FF_norm(e,4);
+
+
+
+	printf("p= ");FF_output(p,4); printf("\n");
+	if (FF_prime(p,&rng,4)) printf("p is a prime\n");
+	printf("e= ");FF_output(e,4); printf("\n");
+
+	FF_skpow(r,x,e,p,4);
+	printf("r= ");FF_output(r,4); printf("\n");
+}
+
+*/
diff --git a/version3/cpp/ff.h b/version3/cpp/ff.h
new file mode 100644
index 0000000..5f3c856
--- /dev/null
+++ b/version3/cpp/ff.h
@@ -0,0 +1,276 @@
+#ifndef FF_WWW_H
+#define FF_WWW_H
+
+#include "big_XXX.h"
+#include "config_ff_WWW.h"
+
+using namespace amcl;
+
+#define HFLEN_WWW (FFLEN_WWW/2) /**< Useful for half-size RSA private key operations */
+#define P_MBITS_WWW (MODBYTES_XXX*8)
+#define P_TBITS_WWW (P_MBITS_WWW%BASEBITS_XXX)
+#define P_EXCESS_WWW(a) (((a[NLEN_XXX-1])>>(P_TBITS_WWW))+1)
+#define P_FEXCESS_WWW ((chunk)1<<(BASEBITS_XXX*NLEN_XXX-P_MBITS_WWW-1))
+
+
+namespace WWW {
+
+/* Finite Field Prototypes */
+/**	@brief Copy one FF element of given length to another
+ *
+	@param x FF instance to be copied to, on exit = y
+	@param y FF instance to be copied from
+	@param n size of FF in BIGs
+
+ */
+extern void FF_copy(XXX::BIG *x,XXX::BIG *y,int n);
+/**	@brief Initialize an FF element of given length from a 32-bit integer m
+ *
+	@param x FF instance to be copied to, on exit = m
+	@param m integer
+	@param n size of FF in BIGs
+ */
+extern void FF_init(XXX::BIG *x,sign32 m,int n);
+/**	@brief Set FF element of given size to zero
+ *
+	@param x FF instance to be set to zero
+	@param n size of FF in BIGs
+ */
+extern void FF_zero(XXX::BIG *x,int n);
+/**	@brief Tests for FF element equal to zero
+ *
+	@param x FF number to be tested
+	@param n size of FF in BIGs
+	@return 1 if zero, else returns 0
+ */
+extern int FF_iszilch(XXX::BIG *x,int n);
+/**	@brief  return parity of an FF, that is the least significant bit
+ *
+	@param x FF number
+	@return 0 or 1
+ */
+extern int FF_parity(XXX::BIG *x);
+/**	@brief  return least significant m bits of an FF
+ *
+	@param x FF number
+	@param m number of bits to return. Assumed to be less than BASEBITS.
+	@return least significant n bits as an integer
+ */
+extern int FF_lastbits(XXX::BIG *x,int m);
+/**	@brief Set FF element of given size to unity
+ *
+	@param x FF instance to be set to unity
+	@param n size of FF in BIGs
+ */
+extern void FF_one(XXX::BIG *x,int n);
+/**	@brief Compares two FF numbers. Inputs must be normalised externally
+ *
+	@param x first FF number to be compared
+	@param y second FF number to be compared
+	@param n size of FF in BIGs
+	@return -1 is x<y, 0 if x=y, 1 if x>y
+ */
+extern int FF_comp(XXX::BIG *x,XXX::BIG *y,int n);
+/**	@brief addition of two FFs
+ *
+	@param x FF instance, on exit = y+z
+	@param y FF instance
+	@param z FF instance
+	@param n size of FF in BIGs
+ */
+extern void FF_add(XXX::BIG *x,XXX::BIG *y,XXX::BIG *z,int n);
+/**	@brief subtraction of two FFs
+ *
+	@param x FF instance, on exit = y-z
+	@param y FF instance
+	@param z FF instance
+	@param n size of FF in BIGs
+ */
+extern void FF_sub(XXX::BIG *x,XXX::BIG *y,XXX::BIG *z,int n);
+/**	@brief increment an FF by an integer,and normalise
+ *
+	@param x FF instance, on exit = x+m
+	@param m an integer to be added to x
+	@param n size of FF in BIGs
+ */
+extern void FF_inc(XXX::BIG *x,int m,int n);
+/**	@brief Decrement an FF by an integer,and normalise
+ *
+	@param x FF instance, on exit = x-m
+	@param m an integer to be subtracted from x
+	@param n size of FF in BIGs
+ */
+extern void FF_dec(XXX::BIG *x,int m,int n);
+/**	@brief Normalises the components of an FF
+ *
+	@param x FF instance to be normalised
+	@param n size of FF in BIGs
+ */
+extern void FF_norm(XXX::BIG *x,int n);
+/**	@brief Shift left an FF by 1 bit
+ *
+	@param x FF instance to be shifted left
+	@param n size of FF in BIGs
+ */
+extern void FF_shl(XXX::BIG *x,int n);
+/**	@brief Shift right an FF by 1 bit
+ *
+	@param x FF instance to be shifted right
+	@param n size of FF in BIGs
+ */
+extern void FF_shr(XXX::BIG *x,int n);
+/**	@brief Formats and outputs an FF to the console
+ *
+	@param x FF instance to be printed
+	@param n size of FF in BIGs
+ */
+extern void FF_output(XXX::BIG *x,int n);
+/**	@brief Formats and outputs an FF to the console, in raw form
+ *
+ 	@param x FF instance to be printed
+ 	@param n size of FF in BIGs
+ */
+extern void FF_rawoutput(XXX::BIG *x,int n);
+/**	@brief Formats and outputs an FF instance to an octet string
+ *
+	Converts an FF to big-endian base 256 form.
+	@param S output octet string
+	@param x FF instance to be converted to an octet string
+	@param n size of FF in BIGs
+ */
+extern void FF_toOctet(octet *S,XXX::BIG *x,int n);
+/**	@brief Populates an FF instance from an octet string
+ *
+	Creates FF from big-endian base 256 form.
+	@param x FF instance to be created from an octet string
+	@param S input octet string
+	@param n size of FF in BIGs
+ */
+extern void FF_fromOctet(XXX::BIG *x,octet *S,int n);
+/**	@brief Multiplication of two FFs
+ *
+	Uses Karatsuba method internally
+	@param x FF instance, on exit = y*z
+	@param y FF instance
+	@param z FF instance
+	@param n size of FF in BIGs
+ */
+extern void FF_mul(XXX::BIG *x,XXX::BIG *y,XXX::BIG *z,int n);
+/**	@brief Reduce FF mod a modulus
+ *
+	This is slow
+	@param x FF instance to be reduced mod m - on exit = x mod m
+	@param m FF modulus
+	@param n size of FF in BIGs
+ */
+extern void FF_mod(XXX::BIG *x,XXX::BIG *m,int n);
+/**	@brief Square an FF
+ *
+	Uses Karatsuba method internally
+	@param x FF instance, on exit = y^2
+	@param y FF instance to be squared
+	@param n size of FF in BIGs
+ */
+extern void FF_sqr(XXX::BIG *x,XXX::BIG *y,int n);
+/**	@brief Reduces a double-length FF with respect to a given modulus
+ *
+	This is slow
+	@param x FF instance, on exit = y mod z
+	@param y FF instance, of double length 2*n
+	@param z FF modulus
+	@param n size of FF in BIGs
+ */
+extern void FF_dmod(XXX::BIG *x,XXX::BIG *y,XXX::BIG *z,int n);
+/**	@brief Invert an FF mod a prime modulus
+ *
+	@param x FF instance, on exit = 1/y mod z
+	@param y FF instance
+	@param z FF prime modulus
+	@param n size of FF in BIGs
+ */
+extern void FF_invmodp(XXX::BIG *x,XXX::BIG *y,XXX::BIG *z,int n);
+/**	@brief Create an FF from a random number generator
+ *
+	@param x FF instance, on exit x is a random number of length n BIGs with most significant bit a 1
+	@param R an instance of a Cryptographically Secure Random Number Generator
+	@param n size of FF in BIGs
+ */
+extern void FF_random(XXX::BIG *x,csprng *R,int n);
+/**	@brief Create a random FF less than a given modulus from a random number generator
+ *
+	@param x FF instance, on exit x is a random number < y
+	@param y FF instance, the modulus
+	@param R an instance of a Cryptographically Secure Random Number Generator
+	@param n size of FF in BIGs
+ */
+extern void FF_randomnum(XXX::BIG *x,XXX::BIG *y,csprng *R,int n);
+/**	@brief Calculate r=x^e mod m, side channel resistant
+ *
+	@param r FF instance, on exit = x^e mod p
+	@param x FF instance
+	@param e FF exponent
+	@param m FF modulus
+	@param n size of FF in BIGs
+ */
+extern void FF_skpow(XXX::BIG *r,XXX::BIG *x,XXX::BIG * e,XXX::BIG *m,int n);
+/**	@brief Calculate r=x^e mod m, side channel resistant
+ *
+	For short BIG exponent
+	@param r FF instance, on exit = x^e mod p
+	@param x FF instance
+	@param e BIG exponent
+	@param m FF modulus
+	@param n size of FF in BIGs
+ */
+extern void FF_skspow(XXX::BIG *r,XXX::BIG *x,XXX::BIG e,XXX::BIG *m,int n);
+/**	@brief Calculate r=x^e mod m
+ *
+	For very short integer exponent
+	@param r FF instance, on exit = x^e mod p
+	@param x FF instance
+	@param e integer exponent
+	@param m FF modulus
+	@param n size of FF in BIGs
+ */
+extern void FF_power(XXX::BIG *r,XXX::BIG *x,int e,XXX::BIG *m,int n);
+/**	@brief Calculate r=x^e mod m
+ *
+	@param r FF instance, on exit = x^e mod p
+	@param x FF instance
+	@param e FF exponent
+	@param m FF modulus
+	@param n size of FF in BIGs
+ */
+extern void FF_pow(XXX::BIG *r,XXX::BIG *x,XXX::BIG *e,XXX::BIG *m,int n);
+/**	@brief Test if an FF has factor in common with integer s
+ *
+	@param x FF instance to be tested
+	@param s the supplied integer
+	@param n size of FF in BIGs
+	@return 1 if gcd(x,s)!=1, else return 0
+ */
+extern int FF_cfactor(XXX::BIG *x,sign32 s,int n);
+/**	@brief Test if an FF is prime
+ *
+	Uses Miller-Rabin Method
+	@param x FF instance to be tested
+	@param R an instance of a Cryptographically Secure Random Number Generator
+	@param n size of FF in BIGs
+	@return 1 if x is (almost certainly) prime, else return 0
+ */
+extern int FF_prime(XXX::BIG *x,csprng *R,int n);
+/**	@brief Calculate r=x^e.y^f mod m
+ *
+	@param r FF instance, on exit = x^e.y^f mod p
+	@param x FF instance
+	@param e BIG exponent
+	@param y FF instance
+	@param f BIG exponent
+	@param m FF modulus
+	@param n size of FF in BIGs
+ */
+extern void FF_pow2(XXX::BIG *r,XXX::BIG *x,XXX::BIG e,XXX::BIG *y,XXX::BIG f,XXX::BIG *m,int n);
+
+}
+
+#endif
diff --git a/version3/cpp/fp.cpp b/version3/cpp/fp.cpp
new file mode 100644
index 0000000..11a70fe
--- /dev/null
+++ b/version3/cpp/fp.cpp
@@ -0,0 +1,878 @@
+/*
+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.
+*/
+
+/* AMCL mod p functions */
+/* Small Finite Field arithmetic */
+/* SU=m, SU is Stack Usage (NOT_SPECIAL Modulus) */
+
+#include "fp_YYY.h"
+
+using namespace XXX;
+
+/* Fast Modular Reduction Methods */
+
+/* r=d mod m */
+/* d MUST be normalised */
+/* Products must be less than pR in all cases !!! */
+/* So when multiplying two numbers, their product *must* be less than MODBITS_YYY+BASEBITS_XXX*NLEN_XXX */
+/* Results *may* be one bit bigger than MODBITS_YYY */
+
+#if MODTYPE_YYY == PSEUDO_MERSENNE
+/* r=d mod m */
+
+/* Converts from BIG integer to residue form mod Modulus */
+void YYY::FP_nres(FP *y,BIG x)
+{
+	BIG_copy(y->g,x);
+	y->XES=1;
+}
+
+/* Converts from residue form back to BIG integer form */
+void YYY::FP_redc(BIG x,FP *y)
+{
+	BIG_copy(x,y->g);
+}
+
+/* reduce a DBIG to a BIG exploiting the special form of the modulus */
+void YYY::FP_mod(BIG r,DBIG d)
+{
+    BIG t,b;
+    chunk v,tw;
+    BIG_split(t,b,d,MODBITS_YYY);
+
+    /* Note that all of the excess gets pushed into t. So if squaring a value with a 4-bit excess, this results in
+       t getting all 8 bits of the excess product! So products must be less than pR which is Montgomery compatible */
+
+    if (MConst < NEXCESS_XXX)
+    {
+        BIG_imul(t,t,MConst);
+        BIG_norm(t);
+		BIG_add(r,t,b);
+		BIG_norm(r);
+        tw=r[NLEN_XXX-1];
+        r[NLEN_XXX-1]&=TMASK_YYY;
+        r[0]+=MConst*((tw>>TBITS_YYY));
+    }
+    else
+    {
+        v=BIG_pmul(t,t,MConst);
+		BIG_add(r,t,b);
+		BIG_norm(r);
+        tw=r[NLEN_XXX-1];
+        r[NLEN_XXX-1]&=TMASK_YYY;
+#if CHUNK == 16
+        r[1]+=muladd(MConst,((tw>>TBITS_YYY)+(v<<(BASEBITS_XXX-TBITS_YYY))),0,&r[0]);
+#else
+        r[0]+=MConst*((tw>>TBITS_YYY)+(v<<(BASEBITS_XXX-TBITS_YYY)));
+#endif
+    }
+    BIG_norm(r);
+}
+#endif
+
+/* This only applies to Curve C448, so specialised (for now) */
+#if MODTYPE_YYY == GENERALISED_MERSENNE
+
+void YYY::FP_nres(FP *y,BIG x)
+{
+	BIG_copy(y->g,x);
+	y->XES=1;
+}
+
+/* Converts from residue form back to BIG integer form */
+void YYY::FP_redc(BIG x,FP *y)
+{
+	BIG_copy(x,y->g);
+}
+
+/* reduce a DBIG to a BIG exploiting the special form of the modulus */
+void YYY::FP_mod(BIG r,DBIG d)
+{
+    BIG t,b,t2,b2;
+    chunk carry;
+    BIG_split(t,b,d,MBITS_YYY);
+
+    //BIG_add(r,t,b);
+
+    BIG_dscopy(d,t);
+    BIG_dshl(d,BTset);
+
+    BIG_split(t2,b2,d,MBITS_YYY);
+
+	BIG_add(b,b,b2);
+	BIG_add(t,t,t2);
+
+    //BIG_add(r,r,t2);
+    //BIG_add(r,r,b2);
+	//BIG_add(r,t,b);
+    //BIG_norm(r);
+    BIG_shl(t2,BTset);
+
+	BIG_add(b,b,t2);
+    BIG_norm(b);
+
+// Now multiply t by MConst..(?) 
+
+	BIG_add(r,t,b);
+    BIG_norm(r);
+    //BIG_add(r,r,t2);
+
+    carry=r[NLEN_XXX-1]>>TBITS_YYY;
+
+    r[NLEN_XXX-1]&=TMASK_YYY;
+    r[0]+=carry;
+
+    r[BTset/BASEBITS_XXX]+=carry<<(BTset%BASEBITS_XXX); /* need to check that this falls mid-word */
+    BIG_norm(r);
+}
+
+#endif
+
+#if MODTYPE_YYY == MONTGOMERY_FRIENDLY
+
+/* convert to Montgomery n-residue form */
+void YYY::FP_nres(FP *y,BIG x)
+{
+    DBIG d;
+    BIG r;
+    BIG_rcopy(r,R2modp);
+	BIG_mul(d,x,r);
+	FP_mod(y->g,d);
+	y->XES=2;
+}
+
+/* convert back to regular form */
+void YYY::FP_redc(BIG x,FP *y)
+{
+    DBIG d;
+    BIG_dzero(d);
+    BIG_dscopy(d,y->g);
+    FP_mod(x,d);
+}
+
+/* fast modular reduction from DBIG to BIG exploiting special form of the modulus */
+void YYY::FP_mod(BIG a,DBIG d)
+{
+    int i;
+
+    for (i=0; i<NLEN_XXX; i++)
+        d[NLEN_XXX+i]+=muladd(d[i],MConst-1,d[i],&d[NLEN_XXX+i-1]);
+
+    BIG_sducopy(a,d);
+    BIG_norm(a);
+}
+
+#endif
+
+#if MODTYPE_YYY == NOT_SPECIAL
+
+/* convert to Montgomery n-residue form */
+void YYY::FP_nres(FP *y,BIG x)
+{
+    DBIG d;
+    BIG r;
+    BIG_rcopy(r,R2modp);
+	BIG_mul(d,x,r);
+	FP_mod(y->g,d);
+	y->XES=2;
+}
+
+/* convert back to regular form */
+void YYY::FP_redc(BIG x,FP *y)
+{
+    DBIG d;
+    BIG_dzero(d);
+    BIG_dscopy(d,y->g);
+    FP_mod(x,d);
+}
+
+
+/* reduce a DBIG to a BIG using Montgomery's no trial division method */
+/* d is expected to be dnormed before entry */
+/* SU= 112 */
+void YYY::FP_mod(BIG a,DBIG d)
+{
+	BIG mdls;
+	BIG_rcopy(mdls,Modulus);
+	BIG_monty(a,mdls,MConst,d);
+}
+
+#endif
+
+/* test x==0 ? */
+/* SU= 48 */
+int YYY::FP_iszilch(FP *x)
+{
+    BIG m,t;
+    BIG_rcopy(m,Modulus);
+	BIG_copy(t,x->g);
+    BIG_mod(t,m);
+    return BIG_iszilch(t);
+}
+
+void YYY::FP_copy(FP *y,FP *x)
+{
+	BIG_copy(y->g,x->g);
+	y->XES=x->XES;
+}
+
+void YYY::FP_rcopy(FP *y, const BIG c)
+{
+	BIG b;
+	BIG_rcopy(b,c);
+	FP_nres(y,b);
+}
+
+/* Swap a and b if d=1 */
+void YYY::FP_cswap(FP *a,FP *b,int d)
+{
+	sign32 t,c=d;
+	BIG_cswap(a->g,b->g,d);
+
+    c=~(c-1);
+	t=c&((a->XES)^(b->XES));
+	a->XES^=t;
+	b->XES^=t;
+
+}
+
+/* Move b to a if d=1 */
+void YYY::FP_cmove(FP *a,FP *b,int d)
+{
+	sign32 c=-d;
+
+	BIG_cmove(a->g,b->g,d);
+	a->XES^=(a->XES^b->XES)&c;
+}
+
+void YYY::FP_zero(FP *x)
+{
+	BIG_zero(x->g);
+	x->XES=1;
+}
+
+int YYY::FP_equals(FP *x,FP *y)
+{
+//	int i;
+//	chunk res=0;
+	FP xg,yg;
+	FP_copy(&xg,x);
+	FP_copy(&yg,y);
+	FP_reduce(&xg); FP_reduce(&yg);
+
+//	for (i=0;i<NLEN_XXX;i++)
+//	{
+//		res |= xg.g[i]^yg.g[i];
+//	}
+//	return res;
+
+	if (BIG_comp(xg.g,yg.g)==0) return 1;
+	return 0;
+}
+
+/* output FP */
+/* SU= 48 */
+void YYY::FP_output(FP *r)
+{
+    BIG c;
+    FP_redc(c,r);
+    BIG_output(c);
+}
+
+void YYY::FP_rawoutput(FP *r)
+{
+    BIG_rawoutput(r->g);
+}
+
+#ifdef GET_STATS
+int tsqr=0,rsqr=0,tmul=0,rmul=0;
+int tadd=0,radd=0,tneg=0,rneg=0;
+int tdadd=0,rdadd=0,tdneg=0,rdneg=0;
+#endif
+
+#ifdef FUSED_MODMUL
+
+/* Insert fastest code here */
+
+#endif
+
+/* r=a*b mod Modulus */
+/* product must be less that p.R - and we need to know this in advance! */
+/* SU= 88 */
+void YYY::FP_mul(FP *r,FP *a,FP *b)
+{
+    DBIG d;
+    chunk ea,eb;
+//    BIG_norm(a);
+//    BIG_norm(b);
+//    ea=EXCESS(a->g);
+//    eb=EXCESS(b->g);
+
+
+	if ((sign64)a->XES*b->XES>(sign64)FEXCESS_YYY)
+	{
+#ifdef DEBUG_REDUCE
+        printf("Product too large - reducing it\n");
+#endif
+        FP_reduce(a);  /* it is sufficient to fully reduce just one of them < p */
+	}
+
+#ifdef FUSED_MODMUL
+	FP_modmul(r->g,a->g,b->g);
+#else
+    BIG_mul(d,a->g,b->g);
+    FP_mod(r->g,d);
+#endif
+	r->XES=2;
+}
+
+
+/* multiplication by an integer, r=a*c */
+/* SU= 136 */
+void YYY::FP_imul(FP *r,FP *a,int c)
+{
+    DBIG d;
+	BIG k;
+	FP f;
+ 
+    int s=0;
+   
+    if (c<0)
+    {
+        c=-c;
+        s=1;
+    }
+   
+#if MODTYPE_YYY==PSEUDO_MERSENNE || MODTYPE_YYY==GENERALISED_MERSENNE
+	
+	BIG_pxmul(d,a->g,c);
+	FP_mod(r->g,d);
+	r->XES=2;
+
+#else
+	//Montgomery
+	if (a->XES*c<=FEXCESS_YYY)
+	{
+		BIG_pmul(r->g,a->g,c);
+		r->XES=a->XES*c;    // careful here - XES jumps!
+	}
+	else
+	{// don't want to do this - only a problem for Montgomery modulus and larger constants
+		BIG_zero(k);
+		BIG_inc(k,c);
+		BIG_norm(k);
+		FP_nres(&f,k);
+		FP_mul(r,a,&f);
+	}
+#endif
+/*
+    if (c<=NEXCESS_XXX && a->XES*c <= FEXCESS_YYY)
+	{
+        BIG_imul(r->g,a->g,c);
+		r->XES=a->XES*c;
+		FP_norm(r);
+	}
+    else
+    {
+            BIG_pxmul(d,a->g,c);
+
+            BIG_rcopy(m,Modulus);
+			BIG_dmod(r->g,d,m);
+            //FP_mod(r->g,d);                /// BIG problem here! Too slow for PM, How to do fast for Monty?
+			r->XES=2;
+    }
+*/
+    if (s) 
+	{
+		FP_neg(r,r);
+		FP_norm(r);
+	}
+}
+
+/* Set r=a^2 mod m */
+/* SU= 88 */
+void YYY::FP_sqr(FP *r,FP *a)
+{
+    DBIG d;
+//    chunk ea;
+//    BIG_norm(a);
+//    ea=EXCESS(a->g);
+
+
+	if ((sign64)a->XES*a->XES>(sign64)FEXCESS_YYY)
+	{
+#ifdef DEBUG_REDUCE
+        printf("Product too large - reducing it\n");
+#endif
+        FP_reduce(a);
+    }
+
+    BIG_sqr(d,a->g);
+    FP_mod(r->g,d);
+	r->XES=2;
+}
+
+/* SU= 16 */
+/* Set r=a+b */
+void YYY::FP_add(FP *r,FP *a,FP *b)
+{
+    BIG_add(r->g,a->g,b->g);
+	r->XES=a->XES+b->XES;
+	if (r->XES>FEXCESS_YYY)
+	{
+#ifdef DEBUG_REDUCE
+        printf("Sum too large - reducing it \n");
+#endif
+        FP_reduce(r);
+    }
+}
+
+/* Set r=a-b mod m */
+/* SU= 56 */
+void YYY::FP_sub(FP *r,FP *a,FP *b)
+{
+    FP n;
+//	BIG_norm(b);
+    FP_neg(&n,b);
+//	BIG_norm(n);
+    FP_add(r,a,&n);
+}
+
+// https://graphics.stanford.edu/~seander/bithacks.html
+// constant time log to base 2 (or number of bits in)
+
+static int logb2(unsign32 v)
+{
+    int r;
+    v |= v >> 1;
+    v |= v >> 2;
+    v |= v >> 4;
+    v |= v >> 8;
+    v |= v >> 16;
+
+    v = v - ((v >> 1) & 0x55555555);
+    v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
+    r = (((v + (v >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24;
+    return r;
+}
+
+// find appoximation to quotient of a/m
+// Out by at most 2.
+// Note that MAXXES is bounded to be 2-bits less than half a word
+static int quo(BIG n,BIG m)
+{
+	int sh;
+	chunk num,den;
+	int hb=CHUNK/2;
+	if (TBITS_YYY<hb)
+	{
+		sh=hb-TBITS_YYY;
+		num=(n[NLEN_XXX-1]<<sh)|(n[NLEN_XXX-2]>>(BASEBITS_XXX-sh));
+		den=(m[NLEN_XXX-1]<<sh)|(m[NLEN_XXX-2]>>(BASEBITS_XXX-sh));
+	}
+	else
+	{
+		num=n[NLEN_XXX-1];
+		den=m[NLEN_XXX-1];
+	}
+	return (int)(num/(den+1));
+}
+
+/* SU= 48 */
+/* Fully reduce a mod Modulus */
+void YYY::FP_reduce(FP *a)
+{
+    BIG m,r;
+	int sr,sb,q;
+	chunk carry;
+
+    BIG_rcopy(m,Modulus);
+	BIG_norm(a->g);
+
+	if (a->XES>16)
+	{
+		q=quo(a->g,m);
+		carry=BIG_pmul(r,m,q);
+		r[NLEN_XXX-1]+=(carry<<BASEBITS_XXX); // correction - put any carry out back in again
+		BIG_sub(a->g,a->g,r);
+		BIG_norm(a->g);
+		sb=2;
+	}
+	else sb=logb2(a->XES-1);  // sb does not depend on the actual data
+
+	BIG_fshl(m,sb);
+	while (sb>0)
+	{
+// constant time...
+		sr=BIG_ssn(r,a->g,m);  // optimized combined shift, subtract and norm
+		BIG_cmove(a->g,r,1-sr);
+		sb--;
+	}
+/*
+    BIG_rcopy(m,Modulus);
+	if (BIG_comp(a->g,m)>0)
+	{
+		printf("NOT fully reduced q=%x %x %x %x\n",q,quo(a->g,m),FEXCESS_YYY,a->XES);
+		exit(0);
+	}
+*/
+	a->XES=1;
+}
+
+void YYY::FP_norm(FP *x)
+{
+	BIG_norm(x->g);
+}
+
+/* Set r=-a mod Modulus */
+/* SU= 64 */
+void YYY::FP_neg(FP *r,FP *a)
+{
+    int sb;
+    BIG m;
+
+    BIG_rcopy(m,Modulus);
+
+    sb=logb2(a->XES-1);
+    BIG_fshl(m,sb);
+    BIG_sub(r->g,m,a->g);
+	r->XES=((sign32)1<<sb)+1;  // +1 to cover case where a is zero ?
+
+    if (r->XES>FEXCESS_YYY)
+    {
+#ifdef DEBUG_REDUCE
+        printf("Negation too large -  reducing it \n");
+#endif
+        FP_reduce(r);
+	}
+
+}
+
+/* Set r=a/2. */
+/* SU= 56 */
+void YYY::FP_div2(FP *r,FP *a)
+{
+    BIG m;
+    BIG_rcopy(m,Modulus);
+    FP_copy(r,a);
+//    BIG_norm(a);
+    if (BIG_parity(a->g)==0)
+    {
+
+        BIG_fshr(r->g,1);
+    }
+    else
+    {
+        BIG_add(r->g,r->g,m);
+        BIG_norm(r->g);
+        BIG_fshr(r->g,1);
+    }
+}
+
+#if MODTYPE_YYY == PSEUDO_MERSENNE
+
+// See eprint paper "On inversion modulo pseudo-Mersenne primes"
+// If p=3 mod 4 r= x^{(p-3)/4}, if p=5 mod 8 r=x^{(p-5)/8}
+
+void YYY::FP_fpow(FP *r,FP *x)
+{
+	int i,j,k,bw,w,nw,lo,m,n,c;
+	FP xp[11],t,key;
+	const int ac[]={1,2,3,6,12,15,30,60,120,240,255};
+// phase 1
+	FP_copy(&xp[0],x);	// 1 
+	FP_sqr(&xp[1],x); // 2
+	FP_mul(&xp[2],&xp[1],x);  //3
+	FP_sqr(&xp[3],&xp[2]);  // 6 
+	FP_sqr(&xp[4],&xp[3]); // 12
+	FP_mul(&xp[5],&xp[4],&xp[2]); // 15
+	FP_sqr(&xp[6],&xp[5]); // 30
+	FP_sqr(&xp[7],&xp[6]); // 60
+	FP_sqr(&xp[8],&xp[7]); // 120
+	FP_sqr(&xp[9],&xp[8]); // 240
+	FP_mul(&xp[10],&xp[9],&xp[5]); // 255
+
+    if (MOD8_YYY==5)
+    {
+		n=MODBITS_YYY-3;
+		c=(MConst+5)/8;
+	} else {
+		n=MODBITS_YYY-2;
+		c=(MConst+3)/4;
+	}
+
+
+	bw=0; w=1; while (w<c) {w*=2; bw+=1;}
+	k=w-c;
+
+	if (k!=0)
+	{
+		i=10; while (ac[i]>k) i--;
+		FP_copy(&key,&xp[i]); 
+		k-=ac[i];
+	}
+	while (k!=0)
+	{
+		i--;
+		if (ac[i]>k) continue;
+		FP_mul(&key,&key,&xp[i]);
+		k-=ac[i]; 
+	}
+
+// phase 2 
+	FP_copy(&xp[1],&xp[2]);
+	FP_copy(&xp[2],&xp[5]);
+	FP_copy(&xp[3],&xp[10]);
+
+	j=3; m=8;
+	nw=n-bw;
+	while (2*m<nw)
+	{
+		FP_copy(&t,&xp[j++]);
+		for (i=0;i<m;i++)
+			FP_sqr(&t,&t); 
+		FP_mul(&xp[j],&xp[j-1],&t); 
+		m*=2;
+	}
+
+	lo=nw-m;
+	FP_copy(r,&xp[j]);
+
+	while (lo!=0)
+	{
+		m/=2; j--;
+		if (lo<m) continue;
+		lo-=m;
+		FP_copy(&t,r);
+		for (i=0;i<m;i++)
+			FP_sqr(&t,&t);
+		FP_mul(r,&t,&xp[j]);
+	}
+// phase 3
+
+	for (i=0;i<bw;i++ )
+		FP_sqr(r,r);
+	if (w-c!=0)
+		FP_mul(r,r,&key); 
+}
+
+void YYY::FP_inv(FP *r,FP *x)
+{
+	FP y,t;
+	FP_fpow(&y,x);
+    if (MOD8_YYY==5)
+    { // r=x^3.y^8
+		FP_sqr(&t,x);
+		FP_mul(&t,&t,x);
+		FP_sqr(&y,&y);
+		FP_sqr(&y,&y);
+		FP_sqr(&y,&y);
+		FP_mul(r,&t,&y);
+	} else {
+		FP_sqr(&y,&y);
+		FP_sqr(&y,&y);
+		FP_mul(r,&y,x);
+	}
+}
+
+#else
+
+void YYY::FP_pow(FP *r,FP *a,BIG b)
+{
+	sign8 w[1+(NLEN_XXX*BASEBITS_XXX+3)/4];
+	FP tb[16];
+	BIG t;
+	int i,nb;
+
+	FP_norm(a);
+    BIG_norm(b);
+	BIG_copy(t,b);
+	nb=1+(BIG_nbits(t)+3)/4;
+    // convert exponent to 4-bit window 
+    for (i=0; i<nb; i++)
+    {
+        w[i]=BIG_lastbits(t,4);
+        BIG_dec(t,w[i]);
+        BIG_norm(t);
+        BIG_fshr(t,4);
+    }	
+
+	FP_one(&tb[0]);
+	FP_copy(&tb[1],a);
+	for (i=2;i<16;i++)
+		FP_mul(&tb[i],&tb[i-1],a);
+	
+	FP_copy(r,&tb[w[nb-1]]);
+    for (i=nb-2; i>=0; i--)
+    {
+		FP_sqr(r,r);
+		FP_sqr(r,r);
+		FP_sqr(r,r);
+		FP_sqr(r,r);
+		FP_mul(r,r,&tb[w[i]]);
+	}
+    FP_reduce(r);
+}
+
+/* set w=1/x */
+void YYY::FP_inv(FP *w,FP *x)
+{
+ 	BIG m2;
+	BIG_rcopy(m2,Modulus);
+	BIG_dec(m2,2);
+	BIG_norm(m2);
+	FP_pow(w,x,m2);
+}
+
+#endif
+
+/* SU=8 */
+/* set n=1 */
+void YYY::FP_one(FP *n)
+{
+	BIG b;
+    BIG_one(b);
+    FP_nres(n,b);
+}
+
+
+
+/* is r a QR? */
+int YYY::FP_qr(FP *r)
+{
+    int j;
+    BIG m;
+	BIG b;
+    BIG_rcopy(m,Modulus);
+    FP_redc(b,r);
+    j=BIG_jacobi(b,m);
+    FP_nres(r,b);
+    if (j==1) return 1;
+    return 0;
+
+}
+
+/* Set a=sqrt(b) mod Modulus */
+/* SU= 160 */
+void YYY::FP_sqrt(FP *r,FP *a)
+{
+	FP v,i;
+    BIG b;
+    BIG m;
+    BIG_rcopy(m,Modulus);
+    BIG_mod(a->g,m);
+    BIG_copy(b,m);
+    if (MOD8_YYY==5)
+    {
+        FP_copy(&i,a);
+        BIG_fshl(i.g,1);
+#if MODTYPE_YYY == PSEUDO_MERSENNE
+		FP_fpow(&v,&i);
+#else
+        BIG_dec(b,5);
+        BIG_norm(b);
+        BIG_fshr(b,3); /* (p-5)/8 */
+        FP_pow(&v,&i,b);
+#endif
+        FP_mul(&i,&i,&v);
+        FP_mul(&i,&i,&v);
+        BIG_dec(i.g,1);
+        FP_mul(r,a,&v);
+        FP_mul(r,r,&i);
+        FP_reduce(r);
+    }
+    if (MOD8_YYY==3 || MOD8_YYY==7)
+    {
+#if MODTYPE_YYY == PSEUDO_MERSENNE
+		FP_fpow(r,a);
+		FP_mul(r,r,a);
+#else
+        BIG_inc(b,1);
+        BIG_norm(b);
+        BIG_fshr(b,2); /* (p+1)/4 */
+        FP_pow(r,a,b);
+#endif
+    }
+}
+
+/*
+int main()
+{
+
+	BIG r;
+
+	FP_one(r);
+	FP_sqr(r,r);
+
+	BIG_output(r);
+
+	int i,carry;
+	DBIG c={0,0,0,0,0,0,0,0};
+	BIG a={1,2,3,4};
+	BIG b={3,4,5,6};
+	BIG r={11,12,13,14};
+	BIG s={23,24,25,15};
+	BIG w;
+
+//	printf("NEXCESS_XXX= %d\n",NEXCESS_XXX);
+//	printf("MConst= %d\n",MConst);
+
+	BIG_copy(b,Modulus);
+	BIG_dec(b,1);
+	BIG_norm(b);
+
+	BIG_randomnum(r); BIG_norm(r); BIG_mod(r,Modulus);
+//	BIG_randomnum(s); norm(s); BIG_mod(s,Modulus);
+
+//	BIG_output(r);
+//	BIG_output(s);
+
+	BIG_output(r);
+	FP_nres(r);
+	BIG_output(r);
+	BIG_copy(a,r);
+	FP_redc(r);
+	BIG_output(r);
+	BIG_dscopy(c,a);
+	FP_mod(r,c);
+	BIG_output(r);
+
+
+//	exit(0);
+
+//	copy(r,a);
+	printf("r=   "); BIG_output(r);
+	BIG_modsqr(r,r,Modulus);
+	printf("r^2= "); BIG_output(r);
+
+	FP_nres(r);
+	FP_sqrt(r,r);
+	FP_redc(r);
+	printf("r=   "); BIG_output(r);
+	BIG_modsqr(r,r,Modulus);
+	printf("r^2= "); BIG_output(r);
+
+
+//	for (i=0;i<100000;i++) FP_sqr(r,r);
+//	for (i=0;i<100000;i++)
+		FP_sqrt(r,r);
+
+	BIG_output(r);
+}
+*/
diff --git a/version3/cpp/fp.h b/version3/cpp/fp.h
new file mode 100644
index 0000000..9a22b0b
--- /dev/null
+++ b/version3/cpp/fp.h
@@ -0,0 +1,229 @@
+#ifndef FP_YYY_H
+#define FP_YYY_H
+
+#include "big_XXX.h"
+#include "config_field_YYY.h"
+
+using namespace amcl;
+
+#define MODBITS_YYY MBITS_YYY
+#define TBITS_YYY (MBITS_YYY%BASEBITS_XXX)                    /**< Number of active bits in top word */
+#define TMASK_YYY (((chunk)1<<TBITS_YYY)-1)               /**< Mask for active bits in top word */
+#define FEXCESS_YYY (((sign32)1<<MAXXES_YYY)-1)				/**< 2^(BASEBITS*NLEN-MODBITS) - normalised BIG can be multiplied by less than this before reduction */
+#define OMASK_YYY (-((chunk)(1)<<TBITS_YYY))              /**<  for masking out overflow bits */
+
+namespace YYY {
+
+/**
+	@brief FP Structure - quadratic extension field
+*/
+
+typedef struct
+{
+    XXX::BIG g;	/**< Big representation of field element */
+    sign32 XES;	/**< Excess */
+} FP;
+
+/* Field Params - see rom.c */
+extern const XXX::BIG Modulus;	/**< Actual Modulus set in romf.c */
+extern const XXX::BIG R2modp;	/**< Montgomery constant */
+extern const chunk MConst;		/**< Constant associated with Modulus - for Montgomery = 1/p mod 2^BASEBITS */
+extern const int BTset;			/**< Set Bit in Generalised Mersenne */
+extern const XXX::BIG Fra; /**< real part of BN curve Frobenius Constant */
+extern const XXX::BIG Frb; /**< imaginary part of BN curve Frobenius Constant */
+
+//#define FUSED_MODMUL
+//#define DEBUG_REDUCE
+
+/* FP prototypes */
+
+/**	@brief Tests for FP equal to zero mod Modulus
+ *
+	@param x BIG number to be tested
+	@return 1 if zero, else returns 0
+ */
+extern int FP_iszilch(FP *x);
+
+
+/**	@brief Set FP to zero
+ *
+	@param x FP number to be set to 0
+ */
+extern void FP_zero(FP *x);
+
+/**	@brief Copy an FP
+ *
+	@param y FP number to be copied to
+	@param x FP to be copied from
+ */
+extern void FP_copy(FP *y,FP *x);
+
+/**	@brief Copy from ROM to an FP
+ *
+	@param y FP number to be copied to
+	@param x BIG to be copied from ROM
+ */
+extern void FP_rcopy(FP *y,const XXX::BIG x);
+
+
+/**	@brief Compares two FPs
+ *
+	@param x FP number
+	@param y FP number
+	@return 1 if equal, else returns 0
+ */
+extern int FP_equals(FP *x,FP *y);
+
+
+/**	@brief Conditional constant time swap of two FP numbers
+ *
+	Conditionally swaps parameters in constant time (without branching)
+	@param x an FP number
+	@param y another FP number
+	@param s swap takes place if not equal to 0
+ */
+extern void FP_cswap(FP *x,FP *y,int s);
+/**	@brief Conditional copy of FP number
+ *
+	Conditionally copies second parameter to the first (without branching)
+	@param x an FP number
+	@param y another FP number
+	@param s copy takes place if not equal to 0
+ */
+extern void FP_cmove(FP *x,FP *y,int s);
+/**	@brief Converts from BIG integer to residue form mod Modulus
+ *
+	@param x BIG number to be converted
+	@param y FP result
+ */
+extern void FP_nres(FP *y,XXX::BIG x);
+/**	@brief Converts from residue form back to BIG integer form
+ *
+	@param y FP number to be converted to BIG
+	@param x BIG result
+ */
+extern void FP_redc(XXX::BIG x,FP *y);
+/**	@brief Sets FP to representation of unity in residue form
+ *
+	@param x FP number to be set equal to unity.
+ */
+extern void FP_one(FP *x);
+/**	@brief Reduces DBIG to BIG exploiting special form of the modulus
+ *
+	This function comes in different flavours depending on the form of Modulus that is currently in use.
+	@param r BIG number, on exit = d mod Modulus
+	@param d DBIG number to be reduced
+ */
+extern void FP_mod(XXX::BIG r,XXX::DBIG d);
+
+#ifdef FUSED_MODMUL
+extern void FP_modmul(XXX::BIG,XXX::BIG,XXX::BIG);
+#endif
+
+/**	@brief Fast Modular multiplication of two FPs, mod Modulus
+ *
+	Uses appropriate fast modular reduction method
+	@param x FP number, on exit the modular product = y*z mod Modulus
+	@param y FP number, the multiplicand
+	@param z FP number, the multiplier
+ */
+extern void FP_mul(FP *x,FP *y,FP *z);
+/**	@brief Fast Modular multiplication of an FP, by a small integer, mod Modulus
+ *
+	@param x FP number, on exit the modular product = y*i mod Modulus
+	@param y FP number, the multiplicand
+	@param i a small number, the multiplier
+ */
+extern void FP_imul(FP *x,FP *y,int i);
+/**	@brief Fast Modular squaring of an FP, mod Modulus
+ *
+	Uses appropriate fast modular reduction method
+	@param x FP number, on exit the modular product = y^2 mod Modulus
+	@param y FP number, the number to be squared
+
+ */
+extern void FP_sqr(FP *x,FP *y);
+/**	@brief Modular addition of two FPs, mod Modulus
+ *
+	@param x FP number, on exit the modular sum = y+z mod Modulus
+	@param y FP number
+	@param z FP number
+ */
+extern void FP_add(FP *x,FP *y,FP *z);
+/**	@brief Modular subtraction of two FPs, mod Modulus
+ *
+	@param x FP number, on exit the modular difference = y-z mod Modulus
+	@param y FP number
+	@param z FP number
+ */
+extern void FP_sub(FP *x,FP *y,FP *z);
+/**	@brief Modular division by 2 of an FP, mod Modulus
+ *
+	@param x FP number, on exit =y/2 mod Modulus
+	@param y FP number
+ */
+extern void FP_div2(FP *x,FP *y);
+/**	@brief Fast Modular exponentiation of an FP, to the power of a BIG, mod Modulus
+ *
+	@param x FP number, on exit  = y^z mod Modulus
+	@param y FP number
+	@param z BIG number exponent
+ */
+extern void FP_pow(FP *x,FP *y,XXX::BIG z);
+/**	@brief Fast Modular square root of a an FP, mod Modulus
+ *
+	@param x FP number, on exit  = sqrt(y) mod Modulus
+	@param y FP number, the number whose square root is calculated
+
+ */
+extern void FP_sqrt(FP *x,FP *y);
+/**	@brief Modular negation of a an FP, mod Modulus
+ *
+	@param x FP number, on exit = -y mod Modulus
+	@param y FP number
+ */
+extern void FP_neg(FP *x,FP *y);
+/**	@brief Outputs an FP number to the console
+ *
+	Converts from residue form before output
+	@param x an FP number
+ */
+extern void FP_output(FP *x);
+/**	@brief Outputs an FP number to the console, in raw form
+ *
+	@param x a BIG number
+ */
+extern void FP_rawoutput(FP *x);
+/**	@brief Reduces possibly unreduced FP mod Modulus
+ *
+	@param x FP number, on exit reduced mod Modulus
+ */
+extern void FP_reduce(FP *x);
+/**	@brief normalizes FP
+ *
+	@param x FP number, on exit normalized
+ */
+extern void FP_norm(FP *x);
+/**	@brief Tests for FP a quadratic residue mod Modulus
+ *
+	@param x FP number to be tested
+	@return 1 if quadratic residue, else returns 0 if quadratic non-residue
+ */
+extern int FP_qr(FP *x);
+/**	@brief Modular inverse of a an FP, mod Modulus
+ *
+	@param x FP number, on exit = 1/y mod Modulus
+	@param y FP number
+ */
+extern void FP_inv(FP *x,FP *y);
+
+/**	@brief Special exponent of an FP, mod Modulus
+ *
+	@param x FP number, on exit = x^s mod Modulus
+	@param y FP number
+ */
+extern void FP_fpow(FP *x,FP *y);
+
+}
+
+#endif
diff --git a/version3/cpp/fp12.cpp b/version3/cpp/fp12.cpp
new file mode 100644
index 0000000..005c4a8
--- /dev/null
+++ b/version3/cpp/fp12.cpp
@@ -0,0 +1,1005 @@
+/*
+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.
+*/
+
+/* AMCL Fp^12 functions */
+/* SU=m, m is Stack Usage (no lazy )*/
+/* FP12 elements are of the form a+i.b+i^2.c */
+
+#include "fp12_YYY.h"
+
+using namespace XXX;
+
+/* return 1 if b==c, no branching */
+static int teq(sign32 b,sign32 c)
+{
+    sign32 x=b^c;
+    x-=1;  // if x=0, x now -1
+    return (int)((x>>31)&1);
+}
+
+
+/* Constant time select from pre-computed table */
+static void FP12_select(YYY::FP12 *f,YYY::FP12 g[],sign32 b)
+{
+    YYY::FP12 invf;
+    sign32 m=b>>31;
+    sign32 babs=(b^m)-m;
+
+    babs=(babs-1)/2;
+
+    FP12_cmove(f,&g[0],teq(babs,0));  // conditional move
+    FP12_cmove(f,&g[1],teq(babs,1));
+    FP12_cmove(f,&g[2],teq(babs,2));
+    FP12_cmove(f,&g[3],teq(babs,3));
+    FP12_cmove(f,&g[4],teq(babs,4));
+    FP12_cmove(f,&g[5],teq(babs,5));
+    FP12_cmove(f,&g[6],teq(babs,6));
+    FP12_cmove(f,&g[7],teq(babs,7));
+
+    FP12_copy(&invf,f);
+    FP12_conj(&invf,&invf);  // 1/f
+    FP12_cmove(f,&invf,(int)(m&1));
+}
+
+/* test x==0 ? */
+/* SU= 8 */
+int YYY::FP12_iszilch(FP12 *x)
+{
+    if (FP4_iszilch(&(x->a)) && FP4_iszilch(&(x->b)) && FP4_iszilch(&(x->c))) return 1;
+    return 0;
+}
+
+/* test x==1 ? */
+/* SU= 8 */
+int YYY::FP12_isunity(FP12 *x)
+{
+    if (FP4_isunity(&(x->a)) && FP4_iszilch(&(x->b)) && FP4_iszilch(&(x->c))) return 1;
+    return 0;
+}
+
+/* FP12 copy w=x */
+/* SU= 16 */
+void YYY::FP12_copy(FP12 *w,FP12 *x)
+{
+    if (x==w) return;
+    FP4_copy(&(w->a),&(x->a));
+    FP4_copy(&(w->b),&(x->b));
+    FP4_copy(&(w->c),&(x->c));
+}
+
+/* FP12 w=1 */
+/* SU= 8 */
+void YYY::FP12_one(FP12 *w)
+{
+    FP4_one(&(w->a));
+    FP4_zero(&(w->b));
+    FP4_zero(&(w->c));
+}
+
+/* return 1 if x==y, else 0 */
+/* SU= 16 */
+int YYY::FP12_equals(FP12 *x,FP12 *y)
+{
+    if (FP4_equals(&(x->a),&(y->a)) && FP4_equals(&(x->b),&(y->b)) && FP4_equals(&(x->b),&(y->b)))
+        return 1;
+    return 0;
+}
+
+/* Set w=conj(x) */
+/* SU= 8 */
+void YYY::FP12_conj(FP12 *w,FP12 *x)
+{
+    FP12_copy(w,x);
+    FP4_conj(&(w->a),&(w->a));
+    FP4_nconj(&(w->b),&(w->b));
+    FP4_conj(&(w->c),&(w->c));
+}
+
+/* Create FP12 from FP4 */
+/* SU= 8 */
+void YYY::FP12_from_FP4(FP12 *w,FP4 *a)
+{
+    FP4_copy(&(w->a),a);
+    FP4_zero(&(w->b));
+    FP4_zero(&(w->c));
+}
+
+/* Create FP12 from 3 FP4's */
+/* SU= 16 */
+void YYY::FP12_from_FP4s(FP12 *w,FP4 *a,FP4 *b,FP4 *c)
+{
+    FP4_copy(&(w->a),a);
+    FP4_copy(&(w->b),b);
+    FP4_copy(&(w->c),c);
+}
+
+/* Granger-Scott Unitary Squaring. This does not benefit from lazy reduction */
+/* SU= 600 */
+void YYY::FP12_usqr(FP12 *w,FP12 *x)
+{
+    FP4 A,B,C,D;
+
+    FP4_copy(&A,&(x->a));   
+
+    FP4_sqr(&(w->a),&(x->a));  // Wa XES=2
+    FP4_add(&D,&(w->a),&(w->a)); // Wa XES=4
+    FP4_add(&(w->a),&D,&(w->a)); // Wa XES=6
+
+    FP4_norm(&(w->a));
+    FP4_nconj(&A,&A);
+
+    FP4_add(&A,&A,&A);
+    FP4_add(&(w->a),&(w->a),&A); // Wa XES=8
+    FP4_sqr(&B,&(x->c));
+    FP4_times_i(&B);
+
+    FP4_add(&D,&B,&B);
+    FP4_add(&B,&B,&D);
+    FP4_norm(&B);
+
+    FP4_sqr(&C,&(x->b));
+
+    FP4_add(&D,&C,&C);
+    FP4_add(&C,&C,&D);
+
+    FP4_norm(&C);
+    FP4_conj(&(w->b),&(x->b));
+    FP4_add(&(w->b),&(w->b),&(w->b));
+    FP4_nconj(&(w->c),&(x->c));
+
+    FP4_add(&(w->c),&(w->c),&(w->c));
+    FP4_add(&(w->b),&B,&(w->b));
+    FP4_add(&(w->c),&C,&(w->c));
+/*
+	FP n;
+	FP_one(&n);
+	FP4_qmul(&(w->a),&(w->a),&n);
+	FP4_qmul(&(w->b),&(w->b),&n);
+	FP4_qmul(&(w->c),&(w->c),&n);
+*/
+
+	//FP12_norm(w);
+    FP12_reduce(w);	    /* reduce here as in pow function repeated squarings would trigger multiple reductions */
+}
+
+/* FP12 squaring w=x^2 */
+/* SU= 600 */
+void YYY::FP12_sqr(FP12 *w,FP12 *x)
+{
+    /* Use Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
+
+    FP4 A,B,C,D;
+
+    FP4_sqr(&A,&(x->a));
+    FP4_mul(&B,&(x->b),&(x->c));
+    FP4_add(&B,&B,&B);
+FP4_norm(&B);
+    FP4_sqr(&C,&(x->c));
+
+    FP4_mul(&D,&(x->a),&(x->b));
+    FP4_add(&D,&D,&D);
+    FP4_add(&(w->c),&(x->a),&(x->c));
+    FP4_add(&(w->c),&(x->b),&(w->c));
+FP4_norm(&(w->c));	
+
+    FP4_sqr(&(w->c),&(w->c));
+
+    FP4_copy(&(w->a),&A);
+    FP4_add(&A,&A,&B);
+
+    FP4_norm(&A);
+
+    FP4_add(&A,&A,&C);
+    FP4_add(&A,&A,&D);
+
+    FP4_norm(&A);
+    FP4_neg(&A,&A);
+    FP4_times_i(&B);
+    FP4_times_i(&C);
+
+    FP4_add(&(w->a),&(w->a),&B);
+    FP4_add(&(w->b),&C,&D);
+    FP4_add(&(w->c),&(w->c),&A);
+
+    FP12_norm(w);
+}
+
+/* FP12 full multiplication w=w*y */
+
+
+/* SU= 896 */
+/* FP12 full multiplication w=w*y */
+void YYY::FP12_mul(FP12 *w,FP12 *y)
+{
+    FP4 z0,z1,z2,z3,t0,t1;
+
+    FP4_mul(&z0,&(w->a),&(y->a));
+    FP4_mul(&z2,&(w->b),&(y->b));  //
+
+    FP4_add(&t0,&(w->a),&(w->b));
+    FP4_add(&t1,&(y->a),&(y->b));  //
+
+FP4_norm(&t0);
+FP4_norm(&t1);
+
+    FP4_mul(&z1,&t0,&t1);
+    FP4_add(&t0,&(w->b),&(w->c));
+    FP4_add(&t1,&(y->b),&(y->c));  //
+
+FP4_norm(&t0);
+FP4_norm(&t1);
+
+    FP4_mul(&z3,&t0,&t1);
+
+    FP4_neg(&t0,&z0);
+    FP4_neg(&t1,&z2);
+
+    FP4_add(&z1,&z1,&t0);   // z1=z1-z0
+//    FP4_norm(&z1);
+    FP4_add(&(w->b),&z1,&t1);
+// z1=z1-z2
+    FP4_add(&z3,&z3,&t1);        // z3=z3-z2
+    FP4_add(&z2,&z2,&t0);        // z2=z2-z0
+
+    FP4_add(&t0,&(w->a),&(w->c));
+    FP4_add(&t1,&(y->a),&(y->c));
+
+FP4_norm(&t0);
+FP4_norm(&t1);
+
+    FP4_mul(&t0,&t1,&t0);
+    FP4_add(&z2,&z2,&t0);
+
+    FP4_mul(&t0,&(w->c),&(y->c));
+    FP4_neg(&t1,&t0);
+
+    FP4_add(&(w->c),&z2,&t1);
+    FP4_add(&z3,&z3,&t1);
+    FP4_times_i(&t0);
+    FP4_add(&(w->b),&(w->b),&t0);
+FP4_norm(&z3);
+    FP4_times_i(&z3);
+    FP4_add(&(w->a),&z0,&z3);
+
+    FP12_norm(w);
+}
+
+/* FP12 multiplication w=w*y */
+/* SU= 744 */
+/* catering for special case that arises from special form of ATE pairing line function */
+void YYY::FP12_smul(FP12 *w,FP12 *y,int type)
+{
+    FP4 z0,z1,z2,z3,t0,t1;
+
+	if (type==D_TYPE)
+	{ // y->c is 0
+
+		FP4_copy(&z3,&(w->b));
+		FP4_mul(&z0,&(w->a),&(y->a));
+
+		FP4_pmul(&z2,&(w->b),&(y->b).a);
+		FP4_add(&(w->b),&(w->a),&(w->b));
+		FP4_copy(&t1,&(y->a));
+		FP2_add(&t1.a,&t1.a,&(y->b).a);
+
+		FP4_norm(&t1);
+		FP4_norm(&(w->b));
+
+		FP4_mul(&(w->b),&(w->b),&t1);
+		FP4_add(&z3,&z3,&(w->c));
+		FP4_norm(&z3);
+		FP4_pmul(&z3,&z3,&(y->b).a);
+		FP4_neg(&t0,&z0);
+		FP4_neg(&t1,&z2);
+
+		FP4_add(&(w->b),&(w->b),&t0);   // z1=z1-z0
+//    FP4_norm(&(w->b));
+		FP4_add(&(w->b),&(w->b),&t1);   // z1=z1-z2
+
+		FP4_add(&z3,&z3,&t1);        // z3=z3-z2
+		FP4_add(&z2,&z2,&t0);        // z2=z2-z0
+
+		FP4_add(&t0,&(w->a),&(w->c));
+
+		FP4_norm(&t0);
+		FP4_norm(&z3);
+
+		FP4_mul(&t0,&(y->a),&t0);
+		FP4_add(&(w->c),&z2,&t0);
+
+		FP4_times_i(&z3);
+		FP4_add(&(w->a),&z0,&z3);
+	}
+
+	if (type==M_TYPE)
+	{ // y->b is zero
+		FP4_mul(&z0,&(w->a),&(y->a));
+		FP4_add(&t0,&(w->a),&(w->b));
+		FP4_norm(&t0);
+
+		FP4_mul(&z1,&t0,&(y->a));
+		FP4_add(&t0,&(w->b),&(w->c));
+		FP4_norm(&t0);
+
+		FP4_pmul(&z3,&t0,&(y->c).b);
+		FP4_times_i(&z3);
+
+		FP4_neg(&t0,&z0);
+		FP4_add(&z1,&z1,&t0);   // z1=z1-z0
+
+		FP4_copy(&(w->b),&z1);
+
+		FP4_copy(&z2,&t0);
+
+		FP4_add(&t0,&(w->a),&(w->c));
+		FP4_add(&t1,&(y->a),&(y->c));
+
+		FP4_norm(&t0);
+		FP4_norm(&t1);
+
+		FP4_mul(&t0,&t1,&t0);
+		FP4_add(&z2,&z2,&t0);
+
+		FP4_pmul(&t0,&(w->c),&(y->c).b);
+		FP4_times_i(&t0);
+		FP4_neg(&t1,&t0);
+		FP4_times_i(&t0);
+
+		FP4_add(&(w->c),&z2,&t1);
+		FP4_add(&z3,&z3,&t1);
+
+		FP4_add(&(w->b),&(w->b),&t0);
+		FP4_norm(&z3);
+		FP4_times_i(&z3);
+		FP4_add(&(w->a),&z0,&z3);
+	}
+    FP12_norm(w);
+}
+
+/* Set w=1/x */
+/* SU= 600 */
+void YYY::FP12_inv(FP12 *w,FP12 *x)
+{
+    FP4 f0,f1,f2,f3;
+//    FP12_norm(x);
+
+    FP4_sqr(&f0,&(x->a));
+    FP4_mul(&f1,&(x->b),&(x->c));
+    FP4_times_i(&f1);
+    FP4_sub(&f0,&f0,&f1);  /* y.a */
+	FP4_norm(&f0); 		
+
+    FP4_sqr(&f1,&(x->c));
+    FP4_times_i(&f1);
+    FP4_mul(&f2,&(x->a),&(x->b));
+    FP4_sub(&f1,&f1,&f2);  /* y.b */
+	FP4_norm(&f1); 
+
+    FP4_sqr(&f2,&(x->b));
+    FP4_mul(&f3,&(x->a),&(x->c));
+    FP4_sub(&f2,&f2,&f3);  /* y.c */
+	FP4_norm(&f2); 
+
+    FP4_mul(&f3,&(x->b),&f2);
+    FP4_times_i(&f3);
+    FP4_mul(&(w->a),&f0,&(x->a));
+    FP4_add(&f3,&(w->a),&f3);
+    FP4_mul(&(w->c),&f1,&(x->c));
+    FP4_times_i(&(w->c));
+
+    FP4_add(&f3,&(w->c),&f3);
+	FP4_norm(&f3);
+	
+    FP4_inv(&f3,&f3);
+
+    FP4_mul(&(w->a),&f0,&f3);
+    FP4_mul(&(w->b),&f1,&f3);
+    FP4_mul(&(w->c),&f2,&f3);
+
+}
+
+/* constant time powering by small integer of max length bts */
+
+void YYY::FP12_pinpow(FP12 *r,int e,int bts)
+{
+    int i,b;
+    FP12 R[2];
+
+    FP12_one(&R[0]);
+    FP12_copy(&R[1],r);
+
+    for (i=bts-1; i>=0; i--)
+    {
+        b=(e>>i)&1;
+        FP12_mul(&R[1-b],&R[b]);
+        FP12_usqr(&R[b],&R[b]);
+    }
+    FP12_copy(r,&R[0]);
+}
+
+/* Compressed powering of unitary elements y=x^(e mod r) */
+
+void YYY::FP12_compow(FP4 *c,FP12 *x,BIG e,BIG r)
+{
+    FP12 g1,g2;
+	FP4 cp,cpm1,cpm2;
+    FP2 f;
+	BIG q,a,b,m;
+
+    BIG_rcopy(a,Fra);
+    BIG_rcopy(b,Frb);
+    FP2_from_BIGs(&f,a,b);
+
+    BIG_rcopy(q,Modulus);
+
+    FP12_copy(&g1,x);
+	FP12_copy(&g2,x);
+
+    BIG_copy(m,q);
+    BIG_mod(m,r);
+
+    BIG_copy(a,e);
+    BIG_mod(a,m);
+
+    BIG_copy(b,e);
+    BIG_sdiv(b,m);
+
+    FP12_trace(c,&g1);
+
+	if (BIG_iszilch(b))
+	{
+		FP4_xtr_pow(c,c,e);
+		return;
+	}
+
+    FP12_frob(&g2,&f);
+    FP12_trace(&cp,&g2);
+
+    FP12_conj(&g1,&g1);
+    FP12_mul(&g2,&g1);
+    FP12_trace(&cpm1,&g2);
+    FP12_mul(&g2,&g1);
+    FP12_trace(&cpm2,&g2);
+
+    FP4_xtr_pow2(c,&cp,c,&cpm1,&cpm2,a,b);
+
+}
+
+/* Note this is simple square and multiply, so not side-channel safe */
+/* But fast for final exponentiation where exponent is not a secret */
+
+void YYY::FP12_pow(FP12 *r,FP12 *a,BIG b)
+{
+    FP12 w,sf;
+    BIG b1,b3;
+    int i,nb,bt;
+	BIG_copy(b1,b);
+	BIG_norm(b1);
+    //BIG_norm(b);
+	BIG_pmul(b3,b1,3);
+	BIG_norm(b3);
+	FP12_copy(&sf,a);
+	FP12_norm(&sf);
+    FP12_copy(&w,&sf);
+
+	nb=BIG_nbits(b3);
+	for (i=nb-2;i>=1;i--)
+	{
+		FP12_usqr(&w,&w);
+		bt=BIG_bit(b3,i)-BIG_bit(b1,i);
+		if (bt==1)
+			FP12_mul(&w,&sf);
+		if (bt==-1)
+		{
+			FP12_conj(&sf,&sf);
+			FP12_mul(&w,&sf);
+			FP12_conj(&sf,&sf);
+		}
+	}
+
+	FP12_copy(r,&w);
+	FP12_reduce(r);
+
+
+}
+
+
+/* SU= 528 */
+/* set r=a^b */
+/* Note this is simple square and multiply, so not side-channel safe
+
+void YYY::FP12_pow(FP12 *r,FP12 *a,BIG b)
+{
+    FP12 w;
+    BIG z,zilch;
+    int bt;
+    BIG_zero(zilch);
+    BIG_norm(b);
+    BIG_copy(z,b);
+    FP12_copy(&w,a);
+    FP12_one(r);
+
+    while(1)
+    {
+        bt=BIG_parity(z);
+        BIG_shr(z,1);
+        if (bt)
+            FP12_mul(r,&w);
+        if (BIG_comp(z,zilch)==0) break;
+        FP12_usqr(&w,&w);
+    }
+
+    FP12_reduce(r);
+}  */
+
+
+/* p=q0^u0.q1^u1.q2^u2.q3^u3 */
+/* Side channel attack secure */
+// Bos & Costello https://eprint.iacr.org/2013/458.pdf
+// Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
+
+void YYY::FP12_pow4(FP12 *p,FP12 *q,BIG u[4])
+{
+    int i,j,k,nb,pb,bt;
+	FP12 g[8],r;
+	BIG t[4],mt;
+    sign8 w[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 s[NLEN_XXX*BASEBITS_XXX+1];
+
+    for (i=0; i<4; i++)
+        BIG_copy(t[i],u[i]);
+
+
+// Precomputed table
+    FP12_copy(&g[0],&q[0]); // q[0]
+    FP12_copy(&g[1],&g[0]);
+	FP12_mul(&g[1],&q[1]);	// q[0].q[1]
+    FP12_copy(&g[2],&g[0]);
+	FP12_mul(&g[2],&q[2]);	// q[0].q[2]
+	FP12_copy(&g[3],&g[1]);
+	FP12_mul(&g[3],&q[2]);	// q[0].q[1].q[2]
+	FP12_copy(&g[4],&g[0]);
+	FP12_mul(&g[4],&q[3]);  // q[0].q[3]
+	FP12_copy(&g[5],&g[1]);
+	FP12_mul(&g[5],&q[3]);	// q[0].q[1].q[3]
+	FP12_copy(&g[6],&g[2]);
+	FP12_mul(&g[6],&q[3]);	// q[0].q[2].q[3]
+	FP12_copy(&g[7],&g[3]);
+	FP12_mul(&g[7],&q[3]);	// q[0].q[1].q[2].q[3]
+
+// Make it odd
+	pb=1-BIG_parity(t[0]);
+	BIG_inc(t[0],pb);
+	BIG_norm(t[0]);
+
+// Number of bits
+    BIG_zero(mt);
+    for (i=0; i<4; i++)
+    {
+        BIG_or(mt,mt,t[i]);
+    }
+    nb=1+BIG_nbits(mt);
+
+// Sign pivot 
+	s[nb-1]=1;
+	for (i=0;i<nb-1;i++)
+	{
+        BIG_fshr(t[0],1);
+		s[i]=2*BIG_parity(t[0])-1;
+	}
+
+// Recoded exponent
+    for (i=0; i<nb; i++)
+    {
+		w[i]=0;
+		k=1;
+		for (j=1; j<4; j++)
+		{
+			bt=s[i]*BIG_parity(t[j]);
+			BIG_fshr(t[j],1);
+
+			BIG_dec(t[j],(bt>>1));
+			BIG_norm(t[j]);
+			w[i]+=bt*k;
+			k*=2;
+        }
+    }		
+
+// Main loop
+	FP12_select(p,g,2*w[nb-1]+1);
+    for (i=nb-2; i>=0; i--)
+    {
+        FP12_select(&r,g,2*w[i]+s[i]);
+		FP12_usqr(p,p);
+        FP12_mul(p,&r);
+    }
+// apply correction
+	FP12_conj(&r,&q[0]);   
+	FP12_mul(&r,p);
+	FP12_cmove(p,&r,pb);
+
+	FP12_reduce(p);
+}
+
+/* p=q0^u0.q1^u1.q2^u2.q3^u3 */
+/* Side channel attack secure */
+/*
+void YYY::FP12_pow4(FP12 *p,FP12 *q,BIG u[4])
+{
+    int i,j,a[4],nb,m,pb;
+    FP12 g[8],c,r,v;
+    BIG t[4],mt;
+    sign8 w[NLEN_XXX*BASEBITS_XXX+1];
+
+    for (i=0; i<4; i++)
+        BIG_copy(t[i],u[i]);
+
+    FP12_copy(&g[0],&q[0]);
+    FP12_conj(&r,&q[1]);
+    FP12_mul(&g[0],&r);  // P/Q 
+    FP12_copy(&g[1],&g[0]);
+    FP12_copy(&g[2],&g[0]);
+    FP12_copy(&g[3],&g[0]);
+    FP12_copy(&g[4],&q[0]);
+    FP12_mul(&g[4],&q[1]);  // P*Q 
+    FP12_copy(&g[5],&g[4]);
+    FP12_copy(&g[6],&g[4]);
+    FP12_copy(&g[7],&g[4]);
+
+    FP12_copy(&v,&q[2]);
+    FP12_conj(&r,&q[3]);
+    FP12_mul(&v,&r);       // R/S 
+    FP12_conj(&r,&v);
+    FP12_mul(&g[1],&r);
+    FP12_mul(&g[2],&v);
+    FP12_mul(&g[5],&r);
+    FP12_mul(&g[6],&v);
+    FP12_copy(&v,&q[2]);
+    FP12_mul(&v,&q[3]);      // R*S 
+    FP12_conj(&r,&v);
+    FP12_mul(&g[0],&r);
+    FP12_mul(&g[3],&v);
+    FP12_mul(&g[4],&r);
+    FP12_mul(&g[7],&v);
+
+    // if power is even add 1 to power, and add q to correction 
+    FP12_one(&c);
+
+    BIG_zero(mt);
+    for (i=0; i<4; i++)
+    {
+
+		pb=BIG_parity(t[i]);
+		BIG_inc(t[i],1-pb);
+		BIG_norm(t[i]);
+		FP12_copy(&r,&c);
+		FP12_mul(&r,&q[i]);
+		FP12_cmove(&c,&r,1-pb);
+
+        BIG_add(mt,mt,t[i]);
+        BIG_norm(mt);
+    }
+
+    FP12_conj(&c,&c);
+    nb=1+BIG_nbits(mt);
+
+    // convert exponent to signed 1-bit window 
+    for (j=0; j<nb; j++)
+    {
+        for (i=0; i<4; i++)
+        {
+            a[i]=BIG_lastbits(t[i],2)-2;
+            BIG_dec(t[i],a[i]);
+            BIG_norm(t[i]);
+            BIG_fshr(t[i],1);
+        }
+        w[j]=8*a[0]+4*a[1]+2*a[2]+a[3];
+    }
+    w[nb]=8*BIG_lastbits(t[0],2)+4*BIG_lastbits(t[1],2)+2*BIG_lastbits(t[2],2)+BIG_lastbits(t[3],2);
+    FP12_copy(p,&g[(w[nb]-1)/2]);
+
+    for (i=nb-1; i>=0; i--)
+    {
+		FP12_select(&r,g,w[i]);
+		FP12_usqr(p,p);
+        FP12_mul(p,&r);
+    }
+    FP12_mul(p,&c); // apply correction 
+    FP12_reduce(p);
+}
+*/
+
+/* Set w=w^p using Frobenius */
+/* SU= 160 */
+void YYY::FP12_frob(FP12 *w,FP2 *f)
+{
+    FP2 f2,f3;
+    FP2_sqr(&f2,f);     /* f2=f^2 */
+    FP2_mul(&f3,&f2,f); /* f3=f^3 */
+
+    FP4_frob(&(w->a),&f3);
+    FP4_frob(&(w->b),&f3);
+    FP4_frob(&(w->c),&f3);
+
+    FP4_pmul(&(w->b),&(w->b),f);
+    FP4_pmul(&(w->c),&(w->c),&f2);
+}
+
+/* SU= 8 */
+/* normalise all components of w */
+void YYY::FP12_norm(FP12 *w)
+{
+    FP4_norm(&(w->a));
+    FP4_norm(&(w->b));
+    FP4_norm(&(w->c));
+}
+
+/* SU= 8 */
+/* reduce all components of w */
+void YYY::FP12_reduce(FP12 *w)
+{
+    FP4_reduce(&(w->a));
+    FP4_reduce(&(w->b));
+    FP4_reduce(&(w->c));
+}
+
+/* trace function w=trace(x) */
+/* SU= 8 */
+void YYY::FP12_trace(FP4 *w,FP12 *x)
+{
+    FP4_imul(w,&(x->a),3);
+    FP4_reduce(w);
+}
+
+/* SU= 8 */
+/* Output w in hex */
+void YYY::FP12_output(FP12 *w)
+{
+    printf("[");
+    FP4_output(&(w->a));
+    printf(",");
+    FP4_output(&(w->b));
+    printf(",");
+    FP4_output(&(w->c));
+    printf("]");
+}
+
+/* SU= 64 */
+/* Convert g to octet string w */
+void YYY::FP12_toOctet(octet *W,FP12 *g)
+{
+    BIG a;
+    W->len=12*MODBYTES_XXX;
+
+    FP_redc(a,&(g->a.a.a));
+    BIG_toBytes(&(W->val[0]),a);
+    FP_redc(a,&(g->a.a.b));
+    BIG_toBytes(&(W->val[MODBYTES_XXX]),a);
+    FP_redc(a,&(g->a.b.a));
+    BIG_toBytes(&(W->val[2*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->a.b.b));
+    BIG_toBytes(&(W->val[3*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->b.a.a));
+    BIG_toBytes(&(W->val[4*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->b.a.b));
+    BIG_toBytes(&(W->val[5*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->b.b.a));
+    BIG_toBytes(&(W->val[6*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->b.b.b));
+    BIG_toBytes(&(W->val[7*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->c.a.a));
+    BIG_toBytes(&(W->val[8*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->c.a.b));
+    BIG_toBytes(&(W->val[9*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->c.b.a));
+    BIG_toBytes(&(W->val[10*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->c.b.b));
+    BIG_toBytes(&(W->val[11*MODBYTES_XXX]),a);
+}
+
+/* SU= 24 */
+/* Restore g from octet string w */
+void YYY::FP12_fromOctet(FP12 *g,octet *W)
+{
+	BIG b;
+    BIG_fromBytes(b,&W->val[0]);
+    FP_nres(&(g->a.a.a),b);
+    BIG_fromBytes(b,&W->val[MODBYTES_XXX]);
+    FP_nres(&(g->a.a.b),b);
+    BIG_fromBytes(b,&W->val[2*MODBYTES_XXX]);
+    FP_nres(&(g->a.b.a),b);
+    BIG_fromBytes(b,&W->val[3*MODBYTES_XXX]);
+    FP_nres(&(g->a.b.b),b);
+    BIG_fromBytes(b,&W->val[4*MODBYTES_XXX]);
+    FP_nres(&(g->b.a.a),b);
+    BIG_fromBytes(b,&W->val[5*MODBYTES_XXX]);
+    FP_nres(&(g->b.a.b),b);
+    BIG_fromBytes(b,&W->val[6*MODBYTES_XXX]);
+    FP_nres(&(g->b.b.a),b);
+    BIG_fromBytes(b,&W->val[7*MODBYTES_XXX]);
+    FP_nres(&(g->b.b.b),b);
+    BIG_fromBytes(b,&W->val[8*MODBYTES_XXX]);
+    FP_nres(&(g->c.a.a),b);
+    BIG_fromBytes(b,&W->val[9*MODBYTES_XXX]);
+    FP_nres(&(g->c.a.b),b);
+    BIG_fromBytes(b,&W->val[10*MODBYTES_XXX]);
+    FP_nres(&(g->c.b.a),b);
+    BIG_fromBytes(b,&W->val[11*MODBYTES_XXX]);
+    FP_nres(&(g->c.b.b),b);
+}
+
+/* Move b to a if d=1 */
+void YYY::FP12_cmove(FP12 *f,FP12 *g,int d)
+{
+    FP4_cmove(&(f->a),&(g->a),d);
+    FP4_cmove(&(f->b),&(g->b),d);
+    FP4_cmove(&(f->c),&(g->c),d);
+}
+
+
+
+/*
+int main(){
+		FP2 f,w0,w1;
+		FP4 t0,t1,t2;
+		FP12 w,t,lv;
+		BIG a,b;
+		BIG p;
+
+		//Test w^(P^4) = w mod p^2
+//		BIG_randomnum(a);
+//		BIG_randomnum(b);
+//		BIG_mod(a,Modulus); BIG_mod(b,Modulus);
+	BIG_zero(a); BIG_zero(b); BIG_inc(a,1); BIG_inc(b,2); FP_nres(a); FP_nres(b);
+		FP2_from_zps(&w0,a,b);
+
+//		BIG_randomnum(a); BIG_randomnum(b);
+//		BIG_mod(a,Modulus); BIG_mod(b,Modulus);
+	BIG_zero(a); BIG_zero(b); BIG_inc(a,3); BIG_inc(b,4); FP_nres(a); FP_nres(b);
+		FP2_from_zps(&w1,a,b);
+
+		FP4_from_FP2s(&t0,&w0,&w1);
+		FP4_reduce(&t0);
+
+//		BIG_randomnum(a);
+//		BIG_randomnum(b);
+//		BIG_mod(a,Modulus); BIG_mod(b,Modulus);
+		BIG_zero(a); BIG_zero(b); BIG_inc(a,5); BIG_inc(b,6); FP_nres(a); FP_nres(b);
+		FP2_from_zps(&w0,a,b);
+
+//		BIG_randomnum(a); BIG_randomnum(b);
+//		BIG_mod(a,Modulus); BIG_mod(b,Modulus);
+
+		BIG_zero(a); BIG_zero(b); BIG_inc(a,7); BIG_inc(b,8); FP_nres(a); FP_nres(b);
+		FP2_from_zps(&w1,a,b);
+
+		FP4_from_FP2s(&t1,&w0,&w1);
+		FP4_reduce(&t1);
+
+//		BIG_randomnum(a);
+//		BIG_randomnum(b);
+//		BIG_mod(a,Modulus); BIG_mod(b,Modulus);
+		BIG_zero(a); BIG_zero(b); BIG_inc(a,9); BIG_inc(b,10); FP_nres(a); FP_nres(b);
+		FP2_from_zps(&w0,a,b);
+
+//		BIG_randomnum(a); BIG_randomnum(b);
+//		BIG_mod(a,Modulus); BIG_mod(b,Modulus);
+		BIG_zero(a); BIG_zero(b); BIG_inc(a,11); BIG_inc(b,12); FP_nres(a); FP_nres(b);
+		FP2_from_zps(&w1,a,b);
+
+		FP4_from_FP2s(&t2,&w0,&w1);
+		FP4_reduce(&t2);
+
+		FP12_from_FP4s(&w,&t0,&t1,&t2);
+
+		FP12_copy(&t,&w);
+
+		printf("w= ");
+		FP12_output(&w);
+		printf("\n");
+
+		BIG_rcopy(p,Modulus);
+		//BIG_zero(p); BIG_inc(p,7);
+
+		FP12_pow(&w,&w,p);
+
+		printf("w^p= ");
+		FP12_output(&w);
+		printf("\n");
+
+		FP2_gfc(&f,12);
+		FP12_frob(&t,&f);
+		printf("w^p= ");
+		FP12_output(&t);
+		printf("\n");
+
+//exit(0);
+
+		FP12_pow(&w,&w,p);
+		//printf("w^p^2= ");
+		//FP12_output(&w);
+		//printf("\n");
+		FP12_pow(&w,&w,p);
+		//printf("w^p^3= ");
+		//FP12_output(&w);
+		//printf("\n");
+		FP12_pow(&w,&w,p);
+		FP12_pow(&w,&w,p);
+		FP12_pow(&w,&w,p);
+		printf("w^p^6= ");
+		FP12_output(&w);
+		printf("\n");
+		FP12_pow(&w,&w,p);
+		FP12_pow(&w,&w,p);
+		printf("w^p^8= ");
+		FP12_output(&w);
+		printf("\n");
+		FP12_pow(&w,&w,p);
+		FP12_pow(&w,&w,p);
+		FP12_pow(&w,&w,p);
+		printf("w^p^11= ");
+		FP12_output(&w);
+		printf("\n");
+
+	//	BIG_zero(p); BIG_inc(p,7); BIG_norm(p);
+		FP12_pow(&w,&w,p);
+
+		printf("w^p12= ");
+		FP12_output(&w);
+		printf("\n");
+//exit(0);
+
+		FP12_inv(&t,&w);
+		printf("1/w mod p^4 = ");
+		FP12_output(&t);
+		printf("\n");
+
+		FP12_inv(&w,&t);
+		printf("1/(1/w) mod p^4 = ");
+		FP12_output(&w);
+		printf("\n");
+
+
+
+	FP12_inv(&lv,&w);
+//printf("w= "); FP12_output(&w); printf("\n");
+	FP12_conj(&w,&w);
+//printf("w= "); FP12_output(&w); printf("\n");
+//exit(0);
+	FP12_mul(&w,&w,&lv);
+//printf("w= "); FP12_output(&w); printf("\n");
+	FP12_copy(&lv,&w);
+	FP12_frob(&w,&f);
+	FP12_frob(&w,&f);
+	FP12_mul(&w,&w,&lv);
+
+//printf("w= "); FP12_output(&w); printf("\n");
+//exit(0);
+
+w.unitary=0;
+FP12_conj(&lv,&w);
+	printf("rx= "); FP12_output(&lv); printf("\n");
+FP12_inv(&lv,&w);
+	printf("ry= "); FP12_output(&lv); printf("\n");
+
+
+		return 0;
+}
+
+*/
diff --git a/version3/cpp/fp12.h b/version3/cpp/fp12.h
new file mode 100644
index 0000000..8157e8b
--- /dev/null
+++ b/version3/cpp/fp12.h
@@ -0,0 +1,194 @@
+#ifndef FP12_YYY_H
+#define FP12_YYY_H
+
+#include "fp4_YYY.h"
+
+using namespace amcl;
+
+namespace YYY {
+/**
+	@brief FP12 Structure - towered over three FP4
+*/
+
+typedef struct
+{
+    FP4 a; /**< first part of FP12 */
+    FP4 b; /**< second part of FP12 */
+    FP4 c; /**< third part of FP12 */
+} FP12;
+
+extern const XXX::BIG Fra; /**< real part of BN curve Frobenius Constant */
+extern const XXX::BIG Frb; /**< imaginary part of BN curve Frobenius Constant */
+
+/* FP12 prototypes */
+/**	@brief Tests for FP12 equal to zero
+ *
+	@param x FP12 number to be tested
+	@return 1 if zero, else returns 0
+ */
+extern int FP12_iszilch(FP12 *x);
+/**	@brief Tests for FP12 equal to unity
+ *
+	@param x FP12 number to be tested
+	@return 1 if unity, else returns 0
+ */
+extern int FP12_isunity(FP12 *x);
+/**	@brief Copy FP12 to another FP12
+ *
+	@param x FP12 instance, on exit = y
+	@param y FP12 instance to be copied
+ */
+extern void FP12_copy(FP12 *x,FP12 *y);
+/**	@brief Set FP12 to unity
+ *
+	@param x FP12 instance to be set to one
+ */
+extern void FP12_one(FP12 *x);
+/**	@brief Tests for equality of two FP12s
+ *
+	@param x FP12 instance to be compared
+	@param y FP12 instance to be compared
+	@return 1 if x=y, else returns 0
+ */
+extern int FP12_equals(FP12 *x,FP12 *y);
+/**	@brief Conjugation of FP12
+ *
+	If y=(a,b,c) (where a,b,c are its three FP4 components) on exit x=(conj(a),-conj(b),conj(c))
+	@param x FP12 instance, on exit = conj(y)
+	@param y FP12 instance
+ */
+extern void FP12_conj(FP12 *x,FP12 *y);
+/**	@brief Initialise FP12 from single FP4
+ *
+	Sets first FP4 component of an FP12, other components set to zero
+	@param x FP12 instance to be initialised
+	@param a FP4 to form first part of FP4
+ */
+extern void FP12_from_FP4(FP12 *x,FP4 *a);
+/**	@brief Initialise FP12 from three FP4s
+ *
+	@param x FP12 instance to be initialised
+	@param a FP4 to form first part of FP12
+	@param b FP4 to form second part of FP12
+	@param c FP4 to form third part of FP12
+ */
+extern void FP12_from_FP4s(FP12 *x,FP4 *a,FP4* b,FP4 *c);
+/**	@brief Fast Squaring of an FP12 in "unitary" form
+ *
+	@param x FP12 instance, on exit = y^2
+	@param y FP4 instance, must be unitary
+ */
+extern void FP12_usqr(FP12 *x,FP12 *y);
+/**	@brief Squaring an FP12
+ *
+	@param x FP12 instance, on exit = y^2
+	@param y FP12 instance
+ */
+extern void FP12_sqr(FP12 *x,FP12 *y);
+/**	@brief Fast multiplication of an FP12 by an FP12 that arises from an ATE pairing line function
+ *
+	Here the multiplier has a special form that can be exploited
+	@param x FP12 instance, on exit = x*y
+	@param y FP12 instance, of special form
+	@param t D_TYPE or M_TYPE twist
+ */
+extern void FP12_smul(FP12 *x,FP12 *y,int t);
+/**	@brief Multiplication of two FP12s
+ *
+	@param x FP12 instance, on exit = x*y
+	@param y FP12 instance, the multiplier
+ */
+extern void FP12_mul(FP12 *x,FP12 *y);
+/**	@brief Inverting an FP12
+ *
+	@param x FP12 instance, on exit = 1/y
+	@param y FP12 instance
+ */
+extern void FP12_inv(FP12 *x,FP12 *y);
+/**	@brief Raises an FP12 to the power of a BIG
+ *
+	@param r FP12 instance, on exit = y^b
+	@param x FP12 instance
+	@param b BIG number
+ */
+extern void FP12_pow(FP12 *r,FP12 *x,XXX::BIG b);
+/**	@brief Raises an FP12 instance x to a small integer power, side-channel resistant
+ *
+	@param x FP12 instance, on exit = x^i
+	@param i small integer exponent
+	@param b maximum number of bits in exponent
+ */
+extern void FP12_pinpow(FP12 *x,int i,int b);
+
+/**	@brief Raises an FP12 instance x to a BIG power, compressed to FP4 
+ *
+	@param c FP4 instance, on exit = x^(e mod r) as FP4
+	@param x FP12 input
+	@param e BIG exponent
+	@param r BIG group order
+ */
+extern void FP12_compow(FP4 *c,FP12 *x,XXX::BIG e,XXX::BIG r);
+
+/**	@brief Calculate x[0]^b[0].x[1]^b[1].x[2]^b[2].x[3]^b[3], side-channel resistant
+ *
+	@param r FP12 instance, on exit = x[0]^b[0].x[1]^b[1].x[2]^b[2].x[3]^b[3]
+	@param x FP12 array with 4 FP12s
+	@param b BIG array of 4 exponents
+ */
+extern void FP12_pow4(FP12 *r,FP12 *x,XXX::BIG *b);
+/**	@brief Raises an FP12 to the power of the internal modulus p, using the Frobenius
+ *
+	@param x FP12 instance, on exit = x^p
+	@param f FP2 precalculated Frobenius constant
+ */
+extern void FP12_frob(FP12 *x,FP2 *f);
+/**	@brief Reduces all components of possibly unreduced FP12 mod Modulus
+ *
+	@param x FP12 instance, on exit reduced mod Modulus
+ */
+extern void FP12_reduce(FP12 *x);
+/**	@brief Normalises the components of an FP12
+ *
+	@param x FP12 instance to be normalised
+ */
+extern void FP12_norm(FP12 *x);
+/**	@brief Formats and outputs an FP12 to the console
+ *
+	@param x FP12 instance to be printed
+ */
+extern void FP12_output(FP12 *x);
+/**	@brief Formats and outputs an FP12 instance to an octet string
+ *
+	Serializes the components of an FP12 to big-endian base 256 form.
+	@param S output octet string
+	@param x FP12 instance to be converted to an octet string
+ */
+extern void FP12_toOctet(octet *S,FP12 *x);
+/**	@brief Creates an FP12 instance from an octet string
+ *
+	De-serializes the components of an FP12 to create an FP12 from big-endian base 256 components.
+	@param x FP12 instance to be created from an octet string
+	@param S input octet string
+
+ */
+extern void FP12_fromOctet(FP12 *x,octet *S);
+/**	@brief Calculate the trace of an FP12
+ *
+	@param t FP4 trace of x, on exit = tr(x)
+	@param x FP12 instance
+
+ */
+extern void FP12_trace(FP4 *t,FP12 *x);
+
+/**	@brief Conditional copy of FP12 number
+ *
+	Conditionally copies second parameter to the first (without branching)
+	@param x FP12 instance, set to y if s!=0
+	@param y another FP12 instance
+	@param s copy only takes place if not equal to 0
+ */
+extern void FP12_cmove(FP12 *x,FP12 *y,int s);
+
+
+}
+#endif
diff --git a/version3/cpp/fp16.cpp b/version3/cpp/fp16.cpp
new file mode 100644
index 0000000..3f8f6c2
--- /dev/null
+++ b/version3/cpp/fp16.cpp
@@ -0,0 +1,697 @@
+/*
+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.
+*/
+
+/* AMCL Fp^8 functions */
+
+/* FP16 elements are of the form a+ib, where i is sqrt(sqrt(-1+sqrt(-1))) */
+
+#include "fp16_YYY.h"
+
+using namespace XXX;
+
+/* test x==0 ? */
+int YYY::FP16_iszilch(FP16 *x)
+{
+    if (FP8_iszilch(&(x->a)) && FP8_iszilch(&(x->b))) return 1;
+    return 0;
+}
+
+/* test x==1 ? */
+int YYY::FP16_isunity(FP16 *x)
+{
+    if (FP8_isunity(&(x->a)) && FP8_iszilch(&(x->b))) return 1;
+    return 0;
+}
+
+/* test is w real? That is in a+ib test b is zero */
+int YYY::FP16_isreal(FP16 *w)
+{
+    return FP8_iszilch(&(w->b));
+}
+
+/* return 1 if x==y, else 0 */
+int YYY::FP16_equals(FP16 *x,FP16 *y)
+{
+    if (FP8_equals(&(x->a),&(y->a)) && FP8_equals(&(x->b),&(y->b)))
+        return 1;
+    return 0;
+}
+
+/* set FP16 from two FP8s */
+void YYY::FP16_from_FP8s(FP16 *w,FP8 * x,FP8* y)
+{
+    FP8_copy(&(w->a), x);
+    FP8_copy(&(w->b), y);
+}
+
+/* set FP16 from FP8 */
+void YYY::FP16_from_FP8(FP16 *w,FP8 *x)
+{
+    FP8_copy(&(w->a), x);
+    FP8_zero(&(w->b));
+}
+
+/* set high part of FP16 from FP8 */
+void YYY::FP16_from_FP8H(FP16 *w,FP8 *x)
+{
+    FP8_copy(&(w->b), x);
+    FP8_zero(&(w->a));
+}
+
+/* FP16 copy w=x */
+void YYY::FP16_copy(FP16 *w,FP16 *x)
+{
+    if (w==x) return;
+    FP8_copy(&(w->a), &(x->a));
+    FP8_copy(&(w->b), &(x->b));
+}
+
+/* FP16 w=0 */
+void YYY::FP16_zero(FP16 *w)
+{
+    FP8_zero(&(w->a));
+    FP8_zero(&(w->b));
+}
+
+/* FP16 w=1 */
+void YYY::FP16_one(FP16 *w)
+{
+    FP8_one(&(w->a));
+    FP8_zero(&(w->b));
+}
+
+/* Set w=-x */
+void YYY::FP16_neg(FP16 *w,FP16 *x)
+{
+    /* Just one field neg */
+    FP8 m,t;
+	FP16_norm(x);
+    FP8_add(&m,&(x->a),&(x->b));
+	FP8_norm(&m);
+    FP8_neg(&m,&m);
+    FP8_add(&t,&m,&(x->b));
+    FP8_add(&(w->b),&m,&(x->a));
+    FP8_copy(&(w->a),&t);
+	FP16_norm(w);
+}
+
+/* Set w=conj(x) */
+void YYY::FP16_conj(FP16 *w,FP16 *x)
+{
+    FP8_copy(&(w->a), &(x->a));
+    FP8_neg(&(w->b), &(x->b));
+	FP16_norm(w);
+}
+
+/* Set w=-conj(x) */
+void YYY::FP16_nconj(FP16 *w,FP16 *x)
+{
+    FP8_copy(&(w->b),&(x->b));
+    FP8_neg(&(w->a), &(x->a));
+	FP16_norm(w);
+}
+
+/* Set w=x+y */
+void YYY::FP16_add(FP16 *w,FP16 *x,FP16 *y)
+{
+    FP8_add(&(w->a), &(x->a), &(y->a));
+    FP8_add(&(w->b), &(x->b), &(y->b));
+}
+
+/* Set w=x-y */
+/* Input y MUST be normed */
+void YYY::FP16_sub(FP16 *w,FP16 *x,FP16 *y)
+{
+    FP16 my;
+
+    FP16_neg(&my, y);
+    FP16_add(w, x, &my);
+
+}
+
+/* reduce all components of w mod Modulus */
+void YYY::FP16_reduce(FP16 *w)
+{
+    FP8_reduce(&(w->a));
+    FP8_reduce(&(w->b));
+}
+
+/* normalise all elements of w */
+void YYY::FP16_norm(FP16 *w)
+{
+    FP8_norm(&(w->a));
+    FP8_norm(&(w->b));
+}
+
+/* Set w=s*x, where s is FP8 */
+void YYY::FP16_pmul(FP16 *w,FP16 *x,FP8 *s)
+{
+    FP8_mul(&(w->a),&(x->a),s);
+    FP8_mul(&(w->b),&(x->b),s);
+}
+
+/* Set w=s*x, where s is FP2 */
+void YYY::FP16_qmul(FP16 *w,FP16 *x,FP2 *s)
+{
+    FP8_qmul(&(w->a),&(x->a),s);
+    FP8_qmul(&(w->b),&(x->b),s);
+}
+
+/* Set w=s*x, where s is int */
+void YYY::FP16_imul(FP16 *w,FP16 *x,int s)
+{
+    FP8_imul(&(w->a),&(x->a),s);
+    FP8_imul(&(w->b),&(x->b),s);
+}
+
+/* Set w=x^2 */
+/* Input MUST be normed  */
+void YYY::FP16_sqr(FP16 *w,FP16 *x)
+{
+    FP8 t1,t2,t3;
+
+    FP8_mul(&t3,&(x->a),&(x->b)); /* norms x */
+    FP8_copy(&t2,&(x->b));
+    FP8_add(&t1,&(x->a),&(x->b));
+    FP8_times_i(&t2);
+
+    FP8_add(&t2,&(x->a),&t2);
+
+	FP8_norm(&t1);  // 2
+	FP8_norm(&t2);  // 2
+
+    FP8_mul(&(w->a),&t1,&t2);
+
+    FP8_copy(&t2,&t3);
+    FP8_times_i(&t2);
+
+    FP8_add(&t2,&t2,&t3);
+
+	FP8_norm(&t2);  // 2
+    FP8_neg(&t2,&t2);
+    FP8_add(&(w->a),&(w->a),&t2);  /* a=(a+b)(a+i^2.b)-i^2.ab-ab = a*a+ib*ib */
+    FP8_add(&(w->b),&t3,&t3);  /* b=2ab */
+
+    FP16_norm(w);
+}
+
+/* Set w=x*y */
+/* Inputs MUST be normed  */
+void YYY::FP16_mul(FP16 *w,FP16 *x,FP16 *y)
+{
+
+    FP8 t1,t2,t3,t4;
+    FP8_mul(&t1,&(x->a),&(y->a)); 
+    FP8_mul(&t2,&(x->b),&(y->b)); 
+
+    FP8_add(&t3,&(y->b),&(y->a));
+    FP8_add(&t4,&(x->b),&(x->a));
+
+	FP8_norm(&t4); // 2
+	FP8_norm(&t3); // 2
+//printf("Into 16 mul 2\n");
+    FP8_mul(&t4,&t4,&t3); /* (xa+xb)(ya+yb) */
+//printf("Into 16 mul 2a\n");
+	FP8_neg(&t3,&t1);  // 1
+	FP8_add(&t4,&t4,&t3);  //t4E=3
+    FP8_norm(&t4);
+
+	FP8_neg(&t3,&t2);  // 1
+	FP8_add(&(w->b),&t4,&t3); //wbE=3
+
+    FP8_times_i(&t2);
+    FP8_add(&(w->a),&t2,&t1);
+
+    FP16_norm(w);
+}
+
+/* output FP16 in format [a,b] */
+void YYY::FP16_output(FP16 *w)
+{
+    printf("[");
+    FP8_output(&(w->a));
+    printf(",");
+    FP8_output(&(w->b));
+    printf("]");
+}
+
+void YYY::FP16_rawoutput(FP16 *w)
+{
+    printf("[");
+    FP8_rawoutput(&(w->a));
+    printf(",");
+    FP8_rawoutput(&(w->b));
+    printf("]");
+}
+
+/* Set w=1/x */
+void YYY::FP16_inv(FP16 *w,FP16 *x)
+{
+    FP8 t1,t2;
+    FP8_sqr(&t1,&(x->a));
+    FP8_sqr(&t2,&(x->b));
+    FP8_times_i(&t2);
+	FP8_norm(&t2);
+
+    FP8_sub(&t1,&t1,&t2);
+	FP8_norm(&t1);
+
+    FP8_inv(&t1,&t1);
+
+    FP8_mul(&(w->a),&t1,&(x->a));
+    FP8_neg(&t1,&t1);
+	FP8_norm(&t1);
+    FP8_mul(&(w->b),&t1,&(x->b));
+}
+
+/* w*=i where i = sqrt(sqrt(-1+sqrt(-1))) */
+void YYY::FP16_times_i(FP16 *w)
+{
+	FP8 s,t;
+	FP8_copy(&s,&(w->b));
+	FP8_copy(&t,&(w->a));
+	FP8_times_i(&s);
+	FP8_copy(&(w->a),&s);
+	FP8_copy(&(w->b),&t);
+	FP16_norm(w);
+}
+
+void YYY::FP16_times_i2(FP16 *w)
+{
+	FP8_times_i(&(w->a));
+	FP8_times_i(&(w->b));
+}
+
+void YYY::FP16_times_i4(FP16 *w)
+{
+	FP8_times_i2(&(w->a));
+	FP8_times_i2(&(w->b));
+}
+
+/* Set w=w^p using Frobenius */
+void YYY::FP16_frob(FP16 *w,FP2 *f)
+{ // f=(i+1)^(p-3)/8
+	FP2 ff;
+	//FP4 f4;
+	FP2_sqr(&ff,f);  // (i+1)^(p-3)/4
+	FP2_norm(&ff);
+
+	FP8_frob(&(w->a),&ff);
+	FP8_frob(&(w->b),&ff);
+
+	//FP4_from_FP2(&f4,f); // (1+i)^(p-3)/8
+
+	FP8_qmul(&(w->b),&(w->b),f);  // times (1+i)^(p-3)/8
+	FP8_times_i(&(w->b));		// (i+1)^(p-1)/8
+}
+
+/* Set r=a^b mod m */
+void YYY::FP16_pow(FP16 *r,FP16* a,BIG b)
+{
+    FP16 w;
+    BIG z,zilch;
+    int bt;
+
+    BIG_zero(zilch);
+
+    BIG_copy(z,b);
+    FP16_copy(&w,a);
+    FP16_one(r);
+    BIG_norm(z);
+    while(1)
+    {
+        bt=BIG_parity(z);
+        BIG_shr(z,1);
+        if (bt) FP16_mul(r,r,&w);
+        if (BIG_comp(z,zilch)==0) break;
+        FP16_sqr(&w,&w);
+    }
+    FP16_reduce(r);
+}
+
+/* Move b to a if d=1 */
+void YYY::FP16_cmove(FP16 *f,FP16 *g,int d)
+{
+    FP8_cmove(&(f->a),&(g->a),d);
+    FP8_cmove(&(f->b),&(g->b),d);
+}
+
+#if CURVE_SECURITY_ZZZ == 256
+
+/* XTR xtr_a function */
+void YYY::FP16_xtr_A(FP16 *r,FP16 *w,FP16 *x,FP16 *y,FP16 *z)
+{
+    FP16 t1,t2;
+
+    FP16_copy(r,x);
+    FP16_sub(&t1,w,y);
+	FP16_norm(&t1);
+    FP16_pmul(&t1,&t1,&(r->a));
+    FP16_add(&t2,w,y);
+	FP16_norm(&t2);
+    FP16_pmul(&t2,&t2,&(r->b));
+    FP16_times_i(&t2);
+
+    FP16_add(r,&t1,&t2);
+    FP16_add(r,r,z);
+
+    FP16_reduce(r);
+}
+
+/* XTR xtr_d function */
+void YYY::FP16_xtr_D(FP16 *r,FP16 *x)
+{
+    FP16 w;
+    FP16_copy(r,x);
+    FP16_conj(&w,r);
+    FP16_add(&w,&w,&w);
+    FP16_sqr(r,r);
+	FP16_norm(&w);
+    FP16_sub(r,r,&w);
+    FP16_reduce(r);    /* reduce here as multiple calls trigger automatic reductions */
+}
+
+/* r=x^n using XTR method on traces of FP12s */
+void YYY::FP16_xtr_pow(FP16 *r,FP16 *x,BIG n)
+{
+    int i,par,nb;
+    BIG v;
+    FP2 w2;
+	FP4 w4;
+	FP8 w8;
+    FP16 t,a,b,c,sf;
+
+	FP16_copy(&sf,x);
+	FP16_norm(&sf);
+    BIG_zero(v);
+    BIG_inc(v,3);
+	BIG_norm(v);
+    FP2_from_BIG(&w2,v);
+    FP4_from_FP2(&w4,&w2);
+	FP8_from_FP4(&w8,&w4);
+    FP16_from_FP8(&a,&w8);
+
+	FP16_copy(&b,&sf);
+    FP16_xtr_D(&c,&sf);
+
+
+    par=BIG_parity(n);
+    BIG_copy(v,n);
+    BIG_norm(v);
+    BIG_shr(v,1);
+    if (par==0)
+    {
+        BIG_dec(v,1);
+        BIG_norm(v);
+    }
+
+    nb=BIG_nbits(v);
+    for (i=nb-1; i>=0; i--)
+    {
+        if (!BIG_bit(v,i))
+        {
+            FP16_copy(&t,&b);
+            FP16_conj(&sf,&sf);
+            FP16_conj(&c,&c);
+            FP16_xtr_A(&b,&a,&b,&sf,&c);
+            FP16_conj(&sf,&sf);
+            FP16_xtr_D(&c,&t);
+            FP16_xtr_D(&a,&a);
+        }
+        else
+        {
+            FP16_conj(&t,&a);
+            FP16_xtr_D(&a,&b);
+            FP16_xtr_A(&b,&c,&b,&sf,&t);
+            FP16_xtr_D(&c,&c);
+        }
+    }
+
+    if (par==0) FP16_copy(r,&c);
+    else FP16_copy(r,&b);
+    FP16_reduce(r);
+}
+
+/* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */
+void YYY::FP16_xtr_pow2(FP16 *r,FP16 *ck,FP16 *cl,FP16 *ckml,FP16 *ckm2l,BIG a,BIG b)
+{
+    int i,f2;
+    BIG d,e,w;
+    FP16 t,cu,cv,cumv,cum2v;
+
+
+    BIG_copy(e,a);
+    BIG_copy(d,b);
+    BIG_norm(d);
+	BIG_norm(e);
+    FP16_copy(&cu,ck);
+    FP16_copy(&cv,cl);
+    FP16_copy(&cumv,ckml);
+    FP16_copy(&cum2v,ckm2l);
+
+    f2=0;
+    while (BIG_parity(d)==0 && BIG_parity(e)==0)
+    {
+        BIG_shr(d,1);
+        BIG_shr(e,1);
+        f2++;
+    }
+    while (BIG_comp(d,e)!=0)
+    {
+        if (BIG_comp(d,e)>0)
+        {
+            BIG_imul(w,e,4);
+            BIG_norm(w);
+            if (BIG_comp(d,w)<=0)
+            {
+                BIG_copy(w,d);
+                BIG_copy(d,e);
+                BIG_sub(e,w,e);
+                BIG_norm(e);
+                FP16_xtr_A(&t,&cu,&cv,&cumv,&cum2v);
+                FP16_conj(&cum2v,&cumv);
+                FP16_copy(&cumv,&cv);
+                FP16_copy(&cv,&cu);
+                FP16_copy(&cu,&t);
+            }
+            else if (BIG_parity(d)==0)
+            {
+                BIG_shr(d,1);
+                FP16_conj(r,&cum2v);
+                FP16_xtr_A(&t,&cu,&cumv,&cv,r);
+                FP16_xtr_D(&cum2v,&cumv);
+                FP16_copy(&cumv,&t);
+                FP16_xtr_D(&cu,&cu);
+            }
+            else if (BIG_parity(e)==1)
+            {
+                BIG_sub(d,d,e);
+                BIG_norm(d);
+                BIG_shr(d,1);
+                FP16_xtr_A(&t,&cu,&cv,&cumv,&cum2v);
+                FP16_xtr_D(&cu,&cu);
+                FP16_xtr_D(&cum2v,&cv);
+                FP16_conj(&cum2v,&cum2v);
+                FP16_copy(&cv,&t);
+            }
+            else
+            {
+                BIG_copy(w,d);
+                BIG_copy(d,e);
+                BIG_shr(d,1);
+                BIG_copy(e,w);
+                FP16_xtr_D(&t,&cumv);
+                FP16_conj(&cumv,&cum2v);
+                FP16_conj(&cum2v,&t);
+                FP16_xtr_D(&t,&cv);
+                FP16_copy(&cv,&cu);
+                FP16_copy(&cu,&t);
+            }
+        }
+        if (BIG_comp(d,e)<0)
+        {
+            BIG_imul(w,d,4);
+            BIG_norm(w);
+            if (BIG_comp(e,w)<=0)
+            {
+                BIG_sub(e,e,d);
+                BIG_norm(e);
+                FP16_xtr_A(&t,&cu,&cv,&cumv,&cum2v);
+                FP16_copy(&cum2v,&cumv);
+                FP16_copy(&cumv,&cu);
+                FP16_copy(&cu,&t);
+            }
+            else if (BIG_parity(e)==0)
+            {
+                BIG_copy(w,d);
+                BIG_copy(d,e);
+                BIG_shr(d,1);
+                BIG_copy(e,w);
+                FP16_xtr_D(&t,&cumv);
+                FP16_conj(&cumv,&cum2v);
+                FP16_conj(&cum2v,&t);
+                FP16_xtr_D(&t,&cv);
+                FP16_copy(&cv,&cu);
+                FP16_copy(&cu,&t);
+            }
+            else if (BIG_parity(d)==1)
+            {
+                BIG_copy(w,e);
+                BIG_copy(e,d);
+                BIG_sub(w,w,d);
+                BIG_norm(w);
+                BIG_copy(d,w);
+                BIG_shr(d,1);
+                FP16_xtr_A(&t,&cu,&cv,&cumv,&cum2v);
+                FP16_conj(&cumv,&cumv);
+                FP16_xtr_D(&cum2v,&cu);
+                FP16_conj(&cum2v,&cum2v);
+                FP16_xtr_D(&cu,&cv);
+                FP16_copy(&cv,&t);
+            }
+            else
+            {
+                BIG_shr(d,1);
+                FP16_conj(r,&cum2v);
+                FP16_xtr_A(&t,&cu,&cumv,&cv,r);
+                FP16_xtr_D(&cum2v,&cumv);
+                FP16_copy(&cumv,&t);
+                FP16_xtr_D(&cu,&cu);
+            }
+        }
+    }
+    FP16_xtr_A(r,&cu,&cv,&cumv,&cum2v);
+    for (i=0; i<f2; i++)	FP16_xtr_D(r,r);
+    FP16_xtr_pow(r,r,d);
+}
+
+#endif
+
+
+
+/*
+int main(){
+		FP2 w0,w1,f;
+		FP8 w,t;
+		FP8 c1,c2,c3,c4,cr;
+		BIG a,b;
+		BIG e,e1,e2;
+		BIG p,md;
+
+
+		BIG_rcopy(md,Modulus);
+		//Test w^(P^4) = w mod p^2
+		BIG_zero(a); BIG_inc(a,27);
+		BIG_zero(b); BIG_inc(b,45);
+		FP2_from_BIGs(&w0,a,b);
+
+		BIG_zero(a); BIG_inc(a,33);
+		BIG_zero(b); BIG_inc(b,54);
+		FP2_from_BIGs(&w1,a,b);
+
+		FP8_from_FP2s(&w,&w0,&w1);
+		FP8_reduce(&w);
+
+		printf("w= ");
+		FP8_output(&w);
+		printf("\n");
+
+
+		FP8_copy(&t,&w);
+
+
+		BIG_copy(p,md);
+		FP8_pow(&w,&w,p);
+
+		printf("w^p= ");
+		FP8_output(&w);
+		printf("\n");
+//exit(0);
+
+		BIG_rcopy(a,CURVE_Fra);
+		BIG_rcopy(b,CURVE_Frb);
+		FP2_from_BIGs(&f,a,b);
+
+		FP8_frob(&t,&f);
+		printf("w^p= ");
+		FP8_output(&t);
+		printf("\n");
+
+		FP8_pow(&w,&w,p);
+		FP8_pow(&w,&w,p);
+		FP8_pow(&w,&w,p);
+		printf("w^p4= ");
+		FP8_output(&w);
+		printf("\n");
+
+// Test 1/(1/x) = x mod p^4
+		FP8_from_FP2s(&w,&w0,&w1);
+		printf("Test Inversion \nw= ");
+		FP8_output(&w);
+		printf("\n");
+
+		FP8_inv(&w,&w);
+		printf("1/w mod p^4 = ");
+		FP8_output(&w);
+		printf("\n");
+
+		FP8_inv(&w,&w);
+		printf("1/(1/w) mod p^4 = ");
+		FP8_output(&w);
+		printf("\n");
+
+		BIG_zero(e); BIG_inc(e,12);
+
+
+
+	//	FP8_xtr_A(&w,&t,&w,&t,&t);
+		FP8_xtr_pow(&w,&w,e);
+
+		printf("w^e= ");
+		FP8_output(&w);
+		printf("\n");
+
+
+		BIG_zero(a); BIG_inc(a,37);
+		BIG_zero(b); BIG_inc(b,17);
+		FP2_from_BIGs(&w0,a,b);
+
+		BIG_zero(a); BIG_inc(a,49);
+		BIG_zero(b); BIG_inc(b,31);
+		FP2_from_BIGs(&w1,a,b);
+
+		FP8_from_FP2s(&c1,&w0,&w1);
+		FP8_from_FP2s(&c2,&w0,&w1);
+		FP8_from_FP2s(&c3,&w0,&w1);
+		FP8_from_FP2s(&c4,&w0,&w1);
+
+		BIG_zero(e1); BIG_inc(e1,3331);
+		BIG_zero(e2); BIG_inc(e2,3372);
+
+		FP8_xtr_pow2(&w,&c1,&w,&c2,&c3,e1,e2);
+
+		printf("c^e= ");
+		FP8_output(&w);
+		printf("\n");
+
+
+		return 0;
+}
+*/
+
diff --git a/version3/cpp/fp16.h b/version3/cpp/fp16.h
new file mode 100644
index 0000000..1cf1138
--- /dev/null
+++ b/version3/cpp/fp16.h
@@ -0,0 +1,264 @@
+#ifndef FP16_YYY_H
+#define FP16_YYY_H
+
+#include "fp8_YYY.h"
+#include "config_curve_ZZZ.h"
+
+using namespace amcl;
+
+namespace YYY{
+
+/**
+	@brief FP16 Structure - towered over two FP4
+*/
+
+typedef struct
+{
+    FP8 a; /**< real part of FP16 */
+    FP8 b; /**< imaginary part of FP16 */
+} FP16;
+
+
+/* FP16 prototypes */
+/**	@brief Tests for FP16 equal to zero
+ *
+	@param x FP16 number to be tested
+	@return 1 if zero, else returns 0
+ */
+extern int FP16_iszilch(FP16 *x);
+/**	@brief Tests for FP16 equal to unity
+ *
+	@param x FP16 number to be tested
+	@return 1 if unity, else returns 0
+ */
+extern int FP16_isunity(FP16 *x);
+/**	@brief Tests for equality of two FP16s
+ *
+	@param x FP16 instance to be compared
+	@param y FP16 instance to be compared
+	@return 1 if x=y, else returns 0
+ */
+extern int FP16_equals(FP16 *x,FP16 *y);
+/**	@brief Tests for FP16 having only a real part and no imaginary part
+ *
+	@param x FP16 number to be tested
+	@return 1 if real, else returns 0
+ */
+extern int FP16_isreal(FP16 *x);
+/**	@brief Initialise FP16 from two FP8s
+ *
+	@param x FP16 instance to be initialised
+	@param a FP8 to form real part of FP16
+	@param b FP8 to form imaginary part of FP16
+ */
+extern void FP16_from_FP8s(FP16 *x,FP8 *a,FP8 *b);
+/**	@brief Initialise FP16 from single FP8
+ *
+	Imaginary part is set to zero
+	@param x FP16 instance to be initialised
+	@param a FP8 to form real part of FP16
+ */
+extern void FP16_from_FP8(FP16 *x,FP8 *a);
+
+/**	@brief Initialise FP16 from single FP8
+ *
+	real part is set to zero
+	@param x FP16 instance to be initialised
+	@param a FP8 to form imaginary part of FP16
+ */
+extern void FP16_from_FP8H(FP16 *x,FP8 *a);
+
+
+/**	@brief Copy FP16 to another FP16
+ *
+	@param x FP16 instance, on exit = y
+	@param y FP16 instance to be copied
+ */
+extern void FP16_copy(FP16 *x,FP16 *y);
+/**	@brief Set FP16 to zero
+ *
+	@param x FP16 instance to be set to zero
+ */
+extern void FP16_zero(FP16 *x);
+/**	@brief Set FP16 to unity
+ *
+	@param x FP16 instance to be set to one
+ */
+extern void FP16_one(FP16 *x);
+/**	@brief Negation of FP16
+ *
+	@param x FP16 instance, on exit = -y
+	@param y FP16 instance
+ */
+extern void FP16_neg(FP16 *x,FP16 *y);
+/**	@brief Conjugation of FP16
+ *
+	If y=(a,b) on exit x=(a,-b)
+	@param x FP16 instance, on exit = conj(y)
+	@param y FP16 instance
+ */
+extern void FP16_conj(FP16 *x,FP16 *y);
+/**	@brief Negative conjugation of FP16
+ *
+	If y=(a,b) on exit x=(-a,b)
+	@param x FP16 instance, on exit = -conj(y)
+	@param y FP16 instance
+ */
+extern void FP16_nconj(FP16 *x,FP16 *y);
+/**	@brief addition of two FP16s
+ *
+	@param x FP16 instance, on exit = y+z
+	@param y FP16 instance
+	@param z FP16 instance
+ */
+extern void FP16_add(FP16 *x,FP16 *y,FP16 *z);
+/**	@brief subtraction of two FP16s
+ *
+	@param x FP16 instance, on exit = y-z
+	@param y FP16 instance
+	@param z FP16 instance
+ */
+extern void FP16_sub(FP16 *x,FP16 *y,FP16 *z);
+/**	@brief Multiplication of an FP16 by an FP8
+ *
+	@param x FP16 instance, on exit = y*a
+	@param y FP16 instance
+	@param a FP4 multiplier
+ */
+extern void FP16_pmul(FP16 *x,FP16 *y,FP8 *a);
+
+/**	@brief Multiplication of an FP16 by an FP2
+ *
+	@param x FP16 instance, on exit = y*a
+	@param y FP16 instance
+	@param a FP2 multiplier
+ */
+extern void FP16_qmul(FP16 *x,FP16 *y,FP2 *a);
+
+/**	@brief Multiplication of an FP16 by a small integer
+ *
+	@param x FP16 instance, on exit = y*i
+	@param y FP16 instance
+	@param i an integer
+ */
+extern void FP16_imul(FP16 *x,FP16 *y,int i);
+/**	@brief Squaring an FP16
+ *
+	@param x FP16 instance, on exit = y^2
+	@param y FP16 instance
+ */
+extern void FP16_sqr(FP16 *x,FP16 *y);
+/**	@brief Multiplication of two FP16s
+ *
+	@param x FP16 instance, on exit = y*z
+	@param y FP16 instance
+	@param z FP16 instance
+ */
+extern void FP16_mul(FP16 *x,FP16 *y,FP16 *z);
+/**	@brief Inverting an FP16
+ *
+	@param x FP16 instance, on exit = 1/y
+	@param y FP16 instance
+ */
+extern void FP16_inv(FP16 *x,FP16 *y);
+/**	@brief Formats and outputs an FP16 to the console
+ *
+	@param x FP16 instance to be printed
+ */
+extern void FP16_output(FP16 *x);
+/**	@brief Formats and outputs an FP16 to the console in raw form (for debugging)
+ *
+	@param x FP16 instance to be printed
+ */
+extern void FP16_rawoutput(FP16 *x);
+/**	@brief multiplies an FP16 instance by irreducible polynomial sqrt(1+sqrt(-1))
+ *
+	@param x FP16 instance, on exit = sqrt(1+sqrt(-1)*x
+ */
+extern void FP16_times_i(FP16 *x);
+/**	@brief multiplies an FP16 instance by irreducible polynomial (1+sqrt(-1))
+ *
+	@param x FP16 instance, on exit = sqrt(1+sqrt(-1))^2*x
+ */
+extern void FP16_times_i2(FP16 *x);
+
+/**	@brief multiplies an FP16 instance by irreducible polynomial (1+sqrt(-1))
+ *
+	@param x FP16 instance, on exit = sqrt(1+sqrt(-1))^4*x
+ */
+extern void FP16_times_i4(FP16 *x);
+
+
+/**	@brief Normalises the components of an FP16
+ *
+	@param x FP16 instance to be normalised
+ */
+extern void FP16_norm(FP16 *x);
+/**	@brief Reduces all components of possibly unreduced FP16 mod Modulus
+ *
+	@param x FP16 instance, on exit reduced mod Modulus
+ */
+extern void FP16_reduce(FP16 *x);
+/**	@brief Raises an FP16 to the power of a BIG
+ *
+	@param x FP16 instance, on exit = y^b
+	@param y FP16 instance
+	@param b BIG number
+ */
+extern void FP16_pow(FP16 *x,FP16 *y,XXX::BIG b);
+/**	@brief Raises an FP16 to the power of the internal modulus p, using the Frobenius
+ *
+	@param x FP16 instance, on exit = x^p
+	@param f FP2 precalculated Frobenius constant
+ */
+extern void FP16_frob(FP16 *x,FP2 *f);
+/**	@brief Calculates the XTR addition function r=w*x-conj(x)*y+z
+ *
+	@param r FP16 instance, on exit = w*x-conj(x)*y+z
+	@param w FP16 instance
+	@param x FP16 instance
+	@param y FP16 instance
+	@param z FP16 instance
+ */
+extern void FP16_xtr_A(FP16 *r,FP16 *w,FP16 *x,FP16 *y,FP16 *z);
+/**	@brief Calculates the XTR doubling function r=x^2-2*conj(x)
+ *
+	@param r FP16 instance, on exit = x^2-2*conj(x)
+	@param x FP16 instance
+ */
+extern void FP16_xtr_D(FP16 *r,FP16 *x);
+/**	@brief Calculates FP16 trace of an FP12 raised to the power of a BIG number
+ *
+	XTR single exponentiation
+	@param r FP16 instance, on exit = trace(w^b)
+	@param x FP16 instance, trace of an FP12 w
+	@param b BIG number
+ */
+extern void FP16_xtr_pow(FP16 *r,FP16 *x,XXX::BIG b);
+/**	@brief Calculates FP16 trace of c^a.d^b, where c and d are derived from FP16 traces of FP12s
+ *
+	XTR double exponentiation
+	Assumes c=tr(x^m), d=tr(x^n), e=tr(x^(m-n)), f=tr(x^(m-2n))
+	@param r FP16 instance, on exit = trace(c^a.d^b)
+	@param c FP16 instance, trace of an FP12
+	@param d FP16 instance, trace of an FP12
+	@param e FP16 instance, trace of an FP12
+	@param f FP16 instance, trace of an FP12
+	@param a BIG number
+	@param b BIG number
+ */
+extern void FP16_xtr_pow2(FP16 *r,FP16 *c,FP16 *d,FP16 *e,FP16 *f,XXX::BIG a,XXX::BIG b);
+
+/**	@brief Conditional copy of FP16 number
+ *
+	Conditionally copies second parameter to the first (without branching)
+	@param x FP16 instance, set to y if s!=0
+	@param y another FP16 instance
+	@param s copy only takes place if not equal to 0
+ */
+extern void FP16_cmove(FP16 *x,FP16 *y,int s);
+
+}
+
+#endif
+
diff --git a/version3/cpp/fp2.cpp b/version3/cpp/fp2.cpp
new file mode 100644
index 0000000..c39f08a
--- /dev/null
+++ b/version3/cpp/fp2.cpp
@@ -0,0 +1,486 @@
+/*
+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.
+*/
+
+/* AMCL Fp^2 functions */
+/* SU=m, m is Stack Usage (no lazy )*/
+
+/* FP2 elements are of the form a+ib, where i is sqrt(-1) */
+
+#include "fp2_YYY.h"
+
+using namespace XXX;
+
+/* test x==0 ? */
+/* SU= 8 */
+int YYY::FP2_iszilch(FP2 *x)
+{
+    //FP2_reduce(x);
+    if (FP_iszilch(&(x->a)) && FP_iszilch(&(x->b))) return 1;
+    return 0;
+}
+
+/* Move b to a if d=1 */
+void YYY::FP2_cmove(FP2 *f,FP2 *g,int d)
+{
+    FP_cmove(&(f->a),&(g->a),d);
+    FP_cmove(&(f->b),&(g->b),d);
+}
+
+/* test x==1 ? */
+/* SU= 48 */
+int YYY::FP2_isunity(FP2 *x)
+{
+    FP one;
+    FP_one(&one);
+    //FP2_reduce(x);
+    if (FP_equals(&(x->a),&one) && FP_iszilch(&(x->b))) return 1;
+    return 0;
+}
+
+/* SU= 8 */
+/* Fully reduce a and b mod Modulus */
+void YYY::FP2_reduce(FP2 *w)
+{
+    FP_reduce(&(w->a));
+    FP_reduce(&(w->b));
+}
+
+/* return 1 if x==y, else 0 */
+/* SU= 16 */
+int YYY::FP2_equals(FP2 *x,FP2 *y)
+{
+    if (FP_equals(&(x->a),&(y->a)) && FP_equals(&(x->b),&(y->b)))
+        return 1;
+    return 0;
+}
+
+/* Create FP2 from two FPs */
+/* SU= 16 */
+void YYY::FP2_from_FPs(FP2 *w,FP *x,FP *y)
+{
+    FP_copy(&(w->a),x);
+    FP_copy(&(w->b),y);
+}
+
+/* Create FP2 from two BIGS */
+/* SU= 16 */
+void YYY::FP2_from_BIGs(FP2 *w,BIG x,BIG y)
+{
+    FP_nres(&(w->a),x);
+    FP_nres(&(w->b),y);
+}
+
+/* Create FP2 from FP */
+/* SU= 8 */
+void YYY::FP2_from_FP(FP2 *w,FP *x)
+{
+    FP_copy(&(w->a),x);
+    FP_zero(&(w->b));
+}
+
+/* Create FP2 from BIG */
+/* SU= 8 */
+void YYY::FP2_from_BIG(FP2 *w,BIG x)
+{
+    FP_nres(&(w->a),x);
+    FP_zero(&(w->b));
+}
+
+/* FP2 copy w=x */
+/* SU= 16 */
+void YYY::FP2_copy(FP2 *w,FP2 *x)
+{
+    if (w==x) return;
+    FP_copy(&(w->a),&(x->a));
+    FP_copy(&(w->b),&(x->b));
+}
+
+/* FP2 set w=0 */
+/* SU= 8 */
+void YYY::FP2_zero(FP2 *w)
+{
+    FP_zero(&(w->a));
+    FP_zero(&(w->b));
+}
+
+/* FP2 set w=1 */
+/* SU= 48 */
+void YYY::FP2_one(FP2 *w)
+{
+    FP one;
+    FP_one(&one);
+    FP2_from_FP(w,&one);
+}
+
+/* Set w=-x */
+/* SU= 88 */
+void YYY::FP2_neg(FP2 *w,FP2 *x)
+{
+    /* Just one neg! */
+    FP m,t;
+//    FP2_norm(x);
+    FP_add(&m,&(x->a),&(x->b));
+    FP_neg(&m,&m);
+    FP_add(&t,&m,&(x->b));
+    FP_add(&(w->b),&m,&(x->a));
+    FP_copy(&(w->a),&t);
+
+}
+
+/* Set w=conj(x) */
+/* SU= 16 */
+void YYY::FP2_conj(FP2 *w,FP2 *x)
+{
+    FP_copy(&(w->a),&(x->a));
+	//FP_norm(&(x->b));
+    FP_neg(&(w->b),&(x->b));
+	FP_norm(&(w->b));
+}
+
+/* Set w=x+y */
+/* SU= 16 */
+void YYY::FP2_add(FP2 *w,FP2 *x,FP2 *y)
+{
+    FP_add(&(w->a),&(x->a),&(y->a));
+    FP_add(&(w->b),&(x->b),&(y->b));
+}
+
+/* Set w=x-y */
+/* Input y MUST be normed */ 
+void YYY::FP2_sub(FP2 *w,FP2 *x,FP2 *y)
+{
+    FP2 m;
+    FP2_neg(&m,y);
+    FP2_add(w,x,&m);
+}
+
+/* Set w=s*x, where s is FP */
+/* SU= 16 */
+void YYY::FP2_pmul(FP2 *w,FP2 *x,FP *s)
+{
+    FP_mul(&(w->a),&(x->a),s);
+    FP_mul(&(w->b),&(x->b),s);
+}
+
+/* SU= 16 */
+/* Set w=s*x, where s is int */
+void YYY::FP2_imul(FP2 *w,FP2 *x,int s)
+{
+    FP_imul(&(w->a),&(x->a),s);
+    FP_imul(&(w->b),&(x->b),s);
+}
+
+/* Set w=x^2 */
+/* SU= 128 */
+void YYY::FP2_sqr(FP2 *w,FP2 *x)
+{
+    FP w1,w3,mb;
+
+    FP_add(&w1,&(x->a),&(x->b)); 
+    FP_neg(&mb,&(x->b));  
+	
+	FP_add(&w3,&(x->a),&(x->a));
+	FP_norm(&w3);
+    FP_mul(&(w->b),&w3,&(x->b)); 
+
+    FP_add(&(w->a),&(x->a),&mb);   
+
+	FP_norm(&w1);
+	FP_norm(&(w->a));
+
+    FP_mul(&(w->a),&w1,&(w->a));     /* w->a#2 w->a=1 w1&w2=6 w1*w2=2 */
+}
+
+
+/* Set w=x*y */
+/* Inputs MUST be normed  */
+/* Now uses Lazy reduction */
+void YYY::FP2_mul(FP2 *w,FP2 *x,FP2 *y)
+{
+	DBIG A,B,E,F,pR;
+	BIG C,D,p;
+
+    BIG_rcopy(p,Modulus);
+	BIG_dsucopy(pR,p);
+
+// reduce excesses of a and b as required (so product < pR)
+
+	if ((sign64)(x->a.XES+x->b.XES)*(y->a.XES+y->b.XES)>(sign64)FEXCESS_YYY)
+	{
+#ifdef DEBUG_REDUCE
+		printf("FP2 Product too large - reducing it\n");
+#endif
+		if (x->a.XES>1) FP_reduce(&(x->a));
+        if (x->b.XES>1) FP_reduce(&(x->b));        
+    }
+
+	BIG_mul(A,x->a.g,y->a.g);
+	BIG_mul(B,x->b.g,y->b.g);
+
+	BIG_add(C,x->a.g,x->b.g); BIG_norm(C);
+	BIG_add(D,y->a.g,y->b.g); BIG_norm(D);
+
+	BIG_mul(E,C,D);
+	BIG_dadd(F,A,B);
+	BIG_dsub(B,pR,B); // 
+
+	BIG_dadd(A,A,B);    // A<pR? Not necessarily, but <2pR
+	BIG_dsub(E,E,F);    // E<pR ? Yes
+
+	BIG_dnorm(A); FP_mod(w->a.g,A);  w->a.XES=3;// may drift above 2p...
+	BIG_dnorm(E); FP_mod(w->b.g,E);  w->b.XES=2;
+
+}
+
+/* output FP2 in hex format [a,b] */
+/* SU= 16 */
+void YYY::FP2_output(FP2 *w)
+{
+	BIG bx,by;
+    FP2_reduce(w);
+    FP_redc(bx,&(w->a));
+    FP_redc(by,&(w->b));
+    printf("[");
+    BIG_output(bx);
+    printf(",");
+    BIG_output(by);
+    printf("]");
+    FP_nres(&(w->a),bx);
+    FP_nres(&(w->b),by);
+}
+
+/* SU= 8 */
+void YYY::FP2_rawoutput(FP2 *w)
+{
+    printf("[");
+    BIG_rawoutput(w->a.g);
+    printf(",");
+    BIG_rawoutput(w->b.g);
+    printf("]");
+}
+
+
+/* Set w=1/x */
+/* SU= 128 */
+void YYY::FP2_inv(FP2 *w,FP2 *x)
+{
+    BIG b;
+	FP w1,w2;
+
+    FP2_norm(x);
+    FP_sqr(&w1,&(x->a));
+    FP_sqr(&w2,&(x->b));
+    FP_add(&w1,&w1,&w2);
+
+	FP_inv(&w1,&w1);
+
+    FP_mul(&(w->a),&(x->a),&w1);
+    FP_neg(&w1,&w1);
+	FP_norm(&w1);
+    FP_mul(&(w->b),&(x->b),&w1);
+//	FP2_norm(w);
+}
+
+
+/* Set w=x/2 */
+/* SU= 16 */
+void YYY::FP2_div2(FP2 *w,FP2 *x)
+{
+    FP_div2(&(w->a),&(x->a));
+    FP_div2(&(w->b),&(x->b));
+}
+
+/* Set w*=(1+sqrt(-1)) */
+/* where X^2-(1+sqrt(-1)) is irreducible for FP4, assumes p=3 mod 8 */
+
+/* Input MUST be normed */
+void YYY::FP2_mul_ip(FP2 *w)
+{
+    FP z;
+	FP2 t;
+
+ //   FP2_norm(w);
+    FP2_copy(&t,w);
+
+    FP_copy(&z,&(w->a));
+    FP_neg(&(w->a),&(w->b));
+    FP_copy(&(w->b),&z);
+
+    FP2_add(w,&t,w);
+//    Output NOT normed, so use with care
+}
+
+
+void YYY::FP2_div_ip2(FP2 *w)
+{
+    FP2 t;
+	FP2_norm(&t);
+    FP_add(&(t.a),&(w->a),&(w->b));
+    FP_sub(&(t.b),&(w->b),&(w->a));
+	FP2_norm(&t);
+	FP2_copy(w,&t);
+}
+
+/* Set w/=(1+sqrt(-1)) */
+/* SU= 88 */
+void YYY::FP2_div_ip(FP2 *w)
+{
+    FP2 t;
+    FP2_norm(w);
+    FP_add(&t.a,&(w->a),&(w->b));
+    FP_sub(&t.b,&(w->b),&(w->a));
+	FP2_norm(&t);
+    FP2_div2(w,&t);
+}
+
+/* SU= 8 */
+/* normalise a and b components of w */
+void YYY::FP2_norm(FP2 *w)
+{
+    FP_norm(&(w->a));
+    FP_norm(&(w->b));
+}
+
+/* Set w=a^b mod m */
+/* SU= 208 */
+void YYY::FP2_pow(FP2 *r,FP2* a,BIG b)
+{
+    FP2 w;
+	FP one;
+    BIG z,zilch;
+    int bt;
+
+    BIG_norm(b);
+    BIG_copy(z,b);
+    FP2_copy(&w,a);
+    FP_one(&one);
+    BIG_zero(zilch);
+    FP2_from_FP(r,&one);
+    while(1)
+    {
+        bt=BIG_parity(z);
+        BIG_shr(z,1);
+        if (bt) FP2_mul(r,r,&w);
+        if (BIG_comp(z,zilch)==0) break;
+        FP2_sqr(&w,&w);
+    }
+    FP2_reduce(r);
+}
+
+/* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */
+/* returns true if u is QR */
+
+int YYY::FP2_sqrt(FP2 *w,FP2 *u)
+{
+    BIG b;
+	FP w1,w2;
+    FP2_copy(w,u);
+    if (FP2_iszilch(w)) return 1;
+
+    FP_sqr(&w1,&(w->b));
+    FP_sqr(&w2,&(w->a));
+    FP_add(&w1,&w1,&w2);
+    if (!FP_qr(&w1))
+    {
+        FP2_zero(w);
+        return 0;
+    }
+    FP_sqrt(&w1,&w1);
+    FP_add(&w2,&(w->a),&w1);
+	FP_norm(&w2);
+    FP_div2(&w2,&w2);
+    if (!FP_qr(&w2))
+    {
+        FP_sub(&w2,&(w->a),&w1);
+		FP_norm(&w2);
+        FP_div2(&w2,&w2);
+        if (!FP_qr(&w2))
+        {
+            FP2_zero(w);
+            return 0;
+        }
+    }
+    FP_sqrt(&w2,&w2);
+    FP_copy(&(w->a),&w2);
+    FP_add(&w2,&w2,&w2);
+
+	FP_inv(&w2,&w2);
+
+    FP_mul(&(w->b),&(w->b),&w2);
+    return 1;
+}
+
+/* New stuff for ECp4 support */
+
+/* Input MUST be normed */
+void YYY::FP2_times_i(FP2 *w)
+{
+    FP z;
+
+ //   FP2_norm(w);
+
+    FP_copy(&z,&(w->a));
+    FP_neg(&(w->a),&(w->b));
+    FP_copy(&(w->b),&z);
+
+//    Output NOT normed, so use with care
+}
+
+
+/*
+int main()
+{
+	int i;
+	FP2 w,z;
+	BIG a,b,e;
+	BIG pp1,pm1;
+	BIG_unity(a); BIG_unity(b);
+	FP2_from_BIGs(&w,a,b);
+//	for (i=0;i<100;i++)
+//	{
+//		BIG_randomnum(a); BIG_randomnum(b);
+//		BIG_mod(a,Modulus); BIG_mod(b,Modulus);
+//		FP2_from_FPs(&w,a,b);
+//		FP2_output(&w);
+//		FP2_inv(&z,&w);
+//				FP2_output(&z);
+//		FP2_inv(&z,&z);
+//				FP2_output(&z);
+//				FP2_output(&w);
+//		if (FP2_comp(&w,&z)!=1) printf("error \n");
+//		else printf("OK \n");
+//	}
+//exit(0);
+	printf("w= "); FP2_output(&w); printf("\n");
+	BIG_zero(e); BIG_inc(e,27);
+	FP2_pow(&w,&w,e);
+	FP2_output(&w);
+exit(0);
+	BIG_rcopy(pp1,Modulus);
+	BIG_rcopy(pm1,Modulus);
+	BIG_inc(pp1,1);
+	BIG_dec(pm1,1);
+	BIG_norm(pp1);
+	BIG_norm(pm1);
+	FP2_pow(&w,&w,pp1);
+	FP2_pow(&w,&w,pm1);
+	FP2_output(&w);
+}
+
+*/
diff --git a/version3/cpp/fp2.h b/version3/cpp/fp2.h
new file mode 100644
index 0000000..8cbe630
--- /dev/null
+++ b/version3/cpp/fp2.h
@@ -0,0 +1,219 @@
+#ifndef FP2_YYY_H
+#define FP2_YYY_H
+
+#include "fp_YYY.h"
+
+using namespace amcl;
+
+namespace YYY {
+
+/**
+	@brief FP2 Structure - quadratic extension field
+*/
+
+typedef struct
+{
+    FP a; /**< real part of FP2 */
+    FP b; /**< imaginary part of FP2 */
+} FP2;
+
+/* FP2 prototypes */
+
+/**	@brief Tests for FP2 equal to zero
+ *
+	@param x FP2 number to be tested
+	@return 1 if zero, else returns 0
+ */
+extern int FP2_iszilch(FP2 *x);
+/**	@brief Conditional copy of FP2 number
+ *
+	Conditionally copies second parameter to the first (without branching)
+	@param x FP2 instance, set to y if s!=0
+	@param y another FP2 instance
+	@param s copy only takes place if not equal to 0
+ */
+extern void FP2_cmove(FP2 *x,FP2 *y,int s);
+/**	@brief Tests for FP2 equal to one
+ *
+	@param x FP2 instance to be tested
+	@return 1 if x=1, else returns 0
+ */
+extern int FP2_isunity(FP2 *x);
+/**	@brief Tests for equality of two FP2s
+ *
+	@param x FP2 instance to be compared
+	@param y FP2 instance to be compared
+	@return 1 if x=y, else returns 0
+ */
+extern int FP2_equals(FP2 *x,FP2 *y);
+/**	@brief Initialise FP2 from two FP numbers
+ *
+	@param x FP2 instance to be initialised
+	@param a FP to form real part of FP2
+	@param b FP to form imaginary part of FP2
+ */
+extern void FP2_from_FPs(FP2 *x,FP *a,FP *b);
+/**	@brief Initialise FP2 from two BIG integers
+ *
+	@param x FP2 instance to be initialised
+	@param a BIG to form real part of FP2
+	@param b BIG to form imaginary part of FP2
+ */
+extern void FP2_from_BIGs(FP2 *x,XXX::BIG a,XXX::BIG b);
+/**	@brief Initialise FP2 from single FP
+ *
+	Imaginary part is set to zero
+	@param x FP2 instance to be initialised
+	@param an FP to form real part of FP2
+ */
+extern void FP2_from_FP(FP2 *x,FP *a);
+/**	@brief Initialise FP2 from single BIG
+ *
+	Imaginary part is set to zero
+	@param x FP2 instance to be initialised
+	@param a BIG to form real part of FP2
+ */
+extern void FP2_from_BIG(FP2 *x,XXX::BIG a);
+/**	@brief Copy FP2 to another FP2
+ *
+	@param x FP2 instance, on exit = y
+	@param y FP2 instance to be copied
+ */
+extern void FP2_copy(FP2 *x,FP2 *y);
+/**	@brief Set FP2 to zero
+ *
+	@param x FP2 instance to be set to zero
+ */
+extern void FP2_zero(FP2 *x);
+/**	@brief Set FP2 to unity
+ *
+	@param x FP2 instance to be set to one
+ */
+extern void FP2_one(FP2 *x);
+/**	@brief Negation of FP2
+ *
+	@param x FP2 instance, on exit = -y
+	@param y FP2 instance
+ */
+extern void FP2_neg(FP2 *x,FP2 *y);
+/**	@brief Conjugation of FP2
+ *
+	If y=(a,b) on exit x=(a,-b)
+	@param x FP2 instance, on exit = conj(y)
+	@param y FP2 instance
+ */
+extern void FP2_conj(FP2 *x,FP2 *y);
+/**	@brief addition of two FP2s
+ *
+	@param x FP2 instance, on exit = y+z
+	@param y FP2 instance
+	@param z FP2 instance
+ */
+extern void FP2_add(FP2 *x,FP2 *y,FP2 *z);
+/**	@brief subtraction of two FP2s
+ *
+	@param x FP2 instance, on exit = y-z
+	@param y FP2 instance
+	@param z FP2 instance
+ */
+extern void FP2_sub(FP2 *x,FP2 *y,FP2 *z);
+/**	@brief Multiplication of an FP2 by an FP
+ *
+	@param x FP2 instance, on exit = y*b
+	@param y FP2 instance
+	@param b FP residue
+ */
+extern void FP2_pmul(FP2 *x,FP2 *y,FP *b);
+/**	@brief Multiplication of an FP2 by a small integer
+ *
+	@param x FP2 instance, on exit = y*i
+	@param y FP2 instance
+	@param i an integer
+ */
+extern void FP2_imul(FP2 *x,FP2 *y,int i);
+/**	@brief Squaring an FP2
+ *
+	@param x FP2 instance, on exit = y^2
+	@param y FP2 instance
+ */
+extern void FP2_sqr(FP2 *x,FP2 *y);
+/**	@brief Multiplication of two FP2s
+ *
+	@param x FP2 instance, on exit = y*z
+	@param y FP2 instance
+	@param z FP2 instance
+ */
+extern void FP2_mul(FP2 *x,FP2 *y,FP2 *z);
+/**	@brief Formats and outputs an FP2 to the console
+ *
+	@param x FP2 instance
+ */
+extern void FP2_output(FP2 *x);
+/**	@brief Formats and outputs an FP2 to the console in raw form (for debugging)
+ *
+	@param x FP2 instance
+ */
+extern void FP2_rawoutput(FP2 *x);
+/**	@brief Inverting an FP2
+ *
+	@param x FP2 instance, on exit = 1/y
+	@param y FP2 instance
+ */
+extern void FP2_inv(FP2 *x,FP2 *y);
+/**	@brief Divide an FP2 by 2
+ *
+	@param x FP2 instance, on exit = y/2
+	@param y FP2 instance
+ */
+extern void FP2_div2(FP2 *x,FP2 *y);
+/**	@brief Multiply an FP2 by (1+sqrt(-1))
+ *
+	Note that (1+sqrt(-1)) is irreducible for FP4
+	@param x FP2 instance, on exit = x*(1+sqrt(-1))
+ */
+extern void FP2_mul_ip(FP2 *x);
+/**	@brief Divide an FP2 by (1+sqrt(-1))/2 - 
+ *
+	Note that (1+sqrt(-1)) is irreducible for FP4
+	@param x FP2 instance, on exit = 2x/(1+sqrt(-1))
+ */
+extern void FP2_div_ip2(FP2 *x);
+/**	@brief Divide an FP2 by (1+sqrt(-1))
+ *
+	Note that (1+sqrt(-1)) is irreducible for FP4
+	@param x FP2 instance, on exit = x/(1+sqrt(-1))
+ */
+extern void FP2_div_ip(FP2 *x);
+/**	@brief Normalises the components of an FP2
+ *
+	@param x FP2 instance to be normalised
+ */
+extern void FP2_norm(FP2 *x);
+/**	@brief Reduces all components of possibly unreduced FP2 mod Modulus
+ *
+	@param x FP2 instance, on exit reduced mod Modulus
+ */
+extern void FP2_reduce(FP2 *x);
+/**	@brief Raises an FP2 to the power of a BIG
+ *
+	@param x FP2 instance, on exit = y^b
+	@param y FP2 instance
+	@param b BIG number
+ */
+extern void FP2_pow(FP2 *x,FP2 *y,XXX::BIG b);
+/**	@brief Square root of an FP2
+ *
+	@param x FP2 instance, on exit = sqrt(y)
+	@param y FP2 instance
+ */
+extern int FP2_sqrt(FP2 *x,FP2 *y);
+/**	@brief Multiply an FP2 by sqrt(-1)
+ *
+	Note that -1 is QNR
+	@param x FP2 instance, on exit = x*sqrt(-1)
+ */
+extern void FP2_times_i(FP2 *x);
+
+}
+
+#endif
\ No newline at end of file
diff --git a/version3/cpp/fp24.cpp b/version3/cpp/fp24.cpp
new file mode 100644
index 0000000..f275e11
--- /dev/null
+++ b/version3/cpp/fp24.cpp
@@ -0,0 +1,1126 @@
+/*
+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.
+*/
+
+/* AMCL Fp^12 functions */
+/* SU=m, m is Stack Usage (no lazy )*/
+/* FP24 elements are of the form a+i.b+i^2.c */
+
+#include "fp24_YYY.h"
+
+using namespace XXX;
+
+/* return 1 if b==c, no branching */
+static int teq(sign32 b,sign32 c)
+{
+    sign32 x=b^c;
+    x-=1;  // if x=0, x now -1
+    return (int)((x>>31)&1);
+}
+
+
+/* Constant time select from pre-computed table */
+static void FP24_select(YYY::FP24 *f,YYY::FP24 g[],sign32 b)
+{
+    YYY::FP24 invf;
+    sign32 m=b>>31;
+    sign32 babs=(b^m)-m;
+
+    babs=(babs-1)/2;
+
+    FP24_cmove(f,&g[0],teq(babs,0));  // conditional move
+    FP24_cmove(f,&g[1],teq(babs,1));
+    FP24_cmove(f,&g[2],teq(babs,2));
+    FP24_cmove(f,&g[3],teq(babs,3));
+    FP24_cmove(f,&g[4],teq(babs,4));
+    FP24_cmove(f,&g[5],teq(babs,5));
+    FP24_cmove(f,&g[6],teq(babs,6));
+    FP24_cmove(f,&g[7],teq(babs,7));
+
+    FP24_copy(&invf,f);
+    FP24_conj(&invf,&invf);  // 1/f
+    FP24_cmove(f,&invf,(int)(m&1));
+}
+
+/* test x==0 ? */
+/* SU= 8 */
+int YYY::FP24_iszilch(FP24 *x)
+{
+    if (FP8_iszilch(&(x->a)) && FP8_iszilch(&(x->b)) && FP8_iszilch(&(x->c))) return 1;
+    return 0;
+}
+
+/* test x==1 ? */
+/* SU= 8 */
+int YYY::FP24_isunity(FP24 *x)
+{
+    if (FP8_isunity(&(x->a)) && FP8_iszilch(&(x->b)) && FP8_iszilch(&(x->c))) return 1;
+    return 0;
+}
+
+/* FP24 copy w=x */
+/* SU= 16 */
+void YYY::FP24_copy(FP24 *w,FP24 *x)
+{
+    if (x==w) return;
+    FP8_copy(&(w->a),&(x->a));
+    FP8_copy(&(w->b),&(x->b));
+    FP8_copy(&(w->c),&(x->c));
+}
+
+/* FP24 w=1 */
+/* SU= 8 */
+void YYY::FP24_one(FP24 *w)
+{
+    FP8_one(&(w->a));
+    FP8_zero(&(w->b));
+    FP8_zero(&(w->c));
+}
+
+/* return 1 if x==y, else 0 */
+/* SU= 16 */
+int YYY::FP24_equals(FP24 *x,FP24 *y)
+{
+    if (FP8_equals(&(x->a),&(y->a)) && FP8_equals(&(x->b),&(y->b)) && FP8_equals(&(x->b),&(y->b)))
+        return 1;
+    return 0;
+}
+
+/* Set w=conj(x) */
+/* SU= 8 */
+void YYY::FP24_conj(FP24 *w,FP24 *x)
+{
+    FP24_copy(w,x);
+    FP8_conj(&(w->a),&(w->a));
+    FP8_nconj(&(w->b),&(w->b));
+    FP8_conj(&(w->c),&(w->c));
+}
+
+/* Create FP24 from FP8 */
+/* SU= 8 */
+void YYY::FP24_from_FP8(FP24 *w,FP8 *a)
+{
+    FP8_copy(&(w->a),a);
+    FP8_zero(&(w->b));
+    FP8_zero(&(w->c));
+}
+
+/* Create FP24 from 3 FP8's */
+/* SU= 16 */
+void YYY::FP24_from_FP8s(FP24 *w,FP8 *a,FP8 *b,FP8 *c)
+{
+    FP8_copy(&(w->a),a);
+    FP8_copy(&(w->b),b);
+    FP8_copy(&(w->c),c);
+}
+
+/* Granger-Scott Unitary Squaring. This does not benefit from lazy reduction */
+/* SU= 600 */
+void YYY::FP24_usqr(FP24 *w,FP24 *x)
+{
+    FP8 A,B,C,D;
+
+    FP8_copy(&A,&(x->a));
+
+    FP8_sqr(&(w->a),&(x->a));
+    FP8_add(&D,&(w->a),&(w->a));
+    FP8_add(&(w->a),&D,&(w->a));
+
+    FP8_norm(&(w->a));
+    FP8_nconj(&A,&A);
+
+    FP8_add(&A,&A,&A);
+    FP8_add(&(w->a),&(w->a),&A);
+    FP8_sqr(&B,&(x->c));
+    FP8_times_i(&B);
+
+    FP8_add(&D,&B,&B);
+    FP8_add(&B,&B,&D);
+    FP8_norm(&B);
+
+    FP8_sqr(&C,&(x->b));
+
+    FP8_add(&D,&C,&C);
+    FP8_add(&C,&C,&D);
+
+    FP8_norm(&C);
+    FP8_conj(&(w->b),&(x->b));
+    FP8_add(&(w->b),&(w->b),&(w->b));
+    FP8_nconj(&(w->c),&(x->c));
+
+    FP8_add(&(w->c),&(w->c),&(w->c));
+    FP8_add(&(w->b),&B,&(w->b));
+    FP8_add(&(w->c),&C,&(w->c));
+
+//	FP24_norm(w);
+    FP24_reduce(w);	    /* reduce here as in pow function repeated squarings would trigger multiple reductions */
+}
+
+/* FP24 squaring w=x^2 */
+/* SU= 600 */
+void YYY::FP24_sqr(FP24 *w,FP24 *x)
+{
+    /* Use Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
+
+    FP8 A,B,C,D;
+
+    FP8_sqr(&A,&(x->a));
+    FP8_mul(&B,&(x->b),&(x->c));
+    FP8_add(&B,&B,&B);
+FP8_norm(&B);
+    FP8_sqr(&C,&(x->c));
+
+    FP8_mul(&D,&(x->a),&(x->b));
+    FP8_add(&D,&D,&D);
+
+    FP8_add(&(w->c),&(x->a),&(x->c));
+    FP8_add(&(w->c),&(x->b),&(w->c));
+FP8_norm(&(w->c));	
+
+    FP8_sqr(&(w->c),&(w->c));
+
+    FP8_copy(&(w->a),&A);
+    FP8_add(&A,&A,&B);
+
+    FP8_norm(&A);
+
+    FP8_add(&A,&A,&C);
+    FP8_add(&A,&A,&D);
+
+    FP8_norm(&A);
+
+    FP8_neg(&A,&A);
+    FP8_times_i(&B);
+    FP8_times_i(&C);
+
+    FP8_add(&(w->a),&(w->a),&B);
+    FP8_add(&(w->b),&C,&D);
+    FP8_add(&(w->c),&(w->c),&A);
+
+    FP24_norm(w);
+}
+
+/* FP24 full multiplication w=w*y */
+
+
+/* SU= 896 */
+/* FP24 full multiplication w=w*y */
+void YYY::FP24_mul(FP24 *w,FP24 *y)
+{
+    FP8 z0,z1,z2,z3,t0,t1;
+
+    FP8_mul(&z0,&(w->a),&(y->a));
+    FP8_mul(&z2,&(w->b),&(y->b));  //
+
+    FP8_add(&t0,&(w->a),&(w->b));
+    FP8_add(&t1,&(y->a),&(y->b));  //
+
+FP8_norm(&t0);
+FP8_norm(&t1);
+
+    FP8_mul(&z1,&t0,&t1);
+    FP8_add(&t0,&(w->b),&(w->c));
+    FP8_add(&t1,&(y->b),&(y->c));  //
+
+FP8_norm(&t0);
+FP8_norm(&t1);
+
+    FP8_mul(&z3,&t0,&t1);
+
+    FP8_neg(&t0,&z0);
+    FP8_neg(&t1,&z2);
+
+    FP8_add(&z1,&z1,&t0);   // z1=z1-z0
+//    FP8_norm(&z1);
+    FP8_add(&(w->b),&z1,&t1);
+// z1=z1-z2
+    FP8_add(&z3,&z3,&t1);        // z3=z3-z2
+    FP8_add(&z2,&z2,&t0);        // z2=z2-z0
+
+    FP8_add(&t0,&(w->a),&(w->c));
+    FP8_add(&t1,&(y->a),&(y->c));
+
+FP8_norm(&t0);
+FP8_norm(&t1);
+
+    FP8_mul(&t0,&t1,&t0);
+    FP8_add(&z2,&z2,&t0);
+
+    FP8_mul(&t0,&(w->c),&(y->c));
+    FP8_neg(&t1,&t0);
+
+    FP8_add(&(w->c),&z2,&t1);
+    FP8_add(&z3,&z3,&t1);
+    FP8_times_i(&t0);
+    FP8_add(&(w->b),&(w->b),&t0);
+FP8_norm(&z3);
+    FP8_times_i(&z3);
+    FP8_add(&(w->a),&z0,&z3);
+
+    FP24_norm(w);
+}
+
+/* FP24 multiplication w=w*y */
+/* SU= 744 */
+/* catering for special case that arises from special form of ATE pairing line function */
+void YYY::FP24_smul(FP24 *w,FP24 *y,int type)
+{
+    FP8 z0,z1,z2,z3,t0,t1;
+
+	if (type==D_TYPE)
+	{ // y->c is 0
+
+		FP8_copy(&z3,&(w->b));
+		FP8_mul(&z0,&(w->a),&(y->a));
+
+		FP8_pmul(&z2,&(w->b),&(y->b).a);
+		FP8_add(&(w->b),&(w->a),&(w->b));
+		FP8_copy(&t1,&(y->a));
+		FP4_add(&t1.a,&t1.a,&(y->b).a);
+
+		FP8_norm(&t1);
+		FP8_norm(&(w->b));
+
+		FP8_mul(&(w->b),&(w->b),&t1);
+		FP8_add(&z3,&z3,&(w->c));
+		FP8_norm(&z3);
+		FP8_pmul(&z3,&z3,&(y->b).a);
+		FP8_neg(&t0,&z0);
+		FP8_neg(&t1,&z2);
+
+		FP8_add(&(w->b),&(w->b),&t0);   // z1=z1-z0
+//    FP8_norm(&(w->b));
+		FP8_add(&(w->b),&(w->b),&t1);   // z1=z1-z2
+
+		FP8_add(&z3,&z3,&t1);        // z3=z3-z2
+		FP8_add(&z2,&z2,&t0);        // z2=z2-z0
+
+		FP8_add(&t0,&(w->a),&(w->c));
+
+		FP8_norm(&t0);
+		FP8_norm(&z3);
+
+		FP8_mul(&t0,&(y->a),&t0);
+		FP8_add(&(w->c),&z2,&t0);
+
+		FP8_times_i(&z3);
+		FP8_add(&(w->a),&z0,&z3);
+	}
+
+	if (type==M_TYPE)
+	{ // y->b is zero
+		FP8_mul(&z0,&(w->a),&(y->a));
+		FP8_add(&t0,&(w->a),&(w->b));
+		FP8_norm(&t0);
+
+		FP8_mul(&z1,&t0,&(y->a));
+		FP8_add(&t0,&(w->b),&(w->c));
+		FP8_norm(&t0);
+
+		FP8_pmul(&z3,&t0,&(y->c).b);
+		FP8_times_i(&z3);
+
+		FP8_neg(&t0,&z0);
+		FP8_add(&z1,&z1,&t0);   // z1=z1-z0
+
+		FP8_copy(&(w->b),&z1);
+
+		FP8_copy(&z2,&t0);
+
+		FP8_add(&t0,&(w->a),&(w->c));
+		FP8_add(&t1,&(y->a),&(y->c));
+
+		FP8_norm(&t0);
+		FP8_norm(&t1);
+
+		FP8_mul(&t0,&t1,&t0);
+		FP8_add(&z2,&z2,&t0);
+
+		FP8_pmul(&t0,&(w->c),&(y->c).b);
+		FP8_times_i(&t0);
+		FP8_neg(&t1,&t0);
+		FP8_times_i(&t0);
+
+		FP8_add(&(w->c),&z2,&t1);
+		FP8_add(&z3,&z3,&t1);
+
+		FP8_add(&(w->b),&(w->b),&t0);
+		FP8_norm(&z3);
+		FP8_times_i(&z3);
+		FP8_add(&(w->a),&z0,&z3);
+	}
+    FP24_norm(w);
+}
+
+/* Set w=1/x */
+/* SU= 600 */
+void YYY::FP24_inv(FP24 *w,FP24 *x)
+{
+    FP8 f0,f1,f2,f3;
+//    FP24_norm(x);
+
+    FP8_sqr(&f0,&(x->a));
+    FP8_mul(&f1,&(x->b),&(x->c));
+    FP8_times_i(&f1);
+    FP8_sub(&f0,&f0,&f1);  /* y.a */
+	FP8_norm(&f0); 		
+
+    FP8_sqr(&f1,&(x->c));
+    FP8_times_i(&f1);
+    FP8_mul(&f2,&(x->a),&(x->b));
+    FP8_sub(&f1,&f1,&f2);  /* y.b */
+	FP8_norm(&f1); 
+
+    FP8_sqr(&f2,&(x->b));
+    FP8_mul(&f3,&(x->a),&(x->c));
+    FP8_sub(&f2,&f2,&f3);  /* y.c */
+	FP8_norm(&f2); 
+
+    FP8_mul(&f3,&(x->b),&f2);
+    FP8_times_i(&f3);
+    FP8_mul(&(w->a),&f0,&(x->a));
+    FP8_add(&f3,&(w->a),&f3);
+    FP8_mul(&(w->c),&f1,&(x->c));
+    FP8_times_i(&(w->c));
+
+
+
+    FP8_add(&f3,&(w->c),&f3);
+	FP8_norm(&f3);
+	
+    FP8_inv(&f3,&f3);
+    FP8_mul(&(w->a),&f0,&f3);
+    FP8_mul(&(w->b),&f1,&f3);
+    FP8_mul(&(w->c),&f2,&f3);
+
+}
+
+/* constant time powering by small integer of max length bts */
+
+void YYY::FP24_pinpow(FP24 *r,int e,int bts)
+{
+    int i,b;
+    FP24 R[2];
+
+    FP24_one(&R[0]);
+    FP24_copy(&R[1],r);
+
+    for (i=bts-1; i>=0; i--)
+    {
+        b=(e>>i)&1;
+        FP24_mul(&R[1-b],&R[b]);
+        FP24_usqr(&R[b],&R[b]);
+    }
+    FP24_copy(r,&R[0]);
+}
+
+/* Compressed powering of unitary elements y=x^(e mod r) */
+
+void YYY::FP24_compow(FP8 *c,FP24 *x,BIG e,BIG r)
+{
+    FP24 g1,g2;
+	FP8 cp,cpm1,cpm2;
+    FP2 f;
+	BIG q,a,b,m;
+
+    BIG_rcopy(a,Fra);
+    BIG_rcopy(b,Frb);
+    FP2_from_BIGs(&f,a,b);
+
+    BIG_rcopy(q,Modulus);
+
+    FP24_copy(&g1,x);
+	FP24_copy(&g2,x);
+
+    BIG_copy(m,q);
+    BIG_mod(m,r);
+
+    BIG_copy(a,e);
+    BIG_mod(a,m);
+
+    BIG_copy(b,e);
+    BIG_sdiv(b,m);
+
+    FP24_trace(c,&g1);
+
+	if (BIG_iszilch(b))
+	{
+		FP8_xtr_pow(c,c,e);
+		return;
+	}
+
+    FP24_frob(&g2,&f,1);
+    FP24_trace(&cp,&g2);
+    FP24_conj(&g1,&g1);
+    FP24_mul(&g2,&g1);
+    FP24_trace(&cpm1,&g2);
+    FP24_mul(&g2,&g1);
+
+    FP24_trace(&cpm2,&g2);
+
+    FP8_xtr_pow2(c,&cp,c,&cpm1,&cpm2,a,b);
+
+}
+
+/* Note this is simple square and multiply, so not side-channel safe */
+
+void YYY::FP24_pow(FP24 *r,FP24 *a,BIG b)
+{
+    FP24 w,sf;
+    BIG b1,b3;
+    int i,nb,bt;
+	BIG_copy(b1,b);
+    BIG_norm(b1);
+	BIG_pmul(b3,b1,3);
+	BIG_norm(b3);
+
+	FP24_copy(&sf,a);
+	FP24_norm(&sf);
+    FP24_copy(&w,&sf);
+
+
+	nb=BIG_nbits(b3);
+	for (i=nb-2;i>=1;i--)
+	{
+		FP24_usqr(&w,&w);
+		bt=BIG_bit(b3,i)-BIG_bit(b1,i);
+		if (bt==1)
+			FP24_mul(&w,&sf);
+		if (bt==-1)
+		{
+			FP24_conj(&sf,&sf);
+			FP24_mul(&w,&sf);
+			FP24_conj(&sf,&sf);
+		}
+	}
+
+	FP24_copy(r,&w);
+	FP24_reduce(r);
+}
+
+
+/* SU= 528 */
+/* set r=a^b */
+/* Note this is simple square and multiply, so not side-channel safe 
+
+void YYY::FP24_ppow(FP24 *r,FP24 *a,BIG b)
+{
+    FP24 w;
+    BIG z,zilch;
+    int bt;
+    BIG_zero(zilch);
+    BIG_norm(b);
+    BIG_copy(z,b);
+    FP24_copy(&w,a);
+    FP24_one(r);
+
+    while(1)
+    {
+        bt=BIG_parity(z);
+        BIG_shr(z,1);
+        if (bt)
+		{
+			//printf("In mul\n");
+            FP24_mul(r,&w);
+			//printf("Out of mul\n");
+		}
+        if (BIG_comp(z,zilch)==0) break;
+		//printf("In sqr\n");
+        FP24_sqr(&w,&w);
+		//printf("Out of sqr\n");
+    }
+
+    FP24_reduce(r);
+}  */
+
+
+/* p=q0^u0.q1^u1.q2^u2.q3^u3... */
+/* Side channel attack secure */
+// Bos & Costello https://eprint.iacr.org/2013/458.pdf
+// Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
+
+void YYY::FP24_pow8(FP24 *p,FP24 *q,BIG u[8])
+{
+    int i,j,k,nb,pb1,pb2,bt;
+	FP24 g1[8],g2[8],r;
+	BIG t[8],mt;
+    sign8 w1[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 s1[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 w2[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 s2[NLEN_XXX*BASEBITS_XXX+1];
+    FP fx,fy;
+	FP2 X;
+
+    FP_rcopy(&fx,Fra);
+    FP_rcopy(&fy,Frb);
+    FP2_from_FPs(&X,&fx,&fy);
+
+    for (i=0; i<8; i++)
+        BIG_copy(t[i],u[i]);
+
+// Precomputed table
+    FP24_copy(&g1[0],&q[0]); // q[0]
+    FP24_copy(&g1[1],&g1[0]);
+	FP24_mul(&g1[1],&q[1]);	// q[0].q[1]
+    FP24_copy(&g1[2],&g1[0]);
+	FP24_mul(&g1[2],&q[2]);	// q[0].q[2]
+	FP24_copy(&g1[3],&g1[1]);
+	FP24_mul(&g1[3],&q[2]);	// q[0].q[1].q[2]
+	FP24_copy(&g1[4],&g1[0]);
+	FP24_mul(&g1[4],&q[3]);  // q[0].q[3]
+	FP24_copy(&g1[5],&g1[1]);
+	FP24_mul(&g1[5],&q[3]);	// q[0].q[1].q[3]
+	FP24_copy(&g1[6],&g1[2]);
+	FP24_mul(&g1[6],&q[3]);	// q[0].q[2].q[3]
+	FP24_copy(&g1[7],&g1[3]);
+	FP24_mul(&g1[7],&q[3]);	// q[0].q[1].q[2].q[3]
+
+// Use Frobenius
+
+	for (i=0;i<8;i++)
+	{
+		FP24_copy(&g2[i],&g1[i]);
+		FP24_frob(&g2[i],&X,4);
+	}
+
+// Make it odd
+	pb1=1-BIG_parity(t[0]);
+	BIG_inc(t[0],pb1);
+	BIG_norm(t[0]);
+
+	pb2=1-BIG_parity(t[4]);
+	BIG_inc(t[4],pb2);
+	BIG_norm(t[4]);
+
+// Number of bits
+    BIG_zero(mt);
+    for (i=0; i<8; i++)
+    {
+        BIG_or(mt,mt,t[i]);
+    }
+    nb=1+BIG_nbits(mt);
+
+// Sign pivot 
+	s1[nb-1]=1;
+	s2[nb-1]=1;
+	for (i=0;i<nb-1;i++)
+	{
+        BIG_fshr(t[0],1);
+		s1[i]=2*BIG_parity(t[0])-1;
+        BIG_fshr(t[4],1);
+		s2[i]=2*BIG_parity(t[4])-1;
+	}
+
+// Recoded exponents
+    for (i=0; i<nb; i++)
+    {
+		w1[i]=0;
+		k=1;
+		for (j=1; j<4; j++)
+		{
+			bt=s1[i]*BIG_parity(t[j]);
+			BIG_fshr(t[j],1);
+
+			BIG_dec(t[j],(bt>>1));
+			BIG_norm(t[j]);
+			w1[i]+=bt*k;
+			k*=2;
+        }
+
+		w2[i]=0;
+		k=1;
+		for (j=5; j<8; j++)
+		{
+			bt=s2[i]*BIG_parity(t[j]);
+			BIG_fshr(t[j],1);
+
+			BIG_dec(t[j],(bt>>1));
+			BIG_norm(t[j]);
+			w2[i]+=bt*k;
+			k*=2;
+        }
+    }	
+
+// Main loop
+	FP24_select(p,g1,2*w1[nb-1]+1);
+	FP24_select(&r,g2,2*w2[nb-1]+1);
+	FP24_mul(p,&r);
+    for (i=nb-2; i>=0; i--)
+    {
+		FP24_usqr(p,p);
+        FP24_select(&r,g1,2*w1[i]+s1[i]);
+        FP24_mul(p,&r);
+        FP24_select(&r,g2,2*w2[i]+s2[i]);
+        FP24_mul(p,&r);
+    }
+
+// apply correction
+	FP24_conj(&r,&q[0]);   
+	FP24_mul(&r,p);
+	FP24_cmove(p,&r,pb1);
+	FP24_conj(&r,&q[4]);   
+	FP24_mul(&r,p);
+	FP24_cmove(p,&r,pb2);
+
+	FP24_reduce(p);
+}
+
+/*
+void YYY::FP24_pow8(FP24 *p,FP24 *q,BIG u[8])
+{
+    int i,j,a[4],nb,m;
+    FP24 g[8],f[8],c,s[2];
+    BIG t[8],mt;
+    sign8 w[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 z[NLEN_XXX*BASEBITS_XXX+1];
+    FP fx,fy;
+	FP2 X;
+
+    FP_rcopy(&fx,Fra);
+    FP_rcopy(&fy,Frb);
+    FP2_from_FPs(&X,&fx,&fy);
+
+    for (i=0; i<8; i++)
+        BIG_copy(t[i],u[i]);
+
+    FP24_copy(&g[0],&q[0]);
+    FP24_conj(&s[0],&q[1]);
+    FP24_mul(&g[0],&s[0]);  // P/Q 
+    FP24_copy(&g[1],&g[0]);
+    FP24_copy(&g[2],&g[0]);
+    FP24_copy(&g[3],&g[0]);
+    FP24_copy(&g[4],&q[0]);
+    FP24_mul(&g[4],&q[1]);  // P*Q 
+    FP24_copy(&g[5],&g[4]);
+    FP24_copy(&g[6],&g[4]);
+    FP24_copy(&g[7],&g[4]);
+
+    FP24_copy(&s[1],&q[2]);
+    FP24_conj(&s[0],&q[3]);
+    FP24_mul(&s[1],&s[0]);       // R/S 
+    FP24_conj(&s[0],&s[1]);
+    FP24_mul(&g[1],&s[0]);
+    FP24_mul(&g[2],&s[1]);
+    FP24_mul(&g[5],&s[0]);
+    FP24_mul(&g[6],&s[1]);
+    FP24_copy(&s[1],&q[2]);
+    FP24_mul(&s[1],&q[3]);      // R*S 
+    FP24_conj(&s[0],&s[1]);
+    FP24_mul(&g[0],&s[0]);
+    FP24_mul(&g[3],&s[1]);
+    FP24_mul(&g[4],&s[0]);
+    FP24_mul(&g[7],&s[1]);
+
+// Use Frobenius
+
+	for (i=0;i<8;i++)
+	{
+		FP24_copy(&f[i],&g[i]);
+		FP24_frob(&f[i],&X,4);
+	}
+
+
+    // if power is even add 1 to power, and add q to correction 
+    FP24_one(&c);
+
+    BIG_zero(mt);
+    for (i=0; i<8; i++)
+    {
+        if (BIG_parity(t[i])==0)
+        {
+            BIG_inc(t[i],1);
+            BIG_norm(t[i]);
+            FP24_mul(&c,&q[i]);
+        }
+        BIG_add(mt,mt,t[i]);
+        BIG_norm(mt);
+    }
+
+    FP24_conj(&c,&c);
+    nb=1+BIG_nbits(mt);
+
+    // convert exponents to signed 1-bit windows 
+    for (j=0; j<nb; j++)
+    {
+        for (i=0; i<4; i++)
+        {
+            a[i]=BIG_lastbits(t[i],2)-2;
+            BIG_dec(t[i],a[i]);
+            BIG_norm(t[i]);
+            BIG_fshr(t[i],1);
+        }
+        w[j]=8*a[0]+4*a[1]+2*a[2]+a[3];
+    }
+    w[nb]=8*BIG_lastbits(t[0],2)+4*BIG_lastbits(t[1],2)+2*BIG_lastbits(t[2],2)+BIG_lastbits(t[3],2);
+
+
+    for (j=0; j<nb; j++)
+    {
+        for (i=0; i<4; i++)
+        {
+            a[i]=BIG_lastbits(t[i+4],2)-2;
+            BIG_dec(t[i+4],a[i]);
+            BIG_norm(t[i+4]);
+            BIG_fshr(t[i+4],1);
+        }
+        z[j]=8*a[0]+4*a[1]+2*a[2]+a[3];
+    }
+    z[nb]=8*BIG_lastbits(t[4],2)+4*BIG_lastbits(t[5],2)+2*BIG_lastbits(t[6],2)+BIG_lastbits(t[7],2);
+
+
+    FP24_copy(p,&g[(w[nb]-1)/2]);
+    FP24_mul(p,&f[(z[nb]-1)/2]);
+    for (i=nb-1; i>=0; i--)
+    {
+		FP24_usqr(p,p);
+
+        m=w[i]>>7;
+        j=(w[i]^m)-m;  // j=abs(w[i]) 
+        j=(j-1)/2;
+        FP24_copy(&s[0],&g[j]);
+        FP24_conj(&s[1],&g[j]);
+        FP24_mul(p,&s[m&1]);
+
+        m=z[i]>>7;
+        j=(z[i]^m)-m;  // j=abs(w[i]) 
+        j=(j-1)/2;
+        FP24_copy(&s[0],&f[j]);
+        FP24_conj(&s[1],&f[j]);
+        FP24_mul(p,&s[m&1]);
+
+    }
+    FP24_mul(p,&c); // apply correction 
+    FP24_reduce(p);
+}
+*/
+
+/* Set w=w^p using Frobenius */
+/* SU= 160 */
+void YYY::FP24_frob(FP24 *w,FP2 *f,int n)
+{
+	int i;
+	FP4 X2,X4;
+    FP2 f3,f2;				// f=(1+i)^(p-7)/12
+    FP2_sqr(&f2,f);     // 
+    FP2_mul(&f3,&f2,f); // f3=f^3=(1+i)^(p-7)/4
+
+	FP2_mul_ip(&f3);    // f3 = (1+i).f3 = (1+i)^(p-3)/4 
+	FP2_norm(&f3);
+
+	for (i=0;i<n;i++)
+	{
+		FP8_frob(&(w->a),&f3);   // a=a^p
+		FP8_frob(&(w->b),&f3);   // b=b^p
+		FP8_frob(&(w->c),&f3);   // c=c^p
+  
+		FP8_qmul(&(w->b),&(w->b),f); FP8_times_i2(&(w->b));
+		FP8_qmul(&(w->c),&(w->c),&f2); FP8_times_i2(&(w->c)); FP8_times_i2(&(w->c));
+	}
+}
+
+
+/* SU= 8 */
+/* normalise all components of w */
+void YYY::FP24_norm(FP24 *w)
+{
+    FP8_norm(&(w->a));
+    FP8_norm(&(w->b));
+    FP8_norm(&(w->c));
+}
+
+/* SU= 8 */
+/* reduce all components of w */
+void YYY::FP24_reduce(FP24 *w)
+{
+    FP8_reduce(&(w->a));
+    FP8_reduce(&(w->b));
+    FP8_reduce(&(w->c));
+}
+
+/* trace function w=trace(x) */
+/* SU= 8 */
+void YYY::FP24_trace(FP8 *w,FP24 *x)
+{
+    FP8_imul(w,&(x->a),3);
+    FP8_reduce(w);
+}
+
+/* SU= 8 */
+/* Output w in hex */
+void YYY::FP24_output(FP24 *w)
+{
+    printf("[");
+    FP8_output(&(w->a));
+    printf(",");
+    FP8_output(&(w->b));
+    printf(",");
+    FP8_output(&(w->c));
+    printf("]");
+}
+
+/* SU= 64 */
+/* Convert g to octet string w */
+void YYY::FP24_toOctet(octet *W,FP24 *g)
+{
+    BIG a;
+    W->len=24*MODBYTES_XXX;
+
+    FP_redc(a,&(g->a.a.a.a));
+    BIG_toBytes(&(W->val[0]),a);
+    FP_redc(a,&(g->a.a.a.b));
+    BIG_toBytes(&(W->val[MODBYTES_XXX]),a);
+    FP_redc(a,&(g->a.a.b.a));
+    BIG_toBytes(&(W->val[2*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->a.a.b.b));
+    BIG_toBytes(&(W->val[3*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->a.b.a.a));
+    BIG_toBytes(&(W->val[4*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->a.b.a.b));
+    BIG_toBytes(&(W->val[5*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->a.b.b.a));
+    BIG_toBytes(&(W->val[6*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->a.b.b.b));
+    BIG_toBytes(&(W->val[7*MODBYTES_XXX]),a);
+
+    FP_redc(a,&(g->b.a.a.a));
+    BIG_toBytes(&(W->val[8*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->b.a.a.b));
+    BIG_toBytes(&(W->val[9*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->b.a.b.a));
+    BIG_toBytes(&(W->val[10*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->b.a.b.b));
+    BIG_toBytes(&(W->val[11*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->b.b.a.a));
+    BIG_toBytes(&(W->val[12*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->b.b.a.b));
+    BIG_toBytes(&(W->val[13*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->b.b.b.a));
+    BIG_toBytes(&(W->val[14*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->b.b.b.b));
+    BIG_toBytes(&(W->val[15*MODBYTES_XXX]),a);
+
+    FP_redc(a,&(g->c.a.a.a));
+    BIG_toBytes(&(W->val[16*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->c.a.a.b));
+    BIG_toBytes(&(W->val[17*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->c.a.b.a));
+    BIG_toBytes(&(W->val[18*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->c.a.b.b));
+    BIG_toBytes(&(W->val[19*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->c.b.a.a));
+    BIG_toBytes(&(W->val[20*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->c.b.a.b));
+    BIG_toBytes(&(W->val[21*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->c.b.b.a));
+    BIG_toBytes(&(W->val[22*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->c.b.b.b));
+    BIG_toBytes(&(W->val[23*MODBYTES_XXX]),a);
+}
+
+/* SU= 24 */
+/* Restore g from octet string w */
+void YYY::FP24_fromOctet(FP24 *g,octet *W)
+{
+	BIG b;
+
+    BIG_fromBytes(b,&W->val[0]);
+    FP_nres(&(g->a.a.a.a),b);
+    BIG_fromBytes(b,&W->val[MODBYTES_XXX]);
+    FP_nres(&(g->a.a.a.b),b);
+    BIG_fromBytes(b,&W->val[2*MODBYTES_XXX]);
+    FP_nres(&(g->a.a.b.a),b);
+    BIG_fromBytes(b,&W->val[3*MODBYTES_XXX]);
+    FP_nres(&(g->a.a.b.b),b);
+    BIG_fromBytes(b,&W->val[4*MODBYTES_XXX]);
+    FP_nres(&(g->a.b.a.a),b);
+    BIG_fromBytes(b,&W->val[5*MODBYTES_XXX]);
+    FP_nres(&(g->a.b.a.b),b);
+    BIG_fromBytes(b,&W->val[6*MODBYTES_XXX]);
+    FP_nres(&(g->a.b.b.a),b);
+    BIG_fromBytes(b,&W->val[7*MODBYTES_XXX]);
+    FP_nres(&(g->a.b.b.b),b);
+
+    BIG_fromBytes(b,&W->val[8*MODBYTES_XXX]);
+    FP_nres(&(g->b.a.a.a),b);
+    BIG_fromBytes(b,&W->val[9*MODBYTES_XXX]);
+    FP_nres(&(g->b.a.a.b),b);
+    BIG_fromBytes(b,&W->val[10*MODBYTES_XXX]);
+    FP_nres(&(g->b.a.b.a),b);
+    BIG_fromBytes(b,&W->val[11*MODBYTES_XXX]);
+    FP_nres(&(g->b.a.b.b),b);
+    BIG_fromBytes(b,&W->val[12*MODBYTES_XXX]);
+    FP_nres(&(g->b.b.a.a),b);
+    BIG_fromBytes(b,&W->val[13*MODBYTES_XXX]);
+    FP_nres(&(g->b.b.a.b),b);
+    BIG_fromBytes(b,&W->val[14*MODBYTES_XXX]);
+    FP_nres(&(g->b.b.b.a),b);
+    BIG_fromBytes(b,&W->val[15*MODBYTES_XXX]);
+    FP_nres(&(g->b.b.b.b),b);
+
+    BIG_fromBytes(b,&W->val[16*MODBYTES_XXX]);
+    FP_nres(&(g->c.a.a.a),b);
+    BIG_fromBytes(b,&W->val[17*MODBYTES_XXX]);
+    FP_nres(&(g->c.a.a.b),b);
+    BIG_fromBytes(b,&W->val[18*MODBYTES_XXX]);
+    FP_nres(&(g->c.a.b.a),b);
+    BIG_fromBytes(b,&W->val[19*MODBYTES_XXX]);
+    FP_nres(&(g->c.a.b.b),b);
+    BIG_fromBytes(b,&W->val[20*MODBYTES_XXX]);
+    FP_nres(&(g->c.b.a.a),b);
+    BIG_fromBytes(b,&W->val[21*MODBYTES_XXX]);
+    FP_nres(&(g->c.b.a.b),b);
+    BIG_fromBytes(b,&W->val[22*MODBYTES_XXX]);
+    FP_nres(&(g->c.b.b.a),b);
+    BIG_fromBytes(b,&W->val[23*MODBYTES_XXX]);
+    FP_nres(&(g->c.b.b.b),b);
+}
+
+/* Move b to a if d=1 */
+void YYY::FP24_cmove(FP24 *f,FP24 *g,int d)
+{
+    FP8_cmove(&(f->a),&(g->a),d);
+    FP8_cmove(&(f->b),&(g->b),d);
+    FP8_cmove(&(f->c),&(g->c),d);
+}
+
+/*
+using namespace YYY;
+
+int main() {
+	int i;
+	FP2 f,w0,w1,X;
+	FP4 f0,f1;
+	FP8 t0,t1,t2;
+	FP24 w,t,lv;
+	BIG a,b;
+	BIG p;
+
+
+	char raw[100];
+	csprng RNG;                // Crypto Strong RNG 
+
+	for (i=0; i<100; i++) raw[i]=i;
+
+	BIG_rcopy(a,Fra);
+    BIG_rcopy(b,Frb);
+	FP2_from_BIGs(&X,a,b);
+
+
+
+    RAND_seed(&RNG,100,raw);   // initialise strong RNG 
+
+	BIG_rcopy(p,Modulus);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w0,a,b);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w1,a,b);
+
+	FP4_from_FP2s(&f0,&w0,&w1);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w0,a,b);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w1,a,b);
+
+	FP4_from_FP2s(&f1,&w0,&w1);
+	FP8_from_FP4s(&t0,&f0,&f1);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w0,a,b);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w1,a,b);
+
+	FP4_from_FP2s(&f0,&w0,&w1);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w0,a,b);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w1,a,b);
+
+	FP4_from_FP2s(&f1,&w0,&w1);
+	FP8_from_FP4s(&t1,&f0,&f1);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w0,a,b);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w1,a,b);
+
+	FP4_from_FP2s(&f0,&w0,&w1);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w0,a,b);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w1,a,b);
+
+	FP4_from_FP2s(&f1,&w0,&w1);
+	FP8_from_FP4s(&t2,&f0,&f1);
+
+	FP24_from_FP8s(&w,&t0,&t1,&t2);
+
+
+	FP24_copy(&t,&w);
+
+	printf("w= ");
+	FP24_output(&w);
+	printf("\n");
+
+	FP24_norm(&w);
+
+	printf("w^p= ");
+	FP24_frob(&w,&X);
+	FP24_output(&w);
+	printf("\n");	
+
+//	printf("p.w= ");
+//	FP24_ppow(&t,&t,p);
+//	FP24_output(&t);
+//	printf("\n");	
+
+	printf("1/w= ");
+	FP24_inv(&t,&w);
+	FP24_output(&t);
+	printf("\n");	
+
+	printf("w= ");
+	FP24_inv(&w,&t);
+	FP24_output(&w);
+	printf("\n");	
+
+	return 0;
+}
+
+*/
diff --git a/version3/cpp/fp24.h b/version3/cpp/fp24.h
new file mode 100644
index 0000000..d7a0fa0
--- /dev/null
+++ b/version3/cpp/fp24.h
@@ -0,0 +1,200 @@
+#ifndef FP24_YYY_H
+#define FP24_YYY_H
+
+#include "fp8_YYY.h"
+
+using namespace amcl;
+
+namespace YYY {
+/**
+	@brief FP12 Structure - towered over three FP8
+*/
+
+typedef struct
+{
+    FP8 a; /**< first part of FP12 */
+    FP8 b; /**< second part of FP12 */
+    FP8 c; /**< third part of FP12 */
+} FP24;
+
+extern const XXX::BIG Fra; /**< real part of BN curve Frobenius Constant */
+extern const XXX::BIG Frb; /**< imaginary part of BN curve Frobenius Constant */
+
+/* FP24 prototypes */
+/**	@brief Tests for FP24 equal to zero
+ *
+	@param x FP24 number to be tested
+	@return 1 if zero, else returns 0
+ */
+extern int FP24_iszilch(FP24 *x);
+/**	@brief Tests for FP24 equal to unity
+ *
+	@param x FP24 number to be tested
+	@return 1 if unity, else returns 0
+ */
+extern int FP24_isunity(FP24 *x);
+/**	@brief Copy FP24 to another FP24
+ *
+	@param x FP24 instance, on exit = y
+	@param y FP24 instance to be copied
+ */
+extern void FP24_copy(FP24 *x,FP24 *y);
+/**	@brief Set FP24 to unity
+ *
+	@param x FP24 instance to be set to one
+ */
+extern void FP24_one(FP24 *x);
+/**	@brief Tests for equality of two FP24s
+ *
+	@param x FP24 instance to be compared
+	@param y FP24 instance to be compared
+	@return 1 if x=y, else returns 0
+ */
+extern int FP24_equals(FP24 *x,FP24 *y);
+/**	@brief Conjugation of FP24
+ *
+	If y=(a,b,c) (where a,b,c are its three FP8 components) on exit x=(conj(a),-conj(b),conj(c))
+	@param x FP24 instance, on exit = conj(y)
+	@param y FP24 instance
+ */
+extern void FP24_conj(FP24 *x,FP24 *y);
+/**	@brief Initialise FP24 from single FP8
+ *
+	Sets first FP8 component of an FP24, other components set to zero
+	@param x FP24 instance to be initialised
+	@param a FP8 to form first part of FP8
+ */
+extern void FP24_from_FP8(FP24 *x,FP8 *a);
+/**	@brief Initialise FP24 from three FP8s
+ *
+	@param x FP24 instance to be initialised
+	@param a FP8 to form first part of FP24
+	@param b FP8 to form second part of FP24
+	@param c FP8 to form third part of FP24
+ */
+extern void FP24_from_FP8s(FP24 *x,FP8 *a,FP8* b,FP8 *c);
+/**	@brief Fast Squaring of an FP24 in "unitary" form
+ *
+	@param x FP24 instance, on exit = y^2
+	@param y FP8 instance, must be unitary
+ */
+extern void FP24_usqr(FP24 *x,FP24 *y);
+/**	@brief Squaring an FP24
+ *
+	@param x FP24 instance, on exit = y^2
+	@param y FP24 instance
+ */
+extern void FP24_sqr(FP24 *x,FP24 *y);
+/**	@brief Fast multiplication of an FP24 by an FP24 that arises from an ATE pairing line function
+ *
+	Here the multiplier has a special form that can be exploited
+	@param x FP24 instance, on exit = x*y
+	@param y FP24 instance, of special form
+	@param t D_TYPE or M_TYPE twist
+ */
+extern void FP24_smul(FP24 *x,FP24 *y,int t);
+/**	@brief Multiplication of two FP24s
+ *
+	@param x FP24 instance, on exit = x*y
+	@param y FP24 instance, the multiplier
+ */
+extern void FP24_mul(FP24 *x,FP24 *y);
+/**	@brief Inverting an FP24
+ *
+	@param x FP24 instance, on exit = 1/y
+	@param y FP24 instance
+ */
+extern void FP24_inv(FP24 *x,FP24 *y);
+/**	@brief Raises an FP24 to the power of a BIG
+ *
+	@param r FP24 instance, on exit = y^b
+	@param x FP24 instance
+	@param b BIG number
+ */
+extern void FP24_pow(FP24 *r,FP24 *x,XXX::BIG b);
+
+//extern void FP24_ppow(FP24 *r,FP24 *x,XXX::BIG b);
+
+/**	@brief Raises an FP24 instance x to a small integer power, side-channel resistant
+ *
+	@param x FP24 instance, on exit = x^i
+	@param i small integer exponent
+	@param b maximum number of bits in exponent
+ */
+extern void FP24_pinpow(FP24 *x,int i,int b);
+
+/**	@brief Raises an FP24 instance x to a BIG power, compressed to FP8 
+ *
+	@param c FP8 instance, on exit = x^(e mod r) as FP8
+	@param x FP24 input
+	@param e BIG exponent
+	@param r BIG group order
+ */
+extern void FP24_compow(FP8 *c,FP24 *x,XXX::BIG e,XXX::BIG r);
+
+/**	@brief Calculate Pi x[i]^b[i] for i=0 to 7, side-channel resistant
+ *
+	@param r FP24 instance, on exit = Pi x[i]^b[i] for i=0 to 7
+	@param x FP24 array with 4 FP24s
+	@param b BIG array of 4 exponents
+ */
+extern void FP24_pow8(FP24 *r,FP24 *x,XXX::BIG *b);
+
+
+/**	@brief Raises an FP24 to the power of the internal modulus p, using the Frobenius
+ *
+	@param x FP24 instance, on exit = x^p^n
+	@param f FP2 precalculated Frobenius constant
+	@param n power of p
+ */
+extern void FP24_frob(FP24 *x,FP2 *f,int n);
+
+/**	@brief Reduces all components of possibly unreduced FP24 mod Modulus
+ *
+	@param x FP24 instance, on exit reduced mod Modulus
+ */
+extern void FP24_reduce(FP24 *x);
+/**	@brief Normalises the components of an FP24
+ *
+	@param x FP24 instance to be normalised
+ */
+extern void FP24_norm(FP24 *x);
+/**	@brief Formats and outputs an FP24 to the console
+ *
+	@param x FP24 instance to be printed
+ */
+extern void FP24_output(FP24 *x);
+/**	@brief Formats and outputs an FP24 instance to an octet string
+ *
+	Serializes the components of an FP24 to big-endian base 256 form.
+	@param S output octet string
+	@param x FP24 instance to be converted to an octet string
+ */
+extern void FP24_toOctet(octet *S,FP24 *x);
+/**	@brief Creates an FP24 instance from an octet string
+ *
+	De-serializes the components of an FP24 to create an FP24 from big-endian base 256 components.
+	@param x FP24 instance to be created from an octet string
+	@param S input octet string
+
+ */
+extern void FP24_fromOctet(FP24 *x,octet *S);
+/**	@brief Calculate the trace of an FP24
+ *
+	@param t FP8 trace of x, on exit = tr(x)
+	@param x FP24 instance
+
+ */
+extern void FP24_trace(FP8 *t,FP24 *x);
+
+/**	@brief Conditional copy of FP24 number
+ *
+	Conditionally copies second parameter to the first (without branching)
+	@param x FP24 instance, set to y if s!=0
+	@param y another FP24 instance
+	@param s copy only takes place if not equal to 0
+ */
+extern void FP24_cmove(FP24 *x,FP24 *y,int s);
+
+}
+#endif
diff --git a/version3/cpp/fp4.cpp b/version3/cpp/fp4.cpp
new file mode 100644
index 0000000..2c2cc59
--- /dev/null
+++ b/version3/cpp/fp4.cpp
@@ -0,0 +1,808 @@
+/*
+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.
+*/
+
+/* AMCL Fp^4 functions */
+/* SU=m, m is Stack Usage (no lazy )*/
+
+/* FP4 elements are of the form a+ib, where i is sqrt(-1+sqrt(-1)) */
+
+#include "fp4_YYY.h"
+
+using namespace XXX;
+
+/* test x==0 ? */
+/* SU= 8 */
+int YYY::FP4_iszilch(FP4 *x)
+{
+    if (FP2_iszilch(&(x->a)) && FP2_iszilch(&(x->b))) return 1;
+    return 0;
+}
+
+/* test x==1 ? */
+/* SU= 8 */
+int YYY::FP4_isunity(FP4 *x)
+{
+    if (FP2_isunity(&(x->a)) && FP2_iszilch(&(x->b))) return 1;
+    return 0;
+}
+
+/* test is w real? That is in a+ib test b is zero */
+int YYY::FP4_isreal(FP4 *w)
+{
+    return FP2_iszilch(&(w->b));
+}
+
+/* return 1 if x==y, else 0 */
+/* SU= 16 */
+int YYY::FP4_equals(FP4 *x,FP4 *y)
+{
+    if (FP2_equals(&(x->a),&(y->a)) && FP2_equals(&(x->b),&(y->b)))
+        return 1;
+    return 0;
+}
+
+/* set FP4 from two FP2s */
+/* SU= 16 */
+void YYY::FP4_from_FP2s(FP4 *w,FP2 * x,FP2* y)
+{
+    FP2_copy(&(w->a), x);
+    FP2_copy(&(w->b), y);
+}
+
+/* set FP4 from FP2 */
+/* SU= 8 */
+void YYY::FP4_from_FP2(FP4 *w,FP2 *x)
+{
+    FP2_copy(&(w->a), x);
+    FP2_zero(&(w->b));
+}
+
+/* set high part of FP4 from FP2 */
+/* SU= 8 */
+void YYY::FP4_from_FP2H(FP4 *w,FP2 *x)
+{
+    FP2_copy(&(w->b), x);
+    FP2_zero(&(w->a));
+}
+
+/* FP4 copy w=x */
+/* SU= 16 */
+void YYY::FP4_copy(FP4 *w,FP4 *x)
+{
+    if (w==x) return;
+    FP2_copy(&(w->a), &(x->a));
+    FP2_copy(&(w->b), &(x->b));
+}
+
+/* FP4 w=0 */
+/* SU= 8 */
+void YYY::FP4_zero(FP4 *w)
+{
+    FP2_zero(&(w->a));
+    FP2_zero(&(w->b));
+}
+
+/* FP4 w=1 */
+/* SU= 8 */
+void YYY::FP4_one(FP4 *w)
+{
+    FP2_one(&(w->a));
+    FP2_zero(&(w->b));
+}
+
+/* Set w=-x */
+/* SU= 160 */
+void YYY::FP4_neg(FP4 *w,FP4 *x)
+{
+    /* Just one field neg */
+    FP2 m,t;
+	FP4_norm(x);
+
+    FP2_add(&m,&(x->a),&(x->b));
+//	FP2_norm(&m);
+    FP2_neg(&m,&m);
+//    FP2_norm(&m);
+    FP2_add(&t,&m,&(x->b));
+    FP2_add(&(w->b),&m,&(x->a));
+    FP2_copy(&(w->a),&t);
+	FP4_norm(w);
+}
+
+/* Set w=conj(x) */
+/* SU= 16 */
+void YYY::FP4_conj(FP4 *w,FP4 *x)
+{
+    FP2_copy(&(w->a), &(x->a));
+    FP2_neg(&(w->b), &(x->b));
+FP4_norm(w);
+}
+
+/* Set w=-conj(x) */
+/* SU= 16 */
+void YYY::FP4_nconj(FP4 *w,FP4 *x)
+{
+    FP2_copy(&(w->b),&(x->b));
+    FP2_neg(&(w->a), &(x->a));
+FP4_norm(w);
+}
+
+/* Set w=x+y */
+/* SU= 16 */
+void YYY::FP4_add(FP4 *w,FP4 *x,FP4 *y)
+{
+    FP2_add(&(w->a), &(x->a), &(y->a));
+    FP2_add(&(w->b), &(x->b), &(y->b));
+}
+
+/* Set w=x-y */
+/* Input y MUST be normed */
+void YYY::FP4_sub(FP4 *w,FP4 *x,FP4 *y)
+{
+    FP4 my;
+
+    FP4_neg(&my, y);
+    FP4_add(w, x, &my);
+
+}
+/* SU= 8 */
+/* reduce all components of w mod Modulus */
+void YYY::FP4_reduce(FP4 *w)
+{
+    FP2_reduce(&(w->a));
+    FP2_reduce(&(w->b));
+}
+
+/* SU= 8 */
+/* normalise all elements of w */
+void YYY::FP4_norm(FP4 *w)
+{
+    FP2_norm(&(w->a));
+    FP2_norm(&(w->b));
+}
+
+/* Set w=s*x, where s is FP2 */
+/* SU= 16 */
+void YYY::FP4_pmul(FP4 *w,FP4 *x,FP2 *s)
+{
+    FP2_mul(&(w->a),&(x->a),s);
+    FP2_mul(&(w->b),&(x->b),s);
+}
+
+/* Set w=s*x, where s is FP */
+void YYY::FP4_qmul(FP4 *w,FP4 *x,FP *s)
+{
+    FP2_pmul(&(w->a),&(x->a),s);
+    FP2_pmul(&(w->b),&(x->b),s);
+}
+
+/* SU= 16 */
+/* Set w=s*x, where s is int */
+void YYY::FP4_imul(FP4 *w,FP4 *x,int s)
+{
+    FP2_imul(&(w->a),&(x->a),s);
+    FP2_imul(&(w->b),&(x->b),s);
+}
+
+/* Set w=x^2 */
+/* Input MUST be normed  */
+void YYY::FP4_sqr(FP4 *w,FP4 *x)
+{
+    FP2 t1,t2,t3;
+
+    FP2_mul(&t3,&(x->a),&(x->b)); /* norms x */
+    FP2_copy(&t2,&(x->b));
+    FP2_add(&t1,&(x->a),&(x->b));
+    FP2_mul_ip(&t2);
+
+    FP2_add(&t2,&(x->a),&t2);
+
+	FP2_norm(&t1);  // 2
+	FP2_norm(&t2);  // 2
+
+    FP2_mul(&(w->a),&t1,&t2);
+
+    FP2_copy(&t2,&t3);
+    FP2_mul_ip(&t2);
+
+    FP2_add(&t2,&t2,&t3);
+
+	FP2_norm(&t2);  // 2
+    FP2_neg(&t2,&t2);
+    FP2_add(&(w->a),&(w->a),&t2);  /* a=(a+b)(a+i^2.b)-i^2.ab-ab = a*a+ib*ib */
+    FP2_add(&(w->b),&t3,&t3);  /* b=2ab */
+
+    FP4_norm(w);
+}
+
+/* Set w=x*y */
+/* Inputs MUST be normed  */
+void YYY::FP4_mul(FP4 *w,FP4 *x,FP4 *y)
+{
+
+    FP2 t1,t2,t3,t4;
+
+    FP2_mul(&t1,&(x->a),&(y->a)); 
+
+    FP2_mul(&t2,&(x->b),&(y->b)); 
+//printf("Into 4 mul 0a\n");
+    FP2_add(&t3,&(y->b),&(y->a));
+//printf("Into 4 mul 0b\n");
+    FP2_add(&t4,&(x->b),&(x->a));
+
+	FP2_norm(&t4); // 2
+	FP2_norm(&t3); // 2
+
+    FP2_mul(&t4,&t4,&t3); /* (xa+xb)(ya+yb) */
+
+	FP2_neg(&t3,&t1);  // 1
+	FP2_add(&t4,&t4,&t3);  //t4E=3
+    FP2_norm(&t4);
+
+	FP2_neg(&t3,&t2);  // 1
+	FP2_add(&(w->b),&t4,&t3); //wbE=3
+
+    FP2_mul_ip(&t2);
+    FP2_add(&(w->a),&t2,&t1);
+
+    FP4_norm(w);
+}
+
+/* output FP4 in format [a,b] */
+/* SU= 8 */
+void YYY::FP4_output(FP4 *w)
+{
+    printf("[");
+    FP2_output(&(w->a));
+    printf(",");
+    FP2_output(&(w->b));
+    printf("]");
+}
+
+/* SU= 8 */
+void YYY::FP4_rawoutput(FP4 *w)
+{
+    printf("[");
+    FP2_rawoutput(&(w->a));
+    printf(",");
+    FP2_rawoutput(&(w->b));
+    printf("]");
+}
+
+/* Set w=1/x */
+/* SU= 160 */
+void YYY::FP4_inv(FP4 *w,FP4 *x)
+{
+    FP2 t1,t2;
+    FP2_sqr(&t1,&(x->a));
+    FP2_sqr(&t2,&(x->b));
+    FP2_mul_ip(&t2);
+FP2_norm(&t2);
+    FP2_sub(&t1,&t1,&t2);
+    FP2_inv(&t1,&t1);
+    FP2_mul(&(w->a),&t1,&(x->a));
+    FP2_neg(&t1,&t1);
+FP2_norm(&t1);
+    FP2_mul(&(w->b),&t1,&(x->b));
+}
+
+/* w*=i where i = sqrt(-1+sqrt(-1)) */
+/* SU= 200 */
+void YYY::FP4_times_i(FP4 *w)
+{
+    FP z;
+    FP2 s,t;
+
+//    FP4_norm(w);
+    FP2_copy(&t,&(w->b));
+
+    FP2_copy(&s,&t);
+
+    FP_copy(&z,&(s.a));
+    FP_neg(&(s.a),&(s.b));
+    FP_copy(&(s.b),&z);
+
+    FP2_add(&t,&t,&s);
+
+    FP2_copy(&(w->b),&(w->a));
+    FP2_copy(&(w->a),&t);
+	FP4_norm(w);
+}
+
+/* Set w=w^p using Frobenius */
+/* SU= 16 */
+void YYY::FP4_frob(FP4 *w,FP2 *f)
+{
+    FP2_conj(&(w->a),&(w->a));
+    FP2_conj(&(w->b),&(w->b));
+    FP2_mul( &(w->b),f,&(w->b));
+}
+
+/* Set r=a^b mod m */
+/* SU= 240 */
+void YYY::FP4_pow(FP4 *r,FP4* a,BIG b)
+{
+    FP4 w;
+    BIG z,zilch;
+    int bt;
+
+    BIG_zero(zilch);
+    BIG_copy(z,b);
+    BIG_norm(z);
+    FP4_copy(&w,a);
+	FP4_norm(&w);
+    FP4_one(r);
+
+    while(1)
+    {
+        bt=BIG_parity(z);
+        BIG_shr(z,1);
+        if (bt) FP4_mul(r,r,&w);
+        if (BIG_comp(z,zilch)==0) break;
+        FP4_sqr(&w,&w);
+    }
+    FP4_reduce(r);
+}
+
+#if CURVE_SECURITY_ZZZ == 128
+
+/* SU= 304 */
+/* XTR xtr_a function */
+void YYY::FP4_xtr_A(FP4 *r,FP4 *w,FP4 *x,FP4 *y,FP4 *z)
+{
+    FP4 t1,t2;
+
+    FP4_copy(r,x);
+//FP4_norm(y);
+    FP4_sub(&t1,w,y);
+FP4_norm(&t1);
+    FP4_pmul(&t1,&t1,&(r->a));
+    FP4_add(&t2,w,y);
+FP4_norm(&t2);
+    FP4_pmul(&t2,&t2,&(r->b));
+    FP4_times_i(&t2);
+
+    FP4_add(r,&t1,&t2);
+    FP4_add(r,r,z);
+
+    FP4_reduce(r);
+}
+
+/* SU= 152 */
+/* XTR xtr_d function */
+void YYY::FP4_xtr_D(FP4 *r,FP4 *x)
+{
+    FP4 w;
+    FP4_copy(r,x);
+    FP4_conj(&w,r);
+    FP4_add(&w,&w,&w);
+    FP4_sqr(r,r);
+FP4_norm(&w);
+    FP4_sub(r,r,&w);
+    FP4_reduce(r);    /* reduce here as multiple calls trigger automatic reductions */
+}
+
+/* SU= 728 */
+/* r=x^n using XTR method on traces of FP12s */
+void YYY::FP4_xtr_pow(FP4 *r,FP4 *x,BIG n)
+{
+    int i,par,nb;
+    BIG v;
+    FP2 w;
+    FP4 t,a,b,c,sf;
+
+    BIG_zero(v);
+    BIG_inc(v,3);
+	BIG_norm(v);
+    FP2_from_BIG(&w,v);
+    FP4_from_FP2(&a,&w);
+    FP4_copy(&sf,x);
+	FP4_norm(&sf);
+	FP4_copy(&b,&sf);
+    FP4_xtr_D(&c,&sf);
+
+    //BIG_norm(n);
+    par=BIG_parity(n);
+    BIG_copy(v,n);
+	BIG_norm(v);
+    BIG_shr(v,1);
+    if (par==0)
+    {
+        BIG_dec(v,1);
+        BIG_norm(v);
+    }
+
+    nb=BIG_nbits(v);
+    for (i=nb-1; i>=0; i--)
+    {
+        if (!BIG_bit(v,i))
+        {
+            FP4_copy(&t,&b);
+            FP4_conj(&sf,&sf);
+            FP4_conj(&c,&c);
+            FP4_xtr_A(&b,&a,&b,&sf,&c);
+            FP4_conj(&sf,&sf);
+            FP4_xtr_D(&c,&t);
+            FP4_xtr_D(&a,&a);
+        }
+        else
+        {
+            FP4_conj(&t,&a);
+            FP4_xtr_D(&a,&b);
+            FP4_xtr_A(&b,&c,&b,&sf,&t);
+            FP4_xtr_D(&c,&c);
+        }
+    }
+
+    if (par==0) FP4_copy(r,&c);
+    else FP4_copy(r,&b);
+    FP4_reduce(r);
+}
+
+/* SU= 872 */
+/* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */
+void YYY::FP4_xtr_pow2(FP4 *r,FP4 *ck,FP4 *cl,FP4 *ckml,FP4 *ckm2l,BIG a,BIG b)
+{
+    int i,f2;
+    BIG d,e,w;
+    FP4 t,cu,cv,cumv,cum2v;
+
+
+    BIG_copy(e,a);
+    BIG_copy(d,b);
+    BIG_norm(e);
+	BIG_norm(d);
+    FP4_copy(&cu,ck);
+    FP4_copy(&cv,cl);
+    FP4_copy(&cumv,ckml);
+    FP4_copy(&cum2v,ckm2l);
+
+    f2=0;
+    while (BIG_parity(d)==0 && BIG_parity(e)==0)
+    {
+        BIG_shr(d,1);
+        BIG_shr(e,1);
+        f2++;
+    }
+    while (BIG_comp(d,e)!=0)
+    {
+        if (BIG_comp(d,e)>0)
+        {
+            BIG_imul(w,e,4);
+            BIG_norm(w);
+            if (BIG_comp(d,w)<=0)
+            {
+                BIG_copy(w,d);
+                BIG_copy(d,e);
+                BIG_sub(e,w,e);
+                BIG_norm(e);
+                FP4_xtr_A(&t,&cu,&cv,&cumv,&cum2v);
+                FP4_conj(&cum2v,&cumv);
+                FP4_copy(&cumv,&cv);
+                FP4_copy(&cv,&cu);
+                FP4_copy(&cu,&t);
+            }
+            else if (BIG_parity(d)==0)
+            {
+                BIG_shr(d,1);
+                FP4_conj(r,&cum2v);
+                FP4_xtr_A(&t,&cu,&cumv,&cv,r);
+                FP4_xtr_D(&cum2v,&cumv);
+                FP4_copy(&cumv,&t);
+                FP4_xtr_D(&cu,&cu);
+            }
+            else if (BIG_parity(e)==1)
+            {
+                BIG_sub(d,d,e);
+                BIG_norm(d);
+                BIG_shr(d,1);
+                FP4_xtr_A(&t,&cu,&cv,&cumv,&cum2v);
+                FP4_xtr_D(&cu,&cu);
+                FP4_xtr_D(&cum2v,&cv);
+                FP4_conj(&cum2v,&cum2v);
+                FP4_copy(&cv,&t);
+            }
+            else
+            {
+                BIG_copy(w,d);
+                BIG_copy(d,e);
+                BIG_shr(d,1);
+                BIG_copy(e,w);
+                FP4_xtr_D(&t,&cumv);
+                FP4_conj(&cumv,&cum2v);
+                FP4_conj(&cum2v,&t);
+                FP4_xtr_D(&t,&cv);
+                FP4_copy(&cv,&cu);
+                FP4_copy(&cu,&t);
+            }
+        }
+        if (BIG_comp(d,e)<0)
+        {
+            BIG_imul(w,d,4);
+            BIG_norm(w);
+            if (BIG_comp(e,w)<=0)
+            {
+                BIG_sub(e,e,d);
+                BIG_norm(e);
+                FP4_xtr_A(&t,&cu,&cv,&cumv,&cum2v);
+                FP4_copy(&cum2v,&cumv);
+                FP4_copy(&cumv,&cu);
+                FP4_copy(&cu,&t);
+            }
+            else if (BIG_parity(e)==0)
+            {
+                BIG_copy(w,d);
+                BIG_copy(d,e);
+                BIG_shr(d,1);
+                BIG_copy(e,w);
+                FP4_xtr_D(&t,&cumv);
+                FP4_conj(&cumv,&cum2v);
+                FP4_conj(&cum2v,&t);
+                FP4_xtr_D(&t,&cv);
+                FP4_copy(&cv,&cu);
+                FP4_copy(&cu,&t);
+            }
+            else if (BIG_parity(d)==1)
+            {
+                BIG_copy(w,e);
+                BIG_copy(e,d);
+                BIG_sub(w,w,d);
+                BIG_norm(w);
+                BIG_copy(d,w);
+                BIG_shr(d,1);
+                FP4_xtr_A(&t,&cu,&cv,&cumv,&cum2v);
+                FP4_conj(&cumv,&cumv);
+                FP4_xtr_D(&cum2v,&cu);
+                FP4_conj(&cum2v,&cum2v);
+                FP4_xtr_D(&cu,&cv);
+                FP4_copy(&cv,&t);
+            }
+            else
+            {
+                BIG_shr(d,1);
+                FP4_conj(r,&cum2v);
+                FP4_xtr_A(&t,&cu,&cumv,&cv,r);
+                FP4_xtr_D(&cum2v,&cumv);
+                FP4_copy(&cumv,&t);
+                FP4_xtr_D(&cu,&cu);
+            }
+        }
+    }
+    FP4_xtr_A(r,&cu,&cv,&cumv,&cum2v);
+    for (i=0; i<f2; i++)	FP4_xtr_D(r,r);
+    FP4_xtr_pow(r,r,d);
+}
+
+#endif
+
+/* New stuff for ECp4 support */
+
+/* Set w=x/2 */
+void YYY::FP4_div2(FP4 *w,FP4 *x)
+{
+    FP2_div2(&(w->a),&(x->a));
+    FP2_div2(&(w->b),&(x->b));
+}
+
+/* Move b to a if d=1 */
+void YYY::FP4_cmove(FP4 *f,FP4 *g,int d)
+{
+    FP2_cmove(&(f->a),&(g->a),d);
+    FP2_cmove(&(f->b),&(g->b),d);
+}
+
+#if CURVE_SECURITY_ZZZ >= 192
+
+/* sqrt(a+xb) = sqrt((a+sqrt(a*a-n*b*b))/2)+x.b/(2*sqrt((a+sqrt(a*a-n*b*b))/2)) */
+/* returns true if x is QR */
+int YYY::FP4_sqrt(FP4 *r,FP4* x)
+{
+	FP2 a,s,t;
+
+	FP4_copy(r,x);
+	if (FP4_iszilch(x))
+		return 1;
+	
+	FP2_copy(&a,&(x->a));
+	FP2_copy(&s,&(x->b));
+
+	if (FP2_iszilch(&s))
+	{
+		if (FP2_sqrt(&t,&a))
+		{
+			FP4_from_FP2(r,&t);
+		}
+		else
+		{
+			FP2_div_ip(&a);
+			FP2_sqrt(&t,&a);
+			FP4_from_FP2H(r,&t);
+		}
+		return 1;
+	}
+
+	FP2_sqr(&s,&s);  // s*=s
+	FP2_sqr(&a,&a);  // a*=a
+	FP2_mul_ip(&s);
+	FP2_norm(&s);
+	FP2_sub(&a,&a,&s); // a-=txx(s)
+
+	if (!FP2_sqrt(&s,&a)) return 0;
+
+	//FP2_sqr(&t,&s);
+
+
+	FP2_copy(&t,&(x->a));
+	FP2_add(&a,&t,&s);
+	FP2_norm(&a);
+	FP2_div2(&a,&a);
+
+	if (!FP2_sqrt(&a,&a))
+	{
+		FP2_sub(&a,&t,&s);
+		FP2_norm(&a);
+		FP2_div2(&a,&a);
+		if (!FP2_sqrt(&a,&a)) return 0;
+	}
+
+	FP2_copy(&t,&(x->b));
+	FP2_add(&s,&a,&a);
+	FP2_inv(&s,&s);
+
+	FP2_mul(&t,&t,&s);
+	FP4_from_FP2s(r,&a,&t);
+
+	return 1;
+
+}
+
+void YYY::FP4_div_i(FP4 *f)
+{
+	FP2 u,v;
+	FP2_copy(&u,&(f->a));
+	FP2_copy(&v,&(f->b));
+	FP2_div_ip(&u);
+	FP2_copy(&(f->a),&v);
+	FP2_copy(&(f->b),&u);
+}
+
+void YYY::FP4_div_2i(FP4 *f)
+{
+	FP2 u,v;
+	FP2_copy(&u,&(f->a));
+	FP2_copy(&v,&(f->b));
+	FP2_div_ip2(&u);
+	FP2_add(&v,&v,&v);
+	FP2_norm(&v);
+	FP2_copy(&(f->a),&v);
+	FP2_copy(&(f->b),&u);
+}
+
+
+#endif
+
+/*
+int main(){
+		FP2 w0,w1,f;
+		FP4 w,t;
+		FP4 c1,c2,c3,c4,cr;
+		BIG a,b;
+		BIG e,e1,e2;
+		BIG p,md;
+
+
+		BIG_rcopy(md,Modulus);
+		//Test w^(P^4) = w mod p^2
+		BIG_zero(a); BIG_inc(a,27);
+		BIG_zero(b); BIG_inc(b,45);
+		FP2_from_BIGs(&w0,a,b);
+
+		BIG_zero(a); BIG_inc(a,33);
+		BIG_zero(b); BIG_inc(b,54);
+		FP2_from_BIGs(&w1,a,b);
+
+		FP4_from_FP2s(&w,&w0,&w1);
+		FP4_reduce(&w);
+
+		printf("w= ");
+		FP4_output(&w);
+		printf("\n");
+
+
+		FP4_copy(&t,&w);
+
+
+		BIG_copy(p,md);
+		FP4_pow(&w,&w,p);
+
+		printf("w^p= ");
+		FP4_output(&w);
+		printf("\n");
+//exit(0);
+
+		BIG_rcopy(a,CURVE_Fra);
+		BIG_rcopy(b,CURVE_Frb);
+		FP2_from_BIGs(&f,a,b);
+
+		FP4_frob(&t,&f);
+		printf("w^p= ");
+		FP4_output(&t);
+		printf("\n");
+
+		FP4_pow(&w,&w,p);
+		FP4_pow(&w,&w,p);
+		FP4_pow(&w,&w,p);
+		printf("w^p4= ");
+		FP4_output(&w);
+		printf("\n");
+
+// Test 1/(1/x) = x mod p^4
+		FP4_from_FP2s(&w,&w0,&w1);
+		printf("Test Inversion \nw= ");
+		FP4_output(&w);
+		printf("\n");
+
+		FP4_inv(&w,&w);
+		printf("1/w mod p^4 = ");
+		FP4_output(&w);
+		printf("\n");
+
+		FP4_inv(&w,&w);
+		printf("1/(1/w) mod p^4 = ");
+		FP4_output(&w);
+		printf("\n");
+
+		BIG_zero(e); BIG_inc(e,12);
+
+
+
+	//	FP4_xtr_A(&w,&t,&w,&t,&t);
+		FP4_xtr_pow(&w,&w,e);
+
+		printf("w^e= ");
+		FP4_output(&w);
+		printf("\n");
+
+
+		BIG_zero(a); BIG_inc(a,37);
+		BIG_zero(b); BIG_inc(b,17);
+		FP2_from_BIGs(&w0,a,b);
+
+		BIG_zero(a); BIG_inc(a,49);
+		BIG_zero(b); BIG_inc(b,31);
+		FP2_from_BIGs(&w1,a,b);
+
+		FP4_from_FP2s(&c1,&w0,&w1);
+		FP4_from_FP2s(&c2,&w0,&w1);
+		FP4_from_FP2s(&c3,&w0,&w1);
+		FP4_from_FP2s(&c4,&w0,&w1);
+
+		BIG_zero(e1); BIG_inc(e1,3331);
+		BIG_zero(e2); BIG_inc(e2,3372);
+
+		FP4_xtr_pow2(&w,&c1,&w,&c2,&c3,e1,e2);
+
+		printf("c^e= ");
+		FP4_output(&w);
+		printf("\n");
+
+
+		return 0;
+}
+*/
+
diff --git a/version3/cpp/fp4.h b/version3/cpp/fp4.h
new file mode 100644
index 0000000..ffd728c
--- /dev/null
+++ b/version3/cpp/fp4.h
@@ -0,0 +1,286 @@
+#ifndef FP4_YYY_H
+#define FP4_YYY_H
+
+#include "fp2_YYY.h"
+#include "config_curve_ZZZ.h"
+
+using namespace amcl;
+
+namespace YYY{
+
+/**
+	@brief FP4 Structure - towered over two FP2
+*/
+
+typedef struct
+{
+    FP2 a; /**< real part of FP4 */
+    FP2 b; /**< imaginary part of FP4 */
+} FP4;
+
+
+/* FP4 prototypes */
+/**	@brief Tests for FP4 equal to zero
+ *
+	@param x FP4 number to be tested
+	@return 1 if zero, else returns 0
+ */
+extern int FP4_iszilch(FP4 *x);
+/**	@brief Tests for FP4 equal to unity
+ *
+	@param x FP4 number to be tested
+	@return 1 if unity, else returns 0
+ */
+extern int FP4_isunity(FP4 *x);
+/**	@brief Tests for equality of two FP4s
+ *
+	@param x FP4 instance to be compared
+	@param y FP4 instance to be compared
+	@return 1 if x=y, else returns 0
+ */
+extern int FP4_equals(FP4 *x,FP4 *y);
+/**	@brief Tests for FP4 having only a real part and no imaginary part
+ *
+	@param x FP4 number to be tested
+	@return 1 if real, else returns 0
+ */
+extern int FP4_isreal(FP4 *x);
+/**	@brief Initialise FP4 from two FP2s
+ *
+	@param x FP4 instance to be initialised
+	@param a FP2 to form real part of FP4
+	@param b FP2 to form imaginary part of FP4
+ */
+extern void FP4_from_FP2s(FP4 *x,FP2 *a,FP2 *b);
+/**	@brief Initialise FP4 from single FP2
+ *
+	Imaginary part is set to zero
+	@param x FP4 instance to be initialised
+	@param a FP2 to form real part of FP4
+ */
+extern void FP4_from_FP2(FP4 *x,FP2 *a);
+
+/**	@brief Initialise FP4 from single FP2
+ *
+	real part is set to zero
+	@param x FP4 instance to be initialised
+	@param a FP2 to form imaginary part of FP4
+ */
+extern void FP4_from_FP2H(FP4 *x,FP2 *a);
+
+
+/**	@brief Copy FP4 to another FP4
+ *
+	@param x FP4 instance, on exit = y
+	@param y FP4 instance to be copied
+ */
+extern void FP4_copy(FP4 *x,FP4 *y);
+/**	@brief Set FP4 to zero
+ *
+	@param x FP4 instance to be set to zero
+ */
+extern void FP4_zero(FP4 *x);
+/**	@brief Set FP4 to unity
+ *
+	@param x FP4 instance to be set to one
+ */
+extern void FP4_one(FP4 *x);
+/**	@brief Negation of FP4
+ *
+	@param x FP4 instance, on exit = -y
+	@param y FP4 instance
+ */
+extern void FP4_neg(FP4 *x,FP4 *y);
+/**	@brief Conjugation of FP4
+ *
+	If y=(a,b) on exit x=(a,-b)
+	@param x FP4 instance, on exit = conj(y)
+	@param y FP4 instance
+ */
+extern void FP4_conj(FP4 *x,FP4 *y);
+/**	@brief Negative conjugation of FP4
+ *
+	If y=(a,b) on exit x=(-a,b)
+	@param x FP4 instance, on exit = -conj(y)
+	@param y FP4 instance
+ */
+extern void FP4_nconj(FP4 *x,FP4 *y);
+/**	@brief addition of two FP4s
+ *
+	@param x FP4 instance, on exit = y+z
+	@param y FP4 instance
+	@param z FP4 instance
+ */
+extern void FP4_add(FP4 *x,FP4 *y,FP4 *z);
+/**	@brief subtraction of two FP4s
+ *
+	@param x FP4 instance, on exit = y-z
+	@param y FP4 instance
+	@param z FP4 instance
+ */
+extern void FP4_sub(FP4 *x,FP4 *y,FP4 *z);
+/**	@brief Multiplication of an FP4 by an FP2
+ *
+	@param x FP4 instance, on exit = y*a
+	@param y FP4 instance
+	@param a FP2 multiplier
+ */
+extern void FP4_pmul(FP4 *x,FP4 *y,FP2 *a);
+
+/**	@brief Multiplication of an FP4 by an FP
+ *
+	@param x FP4 instance, on exit = y*a
+	@param y FP4 instance
+	@param a FP multiplier
+ */
+extern void FP4_qmul(FP4 *x,FP4 *y,FP *a);
+
+/**	@brief Multiplication of an FP4 by a small integer
+ *
+	@param x FP4 instance, on exit = y*i
+	@param y FP4 instance
+	@param i an integer
+ */
+extern void FP4_imul(FP4 *x,FP4 *y,int i);
+/**	@brief Squaring an FP4
+ *
+	@param x FP4 instance, on exit = y^2
+	@param y FP4 instance
+ */
+extern void FP4_sqr(FP4 *x,FP4 *y);
+/**	@brief Multiplication of two FP4s
+ *
+	@param x FP4 instance, on exit = y*z
+	@param y FP4 instance
+	@param z FP4 instance
+ */
+extern void FP4_mul(FP4 *x,FP4 *y,FP4 *z);
+/**	@brief Inverting an FP4
+ *
+	@param x FP4 instance, on exit = 1/y
+	@param y FP4 instance
+ */
+extern void FP4_inv(FP4 *x,FP4 *y);
+
+/**	@brief Divide an FP4 by 2
+ *
+	@param x FP4 instance, on exit = y/2
+	@param y FP4 instance
+ */
+extern void FP4_div2(FP4 *x,FP4 *y);
+
+
+/**	@brief Formats and outputs an FP4 to the console
+ *
+	@param x FP4 instance to be printed
+ */
+extern void FP4_output(FP4 *x);
+/**	@brief Formats and outputs an FP4 to the console in raw form (for debugging)
+ *
+	@param x FP4 instance to be printed
+ */
+extern void FP4_rawoutput(FP4 *x);
+/**	@brief multiplies an FP4 instance by irreducible polynomial sqrt(1+sqrt(-1))
+ *
+	@param x FP4 instance, on exit = sqrt(1+sqrt(-1)*x
+ */
+extern void FP4_times_i(FP4 *x);
+/**	@brief Normalises the components of an FP4
+ *
+	@param x FP4 instance to be normalised
+ */
+extern void FP4_norm(FP4 *x);
+/**	@brief Reduces all components of possibly unreduced FP4 mod Modulus
+ *
+	@param x FP4 instance, on exit reduced mod Modulus
+ */
+extern void FP4_reduce(FP4 *x);
+/**	@brief Raises an FP4 to the power of a BIG
+ *
+	@param x FP4 instance, on exit = y^b
+	@param y FP4 instance
+	@param b BIG number
+ */
+extern void FP4_pow(FP4 *x,FP4 *y,XXX::BIG b);
+/**	@brief Raises an FP4 to the power of the internal modulus p, using the Frobenius
+ *
+	@param x FP4 instance, on exit = x^p
+	@param f FP2 precalculated Frobenius constant
+ */
+extern void FP4_frob(FP4 *x,FP2 *f);
+/**	@brief Calculates the XTR addition function r=w*x-conj(x)*y+z
+ *
+	@param r FP4 instance, on exit = w*x-conj(x)*y+z
+	@param w FP4 instance
+	@param x FP4 instance
+	@param y FP4 instance
+	@param z FP4 instance
+ */
+extern void FP4_xtr_A(FP4 *r,FP4 *w,FP4 *x,FP4 *y,FP4 *z);
+/**	@brief Calculates the XTR doubling function r=x^2-2*conj(x)
+ *
+	@param r FP4 instance, on exit = x^2-2*conj(x)
+	@param x FP4 instance
+ */
+extern void FP4_xtr_D(FP4 *r,FP4 *x);
+/**	@brief Calculates FP4 trace of an FP12 raised to the power of a BIG number
+ *
+	XTR single exponentiation
+	@param r FP4 instance, on exit = trace(w^b)
+	@param x FP4 instance, trace of an FP12 w
+	@param b BIG number
+ */
+extern void FP4_xtr_pow(FP4 *r,FP4 *x,XXX::BIG b);
+/**	@brief Calculates FP4 trace of c^a.d^b, where c and d are derived from FP4 traces of FP12s
+ *
+	XTR double exponentiation
+	Assumes c=tr(x^m), d=tr(x^n), e=tr(x^(m-n)), f=tr(x^(m-2n))
+	@param r FP4 instance, on exit = trace(c^a.d^b)
+	@param c FP4 instance, trace of an FP12
+	@param d FP4 instance, trace of an FP12
+	@param e FP4 instance, trace of an FP12
+	@param f FP4 instance, trace of an FP12
+	@param a BIG number
+	@param b BIG number
+ */
+extern void FP4_xtr_pow2(FP4 *r,FP4 *c,FP4 *d,FP4 *e,FP4 *f,XXX::BIG a,XXX::BIG b);
+
+
+/**	@brief Calculate square root of an FP4
+ *
+	Square root
+	@param r FP4 instance, on exit = sqrt(x)
+	@param x FP4 instance
+	@return 1 x is a QR, otherwise 0
+ */
+extern int  FP4_sqrt(FP4 *r,FP4 *x);
+
+
+/**	@brief Conditional copy of FP4 number
+ *
+	Conditionally copies second parameter to the first (without branching)
+	@param x FP4 instance, set to y if s!=0
+	@param y another FP4 instance
+	@param s copy only takes place if not equal to 0
+ */
+extern void FP4_cmove(FP4 *x,FP4 *y,int s);
+
+
+/**	@brief Divide FP4 number by QNR
+ *
+	Divide FP4 by the QNR
+	@param x FP4 instance
+ */
+extern void FP4_div_i(FP4 *x);
+
+/**	@brief Divide an FP4 by QNR/2
+ *
+	Divide FP4 by the QNR/2
+	@param x FP4 instance
+ */
+extern void FP4_div_2i(FP4 *x);
+
+}
+
+#endif
+
diff --git a/version3/cpp/fp48.cpp b/version3/cpp/fp48.cpp
new file mode 100644
index 0000000..904935e
--- /dev/null
+++ b/version3/cpp/fp48.cpp
@@ -0,0 +1,1389 @@
+/*
+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.
+*/
+
+/* AMCL Fp^12 functions */
+/* SU=m, m is Stack Usage (no lazy )*/
+/* FP48 elements are of the form a+i.b+i^2.c */
+
+#include "fp48_YYY.h"
+
+using namespace XXX;
+
+/* return 1 if b==c, no branching */
+static int teq(sign32 b,sign32 c)
+{
+    sign32 x=b^c;
+    x-=1;  // if x=0, x now -1
+    return (int)((x>>31)&1);
+}
+
+
+/* Constant time select from pre-computed table */
+static void FP48_select(YYY::FP48 *f,YYY::FP48 g[],sign32 b)
+{
+    YYY::FP48 invf;
+    sign32 m=b>>31;
+    sign32 babs=(b^m)-m;
+
+    babs=(babs-1)/2;
+
+    FP48_cmove(f,&g[0],teq(babs,0));  // conditional move
+    FP48_cmove(f,&g[1],teq(babs,1));
+    FP48_cmove(f,&g[2],teq(babs,2));
+    FP48_cmove(f,&g[3],teq(babs,3));
+    FP48_cmove(f,&g[4],teq(babs,4));
+    FP48_cmove(f,&g[5],teq(babs,5));
+    FP48_cmove(f,&g[6],teq(babs,6));
+    FP48_cmove(f,&g[7],teq(babs,7));
+
+    FP48_copy(&invf,f);
+    FP48_conj(&invf,&invf);  // 1/f
+    FP48_cmove(f,&invf,(int)(m&1));
+}
+
+
+/* test x==0 ? */
+/* SU= 8 */
+int YYY::FP48_iszilch(FP48 *x)
+{
+    if (FP16_iszilch(&(x->a)) && FP16_iszilch(&(x->b)) && FP16_iszilch(&(x->c))) return 1;
+    return 0;
+}
+
+/* test x==1 ? */
+/* SU= 8 */
+int YYY::FP48_isunity(FP48 *x)
+{
+    if (FP16_isunity(&(x->a)) && FP16_iszilch(&(x->b)) && FP16_iszilch(&(x->c))) return 1;
+    return 0;
+}
+
+/* FP48 copy w=x */
+/* SU= 16 */
+void YYY::FP48_copy(FP48 *w,FP48 *x)
+{
+    if (x==w) return;
+    FP16_copy(&(w->a),&(x->a));
+    FP16_copy(&(w->b),&(x->b));
+    FP16_copy(&(w->c),&(x->c));
+}
+
+/* FP48 w=1 */
+/* SU= 8 */
+void YYY::FP48_one(FP48 *w)
+{
+    FP16_one(&(w->a));
+    FP16_zero(&(w->b));
+    FP16_zero(&(w->c));
+}
+
+/* return 1 if x==y, else 0 */
+/* SU= 16 */
+int YYY::FP48_equals(FP48 *x,FP48 *y)
+{
+    if (FP16_equals(&(x->a),&(y->a)) && FP16_equals(&(x->b),&(y->b)) && FP16_equals(&(x->b),&(y->b)))
+        return 1;
+    return 0;
+}
+
+/* Set w=conj(x) */
+/* SU= 8 */
+void YYY::FP48_conj(FP48 *w,FP48 *x)
+{
+    FP48_copy(w,x);
+    FP16_conj(&(w->a),&(w->a));
+    FP16_nconj(&(w->b),&(w->b));
+    FP16_conj(&(w->c),&(w->c));
+}
+
+/* Create FP48 from FP16 */
+/* SU= 8 */
+void YYY::FP48_from_FP16(FP48 *w,FP16 *a)
+{
+    FP16_copy(&(w->a),a);
+    FP16_zero(&(w->b));
+    FP16_zero(&(w->c));
+}
+
+/* Create FP48 from 3 FP16's */
+/* SU= 16 */
+void YYY::FP48_from_FP16s(FP48 *w,FP16 *a,FP16 *b,FP16 *c)
+{
+    FP16_copy(&(w->a),a);
+    FP16_copy(&(w->b),b);
+    FP16_copy(&(w->c),c);
+}
+
+/* Granger-Scott Unitary Squaring. This does not benefit from lazy reduction */
+/* SU= 600 */
+void YYY::FP48_usqr(FP48 *w,FP48 *x)
+{
+    FP16 A,B,C,D;
+
+    FP16_copy(&A,&(x->a));
+
+    FP16_sqr(&(w->a),&(x->a));
+    FP16_add(&D,&(w->a),&(w->a));
+    FP16_add(&(w->a),&D,&(w->a));
+
+    FP16_norm(&(w->a));
+    FP16_nconj(&A,&A);
+
+    FP16_add(&A,&A,&A);
+    FP16_add(&(w->a),&(w->a),&A);
+    FP16_sqr(&B,&(x->c));
+    FP16_times_i(&B);
+
+    FP16_add(&D,&B,&B);
+    FP16_add(&B,&B,&D);
+    FP16_norm(&B);
+
+    FP16_sqr(&C,&(x->b));
+
+    FP16_add(&D,&C,&C);
+    FP16_add(&C,&C,&D);
+
+    FP16_norm(&C);
+    FP16_conj(&(w->b),&(x->b));
+    FP16_add(&(w->b),&(w->b),&(w->b));
+    FP16_nconj(&(w->c),&(x->c));
+
+    FP16_add(&(w->c),&(w->c),&(w->c));
+    FP16_add(&(w->b),&B,&(w->b));
+    FP16_add(&(w->c),&C,&(w->c));
+
+	//FP48_norm(w);
+    FP48_reduce(w);	    /* reduce here as in pow function repeated squarings would trigger multiple reductions */
+}
+
+/* FP48 squaring w=x^2 */
+/* SU= 600 */
+void YYY::FP48_sqr(FP48 *w,FP48 *x)
+{
+    /* Use Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
+
+    FP16 A,B,C,D;
+
+    FP16_sqr(&A,&(x->a));
+    FP16_mul(&B,&(x->b),&(x->c));
+    FP16_add(&B,&B,&B);
+FP16_norm(&B);
+    FP16_sqr(&C,&(x->c));
+
+    FP16_mul(&D,&(x->a),&(x->b));
+    FP16_add(&D,&D,&D);
+
+    FP16_add(&(w->c),&(x->a),&(x->c));
+    FP16_add(&(w->c),&(x->b),&(w->c));
+FP16_norm(&(w->c));	
+
+    FP16_sqr(&(w->c),&(w->c));
+
+    FP16_copy(&(w->a),&A);
+    FP16_add(&A,&A,&B);
+
+    FP16_norm(&A);
+
+    FP16_add(&A,&A,&C);
+    FP16_add(&A,&A,&D);
+
+    FP16_norm(&A);
+
+    FP16_neg(&A,&A);
+    FP16_times_i(&B);
+    FP16_times_i(&C);
+
+    FP16_add(&(w->a),&(w->a),&B);
+    FP16_add(&(w->b),&C,&D);
+    FP16_add(&(w->c),&(w->c),&A);
+
+    FP48_norm(w);
+}
+
+/* FP48 full multiplication w=w*y */
+
+
+/* SU= 896 */
+/* FP48 full multiplication w=w*y */
+void YYY::FP48_mul(FP48 *w,FP48 *y)
+{
+    FP16 z0,z1,z2,z3,t0,t1;
+
+    FP16_mul(&z0,&(w->a),&(y->a));
+    FP16_mul(&z2,&(w->b),&(y->b));  //
+
+    FP16_add(&t0,&(w->a),&(w->b));
+    FP16_add(&t1,&(y->a),&(y->b));  //
+
+FP16_norm(&t0);
+FP16_norm(&t1);
+
+    FP16_mul(&z1,&t0,&t1);
+    FP16_add(&t0,&(w->b),&(w->c));
+    FP16_add(&t1,&(y->b),&(y->c));  //
+
+FP16_norm(&t0);
+FP16_norm(&t1);
+
+    FP16_mul(&z3,&t0,&t1);
+
+    FP16_neg(&t0,&z0);
+    FP16_neg(&t1,&z2);
+
+    FP16_add(&z1,&z1,&t0);   // z1=z1-z0
+//    FP16_norm(&z1);
+    FP16_add(&(w->b),&z1,&t1);
+// z1=z1-z2
+    FP16_add(&z3,&z3,&t1);        // z3=z3-z2
+    FP16_add(&z2,&z2,&t0);        // z2=z2-z0
+
+    FP16_add(&t0,&(w->a),&(w->c));
+    FP16_add(&t1,&(y->a),&(y->c));
+
+FP16_norm(&t0);
+FP16_norm(&t1);
+//printf("Into mul 3a\n");
+    FP16_mul(&t0,&t1,&t0);
+//printf("Into mul 3b\n");
+    FP16_add(&z2,&z2,&t0);
+
+    FP16_mul(&t0,&(w->c),&(y->c));
+    FP16_neg(&t1,&t0);
+
+    FP16_add(&(w->c),&z2,&t1);
+    FP16_add(&z3,&z3,&t1);
+    FP16_times_i(&t0);
+    FP16_add(&(w->b),&(w->b),&t0);
+FP16_norm(&z3);
+    FP16_times_i(&z3);
+    FP16_add(&(w->a),&z0,&z3);
+
+    FP48_norm(w);
+}
+
+/* FP48 multiplication w=w*y */
+/* SU= 744 */
+/* catering for special case that arises from special form of ATE pairing line function */
+void YYY::FP48_smul(FP48 *w,FP48 *y,int type)
+{
+    FP16 z0,z1,z2,z3,t0,t1;
+
+	if (type==D_TYPE)
+	{ // y->c is 0
+
+		FP16_copy(&z3,&(w->b));
+		FP16_mul(&z0,&(w->a),&(y->a));
+
+		FP16_pmul(&z2,&(w->b),&(y->b).a);
+		FP16_add(&(w->b),&(w->a),&(w->b));
+		FP16_copy(&t1,&(y->a));
+		FP8_add(&t1.a,&t1.a,&(y->b).a);
+
+		FP16_norm(&t1);
+		FP16_norm(&(w->b));
+
+		FP16_mul(&(w->b),&(w->b),&t1);
+		FP16_add(&z3,&z3,&(w->c));
+		FP16_norm(&z3);
+		FP16_pmul(&z3,&z3,&(y->b).a);
+		FP16_neg(&t0,&z0);
+		FP16_neg(&t1,&z2);
+
+		FP16_add(&(w->b),&(w->b),&t0);   // z1=z1-z0
+//    FP16_norm(&(w->b));
+		FP16_add(&(w->b),&(w->b),&t1);   // z1=z1-z2
+
+		FP16_add(&z3,&z3,&t1);        // z3=z3-z2
+		FP16_add(&z2,&z2,&t0);        // z2=z2-z0
+
+		FP16_add(&t0,&(w->a),&(w->c));
+
+		FP16_norm(&t0);
+		FP16_norm(&z3);
+
+		FP16_mul(&t0,&(y->a),&t0);
+		FP16_add(&(w->c),&z2,&t0);
+
+		FP16_times_i(&z3);
+		FP16_add(&(w->a),&z0,&z3);
+	}
+
+	if (type==M_TYPE)
+	{ // y->b is zero
+		FP16_mul(&z0,&(w->a),&(y->a));
+		FP16_add(&t0,&(w->a),&(w->b));
+		FP16_norm(&t0);
+
+		FP16_mul(&z1,&t0,&(y->a));
+		FP16_add(&t0,&(w->b),&(w->c));
+		FP16_norm(&t0);
+
+		FP16_pmul(&z3,&t0,&(y->c).b);
+		FP16_times_i(&z3);
+
+		FP16_neg(&t0,&z0);
+		FP16_add(&z1,&z1,&t0);   // z1=z1-z0
+
+		FP16_copy(&(w->b),&z1);
+
+		FP16_copy(&z2,&t0);
+
+		FP16_add(&t0,&(w->a),&(w->c));
+		FP16_add(&t1,&(y->a),&(y->c));
+
+		FP16_norm(&t0);
+		FP16_norm(&t1);
+
+		FP16_mul(&t0,&t1,&t0);
+		FP16_add(&z2,&z2,&t0);
+
+		FP16_pmul(&t0,&(w->c),&(y->c).b);
+		FP16_times_i(&t0);
+		FP16_neg(&t1,&t0);
+		FP16_times_i(&t0);
+
+		FP16_add(&(w->c),&z2,&t1);
+		FP16_add(&z3,&z3,&t1);
+
+		FP16_add(&(w->b),&(w->b),&t0);
+		FP16_norm(&z3);
+		FP16_times_i(&z3);
+		FP16_add(&(w->a),&z0,&z3);
+	}
+    FP48_norm(w);
+}
+
+/* Set w=1/x */
+/* SU= 600 */
+void YYY::FP48_inv(FP48 *w,FP48 *x)
+{
+    FP16 f0,f1,f2,f3;
+//    FP48_norm(x);
+
+    FP16_sqr(&f0,&(x->a));
+    FP16_mul(&f1,&(x->b),&(x->c));
+    FP16_times_i(&f1);
+    FP16_sub(&f0,&f0,&f1);  /* y.a */
+	FP16_norm(&f0); 		
+
+    FP16_sqr(&f1,&(x->c));
+    FP16_times_i(&f1);
+    FP16_mul(&f2,&(x->a),&(x->b));
+    FP16_sub(&f1,&f1,&f2);  /* y.b */
+	FP16_norm(&f1); 
+
+    FP16_sqr(&f2,&(x->b));
+    FP16_mul(&f3,&(x->a),&(x->c));
+    FP16_sub(&f2,&f2,&f3);  /* y.c */
+	FP16_norm(&f2); 
+
+    FP16_mul(&f3,&(x->b),&f2);
+    FP16_times_i(&f3);
+    FP16_mul(&(w->a),&f0,&(x->a));
+    FP16_add(&f3,&(w->a),&f3);
+    FP16_mul(&(w->c),&f1,&(x->c));
+    FP16_times_i(&(w->c));
+
+
+
+    FP16_add(&f3,&(w->c),&f3);
+	FP16_norm(&f3);
+	
+    FP16_inv(&f3,&f3);
+    FP16_mul(&(w->a),&f0,&f3);
+    FP16_mul(&(w->b),&f1,&f3);
+    FP16_mul(&(w->c),&f2,&f3);
+
+}
+
+/* constant time powering by small integer of max length bts */
+
+void YYY::FP48_pinpow(FP48 *r,int e,int bts)
+{
+    int i,b;
+    FP48 R[2];
+
+    FP48_one(&R[0]);
+    FP48_copy(&R[1],r);
+
+    for (i=bts-1; i>=0; i--)
+    {
+        b=(e>>i)&1;
+        FP48_mul(&R[1-b],&R[b]);
+        FP48_usqr(&R[b],&R[b]);
+    }
+    FP48_copy(r,&R[0]);
+}
+
+/* Compressed powering of unitary elements y=x^(e mod r) */
+
+void YYY::FP48_compow(FP16 *c,FP48 *x,BIG e,BIG r)
+{
+    FP48 g1,g2;
+	FP16 cp,cpm1,cpm2;
+    FP2 f;
+	BIG q,a,b,m;
+
+    BIG_rcopy(a,Fra);
+    BIG_rcopy(b,Frb);
+    FP2_from_BIGs(&f,a,b);
+
+    BIG_rcopy(q,Modulus);
+
+    FP48_copy(&g1,x);
+	FP48_copy(&g2,x);
+
+    BIG_copy(m,q);
+    BIG_mod(m,r);
+
+    BIG_copy(a,e);
+    BIG_mod(a,m);
+
+    BIG_copy(b,e);
+    BIG_sdiv(b,m);
+
+    FP48_trace(c,&g1);
+
+	if (BIG_iszilch(b))
+	{
+		FP16_xtr_pow(c,c,e);
+		return;
+	}
+
+    FP48_frob(&g2,&f,1);
+    FP48_trace(&cp,&g2);
+    FP48_conj(&g1,&g1);
+    FP48_mul(&g2,&g1);
+    FP48_trace(&cpm1,&g2);
+    FP48_mul(&g2,&g1);
+
+    FP48_trace(&cpm2,&g2);
+
+    FP16_xtr_pow2(c,&cp,c,&cpm1,&cpm2,a,b);
+
+}
+
+/* Note this is simple square and multiply, so not side-channel safe */
+
+void YYY::FP48_pow(FP48 *r,FP48 *a,BIG b)
+{
+    FP48 w,sf;
+    BIG b1,b3;
+    int i,nb,bt;
+	BIG_copy(b1,b);
+    BIG_norm(b1);
+	BIG_pmul(b3,b1,3);
+	BIG_norm(b3);
+
+	FP48_copy(&sf,a);
+	FP48_norm(&sf);
+    FP48_copy(&w,&sf);
+
+	nb=BIG_nbits(b3);
+	for (i=nb-2;i>=1;i--)
+	{
+		FP48_usqr(&w,&w);
+		bt=BIG_bit(b3,i)-BIG_bit(b1,i);
+		if (bt==1)
+			FP48_mul(&w,&sf);
+		if (bt==-1)
+		{
+			FP48_conj(&sf,&sf);
+			FP48_mul(&w,&sf);
+			FP48_conj(&sf,&sf);
+		}
+	}
+
+	FP48_copy(r,&w);
+	FP48_reduce(r);
+}
+
+
+/* SU= 528 */
+/* set r=a^b */
+/* Note this is simple square and multiply, so not side-channel safe 
+
+void YYY::FP48_ppow(FP48 *r,FP48 *a,BIG b)
+{
+    FP48 w;
+    BIG z,zilch;
+    int bt;
+    BIG_zero(zilch);
+    BIG_norm(b);
+    BIG_copy(z,b);
+    FP48_copy(&w,a);
+    FP48_one(r);
+
+    while(1)
+    {
+        bt=BIG_parity(z);
+        BIG_shr(z,1);
+        if (bt)
+		{
+			//printf("In mul\n");
+            FP48_mul(r,&w);
+			//printf("Out of mul\n");
+		}
+        if (BIG_comp(z,zilch)==0) break;
+		//printf("In sqr\n");
+        FP48_sqr(&w,&w);
+		//printf("Out of sqr\n");
+    }
+
+    FP48_reduce(r);
+}  */
+
+/* p=q0^u0.q1^u1.q2^u2.q3^u3... */
+/* Side channel attack secure */
+// Bos & Costello https://eprint.iacr.org/2013/458.pdf
+// Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
+
+void YYY::FP48_pow16(FP48 *p,FP48 *q,BIG u[16])
+{
+    int i,j,k,nb,pb1,pb2,pb3,pb4,bt;
+	FP48 g1[8],g2[8],g3[8],g4[8],r;
+	BIG t[16],mt;
+    sign8 w1[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 s1[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 w2[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 s2[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 w3[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 s3[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 w4[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 s4[NLEN_XXX*BASEBITS_XXX+1];
+    FP fx,fy;
+	FP2 X;
+
+    FP_rcopy(&fx,Fra);
+    FP_rcopy(&fy,Frb);
+    FP2_from_FPs(&X,&fx,&fy);
+
+    for (i=0; i<16; i++)
+        BIG_copy(t[i],u[i]);
+
+// Precomputed table
+    FP48_copy(&g1[0],&q[0]); // q[0]
+    FP48_copy(&g1[1],&g1[0]);
+	FP48_mul(&g1[1],&q[1]);	// q[0].q[1]
+    FP48_copy(&g1[2],&g1[0]);
+	FP48_mul(&g1[2],&q[2]);	// q[0].q[2]
+	FP48_copy(&g1[3],&g1[1]);
+	FP48_mul(&g1[3],&q[2]);	// q[0].q[1].q[2]
+	FP48_copy(&g1[4],&g1[0]);
+	FP48_mul(&g1[4],&q[3]);  // q[0].q[3]
+	FP48_copy(&g1[5],&g1[1]);
+	FP48_mul(&g1[5],&q[3]);	// q[0].q[1].q[3]
+	FP48_copy(&g1[6],&g1[2]);
+	FP48_mul(&g1[6],&q[3]);	// q[0].q[2].q[3]
+	FP48_copy(&g1[7],&g1[3]);
+	FP48_mul(&g1[7],&q[3]);	// q[0].q[1].q[2].q[3]
+
+// Use Frobenius
+
+	for (i=0;i<8;i++)
+	{
+		FP48_copy(&g2[i],&g1[i]);
+		FP48_frob(&g2[i],&X,4);
+
+		FP48_copy(&g3[i],&g2[i]);
+		FP48_frob(&g3[i],&X,4);
+
+		FP48_copy(&g4[i],&g3[i]);
+		FP48_frob(&g4[i],&X,4);
+	}
+
+// Make them odd
+	pb1=1-BIG_parity(t[0]);
+	BIG_inc(t[0],pb1);
+	BIG_norm(t[0]);
+
+	pb2=1-BIG_parity(t[4]);
+	BIG_inc(t[4],pb2);
+	BIG_norm(t[4]);
+
+	pb3=1-BIG_parity(t[8]);
+	BIG_inc(t[8],pb3);
+	BIG_norm(t[8]);
+
+	pb4=1-BIG_parity(t[12]);
+	BIG_inc(t[12],pb4);
+	BIG_norm(t[12]);
+
+// Number of bits
+    BIG_zero(mt);
+    for (i=0; i<16; i++)
+    {
+        BIG_or(mt,mt,t[i]);
+    }
+    nb=1+BIG_nbits(mt);
+
+// Sign pivot 
+	s1[nb-1]=1;
+	s2[nb-1]=1;
+	s3[nb-1]=1;
+	s4[nb-1]=1;
+	for (i=0;i<nb-1;i++)
+	{
+        BIG_fshr(t[0],1);
+		s1[i]=2*BIG_parity(t[0])-1;
+        BIG_fshr(t[4],1);
+		s2[i]=2*BIG_parity(t[4])-1;
+        BIG_fshr(t[8],1);
+		s3[i]=2*BIG_parity(t[8])-1;
+        BIG_fshr(t[12],1);
+		s4[i]=2*BIG_parity(t[12])-1;
+	}
+
+// Recoded exponents
+    for (i=0; i<nb; i++)
+    {
+		w1[i]=0;
+		k=1;
+		for (j=1; j<4; j++)
+		{
+			bt=s1[i]*BIG_parity(t[j]);
+			BIG_fshr(t[j],1);
+
+			BIG_dec(t[j],(bt>>1));
+			BIG_norm(t[j]);
+			w1[i]+=bt*k;
+			k*=2;
+        }
+
+		w2[i]=0;
+		k=1;
+		for (j=5; j<8; j++)
+		{
+			bt=s2[i]*BIG_parity(t[j]);
+			BIG_fshr(t[j],1);
+
+			BIG_dec(t[j],(bt>>1));
+			BIG_norm(t[j]);
+			w2[i]+=bt*k;
+			k*=2;
+        }
+
+		w3[i]=0;
+		k=1;
+		for (j=9; j<12; j++)
+		{
+			bt=s3[i]*BIG_parity(t[j]);
+			BIG_fshr(t[j],1);
+
+			BIG_dec(t[j],(bt>>1));
+			BIG_norm(t[j]);
+			w3[i]+=bt*k;
+			k*=2;
+        }
+
+		w4[i]=0;
+		k=1;
+		for (j=13; j<16; j++)
+		{
+			bt=s4[i]*BIG_parity(t[j]);
+			BIG_fshr(t[j],1);
+
+			BIG_dec(t[j],(bt>>1));
+			BIG_norm(t[j]);
+			w4[i]+=bt*k;
+			k*=2;
+        }
+    }	
+
+// Main loop
+	FP48_select(p,g1,2*w1[nb-1]+1);
+	FP48_select(&r,g2,2*w2[nb-1]+1);
+	FP48_mul(p,&r);
+	FP48_select(&r,g3,2*w3[nb-1]+1);
+	FP48_mul(p,&r);
+	FP48_select(&r,g4,2*w4[nb-1]+1);
+	FP48_mul(p,&r);
+    for (i=nb-2; i>=0; i--)
+    {
+		FP48_usqr(p,p);
+        FP48_select(&r,g1,2*w1[i]+s1[i]);
+        FP48_mul(p,&r);
+        FP48_select(&r,g2,2*w2[i]+s2[i]);
+        FP48_mul(p,&r);
+        FP48_select(&r,g3,2*w3[i]+s3[i]);
+        FP48_mul(p,&r);
+        FP48_select(&r,g4,2*w4[i]+s4[i]);
+        FP48_mul(p,&r);
+    }
+
+// apply correction
+	FP48_conj(&r,&q[0]);   
+	FP48_mul(&r,p);
+	FP48_cmove(p,&r,pb1);
+	FP48_conj(&r,&q[4]);   
+	FP48_mul(&r,p);
+	FP48_cmove(p,&r,pb2);
+
+	FP48_conj(&r,&q[8]);   
+	FP48_mul(&r,p);
+	FP48_cmove(p,&r,pb3);
+	FP48_conj(&r,&q[12]);   
+	FP48_mul(&r,p);
+	FP48_cmove(p,&r,pb4);
+
+	FP48_reduce(p);
+}
+
+/*
+void YYY::FP48_pow16(FP48 *p,FP48 *q,BIG u[16])
+{
+    int i,j,a[4],nb,m;
+    FP48 g[8],f[8],gg[8],ff[8],c,s[2];
+    BIG t[16],mt;
+    sign8 w[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 z[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 ww[NLEN_XXX*BASEBITS_XXX+1];
+    sign8 zz[NLEN_XXX*BASEBITS_XXX+1];
+
+    FP fx,fy;
+	FP2 X;
+
+    FP_rcopy(&fx,Fra);
+    FP_rcopy(&fy,Frb);
+    FP2_from_FPs(&X,&fx,&fy);
+
+    for (i=0; i<16; i++)
+        BIG_copy(t[i],u[i]);
+
+    FP48_copy(&g[0],&q[0]);
+    FP48_conj(&s[0],&q[1]);
+    FP48_mul(&g[0],&s[0]);  // P/Q 
+    FP48_copy(&g[1],&g[0]);
+    FP48_copy(&g[2],&g[0]);
+    FP48_copy(&g[3],&g[0]);
+    FP48_copy(&g[4],&q[0]);
+    FP48_mul(&g[4],&q[1]);  // P*Q 
+    FP48_copy(&g[5],&g[4]);
+    FP48_copy(&g[6],&g[4]);
+    FP48_copy(&g[7],&g[4]);
+
+    FP48_copy(&s[1],&q[2]);
+    FP48_conj(&s[0],&q[3]);
+    FP48_mul(&s[1],&s[0]);       // R/S 
+    FP48_conj(&s[0],&s[1]);
+    FP48_mul(&g[1],&s[0]);
+    FP48_mul(&g[2],&s[1]);
+    FP48_mul(&g[5],&s[0]);
+    FP48_mul(&g[6],&s[1]);
+    FP48_copy(&s[1],&q[2]);
+    FP48_mul(&s[1],&q[3]);      // R*S 
+    FP48_conj(&s[0],&s[1]);
+    FP48_mul(&g[0],&s[0]);
+    FP48_mul(&g[3],&s[1]);
+    FP48_mul(&g[4],&s[0]);
+    FP48_mul(&g[7],&s[1]);
+
+// Use Frobenius
+
+	for (i=0;i<8;i++)
+	{
+		FP48_copy(&f[i],&g[i]);
+		FP48_frob(&f[i],&X,4);
+	}
+
+	for (i=0;i<8;i++)
+	{
+		FP48_copy(&gg[i],&f[i]);
+		FP48_frob(&gg[i],&X,4);
+	}
+
+	for (i=0;i<8;i++)
+	{
+		FP48_copy(&ff[i],&gg[i]);
+		FP48_frob(&ff[i],&X,4);
+	}
+
+
+    // if power is even add 1 to power, and add q to correction 
+    FP48_one(&c);
+
+    BIG_zero(mt);
+    for (i=0; i<16; i++)
+    {
+        if (BIG_parity(t[i])==0)
+        {
+            BIG_inc(t[i],1);
+            BIG_norm(t[i]);
+            FP48_mul(&c,&q[i]);
+        }
+        BIG_add(mt,mt,t[i]);
+        BIG_norm(mt);
+    }
+
+    FP48_conj(&c,&c);
+    nb=1+BIG_nbits(mt);
+
+    // convert exponents to signed 1-bit windows 
+    for (j=0; j<nb; j++)
+    {
+        for (i=0; i<4; i++)
+        {
+            a[i]=BIG_lastbits(t[i],2)-2;
+            BIG_dec(t[i],a[i]);
+            BIG_norm(t[i]);
+            BIG_fshr(t[i],1);
+        }
+        w[j]=8*a[0]+4*a[1]+2*a[2]+a[3];
+    }
+    w[nb]=8*BIG_lastbits(t[0],2)+4*BIG_lastbits(t[1],2)+2*BIG_lastbits(t[2],2)+BIG_lastbits(t[3],2);
+
+
+    for (j=0; j<nb; j++)
+    {
+        for (i=0; i<4; i++)
+        {
+            a[i]=BIG_lastbits(t[i+4],2)-2;
+            BIG_dec(t[i+4],a[i]);
+            BIG_norm(t[i+4]);
+            BIG_fshr(t[i+4],1);
+        }
+        z[j]=8*a[0]+4*a[1]+2*a[2]+a[3];
+    }
+    z[nb]=8*BIG_lastbits(t[4],2)+4*BIG_lastbits(t[5],2)+2*BIG_lastbits(t[6],2)+BIG_lastbits(t[7],2);
+
+    for (j=0; j<nb; j++)
+    {
+        for (i=0; i<4; i++)
+        {
+            a[i]=BIG_lastbits(t[i+8],2)-2;
+            BIG_dec(t[i+8],a[i]);
+            BIG_norm(t[i+8]);
+            BIG_fshr(t[i+8],1);
+        }
+        ww[j]=8*a[0]+4*a[1]+2*a[2]+a[3];
+    }
+    ww[nb]=8*BIG_lastbits(t[8],2)+4*BIG_lastbits(t[9],2)+2*BIG_lastbits(t[10],2)+BIG_lastbits(t[11],2);
+
+    for (j=0; j<nb; j++)
+    {
+        for (i=0; i<4; i++)
+        {
+            a[i]=BIG_lastbits(t[i+12],2)-2;
+            BIG_dec(t[i+12],a[i]);
+            BIG_norm(t[i+12]);
+            BIG_fshr(t[i+12],1);
+        }
+        zz[j]=8*a[0]+4*a[1]+2*a[2]+a[3];
+    }
+    zz[nb]=8*BIG_lastbits(t[12],2)+4*BIG_lastbits(t[13],2)+2*BIG_lastbits(t[14],2)+BIG_lastbits(t[15],2);
+
+    FP48_copy(p,&g[(w[nb]-1)/2]);
+    FP48_mul(p,&f[(z[nb]-1)/2]);
+    FP48_mul(p,&gg[(ww[nb]-1)/2]);
+    FP48_mul(p,&ff[(zz[nb]-1)/2]);
+
+    for (i=nb-1; i>=0; i--)
+    {
+		FP48_usqr(p,p);
+
+        m=w[i]>>7;
+        j=(w[i]^m)-m;  // j=abs(w[i]) 
+        j=(j-1)/2;
+        FP48_copy(&s[0],&g[j]);
+        FP48_conj(&s[1],&g[j]);
+        FP48_mul(p,&s[m&1]);
+
+        m=z[i]>>7;
+        j=(z[i]^m)-m;  // j=abs(w[i]) 
+        j=(j-1)/2;
+        FP48_copy(&s[0],&f[j]);
+        FP48_conj(&s[1],&f[j]);
+        FP48_mul(p,&s[m&1]);
+
+        m=ww[i]>>7;
+        j=(ww[i]^m)-m;  // j=abs(w[i]) 
+        j=(j-1)/2;
+        FP48_copy(&s[0],&gg[j]);
+        FP48_conj(&s[1],&gg[j]);
+        FP48_mul(p,&s[m&1]);
+
+        m=zz[i]>>7;
+        j=(zz[i]^m)-m;  // j=abs(w[i]) 
+        j=(j-1)/2;
+        FP48_copy(&s[0],&ff[j]);
+        FP48_conj(&s[1],&ff[j]);
+        FP48_mul(p,&s[m&1]);
+
+    }
+    FP48_mul(p,&c); // apply correction 
+    FP48_reduce(p);
+}
+*/
+
+/* Set w=w^p using Frobenius */
+/* SU= 160 */
+void YYY::FP48_frob(FP48 *w,FP2 *f,int n)
+{
+	int i;
+	FP8 X2,X4;
+	FP4 F;
+    FP2 f3,f2;				// f=(1+i)^(p-19)/24
+    FP2_sqr(&f2,f);     // 
+    FP2_mul(&f3,&f2,f); // f3=f^3=(1+i)^(p-19)/8
+
+	FP2_mul_ip(&f3);
+	FP2_norm(&f3);
+	FP2_mul_ip(&f3);    // f3 = (1+i)^16/8.(1+i)^(p-19)/8 = (1+i)^(p-3)/8 
+	FP2_norm(&f3);
+
+	for (i=0;i<n;i++)
+	{
+		FP16_frob(&(w->a),&f3);   // a=a^p
+		FP16_frob(&(w->b),&f3);   // b=b^p
+		FP16_frob(&(w->c),&f3);   // c=c^p
+  
+		FP16_qmul(&(w->b),&(w->b),f); FP16_times_i4(&(w->b)); FP16_times_i2(&(w->b)); 
+		FP16_qmul(&(w->c),&(w->c),&f2); FP16_times_i4(&(w->c)); FP16_times_i4(&(w->c)); FP16_times_i4(&(w->c)); 
+
+	}
+}
+
+/* SU= 8 */
+/* normalise all components of w */
+void YYY::FP48_norm(FP48 *w)
+{
+    FP16_norm(&(w->a));
+    FP16_norm(&(w->b));
+    FP16_norm(&(w->c));
+}
+
+/* SU= 8 */
+/* reduce all components of w */
+void YYY::FP48_reduce(FP48 *w)
+{
+    FP16_reduce(&(w->a));
+    FP16_reduce(&(w->b));
+    FP16_reduce(&(w->c));
+}
+
+/* trace function w=trace(x) */
+/* SU= 8 */
+void YYY::FP48_trace(FP16 *w,FP48 *x)
+{
+    FP16_imul(w,&(x->a),3);
+    FP16_reduce(w);
+}
+
+/* SU= 8 */
+/* Output w in hex */
+void YYY::FP48_output(FP48 *w)
+{
+    printf("[");
+    FP16_output(&(w->a));
+    printf(",");
+    FP16_output(&(w->b));
+    printf(",");
+    FP16_output(&(w->c));
+    printf("]");
+}
+
+/* Convert g to octet string w */
+void YYY::FP48_toOctet(octet *W,FP48 *g)
+{
+    BIG a;
+    W->len=48*MODBYTES_XXX;
+
+    FP_redc(a,&(g->a.a.a.a.a));
+    BIG_toBytes(&(W->val[0]),a);
+    FP_redc(a,&(g->a.a.a.a.b));
+    BIG_toBytes(&(W->val[MODBYTES_XXX]),a);
+    
+	FP_redc(a,&(g->a.a.a.b.a));
+    BIG_toBytes(&(W->val[2*MODBYTES_XXX]),a);
+	FP_redc(a,&(g->a.a.a.b.b));
+    BIG_toBytes(&(W->val[3*MODBYTES_XXX]),a);
+
+    FP_redc(a,&(g->a.a.b.a.a));
+    BIG_toBytes(&(W->val[4*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->a.a.b.a.b));
+    BIG_toBytes(&(W->val[5*MODBYTES_XXX]),a);
+
+    FP_redc(a,&(g->a.a.b.b.a));
+    BIG_toBytes(&(W->val[6*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->a.a.b.b.b));
+    BIG_toBytes(&(W->val[7*MODBYTES_XXX]),a);
+
+    FP_redc(a,&(g->a.b.a.a.a));
+    BIG_toBytes(&(W->val[8*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->a.b.a.a.b));
+    BIG_toBytes(&(W->val[9*MODBYTES_XXX]),a);
+
+    FP_redc(a,&(g->a.b.a.b.a));
+    BIG_toBytes(&(W->val[10*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->a.b.a.b.b));
+    BIG_toBytes(&(W->val[11*MODBYTES_XXX]),a);
+
+    FP_redc(a,&(g->a.b.b.a.a));
+    BIG_toBytes(&(W->val[12*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->a.b.b.a.b));
+    BIG_toBytes(&(W->val[13*MODBYTES_XXX]),a);
+
+    FP_redc(a,&(g->a.b.b.b.a));
+    BIG_toBytes(&(W->val[14*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->a.b.b.b.b));
+    BIG_toBytes(&(W->val[15*MODBYTES_XXX]),a);
+
+    FP_redc(a,&(g->b.a.a.a.a));
+    BIG_toBytes(&(W->val[16*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->b.a.a.a.b));
+    BIG_toBytes(&(W->val[17*MODBYTES_XXX]),a);
+
+    FP_redc(a,&(g->b.a.a.b.a));
+    BIG_toBytes(&(W->val[18*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->b.a.a.b.b));
+    BIG_toBytes(&(W->val[19*MODBYTES_XXX]),a);
+
+    FP_redc(a,&(g->b.a.b.a.a));
+    BIG_toBytes(&(W->val[20*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->b.a.b.a.b));
+    BIG_toBytes(&(W->val[21*MODBYTES_XXX]),a);
+
+    FP_redc(a,&(g->b.a.b.b.a));
+    BIG_toBytes(&(W->val[22*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->b.a.b.b.b));
+    BIG_toBytes(&(W->val[23*MODBYTES_XXX]),a);
+
+    FP_redc(a,&(g->b.b.a.a.a));
+    BIG_toBytes(&(W->val[24*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->b.b.a.a.b));
+    BIG_toBytes(&(W->val[25*MODBYTES_XXX]),a);
+
+    FP_redc(a,&(g->b.b.a.b.a));
+    BIG_toBytes(&(W->val[26*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->b.b.a.b.b));
+    BIG_toBytes(&(W->val[27*MODBYTES_XXX]),a);
+
+    FP_redc(a,&(g->b.b.b.a.a));
+    BIG_toBytes(&(W->val[28*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->b.b.b.a.b));
+    BIG_toBytes(&(W->val[29*MODBYTES_XXX]),a);
+
+    FP_redc(a,&(g->b.b.b.b.a));
+    BIG_toBytes(&(W->val[30*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->b.b.b.b.b));
+    BIG_toBytes(&(W->val[31*MODBYTES_XXX]),a);
+
+    FP_redc(a,&(g->c.a.a.a.a));
+    BIG_toBytes(&(W->val[32*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->c.a.a.a.b));
+    BIG_toBytes(&(W->val[33*MODBYTES_XXX]),a);
+
+    FP_redc(a,&(g->c.a.a.b.a));
+    BIG_toBytes(&(W->val[34*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->c.a.a.b.b));
+    BIG_toBytes(&(W->val[35*MODBYTES_XXX]),a);
+
+    FP_redc(a,&(g->c.a.b.a.a));
+    BIG_toBytes(&(W->val[36*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->c.a.b.a.b));
+    BIG_toBytes(&(W->val[37*MODBYTES_XXX]),a);
+
+    FP_redc(a,&(g->c.a.b.b.a));
+    BIG_toBytes(&(W->val[38*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->c.a.b.b.b));
+    BIG_toBytes(&(W->val[39*MODBYTES_XXX]),a);
+
+    FP_redc(a,&(g->c.b.a.a.a));
+    BIG_toBytes(&(W->val[40*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->c.b.a.a.b));
+    BIG_toBytes(&(W->val[41*MODBYTES_XXX]),a);
+
+    FP_redc(a,&(g->c.b.a.b.a));
+    BIG_toBytes(&(W->val[42*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->c.b.a.b.b));
+    BIG_toBytes(&(W->val[43*MODBYTES_XXX]),a);
+
+    FP_redc(a,&(g->c.b.b.a.a));
+    BIG_toBytes(&(W->val[44*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->c.b.b.a.b));
+    BIG_toBytes(&(W->val[45*MODBYTES_XXX]),a);
+
+    FP_redc(a,&(g->c.b.b.b.a));
+    BIG_toBytes(&(W->val[46*MODBYTES_XXX]),a);
+    FP_redc(a,&(g->c.b.b.b.b));
+    BIG_toBytes(&(W->val[47*MODBYTES_XXX]),a);
+
+}
+
+/* Restore g from octet string w */
+void YYY::FP48_fromOctet(FP48 *g,octet *W)
+{
+	BIG b;
+
+    BIG_fromBytes(b,&W->val[0]);
+    FP_nres(&(g->a.a.a.a.a),b);
+    BIG_fromBytes(b,&W->val[MODBYTES_XXX]);
+    FP_nres(&(g->a.a.a.a.b),b);
+
+    BIG_fromBytes(b,&W->val[2*MODBYTES_XXX]);
+    FP_nres(&(g->a.a.a.b.a),b);
+    BIG_fromBytes(b,&W->val[3*MODBYTES_XXX]);
+    FP_nres(&(g->a.a.a.b.b),b);
+
+    BIG_fromBytes(b,&W->val[4*MODBYTES_XXX]);
+    FP_nres(&(g->a.a.b.a.a),b);
+    BIG_fromBytes(b,&W->val[5*MODBYTES_XXX]);
+    FP_nres(&(g->a.a.b.a.b),b);
+
+    BIG_fromBytes(b,&W->val[6*MODBYTES_XXX]);
+    FP_nres(&(g->a.a.b.b.a),b);
+    BIG_fromBytes(b,&W->val[7*MODBYTES_XXX]);
+    FP_nres(&(g->a.a.b.b.b),b);
+
+    BIG_fromBytes(b,&W->val[8*MODBYTES_XXX]);
+    FP_nres(&(g->a.b.a.a.a),b);
+    BIG_fromBytes(b,&W->val[9*MODBYTES_XXX]);
+    FP_nres(&(g->a.b.a.a.b),b);
+
+    BIG_fromBytes(b,&W->val[10*MODBYTES_XXX]);
+    FP_nres(&(g->a.b.a.b.a),b);
+    BIG_fromBytes(b,&W->val[11*MODBYTES_XXX]);
+    FP_nres(&(g->a.b.a.b.b),b);
+
+    BIG_fromBytes(b,&W->val[12*MODBYTES_XXX]);
+    FP_nres(&(g->a.b.b.a.a),b);
+    BIG_fromBytes(b,&W->val[13*MODBYTES_XXX]);
+    FP_nres(&(g->a.b.b.a.b),b);
+
+    BIG_fromBytes(b,&W->val[14*MODBYTES_XXX]);
+    FP_nres(&(g->a.b.b.b.a),b);
+    BIG_fromBytes(b,&W->val[15*MODBYTES_XXX]);
+    FP_nres(&(g->a.b.b.b.b),b);
+
+    BIG_fromBytes(b,&W->val[16*MODBYTES_XXX]);
+    FP_nres(&(g->b.a.a.a.a),b);
+    BIG_fromBytes(b,&W->val[17*MODBYTES_XXX]);
+    FP_nres(&(g->b.a.a.a.b),b);
+
+    BIG_fromBytes(b,&W->val[18*MODBYTES_XXX]);
+    FP_nres(&(g->b.a.a.b.a),b);
+    BIG_fromBytes(b,&W->val[19*MODBYTES_XXX]);
+    FP_nres(&(g->b.a.a.b.b),b);
+
+    BIG_fromBytes(b,&W->val[20*MODBYTES_XXX]);
+    FP_nres(&(g->b.a.b.a.a),b);
+    BIG_fromBytes(b,&W->val[21*MODBYTES_XXX]);
+    FP_nres(&(g->b.a.b.a.b),b);
+
+    BIG_fromBytes(b,&W->val[22*MODBYTES_XXX]);
+    FP_nres(&(g->b.a.b.b.a),b);
+    BIG_fromBytes(b,&W->val[23*MODBYTES_XXX]);
+    FP_nres(&(g->b.a.b.b.b),b);
+
+    BIG_fromBytes(b,&W->val[24*MODBYTES_XXX]);
+    FP_nres(&(g->b.b.a.a.a),b);
+    BIG_fromBytes(b,&W->val[25*MODBYTES_XXX]);
+    FP_nres(&(g->b.b.a.a.b),b);
+
+    BIG_fromBytes(b,&W->val[26*MODBYTES_XXX]);
+    FP_nres(&(g->b.b.a.b.a),b);
+    BIG_fromBytes(b,&W->val[27*MODBYTES_XXX]);
+    FP_nres(&(g->b.b.a.b.b),b);
+
+    BIG_fromBytes(b,&W->val[28*MODBYTES_XXX]);
+    FP_nres(&(g->b.b.b.a.a),b);
+    BIG_fromBytes(b,&W->val[29*MODBYTES_XXX]);
+    FP_nres(&(g->b.b.b.a.b),b);
+
+    BIG_fromBytes(b,&W->val[30*MODBYTES_XXX]);
+    FP_nres(&(g->b.b.b.b.a),b);
+    BIG_fromBytes(b,&W->val[31*MODBYTES_XXX]);
+    FP_nres(&(g->b.b.b.b.b),b);
+
+    BIG_fromBytes(b,&W->val[32*MODBYTES_XXX]);
+    FP_nres(&(g->c.a.a.a.a),b);
+    BIG_fromBytes(b,&W->val[33*MODBYTES_XXX]);
+    FP_nres(&(g->c.a.a.a.b),b);
+
+    BIG_fromBytes(b,&W->val[34*MODBYTES_XXX]);
+    FP_nres(&(g->c.a.a.b.a),b);
+    BIG_fromBytes(b,&W->val[35*MODBYTES_XXX]);
+    FP_nres(&(g->c.a.a.b.b),b);
+
+    BIG_fromBytes(b,&W->val[36*MODBYTES_XXX]);
+    FP_nres(&(g->c.a.b.a.a),b);
+    BIG_fromBytes(b,&W->val[37*MODBYTES_XXX]);
+    FP_nres(&(g->c.a.b.a.b),b);
+
+    BIG_fromBytes(b,&W->val[38*MODBYTES_XXX]);
+    FP_nres(&(g->c.a.b.b.a),b);
+    BIG_fromBytes(b,&W->val[39*MODBYTES_XXX]);
+    FP_nres(&(g->c.a.b.b.b),b);
+
+    BIG_fromBytes(b,&W->val[40*MODBYTES_XXX]);
+    FP_nres(&(g->c.b.a.a.a),b);
+    BIG_fromBytes(b,&W->val[41*MODBYTES_XXX]);
+    FP_nres(&(g->c.b.a.a.b),b);
+
+    BIG_fromBytes(b,&W->val[42*MODBYTES_XXX]);
+    FP_nres(&(g->c.b.a.b.a),b);
+    BIG_fromBytes(b,&W->val[43*MODBYTES_XXX]);
+    FP_nres(&(g->c.b.a.b.b),b);
+
+    BIG_fromBytes(b,&W->val[44*MODBYTES_XXX]);
+    FP_nres(&(g->c.b.b.a.a),b);
+    BIG_fromBytes(b,&W->val[45*MODBYTES_XXX]);
+    FP_nres(&(g->c.b.b.a.b),b);
+
+    BIG_fromBytes(b,&W->val[46*MODBYTES_XXX]);
+    FP_nres(&(g->c.b.b.b.a),b);
+    BIG_fromBytes(b,&W->val[47*MODBYTES_XXX]);
+    FP_nres(&(g->c.b.b.b.b),b);
+
+}
+
+/* Move b to a if d=1 */
+void YYY::FP48_cmove(FP48 *f,FP48 *g,int d)
+{
+    FP16_cmove(&(f->a),&(g->a),d);
+    FP16_cmove(&(f->b),&(g->b),d);
+    FP16_cmove(&(f->c),&(g->c),d);
+}
+
+/*
+using namespace YYY;
+
+int main() {
+	int i;
+	FP2 f,w0,w1,X;
+	FP4 f0,f1;
+	FP16 t0,t1,t2;
+	FP48 w,t,lv;
+	BIG a,b;
+	BIG p;
+
+
+	char raw[100];
+	csprng RNG;                // Crypto Strong RNG 
+
+	for (i=0; i<100; i++) raw[i]=i;
+
+	BIG_rcopy(a,Fra);
+    BIG_rcopy(b,Frb);
+	FP2_from_BIGs(&X,a,b);
+
+
+
+    RAND_seed(&RNG,100,raw);   // initialise strong RNG 
+
+	BIG_rcopy(p,Modulus);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w0,a,b);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w1,a,b);
+
+	FP4_from_FP2s(&f0,&w0,&w1);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w0,a,b);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w1,a,b);
+
+	FP4_from_FP2s(&f1,&w0,&w1);
+	FP16_from_FP4s(&t0,&f0,&f1);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w0,a,b);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w1,a,b);
+
+	FP4_from_FP2s(&f0,&w0,&w1);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w0,a,b);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w1,a,b);
+
+	FP4_from_FP2s(&f1,&w0,&w1);
+	FP16_from_FP4s(&t1,&f0,&f1);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w0,a,b);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w1,a,b);
+
+	FP4_from_FP2s(&f0,&w0,&w1);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w0,a,b);
+
+	BIG_randomnum(a,p,&RNG);
+	BIG_randomnum(b,p,&RNG);
+	FP2_from_BIGs(&w1,a,b);
+
+	FP4_from_FP2s(&f1,&w0,&w1);
+	FP16_from_FP4s(&t2,&f0,&f1);
+
+	FP48_from_FP16s(&w,&t0,&t1,&t2);
+
+
+	FP48_copy(&t,&w);
+
+	printf("w= ");
+	FP48_output(&w);
+	printf("\n");
+
+	FP48_norm(&w);
+
+	printf("w^p= ");
+	FP48_frob(&w,&X);
+	FP48_output(&w);
+	printf("\n");	
+
+//	printf("p.w= ");
+//	FP48_ppow(&t,&t,p);
+//	FP48_output(&t);
+//	printf("\n");	
+
+	printf("1/w= ");
+	FP48_inv(&t,&w);
+	FP48_output(&t);
+	printf("\n");	
+
+	printf("w= ");
+	FP48_inv(&w,&t);
+	FP48_output(&w);
+	printf("\n");	
+
+	return 0;
+}
+
+*/
diff --git a/version3/cpp/fp48.h b/version3/cpp/fp48.h
new file mode 100644
index 0000000..64be9e9
--- /dev/null
+++ b/version3/cpp/fp48.h
@@ -0,0 +1,199 @@
+#ifndef FP48_YYY_H
+#define FP48_YYY_H
+
+#include "fp16_YYY.h"
+
+using namespace amcl;
+
+namespace YYY {
+/**
+	@brief FP12 Structure - towered over three FP16
+*/
+
+typedef struct
+{
+    FP16 a; /**< first part of FP12 */
+    FP16 b; /**< second part of FP12 */
+    FP16 c; /**< third part of FP12 */
+} FP48;
+
+extern const XXX::BIG Fra; /**< real part of BN curve Frobenius Constant */
+extern const XXX::BIG Frb; /**< imaginary part of BN curve Frobenius Constant */
+
+/* FP48 prototypes */
+/**	@brief Tests for FP48 equal to zero
+ *
+	@param x FP48 number to be tested
+	@return 1 if zero, else returns 0
+ */
+extern int FP48_iszilch(FP48 *x);
+/**	@brief Tests for FP48 equal to unity
+ *
+	@param x FP48 number to be tested
+	@return 1 if unity, else returns 0
+ */
+extern int FP48_isunity(FP48 *x);
+/**	@brief Copy FP48 to another FP48
+ *
+	@param x FP48 instance, on exit = y
+	@param y FP48 instance to be copied
+ */
+extern void FP48_copy(FP48 *x,FP48 *y);
+/**	@brief Set FP48 to unity
+ *
+	@param x FP48 instance to be set to one
+ */
+extern void FP48_one(FP48 *x);
+/**	@brief Tests for equality of two FP48s
+ *
+	@param x FP48 instance to be compared
+	@param y FP48 instance to be compared
+	@return 1 if x=y, else returns 0
+ */
+extern int FP48_equals(FP48 *x,FP48 *y);
+/**	@brief Conjugation of FP48
+ *
+	If y=(a,b,c) (where a,b,c are its three FP16 components) on exit x=(conj(a),-conj(b),conj(c))
+	@param x FP48 instance, on exit = conj(y)
+	@param y FP48 instance
+ */
+extern void FP48_conj(FP48 *x,FP48 *y);
+/**	@brief Initialise FP48 from single FP16
+ *
+	Sets first FP16 component of an FP48, other components set to zero
+	@param x FP48 instance to be initialised
+	@param a FP16 to form first part of FP48
+ */
+extern void FP48_from_FP16(FP48 *x,FP16 *a);
+/**	@brief Initialise FP48 from three FP16s
+ *
+	@param x FP48 instance to be initialised
+	@param a FP16 to form first part of FP48
+	@param b FP16 to form second part of FP48
+	@param c FP16 to form third part of FP48
+ */
+extern void FP48_from_FP16s(FP48 *x,FP16 *a,FP16* b,FP16 *c);
+/**	@brief Fast Squaring of an FP48 in "unitary" form
+ *
+	@param x FP48 instance, on exit = y^2
+	@param y FP16 instance, must be unitary
+ */
+extern void FP48_usqr(FP48 *x,FP48 *y);
+/**	@brief Squaring an FP48
+ *
+	@param x FP48 instance, on exit = y^2
+	@param y FP48 instance
+ */
+extern void FP48_sqr(FP48 *x,FP48 *y);
+/**	@brief Fast multiplication of an FP48 by an FP48 that arises from an ATE pairing line function
+ *
+	Here the multiplier has a special form that can be exploited
+	@param x FP48 instance, on exit = x*y
+	@param y FP48 instance, of special form
+	@param t D_TYPE or M_TYPE twist
+ */
+extern void FP48_smul(FP48 *x,FP48 *y,int t);
+/**	@brief Multiplication of two FP48s
+ *
+	@param x FP48 instance, on exit = x*y
+	@param y FP48 instance, the multiplier
+ */
+extern void FP48_mul(FP48 *x,FP48 *y);
+/**	@brief Inverting an FP48
+ *
+	@param x FP48 instance, on exit = 1/y
+	@param y FP48 instance
+ */
+extern void FP48_inv(FP48 *x,FP48 *y);
+/**	@brief Raises an FP48 to the power of a BIG
+ *
+	@param r FP48 instance, on exit = y^b
+	@param x FP48 instance
+	@param b BIG number
+ */
+extern void FP48_pow(FP48 *r,FP48 *x,XXX::BIG b);
+
+//extern void FP48_ppow(FP48 *r,FP48 *x,XXX::BIG b);
+
+/**	@brief Raises an FP48 instance x to a small integer power, side-channel resistant
+ *
+	@param x FP48 instance, on exit = x^i
+	@param i small integer exponent
+	@param b maximum number of bits in exponent
+ */
+extern void FP48_pinpow(FP48 *x,int i,int b);
+
+/**	@brief Raises an FP48 instance x to a BIG power, compressed to FP16 
+ *
+	@param c FP16 instance, on exit = x^(e mod r) as FP16
+	@param x FP48 input
+	@param e BIG exponent
+	@param r BIG group order
+ */
+extern void FP48_compow(FP16 *c,FP48 *x,XXX::BIG e,XXX::BIG r);
+
+/**	@brief Calculate Pi x[i]^b[i] for i=0 to 15, side-channel resistant
+ *
+	@param r FP48 instance, on exit = Pi x[i]^b[i] for i=0 to 15
+	@param x FP48 array with 16 FP48s
+	@param b BIG array of 16 exponents
+ */
+extern void FP48_pow16(FP48 *r,FP48 *x,XXX::BIG *b);
+
+
+/**	@brief Raises an FP48 to the power of the internal modulus p, using the Frobenius
+ *
+	@param x FP48 instance, on exit = x^p^n
+	@param f FP2 precalculated Frobenius constant
+	@param n power of p
+ */
+extern void FP48_frob(FP48 *x,FP2 *f,int n);
+
+/**	@brief Reduces all components of possibly unreduced FP48 mod Modulus
+ *
+	@param x FP48 instance, on exit reduced mod Modulus
+ */
+extern void FP48_reduce(FP48 *x);
+/**	@brief Normalises the components of an FP48
+ *
+	@param x FP48 instance to be normalised
+ */
+extern void FP48_norm(FP48 *x);
+/**	@brief Formats and outputs an FP48 to the console
+ *
+	@param x FP48 instance to be printed
+ */
+extern void FP48_output(FP48 *x);
+/**	@brief Formats and outputs an FP48 instance to an octet string
+ *
+	Serializes the components of an FP48 to big-endian base 256 form.
+	@param S output octet string
+	@param x FP48 instance to be converted to an octet string
+ */
+extern void FP48_toOctet(octet *S,FP48 *x);
+/**	@brief Creates an FP48 instance from an octet string
+ *
+	De-serializes the components of an FP48 to create an FP48 from big-endian base 256 components.
+	@param x FP48 instance to be created from an octet string
+	@param S input octet string
+
+ */
+extern void FP48_fromOctet(FP48 *x,octet *S);
+/**	@brief Calculate the trace of an FP48
+ *
+	@param t FP16 trace of x, on exit = tr(x)
+	@param x FP48 instance
+
+ */
+extern void FP48_trace(FP16 *t,FP48 *x);
+
+/**	@brief Conditional copy of FP48 number
+ *
+	Conditionally copies second parameter to the first (without branching)
+	@param x FP48 instance, set to y if s!=0
+	@param y another FP48 instance
+	@param s copy only takes place if not equal to 0
+ */
+extern void FP48_cmove(FP48 *x,FP48 *y,int s);
+}
+#endif
diff --git a/version3/cpp/fp8.cpp b/version3/cpp/fp8.cpp
new file mode 100644
index 0000000..4b29d03
--- /dev/null
+++ b/version3/cpp/fp8.cpp
@@ -0,0 +1,800 @@
+/*
+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.
+*/
+
+/* AMCL Fp^8 functions */
+
+/* FP8 elements are of the form a+ib, where i is sqrt(sqrt(-1+sqrt(-1))) */
+
+#include "fp8_YYY.h"
+
+using namespace XXX;
+
+/* test x==0 ? */
+int YYY::FP8_iszilch(FP8 *x)
+{
+    if (FP4_iszilch(&(x->a)) && FP4_iszilch(&(x->b))) return 1;
+    return 0;
+}
+
+/* test x==1 ? */
+int YYY::FP8_isunity(FP8 *x)
+{
+    if (FP4_isunity(&(x->a)) && FP4_iszilch(&(x->b))) return 1;
+    return 0;
+}
+
+/* test is w real? That is in a+ib test b is zero */
+int YYY::FP8_isreal(FP8 *w)
+{
+    return FP4_iszilch(&(w->b));
+}
+
+/* return 1 if x==y, else 0 */
+int YYY::FP8_equals(FP8 *x,FP8 *y)
+{
+    if (FP4_equals(&(x->a),&(y->a)) && FP4_equals(&(x->b),&(y->b)))
+        return 1;
+    return 0;
+}
+
+/* set FP8 from two FP4s */
+void YYY::FP8_from_FP4s(FP8 *w,FP4 * x,FP4* y)
+{
+    FP4_copy(&(w->a), x);
+    FP4_copy(&(w->b), y);
+}
+
+/* set FP8 from FP4 */
+void YYY::FP8_from_FP4(FP8 *w,FP4 *x)
+{
+    FP4_copy(&(w->a), x);
+    FP4_zero(&(w->b));
+}
+
+/* set high part of FP8 from FP4 */
+void YYY::FP8_from_FP4H(FP8 *w,FP4 *x)
+{
+    FP4_copy(&(w->b), x);
+    FP4_zero(&(w->a));
+}
+
+/* FP8 copy w=x */
+void YYY::FP8_copy(FP8 *w,FP8 *x)
+{
+    if (w==x) return;
+    FP4_copy(&(w->a), &(x->a));
+    FP4_copy(&(w->b), &(x->b));
+}
+
+/* FP8 w=0 */
+void YYY::FP8_zero(FP8 *w)
+{
+    FP4_zero(&(w->a));
+    FP4_zero(&(w->b));
+}
+
+/* FP8 w=1 */
+void YYY::FP8_one(FP8 *w)
+{
+    FP4_one(&(w->a));
+    FP4_zero(&(w->b));
+}
+
+/* Set w=-x */
+void YYY::FP8_neg(FP8 *w,FP8 *x)
+{
+    /* Just one field neg */
+    FP4 m,t;
+	FP8_norm(x);
+//printf("Into neg 1\n");
+    FP4_add(&m,&(x->a),&(x->b));
+	FP4_norm(&m);
+//printf("Into neg 2\n");
+    FP4_neg(&m,&m);
+//printf("Into neg 3\n");
+    FP4_add(&t,&m,&(x->b));
+//printf("Into neg 4\n");
+    FP4_add(&(w->b),&m,&(x->a));
+//printf("Into neg 5\n");
+    FP4_copy(&(w->a),&t);
+	FP8_norm(w);
+}
+
+/* Set w=conj(x) */
+void YYY::FP8_conj(FP8 *w,FP8 *x)
+{
+    FP4_copy(&(w->a), &(x->a));
+    FP4_neg(&(w->b), &(x->b));
+	FP8_norm(w);
+}
+
+/* Set w=-conj(x) */
+void YYY::FP8_nconj(FP8 *w,FP8 *x)
+{
+    FP4_copy(&(w->b),&(x->b));
+    FP4_neg(&(w->a), &(x->a));
+	FP8_norm(w);
+}
+
+/* Set w=x+y */
+void YYY::FP8_add(FP8 *w,FP8 *x,FP8 *y)
+{
+    FP4_add(&(w->a), &(x->a), &(y->a));
+    FP4_add(&(w->b), &(x->b), &(y->b));
+}
+
+/* Set w=x-y */
+/* Input y MUST be normed */
+void YYY::FP8_sub(FP8 *w,FP8 *x,FP8 *y)
+{
+    FP8 my;
+
+    FP8_neg(&my, y);
+    FP8_add(w, x, &my);
+
+}
+
+/* reduce all components of w mod Modulus */
+void YYY::FP8_reduce(FP8 *w)
+{
+    FP4_reduce(&(w->a));
+    FP4_reduce(&(w->b));
+}
+
+/* normalise all elements of w */
+void YYY::FP8_norm(FP8 *w)
+{
+    FP4_norm(&(w->a));
+    FP4_norm(&(w->b));
+}
+
+/* Set w=s*x, where s is FP4 */
+void YYY::FP8_pmul(FP8 *w,FP8 *x,FP4 *s)
+{
+    FP4_mul(&(w->a),&(x->a),s);
+    FP4_mul(&(w->b),&(x->b),s);
+}
+
+/* Set w=s*x, where s is FP2 */
+void YYY::FP8_qmul(FP8 *w,FP8 *x,FP2 *s)
+{
+    FP4_pmul(&(w->a),&(x->a),s);
+    FP4_pmul(&(w->b),&(x->b),s);
+}
+
+/* Set w=s*x, where s is FP2 */
+void YYY::FP8_tmul(FP8 *w,FP8 *x,FP *s)
+{
+    FP4_qmul(&(w->a),&(x->a),s);
+    FP4_qmul(&(w->b),&(x->b),s);
+}
+
+/* Set w=s*x, where s is int */
+void YYY::FP8_imul(FP8 *w,FP8 *x,int s)
+{
+    FP4_imul(&(w->a),&(x->a),s);
+    FP4_imul(&(w->b),&(x->b),s);
+}
+
+/* Set w=x^2 */
+/* Input MUST be normed  */
+void YYY::FP8_sqr(FP8 *w,FP8 *x)
+{
+    FP4 t1,t2,t3;
+
+    FP4_mul(&t3,&(x->a),&(x->b)); /* norms x */
+    FP4_copy(&t2,&(x->b));
+    FP4_add(&t1,&(x->a),&(x->b));
+    FP4_times_i(&t2);
+
+    FP4_add(&t2,&(x->a),&t2);
+
+	FP4_norm(&t1);  // 2
+	FP4_norm(&t2);  // 2
+
+    FP4_mul(&(w->a),&t1,&t2);
+
+    FP4_copy(&t2,&t3);
+    FP4_times_i(&t2);
+
+    FP4_add(&t2,&t2,&t3);
+
+	FP4_norm(&t2);  // 2
+    FP4_neg(&t2,&t2);
+    FP4_add(&(w->a),&(w->a),&t2);  /* a=(a+b)(a+i^2.b)-i^2.ab-ab = a*a+ib*ib */
+    FP4_add(&(w->b),&t3,&t3);  /* b=2ab */
+
+    FP8_norm(w);
+}
+
+/* Set w=x*y */
+/* Inputs MUST be normed  */
+void YYY::FP8_mul(FP8 *w,FP8 *x,FP8 *y)
+{
+
+    FP4 t1,t2,t3,t4;
+
+    FP4_mul(&t1,&(x->a),&(y->a)); 
+//printf("Into 8 mul 0a\n");
+    FP4_mul(&t2,&(x->b),&(y->b)); 
+//printf("Into 8 mul 0b\n");
+    FP4_add(&t3,&(y->b),&(y->a));
+    FP4_add(&t4,&(x->b),&(x->a));
+
+	FP4_norm(&t4); // 2
+	FP4_norm(&t3); // 2
+
+    FP4_mul(&t4,&t4,&t3); /* (xa+xb)(ya+yb) */
+	FP4_neg(&t3,&t1);  // 1
+	FP4_add(&t4,&t4,&t3);  //t4E=3
+    FP4_norm(&t4);
+
+	FP4_neg(&t3,&t2);  // 1
+	FP4_add(&(w->b),&t4,&t3); //wbE=3
+
+    FP4_times_i(&t2);
+    FP4_add(&(w->a),&t2,&t1);
+
+    FP8_norm(w);
+}
+
+/* output FP8 in format [a,b] */
+void YYY::FP8_output(FP8 *w)
+{
+    printf("[");
+    FP4_output(&(w->a));
+    printf(",");
+    FP4_output(&(w->b));
+    printf("]");
+}
+
+void YYY::FP8_rawoutput(FP8 *w)
+{
+    printf("[");
+    FP4_rawoutput(&(w->a));
+    printf(",");
+    FP4_rawoutput(&(w->b));
+    printf("]");
+}
+
+/* Set w=1/x */
+void YYY::FP8_inv(FP8 *w,FP8 *x)
+{
+    FP4 t1,t2;
+    FP4_sqr(&t1,&(x->a));
+    FP4_sqr(&t2,&(x->b));
+    FP4_times_i(&t2);
+	FP4_norm(&t2);
+
+    FP4_sub(&t1,&t1,&t2);
+	FP4_norm(&t1);
+//printf(" in mark 1\n");
+    FP4_inv(&t1,&t1);
+//printf(" in mark 2\n");
+    FP4_mul(&(w->a),&t1,&(x->a));
+    FP4_neg(&t1,&t1);
+	FP4_norm(&t1);
+    FP4_mul(&(w->b),&t1,&(x->b));
+}
+
+/* w*=i where i = sqrt(sqrt(-1+sqrt(-1))) */
+void YYY::FP8_times_i(FP8 *w)
+{
+	FP4 s,t;
+	FP4_copy(&s,&(w->b));
+	FP4_copy(&t,&(w->a));
+	FP4_times_i(&s);
+	FP4_copy(&(w->a),&s);
+	FP4_copy(&(w->b),&t);
+	FP8_norm(w);
+}
+
+void YYY::FP8_times_i2(FP8 *w)
+{
+	FP4_times_i(&(w->a));
+	FP4_times_i(&(w->b));
+}
+
+/* Set w=w^p using Frobenius */
+void YYY::FP8_frob(FP8 *w,FP2 *f)
+{ // f=(i+1)^(p-3)/4
+	FP2 ff;
+	FP2_sqr(&ff,f);  // (i+1)^(p-3)/2
+	FP2_mul_ip(&ff); // (i+1)^(p-1)/2
+	FP2_norm(&ff);
+//printf("in in here 1\n");
+	FP4_frob(&(w->a),&ff);
+	FP4_frob(&(w->b),&ff);
+//printf("in in here 2\n");
+	FP4_pmul(&(w->b),&(w->b),f);  // times (1+i)^(p-3)/4
+	FP4_times_i(&(w->b));		// (i+1)^(p-1)/4
+}
+
+/* Set r=a^b mod m */
+void YYY::FP8_pow(FP8 *r,FP8* a,BIG b)
+{
+    FP8 w;
+    BIG z,zilch;
+    int bt;
+
+    BIG_zero(zilch);
+
+    BIG_copy(z,b);
+    FP8_copy(&w,a);
+    FP8_one(r);
+    BIG_norm(z);
+
+    while(1)
+    {
+        bt=BIG_parity(z);
+        BIG_shr(z,1);
+        if (bt) FP8_mul(r,r,&w);
+        if (BIG_comp(z,zilch)==0) break;
+        FP8_sqr(&w,&w);
+    }
+    FP8_reduce(r);
+}
+
+#if CURVE_SECURITY_ZZZ == 192
+
+/* XTR xtr_a function */
+void YYY::FP8_xtr_A(FP8 *r,FP8 *w,FP8 *x,FP8 *y,FP8 *z)
+{
+    FP8 t1,t2;
+
+    FP8_copy(r,x);
+    FP8_sub(&t1,w,y);
+	FP8_norm(&t1);
+    FP8_pmul(&t1,&t1,&(r->a));
+    FP8_add(&t2,w,y);
+	FP8_norm(&t2);
+    FP8_pmul(&t2,&t2,&(r->b));
+    FP8_times_i(&t2);
+
+    FP8_add(r,&t1,&t2);
+    FP8_add(r,r,z);
+
+    FP8_reduce(r);
+}
+
+/* XTR xtr_d function */
+void YYY::FP8_xtr_D(FP8 *r,FP8 *x)
+{
+    FP8 w;
+    FP8_copy(r,x);
+    FP8_conj(&w,r);
+    FP8_add(&w,&w,&w);
+    FP8_sqr(r,r);
+	FP8_norm(&w);
+    FP8_sub(r,r,&w);
+    FP8_reduce(r);    /* reduce here as multiple calls trigger automatic reductions */
+}
+
+/* r=x^n using XTR method on traces of FP12s */
+void YYY::FP8_xtr_pow(FP8 *r,FP8 *x,BIG n)
+{
+    int i,par,nb;
+    BIG v;
+    FP2 w2;
+	FP4 w4;
+    FP8 t,a,b,c,sf;
+
+    BIG_zero(v);
+    BIG_inc(v,3);
+	BIG_norm(v);
+    FP2_from_BIG(&w2,v);
+    FP4_from_FP2(&w4,&w2);
+    FP8_from_FP4(&a,&w4);
+
+	FP8_copy(&sf,x);
+	FP8_norm(&sf);
+	FP8_copy(&b,&sf);
+    FP8_xtr_D(&c,&sf);
+
+    //BIG_norm(n);
+    par=BIG_parity(n);
+    BIG_copy(v,n);
+	BIG_norm(v);
+    BIG_shr(v,1);
+    if (par==0)
+    {
+        BIG_dec(v,1);
+        BIG_norm(v);
+    }
+
+    nb=BIG_nbits(v);
+    for (i=nb-1; i>=0; i--)
+    {
+        if (!BIG_bit(v,i))
+        {
+            FP8_copy(&t,&b);
+            FP8_conj(&sf,&sf);
+            FP8_conj(&c,&c);
+            FP8_xtr_A(&b,&a,&b,&sf,&c);
+            FP8_conj(&sf,&sf);
+            FP8_xtr_D(&c,&t);
+            FP8_xtr_D(&a,&a);
+        }
+        else
+        {
+            FP8_conj(&t,&a);
+            FP8_xtr_D(&a,&b);
+            FP8_xtr_A(&b,&c,&b,&sf,&t);
+            FP8_xtr_D(&c,&c);
+        }
+    }
+
+    if (par==0) FP8_copy(r,&c);
+    else FP8_copy(r,&b);
+    FP8_reduce(r);
+}
+
+/* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */
+void YYY::FP8_xtr_pow2(FP8 *r,FP8 *ck,FP8 *cl,FP8 *ckml,FP8 *ckm2l,BIG a,BIG b)
+{
+    int i,f2;
+    BIG d,e,w;
+    FP8 t,cu,cv,cumv,cum2v;
+
+
+    BIG_copy(e,a);
+    BIG_copy(d,b);
+    BIG_norm(e);
+	BIG_norm(d);
+
+    FP8_copy(&cu,ck);
+    FP8_copy(&cv,cl);
+    FP8_copy(&cumv,ckml);
+    FP8_copy(&cum2v,ckm2l);
+
+    f2=0;
+    while (BIG_parity(d)==0 && BIG_parity(e)==0)
+    {
+        BIG_shr(d,1);
+        BIG_shr(e,1);
+        f2++;
+    }
+    while (BIG_comp(d,e)!=0)
+    {
+        if (BIG_comp(d,e)>0)
+        {
+            BIG_imul(w,e,4);
+            BIG_norm(w);
+            if (BIG_comp(d,w)<=0)
+            {
+                BIG_copy(w,d);
+                BIG_copy(d,e);
+                BIG_sub(e,w,e);
+                BIG_norm(e);
+                FP8_xtr_A(&t,&cu,&cv,&cumv,&cum2v);
+                FP8_conj(&cum2v,&cumv);
+                FP8_copy(&cumv,&cv);
+                FP8_copy(&cv,&cu);
+                FP8_copy(&cu,&t);
+            }
+            else if (BIG_parity(d)==0)
+            {
+                BIG_shr(d,1);
+                FP8_conj(r,&cum2v);
+                FP8_xtr_A(&t,&cu,&cumv,&cv,r);
+                FP8_xtr_D(&cum2v,&cumv);
+                FP8_copy(&cumv,&t);
+                FP8_xtr_D(&cu,&cu);
+            }
+            else if (BIG_parity(e)==1)
+            {
+                BIG_sub(d,d,e);
+                BIG_norm(d);
+                BIG_shr(d,1);
+                FP8_xtr_A(&t,&cu,&cv,&cumv,&cum2v);
+                FP8_xtr_D(&cu,&cu);
+                FP8_xtr_D(&cum2v,&cv);
+                FP8_conj(&cum2v,&cum2v);
+                FP8_copy(&cv,&t);
+            }
+            else
+            {
+                BIG_copy(w,d);
+                BIG_copy(d,e);
+                BIG_shr(d,1);
+                BIG_copy(e,w);
+                FP8_xtr_D(&t,&cumv);
+                FP8_conj(&cumv,&cum2v);
+                FP8_conj(&cum2v,&t);
+                FP8_xtr_D(&t,&cv);
+                FP8_copy(&cv,&cu);
+                FP8_copy(&cu,&t);
+            }
+        }
+        if (BIG_comp(d,e)<0)
+        {
+            BIG_imul(w,d,4);
+            BIG_norm(w);
+            if (BIG_comp(e,w)<=0)
+            {
+                BIG_sub(e,e,d);
+                BIG_norm(e);
+                FP8_xtr_A(&t,&cu,&cv,&cumv,&cum2v);
+                FP8_copy(&cum2v,&cumv);
+                FP8_copy(&cumv,&cu);
+                FP8_copy(&cu,&t);
+            }
+            else if (BIG_parity(e)==0)
+            {
+                BIG_copy(w,d);
+                BIG_copy(d,e);
+                BIG_shr(d,1);
+                BIG_copy(e,w);
+                FP8_xtr_D(&t,&cumv);
+                FP8_conj(&cumv,&cum2v);
+                FP8_conj(&cum2v,&t);
+                FP8_xtr_D(&t,&cv);
+                FP8_copy(&cv,&cu);
+                FP8_copy(&cu,&t);
+            }
+            else if (BIG_parity(d)==1)
+            {
+                BIG_copy(w,e);
+                BIG_copy(e,d);
+                BIG_sub(w,w,d);
+                BIG_norm(w);
+                BIG_copy(d,w);
+                BIG_shr(d,1);
+                FP8_xtr_A(&t,&cu,&cv,&cumv,&cum2v);
+                FP8_conj(&cumv,&cumv);
+                FP8_xtr_D(&cum2v,&cu);
+                FP8_conj(&cum2v,&cum2v);
+                FP8_xtr_D(&cu,&cv);
+                FP8_copy(&cv,&t);
+            }
+            else
+            {
+                BIG_shr(d,1);
+                FP8_conj(r,&cum2v);
+                FP8_xtr_A(&t,&cu,&cumv,&cv,r);
+                FP8_xtr_D(&cum2v,&cumv);
+                FP8_copy(&cumv,&t);
+                FP8_xtr_D(&cu,&cu);
+            }
+        }
+    }
+    FP8_xtr_A(r,&cu,&cv,&cumv,&cum2v);
+    for (i=0; i<f2; i++)	FP8_xtr_D(r,r);
+    FP8_xtr_pow(r,r,d);
+}
+
+#endif
+
+
+/* New stuff for ECp8 support */
+
+/* Move b to a if d=1 */
+void YYY::FP8_cmove(FP8 *f,FP8 *g,int d)
+{
+    FP4_cmove(&(f->a),&(g->a),d);
+    FP4_cmove(&(f->b),&(g->b),d);
+}
+
+#if CURVE_SECURITY_ZZZ == 256
+
+/* sqrt(a+xb) = sqrt((a+sqrt(a*a-n*b*b))/2)+x.b/(2*sqrt((a+sqrt(a*a-n*b*b))/2)) */
+/* returns true if x is QR */
+int YYY::FP8_sqrt(FP8 *r,FP8* x)
+{
+	FP4 a,s,t;
+
+	FP8_copy(r,x);
+	if (FP8_iszilch(x))
+		return 1;
+	
+	FP4_copy(&a,&(x->a));
+	FP4_copy(&s,&(x->b));
+
+	if (FP4_iszilch(&s))
+	{
+		if (FP4_sqrt(&t,&a))
+		{
+			FP8_from_FP4(r,&t);
+		}
+		else
+		{
+			FP4_div_i(&a);
+			FP4_sqrt(&t,&a);
+			FP8_from_FP4H(r,&t);
+		}
+		return 1;
+	}
+
+	FP4_sqr(&s,&s);  // s*=s
+	FP4_sqr(&a,&a);  // a*=a
+	FP4_times_i(&s);
+	FP4_norm(&s);
+	FP4_sub(&a,&a,&s); // a-=txx(s)
+
+	if (!FP4_sqrt(&s,&a)) return 0;
+
+	//FP4_sqr(&t,&s);
+
+
+	FP4_copy(&t,&(x->a));
+	FP4_add(&a,&t,&s);
+	FP4_norm(&a);
+	FP4_div2(&a,&a);
+
+	if (!FP4_sqrt(&a,&a))
+	{
+		FP4_sub(&a,&t,&s);
+		FP4_norm(&a);
+		FP4_div2(&a,&a);
+		if (!FP4_sqrt(&a,&a)) return 0;
+	}
+
+	FP4_copy(&t,&(x->b));
+	FP4_add(&s,&a,&a);
+	FP4_inv(&s,&s);
+
+	FP4_mul(&t,&t,&s);
+	FP8_from_FP4s(r,&a,&t);
+
+	return 1;
+
+}
+
+void YYY::FP8_div_i(FP8 *f)
+{
+	FP4 u,v;
+	FP4_copy(&u,&(f->a));
+	FP4_copy(&v,&(f->b));
+	FP4_div_i(&u);
+	FP4_copy(&(f->a),&v);
+	FP4_copy(&(f->b),&u);
+}
+
+void YYY::FP8_div_i2(FP8 *f)
+{
+	FP4_div_i(&(f->a));
+	FP4_div_i(&(f->b));
+}
+
+void YYY::FP8_div_2i(FP8 *f)
+{
+	FP4 u,v;
+	FP4_copy(&u,&(f->a));
+	FP4_copy(&v,&(f->b));
+	FP4_div_2i(&u);
+	FP4_add(&v,&v,&v);
+	FP4_norm(&v);
+	FP4_copy(&(f->a),&v);
+	FP4_copy(&(f->b),&u);
+}
+
+
+
+#endif
+
+/*
+int main(){
+		FP2 w0,w1,f;
+		FP4 w,t;
+		FP4 c1,c2,c3,c4,cr;
+		BIG a,b;
+		BIG e,e1,e2;
+		BIG p,md;
+
+
+		BIG_rcopy(md,Modulus);
+		//Test w^(P^4) = w mod p^2
+		BIG_zero(a); BIG_inc(a,27);
+		BIG_zero(b); BIG_inc(b,45);
+		FP2_from_BIGs(&w0,a,b);
+
+		BIG_zero(a); BIG_inc(a,33);
+		BIG_zero(b); BIG_inc(b,54);
+		FP2_from_BIGs(&w1,a,b);
+
+		FP4_from_FP2s(&w,&w0,&w1);
+		FP4_reduce(&w);
+
+		printf("w= ");
+		FP4_output(&w);
+		printf("\n");
+
+
+		FP4_copy(&t,&w);
+
+
+		BIG_copy(p,md);
+		FP4_pow(&w,&w,p);
+
+		printf("w^p= ");
+		FP4_output(&w);
+		printf("\n");
+//exit(0);
+
+		BIG_rcopy(a,CURVE_Fra);
+		BIG_rcopy(b,CURVE_Frb);
+		FP2_from_BIGs(&f,a,b);
+
+		FP4_frob(&t,&f);
+		printf("w^p= ");
+		FP4_output(&t);
+		printf("\n");
+
+		FP4_pow(&w,&w,p);
+		FP4_pow(&w,&w,p);
+		FP4_pow(&w,&w,p);
+		printf("w^p4= ");
+		FP4_output(&w);
+		printf("\n");
+
+// Test 1/(1/x) = x mod p^4
+		FP4_from_FP2s(&w,&w0,&w1);
+		printf("Test Inversion \nw= ");
+		FP4_output(&w);
+		printf("\n");
+
+		FP4_inv(&w,&w);
+		printf("1/w mod p^4 = ");
+		FP4_output(&w);
+		printf("\n");
+
+		FP4_inv(&w,&w);
+		printf("1/(1/w) mod p^4 = ");
+		FP4_output(&w);
+		printf("\n");
+
+		BIG_zero(e); BIG_inc(e,12);
+
+
+
+	//	FP4_xtr_A(&w,&t,&w,&t,&t);
+		FP4_xtr_pow(&w,&w,e);
+
+		printf("w^e= ");
+		FP4_output(&w);
+		printf("\n");
+
+
+		BIG_zero(a); BIG_inc(a,37);
+		BIG_zero(b); BIG_inc(b,17);
+		FP2_from_BIGs(&w0,a,b);
+
+		BIG_zero(a); BIG_inc(a,49);
+		BIG_zero(b); BIG_inc(b,31);
+		FP2_from_BIGs(&w1,a,b);
+
+		FP4_from_FP2s(&c1,&w0,&w1);
+		FP4_from_FP2s(&c2,&w0,&w1);
+		FP4_from_FP2s(&c3,&w0,&w1);
+		FP4_from_FP2s(&c4,&w0,&w1);
+
+		BIG_zero(e1); BIG_inc(e1,3331);
+		BIG_zero(e2); BIG_inc(e2,3372);
+
+		FP4_xtr_pow2(&w,&c1,&w,&c2,&c3,e1,e2);
+
+		printf("c^e= ");
+		FP4_output(&w);
+		printf("\n");
+
+
+		return 0;
+}
+*/
+
diff --git a/version3/cpp/fp8.h b/version3/cpp/fp8.h
new file mode 100644
index 0000000..6360b2f
--- /dev/null
+++ b/version3/cpp/fp8.h
@@ -0,0 +1,301 @@
+#ifndef FP8_YYY_H
+#define FP8_YYY_H
+
+#include "fp4_YYY.h"
+#include "config_curve_ZZZ.h"
+
+using namespace amcl;
+
+namespace YYY{
+
+/**
+	@brief FP8 Structure - towered over two FP4
+*/
+
+typedef struct
+{
+    FP4 a; /**< real part of FP8 */
+    FP4 b; /**< imaginary part of FP8 */
+} FP8;
+
+
+/* FP8 prototypes */
+/**	@brief Tests for FP8 equal to zero
+ *
+	@param x FP8 number to be tested
+	@return 1 if zero, else returns 0
+ */
+extern int FP8_iszilch(FP8 *x);
+/**	@brief Tests for FP8 equal to unity
+ *
+	@param x FP8 number to be tested
+	@return 1 if unity, else returns 0
+ */
+extern int FP8_isunity(FP8 *x);
+/**	@brief Tests for equality of two FP8s
+ *
+	@param x FP8 instance to be compared
+	@param y FP8 instance to be compared
+	@return 1 if x=y, else returns 0
+ */
+extern int FP8_equals(FP8 *x,FP8 *y);
+/**	@brief Tests for FP8 having only a real part and no imaginary part
+ *
+	@param x FP8 number to be tested
+	@return 1 if real, else returns 0
+ */
+extern int FP8_isreal(FP8 *x);
+/**	@brief Initialise FP8 from two FP4s
+ *
+	@param x FP8 instance to be initialised
+	@param a FP4 to form real part of FP8
+	@param b FP4 to form imaginary part of FP8
+ */
+extern void FP8_from_FP4s(FP8 *x,FP4 *a,FP4 *b);
+/**	@brief Initialise FP8 from single FP4
+ *
+	Imaginary part is set to zero
+	@param x FP8 instance to be initialised
+	@param a FP4 to form real part of FP8
+ */
+extern void FP8_from_FP4(FP8 *x,FP4 *a);
+
+/**	@brief Initialise FP8 from single FP4
+ *
+	real part is set to zero
+	@param x FP8 instance to be initialised
+	@param a FP4 to form imaginary part of FP8
+ */
+extern void FP8_from_FP4H(FP8 *x,FP4 *a);
+
+
+/**	@brief Copy FP8 to another FP8
+ *
+	@param x FP8 instance, on exit = y
+	@param y FP8 instance to be copied
+ */
+extern void FP8_copy(FP8 *x,FP8 *y);
+/**	@brief Set FP8 to zero
+ *
+	@param x FP8 instance to be set to zero
+ */
+extern void FP8_zero(FP8 *x);
+/**	@brief Set FP8 to unity
+ *
+	@param x FP8 instance to be set to one
+ */
+extern void FP8_one(FP8 *x);
+/**	@brief Negation of FP8
+ *
+	@param x FP8 instance, on exit = -y
+	@param y FP8 instance
+ */
+extern void FP8_neg(FP8 *x,FP8 *y);
+/**	@brief Conjugation of FP8
+ *
+	If y=(a,b) on exit x=(a,-b)
+	@param x FP8 instance, on exit = conj(y)
+	@param y FP8 instance
+ */
+extern void FP8_conj(FP8 *x,FP8 *y);
+/**	@brief Negative conjugation of FP8
+ *
+	If y=(a,b) on exit x=(-a,b)
+	@param x FP8 instance, on exit = -conj(y)
+	@param y FP8 instance
+ */
+extern void FP8_nconj(FP8 *x,FP8 *y);
+/**	@brief addition of two FP8s
+ *
+	@param x FP8 instance, on exit = y+z
+	@param y FP8 instance
+	@param z FP8 instance
+ */
+extern void FP8_add(FP8 *x,FP8 *y,FP8 *z);
+/**	@brief subtraction of two FP8s
+ *
+	@param x FP8 instance, on exit = y-z
+	@param y FP8 instance
+	@param z FP8 instance
+ */
+extern void FP8_sub(FP8 *x,FP8 *y,FP8 *z);
+/**	@brief Multiplication of an FP8 by an FP4
+ *
+	@param x FP8 instance, on exit = y*a
+	@param y FP8 instance
+	@param a FP4 multiplier
+ */
+extern void FP8_pmul(FP8 *x,FP8 *y,FP4 *a);
+
+/**	@brief Multiplication of an FP8 by an FP2
+ *
+	@param x FP8 instance, on exit = y*a
+	@param y FP8 instance
+	@param a FP2 multiplier
+ */
+extern void FP8_qmul(FP8 *x,FP8 *y,FP2 *a);
+
+/**	@brief Multiplication of an FP8 by an FP
+ *
+	@param x FP8 instance, on exit = y*a
+	@param y FP8 instance
+	@param a FP multiplier
+ */
+extern void FP8_tmul(FP8 *x,FP8 *y,FP *a);
+
+
+
+/**	@brief Multiplication of an FP8 by a small integer
+ *
+	@param x FP8 instance, on exit = y*i
+	@param y FP8 instance
+	@param i an integer
+ */
+extern void FP8_imul(FP8 *x,FP8 *y,int i);
+/**	@brief Squaring an FP8
+ *
+	@param x FP8 instance, on exit = y^2
+	@param y FP8 instance
+ */
+extern void FP8_sqr(FP8 *x,FP8 *y);
+/**	@brief Multiplication of two FP8s
+ *
+	@param x FP8 instance, on exit = y*z
+	@param y FP8 instance
+	@param z FP8 instance
+ */
+extern void FP8_mul(FP8 *x,FP8 *y,FP8 *z);
+/**	@brief Inverting an FP8
+ *
+	@param x FP8 instance, on exit = 1/y
+	@param y FP8 instance
+ */
+extern void FP8_inv(FP8 *x,FP8 *y);
+/**	@brief Formats and outputs an FP8 to the console
+ *
+	@param x FP8 instance to be printed
+ */
+extern void FP8_output(FP8 *x);
+/**	@brief Formats and outputs an FP8 to the console in raw form (for debugging)
+ *
+	@param x FP8 instance to be printed
+ */
+extern void FP8_rawoutput(FP8 *x);
+/**	@brief multiplies an FP8 instance by irreducible polynomial sqrt(1+sqrt(-1))
+ *
+	@param x FP8 instance, on exit = sqrt(1+sqrt(-1)*x
+ */
+extern void FP8_times_i(FP8 *x);
+/**	@brief multiplies an FP8 instance by irreducible polynomial (1+sqrt(-1))
+ *
+	@param x FP8 instance, on exit = (1+sqrt(-1)*x
+ */
+extern void FP8_times_i2(FP8 *x);
+
+/**	@brief Normalises the components of an FP8
+ *
+	@param x FP8 instance to be normalised
+ */
+extern void FP8_norm(FP8 *x);
+/**	@brief Reduces all components of possibly unreduced FP8 mod Modulus
+ *
+	@param x FP8 instance, on exit reduced mod Modulus
+ */
+extern void FP8_reduce(FP8 *x);
+/**	@brief Raises an FP8 to the power of a BIG
+ *
+	@param x FP8 instance, on exit = y^b
+	@param y FP8 instance
+	@param b BIG number
+ */
+extern void FP8_pow(FP8 *x,FP8 *y,XXX::BIG b);
+/**	@brief Raises an FP8 to the power of the internal modulus p, using the Frobenius
+ *
+	@param x FP8 instance, on exit = x^p
+	@param f FP2 precalculated Frobenius constant
+ */
+extern void FP8_frob(FP8 *x,FP2 *f);
+/**	@brief Calculates the XTR addition function r=w*x-conj(x)*y+z
+ *
+	@param r FP8 instance, on exit = w*x-conj(x)*y+z
+	@param w FP8 instance
+	@param x FP8 instance
+	@param y FP8 instance
+	@param z FP8 instance
+ */
+extern void FP8_xtr_A(FP8 *r,FP8 *w,FP8 *x,FP8 *y,FP8 *z);
+/**	@brief Calculates the XTR doubling function r=x^2-2*conj(x)
+ *
+	@param r FP8 instance, on exit = x^2-2*conj(x)
+	@param x FP8 instance
+ */
+extern void FP8_xtr_D(FP8 *r,FP8 *x);
+/**	@brief Calculates FP8 trace of an FP12 raised to the power of a BIG number
+ *
+	XTR single exponentiation
+	@param r FP8 instance, on exit = trace(w^b)
+	@param x FP8 instance, trace of an FP12 w
+	@param b BIG number
+ */
+extern void FP8_xtr_pow(FP8 *r,FP8 *x,XXX::BIG b);
+/**	@brief Calculates FP8 trace of c^a.d^b, where c and d are derived from FP8 traces of FP12s
+ *
+	XTR double exponentiation
+	Assumes c=tr(x^m), d=tr(x^n), e=tr(x^(m-n)), f=tr(x^(m-2n))
+	@param r FP8 instance, on exit = trace(c^a.d^b)
+	@param c FP8 instance, trace of an FP12
+	@param d FP8 instance, trace of an FP12
+	@param e FP8 instance, trace of an FP12
+	@param f FP8 instance, trace of an FP12
+	@param a BIG number
+	@param b BIG number
+ */
+extern void FP8_xtr_pow2(FP8 *r,FP8 *c,FP8 *d,FP8 *e,FP8 *f,XXX::BIG a,XXX::BIG b);
+
+
+/**	@brief Calculate square root of an FP8
+ *
+	Square root
+	@param r FP8 instance, on exit = sqrt(x)
+	@param x FP8 instance
+	@return 1 x is a QR, otherwise 0
+ */
+extern int  FP8_sqrt(FP8 *r,FP8 *x);
+
+
+/**	@brief Conditional copy of FP8 number
+ *
+	Conditionally copies second parameter to the first (without branching)
+	@param x FP8 instance, set to y if s!=0
+	@param y another FP8 instance
+	@param s copy only takes place if not equal to 0
+ */
+extern void FP8_cmove(FP8 *x,FP8 *y,int s);
+
+
+/**	@brief Divide FP8 number by QNR
+ *
+	Divide FP8 by the QNR
+	@param x FP8 instance
+ */
+extern void FP8_div_i(FP8 *x);
+
+/**	@brief Divide FP8 number by QNR twice
+ *
+	Divide FP8 by the QNR twice
+	@param x FP8 instance
+ */
+extern void FP8_div_i2(FP8 *x);
+
+/**	@brief Divide FP8 number by QNR/2
+ *
+	Divide FP8 by the QNR/2
+	@param x FP8 instance
+ */
+extern void FP8_div_2i(FP8 *x);
+
+
+}
+
+#endif
+
diff --git a/version3/cpp/gcm.cpp b/version3/cpp/gcm.cpp
new file mode 100644
index 0000000..826864a
--- /dev/null
+++ b/version3/cpp/gcm.cpp
@@ -0,0 +1,413 @@
+/*
+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.
+*/
+
+/*
+ * Implementation of the AES-GCM Encryption/Authentication
+ *
+ * Some restrictions..
+ * 1. Only for use with AES
+ * 2. Returned tag is always 128-bits. Truncate at your own risk.
+ * 3. The order of function calls must follow some rules
+ *
+ * Typical sequence of calls..
+ * 1. call GCM_init
+ * 2. call GCM_add_header any number of times, as long as length of header is multiple of 16 bytes (block size)
+ * 3. call GCM_add_header one last time with any length of header
+ * 4. call GCM_add_cipher any number of times, as long as length of cipher/plaintext is multiple of 16 bytes
+ * 5. call GCM_add_cipher one last time with any length of cipher/plaintext
+ * 6. call GCM_finish to extract the tag.
+ *
+ * See http://www.mindspring.com/~dmcgrew/gcm-nist-6.pdf
+ */
+/* SU=m, m is Stack Usage */
+
+#include <stdlib.h>
+#include <string.h>
+#include "arch.h"
+#include "amcl.h"
+
+using namespace amcl;
+
+#define NB 4
+#define MR_TOBYTE(x) ((uchar)((x)))
+
+static unsign32 pack(const uchar *b)
+{
+    /* pack bytes into a 32-bit Word */
+    return ((unsign32)b[0]<<24)|((unsign32)b[1]<<16)|((unsign32)b[2]<<8)|(unsign32)b[3];
+}
+
+static void unpack(unsign32 a,uchar *b)
+{
+    /* unpack bytes from a word */
+    b[3]=MR_TOBYTE(a);
+    b[2]=MR_TOBYTE(a>>8);
+    b[1]=MR_TOBYTE(a>>16);
+    b[0]=MR_TOBYTE(a>>24);
+}
+
+static void precompute(gcm *g,uchar *H)
+{
+    /* precompute small 2k bytes gf2m table of x^n.H */
+    int i,j;
+    unsign32 *last,*next,b;
+
+    for (i=j=0; i<NB; i++,j+=4) g->table[0][i]=pack((uchar *)&H[j]);
+
+    for (i=1; i<128; i++)
+    {
+        next=g->table[i];
+        last=g->table[i-1];
+        b=0;
+        for (j=0; j<NB; j++)
+        {
+            next[j]=b|(last[j])>>1;
+            b=last[j]<<31;
+        }
+        if (b) next[0]^=0xE1000000; /* irreducible polynomial */
+    }
+}
+
+/* SU= 32 */
+static void gf2mul(gcm *g)
+{
+    /* gf2m mul - Z=H*X mod 2^128 */
+    int i,j,m,k;
+    unsign32 P[4];
+    unsign32 b;
+
+    P[0]=P[1]=P[2]=P[3]=0;
+    j=8;
+    m=0;
+    for (i=0; i<128; i++)
+    {
+        b=(unsign32)(g->stateX[m]>>(--j))&1;
+        b=~b+1;
+        for (k=0; k<NB; k++) P[k]^=(g->table[i][k]&b);
+        if (j==0)
+        {
+            j=8;
+            m++;
+            if (m==16) break;
+        }
+    }
+    for (i=j=0; i<NB; i++,j+=4) unpack(P[i],(uchar *)&g->stateX[j]);
+}
+
+/* SU= 32 */
+static void GCM_wrap(gcm *g)
+{
+    /* Finish off GHASH */
+    int i,j;
+    unsign32 F[4];
+    uchar L[16];
+
+    /* convert lengths from bytes to bits */
+    F[0]=(g->lenA[0]<<3)|(g->lenA[1]&0xE0000000)>>29;
+    F[1]=g->lenA[1]<<3;
+    F[2]=(g->lenC[0]<<3)|(g->lenC[1]&0xE0000000)>>29;
+    F[3]=g->lenC[1]<<3;
+    for (i=j=0; i<NB; i++,j+=4) unpack(F[i],(uchar *)&L[j]);
+
+    for (i=0; i<16; i++) g->stateX[i]^=L[i];
+    gf2mul(g);
+}
+
+static int GCM_ghash(gcm *g,char *plain,int len)
+{
+    int i,j=0;
+    if (g->status==GCM_ACCEPTING_HEADER) g->status=GCM_ACCEPTING_CIPHER;
+    if (g->status!=GCM_ACCEPTING_CIPHER) return 0;
+
+    while (j<len)
+    {
+        for (i=0; i<16 && j<len; i++)
+        {
+            g->stateX[i]^=plain[j++];
+            g->lenC[1]++;
+            if (g->lenC[1]==0) g->lenC[0]++;
+        }
+        gf2mul(g);
+    }
+    if (len%16!=0) g->status=GCM_NOT_ACCEPTING_MORE;
+    return 1;
+}
+
+/* SU= 48 */
+/* Initialize GCM mode */
+void amcl::GCM_init(gcm* g,int nk,char *key,int niv,char *iv)
+{
+    /* iv size niv is usually 12 bytes (96 bits). AES key size nk can be 16,24 or 32 bytes */
+    int i;
+    uchar H[16];
+    for (i=0; i<16; i++)
+    {
+        H[i]=0;
+        g->stateX[i]=0;
+    }
+
+    AES_init(&(g->a),ECB,nk,key,iv);
+    AES_ecb_encrypt(&(g->a),H);     /* E(K,0) */
+    precompute(g,H);
+
+    g->lenA[0]=g->lenC[0]=g->lenA[1]=g->lenC[1]=0;
+    if (niv==12)
+    {
+        for (i=0; i<12; i++) g->a.f[i]=iv[i];
+        unpack((unsign32)1,(uchar *)&(g->a.f[12]));  /* initialise IV */
+        for (i=0; i<16; i++) g->Y_0[i]=g->a.f[i];
+    }
+    else
+    {
+        g->status=GCM_ACCEPTING_CIPHER;
+        GCM_ghash(g,iv,niv); /* GHASH(H,0,IV) */
+        GCM_wrap(g);
+        for (i=0; i<16; i++)
+        {
+            g->a.f[i]=g->stateX[i];
+            g->Y_0[i]=g->a.f[i];
+            g->stateX[i]=0;
+        }
+        g->lenA[0]=g->lenC[0]=g->lenA[1]=g->lenC[1]=0;
+    }
+    g->status=GCM_ACCEPTING_HEADER;
+}
+
+/* SU= 24 */
+/* Add Header data - included but not encrypted */
+int amcl::GCM_add_header(gcm* g,char *header,int len)
+{
+    /* Add some header. Won't be encrypted, but will be authenticated. len is length of header */
+    int i,j=0;
+    if (g->status!=GCM_ACCEPTING_HEADER) return 0;
+
+    while (j<len)
+    {
+        for (i=0; i<16 && j<len; i++)
+        {
+            g->stateX[i]^=header[j++];
+            g->lenA[1]++;
+            if (g->lenA[1]==0) g->lenA[0]++;
+        }
+        gf2mul(g);
+    }
+    if (len%16!=0) g->status=GCM_ACCEPTING_CIPHER;
+    return 1;
+}
+
+/* SU= 48 */
+/* Add Plaintext - included and encrypted */
+int amcl::GCM_add_plain(gcm *g,char *cipher,char *plain,int len)
+{
+    /* Add plaintext to extract ciphertext, len is length of plaintext.  */
+    int i,j=0;
+    unsign32 counter;
+    uchar B[16];
+    if (g->status==GCM_ACCEPTING_HEADER) g->status=GCM_ACCEPTING_CIPHER;
+    if (g->status!=GCM_ACCEPTING_CIPHER) return 0;
+
+    while (j<len)
+    {
+        counter=pack((uchar *)&(g->a.f[12]));
+        counter++;
+        unpack(counter,(uchar *)&(g->a.f[12]));  /* increment counter */
+        for (i=0; i<16; i++) B[i]=g->a.f[i];
+        AES_ecb_encrypt(&(g->a),B);        /* encrypt it  */
+
+        for (i=0; i<16 && j<len; i++)
+        {
+            cipher[j]=plain[j]^B[i];
+            g->stateX[i]^=cipher[j++];
+            g->lenC[1]++;
+            if (g->lenC[1]==0) g->lenC[0]++;
+        }
+        gf2mul(g);
+    }
+    if (len%16!=0) g->status=GCM_NOT_ACCEPTING_MORE;
+    return 1;
+}
+
+/* SU= 48 */
+/* Add Ciphertext - decrypts to plaintext */
+int amcl::GCM_add_cipher(gcm *g,char *plain,char *cipher,int len)
+{
+    /* Add ciphertext to extract plaintext, len is length of ciphertext. */
+    int i,j=0;
+    unsign32 counter;
+    char oc;
+    uchar B[16];
+    if (g->status==GCM_ACCEPTING_HEADER) g->status=GCM_ACCEPTING_CIPHER;
+    if (g->status!=GCM_ACCEPTING_CIPHER) return 0;
+
+    while (j<len)
+    {
+        counter=pack((uchar *)&(g->a.f[12]));
+        counter++;
+        unpack(counter,(uchar *)&(g->a.f[12]));  /* increment counter */
+        for (i=0; i<16; i++) B[i]=g->a.f[i];
+        AES_ecb_encrypt(&(g->a),B);        /* encrypt it  */
+        for (i=0; i<16 && j<len; i++)
+        {
+            oc=cipher[j];
+            plain[j]=cipher[j]^B[i];
+            g->stateX[i]^=oc;
+            j++;
+            g->lenC[1]++;
+            if (g->lenC[1]==0) g->lenC[0]++;
+        }
+        gf2mul(g);
+    }
+    if (len%16!=0) g->status=GCM_NOT_ACCEPTING_MORE;
+    return 1;
+}
+
+/* SU= 16 */
+/* Finish and extract Tag */
+void amcl::GCM_finish(gcm *g,char *tag)
+{
+    /* Finish off GHASH and extract tag (MAC) */
+    int i;
+
+    GCM_wrap(g);
+
+    /* extract tag */
+    if (tag!=NULL)
+    {
+        AES_ecb_encrypt(&(g->a),g->Y_0);        /* E(K,Y0) */
+        for (i=0; i<16; i++) g->Y_0[i]^=g->stateX[i];
+        for (i=0; i<16; i++)
+        {
+            tag[i]=g->Y_0[i];
+            g->Y_0[i]=g->stateX[i]=0;
+        }
+    }
+    g->status=GCM_FINISHED;
+    AES_end(&(g->a));
+}
+
+
+// Compile with
+// gcc -O2 gcm.c aes.c -o gcm.exe
+/* SU= 16
+*/
+
+/* static void hex2bytes(char *hex,char *bin) */
+/* { */
+/* 	int i; */
+/* 	char v; */
+/* 	int len=strlen(hex); */
+/* 	for (i = 0; i < len/2; i++) { */
+/*         char c = hex[2*i]; */
+/*         if (c >= '0' && c <= '9') { */
+/*             v = c - '0'; */
+/*         } else if (c >= 'A' && c <= 'F') { */
+/*             v = c - 'A' + 10; */
+/*         } else if (c >= 'a' && c <= 'f') { */
+/*             v = c - 'a' + 10; */
+/*         } else { */
+/*             v = 0; */
+/*         } */
+/*         v <<= 4; */
+/*         c = hex[2*i + 1]; */
+/*         if (c >= '0' && c <= '9') { */
+/*             v += c - '0'; */
+/*         } else if (c >= 'A' && c <= 'F') { */
+/*             v += c - 'A' + 10; */
+/*         } else if (c >= 'a' && c <= 'f') { */
+/*             v += c - 'a' + 10; */
+/*         } else { */
+/*             v = 0; */
+/*         } */
+/*         bin[i] = v; */
+/*     } */
+/* } */
+
+/*
+int main()
+{
+	int i;
+
+//	char* KT="feffe9928665731c6d6a8f9467308308";
+//	char* MT="d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39";
+//	char* HT="feedfacedeadbeeffeedfacedeadbeefabaddad2";
+//	char* NT="cafebabefacedbaddecaf888";
+// Tag should be 5bc94fbc3221a5db94fae95ae7121a47
+//	char* NT="9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b";
+// Tag should be 619cc5aefffe0bfa462af43c1699d050
+
+  char* KT="6dfb5dc68af6ae2f3242e9184f100918";
+  char* MT="47809d16c2c6ec685962c90e53fe1bba";
+  char* HT="dd0fa6e494031139d71ee45f00d56fa4";
+  char* NT="37d36f5c54d53479d4745dd1";
+
+
+	int len=strlen(MT)/2;
+	int lenH=strlen(HT)/2;
+	int lenK=strlen(KT)/2;
+	int lenIV=strlen(NT)/2;
+
+	char T[16];   // Tag
+	char K[16];   // AES Key
+	char H[64];   // Header - to be included in Authentication, but not encrypted
+	char N[100];   // IV - Initialisation vector
+	char M[100];  // Plaintext to be encrypted/authenticated
+	char C[100];  // Ciphertext
+	char P[100];  // Recovered Plaintext
+
+	gcm g;
+
+    hex2bytes(MT, M);
+    hex2bytes(HT, H);
+    hex2bytes(NT, N);
+	hex2bytes(KT, K);
+
+	printf("lenK= %d\n",lenK);
+
+ 	printf("Plaintext=\n");
+	for (i=0;i<len;i++) printf("%02x",(unsigned char)M[i]);
+	printf("\n");
+
+	GCM_init(&g,16,K,lenIV,N);
+	GCM_add_header(&g,H,lenH);
+	GCM_add_plain(&g,C,M,len);
+	GCM_finish(&g,T);
+
+	printf("Ciphertext=\n");
+	for (i=0;i<len;i++) printf("%02x",(unsigned char)C[i]);
+	printf("\n");
+
+	printf("Tag=\n");
+	for (i=0;i<16;i++) printf("%02x",(unsigned char)T[i]);
+	printf("\n");
+
+	GCM_init(&g,16,K,lenIV,N);
+	GCM_add_header(&g,H,lenH);
+	GCM_add_cipher(&g,P,C,len);
+	GCM_finish(&g,T);
+
+ 	printf("Plaintext=\n");
+	for (i=0;i<len;i++) printf("%02x",(unsigned char)P[i]);
+	printf("\n");
+
+	printf("Tag=\n");
+	for (i=0;i<16;i++) printf("%02x",(unsigned char)T[i]);
+	printf("\n");
+}
+
+*/
diff --git a/version3/cpp/hash.cpp b/version3/cpp/hash.cpp
new file mode 100644
index 0000000..676f145
--- /dev/null
+++ b/version3/cpp/hash.cpp
@@ -0,0 +1,599 @@
+/*
+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.
+*/
+
+/*
+ * Implementation of the Secure Hashing Algorithm (SHA-256/384/512 and SHA3)
+ *
+ * Generates a message digest. It should be impossible to come
+ * come up with two messages that hash to the same value ("collision free").
+ *
+ * For use with byte-oriented messages only. Could/Should be speeded
+ * up by unwinding loops in HASH_transform(), and assembly patches.
+ */
+
+#include "arch.h"
+#include "amcl.h"
+
+using namespace amcl;
+
+#define H0_256 0x6A09E667L
+#define H1_256 0xBB67AE85L
+#define H2_256 0x3C6EF372L
+#define H3_256 0xA54FF53AL
+#define H4_256 0x510E527FL
+#define H5_256 0x9B05688CL
+#define H6_256 0x1F83D9ABL
+#define H7_256 0x5BE0CD19L
+
+static const unsign32 K_256[64]=
+{
+    0x428a2f98L,0x71374491L,0xb5c0fbcfL,0xe9b5dba5L,0x3956c25bL,0x59f111f1L,0x923f82a4L,0xab1c5ed5L,
+    0xd807aa98L,0x12835b01L,0x243185beL,0x550c7dc3L,0x72be5d74L,0x80deb1feL,0x9bdc06a7L,0xc19bf174L,
+    0xe49b69c1L,0xefbe4786L,0x0fc19dc6L,0x240ca1ccL,0x2de92c6fL,0x4a7484aaL,0x5cb0a9dcL,0x76f988daL,
+    0x983e5152L,0xa831c66dL,0xb00327c8L,0xbf597fc7L,0xc6e00bf3L,0xd5a79147L,0x06ca6351L,0x14292967L,
+    0x27b70a85L,0x2e1b2138L,0x4d2c6dfcL,0x53380d13L,0x650a7354L,0x766a0abbL,0x81c2c92eL,0x92722c85L,
+    0xa2bfe8a1L,0xa81a664bL,0xc24b8b70L,0xc76c51a3L,0xd192e819L,0xd6990624L,0xf40e3585L,0x106aa070L,
+    0x19a4c116L,0x1e376c08L,0x2748774cL,0x34b0bcb5L,0x391c0cb3L,0x4ed8aa4aL,0x5b9cca4fL,0x682e6ff3L,
+    0x748f82eeL,0x78a5636fL,0x84c87814L,0x8cc70208L,0x90befffaL,0xa4506cebL,0xbef9a3f7L,0xc67178f2L
+};
+
+#define PAD  0x80
+#define ZERO 0
+
+/* functions */
+
+#define S(m,n,x) (((x)>>n) | ((x)<<(m-n)))
+#define R(n,x) ((x)>>n)
+
+#define Ch(x,y,z)  ((x&y)^(~(x)&z))
+#define Maj(x,y,z) ((x&y)^(x&z)^(y&z))
+#define Sig0_256(x)    (S(32,2,x)^S(32,13,x)^S(32,22,x))
+#define Sig1_256(x)    (S(32,6,x)^S(32,11,x)^S(32,25,x))
+#define theta0_256(x)  (S(32,7,x)^S(32,18,x)^R(3,x))
+#define theta1_256(x)  (S(32,17,x)^S(32,19,x)^R(10,x))
+
+#define Sig0_512(x)    (S(64,28,x)^S(64,34,x)^S(64,39,x))
+#define Sig1_512(x)    (S(64,14,x)^S(64,18,x)^S(64,41,x))
+#define theta0_512(x)  (S(64,1,x)^S(64,8,x)^R(7,x))
+#define theta1_512(x)  (S(64,19,x)^S(64,61,x)^R(6,x))
+
+
+/* SU= 72 */
+static void HASH256_transform(hash256 *sh)
+{
+    /* basic transformation step */
+    unsign32 a,b,c,d,e,f,g,h,t1,t2;
+    int j;
+    for (j=16; j<64; j++)
+        sh->w[j]=theta1_256(sh->w[j-2])+sh->w[j-7]+theta0_256(sh->w[j-15])+sh->w[j-16];
+
+    a=sh->h[0];
+    b=sh->h[1];
+    c=sh->h[2];
+    d=sh->h[3];
+    e=sh->h[4];
+    f=sh->h[5];
+    g=sh->h[6];
+    h=sh->h[7];
+
+    for (j=0; j<64; j++)
+    {
+        /* 64 times - mush it up */
+        t1=h+Sig1_256(e)+Ch(e,f,g)+K_256[j]+sh->w[j];
+        t2=Sig0_256(a)+Maj(a,b,c);
+        h=g;
+        g=f;
+        f=e;
+        e=d+t1;
+        d=c;
+        c=b;
+        b=a;
+        a=t1+t2;
+    }
+
+    sh->h[0]+=a;
+    sh->h[1]+=b;
+    sh->h[2]+=c;
+    sh->h[3]+=d;
+    sh->h[4]+=e;
+    sh->h[5]+=f;
+    sh->h[6]+=g;
+    sh->h[7]+=h;
+}
+
+/* Initialise Hash function */
+void amcl::HASH256_init(hash256 *sh)
+{
+    /* re-initialise */
+    int i;
+    for (i=0; i<64; i++) sh->w[i]=0L;
+    sh->length[0]=sh->length[1]=0L;
+    sh->h[0]=H0_256;
+    sh->h[1]=H1_256;
+    sh->h[2]=H2_256;
+    sh->h[3]=H3_256;
+    sh->h[4]=H4_256;
+    sh->h[5]=H5_256;
+    sh->h[6]=H6_256;
+    sh->h[7]=H7_256;
+
+    sh->hlen=32;
+}
+
+/* process a single byte */
+void amcl::HASH256_process(hash256 *sh,int byt)
+{
+    /* process the next message byte */
+    int cnt;
+//printf("byt= %x\n",byt);
+    cnt=(int)((sh->length[0]/32)%16);
+
+    sh->w[cnt]<<=8;
+    sh->w[cnt]|=(unsign32)(byt&0xFF);
+
+    sh->length[0]+=8;
+    if (sh->length[0]==0L)
+    {
+        sh->length[1]++;
+        sh->length[0]=0L;
+    }
+    if ((sh->length[0]%512)==0) HASH256_transform(sh);
+}
+
+/* SU= 24 */
+/* Generate 32-byte Hash */
+void amcl::HASH256_hash(hash256 *sh,char *digest)
+{
+    /* pad message and finish - supply digest */
+    int i;
+    unsign32 len0,len1;
+    len0=sh->length[0];
+    len1=sh->length[1];
+    HASH256_process(sh,PAD);
+    while ((sh->length[0]%512)!=448) HASH256_process(sh,ZERO);
+    sh->w[14]=len1;
+    sh->w[15]=len0;
+    HASH256_transform(sh);
+    for (i=0; i<sh->hlen; i++)
+    {
+        /* convert to bytes */
+        digest[i]=(char)((sh->h[i/4]>>(8*(3-i%4))) & 0xffL);
+    }
+    HASH256_init(sh);
+}
+
+
+#define H0_512 0x6a09e667f3bcc908
+#define H1_512 0xbb67ae8584caa73b
+#define H2_512 0x3c6ef372fe94f82b
+#define H3_512 0xa54ff53a5f1d36f1
+#define H4_512 0x510e527fade682d1
+#define H5_512 0x9b05688c2b3e6c1f
+#define H6_512 0x1f83d9abfb41bd6b
+#define H7_512 0x5be0cd19137e2179
+
+#define H8_512 0xcbbb9d5dc1059ed8
+#define H9_512 0x629a292a367cd507
+#define HA_512 0x9159015a3070dd17
+#define HB_512 0x152fecd8f70e5939
+#define HC_512 0x67332667ffc00b31
+#define HD_512 0x8eb44a8768581511
+#define HE_512 0xdb0c2e0d64f98fa7
+#define HF_512 0x47b5481dbefa4fa4
+
+/* */
+
+static const unsign64 K_512[80]=
+{
+    0x428a2f98d728ae22 ,0x7137449123ef65cd ,0xb5c0fbcfec4d3b2f ,0xe9b5dba58189dbbc ,
+    0x3956c25bf348b538 ,0x59f111f1b605d019 ,0x923f82a4af194f9b ,0xab1c5ed5da6d8118 ,
+    0xd807aa98a3030242 ,0x12835b0145706fbe ,0x243185be4ee4b28c ,0x550c7dc3d5ffb4e2 ,
+    0x72be5d74f27b896f ,0x80deb1fe3b1696b1 ,0x9bdc06a725c71235 ,0xc19bf174cf692694 ,
+    0xe49b69c19ef14ad2 ,0xefbe4786384f25e3 ,0x0fc19dc68b8cd5b5 ,0x240ca1cc77ac9c65 ,
+    0x2de92c6f592b0275 ,0x4a7484aa6ea6e483 ,0x5cb0a9dcbd41fbd4 ,0x76f988da831153b5 ,
+    0x983e5152ee66dfab ,0xa831c66d2db43210 ,0xb00327c898fb213f ,0xbf597fc7beef0ee4 ,
+    0xc6e00bf33da88fc2 ,0xd5a79147930aa725 ,0x06ca6351e003826f ,0x142929670a0e6e70 ,
+    0x27b70a8546d22ffc ,0x2e1b21385c26c926 ,0x4d2c6dfc5ac42aed ,0x53380d139d95b3df ,
+    0x650a73548baf63de ,0x766a0abb3c77b2a8 ,0x81c2c92e47edaee6 ,0x92722c851482353b ,
+    0xa2bfe8a14cf10364 ,0xa81a664bbc423001 ,0xc24b8b70d0f89791 ,0xc76c51a30654be30 ,
+    0xd192e819d6ef5218 ,0xd69906245565a910 ,0xf40e35855771202a ,0x106aa07032bbd1b8 ,
+    0x19a4c116b8d2d0c8 ,0x1e376c085141ab53 ,0x2748774cdf8eeb99 ,0x34b0bcb5e19b48a8 ,
+    0x391c0cb3c5c95a63 ,0x4ed8aa4ae3418acb ,0x5b9cca4f7763e373 ,0x682e6ff3d6b2b8a3 ,
+    0x748f82ee5defb2fc ,0x78a5636f43172f60 ,0x84c87814a1f0ab72 ,0x8cc702081a6439ec ,
+    0x90befffa23631e28 ,0xa4506cebde82bde9 ,0xbef9a3f7b2c67915 ,0xc67178f2e372532b ,
+    0xca273eceea26619c ,0xd186b8c721c0c207 ,0xeada7dd6cde0eb1e ,0xf57d4f7fee6ed178 ,
+    0x06f067aa72176fba ,0x0a637dc5a2c898a6 ,0x113f9804bef90dae ,0x1b710b35131c471b ,
+    0x28db77f523047d84 ,0x32caab7b40c72493 ,0x3c9ebe0a15c9bebc ,0x431d67c49c100d4c ,
+    0x4cc5d4becb3e42b6 ,0x597f299cfc657e2a ,0x5fcb6fab3ad6faec ,0x6c44198c4a475817
+};
+
+
+static void HASH512_transform(hash512 *sh)
+{
+    /* basic transformation step */
+    unsign64 a,b,c,d,e,f,g,h,t1,t2;
+    int j;
+    for (j=16; j<80; j++)
+        sh->w[j]=theta1_512(sh->w[j-2])+sh->w[j-7]+theta0_512(sh->w[j-15])+sh->w[j-16];
+
+    a=sh->h[0];
+    b=sh->h[1];
+    c=sh->h[2];
+    d=sh->h[3];
+    e=sh->h[4];
+    f=sh->h[5];
+    g=sh->h[6];
+    h=sh->h[7];
+
+    for (j=0; j<80; j++)
+    {
+        /* 80 times - mush it up */
+        t1=h+Sig1_512(e)+Ch(e,f,g)+K_512[j]+sh->w[j];
+        t2=Sig0_512(a)+Maj(a,b,c);
+        h=g;
+        g=f;
+        f=e;
+        e=d+t1;
+        d=c;
+        c=b;
+        b=a;
+        a=t1+t2;
+    }
+    sh->h[0]+=a;
+    sh->h[1]+=b;
+    sh->h[2]+=c;
+    sh->h[3]+=d;
+    sh->h[4]+=e;
+    sh->h[5]+=f;
+    sh->h[6]+=g;
+    sh->h[7]+=h;
+}
+
+void amcl::HASH384_init(hash384 *sh)
+{
+    /* re-initialise */
+    int i;
+    for (i=0; i<80; i++) sh->w[i]=0;
+    sh->length[0]=sh->length[1]=0;
+    sh->h[0]=H8_512;
+    sh->h[1]=H9_512;
+    sh->h[2]=HA_512;
+    sh->h[3]=HB_512;
+    sh->h[4]=HC_512;
+    sh->h[5]=HD_512;
+    sh->h[6]=HE_512;
+    sh->h[7]=HF_512;
+
+    sh->hlen=48;
+
+}
+
+void amcl::HASH384_process(hash384 *sh,int byt)
+{
+    /* process the next message byte */
+    HASH512_process(sh,byt);
+}
+
+void amcl::HASH384_hash(hash384 *sh,char *hash)
+{
+    /* pad message and finish - supply digest */
+    HASH512_hash(sh,hash);
+}
+
+void amcl::HASH512_init(hash512 *sh)
+{
+    /* re-initialise */
+    int i;
+
+    for (i=0; i<80; i++) sh->w[i]=0;
+    sh->length[0]=sh->length[1]=0;
+    sh->h[0]=H0_512;
+    sh->h[1]=H1_512;
+    sh->h[2]=H2_512;
+    sh->h[3]=H3_512;
+    sh->h[4]=H4_512;
+    sh->h[5]=H5_512;
+    sh->h[6]=H6_512;
+    sh->h[7]=H7_512;
+
+    sh->hlen=64;
+}
+
+void amcl::HASH512_process(hash512 *sh,int byt)
+{
+    /* process the next message byte */
+    int cnt;
+
+    cnt=(int)((sh->length[0]/64)%16);
+
+    sh->w[cnt]<<=8;
+    sh->w[cnt]|=(unsign64)(byt&0xFF);
+
+    sh->length[0]+=8;
+    if (sh->length[0]==0L)
+    {
+        sh->length[1]++;
+        sh->length[0]=0L;
+    }
+    if ((sh->length[0]%1024)==0) HASH512_transform(sh);
+}
+
+void amcl::HASH512_hash(hash512 *sh,char *hash)
+{
+    /* pad message and finish - supply digest */
+    int i;
+    unsign64 len0,len1;
+    len0=sh->length[0];
+    len1=sh->length[1];
+    HASH512_process(sh,PAD);
+    while ((sh->length[0]%1024)!=896) HASH512_process(sh,ZERO);
+    sh->w[14]=len1;
+    sh->w[15]=len0;
+    HASH512_transform(sh);
+    for (i=0; i<sh->hlen; i++)
+    {
+        /* convert to bytes */
+        hash[i]=(char)((sh->h[i/8]>>(8*(7-i%8))) & 0xffL);
+    }
+    HASH512_init(sh);
+}
+
+
+
+/* SHA3 */
+
+#define SHA3_ROUNDS 24
+#define rotl(x,n) (((x)<<n) | ((x)>>(64-n)))
+
+/* round constants */
+
+static const unsign64 RC[24]={
+0x0000000000000001UL,0x0000000000008082UL,0x800000000000808AUL,0x8000000080008000UL,
+0x000000000000808BUL,0x0000000080000001UL,0x8000000080008081UL,0x8000000000008009UL,
+0x000000000000008AUL,0x0000000000000088UL,0x0000000080008009UL,0x000000008000000AUL,
+0x000000008000808BUL,0x800000000000008BUL,0x8000000000008089UL,0x8000000000008003UL,
+0x8000000000008002UL,0x8000000000000080UL,0x000000000000800AUL,0x800000008000000AUL,
+0x8000000080008081UL,0x8000000000008080UL,0x0000000080000001UL,0x8000000080008008UL};
+
+/* permutation */
+
+static void SHA3_transform(sha3 *sh)
+{
+	int i,j,k;
+	unsign64 C[5],D[5],B[5][5];
+	
+	for (k=0;k<SHA3_ROUNDS;k++)
+	{
+		C[0]=sh->S[0][0]^sh->S[0][1]^sh->S[0][2]^sh->S[0][3]^sh->S[0][4];
+		C[1]=sh->S[1][0]^sh->S[1][1]^sh->S[1][2]^sh->S[1][3]^sh->S[1][4];
+		C[2]=sh->S[2][0]^sh->S[2][1]^sh->S[2][2]^sh->S[2][3]^sh->S[2][4];
+		C[3]=sh->S[3][0]^sh->S[3][1]^sh->S[3][2]^sh->S[3][3]^sh->S[3][4];
+		C[4]=sh->S[4][0]^sh->S[4][1]^sh->S[4][2]^sh->S[4][3]^sh->S[4][4];
+
+		D[0]=C[4]^rotl(C[1],1);
+		D[1]=C[0]^rotl(C[2],1);
+		D[2]=C[1]^rotl(C[3],1);
+		D[3]=C[2]^rotl(C[4],1);
+		D[4]=C[3]^rotl(C[0],1);
+
+		for (i=0;i<5;i++)
+			for (j=0;j<5;j++)
+				sh->S[i][j]^=D[i];  /* let the compiler unroll it! */
+
+		B[0][0]=sh->S[0][0];
+		B[1][3]=rotl(sh->S[0][1],36);
+		B[2][1]=rotl(sh->S[0][2],3);
+		B[3][4]=rotl(sh->S[0][3],41);
+		B[4][2]=rotl(sh->S[0][4],18);
+
+		B[0][2]=rotl(sh->S[1][0],1);
+		B[1][0]=rotl(sh->S[1][1],44);
+		B[2][3]=rotl(sh->S[1][2],10);
+		B[3][1]=rotl(sh->S[1][3],45);
+		B[4][4]=rotl(sh->S[1][4],2);
+
+		B[0][4]=rotl(sh->S[2][0],62);
+		B[1][2]=rotl(sh->S[2][1],6);
+		B[2][0]=rotl(sh->S[2][2],43);
+		B[3][3]=rotl(sh->S[2][3],15);
+		B[4][1]=rotl(sh->S[2][4],61);
+
+		B[0][1]=rotl(sh->S[3][0],28);
+		B[1][4]=rotl(sh->S[3][1],55);
+		B[2][2]=rotl(sh->S[3][2],25);
+		B[3][0]=rotl(sh->S[3][3],21);
+		B[4][3]=rotl(sh->S[3][4],56);
+
+		B[0][3]=rotl(sh->S[4][0],27);
+		B[1][1]=rotl(sh->S[4][1],20);
+		B[2][4]=rotl(sh->S[4][2],39);
+		B[3][2]=rotl(sh->S[4][3],8);
+		B[4][0]=rotl(sh->S[4][4],14);
+
+		for (i=0;i<5;i++)
+			for (j=0;j<5;j++)
+				sh->S[i][j]=B[i][j]^(~B[(i+1)%5][j]&B[(i+2)%5][j]);
+
+		sh->S[0][0]^=RC[k];
+	}
+}
+
+/* Re-Initialize. olen is output length in bytes - 
+   should be 28, 32, 48 or 64 (224, 256, 384, 512 bits resp.) */
+
+void amcl::SHA3_init(sha3 *sh,int olen)
+{ 
+    int i,j;
+    for (i=0;i<5;i++) 
+		for (j=0;j<5;j++)
+			sh->S[i][j]=0;    /* 5x5x8 bytes = 200 bytes of state */
+    sh->length=0;
+	sh->len=olen;
+	sh->rate=200-2*olen; /* number of bytes consumed in one gulp. Note that some bytes in the 
+	                        state ("capacity") are not touched. Gulps are smaller for larger digests. 
+							Important that olen<rate */
+}
+
+/* process a single byte */
+void amcl::SHA3_process(sha3 *sh,int byt)
+{
+	int cnt=(int)(sh->length%sh->rate);
+	int i,j,b=cnt%8;
+	cnt/=8;
+	i=cnt%5; j=cnt/5;  /* process by columns! */
+	sh->S[i][j]^=((unsign64)byt<<(8*b));
+	sh->length++;
+	if (sh->length%sh->rate==0) SHA3_transform(sh);
+}
+
+/* squeeze the sponge */
+void amcl::SHA3_squeeze(sha3 *sh,char *buff,int len)
+{
+	int done,i,j,k,m=0;
+	unsign64 el;
+/* extract by columns */
+	done=0;
+	for (;;)
+	{
+		for (j=0;j<5;j++)
+		{
+			for (i=0;i<5;i++)
+			{
+				el=sh->S[i][j];
+				for (k=0;k<8;k++)
+				{
+					buff[m++]=(el&0xff);
+					if (m>=len || m%sh->rate==0) {done=1; break;} 
+					el>>=8;
+				}
+				if (done) break;
+			}
+			if (done) break;
+		}
+		if (m>=len) break;
+		done=0;
+		SHA3_transform(sh);
+	}
+}
+
+void amcl::SHA3_hash(sha3 *sh,char *hash)
+{ /* generate a SHA3 hash of appropriate size */
+	int q=sh->rate-(sh->length%sh->rate);
+	if (q==1) SHA3_process(sh,0x86); 
+	else
+	{
+		SHA3_process(sh,0x06);   /* 0x06 for SHA-3 */
+		while (sh->length%sh->rate!=sh->rate-1) SHA3_process(sh,0x00);
+		SHA3_process(sh,0x80); /* this will force a final transform */
+	}
+	SHA3_squeeze(sh,hash,sh->len);
+}
+
+void amcl::SHA3_shake(sha3 *sh,char *buff,int len)
+{ /* SHAKE out a buffer of variable length len */
+	int q=sh->rate-(sh->length%sh->rate);
+	if (q==1) SHA3_process(sh,0x9f); 
+	else
+	{
+		SHA3_process(sh,0x1f);   // 0x06 for SHA-3 !!!!
+		while (sh->length%sh->rate!=sh->rate-1) SHA3_process(sh,0x00);
+		SHA3_process(sh,0x80); /* this will force a final transform */
+	}
+	SHA3_squeeze(sh,buff,len);
+}
+
+
+/* test program: should produce digest
+
+160 bit
+
+84983e44 1c3bd26e baae4aa1 f95129e5 e54670f1
+
+256 bit
+
+248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1
+
+512 bit
+
+8e959b75dae313da 8cf4f72814fc143f 8f7779c6eb9f7fa1 7299aeadb6889018
+501d289e4900f7e4 331b99dec4b5433a c7d329eeb6dd2654 5e96e55b874be909
+
+384 bit
+
+09330c33f71147e8 3d192fc782cd1b47 53111b173b3b05d2 2fa08086e3b0f712
+fcc7c71a557e2db9 66c3e9fa91746039
+*/
+/*
+#include <stdio.h>
+
+char test160[]="abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
+char test256[]="abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
+char test512[]="abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu";
+
+int main()
+{
+    char digest[100];
+    int i;
+
+    hash256 sh256;
+	hash384 sh384;
+	hash512 sh512;
+	sha3 SHA3;
+
+    HASH256_init(&sh256);
+    for (i=0;test256[i]!=0;i++) HASH256_process(&sh256,test256[i]);
+    HASH256_hash(&sh256,digest);
+    for (i=0;i<32;i++) printf("%02x",(unsigned char)digest[i]);
+    printf("\n");
+
+    HASH384_init(&sh384);
+    for (i=0;test512[i]!=0;i++) HASH384_process(&sh384,test512[i]);
+    HASH384_hash(&sh384,digest);
+    for (i=0;i<48;i++) printf("%02x",(unsigned char)digest[i]);
+    printf("\n");
+
+    HASH512_init(&sh512);
+    for (i=0;test512[i]!=0;i++) HASH512_process(&sh512,test512[i]);
+    HASH512_hash(&sh512,digest);
+    for (i=0;i<64;i++) printf("%02x",(unsigned char)digest[i]);
+    printf("\n");
+
+	SHA3_init(&SHA3,SHA3_HASH256);
+    for (i=0;test512[i]!=0;i++) SHA3_process(&SHA3,test512[i]);
+    SHA3_hash(&sh512,digest);
+    for (i=0;i<32;i++) printf("%02x",(unsigned char)digest[i]);
+    printf("\n");
+
+	SHA3_init(&SHA3,SHA3_HASH512);
+    for (i=0;test512[i]!=0;i++) SHA3_process(&SHA3,test512[i]);
+    SHA3_hash(&sh512,digest);
+    for (i=0;i<64;i++) printf("%02x",(unsigned char)digest[i]);
+    printf("\n");
+
+	SHA3_init(&SHA3,SHAKE256);
+    for (i=0;test512[i]!=0;i++) SHA3_process(&SHA3,test512[i]);
+    SHA3_shake(&sh512,digest,72);
+    for (i=0;i<72;i++) printf("%02x",(unsigned char)digest[i]);
+    printf("\n");
+
+
+    return 0;
+}
+
+*/
diff --git a/version3/cpp/mpin.cpp b/version3/cpp/mpin.cpp
new file mode 100644
index 0000000..337d008
--- /dev/null
+++ b/version3/cpp/mpin.cpp
@@ -0,0 +1,1012 @@
+/*
+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.
+*/
+
+/* MPIN Functions */
+
+/* Version 3.0 - supports Time Permits */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "mpin_ZZZ.h"
+
+using namespace XXX;
+using namespace YYY;
+
+#define ROUNDUP(a,b) ((a)-1)/(b)+1
+
+namespace ZZZ {
+	static void mpin_hash(int,FP4 *, ECP *,octet *);
+	static void map(ECP *,BIG ,int );
+	static int unmap(BIG ,int *,ECP *);
+}
+
+/* Special mpin hashing */
+static void ZZZ::mpin_hash(int sha,FP4 *f, ECP *P,octet *w)
+{
+    int i;
+    BIG x,y;
+    char h[64];
+    hash256 sha256;
+    hash512 sha512;
+    char t[6*MODBYTES_XXX];  // to hold 6 BIGs
+    int hlen=sha;
+
+
+	FP_redc(x,&(f->a.a));
+    BIG_toBytes(&t[0],x);
+    FP_redc(x,&(f->a.b));
+    BIG_toBytes(&t[MODBYTES_XXX],x);
+    FP_redc(x,&(f->b.a));
+    BIG_toBytes(&t[2*MODBYTES_XXX],x);
+    FP_redc(x,&(f->b.b));
+    BIG_toBytes(&t[3*MODBYTES_XXX],x);
+    ECP_get(x,y,P);
+    BIG_toBytes(&t[4*MODBYTES_XXX],x);
+    BIG_toBytes(&t[5*MODBYTES_XXX],y);
+
+    OCT_empty(w);
+    switch (sha)
+    {
+    case SHA256:
+        HASH256_init(&sha256);
+        for (i=0; i<6*MODBYTES_XXX; i++) HASH256_process(&sha256,t[i]);
+        HASH256_hash(&sha256,h);
+        break;
+    case SHA384:
+        HASH384_init(&sha512);
+        for (i=0; i<6*MODBYTES_XXX; i++) HASH384_process(&sha512,t[i]);
+        HASH384_hash(&sha512,h);
+        break;
+    case SHA512:
+        HASH512_init(&sha512);
+        for (i=0; i<6*MODBYTES_XXX; i++) HASH512_process(&sha512,t[i]);
+        HASH512_hash(&sha512,h);
+        break;
+    }
+
+    OCT_jbytes(w,h,AESKEY_ZZZ);
+    for (i=0; i<hlen; i++) h[i]=0;
+}
+
+/* these next two functions help to implement elligator squared - http://eprint.iacr.org/2014/043 */
+/* maps a random u to a point on the curve */
+static void ZZZ::map(ECP *P,BIG u,int cb)
+{
+    BIG x,q;
+
+    BIG_rcopy(q,Modulus);
+    BIG_copy(x,u);
+    BIG_mod(x,q);
+
+    while (!ECP_setx(P,x,cb))
+	{
+        BIG_inc(x,1); BIG_norm(x);
+	}
+}
+
+/* returns u derived from P. Random value in range 1 to return value should then be added to u */
+static int ZZZ::unmap(BIG u,int *cb,ECP *P)
+{
+    int s,r=0;
+    BIG x;
+
+    s=ECP_get(x,x,P);
+    BIG_copy(u,x);
+    do
+    {
+        BIG_dec(u,1); BIG_norm(u);
+        r++;
+    }
+    while (!ECP_setx(P,u,s));
+    ECP_setx(P,x,s);
+
+    *cb=s;
+
+    return r;
+}
+
+/* these next two functions implement elligator squared - http://eprint.iacr.org/2014/043 */
+/* Elliptic curve point E in format (0x04,x,y} is converted to form {0x0-,u,v} */
+/* Note that u and v are indistinguisible from random strings */
+int ZZZ::MPIN_ENCODING(csprng *RNG,octet *E)
+{
+    int rn,m,su,sv,res=0;
+
+    BIG q,u,v;
+    ECP P,W;
+
+    if (!ECP_fromOctet(&P,E)) res=MPIN_INVALID_POINT;
+    if (res==0)
+    {
+        BIG_rcopy(q,Modulus);
+
+        BIG_randomnum(u,q,RNG);
+
+        su=RAND_byte(RNG);
+        if (su<0) su=-su;
+        su%=2;
+        map(&W,u,su);
+        ECP_sub(&P,&W); //ECP_affine(&P);
+
+        rn=unmap(v,&sv,&P);
+        m=RAND_byte(RNG);
+        if (m<0) m=-m;
+        m%=rn;
+        BIG_inc(v,m+1);
+        E->val[0]=su+2*sv;
+        BIG_toBytes(&(E->val[1]),u);
+        BIG_toBytes(&(E->val[PFS_ZZZ+1]),v);
+    }
+    return res;
+}
+
+int ZZZ::MPIN_DECODING(octet *D)
+{
+    int su,sv;
+    BIG u,v;
+    ECP P,W;
+    int res=0;
+
+    if ((D->val[0]&0x04)!=0) res=MPIN_INVALID_POINT;
+    if (res==0)
+    {
+
+        BIG_fromBytes(u,&(D->val[1]));
+        BIG_fromBytes(v,&(D->val[PFS_ZZZ+1]));
+
+        su=D->val[0]&1;
+        sv=(D->val[0]>>1)&1;
+        map(&W,u,su);
+        map(&P,v,sv);
+        ECP_add(&P,&W); //ECP_affine(&P);
+        ECP_toOctet(D,&P,false);
+    }
+
+    return res;
+}
+
+/* R=R1+R2 in group G1 */
+int ZZZ::MPIN_RECOMBINE_G1(octet *R1,octet *R2,octet *R)
+{
+    ECP P,T;
+    int res=0;
+    if (res==0)
+    {
+        if (!ECP_fromOctet(&P,R1)) res=MPIN_INVALID_POINT;
+        if (!ECP_fromOctet(&T,R2)) res=MPIN_INVALID_POINT;
+    }
+    if (res==0)
+    {
+        ECP_add(&P,&T); //ECP_affine(&P);
+        ECP_toOctet(R,&P,false);
+    }
+    return res;
+}
+
+/* W=W1+W2 in group G2 */
+int ZZZ::MPIN_RECOMBINE_G2(octet *W1,octet *W2,octet *W)
+{
+    ECP2 Q,T;
+    int res=0;
+    if (!ECP2_fromOctet(&Q,W1)) res=MPIN_INVALID_POINT;
+    if (!ECP2_fromOctet(&T,W2)) res=MPIN_INVALID_POINT;
+    if (res==0)
+    {
+        ECP2_add(&Q,&T); //ECP2_affine(&Q);
+        ECP2_toOctet(W,&Q);
+    }
+    return res;
+}
+
+/* create random secret S */
+int ZZZ::MPIN_RANDOM_GENERATE(csprng *RNG,octet* S)
+{
+    BIG r,s;
+
+    BIG_rcopy(r,CURVE_Order);
+    BIG_randomnum(s,r,RNG);
+#ifdef AES_S
+    BIG_mod2m(s,2*AES_S);
+#endif
+    BIG_toBytes(S->val,s);
+    S->len=MODBYTES_XXX;
+    return 0;
+}
+
+/* Extract PIN from TOKEN for identity CID */
+int ZZZ::MPIN_EXTRACT_PIN(int sha,octet *CID,int pin,octet *TOKEN)
+{
+	pin%=MAXPIN;
+	return MPIN_EXTRACT_FACTOR(sha,CID,pin,PBLEN,TOKEN);
+}
+
+/* Extract a factor < 32 bits for identity CID */
+int ZZZ::MPIN_EXTRACT_FACTOR(int sha,octet *CID,int factor,int facbits,octet *TOKEN)
+{
+    ECP P,R;
+    int res=0;
+    char h[MODBYTES_XXX];
+    octet H= {0,sizeof(h),h};
+
+    if (!ECP_fromOctet(&P,TOKEN))  res=MPIN_INVALID_POINT;
+    if (res==0)
+    {
+        mhashit(sha,-1,CID,&H);
+        ECP_mapit(&R,&H);
+
+        ECP_pinmul(&R,factor,facbits);
+        ECP_sub(&P,&R); //ECP_affine(&P);
+
+        ECP_toOctet(TOKEN,&P,false);
+    }
+    return res;
+}
+
+/* Extract a factor < 32 bits for identity CID */
+int ZZZ::MPIN_RESTORE_FACTOR(int sha,octet *CID,int factor,int facbits,octet *TOKEN)
+{
+    ECP P,R;
+    int res=0;
+    char h[MODBYTES_XXX];
+    octet H= {0,sizeof(h),h};
+
+    if (!ECP_fromOctet(&P,TOKEN))  res=MPIN_INVALID_POINT;
+    if (res==0)
+    {
+        mhashit(sha,-1,CID,&H);
+        ECP_mapit(&R,&H);
+
+        ECP_pinmul(&R,factor,facbits);
+        ECP_add(&P,&R); //ECP_affine(&P);
+
+        ECP_toOctet(TOKEN,&P,false);
+    }
+    return res;
+}
+
+/* Implement step 2 on client side of MPin protocol - SEC=-(x+y)*SEC */
+int ZZZ::MPIN_CLIENT_2(octet *X,octet *Y,octet *SEC)
+{
+    BIG px,py,r;
+    ECP P;
+    int res=0;
+    BIG_rcopy(r,CURVE_Order);
+    if (!ECP_fromOctet(&P,SEC)) res=MPIN_INVALID_POINT;
+    if (res==0)
+    {
+        BIG_fromBytes(px,X->val);
+        BIG_fromBytes(py,Y->val);
+        BIG_add(px,px,py);
+        BIG_mod(px,r);
+        //	BIG_sub(px,r,px);
+        PAIR_G1mul(&P,px);
+        ECP_neg(&P);
+        ECP_toOctet(SEC,&P,false);   /* change to TRUE for point compression */
+
+/*		printf("CLIENT SEC= "); ECP_output(&P); printf("\n"); */
+    }
+    return res;
+}
+
+/*
+ W=x*H(G);
+ if RNG == NULL then X is passed in
+ if RNG != NULL the X is passed out
+ if type=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve
+*/
+
+int ZZZ::MPIN_GET_G1_MULTIPLE(csprng *RNG,int type,octet *X,octet *G,octet *W)
+{
+    ECP P;
+    BIG r,x;
+    int res=0;
+    if (RNG!=NULL)
+    {
+        BIG_rcopy(r,CURVE_Order);
+        BIG_randomnum(x,r,RNG);
+#ifdef AES_S
+        BIG_mod2m(x,2*AES_S);
+#endif
+        X->len=MODBYTES_XXX;
+        BIG_toBytes(X->val,x);
+    }
+    else
+        BIG_fromBytes(x,X->val);
+
+    if (type==0)
+    {
+        if (!ECP_fromOctet(&P,G)) res=MPIN_INVALID_POINT;
+    }
+    else 
+	{
+		ECP_mapit(&P,G);
+	}
+
+    if (res==0)
+    {
+        PAIR_G1mul(&P,x);
+        ECP_toOctet(W,&P,false);  /* change to TRUE for point compression */
+    }
+    return res;
+}
+
+/*
+ if RNG == NULL then X is passed in
+ if RNG != NULL the X is passed out
+ W=x*G where G is point on the curve
+ if type==1 W=(x^-1)G
+*/
+
+int ZZZ::MPIN_GET_G2_MULTIPLE(csprng *RNG,int type,octet *X,octet *G,octet *W)
+{
+    ECP2 P;
+    BIG r,x;
+    int res=0;
+    BIG_rcopy(r,CURVE_Order);
+    if (RNG!=NULL)
+    {
+        BIG_randomnum(x,r,RNG);
+#ifdef AES_S
+        BIG_mod2m(x,2*AES_S);
+#endif
+        X->len=MODBYTES_XXX;
+        BIG_toBytes(X->val,x);
+    }
+    else
+    {
+        BIG_fromBytes(x,X->val);
+        if (type==1) BIG_invmodp(x,x,r);
+    }
+
+    if (!ECP2_fromOctet(&P,G)) res=MPIN_INVALID_POINT;
+
+    if (res==0)
+    {
+        PAIR_G2mul(&P,x);
+        ECP2_toOctet(W,&P);
+    }
+    return res;
+}
+
+
+
+/* Client secret CST=s*H(CID) where CID is client ID and s is master secret */
+/* CID is hashed externally */
+int ZZZ::MPIN_GET_CLIENT_SECRET(octet *S,octet *CID,octet *CST)
+{
+    return MPIN_GET_G1_MULTIPLE(NULL,1,S,CID,CST);
+}
+
+/* Implement step 1 on client side of MPin protocol */
+int ZZZ::MPIN_CLIENT_1(int sha,int date,octet *CLIENT_ID,csprng *RNG,octet *X,int pin,octet *TOKEN,octet *SEC,octet *xID,octet *xCID,octet *PERMIT)
+{
+    BIG r,x;
+    ECP P,T,W;
+    int res=0;
+    char h[MODBYTES_XXX];
+    octet H= {0,sizeof(h),h};
+
+    BIG_rcopy(r,CURVE_Order);
+    if (RNG!=NULL)
+    {
+        BIG_randomnum(x,r,RNG);
+#ifdef AES_S
+        BIG_mod2m(x,2*AES_S);
+#endif
+        X->len=MODBYTES_XXX;
+        BIG_toBytes(X->val,x);
+    }
+    else
+        BIG_fromBytes(x,X->val);
+
+    mhashit(sha,-1,CLIENT_ID,&H);
+
+    ECP_mapit(&P,&H);
+
+    if (!ECP_fromOctet(&T,TOKEN)) res=MPIN_INVALID_POINT;
+
+    if (res==0)
+    {
+        pin%=MAXPIN;
+
+        ECP_copy(&W,&P);				// W=H(ID)
+        ECP_pinmul(&W,pin,PBLEN);			// W=alpha.H(ID)
+        ECP_add(&T,&W);					// T=Token+alpha.H(ID) = s.H(ID)
+
+        if (date)
+        {
+            if (PERMIT!=NULL)
+            {
+                if (!ECP_fromOctet(&W,PERMIT)) res=MPIN_INVALID_POINT;
+                ECP_add(&T,&W);					// SEC=s.H(ID)+s.H(T|ID)
+            }
+            mhashit(sha,date,&H,&H);
+
+            ECP_mapit(&W,&H);
+            if (xID!=NULL)
+            {
+                PAIR_G1mul(&P,x);				// P=x.H(ID)
+                ECP_toOctet(xID,&P,false);  // xID		/* change to TRUE for point compression */
+                PAIR_G1mul(&W,x);               // W=x.H(T|ID)
+                ECP_add(&P,&W); //ECP_affine(&P);
+            }
+            else
+            {
+                ECP_add(&P,&W); //ECP_affine(&P);
+                PAIR_G1mul(&P,x);
+            }
+            if (xCID!=NULL) ECP_toOctet(xCID,&P,false);  // U     /* change to TRUE for point compression */
+        }
+        else
+        {
+            if (xID!=NULL)
+            {
+                PAIR_G1mul(&P,x);				// P=x.H(ID)
+                ECP_toOctet(xID,&P,false);  // xID     /* change to TRUE for point compression */
+            }
+        }
+    }
+
+    if (res==0)
+	{
+		//ECP_affine(&T);
+        ECP_toOctet(SEC,&T,false);  // V    /* change to TRUE for point compression */
+	}
+    return res;
+}
+
+/* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */
+int ZZZ::MPIN_GET_SERVER_SECRET(octet *S,octet *SST)
+{
+    BIG r,s;
+    ECP2 Q;
+    int res=0;
+
+    BIG_rcopy(r,CURVE_Order);
+
+	ECP2_generator(&Q);
+
+    if (res==0)
+    {
+
+        BIG_fromBytes(s,S->val);
+//printf("Into G2mul\n");
+        PAIR_G2mul(&Q,s);
+//printf("Out of G2mul\n");
+        ECP2_toOctet(SST,&Q);
+    }
+
+    return res;
+}
+
+
+/* Time Permit CTT=s*H(date|H(CID)) where s is master secret */
+int ZZZ::MPIN_GET_CLIENT_PERMIT(int sha,int date,octet *S,octet *CID,octet *CTT)
+{
+    BIG s;
+    ECP P;
+    char h[MODBYTES_XXX];
+    octet H= {0,sizeof(h),h};
+
+    mhashit(sha,date,CID,&H);
+
+    ECP_mapit(&P,&H);
+
+//printf("P= "); ECP_output(&P); printf("\n");
+//exit(0);
+
+    BIG_fromBytes(s,S->val);
+
+
+
+//printf("s= "); BIG_output(s); printf("\n");
+    PAIR_G1mul(&P,s);
+//printf("OP= "); ECP_output(&P); printf("\n");
+//
+    ECP_toOctet(CTT,&P,false);
+    return 0;
+}
+
+// if date=0 only use HID, set HCID=NULL
+// if date and PE, use HID and HCID
+
+/* Outputs H(CID) and H(CID)+H(T|H(CID)) for time permits. If no time permits set HTID=NULL */
+void ZZZ::MPIN_SERVER_1(int sha,int date,octet *CID,octet *HID,octet *HTID)
+{
+    char h[MODBYTES_XXX];
+    octet H= {0,sizeof(h),h};
+    ECP P,R;
+	BIG x;
+
+#ifdef USE_ANONYMOUS
+    ECP_mapit(&P,CID);
+#else
+    mhashit(sha,-1,CID,&H);
+    ECP_mapit(&P,&H);
+#endif
+
+    ECP_toOctet(HID,&P,false);  // new
+
+    if (date)
+    {
+        //	if (HID!=NULL) ECP_toOctet(HID,&P,false);
+#ifdef USE_ANONYMOUS
+        mhashit(sha,date,CID,&H);
+#else
+        mhashit(sha,date,&H,&H);
+#endif
+        ECP_mapit(&R,&H);
+        ECP_add(&P,&R); //ECP_affine(&P);
+        ECP_toOctet(HTID,&P,false);
+    }
+    //else ECP_toOctet(HID,&P,false);
+
+}
+
+/* Implement M-Pin on server side */
+int ZZZ::MPIN_SERVER_2(int date,octet *HID,octet *HTID,octet *Y,octet *SST,octet *xID,octet *xCID,octet *mSEC,octet *E,octet *F,octet *Pa)
+{
+    BIG y;
+    FP12 g;
+    ECP2 Q,sQ;
+    ECP P,R;
+    int res=0;
+
+	ECP2_generator(&Q);
+
+    // key-escrow less scheme: use Pa instead of Q in pairing computation
+    // Q left for backward compatiblity
+    if (Pa!=NULL)
+    {
+        if (!ECP2_fromOctet(&Q, Pa)) res=MPIN_INVALID_POINT;
+    }
+
+    if (res==0)
+    {
+        if (!ECP2_fromOctet(&sQ,SST)) res=MPIN_INVALID_POINT;
+    }
+
+    if (res==0)
+    {
+        if (date)
+        {
+            //BIG_fromBytes(px,&(xCID->val[1]));
+            //BIG_fromBytes(py,&(xCID->val[PFS_ZZZ+1]));
+			if (!ECP_fromOctet(&R,xCID))  res=MPIN_INVALID_POINT;
+		
+        }
+        else
+        {
+            //BIG_fromBytes(px,&(xID->val[1]));
+            //BIG_fromBytes(py,&(xID->val[PFS_ZZZ+1]));
+			if (!ECP_fromOctet(&R,xID))  res=MPIN_INVALID_POINT;
+        }
+        //if (!ECP_set(&R,px,py)) res=MPIN_INVALID_POINT; // x(A+AT)
+    }
+    if (res==0)
+    {
+        BIG_fromBytes(y,Y->val);
+        if (date)
+        {
+            if (!ECP_fromOctet(&P,HTID))  res=MPIN_INVALID_POINT;
+        }
+        else
+        {
+            if (!ECP_fromOctet(&P,HID))  res=MPIN_INVALID_POINT;
+        }
+    }
+    if (res==0)
+    {
+        PAIR_G1mul(&P,y);  // y(A+AT)
+        ECP_add(&P,&R); // x(A+AT)+y(A+T)
+		//ECP_affine(&P);
+        if (!ECP_fromOctet(&R,mSEC))  res=MPIN_INVALID_POINT; // V
+
+//		printf("CLIENT SEC= "); ECP_output(&R); printf("\n");
+
+    }
+    if (res==0)
+    {
+
+        PAIR_double_ate(&g,&Q,&R,&sQ,&P);
+        PAIR_fexp(&g);
+
+        if (!FP12_isunity(&g))
+        {
+            if (HID!=NULL && xID!=NULL && E!=NULL && F !=NULL)
+            {
+                /* xID is set to NULL if there is no way to calculate PIN error */
+                FP12_toOctet(E,&g);
+
+                /* Note error is in the PIN, not in the time permit! Hence the need to exclude Time Permit from this check */
+
+                if (date)
+                {
+                    if (!ECP_fromOctet(&P,HID)) res=MPIN_INVALID_POINT;
+                    if (!ECP_fromOctet(&R,xID)) res=MPIN_INVALID_POINT; // U
+
+                    if (res==0)
+                    {
+                        PAIR_G1mul(&P,y);  // yA
+                        ECP_add(&P,&R); // yA+xA
+						//ECP_affine(&P);
+                    }
+                }
+                if (res==0)
+                {
+                    PAIR_ate(&g,&Q,&P);
+                    PAIR_fexp(&g);
+                    FP12_toOctet(F,&g);
+                }
+            }
+            res=MPIN_BAD_PIN;
+        }
+    }
+
+    return res;
+}
+
+#if MAXPIN==10000
+#define MR_TS 10  /* 2^10/10 approx = sqrt(MAXPIN) */
+#define TRAP 200  /* 2*sqrt(MAXPIN) */
+#endif
+
+#if MAXPIN==1000000
+#define MR_TS 14
+#define TRAP 2000
+#endif
+
+/* Pollards kangaroos used to return PIN error */
+int ZZZ::MPIN_KANGAROO(octet *E,octet *F)
+{
+    int i,j,m,s,dn,dm,steps;
+    int distance[MR_TS];
+    FP12 ge,gf,t,table[MR_TS];
+    int res=0;
+    // BIG w;
+
+    FP12_fromOctet(&ge,E);
+    FP12_fromOctet(&gf,F);
+
+    FP12_copy(&t,&gf);
+
+    for (s=1,m=0; m<MR_TS; m++)
+    {
+        distance[m]=s;
+        FP12_copy(&table[m],&t);
+        s*=2;
+        FP12_usqr(&t,&t);
+        FP12_reduce(&t);
+    }
+
+    FP12_one(&t);
+
+    for (dn=0,j=0; j<TRAP; j++)
+    {
+
+        //BIG_copy(w,t.a.a.a);
+        //FP_redc(w);
+        //i=BIG_lastbits(w,20)%MR_TS;
+
+        i=t.a.a.a.g[0]%MR_TS;
+
+        FP12_mul(&t,&table[i]);
+        FP12_reduce(&t);
+        dn+=distance[i];
+    }
+
+    FP12_conj(&gf,&t);
+    steps=0;
+    dm=0;
+    while (dm-dn<MAXPIN)
+    {
+        steps++;
+        if (steps>4*TRAP) break;
+
+        //BIG_copy(w,ge.a.a.a);
+        //FP_redc(w);
+        //i=BIG_lastbits(w,20)%MR_TS;
+
+        i=ge.a.a.a.g[0]%MR_TS;
+
+        FP12_mul(&ge,&table[i]);
+        FP12_reduce(&ge);
+        dm+=distance[i];
+        if (FP12_equals(&ge,&t))
+        {
+            res=dm-dn;
+            break;
+        }
+        if (FP12_equals(&ge,&gf))
+        {
+            res=dn-dm;
+            break;
+        }
+    }
+    if (steps>4*TRAP || dm-dn>=MAXPIN)
+    {
+        res=0;    /* Trap Failed  - probable invalid token */
+    }
+
+    return res;
+}
+
+/* Functions to support M-Pin Full */
+
+int ZZZ::MPIN_PRECOMPUTE(octet *TOKEN,octet *CID,octet *CP,octet *G1,octet *G2)
+{
+    ECP P,T;
+    ECP2 Q;
+    FP12 g;
+	BIG x;
+    int res=0;
+
+    if (!ECP_fromOctet(&T,TOKEN)) res=MPIN_INVALID_POINT;
+
+    if (res==0)
+    {
+        ECP_mapit(&P,CID);
+        if (CP!=NULL)
+        {
+            if (!ECP2_fromOctet(&Q,CP)) res=MPIN_INVALID_POINT;
+        }
+        else
+        {
+			ECP2_generator(&Q);
+        }
+    }
+    if (res==0)
+    {
+        PAIR_ate(&g,&Q,&T);
+        PAIR_fexp(&g);
+
+        FP12_toOctet(G1,&g);
+        if (G2!=NULL)
+        {
+            PAIR_ate(&g,&Q,&P);
+            PAIR_fexp(&g);
+            FP12_toOctet(G2,&g);
+        }
+    }
+    return res;
+}
+
+/* calculate common key on client side */
+/* wCID = w.(A+AT) */
+int ZZZ::MPIN_CLIENT_KEY(int sha,octet *G1,octet *G2,int pin,octet *R,octet *X,octet *H,octet *wCID,octet *CK)
+{
+    FP12 g1,g2;
+	FP4 c;//,cp,cpm1,cpm2;
+//    FP2 f;
+    ECP W;
+    int res=0;
+    BIG r,z,x,h;//q,m,a,b;
+
+    FP12_fromOctet(&g1,G1);
+    FP12_fromOctet(&g2,G2);
+    BIG_fromBytes(z,R->val);
+    BIG_fromBytes(x,X->val);
+    BIG_fromBytes(h,H->val);
+
+    if (!ECP_fromOctet(&W,wCID)) res=MPIN_INVALID_POINT;
+
+    if (res==0)
+    {
+        BIG_rcopy(r,CURVE_Order);
+        BIG_add(z,z,h);    // new
+        BIG_mod(z,r);
+
+        FP12_pinpow(&g2,pin,PBLEN);
+        FP12_mul(&g1,&g2);
+
+		PAIR_G1mul(&W,x);
+
+		FP12_compow(&c,&g1,z,r);
+
+ /*       BIG_rcopy(a,Fra);
+        BIG_rcopy(b,Frb);
+        FP2_from_BIGs(&f,a,b);
+
+        BIG_rcopy(q,Modulus);
+        BIG_copy(m,q);
+        BIG_mod(m,r);
+
+        BIG_copy(a,z);
+        BIG_mod(a,m);
+
+        BIG_copy(b,z);
+        BIG_sdiv(b,m);
+
+
+        FP12_trace(&c,&g1);
+
+        FP12_copy(&g2,&g1);
+        FP12_frob(&g2,&f);
+        FP12_trace(&cp,&g2);
+
+        FP12_conj(&g1,&g1);
+        FP12_mul(&g2,&g1);
+        FP12_trace(&cpm1,&g2);
+        FP12_mul(&g2,&g1);
+        FP12_trace(&cpm2,&g2);
+
+        FP4_xtr_pow2(&c,&cp,&c,&cpm1,&cpm2,a,b);
+ */
+		mpin_hash(sha,&c,&W,CK);
+
+    }
+    return res;
+}
+
+/* calculate common key on server side */
+/* Z=r.A - no time permits involved */
+
+int ZZZ::MPIN_SERVER_KEY(int sha,octet *Z,octet *SST,octet *W,octet *H,octet *HID,octet *xID,octet *xCID,octet *SK)
+{
+    int res=0;
+    FP12 g;
+    FP4 c;
+    ECP R,U,A;
+    ECP2 sQ;
+    BIG w,h;
+
+    if (!ECP2_fromOctet(&sQ,SST)) res=MPIN_INVALID_POINT;
+    if (!ECP_fromOctet(&R,Z)) res=MPIN_INVALID_POINT;
+
+
+    if (!ECP_fromOctet(&A,HID)) res=MPIN_INVALID_POINT;
+
+    // new
+    if (xCID!=NULL)
+    {
+        if (!ECP_fromOctet(&U,xCID)) res=MPIN_INVALID_POINT;
+    }
+    else
+    {
+        if (!ECP_fromOctet(&U,xID)) res=MPIN_INVALID_POINT;
+    }
+    BIG_fromBytes(w,W->val);
+    BIG_fromBytes(h,H->val);
+
+
+    PAIR_ate(&g,&sQ,&A);
+    PAIR_fexp(&g);
+
+    if (res==0)
+    {
+        PAIR_G1mul(&A,h);
+        ECP_add(&R,&A);  // new
+		//ECP_affine(&R);
+        PAIR_ate(&g,&sQ,&R);
+        PAIR_fexp(&g);
+        PAIR_G1mul(&U,w);
+        FP12_trace(&c,&g);
+        mpin_hash(sha,&c,&U,SK);
+    }
+    return res;
+}
+
+/* Generate Y = H(TimeValue, xCID/xID) */
+void ZZZ::MPIN_GET_Y(int sha,int TimeValue,octet *xCID,octet *Y)
+{
+    BIG q,y;
+    char h[MODBYTES_XXX];
+    octet H= {0,sizeof(h),h};
+
+    mhashit(sha,TimeValue,xCID,&H);
+    BIG_fromBytes(y,H.val);
+    BIG_rcopy(q,CURVE_Order);
+    BIG_mod(y,q);
+    BIG_toBytes(Y->val,y);
+    Y->len=PGS_ZZZ;
+}
+
+/* One pass MPIN Client */
+int ZZZ::MPIN_CLIENT(int sha,int date,octet *ID,csprng *RNG,octet *X,int pin,octet *TOKEN,octet *V,octet *U,octet *UT,octet *TP,octet *MESSAGE,int TimeValue,octet *Y)
+{
+    int rtn=0;
+    char m[2*PFS_ZZZ+1];
+    octet M= {0,sizeof(m),m};
+
+    octet *pID;
+    if (date == 0)
+        pID = U;
+    else
+        pID = UT;
+
+    rtn = MPIN_CLIENT_1(sha,date,ID,RNG,X,pin,TOKEN,V,U,UT,TP);
+    if (rtn != 0)
+        return rtn;
+
+    OCT_joctet(&M,pID);
+   if (MESSAGE!=NULL)
+   {
+       OCT_joctet(&M,MESSAGE);
+   }
+
+    MPIN_GET_Y(sha,TimeValue,&M,Y);
+
+    rtn = MPIN_CLIENT_2(X,Y,V);
+    if (rtn != 0)
+        return rtn;
+
+    return 0;
+}
+
+/* One pass MPIN Server */
+int ZZZ::MPIN_SERVER(int sha,int date,octet *HID,octet *HTID,octet *Y,octet *sQ,octet *U,octet *UT,octet *V,octet *E,octet *F,octet *ID,octet *MESSAGE,int TimeValue, octet *Pa)
+{
+    int rtn=0;
+    char m[2*PFS_ZZZ+1];
+    octet M= {0,sizeof(m),m};
+
+    octet *pU;
+    if (date == 0)
+        pU = U;
+    else
+        pU = UT;
+
+    MPIN_SERVER_1(sha,date,ID,HID,HTID);
+
+    OCT_joctet(&M,pU);
+   if (MESSAGE!=NULL)
+   {
+       OCT_joctet(&M,MESSAGE);
+   }
+
+    MPIN_GET_Y(sha,TimeValue,&M,Y);
+
+    rtn = MPIN_SERVER_2(date,HID,HTID,Y,sQ,U,UT,V,E,F,Pa);
+    if (rtn != 0)
+        return rtn;
+
+    return 0;
+}
+
+int ZZZ::MPIN_GET_DVS_KEYPAIR(csprng *R,octet *Z,octet *Pa)
+{
+    BIG z,r;
+    ECP2 Q;
+    int res=0;
+
+    BIG_rcopy(r,CURVE_Order);
+
+    if (R!=NULL)
+    {
+        BIG_randomnum(z,r,R);
+        Z->len=MODBYTES_XXX;
+        BIG_toBytes(Z->val,z);
+    }
+    else
+        BIG_fromBytes(z,Z->val);
+
+    BIG_invmodp(z,z,r);
+
+	ECP2_generator(&Q);
+
+    if (res==0)
+    {
+        PAIR_G2mul(&Q,z);
+        ECP2_toOctet(Pa,&Q);
+    }
+
+    return res;
+}
\ No newline at end of file
diff --git a/version3/cpp/mpin.h b/version3/cpp/mpin.h
new file mode 100644
index 0000000..6605cc6
--- /dev/null
+++ b/version3/cpp/mpin.h
@@ -0,0 +1,340 @@
+/*
+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.
+*/
+
+/**
+ * @file mpin.h
+ * @author Mike Scott and Kealan McCusker
+ * @date 2nd June 2015
+ * @brief M-Pin Header file
+ *
+ * Allows some user configuration
+ * defines structures
+ * declares functions
+ *
+ */
+
+#ifndef MPIN_ZZZ_H
+#define MPIN_ZZZ_H
+
+#include "pair_ZZZ.h"
+#include "pbc_support.h"
+
+using namespace amcl;
+
+
+namespace ZZZ {
+
+/* Field size is assumed to be greater than or equal to group size */
+
+#define PGS_ZZZ MODBYTES_XXX  /**< MPIN Group Size */
+#define PFS_ZZZ MODBYTES_XXX  /**< MPIN Field Size */
+
+#define MPIN_OK             0   /**< Function completed without error */
+#define MPIN_INVALID_POINT  -14	/**< Point is NOT on the curve */
+#define MPIN_BAD_PIN        -19 /**< Bad PIN number entered */
+
+#define MAXPIN 10000         /**< max PIN */
+#define PBLEN 14             /**< max length of PIN in bits */
+
+//#define PAS_ZZZ 16        /**< MPIN Symmetric Key Size 128 bits */
+//#define HASH_TYPE_MPIN_ZZZ SHA256   /**< Choose Hash function */
+
+/* MPIN support functions */
+
+/* MPIN primitives */
+
+
+void MPIN_GET_Y(int h,int t,octet *O,octet *Y);
+/**	@brief Extract a PIN number from a client secret
+ *
+  	@param h is the hash type
+	@param ID is the input client identity
+	@param factor is an input factor
+	@param facbits is the number of bits in the factor
+	@param CS is the client secret from which the factor is to be extracted
+	@return 0 or an error code
+ */
+int MPIN_EXTRACT_FACTOR(int h,octet *ID,int factor,int facbits,octet *CS);
+
+/**	@brief Extract a PIN number from a client secret
+ *
+  	@param h is the hash type
+	@param ID is the input client identity
+	@param factor is an input factor
+	@param facbits is the number of bits in the factor
+	@param CS is the client secret to which the factor is to be added
+	@return 0 or an error code
+ */
+int MPIN_RESTORE_FACTOR(int h,octet *ID,int factor,int facbits,octet *CS);
+
+
+/**	@brief Extract a PIN number from a client secret
+ *
+  	@param h is the hash type
+	@param ID is the input client identity
+	@param pin is an input PIN number
+	@param CS is the client secret from which the PIN is to be extracted
+	@return 0 or an error code
+ */
+int MPIN_EXTRACT_PIN(int h,octet *ID,int pin,octet *CS);
+
+/**	@brief Perform client side of the one-pass version of the M-Pin protocol
+ *
+	If Time Permits are disabled, set d = 0, and UT is not generated and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is OFF, U is not generated and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is ON, U and UT are both generated.
+ 	@param h is the hash type
+	@param d is input date, in days since the epoch. Set to 0 if Time permits disabled
+	@param ID is the input client identity
+	@param R is a pointer to a cryptographically secure random number generator
+	@param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input
+	@param pin is the input PIN number
+	@param T is the input M-Pin token (the client secret with PIN portion removed)
+	@param V is output = -(x+y)(CS+TP), where CS is the reconstructed client secret, and TP is the time permit
+	@param U is output = x.H(ID)
+	@param UT is output = x.(H(ID)+H(d|H(ID)))
+	@param TP is the input time permit
+	@param MESSAGE is the message to be signed
+	@param t is input epoch time in seconds - a timestamp
+	@param y is output H(t|U) or H(t|UT) if Time Permits enabled
+	@return 0 or an error code
+ */
+int MPIN_CLIENT(int h,int d,octet *ID,csprng *R,octet *x,int pin,octet *T,octet *V,octet *U,octet *UT,octet *TP, octet* MESSAGE, int t, octet *y);
+/**	@brief Perform first pass of the client side of the 3-pass version of the M-Pin protocol
+ *
+	If Time Permits are disabled, set d = 0, and UT is not generated and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is OFF, U is not generated and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is ON, U and UT are both generated.
+ 	@param h is the hash type
+	@param d is input date, in days since the epoch. Set to 0 if Time permits disabled
+	@param ID is the input client identity
+	@param R is a pointer to a cryptographically secure random number generator
+	@param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input
+	@param pin is the input PIN number
+	@param T is the input M-Pin token (the client secret with PIN portion removed)
+	@param S is output = CS+TP, where CS=is the reconstructed client secret, and TP is the time permit
+	@param U is output = x.H(ID)
+	@param UT is output = x.(H(ID)+H(d|H(ID)))
+	@param TP is the input time permit
+	@return 0 or an error code
+ */
+int MPIN_CLIENT_1(int h,int d,octet *ID,csprng *R,octet *x,int pin,octet *T,octet *S,octet *U,octet *UT,octet *TP);
+/**	@brief Generate a random group element
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param S is the output random octet
+	@return 0 or an error code
+ */
+int MPIN_RANDOM_GENERATE(csprng *R,octet *S);
+/**	@brief Perform second pass of the client side of the 3-pass version of the M-Pin protocol
+ *
+	@param x an input, a locally generated random number
+	@param y an input random challenge from the server
+	@param V on output = -(x+y).V
+	@return 0 or an error code
+ */
+int MPIN_CLIENT_2(octet *x,octet *y,octet *V);
+/**	@brief Perform server side of the one-pass version of the M-Pin protocol
+ *
+	If Time Permits are disabled, set d = 0, and UT and HTID are not generated and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is OFF, U and HID are not needed and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is ON, U, UT, HID and HTID are all required.
+ 	@param h is the hash type
+	@param d is input date, in days since the epoch. Set to 0 if Time permits disabled
+	@param HID is output H(ID), a hash of the client ID
+	@param HTID is output H(ID)+H(d|H(ID))
+	@param y is output H(t|U) or H(t|UT) if Time Permits enabled
+	@param SS is the input server secret
+	@param U is input from the client = x.H(ID)
+	@param UT is input from the client= x.(H(ID)+H(d|H(ID)))
+	@param V is an input from the client
+	@param E is an output to help the Kangaroos to find the PIN error, or NULL if not required
+	@param F is an output to help the Kangaroos to find the PIN error, or NULL if not required
+	@param ID is the input claimed client identity
+	@param MESSAGE is the message to be signed
+	@param t is input epoch time in seconds - a timestamp
+	@param Pa is input from the client z.Q or NULL if the key-escrow less scheme is not used
+	@return 0 or an error code
+ */
+int MPIN_SERVER(int h,int d,octet *HID,octet *HTID,octet *y,octet *SS,octet *U,octet *UT,octet *V,octet *E,octet *F,octet *ID,octet *MESSAGE, int t, octet *Pa);
+/**	@brief Perform first pass of the server side of the 3-pass version of the M-Pin protocol
+ *
+ 	@param h is the hash type
+	@param d is input date, in days since the epoch. Set to 0 if Time permits disabled
+	@param ID is the input claimed client identity
+	@param HID is output H(ID), a hash of the client ID
+	@param HTID is output H(ID)+H(d|H(ID))
+	@return 0 or an error code
+ */
+void MPIN_SERVER_1(int h,int d,octet *ID,octet *HID,octet *HTID);
+/**	@brief Perform third pass on the server side of the 3-pass version of the M-Pin protocol
+ *
+	If Time Permits are disabled, set d = 0, and UT and HTID are not needed and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is OFF, U and HID are not needed and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is ON, U, UT, HID and HTID are all required.
+	@param d is input date, in days since the epoch. Set to 0 if Time permits disabled
+	@param HID is input H(ID), a hash of the client ID
+	@param HTID is input H(ID)+H(d|H(ID))
+	@param y is the input server's randomly generated challenge
+	@param SS is the input server secret
+	@param U is input from the client = x.H(ID)
+	@param UT is input from the client= x.(H(ID)+H(d|H(ID)))
+	@param V is an input from the client
+	@param E is an output to help the Kangaroos to find the PIN error, or NULL if not required
+	@param F is an output to help the Kangaroos to find the PIN error, or NULL if not required
+	@param Pa is the input public key from the client, z.Q or NULL if the client uses regular mpin
+	@return 0 or an error code
+ */
+int MPIN_SERVER_2(int d,octet *HID,octet *HTID,octet *y,octet *SS,octet *U,octet *UT,octet *V,octet *E,octet *F,octet *Pa);
+/**	@brief Add two members from the group G1
+ *
+	@param Q1 an input member of G1
+	@param Q2 an input member of G1
+	@param Q an output member of G1 = Q1+Q2
+	@return 0 or an error code
+ */
+int MPIN_RECOMBINE_G1(octet *Q1,octet *Q2,octet *Q);
+/**	@brief Add two members from the group G2
+ *
+	@param P1 an input member of G2
+	@param P2 an input member of G2
+	@param P an output member of G2 = P1+P2
+	@return 0 or an error code
+ */
+int MPIN_RECOMBINE_G2(octet *P1,octet *P2,octet *P);
+/**	@brief Use Kangaroos to find PIN error
+ *
+	@param E a member of the group GT
+	@param F a member of the group GT =  E^e
+	@return 0 if Kangaroos failed, or the PIN error e
+ */
+int MPIN_KANGAROO(octet *E,octet *F);
+/**	@brief Encoding of a Time Permit to make it indistinguishable from a random string
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param TP is the input time permit, obfuscated on output
+	@return 0 or an error code
+ */
+int MPIN_ENCODING(csprng *R,octet *TP);
+/**	@brief Encoding of an obfuscated Time Permit
+ *
+	@param TP is the input obfuscated time permit, restored on output
+	@return 0 or an error code
+ */
+int MPIN_DECODING(octet *TP);
+
+/**	@brief Find a random multiple of a point in G1
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param type determines type of action to be taken
+	@param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input
+	@param G if type=0 a point in G1, else an octet to be mapped to G1
+	@param W the output =x.G or x.M(G), where M(.) is a mapping
+	@return 0 or an error code
+ */
+int MPIN_GET_G1_MULTIPLE(csprng *R,int type,octet *x,octet *G,octet *W);
+/**	@brief Find a random multiple of a point in G1
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param type determines type of action to betaken
+	@param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input
+	@param G a point in G2
+	@param W the output =x.G or (1/x).G
+	@return 0 or an error code
+ */
+int MPIN_GET_G2_MULTIPLE(csprng *R,int type,octet *x,octet *G,octet *W);
+
+/**	@brief Create a client secret in G1 from a master secret and the client ID
+ *
+	@param S is an input master secret
+	@param ID is the input client identity
+	@param CS is the full client secret = s.H(ID)
+	@return 0 or an error code
+ */
+int MPIN_GET_CLIENT_SECRET(octet *S,octet *ID,octet *CS);
+/**	@brief Create a Time Permit in G1 from a master secret and the client ID
+ *
+  	@param h is the hash type
+	@param d is input date, in days since the epoch.
+	@param S is an input master secret
+	@param ID is the input client identity
+	@param TP is a Time Permit for the given date = s.H(d|H(ID))
+	@return 0 or an error code
+ */
+int MPIN_GET_CLIENT_PERMIT(int h,int d,octet *S,octet *ID,octet *TP);
+/**	@brief Create a server secret in G2 from a master secret
+ *
+	@param S is an input master secret
+	@param SS is the server secret = s.Q where Q is a fixed generator of G2
+	@return 0 or an error code
+ */
+int MPIN_GET_SERVER_SECRET(octet *S,octet *SS);
+/* int MPIN_TEST_PAIRING(octet *,octet *); */
+
+/* For M-Pin Full */
+/**	@brief Precompute values for use by the client side of M-Pin Full
+ *
+	@param T is the input M-Pin token (the client secret with PIN portion removed)
+	@param ID is the input client identity
+	@param CP is Public Key (or NULL)
+	@param g1 precomputed output
+	@param g2 precomputed output
+	@return 0 or an error code
+ */
+int MPIN_PRECOMPUTE(octet *T,octet *ID,octet *CP,octet *g1,octet *g2);
+/**	@brief Calculate Key on Server side for M-Pin Full
+ *
+	Uses UT internally for the key calculation, unless not available in which case U is used
+ 	@param h is the hash type
+	@param Z is the input Client-side Diffie-Hellman component
+	@param SS is the input server secret
+	@param w is an input random number generated by the server
+	@param p is an input, hash of the protocol transcript
+	@param I is the hashed input client ID = H(ID)
+	@param U is input from the client = x.H(ID)
+	@param UT is input from the client= x.(H(ID)+H(d|H(ID)))
+	@param K is the output calculated shared key
+	@return 0 or an error code
+ */
+int MPIN_SERVER_KEY(int h,octet *Z,octet *SS,octet *w,octet *p,octet *I,octet *U,octet *UT,octet *K);
+/**	@brief Calculate Key on Client side for M-Pin Full
+ *
+  	@param h is the hash type
+	@param g1 precomputed input
+	@param g2 precomputed input
+	@param pin is the input PIN number
+	@param r is an input, a locally generated random number
+	@param x is an input, a locally generated random number
+	@param p is an input, hash of the protocol transcript
+	@param T is the input Server-side Diffie-Hellman component
+	@param K is the output calculated shared key
+	@return 0 or an error code
+ */
+int MPIN_CLIENT_KEY(int h,octet *g1,octet *g2,int pin,octet *r,octet *x,octet *p,octet *T,octet *K);
+
+/** @brief Generates a random public key for the client z.Q
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param Z an output internally randomly generated if R!=NULL, otherwise it must be provided as an input
+	@param Pa the output public key for the client
+ */
+int MPIN_GET_DVS_KEYPAIR(csprng *R,octet *Z,octet *Pa);
+}
+#endif
+
diff --git a/version3/cpp/mpin192.cpp b/version3/cpp/mpin192.cpp
new file mode 100644
index 0000000..090f0e3
--- /dev/null
+++ b/version3/cpp/mpin192.cpp
@@ -0,0 +1,985 @@
+/*
+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.
+*/
+
+/* MPIN Functions */
+
+/* Version 3.0 - supports Time Permits */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "mpin192_ZZZ.h"
+
+using namespace XXX;
+using namespace YYY;
+
+#define ROUNDUP(a,b) ((a)-1)/(b)+1
+
+namespace ZZZ {
+	static void mpin_hash(int,FP8 *, ECP *,octet *);
+	static void map(ECP *,BIG ,int );
+	static int unmap(BIG ,int *,ECP *);
+}
+
+/* Special mpin hashing */
+static void ZZZ::mpin_hash(int sha,FP8 *f, ECP *P,octet *w)
+{
+    int i;
+    BIG x,y;
+    char h[64];
+    hash256 sha256;
+    hash512 sha512;
+    char t[10*MODBYTES_XXX];  // to hold 10 BIGs
+    int hlen=sha;
+
+
+	FP_redc(x,&(f->a.a.a));
+    BIG_toBytes(&t[0],x);
+    FP_redc(x,&(f->a.a.b));
+    BIG_toBytes(&t[MODBYTES_XXX],x);
+    FP_redc(x,&(f->a.b.a));
+    BIG_toBytes(&t[2*MODBYTES_XXX],x);
+    FP_redc(x,&(f->a.b.b));
+    BIG_toBytes(&t[3*MODBYTES_XXX],x);
+
+	FP_redc(x,&(f->b.a.a));
+    BIG_toBytes(&t[4*MODBYTES_XXX],x);
+    FP_redc(x,&(f->b.a.b));
+    BIG_toBytes(&t[5*MODBYTES_XXX],x);
+    FP_redc(x,&(f->b.b.a));
+    BIG_toBytes(&t[6*MODBYTES_XXX],x);
+    FP_redc(x,&(f->b.b.b));
+    BIG_toBytes(&t[7*MODBYTES_XXX],x);
+
+    ECP_get(x,y,P);
+    BIG_toBytes(&t[8*MODBYTES_XXX],x);
+    BIG_toBytes(&t[9*MODBYTES_XXX],y);
+
+    OCT_empty(w);
+    switch (sha)
+    {
+    case SHA256:
+        HASH256_init(&sha256);
+        for (i=0; i<10*MODBYTES_XXX; i++) HASH256_process(&sha256,t[i]);
+        HASH256_hash(&sha256,h);
+        break;
+    case SHA384:
+        HASH384_init(&sha512);
+        for (i=0; i<10*MODBYTES_XXX; i++) HASH384_process(&sha512,t[i]);
+        HASH384_hash(&sha512,h);
+        break;
+    case SHA512:
+        HASH512_init(&sha512);
+        for (i=0; i<10*MODBYTES_XXX; i++) HASH512_process(&sha512,t[i]);
+        HASH512_hash(&sha512,h);
+        break;
+    }
+
+    OCT_jbytes(w,h,AESKEY_ZZZ);
+    for (i=0; i<hlen; i++) h[i]=0;
+}
+
+/* these next two functions help to implement elligator squared - http://eprint.iacr.org/2014/043 */
+/* maps a random u to a point on the curve */
+static void ZZZ::map(ECP *P,BIG u,int cb)
+{
+    BIG x,q;
+
+    BIG_rcopy(q,Modulus);
+    BIG_copy(x,u);
+    BIG_mod(x,q);
+
+    while (!ECP_setx(P,x,cb))
+	{
+        BIG_inc(x,1); BIG_norm(x);
+	}
+}
+
+/* returns u derived from P. Random value in range 1 to return value should then be added to u */
+static int ZZZ::unmap(BIG u,int *cb,ECP *P)
+{
+    int s,r=0;
+    BIG x;
+
+    s=ECP_get(x,x,P);
+    BIG_copy(u,x);
+    do
+    {
+        BIG_dec(u,1); BIG_norm(u);
+        r++;
+    }
+    while (!ECP_setx(P,u,s));
+    ECP_setx(P,x,s);
+
+    *cb=s;
+
+    return r;
+}
+
+/* these next two functions implement elligator squared - http://eprint.iacr.org/2014/043 */
+/* Elliptic curve point E in format (0x04,x,y} is converted to form {0x0-,u,v} */
+/* Note that u and v are indistinguisible from random strings */
+int ZZZ::MPIN_ENCODING(csprng *RNG,octet *E)
+{
+    int rn,m,su,sv,res=0;
+
+    BIG q,u,v;
+    ECP P,W;
+
+    if (!ECP_fromOctet(&P,E)) res=MPIN_INVALID_POINT;
+    if (res==0)
+    {
+        BIG_rcopy(q,Modulus);
+
+        BIG_randomnum(u,q,RNG);
+
+        su=RAND_byte(RNG);
+        if (su<0) su=-su;
+        su%=2;
+        map(&W,u,su);
+        ECP_sub(&P,&W); //ECP_affine(&P);
+
+        rn=unmap(v,&sv,&P);
+        m=RAND_byte(RNG);
+        if (m<0) m=-m;
+        m%=rn;
+        BIG_inc(v,m+1);
+        E->val[0]=su+2*sv;
+        BIG_toBytes(&(E->val[1]),u);
+        BIG_toBytes(&(E->val[PFS_ZZZ+1]),v);
+    }
+    return res;
+}
+
+int ZZZ::MPIN_DECODING(octet *D)
+{
+    int su,sv;
+    BIG u,v;
+    ECP P,W;
+    int res=0;
+
+    if ((D->val[0]&0x04)!=0) res=MPIN_INVALID_POINT;
+    if (res==0)
+    {
+
+        BIG_fromBytes(u,&(D->val[1]));
+        BIG_fromBytes(v,&(D->val[PFS_ZZZ+1]));
+
+        su=D->val[0]&1;
+        sv=(D->val[0]>>1)&1;
+        map(&W,u,su);
+        map(&P,v,sv);
+        ECP_add(&P,&W); //ECP_affine(&P);
+        ECP_toOctet(D,&P,false);
+    }
+
+    return res;
+}
+
+/* R=R1+R2 in group G1 */
+int ZZZ::MPIN_RECOMBINE_G1(octet *R1,octet *R2,octet *R)
+{
+    ECP P,T;
+    int res=0;
+    if (res==0)
+    {
+        if (!ECP_fromOctet(&P,R1)) res=MPIN_INVALID_POINT;
+        if (!ECP_fromOctet(&T,R2)) res=MPIN_INVALID_POINT;
+    }
+    if (res==0)
+    {
+        ECP_add(&P,&T); //ECP_affine(&P);
+        ECP_toOctet(R,&P,false);
+    }
+    return res;
+}
+
+/* W=W1+W2 in group G2 */
+int ZZZ::MPIN_RECOMBINE_G2(octet *W1,octet *W2,octet *W)
+{
+    ECP4 Q,T;
+    int res=0;
+    if (!ECP4_fromOctet(&Q,W1)) res=MPIN_INVALID_POINT;
+    if (!ECP4_fromOctet(&T,W2)) res=MPIN_INVALID_POINT;
+    if (res==0)
+    {
+        ECP4_add(&Q,&T); //ECP4_affine(&Q);
+        ECP4_toOctet(W,&Q);
+    }
+    return res;
+}
+
+/* create random secret S */
+int ZZZ::MPIN_RANDOM_GENERATE(csprng *RNG,octet* S)
+{
+    BIG r,s;
+
+    BIG_rcopy(r,CURVE_Order);
+    BIG_randomnum(s,r,RNG);
+#ifdef AES_S
+    BIG_mod2m(s,2*AES_S);
+#endif
+    BIG_toBytes(S->val,s);
+    S->len=MODBYTES_XXX;
+    return 0;
+}
+
+/* Extract PIN from TOKEN for identity CID */
+int ZZZ::MPIN_EXTRACT_PIN(int sha,octet *CID,int pin,octet *TOKEN)
+{
+	pin%=MAXPIN;
+	return MPIN_EXTRACT_FACTOR(sha,CID,pin,PBLEN,TOKEN);
+}
+
+/* Extract a factor < 32 bits for identity CID */
+int ZZZ::MPIN_EXTRACT_FACTOR(int sha,octet *CID,int factor,int facbits,octet *TOKEN)
+{
+    ECP P,R;
+    int res=0;
+    char h[MODBYTES_XXX];
+    octet H= {0,sizeof(h),h};
+
+    if (!ECP_fromOctet(&P,TOKEN))  res=MPIN_INVALID_POINT;
+    if (res==0)
+    {
+        mhashit(sha,-1,CID,&H);
+        ECP_mapit(&R,&H);
+
+        ECP_pinmul(&R,factor,facbits);
+        ECP_sub(&P,&R); //ECP_affine(&P);
+
+        ECP_toOctet(TOKEN,&P,false);
+    }
+    return res;
+}
+
+/* Extract a factor < 32 bits for identity CID */
+int ZZZ::MPIN_RESTORE_FACTOR(int sha,octet *CID,int factor,int facbits,octet *TOKEN)
+{
+    ECP P,R;
+    int res=0;
+    char h[MODBYTES_XXX];
+    octet H= {0,sizeof(h),h};
+
+    if (!ECP_fromOctet(&P,TOKEN))  res=MPIN_INVALID_POINT;
+    if (res==0)
+    {
+        mhashit(sha,-1,CID,&H);
+        ECP_mapit(&R,&H);
+
+        ECP_pinmul(&R,factor,facbits);
+        ECP_add(&P,&R); //ECP_affine(&P);
+
+        ECP_toOctet(TOKEN,&P,false);
+    }
+    return res;
+}
+
+/* Implement step 2 on client side of MPin protocol - SEC=-(x+y)*SEC */
+int ZZZ::MPIN_CLIENT_2(octet *X,octet *Y,octet *SEC)
+{
+    BIG px,py,r;
+    ECP P;
+    int res=0;
+    BIG_rcopy(r,CURVE_Order);
+    if (!ECP_fromOctet(&P,SEC)) res=MPIN_INVALID_POINT;
+    if (res==0)
+    {
+        BIG_fromBytes(px,X->val);
+        BIG_fromBytes(py,Y->val);
+        BIG_add(px,px,py);
+        BIG_mod(px,r);
+        //	BIG_sub(px,r,px);
+        PAIR_G1mul(&P,px);
+        ECP_neg(&P);
+        ECP_toOctet(SEC,&P,false);
+    }
+    return res;
+}
+
+/*
+ W=x*H(G);
+ if RNG == NULL then X is passed in
+ if RNG != NULL the X is passed out
+ if type=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve
+*/
+
+int ZZZ::MPIN_GET_G1_MULTIPLE(csprng *RNG,int type,octet *X,octet *G,octet *W)
+{
+    ECP P;
+    BIG r,x;
+    int res=0;
+    if (RNG!=NULL)
+    {
+        BIG_rcopy(r,CURVE_Order);
+        BIG_randomnum(x,r,RNG);
+#ifdef AES_S
+        BIG_mod2m(x,2*AES_S);
+#endif
+        X->len=MODBYTES_XXX;
+        BIG_toBytes(X->val,x);
+    }
+    else
+        BIG_fromBytes(x,X->val);
+
+    if (type==0)
+    {
+        if (!ECP_fromOctet(&P,G)) res=MPIN_INVALID_POINT;
+    }
+    else 
+	{
+		ECP_mapit(&P,G);
+	}
+
+    if (res==0)
+    {
+        PAIR_G1mul(&P,x);
+        ECP_toOctet(W,&P,false);
+    }
+    return res;
+}
+
+/*
+ if RNG == NULL then X is passed in
+ if RNG != NULL the X is passed out
+ W=x*G where G is point on the curve
+ if type==1 W=(x^-1)G
+*/
+
+int ZZZ::MPIN_GET_G2_MULTIPLE(csprng *RNG,int type,octet *X,octet *G,octet *W)
+{
+    ECP4 P;
+    BIG r,x;
+    int res=0;
+    BIG_rcopy(r,CURVE_Order);
+    if (RNG!=NULL)
+    {
+        BIG_randomnum(x,r,RNG);
+#ifdef AES_S
+        BIG_mod2m(x,2*AES_S);
+#endif
+        X->len=MODBYTES_XXX;
+        BIG_toBytes(X->val,x);
+    }
+    else
+    {
+        BIG_fromBytes(x,X->val);
+        if (type==1) BIG_invmodp(x,x,r);
+    }
+
+    if (!ECP4_fromOctet(&P,G)) res=MPIN_INVALID_POINT;
+
+    if (res==0)
+    {
+        PAIR_G2mul(&P,x);
+        ECP4_toOctet(W,&P);
+    }
+    return res;
+}
+
+
+
+/* Client secret CST=s*H(CID) where CID is client ID and s is master secret */
+/* CID is hashed externally */
+int ZZZ::MPIN_GET_CLIENT_SECRET(octet *S,octet *CID,octet *CST)
+{
+    return MPIN_GET_G1_MULTIPLE(NULL,1,S,CID,CST);
+}
+
+/* Implement step 1 on client side of MPin protocol */
+int ZZZ::MPIN_CLIENT_1(int sha,int date,octet *CLIENT_ID,csprng *RNG,octet *X,int pin,octet *TOKEN,octet *SEC,octet *xID,octet *xCID,octet *PERMIT)
+{
+    BIG r,x;
+    ECP P,T,W;
+    int res=0;
+    char h[MODBYTES_XXX];
+    octet H= {0,sizeof(h),h};
+
+    BIG_rcopy(r,CURVE_Order);
+    if (RNG!=NULL)
+    {
+        BIG_randomnum(x,r,RNG);
+#ifdef AES_S
+        BIG_mod2m(x,2*AES_S);
+#endif
+        X->len=MODBYTES_XXX;
+        BIG_toBytes(X->val,x);
+    }
+    else
+        BIG_fromBytes(x,X->val);
+
+    mhashit(sha,-1,CLIENT_ID,&H);
+
+    ECP_mapit(&P,&H);
+
+    if (!ECP_fromOctet(&T,TOKEN)) res=MPIN_INVALID_POINT;
+
+    if (res==0)
+    {
+        pin%=MAXPIN;
+
+        ECP_copy(&W,&P);				// W=H(ID)
+        ECP_pinmul(&W,pin,PBLEN);			// W=alpha.H(ID)
+        ECP_add(&T,&W);					// T=Token+alpha.H(ID) = s.H(ID)
+
+        if (date)
+        {
+            if (PERMIT!=NULL)
+            {
+                if (!ECP_fromOctet(&W,PERMIT)) res=MPIN_INVALID_POINT;
+                ECP_add(&T,&W);					// SEC=s.H(ID)+s.H(T|ID)
+            }
+            mhashit(sha,date,&H,&H);
+
+            ECP_mapit(&W,&H);
+            if (xID!=NULL)
+            {
+                PAIR_G1mul(&P,x);				// P=x.H(ID)
+                ECP_toOctet(xID,&P,false);  // xID
+                PAIR_G1mul(&W,x);               // W=x.H(T|ID)
+                ECP_add(&P,&W); //ECP_affine(&P);
+            }
+            else
+            {
+                ECP_add(&P,&W); //ECP_affine(&P);
+                PAIR_G1mul(&P,x);
+            }
+            if (xCID!=NULL) ECP_toOctet(xCID,&P,false);  // U
+        }
+        else
+        {
+            if (xID!=NULL)
+            {
+                PAIR_G1mul(&P,x);				// P=x.H(ID)
+                ECP_toOctet(xID,&P,false);  // xID
+            }
+        }
+    }
+
+    if (res==0)
+	{
+		//ECP_affine(&T);
+        ECP_toOctet(SEC,&T,false);  // V
+	}
+    return res;
+}
+
+/* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */
+int ZZZ::MPIN_GET_SERVER_SECRET(octet *S,octet *SST)
+{
+    BIG r,s;
+    ECP4 Q;
+    int res=0;
+
+    BIG_rcopy(r,CURVE_Order);
+
+	ECP4_generator(&Q);
+
+    if (res==0)
+    {
+        BIG_fromBytes(s,S->val);
+        PAIR_G2mul(&Q,s);
+        ECP4_toOctet(SST,&Q);
+    }
+
+    return res;
+}
+
+
+/* Time Permit CTT=s*H(date|H(CID)) where s is master secret */
+int ZZZ::MPIN_GET_CLIENT_PERMIT(int sha,int date,octet *S,octet *CID,octet *CTT)
+{
+    BIG s;
+    ECP P;
+    char h[MODBYTES_XXX];
+    octet H= {0,sizeof(h),h};
+
+    mhashit(sha,date,CID,&H);
+
+    ECP_mapit(&P,&H);
+
+//printf("P= "); ECP_output(&P); printf("\n");
+//exit(0);
+
+    BIG_fromBytes(s,S->val);
+
+
+
+//printf("s= "); BIG_output(s); printf("\n");
+    PAIR_G1mul(&P,s);
+//printf("OP= "); ECP_output(&P); printf("\n");
+//
+    ECP_toOctet(CTT,&P,false);
+    return 0;
+}
+
+// if date=0 only use HID, set HCID=NULL
+// if date and PE, use HID and HCID
+
+/* Outputs H(CID) and H(CID)+H(T|H(CID)) for time permits. If no time permits set HTID=NULL */
+void ZZZ::MPIN_SERVER_1(int sha,int date,octet *CID,octet *HID,octet *HTID)
+{
+    char h[MODBYTES_XXX];
+    octet H= {0,sizeof(h),h};
+    ECP P,R;
+	BIG x;
+
+#ifdef USE_ANONYMOUS
+    ECP_mapit(&P,CID);
+#else
+    mhashit(sha,-1,CID,&H);
+    ECP_mapit(&P,&H);
+#endif
+
+    ECP_toOctet(HID,&P,false);  // new
+
+    if (date)
+    {
+        //	if (HID!=NULL) ECP_toOctet(HID,&P,false);
+#ifdef USE_ANONYMOUS
+        mhashit(sha,date,CID,&H);
+#else
+        mhashit(sha,date,&H,&H);
+#endif
+        ECP_mapit(&R,&H);
+        ECP_add(&P,&R); //ECP_affine(&P);
+        ECP_toOctet(HTID,&P,false);
+    }
+    //else ECP_toOctet(HID,&P,false);
+
+}
+
+/* Implement M-Pin on server side */
+int ZZZ::MPIN_SERVER_2(int date,octet *HID,octet *HTID,octet *Y,octet *SST,octet *xID,octet *xCID,octet *mSEC,octet *E,octet *F,octet *Pa)
+{
+    BIG y;
+    FP24 g;
+    ECP4 Q,sQ;
+    ECP P,R;
+    int res=0;
+
+	ECP4_generator(&Q);
+
+    // key-escrow less scheme: use Pa instead of Q in pairing computation
+    // Q left for backward compatiblity
+    if (Pa!=NULL)
+    {
+        if (!ECP4_fromOctet(&Q, Pa)) res=MPIN_INVALID_POINT;
+    }
+
+
+    if (res==0)
+    {
+        if (!ECP4_fromOctet(&sQ,SST)) res=MPIN_INVALID_POINT;
+    }
+
+    if (res==0)
+    {
+        if (date)
+        {
+            //BIG_fromBytes(px,&(xCID->val[1]));
+            //BIG_fromBytes(py,&(xCID->val[PFS_ZZZ+1]));
+			if (!ECP_fromOctet(&R,xCID))  res=MPIN_INVALID_POINT;
+		
+        }
+        else
+        {
+            //BIG_fromBytes(px,&(xID->val[1]));
+            //BIG_fromBytes(py,&(xID->val[PFS_ZZZ+1]));
+			if (!ECP_fromOctet(&R,xID))  res=MPIN_INVALID_POINT;
+        }
+        //if (!ECP_set(&R,px,py)) res=MPIN_INVALID_POINT; // x(A+AT)
+    }
+    if (res==0)
+    {
+        BIG_fromBytes(y,Y->val);
+        if (date)
+        {
+            if (!ECP_fromOctet(&P,HTID))  res=MPIN_INVALID_POINT;
+        }
+        else
+        {
+            if (!ECP_fromOctet(&P,HID))  res=MPIN_INVALID_POINT;
+        }
+    }
+    if (res==0)
+    {
+        PAIR_G1mul(&P,y);  // y(A+AT)
+        ECP_add(&P,&R); // x(A+AT)+y(A+T)
+		//ECP_affine(&P);
+        if (!ECP_fromOctet(&R,mSEC))  res=MPIN_INVALID_POINT; // V
+    }
+    if (res==0)
+    {
+
+        PAIR_double_ate(&g,&Q,&R,&sQ,&P);
+        PAIR_fexp(&g);
+
+        if (!FP24_isunity(&g))
+        {
+            if (HID!=NULL && xID!=NULL && E!=NULL && F !=NULL)
+            {
+                /* xID is set to NULL if there is no way to calculate PIN error */
+                FP24_toOctet(E,&g);
+
+                /* Note error is in the PIN, not in the time permit! Hence the need to exclude Time Permit from this check */
+
+                if (date)
+                {
+                    if (!ECP_fromOctet(&P,HID)) res=MPIN_INVALID_POINT;
+                    if (!ECP_fromOctet(&R,xID)) res=MPIN_INVALID_POINT; // U
+
+                    if (res==0)
+                    {
+                        PAIR_G1mul(&P,y);  // yA
+                        ECP_add(&P,&R); // yA+xA
+						//ECP_affine(&P);
+                    }
+                }
+                if (res==0)
+                {
+                    PAIR_ate(&g,&Q,&P);
+                    PAIR_fexp(&g);
+                    FP24_toOctet(F,&g);
+                }
+            }
+            res=MPIN_BAD_PIN;
+        }
+    }
+
+    return res;
+}
+
+#if MAXPIN==10000
+#define MR_TS 10  /* 2^10/10 approx = sqrt(MAXPIN) */
+#define TRAP 200  /* 2*sqrt(MAXPIN) */
+#endif
+
+#if MAXPIN==1000000
+#define MR_TS 14
+#define TRAP 2000
+#endif
+
+/* Pollards kangaroos used to return PIN error */
+int ZZZ::MPIN_KANGAROO(octet *E,octet *F)
+{
+    int i,j,m,s,dn,dm,steps;
+    int distance[MR_TS];
+    FP24 ge,gf,t,table[MR_TS];
+    int res=0;
+    // BIG w;
+
+    FP24_fromOctet(&ge,E);
+    FP24_fromOctet(&gf,F);
+
+    FP24_copy(&t,&gf);
+
+    for (s=1,m=0; m<MR_TS; m++)
+    {
+        distance[m]=s;
+        FP24_copy(&table[m],&t);
+        s*=2;
+        FP24_usqr(&t,&t);
+        FP24_reduce(&t);
+    }
+
+    FP24_one(&t);
+
+    for (dn=0,j=0; j<TRAP; j++)
+    {
+
+        //BIG_copy(w,t.a.a.a);
+        //FP_redc(w);
+        //i=BIG_lastbits(w,20)%MR_TS;
+
+        i=t.a.a.a.a.g[0]%MR_TS;
+
+        FP24_mul(&t,&table[i]);
+        FP24_reduce(&t);
+        dn+=distance[i];
+    }
+
+    FP24_conj(&gf,&t);
+    steps=0;
+    dm=0;
+    while (dm-dn<MAXPIN)
+    {
+        steps++;
+        if (steps>4*TRAP) break;
+
+        //BIG_copy(w,ge.a.a.a);
+        //FP_redc(w);
+        //i=BIG_lastbits(w,20)%MR_TS;
+
+        i=ge.a.a.a.a.g[0]%MR_TS;
+
+        FP24_mul(&ge,&table[i]);
+        FP24_reduce(&ge);
+        dm+=distance[i];
+        if (FP24_equals(&ge,&t))
+        {
+            res=dm-dn;
+            break;
+        }
+        if (FP24_equals(&ge,&gf))
+        {
+            res=dn-dm;
+            break;
+        }
+    }
+    if (steps>4*TRAP || dm-dn>=MAXPIN)
+    {
+        res=0;    /* Trap Failed  - probable invalid token */
+    }
+
+    return res;
+}
+
+/* Functions to support M-Pin Full */
+
+int ZZZ::MPIN_PRECOMPUTE(octet *TOKEN,octet *CID,octet *CP,octet *G1,octet *G2)
+{
+    ECP P,T;
+    ECP4 Q;
+    FP24 g;
+	BIG x;
+    int res=0;
+
+    if (!ECP_fromOctet(&T,TOKEN)) res=MPIN_INVALID_POINT;
+
+    if (res==0)
+    {
+        ECP_mapit(&P,CID);
+        if (CP!=NULL)
+        {
+            if (!ECP4_fromOctet(&Q,CP)) res=MPIN_INVALID_POINT;
+        }
+        else
+        {
+			ECP4_generator(&Q);
+        }
+    }
+    if (res==0)
+    {
+        PAIR_ate(&g,&Q,&T);
+        PAIR_fexp(&g);
+
+        FP24_toOctet(G1,&g);
+        if (G2!=NULL)
+        {
+            PAIR_ate(&g,&Q,&P);
+            PAIR_fexp(&g);
+            FP24_toOctet(G2,&g);
+        }
+    }
+    return res;
+}
+
+/* calculate common key on client side */
+/* wCID = w.(A+AT) */
+int ZZZ::MPIN_CLIENT_KEY(int sha,octet *G1,octet *G2,int pin,octet *R,octet *X,octet *H,octet *wCID,octet *CK)
+{
+    FP24 g1,g2;
+	FP8 c;//,cp,cpm1,cpm2;
+
+    ECP W;
+    int res=0;
+    BIG r,z,x,h;//q,m,a,b;
+
+    FP24_fromOctet(&g1,G1);
+    FP24_fromOctet(&g2,G2);
+    BIG_fromBytes(z,R->val);
+    BIG_fromBytes(x,X->val);
+    BIG_fromBytes(h,H->val);
+
+    if (!ECP_fromOctet(&W,wCID)) res=MPIN_INVALID_POINT;
+
+    if (res==0)
+    {
+        BIG_rcopy(r,CURVE_Order);
+        BIG_add(z,z,h);    // new
+        BIG_mod(z,r);
+
+        FP24_pinpow(&g2,pin,PBLEN);
+        FP24_mul(&g1,&g2);
+
+		PAIR_G1mul(&W,x);
+
+		FP24_compow(&c,&g1,z,r);
+		mpin_hash(sha,&c,&W,CK);
+
+    }
+    return res;
+}
+
+/* calculate common key on server side */
+/* Z=r.A - no time permits involved */
+
+int ZZZ::MPIN_SERVER_KEY(int sha,octet *Z,octet *SST,octet *W,octet *H,octet *HID,octet *xID,octet *xCID,octet *SK)
+{
+    int res=0;
+    FP24 g;
+    FP8 c;
+    ECP R,U,A;
+    ECP4 sQ;
+    BIG w,h;
+
+    if (!ECP4_fromOctet(&sQ,SST)) res=MPIN_INVALID_POINT;
+    if (!ECP_fromOctet(&R,Z)) res=MPIN_INVALID_POINT;
+
+
+    if (!ECP_fromOctet(&A,HID)) res=MPIN_INVALID_POINT;
+
+    // new
+    if (xCID!=NULL)
+    {
+        if (!ECP_fromOctet(&U,xCID)) res=MPIN_INVALID_POINT;
+    }
+    else
+    {
+        if (!ECP_fromOctet(&U,xID)) res=MPIN_INVALID_POINT;
+    }
+    BIG_fromBytes(w,W->val);
+    BIG_fromBytes(h,H->val);
+
+
+    PAIR_ate(&g,&sQ,&A);
+    PAIR_fexp(&g);
+
+    if (res==0)
+    {
+        PAIR_G1mul(&A,h);
+        ECP_add(&R,&A);  // new
+		//ECP_affine(&R);
+        PAIR_ate(&g,&sQ,&R);
+        PAIR_fexp(&g);
+        PAIR_G1mul(&U,w);
+        FP24_trace(&c,&g);
+        mpin_hash(sha,&c,&U,SK);
+    }
+    return res;
+}
+
+/* Generate Y = H(TimeValue, xCID/xID) */
+void ZZZ::MPIN_GET_Y(int sha,int TimeValue,octet *xCID,octet *Y)
+{
+    BIG q,y;
+    char h[MODBYTES_XXX];
+    octet H= {0,sizeof(h),h};
+
+    mhashit(sha,TimeValue,xCID,&H);
+    BIG_fromBytes(y,H.val);
+    BIG_rcopy(q,CURVE_Order);
+    BIG_mod(y,q);
+    BIG_toBytes(Y->val,y);
+    Y->len=PGS_ZZZ;
+}
+
+/* One pass MPIN Client */
+int ZZZ::MPIN_CLIENT(int sha,int date,octet *ID,csprng *RNG,octet *X,int pin,octet *TOKEN,octet *V,octet *U,octet *UT,octet *TP,octet *MESSAGE,int TimeValue,octet *Y)
+{
+    int rtn=0;
+    char m[2*PFS_ZZZ+1];
+    octet M= {0,sizeof(m),m};
+
+    octet *pID;
+    if (date == 0)
+        pID = U;
+    else
+        pID = UT;
+
+    rtn = MPIN_CLIENT_1(sha,date,ID,RNG,X,pin,TOKEN,V,U,UT,TP);
+    if (rtn != 0)
+        return rtn;
+
+    OCT_joctet(&M,pID);
+   if (MESSAGE!=NULL)
+   {
+       OCT_joctet(&M,MESSAGE);
+   }
+
+    MPIN_GET_Y(sha,TimeValue,&M,Y);
+
+    rtn = MPIN_CLIENT_2(X,Y,V);
+    if (rtn != 0)
+        return rtn;
+
+    return 0;
+}
+
+/* One pass MPIN Server */
+int ZZZ::MPIN_SERVER(int sha,int date,octet *HID,octet *HTID,octet *Y,octet *sQ,octet *U,octet *UT,octet *V,octet *E,octet *F,octet *ID,octet *MESSAGE,int TimeValue, octet *Pa)
+{
+    int rtn=0;
+    char m[2*PFS_ZZZ+1];
+    octet M= {0,sizeof(m),m};
+
+    octet *pU;
+    if (date == 0)
+        pU = U;
+    else
+        pU = UT;
+
+    MPIN_SERVER_1(sha,date,ID,HID,HTID);
+
+    OCT_joctet(&M,pU);
+   if (MESSAGE!=NULL)
+   {
+       OCT_joctet(&M,MESSAGE);
+   }
+
+    MPIN_GET_Y(sha,TimeValue,&M,Y);
+
+    rtn = MPIN_SERVER_2(date,HID,HTID,Y,sQ,U,UT,V,E,F,Pa);
+    if (rtn != 0)
+        return rtn;
+
+    return 0;
+}
+
+int ZZZ::MPIN_GET_DVS_KEYPAIR(csprng *R,octet *Z,octet *Pa)
+{
+    BIG z,r;
+    ECP4 Q;
+    int res=0;
+
+    BIG_rcopy(r,CURVE_Order);
+
+    if (R!=NULL)
+    {
+        BIG_randomnum(z,r,R);
+        Z->len=MODBYTES_XXX;
+        BIG_toBytes(Z->val,z);
+    }
+    else
+        BIG_fromBytes(z,Z->val);
+
+    BIG_invmodp(z,z,r);
+
+	ECP4_generator(&Q);
+
+    if (res==0)
+    {
+        PAIR_G2mul(&Q,z);
+        ECP4_toOctet(Pa,&Q);
+    }
+
+    return res;
+}
\ No newline at end of file
diff --git a/version3/cpp/mpin192.h b/version3/cpp/mpin192.h
new file mode 100644
index 0000000..72b4db7
--- /dev/null
+++ b/version3/cpp/mpin192.h
@@ -0,0 +1,340 @@
+/*
+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.
+*/
+
+/**
+ * @file mpin.h
+ * @author Mike Scott and Kealan McCusker
+ * @date 2nd June 2015
+ * @brief M-Pin Header file
+ *
+ * Allows some user configuration
+ * defines structures
+ * declares functions
+ *
+ */
+
+#ifndef MPIN_ZZZ_H
+#define MPIN_ZZZ_H
+
+#include "pair192_ZZZ.h"
+#include "pbc_support.h"
+
+using namespace amcl;
+
+
+namespace ZZZ {
+
+/* Field size is assumed to be greater than or equal to group size */
+
+#define PGS_ZZZ MODBYTES_XXX  /**< MPIN Group Size */
+#define PFS_ZZZ MODBYTES_XXX  /**< MPIN Field Size */
+
+#define MPIN_OK             0   /**< Function completed without error */
+#define MPIN_INVALID_POINT  -14	/**< Point is NOT on the curve */
+#define MPIN_BAD_PIN        -19 /**< Bad PIN number entered */
+
+#define MAXPIN 10000         /**< max PIN */
+#define PBLEN 14             /**< max length of PIN in bits */
+
+//#define PAS_ZZZ 24        /**< MPIN Symmetric Key Size 192 bits  */
+//#define HASH_TYPE_MPIN_ZZZ SHA384   /**< Choose Hash function */
+
+/* MPIN support functions */
+
+/* MPIN primitives */
+
+
+void MPIN_GET_Y(int h,int t,octet *O,octet *Y);
+/**	@brief Extract a PIN number from a client secret
+ *
+  	@param h is the hash type
+	@param ID is the input client identity
+	@param factor is an input factor
+	@param facbits is the number of bits in the factor
+	@param CS is the client secret from which the factor is to be extracted
+	@return 0 or an error code
+ */
+int MPIN_EXTRACT_FACTOR(int h,octet *ID,int factor,int facbits,octet *CS);
+
+/**	@brief Extract a PIN number from a client secret
+ *
+  	@param h is the hash type
+	@param ID is the input client identity
+	@param factor is an input factor
+	@param facbits is the number of bits in the factor
+	@param CS is the client secret to which the factor is to be added
+	@return 0 or an error code
+ */
+int MPIN_RESTORE_FACTOR(int h,octet *ID,int factor,int facbits,octet *CS);
+
+
+/**	@brief Extract a PIN number from a client secret
+ *
+  	@param h is the hash type
+	@param ID is the input client identity
+	@param pin is an input PIN number
+	@param CS is the client secret from which the PIN is to be extracted
+	@return 0 or an error code
+ */
+int MPIN_EXTRACT_PIN(int h,octet *ID,int pin,octet *CS);
+
+/**	@brief Perform client side of the one-pass version of the M-Pin protocol
+ *
+	If Time Permits are disabled, set d = 0, and UT is not generated and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is OFF, U is not generated and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is ON, U and UT are both generated.
+ 	@param h is the hash type
+	@param d is input date, in days since the epoch. Set to 0 if Time permits disabled
+	@param ID is the input client identity
+	@param R is a pointer to a cryptographically secure random number generator
+	@param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input
+	@param pin is the input PIN number
+	@param T is the input M-Pin token (the client secret with PIN portion removed)
+	@param V is output = -(x+y)(CS+TP), where CS is the reconstructed client secret, and TP is the time permit
+	@param U is output = x.H(ID)
+	@param UT is output = x.(H(ID)+H(d|H(ID)))
+	@param TP is the input time permit
+	@param MESSAGE is the message to be signed
+	@param t is input epoch time in seconds - a timestamp
+	@param y is output H(t|U) or H(t|UT) if Time Permits enabled
+	@return 0 or an error code
+ */
+int MPIN_CLIENT(int h,int d,octet *ID,csprng *R,octet *x,int pin,octet *T,octet *V,octet *U,octet *UT,octet *TP, octet* MESSAGE, int t, octet *y);
+/**	@brief Perform first pass of the client side of the 3-pass version of the M-Pin protocol
+ *
+	If Time Permits are disabled, set d = 0, and UT is not generated and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is OFF, U is not generated and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is ON, U and UT are both generated.
+ 	@param h is the hash type
+	@param d is input date, in days since the epoch. Set to 0 if Time permits disabled
+	@param ID is the input client identity
+	@param R is a pointer to a cryptographically secure random number generator
+	@param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input
+	@param pin is the input PIN number
+	@param T is the input M-Pin token (the client secret with PIN portion removed)
+	@param S is output = CS+TP, where CS=is the reconstructed client secret, and TP is the time permit
+	@param U is output = x.H(ID)
+	@param UT is output = x.(H(ID)+H(d|H(ID)))
+	@param TP is the input time permit
+	@return 0 or an error code
+ */
+int MPIN_CLIENT_1(int h,int d,octet *ID,csprng *R,octet *x,int pin,octet *T,octet *S,octet *U,octet *UT,octet *TP);
+/**	@brief Generate a random group element
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param S is the output random octet
+	@return 0 or an error code
+ */
+int MPIN_RANDOM_GENERATE(csprng *R,octet *S);
+/**	@brief Perform second pass of the client side of the 3-pass version of the M-Pin protocol
+ *
+	@param x an input, a locally generated random number
+	@param y an input random challenge from the server
+	@param V on output = -(x+y).V
+	@return 0 or an error code
+ */
+int MPIN_CLIENT_2(octet *x,octet *y,octet *V);
+/**	@brief Perform server side of the one-pass version of the M-Pin protocol
+ *
+	If Time Permits are disabled, set d = 0, and UT and HTID are not generated and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is OFF, U and HID are not needed and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is ON, U, UT, HID and HTID are all required.
+ 	@param h is the hash type
+	@param d is input date, in days since the epoch. Set to 0 if Time permits disabled
+	@param HID is output H(ID), a hash of the client ID
+	@param HTID is output H(ID)+H(d|H(ID))
+	@param y is output H(t|U) or H(t|UT) if Time Permits enabled
+	@param SS is the input server secret
+	@param U is input from the client = x.H(ID)
+	@param UT is input from the client= x.(H(ID)+H(d|H(ID)))
+	@param V is an input from the client
+	@param E is an output to help the Kangaroos to find the PIN error, or NULL if not required
+	@param F is an output to help the Kangaroos to find the PIN error, or NULL if not required
+	@param ID is the input claimed client identity
+	@param MESSAGE is the message to be signed
+	@param t is input epoch time in seconds - a timestamp
+	@param Pa is input from the client z.Q or NULL if the key-escrow less scheme is not used
+	@return 0 or an error code
+ */
+int MPIN_SERVER(int h,int d,octet *HID,octet *HTID,octet *y,octet *SS,octet *U,octet *UT,octet *V,octet *E,octet *F,octet *ID,octet *MESSAGE, int t, octet *Pa);
+/**	@brief Perform first pass of the server side of the 3-pass version of the M-Pin protocol
+ *
+ 	@param h is the hash type
+	@param d is input date, in days since the epoch. Set to 0 if Time permits disabled
+	@param ID is the input claimed client identity
+	@param HID is output H(ID), a hash of the client ID
+	@param HTID is output H(ID)+H(d|H(ID))
+	@return 0 or an error code
+ */
+void MPIN_SERVER_1(int h,int d,octet *ID,octet *HID,octet *HTID);
+/**	@brief Perform third pass on the server side of the 3-pass version of the M-Pin protocol
+ *
+	If Time Permits are disabled, set d = 0, and UT and HTID are not needed and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is OFF, U and HID are not needed and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is ON, U, UT, HID and HTID are all required.
+	@param d is input date, in days since the epoch. Set to 0 if Time permits disabled
+	@param HID is input H(ID), a hash of the client ID
+	@param HTID is input H(ID)+H(d|H(ID))
+	@param y is the input server's randomly generated challenge
+	@param SS is the input server secret
+	@param U is input from the client = x.H(ID)
+	@param UT is input from the client= x.(H(ID)+H(d|H(ID)))
+	@param V is an input from the client
+	@param E is an output to help the Kangaroos to find the PIN error, or NULL if not required
+	@param F is an output to help the Kangaroos to find the PIN error, or NULL if not required
+	@param Pa is the input public key from the client, z.Q or NULL if the client uses regular mpin
+	@return 0 or an error code
+ */
+int MPIN_SERVER_2(int d,octet *HID,octet *HTID,octet *y,octet *SS,octet *U,octet *UT,octet *V,octet *E,octet *F,octet *Pa);
+/**	@brief Add two members from the group G1
+ *
+	@param Q1 an input member of G1
+	@param Q2 an input member of G1
+	@param Q an output member of G1 = Q1+Q2
+	@return 0 or an error code
+ */
+int MPIN_RECOMBINE_G1(octet *Q1,octet *Q2,octet *Q);
+/**	@brief Add two members from the group G2
+ *
+	@param P1 an input member of G2
+	@param P2 an input member of G2
+	@param P an output member of G2 = P1+P2
+	@return 0 or an error code
+ */
+int MPIN_RECOMBINE_G2(octet *P1,octet *P2,octet *P);
+/**	@brief Use Kangaroos to find PIN error
+ *
+	@param E a member of the group GT
+	@param F a member of the group GT =  E^e
+	@return 0 if Kangaroos failed, or the PIN error e
+ */
+int MPIN_KANGAROO(octet *E,octet *F);
+/**	@brief Encoding of a Time Permit to make it indistinguishable from a random string
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param TP is the input time permit, obfuscated on output
+	@return 0 or an error code
+ */
+int MPIN_ENCODING(csprng *R,octet *TP);
+/**	@brief Encoding of an obfuscated Time Permit
+ *
+	@param TP is the input obfuscated time permit, restored on output
+	@return 0 or an error code
+ */
+int MPIN_DECODING(octet *TP);
+
+/**	@brief Find a random multiple of a point in G1
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param type determines type of action to be taken
+	@param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input
+	@param G if type=0 a point in G1, else an octet to be mapped to G1
+	@param W the output =x.G or x.M(G), where M(.) is a mapping
+	@return 0 or an error code
+ */
+int MPIN_GET_G1_MULTIPLE(csprng *R,int type,octet *x,octet *G,octet *W);
+/**	@brief Find a random multiple of a point in G1
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param type determines type of action to betaken
+	@param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input
+	@param G a point in G2
+	@param W the output =x.G or (1/x).G
+	@return 0 or an error code
+ */
+int MPIN_GET_G2_MULTIPLE(csprng *R,int type,octet *x,octet *G,octet *W);
+
+/**	@brief Create a client secret in G1 from a master secret and the client ID
+ *
+	@param S is an input master secret
+	@param ID is the input client identity
+	@param CS is the full client secret = s.H(ID)
+	@return 0 or an error code
+ */
+int MPIN_GET_CLIENT_SECRET(octet *S,octet *ID,octet *CS);
+/**	@brief Create a Time Permit in G1 from a master secret and the client ID
+ *
+  	@param h is the hash type
+	@param d is input date, in days since the epoch.
+	@param S is an input master secret
+	@param ID is the input client identity
+	@param TP is a Time Permit for the given date = s.H(d|H(ID))
+	@return 0 or an error code
+ */
+int MPIN_GET_CLIENT_PERMIT(int h,int d,octet *S,octet *ID,octet *TP);
+/**	@brief Create a server secret in G2 from a master secret
+ *
+	@param S is an input master secret
+	@param SS is the server secret = s.Q where Q is a fixed generator of G2
+	@return 0 or an error code
+ */
+int MPIN_GET_SERVER_SECRET(octet *S,octet *SS);
+/* int MPIN_TEST_PAIRING(octet *,octet *); */
+
+/* For M-Pin Full */
+/**	@brief Precompute values for use by the client side of M-Pin Full
+ *
+	@param T is the input M-Pin token (the client secret with PIN portion removed)
+	@param ID is the input client identity
+	@param CP is Public Key (or NULL)
+	@param g1 precomputed output
+	@param g2 precomputed output
+	@return 0 or an error code
+ */
+int MPIN_PRECOMPUTE(octet *T,octet *ID,octet *CP,octet *g1,octet *g2);
+/**	@brief Calculate Key on Server side for M-Pin Full
+ *
+	Uses UT internally for the key calculation, unless not available in which case U is used
+ 	@param h is the hash type
+	@param Z is the input Client-side Diffie-Hellman component
+	@param SS is the input server secret
+	@param w is an input random number generated by the server
+	@param p is an input, hash of the protocol transcript
+	@param I is the hashed input client ID = H(ID)
+	@param U is input from the client = x.H(ID)
+	@param UT is input from the client= x.(H(ID)+H(d|H(ID)))
+	@param K is the output calculated shared key
+	@return 0 or an error code
+ */
+int MPIN_SERVER_KEY(int h,octet *Z,octet *SS,octet *w,octet *p,octet *I,octet *U,octet *UT,octet *K);
+/**	@brief Calculate Key on Client side for M-Pin Full
+ *
+  	@param h is the hash type
+	@param g1 precomputed input
+	@param g2 precomputed input
+	@param pin is the input PIN number
+	@param r is an input, a locally generated random number
+	@param x is an input, a locally generated random number
+	@param p is an input, hash of the protocol transcript
+	@param T is the input Server-side Diffie-Hellman component
+	@param K is the output calculated shared key
+	@return 0 or an error code
+ */
+int MPIN_CLIENT_KEY(int h,octet *g1,octet *g2,int pin,octet *r,octet *x,octet *p,octet *T,octet *K);
+
+/** @brief Generates a random public key for the client z.Q
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param Z an output internally randomly generated if R!=NULL, otherwise it must be provided as an input
+	@param Pa the output public key for the client
+ */
+int MPIN_GET_DVS_KEYPAIR(csprng *R,octet *Z,octet *Pa);
+}
+#endif
+
diff --git a/version3/cpp/mpin256.cpp b/version3/cpp/mpin256.cpp
new file mode 100644
index 0000000..787a1c7
--- /dev/null
+++ b/version3/cpp/mpin256.cpp
@@ -0,0 +1,1006 @@
+/*
+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.
+*/
+
+/* MPIN Functions */
+
+/* Version 3.0 - supports Time Permits */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "mpin256_ZZZ.h"
+
+using namespace XXX;
+using namespace YYY;
+
+#define ROUNDUP(a,b) ((a)-1)/(b)+1
+
+namespace ZZZ {
+	static void mpin_hash(int,FP16 *, ECP *,octet *);
+	static void map(ECP *,BIG ,int );
+	static int unmap(BIG ,int *,ECP *);
+}
+
+/* Special mpin hashing */
+static void ZZZ::mpin_hash(int sha,FP16 *f, ECP *P,octet *w)
+{
+    int i;
+    BIG x,y;
+    char h[64];
+    hash256 sha256;
+    hash512 sha512;
+    char t[18*MODBYTES_XXX];  // to hold 10 BIGs
+    int hlen=sha;
+
+	FP_redc(x,&(f->a.a.a.a));
+    BIG_toBytes(&t[0],x);
+	FP_redc(x,&(f->a.a.a.b));
+    BIG_toBytes(&t[MODBYTES_XXX],x);
+
+    FP_redc(x,&(f->a.a.b.a));
+    BIG_toBytes(&t[2*MODBYTES_XXX],x);
+    FP_redc(x,&(f->a.a.b.b));
+    BIG_toBytes(&t[3*MODBYTES_XXX],x);
+
+    FP_redc(x,&(f->a.b.a.a));
+    BIG_toBytes(&t[4*MODBYTES_XXX],x);
+    FP_redc(x,&(f->a.b.a.b));
+    BIG_toBytes(&t[5*MODBYTES_XXX],x);
+
+    FP_redc(x,&(f->a.b.b.a));
+    BIG_toBytes(&t[6*MODBYTES_XXX],x);
+    FP_redc(x,&(f->a.b.b.b));
+    BIG_toBytes(&t[7*MODBYTES_XXX],x);
+
+	FP_redc(x,&(f->b.a.a.a));
+    BIG_toBytes(&t[8*MODBYTES_XXX],x);
+	FP_redc(x,&(f->b.a.a.b));
+    BIG_toBytes(&t[9*MODBYTES_XXX],x);
+
+    FP_redc(x,&(f->b.a.b.a));
+    BIG_toBytes(&t[10*MODBYTES_XXX],x);
+	FP_redc(x,&(f->b.a.b.b));
+    BIG_toBytes(&t[11*MODBYTES_XXX],x);
+
+    FP_redc(x,&(f->b.b.a.a));
+    BIG_toBytes(&t[12*MODBYTES_XXX],x);
+    FP_redc(x,&(f->b.b.a.b));
+    BIG_toBytes(&t[13*MODBYTES_XXX],x);
+
+    FP_redc(x,&(f->b.b.b.a));
+    BIG_toBytes(&t[14*MODBYTES_XXX],x);
+    FP_redc(x,&(f->b.b.b.b));
+    BIG_toBytes(&t[15*MODBYTES_XXX],x);
+
+    ECP_get(x,y,P);
+    BIG_toBytes(&t[16*MODBYTES_XXX],x);
+    BIG_toBytes(&t[17*MODBYTES_XXX],y);
+
+    OCT_empty(w);
+    switch (sha)
+    {
+    case SHA256:
+        HASH256_init(&sha256);
+        for (i=0; i<18*MODBYTES_XXX; i++) HASH256_process(&sha256,t[i]);
+        HASH256_hash(&sha256,h);
+        break;
+    case SHA384:
+        HASH384_init(&sha512);
+        for (i=0; i<18*MODBYTES_XXX; i++) HASH384_process(&sha512,t[i]);
+        HASH384_hash(&sha512,h);
+        break;
+    case SHA512:
+        HASH512_init(&sha512);
+        for (i=0; i<18*MODBYTES_XXX; i++) HASH512_process(&sha512,t[i]);
+        HASH512_hash(&sha512,h);
+        break;
+    }
+
+    OCT_jbytes(w,h,AESKEY_ZZZ);
+    for (i=0; i<hlen; i++) h[i]=0;
+}
+
+/* these next two functions help to implement elligator squared - http://eprint.iacr.org/2014/043 */
+/* maps a random u to a point on the curve */
+static void ZZZ::map(ECP *P,BIG u,int cb)
+{
+    BIG x,q;
+
+    BIG_rcopy(q,Modulus);
+    BIG_copy(x,u);
+    BIG_mod(x,q);
+
+    while (!ECP_setx(P,x,cb))
+	{
+        BIG_inc(x,1); BIG_norm(x);
+	}
+}
+
+/* returns u derived from P. Random value in range 1 to return value should then be added to u */
+static int ZZZ::unmap(BIG u,int *cb,ECP *P)
+{
+    int s,r=0;
+    BIG x;
+
+    s=ECP_get(x,x,P);
+    BIG_copy(u,x);
+    do
+    {
+        BIG_dec(u,1); BIG_norm(u);
+        r++;
+    }
+    while (!ECP_setx(P,u,s));
+    ECP_setx(P,x,s);
+
+    *cb=s;
+
+    return r;
+}
+
+/* these next two functions implement elligator squared - http://eprint.iacr.org/2014/043 */
+/* Elliptic curve point E in format (0x04,x,y} is converted to form {0x0-,u,v} */
+/* Note that u and v are indistinguisible from random strings */
+int ZZZ::MPIN_ENCODING(csprng *RNG,octet *E)
+{
+    int rn,m,su,sv,res=0;
+
+    BIG q,u,v;
+    ECP P,W;
+
+    if (!ECP_fromOctet(&P,E)) res=MPIN_INVALID_POINT;
+    if (res==0)
+    {
+        BIG_rcopy(q,Modulus);
+
+        BIG_randomnum(u,q,RNG);
+
+        su=RAND_byte(RNG);
+        if (su<0) su=-su;
+        su%=2;
+        map(&W,u,su);
+        ECP_sub(&P,&W); //ECP_affine(&P);
+
+        rn=unmap(v,&sv,&P);
+        m=RAND_byte(RNG);
+        if (m<0) m=-m;
+        m%=rn;
+        BIG_inc(v,m+1);
+        E->val[0]=su+2*sv;
+        BIG_toBytes(&(E->val[1]),u);
+        BIG_toBytes(&(E->val[PFS_ZZZ+1]),v);
+    }
+    return res;
+}
+
+int ZZZ::MPIN_DECODING(octet *D)
+{
+    int su,sv;
+    BIG u,v;
+    ECP P,W;
+    int res=0;
+
+    if ((D->val[0]&0x04)!=0) res=MPIN_INVALID_POINT;
+    if (res==0)
+    {
+
+        BIG_fromBytes(u,&(D->val[1]));
+        BIG_fromBytes(v,&(D->val[PFS_ZZZ+1]));
+
+        su=D->val[0]&1;
+        sv=(D->val[0]>>1)&1;
+        map(&W,u,su);
+        map(&P,v,sv);
+        ECP_add(&P,&W); //ECP_affine(&P);
+        ECP_toOctet(D,&P,false);
+    }
+
+    return res;
+}
+
+/* R=R1+R2 in group G1 */
+int ZZZ::MPIN_RECOMBINE_G1(octet *R1,octet *R2,octet *R)
+{
+    ECP P,T;
+    int res=0;
+    if (res==0)
+    {
+        if (!ECP_fromOctet(&P,R1)) res=MPIN_INVALID_POINT;
+        if (!ECP_fromOctet(&T,R2)) res=MPIN_INVALID_POINT;
+    }
+    if (res==0)
+    {
+        ECP_add(&P,&T); //ECP_affine(&P);
+        ECP_toOctet(R,&P,false);
+    }
+    return res;
+}
+
+/* W=W1+W2 in group G2 */
+int ZZZ::MPIN_RECOMBINE_G2(octet *W1,octet *W2,octet *W)
+{
+    ECP8 Q,T;
+    int res=0;
+    if (!ECP8_fromOctet(&Q,W1)) res=MPIN_INVALID_POINT;
+    if (!ECP8_fromOctet(&T,W2)) res=MPIN_INVALID_POINT;
+    if (res==0)
+    {
+        ECP8_add(&Q,&T); //ECP8_affine(&Q);
+        ECP8_toOctet(W,&Q);
+    }
+    return res;
+}
+
+/* create random secret S */
+int ZZZ::MPIN_RANDOM_GENERATE(csprng *RNG,octet* S)
+{
+    BIG r,s;
+
+    BIG_rcopy(r,CURVE_Order);
+    BIG_randomnum(s,r,RNG);
+#ifdef AES_S
+    BIG_mod2m(s,2*AES_S);
+#endif
+    BIG_toBytes(S->val,s);
+    S->len=MODBYTES_XXX;
+    return 0;
+}
+
+/* Extract PIN from TOKEN for identity CID */
+int ZZZ::MPIN_EXTRACT_PIN(int sha,octet *CID,int pin,octet *TOKEN)
+{
+	pin%=MAXPIN;
+	return MPIN_EXTRACT_FACTOR(sha,CID,pin,PBLEN,TOKEN);
+}
+
+/* Extract a factor < 32 bits for identity CID */
+int ZZZ::MPIN_EXTRACT_FACTOR(int sha,octet *CID,int factor,int facbits,octet *TOKEN)
+{
+    ECP P,R;
+    int res=0;
+    char h[MODBYTES_XXX];
+    octet H= {0,sizeof(h),h};
+
+    if (!ECP_fromOctet(&P,TOKEN))  res=MPIN_INVALID_POINT;
+    if (res==0)
+    {
+        mhashit(sha,-1,CID,&H);
+        ECP_mapit(&R,&H);
+
+        ECP_pinmul(&R,factor,facbits);
+        ECP_sub(&P,&R); //ECP_affine(&P);
+
+        ECP_toOctet(TOKEN,&P,false);
+    }
+    return res;
+}
+
+/* Extract a factor < 32 bits for identity CID */
+int ZZZ::MPIN_RESTORE_FACTOR(int sha,octet *CID,int factor,int facbits,octet *TOKEN)
+{
+    ECP P,R;
+    int res=0;
+    char h[MODBYTES_XXX];
+    octet H= {0,sizeof(h),h};
+
+    if (!ECP_fromOctet(&P,TOKEN))  res=MPIN_INVALID_POINT;
+    if (res==0)
+    {
+        mhashit(sha,-1,CID,&H);
+        ECP_mapit(&R,&H);
+
+        ECP_pinmul(&R,factor,facbits);
+        ECP_add(&P,&R); //ECP_affine(&P);
+
+        ECP_toOctet(TOKEN,&P,false);
+    }
+    return res;
+}
+
+/* Implement step 2 on client side of MPin protocol - SEC=-(x+y)*SEC */
+int ZZZ::MPIN_CLIENT_2(octet *X,octet *Y,octet *SEC)
+{
+    BIG px,py,r;
+    ECP P;
+    int res=0;
+    BIG_rcopy(r,CURVE_Order);
+    if (!ECP_fromOctet(&P,SEC)) res=MPIN_INVALID_POINT;
+    if (res==0)
+    {
+        BIG_fromBytes(px,X->val);
+        BIG_fromBytes(py,Y->val);
+        BIG_add(px,px,py);
+        BIG_mod(px,r);
+        //	BIG_sub(px,r,px);
+        PAIR_G1mul(&P,px);
+        ECP_neg(&P);
+        ECP_toOctet(SEC,&P,false);
+    }
+    return res;
+}
+
+/*
+ W=x*H(G);
+ if RNG == NULL then X is passed in
+ if RNG != NULL the X is passed out
+ if type=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve
+*/
+
+int ZZZ::MPIN_GET_G1_MULTIPLE(csprng *RNG,int type,octet *X,octet *G,octet *W)
+{
+    ECP P;
+    BIG r,x;
+    int res=0;
+    if (RNG!=NULL)
+    {
+        BIG_rcopy(r,CURVE_Order);
+        BIG_randomnum(x,r,RNG);
+#ifdef AES_S
+        BIG_mod2m(x,2*AES_S);
+#endif
+        X->len=MODBYTES_XXX;
+        BIG_toBytes(X->val,x);
+    }
+    else
+        BIG_fromBytes(x,X->val);
+
+    if (type==0)
+    {
+        if (!ECP_fromOctet(&P,G)) res=MPIN_INVALID_POINT;
+    }
+    else 
+	{
+		ECP_mapit(&P,G);
+	}
+
+    if (res==0)
+    {
+        PAIR_G1mul(&P,x);
+        ECP_toOctet(W,&P,false);
+    }
+    return res;
+}
+
+/*
+ if RNG == NULL then X is passed in
+ if RNG != NULL the X is passed out
+ W=x*G where G is point on the curve
+ if type==1 W=(x^-1)G
+*/
+
+int ZZZ::MPIN_GET_G2_MULTIPLE(csprng *RNG,int type,octet *X,octet *G,octet *W)
+{
+    ECP8 P;
+    BIG r,x;
+    int res=0;
+    BIG_rcopy(r,CURVE_Order);
+    if (RNG!=NULL)
+    {
+        BIG_randomnum(x,r,RNG);
+#ifdef AES_S
+        BIG_mod2m(x,2*AES_S);
+#endif
+        X->len=MODBYTES_XXX;
+        BIG_toBytes(X->val,x);
+    }
+    else
+    {
+        BIG_fromBytes(x,X->val);
+        if (type==1) BIG_invmodp(x,x,r);
+    }
+
+    if (!ECP8_fromOctet(&P,G)) res=MPIN_INVALID_POINT;
+
+    if (res==0)
+    {
+        PAIR_G2mul(&P,x);
+        ECP8_toOctet(W,&P);
+    }
+    return res;
+}
+
+
+
+/* Client secret CST=s*H(CID) where CID is client ID and s is master secret */
+/* CID is hashed externally */
+int ZZZ::MPIN_GET_CLIENT_SECRET(octet *S,octet *CID,octet *CST)
+{
+    return MPIN_GET_G1_MULTIPLE(NULL,1,S,CID,CST);
+}
+
+/* Implement step 1 on client side of MPin protocol */
+int ZZZ::MPIN_CLIENT_1(int sha,int date,octet *CLIENT_ID,csprng *RNG,octet *X,int pin,octet *TOKEN,octet *SEC,octet *xID,octet *xCID,octet *PERMIT)
+{
+    BIG r,x;
+    ECP P,T,W;
+    int res=0;
+    char h[MODBYTES_XXX];
+    octet H= {0,sizeof(h),h};
+
+    BIG_rcopy(r,CURVE_Order);
+    if (RNG!=NULL)
+    {
+        BIG_randomnum(x,r,RNG);
+#ifdef AES_S
+        BIG_mod2m(x,2*AES_S);
+#endif
+        X->len=MODBYTES_XXX;
+        BIG_toBytes(X->val,x);
+    }
+    else
+        BIG_fromBytes(x,X->val);
+
+    mhashit(sha,-1,CLIENT_ID,&H);
+
+    ECP_mapit(&P,&H);
+
+    if (!ECP_fromOctet(&T,TOKEN)) res=MPIN_INVALID_POINT;
+
+    if (res==0)
+    {
+        pin%=MAXPIN;
+
+        ECP_copy(&W,&P);				// W=H(ID)
+        ECP_pinmul(&W,pin,PBLEN);			// W=alpha.H(ID)
+        ECP_add(&T,&W);					// T=Token+alpha.H(ID) = s.H(ID)
+
+        if (date)
+        {
+            if (PERMIT!=NULL)
+            {
+                if (!ECP_fromOctet(&W,PERMIT)) res=MPIN_INVALID_POINT;
+                ECP_add(&T,&W);					// SEC=s.H(ID)+s.H(T|ID)
+            }
+            mhashit(sha,date,&H,&H);
+
+            ECP_mapit(&W,&H);
+            if (xID!=NULL)
+            {
+                PAIR_G1mul(&P,x);				// P=x.H(ID)
+                ECP_toOctet(xID,&P,false);  // xID
+                PAIR_G1mul(&W,x);               // W=x.H(T|ID)
+                ECP_add(&P,&W); //ECP_affine(&P);
+            }
+            else
+            {
+                ECP_add(&P,&W); //ECP_affine(&P);
+                PAIR_G1mul(&P,x);
+            }
+            if (xCID!=NULL) ECP_toOctet(xCID,&P,false);  // U
+        }
+        else
+        {
+            if (xID!=NULL)
+            {
+                PAIR_G1mul(&P,x);				// P=x.H(ID)
+                ECP_toOctet(xID,&P,false);  // xID
+            }
+        }
+    }
+
+    if (res==0)
+	{
+		//ECP_affine(&T);
+        ECP_toOctet(SEC,&T,false);  // V
+	}
+    return res;
+}
+
+/* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */
+int ZZZ::MPIN_GET_SERVER_SECRET(octet *S,octet *SST)
+{
+    BIG r,s;
+    ECP8 Q;
+    int res=0;
+
+    BIG_rcopy(r,CURVE_Order);
+
+	ECP8_generator(&Q);
+
+    if (res==0)
+    {
+        BIG_fromBytes(s,S->val);
+        PAIR_G2mul(&Q,s);
+        ECP8_toOctet(SST,&Q);
+    }
+
+    return res;
+}
+
+
+/* Time Permit CTT=s*H(date|H(CID)) where s is master secret */
+int ZZZ::MPIN_GET_CLIENT_PERMIT(int sha,int date,octet *S,octet *CID,octet *CTT)
+{
+    BIG s;
+    ECP P;
+    char h[MODBYTES_XXX];
+    octet H= {0,sizeof(h),h};
+
+    mhashit(sha,date,CID,&H);
+
+    ECP_mapit(&P,&H);
+
+//printf("P= "); ECP_output(&P); printf("\n");
+//exit(0);
+
+    BIG_fromBytes(s,S->val);
+
+
+
+//printf("s= "); BIG_output(s); printf("\n");
+    PAIR_G1mul(&P,s);
+//printf("OP= "); ECP_output(&P); printf("\n");
+//
+    ECP_toOctet(CTT,&P,false);
+    return 0;
+}
+
+// if date=0 only use HID, set HCID=NULL
+// if date and PE, use HID and HCID
+
+/* Outputs H(CID) and H(CID)+H(T|H(CID)) for time permits. If no time permits set HTID=NULL */
+void ZZZ::MPIN_SERVER_1(int sha,int date,octet *CID,octet *HID,octet *HTID)
+{
+    char h[MODBYTES_XXX];
+    octet H= {0,sizeof(h),h};
+    ECP P,R;
+	BIG x;
+
+#ifdef USE_ANONYMOUS
+    ECP_mapit(&P,CID);
+#else
+    mhashit(sha,-1,CID,&H);
+    ECP_mapit(&P,&H);
+#endif
+
+    ECP_toOctet(HID,&P,false);  // new
+
+    if (date)
+    {
+        //	if (HID!=NULL) ECP_toOctet(HID,&P,false);
+#ifdef USE_ANONYMOUS
+        mhashit(sha,date,CID,&H);
+#else
+        mhashit(sha,date,&H,&H);
+#endif
+        ECP_mapit(&R,&H);
+        ECP_add(&P,&R); //ECP_affine(&P);
+        ECP_toOctet(HTID,&P,false);
+    }
+    //else ECP_toOctet(HID,&P,false);
+
+}
+
+/* Implement M-Pin on server side */
+int ZZZ::MPIN_SERVER_2(int date,octet *HID,octet *HTID,octet *Y,octet *SST,octet *xID,octet *xCID,octet *mSEC,octet *E,octet *F,octet *Pa)
+{
+    BIG y;
+    FP48 g;
+    ECP8 Q,sQ;
+    ECP P,R;
+    int res=0;
+
+	ECP8_generator(&Q);
+
+    // key-escrow less scheme: use Pa instead of Q in pairing computation
+    // Q left for backward compatiblity
+    if (Pa!=NULL)
+    {
+        if (!ECP8_fromOctet(&Q, Pa)) res=MPIN_INVALID_POINT;
+    }
+
+
+    if (res==0)
+    {
+        if (!ECP8_fromOctet(&sQ,SST)) res=MPIN_INVALID_POINT;
+    }
+
+    if (res==0)
+    {
+        if (date)
+        {
+            //BIG_fromBytes(px,&(xCID->val[1]));
+            //BIG_fromBytes(py,&(xCID->val[PFS_ZZZ+1]));
+			if (!ECP_fromOctet(&R,xCID))  res=MPIN_INVALID_POINT;
+		
+        }
+        else
+        {
+            //BIG_fromBytes(px,&(xID->val[1]));
+            //BIG_fromBytes(py,&(xID->val[PFS_ZZZ+1]));
+			if (!ECP_fromOctet(&R,xID))  res=MPIN_INVALID_POINT;
+        }
+        //if (!ECP_set(&R,px,py)) res=MPIN_INVALID_POINT; // x(A+AT)
+    }
+    if (res==0)
+    {
+        BIG_fromBytes(y,Y->val);
+        if (date)
+        {
+            if (!ECP_fromOctet(&P,HTID))  res=MPIN_INVALID_POINT;
+        }
+        else
+        {
+            if (!ECP_fromOctet(&P,HID))  res=MPIN_INVALID_POINT;
+        }
+    }
+    if (res==0)
+    {
+        PAIR_G1mul(&P,y);  // y(A+AT)
+        ECP_add(&P,&R); // x(A+AT)+y(A+T)
+		//ECP_affine(&P);
+        if (!ECP_fromOctet(&R,mSEC))  res=MPIN_INVALID_POINT; // V
+    }
+    if (res==0)
+    {
+
+        PAIR_double_ate(&g,&Q,&R,&sQ,&P);
+        PAIR_fexp(&g);
+
+        if (!FP48_isunity(&g))
+        {
+            if (HID!=NULL && xID!=NULL && E!=NULL && F !=NULL)
+            {
+                /* xID is set to NULL if there is no way to calculate PIN error */
+                FP48_toOctet(E,&g);
+
+                /* Note error is in the PIN, not in the time permit! Hence the need to exclude Time Permit from this check */
+
+                if (date)
+                {
+                    if (!ECP_fromOctet(&P,HID)) res=MPIN_INVALID_POINT;
+                    if (!ECP_fromOctet(&R,xID)) res=MPIN_INVALID_POINT; // U
+
+                    if (res==0)
+                    {
+                        PAIR_G1mul(&P,y);  // yA
+                        ECP_add(&P,&R); // yA+xA
+						//ECP_affine(&P);
+                    }
+                }
+                if (res==0)
+                {
+                    PAIR_ate(&g,&Q,&P);
+                    PAIR_fexp(&g);
+                    FP48_toOctet(F,&g);
+                }
+            }
+            res=MPIN_BAD_PIN;
+        }
+    }
+
+    return res;
+}
+
+#if MAXPIN==10000
+#define MR_TS 10  /* 2^10/10 approx = sqrt(MAXPIN) */
+#define TRAP 200  /* 2*sqrt(MAXPIN) */
+#endif
+
+#if MAXPIN==1000000
+#define MR_TS 14
+#define TRAP 2000
+#endif
+
+/* Pollards kangaroos used to return PIN error */
+int ZZZ::MPIN_KANGAROO(octet *E,octet *F)
+{
+    int i,j,m,s,dn,dm,steps;
+    int distance[MR_TS];
+    FP48 ge,gf,t,table[MR_TS];
+    int res=0;
+    // BIG w;
+
+    FP48_fromOctet(&ge,E);
+    FP48_fromOctet(&gf,F);
+
+    FP48_copy(&t,&gf);
+
+    for (s=1,m=0; m<MR_TS; m++)
+    {
+        distance[m]=s;
+        FP48_copy(&table[m],&t);
+        s*=2;
+        FP48_usqr(&t,&t);
+        FP48_reduce(&t);
+    }
+
+    FP48_one(&t);
+
+    for (dn=0,j=0; j<TRAP; j++)
+    {
+
+        //BIG_copy(w,t.a.a.a);
+        //FP_redc(w);
+        //i=BIG_lastbits(w,20)%MR_TS;
+
+        i=t.a.a.a.a.a.g[0]%MR_TS;
+
+        FP48_mul(&t,&table[i]);
+        FP48_reduce(&t);
+        dn+=distance[i];
+    }
+
+    FP48_conj(&gf,&t);
+    steps=0;
+    dm=0;
+    while (dm-dn<MAXPIN)
+    {
+        steps++;
+        if (steps>4*TRAP) break;
+
+        //BIG_copy(w,ge.a.a.a);
+        //FP_redc(w);
+        //i=BIG_lastbits(w,20)%MR_TS;
+
+        i=ge.a.a.a.a.a.g[0]%MR_TS;
+
+        FP48_mul(&ge,&table[i]);
+        FP48_reduce(&ge);
+        dm+=distance[i];
+        if (FP48_equals(&ge,&t))
+        {
+            res=dm-dn;
+            break;
+        }
+        if (FP48_equals(&ge,&gf))
+        {
+            res=dn-dm;
+            break;
+        }
+    }
+    if (steps>4*TRAP || dm-dn>=MAXPIN)
+    {
+        res=0;    /* Trap Failed  - probable invalid token */
+    }
+
+    return res;
+}
+
+/* Functions to support M-Pin Full */
+
+int ZZZ::MPIN_PRECOMPUTE(octet *TOKEN,octet *CID,octet *CP,octet *G1,octet *G2)
+{
+    ECP P,T;
+    ECP8 Q;
+    FP48 g;
+	BIG x;
+    int res=0;
+
+    if (!ECP_fromOctet(&T,TOKEN)) res=MPIN_INVALID_POINT;
+
+    if (res==0)
+    {
+        ECP_mapit(&P,CID);
+        if (CP!=NULL)
+        {
+            if (!ECP8_fromOctet(&Q,CP)) res=MPIN_INVALID_POINT;
+        }
+        else
+        {
+			ECP8_generator(&Q);
+        }
+    }
+    if (res==0)
+    {
+        PAIR_ate(&g,&Q,&T);
+        PAIR_fexp(&g);
+
+        FP48_toOctet(G1,&g);
+        if (G2!=NULL)
+        {
+            PAIR_ate(&g,&Q,&P);
+            PAIR_fexp(&g);
+            FP48_toOctet(G2,&g);
+        }
+    }
+    return res;
+}
+
+/* calculate common key on client side */
+/* wCID = w.(A+AT) */
+int ZZZ::MPIN_CLIENT_KEY(int sha,octet *G1,octet *G2,int pin,octet *R,octet *X,octet *H,octet *wCID,octet *CK)
+{
+    FP48 g1,g2;
+	FP16 c;//,cp,cpm1,cpm2;
+
+    ECP W;
+    int res=0;
+    BIG r,z,x,h;//q,m,a,b;
+
+    FP48_fromOctet(&g1,G1);
+    FP48_fromOctet(&g2,G2);
+    BIG_fromBytes(z,R->val);
+    BIG_fromBytes(x,X->val);
+    BIG_fromBytes(h,H->val);
+
+    if (!ECP_fromOctet(&W,wCID)) res=MPIN_INVALID_POINT;
+
+    if (res==0)
+    {
+        BIG_rcopy(r,CURVE_Order);
+        BIG_add(z,z,h);    // new
+        BIG_mod(z,r);
+
+        FP48_pinpow(&g2,pin,PBLEN);
+        FP48_mul(&g1,&g2);
+
+		PAIR_G1mul(&W,x);
+
+		FP48_compow(&c,&g1,z,r);
+		mpin_hash(sha,&c,&W,CK);
+
+    }
+    return res;
+}
+
+/* calculate common key on server side */
+/* Z=r.A - no time permits involved */
+
+int ZZZ::MPIN_SERVER_KEY(int sha,octet *Z,octet *SST,octet *W,octet *H,octet *HID,octet *xID,octet *xCID,octet *SK)
+{
+    int res=0;
+    FP48 g;
+    FP16 c;
+    ECP R,U,A;
+    ECP8 sQ;
+    BIG w,h;
+
+    if (!ECP8_fromOctet(&sQ,SST)) res=MPIN_INVALID_POINT;
+    if (!ECP_fromOctet(&R,Z)) res=MPIN_INVALID_POINT;
+
+
+    if (!ECP_fromOctet(&A,HID)) res=MPIN_INVALID_POINT;
+
+    // new
+    if (xCID!=NULL)
+    {
+        if (!ECP_fromOctet(&U,xCID)) res=MPIN_INVALID_POINT;
+    }
+    else
+    {
+        if (!ECP_fromOctet(&U,xID)) res=MPIN_INVALID_POINT;
+    }
+    BIG_fromBytes(w,W->val);
+    BIG_fromBytes(h,H->val);
+
+
+    PAIR_ate(&g,&sQ,&A);
+    PAIR_fexp(&g);
+
+    if (res==0)
+    {
+        PAIR_G1mul(&A,h);
+        ECP_add(&R,&A);  // new
+		//ECP_affine(&R);
+        PAIR_ate(&g,&sQ,&R);
+        PAIR_fexp(&g);
+        PAIR_G1mul(&U,w);
+        FP48_trace(&c,&g);
+        mpin_hash(sha,&c,&U,SK);
+    }
+    return res;
+}
+
+/* Generate Y = H(TimeValue, xCID/xID) */
+void ZZZ::MPIN_GET_Y(int sha,int TimeValue,octet *xCID,octet *Y)
+{
+    BIG q,y;
+    char h[MODBYTES_XXX];
+    octet H= {0,sizeof(h),h};
+
+    mhashit(sha,TimeValue,xCID,&H);
+    BIG_fromBytes(y,H.val);
+    BIG_rcopy(q,CURVE_Order);
+    BIG_mod(y,q);
+    BIG_toBytes(Y->val,y);
+    Y->len=PGS_ZZZ;
+}
+
+/* One pass MPIN Client */
+int ZZZ::MPIN_CLIENT(int sha,int date,octet *ID,csprng *RNG,octet *X,int pin,octet *TOKEN,octet *V,octet *U,octet *UT,octet *TP,octet *MESSAGE,int TimeValue,octet *Y)
+{
+    int rtn=0;
+    char m[2*PFS_ZZZ+1];
+    octet M= {0,sizeof(m),m};
+
+    octet *pID;
+    if (date == 0)
+        pID = U;
+    else
+        pID = UT;
+
+    rtn = MPIN_CLIENT_1(sha,date,ID,RNG,X,pin,TOKEN,V,U,UT,TP);
+    if (rtn != 0)
+        return rtn;
+
+    OCT_joctet(&M,pID);
+   if (MESSAGE!=NULL)
+   {
+       OCT_joctet(&M,MESSAGE);
+   }
+
+    MPIN_GET_Y(sha,TimeValue,&M,Y);
+
+    rtn = MPIN_CLIENT_2(X,Y,V);
+    if (rtn != 0)
+        return rtn;
+
+    return 0;
+}
+
+/* One pass MPIN Server */
+int ZZZ::MPIN_SERVER(int sha,int date,octet *HID,octet *HTID,octet *Y,octet *sQ,octet *U,octet *UT,octet *V,octet *E,octet *F,octet *ID,octet *MESSAGE,int TimeValue, octet *Pa)
+{
+    int rtn=0;
+    char m[2*PFS_ZZZ+1];
+    octet M= {0,sizeof(m),m};
+
+    octet *pU;
+    if (date == 0)
+        pU = U;
+    else
+        pU = UT;
+
+    MPIN_SERVER_1(sha,date,ID,HID,HTID);
+
+    OCT_joctet(&M,pU);
+   if (MESSAGE!=NULL)
+   {
+       OCT_joctet(&M,MESSAGE);
+   }
+
+    MPIN_GET_Y(sha,TimeValue,&M,Y);
+
+    rtn = MPIN_SERVER_2(date,HID,HTID,Y,sQ,U,UT,V,E,F,Pa);
+    if (rtn != 0)
+        return rtn;
+
+    return 0;
+}
+
+int ZZZ::MPIN_GET_DVS_KEYPAIR(csprng *R,octet *Z,octet *Pa)
+{
+    BIG z,r;
+    ECP8 Q;
+    int res=0;
+
+    BIG_rcopy(r,CURVE_Order);
+
+    if (R!=NULL)
+    {
+        BIG_randomnum(z,r,R);
+        Z->len=MODBYTES_XXX;
+        BIG_toBytes(Z->val,z);
+    }
+    else
+        BIG_fromBytes(z,Z->val);
+
+    BIG_invmodp(z,z,r);
+
+	ECP8_generator(&Q);
+
+    if (res==0)
+    {
+        PAIR_G2mul(&Q,z);
+        ECP8_toOctet(Pa,&Q);
+    }
+
+    return res;
+}
diff --git a/version3/cpp/mpin256.h b/version3/cpp/mpin256.h
new file mode 100644
index 0000000..35d8afe
--- /dev/null
+++ b/version3/cpp/mpin256.h
@@ -0,0 +1,340 @@
+/*
+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.
+*/
+
+/**
+ * @file mpin.h
+ * @author Mike Scott and Kealan McCusker
+ * @date 2nd June 2015
+ * @brief M-Pin Header file
+ *
+ * Allows some user configuration
+ * defines structures
+ * declares functions
+ *
+ */
+
+#ifndef MPIN_ZZZ_H
+#define MPIN_ZZZ_H
+
+#include "pair256_ZZZ.h"
+#include "pbc_support.h"
+
+using namespace amcl;
+
+
+namespace ZZZ {
+
+/* Field size is assumed to be greater than or equal to group size */
+
+#define PGS_ZZZ MODBYTES_XXX  /**< MPIN Group Size */
+#define PFS_ZZZ MODBYTES_XXX  /**< MPIN Field Size */
+
+#define MPIN_OK             0   /**< Function completed without error */
+#define MPIN_INVALID_POINT  -14	/**< Point is NOT on the curve */
+#define MPIN_BAD_PIN        -19 /**< Bad PIN number entered */
+
+#define MAXPIN 10000         /**< max PIN */
+#define PBLEN 14             /**< max length of PIN in bits */
+
+//#define PAS_ZZZ 24        /**< MPIN Symmetric Key Size 192 bits  */
+//#define HASH_TYPE_MPIN_ZZZ SHA384   /**< Choose Hash function */
+
+/* MPIN support functions */
+
+/* MPIN primitives */
+
+
+void MPIN_GET_Y(int h,int t,octet *O,octet *Y);
+/**	@brief Extract a PIN number from a client secret
+ *
+  	@param h is the hash type
+	@param ID is the input client identity
+	@param factor is an input factor
+	@param facbits is the number of bits in the factor
+	@param CS is the client secret from which the factor is to be extracted
+	@return 0 or an error code
+ */
+int MPIN_EXTRACT_FACTOR(int h,octet *ID,int factor,int facbits,octet *CS);
+
+/**	@brief Extract a PIN number from a client secret
+ *
+  	@param h is the hash type
+	@param ID is the input client identity
+	@param factor is an input factor
+	@param facbits is the number of bits in the factor
+	@param CS is the client secret to which the factor is to be added
+	@return 0 or an error code
+ */
+int MPIN_RESTORE_FACTOR(int h,octet *ID,int factor,int facbits,octet *CS);
+
+
+/**	@brief Extract a PIN number from a client secret
+ *
+  	@param h is the hash type
+	@param ID is the input client identity
+	@param pin is an input PIN number
+	@param CS is the client secret from which the PIN is to be extracted
+	@return 0 or an error code
+ */
+int MPIN_EXTRACT_PIN(int h,octet *ID,int pin,octet *CS);
+
+/**	@brief Perform client side of the one-pass version of the M-Pin protocol
+ *
+	If Time Permits are disabled, set d = 0, and UT is not generated and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is OFF, U is not generated and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is ON, U and UT are both generated.
+ 	@param h is the hash type
+	@param d is input date, in days since the epoch. Set to 0 if Time permits disabled
+	@param ID is the input client identity
+	@param R is a pointer to a cryptographically secure random number generator
+	@param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input
+	@param pin is the input PIN number
+	@param T is the input M-Pin token (the client secret with PIN portion removed)
+	@param V is output = -(x+y)(CS+TP), where CS is the reconstructed client secret, and TP is the time permit
+	@param U is output = x.H(ID)
+	@param UT is output = x.(H(ID)+H(d|H(ID)))
+	@param TP is the input time permit
+	@param MESSAGE is the message to be signed
+	@param t is input epoch time in seconds - a timestamp
+	@param y is output H(t|U) or H(t|UT) if Time Permits enabled
+	@return 0 or an error code
+ */
+int MPIN_CLIENT(int h,int d,octet *ID,csprng *R,octet *x,int pin,octet *T,octet *V,octet *U,octet *UT,octet *TP, octet* MESSAGE, int t, octet *y);
+/**	@brief Perform first pass of the client side of the 3-pass version of the M-Pin protocol
+ *
+	If Time Permits are disabled, set d = 0, and UT is not generated and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is OFF, U is not generated and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is ON, U and UT are both generated.
+ 	@param h is the hash type
+	@param d is input date, in days since the epoch. Set to 0 if Time permits disabled
+	@param ID is the input client identity
+	@param R is a pointer to a cryptographically secure random number generator
+	@param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input
+	@param pin is the input PIN number
+	@param T is the input M-Pin token (the client secret with PIN portion removed)
+	@param S is output = CS+TP, where CS=is the reconstructed client secret, and TP is the time permit
+	@param U is output = x.H(ID)
+	@param UT is output = x.(H(ID)+H(d|H(ID)))
+	@param TP is the input time permit
+	@return 0 or an error code
+ */
+int MPIN_CLIENT_1(int h,int d,octet *ID,csprng *R,octet *x,int pin,octet *T,octet *S,octet *U,octet *UT,octet *TP);
+/**	@brief Generate a random group element
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param S is the output random octet
+	@return 0 or an error code
+ */
+int MPIN_RANDOM_GENERATE(csprng *R,octet *S);
+/**	@brief Perform second pass of the client side of the 3-pass version of the M-Pin protocol
+ *
+	@param x an input, a locally generated random number
+	@param y an input random challenge from the server
+	@param V on output = -(x+y).V
+	@return 0 or an error code
+ */
+int MPIN_CLIENT_2(octet *x,octet *y,octet *V);
+/**	@brief Perform server side of the one-pass version of the M-Pin protocol
+ *
+	If Time Permits are disabled, set d = 0, and UT and HTID are not generated and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is OFF, U and HID are not needed and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is ON, U, UT, HID and HTID are all required.
+ 	@param h is the hash type
+	@param d is input date, in days since the epoch. Set to 0 if Time permits disabled
+	@param HID is output H(ID), a hash of the client ID
+	@param HTID is output H(ID)+H(d|H(ID))
+	@param y is output H(t|U) or H(t|UT) if Time Permits enabled
+	@param SS is the input server secret
+	@param U is input from the client = x.H(ID)
+	@param UT is input from the client= x.(H(ID)+H(d|H(ID)))
+	@param V is an input from the client
+	@param E is an output to help the Kangaroos to find the PIN error, or NULL if not required
+	@param F is an output to help the Kangaroos to find the PIN error, or NULL if not required
+	@param ID is the input claimed client identity
+	@param MESSAGE is the message to be signed
+	@param t is input epoch time in seconds - a timestamp
+	@param Pa is input from the client z.Q or NULL if the key-escrow less scheme is not used
+	@return 0 or an error code
+ */
+int MPIN_SERVER(int h,int d,octet *HID,octet *HTID,octet *y,octet *SS,octet *U,octet *UT,octet *V,octet *E,octet *F,octet *ID,octet *MESSAGE, int t, octet *Pa);
+/**	@brief Perform first pass of the server side of the 3-pass version of the M-Pin protocol
+ *
+ 	@param h is the hash type
+	@param d is input date, in days since the epoch. Set to 0 if Time permits disabled
+	@param ID is the input claimed client identity
+	@param HID is output H(ID), a hash of the client ID
+	@param HTID is output H(ID)+H(d|H(ID))
+	@return 0 or an error code
+ */
+void MPIN_SERVER_1(int h,int d,octet *ID,octet *HID,octet *HTID);
+/**	@brief Perform third pass on the server side of the 3-pass version of the M-Pin protocol
+ *
+	If Time Permits are disabled, set d = 0, and UT and HTID are not needed and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is OFF, U and HID are not needed and can be set to NULL.
+	If Time Permits are enabled, and PIN error detection is ON, U, UT, HID and HTID are all required.
+	@param d is input date, in days since the epoch. Set to 0 if Time permits disabled
+	@param HID is input H(ID), a hash of the client ID
+	@param HTID is input H(ID)+H(d|H(ID))
+	@param y is the input server's randomly generated challenge
+	@param SS is the input server secret
+	@param U is input from the client = x.H(ID)
+	@param UT is input from the client= x.(H(ID)+H(d|H(ID)))
+	@param V is an input from the client
+	@param E is an output to help the Kangaroos to find the PIN error, or NULL if not required
+	@param F is an output to help the Kangaroos to find the PIN error, or NULL if not required
+	@param Pa is the input public key from the client, z.Q or NULL if the client uses regular mpin
+	@return 0 or an error code
+ */
+int MPIN_SERVER_2(int d,octet *HID,octet *HTID,octet *y,octet *SS,octet *U,octet *UT,octet *V,octet *E,octet *F,octet *Pa);
+/**	@brief Add two members from the group G1
+ *
+	@param Q1 an input member of G1
+	@param Q2 an input member of G1
+	@param Q an output member of G1 = Q1+Q2
+	@return 0 or an error code
+ */
+int MPIN_RECOMBINE_G1(octet *Q1,octet *Q2,octet *Q);
+/**	@brief Add two members from the group G2
+ *
+	@param P1 an input member of G2
+	@param P2 an input member of G2
+	@param P an output member of G2 = P1+P2
+	@return 0 or an error code
+ */
+int MPIN_RECOMBINE_G2(octet *P1,octet *P2,octet *P);
+/**	@brief Use Kangaroos to find PIN error
+ *
+	@param E a member of the group GT
+	@param F a member of the group GT =  E^e
+	@return 0 if Kangaroos failed, or the PIN error e
+ */
+int MPIN_KANGAROO(octet *E,octet *F);
+/**	@brief Encoding of a Time Permit to make it indistinguishable from a random string
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param TP is the input time permit, obfuscated on output
+	@return 0 or an error code
+ */
+int MPIN_ENCODING(csprng *R,octet *TP);
+/**	@brief Encoding of an obfuscated Time Permit
+ *
+	@param TP is the input obfuscated time permit, restored on output
+	@return 0 or an error code
+ */
+int MPIN_DECODING(octet *TP);
+
+/**	@brief Find a random multiple of a point in G1
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param type determines type of action to be taken
+	@param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input
+	@param G if type=0 a point in G1, else an octet to be mapped to G1
+	@param W the output =x.G or x.M(G), where M(.) is a mapping
+	@return 0 or an error code
+ */
+int MPIN_GET_G1_MULTIPLE(csprng *R,int type,octet *x,octet *G,octet *W);
+/**	@brief Find a random multiple of a point in G1
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param type determines type of action to betaken
+	@param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input
+	@param G a point in G2
+	@param W the output =x.G or (1/x).G
+	@return 0 or an error code
+ */
+int MPIN_GET_G2_MULTIPLE(csprng *R,int type,octet *x,octet *G,octet *W);
+
+/**	@brief Create a client secret in G1 from a master secret and the client ID
+ *
+	@param S is an input master secret
+	@param ID is the input client identity
+	@param CS is the full client secret = s.H(ID)
+	@return 0 or an error code
+ */
+int MPIN_GET_CLIENT_SECRET(octet *S,octet *ID,octet *CS);
+/**	@brief Create a Time Permit in G1 from a master secret and the client ID
+ *
+  	@param h is the hash type
+	@param d is input date, in days since the epoch.
+	@param S is an input master secret
+	@param ID is the input client identity
+	@param TP is a Time Permit for the given date = s.H(d|H(ID))
+	@return 0 or an error code
+ */
+int MPIN_GET_CLIENT_PERMIT(int h,int d,octet *S,octet *ID,octet *TP);
+/**	@brief Create a server secret in G2 from a master secret
+ *
+	@param S is an input master secret
+	@param SS is the server secret = s.Q where Q is a fixed generator of G2
+	@return 0 or an error code
+ */
+int MPIN_GET_SERVER_SECRET(octet *S,octet *SS);
+/* int MPIN_TEST_PAIRING(octet *,octet *); */
+
+/* For M-Pin Full */
+/**	@brief Precompute values for use by the client side of M-Pin Full
+ *
+	@param T is the input M-Pin token (the client secret with PIN portion removed)
+	@param ID is the input client identity
+	@param CP is Public Key (or NULL)
+	@param g1 precomputed output
+	@param g2 precomputed output
+	@return 0 or an error code
+ */
+int MPIN_PRECOMPUTE(octet *T,octet *ID,octet *CP,octet *g1,octet *g2);
+/**	@brief Calculate Key on Server side for M-Pin Full
+ *
+	Uses UT internally for the key calculation, unless not available in which case U is used
+ 	@param h is the hash type
+	@param Z is the input Client-side Diffie-Hellman component
+	@param SS is the input server secret
+	@param w is an input random number generated by the server
+	@param p is an input, hash of the protocol transcript
+	@param I is the hashed input client ID = H(ID)
+	@param U is input from the client = x.H(ID)
+	@param UT is input from the client= x.(H(ID)+H(d|H(ID)))
+	@param K is the output calculated shared key
+	@return 0 or an error code
+ */
+int MPIN_SERVER_KEY(int h,octet *Z,octet *SS,octet *w,octet *p,octet *I,octet *U,octet *UT,octet *K);
+/**	@brief Calculate Key on Client side for M-Pin Full
+ *
+  	@param h is the hash type
+	@param g1 precomputed input
+	@param g2 precomputed input
+	@param pin is the input PIN number
+	@param r is an input, a locally generated random number
+	@param x is an input, a locally generated random number
+	@param p is an input, hash of the protocol transcript
+	@param T is the input Server-side Diffie-Hellman component
+	@param K is the output calculated shared key
+	@return 0 or an error code
+ */
+int MPIN_CLIENT_KEY(int h,octet *g1,octet *g2,int pin,octet *r,octet *x,octet *p,octet *T,octet *K);
+
+/** @brief Generates a random public key for the client z.Q
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param Z an output internally randomly generated if R!=NULL, otherwise it must be provided as an input
+	@param Pa the output public key for the client
+ */
+int MPIN_GET_DVS_KEYPAIR(csprng *R,octet *Z,octet *Pa);
+}
+#endif
+
diff --git a/version3/cpp/newhope.cpp b/version3/cpp/newhope.cpp
new file mode 100644
index 0000000..be200c3
--- /dev/null
+++ b/version3/cpp/newhope.cpp
@@ -0,0 +1,515 @@
+/*
+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.
+*/
+
+/* NewHope API implementation. Constant time.
+
+	LOOK - no if statements!
+
+   M.Scott 21/07/2017
+*/
+
+#include "newhope.h"
+
+using namespace amcl;
+
+const sign16 roots[] ={0x2ac8,0x2baf,0x299b,0x685,0x2f04,0x158d,0x2d49,0x24b5,0x1edc,0xab3,0x2a95,0x24d,0x3cb,0x6a8,0x12f9,0x15ba,0x1861,0x2a89,0x1c5c,0xbe6,0xc1e,0x2024,0x207,0x19ce,0x2710,0x1744,0x18bc,0x2cd7,0x396,0x18d5,0x1c45,0xc4,0x21a6,0xe03,0x2b3c,0x2d91,0xc5d,0x432,0x1fbc,0xcae,0x2512,0x2979,0x3b2,0x714,0xb2e,0x1a97,0x1a03,0x1bcd,0x2216,0x2701,0xa,0x263c,0x1179,0x200c,0x2d08,0x1c34,0x291,0x2c99,0x2a5a,0x723,0xb1d,0x1ccc,0x1fb6,0x2f58,0x2bfe,0x1cda,0x2a0,0x5f1,0x2de,0x1fc7,0x1ea8,0x1719,0x2fa7,0x27ec,0x20ff,0x12c0,0x1ac1,0x2232,0x2f9b,0xd3e,0x2aed,0x15f0,0x11e8,0xed0,0x26a,0x1de5,0xa3f,0xf43,0xebf,0x204e,0xac7,0x2d9c,0x5ea,0x25d1,0xb6,0x49c,0x995,0x2555,0x26e2,0x100,0x1878,0x5aa,0x2e10,0x271c,0xcb,0x1b4c,0x2fb8,0x25b7,0x1543,0x2c7b,0x241a,0x2223,0x20ca,0x24ed,0x137,0x1b65,0x1dc2,0x7c7,0x2ec3,0xd0c,0x1169,0x1c7a,0x1ea1,0xf89,0x2199,0x291d,0x1088,0x2046,0x256d,0x2bc7,0x2e9b,0x41f,0x1b55,0x2b38,0xd0,0x2e6a,0x1755,0x6bc,0x2724,0x3ba,0x222e,0x2c5c,0x2da5,0x213c,0x10fe,0x169a,0x1552,0x5d3,0x300,0x1b5d,0x1342,0x2004,0x256f,0x2039,0x667,0x23b5,0x1123,0xdb,0x2da0,0xe1e,0x2f54,0x2767,0x154a,0x40a,0x11d3,0x2821,0xc09,0x974,0x694,0xfbf,0x27ba,0x132,0x83f,0x2d06,0x10e,0x183f,0x29ae,0x28c3,0x2dc9,0x1144,0x2c70,0x2a4a,0xf3c,0x1e32,0x1171,0x1e43,0xdd4,0x2ddf,0x28d2,0xfac,0x3c4,0x2f19,0x10a6,0x2f7,0xe1d,0x828,0x138f,0x1332,0xfab,0xcf6,0x13f8,0x24a0,0x112d,0x2717,0x6e7,0x1044,0x36e,0xfe8,0x6a,0xba7,0x1d69,0x29ec,0x23b2,0xaee,0x16df,0x1068,0x1a7e,0x253f,0x24c,0xb33,0x2683,0x15ce,0x1ad3,0x1a36,0xc96,0xaea,0x260a,0xce,0x28b1,0xe4f,0x2b11,0x5f8,0x1fc4,0xe77,0x2366,0x11f9,0x153c,0x24eb,0x20cd,0x1398,0x22,0x2b97,0x249b,0x8eb,0x12b2,0x2fe3,0x29c1,0x1b00,0x2663,0xeaa,0x2e06,0xe0,0x1569,0x10f5,0x284e,0xa38,0x201d,0x1c53,0x1681,0x1f6f,0x2f95,0x2fe8,0xacb,0x1680,0x17fd,0x2c39,0x165a,0x10bb,0x29d8,0x2622,0x1196,0x884,0x2a79,0x140e,0x2d80,0x6fa,0x11b2,0x26c4,0x355,0x1054,0x29e9,0x23ed,0xbe3,0x24fa,0x1fb3,0x10ac,0x2919,0x2584,0x10a4,0xe85,0x650,0x1893,0x1dc1,0xd8e,0x12dc,0x2d42,0x284d,0xfff,0x250f,0xacd,0x13c3,0x6cc,0x1a79,0x1221,0x2614,0x270a,0x1ea,0x155,0x2818,0x222c,0x2e5b,0x25d8,0x1dbf,0x191c,0xb0f,0xdac,0x1082,0x12ef,0x11b6,0xfa8,0x2b72,0x159d,0x209e,0x31b,0x2c7c,0x14f7,0xe09,0x1bb2,0x1ec7,0x2404,0x20ae,0x6ad,0xed6,0x2b70,0x1c7b,0x18d1,0x2732,0x12da,0xd56,0x5c1,0x1648,0x18b7,0x1605,0x1bc4,0x280,0x2ece,0xc,0x1aae,0x1c4,0x1cdb,0x22d6,0x21d8,0x257c,0x51f,0x211b,0xff,0x2ee0,0x2585,0xe1,0x2c35,0x26db,0x2971,0x2208,0x17e1,0x21be,0x135e,0x28d6,0x2891,0x1689,0x2138,0xb86,0x2e3a,0x1204,0x2d10,0x2324,0xf3f,0x2508,0x33d,0xcb2,0x292a,0xe27,0x2e64,0x29f8,0x2d46,0x9b7,0x20eb,0x1b7c,0x9eb,0x2b2a,0x58c,0x27d0,0x121b,0x272e,0x29f6,0x2dbd,0x2697,0x2aac,0xd6f,0x1c67,0x2c5b,0x108d,0x363,0x249d,0x2d5e,0x2fd,0x2cb2,0x1f8f,0x20a4,0xa19,0x2ac9,0x19b1,0x1581,0x17a2,0x29eb,0x1b72,0x13b0,0xee4,0xa8f,0x2315,0x5e6,0x951,0x2e29,0xdad,0x1f2b,0x224e,0x37f,0x1a72,0xa91,0x1407,0x2df9,0x3ad,0x23f7,0x1a24,0x1d2a,0x234b,0x1df3,0x1143,0x7ff,0x1a6d,0x2774,0x2690,0x2ab5,0x586,0x2781,0x2009,0x2fdd,0x2881,0x399,0x2fb6,0x144,0x137f,0xfa0,0x2e4c,0x1c7f,0x2fac,0xb09,0x1264,0x127b,0x198c,0x2b40,0x230,0x1cf4,0x180b,0xb58,0x144a,0x2aec,0xfb,0x2602,0x14ee,0x783,0x1098,0x23d8,0x203,0xe9,0x108a,0x14b8,0xeec,0xc58,0x1248,0x243c,0x28aa,0x6bf,0x27c4,0x276e,0x19b8,0x1d11,0x2e16,0x472,0x1464,0x24b9,0x662,0x1097,0x2067,0x20d6,0x171c,0x4,0x682,0x17bb,0x1186,0x4f2,0x3ff,0x2a43,0x1dc7,0x1ae5,0x8cc,0x2e7c,0x2ef8,0x2ae0,0x2904,0xed4,0x6c5,0x14ae,0xb72,0x11c3,0x337,0x2da3,0x2916,0x6d8,0x1cf9,0x10ee,0x1800,0x1ae4,0xa0d,0x101b,0x1a8d,0x2e98,0x24cd,0x813,0x1aa4,0x9b9,0x680,0x2349,0x24d1,0x20f8,0xe31,0x249f,0x216b,0x12d9,0x1d21,0x19db,0x191a,0x1dd0,0x5df,0x55c,0x2b86,0x213,0xe9e,0x1ef1,0x268a,0x1d5e,0x1e20,0x28c1,0x1379,0x249,0x19de,0x18b,0x1e41,0x2a1e,0x2612,0x297,0x2e96,0x2102,0x46,0x1b9f,0x1a4d,0x2050,0x1b32,0x568,0x11f7,0x1829,0x870,0x1f4,0x1dca,0x990,0x1df6,0x2b62,0x13ec,0x9f2,0x1260,0x2997,0x1412,0x1e6d,0x1694,0x11ac,0x2d8b,0x276f,0x26f5,0x233e,0x2b44,0x2f5a,0x2d37,0x2cb1,0xc75,0x98d,0x1d56,0x7ae,0x10e6,0x113f,0x17b8,0xad3,0x737,0x221e,0x1b70,0x1f3e,0x2966,0x18b2,0x4fa,0x2044,0x1312,0x154e,0x2029,0x700,0x1b45,0x27a6,0x226a,0x21bf,0x58d,0x2f11,0x2e02,0x17fc,0x4d2,0x1757,0xcb1,0x2ef1,0x2582,0x1276,0x881,0x2fc0,0x104a,0x670,0x274f,0x2b53,0x19dd,0x752,0x1663,0xcbd,0x2b2b,0x2fc6,0x13b6,0x21e6,0x15f6,0x126b,0x2637,0x1cd9,0x2f50,0xe82,0x5b0,0x24e0,0x1350,0x2f24,0x21f7,0x1a16,0x2f3e,0x167e,0x1f7d,0x28a0,0x16f0,0xe33,0x53b,0x28c5,0x1500,0x2f88,0x26cc,0x2018,0x1604,0x218b,0x2cd1,0x9ee,0x17f3,0x5fd,0x1f5a,0x2d0,0x2b46,0x23cc,0x503,0x1c46,0x1cc3,0x28e2,0x243e,0x122b,0x2e0c,0xe37,0x2611,0x85e,0x9b8,0x1b24,0x762,0x19b6,0x3bc,0x2d50,0x2079,0x18da,0x170a,0x800,0xaa2,0x135a,0x1a15,0x13d1,0xca,0x2113,0x2db9,0xdb2,0x1a5c,0x29a9,0x1488,0x14c1,0x2c9,0x917,0x28e7,0x265c,0xdab,0x2ab9,0x2bc6,0x105b,0x1839,0x219c,0x50,0x11da,0x1802,0xf56,0x2e6,0x2190,0xddb,0x56e,0x9d9,0x1c81,0x1016,0x12d6,0x296f,0x14b4,0x1014,0x1e64,0x1d90,0x89f,0x2bc2,0x2777,0x2819,0x1c65,0x1a41,0x5a2,0x2cd2,0x427,0xd71,0x29c8,0x1e58,0x53f,0x7c5,0x1dcd,0x4a1,0x1268,0x2597,0x2926,0xee,0x111b,0x1038,0xe6c,0x22dc,0x2f2f,0x441,0x2cfd,0x1cb0,0x6a4,0x2224,0x620,0x5dc,0x16b1,0x2a1d,0x1787,0x20c7,0x641,0xd84,0x1c05,0x2d0d,0x2f52,0x1b8c,0xd7d,0x17e8,0x1589,0xc73,0x151b,0x4e2,0x1ae9,0x1b18,0xb9b,0x949,0x2c60,0x1e7a,0xd5,0x1bdc,0x1f57,0x1753,0x124a,0x559,0xb76,0x2334,0x12d1,0x1de1,0x14b2,0x2faa,0x1697,0x147a,0x5a1,0x2c30,0x1c02,0x1043,0x2ee1,0x2402,0x1cc8,0x2a16,0xff7,0x1364,0x1b9a,0x2a53,0x2f94,0x294c,0x1ee5,0x1a87,0x2141,0xd66,0x953,0x28a3,0x2f30,0x2477,0x18e3,0x1035,0x1fc1,0x1d68,0x2fb3,0x138c,0x2487,0x1bf8,0xd96,0x1018,0x748,0x244e,0x15bd,0x175e,0x2be,0x23d,0x1da,0x176d,0xc17,0x24be,0x2ebb,0x7d8,0x100a,0x759,0x1db4,0x2259,0x23f4,0x2d59,0x2847,0xbf5,0x1cfe,0xa20,0x258,0x1180,0x279c,0x54,0x2abf,0xc5c,0x9f9,0x3d5,0x2ce4,0x165f,0x23d9,0x27b9,0x6f9,0x281a,0x169e,0x627,0x156d,0x1ff8,0x211,0x2e34,0x1724,0x2c2e,0x2790,0x2dd5,0x2bf2,0xdbc,0x2884,0x20a9,0x2390,0x1e1a,0x1b6a,0x5f7,0xab7,0x1333,0x16ab,0x28dd,0x20,0x30f,0x24b6,0x5c2,0x1ce4,0x1400,0x2669,0x60,0x156c,0xe20,0x26d4,0x26ab,0x1ebb,0x223d,0x5b4,0x2025,0x1e1c,0xaae,0x2e08,0x6cd,0x1677,0x13d9,0x17b5,0x1046,0x1d8c,0x14eb,0x18d8,0x1ce5,0x2478,0x16ae,0xb79,0x23d4,0x684,0x156b,0x567,0x1a,0x29ce,0x83a,0x19e8,0x58e,0x294a,0x1136,0x2319,0x2fba,0x1a29,0x1d,0x1879,0x291b,0x19f6,0x2c2f,0x21c9,0x19bb,0xbbc,0x26f9,0xc22,0x708,0x11a1,0x18d3,0x7f8,0x28f8,0x2427,0x1deb,0xaed,0x26aa,0x2482,0x203b,0x2f05,0x2b82,0x192f,0x2df4,0x8dc,0x2877,0xd5e,0x240e,0x775,0x2dae,0x1d3e,0x20ba,0x215b,0x22d1,0xeba,0xf50,0xaa8,0x184a,0x1f67,0x2e04,0xc6e,0x6dd,0x1a09,0x27f,0x494,0x1426,0xae3,0xe15,0x65f,0x13c4,0x105,0x872,0x2667,0x1ff6,0xd9f,0x2ca1,0x2f39,0x2657,0x23fd,0x2405,0xb73,0x2294,0x1f1e,0x2eba,0x110a,0x2cae,0x141f,0x22cd,0x25d6,0x11c1,0x1c,0x2d8e,0x161a,0x1aa8,0x229e,0x1bf9,0x7cf,0x106d,0x2c40,0xd93,0x255e,0x28c2,0xc1a,0x2f17,0x7ca,0x2f63,0xbf};
+const sign16 iroots[]= {0x2ac8,0x452,0x297c,0x666,0xb4c,0x2b8,0x1a74,0xfd,0x1a47,0x1d08,0x2959,0x2c36,0x2db4,0x56c,0x254e,0x1125,0x2f3d,0x13bc,0x172c,0x2c6b,0x32a,0x1745,0x18bd,0x8f1,0x1633,0x2dfa,0xfdd,0x23e3,0x241b,0x13a5,0x578,0x17a0,0xa9,0x104b,0x1335,0x24e4,0x28de,0x5a7,0x368,0x2d70,0x13cd,0x2f9,0xff5,0x1e88,0x9c5,0x2ff7,0x900,0xdeb,0x1434,0x15fe,0x156a,0x24d3,0x28ed,0x2c4f,0x688,0xaef,0x2353,0x1045,0x2bcf,0x23a4,0x270,0x4c5,0x21fe,0xe5b,0xfbb,0x1f79,0x6e4,0xe68,0x2078,0x1160,0x1387,0x1e98,0x22f5,0x13e,0x283a,0x123f,0x149c,0x2eca,0xb14,0xf37,0xdde,0xbe7,0x386,0x1abe,0xa4a,0x49,0x14b5,0x2f36,0x8e5,0x1f1,0x2a57,0x1789,0x2f01,0x91f,0xaac,0x266c,0x2b65,0x2f4b,0xa30,0x2a17,0x265,0x253a,0xfb3,0x2142,0x20be,0x25c2,0x121c,0x2d97,0x2131,0x1e19,0x1a11,0x514,0x22c3,0x66,0xdcf,0x1540,0x1d41,0xf02,0x815,0x5a,0x18e8,0x1159,0x103a,0x2d23,0x2a10,0x2d61,0x1327,0x403,0x25c9,0x7b3,0x1f0c,0x1a98,0x2f21,0x1fb,0x2157,0x99e,0x1501,0x640,0x1e,0x1d4f,0x2716,0xb66,0x46a,0x2fdf,0x1c69,0xf34,0xb16,0x1ac5,0x1e08,0xc9b,0x218a,0x103d,0x2a09,0x4f0,0x21b2,0x750,0x2f33,0x9f7,0x2517,0x236b,0x15cb,0x152e,0x1a33,0x97e,0x24ce,0x2db5,0xac2,0x1583,0x1f99,0x1922,0x2513,0xc4f,0x615,0x1298,0x245a,0x2f97,0x2019,0x2c93,0x1fbd,0x291a,0x8ea,0x1ed4,0xb61,0x1c09,0x230b,0x2056,0x1ccf,0x1c72,0x27d9,0x21e4,0x2d0a,0x1f5b,0xe8,0x2c3d,0x2055,0x72f,0x222,0x222d,0x11be,0x1e90,0x11cf,0x20c5,0x5b7,0x391,0x1ebd,0x238,0x73e,0x653,0x17c2,0x2ef3,0x2fb,0x27c2,0x2ecf,0x847,0x2042,0x296d,0x268d,0x23f8,0x7e0,0x1e2e,0x2bf7,0x1ab7,0x89a,0xad,0x21e3,0x261,0x2f26,0x1ede,0xc4c,0x299a,0xfc8,0xa92,0xffd,0x1cbf,0x14a4,0x2d01,0x2a2e,0x1aaf,0x1967,0x1f03,0xec5,0x25c,0x3a5,0xdd3,0x2c47,0x8dd,0x2945,0x18ac,0x197,0x2f31,0x4c9,0x14ac,0x2be2,0x166,0x43a,0xa94,0x1b53,0x293c,0x212d,0x6fd,0x521,0x109,0x185,0x2735,0x151c,0x123a,0x5be,0x2c02,0x2b0f,0x1e7b,0x1846,0x297f,0x2ffd,0x18e5,0xf2b,0xf9a,0x1f6a,0x299f,0xb48,0x1b9d,0x2b8f,0x1eb,0x12f0,0x1649,0x893,0x83d,0x2942,0x757,0xbc5,0x1db9,0x23a9,0x2115,0x1b49,0x1f77,0x2f18,0x2dfe,0xc29,0x1f69,0x287e,0x1b13,0x9ff,0x2f06,0x515,0x1bb7,0x24a9,0x17f6,0x130d,0x2dd1,0x4c1,0x1675,0x1d86,0x1d9d,0x24f8,0x55,0x1382,0x1b5,0x2061,0x1c82,0x2ebd,0x4b,0x2c68,0x780,0x24,0xff8,0x880,0x2a7b,0x54c,0x971,0x88d,0x1594,0x2802,0x1ebe,0x120e,0xcb6,0x12d7,0x15dd,0xc0a,0x2c54,0x208,0x1bfa,0x2570,0x158f,0x2c82,0xdb3,0x10d6,0x2254,0x1d8,0x26b0,0x2a1b,0xcec,0x2572,0x211d,0x1c51,0x148f,0x616,0x185f,0x1a80,0x1650,0x538,0x25e8,0xf5d,0x1072,0x34f,0x2d04,0x2a3,0xb64,0x2c9e,0x1f74,0x3a6,0x139a,0x2292,0x555,0x96a,0x244,0x60b,0x8d3,0x1de6,0x831,0x2a75,0x4d7,0x2616,0x1485,0xf16,0x264a,0x2bb,0x609,0x19d,0x21da,0x6d7,0x234f,0x2cc4,0xaf9,0x20c2,0xcdd,0x2f1,0x1dfd,0x1c7,0x247b,0xec9,0x1978,0x770,0x72b,0x1ca3,0xe43,0x1820,0xdf9,0x690,0x926,0x3cc,0x2f20,0xa7c,0x121,0x2f02,0xee6,0x2ae2,0xa85,0xe29,0xd2b,0x1326,0x2e3d,0x1553,0x2ff5,0x133,0x2d81,0x143d,0x19fc,0x174a,0x19b9,0x2a40,0x22ab,0x1d27,0x8cf,0x1730,0x1386,0x491,0x212b,0x2954,0xf53,0xbfd,0x113a,0x144f,0x21f8,0x1b0a,0x385,0x2ce6,0xf63,0x1a64,0x48f,0x2059,0x1e4b,0x1d12,0x1f7f,0x2255,0x24f2,0x16e5,0x1242,0xa29,0x1a6,0xdd5,0x7e9,0x2eac,0x2e17,0x8f7,0x9ed,0x1de0,0x1588,0x2935,0x1c3e,0x2534,0xaf2,0x2002,0x7b4,0x2bf,0x1d25,0x2273,0x1240,0x176e,0x29b1,0x217c,0x1f5d,0xa7d,0x6e8,0x1f55,0x104e,0xb07,0x241e,0xc14,0x618,0x1fad,0x2cac,0x93d,0x1e4f,0x2907,0x281,0x1bf3,0x588,0x277d,0x1e6b,0x9df,0x629,0x1f46,0x19a7,0x3c8,0x1804,0x1981,0x2536,0x19,0x6c,0x1092,0x1980,0x13ae,0xfe4,0x2f42,0x9e,0x2837,0xea,0x23e7,0x73f,0xaa3,0x226e,0x3c1,0x1f94,0x2832,0x1408,0xd63,0x1559,0x19e7,0x273,0x2fe5,0x1e40,0xa2b,0xd34,0x1be2,0x353,0x1ef7,0x147,0x10e3,0xd6d,0x248e,0xbfc,0xc04,0x9aa,0xc8,0x360,0x2262,0x100b,0x99a,0x278f,0x2efc,0x1c3d,0x29a2,0x21ec,0x251e,0x1bdb,0x2b6d,0x2d82,0x15f8,0x2924,0x2393,0x1fd,0x109a,0x17b7,0x2559,0x20b1,0x2147,0xd30,0xea6,0xf47,0x12c3,0x253,0x288c,0xbf3,0x22a3,0x78a,0x2725,0x20d,0x16d2,0x47f,0xfc,0xfc6,0xb7f,0x957,0x2514,0x1216,0xbda,0x709,0x2809,0x172e,0x1e60,0x28f9,0x23df,0x908,0x2445,0x1646,0xe38,0x3d2,0x160b,0x6e6,0x1788,0x2fe4,0x15d8,0x47,0xce8,0x1ecb,0x6b7,0x2a73,0x1619,0x27c7,0x633,0x2fe7,0x2a9a,0x1a96,0x297d,0xc2d,0x2488,0x1953,0xb89,0x131c,0x1729,0x1b16,0x1275,0x1fbb,0x184c,0x1c28,0x198a,0x2934,0x1f9,0x2553,0x11e5,0xfdc,0x2a4d,0xdc4,0x1146,0x956,0x92d,0x21e1,0x1a95,0x2fa1,0x998,0x1c01,0x131d,0x2a3f,0xb4b,0x2cf2,0x2fe1,0x724,0x1956,0x1cce,0x254a,0x2a0a,0x1497,0x11e7,0xc71,0xf58,0x77d,0x2245,0x40f,0x22c,0x871,0x3d3,0x18dd,0x1cd,0x2df0,0x1009,0x1a94,0x29da,0x1963,0x7e7,0x2908,0x848,0xc28,0x19a2,0x31d,0x2c2c,0x2608,0x23a5,0x542,0x2fad,0x865,0x1e81,0x2da9,0x25e1,0x1303,0x240c,0x7ba,0x2a8,0xc0d,0xda8,0x124d,0x28a8,0x1ff7,0x2829,0x146,0xb43,0x23ea,0x1894,0x2e27,0x2dc4,0x2d43,0x18a3,0x1a44,0xbb3,0x28b9,0x1fe9,0x226b,0x1409,0xb7a,0x1c75,0x4e,0x1299,0x1040,0x1fcc,0x171e,0xb8a,0xd1,0x75e,0x26ae,0x229b,0xec0,0x157a,0x111c,0x6b5,0x6d,0x5ae,0x1467,0x1c9d,0x200a,0x5eb,0x1339,0xbff,0x120,0x1fbe,0x13ff,0x3d1,0x2a60,0x1b87,0x196a,0x57,0x1b4f,0x1220,0x1d30,0xccd,0x248b,0x2aa8,0x1db7,0x18ae,0x10aa,0x1425,0x2f2c,0x1187,0x3a1,0x26b8,0x2466,0x14e9,0x1518,0x2b1f,0x1ae6,0x238e,0x1a78,0x1819,0x2284,0x1475,0xaf,0x2f4,0x13fc,0x227d,0x29c0,0xf3a,0x187a,0x5e4,0x1950,0x2a25,0x29e1,0xddd,0x295d,0x1351,0x304,0x2bc0,0xd2,0xd25,0x2195,0x1fc9,0x1ee6,0x2f13,0x6db,0xa6a,0x1d99,0x2b60,0x1234,0x283c,0x2ac2,0x11a9,0x639,0x2290,0x2bda,0x32f,0x2a5f,0x15c0,0x139c,0x7e8,0x88a,0x43f,0x2762,0x1271,0x119d,0x1fed,0x1b4d,0x692,0x1d2b,0x1feb,0x1380,0x2628,0x2a93,0x2226,0xe71,0x2d1b,0x20ab,0x17ff,0x1e27,0x2fb1,0xe65,0x17c8,0x1fa6,0x43b,0x548,0x2256,0x9a5,0x71a,0x26ea,0x2d38,0x1b40,0x1b79,0x658,0x15a5,0x224f,0x248,0xeee,0x2f37,0x1c30,0x15ec,0x1ca7,0x255f,0x2801,0x18f7,0x1727,0xf88,0x2b1,0x2c45,0x164b,0x289f,0x14dd,0x2649,0x27a3,0x9f0,0x21ca,0x1f5,0x1dd6,0xbc3,0x71f,0x133e,0x13bb,0x2afe,0xc35,0x4bb,0x2d31,0x10a7,0x2a04,0x180e,0x2613,0x330,0xe76,0x19fd,0xfe9,0x935,0x79,0x1b01,0x73c,0x2ac6,0x21ce,0x1911,0x761,0x1084,0x1983,0xc3,0x15eb,0xe0a,0xdd,0x1cb1,0xb21,0x2a51,0x217f,0xb1,0x1328,0x9ca,0x1d96,0x1a0b,0xe1b,0x1c4b,0x3b,0x4d6,0x2344,0x199e,0x28af,0x1624,0x4ae,0x8b2,0x2991,0x1fb7,0x41,0x2780,0x1d8b,0xa7f,0x110,0x2350,0x18aa,0x2b2f,0x1805,0x1ff,0xf0,0x2a74,0xe42,0xd97,0x85b,0x14bc,0x2901,0xfd8,0x1ab3,0x1cef,0xfbd,0x2b07,0x174f,0x69b,0x10c3,0x1491,0xde3,0x28ca,0x252e,0x1849,0x1ec2,0x1f1b,0x2853,0x12ab,0x2674,0x238c,0x350,0x2ca,0xa7,0x4bd,0xcc3,0x90c,0x892,0x276,0x1e55,0x196d,0x1194,0x1bef,0x66a,0x1da1,0x260f,0x1c15,0x49f,0x120b,0x2671,0x1237,0x2e0d,0x2791,0x17d8,0x1e0a,0x2a99,0x14cf,0xfb1,0x15b4,0x1462,0x2fbb,0xeff,0x16b,0x2d6a,0x9ef,0x5e3,0x11c0,0x2e76,0x1623,0x2db8,0x1c88,0x740,0x11e1,0x12a3,0x977,0x1110,0x2163,0x2dee,0x47b,0x2aa5,0x2a22,0x1231,0x16e7,0x1626,0x12e0,0x1d28,0xe96,0xb62,0x21d0,0xf09,0xb30,0xcb8,0x2981,0x2648,0x155d,0x27ee,0xb34,0x169,0x1574,0x1fe6,0x25f4,0x151d,0x1801,0x1f13,0x1308,0x2929,0x6eb,0x25e,0x2cca,0x1e3e,0x248f};
+const sign16 inv= 0xeab;
+const sign16 invpr= 0x2c2a;
+
+#define DEGREE (1<<RLWE_LGN)
+#define WL 32
+
+#define round(a,b) (((a)+((b)/2))/(b))
+
+/* constant time absolute vaue */
+static sign32 nabs(sign32 x)
+{
+	sign32 mask=(x>>31);
+	return (x+mask)^mask;
+}
+
+/* Montgomery stuff */
+
+static sign32 redc(unsign64 T)
+{
+	unsign32 m=(unsign32)T*(unsign32)RLWE_ND;
+	return ((unsign64)m*RLWE_PRIME+T)>>WL;
+}
+
+static sign32 nres(unsign32 x)
+{
+	return redc((unsign64)x*RLWE_R2MODP);
+}
+
+static sign32 modmul(unsign32 a,unsign32 b)
+{
+	return redc((unsign64)a*b);
+}
+
+/* NTT code */
+/* Cooley-Tukey NTT */
+
+static void ntt(sign32 *x)
+{
+	int m,i,j,k,t=DEGREE/2;
+	sign32 S,U,V,W,q=RLWE_PRIME;
+
+/* Convert to Montgomery form */
+	for (j=0;j<DEGREE;j++)
+		x[j]=nres(x[j]);
+
+	m=1;
+	while (m<DEGREE)
+	{
+		k=0;
+		for (i=0;i<m;i++)
+		{
+			S=roots[m+i];
+			for (j=k;j<k+t;j++)
+			{
+				U=x[j];   
+				V=modmul(x[j+t],S);
+				x[j]=U+V;
+				x[j+t]=U+2*q-V;
+			}
+			k+=2*t;
+		}
+		t/=2;
+		m*=2;
+	}
+}
+
+/* Gentleman-Sande INTT */
+
+static void intt(sign32 *x)
+{
+	int m,i,j,k,t=1;
+	sign32 S,U,V,W,q=RLWE_PRIME;
+
+	m=DEGREE/2;
+	while (m>1)
+	{
+		k=0;
+		for (i=0;i<m;i++)
+		{
+			S=iroots[m+i];
+			for (j=k;j<k+t;j++)
+			{	
+				U=x[j]; 
+				V=x[j+t];
+				x[j]=U+V;	
+				W=U+DEGREE*q-V; 
+				x[j+t]=modmul(W,S); 
+			}
+			k+=2*t;
+		}
+		t*=2;
+		m/=2;
+	}
+
+/* Last iteration merged with n^-1 */
+
+	t=DEGREE/2;
+	for (j=0;j<t;j++)
+	{
+		U=x[j];
+		V=x[j+t];
+		W=U+DEGREE*q-V; 
+		x[j+t]=modmul(W,(sign32)invpr); 
+		x[j]=modmul(U+V,(sign32)inv);
+	}
+/* convert back from Montgomery to "normal" form */
+	for (j=0;j<DEGREE;j++)
+	{
+		x[j]=redc(x[j]);  
+		x[j]-=q;
+		x[j]+=(x[j]>>(WL-1))&q;
+	} 
+}
+
+/* See https://eprint.iacr.org/2016/1157.pdf */ 
+
+static void NHSEncode(byte *key,sign32 *poly)
+{
+	int i,j,b,k,kj,q2;
+
+	q2=RLWE_PRIME/2;
+	for (i=j=0;i<256;)
+	{
+		kj=key[j++];
+		for (k=0;k<8;k++)
+		{
+			b=kj&1;
+			poly[i]=b*q2;
+			poly[i+256]=b*q2;
+			poly[i+512]=b*q2;
+			poly[i+768]=b*q2;
+			kj>>=1;
+			i++;
+		}
+	}		
+}
+
+static void NHSDecode(sign32 *poly,byte *key)
+{
+	int i,j,k;
+	sign32 b,t,q2;
+	q2=RLWE_PRIME/2;
+	for (i=0;i<32;i++)
+		key[i]=0;
+
+	for (i=j=0;i<256;)
+	{
+		for (k=0;k<8;k++)
+		{
+			t=nabs(poly[i]-q2)+nabs(poly[i+256]-q2)+nabs(poly[i+512]-q2)+nabs(poly[i+768]-q2);
+
+			b=t-RLWE_PRIME;
+			b=(b>>31)&1;
+			key[j]=(key[j]>>1)+(b<<7);
+			i++;
+		}
+		j++;
+	}
+}
+
+/* convert 32-byte seed to random polynomial */
+
+static void parse(byte *seed,sign32 *poly)
+{
+	int i,j;
+	sign32 n;
+	byte hash[4*DEGREE];
+	sha3 sh;
+
+	SHA3_init(&sh,SHAKE128);
+	for (i=0;i<32;i++)
+		SHA3_process(&sh,seed[i]);
+	SHA3_shake(&sh,(char *)hash,4*DEGREE);
+
+	for (i=j=0;i<DEGREE;i++)
+	{
+
+		n=hash[j]&0x7f; n<<=8;
+		n+=hash[j+1]; n<<=8;
+		n+=hash[j+2]; n<<=8;
+		n+=hash[j+3]; j+=4;
+		poly[i]=nres(n);
+		//poly[i]=modmul(n,RLWE_ONE); // reduce 31-bit random number mod q
+	}
+} 
+
+/* Compress 14 bits polynomial coefficients into byte array */
+/* 7 bytes is 3x14 */
+
+static void NHSpack(sign32 *poly,byte *array)
+{
+	int i,j;
+	sign32 a,b,c,d;
+
+	for (i=j=0;i<DEGREE; )
+	{
+		a=poly[i++]; b=poly[i++]; c=poly[i++]; d=poly[i++];
+		array[j++]=(byte)(a&0xff);
+		array[j++]=(byte)(((a>>8)|(b<<6))&0xff);
+		array[j++]=(byte)((b>>2)&0xff);
+		array[j++]=(byte)(((b>>10)|(c<<4))&0xff);
+		array[j++]=(byte)((c>>4)&0xff);
+		array[j++]=(byte)(((c>>12)|(d<<2))&0xff);
+		array[j++]=(byte)(d>>6);
+	}
+}
+
+static void NHSunpack(byte *array,sign32 *poly)
+{
+	int i,j;
+	sign32 a,b,c,d,e,f,g;
+
+	for (i=j=0;i<DEGREE; )
+	{
+		a=((sign32)array[j++])&0xff; b=((sign32)array[j++])&0xff; c=((sign32)array[j++])&0xff; d=((sign32)array[j++])&0xff; e=((sign32)array[j++])&0xff; f=((sign32)array[j++])&0xff; g=((sign32)array[j++])&0xff;
+		poly[i++]=a|((b&0x3f)<<8);
+		poly[i++]=(b>>6)|(c<<2)|((d&0xf)<<10);
+		poly[i++]=(d>>4)|(e<<4)|((f&3)<<12);
+		poly[i++]=(f>>2)|(g<<6);
+	}
+}
+
+
+
+/* See https://eprint.iacr.org/2016/1157.pdf */ 
+
+static void NHSCompress(sign32 *poly,byte *array)
+{
+	int i,j,k,b;
+	unsign32 col=0;
+
+	for (i=j=0;i<DEGREE;)
+	{
+		for (k=0;k<8;k++)
+		{
+			b=round((poly[i]*8),RLWE_PRIME)&7; 
+			col=(col<<3)+b;
+			i++;
+		}
+		array[j]=col&0xff;
+		array[j+1]=(col>>8)&0xff;
+		array[j+2]=(col>>16)&0xff;
+		j+=3; col=0;
+	}
+}
+
+static void NHSDecompress(byte *array,sign32 *poly)
+{
+	int i,j,k,b;
+	unsign32 col=0;
+
+	for (i=j=0;i<DEGREE;)
+	{
+		col=array[j+2];
+		col=(col<<8)+array[j+1];
+		col=(col<<8)+array[j];
+		j+=3;
+		for (k=0;k<8;k++)
+		{
+			b=(col&0xe00000)>>21; col<<=3;
+			poly[i]=round((b*RLWE_PRIME),8);
+			i++;
+		}
+	}
+}
+
+/* generate centered binomial distribution */ 
+
+static void NHSError(csprng *RNG,sign32 *poly)
+{
+	int i,j;
+	sign32 n1,n2,r;
+	for (i=0;i<DEGREE;i++)
+	{
+		n1=RAND_byte(RNG)+(RAND_byte(RNG)<<8);
+		n2=RAND_byte(RNG)+(RAND_byte(RNG)<<8);
+		r=0;
+		for (j=0;j<16;j++)
+		{
+			r+=(n1&1)-(n2&1);
+			n1>>=1; n2>>=1;
+		}
+		poly[i]=(r+RLWE_PRIME);
+	}
+}
+
+static void redc_it(sign32 *p)
+{
+	int i;
+	for (i=0;i<DEGREE;i++)
+		p[i]=redc(p[i]);
+}
+
+static void nres_it(sign32 *p)
+{
+	int i;
+	for (i=0;i<DEGREE;i++)
+		p[i]=nres(p[i]);
+}
+
+static void poly_mul(sign32 *p1,sign32 *p2,sign32 *p3)
+{
+	int i;
+	for (i=0;i<DEGREE;i++)
+		p1[i]=modmul(p2[i],p3[i]);
+}
+
+static void poly_add(sign32 *p1,sign32 *p2,sign32 *p3)
+{
+	int i;
+	for (i=0;i<DEGREE;i++)
+		p1[i]=(p2[i]+p3[i]);
+}
+
+static void poly_sub(sign32 *p1,sign32 *p2,sign32 *p3)
+{
+	int i;
+	for (i=0;i<DEGREE;i++)
+		p1[i]=(p2[i]+RLWE_PRIME-p3[i]);
+}
+
+/* reduces inputs < 2q */
+static void poly_soft_reduce(sign32 *poly)
+{
+	int i;
+	sign32 e;
+	for (i=0;i<DEGREE;i++)
+	{
+		e=poly[i]-RLWE_PRIME;
+		poly[i]=e+((e>>(WL-1))&RLWE_PRIME);
+	}
+}
+
+/* fully reduces modulo q */
+static void poly_hard_reduce(sign32 *poly)
+{
+	int i;
+	sign32 e;
+	for (i=0;i<DEGREE;i++)
+	{
+		e=modmul(poly[i],RLWE_ONE);
+		e=e-RLWE_PRIME;
+		poly[i]=e+((e>>(WL-1))&RLWE_PRIME);
+	}
+}
+
+/* API files */
+
+void amcl::NHS_SERVER_1(csprng *RNG,octet *SB,octet *S)
+{
+	int i;
+	byte seed[32],array[1792];
+	sign32 s[DEGREE],e[DEGREE],b[DEGREE];
+
+	for (i=0;i<32;i++)
+		seed[i]=RAND_byte(RNG);
+
+	parse(seed,b);
+	
+	NHSError(RNG,e);
+	NHSError(RNG,s);
+
+	ntt(s);
+	ntt(e);
+	poly_mul(b,b,s);
+	poly_add(b,b,e);
+	poly_hard_reduce(b);
+
+	redc_it(b);
+	NHSpack(b,array);
+
+	OCT_empty(SB);
+	OCT_jbytes(SB,(char *)seed,32);
+	OCT_jbytes(SB,(char *)array,1792);
+
+	poly_hard_reduce(s);
+
+	NHSpack(s,array);
+	OCT_empty(S);
+	OCT_jbytes(S,(char *)array,1792);
+
+}
+
+void amcl::NHS_CLIENT(csprng *RNG,octet *SB,octet *UC,octet *KEY)
+{
+	int i;
+	sha3 sh;
+	byte seed[32],array[1792],key[32],cc[384];
+	sign32 sd[DEGREE],ed[DEGREE],u[DEGREE],k[DEGREE],c[DEGREE];
+	NHSError(RNG,sd);
+	NHSError(RNG,ed);
+
+	ntt(sd);
+	ntt(ed);
+
+	for (i=0;i<32;i++)
+		seed[i]=SB->val[i];
+
+	for (i=0;i<1792;i++)
+		array[i]=SB->val[i+32];
+
+	parse(seed,u);
+
+	poly_mul(u,u,sd);
+	poly_add(u,u,ed);
+	poly_hard_reduce(u);
+
+	for (i=0;i<32;i++)
+		key[i]=RAND_byte(RNG);
+
+	SHA3_init(&sh,SHA3_HASH256);
+	for (i=0;i<32;i++)
+		SHA3_process(&sh,key[i]);
+	SHA3_hash(&sh,(char *)key);
+
+	NHSEncode(key,k);
+
+	NHSunpack(array,c);
+	nres_it(c);
+
+	poly_mul(c,c,sd);
+	intt(c);
+	NHSError(RNG,ed);
+	poly_add(c,c,ed);
+	poly_add(c,c,k);
+
+	NHSCompress(c,cc);
+
+	SHA3_init(&sh,SHA3_HASH256);
+	for (i=0;i<32;i++)
+		SHA3_process(&sh,key[i]);
+	SHA3_hash(&sh,(char *)key);
+
+	OCT_empty(KEY);
+	OCT_jbytes(KEY,(char *)key,32);
+
+	redc_it(u);
+	NHSpack(u,array);
+
+	OCT_empty(UC);
+	OCT_jbytes(UC,(char *)array,1792);
+	OCT_jbytes(UC,(char *)cc,384);
+}
+
+void amcl::NHS_SERVER_2(octet *S,octet *UC,octet *KEY)
+{
+	int i;
+	sha3 sh;
+	sign32 c[DEGREE],s[DEGREE],k[DEGREE];
+	byte array[1792],key[32],cc[384];
+
+	for (i=0;i<1792;i++)
+		array[i]=UC->val[i];
+
+	NHSunpack(array,k);
+	nres_it(k);
+
+	for (i=0;i<384;i++)
+		cc[i]=UC->val[i+1792];
+
+	NHSDecompress(cc,c);
+
+	for (i=0;i<1792;i++)
+		array[i]=S->val[i];
+
+	NHSunpack(array,s);
+
+	poly_mul(k,k,s);
+	intt(k);
+	poly_sub(k,c,k);
+	poly_soft_reduce(k);
+
+	NHSDecode(k,key);
+
+	SHA3_init(&sh,SHA3_HASH256);
+	for (i=0;i<32;i++)
+		SHA3_process(&sh,key[i]);
+	SHA3_hash(&sh,(char *)key);
+
+	OCT_empty(KEY);
+	OCT_jbytes(KEY,(char *)key,32);
+}
+
diff --git a/version3/cpp/newhope.h b/version3/cpp/newhope.h
new file mode 100644
index 0000000..ff4157d
--- /dev/null
+++ b/version3/cpp/newhope.h
@@ -0,0 +1,54 @@
+/*
+	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.
+*/
+
+/* NewHope Simple API */
+
+#ifndef NHS_H
+#define NHS_H
+
+#include "amcl.h"
+
+namespace amcl {
+/**	@brief NHS server first pass
+ *
+	@param RNG Random Number Generator handle
+	@param SB seed and polynomial B concatenated - output
+	@param S server secret - output
+	
+ */
+extern void NHS_SERVER_1(csprng *RNG,octet *SB,octet *S);
+/**	@brief NHS client pass
+ *
+	@param RNG Random Number Generator handle
+	@param SB seed and polynomial B concatenated - input
+	@param UC polynomial U and compressed polynomial c - output
+	@param KEY client key
+ */
+extern void NHS_CLIENT(csprng *RNG,octet *SB,octet *UC,octet *KEY);
+/**	@brief NHS server second pass
+ *
+	@param S server secret - input
+	@param UC polynomial U and compressed polynomial c - input
+	@param KEY server key
+ */
+extern void NHS_SERVER_2(octet *S,octet *UC,octet *KEY);
+
+}
+
+#endif
\ No newline at end of file
diff --git a/version3/cpp/oct.cpp b/version3/cpp/oct.cpp
new file mode 100644
index 0000000..6a47b8d
--- /dev/null
+++ b/version3/cpp/oct.cpp
@@ -0,0 +1,431 @@
+/*
+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.
+*/
+
+/*** Basic Octet string maintainance routines  ***/
+/* SU=m, m is Stack Usage */
+
+#include <string.h>
+#include "amcl.h"
+
+using namespace amcl;
+
+/* Output an octet string (Debug Only) */
+
+/* SU= 16 */
+/* output octet */
+void amcl::OCT_output(octet *w)
+{
+    int i;
+    unsigned char ch;
+    for (i=0; i<w->len; i++)
+    {
+        ch=w->val[i];
+        printf("%02x",ch);
+    }
+    printf("\n");
+}
+
+/* SU= 16 */
+void amcl::OCT_output_string(octet *w)
+{
+    int i;
+    unsigned char ch;
+    for (i=0; i<w->len; i++)
+    {
+        ch=w->val[i];
+        printf("%c",ch);
+    }
+    /*  printf("\n"); */
+}
+
+/* Convert C string to octet format - truncates if no room  */
+void amcl::OCT_jstring(octet *y,char *s)
+{
+    int i,j;
+    i=y->len;
+    j=0;
+    while (s[j]!=0 && i<y->max)
+    {
+        y->val[i]=s[j];
+        y->len++;
+        i++;
+        j++;
+    }
+}
+
+/* compare 2 octet strings.
+ * If x==y return TRUE, else return FALSE */
+/* SU= 8 */
+int amcl::OCT_comp(octet *x,octet *y)
+{
+    int i;
+    if (x->len>y->len) return 0;
+    if (x->len<y->len) return 0;
+    for (i=0; i<x->len; i++)
+    {
+        if (x->val[i]!=y->val[i]) return 0;
+    }
+    return 1;
+}
+
+/* check are first n bytes the same (in constant time) */
+
+int amcl::OCT_ncomp(octet *x,octet *y,int n)
+{
+    int i,res=0;
+    if (n>y->len || n>x->len) return 0;
+    for (i=0; i<n; i++)
+    {
+        res|=(int)(x->val[i]^y->val[i]);
+    }
+    if (res==0) return 1;
+	return 0;
+}
+
+/* Shift octet to the left by n bytes. Leftmost bytes disappear  */
+void amcl::OCT_shl(octet *x,int n)
+{
+    int i;
+    if (n>=x->len)
+    {
+        x->len=0;
+        return;
+    }
+    x->len-=n;
+    for (i=0; i<x->len; i++)
+        x->val[i]=x->val[i+n];
+}
+
+/* Append binary string to octet - truncates if no room */
+/* SU= 12 */
+void amcl::OCT_jbytes(octet *y,char *b,int len)
+{
+    int i,j;
+    i=y->len;
+    for (j=0; j<len && i<y->max; j++)
+    {
+        y->val[i]=b[j];
+        y->len++;
+        i++;
+    }
+}
+
+/* Concatenates two octet strings */
+/* SU= 8 */
+void amcl::OCT_joctet(octet *y,octet *x)
+{
+    /* y=y || x */
+    int i,j;
+    if (x==NULL) return;
+
+    for (i=0; i<x->len; i++)
+    {
+        j=y->len+i;
+        if (j>=y->max)
+        {
+            y->len=y->max;
+            return;
+        }
+        y->val[j]=x->val[i];
+    }
+    y->len+=x->len;
+}
+
+/* Append byte to octet rep times */
+/* SU= 8 */
+void amcl::OCT_jbyte(octet *y,int ch,int rep)
+{
+    int i,j;
+    i=y->len;
+    for (j=0; j<rep && i<y->max; j++)
+    {
+        y->val[i]=ch;
+        y->len++;
+        i++;
+    }
+}
+
+/* XOR common bytes of x with y */
+/* SU= 8 */
+void amcl::OCT_xor(octet *y,octet *x)
+{
+    /* xor first x->len bytes of y */
+
+    int i;
+    for (i=0; i<x->len && i<y->len; i++)
+    {
+        y->val[i]^=x->val[i];
+    }
+}
+
+/* clear an octet */
+void amcl::OCT_empty(octet *w)
+{
+    w->len=0;
+}
+
+/* Kill an octet string - Zeroise it for security */
+void amcl::OCT_clear(octet *w)
+{
+    int i;
+    for (i=0; i<w->max; i++) w->val[i]=0;
+    w->len=0;
+}
+
+/* appends int x of length len bytes to OCTET string */
+/* SU= 8 */
+void amcl::OCT_jint(octet *y,int x,int len)
+{
+    int i,n;
+    n=y->len+len;
+    if (n>y->max || len<=0) return;
+    for (i=y->len; i<n; i++) y->val[i]=0;
+    y->len=n;
+
+    i=y->len;
+    while (x>0 && i>0)
+    {
+        i--;
+        y->val[i]=x%256;
+        x/=256;
+    }
+}
+
+/* Pad an octet to a given length */
+/* SU= 8 */
+int amcl::OCT_pad(octet *w,int n)
+{
+    int i,d;
+    if (w->len>n || n>w->max) return 0;
+    if (n==w->len) return 1;
+    d=n-w->len;
+    for (i=n-1; i>=d; i--)
+        w->val[i]=w->val[i-d];
+    for (i=d-1; i>=0; i--)
+        w->val[i]=0;
+    w->len=n;
+    return 1;
+}
+
+
+/* Convert an octet string to base64 string */
+/* SU= 56 */
+void amcl::OCT_tobase64(char *b,octet *w)
+{
+    int i,j,k,rem,last;
+    int c,ch[4];
+    unsigned char ptr[3];
+    rem=w->len%3;
+    j=k=0;
+    last=4;
+    while (j<w->len)
+    {
+        for (i=0; i<3; i++)
+        {
+            if (j<w->len) ptr[i]=w->val[j++];
+            else
+            {
+                ptr[i]=0;
+                last--;
+            }
+        }
+        ch[0]=(ptr[0]>>2)&0x3f;
+        ch[1]=((ptr[0]<<4)|(ptr[1]>>4))&0x3f;
+        ch[2]=((ptr[1]<<2)|(ptr[2]>>6))&0x3f;
+        ch[3]=ptr[2]&0x3f;
+        for (i=0; i<last; i++)
+        {
+            c=ch[i];
+            if (c<26) c+=65;
+            if (c>=26 && c<52) c+=71;
+            if (c>=52 && c<62) c-=4;
+            if (c==62) c='+';
+            if (c==63) c='/';
+            b[k++]=c;
+        }
+    }
+    if (rem>0) for (i=rem; i<3; i++) b[k++]='=';
+    b[k]='\0';  /* dangerous! */
+}
+
+/* SU= 56 */
+void amcl::OCT_frombase64(octet *w,char *b)
+{
+    int i,j,k,pads,len=(int)strlen(b);
+    int c,ch[4],ptr[3];
+    /* int lead=1; */
+    j=k=0;
+    while (j<len && k<w->max)
+    {
+        pads=0;
+        for (i=0; i<4; i++)
+        {
+            c=80+b[j++];
+            if (c<=112) continue; /* ignore white space */
+            if (c>144 && c<171) c-=145;
+            if (c>176 && c<203) c-=151;
+            if (c>127 && c<138) c-=76;
+            if (c==123) c=62;
+            if (c==127) c=63;
+            if (c==141)
+            {
+                pads++;    /* ignore pads '=' */
+                continue;
+            }
+            ch[i]=c;
+        }
+        ptr[0]=(ch[0]<<2)|(ch[1]>>4);
+        ptr[1]=(ch[1]<<4)|(ch[2]>>2);
+        ptr[2]=(ch[2]<<6)|ch[3];
+        for (i=0; i<3-pads && k<w->max; i++)
+        {
+            /* don't put in leading zeros */
+            /* if (lead && ptr[i]==0) continue; */
+            w->val[k++]=ptr[i];
+            /* lead=0; */
+        }
+
+    }
+    w->len=k;
+}
+
+/* copy an octet string - truncates if no room */
+/* SU= 16 */
+void amcl::OCT_copy(octet *y,octet *x)
+{
+    int i;
+    OCT_clear(y);
+    y->len=x->len;
+    if (y->len>y->max) y->len=y->max;
+
+    for (i=0; i<y->len; i++)
+        y->val[i]=x->val[i];
+}
+
+/* XOR m with all of x */
+void amcl::OCT_xorbyte(octet *x,int m)
+{
+    int i;
+    for (i=0; i<x->len; i++) x->val[i]^=m;
+}
+
+/* truncates x to n bytes and places the rest in y (if y is not NULL) */
+/* SU= 8 */
+void amcl::OCT_chop(octet *x,octet *y,int n)
+{
+    int i;
+    if (n>=x->len)
+    {
+        if (y!=NULL) y->len=0;
+        return;
+    }
+    if (y!=NULL) y->len=x->len-n;
+    x->len=n;
+
+    if (y!=NULL)
+    {
+        for (i=0; i<y->len && i<y->max; i++) y->val[i]=x->val[i+n];
+    }
+}
+
+/* set x to len random bytes */
+void amcl::OCT_rand(octet *x,csprng *RNG,int len)
+{
+    int i;
+    if (len>x->max) len=x->max;
+    x->len=len;
+
+    for (i=0; i<len; i++) x->val[i]=RAND_byte(RNG);
+}
+
+/* Convert an octet to a hex string */
+void amcl::OCT_toHex(octet *src,char *dst)
+{
+    int i;
+    unsigned char ch;
+    for (i=0; i<src->len; i++)
+    {
+        ch=src->val[i];
+        sprintf(&dst[i*2],"%02x", ch);
+    }
+}
+
+static int char2int(char input)
+{
+    if(input >= '0' && input <= '9')
+        return input - '0';
+    if(input >= 'A' && input <= 'F')
+        return input - 'A' + 10;
+    if(input >= 'a' && input <= 'f')
+        return input - 'a' + 10;
+    return 0;
+}
+
+/* Convert from a hex string */
+void amcl::OCT_fromHex(octet *dst,char *src)
+{
+    int i=0;
+    int j=0;
+    OCT_clear(dst);
+
+    while(src[j]!=0)
+    {
+        dst->val[i++] = char2int(src[j])*16 + char2int(src[j+1]);
+        j += 2;
+    }
+    dst->len=i;
+}
+
+
+/* Convert an octet to a string */
+void amcl::OCT_toStr(octet *src,char *dst)
+{
+    int i;
+    unsigned char ch;
+    for (i=0; i<src->len; i++)
+    {
+        ch=src->val[i];
+        sprintf(&dst[i],"%c", ch);
+    }
+}
+
+/* Test program
+#include <stdio.h>
+#include "amcl.h"
+
+char test[]="abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
+
+int main()
+{
+	char gm[100],gn[100],t[100];
+    octet m={0,sizeof(gm),gm};
+    octet n={0,sizeof(gn),gn};
+
+	OCT_jbytes(&m,test,strlen(test));
+	OCT_output(&m);
+
+	OCT_tobase64(t,&m);
+	printf(t); printf("\n");
+
+	OCT_frombase64(&n,t);
+	OCT_output(&n);
+
+    return 0;
+}
+*/
diff --git a/version3/cpp/pair.cpp b/version3/cpp/pair.cpp
new file mode 100644
index 0000000..5a8ffe8
--- /dev/null
+++ b/version3/cpp/pair.cpp
@@ -0,0 +1,983 @@
+/*
+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.
+*/
+
+/* AMCL BN Curve pairing functions */
+
+//#define HAS_MAIN
+
+#include "pair_ZZZ.h"
+
+using namespace XXX;
+using namespace YYY;
+
+namespace ZZZ {
+	static void PAIR_line(FP12 *,ECP2 *,ECP2 *,FP *,FP *);
+	static void glv(BIG u[2],BIG);
+	static void gs(BIG u[4],BIG);
+}
+
+/* Line function */
+static void ZZZ::PAIR_line(FP12 *v,ECP2 *A,ECP2 *B,FP *Qx,FP *Qy)
+{
+	FP2 X1,Y1,T1,T2;
+	FP2 XX,YY,ZZ,YZ;
+    FP4 a,b,c;
+
+	if (A==B)
+    {
+        /* doubling */
+ 		FP2_copy(&XX,&(A->x));	//FP2 XX=new FP2(A.getx());  //X
+		FP2_copy(&YY,&(A->y));	//FP2 YY=new FP2(A.gety());  //Y
+		FP2_copy(&ZZ,&(A->z));	//FP2 ZZ=new FP2(A.getz());  //Z
+
+
+		FP2_copy(&YZ,&YY);		//FP2 YZ=new FP2(YY);        //Y 
+		FP2_mul(&YZ,&YZ,&ZZ);		//YZ.mul(ZZ);                //YZ
+		FP2_sqr(&XX,&XX);		//XX.sqr();	               //X^2
+		FP2_sqr(&YY,&YY);		//YY.sqr();	               //Y^2
+		FP2_sqr(&ZZ,&ZZ);		//ZZ.sqr();			       //Z^2
+			
+		FP2_imul(&YZ,&YZ,4);	//YZ.imul(4);
+		FP2_neg(&YZ,&YZ);		//YZ.neg(); 
+		FP2_norm(&YZ);			//YZ.norm();       //-4YZ
+
+		FP2_imul(&XX,&XX,6);					//6X^2
+		FP2_pmul(&XX,&XX,Qx);	               //6X^2.Xs
+
+		FP2_imul(&ZZ,&ZZ,3*CURVE_B_I);	//3Bz^2 
+
+		FP2_pmul(&YZ,&YZ,Qy);	//-4YZ.Ys
+
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+		FP2_div_ip2(&ZZ);		//6(b/i)z^2
+#endif
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+		FP2_mul_ip(&ZZ);
+		FP2_add(&ZZ,&ZZ,&ZZ);  // 6biz^2
+		FP2_mul_ip(&YZ);
+		FP2_norm(&YZ);	
+#endif
+		FP2_norm(&ZZ);			// 6bi.Z^2 
+
+		FP2_add(&YY,&YY,&YY);	// 2y^2
+		FP2_sub(&ZZ,&ZZ,&YY);	// 
+		FP2_norm(&ZZ);			// 6b.Z^2-2Y^2
+
+		FP4_from_FP2s(&a,&YZ,&ZZ); // -4YZ.Ys | 6b.Z^2-2Y^2 | 6X^2.Xs 
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+		FP4_from_FP2(&b,&XX);	
+		FP4_zero(&c);
+#endif
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+		FP4_zero(&b);
+		FP4_from_FP2H(&c,&XX);
+#endif
+
+		ECP2_dbl(A);				//A.dbl();
+    }
+    else
+    {
+        /* addition */
+
+		FP2_copy(&X1,&(A->x));		//FP2 X1=new FP2(A.getx());    // X1
+		FP2_copy(&Y1,&(A->y));		//FP2 Y1=new FP2(A.gety());    // Y1
+		FP2_copy(&T1,&(A->z));		//FP2 T1=new FP2(A.getz());    // Z1
+			
+		FP2_copy(&T2,&T1);		//FP2 T2=new FP2(A.getz());    // Z1
+
+		FP2_mul(&T1,&T1,&(B->y));	//T1.mul(B.gety());    // T1=Z1.Y2 
+		FP2_mul(&T2,&T2,&(B->x));	//T2.mul(B.getx());    // T2=Z1.X2
+
+		FP2_sub(&X1,&X1,&T2);		//X1.sub(T2); 
+		FP2_norm(&X1);				//X1.norm();  // X1=X1-Z1.X2
+		FP2_sub(&Y1,&Y1,&T1);		//Y1.sub(T1); 
+		FP2_norm(&Y1);				//Y1.norm();  // Y1=Y1-Z1.Y2
+
+		FP2_copy(&T1,&X1);			//T1.copy(X1);            // T1=X1-Z1.X2
+
+		FP2_pmul(&X1,&X1,Qy);		//X1.pmul(Qy);            // X1=(X1-Z1.X2).Ys
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+		FP2_mul_ip(&X1);
+		FP2_norm(&X1);
+#endif
+
+		FP2_mul(&T1,&T1,&(B->y));	//T1.mul(B.gety());       // T1=(X1-Z1.X2).Y2
+
+		FP2_copy(&T2,&Y1);			//T2.copy(Y1);            // T2=Y1-Z1.Y2
+		FP2_mul(&T2,&T2,&(B->x));	//T2.mul(B.getx());       // T2=(Y1-Z1.Y2).X2
+		FP2_sub(&T2,&T2,&T1);		//T2.sub(T1); 
+		FP2_norm(&T2);				//T2.norm();          // T2=(Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2
+		FP2_pmul(&Y1,&Y1,Qx);		//Y1.pmul(Qx);  
+		FP2_neg(&Y1,&Y1);			//Y1.neg(); 
+		FP2_norm(&Y1);				//Y1.norm(); // Y1=-(Y1-Z1.Y2).Xs
+
+		FP4_from_FP2s(&a,&X1,&T2);	// (X1-Z1.X2).Ys  |  (Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2  | - (Y1-Z1.Y2).Xs
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+		FP4_from_FP2(&b,&Y1);		//b=new FP4(Y1);
+		FP4_zero(&c);
+#endif
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+		FP4_zero(&b);
+		FP4_from_FP2H(&c,&Y1);		//b=new FP4(Y1);
+#endif
+		ECP2_add(A,B);			//A.add(B);
+    }
+
+    FP12_from_FP4s(v,&a,&b,&c);
+//	FP12_norm(v);
+}
+
+/* Optimal R-ate pairing r=e(P,Q) */
+void ZZZ::PAIR_ate(FP12 *r,ECP2 *P1,ECP *Q1)
+{
+    BIG x,n,n3;
+	FP Qx,Qy;
+    int i,nb,bt;
+    ECP2 A,NP,P;
+	ECP Q;
+    FP12 lv;
+#if PAIRING_FRIENDLY_ZZZ==BN
+    ECP2 KA;
+    FP2 X;
+
+    FP_rcopy(&Qx,Fra);
+    FP_rcopy(&Qy,Frb);
+    FP2_from_FPs(&X,&Qx,&Qy);
+
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+	FP2_inv(&X,&X);
+	FP2_norm(&X);
+#endif
+
+#endif
+
+    BIG_rcopy(x,CURVE_Bnx);
+
+#if PAIRING_FRIENDLY_ZZZ==BN
+    BIG_pmul(n,x,6);
+#if SIGN_OF_X_ZZZ==POSITIVEX
+	BIG_inc(n,2);
+#else
+    BIG_dec(n,2);
+#endif
+
+#else
+    BIG_copy(n,x);
+#endif
+
+    BIG_norm(n);
+	BIG_pmul(n3,n,3);
+	BIG_norm(n3);
+
+//    ECP2_affine(P);
+//    ECP_affine(Q);
+	ECP2_copy(&P,P1);
+	ECP_copy(&Q,Q1);
+
+	ECP2_affine(&P);
+	ECP_affine(&Q);
+
+
+    FP_copy(&Qx,&(Q.x));
+    FP_copy(&Qy,&(Q.y));
+
+    ECP2_copy(&A,&P);
+
+	ECP2_copy(&NP,&P); ECP2_neg(&NP);
+
+    FP12_one(r);
+    nb=BIG_nbits(n3);
+
+    /* Main Miller Loop */
+    for (i=nb-2; i>=1; i--)
+    {
+		FP12_sqr(r,r);
+        PAIR_line(&lv,&A,&A,&Qx,&Qy);
+        FP12_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+
+		bt=BIG_bit(n3,i)-BIG_bit(n,i); // bt=BIG_bit(n,i);
+        if (bt==1)
+        {
+            PAIR_line(&lv,&A,&P,&Qx,&Qy);
+            FP12_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+        }
+		if (bt==-1)
+		{
+			//ECP2_neg(P);
+            PAIR_line(&lv,&A,&NP,&Qx,&Qy);
+            FP12_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+			//ECP2_neg(P);
+		}
+
+    }
+
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+    FP12_conj(r,r);
+#endif
+    /* R-ate fixup required for BN curves */
+#if PAIRING_FRIENDLY_ZZZ==BN
+    ECP2_copy(&KA,&P);
+    ECP2_frob(&KA,&X);
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+    ECP2_neg(&A);
+    //FP12_conj(r,r);
+#endif
+    PAIR_line(&lv,&A,&KA,&Qx,&Qy);
+    FP12_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+    ECP2_frob(&KA,&X);
+    ECP2_neg(&KA);
+    PAIR_line(&lv,&A,&KA,&Qx,&Qy);
+    FP12_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+#endif
+}
+
+/* Optimal R-ate double pairing e(P,Q).e(R,S) */
+void ZZZ::PAIR_double_ate(FP12 *r,ECP2 *P1,ECP *Q1,ECP2 *R1,ECP *S1)
+{
+
+    BIG x,n,n3;
+	FP Qx,Qy,Sx,Sy;
+    int i,nb,bt;
+    ECP2 A,B,NP,NR,P,R;
+	ECP Q,S;
+    FP12 lv;
+#if PAIRING_FRIENDLY_ZZZ==BN
+    ECP2 K;
+    FP2 X;
+
+    FP_rcopy(&Qx,Fra);
+    FP_rcopy(&Qy,Frb);
+    FP2_from_FPs(&X,&Qx,&Qy);
+
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+	FP2_inv(&X,&X);
+	FP2_norm(&X);
+#endif
+
+#endif
+    BIG_rcopy(x,CURVE_Bnx);
+
+#if PAIRING_FRIENDLY_ZZZ==BN
+    BIG_pmul(n,x,6);
+#if SIGN_OF_X_ZZZ==POSITIVEX
+	BIG_inc(n,2);
+#else
+    BIG_dec(n,2);
+#endif
+#else
+    BIG_copy(n,x);
+#endif
+
+    BIG_norm(n);
+	BIG_pmul(n3,n,3);
+	BIG_norm(n3);
+
+	ECP2_copy(&P,P1);
+	ECP_copy(&Q,Q1);
+
+	ECP2_affine(&P);
+	ECP_affine(&Q);
+
+	ECP2_copy(&R,R1);
+	ECP_copy(&S,S1);
+
+	ECP2_affine(&R);
+	ECP_affine(&S);
+
+
+
+    FP_copy(&Qx,&(Q.x));
+    FP_copy(&Qy,&(Q.y));
+
+    FP_copy(&Sx,&(S.x));
+    FP_copy(&Sy,&(S.y));
+
+    ECP2_copy(&A,&P);
+    ECP2_copy(&B,&R);
+
+	ECP2_copy(&NP,&P); ECP2_neg(&NP);
+	ECP2_copy(&NR,&R); ECP2_neg(&NR);
+
+    FP12_one(r);
+    nb=BIG_nbits(n3);
+
+    /* Main Miller Loop */
+    for (i=nb-2; i>=1; i--)
+    {
+        FP12_sqr(r,r);
+        PAIR_line(&lv,&A,&A,&Qx,&Qy);
+        FP12_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+
+        PAIR_line(&lv,&B,&B,&Sx,&Sy);
+        FP12_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+
+		bt=BIG_bit(n3,i)-BIG_bit(n,i); // bt=BIG_bit(n,i);
+        if (bt==1)
+        {
+            PAIR_line(&lv,&A,&P,&Qx,&Qy);
+            FP12_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+
+            PAIR_line(&lv,&B,&R,&Sx,&Sy);
+            FP12_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+        }
+		if (bt==-1)
+		{
+			//ECP2_neg(P); 
+            PAIR_line(&lv,&A,&NP,&Qx,&Qy);
+            FP12_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+			//ECP2_neg(P); 
+			//ECP2_neg(R);
+            PAIR_line(&lv,&B,&NR,&Sx,&Sy);
+            FP12_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+			//ECP2_neg(R);
+		}
+	}
+
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+    FP12_conj(r,r);
+#endif
+    /* R-ate fixup required for BN curves */
+#if PAIRING_FRIENDLY_ZZZ==BN
+
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+//   FP12_conj(r,r);
+    ECP2_neg(&A);
+    ECP2_neg(&B);
+#endif
+
+    ECP2_copy(&K,&P);
+    ECP2_frob(&K,&X);
+    PAIR_line(&lv,&A,&K,&Qx,&Qy);
+    FP12_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+    ECP2_frob(&K,&X);
+    ECP2_neg(&K);
+    PAIR_line(&lv,&A,&K,&Qx,&Qy);
+    FP12_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+    ECP2_copy(&K,&R);
+    ECP2_frob(&K,&X);
+
+    PAIR_line(&lv,&B,&K,&Sx,&Sy);
+    FP12_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+    ECP2_frob(&K,&X);
+    ECP2_neg(&K);
+    PAIR_line(&lv,&B,&K,&Sx,&Sy);
+    FP12_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+#endif
+}
+
+/* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */
+void ZZZ::PAIR_fexp(FP12 *r)
+{
+    FP2 X;
+    BIG x;
+	FP a,b;
+    FP12 t0,y0,y1,y2,y3;
+
+    BIG_rcopy(x,CURVE_Bnx);
+    FP_rcopy(&a,Fra);
+    FP_rcopy(&b,Frb);
+    FP2_from_FPs(&X,&a,&b);
+
+    /* Easy part of final exp */
+
+    FP12_inv(&t0,r);
+    FP12_conj(r,r);
+
+    FP12_mul(r,&t0);
+    FP12_copy(&t0,r);
+
+    FP12_frob(r,&X);
+    FP12_frob(r,&X);
+    FP12_mul(r,&t0);
+
+    /* Hard part of final exp - see Duquesne & Ghamman eprint 2015/192.pdf */
+#if PAIRING_FRIENDLY_ZZZ==BN
+    FP12_pow(&t0,r,x); // t0=f^-u
+#if SIGN_OF_X_ZZZ==POSITIVEX
+	FP12_conj(&t0,&t0);
+#endif
+    FP12_usqr(&y3,&t0); // y3=t0^2
+    FP12_copy(&y0,&t0);
+    FP12_mul(&y0,&y3); // y0=t0*y3
+    FP12_copy(&y2,&y3);
+    FP12_frob(&y2,&X); // y2=y3^p
+    FP12_mul(&y2,&y3); //y2=y2*y3
+    FP12_usqr(&y2,&y2); //y2=y2^2
+    FP12_mul(&y2,&y3); // y2=y2*y3
+
+    FP12_pow(&t0,&y0,x);  //t0=y0^-u
+#if SIGN_OF_X_ZZZ==POSITIVEX
+	FP12_conj(&t0,&t0);
+#endif
+    FP12_conj(&y0,r);     //y0=~r
+    FP12_copy(&y1,&t0);
+    FP12_frob(&y1,&X);
+    FP12_frob(&y1,&X); //y1=t0^p^2
+    FP12_mul(&y1,&y0); // y1=y0*y1
+    FP12_conj(&t0,&t0); // t0=~t0
+    FP12_copy(&y3,&t0);
+    FP12_frob(&y3,&X); //y3=t0^p
+    FP12_mul(&y3,&t0); // y3=t0*y3
+    FP12_usqr(&t0,&t0); // t0=t0^2
+    FP12_mul(&y1,&t0); // y1=t0*y1
+
+    FP12_pow(&t0,&y3,x); // t0=y3^-u
+#if SIGN_OF_X_ZZZ==POSITIVEX
+	FP12_conj(&t0,&t0);
+#endif
+    FP12_usqr(&t0,&t0); //t0=t0^2
+    FP12_conj(&t0,&t0); //t0=~t0
+    FP12_mul(&y3,&t0); // y3=t0*y3
+
+    FP12_frob(r,&X);
+    FP12_copy(&y0,r);
+    FP12_frob(r,&X);
+    FP12_mul(&y0,r);
+    FP12_frob(r,&X);
+    FP12_mul(&y0,r);
+
+    FP12_usqr(r,&y3);  //r=y3^2
+    FP12_mul(r,&y2);   //r=y2*r
+    FP12_copy(&y3,r);
+    FP12_mul(&y3,&y0); // y3=r*y0
+    FP12_mul(r,&y1); // r=r*y1
+    FP12_usqr(r,r); // r=r^2
+    FP12_mul(r,&y3); // r=r*y3
+    FP12_reduce(r);
+#else
+// Ghamman & Fouotsa Method
+
+    FP12_usqr(&y0,r);
+    FP12_pow(&y1,&y0,x);
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP12_conj(&y1,&y1);
+#endif
+
+    BIG_fshr(x,1);
+    FP12_pow(&y2,&y1,x);
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP12_conj(&y2,&y2);
+#endif
+    BIG_fshl(x,1); // x must be even
+    FP12_conj(&y3,r);
+    FP12_mul(&y1,&y3);
+
+    FP12_conj(&y1,&y1);
+    FP12_mul(&y1,&y2);
+
+    FP12_pow(&y2,&y1,x);
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP12_conj(&y2,&y2);
+#endif
+    FP12_pow(&y3,&y2,x);
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP12_conj(&y3,&y3);
+#endif
+    FP12_conj(&y1,&y1);
+    FP12_mul(&y3,&y1);
+
+    FP12_conj(&y1,&y1);
+    FP12_frob(&y1,&X);
+    FP12_frob(&y1,&X);
+    FP12_frob(&y1,&X);
+    FP12_frob(&y2,&X);
+    FP12_frob(&y2,&X);
+    FP12_mul(&y1,&y2);
+
+    FP12_pow(&y2,&y3,x);
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP12_conj(&y2,&y2);
+#endif
+    FP12_mul(&y2,&y0);
+    FP12_mul(&y2,r);
+
+    FP12_mul(&y1,&y2);
+    FP12_copy(&y2,&y3);
+    FP12_frob(&y2,&X);
+    FP12_mul(&y1,&y2);
+    FP12_copy(r,&y1);
+    FP12_reduce(r);
+
+// Aranha et al method as described by Ghamman & Fouotsa
+    /*
+    	FP12_usqr(&y0,r);  // t0=f^2
+    	FP12_conj(&y3,&y0); // t0=f^-2
+    	FP12_pow(&t0,r,x); // t5=f^u
+    	FP12_usqr(&y1,&t0); // t1=t5^2
+    	FP12_mul(&y3,&t0); // t3=t0*t5
+
+    	FP12_pow(&y0,&y3,x);
+
+    	FP12_pow(&y2,&y0,x);
+
+    	FP12_pow(&y4,&y2,x);
+
+    	FP12_mul(&y4,&y1);
+    	FP12_pow(&y1,&y4,x);
+    	FP12_conj(&y3,&y3);
+    	FP12_mul(&y1,&y3);
+    	FP12_mul(&y1,r);
+
+    	FP12_conj(&y3,r);
+    	FP12_mul(&y0,r);
+    	FP12_frob(&y0,&X); FP12_frob(&y0,&X); FP12_frob(&y0,&X);
+
+    	FP12_mul(&y4,&y3);
+    	FP12_frob(&y4,&X);
+
+    	FP12_mul(&t0,&y2);
+    	FP12_frob(&t0,&X); FP12_frob(&t0,&X);
+
+    	FP12_mul(&t0,&y0);
+    	FP12_mul(&t0,&y4);
+    	FP12_mul(&t0,&y1);
+    	FP12_copy(r,&t0);
+    	FP12_reduce(r);*/
+
+//-----------------------------------
+    /*
+    	FP12_copy(&y0,r);						// y0=r;
+    	FP12_copy(&y1,r);						// y1=r;
+    	FP12_copy(&t0,r); FP12_frob(&t0,&X);	// t0=Frobenius(r,X,1);
+    	FP12_conj(&y3,&t0); FP12_mul(&y1,&y3);	// y1*=inverse(t0);
+    	FP12_frob(&t0,&X); FP12_frob(&t0,&X);	// t0=Frobenius(t0,X,2);
+    	FP12_mul(&y1,&t0);						// y1*=t0;
+
+    	FP12_pow(r,r,x);						// r=pow(r,x);
+    	FP12_conj(&y3,r); FP12_mul(&y1,&y3);	// y1*=inverse(r);
+    	FP12_copy(&t0,r); FP12_frob(&t0,&X);	// t0=Frobenius(r,X,1);
+    	FP12_mul(&y0,&t0);						// y0*=t0;
+    	FP12_frob(&t0,&X);						// t0=Frobenius(t0,X,1);
+    	FP12_mul(&y1,&t0);						// y1*=t0;
+    	FP12_frob(&t0,&X);						// t0=Frobenius(t0,X,1);
+    	FP12_conj(&y3,&t0); FP12_mul(&y0,&y3);	// y0*=inverse(t0);
+
+    	FP12_pow(r,r,x);						// r=pow(r,x);
+    	FP12_mul(&y0,r);						// y0*=r;
+    	FP12_copy(&t0,r); FP12_frob(&t0,&X); FP12_frob(&t0,&X); // t0=Frobenius(r,X,2);
+    	FP12_conj(&y3,&t0); FP12_mul(&y0,&y3);	// y0*=inverse(t0);
+    	FP12_frob(&t0,&X);						// t0=Frobenius(t0,X,1);
+    	FP12_mul(&y1,&t0);						// y1*=t0;
+
+    	FP12_pow(r,r,x);						// r=pow(r,x);			// r^x3
+    	FP12_copy(&t0,r); FP12_frob(&t0,&X);	// t0=Frobenius(r,X,1);
+    	FP12_conj(&y3,&t0); FP12_mul(&y0,&y3);	// y0*=inverse(t0);
+    	FP12_frob(&t0,&X);						// t0=Frobenius(t0,X,1);
+    	FP12_mul(&y1,&t0);						// y1*=t0;
+
+    	FP12_pow(r,r,x);						// r=pow(r,x);			// r^x4
+    	FP12_conj(&y3,r); FP12_mul(&y0,&y3);	// y0*=inverse(r);
+    	FP12_copy(&t0,r); FP12_frob(&t0,&X);	// t0=Frobenius(r,X,1);
+    	FP12_mul(&y1,&t0);						//y1*=t0;
+
+    	FP12_pow(r,r,x);						// r=pow(r,x);			// r^x5
+    	FP12_mul(&y1,r);						// y1*=r;
+
+    	FP12_usqr(&y0,&y0);						// r=y0*y0*y1;
+    	FP12_mul(&y0,&y1);
+    	FP12_copy(r,&y0);
+    	FP12_reduce(r); */
+#endif
+}
+
+#ifdef USE_GLV_ZZZ
+/* GLV method */
+static void ZZZ::glv(BIG u[2],BIG e)
+{
+#if PAIRING_FRIENDLY_ZZZ==BN
+    int i,j;
+    BIG v[2],t,q;
+    DBIG d;
+    BIG_rcopy(q,CURVE_Order);
+    for (i=0; i<2; i++)
+    {
+        BIG_rcopy(t,CURVE_W[i]);
+//BIG_norm(t); BIG_norm(e);
+        BIG_mul(d,t,e);
+        BIG_ddiv(v[i],d,q);
+        BIG_zero(u[i]);
+    }
+    BIG_copy(u[0],e);
+    for (i=0; i<2; i++)
+        for (j=0; j<2; j++)
+        {
+            BIG_rcopy(t,CURVE_SB[j][i]);
+            BIG_modmul(t,v[j],t,q);
+            BIG_add(u[i],u[i],q);
+            BIG_sub(u[i],u[i],t);
+            BIG_mod(u[i],q);
+        }
+
+#else
+// -(x^2).P = (Beta.x,y)
+
+    BIG x,x2,q;
+    BIG_rcopy(x,CURVE_Bnx);
+    BIG_smul(x2,x,x);
+    BIG_copy(u[0],e);
+    BIG_mod(u[0],x2);
+    BIG_copy(u[1],e);
+    BIG_sdiv(u[1],x2);
+
+    BIG_rcopy(q,CURVE_Order);
+    BIG_sub(u[1],q,u[1]);
+
+#endif
+
+    return;
+}
+#endif // USE_GLV
+
+/* Galbraith & Scott Method */
+static void ZZZ::gs(BIG u[4],BIG e)
+{
+    int i;
+#if PAIRING_FRIENDLY_ZZZ==BN
+    int j;
+    BIG v[4],t,q;
+    DBIG d;
+    BIG_rcopy(q,CURVE_Order);
+    for (i=0; i<4; i++)
+    {
+        BIG_rcopy(t,CURVE_WB[i]);
+//BIG_norm(t); BIG_norm(e);
+        BIG_mul(d,t,e);
+        BIG_ddiv(v[i],d,q);
+        BIG_zero(u[i]);
+    }
+
+    BIG_copy(u[0],e);
+    for (i=0; i<4; i++)
+        for (j=0; j<4; j++)
+        {
+            BIG_rcopy(t,CURVE_BB[j][i]);
+            BIG_modmul(t,v[j],t,q);
+            BIG_add(u[i],u[i],q);
+            BIG_sub(u[i],u[i],t);
+            BIG_mod(u[i],q);
+        }
+
+#else
+
+    BIG x,w,q;
+	BIG_rcopy(q,CURVE_Order);
+    BIG_rcopy(x,CURVE_Bnx);
+    BIG_copy(w,e);
+
+    for (i=0; i<3; i++)
+    {
+        BIG_copy(u[i],w);
+        BIG_mod(u[i],x);
+        BIG_sdiv(w,x);
+    }
+	BIG_copy(u[3],w);
+
+/*  */
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	BIG_modneg(u[1],u[1],q);
+	BIG_modneg(u[3],u[3],q);
+#endif
+
+#endif
+    return;
+}
+
+/* Multiply P by e in group G1 */
+void ZZZ::PAIR_G1mul(ECP *P,BIG e)
+{
+#ifdef USE_GLV_ZZZ   /* Note this method is patented */
+    int np,nn;
+    ECP Q;
+	FP cru;
+    BIG t,q;
+    BIG u[2];
+
+    BIG_rcopy(q,CURVE_Order);
+    glv(u,e);
+
+    //ECP_affine(P);
+    ECP_copy(&Q,P); ECP_affine(&Q);
+    FP_rcopy(&cru,CURVE_Cru);
+    FP_mul(&(Q.x),&(Q.x),&cru);
+
+    /* note that -a.B = a.(-B). Use a or -a depending on which is smaller */
+
+    np=BIG_nbits(u[0]);
+    BIG_modneg(t,u[0],q);
+    nn=BIG_nbits(t);
+    if (nn<np)
+    {
+        BIG_copy(u[0],t);
+        ECP_neg(P);
+    }
+
+    np=BIG_nbits(u[1]);
+    BIG_modneg(t,u[1],q);
+    nn=BIG_nbits(t);
+    if (nn<np)
+    {
+        BIG_copy(u[1],t);
+        ECP_neg(&Q);
+    }
+    BIG_norm(u[0]);
+    BIG_norm(u[1]);
+    ECP_mul2(P,&Q,u[0],u[1]);
+
+#else
+    ECP_mul(P,e);
+#endif
+}
+
+/* Multiply P by e in group G2 */
+void ZZZ::PAIR_G2mul(ECP2 *P,BIG e)
+{
+#ifdef USE_GS_G2_ZZZ   /* Well I didn't patent it :) */
+    int i,np,nn;
+    ECP2 Q[4];
+    FP2 X;
+    FP fx,fy;
+    BIG x,y,u[4];
+
+    FP_rcopy(&fx,Fra);
+    FP_rcopy(&fy,Frb);
+    FP2_from_FPs(&X,&fx,&fy);
+
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+	FP2_inv(&X,&X);
+	FP2_norm(&X);
+#endif
+
+    BIG_rcopy(y,CURVE_Order);
+    gs(u,e);
+
+
+    ECP2_copy(&Q[0],P);
+    for (i=1; i<4; i++)
+    {
+        ECP2_copy(&Q[i],&Q[i-1]);
+        ECP2_frob(&Q[i],&X);
+    }
+
+
+    for (i=0; i<4; i++)
+    {
+        np=BIG_nbits(u[i]);
+        BIG_modneg(x,u[i],y);
+        nn=BIG_nbits(x);
+        if (nn<np)
+        {
+            BIG_copy(u[i],x);
+            ECP2_neg(&Q[i]);
+        }
+        BIG_norm(u[i]);  
+    }
+
+    ECP2_mul4(P,Q,u);
+
+#else
+    ECP2_mul(P,e);
+#endif
+}
+
+/* f=f^e */
+void ZZZ::PAIR_GTpow(FP12 *f,BIG e)
+{
+#ifdef USE_GS_GT_ZZZ   /* Note that this option requires a lot of RAM! Maybe better to use compressed XTR method, see fp4.c */
+    int i,np,nn;
+    FP12 g[4];
+    FP2 X;
+    BIG t,q;
+	FP fx,fy;
+    BIG u[4];
+
+    FP_rcopy(&fx,Fra);
+    FP_rcopy(&fy,Frb);
+    FP2_from_FPs(&X,&fx,&fy);
+
+    BIG_rcopy(q,CURVE_Order);
+    gs(u,e);
+
+    FP12_copy(&g[0],f);
+    for (i=1; i<4; i++)
+    {
+        FP12_copy(&g[i],&g[i-1]);
+        FP12_frob(&g[i],&X);
+    }
+
+    for (i=0; i<4; i++)
+    {
+        np=BIG_nbits(u[i]);
+        BIG_modneg(t,u[i],q);
+        nn=BIG_nbits(t);
+        if (nn<np)
+        {
+            BIG_copy(u[i],t);
+            FP12_conj(&g[i],&g[i]);
+        }
+        BIG_norm(u[i]);        
+    }
+    FP12_pow4(f,g,u);
+
+#else
+    FP12_pow(f,f,e);
+#endif
+}
+
+/* test group membership test - no longer needed */
+/* with GT-Strong curve, now only check that m!=1, conj(m)*m==1, and m.m^{p^4}=m^{p^2} */
+
+/*
+int PAIR_GTmember(FP12 *m)
+{
+	BIG a,b;
+	FP2 X;
+	FP12 r,w;
+	if (FP12_isunity(m)) return 0;
+	FP12_conj(&r,m);
+	FP12_mul(&r,m);
+	if (!FP12_isunity(&r)) return 0;
+
+	BIG_rcopy(a,CURVE_Fra);
+	BIG_rcopy(b,CURVE_Frb);
+	FP2_from_BIGs(&X,a,b);
+
+
+	FP12_copy(&r,m); FP12_frob(&r,&X); FP12_frob(&r,&X);
+	FP12_copy(&w,&r); FP12_frob(&w,&X); FP12_frob(&w,&X);
+	FP12_mul(&w,m);
+
+
+#ifndef GT_STRONG
+	if (!FP12_equals(&w,&r)) return 0;
+
+	BIG_rcopy(a,CURVE_Bnx);
+
+	FP12_copy(&r,m); FP12_pow(&w,&r,a); FP12_pow(&w,&w,a);
+	FP12_sqr(&r,&w); FP12_mul(&r,&w); FP12_sqr(&r,&r);
+
+	FP12_copy(&w,m); FP12_frob(&w,&X);
+ #endif
+
+	return FP12_equals(&w,&r);
+}
+
+*/
+
+
+#ifdef HAS_MAIN
+/*
+#if CHOICE==BN254_T
+
+const BIG TEST_Gx={0x18AFF11A,0xF2EF406,0xAF68220,0x171F2E27,0x6BA0959,0x124C50E0,0x450BE27,0x7003EA8,0x8A914};
+const BIG TEST_Gy={0x6E010F4,0xA71D07E,0x7ECADA8,0x8260E8E,0x1F79C328,0x17A09412,0xBFAE690,0x1C57CBD1,0x17DF54};
+
+const BIG TEST_Pxa={0x1047D566,0xD83CD71,0x10322E9D,0x991FA93,0xA282C48,0x18AEBEC8,0xCB05850,0x13B4F669,0x21794A};
+const BIG TEST_Pxb={0x1E305936,0x16885BF1,0x327060,0xE26F794,0x1547D870,0x1963E5B2,0x1BEBB96C,0x988A33C,0x1A9B47};
+const BIG TEST_Pya={0x20FF876,0x4427E67,0x18732211,0xE88E45E,0x174D1A7E,0x17D877ED,0x343AB37,0x97EB453,0xB00D5};
+const BIG TEST_Pyb={0x1D746B7B,0x732F4C2,0x122A49B0,0x16267985,0x235DF56,0x10B1E4D,0x14D8F210,0x17A05C3E,0x5ECF8};
+
+#endif
+
+#if CHOICE==BN254_T2
+
+const BIG TEST_Gx={0x15488765,0x46790D7,0xD9900A,0x1DFB43F,0x9F2D307,0xC4724E8,0x5678E51,0x15C3E3A7,0x1BEC8E};
+const BIG TEST_Gy={0x3D3273C,0x1AFA5FF,0x1880A139,0xACD34DF,0x17493067,0x10FA4103,0x1D4C9766,0x1A73F3DB,0x2D148};
+
+const BIG TEST_Pxa={0xF8DC275,0xAC27FA,0x11815151,0x152691C8,0x5CDEBF1,0x7D5A965,0x1BF70CE3,0x679A1C8,0xD62CF};
+const BIG TEST_Pxb={0x1D17D7A8,0x6B28DF4,0x174A0389,0xFE67E5F,0x1FA97A3C,0x7F5F473,0xFFB5146,0x4BC19A5,0x227010};
+const BIG TEST_Pya={0x16CC1F90,0x5284627,0x171B91AB,0x11F843B9,0x1D468755,0x67E279C,0x19FE0EF8,0x1A0CAA6B,0x1CC6CB};
+const BIG TEST_Pyb={0x1FF0CF2A,0xBC83255,0x6DD6EE8,0xB8B752F,0x13E484EC,0x1809BE81,0x1A648AA1,0x8CEF3F3,0x86EE};
+
+
+#endif
+
+#if CHOICE==BN254
+
+const BIG TEST_Gx={0x14BEC4670E4EB7,0xEA2973860F6861,0x35C14B2FC3C28F,0x4402A0B63B9473,0x2074A81D};
+const BIG TEST_Gy={0xC284846631CBEB,0x34A6E8D871B3B,0x89FB94A82B2006,0x87B20038771FC,0x6A41108};
+
+const BIG TEST_Pxa={0xE4A00F52183C77,0x554E02DF4F8354,0xB65EB5CF1C2F89,0x8B71A87BFCFC9,0x49EEDB1};
+const BIG TEST_Pxb={0xCFB8FA9AA8845D,0x8A9CC76D966697,0x185BA05BF5EC08,0x76140E87D97226,0x1FB93AB6};
+const BIG TEST_Pya={0x3644CC1EDF208A,0xA637FB3FF8E257,0x4453DA2BB9E686,0xD14AD3CDF6A1FE,0xCD04A1E};
+const BIG TEST_Pyb={0x71BD7630A43C14,0x1CAA9F14EA264E,0x3C3C2DFC765DEF,0xCF59D1A1A7D6EE,0x11FF7795};
+
+
+#endif
+*/
+int main()
+{
+    int i;
+    char byt[32];
+    csprng rng;
+    BIG xa,xb,ya,yb,w,a,b,t1,q,u[2],v[4],m,r;
+    ECP2 P,G;
+    ECP Q,R;
+    FP12 g,gp;
+    FP4 t,c,cp,cpm1,cpm2;
+    FP2 x,y,X;
+
+
+    BIG_rcopy(a,CURVE_Fra);
+    BIG_rcopy(b,CURVE_Frb);
+    FP2_from_BIGs(&X,a,b);
+
+    BIG_rcopy(xa,CURVE_Gx);
+    BIG_rcopy(ya,CURVE_Gy);
+
+    ECP_set(&Q,xa,ya);
+    if (Q.inf) printf("Failed to set - point not on curve\n");
+    else printf("G1 set success\n");
+
+    printf("Q= ");
+    ECP_output(&Q);
+    printf("\n");
+
+//	BIG_rcopy(r,CURVE_Order); BIG_dec(r,7); BIG_norm(r);
+    BIG_rcopy(xa,CURVE_Pxa);
+    BIG_rcopy(xb,CURVE_Pxb);
+    BIG_rcopy(ya,CURVE_Pya);
+    BIG_rcopy(yb,CURVE_Pyb);
+
+    FP2_from_BIGs(&x,xa,xb);
+    FP2_from_BIGs(&y,ya,yb);
+
+    ECP2_set(&P,&x,&y);
+    if (P.inf) printf("Failed to set - point not on curve\n");
+    else printf("G2 set success\n");
+
+    printf("P= ");
+    ECP2_output(&P);
+    printf("\n");
+
+    for (i=0; i<1000; i++ )
+    {
+
+        PAIR_ate(&g,&P,&Q);
+        PAIR_fexp(&g);
+
+//	PAIR_GTpow(&g,xa);
+
+    }
+    printf("g= ");
+    FP12_output(&g);
+    printf("\n");
+
+}
+
+#endif
diff --git a/version3/cpp/pair.h b/version3/cpp/pair.h
new file mode 100644
index 0000000..0d6d179
--- /dev/null
+++ b/version3/cpp/pair.h
@@ -0,0 +1,80 @@
+#ifndef PAIR_ZZZ_H
+#define PAIR_ZZZ_H
+
+#include "fp12_YYY.h"
+#include "ecp2_ZZZ.h"
+#include "ecp_ZZZ.h"
+
+using namespace amcl;
+
+namespace ZZZ {
+/* Pairing constants */
+
+extern const XXX::BIG CURVE_Bnx; /**< BN curve x parameter */
+extern const XXX::BIG CURVE_Cru; /**< BN curve Cube Root of Unity */
+
+extern const XXX::BIG CURVE_W[2];	 /**< BN curve constant for GLV decomposition */
+extern const XXX::BIG CURVE_SB[2][2]; /**< BN curve constant for GLV decomposition */
+extern const XXX::BIG CURVE_WB[4];	 /**< BN curve constant for GS decomposition */
+extern const XXX::BIG CURVE_BB[4][4]; /**< BN curve constant for GS decomposition */
+
+/* Pairing function prototypes */
+/**	@brief Calculate Miller loop for Optimal ATE pairing e(P,Q)
+ *
+	@param r FP12 result of the pairing calculation e(P,Q)
+	@param P ECP2 instance, an element of G2
+	@param Q ECP instance, an element of G1
+
+ */
+extern void PAIR_ate(YYY::FP12 *r,ECP2 *P,ECP *Q);
+/**	@brief Calculate Miller loop for Optimal ATE double-pairing e(P,Q).e(R,S)
+ *
+	Faster than calculating two separate pairings
+	@param r FP12 result of the pairing calculation e(P,Q).e(R,S), an element of GT
+	@param P ECP2 instance, an element of G2
+	@param Q ECP instance, an element of G1
+	@param R ECP2 instance, an element of G2
+	@param S ECP instance, an element of G1
+ */
+extern void PAIR_double_ate(YYY::FP12 *r,ECP2 *P,ECP *Q,ECP2 *R,ECP *S);
+/**	@brief Final exponentiation of pairing, converts output of Miller loop to element in GT
+ *
+	Here p is the internal modulus, and r is the group order
+	@param x FP12, on exit = x^((p^12-1)/r)
+ */
+extern void PAIR_fexp(YYY::FP12 *x);
+/**	@brief Fast point multiplication of a member of the group G1 by a BIG number
+ *
+	May exploit endomorphism for speed.
+	@param Q ECP member of G1.
+	@param b BIG multiplier
+
+ */
+extern void PAIR_G1mul(ECP *Q,XXX::BIG b);
+/**	@brief Fast point multiplication of a member of the group G2 by a BIG number
+ *
+	May exploit endomorphism for speed.
+	@param P ECP2 member of G1.
+	@param b BIG multiplier
+
+ */
+extern void PAIR_G2mul(ECP2 *P,XXX::BIG b);
+/**	@brief Fast raising of a member of GT to a BIG power
+ *
+	May exploit endomorphism for speed.
+	@param x FP12 member of GT.
+	@param b BIG exponent
+
+ */
+extern void PAIR_GTpow(YYY::FP12 *x,XXX::BIG b);
+/**	@brief Tests FP12 for membership of GT
+ *
+	@param x FP12 instance
+	@return 1 if x is in GT, else return 0
+
+ */
+extern int PAIR_GTmember(YYY::FP12 *x);
+
+}
+
+#endif
diff --git a/version3/cpp/pair192.cpp b/version3/cpp/pair192.cpp
new file mode 100644
index 0000000..af803ac
--- /dev/null
+++ b/version3/cpp/pair192.cpp
@@ -0,0 +1,758 @@
+/*
+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.
+*/
+
+/* AMCL BLS Curve pairing functions */
+
+//#define HAS_MAIN
+
+#include "pair192_ZZZ.h"
+
+using namespace XXX;
+using namespace YYY;
+
+namespace ZZZ {
+	static void PAIR_line(FP24 *,ECP4 *,ECP4 *,FP *,FP *);
+	static void glv(BIG u[2],BIG);
+	static void gs(BIG u[4],BIG);
+}
+
+/* Line function */
+static void ZZZ::PAIR_line(FP24 *v,ECP4 *A,ECP4 *B,FP *Qx,FP *Qy)
+{
+	FP4 X1,Y1,T1,T2;
+	FP4 XX,YY,ZZ,YZ;
+    FP8 a,b,c;
+
+	if (A==B)
+    {
+        /* doubling */
+ 		FP4_copy(&XX,&(A->x));	//FP4 XX=new FP4(A.getx());  //X
+		FP4_copy(&YY,&(A->y));	//FP4 YY=new FP4(A.gety());  //Y
+		FP4_copy(&ZZ,&(A->z));	//FP4 ZZ=new FP4(A.getz());  //Z
+
+
+		FP4_copy(&YZ,&YY);		//FP4 YZ=new FP4(YY);        //Y 
+		FP4_mul(&YZ,&YZ,&ZZ);		//YZ.mul(ZZ);                //YZ
+		FP4_sqr(&XX,&XX);		//XX.sqr();	               //X^2
+		FP4_sqr(&YY,&YY);		//YY.sqr();	               //Y^2
+		FP4_sqr(&ZZ,&ZZ);		//ZZ.sqr();			       //Z^2
+			
+		FP4_imul(&YZ,&YZ,4);	//YZ.imul(4);
+		FP4_neg(&YZ,&YZ);		//YZ.neg(); 
+		FP4_norm(&YZ);			//YZ.norm();       //-4YZ
+
+		FP4_imul(&XX,&XX,6);					//6X^2
+		FP4_qmul(&XX,&XX,Qx);	               //6X^2.Xs
+
+		FP4_imul(&ZZ,&ZZ,3*CURVE_B_I);	//3Bz^2 
+
+		FP4_qmul(&YZ,&YZ,Qy);	//-4YZ.Ys
+
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+		FP4_div_2i(&ZZ);		//6(b/i)z^2
+#endif
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+		FP4_times_i(&ZZ);
+		FP4_add(&ZZ,&ZZ,&ZZ);  // 6biz^2
+		FP4_times_i(&YZ);
+		FP4_norm(&YZ);	
+#endif
+		FP4_norm(&ZZ);			// 6bi.Z^2 
+
+		FP4_add(&YY,&YY,&YY);	// 2y^2
+		FP4_sub(&ZZ,&ZZ,&YY);	// 
+		FP4_norm(&ZZ);			// 6b.Z^2-2Y^2
+
+		FP8_from_FP4s(&a,&YZ,&ZZ); // -4YZ.Ys | 6b.Z^2-2Y^2 | 6X^2.Xs 
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+		FP8_from_FP4(&b,&XX);	
+		FP8_zero(&c);
+#endif
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+		FP8_zero(&b);
+		FP8_from_FP4H(&c,&XX);
+#endif
+
+		ECP4_dbl(A);				//A.dbl();
+    }
+    else
+    {
+        /* addition */
+
+		FP4_copy(&X1,&(A->x));		//FP4 X1=new FP4(A.getx());    // X1
+		FP4_copy(&Y1,&(A->y));		//FP4 Y1=new FP4(A.gety());    // Y1
+		FP4_copy(&T1,&(A->z));		//FP4 T1=new FP4(A.getz());    // Z1
+			
+		FP4_copy(&T2,&T1);		//FP4 T2=new FP4(A.getz());    // Z1
+
+		FP4_mul(&T1,&T1,&(B->y));	//T1.mul(B.gety());    // T1=Z1.Y2 
+		FP4_mul(&T2,&T2,&(B->x));	//T2.mul(B.getx());    // T2=Z1.X2
+
+		FP4_sub(&X1,&X1,&T2);		//X1.sub(T2); 
+		FP4_norm(&X1);				//X1.norm();  // X1=X1-Z1.X2
+		FP4_sub(&Y1,&Y1,&T1);		//Y1.sub(T1); 
+		FP4_norm(&Y1);				//Y1.norm();  // Y1=Y1-Z1.Y2
+
+		FP4_copy(&T1,&X1);			//T1.copy(X1);            // T1=X1-Z1.X2
+
+		FP4_qmul(&X1,&X1,Qy);		//X1.pmul(Qy);            // X1=(X1-Z1.X2).Ys
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+		FP4_times_i(&X1);
+		FP4_norm(&X1);
+#endif
+
+		FP4_mul(&T1,&T1,&(B->y));	//T1.mul(B.gety());       // T1=(X1-Z1.X2).Y2
+
+		FP4_copy(&T2,&Y1);			//T2.copy(Y1);            // T2=Y1-Z1.Y2
+		FP4_mul(&T2,&T2,&(B->x));	//T2.mul(B.getx());       // T2=(Y1-Z1.Y2).X2
+		FP4_sub(&T2,&T2,&T1);		//T2.sub(T1); 
+		FP4_norm(&T2);				//T2.norm();          // T2=(Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2
+		FP4_qmul(&Y1,&Y1,Qx);		//Y1.pmul(Qx);  
+		FP4_neg(&Y1,&Y1);			//Y1.neg(); 
+		FP4_norm(&Y1);				//Y1.norm(); // Y1=-(Y1-Z1.Y2).Xs
+
+		FP8_from_FP4s(&a,&X1,&T2);	// (X1-Z1.X2).Ys  |  (Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2  | - (Y1-Z1.Y2).Xs
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+		FP8_from_FP4(&b,&Y1);		//b=new FP4(Y1);
+		FP8_zero(&c);
+#endif
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+		FP8_zero(&b);
+		FP8_from_FP4H(&c,&Y1);		//b=new FP4(Y1);
+#endif
+		ECP4_add(A,B);			//A.add(B);
+    }
+
+
+    FP24_from_FP8s(v,&a,&b,&c);
+}
+
+/* Optimal R-ate pairing r=e(P,Q) */
+void ZZZ::PAIR_ate(FP24 *r,ECP4 *P1,ECP *Q1)
+{
+    BIG x,n,n3;
+	FP Qx,Qy;
+    int i,j,nb,bt;
+    ECP4 A,NP,P;
+	ECP Q;
+    FP24 lv;
+
+    BIG_rcopy(x,CURVE_Bnx);
+
+    BIG_copy(n,x);
+
+    //BIG_norm(n);
+	BIG_pmul(n3,n,3);
+	BIG_norm(n3);
+
+	ECP4_copy(&P,P1);
+	ECP_copy(&Q,Q1);
+
+	ECP4_affine(&P);
+	ECP_affine(&Q);
+
+    FP_copy(&Qx,&(Q.x));
+    FP_copy(&Qy,&(Q.y));
+
+    ECP4_copy(&A,&P);
+
+	ECP4_copy(&NP,&P); ECP4_neg(&NP);
+
+    FP24_one(r);
+    nb=BIG_nbits(n3);  // n3
+
+	j=0;
+    /* Main Miller Loop */
+    for (i=nb-2; i>=1; i--)
+    {
+		j++;
+		FP24_sqr(r,r);
+        PAIR_line(&lv,&A,&A,&Qx,&Qy);
+        FP24_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+
+		bt= BIG_bit(n3,i)-BIG_bit(n,i);  // BIG_bit(n,i); 
+        if (bt==1)
+        {
+            PAIR_line(&lv,&A,&P,&Qx,&Qy);
+            FP24_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+        }
+		if (bt==-1)
+		{
+			//ECP4_neg(P);
+            PAIR_line(&lv,&A,&NP,&Qx,&Qy);
+            FP24_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+			//ECP4_neg(P);
+		}
+
+    }
+
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+    FP24_conj(r,r);
+#endif
+
+}
+
+/* Optimal R-ate double pairing e(P,Q).e(R,S) */
+void ZZZ::PAIR_double_ate(FP24 *r,ECP4 *P1,ECP *Q1,ECP4 *R1,ECP *S1)
+{
+    BIG x,n,n3;
+	FP Qx,Qy,Sx,Sy;
+    int i,nb,bt;
+    ECP4 A,B,NP,NR,P,R;
+	ECP Q,S;
+    FP24 lv;
+
+    BIG_rcopy(x,CURVE_Bnx);
+    BIG_copy(n,x);
+
+    //BIG_norm(n);
+	BIG_pmul(n3,n,3);
+	BIG_norm(n3);
+
+	ECP4_copy(&P,P1);
+	ECP_copy(&Q,Q1);
+
+	ECP4_affine(&P);
+	ECP_affine(&Q);
+
+	ECP4_copy(&R,R1);
+	ECP_copy(&S,S1);
+
+	ECP4_affine(&R);
+	ECP_affine(&S);
+
+    FP_copy(&Qx,&(Q.x));
+    FP_copy(&Qy,&(Q.y));
+
+    FP_copy(&Sx,&(S.x));
+    FP_copy(&Sy,&(S.y));
+
+    ECP4_copy(&A,&P);
+    ECP4_copy(&B,&R);
+
+	ECP4_copy(&NP,&P); ECP4_neg(&NP);
+	ECP4_copy(&NR,&R); ECP4_neg(&NR);
+
+
+    FP24_one(r);
+    nb=BIG_nbits(n3);
+
+    /* Main Miller Loop */
+    for (i=nb-2; i>=1; i--)
+    {
+        FP24_sqr(r,r);
+        PAIR_line(&lv,&A,&A,&Qx,&Qy);
+        FP24_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+
+        PAIR_line(&lv,&B,&B,&Sx,&Sy);
+        FP24_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+
+		bt=BIG_bit(n3,i)-BIG_bit(n,i); // bt=BIG_bit(n,i);
+        if (bt==1)
+        {
+            PAIR_line(&lv,&A,&P,&Qx,&Qy);
+            FP24_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+
+            PAIR_line(&lv,&B,&R,&Sx,&Sy);
+            FP24_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+        }
+		if (bt==-1)
+		{
+			//ECP4_neg(P); 
+            PAIR_line(&lv,&A,&NP,&Qx,&Qy);
+            FP24_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+			//ECP4_neg(P); 
+			//ECP4_neg(R);
+            PAIR_line(&lv,&B,&NR,&Sx,&Sy);
+            FP24_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+			//ECP4_neg(R);
+		}
+	}
+
+
+
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+    FP24_conj(r,r);
+#endif
+
+}
+
+/* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */
+
+void ZZZ::PAIR_fexp(FP24 *r)
+{
+    FP2 X;
+    BIG x;
+	FP a,b;
+    FP24 t0,t1,t2,t3,t4,t5,t6,t7;  // could lose one of these - r=t3
+
+    BIG_rcopy(x,CURVE_Bnx);
+    FP_rcopy(&a,Fra);
+    FP_rcopy(&b,Frb);
+    FP2_from_FPs(&X,&a,&b);
+
+    /* Easy part of final exp - r^(p^12-1)(p^4+1)*/
+
+    FP24_inv(&t0,r);
+    FP24_conj(r,r);
+
+    FP24_mul(r,&t0);
+    FP24_copy(&t0,r);
+
+    FP24_frob(r,&X,4);
+
+    FP24_mul(r,&t0);
+
+// Ghamman & Fouotsa Method - (completely garbled in  https://eprint.iacr.org/2016/130)
+
+	FP24_usqr(&t7,r);			// t7=f^2
+	FP24_pow(&t1,&t7,x);		// t1=t7^u
+
+	BIG_fshr(x,1);
+	FP24_pow(&t2,&t1,x);		// t2=t1^(u/2)
+	BIG_fshl(x,1);  // x must be even
+
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP24_conj(&t1,&t1);
+#endif
+
+	FP24_conj(&t3,&t1);		// t3=1/t1
+	FP24_mul(&t2,&t3);		// t2=t1*t3
+	FP24_mul(&t2,r);		// t2=t2*f
+
+
+	FP24_pow(&t3,&t2,x);		// t3=t2^u
+	FP24_pow(&t4,&t3,x);		// t4=t3^u
+	FP24_pow(&t5,&t4,x);		// t5=t4^u
+
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP24_conj(&t3,&t3);
+	FP24_conj(&t5,&t5);
+#endif
+
+	FP24_frob(&t3,&X,6);
+	FP24_frob(&t4,&X,5);
+
+	FP24_mul(&t3,&t4);		// t3=t3.t4
+
+
+	FP24_pow(&t6,&t5,x);		// t6=t5^u
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP24_conj(&t6,&t6);
+#endif
+
+
+	FP24_frob(&t5,&X,4); 
+	FP24_mul(&t3,&t5); // ??
+
+
+	FP24_conj(&t0,&t2);			// t0=1/t2
+	FP24_mul(&t6,&t0);		// t6=t6*t0
+
+	FP24_copy(&t5,&t6);
+	FP24_frob(&t5,&X,3); 
+
+	FP24_mul(&t3,&t5);		// t3=t3*t5
+	FP24_pow(&t5,&t6,x);	// t5=t6^x
+	FP24_pow(&t6,&t5,x);	// t6=t5^x
+
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP24_conj(&t5,&t5);
+#endif
+
+	FP24_copy(&t0,&t5);	
+	FP24_frob(&t0,&X,2); 
+	FP24_mul(&t3,&t0);		// t3=t3*t0
+	FP24_copy(&t0,&t6);     // 
+	FP24_frob(&t0,&X,1);
+
+	FP24_mul(&t3,&t0);		// t3=t3*t0
+	FP24_pow(&t5,&t6,x);    // t5=t6*x
+
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP24_conj(&t5,&t5);
+#endif
+
+	FP24_frob(&t2,&X,7); 
+
+	FP24_mul(&t5,&t7);		// t5=t5*t7
+	FP24_mul(&t3,&t2);		// t3=t3*t2
+	FP24_mul(&t3,&t5);		// t3=t3*t5
+
+	FP24_mul(r,&t3);
+	FP24_reduce(r);
+
+}
+
+#ifdef USE_GLV_ZZZ
+/* GLV method */
+static void ZZZ::glv(BIG u[2],BIG e)
+{
+
+// -(x^4).P = (Beta.x,y)
+
+    BIG x,x2,q;
+    BIG_rcopy(x,CURVE_Bnx);
+    BIG_smul(x2,x,x);
+	BIG_smul(x,x2,x2);
+    BIG_copy(u[0],e);
+    BIG_mod(u[0],x);
+    BIG_copy(u[1],e);
+    BIG_sdiv(u[1],x);
+
+    BIG_rcopy(q,CURVE_Order);
+    BIG_sub(u[1],q,u[1]);
+
+
+    return;
+}
+#endif // USE_GLV
+
+/* Galbraith & Scott Method */
+static void ZZZ::gs(BIG u[8],BIG e)
+{
+    int i;
+
+    BIG x,w,q;
+	BIG_rcopy(q,CURVE_Order);
+    BIG_rcopy(x,CURVE_Bnx);
+    BIG_copy(w,e);
+
+    for (i=0; i<7; i++)
+    {
+        BIG_copy(u[i],w);
+        BIG_mod(u[i],x);
+        BIG_sdiv(w,x);
+    }
+	BIG_copy(u[7],w);
+
+/*  */
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	BIG_modneg(u[1],u[1],q);
+	BIG_modneg(u[3],u[3],q);
+	BIG_modneg(u[5],u[5],q);
+	BIG_modneg(u[7],u[7],q);
+#endif
+
+
+    return;
+}
+
+/* Multiply P by e in group G1 */
+void ZZZ::PAIR_G1mul(ECP *P,BIG e)
+{
+#ifdef USE_GLV_ZZZ   /* Note this method is patented */
+    int np,nn;
+    ECP Q;
+	FP cru;
+    BIG t,q;
+    BIG u[2];
+
+    BIG_rcopy(q,CURVE_Order);
+    glv(u,e);
+
+    //ECP_affine(P);
+    ECP_copy(&Q,P); ECP_affine(&Q);
+    FP_rcopy(&cru,CURVE_Cru);
+    FP_mul(&(Q.x),&(Q.x),&cru);
+
+    /* note that -a.B = a.(-B). Use a or -a depending on which is smaller */
+
+    np=BIG_nbits(u[0]);
+    BIG_modneg(t,u[0],q);
+    nn=BIG_nbits(t);
+    if (nn<np)
+    {
+        BIG_copy(u[0],t);
+        ECP_neg(P);
+    }
+
+    np=BIG_nbits(u[1]);
+    BIG_modneg(t,u[1],q);
+    nn=BIG_nbits(t);
+    if (nn<np)
+    {
+        BIG_copy(u[1],t);
+        ECP_neg(&Q);
+    }
+    BIG_norm(u[0]);
+    BIG_norm(u[1]);    
+    ECP_mul2(P,&Q,u[0],u[1]);
+
+#else
+    ECP_mul(P,e);
+#endif
+}
+
+/* Multiply P by e in group G2 */
+void ZZZ::PAIR_G2mul(ECP4 *P,BIG e)
+{
+#ifdef USE_GS_G2_ZZZ   /* Well I didn't patent it :) */
+    int i,np,nn;
+    ECP4 Q[8];
+    FP2 X[3];
+    BIG x,y,u[8];
+
+	ECP4_frob_constants(X);
+
+    BIG_rcopy(y,CURVE_Order);
+    gs(u,e);
+
+    //ECP4_affine(P);
+
+    ECP4_copy(&Q[0],P);
+    for (i=1; i<8; i++)
+    {
+        ECP4_copy(&Q[i],&Q[i-1]);
+        ECP4_frob(&Q[i],X,1);
+    }
+
+    for (i=0; i<8; i++)
+    {
+        np=BIG_nbits(u[i]);
+        BIG_modneg(x,u[i],y);
+        nn=BIG_nbits(x);
+        if (nn<np)
+        {
+            BIG_copy(u[i],x);
+            ECP4_neg(&Q[i]);
+        }
+        BIG_norm(u[i]);     
+		//ECP4_affine(&Q[i]);
+    }
+
+    ECP4_mul8(P,Q,u);
+
+#else
+    ECP4_mul(P,e);
+#endif
+}
+
+/* f=f^e */
+void ZZZ::PAIR_GTpow(FP24 *f,BIG e)
+{
+#ifdef USE_GS_GT_ZZZ   /* Note that this option requires a lot of RAM! Maybe better to use compressed XTR method, see FP8.c */
+    int i,np,nn;
+    FP24 g[8];
+    FP2 X;
+    BIG t,q;
+	FP fx,fy;
+    BIG u[8];
+
+    FP_rcopy(&fx,Fra);
+    FP_rcopy(&fy,Frb);
+    FP2_from_FPs(&X,&fx,&fy);
+
+    BIG_rcopy(q,CURVE_Order);
+    gs(u,e);
+
+    FP24_copy(&g[0],f);
+    for (i=1; i<8; i++)
+    {
+        FP24_copy(&g[i],&g[i-1]);
+        FP24_frob(&g[i],&X,1);
+    }
+
+    for (i=0; i<8; i++)
+    {
+        np=BIG_nbits(u[i]);
+        BIG_modneg(t,u[i],q);
+        nn=BIG_nbits(t);
+        if (nn<np)
+        {
+            BIG_copy(u[i],t);
+            FP24_conj(&g[i],&g[i]);
+        }
+        BIG_norm(u[i]);        
+    }
+    FP24_pow8(f,g,u);
+
+#else
+    FP24_pow(f,f,e);
+#endif
+}
+
+/* test group membership test - no longer needed */
+/* with GT-Strong curve, now only check that m!=1, conj(m)*m==1, and m.m^{p^4}=m^{p^2} */
+
+/*
+int PAIR_GTmember(FP24 *m)
+{
+	BIG a,b;
+	FP2 X;
+	FP24 r,w;
+	if (FP24_isunity(m)) return 0;
+	FP24_conj(&r,m);
+	FP24_mul(&r,m);
+	if (!FP24_isunity(&r)) return 0;
+
+	BIG_rcopy(a,CURVE_Fra);
+	BIG_rcopy(b,CURVE_Frb);
+	FP2_from_BIGs(&X,a,b);
+
+
+	FP24_copy(&r,m); FP24_frob(&r,&X); FP24_frob(&r,&X);
+	FP24_copy(&w,&r); FP24_frob(&w,&X); FP24_frob(&w,&X);
+	FP24_mul(&w,m);
+
+
+#ifndef GT_STRONG
+	if (!FP24_equals(&w,&r)) return 0;
+
+	BIG_rcopy(a,CURVE_Bnx);
+
+	FP24_copy(&r,m); FP24_pow(&w,&r,a); FP24_pow(&w,&w,a);
+	FP24_sqr(&r,&w); FP24_mul(&r,&w); FP24_sqr(&r,&r);
+
+	FP24_copy(&w,m); FP24_frob(&w,&X);
+ #endif
+
+	return FP24_equals(&w,&r);
+}
+
+*/
+
+
+#ifdef HAS_MAIN
+
+using namespace std;
+using namespace ZZZ;
+
+
+// g++ -O2 pair192_BLS24.cpp ecp4_BLS24.cpp fp24_BLS24.cpp fp8_BLS24.cpp fp4_BLS24.cpp fp2_BLS24.cpp ecp_BLS24.cpp fp_BLS24.cpp big_XXX.cpp rom_curve_BLS24.cpp rom_field_BLS24.cpp rand.cpp hash.cpp oct.cpp -o pair192_BLS24.exe
+
+int main()
+{
+    int i;
+    char byt[32];
+    csprng rng;
+    BIG xa,xb,ya,yb,w,a,b,t1,q,u[2],v[4],m,r,xx,x2,x4,p;
+    ECP4 P,G;
+    ECP Q,R;
+    FP24 g,gp;
+    FP8 t,c,cp,cpm1,cpm2;
+	FP4 X,Y;
+    FP2 x,y,f,Aa,Bb;
+	FP cru;
+
+	for (i=0;i<32;i++)
+		byt[i]=i+9;
+	RAND_seed(&rng,32,byt);
+
+	BIG_rcopy(r,CURVE_Order);
+	BIG_rcopy(p,Modulus);
+
+
+    BIG_rcopy(xa,CURVE_Gx);
+    BIG_rcopy(ya,CURVE_Gy);
+
+    ECP_set(&Q,xa,ya);
+    if (Q.inf) printf("Failed to set - point not on curve\n");
+    else printf("G1 set success\n");
+
+    printf("Q= ");
+    ECP_output(&Q);
+    printf("\n");
+
+	ECP4_generator(&P);
+
+    if (P.inf) printf("Failed to set - point not on curve\n");
+    else printf("G2 set success\n");
+
+    BIG_rcopy(a,Fra);
+    BIG_rcopy(b,Frb);
+    FP2_from_BIGs(&f,a,b);
+
+
+//exit(0);
+
+    PAIR_ate(&g,&P,&Q);
+
+	printf("gb= ");
+    FP24_output(&g);
+    printf("\n");
+    PAIR_fexp(&g);
+
+    printf("g= ");
+    FP24_output(&g);
+    printf("\n");
+
+	//FP24_pow(&g,&g,r);
+
+   // printf("g^r= ");
+    //FP24_output(&g);
+    //printf("\n");
+
+	ECP_copy(&R,&Q);
+	ECP4_copy(&G,&P);
+
+	ECP4_dbl(&G);
+	ECP_dbl(&R);
+	ECP_affine(&R);
+
+    PAIR_ate(&g,&G,&Q);
+    PAIR_fexp(&g);
+
+    printf("g1= ");
+    FP24_output(&g);
+    printf("\n");
+
+    PAIR_ate(&g,&P,&R);
+    PAIR_fexp(&g);
+
+    printf("g2= ");
+    FP24_output(&g);
+    printf("\n");
+
+
+	PAIR_G1mul(&Q,r);
+	printf("rQ= ");ECP_output(&Q); printf("\n");
+
+	PAIR_G2mul(&P,r);
+	printf("rP= ");ECP4_output(&P); printf("\n");
+
+	//PAIR_GTpow(&g,r);
+	//printf("g^r= ");FP24_output(&g); printf("\n");
+
+
+	BIG_randomnum(w,r,&rng);
+
+	FP24_copy(&gp,&g);
+
+	PAIR_GTpow(&g,w);
+
+	FP24_trace(&t,&g);
+
+	printf("g^r=  ");FP8_output(&t); printf("\n");
+
+	FP24_compow(&t,&gp,w,r);
+
+	printf("t(g)= "); FP8_output(&t); printf("\n");
+
+//    PAIR_ate(&g,&P,&R);
+//    PAIR_fexp(&g);
+
+//    printf("g= ");
+//    FP24_output(&g);
+//    printf("\n");
+
+//	PAIR_GTpow(&g,xa);
+}
+
+#endif
diff --git a/version3/cpp/pair192.h b/version3/cpp/pair192.h
new file mode 100644
index 0000000..09baec4
--- /dev/null
+++ b/version3/cpp/pair192.h
@@ -0,0 +1,80 @@
+#ifndef PAIR192_ZZZ_H
+#define PAIR192_ZZZ_H
+
+#include "fp24_YYY.h"
+#include "ecp4_ZZZ.h"
+#include "ecp_ZZZ.h"
+
+using namespace amcl;
+
+namespace ZZZ {
+/* Pairing constants */
+
+extern const XXX::BIG CURVE_Bnx; /**< BN curve x parameter */
+extern const XXX::BIG CURVE_Cru; /**< BN curve Cube Root of Unity */
+
+extern const XXX::BIG CURVE_W[2];	 /**< BN curve constant for GLV decomposition */
+extern const XXX::BIG CURVE_SB[2][2]; /**< BN curve constant for GLV decomposition */
+extern const XXX::BIG CURVE_WB[4];	 /**< BN curve constant for GS decomposition */
+extern const XXX::BIG CURVE_BB[4][4]; /**< BN curve constant for GS decomposition */
+
+/* Pairing function prototypes */
+/**	@brief Calculate Miller loop for Optimal ATE pairing e(P,Q)
+ *
+	@param r FP24 result of the pairing calculation e(P,Q)
+	@param P ECP4 instance, an element of G2
+	@param Q ECP instance, an element of G1
+
+ */
+extern void PAIR_ate(YYY::FP24 *r,ECP4 *P,ECP *Q);
+/**	@brief Calculate Miller loop for Optimal ATE double-pairing e(P,Q).e(R,S)
+ *
+	Faster than calculating two separate pairings
+	@param r FP24 result of the pairing calculation e(P,Q).e(R,S), an element of GT
+	@param P ECP4 instance, an element of G2
+	@param Q ECP instance, an element of G1
+	@param R ECP4 instance, an element of G2
+	@param S ECP instance, an element of G1
+ */
+extern void PAIR_double_ate(YYY::FP24 *r,ECP4 *P,ECP *Q,ECP4 *R,ECP *S);
+/**	@brief Final exponentiation of pairing, converts output of Miller loop to element in GT
+ *
+	Here p is the internal modulus, and r is the group order
+	@param x FP24, on exit = x^((p^12-1)/r)
+ */
+extern void PAIR_fexp(YYY::FP24 *x);
+/**	@brief Fast point multiplication of a member of the group G1 by a BIG number
+ *
+	May exploit endomorphism for speed.
+	@param Q ECP member of G1.
+	@param b BIG multiplier
+
+ */
+extern void PAIR_G1mul(ECP *Q,XXX::BIG b);
+/**	@brief Fast point multiplication of a member of the group G2 by a BIG number
+ *
+	May exploit endomorphism for speed.
+	@param P ECP4 member of G1.
+	@param b BIG multiplier
+
+ */
+extern void PAIR_G2mul(ECP4 *P,XXX::BIG b);
+/**	@brief Fast raising of a member of GT to a BIG power
+ *
+	May exploit endomorphism for speed.
+	@param x FP24 member of GT.
+	@param b BIG exponent
+
+ */
+extern void PAIR_GTpow(YYY::FP24 *x,XXX::BIG b);
+/**	@brief Tests FP24 for membership of GT
+ *
+	@param x FP24 instance
+	@return 1 if x is in GT, else return 0
+
+ */
+extern int PAIR_GTmember(YYY::FP24 *x);
+
+}
+
+#endif
diff --git a/version3/cpp/pair256.cpp b/version3/cpp/pair256.cpp
new file mode 100644
index 0000000..0c2aa57
--- /dev/null
+++ b/version3/cpp/pair256.cpp
@@ -0,0 +1,878 @@
+/*
+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.
+*/
+
+/* AMCL BLS Curve pairing functions */
+
+//#define HAS_MAIN
+
+#include "pair256_ZZZ.h"
+
+using namespace XXX;
+using namespace YYY;
+
+namespace ZZZ {
+	static void PAIR_line(FP48 *,ECP8 *,ECP8 *,FP *,FP *);
+	static void glv(BIG u[2],BIG);
+	static void gs(BIG u[4],BIG);
+}
+
+/* Line function */
+static void ZZZ::PAIR_line(FP48 *v,ECP8 *A,ECP8 *B,FP *Qx,FP *Qy)
+{
+	//FP2 t;
+
+	FP8 X1,Y1,T1,T2;
+	FP8 XX,YY,ZZ,YZ;
+    FP16 a,b,c;
+
+	if (A==B)
+    {
+        /* doubling */
+ 		FP8_copy(&XX,&(A->x));	//FP8 XX=new FP8(A.getx());  //X
+		FP8_copy(&YY,&(A->y));	//FP8 YY=new FP8(A.gety());  //Y
+		FP8_copy(&ZZ,&(A->z));	//FP8 ZZ=new FP8(A.getz());  //Z
+
+
+		FP8_copy(&YZ,&YY);		//FP8 YZ=new FP8(YY);        //Y 
+		FP8_mul(&YZ,&YZ,&ZZ);		//YZ.mul(ZZ);                //YZ
+		FP8_sqr(&XX,&XX);		//XX.sqr();	               //X^2
+		FP8_sqr(&YY,&YY);		//YY.sqr();	               //Y^2
+		FP8_sqr(&ZZ,&ZZ);		//ZZ.sqr();			       //Z^2
+			
+		FP8_imul(&YZ,&YZ,4);	//YZ.imul(4);
+		FP8_neg(&YZ,&YZ);		//YZ.neg(); 
+		FP8_norm(&YZ);			//YZ.norm();       //-4YZ
+
+		FP8_imul(&XX,&XX,6);					//6X^2
+		//FP2_from_FP(&t,Qx);
+		FP8_tmul(&XX,&XX,Qx);	               //6X^2.Xs
+
+		FP8_imul(&ZZ,&ZZ,3*CURVE_B_I);	//3Bz^2 
+		//FP2_from_FP(&t,Qy);
+		FP8_tmul(&YZ,&YZ,Qy);	//-4YZ.Ys
+
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+		FP8_div_2i(&ZZ);		//6(b/i)z^2
+#endif
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+		FP8_times_i(&ZZ);
+		FP8_add(&ZZ,&ZZ,&ZZ);  // 6biz^2
+		FP8_times_i(&YZ);
+		FP8_norm(&YZ);	
+#endif
+		FP8_norm(&ZZ);			// 6bi.Z^2 
+
+		FP8_add(&YY,&YY,&YY);	// 2y^2
+		FP8_sub(&ZZ,&ZZ,&YY);	// 
+		FP8_norm(&ZZ);			// 6b.Z^2-2Y^2
+
+		FP16_from_FP8s(&a,&YZ,&ZZ); // -4YZ.Ys | 6b.Z^2-2Y^2 | 6X^2.Xs 
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+		FP16_from_FP8(&b,&XX);	
+		FP16_zero(&c);
+#endif
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+		FP16_zero(&b);
+		FP16_from_FP8H(&c,&XX);
+#endif
+
+		ECP8_dbl(A);				//A.dbl();
+    }
+    else
+    {
+        /* addition */
+
+		FP8_copy(&X1,&(A->x));		//FP8 X1=new FP8(A.getx());    // X1
+		FP8_copy(&Y1,&(A->y));		//FP8 Y1=new FP8(A.gety());    // Y1
+		FP8_copy(&T1,&(A->z));		//FP8 T1=new FP8(A.getz());    // Z1
+			
+		FP8_copy(&T2,&T1);		//FP8 T2=new FP8(A.getz());    // Z1
+
+		FP8_mul(&T1,&T1,&(B->y));	//T1.mul(B.gety());    // T1=Z1.Y2 
+		FP8_mul(&T2,&T2,&(B->x));	//T2.mul(B.getx());    // T2=Z1.X2
+
+		FP8_sub(&X1,&X1,&T2);		//X1.sub(T2); 
+		FP8_norm(&X1);				//X1.norm();  // X1=X1-Z1.X2
+		FP8_sub(&Y1,&Y1,&T1);		//Y1.sub(T1); 
+		FP8_norm(&Y1);				//Y1.norm();  // Y1=Y1-Z1.Y2
+
+		FP8_copy(&T1,&X1);			//T1.copy(X1);            // T1=X1-Z1.X2
+		//FP2_from_FP(&t,Qy);
+		FP8_tmul(&X1,&X1,Qy);		//X1.pmul(Qy);            // X1=(X1-Z1.X2).Ys
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+		FP8_times_i(&X1);
+		FP8_norm(&X1);
+#endif
+
+		FP8_mul(&T1,&T1,&(B->y));	//T1.mul(B.gety());       // T1=(X1-Z1.X2).Y2
+
+		FP8_copy(&T2,&Y1);			//T2.copy(Y1);            // T2=Y1-Z1.Y2
+		FP8_mul(&T2,&T2,&(B->x));	//T2.mul(B.getx());       // T2=(Y1-Z1.Y2).X2
+		FP8_sub(&T2,&T2,&T1);		//T2.sub(T1); 
+		FP8_norm(&T2);				//T2.norm();          // T2=(Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2
+		//FP2_from_FP(&t,Qx);
+		FP8_tmul(&Y1,&Y1,Qx);		//Y1.pmul(Qx);  
+		FP8_neg(&Y1,&Y1);			//Y1.neg(); 
+		FP8_norm(&Y1);				//Y1.norm(); // Y1=-(Y1-Z1.Y2).Xs
+
+		FP16_from_FP8s(&a,&X1,&T2);	// (X1-Z1.X2).Ys  |  (Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2  | - (Y1-Z1.Y2).Xs
+#if SEXTIC_TWIST_ZZZ==D_TYPE
+		FP16_from_FP8(&b,&Y1);		//b=new FP4(Y1);
+		FP16_zero(&c);
+#endif
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+		FP16_zero(&b);
+		FP16_from_FP8H(&c,&Y1);		//b=new FP4(Y1);
+#endif
+		ECP8_add(A,B);			// A.add(B);
+    }
+
+
+    FP48_from_FP16s(v,&a,&b,&c);
+}
+
+/* Optimal R-ate pairing r=e(P,Q) */
+void ZZZ::PAIR_ate(FP48 *r,ECP8 *P1,ECP *Q1)
+{
+    BIG x,n,n3;
+	FP Qx,Qy;
+    int i,j,nb,bt;
+    ECP8 A,NP,P;
+	ECP Q;
+    FP48 lv;
+
+    BIG_rcopy(x,CURVE_Bnx);
+
+    BIG_copy(n,x);
+
+    //BIG_norm(n);
+	BIG_pmul(n3,n,3);
+	BIG_norm(n3);
+
+	ECP8_copy(&P,P1);
+	ECP_copy(&Q,Q1);
+
+	ECP8_affine(&P);
+	ECP_affine(&Q);
+
+
+    FP_copy(&Qx,&(Q.x));
+    FP_copy(&Qy,&(Q.y));
+
+    ECP8_copy(&A,&P);
+
+	ECP8_copy(&NP,&P); ECP8_neg(&NP);
+
+    FP48_one(r);
+    nb=BIG_nbits(n3);  // n3
+
+	j=0;
+    /* Main Miller Loop */
+    for (i=nb-2; i>=1; i--)
+    {
+		j++;
+		FP48_sqr(r,r);
+        PAIR_line(&lv,&A,&A,&Qx,&Qy);
+        FP48_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+//printf("r= "); FP48_output(r); printf("\n");
+//if (j>3) exit(0);
+		bt= BIG_bit(n3,i)-BIG_bit(n,i);  // BIG_bit(n,i); 
+        if (bt==1)
+        {
+//printf("bt=1\n");
+            PAIR_line(&lv,&A,&P,&Qx,&Qy);
+            FP48_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+        }
+		if (bt==-1)
+		{
+//printf("bt=-1\n");
+			//ECP8_neg(P);
+            PAIR_line(&lv,&A,&NP,&Qx,&Qy);
+            FP48_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+			//ECP8_neg(P);
+		}
+
+    }
+
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+    FP48_conj(r,r);
+#endif
+
+}
+
+/* Optimal R-ate double pairing e(P,Q).e(R,S) */
+void ZZZ::PAIR_double_ate(FP48 *r,ECP8 *P1,ECP *Q1,ECP8 *R1,ECP *S1)
+{
+    BIG x,n,n3;
+	FP Qx,Qy,Sx,Sy;
+    int i,nb,bt;
+    ECP8 A,B,NP,NR,P,R;
+	ECP Q,S;
+    FP48 lv;
+
+    BIG_rcopy(x,CURVE_Bnx);
+    BIG_copy(n,x);
+
+    //BIG_norm(n);
+	BIG_pmul(n3,n,3);
+	BIG_norm(n3);
+
+	ECP8_copy(&P,P1);
+	ECP_copy(&Q,Q1);
+
+	ECP8_affine(&P);
+	ECP_affine(&Q);
+
+	ECP8_copy(&R,R1);
+	ECP_copy(&S,S1);
+
+	ECP8_affine(&R);
+	ECP_affine(&S);
+
+
+    FP_copy(&Qx,&(Q.x));
+    FP_copy(&Qy,&(Q.y));
+
+    FP_copy(&Sx,&(S.x));
+    FP_copy(&Sy,&(S.y));
+
+    ECP8_copy(&A,&P);
+    ECP8_copy(&B,&R);
+
+	ECP8_copy(&NP,&P); ECP8_neg(&NP);
+	ECP8_copy(&NR,&R); ECP8_neg(&NR);
+
+
+    FP48_one(r);
+    nb=BIG_nbits(n3);
+
+    /* Main Miller Loop */
+    for (i=nb-2; i>=1; i--)
+    {
+        FP48_sqr(r,r);
+        PAIR_line(&lv,&A,&A,&Qx,&Qy);
+        FP48_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+
+        PAIR_line(&lv,&B,&B,&Sx,&Sy);
+        FP48_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+
+		bt=BIG_bit(n3,i)-BIG_bit(n,i); // bt=BIG_bit(n,i);
+        if (bt==1)
+        {
+            PAIR_line(&lv,&A,&P,&Qx,&Qy);
+            FP48_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+
+            PAIR_line(&lv,&B,&R,&Sx,&Sy);
+            FP48_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+        }
+		if (bt==-1)
+		{
+			//ECP8_neg(P); 
+            PAIR_line(&lv,&A,&NP,&Qx,&Qy);
+            FP48_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+			//ECP8_neg(P); 
+			//ECP8_neg(R);
+            PAIR_line(&lv,&B,&NR,&Sx,&Sy);
+            FP48_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+			//ECP8_neg(R);
+		}
+	}
+
+
+
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+    FP48_conj(r,r);
+#endif
+
+}
+
+/* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */
+
+void ZZZ::PAIR_fexp(FP48 *r)
+{
+    FP2 X;
+    BIG x;
+	FP a,b;
+    FP48 t1,t2,t3,t7;  
+
+    BIG_rcopy(x,CURVE_Bnx);
+    FP_rcopy(&a,Fra);
+    FP_rcopy(&b,Frb);
+    FP2_from_FPs(&X,&a,&b);
+
+    /* Easy part of final exp - r^(p^24-1)(p^8+1)*/
+
+    FP48_inv(&t7,r);
+    FP48_conj(r,r);
+
+    FP48_mul(r,&t7);
+    FP48_copy(&t7,r);
+
+    FP48_frob(r,&X,8);
+
+    FP48_mul(r,&t7);
+
+
+// Ghamman & Fouotsa Method for hard part of fexp - r^e1 . r^p^e2 . r^p^2^e3 ..
+
+// e0 = u^17 - 2*u^16 + u^15 - u^9 + 2*u^8 - u^7 + 3	// .p^0
+// e1 = u^16 - 2*u^15 + u^14 - u^8 + 2*u^7 - u^6		// .p^1
+// e2 = u^15 - 2*u^14 + u^13 - u^7 + 2*u^6 - u^5
+// e3 = u^14 - 2*u^13 + u^12 - u^6 + 2*u^5 - u^4
+// e4 = u^13 - 2*u^12 + u^11 - u^5 + 2*u^4 - u^3
+// e5 = u^12 - 2*u^11 + u^10 - u^4 + 2*u^3 - u^2
+// e6 = u^11 - 2*u^10 + u^9 - u^3 + 2*u^2 - u
+// e7 =  u^10 - 2*u^9 + u^8 - u^2 + 2*u - 1
+// e8 =  u^9 - 2*u^8 + u^7
+// e9 =  u^8 - 2*u^7 + u^6
+// e10 = u^7 - 2*u^6 + u^5
+// e11 = u^6 - 2*u^5 + u^4
+// e12 = u^5 - 2*u^4 + u^3
+// e13 = u^4 - 2*u^3 + u^2
+// e14 = u^3 - 2*u^2 + u
+// e15 = u^2 - 2*u + 1
+
+// e15 = u^2-2*u+1
+// e14 = u.e15
+// e13 = u.e14
+// e12 = u.e13
+// e11 = u.e12
+// e10 = u.e11
+// e9 =  u.e10
+// e8 =  u.e9
+// e7 =  u.e8 - e15
+// e6 =  u.e7
+// e5 =  u.e6
+// e4 =  u.e5
+// e3 =  u.e4
+// e2 =  u.e3
+// e1 =  u.e2
+// e0 =  u.e1 + 3
+
+// f^e0.f^e1^p.f^e2^p^2.. .. f^e14^p^14.f^e15^p^15
+
+	FP48_usqr(&t7,r);			// t7=f^2
+	FP48_pow(&t1,&t7,x);		// t1=f^2u
+
+	BIG_fshr(x,1);
+	FP48_pow(&t2,&t1,x);		// t2=f^2u^(u/2) =  f^u^2
+	BIG_fshl(x,1);				// x must be even
+
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP48_conj(&t1,&t1);
+#endif
+
+	FP48_conj(&t3,&t1);		// t3=f^-2u
+	FP48_mul(&t2,&t3);		// t2=f^u^2.f^-2u
+	FP48_mul(&t2,r);		// t2=f^u^2.f^-2u.f = f^(u^2-2u+1) = f^e15
+
+	FP48_mul(r,&t7);		// f^3
+
+	FP48_pow(&t1,&t2,x);	// f^e15^u = f^(u.e15) = f^(u^3-2u^2+u) = f^(e14)
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP48_conj(&t1,&t1);
+#endif
+	FP48_copy(&t3,&t1);
+	FP48_frob(&t3,&X,14);	// f^(u^3-2u^2+u)^p^14
+	FP48_mul(r,&t3);		// f^3.f^(u^3-2u^2+u)^p^14
+
+	FP48_pow(&t1,&t1,x);	// f^(u.e14) = f^(u^4-2u^3+u^2) =  f^(e13)
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP48_conj(&t1,&t1);
+#endif
+	FP48_copy(&t3,&t1);
+	FP48_frob(&t3,&X,13);	// f^(e13)^p^13
+	FP48_mul(r,&t3);		// f^3.f^(u^3-2u^2+u)^p^14.f^(u^4-2u^3+u^2)^p^13
+
+	FP48_pow(&t1,&t1,x);	// f^(u.e13)
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP48_conj(&t1,&t1);
+#endif
+	FP48_copy(&t3,&t1);
+	FP48_frob(&t3,&X,12);	// f^(e12)^p^12
+	FP48_mul(r,&t3);		
+
+	FP48_pow(&t1,&t1,x);	// f^(u.e12)
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP48_conj(&t1,&t1);
+#endif
+	FP48_copy(&t3,&t1);
+	FP48_frob(&t3,&X,11);	// f^(e11)^p^11
+	FP48_mul(r,&t3);		
+
+	FP48_pow(&t1,&t1,x);	// f^(u.e11)
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP48_conj(&t1,&t1);
+#endif
+	FP48_copy(&t3,&t1);
+	FP48_frob(&t3,&X,10);	// f^(e10)^p^10
+	FP48_mul(r,&t3);		
+
+	FP48_pow(&t1,&t1,x);	// f^(u.e10)
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP48_conj(&t1,&t1);
+#endif
+	FP48_copy(&t3,&t1);
+	FP48_frob(&t3,&X,9);	// f^(e9)^p^9
+	FP48_mul(r,&t3);		
+
+	FP48_pow(&t1,&t1,x);	// f^(u.e9)
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP48_conj(&t1,&t1);
+#endif
+	FP48_copy(&t3,&t1);
+	FP48_frob(&t3,&X,8);	// f^(e8)^p^8
+	FP48_mul(r,&t3);		
+
+	FP48_pow(&t1,&t1,x);	// f^(u.e8)
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP48_conj(&t1,&t1);
+#endif
+	FP48_conj(&t3,&t2);
+	FP48_mul(&t1,&t3);  // f^(u.e8).f^-e15
+	FP48_copy(&t3,&t1);
+	FP48_frob(&t3,&X,7);	// f^(e7)^p^7
+	FP48_mul(r,&t3);		
+
+	FP48_pow(&t1,&t1,x);	// f^(u.e7)
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP48_conj(&t1,&t1);
+#endif
+	FP48_copy(&t3,&t1);
+	FP48_frob(&t3,&X,6);	// f^(e6)^p^6
+	FP48_mul(r,&t3);		
+
+	FP48_pow(&t1,&t1,x);	// f^(u.e6)
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP48_conj(&t1,&t1);
+#endif
+	FP48_copy(&t3,&t1);
+	FP48_frob(&t3,&X,5);	// f^(e5)^p^5
+	FP48_mul(r,&t3);		
+
+	FP48_pow(&t1,&t1,x);	// f^(u.e5)
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP48_conj(&t1,&t1);
+#endif
+	FP48_copy(&t3,&t1);
+	FP48_frob(&t3,&X,4);	// f^(e4)^p^4
+	FP48_mul(r,&t3);		
+
+	FP48_pow(&t1,&t1,x);	// f^(u.e4)
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP48_conj(&t1,&t1);
+#endif
+	FP48_copy(&t3,&t1);
+	FP48_frob(&t3,&X,3);	// f^(e3)^p^3
+	FP48_mul(r,&t3);		
+
+	FP48_pow(&t1,&t1,x);	// f^(u.e3)
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP48_conj(&t1,&t1);
+#endif
+	FP48_copy(&t3,&t1);
+	FP48_frob(&t3,&X,2);	// f^(e2)^p^2
+	FP48_mul(r,&t3);		
+
+	FP48_pow(&t1,&t1,x);	// f^(u.e2)
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP48_conj(&t1,&t1);
+#endif
+	FP48_copy(&t3,&t1);
+	FP48_frob(&t3,&X,1);	// f^(e1)^p^1
+	FP48_mul(r,&t3);		
+
+	FP48_pow(&t1,&t1,x);	// f^(u.e1)
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	FP48_conj(&t1,&t1);
+#endif
+	FP48_mul(r,&t1);		// r.f^e0		
+
+	FP48_frob(&t2,&X,15);	// f^(e15.p^15)
+	FP48_mul(r,&t2);
+
+
+	FP48_reduce(r);
+
+}
+
+#ifdef USE_GLV_ZZZ
+/* GLV method */
+static void ZZZ::glv(BIG u[2],BIG e)
+{
+
+// -(x^8).P = (Beta.x,y)
+
+    BIG x,x2,q;
+    BIG_rcopy(x,CURVE_Bnx);
+    
+	BIG_smul(x2,x,x);
+	BIG_smul(x,x2,x2);
+	BIG_smul(x2,x,x);
+
+    BIG_copy(u[0],e);
+    BIG_mod(u[0],x2);
+    BIG_copy(u[1],e);
+    BIG_sdiv(u[1],x2);
+
+    BIG_rcopy(q,CURVE_Order);
+    BIG_sub(u[1],q,u[1]);
+
+
+    return;
+}
+#endif // USE_GLV
+
+/* Galbraith & Scott Method */
+static void ZZZ::gs(BIG u[16],BIG e)
+{
+    int i;
+
+    BIG x,w,q;
+	BIG_rcopy(q,CURVE_Order);
+    BIG_rcopy(x,CURVE_Bnx);
+    BIG_copy(w,e);
+
+    for (i=0; i<15; i++)
+    {
+        BIG_copy(u[i],w);
+        BIG_mod(u[i],x);
+        BIG_sdiv(w,x);
+    }
+	BIG_copy(u[15],w);
+
+/*  */
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+	BIG_modneg(u[1],u[1],q);
+	BIG_modneg(u[3],u[3],q);
+	BIG_modneg(u[5],u[5],q);
+	BIG_modneg(u[7],u[7],q);
+	BIG_modneg(u[9],u[9],q);
+	BIG_modneg(u[11],u[11],q);
+	BIG_modneg(u[13],u[13],q);
+	BIG_modneg(u[15],u[15],q);
+#endif
+
+
+    return;
+}
+
+/* Multiply P by e in group G1 */
+void ZZZ::PAIR_G1mul(ECP *P,BIG e)
+{
+#ifdef USE_GLV_ZZZ   /* Note this method is patented */
+    int np,nn;
+    ECP Q;
+	FP cru;
+    BIG t,q;
+    BIG u[2];
+
+    BIG_rcopy(q,CURVE_Order);
+    glv(u,e);
+
+    //ECP_affine(P);
+    ECP_copy(&Q,P); ECP_affine(&Q);
+    FP_rcopy(&cru,CURVE_Cru);
+    FP_mul(&(Q.x),&(Q.x),&cru);
+
+    /* note that -a.B = a.(-B). Use a or -a depending on which is smaller */
+
+    np=BIG_nbits(u[0]);
+    BIG_modneg(t,u[0],q);
+    nn=BIG_nbits(t);
+    if (nn<np)
+    {
+        BIG_copy(u[0],t);
+        ECP_neg(P);
+    }
+
+    np=BIG_nbits(u[1]);
+    BIG_modneg(t,u[1],q);
+    nn=BIG_nbits(t);
+    if (nn<np)
+    {
+        BIG_copy(u[1],t);
+        ECP_neg(&Q);
+    }
+    BIG_norm(u[0]);
+    BIG_norm(u[1]);    
+    ECP_mul2(P,&Q,u[0],u[1]);
+
+#else
+    ECP_mul(P,e);
+#endif
+}
+
+/* Multiply P by e in group G2 */
+void ZZZ::PAIR_G2mul(ECP8 *P,BIG e)
+{
+#ifdef USE_GS_G2_ZZZ   /* Well I didn't patent it :) */
+    int i,np,nn;
+    ECP8 Q[16];
+    FP2 X[3];
+    BIG x,y,u[16];
+
+	ECP8_frob_constants(X);
+
+    BIG_rcopy(y,CURVE_Order);
+    gs(u,e);
+
+    //ECP8_affine(P);
+
+    ECP8_copy(&Q[0],P);
+    for (i=1; i<16; i++)
+    {
+        ECP8_copy(&Q[i],&Q[i-1]);
+        ECP8_frob(&Q[i],X,1);
+    }
+
+    for (i=0; i<16; i++)
+    {
+        np=BIG_nbits(u[i]);
+        BIG_modneg(x,u[i],y);
+        nn=BIG_nbits(x);
+        if (nn<np)
+        {
+            BIG_copy(u[i],x);
+            ECP8_neg(&Q[i]);
+        }
+        BIG_norm(u[i]);   
+		//ECP8_affine(&Q[i]);
+    }
+
+    ECP8_mul16(P,Q,u);
+
+#else
+    ECP8_mul(P,e);
+#endif
+}
+
+/* f=f^e */
+void ZZZ::PAIR_GTpow(FP48 *f,BIG e)
+{
+#ifdef USE_GS_GT_ZZZ   /* Note that this option requires a lot of RAM! Maybe better to use compressed XTR method, see FP16.cpp */
+    int i,np,nn;
+    FP48 g[16];
+    FP2 X;
+    BIG t,q;
+	FP fx,fy;
+    BIG u[16];
+
+    FP_rcopy(&fx,Fra);
+    FP_rcopy(&fy,Frb);
+    FP2_from_FPs(&X,&fx,&fy);
+
+    BIG_rcopy(q,CURVE_Order);
+    gs(u,e);
+
+    FP48_copy(&g[0],f);
+    for (i=1; i<16; i++)
+    {
+        FP48_copy(&g[i],&g[i-1]);
+        FP48_frob(&g[i],&X,1);
+    }
+
+    for (i=0; i<16; i++)
+    {
+        np=BIG_nbits(u[i]);
+        BIG_modneg(t,u[i],q);
+        nn=BIG_nbits(t);
+        if (nn<np)
+        {
+            BIG_copy(u[i],t);
+            FP48_conj(&g[i],&g[i]);
+        }
+        BIG_norm(u[i]);
+    }
+    FP48_pow16(f,g,u);
+
+#else
+    FP48_pow(f,f,e);
+#endif
+}
+
+/* test group membership test - no longer needed */
+/* with GT-Strong curve, now only check that m!=1, conj(m)*m==1, and m.m^{p^4}=m^{p^2} */
+
+/*
+int PAIR_GTmember(FP48 *m)
+{
+	BIG a,b;
+	FP2 X;
+	FP48 r,w;
+	if (FP48_isunity(m)) return 0;
+	FP48_conj(&r,m);
+	FP48_mul(&r,m);
+	if (!FP48_isunity(&r)) return 0;
+
+	BIG_rcopy(a,CURVE_Fra);
+	BIG_rcopy(b,CURVE_Frb);
+	FP2_from_BIGs(&X,a,b);
+
+
+	FP48_copy(&r,m); FP48_frob(&r,&X); FP48_frob(&r,&X);
+	FP48_copy(&w,&r); FP48_frob(&w,&X); FP48_frob(&w,&X);
+	FP48_mul(&w,m);
+
+
+#ifndef GT_STRONG
+	if (!FP48_equals(&w,&r)) return 0;
+
+	BIG_rcopy(a,CURVE_Bnx);
+
+	FP48_copy(&r,m); FP48_pow(&w,&r,a); FP48_pow(&w,&w,a);
+	FP48_sqr(&r,&w); FP48_mul(&r,&w); FP48_sqr(&r,&r);
+
+	FP48_copy(&w,m); FP48_frob(&w,&X);
+ #endif
+
+	return FP48_equals(&w,&r);
+}
+
+*/
+
+
+#ifdef HAS_MAIN
+
+using namespace std;
+using namespace ZZZ;
+
+
+// g++ -O2 pair256_BLS48.cpp ecp8_BLS48.cpp fp48_BLS48.cpp fp16_BLS48.cpp fp8_BLS48.cpp fp4_BLS48.cpp fp2_BLS48.cpp ecp_BLS48.cpp fp_BLS48.cpp big_B560_29.cpp rom_curve_BLS48.cpp rom_field_BLS48.cpp rand.cpp hash.cpp oct.cpp -o pair256_BLS48.exe
+
+int main()
+{
+    int i;
+    char byt[32];
+    csprng rng;
+    BIG xa,xb,ya,yb,w,a,b,t1,q,u[2],v[4],m,r,xx,x2,x4,p;
+    ECP8 P,G;
+    ECP Q,R;
+    FP48 g,gp;
+    FP16 t,c,cp,cpm1,cpm2;
+	FP8 X,Y;
+    FP2 x,y,f,Aa,Bb;
+	FP cru;
+
+	for (i=0;i<32;i++)
+		byt[i]=i+9;
+	RAND_seed(&rng,32,byt);
+
+	BIG_rcopy(r,CURVE_Order);
+	BIG_rcopy(p,Modulus);
+
+
+    BIG_rcopy(xa,CURVE_Gx);
+    BIG_rcopy(ya,CURVE_Gy);
+
+    ECP_set(&Q,xa,ya);
+    if (Q.inf) printf("Failed to set - point not on curve\n");
+    else printf("G1 set success\n");
+
+    printf("Q= ");
+    ECP_output(&Q);
+    printf("\n");
+
+	ECP8_generator(&P);
+
+    if (P.inf) printf("Failed to set - point not on curve\n");
+    else printf("G2 set success\n");
+
+    BIG_rcopy(a,Fra);
+    BIG_rcopy(b,Frb);
+    FP2_from_BIGs(&f,a,b);
+
+
+//exit(0);
+
+    PAIR_ate(&g,&P,&Q);
+
+	printf("gb= ");
+    FP48_output(&g);
+    printf("\n");
+    PAIR_fexp(&g);
+
+    printf("g= ");
+    FP48_output(&g);
+    printf("\n");
+
+	//FP48_pow(&g,&g,r);
+
+   // printf("g^r= ");
+    //FP48_output(&g);
+    //printf("\n");
+
+	ECP_copy(&R,&Q);
+	ECP8_copy(&G,&P);
+
+	ECP8_dbl(&G);
+	ECP_dbl(&R);
+	ECP_affine(&R);
+
+    PAIR_ate(&g,&G,&Q);
+    PAIR_fexp(&g);
+
+    printf("g1= ");
+    FP48_output(&g);
+    printf("\n");
+
+    PAIR_ate(&g,&P,&R);
+    PAIR_fexp(&g);
+
+    printf("g2= ");
+    FP48_output(&g);
+    printf("\n");
+
+
+	PAIR_G1mul(&Q,r);
+	printf("rQ= ");ECP_output(&Q); printf("\n");
+
+	PAIR_G2mul(&P,r);
+	printf("rP= ");ECP8_output(&P); printf("\n");
+
+	//FP48_pow(&g,&g,r);
+	PAIR_GTpow(&g,r);
+	printf("g^r= ");FP48_output(&g); printf("\n");
+
+
+	BIG_randomnum(w,r,&rng);
+
+	FP48_copy(&gp,&g);
+
+	PAIR_GTpow(&g,w);
+
+	FP48_trace(&t,&g);
+
+	printf("g^r=  ");FP16_output(&t); printf("\n");
+
+	FP48_compow(&t,&gp,w,r);
+
+	printf("t(g)= "); FP16_output(&t); printf("\n");
+
+//    PAIR_ate(&g,&P,&R);
+//    PAIR_fexp(&g);
+
+//    printf("g= ");
+//    FP48_output(&g);
+//    printf("\n");
+
+//	PAIR_GTpow(&g,xa);
+}
+
+#endif
diff --git a/version3/cpp/pair256.h b/version3/cpp/pair256.h
new file mode 100644
index 0000000..353b30a
--- /dev/null
+++ b/version3/cpp/pair256.h
@@ -0,0 +1,80 @@
+#ifndef PAIR256_ZZZ_H
+#define PAIR256_ZZZ_H
+
+#include "fp48_YYY.h"
+#include "ecp8_ZZZ.h"
+#include "ecp_ZZZ.h"
+
+using namespace amcl;
+
+namespace ZZZ {
+/* Pairing constants */
+
+extern const XXX::BIG CURVE_Bnx; /**< BN curve x parameter */
+extern const XXX::BIG CURVE_Cru; /**< BN curve Cube Root of Unity */
+
+extern const XXX::BIG CURVE_W[2];	 /**< BN curve constant for GLV decomposition */
+extern const XXX::BIG CURVE_SB[2][2]; /**< BN curve constant for GLV decomposition */
+extern const XXX::BIG CURVE_WB[4];	 /**< BN curve constant for GS decomposition */
+extern const XXX::BIG CURVE_BB[4][4]; /**< BN curve constant for GS decomposition */
+
+/* Pairing function prototypes */
+/**	@brief Calculate Miller loop for Optimal ATE pairing e(P,Q)
+ *
+	@param r FP48 result of the pairing calculation e(P,Q)
+	@param P ECP8 instance, an element of G2
+	@param Q ECP instance, an element of G1
+
+ */
+extern void PAIR_ate(YYY::FP48 *r,ECP8 *P,ECP *Q);
+/**	@brief Calculate Miller loop for Optimal ATE double-pairing e(P,Q).e(R,S)
+ *
+	Faster than calculating two separate pairings
+	@param r FP48 result of the pairing calculation e(P,Q).e(R,S), an element of GT
+	@param P ECP8 instance, an element of G2
+	@param Q ECP instance, an element of G1
+	@param R ECP8 instance, an element of G2
+	@param S ECP instance, an element of G1
+ */
+extern void PAIR_double_ate(YYY::FP48 *r,ECP8 *P,ECP *Q,ECP8 *R,ECP *S);
+/**	@brief Final exponentiation of pairing, converts output of Miller loop to element in GT
+ *
+	Here p is the internal modulus, and r is the group order
+	@param x FP48, on exit = x^((p^12-1)/r)
+ */
+extern void PAIR_fexp(YYY::FP48 *x);
+/**	@brief Fast point multiplication of a member of the group G1 by a BIG number
+ *
+	May exploit endomorphism for speed.
+	@param Q ECP member of G1.
+	@param b BIG multiplier
+
+ */
+extern void PAIR_G1mul(ECP *Q,XXX::BIG b);
+/**	@brief Fast point multiplication of a member of the group G2 by a BIG number
+ *
+	May exploit endomorphism for speed.
+	@param P ECP8 member of G1.
+	@param b BIG multiplier
+
+ */
+extern void PAIR_G2mul(ECP8 *P,XXX::BIG b);
+/**	@brief Fast raising of a member of GT to a BIG power
+ *
+	May exploit endomorphism for speed.
+	@param x FP48 member of GT.
+	@param b BIG exponent
+
+ */
+extern void PAIR_GTpow(YYY::FP48 *x,XXX::BIG b);
+/**	@brief Tests FP48 for membership of GT
+ *
+	@param x FP48 instance
+	@return 1 if x is in GT, else return 0
+
+ */
+extern int PAIR_GTmember(YYY::FP48 *x);
+
+}
+
+#endif
diff --git a/version3/cpp/pbc_support.cpp b/version3/cpp/pbc_support.cpp
new file mode 100644
index 0000000..f80d080
--- /dev/null
+++ b/version3/cpp/pbc_support.cpp
@@ -0,0 +1,179 @@
+/*
+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.
+*/
+
+/* Symmetric crypto support functions Functions  */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "pbc_support.h"
+
+using namespace amcl;
+
+/* general purpose hash function w=hash(p|n|x|y) */
+void amcl::mhashit(int sha,int n,octet *x,octet *w)
+{
+    int i,c[4],hlen;
+    hash256 sha256;
+    hash512 sha512;
+    char hh[64];
+
+    switch (sha)
+    {
+    case SHA256:
+        HASH256_init(&sha256);
+        break;
+    case SHA384:
+        HASH384_init(&sha512);
+        break;
+    case SHA512:
+        HASH512_init(&sha512);
+        break;
+    }
+
+    hlen=sha;
+
+    if (n>0)
+    {
+        c[0]=(n>>24)&0xff;
+        c[1]=(n>>16)&0xff;
+        c[2]=(n>>8)&0xff;
+        c[3]=(n)&0xff;
+        for (i=0; i<4; i++)
+        {
+            switch(sha)
+            {
+            case SHA256:
+                HASH256_process(&sha256,c[i]);
+                break;
+            case SHA384:
+                HASH384_process(&sha512,c[i]);
+                break;
+            case SHA512:
+                HASH512_process(&sha512,c[i]);
+                break;
+            }
+        }
+    }
+
+    if (x!=NULL) for (i=0; i<x->len; i++)
+        {
+            switch(sha)
+            {
+            case SHA256:
+                HASH256_process(&sha256,x->val[i]);
+
+                break;
+            case SHA384:
+                HASH384_process(&sha512,x->val[i]);
+                break;
+            case SHA512:
+                HASH512_process(&sha512,x->val[i]);
+                break;
+            }
+        }
+
+    for (i=0; i<hlen; i++) hh[i]=0;
+    switch (sha)
+    {
+    case SHA256:
+        HASH256_hash(&sha256,hh);
+        break;
+    case SHA384:
+        HASH384_hash(&sha512,hh);
+        break;
+    case SHA512:
+        HASH512_hash(&sha512,hh);
+        break;
+    }
+
+    OCT_empty(w);
+
+    if (hlen>=w->max)
+        OCT_jbytes(w,hh,w->max);
+    else
+    {
+        OCT_jbyte(w,0,w->max-hlen);
+        OCT_jbytes(w,hh,hlen);
+    }
+}
+
+unsign32 amcl::today(void)
+{
+    /* return time in slots since epoch */
+    unsign32 ti=(unsign32)time(NULL);
+    return (uint32_t)(ti/(60*TIME_SLOT_MINUTES));
+}
+
+/* Hash the M-Pin transcript - new */
+
+void amcl::HASH_ALL(int sha,octet *HID,octet *xID,octet *xCID,octet *SEC,octet *Y,octet *R,octet *W,octet *H)
+{
+    char t[1284];   // assumes max modulus of 1024-bits
+    octet T= {0,sizeof(t),t};
+
+    OCT_joctet(&T,HID);
+    if (xCID!=NULL) OCT_joctet(&T,xCID);
+    else OCT_joctet(&T,xID);
+    OCT_joctet(&T,SEC);
+    OCT_joctet(&T,Y);
+    OCT_joctet(&T,R);
+    OCT_joctet(&T,W);
+
+    mhashit(sha,0,&T,H);
+}
+
+void amcl::HASH_ID(int sha,octet *ID,octet *HID)
+{
+    mhashit(sha,0,ID,HID);
+}
+
+unsign32 amcl::GET_TIME(void)
+{
+    return (unsign32)time(NULL);
+}
+
+/* AES-GCM Encryption of octets, K is key, H is header,
+   P is plaintext, C is ciphertext, T is authentication tag */
+void amcl::AES_GCM_ENCRYPT(octet *K,octet *IV,octet *H,octet *P,octet *C,octet *T)
+{
+    gcm g;
+    GCM_init(&g,K->len,K->val,IV->len,IV->val);
+    GCM_add_header(&g,H->val,H->len);
+    GCM_add_plain(&g,C->val,P->val,P->len);
+    C->len=P->len;
+    GCM_finish(&g,T->val);
+    T->len=16;
+}
+
+/* AES-GCM Decryption of octets, K is key, H is header,
+   P is plaintext, C is ciphertext, T is authentication tag */
+void amcl::AES_GCM_DECRYPT(octet *K,octet *IV,octet *H,octet *C,octet *P,octet *T)
+{
+    gcm g;
+    GCM_init(&g,K->len,K->val,IV->len,IV->val);
+    GCM_add_header(&g,H->val,H->len);
+    GCM_add_cipher(&g,P->val,C->val,C->len);
+    P->len=C->len;
+    GCM_finish(&g,T->val);
+    T->len=16;
+}
+
diff --git a/version3/cpp/pbc_support.h b/version3/cpp/pbc_support.h
new file mode 100644
index 0000000..1942d39
--- /dev/null
+++ b/version3/cpp/pbc_support.h
@@ -0,0 +1,66 @@
+#ifndef MPIN_SUPPORT_H
+#define MPIN_SUPPORT_H
+
+#include "amcl.h"
+
+namespace amcl {
+
+#define TIME_SLOT_MINUTES 1440  /**< Time Slot = 1 day */
+
+extern void mhashit(int ,int ,octet *,octet *);
+
+
+/**	@brief Supply today's date as days from the epoch
+ *
+	@return today's date, as number of days elapsed since the epoch
+ */
+unsign32 today(void);
+/** @brief Hash the session transcript
+ 	@param h is the hash type
+	@param I is the hashed input client ID = H(ID)
+	@param U is the client output = x.H(ID)
+	@param CU is the client output = x.(H(ID)+H(T|H(ID)))
+	@param Y is the server challenge
+	@param V is the client part response
+	@param R is the client part response
+	@param W is the server part response
+	@param H the output is the hash of all of the above that apply
+*/
+void HASH_ALL(int h,octet *I,octet *U,octet *CU,octet *Y,octet *V,octet *R,octet *W,octet *H);
+/**	@brief Hash an M-Pin Identity to an octet string
+ *
+ 	@param h is the hash type
+	@param ID an octet containing the identity
+	@param HID an octet containing the hashed identity
+ */
+void HASH_ID(int h,octet *ID,octet *HID);
+/**	@brief Get epoch time as unsigned integer
+ *
+	@return current epoch time in seconds
+ */
+unsign32 GET_TIME(void);
+/**	@brief AES-GCM Encryption
+ *
+	@param K  AES key
+	@param IV Initialization vector
+	@param H Header
+	@param P Plaintext
+	@param C Ciphertext
+	@param T Checksum
+ */
+void AES_GCM_ENCRYPT(octet *K,octet *IV,octet *H,octet *P,octet *C,octet *T);
+
+/**	@brief AES-GCM Decryption
+ *
+	@param K  AES key
+	@param IV Initialization vector
+	@param H Header
+	@param P Plaintext
+	@param C Ciphertext
+	@param T Checksum
+ */
+void AES_GCM_DECRYPT(octet *K,octet *IV,octet *H,octet *C,octet *P,octet *T);
+
+}
+
+#endif
\ No newline at end of file
diff --git a/version3/cpp/rand.cpp b/version3/cpp/rand.cpp
new file mode 100644
index 0000000..20b7605
--- /dev/null
+++ b/version3/cpp/rand.cpp
@@ -0,0 +1,174 @@
+/*
+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.
+*/
+
+/*
+ *   Cryptographic strong random number generator
+ *
+ *   Unguessable seed -> SHA -> PRNG internal state -> SHA -> random numbers
+ *   Slow - but secure
+ *
+ *   See ftp://ftp.rsasecurity.com/pub/pdfs/bull-1.pdf for a justification
+ */
+/* SU=m, m is Stack Usage */
+
+#include "amcl.h"
+
+using namespace amcl;
+
+/* SU= 20 */
+static unsign32 sbrand(csprng *rng)
+{
+    /* Marsaglia & Zaman random number generator */
+    int i,k;
+    unsign32 pdiff,t;
+    rng->rndptr++;
+    if (rng->rndptr<NK) return rng->ira[rng->rndptr];
+    rng->rndptr=0;
+    for (i=0,k=NK-NJ; i<NK; i++,k++)
+    {
+        /* calculate next NK values */
+        if (k==NK) k=0;
+        t=rng->ira[k];
+        pdiff=t - rng->ira[i] - rng->borrow;
+
+        if (pdiff<t) rng->borrow=0;
+        if (pdiff>t) rng->borrow=1;
+        rng->ira[i]=pdiff;
+    }
+    return rng->ira[0];
+}
+
+/* SU= 20 */
+static void sirand(csprng* rng,unsign32 seed)
+{
+    /* initialise random number system */
+    /* modified so that a subsequent call "stirs" in another seed value */
+    /* in this way as many seed bits as desired may be used */
+    int i,in;
+    unsign32 t,m=1;
+    rng->borrow=0L;
+    rng->rndptr=0;
+    rng->ira[0]^=seed;
+    for (i=1; i<NK; i++)
+    {
+        /* fill initialisation vector */
+        in=(NV*i)%NK;
+        rng->ira[in]^=m;      /* note XOR */
+        t=m;
+        m=seed-m;
+        seed=t;
+    }
+    for (i=0; i<10000; i++) sbrand(rng ); /* "warm-up" & stir the generator */
+}
+
+/* SU= 312 */
+static void fill_pool(csprng *rng)
+{
+    /* hash down output of RNG to re-fill the pool */
+    int i;
+    hash256 sh;
+    HASH256_init(&sh);
+    for (i=0; i<128; i++) HASH256_process(&sh,sbrand(rng));
+    HASH256_hash(&sh,rng->pool);
+    rng->pool_ptr=0;
+}
+
+static unsign32 pack(const uchar *b)
+{
+    /* pack bytes into a 32-bit Word */
+    return ((unsign32)b[3]<<24)|((unsign32)b[2]<<16)|((unsign32)b[1]<<8)|(unsign32)b[0];
+}
+
+/* SU= 360 */
+/* Initialize RNG with some real entropy from some external source */
+void amcl::RAND_seed(csprng *rng,int rawlen,char *raw)
+{
+    /* initialise from at least 128 byte string of raw  *
+     * random (keyboard?) input, and 32-bit time-of-day */
+    int i;
+    char digest[32];
+    uchar b[4];
+    hash256 sh;
+    rng->pool_ptr=0;
+    for (i=0; i<NK; i++) rng->ira[i]=0;
+    if (rawlen>0)
+    {
+        HASH256_init(&sh);
+        for (i=0; i<rawlen; i++)
+            HASH256_process(&sh,raw[i]);
+        HASH256_hash(&sh,digest);
+
+        /* initialise PRNG from distilled randomness */
+
+        for (i=0; i<8; i++)
+        {
+            b[0]=digest[4*i];
+            b[1]=digest[4*i+1];
+            b[2]=digest[4*i+2];
+            b[3]=digest[4*i+3];
+            //	printf("%08x\n",pack(b));
+            sirand(rng,pack(b));
+        }
+    }
+    fill_pool(rng);
+}
+
+/* Terminate and clean up */
+void amcl::RAND_clean(csprng *rng)
+{
+    /* kill internal state */
+    int i;
+    rng->pool_ptr=rng->rndptr=0;
+    for (i=0; i<32; i++) rng->pool[i]=0;
+    for (i=0; i<NK; i++) rng->ira[i]=0;
+    rng->borrow=0;
+}
+
+/* get random byte */
+/* SU= 8 */
+int amcl::RAND_byte(csprng *rng)
+{
+    int r;
+    r=rng->pool[rng->pool_ptr++];
+    if (rng->pool_ptr>=32) fill_pool(rng);
+    return (r&0xff);
+}
+
+/* test main program */
+/*
+#include <stdio.h>
+#include <string.h>
+
+void main()
+{
+    int i;
+    char raw[256];
+    csprng rng;
+
+	RAND_clean(&rng);
+
+
+	for (i=0;i<256;i++) raw[i]=(char)i;
+    RAND_seed(&rng,256,raw);
+
+	for (i=0;i<1000;i++)
+		printf("%02x ",(unsigned char)RAND_byte(&rng));
+}
+
+*/
diff --git a/version3/cpp/randapi.cpp b/version3/cpp/randapi.cpp
new file mode 100644
index 0000000..d5c5fdb
--- /dev/null
+++ b/version3/cpp/randapi.cpp
@@ -0,0 +1,17 @@
+#include "randapi.h"
+
+using namespace amcl;
+
+/* Initialise a Cryptographically Strong Random Number Generator from
+   an octet of raw random data */
+
+void amcl::CREATE_CSPRNG(csprng *RNG,octet *RAW)
+{
+    RAND_seed(RNG,RAW->len,RAW->val);
+}
+
+void amcl::KILL_CSPRNG(csprng *RNG)
+{
+    RAND_clean(RNG);
+}
+
diff --git a/version3/cpp/randapi.h b/version3/cpp/randapi.h
new file mode 100644
index 0000000..a880c09
--- /dev/null
+++ b/version3/cpp/randapi.h
@@ -0,0 +1,24 @@
+#ifndef RANDOM_H
+#define RANDOM_H
+
+#include "amcl.h"
+
+namespace amcl {
+
+/**	@brief Initialise a random number generator
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param S is an input truly random seed value
+ */
+extern void CREATE_CSPRNG(csprng *R,octet *S);
+/**	@brief Kill a random number generator
+ *
+	Deletes all internal state
+	@param R is a pointer to a cryptographically secure random number generator
+ */
+extern void KILL_CSPRNG(csprng *R);
+
+}
+
+#endif
+
diff --git a/version3/cpp/readme.txt b/version3/cpp/readme.txt
new file mode 100644
index 0000000..ad85d6b
--- /dev/null
+++ b/version3/cpp/readme.txt
@@ -0,0 +1,61 @@
+This C++ version is really just C plus namespaces. Namespaces are the 
+only feature of C++ that is used
+
+Separate ROM files provide the constants required for each curve. The
+associated header files (big.h, fp.h and ecp.h) also specify 
+certain constants that must be set for the particular curve.
+
+--------------------------------------
+
+To build the library and see it in action, copy all of the files in this 
+directory to a fresh directory. Then execute the python3 script config32.py 
+for a 32-bit build, or config64.py for a 64-bit build, and select the curves 
+that you wish to support. Note that support for 16-bit builds is currently 
+somewhat limited - see config16.py. A library is built automatically 
+including all of the modules that you will need.
+
+The configuration files assume the g++ compiler. For clang++ edit the
+config32.py and config64.py files and substitute "clang++" for "g++".
+Note that clang++ is about 10-15% faster.*
+
+As a quick example execute
+
+py config32.py
+
+or
+
+python3 config32.py
+
+Then select options 1, 3, 7, 18, 20, 25, 26 and 27, which are fixed for the example 
+program. (For a 16-bit build select 1, 3 and 5). Select 0 then to exit.
+
+Then compile
+
+g++ -O2  testall.cpp amcl.a -o testall.exe
+
+if using MINGW in Windows. Or for Linux
+
+g++ -O2  testall.cpp amcl.a -o testall
+
+The test program exercises 3 different ordinary elliptic curves, a 
+pairing friendly curve and RSA, all in the one binary.
+
+The correct PIN is 1234
+
+
+Next compile 
+
+
+g++ -O2  benchtest_all.cpp amcl.a -o benchtest_all.exe
+
+if using MINGW in Windows. Or for Linux
+
+g++ -O2  benchtest_all.cpp amcl.a -o benchtest_all
+
+This program provides some timings.
+
+*Using clang on Windows
+Download latest clang from http://releases.llvm.org/download.html
+Choose Clang for Windows (64-bit) (.sig) 
+Install a free version of Microsoft Visual C++ https://www.visualstudio.com/downloads/
+Now use "clang++" wherever "g++" was used before.
diff --git a/version3/cpp/rom_curve_ANSSI.cpp b/version3/cpp/rom_curve_ANSSI.cpp
new file mode 100644
index 0000000..0aabc22
--- /dev/null
+++ b/version3/cpp/rom_curve_ANSSI.cpp
@@ -0,0 +1,42 @@
+#include "arch.h"
+#include "ecp_ANSSI.h"
+
+
+namespace ANSSI {
+/* ANSSI Curve */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+using namespace B256_28;
+
+const int CURVE_Cof_I=1;
+const BIG CURVE_Cof= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const int CURVE_A= -3;
+const int CURVE_B_I= 0;
+const BIG CURVE_B= {0xB7BB73F,0x75ED967,0x1A18030,0xC9AE4B,0xFDFEC,0x754A44C,0xD4ABA,0x5428A93,0xE353FCA,0xE};
+const BIG CURVE_Order= {0x6D655E1,0xFDD459C,0x2BF941F,0x67E140D,0x35B53DC,0xE8CE424,0xF10126D,0xB3AD58,0x1FD178C,0xF};
+const BIG CURVE_Gx= {0x98F5CFF,0xC97A2DD,0x8B70164,0xD2DCAF9,0x3958C27,0x4749D42,0xB31183D,0x56C139E,0x6B3D4C3,0xB};
+const BIG CURVE_Gy= {0x4062CFB,0x115A155,0x4C9E183,0xC307E8E,0xF8C2701,0xF0F3ECE,0x11F9271,0xC8B2049,0x142E0F7,0x6};
+#endif
+
+#if CHUNK==64
+
+using namespace B256_56;
+
+const int CURVE_Cof_I=1;
+const BIG CURVE_Cof= {0x1L,0x0L,0x0L,0x0L,0x0L};
+const int CURVE_A= -3;
+const int CURVE_B_I= 0;
+const BIG CURVE_B= {0x75ED967B7BB73FL,0xC9AE4B1A18030L,0x754A44C00FDFECL,0x5428A9300D4ABAL,0xEE353FCAL};
+const BIG CURVE_Order= {0xFDD459C6D655E1L,0x67E140D2BF941FL,0xE8CE42435B53DCL,0xB3AD58F10126DL,0xF1FD178CL};
+const BIG CURVE_Gx= {0xC97A2DD98F5CFFL,0xD2DCAF98B70164L,0x4749D423958C27L,0x56C139EB31183DL,0xB6B3D4C3L};
+const BIG CURVE_Gy= {0x115A1554062CFBL,0xC307E8E4C9E183L,0xF0F3ECEF8C2701L,0xC8B204911F9271L,0x6142E0F7L};
+#endif
+
+}
diff --git a/version3/cpp/rom_curve_BLS24.cpp b/version3/cpp/rom_curve_BLS24.cpp
new file mode 100644
index 0000000..d78760f
--- /dev/null
+++ b/version3/cpp/rom_curve_BLS24.cpp
@@ -0,0 +1,78 @@
+#include "arch.h"
+#include "ecp_BLS24.h"
+
+namespace BLS24 {
+/* Curve BLS24 - Pairing friendly BLS curve */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+using namespace B480_29;
+
+// Base Bits= 29
+
+const int CURVE_Cof_I=0;
+const int CURVE_A= 0;
+const int CURVE_B_I= 19;
+const BIG CURVE_B= {0x13,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Order= {0x10000001,0xD047FF,0x1FD54464,0x1E3CE067,0xE322DDA,0x1D356F3F,0x7433B44,0x49091F9,0x1729CC2,0x250286C,0x16E62ED,0xB403E1E,0x1001000,0x80,0x0,0x0,0x0};
+const BIG CURVE_Gx= {0xBE3CCD4,0x33B07AF,0x1B67D159,0x3DFC5B5,0xEBA1FCC,0x1A3C1F84,0x56BE204,0xEF8DF1B,0x11AE2D84,0x5FEE546,0x161B3BF9,0x183B20EE,0x1EA5D99B,0x14F0C5BF,0xBE521B7,0x17C682F9,0x1AB2};
+const BIG CURVE_Gy= {0x121E5245,0x65D2E56,0x11577DB1,0x16DACC11,0x14F39746,0x459F694,0x12483FCF,0xC828B04,0xFD63E5A,0x7B1D52,0xAFDE738,0xF349254,0x1A4529FF,0x10E53353,0xF91DEE1,0x16E18D8A,0x47FC};
+
+const BIG CURVE_Bnx= {0x11FF80,0x80010,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Cof= {0x19F415AB,0x1E0FFDFF,0x15AAADFF,0xAA,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Cru= {0xDD794A9,0x1DE138A3,0x2BCCE90,0xC746127,0x15223DDC,0x1DD8890B,0xED08DB7,0xE24B9F,0xE379CE6,0x37011AC,0x11BAC820,0x1EEFAD01,0x200860F,0x147218A6,0xF16A209,0xF0079,0x555C};
+const BIG CURVE_Pxaa= {0x14E24678,0x1F149A9B,0x9609022,0x1C186868,0xCDEFC69,0x1C87BB2E,0x14A2235F,0x7586755,0x5896747,0x159BFE92,0x3B5572E,0x1710A521,0x71EB14A,0xC643C33,0x12581DE5,0x1BCA747D,0x959};
+const BIG CURVE_Pxab= {0x1FB099B8,0x3FCF5D7,0x4A91C0E,0xC6EEB40,0x11FC2385,0x11B5AE8D,0x1A9CC3E7,0x194FE144,0x185DB2A5,0x930E1C7,0x14F85F9A,0x1F2ED4E,0x1D1BE5AD,0xF26169C,0xCF7F194,0x1DA1062E,0x3B0D};
+const BIG CURVE_Pxba= {0x11AD15D3,0xD0E6F38,0x17DB85BB,0x30A62F1,0x1EA3E09A,0x17B25FA1,0x1B7959AC,0x1165B19A,0x6C74FDB,0x18F790E1,0x12278FDA,0x1E008F79,0x103F329,0x14619FF1,0x1EBCAA8,0xFF5A9CA,0x3EC2};
+const BIG CURVE_Pxbb= {0x1EE0F480,0x3D5943A,0xF5B12E3,0x128AADC8,0x180E1CB9,0x1EFD916F,0x48BC7F,0x1D5EE1FA,0x5698EF5,0x11D6AED9,0x1386BC6E,0x196E900B,0x1CE2E465,0xC2A8ED3,0x1E67DF99,0x71B7940,0xA5B};
+const BIG CURVE_Pyaa= {0x14781AA0,0xC324C98,0xEDC2AC,0x16C13B46,0x145FC44B,0x12529530,0x1310A8C4,0x1768C5C0,0xE19AE68,0x56E1C1D,0x13DAF93F,0x17E94366,0xF901AD0,0x76800CC,0x10250D8B,0x1E6BAE6D,0x5057};
+const BIG CURVE_Pyab= {0xEAE08FA,0xDDF62BF,0xA97E5AB,0xF0EE97,0x99A42CA,0x1C326578,0xF33DC11,0x8B913F7,0xFEF8552,0x19F35B90,0x58DDBDE,0xFC32FF2,0x1587B5DF,0xB5EB07A,0x1A258DE0,0x1692CC3D,0x2CE2};
+const BIG CURVE_Pyba= {0x5F0CC41,0xB9813B5,0x14C2A87D,0xFF1264A,0x19AF8A14,0x6CE6C3,0x2A7F8A2,0x121DCA7D,0x7D37153,0x19D21078,0x15466DC7,0x1362982B,0x1DD3CB5B,0x1CFC0D1C,0x18C69AF8,0x8CC7DC,0x1807};
+const BIG CURVE_Pybb= {0x115C1CAE,0x78D9732,0x16C26237,0x5A81A6A,0x1C38A777,0x56121FE,0x4DAD9D7,0x1BEBA670,0xA1D72FC,0xD60B274,0x19734258,0x1D621775,0x4691771,0x14206B68,0x17B22DE4,0x29D5B37,0x499D};
+const BIG CURVE_W[2]= {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+const BIG CURVE_SB[2][2]= {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+const BIG CURVE_WB[4]= {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+const BIG CURVE_BB[4][4]= {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+
+
+#endif
+
+#if CHUNK==64
+
+using namespace B480_56;
+
+// Base Bits= 56
+
+const int CURVE_Cof_I=0;
+const int CURVE_A= 0;
+const int CURVE_B_I= 19;
+const BIG CURVE_B= {0x13L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG CURVE_Order= {0x1A08FFF0000001L,0x1E7033FF551190L,0x6ADE7EE322DDAFL,0x848FC9D0CED13AL,0x50D81729CC224L,0x1F0F05B98BB44AL,0x10010010005A0L,0x0L,0x0L};
+const BIG CURVE_Gx= {0x6760F5EBE3CCD4L,0xEFE2DAED9F4564L,0x783F08EBA1FCC1L,0xC6F8D95AF88134L,0xDCA8D1AE2D8477L,0x9077586CEFE4BFL,0x8B7FEA5D99BC1DL,0x17CAF9486DE9E1L,0x1AB2BE34L};
+const BIG CURVE_Gy= {0xCBA5CAD21E5245L,0x6D6608C55DF6C4L,0xB3ED294F39746BL,0x145824920FF3C8L,0x63AA4FD63E5A64L,0x492A2BF79CE00FL,0x66A7A4529FF79AL,0x6C53E477B861CAL,0x47FCB70CL};
+
+const BIG CURVE_Bnx= {0x100020011FF80L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG CURVE_Cof= {0xC1FFBFF9F415ABL,0x5556AAB7FFL,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG CURVE_Cru= {0xBC27146DD794A9L,0x3A30938AF33A43L,0xB112175223DDC6L,0x125CFBB4236DFBL,0x2358E379CE607L,0xD680C6EB20806EL,0x314C200860FF77L,0x3CBC5A88268E4L,0x555C0078L};
+const BIG CURVE_Pxaa= {0xE2935374E24678L,0xC34342582408BL,0xF765CCDEFC69EL,0xC33AAD2888D7F9L,0x7FD2458967473AL,0x52908ED55CBAB3L,0x786671EB14AB88L,0xA3EC96077958C8L,0x959DE53L};
+const BIG CURVE_Pxab= {0x7F9EBAFFB099B8L,0x3775A012A47038L,0x6B5D1B1FC23856L,0x7F0A26A730F9E3L,0x1C38F85DB2A5CAL,0x76A753E17E6926L,0x2D39D1BE5AD0F9L,0x31733DFC651E4CL,0x3B0DED08L};
+const BIG CURVE_Pxba= {0xA1CDE711AD15D3L,0x853178DF6E16EDL,0x64BF43EA3E09A1L,0x2D8CD6DE566B2FL,0xF21C26C74FDB8BL,0x47BCC89E3F6B1EL,0x3FE2103F329F00L,0x4E507AF2AA28C3L,0x3EC27FADL};
+const BIG CURVE_Pxbb= {0x7AB2875EE0F480L,0x4556E43D6C4B8CL,0xFB22DF80E1CB99L,0xF70FD0122F1FFDL,0xD5DB25698EF5EAL,0x4805CE1AF1BA3AL,0x1DA7CE2E465CB7L,0xCA0799F7E65855L,0xA5B38DBL};
+const BIG CURVE_Pyaa= {0x86499314781AA0L,0x609DA303B70AB1L,0xA52A6145FC44BBL,0x462E04C42A3124L,0xC383AE19AE68BBL,0xA1B34F6BE4FCADL,0x198F901AD0BF4L,0x736C094362CED0L,0x5057F35DL};
+const BIG CURVE_Pyab= {0xBBEC57EEAE08FAL,0x78774BAA5F96ADL,0x64CAF099A42CA0L,0xC89FBBCCF70478L,0x6B720FEF855245L,0x97F916376F7B3EL,0x60F5587B5DF7E1L,0x61EE89637816BDL,0x2CE2B496L};
+const BIG CURVE_Pyba= {0x730276A5F0CC41L,0xF89325530AA1F5L,0xD9CD879AF8A147L,0xEE53E8A9FE2880L,0x420F07D3715390L,0x4C15D519B71F3AL,0x1A39DD3CB5B9B1L,0x3EE631A6BE39F8L,0x18070466L};
+const BIG CURVE_Pybb= {0xF1B2E6515C1CAEL,0xD40D355B0988DCL,0xC243FDC38A7772L,0x5D338136B675CAL,0x164E8A1D72FCDFL,0xBBAE5CD0961ACL,0xD6D04691771EB1L,0xD9BDEC8B792840L,0x499D14EAL};
+const BIG CURVE_W[2]= {{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}};
+const BIG CURVE_SB[2][2]= {{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}}};
+const BIG CURVE_WB[4]= {{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}};
+const BIG CURVE_BB[4][4]= {{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}}};
+
+#endif
+
+}
diff --git a/version3/cpp/rom_curve_BLS381.cpp b/version3/cpp/rom_curve_BLS381.cpp
new file mode 100644
index 0000000..41b3cf6
--- /dev/null
+++ b/version3/cpp/rom_curve_BLS381.cpp
@@ -0,0 +1,64 @@
+#include "arch.h"
+#include "ecp_BLS381.h"
+
+namespace BLS381 {
+/* Curve BLS381 - Pairing friendly BLS curve */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+using namespace B384_29;
+
+const int CURVE_Cof_I=0;
+const int CURVE_A= 0;
+const int CURVE_B_I= 4;
+const BIG CURVE_B= {0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Order= {0x1,0x1FFFFFF8,0x1F96FFBF,0x1B4805FF,0x1D80553B,0xC0404D0,0x1520CCE7,0xA6533AF,0x73EDA7,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Gx= {0x1B22C6BB,0x19D78056,0x1E86BBFE,0xBD07FF2,0x1AC586C5,0x1D1F8B8D,0x4168538,0x9F2EE97,0xFC3688C,0x27D4D60,0x9A558E3,0x32FAF28,0x1F1D3A73,0xB};
+const BIG CURVE_Gy= {0x6C5E7E1,0x551194A,0x222B903,0x198E8945,0xB3EDD03,0xC659602,0xBD8036C,0x12BABA01,0x4FCF5E0,0xBA0EC57,0x8278C3B,0x75541E3,0xB3F481E,0x4};
+
+const BIG CURVE_Bnx= {0x10000,0x10080000,0x34,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Cof= {0xAAAB,0x55558,0x157855A3,0x191800AA,0x396,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Cru= {0x1FFEFFFE,0x100FFFFF,0x280008B,0xFB026C4,0x9688DE1,0x149DF37C,0x1FAB76CE,0xED41EE,0x11BA69C6,0x1EFBB672,0x17C659CB,0x0,0x0,0x0};
+const BIG CURVE_Pxa= {0x121BDB8,0x402B646,0x16EFBF5,0x18064D50,0x1D1770BA,0x5B23D71,0xC0AD144,0x1A9F4807,0x11C6E47A,0x196E2882,0x9820149,0x11E1522,0x4AA2B2F,0x1};
+const BIG CURVE_Pxb= {0x1D042B7E,0xD63E82A,0x51755F9,0x19E22427,0x15049334,0x10DDEE3F,0x186AD769,0x1A132416,0x5596BD0,0x4413A7B,0x1F6B34E8,0x4E33EC0,0x1E02B605,0x9};
+const BIG CURVE_Pya= {0x8B82801,0xC9AA430,0xB28A278,0x15939877,0xD12C923,0xD34A8B0,0xE9DB50A,0x155197BA,0x1AADFD9B,0x16D171A8,0x3327371,0x4FADC23,0xE5D5277,0x6};
+const BIG CURVE_Pyb= {0x105F79BE,0x15483AFF,0x1B07686A,0xE1A4EB9,0x99AB3F3,0x955AB97,0xEBC99D2,0xFD0B4EC,0x19CB3E28,0x15E145C,0xCAB34AC,0x1D4E6998,0x6C4A02,0x3};
+const BIG CURVE_W[2]= {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+const BIG CURVE_SB[2][2]= {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+const BIG CURVE_WB[4]= {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+const BIG CURVE_BB[4][4]= {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+#endif
+
+#if CHUNK==64
+
+using namespace B384_58;
+
+const int CURVE_Cof_I=0;
+const int CURVE_A= 0;
+const int CURVE_B_I= 4;
+const BIG CURVE_B= {0x4L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG CURVE_Order= {0x3FFFFFF00000001L,0x36900BFFF96FFBFL,0x180809A1D80553BL,0x14CA675F520CCE7L,0x73EDA7L,0x0L,0x0L};
+const BIG CURVE_Gx= {0x33AF00ADB22C6BBL,0x17A0FFE5E86BBFEL,0x3A3F171BAC586C5L,0x13E5DD2E4168538L,0x4FA9AC0FC3688CL,0x65F5E509A558E3L,0x17F1D3A73L};
+const BIG CURVE_Gy= {0xAA232946C5E7E1L,0x331D128A222B903L,0x18CB2C04B3EDD03L,0x25757402BD8036CL,0x1741D8AE4FCF5E0L,0xEAA83C68278C3BL,0x8B3F481EL};
+
+const BIG CURVE_Bnx= {0x201000000010000L,0x34L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG CURVE_Cof= {0xAAAB0000AAABL,0x3230015557855A3L,0x396L,0x0L,0x0L,0x0L,0x0L};
+const BIG CURVE_Cru= {0x201FFFFFFFEFFFEL,0x1F604D88280008BL,0x293BE6F89688DE1L,0x1DA83DDFAB76CEL,0x3DF76CE51BA69C6L,0x17C659CBL,0x0L};
+const BIG CURVE_Pxa= {0x8056C8C121BDB8L,0x300C9AA016EFBF5L,0xB647AE3D1770BAL,0x353E900EC0AD144L,0x32DC51051C6E47AL,0x23C2A449820149L,0x24AA2B2FL};
+const BIG CURVE_Pxb= {0x1AC7D055D042B7EL,0x33C4484E51755F9L,0x21BBDC7F5049334L,0x3426482D86AD769L,0x88274F65596BD0L,0x9C67D81F6B34E8L,0x13E02B605L};
+const BIG CURVE_Pya= {0x193548608B82801L,0x2B2730EEB28A278L,0x1A695160D12C923L,0x2AA32F74E9DB50AL,0x2DA2E351AADFD9BL,0x9F5B8463327371L,0xCE5D5277L};
+const BIG CURVE_Pyb= {0x2A9075FF05F79BEL,0x1C349D73B07686AL,0x12AB572E99AB3F3L,0x1FA169D8EBC99D2L,0x2BC28B99CB3E28L,0x3A9CD330CAB34ACL,0x606C4A02L};
+const BIG CURVE_W[2]= {{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}};
+const BIG CURVE_SB[2][2]= {{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}}};
+const BIG CURVE_WB[4]= {{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}};
+const BIG CURVE_BB[4][4]= {{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}}};
+
+#endif
+
+}
diff --git a/version3/cpp/rom_curve_BLS383.cpp b/version3/cpp/rom_curve_BLS383.cpp
new file mode 100644
index 0000000..1cceeed
--- /dev/null
+++ b/version3/cpp/rom_curve_BLS383.cpp
@@ -0,0 +1,68 @@
+#include "arch.h"
+#include "ecp_BLS383.h"
+
+namespace BLS383 {
+/* Curve BLS383 - Pairing friendly BLS curve */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+using namespace B384_29;
+
+// Base Bits= 29
+
+const int CURVE_A= 0;
+const int CURVE_Cof_I= 0;
+const BIG CURVE_Cof= {0x15169EAB,0xA82AB0A,0xAAEFFED,0x15558001,0x555,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const int CURVE_B_I= 15;
+const BIG CURVE_B= {0xF,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Order= {0x1EBC0001,0x1904CF5F,0x834E5CE,0xBE12B42,0xB381DE0,0xE40B4C,0x270110,0x10018017,0x1002001,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Gx= {0x8734573,0x623B9C8,0x1D1DC11E,0xBB7E107,0x1E3445C5,0x1D6C2578,0x10B0BE1E,0xED6103E,0x10F31D9F,0x296ED82,0x18E0D7D0,0x12F3D9C9,0x1FCBA55B,0x20};
+const BIG CURVE_Gy= {0x3F224,0x968B2F4,0x1FE63F48,0xFA93D90,0x14D2DDE5,0x54A56F5,0x12441D4C,0x18CD76C8,0x199D0DAD,0xE18E236,0x92BA73,0x99F6600,0x8F16727,0x3};
+
+const BIG CURVE_Bnx= {0x1001200,0x400000,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Cru= {0xEAAC2A9,0x61B3A81,0x17D974B7,0xBED0345,0xA341BC2,0x17A51A6F,0x5738948,0x69B7BAE,0x14605445,0x374A43,0x8116AD1,0x956DD69,0x16556956,0x2A};
+const BIG CURVE_Pxa= {0xD7F2D86,0x1E59DB1,0x17474F85,0x1FB56CF2,0x572EE81,0xE487AB1,0x96F51FC,0x190A5AAE,0x6432501,0x13E58F3A,0x101E6425,0xFD807D1,0x34D2240,0x3};
+const BIG CURVE_Pxb= {0x452DE15,0x1ECF20F6,0x1FF9837B,0x95651AA,0xD5D75B5,0x5D44749,0x12277F66,0x1DB3A0B9,0x1D24F498,0x19441B0E,0x1CDE9DC5,0x2C975,0xD78006,0x18};
+const BIG CURVE_Pya= {0x1408CB41,0x34785DC,0x3586597,0x13DBC9E4,0x1A2E75B4,0x1D65489,0xCF9A25E,0x1ACE7933,0x1B6E990E,0x19FF31A3,0x12527615,0x1A44A68F,0x1792CF93,0x19};
+const BIG CURVE_Pyb= {0x1F479093,0x16C2321B,0x1889218E,0x87961BC,0x1BC98B01,0x197A24FB,0xA3DEBC2,0x88D67DF,0x1CE0D,0x1E8AD3D7,0x93B9EE9,0x59B18D6,0xE5247DD,0x10};
+const BIG CURVE_W[2]= {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+const BIG CURVE_SB[2][2]= {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+const BIG CURVE_WB[4]= {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+const BIG CURVE_BB[4][4]= {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+#endif
+
+#if CHUNK==64
+
+using namespace B384_58;
+
+// Base Bits= 58
+
+const int CURVE_A= 0;
+const int CURVE_Cof_I= 0;
+const BIG CURVE_Cof= {0x150556155169EABL,0x2AAB0002AAEFFEDL,0x555L,0x0L,0x0L,0x0L,0x0L};
+const int CURVE_B_I= 15;
+const BIG CURVE_B= {0xFL,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG CURVE_Order= {0x32099EBFEBC0001L,0x17C25684834E5CEL,0x1C81698B381DE0L,0x2003002E0270110L,0x1002001L,0x0L,0x0L};
+const BIG CURVE_Gx= {0xC4773908734573L,0x176FC20FD1DC11EL,0x3AD84AF1E3445C5L,0x1DAC207D0B0BE1EL,0x52DDB050F31D9FL,0x25E7B3938E0D7D0L,0x41FCBA55BL};
+const BIG CURVE_Gy= {0x12D165E8003F224L,0x1F527B21FE63F48L,0xA94ADEB4D2DDE5L,0x319AED912441D4CL,0x1C31C46D99D0DADL,0x133ECC00092BA73L,0x68F16727L};
+
+const BIG CURVE_Bnx= {0x8000001001200L,0x40L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG CURVE_Cru= {0xC367502EAAC2A9L,0x17DA068B7D974B7L,0x2F4A34DEA341BC2L,0xD36F75C5738948L,0x6E94874605445L,0x12ADBAD28116AD1L,0x556556956L};
+const BIG CURVE_Pxa= {0x3CB3B62D7F2D86L,0x3F6AD9E57474F85L,0x1C90F562572EE81L,0x3214B55C96F51FCL,0x27CB1E746432501L,0x1FB00FA301E6425L,0x634D2240L};
+const BIG CURVE_Pxb= {0x3D9E41EC452DE15L,0x12ACA355FF9837BL,0xBA88E92D5D75B5L,0x3B6741732277F66L,0x3288361DD24F498L,0x592EBCDE9DC5L,0x300D78006L};
+const BIG CURVE_Pya= {0x68F0BB9408CB41L,0x27B793C83586597L,0x3ACA913A2E75B4L,0x359CF266CF9A25EL,0x33FE6347B6E990EL,0x34894D1F2527615L,0x33792CF93L};
+const BIG CURVE_Pyb= {0x2D846437F479093L,0x10F2C379889218EL,0x32F449F7BC98B01L,0x111ACFBEA3DEBC2L,0x3D15A7AE001CE0DL,0xB3631AC93B9EE9L,0x20E5247DDL};
+const BIG CURVE_W[2]= {{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}};
+const BIG CURVE_SB[2][2]= {{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}}};
+const BIG CURVE_WB[4]= {{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}};
+const BIG CURVE_BB[4][4]= {{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}}};
+
+#endif
+
+}
diff --git a/version3/cpp/rom_curve_BLS461.cpp b/version3/cpp/rom_curve_BLS461.cpp
new file mode 100644
index 0000000..336887b
--- /dev/null
+++ b/version3/cpp/rom_curve_BLS461.cpp
@@ -0,0 +1,69 @@
+#include "arch.h"
+#include "ecp_BLS461.h"
+
+namespace BLS461 {
+/* Curve BLS461 - Pairing friendly BLS curve */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+using namespace B464_28;
+
+const int CURVE_Cof_I=0;
+const int CURVE_A= 0;
+const int CURVE_B_I= 9;
+const BIG CURVE_B= {0x9,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Order= {0x1,0x0,0xFFFFC00,0x7FEFFFE,0x110000,0x7FFC800,0x801FC01,0x5FD000E,0x17FE0,0xFFFC018,0xFFFFFF7,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Gx= {0xADEE93D,0x4D026A8,0x74B7411,0xD9C00EE,0x31AC7F2,0xC3981B5,0x9218229,0xD3564DC,0xA096650,0x6F7C292,0x9743616,0xBE922B1,0x12CF668,0xC81327,0x463B73A,0xE74E99B,0xAD0};
+const BIG CURVE_Gy= {0xAD1D465,0xF763157,0xC4FF470,0x17884C8,0xB8D215D,0xA819E66,0xF4959D0,0xE5C3245,0xB84910A,0xB8BFA40,0xBE96EEC,0x8BF9F8C,0xF277ACC,0x5F1C3F2,0x5F68C9,0xCDB14B3,0x77B};
+
+const BIG CURVE_Bnx= {0x0,0xFBFFFE0,0x1FFFFF,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Cof= {0xAAAAAAB,0xA7FFFEA,0x1556AA,0xD55AAAB,0x554FFFF,0x1555,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+
+const BIG CURVE_Cru= {0xFFFFFFE,0x40001F,0xFE00000,0xFFE7FFF,0xF0FFF6F,0x7200C47,0x7BCC604,0x15796DB,0xCF47771,0x9875433,0x613F0E8,0x5000502,0xEBFFF60,0x1FFFFF,0x0,0x0,0x0};
+
+const BIG CURVE_Pxa= {0x6D0A37C,0x5B50318,0x75DCC46,0xC2E492E,0xD6878A9,0xE01F919,0xF92F564,0x86DB74F,0x66803F0,0x46D581A,0x7ED78D,0x2F97C29,0xC270C89,0xF679453,0x6A50A9A,0x54138A0,0x10CC};
+const BIG CURVE_Pxb= {0x2C1C0AD,0xF85CA8C,0x25CADE9,0x6CD66C4,0xA289609,0xC612951,0xEE2401A,0x529ABEB,0xF65B17D,0xBA09D33,0xD4C5AF5,0x4D4371E,0x46A672E,0xA279D22,0xACEA37C,0x1FB4FE5,0x95C};
+const BIG CURVE_Pya= {0x2FB006,0xCCD0C1B,0xA12A337,0x3D194A4,0xC92C895,0x4960CFC,0x39FC68B,0x3A9B00F,0xED1BA0F,0xA7DBBC5,0xA9CDFD8,0x27CC2F7,0x4E73ED2,0x6070F4F,0xEBA7E67,0xAC848E7,0x226};
+const BIG CURVE_Pyb= {0xDF1457C,0xA506ADF,0x4C20A8,0xD6A31DC,0x36E3FB4,0xEA9A8F1,0x92F5668,0x3C3BE44,0x67A1297,0x74BEABA,0x56A20BE,0x4C42E38,0x45157F0,0x2AB1D00,0xBB402EA,0x101B4FA,0xE38};
+const BIG CURVE_W[2]= {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+const BIG CURVE_SB[2][2]= {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+const BIG CURVE_WB[4]= {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+const BIG CURVE_BB[4][4]= {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+
+#endif
+
+#if CHUNK==64
+
+using namespace B464_60;
+
+const int CURVE_Cof_I=0;
+const int CURVE_A= 0;
+const int CURVE_B_I= 9;
+const BIG CURVE_B= {0x9L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG CURVE_Order= {0x1L,0x7FEFFFEFFFFC0L,0xC017FFC80001100L,0x7FE05FD000E801FL,0xFFFF7FFFC018001L,0xFFL,0x0L,0x0L};
+const BIG CURVE_Gx= {0x14D026A8ADEE93DL,0xF2D9C00EE74B741L,0x229C3981B531AC7L,0x6650D3564DC9218L,0x436166F7C292A09L,0x2CF668BE922B197L,0x463B73A0C813271L,0xAD0E74E99BL};
+const BIG CURVE_Gy= {0xF763157AD1D465L,0x5D17884C8C4FF47L,0x9D0A819E66B8D21L,0x910AE5C3245F495L,0x96EECB8BFA40B84L,0x277ACC8BF9F8CBEL,0x5F68C95F1C3F2FL,0x77BCDB14B3L};
+
+const BIG CURVE_Bnx= {0xFFBFFFE00000000L,0x1FFFFL,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG CURVE_Cof= {0xAA7FFFEAAAAAAABL,0xFFD55AAAB01556AL,0x1555554FFL,0x0L,0x0L,0x0L,0x0L,0x0L};
+
+const BIG CURVE_Cru= {0x40001FFFFFFFEL,0x6FFFE7FFFFE0000L,0x6047200C47F0FFFL,0x777115796DB7BCCL,0x3F0E89875433CF4L,0xBFFF60500050261L,0x1FFFFFEL,0x0L};
+
+const BIG CURVE_Pxa= {0x65B503186D0A37CL,0xA9C2E492E75DCC4L,0x564E01F919D6878L,0x3F086DB74FF92FL,0xED78D46D581A668L,0x270C892F97C2907L,0x6A50A9AF679453CL,0x10CC54138A0L};
+const BIG CURVE_Pxb= {0x9F85CA8C2C1C0ADL,0x96CD66C425CADEL,0x1AC612951A2896L,0xB17D529ABEBEE24L,0xC5AF5BA09D33F65L,0x6A672E4D4371ED4L,0xACEA37CA279D224L,0x95C1FB4FE5L};
+const BIG CURVE_Pya= {0x7CCD0C1B02FB006L,0x953D194A4A12A33L,0x68B4960CFCC92C8L,0xBA0F3A9B00F39FCL,0xCDFD8A7DBBC5ED1L,0xE73ED227CC2F7A9L,0xEBA7E676070F4F4L,0x226AC848E7L};
+const BIG CURVE_Pyb= {0x8A506ADFDF1457CL,0xB4D6A31DC04C20AL,0x668EA9A8F136E3FL,0x12973C3BE4492F5L,0xA20BE74BEABA67AL,0x5157F04C42E3856L,0xBB402EA2AB1D004L,0xE38101B4FAL};
+const BIG CURVE_W[2]= {{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}};
+const BIG CURVE_SB[2][2]= {{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}}};
+const BIG CURVE_WB[4]= {{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}};
+const BIG CURVE_BB[4][4]= {{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}}};
+
+#endif
+
+}
diff --git a/version3/cpp/rom_curve_BLS48.cpp b/version3/cpp/rom_curve_BLS48.cpp
new file mode 100644
index 0000000..e332b86
--- /dev/null
+++ b/version3/cpp/rom_curve_BLS48.cpp
@@ -0,0 +1,95 @@
+#include "arch.h"
+#include "ecp_BLS48.h"
+
+namespace BLS48 {
+/* Curve BLS48 - Pairing friendly BLS curve */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+using namespace B560_29;
+
+// Base Bits= 29
+
+const int CURVE_Cof_I=0;
+const int CURVE_A= 0;
+const int CURVE_B_I= 17;
+const BIG CURVE_B= {0x11,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Order= {0x1,0x17FFF800,0xA769C21,0x8AA813C,0x2029C21,0xA68F58B,0xB6307F4,0x1184DA51,0x6DFED78,0x1A3C85E9,0x571037B,0x1637F1F9,0x1C465FB0,0x98354B9,0x118DF17A,0x1422355D,0x43BF73E,0x6,0x0,0x0};
+const BIG CURVE_Gx= {0x5D71D33,0x1943697B,0x18CB783F,0x1B00AA9F,0x1711EE0B,0x7F80B23,0x129FD8CC,0x1345E03F,0x9A80F66,0x7038173,0xC056511,0x142801F5,0x42B2C3A,0x1AF09869,0x7924166,0x8381264,0x957EDD7,0xBACAEDC,0xA27A4A1,0x13};
+const BIG CURVE_Gy= {0xA6ED83A,0x14D2D9FF,0xA29C33D,0x1B8972A9,0x6958677,0x19C8F547,0x1DED7E3E,0x14F9E3DC,0x18FB7229,0x27171C0,0x1551E32D,0xE6184CC,0x6260E3C,0x733D204,0x579C437,0x1534665C,0x2B3349D,0x3162FD7,0xB634253,0x1};
+
+const BIG CURVE_Bnx= {0x1DE40020,0x3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Cof= {0x1F12ABEB,0x516887B,0x5,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Cru= {0xCBBA429,0x1B273F3,0xD3DD160,0x19C61452,0x308093A,0x146E1E34,0xAE0E768,0x1185948,0x1B73BC2D,0x93D855C,0x1B1A639C,0x118C919B,0xFF04AE3,0xF1CCD77,0x91318E5,0x10644780,0x3A79F7,0x1BE77919,0x145F60F3,0x1F};
+const BIG CURVE_Pxaaa= {0x923CE4A,0x14697474,0xAE04F4A,0x17AE205A,0x1313A20C,0x10B2EC50,0x18DF074F,0x15FE3FE8,0x7C90B98,0x959BF85,0xE57BD37,0x14376C96,0xBF57375,0xE20B625,0x12EE2172,0x1CBBCE85,0x1A5D9487,0xD0E024B,0x195E3602,0x1C};
+const BIG CURVE_Pxaab= {0xC0A1BE1,0x138E6E2D,0x1DF5FDC,0x151FC760,0x33972C5,0x56AA3C2,0x2491D8C,0x115B9FD7,0x140A11FA,0x1873AE35,0x1F259C26,0x74B0647,0x12D18B04,0x4672431,0x1C27F419,0x1CAA4D35,0x18DB48B6,0x13A54BDA,0x5080497,0x5};
+const BIG CURVE_Pxaba= {0x170C5DC4,0x11D39263,0x16B3BCB6,0x152C95BB,0x19BEC736,0x8849A12,0x49AB2A8,0xC7162D3,0xC58CD55,0x15C2659,0x11EE8B90,0xB40CAFC,0xE233167,0x7BEC8BE,0x129335BD,0x151C7DBB,0x78B689B,0x1B6B8EED,0x14BFBE3D,0x16};
+const BIG CURVE_Pxabb= {0x1A64B740,0x6B14B34,0x12481578,0x23FA931,0x323ADD1,0x206B82A,0xD789E1B,0x1FCFA666,0x1F4EEA7,0xF1E39E2,0x1968610,0xAF3EBD3,0x590D3B,0xDA0C35A,0x17306AAF,0xCF9DD2B,0x3F63B1A,0x96FF2F9,0xE102A76,0x12};
+const BIG CURVE_Pxbaa= {0x12F1E01F,0xDD8630B,0x12C29802,0x186239A6,0x19218788,0x4C87D1,0x16AE2501,0x775C076,0x870C80B,0x1A394429,0x1637D478,0x4A420E8,0x1C3AD4D4,0x10E5E713,0x111E6AD5,0x514FCF0,0x7CC49D3,0xC678A2,0x1787BDFD,0x1B};
+const BIG CURVE_Pxbab= {0x637383D,0x1851C11C,0x661F866,0x14404A7F,0x15D3D212,0x9AE28F6,0x8051F25,0x1E1CE2BF,0x137D882F,0xB231CEB,0xA8DB8FC,0x18957645,0x5E54DA8,0x1FF41C44,0x1A297414,0x17E1CBC5,0x1014F91F,0x4282AB7,0xB6CE9E3,0x10};
+const BIG CURVE_Pxbba= {0x1711939C,0xB41ED9E,0x69066BA,0x137CA3AD,0xCF2F6C0,0x5E6DAB9,0x2CE1323,0x946E448,0xF353D1C,0x14D9919F,0x46B7046,0x1A12015,0x3D6070,0x18C3E8D2,0x1F23BA45,0x1F1A337C,0x435A9CC,0x6CA1DF1,0x8A9CE1,0x15};
+const BIG CURVE_Pxbbb= {0x56F4899,0x196A0854,0xA959750,0x38A3D72,0x190BC9BC,0x145752BC,0x1E9E26DA,0x1403F88,0x71895E3,0x14162F5D,0x19FEC5FF,0x14190B16,0x7597C,0x19A3CF18,0x26A4B00,0x113D1BB6,0x7857A32,0xE0B78AB,0x1DD51E0F,0x1B};
+const BIG CURVE_Pyaaa= {0x14137844,0x1704BE7D,0x1FD3CCDD,0x189D8C93,0x1C768851,0xF5C37D5,0xE29C659,0x20AB1C1,0xF8896E0,0x1E08663E,0x1D1D539C,0x117E1C47,0x156CDD39,0x161F1017,0x143E8C72,0x174B22FD,0x18706190,0x49AA47E,0x19BB42E1,0xE};
+const BIG CURVE_Pyaab= {0xDC83190,0x12F19247,0x1AA26424,0x15D55E88,0xC418D32,0xB0E91DD,0x47CBFF7,0x2D992C1,0xDE03C1F,0x7694AE5,0x5C741A2,0x1D423AC6,0x5E02B9E,0x1E903F10,0x4EA6513,0x433A1F1,0x8EFA1C4,0xED54713,0x1E72CE4F,0x4};
+const BIG CURVE_Pyaba= {0x1985C0D,0xEE2FE82,0x64770FA,0x11A809B4,0x1483ACE9,0x18BCD2FA,0x171F32C,0x1612D58D,0x1E658341,0x1CBE2201,0x186E971,0x73F0E1,0xB0A5F40,0xAC90FB0,0x1635E008,0x237498B,0x1F3140D6,0xBF789A9,0x1166F259,0x1A};
+const BIG CURVE_Pyabb= {0x159D42F8,0x1B7F0540,0x45895D7,0x14875FA2,0x1E9E7F2B,0x10139D87,0x10F3FD7D,0x11D3717F,0x69E5006,0xF9BB3C4,0x13C9ED8D,0x16516DA,0x102F51DE,0x2725FEC,0x1F125B66,0xFFC324,0x1ED80731,0x1C16C4D,0x383AAA8,0x14};
+const BIG CURVE_Pybaa= {0x1F38039F,0x6A8959C,0x13C68984,0x11DD12AF,0x58093CF,0x1C8550A0,0xFFA1622,0xFF85979,0x1F2ABB75,0x18862E62,0x1EB6A2C9,0x1EC80B64,0x8EC2F18,0xE7BF713,0xC36B65A,0x19C5DD89,0x18A1D1AB,0xF772C8D,0xC11927C,0x5};
+const BIG CURVE_Pybab= {0x95F7865,0x134F0379,0x1CE9A0E,0x17E0EADD,0x1DACADD7,0x1B18F9F8,0x181D3943,0x186679A,0x2505BB0,0x1FDF1DC8,0x11B36A49,0x11E254E9,0xA438576,0x102B09AE,0x139984F4,0x15BC0233,0x1B6F180E,0x960562B,0x48CA65B,0x6};
+const BIG CURVE_Pybba= {0x7CC1979,0xEC1D4FB,0x1D89E6F0,0x955F38E,0x1635FDA9,0x123D8E10,0x10076209,0x494404A,0xD733D7,0x17678BCF,0x153841F9,0x10696FFD,0x5BC9FE8,0x1A20D8B2,0xE22EC9D,0x18449116,0x108C86C5,0x1B4CD720,0x34967,0x19};
+const BIG CURVE_Pybbb= {0xFC9F25B,0x7E44AB1,0xE9AB5D3,0x589F00D,0x1C9D264F,0xC7478B4,0x16B24A13,0x1D2C146B,0xEF84D9A,0xF47ECDE,0x1BFEE16A,0x1B69071E,0x11AB4C1C,0xBE9D9EF,0x390F005,0x78C8288,0x1B9BF549,0x9320730,0x3D84D97,0x14};
+const BIG CURVE_W[2]= {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+const BIG CURVE_SB[2][2]= {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+const BIG CURVE_WB[4]= {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+const BIG CURVE_BB[4][4]= {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+
+
+#endif
+
+#if CHUNK==64
+
+using namespace B560_58;
+
+// Base Bits= 58
+
+const int CURVE_Cof_I=0;
+const int CURVE_A= 0;
+const int CURVE_B_I= 17;
+const BIG CURVE_B= {0x11L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG CURVE_Order= {0x2FFFF0000000001L,0x11550278A769C21L,0x14D1EB162029C21L,0x2309B4A2B6307F4L,0x34790BD26DFED78L,0x2C6FE3F2571037BL,0x1306A973C465FB0L,0x28446ABB18DF17AL,0xC43BF73EL,0x0L};
+const BIG CURVE_Gx= {0x3286D2F65D71D33L,0x3601553F8CB783FL,0xFF01647711EE0BL,0x268BC07F29FD8CCL,0xE0702E69A80F66L,0x285003EAC056511L,0x35E130D242B2C3AL,0x107024C87924166L,0x17595DB8957EDD7L,0x26A27A4A1L};
+const BIG CURVE_Gy= {0x29A5B3FEA6ED83AL,0x3712E552A29C33DL,0x3391EA8E6958677L,0x29F3C7B9DED7E3EL,0x4E2E3818FB7229L,0x1CC30999551E32DL,0xE67A4086260E3CL,0x2A68CCB8579C437L,0x62C5FAE2B3349DL,0x2B634253L};
+
+const BIG CURVE_Bnx= {0x7DE40020L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG CURVE_Cof= {0xA2D10F7F12ABEBL,0x5L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG CURVE_Cru= {0x364E7E6CBBA429L,0x338C28A4D3DD160L,0x28DC3C68308093AL,0x230B290AE0E768L,0x127B0AB9B73BC2DL,0x23192337B1A639CL,0x1E399AEEFF04AE3L,0x20C88F0091318E5L,0x37CEF23203A79F7L,0x3F45F60F3L};
+const BIG CURVE_Pxaaa= {0x28D2E8E8923CE4AL,0x2F5C40B4AE04F4AL,0x2165D8A1313A20CL,0x2BFC7FD18DF074FL,0x12B37F0A7C90B98L,0x286ED92CE57BD37L,0x1C416C4ABF57375L,0x39779D0B2EE2172L,0x1A1C0497A5D9487L,0x3995E3602L};
+const BIG CURVE_Pxaab= {0x271CDC5AC0A1BE1L,0x2A3F8EC01DF5FDCL,0xAD5478433972C5L,0x22B73FAE2491D8CL,0x30E75C6B40A11FAL,0xE960C8FF259C26L,0x8CE48632D18B04L,0x39549A6BC27F419L,0x274A97B58DB48B6L,0xA5080497L};
+const BIG CURVE_Pxaba= {0x23A724C770C5DC4L,0x2A592B776B3BCB6L,0x110934259BEC736L,0x18E2C5A649AB2A8L,0x2B84CB2C58CD55L,0x168195F91EE8B90L,0xF7D917CE233167L,0x2A38FB7729335BDL,0x36D71DDA78B689BL,0x2D4BFBE3DL};
+const BIG CURVE_Pxabb= {0xD629669A64B740L,0x47F52632481578L,0x40D7054323ADD1L,0x3F9F4CCCD789E1BL,0x1E3C73C41F4EEA7L,0x15E7D7A61968610L,0x1B4186B40590D3BL,0x19F3BA577306AAFL,0x12DFE5F23F63B1AL,0x24E102A76L};
+const BIG CURVE_Pxbaa= {0x1BB0C6172F1E01FL,0x30C4734D2C29802L,0x990FA39218788L,0xEEB80ED6AE2501L,0x34728852870C80BL,0x94841D1637D478L,0x21CBCE27C3AD4D4L,0xA29F9E111E6AD5L,0x18CF1447CC49D3L,0x37787BDFDL};
+const BIG CURVE_Pxbab= {0x30A38238637383DL,0x288094FE661F866L,0x135C51ED5D3D212L,0x3C39C57E8051F25L,0x164639D737D882FL,0x312AEC8AA8DB8FCL,0x3FE838885E54DA8L,0x2FC3978BA297414L,0x850556F014F91FL,0x20B6CE9E3L};
+const BIG CURVE_Pxbba= {0x1683DB3D711939CL,0x26F9475A69066BAL,0xBCDB572CF2F6C0L,0x128DC8902CE1323L,0x29B3233EF353D1CL,0x342402A46B7046L,0x3187D1A403D6070L,0x3E3466F9F23BA45L,0xD943BE2435A9CCL,0x2A08A9CE1L};
+const BIG CURVE_Pxbbb= {0x32D410A856F4899L,0x7147AE4A959750L,0x28AEA57990BC9BCL,0x2807F11E9E26DAL,0x282C5EBA71895E3L,0x2832162D9FEC5FFL,0x33479E30007597CL,0x227A376C26A4B00L,0x1C16F1567857A32L,0x37DD51E0FL};
+const BIG CURVE_Pyaaa= {0x2E097CFB4137844L,0x313B1927FD3CCDDL,0x1EB86FABC768851L,0x4156382E29C659L,0x3C10CC7CF8896E0L,0x22FC388FD1D539CL,0x2C3E202F56CDD39L,0x2E9645FB43E8C72L,0x93548FD8706190L,0x1D9BB42E1L};
+const BIG CURVE_Pyaab= {0x25E3248EDC83190L,0x2BAABD11AA26424L,0x161D23BAC418D32L,0x5B3258247CBFF7L,0xED295CADE03C1FL,0x3A84758C5C741A2L,0x3D207E205E02B9EL,0x86743E24EA6513L,0x1DAA8E268EFA1C4L,0x9E72CE4FL};
+const BIG CURVE_Pyaba= {0x1DC5FD041985C0DL,0x2350136864770FAL,0x3179A5F5483ACE9L,0x2C25AB1A171F32CL,0x397C4403E658341L,0xE7E1C2186E971L,0x15921F60B0A5F40L,0x46E9317635E008L,0x17EF1353F3140D6L,0x35166F259L};
+const BIG CURVE_Pyabb= {0x36FE0A8159D42F8L,0x290EBF4445895D7L,0x20273B0FE9E7F2BL,0x23A6E2FF0F3FD7DL,0x1F37678869E5006L,0x2CA2DB53C9ED8DL,0x4E4BFD902F51DEL,0x1FF8649F125B66L,0x382D89BED80731L,0x28383AAA8L};
+const BIG CURVE_Pybaa= {0xD512B39F38039FL,0x23BA255F3C68984L,0x390AA14058093CFL,0x1FF0B2F2FFA1622L,0x310C5CC5F2ABB75L,0x3D9016C9EB6A2C9L,0x1CF7EE268EC2F18L,0x338BBB12C36B65AL,0x1EEE591B8A1D1ABL,0xAC11927CL};
+const BIG CURVE_Pybab= {0x269E06F295F7865L,0x2FC1D5BA1CE9A0EL,0x3631F3F1DACADD7L,0x30CCF3581D3943L,0x3FBE3B902505BB0L,0x23C4A9D31B36A49L,0x2056135CA438576L,0x2B78046739984F4L,0x12C0AC57B6F180EL,0xC48CA65BL};
+const BIG CURVE_Pybba= {0x1D83A9F67CC1979L,0x12ABE71DD89E6F0L,0x247B1C21635FDA9L,0x92880950076209L,0x2ECF179E0D733D7L,0x20D2DFFB53841F9L,0x3441B1645BC9FE8L,0x3089222CE22EC9DL,0x3699AE4108C86C5L,0x320034967L};
+const BIG CURVE_Pybbb= {0xFC89562FC9F25BL,0xB13E01AE9AB5D3L,0x18E8F169C9D264FL,0x3A5828D76B24A13L,0x1E8FD9BCEF84D9AL,0x36D20E3DBFEE16AL,0x17D3B3DF1AB4C1CL,0xF190510390F005L,0x12640E61B9BF549L,0x283D84D97L};
+const BIG CURVE_W[2]= {{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}};
+const BIG CURVE_SB[2][2]= {{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}}};
+const BIG CURVE_WB[4]= {{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}};
+const BIG CURVE_BB[4][4]= {{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}}};
+
+
+#endif
+
+}
diff --git a/version3/cpp/rom_curve_BN254.cpp b/version3/cpp/rom_curve_BN254.cpp
new file mode 100644
index 0000000..5a68453
--- /dev/null
+++ b/version3/cpp/rom_curve_BN254.cpp
@@ -0,0 +1,89 @@
+#include "arch.h"
+#include "ecp_BN254.h"
+
+namespace BN254 {
+
+/* Curve BN254 - Pairing friendly BN curve */
+
+/* Nogami's fast curve */
+
+#if CHUNK==16
+
+using namespace B256_13;
+
+const int CURVE_Cof_I=1;
+const int CURVE_A= 0;
+const int CURVE_B_I= 2;
+const BIG CURVE_B= {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Order= {0xD,0x0,0x0,0x0,0xA10,0x8,0x0,0x0,0x1F80,0x1FFC,0x1,0x0,0x1800,0x1A26,0x6E8,0x0,0x0,0x412,0x8D9,0x4A};
+const BIG CURVE_Gx= {0x12,0x0,0x0,0x0,0x1A70,0x9,0x0,0x0,0x100,0x309,0x2,0x0,0x1800,0x1A26,0x6E8,0x0,0x0,0x412,0x8D9,0x4A};
+const BIG CURVE_Gy= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+
+const BIG CURVE_Bnx= {0x1,0x0,0x0,0x0,0x408,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Cof= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Cru= {0x7,0x0,0x0,0x0,0xCD8,0x3,0x0,0x0,0x900,0x1248,0x0,0x0,0x400,0x19B1,0x126,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Pxa= {0x1B2B,0x1F,0x932,0x1C84,0x191E,0x1F86,0x262,0x1769,0x48B,0x1523,0x1B6D,0x18C3,0x7E8,0x6C6,0x1FAE,0x16C5,0x119E,0x5DA,0x684,0xC};
+const BIG CURVE_Pxb= {0xCF3,0x1EAA,0x1079,0x1869,0x10D8,0x25B,0x18DE,0xD75,0xD74,0x18FA,0xA96,0x1305,0x18C5,0x553,0xCC4,0xF06,0x1A73,0x17CD,0x5AA,0xA};
+const BIG CURVE_Pya= {0xB9A,0xE69,0x1E24,0x1C0,0x119F,0x4DE,0x16F8,0x1CD7,0x1D0A,0x194D,0x88,0x1319,0x966,0x870,0xE6A,0x1268,0xBAF,0x1D03,0x625,0x4};
+const BIG CURVE_Pyb= {0xE9B,0x19D6,0x1B1A,0x1A35,0x18A2,0x4AB,0x1CE7,0x1FFA,0x1006,0x1D84,0x34D,0xBE7,0x56F,0x16A2,0x1A3D,0x2A4,0x1C8B,0x1873,0xECA,0x1D};
+const BIG CURVE_W[2]= {{0x3,0x0,0x0,0x0,0x40,0x1,0x0,0x0,0x180,0x30C,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x0,0x0,0x0,0x810,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+const BIG CURVE_SB[2][2]= {{{0x4,0x0,0x0,0x0,0x850,0x1,0x0,0x0,0x180,0x30C,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x0,0x0,0x0,0x810,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x1,0x0,0x0,0x0,0x810,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xA,0x0,0x0,0x0,0x9D0,0x7,0x0,0x0,0x1E00,0x1CF0,0x1,0x0,0x1800,0x1A26,0x6E8,0x0,0x0,0x412,0x8D9,0x4A}}};
+const BIG CURVE_WB[4]= {{0x0,0x0,0x0,0x0,0x408,0x0,0x0,0x0,0x80,0x104,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x5,0x0,0x0,0x0,0x14A8,0x2,0x0,0x0,0x700,0xE38,0x0,0x0,0x1800,0x1120,0xC4,0x0,0x0,0x0,0x0,0x0},{0x3,0x0,0x0,0x0,0xC58,0x1,0x0,0x0,0x380,0x71C,0x0,0x0,0xC00,0x890,0x62,0x0,0x0,0x0,0x0,0x0},{0x1,0x0,0x0,0x0,0xC18,0x0,0x0,0x0,0x80,0x104,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+const BIG CURVE_BB[4][4]= {{{0xD,0x0,0x0,0x0,0x608,0x8,0x0,0x0,0x1F80,0x1FFC,0x1,0x0,0x1800,0x1A26,0x6E8,0x0,0x0,0x412,0x8D9,0x4A},{0xC,0x0,0x0,0x0,0x608,0x8,0x0,0x0,0x1F80,0x1FFC,0x1,0x0,0x1800,0x1A26,0x6E8,0x0,0x0,0x412,0x8D9,0x4A},{0xC,0x0,0x0,0x0,0x608,0x8,0x0,0x0,0x1F80,0x1FFC,0x1,0x0,0x1800,0x1A26,0x6E8,0x0,0x0,0x412,0x8D9,0x4A},{0x2,0x0,0x0,0x0,0x810,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x1,0x0,0x0,0x0,0x810,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xC,0x0,0x0,0x0,0x608,0x8,0x0,0x0,0x1F80,0x1FFC,0x1,0x0,0x1800,0x1A26,0x6E8,0x0,0x0,0x412,0x8D9,0x4A},{0xD,0x0,0x0,0x0,0x608,0x8,0x0,0x0,0x1F80,0x1FFC,0x1,0x0,0x1800,0x1A26,0x6E8,0x0,0x0,0x412,0x8D9,0x4A},{0xC,0x0,0x0,0x0,0x608,0x8,0x0,0x0,0x1F80,0x1FFC,0x1,0x0,0x1800,0x1A26,0x6E8,0x0,0x0,0x412,0x8D9,0x4A}},{{0x2,0x0,0x0,0x0,0x810,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x0,0x0,0x0,0x810,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x0,0x0,0x0,0x810,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x0,0x0,0x0,0x810,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x2,0x0,0x0,0x0,0x408,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x2,0x0,0x0,0x0,0x1020,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xA,0x0,0x0,0x0,0x200,0x8,0x0,0x0,0x1F80,0x1FFC,0x1,0x0,0x1800,0x1A26,0x6E8,0x0,0x0,0x412,0x8D9,0x4A},{0x2,0x0,0x0,0x0,0x408,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+
+
+#endif
+
+#if CHUNK==32
+
+using namespace B256_28;
+
+const int CURVE_Cof_I=1;
+const int CURVE_A= 0;
+const int CURVE_B_I= 2;
+const BIG CURVE_B= {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Order= {0xD,0x0,0x10A1,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2};
+const BIG CURVE_Gx= {0x12,0x0,0x13A7,0x0,0x86121,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2};
+const BIG CURVE_Gy= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+
+const BIG CURVE_Bnx= {0x1,0x8000000,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Cof= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Cru= {0x7,0x8000000,0x6CD,0x0,0x24909,0x4000000,0x49B362,0x0,0x0,0x0};
+const BIG CURVE_Pxa= {0x803FB2B,0xEE4224C,0x8BF0D91,0x8BBB489,0xDB6A464,0x7E8C61E,0xFEB8D8C,0x519EB62,0x61A10BB,0x0};
+const BIG CURVE_Pxb= {0x7D54CF3,0x8C34C1E,0x784B70D,0x746BAE3,0xA5B1F4D,0x8C5982A,0x3310AA7,0xBA73783,0x516AAF9,0x0};
+const BIG CURVE_Pya= {0x1CD2B9A,0xF0E0789,0xE09BD19,0xAE6BDB,0x22329BD,0x96698C8,0x39A90E0,0x6BAF934,0x21897A0,0x0};
+const BIG CURVE_Pyb= {0xB3ACE9B,0x2D1AEC6,0x9C9578A,0x6FFD73,0xD37B090,0x56F5F38,0x68F6D44,0x7C8B152,0xEBB2B0E,0x0};
+const BIG CURVE_W[2]= {{0x3,0x0,0x204,0x8000000,0x6181,0x0,0x0,0x0,0x0,0x0},{0x1,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+const BIG CURVE_SB[2][2]= {{{0x4,0x0,0x285,0x8000000,0x6181,0x0,0x0,0x0,0x0,0x0},{0x1,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x1,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xA,0x0,0xE9D,0x0,0x79E1E,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2}}};
+const BIG CURVE_WB[4]= {{0x0,0x8000000,0x40,0x8000000,0x2080,0x0,0x0,0x0,0x0,0x0},{0x5,0x8000000,0x54A,0x0,0x1C707,0x8000000,0x312241,0x0,0x0,0x0},{0x3,0x8000000,0x2C5,0x8000000,0xE383,0xC000000,0x189120,0x0,0x0,0x0},{0x1,0x8000000,0xC1,0x8000000,0x2080,0x0,0x0,0x0,0x0,0x0}};
+const BIG CURVE_BB[4][4]= {{{0xD,0x8000000,0x1060,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2},{0xC,0x8000000,0x1060,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2},{0xC,0x8000000,0x1060,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2},{0x2,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x1,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xC,0x8000000,0x1060,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2},{0xD,0x8000000,0x1060,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2},{0xC,0x8000000,0x1060,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2}},{{0x2,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x2,0x8000000,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x2,0x0,0x102,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xA,0x0,0x1020,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2},{0x2,0x8000000,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+#endif
+
+#if CHUNK==64
+
+using namespace B256_56;
+
+const int CURVE_Cof_I=1;
+const int CURVE_A= 0;
+const int CURVE_B_I= 2;
+const BIG CURVE_B= {0x2L,0x0L,0x0L,0x0L,0x0L};
+const BIG CURVE_Order= {0xDL,0x800000000010A1L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L};
+const BIG CURVE_Gx= {0x12L,0x13A7L,0x80000000086121L,0x40000001BA344DL,0x25236482L};
+const BIG CURVE_Gy= {0x1L,0x0L,0x0L,0x0L,0x0L};
+
+const BIG CURVE_Bnx= {0x80000000000001L,0x40L,0x0L,0x0L,0x0L};
+const BIG CURVE_Cof= {0x1L,0x0L,0x0L,0x0L,0x0L};
+const BIG CURVE_Cru= {0x80000000000007L,0x6CDL,0x40000000024909L,0x49B362L,0x0L};
+const BIG CURVE_Pxa= {0xEE4224C803FB2BL,0x8BBB4898BF0D91L,0x7E8C61EDB6A464L,0x519EB62FEB8D8CL,0x61A10BBL};
+const BIG CURVE_Pxb= {0x8C34C1E7D54CF3L,0x746BAE3784B70DL,0x8C5982AA5B1F4DL,0xBA737833310AA7L,0x516AAF9L};
+const BIG CURVE_Pya= {0xF0E07891CD2B9AL,0xAE6BDBE09BD19L,0x96698C822329BDL,0x6BAF93439A90E0L,0x21897A0L};
+const BIG CURVE_Pyb= {0x2D1AEC6B3ACE9BL,0x6FFD739C9578AL,0x56F5F38D37B090L,0x7C8B15268F6D44L,0xEBB2B0EL};
+const BIG CURVE_W[2]= {{0x3L,0x80000000000204L,0x6181L,0x0L,0x0L},{0x1L,0x81L,0x0L,0x0L,0x0L}};
+const BIG CURVE_SB[2][2]= {{{0x4L,0x80000000000285L,0x6181L,0x0L,0x0L},{0x1L,0x81L,0x0L,0x0L,0x0L}},{{0x1L,0x81L,0x0L,0x0L,0x0L},{0xAL,0xE9DL,0x80000000079E1EL,0x40000001BA344DL,0x25236482L}}};
+const BIG CURVE_WB[4]= {{0x80000000000000L,0x80000000000040L,0x2080L,0x0L,0x0L},{0x80000000000005L,0x54AL,0x8000000001C707L,0x312241L,0x0L},{0x80000000000003L,0x800000000002C5L,0xC000000000E383L,0x189120L,0x0L},{0x80000000000001L,0x800000000000C1L,0x2080L,0x0L,0x0L}};
+const BIG CURVE_BB[4][4]= {{{0x8000000000000DL,0x80000000001060L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L},{0x8000000000000CL,0x80000000001060L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L},{0x8000000000000CL,0x80000000001060L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L},{0x2L,0x81L,0x0L,0x0L,0x0L}},{{0x1L,0x81L,0x0L,0x0L,0x0L},{0x8000000000000CL,0x80000000001060L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L},{0x8000000000000DL,0x80000000001060L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L},{0x8000000000000CL,0x80000000001060L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L}},{{0x2L,0x81L,0x0L,0x0L,0x0L},{0x1L,0x81L,0x0L,0x0L,0x0L},{0x1L,0x81L,0x0L,0x0L,0x0L},{0x1L,0x81L,0x0L,0x0L,0x0L}},{{0x80000000000002L,0x40L,0x0L,0x0L,0x0L},{0x2L,0x102L,0x0L,0x0L,0x0L},{0xAL,0x80000000001020L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L},{0x80000000000002L,0x40L,0x0L,0x0L,0x0L}}};
+
+
+#endif
+
+}
diff --git a/version3/cpp/rom_curve_BN254CX.cpp b/version3/cpp/rom_curve_BN254CX.cpp
new file mode 100644
index 0000000..e7550e6
--- /dev/null
+++ b/version3/cpp/rom_curve_BN254CX.cpp
@@ -0,0 +1,83 @@
+#include "arch.h"
+#include "ecp_BN254CX.h"
+
+namespace BN254CX {
+
+/* Curve BN254CX - Pairing friendly BN curve */
+
+/* CertiVox BN curve/field  */
+
+
+#if CHUNK==16
+
+using namespace B256_13;
+
+const int CURVE_Cof_I=1;
+const int CURVE_A= 0;
+const int CURVE_B_I= 2;
+const BIG CURVE_B= {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Order= {0x1F6D,0x1758,0x98D,0x381,0xBE1,0x367,0x1324,0x1DC1,0x1FD6,0x1621,0x19B4,0x14C6,0x1647,0x1EEF,0x16C2,0x541,0x870,0x0,0x0,0x48};
+const BIG CURVE_Gx= {0x15B2,0xDA,0x1BD7,0xC47,0x1BE6,0x1F70,0x24,0x1DC3,0x1FD6,0x1921,0x19B4,0x14C6,0x1647,0x1EEF,0x16C2,0x541,0x870,0x0,0x0,0x48};
+const BIG CURVE_Gy= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Bnx= {0x12B1,0x1E00,0x0,0x0,0x400,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Cof= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Cru= {0x1C97,0x11A,0x5E5,0x126,0x31E,0x3AB,0x7BE,0xC8E,0x1DDF,0x205,0xFC5,0x1950,0x0,0x0,0x120,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Pxa= {0xAF5,0x1AFD,0x1B2,0x7D0,0x51C,0x1B14,0xE64,0x1CC3,0xFB8,0x4A2,0x10BC,0x1633,0x73C,0x90E,0x1E9C,0x1369,0x1F9A,0x12DB,0x1256,0x35};
+const BIG CURVE_Pxb= {0x1433,0xAF,0x183F,0xA00,0x1EDE,0x4A6,0xF68,0x1435,0x1A33,0xDD,0xD93,0x103E,0xD16,0x8E1,0x10FC,0xCC0,0x365,0x8,0xF4C,0xA};
+const BIG CURVE_Pya= {0x299,0x1B95,0x1AA5,0x642,0x683,0x427,0x1A8D,0x126D,0x1FF0,0x3CE,0x1019,0x1230,0x1FEF,0x35D,0xBB8,0xDF6,0x109E,0xB85,0x1C9E,0x2A};
+const BIG CURVE_Pyb= {0x8CD,0x24F,0x7E7,0x1782,0x1C41,0x10D6,0x681,0xC12,0x5,0x1699,0x59,0xC0E,0x17F5,0x1DEB,0x1F55,0x313,0x2AC,0xB60,0xF2D,0x23};
+const BIG CURVE_W[2]= {{0xB83,0x117F,0x1245,0x8C6,0x5,0x1C09,0xD00,0x1,0x0,0x300,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x561,0x1C01,0x1,0x0,0x800,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+const BIG CURVE_SB[2][2]= {{{0x10E4,0xD80,0x1247,0x8C6,0x805,0x1C09,0xD00,0x1,0x0,0x300,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x561,0x1C01,0x1,0x0,0x800,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x561,0x1C01,0x1,0x0,0x800,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x13EA,0x5D9,0x1748,0x1ABA,0xBDB,0x75E,0x623,0x1DC0,0x1FD6,0x1321,0x19B4,0x14C6,0x1647,0x1EEF,0x16C2,0x541,0x870,0x0,0x0,0x48}}};
+const BIG CURVE_WB[4]= {{0x4B0,0x13D4,0x615,0x1842,0x401,0x958,0xF00,0x0,0x0,0x100,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x475,0x1110,0x56F,0x1BF3,0x36C,0x1FCD,0x329,0x1DB5,0x1E94,0xE03,0xA83,0x10E0,0x0,0x0,0xC0,0x0,0x0,0x0,0x0,0x0},{0xB93,0x788,0x12B8,0xDF9,0x13B6,0x1FE6,0x1194,0xEDA,0x1F4A,0x1701,0x541,0x870,0x0,0x0,0x60,0x0,0x0,0x0,0x0,0x0},{0xA11,0xFD5,0x617,0x1842,0xC01,0x958,0xF00,0x0,0x0,0x100,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+const BIG CURVE_BB[4][4]= {{{0xCBD,0x1958,0x98C,0x381,0x7E1,0x367,0x1324,0x1DC1,0x1FD6,0x1621,0x19B4,0x14C6,0x1647,0x1EEF,0x16C2,0x541,0x870,0x0,0x0,0x48},{0xCBC,0x1958,0x98C,0x381,0x7E1,0x367,0x1324,0x1DC1,0x1FD6,0x1621,0x19B4,0x14C6,0x1647,0x1EEF,0x16C2,0x541,0x870,0x0,0x0,0x48},{0xCBC,0x1958,0x98C,0x381,0x7E1,0x367,0x1324,0x1DC1,0x1FD6,0x1621,0x19B4,0x14C6,0x1647,0x1EEF,0x16C2,0x541,0x870,0x0,0x0,0x48},{0x562,0x1C01,0x1,0x0,0x800,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x561,0x1C01,0x1,0x0,0x800,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xCBC,0x1958,0x98C,0x381,0x7E1,0x367,0x1324,0x1DC1,0x1FD6,0x1621,0x19B4,0x14C6,0x1647,0x1EEF,0x16C2,0x541,0x870,0x0,0x0,0x48},{0xCBD,0x1958,0x98C,0x381,0x7E1,0x367,0x1324,0x1DC1,0x1FD6,0x1621,0x19B4,0x14C6,0x1647,0x1EEF,0x16C2,0x541,0x870,0x0,0x0,0x48},{0xCBC,0x1958,0x98C,0x381,0x7E1,0x367,0x1324,0x1DC1,0x1FD6,0x1621,0x19B4,0x14C6,0x1647,0x1EEF,0x16C2,0x541,0x870,0x0,0x0,0x48}},{{0x562,0x1C01,0x1,0x0,0x800,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x561,0x1C01,0x1,0x0,0x800,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x561,0x1C01,0x1,0x0,0x800,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x561,0x1C01,0x1,0x0,0x800,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x12B2,0x1E00,0x0,0x0,0x400,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xAC2,0x1802,0x3,0x0,0x1000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1A0A,0x1B57,0x98B,0x381,0x3E1,0x367,0x1324,0x1DC1,0x1FD6,0x1621,0x19B4,0x14C6,0x1647,0x1EEF,0x16C2,0x541,0x870,0x0,0x0,0x48},{0x12B2,0x1E00,0x0,0x0,0x400,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+#endif
+
+#if CHUNK==32
+
+using namespace B256_28;
+
+const int CURVE_Cof_I=1;
+const int CURVE_A= 0;
+const int CURVE_B_I= 2;
+const BIG CURVE_B= {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Order= {0x6EB1F6D,0x11C0A63,0x906CEBE,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2};
+const BIG CURVE_Gx= {0xC1B55B2,0x6623EF5,0x93EE1BE,0xD6EE180,0x6D3243F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2};
+const BIG CURVE_Gy= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Bnx= {0x3C012B1,0x0,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Cof= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Cru= {0x4235C97,0xE093179,0xF875631,0xDF6471E,0xF1440BD,0xCA83,0x480000,0x0,0x0,0x0};
+const BIG CURVE_Pxa= {0xB5FAAF5,0xC3E806C,0x9362851,0xB8E61B9,0x2F0944F,0x73CB19C,0xFA7121C,0x7F9A9B4,0xAC95A5B,0x1};
+const BIG CURVE_Pxb= {0xC15F433,0xE50060F,0xA094DED,0x33A1ABD,0x64C1BBA,0xD1681F3,0x43F11C2,0x365660,0x53D3001,0x0};
+const BIG CURVE_Pya= {0x772A299,0x33216A9,0x3484E68,0xF0936EA,0x6479DF,0xFEF9184,0x2EE06BB,0xB09E6FB,0x5727970,0x1};
+const BIG CURVE_Pyb= {0xC49E8CD,0x1BC11F9,0x61ADC4,0x56091A,0x166D320,0x7F56070,0xFD57BD7,0x2AC189,0x1BCB56C,0x1};
+const BIG CURVE_W[2]= {{0x62FEB83,0x5463491,0x381200,0xB4,0x6000,0x0,0x0,0x0,0x0,0x0},{0x7802561,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+const BIG CURVE_SB[2][2]= {{{0xDB010E4,0x5463491,0x381280,0xB4,0x6000,0x0,0x0,0x0,0x0,0x0},{0x7802561,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x7802561,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xBB33EA,0xBD5D5D2,0x8CEBCBD,0xD6EE018,0x6D2643F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2}}};
+const BIG CURVE_WB[4]= {{0x67A84B0,0x1C21185,0x12B040,0x3C,0x2000,0x0,0x0,0x0,0x0,0x0},{0xE220475,0xCDF995B,0xA7F9A36,0x94EDA8C,0xA0DC07E,0x8702,0x300000,0x0,0x0,0x0},{0xF10B93,0x66FCCAE,0x53FCD3B,0x4A76D46,0x506E03F,0x4381,0x180000,0x0,0x0,0x0},{0xDFAAA11,0x1C21185,0x12B0C0,0x3C,0x2000,0x0,0x0,0x0,0x0,0x0}};
+const BIG CURVE_BB[4][4]= {{{0x32B0CBD,0x11C0A63,0x906CE7E,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2},{0x32B0CBC,0x11C0A63,0x906CE7E,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2},{0x32B0CBC,0x11C0A63,0x906CE7E,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2},{0x7802562,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x7802561,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x32B0CBC,0x11C0A63,0x906CE7E,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2},{0x32B0CBD,0x11C0A63,0x906CE7E,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2},{0x32B0CBC,0x11C0A63,0x906CE7E,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2}},{{0x7802562,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x7802561,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x7802561,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x7802561,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x3C012B2,0x0,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xF004AC2,0x0,0x100,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xF6AFA0A,0x11C0A62,0x906CE3E,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2},{0x3C012B2,0x0,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+#endif
+
+#if CHUNK==64
+
+using namespace B256_56;
+
+const int CURVE_Cof_I=1;
+const int CURVE_A= 0;
+const int CURVE_B_I= 2;
+const BIG CURVE_B= {0x2L,0x0L,0x0L,0x0L,0x0L};
+const BIG CURVE_Order= {0x11C0A636EB1F6DL,0xD6EE0CC906CEBEL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L};
+const BIG CURVE_Gx= {0x6623EF5C1B55B2L,0xD6EE18093EE1BEL,0x647A6366D3243FL,0x8702A0DB0BDDFL,0x24000000L};
+const BIG CURVE_Gy= {0x1L,0x0L,0x0L,0x0L,0x0L};
+const BIG CURVE_Bnx= {0x3C012B1L,0x40L,0x0L,0x0L,0x0L};
+const BIG CURVE_Cof= {0x1L,0x0L,0x0L,0x0L,0x0L};
+const BIG CURVE_Cru= {0xE0931794235C97L,0xDF6471EF875631L,0xCA83F1440BDL,0x480000L,0x0L};
+const BIG CURVE_Pxa= {0xC3E806CB5FAAF5L,0xB8E61B99362851L,0x73CB19C2F0944FL,0x7F9A9B4FA7121CL,0x1AC95A5BL};
+const BIG CURVE_Pxb= {0xE50060FC15F433L,0x33A1ABDA094DEDL,0xD1681F364C1BBAL,0x36566043F11C2L,0x53D3001L};
+const BIG CURVE_Pya= {0x33216A9772A299L,0xF0936EA3484E68L,0xFEF918406479DFL,0xB09E6FB2EE06BBL,0x15727970L};
+const BIG CURVE_Pyb= {0x1BC11F9C49E8CDL,0x56091A061ADC4L,0x7F56070166D320L,0x2AC189FD57BD7L,0x11BCB56CL};
+const BIG CURVE_W[2]= {{0x546349162FEB83L,0xB40381200L,0x6000L,0x0L,0x0L},{0x7802561L,0x80L,0x0L,0x0L,0x0L}};
+const BIG CURVE_SB[2][2]= {{{0x5463491DB010E4L,0xB40381280L,0x6000L,0x0L,0x0L},{0x7802561L,0x80L,0x0L,0x0L,0x0L}},{{0x7802561L,0x80L,0x0L,0x0L,0x0L},{0xBD5D5D20BB33EAL,0xD6EE0188CEBCBDL,0x647A6366D2643FL,0x8702A0DB0BDDFL,0x24000000L}}};
+const BIG CURVE_WB[4]= {{0x1C2118567A84B0L,0x3C012B040L,0x2000L,0x0L,0x0L},{0xCDF995BE220475L,0x94EDA8CA7F9A36L,0x8702A0DC07EL,0x300000L,0x0L},{0x66FCCAE0F10B93L,0x4A76D4653FCD3BL,0x4381506E03FL,0x180000L,0x0L},{0x1C21185DFAAA11L,0x3C012B0C0L,0x2000L,0x0L,0x0L}};
+const BIG CURVE_BB[4][4]= {{{0x11C0A6332B0CBDL,0xD6EE0CC906CE7EL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L},{0x11C0A6332B0CBCL,0xD6EE0CC906CE7EL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L},{0x11C0A6332B0CBCL,0xD6EE0CC906CE7EL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L},{0x7802562L,0x80L,0x0L,0x0L,0x0L}},{{0x7802561L,0x80L,0x0L,0x0L,0x0L},{0x11C0A6332B0CBCL,0xD6EE0CC906CE7EL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L},{0x11C0A6332B0CBDL,0xD6EE0CC906CE7EL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L},{0x11C0A6332B0CBCL,0xD6EE0CC906CE7EL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L}},{{0x7802562L,0x80L,0x0L,0x0L,0x0L},{0x7802561L,0x80L,0x0L,0x0L,0x0L},{0x7802561L,0x80L,0x0L,0x0L,0x0L},{0x7802561L,0x80L,0x0L,0x0L,0x0L}},{{0x3C012B2L,0x40L,0x0L,0x0L,0x0L},{0xF004AC2L,0x100L,0x0L,0x0L,0x0L},{0x11C0A62F6AFA0AL,0xD6EE0CC906CE3EL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L},{0x3C012B2L,0x40L,0x0L,0x0L,0x0L}}};
+#endif
+
+}
diff --git a/version3/cpp/rom_curve_BRAINPOOL.cpp b/version3/cpp/rom_curve_BRAINPOOL.cpp
new file mode 100644
index 0000000..d983d33
--- /dev/null
+++ b/version3/cpp/rom_curve_BRAINPOOL.cpp
@@ -0,0 +1,43 @@
+#include "arch.h"
+#include "ecp_BRAINPOOL.h"
+
+namespace BRAINPOOL {
+
+/* Brainpool Curve  */
+/* Note that the original curve has been transformed to an isomorphic curve with A=-3 */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+using namespace B256_28;
+
+const int CURVE_Cof_I=1;
+const BIG CURVE_Cof= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const int CURVE_A= -3;
+const int CURVE_B_I= 0;
+const BIG CURVE_B= {0xEE92B04,0xE58101F,0xF49256A,0xEBC4AF2,0x6B7BF93,0x733D0B7,0x4FE66A7,0x30D84EA,0x62C61C4,0x6};
+const BIG CURVE_Order= {0x74856A7,0x1E0E829,0x1A6F790,0x7AA3B56,0xD718C39,0x909D838,0xC3E660A,0xA1EEA9B,0x9FB57DB,0xA};
+const BIG CURVE_Gx= {0xE1305F4,0xA191562,0xFBC2B79,0x42C47AA,0x149AFA1,0xB23A656,0x7732213,0xC1CFE7B,0x3E8EB3C,0xA};
+const BIG CURVE_Gy= {0xB25C9BE,0xABE8F35,0x27001D,0xB6DE39D,0x17E69BC,0xE146444,0xD7F7B22,0x3439C56,0xD996C82,0x2};
+#endif
+
+#if CHUNK==64
+
+using namespace B256_56;
+
+const int CURVE_Cof_I=1;
+const BIG CURVE_Cof= {0x1L,0x0L,0x0L,0x0L,0x0L};
+const int CURVE_A= -3;
+const int CURVE_B_I= 0;
+const BIG CURVE_B= {0xE58101FEE92B04L,0xEBC4AF2F49256AL,0x733D0B76B7BF93L,0x30D84EA4FE66A7L,0x662C61C4L};
+const BIG CURVE_Order= {0x1E0E82974856A7L,0x7AA3B561A6F790L,0x909D838D718C39L,0xA1EEA9BC3E660AL,0xA9FB57DBL};
+const BIG CURVE_Gx= {0xA191562E1305F4L,0x42C47AAFBC2B79L,0xB23A656149AFA1L,0xC1CFE7B7732213L,0xA3E8EB3CL};
+const BIG CURVE_Gy= {0xABE8F35B25C9BEL,0xB6DE39D027001DL,0xE14644417E69BCL,0x3439C56D7F7B22L,0x2D996C82L};
+#endif
+
+}
diff --git a/version3/cpp/rom_curve_C25519.cpp b/version3/cpp/rom_curve_C25519.cpp
new file mode 100644
index 0000000..8f29c1d
--- /dev/null
+++ b/version3/cpp/rom_curve_C25519.cpp
@@ -0,0 +1,36 @@
+#include "arch.h"
+#include "ecp_C25519.h"
+
+namespace C25519 {
+
+/* Curve 25519 */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+using namespace B256_29;
+
+const int CURVE_Cof_I=8;
+const BIG CURVE_Cof= {0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const int CURVE_A=486662;
+const BIG CURVE_Order= {0x1CF5D3ED,0x9318D2,0x1DE73596,0x1DF3BD45,0x14D,0x0,0x0,0x0,0x100000};
+const BIG CURVE_Gx= {0x9};
+#endif
+
+#if CHUNK==64
+
+using namespace B256_56;
+
+const int CURVE_Cof_I=8;
+const BIG CURVE_Cof= {0x8L,0x0L,0x0L,0x0L,0x0L};
+const int CURVE_A=486662;
+const BIG CURVE_Order= {0x12631A5CF5D3ED,0xF9DEA2F79CD658,0x14DE,0x0,0x10000000};
+const BIG CURVE_Gx= {0x9};
+#endif
+
+}
diff --git a/version3/cpp/rom_curve_C41417.cpp b/version3/cpp/rom_curve_C41417.cpp
new file mode 100644
index 0000000..f7f1950
--- /dev/null
+++ b/version3/cpp/rom_curve_C41417.cpp
@@ -0,0 +1,42 @@
+#include "arch.h"
+#include "ecp_C41417.h"
+
+namespace C41417 {
+
+/* Curve C41417 */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+using namespace B416_29;
+
+const int CURVE_Cof_I=8;
+const BIG CURVE_Cof= {0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const int CURVE_A= 1;
+const int CURVE_B_I= 3617;
+const BIG CURVE_B= {0xE21,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Order= {0x106AF79,0x18738D2F,0x18F3C606,0x1806715A,0x22B36F1,0xA67B830,0xCF32490,0x1FFFFFFD,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1F};
+const BIG CURVE_Gx= {0x13CBC595,0x7E9C097,0x14DF1931,0x14E7F550,0x1A111301,0x15A6B6B5,0xD526292,0x18FEAFFE,0x1F44C03E,0x1E6A31B4,0x70C9B97,0x43180C6,0x1443300,0x19A4828A,0x68};
+const BIG CURVE_Gy= {0x22,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+#endif
+
+#if CHUNK==64
+
+using namespace B416_60;
+
+const int CURVE_Cof_I=8;
+const BIG CURVE_Cof= {0x8L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const int CURVE_A= 1;
+const int CURVE_B_I= 3617;
+const BIG CURVE_B= {0xE21L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG CURVE_Order= {0xB0E71A5E106AF79L,0x1C0338AD63CF181L,0x414CF706022B36FL,0xFFFFFFFFEB3CC92L,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0x7FFFFFFFFFFFFL};
+const BIG CURVE_Gx= {0x4FD3812F3CBC595L,0x1A73FAA8537C64CL,0x4AB4D6D6BA11130L,0x3EC7F57FF35498AL,0xE5FCD46369F44C0L,0x300218C0631C326L,0x1A334905141443L};
+const BIG CURVE_Gy= {0x22L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+#endif
+
+}
diff --git a/version3/cpp/rom_curve_ED25519.cpp b/version3/cpp/rom_curve_ED25519.cpp
new file mode 100644
index 0000000..4e9b8e0
--- /dev/null
+++ b/version3/cpp/rom_curve_ED25519.cpp
@@ -0,0 +1,54 @@
+#include "arch.h"
+#include "ecp_ED25519.h"
+
+namespace ED25519 {
+
+/* ED25519 */
+
+#if CHUNK==16
+/* Ed25519 Curve */
+
+using namespace B256_13;
+
+const int CURVE_Cof_I=8;
+const BIG CURVE_Cof= {0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const int CURVE_A= -1;
+const int CURVE_B_I= 0;
+const BIG CURVE_B= {0x18A3,0x1ACB,0x1284,0x169B,0x175E,0xC55,0x507,0x9A8,0x100A,0x3,0x1A26,0xEF3,0x797,0x3A0,0xE33,0x1FCE,0xB6F,0x771,0xDB,0xA4};
+const BIG CURVE_Order= {0x13ED,0x7AE,0x697,0x4C6,0x581,0xE6B,0xBDE,0x1BD4,0x1EF9,0xA6,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20};
+const BIG CURVE_Gx= {0x151A,0x192E,0x1823,0xC5A,0xC95,0x13D9,0x1496,0xC12,0xCC7,0x349,0x1717,0x1BAD,0x31F,0x1271,0x1B02,0xA7F,0xD6E,0x169E,0x1A4D,0x42};
+const BIG CURVE_Gy= {0x658,0x1333,0x1999,0xCCC,0x666,0x1333,0x1999,0xCCC,0x666,0x1333,0x1999,0xCCC,0x666,0x1333,0x1999,0xCCC,0x666,0x1333,0x1999,0xCC};
+#endif
+
+#if CHUNK==32
+
+using namespace B256_29;
+
+const int CURVE_Cof_I=8;
+const BIG CURVE_Cof= {0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const int CURVE_A= -1;
+const int CURVE_B_I= 0;
+const BIG CURVE_B= {0x135978A3,0xF5A6E50,0x10762ADD,0x149A82,0x1E898007,0x3CBBBC,0x19CE331D,0x1DC56DFF,0x52036C};
+const BIG CURVE_Order= {0x1CF5D3ED,0x9318D2,0x1DE73596,0x1DF3BD45,0x14D,0x0,0x0,0x0,0x100000};
+const BIG CURVE_Gx= {0xF25D51A,0xAB16B04,0x969ECB2,0x198EC12A,0xDC5C692,0x1118FEEB,0xFFB0293,0x1A79ADCA,0x216936};
+const BIG CURVE_Gy= {0x6666658,0x13333333,0x19999999,0xCCCCCCC,0x6666666,0x13333333,0x19999999,0xCCCCCCC,0x666666};
+
+
+#endif
+
+#if CHUNK==64
+
+using namespace B256_56;
+
+const int CURVE_Cof_I=8;
+const BIG CURVE_Cof= {0x8L,0x0L,0x0L,0x0L,0x0L};
+const int CURVE_A= -1;
+const int CURVE_B_I= 0;
+const BIG CURVE_B= {0xEB4DCA135978A3L,0xA4D4141D8AB75L,0x797779E8980070L,0x2B6FFE738CC740L,0x52036CEEL};
+const BIG CURVE_Order= {0x12631A5CF5D3EDL,0xF9DEA2F79CD658L,0x14DEL,0x0L,0x10000000L};
+const BIG CURVE_Gx= {0x562D608F25D51AL,0xC7609525A7B2C9L,0x31FDD6DC5C692CL,0xCD6E53FEC0A4E2L,0x216936D3L};
+const BIG CURVE_Gy= {0x66666666666658L,0x66666666666666L,0x66666666666666L,0x66666666666666L,0x66666666L};
+
+#endif
+
+}
diff --git a/version3/cpp/rom_curve_FP256BN.cpp b/version3/cpp/rom_curve_FP256BN.cpp
new file mode 100644
index 0000000..a8d0b3b
--- /dev/null
+++ b/version3/cpp/rom_curve_FP256BN.cpp
@@ -0,0 +1,86 @@
+#include "arch.h"
+#include "ecp_FP256BN.h"
+
+namespace FP256BN {
+
+/* Curve BN254 - Pairing friendly BN curve */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+using namespace B256_28;
+
+const int CURVE_Cof_I=1;
+const int CURVE_A= 0;
+const int CURVE_B_I= 3;
+const BIG CURVE_B= {0x3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Order= {0x10B500D,0x2D536CD,0x9921AF6,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF};
+const BIG CURVE_Gx= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Gy= {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+
+const BIG CURVE_Bnx= {0xB0A801,0x82F5C03,0x68,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Cof= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Cru= {0x3A1B807,0x1C0A24A,0x32D1EDB,0xD79DF19,0x8659BCD,0x4092101,0x13988E1,0x0,0x0,0x0};
+const BIG CURVE_Pxa= {0x9C09EFB,0x2616B68,0xF843CD2,0x539A12B,0x13ACE1C,0x577C289,0x28560F,0xB4C96C2,0xE0C3350,0xF};
+const BIG CURVE_Pxb= {0x37E6A2B,0x69ED34A,0x3589D2,0x78E287D,0x3B924DD,0xC637D81,0x4DB5AE1,0x738AC05,0xEA66057,0x4};
+const BIG CURVE_Pya= {0xEDC27FF,0x9B481B,0x15848E9,0x24758D6,0xE51EFCB,0x75124E3,0x376770D,0xC542A3B,0x2046E7,0x7};
+const BIG CURVE_Pyb= {0xAAD049B,0x1281114,0xA98B3E0,0xBE80821,0x29F8B4C,0x49297EB,0x42EEA6,0xD388C29,0x554E3BC,0x0};
+const BIG CURVE_W[2]= {{0xB054003,0xF0036E1,0xE78663A,0xFFFFFFF,0xFFFF,0x0,0x0,0x0,0x0,0x0},{0x1615001,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+const BIG CURVE_SB[2][2]= {{{0xC669004,0xF5EEEE7,0xE78670B,0xFFFFFFF,0xFFFF,0x0,0x0,0x0,0x0,0x0},{0x1615001,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x1615001,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x606100A,0x3D4FFEB,0xB19B4BB,0x65FB129,0x49D0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF}}};
+const BIG CURVE_WB[4]= {{0xD30A800,0x20678F0,0x4D2CC10,0x5555555,0x5555,0x0,0x0,0x0,0x0,0x0},{0xD7DC805,0xD6764C0,0xBC3AD1A,0x8FBEA10,0x4467DE,0x8061601,0xD105EB,0x0,0x0,0x0},{0xF173803,0xACB6061,0x5E1D6C1,0x47DF508,0x82233EF,0xC030B00,0x6882F5,0x0,0x0,0x0},{0xE91F801,0x26530F6,0x4D2CCE1,0x5555555,0x5555,0x0,0x0,0x0,0x0,0x0}};
+const BIG CURVE_BB[4][4]= {{{0x5AA80D,0xAA5DACA,0x9921A8D,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF},
+                                           {0x5AA80C,0xAA5DACA,0x9921A8D,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF},
+	                                       {0x5AA80C,0xAA5DACA,0x9921A8D,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF},
+	                                       {0x1615002,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},
+	                                       {{0x1615001,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
+	                                        {0x5AA80C,0xAA5DACA,0x9921A8D,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF},
+	                                        {0x5AA80D,0xAA5DACA,0x9921A8D,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF},
+	                                        {0x5AA80C,0xAA5DACA,0x9921A8D,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF}},
+	                                        {{0x1615002,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
+	                                         {0x1615001,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
+	                                         {0x1615001,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
+	                                         {0x1615001,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},
+	                                         {{0xB0A802,0x82F5C03,0x68,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
+	                                          {0x2C2A002,0xBD700C,0x1A2,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
+	                                          {0xFAA000A,0x2767EC6,0x9921A25,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF},
+	                                          {0xB0A802,0x82F5C03,0x68,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+
+
+
+
+#endif
+
+#if CHUNK==64
+
+using namespace B256_56;
+
+const int CURVE_Cof_I=1;
+const int CURVE_A= 0;
+const int CURVE_B_I= 3;
+const BIG CURVE_B= {0x3L,0x0L,0x0L,0x0L,0x0L};
+const BIG CURVE_Order= {0x2D536CD10B500DL,0x65FB1299921AF6L,0x5EEE71A49E0CDCL,0xFFFCF0CD46E5F2L,0xFFFFFFFFL};
+const BIG CURVE_Gx= {0x1L,0x0L,0x0L,0x0L,0x0L};
+const BIG CURVE_Gy= {0x2L,0x0L,0x0L,0x0L,0x0L};
+
+const BIG CURVE_Bnx= {0x82F5C030B0A801L,0x68L,0x0L,0x0L,0x0L};
+const BIG CURVE_Cof= {0x1L,0x0L,0x0L,0x0L,0x0L};
+const BIG CURVE_Cru= {0x1C0A24A3A1B807L,0xD79DF1932D1EDBL,0x40921018659BCDL,0x13988E1L,0x0L};
+const BIG CURVE_Pxa= {0x2616B689C09EFBL,0x539A12BF843CD2L,0x577C28913ACE1CL,0xB4C96C2028560FL,0xFE0C3350L};
+const BIG CURVE_Pxb= {0x69ED34A37E6A2BL,0x78E287D03589D2L,0xC637D813B924DDL,0x738AC054DB5AE1L,0x4EA66057L};
+const BIG CURVE_Pya= {0x9B481BEDC27FFL,0x24758D615848E9L,0x75124E3E51EFCBL,0xC542A3B376770DL,0x702046E7L};
+const BIG CURVE_Pyb= {0x1281114AAD049BL,0xBE80821A98B3E0L,0x49297EB29F8B4CL,0xD388C29042EEA6L,0x554E3BCL};
+const BIG CURVE_W[2]= {{0xF0036E1B054003L,0xFFFFFFFE78663AL,0xFFFFL,0x0L,0x0L},{0x5EB8061615001L,0xD1L,0x0L,0x0L,0x0L}};
+const BIG CURVE_SB[2][2]= {{{0xF5EEEE7C669004L,0xFFFFFFFE78670BL,0xFFFFL,0x0L,0x0L},{0x5EB8061615001L,0xD1L,0x0L,0x0L,0x0L}},{{0x5EB8061615001L,0xD1L,0x0L,0x0L,0x0L},{0x3D4FFEB606100AL,0x65FB129B19B4BBL,0x5EEE71A49D0CDCL,0xFFFCF0CD46E5F2L,0xFFFFFFFFL}}};
+const BIG CURVE_WB[4]= {{0x20678F0D30A800L,0x55555554D2CC10L,0x5555L,0x0L,0x0L},{0xD6764C0D7DC805L,0x8FBEA10BC3AD1AL,0x806160104467DEL,0xD105EBL,0x0L},{0xACB6061F173803L,0x47DF5085E1D6C1L,0xC030B0082233EFL,0x6882F5L,0x0L},{0x26530F6E91F801L,0x55555554D2CCE1L,0x5555L,0x0L,0x0L}};
+const BIG CURVE_BB[4][4]= {{{0xAA5DACA05AA80DL,0x65FB1299921A8DL,0x5EEE71A49E0CDCL,0xFFFCF0CD46E5F2L,0xFFFFFFFFL},{0xAA5DACA05AA80CL,0x65FB1299921A8DL,0x5EEE71A49E0CDCL,0xFFFCF0CD46E5F2L,0xFFFFFFFFL},{0xAA5DACA05AA80CL,0x65FB1299921A8DL,0x5EEE71A49E0CDCL,0xFFFCF0CD46E5F2L,0xFFFFFFFFL},{0x5EB8061615002L,0xD1L,0x0L,0x0L,0x0L}},{{0x5EB8061615001L,0xD1L,0x0L,0x0L,0x0L},{0xAA5DACA05AA80CL,0x65FB1299921A8DL,0x5EEE71A49E0CDCL,0xFFFCF0CD46E5F2L,0xFFFFFFFFL},{0xAA5DACA05AA80DL,0x65FB1299921A8DL,0x5EEE71A49E0CDCL,0xFFFCF0CD46E5F2L,0xFFFFFFFFL},{0xAA5DACA05AA80CL,0x65FB1299921A8DL,0x5EEE71A49E0CDCL,0xFFFCF0CD46E5F2L,0xFFFFFFFFL}},{{0x5EB8061615002L,0xD1L,0x0L,0x0L,0x0L},{0x5EB8061615001L,0xD1L,0x0L,0x0L,0x0L},{0x5EB8061615001L,0xD1L,0x0L,0x0L,0x0L},{0x5EB8061615001L,0xD1L,0x0L,0x0L,0x0L}},{{0x82F5C030B0A802L,0x68L,0x0L,0x0L,0x0L},{0xBD700C2C2A002L,0x1A2L,0x0L,0x0L,0x0L},{0x2767EC6FAA000AL,0x65FB1299921A25L,0x5EEE71A49E0CDCL,0xFFFCF0CD46E5F2L,0xFFFFFFFFL},{0x82F5C030B0A802L,0x68L,0x0L,0x0L,0x0L}}};
+
+
+
+#endif
+
+}
diff --git a/version3/cpp/rom_curve_FP512BN.cpp b/version3/cpp/rom_curve_FP512BN.cpp
new file mode 100644
index 0000000..ae2564c
--- /dev/null
+++ b/version3/cpp/rom_curve_FP512BN.cpp
@@ -0,0 +1,88 @@
+#include "arch.h"
+#include "ecp_FP512BN.h"
+
+namespace FP512BN {
+
+/* Curve FP512BN - Pairing friendly BN curve */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+using namespace B512_29;
+
+const int CURVE_Cof_I=1;
+const int CURVE_A= 0;
+const int CURVE_B_I= 3;
+const BIG CURVE_B= {0x3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Order= {0x119A09ED,0x153252FA,0x1E68AD01,0x627C09,0x79A34A1,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF};
+const BIG CURVE_Gx= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Gy= {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+
+const BIG CURVE_Bnx= {0x1E1BD80F,0x59835DA,0xC3DFC04,0x5EB8061,0x688,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Cof= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+
+const BIG CURVE_Cru= {0x1C79298A,0x1838B104,0x2C5F052,0x1DCCF337,0x6092AEC,0x4B35F29,0x1EB361E,0x11384EA,0x3074B20,0x17BB08FD,0x3A8B3E3,0xD70D66F,0x3D2A614,0x1CF63EE4,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF};
+
+const BIG CURVE_Pxa= {0xDB646B5,0x183D4B70,0x1CBFFA3,0x11F0E632,0x1C78F221,0x1F10DE5D,0x171B715E,0xF0C6A29,0x10B02453,0xBE63C66,0xE6D5F69,0x166B1E1B,0x4BBBD29,0x179E750F,0x6E9D04,0xC912B10,0x1339E138,0x1D8B2};
+const BIG CURVE_Pxb= {0x1A8AE0E9,0xDAE5F7E,0x22446CF,0x1948239B,0x15ADCE40,0xB709C1E,0x18357943,0xE50AA4D,0x19781E22,0x12B35CA6,0x11DAA2C0,0x18D8DDE4,0x5EA656D,0x15F45A41,0xD311A02,0xCFCD913,0x13CBF850,0x240E0};
+const BIG CURVE_Pya= {0xDDE67A1,0x12401895,0x17BEE178,0x142F5AC2,0xB7BC5CD,0x92A1404,0x1A3B748C,0x17BD82A7,0x14B6CD18,0xAC34CE,0x1740FB97,0x1ECC15F9,0x17085B1D,0x1D1BA793,0x1BD6AC32,0x18F70525,0xC84C827,0x3780F};
+const BIG CURVE_Pyb= {0x84F8E8B,0xC5B8C36,0xFDD85A1,0xB84449,0x19C08DFF,0x56BF713,0x1C5290C4,0x187C5CA0,0x1DA2897F,0x24B0CA0,0x326D8F4,0x2310CF6,0x1021438C,0xFBAEC8F,0xD9030C5,0x1CF06358,0x1CEC8B04,0x28D1D};
+const BIG CURVE_W[2]= {{0x9834583,0x887C4BA,0x5A85CFC,0xBF7223A,0xF63FE96,0x1FFFFFFE,0x1FFFFFFF,0x1FFFFFFF,0xFFFFFF,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1C37B01F,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+const BIG CURVE_SB[2][2]= {{{0xD4B9564,0x1D575904,0xD2C64F3,0x202177,0xF63F186,0x1FFFFFFE,0x1FFFFFFF,0x1FFFFFFF,0xFFFFFF,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x156259CE,0xA01E744,0x5ECB4F9,0x148B7B47,0x79A2790,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF}},{{0x1C37B01F,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x9834583,0x887C4BA,0x5A85CFC,0xBF7223A,0xF63FE96,0x1FFFFFFE,0x1FFFFFFF,0x1FFFFFFF,0xFFFFFF,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+const BIG CURVE_WB[4]= {{0x155A29F0,0x16D59B55,0xF4C305,0x18858C0B,0x5215FBF,0xAAAAAAA,0x15555555,0xAAAAAAA,0x555555,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x2355D4B,0x1758095D,0x1FE13C5F,0x41F83FA,0xBB5E5CF,0x97D4EF1,0xB503D62,0x172C0C9B,0x16315274,0x15E1A9A8,0x859835D,0x2C3DFC0,0x105EB806,0x68,0x0,0x0,0x0,0x0},{0x289AAD,0x1E781F9C,0x60F9C31,0x1505822E,0x15DAF62B,0x4BEA778,0x15A81EB1,0xB96064D,0xB18A93A,0x1AF0D4D4,0x42CC1AE,0x161EFE0,0x82F5C03,0x34,0x0,0x0,0x0,0x0},{0x192279D1,0xBA52F9F,0x878CAFD,0xCAE8B48,0x52152AF,0xAAAAAAA,0x15555555,0xAAAAAAA,0x555555,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+const BIG CURVE_BB[4][4]= {{{0x1E1BD810,0x59835DA,0xC3DFC04,0x5EB8061,0x688,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
+											{0x1E1BD80F,0x59835DA,0xC3DFC04,0x5EB8061,0x688,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
+											{0x1E1BD80F,0x59835DA,0xC3DFC04,0x5EB8061,0x688,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
+											{0x156259CF,0xA01E744,0x5ECB4F9,0x148B7B47,0x79A2790,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF}},
+											{{0x1C37B01F,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
+											 {0x137E31DE,0xF9A1D1F,0x122AB0FD,0x1A76FBA8,0x79A2E18,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF},
+											 {0x137E31DD,0xF9A1D1F,0x122AB0FD,0x1A76FBA8,0x79A2E18,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF},
+											 {0x137E31DE,0xF9A1D1F,0x122AB0FD,0x1A76FBA8,0x79A2E18,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF}},
+											 {{0x1C37B01E,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
+											  {0x1C37B01F,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
+											  {0x1C37B01F,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
+											  {0x1C37B01F,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},
+											   {{0x137E31DF,0xF9A1D1F,0x122AB0FD,0x1A76FBA8,0x79A2E18,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF},
+												{0x192AA9AF,0x1ED17B8E,0xD70BCF0,0x8B47A84,0x79A1A80,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF},
+												{0x1C37B01D,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
+												{0x137E31DF,0xF9A1D1F,0x122AB0FD,0x1A76FBA8,0x79A2E18,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF}}};
+
+
+
+#endif
+
+#if CHUNK==64
+
+using namespace B512_60;
+
+const int CURVE_Cof_I=1;
+const int CURVE_A= 0;
+const int CURVE_B_I= 3;
+const BIG CURVE_B= {0x3L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG CURVE_Order= {0x6A64A5F519A09EDL,0x10313E04F9A2B40L,0xC65DEAB2679A34AL,0xCF1EACBE98B8E48L,0x3C111B0EF445146L,0xA1D8CB5307C0BBEL,0xFFFF9EC7F01C60BL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFL};
+const BIG CURVE_Gx= {0x1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG CURVE_Gy= {0x2L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+
+const BIG CURVE_Bnx= {0xB306BB5E1BD80FL,0x82F5C030B0F7F01L,0x68L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG CURVE_Cof= {0x1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+
+const BIG CURVE_Cru= {0xB0716209C79298AL,0xCEE6799B8B17C14L,0x78966BE526092AEL,0x20089C27507ACD8L,0xF8EF7611FA3074BL,0x6146B86B378EA2CL,0xFFFF9EC7DC83D2AL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFL};
+
+const BIG CURVE_Pxa= {0xF07A96E0DB646B5L,0x18F87319072FFE8L,0x7BE21BCBBC78F22L,0x537863514DC6DC5L,0xDA57CC78CD0B024L,0xD29B358F0DB9B57L,0x7412F3CEA1E4BBBL,0xE138648958801BAL,0x3B165339L};
+const BIG CURVE_Pxb= {0xDB5CBEFDA8AE0E9L,0xCA411CD88911B3L,0xD6E1383D5ADCE4L,0x227285526E0D5E5L,0xB02566B94D9781EL,0x56DC6C6EF2476A8L,0x680ABE8B4825EA6L,0xF85067E6C89B4C4L,0x481C13CBL};
+const BIG CURVE_Pya= {0x2480312ADDE67A1L,0xDA17AD615EFB85EL,0x312542808B7BC5CL,0x18BDEC153E8EDD2L,0xE5C158699D4B6CDL,0xB1DF660AFCDD03EL,0xB0CBA374F277085L,0xC827C7B8292EF5AL,0x6F01EC84L};
+const BIG CURVE_Pyb= {0x58B7186C84F8E8BL,0xF05C2224BF76168L,0x10AD7EE279C08DFL,0x7FC3E2E50714A43L,0x3D04961941DA289L,0x38C118867B0C9B6L,0xC315F75D91F0214L,0x8B04E7831AC3640L,0x51A3BCECL};
+const BIG CURVE_W[2]= {{0x110F89749834583L,0x65FB911D16A173FL,0xFFFFFFFFCF63FE9L,0xFFFFFFFFFFFFFFFL,0xFFFFL,0x0L,0x0L,0x0L,0x0L},{0x1660D76BC37B01FL,0x5EB806161EFE02L,0xD1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}};
+const BIG CURVE_SB[2][2]= {{{0xFAAEB208D4B9564L,0x601010BBB4B193CL,0xFFFFFFFFCF63F18L,0xFFFFFFFFFFFFFFFL,0xFFFFL,0x0L,0x0L,0x0L,0x0L},{0x5403CE8956259CEL,0xA45BDA397B2D3EL,0xC65DEAB2679A279L,0xCF1EACBE98B8E48L,0x3C111B0EF445146L,0xA1D8CB5307C0BBEL,0xFFFF9EC7F01C60BL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFL}},{{0x1660D76BC37B01FL,0x5EB806161EFE02L,0xD1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x110F89749834583L,0x65FB911D16A173FL,0xFFFFFFFFCF63FE9L,0xFFFFFFFFFFFFFFFL,0xFFFFL,0x0L,0x0L,0x0L,0x0L}}};
+const BIG CURVE_WB[4]= {{0x6DAB36AB55A29F0L,0xFC42C60583D30C1L,0x5555555545215FBL,0x555555555555555L,0x5555L,0x0L,0x0L,0x0L,0x0L},{0xEEB012BA2355D4BL,0xF20FC1FD7F84F17L,0x892FA9DE2BB5E5CL,0x74B96064DAD40F5L,0xD76BC3535163152L,0x806161EFE021660L,0xD105EBL,0x0L,0x0L},{0x7CF03F380289AADL,0xBA82C117183E70CL,0xC497D4EF15DAF62L,0x3A5CB0326D6A07AL,0x6BB5E1A9A8B18A9L,0xC030B0F7F010B30L,0x6882F5L,0x0L,0x0L},{0x574A5F3F92279D1L,0xF65745A421E32BFL,0x55555555452152AL,0x555555555555555L,0x5555L,0x0L,0x0L,0x0L,0x0L}};
+const BIG CURVE_BB[4][4]= {{{0xB306BB5E1BD810L,0x82F5C030B0F7F01L,0x68L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0xB306BB5E1BD80FL,0x82F5C030B0F7F01L,0x68L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0xB306BB5E1BD80FL,0x82F5C030B0F7F01L,0x68L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x5403CE8956259CFL,0xA45BDA397B2D3EL,0xC65DEAB2679A279L,0xCF1EACBE98B8E48L,0x3C111B0EF445146L,0xA1D8CB5307C0BBEL,0xFFFF9EC7F01C60BL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFL}},{{0x1660D76BC37B01FL,0x5EB806161EFE02L,0xD1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x5F343A3F37E31DEL,0x8D3B7DD448AAC3FL,0xC65DEAB2679A2E1L,0xCF1EACBE98B8E48L,0x3C111B0EF445146L,0xA1D8CB5307C0BBEL,0xFFFF9EC7F01C60BL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFL},{0x5F343A3F37E31DDL,0x8D3B7DD448AAC3FL,0xC65DEAB2679A2E1L,0xCF1EACBE98B8E48L,0x3C111B0EF445146L,0xA1D8CB5307C0BBEL,0xFFFF9EC7F01C60BL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFL},{0x5F343A3F37E31DEL,0x8D3B7DD448AAC3FL,0xC65DEAB2679A2E1L,0xCF1EACBE98B8E48L,0x3C111B0EF445146L,0xA1D8CB5307C0BBEL,0xFFFF9EC7F01C60BL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFL}},{{0x1660D76BC37B01EL,0x5EB806161EFE02L,0xD1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x1660D76BC37B01FL,0x5EB806161EFE02L,0xD1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x1660D76BC37B01FL,0x5EB806161EFE02L,0xD1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x1660D76BC37B01FL,0x5EB806161EFE02L,0xD1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x5F343A3F37E31DFL,0x8D3B7DD448AAC3FL,0xC65DEAB2679A2E1L,0xCF1EACBE98B8E48L,0x3C111B0EF445146L,0xA1D8CB5307C0BBEL,0xFFFF9EC7F01C60BL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFL},{0x3DA2F71D92AA9AFL,0x45A3D4235C2F3CL,0xC65DEAB2679A1A8L,0xCF1EACBE98B8E48L,0x3C111B0EF445146L,0xA1D8CB5307C0BBEL,0xFFFF9EC7F01C60BL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFL},{0x1660D76BC37B01DL,0x5EB806161EFE02L,0xD1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x5F343A3F37E31DFL,0x8D3B7DD448AAC3FL,0xC65DEAB2679A2E1L,0xCF1EACBE98B8E48L,0x3C111B0EF445146L,0xA1D8CB5307C0BBEL,0xFFFF9EC7F01C60BL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFL}}};
+
+
+#endif
+
+}
diff --git a/version3/cpp/rom_curve_GOLDILOCKS.cpp b/version3/cpp/rom_curve_GOLDILOCKS.cpp
new file mode 100644
index 0000000..a7153f2
--- /dev/null
+++ b/version3/cpp/rom_curve_GOLDILOCKS.cpp
@@ -0,0 +1,43 @@
+#include "arch.h"
+#include "ecp_GOLDILOCKS.h"
+
+namespace GOLDILOCKS {
+
+/* Curve GOLDILOCKS */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+using namespace B448_29;
+
+const int CURVE_Cof_I=4;
+const BIG CURVE_Cof= {0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const int CURVE_A= 1;
+const int CURVE_B_I= -39081;
+const BIG CURVE_B= {0x1FFF6756,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FDFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFF};
+const BIG CURVE_Order= {0xB5844F3,0x1BC61495,0x1163D548,0x1984E51B,0x3690216,0xDA4D76B,0xFA7113B,0x1FEF9944,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FF};
+const BIG CURVE_Gx= {0x15555555,0xAAAAAAA,0x15555555,0xAAAAAAA,0x15555555,0xAAAAAAA,0x15555555,0x152AAAAA,0xAAAAAAA,0x15555555,0xAAAAAAA,0x15555555,0xAAAAAAA,0x15555555,0xAAAAAAA,0x1555};
+const BIG CURVE_Gy= {0xA9386ED,0x1757DE6F,0x13681AF6,0x19657DA3,0x3098BBB,0x12C19D15,0x12E03595,0xE515B18,0x17B7E36D,0x1AC426E,0xDBB5E8,0x10D8560,0x159D6205,0xB8246D9,0x17A58D2B,0x15C0};
+
+#endif
+
+#if CHUNK==64
+
+using namespace B448_58;
+
+const int CURVE_Cof_I=4;
+const BIG CURVE_Cof= {0x4L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const int CURVE_A= 1;
+const int CURVE_B_I= -39081;
+const BIG CURVE_B= {0x3FFFFFFFFFF6756L,0x3FFFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFFL,0x3FBFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFFL,0x3FFFFFFFFFFL};
+const BIG CURVE_Order= {0x378C292AB5844F3L,0x3309CA37163D548L,0x1B49AED63690216L,0x3FDF3288FA7113BL,0x3FFFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFFL,0xFFFFFFFFFFL};
+const BIG CURVE_Gx= {0x155555555555555L,0x155555555555555L,0x155555555555555L,0x2A5555555555555L,0x2AAAAAAAAAAAAAAL,0x2AAAAAAAAAAAAAAL,0x2AAAAAAAAAAAAAAL,0x2AAAAAAAAAAL};
+const BIG CURVE_Gy= {0x2EAFBCDEA9386EDL,0x32CAFB473681AF6L,0x25833A2A3098BBBL,0x1CA2B6312E03595L,0x35884DD7B7E36DL,0x21B0AC00DBB5E8L,0x17048DB359D6205L,0x2B817A58D2BL};
+#endif
+
+}
diff --git a/version3/cpp/rom_curve_HIFIVE.cpp b/version3/cpp/rom_curve_HIFIVE.cpp
new file mode 100644
index 0000000..775651c
--- /dev/null
+++ b/version3/cpp/rom_curve_HIFIVE.cpp
@@ -0,0 +1,43 @@
+#include "arch.h"
+#include "ecp_HIFIVE.h"
+
+namespace HIFIVE {
+
+/* Curve HIFIVE */
+
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+using namespace B336_29;
+
+const int CURVE_Cof_I=8;
+const BIG CURVE_Cof= {0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const int CURVE_A= 1;
+const int CURVE_B_I= 11111;
+const BIG CURVE_B= {0x2B67,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Order= {0x1E9FA805,0x197CACB9,0x1E4EEA9E,0x17AD70F,0x1FA9850C,0x38A0A,0x0,0x0,0x0,0x0,0x0,0x4000};
+const BIG CURVE_Gx= {0xC,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Gy= {0x5FE8632,0x15F63428,0xD976C4,0x1AACA194,0x35B6DB5,0x8E3F7A,0x52D1B0E,0xF0A7A36,0x1C161D00,0x8170C70,0x1185AD59,0x181B};
+#endif
+
+#if CHUNK==64
+
+using namespace B336_60;
+
+const int CURVE_Cof_I=8;
+const BIG CURVE_Cof= {0x8L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const int CURVE_A= 1;
+const int CURVE_B_I= 11111;
+const BIG CURVE_B= {0x2B67L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG CURVE_Order= {0xB2F95973E9FA805L,0xC0BD6B87F93BAA7L,0x71415FA9850L,0x0L,0x0L,0x200000000L};
+const BIG CURVE_Gx= {0xCL,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG CURVE_Gy= {0x2BEC68505FE8632L,0x5D5650CA0365DB1L,0x3811C7EF435B6DBL,0x7853D1B14B46CL,0x56502E18E1C161DL,0xC0DC616BL};
+#endif
+
+}
diff --git a/version3/cpp/rom_curve_NIST256.cpp b/version3/cpp/rom_curve_NIST256.cpp
new file mode 100644
index 0000000..ae4ac90
--- /dev/null
+++ b/version3/cpp/rom_curve_NIST256.cpp
@@ -0,0 +1,44 @@
+#include "arch.h"
+#include "ecp_NIST256.h"
+
+namespace NIST256 {
+
+/* Curve NIST256 */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+using namespace B256_28;
+
+const int CURVE_Cof_I=1;
+const BIG CURVE_Cof= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const int CURVE_A= -3;
+const int CURVE_B_I= 0;
+const BIG CURVE_B= {0x7D2604B,0xCE3C3E2,0x3B0F63B,0x6B0CC5,0x6BC651D,0x5576988,0x7B3EBBD,0xAA3A93E,0xAC635D8,0x5};
+const BIG CURVE_Order= {0xC632551,0xB9CAC2F,0x79E84F3,0xFAADA71,0xFFFBCE6,0xFFFFFFF,0xFFFFFF,0x0,0xFFFFFFF,0xF};
+const BIG CURVE_Gx= {0x898C296,0xA13945D,0xB33A0F4,0x7D812DE,0xF27703,0xE563A44,0x7F8BCE6,0xE12C424,0xB17D1F2,0x6};
+const BIG CURVE_Gy= {0x7BF51F5,0xB640683,0x15ECECB,0x33576B3,0xE162BCE,0x4A7C0F9,0xB8EE7EB,0xFE1A7F9,0xFE342E2,0x4};
+
+
+#endif
+
+#if CHUNK==64
+
+using namespace B256_56;
+
+const int CURVE_Cof_I=1;
+const BIG CURVE_Cof= {0x1L,0x0L,0x0L,0x0L,0x0L};
+const int CURVE_A= -3;
+const int CURVE_B_I= 0;
+const BIG CURVE_B= {0xCE3C3E27D2604BL,0x6B0CC53B0F63BL,0x55769886BC651DL,0xAA3A93E7B3EBBDL,0x5AC635D8L};
+const BIG CURVE_Order= {0xB9CAC2FC632551L,0xFAADA7179E84F3L,0xFFFFFFFFFFBCE6L,0xFFFFFFL,0xFFFFFFFFL};
+const BIG CURVE_Gx= {0xA13945D898C296L,0x7D812DEB33A0F4L,0xE563A440F27703L,0xE12C4247F8BCE6L,0x6B17D1F2L};
+const BIG CURVE_Gy= {0xB6406837BF51F5L,0x33576B315ECECBL,0x4A7C0F9E162BCEL,0xFE1A7F9B8EE7EBL,0x4FE342E2L};
+#endif
+
+}
diff --git a/version3/cpp/rom_curve_NIST384.cpp b/version3/cpp/rom_curve_NIST384.cpp
new file mode 100644
index 0000000..c620b69
--- /dev/null
+++ b/version3/cpp/rom_curve_NIST384.cpp
@@ -0,0 +1,42 @@
+#include "arch.h"
+#include "ecp_NIST384.h"
+
+namespace NIST384 {
+
+/* Curve NIST384 */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+using namespace B384_29;
+
+const int CURVE_Cof_I=1;
+const BIG CURVE_Cof= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const int CURVE_A= -3;
+const int CURVE_B_I= 0;
+const BIG CURVE_B= {0x13EC2AEF,0x142E476E,0xBB4674A,0xC731B14,0x1875AC65,0x447A809,0x4480C50,0xDDFD028,0x19181D9C,0x1F1FC168,0x623815A,0x47DCFC9,0x1312FA7E,0x59};
+const BIG CURVE_Order= {0xCC52973,0x760CB56,0xC29DEBB,0x141B6491,0x12DDF581,0x6C0FA1B,0x1FFF1D8D,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F};
+const BIG CURVE_Gx= {0x12760AB7,0x12A2F1C3,0x154A5B0E,0x5E4BB7E,0x2A38550,0xF0412A,0xE6167DD,0xC5174F3,0x146E1D3B,0x1799056B,0x3AC71C7,0x1D160A6F,0x87CA22B,0x55};
+const BIG CURVE_Gy= {0x10EA0E5F,0x1218EBE4,0x1FA0675E,0x1639C3A,0xB8C00A6,0x1889DAF8,0x11F3A768,0x17A51342,0x9F8F41D,0x1C9496E1,0x1767A62F,0xC4C58DE,0x17DE4A9,0x1B};
+#endif
+
+#if CHUNK==64
+
+using namespace B384_56;
+
+const int CURVE_Cof_I=1;
+const BIG CURVE_Cof= {0x1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const int CURVE_A= -3;
+const int CURVE_B_I= 0;
+const BIG CURVE_B= {0x85C8EDD3EC2AEFL,0x398D8A2ED19D2AL,0x8F5013875AC656L,0xFE814112031408L,0xF82D19181D9C6EL,0xE7E4988E056BE3L,0xB3312FA7E23EL};
+const BIG CURVE_Order= {0xEC196ACCC52973L,0xDB248B0A77AECL,0x81F4372DDF581AL,0xFFFFFFFFC7634DL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFL};
+const BIG CURVE_Gx= {0x545E3872760AB7L,0xF25DBF55296C3AL,0xE082542A385502L,0x8BA79B9859F741L,0x20AD746E1D3B62L,0x5378EB1C71EF3L,0xAA87CA22BE8BL};
+const BIG CURVE_Gy= {0x431D7C90EA0E5FL,0xB1CE1D7E819D7AL,0x13B5F0B8C00A60L,0x289A147CE9DA31L,0x92DC29F8F41DBDL,0x2C6F5D9E98BF92L,0x3617DE4A9626L};
+#endif
+
+}
diff --git a/version3/cpp/rom_curve_NIST521.cpp b/version3/cpp/rom_curve_NIST521.cpp
new file mode 100644
index 0000000..e6051c5
--- /dev/null
+++ b/version3/cpp/rom_curve_NIST521.cpp
@@ -0,0 +1,42 @@
+#include "arch.h"
+#include "ecp_NIST521.h"
+
+namespace NIST521 {
+
+/* Curve NIST521 */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+using namespace B528_28;
+
+const int CURVE_Cof_I=1;
+const BIG CURVE_Cof= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const int CURVE_A= -3;
+const int CURVE_B_I= 0;
+const BIG CURVE_B= {0xB503F00,0x451FD46,0xC34F1EF,0xDF883D2,0xF073573,0xBD3BB1B,0xB1652C0,0xEC7E937,0x6193951,0xF109E15,0x489918E,0x15F3B8B,0x25B99B3,0xEEA2DA7,0xB68540,0x929A21A,0xE1C9A1F,0x3EB9618,0x5195};
+const BIG CURVE_Order= {0x1386409,0x6FB71E9,0xC47AEBB,0xC9B8899,0x5D03BB5,0x48F709A,0xB7FCC01,0xBF2F966,0x1868783,0xFFFFFA5,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0x1FFFF};
+const BIG CURVE_Gx= {0x2E5BD66,0x7E7E31C,0xA429BF9,0xB3C1856,0x8DE3348,0x27A2FFA,0x8FE1DC1,0xEFE7592,0x14B5E77,0x4D3DBAA,0x8AF606B,0xB521F82,0x139053F,0x429C648,0x62395B4,0x9E3ECB6,0x404E9CD,0x8E06B70,0xC685};
+const BIG CURVE_Gy= {0xFD16650,0xBE94769,0x2C24088,0x7086A27,0x761353C,0x13FAD0,0xC550B9,0x5EF4264,0x7EE7299,0x3E662C9,0xFBD1727,0x446817A,0x449579B,0xD998F54,0x42C7D1B,0x5C8A5FB,0xA3BC004,0x296A789,0x11839};
+#endif
+
+#if CHUNK==64
+
+using namespace B528_60;
+
+const int CURVE_Cof_I=1;
+const BIG CURVE_Cof= {0x1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const int CURVE_A= -3;
+const int CURVE_B_I= 0;
+const BIG CURVE_B= {0xF451FD46B503F00L,0x73DF883D2C34F1EL,0x2C0BD3BB1BF0735L,0x3951EC7E937B165L,0x9918EF109E15619L,0x5B99B315F3B8B48L,0xB68540EEA2DA72L,0x8E1C9A1F929A21AL,0x51953EB961L};
+const BIG CURVE_Order= {0xB6FB71E91386409L,0xB5C9B8899C47AEBL,0xC0148F709A5D03BL,0x8783BF2F966B7FCL,0xFFFFFFFFFFA5186L,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0x1FFFFFFFFFFL};
+const BIG CURVE_Gx= {0x97E7E31C2E5BD66L,0x48B3C1856A429BFL,0xDC127A2FFA8DE33L,0x5E77EFE75928FE1L,0xF606B4D3DBAA14BL,0x39053FB521F828AL,0x62395B4429C6481L,0x404E9CD9E3ECB6L,0xC6858E06B7L};
+const BIG CURVE_Gy= {0x8BE94769FD16650L,0x3C7086A272C2408L,0xB9013FAD076135L,0x72995EF42640C55L,0xD17273E662C97EEL,0x49579B446817AFBL,0x42C7D1BD998F544L,0x9A3BC0045C8A5FBL,0x11839296A78L};
+#endif
+
+}
diff --git a/version3/cpp/rom_curve_NUMS256E.cpp b/version3/cpp/rom_curve_NUMS256E.cpp
new file mode 100644
index 0000000..3f52f11
--- /dev/null
+++ b/version3/cpp/rom_curve_NUMS256E.cpp
@@ -0,0 +1,53 @@
+#include "arch.h"
+#include "ecp_NUMS256E.h"
+
+namespace NUMS256E {
+
+/*  NUMS 256-bit Curve - Edwards */
+
+#if CHUNK==16
+
+using namespace B256_13;
+
+const int CURVE_Cof_I=4;
+const BIG CURVE_Cof= {0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const int CURVE_A= 1;
+const int CURVE_B_I= -15342;
+const BIG CURVE_B= {0x355,0x1FFE,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FF};
+const BIG CURVE_Order= {0xAF5,0x16EA,0x43B,0xF63,0x11A4,0x1CD,0x1D65,0x14A5,0x155A,0x20C,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x80};
+const BIG CURVE_Gx= {0x13DA,0x1768,0x40B,0x1D81,0xA0D,0x1AC3,0xC20,0x1DC,0x198A,0x1061,0x6F5,0x1241,0x15F6,0xF1E,0x1734,0x46F,0xAEA,0x7DB,0x1D45,0x114};
+const BIG CURVE_Gy= {0x9E6,0xC54,0x19DE,0xC2D,0x12FA,0x1769,0x215,0x1B02,0x1F61,0x38A,0x4,0xC97,0x1D9A,0xB32,0x1F3A,0x4B8,0x19D9,0x14FE,0x154F,0x89};
+
+#endif
+
+#if CHUNK==32
+
+using namespace B256_29;
+
+const int CURVE_Cof_I=4;
+const BIG CURVE_Cof= {0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const int CURVE_A= 1;
+const int CURVE_B_I= -15342;
+const BIG CURVE_B= {0x1FFFC355,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFFFFFF};
+const BIG CURVE_Order= {0xEDD4AF5,0x123D8C87,0x1650E6C6,0xAB54A5E,0x419,0x0,0x0,0x0,0x400000};
+const BIG CURVE_Gx= {0xEED13DA,0x6F60481,0x20D61A8,0x13141DC6,0x9BD60C3,0x1EAFB490,0xDF73478,0x1F6D5D44,0x8A7514};
+const BIG CURVE_Gy= {0x198A89E6,0x1D30B73B,0x15BB4CB,0x1EC3B021,0x18010715,0x12ECD325,0x171F3A59,0x13FB3B24,0x44D53E};
+
+#endif
+
+#if CHUNK==64
+
+using namespace B256_56;
+
+const int CURVE_Cof_I=4;
+const BIG CURVE_Cof= {0x4L,0x0L,0x0L,0x0L,0x0L};
+const int CURVE_A= 1;
+const int CURVE_B_I= -15342;
+const BIG CURVE_B= {0xFFFFFFFFFFC355L,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFL};
+const BIG CURVE_Order= {0x47B190EEDD4AF5L,0x5AA52F59439B1AL,0x4195L,0x0L,0x40000000L};
+const BIG CURVE_Gx= {0xDEC0902EED13DAL,0x8A0EE3083586A0L,0x5F69209BD60C39L,0x6AEA237DCD1E3DL,0x8A7514FBL};
+const BIG CURVE_Gy= {0xA616E7798A89E6L,0x61D810856ED32FL,0xD9A64B8010715FL,0xD9D925C7CE9665L,0x44D53E9FL};
+
+#endif
+
+}
diff --git a/version3/cpp/rom_curve_NUMS256W.cpp b/version3/cpp/rom_curve_NUMS256W.cpp
new file mode 100644
index 0000000..dd8956c
--- /dev/null
+++ b/version3/cpp/rom_curve_NUMS256W.cpp
@@ -0,0 +1,44 @@
+#include "arch.h"
+#include "ecp_NUMS256W.h"
+
+namespace NUMS256W {
+
+/*  NUMS 256-bit Curve - Weierstrass */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+using namespace B256_28;
+
+const int CURVE_Cof_I=1;
+const BIG CURVE_Cof= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const int CURVE_A= -3;
+const int CURVE_B_I= 152961;
+const BIG CURVE_B= {0x25581,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Order= {0x751A825,0xAB20294,0x65C6020,0x8275EA2,0xFFFE43C,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xF};
+const BIG CURVE_Gx= {0x21AACB1,0x52EE1EB,0x4C73ABC,0x9B0903D,0xB098357,0xA04F42C,0x1297A95,0x5AAADB6,0xC9ED6B6,0xB};
+const BIG CURVE_Gy= {0x184DE9F,0xB5B9CB2,0x10FBB80,0xC3D1153,0x35C955,0xF77E04E,0x673448B,0x3399B6A,0x8FC0F1,0xD};
+
+#endif
+
+#if CHUNK==64
+
+using namespace B256_56;
+
+const int CURVE_Cof_I=1;
+const BIG CURVE_Cof= {0x1L,0x0L,0x0L,0x0L,0x0L};
+const int CURVE_A= -3;
+const int CURVE_B_I= 152961;
+const BIG CURVE_B= {0x25581L,0x0L,0x0L,0x0L,0x0L};
+const BIG CURVE_Order= {0xAB20294751A825L,0x8275EA265C6020L,0xFFFFFFFFFFE43CL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFL};
+const BIG CURVE_Gx= {0x52EE1EB21AACB1L,0x9B0903D4C73ABCL,0xA04F42CB098357L,0x5AAADB61297A95L,0xBC9ED6B6L};
+const BIG CURVE_Gy= {0xB5B9CB2184DE9FL,0xC3D115310FBB80L,0xF77E04E035C955L,0x3399B6A673448BL,0xD08FC0F1L};
+
+#endif
+
+}
diff --git a/version3/cpp/rom_curve_NUMS384E.cpp b/version3/cpp/rom_curve_NUMS384E.cpp
new file mode 100644
index 0000000..2cc6c28
--- /dev/null
+++ b/version3/cpp/rom_curve_NUMS384E.cpp
@@ -0,0 +1,42 @@
+#include "arch.h"
+#include "ecp_NUMS384E.h"
+
+namespace NUMS384E {
+
+/*  NUMS 384-bit Curve - Edwards */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+using namespace B384_29;
+
+const int CURVE_Cof_I=4;
+const BIG CURVE_Cof= {0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const int CURVE_A= 1;
+const int CURVE_B_I= -11556;
+const BIG CURVE_B= {0x1FFFD19F,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F};
+const BIG CURVE_Order= {0x6A3897D,0x5CEE627,0xD721E48,0x8AAB556,0x1E1CF61E,0xD0E5A35,0x1FFF891C,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1F};
+const BIG CURVE_Gx= {0xC206BDE,0x6AA0723,0x116504D4,0x52562CA,0x163406FF,0x1FD47998,0x10015D8F,0x8DCB7C9,0x15B30BF4,0x14D72AED,0x102DA884,0xB524CD9,0x1B111FB4,0x30};
+const BIG CURVE_Gy= {0x10729392,0xC681F0F,0x1B123727,0x561F28D,0x1964B007,0xC7BFB22,0x1D5A0C3E,0xE9E284B,0x1716AD82,0x11D886E,0x1CE2C69,0x134DDD61,0x983E67B,0x41};
+#endif
+
+#if CHUNK==64
+
+using namespace B384_56;
+
+const int CURVE_Cof_I=4;
+const BIG CURVE_Cof= {0x4L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const int CURVE_A= 1;
+const int CURVE_B_I= -11556;
+const BIG CURVE_B= {0xFFFFFFFFFFD19FL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFL};
+const BIG CURVE_Order= {0xB9DCC4E6A3897DL,0x555AAB35C87920L,0x1CB46BE1CF61E4L,0xFFFFFFFFE2471AL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0x3FFFFFFFFFFFL};
+const BIG CURVE_Gx= {0xD540E46C206BDEL,0x92B16545941350L,0xA8F33163406FF2L,0xE5BE4C005763FFL,0xE55DB5B30BF446L,0x266CC0B6A2129AL,0x61B111FB45A9L};
+const BIG CURVE_Gy= {0x8D03E1F0729392L,0xB0F946EC48DC9DL,0xF7F645964B0072L,0xF1425F56830F98L,0xB10DD716AD8274L,0xEEB08738B1A423L,0x82983E67B9A6L};
+#endif
+
+}
diff --git a/version3/cpp/rom_curve_NUMS384W.cpp b/version3/cpp/rom_curve_NUMS384W.cpp
new file mode 100644
index 0000000..86eef40
--- /dev/null
+++ b/version3/cpp/rom_curve_NUMS384W.cpp
@@ -0,0 +1,42 @@
+#include "arch.h"
+#include "ecp_NUMS384W.h"
+
+namespace NUMS384W {
+
+/*  NUMS 384-bit Curve - Weierstrass */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+using namespace B384_29;
+
+const int CURVE_Cof_I=1;
+const BIG CURVE_Cof= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const int CURVE_A= -3;
+const int CURVE_B_I= -34568;
+const BIG CURVE_B= {0x1FFF77BB,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F};
+const BIG CURVE_Order= {0x1B0E61B9,0x26C0FB3,0xDF89E98,0x153A7A98,0x16881BED,0x178F75AE,0x1FFF587A,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F};
+const BIG CURVE_Gx= {0x98152A,0x1CE5D021,0x18711EFA,0x1DDA201E,0xC742522,0x148D9536,0x7D3CEF4,0x19BF703F,0x60225C1,0x12082F8D,0x12203288,0x2DE3038,0x17956F0B,0x3A};
+const BIG CURVE_Gy= {0x6180716,0x3A5C763,0x1D2B4997,0xD69B77F,0x837EBCD,0x1BE890D,0xE72E482,0xEFF0FEE,0x1EB00469,0x2C267B,0x15F8CF4C,0x3371C71,0xDEE368E,0x56};
+#endif
+
+#if CHUNK==64
+
+using namespace B384_56;
+
+const int CURVE_Cof_I=1;
+const BIG CURVE_Cof= {0x1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const int CURVE_A= -3;
+const int CURVE_B_I= -34568;
+const BIG CURVE_B= {0xFFFFFFFFFF77BBL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFL};
+const BIG CURVE_Order= {0x4D81F67B0E61B9L,0x9D3D4C37E27A60L,0x1EEB5D6881BEDAL,0xFFFFFFFFD61EAFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFL};
+const BIG CURVE_Gx= {0x9CBA042098152AL,0xED100F61C47BEBL,0x1B2A6CC742522EL,0xFB81F9F4F3BD29L,0x5F1A60225C1CDL,0x181C4880CA2241L,0x757956F0B16FL};
+const BIG CURVE_Gy= {0x74B8EC66180716L,0xB4DBBFF4AD265CL,0x7D121A837EBCD6L,0xF87F739CB92083L,0x84CF7EB0046977L,0x8E38D7E33D3005L,0xACDEE368E19BL};
+#endif
+
+}
diff --git a/version3/cpp/rom_curve_NUMS512E.cpp b/version3/cpp/rom_curve_NUMS512E.cpp
new file mode 100644
index 0000000..d0b4aeb
--- /dev/null
+++ b/version3/cpp/rom_curve_NUMS512E.cpp
@@ -0,0 +1,42 @@
+#include "arch.h"
+#include "ecp_NUMS512E.h"
+
+namespace NUMS512E {
+
+/*  NUMS 512-bit Curve - Edwards */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+using namespace B512_29;
+
+const int CURVE_Cof_I=4;
+const BIG CURVE_Cof= {0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const int CURVE_A= 1;
+const int CURVE_B_I= -78296;
+const BIG CURVE_B= {0x1FFECBEF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF};
+const BIG CURVE_Order= {0x1BEED46D,0x1A3467A8,0x1BFB3FD9,0xC0AF0DB,0x86F52A4,0xC64B85B,0x6EA78FF,0xDA5F9F2,0x1FB4F063,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFF};
+const BIG CURVE_Gx= {0x19EC57FE,0xDCD594C,0x113C0571,0xA4A84F9,0x104AD0FE,0x4C92B44,0xC3DE2F7,0x9DDC8CE,0x74621C1,0x1139DC0A,0x9E85FAF,0x1B894704,0x1D1E79F4,0x9E29997,0x32DE223,0x16D38F43,0x116D128D,0x6FC71};
+const BIG CURVE_Gy= {0x1E2F5E1,0x136EF606,0x1C7407CC,0xDA71537,0xC1FD026,0x3431576,0x15898068,0x1E5D32C6,0x120CA53,0xC84F41A,0xA4ADAE5,0x104B3A45,0x76F726D,0x1512B772,0x3D5DEA0,0x194E3316,0x1FF39D49,0x3684D};
+#endif
+
+#if CHUNK==64
+
+using namespace B512_56;
+
+const int CURVE_Cof_I=4;
+const BIG CURVE_Cof= {0x4L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const int CURVE_A= 1;
+const int CURVE_B_I= -78296;
+const BIG CURVE_B= {0xFFFFFFFFFECBEFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFL};
+const BIG CURVE_Order= {0x468CF51BEED46DL,0x5786DEFECFF67L,0xC970B686F52A46L,0x2FCF91BA9E3FD8L,0xFFFFFFB4F0636DL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0x3FL};
+const BIG CURVE_Gx= {0xB9AB2999EC57FEL,0x25427CC4F015C5L,0x92568904AD0FE5L,0xEE46730F78BDC9L,0x3B81474621C14EL,0xA38227A17EBE27L,0x332FD1E79F4DC4L,0x7A18CB7888D3C5L,0x8E316D128DB69CL,0xDFL};
+const BIG CURVE_Gy= {0x6DDEC0C1E2F5E1L,0xD38A9BF1D01F32L,0x862AECC1FD0266L,0xE9963562601A06L,0x9E834120CA53F2L,0x9D22A92B6B9590L,0x6EE476F726D825L,0x98B0F577A82A25L,0x9BFF39D49CA71L,0x6DL};
+#endif
+
+}
diff --git a/version3/cpp/rom_curve_NUMS512W.cpp b/version3/cpp/rom_curve_NUMS512W.cpp
new file mode 100644
index 0000000..d9f3c05
--- /dev/null
+++ b/version3/cpp/rom_curve_NUMS512W.cpp
@@ -0,0 +1,42 @@
+#include "arch.h"
+#include "ecp_NUMS512W.h"
+
+namespace NUMS512W {
+
+/*  NUMS 512-bit Curve - Weierstrass */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+using namespace B512_29;
+
+const int CURVE_Cof_I=1;
+const BIG CURVE_Cof= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const int CURVE_A= -3;
+const int CURVE_B_I= 121243;
+const BIG CURVE_B= {0x1D99B,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Order= {0x433555D,0x10A9F9C8,0x1F3490F3,0xD166CC0,0xBDC63B5,0xC76CBE8,0xC6D3F09,0x1F729CF0,0x1F5B3CA4,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF};
+const BIG CURVE_Gx= {0xCABAE57,0x4143CAC,0x1BD778B7,0x1AC026FA,0x15831D5,0x14312AB,0x167A4DE5,0xA20ED66,0x195021A1,0x129836CF,0x1141B830,0xA03ED0A,0xCAD83BB,0x1E9DA94C,0xDC00A80,0x1527B45,0x1447141D,0x1D601};
+const BIG CURVE_Gy= {0x183527A6,0x1D043B01,0x1F43FA48,0x16B83C99,0x5602CF2,0x1420592D,0x17A70486,0x1B5161DD,0x14A28415,0x3DE8A78,0x3D2C983,0x17797719,0x197DBDEA,0x15D88025,0x1BBB718F,0xAD679C1,0x14CA29AD,0x4A1D2};
+#endif
+
+#if CHUNK==64
+
+using namespace B512_56;
+
+const int CURVE_Cof_I=1;
+const BIG CURVE_Cof= {0x1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const int CURVE_A= -3;
+const int CURVE_B_I= 121243;
+const BIG CURVE_B= {0x1D99BL,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const BIG CURVE_Order= {0x153F390433555DL,0x8B36607CD243CEL,0xED97D0BDC63B56L,0x94E7831B4FC258L,0xFFFFFF5B3CA4FBL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFL};
+const BIG CURVE_Gx= {0x8287958CABAE57L,0x60137D6F5DE2DCL,0x86255615831D5DL,0x76B359E937942L,0x6D9F95021A151L,0xF6854506E0C253L,0x5298CAD83BB501L,0xDA2B7002A03D3BL,0xC03447141D0A93L,0x3AL};
+const BIG CURVE_Gy= {0xA08760383527A6L,0x5C1E4CFD0FE923L,0x40B25A5602CF2BL,0x8B0EEDE9C121A8L,0xD14F14A28415DAL,0xBB8C8F4B260C7BL,0x4B97DBDEABBCL,0xCE0EEEDC63EBB1L,0x3A54CA29AD56B3L,0x94L};
+#endif
+
+}
diff --git a/version3/cpp/rom_curve_SECP256K1.cpp b/version3/cpp/rom_curve_SECP256K1.cpp
new file mode 100644
index 0000000..8f45400
--- /dev/null
+++ b/version3/cpp/rom_curve_SECP256K1.cpp
@@ -0,0 +1,45 @@
+#include "arch.h"
+#include "ecp_SECP256K1.h"
+
+namespace SECP256K1 {
+
+/* Curve SECP256K1 */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+using namespace B256_28;
+
+const int CURVE_Cof_I=1;
+const BIG CURVE_Cof= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const int CURVE_A= 0;
+const int CURVE_B_I= 7;
+const BIG CURVE_B= {0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const BIG CURVE_Order= {0x364141,0xD25E8CD,0x8A03BBF,0xDCE6AF4,0xFFEBAAE,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xF};
+const BIG CURVE_Gx= {0x6F81798,0xF2815B1,0xE28D959,0xFCDB2DC,0xB07029B,0x95CE870,0xC55A062,0xF9DCBBA,0x9BE667E,0x7};
+const BIG CURVE_Gy= {0xB10D4B8,0x47D08FF,0x554199C,0xB448A68,0x8A8FD17,0xFC0E110,0x55DA4FB,0x26A3C46,0x83ADA77,0x4};
+
+#endif
+
+#if CHUNK==64
+
+using namespace B256_56;
+
+// Base Bits= 56
+const int CURVE_Cof_I=1;
+const BIG CURVE_Cof= {0x1L,0x0L,0x0L,0x0L,0x0L};
+const int CURVE_A= 0;
+const int CURVE_B_I= 7;
+const BIG CURVE_B= {0x7L,0x0L,0x0L,0x0L,0x0L};
+const BIG CURVE_Order= {0xD25E8CD0364141L,0xDCE6AF48A03BBFL,0xFFFFFFFFFEBAAEL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFL};
+const BIG CURVE_Gx= {0xF2815B16F81798L,0xFCDB2DCE28D959L,0x95CE870B07029BL,0xF9DCBBAC55A062L,0x79BE667EL};
+const BIG CURVE_Gy= {0x47D08FFB10D4B8L,0xB448A68554199CL,0xFC0E1108A8FD17L,0x26A3C4655DA4FBL,0x483ADA77L};
+
+#endif
+
+}
diff --git a/version3/cpp/rom_field_ANSSI.cpp b/version3/cpp/rom_field_ANSSI.cpp
new file mode 100644
index 0000000..c612c18
--- /dev/null
+++ b/version3/cpp/rom_field_ANSSI.cpp
@@ -0,0 +1,34 @@
+#include "arch.h"
+#include "fp_ANSSI.h"
+
+namespace ANSSI {
+
+/* ANNSI Curve */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+using namespace B256_28;
+
+// Base Bits= 28
+const BIG Modulus= {0x86E9C03,0xFCF353D,0x8CA6DE8,0xADBCABC,0x35B3961,0xE8CE424,0xF10126D,0xB3AD58,0x1FD178C,0xF};
+const BIG R2modp= {0x288CC9C,0x18D2374,0x646BD2B,0x4929E67,0xD6F7F2D,0x220E6C1,0xABCE02E,0x751B1FD,0x7401B78,0xE};
+const chunk MConst= 0x64E1155;
+#endif
+
+#if CHUNK==64
+
+using namespace B256_56;
+
+// Base Bits= 56
+const BIG Modulus= {0xFCF353D86E9C03L,0xADBCABC8CA6DE8L,0xE8CE42435B3961L,0xB3AD58F10126DL,0xF1FD178CL};
+const BIG R2modp= {0x18D2374288CC9CL,0x4929E67646BD2BL,0x220E6C1D6F7F2DL,0x751B1FDABCE02EL,0xE7401B78L};
+const chunk MConst= 0x97483A164E1155L;
+#endif
+
+}
diff --git a/version3/cpp/rom_field_BLS24.cpp b/version3/cpp/rom_field_BLS24.cpp
new file mode 100644
index 0000000..3644dce
--- /dev/null
+++ b/version3/cpp/rom_field_BLS24.cpp
@@ -0,0 +1,37 @@
+#include "arch.h"
+#include "fp_BLS24.h"
+
+namespace BLS24 {
+
+/* Curve BLS24 - Pairing friendly BLS curve */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+using namespace B480_29;
+
+const BIG Modulus= {0xA06152B,0x2260B3A,0xB4C36BE,0x5FFC5D0,0xBDB6A64,0x5B78E2E,0x1C1A28CA,0x10E6441B,0x1F244061,0xB4704F0,0x141E5CCD,0x9837504,0x3F2E77E,0xD763740,0x1316EA0E,0xF0079,0x555C};
+const BIG R2modp= {0x8533EA9,0x6A02789,0x183B24DE,0x1E45ECF8,0xC8F8F37,0x10CAD209,0x4C0C4B8,0x9B1FABD,0xDEBE4C0,0xDC353F9,0x18A18E26,0x10F489BB,0x31206A5,0x19673BBF,0x6BE69F9,0xB091169,0x9CD};
+const chunk MConst= 0x95FE7D;
+const BIG Fra= {0x1BF96F1D,0xAE53A55,0x31BFEEB,0x183FF17A,0x6237469,0x12A4F4F1,0x12101FE3,0x16E79D94,0xFF59267,0x5EB4EB4,0x78CC49F,0x274BA33,0x149184F3,0x16C6DCBA,0x1C90B694,0x10F729CE,0x4BBC};
+const BIG Frb= {0xE0CA60E,0x1740D0E4,0x83037D2,0xDBFD456,0x5B7F5FA,0x1312993D,0xA0A08E6,0x19FEA687,0xF2EADF9,0x55BB63C,0xC91982E,0x70EBAD1,0xF61628B,0x16AF5A85,0x16863379,0xF17D6AA,0x99F};
+
+#endif
+
+#if CHUNK==64
+
+using namespace B480_56;
+// Base Bits= 56
+const BIG Modulus= {0x44C1674A06152BL,0xFFE2E82D30DAF8L,0x6F1C5CBDB6A642L,0x3220DF068A328BL,0xE09E1F24406187L,0xBA825079733568L,0x6E803F2E77E4C1L,0x3CCC5BA839AECL,0x555C0078L};
+const BIG R2modp= {0x6A4A1FE013DF5BL,0xE8E46D4D1BDE65L,0x1F841391F45C67L,0x9148A4516FB28L,0x4398524EDF4C88L,0x41C0E241B6DCE8L,0xE42C208C19411L,0xA7FE6FD73A7B1CL,0xFCCCA76L};
+const chunk MConst= 0xBD5D7D8095FE7DL;
+const BIG Fra= {0x5CA74ABBF96F1DL,0x1FF8BD0C6FFBADL,0x49E9E26237469CL,0x3CECA48407F8E5L,0x69D68FF59267B7L,0x5D199E33127CBDL,0xB97549184F313AL,0x4E77242DA52D8DL,0x4BBC87B9L};
+const BIG Frb= {0xE81A1C8E0CA60EL,0xDFEA2B20C0DF4AL,0x25327A5B7F5FA6L,0xF5343A828239A6L,0x76C78F2EADF9CFL,0x5D68B24660B8ABL,0xB50AF61628B387L,0xB555A18CDE6D5EL,0x99F78BEL};
+#endif
+
+}
diff --git a/version3/cpp/rom_field_BLS381.cpp b/version3/cpp/rom_field_BLS381.cpp
new file mode 100644
index 0000000..a9c81b2
--- /dev/null
+++ b/version3/cpp/rom_field_BLS381.cpp
@@ -0,0 +1,39 @@
+#include "arch.h"
+#include "fp_BLS381.h"
+
+namespace BLS381 {
+
+/* Curve BLS381 - Pairing friendly BLS curve */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+using namespace B384_29;
+
+// Base Bits= 29
+const BIG Modulus= {0x1FFFAAAB,0xFF7FFFF,0x14FFFFEE,0x17FFFD62,0xF6241EA,0x9507B58,0xAFD9CC3,0x109E70A2,0x1764774B,0x121A5D66,0x12C6E9ED,0x12FFCD34,0x111EA3,0xD};
+const BIG R2modp= {0x15BEF7AE,0x1031CD0E,0x2DD93E8,0x9226323,0xE6E2CD2,0x11684DAA,0x1170E5DB,0x88E25B1,0x1B366399,0x1C536F47,0xD1F9CBC,0x278B67F,0x1EA66A2B,0xC};
+const chunk MConst= 0x1FFCFFFD;
+const BIG Fra= {0x12235FB8,0x83BAF6C,0x19E04F63,0x1D4A7AC7,0xB9C4F67,0x1EBC25D,0x1D3DEC91,0x1FA797AB,0x1F0FD603,0x1016068,0x108C6FAD,0x5760CCF,0x104D3BF0,0xC};
+const BIG Frb= {0xDDC4AF3,0x7BC5093,0x1B1FB08B,0x1AB5829A,0x3C5F282,0x764B8FB,0xDBFB032,0x10F6D8F6,0x1854A147,0x1118FCFD,0x23A7A40,0xD89C065,0xFC3E2B3,0x0};
+
+#endif
+
+#if CHUNK==64
+
+using namespace B384_58;
+// Base Bits= 58
+const BIG Modulus= {0x1FEFFFFFFFFAAABL,0x2FFFFAC54FFFFEEL,0x12A0F6B0F6241EAL,0x213CE144AFD9CC3L,0x2434BACD764774BL,0x25FF9A692C6E9EDL,0x1A0111EA3L};
+const BIG R2modp= {0x20639A1D5BEF7AEL,0x1244C6462DD93E8L,0x22D09B54E6E2CD2L,0x111C4B63170E5DBL,0x38A6DE8FB366399L,0x4F16CFED1F9CBCL,0x19EA66A2BL};
+const chunk MConst= 0x1F3FFFCFFFCFFFDL;
+const BIG Fra= {0x10775ED92235FB8L,0x3A94F58F9E04F63L,0x3D784BAB9C4F67L,0x3F4F2F57D3DEC91L,0x202C0D1F0FD603L,0xAEC199F08C6FADL,0x1904D3BF0L};
+const BIG Frb= {0xF78A126DDC4AF3L,0x356B0535B1FB08BL,0xEC971F63C5F282L,0x21EDB1ECDBFB032L,0x2231F9FB854A147L,0x1B1380CA23A7A40L,0xFC3E2B3L};
+
+#endif
+
+}
diff --git a/version3/cpp/rom_field_BLS383.cpp b/version3/cpp/rom_field_BLS383.cpp
new file mode 100644
index 0000000..7aaa6fc
--- /dev/null
+++ b/version3/cpp/rom_field_BLS383.cpp
@@ -0,0 +1,39 @@
+#include "arch.h"
+#include "fp_BLS383.h"
+
+namespace BLS383 {
+
+/* Curve BLS383 - Pairing friendly BLS curve */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+using namespace B384_29;
+
+// Base Bits= 29
+const BIG Modulus= {0x5AAB0AB,0x11B8EB24,0x19214AF6,0x187E5314,0x124F47A8,0x1C00B4B0,0x1446B0C6,0x59E6CB4,0x4A0AD46,0xFF5494,0x81B6B71,0x956DD6B,0x16556956,0x2A};
+const BIG R2modp= {0x116907F4,0x405B700,0x1752AC11,0x67A9E7C,0x1941C581,0x1AEA38C4,0xB1E4D22,0xCE841AE,0xA0FC49B,0xB4B1F48,0x13852312,0x1B3FDCED,0x1FECE397,0x26};
+const chunk MConst= 0x73435FD;
+const BIG Fra= {0x1311DAC1,0x296B969,0x19DCF806,0x126901FC,0xD8C8A36,0x1A2572A8,0xA1A0959,0x1A47F743,0x110E4C6C,0x1608DA97,0xCE2E7F0,0x4FED178,0xACD5BF0,0x11};
+const BIG Frb= {0x1298D5EA,0xF2231BA,0x1F4452F0,0x6155117,0x4C2BD72,0x1DB4208,0xA2CA76D,0xB567571,0x139260D9,0xAF679FC,0x1B388380,0x4580BF2,0xB880D66,0x19};
+#endif
+
+#if CHUNK==64
+
+using namespace B384_58;
+
+// Base Bits= 58
+const BIG Modulus= {0x2371D6485AAB0ABL,0x30FCA6299214AF6L,0x3801696124F47A8L,0xB3CD969446B0C6L,0x1FEA9284A0AD46L,0x12ADBAD681B6B71L,0x556556956L};
+const BIG R2modp= {0x80B6E0116907F4L,0xCF53CF9752AC11L,0x35D47189941C581L,0x19D0835CB1E4D22L,0x16963E90A0FC49BL,0x367FB9DB3852312L,0x4DFECE397L};
+const chunk MConst= 0x1BC0571073435FDL;
+const BIG Fra= {0x52D72D3311DAC1L,0x24D203F99DCF806L,0x344AE550D8C8A36L,0x348FEE86A1A0959L,0x2C11B52F10E4C6CL,0x9FDA2F0CE2E7F0L,0x22ACD5BF0L};
+const BIG Frb= {0x1E446375298D5EAL,0xC2AA22FF4452F0L,0x3B684104C2BD72L,0x16ACEAE2A2CA76DL,0x15ECF3F939260D9L,0x8B017E5B388380L,0x32B880D66L};
+
+#endif
+
+}
diff --git a/version3/cpp/rom_field_BLS461.cpp b/version3/cpp/rom_field_BLS461.cpp
new file mode 100644
index 0000000..696d82e
--- /dev/null
+++ b/version3/cpp/rom_field_BLS461.cpp
@@ -0,0 +1,40 @@
+#include "arch.h"
+#include "fp_BLS461.h"
+
+namespace BLS461 {
+
+/* Curve BLS383 - Pairing friendly BLS curve */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+using namespace B464_28;
+
+// Base Bits= 28
+const BIG Modulus= {0xAAAAAAB,0xAC0000A,0x54AAAAA,0x5555,0x400020,0x91557F0,0xF26AA,0xFA5C1CC,0xB42A8DF,0x7B14848,0x8BACCA4,0x6F1E32D,0x4935FBD,0x55D6941,0xD5A555A,0x5545554,0x1555};
+const BIG R2modp= {0xC9B6A33,0x2ECD087,0x3CCB2B1,0xCD461FE,0x8CB5AB2,0xC5B9635,0x5312E92,0xB659F64,0x3B596FA,0x8679006,0xA92E2B3,0x3CE05E3,0x363550F,0x7C07A8E,0x382C083,0x6347FEA,0xBD};
+const chunk MConst= 0xFFFFFFD;
+const BIG Fra= {0xB812A3A,0x7117BF9,0x99C400F,0xC6308A5,0x5BF8A1,0x510E075,0x45FA5A6,0xCE4858D,0x770B31A,0xBC2CB04,0xE2FC61E,0xD073588,0x4366190,0x4DFEFA8,0x69E55E2,0x504B7F,0x12E4};
+const BIG Frb= {0xF298071,0x3AE8410,0xBAE6A9B,0x39D4CAF,0xFE4077E,0x404777A,0xBAF8104,0x2C13C3E,0x3D1F5C5,0xBEE7D44,0xA8B0685,0x9EAADA4,0x5CFE2C,0x7D7999,0x6BBFF78,0x50409D5,0x271};
+
+#endif
+
+#if CHUNK==64
+
+using namespace B464_60;
+
+// Base Bits= 60
+const BIG Modulus= {0xAAC0000AAAAAAABL,0x20000555554AAAAL,0x6AA91557F004000L,0xA8DFFA5C1CC00F2L,0xACCA47B14848B42L,0x935FBD6F1E32D8BL,0xD5A555A55D69414L,0x15555545554L};
+const BIG R2modp= {0x96D08774614DDA8L,0xCD45F539225D5BDL,0xD712EB760C95AB1L,0xB3B687155F30B55L,0xC4E62A05C3F5B81L,0xBA1151676CA3CD0L,0x7EDD8A958F442BEL,0x12B89DD3F91L};
+const chunk MConst= 0xC0005FFFFFFFDL;
+const BIG Fra= {0xF7117BF9B812A3AL,0xA1C6308A599C400L,0x5A6510E07505BF8L,0xB31ACE4858D45FAL,0xFC61EBC2CB04770L,0x366190D073588E2L,0x69E55E24DFEFA84L,0x12E40504B7FL};
+const BIG Frb= {0xB3AE8410F298071L,0x7E39D4CAFBAE6A9L,0x104404777AFE407L,0xF5C52C13C3EBAF8L,0xB0685BEE7D443D1L,0x5CFE2C9EAADA4A8L,0x6BBFF7807D79990L,0x27150409D5L};
+
+#endif
+
+}
diff --git a/version3/cpp/rom_field_BLS48.cpp b/version3/cpp/rom_field_BLS48.cpp
new file mode 100644
index 0000000..bb13d00
--- /dev/null
+++ b/version3/cpp/rom_field_BLS48.cpp
@@ -0,0 +1,38 @@
+#include "arch.h"
+#include "fp_BLS48.h"
+
+namespace BLS48 {
+
+/* Curve BLS48 - Pairing friendly BLS curve */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+using namespace B560_29;
+
+// Base Bits= 29
+const BIG Modulus= {0x1CF6AC0B,0x17B7307F,0x19877E7B,0x12CE0134,0x14228402,0x1BD4C386,0x1DACBB04,0x40410D0,0x25A415,0x980B53E,0xDE6E250,0x15D9AAD6,0x5DA950,0x1029B7A,0x54AB351,0x14AD90CE,0x3729047,0x1FE7E2D9,0x145F610B,0x1F};
+const BIG R2modp= {0xD59D0FA,0x12F01FD0,0xDE8FD41,0x35AAEE1,0xB937F48,0x50700E8,0x1F50EFCE,0x1019B13C,0x3470A2F,0x11094115,0xF9FB72D,0x6AD10E2,0x1CFD9F8,0x44F4785,0x2B48793,0x1148ED3,0xF609E61,0x1EE34BC7,0x1735D29E,0x0};
+const chunk MConst= 0x9DA805D;
+const BIG Fra= {0x1325BF89,0x1311E7EC,0xCD0A56F,0x1A0FD46E,0xE83BCCA,0xCA97DD0,0x18D1D297,0x5F1E137,0x7AB9F2C,0x13FC255F,0x1C9DECEB,0x9DEF4A2,0x3C0F60B,0x1D9909E4,0x1FF27FF7,0x1DBF8208,0x89BB36C,0x40044E0,0x62E01EE,0x5};
+const BIG Frb= {0x1325BF89,0x1311E7EC,0xCD0A56F,0x1A0FD46E,0xE83BCCA,0xCA97DD0,0x18D1D297,0x5F1E137,0x7AB9F2C,0x13FC255F,0x1C9DECEB,0x9DEF4A2,0x3C0F60B,0x1D9909E4,0x1FF27FF7,0x1DBF8208,0x89BB36C,0x40044E0,0x62E01EE,0x5};
+#endif
+
+#if CHUNK==64
+
+using namespace B560_58;
+
+// Base Bits= 58
+const BIG Modulus= {0x2F6E60FFCF6AC0BL,0x259C02699877E7BL,0x37A9870D4228402L,0x80821A1DACBB04L,0x13016A7C025A415L,0x2BB355ACDE6E250L,0x20536F405DA950L,0x295B219C54AB351L,0x3FCFC5B23729047L,0x3F45F610BL};
+const BIG R2modp= {0x25E03FA0D59D0FAL,0x6B55DC2DE8FD41L,0xA0E01D0B937F48L,0x20336279F50EFCEL,0x2212822A3470A2FL,0xD5A21C4F9FB72DL,0x89E8F0A1CFD9F8L,0x2291DA62B48793L,0x3DC6978EF609E61L,0x1735D29EL};
+const chunk MConst= 0x21BFCBCA9DA805DL;
+const BIG Fra= {0x2623CFD9325BF89L,0x341FA8DCCD0A56FL,0x1952FBA0E83BCCAL,0xBE3C26F8D1D297L,0x27F84ABE7AB9F2CL,0x13BDE945C9DECEBL,0x3B3213C83C0F60BL,0x3B7F0411FF27FF7L,0x80089C089BB36CL,0xA62E01EEL};
+const BIG Frb= {0x2623CFD9325BF89L,0x341FA8DCCD0A56FL,0x1952FBA0E83BCCAL,0xBE3C26F8D1D297L,0x27F84ABE7AB9F2CL,0x13BDE945C9DECEBL,0x3B3213C83C0F60BL,0x3B7F0411FF27FF7L,0x80089C089BB36CL,0xA62E01EEL};
+#endif
+
+}
diff --git a/version3/cpp/rom_field_BN254.cpp b/version3/cpp/rom_field_BN254.cpp
new file mode 100644
index 0000000..1f06217
--- /dev/null
+++ b/version3/cpp/rom_field_BN254.cpp
@@ -0,0 +1,48 @@
+#include "arch.h"
+#include "fp_BN254.h"
+
+namespace BN254 {
+
+/* Curve BN254 - Pairing friendly BN curve */
+
+/* Nogami's fast curve */
+
+#if CHUNK==16
+
+using namespace B256_13;
+
+// Base Bits= 13
+const BIG Modulus= {0x13,0x0,0x0,0x0,0x1A70,0x9,0x0,0x0,0x100,0x309,0x2,0x0,0x1800,0x1A26,0x6E8,0x0,0x0,0x412,0x8D9,0x4A};
+const BIG R2modp= {0xF32,0x239,0x14DC,0xCE8,0x928,0x11B6,0x130F,0x1183,0x56E,0x1AEE,0x124F,0xD2A,0x7F8,0x1CE6,0x1B50,0x77C,0x3A,0x1A9E,0x1EFD,0x1C};
+const chunk MConst= 0x15E5;
+const BIG Fra= {0xDE9,0x1953,0x101B,0x1BCD,0xE17,0x1BE1,0x14FD,0x1249,0x974,0x1C28,0x54F,0x108D,0x150A,0x4CD,0x12D9,0xF91,0x12E,0x10C9,0xDDD,0x36};
+const BIG Frb= {0x122A,0x6AC,0xFE4,0x432,0xC58,0x428,0xB02,0xDB6,0x178B,0x6E0,0x1AB2,0xF72,0x2F5,0x1559,0x140F,0x106E,0x1ED1,0x1348,0x1AFB,0x13};
+
+#endif
+
+#if CHUNK==32
+
+using namespace B256_28;
+
+// Base Bits= 28
+const BIG Modulus= {0x13,0x0,0x13A7,0x0,0x86121,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2};
+const BIG R2modp= {0xF5E7E39,0x2F2A96F,0xB96F13C,0x64E8642,0xC7146,0x9926F7B,0x4DACD24,0x8321E7B,0xD127A2E,0x1};
+const chunk MConst= 0x79435E5;
+const BIG Fra= {0xF2A6DE9,0x7DE6C06,0xF77C2E1,0x74924D3,0x53F8509,0x50A8469,0xCB6499B,0x212E7C8,0xB377619,0x1};
+const BIG Frb= {0xD5922A,0x82193F9,0x8850C5,0x8B6DB2C,0xAC8DC17,0x2F57B96,0x503EAB2,0x1ED1837,0x9EBEE69,0x0};
+
+#endif
+
+#if CHUNK==64
+
+using namespace B256_56;
+
+// Base Bits= 56
+const BIG Modulus= {0x13L,0x13A7L,0x80000000086121L,0x40000001BA344DL,0x25236482L};
+const BIG R2modp= {0x2F2A96FF5E7E39L,0x64E8642B96F13CL,0x9926F7B00C7146L,0x8321E7B4DACD24L,0x1D127A2EL};
+const chunk MConst= 0x435E50D79435E5L;
+const BIG Fra= {0x7DE6C06F2A6DE9L,0x74924D3F77C2E1L,0x50A846953F8509L,0x212E7C8CB6499BL,0x1B377619L};
+const BIG Frb= {0x82193F90D5922AL,0x8B6DB2C08850C5L,0x2F57B96AC8DC17L,0x1ED1837503EAB2L,0x9EBEE69L};
+#endif
+
+}
diff --git a/version3/cpp/rom_field_BN254CX.cpp b/version3/cpp/rom_field_BN254CX.cpp
new file mode 100644
index 0000000..d49488e
--- /dev/null
+++ b/version3/cpp/rom_field_BN254CX.cpp
@@ -0,0 +1,49 @@
+#include "arch.h"
+#include "fp_BN254CX.h"
+
+namespace BN254CX {
+
+/* Curve BN254CX - Pairing friendly BN curve */
+
+/* CertiVox BN curve/field  */
+
+#if CHUNK==16
+
+using namespace B256_13;
+
+// Base Bits= 13
+const BIG Modulus= {0x15B3,0xDA,0x1BD7,0xC47,0x1BE6,0x1F70,0x24,0x1DC3,0x1FD6,0x1921,0x19B4,0x14C6,0x1647,0x1EEF,0x16C2,0x541,0x870,0x0,0x0,0x48};
+const BIG R2modp= {0x1527,0x146B,0x12A7,0x1A60,0x1E0A,0x1382,0x2BC,0x1D3F,0xB30,0xA8,0xD19,0x11AB,0x1D40,0x1965,0xD6D,0x643,0x10FF,0x1BC7,0x1E61,0x31};
+const chunk MConst= 0x1E85;
+const BIG Fra= {0xEA3,0xE40,0xCD5,0x1210,0x15BD,0x1C10,0x5CF,0x4DE,0x773,0x343,0x626,0x194E,0x18AA,0x10C5,0x12BF,0x2C,0x63A,0x17D,0x1642,0x26};
+const BIG Frb= {0x710,0x129A,0xF01,0x1A37,0x628,0x360,0x1A55,0x18E4,0x1863,0x15DE,0x138E,0x1B78,0x1D9C,0xE29,0x403,0x515,0x236,0x1E83,0x9BD,0x21};
+
+
+#endif
+
+#if CHUNK==32
+
+using namespace B256_28;
+
+// Base Bits= 28
+const BIG Modulus= {0xC1B55B3,0x6623EF5,0x93EE1BE,0xD6EE180,0x6D3243F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2};
+const BIG R2modp= {0x8A0800A,0x466A061,0x43056A3,0x2B3A225,0x9C6600,0x148515B,0x6BDF50,0xEC9EA56,0xC992E66,0x1};
+const chunk MConst= 0x9789E85;
+const BIG Fra= {0x5C80EA3,0xD908335,0x3F8215B,0x7326F17,0x8986867,0x8AACA71,0x4AFE18B,0xA63A016,0x359082F,0x1};
+const BIG Frb= {0x6534710,0x8D1BBC0,0x546C062,0x63C7269,0xE3ABBD8,0xD9CDBC4,0x900DC53,0x623628A,0xA6F7D0,0x1};
+
+#endif
+
+#if CHUNK==64
+
+using namespace B256_56;
+
+// Base Bits= 56
+const BIG Modulus= {0x6623EF5C1B55B3L,0xD6EE18093EE1BEL,0x647A6366D3243FL,0x8702A0DB0BDDFL,0x24000000L};
+const BIG R2modp= {0x466A0618A0800AL,0x2B3A22543056A3L,0x148515B09C6600L,0xEC9EA5606BDF50L,0x1C992E66L};
+const chunk MConst= 0x4E205BF9789E85L;
+const BIG Fra= {0xD9083355C80EA3L,0x7326F173F8215BL,0x8AACA718986867L,0xA63A0164AFE18BL,0x1359082FL};
+const BIG Frb= {0x8D1BBC06534710L,0x63C7269546C062L,0xD9CDBC4E3ABBD8L,0x623628A900DC53L,0x10A6F7D0L};
+#endif
+
+}
diff --git a/version3/cpp/rom_field_BRAINPOOL.cpp b/version3/cpp/rom_field_BRAINPOOL.cpp
new file mode 100644
index 0000000..a9615aa
--- /dev/null
+++ b/version3/cpp/rom_field_BRAINPOOL.cpp
@@ -0,0 +1,34 @@
+#include "arch.h"
+#include "fp_BRAINPOOL.h"
+
+namespace BRAINPOOL {
+
+/* Brainpool Modulus  */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+using namespace B256_28;
+
+// Base Bits= 28
+const BIG Modulus= {0xF6E5377,0x13481D1,0x6202820,0xF623D52,0xD726E3B,0x909D838,0xC3E660A,0xA1EEA9B,0x9FB57DB,0xA};
+const BIG R2modp= {0xB9A3787,0x9E04F49,0x8F3CF49,0x2931721,0xF1DBC89,0x54E8C3C,0xF7559CA,0xBB411A3,0x773E15F,0x9};
+const chunk MConst= 0xEFD89B9;
+#endif
+
+#if CHUNK==64
+
+using namespace B256_56;
+
+// Base Bits= 56
+const BIG Modulus= {0x13481D1F6E5377L,0xF623D526202820L,0x909D838D726E3BL,0xA1EEA9BC3E660AL,0xA9FB57DBL};
+const BIG R2modp= {0x9E04F49B9A3787L,0x29317218F3CF49L,0x54E8C3CF1DBC89L,0xBB411A3F7559CAL,0x9773E15FL};
+const chunk MConst= 0xA75590CEFD89B9L;
+#endif
+
+}
diff --git a/version3/cpp/rom_field_C41417.cpp b/version3/cpp/rom_field_C41417.cpp
new file mode 100644
index 0000000..d1ecbf6
--- /dev/null
+++ b/version3/cpp/rom_field_C41417.cpp
@@ -0,0 +1,34 @@
+#include "arch.h"
+#include "fp_C41417.h"
+
+namespace C41417 {
+
+/* Curve C41417 */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+using namespace B416_29;
+
+// Base Bits= 29
+const BIG Modulus= {0x1FFFFFEF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFF};
+const BIG R2modp= {0x0,0x242000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const chunk MConst= 0x11;
+#endif
+
+#if CHUNK==64
+
+using namespace B416_60;
+
+// Base Bits= 60
+const BIG Modulus= {0xFFFFFFFFFFFFFEFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFL};
+const BIG R2modp= {0x121000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const chunk MConst= 0x11L;
+#endif
+
+}
diff --git a/version3/cpp/rom_field_F25519.cpp b/version3/cpp/rom_field_F25519.cpp
new file mode 100644
index 0000000..15ef934
--- /dev/null
+++ b/version3/cpp/rom_field_F25519.cpp
@@ -0,0 +1,43 @@
+#include "arch.h"
+#include "fp_F25519.h"
+
+
+namespace F25519 {
+/* Curve 25519 */
+
+#if CHUNK==16
+
+using namespace B256_13;
+
+// Base Bits= 13
+const BIG Modulus= {0x1FED,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0xFF};
+const BIG R2modp= {0x400,0x2D,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const chunk MConst= 0x13;
+
+#endif
+
+#if CHUNK==32
+
+using namespace B256_29;
+
+// Base Bits= 29
+const BIG Modulus= {0x1FFFFFED,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFFF};
+const BIG R2modp= {0x169000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const chunk MConst= 0x13;
+
+
+#endif
+
+#if CHUNK==64
+
+using namespace B256_56;
+
+// Base Bits= 56
+const BIG Modulus= {0xFFFFFFFFFFFFEDL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0x7FFFFFFFL};
+const BIG R2modp= {0xA4000000000000L,0x5L,0x0L,0x0L,0x0L};
+const chunk MConst= 0x13L;
+
+
+#endif
+
+}
diff --git a/version3/cpp/rom_field_F256PME.cpp b/version3/cpp/rom_field_F256PME.cpp
new file mode 100644
index 0000000..3bd0f7c
--- /dev/null
+++ b/version3/cpp/rom_field_F256PME.cpp
@@ -0,0 +1,41 @@
+#include "arch.h"
+#include "fp_F256PME.h"
+
+namespace F256PME {
+
+/* NUMS 256-bit modulus */
+
+
+#if CHUNK==16
+
+using namespace B256_13;
+
+// Base Bits= 13
+const BIG Modulus= {0x1F43,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FFF,0x1FF};
+const BIG R2modp= {0x900,0x45C,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const chunk MConst= 0xBD;
+#endif
+
+#if CHUNK==32
+
+using namespace B256_29;
+
+// Base Bits= 29
+const BIG Modulus= {0x1FFFFF43,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFFFFFF};
+const BIG R2modp= {0x22E2400,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const chunk MConst= 0xBD;
+
+#endif
+
+#if CHUNK==64
+
+using namespace B256_56;
+
+// Base Bits= 56
+const BIG Modulus= {0xFFFFFFFFFFFF43L,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFL};
+const BIG R2modp= {0x89000000000000L,0x8BL,0x0L,0x0L,0x0L};
+const chunk MConst= 0xBDL;
+
+#endif
+
+}
diff --git a/version3/cpp/rom_field_F256PMW.cpp b/version3/cpp/rom_field_F256PMW.cpp
new file mode 100644
index 0000000..c8a418d
--- /dev/null
+++ b/version3/cpp/rom_field_F256PMW.cpp
@@ -0,0 +1,36 @@
+#include "arch.h"
+#include "fp_F256PMW.h"
+
+namespace F256PMW {
+
+/* NUMS 256-bit modulus */
+
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+using namespace B256_28;
+
+// Base Bits= 28
+const BIG Modulus= {0xFFFFF43,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xF};
+const BIG R2modp= {0x0,0x8900000,0x8B,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const chunk MConst= 0xBD;
+#endif
+
+#if CHUNK==64
+
+using namespace B256_56;
+
+// Base Bits= 56
+const BIG Modulus= {0xFFFFFFFFFFFF43L,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFL};
+const BIG R2modp= {0x89000000000000L,0x8BL,0x0L,0x0L,0x0L};
+const chunk MConst= 0xBDL;
+
+#endif
+
+}
diff --git a/version3/cpp/rom_field_F384PM.cpp b/version3/cpp/rom_field_F384PM.cpp
new file mode 100644
index 0000000..9d64cb0
--- /dev/null
+++ b/version3/cpp/rom_field_F384PM.cpp
@@ -0,0 +1,35 @@
+#include "arch.h"
+#include "fp_F384PM.h"
+
+namespace F384PM {
+
+/* NUMS 384-bit modulus */
+
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+using namespace B384_29;
+
+// Base Bits= 29
+const BIG Modulus= {0x1FFFFEC3,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F};
+const BIG R2modp= {0x0,0x4448000,0x6,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const chunk MConst= 0x13D;
+#endif
+
+#if CHUNK==64
+
+using namespace B384_56;
+
+// Base Bits= 56
+const BIG Modulus= {0xFFFFFFFFFFFEC3L,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFL};
+const BIG R2modp= {0x188890000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const chunk MConst= 0x13DL;
+#endif
+
+}
diff --git a/version3/cpp/rom_field_F512PM.cpp b/version3/cpp/rom_field_F512PM.cpp
new file mode 100644
index 0000000..9768bc2
--- /dev/null
+++ b/version3/cpp/rom_field_F512PM.cpp
@@ -0,0 +1,35 @@
+#include "arch.h"
+#include "fp_F512PM.h"
+
+namespace F512PM {
+
+/* NUMS 512-bit modulus */
+
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+using namespace B512_29;
+
+// Base Bits= 29
+const BIG Modulus= {0x1FFFFDC7,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF};
+const BIG R2modp= {0xB100000,0x278,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const chunk MConst= 0x239;
+#endif
+
+#if CHUNK==64
+
+using namespace B512_56;
+
+// Base Bits= 56
+const BIG Modulus= {0xFFFFFFFFFFFDC7L,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFL};
+const BIG R2modp= {0x0L,0xF0B10000000000L,0x4L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const chunk MConst= 0x239L;
+#endif
+
+}
diff --git a/version3/cpp/rom_field_FP256BN.cpp b/version3/cpp/rom_field_FP256BN.cpp
new file mode 100644
index 0000000..bbbe6c0
--- /dev/null
+++ b/version3/cpp/rom_field_FP256BN.cpp
@@ -0,0 +1,45 @@
+#include "arch.h"
+#include "fp_FP256BN.h"
+
+namespace FP256BN {
+
+/* Curve FP512BN - Pairing friendly BN curve */
+
+/* ISO curve */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+using namespace B256_28;
+
+// Base Bits= 28
+
+const BIG Modulus= {0xED33013,0x292DDBA,0x80A82D3,0x65FB129,0x49F0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF};
+const BIG R2modp= {0x3B9F8B,0xEDE3363,0xFEC54E8,0x92FFEE9,0x3C55F79,0x13C1C06,0xC0123FA,0xA12F2EA,0xE559B2A,0x8};
+const chunk MConst= 0x537E5E5;
+const BIG Fra= {0xF943106,0x760328A,0xAB28F74,0x71511E3,0x7CF39A1,0x8DDB086,0x52D1A6E,0xCA786F3,0xD617662,0x3};
+const BIG Frb= {0xF3EFF0D,0xB32AB2F,0xD57F35E,0xF4A9F45,0xCCFD33A,0xD113693,0x819CB83,0x3584819,0x29E899D,0xC};
+
+
+#endif
+
+#if CHUNK==64
+
+using namespace B256_56;
+
+// Base Bits= 56
+const BIG Modulus= {0x292DDBAED33013L,0x65FB12980A82D3L,0x5EEE71A49F0CDCL,0xFFFCF0CD46E5F2L,0xFFFFFFFFL};
+const BIG R2modp= {0xEDE336303B9F8BL,0x92FFEE9FEC54E8L,0x13C1C063C55F79L,0xA12F2EAC0123FAL,0x8E559B2AL};
+const chunk MConst= 0x6C964E0537E5E5L;
+const BIG Fra= {0x760328AF943106L,0x71511E3AB28F74L,0x8DDB0867CF39A1L,0xCA786F352D1A6EL,0x3D617662L};
+const BIG Frb= {0xB32AB2FF3EFF0DL,0xF4A9F45D57F35EL,0xD113693CCFD33AL,0x3584819819CB83L,0xC29E899DL};
+
+
+#endif
+
+}
diff --git a/version3/cpp/rom_field_FP512BN.cpp b/version3/cpp/rom_field_FP512BN.cpp
new file mode 100644
index 0000000..ed9abd3
--- /dev/null
+++ b/version3/cpp/rom_field_FP512BN.cpp
@@ -0,0 +1,47 @@
+#include "arch.h"
+#include "fp_FP512BN.h"
+
+namespace FP512BN {
+
+/* Curve FP512BN - Pairing friendly BN curve */
+
+/* ISO curve */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+using namespace B512_29;
+
+// Base Bits= 29
+
+const BIG Modulus= {0x2ADEF33,0x7594049,0x131919ED,0x14AB9CBE,0x16FE1916,0x12EF5591,0x2E39231,0x3D597D3,0x55146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF};
+const BIG R2modp= {0xFD68B47,0xFCF5D2C,0x437675A,0x1BBC3FBF,0x1411E413,0x13453559,0x10B5639,0x1C34CE79,0x6D476BF,0xFD05F2B,0x15D17C28,0x6C9F76E,0x1C2375B3,0x78CCE9B,0x15F0AB33,0x1960F32E,0x1A8D44E,0x57A38};
+const chunk MConst= 0x1CCC5C05;
+const BIG Fra= {0x14B73AB2,0x4B0BD8F,0xABB47D,0x2A29EC4,0x18681E17,0x104069DE,0x12EED67D,0x1553D0A5,0x398E9F8,0x7971034,0xAC9AF23,0x52DEF23,0x14EA18A5,0x1463E345,0x6DE465A,0x17F212B4,0x1AA9CF5B,0xF7B8};
+const BIG Frb= {0xDF6B481,0x2A882B9,0x126D6570,0x1208FDFA,0x1E95FAFF,0x2AEEBB2,0xFF4BBB4,0xE81C72D,0x1B85CD6,0xF67746,0x56549CD,0xC68B6EC,0x776A178,0x8925C3B,0x1921B9A5,0x80DED4B,0x55630A4,0x70847};
+
+
+
+#endif
+
+#if CHUNK==64
+
+using namespace B512_60;
+
+// Base Bits= 60
+
+const BIG Modulus= {0x4EB280922ADEF33L,0x6A55CE5F4C6467BL,0xC65DEAB236FE191L,0xCF1EACBE98B8E48L,0x3C111B0EF455146L,0xA1D8CB5307C0BBEL,0xFFFF9EC7F01C60BL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFL};
+const BIG R2modp= {0x1FA6DCEF99812E9L,0xAB3452895A0B74EL,0xC53EA988C079E1EL,0x1E90E033BA630B9L,0xF1EA41C0714D8B0L,0xE72785387509E28L,0xD86794F834DAB00L,0x9757C2ACCD342A1L,0x44ECB079L};
+const chunk MConst= 0x692A189FCCC5C05L;
+const BIG Fra= {0x49617B1F4B73AB2L,0x71514F6202AED1FL,0xF6080D3BD8681E1L,0xF8AA9E852CBBB59L,0xC8CF2E2068398E9L,0x8A5296F791AB26BL,0x196A8C7C68B4EA1L,0xCF5BBF9095A1B79L,0x1EF71AA9L};
+const BIG Frb= {0x5510572DF6B481L,0xF9047EFD49B595CL,0xD055DD765E95FAFL,0xD6740E396BFD2EEL,0x7341ECEE8C1B85CL,0x1786345B7615952L,0xE695124B876776AL,0x30A4406F6A5E486L,0xE108E556L};
+
+
+#endif
+
+}
diff --git a/version3/cpp/rom_field_GOLDILOCKS.cpp b/version3/cpp/rom_field_GOLDILOCKS.cpp
new file mode 100644
index 0000000..d3881f9
--- /dev/null
+++ b/version3/cpp/rom_field_GOLDILOCKS.cpp
@@ -0,0 +1,38 @@
+#include "arch.h"
+#include "fp_GOLDILOCKS.h"
+
+namespace GOLDILOCKS {
+
+/* Curve GOLDILOCKS */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+using namespace B448_29;
+
+// Base Bits= 29
+const BIG Modulus= {0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FDFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFF};
+const BIG R2modp= {0x0,0x10,0x0,0x0,0x0,0x0,0x0,0x0,0x3000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const chunk MConst= 0x1;
+const int BTset= 224;
+
+#endif
+
+#if CHUNK==64
+
+using namespace B448_58;
+
+// Base Bits= 58
+const BIG Modulus= {0x3FFFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFFL,0x3FBFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFFL,0x3FFFFFFFFFFL};
+const BIG R2modp= {0x200000000L,0x0L,0x0L,0x0L,0x3000000L,0x0L,0x0L,0x0L};
+const chunk MConst= 0x1L;
+const int BTset=224;
+
+#endif
+
+}
diff --git a/version3/cpp/rom_field_HIFIVE.cpp b/version3/cpp/rom_field_HIFIVE.cpp
new file mode 100644
index 0000000..795ce37
--- /dev/null
+++ b/version3/cpp/rom_field_HIFIVE.cpp
@@ -0,0 +1,35 @@
+#include "arch.h"
+#include "fp_HIFIVE.h"
+
+namespace HIFIVE {
+
+/* Curve HIFIVE */
+
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+using namespace B336_29;
+
+// Base Bits= 29
+const BIG Modulus= {0x1FFFFFFD,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFF};
+const BIG R2modp= {0x9000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const chunk MConst= 0x3;
+#endif
+
+#if CHUNK==64
+
+using namespace B336_60;
+
+// Base Bits= 60
+const BIG Modulus= {0xFFFFFFFFFFFFFFDL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFL};
+const BIG R2modp= {0x9000000000000L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const chunk MConst= 0x3L;
+#endif
+
+}
diff --git a/version3/cpp/rom_field_NIST256.cpp b/version3/cpp/rom_field_NIST256.cpp
new file mode 100644
index 0000000..a1ae623
--- /dev/null
+++ b/version3/cpp/rom_field_NIST256.cpp
@@ -0,0 +1,35 @@
+#include "arch.h"
+#include "fp_NIST256.h"
+
+namespace NIST256 {
+
+/* Curve NIST256 */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+using namespace B256_28;
+
+// Base Bits= 28
+const BIG Modulus= {0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFF,0x0,0x0,0x1000000,0x0,0xFFFFFFF,0xF};
+const BIG R2modp= {0x50000,0x300000,0x0,0x0,0xFFFFFFA,0xFFFFFBF,0xFFFFEFF,0xFFFAFFF,0x2FFFF,0x0};
+const chunk MConst= 0x1;
+#endif
+
+#if CHUNK==64
+
+using namespace B256_56;
+
+// Base Bits= 56
+const BIG Modulus= {0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFL,0x0L,0x1000000L,0xFFFFFFFFL};
+const BIG R2modp= {0x3000000050000L,0x0L,0xFFFFFBFFFFFFFAL,0xFFFAFFFFFFFEFFL,0x2FFFFL};
+const chunk MConst= 0x1L;
+
+#endif
+
+}
diff --git a/version3/cpp/rom_field_NIST384.cpp b/version3/cpp/rom_field_NIST384.cpp
new file mode 100644
index 0000000..12d6044
--- /dev/null
+++ b/version3/cpp/rom_field_NIST384.cpp
@@ -0,0 +1,35 @@
+#include "arch.h"
+#include "fp_NIST384.h"
+
+namespace NIST384 {
+
+/* Curve NIST384 */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+using namespace B384_29;
+
+// Base Bits= 29
+const BIG Modulus= {0x1FFFFFFF,0x7,0x0,0x1FFFFE00,0x1FFFEFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F};
+const BIG R2modp= {0x0,0x8000,0x1FF80000,0x1FFFFF,0x2000000,0x0,0x0,0x1FFFFFFC,0xF,0x100,0x400,0x0,0x0,0x0};
+const chunk MConst= 0x1;
+#endif
+
+#if CHUNK==64
+
+using namespace B384_56;
+
+// Base Bits= 56
+const BIG Modulus= {0xFFFFFFFFL,0xFFFF0000000000L,0xFFFFFFFFFEFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFL};
+const BIG R2modp= {0xFE000000010000L,0xFFFFFFL,0x2L,0xFFFFFFFE00L,0x1000000020000L,0x0L,0x0L};
+const chunk MConst= 0x100000001L;
+
+#endif
+
+}
diff --git a/version3/cpp/rom_field_NIST521.cpp b/version3/cpp/rom_field_NIST521.cpp
new file mode 100644
index 0000000..a92393c
--- /dev/null
+++ b/version3/cpp/rom_field_NIST521.cpp
@@ -0,0 +1,34 @@
+#include "arch.h"
+#include "fp_NIST521.h"
+
+namespace NIST521 {
+
+/* Curve NIST521 */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+using namespace B528_28;
+
+// Base Bits= 28
+const BIG Modulus= {0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0x1FFFF};
+const BIG R2modp= {0x400000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+const chunk MConst= 0x1;
+#endif
+
+#if CHUNK==64
+
+using namespace B528_56;
+
+// Base Bits= 60
+const BIG Modulus= {0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0x1FFFFFFFFFFL};
+const BIG R2modp= {0x4000000000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+const chunk MConst= 0x1L;
+#endif
+
+}
diff --git a/version3/cpp/rom_field_SECP256K1.cpp b/version3/cpp/rom_field_SECP256K1.cpp
new file mode 100644
index 0000000..a4db853
--- /dev/null
+++ b/version3/cpp/rom_field_SECP256K1.cpp
@@ -0,0 +1,38 @@
+#include "arch.h"
+#include "fp_SECP256K1.h"
+
+namespace SECP256K1 {
+
+/* Curve SECP256K1 */
+
+#if CHUNK==16
+
+#error Not supported
+
+#endif
+
+#if CHUNK==32
+
+using namespace B256_28;
+
+// Base Bits= 28
+const BIG Modulus= {0xFFFFC2F,0xFFFFFEF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xF};
+const BIG R2modp= {0x0,0xA100000,0x2000E90,0x7A,0x1,0x0,0x0,0x0,0x0,0x0};
+const chunk MConst= 0x2253531;
+
+#endif
+
+#if CHUNK==64
+
+using namespace B256_56;
+
+// Base Bits= 56
+const BIG Modulus= {0xFFFFFEFFFFFC2FL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFL};
+const BIG R2modp= {0xA1000000000000L,0x7A2000E90L,0x1L,0x0L,0x0L};
+//const chunk MConst= 0x1000003D1L;
+
+const chunk MConst= 0x38091DD2253531L;
+
+#endif
+
+}
diff --git a/version3/cpp/rsa.cpp b/version3/cpp/rsa.cpp
new file mode 100644
index 0000000..e55b197
--- /dev/null
+++ b/version3/cpp/rsa.cpp
@@ -0,0 +1,164 @@
+/*
+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.
+*/
+
+/* RSA Functions - see main program below */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "rsa_WWW.h"
+#include "rsa_support.h"
+
+using namespace XXX;
+
+/* generate an RSA key pair */
+void WWW::RSA_KEY_PAIR(csprng *RNG,sign32 e,rsa_private_key *PRIV,rsa_public_key *PUB,octet *P, octet* Q)
+{
+    /* IEEE1363 A16.11/A16.12 more or less */
+    BIG t[HFLEN_WWW],p1[HFLEN_WWW],q1[HFLEN_WWW];
+
+    if (RNG!=NULL)
+    {
+
+        for (;;)
+        {
+
+            FF_random(PRIV->p,RNG,HFLEN_WWW);
+            while (FF_lastbits(PRIV->p,2)!=3) FF_inc(PRIV->p,1,HFLEN_WWW);
+            while (!FF_prime(PRIV->p,RNG,HFLEN_WWW))
+                FF_inc(PRIV->p,4,HFLEN_WWW);
+
+            FF_copy(p1,PRIV->p,HFLEN_WWW);
+            FF_dec(p1,1,HFLEN_WWW);
+
+            if (FF_cfactor(p1,e,HFLEN_WWW)) continue;
+            break;
+        }
+
+        for (;;)
+        {
+            FF_random(PRIV->q,RNG,HFLEN_WWW);
+            while (FF_lastbits(PRIV->q,2)!=3) FF_inc(PRIV->q,1,HFLEN_WWW);
+            while (!FF_prime(PRIV->q,RNG,HFLEN_WWW))
+                FF_inc(PRIV->q,4,HFLEN_WWW);
+
+            FF_copy(q1,PRIV->q,HFLEN_WWW);
+            FF_dec(q1,1,HFLEN_WWW);
+            if (FF_cfactor(q1,e,HFLEN_WWW)) continue;
+
+            break;
+        }
+
+    }
+    else
+    {
+        FF_fromOctet(PRIV->p,P,HFLEN_WWW);
+        FF_fromOctet(PRIV->q,Q,HFLEN_WWW);
+
+        FF_copy(p1,PRIV->p,HFLEN_WWW);
+        FF_dec(p1,1,HFLEN_WWW);
+
+        FF_copy(q1,PRIV->q,HFLEN_WWW);
+        FF_dec(q1,1,HFLEN_WWW);
+    }
+
+    FF_mul(PUB->n,PRIV->p,PRIV->q,HFLEN_WWW);
+    PUB->e=e;
+
+    FF_copy(t,p1,HFLEN_WWW);
+    FF_shr(t,HFLEN_WWW);
+    FF_init(PRIV->dp,e,HFLEN_WWW);
+    FF_invmodp(PRIV->dp,PRIV->dp,t,HFLEN_WWW);
+    if (FF_parity(PRIV->dp)==0) FF_add(PRIV->dp,PRIV->dp,t,HFLEN_WWW);
+    FF_norm(PRIV->dp,HFLEN_WWW);
+
+    FF_copy(t,q1,HFLEN_WWW);
+    FF_shr(t,HFLEN_WWW);
+    FF_init(PRIV->dq,e,HFLEN_WWW);
+    FF_invmodp(PRIV->dq,PRIV->dq,t,HFLEN_WWW);
+    if (FF_parity(PRIV->dq)==0) FF_add(PRIV->dq,PRIV->dq,t,HFLEN_WWW);
+    FF_norm(PRIV->dq,HFLEN_WWW);
+
+    FF_invmodp(PRIV->c,PRIV->p,PRIV->q,HFLEN_WWW);
+
+    return;
+}
+
+/* destroy the Private Key structure */
+void WWW::RSA_PRIVATE_KEY_KILL(rsa_private_key *PRIV)
+{
+    FF_zero(PRIV->p,HFLEN_WWW);
+    FF_zero(PRIV->q,HFLEN_WWW);
+    FF_zero(PRIV->dp,HFLEN_WWW);
+    FF_zero(PRIV->dq,HFLEN_WWW);
+    FF_zero(PRIV->c,HFLEN_WWW);
+}
+
+void WWW::RSA_fromOctet(BIG x[],octet *w)
+{
+	FF_fromOctet(x,w,FFLEN_WWW);
+}
+
+/* RSA encryption with the public key */
+void WWW::RSA_ENCRYPT(rsa_public_key *PUB,octet *F,octet *G)
+{
+    BIG f[FFLEN_WWW];
+    FF_fromOctet(f,F,FFLEN_WWW);
+
+    FF_power(f,f,PUB->e,PUB->n,FFLEN_WWW);
+
+    FF_toOctet(G,f,FFLEN_WWW);
+}
+
+/* RSA decryption with the private key */
+void WWW::RSA_DECRYPT(rsa_private_key *PRIV,octet *G,octet *F)
+{
+    BIG g[FFLEN_WWW],t[FFLEN_WWW],jp[HFLEN_WWW],jq[HFLEN_WWW];
+
+    FF_fromOctet(g,G,FFLEN_WWW);
+
+    FF_dmod(jp,g,PRIV->p,HFLEN_WWW);
+    FF_dmod(jq,g,PRIV->q,HFLEN_WWW);
+
+    FF_skpow(jp,jp,PRIV->dp,PRIV->p,HFLEN_WWW);
+    FF_skpow(jq,jq,PRIV->dq,PRIV->q,HFLEN_WWW);
+
+
+    FF_zero(g,FFLEN_WWW);
+    FF_copy(g,jp,HFLEN_WWW);
+    FF_mod(jp,PRIV->q,HFLEN_WWW);
+    if (FF_comp(jp,jq,HFLEN_WWW)>0)
+        FF_add(jq,jq,PRIV->q,HFLEN_WWW);
+    FF_sub(jq,jq,jp,HFLEN_WWW);
+    FF_norm(jq,HFLEN_WWW);
+
+    FF_mul(t,PRIV->c,jq,HFLEN_WWW);
+    FF_dmod(jq,t,PRIV->q,HFLEN_WWW);
+
+    FF_mul(t,jq,PRIV->p,HFLEN_WWW);
+    FF_add(g,t,g,FFLEN_WWW);
+    FF_norm(g,FFLEN_WWW);
+
+    FF_toOctet(F,g,FFLEN_WWW);
+
+    return;
+}
+
diff --git a/version3/cpp/rsa.h b/version3/cpp/rsa.h
new file mode 100644
index 0000000..81d2578
--- /dev/null
+++ b/version3/cpp/rsa.h
@@ -0,0 +1,106 @@
+/*
+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.
+*/
+
+/**
+ * @file rsa.h
+ * @author Mike Scott and Kealan McCusker
+ * @date 2nd June 2015
+ * @brief RSA Header file for implementation of RSA protocol
+ *
+ * declares functions
+ *
+ */
+
+#ifndef RSA_WWW_H
+#define RSA_WWW_H
+
+#include "ff_WWW.h"
+#include "rsa_support.h"
+
+using namespace amcl;
+
+/*** START OF USER CONFIGURABLE SECTION -  ***/
+
+#define HASH_TYPE_RSA_WWW SHA256 /**< Chosen Hash algorithm */
+
+/*** END OF USER CONFIGURABLE SECTION ***/
+
+#define RFS_WWW MODBYTES_XXX*FFLEN_WWW /**< RSA Public Key Size in bytes */
+
+
+namespace WWW {
+
+/**
+	@brief Integer Factorisation Public Key
+*/
+
+typedef struct
+{
+    sign32 e;     /**< RSA exponent (typically 65537) */
+    XXX::BIG n[FFLEN_WWW]; /**< An array of BIGs to store public key */
+} rsa_public_key;
+
+/**
+	@brief Integer Factorisation Private Key
+*/
+
+typedef struct
+{
+    XXX::BIG p[FFLEN_WWW/2];  /**< secret prime p  */
+    XXX::BIG q[FFLEN_WWW/2];  /**< secret prime q  */
+    XXX::BIG dp[FFLEN_WWW/2]; /**< decrypting exponent mod (p-1)  */
+    XXX::BIG dq[FFLEN_WWW/2]; /**< decrypting exponent mod (q-1)  */
+    XXX::BIG c[FFLEN_WWW/2];  /**< 1/p mod q */
+} rsa_private_key;
+
+/* RSA Auxiliary Functions */
+
+extern void RSA_KEY_PAIR(csprng *R,sign32 e,rsa_private_key* PRIV,rsa_public_key* PUB,octet *P, octet* Q);
+
+/**	@brief RSA encryption of suitably padded plaintext
+ *
+	@param PUB the input RSA public key
+	@param F is input padded message
+	@param G is the output ciphertext
+ */
+extern void RSA_ENCRYPT(rsa_public_key* PUB,octet *F,octet *G);
+/**	@brief RSA decryption of ciphertext
+ *
+	@param PRIV the input RSA private key
+	@param G is the input ciphertext
+	@param F is output plaintext (requires unpadding)
+
+ */
+extern void RSA_DECRYPT(rsa_private_key* PRIV,octet *G,octet *F);
+/**	@brief Destroy an RSA private Key
+ *
+	@param PRIV the input RSA private key. Destroyed on output.
+ */
+extern void RSA_PRIVATE_KEY_KILL(rsa_private_key *PRIV);
+/**	@brief Populates an RSA public key from an octet string
+ *
+	Creates RSA public key from big-endian base 256 form.
+	@param x FF instance to be created from an octet string
+	@param S input octet string
+ */
+extern void RSA_fromOctet(XXX::BIG *x,octet *S);
+}
+
+
+#endif
diff --git a/version3/cpp/rsa_support.cpp b/version3/cpp/rsa_support.cpp
new file mode 100644
index 0000000..e313e39
--- /dev/null
+++ b/version3/cpp/rsa_support.cpp
@@ -0,0 +1,239 @@
+#include "rsa_support.h"
+
+using namespace amcl;
+
+#define ROUNDUP(a,b) ((a)-1)/(b)+1
+
+/* general purpose hash function w=hash(p|n|x|y) */
+static int hashit(int sha,octet *p,int n,octet *w)
+{
+    int i,c[4],hlen;
+    hash256 sha256;
+    hash512 sha512;
+    char hh[64];
+
+    switch (sha)
+    {
+    case SHA256:
+        HASH256_init(&sha256);
+        break;
+    case SHA384:
+        HASH384_init(&sha512);
+        break;
+    case SHA512:
+        HASH512_init(&sha512);
+        break;
+    }
+
+    hlen=sha;
+
+    if (p!=NULL) for (i=0; i<p->len; i++)
+        {
+            switch(sha)
+            {
+            case SHA256:
+                HASH256_process(&sha256,p->val[i]);
+                break;
+            case SHA384:
+                HASH384_process(&sha512,p->val[i]);
+                break;
+            case SHA512:
+                HASH512_process(&sha512,p->val[i]);
+                break;
+            }
+        }
+    if (n>=0)
+    {
+        c[0]=(n>>24)&0xff;
+        c[1]=(n>>16)&0xff;
+        c[2]=(n>>8)&0xff;
+        c[3]=(n)&0xff;
+        for (i=0; i<4; i++)
+        {
+            switch(sha)
+            {
+            case SHA256:
+                HASH256_process(&sha256,c[i]);
+                break;
+            case SHA384:
+                HASH384_process(&sha512,c[i]);
+                break;
+            case SHA512:
+                HASH512_process(&sha512,c[i]);
+                break;
+            }
+        }
+    }
+
+    switch (sha)
+    {
+    case SHA256:
+        HASH256_hash(&sha256,hh);
+        break;
+    case SHA384:
+        HASH384_hash(&sha512,hh);
+        break;
+    case SHA512:
+        HASH512_hash(&sha512,hh);
+        break;
+    }
+
+    OCT_empty(w);
+    OCT_jbytes(w,hh,hlen);
+    for (i=0; i<hlen; i++) hh[i]=0;
+
+    return hlen;
+}
+
+/* Mask Generation Function */
+
+static void MGF1(int sha,octet *z,int olen,octet *mask)
+{
+    char h[64];
+    octet H= {0,sizeof(h),h};
+    int hlen=sha;
+    int counter,cthreshold;
+
+    OCT_empty(mask);
+
+    cthreshold=ROUNDUP(olen,hlen);
+    for (counter=0; counter<cthreshold; counter++)
+    {
+        hashit(sha,z,counter,&H);
+        if (mask->len+hlen>olen) OCT_jbytes(mask,H.val,olen%hlen);
+        else                     OCT_joctet(mask,&H);
+    }
+    OCT_clear(&H);
+}
+
+/* SHAXXX identifier strings */
+const unsigned char SHA256ID[]= {0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20};
+const unsigned char SHA384ID[]= {0x30,0x41,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00,0x04,0x30};
+const unsigned char SHA512ID[]= {0x30,0x51,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0x04,0x40};
+
+/* PKCS 1.5 padding of a message to be signed */
+
+int amcl::PKCS15(int sha,octet *m,octet *w)
+{
+    int olen=w->max;
+    int hlen=sha;
+    int idlen=19;
+    char h[64];
+    octet H= {0,sizeof(h),h};
+
+    if (olen<idlen+hlen+10) return 0;
+    hashit(sha,m,-1,&H);
+
+    OCT_empty(w);
+    OCT_jbyte(w,0x00,1);
+    OCT_jbyte(w,0x01,1);
+    OCT_jbyte(w,0xff,olen-idlen-hlen-3);
+    OCT_jbyte(w,0x00,1);
+
+    if (hlen==32) OCT_jbytes(w,(char *)SHA256ID,idlen);
+    if (hlen==48) OCT_jbytes(w,(char *)SHA384ID,idlen);
+    if (hlen==64) OCT_jbytes(w,(char *)SHA512ID,idlen);
+
+    OCT_joctet(w,&H);
+
+    return 1;
+}
+
+/* OAEP Message Encoding for Encryption */
+
+int amcl::OAEP_ENCODE(int sha,octet *m,csprng *RNG,octet *p,octet *f)
+{
+    int slen,olen=f->max-1;
+    int mlen=m->len;
+    int hlen,seedlen;
+    char dbmask[MAX_RSA_BYTES],seed[64];
+    octet DBMASK= {0,sizeof(dbmask),dbmask};
+    octet SEED= {0,sizeof(seed),seed};
+
+    hlen=seedlen=sha;
+    if (mlen>olen-hlen-seedlen-1) return 0;
+    if (m==f) return 0;  /* must be distinct octets */
+
+    hashit(sha,p,-1,f);
+
+    slen=olen-mlen-hlen-seedlen-1;
+
+    OCT_jbyte(f,0,slen);
+    OCT_jbyte(f,0x1,1);
+    OCT_joctet(f,m);
+
+    OCT_rand(&SEED,RNG,seedlen);
+
+    MGF1(sha,&SEED,olen-seedlen,&DBMASK);
+
+    OCT_xor(&DBMASK,f);
+    MGF1(sha,&DBMASK,seedlen,f);
+
+    OCT_xor(f,&SEED);
+
+    OCT_joctet(f,&DBMASK);
+
+    OCT_pad(f,f->max);
+    OCT_clear(&SEED);
+    OCT_clear(&DBMASK);
+
+    return 1;
+}
+
+/* OAEP Message Decoding for Decryption */
+
+int amcl::OAEP_DECODE(int sha,octet *p,octet *f)
+{
+    int comp,x,t;
+    int i,k,olen=f->max-1;
+    int hlen,seedlen;
+    char dbmask[MAX_RSA_BYTES],seed[64],chash[64];
+    octet DBMASK= {0,sizeof(dbmask),dbmask};
+    octet SEED= {0,sizeof(seed),seed};
+    octet CHASH= {0,sizeof(chash),chash};
+
+    seedlen=hlen=sha;
+    if (olen<seedlen+hlen+1) return 0;
+    if (!OCT_pad(f,olen+1)) return 0;
+    hashit(sha,p,-1,&CHASH);
+
+    x=f->val[0];
+    for (i=seedlen; i<olen; i++)
+        DBMASK.val[i-seedlen]=f->val[i+1];
+    DBMASK.len=olen-seedlen;
+
+    MGF1(sha,&DBMASK,seedlen,&SEED);
+    for (i=0; i<seedlen; i++) SEED.val[i]^=f->val[i+1];
+    MGF1(sha,&SEED,olen-seedlen,f);
+    OCT_xor(&DBMASK,f);
+
+    comp=OCT_ncomp(&CHASH,&DBMASK,hlen);
+
+    OCT_shl(&DBMASK,hlen);
+
+    OCT_clear(&SEED);
+    OCT_clear(&CHASH);
+
+    for (k=0;; k++)
+    {
+        if (k>=DBMASK.len)
+        {
+            OCT_clear(&DBMASK);
+            return 0;
+        }
+        if (DBMASK.val[k]!=0) break;
+    }
+
+    t=DBMASK.val[k];
+    if (!comp || x!=0 || t!=0x01)
+    {
+        OCT_clear(&DBMASK);
+        return 0;
+    }
+
+    OCT_shl(&DBMASK,k+1);
+    OCT_copy(f,&DBMASK);
+    OCT_clear(&DBMASK);
+
+    return 1;
+}
\ No newline at end of file
diff --git a/version3/cpp/rsa_support.h b/version3/cpp/rsa_support.h
new file mode 100644
index 0000000..3bec69f
--- /dev/null
+++ b/version3/cpp/rsa_support.h
@@ -0,0 +1,49 @@
+#ifndef RSA_SUPPORT_H
+#define RSA_SUPPORT_H
+
+#include "amcl.h"
+
+namespace amcl {
+
+#define MAX_RSA_BYTES 512 // Maximum of 4096
+
+/**	@brief RSA Key Pair Generator
+ *
+	@param R is a pointer to a cryptographically secure random number generator
+	@param e the encryption exponent
+	@param PRIV the output RSA private key
+	@param PUB the output RSA public key
+        @param P Input prime number. Used when R is equal to NULL for testing
+        @param Q Inpuy prime number. Used when R is equal to NULL for testing
+ */
+/**	@brief PKCS V1.5 padding of a message prior to RSA signature
+ *
+	@param h is the hash type
+	@param M is the input message
+	@param W is the output encoding, ready for RSA signature
+	@return 1 if OK, else 0
+ */
+extern int PKCS15(int h,octet *M,octet *W);
+/**	@brief OAEP padding of a message prior to RSA encryption
+ *
+	@param h is the hash type
+	@param M is the input message
+	@param R is a pointer to a cryptographically secure random number generator
+	@param P are input encoding parameter string (could be NULL)
+	@param F is the output encoding, ready for RSA encryption
+	@return 1 if OK, else 0
+ */
+extern int	OAEP_ENCODE(int h,octet *M,csprng *R,octet *P,octet *F);
+/**	@brief OAEP unpadding of a message after RSA decryption
+ *
+	Unpadding is done in-place
+	@param h is the hash type
+	@param P are input encoding parameter string (could be NULL)
+	@param F is input padded message, unpadded on output
+	@return 1 if OK, else 0
+ */
+extern int  OAEP_DECODE(int h,octet *P,octet *F);
+
+}
+
+#endif
\ No newline at end of file
diff --git a/version3/cpp/testall.cpp b/version3/cpp/testall.cpp
new file mode 100644
index 0000000..36e73e2
--- /dev/null
+++ b/version3/cpp/testall.cpp
@@ -0,0 +1,1643 @@
+/*
+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.
+*/
+
+/* test driver and function exerciser for ECDH/ECIES/ECDSA API Functions */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "ecdh_ED25519.h"
+#include "mpin_BN254.h"
+
+#if CHUNK==32 || CHUNK==64
+#include "mpin_BLS383.h"
+#include "mpin192_BLS24.h"
+#include "mpin256_BLS48.h"
+#endif
+
+#include "rsa_RSA2048.h"
+#include "randapi.h"
+
+#if CHUNK==32 || CHUNK==64
+#include "ecdh_NIST256.h"
+#include "ecdh_GOLDILOCKS.h"
+#endif
+
+using namespace amcl;
+
+int ecdh_ED25519(csprng *RNG)
+{
+	using namespace ED25519;
+
+    int i,res;
+    unsigned long ran;
+    char *pp=(char *)"M0ng00se";
+    // These octets are automatically protected against buffer overflow attacks 
+    // Note salt must be big enough to include an appended word 
+    // Note ECIES ciphertext C must be big enough to include at least 1 appended block 
+    // Recall EFS_ED25519 is field size in bytes. So EFS_ED25519=32 for 256-bit curve 
+    char s0[2*EGS_ED25519],s1[EGS_ED25519],w0[2*EFS_ED25519+1],w1[2*EFS_ED25519+1],z0[EFS_ED25519],z1[EFS_ED25519],key[AESKEY_ED25519],salt[40],pw[40];
+    octet S0= {0,sizeof(s0),s0};
+    octet S1= {0,sizeof(s1),s1};
+    octet W0= {0,sizeof(w0),w0};
+    octet W1= {0,sizeof(w1),w1};
+    octet Z0= {0,sizeof(z0),z0};
+    octet Z1= {0,sizeof(z1),z1};
+    octet KEY= {0,sizeof(key),key};
+    octet SALT= {0,sizeof(salt),salt};
+    octet PW= {0,sizeof(pw),pw};
+
+    SALT.len=8;
+    for (i=0; i<8; i++) SALT.val[i]=i+1; // set Salt
+
+    printf("Alice's Passphrase= %s\n",pp);
+
+    OCT_empty(&PW);
+    OCT_jstring(&PW,pp);   // set Password from string
+
+    // private key S0 of size EGS_ED25519 bytes derived from Password and Salt 
+
+    PBKDF2(HASH_TYPE_ED25519,&PW,&SALT,1000,EGS_ED25519,&S0);
+
+    printf("Alices private key= 0x");
+    OCT_output(&S0);
+
+    // Generate Key pair S/W 
+
+    ECP_KEY_PAIR_GENERATE(NULL,&S0,&W0);
+    printf("Alices public key= 0x");
+    OCT_output(&W0);
+
+    res=ECP_PUBLIC_KEY_VALIDATE(&W0);
+    if (res!=0)
+    {
+        printf("ECP Public Key is invalid!\n");
+        return 0;
+    }
+
+    // Random private key for other party 
+    ECP_KEY_PAIR_GENERATE(RNG,&S1,&W1);
+    res=ECP_PUBLIC_KEY_VALIDATE(&W1);
+    if (res!=0)
+    {
+        printf("ECP Public Key is invalid!\n");
+        return 0;
+    }
+    printf("Servers private key= 0x");
+    OCT_output(&S1);
+    printf("Servers public key= 0x");
+    OCT_output(&W1);
+
+    // Calculate common key using DH - IEEE 1363 method 
+
+    ECP_SVDP_DH(&S0,&W1,&Z0);
+    ECP_SVDP_DH(&S1,&W0,&Z1);
+
+    if (!OCT_comp(&Z0,&Z1))
+    {
+        printf("*** ECPSVDP-DH Failed\n");
+        return 0;
+    }
+
+    KDF2(HASH_TYPE_ED25519,&Z0,NULL,AESKEY_ED25519,&KEY);
+
+    printf("Alice's DH Key=  0x");
+    OCT_output(&KEY);
+    printf("Servers DH Key=  0x");
+    OCT_output(&KEY);
+
+#if CURVETYPE_ED25519 != MONTGOMERY
+
+    char ds[EGS_ED25519],p1[30],p2[30],v[2*EFS_ED25519+1],m[32],c[64],t[32],cs[EGS_ED25519];
+    octet DS= {0,sizeof(ds),ds};
+    octet CS= {0,sizeof(cs),cs};
+    octet P1= {0,sizeof(p1),p1};
+    octet P2= {0,sizeof(p2),p2};
+    octet V= {0,sizeof(v),v};
+    octet M= {0,sizeof(m),m};
+    octet C= {0,sizeof(c),c};
+    octet T= {0,sizeof(t),t};
+
+    printf("Testing ECIES\n");
+
+    P1.len=3;
+    P1.val[0]=0x0;
+    P1.val[1]=0x1;
+    P1.val[2]=0x2;
+    P2.len=4;
+    P2.val[0]=0x0;
+    P2.val[1]=0x1;
+    P2.val[2]=0x2;
+    P2.val[3]=0x3;
+
+    M.len=17;
+    for (i=0; i<=16; i++) M.val[i]=i;
+
+    ECP_ECIES_ENCRYPT(HASH_TYPE_ED25519,&P1,&P2,RNG,&W1,&M,12,&V,&C,&T);
+
+    printf("Ciphertext= \n");
+    printf("V= 0x");
+    OCT_output(&V);
+    printf("C= 0x");
+    OCT_output(&C);
+    printf("T= 0x");
+    OCT_output(&T);
+
+    if (!ECP_ECIES_DECRYPT(HASH_TYPE_ED25519,&P1,&P2,&V,&C,&T,&S1,&M))
+    {
+        printf("*** ECIES Decryption Failed\n");
+        return 0;
+    }
+    else printf("Decryption succeeded\n");
+
+    printf("Message is 0x");
+    OCT_output(&M);
+
+
+    printf("Testing ECDSA\n");
+
+    if (ECP_SP_DSA(HASH_TYPE_ED25519,RNG,NULL,&S0,&M,&CS,&DS)!=0)
+    {
+        printf("***ECDSA Signature Failed\n");
+        return 0;
+    }
+
+    printf("Signature C = 0x");
+    OCT_output(&CS);
+    printf("Signature D = 0x");
+    OCT_output(&DS);
+
+    if (ECP_VP_DSA(HASH_TYPE_ED25519,&W0,&M,&CS,&DS)!=0)
+    {
+        printf("***ECDSA Verification Failed\n");
+        return 0;
+    }
+    else 
+    {
+      printf("ECDSA Signature/Verification succeeded\n");
+    }
+
+#endif
+
+    return 0;
+}
+
+#if CHUNK==32 || CHUNK==64
+int ecdh_NIST256(csprng *RNG)
+{
+	using namespace NIST256;
+
+    int i,res;
+    unsigned long ran;
+    char *pp=(char *)"M0ng00se";
+    // These octets are automatically protected against buffer overflow attacks 
+    // Note salt must be big enough to include an appended word 
+    // Note ECIES ciphertext C must be big enough to include at least 1 appended block 
+    // Recall EFS_NIST256 is field size in bytes. So EFS_NIST256=32 for 256-bit curve 
+    char s0[2*EGS_NIST256],s1[EGS_NIST256],w0[2*EFS_NIST256+1],w1[2*EFS_NIST256+1],z0[EFS_NIST256],z1[EFS_NIST256],key[AESKEY_NIST256],salt[40],pw[40];
+    octet S0= {0,sizeof(s0),s0};
+    octet S1= {0,sizeof(s1),s1};
+    octet W0= {0,sizeof(w0),w0};
+    octet W1= {0,sizeof(w1),w1};
+    octet Z0= {0,sizeof(z0),z0};
+    octet Z1= {0,sizeof(z1),z1};
+    octet KEY= {0,sizeof(key),key};
+    octet SALT= {0,sizeof(salt),salt};
+    octet PW= {0,sizeof(pw),pw};
+
+    SALT.len=8;
+    for (i=0; i<8; i++) SALT.val[i]=i+1; // set Salt
+
+    printf("Alice's Passphrase= %s\n",pp);
+
+    OCT_empty(&PW);
+    OCT_jstring(&PW,pp);   // set Password from string
+
+    // private key S0 of size EGS_NIST256 bytes derived from Password and Salt 
+
+    PBKDF2(HASH_TYPE_NIST256,&PW,&SALT,1000,EGS_NIST256,&S0);
+
+    printf("Alices private key= 0x");
+    OCT_output(&S0);
+
+    // Generate Key pair S/W 
+
+    ECP_KEY_PAIR_GENERATE(NULL,&S0,&W0);
+    printf("Alices public key= 0x");
+    OCT_output(&W0);
+
+    res=ECP_PUBLIC_KEY_VALIDATE(&W0);
+    if (res!=0)
+    {
+        printf("ECP Public Key is invalid!\n");
+        return 0;
+    }
+
+    // Random private key for other party 
+    ECP_KEY_PAIR_GENERATE(RNG,&S1,&W1);
+    res=ECP_PUBLIC_KEY_VALIDATE(&W1);
+    if (res!=0)
+    {
+        printf("ECP Public Key is invalid!\n");
+        return 0;
+    }
+    printf("Servers private key= 0x");
+    OCT_output(&S1);
+    printf("Servers public key= 0x");
+    OCT_output(&W1);
+
+    // Calculate common key using DH - IEEE 1363 method 
+
+    ECP_SVDP_DH(&S0,&W1,&Z0);
+    ECP_SVDP_DH(&S1,&W0,&Z1);
+
+    if (!OCT_comp(&Z0,&Z1))
+    {
+        printf("*** ECPSVDP-DH Failed\n");
+        return 0;
+    }
+
+    KDF2(HASH_TYPE_NIST256,&Z0,NULL,AESKEY_NIST256,&KEY);
+
+    printf("Alice's DH Key=  0x");
+    OCT_output(&KEY);
+    printf("Servers DH Key=  0x");
+    OCT_output(&KEY);
+
+#if CURVETYPE_NIST256 != MONTGOMERY
+
+    char ds[EGS_NIST256],p1[30],p2[30],v[2*EFS_NIST256+1],m[32],c[64],t[32],cs[EGS_NIST256];
+    octet DS= {0,sizeof(ds),ds};
+    octet CS= {0,sizeof(cs),cs};
+    octet P1= {0,sizeof(p1),p1};
+    octet P2= {0,sizeof(p2),p2};
+    octet V= {0,sizeof(v),v};
+    octet M= {0,sizeof(m),m};
+    octet C= {0,sizeof(c),c};
+    octet T= {0,sizeof(t),t};
+
+    printf("Testing ECIES\n");
+
+    P1.len=3;
+    P1.val[0]=0x0;
+    P1.val[1]=0x1;
+    P1.val[2]=0x2;
+    P2.len=4;
+    P2.val[0]=0x0;
+    P2.val[1]=0x1;
+    P2.val[2]=0x2;
+    P2.val[3]=0x3;
+
+    M.len=17;
+    for (i=0; i<=16; i++) M.val[i]=i;
+
+    ECP_ECIES_ENCRYPT(HASH_TYPE_NIST256,&P1,&P2,RNG,&W1,&M,12,&V,&C,&T);
+
+    printf("Ciphertext= \n");
+    printf("V= 0x");
+    OCT_output(&V);
+    printf("C= 0x");
+    OCT_output(&C);
+    printf("T= 0x");
+    OCT_output(&T);
+
+    if (!ECP_ECIES_DECRYPT(HASH_TYPE_NIST256,&P1,&P2,&V,&C,&T,&S1,&M))
+    {
+        printf("*** ECIES Decryption Failed\n");
+        return 0;
+    }
+    else printf("Decryption succeeded\n");
+
+    printf("Message is 0x");
+    OCT_output(&M);
+
+
+    printf("Testing ECDSA\n");
+
+    if (ECP_SP_DSA(HASH_TYPE_NIST256,RNG,NULL,&S0,&M,&CS,&DS)!=0)
+    {
+        printf("***ECDSA Signature Failed\n");
+        return 0;
+    }
+
+    printf("Signature C = 0x");
+    OCT_output(&CS);
+    printf("Signature D = 0x");
+    OCT_output(&DS);
+
+    if (ECP_VP_DSA(HASH_TYPE_NIST256,&W0,&M,&CS,&DS)!=0)
+    {
+        printf("***ECDSA Verification Failed\n");
+        return 0;
+    }
+    else 
+    {
+      printf("ECDSA Signature/Verification succeeded\n");
+    }
+
+#endif
+
+    return 0;
+}
+
+int ecdh_GOLDILOCKS(csprng *RNG)
+{
+	using namespace GOLDILOCKS;
+
+    int i,res;
+    unsigned long ran;
+    char *pp=(char *)"M0ng00se";
+    // These octets are automatically protected against buffer overflow attacks 
+    // Note salt must be big enough to include an appended word 
+    // Note ECIES ciphertext C must be big enough to include at least 1 appended block 
+    // Recall EFS_GOLDILOCKS is field size in bytes. So EFS_GOLDILOCKS=32 for 256-bit curve 
+    char s0[2*EGS_GOLDILOCKS],s1[EGS_GOLDILOCKS],w0[2*EFS_GOLDILOCKS+1],w1[2*EFS_GOLDILOCKS+1],z0[EFS_GOLDILOCKS],z1[EFS_GOLDILOCKS],key[AESKEY_GOLDILOCKS],salt[40],pw[40];
+    octet S0= {0,sizeof(s0),s0};
+    octet S1= {0,sizeof(s1),s1};
+    octet W0= {0,sizeof(w0),w0};
+    octet W1= {0,sizeof(w1),w1};
+    octet Z0= {0,sizeof(z0),z0};
+    octet Z1= {0,sizeof(z1),z1};
+    octet KEY= {0,sizeof(key),key};
+    octet SALT= {0,sizeof(salt),salt};
+    octet PW= {0,sizeof(pw),pw};
+
+    SALT.len=8;
+    for (i=0; i<8; i++) SALT.val[i]=i+1; // set Salt
+
+    printf("Alice's Passphrase= %s\n",pp);
+
+    OCT_empty(&PW);
+    OCT_jstring(&PW,pp);   // set Password from string
+
+    // private key S0 of size EGS_GOLDILOCKS bytes derived from Password and Salt 
+
+    PBKDF2(HASH_TYPE_GOLDILOCKS,&PW,&SALT,1000,EGS_GOLDILOCKS,&S0);
+
+    printf("Alices private key= 0x");
+    OCT_output(&S0);
+
+    // Generate Key pair S/W 
+
+    ECP_KEY_PAIR_GENERATE(NULL,&S0,&W0);
+    printf("Alices public key= 0x");
+    OCT_output(&W0);
+
+    res=ECP_PUBLIC_KEY_VALIDATE(&W0);
+    if (res!=0)
+    {
+        printf("ECP Public Key is invalid!\n");
+        return 0;
+    }
+
+    // Random private key for other party 
+    ECP_KEY_PAIR_GENERATE(RNG,&S1,&W1);
+    res=ECP_PUBLIC_KEY_VALIDATE(&W1);
+    if (res!=0)
+    {
+        printf("ECP Public Key is invalid!\n");
+        return 0;
+    }
+    printf("Servers private key= 0x");
+    OCT_output(&S1);
+    printf("Servers public key= 0x");
+    OCT_output(&W1);
+
+    // Calculate common key using DH - IEEE 1363 method 
+
+    ECP_SVDP_DH(&S0,&W1,&Z0);
+    ECP_SVDP_DH(&S1,&W0,&Z1);
+
+    if (!OCT_comp(&Z0,&Z1))
+    {
+        printf("*** ECPSVDP-DH Failed\n");
+        return 0;
+    }
+
+    KDF2(HASH_TYPE_GOLDILOCKS,&Z0,NULL,AESKEY_GOLDILOCKS,&KEY);
+
+    printf("Alice's DH Key=  0x");
+    OCT_output(&KEY);
+    printf("Servers DH Key=  0x");
+    OCT_output(&KEY);
+
+#if CURVETYPE_GOLDILOCKS != MONTGOMERY
+
+    char ds[EGS_GOLDILOCKS],p1[30],p2[30],v[2*EFS_GOLDILOCKS+1],m[32],c[64],t[32],cs[EGS_GOLDILOCKS];
+    octet DS= {0,sizeof(ds),ds};
+    octet CS= {0,sizeof(cs),cs};
+    octet P1= {0,sizeof(p1),p1};
+    octet P2= {0,sizeof(p2),p2};
+    octet V= {0,sizeof(v),v};
+    octet M= {0,sizeof(m),m};
+    octet C= {0,sizeof(c),c};
+    octet T= {0,sizeof(t),t};
+
+    printf("Testing ECIES\n");
+
+    P1.len=3;
+    P1.val[0]=0x0;
+    P1.val[1]=0x1;
+    P1.val[2]=0x2;
+    P2.len=4;
+    P2.val[0]=0x0;
+    P2.val[1]=0x1;
+    P2.val[2]=0x2;
+    P2.val[3]=0x3;
+
+    M.len=17;
+    for (i=0; i<=16; i++) M.val[i]=i;
+
+    ECP_ECIES_ENCRYPT(HASH_TYPE_GOLDILOCKS,&P1,&P2,RNG,&W1,&M,12,&V,&C,&T);
+
+    printf("Ciphertext= \n");
+    printf("V= 0x");
+    OCT_output(&V);
+    printf("C= 0x");
+    OCT_output(&C);
+    printf("T= 0x");
+    OCT_output(&T);
+
+    if (!ECP_ECIES_DECRYPT(HASH_TYPE_GOLDILOCKS,&P1,&P2,&V,&C,&T,&S1,&M))
+    {
+        printf("*** ECIES Decryption Failed\n");
+        return 0;
+    }
+    else printf("Decryption succeeded\n");
+
+    printf("Message is 0x");
+    OCT_output(&M);
+
+
+    printf("Testing ECDSA\n");
+
+    if (ECP_SP_DSA(HASH_TYPE_GOLDILOCKS,RNG,NULL,&S0,&M,&CS,&DS)!=0)
+    {
+        printf("***ECDSA Signature Failed\n");
+        return 0;
+    }
+
+    printf("Signature C = 0x");
+    OCT_output(&CS);
+    printf("Signature D = 0x");
+    OCT_output(&DS);
+
+    if (ECP_VP_DSA(HASH_TYPE_GOLDILOCKS,&W0,&M,&CS,&DS)!=0)
+    {
+        printf("***ECDSA Verification Failed\n");
+        return 0;
+    }
+    else 
+    {
+      printf("ECDSA Signature/Verification succeeded\n");
+    }
+
+#endif
+
+    return 0;
+}
+#endif
+
+#define PERMITS  // for time permits ON or OFF 
+#define PINERROR // For PIN ERROR detection ON or OFF 
+#define FULL     // for M-Pin Full or M-Pin regular 
+
+int mpin_BN254(csprng *RNG)
+{
+
+	using namespace BN254;
+
+    int i,pin,rtn,err;
+#ifdef PERMITS
+    int date=today();
+#else
+    int date=0;
+#endif
+    unsigned long ran;
+    char x[PGS_BN254],s[PGS_BN254],y[PGS_BN254],client_id[100],sst[4*PFS_BN254],token[2*PFS_BN254+1],sec[2*PFS_BN254+1],permit[2*PFS_BN254+1],xcid[2*PFS_BN254+1],xid[2*PFS_BN254+1],e[12*PFS_BN254],f[12*PFS_BN254];
+    char hcid[PFS_BN254],hsid[PFS_BN254],hid[2*PFS_BN254+1],htid[2*PFS_BN254+1],h[PGS_BN254];
+#ifdef FULL
+    char r[PGS_BN254],z[2*PFS_BN254+1],w[PGS_BN254],t[2*PFS_BN254+1];
+    char g1[12*PFS_BN254],g2[12*PFS_BN254];
+    char ck[AESKEY_BN254],sk[AESKEY_BN254];
+#endif
+    octet S= {0,sizeof(s),s};
+    octet X= {0,sizeof(x),x};
+    octet Y= {0,sizeof(y),y};
+    octet H= {0,sizeof(h),h};
+    octet CLIENT_ID= {0,sizeof(client_id),client_id};
+    octet SST= {0,sizeof(sst),sst};
+    octet TOKEN= {0,sizeof(token),token};
+    octet SEC= {0,sizeof(sec),sec};
+    octet PERMIT= {0,sizeof(permit),permit};
+    octet xCID= {0,sizeof(xcid),xcid};
+    octet xID= {0,sizeof(xid),xid};
+    octet HCID= {0,sizeof(hcid),hcid};
+    octet HSID= {0,sizeof(hsid),hsid};
+    octet HID= {0,sizeof(hid),hid};
+    octet HTID= {0,sizeof(htid),htid};
+    octet E= {0,sizeof(e),e};
+    octet F= {0,sizeof(f),f};
+#ifdef FULL
+    octet R= {0,sizeof(r),r};
+    octet Z= {0,sizeof(z),z};
+    octet W= {0,sizeof(w),w};
+    octet T= {0,sizeof(t),t};
+    octet G1= {0,sizeof(g1),g1};
+    octet G2= {0,sizeof(g2),g2};
+    octet SK= {0,sizeof(sk),sk};
+    octet CK= {0,sizeof(ck),ck};
+#endif
+    octet *pxID,*pxCID,*pHID,*pHTID,*pE,*pF,*pPERMIT,*prHID;
+    char idhex[100];
+
+    // Trusted Authority set-up 
+    MPIN_RANDOM_GENERATE(RNG,&S);
+    printf("Master Secret= ");
+    OCT_output(&S);
+
+    // Create Client Identity 
+    OCT_jstring(&CLIENT_ID,(char *)"testUser@miracl.com");
+    HASH_ID(HASH_TYPE_BN254,&CLIENT_ID,&HCID);  // Either Client or TA calculates Hash(ID) - you decide! 
+
+    printf("Client ID Hash= ");
+    OCT_output(&HCID);
+    printf("\n");
+
+    OCT_toHex(&CLIENT_ID,idhex);
+    printf("Client ID= %s\n",idhex);// OCT_toHex(&CLIENT_ID); printf("\n");
+
+    MPIN_GET_CLIENT_SECRET(&S,&HCID,&TOKEN);
+    printf("Client Secret= ");
+    OCT_output(&TOKEN);
+
+
+// Client and Server are issued secrets by DTA 
+    MPIN_GET_SERVER_SECRET(&S,&SST);
+    printf("Server Secret= ");
+    OCT_output(&SST);
+
+    // Client extracts PIN from secret to create Token 
+    pin=1234;
+    printf("Client extracts PIN= %d\n",pin);
+    MPIN_EXTRACT_PIN(HASH_TYPE_BN254,&CLIENT_ID,pin,&TOKEN);
+    printf("Client Token= ");
+    OCT_output(&TOKEN);
+
+#ifdef FULL
+    MPIN_PRECOMPUTE(&TOKEN,&HCID,NULL,&G1,&G2);
+#endif
+
+#ifdef PERMITS
+    // Client gets "Time Permit" from DTA 
+    printf("Client gets Time Permit\n");
+
+    MPIN_GET_CLIENT_PERMIT(HASH_TYPE_BN254,date,&S,&HCID,&PERMIT);
+    printf("Time Permit= ");
+    OCT_output(&PERMIT);
+
+    // This encoding makes Time permit look random 
+    if (MPIN_ENCODING(RNG,&PERMIT)!=0) printf("Encoding error\n");
+    // printf("Encoded Time Permit= "); OCT_output(&PERMIT); 
+    if (MPIN_DECODING(&PERMIT)!=0) printf("Decoding error\n");
+    // printf("Decoded Time Permit= "); OCT_output(&PERMIT); 
+#endif
+
+    // MPin Protocol 
+
+    // Client enters PIN 
+    printf("\nPIN= ");
+    if(scanf("%d",&pin)) {};
+    // to avoid silly compile error 
+    getchar();
+
+    // 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
+
+   // HSID - hashed client ID as calculated by the server
+   // HCID - hashed client ID as calculated by the client
+
+   // 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.
+
+    
+
+    pxID=&xID;
+    pxCID=&xCID;
+    pHID=&HID;
+    pHTID=&HTID;
+    pE=&E;
+    pF=&F;
+    pPERMIT=&PERMIT;
+
+#ifdef PERMITS
+    prHID=pHTID;
+#ifndef PINERROR
+    pxID=NULL;
+//   pHID=NULL;  //new
+#endif
+#else
+    prHID=pHID;
+    pPERMIT=NULL;
+    pxCID=NULL;
+    pHTID=NULL;
+#endif
+#ifndef PINERROR
+    pE=NULL;
+    pF=NULL;
+#endif
+
+    // When set only send hashed IDs to server 
+    octet *pID;
+#ifdef USE_ANONYMOUS
+    pID = &HCID;
+#else
+    pID = &CLIENT_ID;
+#endif
+
+#ifdef SINGLE_PASS
+    int timeValue;
+    printf("MPIN Single Pass\n");
+    timeValue = MPIN_GET_TIME();
+
+    rtn=MPIN_CLIENT(HASH_TYPE_BN254,date,&CLIENT_ID,RNG,&X,pin,&TOKEN,&SEC,pxID,pxCID,pPERMIT,NULL,timeValue,&Y);
+
+    if (rtn != 0)
+    {
+        printf("MPIN_CLIENT ERROR %d\n", rtn);
+        return 1;
+    }
+
+#ifdef FULL
+    MPIN_GET_G1_MULTIPLE(RNG,1,&R,&HCID,&Z);  // Also Send Z=r.ID to Server, remember random r 
+#endif
+
+
+    rtn=MPIN_SERVER(HASH_TYPE_BN254,date,pHID,pHTID,&Y,&SST,pxID,pxCID,&SEC,pE,pF,pID,NULL,timeValue,NULL);
+
+#ifdef FULL
+    HASH_ID(HASH_TYPE_BN254,&CLIENT_ID,&HSID);  // new
+    MPIN_GET_G1_MULTIPLE(RNG,0,&W,prHID,&T);  // Also send T=w.ID to client, remember random w  
+#endif
+
+#else // SINGLE_PASS
+    printf("MPIN Multi Pass\n");
+    if (MPIN_CLIENT_1(HASH_TYPE_BN254,date,&CLIENT_ID,RNG,&X,pin,&TOKEN,&SEC,pxID,pxCID,pPERMIT)!=0)
+    {
+        printf("Error from Client side - First Pass\n");
+        return 0;
+    }
+
+    // Send U=x.ID to server, and recreate secret from token and pin 
+
+#ifdef FULL
+    HASH_ID(HASH_TYPE_BN254,&CLIENT_ID,&HCID);
+    MPIN_GET_G1_MULTIPLE(RNG,1,&R,&HCID,&Z);  // Also Send Z=r.ID to Server, remember random r, DH component 
+#endif
+
+    // Server calculates H(ID) and H(ID)+H(T|H(ID)) (if time permits enabled), and maps them to points on the curve HID and HTID resp. 
+    MPIN_SERVER_1(HASH_TYPE_BN254,date,pID,pHID,pHTID);
+
+    // Server generates Random number Y and sends it to Client 
+    MPIN_RANDOM_GENERATE(RNG,&Y);
+
+#ifdef FULL
+    HASH_ID(HASH_TYPE_BN254,&CLIENT_ID,&HSID); //new
+    MPIN_GET_G1_MULTIPLE(RNG,0,&W,prHID,&T);  // Also send T=w.ID to client, remember random w, DH component  
+#endif
+
+    // Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC 
+    if (MPIN_CLIENT_2(&X,&Y,&SEC)!=0)
+    {
+        printf("Error from Client side - Second Pass\n");
+        return 1;
+    }
+
+    // Server Second phase. 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=MPIN_SERVER_2(date,pHID,pHTID,&Y,&SST,pxID,pxCID,&SEC,pE,pF,NULL);
+#endif // SINGLE_PASS
+
+    if (rtn!=0)
+    {
+        printf("Server says - Bad Pin.\n");
+#ifdef PINERROR
+
+        err=MPIN_KANGAROO(&E,&F);
+        if (err) printf("(Client PIN is out by %d)\n",err);
+
+#endif
+        return 1;
+    }
+    else
+    {
+        printf("Server says - PIN is good! You really are ");
+        OCT_output_string(&CLIENT_ID);
+        printf(".\n");
+    }
+
+#ifdef FULL
+
+    HASH_ALL(HASH_TYPE_BN254,&HCID,pxID,pxCID,&SEC,&Y,&Z,&T,&H);  // new
+    MPIN_CLIENT_KEY(HASH_TYPE_BN254,&G1,&G2,pin,&R,&X,&H,&T,&CK);      // new H
+    printf("Client Key = ");
+    OCT_output(&CK);
+
+    HASH_ALL(HASH_TYPE_BN254,&HSID,pxID,pxCID,&SEC,&Y,&Z,&T,&H);
+    MPIN_SERVER_KEY(HASH_TYPE_BN254,&Z,&SST,&W,&H,pHID,pxID,pxCID,&SK); // new H,pHID
+    printf("Server Key = ");
+    OCT_output(&SK);
+#endif
+    return 0;
+}
+
+#if CHUNK==32 || CHUNK==64
+
+int mpin_BLS383(csprng *RNG)
+{
+
+	using namespace BLS383;
+
+    int i,pin,rtn,err;
+#ifdef PERMITS
+    int date=today();
+#else
+    int date=0;
+#endif
+    unsigned long ran;
+    char x[PGS_BLS383],s[PGS_BLS383],y[PGS_BLS383],client_id[100],sst[4*PFS_BLS383],token[2*PFS_BLS383+1],sec[2*PFS_BLS383+1],permit[2*PFS_BLS383+1],xcid[2*PFS_BLS383+1],xid[2*PFS_BLS383+1],e[12*PFS_BLS383],f[12*PFS_BLS383];
+    char hcid[PFS_BLS383],hsid[PFS_BLS383],hid[2*PFS_BLS383+1],htid[2*PFS_BLS383+1],h[PGS_BLS383];
+#ifdef FULL
+    char r[PGS_BLS383],z[2*PFS_BLS383+1],w[PGS_BLS383],t[2*PFS_BLS383+1];
+    char g1[12*PFS_BLS383],g2[12*PFS_BLS383];
+    char ck[AESKEY_BLS383],sk[AESKEY_BLS383];
+#endif
+    octet S= {0,sizeof(s),s};
+    octet X= {0,sizeof(x),x};
+    octet Y= {0,sizeof(y),y};
+    octet H= {0,sizeof(h),h};
+    octet CLIENT_ID= {0,sizeof(client_id),client_id};
+    octet SST= {0,sizeof(sst),sst};
+    octet TOKEN= {0,sizeof(token),token};
+    octet SEC= {0,sizeof(sec),sec};
+    octet PERMIT= {0,sizeof(permit),permit};
+    octet xCID= {0,sizeof(xcid),xcid};
+    octet xID= {0,sizeof(xid),xid};
+    octet HCID= {0,sizeof(hcid),hcid};
+    octet HSID= {0,sizeof(hsid),hsid};
+    octet HID= {0,sizeof(hid),hid};
+    octet HTID= {0,sizeof(htid),htid};
+    octet E= {0,sizeof(e),e};
+    octet F= {0,sizeof(f),f};
+#ifdef FULL
+    octet R= {0,sizeof(r),r};
+    octet Z= {0,sizeof(z),z};
+    octet W= {0,sizeof(w),w};
+    octet T= {0,sizeof(t),t};
+    octet G1= {0,sizeof(g1),g1};
+    octet G2= {0,sizeof(g2),g2};
+    octet SK= {0,sizeof(sk),sk};
+    octet CK= {0,sizeof(ck),ck};
+#endif
+    octet *pxID,*pxCID,*pHID,*pHTID,*pE,*pF,*pPERMIT,*prHID;
+    char idhex[100];
+
+    // Trusted Authority set-up 
+    MPIN_RANDOM_GENERATE(RNG,&S);
+    printf("Master Secret= ");
+    OCT_output(&S);
+
+    // Create Client Identity 
+    OCT_jstring(&CLIENT_ID,(char *)"testUser@miracl.com");
+    HASH_ID(HASH_TYPE_BLS383,&CLIENT_ID,&HCID);  // Either Client or TA calculates Hash(ID) - you decide! 
+
+    printf("Client ID Hash= ");
+    OCT_output(&HCID);
+    printf("\n");
+
+    OCT_toHex(&CLIENT_ID,idhex);
+    printf("Client ID= %s\n",idhex);// OCT_toHex(&CLIENT_ID); printf("\n");
+
+    MPIN_GET_CLIENT_SECRET(&S,&HCID,&TOKEN);
+    printf("Client Secret= ");
+    OCT_output(&TOKEN);
+
+// Client and Server are issued secrets by DTA 
+    MPIN_GET_SERVER_SECRET(&S,&SST);
+    printf("Server Secret= ");
+    OCT_output(&SST);
+
+
+
+    // Client extracts PIN from secret to create Token 
+    pin=1234;
+    printf("Client extracts PIN= %d\n",pin);
+    MPIN_EXTRACT_PIN(HASH_TYPE_BLS383,&CLIENT_ID,pin,&TOKEN);
+    printf("Client Token= ");
+    OCT_output(&TOKEN);
+
+#ifdef FULL
+    MPIN_PRECOMPUTE(&TOKEN,&HCID,NULL,&G1,&G2);
+#endif
+
+#ifdef PERMITS
+    // Client gets "Time Permit" from DTA 
+    printf("Client gets Time Permit\n");
+
+    MPIN_GET_CLIENT_PERMIT(HASH_TYPE_BLS383,date,&S,&HCID,&PERMIT);
+    printf("Time Permit= ");
+    OCT_output(&PERMIT);
+
+    // This encoding makes Time permit look random 
+    if (MPIN_ENCODING(RNG,&PERMIT)!=0) printf("Encoding error\n");
+    // printf("Encoded Time Permit= "); OCT_output(&PERMIT); 
+    if (MPIN_DECODING(&PERMIT)!=0) printf("Decoding error\n");
+    // printf("Decoded Time Permit= "); OCT_output(&PERMIT); 
+#endif
+
+    // MPin Protocol 
+
+    // Client enters PIN 
+    printf("\nPIN= ");
+    if(scanf("%d",&pin)) {};
+    // to avoid silly compile error 
+    getchar();
+
+    // 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
+
+   // HSID - hashed client ID as calculated by the server
+   // HCID - hashed client ID as calculated by the client
+
+   // 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.
+
+    
+
+    pxID=&xID;
+    pxCID=&xCID;
+    pHID=&HID;
+    pHTID=&HTID;
+    pE=&E;
+    pF=&F;
+    pPERMIT=&PERMIT;
+
+#ifdef PERMITS
+    prHID=pHTID;
+#ifndef PINERROR
+    pxID=NULL;
+//   pHID=NULL;  //new
+#endif
+#else
+    prHID=pHID;
+    pPERMIT=NULL;
+    pxCID=NULL;
+    pHTID=NULL;
+#endif
+#ifndef PINERROR
+    pE=NULL;
+    pF=NULL;
+#endif
+
+    // When set only send hashed IDs to server 
+    octet *pID;
+#ifdef USE_ANONYMOUS
+    pID = &HCID;
+#else
+    pID = &CLIENT_ID;
+#endif
+
+#ifdef SINGLE_PASS
+    int timeValue;
+    printf("MPIN Single Pass\n");
+    timeValue = MPIN_GET_TIME();
+
+    rtn=MPIN_CLIENT(HASH_TYPE_BLS383,date,&CLIENT_ID,RNG,&X,pin,&TOKEN,&SEC,pxID,pxCID,pPERMIT,NULL,timeValue,&Y);
+
+    if (rtn != 0)
+    {
+        printf("MPIN_CLIENT ERROR %d\n", rtn);
+        return 1;
+    }
+
+#ifdef FULL
+    MPIN_GET_G1_MULTIPLE(RNG,1,&R,&HCID,&Z);  // Also Send Z=r.ID to Server, remember random r 
+#endif
+
+
+    rtn=MPIN_SERVER(HASH_TYPE_BLS383,date,pHID,pHTID,&Y,&SST,pxID,pxCID,&SEC,pE,pF,pID,NULL,timeValue,NULL);
+
+#ifdef FULL
+    HASH_ID(HASH_TYPE_BLS383,&CLIENT_ID,&HSID);  // new
+    MPIN_GET_G1_MULTIPLE(RNG,0,&W,prHID,&T);  // Also send T=w.ID to client, remember random w  
+#endif
+
+#else // SINGLE_PASS
+    printf("MPIN Multi Pass\n");
+    if (MPIN_CLIENT_1(HASH_TYPE_BLS383,date,&CLIENT_ID,RNG,&X,pin,&TOKEN,&SEC,pxID,pxCID,pPERMIT)!=0)
+    {
+        printf("Error from Client side - First Pass\n");
+        return 0;
+    }
+
+    // Send U=x.ID to server, and recreate secret from token and pin 
+
+#ifdef FULL
+    HASH_ID(HASH_TYPE_BLS383,&CLIENT_ID,&HCID);
+    MPIN_GET_G1_MULTIPLE(RNG,1,&R,&HCID,&Z);  // Also Send Z=r.ID to Server, remember random r, DH component 
+#endif
+
+    // Server calculates H(ID) and H(ID)+H(T|H(ID)) (if time permits enabled), and maps them to points on the curve HID and HTID resp. 
+    MPIN_SERVER_1(HASH_TYPE_BLS383,date,pID,pHID,pHTID);
+
+    // Server generates Random number Y and sends it to Client 
+    MPIN_RANDOM_GENERATE(RNG,&Y);
+
+#ifdef FULL
+    HASH_ID(HASH_TYPE_BLS383,&CLIENT_ID,&HSID); //new
+    MPIN_GET_G1_MULTIPLE(RNG,0,&W,prHID,&T);  // Also send T=w.ID to client, remember random w, DH component  
+#endif
+
+    // Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC 
+    if (MPIN_CLIENT_2(&X,&Y,&SEC)!=0)
+    {
+        printf("Error from Client side - Second Pass\n");
+        return 1;
+    }
+
+    // Server Second phase. 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=MPIN_SERVER_2(date,pHID,pHTID,&Y,&SST,pxID,pxCID,&SEC,pE,pF,NULL);
+#endif // SINGLE_PASS
+
+    if (rtn!=0)
+    {
+        printf("Server says - Bad Pin.\n");
+#ifdef PINERROR
+
+        err=MPIN_KANGAROO(&E,&F);
+        if (err) printf("(Client PIN is out by %d)\n",err);
+
+#endif
+        return 1;
+    }
+    else
+    {
+        printf("Server says - PIN is good! You really are ");
+        OCT_output_string(&CLIENT_ID);
+        printf(".\n");
+    }
+
+#ifdef FULL
+
+    HASH_ALL(HASH_TYPE_BLS383,&HCID,pxID,pxCID,&SEC,&Y,&Z,&T,&H);  // new
+    MPIN_CLIENT_KEY(HASH_TYPE_BLS383,&G1,&G2,pin,&R,&X,&H,&T,&CK);      // new H
+    printf("Client Key = ");
+    OCT_output(&CK);
+
+    HASH_ALL(HASH_TYPE_BLS383,&HSID,pxID,pxCID,&SEC,&Y,&Z,&T,&H);
+    MPIN_SERVER_KEY(HASH_TYPE_BLS383,&Z,&SST,&W,&H,pHID,pxID,pxCID,&SK); // new H,pHID
+    printf("Server Key = ");
+    OCT_output(&SK);
+#endif
+    return 0;
+}
+
+int mpin192_BLS24(csprng *RNG)
+{
+
+	using namespace BLS24;
+
+    int i,pin,rtn,err;
+#ifdef PERMITS
+    int date=today();
+#else
+    int date=0;
+#endif
+    unsigned long ran;
+    char x[PGS_BLS24],s[PGS_BLS24],y[PGS_BLS24],client_id[100],sst[8*PFS_BLS24],token[2*PFS_BLS24+1],sec[2*PFS_BLS24+1],permit[2*PFS_BLS24+1],xcid[2*PFS_BLS24+1],xid[2*PFS_BLS24+1],e[24*PFS_BLS24],f[24*PFS_BLS24];
+    char hcid[PFS_BLS24],hsid[PFS_BLS24],hid[2*PFS_BLS24+1],htid[2*PFS_BLS24+1],h[PGS_BLS24];
+#ifdef FULL
+    char r[PGS_BLS24],z[2*PFS_BLS24+1],w[PGS_BLS24],t[2*PFS_BLS24+1];
+    char g1[24*PFS_BLS24],g2[24*PFS_BLS24];
+    char ck[AESKEY_BLS24],sk[AESKEY_BLS24];
+#endif
+    octet S= {0,sizeof(s),s};
+    octet X= {0,sizeof(x),x};
+    octet Y= {0,sizeof(y),y};
+    octet H= {0,sizeof(h),h};
+    octet CLIENT_ID= {0,sizeof(client_id),client_id};
+    octet SST= {0,sizeof(sst),sst};
+    octet TOKEN= {0,sizeof(token),token};
+    octet SEC= {0,sizeof(sec),sec};
+    octet PERMIT= {0,sizeof(permit),permit};
+    octet xCID= {0,sizeof(xcid),xcid};
+    octet xID= {0,sizeof(xid),xid};
+    octet HCID= {0,sizeof(hcid),hcid};
+    octet HSID= {0,sizeof(hsid),hsid};
+    octet HID= {0,sizeof(hid),hid};
+    octet HTID= {0,sizeof(htid),htid};
+    octet E= {0,sizeof(e),e};
+    octet F= {0,sizeof(f),f};
+#ifdef FULL
+    octet R= {0,sizeof(r),r};
+    octet Z= {0,sizeof(z),z};
+    octet W= {0,sizeof(w),w};
+    octet T= {0,sizeof(t),t};
+    octet G1= {0,sizeof(g1),g1};
+    octet G2= {0,sizeof(g2),g2};
+    octet SK= {0,sizeof(sk),sk};
+    octet CK= {0,sizeof(ck),ck};
+#endif
+    octet *pxID,*pxCID,*pHID,*pHTID,*pE,*pF,*pPERMIT,*prHID;
+    char idhex[100];
+
+    // Trusted Authority set-up 
+    MPIN_RANDOM_GENERATE(RNG,&S);
+    printf("Master Secret= ");
+    OCT_output(&S);
+
+    // Create Client Identity 
+    OCT_jstring(&CLIENT_ID,(char *)"testUser@miracl.com");
+    HASH_ID(HASH_TYPE_BLS24,&CLIENT_ID,&HCID);  // Either Client or TA calculates Hash(ID) - you decide! 
+
+    printf("Client ID Hash= ");
+    OCT_output(&HCID);
+    printf("\n");
+
+    OCT_toHex(&CLIENT_ID,idhex);
+    printf("Client ID= %s\n",idhex);// OCT_toHex(&CLIENT_ID); printf("\n");
+
+    MPIN_GET_CLIENT_SECRET(&S,&HCID,&TOKEN);
+    printf("Client Secret= ");
+    OCT_output(&TOKEN);
+
+// Client and Server are issued secrets by DTA 
+    MPIN_GET_SERVER_SECRET(&S,&SST);
+    printf("Server Secret= ");
+    OCT_output(&SST);
+
+    // Client extracts PIN from secret to create Token 
+    pin=1234;
+    printf("Client extracts PIN= %d\n",pin);
+    MPIN_EXTRACT_PIN(HASH_TYPE_BLS24,&CLIENT_ID,pin,&TOKEN);
+    printf("Client Token= ");
+    OCT_output(&TOKEN);
+
+#ifdef FULL
+    MPIN_PRECOMPUTE(&TOKEN,&HCID,NULL,&G1,&G2);
+#endif
+
+#ifdef PERMITS
+    // Client gets "Time Permit" from DTA 
+    printf("Client gets Time Permit\n");
+
+    MPIN_GET_CLIENT_PERMIT(HASH_TYPE_BLS24,date,&S,&HCID,&PERMIT);
+    printf("Time Permit= ");
+    OCT_output(&PERMIT);
+
+    // This encoding makes Time permit look random 
+    if (MPIN_ENCODING(RNG,&PERMIT)!=0) printf("Encoding error\n");
+    // printf("Encoded Time Permit= "); OCT_output(&PERMIT); 
+    if (MPIN_DECODING(&PERMIT)!=0) printf("Decoding error\n");
+    // printf("Decoded Time Permit= "); OCT_output(&PERMIT); 
+#endif
+
+    // MPin Protocol 
+
+    // Client enters PIN 
+    printf("\nPIN= ");
+    if(scanf("%d",&pin)) {};
+    // to avoid silly compile error 
+    getchar();
+
+    // 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
+
+   // HSID - hashed client ID as calculated by the server
+   // HCID - hashed client ID as calculated by the client
+
+   // 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.
+
+    
+
+    pxID=&xID;
+    pxCID=&xCID;
+    pHID=&HID;
+    pHTID=&HTID;
+    pE=&E;
+    pF=&F;
+    pPERMIT=&PERMIT;
+
+#ifdef PERMITS
+    prHID=pHTID;
+#ifndef PINERROR
+    pxID=NULL;
+//   pHID=NULL;  //new
+#endif
+#else
+    prHID=pHID;
+    pPERMIT=NULL;
+    pxCID=NULL;
+    pHTID=NULL;
+#endif
+#ifndef PINERROR
+    pE=NULL;
+    pF=NULL;
+#endif
+
+    // When set only send hashed IDs to server 
+    octet *pID;
+#ifdef USE_ANONYMOUS
+    pID = &HCID;
+#else
+    pID = &CLIENT_ID;
+#endif
+
+#ifdef SINGLE_PASS
+    int timeValue;
+    printf("MPIN Single Pass\n");
+    timeValue = MPIN_GET_TIME();
+
+    rtn=MPIN_CLIENT(HASH_TYPE_BLS24,date,&CLIENT_ID,RNG,&X,pin,&TOKEN,&SEC,pxID,pxCID,pPERMIT,NULL,timeValue,&Y);
+
+    if (rtn != 0)
+    {
+        printf("MPIN_CLIENT ERROR %d\n", rtn);
+        return 1;
+    }
+
+#ifdef FULL
+    MPIN_GET_G1_MULTIPLE(RNG,1,&R,&HCID,&Z);  // Also Send Z=r.ID to Server, remember random r 
+#endif
+
+
+    rtn=MPIN_SERVER(HASH_TYPE_BLS24,date,pHID,pHTID,&Y,&SST,pxID,pxCID,&SEC,pE,pF,pID,NULL,timeValue,NULL);
+
+#ifdef FULL
+    HASH_ID(HASH_TYPE_BLS24,&CLIENT_ID,&HSID);  // new
+    MPIN_GET_G1_MULTIPLE(RNG,0,&W,prHID,&T);  // Also send T=w.ID to client, remember random w  
+#endif
+
+#else // SINGLE_PASS
+    printf("MPIN Multi Pass\n");
+    if (MPIN_CLIENT_1(HASH_TYPE_BLS24,date,&CLIENT_ID,RNG,&X,pin,&TOKEN,&SEC,pxID,pxCID,pPERMIT)!=0)
+    {
+        printf("Error from Client side - First Pass\n");
+        return 0;
+    }
+
+    // Send U=x.ID to server, and recreate secret from token and pin 
+
+#ifdef FULL
+    HASH_ID(HASH_TYPE_BLS24,&CLIENT_ID,&HCID);
+    MPIN_GET_G1_MULTIPLE(RNG,1,&R,&HCID,&Z);  // Also Send Z=r.ID to Server, remember random r, DH component 
+#endif
+
+    // Server calculates H(ID) and H(ID)+H(T|H(ID)) (if time permits enabled), and maps them to points on the curve HID and HTID resp. 
+    MPIN_SERVER_1(HASH_TYPE_BLS24,date,pID,pHID,pHTID);
+
+    // Server generates Random number Y and sends it to Client 
+    MPIN_RANDOM_GENERATE(RNG,&Y);
+
+#ifdef FULL
+    HASH_ID(HASH_TYPE_BLS24,&CLIENT_ID,&HSID); //new
+    MPIN_GET_G1_MULTIPLE(RNG,0,&W,prHID,&T);  // Also send T=w.ID to client, remember random w, DH component  
+#endif
+
+    // Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC 
+    if (MPIN_CLIENT_2(&X,&Y,&SEC)!=0)
+    {
+        printf("Error from Client side - Second Pass\n");
+        return 1;
+    }
+
+    // Server Second phase. 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=MPIN_SERVER_2(date,pHID,pHTID,&Y,&SST,pxID,pxCID,&SEC,pE,pF,NULL);
+#endif // SINGLE_PASS
+
+    if (rtn!=0)
+    {
+        printf("Server says - Bad Pin.\n");
+#ifdef PINERROR
+
+        err=MPIN_KANGAROO(&E,&F);
+        if (err) printf("(Client PIN is out by %d)\n",err);
+
+#endif
+        return 1;
+    }
+    else
+    {
+        printf("Server says - PIN is good! You really are ");
+        OCT_output_string(&CLIENT_ID);
+        printf(".\n");
+    }
+
+#ifdef FULL
+
+    HASH_ALL(HASH_TYPE_BLS24,&HCID,pxID,pxCID,&SEC,&Y,&Z,&T,&H);  // new
+    i=MPIN_CLIENT_KEY(HASH_TYPE_BLS24,&G1,&G2,pin,&R,&X,&H,&T,&CK);      // new H
+    printf("Client Key = ");
+    OCT_output(&CK);
+
+    HASH_ALL(HASH_TYPE_BLS24,&HSID,pxID,pxCID,&SEC,&Y,&Z,&T,&H);
+    i=MPIN_SERVER_KEY(HASH_TYPE_BLS24,&Z,&SST,&W,&H,pHID,pxID,pxCID,&SK); // new H,pHID
+    printf("Server Key = ");
+    OCT_output(&SK);
+#endif
+    return 0;
+}
+
+int mpin256_BLS48(csprng *RNG)
+{
+
+	using namespace BLS48;
+
+    int i,pin,rtn,err;
+#ifdef PERMITS
+    int date=today();
+#else
+    int date=0;
+#endif
+    unsigned long ran;
+    char x[PGS_BLS48],s[PGS_BLS48],y[PGS_BLS48],client_id[100],sst[16*PFS_BLS48],token[2*PFS_BLS48+1],sec[2*PFS_BLS48+1],permit[2*PFS_BLS48+1],xcid[2*PFS_BLS48+1],xid[2*PFS_BLS48+1],e[48*PFS_BLS48],f[48*PFS_BLS48];
+    char hcid[PFS_BLS48],hsid[PFS_BLS48],hid[2*PFS_BLS48+1],htid[2*PFS_BLS48+1],h[PGS_BLS48];
+#ifdef FULL
+    char r[PGS_BLS48],z[2*PFS_BLS48+1],w[PGS_BLS48],t[2*PFS_BLS48+1];
+    char g1[48*PFS_BLS48],g2[48*PFS_BLS48];
+    char ck[AESKEY_BLS48],sk[AESKEY_BLS48];
+#endif
+    octet S= {0,sizeof(s),s};
+    octet X= {0,sizeof(x),x};
+    octet Y= {0,sizeof(y),y};
+    octet H= {0,sizeof(h),h};
+    octet CLIENT_ID= {0,sizeof(client_id),client_id};
+    octet SST= {0,sizeof(sst),sst};
+    octet TOKEN= {0,sizeof(token),token};
+    octet SEC= {0,sizeof(sec),sec};
+    octet PERMIT= {0,sizeof(permit),permit};
+    octet xCID= {0,sizeof(xcid),xcid};
+    octet xID= {0,sizeof(xid),xid};
+    octet HCID= {0,sizeof(hcid),hcid};
+    octet HSID= {0,sizeof(hsid),hsid};
+    octet HID= {0,sizeof(hid),hid};
+    octet HTID= {0,sizeof(htid),htid};
+    octet E= {0,sizeof(e),e};
+    octet F= {0,sizeof(f),f};
+#ifdef FULL
+    octet R= {0,sizeof(r),r};
+    octet Z= {0,sizeof(z),z};
+    octet W= {0,sizeof(w),w};
+    octet T= {0,sizeof(t),t};
+    octet G1= {0,sizeof(g1),g1};
+    octet G2= {0,sizeof(g2),g2};
+    octet SK= {0,sizeof(sk),sk};
+    octet CK= {0,sizeof(ck),ck};
+#endif
+    octet *pxID,*pxCID,*pHID,*pHTID,*pE,*pF,*pPERMIT,*prHID;
+    char idhex[100];
+
+    // Trusted Authority set-up 
+    MPIN_RANDOM_GENERATE(RNG,&S);
+    printf("Master Secret= ");
+    OCT_output(&S);
+
+    // Create Client Identity 
+    OCT_jstring(&CLIENT_ID,(char *)"testUser@miracl.com");
+    HASH_ID(HASH_TYPE_BLS48,&CLIENT_ID,&HCID);  // Either Client or TA calculates Hash(ID) - you decide! 
+
+    printf("Client ID Hash= ");
+    OCT_output(&HCID);
+    printf("\n");
+
+    OCT_toHex(&CLIENT_ID,idhex);
+    printf("Client ID= %s\n",idhex);// OCT_toHex(&CLIENT_ID); printf("\n");
+
+    MPIN_GET_CLIENT_SECRET(&S,&HCID,&TOKEN);
+    printf("Client Secret= ");
+    OCT_output(&TOKEN);
+
+// Client and Server are issued secrets by DTA 
+    MPIN_GET_SERVER_SECRET(&S,&SST);
+    printf("Server Secret= ");
+    OCT_output(&SST);
+
+    // Client extracts PIN from secret to create Token 
+    pin=1234;
+    printf("Client extracts PIN= %d\n",pin);
+    MPIN_EXTRACT_PIN(HASH_TYPE_BLS48,&CLIENT_ID,pin,&TOKEN);
+    printf("Client Token= ");
+    OCT_output(&TOKEN);
+
+#ifdef FULL
+    MPIN_PRECOMPUTE(&TOKEN,&HCID,NULL,&G1,&G2);
+#endif
+
+#ifdef PERMITS
+    // Client gets "Time Permit" from DTA 
+    printf("Client gets Time Permit\n");
+
+    MPIN_GET_CLIENT_PERMIT(HASH_TYPE_BLS48,date,&S,&HCID,&PERMIT);
+    printf("Time Permit= ");
+    OCT_output(&PERMIT);
+
+    // This encoding makes Time permit look random 
+    if (MPIN_ENCODING(RNG,&PERMIT)!=0) printf("Encoding error\n");
+    // printf("Encoded Time Permit= "); OCT_output(&PERMIT); 
+    if (MPIN_DECODING(&PERMIT)!=0) printf("Decoding error\n");
+    // printf("Decoded Time Permit= "); OCT_output(&PERMIT); 
+#endif
+
+    // MPin Protocol 
+
+    // Client enters PIN 
+    printf("\nPIN= ");
+    if(scanf("%d",&pin)) {};
+    // to avoid silly compile error 
+    getchar();
+
+    // 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
+
+   // HSID - hashed client ID as calculated by the server
+   // HCID - hashed client ID as calculated by the client
+
+   // 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.
+
+    
+
+    pxID=&xID;
+    pxCID=&xCID;
+    pHID=&HID;
+    pHTID=&HTID;
+    pE=&E;
+    pF=&F;
+    pPERMIT=&PERMIT;
+
+#ifdef PERMITS
+    prHID=pHTID;
+#ifndef PINERROR
+    pxID=NULL;
+//   pHID=NULL;  //new
+#endif
+#else
+    prHID=pHID;
+    pPERMIT=NULL;
+    pxCID=NULL;
+    pHTID=NULL;
+#endif
+#ifndef PINERROR
+    pE=NULL;
+    pF=NULL;
+#endif
+
+    // When set only send hashed IDs to server 
+    octet *pID;
+#ifdef USE_ANONYMOUS
+    pID = &HCID;
+#else
+    pID = &CLIENT_ID;
+#endif
+
+#ifdef SINGLE_PASS
+    int timeValue;
+    printf("MPIN Single Pass\n");
+    timeValue = MPIN_GET_TIME();
+
+    rtn=MPIN_CLIENT(HASH_TYPE_BLS48,date,&CLIENT_ID,RNG,&X,pin,&TOKEN,&SEC,pxID,pxCID,pPERMIT,NULL,timeValue,&Y);
+
+    if (rtn != 0)
+    {
+        printf("MPIN_CLIENT ERROR %d\n", rtn);
+        return 1;
+    }
+
+#ifdef FULL
+    MPIN_GET_G1_MULTIPLE(RNG,1,&R,&HCID,&Z);  // Also Send Z=r.ID to Server, remember random r 
+#endif
+
+
+    rtn=MPIN_SERVER(HASH_TYPE_BLS48,date,pHID,pHTID,&Y,&SST,pxID,pxCID,&SEC,pE,pF,pID,NULL,timeValue,NULL);
+
+#ifdef FULL
+    HASH_ID(HASH_TYPE_BLS48,&CLIENT_ID,&HSID);  // new
+    MPIN_GET_G1_MULTIPLE(RNG,0,&W,prHID,&T);  // Also send T=w.ID to client, remember random w  
+#endif
+
+#else // SINGLE_PASS
+    printf("MPIN Multi Pass\n");
+    if (MPIN_CLIENT_1(HASH_TYPE_BLS48,date,&CLIENT_ID,RNG,&X,pin,&TOKEN,&SEC,pxID,pxCID,pPERMIT)!=0)
+    {
+        printf("Error from Client side - First Pass\n");
+        return 0;
+    }
+
+    // Send U=x.ID to server, and recreate secret from token and pin 
+
+#ifdef FULL
+    HASH_ID(HASH_TYPE_BLS48,&CLIENT_ID,&HCID);
+    MPIN_GET_G1_MULTIPLE(RNG,1,&R,&HCID,&Z);  // Also Send Z=r.ID to Server, remember random r, DH component 
+#endif
+
+    // Server calculates H(ID) and H(ID)+H(T|H(ID)) (if time permits enabled), and maps them to points on the curve HID and HTID resp. 
+    MPIN_SERVER_1(HASH_TYPE_BLS48,date,pID,pHID,pHTID);
+
+    // Server generates Random number Y and sends it to Client 
+    MPIN_RANDOM_GENERATE(RNG,&Y);
+
+#ifdef FULL
+    HASH_ID(HASH_TYPE_BLS48,&CLIENT_ID,&HSID); //new
+    MPIN_GET_G1_MULTIPLE(RNG,0,&W,prHID,&T);  // Also send T=w.ID to client, remember random w, DH component  
+#endif
+
+    // Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC 
+    if (MPIN_CLIENT_2(&X,&Y,&SEC)!=0)
+    {
+        printf("Error from Client side - Second Pass\n");
+        return 1;
+    }
+
+    // Server Second phase. 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=MPIN_SERVER_2(date,pHID,pHTID,&Y,&SST,pxID,pxCID,&SEC,pE,pF,NULL);
+#endif // SINGLE_PASS
+
+    if (rtn!=0)
+    {
+        printf("Server says - Bad Pin.\n");
+#ifdef PINERROR
+
+        err=MPIN_KANGAROO(&E,&F);
+        if (err) printf("(Client PIN is out by %d)\n",err);
+
+#endif
+        return 1;
+    }
+    else
+    {
+        printf("Server says - PIN is good! You really are ");
+        OCT_output_string(&CLIENT_ID);
+        printf(".\n");
+    }
+
+#ifdef FULL
+
+    HASH_ALL(HASH_TYPE_BLS48,&HCID,pxID,pxCID,&SEC,&Y,&Z,&T,&H);  // new
+    i=MPIN_CLIENT_KEY(HASH_TYPE_BLS48,&G1,&G2,pin,&R,&X,&H,&T,&CK);      // new H
+    printf("Client Key = ");
+    OCT_output(&CK);
+
+    HASH_ALL(HASH_TYPE_BLS48,&HSID,pxID,pxCID,&SEC,&Y,&Z,&T,&H);
+    i=MPIN_SERVER_KEY(HASH_TYPE_BLS48,&Z,&SST,&W,&H,pHID,pxID,pxCID,&SK); // new H,pHID
+    printf("Server Key = ");
+    OCT_output(&SK);
+#endif
+    return 0;
+}
+#endif
+
+int rsa_2048(csprng *RNG)
+{
+	using namespace RSA2048;
+
+    int i;
+    unsigned long ran;
+    char m[RFS_RSA2048],ml[RFS_RSA2048],c[RFS_RSA2048],e[RFS_RSA2048],s[RFS_RSA2048];
+    rsa_public_key pub;
+    rsa_private_key priv;
+    
+    octet M= {0,sizeof(m),m};
+    octet ML= {0,sizeof(ml),ml};
+    octet C= {0,sizeof(c),c};
+    octet E= {0,sizeof(e),e};
+    octet S= {0,sizeof(s),s};
+
+    printf("Generating public/private key pair\n");
+    RSA_KEY_PAIR(RNG,65537,&priv,&pub,NULL,NULL);
+
+    printf("Encrypting test string\n");
+    OCT_jstring(&M,(char *)"Hello World\n");
+
+    OAEP_ENCODE(HASH_TYPE_RSA_RSA2048,&M,RNG,NULL,&E); // OAEP encode message m to e  
+
+    RSA_ENCRYPT(&pub,&E,&C);     // encrypt encoded message 
+    printf("Ciphertext= ");
+    OCT_output(&C);
+
+    printf("Decrypting test string\n");
+    RSA_DECRYPT(&priv,&C,&ML);   // ... and then decrypt it 
+
+    OAEP_DECODE(HASH_TYPE_RSA_RSA2048,NULL,&ML);    // decode it 
+    OCT_output_string(&ML);
+
+    printf("Signing message\n");
+    PKCS15(HASH_TYPE_RSA_RSA2048,&M,&C);
+
+    RSA_DECRYPT(&priv,&C,&S); // create signature in S 
+
+    printf("Signature= ");
+    OCT_output(&S);
+
+    RSA_ENCRYPT(&pub,&S,&ML);
+
+    if (OCT_comp(&C,&ML)) printf("Signature is valid\n");
+    else printf("Signature is INVALID\n");
+
+    RSA_PRIVATE_KEY_KILL(&priv);
+
+    OCT_clear(&M);
+    OCT_clear(&ML);   // clean up afterwards 
+    OCT_clear(&C);
+    OCT_clear(&E);
+
+    return 0;
+}
+
+
+int main()
+{
+    int i,res;
+    unsigned long ran;
+
+	char raw[100];
+    octet RAW= {0,sizeof(raw),raw};
+    csprng RNG;                // Crypto Strong RNG 
+
+    time((time_t *)&ran);
+
+    RAW.len=100;				// fake random seed source 
+    RAW.val[0]=ran;
+    RAW.val[1]=ran>>8;
+    RAW.val[2]=ran>>16;
+    RAW.val[3]=ran>>24;
+    for (i=0; i<100; i++) RAW.val[i]=i;
+
+    CREATE_CSPRNG(&RNG,&RAW);   // initialise strong RNG 
+
+	printf("\nTesting MPIN protocols for curve BN254\n");
+	mpin_BN254(&RNG);
+
+#if CHUNK!=16
+	printf("\nTesting MPIN protocols for curve BLS383\n");
+	mpin_BLS383(&RNG);
+	printf("\nTesting MPIN protocols for curve BLS24\n");
+	mpin192_BLS24(&RNG);
+	printf("\nTesting MPIN protocols for curve BLS48\n");
+	mpin256_BLS48(&RNG);
+#endif
+
+	printf("\nTesting ECDH protocols for curve ED25519\n");
+	ecdh_ED25519(&RNG);
+#if CHUNK!=16
+	printf("\nTesting ECDH protocols for curve NIST256\n");
+	ecdh_NIST256(&RNG);
+	printf("\nTesting ECDH protocols for curve GOLDILOCKS\n");
+	ecdh_GOLDILOCKS(&RNG);
+#endif
+	printf("\nTesting RSA protocols for 2048-bit RSA\n");
+	rsa_2048(&RNG);
+
+	KILL_CSPRNG(&RNG);
+}
+
diff --git a/version3/cpp/testnhs.cpp b/version3/cpp/testnhs.cpp
new file mode 100644
index 0000000..a29f841
--- /dev/null
+++ b/version3/cpp/testnhs.cpp
@@ -0,0 +1,73 @@
+/*
+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.
+*/
+
+/* test driver and function exerciser for NewHope Functions */
+
+// See https://eprint.iacr.org/2016/1157 (Alkim, Ducas, Popplemann and Schwabe)
+
+/* gcc -O2 testnhs.c amcl.a -o testnhs.exe */
+
+#include <stdio.h>
+#include <time.h>
+#include "newhope.h"
+
+using namespace amcl;
+
+int main()
+{
+	int i,ii,j,err;
+    unsigned long ran;
+	char raw[100];
+	csprng SRNG,CRNG;
+	RAND_clean(&SRNG); RAND_clean(&CRNG);
+	char s[1792],sb[1824],uc[2176],keyA[32],keyB[32];
+
+	octet S= {0,sizeof(s),s};
+	octet SB= {0,sizeof(sb),sb};
+	octet UC= {0,sizeof(uc),uc};
+	octet KEYA={0,sizeof(keyA),keyA};
+	octet KEYB={0,sizeof(keyB),keyB};
+
+// initialise random number generators
+    time((time_t *)&ran);
+
+    raw[0]=ran;
+    raw[1]=ran>>8;
+    raw[2]=ran>>16;
+    raw[3]=ran>>24;
+
+	for (i=4;i<100;i++) raw[i]=i+1;
+	RAND_seed(&SRNG,100,raw);
+										for (i=4;i<100;i++) raw[i]=i+2;
+										RAND_seed(&CRNG,100,raw);
+// NewHope Simple key exchange
+
+	NHS_SERVER_1(&SRNG,&SB,&S);
+										NHS_CLIENT(&CRNG,&SB,&UC,&KEYB);
+	NHS_SERVER_2(&S,&UC,&KEYA);
+
+    printf("Alice key= 0x");
+    OCT_output(&KEYA);
+										printf("Bob's key= 0x");
+										OCT_output(&KEYB);
+
+	return 0;
+}
+
+
diff --git a/version3/cpp/x509.cpp b/version3/cpp/x509.cpp
new file mode 100644
index 0000000..3e08f66
--- /dev/null
+++ b/version3/cpp/x509.cpp
@@ -0,0 +1,1097 @@
+/*
+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.
+*/
+
+/* AMCL X.509 Functions */
+
+// To run test program, define HAS_MAIN
+// gcc -std=c99 x509.c  amcl.a -o x509.exe
+
+//#define HAS_MAIN
+
+#include <stdio.h>
+#include "amcl.h"  // for octet support only
+#include "x509.h"
+
+// ASN.1 tags
+
+#define ANY 0x00
+#define SEQ 0x30
+#define OID 0x06
+#define INT 0x02
+#define NUL 0x05
+#define ZER 0x00
+#define UTF 0x0C
+#define UTC 0x17
+#define LOG 0x01
+#define BIT 0x03
+#define OCT 0x04
+#define STR 0x13
+#define SET 0x31
+#define IA5 0x16
+
+// Supported Encryption Methods
+
+#define ECC 1
+#define RSA 2
+
+// Supported Hash functions
+
+#define H256 2
+#define H384 3
+#define H512 4
+
+// Supported Curves
+
+#define NIST256 0    /**< For the NIST 256-bit standard curve - WEIERSTRASS only */
+#define C25519 1     /**< Bernstein's Modulus 2^255-19 - EDWARDS or MONTGOMERY only */
+#define BRAINPOOL 2  /**< For Brainpool 256-bit curve - WEIERSTRASS only */
+#define ANSSI 3      /**< For French 256-bit standard curve - WEIERSTRASS only */
+#define NIST384 10   /**< For the NIST 384-bit standard curve - WEIERSTRASS only */
+#define NIST521 12   /**< For the NIST 521-bit standard curve - WEIERSTRASS only */
+
+
+// Define some OIDs
+
+// Elliptic Curve with SHA256
+static unsigned char eccsha256[8]= {0x2a,0x86,0x48,0xce,0x3d,0x04,0x03,0x02};
+static octet ECCSHA256= {8,sizeof(eccsha256),(char *)eccsha256};
+
+// Elliptic Curve with SHA384
+static unsigned char eccsha384[8]= {0x2a,0x86,0x48,0xce,0x3d,0x04,0x03,0x03};
+static octet ECCSHA384= {8,sizeof(eccsha384),(char *)eccsha384};
+
+// Elliptic Curve with SHA512
+static unsigned char eccsha512[8]= {0x2a,0x86,0x48,0xce,0x3d,0x04,0x03,0x04};
+static octet ECCSHA512= {8,sizeof(eccsha512),(char *)eccsha512};
+
+// EC Public Key
+static unsigned char ecpk[7]= {0x2a,0x86,0x48,0xce,0x3d,0x02,0x01};
+static octet ECPK= {7,sizeof(ecpk),(char *)ecpk};
+
+// C25519 curve
+static unsigned char prime25519[9]= {0x2B,0x06,0x01,0x04,0x01,0xDA,0x47,0x0F,0x01}; /*****/
+static octet PRIME25519= {9,sizeof(prime25519),(char *)prime25519};
+
+// NIST256 curve
+static unsigned char prime256v1[8]= {0x2a,0x86,0x48,0xce,0x3d,0x03,0x01,0x07};
+static octet PRIME256V1= {8,sizeof(prime256v1),(char *)prime256v1};
+
+// NIST384 curve
+static unsigned char secp384r1[5]= {0x2B,0x81,0x04,0x00,0x22};
+static octet SECP384R1= {5,sizeof(secp384r1),(char *)secp384r1};
+
+// NIST521 curve
+static unsigned char secp521r1[5]= {0x2B,0x81,0x04,0x00,0x23};
+static octet SECP521R1= {5,sizeof(secp521r1),(char *)secp521r1};
+
+// RSA Public Key
+static unsigned char rsapk[9]= {0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01};
+static octet RSAPK= {9,sizeof(rsapk),(char *)rsapk};
+
+// RSA with SHA256
+static unsigned char rsasha256[9]= {0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b};
+static octet RSASHA256= {9,sizeof(rsasha256),(char *)rsasha256};
+
+// RSA with SHA384
+static unsigned char rsasha384[9]= {0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0c};
+static octet RSASHA384= {9,sizeof(rsasha384),(char *)rsasha384};
+
+// RSA with SHA512
+static unsigned char rsasha512[9]= {0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0d};
+static octet RSASHA512= {9,sizeof(rsasha512),(char *)rsasha512};
+
+#ifdef HAS_MAIN
+// countryName
+static unsigned char cn[3]= {0x55,0x04,0x06};
+static octet CN= {3,sizeof(cn),(char *)cn};
+
+// stateName
+// static char sn[3]= {0x55,0x04,0x08};
+// static octet SN= {3,sizeof(sn),sn};
+
+// localName
+// static char ln[3]= {0x55,0x04,0x07};
+// static octet LN= {3,sizeof(ln),ln};
+
+// orgName
+static unsigned char on[3]= {0x55,0x04,0x0A};
+static octet ON= {3,sizeof(on),(char *)on};
+
+// unitName
+// static char un[3]= {0x55,0x04,0x0B};
+// static octet UN= {3,sizeof(un),un};
+
+// myName
+// static char mn[3]= {0x55,0x04,0x03};
+// static octet MN= {3,sizeof(mn),mn};
+
+// emailName
+static unsigned char en[9]= {0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x09,0x01};
+static octet EN= {9,sizeof(en),(char *)en};
+#endif // HAS_MAIN
+
+/* Check expected TAG and return ASN.1 field length. If tag=0 skip check. */
+static int getalen(int tag,char *b,int j)
+{
+    int len;
+
+    if (tag!=0 && (unsigned char)b[j]!=tag) return -1; // not a valid tag
+    j++;
+
+    if ((unsigned char)b[j]==0x81)
+    {
+        j++;
+        len=(unsigned char)b[j];
+    }
+    else if ((unsigned char)b[j]==0x82)
+    {
+        j++;
+        len=256*b[j++];
+        len+=(unsigned char)b[j];
+    }
+    else
+    {
+        len=(unsigned char)b[j];
+        if (len>127) return -1;
+    }
+    return len;
+}
+
+/* jump over length field */
+static int skip(int len)
+{
+    if (len<128) return 2;
+    if (len>=128 && len<256) return 3;
+    return 4;
+}
+
+/* round length up to nearest 8-byte length */
+static int bround(int len)
+{
+    if (len%8==0) return len;
+    return len+(8-len%8);
+
+}
+
+//	Input signed cert as octet, and extract signature
+//	Return 0 for failure, ECC for Elliptic Curve signature, RSA for RSA signature
+//  Note that signature type is not provided here - its the type of the public key that
+//  is used to verify it that matters, and which determines for example the curve to be used!
+
+pktype X509_extract_cert_sig(octet *sc,octet *sig)
+{
+    int i,j,k,fin,len,rlen,sj,ex;
+    char soid[9];
+    octet SOID= {0,sizeof(soid),soid};
+    pktype ret;
+
+    ret.type=0;
+    ret.hash=0;
+
+    j=0;
+
+    len=getalen(SEQ,sc->val,j);		// Check for expected SEQ clause, and get length
+    if (len<0) return ret;			// if not a SEQ clause, there is a problem, exit
+    j+=skip(len);					// skip over length to clause contents. Add len to skip clause
+
+    if (len+j!=sc->len) return ret;
+
+    len=getalen(SEQ,sc->val,j);
+    if (len<0) return ret;
+    j+=skip(len)+len; // jump over cert to signature OID
+
+    len=getalen(SEQ,sc->val,j);
+    if (len<0) return ret;
+    j+=skip(len);
+
+    sj=j+len; // Needed to jump over signature OID
+
+// dive in to extract OID
+    len=getalen(OID,sc->val,j);
+    if (len<0) return ret;
+    j+=skip(len);
+
+    fin=j+len;
+    SOID.len=len;
+    for (i=0; j<fin; j++)
+        SOID.val[i++]= sc->val[j];
+
+    // check OID here..
+
+    if (OCT_comp(&ECCSHA256,&SOID))
+    {
+        ret.type=ECC;
+        ret.hash=H256;
+    }
+    if (OCT_comp(&ECCSHA384,&SOID))
+    {
+        ret.type=ECC;
+        ret.hash=H384;
+    }
+    if (OCT_comp(&ECCSHA512,&SOID))
+    {
+        ret.type=ECC;
+        ret.hash=H512;
+    }
+    if (OCT_comp(&RSASHA256,&SOID))
+    {
+        ret.type=RSA;
+        ret.hash=H256;
+    }
+    if (OCT_comp(&RSASHA384,&SOID))
+    {
+        ret.type=RSA;
+        ret.hash=H384;
+    }
+    if (OCT_comp(&RSASHA512,&SOID))
+    {
+        ret.type=RSA;
+        ret.hash=H512;
+    }
+
+    if (ret.type==0) return ret; // unsupported type
+
+    j=sj;  // jump out to signature
+
+    len=getalen(BIT,sc->val,j);
+    if (len<0)
+    {
+        ret.type=0;
+        return ret;
+    }
+    j+=skip(len);
+    j++;
+    len--; // skip bit shift (hopefully 0!)
+
+    if (ret.type==ECC)
+    {
+        // signature in the form (r,s)
+        len=getalen(SEQ,sc->val,j);
+        if (len<0)
+        {
+            ret.type=0;
+            return ret;
+        }
+        j+=skip(len);
+
+        // pick up r part of signature
+        len=getalen(INT,sc->val,j);
+        if (len<0)
+        {
+            ret.type=0;
+            return ret;
+        }
+        j+=skip(len);
+
+        if (sc->val[j]==0)
+        {
+            // skip leading zero
+            j++;
+            len--;
+        }
+        rlen=bround(len);
+
+        ex=rlen-len;
+        sig->len=2*rlen;
+
+        i=0;
+        for (k=0; k<ex; k++)
+            sig->val[i++]=0;
+
+        fin=j+len;
+        for (; j<fin; j++)
+            sig->val[i++]= sc->val[j];
+
+        // pick up s part of signature
+        len=getalen(INT,sc->val,j);
+        if (len<0)
+        {
+            ret.type=0;
+            return ret;
+        }
+        j+=skip(len);
+
+        if (sc->val[j]==0)
+        {
+            // skip leading zeros
+            j++;
+            len--;
+        }
+        rlen=bround(len);
+        ex=rlen-len;
+        for (k=0; k<ex; k++)
+            sig->val[i++]=0;
+
+        fin=j+len;
+        for (; j<fin; j++)
+            sig->val[i++]= sc->val[j];
+
+    }
+    if (ret.type==RSA)
+    {
+        rlen=bround(len);
+        ex=rlen-len;
+
+        sig->len=rlen;
+        i=0;
+        for (k=0; k<ex; k++)
+            sig->val[i++]=0;
+
+        fin=j+len;
+        for (; j<fin; j++)
+            sig->val[i++]= sc->val[j];
+
+    }
+    if (ret.hash==H256) ret.curve=NIST256;
+    if (ret.hash==H384) ret.curve=NIST384;
+    if (ret.hash==H512) ret.curve=NIST521;
+
+    return ret;
+}
+
+// Extract certificate from signed cert
+int X509_extract_cert(octet *sc,octet *cert)
+{
+    int i,j,fin,len,k;
+
+    j=0;
+    len=getalen(SEQ,sc->val,j);
+
+    if (len<0) return 0;
+    j+=skip(len);
+
+    k=j;
+
+    len=getalen(SEQ,sc->val,j);
+    if (len<0) return 0;
+    j+=skip(len);
+
+    fin=j+len;
+    cert->len=fin-k;
+    for (i=k; i<fin; i++) cert->val[i-k]=sc->val[i];
+
+    return 1;
+}
+
+// Extract Public Key from inside Certificate
+pktype X509_extract_public_key(octet *c,octet *key)
+{
+    int i,j,fin,len,sj;
+    char koid[12];     /*****/
+    octet KOID= {0,sizeof(koid),koid};
+    pktype ret;
+
+    ret.type=ret.hash=0;
+    ret.curve=-1;
+
+    j=0;
+
+    len=getalen(SEQ,c->val,j);
+    if (len<0) return ret;
+    j+=skip(len);
+
+    if (len+j!=c->len) return ret;
+
+    len=getalen(0,c->val,j);
+    if (len<0) return ret;
+    j+=skip(len)+len; //jump over version clause
+
+    len=getalen(INT,c->val,j);
+
+    if (len>0) j+=skip(len)+len; // jump over serial number clause (if there is one)
+
+    len=getalen(SEQ,c->val,j);
+    if (len<0) return ret;
+    j+=skip(len)+len;  // jump over signature algorithm
+
+    len=getalen(SEQ,c->val,j);
+    if (len<0) return ret;
+    j+=skip(len)+len; // skip issuer
+
+    len=getalen(SEQ,c->val,j);
+    if (len<0) return ret;
+    j+=skip(len)+len; // skip validity
+
+    len=getalen(SEQ,c->val,j);
+    if (len<0) return ret;
+    j+=skip(len)+len; // skip subject
+
+    len=getalen(SEQ,c->val,j);
+    if (len<0) return ret;
+    j+=skip(len); //
+
+    len=getalen(SEQ,c->val,j);
+    if (len<0) return ret;
+    j+=skip(len);
+
+// ** Maybe dive in and check Public Key OIDs here?
+// ecpublicKey & prime256v1, secp384r1 or secp521r1 for ECC
+// rsapublicKey for RSA
+
+    sj=j+len;
+
+    len=getalen(OID,c->val,j);
+    if (len<0) return ret;
+    j+=skip(len);
+
+    fin=j+len;
+    KOID.len=len;
+    for (i=0; j<fin; j++)
+        KOID.val[i++]= c->val[j];
+
+    ret.type=0;
+    if (OCT_comp(&ECPK,&KOID)) ret.type=ECC;
+    if (OCT_comp(&RSAPK,&KOID)) ret.type=RSA;
+
+    if (ret.type==0) return ret;
+
+    if (ret.type==ECC)
+    {
+        // which elliptic curve?
+        len=getalen(OID,c->val,j);
+        if (len<0)
+        {
+            ret.type=0;
+            return ret;
+        }
+        j+=skip(len);
+
+        fin=j+len;
+        KOID.len=len;
+        for (i=0; j<fin; j++)
+            KOID.val[i++]= c->val[j];
+
+        if (OCT_comp(&PRIME25519,&KOID)) ret.curve=C25519;   /*****/
+        if (OCT_comp(&PRIME256V1,&KOID)) ret.curve=NIST256;
+        if (OCT_comp(&SECP384R1,&KOID)) ret.curve=NIST384;
+        if (OCT_comp(&SECP521R1,&KOID)) ret.curve=NIST521;
+    }
+
+    j=sj; // skip to actual Public Key
+
+    len=getalen(BIT,c->val,j);
+    if (len<0)
+    {
+        ret.type=0;
+        return ret;
+    }
+    j+=skip(len); //
+    j++;
+    len--; // skip bit shift (hopefully 0!)
+
+// extract key
+    if (ret.type==ECC)
+    {
+        key->len=len;
+        fin=j+len;
+        for (i=0; j<fin; j++)
+            key->val[i++]= c->val[j];
+
+    }
+    if (ret.type==RSA)
+    {
+        // Key is (modulus,exponent) - assume exponent is 65537
+        len=getalen(SEQ,c->val,j);
+        if (len<0)
+        {
+            ret.type=0;
+            return ret;
+        }
+        j+=skip(len); //
+
+        len=getalen(INT,c->val,j); // get modulus
+        if (len<0)
+        {
+            ret.type=0;
+            return ret;
+        }
+        j+=skip(len); //
+        if (c->val[j]==0)
+        {
+            j++;
+            len--; // remove leading zero
+        }
+
+        key->len=len;
+        fin=j+len;
+        for (i=0; j<fin; j++)
+            key->val[i++]= c->val[j];
+
+		ret.curve=8*len;
+    }
+    return ret;
+}
+
+// Find pointer to main sections of cert, before extracting individual field
+// Find index to issuer in cert
+int X509_find_issuer(octet *c)
+{
+    int j,len;
+    j=0;
+    len=getalen(SEQ,c->val,j);
+    if (len<0) return 0;
+    j+=skip(len);
+
+    if (len+j!=c->len) return 0;
+
+    len=getalen(0,c->val,j);
+    if (len<0) return 0;
+    j+=skip(len)+len; //jump over version clause
+
+    len=getalen(INT,c->val,j);
+
+    if (len>0) j+=skip(len)+len; // jump over serial number clause (if there is one)
+
+    len=getalen(SEQ,c->val,j);
+    if (len<0) return 0;
+    j+=skip(len)+len;  // jump over signature algorithm
+
+    return j;
+}
+
+// Find index to validity period
+int X509_find_validity(octet *c)
+{
+    int j,len;
+    j=X509_find_issuer(c);
+
+    len=getalen(SEQ,c->val,j);
+    if (len<0) return 0;
+    j+=skip(len)+len; // skip issuer
+
+    return j;
+}
+
+// Find index to subject in cert
+int X509_find_subject(octet *c)
+{
+    int j,len;
+    j=X509_find_validity(c);
+
+    len=getalen(SEQ,c->val,j);
+    if (len<0) return 0;
+    j+=skip(len)+len; // skip validity
+
+    return j;
+}
+
+// NOTE: When extracting cert information, we actually return just an index to the data inside the cert, and maybe its length
+// So no memory is assigned to store cert info. It is the callers responsibility to allocate such memory if required, and copy
+// cert information into it.
+
+// Find entity property indicated by SOID, given start of issuer or subject field. Return index in cert, flen=length of field
+
+int X509_find_entity_property(octet *c,octet *SOID,int start,int *flen)
+{
+    int i,j,k,fin,len,tlen;
+    char foid[50];  /*****/
+    octet FOID= {0,sizeof(foid),foid};
+
+    j=start;
+
+    tlen=getalen(SEQ,c->val,j);
+    if (tlen<0) return 0;
+    j+=skip(tlen);
+
+    for (k=j; j<k+tlen;)
+    {
+        // search for Owner OID
+        len=getalen(SET,c->val,j);
+        if (len<0) return 0;
+        j+=skip(len);
+        len=getalen(SEQ,c->val,j);
+        if (len<0) return 0;
+        j+=skip(len);
+        len=getalen(OID,c->val,j);
+        if (len<0) return 0;
+        j+=skip(len);
+        fin=j+len;  // extract OID
+        FOID.len=len;
+        for (i=0; j<fin; j++)
+            FOID.val[i++]= c->val[j];
+        len=getalen(ANY,c->val,j);  // get text, could be any type
+        if (len<0) return 0;
+
+        j+=skip(len);
+        if (OCT_comp(&FOID,SOID))
+        {
+            // if its the right one return
+            *flen=len;
+            return j;
+        }
+        j+=len;  // skip over it
+    }
+    *flen=0; /*****/
+    return 0;
+}
+
+// Find start date of certificate validity period
+int X509_find_start_date(octet *c,int start)
+{
+    int j,len;
+    j=start;
+
+    len=getalen(SEQ,c->val,j);
+    if (len<0) return 0;
+    j+=skip(len);
+
+    len=getalen(UTC,c->val,j);
+    if (len<0) return 0;
+    j+=skip(len);
+    return j;
+}
+
+// Find expiry date of certificate validity period
+int X509_find_expiry_date(octet *c,int start)
+{
+    int j,len;
+    j=start;
+
+    len=getalen(SEQ,c->val,j);
+    if (len<0) return 0;
+    j+=skip(len);
+
+    len=getalen(UTC,c->val,j);
+    if (len<0) return 0;
+    j+=skip(len)+len;
+
+    len=getalen(UTC,c->val,j);
+    if (len<0) return 0;
+    j+=skip(len);
+
+    return j;
+}
+
+void print_out(char *des,octet *c,int index,int len)
+{
+    int i;
+    printf("%s [",des);
+    for (i=0; i<len; i++)
+        printf("%c",c->val[index+i]);
+    printf("]\n");
+}
+
+void print_date(char *des,octet *c,int index)
+{
+    int i=index;
+    printf("%s [",des);
+    if (i==0) printf("]\n");
+    else printf("20%c%c-%c%c-%c%c %c%c:%c%c:%c%c]\n",c->val[i],c->val[i+1],c->val[i+2],c->val[i+3],c->val[i+4],c->val[i+5],c->val[i+6],c->val[i+7],c->val[i+8],c->val[i+9],c->val[i+10],c->val[i+11]);
+}
+
+
+#ifdef HAS_MAIN
+
+/* This simple driver program is hard-wired to support just one elliptic curve and one 
+   RSA bit length. To change replace the text string NIST256 in the main program to 
+   another curve and 2048 to some other value, where the curve and the RSA bit length 
+   are suppported by the library. Of course a more elaborate program could support
+   muliple curves simultaneously */
+
+#define CHOICE NIST256
+
+
+
+/* test driver program */
+// Sample Certs. Uncomment one CA cert and one example cert. Note that AMCL library must be built to support given curve.
+// Sample Certs all created using OpenSSL - see http://blog.didierstevens.com/2008/12/30/howto-make-your-own-cert-with-openssl/
+// Note - SSL currently only supports NIST curves. Howevever version 1.1.0 of OpenSSL now supports C25519
+
+#if CHOICE==NIST256
+
+#include "ecdh_NIST256.h"
+#include "rsa_2048.h"
+
+// ** CA is RSA 2048-bit based - for use with NIST256 build of library - assumes use of SHA256 in Certs
+// RSA 2048 Self-Signed CA cert
+char ca_b64[]="MIIDuzCCAqOgAwIBAgIJAP44jcM1MOROMA0GCSqGSIb3DQEBCwUAMHQxCzAJBgNVBAYTAklFMRAwDgYDVQQIDAdJcmVsYW5kMQ8wDQYDVQQHDAZEdWJsaW4xITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEfMB0GCSqGSIb3DQEJARYQbXNjb3R0QGluZGlnby5pZTAeFw0xNTExMjYwOTUwMzlaFw0yMDExMjUwOTUwMzlaMHQxCzAJBgNVBAYTAklFMRAwDgYDVQQIDAdJcmVsYW5kMQ8wDQYDVQQHDAZEdWJsaW4xITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEfMB0GCSqGSIb3DQEJARYQbXNjb3R0QGluZGlnby5pZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANUs7/nri9J8zw8rW8JVszXP0ZqeLoQJaq2X28ebm8x5VT3okr9rnBjFjpx0YKQCAFQf8iSOOYuNpDvtZ/YpsjPbk2rg5sLY9G0eUMqrTuZ7moPSxnrXS5evizjD9Z9HqaqeNEYD3sPouPg+lhU1oAUQjUTJVFhEr1x0EnSEYbbrWtY9ZDSuZv+d4NIeqqPOYFd1yZc+LYZyQbAAQqwRLNPZH/rnIykLa6I7w7mGT7H6SBz2O09BtgpTHhalL40ecXa4ZOEze0xwzlc+mEFIrnmdadg3vQrJt42RVbo3LN6RfDIqUZOMOtQW/53pUR1lIpCwVWJTiOpmSEIEqhhjFq0CAwEAAaNQME4wHQYDVR0OBBYEFJrz6LHeT6FcjRahpUC3hAMxKRTCMB8GA1UdIwQYMBaAFJrz6LHeT6FcjRahpUC3hAMxKRTCMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBADqkqCYVa3X8XO9Ufu6XIUoZafFPRjSeJXvEIWqlbm7ixJZ2FPOvf2eMc5RCZYigNKhsxru5Ojw0lPcpa8DDmEsdZDf7p0vlmf7T7xH9gtoInh4DzgI8HRHFc8R/z2/jLX7nlLoopKX5yp7F1gRACg0pd4tGpQ6EnBNcYZZghFH9UIRDmx+vDlwDCu8vyRPt35orrEiI4XGq/QkvxxAb5YWxQ4i06064ULfyCI7suu3KoobdM1aAaA8zhpOOBXKbq+Wi9IGFe/wiEMHLmfHdt9CBTjIWb//IHji4RT05kCmTVrx97pb7EHafuL3L10mM5cpTyBWKnb4kMFtx9yw+S2U=";
+// an RSA 2048 CA-signed cert
+//char cert_b64[]="MIIDcjCCAloCAQEwDQYJKoZIhvcNAQELBQAwdDELMAkGA1UEBhMCSUUxEDAOBgNVBAgMB0lyZWxhbmQxDzANBgNVBAcMBkR1YmxpbjEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMR8wHQYJKoZIhvcNAQkBFhBtc2NvdHRAaW5kaWdvLmllMB4XDTE1MTEyNjEwMzQzMFoXDTE3MTEyNTEwMzQzMFowgYkxCzAJBgNVBAYTAklFMRAwDgYDVQQIDAdJcmVsYW5kMQ8wDQYDVQQHDAZEdWJsaW4xETAPBgNVBAoMCENlcnRpVm94MQ0wCwYDVQQLDARMYWJzMQ0wCwYDVQQDDARNSUtFMSYwJAYJKoZIhvcNAQkBFhdtaWtlLnNjb3R0QGNlcnRpdm94LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMIoxaQHFQzfyNChrw+3i7FjRFMHZ4zspkjkAcJW21LdBCqrxU+sdjyBoSFlrlafQOHshbrEP93AKX1bfaYbuV4fzq7OlRaLxaK+b+xrOJdewMI2WZ5OwEzj3onZATISogIoB6dTdzJ41NuxuMqQ/DqOnVrRA0SoIespbQhB8FGHBLw0hJATBzUk+bqOIt0HmnMp2EbYgtuG4lYINU/lD3Qt16SunUukWRLtxqJkioie+dkhP2zm+bOlSVmeQb4Wp8AI14OKkTfkdYC8qCxb5eabg90Q33rQUhNwRQHhHwopZwD/BgodasoSrPfwUlj0awh6y87eMGcik5Q/mjkCk5MCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAFrd7R/67ClkbLhpiX++6QTOa47siUAB9v+Qil9hZfhPNeeM589ixYkD4zH5pOK2B0ea+CXEKkanQ6lXx9KV86yS7fq6Yww7wO0diecusHd0+P82i46Tq0nm8nlsnAuhYoFRUGa2m2DkB1HSsB0ts8DjzFLySonFjSSLHDU0ox9/uFbJMzipy3ijAA4XM0N4jRrUfrmxpA7DOOsbEbGkvvB7VK9+s9PHE/4dJTwhSteplUnhxVFkkDo/JwaLx4/IEQRlCF3KEQ5s3AwRHnbrIjOY2yONxHBtJEp7QN5aOHruwvMNRNheCBPiQJyLitUsFGr4voANmobkrFgYtu0tRMQ==";
+// an ECC 256 CA-signed cert
+char cert_b64[]="MIICojCCAYoCAQMwDQYJKoZIhvcNAQELBQAwdDELMAkGA1UEBhMCSUUxEDAOBgNVBAgMB0lyZWxhbmQxDzANBgNVBAcMBkR1YmxpbjEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMR8wHQYJKoZIhvcNAQkBFhBtc2NvdHRAaW5kaWdvLmllMB4XDTE1MTEyNjEzNDcyOVoXDTE3MTEyNTEzNDcyOVowgYQxCzAJBgNVBAYTAklFMRAwDgYDVQQIDAdJcmVsYW5kMQ8wDQYDVQQHDAZEdWJsaW4xETAPBgNVBAoMCENlcnRpdm94MQ0wCwYDVQQLDARMYWJzMQ8wDQYDVQQDDAZtc2NvdHQxHzAdBgkqhkiG9w0BCQEWEG1zY290dEBpbmRpZ28uaWUwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATO2iZiQZsXxzwBKnufKfZcsctNXZ4PmfJm638PmX9DQ3Xdb+nD5VxiOakNcB9xf5im8CriiOF5Z/7yPGyzUMbdMA0GCSqGSIb3DQEBCwUAA4IBAQAK5fMgGCCiPts8hMUZvYDpu8hd7qtPKPBc10QUccHb7PGrhqf/Ex2Gpj1aaURmx7SGZG0HX97LtkdW8KQpEoyaa60r7cjVA589TznxXKSGg5ggVoFJNpuZUm7VcolLjwIgTxtGbPzrvVMiZ4cl4PwFePXVKTl4f8XkOFX5gLmVSuCf729lEBmpx3IzqGmTjmnBixaApUElOKVeL7hiUKP3TqMUxZN+QNJBq4Mh9K9h4Sks2oneLwBwhMqQvpmcOb/7SucJn5N0IgJoGaMbfX0oCJJID1NSbagUSbFD1XciR2Ng9VtvnRP+htmEQ7jtww8phFdrWt5M5zPGOHUppqDx";
+
+// ** CA is ECC 256 based  - for use with NIST256 build of library
+// ECC 256 Self-Signed CA cert
+//char ca_b64[]="MIIB7TCCAZOgAwIBAgIJANp4nGS/VYj2MAoGCCqGSM49BAMCMFMxCzAJBgNVBAYTAklFMRAwDgYDVQQIDAdJcmVsYW5kMQ8wDQYDVQQHDAZEdWJsaW4xITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0xNTExMjYxMzI0MTBaFw0yMDExMjUxMzI0MTBaMFMxCzAJBgNVBAYTAklFMRAwDgYDVQQIDAdJcmVsYW5kMQ8wDQYDVQQHDAZEdWJsaW4xITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABPb6IjYNKyfbEtL1aafzW1jrn6ALn3PnGm7AyX+pcvwG0GKmb3Z/uHzhT4GysNE0/GB1n4Y/mrORQIm2X98rRs6jUDBOMB0GA1UdDgQWBBSfXUNkgJVklIhuXq4DCnVYhsdzwDAfBgNVHSMEGDAWgBSfXUNkgJVklIhuXq4DCnVYhsdzwDAMBgNVHRMEBTADAQH/MAoGCCqGSM49BAMCA0gAMEUCIQDrZJ1tshwTl/jabU2i49EOgbWe0ZgE3QZywJclf5IVwwIgVmz79AAf7e098lyrOKYAqbwjHVyMZGfmkNNGIuIhp/Q=";
+// an ECC 256 CA-signed cert
+//char cert_b64[]="MIIBvjCCAWQCAQEwCgYIKoZIzj0EAwIwUzELMAkGA1UEBhMCSUUxEDAOBgNVBAgMB0lyZWxhbmQxDzANBgNVBAcMBkR1YmxpbjEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMB4XDTE1MTEyNjEzMjc1N1oXDTE3MTEyNTEzMjc1N1owgYIxCzAJBgNVBAYTAklFMRAwDgYDVQQIDAdJcmVsYW5kMQ8wDQYDVQQHDAZEdWJsaW4xETAPBgNVBAoMCENlcnRpdm94MQ0wCwYDVQQLDARMYWJzMQ0wCwYDVQQDDARtaWtlMR8wHQYJKoZIhvcNAQkBFhBtc2NvdHRAaW5kaWdvLmllMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEY42H52TfWMLueKB1o2Sq8uKaKErbHJ2GRAxrnJdNxex0hxZF5FUx7664BbPUolKhpvKTnJxDq5/gMqXzpKgR6DAKBggqhkjOPQQDAgNIADBFAiEA0ew08Xg32g7BwheslVKwXo9XRRx4kygYha1+cn0tvaUCIEKCEwnosZlAckjcZt8aHN5zslE9K9Y7XxTErTstthKc";
+// an RSA 2048 CA-signed cert
+//char cert_b64[]="MIICiDCCAi4CAQIwCgYIKoZIzj0EAwIwUzELMAkGA1UEBhMCSUUxEDAOBgNVBAgMB0lyZWxhbmQxDzANBgNVBAcMBkR1YmxpbjEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMB4XDTE1MTEyNjEzMzcwNVoXDTE3MTEyNTEzMzcwNVowgYExCzAJBgNVBAYTAklFMQ8wDQYDVQQIDAZJZWxhbmQxDzANBgNVBAcMBkR1YmxpbjERMA8GA1UECgwIQ2VydGl2b3gxDTALBgNVBAsMBExhYnMxDTALBgNVBAMMBE1pa2UxHzAdBgkqhkiG9w0BCQEWEG1zY290dEBpbmRpZ28uaWUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCjPBVwmPg8Gwx0+8xekmomptA0BDwS7NUfBetqDqNMNyji0bSe8LAfpciU7NW/HWfUE1lndCqSDDwnMJmwC5e3GAl/Bus+a+z8ruEhWGbn95xrHXFkOawbRlXuS7UcEQCvPr8KQHhNsg4cyV7Hn527CPUl27n+WN8/pANo01cTN/dQaK87naU0Mid09vktlMKSN0zyJOnc5CsaTLs+vCRKJ9sUL3d4IQIA2y7gvrTe+iY/QI26nqhGpNWYyFkAdy9PdHUEnDI6JsfF7jFh37yG7XEgDDA3asp/oi1T1+ZoASj2boL++opdqCzDndeWwzDWAWuvJ9wULd80ti6x737ZAgMBAAEwCgYIKoZIzj0EAwIDSAAwRQIgCDwgl98+9moBo+etaLt8MvB/z5Ti6i9neRTZkvoFl7YCIQDq//M3OB757fepErRzIQo3aFAFYjOooi6WdSqP3XqGIg==";
+
+#endif
+
+#if CHOICE==NIST384
+
+#include "ecdh_NIST384.h"
+#include "rsa_3072.h"
+
+// ** CA is RSA 3072-bit based  - for use with NIST384 build of library - assumes use of SHA384 in Certs
+// RSA 3072 Self-Signed CA cert
+char ca_b64[]="MIIElzCCAv+gAwIBAgIJAJA+8OyEeK4FMA0GCSqGSIb3DQEBDAUAMGIxCzAJBgNVBAYTAklFMRAwDgYDVQQIDAdJcmVsYW5kMQ8wDQYDVQQHDAZEdWJsaW4xITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDENMAsGA1UEAwwETWlrZTAeFw0xNTExMjYxNDQ0MDBaFw0yMDExMjUxNDQ0MDBaMGIxCzAJBgNVBAYTAklFMRAwDgYDVQQIDAdJcmVsYW5kMQ8wDQYDVQQHDAZEdWJsaW4xITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDENMAsGA1UEAwwETWlrZTCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBANvNO8ahsanxzqwkp3A3bujwObJoP3xpOiAAxwGbW867wx4EqBjPRZP+Wcm9Du6e4Fx9U7tHrOLocIUUBcRrmxUJ7Z375hX0cV9yuoYPNv0o2klJhB8+i4YXddkOrSmDLV4r46Ytt1/gjImziat6ZJALdd/uIuhaXwjzy1fFqSEBpkzhrFwFP9MG+5CgbRQed+YxZ10l/rjk+h3LKq9UFsxRCMPYhBFgmEKAVTMnbTfNNxawTRCKtK7nxxruGvAEM+k0ge5rvybERQ0NxtizefBSsB3Q6QVZOsRJiyC0HQhE6ZBHn4h3A5nHUZwPeh71KShw3uMPPB3Kp1pb/1Euq8azyXSshEMPivvgcGJSlm2b/xqsyrT1tie82MqB0APYAtbx3i5q8p+rD143NiNO8fzCq/J+EV82rVyvqDxf7AaTdJqDbZmnFRbIcrLcQdigWZdSjc+WxrCeOtebRmRknuUmetsCUPVzGv71PLMUNQ2qEiq8KGWmnMBJYVMl96bPxwIDAQABo1AwTjAdBgNVHQ4EFgQUsSjrHeZ5TNI2tMcQd6wUnFpU8DcwHwYDVR0jBBgwFoAUsSjrHeZ5TNI2tMcQd6wUnFpU8DcwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQwFAAOCAYEADlnC1gYIHpVf4uSuBpYNHMO324hhGajHNraHYQAoYc0bW4OcKi0732ib5CHDrV3LCxjxF4lxZVo61gatg5LnfJYldXc0vP0GQRcaqC6lXlLb8ZJ0O3oPgZkAqpzc+AQxYW1wFxbzX8EJU0stSwAuxkgs9bwg8tTxIhDutrcjQl3osnAqGDyM+7VAG5QLRMzxiZumyD7s/xBUOa+L6OKXf4QRr/SH/rPU8H+ENaNkv4PApSVzCgTBPOFBIzqEuO4hcQI0laUopsp2kK1w6wYB5oY/rR/O6lNNfB2WEtfdIhdbQru4cUE3boKerM8Mjd21RuerAuK4X8cbDudHIFsaopGSNuzZwPo/bu0OsmZkORxvdjahHJ0G3/6jM6nEDoIy6mXUCGOUOMhGQKCa8TYlZdPKz29QIxk6HA1wCA38MxUo/29Z7oYw27Mx3x8Gcr+UA4vc+oBN3IEzRmhRZKAYQ10MhYPx3NmYGZBDqHvT06oG5hysTCtlVzx0Tm+o01JQ";
+// an RSA 3072 CA-signed cert
+//char cert_b64[]="MIIEWzCCAsMCAQYwDQYJKoZIhvcNAQEMBQAwYjELMAkGA1UEBhMCSUUxEDAOBgNVBAgMB0lyZWxhbmQxDzANBgNVBAcMBkR1YmxpbjEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMQ0wCwYDVQQDDARNaWtlMB4XDTE1MTEyNjE0NDY0MloXDTE3MTEyNTE0NDY0MlowgYQxCzAJBgNVBAYTAklFMRAwDgYDVQQIDAdJcmVsYW5kMQ8wDQYDVQQHDAZEdWJsaW4xETAPBgNVBAoMCENlcnRpdm94MQ0wCwYDVQQLDARMYWJzMQ8wDQYDVQQDDAZtc2NvdHQxHzAdBgkqhkiG9w0BCQEWEG1zY290dEBpbmRpZ28uaWUwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQC6SrDiE4BpTEks1YpX209q8iH0dfvhGO8hi1rGYFYnz+eeiOvPdXiCdIPVPbGwxQGMEnZQV1X0KupYJw3LR2EsXhN4LZBxnQZmDvUXsTU+Ft/CKZUxVoXpNMxzwl70RC6XeUpPxvdPXa78AnfLL/DsOKsxCfNaKYZZ6G53L6Y69+HrCbyM7g2KrZ9/K/FXS1veMpRj9EbA6Mcdv1TUDNK2fTDV952AQO3kC3+PqywdVgPvntraAoQomrni+tcFW7UXe2Sk7DRcF/acBSuo2UtP3m9UWNL+8HOXvtRqmhns55Vj4DxKuPln759UBS7WZ11apCvC3BvCHR/k3WRf9PQWnW2cmT73/kEShvTRi8h7F9RWvYTEF1MuwSVy+l51q8O3rJU4XxnLm/YbtIGXZUf5Rqb0985zQkA+6rip/OSc8X5a3OV3kp38U7tXJ5sqBMg9RdIIz42cmiRLG5NYSj0/T6zjYEdwj3SYEBoPN/7UGSmhu8fdxS7JYPNpOsgeiu8CAwEAATANBgkqhkiG9w0BAQwFAAOCAYEAyxxEg0hWLFuN2fiukX6vqzSDx5Ac8w1JI4W/bamRd7iDZfHQYqyPDZi9s07I2PcGbByj2oqoyGiIEBLbsljdIEF4D229h2kisn1gA9O+0IM44EgjhBTUoNDgC+SbfJrXlU2GZ1XI3OWjbK7+1wiv0NaBShbbiPgSdjQBP8S+9W7lyyIrZEM1J7maBdepie1BS//DUDmpQzEi0UlB1J+HmQpyZsnT97J9uIPKsK4t2/+iOiknl6iS4GzAQKMLqj2yIBRf/O44ZZ6UZIKLtI4PCVS/8H5Lrg3AC0kr4ZkPAXzefUiTwyLVkqYSxSSTvtb3BpgOxIbmA6juFid0rvUyjN4fuDQkxl3PZyQwIHjpz33HyKrmo4BZ8Dg4JT8LCsQgd0AaD3r0QOS5FdLhkb+rD8EMSsCoOCEtPI6lqLJCrGOQWj7zbcUdPOEsczWMI9hSfK3u/P9+gOUBUFkb0gBIn3WvNuHifIHpsZ5bzbR+SGtu5Tgc7CCCPyNgz1Beb247";
+// an ECC 384 CA-signed cert
+char cert_b64[]="MIIDCDCCAXACAQcwDQYJKoZIhvcNAQEMBQAwYjELMAkGA1UEBhMCSUUxEDAOBgNVBAgMB0lyZWxhbmQxDzANBgNVBAcMBkR1YmxpbjEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMQ0wCwYDVQQDDARNaWtlMB4XDTE1MTEyNjE1MzU1M1oXDTE3MTEyNTE1MzU1M1owYDELMAkGA1UEBhMCSUUxEDAOBgNVBAgMB0lyZWxhbmQxDzANBgNVBAcMBkR1YmxpbjEQMA4GA1UECgwHQ2VydGl2bzENMAsGA1UECwwETGFiczENMAsGA1UEAwwEbWlrZTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJ1J+FT5mxxYEM4aYKM0CvZHmh8JFXzoBmzibabrvyTz79+1QOrR+6MEEsKtmJIYPJi+GsQ0PmjF2HmJncM1zeQh7DQYJf2Xc8p5Vjd8//6YREBVfN3UIyrl87MSucy+mjANBgkqhkiG9w0BAQwFAAOCAYEAmuwa64+K1qlCELpcnCyWwMhSb+Zsw0Hh6q/BfxalZhsX1UFEwE9nHoVJcokaEEYF4u4AYXU5rdysRHxYBfgMbohguTT7sJwCfve2JqpqvhQOkGDG1DB4Ho4y7NPPYB2+UMd7JMD0TOcHXdgQ8FtAE0ClD8VkW0gAC0lCrbQbynfLoUjIWqg3w2g79hvdZPgRt208nFiHuezynOaEFePoXl8CxHInsxAnMaJn2fEs5/QH67pwD65mPdNFsvlr0zdzYcceqEmEHpRAXFOQAJtffGjWAGGX/CsghLuqlpdCiTGA1B53XoXKJvArr/kHpTNMsU1NnkQIHZ5n4USCo4QgL6n9nwem7U2mYBYjmxPi5Y3JJnTZz4zUnv0bD0vSwoivnFZox9H6qTAkeIX1ojJ2ujxWHNOMvOFb6nU2gqNZj2vYcO38OIrK9gwM9lm4FF20YBufh+WOzQthrHJv0YuQt3NuDQEMkvz+23YvzZlr+e2XqDlMhyR01Kk0MXeLGGcv";
+
+// ** CA is ECC 384 based - - for use with NIST384 build of library - assumes use of SHA384 in Certs
+// ECC 384 Self-Signed CA Cert
+//char ca_b64[]="MIICSTCCAc6gAwIBAgIJAIwHpOFSZLXnMAoGCCqGSM49BAMDMGIxCzAJBgNVBAYTAklFMRAwDgYDVQQIDAdJcmVsYW5kMQ8wDQYDVQQHDAZEdWJsaW4xITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDENMAsGA1UEAwwEbWlrZTAeFw0xNTExMjYxNTQ0NTlaFw0yMDExMjUxNTQ0NTlaMGIxCzAJBgNVBAYTAklFMRAwDgYDVQQIDAdJcmVsYW5kMQ8wDQYDVQQHDAZEdWJsaW4xITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDENMAsGA1UEAwwEbWlrZTB2MBAGByqGSM49AgEGBSuBBAAiA2IABOEPMYBqzIn1hJAMZ0aEVxQ08gBF2aSfWtEJtmKj64014w7VfWdeFQSIMP9SjmhatFbAvxep8xgcwbeAobGTqCgUp+0EdFZR1ktKSND/S+UDU1YSNCFRvlNTJ6YmXUkW36NQME4wHQYDVR0OBBYEFDQxIZoKNniNuW91UMJ1KWEjs045MB8GA1UdIwQYMBaAFDQxIZoKNniNuW91UMJ1KWEjs045MAwGA1UdEwQFMAMBAf8wCgYIKoZIzj0EAwMDaQAwZgIxANbml6sp5A92qQiCM/OtBf+TbXpSpIO83TuNP9V2lsphp0CEX3KwAuqBXB95m9/xWAIxAOXAT2LqieSbUh4fpxcdaeY01RoGtD2AQch1a6BuIugcQqTfqLcXy7D51R70R729sA==";
+// an ECC 384 CA-signed cert
+//char cert_b64[]="MIICCjCCAZACAQgwCgYIKoZIzj0EAwMwYjELMAkGA1UEBhMCSUUxEDAOBgNVBAgMB0lyZWxhbmQxDzANBgNVBAcMBkR1YmxpbjEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMQ0wCwYDVQQDDARtaWtlMB4XDTE1MTEyNjE1NTIxMFoXDTE3MTEyNTE1NTIxMFowgYIxCzAJBgNVBAYTAklFMRAwDgYDVQQIDAdJcmVsYW5kMQ8wDQYDVQQHDAZEdWJsaW4xETAPBgNVBAoMCENlcnRpdm94MQ0wCwYDVQQLDARMYWJzMQ0wCwYDVQQDDARtaWtlMR8wHQYJKoZIhvcNAQkBFhBtc2NvdHRAaW5kaWdvLmllMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEf2Qm6jH2U+vhAApsMqH9gzGCH8rk+mUwFSD3Uud4NiyPBqrJRC1eetVvr3cYb6ucDTa15km6QKvZZrsRW+Z4ZpryoEE6esmD4XPLrtrOtoxtxFNRhiMmT/M9zcrfMJC5MAoGCCqGSM49BAMDA2gAMGUCMF0x6PAvvnJR3riZdUPC4OWFC2K3eiz3QuLCdFOZVIqX7mkLftdS8BtzusXWMMgFCQIxALJNMKLs39P9wYQHu1C+v9ieltQr20C+WVYxqUvgL/KTdxd9dzc3wseZRDT1CydqOA==";
+// an RSA 3072 CA-signed cert
+//char cert_b64[]="MIIDFjCCAp4CAQkwCgYIKoZIzj0EAwMwYjELMAkGA1UEBhMCSUUxEDAOBgNVBAgMB0lyZWxhbmQxDzANBgNVBAcMBkR1YmxpbjEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMQ0wCwYDVQQDDARtaWtlMB4XDTE1MTEyNjE2MTYwNloXDTE3MTEyNTE2MTYwNlowYzELMAkGA1UEBhMCSUUxEDAOBgNVBAgMB0lyZWxhbmQxDzANBgNVBAcMBkR1YmxpbjERMA8GA1UECgwIQ2VydGl2b3gxDTALBgNVBAsMBGxhYnMxDzANBgNVBAMMBmtlYWxhbjCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAK5QhVjR+UGt3ZWPSGicpviqaOhxXmmvOepdl5Seqr+Iweb3IuEDgtHGwrw/EEgWlKPfS/2LW9ncptdNbVQh7+2rojj7ZtedrAK5p7I9b22f2U3sSHIqjtTT0BjqzL0qEwy/ATqbf93Tcr3yT0Ygh3yzbvn4zodrWQZK8kkN3PQKkiHBCuIxo+8MlTs8d99dl1hbJ84MYZuPmhrkB4oLEAt8+srtL+a4Yd0wPhuCYrLjBnYkD9TlcWLWWh8/iwXiznrY8gQsXSveQNzQjcmHilZrTlTL2dnyI2v7BAXXHSwo6UeES0n064fnYTr3JB0GArMcty6RD3E7xr64HNzzTE2+8cDxufNvU0tq2Z72oZ9cAReHUL5P6mLfORI+AhtCHrXGJch/F07ZX9h8UFpzok8NK5++Q7lHKuezTYRRPlDL5hDB3BUpBwvILdqujcbNil04cuLRBNT/WgqRXEBRjlHLgZaLChFV2VSJ9Z1Uke2lfm5X2O0XPQLhjMSiuvr4HwIDAQABMAoGCCqGSM49BAMDA2YAMGMCLxHSQAYP2EsuIpR4TzDDSIlsw4BBsD7W0ZfH91v9J0j5UWQJD/yNjMtyA2Qlkq/0AjB+SJQbLgycNJH5SnR/X5wx26/62ln9s0swUtlCYVtNzyEQ3YRHSZbmTbh16RUT7Ak=";
+
+#endif
+
+#if CHOICE==NIST521
+
+#include "ecdh_NIST521.h"
+#include "rsa_4096.h"
+
+// ** CA is ECC 521 based - - for use with NIST521 build of library - assumes use of SHA512 in Certs
+// ECC 521 Self-Signed CA Cert
+char ca_b64[]="MIIC+TCCAlqgAwIBAgIJAKlppiHsRpY8MAoGCCqGSM49BAMEMIGUMQswCQYDVQQGEwJJRTEQMA4GA1UECAwHSXJlbGFuZDEPMA0GA1UEBwwGRHVibGluMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxDTALBgNVBAsMBExhYnMxDzANBgNVBAMMBm1zY290dDEfMB0GCSqGSIb3DQEJARYQbXNjb3R0QGluZGlnby5pZTAeFw0xNTEyMDExMzE5MjZaFw0yMDExMzAxMzE5MjZaMIGUMQswCQYDVQQGEwJJRTEQMA4GA1UECAwHSXJlbGFuZDEPMA0GA1UEBwwGRHVibGluMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxDTALBgNVBAsMBExhYnMxDzANBgNVBAMMBm1zY290dDEfMB0GCSqGSIb3DQEJARYQbXNjb3R0QGluZGlnby5pZTCBmzAQBgcqhkjOPQIBBgUrgQQAIwOBhgAEAKUj6Qa4Vr1vyango8XHlLIIEzY9IVppdpGUrMlNfo0Spu+AXGhnluwJTZXOYLi8jSIPEAL7vuwS5H6uPPIz1QWXALRETVYAQfK0pIfPHq+edTHVTXMcAUpdNla2d4LwYO7HpkSQFHd7aaDN3yVhSL2J0LBLgy0wGkEHuyK1O2r0xNu6o1AwTjAdBgNVHQ4EFgQU966PLshKffU/NRCivMmNq8RiRkAwHwYDVR0jBBgwFoAU966PLshKffU/NRCivMmNq8RiRkAwDAYDVR0TBAUwAwEB/zAKBggqhkjOPQQDBAOBjAAwgYgCQgHkLczeTWXq5BfY0bsTOSNU8bYy39OhiQ8wr5rlXY0zOg0fDyokueL4dhkXp8FjbIyUfQBY5OMxjtcn2p+cXU+6MwJCAci61REgxZvjpf1X8pGeSsOKa7GhfsfVnbQm+LQmjVmhMHbVRkQ4h93CENN4MH/86XNozO9USh+ydTislAcXvCb0";
+// an ECC 521 CA-signed cert
+char cert_b64[]="MIICZjCCAccCAQMwCgYIKoZIzj0EAwQwgZQxCzAJBgNVBAYTAklFMRAwDgYDVQQIDAdJcmVsYW5kMQ8wDQYDVQQHDAZEdWJsaW4xITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDENMAsGA1UECwwETGFiczEPMA0GA1UEAwwGbXNjb3R0MR8wHQYJKoZIhvcNAQkBFhBtc2NvdHRAaW5kaWdvLmllMB4XDTE1MTIwMTEzMjkxN1oXDTE3MTEzMDEzMjkxN1owYTELMAkGA1UEBhMCSUUxEDAOBgNVBAgMB0lyZWxhbmQxDzANBgNVBAcMBkR1YmxpbjERMA8GA1UECgwIQ2VydGlWb3gxDTALBgNVBAsMBExhYnMxDTALBgNVBAMMBE1pa2UwgZswEAYHKoZIzj0CAQYFK4EEACMDgYYABAAva/N4kP2LMSGJZ5tvULlfdNx2M/+xYeCrQkuFmY8sG+mdcUAaSx819fztn2jz1nfdTJnuj79AhfUOL8hlTW14BwErp3DnqWa7Y/rpSJP+AsnJ2bZg4yGUDfVy/Q0AQychSzJm2oGRfdliyBIc+2SoQJ/Rf0ZVKVJ5FfRbWUUiKqYUqjAKBggqhkjOPQQDBAOBjAAwgYgCQgFE1Y7d9aBdxpZqROtkdVNG8XBCTSlMX0fISWkSM8ZEiQfYf7YgXzLjk8wHnv04Mv6kmAuV0V1AHs2M0/753CYEfAJCAPZo801McsGe+3jYALrFFw9Wj7KQC/sFEJ7/I+PYyJtrlfTTqmV0IFKdJzjEsk7ic+Gd4Nbs6kIe1GyYbrcyC4wT";
+
+#endif
+
+char io[5000];
+octet IO= {0,sizeof(io),io};
+
+#define MAXMODBYTES 72
+#define MAXFFLEN 16
+
+char sig[MAXMODBYTES*MAXFFLEN];
+octet SIG= {0,sizeof(sig),sig};
+
+char r[MAXMODBYTES];
+octet R= {0,sizeof(r),r};
+
+char s[MAXMODBYTES];
+octet S= {0,sizeof(s),s};
+
+char cakey[MAXMODBYTES*MAXFFLEN];
+octet CAKEY= {0,sizeof(cakey),cakey};
+
+char certkey[MAXMODBYTES*MAXFFLEN];
+octet CERTKEY= {0,sizeof(certkey),certkey};
+
+char h[5000];
+octet H= {0,sizeof(h),h};
+
+char hh[5000];
+octet HH= {0,sizeof(hh),hh};
+
+char hp[RFS_2048];
+octet HP= {0,sizeof(hp),hp};
+
+
+int main()
+{
+    int res,len,sha;
+    int c,ic;
+    rsa_public_key_2048 PK;
+    pktype st,ca,pt;
+
+    printf("First check signature on self-signed cert and extract CA public key\n");
+    OCT_frombase64(&IO,ca_b64);
+    printf("CA Self-Signed Cert= \n");
+    OCT_output(&IO);
+    printf("\n");
+
+    st=X509_extract_cert_sig(&IO,&SIG); // returns signature type
+
+    if (st.type==0)
+    {
+        printf("Unable to extract cert signature\n");
+        return 0;
+    }
+
+    if (st.type==ECC)
+    {
+        OCT_chop(&SIG,&S,SIG.len/2);
+        OCT_copy(&R,&SIG);
+        printf("ECC SIG= \n");
+        OCT_output(&R);
+        OCT_output(&S);
+        printf("\n");
+    }
+
+    if (st.type==RSA)
+    {
+        printf("RSA SIG= \n");
+        OCT_output(&SIG);
+        printf("\n");
+    }
+
+    if (st.hash==H256) printf("Hashed with SHA256\n");
+    if (st.hash==H384) printf("Hashed with SHA384\n");
+    if (st.hash==H512) printf("Hashed with SHA512\n");
+
+// Extract Cert from signed Cert
+
+    c=X509_extract_cert(&IO,&H);
+
+    printf("\nCert= \n");
+    OCT_output(&H);
+    printf("\n");
+
+// show some details
+    printf("Issuer Details\n");
+    ic=X509_find_issuer(&H);
+    c=X509_find_entity_property(&H,&ON,ic,&len);
+    print_out("owner=",&H,c,len);
+    c=X509_find_entity_property(&H,&CN,ic,&len);
+    print_out("country=",&H,c,len);
+    c=X509_find_entity_property(&H,&EN,ic,&len);
+    print_out("email=",&H,c,len);
+    printf("\n");
+
+    ca=X509_extract_public_key(&H,&CAKEY);
+
+    if (ca.type==0)
+    {
+        printf("Not supported by library\n");
+        return 0;
+    }
+    if (ca.type!=st.type)
+    {
+        printf("Not self-signed\n");
+    }
+
+    if (ca.type==ECC)
+    {
+        printf("EXTRACTED ECC PUBLIC KEY= \n");
+        OCT_output(&CAKEY);
+    }
+    if (ca.type==RSA)
+    {
+        printf("EXTRACTED RSA PUBLIC KEY= \n");
+        OCT_output(&CAKEY);
+    }
+    printf("\n");
+
+// Cert is self-signed - so check signature
+
+    printf("Checking Self-Signed Signature\n");
+    if (ca.type==ECC)
+    {
+        if (ca.curve!=CHOICE)
+        {
+            printf("Curve is not supported\n");
+            return 0;
+        }
+        res=ECP_NIST256_PUBLIC_KEY_VALIDATE(1,&CAKEY);
+        if (res!=0)
+        {
+            printf("ECP Public Key is invalid!\n");
+            return 0;
+        }
+        else printf("ECP Public Key is Valid\n");
+
+        sha=0;
+
+        if (st.hash==H256) sha=SHA256;
+        if (st.hash==H384) sha=SHA384;
+        if (st.hash==H512) sha=SHA512;
+        if (st.hash==0)
+        {
+            printf("Hash Function not supported\n");
+            return 0;
+        }
+
+        if (ECP_NIST256_VP_DSA(sha,&CAKEY,&H,&R,&S)!=0)
+        {
+            printf("***ECDSA Verification Failed\n");
+            return 0;
+        }
+        else
+            printf("ECDSA Signature/Verification succeeded \n");
+    }
+
+    if (ca.type==RSA)
+    {
+		if (ca.curve!=2048)
+		{
+            printf("RSA bit size is not supported\n");
+            return 0;
+		}
+        PK.e=65537; // assuming this!
+        RSA_2048_fromOctet(PK.n,&CAKEY);
+
+        sha=0;
+
+        if (st.hash==H256) sha=SHA256;
+        if (st.hash==H384) sha=SHA384;
+        if (st.hash==H512) sha=SHA512;
+        if (st.hash==0)
+        {
+            printf("Hash Function not supported\n");
+            return 0;
+        }
+        PKCS15(sha,&H,&HP);
+
+        RSA_2048_ENCRYPT(&PK,&SIG,&HH);
+
+        if (OCT_comp(&HP,&HH))
+            printf("RSA Signature/Verification succeeded \n");
+        else
+        {
+            printf("***RSA Verification Failed\n");
+            return 0;
+        }
+    }
+
+    printf("\nNext check CA signature on cert, and extract public key\n");
+
+    OCT_frombase64(&IO,cert_b64);
+    printf("Example Cert= \n");
+    OCT_output(&IO);
+    printf("\n");
+
+    st=X509_extract_cert_sig(&IO,&SIG);
+
+    if (st.type==0)
+    {
+        printf("Unable to check cert signature\n");
+        return 0;
+    }
+
+    if (st.type==ECC)
+    {
+        OCT_chop(&SIG,&S,SIG.len/2);
+        OCT_copy(&R,&SIG);
+        printf("SIG= \n");
+        OCT_output(&R);
+
+        OCT_output(&S);
+
+        printf("\n");
+    }
+
+    if (st.type==RSA)
+    {
+        printf("SIG= \n");
+        OCT_output(&SIG);
+        printf("\n");
+    }
+
+    c=X509_extract_cert(&IO,&H);
+
+    printf("Cert= \n");
+    OCT_output(&H);
+    printf("\n");
+
+    printf("Subject Details\n");
+    ic=X509_find_subject(&H);
+    c=X509_find_entity_property(&H,&ON,ic,&len);
+    print_out("owner=",&H,c,len);
+    c=X509_find_entity_property(&H,&CN,ic,&len);
+    print_out("country=",&H,c,len);
+    c=X509_find_entity_property(&H,&EN,ic,&len);
+    print_out("email=",&H,c,len);
+    printf("\n");
+
+    ic=X509_find_validity(&H);
+    c=X509_find_start_date(&H,ic);
+    print_date("start date= ",&H,c);
+    c=X509_find_expiry_date(&H,ic);
+    print_date("expiry date=",&H,c);
+    printf("\n");
+
+    pt=X509_extract_public_key(&H,&CERTKEY);
+
+    if (pt.type==0)
+    {
+        printf("Not supported by library\n");
+        return 0;
+    }
+
+    if (pt.type==ECC)
+    {
+        printf("EXTRACTED ECC PUBLIC KEY= \n");
+        OCT_output(&CERTKEY);
+    }
+    if (pt.type==RSA)
+    {
+        printf("EXTRACTED RSA PUBLIC KEY= \n");
+        OCT_output(&CERTKEY);
+    }
+
+    printf("\n");
+
+    /* Check CA signature */
+
+    if (ca.type==ECC)
+    {
+        printf("Checking CA's ECC Signature on Cert\n");
+        res=ECP_NIST256_PUBLIC_KEY_VALIDATE(1,&CAKEY);
+        if (res!=0)
+            printf("ECP Public Key is invalid!\n");
+        else printf("ECP Public Key is Valid\n");
+
+        sha=0;
+
+        if (st.hash==H256) sha=SHA256;
+        if (st.hash==H384) sha=SHA384;
+        if (st.hash==H512) sha=SHA512;
+        if (st.hash==0)
+        {
+            printf("Hash Function not supported\n");
+            return 0;
+        }
+
+        if (ECP_NIST256_VP_DSA(sha,&CAKEY,&H,&R,&S)!=0)
+            printf("***ECDSA Verification Failed\n");
+        else
+            printf("ECDSA Signature/Verification succeeded \n");
+    }
+
+    if (ca.type==RSA)
+    {
+        printf("Checking CA's RSA Signature on Cert\n");
+        PK.e=65537; // assuming this!
+        RSA_2048_fromOctet(PK.n,&CAKEY);
+
+        sha=0;
+
+        if (st.hash==H256) sha=SHA256;
+        if (st.hash==H384) sha=SHA384;
+        if (st.hash==H512) sha=SHA512;
+        if (st.hash==0)
+        {
+            printf("Hash Function not supported\n");
+            return 0;
+        }
+        PKCS15(sha,&H,&HP);
+
+        RSA_2048_ENCRYPT(&PK,&SIG,&HH);
+
+        if (OCT_comp(&HP,&HH))
+            printf("RSA Signature/Verification succeeded \n");
+        else
+            printf("***RSA Verification Failed\n");
+
+    }
+
+    return 0;
+}
+
+#endif
diff --git a/version3/cpp/x509.h b/version3/cpp/x509.h
new file mode 100644
index 0000000..b845ab3
--- /dev/null
+++ b/version3/cpp/x509.h
@@ -0,0 +1,115 @@
+/*
+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.
+*/
+
+/* AMCL x509 header file */
+
+/**
+ * @file x509.h
+ * @author Mike Scott and Kealan McCusker
+ * @date 19th May 2015
+ * @brief X509 function Header File
+ *
+ * defines structures
+ * declares functions
+ *
+ */
+
+#ifndef X509_H
+#define X509_H
+
+using namespace amcl;
+
+/**
+ * @brief Public key type
+ */
+typedef struct
+{
+    int type;  /**< signature type (ECC or RSA) */
+    int hash;  /**< hash type */
+    int curve; /**< elliptic curve used or RSA key length in bits  */
+} pktype;
+
+
+/* X.509 functions */
+/** @brief Extract certificate signature
+ *
+	@param c an X.509 certificate
+	@param s the extracted signature
+	@return 0 on failure, or indicator of signature type (ECC or RSA)
+
+*/
+extern pktype X509_extract_cert_sig(octet *c,octet *s);
+/** @brief
+ *
+	@param sc a signed certificate
+	@param c the extracted certificate
+	@return 0 on failure
+*/
+extern int X509_extract_cert(octet *sc,octet *c);
+/** @brief
+ *
+	@param c an X.509 certificate
+	@param k the extracted key
+	@return 0 on failure, or indicator of public key type (ECC or RSA)
+*/
+extern pktype X509_extract_public_key(octet *c,octet *k);
+/** @brief
+ *
+	@param c an X.509 certificate
+	@return 0 on failure, or pointer to issuer field in cert
+*/
+extern int X509_find_issuer(octet *c);
+/** @brief
+ *
+	@param c an X.509 certificate
+	@return 0 on failure, or pointer to validity field in cert
+*/
+extern int X509_find_validity(octet *c);
+/** @brief
+ *
+	@param c an X.509 certificate
+	@return 0 on failure, or pointer to subject field in cert
+*/
+extern int X509_find_subject(octet *c);
+/** @brief
+ *
+	@param c an X.509 certificate
+	@param S is OID of property we are looking for
+	@param s is a pointer to the section of interest in the cert
+	@param f is pointer to the length of the property
+	@return 0 on failure, or pointer to the property
+*/
+extern int X509_find_entity_property(octet *c,octet *S,int s,int *f);
+/** @brief
+ *
+	@param c an X.509 certificate
+	@param s is a pointer to the start of the validity field
+	@return 0 on failure, or pointer to the start date
+*/
+extern int X509_find_start_date(octet *c,int s);
+/** @brief
+ *
+	@param c an X.509 certificate
+	@param s is a pointer to the start of the validity field
+	@return 0 on failure, or pointer to the expiry date
+*/
+extern int X509_find_expiry_date(octet *c,int s);
+
+
+#endif
diff --git a/version3/curves.txt b/version3/curves.txt
new file mode 100644
index 0000000..aab40e6
--- /dev/null
+++ b/version3/curves.txt
@@ -0,0 +1,35 @@
+Here we briefly describe the supported curves
+
+1. ED25519 - This is the Bernstein et al Edwards curve https://ed25519.cr.yp.to/ed25519-20110926.pdf
+2. C25519 - The original Bernstein Montgomery curve https://cr.yp.to/ecdh/curve25519-20060209.pdf
+3. NIST256 - The NIST standard 256-bit curve secp256r1 http://www.secg.org/SEC2-Ver-1.0.pdf
+4. BRAINPOOL - The 256-bit Brainpool twisted curve P256r1 http://www.ecc-brainpool.org/download/Domain-parameters.pdf
+5. ANNSI - French standard 256-bit curve https://safecurves.cr.yp.to/
+6. HIFIVE - Our own suggested curve https://eprint.iacr.org/2015/991
+7. GOLDILOCKS - New standard 448-bit curve https://eprint.iacr.org/2015/625
+8. NIST384 - The NIST standard 384-bit curve secp384r1 http://www.secg.org/SEC2-Ver-1.0.pdf
+9. C41417 - An efficient high-security 414-bit curve https://eprint.iacr.org/2014/526
+10. NIST521 - The NIST standard 521-bit curve secp521r1 http://www.secg.org/SEC2-Ver-1.0.pdf
+11-16. The Microsoft NUMS suggested standard curves - https://www.microsoft.com/en-us/research/publication/selecting-elliptic-curves-for-cryptography-an-efficiency-and-security-analysis/
+17. SEC256K1 - The other NIST standard Bitcoin curve
+
+Pairing-friendly curves
+
+Note that efforts to standardise these curves seem to have stalled, probably due to new insights
+into their true security. There seems to be a move from BN curves to BLS curves for 128-bit
+security and above.
+
+18. BN254 - The Nogami BN curve - https://eprint.iacr.org/2005/133
+19. BN254CX - The CertiVox standard BN curve
+20. BLS383 - Our own suggested new standard curve, a GT-Strong 383-bit BLS12 curve - https://eprint.iacr.org/2002/088
+21. BLS381 - The zk-SNARK BLS12 standard curve - https://blog.z.cash/new-snark-curve/
+22. FP256BN - An ISO standard 256-bit BN curve, as recommended for use by FIDO - https://tools.ietf.org/pdf/draft-kasamatsu-bncurves-02.pdf
+23. FP512BN - An ISO standard 512-bit BN curve, as recommended for use by FIDO - https://tools.ietf.org/pdf/draft-kasamatsu-bncurves-02.pdf
+24. BLS461 - A 461 bit BLS12 curve suggested by Barbulescu and Duquesne https://eprint.iacr.org/2017/334
+
+25. BLS24 - An experimental (approx AES-192 bit security) BLS24 GT-Strong curve
+26. BLS48 - An experimental (approx AES-256 bit security) BLS48 GT-Strong curve
+
+Note that it is quite possible to add new curves, and some programs are supplied to assist in the process.
+Let us know if you have a particular request - mike.scott@miracl.com
+
diff --git a/version3/go/AES.go b/version3/go/AES.go
new file mode 100644
index 0000000..df12bae
--- /dev/null
+++ b/version3/go/AES.go
@@ -0,0 +1,634 @@
+/*
+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.
+*/
+
+/* AES Encryption */ 
+
+package amcl
+
+//import "fmt"
+
+const AES_ECB int=0
+const AES_CBC int=1
+const AES_CFB1 int=2
+const AES_CFB2 int=3
+const AES_CFB4 int=5
+const AES_OFB1 int=14
+const AES_OFB2 int=15
+const AES_OFB4 int=17
+const AES_OFB8 int=21
+const AES_OFB16 int=29
+const AES_CTR1 int=30
+const AES_CTR2 int=31
+const AES_CTR4 int=33 
+const AES_CTR8 int=37 
+const AES_CTR16 int=45 
+
+var aes_InCo = [...]byte {0xB,0xD,0x9,0xE}  /* Inverse Coefficients */
+
+var aes_ptab = [...]byte {
+     1, 3, 5, 15, 17, 51, 85, 255, 26, 46, 114, 150, 161, 248, 19, 53,
+     95, 225, 56, 72, 216, 115, 149, 164, 247, 2, 6, 10, 30, 34, 102, 170,
+     229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217, 112, 144, 171, 230, 49,
+     83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104, 184, 211, 110, 178, 205,
+     76, 212, 103, 169, 224, 59, 77, 215, 98, 166, 241, 8, 24, 40, 120, 136,
+     131, 158, 185, 208, 107, 189, 220, 127, 129, 152, 179, 206, 73, 219, 118, 154,
+     181, 196, 87, 249, 16, 48, 80, 240, 11, 29, 39, 105, 187, 214, 97, 163,
+     254, 25, 43, 125, 135, 146, 173, 236, 47, 113, 147, 174, 233, 32, 96, 160,
+     251, 22, 58, 78, 210, 109, 183, 194, 93, 231, 50, 86, 250, 21, 63, 65,
+     195, 94, 226, 61, 71, 201, 64, 192, 91, 237, 44, 116, 156, 191, 218, 117,
+     159, 186, 213, 100, 172, 239, 42, 126, 130, 157, 188, 223, 122, 142, 137, 128,
+     155, 182, 193, 88, 232, 35, 101, 175, 234, 37, 111, 177, 200, 67, 197, 84,
+     252, 31, 33, 99, 165, 244, 7, 9, 27, 45, 119, 153, 176, 203, 70, 202,
+     69, 207, 74, 222, 121, 139, 134, 145, 168, 227, 62, 66, 198, 81, 243, 14,
+     18, 54, 90, 238, 41, 123, 141, 140, 143, 138, 133, 148, 167, 242, 13, 23,
+     57, 75, 221, 124, 132, 151, 162, 253, 28, 36, 108, 180, 199, 82, 246, 1}
+
+var aes_ltab = [...]byte {
+      0, 255, 25, 1, 50, 2, 26, 198, 75, 199, 27, 104, 51, 238, 223, 3,
+     100, 4, 224, 14, 52, 141, 129, 239, 76, 113, 8, 200, 248, 105, 28, 193,
+     125, 194, 29, 181, 249, 185, 39, 106, 77, 228, 166, 114, 154, 201, 9, 120,
+     101, 47, 138, 5, 33, 15, 225, 36, 18, 240, 130, 69, 53, 147, 218, 142,
+     150, 143, 219, 189, 54, 208, 206, 148, 19, 92, 210, 241, 64, 70, 131, 56,
+     102, 221, 253, 48, 191, 6, 139, 98, 179, 37, 226, 152, 34, 136, 145, 16,
+     126, 110, 72, 195, 163, 182, 30, 66, 58, 107, 40, 84, 250, 133, 61, 186,
+     43, 121, 10, 21, 155, 159, 94, 202, 78, 212, 172, 229, 243, 115, 167, 87,
+     175, 88, 168, 80, 244, 234, 214, 116, 79, 174, 233, 213, 231, 230, 173, 232,
+     44, 215, 117, 122, 235, 22, 11, 245, 89, 203, 95, 176, 156, 169, 81, 160,
+     127, 12, 246, 111, 23, 196, 73, 236, 216, 67, 31, 45, 164, 118, 123, 183,
+     204, 187, 62, 90, 251, 96, 177, 134, 59, 82, 161, 108, 170, 85, 41, 157,
+     151, 178, 135, 144, 97, 190, 220, 252, 188, 149, 207, 205, 55, 63, 91, 209,
+     83, 57, 132, 60, 65, 162, 109, 71, 20, 42, 158, 93, 86, 242, 211, 171,
+     68, 17, 146, 217, 35, 32, 46, 137, 180, 124, 184, 38, 119, 153, 227, 165,
+     103, 74, 237, 222, 197, 49, 254, 24, 13, 99, 140, 128, 192, 247, 112, 7}
+   
+
+var aes_fbsub = [...]byte {
+     99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118,
+     202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192,
+     183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21,
+     4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117,
+     9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132,
+     83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207,
+     208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168,
+     81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210,
+     205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115,
+     96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219,
+     224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121,
+     231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8,
+     186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138,
+     112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158,
+     225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223,
+     140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22}
+    
+var aes_rbsub = [...]byte {
+     82, 9, 106, 213, 48, 54, 165, 56, 191, 64, 163, 158, 129, 243, 215, 251,
+     124, 227, 57, 130, 155, 47, 255, 135, 52, 142, 67, 68, 196, 222, 233, 203,
+     84, 123, 148, 50, 166, 194, 35, 61, 238, 76, 149, 11, 66, 250, 195, 78,
+     8, 46, 161, 102, 40, 217, 36, 178, 118, 91, 162, 73, 109, 139, 209, 37,
+     114, 248, 246, 100, 134, 104, 152, 22, 212, 164, 92, 204, 93, 101, 182, 146,
+     108, 112, 72, 80, 253, 237, 185, 218, 94, 21, 70, 87, 167, 141, 157, 132,
+     144, 216, 171, 0, 140, 188, 211, 10, 247, 228, 88, 5, 184, 179, 69, 6,
+     208, 44, 30, 143, 202, 63, 15, 2, 193, 175, 189, 3, 1, 19, 138, 107,
+     58, 145, 17, 65, 79, 103, 220, 234, 151, 242, 207, 206, 240, 180, 230, 115,
+     150, 172, 116, 34, 231, 173, 53, 133, 226, 249, 55, 232, 28, 117, 223, 110,
+     71, 241, 26, 113, 29, 41, 197, 137, 111, 183, 98, 14, 170, 24, 190, 27,
+     252, 86, 62, 75, 198, 210, 121, 32, 154, 219, 192, 254, 120, 205, 90, 244,
+     31, 221, 168, 51, 136, 7, 199, 49, 177, 18, 16, 89, 39, 128, 236, 95,
+     96, 81, 127, 169, 25, 181, 74, 13, 45, 229, 122, 159, 147, 201, 156, 239,
+     160, 224, 59, 77, 174, 42, 245, 176, 200, 235, 187, 60, 131, 83, 153, 97,
+     23, 43, 4, 126, 186, 119, 214, 38, 225, 105, 20, 99, 85, 33, 12, 125}
+    
+
+var aes_rco = [...]byte {1,2,4,8,16,32,64,128,27,54,108,216,171,77,154,47}
+
+var aes_ftable = [...]uint32 {
+    0xa56363c6,0x847c7cf8,0x997777ee,0x8d7b7bf6,0xdf2f2ff,0xbd6b6bd6,
+    0xb16f6fde,0x54c5c591,0x50303060,0x3010102,0xa96767ce,0x7d2b2b56,
+    0x19fefee7,0x62d7d7b5,0xe6abab4d,0x9a7676ec,0x45caca8f,0x9d82821f,
+    0x40c9c989,0x877d7dfa,0x15fafaef,0xeb5959b2,0xc947478e,0xbf0f0fb,
+    0xecadad41,0x67d4d4b3,0xfda2a25f,0xeaafaf45,0xbf9c9c23,0xf7a4a453,
+    0x967272e4,0x5bc0c09b,0xc2b7b775,0x1cfdfde1,0xae93933d,0x6a26264c,
+    0x5a36366c,0x413f3f7e,0x2f7f7f5,0x4fcccc83,0x5c343468,0xf4a5a551,
+    0x34e5e5d1,0x8f1f1f9,0x937171e2,0x73d8d8ab,0x53313162,0x3f15152a,
+    0xc040408,0x52c7c795,0x65232346,0x5ec3c39d,0x28181830,0xa1969637,
+    0xf05050a,0xb59a9a2f,0x907070e,0x36121224,0x9b80801b,0x3de2e2df,
+    0x26ebebcd,0x6927274e,0xcdb2b27f,0x9f7575ea,0x1b090912,0x9e83831d,
+    0x742c2c58,0x2e1a1a34,0x2d1b1b36,0xb26e6edc,0xee5a5ab4,0xfba0a05b,
+    0xf65252a4,0x4d3b3b76,0x61d6d6b7,0xceb3b37d,0x7b292952,0x3ee3e3dd,
+    0x712f2f5e,0x97848413,0xf55353a6,0x68d1d1b9,0x0,0x2cededc1,
+    0x60202040,0x1ffcfce3,0xc8b1b179,0xed5b5bb6,0xbe6a6ad4,0x46cbcb8d,
+    0xd9bebe67,0x4b393972,0xde4a4a94,0xd44c4c98,0xe85858b0,0x4acfcf85,
+    0x6bd0d0bb,0x2aefefc5,0xe5aaaa4f,0x16fbfbed,0xc5434386,0xd74d4d9a,
+    0x55333366,0x94858511,0xcf45458a,0x10f9f9e9,0x6020204,0x817f7ffe,
+    0xf05050a0,0x443c3c78,0xba9f9f25,0xe3a8a84b,0xf35151a2,0xfea3a35d,
+    0xc0404080,0x8a8f8f05,0xad92923f,0xbc9d9d21,0x48383870,0x4f5f5f1,
+    0xdfbcbc63,0xc1b6b677,0x75dadaaf,0x63212142,0x30101020,0x1affffe5,
+    0xef3f3fd,0x6dd2d2bf,0x4ccdcd81,0x140c0c18,0x35131326,0x2fececc3,
+    0xe15f5fbe,0xa2979735,0xcc444488,0x3917172e,0x57c4c493,0xf2a7a755,
+    0x827e7efc,0x473d3d7a,0xac6464c8,0xe75d5dba,0x2b191932,0x957373e6,
+    0xa06060c0,0x98818119,0xd14f4f9e,0x7fdcdca3,0x66222244,0x7e2a2a54,
+    0xab90903b,0x8388880b,0xca46468c,0x29eeeec7,0xd3b8b86b,0x3c141428,
+    0x79dedea7,0xe25e5ebc,0x1d0b0b16,0x76dbdbad,0x3be0e0db,0x56323264,
+    0x4e3a3a74,0x1e0a0a14,0xdb494992,0xa06060c,0x6c242448,0xe45c5cb8,
+    0x5dc2c29f,0x6ed3d3bd,0xefacac43,0xa66262c4,0xa8919139,0xa4959531,
+    0x37e4e4d3,0x8b7979f2,0x32e7e7d5,0x43c8c88b,0x5937376e,0xb76d6dda,
+    0x8c8d8d01,0x64d5d5b1,0xd24e4e9c,0xe0a9a949,0xb46c6cd8,0xfa5656ac,
+    0x7f4f4f3,0x25eaeacf,0xaf6565ca,0x8e7a7af4,0xe9aeae47,0x18080810,
+    0xd5baba6f,0x887878f0,0x6f25254a,0x722e2e5c,0x241c1c38,0xf1a6a657,
+    0xc7b4b473,0x51c6c697,0x23e8e8cb,0x7cdddda1,0x9c7474e8,0x211f1f3e,
+    0xdd4b4b96,0xdcbdbd61,0x868b8b0d,0x858a8a0f,0x907070e0,0x423e3e7c,
+    0xc4b5b571,0xaa6666cc,0xd8484890,0x5030306,0x1f6f6f7,0x120e0e1c,
+    0xa36161c2,0x5f35356a,0xf95757ae,0xd0b9b969,0x91868617,0x58c1c199,
+    0x271d1d3a,0xb99e9e27,0x38e1e1d9,0x13f8f8eb,0xb398982b,0x33111122,
+    0xbb6969d2,0x70d9d9a9,0x898e8e07,0xa7949433,0xb69b9b2d,0x221e1e3c,
+    0x92878715,0x20e9e9c9,0x49cece87,0xff5555aa,0x78282850,0x7adfdfa5,
+    0x8f8c8c03,0xf8a1a159,0x80898909,0x170d0d1a,0xdabfbf65,0x31e6e6d7,
+    0xc6424284,0xb86868d0,0xc3414182,0xb0999929,0x772d2d5a,0x110f0f1e,
+    0xcbb0b07b,0xfc5454a8,0xd6bbbb6d,0x3a16162c}
+
+var aes_rtable = [...]uint32 {
+    0x50a7f451,0x5365417e,0xc3a4171a,0x965e273a,0xcb6bab3b,0xf1459d1f,
+    0xab58faac,0x9303e34b,0x55fa3020,0xf66d76ad,0x9176cc88,0x254c02f5,
+    0xfcd7e54f,0xd7cb2ac5,0x80443526,0x8fa362b5,0x495ab1de,0x671bba25,
+    0x980eea45,0xe1c0fe5d,0x2752fc3,0x12f04c81,0xa397468d,0xc6f9d36b,
+    0xe75f8f03,0x959c9215,0xeb7a6dbf,0xda595295,0x2d83bed4,0xd3217458,
+    0x2969e049,0x44c8c98e,0x6a89c275,0x78798ef4,0x6b3e5899,0xdd71b927,
+    0xb64fe1be,0x17ad88f0,0x66ac20c9,0xb43ace7d,0x184adf63,0x82311ae5,
+    0x60335197,0x457f5362,0xe07764b1,0x84ae6bbb,0x1ca081fe,0x942b08f9,
+    0x58684870,0x19fd458f,0x876cde94,0xb7f87b52,0x23d373ab,0xe2024b72,
+    0x578f1fe3,0x2aab5566,0x728ebb2,0x3c2b52f,0x9a7bc586,0xa50837d3,
+    0xf2872830,0xb2a5bf23,0xba6a0302,0x5c8216ed,0x2b1ccf8a,0x92b479a7,
+    0xf0f207f3,0xa1e2694e,0xcdf4da65,0xd5be0506,0x1f6234d1,0x8afea6c4,
+    0x9d532e34,0xa055f3a2,0x32e18a05,0x75ebf6a4,0x39ec830b,0xaaef6040,
+    0x69f715e,0x51106ebd,0xf98a213e,0x3d06dd96,0xae053edd,0x46bde64d,
+    0xb58d5491,0x55dc471,0x6fd40604,0xff155060,0x24fb9819,0x97e9bdd6,
+    0xcc434089,0x779ed967,0xbd42e8b0,0x888b8907,0x385b19e7,0xdbeec879,
+    0x470a7ca1,0xe90f427c,0xc91e84f8,0x0,0x83868009,0x48ed2b32,
+    0xac70111e,0x4e725a6c,0xfbff0efd,0x5638850f,0x1ed5ae3d,0x27392d36,
+    0x64d90f0a,0x21a65c68,0xd1545b9b,0x3a2e3624,0xb1670a0c,0xfe75793,
+    0xd296eeb4,0x9e919b1b,0x4fc5c080,0xa220dc61,0x694b775a,0x161a121c,
+    0xaba93e2,0xe52aa0c0,0x43e0223c,0x1d171b12,0xb0d090e,0xadc78bf2,
+    0xb9a8b62d,0xc8a91e14,0x8519f157,0x4c0775af,0xbbdd99ee,0xfd607fa3,
+    0x9f2601f7,0xbcf5725c,0xc53b6644,0x347efb5b,0x7629438b,0xdcc623cb,
+    0x68fcedb6,0x63f1e4b8,0xcadc31d7,0x10856342,0x40229713,0x2011c684,
+    0x7d244a85,0xf83dbbd2,0x1132f9ae,0x6da129c7,0x4b2f9e1d,0xf330b2dc,
+    0xec52860d,0xd0e3c177,0x6c16b32b,0x99b970a9,0xfa489411,0x2264e947,
+    0xc48cfca8,0x1a3ff0a0,0xd82c7d56,0xef903322,0xc74e4987,0xc1d138d9,
+    0xfea2ca8c,0x360bd498,0xcf81f5a6,0x28de7aa5,0x268eb7da,0xa4bfad3f,
+    0xe49d3a2c,0xd927850,0x9bcc5f6a,0x62467e54,0xc2138df6,0xe8b8d890,
+    0x5ef7392e,0xf5afc382,0xbe805d9f,0x7c93d069,0xa92dd56f,0xb31225cf,
+    0x3b99acc8,0xa77d1810,0x6e639ce8,0x7bbb3bdb,0x97826cd,0xf418596e,
+    0x1b79aec,0xa89a4f83,0x656e95e6,0x7ee6ffaa,0x8cfbc21,0xe6e815ef,
+    0xd99be7ba,0xce366f4a,0xd4099fea,0xd67cb029,0xafb2a431,0x31233f2a,
+    0x3094a5c6,0xc066a235,0x37bc4e74,0xa6ca82fc,0xb0d090e0,0x15d8a733,
+    0x4a9804f1,0xf7daec41,0xe50cd7f,0x2ff69117,0x8dd64d76,0x4db0ef43,
+    0x544daacc,0xdf0496e4,0xe3b5d19e,0x1b886a4c,0xb81f2cc1,0x7f516546,
+    0x4ea5e9d,0x5d358c01,0x737487fa,0x2e410bfb,0x5a1d67b3,0x52d2db92,
+    0x335610e9,0x1347d66d,0x8c61d79a,0x7a0ca137,0x8e14f859,0x893c13eb,
+    0xee27a9ce,0x35c961b7,0xede51ce1,0x3cb1477a,0x59dfd29c,0x3f73f255,
+    0x79ce1418,0xbf37c773,0xeacdf753,0x5baafd5f,0x146f3ddf,0x86db4478,
+    0x81f3afca,0x3ec468b9,0x2c342438,0x5f40a3c2,0x72c31d16,0xc25e2bc,
+    0x8b493c28,0x41950dff,0x7101a839,0xdeb30c08,0x9ce4b4d8,0x90c15664,
+    0x6184cb7b,0x70b632d5,0x745c6c48,0x4257b8d0}
+
+type AES struct {
+	Nk int
+	Nr int
+	mode int
+	fkey [60]uint32
+	rkey [60]uint32
+	f [16]byte
+}
+
+/* Rotates 32-bit word left by 1, 2 or 3 byte  */
+
+func aes_ROTL8(x uint32) uint32 {
+	return (((x)<<8)|((x)>>24))
+}
+
+func aes_ROTL16(x uint32) uint32 {
+	return (((x)<<16)|((x)>>16))
+}
+
+func aes_ROTL24(x uint32) uint32 {
+	return (((x)<<24)|((x)>>8))
+}
+
+func aes_pack(b [4]byte) uint32 { /* pack bytes into a 32-bit Word */
+        return ((uint32(b[3])&0xff)<<24)|((uint32(b[2])&0xff)<<16)|((uint32(b[1])&0xff)<<8)|(uint32(b[0])&0xff)
+}
+  
+func aes_unpack(a uint32) [4]byte { /* unpack bytes from a word */
+        var b=[4]byte{byte(a&0xff),byte((a>>8)&0xff),byte((a>>16)&0xff),byte((a>>24)&0xff)}
+	return b;
+}
+  
+func aes_bmul(x byte,y byte) byte { /* x.y= AntiLog(Log(x) + Log(y)) */
+    
+        ix:=int(x)&0xff
+        iy:=int(y)&0xff
+        lx:=int(aes_ltab[ix])&0xff
+        ly:=int(aes_ltab[iy])&0xff
+    
+        if x != 0 && y != 0 {
+		return aes_ptab[(lx+ly)%255]
+	} else {return byte(0)}
+}
+  
+func aes_SubByte(a uint32) uint32 {
+        b:=aes_unpack(a)
+        b[0]=aes_fbsub[int(b[0])]
+        b[1]=aes_fbsub[int(b[1])]
+        b[2]=aes_fbsub[int(b[2])]
+        b[3]=aes_fbsub[int(b[3])]
+        return aes_pack(b);
+}    
+
+func aes_product(x uint32,y uint32) byte { /* dot product of two 4-byte arrays */
+        xb:=aes_unpack(x)
+        yb:=aes_unpack(y)
+    
+        return (aes_bmul(xb[0],yb[0])^aes_bmul(xb[1],yb[1])^aes_bmul(xb[2],yb[2])^aes_bmul(xb[3],yb[3]))
+}
+
+func aes_InvMixCol(x uint32) uint32 { /* matrix Multiplication */
+        var b [4]byte
+        m:=aes_pack(aes_InCo)
+        b[3]=aes_product(m,x)
+        m=aes_ROTL24(m)
+        b[2]=aes_product(m,x)
+        m=aes_ROTL24(m)
+        b[1]=aes_product(m,x)
+        m=aes_ROTL24(m)
+        b[0]=aes_product(m,x)
+        var y=aes_pack(b)
+        return y
+}
+
+func aes_increment(f []byte) {
+	for i:=0;i<16;i++ {
+		f[i]++
+		if f[i]!=0 {break}
+	}
+}
+
+/* reset cipher */
+func (A *AES) Reset(m int,iv []byte) { /* reset mode, or reset iv */
+	A.mode=m;
+        for i:=0;i<16;i++ {A.f[i]=0}
+        if (A.mode != AES_ECB) && (iv != nil) {
+            for i:=0;i<16;i++ {A.f[i]=iv[i]}
+	}
+}
+
+func (A *AES) Init(m int,nk int,key []byte,iv []byte) bool { 
+/* Key Scheduler. Create expanded encryption key */
+	var CipherKey [8]uint32
+        var b [4]byte
+        nk/=4
+	if nk!=4 && nk!=6 && nk!=8 {return false}
+	nr:=6+nk
+	A.Nk=nk
+	A.Nr=nr
+        A.Reset(m,iv);
+        N:=4*(nr+1)
+        
+        j:=0
+        for  i:=0;i<nk;i++ {
+            for k:=0;k<4;k++ {b[k]=key[j+k]}
+            CipherKey[i]=aes_pack(b);
+            j+=4;
+        }
+        for i:=0;i<nk;i++ {A.fkey[i]=CipherKey[i]}
+        j=nk
+        for k:=0;j<N;k++ {
+            A.fkey[j]=A.fkey[j-nk]^aes_SubByte(aes_ROTL24(A.fkey[j-1]))^uint32(aes_rco[k])
+            for i:=1;i<nk && (i+j)<N;i++ {
+                A.fkey[i+j]=A.fkey[i+j-nk]^A.fkey[i+j-1]
+            }
+            j+=nk
+        }
+        
+        /* now for the expanded decrypt key in reverse order */
+        
+        for j:=0;j<4;j++ {A.rkey[j+N-4]=A.fkey[j]}
+        for i:=4;i<N-4;i+=4 {
+            k:=N-4-i;
+            for j:=0;j<4;j++ {A.rkey[k+j]=aes_InvMixCol(A.fkey[i+j])}
+        }
+        for j:=N-4;j<N;j++ {A.rkey[j-N+4]=A.fkey[j]}
+	return true
+}
+
+func NewAES() *AES {
+	var A=new(AES)
+	return A
+}
+
+func (A *AES) Getreg() [16]byte {
+        var ir [16]byte
+        for i:=0;i<16;i++ {ir[i]=A.f[i]}
+        return ir
+}
+
+    /* Encrypt a single block */
+func (A *AES) ecb_encrypt(buff []byte) {
+        var b [4]byte
+        var p [4]uint32
+        var q [4]uint32
+    
+        j:=0
+        for i:=0;i<4;i++ {
+            for k:=0;k<4;k++ {b[k]=buff[j+k]}
+            p[i]=aes_pack(b)
+            p[i]^=A.fkey[i]
+            j+=4
+        }
+    
+        k:=4
+    
+    /* State alternates between p and q */
+        for i:=1;i<A.Nr;i++ {
+            q[0]=A.fkey[k]^aes_ftable[int(p[0]&0xff)]^aes_ROTL8(aes_ftable[int((p[1]>>8)&0xff)])^aes_ROTL16(aes_ftable[int((p[2]>>16)&0xff)])^aes_ROTL24(aes_ftable[int((p[3]>>24)&0xff)])
+            
+            q[1]=A.fkey[k+1]^aes_ftable[int(p[1]&0xff)]^aes_ROTL8(aes_ftable[int((p[2]>>8)&0xff)])^aes_ROTL16(aes_ftable[int((p[3]>>16)&0xff)])^aes_ROTL24(aes_ftable[int((p[0]>>24)&0xff)])
+            
+            q[2]=A.fkey[k+2]^aes_ftable[int(p[2]&0xff)]^aes_ROTL8(aes_ftable[int((p[3]>>8)&0xff)])^aes_ROTL16(aes_ftable[int((p[0]>>16)&0xff)])^aes_ROTL24(aes_ftable[int((p[1]>>24)&0xff)])
+            
+            q[3]=A.fkey[k+3]^aes_ftable[int(p[3]&0xff)]^aes_ROTL8(aes_ftable[int((p[0]>>8)&0xff)])^aes_ROTL16(aes_ftable[int((p[1]>>16)&0xff)])^aes_ROTL24(aes_ftable[int((p[2]>>24)&0xff)])
+            
+            k+=4;
+            for j=0;j<4;j++ {
+		t:=p[j]; p[j]=q[j]; q[j]=t
+            }
+        }
+    
+    /* Last Round */
+    
+        q[0]=A.fkey[k]^uint32(aes_fbsub[int(p[0]&0xff)])^aes_ROTL8(uint32(aes_fbsub[int((p[1]>>8)&0xff)]))^aes_ROTL16(uint32(aes_fbsub[int((p[2]>>16)&0xff)]))^aes_ROTL24(uint32(aes_fbsub[int((p[3]>>24)&0xff)]))
+    
+        q[1]=A.fkey[k+1]^uint32(aes_fbsub[int(p[1]&0xff)])^aes_ROTL8(uint32(aes_fbsub[int((p[2]>>8)&0xff)]))^aes_ROTL16(uint32(aes_fbsub[int((p[3]>>16)&0xff)]))^aes_ROTL24(uint32(aes_fbsub[int((p[0]>>24)&0xff)]))
+    
+        q[2]=A.fkey[k+2]^uint32(aes_fbsub[int(p[2]&0xff)])^aes_ROTL8(uint32(aes_fbsub[int((p[3]>>8)&0xff)]))^aes_ROTL16(uint32(aes_fbsub[int((p[0]>>16)&0xff)]))^aes_ROTL24(uint32(aes_fbsub[int((p[1]>>24)&0xff)]))
+    
+        q[3]=A.fkey[k+3]^uint32(aes_fbsub[int(p[3]&0xff)])^aes_ROTL8(uint32(aes_fbsub[int((p[0]>>8)&0xff)]))^aes_ROTL16(uint32(aes_fbsub[int((p[1]>>16)&0xff)]))^aes_ROTL24(uint32(aes_fbsub[int((p[2]>>24)&0xff)]))
+    
+        j=0
+        for i:=0;i<4;i++ {
+            b=aes_unpack(q[i])
+            for k=0;k<4;k++ {buff[j+k]=b[k]}
+            j+=4
+        }
+}
+    
+    /* Decrypt a single block */
+func (A *AES)  ecb_decrypt(buff []byte) {
+        var b [4]byte
+        var p [4]uint32
+        var q [4]uint32
+    
+        j:=0
+        for i:=0;i<4;i++ {
+            for k:=0;k<4;k++ {b[k]=buff[j+k]}
+            p[i]=aes_pack(b)
+            p[i]^=A.rkey[i]
+            j+=4
+        }
+    
+        k:=4
+    
+    /* State alternates between p and q */
+        for i:=1;i<A.Nr;i++ {
+            
+            q[0]=A.rkey[k]^aes_rtable[int(p[0]&0xff)]^aes_ROTL8(aes_rtable[int((p[3]>>8)&0xff)])^aes_ROTL16(aes_rtable[int((p[2]>>16)&0xff)])^aes_ROTL24(aes_rtable[int((p[1]>>24)&0xff)])
+            
+            q[1]=A.rkey[k+1]^aes_rtable[int(p[1]&0xff)]^aes_ROTL8(aes_rtable[int((p[0]>>8)&0xff)])^aes_ROTL16(aes_rtable[int((p[3]>>16)&0xff)])^aes_ROTL24(aes_rtable[int((p[2]>>24)&0xff)])
+            
+        
+            q[2]=A.rkey[k+2]^aes_rtable[int(p[2]&0xff)]^aes_ROTL8(aes_rtable[int((p[1]>>8)&0xff)])^aes_ROTL16(aes_rtable[int((p[0]>>16)&0xff)])^aes_ROTL24(aes_rtable[int((p[3]>>24)&0xff)])
+       
+            q[3]=A.rkey[k+3]^aes_rtable[int(p[3]&0xff)]^aes_ROTL8(aes_rtable[int((p[2]>>8)&0xff)])^aes_ROTL16(aes_rtable[int((p[1]>>16)&0xff)])^aes_ROTL24(aes_rtable[int((p[0]>>24)&0xff)])
+            
+    
+            k+=4;
+            for j:=0;j<4;j++ {
+			t:=p[j]; p[j]=q[j]; q[j]=t
+            }
+        }
+    
+    /* Last Round */
+        
+        q[0]=A.rkey[k]^uint32(aes_rbsub[int(p[0]&0xff)])^aes_ROTL8(uint32(aes_rbsub[int((p[3]>>8)&0xff)]))^aes_ROTL16(uint32(aes_rbsub[int((p[2]>>16)&0xff)]))^aes_ROTL24(uint32(aes_rbsub[int((p[1]>>24)&0xff)]))
+        
+        q[1]=A.rkey[k+1]^uint32(aes_rbsub[int(p[1]&0xff)])^aes_ROTL8(uint32(aes_rbsub[int((p[0]>>8)&0xff)]))^aes_ROTL16(uint32(aes_rbsub[int((p[3]>>16)&0xff)]))^aes_ROTL24(uint32(aes_rbsub[int((p[2]>>24)&0xff)]))
+        
+        
+        q[2]=A.rkey[k+2]^uint32(aes_rbsub[int(p[2]&0xff)])^aes_ROTL8(uint32(aes_rbsub[int((p[1]>>8)&0xff)]))^aes_ROTL16(uint32(aes_rbsub[int((p[0]>>16)&0xff)]))^aes_ROTL24(uint32(aes_rbsub[int((p[3]>>24)&0xff)]))
+
+        q[3]=A.rkey[k+3]^uint32(aes_rbsub[int((p[3])&0xff)])^aes_ROTL8(uint32(aes_rbsub[int((p[2]>>8)&0xff)]))^aes_ROTL16(uint32(aes_rbsub[int((p[1]>>16)&0xff)]))^aes_ROTL24(uint32(aes_rbsub[int((p[0]>>24)&0xff)]))
+    
+        j=0
+        for i:=0;i<4;i++ {
+            b=aes_unpack(q[i]);
+            for k:=0;k<4;k++ {buff[j+k]=b[k]}
+            j+=4
+        }
+}
+
+/* Encrypt using selected mode of operation */
+func (A *AES) Encrypt(buff []byte) uint32 {
+	var st [16]byte
+    
+    // Supported Modes of Operation
+    
+        var fell_off uint32=0
+        switch A.mode {
+        case AES_ECB:
+            A.ecb_encrypt(buff)
+            return 0
+        case AES_CBC:
+            for j:=0;j<16;j++ {buff[j]^=A.f[j]}
+            A.ecb_encrypt(buff)
+            for j:=0;j<16;j++ {A.f[j]=buff[j]}
+            return 0
+    
+        case AES_CFB1:
+            fallthrough
+        case AES_CFB2:
+            fallthrough
+        case AES_CFB4:
+            bytes:=A.mode-AES_CFB1+1
+            for j:=0;j<bytes;j++ {fell_off=(fell_off<<8)|uint32(A.f[j])}
+            for j:=0;j<16;j++ {st[j]=A.f[j]}
+            for j:=bytes;j<16;j++ {A.f[j-bytes]=A.f[j]}
+            A.ecb_encrypt(st[:])
+            for j:=0;j<bytes;j++ {
+		buff[j]^=st[j]
+		A.f[16-bytes+j]=buff[j]
+            }
+            return fell_off
+    
+        case AES_OFB1:
+            fallthrough
+        case AES_OFB2:
+            fallthrough
+        case AES_OFB4:
+            fallthrough
+        case AES_OFB8:
+            fallthrough
+        case AES_OFB16:
+    
+            bytes:=A.mode-AES_OFB1+1
+            A.ecb_encrypt(A.f[:])
+            for j:=0;j<bytes;j++ {buff[j]^=A.f[j]}
+            return 0;
+    
+	case AES_CTR1:
+	    fallthrough
+	case AES_CTR2:
+	    fallthrough
+	case AES_CTR4:
+	    fallthrough
+	case AES_CTR8:
+	    fallthrough
+	case AES_CTR16:
+	    bytes:=A.mode-AES_CTR1+1
+	    for j:=0;j<16;j++ {st[j]=A.f[j]}
+	    A.ecb_encrypt(st[:])
+	    for j:=0;j<bytes;j++ {buff[j]^=st[j]}
+	    aes_increment(A.f[:])
+	    return 0
+
+        default:
+            return 0
+        }
+}
+    
+    /* Decrypt using selected mode of operation */
+func (A *AES) Decrypt(buff []byte) uint32 {
+
+	var st [16]byte
+        
+        // Supported Modes of Operation
+        
+        var fell_off uint32=0
+        switch A.mode {
+        case AES_ECB:
+            A.ecb_decrypt(buff);
+            return 0;
+        case AES_CBC:
+            for j:=0;j<16;j++ {
+		st[j]=A.f[j];
+		A.f[j]=buff[j];
+            }
+            A.ecb_decrypt(buff);
+            for j:=0;j<16;j++ {
+		buff[j]^=st[j];
+		st[j]=0
+            }
+            return 0
+        case AES_CFB1:
+            fallthrough
+        case AES_CFB2:
+            fallthrough
+        case AES_CFB4:
+            bytes:=A.mode-AES_CFB1+1;
+            for j:=0;j<bytes;j++ {fell_off=(fell_off<<8)|uint32(A.f[j])}
+            for j:=0;j<16;j++ {st[j]=A.f[j]}
+            for j:=bytes;j<16;j++ {A.f[j-bytes]=A.f[j]}
+            A.ecb_encrypt(st[:])
+            for j:=0;j<bytes;j++ {
+		A.f[16-bytes+j]=buff[j]
+		buff[j]^=st[j]
+            }
+            return fell_off
+        case AES_OFB1:
+            fallthrough
+        case AES_OFB2:
+            fallthrough
+        case AES_OFB4:
+            fallthrough
+        case AES_OFB8:
+            fallthrough
+        case AES_OFB16:
+            bytes:=A.mode-AES_OFB1+1
+            A.ecb_encrypt(A.f[:]);
+            for j:=0;j<bytes;j++ {buff[j]^=A.f[j]}
+            return 0
+
+	case AES_CTR1:
+	    fallthrough
+	case AES_CTR2:
+	    fallthrough
+	case AES_CTR4:
+	    fallthrough
+	case AES_CTR8:
+	    fallthrough
+	case AES_CTR16:
+	    bytes:=A.mode-AES_CTR1+1
+	    for j:=0;j<16;j++ {st[j]=A.f[j]}
+	    A.ecb_encrypt(st[:])
+	    for j:=0;j<bytes;j++ {buff[j]^=st[j]}
+	    aes_increment(A.f[:])
+	    return 0
+
+        default:
+            return 0;
+        }
+    } 
+    
+/* Clean up and delete left-overs */
+func (A *AES) End() { // clean up
+    for i:=0;i<4*(A.Nr+1);i++ {A.fkey[i]=0; A.rkey[i]=0}
+    for i:=0;i<16;i++ {A.f[i]=0}
+}
+/*
+func main() {
+	var key [32]byte
+	var block [16]byte
+	var iv [16]byte
+
+	for i:=0;i<32;i++ {key[i]=0}
+	key[0]=1
+	for i:=0;i<16;i++ {iv[i]=byte(i)}
+	for i:=0;i<16;i++ {block[i]=byte(i)}
+
+	a:=NewAES()
+
+	a.Init(AES_CTR16,32,key[:],iv[:])
+	fmt.Printf("Plain= \n")
+	for i:=0;i<16;i++  {fmt.Printf("%02X ", block[i]&0xff)}
+	fmt.Printf("\n")
+
+	a.Encrypt(block[:])
+
+	fmt.Printf("Encrypt= \n") 
+	for i:=0;i<16;i++  {fmt.Printf("%02X ", block[i]&0xff)}
+	fmt.Printf("\n")
+
+	a.Reset(AES_CTR16,iv[:])
+	a.Decrypt(block[:])
+
+	fmt.Printf("Decrypt= \n") 
+	for i:=0;i<16;i++  {fmt.Printf("%02X ", block[i]&0xff)}
+	fmt.Printf("\n")
+
+	a.End();
+}
+*/
diff --git a/version3/go/ARCH32.go b/version3/go/ARCH32.go
new file mode 100644
index 0000000..59379fc
--- /dev/null
+++ b/version3/go/ARCH32.go
@@ -0,0 +1,28 @@
+/*
+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.
+*/
+
+/* AMCL BIG number class */ 
+
+package XXX
+
+type Chunk int32
+type DChunk int64
+
+const CHUNK int=32	/* Set word size */
+
diff --git a/version3/go/ARCH64.go b/version3/go/ARCH64.go
new file mode 100644
index 0000000..2cf1f2b
--- /dev/null
+++ b/version3/go/ARCH64.go
@@ -0,0 +1,26 @@
+/*
+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.
+*/
+
+/* AMCL BIG number class */ 
+
+package XXX
+
+type Chunk int64
+const CHUNK int=64	/* Set word size */
+
diff --git a/version3/go/BIG32.go b/version3/go/BIG32.go
new file mode 100644
index 0000000..368b536
--- /dev/null
+++ b/version3/go/BIG32.go
@@ -0,0 +1,961 @@
+/*
+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.
+*/
+
+/* AMCL BIG number class */ 
+
+package XXX
+
+import "strconv"
+import "github.com/milagro-crypto/amcl/version3/go/amcl"
+
+//import "fmt"
+
+const MODBYTES uint=@NB@
+const BASEBITS uint=@BASE@
+
+const NLEN int=int((1+((8*MODBYTES-1)/BASEBITS)))
+const DNLEN int=2*NLEN
+const BMASK Chunk= ((Chunk(1)<<BASEBITS)-1)
+const HBITS uint=(BASEBITS/2)
+const HMASK Chunk= ((Chunk(1)<<HBITS)-1)
+//const NEXCESS int=4
+const NEXCESS int=(1<<(uint(CHUNK)-BASEBITS-1));
+
+const BIGBITS int=int(MODBYTES*8)
+
+
+type BIG struct {
+	w [NLEN]Chunk
+}
+
+type DBIG struct {
+	w [2*NLEN]Chunk
+}
+
+/***************** 32-bit specific code ****************/
+
+
+/* First the 32/64-bit dependent BIG code */
+/* Note that because of the lack of a 128-bit integer, 32 and 64-bit code needs to be done differently */
+
+/* return a*b as DBIG */
+func mul(a *BIG,b *BIG) *DBIG {
+	c:=NewDBIG()
+	var d [NLEN]DChunk
+
+	for i:=0;i<NLEN;i++ {
+		d[i]=DChunk(a.w[i])*DChunk(b.w[i])
+	}
+	s:=d[0]
+	t:=s; c.w[0]=Chunk(t)&BMASK; co:=t>>BASEBITS
+
+	for k:=1;k<NLEN;k++ {
+		s+=d[k]; t=co+s; for i:=k;i>=1+k/2;i-- {t+=DChunk(a.w[i]-a.w[k-i])*DChunk(b.w[k-i]-b.w[i])}; c.w[k]=Chunk(t)&BMASK; co=t>>BASEBITS
+	}
+
+	for k:=NLEN;k<2*NLEN-1;k++ {
+		s-=d[k-NLEN]; t=co+s; for i:=NLEN-1;i>=1+k/2;i-- {t+=DChunk(a.w[i]-a.w[k-i])*DChunk(b.w[k-i]-b.w[i])}; c.w[k]=Chunk(t)&BMASK; co=t>>BASEBITS
+	}
+	c.w[2*NLEN-1]=Chunk(co)
+
+	return c
+}
+
+/* return a^2 as DBIG */
+func sqr(a *BIG) *DBIG {
+	c:=NewDBIG()
+
+	t:=DChunk(a.w[0])*DChunk(a.w[0])
+	c.w[0]=Chunk(t)&BMASK; co:=t>>BASEBITS
+
+
+	for j:=1;j<NLEN-1; {
+		t=DChunk(a.w[j])*DChunk(a.w[0])
+		for i:=1; i<(j+1)/2; i++ {t+=DChunk(a.w[j-i])*DChunk(a.w[i]) }
+		t+=t; t+=co
+		c.w[j]=Chunk(t)&BMASK
+		co=t>>BASEBITS
+		j++
+		t=DChunk(a.w[j])*DChunk(a.w[0]); 
+		for i:=1; i<(j+1)/2; i++ {t+=DChunk(a.w[j-i])*DChunk(a.w[i]) }
+		t+=t; t+=co 
+		t+=DChunk(a.w[j/2])*DChunk(a.w[j/2]); 
+		c.w[j]=Chunk(t)&BMASK;
+		co=t>>BASEBITS; j++
+	}
+
+	for j:=NLEN-1+(NLEN%2);j<DNLEN-3; {
+		t=DChunk(a.w[NLEN-1])*DChunk(a.w[j-NLEN+1]); 
+		for i:=j-NLEN+2; i<(j+1)/2; i++ {t+=DChunk(a.w[j-i])*DChunk(a.w[i]);  }
+		t+=t; t+=co 
+		c.w[j]=Chunk(t)&BMASK;
+		co=t>>BASEBITS; j++
+		t=DChunk(a.w[NLEN-1])*DChunk(a.w[j-NLEN+1]); 
+		for i:=j-NLEN+2; i<(j+1)/2; i++ {t+=DChunk(a.w[j-i])*DChunk(a.w[i]);  }
+		t+=t;  t+=co 
+		t+=DChunk(a.w[j/2])*DChunk(a.w[j/2]); 
+		c.w[j]=Chunk(t)&BMASK;
+		co=t>>BASEBITS; j++
+	}
+
+	t=DChunk(a.w[NLEN-2])*DChunk(a.w[NLEN-1]);
+	t+=t; t+=co
+	c.w[DNLEN-3]=Chunk(t)&BMASK
+	co=t>>BASEBITS
+	
+	t=DChunk(a.w[NLEN-1])*DChunk(a.w[NLEN-1])+co
+	c.w[DNLEN-2]=Chunk(t)&BMASK;
+	co=t>>BASEBITS
+	c.w[DNLEN-1]=Chunk(co)
+
+	return c
+}
+
+func monty(m* BIG, mc Chunk,d* DBIG) *BIG {
+	var dd [NLEN]DChunk
+
+	var v [NLEN]Chunk
+	b:=NewBIG()
+
+	t:=DChunk(d.w[0]); v[0]=(Chunk(t)*mc)&BMASK; t+=DChunk(v[0])*DChunk(m.w[0]); c:=(t>>BASEBITS)+DChunk(d.w[1]); s:=DChunk(0)
+
+	for k:=1;k<NLEN;k++ {
+		t=c+s+DChunk(v[0])*DChunk(m.w[k])
+		for i:=k-1;i>k/2;i-- {t+=DChunk(v[k-i]-v[i])*DChunk(m.w[i]-m.w[k-i])}
+		v[k]=(Chunk(t)*mc)&BMASK; t+=DChunk(v[k])*DChunk(m.w[0]); c=(t>>BASEBITS)+DChunk(d.w[k+1])
+		dd[k]=DChunk(v[k])*DChunk(m.w[k]); s+=dd[k]
+	}
+	for k:=NLEN;k<2*NLEN-1;k++ {
+		t=c+s;
+		for i:=NLEN-1;i>=1+k/2;i-- {t+=DChunk(v[k-i]-v[i])*DChunk(m.w[i]-m.w[k-i])}
+		b.w[k-NLEN]=Chunk(t)&BMASK; c=(t>>BASEBITS)+DChunk(d.w[k+1]); s-=dd[k-NLEN+1]
+	}
+	b.w[NLEN-1]=Chunk(c)&BMASK;	
+//	b.norm()
+	return b
+}
+
+
+/* set this[i]+=x*y+c, and return high part */
+func muladd(a Chunk,b Chunk,c Chunk,r Chunk) (Chunk,Chunk) {
+	var prod=DChunk(a)*DChunk(b)+DChunk(c)+DChunk(r);
+	bot:=Chunk(prod)&BMASK;
+	top:=Chunk(prod>>BASEBITS);
+	return top,bot
+}
+
+/***************************************************************************/
+
+
+
+func (r *BIG) get(i int) Chunk {
+	return r.w[i] 
+}
+
+func (r *BIG) set(i int,x Chunk) {
+	r.w[i]=x	
+}
+
+func (r *BIG) xortop(x Chunk) {
+	r.w[NLEN-1]^=x
+}
+
+/* normalise BIG - force all digits < 2^BASEBITS */
+func (r *BIG) norm() Chunk {
+	carry:=Chunk(0)
+	for i:=0;i<NLEN-1;i++ {
+		d:=r.w[i]+carry
+		r.w[i]=d&BMASK
+		carry=d>>BASEBITS
+	}
+	r.w[NLEN-1]=(r.w[NLEN-1]+carry)
+	return (r.w[NLEN-1]>>((8*MODBYTES)%BASEBITS))  
+}
+
+/* Shift right by less than a word */
+func (r *BIG) fshr(k uint) int {
+	w:=r.w[0]&((Chunk(1)<<k)-1) /* shifted out part */
+	for i:=0;i<NLEN-1;i++ {
+		r.w[i]=(r.w[i]>>k)|((r.w[i+1]<<(BASEBITS-k))&BMASK)
+	}
+	r.w[NLEN-1]=r.w[NLEN-1]>>k
+	return int(w)
+}
+
+/* Shift right by less than a word */
+func (r *BIG) fshl(k uint) int {
+	r.w[NLEN-1]=((r.w[NLEN-1]<<k))|(r.w[NLEN-2]>>(BASEBITS-k))
+	for i:=NLEN-2;i>0;i-- {
+		r.w[i]=((r.w[i]<<k)&BMASK)|(r.w[i-1]>>(BASEBITS-k))
+	}
+	r.w[0]=(r.w[0]<<k)&BMASK
+	return int(r.w[NLEN-1]>>((8*MODBYTES)%BASEBITS)) /* return excess - only used in ff.c */
+}
+
+func NewBIG() *BIG {
+	b:=new(BIG)
+	for i:=0;i<NLEN;i++ {
+		b.w[i]=0
+	}
+	return b
+}
+
+func NewBIGints(x [NLEN]Chunk) *BIG {
+	b:=new(BIG)
+	for i:=0;i<NLEN;i++ {
+		b.w[i]=x[i]
+	}
+	return b	
+}
+
+func NewBIGint(x int) *BIG {
+	b:=new(BIG)
+	b.w[0]=Chunk(x)
+	for i:=1;i<NLEN;i++ {
+		b.w[i]=0
+	}
+	return b
+}
+
+func NewBIGcopy(x *BIG) *BIG {
+	b:=new(BIG)
+	for i:=0;i<NLEN;i++ {
+		b.w[i]=x.w[i]
+	}
+	return b
+}
+
+func NewBIGdcopy(x *DBIG) *BIG {
+	b:=new(BIG)
+	for i:=0;i<NLEN;i++ {
+		b.w[i]=x.w[i]
+	}
+	return b
+}
+
+/* test for zero */
+func (r *BIG) iszilch() bool {
+	for i:=0;i<NLEN;i++ {
+		if r.w[i]!=0 {return false}
+	}
+	return true; 
+}
+
+/* set to zero */
+func (r *BIG) zero() {
+	for i:=0;i<NLEN;i++ {
+		r.w[i]=0
+	}
+}
+
+/* Test for equal to one */
+func (r *BIG) isunity() bool {
+	for i:=1;i<NLEN;i++ {
+		if r.w[i]!=0 {return false}
+	}
+	if r.w[0]!=1 {return false}
+	return true;
+}
+
+
+/* set to one */
+func (r *BIG) one() {
+	r.w[0]=1
+	for i:=1;i<NLEN;i++ {
+		r.w[i]=0
+	}
+}
+
+/* Copy from another BIG */
+func (r *BIG) copy(x *BIG) {
+	for i:=0;i<NLEN;i++ {
+		r.w[i]=x.w[i]
+	}
+}
+
+/* Copy from another DBIG */
+func (r *BIG) dcopy(x *DBIG) {
+	for i:=0;i<NLEN;i++ {
+		r.w[i]=x.w[i]
+	}
+}
+
+/* Conditional swap of two bigs depending on d using XOR - no branches */
+func (r *BIG) cswap(b *BIG,d int) {
+	c:=Chunk(d)
+	c=^(c-1)
+
+	for i:=0;i<NLEN;i++ {
+		t:=c&(r.w[i]^b.w[i])
+		r.w[i]^=t
+		b.w[i]^=t
+	}
+}
+
+func (r *BIG) cmove(g *BIG,d int){
+	b:=Chunk(-d)
+
+	for i:=0;i<NLEN;i++ {
+		r.w[i]^=(r.w[i]^g.w[i])&b
+	}
+}
+
+/* general shift right */
+func (r *BIG) shr(k uint) {
+	n:=(k%BASEBITS)
+	m:=int(k/BASEBITS)	
+	for i:=0;i<NLEN-m-1;i++ {
+		r.w[i]=(r.w[m+i]>>n)|((r.w[m+i+1]<<(BASEBITS-n))&BMASK)
+	}
+	r.w[NLEN-m-1]=r.w[NLEN-1]>>n;
+	for i:=NLEN-m;i<NLEN;i++ {r.w[i]=0}
+}
+
+
+/* general shift left */
+func (r *BIG) shl(k uint) {
+	n:=k%BASEBITS
+	m:=int(k/BASEBITS)
+
+	r.w[NLEN-1]=((r.w[NLEN-1-m]<<n))
+	if NLEN>=m+2 {r.w[NLEN-1]|=(r.w[NLEN-m-2]>>(BASEBITS-n))}
+	for i:=NLEN-2;i>m;i-- {
+		r.w[i]=((r.w[i-m]<<n)&BMASK)|(r.w[i-m-1]>>(BASEBITS-n))
+	}
+	r.w[m]=(r.w[0]<<n)&BMASK; 
+	for i:=0;i<m;i++ {r.w[i]=0}
+}
+
+/* return number of bits */
+func (r *BIG) nbits() int {	
+	t:=NewBIGcopy(r)
+	k:=NLEN-1
+	t.norm()
+	for (k>=0 && t.w[k]==0) {k--}
+	if k<0 {return 0}
+	bts:=int(BASEBITS)*k;
+	c:=t.w[k];
+	for c!=0 {c/=2; bts++}
+	return bts
+}
+
+/* Convert to Hex String */
+func (r *BIG) ToString() string {
+	s:=""
+	len:=r.nbits()
+
+	if len%4==0 {
+		len/=4
+	} else {
+		len/=4 
+		len++
+
+	}
+	MB:=int(MODBYTES*2)
+	if len<MB {len=MB}
+
+	for i:=len-1;i>=0;i-- {
+		b:=NewBIGcopy(r)
+		
+		b.shr(uint(i*4))
+		s+=strconv.FormatInt(int64(b.w[0]&15),16)
+	}
+	return s
+}
+
+func (r *BIG) add(x *BIG) {
+	for i:=0;i<NLEN;i++ {
+		r.w[i]=r.w[i]+x.w[i] 
+	}
+}
+
+func (r *BIG) or(x *BIG) {
+	for i:=0;i<NLEN;i++ {
+		r.w[i]=r.w[i]|x.w[i] 
+	}
+}
+
+/* return this+x */
+func (r *BIG) Plus(x *BIG) *BIG {
+	s:=new(BIG)
+	for i:=0;i<NLEN;i++ {
+		s.w[i]=r.w[i]+x.w[i];
+	}
+	return s;
+}
+
+/* this+=x, where x is int */
+func (r *BIG) inc(x int) {
+	r.norm();
+	r.w[0]+=Chunk(x);
+}
+
+/* this*=c and catch overflow in DBIG */
+func (r *BIG) pxmul(c int) *DBIG {
+	m:=NewDBIG()	
+	carry:=Chunk(0)
+	for j:=0;j<NLEN;j++ {
+		carry,m.w[j]=muladd(r.w[j],Chunk(c),carry,m.w[j])
+	}
+	m.w[NLEN]=carry;		
+	return m;
+}
+
+/* return this-x */
+func (r *BIG) Minus(x *BIG) *BIG {
+	d:=new(BIG)
+	for i:=0;i<NLEN;i++ {
+		d.w[i]=r.w[i]-x.w[i] 
+	}
+	return d;
+}
+
+/* this-=x */
+func (r *BIG) sub(x *BIG) {
+	for i:=0;i<NLEN;i++ {
+		r.w[i]=r.w[i]-x.w[i] 
+	}
+} 
+
+/* reverse subtract this=x-this */ 
+func (r *BIG) rsub(x *BIG) {
+	for i:=0;i<NLEN;i++ {
+		r.w[i]=x.w[i]-r.w[i] 
+	}
+} 
+
+/* this-=x, where x is int */
+func (r *BIG) dec(x int) {
+	r.norm();
+	r.w[0]-=Chunk(x)
+} 
+
+/* this*=x, where x is small int<NEXCESS */
+func (r *BIG) imul(c int) {
+	for i:=0;i<NLEN;i++{ 
+		r.w[i]*=Chunk(c)
+	}
+}
+
+/* this*=x, where x is >NEXCESS */
+func (r *BIG) pmul(c int) Chunk {
+	carry:=Chunk(0)
+//	r.norm();
+	for i:=0;i<NLEN;i++ {
+		ak:=r.w[i]
+		r.w[i]=0
+		carry,r.w[i]=muladd(ak,Chunk(c),carry,r.w[i])
+	}
+	return carry
+}
+
+/* convert this BIG to byte array */
+func (r *BIG) tobytearray(b []byte,n int) {
+	//r.norm();
+	c:=NewBIGcopy(r)
+	c.norm()
+	for i:=int(MODBYTES)-1;i>=0;i-- {
+		b[i+n]=byte(c.w[0])
+		c.fshr(8)
+	}
+}
+
+/* convert from byte array to BIG */
+func frombytearray(b []byte,n int) *BIG {
+	m:=NewBIG();
+	for i:=0;i<int(MODBYTES);i++ {
+		m.fshl(8); m.w[0]+=Chunk(int(b[i+n]&0xff))
+	}
+	return m
+}
+
+func (r *BIG) ToBytes(b []byte) {
+	r.tobytearray(b,0)
+}
+
+func FromBytes(b []byte) *BIG {
+	return frombytearray(b,0)
+}
+
+/* divide by 3 */
+func (r *BIG) div3() int {	
+	carry:=Chunk(0)
+	r.norm();
+	base:=(Chunk(1)<<BASEBITS)
+	for i:=NLEN-1;i>=0;i-- {
+		ak:=(carry*base+r.w[i])
+		r.w[i]=ak/3;
+		carry=ak%3;
+	}
+	return int(carry)
+}
+
+/* return a*b where result fits in a BIG */
+func smul(a *BIG,b *BIG) *BIG {
+	carry:=Chunk(0)
+	c:=NewBIG()
+	for i:=0;i<NLEN;i++ {
+		carry=0;
+		for j:=0;j<NLEN;j++ {
+			if i+j<NLEN {
+				carry,c.w[i+j]=muladd(a.w[i],b.w[j],carry,c.w[i+j])
+				//carry=c.muladd(a.w[i],b.w[j],carry,i+j)
+			}
+		}
+	}
+	return c;
+}
+
+/* Compare a and b, return 0 if a==b, -1 if a<b, +1 if a>b. Inputs must be normalised */
+func Comp(a *BIG,b *BIG) int {
+	for i:=NLEN-1;i>=0;i-- {
+		if a.w[i]==b.w[i] {continue}
+		if a.w[i]>b.w[i] {
+			return 1
+		} else  {return -1}
+	}
+	return 0
+}
+
+/* return parity */
+func (r *BIG) parity() int {
+	return int(r.w[0]%2)
+}
+
+/* return n-th bit */
+func (r *BIG) bit(n int) int {
+	if (r.w[n/int(BASEBITS)]&(Chunk(1)<<(uint(n)%BASEBITS)))>0 {return 1}
+	return 0;
+}
+
+/* return n last bits */
+func (r *BIG) lastbits(n int) int {
+	msk:=(1<<uint(n))-1;
+	r.norm();
+	return (int(r.w[0]))&msk
+}
+
+
+/* set x = x mod 2^m */
+func (r *BIG) mod2m(m uint) {
+	wd:=int(m/BASEBITS)
+	bt:=m%BASEBITS
+	msk:=(Chunk(1)<<bt)-1
+	r.w[wd]&=msk
+	for i:=wd+1;i<NLEN;i++ {r.w[i]=0}
+}
+
+
+
+/* a=1/a mod 2^256. This is very fast! */
+func (r *BIG) invmod2m() {
+	U:=NewBIG()
+	b:=NewBIG()
+	c:=NewBIG()
+
+	U.inc(invmod256(r.lastbits(8)))
+
+	for i:=8;i<BIGBITS;i<<=1 {
+		U.norm()
+		ui:=uint(i)
+		b.copy(r); b.mod2m(ui)
+		t1:=smul(U,b); t1.shr(ui)
+		c.copy(r); c.shr(ui); c.mod2m(ui)
+
+		t2:=smul(U,c); t2.mod2m(ui)
+		t1.add(t2)
+		t1.norm()
+		b=smul(t1,U); t1.copy(b)
+		t1.mod2m(ui)
+
+		t2.one(); t2.shl(ui); t1.rsub(t2); t1.norm()
+		t1.shl(ui)
+		U.add(t1)
+	}
+	U.mod2m(8*MODBYTES)
+	r.copy(U)
+	r.norm()
+}
+
+/* reduce this mod m */
+func (r *BIG) Mod(m1 *BIG) {
+	m:=NewBIGcopy(m1)
+	sr:=NewBIG()
+	r.norm()
+	if Comp(r,m)<0 {return}
+
+	m.fshl(1); k:=1
+
+	for Comp(r,m)>=0 {
+		m.fshl(1)
+		k++;
+	}
+
+	for k>0 {
+		m.fshr(1);
+
+			sr.copy(r)
+			sr.sub(m)
+			sr.norm()
+			r.cmove(sr,int(1-((sr.w[NLEN-1]>>uint(CHUNK-1))&1)));
+/*
+		if Comp(r,m)>=0 {
+			r.sub(m)
+			r.norm()
+		} */
+		k--;
+	}
+}
+
+/* divide this by m */
+func (r *BIG) div(m1 *BIG) {
+	m:=NewBIGcopy(m1)
+	var d int
+	k:=0
+	r.norm();
+	sr:=NewBIG();
+	e:=NewBIGint(1)
+	b:=NewBIGcopy(r)
+	r.zero();
+
+	for (Comp(b,m)>=0) {
+		e.fshl(1)
+		m.fshl(1)
+		k++
+	}
+
+	for k>0 {
+		m.fshr(1)
+		e.fshr(1)
+
+		sr.copy(b);
+		sr.sub(m);
+		sr.norm();
+		d=int(1-((sr.w[NLEN-1]>>uint(CHUNK-1))&1));
+		b.cmove(sr,d);
+		sr.copy(r);
+		sr.add(e);
+		sr.norm();
+		r.cmove(sr,d);
+/*
+		if Comp(b,m)>=0 {
+			r.add(e)
+			r.norm()
+			b.sub(m)
+			b.norm()
+		} */
+		k--
+	}
+}
+
+/* get 8*MODBYTES size random number */
+func random(rng *amcl.RAND) *BIG {
+	m:=NewBIG()
+	var j int=0
+	var r byte=0
+/* generate random BIG */ 
+	for i:=0;i<8*int(MODBYTES);i++   {
+		if j==0 {
+			r=rng.GetByte()
+		} else {r>>=1}
+
+		b:=Chunk(int(r&1))
+		m.shl(1); m.w[0]+=b// m.inc(b)
+		j++; j&=7; 
+	}
+	return m;
+}
+
+/* Create random BIG in portable way, one bit at a time */
+func Randomnum(q *BIG,rng *amcl.RAND) *BIG {
+	d:=NewDBIG();
+	var j int=0
+	var r byte=0
+	for i:=0;i<2*q.nbits();i++ {
+		if (j==0) {
+			r=rng.GetByte();
+		} else {r>>=1}
+
+		b:=Chunk(int(r&1))
+		d.shl(1); d.w[0]+=b// m.inc(b);
+		j++; j&=7 
+	}
+	m:=d.mod(q)
+	return m;
+}
+
+
+/* return NAF value as +/- 1, 3 or 5. x and x3 should be normed. 
+nbs is number of bits processed, and nzs is number of trailing 0s detected */
+/*
+func nafbits(x *BIG,x3 *BIG ,i int) [3]int {
+	var n [3]int
+	var j int
+	nb:=x3.bit(i)-x.bit(i)
+
+
+	n[1]=1
+	n[0]=0
+	if nb==0 {n[0]=0; return n}
+	if i==0 {n[0]=nb; return n}
+	if nb>0 {
+		n[0]=1;
+	} else  {n[0]=(-1)}
+
+	for j=i-1;j>0;j-- {
+		n[1]++
+		n[0]*=2
+		nb=x3.bit(j)-x.bit(j)
+		if nb>0 {n[0]+=1}
+		if nb<0 {n[0]-=1}
+		if (n[0]>5 || n[0] < -5) {break}
+	}
+
+	if n[0]%2!=0 && j!=0 { // backtrack 
+		if nb>0 {n[0]=(n[0]-1)/2}
+		if nb<0 {n[0]=(n[0]+1)/2}
+		n[1]--
+	}
+	for n[0]%2==0 { // remove trailing zeros 
+		n[0]/=2
+		n[2]++
+		n[1]--
+	}
+	return n;
+}
+*/
+
+/* return a*b mod m */
+func Modmul(a1,b1,m *BIG) *BIG {
+	a:=NewBIGcopy(a1)
+	b:=NewBIGcopy(b1)
+	a.Mod(m)
+	b.Mod(m)
+	d:=mul(a,b);
+	return d.mod(m)
+}
+
+/* return a^2 mod m */
+func Modsqr(a1,m *BIG) *BIG {
+	a:=NewBIGcopy(a1)
+	a.Mod(m)
+	d:=sqr(a)
+	return d.mod(m)
+}
+
+/* return -a mod m */
+func Modneg(a1,m *BIG) *BIG {
+	a:=NewBIGcopy(a1)
+	a.Mod(m)
+	return m.Minus(a)
+}
+
+/* Jacobi Symbol (this/p). Returns 0, 1 or -1 */
+func (r *BIG) Jacobi(p *BIG) int {
+	m:=0;
+	t:=NewBIGint(0)
+	x:=NewBIGint(0)
+	n:=NewBIGint(0)
+	zilch:=NewBIGint(0)
+	one:=NewBIGint(1)
+	if (p.parity()==0 || Comp(r,zilch)==0 || Comp(p,one)<=0) {return 0}
+	r.norm()
+	x.copy(r)
+	n.copy(p)
+	x.Mod(p)
+
+	for Comp(n,one)>0 {
+		if Comp(x,zilch)==0 {return 0}
+		n8:=n.lastbits(3)
+		k:=0
+		for x.parity()==0 {
+			k++
+			x.shr(1)
+		}
+		if k%2==1 {m+=(n8*n8-1)/8}
+		m+=(n8-1)*(x.lastbits(2)-1)/4
+		t.copy(n)
+		t.Mod(x)
+		n.copy(x)
+		x.copy(t)
+		m%=2
+
+	}
+	if m==0 {return 1}
+	return -1
+}
+
+/* this=1/this mod p. Binary method */
+func (r *BIG) Invmodp(p *BIG) {
+	r.Mod(p)
+	u:=NewBIGcopy(r)
+
+	v:=NewBIGcopy(p)
+	x1:=NewBIGint(1)
+	x2:=NewBIGint(0)
+	t:=NewBIGint(0)
+	one:=NewBIGint(1)
+	for (Comp(u,one)!=0 && Comp(v,one)!=0) {
+		for u.parity()==0 {
+			u.fshr(1);
+			if x1.parity()!=0 {
+				x1.add(p)
+				x1.norm()
+			}
+			x1.fshr(1)
+		}
+		for v.parity()==0 {
+			v.fshr(1);
+			if x2.parity()!=0 {
+				x2.add(p)
+				x2.norm()
+			}
+			x2.fshr(1)
+		}
+		if Comp(u,v)>=0 {
+			u.sub(v)
+			u.norm()
+			if Comp(x1,x2)>=0 {
+				x1.sub(x2)
+			} else {
+				t.copy(p)
+				t.sub(x2)
+				x1.add(t)
+			}
+			x1.norm()
+		} else {
+			v.sub(u)
+			v.norm()
+			if Comp(x2,x1)>=0 { 
+				x2.sub(x1)
+			} else {
+				t.copy(p)
+				t.sub(x1)
+				x2.add(t)
+			}
+			x2.norm()
+		}
+	}
+	if Comp(u,one)==0 {
+		r.copy(x1)
+	} else {r.copy(x2)}
+}
+
+/* return this^e mod m */
+func (r *BIG) Powmod(e1 *BIG,m *BIG) *BIG {
+	e:=NewBIGcopy(e1)
+	r.norm()
+	e.norm()
+	a:=NewBIGint(1)
+	z:=NewBIGcopy(e)
+	s:=NewBIGcopy(r)
+	for true {
+		bt:=z.parity()
+		z.fshr(1)
+		if bt==1 {a=Modmul(a,s,m)}
+		if z.iszilch() {break}
+		s=Modsqr(s,m)
+	}
+	return a;
+}
+
+/* Arazi and Qi inversion mod 256 */
+func invmod256(a int) int {
+	var t1 int=0
+	c:=(a>>1)&1
+	t1+=c
+	t1&=1
+	t1=2-t1
+	t1<<=1
+	U:=t1+1;
+
+// i=2
+	b:=a&3;
+	t1=U*b; t1>>=2
+	c=(a>>2)&3
+	t2:=(U*c)&3
+	t1+=t2;
+	t1*=U; t1&=3
+	t1=4-t1
+	t1<<=2
+	U+=t1
+
+// i=4
+	b=a&15
+	t1=U*b; t1>>=4
+	c=(a>>4)&15
+	t2=(U*c)&15
+	t1+=t2
+	t1*=U; t1&=15
+	t1=16-t1
+	t1<<=4
+	U+=t1
+
+	return U;
+}
+
+func logb2(w uint32) uint {
+	v:=w
+	v |= (v >> 1)
+	v |= (v >> 2)
+	v |= (v >> 4)
+	v |= (v >> 8)
+	v |= (v >> 16)
+
+	v = v - ((v >> 1) & 0x55555555)                 
+	v = (v & 0x33333333) + ((v >> 2) & 0x33333333)  
+	r:= uint((   ((v + (v >> 4)) & 0xF0F0F0F)   * 0x1010101) >> 24)
+	return (r)
+}
+
+// Optimized combined shift, subtract and norm
+func ssn(r *BIG,a *BIG,m *BIG) int {
+        n:=NLEN-1
+        m.w[0]=(m.w[0]>>1)|((m.w[1]<<(BASEBITS-1))&BMASK)
+	r.w[0]=a.w[0]-m.w[0]
+	carry:=r.w[0]>>BASEBITS
+	r.w[0] &= BMASK
+	for i:=1;i<n;i++  {
+            m.w[i]=(m.w[i]>>1)|((m.w[i+1]<<(BASEBITS-1))&BMASK)
+            r.w[i]=a.w[i]-m.w[i]+carry
+            carry=r.w[i]>>BASEBITS
+            r.w[i] &= BMASK
+        }
+	m.w[n]>>=1
+	r.w[n]=a.w[n]-m.w[n]+carry
+	return int((r.w[n]>>uint(CHUNK-1))&1)
+}
+
+/*
+func main() {
+	a := NewBIGint(3)
+	m := NewBIGints(Modulus)
+
+	fmt.Printf("Modulus= "+m.ToString())
+	fmt.Printf("\n")
+
+
+	e := NewBIGcopy(m);
+	e.dec(1); e.norm();
+	fmt.Printf("Exponent= "+e.ToString())
+	fmt.Printf("\n")
+	a=a.Powmod(e,m);
+	fmt.Printf("Result= "+a.ToString())
+}
+*/
diff --git a/version3/go/BIG64.go b/version3/go/BIG64.go
new file mode 100644
index 0000000..31d17d1
--- /dev/null
+++ b/version3/go/BIG64.go
@@ -0,0 +1,963 @@
+/*
+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.
+*/
+
+/* AMCL BIG number class */ 
+
+package XXX
+
+import "strconv"
+import "github.com/milagro-crypto/amcl/version3/go/amcl"
+
+//import "fmt"
+
+const MODBYTES uint=@NB@
+const BASEBITS uint=@BASE@
+
+const NLEN int=int((1+((8*MODBYTES-1)/BASEBITS)))
+const DNLEN int=2*NLEN
+const BMASK Chunk= ((Chunk(1)<<BASEBITS)-1)
+const HBITS uint=(BASEBITS/2)
+const HMASK Chunk= ((Chunk(1)<<HBITS)-1)
+//const NEXCESS int=4
+const NEXCESS int=(1<<(uint(CHUNK)-BASEBITS-1));
+
+const BIGBITS int=int(MODBYTES*8)
+
+
+type BIG struct {
+	w [NLEN]Chunk
+}
+
+type DBIG struct {
+	w [2*NLEN]Chunk
+}
+
+/*
+func (r *BIG) isok() bool {
+	ok:=true
+	for i:=0;i<NLEN;i++ {
+		if (r.w[i]>>BASEBITS)!=0 {
+			ok=false
+		}
+	}
+	return ok;
+}
+*/
+/***************** 64-bit specific code ****************/
+
+/* First the 32/64-bit dependent BIG code */
+/* Note that because of the lack of a 128-bit integer, 32 and 64-bit code needs to be done differently */
+
+/* return a*b as DBIG */
+func mul(a *BIG,b *BIG) *DBIG {
+	c:=NewDBIG()
+	carry:= Chunk(0)
+//	a.norm()
+//	b.norm()
+
+//	if !a.isok() || !b.isok() {fmt.Printf("Problem in mul\n")}
+
+
+	for i:=0;i<NLEN;i++ {
+		carry=0
+		for j:=0;j<NLEN;j++ {
+			carry,c.w[i+j]=muladd(a.w[i],b.w[j],carry,c.w[i+j])
+			//carry=c.muladd(a.w[i],b.w[j],carry,i+j)
+		}
+		c.w[NLEN+i]=carry
+	}
+	
+	return c
+}
+
+/* return a^2 as DBIG */
+func sqr(a *BIG) *DBIG {
+	c:=NewDBIG()
+	carry:= Chunk(0)
+//	a.norm()
+
+//if !a.isok() {fmt.Printf("Problem in sqr")}
+
+	for i:=0;i<NLEN;i++ {
+		carry=0;
+		for j:=i+1;j<NLEN;j++ {
+			carry,c.w[i+j]=muladd(2*a.w[i],a.w[j],carry,c.w[i+j])
+			//carry=c.muladd(2*a.w[i],a.w[j],carry,i+j)
+		}
+		c.w[NLEN+i]=carry
+	}
+
+	for i:=0;i<NLEN;i++ {
+		top,bot:=muladd(a.w[i],a.w[i],0,c.w[2*i])
+		c.w[2*i]=bot
+		c.w[2*i+1]+=top
+		//c.w[2*i+1]+=c.muladd(a.w[i],a.w[i],0,2*i)
+
+	}
+	c.norm()
+	return c
+}
+
+func monty(md* BIG, mc Chunk,d* DBIG) *BIG {
+	carry:=Chunk(0)
+	m:=Chunk(0)
+	for i:=0;i<NLEN;i++ {
+		if (mc==-1) { 
+			m=(-d.w[i])&BMASK
+		} else {
+			if (mc==1) {
+				m=d.w[i]
+			} else {m=(mc*d.w[i])&BMASK}
+		}
+
+		carry=0
+		for j:=0;j<NLEN;j++ {
+			carry,d.w[i+j]=muladd(m,md.w[j],carry,d.w[i+j])
+				//carry=d.muladd(m,md.w[j],carry,i+j)
+		}
+		d.w[NLEN+i]+=carry
+	}
+
+	b:=NewBIG()
+	for i:=0;i<NLEN;i++ {
+		b.w[i]=d.w[NLEN+i]
+	}
+	b.norm()
+	return b		
+}
+
+/* set this[i]+=x*y+c, and return high part */
+func muladd(a Chunk,b Chunk,c Chunk,r Chunk) (Chunk,Chunk) {
+	x0:=a&HMASK
+	x1:=(a>>HBITS)
+	y0:=b&HMASK;
+	y1:=(b>>HBITS)
+	bot:=x0*y0
+	top:=x1*y1
+	mid:=x0*y1+x1*y0
+	x0=mid&HMASK;
+	x1=(mid>>HBITS)
+	bot+=x0<<HBITS; bot+=c; bot+=r 
+	top+=x1;
+	carry:=bot>>BASEBITS
+	bot&=BMASK
+	top+=carry
+	return top,bot
+}
+
+/************************************************************/
+
+func (r *BIG) get(i int) Chunk {
+	return r.w[i] 
+}
+
+func (r *BIG) set(i int,x Chunk) {
+	r.w[i]=x	
+}
+
+func (r *BIG) xortop(x Chunk) {
+	r.w[NLEN-1]^=x
+}
+
+/* normalise BIG - force all digits < 2^BASEBITS */
+func (r *BIG) norm() Chunk {
+	carry:=Chunk(0)
+	for i:=0;i<NLEN-1;i++ {
+		d:=r.w[i]+carry
+		r.w[i]=d&BMASK
+		carry=d>>BASEBITS
+	}
+	r.w[NLEN-1]=(r.w[NLEN-1]+carry)
+	return (r.w[NLEN-1]>>((8*MODBYTES)%BASEBITS))  
+}
+
+/* Shift right by less than a word */
+func (r *BIG) fshr(k uint) int {
+	w:=r.w[0]&((Chunk(1)<<k)-1) /* shifted out part */
+	for i:=0;i<NLEN-1;i++ {
+		r.w[i]=(r.w[i]>>k)|((r.w[i+1]<<(BASEBITS-k))&BMASK)
+	}
+	r.w[NLEN-1]=r.w[NLEN-1]>>k
+	return int(w)
+}
+
+/* Shift right by less than a word */
+func (r *BIG) fshl(k uint) int {
+	r.w[NLEN-1]=((r.w[NLEN-1]<<k))|(r.w[NLEN-2]>>(BASEBITS-k))
+	for i:=NLEN-2;i>0;i-- {
+		r.w[i]=((r.w[i]<<k)&BMASK)|(r.w[i-1]>>(BASEBITS-k))
+	}
+	r.w[0]=(r.w[0]<<k)&BMASK
+	return int(r.w[NLEN-1]>>((8*MODBYTES)%BASEBITS)) /* return excess - only used in ff.c */
+}
+
+func NewBIG() *BIG {
+	b:=new(BIG)
+	for i:=0;i<NLEN;i++ {
+		b.w[i]=0
+	}
+	return b
+}
+
+func NewBIGints(x [NLEN]Chunk) *BIG {
+	b:=new(BIG)
+	for i:=0;i<NLEN;i++ {
+		b.w[i]=x[i]
+	}
+	return b	
+}
+
+func NewBIGint(x int) *BIG {
+	b:=new(BIG)
+	b.w[0]=Chunk(x)
+	for i:=1;i<NLEN;i++ {
+		b.w[i]=0
+	}
+	return b
+}
+
+func NewBIGcopy(x *BIG) *BIG {
+	b:=new(BIG)
+	for i:=0;i<NLEN;i++ {
+		b.w[i]=x.w[i]
+	}
+	return b
+}
+
+func NewBIGdcopy(x *DBIG) *BIG {
+	b:=new(BIG)
+	for i:=0;i<NLEN;i++ {
+		b.w[i]=x.w[i]
+	}
+	return b
+}
+
+/* test for zero */
+func (r *BIG) iszilch() bool {
+	for i:=0;i<NLEN;i++ {
+		if r.w[i]!=0 {return false}
+	}
+	return true; 
+}
+
+/* set to zero */
+func (r *BIG) zero() {
+	for i:=0;i<NLEN;i++ {
+		r.w[i]=0
+	}
+}
+
+/* Test for equal to one */
+func (r *BIG) isunity() bool {
+	for i:=1;i<NLEN;i++ {
+		if r.w[i]!=0 {return false}
+	}
+	if r.w[0]!=1 {return false}
+	return true;
+}
+
+
+/* set to one */
+func (r *BIG) one() {
+	r.w[0]=1
+	for i:=1;i<NLEN;i++ {
+		r.w[i]=0
+	}
+}
+
+/* Copy from another BIG */
+func (r *BIG) copy(x *BIG) {
+	for i:=0;i<NLEN;i++ {
+		r.w[i]=x.w[i]
+	}
+}
+
+/* Copy from another DBIG */
+func (r *BIG) dcopy(x *DBIG) {
+	for i:=0;i<NLEN;i++ {
+		r.w[i]=x.w[i]
+	}
+}
+
+/* Conditional swap of two bigs depending on d using XOR - no branches */
+func (r *BIG) cswap(b *BIG,d int) {
+	c:=Chunk(d)
+	c=^(c-1)
+
+	for i:=0;i<NLEN;i++ {
+		t:=c&(r.w[i]^b.w[i])
+		r.w[i]^=t
+		b.w[i]^=t
+	}
+}
+
+func (r *BIG) cmove(g *BIG,d int){
+	b:=Chunk(-d)
+
+	for i:=0;i<NLEN;i++ {
+		r.w[i]^=(r.w[i]^g.w[i])&b
+	}
+}
+
+/* general shift right */
+func (r *BIG) shr(k uint) {
+	n:=(k%BASEBITS)
+	m:=int(k/BASEBITS)	
+	for i:=0;i<NLEN-m-1;i++ {
+		r.w[i]=(r.w[m+i]>>n)|((r.w[m+i+1]<<(BASEBITS-n))&BMASK)
+	}
+	r.w[NLEN-m-1]=r.w[NLEN-1]>>n;
+	for i:=NLEN-m;i<NLEN;i++ {r.w[i]=0}
+}
+
+
+/* general shift left */
+func (r *BIG) shl(k uint) {
+	n:=k%BASEBITS
+	m:=int(k/BASEBITS)
+
+	r.w[NLEN-1]=((r.w[NLEN-1-m]<<n))
+	if NLEN>=m+2 {r.w[NLEN-1]|=(r.w[NLEN-m-2]>>(BASEBITS-n))}
+	for i:=NLEN-2;i>m;i-- {
+		r.w[i]=((r.w[i-m]<<n)&BMASK)|(r.w[i-m-1]>>(BASEBITS-n))
+	}
+	r.w[m]=(r.w[0]<<n)&BMASK; 
+	for i:=0;i<m;i++ {r.w[i]=0}
+}
+
+/* return number of bits */
+func (r *BIG) nbits() int {
+	t:=NewBIGcopy(r)
+	k:=NLEN-1
+	t.norm()
+	for (k>=0 && t.w[k]==0) {k--}
+	if k<0 {return 0}
+	bts:=int(BASEBITS)*k;
+	c:=t.w[k];
+	for c!=0 {c/=2; bts++}
+	return bts
+}
+
+/* Convert to Hex String */
+func (r *BIG) ToString() string {
+	s:=""
+	len:=r.nbits()
+
+	if len%4==0 {
+		len/=4
+	} else {
+		len/=4 
+		len++
+
+	}
+	MB:=int(MODBYTES*2)
+	if len<MB {len=MB}
+
+	for i:=len-1;i>=0;i-- {
+		b:=NewBIGcopy(r)
+		
+		b.shr(uint(i*4))
+		s+=strconv.FormatInt(int64(b.w[0]&15),16)
+	}
+	return s
+}
+
+func (r *BIG) add(x *BIG) {
+	for i:=0;i<NLEN;i++ {
+		r.w[i]=r.w[i]+x.w[i] 
+	}
+}
+
+func (r *BIG) or(x *BIG) {
+	for i:=0;i<NLEN;i++ {
+		r.w[i]=r.w[i]|x.w[i] 
+	}
+}
+
+/* return this+x */
+func (r *BIG) Plus(x *BIG) *BIG {
+	s:=new(BIG)
+	for i:=0;i<NLEN;i++ {
+		s.w[i]=r.w[i]+x.w[i];
+	}
+	return s;
+}
+
+/* this+=x, where x is int */
+func (r *BIG) inc(x int) {
+	r.norm();
+	r.w[0]+=Chunk(x);
+}
+
+/* this*=c and catch overflow in DBIG */
+func (r *BIG) pxmul(c int) *DBIG {
+	m:=NewDBIG()	
+	carry:=Chunk(0)
+	for j:=0;j<NLEN;j++ {
+		carry,m.w[j]=muladd(r.w[j],Chunk(c),carry,m.w[j])
+	}
+	m.w[NLEN]=carry;		
+	return m;
+}
+
+/* return this-x */
+func (r *BIG) Minus(x *BIG) *BIG {
+	d:=new(BIG)
+	for i:=0;i<NLEN;i++ {
+		d.w[i]=r.w[i]-x.w[i] 
+	}
+	return d;
+}
+
+/* this-=x */
+func (r *BIG) sub(x *BIG) {
+	for i:=0;i<NLEN;i++ {
+		r.w[i]=r.w[i]-x.w[i] 
+	}
+} 
+
+/* reverse subtract this=x-this */ 
+func (r *BIG) rsub(x *BIG) {
+	for i:=0;i<NLEN;i++ {
+		r.w[i]=x.w[i]-r.w[i] 
+	}
+} 
+
+/* this-=x, where x is int */
+func (r *BIG) dec(x int) {
+	r.norm();
+	r.w[0]-=Chunk(x)
+} 
+
+/* this*=x, where x is small int<NEXCESS */
+func (r *BIG) imul(c int) {
+	for i:=0;i<NLEN;i++{ 
+		r.w[i]*=Chunk(c)
+	}
+}
+
+/* this*=x, where x is >NEXCESS */
+func (r *BIG) pmul(c int) Chunk {
+	carry:=Chunk(0)
+//	r.norm();
+	for i:=0;i<NLEN;i++ {
+		ak:=r.w[i]
+		r.w[i]=0
+		carry,r.w[i]=muladd(ak,Chunk(c),carry,r.w[i])
+	}
+	return carry
+}
+
+/* convert this BIG to byte array */
+func (r *BIG) tobytearray(b []byte,n int) {
+	//r.norm();
+	c:=NewBIGcopy(r)
+	c.norm();
+
+	for i:=int(MODBYTES)-1;i>=0;i-- {
+		b[i+n]=byte(c.w[0])
+		c.fshr(8)
+	}
+}
+
+/* convert from byte array to BIG */
+func frombytearray(b []byte,n int) *BIG {
+	m:=NewBIG();
+	for i:=0;i<int(MODBYTES);i++ {
+		m.fshl(8); m.w[0]+=Chunk(int(b[i+n]&0xff))
+	}
+	return m
+}
+
+func (r *BIG) ToBytes(b []byte) {
+	r.tobytearray(b,0)
+}
+
+func FromBytes(b []byte) *BIG {
+	return frombytearray(b,0)
+}
+
+/* divide by 3 */
+func (r *BIG) div3() int {	
+	carry:=Chunk(0)
+	r.norm();
+	base:=(Chunk(1)<<BASEBITS)
+	for i:=NLEN-1;i>=0;i-- {
+		ak:=(carry*base+r.w[i])
+		r.w[i]=ak/3;
+		carry=ak%3;
+	}
+	return int(carry)
+}
+
+/* return a*b where result fits in a BIG */
+func smul(a *BIG,b *BIG) *BIG {
+	carry:=Chunk(0)
+	c:=NewBIG()
+	for i:=0;i<NLEN;i++ {
+		carry=0;
+		for j:=0;j<NLEN;j++ {
+			if i+j<NLEN {
+				carry,c.w[i+j]=muladd(a.w[i],b.w[j],carry,c.w[i+j])
+				//carry=c.muladd(a.w[i],b.w[j],carry,i+j)
+			}
+		}
+	}
+	return c;
+}
+
+
+
+/* Compare a and b, return 0 if a==b, -1 if a<b, +1 if a>b. Inputs must be normalised */
+func Comp(a *BIG,b *BIG) int {
+	for i:=NLEN-1;i>=0;i-- {
+		if a.w[i]==b.w[i] {continue}
+		if a.w[i]>b.w[i] {
+			return 1
+		} else  {return -1}
+	}
+	return 0
+}
+
+/* return parity */
+func (r *BIG) parity() int {
+	return int(r.w[0]%2)
+}
+
+/* return n-th bit */
+func (r *BIG) bit(n int) int {
+	if (r.w[n/int(BASEBITS)]&(Chunk(1)<<(uint(n)%BASEBITS)))>0 {return 1}
+	return 0;
+}
+
+/* return n last bits */
+func (r *BIG) lastbits(n int) int {
+	msk:=(1<<uint(n))-1;
+	r.norm();
+	return (int(r.w[0]))&msk
+}
+
+
+/* set x = x mod 2^m */
+func (r *BIG) mod2m(m uint) {
+	wd:=int(m/BASEBITS)
+	bt:=m%BASEBITS
+	msk:=(Chunk(1)<<bt)-1
+	r.w[wd]&=msk
+	for i:=wd+1;i<NLEN;i++ {r.w[i]=0}
+}
+
+
+
+/* a=1/a mod 2^256. This is very fast! */
+func (r *BIG) invmod2m() {
+	U:=NewBIG()
+	b:=NewBIG()
+	c:=NewBIG()
+
+	U.inc(invmod256(r.lastbits(8)))
+
+	for i:=8;i<BIGBITS;i<<=1 {
+		U.norm()
+		ui:=uint(i)
+		b.copy(r); b.mod2m(ui)
+		t1:=smul(U,b); t1.shr(ui)
+		c.copy(r); c.shr(ui); c.mod2m(ui)
+
+		t2:=smul(U,c); t2.mod2m(ui)
+		t1.add(t2)
+		t1.norm()
+		b=smul(t1,U); t1.copy(b)
+		t1.mod2m(ui)
+
+		t2.one(); t2.shl(ui); t1.rsub(t2); t1.norm()
+		t1.shl(ui)
+		U.add(t1)
+	}
+	U.mod2m(8*MODBYTES)
+	r.copy(U)
+	r.norm()
+}
+
+/* reduce this mod m */
+func (r *BIG) Mod(m1 *BIG) {
+	m:=NewBIGcopy(m1)
+	sr:=NewBIG()
+	r.norm()
+	if Comp(r,m)<0 {return}
+
+	m.fshl(1); k:=1
+
+	for Comp(r,m)>=0 {
+		m.fshl(1)
+		k++;
+	}
+
+	for k>0 {
+		m.fshr(1);
+
+			sr.copy(r)
+			sr.sub(m)
+			sr.norm()
+			r.cmove(sr,int(1-((sr.w[NLEN-1]>>uint(CHUNK-1))&1)));
+/*
+		if Comp(r,m)>=0 {
+			r.sub(m)
+			r.norm()
+		} */
+		k--;
+	}
+}
+
+/* divide this by m */
+func (r *BIG) div(m1 *BIG) {
+	m:=NewBIGcopy(m1)
+	var d int
+	k:=0
+	r.norm();
+	sr:=NewBIG();
+	e:=NewBIGint(1)
+	b:=NewBIGcopy(r)
+	r.zero();
+
+	for (Comp(b,m)>=0) {
+		e.fshl(1)
+		m.fshl(1)
+		k++
+	}
+
+	for k>0 {
+		m.fshr(1)
+		e.fshr(1)
+
+		sr.copy(b);
+		sr.sub(m);
+		sr.norm();
+		d=int(1-((sr.w[NLEN-1]>>uint(CHUNK-1))&1));
+		b.cmove(sr,d);
+		sr.copy(r);
+		sr.add(e);
+		sr.norm();
+		r.cmove(sr,d);
+/*
+		if Comp(b,m)>=0 {
+			r.add(e)
+			r.norm()
+			b.sub(m)
+			b.norm()
+		} */
+		k--
+	}
+}
+
+/* get 8*MODBYTES size random number */
+func random(rng *amcl.RAND) *BIG {
+	m:=NewBIG()
+	var j int=0
+	var r byte=0
+/* generate random BIG */ 
+	for i:=0;i<8*int(MODBYTES);i++   {
+		if j==0 {
+			r=rng.GetByte()
+		} else {r>>=1}
+
+		b:=Chunk(int(r&1))
+		m.shl(1); m.w[0]+=b// m.inc(b)
+		j++; j&=7; 
+	}
+	return m;
+}
+
+/* Create random BIG in portable way, one bit at a time */
+func Randomnum(q *BIG,rng *amcl.RAND) *BIG {
+	d:=NewDBIG();
+	var j int=0
+	var r byte=0
+	for i:=0;i<2*q.nbits();i++ {
+		if (j==0) {
+			r=rng.GetByte();
+		} else {r>>=1}
+
+		b:=Chunk(int(r&1))
+		d.shl(1); d.w[0]+=b// m.inc(b);
+		j++; j&=7 
+	}
+	m:=d.mod(q)
+	return m;
+}
+
+
+/* return NAF value as +/- 1, 3 or 5. x and x3 should be normed. 
+nbs is number of bits processed, and nzs is number of trailing 0s detected */
+/*
+func nafbits(x *BIG,x3 *BIG ,i int) [3]int {
+	var n [3]int
+	var j int
+	nb:=x3.bit(i)-x.bit(i)
+
+
+	n[1]=1
+	n[0]=0
+	if nb==0 {n[0]=0; return n}
+	if i==0 {n[0]=nb; return n}
+	if nb>0 {
+		n[0]=1;
+	} else  {n[0]=(-1)}
+
+	for j=i-1;j>0;j-- {
+		n[1]++
+		n[0]*=2
+		nb=x3.bit(j)-x.bit(j)
+		if nb>0 {n[0]+=1}
+		if nb<0 {n[0]-=1}
+		if (n[0]>5 || n[0] < -5) {break}
+	}
+
+	if n[0]%2!=0 && j!=0 { // backtrack 
+		if nb>0 {n[0]=(n[0]-1)/2}
+		if nb<0 {n[0]=(n[0]+1)/2}
+		n[1]--
+	}
+	for n[0]%2==0 { // remove trailing zeros 
+		n[0]/=2
+		n[2]++
+		n[1]--
+	}
+	return n;
+}
+*/
+
+/* return a*b mod m */
+func Modmul(a1,b1,m *BIG) *BIG {
+	a:=NewBIGcopy(a1)
+	b:=NewBIGcopy(b1)
+	a.Mod(m)
+	b.Mod(m)
+	d:=mul(a,b);
+	return d.mod(m)
+}
+
+/* return a^2 mod m */
+func Modsqr(a1,m *BIG) *BIG {
+	a:=NewBIGcopy(a1)
+	a.Mod(m)
+	d:=sqr(a)
+	return d.mod(m)
+}
+
+/* return -a mod m */
+func Modneg(a1,m *BIG) *BIG {
+	a:=NewBIGcopy(a1)
+	a.Mod(m)
+	return m.Minus(a)
+}
+
+/* Jacobi Symbol (this/p). Returns 0, 1 or -1 */
+func (r *BIG) Jacobi(p *BIG) int {
+	m:=0;
+	t:=NewBIGint(0)
+	x:=NewBIGint(0)
+	n:=NewBIGint(0)
+	zilch:=NewBIGint(0)
+	one:=NewBIGint(1)
+	if (p.parity()==0 || Comp(r,zilch)==0 || Comp(p,one)<=0) {return 0}
+	r.norm()
+	x.copy(r)
+	n.copy(p)
+	x.Mod(p)
+
+	for Comp(n,one)>0 {
+		if Comp(x,zilch)==0 {return 0}
+		n8:=n.lastbits(3)
+		k:=0
+		for x.parity()==0 {
+			k++
+			x.shr(1)
+		}
+		if k%2==1 {m+=(n8*n8-1)/8}
+		m+=(n8-1)*(x.lastbits(2)-1)/4
+		t.copy(n)
+		t.Mod(x)
+		n.copy(x)
+		x.copy(t)
+		m%=2
+
+	}
+	if m==0 {return 1}
+	return -1
+}
+
+/* this=1/this mod p. Binary method */
+func (r *BIG) Invmodp(p *BIG) {
+	r.Mod(p)
+	u:=NewBIGcopy(r)
+
+	v:=NewBIGcopy(p)
+	x1:=NewBIGint(1)
+	x2:=NewBIGint(0)
+	t:=NewBIGint(0)
+	one:=NewBIGint(1)
+	for (Comp(u,one)!=0 && Comp(v,one)!=0) {
+		for u.parity()==0 {
+			u.fshr(1);
+			if x1.parity()!=0 {
+				x1.add(p)
+				x1.norm()
+			}
+			x1.fshr(1)
+		}
+		for v.parity()==0 {
+			v.fshr(1);
+			if x2.parity()!=0 {
+				x2.add(p)
+				x2.norm()
+			}
+			x2.fshr(1)
+		}
+		if Comp(u,v)>=0 {
+			u.sub(v)
+			u.norm()
+			if Comp(x1,x2)>=0 {
+				x1.sub(x2)
+			} else {
+				t.copy(p)
+				t.sub(x2)
+				x1.add(t)
+			}
+			x1.norm()
+		} else {
+			v.sub(u)
+			v.norm()
+			if Comp(x2,x1)>=0 { 
+				x2.sub(x1)
+			} else {
+				t.copy(p)
+				t.sub(x1)
+				x2.add(t)
+			}
+			x2.norm()
+		}
+	}
+	if Comp(u,one)==0 {
+		r.copy(x1)
+	} else {r.copy(x2)}
+}
+
+/* return this^e mod m */
+func (r *BIG) Powmod(e1 *BIG,m *BIG) *BIG {
+	e:=NewBIGcopy(e1)
+	r.norm()
+	e.norm()
+	a:=NewBIGint(1)
+	z:=NewBIGcopy(e)
+	s:=NewBIGcopy(r)
+	for true {
+		bt:=z.parity()
+		z.fshr(1)
+		if bt==1 {a=Modmul(a,s,m)}
+		if z.iszilch() {break}
+		s=Modsqr(s,m)
+	}
+	return a;
+}
+
+/* Arazi and Qi inversion mod 256 */
+func invmod256(a int) int {
+	var t1 int=0
+	c:=(a>>1)&1
+	t1+=c
+	t1&=1
+	t1=2-t1
+	t1<<=1
+	U:=t1+1;
+
+// i=2
+	b:=a&3;
+	t1=U*b; t1>>=2
+	c=(a>>2)&3
+	t2:=(U*c)&3
+	t1+=t2;
+	t1*=U; t1&=3
+	t1=4-t1
+	t1<<=2
+	U+=t1
+
+// i=4
+	b=a&15
+	t1=U*b; t1>>=4
+	c=(a>>4)&15
+	t2=(U*c)&15
+	t1+=t2
+	t1*=U; t1&=15
+	t1=16-t1
+	t1<<=4
+	U+=t1
+
+	return U;
+}
+
+func logb2(w uint32) uint {
+	v:=w
+	v |= (v >> 1)
+	v |= (v >> 2)
+	v |= (v >> 4)
+	v |= (v >> 8)
+	v |= (v >> 16)
+
+	v = v - ((v >> 1) & 0x55555555)                 
+	v = (v & 0x33333333) + ((v >> 2) & 0x33333333)  
+	r:= uint((   ((v + (v >> 4)) & 0xF0F0F0F)   * 0x1010101) >> 24)
+	return (r)
+}
+
+// Optimized combined shift, subtract and norm
+func ssn(r *BIG,a *BIG,m *BIG) int {
+        n:=NLEN-1
+        m.w[0]=(m.w[0]>>1)|((m.w[1]<<(BASEBITS-1))&BMASK)
+	r.w[0]=a.w[0]-m.w[0]
+	carry:=r.w[0]>>BASEBITS
+	r.w[0] &= BMASK
+	for i:=1;i<n;i++  {
+            m.w[i]=(m.w[i]>>1)|((m.w[i+1]<<(BASEBITS-1))&BMASK)
+            r.w[i]=a.w[i]-m.w[i]+carry
+            carry=r.w[i]>>BASEBITS
+            r.w[i] &= BMASK
+        }
+	m.w[n]>>=1
+	r.w[n]=a.w[n]-m.w[n]+carry
+	return int((r.w[n]>>uint(CHUNK-1))&1)
+}
+
+/*
+func main() {
+	a := NewBIGint(3)
+	m := NewBIGints(Modulus)
+
+	fmt.Printf("Modulus= "+m.ToString())
+	fmt.Printf("\n")
+
+
+	e := NewBIGcopy(m);
+	e.dec(1); e.norm();
+	fmt.Printf("Exponent= "+e.ToString())
+	fmt.Printf("\n")
+	a=a.Powmod(e,m);
+	fmt.Printf("Result= "+a.ToString())
+}
+*/
diff --git a/version3/go/BenchtestALL.go b/version3/go/BenchtestALL.go
new file mode 100644
index 0000000..5db24e7
--- /dev/null
+++ b/version3/go/BenchtestALL.go
@@ -0,0 +1,881 @@
+/*
+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.
+*/
+
+/* Test and benchmark elliptic curve and RSA functions */
+
+package main
+
+import "fmt"
+
+import "github.com/milagro-crypto/amcl/version3/go/amcl"
+import "github.com/milagro-crypto/amcl/version3/go/amcl/ED25519"
+import "github.com/milagro-crypto/amcl/version3/go/amcl/NIST256"
+import "github.com/milagro-crypto/amcl/version3/go/amcl/GOLDILOCKS"
+import "github.com/milagro-crypto/amcl/version3/go/amcl/BN254"
+import "github.com/milagro-crypto/amcl/version3/go/amcl/BLS383"
+import "github.com/milagro-crypto/amcl/version3/go/amcl/RSA2048"
+import "github.com/milagro-crypto/amcl/version3/go/amcl/BLS24"
+import "github.com/milagro-crypto/amcl/version3/go/amcl/BLS48"
+
+//import "amcl"
+//import "amcl/BN254"
+//import "amcl/ED25519"
+//import "amcl/RSA2048"
+
+import "time"
+
+const MIN_TIME int=10
+const MIN_ITERS int=10
+
+func ED_25519(rng *amcl.RAND) {
+	fmt.Printf("Testing/Timing ED25519 ECC\n")
+
+	if ED25519.CURVETYPE==ED25519.WEIERSTRASS {
+		fmt.Printf("Weierstrass parameterization\n")
+	}		
+	if ED25519.CURVETYPE==ED25519.EDWARDS {
+		fmt.Printf("Edwards parameterization\n")
+	}
+	if ED25519.CURVETYPE==ED25519.MONTGOMERY {
+		fmt.Printf("Montgomery parameterization\n")
+	}
+
+	if ED25519.MODTYPE==ED25519.PSEUDO_MERSENNE {
+		fmt.Printf("Pseudo-Mersenne Modulus\n")
+	}
+	if ED25519.MODTYPE==ED25519.MONTGOMERY_FRIENDLY {
+		fmt.Printf("Montgomery friendly Modulus\n")
+	}
+	if ED25519.MODTYPE==ED25519.GENERALISED_MERSENNE {
+		fmt.Printf("Generalised-Mersenne Modulus\n")
+	}
+	if ED25519.MODTYPE==ED25519.NOT_SPECIAL {
+		fmt.Printf("Not special Modulus\n")
+	}
+
+	fmt.Printf("Modulus size %d bits\n",ED25519.MODBITS)
+	fmt.Printf("%d bit build\n",ED25519.CHUNK)
+
+	var es *ED25519.BIG
+
+	EG:=ED25519.ECP_generator();
+	er:=ED25519.NewBIGints(ED25519.CURVE_Order)
+	es=ED25519.Randomnum(er,rng)
+
+	WP:=EG.Mul(er)
+	if !WP.Is_infinity() {
+		fmt.Printf("FAILURE - rG!=O\n")
+		return
+	}
+
+	start := time.Now()
+	iterations:=0
+	elapsed:=time.Since(start)
+	for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS {
+		WP=EG.Mul(es)
+		iterations++
+		elapsed=time.Since(start)
+	} 
+	dur:=float64(elapsed/time.Millisecond)/float64(iterations)
+	fmt.Printf("EC  mul - %8d iterations  ",iterations)
+	fmt.Printf(" %8.2f ms per iteration\n",dur)
+
+}
+
+
+func NIST_256(rng *amcl.RAND) {
+	fmt.Printf("Testing/Timing NIST256 ECC\n")
+
+	if NIST256.CURVETYPE==NIST256.WEIERSTRASS {
+		fmt.Printf("Weierstrass parameterization\n")
+	}		
+	if NIST256.CURVETYPE==NIST256.EDWARDS {
+		fmt.Printf("Edwards parameterization\n")
+	}
+	if NIST256.CURVETYPE==NIST256.MONTGOMERY {
+		fmt.Printf("Montgomery parameterization\n")
+	}
+
+	if NIST256.MODTYPE==NIST256.PSEUDO_MERSENNE {
+		fmt.Printf("Pseudo-Mersenne Modulus\n")
+	}
+	if NIST256.MODTYPE==NIST256.MONTGOMERY_FRIENDLY {
+		fmt.Printf("Montgomery friendly Modulus\n")
+	}
+	if NIST256.MODTYPE==NIST256.GENERALISED_MERSENNE {
+		fmt.Printf("Generalised-Mersenne Modulus\n")
+	}
+	if NIST256.MODTYPE==NIST256.NOT_SPECIAL {
+		fmt.Printf("Not special Modulus\n")
+	}
+
+	fmt.Printf("Modulus size %d bits\n",NIST256.MODBITS)
+	fmt.Printf("%d bit build\n",NIST256.CHUNK)
+
+	var es *NIST256.BIG
+
+	EG:=NIST256.ECP_generator();
+	er:=NIST256.NewBIGints(NIST256.CURVE_Order)
+	es=NIST256.Randomnum(er,rng)
+
+	WP:=EG.Mul(er)
+	if !WP.Is_infinity() {
+		fmt.Printf("FAILURE - rG!=O\n")
+		return
+	}
+
+	start := time.Now()
+	iterations:=0
+	elapsed:=time.Since(start)
+	for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS {
+		WP=EG.Mul(es)
+		iterations++
+		elapsed=time.Since(start)
+	} 
+	dur:=float64(elapsed/time.Millisecond)/float64(iterations)
+	fmt.Printf("EC  mul - %8d iterations  ",iterations)
+	fmt.Printf(" %8.2f ms per iteration\n",dur)
+
+}
+
+func GOLDI_LOCKS(rng *amcl.RAND) {
+	fmt.Printf("Testing/Timing GOLDILOCKS ECC\n")
+
+	if GOLDILOCKS.CURVETYPE==GOLDILOCKS.WEIERSTRASS {
+		fmt.Printf("Weierstrass parameterization\n")
+	}		
+	if GOLDILOCKS.CURVETYPE==GOLDILOCKS.EDWARDS {
+		fmt.Printf("Edwards parameterization\n")
+	}
+	if GOLDILOCKS.CURVETYPE==GOLDILOCKS.MONTGOMERY {
+		fmt.Printf("Montgomery parameterization\n")
+	}
+
+	if GOLDILOCKS.MODTYPE==GOLDILOCKS.PSEUDO_MERSENNE {
+		fmt.Printf("Pseudo-Mersenne Modulus\n")
+	}
+	if GOLDILOCKS.MODTYPE==GOLDILOCKS.MONTGOMERY_FRIENDLY {
+		fmt.Printf("Montgomery friendly Modulus\n")
+	}
+	if GOLDILOCKS.MODTYPE==GOLDILOCKS.GENERALISED_MERSENNE {
+		fmt.Printf("Generalised-Mersenne Modulus\n")
+	}
+	if GOLDILOCKS.MODTYPE==GOLDILOCKS.NOT_SPECIAL {
+		fmt.Printf("Not special Modulus\n")
+	}
+
+	fmt.Printf("Modulus size %d bits\n",GOLDILOCKS.MODBITS)
+	fmt.Printf("%d bit build\n",GOLDILOCKS.CHUNK)
+
+	var es *GOLDILOCKS.BIG
+
+	EG:=GOLDILOCKS.ECP_generator();
+	er:=GOLDILOCKS.NewBIGints(GOLDILOCKS.CURVE_Order)
+	es=GOLDILOCKS.Randomnum(er,rng)
+
+	WP:=EG.Mul(er)
+	if !WP.Is_infinity() {
+		fmt.Printf("FAILURE - rG!=O\n")
+		return
+	}
+
+	start := time.Now()
+	iterations:=0
+	elapsed:=time.Since(start)
+	for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS {
+		WP=EG.Mul(es)
+		iterations++
+		elapsed=time.Since(start)
+	} 
+	dur:=float64(elapsed/time.Millisecond)/float64(iterations)
+	fmt.Printf("EC  mul - %8d iterations  ",iterations)
+	fmt.Printf(" %8.2f ms per iteration\n",dur)
+
+}
+
+func BN_254(rng *amcl.RAND) {
+
+	fmt.Printf("\nTesting/Timing BN254 Pairings\n")
+
+	if BN254.CURVE_PAIRING_TYPE==BN254.BN {
+		fmt.Printf("BN Pairing-Friendly Curve\n")
+	}
+	if BN254.CURVE_PAIRING_TYPE==BN254.BLS {
+		fmt.Printf("BLS Pairing-Friendly Curve\n")
+	}
+
+	fmt.Printf("Modulus size %d bits\n",BN254.MODBITS)
+	fmt.Printf("%d bit build\n",BN254.CHUNK)
+
+	G:=BN254.ECP_generator();
+	r:=BN254.NewBIGints(BN254.CURVE_Order)
+	s:=BN254.Randomnum(r,rng)
+
+	P:=BN254.G1mul(G,r)
+
+	if !P.Is_infinity() {
+		fmt.Printf("FAILURE - rP!=O\n");
+		return;
+	}
+
+	start:= time.Now()
+	iterations:=0
+	elapsed:=time.Since(start)
+	for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS {
+		P=BN254.G1mul(G,s)
+		iterations++
+		elapsed=time.Since(start)
+	} 
+	dur:=float64(elapsed/time.Millisecond)/float64(iterations)
+	fmt.Printf("G1 mul              - %8d iterations  ",iterations)
+	fmt.Printf(" %8.2f ms per iteration\n",dur)
+
+	Q:=BN254.ECP2_generator();
+	W:=BN254.G2mul(Q,r)
+
+	if !W.Is_infinity() {
+		fmt.Printf("FAILURE - rQ!=O\n");
+		return;
+	}
+
+	start = time.Now()
+	iterations=0
+	elapsed=time.Since(start)
+	for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS {
+		W=BN254.G2mul(Q,s)
+		iterations++
+		elapsed=time.Since(start)
+	} 
+	dur=float64(elapsed/time.Millisecond)/float64(iterations)
+	fmt.Printf("G2 mul              - %8d iterations  ",iterations)
+	fmt.Printf(" %8.2f ms per iteration\n",dur)
+
+	w:=BN254.Ate(Q,P)
+	w=BN254.Fexp(w)
+
+	g:=BN254.GTpow(w,r)
+
+	if !g.Isunity() {
+		fmt.Printf("FAILURE - g^r!=1\n");
+		return;
+	}
+
+	start = time.Now()
+	iterations=0
+	elapsed=time.Since(start)
+	for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS {
+		g=BN254.GTpow(w,s)
+		iterations++
+		elapsed=time.Since(start)
+	} 
+	dur=float64(elapsed/time.Millisecond)/float64(iterations)
+	fmt.Printf("GT pow              - %8d iterations  ",iterations)
+	fmt.Printf(" %8.2f ms per iteration\n",dur)
+
+	start = time.Now()
+	iterations=0
+	elapsed=time.Since(start)
+	for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS {
+		_=w.Compow(s,r)
+		iterations++
+		elapsed=time.Since(start)
+	} 
+	dur=float64(elapsed/time.Millisecond)/float64(iterations)
+	fmt.Printf("GT pow (compressed) - %8d iterations  ",iterations)
+	fmt.Printf(" %8.2f ms per iteration\n",dur)
+
+	start = time.Now()
+	iterations=0
+	elapsed=time.Since(start)
+	for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS {
+		w=BN254.Ate(Q,P)
+		iterations++
+		elapsed=time.Since(start)
+	} 
+	dur=float64(elapsed/time.Millisecond)/float64(iterations)
+	fmt.Printf("PAIRing ATE         - %8d iterations  ",iterations)
+	fmt.Printf(" %8.2f ms per iteration\n",dur)
+
+	start = time.Now()
+	iterations=0
+	elapsed=time.Since(start)
+	for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS {
+		g=BN254.Fexp(w)
+		iterations++
+		elapsed=time.Since(start)
+	} 
+	dur=float64(elapsed/time.Millisecond)/float64(iterations)
+	fmt.Printf("PAIRing FEXP        - %8d iterations  ",iterations)
+	fmt.Printf(" %8.2f ms per iteration\n",dur)
+
+	P.Copy(G)
+	Q.Copy(W)
+
+	P=BN254.G1mul(P,s)
+
+	g=BN254.Ate(Q,P)
+	g=BN254.Fexp(g)
+
+	P.Copy(G)
+	Q=BN254.G2mul(Q,s)
+
+	w=BN254.Ate(Q,P)
+	w=BN254.Fexp(w)
+
+	if !g.Equals(w) {
+		fmt.Printf("FAILURE - e(sQ,p)!=e(Q,sP) \n")
+		return
+	}
+
+	Q.Copy(W);
+	g=BN254.Ate(Q,P)
+	g=BN254.Fexp(g)
+	g=BN254.GTpow(g,s)
+
+	if !g.Equals(w) {
+		fmt.Printf("FAILURE - e(sQ,p)!=e(Q,P)^s \n")
+		return
+	}
+
+}
+
+func BLS_383(rng *amcl.RAND) {
+
+	fmt.Printf("\nTesting/Timing BLS383 Pairings\n")
+
+	if BLS383.CURVE_PAIRING_TYPE==BLS383.BN {
+		fmt.Printf("BN Pairing-Friendly Curve\n")
+	}
+	if BLS383.CURVE_PAIRING_TYPE==BLS383.BLS {
+		fmt.Printf("BLS Pairing-Friendly Curve\n")
+	}
+
+	fmt.Printf("Modulus size %d bits\n",BLS383.MODBITS)
+	fmt.Printf("%d bit build\n",BLS383.CHUNK)
+
+	G:=BLS383.ECP_generator();
+	r:=BLS383.NewBIGints(BLS383.CURVE_Order)
+	s:=BLS383.Randomnum(r,rng)
+
+	P:=BLS383.G1mul(G,r)
+
+	if !P.Is_infinity() {
+		fmt.Printf("FAILURE - rP!=O\n");
+		return;
+	}
+
+	start:= time.Now()
+	iterations:=0
+	elapsed:=time.Since(start)
+	for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS {
+		P=BLS383.G1mul(G,s)
+		iterations++
+		elapsed=time.Since(start)
+	} 
+	dur:=float64(elapsed/time.Millisecond)/float64(iterations)
+	fmt.Printf("G1 mul              - %8d iterations  ",iterations)
+	fmt.Printf(" %8.2f ms per iteration\n",dur)
+
+	Q:=BLS383.ECP2_generator();
+	W:=BLS383.G2mul(Q,r)
+
+	if !W.Is_infinity() {
+		fmt.Printf("FAILURE - rQ!=O\n");
+		return;
+	}
+
+	start = time.Now()
+	iterations=0
+	elapsed=time.Since(start)
+	for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS {
+		W=BLS383.G2mul(Q,s)
+		iterations++
+		elapsed=time.Since(start)
+	} 
+	dur=float64(elapsed/time.Millisecond)/float64(iterations)
+	fmt.Printf("G2 mul              - %8d iterations  ",iterations)
+	fmt.Printf(" %8.2f ms per iteration\n",dur)
+
+	w:=BLS383.Ate(Q,P)
+	w=BLS383.Fexp(w)
+
+	g:=BLS383.GTpow(w,r)
+
+	if !g.Isunity() {
+		fmt.Printf("FAILURE - g^r!=1\n");
+		return;
+	}
+
+	start = time.Now()
+	iterations=0
+	elapsed=time.Since(start)
+	for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS {
+		g=BLS383.GTpow(w,s)
+		iterations++
+		elapsed=time.Since(start)
+	} 
+	dur=float64(elapsed/time.Millisecond)/float64(iterations)
+	fmt.Printf("GT pow              - %8d iterations  ",iterations)
+	fmt.Printf(" %8.2f ms per iteration\n",dur)
+
+	start = time.Now()
+	iterations=0
+	elapsed=time.Since(start)
+	for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS {
+		_=w.Compow(s,r)
+		iterations++
+		elapsed=time.Since(start)
+	} 
+	dur=float64(elapsed/time.Millisecond)/float64(iterations)
+	fmt.Printf("GT pow (compressed) - %8d iterations  ",iterations)
+	fmt.Printf(" %8.2f ms per iteration\n",dur)
+
+	start = time.Now()
+	iterations=0
+	elapsed=time.Since(start)
+	for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS {
+		w=BLS383.Ate(Q,P)
+		iterations++
+		elapsed=time.Since(start)
+	} 
+	dur=float64(elapsed/time.Millisecond)/float64(iterations)
+	fmt.Printf("PAIRing ATE         - %8d iterations  ",iterations)
+	fmt.Printf(" %8.2f ms per iteration\n",dur)
+
+	start = time.Now()
+	iterations=0
+	elapsed=time.Since(start)
+	for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS {
+		g=BLS383.Fexp(w)
+		iterations++
+		elapsed=time.Since(start)
+	} 
+	dur=float64(elapsed/time.Millisecond)/float64(iterations)
+	fmt.Printf("PAIRing FEXP        - %8d iterations  ",iterations)
+	fmt.Printf(" %8.2f ms per iteration\n",dur)
+
+	P.Copy(G)
+	Q.Copy(W)
+
+	P=BLS383.G1mul(P,s)
+
+	g=BLS383.Ate(Q,P)
+	g=BLS383.Fexp(g)
+
+	P.Copy(G)
+	Q=BLS383.G2mul(Q,s)
+
+	w=BLS383.Ate(Q,P)
+	w=BLS383.Fexp(w)
+
+	if !g.Equals(w) {
+		fmt.Printf("FAILURE - e(sQ,p)!=e(Q,sP) \n")
+		return
+	}
+
+	Q.Copy(W);
+	g=BLS383.Ate(Q,P)
+	g=BLS383.Fexp(g)
+	g=BLS383.GTpow(g,s)
+
+	if !g.Equals(w) {
+		fmt.Printf("FAILURE - e(sQ,p)!=e(Q,P)^s \n")
+		return
+	}
+
+}
+
+
+func BLS_24(rng *amcl.RAND) {
+
+	fmt.Printf("\nTesting/Timing BLS24 Pairings\n")
+
+	if BLS24.CURVE_PAIRING_TYPE==BLS24.BN {
+		fmt.Printf("BN Pairing-Friendly Curve\n")
+	}
+	if BLS24.CURVE_PAIRING_TYPE==BLS24.BLS {
+		fmt.Printf("BLS Pairing-Friendly Curve\n")
+	}
+
+	fmt.Printf("Modulus size %d bits\n",BLS24.MODBITS)
+	fmt.Printf("%d bit build\n",BLS24.CHUNK)
+
+	G:=BLS24.ECP_generator();
+	r:=BLS24.NewBIGints(BLS24.CURVE_Order)
+	s:=BLS24.Randomnum(r,rng)
+
+	P:=BLS24.G1mul(G,r)
+
+	if !P.Is_infinity() {
+		fmt.Printf("FAILURE - rP!=O\n");
+		return;
+	}
+
+	start := time.Now()
+	iterations:=0
+	elapsed:=time.Since(start)
+	for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS {
+		P=BLS24.G1mul(G,s)
+		iterations++
+		elapsed=time.Since(start)
+	} 
+	dur:=float64(elapsed/time.Millisecond)/float64(iterations)
+	fmt.Printf("G1 mul              - %8d iterations  ",iterations)
+	fmt.Printf(" %8.2f ms per iteration\n",dur)
+
+	Q:=BLS24.ECP4_generator();
+
+	W:=BLS24.G2mul(Q,r)
+
+	if !W.Is_infinity() {
+		fmt.Printf("FAILURE - rQ!=O\n");
+		return;
+	}
+
+	start = time.Now()
+	iterations=0
+	elapsed=time.Since(start)
+	for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS {
+		W=BLS24.G2mul(Q,s)
+		iterations++
+		elapsed=time.Since(start)
+	} 
+	dur=float64(elapsed/time.Millisecond)/float64(iterations)
+	fmt.Printf("G2 mul              - %8d iterations  ",iterations)
+	fmt.Printf(" %8.2f ms per iteration\n",dur)
+
+	w:=BLS24.Ate(Q,P)
+	w=BLS24.Fexp(w)
+
+	g:=BLS24.GTpow(w,r)
+
+	if !g.Isunity() {
+		fmt.Printf("FAILURE - g^r!=1\n");
+		return;
+	}
+
+	start = time.Now()
+	iterations=0
+	elapsed=time.Since(start)
+	for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS {
+		g=BLS24.GTpow(w,s)
+		iterations++
+		elapsed=time.Since(start)
+	} 
+	dur=float64(elapsed/time.Millisecond)/float64(iterations)
+	fmt.Printf("GT pow              - %8d iterations  ",iterations)
+	fmt.Printf(" %8.2f ms per iteration\n",dur)
+
+	start = time.Now()
+	iterations=0
+	elapsed=time.Since(start)
+	for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS {
+		_=w.Compow(s,r)
+		iterations++
+		elapsed=time.Since(start)
+	} 
+	dur=float64(elapsed/time.Millisecond)/float64(iterations)
+	fmt.Printf("GT pow (compressed) - %8d iterations  ",iterations)
+	fmt.Printf(" %8.2f ms per iteration\n",dur)
+
+	start = time.Now()
+	iterations=0
+	elapsed=time.Since(start)
+	for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS {
+		w=BLS24.Ate(Q,P)
+		iterations++
+		elapsed=time.Since(start)
+	} 
+	dur=float64(elapsed/time.Millisecond)/float64(iterations)
+	fmt.Printf("PAIRing ATE         - %8d iterations  ",iterations)
+	fmt.Printf(" %8.2f ms per iteration\n",dur)
+
+	start = time.Now()
+	iterations=0
+	elapsed=time.Since(start)
+	for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS {
+		g=BLS24.Fexp(w)
+		iterations++
+		elapsed=time.Since(start)
+	} 
+	dur=float64(elapsed/time.Millisecond)/float64(iterations)
+	fmt.Printf("PAIRing FEXP        - %8d iterations  ",iterations)
+	fmt.Printf(" %8.2f ms per iteration\n",dur)
+
+	P.Copy(G)
+	Q.Copy(W)
+
+	P=BLS24.G1mul(P,s)
+
+	g=BLS24.Ate(Q,P)
+	g=BLS24.Fexp(g)
+
+	P.Copy(G)
+	Q=BLS24.G2mul(Q,s)
+
+	w=BLS24.Ate(Q,P)
+	w=BLS24.Fexp(w)
+
+	if !g.Equals(w) {
+		fmt.Printf("FAILURE - e(sQ,p)!=e(Q,sP) \n")
+		return
+	}
+
+	Q.Copy(W);
+	g=BLS24.Ate(Q,P)
+	g=BLS24.Fexp(g)
+	g=BLS24.GTpow(g,s)
+
+	if !g.Equals(w) {
+		fmt.Printf("FAILURE - e(sQ,p)!=e(Q,P)^s \n")
+		return
+	}
+
+}
+
+func BLS_48(rng *amcl.RAND) {
+
+	fmt.Printf("\nTesting/Timing BLS48 Pairings\n")
+
+	if BLS48.CURVE_PAIRING_TYPE==BLS48.BN {
+		fmt.Printf("BN Pairing-Friendly Curve\n")
+	}
+	if BLS48.CURVE_PAIRING_TYPE==BLS48.BLS {
+		fmt.Printf("BLS Pairing-Friendly Curve\n")
+	}
+
+	fmt.Printf("Modulus size %d bits\n",BLS48.MODBITS)
+	fmt.Printf("%d bit build\n",BLS48.CHUNK)
+
+	G:=BLS48.ECP_generator();
+	r:=BLS48.NewBIGints(BLS48.CURVE_Order)
+	s:=BLS48.Randomnum(r,rng)
+
+	P:=BLS48.G1mul(G,r)
+
+	if !P.Is_infinity() {
+		fmt.Printf("FAILURE - rP!=O\n");
+		return;
+	}
+
+	start := time.Now()
+	iterations:=0
+	elapsed:=time.Since(start)
+	for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS {
+		P=BLS48.G1mul(G,s)
+		iterations++
+		elapsed=time.Since(start)
+	} 
+	dur:=float64(elapsed/time.Millisecond)/float64(iterations)
+	fmt.Printf("G1 mul              - %8d iterations  ",iterations)
+	fmt.Printf(" %8.2f ms per iteration\n",dur)
+
+	Q:=BLS48.ECP8_generator();
+
+	W:=BLS48.G2mul(Q,r)
+
+	if !W.Is_infinity() {
+		fmt.Printf("FAILURE - rQ!=O\n");
+		return;
+	}
+
+	start = time.Now()
+	iterations=0
+	elapsed=time.Since(start)
+	for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS {
+		W=BLS48.G2mul(Q,s)
+		iterations++
+		elapsed=time.Since(start)
+	} 
+	dur=float64(elapsed/time.Millisecond)/float64(iterations)
+	fmt.Printf("G2 mul              - %8d iterations  ",iterations)
+	fmt.Printf(" %8.2f ms per iteration\n",dur)
+
+	w:=BLS48.Ate(Q,P)
+	w=BLS48.Fexp(w)
+
+	g:=BLS48.GTpow(w,r)
+
+	if !g.Isunity() {
+		fmt.Printf("FAILURE - g^r!=1\n");
+		return;
+	}
+
+	start = time.Now()
+	iterations=0
+	elapsed=time.Since(start)
+	for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS {
+		g=BLS48.GTpow(w,s)
+		iterations++
+		elapsed=time.Since(start)
+	} 
+	dur=float64(elapsed/time.Millisecond)/float64(iterations)
+	fmt.Printf("GT pow              - %8d iterations  ",iterations)
+	fmt.Printf(" %8.2f ms per iteration\n",dur)
+
+	start = time.Now()
+	iterations=0
+	elapsed=time.Since(start)
+	for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS {
+		_=w.Compow(s,r)
+		iterations++
+		elapsed=time.Since(start)
+	} 
+	dur=float64(elapsed/time.Millisecond)/float64(iterations)
+	fmt.Printf("GT pow (compressed) - %8d iterations  ",iterations)
+	fmt.Printf(" %8.2f ms per iteration\n",dur)
+
+	start = time.Now()
+	iterations=0
+	elapsed=time.Since(start)
+	for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS {
+		w=BLS48.Ate(Q,P)
+		iterations++
+		elapsed=time.Since(start)
+	} 
+	dur=float64(elapsed/time.Millisecond)/float64(iterations)
+	fmt.Printf("PAIRing ATE         - %8d iterations  ",iterations)
+	fmt.Printf(" %8.2f ms per iteration\n",dur)
+
+	start = time.Now()
+	iterations=0
+	elapsed=time.Since(start)
+	for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS {
+		g=BLS48.Fexp(w)
+		iterations++
+		elapsed=time.Since(start)
+	} 
+	dur=float64(elapsed/time.Millisecond)/float64(iterations)
+	fmt.Printf("PAIRing FEXP        - %8d iterations  ",iterations)
+	fmt.Printf(" %8.2f ms per iteration\n",dur)
+
+	P.Copy(G)
+	Q.Copy(W)
+
+	P=BLS48.G1mul(P,s)
+
+	g=BLS48.Ate(Q,P)
+	g=BLS48.Fexp(g)
+
+	P.Copy(G)
+	Q=BLS48.G2mul(Q,s)
+
+	w=BLS48.Ate(Q,P)
+	w=BLS48.Fexp(w)
+
+	if !g.Equals(w) {
+		fmt.Printf("FAILURE - e(sQ,p)!=e(Q,sP) \n")
+		return
+	}
+
+	Q.Copy(W);
+	g=BLS48.Ate(Q,P)
+	g=BLS48.Fexp(g)
+	g=BLS48.GTpow(g,s)
+
+	if !g.Equals(w) {
+		fmt.Printf("FAILURE - e(sQ,p)!=e(Q,P)^s \n")
+		return
+	}
+
+}
+
+func RSA_2048(rng *amcl.RAND) {
+
+	fmt.Printf("\nTesting/Timing 2048-bit RSA\n")
+
+	pub:=RSA2048.New_public_key(RSA2048.FFLEN)
+	priv:=RSA2048.New_private_key(RSA2048.HFLEN)
+
+	var PT [RSA2048.RFS]byte
+	var M [RSA2048.RFS]byte
+	var CT [RSA2048.RFS]byte
+
+	fmt.Printf("Generating 2048-bit RSA public/private key pair\n");
+
+	start:= time.Now()
+	iterations:=0
+	elapsed:=time.Since(start)
+	for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS {
+		RSA2048.RSA_KEY_PAIR(rng,65537,priv,pub)
+		iterations++
+		elapsed=time.Since(start)
+	} 
+	dur:=float64(elapsed/time.Millisecond)/float64(iterations)
+	fmt.Printf("RSA gen - %8d iterations  ",iterations)
+	fmt.Printf(" %8.2f ms per iteration\n",dur)
+
+	for i:=0;i<RSA2048.RFS;i++ {M[i]=byte(i%128)};
+
+	start = time.Now()
+	iterations=0
+	elapsed=time.Since(start)
+	for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS {
+		RSA2048.RSA_ENCRYPT(pub,M[:],CT[:])
+		iterations++
+		elapsed=time.Since(start)
+	} 
+	dur=float64(elapsed/time.Millisecond)/float64(iterations)
+	fmt.Printf("RSA enc - %8d iterations  ",iterations)
+	fmt.Printf(" %8.2f ms per iteration\n",dur)
+
+	start = time.Now()
+	iterations=0
+	elapsed=time.Since(start)
+	for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS {
+		RSA2048.RSA_DECRYPT(priv,CT[:],PT[:])
+		iterations++
+		elapsed=time.Since(start)
+	} 
+	dur=float64(elapsed/time.Millisecond)/float64(iterations)
+	fmt.Printf("RSA dec - %8d iterations  ",iterations)
+	fmt.Printf(" %8.2f ms per iteration\n",dur)
+
+	for i:=0;i<RSA2048.RFS;i++ {
+		if (PT[i]!=M[i]) {
+			fmt.Printf("FAILURE - RSA decryption\n")
+			return
+		}
+	}
+
+	fmt.Printf("All tests pass\n") 
+}
+
+func main() {
+	var RAW [100]byte
+
+	rng:=amcl.NewRAND()
+
+	rng.Clean();
+	for i:=0;i<100;i++ {RAW[i]=byte(i)}
+
+	rng.Seed(100,RAW[:])
+	
+	ED_25519(rng)
+	NIST_256(rng)
+	GOLDI_LOCKS(rng)
+	BN_254(rng)
+	BLS_383(rng)
+	BLS_24(rng)
+	BLS_48(rng)
+	RSA_2048(rng)
+
+}
+
+
diff --git a/version3/go/DBIG.go b/version3/go/DBIG.go
new file mode 100644
index 0000000..694cc98
--- /dev/null
+++ b/version3/go/DBIG.go
@@ -0,0 +1,274 @@
+/*
+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.
+*/
+
+/* MiotCL double length DBIG number class */ 
+
+
+package XXX
+
+import "strconv"
+//import "fmt"
+
+func NewDBIG() *DBIG {
+	b:=new(DBIG)
+	for i:=0;i<DNLEN;i++ {
+		b.w[i]=0
+	}
+	return b
+}
+
+func NewDBIGcopy(x *DBIG) *DBIG {
+	b:=new(DBIG)
+	for i:=0;i<DNLEN;i++ {
+		b.w[i]=x.w[i]
+	}
+	return b
+}
+
+func NewDBIGscopy(x *BIG) *DBIG {
+	b:=new(DBIG)
+	for i:=0;i<NLEN-1;i++ {
+		b.w[i]=x.w[i]
+	}
+	b.w[NLEN-1]=x.get(NLEN-1)&BMASK /* top word normalized */
+	b.w[NLEN]=x.get(NLEN-1)>>BASEBITS
+
+	for i:=NLEN+1;i<DNLEN;i++  {b.w[i]=0}
+	return b
+}
+
+/* normalise this */
+func (r *DBIG) norm() {
+	carry:=Chunk(0)
+	for i:=0;i<DNLEN-1;i++ {
+		d:=r.w[i]+carry
+		r.w[i]=d&BMASK
+		carry=d>>BASEBITS
+	}
+	r.w[DNLEN-1]=(r.w[DNLEN-1]+carry)
+}
+
+/* split DBIG at position n, return higher half, keep lower half */
+func (r *DBIG) split(n uint) *BIG {
+	t:=NewBIG()
+	m:=n%BASEBITS;
+	carry:=r.w[DNLEN-1]<<(BASEBITS-m)
+
+	for i:=DNLEN-2;i>=NLEN-1;i-- {
+		nw:=(r.w[i]>>m)|carry;
+		carry=(r.w[i]<<(BASEBITS-m))&BMASK;
+		t.set(i-NLEN+1,nw);
+	}
+	r.w[NLEN-1]&=((Chunk(1)<<m)-1)
+	return t;
+}
+
+func (r *DBIG) cmove(g *DBIG,d int){
+	var b=Chunk(-d)
+
+	for i:=0;i<DNLEN;i++ {
+		r.w[i]^=(r.w[i]^g.w[i])&b
+	}
+}
+
+/* Compare a and b, return 0 if a==b, -1 if a<b, +1 if a>b. Inputs must be normalised */
+func dcomp(a *DBIG,b *DBIG) int {
+	for i:=DNLEN-1;i>=0;i-- {
+		if a.w[i]==b.w[i] {continue}
+		if a.w[i]>b.w[i] {
+			return 1
+		} else  {return -1}
+	}
+	return 0
+}
+
+/* Copy from another DBIG */
+func (r *DBIG) copy(x *DBIG) {
+	for i:=0;i<DNLEN;i++ {
+		r.w[i]=x.w[i]
+	}
+}
+
+/* Copy from another BIG to upper half */
+func (r *DBIG) ucopy(x *BIG) {
+	for i:=0;i<NLEN;i++ {
+		r.w[i]=0
+	}
+	for i:=NLEN;i<DNLEN;i++ {
+		r.w[i]=x.w[i-NLEN]
+	}
+}
+
+func (r *DBIG) add(x *DBIG) {
+	for i:=0;i<DNLEN;i++ {
+		r.w[i]=r.w[i]+x.w[i] 
+	}
+}
+
+/* this-=x */
+func (r *DBIG) sub(x *DBIG) {
+	for i:=0;i<DNLEN;i++ {
+		r.w[i]=r.w[i]-x.w[i] 
+	}
+} 
+
+/* this-=x */
+func (r *DBIG) rsub(x *DBIG) {
+	for i:=0;i<DNLEN;i++ {
+		r.w[i]=x.w[i]-r.w[i] 
+	}
+} 
+
+/* general shift left */
+func (r *DBIG) shl(k uint) {
+	n:=k%BASEBITS
+	m:=int(k/BASEBITS)
+
+	r.w[DNLEN-1]=((r.w[DNLEN-1-m]<<n))|(r.w[DNLEN-m-2]>>(BASEBITS-n))
+	for i:=DNLEN-2;i>m;i-- {
+		r.w[i]=((r.w[i-m]<<n)&BMASK)|(r.w[i-m-1]>>(BASEBITS-n))
+	}
+	r.w[m]=(r.w[0]<<n)&BMASK; 
+	for i:=0;i<m;i++ {r.w[i]=0}
+}
+
+/* general shift right */
+func (r *DBIG) shr(k uint) {
+	n:=(k%BASEBITS)
+	m:=int(k/BASEBITS)	
+	for i:=0;i<DNLEN-m-1;i++ {
+		r.w[i]=(r.w[m+i]>>n)|((r.w[m+i+1]<<(BASEBITS-n))&BMASK)
+	}
+	r.w[DNLEN-m-1]=r.w[DNLEN-1]>>n;
+	for i:=DNLEN-m;i<DNLEN;i++ {r.w[i]=0}
+}
+
+/* reduces this DBIG mod a BIG, and returns the BIG */
+func (r *DBIG) mod(c *BIG) *BIG {
+	r.norm()
+	m:=NewDBIGscopy(c)
+	dr:=NewDBIG();
+
+	if dcomp(r,m)<0 {
+		return NewBIGdcopy(r)
+	}
+
+	m.shl(1);
+	k:=1;
+		
+	for dcomp(r,m)>=0 {
+		m.shl(1);
+		k++;
+	}
+
+	for k>0 {
+		m.shr(1);
+
+		dr.copy(r);
+		dr.sub(m);
+		dr.norm();
+		r.cmove(dr,int(1-((dr.w[DNLEN-1]>>uint(CHUNK-1))&1)));
+/*
+		if dcomp(r,m)>=0 {
+			r.sub(m);
+			r.norm();
+		} */
+		k--;
+	}
+	return NewBIGdcopy(r)
+}
+
+/* return this/c */
+func (r *DBIG) div(c *BIG) *BIG {
+	var d int
+	k:=0
+	m:=NewDBIGscopy(c)
+	a:=NewBIGint(0)
+	e:=NewBIGint(1)
+	sr:=NewBIG()
+	dr:=NewDBIG()
+	r.norm()
+
+	for dcomp(r,m)>=0 {
+		e.fshl(1)
+		m.shl(1)
+		k++
+	}
+
+	for k>0 {
+		m.shr(1)
+		e.shr(1)
+
+		dr.copy(r);
+		dr.sub(m);
+		dr.norm();
+		d=int(1-((dr.w[DNLEN-1]>>uint(CHUNK-1))&1));
+		r.cmove(dr,d);
+		sr.copy(a);
+		sr.add(e);
+		sr.norm();
+		a.cmove(sr,d);
+
+/*
+		if dcomp(r,m)>0 {
+			a.add(e)
+			a.norm()
+			r.sub(m)
+			r.norm()
+		} */
+		k--
+	}
+	return a
+}
+
+/* Convert to Hex String */
+func (r *DBIG) toString() string {
+	s:=""
+	len:=r.nbits()
+
+	if len%4==0 {
+		len/=4
+	} else {
+		len/=4 
+		len++
+
+	}
+
+	for i:=len-1;i>=0;i-- {
+		b:=NewDBIGcopy(r)
+		
+		b.shr(uint(i*4))
+		s+=strconv.FormatInt(int64(b.w[0]&15),16)
+	}
+	return s
+}
+
+/* return number of bits */
+func (r *DBIG) nbits() int {
+	k:=DNLEN-1
+	t:=NewDBIGcopy(r);
+	t.norm()
+	for (k>=0 && t.w[k]==0) {k--}
+	if k<0 {return 0}
+	bts:=int(BASEBITS)*k;
+	c:=t.w[k];
+	for c!=0 {c/=2; bts++}
+	return bts
+}
+
diff --git a/version3/go/ECDH.go b/version3/go/ECDH.go
new file mode 100644
index 0000000..04c0f41
--- /dev/null
+++ b/version3/go/ECDH.go
@@ -0,0 +1,565 @@
+/*
+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.
+*/
+
+/* Elliptic Curve API high-level functions  */
+
+package XXX
+
+//import "fmt"
+import "github.com/milagro-crypto/amcl/version3/go/amcl"
+
+const INVALID_PUBLIC_KEY int=-2
+const ERROR int=-3
+const INVALID int=-4
+const EFS int=int(MODBYTES)
+const EGS int=int(MODBYTES)
+//const EAS int=16
+//const EBS int=16
+
+
+//const ECDH_HASH_TYPE int=amcl.SHA512
+
+/* Convert Integer to n-byte array */
+func inttoBytes(n int,len int) []byte {
+	var b []byte
+	var i int
+	for i=0;i<len;i++ {b=append(b,0)}
+	i=len
+	for (n>0 && i>0) {
+		i--;
+		b[i]=byte(n&0xff)
+		n/=256
+	}	
+	return b
+}
+
+func ehashit(sha int,A []byte,n int,B []byte,pad int) []byte {
+	var R []byte
+	if sha==amcl.SHA256 {
+		H:=amcl.NewHASH256()
+		H.Process_array(A)
+		if n>0 {H.Process_num(int32(n))}
+		if B!=nil {H.Process_array(B)}
+		R=H.Hash()
+	}
+	if sha==amcl.SHA384 {
+		H:=amcl.NewHASH384()
+		H.Process_array(A)
+		if n>0 {H.Process_num(int32(n))}
+		if B!=nil {H.Process_array(B)}
+		R=H.Hash()
+	}
+	if sha==amcl.SHA512 {
+		H:=amcl.NewHASH512()
+		H.Process_array(A)
+		if n>0 {H.Process_num(int32(n))}
+		if B!=nil {H.Process_array(B)}
+		R=H.Hash()
+	}
+	if R==nil {return nil}
+
+	if pad==0 {return R}
+	var W []byte
+	for i:=0;i<pad;i++ {W=append(W,0)}
+	if pad<=sha {
+		for i:=0;i<pad;i++ {W[i]=R[i]}
+	} else {
+		for i:=0;i<sha;i++ {W[i+pad-sha]=R[i]}
+		for i:=0;i<pad-sha;i++ {W[i]=0}
+ 
+
+		//for i:=0;i<sha;i++ {W[i]=R[i]}
+		//for i:=sha;i<pad;i++ {W[i]=0}
+	}
+	return W
+}
+
+/* Key Derivation Functions */
+/* Input octet Z */
+/* Output key of length olen */
+func ECDH_KDF1(sha int,Z []byte,olen int) []byte {
+/* NOTE: the parameter olen is the length of the output K in bytes */
+	hlen:=sha
+	var K []byte
+	k:=0
+    
+	for i:=0;i<olen;i++ {K=append(K,0)}
+
+	cthreshold:=olen/hlen; if olen%hlen!=0 {cthreshold++}
+
+	for counter:=0;counter<cthreshold;counter++ {
+		B:=ehashit(sha,Z,counter,nil,0)
+		if k+hlen>olen {
+			for i:=0;i<olen%hlen;i++ {K[k]=B[i]; k++}
+		} else {
+			for i:=0;i<hlen;i++ {K[k]=B[i]; k++}
+		}
+	}
+	return K;
+}
+
+func ECDH_KDF2(sha int,Z []byte,P []byte,olen int) []byte {
+/* NOTE: the parameter olen is the length of the output k in bytes */
+	hlen:=sha
+	var K []byte
+	k:=0
+    
+	for i:=0;i<olen;i++ {K=append(K,0)}
+
+	cthreshold:=olen/hlen; if olen%hlen!=0 {cthreshold++}
+
+	for counter:=1;counter<=cthreshold;counter++ {
+		B:=ehashit(sha,Z,counter,P,0)
+		if k+hlen>olen {
+			for i:=0;i<olen%hlen;i++ {K[k]=B[i]; k++}
+		} else {
+			for i:=0;i<hlen;i++ {K[k]=B[i]; k++}
+		}
+	}
+	return K
+}
+
+/* Password based Key Derivation Function */
+/* Input password p, salt s, and repeat count */
+/* Output key of length olen */
+func ECDH_PBKDF2(sha int,Pass []byte,Salt []byte,rep int,olen int) []byte {
+	d:=olen/sha; if olen%sha!=0 {d++}
+
+	var F []byte
+	var U []byte
+	var S []byte
+	var K []byte
+	
+	for i:=0;i<sha;i++{F=append(F,0); U=append(U,0)}
+
+	for i:=1;i<=d;i++ {
+		for j:=0;j<len(Salt);j++ {S=append(S,Salt[j])} 
+		N:=inttoBytes(i,4)
+		for j:=0;j<4;j++ {S=append(S,N[j])}   
+
+		HMAC(sha,S,Pass,F[:])
+
+		for j:=0;j<sha;j++ {U[j]=F[j]}
+		for j:=2;j<=rep;j++ {
+			HMAC(sha,U[:],Pass,U[:]);
+			for k:=0;k<sha;k++ {F[k]^=U[k]}
+		}
+		for j:=0;j<sha;j++ {K=append(K,F[j])} 
+	}
+	var key []byte
+	for i:=0;i<olen;i++ {key=append(key,K[i])}
+	return key
+}
+
+/* Calculate HMAC of m using key k. HMAC is tag of length olen (which is length of tag) */
+func HMAC(sha int,M []byte,K []byte,tag []byte) int {
+	/* Input is from an octet m        *
+	* olen is requested output length in bytes. k is the key  *
+	* The output is the calculated tag */
+	var B []byte
+	b:=64
+	if sha>32 {b=128}
+
+	var K0 [128]byte
+	olen:=len(tag)
+
+	if (olen<4 /*|| olen>sha */) {return 0}
+
+	for i:=0;i<b;i++ {K0[i]=0}
+
+	if len(K) > b {
+		B=ehashit(sha,K,0,nil,0) 
+		for i:=0;i<sha;i++ {K0[i]=B[i]}
+	} else {
+		for i:=0;i<len(K);i++  {K0[i]=K[i]}
+	}
+		
+	for i:=0;i<b;i++ {K0[i]^=0x36}
+	B=ehashit(sha,K0[0:b],0,M,0);
+
+	for i:=0;i<b;i++ {K0[i]^=0x6a}
+	B=ehashit(sha,K0[0:b],0,B,olen)
+
+	for i:=0;i<olen;i++ {tag[i]=B[i]}
+
+	return 1
+}
+
+/* AES encryption/decryption. Encrypt byte array M using key K and returns ciphertext */
+func AES_CBC_IV0_ENCRYPT(K []byte,M []byte) []byte { /* AES CBC encryption, with Null IV and key K */
+	/* Input is from an octet string M, output is to an octet string C */
+	/* Input is padded as necessary to make up a full final block */
+	a:=amcl.NewAES()
+	fin:=false
+
+	var buff [16]byte
+	var C []byte
+
+	a.Init(amcl.AES_CBC,len(K),K,nil)
+
+	ipt:=0; //opt:=0
+	var i int
+	for true {
+		for i=0;i<16;i++ {
+			if ipt<len(M) {
+				buff[i]=M[ipt]; ipt++;
+			} else {fin=true; break;}
+		}
+		if fin {break}
+		a.Encrypt(buff[:])
+		for i=0;i<16;i++ {
+			C=append(C,buff[i])
+		}
+	}    
+
+/* last block, filled up to i-th index */
+
+	padlen:=16-i
+	for j:=i;j<16;j++ {buff[j]=byte(padlen)}
+
+	a.Encrypt(buff[:])
+
+	for i=0;i<16;i++ {
+		C=append(C,buff[i])
+	}
+	a.End()   
+	return C
+}
+
+/* returns plaintext if all consistent, else returns null string */
+func AES_CBC_IV0_DECRYPT(K []byte,C []byte) []byte { /* padding is removed */
+	a:=amcl.NewAES()
+	var buff [16]byte
+	var MM []byte
+	var M []byte
+
+	var i int
+	ipt:=0; opt:=0
+
+	a.Init(amcl.AES_CBC,len(K),K,nil);
+
+	if len(C)==0 {return nil}
+	ch:=C[ipt]; ipt++
+  
+	fin:=false
+
+	for true {
+		for i=0;i<16;i++ {
+			buff[i]=ch    
+			if ipt>=len(C) {
+				fin=true; break
+			}  else {ch=C[ipt]; ipt++ }
+		}
+		a.Decrypt(buff[:])
+		if fin {break}
+		for i=0;i<16;i++ {
+			MM=append(MM,buff[i]); opt++
+		}
+	}    
+
+	a.End();
+	bad:=false
+	padlen:=int(buff[15])
+	if (i!=15 || padlen<1 || padlen>16) {bad=true}
+	if (padlen>=2 && padlen<=16) {
+		for i=16-padlen;i<16;i++ {
+			if buff[i]!=byte(padlen) {bad=true}
+		}
+	}
+    
+	if !bad { 
+		for i=0;i<16-padlen;i++ {
+			MM=append(MM,buff[i]); opt++
+		}
+	}
+
+	if bad {return nil}
+
+	for i=0;i<opt;i++ {M=append(M,MM[i])}
+
+	return M;
+}
+
+/* Calculate a public/private EC GF(p) key pair W,S where W=S.G mod EC(p),
+ * where S is the secret key and W is the public key
+ * and G is fixed generator.
+ * If RNG is NULL then the private key is provided externally in S
+ * otherwise it is generated randomly internally */
+func ECDH_KEY_PAIR_GENERATE(RNG *amcl.RAND,S []byte,W []byte) int {
+	res:=0
+//	var T [EFS]byte
+	var s *BIG
+	var G *ECP
+
+	G=ECP_generator();
+
+	r:=NewBIGints(CURVE_Order)
+
+	if RNG==nil {
+		s=FromBytes(S)
+		s.Mod(r)
+	} else {
+		s=Randomnum(r,RNG)
+		
+	//	s.ToBytes(T[:])
+	//	for i:=0;i<EGS;i++ {S[i]=T[i]}
+	}
+
+	//if AES_S>0 {
+	//	s.mod2m(2*AES_S)
+	//}
+	s.ToBytes(S)
+
+	WP:=G.mul(s)
+
+	WP.ToBytes(W,false)    // To use point compression on public keys, change to true 
+
+	return res
+}
+
+/* validate public key */
+func ECDH_PUBLIC_KEY_VALIDATE(W []byte) int {
+	WP:=ECP_fromBytes(W)
+	res:=0
+
+	r:=NewBIGints(CURVE_Order)
+
+	if WP.Is_infinity() {res=INVALID_PUBLIC_KEY}
+	if res==0 {
+
+		q:=NewBIGints(Modulus)
+		nb:=q.nbits()
+		k:=NewBIGint(1); k.shl(uint((nb+4)/2))
+		k.add(q)
+		k.div(r)
+
+		for (k.parity()==0) {
+			k.shr(1)
+			WP.dbl()
+		}
+
+		if !k.isunity() {
+			WP=WP.mul(k)
+		}
+		if WP.Is_infinity() {res=INVALID_PUBLIC_KEY}
+
+	}
+	return res
+}
+
+/* IEEE-1363 Diffie-Hellman online calculation Z=S.WD */
+func ECDH_ECPSVDP_DH(S []byte,WD []byte,Z []byte) int {
+	res:=0;
+	var T [EFS]byte
+
+	s:=FromBytes(S)
+
+	W:=ECP_fromBytes(WD)
+	if W.Is_infinity() {res=ERROR}
+
+	if res==0 {
+		r:=NewBIGints(CURVE_Order)
+		s.Mod(r)
+		W=W.mul(s)
+		if W.Is_infinity() { 
+			res=ERROR
+		} else {
+			W.GetX().ToBytes(T[:])
+			for i:=0;i<EFS;i++ {Z[i]=T[i]}
+		}
+	}
+	return res
+}
+
+/* IEEE ECDSA Signature, C and D are signature on F using private key S */
+func ECDH_ECPSP_DSA(sha int,RNG *amcl.RAND,S []byte,F []byte,C []byte,D []byte) int {
+	var T [EFS]byte
+
+	B:=ehashit(sha,F,0,nil,int(MODBYTES));
+	G:=ECP_generator();
+
+	r:=NewBIGints(CURVE_Order)
+
+	s:=FromBytes(S)
+	f:=FromBytes(B[:])
+
+	c:=NewBIGint(0)
+	d:=NewBIGint(0)
+	V:=NewECP()
+
+	for d.iszilch() {
+		u:=Randomnum(r,RNG);
+		w:=Randomnum(r,RNG);  /* side channel masking */
+		//if AES_S>0 {
+		//	u.mod2m(2*AES_S)
+		//}			
+		V.Copy(G)
+		V=V.mul(u)   		
+		vx:=V.GetX()
+		c.copy(vx)
+		c.Mod(r);
+		if c.iszilch() {continue}
+		u.copy(Modmul(u,w,r))
+		u.Invmodp(r)
+		d.copy(Modmul(s,c,r))
+		d.add(f)
+		d.copy(Modmul(d,w,r))
+		d.copy(Modmul(u,d,r))
+	} 
+       
+	c.ToBytes(T[:])
+	for i:=0;i<EFS;i++ {C[i]=T[i]}
+	d.ToBytes(T[:])
+	for i:=0;i<EFS;i++ {D[i]=T[i]}
+	return 0
+}
+
+/* IEEE1363 ECDSA Signature Verification. Signature C and D on F is verified using public key W */
+func ECDH_ECPVP_DSA(sha int,W []byte,F []byte,C []byte,D []byte) int {
+	res:=0
+
+	B:=ehashit(sha,F,0,nil,int(MODBYTES));
+
+	G:=ECP_generator(); 
+	r:=NewBIGints(CURVE_Order)
+
+	c:=FromBytes(C)
+	d:=FromBytes(D)
+	f:=FromBytes(B[:])
+     
+	if (c.iszilch() || Comp(c,r)>=0 || d.iszilch() || Comp(d,r)>=0) {
+            res=INVALID;
+	}
+
+	if res==0 {
+		d.Invmodp(r)
+		f.copy(Modmul(f,d,r))
+		h2:=Modmul(c,d,r)
+
+		WP:=ECP_fromBytes(W)
+		if WP.Is_infinity() {
+			res=ERROR
+		} else {
+			P:=NewECP()
+			P.Copy(WP)
+
+			P=P.Mul2(h2,G,f)
+
+			if P.Is_infinity() {
+				res=INVALID;
+			} else {
+				d=P.GetX()
+				d.Mod(r)
+
+				if Comp(d,c)!=0 {res=INVALID}
+			}
+		}
+	}
+
+	return res
+}
+
+/* IEEE1363 ECIES encryption. Encryption of plaintext M uses public key W and produces ciphertext V,C,T */
+func ECDH_ECIES_ENCRYPT(sha int,P1 []byte,P2 []byte,RNG *amcl.RAND,W []byte,M []byte,V []byte,T []byte) []byte { 
+	var Z [EFS]byte
+	var VZ [3*EFS+1]byte
+	var K1 [AESKEY]byte
+	var K2 [AESKEY]byte
+	var U [EGS]byte
+
+	if ECDH_KEY_PAIR_GENERATE(RNG,U[:],V)!=0 {return nil}
+	if ECDH_ECPSVDP_DH(U[:],W,Z[:])!=0 {return nil}     
+
+	for i:=0;i<2*EFS+1;i++ {VZ[i]=V[i]}
+	for i:=0;i<EFS;i++ {VZ[2*EFS+1+i]=Z[i]}
+
+
+	K:=ECDH_KDF2(sha,VZ[:],P1,2*AESKEY)
+
+	for i:=0;i<AESKEY;i++ {K1[i]=K[i]; K2[i]=K[AESKEY+i]} 
+
+	C:=AES_CBC_IV0_ENCRYPT(K1[:],M)
+
+	L2:=inttoBytes(len(P2),8)	
+	
+	var AC []byte
+
+	for i:=0;i<len(C);i++ {AC=append(AC,C[i])}   
+	for i:=0;i<len(P2);i++ {AC=append(AC,P2[i])}
+	for i:=0;i<8;i++ {AC=append(AC,L2[i])}
+	
+	HMAC(sha,AC,K2[:],T)
+
+	return C
+}
+
+/* constant time n-byte compare */
+func ncomp(T1 []byte,T2 []byte,n int) bool {
+	res:=0
+	for i:=0;i<n;i++ {
+		res|=int(T1[i]^T2[i])
+	}
+	if res==0 {return true}
+	return false;
+}
+
+/* IEEE1363 ECIES decryption. Decryption of ciphertext V,C,T using private key U outputs plaintext M */
+func ECDH_ECIES_DECRYPT(sha int,P1 []byte,P2 []byte,V []byte,C []byte,T []byte,U []byte) []byte { 
+	var Z [EFS]byte
+	var VZ [3*EFS+1]byte
+	var K1 [AESKEY]byte
+	var K2 [AESKEY]byte
+
+	var TAG []byte =T[:]  
+
+	if ECDH_ECPSVDP_DH(U,V,Z[:])!=0 {return nil}
+
+	for i:=0;i<2*EFS+1;i++ {VZ[i]=V[i]}
+	for i:=0;i<EFS;i++ {VZ[2*EFS+1+i]=Z[i]}
+
+	K:=ECDH_KDF2(sha,VZ[:],P1,2*AESKEY)
+
+	for i:=0;i<AESKEY;i++ {K1[i]=K[i]; K2[i]=K[AESKEY+i]} 
+
+	M:=AES_CBC_IV0_DECRYPT(K1[:],C)
+
+	if M==nil {return nil}
+
+	L2:=inttoBytes(len(P2),8)	
+	
+	var AC []byte
+	
+	for i:=0;i<len(C);i++ {AC=append(AC,C[i])}   
+	for i:=0;i<len(P2);i++ {AC=append(AC,P2[i])}
+	for i:=0;i<8;i++ {AC=append(AC,L2[i])}
+	
+	HMAC(sha,AC,K2[:],TAG)
+
+	if !ncomp(T,TAG,len(T)) {return nil}
+	
+//	same:=true
+//	for i:=0;i<len(T);i++ {
+//		if T[i]!=TAG[i] {same=false}
+//	}
+//	if !same {return nil}
+	
+	return M
+}
+
+
diff --git a/version3/go/ECP.go b/version3/go/ECP.go
new file mode 100644
index 0000000..bf1f6b1
--- /dev/null
+++ b/version3/go/ECP.go
@@ -0,0 +1,1038 @@
+/*
+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.
+*/
+
+package XXX
+//import "fmt"
+
+const WEIERSTRASS int=0
+const EDWARDS int=1
+const MONTGOMERY int=2
+const NOT int=0
+const BN int=1
+const BLS int=2
+const D_TYPE int=0
+const M_TYPE int=1
+const POSITIVEX int=0
+const NEGATIVEX int=1
+
+const CURVETYPE int=@CT@
+const CURVE_PAIRING_TYPE int=@PF@
+const SEXTIC_TWIST int=@ST@
+const SIGN_OF_X int=@SX@
+
+const HASH_TYPE int=@HT@
+const AESKEY int=@AK@
+
+/* Elliptic Curve Point Structure */
+
+type ECP struct {
+	x *FP
+	y *FP
+	z *FP
+//	INF bool
+}
+
+/* Constructors */
+func NewECP() *ECP {
+	E:=new(ECP)
+	E.x=NewFPint(0)
+	E.y=NewFPint(1)
+	if CURVETYPE==EDWARDS {
+		E.z=NewFPint(1)
+	} else {
+		E.z=NewFPint(0)
+	}
+//	E.INF=true
+	return E
+}
+
+/* set (x,y) from two BIGs */
+func NewECPbigs(ix *BIG,iy *BIG) *ECP {
+	E:=new(ECP)
+	E.x=NewFPbig(ix)
+	E.y=NewFPbig(iy)
+	E.z=NewFPint(1)
+	E.x.norm()
+	rhs:=RHS(E.x)
+
+	if CURVETYPE==MONTGOMERY {
+		if rhs.jacobi()!=1 {
+			E.inf()
+		}
+	} else {
+		y2:=NewFPcopy(E.y)
+		y2.sqr()
+		if !y2.Equals(rhs) {
+			E.inf()
+		}
+	}
+	return E
+}
+
+/* set (x,y) from BIG and a bit */
+func NewECPbigint(ix *BIG,s int) *ECP {
+	E:=new(ECP)
+	E.x=NewFPbig(ix)
+	E.y=NewFPint(0)
+	E.x.norm()
+	rhs:=RHS(E.x)
+	E.z=NewFPint(1)
+	if rhs.jacobi()==1 {
+		ny:=rhs.sqrt()
+		if ny.redc().parity()!=s {ny.neg()}
+		E.y.copy(ny)
+		//E.INF=false
+	} else {E.inf()}
+	return E;
+}
+
+/* set from x - calculate y from curve equation */
+func NewECPbig(ix *BIG) *ECP {
+	E:=new(ECP)	
+	E.x=NewFPbig(ix)
+	E.y=NewFPint(0)
+	E.x.norm()
+	rhs:=RHS(E.x)
+	E.z=NewFPint(1)
+	if rhs.jacobi()==1 {
+		if CURVETYPE!=MONTGOMERY {E.y.copy(rhs.sqrt())}
+		//E.INF=false
+	} else {E.inf()}
+	return E
+}
+
+/* test for O point-at-infinity */
+func (E *ECP) Is_infinity() bool {
+//	if E.INF {return true}
+	E.x.reduce(); E.z.reduce()
+	if CURVETYPE==EDWARDS {
+		E.y.reduce();
+		return (E.x.iszilch() && E.y.Equals(E.z))
+	} 
+	if CURVETYPE==WEIERSTRASS {
+		E.y.reduce();
+		return (E.x.iszilch() && E.z.iszilch())
+	}
+	if CURVETYPE==MONTGOMERY {
+		return E.z.iszilch()
+	}
+	return true
+}
+
+/* Conditional swap of P and Q dependant on d */
+func (E *ECP) cswap(Q *ECP,d int) {
+	E.x.cswap(Q.x,d)
+	if CURVETYPE!=MONTGOMERY {E.y.cswap(Q.y,d)}
+	E.z.cswap(Q.z,d)
+/*
+	bd:=true
+	if d==0 {bd=false}
+	bd=bd&&(E.INF!=Q.INF)
+	E.INF=(bd!=E.INF)
+	Q.INF=(bd!=Q.INF)
+*/
+}
+
+/* Conditional move of Q to P dependant on d */
+func (E *ECP) cmove(Q *ECP,d int) {
+	E.x.cmove(Q.x,d)
+	if CURVETYPE!=MONTGOMERY {E.y.cmove(Q.y,d)}
+	E.z.cmove(Q.z,d);
+/*
+	bd:=true
+	if d==0 {bd=false}
+	E.INF=(E.INF!=((E.INF!=Q.INF)&&bd))
+*/
+}
+
+/* return 1 if b==c, no branching */
+func teq(b int32,c int32) int {
+	x:=b^c
+	x-=1  // if x=0, x now -1
+	return int((x>>31)&1)
+}
+
+/* this=P */
+func (E *ECP) Copy(P *ECP) {
+	E.x.copy(P.x);
+	if CURVETYPE!=MONTGOMERY {E.y.copy(P.y)}
+	E.z.copy(P.z);
+//	E.INF=P.INF;
+}
+
+/* this=-this */
+func (E *ECP) neg() {
+//	if E.Is_infinity() {return}
+	if CURVETYPE==WEIERSTRASS {
+		E.y.neg(); E.y.norm()
+	}
+	if CURVETYPE==EDWARDS {
+		E.x.neg(); E.x.norm()
+	}
+	return;
+}
+
+/* Constant time select from pre-computed table */
+func (E *ECP) selector(W []*ECP,b int32) {
+	MP:=NewECP()
+	m:=b>>31;
+	babs:=(b^m)-m;
+
+	babs=(babs-1)/2
+
+	E.cmove(W[0],teq(babs,0))  // conditional move
+	E.cmove(W[1],teq(babs,1))
+	E.cmove(W[2],teq(babs,2))
+	E.cmove(W[3],teq(babs,3))
+	E.cmove(W[4],teq(babs,4))
+	E.cmove(W[5],teq(babs,5))
+	E.cmove(W[6],teq(babs,6))
+	E.cmove(W[7],teq(babs,7))
+ 
+	MP.Copy(E);
+	MP.neg()
+	E.cmove(MP,int(m&1));
+}
+
+/* set this=O */
+func (E *ECP) inf() {
+//	E.INF=true;
+	E.x.zero()
+	if CURVETYPE!=MONTGOMERY {E.y.one()}
+	if CURVETYPE!=EDWARDS {
+		E.z.zero()
+	} else {E.z.one()}
+}
+
+/* Test P == Q */
+func( E *ECP) Equals(Q *ECP) bool {
+//	if E.Is_infinity() && Q.Is_infinity() {return true}
+//	if E.Is_infinity() || Q.Is_infinity() {return false}
+
+	a:=NewFPint(0)
+	b:=NewFPint(0)
+	a.copy(E.x); a.mul(Q.z); a.reduce()
+	b.copy(Q.x); b.mul(E.z); b.reduce()
+	if !a.Equals(b) {return false}
+	if CURVETYPE!=MONTGOMERY {
+		a.copy(E.y); a.mul(Q.z); a.reduce()
+		b.copy(Q.y); b.mul(E.z); b.reduce()
+		if !a.Equals(b) {return false}
+	}
+
+	return true
+}
+
+/* Calculate RHS of curve equation */
+func RHS(x *FP) *FP {
+	//x.norm()
+	r:=NewFPcopy(x)
+	r.sqr();
+
+	if CURVETYPE==WEIERSTRASS { // x^3+Ax+B
+		b:=NewFPbig(NewBIGints(CURVE_B))
+		r.mul(x);
+		if CURVE_A==-3 {
+			cx:=NewFPcopy(x)
+			cx.imul(3)
+			cx.neg(); cx.norm()
+			r.add(cx)
+		}
+		r.add(b)
+	}
+	if CURVETYPE==EDWARDS { // (Ax^2-1)/(Bx^2-1) 
+		b:=NewFPbig(NewBIGints(CURVE_B))
+
+		one:=NewFPint(1)
+		b.mul(r)
+		b.sub(one)
+		b.norm()
+		if CURVE_A==-1 {r.neg()}
+		r.sub(one); r.norm()
+		b.inverse()
+		r.mul(b)
+	}
+	if CURVETYPE==MONTGOMERY { // x^3+Ax^2+x
+		x3:=NewFPint(0)
+		x3.copy(r)
+		x3.mul(x)
+		r.imul(CURVE_A)
+		r.add(x3)
+		r.add(x)
+	}
+	r.reduce()
+	return r
+}
+
+/* set to affine - from (x,y,z) to (x,y) */
+func (E *ECP) Affine() {
+	if E.Is_infinity() {return}
+	one:=NewFPint(1)
+	if E.z.Equals(one) {return}
+	E.z.inverse()
+	E.x.mul(E.z); E.x.reduce()
+
+	if CURVETYPE!=MONTGOMERY {
+		E.y.mul(E.z); E.y.reduce()
+	}
+	E.z.copy(one)
+}
+
+/* extract x as a BIG */
+func (E *ECP) GetX() *BIG {
+	W:=NewECP(); W.Copy(E)
+	W.Affine()
+	return W.x.redc()
+}
+/* extract y as a BIG */
+func (E *ECP) GetY() *BIG {
+	W:=NewECP(); W.Copy(E)
+	W.Affine()
+	return W.y.redc()
+}
+
+/* get sign of Y */
+func (E *ECP) GetS() int {
+	//E.Affine()
+	y:=E.GetY()
+	return y.parity()
+}
+/* extract x as an FP */
+func (E *ECP) getx() *FP {
+	return E.x;
+}
+/* extract y as an FP */
+func (E *ECP) gety() *FP {
+	return E.y
+}
+/* extract z as an FP */
+func (E *ECP) getz() *FP {
+	return E.z
+}
+
+/* convert to byte array */
+func (E *ECP) ToBytes(b []byte,compress bool) {
+	var t [int(MODBYTES)]byte
+	MB:=int(MODBYTES)
+	W:=NewECP(); W.Copy(E);
+	W.Affine()
+	W.x.redc().ToBytes(t[:])
+	for i:=0;i<MB;i++ {b[i+1]=t[i]}
+
+	if CURVETYPE==MONTGOMERY {
+		b[0]=0x06
+		return;
+	} 
+
+	if compress {
+		b[0]=0x02
+		if W.y.redc().parity()==1 {b[0]=0x03}
+		return;
+	}
+	
+	b[0]=0x04
+
+	W.y.redc().ToBytes(t[:])
+	for i:=0;i<MB;i++ {b[i+MB+1]=t[i]}
+}
+
+/* convert from byte array to point */
+func ECP_fromBytes(b []byte) *ECP {
+	var t [int(MODBYTES)]byte
+	MB:=int(MODBYTES)
+	p:=NewBIGints(Modulus)
+
+	for i:=0;i<MB;i++ {t[i]=b[i+1]}
+	px:=FromBytes(t[:])
+	if Comp(px,p)>=0 {return NewECP()}
+
+	if CURVETYPE==MONTGOMERY {
+		return NewECPbig(px)
+	}
+
+	if b[0]==0x04 {
+		for i:=0;i<MB;i++ {t[i]=b[i+MB+1]}
+		py:=FromBytes(t[:])
+		if Comp(py,p)>=0 {return NewECP()}
+		return NewECPbigs(px,py)
+	}
+
+	if b[0]==0x02 || b[0]==0x03 {
+		return NewECPbigint(px,int(b[0]&1))
+	}
+
+	return NewECP()
+}
+
+/* convert to hex string */
+func (E *ECP) ToString() string {
+	W:=NewECP(); W.Copy(E);
+	W.Affine()
+	if W.Is_infinity() {return "infinity"}
+	if CURVETYPE==MONTGOMERY {
+		return "("+W.x.redc().ToString()+")"
+	} else {return "("+W.x.redc().ToString()+","+W.y.redc().ToString()+")"}
+}
+
+/* this*=2 */
+func (E *ECP) dbl() {
+
+//	if E.INF {return}
+	if CURVETYPE==WEIERSTRASS {
+		if CURVE_A==0 {
+			t0:=NewFPcopy(E.y)                      /*** Change ***/    // Edits made
+			t0.sqr()
+			t1:=NewFPcopy(E.y)
+			t1.mul(E.z)
+			t2:=NewFPcopy(E.z)
+			t2.sqr()
+
+			E.z.copy(t0)
+			E.z.add(t0); E.z.norm(); 
+			E.z.add(E.z); E.z.add(E.z); E.z.norm()
+			t2.imul(3*CURVE_B_I)
+
+			x3:=NewFPcopy(t2)
+			x3.mul(E.z)
+
+			y3:=NewFPcopy(t0)
+			y3.add(t2); y3.norm()
+			E.z.mul(t1)
+			t1.copy(t2); t1.add(t2); t2.add(t1)
+			t0.sub(t2); t0.norm(); y3.mul(t0); y3.add(x3)
+			t1.copy(E.x); t1.mul(E.y) 
+			E.x.copy(t0); E.x.norm(); E.x.mul(t1); E.x.add(E.x)
+			E.x.norm(); 
+			E.y.copy(y3); E.y.norm();
+		} else {
+			t0:=NewFPcopy(E.x)
+			t1:=NewFPcopy(E.y)
+			t2:=NewFPcopy(E.z)
+			t3:=NewFPcopy(E.x)
+			z3:=NewFPcopy(E.z)
+			y3:=NewFPint(0)
+			x3:=NewFPint(0)
+			b:=NewFPint(0)
+
+			if CURVE_B_I==0 {b.copy(NewFPbig(NewBIGints(CURVE_B)))}
+
+			t0.sqr()  //1    x^2
+			t1.sqr()  //2    y^2
+			t2.sqr()  //3
+
+			t3.mul(E.y) //4
+			t3.add(t3); t3.norm() //5
+			z3.mul(E.x);   //6
+			z3.add(z3);  z3.norm()//7
+			y3.copy(t2) 
+				
+			if CURVE_B_I==0 {
+				y3.mul(b)
+			} else {
+				y3.imul(CURVE_B_I)
+			}
+				
+			y3.sub(z3) //y3.norm(); //9  ***
+			x3.copy(y3); x3.add(y3); x3.norm() //10
+
+			y3.add(x3) //y3.norm();//11
+			x3.copy(t1); x3.sub(y3); x3.norm() //12
+			y3.add(t1); y3.norm() //13
+			y3.mul(x3)  //14
+			x3.mul(t3)  //15
+			t3.copy(t2); t3.add(t2)  //t3.norm(); //16
+			t2.add(t3)  //t2.norm(); //17
+
+			if CURVE_B_I==0 {
+				z3.mul(b)
+			} else {
+				z3.imul(CURVE_B_I)
+			}
+
+			z3.sub(t2) //z3.norm();//19
+			z3.sub(t0); z3.norm()//20  ***
+			t3.copy(z3); t3.add(z3) //t3.norm();//21
+
+			z3.add(t3); z3.norm()  //22
+			t3.copy(t0); t3.add(t0)  //t3.norm(); //23
+			t0.add(t3)  //t0.norm();//24
+			t0.sub(t2); t0.norm() //25
+
+			t0.mul(z3) //26
+			y3.add(t0) //y3.norm();//27
+			t0.copy(E.y); t0.mul(E.z)//28
+			t0.add(t0); t0.norm() //29
+			z3.mul(t0)//30
+			x3.sub(z3) //x3.norm();//31
+			t0.add(t0); t0.norm() //32
+			t1.add(t1); t1.norm() //33
+			z3.copy(t0); z3.mul(t1) //34
+
+			E.x.copy(x3); E.x.norm() 
+			E.y.copy(y3); E.y.norm()
+			E.z.copy(z3); E.z.norm()
+		}
+	}
+
+	if CURVETYPE==EDWARDS {
+		C:=NewFPcopy(E.x)
+		D:=NewFPcopy(E.y)
+		H:=NewFPcopy(E.z)
+		J:=NewFPint(0)
+	
+		E.x.mul(E.y); E.x.add(E.x); E.x.norm()
+		C.sqr()
+		D.sqr()
+		if CURVE_A==-1 {C.neg()}	
+		E.y.copy(C); E.y.add(D); E.y.norm()
+
+		H.sqr(); H.add(H)
+		E.z.copy(E.y)
+		J.copy(E.y); J.sub(H); J.norm()
+		E.x.mul(J)
+		C.sub(D); C.norm()
+		E.y.mul(C)
+		E.z.mul(J)
+
+
+	}
+	if CURVETYPE==MONTGOMERY {
+		A:=NewFPcopy(E.x)
+		B:=NewFPcopy(E.x)	
+		AA:=NewFPint(0)
+		BB:=NewFPint(0)
+		C:=NewFPint(0)
+	
+	//	if E.INF {return}
+
+		A.add(E.z); A.norm()
+		AA.copy(A); AA.sqr()
+		B.sub(E.z); B.norm()
+		BB.copy(B); BB.sqr()
+		C.copy(AA); C.sub(BB)
+		C.norm()
+
+		E.x.copy(AA); E.x.mul(BB)
+
+		A.copy(C); A.imul((CURVE_A+2)/4)
+
+		BB.add(A); BB.norm()
+		E.z.copy(BB); E.z.mul(C)
+	}
+	return;
+}
+
+/* this+=Q */
+func (E *ECP) Add(Q *ECP) {
+/*
+	if E.INF {
+		E.Copy(Q)
+		return
+	}
+	if Q.INF {return}
+*/
+	if CURVETYPE==WEIERSTRASS {
+		if CURVE_A==0 {
+			b:=3*CURVE_B_I
+			t0:=NewFPcopy(E.x)
+			t0.mul(Q.x)
+			t1:=NewFPcopy(E.y)
+			t1.mul(Q.y)
+			t2:=NewFPcopy(E.z)
+			t2.mul(Q.z)
+			t3:=NewFPcopy(E.x)
+			t3.add(E.y); t3.norm()
+			t4:=NewFPcopy(Q.x)
+			t4.add(Q.y); t4.norm()
+			t3.mul(t4)
+			t4.copy(t0); t4.add(t1)
+
+			t3.sub(t4); t3.norm()
+			t4.copy(E.y)
+			t4.add(E.z); t4.norm()
+			x3:=NewFPcopy(Q.y)
+			x3.add(Q.z); x3.norm()
+
+			t4.mul(x3)
+			x3.copy(t1)
+			x3.add(t2)
+	
+			t4.sub(x3); t4.norm()
+			x3.copy(E.x); x3.add(E.z); x3.norm()
+			y3:=NewFPcopy(Q.x)
+			y3.add(Q.z); y3.norm()
+			x3.mul(y3)
+			y3.copy(t0)
+			y3.add(t2)
+			y3.rsub(x3); y3.norm()
+			x3.copy(t0); x3.add(t0) 
+			t0.add(x3); t0.norm()
+			t2.imul(b)
+
+			z3:=NewFPcopy(t1); z3.add(t2); z3.norm()
+			t1.sub(t2); t1.norm() 
+			y3.imul(b)
+	
+			x3.copy(y3); x3.mul(t4); t2.copy(t3); t2.mul(t1); x3.rsub(t2)
+			y3.mul(t0); t1.mul(z3); y3.add(t1)
+			t0.mul(t3); z3.mul(t4); z3.add(t0)
+
+			E.x.copy(x3); E.x.norm()
+			E.y.copy(y3); E.y.norm()
+			E.z.copy(z3); E.z.norm()	
+		} else {
+
+			t0:=NewFPcopy(E.x)
+			t1:=NewFPcopy(E.y)
+			t2:=NewFPcopy(E.z)
+			t3:=NewFPcopy(E.x)
+			t4:=NewFPcopy(Q.x)
+			z3:=NewFPint(0)
+			y3:=NewFPcopy(Q.x)
+			x3:=NewFPcopy(Q.y)
+			b:=NewFPint(0)
+
+			if CURVE_B_I==0 {b.copy(NewFPbig(NewBIGints(CURVE_B)))}
+
+			t0.mul(Q.x) //1
+			t1.mul(Q.y) //2
+			t2.mul(Q.z) //3
+
+			t3.add(E.y); t3.norm() //4
+			t4.add(Q.y); t4.norm() //5
+			t3.mul(t4) //6
+			t4.copy(t0); t4.add(t1) //t4.norm(); //7
+			t3.sub(t4); t3.norm() //8
+			t4.copy(E.y); t4.add(E.z); t4.norm() //9
+			x3.add(Q.z); x3.norm() //10
+			t4.mul(x3) //11
+			x3.copy(t1); x3.add(t2) //x3.norm();//12
+
+			t4.sub(x3); t4.norm() //13
+			x3.copy(E.x); x3.add(E.z); x3.norm() //14
+			y3.add(Q.z); y3.norm() //15
+
+			x3.mul(y3) //16
+			y3.copy(t0); y3.add(t2) //y3.norm();//17
+
+			y3.rsub(x3); y3.norm() //18
+			z3.copy(t2) 
+				
+			if CURVE_B_I==0 {
+				z3.mul(b)
+			} else {
+				z3.imul(CURVE_B_I)
+			}
+				
+			x3.copy(y3); x3.sub(z3); x3.norm() //20
+			z3.copy(x3); z3.add(x3) //z3.norm(); //21
+
+			x3.add(z3) //x3.norm(); //22
+			z3.copy(t1); z3.sub(x3); z3.norm() //23
+			x3.add(t1); x3.norm() //24
+
+			if CURVE_B_I==0 {
+				y3.mul(b)
+			} else {
+				y3.imul(CURVE_B_I)
+			}
+
+			t1.copy(t2); t1.add(t2); //t1.norm();//26
+			t2.add(t1) //t2.norm();//27
+
+			y3.sub(t2) //y3.norm(); //28
+
+			y3.sub(t0); y3.norm() //29
+			t1.copy(y3); t1.add(y3) //t1.norm();//30
+			y3.add(t1); y3.norm() //31
+
+			t1.copy(t0); t1.add(t0) //t1.norm(); //32
+			t0.add(t1) //t0.norm();//33
+			t0.sub(t2); t0.norm() //34
+			t1.copy(t4); t1.mul(y3) //35
+			t2.copy(t0); t2.mul(y3) //36
+			y3.copy(x3); y3.mul(z3) //37
+			y3.add(t2) //y3.norm();//38
+			x3.mul(t3) //39
+			x3.sub(t1) //40
+			z3.mul(t4) //41
+			t1.copy(t3); t1.mul(t0) //42
+			z3.add(t1) 
+			E.x.copy(x3); E.x.norm() 
+			E.y.copy(y3); E.y.norm()
+			E.z.copy(z3); E.z.norm()
+
+		}
+	}
+	if CURVETYPE==EDWARDS {
+		b:=NewFPbig(NewBIGints(CURVE_B))
+		A:=NewFPcopy(E.z)
+		B:=NewFPint(0)
+		C:=NewFPcopy(E.x)
+		D:=NewFPcopy(E.y)
+		EE:=NewFPint(0)
+		F:=NewFPint(0)
+		G:=NewFPint(0)
+	
+		A.mul(Q.z);
+		B.copy(A); B.sqr()
+		C.mul(Q.x)
+		D.mul(Q.y)
+
+		EE.copy(C); EE.mul(D); EE.mul(b)
+		F.copy(B); F.sub(EE)
+		G.copy(B); G.add(EE)
+
+		if CURVE_A==1 {
+			EE.copy(D); EE.sub(C)
+		}
+		C.add(D)
+
+		B.copy(E.x); B.add(E.y)
+		D.copy(Q.x); D.add(Q.y)
+		B.norm(); D.norm()
+		B.mul(D)
+		B.sub(C)
+		B.norm(); F.norm()
+		B.mul(F)
+		E.x.copy(A); E.x.mul(B)
+		G.norm()
+		if CURVE_A==1 {
+			EE.norm(); C.copy(EE); C.mul(G)
+		}
+		if CURVE_A==-1 {
+			C.norm(); C.mul(G)
+		}
+		E.y.copy(A); E.y.mul(C)
+		E.z.copy(F); E.z.mul(G)
+	}
+	return
+}
+
+/* Differential Add for Montgomery curves. this+=Q where W is this-Q and is affine. */
+func (E *ECP) dadd(Q *ECP,W *ECP) {
+	A:=NewFPcopy(E.x)
+	B:=NewFPcopy(E.x)
+	C:=NewFPcopy(Q.x)
+	D:=NewFPcopy(Q.x)
+	DA:=NewFPint(0)
+	CB:=NewFPint(0)
+			
+	A.add(E.z)
+	B.sub(E.z)
+
+	C.add(Q.z)
+	D.sub(Q.z)
+	A.norm(); D.norm()
+
+	DA.copy(D); DA.mul(A)
+	C.norm(); B.norm()
+
+	CB.copy(C); CB.mul(B)
+
+	A.copy(DA); A.add(CB); A.norm(); A.sqr()
+	B.copy(DA); B.sub(CB); B.norm(); B.sqr()
+
+	E.x.copy(A)
+	E.z.copy(W.x); E.z.mul(B)
+
+//	if E.z.iszilch() {
+//		E.inf()
+//	} else {E.INF=false;}
+
+}
+
+/* this-=Q */
+func (E *ECP) Sub(Q *ECP) {
+	NQ:=NewECP(); NQ.Copy(Q);
+	NQ.neg()
+	E.Add(NQ)
+}
+
+/* constant time multiply by small integer of length bts - use ladder */
+func (E *ECP) pinmul(e int32,bts int32) *ECP {	
+	if CURVETYPE==MONTGOMERY {
+		return E.mul(NewBIGint(int(e)))
+	} else {
+		P:=NewECP()
+		R0:=NewECP()
+		R1:=NewECP(); R1.Copy(E)
+
+		for i:=bts-1;i>=0;i-- {
+			b:=int((e>>uint32(i))&1)
+			P.Copy(R1)
+			P.Add(R0)
+			R0.cswap(R1,b)
+			R1.Copy(P)
+			R0.dbl()
+			R0.cswap(R1,b)
+		}
+		P.Copy(R0)
+		P.Affine()
+		return P
+	}
+}
+
+/* return e.this */
+
+func (E *ECP) mul(e *BIG) *ECP {
+	if (e.iszilch() || E.Is_infinity()) {return NewECP()}
+	P:=NewECP()
+	if CURVETYPE==MONTGOMERY {
+/* use Ladder */
+		D:=NewECP();
+		R0:=NewECP(); R0.Copy(E)
+		R1:=NewECP(); R1.Copy(E)
+		R1.dbl()
+		D.Copy(E); D.Affine()
+		nb:=e.nbits()
+		for i:=nb-2;i>=0;i-- {
+			b:=int(e.bit(i))
+			P.Copy(R1)
+			P.dadd(R0,D)
+			R0.cswap(R1,b)
+			R1.Copy(P)
+			R0.dbl()
+			R0.cswap(R1,b)
+		}
+		P.Copy(R0)
+	} else {
+// fixed size windows 
+		mt:=NewBIG()
+		t:=NewBIG()
+		Q:=NewECP()
+		C:=NewECP()
+
+		var W []*ECP
+		var w [1+(NLEN*int(BASEBITS)+3)/4]int8
+
+		//E.Affine();
+
+		Q.Copy(E);
+		Q.dbl();
+
+		W=append(W,NewECP());
+		W[0].Copy(E);
+
+		for i:=1;i<8;i++ {
+			W=append(W,NewECP())
+			W[i].Copy(W[i-1])
+			W[i].Add(Q)
+		}
+
+// make exponent odd - add 2P if even, P if odd 
+		t.copy(e)
+		s:=int(t.parity())
+		t.inc(1); t.norm(); ns:=int(t.parity()); mt.copy(t); mt.inc(1); mt.norm()
+		t.cmove(mt,s)
+		Q.cmove(E,ns)
+		C.Copy(Q)
+
+		nb:=1+(t.nbits()+3)/4
+
+// convert exponent to signed 4-bit window 
+		for i:=0;i<nb;i++ {
+			w[i]=int8(t.lastbits(5)-16)
+			t.dec(int(w[i])); t.norm()
+			t.fshr(4)	
+		}
+		w[nb]=int8(t.lastbits(5))
+
+		P.Copy(W[(int(w[nb])-1)/2])  
+		for i:=nb-1;i>=0;i-- {
+			Q.selector(W,int32(w[i]))
+			P.dbl()
+			P.dbl()
+			P.dbl()
+			P.dbl()
+			P.Add(Q)
+		}
+		P.Sub(C) /* apply correction */
+	}
+	P.Affine()
+	return P
+}
+
+/* Public version */
+func (E *ECP) Mul(e *BIG) *ECP {
+	return E.mul(e)
+}
+
+/* Return e.this+f.Q */
+
+func (E *ECP) Mul2(e *BIG,Q *ECP,f *BIG) *ECP {
+	te:=NewBIG()
+	tf:=NewBIG()
+	mt:=NewBIG()
+	S:=NewECP()
+	T:=NewECP()
+	C:=NewECP()
+	var W [] *ECP
+	//ECP[] W=new ECP[8];
+	var w [1+(NLEN*int(BASEBITS)+1)/2]int8		
+
+	//E.Affine()
+	//Q.Affine()
+
+	te.copy(e)
+	tf.copy(f)
+
+// precompute table 
+	for i:=0;i<8;i++ {
+		W=append(W,NewECP())
+	}
+	W[1].Copy(E); W[1].Sub(Q)
+	W[2].Copy(E); W[2].Add(Q);
+	S.Copy(Q); S.dbl();
+	W[0].Copy(W[1]); W[0].Sub(S);
+	W[3].Copy(W[2]); W[3].Add(S);
+	T.Copy(E); T.dbl();
+	W[5].Copy(W[1]); W[5].Add(T);
+	W[6].Copy(W[2]); W[6].Add(T);
+	W[4].Copy(W[5]); W[4].Sub(S);
+	W[7].Copy(W[6]); W[7].Add(S);
+
+// if multiplier is odd, add 2, else add 1 to multiplier, and add 2P or P to correction 
+
+	s:=int(te.parity());
+	te.inc(1); te.norm(); ns:=int(te.parity()); mt.copy(te); mt.inc(1); mt.norm()
+	te.cmove(mt,s)
+	T.cmove(E,ns)
+	C.Copy(T)
+
+	s=int(tf.parity())
+	tf.inc(1); tf.norm(); ns=int(tf.parity()); mt.copy(tf); mt.inc(1); mt.norm()
+	tf.cmove(mt,s)
+	S.cmove(Q,ns)
+	C.Add(S)
+
+	mt.copy(te); mt.add(tf); mt.norm()
+	nb:=1+(mt.nbits()+1)/2
+
+// convert exponent to signed 2-bit window 
+	for i:=0;i<nb;i++ {
+		a:=(te.lastbits(3)-4)
+		te.dec(int(a)); te.norm()
+		te.fshr(2)
+		b:=(tf.lastbits(3)-4)
+		tf.dec(int(b)); tf.norm()
+		tf.fshr(2)
+		w[i]=int8(4*a+b)
+	}
+	w[nb]=int8(4*te.lastbits(3)+tf.lastbits(3))
+	S.Copy(W[(w[nb]-1)/2])  
+
+	for i:=nb-1;i>=0;i-- {
+		T.selector(W,int32(w[i]));
+		S.dbl()
+		S.dbl()
+		S.Add(T)
+	}
+	S.Sub(C) /* apply correction */
+	S.Affine()
+	return S
+}
+
+func (E *ECP) cfp() {
+	cf:=CURVE_Cof_I;
+	if cf==1 {return}
+	if cf==4 {
+		E.dbl(); E.dbl()
+		//E.Affine();
+		return;
+	} 
+	if cf==8 {
+		E.dbl(); E.dbl(); E.dbl()
+		//E.Affine();
+		return;
+	}
+	c:=NewBIGints(CURVE_Cof);
+	E.Copy(E.mul(c));
+}
+
+func ECP_mapit(h []byte) *ECP {
+	q:=NewBIGints(Modulus)
+	x:=FromBytes(h[:])
+	x.Mod(q)
+	var P *ECP
+
+	for true {
+		for true {
+			if CURVETYPE!=MONTGOMERY {
+				P=NewECPbigint(x,0)
+			} else {
+				P=NewECPbig(x)
+			}
+			x.inc(1); x.norm()
+			if !P.Is_infinity() {break}
+		}
+		P.cfp()
+		if !P.Is_infinity() {break}
+	}
+			
+	return P
+}
+
+func ECP_generator() *ECP {
+	var G *ECP
+
+	gx:=NewBIGints(CURVE_Gx)
+	if CURVETYPE!=MONTGOMERY {
+		gy:=NewBIGints(CURVE_Gy)
+		G=NewECPbigs(gx,gy)
+	} else {
+		G=NewECPbig(gx)
+	}
+	return G
+}
+
+/*
+func main() {
+	Gx:=NewBIGints(CURVE_Gx);
+	var Gy *BIG
+	var P *ECP
+
+	if CURVETYPE!=MONTGOMERY {Gy=NewBIGints(CURVE_Gy)}
+	r:=NewBIGints(CURVE_Order)
+
+	//r.dec(7);
+	
+	fmt.Printf("Gx= "+Gx.ToString())
+	fmt.Printf("\n")
+
+	if CURVETYPE!=MONTGOMERY {
+		fmt.Printf("Gy= "+Gy.ToString())
+		fmt.Printf("\n")
+	}	
+
+	if CURVETYPE!=MONTGOMERY {
+		P=NewECPbigs(Gx,Gy)
+	} else  {P=NewECPbig(Gx)}
+
+	fmt.Printf("P= "+P.ToString());		
+	fmt.Printf("\n")
+
+	R:=P.mul(r);
+		//for (int i=0;i<10000;i++)
+		//	R=P.mul(r);
+	
+	fmt.Printf("R= "+R.ToString())
+	fmt.Printf("\n")
+}
+*/
\ No newline at end of file
diff --git a/version3/go/ECP2.go b/version3/go/ECP2.go
new file mode 100644
index 0000000..b29c763
--- /dev/null
+++ b/version3/go/ECP2.go
@@ -0,0 +1,701 @@
+/*
+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.
+*/
+
+/* MiotCL Weierstrass elliptic curve functions over FP2 */
+
+package XXX
+
+//import "fmt"
+
+type ECP2 struct {
+	x *FP2
+	y *FP2
+	z *FP2
+//	INF bool
+}
+
+func NewECP2() *ECP2 {
+	E:=new(ECP2)
+	E.x=NewFP2int(0)
+	E.y=NewFP2int(1)
+	E.z=NewFP2int(0)
+//	E.INF=true
+	return E
+}
+
+/* Test this=O? */
+func (E *ECP2) Is_infinity() bool {
+//	if E.INF {return true}
+	E.x.reduce(); E.y.reduce(); E.z.reduce()
+	return E.x.iszilch() && E.z.iszilch()
+}
+/* copy this=P */
+func (E *ECP2) Copy(P *ECP2) {
+	E.x.copy(P.x)
+	E.y.copy(P.y)
+	E.z.copy(P.z)
+//	E.INF=P.INF
+}
+/* set this=O */
+func (E *ECP2) inf() {
+//	E.INF=true
+	E.x.zero()
+	E.y.one()
+	E.z.zero()
+}
+
+/* set this=-this */
+func (E *ECP2) neg() {
+//	if E.Is_infinity() {return}
+	E.y.norm(); E.y.neg(); E.y.norm()
+}
+
+/* Conditional move of Q to P dependant on d */
+func (E *ECP2) cmove(Q *ECP2,d int) {
+	E.x.cmove(Q.x,d)
+	E.y.cmove(Q.y,d)
+	E.z.cmove(Q.z,d)
+/*
+	var bd bool
+	if (d==0) {
+		bd=false
+	} else {bd=true}
+	E.INF=(E.INF!=(E.INF!=Q.INF)&&bd)
+*/
+}
+
+/* Constant time select from pre-computed table */
+func (E *ECP2) selector(W []*ECP2,b int32) {
+	MP:=NewECP2() 
+	m:=b>>31
+	babs:=(b^m)-m
+
+	babs=(babs-1)/2
+
+	E.cmove(W[0],teq(babs,0))  // conditional move
+	E.cmove(W[1],teq(babs,1))
+	E.cmove(W[2],teq(babs,2))
+	E.cmove(W[3],teq(babs,3))
+	E.cmove(W[4],teq(babs,4))
+	E.cmove(W[5],teq(babs,5))
+	E.cmove(W[6],teq(babs,6))
+	E.cmove(W[7],teq(babs,7))
+ 
+	MP.Copy(E)
+	MP.neg()
+	E.cmove(MP,int(m&1))
+}
+
+/* Test if P == Q */
+func (E *ECP2) Equals(Q *ECP2) bool {
+//	if E.Is_infinity() && Q.Is_infinity() {return true}
+//	if E.Is_infinity() || Q.Is_infinity() {return false}
+
+	a:=NewFP2copy(E.x)
+	b:=NewFP2copy(Q.x)
+	a.mul(Q.z); b.mul(E.z)
+
+	if !a.Equals(b) {return false}
+	a.copy(E.y); b.copy(Q.y)
+	a.mul(Q.z); b.mul(E.z);
+	if !a.Equals(b) {return false}
+
+	return true
+}
+
+/* set to Affine - (x,y,z) to (x,y) */
+func (E *ECP2) Affine() {
+	if E.Is_infinity() {return}
+	one:=NewFP2int(1)
+	if E.z.Equals(one) {E.x.reduce(); E.y.reduce(); return}
+	E.z.inverse()
+
+	E.x.mul(E.z); E.x.reduce()
+	E.y.mul(E.z); E.y.reduce()
+	E.z.copy(one)
+}
+
+/* extract affine x as FP2 */
+func (E *ECP2) GetX() *FP2 {
+	W:=NewECP2(); W.Copy(E)
+	W.Affine()
+	return W.x
+}
+/* extract affine y as FP2 */
+func (E *ECP2) GetY() *FP2 {
+	W:=NewECP2(); W.Copy(E)
+	W.Affine()
+	return W.y;
+}
+/* extract projective x */
+func (E *ECP2) getx() *FP2 {
+	return E.x
+}
+/* extract projective y */
+func (E *ECP2) gety() *FP2 {
+	return E.y
+}
+/* extract projective z */
+func (E *ECP2) getz() *FP2 {
+	return E.z
+}
+
+/* convert to byte array */
+func (E *ECP2) ToBytes(b []byte) {
+	var t [int(MODBYTES)]byte
+	MB:=int(MODBYTES)
+
+	W:=NewECP2(); W.Copy(E);
+	W.Affine()
+
+	W.x.GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ { b[i]=t[i]}
+	W.x.GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ { b[i+MB]=t[i]}
+
+	W.y.GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ {b[i+2*MB]=t[i]}
+	W.y.GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ {b[i+3*MB]=t[i]}
+}
+
+/* convert from byte array to point */
+func ECP2_fromBytes(b []byte) *ECP2 {
+	var t [int(MODBYTES)]byte
+	MB:=int(MODBYTES)
+
+	for i:=0;i<MB;i++ {t[i]=b[i]}
+	ra:=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=b[i+MB]}
+	rb:=FromBytes(t[:])
+	rx:=NewFP2bigs(ra,rb)
+
+	for i:=0;i<MB;i++ {t[i]=b[i+2*MB]}
+	ra=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=b[i+3*MB]}
+	rb=FromBytes(t[:])
+	ry:=NewFP2bigs(ra,rb)
+
+	return NewECP2fp2s(rx,ry)
+}
+
+/* convert this to hex string */
+func (E *ECP2) ToString() string {
+	W:=NewECP2(); W.Copy(E);
+	W.Affine()
+	if W.Is_infinity() {return "infinity"}
+	return "("+W.x.toString()+","+W.y.toString()+")"
+}
+
+/* Calculate RHS of twisted curve equation x^3+B/i */
+func RHS2(x *FP2) *FP2 {
+	//x.norm()
+	r:=NewFP2copy(x)
+	r.sqr()
+	b:=NewFP2big(NewBIGints(CURVE_B))
+
+	if SEXTIC_TWIST == D_TYPE {
+		b.div_ip()
+	}
+	if SEXTIC_TWIST == M_TYPE {
+		b.norm()
+		b.mul_ip()
+		b.norm()
+	}	
+	r.mul(x)
+	r.add(b)
+
+	r.reduce()
+	return r
+}
+
+/* construct this from (x,y) - but set to O if not on curve */
+func NewECP2fp2s(ix *FP2,iy *FP2) *ECP2 {
+	E:=new(ECP2)
+	E.x=NewFP2copy(ix)
+	E.y=NewFP2copy(iy)
+	E.z=NewFP2int(1)
+	E.x.norm()
+	rhs:=RHS2(E.x)
+	y2:=NewFP2copy(E.y)
+	y2.sqr()
+	if !y2.Equals(rhs) {
+		E.inf()
+	} 
+	return E
+}
+
+/* construct this from x - but set to O if not on curve */
+func NewECP2fp2(ix *FP2) *ECP2 {	
+	E:=new(ECP2)
+	E.x=NewFP2copy(ix)
+	E.y=NewFP2int(1)
+	E.z=NewFP2int(1)
+	E.x.norm()
+	rhs:=RHS2(E.x)
+	if rhs.sqrt() {
+			E.y.copy(rhs)
+			//E.INF=false;
+	} else {E.inf()}
+	return E
+}
+
+/* this+=this */
+func (E *ECP2) dbl() int {
+//	if E.INF {return -1}
+
+	iy:=NewFP2copy(E.y)
+	if SEXTIC_TWIST == D_TYPE {
+		iy.mul_ip(); iy.norm()
+	}
+
+	t0:=NewFP2copy(E.y)                  //***** Change 
+	t0.sqr();  
+	if SEXTIC_TWIST == D_TYPE {	
+		t0.mul_ip()   
+	}
+	t1:=NewFP2copy(iy)  
+	t1.mul(E.z)
+	t2:=NewFP2copy(E.z)
+	t2.sqr()			// z^2
+
+	E.z.copy(t0)			// y^2
+	E.z.add(t0); E.z.norm()		// 2y^2	
+	E.z.add(E.z)
+	E.z.add(E.z)			// 8y^2
+	E.z.norm()  
+
+	t2.imul(3*CURVE_B_I)		// 3bz^2
+	if SEXTIC_TWIST == M_TYPE {
+		t2.mul_ip()
+		t2.norm()
+	}
+	x3:=NewFP2copy(t2)
+	x3.mul(E.z) 
+
+	y3:=NewFP2copy(t0)   
+
+	y3.add(t2); y3.norm()
+	E.z.mul(t1)
+	t1.copy(t2); t1.add(t2); t2.add(t1); t2.norm()  
+	t0.sub(t2); t0.norm()                           //y^2-9bz^2
+	y3.mul(t0); y3.add(x3)                          //(y^2+3z*2)(y^2-9z^2)+3b.z^2.8y^2
+	t1.copy(E.x); t1.mul(iy)						//
+	E.x.copy(t0); E.x.norm(); E.x.mul(t1); E.x.add(E.x)       //(y^2-9bz^2)xy2
+
+	E.x.norm()
+	E.y.copy(y3); E.y.norm()
+
+	return 1
+}
+
+/* this+=Q - return 0 for add, 1 for double, -1 for O */
+func (E *ECP2) Add(Q *ECP2) int {
+/*	if E.INF {
+		E.Copy(Q)
+		return -1
+	}
+	if Q.INF {return -1}
+*/
+	b:=3*CURVE_B_I
+	t0:=NewFP2copy(E.x)
+	t0.mul(Q.x)         // x.Q.x
+	t1:=NewFP2copy(E.y)
+	t1.mul(Q.y)		 // y.Q.y
+
+	t2:=NewFP2copy(E.z)
+	t2.mul(Q.z)
+	t3:=NewFP2copy(E.x)
+	t3.add(E.y); t3.norm()          //t3=X1+Y1
+	t4:=NewFP2copy(Q.x)            
+	t4.add(Q.y); t4.norm()			//t4=X2+Y2
+	t3.mul(t4)						//t3=(X1+Y1)(X2+Y2)
+	t4.copy(t0); t4.add(t1)		//t4=X1.X2+Y1.Y2
+
+	t3.sub(t4); t3.norm(); 
+	if SEXTIC_TWIST == D_TYPE {
+		t3.mul_ip();  t3.norm()         //t3=(X1+Y1)(X2+Y2)-(X1.X2+Y1.Y2) = X1.Y2+X2.Y1
+	}
+	t4.copy(E.y);                    
+	t4.add(E.z); t4.norm()			//t4=Y1+Z1
+	x3:=NewFP2copy(Q.y)
+	x3.add(Q.z); x3.norm()			//x3=Y2+Z2
+
+	t4.mul(x3)						//t4=(Y1+Z1)(Y2+Z2)
+	x3.copy(t1)					//
+	x3.add(t2)						//X3=Y1.Y2+Z1.Z2
+	
+	t4.sub(x3); t4.norm();
+	if SEXTIC_TWIST == D_TYPE {	
+		t4.mul_ip(); t4.norm()          //t4=(Y1+Z1)(Y2+Z2) - (Y1.Y2+Z1.Z2) = Y1.Z2+Y2.Z1
+	}
+	x3.copy(E.x); x3.add(E.z); x3.norm()	// x3=X1+Z1
+	y3:=NewFP2copy(Q.x)				
+	y3.add(Q.z); y3.norm()				// y3=X2+Z2
+	x3.mul(y3)							// x3=(X1+Z1)(X2+Z2)
+	y3.copy(t0)
+	y3.add(t2)							// y3=X1.X2+Z1+Z2
+	y3.rsub(x3); y3.norm()				// y3=(X1+Z1)(X2+Z2) - (X1.X2+Z1.Z2) = X1.Z2+X2.Z1
+
+	if SEXTIC_TWIST == D_TYPE {
+		t0.mul_ip(); t0.norm() // x.Q.x
+		t1.mul_ip(); t1.norm() // y.Q.y
+	}
+	x3.copy(t0); x3.add(t0) 
+	t0.add(x3); t0.norm()
+	t2.imul(b) 	
+	if SEXTIC_TWIST == M_TYPE {
+		t2.mul_ip(); t2.norm()
+	}
+	z3:=NewFP2copy(t1); z3.add(t2); z3.norm()
+	t1.sub(t2); t1.norm()
+	y3.imul(b) 
+	if SEXTIC_TWIST == M_TYPE {
+		y3.mul_ip()
+		y3.norm()
+	}
+	x3.copy(y3); x3.mul(t4); t2.copy(t3); t2.mul(t1); x3.rsub(t2)
+	y3.mul(t0); t1.mul(z3); y3.add(t1)
+	t0.mul(t3); z3.mul(t4); z3.add(t0)
+
+	E.x.copy(x3); E.x.norm() 
+	E.y.copy(y3); E.y.norm()
+	E.z.copy(z3); E.z.norm()
+
+	return 0
+}
+
+/* set this-=Q */
+func (E *ECP2) Sub(Q *ECP2) int {
+	NQ:=NewECP2(); NQ.Copy(Q)
+	NQ.neg()
+	D:=E.Add(NQ)
+	//Q.neg()
+	return D
+}
+/* set this*=q, where q is Modulus, using Frobenius */
+func (E *ECP2) frob(X *FP2) {
+//	if E.INF {return}
+	X2:=NewFP2copy(X)
+	X2.sqr()
+	E.x.conj()
+	E.y.conj()
+	E.z.conj()
+	E.z.reduce();
+	E.x.mul(X2)
+	E.y.mul(X2)
+	E.y.mul(X)
+}
+
+/* P*=e */
+func (E *ECP2) mul(e *BIG) *ECP2 {
+/* fixed size windows */
+	mt:=NewBIG()
+	t:=NewBIG()
+	P:=NewECP2()
+	Q:=NewECP2()
+	C:=NewECP2()
+
+	if E.Is_infinity() {return NewECP2()}
+
+	var W []*ECP2
+	var w [1+(NLEN*int(BASEBITS)+3)/4]int8
+
+	//E.Affine()
+
+/* precompute table */
+	Q.Copy(E)
+	Q.dbl()
+		
+	W=append(W,NewECP2())
+	W[0].Copy(E);
+
+	for i:=1;i<8;i++ {
+		W=append(W,NewECP2())
+		W[i].Copy(W[i-1])
+		W[i].Add(Q)
+	}
+
+/* make exponent odd - add 2P if even, P if odd */
+	t.copy(e)
+	s:=int(t.parity())
+	t.inc(1); t.norm(); ns:=int(t.parity()); mt.copy(t); mt.inc(1); mt.norm()
+	t.cmove(mt,s)
+	Q.cmove(E,ns)
+	C.Copy(Q)
+
+	nb:=1+(t.nbits()+3)/4
+/* convert exponent to signed 4-bit window */
+	for i:=0;i<nb;i++ {
+		w[i]=int8(t.lastbits(5)-16)
+		t.dec(int(w[i])); t.norm()
+		t.fshr(4)	
+	}
+	w[nb]=int8(t.lastbits(5))
+		
+	P.Copy(W[(w[nb]-1)/2])
+	for i:=nb-1;i>=0;i-- {
+		Q.selector(W,int32(w[i]))
+		P.dbl()
+		P.dbl()
+		P.dbl()
+		P.dbl()
+		P.Add(Q)
+	}
+	P.Sub(C)
+	P.Affine()
+	return P
+}
+
+/* Public version */
+func (E *ECP2) Mul(e *BIG) *ECP2 {
+	return E.mul(e)
+}
+
+/* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3 */
+// Bos & Costello https://eprint.iacr.org/2013/458.pdf
+// Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
+// Side channel attack secure 
+func mul4(Q []*ECP2,u []*BIG) *ECP2 {
+	W:=NewECP2()
+	P:=NewECP2()
+	var T [] *ECP2
+	mt:=NewBIG()
+	var t [] *BIG
+
+	var w [NLEN*int(BASEBITS)+1]int8	
+	var s [NLEN*int(BASEBITS)+1]int8	
+
+	for i:=0;i<4;i++ {
+		t=append(t,NewBIGcopy(u[i]));
+		//Q[i].Affine();
+	}
+
+	T=append(T,NewECP2()); T[0].Copy(Q[0])	// Q[0]
+	T=append(T,NewECP2()); T[1].Copy(T[0]); T[1].Add(Q[1])	// Q[0]+Q[1]
+	T=append(T,NewECP2()); T[2].Copy(T[0]); T[2].Add(Q[2])	// Q[0]+Q[2]
+	T=append(T,NewECP2()); T[3].Copy(T[1]); T[3].Add(Q[2])	// Q[0]+Q[1]+Q[2]
+	T=append(T,NewECP2()); T[4].Copy(T[0]); T[4].Add(Q[3])	// Q[0]+Q[3]
+	T=append(T,NewECP2()); T[5].Copy(T[1]); T[5].Add(Q[3])	// Q[0]+Q[1]+Q[3]
+	T=append(T,NewECP2()); T[6].Copy(T[2]); T[6].Add(Q[3])	// Q[0]+Q[2]+Q[3]
+	T=append(T,NewECP2()); T[7].Copy(T[3]); T[7].Add(Q[3])	// Q[0]+Q[1]+Q[2]+Q[3]
+	
+// Make it odd
+	pb:=1-t[0].parity()
+	t[0].inc(pb)
+//	t[0].norm();
+
+// Number of bits
+	mt.zero()
+	for i:=0;i<4;i++ {
+		t[i].norm()
+		mt.or(t[i])
+	}
+
+	nb:=1+mt.nbits();
+
+// Sign pivot 
+	s[nb-1]=1
+	for i:=0;i<nb-1;i++ {
+		t[0].fshr(1)
+		s[i]=2*int8(t[0].parity())-1
+	}
+
+// Recoded exponent
+	for i:=0; i<nb; i++ {
+		w[i]=0
+		k:=1
+		for j:=1; j<4; j++ {
+			bt:=s[i]*int8(t[j].parity())
+			t[j].fshr(1)
+			t[j].dec(int(bt)>>1)
+			t[j].norm()
+			w[i]+=bt*int8(k)
+			k*=2
+		}
+	}	
+	
+// Main loop
+	P.selector(T,int32(2*w[nb-1]+1))  
+	for i:=nb-2;i>=0;i-- {
+		P.dbl()
+		W.selector(T,int32(2*w[i]+s[i]))
+		P.Add(W)
+	}
+
+// apply correction
+	W.Copy(P)   
+	W.Sub(Q[0])
+	P.cmove(W,pb)
+
+	P.Affine()
+	return P
+}
+
+/*
+func mul4(Q []*ECP2,u []*BIG) *ECP2 {
+	var a [4]int8
+	T:=NewECP2()
+	C:=NewECP2()
+	P:=NewECP2()
+
+	var W [] *ECP2
+
+	mt:=NewBIG()
+	var t []*BIG
+
+	var w [NLEN*int(BASEBITS)+1]int8	
+
+	for i:=0;i<4;i++ {
+		t=append(t,NewBIGcopy(u[i]));
+		Q[i].Affine();
+	}
+
+// precompute table 
+
+	W=append(W,NewECP2()); W[0].Copy(Q[0]); W[0].Sub(Q[1])
+	W=append(W,NewECP2()); W[1].Copy(W[0])
+	W=append(W,NewECP2()); W[2].Copy(W[0])
+	W=append(W,NewECP2()); W[3].Copy(W[0])
+	W=append(W,NewECP2()); W[4].Copy(Q[0]); W[4].Add(Q[1])
+	W=append(W,NewECP2()); W[5].Copy(W[4])
+	W=append(W,NewECP2()); W[6].Copy(W[4])
+	W=append(W,NewECP2()); W[7].Copy(W[4])
+
+	T.Copy(Q[2]); T.Sub(Q[3])
+	W[1].Sub(T)
+	W[2].Add(T)
+	W[5].Sub(T)
+	W[6].Add(T)
+	T.Copy(Q[2]); T.Add(Q[3])
+	W[0].Sub(T)
+	W[3].Add(T)
+	W[4].Sub(T)
+	W[7].Add(T)
+
+// if multiplier is even add 1 to multiplier, and add P to correction 
+	mt.zero(); C.inf()
+	for i:=0;i<4;i++ {
+		if t[i].parity()==0 {
+			t[i].inc(1); t[i].norm()
+			C.Add(Q[i])
+		}
+		mt.add(t[i]); mt.norm()
+	}
+
+	nb:=1+mt.nbits();
+
+// convert exponent to signed 1-bit window 
+	for j:=0;j<nb;j++ {
+		for i:=0;i<4;i++ {
+			a[i]=int8(t[i].lastbits(2)-2)
+			t[i].dec(int(a[i])); t[i].norm()
+			t[i].fshr(1)
+		}
+		w[j]=(8*a[0]+4*a[1]+2*a[2]+a[3])
+	}
+	w[nb]=int8(8*t[0].lastbits(2)+4*t[1].lastbits(2)+2*t[2].lastbits(2)+t[3].lastbits(2))
+
+	P.Copy(W[(w[nb]-1)/2])  
+	for i:=nb-1;i>=0;i-- {
+		T.selector(W,int32(w[i]))
+		P.dbl()
+		P.Add(T)
+	}
+	P.Sub(C) // apply correction 
+
+	P.Affine()
+	return P
+}
+*/
+
+/* needed for SOK */
+func ECP2_mapit(h []byte) *ECP2 {
+	q:=NewBIGints(Modulus)
+	x:=FromBytes(h[:])
+	one:=NewBIGint(1)
+	var X *FP2
+	var Q,T,K,xQ,x2Q *ECP2
+	x.Mod(q)
+	for true {
+		X=NewFP2bigs(one,x)
+		Q=NewECP2fp2(X)
+		if !Q.Is_infinity() {break}
+		x.inc(1); x.norm()
+	}
+/* Fast Hashing to G2 - Fuentes-Castaneda, Knapp and Rodriguez-Henriquez */
+	Fra:=NewBIGints(Fra)
+	Frb:=NewBIGints(Frb)
+	X=NewFP2bigs(Fra,Frb)
+	if SEXTIC_TWIST == M_TYPE {
+		X.inverse()
+		X.norm()
+	}
+
+	x=NewBIGints(CURVE_Bnx)
+
+	if CURVE_PAIRING_TYPE==BN {
+		T=NewECP2(); T.Copy(Q)
+		T=T.mul(x); 
+		if SIGN_OF_X==NEGATIVEX {
+			T.neg()
+		}
+		
+		K=NewECP2(); K.Copy(T)
+		K.dbl(); K.Add(T); //K.Affine()
+
+		K.frob(X)
+		Q.frob(X); Q.frob(X); Q.frob(X)
+		Q.Add(T); Q.Add(K)
+		T.frob(X); T.frob(X)
+		Q.Add(T)
+	}
+	if CURVE_PAIRING_TYPE==BLS {
+//		xQ=NewECP2()
+//		x2Q=NewECP2()
+
+		xQ=Q.mul(x)
+		x2Q=xQ.mul(x)
+
+		if SIGN_OF_X==NEGATIVEX {
+			xQ.neg()
+		}
+
+		x2Q.Sub(xQ)
+		x2Q.Sub(Q)
+
+		xQ.Sub(Q)
+		xQ.frob(X)
+
+		Q.dbl()
+		Q.frob(X)
+		Q.frob(X)
+
+		Q.Add(x2Q)
+		Q.Add(xQ)
+	}
+	Q.Affine()
+	return Q
+}
+
+func ECP2_generator() *ECP2 {
+	var G *ECP2
+	G=NewECP2fp2s(NewFP2bigs(NewBIGints(CURVE_Pxa),NewBIGints(CURVE_Pxb)),NewFP2bigs(NewBIGints(CURVE_Pya),NewBIGints(CURVE_Pyb)))
+	return G
+}
diff --git a/version3/go/ECP4.go b/version3/go/ECP4.go
new file mode 100644
index 0000000..72c4df2
--- /dev/null
+++ b/version3/go/ECP4.go
@@ -0,0 +1,711 @@
+/*
+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.
+*/
+
+/* MiotCL Weierstrass elliptic curve functions over FP2 */
+
+package XXX
+
+//import "fmt"
+
+type ECP4 struct {
+	x *FP4
+	y *FP4
+	z *FP4
+//	INF bool
+}
+
+func NewECP4() *ECP4 {
+	E:=new(ECP4)
+	E.x=NewFP4int(0)
+	E.y=NewFP4int(1)
+	E.z=NewFP4int(0)
+//	E.INF=true
+	return E
+}
+
+/* Test this=O? */
+func (E *ECP4) Is_infinity() bool {
+//	if E.INF {return true}
+	E.x.reduce(); E.y.reduce(); E.z.reduce()
+	return E.x.iszilch() && E.z.iszilch()
+}
+
+/* copy this=P */
+func (E *ECP4) Copy(P *ECP4) {
+	E.x.copy(P.x)
+	E.y.copy(P.y)
+	E.z.copy(P.z)
+//	E.INF=P.INF
+}
+/* set this=O */
+func (E *ECP4) inf() {
+//	E.INF=true
+	E.x.zero()
+	E.y.one()
+	E.z.zero()
+}
+
+/* set this=-this */
+func (E *ECP4) neg() {
+	E.y.norm(); E.y.neg(); E.y.norm()
+}
+
+/* Conditional move of Q to P dependant on d */
+func (E *ECP4) cmove(Q *ECP4,d int) {
+	E.x.cmove(Q.x,d)
+	E.y.cmove(Q.y,d)
+	E.z.cmove(Q.z,d)
+/*
+	var bd bool
+	if (d==0) {
+		bd=false
+	} else {bd=true}
+	E.INF=(E.INF!=((E.INF!=Q.INF)&&bd))
+*/
+}
+
+/* Constant time select from pre-computed table */
+func (E *ECP4) selector(W []*ECP4,b int32) {
+	MP:=NewECP4() 
+	m:=b>>31
+	babs:=(b^m)-m
+
+	babs=(babs-1)/2
+
+	E.cmove(W[0],teq(babs,0))  // conditional move
+	E.cmove(W[1],teq(babs,1))
+	E.cmove(W[2],teq(babs,2))
+	E.cmove(W[3],teq(babs,3))
+	E.cmove(W[4],teq(babs,4))
+	E.cmove(W[5],teq(babs,5))
+	E.cmove(W[6],teq(babs,6))
+	E.cmove(W[7],teq(babs,7))
+ 
+	MP.Copy(E)
+	MP.neg()
+	E.cmove(MP,int(m&1))
+}
+
+/* Test if P == Q */
+func (E *ECP4) Equals(Q *ECP4) bool {
+	if E.Is_infinity() && Q.Is_infinity() {return true}
+	if E.Is_infinity() || Q.Is_infinity() {return false}
+
+	a:=NewFP4copy(E.x)
+	b:=NewFP4copy(Q.x)
+	a.mul(Q.z); b.mul(E.z)
+
+	if !a.Equals(b) {return false}
+	a.copy(E.y); b.copy(Q.y)
+	a.mul(Q.z); b.mul(E.z);
+	if !a.Equals(b) {return false}
+
+	return true
+}
+
+/* set to Affine - (x,y,z) to (x,y) */
+func (E *ECP4) Affine() {
+	if E.Is_infinity() {return}
+	one:=NewFP4int(1)
+	if E.z.Equals(one) {E.x.reduce(); E.y.reduce(); return}
+	E.z.inverse()
+
+	E.x.mul(E.z); E.x.reduce()
+	E.y.mul(E.z); E.y.reduce()
+	E.z.copy(one)
+}
+
+/* extract affine x as FP2 */
+func (E *ECP4) GetX() *FP4 {
+	W:=NewECP4(); W.Copy(E)
+	W.Affine()
+	return W.x
+}
+/* extract affine y as FP2 */
+func (E *ECP4) GetY() *FP4 {
+	W:=NewECP4(); W.Copy(E)
+	W.Affine()
+	return W.y;
+}
+
+/* extract projective x */
+func (E *ECP4) getx() *FP4 {
+	return E.x
+}
+/* extract projective y */
+func (E *ECP4) gety() *FP4 {
+	return E.y
+}
+/* extract projective z */
+func (E *ECP4) getz() *FP4 {
+	return E.z
+}
+
+/* convert to byte array */
+func (E *ECP4) ToBytes(b []byte) {
+	var t [int(MODBYTES)]byte
+	MB:=int(MODBYTES)
+
+	W:=NewECP4(); W.Copy(E);
+	W.Affine()
+
+	W.x.geta().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ { b[i]=t[i]}
+	W.x.geta().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ { b[i+MB]=t[i]}
+	W.x.getb().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ { b[i+2*MB]=t[i]}
+	W.x.getb().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ { b[i+3*MB]=t[i]}
+
+	W.y.geta().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ { b[i+4*MB]=t[i]}
+	W.y.geta().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ { b[i+5*MB]=t[i]}
+	W.y.getb().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ { b[i+6*MB]=t[i]}
+	W.y.getb().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ { b[i+7*MB]=t[i]}
+
+}
+
+/* convert from byte array to point */
+func ECP4_fromBytes(b []byte) *ECP4 {
+	var t [int(MODBYTES)]byte
+	MB:=int(MODBYTES)
+
+	for i:=0;i<MB;i++ {t[i]=b[i]}
+	ra:=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=b[i+MB]}
+	rb:=FromBytes(t[:])
+
+	ra4:=NewFP2bigs(ra,rb)
+
+	for i:=0;i<MB;i++ {t[i]=b[i+2*MB]}
+	ra=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=b[i+3*MB]}
+	rb=FromBytes(t[:])
+
+	rb4:=NewFP2bigs(ra,rb)
+	rx:=NewFP4fp2s(ra4,rb4)
+
+	for i:=0;i<MB;i++ {t[i]=b[i+4*MB]}
+	ra=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=b[i+5*MB]}
+	rb=FromBytes(t[:])
+
+	ra4=NewFP2bigs(ra,rb)
+
+	for i:=0;i<MB;i++ {t[i]=b[i+6*MB]}
+	ra=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=b[i+7*MB]}
+	rb=FromBytes(t[:])
+
+	rb4=NewFP2bigs(ra,rb)
+	ry:=NewFP4fp2s(ra4,rb4)
+
+	return NewECP4fp4s(rx,ry)
+}
+
+/* convert this to hex string */
+func (E *ECP4) ToString() string {
+	W:=NewECP4(); W.Copy(E);
+	W.Affine()
+	if W.Is_infinity() {return "infinity"}
+	return "("+W.x.toString()+","+W.y.toString()+")"
+}
+
+/* Calculate RHS of twisted curve equation x^3+B/i */
+func RHS4(x *FP4) *FP4 {
+	//x.norm()
+	r:=NewFP4copy(x)
+	r.sqr()
+	b2:=NewFP2big(NewBIGints(CURVE_B))
+	b:=NewFP4fp2(b2)
+
+	if SEXTIC_TWIST == D_TYPE {
+		b.div_i()
+	}
+	if SEXTIC_TWIST == M_TYPE {
+		b.times_i()
+	}	
+	r.mul(x)
+	r.add(b)
+
+	r.reduce()
+	return r
+}
+
+/* construct this from (x,y) - but set to O if not on curve */
+func NewECP4fp4s(ix *FP4,iy *FP4) *ECP4 {
+	E:=new(ECP4)
+	E.x=NewFP4copy(ix)
+	E.y=NewFP4copy(iy)
+	E.z=NewFP4int(1)
+	E.x.norm()
+	rhs:=RHS4(E.x)
+	y2:=NewFP4copy(E.y)
+	y2.sqr()
+	if !y2.Equals(rhs) {
+		E.inf()
+	}
+	return E
+}
+
+/* construct this from x - but set to O if not on curve */
+func NewECP4fp4(ix *FP4) *ECP4 {	
+	E:=new(ECP4)
+	E.x=NewFP4copy(ix)
+	E.y=NewFP4int(1)
+	E.z=NewFP4int(1)
+	E.x.norm()
+	rhs:=RHS4(E.x)
+	if rhs.sqrt() {
+			E.y.copy(rhs)
+			//E.INF=false;
+	} else {E.inf()}
+	return E
+}
+
+/* this+=this */
+func (E *ECP4) dbl() int {
+//	if E.INF {return -1}
+
+	iy:=NewFP4copy(E.y)
+	if SEXTIC_TWIST == D_TYPE {
+		iy.times_i(); //iy.norm()
+	}
+
+	t0:=NewFP4copy(E.y)                  //***** Change 
+	t0.sqr();  
+	if SEXTIC_TWIST == D_TYPE {	
+		t0.times_i()   
+	}
+	t1:=NewFP4copy(iy)  
+	t1.mul(E.z)
+	t2:=NewFP4copy(E.z)
+	t2.sqr()
+
+	E.z.copy(t0)
+	E.z.add(t0); E.z.norm() 
+	E.z.add(E.z)
+	E.z.add(E.z) 
+	E.z.norm()  
+
+	t2.imul(3*CURVE_B_I) 
+	if SEXTIC_TWIST == M_TYPE {
+		t2.times_i()
+		//t2.norm()
+	}
+	x3:=NewFP4copy(t2)
+	x3.mul(E.z) 
+
+	y3:=NewFP4copy(t0)   
+
+	y3.add(t2); y3.norm()
+	E.z.mul(t1)
+	t1.copy(t2); t1.add(t2); t2.add(t1); t2.norm()  
+	t0.sub(t2); t0.norm()                           //y^2-9bz^2
+	y3.mul(t0); y3.add(x3)                          //(y^2+3z*2)(y^2-9z^2)+3b.z^2.8y^2
+	t1.copy(E.x); t1.mul(iy)						//
+	E.x.copy(t0); E.x.norm(); E.x.mul(t1); E.x.add(E.x)       //(y^2-9bz^2)xy2
+
+	E.x.norm()
+	E.y.copy(y3); E.y.norm()
+
+	return 1
+}
+
+/* this+=Q - return 0 for add, 1 for double, -1 for O */
+func (E *ECP4) Add(Q *ECP4) int {
+/*	if E.INF {
+		E.Copy(Q)
+		return -1
+	}
+	if Q.INF {return -1}
+*/
+	b:=3*CURVE_B_I
+	t0:=NewFP4copy(E.x)
+	t0.mul(Q.x)         // x.Q.x
+	t1:=NewFP4copy(E.y)
+	t1.mul(Q.y)		 // y.Q.y
+
+	t2:=NewFP4copy(E.z)
+	t2.mul(Q.z)
+	t3:=NewFP4copy(E.x)
+	t3.add(E.y); t3.norm()          //t3=X1+Y1
+	t4:=NewFP4copy(Q.x)            
+	t4.add(Q.y); t4.norm()			//t4=X2+Y2
+	t3.mul(t4)						//t3=(X1+Y1)(X2+Y2)
+	t4.copy(t0); t4.add(t1)		//t4=X1.X2+Y1.Y2
+
+	t3.sub(t4); t3.norm(); 
+	if SEXTIC_TWIST == D_TYPE {
+		t3.times_i();  //t3.norm()         //t3=(X1+Y1)(X2+Y2)-(X1.X2+Y1.Y2) = X1.Y2+X2.Y1
+	}
+	t4.copy(E.y);                    
+	t4.add(E.z); t4.norm()			//t4=Y1+Z1
+	x3:=NewFP4copy(Q.y)
+	x3.add(Q.z); x3.norm()			//x3=Y2+Z2
+
+	t4.mul(x3)						//t4=(Y1+Z1)(Y2+Z2)
+	x3.copy(t1)					//
+	x3.add(t2)						//X3=Y1.Y2+Z1.Z2
+	
+	t4.sub(x3); t4.norm();
+	if SEXTIC_TWIST == D_TYPE {	
+		t4.times_i(); //t4.norm()          //t4=(Y1+Z1)(Y2+Z2) - (Y1.Y2+Z1.Z2) = Y1.Z2+Y2.Z1
+	}
+	x3.copy(E.x); x3.add(E.z); x3.norm()	// x3=X1+Z1
+	y3:=NewFP4copy(Q.x)				
+	y3.add(Q.z); y3.norm()				// y3=X2+Z2
+	x3.mul(y3)							// x3=(X1+Z1)(X2+Z2)
+	y3.copy(t0)
+	y3.add(t2)							// y3=X1.X2+Z1+Z2
+	y3.rsub(x3); y3.norm()				// y3=(X1+Z1)(X2+Z2) - (X1.X2+Z1.Z2) = X1.Z2+X2.Z1
+
+	if SEXTIC_TWIST == D_TYPE {
+		t0.times_i(); //t0.norm() // x.Q.x
+		t1.times_i(); //t1.norm() // y.Q.y
+	}
+	x3.copy(t0); x3.add(t0) 
+	t0.add(x3); t0.norm()
+	t2.imul(b) 	
+	if SEXTIC_TWIST == M_TYPE {
+		t2.times_i()
+	}
+	z3:=NewFP4copy(t1); z3.add(t2); z3.norm()
+	t1.sub(t2); t1.norm()
+	y3.imul(b) 
+	if SEXTIC_TWIST == M_TYPE {
+		y3.times_i()
+		//y3.norm()
+	}
+	x3.copy(y3); x3.mul(t4); t2.copy(t3); t2.mul(t1); x3.rsub(t2)
+	y3.mul(t0); t1.mul(z3); y3.add(t1)
+	t0.mul(t3); z3.mul(t4); z3.add(t0)
+
+	E.x.copy(x3); E.x.norm() 
+	E.y.copy(y3); E.y.norm()
+	E.z.copy(z3); E.z.norm()
+
+	return 0
+}
+
+/* set this-=Q */
+func (E *ECP4) Sub(Q *ECP4) int {
+	NQ:=NewECP4(); NQ.Copy(Q)
+	NQ.neg()	
+	D:=E.Add(NQ)
+	//Q.neg()
+	return D
+}
+
+func ECP4_frob_constants() [3]*FP2 {
+	
+	Fra:=NewBIGints(Fra)
+	Frb:=NewBIGints(Frb)
+	X:=NewFP2bigs(Fra,Frb)	
+
+	F0:=NewFP2copy(X); F0.sqr()
+	F2:=NewFP2copy(F0)
+	F2.mul_ip(); F2.norm()
+	F1:=NewFP2copy(F2); F1.sqr()
+	F2.mul(F1)
+	F1.copy(X)
+	if SEXTIC_TWIST == M_TYPE {
+		F1.mul_ip()
+		F1.inverse()
+		F0.copy(F1); F0.sqr()
+	}
+	F0.mul_ip(); F0.norm()
+	F1.mul(F0)
+	F:=[3]*FP2{F0,F1,F2}
+	return F
+}
+
+/* set this*=q, where q is Modulus, using Frobenius */
+func (E *ECP4) frob(F [3]*FP2,n int) {
+//	if E.INF {return}
+	for i:=0;i<n;i++ {
+		E.x.frob(F[2])
+		E.x.pmul(F[0])
+		
+		E.y.frob(F[2])
+		E.y.pmul(F[1])
+		E.y.times_i()
+
+		E.z.frob(F[2])
+	}
+}
+
+func (E *ECP4) reduce() {
+	E.x.reduce()
+	E.y.reduce()
+	E.z.reduce()
+}
+
+/* P*=e */
+func (E *ECP4) mul(e *BIG) *ECP4 {
+/* fixed size windows */
+	mt:=NewBIG()
+	t:=NewBIG()
+	P:=NewECP4()
+	Q:=NewECP4()
+	C:=NewECP4()
+
+	if E.Is_infinity() {return NewECP4()}
+
+	var W []*ECP4
+	var w [1+(NLEN*int(BASEBITS)+3)/4]int8
+
+	//E.Affine()
+/* precompute table */
+	Q.Copy(E)
+	Q.dbl()
+		
+	W=append(W,NewECP4())
+	W[0].Copy(E);
+
+	for i:=1;i<8;i++ {
+		W=append(W,NewECP4())
+		W[i].Copy(W[i-1])
+		W[i].Add(Q)
+	}
+
+/* make exponent odd - add 2P if even, P if odd */
+	t.copy(e)
+	s:=int(t.parity())
+	t.inc(1); t.norm(); ns:=int(t.parity()); mt.copy(t); mt.inc(1); mt.norm()
+	t.cmove(mt,s)
+	Q.cmove(E,ns)
+	C.Copy(Q)
+
+	nb:=1+(t.nbits()+3)/4
+/* convert exponent to signed 4-bit window */
+	for i:=0;i<nb;i++ {
+		w[i]=int8(t.lastbits(5)-16)
+		t.dec(int(w[i])); t.norm()
+		t.fshr(4)	
+	}
+	w[nb]=int8(t.lastbits(5))
+		
+	P.Copy(W[(w[nb]-1)/2])
+	for i:=nb-1;i>=0;i-- {
+		Q.selector(W,int32(w[i]))
+		P.dbl()
+		P.dbl()
+		P.dbl()
+		P.dbl()
+		P.Add(Q)
+	}
+	P.Sub(C)
+	P.Affine()
+	return P
+}
+
+/* Public version */
+func (E *ECP4) Mul(e *BIG) *ECP4 {
+	return E.mul(e)
+}
+
+func ECP4_generator() *ECP4 {
+	var G *ECP4
+	G=NewECP4fp4s( 
+		NewFP4fp2s( 
+			NewFP2bigs(NewBIGints(CURVE_Pxaa),NewBIGints(CURVE_Pxab)),
+			NewFP2bigs(NewBIGints(CURVE_Pxba),NewBIGints(CURVE_Pxbb))),
+		NewFP4fp2s(
+			NewFP2bigs(NewBIGints(CURVE_Pyaa),NewBIGints(CURVE_Pyab)),
+
+			NewFP2bigs(NewBIGints(CURVE_Pyba),NewBIGints(CURVE_Pybb))))
+	return G
+}
+
+/* needed for SOK */
+func ECP4_mapit(h []byte) *ECP4 {
+	q:=NewBIGints(Modulus)
+	hv:=FromBytes(h[:])
+	one:=NewBIGint(1)
+	var X2 *FP2
+	var X *FP4 
+	var Q *ECP4
+	hv.Mod(q)
+	for true {
+		X2=NewFP2bigs(one,hv)
+		X=NewFP4fp2(X2)
+		Q=NewECP4fp4(X)
+		if !Q.Is_infinity() {break}
+		hv.inc(1); hv.norm()
+	}
+
+
+	F:=ECP4_frob_constants()
+	x:=NewBIGints(CURVE_Bnx)
+	xQ:=Q.mul(x)
+	x2Q:=xQ.mul(x)
+	x3Q:=x2Q.mul(x)
+	x4Q:=x3Q.mul(x)
+
+	if SIGN_OF_X==NEGATIVEX {
+		xQ.neg()
+		x3Q.neg()
+	}
+
+	x4Q.Sub(x3Q)
+	x4Q.Sub(Q)
+
+	x3Q.Sub(x2Q)
+	x3Q.frob(F,1)
+
+	x2Q.Sub(xQ);
+	x2Q.frob(F,2)
+
+	xQ.Sub(Q)
+	xQ.frob(F,3)
+
+	Q.dbl()
+	Q.frob(F,4)
+
+	Q.Add(x4Q)
+	Q.Add(x3Q)
+	Q.Add(x2Q)
+	Q.Add(xQ)
+
+	Q.Affine()
+	return Q
+}
+
+/* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3.. */
+// Bos & Costello https://eprint.iacr.org/2013/458.pdf
+// Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
+// Side channel attack secure 
+func mul8(Q []*ECP4,u []*BIG) *ECP4 {
+	W:=NewECP4()
+	P:=NewECP4()
+	var T1 [] *ECP4
+	var T2 [] *ECP4
+	mt:=NewBIG()
+	var t [] *BIG
+	var bt int8
+	var k int
+
+	var w1 [NLEN*int(BASEBITS)+1]int8	
+	var s1 [NLEN*int(BASEBITS)+1]int8	
+	var w2 [NLEN*int(BASEBITS)+1]int8	
+	var s2 [NLEN*int(BASEBITS)+1]int8	
+
+	for i:=0;i<8;i++ {
+		t=append(t,NewBIGcopy(u[i]));
+		//Q[i].Affine();
+	}
+
+	T1=append(T1,NewECP4()); T1[0].Copy(Q[0])	// Q[0]
+	T1=append(T1,NewECP4()); T1[1].Copy(T1[0]); T1[1].Add(Q[1])	// Q[0]+Q[1]
+	T1=append(T1,NewECP4()); T1[2].Copy(T1[0]); T1[2].Add(Q[2])	// Q[0]+Q[2]
+	T1=append(T1,NewECP4()); T1[3].Copy(T1[1]); T1[3].Add(Q[2])	// Q[0]+Q[1]+Q[2]
+	T1=append(T1,NewECP4()); T1[4].Copy(T1[0]); T1[4].Add(Q[3])	// Q[0]+Q[3]
+	T1=append(T1,NewECP4()); T1[5].Copy(T1[1]); T1[5].Add(Q[3])	// Q[0]+Q[1]+Q[3]
+	T1=append(T1,NewECP4()); T1[6].Copy(T1[2]); T1[6].Add(Q[3])	// Q[0]+Q[2]+Q[3]
+	T1=append(T1,NewECP4()); T1[7].Copy(T1[3]); T1[7].Add(Q[3])	// Q[0]+Q[1]+Q[2]+Q[3]
+
+//  Use Frobenius 
+	F:=ECP4_frob_constants()
+
+	for i:=0;i<8;i++ {
+		T2=append(T2,NewECP4()); T2[i].Copy(T1[i]); T2[i].frob(F,4)
+	}
+
+// Make them odd
+	pb1:=1-t[0].parity()
+	t[0].inc(pb1)
+//	t[0].norm();
+
+	pb2:=1-t[4].parity()
+	t[4].inc(pb2)
+//	t[4].norm();
+
+// Number of bits
+	mt.zero()
+	for i:=0;i<8;i++ {
+		t[i].norm()
+		mt.or(t[i])
+	}
+
+	nb:=1+mt.nbits();
+	
+// Sign pivot 
+	s1[nb-1]=1
+	s2[nb-1]=1
+	for i:=0;i<nb-1;i++ {
+		t[0].fshr(1)
+		s1[i]=2*int8(t[0].parity())-1
+		t[4].fshr(1)
+		s2[i]=2*int8(t[4].parity())-1
+
+	}
+
+// Recoded exponents
+	for i:=0; i<nb; i++ {
+		w1[i]=0
+		k=1
+		for j:=1; j<4; j++ {
+			bt=s1[i]*int8(t[j].parity())
+			t[j].fshr(1)
+			t[j].dec(int(bt)>>1)
+			t[j].norm()
+			w1[i]+=bt*int8(k)
+			k*=2
+		}
+		w2[i]=0
+		k=1
+		for j:=5; j<8; j++ {
+			bt=s2[i]*int8(t[j].parity())
+			t[j].fshr(1)
+			t[j].dec(int(bt)>>1)
+			t[j].norm()
+			w2[i]+=bt*int8(k)
+			k*=2
+		}
+	}
+
+// Main loop
+	P.selector(T1,int32(2*w1[nb-1]+1))  
+	W.selector(T2,int32(2*w2[nb-1]+1))
+	P.Add(W)
+	for i:=nb-2;i>=0;i-- {
+		P.dbl()
+		W.selector(T1,int32(2*w1[i]+s1[i]))
+		P.Add(W)
+		W.selector(T2,int32(2*w2[i]+s2[i]))
+		P.Add(W)
+
+	}
+
+// apply correction
+	W.Copy(P)   
+	W.Sub(Q[0])
+	P.cmove(W,pb1)
+	W.Copy(P)   
+	W.Sub(Q[4])
+	P.cmove(W,pb2)
+
+	P.Affine()
+	return P
+}
diff --git a/version3/go/ECP8.go b/version3/go/ECP8.go
new file mode 100644
index 0000000..eea77bc
--- /dev/null
+++ b/version3/go/ECP8.go
@@ -0,0 +1,862 @@
+/*
+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.
+*/
+
+/* MiotCL Weierstrass elliptic curve functions over FP2 */
+
+package XXX
+
+//import "fmt"
+
+type ECP8 struct {
+	x *FP8
+	y *FP8
+	z *FP8
+//	INF bool
+}
+
+func NewECP8() *ECP8 {
+	E:=new(ECP8)
+	E.x=NewFP8int(0)
+	E.y=NewFP8int(1)
+	E.z=NewFP8int(0)
+//	E.INF=true
+	return E
+}
+
+/* Test this=O? */
+func (E *ECP8) Is_infinity() bool {
+//	if E.INF {return true}
+	E.x.reduce(); E.y.reduce(); E.z.reduce()
+	return E.x.iszilch() && E.z.iszilch()
+}
+
+/* copy this=P */
+func (E *ECP8) Copy(P *ECP8) {
+	E.x.copy(P.x)
+	E.y.copy(P.y)
+	E.z.copy(P.z)
+//	E.INF=P.INF
+}
+/* set this=O */
+func (E *ECP8) inf() {
+//	E.INF=true
+	E.x.zero()
+	E.y.one()
+	E.z.zero()
+}
+
+/* set this=-this */
+func (E *ECP8) neg() {
+	E.y.norm(); E.y.neg(); E.y.norm()
+}
+
+/* Conditional move of Q to P dependant on d */
+func (E *ECP8) cmove(Q *ECP8,d int) {
+	E.x.cmove(Q.x,d)
+	E.y.cmove(Q.y,d)
+	E.z.cmove(Q.z,d)
+/*
+	var bd bool
+	if (d==0) {
+		bd=false
+	} else {bd=true}
+	E.INF=(E.INF!=((E.INF!=Q.INF)&&bd))
+*/
+}
+
+/* Constant time select from pre-computed table */
+func (E *ECP8) selector(W []*ECP8,b int32) {
+	MP:=NewECP8() 
+	m:=b>>31
+	babs:=(b^m)-m
+
+	babs=(babs-1)/2
+
+	E.cmove(W[0],teq(babs,0))  // conditional move
+	E.cmove(W[1],teq(babs,1))
+	E.cmove(W[2],teq(babs,2))
+	E.cmove(W[3],teq(babs,3))
+	E.cmove(W[4],teq(babs,4))
+	E.cmove(W[5],teq(babs,5))
+	E.cmove(W[6],teq(babs,6))
+	E.cmove(W[7],teq(babs,7))
+ 
+	MP.Copy(E)
+	MP.neg()
+	E.cmove(MP,int(m&1))
+}
+
+/* Test if P == Q */
+func (E *ECP8) Equals(Q *ECP8) bool {
+//	if E.Is_infinity() && Q.Is_infinity() {return true}
+//	if E.Is_infinity() || Q.Is_infinity() {return false}
+
+	a:=NewFP8copy(E.x)
+	b:=NewFP8copy(Q.x)
+	a.mul(Q.z); b.mul(E.z)
+
+	if !a.Equals(b) {return false}
+	a.copy(E.y); b.copy(Q.y)
+	a.mul(Q.z); b.mul(E.z);
+	if !a.Equals(b) {return false}
+
+	return true
+}
+
+/* set to Affine - (x,y,z) to (x,y) */
+func (E *ECP8) Affine() {
+	if E.Is_infinity() {return}
+	one:=NewFP8int(1)
+	if E.z.Equals(one) {E.x.reduce(); E.y.reduce(); return}
+	E.z.inverse()
+
+	E.x.mul(E.z); E.x.reduce()
+	E.y.mul(E.z); E.y.reduce()
+	E.z.copy(one)
+}
+
+/* extract affine x as FP2 */
+func (E *ECP8) GetX() *FP8 {
+	W:=NewECP8(); W.Copy(E)
+	W.Affine()
+	return W.x
+}
+/* extract affine y as FP2 */
+func (E *ECP8) GetY() *FP8 {
+	W:=NewECP8(); W.Copy(E)
+	W.Affine()
+	return W.y;
+}
+
+/* extract projective x */
+func (E *ECP8) getx() *FP8 {
+	return E.x
+}
+/* extract projective y */
+func (E *ECP8) gety() *FP8 {
+	return E.y
+}
+/* extract projective z */
+func (E *ECP8) getz() *FP8 {
+	return E.z
+}
+
+/* convert to byte array */
+func (E *ECP8) ToBytes(b []byte) {
+	var t [int(MODBYTES)]byte
+	MB:=int(MODBYTES)
+
+	W:=NewECP8(); W.Copy(E);
+	W.Affine()
+
+	W.x.geta().geta().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ { b[i]=t[i]}
+	W.x.geta().geta().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ { b[i+MB]=t[i]}
+	W.x.geta().getb().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ { b[i+2*MB]=t[i]}
+	W.x.geta().getb().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ { b[i+3*MB]=t[i]}
+
+	W.x.getb().geta().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ { b[i+4*MB]=t[i]}
+	W.x.getb().geta().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ { b[i+5*MB]=t[i]}
+	W.x.getb().getb().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ { b[i+6*MB]=t[i]}
+	W.x.getb().getb().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ { b[i+7*MB]=t[i]}
+
+
+
+	W.y.geta().geta().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ { b[i+8*MB]=t[i]}
+	W.y.geta().geta().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ { b[i+9*MB]=t[i]}
+	W.y.geta().getb().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ { b[i+10*MB]=t[i]}
+	W.y.geta().getb().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ { b[i+11*MB]=t[i]}
+
+	W.y.getb().geta().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ { b[i+12*MB]=t[i]}
+	W.y.getb().geta().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ { b[i+13*MB]=t[i]}
+	W.y.getb().getb().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ { b[i+14*MB]=t[i]}
+	W.y.getb().getb().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ { b[i+15*MB]=t[i]}
+}
+
+/* convert from byte array to point */
+func ECP8_fromBytes(b []byte) *ECP8 {
+	var t [int(MODBYTES)]byte
+	MB:=int(MODBYTES)
+
+	for i:=0;i<MB;i++ {t[i]=b[i]}
+	ra:=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=b[i+MB]}
+	rb:=FromBytes(t[:])
+
+	ra4:=NewFP2bigs(ra,rb)
+
+	for i:=0;i<MB;i++ {t[i]=b[i+2*MB]}
+	ra=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=b[i+3*MB]}
+	rb=FromBytes(t[:])
+
+	rb4:=NewFP2bigs(ra,rb)
+
+	ra8:=NewFP4fp2s(ra4,rb4)
+
+	for i:=0;i<MB;i++ {t[i]=b[i+4*MB]}
+	ra=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=b[i+5*MB]}
+	rb=FromBytes(t[:])
+
+	ra4=NewFP2bigs(ra,rb)
+
+	for i:=0;i<MB;i++ {t[i]=b[i+6*MB]}
+	ra=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=b[i+7*MB]}
+	rb=FromBytes(t[:])
+
+	rb4=NewFP2bigs(ra,rb)
+
+	rb8:=NewFP4fp2s(ra4,rb4)
+
+	rx:=NewFP8fp4s(ra8,rb8)
+
+	for i:=0;i<MB;i++ {t[i]=b[i+8*MB]}
+	ra=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=b[i+9*MB]}
+	rb=FromBytes(t[:])
+
+	ra4=NewFP2bigs(ra,rb)
+
+	for i:=0;i<MB;i++ {t[i]=b[i+10*MB]}
+	ra=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=b[i+11*MB]}
+	rb=FromBytes(t[:])
+
+	rb4=NewFP2bigs(ra,rb)
+
+	ra8=NewFP4fp2s(ra4,rb4);
+
+	for i:=0;i<MB;i++ {t[i]=b[i+12*MB]}
+	ra=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=b[i+13*MB]}
+	rb=FromBytes(t[:])
+
+	ra4=NewFP2bigs(ra,rb)
+
+	for i:=0;i<MB;i++ {t[i]=b[i+14*MB]}
+	ra=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=b[i+15*MB]}
+	rb=FromBytes(t[:])
+
+	rb4=NewFP2bigs(ra,rb)
+
+	rb8=NewFP4fp2s(ra4,rb4)
+
+	ry:=NewFP8fp4s(ra8,rb8)
+
+	return NewECP8fp8s(rx,ry)
+}
+
+/* convert this to hex string */
+func (E *ECP8) ToString() string {
+	W:=NewECP8(); W.Copy(E);
+	W.Affine()
+	if W.Is_infinity() {return "infinity"}
+	return "("+W.x.toString()+","+W.y.toString()+")"
+}
+
+/* Calculate RHS of twisted curve equation x^3+B/i */
+func RHS4(x *FP8) *FP8 {
+	//x.norm()
+	r:=NewFP8copy(x)
+	r.sqr()
+	b2:=NewFP2big(NewBIGints(CURVE_B))
+	b4:=NewFP4fp2(b2)
+	b:=NewFP8fp4(b4)
+
+	if SEXTIC_TWIST == D_TYPE {
+		b.div_i()
+	}
+	if SEXTIC_TWIST == M_TYPE {
+		b.times_i()
+	}	
+	r.mul(x)
+	r.add(b)
+
+	r.reduce()
+	return r
+}
+
+/* construct this from (x,y) - but set to O if not on curve */
+func NewECP8fp8s(ix *FP8,iy *FP8) *ECP8 {
+	E:=new(ECP8)
+	E.x=NewFP8copy(ix)
+	E.y=NewFP8copy(iy)
+	E.z=NewFP8int(1)
+	E.x.norm()
+	rhs:=RHS4(E.x)
+	y2:=NewFP8copy(E.y)
+	y2.sqr()
+	if !y2.Equals(rhs) {
+		E.inf()
+	} 
+	return E
+}
+
+/* construct this from x - but set to O if not on curve */
+func NewECP8fp8(ix *FP8) *ECP8 {	
+	E:=new(ECP8)
+	E.x=NewFP8copy(ix)
+	E.y=NewFP8int(1)
+	E.z=NewFP8int(1)
+	E.x.norm()
+	rhs:=RHS4(E.x)
+	if rhs.sqrt() {
+			E.y.copy(rhs)
+			//E.INF=false;
+	} else {E.inf()}
+	return E
+}
+
+/* this+=this */
+func (E *ECP8) dbl() int {
+//	if E.INF {return -1}
+
+	iy:=NewFP8copy(E.y)
+	if SEXTIC_TWIST == D_TYPE {
+		iy.times_i(); //iy.norm()
+	}
+
+	t0:=NewFP8copy(E.y)                  //***** Change 
+	t0.sqr();  
+	if SEXTIC_TWIST == D_TYPE {	
+		t0.times_i()   
+	}
+	t1:=NewFP8copy(iy)  
+	t1.mul(E.z)
+	t2:=NewFP8copy(E.z)
+	t2.sqr()
+
+	E.z.copy(t0)
+	E.z.add(t0); E.z.norm() 
+	E.z.add(E.z)
+	E.z.add(E.z) 
+	E.z.norm()  
+
+	t2.imul(3*CURVE_B_I) 
+	if SEXTIC_TWIST == M_TYPE {
+		t2.times_i()
+		//t2.norm()
+	}
+	x3:=NewFP8copy(t2)
+	x3.mul(E.z) 
+
+	y3:=NewFP8copy(t0)   
+
+	y3.add(t2); y3.norm()
+	E.z.mul(t1)
+	t1.copy(t2); t1.add(t2); t2.add(t1); t2.norm()  
+	t0.sub(t2); t0.norm()                           //y^2-9bz^2
+	y3.mul(t0); y3.add(x3)                          //(y^2+3z*2)(y^2-9z^2)+3b.z^2.8y^2
+	t1.copy(E.x); t1.mul(iy)						//
+	E.x.copy(t0); E.x.norm(); E.x.mul(t1); E.x.add(E.x)       //(y^2-9bz^2)xy2
+
+	E.x.norm()
+	E.y.copy(y3); E.y.norm()
+
+	return 1
+}
+
+/* this+=Q - return 0 for add, 1 for double, -1 for O */
+func (E *ECP8) Add(Q *ECP8) int {
+/*	if E.INF {
+		E.Copy(Q)
+		return -1
+	}
+	if Q.INF {return -1}
+*/
+	b:=3*CURVE_B_I
+	t0:=NewFP8copy(E.x)
+	t0.mul(Q.x)         // x.Q.x
+	t1:=NewFP8copy(E.y)
+	t1.mul(Q.y)		 // y.Q.y
+
+	t2:=NewFP8copy(E.z)
+	t2.mul(Q.z)
+	t3:=NewFP8copy(E.x)
+	t3.add(E.y); t3.norm()          //t3=X1+Y1
+	t4:=NewFP8copy(Q.x)            
+	t4.add(Q.y); t4.norm()			//t4=X2+Y2
+	t3.mul(t4)						//t3=(X1+Y1)(X2+Y2)
+	t4.copy(t0); t4.add(t1)		//t4=X1.X2+Y1.Y2
+
+	t3.sub(t4); t3.norm(); 
+	if SEXTIC_TWIST == D_TYPE {
+		t3.times_i();  //t3.norm()         //t3=(X1+Y1)(X2+Y2)-(X1.X2+Y1.Y2) = X1.Y2+X2.Y1
+	}
+	t4.copy(E.y);                    
+	t4.add(E.z); t4.norm()			//t4=Y1+Z1
+	x3:=NewFP8copy(Q.y)
+	x3.add(Q.z); x3.norm()			//x3=Y2+Z2
+
+	t4.mul(x3)						//t4=(Y1+Z1)(Y2+Z2)
+	x3.copy(t1)					//
+	x3.add(t2)						//X3=Y1.Y2+Z1.Z2
+	
+	t4.sub(x3); t4.norm();
+	if SEXTIC_TWIST == D_TYPE {	
+		t4.times_i(); //t4.norm()          //t4=(Y1+Z1)(Y2+Z2) - (Y1.Y2+Z1.Z2) = Y1.Z2+Y2.Z1
+	}
+	x3.copy(E.x); x3.add(E.z); x3.norm()	// x3=X1+Z1
+	y3:=NewFP8copy(Q.x)				
+	y3.add(Q.z); y3.norm()				// y3=X2+Z2
+	x3.mul(y3)							// x3=(X1+Z1)(X2+Z2)
+	y3.copy(t0)
+	y3.add(t2)							// y3=X1.X2+Z1+Z2
+	y3.rsub(x3); y3.norm()				// y3=(X1+Z1)(X2+Z2) - (X1.X2+Z1.Z2) = X1.Z2+X2.Z1
+
+	if SEXTIC_TWIST == D_TYPE {
+		t0.times_i(); //t0.norm() // x.Q.x
+		t1.times_i(); //t1.norm() // y.Q.y
+	}
+	x3.copy(t0); x3.add(t0) 
+	t0.add(x3); t0.norm()
+	t2.imul(b) 	
+	if SEXTIC_TWIST == M_TYPE {
+		t2.times_i()
+	}
+	z3:=NewFP8copy(t1); z3.add(t2); z3.norm()
+	t1.sub(t2); t1.norm()
+	y3.imul(b) 
+	if SEXTIC_TWIST == M_TYPE {
+		y3.times_i()
+		//y3.norm()
+	}
+	x3.copy(y3); x3.mul(t4); t2.copy(t3); t2.mul(t1); x3.rsub(t2)
+	y3.mul(t0); t1.mul(z3); y3.add(t1)
+	t0.mul(t3); z3.mul(t4); z3.add(t0)
+
+	E.x.copy(x3); E.x.norm() 
+	E.y.copy(y3); E.y.norm()
+	E.z.copy(z3); E.z.norm()
+
+	return 0
+}
+
+/* set this-=Q */
+func (E *ECP8) Sub(Q *ECP8) int {
+	NQ:=NewECP8(); NQ.Copy(Q)
+	NQ.neg()
+	D:=E.Add(NQ)
+	//Q.neg()
+	return D
+}
+
+func ECP8_frob_constants() [3]*FP2 {
+	Fra:=NewBIGints(Fra)
+	Frb:=NewBIGints(Frb)
+	X:=NewFP2bigs(Fra,Frb)	
+
+	F0:=NewFP2copy(X); F0.sqr()
+	F2:=NewFP2copy(F0)
+	F2.mul_ip(); F2.norm()
+	F1:=NewFP2copy(F2); F1.sqr()
+	F2.mul(F1)
+
+	F2.mul_ip(); F2.norm()
+
+	F1.copy(X)
+	if SEXTIC_TWIST == M_TYPE {
+		F1.mul_ip()
+		F1.inverse()
+		F0.copy(F1); F0.sqr()
+	}
+	F0.mul_ip(); F0.norm()
+	F1.mul(F0)
+	F:=[3]*FP2{F0,F1,F2}
+	return F
+}
+
+/* set this*=q, where q is Modulus, using Frobenius */
+func (E *ECP8) frob(F [3]*FP2,n int) {
+//	if E.INF {return}
+	for i:=0;i<n;i++ {
+		E.x.frob(F[2])
+		E.x.qmul(F[0])
+		if SEXTIC_TWIST == M_TYPE {
+			E.x.div_i2()
+		}
+		if SEXTIC_TWIST == D_TYPE {
+			E.x.times_i2()
+		}		
+
+		E.y.frob(F[2])
+		E.y.qmul(F[1])
+		if SEXTIC_TWIST == M_TYPE {
+			E.y.div_i()
+		}
+		if SEXTIC_TWIST == D_TYPE {
+			E.y.times_i2(); E.y.times_i2(); E.y.times_i()
+		}		
+		E.z.frob(F[2])
+	}
+}
+
+/* P*=e */
+func (E *ECP8) mul(e *BIG) *ECP8 {
+/* fixed size windows */
+	mt:=NewBIG()
+	t:=NewBIG()
+	P:=NewECP8()
+	Q:=NewECP8()
+	C:=NewECP8()
+
+	if E.Is_infinity() {return NewECP8()}
+
+	var W []*ECP8
+	var w [1+(NLEN*int(BASEBITS)+3)/4]int8
+
+	//E.Affine()
+/* precompute table */
+	Q.Copy(E)
+	Q.dbl()
+		
+	W=append(W,NewECP8())
+	W[0].Copy(E);
+
+	for i:=1;i<8;i++ {
+		W=append(W,NewECP8())
+		W[i].Copy(W[i-1])
+		W[i].Add(Q)
+	}
+
+/* make exponent odd - add 2P if even, P if odd */
+	t.copy(e)
+	s:=int(t.parity())
+	t.inc(1); t.norm(); ns:=int(t.parity()); mt.copy(t); mt.inc(1); mt.norm()
+	t.cmove(mt,s)
+	Q.cmove(E,ns)
+	C.Copy(Q)
+
+	nb:=1+(t.nbits()+3)/4
+/* convert exponent to signed 4-bit window */
+	for i:=0;i<nb;i++ {
+		w[i]=int8(t.lastbits(5)-16)
+		t.dec(int(w[i])); t.norm()
+		t.fshr(4)	
+	}
+	w[nb]=int8(t.lastbits(5))
+		
+	P.Copy(W[(w[nb]-1)/2])
+	for i:=nb-1;i>=0;i-- {
+		Q.selector(W,int32(w[i]))
+		P.dbl()
+		P.dbl()
+		P.dbl()
+		P.dbl()
+		P.Add(Q)
+	}
+	P.Sub(C)
+	P.Affine()
+	return P
+}
+
+/* Public version */
+func (E *ECP8) Mul(e *BIG) *ECP8 {
+	return E.mul(e)
+}
+
+func ECP8_generator() *ECP8 {
+	var G *ECP8
+	G=NewECP8fp8s( 
+		NewFP8fp4s(
+			NewFP4fp2s(
+				NewFP2bigs(NewBIGints(CURVE_Pxaaa),NewBIGints(CURVE_Pxaab)),
+				NewFP2bigs(NewBIGints(CURVE_Pxaba),NewBIGints(CURVE_Pxabb))),
+			NewFP4fp2s(
+				NewFP2bigs(NewBIGints(CURVE_Pxbaa),NewBIGints(CURVE_Pxbab)),
+				NewFP2bigs(NewBIGints(CURVE_Pxbba),NewBIGints(CURVE_Pxbbb)))),
+		NewFP8fp4s(
+			NewFP4fp2s(
+				NewFP2bigs(NewBIGints(CURVE_Pyaaa),NewBIGints(CURVE_Pyaab)),
+				NewFP2bigs(NewBIGints(CURVE_Pyaba),NewBIGints(CURVE_Pyabb))),
+			NewFP4fp2s(
+				NewFP2bigs(NewBIGints(CURVE_Pybaa),NewBIGints(CURVE_Pybab)),
+				NewFP2bigs(NewBIGints(CURVE_Pybba),NewBIGints(CURVE_Pybbb)))))
+	return G
+}
+
+/* needed for SOK */
+func ECP8_mapit(h []byte) *ECP8 {
+	q:=NewBIGints(Modulus)
+	hv:=FromBytes(h[:])
+	one:=NewBIGint(1)
+	var X2 *FP2
+	var X4 *FP4 
+	var X *FP8
+	var Q *ECP8
+	hv.Mod(q)
+	for true {
+		X2=NewFP2bigs(one,hv)
+		X4=NewFP4fp2(X2)
+		X=NewFP8fp4(X4)
+		Q=NewECP8fp8(X)
+		if !Q.Is_infinity() {break}
+		hv.inc(1); hv.norm()
+	}
+	F:=ECP8_frob_constants()
+	x:=NewBIGints(CURVE_Bnx)
+
+	xQ:=Q.mul(x)
+	x2Q:=xQ.mul(x)
+	x3Q:=x2Q.mul(x)
+	x4Q:=x3Q.mul(x)
+	x5Q:=x4Q.mul(x)
+	x6Q:=x5Q.mul(x)
+	x7Q:=x6Q.mul(x)
+	x8Q:=x7Q.mul(x)
+
+	if SIGN_OF_X==NEGATIVEX {
+		xQ.neg()
+		x3Q.neg()
+		x5Q.neg()
+		x7Q.neg()
+	}
+	x8Q.Sub(x7Q)
+	x8Q.Sub(Q)
+
+	x7Q.Sub(x6Q)
+	x7Q.frob(F,1)
+
+	x6Q.Sub(x5Q)
+	x6Q.frob(F,2)
+
+	x5Q.Sub(x4Q)
+	x5Q.frob(F,3)
+
+	x4Q.Sub(x3Q)
+	x4Q.frob(F,4)
+
+	x3Q.Sub(x2Q)
+	x3Q.frob(F,5)
+
+	x2Q.Sub(xQ)
+	x2Q.frob(F,6)
+
+	xQ.Sub(Q)
+	xQ.frob(F,7)
+
+	Q.dbl()
+	Q.frob(F,8)
+
+	Q.Add(x8Q)
+	Q.Add(x7Q)
+	Q.Add(x6Q)
+	Q.Add(x5Q)
+
+	Q.Add(x4Q)
+	Q.Add(x3Q)
+	Q.Add(x2Q)
+	Q.Add(xQ)
+
+	Q.Affine()
+	return Q
+}
+
+/* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3.. */
+// Bos & Costello https://eprint.iacr.org/2013/458.pdf
+// Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
+// Side channel attack secure 
+func mul16(Q []*ECP8,u []*BIG) *ECP8 {
+	W:=NewECP8()
+	P:=NewECP8()
+	var T1 [] *ECP8
+	var T2 [] *ECP8
+	var T3 [] *ECP8
+	var T4 [] *ECP8
+	mt:=NewBIG()
+	var t [] *BIG
+	var bt int8
+	var k int
+
+	var w1 [NLEN*int(BASEBITS)+1]int8	
+	var s1 [NLEN*int(BASEBITS)+1]int8	
+	var w2 [NLEN*int(BASEBITS)+1]int8	
+	var s2 [NLEN*int(BASEBITS)+1]int8	
+	var w3 [NLEN*int(BASEBITS)+1]int8	
+	var s3 [NLEN*int(BASEBITS)+1]int8	
+	var w4 [NLEN*int(BASEBITS)+1]int8	
+	var s4 [NLEN*int(BASEBITS)+1]int8	
+
+	for i:=0;i<16;i++ {
+		t=append(t,NewBIGcopy(u[i]));
+		//Q[i].Affine();
+	}
+
+	T1=append(T1,NewECP8()); T1[0].Copy(Q[0])	// Q[0]
+	T1=append(T1,NewECP8()); T1[1].Copy(T1[0]); T1[1].Add(Q[1])	// Q[0]+Q[1]
+	T1=append(T1,NewECP8()); T1[2].Copy(T1[0]); T1[2].Add(Q[2])	// Q[0]+Q[2]
+	T1=append(T1,NewECP8()); T1[3].Copy(T1[1]); T1[3].Add(Q[2])	// Q[0]+Q[1]+Q[2]
+	T1=append(T1,NewECP8()); T1[4].Copy(T1[0]); T1[4].Add(Q[3])	// Q[0]+Q[3]
+	T1=append(T1,NewECP8()); T1[5].Copy(T1[1]); T1[5].Add(Q[3])	// Q[0]+Q[1]+Q[3]
+	T1=append(T1,NewECP8()); T1[6].Copy(T1[2]); T1[6].Add(Q[3])	// Q[0]+Q[2]+Q[3]
+	T1=append(T1,NewECP8()); T1[7].Copy(T1[3]); T1[7].Add(Q[3])	// Q[0]+Q[1]+Q[2]+Q[3]
+
+//  Use Frobenius 
+	F:=ECP8_frob_constants()
+
+	for i:=0;i<8;i++ {
+		T2=append(T2,NewECP8()); T2[i].Copy(T1[i]); T2[i].frob(F,4)
+		T3=append(T3,NewECP8()); T3[i].Copy(T2[i]); T3[i].frob(F,4)
+		T4=append(T4,NewECP8()); T4[i].Copy(T3[i]); T4[i].frob(F,4)
+	}
+
+// Make them odd
+	pb1:=1-t[0].parity()
+	t[0].inc(pb1)
+//	t[0].norm();
+
+	pb2:=1-t[4].parity()
+	t[4].inc(pb2)
+//	t[4].norm();
+
+	pb3:=1-t[8].parity()
+	t[8].inc(pb3)
+//	t[8].norm();
+
+	pb4:=1-t[12].parity()
+	t[12].inc(pb4)
+//	t[12].norm();
+
+// Number of bits
+	mt.zero()
+	for i:=0;i<16;i++ {
+		t[i].norm()
+		mt.or(t[i])
+	}
+
+	nb:=1+mt.nbits();
+	
+// Sign pivot 
+	s1[nb-1]=1
+	s2[nb-1]=1
+	s3[nb-1]=1
+	s4[nb-1]=1
+	for i:=0;i<nb-1;i++ {
+		t[0].fshr(1)
+		s1[i]=2*int8(t[0].parity())-1
+		t[4].fshr(1)
+		s2[i]=2*int8(t[4].parity())-1
+		t[8].fshr(1)
+		s3[i]=2*int8(t[8].parity())-1
+		t[12].fshr(1)
+		s4[i]=2*int8(t[12].parity())-1
+
+	}
+
+// Recoded exponents
+	for i:=0; i<nb; i++ {
+		w1[i]=0
+		k=1
+		for j:=1; j<4; j++ {
+			bt=s1[i]*int8(t[j].parity())
+			t[j].fshr(1)
+			t[j].dec(int(bt)>>1)
+			t[j].norm()
+			w1[i]+=bt*int8(k)
+			k*=2
+		}
+		w2[i]=0
+		k=1
+		for j:=5; j<8; j++ {
+			bt=s2[i]*int8(t[j].parity())
+			t[j].fshr(1)
+			t[j].dec(int(bt)>>1)
+			t[j].norm()
+			w2[i]+=bt*int8(k)
+			k*=2
+		}
+		w3[i]=0
+		k=1
+		for j:=9; j<12; j++ {
+			bt=s3[i]*int8(t[j].parity())
+			t[j].fshr(1)
+			t[j].dec(int(bt)>>1)
+			t[j].norm()
+			w3[i]+=bt*int8(k)
+			k*=2
+		}
+		w4[i]=0
+		k=1
+		for j:=13; j<16; j++ {
+			bt=s4[i]*int8(t[j].parity())
+			t[j].fshr(1)
+			t[j].dec(int(bt)>>1)
+			t[j].norm()
+			w4[i]+=bt*int8(k)
+			k*=2
+		}
+	}
+
+// Main loop
+	P.selector(T1,int32(2*w1[nb-1]+1))  
+	W.selector(T2,int32(2*w2[nb-1]+1))
+	P.Add(W)
+	W.selector(T3,int32(2*w3[nb-1]+1))
+	P.Add(W)
+	W.selector(T4,int32(2*w4[nb-1]+1))
+	P.Add(W)
+	for i:=nb-2;i>=0;i-- {
+		P.dbl()
+		W.selector(T1,int32(2*w1[i]+s1[i]))
+		P.Add(W)
+		W.selector(T2,int32(2*w2[i]+s2[i]))
+		P.Add(W)
+		W.selector(T3,int32(2*w3[i]+s3[i]))
+		P.Add(W)
+		W.selector(T4,int32(2*w4[i]+s4[i]))
+		P.Add(W)
+
+	}
+
+// apply correction
+	W.Copy(P)   
+	W.Sub(Q[0])
+	P.cmove(W,pb1)
+	W.Copy(P)   
+	W.Sub(Q[4])
+	P.cmove(W,pb2)
+	W.Copy(P)   
+	W.Sub(Q[8])
+	P.cmove(W,pb3)
+	W.Copy(P)   
+	W.Sub(Q[12])
+	P.cmove(W,pb4)
+
+	P.Affine()
+	return P
+}
+
diff --git a/version3/go/FF32.go b/version3/go/FF32.go
new file mode 100644
index 0000000..875cb1c
--- /dev/null
+++ b/version3/go/FF32.go
@@ -0,0 +1,943 @@
+/*
+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.
+*/
+
+package XXX
+
+//import "fmt"
+//import "os"
+import "github.com/milagro-crypto/amcl/version3/go/amcl"
+
+//var debug bool = false
+
+const FFLEN int=@ML@
+
+const FF_BITS int=(BIGBITS*FFLEN) /* Finite Field Size in bits - must be 256.2^n */
+const HFLEN int=(FFLEN/2)  /* Useful for half-size RSA private key operations */
+
+const P_MBITS uint=MODBYTES*8
+const P_OMASK Chunk=(Chunk(-1)<<(P_MBITS%BASEBITS))
+const P_FEXCESS Chunk=(Chunk(1)<<(BASEBITS*uint(NLEN)-P_MBITS-1))
+const P_TBITS uint=(P_MBITS%BASEBITS)
+
+func FF_EXCESS(a* BIG) Chunk {
+	return ((a.w[NLEN-1]&P_OMASK)>>(P_TBITS))+1
+}
+
+/***************** Start 64-bit specific code ****************/
+
+func ff_pexceed(a *BIG,b *BIG) bool {
+	ea:=FF_EXCESS(a)
+	eb:=FF_EXCESS(b)
+	if DChunk(ea+1)*DChunk(eb+1)>DChunk(P_FEXCESS) {return true}
+	return false
+}
+
+func ff_sexceed(a *BIG) bool {
+	ea:=FF_EXCESS(a)
+	if DChunk(ea+1)*DChunk(ea+1)>DChunk(P_FEXCESS) {return true}
+	return false
+}
+
+/***************** End 64-bit specific code ****************/
+
+
+type FF struct {
+	length int
+	v []*BIG
+}
+
+/* Constructors */
+func NewFFint(n int) *FF {
+	F:=new(FF)
+	for i:=0;i<n;i++ {
+		F.v=append(F.v,NewBIG())
+	}
+	F.length=n
+	return F
+}
+/*
+func NewFFints(x [][NLEN]int64,n int) *FF {
+	F:=new(FF)
+	for i:=0;i<n;i++ {
+		F.v=append(F.v,NewBIGints(x[i]))
+	}
+	F.length=n
+	return F
+}
+*/
+/* set to zero */
+func (F *FF) zero() {
+	for i:=0;i<F.length;i++ {
+		F.v[i].zero()
+	}
+}
+
+
+
+func (F *FF) getlen() int {
+		return F.length
+	}
+
+/* set to integer */
+func (F *FF) set(m int) {
+	F.zero()
+	F.v[0].set(0,Chunk(m))
+}
+
+/* copy from FF b */
+func (F *FF) copy(b *FF) {
+	for i:=0;i<F.length;i++ {
+		F.v[i].copy(b.v[i])
+	}
+}
+
+/* x=y<<n */
+func (F *FF) dsucopy(b *FF) {
+	for i:=0;i<b.length;i++ {
+		F.v[b.length+i].copy(b.v[i])
+		F.v[i].zero()
+	}
+}
+
+/* x=y */
+func (F *FF) dscopy(b *FF) {
+	for i:=0;i<b.length;i++ {
+		F.v[i].copy(b.v[i])
+		F.v[b.length+i].zero()
+	}
+}
+
+/* x=y>>n */
+func (F *FF) sducopy(b *FF) {
+	for i:=0;i<F.length;i++ {
+		F.v[i].copy(b.v[F.length+i])
+	}
+}
+
+func (F *FF) one() {
+	F.v[0].one();
+	for i:=1;i<F.length;i++ {
+		F.v[i].zero()
+	}
+}
+
+/* test equals 0 */
+func (F *FF) iszilch() bool {
+	for i:=0;i<F.length;i++ {
+		if !F.v[i].iszilch() {return false}
+	}
+	return true
+}
+
+/* shift right by BIGBITS-bit words */
+func (F *FF) shrw(n int) {
+	for i:=0;i<n;i++ {
+		F.v[i].copy(F.v[i+n])
+		F.v[i+n].zero()
+	}
+}
+
+/* shift left by BIGBITS-bit words */
+func (F *FF) shlw(n int) {
+	for i:=0;i<n;i++ {
+		F.v[n+i].copy(F.v[i])
+		F.v[i].zero()
+	}
+}
+
+/* extract last bit */
+func (F *FF) parity() int {
+	return F.v[0].parity()
+}
+
+func (F *FF) lastbits(m int) int {
+	return F.v[0].lastbits(m)
+}
+
+/* compare x and y - must be normalised, and of same length */
+func ff_comp(a *FF,b *FF) int {
+	for i:=a.length-1;i>=0;i-- {
+		j:=Comp(a.v[i],b.v[i])
+		if j!=0 {return j}
+	}
+	return 0
+}
+
+/* recursive add */
+func (F *FF) radd(vp int,x *FF,xp int,y *FF,yp int,n int) {
+	for i:=0;i<n;i++ {
+		F.v[vp+i].copy(x.v[xp+i])
+		F.v[vp+i].add(y.v[yp+i])
+	}
+}
+
+/* recursive inc */
+func (F *FF) rinc(vp int,y *FF,yp int,n int) {
+	for i:=0;i<n;i++ {
+		F.v[vp+i].add(y.v[yp+i])
+	}
+}
+
+/* recursive sub */
+func (F *FF) rsub(vp int,x *FF,xp int,y *FF,yp int,n int) {
+	for i:=0;i<n;i++ {
+		F.v[vp+i].copy(x.v[xp+i])
+		F.v[vp+i].sub(y.v[yp+i])
+	}
+}
+
+/* recursive dec */
+func (F *FF) rdec(vp int,y *FF,yp int,n int) {
+	for i:=0;i<n;i++ {
+		F.v[vp+i].sub(y.v[yp+i])
+	}
+}
+
+/* simple add */
+func (F *FF) add(b *FF) {
+	for i:=0;i<F.length;i++ {
+		F.v[i].add(b.v[i])
+	}
+}
+
+/* simple sub */
+func (F *FF) sub(b *FF) {
+	for i:=0;i<F.length;i++ {
+		F.v[i].sub(b.v[i])
+	}
+}
+	
+/* reverse sub */
+func (F *FF) revsub(b *FF) {
+	for i:=0;i<F.length;i++ {
+		F.v[i].rsub(b.v[i])
+	}
+}
+
+/* normalise - but hold any overflow in top part unless n<0 */
+func (F *FF) rnorm(vp int,n int) {
+	trunc:=false
+	var carry Chunk
+	if n<0 { /* -v n signals to do truncation */
+		n=-n
+		trunc=true
+	}
+	for i:=0;i<n-1;i++ {
+		carry=F.v[vp+i].norm()
+		F.v[vp+i].xortop(carry<<P_TBITS)
+		F.v[vp+i+1].w[0]+=carry; // inc(carry)
+	}
+	carry=F.v[vp+n-1].norm()
+	if trunc {
+		F.v[vp+n-1].xortop(carry<<P_TBITS)
+	}
+}
+
+func (F *FF) norm() {
+	F.rnorm(0,F.length)
+}
+
+/* increment/decrement by a small integer */
+func (F *FF) inc(m int) {
+	F.v[0].inc(m)
+	F.norm()
+}
+
+func (F *FF) dec(m int) {
+	F.v[0].dec(m)
+	F.norm()
+}
+
+/* shift left by one bit */
+func (F *FF) shl() {
+	var delay_carry int=0
+	for i:=0;i<F.length-1;i++ {
+		carry:=F.v[i].fshl(1)
+		F.v[i].inc(delay_carry)
+		F.v[i].xortop(Chunk(carry)<<P_TBITS)
+		delay_carry=int(carry)
+	}
+	F.v[F.length-1].fshl(1)
+	F.v[F.length-1].inc(delay_carry)
+}
+
+/* shift right by one bit */
+
+func (F *FF) shr() {
+	for i:=F.length-1;i>0;i-- {
+		carry:=F.v[i].fshr(1)
+		F.v[i-1].xortop(Chunk(carry)<<P_TBITS)
+	}
+	F.v[0].fshr(1)
+}
+
+/* Convert to Hex String */
+func (F *FF) toString() string {
+	F.norm()
+	s:=""
+	for i:=F.length-1;i>=0;i-- {
+		s+=F.v[i].ToString()
+	}
+	return s
+}
+
+/* Convert FFs to/from byte arrays */
+func (F *FF) toBytes(b []byte) {
+	for i:=0;i<F.length;i++ {
+		F.v[i].tobytearray(b,(F.length-i-1)*int(MODBYTES))
+	}
+}
+
+func ff_fromBytes(x *FF,b []byte) {
+	for i:=0;i<x.length;i++ {
+		x.v[i]=frombytearray(b,(x.length-i-1)*int(MODBYTES))
+	}
+}
+
+/* in-place swapping using xor - side channel resistant - lengths must be the same */
+func ff_cswap(a *FF,b *FF,d int) {
+	for i:=0;i<a.length;i++ {
+		a.v[i].cswap(b.v[i],d)
+	}
+}
+
+/* z=x*y, t is workspace */
+func (F *FF) karmul(vp int,x *FF,xp int,y *FF,yp int,t *FF,tp int,n int) {
+	if n==1 {
+		x.v[xp].norm()
+		y.v[yp].norm()
+		d:=mul(x.v[xp],y.v[yp])
+		F.v[vp+1]=d.split(8*MODBYTES)
+		F.v[vp].dcopy(d)
+		return
+	}
+	nd2:=n/2
+	F.radd(vp,x,xp,x,xp+nd2,nd2)
+		F.rnorm(vp,nd2)
+	F.radd(vp+nd2,y,yp,y,yp+nd2,nd2)
+		F.rnorm(vp+nd2,nd2)
+	t.karmul(tp,F,vp,F,vp+nd2,t,tp+n,nd2)
+	F.karmul(vp,x,xp,y,yp,t,tp+n,nd2)
+	F.karmul(vp+n,x,xp+nd2,y,yp+nd2,t,tp+n,nd2)
+	t.rdec(tp,F,vp,n)
+	t.rdec(tp,F,vp+n,n)
+	F.rinc(vp+nd2,t,tp,n)
+	F.rnorm(vp,2*n)
+}
+
+func (F *FF) karsqr(vp int,x *FF,xp int,t *FF,tp int,n int) {
+	if n==1 {
+		x.v[xp].norm()
+		d:=sqr(x.v[xp])
+		F.v[vp+1].copy(d.split(8*MODBYTES))
+		F.v[vp].dcopy(d)
+		return
+	}	
+
+	nd2:=n/2
+	F.karsqr(vp,x,xp,t,tp+n,nd2)
+	F.karsqr(vp+n,x,xp+nd2,t,tp+n,nd2)
+	t.karmul(tp,x,xp,x,xp+nd2,t,tp+n,nd2)
+	F.rinc(vp+nd2,t,tp,n)
+	F.rinc(vp+nd2,t,tp,n)
+	F.rnorm(vp+nd2,n)
+}
+
+/* Calculates Least Significant bottom half of x*y */
+func (F *FF) karmul_lower(vp int,x *FF,xp int,y *FF,yp int,t *FF,tp int,n int) { 
+	if n==1 { /* only calculate bottom half of product */
+		F.v[vp].copy(smul(x.v[xp],y.v[yp]))
+		return
+	}
+	nd2:=n/2
+
+	F.karmul(vp,x,xp,y,yp,t,tp+n,nd2)
+	t.karmul_lower(tp,x,xp+nd2,y,yp,t,tp+n,nd2)
+	F.rinc(vp+nd2,t,tp,nd2)
+	t.karmul_lower(tp,x,xp,y,yp+nd2,t,tp+n,nd2)
+	F.rinc(vp+nd2,t,tp,nd2)
+	F.rnorm(vp+nd2,-nd2)  /* truncate it */
+}
+
+/* Calculates Most Significant upper half of x*y, given lower part */
+func (F *FF) karmul_upper(x *FF,y *FF,t *FF,n int) { 
+	nd2:=n/2
+	F.radd(n,x,0,x,nd2,nd2)
+	F.radd(n+nd2,y,0,y,nd2,nd2)
+	F.rnorm(n,nd2)
+	F.rnorm(n+nd2,nd2)
+
+	t.karmul(0,F,n+nd2,F,n,t,n,nd2)  /* t = (a0+a1)(b0+b1) */
+	F.karmul(n,x,nd2,y,nd2,t,n,nd2) /* z[n]= a1*b1 */
+
+					/* z[0-nd2]=l(a0b0) z[nd2-n]= h(a0b0)+l(t)-l(a0b0)-l(a1b1) */
+	t.rdec(0,F,n,n)              /* t=t-a1b1  */	
+						
+	F.rinc(nd2,F,0,nd2)  /* z[nd2-n]+=l(a0b0) = h(a0b0)+l(t)-l(a1b1)  */
+	F.rdec(nd2,t,0,nd2)   /* z[nd2-n]=h(a0b0)+l(t)-l(a1b1)-l(t-a1b1)=h(a0b0) */
+
+	F.rnorm(0,-n)		/* a0b0 now in z - truncate it */
+
+	t.rdec(0,F,0,n)         /* (a0+a1)(b0+b1) - a0b0 */
+	F.rinc(nd2,t,0,n)
+
+	F.rnorm(nd2,n)
+}
+
+/* z=x*y. Assumes x and y are of same length. */
+func ff_mul(x *FF,y *FF) *FF {
+	n:=x.length
+	z:=NewFFint(2*n)
+	t:=NewFFint(2*n)
+	z.karmul(0,x,0,y,0,t,0,n)
+	return z
+}
+
+/* return low part of product this*y */
+func (F *FF) lmul(y *FF) {
+	n:=F.length
+	t:=NewFFint(2*n)
+	x:=NewFFint(n); x.copy(F)
+	F.karmul_lower(0,x,0,y,0,t,0,n)
+}
+
+/* Set b=b mod c */
+func (F *FF) mod(c *FF) {
+	var k int=1  
+
+	F.norm()
+	if ff_comp(F,c)<0 {return}
+
+	c.shl()
+	for ff_comp(F,c)>=0 {
+		c.shl()
+		k++
+	}
+
+	for k>0 {
+		c.shr()
+		if ff_comp(F,c)>=0 {
+			F.sub(c)
+			F.norm()
+		}
+		k--
+	}
+}
+
+/* z=x^2 */
+func ff_sqr(x *FF) *FF {
+	n:=x.length
+	z:=NewFFint(2*n)
+	t:=NewFFint(2*n)
+	z.karsqr(0,x,0,t,0,n)
+	return z
+}
+
+/* return This mod modulus, N is modulus, ND is Montgomery Constant */
+func (F *FF) reduce(N *FF,ND *FF) *FF { /* fast karatsuba Montgomery reduction */
+	n:=N.length
+	t:=NewFFint(2*n)
+	r:=NewFFint(n)
+	m:=NewFFint(n)
+
+	r.sducopy(F)
+	m.karmul_lower(0,F,0,ND,0,t,0,n)
+
+	F.karmul_upper(N,m,t,n)
+	
+	m.sducopy(F)
+	r.add(N)
+	r.sub(m)
+	r.norm()
+
+	return r
+
+}
+
+/* Set r=this mod b */
+/* this is of length - 2*n */
+/* r,b is of length - n */
+func (F *FF) dmod(b *FF) *FF {
+	n:=b.length
+	m:=NewFFint(2*n)
+	x:=NewFFint(2*n)
+	r:=NewFFint(n)
+
+	x.copy(F)
+	x.norm()
+	m.dsucopy(b); k:=BIGBITS*n
+
+	for ff_comp(x,m)>=0 {
+		x.sub(m)
+		x.norm()
+	}
+
+	for k>0 {	
+		m.shr()
+
+		if ff_comp(x,m)>=0 {
+			x.sub(m)
+			x.norm()
+		}
+		k--
+	}
+
+	r.copy(x)
+	r.mod(b)
+	return r
+}
+
+/* Set return=1/this mod p. Binary method - a<p on entry */
+
+func (F *FF) invmodp(p *FF) {
+	n:=p.length
+
+	u:=NewFFint(n)
+	v:=NewFFint(n)
+	x1:=NewFFint(n)
+	x2:=NewFFint(n)
+	t:=NewFFint(n)
+	one:=NewFFint(n)
+
+	one.one()
+	u.copy(F)
+	v.copy(p)
+	x1.copy(one)
+	x2.zero()
+
+	// reduce n in here as well! 
+	for (ff_comp(u,one)!=0 && ff_comp(v,one)!=0) {
+		for u.parity()==0 {
+			u.shr()
+			if x1.parity()!=0 {
+				x1.add(p)
+				x1.norm()
+			}
+			x1.shr()
+		}
+		for v.parity()==0 {
+			v.shr() 
+			if x2.parity()!=0 {
+				x2.add(p)
+				x2.norm()
+			}
+			x2.shr()
+		}
+		if ff_comp(u,v)>=0 {
+			u.sub(v)
+			u.norm()
+			if ff_comp(x1,x2)>=0 {
+				x1.sub(x2)
+			} else {
+				t.copy(p)
+				t.sub(x2)
+				x1.add(t)
+			}
+			x1.norm()
+		} else {
+			v.sub(u)
+			v.norm()
+			if ff_comp(x2,x1)>=0 { 
+				x2.sub(x1)
+			} else {
+				t.copy(p)
+				t.sub(x1)
+				x2.add(t)
+			}
+			x2.norm()
+		}
+	}
+	if ff_comp(u,one)==0 {
+		F.copy(x1)
+	} else {
+		F.copy(x2)
+	}
+}
+
+/* nresidue mod m */
+func (F *FF) nres(m *FF) {
+	n:=m.length
+	if n==1 {
+		d:=NewDBIGscopy(F.v[0])
+		d.shl(uint(NLEN)*BASEBITS)
+		F.v[0].copy(d.mod(m.v[0]))
+	} else {
+		d:=NewFFint(2*n)
+		d.dsucopy(F)
+		F.copy(d.dmod(m))
+	}
+}
+
+func (F *FF) redc(m *FF,ND *FF) {
+	n:=m.length
+	if n==1 {
+		d:=NewDBIGscopy(F.v[0])
+		F.v[0].copy(monty(m.v[0],(Chunk(1)<<BASEBITS)-ND.v[0].w[0],d))
+	} else {
+		d:=NewFFint(2*n)
+		F.mod(m)
+		d.dscopy(F)
+		F.copy(d.reduce(m,ND))
+		F.mod(m)
+	}
+}
+
+func (F *FF) mod2m(m int) {
+	for i:=m;i<F.length;i++ {
+		F.v[i].zero()
+	}
+}
+
+/* U=1/a mod 2^m - Arazi & Qi */
+func (F *FF) invmod2m() *FF {
+	n:=F.length
+
+	b:=NewFFint(n)
+	c:=NewFFint(n)
+	U:=NewFFint(n)
+
+	U.zero()
+	U.v[0].copy(F.v[0])
+	U.v[0].invmod2m()
+
+	for i:=1;i<n;i<<=1 {
+		b.copy(F); b.mod2m(i)
+		t:=ff_mul(U,b); t.shrw(i); b.copy(t)
+		c.copy(F); c.shrw(i); c.mod2m(i)
+		c.lmul(U); c.mod2m(i)
+
+		b.add(c); b.norm()
+		b.lmul(U); b.mod2m(i)
+
+		c.one(); c.shlw(i); b.revsub(c); b.norm()
+		b.shlw(i)
+		U.add(b)
+	}
+	U.norm()
+	return U
+}
+
+func (F *FF) random(rng *amcl.RAND) {
+	n:=F.length
+	for i:=0;i<n;i++ {
+		F.v[i].copy(random(rng))
+	}
+	/* make sure top bit is 1 */
+	for (F.v[n-1].nbits()<int(MODBYTES*8)) {
+		F.v[n-1].copy(random(rng))
+	}
+}
+
+/* generate random x less than p */
+func (F *FF) Randomnum(p *FF,rng *amcl.RAND) {
+	n:=F.length
+	d:=NewFFint(2*n)
+
+	for i:=0;i<2*n;i++ {
+		d.v[i].copy(random(rng))
+	}
+	F.copy(d.dmod(p))
+}
+
+/* this*=y mod p */
+func (F *FF) modmul(y *FF,p *FF,nd *FF) {
+	if ff_pexceed(F.v[F.length-1],y.v[y.length-1]) {F.mod(p)}
+	n:=p.length
+	if n==1 {
+		d:=mul(F.v[0],y.v[0])
+		F.v[0].copy(monty(p.v[0],(Chunk(1)<<BASEBITS)-nd.v[0].w[0],d))
+	} else {
+		d:=ff_mul(F,y)
+		F.copy(d.reduce(p,nd))
+	}
+}
+
+/* this*=y mod p */
+func (F *FF) modsqr(p *FF,nd *FF) {
+	if ff_sexceed(F.v[F.length-1]) {F.mod(p)}
+	n:=p.length
+	if n==1 {
+		d:=sqr(F.v[0])
+		F.v[0].copy(monty(p.v[0],(Chunk(1)<<BASEBITS)-nd.v[0].w[0],d))
+	} else {
+		d:=ff_sqr(F)
+		F.copy(d.reduce(p,nd))
+	}
+}
+
+/* this=this^e mod p using side-channel resistant Montgomery Ladder, for large e */
+func (F *FF) skpow(e *FF,p *FF) {
+	n:=p.length
+	R0:=NewFFint(n)
+	R1:=NewFFint(n)
+	ND:=p.invmod2m()
+
+	F.mod(p)
+	R0.one()
+	R1.copy(F)
+	R0.nres(p)
+	R1.nres(p)
+
+	for i:=int(8*MODBYTES)*n-1;i>=0;i-- {
+		b:=int(e.v[i/BIGBITS].bit(i%BIGBITS))
+		F.copy(R0)
+		F.modmul(R1,p,ND)
+
+		ff_cswap(R0,R1,b)
+		R0.modsqr(p,ND)
+
+		R1.copy(F)
+		ff_cswap(R0,R1,b)
+	}
+	F.copy(R0)
+	F.redc(p,ND)
+}
+
+/* this =this^e mod p using side-channel resistant Montgomery Ladder, for short e */
+func (F *FF) skpows(e *BIG,p *FF) {
+	n:=p.length
+	R0:=NewFFint(n)
+	R1:=NewFFint(n)
+	ND:=p.invmod2m()
+
+	F.mod(p)
+	R0.one()
+	R1.copy(F)
+	R0.nres(p)
+	R1.nres(p)
+
+	for i:=int(8*MODBYTES)-1;i>=0;i-- {
+		b:=int(e.bit(i))
+		F.copy(R0)
+		F.modmul(R1,p,ND)
+
+		ff_cswap(R0,R1,b)
+		R0.modsqr(p,ND)
+
+		R1.copy(F)
+		ff_cswap(R0,R1,b)
+	}
+	F.copy(R0)
+	F.redc(p,ND)
+}
+
+/* raise to an integer power - right-to-left method */
+func (F *FF) power(e int,p *FF) {
+	n:=p.length
+	w:=NewFFint(n)
+	ND:=p.invmod2m()
+	f:=true
+
+	w.copy(F)
+	w.nres(p)
+//i:=0;
+	if e==2 {
+		F.copy(w)
+		F.modsqr(p,ND)
+	} else {
+		for (true) {
+			if e%2==1 {
+				if f {
+					F.copy(w)
+				} else {F.modmul(w,p,ND)}
+				f=false
+
+			}
+			e>>=1
+			if e==0 {break}
+//fmt.Printf("wb= "+w.toString()+"\n");
+//debug=true;
+			w.modsqr(p,ND)
+//debug=false;
+//fmt.Printf("wa= "+w.toString()+"\n");
+//i+=1;
+//os.Exit(0);
+		}
+	}
+
+	F.redc(p,ND)
+
+}
+
+/* this=this^e mod p, faster but not side channel resistant */
+func (F *FF) pow(e *FF,p *FF) {
+	n:=p.length
+	w:=NewFFint(n)
+	ND:=p.invmod2m()
+//fmt.Printf("ND= "+ND.toString() +"\n");
+	w.copy(F)
+	F.one()
+	F.nres(p)
+	w.nres(p)
+	for i:=int(8*MODBYTES)*n-1;i>=0;i-- {
+		F.modsqr(p,ND)
+		b:=e.v[i/BIGBITS].bit(i%BIGBITS)
+		if b==1 {F.modmul(w,p,ND)}
+	}
+	F.redc(p,ND)
+}
+
+/* double exponentiation r=x^e.y^f mod p */
+func (F *FF) pow2(e *BIG,y *FF,f *BIG,p *FF) {
+	n:=p.length
+	xn:=NewFFint(n)
+	yn:=NewFFint(n)
+	xy:=NewFFint(n)
+	ND:=p.invmod2m()
+
+	xn.copy(F)
+	yn.copy(y)
+	xn.nres(p)
+	yn.nres(p)
+	xy.copy(xn); xy.modmul(yn,p,ND)
+	F.one()
+	F.nres(p)
+
+	for i:=int(8*MODBYTES)-1;i>=0;i-- {
+		eb:=e.bit(i)
+		fb:=f.bit(i)
+		F.modsqr(p,ND)
+		if eb==1 {
+			if fb==1 {
+				F.modmul(xy,p,ND)
+			} else {F.modmul(xn,p,ND)}
+		} else	{
+			if fb==1 {F.modmul(yn,p,ND)}
+		}
+	}
+	F.redc(p,ND)
+}
+
+func igcd(x int,y int) int { /* integer GCD, returns GCD of x and y */
+	var r int
+	if y==0 {return x}
+	for true {
+		r=x%y
+		if r==0 {break}
+		x=y;y=r
+	}
+	return y
+}
+
+/* quick and dirty check for common factor with n */
+func (F *FF) cfactor(s int) bool {
+	n:=F.length
+
+	x:=NewFFint(n)
+	y:=NewFFint(n)
+
+	y.set(s)
+	x.copy(F)
+	x.norm()
+
+	x.sub(y)
+	x.norm()
+
+	for (!x.iszilch() && x.parity()==0) {x.shr()}
+
+	for (ff_comp(x,y)>0) {
+		x.sub(y)
+		x.norm()
+		for (!x.iszilch() && x.parity()==0) {x.shr()}
+	}
+
+	g:=int(x.v[0].get(0))
+	r:=igcd(s,g)
+	if r>1 {return true}
+	return false
+}
+
+/* Miller-Rabin test for primality. Slow. */
+func prime(p *FF,rng *amcl.RAND) bool {
+	s:=0
+	n:=p.length
+	d:=NewFFint(n)
+	x:=NewFFint(n)
+	unity:=NewFFint(n)
+	nm1:=NewFFint(n)
+
+	sf:=4849845 /* 3*5*.. *19 */
+	p.norm()
+
+	if p.cfactor(sf) {return false}
+	unity.one()
+	nm1.copy(p)
+	nm1.sub(unity)
+	nm1.norm()
+	d.copy(nm1)
+
+	for d.parity()==0 {
+		d.shr()
+		s++
+	}
+	if s==0 {return false}
+
+	for i:=0;i<10;i++ {
+		x.Randomnum(p,rng)
+		x.pow(d,p)
+
+		if (ff_comp(x,unity)==0 || ff_comp(x,nm1)==0) {continue}
+		loop:=false
+		for j:=1;j<s;j++ {
+			x.power(2,p)
+			if ff_comp(x,unity)==0 {return false}
+			if ff_comp(x,nm1)==0 {loop=true; break}
+		}
+		if loop {continue}
+		return false
+	}
+
+	return true
+}
+/*
+func main() {
+
+	var P = [4][5]int64 {{0xAD19A781670957,0x76A79C00965796,0xDEFCC5FC9A9717,0xF02F2940E20E9,0xBF59E34F},{0x6894F31844C908,0x8DADA70E82C79F,0xFD29F3836046F6,0x8C1D874D314DD0,0x46D077B},{0x3C515217813331,0x56680FD1CE935B,0xE55C53EEA8838E,0x92C2F7E14A4A95,0xD945E5B1},{0xACF673E919F5EF,0x6723E7E7DAB446,0x6B6FA69B36EB1B,0xF7D13920ECA300,0xB5FC2165}}
+
+	fmt.Printf("Testing FF\n")
+	var raw [100]byte
+	rng:=NewRAND()
+
+	rng.Clean()
+	for i:=0;i<100;i++ {
+		raw[i]=byte(i)
+	}
+
+	rng.Seed(100,raw[:])
+
+	n:=4
+
+	x:=NewFFint(n)
+	x.set(3)
+
+	p:=NewFFints(P[:],n)
+
+	if prime(p,rng) {fmt.Printf("p is a prime\n"); fmt.Printf("\n")}
+
+	e:=NewFFint(n)
+	e.copy(p)
+	e.dec(1); e.norm()
+
+	fmt.Printf("e= "+e.toString())
+	fmt.Printf("\n")
+	x.skpow(e,p)
+	fmt.Printf("x= "+x.toString())
+	fmt.Printf("\n")
+}
+*/
\ No newline at end of file
diff --git a/version3/go/FF64.go b/version3/go/FF64.go
new file mode 100644
index 0000000..9760303
--- /dev/null
+++ b/version3/go/FF64.go
@@ -0,0 +1,943 @@
+/*
+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.
+*/
+
+package XXX
+
+//import "fmt"
+//import "os"
+import "github.com/milagro-crypto/amcl/version3/go/amcl"
+
+//var debug bool = false
+
+const FFLEN int=@ML@
+
+const FF_BITS int=(BIGBITS*FFLEN) /* Finite Field Size in bits - must be 256.2^n */
+const HFLEN int=(FFLEN/2)  /* Useful for half-size RSA private key operations */
+
+const P_MBITS uint=MODBYTES*8
+const P_OMASK Chunk=(Chunk(-1)<<(P_MBITS%BASEBITS))
+const P_FEXCESS Chunk=(Chunk(1)<<(BASEBITS*uint(NLEN)-P_MBITS-1))
+const P_TBITS uint=(P_MBITS%BASEBITS)
+
+func FF_EXCESS(a* BIG) Chunk {
+	return ((a.w[NLEN-1]&P_OMASK)>>(P_TBITS))+1
+}
+
+/***************** Start 64-bit specific code ****************/
+
+func ff_pexceed(a *BIG,b *BIG) bool {
+	ea:=FF_EXCESS(a)
+	eb:=FF_EXCESS(b)
+	if (ea+1)>P_FEXCESS/(eb+1) {return true}
+	return false
+}
+
+func ff_sexceed(a *BIG) bool {
+	ea:=FF_EXCESS(a)
+	if (ea+1)>P_FEXCESS/(ea+1) {return true}
+	return false
+}
+
+/***************** End 64-bit specific code ****************/
+
+
+type FF struct {
+	length int
+	v []*BIG
+}
+
+/* Constructors */
+func NewFFint(n int) *FF {
+	F:=new(FF)
+	for i:=0;i<n;i++ {
+		F.v=append(F.v,NewBIG())
+	}
+	F.length=n
+	return F
+}
+/*
+func NewFFints(x [][NLEN]int64,n int) *FF {
+	F:=new(FF)
+	for i:=0;i<n;i++ {
+		F.v=append(F.v,NewBIGints(x[i]))
+	}
+	F.length=n
+	return F
+}
+*/
+/* set to zero */
+func (F *FF) zero() {
+	for i:=0;i<F.length;i++ {
+		F.v[i].zero()
+	}
+}
+
+
+
+func (F *FF) getlen() int {
+		return F.length
+	}
+
+/* set to integer */
+func (F *FF) set(m int) {
+	F.zero()
+	F.v[0].set(0,Chunk(m))
+}
+
+/* copy from FF b */
+func (F *FF) copy(b *FF) {
+	for i:=0;i<F.length;i++ {
+		F.v[i].copy(b.v[i])
+	}
+}
+
+/* x=y<<n */
+func (F *FF) dsucopy(b *FF) {
+	for i:=0;i<b.length;i++ {
+		F.v[b.length+i].copy(b.v[i])
+		F.v[i].zero()
+	}
+}
+
+/* x=y */
+func (F *FF) dscopy(b *FF) {
+	for i:=0;i<b.length;i++ {
+		F.v[i].copy(b.v[i])
+		F.v[b.length+i].zero()
+	}
+}
+
+/* x=y>>n */
+func (F *FF) sducopy(b *FF) {
+	for i:=0;i<F.length;i++ {
+		F.v[i].copy(b.v[F.length+i])
+	}
+}
+
+func (F *FF) one() {
+	F.v[0].one();
+	for i:=1;i<F.length;i++ {
+		F.v[i].zero()
+	}
+}
+
+/* test equals 0 */
+func (F *FF) iszilch() bool {
+	for i:=0;i<F.length;i++ {
+		if !F.v[i].iszilch() {return false}
+	}
+	return true
+}
+
+/* shift right by BIGBITS-bit words */
+func (F *FF) shrw(n int) {
+	for i:=0;i<n;i++ {
+		F.v[i].copy(F.v[i+n])
+		F.v[i+n].zero()
+	}
+}
+
+/* shift left by BIGBITS-bit words */
+func (F *FF) shlw(n int) {
+	for i:=0;i<n;i++ {
+		F.v[n+i].copy(F.v[i])
+		F.v[i].zero()
+	}
+}
+
+/* extract last bit */
+func (F *FF) parity() int {
+	return F.v[0].parity()
+}
+
+func (F *FF) lastbits(m int) int {
+	return F.v[0].lastbits(m)
+}
+
+/* compare x and y - must be normalised, and of same length */
+func ff_comp(a *FF,b *FF) int {
+	for i:=a.length-1;i>=0;i-- {
+		j:=Comp(a.v[i],b.v[i])
+		if j!=0 {return j}
+	}
+	return 0
+}
+
+/* recursive add */
+func (F *FF) radd(vp int,x *FF,xp int,y *FF,yp int,n int) {
+	for i:=0;i<n;i++ {
+		F.v[vp+i].copy(x.v[xp+i])
+		F.v[vp+i].add(y.v[yp+i])
+	}
+}
+
+/* recursive inc */
+func (F *FF) rinc(vp int,y *FF,yp int,n int) {
+	for i:=0;i<n;i++ {
+		F.v[vp+i].add(y.v[yp+i])
+	}
+}
+
+/* recursive sub */
+func (F *FF) rsub(vp int,x *FF,xp int,y *FF,yp int,n int) {
+	for i:=0;i<n;i++ {
+		F.v[vp+i].copy(x.v[xp+i])
+		F.v[vp+i].sub(y.v[yp+i])
+	}
+}
+
+/* recursive dec */
+func (F *FF) rdec(vp int,y *FF,yp int,n int) {
+	for i:=0;i<n;i++ {
+		F.v[vp+i].sub(y.v[yp+i])
+	}
+}
+
+/* simple add */
+func (F *FF) add(b *FF) {
+	for i:=0;i<F.length;i++ {
+		F.v[i].add(b.v[i])
+	}
+}
+
+/* simple sub */
+func (F *FF) sub(b *FF) {
+	for i:=0;i<F.length;i++ {
+		F.v[i].sub(b.v[i])
+	}
+}
+	
+/* reverse sub */
+func (F *FF) revsub(b *FF) {
+	for i:=0;i<F.length;i++ {
+		F.v[i].rsub(b.v[i])
+	}
+}
+
+/* normalise - but hold any overflow in top part unless n<0 */
+func (F *FF) rnorm(vp int,n int) {
+	trunc:=false
+	var carry Chunk
+	if n<0 { /* -v n signals to do truncation */
+		n=-n
+		trunc=true
+	}
+	for i:=0;i<n-1;i++ {
+		carry=F.v[vp+i].norm()
+		F.v[vp+i].xortop(carry<<P_TBITS)
+		F.v[vp+i+1].w[0]+=carry; // inc(carry)
+	}
+	carry=F.v[vp+n-1].norm()
+	if trunc {
+		F.v[vp+n-1].xortop(carry<<P_TBITS)
+	}
+}
+
+func (F *FF) norm() {
+	F.rnorm(0,F.length)
+}
+
+/* increment/decrement by a small integer */
+func (F *FF) inc(m int) {
+	F.v[0].inc(m)
+	F.norm()
+}
+
+func (F *FF) dec(m int) {
+	F.v[0].dec(m)
+	F.norm()
+}
+
+/* shift left by one bit */
+func (F *FF) shl() {
+	var delay_carry int=0
+	for i:=0;i<F.length-1;i++ {
+		carry:=F.v[i].fshl(1)
+		F.v[i].inc(delay_carry)
+		F.v[i].xortop(Chunk(carry)<<P_TBITS)
+		delay_carry=int(carry)
+	}
+	F.v[F.length-1].fshl(1)
+	F.v[F.length-1].inc(delay_carry)
+}
+
+/* shift right by one bit */
+
+func (F *FF) shr() {
+	for i:=F.length-1;i>0;i-- {
+		carry:=F.v[i].fshr(1)
+		F.v[i-1].xortop(Chunk(carry)<<P_TBITS)
+	}
+	F.v[0].fshr(1)
+}
+
+/* Convert to Hex String */
+func (F *FF) toString() string {
+	F.norm()
+	s:=""
+	for i:=F.length-1;i>=0;i-- {
+		s+=F.v[i].ToString()
+	}
+	return s
+}
+
+/* Convert FFs to/from byte arrays */
+func (F *FF) toBytes(b []byte) {
+	for i:=0;i<F.length;i++ {
+		F.v[i].tobytearray(b,(F.length-i-1)*int(MODBYTES))
+	}
+}
+
+func ff_fromBytes(x *FF,b []byte) {
+	for i:=0;i<x.length;i++ {
+		x.v[i]=frombytearray(b,(x.length-i-1)*int(MODBYTES))
+	}
+}
+
+/* in-place swapping using xor - side channel resistant - lengths must be the same */
+func ff_cswap(a *FF,b *FF,d int) {
+	for i:=0;i<a.length;i++ {
+		a.v[i].cswap(b.v[i],d)
+	}
+}
+
+/* z=x*y, t is workspace */
+func (F *FF) karmul(vp int,x *FF,xp int,y *FF,yp int,t *FF,tp int,n int) {
+	if n==1 {
+		x.v[xp].norm()
+		y.v[yp].norm()
+		d:=mul(x.v[xp],y.v[yp])
+		F.v[vp+1]=d.split(8*MODBYTES)
+		F.v[vp].dcopy(d)
+		return
+	}
+	nd2:=n/2
+	F.radd(vp,x,xp,x,xp+nd2,nd2)
+		F.rnorm(vp,nd2)
+	F.radd(vp+nd2,y,yp,y,yp+nd2,nd2)
+		F.rnorm(vp+nd2,nd2)
+	t.karmul(tp,F,vp,F,vp+nd2,t,tp+n,nd2)
+	F.karmul(vp,x,xp,y,yp,t,tp+n,nd2)
+	F.karmul(vp+n,x,xp+nd2,y,yp+nd2,t,tp+n,nd2)
+	t.rdec(tp,F,vp,n)
+	t.rdec(tp,F,vp+n,n)
+	F.rinc(vp+nd2,t,tp,n)
+	F.rnorm(vp,2*n)
+}
+
+func (F *FF) karsqr(vp int,x *FF,xp int,t *FF,tp int,n int) {
+	if n==1 {
+		x.v[xp].norm()
+		d:=sqr(x.v[xp])
+		F.v[vp+1].copy(d.split(8*MODBYTES))
+		F.v[vp].dcopy(d)
+		return
+	}	
+
+	nd2:=n/2
+	F.karsqr(vp,x,xp,t,tp+n,nd2)
+	F.karsqr(vp+n,x,xp+nd2,t,tp+n,nd2)
+	t.karmul(tp,x,xp,x,xp+nd2,t,tp+n,nd2)
+	F.rinc(vp+nd2,t,tp,n)
+	F.rinc(vp+nd2,t,tp,n)
+	F.rnorm(vp+nd2,n)
+}
+
+/* Calculates Least Significant bottom half of x*y */
+func (F *FF) karmul_lower(vp int,x *FF,xp int,y *FF,yp int,t *FF,tp int,n int) { 
+	if n==1 { /* only calculate bottom half of product */
+		F.v[vp].copy(smul(x.v[xp],y.v[yp]))
+		return
+	}
+	nd2:=n/2
+
+	F.karmul(vp,x,xp,y,yp,t,tp+n,nd2)
+	t.karmul_lower(tp,x,xp+nd2,y,yp,t,tp+n,nd2)
+	F.rinc(vp+nd2,t,tp,nd2)
+	t.karmul_lower(tp,x,xp,y,yp+nd2,t,tp+n,nd2)
+	F.rinc(vp+nd2,t,tp,nd2)
+	F.rnorm(vp+nd2,-nd2)  /* truncate it */
+}
+
+/* Calculates Most Significant upper half of x*y, given lower part */
+func (F *FF) karmul_upper(x *FF,y *FF,t *FF,n int) { 
+	nd2:=n/2
+	F.radd(n,x,0,x,nd2,nd2)
+	F.radd(n+nd2,y,0,y,nd2,nd2)
+	F.rnorm(n,nd2)
+	F.rnorm(n+nd2,nd2)
+
+	t.karmul(0,F,n+nd2,F,n,t,n,nd2)  /* t = (a0+a1)(b0+b1) */
+	F.karmul(n,x,nd2,y,nd2,t,n,nd2) /* z[n]= a1*b1 */
+
+					/* z[0-nd2]=l(a0b0) z[nd2-n]= h(a0b0)+l(t)-l(a0b0)-l(a1b1) */
+	t.rdec(0,F,n,n)              /* t=t-a1b1  */	
+						
+	F.rinc(nd2,F,0,nd2)  /* z[nd2-n]+=l(a0b0) = h(a0b0)+l(t)-l(a1b1)  */
+	F.rdec(nd2,t,0,nd2)   /* z[nd2-n]=h(a0b0)+l(t)-l(a1b1)-l(t-a1b1)=h(a0b0) */
+
+	F.rnorm(0,-n)		/* a0b0 now in z - truncate it */
+
+	t.rdec(0,F,0,n)         /* (a0+a1)(b0+b1) - a0b0 */
+	F.rinc(nd2,t,0,n)
+
+	F.rnorm(nd2,n)
+}
+
+/* z=x*y. Assumes x and y are of same length. */
+func ff_mul(x *FF,y *FF) *FF {
+	n:=x.length
+	z:=NewFFint(2*n)
+	t:=NewFFint(2*n)
+	z.karmul(0,x,0,y,0,t,0,n)
+	return z
+}
+
+/* return low part of product this*y */
+func (F *FF) lmul(y *FF) {
+	n:=F.length
+	t:=NewFFint(2*n)
+	x:=NewFFint(n); x.copy(F)
+	F.karmul_lower(0,x,0,y,0,t,0,n)
+}
+
+/* Set b=b mod c */
+func (F *FF) mod(c *FF) {
+	var k int=1  
+
+	F.norm()
+	if ff_comp(F,c)<0 {return}
+
+	c.shl()
+	for ff_comp(F,c)>=0 {
+		c.shl()
+		k++
+	}
+
+	for k>0 {
+		c.shr()
+		if ff_comp(F,c)>=0 {
+			F.sub(c)
+			F.norm()
+		}
+		k--
+	}
+}
+
+/* z=x^2 */
+func ff_sqr(x *FF) *FF {
+	n:=x.length
+	z:=NewFFint(2*n)
+	t:=NewFFint(2*n)
+	z.karsqr(0,x,0,t,0,n)
+	return z
+}
+
+/* return This mod modulus, N is modulus, ND is Montgomery Constant */
+func (F *FF) reduce(N *FF,ND *FF) *FF { /* fast karatsuba Montgomery reduction */
+	n:=N.length
+	t:=NewFFint(2*n)
+	r:=NewFFint(n)
+	m:=NewFFint(n)
+
+	r.sducopy(F)
+	m.karmul_lower(0,F,0,ND,0,t,0,n)
+
+	F.karmul_upper(N,m,t,n)
+	
+	m.sducopy(F)
+	r.add(N)
+	r.sub(m)
+	r.norm()
+
+	return r
+
+}
+
+/* Set r=this mod b */
+/* this is of length - 2*n */
+/* r,b is of length - n */
+func (F *FF) dmod(b *FF) *FF {
+	n:=b.length
+	m:=NewFFint(2*n)
+	x:=NewFFint(2*n)
+	r:=NewFFint(n)
+
+	x.copy(F)
+	x.norm()
+	m.dsucopy(b); k:=BIGBITS*n
+
+	for ff_comp(x,m)>=0 {
+		x.sub(m)
+		x.norm()
+	}
+
+	for k>0 {	
+		m.shr()
+
+		if ff_comp(x,m)>=0 {
+			x.sub(m)
+			x.norm()
+		}
+		k--
+	}
+
+	r.copy(x)
+	r.mod(b)
+	return r
+}
+
+/* Set return=1/this mod p. Binary method - a<p on entry */
+
+func (F *FF) invmodp(p *FF) {
+	n:=p.length
+
+	u:=NewFFint(n)
+	v:=NewFFint(n)
+	x1:=NewFFint(n)
+	x2:=NewFFint(n)
+	t:=NewFFint(n)
+	one:=NewFFint(n)
+
+	one.one()
+	u.copy(F)
+	v.copy(p)
+	x1.copy(one)
+	x2.zero()
+
+	// reduce n in here as well! 
+	for (ff_comp(u,one)!=0 && ff_comp(v,one)!=0) {
+		for u.parity()==0 {
+			u.shr()
+			if x1.parity()!=0 {
+				x1.add(p)
+				x1.norm()
+			}
+			x1.shr()
+		}
+		for v.parity()==0 {
+			v.shr() 
+			if x2.parity()!=0 {
+				x2.add(p)
+				x2.norm()
+			}
+			x2.shr()
+		}
+		if ff_comp(u,v)>=0 {
+			u.sub(v)
+			u.norm()
+			if ff_comp(x1,x2)>=0 {
+				x1.sub(x2)
+			} else {
+				t.copy(p)
+				t.sub(x2)
+				x1.add(t)
+			}
+			x1.norm()
+		} else {
+			v.sub(u)
+			v.norm()
+			if ff_comp(x2,x1)>=0 { 
+				x2.sub(x1)
+			} else {
+				t.copy(p)
+				t.sub(x1)
+				x2.add(t)
+			}
+			x2.norm()
+		}
+	}
+	if ff_comp(u,one)==0 {
+		F.copy(x1)
+	} else {
+		F.copy(x2)
+	}
+}
+
+/* nresidue mod m */
+func (F *FF) nres(m *FF) {
+	n:=m.length
+	if n==1 {
+		d:=NewDBIGscopy(F.v[0])
+		d.shl(uint(NLEN)*BASEBITS)
+		F.v[0].copy(d.mod(m.v[0]))
+	} else {
+		d:=NewFFint(2*n)
+		d.dsucopy(F)
+		F.copy(d.dmod(m))
+	}
+}
+
+func (F *FF) redc(m *FF,ND *FF) {
+	n:=m.length
+	if n==1 {
+		d:=NewDBIGscopy(F.v[0])
+		F.v[0].copy(monty(m.v[0],(Chunk(1)<<BASEBITS)-ND.v[0].w[0],d))
+	} else {
+		d:=NewFFint(2*n)
+		F.mod(m)
+		d.dscopy(F)
+		F.copy(d.reduce(m,ND))
+		F.mod(m)
+	}
+}
+
+func (F *FF) mod2m(m int) {
+	for i:=m;i<F.length;i++ {
+		F.v[i].zero()
+	}
+}
+
+/* U=1/a mod 2^m - Arazi & Qi */
+func (F *FF) invmod2m() *FF {
+	n:=F.length
+
+	b:=NewFFint(n)
+	c:=NewFFint(n)
+	U:=NewFFint(n)
+
+	U.zero()
+	U.v[0].copy(F.v[0])
+	U.v[0].invmod2m()
+
+	for i:=1;i<n;i<<=1 {
+		b.copy(F); b.mod2m(i)
+		t:=ff_mul(U,b); t.shrw(i); b.copy(t)
+		c.copy(F); c.shrw(i); c.mod2m(i)
+		c.lmul(U); c.mod2m(i)
+
+		b.add(c); b.norm()
+		b.lmul(U); b.mod2m(i)
+
+		c.one(); c.shlw(i); b.revsub(c); b.norm()
+		b.shlw(i)
+		U.add(b)
+	}
+	U.norm()
+	return U
+}
+
+func (F *FF) random(rng *amcl.RAND) {
+	n:=F.length
+	for i:=0;i<n;i++ {
+		F.v[i].copy(random(rng))
+	}
+	/* make sure top bit is 1 */
+	for (F.v[n-1].nbits()<int(MODBYTES*8)) {
+		F.v[n-1].copy(random(rng))
+	}
+}
+
+/* generate random x less than p */
+func (F *FF) randomnum(p *FF,rng *amcl.RAND) {
+	n:=F.length
+	d:=NewFFint(2*n)
+
+	for i:=0;i<2*n;i++ {
+		d.v[i].copy(random(rng))
+	}
+	F.copy(d.dmod(p))
+}
+
+/* this*=y mod p */
+func (F *FF) modmul(y *FF,p *FF,nd *FF) {
+	if ff_pexceed(F.v[F.length-1],y.v[y.length-1]) {F.mod(p)}
+	n:=p.length
+	if n==1 {
+		d:=mul(F.v[0],y.v[0])
+		F.v[0].copy(monty(p.v[0],(Chunk(1)<<BASEBITS)-nd.v[0].w[0],d))
+	} else {
+		d:=ff_mul(F,y)
+		F.copy(d.reduce(p,nd))
+	}
+}
+
+/* this*=y mod p */
+func (F *FF) modsqr(p *FF,nd *FF) {
+	if ff_sexceed(F.v[F.length-1]) {F.mod(p)}
+	n:=p.length
+	if n==1 {
+		d:=sqr(F.v[0])
+		F.v[0].copy(monty(p.v[0],(Chunk(1)<<BASEBITS)-nd.v[0].w[0],d))
+	} else {
+		d:=ff_sqr(F)
+		F.copy(d.reduce(p,nd))
+	}
+}
+
+/* this=this^e mod p using side-channel resistant Montgomery Ladder, for large e */
+func (F *FF) skpow(e *FF,p *FF) {
+	n:=p.length
+	R0:=NewFFint(n)
+	R1:=NewFFint(n)
+	ND:=p.invmod2m()
+
+	F.mod(p)
+	R0.one()
+	R1.copy(F)
+	R0.nres(p)
+	R1.nres(p)
+
+	for i:=int(8*MODBYTES)*n-1;i>=0;i-- {
+		b:=int(e.v[i/BIGBITS].bit(i%BIGBITS))
+		F.copy(R0)
+		F.modmul(R1,p,ND)
+
+		ff_cswap(R0,R1,b)
+		R0.modsqr(p,ND)
+
+		R1.copy(F)
+		ff_cswap(R0,R1,b)
+	}
+	F.copy(R0)
+	F.redc(p,ND)
+}
+
+/* this =this^e mod p using side-channel resistant Montgomery Ladder, for short e */
+func (F *FF) skpows(e *BIG,p *FF) {
+	n:=p.length
+	R0:=NewFFint(n)
+	R1:=NewFFint(n)
+	ND:=p.invmod2m()
+
+	F.mod(p)
+	R0.one()
+	R1.copy(F)
+	R0.nres(p)
+	R1.nres(p)
+
+	for i:=int(8*MODBYTES)-1;i>=0;i-- {
+		b:=int(e.bit(i))
+		F.copy(R0)
+		F.modmul(R1,p,ND)
+
+		ff_cswap(R0,R1,b)
+		R0.modsqr(p,ND)
+
+		R1.copy(F)
+		ff_cswap(R0,R1,b)
+	}
+	F.copy(R0)
+	F.redc(p,ND)
+}
+
+/* raise to an integer power - right-to-left method */
+func (F *FF) power(e int,p *FF) {
+	n:=p.length
+	w:=NewFFint(n)
+	ND:=p.invmod2m()
+	f:=true
+
+	w.copy(F)
+	w.nres(p)
+//i:=0;
+	if e==2 {
+		F.copy(w)
+		F.modsqr(p,ND)
+	} else {
+		for (true) {
+			if e%2==1 {
+				if f {
+					F.copy(w)
+				} else {F.modmul(w,p,ND)}
+				f=false
+
+			}
+			e>>=1
+			if e==0 {break}
+//fmt.Printf("wb= "+w.toString()+"\n");
+//debug=true;
+			w.modsqr(p,ND)
+//debug=false;
+//fmt.Printf("wa= "+w.toString()+"\n");
+//i+=1;
+//os.Exit(0);
+		}
+	}
+
+	F.redc(p,ND)
+
+}
+
+/* this=this^e mod p, faster but not side channel resistant */
+func (F *FF) pow(e *FF,p *FF) {
+	n:=p.length
+	w:=NewFFint(n)
+	ND:=p.invmod2m()
+//fmt.Printf("ND= "+ND.toString() +"\n");
+	w.copy(F)
+	F.one()
+	F.nres(p)
+	w.nres(p)
+	for i:=int(8*MODBYTES)*n-1;i>=0;i-- {
+		F.modsqr(p,ND)
+		b:=e.v[i/BIGBITS].bit(i%BIGBITS)
+		if b==1 {F.modmul(w,p,ND)}
+	}
+	F.redc(p,ND)
+}
+
+/* double exponentiation r=x^e.y^f mod p */
+func (F *FF) pow2(e *BIG,y *FF,f *BIG,p *FF) {
+	n:=p.length
+	xn:=NewFFint(n)
+	yn:=NewFFint(n)
+	xy:=NewFFint(n)
+	ND:=p.invmod2m()
+
+	xn.copy(F)
+	yn.copy(y)
+	xn.nres(p)
+	yn.nres(p)
+	xy.copy(xn); xy.modmul(yn,p,ND)
+	F.one()
+	F.nres(p)
+
+	for i:=int(8*MODBYTES)-1;i>=0;i-- {
+		eb:=e.bit(i)
+		fb:=f.bit(i)
+		F.modsqr(p,ND)
+		if eb==1 {
+			if fb==1 {
+				F.modmul(xy,p,ND)
+			} else {F.modmul(xn,p,ND)}
+		} else	{
+			if fb==1 {F.modmul(yn,p,ND)}
+		}
+	}
+	F.redc(p,ND)
+}
+
+func igcd(x int,y int) int { /* integer GCD, returns GCD of x and y */
+	var r int
+	if y==0 {return x}
+	for true {
+		r=x%y
+		if r==0 {break}
+		x=y;y=r
+	}
+	return y
+}
+
+/* quick and dirty check for common factor with n */
+func (F *FF) cfactor(s int) bool {
+	n:=F.length
+
+	x:=NewFFint(n)
+	y:=NewFFint(n)
+
+	y.set(s)
+	x.copy(F)
+	x.norm()
+
+	x.sub(y)
+	x.norm()
+
+	for (!x.iszilch() && x.parity()==0) {x.shr()}
+
+	for (ff_comp(x,y)>0) {
+		x.sub(y)
+		x.norm()
+		for (!x.iszilch() && x.parity()==0) {x.shr()}
+	}
+
+	g:=int(x.v[0].get(0))
+	r:=igcd(s,g)
+	if r>1 {return true}
+	return false
+}
+
+/* Miller-Rabin test for primality. Slow. */
+func prime(p *FF,rng *amcl.RAND) bool {
+	s:=0
+	n:=p.length
+	d:=NewFFint(n)
+	x:=NewFFint(n)
+	unity:=NewFFint(n)
+	nm1:=NewFFint(n)
+
+	sf:=4849845 /* 3*5*.. *19 */
+	p.norm()
+
+	if p.cfactor(sf) {return false}
+	unity.one()
+	nm1.copy(p)
+	nm1.sub(unity)
+	nm1.norm()
+	d.copy(nm1)
+
+	for d.parity()==0 {
+		d.shr()
+		s++
+	}
+	if s==0 {return false}
+
+	for i:=0;i<10;i++ {
+		x.randomnum(p,rng)
+		x.pow(d,p)
+
+		if (ff_comp(x,unity)==0 || ff_comp(x,nm1)==0) {continue}
+		loop:=false
+		for j:=1;j<s;j++ {
+			x.power(2,p)
+			if ff_comp(x,unity)==0 {return false}
+			if ff_comp(x,nm1)==0 {loop=true; break}
+		}
+		if loop {continue}
+		return false
+	}
+
+	return true
+}
+/*
+func main() {
+
+	var P = [4][5]int64 {{0xAD19A781670957,0x76A79C00965796,0xDEFCC5FC9A9717,0xF02F2940E20E9,0xBF59E34F},{0x6894F31844C908,0x8DADA70E82C79F,0xFD29F3836046F6,0x8C1D874D314DD0,0x46D077B},{0x3C515217813331,0x56680FD1CE935B,0xE55C53EEA8838E,0x92C2F7E14A4A95,0xD945E5B1},{0xACF673E919F5EF,0x6723E7E7DAB446,0x6B6FA69B36EB1B,0xF7D13920ECA300,0xB5FC2165}}
+
+	fmt.Printf("Testing FF\n")
+	var raw [100]byte
+	rng:=NewRAND()
+
+	rng.Clean()
+	for i:=0;i<100;i++ {
+		raw[i]=byte(i)
+	}
+
+	rng.Seed(100,raw[:])
+
+	n:=4
+
+	x:=NewFFint(n)
+	x.set(3)
+
+	p:=NewFFints(P[:],n)
+
+	if prime(p,rng) {fmt.Printf("p is a prime\n"); fmt.Printf("\n")}
+
+	e:=NewFFint(n)
+	e.copy(p)
+	e.dec(1); e.norm()
+
+	fmt.Printf("e= "+e.toString())
+	fmt.Printf("\n")
+	x.skpow(e,p)
+	fmt.Printf("x= "+x.toString())
+	fmt.Printf("\n")
+}
+*/
\ No newline at end of file
diff --git a/version3/go/FP.go b/version3/go/FP.go
new file mode 100644
index 0000000..5d77247
--- /dev/null
+++ b/version3/go/FP.go
@@ -0,0 +1,556 @@
+/*
+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.
+*/
+
+/* Finite Field arithmetic */
+/* CLINT mod p functions */
+
+package XXX
+
+//import "fmt"
+
+const NOT_SPECIAL int=0
+const PSEUDO_MERSENNE int=1
+const MONTGOMERY_FRIENDLY int=2
+const GENERALISED_MERSENNE int=3
+
+const MODBITS uint=@NBT@ /* Number of bits in Modulus */
+const MOD8 uint=@M8@  /* Modulus mod 8 */
+const MODTYPE int=@MT@ //NOT_SPECIAL
+
+const FEXCESS int32=((int32(1)<<@SH@)-1)
+const OMASK Chunk= ((Chunk(-1))<<(MODBITS%BASEBITS))
+const TBITS uint=MODBITS%BASEBITS // Number of active bits in top word 
+const TMASK Chunk=(Chunk(1)<<TBITS)-1
+
+
+type FP struct {
+	x *BIG
+	XES int32
+}
+
+/* Constructors */
+func NewFPint(a int) *FP {
+	F:=new(FP)
+	F.x=NewBIGint(a)
+	F.nres()
+	return F
+}
+
+func NewFPbig(a *BIG) *FP {
+	F:=new(FP)
+	F.x=NewBIGcopy(a)
+	F.nres()
+	return F
+}
+
+func NewFPcopy(a *FP) *FP {
+	F:=new(FP)
+	F.x=NewBIGcopy(a.x)
+	F.XES=a.XES
+	return F
+}
+
+func (F *FP) toString() string {
+	F.reduce()
+	return F.redc().ToString()
+}
+
+/* convert to Montgomery n-residue form */
+func (F *FP) nres() {
+	if MODTYPE!=PSEUDO_MERSENNE && MODTYPE!=GENERALISED_MERSENNE {
+		r:=NewBIGints(R2modp)
+		d:=mul(F.x,r)
+		F.x.copy(mod(d))
+		F.XES=2
+	} else {
+		F.XES=1
+	}
+}
+
+/* convert back to regular form */
+func (F *FP) redc() *BIG {
+	if MODTYPE!=PSEUDO_MERSENNE && MODTYPE!=GENERALISED_MERSENNE {
+		d:=NewDBIGscopy(F.x)
+		return mod(d)
+	} else {
+		r:=NewBIGcopy(F.x)
+		return r
+	}
+}
+
+/* reduce a DBIG to a BIG using the appropriate form of the modulus */
+
+func mod(d *DBIG) *BIG {
+	if MODTYPE==PSEUDO_MERSENNE {
+		t:=d.split(MODBITS)
+		b:=NewBIGdcopy(d)
+
+		v:=t.pmul(int(MConst))
+
+		t.add(b)
+		t.norm()
+
+		tw:=t.w[NLEN-1]
+		t.w[NLEN-1]&=TMASK
+		t.w[0]+=(MConst*((tw>>TBITS)+(v<<(BASEBITS-TBITS))))
+
+		t.norm()
+		return t
+	//	b.add(t)
+	//	b.norm()
+	//	return b		
+	}
+	if MODTYPE==MONTGOMERY_FRIENDLY {
+		for i:=0;i<NLEN;i++ {
+			top,bot:=muladd(d.w[i],MConst-1,d.w[i],d.w[NLEN+i-1])
+			d.w[NLEN+i-1]=bot
+			d.w[NLEN+i]+=top
+		}
+		b:=NewBIG()
+
+		for i:=0;i<NLEN;i++ {
+			b.w[i]=d.w[NLEN+i]
+		}
+		b.norm()
+		return b		
+	}
+
+	if MODTYPE==GENERALISED_MERSENNE { // GoldiLocks only
+		t:=d.split(MODBITS)
+		b:=NewBIGdcopy(d)
+		b.add(t);
+		dd:=NewDBIGscopy(t)
+		dd.shl(MODBITS/2)
+
+		tt:=dd.split(MODBITS)
+		lo:=NewBIGdcopy(dd)
+		b.add(tt)
+		b.add(lo)
+		b.norm()
+		tt.shl(MODBITS/2)
+		b.add(tt)
+
+		carry:=b.w[NLEN-1]>>TBITS
+		b.w[NLEN-1]&=TMASK
+		b.w[0]+=carry
+			
+		b.w[224/BASEBITS]+=carry<<(224%BASEBITS);
+		b.norm()
+		return b		
+	}
+
+	if MODTYPE==NOT_SPECIAL {
+		md:=NewBIGints(Modulus)
+		return monty(md,MConst,d) 
+	}
+	return NewBIG()
+}
+
+// find appoximation to quotient of a/m
+// Out by at most 2.
+// Note that MAXXES is bounded to be 2-bits less than half a word
+func quo(n *BIG,m *BIG) int {
+	var num  Chunk
+	var den  Chunk
+	hb:=uint(CHUNK)/2
+	if TBITS < hb {
+		sh:=hb-TBITS
+		num=((n.w[NLEN-1]<<sh))|(n.w[NLEN-2]>>(BASEBITS-sh))
+		den=((m.w[NLEN-1]<<sh))|(m.w[NLEN-2]>>(BASEBITS-sh))
+
+	} else {
+		num=n.w[NLEN-1]
+		den=m.w[NLEN-1]
+	}
+	return int(num/(den+1))
+}
+
+/* reduce this mod Modulus */
+func (F *FP) reduce() {
+	m:=NewBIGints(Modulus)
+	r:=NewBIGints(Modulus)
+	var sb uint
+	F.x.norm()
+
+	if F.XES > 16 {
+		q:=quo(F.x,m)
+		carry:=r.pmul(q)
+		r.w[NLEN-1]+=carry<<BASEBITS
+		F.x.sub(r)
+		F.x.norm()
+		sb=2
+	} else { 
+		sb=logb2(uint32(F.XES-1))
+	}
+
+	m.fshl(sb)
+	for sb>0 {
+            sr:=ssn(r,F.x,m)
+	    F.x.cmove(r,1-sr)
+            sb -= 1
+	}
+
+	F.XES=1
+}
+
+/* test this=0? */
+func (F *FP) iszilch() bool {
+	W:=NewFPcopy(F)
+	W.reduce()
+	return W.x.iszilch()
+}
+
+/* copy from FP b */
+func (F *FP) copy(b *FP ) {
+	F.x.copy(b.x)
+	F.XES=b.XES
+}
+
+/* set this=0 */
+func (F *FP) zero() {
+	F.x.zero()
+	F.XES=1
+}
+	
+/* set this=1 */
+func (F *FP) one() {
+	F.x.one(); F.nres()
+}
+
+/* normalise this */
+func (F *FP) norm() {
+	F.x.norm()
+}
+
+/* swap FPs depending on d */
+func (F *FP) cswap(b *FP,d int) {
+	c:=int32(d)
+	c=^(c-1)
+	t:=c&(F.XES^b.XES)
+	F.XES^=t
+	b.XES^=t
+	F.x.cswap(b.x,d)
+}
+
+/* copy FPs depending on d */
+func (F *FP) cmove(b *FP,d int) {
+	F.x.cmove(b.x,d)
+	c:=int32(-d)
+	F.XES^=(F.XES^b.XES)&c
+}
+
+/* this*=b mod Modulus */
+func (F *FP) mul(b *FP) {
+
+	if int64(F.XES)*int64(b.XES)>int64(FEXCESS) {F.reduce()}
+
+	d:=mul(F.x,b.x)
+	F.x.copy(mod(d))
+	F.XES=2
+}
+
+/* this = -this mod Modulus */
+func (F *FP) neg() {
+	m:=NewBIGints(Modulus)
+	sb:=logb2(uint32(F.XES-1))
+
+	m.fshl(sb)
+	F.x.rsub(m)		
+
+	F.XES=(1<<sb)+1
+	if F.XES>FEXCESS {F.reduce()}
+}
+
+
+/* this*=c mod Modulus, where c is a small int */
+func (F *FP) imul(c int) {
+//	F.norm()
+	s:=false
+	if (c<0) {
+		c=-c
+		s=true
+	}
+
+	if MODTYPE==PSEUDO_MERSENNE || MODTYPE==GENERALISED_MERSENNE {
+		d:=F.x.pxmul(c)
+		F.x.copy(mod(d))
+		F.XES=2
+	} else {
+		if F.XES*int32(c)<=FEXCESS {
+			F.x.pmul(c)
+			F.XES*=int32(c)
+		} else {
+			n:=NewFPint(c)
+			F.mul(n)
+		}
+	}
+	if s {F.neg(); F.norm()}
+}
+
+/* this*=this mod Modulus */
+func (F *FP) sqr() {
+	if int64(F.XES)*int64(F.XES)>int64(FEXCESS) {F.reduce()}	
+	d:=sqr(F.x)	
+	F.x.copy(mod(d))
+	F.XES=2
+}
+
+/* this+=b */
+func (F *FP) add(b *FP) {
+	F.x.add(b.x)
+	F.XES+=b.XES
+	if (F.XES>FEXCESS) {F.reduce()}
+}
+
+/* this-=b */
+func (F *FP) sub(b *FP) {
+	n:=NewFPcopy(b)
+	n.neg()
+	F.add(n)
+}
+
+func (F *FP) rsub(b *FP) {
+	F.neg()
+	F.add(b)
+}
+
+/* this/=2 mod Modulus */
+func (F *FP) div2() {
+//	F.x.norm()
+	if (F.x.parity()==0) {
+		F.x.fshr(1)
+	} else {
+		p:=NewBIGints(Modulus);
+		F.x.add(p)
+		F.x.norm()
+		F.x.fshr(1)
+	}
+}
+
+
+// return this^(p-3)/4 or this^(p-5)/8
+func (F *FP) fpow() *FP {
+	ac := [11]int{1, 2, 3, 6, 12, 15, 30, 60, 120, 240,255}
+	var xp []*FP
+// phase 1
+	xp=append(xp,NewFPcopy(F)); 
+	xp=append(xp,NewFPcopy(F)); xp[1].sqr()
+	xp=append(xp,NewFPcopy(xp[1])); xp[2].mul(F)
+	xp=append(xp,NewFPcopy(xp[2])); xp[3].sqr()
+	xp=append(xp,NewFPcopy(xp[3])); xp[4].sqr()
+	xp=append(xp,NewFPcopy(xp[4])); xp[5].mul(xp[2])
+	xp=append(xp,NewFPcopy(xp[5])); xp[6].sqr()
+	xp=append(xp,NewFPcopy(xp[6])); xp[7].sqr()
+	xp=append(xp,NewFPcopy(xp[7])); xp[8].sqr()
+	xp=append(xp,NewFPcopy(xp[8])); xp[9].sqr()
+	xp=append(xp,NewFPcopy(xp[9])); xp[10].mul(xp[5])
+	var n,c int
+		
+	if MOD8==5 {
+		n=int(MODBITS)-3
+		c=(int(MConst)+5)/8
+	} else {
+		n=int(MODBITS)-2
+		c=(int(MConst)+3)/4
+
+	}
+
+	bw:=0; w:=1; for w<c {w*=2; bw+=1}
+	k:=w-c
+
+	i:=10; key:=NewFPint(0)
+		
+	if k!=0 {
+		for ac[i]>k {i--}
+		key.copy(xp[i])
+		k-=ac[i]
+	}
+
+	for k!=0 {
+		i--
+		if ac[i]>k {continue}
+		key.mul(xp[i])
+		k-=ac[i] 
+	}
+// phase 2 
+	xp[1].copy(xp[2])
+	xp[2].copy(xp[5])
+	xp[3].copy(xp[10])
+
+	j:=3; m:=8
+	nw:=n-bw
+	t:=NewFPint(0)
+	for 2*m<nw {
+		t.copy(xp[j]); j++
+		for i=0;i<m;i++ {t.sqr()} 
+		xp[j].copy(xp[j-1])
+		xp[j].mul(t)
+		m*=2
+	}
+	lo:=nw-m
+	r:=NewFPcopy(xp[j])
+
+	for lo!=0 {
+		m/=2; j--
+		if lo<m {continue}
+		lo-=m
+		t.copy(r)
+		for i=0;i<m;i++ {t.sqr()}
+		r.copy(t)
+		r.mul(xp[j])
+	}
+// phase 3
+	for i=0;i<bw;i++ {r.sqr()}
+
+	if w-c != 0 {
+		r.mul(key)
+	}
+
+	return r
+}
+
+
+
+/* this=1/this mod Modulus */
+func (F *FP) inverse() {
+
+	if MODTYPE==PSEUDO_MERSENNE {
+		y:=F.fpow()
+		if MOD8==5 {
+			t:=NewFPcopy(F)
+			t.sqr()
+			F.mul(t)
+			y.sqr()
+		} 
+		y.sqr()
+		y.sqr()
+		F.mul(y)		
+	} else {
+		m2:=NewBIGints(Modulus)
+		m2.dec(2); m2.norm()
+		F.copy(F.pow(m2))
+	}
+
+}
+
+/* return TRUE if this==a */
+func (F *FP) Equals(a *FP) bool {
+	f:=NewFPcopy(F)
+	s:=NewFPcopy(a);
+
+	s.reduce()
+	f.reduce()
+	if (Comp(s.x,f.x)==0) {return true}
+	return false
+}
+
+/* return this^e mod Modulus */
+/*
+func (F *FP) pow(e *BIG) *FP {
+	r:=NewFPint(1)
+	e.norm()
+	F.norm()
+	m:=NewFPcopy(F)
+	for true {
+		bt:=e.parity()
+		e.fshr(1)
+		if bt==1 {r.mul(m)}
+		if e.iszilch() {break}
+		m.sqr()
+	}
+	r.reduce()
+	return r
+}
+*/
+
+
+func (F *FP) pow(e *BIG) *FP {
+	var tb []*FP
+	var w [1+(NLEN*int(BASEBITS)+3)/4]int8	
+	F.norm()
+	t:=NewBIGcopy(e)
+	t.norm()
+	nb:=1+(t.nbits()+3)/4
+
+	for i:=0;i<nb;i++ {
+		lsbs:=t.lastbits(4)
+		t.dec(lsbs)
+		t.norm()
+		w[i]=int8(lsbs)
+		t.fshr(4);
+	}
+	tb=append(tb,NewFPint(1))
+	tb=append(tb,NewFPcopy(F))
+	for i:=2;i<16;i++ {
+		tb=append(tb,NewFPcopy(tb[i-1]))
+		tb[i].mul(F);
+	}
+	r:=NewFPcopy(tb[w[nb-1]])
+	for i:=nb-2;i>=0;i-- {
+		r.sqr()
+		r.sqr()
+		r.sqr()
+		r.sqr()
+		r.mul(tb[w[i]])
+	}
+	r.reduce()
+	return r
+}
+
+
+/* return sqrt(this) mod Modulus */
+func (F *FP) sqrt() *FP {
+	F.reduce();
+	if MOD8==5 {
+		var v *FP
+		i:=NewFPcopy(F); i.x.shl(1)
+		if MODTYPE==PSEUDO_MERSENNE {
+			v=i.fpow()
+		} else {
+			b:=NewBIGints(Modulus);
+			b.dec(5); b.norm(); b.shr(3)
+			v=i.pow(b)
+		}
+
+		i.mul(v); i.mul(v)
+		i.x.dec(1)
+		r:=NewFPcopy(F)
+		r.mul(v); r.mul(i) 
+		r.reduce()
+		return r
+	} else {
+		var r *FP
+		if MODTYPE==PSEUDO_MERSENNE {
+			r=F.fpow()
+			r.mul(F)
+		} else {
+			b:=NewBIGints(Modulus);
+			b.inc(1); b.norm(); b.shr(2)
+			r=F.pow(b)
+		}
+		return r
+	}
+}
+
+/* return jacobi symbol (this/Modulus) */
+func (F *FP) jacobi() int {
+	w:=F.redc();
+	p:=NewBIGints(Modulus);
+	return w.Jacobi(p)
+}
diff --git a/version3/go/FP12.go b/version3/go/FP12.go
new file mode 100644
index 0000000..48d9c10
--- /dev/null
+++ b/version3/go/FP12.go
@@ -0,0 +1,765 @@
+/*
+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.
+*/
+
+/* MiotCL Fp^12 functions */
+/* FP12 elements are of the form a+i.b+i^2.c */
+
+package XXX
+
+//import "fmt"
+
+type FP12 struct {
+	a *FP4
+	b *FP4
+	c *FP4
+}
+
+/* Constructors */
+func NewFP12fp4(d *FP4) *FP12 {
+	F:=new(FP12)
+	F.a=NewFP4copy(d)
+	F.b=NewFP4int(0)
+	F.c=NewFP4int(0)
+	return F
+}
+
+func NewFP12int(d int) *FP12 {
+	F:=new(FP12)
+	F.a=NewFP4int(d)
+	F.b=NewFP4int(0)
+	F.c=NewFP4int(0)
+	return F
+}
+
+func NewFP12fp4s(d *FP4,e *FP4,f *FP4) *FP12 {
+	F:=new(FP12)
+	F.a=NewFP4copy(d)
+	F.b=NewFP4copy(e)
+	F.c=NewFP4copy(f)
+	return F
+}
+
+func NewFP12copy(x *FP12) *FP12 {
+	F:=new(FP12)
+	F.a=NewFP4copy(x.a)
+	F.b=NewFP4copy(x.b)
+	F.c=NewFP4copy(x.c)
+	return F
+}
+
+/* reduce all components of this mod Modulus */
+func (F *FP12) reduce() {
+	F.a.reduce()
+	F.b.reduce()
+	F.c.reduce()
+}
+/* normalise all components of this */
+func (F *FP12) norm() {
+	F.a.norm()
+	F.b.norm()
+	F.c.norm()
+}
+/* test x==0 ? */
+func (F *FP12) iszilch() bool {
+	//F.reduce()
+	return (F.a.iszilch() && F.b.iszilch() && F.c.iszilch())
+}
+
+/* Conditional move */
+func (F *FP12) cmove(g *FP12,d int) {
+	F.a.cmove(g.a,d)
+	F.b.cmove(g.b,d)
+	F.c.cmove(g.c,d)
+}
+
+/* Constant time select from pre-computed table */
+func (F *FP12) selector(g []*FP12,b int32) {
+
+	m:=b>>31
+	babs:=(b^m)-m
+
+	babs=(babs-1)/2
+
+	F.cmove(g[0],teq(babs,0))  // conditional move
+	F.cmove(g[1],teq(babs,1))
+	F.cmove(g[2],teq(babs,2))
+	F.cmove(g[3],teq(babs,3))
+	F.cmove(g[4],teq(babs,4))
+	F.cmove(g[5],teq(babs,5))
+	F.cmove(g[6],teq(babs,6))
+	F.cmove(g[7],teq(babs,7))
+ 
+ 	invF:=NewFP12copy(F) 
+	invF.conj()
+	F.cmove(invF,int(m&1))
+}
+
+/* test x==1 ? */
+func (F *FP12) Isunity() bool {
+	one:=NewFP4int(1)
+	return (F.a.Equals(one) && F.b.iszilch() && F.c.iszilch())
+}
+/* return 1 if x==y, else 0 */
+func (F *FP12) Equals(x *FP12) bool {
+	return (F.a.Equals(x.a) && F.b.Equals(x.b) && F.c.Equals(x.c))
+}
+
+/* extract a from this */
+func (F *FP12) geta() *FP4 {
+	return F.a
+}
+/* extract b */
+func (F *FP12) getb() *FP4 {
+	return F.b
+}
+/* extract c */
+func (F *FP12) getc() *FP4 {
+	return F.c
+}
+/* copy this=x */
+func (F *FP12) Copy(x *FP12) {
+	F.a.copy(x.a)
+	F.b.copy(x.b)
+	F.c.copy(x.c)
+}
+/* set this=1 */
+func (F *FP12) one() {
+	F.a.one()
+	F.b.zero()
+	F.c.zero()
+}
+/* this=conj(this) */
+func (F *FP12) conj() {
+	F.a.conj()
+	F.b.nconj()
+	F.c.conj()
+}
+
+/* Granger-Scott Unitary Squaring */
+func (F *FP12) usqr() {
+	A:=NewFP4copy(F.a)
+	B:=NewFP4copy(F.c)
+	C:=NewFP4copy(F.b)
+	D:=NewFP4int(0)
+
+	F.a.sqr()
+	D.copy(F.a); D.add(F.a)
+	F.a.add(D)
+
+	F.a.norm();
+	A.nconj()
+
+	A.add(A)
+	F.a.add(A)
+	B.sqr()
+	B.times_i()
+
+	D.copy(B); D.add(B)
+	B.add(D)
+	B.norm();
+
+	C.sqr()
+	D.copy(C); D.add(C)
+	C.add(D)
+	C.norm();
+
+	F.b.conj()
+	F.b.add(F.b)
+	F.c.nconj()
+
+	F.c.add(F.c)
+	F.b.add(B)
+	F.c.add(C)
+	F.reduce()
+
+}
+
+/* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
+func (F *FP12)  sqr() {
+	A:=NewFP4copy(F.a)
+	B:=NewFP4copy(F.b)
+	C:=NewFP4copy(F.c)
+	D:=NewFP4copy(F.a)
+
+	A.sqr()
+	B.mul(F.c)
+	B.add(B); B.norm()
+	C.sqr()
+	D.mul(F.b)
+	D.add(D)
+
+	F.c.add(F.a)
+	F.c.add(F.b); F.c.norm()
+	F.c.sqr()
+
+	F.a.copy(A)
+
+	A.add(B)
+	A.norm();
+	A.add(C)
+	A.add(D)
+	A.norm();
+
+	A.neg()
+	B.times_i();
+	C.times_i()
+
+	F.a.add(B)
+
+	F.b.copy(C); F.b.add(D)
+	F.c.add(A)
+	F.norm()
+}
+
+/* FP12 full multiplication this=this*y */
+func (F *FP12) Mul(y *FP12) {
+	z0:=NewFP4copy(F.a)
+	z1:=NewFP4int(0)
+	z2:=NewFP4copy(F.b)
+	z3:=NewFP4int(0)
+	t0:=NewFP4copy(F.a)
+	t1:=NewFP4copy(y.a)
+
+	z0.mul(y.a)
+	z2.mul(y.b)
+
+	t0.add(F.b); t0.norm()
+	t1.add(y.b); t1.norm() 
+
+	z1.copy(t0); z1.mul(t1)
+	t0.copy(F.b); t0.add(F.c); t0.norm()
+
+	t1.copy(y.b); t1.add(y.c); t1.norm()
+	z3.copy(t0); z3.mul(t1)
+
+	t0.copy(z0); t0.neg()
+	t1.copy(z2); t1.neg()
+
+	z1.add(t0)
+	//z1.norm();
+	F.b.copy(z1); F.b.add(t1)
+
+	z3.add(t1)
+	z2.add(t0)
+
+	t0.copy(F.a); t0.add(F.c); t0.norm()
+	t1.copy(y.a); t1.add(y.c); t1.norm()
+	t0.mul(t1)
+	z2.add(t0)
+
+	t0.copy(F.c); t0.mul(y.c)
+	t1.copy(t0); t1.neg()
+
+	F.c.copy(z2); F.c.add(t1)
+	z3.add(t1)
+	t0.times_i()
+	F.b.add(t0)
+	z3.norm()
+	z3.times_i()
+	F.a.copy(z0); F.a.add(z3)
+	F.norm()
+}
+
+/* Special case of multiplication arises from special form of ATE pairing line function */
+func (F *FP12) smul(y *FP12,twist int ) {
+	if twist==D_TYPE {
+		z0:=NewFP4copy(F.a)
+		z2:=NewFP4copy(F.b)
+		z3:=NewFP4copy(F.b)
+		t0:=NewFP4int(0)
+		t1:=NewFP4copy(y.a)
+		
+		z0.mul(y.a)
+		z2.pmul(y.b.real());
+		F.b.add(F.a)
+		t1.real().add(y.b.real())
+
+		t1.norm(); F.b.norm()
+		F.b.mul(t1)
+		z3.add(F.c); z3.norm()
+		z3.pmul(y.b.real())
+
+		t0.copy(z0); t0.neg()
+		t1.copy(z2); t1.neg()
+
+		F.b.add(t0)
+	//F.b.norm();
+
+		F.b.add(t1)
+		z3.add(t1); z3.norm()
+		z2.add(t0)
+
+		t0.copy(F.a); t0.add(F.c); t0.norm()
+		t0.mul(y.a)
+		F.c.copy(z2); F.c.add(t0)
+
+		z3.times_i()
+		F.a.copy(z0); F.a.add(z3)
+	}
+	if twist==M_TYPE {
+		z0:=NewFP4copy(F.a)
+		z1:=NewFP4int(0)
+		z2:=NewFP4int(0)
+		z3:=NewFP4int(0)
+		t0:=NewFP4copy(F.a)
+		t1:=NewFP4int(0)
+		
+		z0.mul(y.a)
+		t0.add(F.b)
+		t0.norm()
+
+		z1.copy(t0); z1.mul(y.a)
+		t0.copy(F.b); t0.add(F.c)
+		t0.norm()
+
+		z3.copy(t0) //z3.mul(y.c);
+		z3.pmul(y.c.getb())
+		z3.times_i()
+
+		t0.copy(z0); t0.neg()
+
+		z1.add(t0)
+		F.b.copy(z1) 
+		z2.copy(t0)
+
+		t0.copy(F.a); t0.add(F.c)
+		t1.copy(y.a); t1.add(y.c)
+
+		t0.norm()
+		t1.norm()
+	
+		t0.mul(t1)
+		z2.add(t0)
+
+		t0.copy(F.c)
+			
+		t0.pmul(y.c.getb())
+		t0.times_i()
+
+		t1.copy(t0); t1.neg()
+
+		F.c.copy(z2); F.c.add(t1)
+		z3.add(t1)
+		t0.times_i()
+		F.b.add(t0)
+		z3.norm()
+		z3.times_i()
+		F.a.copy(z0); F.a.add(z3)
+	}
+	F.norm()
+}
+
+/* this=1/this */
+func (F *FP12) Inverse() {
+	f0:=NewFP4copy(F.a)
+	f1:=NewFP4copy(F.b)
+	f2:=NewFP4copy(F.a)
+	f3:=NewFP4int(0)
+
+	F.norm()
+	f0.sqr()
+	f1.mul(F.c)
+	f1.times_i()
+	f0.sub(f1); f0.norm()
+
+	f1.copy(F.c); f1.sqr()
+	f1.times_i()
+	f2.mul(F.b)
+	f1.sub(f2); f1.norm()
+
+	f2.copy(F.b); f2.sqr()
+	f3.copy(F.a); f3.mul(F.c)
+	f2.sub(f3); f2.norm()
+
+	f3.copy(F.b); f3.mul(f2)
+	f3.times_i()
+	F.a.mul(f0)
+	f3.add(F.a)
+	F.c.mul(f1)
+	F.c.times_i()
+
+	f3.add(F.c); f3.norm()
+	f3.inverse()
+	F.a.copy(f0); F.a.mul(f3)
+	F.b.copy(f1); F.b.mul(f3)
+	F.c.copy(f2); F.c.mul(f3)
+}
+
+/* this=this^p using Frobenius */
+func (F *FP12) frob(f *FP2) {
+	f2:=NewFP2copy(f)
+	f3:=NewFP2copy(f)
+
+	f2.sqr()
+	f3.mul(f2)
+
+	F.a.frob(f3);
+	F.b.frob(f3);
+	F.c.frob(f3);
+
+	F.b.pmul(f);
+	F.c.pmul(f2);
+}
+
+/* trace function */
+func (F *FP12) trace() *FP4 {
+	t:=NewFP4int(0)
+	t.copy(F.a)
+	t.imul(3)
+	t.reduce()
+	return t;
+}
+
+/* convert from byte array to FP12 */
+func FP12_fromBytes(w []byte) *FP12 {
+	var t [int(MODBYTES)]byte
+	MB:=int(MODBYTES)
+
+	for i:=0;i<MB;i++ {t[i]=w[i]}
+	a:=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+MB]}
+	b:=FromBytes(t[:])
+	c:=NewFP2bigs(a,b)
+
+	for i:=0;i<MB;i++ {t[i]=w[i+2*MB]}
+	a=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+3*MB]}
+	b=FromBytes(t[:])
+	d:=NewFP2bigs(a,b)
+
+	e:=NewFP4fp2s(c,d)
+
+
+	for i:=0;i<MB;i++ {t[i]=w[i+4*MB]}
+	a=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+5*MB]}
+	b=FromBytes(t[:])
+	c=NewFP2bigs(a,b)
+
+	for i:=0;i<MB;i++ {t[i]=w[i+6*MB]}
+	a=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+7*MB]}
+	b=FromBytes(t[:])
+	d=NewFP2bigs(a,b)
+
+	f:=NewFP4fp2s(c,d)
+
+
+	for i:=0;i<MB;i++ {t[i]=w[i+8*MB]}
+	a=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+9*MB]}
+	b=FromBytes(t[:]);
+		
+	c=NewFP2bigs(a,b)
+
+	for i:=0;i<MB;i++ {t[i]=w[i+10*MB]}
+	a=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+11*MB]}
+	b=FromBytes(t[:])
+	d=NewFP2bigs(a,b)
+
+	g:=NewFP4fp2s(c,d)
+
+	return NewFP12fp4s(e,f,g)
+}
+
+/* convert this to byte array */
+func (F *FP12) ToBytes(w []byte) {
+	var t [int(MODBYTES)]byte
+	MB:=int(MODBYTES)
+	F.a.geta().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i]=t[i]}
+	F.a.geta().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+MB]=t[i]}
+	F.a.getb().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+2*MB]=t[i]}
+	F.a.getb().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+3*MB]=t[i]}
+
+	F.b.geta().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+4*MB]=t[i]}
+	F.b.geta().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+5*MB]=t[i]}
+	F.b.getb().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+6*MB]=t[i]}
+	F.b.getb().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+7*MB]=t[i]}
+
+	F.c.geta().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+8*MB]=t[i]}
+	F.c.geta().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+9*MB]=t[i]}
+	F.c.getb().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+10*MB]=t[i]}
+	F.c.getb().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+11*MB]=t[i]}
+}
+
+/* convert to hex string */
+func (F *FP12) ToString() string {
+	return ("["+F.a.toString()+","+F.b.toString()+","+F.c.toString()+"]")
+}
+
+/* this=this^e */ 
+func (F *FP12) Pow(e *BIG) *FP12 {
+	//F.norm()
+	e1:=NewBIGcopy(e)
+	e1.norm()
+	e3:=NewBIGcopy(e1)
+	e3.pmul(3)
+	e3.norm()
+	sf:=NewFP12copy(F)
+	sf.norm()
+	w:=NewFP12copy(sf)
+	//z:=NewBIGcopy(e)
+	//r:=NewFP12int(1)
+
+	nb:=e3.nbits()
+	for i:=nb-2;i>=1;i-- {
+		w.usqr()
+		bt:=e3.bit(i)-e1.bit(i)
+		if bt==1 {
+			w.Mul(sf)
+		}
+		if bt==-1 {
+			sf.conj()
+			w.Mul(sf)
+			sf.conj()	
+		}
+	}
+	w.reduce()
+	return w
+/*
+	for true {
+		bt:=z.parity()
+		z.fshr(1)
+		if bt==1 {r.Mul(w)}
+		if z.iszilch() {break}
+		w.usqr()
+	}
+	r.reduce();
+	return r; */
+}
+
+/* constant time powering by small integer of max length bts */
+func (F *FP12) pinpow(e int,bts int) {
+	var R []*FP12
+	R=append(R,NewFP12int(1))
+	R=append(R,NewFP12copy(F))
+
+	for i:=bts-1;i>=0;i-- {
+		b:=(e>>uint(i))&1
+		R[1-b].Mul(R[b])
+		R[b].usqr()
+	}
+	F.Copy(R[0])
+}
+
+/* Fast compressed FP4 power of unitary FP12 */
+func (F *FP12) Compow(e *BIG,r *BIG) *FP4 {
+	q:=NewBIGints(Modulus)
+	//r:=NewBIGints(CURVE_Order)
+	f:=NewFP2bigs(NewBIGints(Fra),NewBIGints(Frb))
+
+	m:=NewBIGcopy(q)
+	m.Mod(r)
+
+	a:=NewBIGcopy(e)
+	a.Mod(m)
+
+	b:=NewBIGcopy(e)
+	b.div(m)
+
+	g1:=NewFP12copy(F);
+	c:=g1.trace()
+
+	if b.iszilch() {
+		c=c.xtr_pow(e)
+		return c
+	}
+
+	g2:=NewFP12copy(F)
+	g2.frob(f)
+	cp:=g2.trace()
+
+	g1.conj()
+	g2.Mul(g1)
+	cpm1:=g2.trace()
+	g2.Mul(g1)
+	cpm2:=g2.trace()
+
+	c=c.xtr_pow2(cp,cpm1,cpm2,a,b)
+	return c
+}
+
+/* p=q0^u0.q1^u1.q2^u2.q3^u3 */
+// Bos & Costello https://eprint.iacr.org/2013/458.pdf
+// Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
+// Side channel attack secure 
+
+func pow4(q []*FP12,u []*BIG) *FP12 {
+	var g []*FP12
+	var w [NLEN*int(BASEBITS)+1]int8
+	var s [NLEN*int(BASEBITS)+1]int8
+	var t []*BIG
+	r:=NewFP12int(0)
+	p:=NewFP12int(0)
+	mt:=NewBIGint(0)
+
+	for i:=0;i<4;i++ {
+		t=append(t,NewBIGcopy(u[i]))
+	}
+
+	g=append(g,NewFP12copy(q[0]))	// q[0]
+	g=append(g,NewFP12copy(g[0])); g[1].Mul(q[1])	// q[0].q[1]
+	g=append(g,NewFP12copy(g[0])); g[2].Mul(q[2])	// q[0].q[2]
+	g=append(g,NewFP12copy(g[1])); g[3].Mul(q[2])	// q[0].q[1].q[2]
+	g=append(g,NewFP12copy(g[0])); g[4].Mul(q[3])	// q[0].q[3]
+	g=append(g,NewFP12copy(g[1])); g[5].Mul(q[3])	// q[0].q[1].q[3]
+	g=append(g,NewFP12copy(g[2])); g[6].Mul(q[3])	// q[0].q[2].q[3]
+	g=append(g,NewFP12copy(g[3])); g[7].Mul(q[3])	// q[0].q[1].q[2].q[3]
+
+// Make it odd
+	pb:=1-t[0].parity()
+	t[0].inc(pb)
+//	t[0].norm();
+
+// Number of bits
+	mt.zero()
+	for i:=0;i<4;i++ {
+		t[i].norm()
+		mt.or(t[i])
+	}
+
+	nb:=1+mt.nbits();
+
+// Sign pivot 
+	s[nb-1]=1
+	for i:=0;i<nb-1;i++ {
+		t[0].fshr(1)
+		s[i]=2*int8(t[0].parity())-1
+	}
+
+// Recoded exponent
+	for i:=0; i<nb; i++ {
+		w[i]=0
+		k:=1
+		for j:=1; j<4; j++ {
+			bt:=s[i]*int8(t[j].parity())
+			t[j].fshr(1)
+			t[j].dec(int(bt)>>1)
+			t[j].norm()
+			w[i]+=bt*int8(k)
+			k*=2
+		}
+	}
+
+// Main loop
+	p.selector(g,int32(2*w[nb-1]+1))  
+	for i:=nb-2;i>=0;i-- {
+		p.usqr()
+		r.selector(g,int32(2*w[i]+s[i]))
+		p.Mul(r)
+	}
+
+// apply correction
+	r.Copy(q[0]); r.conj()   
+	r.Mul(p)
+	p.cmove(r,pb)
+
+	p.reduce()
+	return p;
+}
+
+/*
+func pow4(q []*FP12,u []*BIG) *FP12 {
+	var a [4]int8
+	var g []*FP12
+	var s []*FP12
+	c:=NewFP12int(1)
+	p:=NewFP12int(0)
+	var w [NLEN*int(BASEBITS)+1]int8
+	var t []*BIG
+	mt:=NewBIGint(0)
+
+	for i:=0;i<4;i++ {
+		t=append(t,NewBIGcopy(u[i]))
+	}
+
+	s=append(s,NewFP12int(0))
+	s=append(s,NewFP12int(0))
+
+	g=append(g,NewFP12copy(q[0])); s[0].Copy(q[1]); s[0].conj(); g[0].Mul(s[0])
+	g=append(g,NewFP12copy(g[0]))
+	g=append(g,NewFP12copy(g[0]))
+	g=append(g,NewFP12copy(g[0]))
+	g=append(g,NewFP12copy(q[0])); g[4].Mul(q[1])
+	g=append(g,NewFP12copy(g[4]))
+	g=append(g,NewFP12copy(g[4]))
+	g=append(g,NewFP12copy(g[4]))
+
+	s[1].Copy(q[2]); s[0].Copy(q[3]); s[0].conj(); s[1].Mul(s[0])
+	s[0].Copy(s[1]); s[0].conj(); g[1].Mul(s[0])
+	g[2].Mul(s[1])
+	g[5].Mul(s[0])
+	g[6].Mul(s[1])
+	s[1].Copy(q[2]); s[1].Mul(q[3])
+	s[0].Copy(s[1]); s[0].conj(); g[0].Mul(s[0])
+	g[3].Mul(s[1])
+	g[4].Mul(s[0])
+	g[7].Mul(s[1])
+
+// if power is even add 1 to power, and add q to correction 
+
+	for i:=0;i<4;i++ {
+		if t[i].parity()==0 {
+			t[i].inc(1); t[i].norm()
+			c.Mul(q[i])
+		}
+		mt.add(t[i]); mt.norm()
+	}
+	c.conj()
+	nb:=1+mt.nbits()
+
+// convert exponent to signed 1-bit window 
+	for j:=0;j<nb;j++ {
+		for i:=0;i<4;i++ {
+			a[i]=int8(t[i].lastbits(2)-2)
+			t[i].dec(int(a[i])); t[i].norm();
+			t[i].fshr(1)
+		}
+		w[j]=(8*a[0]+4*a[1]+2*a[2]+a[3])
+	}
+	w[nb]=int8(8*t[0].lastbits(2)+4*t[1].lastbits(2)+2*t[2].lastbits(2)+t[3].lastbits(2))
+	p.Copy(g[(w[nb]-1)/2])
+
+	for i:=nb-1;i>=0;i-- {
+		m:=w[i]>>7
+		j:=(w[i]^m)-m  // j=abs(w[i]) 
+		j=(j-1)/2
+		s[0].Copy(g[j]); s[1].Copy(g[j]); s[1].conj()
+		p.usqr()
+		p.Mul(s[m&1]);
+	}
+	p.Mul(c)  // apply correction 
+	p.reduce()
+	return p;
+}
+*/
+
diff --git a/version3/go/FP16.go b/version3/go/FP16.go
new file mode 100644
index 0000000..4916f13
--- /dev/null
+++ b/version3/go/FP16.go
@@ -0,0 +1,527 @@
+/*
+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.
+*/
+
+/* Finite Field arithmetic  Fp^16 functions */
+
+/* FP4 elements are of the form a+ib, where i is sqrt(-1+sqrt(-1)) */
+
+package XXX
+
+//import "fmt"
+
+type FP16 struct {
+	a *FP8
+	b *FP8
+}
+
+/* Constructors */
+func NewFP16int(a int) *FP16 {
+	F:=new(FP16)
+	F.a=NewFP8int(a)
+	F.b=NewFP8int(0)
+	return F
+}
+
+func NewFP16copy(x *FP16) *FP16 {
+	F:=new(FP16)
+	F.a=NewFP8copy(x.a)
+	F.b=NewFP8copy(x.b)
+	return F
+}
+
+func NewFP16fp8s(c *FP8,d *FP8) *FP16 {
+	F:=new(FP16)
+	F.a=NewFP8copy(c)
+	F.b=NewFP8copy(d)
+	return F
+}
+
+func NewFP16fp8(c *FP8) *FP16 {
+	F:=new(FP16)
+	F.a=NewFP8copy(c)
+	F.b=NewFP8int(0)
+	return F
+}
+
+/* reduce all components of this mod Modulus */
+func (F *FP16) reduce() {
+	F.a.reduce()
+	F.b.reduce()
+}
+
+/* normalise all components of this mod Modulus */
+func (F *FP16) norm() {
+	F.a.norm()
+	F.b.norm()
+}
+
+/* test this==0 ? */
+func (F *FP16) iszilch() bool {
+	//F.reduce()
+	return F.a.iszilch() && F.b.iszilch()
+}
+
+/* Conditional move */
+func (F *FP16) cmove(g *FP16,d int) {
+	F.a.cmove(g.a,d)
+	F.b.cmove(g.b,d)
+}
+
+/* test this==1 ? */
+func (F *FP16) isunity() bool {
+	one:=NewFP8int(1)
+	return F.a.Equals(one) && F.b.iszilch()
+}
+
+/* test is w real? That is in a+ib test b is zero */
+func (F *FP16) isreal() bool {
+	return F.b.iszilch()
+}
+/* extract real part a */
+func (F *FP16) real() *FP8 {
+	return F.a
+}
+
+func (F *FP16) geta() *FP8 {
+	return F.a
+}
+/* extract imaginary part b */
+func (F *FP16) getb() *FP8 {
+	return F.b
+}
+/* test this=x? */
+func (F *FP16) Equals(x *FP16) bool {
+	return (F.a.Equals(x.a) && F.b.Equals(x.b))
+}
+
+/* copy this=x */
+func (F *FP16) copy(x *FP16) {
+	F.a.copy(x.a)
+	F.b.copy(x.b)
+}
+
+/* set this=0 */
+func (F *FP16) zero() {
+	F.a.zero()
+	F.b.zero()
+}
+/* set this=1 */
+func (F *FP16) one() {
+	F.a.one()
+	F.b.zero()
+}
+
+/* set this=-this */
+func (F *FP16) neg() {
+	F.norm()
+	m:=NewFP8copy(F.a);
+	t:=NewFP8int(0)
+	m.add(F.b)
+	m.neg()
+	//m.norm()
+	t.copy(m); t.add(F.b)
+	F.b.copy(m)
+	F.b.add(F.a)
+	F.a.copy(t)
+	F.norm()
+}
+
+/* this=conjugate(this) */
+func (F *FP16) conj() {
+	F.b.neg(); F.norm()
+}
+
+/* this=-conjugate(this) */
+func (F *FP16) nconj() {
+	F.a.neg(); F.norm()
+}
+
+/* this+=x */
+func (F *FP16) add(x *FP16) {
+	F.a.add(x.a)
+	F.b.add(x.b)
+}
+/* this-=x */
+func (F *FP16) sub(x *FP16) {
+	m:=NewFP16copy(x)
+	m.neg()
+	F.add(m)
+}
+
+/* this-=x */
+func (F *FP16) rsub(x *FP16) {
+	F.neg()
+	F.add(x)
+}
+
+/* this*=s where s is FP8 */
+func (F *FP16) pmul(s *FP8) {
+	F.a.mul(s)
+	F.b.mul(s)
+}
+
+/* this*=s where s is FP2 */
+func (F *FP16) qmul(s *FP2) {
+	F.a.qmul(s)
+	F.b.qmul(s)
+}
+
+/* this*=c where c is int */
+func (F *FP16) imul(c int) {
+	F.a.imul(c)
+	F.b.imul(c)
+}
+
+/* this*=this */	
+func (F *FP16) sqr() {
+//	F.norm()
+
+	t1:=NewFP8copy(F.a)
+	t2:=NewFP8copy(F.b)
+	t3:=NewFP8copy(F.a)
+
+	t3.mul(F.b)
+	t1.add(F.b)
+	t2.times_i()
+
+	t2.add(F.a)
+
+	t1.norm(); t2.norm()
+
+	F.a.copy(t1)
+	F.a.mul(t2)
+
+	t2.copy(t3)
+	t2.times_i()
+	t2.add(t3); t2.norm()
+	t2.neg()
+	F.a.add(t2)
+
+	F.b.copy(t3)
+	F.b.add(t3)
+
+	F.norm()
+}
+
+/* this*=y */
+func (F *FP16) mul(y *FP16) {
+//	F.norm()
+
+	t1:=NewFP8copy(F.a)
+	t2:=NewFP8copy(F.b)
+	t3:=NewFP8int(0)
+	t4:=NewFP8copy(F.b)
+
+	t1.mul(y.a)
+	t2.mul(y.b)
+	t3.copy(y.b)
+	t3.add(y.a)
+	t4.add(F.a)
+
+	t3.norm(); t4.norm();
+
+	t4.mul(t3)
+
+	t3.copy(t1)
+	t3.neg()
+	t4.add(t3)
+	t4.norm()
+
+	t3.copy(t2);
+	t3.neg()
+	F.b.copy(t4)
+	F.b.add(t3)
+
+	t2.times_i()
+	F.a.copy(t2)
+	F.a.add(t1)
+
+	F.norm()
+}
+
+/* convert this to hex string */
+func (F *FP16) toString() string {
+	return ("["+F.a.toString()+","+F.b.toString()+"]")
+}
+
+/* this=1/this */
+func (F *FP16) inverse() {
+//	F.norm()
+
+	t1:=NewFP8copy(F.a)
+	t2:=NewFP8copy(F.b)
+
+	t1.sqr()
+	t2.sqr()
+	t2.times_i(); t2.norm()
+	t1.sub(t2); t1.norm()
+	t1.inverse()
+	F.a.mul(t1)
+	t1.neg(); t1.norm()
+	F.b.mul(t1)
+}
+
+/* this*=i where i = sqrt(sqrt(-1+sqrt(-1))) */
+func (F *FP16) times_i() {
+//	F.norm()
+	s:=NewFP8copy(F.b)
+	t:=NewFP8copy(F.a)
+	s.times_i()
+	F.a.copy(s)
+	F.b.copy(t)
+	F.norm()
+}
+
+func (F *FP16) times_i2() {
+	F.a.times_i()
+	F.b.times_i()
+}
+
+func (F *FP16) times_i4() {
+	F.a.times_i2()
+	F.b.times_i2()
+}
+
+/* this=this^p using Frobenius */
+func (F *FP16) frob(f *FP2) {
+	ff:=NewFP2copy(f); ff.sqr(); ff.norm()
+
+	F.a.frob(ff)
+	F.b.frob(ff)
+	F.b.qmul(f)
+	F.b.times_i()
+
+}
+
+/* this=this^e */
+func (F *FP16) pow(e *BIG) *FP16 {
+	w:=NewFP16copy(F)
+	w.norm();
+	z:=NewBIGcopy(e)
+	r:=NewFP16int(1)
+	z.norm()
+	for true {
+		bt:=z.parity()
+		z.fshr(1)
+		if bt==1 {r.mul(w)}
+		if z.iszilch() {break}
+		w.sqr()
+	}
+	r.reduce()
+	return r
+}
+
+/* XTR xtr_a function */
+func (F *FP16) xtr_A(w *FP16,y *FP16,z *FP16) {
+	r:=NewFP16copy(w)
+	t:=NewFP16copy(w)
+	//y.norm()
+	r.sub(y); r.norm()
+	r.pmul(F.a)
+	t.add(y); t.norm()
+	t.pmul(F.b)
+	t.times_i()
+
+	F.copy(r)
+	F.add(t)
+	F.add(z)
+
+	F.norm()
+}
+
+/* XTR xtr_d function */
+func (F *FP16) xtr_D() {
+	w:=NewFP16copy(F)
+	F.sqr(); w.conj()
+	w.add(w); w.norm()
+	F.sub(w)
+	F.reduce()
+}
+
+/* r=x^n using XTR method on traces of FP12s */
+func (F *FP16) xtr_pow(n *BIG) *FP16 {
+	sf:=NewFP16copy(F);
+	sf.norm()
+	a:=NewFP16int(3)
+	b:=NewFP16copy(sf)
+	c:=NewFP16copy(b)
+	c.xtr_D()
+	t:=NewFP16int(0)
+	r:=NewFP16int(0)
+
+	
+	par:=n.parity()
+	v:=NewBIGcopy(n); v.norm(); v.fshr(1)
+	if (par==0) {v.dec(1); v.norm()}
+
+	nb:=v.nbits();
+	for i:=nb-1;i>=0;i-- {
+		if v.bit(i)!=1 {
+			t.copy(b)
+			sf.conj()
+			c.conj()
+			b.xtr_A(a,sf,c)
+			sf.conj()
+			c.copy(t)
+			c.xtr_D()
+			a.xtr_D()
+		} else {
+			t.copy(a); t.conj()
+			a.copy(b)
+			a.xtr_D()
+			b.xtr_A(c,sf,t)
+			c.xtr_D()
+		}
+	}
+	if par==0 {
+		r.copy(c)
+	} else {r.copy(b)}
+	r.reduce()
+	return r
+}
+
+/* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */
+func (F *FP16) xtr_pow2(ck *FP16,ckml *FP16,ckm2l *FP16,a *BIG,b *BIG) *FP16 {
+
+	e:=NewBIGcopy(a)
+	d:=NewBIGcopy(b)
+	w:=NewBIGint(0)
+	e.norm(); d.norm()
+	cu:=NewFP16copy(ck)  // can probably be passed in w/o copying
+	cv:=NewFP16copy(F);
+	cumv:=NewFP16copy(ckml)
+	cum2v:=NewFP16copy(ckm2l)
+	r:=NewFP16int(0)
+	t:=NewFP16int(0)
+
+	f2:=0
+	for (d.parity()==0 && e.parity()==0) {
+		d.fshr(1)
+		e.fshr(1)
+		f2++
+	}
+
+	for Comp(d,e)!=0 {
+		if Comp(d,e)>0 {
+			w.copy(e); w.imul(4); w.norm()
+			if Comp(d,w)<=0 {
+				w.copy(d); d.copy(e)
+				e.rsub(w); e.norm()
+
+				t.copy(cv);
+				t.xtr_A(cu,cumv,cum2v)
+				cum2v.copy(cumv);
+				cum2v.conj()
+				cumv.copy(cv)
+				cv.copy(cu)
+				cu.copy(t)
+			} else {
+					if (d.parity()==0) {
+					d.fshr(1)
+					r.copy(cum2v); r.conj()
+					t.copy(cumv)
+					t.xtr_A(cu,cv,r)
+					cum2v.copy(cumv)
+					cum2v.xtr_D()
+					cumv.copy(t)
+					cu.xtr_D()
+				} else {
+					if (e.parity()==1) {
+						d.sub(e); d.norm()
+						d.fshr(1)
+						t.copy(cv)
+						t.xtr_A(cu,cumv,cum2v)
+						cu.xtr_D()
+						cum2v.copy(cv)
+						cum2v.xtr_D()
+						cum2v.conj()
+						cv.copy(t)
+					} else {
+						w.copy(d)
+						d.copy(e); d.fshr(1)
+						e.copy(w)
+						t.copy(cumv)
+						t.xtr_D()
+						cumv.copy(cum2v); cumv.conj()
+						cum2v.copy(t); cum2v.conj()
+						t.copy(cv)
+						t.xtr_D()
+						cv.copy(cu)
+						cu.copy(t)
+					}
+				}
+			}
+		}
+		if Comp(d,e)<0 {
+			w.copy(d); w.imul(4); w.norm()
+			if Comp(e,w)<=0 {
+				e.sub(d); e.norm()
+				t.copy(cv)
+				t.xtr_A(cu,cumv,cum2v)
+				cum2v.copy(cumv)
+				cumv.copy(cu)
+				cu.copy(t)
+			} else {
+				if (e.parity()==0) {
+					w.copy(d)
+					d.copy(e); d.fshr(1)
+					e.copy(w)
+					t.copy(cumv)
+					t.xtr_D()
+					cumv.copy(cum2v); cumv.conj()
+					cum2v.copy(t); cum2v.conj()
+					t.copy(cv)
+					t.xtr_D()
+					cv.copy(cu)
+					cu.copy(t)
+				} else {
+					if (d.parity()==1) {
+						w.copy(e)
+						e.copy(d)
+						w.sub(d); w.norm()
+						d.copy(w); d.fshr(1)
+						t.copy(cv)
+						t.xtr_A(cu,cumv,cum2v)
+						cumv.conj()
+						cum2v.copy(cu)
+						cum2v.xtr_D()
+						cum2v.conj()
+						cu.copy(cv)
+						cu.xtr_D()
+						cv.copy(t)
+					} else {
+						d.fshr(1)
+						r.copy(cum2v); r.conj()
+						t.copy(cumv)
+						t.xtr_A(cu,cv,r)
+						cum2v.copy(cumv)
+						cum2v.xtr_D()
+						cumv.copy(t)
+						cu.xtr_D()
+					}
+				}
+			}
+		}
+	}
+	r.copy(cv)
+	r.xtr_A(cu,cumv,cum2v)
+	for i:=0;i<f2;i++ {r.xtr_D()}
+	r=r.xtr_pow(d)
+	return r
+}
diff --git a/version3/go/FP2.go b/version3/go/FP2.go
new file mode 100644
index 0000000..ffb3ac6
--- /dev/null
+++ b/version3/go/FP2.go
@@ -0,0 +1,333 @@
+/*
+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.
+*/
+
+/* Finite Field arithmetic  Fp^2 functions */
+
+/* FP2 elements are of the form a+ib, where i is sqrt(-1) */
+
+package XXX
+
+//import "fmt"
+
+type FP2 struct {
+	a *FP
+	b *FP
+}
+
+/* Constructors */
+func NewFP2int(a int) *FP2 {
+	F:=new(FP2)
+	F.a=NewFPint(a)
+	F.b=NewFPint(0)
+	return F
+}
+
+func NewFP2copy(x *FP2) *FP2 {
+	F:=new(FP2)
+	F.a=NewFPcopy(x.a)
+	F.b=NewFPcopy(x.b)
+	return F
+}
+
+func NewFP2fps(c *FP,d *FP) *FP2 {
+	F:=new(FP2)
+	F.a=NewFPcopy(c)
+	F.b=NewFPcopy(d)
+	return F
+}
+
+func NewFP2bigs(c *BIG,d *BIG) *FP2 {
+	F:=new(FP2)
+	F.a=NewFPbig(c)
+	F.b=NewFPbig(d)
+	return F
+}
+
+func NewFP2fp(c *FP) *FP2 {
+	F:=new(FP2)
+	F.a=NewFPcopy(c)
+	F.b=NewFPint(0)
+	return F
+}
+
+func NewFP2big(c *BIG) *FP2 {
+	F:=new(FP2)
+	F.a=NewFPbig(c)
+	F.b=NewFPint(0)
+	return F
+}
+
+/* reduce components mod Modulus */
+func (F *FP2) reduce() {
+	F.a.reduce()
+	F.b.reduce()
+}
+
+/* normalise components of w */
+func (F *FP2) norm() {
+	F.a.norm()
+	F.b.norm()
+}
+
+/* test this=0 ? */
+func (F *FP2) iszilch() bool {
+	//F.reduce()
+	return (F.a.iszilch() && F.b.iszilch())
+}
+
+func (F *FP2) cmove(g *FP2,d int) {
+	F.a.cmove(g.a,d)
+	F.b.cmove(g.b,d)
+}
+
+/* test this=1 ? */
+func (F *FP2)  isunity() bool {
+	one:=NewFPint(1)
+	return (F.a.Equals(one) && F.b.iszilch())
+}
+
+/* test this=x */
+func (F *FP2) Equals(x *FP2) bool {
+	return (F.a.Equals(x.a) && F.b.Equals(x.b))
+}
+
+/* extract a */
+func (F *FP2) GetA() *BIG { 
+	return F.a.redc()
+}
+
+/* extract b */
+func (F *FP2) GetB() *BIG {
+	return F.b.redc()
+}
+
+/* copy this=x */
+func (F *FP2) copy(x *FP2) {
+	F.a.copy(x.a)
+	F.b.copy(x.b)
+}
+
+/* set this=0 */
+func (F *FP2) zero() {
+	F.a.zero()
+	F.b.zero()
+}
+
+/* set this=1 */
+func (F *FP2) one() {
+	F.a.one()
+	F.b.zero()
+}
+
+/* negate this mod Modulus */
+func (F *FP2) neg() {
+//	F.norm()
+	m:=NewFPcopy(F.a)
+	t:= NewFPint(0)
+
+	m.add(F.b)
+	m.neg()
+//	m.norm()
+	t.copy(m); t.add(F.b)
+	F.b.copy(m)
+	F.b.add(F.a)
+	F.a.copy(t)
+}
+
+/* set to a-ib */
+func (F *FP2) conj() {
+	F.b.neg(); F.b.norm()
+}
+
+/* this+=a */
+func (F *FP2) add(x *FP2) {
+	F.a.add(x.a)
+	F.b.add(x.b)
+}
+
+/* this-=a */
+func (F *FP2) sub(x *FP2) {
+	m:=NewFP2copy(x)
+	m.neg()
+	F.add(m)
+}
+
+/* this-=a */
+func (F *FP2) rsub(x *FP2) {
+	F.neg()
+	F.add(x)
+}
+
+/* this*=s, where s is an FP */
+func (F *FP2) pmul(s *FP) {
+	F.a.mul(s)
+	F.b.mul(s)
+}
+
+/* this*=i, where i is an int */
+func (F *FP2) imul(c int) {
+	F.a.imul(c)
+	F.b.imul(c)
+}
+
+/* this*=this */
+func (F *FP2) sqr() {
+	w1:=NewFPcopy(F.a)
+	w3:=NewFPcopy(F.a)
+	mb:=NewFPcopy(F.b)
+
+//	w3.mul(F.b)
+	w1.add(F.b)
+
+w3.add(F.a);
+w3.norm();
+F.b.mul(w3);
+
+	mb.neg()
+	F.a.add(mb)
+
+	w1.norm()
+	F.a.norm()
+
+	F.a.mul(w1)
+//	F.b.copy(w3); F.b.add(w3)
+
+//	F.b.norm()
+}
+
+/* this*=y */
+/* Now using Lazy reduction */
+func (F *FP2) mul(y *FP2) {
+
+	if int64(F.a.XES+F.b.XES)*int64(y.a.XES+y.b.XES)>int64(FEXCESS) {
+		if F.a.XES>1 {F.a.reduce()}
+		if F.b.XES>1 {F.b.reduce()}		
+	}
+
+	pR:=NewDBIG()
+	C:=NewBIGcopy(F.a.x)
+	D:=NewBIGcopy(y.a.x)
+	p:=NewBIGints(Modulus)
+
+	pR.ucopy(p)
+
+	A:=mul(F.a.x,y.a.x)
+	B:=mul(F.b.x,y.b.x)
+
+	C.add(F.b.x); C.norm()
+	D.add(y.b.x); D.norm()
+
+	E:=mul(C,D)
+	FF:=NewDBIGcopy(A); FF.add(B)
+	B.rsub(pR)
+
+	A.add(B); A.norm()
+	E.sub(FF); E.norm()
+
+	F.a.x.copy(mod(A)); F.a.XES=3
+	F.b.x.copy(mod(E)); F.b.XES=2
+
+}
+
+/* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */
+/* returns true if this is QR */
+func (F *FP2) sqrt() bool {
+	if F.iszilch() {return true}
+	w1:=NewFPcopy(F.b)
+	w2:=NewFPcopy(F.a)
+	w1.sqr(); w2.sqr(); w1.add(w2)
+	if w1.jacobi()!=1 { F.zero(); return false }
+	w1=w1.sqrt()
+	w2.copy(F.a); w2.add(w1); w2.norm(); w2.div2()
+	if w2.jacobi()!=1 {
+		w2.copy(F.a); w2.sub(w1); w2.norm(); w2.div2()
+		if w2.jacobi()!=1 { F.zero(); return false }
+	}
+	w2=w2.sqrt()
+	F.a.copy(w2)
+	w2.add(w2)
+	w2.inverse()
+	F.b.mul(w2)
+	return true
+}
+
+/* output to hex string */
+func (F *FP2) toString() string {
+	return ("["+F.a.toString()+","+F.b.toString()+"]")
+}
+
+/* this=1/this */
+func (F *FP2) inverse() {
+	F.norm()
+	w1:=NewFPcopy(F.a)
+	w2:=NewFPcopy(F.b)
+
+	w1.sqr()
+	w2.sqr()
+	w1.add(w2)
+	w1.inverse()
+	F.a.mul(w1)
+	w1.neg(); w1.norm();
+	F.b.mul(w1)
+}
+
+/* this/=2 */
+func (F *FP2) div2() {
+	F.a.div2()
+	F.b.div2()
+}
+
+/* this*=sqrt(-1) */
+func (F *FP2) times_i() {
+	//	a.norm();
+	z:=NewFPcopy(F.a)
+	F.a.copy(F.b); F.a.neg()
+	F.b.copy(z)
+}
+
+/* w*=(1+sqrt(-1)) */
+/* where X*2-(1+sqrt(-1)) is irreducible for FP4, assumes p=3 mod 8 */
+func (F *FP2) mul_ip() {
+//	F.norm()
+	t:=NewFP2copy(F)
+	z:=NewFPcopy(F.a)
+	F.a.copy(F.b)
+	F.a.neg()
+	F.b.copy(z)
+	F.add(t)
+//	F.norm()
+}
+
+func (F *FP2) div_ip2() {
+	t:=NewFP2int(0)
+	F.norm()
+	t.a.copy(F.a); t.a.add(F.b)
+	t.b.copy(F.b); t.b.sub(F.a);
+	F.copy(t); F.norm()
+}
+
+/* w/=(1+sqrt(-1)) */
+func (F *FP2) div_ip() {
+	t:=NewFP2int(0)
+	F.norm()
+	t.a.copy(F.a); t.a.add(F.b)
+	t.b.copy(F.b); t.b.sub(F.a);
+	F.copy(t); F.norm()
+	F.div2()
+}
diff --git a/version3/go/FP24.go b/version3/go/FP24.go
new file mode 100644
index 0000000..eadcb1e
--- /dev/null
+++ b/version3/go/FP24.go
@@ -0,0 +1,885 @@
+/*
+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.
+*/
+
+/* MiotCL Fp^12 functions */
+/* FP12 elements are of the form a+i.b+i^2.c */
+
+package XXX
+
+//import "fmt"
+
+type FP24 struct {
+	a *FP8
+	b *FP8
+	c *FP8
+}
+
+/* Constructors */
+func NewFP24fp8(d *FP8) *FP24 {
+	F:=new(FP24)
+	F.a=NewFP8copy(d)
+	F.b=NewFP8int(0)
+	F.c=NewFP8int(0)
+	return F
+}
+
+func NewFP24int(d int) *FP24 {
+	F:=new(FP24)
+	F.a=NewFP8int(d)
+	F.b=NewFP8int(0)
+	F.c=NewFP8int(0)
+	return F
+}
+
+func NewFP24fp8s(d *FP8,e *FP8,f *FP8) *FP24 {
+	F:=new(FP24)
+	F.a=NewFP8copy(d)
+	F.b=NewFP8copy(e)
+	F.c=NewFP8copy(f)
+	return F
+}
+
+func NewFP24copy(x *FP24) *FP24 {
+	F:=new(FP24)
+	F.a=NewFP8copy(x.a)
+	F.b=NewFP8copy(x.b)
+	F.c=NewFP8copy(x.c)
+	return F
+}
+
+/* reduce all components of this mod Modulus */
+func (F *FP24) reduce() {
+	F.a.reduce()
+	F.b.reduce()
+	F.c.reduce()
+}
+/* normalise all components of this */
+func (F *FP24) norm() {
+	F.a.norm()
+	F.b.norm()
+	F.c.norm()
+}
+/* test x==0 ? */
+func (F *FP24) iszilch() bool {
+	//F.reduce()
+	return (F.a.iszilch() && F.b.iszilch() && F.c.iszilch())
+}
+
+/* Conditional move */
+func (F *FP24) cmove(g *FP24,d int) {
+	F.a.cmove(g.a,d)
+	F.b.cmove(g.b,d)
+	F.c.cmove(g.c,d)
+}
+
+/* Constant time select from pre-computed table */
+func (F *FP24) selector(g []*FP24,b int32) {
+
+	m:=b>>31
+	babs:=(b^m)-m
+
+	babs=(babs-1)/2
+
+	F.cmove(g[0],teq(babs,0))  // conditional move
+	F.cmove(g[1],teq(babs,1))
+	F.cmove(g[2],teq(babs,2))
+	F.cmove(g[3],teq(babs,3))
+	F.cmove(g[4],teq(babs,4))
+	F.cmove(g[5],teq(babs,5))
+	F.cmove(g[6],teq(babs,6))
+	F.cmove(g[7],teq(babs,7))
+ 
+ 	invF:=NewFP24copy(F) 
+	invF.conj()
+	F.cmove(invF,int(m&1))
+}
+
+/* test x==1 ? */
+func (F *FP24) Isunity() bool {
+	one:=NewFP8int(1)
+	return (F.a.Equals(one) && F.b.iszilch() && F.c.iszilch())
+}
+/* return 1 if x==y, else 0 */
+func (F *FP24) Equals(x *FP24) bool {
+	return (F.a.Equals(x.a) && F.b.Equals(x.b) && F.c.Equals(x.c))
+}
+
+/* extract a from this */
+func (F *FP24) geta() *FP8 {
+	return F.a
+}
+/* extract b */
+func (F *FP24) getb() *FP8 {
+	return F.b
+}
+/* extract c */
+func (F *FP24) getc() *FP8 {
+	return F.c
+}
+/* copy this=x */
+func (F *FP24) Copy(x *FP24) {
+	F.a.copy(x.a)
+	F.b.copy(x.b)
+	F.c.copy(x.c)
+}
+/* set this=1 */
+func (F *FP24) one() {
+	F.a.one()
+	F.b.zero()
+	F.c.zero()
+}
+/* this=conj(this) */
+func (F *FP24) conj() {
+	F.a.conj()
+	F.b.nconj()
+	F.c.conj()
+}
+
+/* Granger-Scott Unitary Squaring */
+func (F *FP24) usqr() {
+	A:=NewFP8copy(F.a)
+	B:=NewFP8copy(F.c)
+	C:=NewFP8copy(F.b)
+	D:=NewFP8int(0)
+
+	F.a.sqr()
+	D.copy(F.a); D.add(F.a)
+	F.a.add(D)
+
+	F.a.norm();
+	A.nconj()
+
+	A.add(A)
+	F.a.add(A)
+	B.sqr()
+	B.times_i()
+
+	D.copy(B); D.add(B)
+	B.add(D)
+	B.norm();
+
+	C.sqr()
+	D.copy(C); D.add(C)
+	C.add(D)
+	C.norm();
+
+	F.b.conj()
+	F.b.add(F.b)
+	F.c.nconj()
+
+	F.c.add(F.c)
+	F.b.add(B)
+	F.c.add(C)
+	F.reduce()
+
+}
+
+/* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
+func (F *FP24)  sqr() {
+	A:=NewFP8copy(F.a)
+	B:=NewFP8copy(F.b)
+	C:=NewFP8copy(F.c)
+	D:=NewFP8copy(F.a)
+
+	A.sqr()
+	B.mul(F.c)
+	B.add(B); B.norm()
+	C.sqr()
+	D.mul(F.b)
+	D.add(D)
+
+	F.c.add(F.a)
+	F.c.add(F.b); F.c.norm()
+	F.c.sqr()
+
+	F.a.copy(A)
+
+	A.add(B)
+	A.norm();
+	A.add(C)
+	A.add(D)
+	A.norm();
+
+	A.neg()
+	B.times_i();
+	C.times_i()
+
+	F.a.add(B)
+
+	F.b.copy(C); F.b.add(D)
+	F.c.add(A)
+	F.norm()
+}
+
+/* FP24 full multiplication this=this*y */
+func (F *FP24) Mul(y *FP24) {
+	z0:=NewFP8copy(F.a)
+	z1:=NewFP8int(0)
+	z2:=NewFP8copy(F.b)
+	z3:=NewFP8int(0)
+	t0:=NewFP8copy(F.a)
+	t1:=NewFP8copy(y.a)
+
+	z0.mul(y.a)
+	z2.mul(y.b)
+
+	t0.add(F.b); t0.norm()
+	t1.add(y.b); t1.norm() 
+
+	z1.copy(t0); z1.mul(t1)
+	t0.copy(F.b); t0.add(F.c); t0.norm()
+
+	t1.copy(y.b); t1.add(y.c); t1.norm()
+	z3.copy(t0); z3.mul(t1)
+
+	t0.copy(z0); t0.neg()
+	t1.copy(z2); t1.neg()
+
+	z1.add(t0)
+	//z1.norm();
+	F.b.copy(z1); F.b.add(t1)
+
+	z3.add(t1)
+	z2.add(t0)
+
+	t0.copy(F.a); t0.add(F.c); t0.norm()
+	t1.copy(y.a); t1.add(y.c); t1.norm()
+	t0.mul(t1)
+	z2.add(t0)
+
+	t0.copy(F.c); t0.mul(y.c)
+	t1.copy(t0); t1.neg()
+
+	F.c.copy(z2); F.c.add(t1)
+	z3.add(t1)
+	t0.times_i()
+	F.b.add(t0)
+	z3.norm()
+	z3.times_i()
+	F.a.copy(z0); F.a.add(z3)
+	F.norm()
+}
+
+/* Special case of multiplication arises from special form of ATE pairing line function */
+func (F *FP24) smul(y *FP24,twist int ) {
+	if twist==D_TYPE {
+		z0:=NewFP8copy(F.a)
+		z2:=NewFP8copy(F.b)
+		z3:=NewFP8copy(F.b)
+		t0:=NewFP8int(0)
+		t1:=NewFP8copy(y.a)
+		
+		z0.mul(y.a)
+		z2.pmul(y.b.real());
+		F.b.add(F.a)
+		t1.real().add(y.b.real())
+
+		t1.norm(); F.b.norm()
+		F.b.mul(t1)
+		z3.add(F.c); z3.norm()
+		z3.pmul(y.b.real())
+
+		t0.copy(z0); t0.neg()
+		t1.copy(z2); t1.neg()
+
+		F.b.add(t0)
+	//F.b.norm();
+
+		F.b.add(t1)
+		z3.add(t1); z3.norm()
+		z2.add(t0)
+
+		t0.copy(F.a); t0.add(F.c); t0.norm()
+		t0.mul(y.a)
+		F.c.copy(z2); F.c.add(t0)
+
+		z3.times_i()
+		F.a.copy(z0); F.a.add(z3)
+	}
+	if twist==M_TYPE {
+		z0:=NewFP8copy(F.a)
+		z1:=NewFP8int(0)
+		z2:=NewFP8int(0)
+		z3:=NewFP8int(0)
+		t0:=NewFP8copy(F.a)
+		t1:=NewFP8int(0)
+		
+		z0.mul(y.a)
+		t0.add(F.b)
+		t0.norm()
+
+		z1.copy(t0); z1.mul(y.a)
+		t0.copy(F.b); t0.add(F.c)
+		t0.norm()
+
+		z3.copy(t0) //z3.mul(y.c);
+		z3.pmul(y.c.getb())
+		z3.times_i()
+
+		t0.copy(z0); t0.neg()
+
+		z1.add(t0)
+		F.b.copy(z1) 
+		z2.copy(t0)
+
+		t0.copy(F.a); t0.add(F.c)
+		t1.copy(y.a); t1.add(y.c)
+
+		t0.norm()
+		t1.norm()
+	
+		t0.mul(t1)
+		z2.add(t0)
+
+		t0.copy(F.c)
+			
+		t0.pmul(y.c.getb())
+		t0.times_i()
+
+		t1.copy(t0); t1.neg()
+
+		F.c.copy(z2); F.c.add(t1)
+		z3.add(t1)
+		t0.times_i()
+		F.b.add(t0)
+		z3.norm()
+		z3.times_i()
+		F.a.copy(z0); F.a.add(z3)
+	}
+	F.norm()
+}
+
+/* this=1/this */
+func (F *FP24) Inverse() {
+	f0:=NewFP8copy(F.a)
+	f1:=NewFP8copy(F.b)
+	f2:=NewFP8copy(F.a)
+	f3:=NewFP8int(0)
+
+	F.norm()
+	f0.sqr()
+	f1.mul(F.c)
+	f1.times_i()
+	f0.sub(f1); f0.norm()
+
+	f1.copy(F.c); f1.sqr()
+	f1.times_i()
+	f2.mul(F.b)
+	f1.sub(f2); f1.norm()
+
+	f2.copy(F.b); f2.sqr()
+	f3.copy(F.a); f3.mul(F.c)
+	f2.sub(f3); f2.norm()
+
+	f3.copy(F.b); f3.mul(f2)
+	f3.times_i()
+	F.a.mul(f0)
+	f3.add(F.a)
+	F.c.mul(f1)
+	F.c.times_i()
+
+	f3.add(F.c); f3.norm()
+	f3.inverse()
+	F.a.copy(f0); F.a.mul(f3)
+	F.b.copy(f1); F.b.mul(f3)
+	F.c.copy(f2); F.c.mul(f3)
+}
+
+/* this=this^p using Frobenius */
+func (F *FP24) frob(f *FP2, n int) {
+	f2:=NewFP2copy(f)
+	f3:=NewFP2copy(f)
+
+	f2.sqr()
+	f3.mul(f2)
+
+	f3.mul_ip(); f3.norm()
+
+	for i:=0;i<n;i++ {
+		F.a.frob(f3);
+		F.b.frob(f3);
+		F.c.frob(f3);
+
+		F.b.qmul(f); F.b.times_i2()
+		F.c.qmul(f2); F.c.times_i2(); F.c.times_i2()
+	}
+}
+
+/* trace function */
+func (F *FP24) trace() *FP8 {
+	t:=NewFP8int(0)
+	t.copy(F.a)
+	t.imul(3)
+	t.reduce()
+	return t;
+}
+
+/* convert from byte array to FP24 */
+func FP24_fromBytes(w []byte) *FP24 {
+	var t [int(MODBYTES)]byte
+	MB:=int(MODBYTES)
+
+	for i:=0;i<MB;i++ {t[i]=w[i]}
+	a:=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+MB]}
+	b:=FromBytes(t[:])
+	c:=NewFP2bigs(a,b)
+
+	for i:=0;i<MB;i++ {t[i]=w[i+2*MB]}
+	a=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+3*MB]}
+	b=FromBytes(t[:])
+	d:=NewFP2bigs(a,b)
+
+	ea:=NewFP4fp2s(c,d)
+
+	for i:=0;i<MB;i++ {t[i]=w[i+4*MB]}
+	a=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+5*MB]}
+	b=FromBytes(t[:])
+	c=NewFP2bigs(a,b)
+
+	for i:=0;i<MB;i++ {t[i]=w[i+6*MB]}
+	a=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+7*MB]}
+	b=FromBytes(t[:])
+	d=NewFP2bigs(a,b)
+
+	eb:=NewFP4fp2s(c,d)
+
+	e:=NewFP8fp4s(ea,eb)
+
+
+	for i:=0;i<MB;i++ {t[i]=w[i+8*MB]}
+	a=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+9*MB]}
+	b=FromBytes(t[:])
+	c=NewFP2bigs(a,b)
+
+	for i:=0;i<MB;i++ {t[i]=w[i+10*MB]}
+	a=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+11*MB]}
+	b=FromBytes(t[:])
+	d=NewFP2bigs(a,b)
+
+	fa:=NewFP4fp2s(c,d)
+
+	for i:=0;i<MB;i++ {t[i]=w[i+12*MB]}
+	a=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+13*MB]}
+	b=FromBytes(t[:])
+	c=NewFP2bigs(a,b)
+
+	for i:=0;i<MB;i++ {t[i]=w[i+14*MB]}
+	a=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+15*MB]}
+	b=FromBytes(t[:])
+	d=NewFP2bigs(a,b)
+
+	fb:=NewFP4fp2s(c,d)
+
+	f:=NewFP8fp4s(fa,fb)
+
+	for i:=0;i<MB;i++ {t[i]=w[i+16*MB]}
+	a=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+17*MB]}
+	b=FromBytes(t[:]);
+		
+	c=NewFP2bigs(a,b)
+
+	for i:=0;i<MB;i++ {t[i]=w[i+18*MB]}
+	a=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+19*MB]}
+	b=FromBytes(t[:])
+	d=NewFP2bigs(a,b)
+
+	ga:=NewFP4fp2s(c,d)
+
+
+	for i:=0;i<MB;i++ {t[i]=w[i+20*MB]}
+	a=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+21*MB]}
+	b=FromBytes(t[:]);
+		
+	c=NewFP2bigs(a,b)
+
+	for i:=0;i<MB;i++ {t[i]=w[i+22*MB]}
+	a=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+23*MB]}
+	b=FromBytes(t[:])
+	d=NewFP2bigs(a,b)
+
+	gb:=NewFP4fp2s(c,d)
+
+	g:=NewFP8fp4s(ga,gb)
+	
+	return NewFP24fp8s(e,f,g)
+}
+
+/* convert this to byte array */
+func (F *FP24) ToBytes(w []byte) {
+	var t [int(MODBYTES)]byte
+	MB:=int(MODBYTES)
+	F.a.a.geta().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i]=t[i]}
+	F.a.a.geta().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+MB]=t[i]}
+	F.a.a.getb().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+2*MB]=t[i]}
+	F.a.a.getb().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+3*MB]=t[i]}
+
+	F.a.b.geta().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+4*MB]=t[i]}
+	F.a.b.geta().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+5*MB]=t[i]}
+	F.a.b.getb().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+6*MB]=t[i]}
+	F.a.b.getb().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+7*MB]=t[i]}
+
+	F.b.a.geta().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+8*MB]=t[i]}
+	F.b.a.geta().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+9*MB]=t[i]}
+	F.b.a.getb().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+10*MB]=t[i]}
+	F.b.a.getb().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+11*MB]=t[i]}
+
+	F.b.b.geta().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+12*MB]=t[i]}
+	F.b.b.geta().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+13*MB]=t[i]}
+	F.b.b.getb().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+14*MB]=t[i]}
+	F.b.b.getb().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+15*MB]=t[i]}
+
+	F.c.a.geta().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+16*MB]=t[i]}
+	F.c.a.geta().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+17*MB]=t[i]}
+	F.c.a.getb().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+18*MB]=t[i]}
+	F.c.a.getb().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+19*MB]=t[i]}
+
+	F.c.b.geta().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+20*MB]=t[i]}
+	F.c.b.geta().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+21*MB]=t[i]}
+	F.c.b.getb().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+22*MB]=t[i]}
+	F.c.b.getb().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+23*MB]=t[i]}
+
+}
+
+/* convert to hex string */
+func (F *FP24) ToString() string {
+	return ("["+F.a.toString()+","+F.b.toString()+","+F.c.toString()+"]")
+}
+
+/* this=this^e */ 
+func (F *FP24) Pow(e *BIG) *FP24 {
+	sf:=NewFP24copy(F)
+	sf.norm()
+	
+	e1:=NewBIGcopy(e)
+	e1.norm()
+	e3:=NewBIGcopy(e1)
+	e3.pmul(3)
+	e3.norm()
+
+	w:=NewFP24copy(sf)
+	//z:=NewBIGcopy(e)
+	//r:=NewFP12int(1)
+
+	nb:=e3.nbits()
+	for i:=nb-2;i>=1;i-- {
+		w.usqr()
+		bt:=e3.bit(i)-e1.bit(i)
+		if bt==1 {
+			w.Mul(sf)
+		}
+		if bt==-1 {
+			sf.conj()
+			w.Mul(sf)
+			sf.conj()	
+		}
+	}
+	w.reduce()
+	return w
+/*
+	for true {
+		bt:=z.parity()
+		z.fshr(1)
+		if bt==1 {r.Mul(w)}
+		if z.iszilch() {break}
+		w.usqr()
+	}
+	r.reduce();
+	return r; */
+}
+
+/* constant time powering by small integer of max length bts */
+func (F *FP24) pinpow(e int,bts int) {
+	var R []*FP24
+	R=append(R,NewFP24int(1))
+	R=append(R,NewFP24copy(F))
+
+	for i:=bts-1;i>=0;i-- {
+		b:=(e>>uint(i))&1
+		R[1-b].Mul(R[b])
+		R[b].usqr()
+	}
+	F.Copy(R[0])
+}
+
+/* Fast compressed FP8 power of unitary FP24 */
+func (F *FP24) Compow(e *BIG,r *BIG) *FP8 {
+	q:=NewBIGints(Modulus)
+	//r:=NewBIGints(CURVE_Order)
+	f:=NewFP2bigs(NewBIGints(Fra),NewBIGints(Frb))
+
+	m:=NewBIGcopy(q)
+	m.Mod(r)
+
+	a:=NewBIGcopy(e)
+	a.Mod(m)
+
+	b:=NewBIGcopy(e)
+	b.div(m)
+
+	g1:=NewFP24copy(F);
+	c:=g1.trace()
+
+	if b.iszilch() {
+		c=c.xtr_pow(e)
+		return c
+	}
+
+	g2:=NewFP24copy(F)
+	g2.frob(f,1)
+	cp:=g2.trace()
+
+	g1.conj()
+	g2.Mul(g1)
+	cpm1:=g2.trace()
+	g2.Mul(g1)
+	cpm2:=g2.trace()
+
+	c=c.xtr_pow2(cp,cpm1,cpm2,a,b)
+	return c
+}
+
+/* p=q0^u0.q1^u1.q2^u2.q3^u3.. */
+// Bos & Costello https://eprint.iacr.org/2013/458.pdf
+// Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
+// Side channel attack secure 
+
+func pow8(q []*FP24,u []*BIG) *FP24 {
+	var g1 []*FP24
+	var g2 []*FP24
+	var w1 [NLEN*int(BASEBITS)+1]int8
+	var s1 [NLEN*int(BASEBITS)+1]int8
+	var w2 [NLEN*int(BASEBITS)+1]int8
+	var s2 [NLEN*int(BASEBITS)+1]int8
+	var t []*BIG
+	r:=NewFP24int(0)
+	p:=NewFP24int(0)
+	mt:=NewBIGint(0)
+	var bt int8
+	var k int
+
+	for i:=0;i<8;i++ {
+		t=append(t,NewBIGcopy(u[i]))
+	}
+
+	g1=append(g1,NewFP24copy(q[0]))	// q[0]
+	g1=append(g1,NewFP24copy(g1[0])); g1[1].Mul(q[1])	// q[0].q[1]
+	g1=append(g1,NewFP24copy(g1[0])); g1[2].Mul(q[2])	// q[0].q[2]
+	g1=append(g1,NewFP24copy(g1[1])); g1[3].Mul(q[2])	// q[0].q[1].q[2]
+	g1=append(g1,NewFP24copy(g1[0])); g1[4].Mul(q[3])	// q[0].q[3]
+	g1=append(g1,NewFP24copy(g1[1])); g1[5].Mul(q[3])	// q[0].q[1].q[3]
+	g1=append(g1,NewFP24copy(g1[2])); g1[6].Mul(q[3])	// q[0].q[2].q[3]
+	g1=append(g1,NewFP24copy(g1[3])); g1[7].Mul(q[3])	// q[0].q[1].q[2].q[3]
+
+	Fra:=NewBIGints(Fra)
+	Frb:=NewBIGints(Frb)
+	X:=NewFP2bigs(Fra,Frb)	
+
+// Use Frobenius
+	for i:=0;i<8;i++ {
+		g2=append(g2,NewFP24copy(g1[i])); g2[i].frob(X,4)		
+	}
+
+// Make them odd
+	pb1:=1-t[0].parity()
+	t[0].inc(pb1)
+//	t[0].norm();
+
+	pb2:=1-t[4].parity()
+	t[4].inc(pb2)
+//	t[4].norm();
+
+// Number of bits
+	mt.zero()
+	for i:=0;i<8;i++ {
+		t[i].norm()
+		mt.or(t[i])
+	}
+
+	nb:=1+mt.nbits();
+	
+// Sign pivot 
+	s1[nb-1]=1
+	s2[nb-1]=1
+	for i:=0;i<nb-1;i++ {
+		t[0].fshr(1)
+		s1[i]=2*int8(t[0].parity())-1
+		t[4].fshr(1)
+		s2[i]=2*int8(t[4].parity())-1
+
+	}
+
+// Recoded exponents
+	for i:=0; i<nb; i++ {
+		w1[i]=0
+		k=1
+		for j:=1; j<4; j++ {
+			bt=s1[i]*int8(t[j].parity())
+			t[j].fshr(1)
+			t[j].dec(int(bt)>>1)
+			t[j].norm()
+			w1[i]+=bt*int8(k)
+			k*=2
+		}
+		w2[i]=0
+		k=1
+		for j:=5; j<8; j++ {
+			bt=s2[i]*int8(t[j].parity())
+			t[j].fshr(1)
+			t[j].dec(int(bt)>>1)
+			t[j].norm()
+			w2[i]+=bt*int8(k)
+			k*=2
+		}
+	}
+// Main loop
+	p.selector(g1,int32(2*w1[nb-1]+1))  
+	r.selector(g2,int32(2*w2[nb-1]+1)) 
+	p.Mul(r)
+	for i:=nb-2;i>=0;i-- {
+		p.usqr()
+		r.selector(g1,int32(2*w1[i]+s1[i]))
+		p.Mul(r)
+		r.selector(g2,int32(2*w2[i]+s2[i]))
+		p.Mul(r)
+	}
+
+// apply correction
+	r.Copy(q[0]); r.conj()   
+	r.Mul(p)
+	p.cmove(r,pb1)
+	r.Copy(q[4]); r.conj()   
+	r.Mul(p)
+	p.cmove(r,pb2)
+
+	p.reduce()
+	return p;
+}
+
+/*
+func pow4(q []*FP12,u []*BIG) *FP12 {
+	var a [4]int8
+	var g []*FP12
+	var s []*FP12
+	c:=NewFP12int(1)
+	p:=NewFP12int(0)
+	var w [NLEN*int(BASEBITS)+1]int8
+	var t []*BIG
+	mt:=NewBIGint(0)
+
+	for i:=0;i<4;i++ {
+		t=append(t,NewBIGcopy(u[i]))
+	}
+
+	s=append(s,NewFP12int(0))
+	s=append(s,NewFP12int(0))
+
+	g=append(g,NewFP12copy(q[0])); s[0].Copy(q[1]); s[0].conj(); g[0].Mul(s[0])
+	g=append(g,NewFP12copy(g[0]))
+	g=append(g,NewFP12copy(g[0]))
+	g=append(g,NewFP12copy(g[0]))
+	g=append(g,NewFP12copy(q[0])); g[4].Mul(q[1])
+	g=append(g,NewFP12copy(g[4]))
+	g=append(g,NewFP12copy(g[4]))
+	g=append(g,NewFP12copy(g[4]))
+
+	s[1].Copy(q[2]); s[0].Copy(q[3]); s[0].conj(); s[1].Mul(s[0])
+	s[0].Copy(s[1]); s[0].conj(); g[1].Mul(s[0])
+	g[2].Mul(s[1])
+	g[5].Mul(s[0])
+	g[6].Mul(s[1])
+	s[1].Copy(q[2]); s[1].Mul(q[3])
+	s[0].Copy(s[1]); s[0].conj(); g[0].Mul(s[0])
+	g[3].Mul(s[1])
+	g[4].Mul(s[0])
+	g[7].Mul(s[1])
+
+// if power is even add 1 to power, and add q to correction 
+
+	for i:=0;i<4;i++ {
+		if t[i].parity()==0 {
+			t[i].inc(1); t[i].norm()
+			c.Mul(q[i])
+		}
+		mt.add(t[i]); mt.norm()
+	}
+	c.conj()
+	nb:=1+mt.nbits()
+
+// convert exponent to signed 1-bit window 
+	for j:=0;j<nb;j++ {
+		for i:=0;i<4;i++ {
+			a[i]=int8(t[i].lastbits(2)-2)
+			t[i].dec(int(a[i])); t[i].norm();
+			t[i].fshr(1)
+		}
+		w[j]=(8*a[0]+4*a[1]+2*a[2]+a[3])
+	}
+	w[nb]=int8(8*t[0].lastbits(2)+4*t[1].lastbits(2)+2*t[2].lastbits(2)+t[3].lastbits(2))
+	p.Copy(g[(w[nb]-1)/2])
+
+	for i:=nb-1;i>=0;i-- {
+		m:=w[i]>>7
+		j:=(w[i]^m)-m  // j=abs(w[i]) 
+		j=(j-1)/2
+		s[0].Copy(g[j]); s[1].Copy(g[j]); s[1].conj()
+		p.usqr()
+		p.Mul(s[m&1]);
+	}
+	p.Mul(c)  // apply correction 
+	p.reduce()
+	return p;
+}
+*/
+
diff --git a/version3/go/FP4.go b/version3/go/FP4.go
new file mode 100644
index 0000000..cbbe5c5
--- /dev/null
+++ b/version3/go/FP4.go
@@ -0,0 +1,590 @@
+/*
+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.
+*/
+
+/* Finite Field arithmetic  Fp^4 functions */
+
+/* FP4 elements are of the form a+ib, where i is sqrt(-1+sqrt(-1)) */
+
+package XXX
+
+//import "fmt"
+
+type FP4 struct {
+	a *FP2
+	b *FP2
+}
+
+/* Constructors */
+func NewFP4int(a int) *FP4 {
+	F:=new(FP4)
+	F.a=NewFP2int(a)
+	F.b=NewFP2int(0)
+	return F
+}
+
+func NewFP4copy(x *FP4) *FP4 {
+	F:=new(FP4)
+	F.a=NewFP2copy(x.a)
+	F.b=NewFP2copy(x.b)
+	return F
+}
+
+func NewFP4fp2s(c *FP2,d *FP2) *FP4 {
+	F:=new(FP4)
+	F.a=NewFP2copy(c)
+	F.b=NewFP2copy(d)
+	return F
+}
+
+func NewFP4fp2(c *FP2) *FP4 {
+	F:=new(FP4)
+	F.a=NewFP2copy(c)
+	F.b=NewFP2int(0)
+	return F
+}
+
+/* reduce all components of this mod Modulus */
+func (F *FP4) reduce() {
+	F.a.reduce()
+	F.b.reduce()
+}
+
+/* normalise all components of this mod Modulus */
+func (F *FP4) norm() {
+	F.a.norm()
+	F.b.norm()
+}
+
+/* test this==0 ? */
+func (F *FP4) iszilch() bool {
+	//F.reduce()
+	return F.a.iszilch() && F.b.iszilch()
+}
+
+/* Conditional move */
+func (F *FP4) cmove(g *FP4,d int) {
+	F.a.cmove(g.a,d)
+	F.b.cmove(g.b,d)
+}
+
+/* test this==1 ? */
+func (F *FP4) isunity() bool {
+	one:=NewFP2int(1)
+	return F.a.Equals(one) && F.b.iszilch()
+}
+
+/* test is w real? That is in a+ib test b is zero */
+func (F *FP4) isreal() bool {
+	return F.b.iszilch()
+}
+/* extract real part a */
+func (F *FP4) real() *FP2 {
+	return F.a
+}
+
+func (F *FP4) geta() *FP2 {
+	return F.a
+}
+/* extract imaginary part b */
+func (F *FP4) getb() *FP2 {
+	return F.b
+}
+/* test this=x? */
+func (F *FP4) Equals(x *FP4) bool {
+	return (F.a.Equals(x.a) && F.b.Equals(x.b))
+}
+
+/* copy this=x */
+func (F *FP4) copy(x *FP4) {
+	F.a.copy(x.a)
+	F.b.copy(x.b)
+}
+/* set this=0 */
+func (F *FP4) zero() {
+	F.a.zero()
+	F.b.zero()
+	}
+/* set this=1 */
+func (F *FP4) one() {
+	F.a.one()
+	F.b.zero()
+}
+
+/* set this=-this */
+func (F *FP4) neg() {
+	F.norm()
+	m:=NewFP2copy(F.a);
+	t:=NewFP2int(0)
+	m.add(F.b)
+	m.neg()
+	//m.norm()
+	t.copy(m); t.add(F.b)
+	F.b.copy(m)
+	F.b.add(F.a)
+	F.a.copy(t)
+	F.norm()
+}
+
+/* this=conjugate(this) */
+func (F *FP4) conj() {
+	F.b.neg(); F.norm()
+}
+
+/* this=-conjugate(this) */
+func (F *FP4) nconj() {
+	F.a.neg(); F.norm()
+}
+
+/* this+=x */
+func (F *FP4) add(x *FP4) {
+	F.a.add(x.a)
+	F.b.add(x.b)
+}
+/* this-=x */
+func (F *FP4) sub(x *FP4) {
+	m:=NewFP4copy(x)
+	m.neg()
+	F.add(m)
+}
+
+/* this-=x */
+func (F *FP4) rsub(x *FP4) {
+	F.neg()
+	F.add(x)
+}
+
+/* this*=s where s is FP2 */
+func (F *FP4) pmul(s *FP2) {
+	F.a.mul(s)
+	F.b.mul(s)
+}
+
+/* this*=s where s is FP2 */
+func (F *FP4) qmul(s *FP) {
+	F.a.pmul(s)
+	F.b.pmul(s)
+}
+
+/* this*=c where c is int */
+func (F *FP4) imul(c int) {
+	F.a.imul(c)
+	F.b.imul(c)
+}
+
+/* this*=this */	
+func (F *FP4) sqr() {
+//	F.norm()
+
+	t1:=NewFP2copy(F.a)
+	t2:=NewFP2copy(F.b)
+	t3:=NewFP2copy(F.a)
+
+	t3.mul(F.b)
+	t1.add(F.b)
+	t2.mul_ip()
+
+	t2.add(F.a)
+
+	t1.norm(); t2.norm()
+
+	F.a.copy(t1)
+
+	F.a.mul(t2)
+
+	t2.copy(t3)
+	t2.mul_ip()
+	t2.add(t3); t2.norm()
+	t2.neg()
+	F.a.add(t2)
+
+	F.b.copy(t3)
+	F.b.add(t3)
+
+	F.norm()
+}
+
+/* this*=y */
+func (F *FP4) mul(y *FP4) {
+//	F.norm()
+
+	t1:=NewFP2copy(F.a)
+	t2:=NewFP2copy(F.b)
+	t3:=NewFP2int(0)
+	t4:=NewFP2copy(F.b)
+
+	t1.mul(y.a)
+	t2.mul(y.b)
+	t3.copy(y.b)
+	t3.add(y.a)
+	t4.add(F.a)
+
+	t3.norm(); t4.norm();
+
+	t4.mul(t3)
+
+	t3.copy(t1)
+	t3.neg()
+	t4.add(t3)
+	t4.norm()
+
+	t3.copy(t2);
+	t3.neg()
+	F.b.copy(t4)
+	F.b.add(t3)
+
+	t2.mul_ip()
+	F.a.copy(t2)
+	F.a.add(t1)
+
+	F.norm()
+}
+
+/* convert this to hex string */
+func (F *FP4) toString() string {
+	return ("["+F.a.toString()+","+F.b.toString()+"]")
+}
+
+/* this=1/this */
+func (F *FP4) inverse() {
+//	F.norm()
+
+	t1:=NewFP2copy(F.a)
+	t2:=NewFP2copy(F.b)
+
+	t1.sqr()
+	t2.sqr()
+	t2.mul_ip(); t2.norm()
+	t1.sub(t2)
+	t1.inverse()
+	F.a.mul(t1)
+	t1.neg(); t1.norm()
+	F.b.mul(t1)
+}
+
+/* this*=i where i = sqrt(-1+sqrt(-1)) */
+func (F *FP4) times_i() {
+//	F.norm()
+	s:=NewFP2copy(F.b)
+	t:=NewFP2copy(F.b)
+	s.times_i()
+	t.add(s)
+//	t.norm();
+	F.b.copy(F.a)
+	F.a.copy(t)
+	F.norm()
+}
+
+/* this=this^p using Frobenius */
+func (F *FP4) frob(f *FP2) {
+	F.a.conj()
+	F.b.conj()
+	F.b.mul(f)
+}
+
+/* this=this^e */
+func (F *FP4) pow(e *BIG) *FP4 {
+	w:=NewFP4copy(F)
+	w.norm()
+	z:=NewBIGcopy(e)
+	r:=NewFP4int(1)
+	z.norm()
+	for true {
+		bt:=z.parity()
+		z.fshr(1)
+		if bt==1 {r.mul(w)}
+		if z.iszilch() {break}
+		w.sqr()
+	}
+	r.reduce()
+	return r
+}
+
+/* XTR xtr_a function */
+func (F *FP4) xtr_A(w *FP4,y *FP4,z *FP4) {
+	r:=NewFP4copy(w)
+	t:=NewFP4copy(w)
+	//y.norm()
+	r.sub(y); r.norm()
+	r.pmul(F.a)
+	t.add(y); t.norm()
+	t.pmul(F.b)
+	t.times_i()
+
+	F.copy(r)
+	F.add(t)
+	F.add(z)
+
+	F.norm()
+}
+
+/* XTR xtr_d function */
+func (F *FP4) xtr_D() {
+	w:=NewFP4copy(F)
+	F.sqr(); w.conj()
+	w.add(w); w.norm()
+	F.sub(w)
+	F.reduce()
+}
+
+/* r=x^n using XTR method on traces of FP12s */
+func (F *FP4) xtr_pow(n *BIG) *FP4 {
+	a:=NewFP4int(3)
+	b:=NewFP4copy(F)
+	c:=NewFP4copy(b)
+	c.xtr_D()
+	t:=NewFP4int(0)
+	r:=NewFP4int(0)
+	sf:=NewFP4copy(F)
+	sf.norm()
+
+	//n.norm()
+	par:=n.parity()
+	v:=NewBIGcopy(n); v.norm(); v.fshr(1)
+	if (par==0) {v.dec(1); v.norm()}
+
+	nb:=v.nbits();
+	for i:=nb-1;i>=0;i-- {
+		if v.bit(i)!=1 {
+			t.copy(b)
+			sf.conj()
+			c.conj()
+			b.xtr_A(a,sf,c)
+			sf.conj()
+			c.copy(t)
+			c.xtr_D()
+			a.xtr_D()
+		} else {
+			t.copy(a); t.conj()
+			a.copy(b)
+			a.xtr_D()
+			b.xtr_A(c,sf,t)
+			c.xtr_D()
+		}
+	}
+	if par==0 {
+		r.copy(c)
+	} else {r.copy(b)}
+	r.reduce()
+	return r
+}
+
+/* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */
+func (F *FP4) xtr_pow2(ck *FP4,ckml *FP4,ckm2l *FP4,a *BIG,b *BIG) *FP4 {
+
+	e:=NewBIGcopy(a)
+	d:=NewBIGcopy(b)
+	w:=NewBIGint(0)
+	e.norm(); d.norm()
+
+	cu:=NewFP4copy(ck)  // can probably be passed in w/o copying
+	cv:=NewFP4copy(F);
+	cumv:=NewFP4copy(ckml)
+	cum2v:=NewFP4copy(ckm2l)
+	r:=NewFP4int(0)
+	t:=NewFP4int(0)
+
+	f2:=0
+	for (d.parity()==0 && e.parity()==0) {
+		d.fshr(1)
+		e.fshr(1)
+		f2++
+	}
+
+	for Comp(d,e)!=0 {
+		if Comp(d,e)>0 {
+			w.copy(e); w.imul(4); w.norm()
+			if Comp(d,w)<=0 {
+				w.copy(d); d.copy(e)
+				e.rsub(w); e.norm()
+
+				t.copy(cv);
+				t.xtr_A(cu,cumv,cum2v)
+				cum2v.copy(cumv);
+				cum2v.conj()
+				cumv.copy(cv)
+				cv.copy(cu)
+				cu.copy(t)
+			} else {
+					if (d.parity()==0) {
+					d.fshr(1)
+					r.copy(cum2v); r.conj()
+					t.copy(cumv)
+					t.xtr_A(cu,cv,r)
+					cum2v.copy(cumv)
+					cum2v.xtr_D()
+					cumv.copy(t)
+					cu.xtr_D()
+				} else {
+					if (e.parity()==1) {
+						d.sub(e); d.norm()
+						d.fshr(1)
+						t.copy(cv)
+						t.xtr_A(cu,cumv,cum2v)
+						cu.xtr_D()
+						cum2v.copy(cv)
+						cum2v.xtr_D()
+						cum2v.conj()
+						cv.copy(t)
+					} else {
+						w.copy(d)
+						d.copy(e); d.fshr(1)
+						e.copy(w)
+						t.copy(cumv)
+						t.xtr_D()
+						cumv.copy(cum2v); cumv.conj()
+						cum2v.copy(t); cum2v.conj()
+						t.copy(cv)
+						t.xtr_D()
+						cv.copy(cu)
+						cu.copy(t)
+					}
+				}
+			}
+		}
+		if Comp(d,e)<0 {
+			w.copy(d); w.imul(4); w.norm()
+			if Comp(e,w)<=0 {
+				e.sub(d); e.norm()
+				t.copy(cv)
+				t.xtr_A(cu,cumv,cum2v)
+				cum2v.copy(cumv)
+				cumv.copy(cu)
+				cu.copy(t)
+			} else {
+				if (e.parity()==0) {
+					w.copy(d)
+					d.copy(e); d.fshr(1)
+					e.copy(w)
+					t.copy(cumv)
+					t.xtr_D()
+					cumv.copy(cum2v); cumv.conj()
+					cum2v.copy(t); cum2v.conj()
+					t.copy(cv)
+					t.xtr_D()
+					cv.copy(cu)
+					cu.copy(t)
+				} else {
+					if (d.parity()==1) {
+						w.copy(e)
+						e.copy(d)
+						w.sub(d); w.norm()
+						d.copy(w); d.fshr(1)
+						t.copy(cv)
+						t.xtr_A(cu,cumv,cum2v)
+						cumv.conj()
+						cum2v.copy(cu)
+						cum2v.xtr_D()
+						cum2v.conj()
+						cu.copy(cv)
+						cu.xtr_D()
+						cv.copy(t)
+					} else {
+						d.fshr(1)
+						r.copy(cum2v); r.conj()
+						t.copy(cumv)
+						t.xtr_A(cu,cv,r)
+						cum2v.copy(cumv)
+						cum2v.xtr_D()
+						cumv.copy(t)
+						cu.xtr_D()
+					}
+				}
+			}
+		}
+	}
+	r.copy(cv)
+	r.xtr_A(cu,cumv,cum2v)
+	for i:=0;i<f2;i++ {r.xtr_D()}
+	r=r.xtr_pow(d)
+	return r
+}
+
+/* this/=2 */
+func (F *FP4) div2() {
+	F.a.div2()
+	F.b.div2()
+}
+
+func (F *FP4) div_i() {
+	u:=NewFP2copy(F.a)
+	v:=NewFP2copy(F.b)
+	u.div_ip()
+	F.a.copy(v)
+	F.b.copy(u)
+}	
+
+func (F *FP4) div_2i() {
+	u:=NewFP2copy(F.a)
+	v:=NewFP2copy(F.b)
+	u.div_ip2()
+	v.add(v); v.norm()
+	F.a.copy(v)
+	F.b.copy(u)
+}
+
+/* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */
+/* returns true if this is QR */
+func (F *FP4) sqrt() bool {
+	if F.iszilch() {return true}
+
+	a:=NewFP2copy(F.a)
+	s:=NewFP2copy(F.b)
+	t:=NewFP2copy(F.a)
+
+	if s.iszilch() {
+		if t.sqrt() {
+			F.a.copy(t)
+			F.b.zero()
+		} else {
+			t.div_ip()
+			t.sqrt()
+			F.b.copy(t)
+			F.a.zero()
+		}
+		return true
+	}
+	s.sqr()
+	a.sqr()
+	s.mul_ip()
+	s.norm()
+	a.sub(s)
+
+	s.copy(a)
+	if !s.sqrt() {
+		return false
+	}
+
+	a.copy(t); a.add(s); a.norm(); a.div2()
+
+	if !a.sqrt() {
+		a.copy(t); a.sub(s); a.norm(); a.div2()
+		if !a.sqrt() {
+			return false
+		}
+	}
+	t.copy(F.b)
+	s.copy(a); s.add(a)
+	s.inverse()
+
+	t.mul(s)
+	F.a.copy(a)
+	F.b.copy(t)
+
+	return true
+}
diff --git a/version3/go/FP48.go b/version3/go/FP48.go
new file mode 100644
index 0000000..f1c566f
--- /dev/null
+++ b/version3/go/FP48.go
@@ -0,0 +1,998 @@
+/*
+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.
+*/
+
+/* MiotCL Fp^12 functions */
+/* FP12 elements are of the form a+i.b+i^2.c */
+
+package XXX
+
+//import "fmt"
+
+type FP48 struct {
+	a *FP16
+	b *FP16
+	c *FP16
+}
+
+/* Constructors */
+func NewFP48fp16(d *FP16) *FP48 {
+	F:=new(FP48)
+	F.a=NewFP16copy(d)
+	F.b=NewFP16int(0)
+	F.c=NewFP16int(0)
+	return F
+}
+
+func NewFP48int(d int) *FP48 {
+	F:=new(FP48)
+	F.a=NewFP16int(d)
+	F.b=NewFP16int(0)
+	F.c=NewFP16int(0)
+	return F
+}
+
+func NewFP48fp16s(d *FP16,e *FP16,f *FP16) *FP48 {
+	F:=new(FP48)
+	F.a=NewFP16copy(d)
+	F.b=NewFP16copy(e)
+	F.c=NewFP16copy(f)
+	return F
+}
+
+func NewFP48copy(x *FP48) *FP48 {
+	F:=new(FP48)
+	F.a=NewFP16copy(x.a)
+	F.b=NewFP16copy(x.b)
+	F.c=NewFP16copy(x.c)
+	return F
+}
+
+/* reduce all components of this mod Modulus */
+func (F *FP48) reduce() {
+	F.a.reduce()
+	F.b.reduce()
+	F.c.reduce()
+}
+/* normalise all components of this */
+func (F *FP48) norm() {
+	F.a.norm()
+	F.b.norm()
+	F.c.norm()
+}
+/* test x==0 ? */
+func (F *FP48) iszilch() bool {
+	//F.reduce()
+	return (F.a.iszilch() && F.b.iszilch() && F.c.iszilch())
+}
+
+/* Conditional move */
+func (F *FP48) cmove(g *FP48,d int) {
+	F.a.cmove(g.a,d)
+	F.b.cmove(g.b,d)
+	F.c.cmove(g.c,d)
+}
+
+/* Constant time select from pre-computed table */
+func (F *FP48) selector(g []*FP48,b int32) {
+
+	m:=b>>31
+	babs:=(b^m)-m
+
+	babs=(babs-1)/2
+
+	F.cmove(g[0],teq(babs,0))  // conditional move
+	F.cmove(g[1],teq(babs,1))
+	F.cmove(g[2],teq(babs,2))
+	F.cmove(g[3],teq(babs,3))
+	F.cmove(g[4],teq(babs,4))
+	F.cmove(g[5],teq(babs,5))
+	F.cmove(g[6],teq(babs,6))
+	F.cmove(g[7],teq(babs,7))
+ 
+ 	invF:=NewFP48copy(F) 
+	invF.conj()
+	F.cmove(invF,int(m&1))
+}
+
+/* test x==1 ? */
+func (F *FP48) Isunity() bool {
+	one:=NewFP16int(1)
+	return (F.a.Equals(one) && F.b.iszilch() && F.c.iszilch())
+}
+/* return 1 if x==y, else 0 */
+func (F *FP48) Equals(x *FP48) bool {
+	return (F.a.Equals(x.a) && F.b.Equals(x.b) && F.c.Equals(x.c))
+}
+
+/* extract a from this */
+func (F *FP48) geta() *FP16 {
+	return F.a
+}
+/* extract b */
+func (F *FP48) getb() *FP16 {
+	return F.b
+}
+/* extract c */
+func (F *FP48) getc() *FP16 {
+	return F.c
+}
+/* copy this=x */
+func (F *FP48) Copy(x *FP48) {
+	F.a.copy(x.a)
+	F.b.copy(x.b)
+	F.c.copy(x.c)
+}
+/* set this=1 */
+func (F *FP48) one() {
+	F.a.one()
+	F.b.zero()
+	F.c.zero()
+}
+/* this=conj(this) */
+func (F *FP48) conj() {
+	F.a.conj()
+	F.b.nconj()
+	F.c.conj()
+}
+
+/* Granger-Scott Unitary Squaring */
+func (F *FP48) usqr() {
+	A:=NewFP16copy(F.a)
+	B:=NewFP16copy(F.c)
+	C:=NewFP16copy(F.b)
+	D:=NewFP16int(0)
+
+	F.a.sqr()
+	D.copy(F.a); D.add(F.a)
+	F.a.add(D)
+
+	F.a.norm();
+	A.nconj()
+
+	A.add(A)
+	F.a.add(A)
+	B.sqr()
+	B.times_i()
+
+	D.copy(B); D.add(B)
+	B.add(D)
+	B.norm();
+
+	C.sqr()
+	D.copy(C); D.add(C)
+	C.add(D)
+	C.norm();
+
+	F.b.conj()
+	F.b.add(F.b)
+	F.c.nconj()
+
+	F.c.add(F.c)
+	F.b.add(B)
+	F.c.add(C)
+	F.reduce()
+
+}
+
+/* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
+func (F *FP48)  sqr() {
+	A:=NewFP16copy(F.a)
+	B:=NewFP16copy(F.b)
+	C:=NewFP16copy(F.c)
+	D:=NewFP16copy(F.a)
+
+	A.sqr()
+	B.mul(F.c)
+	B.add(B); B.norm()
+	C.sqr()
+	D.mul(F.b)
+	D.add(D)
+
+	F.c.add(F.a)
+	F.c.add(F.b); F.c.norm()
+	F.c.sqr()
+
+	F.a.copy(A)
+
+	A.add(B)
+	A.norm();
+	A.add(C)
+	A.add(D)
+	A.norm();
+
+	A.neg()
+	B.times_i();
+	C.times_i()
+
+	F.a.add(B)
+
+	F.b.copy(C); F.b.add(D)
+	F.c.add(A)
+	F.norm()
+}
+
+/* FP48 full multiplication this=this*y */
+func (F *FP48) Mul(y *FP48) {
+	z0:=NewFP16copy(F.a)
+	z1:=NewFP16int(0)
+	z2:=NewFP16copy(F.b)
+	z3:=NewFP16int(0)
+	t0:=NewFP16copy(F.a)
+	t1:=NewFP16copy(y.a)
+
+	z0.mul(y.a)
+	z2.mul(y.b)
+
+	t0.add(F.b); t0.norm()
+	t1.add(y.b); t1.norm() 
+
+	z1.copy(t0); z1.mul(t1)
+	t0.copy(F.b); t0.add(F.c); t0.norm()
+
+	t1.copy(y.b); t1.add(y.c); t1.norm()
+	z3.copy(t0); z3.mul(t1)
+
+	t0.copy(z0); t0.neg()
+	t1.copy(z2); t1.neg()
+
+	z1.add(t0)
+	//z1.norm();
+	F.b.copy(z1); F.b.add(t1)
+
+	z3.add(t1)
+	z2.add(t0)
+
+	t0.copy(F.a); t0.add(F.c); t0.norm()
+	t1.copy(y.a); t1.add(y.c); t1.norm()
+	t0.mul(t1)
+	z2.add(t0)
+
+	t0.copy(F.c); t0.mul(y.c)
+	t1.copy(t0); t1.neg()
+
+	F.c.copy(z2); F.c.add(t1)
+	z3.add(t1)
+	t0.times_i()
+	F.b.add(t0)
+	z3.norm()
+	z3.times_i()
+	F.a.copy(z0); F.a.add(z3)
+	F.norm()
+}
+
+/* Special case of multiplication arises from special form of ATE pairing line function */
+func (F *FP48) smul(y *FP48,twist int ) {
+	if twist==D_TYPE {
+		z0:=NewFP16copy(F.a)
+		z2:=NewFP16copy(F.b)
+		z3:=NewFP16copy(F.b)
+		t0:=NewFP16int(0)
+		t1:=NewFP16copy(y.a)
+		
+		z0.mul(y.a)
+		z2.pmul(y.b.real());
+		F.b.add(F.a)
+		t1.real().add(y.b.real())
+
+		t1.norm(); F.b.norm()
+		F.b.mul(t1)
+		z3.add(F.c); z3.norm()
+		z3.pmul(y.b.real())
+
+		t0.copy(z0); t0.neg()
+		t1.copy(z2); t1.neg()
+
+		F.b.add(t0)
+	//F.b.norm();
+
+		F.b.add(t1)
+		z3.add(t1); z3.norm()
+		z2.add(t0)
+
+		t0.copy(F.a); t0.add(F.c); t0.norm()
+		t0.mul(y.a)
+		F.c.copy(z2); F.c.add(t0)
+
+		z3.times_i()
+		F.a.copy(z0); F.a.add(z3)
+	}
+	if twist==M_TYPE {
+		z0:=NewFP16copy(F.a)
+		z1:=NewFP16int(0)
+		z2:=NewFP16int(0)
+		z3:=NewFP16int(0)
+		t0:=NewFP16copy(F.a)
+		t1:=NewFP16int(0)
+		
+		z0.mul(y.a)
+		t0.add(F.b)
+		t0.norm()
+
+		z1.copy(t0); z1.mul(y.a)
+		t0.copy(F.b); t0.add(F.c)
+		t0.norm()
+
+		z3.copy(t0) //z3.mul(y.c);
+		z3.pmul(y.c.getb())
+		z3.times_i()
+
+		t0.copy(z0); t0.neg()
+
+		z1.add(t0)
+		F.b.copy(z1) 
+		z2.copy(t0)
+
+		t0.copy(F.a); t0.add(F.c)
+		t1.copy(y.a); t1.add(y.c)
+
+		t0.norm()
+		t1.norm()
+	
+		t0.mul(t1)
+		z2.add(t0)
+
+		t0.copy(F.c)
+			
+		t0.pmul(y.c.getb())
+		t0.times_i()
+
+		t1.copy(t0); t1.neg()
+
+		F.c.copy(z2); F.c.add(t1)
+		z3.add(t1)
+		t0.times_i()
+		F.b.add(t0)
+		z3.norm()
+		z3.times_i()
+		F.a.copy(z0); F.a.add(z3)
+	}
+	F.norm()
+}
+
+/* this=1/this */
+func (F *FP48) Inverse() {
+	f0:=NewFP16copy(F.a)
+	f1:=NewFP16copy(F.b)
+	f2:=NewFP16copy(F.a)
+	f3:=NewFP16int(0)
+
+	F.norm()
+	f0.sqr()
+	f1.mul(F.c)
+	f1.times_i()
+	f0.sub(f1); f0.norm()
+
+	f1.copy(F.c); f1.sqr()
+	f1.times_i()
+	f2.mul(F.b)
+	f1.sub(f2); f1.norm()
+
+	f2.copy(F.b); f2.sqr()
+	f3.copy(F.a); f3.mul(F.c)
+	f2.sub(f3); f2.norm()
+
+	f3.copy(F.b); f3.mul(f2)
+	f3.times_i()
+	F.a.mul(f0)
+	f3.add(F.a)
+	F.c.mul(f1)
+	F.c.times_i()
+
+	f3.add(F.c); f3.norm()
+	f3.inverse()
+	F.a.copy(f0); F.a.mul(f3)
+	F.b.copy(f1); F.b.mul(f3)
+	F.c.copy(f2); F.c.mul(f3)
+}
+
+/* this=this^p using Frobenius */
+func (F *FP48) frob(f *FP2, n int) {
+	f2:=NewFP2copy(f)
+	f3:=NewFP2copy(f)
+
+	f2.sqr()
+	f3.mul(f2)
+
+	f3.mul_ip(); f3.norm()
+	f3.mul_ip(); f3.norm()
+
+	for i:=0;i<n;i++ {
+		F.a.frob(f3);
+		F.b.frob(f3);
+		F.c.frob(f3);
+
+		F.b.qmul(f); F.b.times_i4(); F.b.times_i2(); 
+		F.c.qmul(f2); F.c.times_i4(); F.c.times_i4(); F.c.times_i4()
+	}
+}
+
+/* trace function */
+func (F *FP48) trace() *FP16 {
+	t:=NewFP16int(0)
+	t.copy(F.a)
+	t.imul(3)
+	t.reduce()
+	return t;
+}
+
+/* convert from byte array to FP48 */
+func FP48_fromBytes(w []byte) *FP48 {
+	var t [int(MODBYTES)]byte
+	MB:=int(MODBYTES)
+
+	for i:=0;i<MB;i++ {t[i]=w[i]}
+	a:=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+MB]}
+	b:=FromBytes(t[:])
+	c:=NewFP2bigs(a,b)
+
+	for i:=0;i<MB;i++ {t[i]=w[i+2*MB]}
+	a=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+3*MB]}
+	b=FromBytes(t[:])
+	d:=NewFP2bigs(a,b)
+
+	ea:=NewFP4fp2s(c,d)
+
+	for i:=0;i<MB;i++ {t[i]=w[i+4*MB]}
+	a=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+5*MB]}
+	b=FromBytes(t[:])
+	c=NewFP2bigs(a,b)
+
+	for i:=0;i<MB;i++ {t[i]=w[i+6*MB]}
+	a=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+7*MB]}
+	b=FromBytes(t[:])
+	d=NewFP2bigs(a,b)
+
+	eb:=NewFP4fp2s(c,d)
+
+	e:=NewFP8fp4s(ea,eb)
+
+	for i:=0;i<MB;i++ {t[i]=w[i+8*MB]}
+	a=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+9*MB]}
+	b=FromBytes(t[:])
+	c=NewFP2bigs(a,b)
+
+	for i:=0;i<MB;i++ {t[i]=w[i+10*MB]}
+	a=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+11*MB]}
+	b=FromBytes(t[:])
+	d=NewFP2bigs(a,b)
+
+	ea=NewFP4fp2s(c,d)
+
+	for i:=0;i<MB;i++ {t[i]=w[i+12*MB]}
+	a=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+13*MB]}
+	b=FromBytes(t[:])
+	c=NewFP2bigs(a,b)
+
+	for i:=0;i<MB;i++ {t[i]=w[i+14*MB]}
+	a=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+15*MB]}
+	b=FromBytes(t[:])
+	d=NewFP2bigs(a,b)
+
+	eb=NewFP4fp2s(c,d)
+
+	f:=NewFP8fp4s(ea,eb)
+
+	g:=NewFP16fp8s(e,f)
+
+
+
+	for i:=0;i<MB;i++ {t[i]=w[i+16*MB]}
+	a=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+17*MB]}
+	b=FromBytes(t[:])
+	c=NewFP2bigs(a,b)
+
+	for i:=0;i<MB;i++ {t[i]=w[i+18*MB]}
+	a=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+19*MB]}
+	b=FromBytes(t[:])
+	d=NewFP2bigs(a,b)
+
+	ea=NewFP4fp2s(c,d)
+
+	for i:=0;i<MB;i++ {t[i]=w[i+20*MB]}
+	a=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+21*MB]}
+	b=FromBytes(t[:])
+	c=NewFP2bigs(a,b)
+
+	for i:=0;i<MB;i++ {t[i]=w[i+22*MB]}
+	a=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+23*MB]}
+	b=FromBytes(t[:])
+	d=NewFP2bigs(a,b)
+
+	eb=NewFP4fp2s(c,d)
+
+	e=NewFP8fp4s(ea,eb)
+
+	for i:=0;i<MB;i++ {t[i]=w[i+24*MB]}
+	a=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+25*MB]}
+	b=FromBytes(t[:])
+	c=NewFP2bigs(a,b)
+
+	for i:=0;i<MB;i++ {t[i]=w[i+26*MB]}
+	a=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+27*MB]}
+	b=FromBytes(t[:])
+	d=NewFP2bigs(a,b)
+
+	ea=NewFP4fp2s(c,d)
+
+	for i:=0;i<MB;i++ {t[i]=w[i+28*MB]}
+	a=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+29*MB]}
+	b=FromBytes(t[:])
+	c=NewFP2bigs(a,b)
+
+	for i:=0;i<MB;i++ {t[i]=w[i+30*MB]}
+	a=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+31*MB]}
+	b=FromBytes(t[:])
+	d=NewFP2bigs(a,b)
+
+	eb=NewFP4fp2s(c,d)
+
+	f=NewFP8fp4s(ea,eb)
+
+	h:=NewFP16fp8s(e,f)
+
+	for i:=0;i<MB;i++ {t[i]=w[i+32*MB]}
+	a=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+33*MB]}
+	b=FromBytes(t[:])
+	c=NewFP2bigs(a,b)
+
+	for i:=0;i<MB;i++ {t[i]=w[i+34*MB]}
+	a=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+35*MB]}
+	b=FromBytes(t[:])
+	d=NewFP2bigs(a,b)
+
+	ea=NewFP4fp2s(c,d)
+
+	for i:=0;i<MB;i++ {t[i]=w[i+36*MB]}
+	a=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+37*MB]}
+	b=FromBytes(t[:])
+	c=NewFP2bigs(a,b)
+
+	for i:=0;i<MB;i++ {t[i]=w[i+38*MB]}
+	a=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+39*MB]}
+	b=FromBytes(t[:])
+	d=NewFP2bigs(a,b)
+
+	eb=NewFP4fp2s(c,d)
+
+	e=NewFP8fp4s(ea,eb)
+
+	for i:=0;i<MB;i++ {t[i]=w[i+40*MB]}
+	a=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+41*MB]}
+	b=FromBytes(t[:])
+	c=NewFP2bigs(a,b)
+
+	for i:=0;i<MB;i++ {t[i]=w[i+42*MB]}
+	a=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+43*MB]}
+	b=FromBytes(t[:])
+	d=NewFP2bigs(a,b)
+
+	ea=NewFP4fp2s(c,d)
+
+	for i:=0;i<MB;i++ {t[i]=w[i+44*MB]}
+	a=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+45*MB]}
+	b=FromBytes(t[:])
+	c=NewFP2bigs(a,b)
+
+	for i:=0;i<MB;i++ {t[i]=w[i+46*MB]}
+	a=FromBytes(t[:])
+	for i:=0;i<MB;i++ {t[i]=w[i+47*MB]}
+	b=FromBytes(t[:])
+	d=NewFP2bigs(a,b)
+
+	eb=NewFP4fp2s(c,d)
+
+	f=NewFP8fp4s(ea,eb)
+
+	i:=NewFP16fp8s(e,f)
+
+	return NewFP48fp16s(g,h,i)
+}
+
+/* convert this to byte array */
+func (F *FP48) ToBytes(w []byte) {
+	var t [int(MODBYTES)]byte
+	MB:=int(MODBYTES)
+	F.a.a.a.geta().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i]=t[i]}
+	F.a.a.a.geta().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+MB]=t[i]}
+	F.a.a.a.getb().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+2*MB]=t[i]}
+	F.a.a.a.getb().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+3*MB]=t[i]}
+	F.a.a.b.geta().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+4*MB]=t[i]}
+	F.a.a.b.geta().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+5*MB]=t[i]}
+	F.a.a.b.getb().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+6*MB]=t[i]}
+	F.a.a.b.getb().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+7*MB]=t[i]}
+
+	F.a.b.a.geta().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+8*MB]=t[i]}
+	F.a.b.a.geta().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+9*MB]=t[i]}
+	F.a.b.a.getb().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+10*MB]=t[i]}
+	F.a.b.a.getb().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+11*MB]=t[i]}
+	F.a.b.b.geta().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+12*MB]=t[i]}
+	F.a.b.b.geta().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+13*MB]=t[i]}
+	F.a.b.b.getb().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+14*MB]=t[i]}
+	F.a.b.b.getb().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+15*MB]=t[i]}
+
+
+	F.b.a.a.geta().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+16*MB]=t[i]}
+	F.b.a.a.geta().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+17*MB]=t[i]}
+	F.b.a.a.getb().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+18*MB]=t[i]}
+	F.b.a.a.getb().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+19*MB]=t[i]}
+	F.b.a.b.geta().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+20*MB]=t[i]}
+	F.b.a.b.geta().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+21*MB]=t[i]}
+	F.b.a.b.getb().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+22*MB]=t[i]}
+	F.b.a.b.getb().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+23*MB]=t[i]}
+
+	F.b.b.a.geta().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+24*MB]=t[i]}
+	F.b.b.a.geta().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+25*MB]=t[i]}
+	F.b.b.a.getb().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+26*MB]=t[i]}
+	F.b.b.a.getb().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+27*MB]=t[i]}
+	F.b.b.b.geta().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+28*MB]=t[i]}
+	F.b.b.b.geta().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+29*MB]=t[i]}
+	F.b.b.b.getb().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+30*MB]=t[i]}
+	F.b.b.b.getb().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+31*MB]=t[i]}
+
+
+
+	F.c.a.a.geta().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+32*MB]=t[i]}
+	F.c.a.a.geta().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+33*MB]=t[i]}
+	F.c.a.a.getb().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+34*MB]=t[i]}
+	F.c.a.a.getb().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+35*MB]=t[i]}
+	F.c.a.b.geta().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+36*MB]=t[i]}
+	F.c.a.b.geta().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+37*MB]=t[i]}
+	F.c.a.b.getb().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+38*MB]=t[i]}
+	F.c.a.b.getb().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+39*MB]=t[i]}
+
+	F.c.b.a.geta().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+40*MB]=t[i]}
+	F.c.b.a.geta().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+41*MB]=t[i]}
+	F.c.b.a.getb().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+42*MB]=t[i]}
+	F.c.b.a.getb().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+43*MB]=t[i]}
+	F.c.b.b.geta().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+44*MB]=t[i]}
+	F.c.b.b.geta().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+45*MB]=t[i]}
+	F.c.b.b.getb().GetA().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+46*MB]=t[i]}
+	F.c.b.b.getb().GetB().ToBytes(t[:])
+	for i:=0;i<MB;i++ {w[i+47*MB]=t[i]}
+}
+
+/* convert to hex string */
+func (F *FP48) ToString() string {
+	return ("["+F.a.toString()+","+F.b.toString()+","+F.c.toString()+"]")
+}
+
+/* this=this^e */ 
+func (F *FP48) Pow(e *BIG) *FP48 {
+	sf:=NewFP48copy(F)
+	sf.norm()
+	e1:=NewBIGcopy(e)
+	e1.norm()
+	e3:=NewBIGcopy(e1)
+	e3.pmul(3)
+	e3.norm()
+
+	w:=NewFP48copy(sf)
+
+	nb:=e3.nbits()
+	for i:=nb-2;i>=1;i-- {
+		w.usqr()
+		bt:=e3.bit(i)-e1.bit(i)
+		if bt==1 {
+			w.Mul(sf)
+		}
+		if bt==-1 {
+			sf.conj()
+			w.Mul(sf)
+			sf.conj()	
+		}
+	}
+	w.reduce()
+	return w
+
+}
+
+/* constant time powering by small integer of max length bts */
+func (F *FP48) pinpow(e int,bts int) {
+	var R []*FP48
+	R=append(R,NewFP48int(1))
+	R=append(R,NewFP48copy(F))
+
+	for i:=bts-1;i>=0;i-- {
+		b:=(e>>uint(i))&1
+		R[1-b].Mul(R[b])
+		R[b].usqr()
+	}
+	F.Copy(R[0])
+}
+
+/* Fast compressed FP16 power of unitary FP48 */
+func (F *FP48) Compow(e *BIG,r *BIG) *FP16 {
+	q:=NewBIGints(Modulus)
+	f:=NewFP2bigs(NewBIGints(Fra),NewBIGints(Frb))
+
+	m:=NewBIGcopy(q)
+	m.Mod(r)
+
+	a:=NewBIGcopy(e)
+	a.Mod(m)
+
+	b:=NewBIGcopy(e)
+	b.div(m)
+
+	g1:=NewFP48copy(F);
+	c:=g1.trace()
+
+	if b.iszilch() {
+		c=c.xtr_pow(e)
+		return c
+	}
+
+	g2:=NewFP48copy(F)
+	g2.frob(f,1)
+	cp:=g2.trace()
+
+	g1.conj()
+	g2.Mul(g1)
+	cpm1:=g2.trace()
+	g2.Mul(g1)
+	cpm2:=g2.trace()
+
+	c=c.xtr_pow2(cp,cpm1,cpm2,a,b)
+	return c
+}
+
+
+/* p=q0^u0.q1^u1.q2^u2.q3^u3.. */
+// Bos & Costello https://eprint.iacr.org/2013/458.pdf
+// Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
+// Side channel attack secure 
+
+func pow16(q []*FP48,u []*BIG) *FP48 {
+	var g1 []*FP48
+	var g2 []*FP48
+	var g3 []*FP48
+	var g4 []*FP48
+	var w1 [NLEN*int(BASEBITS)+1]int8
+	var s1 [NLEN*int(BASEBITS)+1]int8
+	var w2 [NLEN*int(BASEBITS)+1]int8
+	var s2 [NLEN*int(BASEBITS)+1]int8
+	var w3 [NLEN*int(BASEBITS)+1]int8
+	var s3 [NLEN*int(BASEBITS)+1]int8
+	var w4 [NLEN*int(BASEBITS)+1]int8
+	var s4 [NLEN*int(BASEBITS)+1]int8
+	var t []*BIG
+	r:=NewFP48int(0)
+	p:=NewFP48int(0)
+	mt:=NewBIGint(0)
+	var bt int8
+	var k int
+
+	for i:=0;i<16;i++ {
+		t=append(t,NewBIGcopy(u[i]))
+	}
+
+	g1=append(g1,NewFP48copy(q[0]))	// q[0]
+	g1=append(g1,NewFP48copy(g1[0])); g1[1].Mul(q[1])	// q[0].q[1]
+	g1=append(g1,NewFP48copy(g1[0])); g1[2].Mul(q[2])	// q[0].q[2]
+	g1=append(g1,NewFP48copy(g1[1])); g1[3].Mul(q[2])	// q[0].q[1].q[2]
+	g1=append(g1,NewFP48copy(g1[0])); g1[4].Mul(q[3])	// q[0].q[3]
+	g1=append(g1,NewFP48copy(g1[1])); g1[5].Mul(q[3])	// q[0].q[1].q[3]
+	g1=append(g1,NewFP48copy(g1[2])); g1[6].Mul(q[3])	// q[0].q[2].q[3]
+	g1=append(g1,NewFP48copy(g1[3])); g1[7].Mul(q[3])	// q[0].q[1].q[2].q[3]
+
+	Fra:=NewBIGints(Fra)
+	Frb:=NewBIGints(Frb)
+	X:=NewFP2bigs(Fra,Frb)	
+
+// Use Frobenius
+	for i:=0;i<8;i++ {
+		g2=append(g2,NewFP48copy(g1[i])); g2[i].frob(X,4)	
+		g3=append(g3,NewFP48copy(g2[i])); g3[i].frob(X,4)	
+		g4=append(g4,NewFP48copy(g3[i])); g4[i].frob(X,4)			
+	}
+
+// Make them odd
+	pb1:=1-t[0].parity()
+	t[0].inc(pb1)
+//	t[0].norm();
+
+	pb2:=1-t[4].parity()
+	t[4].inc(pb2)
+//	t[4].norm();
+
+	pb3:=1-t[8].parity()
+	t[8].inc(pb3)
+//	t[8].norm();
+
+	pb4:=1-t[12].parity()
+	t[12].inc(pb4)
+//	t[12].norm();
+
+// Number of bits
+	mt.zero()
+	for i:=0;i<16;i++ {
+		t[i].norm()
+		mt.or(t[i])
+	}
+
+	nb:=1+mt.nbits();
+	
+// Sign pivot 
+	s1[nb-1]=1
+	s2[nb-1]=1
+	s3[nb-1]=1
+	s4[nb-1]=1
+	for i:=0;i<nb-1;i++ {
+		t[0].fshr(1)
+		s1[i]=2*int8(t[0].parity())-1
+		t[4].fshr(1)
+		s2[i]=2*int8(t[4].parity())-1
+		t[8].fshr(1)
+		s3[i]=2*int8(t[8].parity())-1
+		t[12].fshr(1)
+		s4[i]=2*int8(t[12].parity())-1
+
+	}
+
+// Recoded exponents
+	for i:=0; i<nb; i++ {
+		w1[i]=0
+		k=1
+		for j:=1; j<4; j++ {
+			bt=s1[i]*int8(t[j].parity())
+			t[j].fshr(1)
+			t[j].dec(int(bt)>>1)
+			t[j].norm()
+			w1[i]+=bt*int8(k)
+			k*=2
+		}
+		w2[i]=0
+		k=1
+		for j:=5; j<8; j++ {
+			bt=s2[i]*int8(t[j].parity())
+			t[j].fshr(1)
+			t[j].dec(int(bt)>>1)
+			t[j].norm()
+			w2[i]+=bt*int8(k)
+			k*=2
+		}
+		w3[i]=0
+		k=1
+		for j:=9; j<12; j++ {
+			bt=s3[i]*int8(t[j].parity())
+			t[j].fshr(1)
+			t[j].dec(int(bt)>>1)
+			t[j].norm()
+			w3[i]+=bt*int8(k)
+			k*=2
+		}
+		w4[i]=0
+		k=1
+		for j:=13; j<16; j++ {
+			bt=s4[i]*int8(t[j].parity())
+			t[j].fshr(1)
+			t[j].dec(int(bt)>>1)
+			t[j].norm()
+			w4[i]+=bt*int8(k)
+			k*=2
+		}
+	}
+
+// Main loop
+	p.selector(g1,int32(2*w1[nb-1]+1))  
+	r.selector(g2,int32(2*w2[nb-1]+1)) 
+	p.Mul(r)
+	r.selector(g3,int32(2*w3[nb-1]+1)) 
+	p.Mul(r)
+	r.selector(g4,int32(2*w4[nb-1]+1)) 
+	p.Mul(r)
+	for i:=nb-2;i>=0;i-- {
+		p.usqr()
+		r.selector(g1,int32(2*w1[i]+s1[i]))
+		p.Mul(r)
+		r.selector(g2,int32(2*w2[i]+s2[i]))
+		p.Mul(r)
+		r.selector(g3,int32(2*w3[i]+s3[i]))
+		p.Mul(r)
+		r.selector(g4,int32(2*w4[i]+s4[i]))
+		p.Mul(r)
+	}
+
+// apply correction
+	r.Copy(q[0]); r.conj()   
+	r.Mul(p)
+	p.cmove(r,pb1)
+	r.Copy(q[4]); r.conj()   
+	r.Mul(p)
+	p.cmove(r,pb2)
+	r.Copy(q[8]); r.conj()   
+	r.Mul(p)
+	p.cmove(r,pb3)
+	r.Copy(q[12]); r.conj()   
+	r.Mul(p)
+	p.cmove(r,pb4)
+
+	p.reduce()
+	return p;
+}
diff --git a/version3/go/FP8.go b/version3/go/FP8.go
new file mode 100644
index 0000000..a2c1e03
--- /dev/null
+++ b/version3/go/FP8.go
@@ -0,0 +1,606 @@
+/*
+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.
+*/
+
+/* Finite Field arithmetic  Fp^8 functions */
+
+/* FP4 elements are of the form a+ib, where i is sqrt(-1+sqrt(-1)) */
+
+package XXX
+
+//import "fmt"
+
+type FP8 struct {
+	a *FP4
+	b *FP4
+}
+
+/* Constructors */
+func NewFP8int(a int) *FP8 {
+	F:=new(FP8)
+	F.a=NewFP4int(a)
+	F.b=NewFP4int(0)
+	return F
+}
+
+func NewFP8copy(x *FP8) *FP8 {
+	F:=new(FP8)
+	F.a=NewFP4copy(x.a)
+	F.b=NewFP4copy(x.b)
+	return F
+}
+
+func NewFP8fp4s(c *FP4,d *FP4) *FP8 {
+	F:=new(FP8)
+	F.a=NewFP4copy(c)
+	F.b=NewFP4copy(d)
+	return F
+}
+
+func NewFP8fp4(c *FP4) *FP8 {
+	F:=new(FP8)
+	F.a=NewFP4copy(c)
+	F.b=NewFP4int(0)
+	return F
+}
+
+/* reduce all components of this mod Modulus */
+func (F *FP8) reduce() {
+	F.a.reduce()
+	F.b.reduce()
+}
+
+/* normalise all components of this mod Modulus */
+func (F *FP8) norm() {
+	F.a.norm()
+	F.b.norm()
+}
+
+/* test this==0 ? */
+func (F *FP8) iszilch() bool {
+	//F.reduce()
+	return F.a.iszilch() && F.b.iszilch()
+}
+
+/* Conditional move */
+func (F *FP8) cmove(g *FP8,d int) {
+	F.a.cmove(g.a,d)
+	F.b.cmove(g.b,d)
+}
+
+/* test this==1 ? */
+func (F *FP8) isunity() bool {
+	one:=NewFP4int(1)
+	return F.a.Equals(one) && F.b.iszilch()
+}
+
+/* test is w real? That is in a+ib test b is zero */
+func (F *FP8) isreal() bool {
+	return F.b.iszilch()
+}
+/* extract real part a */
+func (F *FP8) real() *FP4 {
+	return F.a
+}
+
+func (F *FP8) geta() *FP4 {
+	return F.a
+}
+/* extract imaginary part b */
+func (F *FP8) getb() *FP4 {
+	return F.b
+}
+/* test this=x? */
+func (F *FP8) Equals(x *FP8) bool {
+	return (F.a.Equals(x.a) && F.b.Equals(x.b))
+}
+
+/* copy this=x */
+func (F *FP8) copy(x *FP8) {
+	F.a.copy(x.a)
+	F.b.copy(x.b)
+}
+/* set this=0 */
+func (F *FP8) zero() {
+	F.a.zero()
+	F.b.zero()
+}
+/* set this=1 */
+func (F *FP8) one() {
+	F.a.one()
+	F.b.zero()
+}
+
+/* set this=-this */
+func (F *FP8) neg() {
+	F.norm()
+	m:=NewFP4copy(F.a);
+	t:=NewFP4int(0)
+	m.add(F.b)
+	m.neg()
+	//m.norm()
+	t.copy(m); t.add(F.b)
+	F.b.copy(m)
+	F.b.add(F.a)
+	F.a.copy(t)
+	F.norm()
+}
+
+/* this=conjugate(this) */
+func (F *FP8) conj() {
+	F.b.neg(); F.norm()
+}
+
+/* this=-conjugate(this) */
+func (F *FP8) nconj() {
+	F.a.neg(); F.norm()
+}
+
+/* this+=x */
+func (F *FP8) add(x *FP8) {
+	F.a.add(x.a)
+	F.b.add(x.b)
+}
+/* this-=x */
+func (F *FP8) sub(x *FP8) {
+	m:=NewFP8copy(x)
+	m.neg()
+	F.add(m)
+}
+
+/* this-=x */
+func (F *FP8) rsub(x *FP8) {
+	F.neg()
+	F.add(x)
+}
+
+/* this*=s where s is FP4 */
+func (F *FP8) pmul(s *FP4) {
+	F.a.mul(s)
+	F.b.mul(s)
+}
+
+/* this*=s where s is FP2 */
+func (F *FP8) qmul(s *FP2) {
+	F.a.pmul(s)
+	F.b.pmul(s)
+}
+
+/* this*=s where s is FP */
+func (F *FP8) tmul(s *FP) {
+	F.a.qmul(s)
+	F.b.qmul(s)
+}
+
+/* this*=c where c is int */
+func (F *FP8) imul(c int) {
+	F.a.imul(c)
+	F.b.imul(c)
+}
+
+/* this*=this */	
+func (F *FP8) sqr() {
+//	F.norm()
+
+	t1:=NewFP4copy(F.a)
+	t2:=NewFP4copy(F.b)
+	t3:=NewFP4copy(F.a)
+
+	t3.mul(F.b)
+	t1.add(F.b)
+	t2.times_i()
+
+	t2.add(F.a)
+
+	t1.norm(); t2.norm()
+
+	F.a.copy(t1)
+	F.a.mul(t2)
+
+	t2.copy(t3)
+	t2.times_i()
+	t2.add(t3); t2.norm()
+	t2.neg()
+	F.a.add(t2)
+
+	F.b.copy(t3)
+	F.b.add(t3)
+
+	F.norm()
+}
+
+/* this*=y */
+func (F *FP8) mul(y *FP8) {
+//	F.norm()
+
+	t1:=NewFP4copy(F.a)
+	t2:=NewFP4copy(F.b)
+	t3:=NewFP4int(0)
+	t4:=NewFP4copy(F.b)
+
+	t1.mul(y.a)
+	t2.mul(y.b)
+	t3.copy(y.b)
+	t3.add(y.a)
+	t4.add(F.a)
+
+	t3.norm(); t4.norm();
+
+	t4.mul(t3)
+
+	t3.copy(t1)
+	t3.neg()
+	t4.add(t3)
+	t4.norm()
+
+	t3.copy(t2);
+	t3.neg()
+	F.b.copy(t4)
+	F.b.add(t3)
+
+	t2.times_i()
+	F.a.copy(t2)
+	F.a.add(t1)
+
+	F.norm()
+}
+
+/* convert this to hex string */
+func (F *FP8) toString() string {
+	return ("["+F.a.toString()+","+F.b.toString()+"]")
+}
+
+/* this=1/this */
+func (F *FP8) inverse() {
+//	F.norm()
+
+	t1:=NewFP4copy(F.a)
+	t2:=NewFP4copy(F.b)
+
+	t1.sqr()
+	t2.sqr()
+	t2.times_i(); t2.norm()
+	t1.sub(t2); t1.norm()
+	t1.inverse()
+	F.a.mul(t1)
+	t1.neg(); t1.norm()
+	F.b.mul(t1)
+}
+
+/* this*=i where i = sqrt(sqrt(-1+sqrt(-1))) */
+func (F *FP8) times_i() {
+//	F.norm()
+	s:=NewFP4copy(F.b)
+	t:=NewFP4copy(F.a)
+	s.times_i()
+	F.a.copy(s)
+	F.b.copy(t)
+	F.norm()
+}
+
+func (F *FP8) times_i2() {
+	F.a.times_i()
+	F.b.times_i()
+}
+
+/* this=this^p using Frobenius */
+func (F *FP8) frob(f *FP2) {
+	ff:=NewFP2copy(f); ff.sqr(); ff.mul_ip(); ff.norm()
+
+	F.a.frob(ff)
+	F.b.frob(ff)
+	F.b.pmul(f)
+	F.b.times_i()
+
+}
+
+/* this=this^e */
+func (F *FP8) pow(e *BIG) *FP8 {
+	//F.norm()
+	w:=NewFP8copy(F)
+	w.norm()
+	z:=NewBIGcopy(e)
+	r:=NewFP8int(1)
+	z.norm()
+	for true {
+		bt:=z.parity()
+		z.fshr(1)
+		if bt==1 {r.mul(w)}
+		if z.iszilch() {break}
+		w.sqr()
+	}
+	r.reduce()
+	return r
+}
+
+/* XTR xtr_a function */
+func (F *FP8) xtr_A(w *FP8,y *FP8,z *FP8) {
+	r:=NewFP8copy(w)
+	t:=NewFP8copy(w)
+	//y.norm()
+	r.sub(y); r.norm()
+	r.pmul(F.a)
+	t.add(y); t.norm()
+	t.pmul(F.b)
+	t.times_i()
+
+	F.copy(r)
+	F.add(t)
+	F.add(z)
+
+	F.norm()
+}
+
+/* XTR xtr_d function */
+func (F *FP8) xtr_D() {
+	w:=NewFP8copy(F)
+	F.sqr(); w.conj()
+	w.add(w); w.norm()
+	F.sub(w)
+	F.reduce()
+}
+
+/* r=x^n using XTR method on traces of FP12s */
+func (F *FP8) xtr_pow(n *BIG) *FP8 {
+	a:=NewFP8int(3)
+	b:=NewFP8copy(F)
+	c:=NewFP8copy(b)
+	c.xtr_D()
+	t:=NewFP8int(0)
+	r:=NewFP8int(0)
+	sf:=NewFP8copy(F)
+	sf.norm();
+
+	par:=n.parity()
+	v:=NewBIGcopy(n); v.norm(); v.fshr(1)
+	if (par==0) {v.dec(1); v.norm()}
+
+	nb:=v.nbits();
+	for i:=nb-1;i>=0;i-- {
+		if v.bit(i)!=1 {
+			t.copy(b)
+			sf.conj()
+			c.conj()
+			b.xtr_A(a,sf,c)
+			sf.conj()
+			c.copy(t)
+			c.xtr_D()
+			a.xtr_D()
+		} else {
+			t.copy(a); t.conj()
+			a.copy(b)
+			a.xtr_D()
+			b.xtr_A(c,sf,t)
+			c.xtr_D()
+		}
+	}
+	if par==0 {
+		r.copy(c)
+	} else {r.copy(b)}
+	r.reduce()
+	return r
+}
+
+/* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */
+func (F *FP8) xtr_pow2(ck *FP8,ckml *FP8,ckm2l *FP8,a *BIG,b *BIG) *FP8 {
+
+	e:=NewBIGcopy(a)
+	d:=NewBIGcopy(b)
+	w:=NewBIGint(0)
+	e.norm(); d.norm()
+	cu:=NewFP8copy(ck)  // can probably be passed in w/o copying
+	cv:=NewFP8copy(F);
+	cumv:=NewFP8copy(ckml)
+	cum2v:=NewFP8copy(ckm2l)
+	r:=NewFP8int(0)
+	t:=NewFP8int(0)
+
+	f2:=0
+	for (d.parity()==0 && e.parity()==0) {
+		d.fshr(1)
+		e.fshr(1)
+		f2++
+	}
+
+	for Comp(d,e)!=0 {
+		if Comp(d,e)>0 {
+			w.copy(e); w.imul(4); w.norm()
+			if Comp(d,w)<=0 {
+				w.copy(d); d.copy(e)
+				e.rsub(w); e.norm()
+
+				t.copy(cv);
+				t.xtr_A(cu,cumv,cum2v)
+				cum2v.copy(cumv);
+				cum2v.conj()
+				cumv.copy(cv)
+				cv.copy(cu)
+				cu.copy(t)
+			} else {
+					if (d.parity()==0) {
+					d.fshr(1)
+					r.copy(cum2v); r.conj()
+					t.copy(cumv)
+					t.xtr_A(cu,cv,r)
+					cum2v.copy(cumv)
+					cum2v.xtr_D()
+					cumv.copy(t)
+					cu.xtr_D()
+				} else {
+					if (e.parity()==1) {
+						d.sub(e); d.norm()
+						d.fshr(1)
+						t.copy(cv)
+						t.xtr_A(cu,cumv,cum2v)
+						cu.xtr_D()
+						cum2v.copy(cv)
+						cum2v.xtr_D()
+						cum2v.conj()
+						cv.copy(t)
+					} else {
+						w.copy(d)
+						d.copy(e); d.fshr(1)
+						e.copy(w)
+						t.copy(cumv)
+						t.xtr_D()
+						cumv.copy(cum2v); cumv.conj()
+						cum2v.copy(t); cum2v.conj()
+						t.copy(cv)
+						t.xtr_D()
+						cv.copy(cu)
+						cu.copy(t)
+					}
+				}
+			}
+		}
+		if Comp(d,e)<0 {
+			w.copy(d); w.imul(4); w.norm()
+			if Comp(e,w)<=0 {
+				e.sub(d); e.norm()
+				t.copy(cv)
+				t.xtr_A(cu,cumv,cum2v)
+				cum2v.copy(cumv)
+				cumv.copy(cu)
+				cu.copy(t)
+			} else {
+				if (e.parity()==0) {
+					w.copy(d)
+					d.copy(e); d.fshr(1)
+					e.copy(w)
+					t.copy(cumv)
+					t.xtr_D()
+					cumv.copy(cum2v); cumv.conj()
+					cum2v.copy(t); cum2v.conj()
+					t.copy(cv)
+					t.xtr_D()
+					cv.copy(cu)
+					cu.copy(t)
+				} else {
+					if (d.parity()==1) {
+						w.copy(e)
+						e.copy(d)
+						w.sub(d); w.norm()
+						d.copy(w); d.fshr(1)
+						t.copy(cv)
+						t.xtr_A(cu,cumv,cum2v)
+						cumv.conj()
+						cum2v.copy(cu)
+						cum2v.xtr_D()
+						cum2v.conj()
+						cu.copy(cv)
+						cu.xtr_D()
+						cv.copy(t)
+					} else {
+						d.fshr(1)
+						r.copy(cum2v); r.conj()
+						t.copy(cumv)
+						t.xtr_A(cu,cv,r)
+						cum2v.copy(cumv)
+						cum2v.xtr_D()
+						cumv.copy(t)
+						cu.xtr_D()
+					}
+				}
+			}
+		}
+	}
+	r.copy(cv)
+	r.xtr_A(cu,cumv,cum2v)
+	for i:=0;i<f2;i++ {r.xtr_D()}
+	r=r.xtr_pow(d)
+	return r
+}
+
+/* this/=2 */
+func (F *FP8) div2() {
+	F.a.div2()
+	F.b.div2()
+}
+
+func (F *FP8) div_i() {
+	u:=NewFP4copy(F.a)
+	v:=NewFP4copy(F.b)
+	u.div_i()
+	F.a.copy(v)
+	F.b.copy(u)
+}	
+
+func (F *FP8) div_i2() {
+	F.a.div_i()
+	F.b.div_i()
+}
+
+func (F *FP8) div_2i() {
+	u:=NewFP4copy(F.a)
+	v:=NewFP4copy(F.b)
+	u.div_2i()
+	v.add(v); v.norm()
+	F.a.copy(v)
+	F.b.copy(u)	
+}
+
+/* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */
+/* returns true if this is QR */
+func (F *FP8) sqrt() bool {
+	if F.iszilch() {return true}
+
+	a:=NewFP4copy(F.a)
+	s:=NewFP4copy(F.b)
+	t:=NewFP4copy(F.a)
+
+	if s.iszilch() {
+		if t.sqrt() {
+			F.a.copy(t)
+			F.b.zero()
+		} else {
+			t.div_i()
+			t.sqrt()
+			F.b.copy(t)
+			F.a.zero()
+		}
+		return true
+	}
+	s.sqr()
+	a.sqr()
+	s.times_i()
+	s.norm()
+	a.sub(s)
+
+	s.copy(a)
+	if !s.sqrt() {
+		return false
+	}
+
+	a.copy(t); a.add(s); a.norm(); a.div2()
+
+	if !a.sqrt() {
+		a.copy(t); a.sub(s); a.norm(); a.div2()
+		if !a.sqrt() {
+			return false
+		}
+	}
+	t.copy(F.b)
+	s.copy(a); s.add(a)
+	s.inverse()
+
+	t.mul(s)
+	F.a.copy(a)
+	F.b.copy(t)
+
+	return true
+}
diff --git a/version3/go/GCM.go b/version3/go/GCM.go
new file mode 100644
index 0000000..e6478ce
--- /dev/null
+++ b/version3/go/GCM.go
@@ -0,0 +1,337 @@
+/*
+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.
+*/
+
+/*
+* Implementation of the AES-GCM Encryption/Authentication
+*
+* Some restrictions..
+* 1. Only for use with AES
+* 2. Returned tag is always 128-bits. Truncate at your own risk.
+* 3. The order of function calls must follow some rules
+*
+* Typical sequence of calls..
+* 1. call GCM_init
+* 2. call GCM_add_header any number of times, as long as length of header is multiple of 16 bytes (block size)
+* 3. call GCM_add_header one last time with any length of header
+* 4. call GCM_add_cipher any number of times, as long as length of cipher/plaintext is multiple of 16 bytes
+* 5. call GCM_add_cipher one last time with any length of cipher/plaintext
+* 6. call GCM_finish to extract the tag.
+*
+* See http://www.mindspring.com/~dmcgrew/gcm-nist-6.pdf
+*/
+
+
+package amcl
+
+import
+(
+//	"fmt"
+	"strconv"
+)
+
+const gcm_NB int=4
+const GCM_ACCEPTING_HEADER int=0
+const GCM_ACCEPTING_CIPHER int=1
+const GCM_NOT_ACCEPTING_MORE int=2
+const GCM_FINISHED int=3
+const GCM_ENCRYPTING int=0
+const GCM_DECRYPTING int=1
+
+
+type GCM struct {
+	table [128][4]uint32 /* 2k bytes */
+	stateX [16]byte
+	Y_0 [16]byte
+	counter int
+	lenA [2]uint32
+	lenC [2]uint32
+	status int
+	a  *AES
+}
+
+func gcm_pack(b [4]byte) uint32 { /* pack bytes into a 32-bit Word */
+        return ((uint32(b[0])&0xff)<<24)|((uint32(b[1])&0xff)<<16)|((uint32(b[2])&0xff)<<8)|(uint32(b[3])&0xff)
+}
+
+func gcm_unpack(a uint32) [4]byte { /* unpack bytes from a word */
+        var b=[4]byte{byte((a>>24)&0xff),byte((a>>16)&0xff),byte((a>>8)&0xff),byte(a&0xff)}
+	return b;
+}
+
+func (G *GCM) precompute(H []byte) {
+        var b [4]byte
+        j:=0
+        for i:=0;i<gcm_NB;i++ {
+            b[0]=H[j]; b[1]=H[j+1]; b[2]=H[j+2]; b[3]=H[j+3]
+            G.table[0][i]=gcm_pack(b);
+            j+=4
+        }
+        for i:=1;i<128;i++ {
+	    c:=uint32(0)
+            for j:=0;j<gcm_NB;j++ {G.table[i][j]=c|(G.table[i-1][j])>>1; c=G.table[i-1][j]<<31;}
+            if c != 0  {G.table[i][0]^=0xE1000000} /* irreducible polynomial */
+        }
+}
+
+func (G *GCM) gf2mul() { /* gf2m mul - Z=H*X mod 2^128 */
+        var P [4]uint32
+    
+        for i:=0;i<4;i++ {P[i]=0}
+        j:=uint(8); m:=0
+        for i:=0;i<128;i++ {
+	    j--
+            c:=uint32((G.stateX[m]>>j)&1); c=^c+1
+	    for k:=0;k<gcm_NB;k++ {P[k]^=(G.table[i][k]&c)}
+            if j==0 {
+		j=8; m++;
+                if m==16 {break}
+            }
+        }
+        j=0
+        for i:=0;i<gcm_NB;i++ {
+            b:=gcm_unpack(P[i])
+            G.stateX[j]=b[0]; G.stateX[j+1]=b[1]; G.stateX[j+2]=b[2]; G.stateX[j+3]=b[3];
+            j+=4
+        }
+}
+
+func (G *GCM) wrap() { /* Finish off GHASH */
+	var F [4]uint32
+	var L [16]byte
+   
+    /* convert lengths from bytes to bits */
+        F[0]=(G.lenA[0]<<3)|(G.lenA[1]&0xE0000000)>>29
+        F[1]=G.lenA[1]<<3
+        F[2]=(G.lenC[0]<<3)|(G.lenC[1]&0xE0000000)>>29
+        F[3]=G.lenC[1]<<3
+        j:=0
+        for i:=0;i<gcm_NB;i++ {
+            b:=gcm_unpack(F[i]);
+            L[j]=b[0]; L[j+1]=b[1]; L[j+2]=b[2]; L[j+3]=b[3]
+            j+=4
+        }
+        for i:=0;i<16;i++ {G.stateX[i]^=L[i]}
+        G.gf2mul()
+}
+
+func (G *GCM) ghash(plain []byte,len int) bool {
+        if G.status==GCM_ACCEPTING_HEADER {G.status=GCM_ACCEPTING_CIPHER}
+        if G.status != GCM_ACCEPTING_CIPHER {return false}
+        
+        j:=0
+        for (j<len) {
+            for i:=0;i<16 && j<len;i++ {
+		G.stateX[i]^=plain[j]; j++
+                G.lenC[1]++; if G.lenC[1]==0 {G.lenC[0]++}
+            }
+            G.gf2mul();
+        }
+        if len%16 != 0 {G.status=GCM_NOT_ACCEPTING_MORE}
+        return true;
+    }
+
+    /* Initialize GCM mode */
+func (G *GCM) Init(nk int,key []byte,niv int,iv []byte) { /* iv size niv is usually 12 bytes (96 bits). AES key size nk can be 16,24 or 32 bytes */
+	var H [16]byte
+    
+        for i:=0;i<16;i++ {H[i]=0; G.stateX[i]=0}
+        
+	   G.a=new(AES)
+
+        G.a.Init(AES_ECB,nk,key,iv)
+        G.a.ecb_encrypt(H[:])    /* E(K,0) */
+        G.precompute(H[:])
+        
+        G.lenA[0]=0;G.lenC[0]=0;G.lenA[1]=0;G.lenC[1]=0
+        if niv==12 {
+            for i:=0;i<12;i++ {G.a.f[i]=iv[i]}
+            b:=gcm_unpack(uint32(1))
+            G.a.f[12]=b[0]; G.a.f[13]=b[1]; G.a.f[14]=b[2]; G.a.f[15]=b[3];  /* initialise IV */
+            for i:=0;i<16;i++ {G.Y_0[i]=G.a.f[i]}
+        } else {
+            G.status=GCM_ACCEPTING_CIPHER;
+            G.ghash(iv,niv) /* GHASH(H,0,IV) */
+            G.wrap()
+            for i:=0;i<16;i++ {G.a.f[i]=G.stateX[i];G.Y_0[i]=G.a.f[i];G.stateX[i]=0}
+            G.lenA[0]=0;G.lenC[0]=0;G.lenA[1]=0;G.lenC[1]=0
+        }
+        G.status=GCM_ACCEPTING_HEADER
+}
+
+/* Add Header data - included but not encrypted */
+func (G *GCM) Add_header(header []byte,len int) bool { /* Add some header. Won't be encrypted, but will be authenticated. len is length of header */
+        if G.status != GCM_ACCEPTING_HEADER {return false}
+  
+        j:=0
+        for j<len {
+            for i:=0;i<16 && j<len;i++ {
+		G.stateX[i]^=header[j]; j++
+                G.lenA[1]++; if G.lenA[1]==0 {G.lenA[0]++}
+            }
+            G.gf2mul();
+        }
+        if len%16 != 0 {G.status=GCM_ACCEPTING_CIPHER}
+
+        return true;
+    }
+
+/* Add Plaintext - included and encrypted */
+func (G *GCM) Add_plain(plain []byte,len int) []byte {
+	var B [16]byte
+	var b [4]byte
+        
+        cipher:=make([]byte,len)
+        var counter uint32=0
+        if G.status == GCM_ACCEPTING_HEADER {G.status=GCM_ACCEPTING_CIPHER}
+        if G.status != GCM_ACCEPTING_CIPHER {return nil}
+        
+        j:=0
+        for j<len {
+    
+            b[0]=G.a.f[12]; b[1]=G.a.f[13]; b[2]=G.a.f[14]; b[3]=G.a.f[15];
+            counter=gcm_pack(b)
+            counter++
+            b=gcm_unpack(counter)
+            G.a.f[12]=b[0]; G.a.f[13]=b[1]; G.a.f[14]=b[2]; G.a.f[15]=b[3] /* increment counter */
+            for i:=0;i<16;i++ {B[i]=G.a.f[i]}
+            G.a.ecb_encrypt(B[:]);        /* encrypt it  */
+    
+            for i:=0;i<16 && j<len;i++ {
+		cipher[j]=(plain[j]^B[i])
+		G.stateX[i]^=cipher[j]; j++
+                G.lenC[1]++; if G.lenC[1]==0 {G.lenC[0]++}
+            }
+            G.gf2mul()
+        }
+        if len%16 != 0 {G.status=GCM_NOT_ACCEPTING_MORE}
+        return cipher
+}
+
+/* Add Ciphertext - decrypts to plaintext */
+func (G *GCM) Add_cipher(cipher []byte,len int) []byte {
+	var B [16]byte
+	var b [4]byte
+        
+        plain:=make([]byte,len)
+        var counter uint32=0
+        
+        if G.status==GCM_ACCEPTING_HEADER {G.status=GCM_ACCEPTING_CIPHER}
+        if G.status != GCM_ACCEPTING_CIPHER {return nil}
+    
+        j:=0
+        for j<len {
+            b[0]=G.a.f[12]; b[1]=G.a.f[13]; b[2]=G.a.f[14]; b[3]=G.a.f[15]
+            counter=gcm_pack(b);
+            counter++
+            b=gcm_unpack(counter)
+            G.a.f[12]=b[0]; G.a.f[13]=b[1]; G.a.f[14]=b[2]; G.a.f[15]=b[3]; /* increment counter */
+            for i:=0;i<16;i++ {B[i]=G.a.f[i]}
+            G.a.ecb_encrypt(B[:])        /* encrypt it  */
+            for i:=0;i<16 && j<len;i++ {
+		oc:=cipher[j];
+		plain[j]=(cipher[j]^B[i])
+		G.stateX[i]^=oc; j++
+                G.lenC[1]++; if G.lenC[1]==0 {G.lenC[0]++}
+            }
+            G.gf2mul()
+        }
+        if len%16 != 0 {G.status=GCM_NOT_ACCEPTING_MORE}
+        return plain
+}
+
+/* Finish and extract Tag */
+func (G *GCM) Finish(extract bool) [16]byte { /* Finish off GHASH and extract tag (MAC) */
+	var tag [16]byte
+    
+        G.wrap()
+        /* extract tag */
+        if extract {
+            G.a.ecb_encrypt(G.Y_0[:]);        /* E(K,Y0) */
+            for i:=0;i<16;i++ {G.Y_0[i]^=G.stateX[i]}
+            for i:=0;i<16;i++ {tag[i]=G.Y_0[i];G.Y_0[i]=0;G.stateX[i]=0}
+        }
+        G.status=GCM_FINISHED
+        G.a.End()
+        return tag
+}
+
+func hex2bytes(s string) []byte {
+	lgh:=len(s)
+	data:=make([]byte,lgh/2)
+       
+        for i:=0;i<lgh;i+=2 {
+            a,_ := strconv.ParseInt(s[i:i+2],16,32)
+	    data[i/2]=byte(a)
+        }
+        return data
+}
+
+/*
+func main() {
+
+	KT:="feffe9928665731c6d6a8f9467308308"
+	MT:="d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39"
+	HT:="feedfacedeadbeeffeedfacedeadbeefabaddad2"
+
+	NT:="9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b";
+// Tag should be 619cc5aefffe0bfa462af43c1699d050
+
+	g:=new(GCM)
+
+	M:=hex2bytes(MT)
+	H:=hex2bytes(HT)
+	N:=hex2bytes(NT)
+	K:=hex2bytes(KT)
+
+	lenM:=len(M)
+	lenH:=len(H)
+	lenK:=len(K)
+	lenIV:=len(N)
+
+ 	fmt.Printf("Plaintext=\n");
+	for i:=0;i<lenM;i++ {fmt.Printf("%02x",M[i])}
+	fmt.Printf("\n")
+
+	g.Init(lenK,K,lenIV,N)
+	g.Add_header(H,lenH)
+	C:=g.Add_plain(M,lenM)
+	T:=g.Finish(true)
+
+	fmt.Printf("Ciphertext=\n")
+	for i:=0;i<lenM;i++ {fmt.Printf("%02x",C[i])}
+	fmt.Printf("\n")
+        
+	fmt.Printf("Tag=\n")
+	for i:=0;i<16;i++ {fmt.Printf("%02x",T[i])}
+	fmt.Printf("\n")
+
+	g.Init(lenK,K,lenIV,N)
+	g.Add_header(H,lenH)
+	P:=g.Add_cipher(C,lenM)
+	T=g.Finish(true)
+
+ 	fmt.Printf("Plaintext=\n");
+	for i:=0;i<lenM;i++ {fmt.Printf("%02x",P[i])}
+	fmt.Printf("\n")
+
+	fmt.Printf("Tag=\n");
+	for i:=0;i<16;i++ {fmt.Printf("%02x",T[i])}
+	fmt.Printf("\n")
+}
+*/
diff --git a/version3/go/HASH256.go b/version3/go/HASH256.go
new file mode 100644
index 0000000..94b5256
--- /dev/null
+++ b/version3/go/HASH256.go
@@ -0,0 +1,193 @@
+/*
+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.
+*/
+
+/*
+ * Implementation of the Secure Hashing Algorithm (SHA-256)
+ *
+ * Generates a 256 bit message digest. It should be impossible to come
+ * come up with two messages that hash to the same value ("collision free").
+ *
+ * For use with byte-oriented messages only. 
+ */
+
+
+package amcl
+
+//import "fmt"
+const SHA256 int=32
+
+const hash256_H0 uint32=0x6A09E667
+const hash256_H1 uint32=0xBB67AE85
+const hash256_H2 uint32=0x3C6EF372
+const hash256_H3 uint32=0xA54FF53A
+const hash256_H4 uint32=0x510E527F
+const hash256_H5 uint32=0x9B05688C
+const hash256_H6 uint32=0x1F83D9AB
+const hash256_H7 uint32=0x5BE0CD19
+
+var hash256_K = [...]uint32 {
+	0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,
+	0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,
+	0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,
+	0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,
+	0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
+	0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070,
+	0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,
+	0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2}
+
+
+type HASH256 struct {
+	length [2]uint32
+	h [8]uint32
+	w [64]uint32
+
+}
+
+/* functions */
+func hash256_S(n uint32,x uint32) uint32 {
+	return (((x)>>n) | ((x)<<(32-n)))
+}
+
+func hash256_R(n uint32,x uint32) uint32 {
+	return ((x)>>n)
+}
+
+func hash256_Ch(x,y,z uint32) uint32 {
+	return ((x&y)^(^(x)&z))
+}
+
+func hash256_Maj(x,y,z uint32) uint32 {
+	return ((x&y)^(x&z)^(y&z))
+}
+
+func hash256_Sig0(x uint32) uint32 {
+	return (hash256_S(2,x)^hash256_S(13,x)^hash256_S(22,x))
+}
+
+func hash256_Sig1(x uint32) uint32 {
+	return (hash256_S(6,x)^hash256_S(11,x)^hash256_S(25,x))
+}
+
+func hash256_theta0(x uint32) uint32 {
+	return (hash256_S(7,x)^hash256_S(18,x)^hash256_R(3,x));
+}
+
+func hash256_theta1(x uint32) uint32 {
+		return (hash256_S(17,x)^hash256_S(19,x)^hash256_R(10,x))
+}
+
+func (H *HASH256) transform() { /* basic transformation step */
+	for j:=16;j<64;j++ {
+		H.w[j]=hash256_theta1(H.w[j-2])+H.w[j-7]+hash256_theta0(H.w[j-15])+H.w[j-16]
+	}
+	a:=H.h[0]; b:=H.h[1]; c:=H.h[2]; d:=H.h[3] 
+	e:=H.h[4]; f:=H.h[5]; g:=H.h[6]; hh:=H.h[7]
+	for j:=0;j<64;j++ { /* 64 times - mush it up */
+		t1:=hh+hash256_Sig1(e)+hash256_Ch(e,f,g)+hash256_K[j]+H.w[j]
+		t2:=hash256_Sig0(a)+hash256_Maj(a,b,c)
+		hh=g; g=f; f=e
+		e=d+t1
+		d=c
+		c=b
+		b=a
+		a=t1+t2  
+	}
+	H.h[0]+=a; H.h[1]+=b; H.h[2]+=c; H.h[3]+=d 
+	H.h[4]+=e; H.h[5]+=f; H.h[6]+=g; H.h[7]+=hh 
+} 
+
+/* Initialise Hash function */
+func (H *HASH256) Init() { /* initialise */
+	for i:=0;i<64;i++ {H.w[i]=0}
+	H.length[0]=0; H.length[1]=0
+	H.h[0]=hash256_H0
+	H.h[1]=hash256_H1
+	H.h[2]=hash256_H2
+	H.h[3]=hash256_H3
+	H.h[4]=hash256_H4
+	H.h[5]=hash256_H5
+	H.h[6]=hash256_H6
+	H.h[7]=hash256_H7
+}
+
+func NewHASH256() *HASH256 {
+	H:= new(HASH256)
+	H.Init()
+	return H
+}
+
+/* process a single byte */
+func (H *HASH256) Process(byt byte) { /* process the next message byte */
+	cnt:=(H.length[0]/32)%16;
+    
+	H.w[cnt]<<=8;
+	H.w[cnt]|=uint32(byt&0xFF);
+	H.length[0]+=8;
+	if H.length[0]==0 {H.length[1]++; H.length[0]=0}
+	if (H.length[0]%512)==0 {H.transform()}
+}
+
+/* process an array of bytes */	
+func (H *HASH256) Process_array(b []byte) {
+	for i:=0;i<len(b);i++ {H.Process((b[i]))}
+}
+
+/* process a 32-bit integer */
+func (H *HASH256) Process_num(n int32) {
+	H.Process(byte((n>>24)&0xff));
+	H.Process(byte((n>>16)&0xff));
+	H.Process(byte((n>>8)&0xff));
+	H.Process(byte(n&0xff));
+}
+
+/* Generate 32-byte Hash */
+func (H *HASH256) Hash() []byte { /* pad message and finish - supply digest */
+	var digest [32]byte
+	len0:=H.length[0]
+	len1:=H.length[1]
+	H.Process(0x80);
+	for (H.length[0]%512)!=448 {H.Process(0)}
+	H.w[14]=len1;
+	H.w[15]=len0;    
+	H.transform();
+	for i:=0;i<32;i++ { /* convert to bytes */
+		digest[i]=byte((H.h[i/4]>>uint(8*(3-i%4))) & 0xff);
+	}
+	H.Init()
+	return digest[0:32]
+}
+
+/* test program: should produce digest */
+
+//248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1
+/*
+func main() {
+
+	test := []byte("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")
+	sh:=NewHASH256()
+
+	for i:=0;i<len(test);i++ {
+		sh.Process(test[i])
+	}
+		
+	digest:=sh.Hash()    
+	for i:=0;i<32;i++ {fmt.Printf("%02x",digest[i])}
+
+} */
+
diff --git a/version3/go/HASH384.go b/version3/go/HASH384.go
new file mode 100644
index 0000000..b98c7f2
--- /dev/null
+++ b/version3/go/HASH384.go
@@ -0,0 +1,206 @@
+/*
+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.
+*/
+
+/*
+ * Implementation of the Secure Hashing Algorithm (SHA-384)
+ *
+ * Generates a 384 bit message digest. It should be impossible to come
+ * come up with two messages that hash to the same value ("collision free").
+ *
+ * For use with byte-oriented messages only. 
+ */
+
+
+package amcl
+
+//import "fmt"
+
+const SHA384 int=48
+
+const hash384_H0 uint64=0xcbbb9d5dc1059ed8
+const hash384_H1 uint64=0x629a292a367cd507
+const hash384_H2 uint64=0x9159015a3070dd17
+const hash384_H3 uint64=0x152fecd8f70e5939
+const hash384_H4 uint64=0x67332667ffc00b31
+const hash384_H5 uint64=0x8eb44a8768581511
+const hash384_H6 uint64=0xdb0c2e0d64f98fa7
+const hash384_H7 uint64=0x47b5481dbefa4fa4
+
+var hash384_K = [...]uint64 {
+	0x428a2f98d728ae22,0x7137449123ef65cd,0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc,
+	0x3956c25bf348b538,0x59f111f1b605d019,0x923f82a4af194f9b,0xab1c5ed5da6d8118,
+	0xd807aa98a3030242,0x12835b0145706fbe,0x243185be4ee4b28c,0x550c7dc3d5ffb4e2,
+	0x72be5d74f27b896f,0x80deb1fe3b1696b1,0x9bdc06a725c71235,0xc19bf174cf692694,
+	0xe49b69c19ef14ad2,0xefbe4786384f25e3,0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65,
+	0x2de92c6f592b0275,0x4a7484aa6ea6e483,0x5cb0a9dcbd41fbd4,0x76f988da831153b5,
+	0x983e5152ee66dfab,0xa831c66d2db43210,0xb00327c898fb213f,0xbf597fc7beef0ee4,
+	0xc6e00bf33da88fc2,0xd5a79147930aa725,0x06ca6351e003826f,0x142929670a0e6e70,
+	0x27b70a8546d22ffc,0x2e1b21385c26c926,0x4d2c6dfc5ac42aed,0x53380d139d95b3df,
+	0x650a73548baf63de,0x766a0abb3c77b2a8,0x81c2c92e47edaee6,0x92722c851482353b,
+	0xa2bfe8a14cf10364,0xa81a664bbc423001,0xc24b8b70d0f89791,0xc76c51a30654be30,
+	0xd192e819d6ef5218,0xd69906245565a910,0xf40e35855771202a,0x106aa07032bbd1b8,
+	0x19a4c116b8d2d0c8,0x1e376c085141ab53,0x2748774cdf8eeb99,0x34b0bcb5e19b48a8,
+	0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb,0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3,
+	0x748f82ee5defb2fc,0x78a5636f43172f60,0x84c87814a1f0ab72,0x8cc702081a6439ec,
+	0x90befffa23631e28,0xa4506cebde82bde9,0xbef9a3f7b2c67915,0xc67178f2e372532b,
+	0xca273eceea26619c,0xd186b8c721c0c207,0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178,
+	0x06f067aa72176fba,0x0a637dc5a2c898a6,0x113f9804bef90dae,0x1b710b35131c471b,
+	0x28db77f523047d84,0x32caab7b40c72493,0x3c9ebe0a15c9bebc,0x431d67c49c100d4c,
+	0x4cc5d4becb3e42b6,0x597f299cfc657e2a,0x5fcb6fab3ad6faec,0x6c44198c4a475817}
+
+
+type HASH384 struct {
+	length [2]uint64
+	h [8]uint64
+	w [80]uint64
+
+}
+
+/* functions */
+func hash384_S(n uint64,x uint64) uint64 {
+	return (((x)>>n) | ((x)<<(64-n)))
+}
+
+func hash384_R(n uint64,x uint64) uint64 {
+	return ((x)>>n)
+}
+
+func hash384_Ch(x,y,z uint64) uint64 {
+	return ((x&y)^(^(x)&z))
+}
+
+func hash384_Maj(x,y,z uint64) uint64 {
+	return ((x&y)^(x&z)^(y&z))
+}
+
+func hash384_Sig0(x uint64) uint64 {
+	return (hash384_S(28,x)^hash384_S(34,x)^hash384_S(39,x))
+}
+
+func hash384_Sig1(x uint64) uint64 {
+	return (hash384_S(14,x)^hash384_S(18,x)^hash384_S(41,x))
+}
+
+func hash384_theta0(x uint64) uint64 {
+	return (hash384_S(1,x)^hash384_S(8,x)^hash384_R(7,x));
+}
+
+func hash384_theta1(x uint64) uint64 {
+		return (hash384_S(19,x)^hash384_S(61,x)^hash384_R(6,x))
+}
+
+func (H *HASH384) transform() { /* basic transformation step */
+	for j:=16;j<80;j++ {
+		H.w[j]=hash384_theta1(H.w[j-2])+H.w[j-7]+hash384_theta0(H.w[j-15])+H.w[j-16]
+	}
+	a:=H.h[0]; b:=H.h[1]; c:=H.h[2]; d:=H.h[3] 
+	e:=H.h[4]; f:=H.h[5]; g:=H.h[6]; hh:=H.h[7]
+	for j:=0;j<80;j++ { /* 80 times - mush it up */
+		t1:=hh+hash384_Sig1(e)+hash384_Ch(e,f,g)+hash384_K[j]+H.w[j]
+		t2:=hash384_Sig0(a)+hash384_Maj(a,b,c)
+		hh=g; g=f; f=e
+		e=d+t1
+		d=c
+		c=b
+		b=a
+		a=t1+t2  
+	}
+	H.h[0]+=a; H.h[1]+=b; H.h[2]+=c; H.h[3]+=d 
+	H.h[4]+=e; H.h[5]+=f; H.h[6]+=g; H.h[7]+=hh 
+} 
+
+/* Initialise Hash function */
+func (H *HASH384) Init() { /* initialise */
+	for i:=0;i<80;i++ {H.w[i]=0}
+	H.length[0]=0; H.length[1]=0
+	H.h[0]=hash384_H0
+	H.h[1]=hash384_H1
+	H.h[2]=hash384_H2
+	H.h[3]=hash384_H3
+	H.h[4]=hash384_H4
+	H.h[5]=hash384_H5
+	H.h[6]=hash384_H6
+	H.h[7]=hash384_H7
+}
+
+func NewHASH384() *HASH384 {
+	H:= new(HASH384)
+	H.Init()
+	return H
+}
+
+/* process a single byte */
+func (H *HASH384) Process(byt byte) { /* process the next message byte */
+	cnt:=(H.length[0]/64)%16;
+    
+	H.w[cnt]<<=8;
+	H.w[cnt]|=uint64(byt&0xFF);
+	H.length[0]+=8;
+	if H.length[0]==0 {H.length[1]++; H.length[0]=0}
+	if (H.length[0]%1024)==0 {H.transform()}
+}
+
+/* process an array of bytes */	
+func (H *HASH384) Process_array(b []byte) {
+	for i:=0;i<len(b);i++ {H.Process((b[i]))}
+}
+
+/* process a 32-bit integer */
+func (H *HASH384) Process_num(n int32) {
+	H.Process(byte((n>>24)&0xff));
+	H.Process(byte((n>>16)&0xff));
+	H.Process(byte((n>>8)&0xff));
+	H.Process(byte(n&0xff));
+}
+
+/* Generate 32-byte Hash */
+func (H *HASH384) Hash() []byte { /* pad message and finish - supply digest */
+	var digest [48]byte
+	len0:=H.length[0]
+	len1:=H.length[1]
+	H.Process(0x80);
+	for (H.length[0]%1024)!=896 {H.Process(0)}
+	H.w[14]=len1;
+	H.w[15]=len0;    
+	H.transform();
+	for i:=0;i<48;i++ { /* convert to bytes */
+		digest[i]=byte((H.h[i/8]>>uint(8*(7-i%8))) & 0xff);
+	}
+	H.Init()
+	return digest[0:48]
+}
+
+/* test program: should produce digest */
+
+//09330c33f71147e8 3d192fc782cd1b47 53111b173b3b05d2 2fa08086e3b0f712 fcc7c71a557e2db9 66c3e9fa91746039
+/*
+func main() {
+
+	test := []byte("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu")
+	sh:=NewHASH384()
+
+	for i:=0;i<len(test);i++ {
+		sh.Process(test[i])
+	}
+		
+	digest:=sh.Hash()    
+	for i:=0;i<48;i++ {fmt.Printf("%02x",digest[i])}
+
+}
+*/
diff --git a/version3/go/HASH512.go b/version3/go/HASH512.go
new file mode 100644
index 0000000..f320fd9
--- /dev/null
+++ b/version3/go/HASH512.go
@@ -0,0 +1,206 @@
+/*
+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.
+*/
+
+/*
+ * Implementation of the Secure Hashing Algorithm (SHA-384)
+ *
+ * Generates a 384 bit message digest. It should be impossible to come
+ * come up with two messages that hash to the same value ("collision free").
+ *
+ * For use with byte-oriented messages only. 
+ */
+
+
+package amcl
+
+//import "fmt"
+
+const SHA512 int=64
+
+const hash512_H0 uint64=0x6a09e667f3bcc908
+const hash512_H1 uint64=0xbb67ae8584caa73b
+const hash512_H2 uint64=0x3c6ef372fe94f82b
+const hash512_H3 uint64=0xa54ff53a5f1d36f1
+const hash512_H4 uint64=0x510e527fade682d1
+const hash512_H5 uint64=0x9b05688c2b3e6c1f
+const hash512_H6 uint64=0x1f83d9abfb41bd6b
+const hash512_H7 uint64=0x5be0cd19137e2179
+
+var hash512_K = [...]uint64 {
+	0x428a2f98d728ae22,0x7137449123ef65cd,0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc,
+	0x3956c25bf348b538,0x59f111f1b605d019,0x923f82a4af194f9b,0xab1c5ed5da6d8118,
+	0xd807aa98a3030242,0x12835b0145706fbe,0x243185be4ee4b28c,0x550c7dc3d5ffb4e2,
+	0x72be5d74f27b896f,0x80deb1fe3b1696b1,0x9bdc06a725c71235,0xc19bf174cf692694,
+	0xe49b69c19ef14ad2,0xefbe4786384f25e3,0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65,
+	0x2de92c6f592b0275,0x4a7484aa6ea6e483,0x5cb0a9dcbd41fbd4,0x76f988da831153b5,
+	0x983e5152ee66dfab,0xa831c66d2db43210,0xb00327c898fb213f,0xbf597fc7beef0ee4,
+	0xc6e00bf33da88fc2,0xd5a79147930aa725,0x06ca6351e003826f,0x142929670a0e6e70,
+	0x27b70a8546d22ffc,0x2e1b21385c26c926,0x4d2c6dfc5ac42aed,0x53380d139d95b3df,
+	0x650a73548baf63de,0x766a0abb3c77b2a8,0x81c2c92e47edaee6,0x92722c851482353b,
+	0xa2bfe8a14cf10364,0xa81a664bbc423001,0xc24b8b70d0f89791,0xc76c51a30654be30,
+	0xd192e819d6ef5218,0xd69906245565a910,0xf40e35855771202a,0x106aa07032bbd1b8,
+	0x19a4c116b8d2d0c8,0x1e376c085141ab53,0x2748774cdf8eeb99,0x34b0bcb5e19b48a8,
+	0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb,0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3,
+	0x748f82ee5defb2fc,0x78a5636f43172f60,0x84c87814a1f0ab72,0x8cc702081a6439ec,
+	0x90befffa23631e28,0xa4506cebde82bde9,0xbef9a3f7b2c67915,0xc67178f2e372532b,
+	0xca273eceea26619c,0xd186b8c721c0c207,0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178,
+	0x06f067aa72176fba,0x0a637dc5a2c898a6,0x113f9804bef90dae,0x1b710b35131c471b,
+	0x28db77f523047d84,0x32caab7b40c72493,0x3c9ebe0a15c9bebc,0x431d67c49c100d4c,
+	0x4cc5d4becb3e42b6,0x597f299cfc657e2a,0x5fcb6fab3ad6faec,0x6c44198c4a475817}
+
+
+type HASH512 struct {
+	length [2]uint64
+	h [8]uint64
+	w [80]uint64
+
+}
+
+/* functions */
+func hash512_S(n uint64,x uint64) uint64 {
+	return (((x)>>n) | ((x)<<(64-n)))
+}
+
+func hash512_R(n uint64,x uint64) uint64 {
+	return ((x)>>n)
+}
+
+func hash512_Ch(x,y,z uint64) uint64 {
+	return ((x&y)^(^(x)&z))
+}
+
+func hash512_Maj(x,y,z uint64) uint64 {
+	return ((x&y)^(x&z)^(y&z))
+}
+
+func hash512_Sig0(x uint64) uint64 {
+	return (hash512_S(28,x)^hash512_S(34,x)^hash512_S(39,x))
+}
+
+func hash512_Sig1(x uint64) uint64 {
+	return (hash512_S(14,x)^hash512_S(18,x)^hash512_S(41,x))
+}
+
+func hash512_theta0(x uint64) uint64 {
+	return (hash512_S(1,x)^hash512_S(8,x)^hash512_R(7,x));
+}
+
+func hash512_theta1(x uint64) uint64 {
+		return (hash512_S(19,x)^hash512_S(61,x)^hash512_R(6,x))
+}
+
+func (H *HASH512) transform() { /* basic transformation step */
+	for j:=16;j<80;j++ {
+		H.w[j]=hash512_theta1(H.w[j-2])+H.w[j-7]+hash512_theta0(H.w[j-15])+H.w[j-16]
+	}
+	a:=H.h[0]; b:=H.h[1]; c:=H.h[2]; d:=H.h[3] 
+	e:=H.h[4]; f:=H.h[5]; g:=H.h[6]; hh:=H.h[7]
+	for j:=0;j<80;j++ { /* 80 times - mush it up */
+		t1:=hh+hash512_Sig1(e)+hash512_Ch(e,f,g)+hash512_K[j]+H.w[j]
+		t2:=hash512_Sig0(a)+hash512_Maj(a,b,c)
+		hh=g; g=f; f=e
+		e=d+t1
+		d=c
+		c=b
+		b=a
+		a=t1+t2  
+	}
+	H.h[0]+=a; H.h[1]+=b; H.h[2]+=c; H.h[3]+=d 
+	H.h[4]+=e; H.h[5]+=f; H.h[6]+=g; H.h[7]+=hh 
+} 
+
+/* Initialise Hash function */
+func (H *HASH512) Init() { /* initialise */
+	for i:=0;i<80;i++ {H.w[i]=0}
+	H.length[0]=0; H.length[1]=0
+	H.h[0]=hash512_H0
+	H.h[1]=hash512_H1
+	H.h[2]=hash512_H2
+	H.h[3]=hash512_H3
+	H.h[4]=hash512_H4
+	H.h[5]=hash512_H5
+	H.h[6]=hash512_H6
+	H.h[7]=hash512_H7
+}
+
+func NewHASH512() *HASH512 {
+	H:= new(HASH512)
+	H.Init()
+	return H
+}
+
+/* process a single byte */
+func (H *HASH512) Process(byt byte) { /* process the next message byte */
+	cnt:=(H.length[0]/64)%16;
+    
+	H.w[cnt]<<=8;
+	H.w[cnt]|=uint64(byt&0xFF);
+	H.length[0]+=8;
+	if H.length[0]==0 {H.length[1]++; H.length[0]=0}
+	if (H.length[0]%1024)==0 {H.transform()}
+}
+
+/* process an array of bytes */	
+func (H *HASH512) Process_array(b []byte) {
+	for i:=0;i<len(b);i++ {H.Process((b[i]))}
+}
+
+/* process a 32-bit integer */
+func (H *HASH512) Process_num(n int32) {
+	H.Process(byte((n>>24)&0xff));
+	H.Process(byte((n>>16)&0xff));
+	H.Process(byte((n>>8)&0xff));
+	H.Process(byte(n&0xff));
+}
+
+/* Generate 64-byte Hash */
+func (H *HASH512) Hash() []byte { /* pad message and finish - supply digest */
+	var digest [64]byte
+	len0:=H.length[0]
+	len1:=H.length[1]
+	H.Process(0x80);
+	for (H.length[0]%1024)!=896 {H.Process(0)}
+	H.w[14]=len1;
+	H.w[15]=len0;    
+	H.transform();
+	for i:=0;i<64;i++ { /* convert to bytes */
+		digest[i]=byte((H.h[i/8]>>uint(8*(7-i%8))) & 0xff);
+	}
+	H.Init()
+	return digest[0:64]
+}
+
+/* test program: should produce digest */
+
+//8e959b75dae313da 8cf4f72814fc143f 8f7779c6eb9f7fa1 7299aeadb6889018 501d289e4900f7e4 331b99dec4b5433a c7d329eeb6dd2654 5e96e55b874be909
+/*
+func main() {
+
+	test := []byte("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu")
+	sh:=NewHASH512()
+
+	for i:=0;i<len(test);i++ {
+		sh.Process(test[i])
+	}
+		
+	digest:=sh.Hash()    
+	for i:=0;i<64;i++ {fmt.Printf("%02x",digest[i])}
+
+}
+*/
diff --git a/version3/go/MPIN.go b/version3/go/MPIN.go
new file mode 100644
index 0000000..015de75
--- /dev/null
+++ b/version3/go/MPIN.go
@@ -0,0 +1,755 @@
+/*
+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.
+*/
+
+/* MPIN API Functions */
+
+package XXX
+
+import "time"
+import "github.com/milagro-crypto/amcl/version3/go/amcl"
+
+//import "fmt"
+
+const MFS int=int(MODBYTES)
+const MGS int=int(MODBYTES)
+//const PAS int=16
+const BAD_PARAMS int=-11
+const INVALID_POINT int=-14
+const WRONG_ORDER int=-18
+const BAD_PIN int=-19
+
+
+/* Configure your PIN here */
+
+const MAXPIN int32=10000  /* PIN less than this */
+const PBLEN int32=14      /* Number of bits in PIN */
+const TS int=10         /* 10 for 4 digit PIN, 14 for 6-digit PIN - 2^TS/TS approx = sqrt(MAXPIN) */
+const TRAP int=200      /* 200 for 4 digit PIN, 2000 for 6-digit PIN  - approx 2*sqrt(MAXPIN) */
+
+//const MPIN_HASH_TYPE int=amcl.SHA256
+
+func mpin_hash(sha int,c *FP4,U *ECP) []byte {
+	var w [MFS]byte
+	var t [6*MFS]byte
+	var h []byte
+
+	c.geta().GetA().ToBytes(w[:]); for i:=0;i<MFS;i++ {t[i]=w[i]}
+	c.geta().GetB().ToBytes(w[:]); for i:=MFS;i<2*MFS;i++ {t[i]=w[i-MFS]}
+	c.getb().GetA().ToBytes(w[:]); for i:=2*MFS;i<3*MFS;i++ {t[i]=w[i-2*MFS]}
+	c.getb().GetB().ToBytes(w[:]); for i:=3*MFS;i<4*MFS;i++ {t[i]=w[i-3*MFS]}
+
+	U.GetX().ToBytes(w[:]); for i:=4*MFS;i<5*MFS;i++ {t[i]=w[i-4*MFS]}
+	U.GetY().ToBytes(w[:]); for i:=5*MFS;i<6*MFS;i++ {t[i]=w[i-5*MFS]}
+
+	if sha==amcl.SHA256 {
+		H:=amcl.NewHASH256()
+		H.Process_array(t[:])
+		h=H.Hash()
+	}
+	if sha==amcl.SHA384 {
+		H:=amcl.NewHASH384()
+		H.Process_array(t[:])
+		h=H.Hash()
+	}
+	if sha==amcl.SHA512 {
+		H:=amcl.NewHASH512()
+		H.Process_array(t[:])
+		h=H.Hash()
+	}
+	if h==nil {return nil}
+	R:=make([]byte,AESKEY)
+	for i:=0;i<AESKEY;i++ {R[i]=h[i]}
+	return R
+}
+
+/* Hash number (optional) and string to coordinate on curve */
+
+func mhashit(sha int,n int32,ID []byte) []byte {
+	var R []byte
+	if sha==amcl.SHA256 {
+		H:=amcl.NewHASH256()
+		if n!=0 {H.Process_num(n)}
+		H.Process_array(ID)
+		R=H.Hash()
+	}
+	if sha==amcl.SHA384 {
+		H:=amcl.NewHASH384()
+		if n!=0 {H.Process_num(n)}
+		H.Process_array(ID)
+		R=H.Hash()
+	}
+	if sha==amcl.SHA512 {
+		H:=amcl.NewHASH512()
+		if n!=0 {H.Process_num(n)}
+		H.Process_array(ID)
+		R=H.Hash()
+	}
+	if R==nil {return nil}
+	const RM int=int(MODBYTES)
+	var W [RM]byte
+	if sha>=RM {
+		for i:=0;i<RM;i++ {W[i]=R[i]}
+	} else {
+		for i:=0;i<sha;i++ {W[i+RM-sha]=R[i]}
+		for i:=0;i<RM-sha;i++ {W[i]=0}
+
+
+	//	for i:=0;i<sha;i++ {W[i]=R[i]}	
+	//	for i:=sha;i<RM;i++ {W[i]=0}
+	}
+
+	return W[:]
+}
+
+/* return time in slots since epoch */
+func Today() int {
+	now:=time.Now()
+	return int(now.Unix())/(60*1440)
+}
+
+/* these next two functions help to implement elligator squared - http://eprint.iacr.org/2014/043 */
+/* maps a random u to a point on the curve */
+func emap(u *BIG,cb int) *ECP {
+	var P *ECP
+	x:=NewBIGcopy(u)
+	p:=NewBIGints(Modulus)
+	x.Mod(p)
+	for true {
+		P=NewECPbigint(x,cb)
+		if !P.Is_infinity() {break}
+		x.inc(1);  x.norm()
+	}
+	return P
+}
+
+/* returns u derived from P. Random value in range 1 to return value should then be added to u */
+func unmap(u* BIG,P *ECP) int {
+	s:=P.GetS()
+	var R *ECP
+	r:=0
+	x:=P.GetX()
+	u.copy(x)
+	for true {
+		u.dec(1); u.norm()
+		r++
+		R=NewECPbigint(u,s)
+		if !R.Is_infinity() {break}
+	}
+	return r
+}
+
+func MPIN_HASH_ID(sha int,ID []byte) []byte {
+	return mhashit(sha,0,ID)
+}
+
+/* these next two functions implement elligator squared - http://eprint.iacr.org/2014/043 */
+/* Elliptic curve point E in format (0x04,x,y} is converted to form {0x0-,u,v} */
+/* Note that u and v are indistinguisible from random strings */
+func MPIN_ENCODING(rng *amcl.RAND,E []byte) int {
+	var T [MFS]byte
+
+	for i:=0;i<MFS;i++ {T[i]=E[i+1]}
+	u:=FromBytes(T[:])
+	for i:=0;i<MFS;i++ {T[i]=E[i+MFS+1]}
+	v:=FromBytes(T[:])
+		
+	P:=NewECPbigs(u,v)
+	if P.Is_infinity() {return INVALID_POINT}
+
+	p:=NewBIGints(Modulus)
+	u=Randomnum(p,rng)
+
+	su:=int(rng.GetByte()); /*if (su<0) su=-su;*/ su%=2
+		
+	W:=emap(u,su)
+	P.Sub(W)
+	sv:=P.GetS()
+	rn:=unmap(v,P)
+	m:=int(rng.GetByte()); /*if (m<0) m=-m;*/ m%=rn
+	v.inc(m+1)
+	E[0]=byte(su+2*sv)
+	u.ToBytes(T[:])
+	for i:=0;i<MFS;i++ {E[i+1]=T[i]}
+	v.ToBytes(T[:])
+	for i:=0;i<MFS;i++ {E[i+MFS+1]=T[i]}		
+		
+	return 0
+}
+
+func MPIN_DECODING(D []byte) int {
+	var T [MFS]byte
+
+	if (D[0]&0x04)!=0 {return INVALID_POINT}
+
+	for i:=0;i<MFS;i++ {T[i]=D[i+1]}
+	u:=FromBytes(T[:])
+	for i:=0;i<MFS;i++ {T[i]=D[i+MFS+1]}
+	v:=FromBytes(T[:])
+
+	su:=int(D[0]&1)
+	sv:=int((D[0]>>1)&1)
+	W:=emap(u,su)
+	P:=emap(v,sv)
+	P.Add(W)
+	u=P.GetX()
+	v=P.GetY()
+	D[0]=0x04
+	u.ToBytes(T[:])
+	for i:=0;i<MFS;i++ {D[i+1]=T[i]}
+	v.ToBytes(T[:])
+	for i:=0;i<MFS;i++ {D[i+MFS+1]=T[i]}		
+		
+	return 0
+}
+
+/* R=R1+R2 in group G1 */
+func MPIN_RECOMBINE_G1(R1 []byte,R2 []byte,R []byte) int {
+	P:=ECP_fromBytes(R1)
+	Q:=ECP_fromBytes(R2)
+
+	if (P.Is_infinity() || Q.Is_infinity()) {return INVALID_POINT}
+
+	P.Add(Q)
+
+	P.ToBytes(R[:],false)
+	return 0
+}
+
+/* W=W1+W2 in group G2 */
+func MPIN_RECOMBINE_G2(W1 []byte,W2 []byte,W []byte) int {
+	P:=ECP2_fromBytes(W1)
+	Q:=ECP2_fromBytes(W2)
+
+	if (P.Is_infinity() || Q.Is_infinity()) {return INVALID_POINT}
+
+	P.Add(Q)
+	
+	P.ToBytes(W)
+	return 0
+}
+	
+/* create random secret S */
+func MPIN_RANDOM_GENERATE(rng *amcl.RAND,S []byte) int {
+	r:=NewBIGints(CURVE_Order);
+	s:=Randomnum(r,rng)
+	//if AES_S>0 {
+	//	s.mod2m(2*AES_S)
+	//}		
+	s.ToBytes(S)
+	return 0
+}
+
+
+func MPIN_EXTRACT_PIN(sha int,CID []byte,pin int,TOKEN []byte) int {
+	return MPIN_EXTRACT_FACTOR(sha,CID,int32(pin)%MAXPIN,PBLEN,TOKEN)
+}
+
+/* Extract factor from TOKEN for identity CID */
+func MPIN_EXTRACT_FACTOR(sha int,CID []byte,factor int32,facbits int32,TOKEN []byte) int {
+	P:=ECP_fromBytes(TOKEN)
+	if P.Is_infinity() {return INVALID_POINT}
+	h:=mhashit(sha,0,CID)
+	R:=ECP_mapit(h)
+
+	R=R.pinmul(factor,facbits)
+	P.Sub(R)
+
+	P.ToBytes(TOKEN,false)
+
+	return 0
+}
+
+/* Restore factor to TOKEN for identity CID */
+func MPIN_RESTORE_FACTOR(sha int,CID []byte,factor int32,facbits int32,TOKEN []byte) int {
+	P:=ECP_fromBytes(TOKEN)
+	if P.Is_infinity() {return INVALID_POINT}
+	h:=mhashit(sha,0,CID)
+	R:=ECP_mapit(h)
+
+	R=R.pinmul(factor,facbits)
+	P.Add(R)
+
+	P.ToBytes(TOKEN,false)
+
+	return 0
+}
+
+
+/* Extract PIN from TOKEN for identity CID 
+func MPIN_EXTRACT_PIN(sha int,CID []byte,pin int,TOKEN []byte) int {
+	P:=ECP_fromBytes(TOKEN)
+	if P.Is_infinity() {return INVALID_POINT}
+	h:=mhashit(sha,0,CID)
+	R:=ECP_mapit(h)
+
+	R=R.pinmul(int32(pin)%MAXPIN,PBLEN)
+	P.Sub(R)
+
+	P.ToBytes(TOKEN,false)
+
+	return 0
+}*/
+
+/* Implement step 2 on client side of MPin protocol */
+func MPIN_CLIENT_2(X []byte,Y []byte,SEC []byte) int {
+	r:=NewBIGints(CURVE_Order)
+	P:=ECP_fromBytes(SEC)
+	if P.Is_infinity() {return INVALID_POINT}
+
+	px:=FromBytes(X)
+	py:=FromBytes(Y)
+	px.add(py)
+	px.Mod(r)
+	//px.rsub(r)
+
+	P=G1mul(P,px)
+	P.neg()
+	P.ToBytes(SEC,false)
+	//G1mul(P,px).ToBytes(SEC,false)
+	return 0
+}
+
+/* Implement step 1 on client side of MPin protocol */
+func MPIN_CLIENT_1(sha int,date int,CLIENT_ID []byte,rng *amcl.RAND,X []byte,pin int,TOKEN []byte,SEC []byte,xID []byte,xCID []byte,PERMIT []byte) int {
+	r:=NewBIGints(CURVE_Order)
+		
+	var x *BIG
+	if (rng!=nil) {
+		x=Randomnum(r,rng)
+		//if AES_S>0 {
+		//	x.mod2m(2*AES_S)
+		//}
+		x.ToBytes(X)
+	} else {
+		x=FromBytes(X)
+	}
+
+	h:=mhashit(sha,0,CLIENT_ID)
+	P:=ECP_mapit(h)
+	
+	T:=ECP_fromBytes(TOKEN)
+	if T.Is_infinity() {return INVALID_POINT}
+
+	W:=P.pinmul(int32(pin)%MAXPIN,PBLEN)
+	T.Add(W)
+	if date!=0 {
+		W=ECP_fromBytes(PERMIT)
+		if W.Is_infinity() {return INVALID_POINT}
+		T.Add(W)
+		h=mhashit(sha,int32(date),h)
+		W=ECP_mapit(h)
+		if xID!=nil {
+			P=G1mul(P,x)
+			P.ToBytes(xID,false)
+			W=G1mul(W,x)
+			P.Add(W)
+		} else {
+			P.Add(W)
+			P=G1mul(P,x)
+		}
+		if xCID!=nil {P.ToBytes(xCID,false)}
+	} else {
+		if xID!=nil {
+			P=G1mul(P,x)
+			P.ToBytes(xID,false)
+		}
+	}
+
+
+	T.ToBytes(SEC,false)
+	return 0
+}
+
+/* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */
+func MPIN_GET_SERVER_SECRET(S []byte,SST []byte) int {
+	Q:=ECP2_generator(); 
+
+	s:=FromBytes(S)
+	Q=G2mul(Q,s)
+	Q.ToBytes(SST)
+	return 0
+}
+
+/*
+ W=x*H(G);
+ if RNG == NULL then X is passed in 
+ if RNG != NULL the X is passed out 
+ if type=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve
+*/
+func MPIN_GET_G1_MULTIPLE(rng *amcl.RAND,typ int,X []byte,G []byte,W []byte) int {
+	var x *BIG
+	r:=NewBIGints(CURVE_Order)
+	if rng!=nil {
+		x=Randomnum(r,rng)
+		//if AES_S>0 {
+		//	x.mod2m(2*AES_S)
+		//}
+		x.ToBytes(X)
+	} else {
+		x=FromBytes(X)
+	}
+	var P *ECP
+	if typ==0 {
+		P=ECP_fromBytes(G)
+		if P.Is_infinity() {return INVALID_POINT}
+	} else {P=ECP_mapit(G)}
+
+	G1mul(P,x).ToBytes(W,false)
+	return 0
+}
+
+/* Client secret CST=S*H(CID) where CID is client ID and S is master secret */
+/* CID is hashed externally */
+func MPIN_GET_CLIENT_SECRET(S []byte,CID []byte,CST []byte) int {
+	return MPIN_GET_G1_MULTIPLE(nil,1,S,CID,CST)
+}
+
+/* Time Permit CTT=S*(date|H(CID)) where S is master secret */
+func MPIN_GET_CLIENT_PERMIT(sha,date int,S []byte,CID []byte,CTT []byte) int {
+	h:=mhashit(sha,int32(date),CID)
+	P:=ECP_mapit(h)
+
+	s:=FromBytes(S)
+	G1mul(P,s).ToBytes(CTT,false)
+	return 0
+}
+
+/* Outputs H(CID) and H(T|H(CID)) for time permits. If no time permits set HID=HTID */
+func MPIN_SERVER_1(sha int,date int,CID []byte,HID []byte,HTID []byte) {
+	h:=mhashit(sha,0,CID)
+	P:=ECP_mapit(h)
+	
+	P.ToBytes(HID,false);
+	if date!=0 {
+	//	if HID!=nil {P.ToBytes(HID,false)}
+		h=mhashit(sha,int32(date),h)
+		R:=ECP_mapit(h)
+		P.Add(R)
+		P.ToBytes(HTID,false)
+	} //else {P.ToBytes(HID,false)}
+}
+
+/* Implement step 2 of MPin protocol on server side */
+func MPIN_SERVER_2(date int,HID []byte,HTID []byte,Y []byte,SST []byte,xID []byte,xCID []byte,mSEC []byte,E []byte,F []byte) int {
+//	q:=NewBIGints(Modulus)
+	Q:=ECP2_generator(); 
+
+	sQ:=ECP2_fromBytes(SST)
+	if sQ.Is_infinity() {return INVALID_POINT}	
+
+	var R *ECP
+	if date!=0 {
+		R=ECP_fromBytes(xCID)
+	} else {
+		if xID==nil {return BAD_PARAMS}
+		R=ECP_fromBytes(xID)
+	}
+	if R.Is_infinity() {return INVALID_POINT}
+
+	y:=FromBytes(Y)
+	var P *ECP
+	if date!=0 {
+		P=ECP_fromBytes(HTID)
+	} else {
+		if HID==nil {return BAD_PARAMS}
+		P=ECP_fromBytes(HID)
+	}
+	
+	if P.Is_infinity() {return INVALID_POINT}
+
+	P=G1mul(P,y)
+	P.Add(R)
+	//P.Affine()
+	R=ECP_fromBytes(mSEC)
+	if R.Is_infinity() {return INVALID_POINT}
+
+	var g *FP12
+//		FP12 g1=new FP12(0);
+
+	g=Ate2(Q,R,sQ,P)
+	g=Fexp(g)
+
+	if !g.Isunity() {
+		if (HID!=nil && xID!=nil && E!=nil && F!=nil) {
+			g.ToBytes(E)
+			if date!=0 {
+				P=ECP_fromBytes(HID)
+				if P.Is_infinity() {return INVALID_POINT}
+				R=ECP_fromBytes(xID)
+				if R.Is_infinity() {return INVALID_POINT}
+
+				P=G1mul(P,y)
+				P.Add(R)
+				//P.Affine()
+			}
+			g=Ate(Q,P)
+			g=Fexp(g)
+			g.ToBytes(F)
+		}
+		return BAD_PIN
+	}
+
+	return 0
+}
+
+/* Pollards kangaroos used to return PIN error */
+func MPIN_KANGAROO(E []byte,F []byte) int {
+	ge:=FP12_fromBytes(E)
+	gf:=FP12_fromBytes(F)
+	var distance [TS]int
+	t:=NewFP12copy(gf)
+
+	var table []*FP12
+	var i int
+	s:=1
+	for m:=0;m<TS;m++ {
+		distance[m]=s
+		table=append(table,NewFP12copy(t))
+		s*=2
+		t.usqr()
+	}
+	t.one()
+	dn:=0
+	for j:=0;j<TRAP;j++ {
+		i=t.geta().geta().GetA().lastbits(20)%TS
+		t.Mul(table[i])
+		dn+=distance[i]
+	}
+	gf.Copy(t); gf.conj()
+	steps:=0; dm:=0
+	res:=0
+	for dm-dn<int(MAXPIN) {
+		steps++
+		if steps>4*TRAP {break}
+		i=ge.geta().geta().GetA().lastbits(20)%TS;
+		ge.Mul(table[i])
+		dm+=distance[i]
+		if ge.Equals(t) {
+			res=dm-dn
+			break;
+		}
+		if ge.Equals(gf) {
+			res=dn-dm
+			break
+		}
+
+	}
+	if (steps>4*TRAP || dm-dn>=int(MAXPIN)) {res=0 }    // Trap Failed  - probable invalid token
+	return int(res)
+}
+
+/* Functions to support M-Pin Full */
+
+func MPIN_PRECOMPUTE(TOKEN []byte,CID []byte,G1 []byte,G2 []byte) int {
+	var P,T *ECP
+	var g *FP12
+
+	T=ECP_fromBytes(TOKEN)
+	if T.Is_infinity() {return INVALID_POINT} 
+
+	P=ECP_mapit(CID)
+
+	Q:=ECP2_generator(); 
+
+	g=Ate(Q,T)
+	g=Fexp(g)
+	g.ToBytes(G1)
+
+	g=Ate(Q,P)
+	g=Fexp(g)
+	g.ToBytes(G2)
+
+	return 0
+}
+
+/* Hash the M-Pin transcript - new */
+
+func MPIN_HASH_ALL(sha int,HID []byte,xID []byte,xCID []byte,SEC []byte,Y []byte,R []byte,W []byte) []byte {
+	tlen:=0
+	var T [10*int(MODBYTES)+4]byte
+
+	for i:=0;i<len(HID);i++ {T[i]=HID[i]}
+	tlen+=len(HID)
+	if xCID!=nil {
+		for i:=0;i<len(xCID);i++ {T[i+tlen]=xCID[i]}
+		tlen+=len(xCID)
+	} else {
+		for i:=0;i<len(xID);i++ {T[i+tlen]=xID[i]}
+		tlen+=len(xID)
+	}	
+	for i:=0;i<len(SEC);i++ {T[i+tlen]=SEC[i]}
+	tlen+=len(SEC)		
+	for i:=0;i<len(Y);i++ {T[i+tlen]=Y[i]}
+	tlen+=len(Y)
+	for i:=0;i<len(R);i++ {T[i+tlen]=R[i]}
+	tlen+=len(R)		
+	for i:=0;i<len(W);i++ {T[i+tlen]=W[i]}
+	tlen+=len(W)	
+
+	return mhashit(sha,0,T[:])
+}
+
+/* calculate common key on client side */
+/* wCID = w.(A+AT) */
+func MPIN_CLIENT_KEY(sha int,G1 []byte,G2 []byte,pin int,R []byte,X []byte,H []byte,wCID []byte,CK []byte) int {
+
+	g1:=FP12_fromBytes(G1)
+	g2:=FP12_fromBytes(G2)
+	z:=FromBytes(R)
+	x:=FromBytes(X)
+	h:=FromBytes(H)
+
+	W:=ECP_fromBytes(wCID)
+	if W.Is_infinity() {return INVALID_POINT} 
+
+	W=G1mul(W,x)
+
+//	f:=NewFP2bigs(NewBIGints(Fra),NewBIGints(Frb))
+	r:=NewBIGints(CURVE_Order)
+//	q:=NewBIGints(Modulus)
+
+	z.add(h);	//new
+	z.Mod(r);
+
+	g2.pinpow(pin,int(PBLEN))
+	g1.Mul(g2)
+
+	c:=g1.Compow(z,r);
+/*
+	m:=NewBIGcopy(q)
+	m.Mod(r)
+
+	a:=NewBIGcopy(z)
+	a.Mod(m)
+
+	b:=NewBIGcopy(z)
+	b.div(m)
+
+
+	c:=g1.trace()
+	g2.Copy(g1)
+	g2.frob(f)
+	cp:=g2.trace()
+	g1.conj()
+	g2.Mul(g1)
+	cpm1:=g2.trace()
+	g2.Mul(g1)
+	cpm2:=g2.trace()
+
+	c=c.xtr_pow2(cp,cpm1,cpm2,a,b)
+*/
+	t:=mpin_hash(sha,c,W);
+
+	for i:=0;i<AESKEY;i++ {CK[i]=t[i]}
+
+	return 0
+}
+
+/* calculate common key on server side */
+/* Z=r.A - no time permits involved */
+
+func MPIN_SERVER_KEY(sha int,Z []byte,SST []byte,W []byte,H []byte,HID []byte,xID []byte,xCID []byte,SK []byte) int {
+	sQ:=ECP2_fromBytes(SST)
+	if sQ.Is_infinity() {return INVALID_POINT} 
+	R:=ECP_fromBytes(Z)
+	if R.Is_infinity() {return INVALID_POINT} 
+	A:=ECP_fromBytes(HID)
+	if A.Is_infinity() {return INVALID_POINT} 
+
+	var U *ECP
+	if xCID!=nil {
+		U=ECP_fromBytes(xCID)
+	} else	{U=ECP_fromBytes(xID)}
+	if U.Is_infinity() {return INVALID_POINT} 
+
+	w:=FromBytes(W)
+	h:=FromBytes(H)
+	A=G1mul(A,h)	// new
+	R.Add(A)
+	//R.Affine()
+
+	U=G1mul(U,w)
+	g:=Ate(sQ,R)
+	g=Fexp(g)
+
+	c:=g.trace()
+
+	t:=mpin_hash(sha,c,U)
+
+	for i:=0;i<AESKEY;i++ {SK[i]=t[i]}
+
+	return 0
+}
+
+/* return time since epoch */
+func MPIN_GET_TIME() int {
+	now:=time.Now()
+	return int(now.Unix())
+}
+
+/* Generate Y = H(epoch, xCID/xID) */
+func MPIN_GET_Y(sha int,TimeValue int,xCID []byte,Y []byte) {
+	h:= mhashit(sha,int32(TimeValue),xCID)
+	y:= FromBytes(h)
+	q:=NewBIGints(CURVE_Order)
+	y.Mod(q)
+	//if AES_S>0 {
+	//	y.mod2m(2*AES_S)
+	//}
+	y.ToBytes(Y)
+}
+        
+/* One pass MPIN Client */
+func MPIN_CLIENT(sha int,date int,CLIENT_ID []byte,RNG *amcl.RAND,X []byte,pin int,TOKEN []byte,SEC []byte,xID []byte,xCID []byte,PERMIT []byte,TimeValue int,Y []byte) int {
+	rtn:=0
+        
+	var pID []byte
+	if date == 0 {
+		pID = xID
+	} else {pID = xCID}
+          
+	rtn = MPIN_CLIENT_1(sha,date,CLIENT_ID,RNG,X,pin,TOKEN,SEC,xID,xCID,PERMIT)
+	if rtn != 0 {return rtn}
+        
+	MPIN_GET_Y(sha,TimeValue,pID,Y)
+        
+	rtn = MPIN_CLIENT_2(X,Y,SEC)
+	if rtn != 0 {return rtn}
+        
+	return 0
+}
+
+/* One pass MPIN Server */
+func MPIN_SERVER(sha int,date int,HID []byte,HTID []byte,Y []byte,SST []byte,xID []byte,xCID []byte,SEC []byte,E []byte,F []byte,CID []byte,TimeValue int) int {
+	rtn:=0
+        
+	var pID []byte
+	if date == 0 {
+		pID = xID
+	} else {pID = xCID}
+       
+	MPIN_SERVER_1(sha,date,CID,HID,HTID)
+	MPIN_GET_Y(sha,TimeValue,pID,Y);
+    
+	rtn = MPIN_SERVER_2(date,HID,HTID,Y,SST,xID,xCID,SEC,E,F)
+	if rtn != 0 {return rtn}
+        
+	return 0
+}
+
diff --git a/version3/go/MPIN192.go b/version3/go/MPIN192.go
new file mode 100644
index 0000000..13873ae
--- /dev/null
+++ b/version3/go/MPIN192.go
@@ -0,0 +1,760 @@
+/*
+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.
+*/
+
+/* MPIN API Functions */
+
+package XXX
+
+import "time"
+import "github.com/milagro-crypto/amcl/version3/go/amcl"
+
+//import "fmt"
+
+const MFS int=int(MODBYTES)
+const MGS int=int(MODBYTES)
+//const PAS int=16
+const BAD_PARAMS int=-11
+const INVALID_POINT int=-14
+const WRONG_ORDER int=-18
+const BAD_PIN int=-19
+
+
+/* Configure your PIN here */
+
+const MAXPIN int32=10000  /* PIN less than this */
+const PBLEN int32=14      /* Number of bits in PIN */
+const TS int=10         /* 10 for 4 digit PIN, 14 for 6-digit PIN - 2^TS/TS approx = sqrt(MAXPIN) */
+const TRAP int=200      /* 200 for 4 digit PIN, 2000 for 6-digit PIN  - approx 2*sqrt(MAXPIN) */
+
+//const MPIN_HASH_TYPE int=amcl.SHA256
+
+func mpin_hash(sha int,c *FP8,U *ECP) []byte {
+	var w [MFS]byte
+	var t [10*MFS]byte
+	var h []byte
+
+	c.geta().geta().GetA().ToBytes(w[:]); for i:=0;i<MFS;i++ {t[i]=w[i]}
+	c.geta().geta().GetB().ToBytes(w[:]); for i:=MFS;i<2*MFS;i++ {t[i]=w[i-MFS]}
+	c.geta().getb().GetA().ToBytes(w[:]); for i:=2*MFS;i<3*MFS;i++ {t[i]=w[i-2*MFS]}
+	c.geta().getb().GetB().ToBytes(w[:]); for i:=3*MFS;i<4*MFS;i++ {t[i]=w[i-3*MFS]}
+
+	c.getb().geta().GetA().ToBytes(w[:]); for i:=4*MFS;i<5*MFS;i++ {t[i]=w[i-4*MFS]}
+	c.getb().geta().GetB().ToBytes(w[:]); for i:=5*MFS;i<6*MFS;i++ {t[i]=w[i-5*MFS]}
+	c.getb().getb().GetA().ToBytes(w[:]); for i:=6*MFS;i<7*MFS;i++ {t[i]=w[i-6*MFS]}
+	c.getb().getb().GetB().ToBytes(w[:]); for i:=7*MFS;i<8*MFS;i++ {t[i]=w[i-7*MFS]}
+
+
+	U.GetX().ToBytes(w[:]); for i:=8*MFS;i<9*MFS;i++ {t[i]=w[i-8*MFS]}
+	U.GetY().ToBytes(w[:]); for i:=9*MFS;i<10*MFS;i++ {t[i]=w[i-9*MFS]}
+
+	if sha==amcl.SHA256 {
+		H:=amcl.NewHASH256()
+		H.Process_array(t[:])
+		h=H.Hash()
+	}
+	if sha==amcl.SHA384 {
+		H:=amcl.NewHASH384()
+		H.Process_array(t[:])
+		h=H.Hash()
+	}
+	if sha==amcl.SHA512 {
+		H:=amcl.NewHASH512()
+		H.Process_array(t[:])
+		h=H.Hash()
+	}
+	if h==nil {return nil}
+	R:=make([]byte,AESKEY)
+	for i:=0;i<AESKEY;i++ {R[i]=h[i]}
+	return R
+}
+
+/* Hash number (optional) and string to coordinate on curve */
+
+func mhashit(sha int,n int32,ID []byte) []byte {
+	var R []byte
+	if sha==amcl.SHA256 {
+		H:=amcl.NewHASH256()
+		if n!=0 {H.Process_num(n)}
+		H.Process_array(ID)
+		R=H.Hash()
+	}
+	if sha==amcl.SHA384 {
+		H:=amcl.NewHASH384()
+		if n!=0 {H.Process_num(n)}
+		H.Process_array(ID)
+		R=H.Hash()
+	}
+	if sha==amcl.SHA512 {
+		H:=amcl.NewHASH512()
+		if n!=0 {H.Process_num(n)}
+		H.Process_array(ID)
+		R=H.Hash()
+	}
+	if R==nil {return nil}
+	const RM int=int(MODBYTES)
+	var W [RM]byte
+	if sha>=RM {
+		for i:=0;i<RM;i++ {W[i]=R[i]}
+	} else {
+		for i:=0;i<sha;i++ {W[i+RM-sha]=R[i]}
+		for i:=0;i<RM-sha;i++ {W[i]=0}
+
+
+	//	for i:=0;i<sha;i++ {W[i]=R[i]}	
+	//	for i:=sha;i<RM;i++ {W[i]=0}
+	}
+
+	return W[:]
+}
+
+/* return time in slots since epoch */
+func Today() int {
+	now:=time.Now()
+	return int(now.Unix())/(60*1440)
+}
+
+/* these next two functions help to implement elligator squared - http://eprint.iacr.org/2014/043 */
+/* maps a random u to a point on the curve */
+func emap(u *BIG,cb int) *ECP {
+	var P *ECP
+	x:=NewBIGcopy(u)
+	p:=NewBIGints(Modulus)
+	x.Mod(p)
+	for true {
+		P=NewECPbigint(x,cb)
+		if !P.Is_infinity() {break}
+		x.inc(1);  x.norm()
+	}
+	return P
+}
+
+/* returns u derived from P. Random value in range 1 to return value should then be added to u */
+func unmap(u* BIG,P *ECP) int {
+	s:=P.GetS()
+	var R *ECP
+	r:=0
+	x:=P.GetX()
+	u.copy(x)
+	for true {
+		u.dec(1); u.norm()
+		r++
+		R=NewECPbigint(u,s)
+		if !R.Is_infinity() {break}
+	}
+	return r
+}
+
+func MPIN_HASH_ID(sha int,ID []byte) []byte {
+	return mhashit(sha,0,ID)
+}
+
+/* these next two functions implement elligator squared - http://eprint.iacr.org/2014/043 */
+/* Elliptic curve point E in format (0x04,x,y} is converted to form {0x0-,u,v} */
+/* Note that u and v are indistinguisible from random strings */
+func MPIN_ENCODING(rng *amcl.RAND,E []byte) int {
+	var T [MFS]byte
+
+	for i:=0;i<MFS;i++ {T[i]=E[i+1]}
+	u:=FromBytes(T[:])
+	for i:=0;i<MFS;i++ {T[i]=E[i+MFS+1]}
+	v:=FromBytes(T[:])
+		
+	P:=NewECPbigs(u,v)
+	if P.Is_infinity() {return INVALID_POINT}
+
+	p:=NewBIGints(Modulus)
+	u=Randomnum(p,rng)
+
+	su:=int(rng.GetByte()); /*if (su<0) su=-su;*/ su%=2
+		
+	W:=emap(u,su)
+	P.Sub(W)
+	sv:=P.GetS()
+	rn:=unmap(v,P)
+	m:=int(rng.GetByte()); /*if (m<0) m=-m;*/ m%=rn
+	v.inc(m+1)
+	E[0]=byte(su+2*sv)
+	u.ToBytes(T[:])
+	for i:=0;i<MFS;i++ {E[i+1]=T[i]}
+	v.ToBytes(T[:])
+	for i:=0;i<MFS;i++ {E[i+MFS+1]=T[i]}		
+		
+	return 0
+}
+
+func MPIN_DECODING(D []byte) int {
+	var T [MFS]byte
+
+	if (D[0]&0x04)!=0 {return INVALID_POINT}
+
+	for i:=0;i<MFS;i++ {T[i]=D[i+1]}
+	u:=FromBytes(T[:])
+	for i:=0;i<MFS;i++ {T[i]=D[i+MFS+1]}
+	v:=FromBytes(T[:])
+
+	su:=int(D[0]&1)
+	sv:=int((D[0]>>1)&1)
+	W:=emap(u,su)
+	P:=emap(v,sv)
+	P.Add(W)
+	u=P.GetX()
+	v=P.GetY()
+	D[0]=0x04
+	u.ToBytes(T[:])
+	for i:=0;i<MFS;i++ {D[i+1]=T[i]}
+	v.ToBytes(T[:])
+	for i:=0;i<MFS;i++ {D[i+MFS+1]=T[i]}		
+		
+	return 0
+}
+
+/* R=R1+R2 in group G1 */
+func MPIN_RECOMBINE_G1(R1 []byte,R2 []byte,R []byte) int {
+	P:=ECP_fromBytes(R1)
+	Q:=ECP_fromBytes(R2)
+
+	if (P.Is_infinity() || Q.Is_infinity()) {return INVALID_POINT}
+
+	P.Add(Q)
+
+	P.ToBytes(R[:],false)
+	return 0
+}
+
+/* W=W1+W2 in group G2 */
+func MPIN_RECOMBINE_G2(W1 []byte,W2 []byte,W []byte) int {
+	P:=ECP4_fromBytes(W1)
+	Q:=ECP4_fromBytes(W2)
+
+	if (P.Is_infinity() || Q.Is_infinity()) {return INVALID_POINT}
+
+	P.Add(Q)
+	
+	P.ToBytes(W)
+	return 0
+}
+	
+/* create random secret S */
+func MPIN_RANDOM_GENERATE(rng *amcl.RAND,S []byte) int {
+	r:=NewBIGints(CURVE_Order);
+	s:=Randomnum(r,rng)
+	//if AES_S>0 {
+	//	s.mod2m(2*AES_S)
+	//}		
+	s.ToBytes(S)
+	return 0
+}
+
+
+func MPIN_EXTRACT_PIN(sha int,CID []byte,pin int,TOKEN []byte) int {
+	return MPIN_EXTRACT_FACTOR(sha,CID,int32(pin)%MAXPIN,PBLEN,TOKEN)
+}
+
+/* Extract factor from TOKEN for identity CID */
+func MPIN_EXTRACT_FACTOR(sha int,CID []byte,factor int32,facbits int32,TOKEN []byte) int {
+	P:=ECP_fromBytes(TOKEN)
+	if P.Is_infinity() {return INVALID_POINT}
+	h:=mhashit(sha,0,CID)
+	R:=ECP_mapit(h)
+
+	R=R.pinmul(factor,facbits)
+	P.Sub(R)
+
+	P.ToBytes(TOKEN,false)
+
+	return 0
+}
+
+/* Restore factor to TOKEN for identity CID */
+func MPIN_RESTORE_FACTOR(sha int,CID []byte,factor int32,facbits int32,TOKEN []byte) int {
+	P:=ECP_fromBytes(TOKEN)
+	if P.Is_infinity() {return INVALID_POINT}
+	h:=mhashit(sha,0,CID)
+	R:=ECP_mapit(h)
+
+	R=R.pinmul(factor,facbits)
+	P.Add(R)
+
+	P.ToBytes(TOKEN,false)
+
+	return 0
+}
+
+
+/* Extract PIN from TOKEN for identity CID 
+func MPIN_EXTRACT_PIN(sha int,CID []byte,pin int,TOKEN []byte) int {
+	P:=ECP_fromBytes(TOKEN)
+	if P.Is_infinity() {return INVALID_POINT}
+	h:=mhashit(sha,0,CID)
+	R:=ECP_mapit(h)
+
+	R=R.pinmul(int32(pin)%MAXPIN,PBLEN)
+	P.Sub(R)
+
+	P.ToBytes(TOKEN,false)
+
+	return 0
+}*/
+
+/* Implement step 2 on client side of MPin protocol */
+func MPIN_CLIENT_2(X []byte,Y []byte,SEC []byte) int {
+	r:=NewBIGints(CURVE_Order)
+	P:=ECP_fromBytes(SEC)
+	if P.Is_infinity() {return INVALID_POINT}
+
+	px:=FromBytes(X)
+	py:=FromBytes(Y)
+	px.add(py)
+	px.Mod(r)
+	//px.rsub(r)
+
+	P=G1mul(P,px)
+	P.neg()
+	P.ToBytes(SEC,false)
+	//G1mul(P,px).ToBytes(SEC,false)
+	return 0
+}
+
+/* Implement step 1 on client side of MPin protocol */
+func MPIN_CLIENT_1(sha int,date int,CLIENT_ID []byte,rng *amcl.RAND,X []byte,pin int,TOKEN []byte,SEC []byte,xID []byte,xCID []byte,PERMIT []byte) int {
+	r:=NewBIGints(CURVE_Order)
+		
+	var x *BIG
+	if (rng!=nil) {
+		x=Randomnum(r,rng)
+		//if AES_S>0 {
+		//	x.mod2m(2*AES_S)
+		//}
+		x.ToBytes(X)
+	} else {
+		x=FromBytes(X)
+	}
+
+	h:=mhashit(sha,0,CLIENT_ID)
+	P:=ECP_mapit(h)
+	
+	T:=ECP_fromBytes(TOKEN)
+	if T.Is_infinity() {return INVALID_POINT}
+
+	W:=P.pinmul(int32(pin)%MAXPIN,PBLEN)
+	T.Add(W)
+	if date!=0 {
+		W=ECP_fromBytes(PERMIT)
+		if W.Is_infinity() {return INVALID_POINT}
+		T.Add(W)
+		h=mhashit(sha,int32(date),h)
+		W=ECP_mapit(h)
+		if xID!=nil {
+			P=G1mul(P,x)
+			P.ToBytes(xID,false)
+			W=G1mul(W,x)
+			P.Add(W)
+		} else {
+			P.Add(W)
+			P=G1mul(P,x)
+		}
+		if xCID!=nil {P.ToBytes(xCID,false)}
+	} else {
+		if xID!=nil {
+			P=G1mul(P,x)
+			P.ToBytes(xID,false)
+		}
+	}
+
+
+	T.ToBytes(SEC,false)
+	return 0
+}
+
+/* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */
+func MPIN_GET_SERVER_SECRET(S []byte,SST []byte) int {
+	Q:=ECP4_generator(); 
+
+	s:=FromBytes(S)
+	Q=G2mul(Q,s)
+	Q.ToBytes(SST)
+	return 0
+}
+
+/*
+ W=x*H(G);
+ if RNG == NULL then X is passed in 
+ if RNG != NULL the X is passed out 
+ if type=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve
+*/
+func MPIN_GET_G1_MULTIPLE(rng *amcl.RAND,typ int,X []byte,G []byte,W []byte) int {
+	var x *BIG
+	r:=NewBIGints(CURVE_Order)
+	if rng!=nil {
+		x=Randomnum(r,rng)
+		//if AES_S>0 {
+		//	x.mod2m(2*AES_S)
+		//}
+		x.ToBytes(X)
+	} else {
+		x=FromBytes(X)
+	}
+	var P *ECP
+	if typ==0 {
+		P=ECP_fromBytes(G)
+		if P.Is_infinity() {return INVALID_POINT}
+	} else {P=ECP_mapit(G)}
+
+	G1mul(P,x).ToBytes(W,false)
+	return 0
+}
+
+/* Client secret CST=S*H(CID) where CID is client ID and S is master secret */
+/* CID is hashed externally */
+func MPIN_GET_CLIENT_SECRET(S []byte,CID []byte,CST []byte) int {
+	return MPIN_GET_G1_MULTIPLE(nil,1,S,CID,CST)
+}
+
+/* Time Permit CTT=S*(date|H(CID)) where S is master secret */
+func MPIN_GET_CLIENT_PERMIT(sha,date int,S []byte,CID []byte,CTT []byte) int {
+	h:=mhashit(sha,int32(date),CID)
+	P:=ECP_mapit(h)
+
+	s:=FromBytes(S)
+	G1mul(P,s).ToBytes(CTT,false)
+	return 0
+}
+
+/* Outputs H(CID) and H(T|H(CID)) for time permits. If no time permits set HID=HTID */
+func MPIN_SERVER_1(sha int,date int,CID []byte,HID []byte,HTID []byte) {
+	h:=mhashit(sha,0,CID)
+	P:=ECP_mapit(h)
+	
+	P.ToBytes(HID,false);
+	if date!=0 {
+	//	if HID!=nil {P.ToBytes(HID,false)}
+		h=mhashit(sha,int32(date),h)
+		R:=ECP_mapit(h)
+		P.Add(R)
+		P.ToBytes(HTID,false)
+	} //else {P.ToBytes(HID,false)}
+}
+
+/* Implement step 2 of MPin protocol on server side */
+func MPIN_SERVER_2(date int,HID []byte,HTID []byte,Y []byte,SST []byte,xID []byte,xCID []byte,mSEC []byte,E []byte,F []byte) int {
+//	q:=NewBIGints(Modulus)
+	Q:=ECP4_generator(); 
+
+	sQ:=ECP4_fromBytes(SST)
+	if sQ.Is_infinity() {return INVALID_POINT}	
+
+	var R *ECP
+	if date!=0 {
+		R=ECP_fromBytes(xCID)
+	} else {
+		if xID==nil {return BAD_PARAMS}
+		R=ECP_fromBytes(xID)
+	}
+	if R.Is_infinity() {return INVALID_POINT}
+
+	y:=FromBytes(Y)
+	var P *ECP
+	if date!=0 {
+		P=ECP_fromBytes(HTID)
+	} else {
+		if HID==nil {return BAD_PARAMS}
+		P=ECP_fromBytes(HID)
+	}
+	
+	if P.Is_infinity() {return INVALID_POINT}
+
+	P=G1mul(P,y)
+	P.Add(R)
+	//P.Affine()
+	R=ECP_fromBytes(mSEC)
+	if R.Is_infinity() {return INVALID_POINT}
+
+	var g *FP24
+
+	g=Ate2(Q,R,sQ,P)
+	g=Fexp(g)
+
+	if !g.Isunity() {
+		if (HID!=nil && xID!=nil && E!=nil && F!=nil) {
+			g.ToBytes(E)
+			if date!=0 {
+				P=ECP_fromBytes(HID)
+				if P.Is_infinity() {return INVALID_POINT}
+				R=ECP_fromBytes(xID)
+				if R.Is_infinity() {return INVALID_POINT}
+
+				P=G1mul(P,y)
+				P.Add(R)
+				//P.Affine()
+			}
+			g=Ate(Q,P)
+			g=Fexp(g)
+			g.ToBytes(F)
+		}
+		return BAD_PIN
+	}
+
+	return 0
+}
+
+/* Pollards kangaroos used to return PIN error */
+func MPIN_KANGAROO(E []byte,F []byte) int {
+	ge:=FP24_fromBytes(E)
+	gf:=FP24_fromBytes(F)
+	var distance [TS]int
+	t:=NewFP24copy(gf)
+
+	var table []*FP24
+	var i int
+	s:=1
+	for m:=0;m<TS;m++ {
+		distance[m]=s
+		table=append(table,NewFP24copy(t))
+		s*=2
+		t.usqr()
+	}
+	t.one()
+	dn:=0
+	for j:=0;j<TRAP;j++ {
+		i=t.geta().geta().geta().GetA().lastbits(20)%TS
+		t.Mul(table[i])
+		dn+=distance[i]
+	}
+	gf.Copy(t); gf.conj()
+	steps:=0; dm:=0
+	res:=0
+	for dm-dn<int(MAXPIN) {
+		steps++
+		if steps>4*TRAP {break}
+		i=ge.geta().geta().geta().GetA().lastbits(20)%TS;
+		ge.Mul(table[i])
+		dm+=distance[i]
+		if ge.Equals(t) {
+			res=dm-dn
+			break;
+		}
+		if ge.Equals(gf) {
+			res=dn-dm
+			break
+		}
+
+	}
+	if (steps>4*TRAP || dm-dn>=int(MAXPIN)) {res=0 }    // Trap Failed  - probable invalid token
+	return int(res)
+}
+
+/* Functions to support M-Pin Full */
+
+func MPIN_PRECOMPUTE(TOKEN []byte,CID []byte,G1 []byte,G2 []byte) int {
+	var P,T *ECP
+	var g *FP24
+
+	T=ECP_fromBytes(TOKEN)
+	if T.Is_infinity() {return INVALID_POINT} 
+
+	P=ECP_mapit(CID)
+
+	Q:=ECP4_generator(); 
+
+	g=Ate(Q,T)
+	g=Fexp(g)
+	g.ToBytes(G1)
+
+	g=Ate(Q,P)
+	g=Fexp(g)
+	g.ToBytes(G2)
+
+	return 0
+}
+
+/* Hash the M-Pin transcript - new */
+
+func MPIN_HASH_ALL(sha int,HID []byte,xID []byte,xCID []byte,SEC []byte,Y []byte,R []byte,W []byte) []byte {
+	tlen:=0
+	var T [10*int(MODBYTES)+4]byte
+
+	for i:=0;i<len(HID);i++ {T[i]=HID[i]}
+	tlen+=len(HID)
+	if xCID!=nil {
+		for i:=0;i<len(xCID);i++ {T[i+tlen]=xCID[i]}
+		tlen+=len(xCID)
+	} else {
+		for i:=0;i<len(xID);i++ {T[i+tlen]=xID[i]}
+		tlen+=len(xID)
+	}	
+	for i:=0;i<len(SEC);i++ {T[i+tlen]=SEC[i]}
+	tlen+=len(SEC)		
+	for i:=0;i<len(Y);i++ {T[i+tlen]=Y[i]}
+	tlen+=len(Y)
+	for i:=0;i<len(R);i++ {T[i+tlen]=R[i]}
+	tlen+=len(R)		
+	for i:=0;i<len(W);i++ {T[i+tlen]=W[i]}
+	tlen+=len(W)	
+
+	return mhashit(sha,0,T[:])
+}
+
+/* calculate common key on client side */
+/* wCID = w.(A+AT) */
+func MPIN_CLIENT_KEY(sha int,G1 []byte,G2 []byte,pin int,R []byte,X []byte,H []byte,wCID []byte,CK []byte) int {
+
+	g1:=FP24_fromBytes(G1)
+	g2:=FP24_fromBytes(G2)
+	z:=FromBytes(R)
+	x:=FromBytes(X)
+	h:=FromBytes(H)
+
+	W:=ECP_fromBytes(wCID)
+	if W.Is_infinity() {return INVALID_POINT} 
+
+	W=G1mul(W,x)
+
+//	f:=NewFP2bigs(NewBIGints(Fra),NewBIGints(Frb))
+	r:=NewBIGints(CURVE_Order)
+//	q:=NewBIGints(Modulus)
+
+	z.add(h);	//new
+	z.Mod(r);
+
+	g2.pinpow(pin,int(PBLEN))
+	g1.Mul(g2)
+
+	c:=g1.Compow(z,r);
+/*
+	m:=NewBIGcopy(q)
+	m.Mod(r)
+
+	a:=NewBIGcopy(z)
+	a.Mod(m)
+
+	b:=NewBIGcopy(z)
+	b.div(m)
+
+
+	c:=g1.trace()
+	g2.Copy(g1)
+	g2.frob(f)
+	cp:=g2.trace()
+	g1.conj()
+	g2.Mul(g1)
+	cpm1:=g2.trace()
+	g2.Mul(g1)
+	cpm2:=g2.trace()
+
+	c=c.xtr_pow2(cp,cpm1,cpm2,a,b)
+*/
+	t:=mpin_hash(sha,c,W);
+
+	for i:=0;i<AESKEY;i++ {CK[i]=t[i]}
+
+	return 0
+}
+
+/* calculate common key on server side */
+/* Z=r.A - no time permits involved */
+
+func MPIN_SERVER_KEY(sha int,Z []byte,SST []byte,W []byte,H []byte,HID []byte,xID []byte,xCID []byte,SK []byte) int {
+	sQ:=ECP4_fromBytes(SST)
+	if sQ.Is_infinity() {return INVALID_POINT} 
+	R:=ECP_fromBytes(Z)
+	if R.Is_infinity() {return INVALID_POINT} 
+	A:=ECP_fromBytes(HID)
+	if A.Is_infinity() {return INVALID_POINT} 
+
+	var U *ECP
+	if xCID!=nil {
+		U=ECP_fromBytes(xCID)
+	} else	{U=ECP_fromBytes(xID)}
+	if U.Is_infinity() {return INVALID_POINT} 
+
+	w:=FromBytes(W)
+	h:=FromBytes(H)
+	A=G1mul(A,h)	// new
+	R.Add(A)
+	//R.Affine()
+
+	U=G1mul(U,w)
+	g:=Ate(sQ,R)
+	g=Fexp(g)
+
+	c:=g.trace()
+
+	t:=mpin_hash(sha,c,U)
+
+	for i:=0;i<AESKEY;i++ {SK[i]=t[i]}
+
+	return 0
+}
+
+/* return time since epoch */
+func MPIN_GET_TIME() int {
+	now:=time.Now()
+	return int(now.Unix())
+}
+
+/* Generate Y = H(epoch, xCID/xID) */
+func MPIN_GET_Y(sha int,TimeValue int,xCID []byte,Y []byte) {
+	h:= mhashit(sha,int32(TimeValue),xCID)
+	y:= FromBytes(h)
+	q:=NewBIGints(CURVE_Order)
+	y.Mod(q)
+	//if AES_S>0 {
+	//	y.mod2m(2*AES_S)
+	//}
+	y.ToBytes(Y)
+}
+        
+/* One pass MPIN Client */
+func MPIN_CLIENT(sha int,date int,CLIENT_ID []byte,RNG *amcl.RAND,X []byte,pin int,TOKEN []byte,SEC []byte,xID []byte,xCID []byte,PERMIT []byte,TimeValue int,Y []byte) int {
+	rtn:=0
+        
+	var pID []byte
+	if date == 0 {
+		pID = xID
+	} else {pID = xCID}
+          
+	rtn = MPIN_CLIENT_1(sha,date,CLIENT_ID,RNG,X,pin,TOKEN,SEC,xID,xCID,PERMIT)
+	if rtn != 0 {return rtn}
+        
+	MPIN_GET_Y(sha,TimeValue,pID,Y)
+        
+	rtn = MPIN_CLIENT_2(X,Y,SEC)
+	if rtn != 0 {return rtn}
+        
+	return 0
+}
+
+/* One pass MPIN Server */
+func MPIN_SERVER(sha int,date int,HID []byte,HTID []byte,Y []byte,SST []byte,xID []byte,xCID []byte,SEC []byte,E []byte,F []byte,CID []byte,TimeValue int) int {
+	rtn:=0
+        
+	var pID []byte
+	if date == 0 {
+		pID = xID
+	} else {pID = xCID}
+       
+	MPIN_SERVER_1(sha,date,CID,HID,HTID)
+	MPIN_GET_Y(sha,TimeValue,pID,Y);
+    
+	rtn = MPIN_SERVER_2(date,HID,HTID,Y,SST,xID,xCID,SEC,E,F)
+	if rtn != 0 {return rtn}
+        
+	return 0
+}
+
diff --git a/version3/go/MPIN256.go b/version3/go/MPIN256.go
new file mode 100644
index 0000000..d02d32d
--- /dev/null
+++ b/version3/go/MPIN256.go
@@ -0,0 +1,728 @@
+/*
+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.
+*/
+
+/* MPIN API Functions */
+
+package XXX
+
+import "time"
+import "github.com/milagro-crypto/amcl/version3/go/amcl"
+
+//import "fmt"
+
+const MFS int=int(MODBYTES)
+const MGS int=int(MODBYTES)
+//const PAS int=16
+const BAD_PARAMS int=-11
+const INVALID_POINT int=-14
+const WRONG_ORDER int=-18
+const BAD_PIN int=-19
+
+/* Configure your PIN here */
+
+const MAXPIN int32=10000  /* PIN less than this */
+const PBLEN int32=14      /* Number of bits in PIN */
+const TS int=10         /* 10 for 4 digit PIN, 14 for 6-digit PIN - 2^TS/TS approx = sqrt(MAXPIN) */
+const TRAP int=200      /* 200 for 4 digit PIN, 2000 for 6-digit PIN  - approx 2*sqrt(MAXPIN) */
+
+func mpin_hash(sha int,c *FP16,U *ECP) []byte {
+	var w [MFS]byte
+	var t [18*MFS]byte
+	var h []byte
+
+	c.geta().geta().geta().GetA().ToBytes(w[:]); for i:=0;i<MFS;i++ {t[i]=w[i]}
+	c.geta().geta().geta().GetB().ToBytes(w[:]); for i:=MFS;i<2*MFS;i++ {t[i]=w[i-MFS]}
+	c.geta().geta().getb().GetA().ToBytes(w[:]); for i:=2*MFS;i<3*MFS;i++ {t[i]=w[i-2*MFS]}
+	c.geta().geta().getb().GetB().ToBytes(w[:]); for i:=3*MFS;i<4*MFS;i++ {t[i]=w[i-3*MFS]}
+
+	c.geta().getb().geta().GetA().ToBytes(w[:]); for i:=4*MFS;i<5*MFS;i++ {t[i]=w[i-4*MFS]}
+	c.geta().getb().geta().GetB().ToBytes(w[:]); for i:=5*MFS;i<6*MFS;i++ {t[i]=w[i-5*MFS]}
+	c.geta().getb().getb().GetA().ToBytes(w[:]); for i:=6*MFS;i<7*MFS;i++ {t[i]=w[i-6*MFS]}
+	c.geta().getb().getb().GetB().ToBytes(w[:]); for i:=7*MFS;i<8*MFS;i++ {t[i]=w[i-7*MFS]}
+
+	c.getb().geta().geta().GetA().ToBytes(w[:]); for i:=8*MFS;i<9*MFS;i++ {t[i]=w[i-8*MFS]}
+	c.getb().geta().geta().GetB().ToBytes(w[:]); for i:=9*MFS;i<10*MFS;i++ {t[i]=w[i-9*MFS]}
+	c.getb().geta().getb().GetA().ToBytes(w[:]); for i:=10*MFS;i<11*MFS;i++ {t[i]=w[i-10*MFS]}
+	c.getb().geta().getb().GetB().ToBytes(w[:]); for i:=11*MFS;i<12*MFS;i++ {t[i]=w[i-11*MFS]}
+
+	c.getb().getb().geta().GetA().ToBytes(w[:]); for i:=12*MFS;i<13*MFS;i++ {t[i]=w[i-12*MFS]}
+	c.getb().getb().geta().GetB().ToBytes(w[:]); for i:=13*MFS;i<14*MFS;i++ {t[i]=w[i-13*MFS]}
+	c.getb().getb().getb().GetA().ToBytes(w[:]); for i:=14*MFS;i<15*MFS;i++ {t[i]=w[i-14*MFS]}
+	c.getb().getb().getb().GetB().ToBytes(w[:]); for i:=15*MFS;i<16*MFS;i++ {t[i]=w[i-15*MFS]}
+
+
+	U.GetX().ToBytes(w[:]); for i:=8*MFS;i<9*MFS;i++ {t[i]=w[i-8*MFS]}
+	U.GetY().ToBytes(w[:]); for i:=9*MFS;i<10*MFS;i++ {t[i]=w[i-9*MFS]}
+
+	if sha==amcl.SHA256 {
+		H:=amcl.NewHASH256()
+		H.Process_array(t[:])
+		h=H.Hash()
+	}
+	if sha==amcl.SHA384 {
+		H:=amcl.NewHASH384()
+		H.Process_array(t[:])
+		h=H.Hash()
+	}
+	if sha==amcl.SHA512 {
+		H:=amcl.NewHASH512()
+		H.Process_array(t[:])
+		h=H.Hash()
+	}
+	if h==nil {return nil}
+	R:=make([]byte,AESKEY)
+	for i:=0;i<AESKEY;i++ {R[i]=h[i]}
+	return R
+}
+
+/* Hash number (optional) and string to coordinate on curve */
+
+func mhashit(sha int,n int32,ID []byte) []byte {
+	var R []byte
+	if sha==amcl.SHA256 {
+		H:=amcl.NewHASH256()
+		if n!=0 {H.Process_num(n)}
+		H.Process_array(ID)
+		R=H.Hash()
+	}
+	if sha==amcl.SHA384 {
+		H:=amcl.NewHASH384()
+		if n!=0 {H.Process_num(n)}
+		H.Process_array(ID)
+		R=H.Hash()
+	}
+	if sha==amcl.SHA512 {
+		H:=amcl.NewHASH512()
+		if n!=0 {H.Process_num(n)}
+		H.Process_array(ID)
+		R=H.Hash()
+	}
+	if R==nil {return nil}
+	const RM int=int(MODBYTES)
+	var W [RM]byte
+	if sha>=RM {
+		for i:=0;i<RM;i++ {W[i]=R[i]}
+	} else {
+		for i:=0;i<sha;i++ {W[i+RM-sha]=R[i]}
+		for i:=0;i<RM-sha;i++ {W[i]=0}
+
+
+	//	for i:=0;i<sha;i++ {W[i]=R[i]}	
+	//	for i:=sha;i<RM;i++ {W[i]=0}
+	}
+
+	return W[:]
+}
+
+/* return time in slots since epoch */
+func Today() int {
+	now:=time.Now()
+	return int(now.Unix())/(60*1440)
+}
+
+/* these next two functions help to implement elligator squared - http://eprint.iacr.org/2014/043 */
+/* maps a random u to a point on the curve */
+func emap(u *BIG,cb int) *ECP {
+	var P *ECP
+	x:=NewBIGcopy(u)
+	p:=NewBIGints(Modulus)
+	x.Mod(p)
+	for true {
+		P=NewECPbigint(x,cb)
+		if !P.Is_infinity() {break}
+		x.inc(1);  x.norm()
+	}
+	return P
+}
+
+/* returns u derived from P. Random value in range 1 to return value should then be added to u */
+func unmap(u* BIG,P *ECP) int {
+	s:=P.GetS()
+	var R *ECP
+	r:=0
+	x:=P.GetX()
+	u.copy(x)
+	for true {
+		u.dec(1); u.norm()
+		r++
+		R=NewECPbigint(u,s)
+		if !R.Is_infinity() {break}
+	}
+	return r
+}
+
+func MPIN_HASH_ID(sha int,ID []byte) []byte {
+	return mhashit(sha,0,ID)
+}
+
+/* these next two functions implement elligator squared - http://eprint.iacr.org/2014/043 */
+/* Elliptic curve point E in format (0x04,x,y} is converted to form {0x0-,u,v} */
+/* Note that u and v are indistinguisible from random strings */
+func MPIN_ENCODING(rng *amcl.RAND,E []byte) int {
+	var T [MFS]byte
+
+	for i:=0;i<MFS;i++ {T[i]=E[i+1]}
+	u:=FromBytes(T[:])
+	for i:=0;i<MFS;i++ {T[i]=E[i+MFS+1]}
+	v:=FromBytes(T[:])
+		
+	P:=NewECPbigs(u,v)
+	if P.Is_infinity() {return INVALID_POINT}
+
+	p:=NewBIGints(Modulus)
+	u=Randomnum(p,rng)
+
+	su:=int(rng.GetByte()); /*if (su<0) su=-su;*/ su%=2
+		
+	W:=emap(u,su)
+	P.Sub(W)
+	sv:=P.GetS()
+	rn:=unmap(v,P)
+	m:=int(rng.GetByte()); /*if (m<0) m=-m;*/ m%=rn
+	v.inc(m+1)
+	E[0]=byte(su+2*sv)
+	u.ToBytes(T[:])
+	for i:=0;i<MFS;i++ {E[i+1]=T[i]}
+	v.ToBytes(T[:])
+	for i:=0;i<MFS;i++ {E[i+MFS+1]=T[i]}		
+		
+	return 0
+}
+
+func MPIN_DECODING(D []byte) int {
+	var T [MFS]byte
+
+	if (D[0]&0x04)!=0 {return INVALID_POINT}
+
+	for i:=0;i<MFS;i++ {T[i]=D[i+1]}
+	u:=FromBytes(T[:])
+	for i:=0;i<MFS;i++ {T[i]=D[i+MFS+1]}
+	v:=FromBytes(T[:])
+
+	su:=int(D[0]&1)
+	sv:=int((D[0]>>1)&1)
+	W:=emap(u,su)
+	P:=emap(v,sv)
+	P.Add(W)
+	u=P.GetX()
+	v=P.GetY()
+	D[0]=0x04
+	u.ToBytes(T[:])
+	for i:=0;i<MFS;i++ {D[i+1]=T[i]}
+	v.ToBytes(T[:])
+	for i:=0;i<MFS;i++ {D[i+MFS+1]=T[i]}		
+		
+	return 0
+}
+
+/* R=R1+R2 in group G1 */
+func MPIN_RECOMBINE_G1(R1 []byte,R2 []byte,R []byte) int {
+	P:=ECP_fromBytes(R1)
+	Q:=ECP_fromBytes(R2)
+
+	if (P.Is_infinity() || Q.Is_infinity()) {return INVALID_POINT}
+
+	P.Add(Q)
+
+	P.ToBytes(R[:],false)
+	return 0
+}
+
+/* W=W1+W2 in group G2 */
+func MPIN_RECOMBINE_G2(W1 []byte,W2 []byte,W []byte) int {
+	P:=ECP8_fromBytes(W1)
+	Q:=ECP8_fromBytes(W2)
+
+	if (P.Is_infinity() || Q.Is_infinity()) {return INVALID_POINT}
+
+	P.Add(Q)
+	
+	P.ToBytes(W)
+	return 0
+}
+
+/* create random secret S */
+func MPIN_RANDOM_GENERATE(rng *amcl.RAND,S []byte) int {
+	r:=NewBIGints(CURVE_Order);
+	s:=Randomnum(r,rng)
+	//if AES_S>0 {
+	//	s.mod2m(2*AES_S)
+	//}		
+	s.ToBytes(S)
+	return 0
+}
+
+
+func MPIN_EXTRACT_PIN(sha int,CID []byte,pin int,TOKEN []byte) int {
+	return MPIN_EXTRACT_FACTOR(sha,CID,int32(pin)%MAXPIN,PBLEN,TOKEN)
+}
+
+/* Extract factor from TOKEN for identity CID */
+func MPIN_EXTRACT_FACTOR(sha int,CID []byte,factor int32,facbits int32,TOKEN []byte) int {
+	P:=ECP_fromBytes(TOKEN)
+	if P.Is_infinity() {return INVALID_POINT}
+	h:=mhashit(sha,0,CID)
+	R:=ECP_mapit(h)
+
+	R=R.pinmul(factor,facbits)
+	P.Sub(R)
+
+	P.ToBytes(TOKEN,false)
+
+	return 0
+}
+
+/* Restore factor to TOKEN for identity CID */
+func MPIN_RESTORE_FACTOR(sha int,CID []byte,factor int32,facbits int32,TOKEN []byte) int {
+	P:=ECP_fromBytes(TOKEN)
+	if P.Is_infinity() {return INVALID_POINT}
+	h:=mhashit(sha,0,CID)
+	R:=ECP_mapit(h)
+
+	R=R.pinmul(factor,facbits)
+	P.Add(R)
+
+	P.ToBytes(TOKEN,false)
+
+	return 0
+}
+
+/* Implement step 2 on client side of MPin protocol */
+func MPIN_CLIENT_2(X []byte,Y []byte,SEC []byte) int {
+	r:=NewBIGints(CURVE_Order)
+	P:=ECP_fromBytes(SEC)
+	if P.Is_infinity() {return INVALID_POINT}
+
+	px:=FromBytes(X)
+	py:=FromBytes(Y)
+	px.add(py)
+	px.Mod(r)
+	//px.rsub(r)
+
+	P=G1mul(P,px)
+	P.neg()
+	P.ToBytes(SEC,false)
+	//G1mul(P,px).ToBytes(SEC,false)
+	return 0
+}
+
+/* Implement step 1 on client side of MPin protocol */
+func MPIN_CLIENT_1(sha int,date int,CLIENT_ID []byte,rng *amcl.RAND,X []byte,pin int,TOKEN []byte,SEC []byte,xID []byte,xCID []byte,PERMIT []byte) int {
+	r:=NewBIGints(CURVE_Order)
+		
+	var x *BIG
+	if (rng!=nil) {
+		x=Randomnum(r,rng)
+		//if AES_S>0 {
+		//	x.mod2m(2*AES_S)
+		//}
+		x.ToBytes(X)
+	} else {
+		x=FromBytes(X)
+	}
+
+	h:=mhashit(sha,0,CLIENT_ID)
+	P:=ECP_mapit(h)
+	
+	T:=ECP_fromBytes(TOKEN)
+	if T.Is_infinity() {return INVALID_POINT}
+
+	W:=P.pinmul(int32(pin)%MAXPIN,PBLEN)
+	T.Add(W)
+	if date!=0 {
+		W=ECP_fromBytes(PERMIT)
+		if W.Is_infinity() {return INVALID_POINT}
+		T.Add(W)
+		h=mhashit(sha,int32(date),h)
+		W=ECP_mapit(h)
+		if xID!=nil {
+			P=G1mul(P,x)
+			P.ToBytes(xID,false)
+			W=G1mul(W,x)
+			P.Add(W)
+		} else {
+			P.Add(W)
+			P=G1mul(P,x)
+		}
+		if xCID!=nil {P.ToBytes(xCID,false)}
+	} else {
+		if xID!=nil {
+			P=G1mul(P,x)
+			P.ToBytes(xID,false)
+		}
+	}
+
+
+	T.ToBytes(SEC,false)
+	return 0
+}
+
+/* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */
+func MPIN_GET_SERVER_SECRET(S []byte,SST []byte) int {
+	Q:=ECP8_generator(); 
+
+	s:=FromBytes(S)
+	Q=G2mul(Q,s)
+	Q.ToBytes(SST)
+	return 0
+}
+
+/*
+ W=x*H(G);
+ if RNG == NULL then X is passed in 
+ if RNG != NULL the X is passed out 
+ if type=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve
+*/
+func MPIN_GET_G1_MULTIPLE(rng *amcl.RAND,typ int,X []byte,G []byte,W []byte) int {
+	var x *BIG
+	r:=NewBIGints(CURVE_Order)
+	if rng!=nil {
+		x=Randomnum(r,rng)
+		//if AES_S>0 {
+		//	x.mod2m(2*AES_S)
+		//}
+		x.ToBytes(X)
+	} else {
+		x=FromBytes(X)
+	}
+	var P *ECP
+	if typ==0 {
+		P=ECP_fromBytes(G)
+		if P.Is_infinity() {return INVALID_POINT}
+	} else {P=ECP_mapit(G)}
+
+	G1mul(P,x).ToBytes(W,false)
+	return 0
+}
+
+/* Client secret CST=S*H(CID) where CID is client ID and S is master secret */
+/* CID is hashed externally */
+func MPIN_GET_CLIENT_SECRET(S []byte,CID []byte,CST []byte) int {
+	return MPIN_GET_G1_MULTIPLE(nil,1,S,CID,CST)
+}
+
+/* Time Permit CTT=S*(date|H(CID)) where S is master secret */
+func MPIN_GET_CLIENT_PERMIT(sha,date int,S []byte,CID []byte,CTT []byte) int {
+	h:=mhashit(sha,int32(date),CID)
+	P:=ECP_mapit(h)
+
+	s:=FromBytes(S)
+	G1mul(P,s).ToBytes(CTT,false)
+	return 0
+}
+
+/* Outputs H(CID) and H(T|H(CID)) for time permits. If no time permits set HID=HTID */
+func MPIN_SERVER_1(sha int,date int,CID []byte,HID []byte,HTID []byte) {
+	h:=mhashit(sha,0,CID)
+	P:=ECP_mapit(h)
+	
+	P.ToBytes(HID,false);
+	if date!=0 {
+	//	if HID!=nil {P.ToBytes(HID,false)}
+		h=mhashit(sha,int32(date),h)
+		R:=ECP_mapit(h)
+		P.Add(R)
+		P.ToBytes(HTID,false)
+	} //else {P.ToBytes(HID,false)}
+}
+
+/* Implement step 2 of MPin protocol on server side */
+func MPIN_SERVER_2(date int,HID []byte,HTID []byte,Y []byte,SST []byte,xID []byte,xCID []byte,mSEC []byte,E []byte,F []byte) int {
+//	q:=NewBIGints(Modulus)
+	Q:=ECP8_generator(); 
+
+	sQ:=ECP8_fromBytes(SST)
+	if sQ.Is_infinity() {return INVALID_POINT}	
+
+	var R *ECP
+	if date!=0 {
+		R=ECP_fromBytes(xCID)
+	} else {
+		if xID==nil {return BAD_PARAMS}
+		R=ECP_fromBytes(xID)
+	}
+	if R.Is_infinity() {return INVALID_POINT}
+
+	y:=FromBytes(Y)
+	var P *ECP
+	if date!=0 {
+		P=ECP_fromBytes(HTID)
+	} else {
+		if HID==nil {return BAD_PARAMS}
+		P=ECP_fromBytes(HID)
+	}
+	
+	if P.Is_infinity() {return INVALID_POINT}
+
+	P=G1mul(P,y)
+	P.Add(R)
+	//P.Affine()
+	R=ECP_fromBytes(mSEC)
+	if R.Is_infinity() {return INVALID_POINT}
+
+	var g *FP48
+
+	g=Ate2(Q,R,sQ,P)
+	g=Fexp(g)
+
+	if !g.Isunity() {
+		if (HID!=nil && xID!=nil && E!=nil && F!=nil) {
+			g.ToBytes(E)
+			if date!=0 {
+				P=ECP_fromBytes(HID)
+				if P.Is_infinity() {return INVALID_POINT}
+				R=ECP_fromBytes(xID)
+				if R.Is_infinity() {return INVALID_POINT}
+
+				P=G1mul(P,y)
+				P.Add(R)
+				//P.Affine()
+			}
+			g=Ate(Q,P)
+			g=Fexp(g)
+			g.ToBytes(F)
+		}
+		return BAD_PIN
+	}
+
+	return 0
+}
+
+/* Pollards kangaroos used to return PIN error */
+func MPIN_KANGAROO(E []byte,F []byte) int {
+	ge:=FP48_fromBytes(E)
+	gf:=FP48_fromBytes(F)
+	var distance [TS]int
+	t:=NewFP48copy(gf)
+
+	var table []*FP48
+	var i int
+	s:=1
+	for m:=0;m<TS;m++ {
+		distance[m]=s
+		table=append(table,NewFP48copy(t))
+		s*=2
+		t.usqr()
+	}
+	t.one()
+	dn:=0
+	for j:=0;j<TRAP;j++ {
+		i=t.geta().geta().geta().geta().GetA().lastbits(20)%TS
+		t.Mul(table[i])
+		dn+=distance[i]
+	}
+	gf.Copy(t); gf.conj()
+	steps:=0; dm:=0
+	res:=0
+	for dm-dn<int(MAXPIN) {
+		steps++
+		if steps>4*TRAP {break}
+		i=ge.geta().geta().geta().geta().GetA().lastbits(20)%TS;
+		ge.Mul(table[i])
+		dm+=distance[i]
+		if ge.Equals(t) {
+			res=dm-dn
+			break;
+		}
+		if ge.Equals(gf) {
+			res=dn-dm
+			break
+		}
+
+	}
+	if (steps>4*TRAP || dm-dn>=int(MAXPIN)) {res=0 }    // Trap Failed  - probable invalid token
+	return int(res)
+}
+
+/* Functions to support M-Pin Full */
+
+func MPIN_PRECOMPUTE(TOKEN []byte,CID []byte,G1 []byte,G2 []byte) int {
+	var P,T *ECP
+	var g *FP48
+
+	T=ECP_fromBytes(TOKEN)
+	if T.Is_infinity() {return INVALID_POINT} 
+
+	P=ECP_mapit(CID)
+
+	Q:=ECP8_generator(); 
+
+	g=Ate(Q,T)
+	g=Fexp(g)
+	g.ToBytes(G1)
+
+	g=Ate(Q,P)
+	g=Fexp(g)
+	g.ToBytes(G2)
+
+	return 0
+}
+
+/* Hash the M-Pin transcript - new */
+
+func MPIN_HASH_ALL(sha int,HID []byte,xID []byte,xCID []byte,SEC []byte,Y []byte,R []byte,W []byte) []byte {
+	tlen:=0
+	var T [10*int(MODBYTES)+4]byte
+
+	for i:=0;i<len(HID);i++ {T[i]=HID[i]}
+	tlen+=len(HID)
+	if xCID!=nil {
+		for i:=0;i<len(xCID);i++ {T[i+tlen]=xCID[i]}
+		tlen+=len(xCID)
+	} else {
+		for i:=0;i<len(xID);i++ {T[i+tlen]=xID[i]}
+		tlen+=len(xID)
+	}	
+	for i:=0;i<len(SEC);i++ {T[i+tlen]=SEC[i]}
+	tlen+=len(SEC)		
+	for i:=0;i<len(Y);i++ {T[i+tlen]=Y[i]}
+	tlen+=len(Y)
+	for i:=0;i<len(R);i++ {T[i+tlen]=R[i]}
+	tlen+=len(R)		
+	for i:=0;i<len(W);i++ {T[i+tlen]=W[i]}
+	tlen+=len(W)	
+
+	return mhashit(sha,0,T[:])
+}
+
+/* calculate common key on client side */
+/* wCID = w.(A+AT) */
+func MPIN_CLIENT_KEY(sha int,G1 []byte,G2 []byte,pin int,R []byte,X []byte,H []byte,wCID []byte,CK []byte) int {
+
+	g1:=FP48_fromBytes(G1)
+	g2:=FP48_fromBytes(G2)
+	z:=FromBytes(R)
+	x:=FromBytes(X)
+	h:=FromBytes(H)
+
+	W:=ECP_fromBytes(wCID)
+	if W.Is_infinity() {return INVALID_POINT} 
+
+	W=G1mul(W,x)
+
+	r:=NewBIGints(CURVE_Order)
+
+	z.add(h);	//new
+	z.Mod(r);
+
+	g2.pinpow(pin,int(PBLEN))
+	g1.Mul(g2)
+
+	c:=g1.Compow(z,r);
+
+	t:=mpin_hash(sha,c,W);
+
+	for i:=0;i<AESKEY;i++ {CK[i]=t[i]}
+
+	return 0
+}
+
+/* calculate common key on server side */
+/* Z=r.A - no time permits involved */
+
+func MPIN_SERVER_KEY(sha int,Z []byte,SST []byte,W []byte,H []byte,HID []byte,xID []byte,xCID []byte,SK []byte) int {
+	sQ:=ECP8_fromBytes(SST)
+	if sQ.Is_infinity() {return INVALID_POINT} 
+	R:=ECP_fromBytes(Z)
+	if R.Is_infinity() {return INVALID_POINT} 
+	A:=ECP_fromBytes(HID)
+	if A.Is_infinity() {return INVALID_POINT} 
+
+	var U *ECP
+	if xCID!=nil {
+		U=ECP_fromBytes(xCID)
+	} else	{U=ECP_fromBytes(xID)}
+	if U.Is_infinity() {return INVALID_POINT} 
+
+	w:=FromBytes(W)
+	h:=FromBytes(H)
+	A=G1mul(A,h)	// new
+	R.Add(A)
+	//R.Affine()
+
+	U=G1mul(U,w)
+	g:=Ate(sQ,R)
+	g=Fexp(g)
+
+	c:=g.trace()
+
+	t:=mpin_hash(sha,c,U)
+
+	for i:=0;i<AESKEY;i++ {SK[i]=t[i]}
+
+	return 0
+}
+
+/* return time since epoch */
+func MPIN_GET_TIME() int {
+	now:=time.Now()
+	return int(now.Unix())
+}
+
+/* Generate Y = H(epoch, xCID/xID) */
+func MPIN_GET_Y(sha int,TimeValue int,xCID []byte,Y []byte) {
+	h:= mhashit(sha,int32(TimeValue),xCID)
+	y:= FromBytes(h)
+	q:=NewBIGints(CURVE_Order)
+	y.Mod(q)
+	//if AES_S>0 {
+	//	y.mod2m(2*AES_S)
+	//}
+	y.ToBytes(Y)
+}
+
+/* One pass MPIN Client */
+func MPIN_CLIENT(sha int,date int,CLIENT_ID []byte,RNG *amcl.RAND,X []byte,pin int,TOKEN []byte,SEC []byte,xID []byte,xCID []byte,PERMIT []byte,TimeValue int,Y []byte) int {
+	rtn:=0
+        
+	var pID []byte
+	if date == 0 {
+		pID = xID
+	} else {pID = xCID}
+          
+	rtn = MPIN_CLIENT_1(sha,date,CLIENT_ID,RNG,X,pin,TOKEN,SEC,xID,xCID,PERMIT)
+	if rtn != 0 {return rtn}
+        
+	MPIN_GET_Y(sha,TimeValue,pID,Y)
+        
+	rtn = MPIN_CLIENT_2(X,Y,SEC)
+	if rtn != 0 {return rtn}
+        
+	return 0
+}
+
+/* One pass MPIN Server */
+func MPIN_SERVER(sha int,date int,HID []byte,HTID []byte,Y []byte,SST []byte,xID []byte,xCID []byte,SEC []byte,E []byte,F []byte,CID []byte,TimeValue int) int {
+	rtn:=0
+        
+	var pID []byte
+	if date == 0 {
+		pID = xID
+	} else {pID = xCID}
+       
+	MPIN_SERVER_1(sha,date,CID,HID,HTID)
+	MPIN_GET_Y(sha,TimeValue,pID,Y);
+    
+	rtn = MPIN_SERVER_2(date,HID,HTID,Y,SST,xID,xCID,SEC,E,F)
+	if rtn != 0 {return rtn}
+        
+	return 0
+}
+
+
diff --git a/version3/go/NHS.go b/version3/go/NHS.go
new file mode 100644
index 0000000..a85009c
--- /dev/null
+++ b/version3/go/NHS.go
@@ -0,0 +1,539 @@
+/*
+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.
+*/
+
+/*
+ * Implementation of the Secure Hashing Algorithm (SHA-384)
+ *
+ * Generates a 384 bit message digest. It should be impossible to come
+ * come up with two messages that hash to the same value ("collision free").
+ *
+ * For use with byte-oriented messages only. 
+ */
+
+//nhs_package main
+
+package amcl
+
+//import "fmt"
+
+
+const NHS_PRIME int32=0x3001	// q in Hex
+const NHS_LGN uint=10		// Degree n=2^LGN
+const NHS_ND uint32=0xF7002FFF	// 1/(R-q) mod R
+const NHS_ONE int32=0x2AC8	// R mod q
+const NHS_R2MODP uint64=0x1620	// R^2 mod q
+
+
+const NHS_DEGREE int=(1<<NHS_LGN)
+const NHS_WL uint=32
+
+const NHS_inv int32=  0xeab
+const NHS_invpr int32= 0x2c2a
+
+var NHS_roots = [1024] int32 {0x2ac8,0x2baf,0x299b,0x685,0x2f04,0x158d,0x2d49,0x24b5,0x1edc,0xab3,0x2a95,0x24d,0x3cb,0x6a8,0x12f9,0x15ba,0x1861,0x2a89,0x1c5c,0xbe6,0xc1e,0x2024,0x207,0x19ce,0x2710,0x1744,0x18bc,0x2cd7,0x396,0x18d5,0x1c45,0xc4,0x21a6,0xe03,0x2b3c,0x2d91,0xc5d,0x432,0x1fbc,0xcae,0x2512,0x2979,0x3b2,0x714,0xb2e,0x1a97,0x1a03,0x1bcd,0x2216,0x2701,0xa,0x263c,0x1179,0x200c,0x2d08,0x1c34,0x291,0x2c99,0x2a5a,0x723,0xb1d,0x1ccc,0x1fb6,0x2f58,0x2bfe,0x1cda,0x2a0,0x5f1,0x2de,0x1fc7,0x1ea8,0x1719,0x2fa7,0x27ec,0x20ff,0x12c0,0x1ac1,0x2232,0x2f9b,0xd3e,0x2aed,0x15f0,0x11e8,0xed0,0x26a,0x1de5,0xa3f,0xf43,0xebf,0x204e,0xac7,0x2d9c,0x5ea,0x25d1,0xb6,0x49c,0x995,0x2555,0x26e2,0x100,0x1878,0x5aa,0x2e10,0x271c,0xcb,0x1b4c,0x2fb8,0x25b7,0x1543,0x2c7b,0x241a,0x2223,0x20ca,0x24ed,0x137,0x1b65,0x1dc2,0x7c7,0x2ec3,0xd0c,0x1169,0x1c7a,0x1ea1,0xf89,0x2199,0x291d,0x1088,0x2046,0x256d,0x2bc7,0x2e9b,0x41f,0x1b55,0x2b38,0xd0,0x2e6a,0x1755,0x6bc,0x2724,0x3ba,0x222e,0x2c5c,0x2da5,0x213c,0x10fe,0x169a,0x1552,0x5d3,0x300,0x1b5d,0x1342,0x2004,0x256f,0x2039,0x667,0x23b5,0x1123,0xdb,0x2da0,0xe1e,0x2f54,0x2767,0x154a,0x40a,0x11d3,0x2821,0xc09,0x974,0x694,0xfbf,0x27ba,0x132,0x83f,0x2d06,0x10e,0x183f,0x29ae,0x28c3,0x2dc9,0x1144,0x2c70,0x2a4a,0xf3c,0x1e32,0x1171,0x1e43,0xdd4,0x2ddf,0x28d2,0xfac,0x3c4,0x2f19,0x10a6,0x2f7,0xe1d,0x828,0x138f,0x1332,0xfab,0xcf6,0x13f8,0x24a0,0x112d,0x2717,0x6e7,0x1044,0x36e,0xfe8,0x6a,0xba7,0x1d69,0x29ec,0x23b2,0xaee,0x16df,0x1068,0x1a7e,0x253f,0x24c,0xb33,0x2683,0x15ce,0x1ad3,0x1a36,0xc96,0xaea,0x260a,0xce,0x28b1,0xe4f,0x2b11,0x5f8,0x1fc4,0xe77,0x2366,0x11f9,0x153c,0x24eb,0x20cd,0x1398,0x22,0x2b97,0x249b,0x8eb,0x12b2,0x2fe3,0x29c1,0x1b00,0x2663,0xeaa,0x2e06,0xe0,0x1569,0x10f5,0x284e,0xa38,0x201d,0x1c53,0x1681,0x1f6f,0x2f95,0x2fe8,0xacb,0x1680,0x17fd,0x2c39,0x165a,0x10bb,0x29d8,0x2622,0x1196,0x884,0x2a79,0x140e,0x2d80,0x6fa,0x11b2,0x26c4,0x355,0x1054,0x29e9,0x23ed,0xbe3,0x24fa,0x1fb3,0x10ac,0x2919,0x2584,0x10a4,0xe85,0x650,0x1893,0x1dc1,0xd8e,0x12dc,0x2d42,0x284d,0xfff,0x250f,0xacd,0x13c3,0x6cc,0x1a79,0x1221,0x2614,0x270a,0x1ea,0x155,0x2818,0x222c,0x2e5b,0x25d8,0x1dbf,0x191c,0xb0f,0xdac,0x1082,0x12ef,0x11b6,0xfa8,0x2b72,0x159d,0x209e,0x31b,0x2c7c,0x14f7,0xe09,0x1bb2,0x1ec7,0x2404,0x20ae,0x6ad,0xed6,0x2b70,0x1c7b,0x18d1,0x2732,0x12da,0xd56,0x5c1,0x1648,0x18b7,0x1605,0x1bc4,0x280,0x2ece,0xc,0x1aae,0x1c4,0x1cdb,0x22d6,0x21d8,0x257c,0x51f,0x211b,0xff,0x2ee0,0x2585,0xe1,0x2c35,0x26db,0x2971,0x2208,0x17e1,0x21be,0x135e,0x28d6,0x2891,0x1689,0x2138,0xb86,0x2e3a,0x1204,0x2d10,0x2324,0xf3f,0x2508,0x33d,0xcb2,0x292a,0xe27,0x2e64,0x29f8,0x2d46,0x9b7,0x20eb,0x1b7c,0x9eb,0x2b2a,0x58c,0x27d0,0x121b,0x272e,0x29f6,0x2dbd,0x2697,0x2aac,0xd6f,0x1c67,0x2c5b,0x108d,0x363,0x249d,0x2d5e,0x2fd,0x2cb2,0x1f8f,0x20a4,0xa19,0x2ac9,0x19b1,0x1581,0x17a2,0x29eb,0x1b72,0x13b0,0xee4,0xa8f,0x2315,0x5e6,0x951,0x2e29,0xdad,0x1f2b,0x224e,0x37f,0x1a72,0xa91,0x1407,0x2df9,0x3ad,0x23f7,0x1a24,0x1d2a,0x234b,0x1df3,0x1143,0x7ff,0x1a6d,0x2774,0x2690,0x2ab5,0x586,0x2781,0x2009,0x2fdd,0x2881,0x399,0x2fb6,0x144,0x137f,0xfa0,0x2e4c,0x1c7f,0x2fac,0xb09,0x1264,0x127b,0x198c,0x2b40,0x230,0x1cf4,0x180b,0xb58,0x144a,0x2aec,0xfb,0x2602,0x14ee,0x783,0x1098,0x23d8,0x203,0xe9,0x108a,0x14b8,0xeec,0xc58,0x1248,0x243c,0x28aa,0x6bf,0x27c4,0x276e,0x19b8,0x1d11,0x2e16,0x472,0x1464,0x24b9,0x662,0x1097,0x2067,0x20d6,0x171c,0x4,0x682,0x17bb,0x1186,0x4f2,0x3ff,0x2a43,0x1dc7,0x1ae5,0x8cc,0x2e7c,0x2ef8,0x2ae0,0x2904,0xed4,0x6c5,0x14ae,0xb72,0x11c3,0x337,0x2da3,0x2916,0x6d8,0x1cf9,0x10ee,0x1800,0x1ae4,0xa0d,0x101b,0x1a8d,0x2e98,0x24cd,0x813,0x1aa4,0x9b9,0x680,0x2349,0x24d1,0x20f8,0xe31,0x249f,0x216b,0x12d9,0x1d21,0x19db,0x191a,0x1dd0,0x5df,0x55c,0x2b86,0x213,0xe9e,0x1ef1,0x268a,0x1d5e,0x1e20,0x28c1,0x1379,0x249,0x19de,0x18b,0x1e41,0x2a1e,0x2612,0x297,0x2e96,0x2102,0x46,0x1b9f,0x1a4d,0x2050,0x1b32,0x568,0x11f7,0x1829,0x870,0x1f4,0x1dca,0x990,0x1df6,0x2b62,0x13ec,0x9f2,0x1260,0x2997,0x1412,0x1e6d,0x1694,0x11ac,0x2d8b,0x276f,0x26f5,0x233e,0x2b44,0x2f5a,0x2d37,0x2cb1,0xc75,0x98d,0x1d56,0x7ae,0x10e6,0x113f,0x17b8,0xad3,0x737,0x221e,0x1b70,0x1f3e,0x2966,0x18b2,0x4fa,0x2044,0x1312,0x154e,0x2029,0x700,0x1b45,0x27a6,0x226a,0x21bf,0x58d,0x2f11,0x2e02,0x17fc,0x4d2,0x1757,0xcb1,0x2ef1,0x2582,0x1276,0x881,0x2fc0,0x104a,0x670,0x274f,0x2b53,0x19dd,0x752,0x1663,0xcbd,0x2b2b,0x2fc6,0x13b6,0x21e6,0x15f6,0x126b,0x2637,0x1cd9,0x2f50,0xe82,0x5b0,0x24e0,0x1350,0x2f24,0x21f7,0x1a16,0x2f3e,0x167e,0x1f7d,0x28a0,0x16f0,0xe33,0x53b,0x28c5,0x1500,0x2f88,0x26cc,0x2018,0x1604,0x218b,0x2cd1,0x9ee,0x17f3,0x5fd,0x1f5a,0x2d0,0x2b46,0x23cc,0x503,0x1c46,0x1cc3,0x28e2,0x243e,0x122b,0x2e0c,0xe37,0x2611,0x85e,0x9b8,0x1b24,0x762,0x19b6,0x3bc,0x2d50,0x2079,0x18da,0x170a,0x800,0xaa2,0x135a,0x1a15,0x13d1,0xca,0x2113,0x2db9,0xdb2,0x1a5c,0x29a9,0x1488,0x14c1,0x2c9,0x917,0x28e7,0x265c,0xdab,0x2ab9,0x2bc6,0x105b,0x1839,0x219c,0x50,0x11da,0x1802,0xf56,0x2e6,0x2190,0xddb,0x56e,0x9d9,0x1c81,0x1016,0x12d6,0x296f,0x14b4,0x1014,0x1e64,0x1d90,0x89f,0x2bc2,0x2777,0x2819,0x1c65,0x1a41,0x5a2,0x2cd2,0x427,0xd71,0x29c8,0x1e58,0x53f,0x7c5,0x1dcd,0x4a1,0x1268,0x2597,0x2926,0xee,0x111b,0x1038,0xe6c,0x22dc,0x2f2f,0x441,0x2cfd,0x1cb0,0x6a4,0x2224,0x620,0x5dc,0x16b1,0x2a1d,0x1787,0x20c7,0x641,0xd84,0x1c05,0x2d0d,0x2f52,0x1b8c,0xd7d,0x17e8,0x1589,0xc73,0x151b,0x4e2,0x1ae9,0x1b18,0xb9b,0x949,0x2c60,0x1e7a,0xd5,0x1bdc,0x1f57,0x1753,0x124a,0x559,0xb76,0x2334,0x12d1,0x1de1,0x14b2,0x2faa,0x1697,0x147a,0x5a1,0x2c30,0x1c02,0x1043,0x2ee1,0x2402,0x1cc8,0x2a16,0xff7,0x1364,0x1b9a,0x2a53,0x2f94,0x294c,0x1ee5,0x1a87,0x2141,0xd66,0x953,0x28a3,0x2f30,0x2477,0x18e3,0x1035,0x1fc1,0x1d68,0x2fb3,0x138c,0x2487,0x1bf8,0xd96,0x1018,0x748,0x244e,0x15bd,0x175e,0x2be,0x23d,0x1da,0x176d,0xc17,0x24be,0x2ebb,0x7d8,0x100a,0x759,0x1db4,0x2259,0x23f4,0x2d59,0x2847,0xbf5,0x1cfe,0xa20,0x258,0x1180,0x279c,0x54,0x2abf,0xc5c,0x9f9,0x3d5,0x2ce4,0x165f,0x23d9,0x27b9,0x6f9,0x281a,0x169e,0x627,0x156d,0x1ff8,0x211,0x2e34,0x1724,0x2c2e,0x2790,0x2dd5,0x2bf2,0xdbc,0x2884,0x20a9,0x2390,0x1e1a,0x1b6a,0x5f7,0xab7,0x1333,0x16ab,0x28dd,0x20,0x30f,0x24b6,0x5c2,0x1ce4,0x1400,0x2669,0x60,0x156c,0xe20,0x26d4,0x26ab,0x1ebb,0x223d,0x5b4,0x2025,0x1e1c,0xaae,0x2e08,0x6cd,0x1677,0x13d9,0x17b5,0x1046,0x1d8c,0x14eb,0x18d8,0x1ce5,0x2478,0x16ae,0xb79,0x23d4,0x684,0x156b,0x567,0x1a,0x29ce,0x83a,0x19e8,0x58e,0x294a,0x1136,0x2319,0x2fba,0x1a29,0x1d,0x1879,0x291b,0x19f6,0x2c2f,0x21c9,0x19bb,0xbbc,0x26f9,0xc22,0x708,0x11a1,0x18d3,0x7f8,0x28f8,0x2427,0x1deb,0xaed,0x26aa,0x2482,0x203b,0x2f05,0x2b82,0x192f,0x2df4,0x8dc,0x2877,0xd5e,0x240e,0x775,0x2dae,0x1d3e,0x20ba,0x215b,0x22d1,0xeba,0xf50,0xaa8,0x184a,0x1f67,0x2e04,0xc6e,0x6dd,0x1a09,0x27f,0x494,0x1426,0xae3,0xe15,0x65f,0x13c4,0x105,0x872,0x2667,0x1ff6,0xd9f,0x2ca1,0x2f39,0x2657,0x23fd,0x2405,0xb73,0x2294,0x1f1e,0x2eba,0x110a,0x2cae,0x141f,0x22cd,0x25d6,0x11c1,0x1c,0x2d8e,0x161a,0x1aa8,0x229e,0x1bf9,0x7cf,0x106d,0x2c40,0xd93,0x255e,0x28c2,0xc1a,0x2f17,0x7ca,0x2f63,0xbf};
+var NHS_iroots= [1024] int32 {0x2ac8,0x452,0x297c,0x666,0xb4c,0x2b8,0x1a74,0xfd,0x1a47,0x1d08,0x2959,0x2c36,0x2db4,0x56c,0x254e,0x1125,0x2f3d,0x13bc,0x172c,0x2c6b,0x32a,0x1745,0x18bd,0x8f1,0x1633,0x2dfa,0xfdd,0x23e3,0x241b,0x13a5,0x578,0x17a0,0xa9,0x104b,0x1335,0x24e4,0x28de,0x5a7,0x368,0x2d70,0x13cd,0x2f9,0xff5,0x1e88,0x9c5,0x2ff7,0x900,0xdeb,0x1434,0x15fe,0x156a,0x24d3,0x28ed,0x2c4f,0x688,0xaef,0x2353,0x1045,0x2bcf,0x23a4,0x270,0x4c5,0x21fe,0xe5b,0xfbb,0x1f79,0x6e4,0xe68,0x2078,0x1160,0x1387,0x1e98,0x22f5,0x13e,0x283a,0x123f,0x149c,0x2eca,0xb14,0xf37,0xdde,0xbe7,0x386,0x1abe,0xa4a,0x49,0x14b5,0x2f36,0x8e5,0x1f1,0x2a57,0x1789,0x2f01,0x91f,0xaac,0x266c,0x2b65,0x2f4b,0xa30,0x2a17,0x265,0x253a,0xfb3,0x2142,0x20be,0x25c2,0x121c,0x2d97,0x2131,0x1e19,0x1a11,0x514,0x22c3,0x66,0xdcf,0x1540,0x1d41,0xf02,0x815,0x5a,0x18e8,0x1159,0x103a,0x2d23,0x2a10,0x2d61,0x1327,0x403,0x25c9,0x7b3,0x1f0c,0x1a98,0x2f21,0x1fb,0x2157,0x99e,0x1501,0x640,0x1e,0x1d4f,0x2716,0xb66,0x46a,0x2fdf,0x1c69,0xf34,0xb16,0x1ac5,0x1e08,0xc9b,0x218a,0x103d,0x2a09,0x4f0,0x21b2,0x750,0x2f33,0x9f7,0x2517,0x236b,0x15cb,0x152e,0x1a33,0x97e,0x24ce,0x2db5,0xac2,0x1583,0x1f99,0x1922,0x2513,0xc4f,0x615,0x1298,0x245a,0x2f97,0x2019,0x2c93,0x1fbd,0x291a,0x8ea,0x1ed4,0xb61,0x1c09,0x230b,0x2056,0x1ccf,0x1c72,0x27d9,0x21e4,0x2d0a,0x1f5b,0xe8,0x2c3d,0x2055,0x72f,0x222,0x222d,0x11be,0x1e90,0x11cf,0x20c5,0x5b7,0x391,0x1ebd,0x238,0x73e,0x653,0x17c2,0x2ef3,0x2fb,0x27c2,0x2ecf,0x847,0x2042,0x296d,0x268d,0x23f8,0x7e0,0x1e2e,0x2bf7,0x1ab7,0x89a,0xad,0x21e3,0x261,0x2f26,0x1ede,0xc4c,0x299a,0xfc8,0xa92,0xffd,0x1cbf,0x14a4,0x2d01,0x2a2e,0x1aaf,0x1967,0x1f03,0xec5,0x25c,0x3a5,0xdd3,0x2c47,0x8dd,0x2945,0x18ac,0x197,0x2f31,0x4c9,0x14ac,0x2be2,0x166,0x43a,0xa94,0x1b53,0x293c,0x212d,0x6fd,0x521,0x109,0x185,0x2735,0x151c,0x123a,0x5be,0x2c02,0x2b0f,0x1e7b,0x1846,0x297f,0x2ffd,0x18e5,0xf2b,0xf9a,0x1f6a,0x299f,0xb48,0x1b9d,0x2b8f,0x1eb,0x12f0,0x1649,0x893,0x83d,0x2942,0x757,0xbc5,0x1db9,0x23a9,0x2115,0x1b49,0x1f77,0x2f18,0x2dfe,0xc29,0x1f69,0x287e,0x1b13,0x9ff,0x2f06,0x515,0x1bb7,0x24a9,0x17f6,0x130d,0x2dd1,0x4c1,0x1675,0x1d86,0x1d9d,0x24f8,0x55,0x1382,0x1b5,0x2061,0x1c82,0x2ebd,0x4b,0x2c68,0x780,0x24,0xff8,0x880,0x2a7b,0x54c,0x971,0x88d,0x1594,0x2802,0x1ebe,0x120e,0xcb6,0x12d7,0x15dd,0xc0a,0x2c54,0x208,0x1bfa,0x2570,0x158f,0x2c82,0xdb3,0x10d6,0x2254,0x1d8,0x26b0,0x2a1b,0xcec,0x2572,0x211d,0x1c51,0x148f,0x616,0x185f,0x1a80,0x1650,0x538,0x25e8,0xf5d,0x1072,0x34f,0x2d04,0x2a3,0xb64,0x2c9e,0x1f74,0x3a6,0x139a,0x2292,0x555,0x96a,0x244,0x60b,0x8d3,0x1de6,0x831,0x2a75,0x4d7,0x2616,0x1485,0xf16,0x264a,0x2bb,0x609,0x19d,0x21da,0x6d7,0x234f,0x2cc4,0xaf9,0x20c2,0xcdd,0x2f1,0x1dfd,0x1c7,0x247b,0xec9,0x1978,0x770,0x72b,0x1ca3,0xe43,0x1820,0xdf9,0x690,0x926,0x3cc,0x2f20,0xa7c,0x121,0x2f02,0xee6,0x2ae2,0xa85,0xe29,0xd2b,0x1326,0x2e3d,0x1553,0x2ff5,0x133,0x2d81,0x143d,0x19fc,0x174a,0x19b9,0x2a40,0x22ab,0x1d27,0x8cf,0x1730,0x1386,0x491,0x212b,0x2954,0xf53,0xbfd,0x113a,0x144f,0x21f8,0x1b0a,0x385,0x2ce6,0xf63,0x1a64,0x48f,0x2059,0x1e4b,0x1d12,0x1f7f,0x2255,0x24f2,0x16e5,0x1242,0xa29,0x1a6,0xdd5,0x7e9,0x2eac,0x2e17,0x8f7,0x9ed,0x1de0,0x1588,0x2935,0x1c3e,0x2534,0xaf2,0x2002,0x7b4,0x2bf,0x1d25,0x2273,0x1240,0x176e,0x29b1,0x217c,0x1f5d,0xa7d,0x6e8,0x1f55,0x104e,0xb07,0x241e,0xc14,0x618,0x1fad,0x2cac,0x93d,0x1e4f,0x2907,0x281,0x1bf3,0x588,0x277d,0x1e6b,0x9df,0x629,0x1f46,0x19a7,0x3c8,0x1804,0x1981,0x2536,0x19,0x6c,0x1092,0x1980,0x13ae,0xfe4,0x2f42,0x9e,0x2837,0xea,0x23e7,0x73f,0xaa3,0x226e,0x3c1,0x1f94,0x2832,0x1408,0xd63,0x1559,0x19e7,0x273,0x2fe5,0x1e40,0xa2b,0xd34,0x1be2,0x353,0x1ef7,0x147,0x10e3,0xd6d,0x248e,0xbfc,0xc04,0x9aa,0xc8,0x360,0x2262,0x100b,0x99a,0x278f,0x2efc,0x1c3d,0x29a2,0x21ec,0x251e,0x1bdb,0x2b6d,0x2d82,0x15f8,0x2924,0x2393,0x1fd,0x109a,0x17b7,0x2559,0x20b1,0x2147,0xd30,0xea6,0xf47,0x12c3,0x253,0x288c,0xbf3,0x22a3,0x78a,0x2725,0x20d,0x16d2,0x47f,0xfc,0xfc6,0xb7f,0x957,0x2514,0x1216,0xbda,0x709,0x2809,0x172e,0x1e60,0x28f9,0x23df,0x908,0x2445,0x1646,0xe38,0x3d2,0x160b,0x6e6,0x1788,0x2fe4,0x15d8,0x47,0xce8,0x1ecb,0x6b7,0x2a73,0x1619,0x27c7,0x633,0x2fe7,0x2a9a,0x1a96,0x297d,0xc2d,0x2488,0x1953,0xb89,0x131c,0x1729,0x1b16,0x1275,0x1fbb,0x184c,0x1c28,0x198a,0x2934,0x1f9,0x2553,0x11e5,0xfdc,0x2a4d,0xdc4,0x1146,0x956,0x92d,0x21e1,0x1a95,0x2fa1,0x998,0x1c01,0x131d,0x2a3f,0xb4b,0x2cf2,0x2fe1,0x724,0x1956,0x1cce,0x254a,0x2a0a,0x1497,0x11e7,0xc71,0xf58,0x77d,0x2245,0x40f,0x22c,0x871,0x3d3,0x18dd,0x1cd,0x2df0,0x1009,0x1a94,0x29da,0x1963,0x7e7,0x2908,0x848,0xc28,0x19a2,0x31d,0x2c2c,0x2608,0x23a5,0x542,0x2fad,0x865,0x1e81,0x2da9,0x25e1,0x1303,0x240c,0x7ba,0x2a8,0xc0d,0xda8,0x124d,0x28a8,0x1ff7,0x2829,0x146,0xb43,0x23ea,0x1894,0x2e27,0x2dc4,0x2d43,0x18a3,0x1a44,0xbb3,0x28b9,0x1fe9,0x226b,0x1409,0xb7a,0x1c75,0x4e,0x1299,0x1040,0x1fcc,0x171e,0xb8a,0xd1,0x75e,0x26ae,0x229b,0xec0,0x157a,0x111c,0x6b5,0x6d,0x5ae,0x1467,0x1c9d,0x200a,0x5eb,0x1339,0xbff,0x120,0x1fbe,0x13ff,0x3d1,0x2a60,0x1b87,0x196a,0x57,0x1b4f,0x1220,0x1d30,0xccd,0x248b,0x2aa8,0x1db7,0x18ae,0x10aa,0x1425,0x2f2c,0x1187,0x3a1,0x26b8,0x2466,0x14e9,0x1518,0x2b1f,0x1ae6,0x238e,0x1a78,0x1819,0x2284,0x1475,0xaf,0x2f4,0x13fc,0x227d,0x29c0,0xf3a,0x187a,0x5e4,0x1950,0x2a25,0x29e1,0xddd,0x295d,0x1351,0x304,0x2bc0,0xd2,0xd25,0x2195,0x1fc9,0x1ee6,0x2f13,0x6db,0xa6a,0x1d99,0x2b60,0x1234,0x283c,0x2ac2,0x11a9,0x639,0x2290,0x2bda,0x32f,0x2a5f,0x15c0,0x139c,0x7e8,0x88a,0x43f,0x2762,0x1271,0x119d,0x1fed,0x1b4d,0x692,0x1d2b,0x1feb,0x1380,0x2628,0x2a93,0x2226,0xe71,0x2d1b,0x20ab,0x17ff,0x1e27,0x2fb1,0xe65,0x17c8,0x1fa6,0x43b,0x548,0x2256,0x9a5,0x71a,0x26ea,0x2d38,0x1b40,0x1b79,0x658,0x15a5,0x224f,0x248,0xeee,0x2f37,0x1c30,0x15ec,0x1ca7,0x255f,0x2801,0x18f7,0x1727,0xf88,0x2b1,0x2c45,0x164b,0x289f,0x14dd,0x2649,0x27a3,0x9f0,0x21ca,0x1f5,0x1dd6,0xbc3,0x71f,0x133e,0x13bb,0x2afe,0xc35,0x4bb,0x2d31,0x10a7,0x2a04,0x180e,0x2613,0x330,0xe76,0x19fd,0xfe9,0x935,0x79,0x1b01,0x73c,0x2ac6,0x21ce,0x1911,0x761,0x1084,0x1983,0xc3,0x15eb,0xe0a,0xdd,0x1cb1,0xb21,0x2a51,0x217f,0xb1,0x1328,0x9ca,0x1d96,0x1a0b,0xe1b,0x1c4b,0x3b,0x4d6,0x2344,0x199e,0x28af,0x1624,0x4ae,0x8b2,0x2991,0x1fb7,0x41,0x2780,0x1d8b,0xa7f,0x110,0x2350,0x18aa,0x2b2f,0x1805,0x1ff,0xf0,0x2a74,0xe42,0xd97,0x85b,0x14bc,0x2901,0xfd8,0x1ab3,0x1cef,0xfbd,0x2b07,0x174f,0x69b,0x10c3,0x1491,0xde3,0x28ca,0x252e,0x1849,0x1ec2,0x1f1b,0x2853,0x12ab,0x2674,0x238c,0x350,0x2ca,0xa7,0x4bd,0xcc3,0x90c,0x892,0x276,0x1e55,0x196d,0x1194,0x1bef,0x66a,0x1da1,0x260f,0x1c15,0x49f,0x120b,0x2671,0x1237,0x2e0d,0x2791,0x17d8,0x1e0a,0x2a99,0x14cf,0xfb1,0x15b4,0x1462,0x2fbb,0xeff,0x16b,0x2d6a,0x9ef,0x5e3,0x11c0,0x2e76,0x1623,0x2db8,0x1c88,0x740,0x11e1,0x12a3,0x977,0x1110,0x2163,0x2dee,0x47b,0x2aa5,0x2a22,0x1231,0x16e7,0x1626,0x12e0,0x1d28,0xe96,0xb62,0x21d0,0xf09,0xb30,0xcb8,0x2981,0x2648,0x155d,0x27ee,0xb34,0x169,0x1574,0x1fe6,0x25f4,0x151d,0x1801,0x1f13,0x1308,0x2929,0x6eb,0x25e,0x2cca,0x1e3e,0x248f};
+
+func round(a int32,b int32) int32 {
+	return (a+b/2)/b
+}
+
+/* constant time absolute vaue */
+func nabs(x int32 ) int32 {
+	mask:=(x>>31)
+	return (x+mask)^mask
+}
+
+/* Montgomery stuff */
+
+func redc(T uint64) int32 {
+	m:=(uint32(T)*NHS_ND)
+	return int32((uint64(m)*uint64(NHS_PRIME)+T)>>NHS_WL)
+}
+
+func nres(x int32) int32 {
+	return redc(uint64(x)*NHS_R2MODP)
+}
+
+func modmul(a int32,b int32) int32 {
+	return redc(uint64(a)*uint64(b))
+}
+
+/* NTT code */
+/* Cooley-Tukey NTT */
+
+func ntt(x []int32) {
+	t:=NHS_DEGREE/2
+	q:=NHS_PRIME
+
+/* Convert to Montgomery form */
+	for j:=0;j<NHS_DEGREE;j++ {x[j]=nres(x[j])}
+	m:=1
+	for m<NHS_DEGREE {
+		k:=0
+		for i:=0;i<m;i++ {
+			S:=NHS_roots[m+i]
+			for j:=k;j<k+t;j++ {
+				U:=x[j]
+				V:=modmul(x[j+t],S)
+				x[j]=U+V
+				x[j+t]=U+2*q-V
+			}
+			k+=2*t
+		}
+		t/=2
+		m*=2
+	}
+}
+
+/* Gentleman-Sande INTT */
+
+func intt(x []int32) {
+	t:=1;
+	q:=NHS_PRIME
+
+	m:=NHS_DEGREE/2;
+	for m>1 {
+		k:=0;
+		for i:=0;i<m;i++ {
+			S:=NHS_iroots[m+i]
+			for j:=k;j<k+t;j++ {	
+				U:=x[j] 
+				V:=x[j+t]
+				x[j]=U+V	
+				W:=U+int32(NHS_DEGREE)*q-V
+				x[j+t]=modmul(W,S) 
+			}
+			k+=2*t
+		}
+		t*=2
+		m/=2
+	}
+
+/* Last iteration merged with n^-1 */
+
+	t=NHS_DEGREE/2
+	for j:=0;j<t;j++ {
+		U:=x[j]
+		V:=x[j+t]
+		W:=U+int32(NHS_DEGREE)*q-V
+		x[j+t]=modmul(W,NHS_invpr)
+		x[j]=modmul(U+V,NHS_inv)
+	}
+/* convert back from Montgomery to "normal" form */
+	for j:=0;j<NHS_DEGREE;j++ {
+		x[j]=redc(uint64(x[j]))
+		x[j]-=q
+		x[j]+=(x[j]>>(NHS_WL-1))&q
+	} 
+}
+
+/* See https://eprint.iacr.org/2016/1157.pdf */ 
+
+func encode(key []byte,poly []int32) {
+
+	q2:=NHS_PRIME/2
+	j:=0
+	for i:=0;i<256;  {
+		kj:=key[j]
+		j++
+		for k:=0;k<8;k++ {
+			b:=int32(kj&1)
+			poly[i]=b*q2
+			poly[i+256]=b*q2
+			poly[i+512]=b*q2
+			poly[i+768]=b*q2
+			kj>>=1
+			i++
+		}
+	}		
+}
+
+func decode(poly []int32,key []byte) {
+	q2:=NHS_PRIME/2
+	for i:=0;i<32;i++ {
+		key[i]=0
+	}
+
+	j:=0
+	for i:=0;i<256; {
+		for k:=0;k<8;k++ {
+			t:=nabs(poly[i]-q2)+nabs(poly[i+256]-q2)+nabs(poly[i+512]-q2)+nabs(poly[i+768]-q2)
+			b:=t-NHS_PRIME
+			b=(b>>31)&1
+			key[j]=(key[j]>>1)+byte(b<<7)
+			i++
+		}
+		j++
+	}
+}
+
+/* convert 32-byte seed to random polynomial */
+
+func parse(seed []byte,poly []int32) {
+	var hash [4*NHS_DEGREE] byte
+	sh:=NewSHA3(SHA3_SHAKE128)
+
+	for i:=0;i<32;i++ {
+		sh.Process(seed[i])
+	}
+	sh.Shake(hash[:],4*NHS_DEGREE)
+
+	j:=0
+	for i:=0;i<NHS_DEGREE;i++ {
+		n:=int32(hash[j]&0x7f); n<<=8
+		n+=int32(hash[j+1]); n<<=8
+		n+=int32(hash[j+2]); n<<=8
+		n+=int32(hash[j+3]); j+=4
+		poly[i]=nres(n)
+		//poly[i]=modmul(n,NHS_ONE) // reduce 31-bit random number mod q
+	}
+} 
+
+/* Compress 14 bits polynomial coefficients into byte array */
+/* 7 bytes is 3x14 */
+
+func nhs_pack(poly []int32,array []byte) {
+	j:=0
+	for i:=0;i<NHS_DEGREE;  {
+		a:=poly[i]; b:=poly[i+1]; c:=poly[i+2]; d:=poly[i+3]; i+=4
+		array[j]=byte(a&0xff)
+		array[j+1]=byte(((a>>8)|(b<<6))&0xff)
+		array[j+2]=byte((b>>2)&0xff)
+		array[j+3]=byte(((b>>10)|(c<<4))&0xff)
+		array[j+4]=byte((c>>4)&0xff)
+		array[j+5]=byte(((c>>12)|(d<<2))&0xff)
+		array[j+6]=byte(d>>6)
+		j+=7
+	}
+}
+
+func nhs_unpack(array []byte,poly []int32) {
+	j:=0
+	for i:=0;i<NHS_DEGREE; {
+		a:=int32((array[j])&0xff); b:=int32((array[j+1])&0xff); c:=int32((array[j+2])&0xff); d:=int32((array[j+3])&0xff); e:=int32((array[j+4])&0xff); f:=int32((array[j+5])&0xff); g:=int32((array[j+6])&0xff); j+=7
+		poly[i]=a|((b&0x3f)<<8)
+		poly[i+1]=(b>>6)|(c<<2)|((d&0xf)<<10)
+		poly[i+2]=(d>>4)|(e<<4)|((f&3)<<12)
+		poly[i+3]=(f>>2)|(g<<6)
+		i+=4
+	}
+}
+
+/* See https://eprint.iacr.org/2016/1157.pdf */ 
+
+func compress(poly []int32,array []byte) {
+	
+	var col int32=0
+	j:=0
+	for i:=0;i<NHS_DEGREE;  {
+		for k:=0;k<8;k++  {
+			b:=round((poly[i]*8),NHS_PRIME)&7 
+			col=(col<<3)+b
+			i+=1
+		}
+		array[j]=byte(col&0xff)
+		array[j+1]=byte((col>>8)&0xff)
+		array[j+2]=byte((col>>16)&0xff)
+		j+=3; col=0
+	}
+}
+
+func decompress(array []byte,poly []int32) {
+	var col int32=0
+	j:=0
+	for i:=0;i<NHS_DEGREE;  {
+		col=int32(array[j+2])&0xff
+		col=(col<<8)+(int32(array[j+1])&0xff)
+		col=(col<<8)+(int32(array[j])&0xff)
+		j+=3
+		for k:=0;k<8;k++ {
+			b:=(col&0xe00000)>>21; col<<=3
+			poly[i]=round((b*NHS_PRIME),8)
+			i+=1
+		}
+	}
+}
+
+/* generate centered binomial distribution */ 
+
+func error(rng *RAND,poly []int32) {
+	var r int32
+	for i:=0;i<NHS_DEGREE;i++ {
+		n1:=(int32(rng.GetByte())&0xff)+((int32(rng.GetByte())&0xff)<<8)
+		n2:=(int32(rng.GetByte())&0xff)+((int32(rng.GetByte())&0xff)<<8)
+		r=0
+		for j:=0;j<16;j++ {
+			r+=(n1&1)-(n2&1)
+			n1>>=1; n2>>=1
+		}
+		poly[i]=(r+NHS_PRIME)
+	}
+}
+
+func redc_it(p []int32) {
+	for i:=0;i<NHS_DEGREE;i++ {
+		p[i]=redc(uint64(p[i]))
+	}	
+}
+
+func nres_it(p []int32) {
+	for i:=0;i<NHS_DEGREE;i++ {
+		p[i]=nres(p[i])
+	}	
+}
+
+func poly_mul(p1 []int32,p2 [] int32,p3 []int32) {
+	for i:=0;i<NHS_DEGREE;i++ {
+		p1[i]=modmul(p2[i],p3[i])
+	}
+}
+
+func poly_add(p1 []int32,p2 []int32,p3 []int32) {
+	for i:=0;i<NHS_DEGREE;i++ {
+		p1[i]=(p2[i]+p3[i])
+	}
+}
+
+func poly_sub(p1 []int32,p2 []int32,p3 []int32) {
+	for i:=0;i<NHS_DEGREE;i++ {
+		p1[i]=(p2[i]+NHS_PRIME-p3[i])
+	}
+}
+
+/* reduces inputs < 2q */
+func poly_soft_reduce(poly []int32) {
+	for i:=0;i<NHS_DEGREE;i++ {
+		e:=poly[i]-NHS_PRIME
+		poly[i]=e+((e>>(NHS_WL-1))&NHS_PRIME)
+	}
+}
+
+/* fully reduces modulo q */
+func poly_hard_reduce(poly []int32) {
+	for i:=0;i<NHS_DEGREE;i++ {
+		e:=modmul(poly[i],NHS_ONE)
+		e=e-NHS_PRIME
+		poly[i]=e+((e>>(NHS_WL-1))&NHS_PRIME)
+	}
+}
+
+/* API files */
+
+func NHS_SERVER_1(rng *RAND,SB []byte,S []byte) {
+	var seed [32] byte
+	var array [1792] byte
+	var s [NHS_DEGREE] int32
+	var e [NHS_DEGREE] int32
+	var b [NHS_DEGREE] int32
+
+	for i:=0;i<32;i++ {
+		seed[i]=rng.GetByte()
+	}
+
+	parse(seed[:],b[:])
+	
+	error(rng,e[:])
+	error(rng,s[:])
+
+	ntt(s[:])
+	ntt(e[:])
+	poly_mul(b[:],b[:],s[:])
+	poly_add(b[:],b[:],e[:])
+	poly_hard_reduce(b[:])
+
+	redc_it(b[:])
+	nhs_pack(b[:],array[:])
+
+	for i:=0;i<32;i++ {
+		SB[i]=seed[i]
+	}
+
+	for i:=0;i<1792;i++ {
+		SB[i+32]=array[i]
+	}
+
+	poly_hard_reduce(s[:])
+	nhs_pack(s[:],array[:])
+
+	for i:=0;i<1792;i++ {
+		S[i]=array[i]
+	}
+
+}
+
+func NHS_CLIENT(rng *RAND,SB []byte,UC []byte,KEY []byte) {
+	sh:=NewSHA3(SHA3_HASH256)
+	var seed [32] byte
+	var array [1792] byte
+	var key [32] byte
+	var cc [384] byte
+
+	var sd [NHS_DEGREE] int32
+	var ed [NHS_DEGREE] int32
+	var u [NHS_DEGREE] int32
+	var k [NHS_DEGREE] int32
+	var c [NHS_DEGREE] int32
+
+	error(rng,sd[:])
+	error(rng,ed[:])
+
+	ntt(sd[:])
+	ntt(ed[:])
+
+	for i:=0;i<32;i++ {
+		seed[i]=SB[i]
+	}
+
+	for i:=0;i<1792;i++ {
+		array[i]=SB[i+32]
+	}
+
+	parse(seed[:],u[:])
+
+	poly_mul(u[:],u[:],sd[:])
+	poly_add(u[:],u[:],ed[:])
+	poly_hard_reduce(u[:])
+
+	for i:=0;i<32;i++ {
+		key[i]=rng.GetByte()
+	}
+
+	for i:=0;i<32;i++ {
+		sh.Process(key[i])
+	}
+	sh.Hash(key[:])
+
+	encode(key[:],k[:])
+
+	nhs_unpack(array[:],c[:])
+	nres_it(c[:])
+
+	poly_mul(c[:],c[:],sd[:])
+	intt(c[:])
+	error(rng,ed[:])
+	poly_add(c[:],c[:],ed[:])
+	poly_add(c[:],c[:],k[:])
+
+	compress(c[:],cc[:])
+
+	sh.Init(SHA3_HASH256)
+	for i:=0;i<32;i++ {
+		sh.Process(key[i])
+	}
+	sh.Hash(key[:])
+
+	for i:=0;i<32;i++ {
+		KEY[i]=key[i]
+	}
+
+	redc_it(u[:])
+	nhs_pack(u[:],array[:])
+
+	for i:=0;i<1792;i++ {
+		UC[i]=array[i]
+	}
+
+	for i:=0;i<384;i++ {
+		UC[i+1792]=cc[i]
+	}
+}
+
+func NHS_SERVER_2(S []byte,UC []byte,KEY []byte) {
+	sh:=NewSHA3(SHA3_HASH256)
+
+	var c [NHS_DEGREE] int32
+	var s [NHS_DEGREE] int32
+	var k [NHS_DEGREE] int32
+
+	var array [1792] byte
+	var key [32] byte
+	var cc [384] byte
+
+	for i:=0;i<1792;i++ {
+		array[i]=UC[i]
+	}
+
+	nhs_unpack(array[:],k[:])
+	nres_it(k[:])
+
+	for i:=0;i<384;i++ {
+		cc[i]=UC[i+1792]
+	}
+
+	decompress(cc[:],c[:])
+
+	for i:=0;i<1792;i++ {
+		array[i]=S[i]
+	}
+
+	nhs_unpack(array[:],s[:])
+
+	poly_mul(k[:],k[:],s[:])
+	intt(k[:])
+	poly_sub(k[:],c[:],k[:])
+	poly_soft_reduce(k[:])
+
+	decode(k[:],key[:])
+
+	for i:=0;i<32;i++ {
+		sh.Process(key[i])
+	}
+	sh.Hash(key[:])
+
+	for i:=0;i<32;i++ {
+		KEY[i]=key[i]
+	}
+}
+
+/*
+func main() {
+
+	srng:=NewRAND()
+	var sraw [100]byte
+	for i:=0;i<100;i++ {sraw[i]=byte(i+1)}
+	srng.Seed(100,sraw[:])
+
+							crng:=NewRAND()
+							var craw [100]byte
+							for i:=0;i<100;i++ {craw[i]=byte(i+2)}
+							crng.Seed(100,craw[:])
+
+	var S [1792] byte
+
+				var SB [1824] byte	
+	NHS_SERVER_1(srng,SB[:],S[:])
+				var UC [2176] byte
+							var KEYB [32] byte
+							NHS_CLIENT(crng,SB[:],UC[:],KEYB[:])
+				
+							fmt.Printf("Bob's Key= ")
+							for i:=0;i<32;i++ {
+								fmt.Printf("%02x", KEYB[i])
+							}
+							fmt.Printf("\n")
+	var KEYA [32] byte
+	NHS_SERVER_2(S[:],UC[:],KEYA[:])
+
+	fmt.Printf("Alice Key= ")
+	for i:=0;i<32;i++ {
+		fmt.Printf("%02x", KEYA[i])
+	}
+	
+} 
+*/
diff --git a/version3/go/PAIR.go b/version3/go/PAIR.go
new file mode 100644
index 0000000..fef6fde
--- /dev/null
+++ b/version3/go/PAIR.go
@@ -0,0 +1,777 @@
+/*
+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.
+*/
+
+/* MiotCL BN Curve Pairing functions */
+
+package XXX
+
+//import "fmt"
+
+/* Line function */
+func line(A *ECP2,B *ECP2,Qx *FP,Qy *FP) *FP12 {
+	var a *FP4
+	var b *FP4
+	var c *FP4
+
+	if (A==B) { /* Doubling */
+		XX:=NewFP2copy(A.getx())  //X
+		YY:=NewFP2copy(A.gety())  //Y
+		ZZ:=NewFP2copy(A.getz())  //Z
+		YZ:=NewFP2copy(YY)        //Y 
+		YZ.mul(ZZ)                //YZ
+		XX.sqr()			//X^2
+		YY.sqr()			//Y^2
+		ZZ.sqr()			//Z^2
+			
+		YZ.imul(4)
+		YZ.neg(); YZ.norm()       //-4YZ
+		YZ.pmul(Qy);               //-4YZ.Ys
+
+		XX.imul(6)                //6X^2
+		XX.pmul(Qx);              //6X^2.Xs
+
+		sb:=3*CURVE_B_I
+		ZZ.imul(sb); 			// 3bZ^2
+		if SEXTIC_TWIST == D_TYPE {	
+			ZZ.div_ip2();
+		}
+		if SEXTIC_TWIST == M_TYPE {
+			ZZ.mul_ip();
+			ZZ.add(ZZ);
+			YZ.mul_ip();
+			YZ.norm();
+		}
+		ZZ.norm() // 3b.Z^2 
+
+		YY.add(YY)
+		ZZ.sub(YY); ZZ.norm()     // 3b.Z^2-2Y^2
+
+		a=NewFP4fp2s(YZ,ZZ);          // -4YZ.Ys | 3b.Z^2-2Y^2 | 6X^2.Xs 
+		if SEXTIC_TWIST == D_TYPE {	
+
+			b=NewFP4fp2(XX)             // L(0,1) | L(0,0) | L(1,0)
+			c=NewFP4int(0)
+		}
+		if SEXTIC_TWIST == M_TYPE {
+			b=NewFP4int(0)
+			c=NewFP4fp2(XX); c.times_i()
+		}
+		A.dbl();
+
+	} else { /* Addition */
+
+		X1:=NewFP2copy(A.getx())    // X1
+		Y1:=NewFP2copy(A.gety())    // Y1
+		T1:=NewFP2copy(A.getz())    // Z1
+		T2:=NewFP2copy(A.getz())    // Z1
+			
+		T1.mul(B.gety())    // T1=Z1.Y2 
+		T2.mul(B.getx())    // T2=Z1.X2
+
+		X1.sub(T2); X1.norm()  // X1=X1-Z1.X2
+		Y1.sub(T1); Y1.norm()  // Y1=Y1-Z1.Y2
+
+		T1.copy(X1)            // T1=X1-Z1.X2
+		X1.pmul(Qy)            // X1=(X1-Z1.X2).Ys
+
+		if SEXTIC_TWIST == M_TYPE {
+			X1.mul_ip()
+			X1.norm()
+		}
+
+		T1.mul(B.gety())       // T1=(X1-Z1.X2).Y2
+
+		T2.copy(Y1)           // T2=Y1-Z1.Y2
+		T2.mul(B.getx())       // T2=(Y1-Z1.Y2).X2
+		T2.sub(T1); T2.norm()          // T2=(Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2
+		Y1.pmul(Qx);  Y1.neg(); Y1.norm() // Y1=-(Y1-Z1.Y2).Xs
+
+		a=NewFP4fp2s(X1,T2)       // (X1-Z1.X2).Ys  |  (Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2  | - (Y1-Z1.Y2).Xs
+		if SEXTIC_TWIST == D_TYPE {
+			b=NewFP4fp2(Y1)
+			c=NewFP4int(0)
+		}
+		if SEXTIC_TWIST == M_TYPE {
+			b=NewFP4int(0)
+			c=NewFP4fp2(Y1); c.times_i()
+		}
+		A.Add(B);
+	}
+
+
+	return NewFP12fp4s(a,b,c)
+}
+
+/* Optimal R-ate pairing */
+func Ate(P1 *ECP2,Q1 *ECP) *FP12 {
+	f:=NewFP2bigs(NewBIGints(Fra),NewBIGints(Frb))
+	x:=NewBIGints(CURVE_Bnx)
+	n:=NewBIGcopy(x)
+	K:=NewECP2()
+	var lv *FP12
+	
+	if CURVE_PAIRING_TYPE == BN {
+		if SEXTIC_TWIST==M_TYPE {
+			f.inverse();
+			f.norm();
+		}
+		n.pmul(6)
+		if SIGN_OF_X==POSITIVEX {
+			n.inc(2)
+		} else {
+			n.dec(2)
+		}
+	} else {n.copy(x)}
+	
+	n.norm()
+
+	n3:=NewBIGcopy(n);
+	n3.pmul(3);
+	n3.norm();
+
+	P:=NewECP2(); P.Copy(P1); P.Affine()
+	Q:=NewECP(); Q.Copy(Q1); Q.Affine()
+
+
+	Qx:=NewFPcopy(Q.getx())
+	Qy:=NewFPcopy(Q.gety())
+
+	A:=NewECP2()
+	r:=NewFP12int(1)
+
+	A.Copy(P)
+
+	NP:=NewECP2()
+	NP.Copy(P)
+	NP.neg()
+
+	nb:=n3.nbits()
+
+	for i:=nb-2;i>=1;i-- {
+		r.sqr()
+		lv=line(A,A,Qx,Qy)
+		r.smul(lv,SEXTIC_TWIST)
+		bt:=n3.bit(i)-n.bit(i);
+		if bt==1 {
+			lv=line(A,P,Qx,Qy)
+			r.smul(lv,SEXTIC_TWIST)
+		}	
+		if bt==-1 {
+			//P.neg()
+			lv=line(A,NP,Qx,Qy)
+			r.smul(lv,SEXTIC_TWIST)
+			//P.neg()
+		}		
+	}
+
+	if SIGN_OF_X==NEGATIVEX {
+		r.conj()
+	}
+
+
+/* R-ate fixup required for BN curves */
+
+	if CURVE_PAIRING_TYPE == BN {
+		if SIGN_OF_X==NEGATIVEX {
+			//r.conj()
+			A.neg()
+		}
+
+		K.Copy(P)
+		K.frob(f)
+		lv=line(A,K,Qx,Qy)
+		r.smul(lv,SEXTIC_TWIST)
+		K.frob(f)
+		K.neg()
+		lv=line(A,K,Qx,Qy)
+		r.smul(lv,SEXTIC_TWIST)
+	} 
+
+	return r
+}
+
+/* Optimal R-ate double pairing e(P,Q).e(R,S) */
+func Ate2(P1 *ECP2,Q1 *ECP,R1 *ECP2,S1 *ECP) *FP12 {
+	f:=NewFP2bigs(NewBIGints(Fra),NewBIGints(Frb))
+	x:=NewBIGints(CURVE_Bnx)
+	n:=NewBIGcopy(x)
+	K:=NewECP2()
+	var lv *FP12
+
+	if CURVE_PAIRING_TYPE == BN {
+		if SEXTIC_TWIST==M_TYPE {
+			f.inverse();
+			f.norm();
+		}
+		n.pmul(6); 
+		if SIGN_OF_X==POSITIVEX {
+			n.inc(2)
+		} else {
+			n.dec(2)
+		}
+	} else {n.copy(x)}
+	
+	n.norm()
+
+	n3:=NewBIGcopy(n);
+	n3.pmul(3);
+	n3.norm();
+
+	P:=NewECP2(); P.Copy(P1); P.Affine()
+	Q:=NewECP(); Q.Copy(Q1); Q.Affine()
+	R:=NewECP2(); R.Copy(R1); R.Affine()
+	S:=NewECP(); S.Copy(S1); S.Affine()
+
+
+	Qx:=NewFPcopy(Q.getx())
+	Qy:=NewFPcopy(Q.gety())
+	Sx:=NewFPcopy(S.getx())
+	Sy:=NewFPcopy(S.gety())
+
+	A:=NewECP2()
+	B:=NewECP2()
+	r:=NewFP12int(1)
+
+	A.Copy(P)
+	B.Copy(R)
+	NP:=NewECP2()
+	NP.Copy(P)
+	NP.neg()
+	NR:=NewECP2()
+	NR.Copy(R)
+	NR.neg()
+
+
+	nb:=n3.nbits()
+
+	for i:=nb-2;i>=1;i-- {
+		r.sqr()
+		lv=line(A,A,Qx,Qy)
+		r.smul(lv,SEXTIC_TWIST)
+		lv=line(B,B,Sx,Sy)
+		r.smul(lv,SEXTIC_TWIST)
+		bt:=n3.bit(i)-n.bit(i);
+		if bt==1 {
+			lv=line(A,P,Qx,Qy)
+			r.smul(lv,SEXTIC_TWIST)
+			lv=line(B,R,Sx,Sy)
+			r.smul(lv,SEXTIC_TWIST)
+		}
+		if bt==-1 {
+			//P.neg(); 
+			lv=line(A,NP,Qx,Qy)
+			r.smul(lv,SEXTIC_TWIST)
+			//P.neg(); 
+			//R.neg()
+			lv=line(B,NR,Sx,Sy)
+			r.smul(lv,SEXTIC_TWIST)
+			//R.neg()
+		}
+	}
+
+	if SIGN_OF_X==NEGATIVEX {
+		r.conj()
+	}
+
+/* R-ate fixup */
+	if CURVE_PAIRING_TYPE == BN {
+		if SIGN_OF_X==NEGATIVEX {
+		//	r.conj()
+			A.neg()
+			B.neg()
+		}
+		K.Copy(P)
+		K.frob(f)
+
+		lv=line(A,K,Qx,Qy)
+		r.smul(lv,SEXTIC_TWIST)
+		K.frob(f)
+		K.neg()
+		lv=line(A,K,Qx,Qy)
+		r.smul(lv,SEXTIC_TWIST)
+
+		K.Copy(R)
+		K.frob(f)
+
+		lv=line(B,K,Sx,Sy)
+		r.smul(lv,SEXTIC_TWIST)
+		K.frob(f)
+		K.neg()
+		lv=line(B,K,Sx,Sy)
+		r.smul(lv,SEXTIC_TWIST)
+	}
+
+	return r
+}
+
+/* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */
+func Fexp(m *FP12) *FP12 {
+	f:=NewFP2bigs(NewBIGints(Fra),NewBIGints(Frb))
+	x:=NewBIGints(CURVE_Bnx)
+	r:=NewFP12copy(m)
+		
+/* Easy part of final exp */
+	lv:=NewFP12copy(r)
+	lv.Inverse()
+	r.conj()
+
+	r.Mul(lv)
+	lv.Copy(r)
+	r.frob(f)
+	r.frob(f)
+	r.Mul(lv)
+/* Hard part of final exp */
+	if CURVE_PAIRING_TYPE == BN {
+		lv.Copy(r)
+		lv.frob(f)
+		x0:=NewFP12copy(lv)
+		x0.frob(f)
+		lv.Mul(r)
+		x0.Mul(lv)
+		x0.frob(f)
+		x1:=NewFP12copy(r)
+		x1.conj()
+		x4:=r.Pow(x)
+		if SIGN_OF_X==POSITIVEX {
+			x4.conj();
+		}
+
+		x3:=NewFP12copy(x4)
+		x3.frob(f)
+
+		x2:=x4.Pow(x)
+		if SIGN_OF_X==POSITIVEX {
+			x2.conj();
+		}
+
+		x5:=NewFP12copy(x2); x5.conj()
+		lv=x2.Pow(x)
+		if SIGN_OF_X==POSITIVEX {
+			lv.conj();
+		}
+
+		x2.frob(f)
+		r.Copy(x2); r.conj()
+
+		x4.Mul(r)
+		x2.frob(f)
+
+		r.Copy(lv)
+		r.frob(f)
+		lv.Mul(r)
+
+		lv.usqr()
+		lv.Mul(x4)
+		lv.Mul(x5)
+		r.Copy(x3)
+		r.Mul(x5)
+		r.Mul(lv)
+		lv.Mul(x2)
+		r.usqr()
+		r.Mul(lv)
+		r.usqr()
+		lv.Copy(r)
+		lv.Mul(x1)
+		r.Mul(x0)
+		lv.usqr()
+		r.Mul(lv)
+		r.reduce()
+	} else {
+		
+// Ghamman & Fouotsa Method
+		y0:=NewFP12copy(r); y0.usqr()
+		y1:=y0.Pow(x)
+		if SIGN_OF_X==NEGATIVEX {
+			y1.conj();
+		}
+
+		x.fshr(1); y2:=y1.Pow(x); 
+		if SIGN_OF_X==NEGATIVEX {
+			y2.conj();
+		}
+		
+		x.fshl(1)
+		y3:=NewFP12copy(r); y3.conj()
+		y1.Mul(y3)
+
+		y1.conj()
+		y1.Mul(y2)
+
+		y2=y1.Pow(x)
+		if SIGN_OF_X==NEGATIVEX {
+			y2.conj();
+		}
+
+
+		y3=y2.Pow(x)
+		if SIGN_OF_X==NEGATIVEX {
+			y3.conj();
+		}
+
+		y1.conj()
+		y3.Mul(y1)
+
+		y1.conj();
+		y1.frob(f); y1.frob(f); y1.frob(f)
+		y2.frob(f); y2.frob(f)
+		y1.Mul(y2)
+
+		y2=y3.Pow(x)
+		if SIGN_OF_X==NEGATIVEX {
+			y2.conj();
+		}
+
+		y2.Mul(y0)
+		y2.Mul(r)
+
+		y1.Mul(y2)
+		y2.Copy(y3); y2.frob(f)
+		y1.Mul(y2)
+		r.Copy(y1)
+		r.reduce()
+
+
+/*
+		x0:=NewFP12copy(r)
+		x1:=NewFP12copy(r)
+		lv.Copy(r); lv.frob(f)
+		x3:=NewFP12copy(lv); x3.conj(); x1.Mul(x3)
+		lv.frob(f); lv.frob(f)
+		x1.Mul(lv)
+
+		r.Copy(r.Pow(x))  //r=r.Pow(x);
+		x3.Copy(r); x3.conj(); x1.Mul(x3)
+		lv.Copy(r); lv.frob(f)
+		x0.Mul(lv)
+		lv.frob(f)
+		x1.Mul(lv)
+		lv.frob(f)
+		x3.Copy(lv); x3.conj(); x0.Mul(x3)
+
+		r.Copy(r.Pow(x))
+		x0.Mul(r)
+		lv.Copy(r); lv.frob(f); lv.frob(f)
+		x3.Copy(lv); x3.conj(); x0.Mul(x3)
+		lv.frob(f)
+		x1.Mul(lv)
+
+		r.Copy(r.Pow(x))
+		lv.Copy(r); lv.frob(f)
+		x3.Copy(lv); x3.conj(); x0.Mul(x3)
+		lv.frob(f)
+		x1.Mul(lv)
+
+		r.Copy(r.Pow(x))
+		x3.Copy(r); x3.conj(); x0.Mul(x3)
+		lv.Copy(r); lv.frob(f)
+		x1.Mul(lv)
+
+		r.Copy(r.Pow(x))
+		x1.Mul(r)
+
+		x0.usqr()
+		x0.Mul(x1)
+		r.Copy(x0)
+		r.reduce() */
+	}
+	return r
+}
+
+/* GLV method */
+func glv(e *BIG) []*BIG {
+	var u []*BIG
+	if CURVE_PAIRING_TYPE == BN {
+		t:=NewBIGint(0)
+		q:=NewBIGints(CURVE_Order)
+		var v []*BIG
+
+		for i:=0;i<2;i++ {
+			t.copy(NewBIGints(CURVE_W[i]))  // why not just t=new BIG(ROM.CURVE_W[i]); 
+			d:=mul(t,e)
+			v=append(v,NewBIGcopy(d.div(q)))
+			u=append(u,NewBIGint(0))
+		}
+		u[0].copy(e)
+		for i:=0;i<2;i++ {
+			for j:=0;j<2;j++ {
+				t.copy(NewBIGints(CURVE_SB[j][i]))
+				t.copy(Modmul(v[j],t,q))
+				u[i].add(q)
+				u[i].sub(t)
+				u[i].Mod(q)
+			}
+		}
+	} else {
+		q:=NewBIGints(CURVE_Order)
+		x:=NewBIGints(CURVE_Bnx)
+		x2:=smul(x,x)
+		u=append(u,NewBIGcopy(e))
+		u[0].Mod(x2)
+		u=append(u,NewBIGcopy(e))
+		u[1].div(x2)
+		u[1].rsub(q)
+	}
+	return u
+}
+
+/* Galbraith & Scott Method */
+func gs(e *BIG) []*BIG {
+	var u []*BIG
+	if CURVE_PAIRING_TYPE == BN {
+		t:=NewBIGint(0)
+		q:=NewBIGints(CURVE_Order)
+
+		var v []*BIG
+		for i:=0;i<4;i++ {
+			t.copy(NewBIGints(CURVE_WB[i]))
+			d:=mul(t,e)
+			v=append(v,NewBIGcopy(d.div(q)))
+			u=append(u,NewBIGint(0))
+		}
+		u[0].copy(e)
+		for i:=0;i<4;i++ {
+			for j:=0;j<4;j++ {
+				t.copy(NewBIGints(CURVE_BB[j][i]))
+				t.copy(Modmul(v[j],t,q))
+				u[i].add(q)
+				u[i].sub(t)
+				u[i].Mod(q)
+			}
+		}
+	} else {
+		q:=NewBIGints(CURVE_Order)
+		x:=NewBIGints(CURVE_Bnx)
+		w:=NewBIGcopy(e)
+		for i:=0;i<3;i++ {
+			u=append(u,NewBIGcopy(w))
+			u[i].Mod(x)
+			w.div(x)
+		}
+		u=append(u,NewBIGcopy(w))
+		if SIGN_OF_X==NEGATIVEX {
+			u[1].copy(Modneg(u[1],q));
+			u[3].copy(Modneg(u[3],q));
+		}
+	}
+	return u
+}	
+
+/* Multiply P by e in group G1 */
+func G1mul(P *ECP,e *BIG) *ECP {
+	var R *ECP
+	if (USE_GLV) {
+		//P.Affine()
+		R=NewECP()
+		R.Copy(P)
+		Q:=NewECP()
+		Q.Copy(P); Q.Affine()
+		q:=NewBIGints(CURVE_Order)
+		cru:=NewFPbig(NewBIGints(CURVE_Cru))
+		t:=NewBIGint(0)
+		u:=glv(e)
+		Q.getx().mul(cru)
+
+		np:=u[0].nbits()
+		t.copy(Modneg(u[0],q))
+		nn:=t.nbits()
+		if nn<np {
+			u[0].copy(t)
+			R.neg()
+		}
+
+		np=u[1].nbits()
+		t.copy(Modneg(u[1],q))
+		nn=t.nbits()
+		if nn<np {
+			u[1].copy(t)
+			Q.neg()
+		}
+		u[0].norm()
+		u[1].norm()
+		R=R.Mul2(u[0],Q,u[1])
+			
+	} else {
+		R=P.mul(e)
+	}
+	return R
+}
+
+/* Multiply P by e in group G2 */
+func G2mul(P *ECP2,e *BIG) *ECP2 {
+	var R *ECP2
+	if (USE_GS_G2) {
+		var Q []*ECP2
+		f:=NewFP2bigs(NewBIGints(Fra),NewBIGints(Frb))
+
+		if SEXTIC_TWIST==M_TYPE {
+			f.inverse();
+			f.norm();
+		}
+
+		q:=NewBIGints(CURVE_Order)
+		u:=gs(e)
+
+		t:=NewBIGint(0)
+		//P.Affine()
+		Q=append(Q,NewECP2());  Q[0].Copy(P);
+		for i:=1;i<4;i++ {
+			Q=append(Q,NewECP2()); Q[i].Copy(Q[i-1])
+			Q[i].frob(f)
+		}
+		for i:=0;i<4;i++ {
+			np:=u[i].nbits()
+			t.copy(Modneg(u[i],q))
+			nn:=t.nbits()
+			if nn<np {
+				u[i].copy(t)
+				Q[i].neg()
+			}
+			u[i].norm()
+		}
+
+		R=mul4(Q,u)
+
+	} else {
+		R=P.mul(e)
+	}
+	return R
+}
+
+/* f=f^e */
+/* Note that this method requires a lot of RAM! Better to use compressed XTR method, see FP4.java */
+func GTpow(d *FP12,e *BIG) *FP12 {
+	var r *FP12
+	if USE_GS_GT {
+		var g []*FP12
+		f:=NewFP2bigs(NewBIGints(Fra),NewBIGints(Frb))
+		q:=NewBIGints(CURVE_Order)
+		t:=NewBIGint(0)
+	
+		u:=gs(e)
+
+		g=append(g,NewFP12copy(d))
+		for i:=1;i<4;i++ {
+			g=append(g,NewFP12int(0))
+			g[i].Copy(g[i-1])
+			g[i].frob(f)
+		}
+		for i:=0;i<4;i++ {
+			np:=u[i].nbits()
+			t.copy(Modneg(u[i],q))
+			nn:=t.nbits()
+			if nn<np {
+				u[i].copy(t)
+				g[i].conj()
+			}
+			u[i].norm()			
+		}
+		r=pow4(g,u)
+	} else {
+		r=d.Pow(e)
+	}
+	return r
+}
+
+/* test group membership - no longer needed*/
+/* with GT-Strong curve, now only check that m!=1, conj(m)*m==1, and m.m^{p^4}=m^{p^2} */
+/*
+func GTmember(m *FP12) bool {
+	if m.Isunity() {return false}
+	r:=NewFP12copy(m)
+	r.conj()
+	r.Mul(m)
+	if !r.Isunity() {return false}
+
+	f:=NewFP2bigs(NewBIGints(Fra),NewBIGints(Frb))
+
+	r.Copy(m); r.frob(f); r.frob(f)
+	w:=NewFP12copy(r); w.frob(f); w.frob(f)
+	w.Mul(m)
+	if !GT_STRONG {
+		if !w.Equals(r) {return false}
+		x:=NewBIGints(CURVE_Bnx);
+		r.Copy(m); w=r.Pow(x); w=w.Pow(x)
+		r.Copy(w); r.sqr(); r.Mul(w); r.sqr()
+		w.Copy(m); w.frob(f)
+	}
+	return w.Equals(r)
+}
+*/
+/*
+func main() {
+
+	Q:=NewECPbigs(NewBIGints(CURVE_Gx),NewBIGints(CURVE_Gy))
+	P:=NewECP2fp2s(NewFP2bigs(NewBIGints(CURVE_Pxa),NewBIGints(CURVE_Pxb)),NewFP2bigs(NewBIGints(CURVE_Pya),NewBIGints(CURVE_Pyb)))
+
+	//r:=NewBIGints(CURVE_Order)
+	//xa:=NewBIGints(CURVE_Pxa)
+
+	fmt.Printf("P= "+P.ToString())
+	fmt.Printf("\n");
+	fmt.Printf("Q= "+Q.ToString());
+	fmt.Printf("\n");
+
+	//m:=NewBIGint(17)
+
+	e:=Ate(P,Q)
+	e=Fexp(e)
+	for i:=1;i<1000;i++ {
+		e=Ate(P,Q)
+//	fmt.Printf("\ne= "+e.ToString())
+//	fmt.Printf("\n")
+
+		e=Fexp(e)
+	}
+	//	e=GTpow(e,m);
+
+	fmt.Printf("\ne= "+e.ToString())
+	fmt.Printf("\n");
+	GLV:=glv(r)
+
+	fmt.Printf("GLV[0]= "+GLV[0].ToString())
+	fmt.Printf("\n")
+
+	fmt.Printf("GLV[0]= "+GLV[1].ToString())
+	fmt.Printf("\n")
+
+	G:=NewECP(); G.Copy(Q)
+	R:=NewECP2(); R.Copy(P)
+
+
+	e=Ate(R,Q)
+	e=Fexp(e)
+
+	e=GTpow(e,xa)
+	fmt.Printf("\ne= "+e.ToString());
+	fmt.Printf("\n")
+
+	R=G2mul(R,xa)
+	e=Ate(R,G)
+	e=Fexp(e)
+
+	fmt.Printf("\ne= "+e.ToString())
+	fmt.Printf("\n")
+
+	G=G1mul(G,xa)
+	e=Ate(P,G)
+	e=Fexp(e)
+	fmt.Printf("\ne= "+e.ToString())
+	fmt.Printf("\n") 
+}
+*/
diff --git a/version3/go/PAIR192.go b/version3/go/PAIR192.go
new file mode 100644
index 0000000..88b5ceb
--- /dev/null
+++ b/version3/go/PAIR192.go
@@ -0,0 +1,574 @@
+/*
+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.
+*/
+
+/* MiotCL BN Curve Pairing functions */
+
+package XXX
+
+//import "fmt"
+
+/* Line function */
+func line(A *ECP4,B *ECP4,Qx *FP,Qy *FP) *FP24 {
+	var a *FP8
+	var b *FP8
+	var c *FP8
+
+	if (A==B) { /* Doubling */
+		XX:=NewFP4copy(A.getx())  //X
+		YY:=NewFP4copy(A.gety())  //Y
+		ZZ:=NewFP4copy(A.getz())  //Z
+		YZ:=NewFP4copy(YY)        //Y 
+		YZ.mul(ZZ)                //YZ
+		XX.sqr()	               //X^2
+		YY.sqr()	               //Y^2
+		ZZ.sqr()			       //Z^2
+			
+		YZ.imul(4)
+		YZ.neg(); YZ.norm()       //-2YZ
+		YZ.qmul(Qy);               //-2YZ.Ys
+
+		XX.imul(6)                //3X^2
+		XX.qmul(Qx);               //3X^2.Xs
+
+		sb:=3*CURVE_B_I
+		ZZ.imul(sb); 	
+		if SEXTIC_TWIST == D_TYPE {	
+			ZZ.div_2i();
+		}
+		if SEXTIC_TWIST == M_TYPE {
+			ZZ.times_i();
+			ZZ.add(ZZ);
+			YZ.times_i();
+			YZ.norm();
+		}
+		ZZ.norm() // 3b.Z^2 
+
+		YY.add(YY)
+		ZZ.sub(YY); ZZ.norm()     // 3b.Z^2-Y^2
+
+		a=NewFP8fp4s(YZ,ZZ);          // -2YZ.Ys | 3b.Z^2-Y^2 | 3X^2.Xs 
+		if SEXTIC_TWIST == D_TYPE {	
+
+			b=NewFP8fp4(XX)             // L(0,1) | L(0,0) | L(1,0)
+			c=NewFP8int(0)
+		}
+		if SEXTIC_TWIST == M_TYPE {
+			b=NewFP8int(0)
+			c=NewFP8fp4(XX); c.times_i()
+		}
+		A.dbl();
+
+	} else { /* Addition */
+
+		X1:=NewFP4copy(A.getx())    // X1
+		Y1:=NewFP4copy(A.gety())    // Y1
+		T1:=NewFP4copy(A.getz())    // Z1
+		T2:=NewFP4copy(A.getz())    // Z1
+			
+		T1.mul(B.gety())    // T1=Z1.Y2 
+		T2.mul(B.getx())    // T2=Z1.X2
+
+		X1.sub(T2); X1.norm()  // X1=X1-Z1.X2
+		Y1.sub(T1); Y1.norm()  // Y1=Y1-Z1.Y2
+
+		T1.copy(X1)            // T1=X1-Z1.X2
+		X1.qmul(Qy)            // X1=(X1-Z1.X2).Ys
+
+		if SEXTIC_TWIST == M_TYPE {
+			X1.times_i()
+			X1.norm()
+		}
+
+		T1.mul(B.gety())       // T1=(X1-Z1.X2).Y2
+
+		T2.copy(Y1)           // T2=Y1-Z1.Y2
+		T2.mul(B.getx())       // T2=(Y1-Z1.Y2).X2
+		T2.sub(T1); T2.norm()          // T2=(Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2
+		Y1.qmul(Qx);  Y1.neg(); Y1.norm() // Y1=-(Y1-Z1.Y2).Xs
+
+		a=NewFP8fp4s(X1,T2)       // (X1-Z1.X2).Ys  |  (Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2  | - (Y1-Z1.Y2).Xs
+		if SEXTIC_TWIST == D_TYPE {
+			b=NewFP8fp4(Y1)
+			c=NewFP8int(0)
+		}
+		if SEXTIC_TWIST == M_TYPE {
+			b=NewFP8int(0)
+			c=NewFP8fp4(Y1); c.times_i()
+		}
+		A.Add(B);
+	}
+
+	return NewFP24fp8s(a,b,c)
+}
+
+/* Optimal R-ate pairing */
+func Ate(P1 *ECP4,Q1 *ECP) *FP24 {
+	x:=NewBIGints(CURVE_Bnx)
+	n:=NewBIGcopy(x)
+	var lv *FP24
+	
+	//n.copy(x); n.norm()
+
+	n3:=NewBIGcopy(n);
+	n3.pmul(3);
+	n3.norm();
+
+	P:=NewECP4(); P.Copy(P1); P.Affine()
+	Q:=NewECP(); Q.Copy(Q1); Q.Affine()
+
+
+	Qx:=NewFPcopy(Q.getx())
+	Qy:=NewFPcopy(Q.gety())
+
+	A:=NewECP4()
+	r:=NewFP24int(1)
+
+	A.Copy(P)
+	NP:=NewECP4()
+	NP.Copy(P)
+	NP.neg()
+
+	nb:=n3.nbits()
+
+	for i:=nb-2;i>=1;i-- {
+		r.sqr()
+		lv=line(A,A,Qx,Qy)
+		r.smul(lv,SEXTIC_TWIST)
+		bt:=n3.bit(i)-n.bit(i);
+		if bt==1 {
+			lv=line(A,P,Qx,Qy)
+			r.smul(lv,SEXTIC_TWIST)
+		}	
+		if bt==-1 {
+			//P.neg()
+			lv=line(A,NP,Qx,Qy)
+			r.smul(lv,SEXTIC_TWIST)
+			//P.neg()
+		}		
+	}
+
+	if SIGN_OF_X==NEGATIVEX {
+		r.conj()
+	}
+
+	return r
+}
+
+/* Optimal R-ate double pairing e(P,Q).e(R,S) */
+func Ate2(P1 *ECP4,Q1 *ECP,R1 *ECP4,S1 *ECP) *FP24 {
+	x:=NewBIGints(CURVE_Bnx)
+	n:=NewBIGcopy(x)
+	var lv *FP24
+
+	//n.copy(x); n.norm()
+
+	n3:=NewBIGcopy(n);
+	n3.pmul(3);
+	n3.norm();
+
+	P:=NewECP4(); P.Copy(P1); P.Affine()
+	Q:=NewECP(); Q.Copy(Q1); Q.Affine()
+	R:=NewECP4(); R.Copy(R1); R.Affine()
+	S:=NewECP(); S.Copy(S1); S.Affine()
+
+
+	Qx:=NewFPcopy(Q.getx())
+	Qy:=NewFPcopy(Q.gety())
+	Sx:=NewFPcopy(S.getx())
+	Sy:=NewFPcopy(S.gety())
+
+	A:=NewECP4()
+	B:=NewECP4()
+	r:=NewFP24int(1)
+
+	A.Copy(P)
+	B.Copy(R)
+	NP:=NewECP4()
+	NP.Copy(P)
+	NP.neg()
+	NR:=NewECP4()
+	NR.Copy(R)
+	NR.neg()
+
+
+	nb:=n3.nbits()
+
+	for i:=nb-2;i>=1;i-- {
+		r.sqr()
+		lv=line(A,A,Qx,Qy)
+		r.smul(lv,SEXTIC_TWIST)
+		lv=line(B,B,Sx,Sy)
+		r.smul(lv,SEXTIC_TWIST)
+		bt:=n3.bit(i)-n.bit(i);
+		if bt==1 {
+			lv=line(A,P,Qx,Qy)
+			r.smul(lv,SEXTIC_TWIST)
+			lv=line(B,R,Sx,Sy)
+			r.smul(lv,SEXTIC_TWIST)
+		}
+		if bt==-1 {
+			//P.neg(); 
+			lv=line(A,NP,Qx,Qy)
+			r.smul(lv,SEXTIC_TWIST)
+			//P.neg(); 
+			//R.neg()
+			lv=line(B,NR,Sx,Sy)
+			r.smul(lv,SEXTIC_TWIST)
+			//R.neg()
+		}
+	}
+
+	if SIGN_OF_X==NEGATIVEX {
+		r.conj()
+	}
+
+	return r
+}
+
+/* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */
+func Fexp(m *FP24) *FP24 {
+	f:=NewFP2bigs(NewBIGints(Fra),NewBIGints(Frb))
+	x:=NewBIGints(CURVE_Bnx)
+	r:=NewFP24copy(m)
+		
+/* Easy part of final exp */
+	lv:=NewFP24copy(r)
+
+	lv.Inverse()
+	r.conj()
+
+	r.Mul(lv)
+	lv.Copy(r)
+	r.frob(f,4)
+	r.Mul(lv)
+
+/* Hard part of final exp */	
+// Ghamman & Fouotsa Method
+
+	t7:=NewFP24copy(r); t7.usqr()
+	t1:=t7.Pow(x)
+
+	x.fshr(1)
+	t2:=t1.Pow(x)
+	x.fshl(1)
+
+	if SIGN_OF_X==NEGATIVEX {
+		t1.conj()
+	}
+	t3:=NewFP24copy(t1); t3.conj()
+	t2.Mul(t3)
+	t2.Mul(r)
+
+	t3=t2.Pow(x)
+	t4:=t3.Pow(x)
+	t5:=t4.Pow(x)
+
+	if SIGN_OF_X==NEGATIVEX {
+		t3.conj(); t5.conj()
+	}
+
+	t3.frob(f,6); t4.frob(f,5)
+	t3.Mul(t4);
+
+	t6:=t5.Pow(x)
+	if SIGN_OF_X==NEGATIVEX {
+		t6.conj()
+	}
+
+	t5.frob(f,4)
+	t3.Mul(t5)
+
+	t0:=NewFP24copy(t2); t0.conj()
+	t6.Mul(t0)
+
+	t5.Copy(t6)
+	t5.frob(f,3)
+
+	t3.Mul(t5)
+	t5=t6.Pow(x)
+	t6=t5.Pow(x)
+
+	if SIGN_OF_X==NEGATIVEX {
+		t5.conj()
+	}
+
+	t0.Copy(t5)
+	t0.frob(f,2)
+	t3.Mul(t0)
+	t0.Copy(t6)
+	t0.frob(f,1)
+
+	t3.Mul(t0)
+	t5=t6.Pow(x)
+
+	if SIGN_OF_X==NEGATIVEX {
+		t5.conj()
+	}
+	t2.frob(f,7)
+
+	t5.Mul(t7)
+	t3.Mul(t2)
+	t3.Mul(t5)
+
+	r.Mul(t3)
+	r.reduce();
+
+	return r
+}
+
+/* GLV method */
+func glv(e *BIG) []*BIG {
+	var u []*BIG
+
+	q:=NewBIGints(CURVE_Order)
+	x:=NewBIGints(CURVE_Bnx)
+	x2:=smul(x,x)
+	x=smul(x2,x2)
+	u=append(u,NewBIGcopy(e))
+	u[0].Mod(x)
+	u=append(u,NewBIGcopy(e))
+	u[1].div(x)
+	u[1].rsub(q)
+	return u
+}
+
+/* Galbraith & Scott Method */
+func gs(e *BIG) []*BIG {
+	var u []*BIG
+
+	q:=NewBIGints(CURVE_Order)
+	x:=NewBIGints(CURVE_Bnx)
+	w:=NewBIGcopy(e)
+	for i:=0;i<7;i++ {
+		u=append(u,NewBIGcopy(w))
+		u[i].Mod(x)
+		w.div(x)
+	}
+	u=append(u,NewBIGcopy(w))
+	if SIGN_OF_X==NEGATIVEX {
+		u[1].copy(Modneg(u[1],q));
+		u[3].copy(Modneg(u[3],q));
+		u[5].copy(Modneg(u[5],q));
+		u[7].copy(Modneg(u[7],q));
+
+	}
+
+	return u
+}	
+
+/* Multiply P by e in group G1 */
+func G1mul(P *ECP,e *BIG) *ECP {
+	var R *ECP
+	if (USE_GLV) {
+		//P.Affine()
+		R=NewECP()
+		R.Copy(P)
+		Q:=NewECP()
+		Q.Copy(P); Q.Affine()
+		q:=NewBIGints(CURVE_Order)
+		cru:=NewFPbig(NewBIGints(CURVE_Cru))
+		t:=NewBIGint(0)
+		u:=glv(e)
+		Q.getx().mul(cru)
+
+		np:=u[0].nbits()
+		t.copy(Modneg(u[0],q))
+		nn:=t.nbits()
+		if nn<np {
+			u[0].copy(t)
+			R.neg()
+		}
+
+		np=u[1].nbits()
+		t.copy(Modneg(u[1],q))
+		nn=t.nbits()
+		if nn<np {
+			u[1].copy(t)
+			Q.neg()
+		}
+		u[0].norm()
+		u[1].norm()
+		R=R.Mul2(u[0],Q,u[1])
+			
+	} else {
+		R=P.mul(e)
+	}
+	return R
+}
+
+/* Multiply P by e in group G2 */
+func G2mul(P *ECP4,e *BIG) *ECP4 {
+	var R *ECP4
+	if (USE_GS_G2) {
+		var Q []*ECP4
+
+		F:=ECP4_frob_constants()
+
+		q:=NewBIGints(CURVE_Order)
+		u:=gs(e)
+
+		t:=NewBIGint(0)
+		//P.Affine()
+
+		Q=append(Q,NewECP4());  Q[0].Copy(P);
+		for i:=1;i<8;i++ {
+			Q=append(Q,NewECP4()); Q[i].Copy(Q[i-1])
+			Q[i].frob(F,1)
+		}
+		for i:=0;i<8;i++ {
+			np:=u[i].nbits()
+			t.copy(Modneg(u[i],q))
+			nn:=t.nbits()
+			if nn<np {
+				u[i].copy(t)
+				Q[i].neg()
+			}
+			u[i].norm()
+		}
+
+		R=mul8(Q,u)
+
+	} else {
+		R=P.mul(e)
+	}
+	return R
+}
+
+/* f=f^e */
+/* Note that this method requires a lot of RAM! Better to use compressed XTR method, see FP4.java */
+func GTpow(d *FP24,e *BIG) *FP24 {
+	var r *FP24
+	if USE_GS_GT {
+		var g []*FP24
+		f:=NewFP2bigs(NewBIGints(Fra),NewBIGints(Frb))
+		q:=NewBIGints(CURVE_Order)
+		t:=NewBIGint(0)
+	
+		u:=gs(e)
+
+		g=append(g,NewFP24copy(d))
+		for i:=1;i<8;i++ {
+			g=append(g,NewFP24int(0))
+			g[i].Copy(g[i-1])
+			g[i].frob(f,1)
+		}
+		for i:=0;i<8;i++ {
+			np:=u[i].nbits()
+			t.copy(Modneg(u[i],q))
+			nn:=t.nbits()
+			if nn<np {
+				u[i].copy(t)
+				g[i].conj()
+			}
+			u[i].norm()			
+		}
+		r=pow8(g,u)
+	} else {
+		r=d.Pow(e)
+	}
+	return r
+}
+
+/* test group membership - no longer needed*/
+/* with GT-Strong curve, now only check that m!=1, conj(m)*m==1, and m.m^{p^4}=m^{p^2} */
+/*
+func GTmember(m *FP12) bool {
+	if m.Isunity() {return false}
+	r:=NewFP12copy(m)
+	r.conj()
+	r.Mul(m)
+	if !r.Isunity() {return false}
+
+	f:=NewFP2bigs(NewBIGints(Fra),NewBIGints(Frb))
+
+	r.Copy(m); r.frob(f); r.frob(f)
+	w:=NewFP12copy(r); w.frob(f); w.frob(f)
+	w.Mul(m)
+	if !GT_STRONG {
+		if !w.Equals(r) {return false}
+		x:=NewBIGints(CURVE_Bnx);
+		r.Copy(m); w=r.Pow(x); w=w.Pow(x)
+		r.Copy(w); r.sqr(); r.Mul(w); r.sqr()
+		w.Copy(m); w.frob(f)
+	}
+	return w.Equals(r)
+}
+*/
+/*
+func main() {
+
+	Q:=NewECPbigs(NewBIGints(CURVE_Gx),NewBIGints(CURVE_Gy))
+	P:=NewECP2fp2s(NewFP2bigs(NewBIGints(CURVE_Pxa),NewBIGints(CURVE_Pxb)),NewFP2bigs(NewBIGints(CURVE_Pya),NewBIGints(CURVE_Pyb)))
+
+	//r:=NewBIGints(CURVE_Order)
+	//xa:=NewBIGints(CURVE_Pxa)
+
+	fmt.Printf("P= "+P.ToString())
+	fmt.Printf("\n");
+	fmt.Printf("Q= "+Q.ToString());
+	fmt.Printf("\n");
+
+	//m:=NewBIGint(17)
+
+	e:=Ate(P,Q)
+	e=Fexp(e)
+	for i:=1;i<1000;i++ {
+		e=Ate(P,Q)
+//	fmt.Printf("\ne= "+e.ToString())
+//	fmt.Printf("\n")
+
+		e=Fexp(e)
+	}
+	//	e=GTpow(e,m);
+
+	fmt.Printf("\ne= "+e.ToString())
+	fmt.Printf("\n");
+	GLV:=glv(r)
+
+	fmt.Printf("GLV[0]= "+GLV[0].ToString())
+	fmt.Printf("\n")
+
+	fmt.Printf("GLV[0]= "+GLV[1].ToString())
+	fmt.Printf("\n")
+
+	G:=NewECP(); G.Copy(Q)
+	R:=NewECP2(); R.Copy(P)
+
+
+	e=Ate(R,Q)
+	e=Fexp(e)
+
+	e=GTpow(e,xa)
+	fmt.Printf("\ne= "+e.ToString());
+	fmt.Printf("\n")
+
+	R=G2mul(R,xa)
+	e=Ate(R,G)
+	e=Fexp(e)
+
+	fmt.Printf("\ne= "+e.ToString())
+	fmt.Printf("\n")
+
+	G=G1mul(G,xa)
+	e=Ate(P,G)
+	e=Fexp(e)
+	fmt.Printf("\ne= "+e.ToString())
+	fmt.Printf("\n") 
+}
+*/
diff --git a/version3/go/PAIR256.go b/version3/go/PAIR256.go
new file mode 100644
index 0000000..b5cab24
--- /dev/null
+++ b/version3/go/PAIR256.go
@@ -0,0 +1,563 @@
+/*
+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.
+*/
+
+/* MiotCL BN Curve Pairing functions */
+
+package XXX
+
+//import "fmt"
+
+/* Line function */
+func line(A *ECP8,B *ECP8,Qx *FP,Qy *FP) *FP48 {
+	var a *FP16
+	var b *FP16
+	var c *FP16
+
+	if (A==B) { /* Doubling */
+		XX:=NewFP8copy(A.getx())  //X
+		YY:=NewFP8copy(A.gety())  //Y
+		ZZ:=NewFP8copy(A.getz())  //Z
+		YZ:=NewFP8copy(YY)        //Y 
+		YZ.mul(ZZ)                //YZ
+		XX.sqr()	               //X^2
+		YY.sqr()	               //Y^2
+		ZZ.sqr()			       //Z^2
+			
+		YZ.imul(4)
+		YZ.neg(); YZ.norm()       //-2YZ
+		YZ.tmul(Qy);               //-2YZ.Ys
+
+		XX.imul(6)                //3X^2
+		XX.tmul(Qx);               //3X^2.Xs
+
+		sb:=3*CURVE_B_I
+		ZZ.imul(sb); 	
+		if SEXTIC_TWIST == D_TYPE {	
+			ZZ.div_2i();
+		}
+		if SEXTIC_TWIST == M_TYPE {
+			ZZ.times_i();
+			ZZ.add(ZZ);
+			YZ.times_i();
+			YZ.norm();
+		}
+		ZZ.norm() // 3b.Z^2 
+
+		YY.add(YY)
+		ZZ.sub(YY); ZZ.norm()     // 3b.Z^2-Y^2
+
+		a=NewFP16fp8s(YZ,ZZ);          // -2YZ.Ys | 3b.Z^2-Y^2 | 3X^2.Xs 
+		if SEXTIC_TWIST == D_TYPE {	
+
+			b=NewFP16fp8(XX)             // L(0,1) | L(0,0) | L(1,0)
+			c=NewFP16int(0)
+		}
+		if SEXTIC_TWIST == M_TYPE {
+			b=NewFP16int(0)
+			c=NewFP16fp8(XX); c.times_i()
+		}
+		A.dbl();
+
+	} else { /* Addition */
+
+		X1:=NewFP8copy(A.getx())    // X1
+		Y1:=NewFP8copy(A.gety())    // Y1
+		T1:=NewFP8copy(A.getz())    // Z1
+		T2:=NewFP8copy(A.getz())    // Z1
+			
+		T1.mul(B.gety())    // T1=Z1.Y2 
+		T2.mul(B.getx())    // T2=Z1.X2
+
+		X1.sub(T2); X1.norm()  // X1=X1-Z1.X2
+		Y1.sub(T1); Y1.norm()  // Y1=Y1-Z1.Y2
+
+		T1.copy(X1)            // T1=X1-Z1.X2
+		X1.tmul(Qy)            // X1=(X1-Z1.X2).Ys
+
+		if SEXTIC_TWIST == M_TYPE {
+			X1.times_i()
+			X1.norm()
+		}
+
+		T1.mul(B.gety())       // T1=(X1-Z1.X2).Y2
+
+		T2.copy(Y1)           // T2=Y1-Z1.Y2
+		T2.mul(B.getx())       // T2=(Y1-Z1.Y2).X2
+		T2.sub(T1); T2.norm()          // T2=(Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2
+		Y1.tmul(Qx);  Y1.neg(); Y1.norm() // Y1=-(Y1-Z1.Y2).Xs
+
+		a=NewFP16fp8s(X1,T2)       // (X1-Z1.X2).Ys  |  (Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2  | - (Y1-Z1.Y2).Xs
+		if SEXTIC_TWIST == D_TYPE {
+			b=NewFP16fp8(Y1)
+			c=NewFP16int(0)
+		}
+		if SEXTIC_TWIST == M_TYPE {
+			b=NewFP16int(0)
+			c=NewFP16fp8(Y1); c.times_i()
+		}
+		A.Add(B);
+	}
+
+	return NewFP48fp16s(a,b,c)
+}
+
+/* Optimal R-ate pairing */
+func Ate(P1 *ECP8,Q1 *ECP) *FP48 {
+	x:=NewBIGints(CURVE_Bnx)
+	n:=NewBIGcopy(x)
+	var lv *FP48
+	
+	//n.copy(x); n.norm()
+
+	n3:=NewBIGcopy(n);
+	n3.pmul(3);
+	n3.norm();
+
+	P:=NewECP8(); P.Copy(P1); P.Affine()
+	Q:=NewECP(); Q.Copy(Q1); Q.Affine()
+
+	Qx:=NewFPcopy(Q.getx())
+	Qy:=NewFPcopy(Q.gety())
+
+	A:=NewECP8()
+	r:=NewFP48int(1)
+
+	A.Copy(P)
+	NP:=NewECP8()
+	NP.Copy(P)
+	NP.neg()
+
+	nb:=n3.nbits()
+
+	for i:=nb-2;i>=1;i-- {
+		r.sqr()
+		lv=line(A,A,Qx,Qy)
+		r.smul(lv,SEXTIC_TWIST)
+		bt:=n3.bit(i)-n.bit(i);
+		if bt==1 {
+			lv=line(A,P,Qx,Qy)
+			r.smul(lv,SEXTIC_TWIST)
+		}	
+		if bt==-1 {
+			//P.neg()
+			lv=line(A,NP,Qx,Qy)
+			r.smul(lv,SEXTIC_TWIST)
+			//P.neg()
+		}		
+	}
+
+	if SIGN_OF_X==NEGATIVEX {
+		r.conj()
+	}
+
+	return r
+}
+
+/* Optimal R-ate double pairing e(P,Q).e(R,S) */
+func Ate2(P1 *ECP8,Q1 *ECP,R1 *ECP8,S1 *ECP) *FP48 {
+	x:=NewBIGints(CURVE_Bnx)
+	n:=NewBIGcopy(x)
+	var lv *FP48
+
+	//n.copy(x); n.norm()
+
+	n3:=NewBIGcopy(n);
+	n3.pmul(3);
+	n3.norm();
+
+	P:=NewECP8(); P.Copy(P1); P.Affine()
+	Q:=NewECP(); Q.Copy(Q1); Q.Affine()
+	R:=NewECP8(); R.Copy(R1); R.Affine()
+	S:=NewECP(); S.Copy(S1); S.Affine()
+
+
+	Qx:=NewFPcopy(Q.getx())
+	Qy:=NewFPcopy(Q.gety())
+	Sx:=NewFPcopy(S.getx())
+	Sy:=NewFPcopy(S.gety())
+
+	A:=NewECP8()
+	B:=NewECP8()
+	r:=NewFP48int(1)
+
+	A.Copy(P)
+	B.Copy(R)
+	NP:=NewECP8()
+	NP.Copy(P)
+	NP.neg()
+	NR:=NewECP8()
+	NR.Copy(R)
+	NR.neg()
+
+
+	nb:=n3.nbits()
+
+	for i:=nb-2;i>=1;i-- {
+		r.sqr()
+		lv=line(A,A,Qx,Qy)
+		r.smul(lv,SEXTIC_TWIST)
+		lv=line(B,B,Sx,Sy)
+		r.smul(lv,SEXTIC_TWIST)
+		bt:=n3.bit(i)-n.bit(i);
+		if bt==1 {
+			lv=line(A,P,Qx,Qy)
+			r.smul(lv,SEXTIC_TWIST)
+			lv=line(B,R,Sx,Sy)
+			r.smul(lv,SEXTIC_TWIST)
+		}
+		if bt==-1 {
+			//P.neg(); 
+			lv=line(A,NP,Qx,Qy)
+			r.smul(lv,SEXTIC_TWIST)
+			//P.neg(); 
+			//R.neg()
+			lv=line(B,NR,Sx,Sy)
+			r.smul(lv,SEXTIC_TWIST)
+			//R.neg()
+		}
+	}
+
+	if SIGN_OF_X==NEGATIVEX {
+		r.conj()
+	}
+
+	return r
+}
+
+/* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */
+func Fexp(m *FP48) *FP48 {
+	f:=NewFP2bigs(NewBIGints(Fra),NewBIGints(Frb))
+	x:=NewBIGints(CURVE_Bnx)
+	r:=NewFP48copy(m)
+		
+/* Easy part of final exp */
+	lv:=NewFP48copy(r)
+
+	lv.Inverse()
+	r.conj()
+
+	r.Mul(lv)
+	lv.Copy(r)
+	r.frob(f,8)
+	r.Mul(lv)
+
+/* Hard part of final exp */	
+// Ghamman & Fouotsa Method
+
+	t7:=NewFP48copy(r); t7.usqr()
+	t1:=t7.Pow(x)
+
+	x.fshr(1)
+	t2:=t1.Pow(x)
+	x.fshl(1)
+
+	if SIGN_OF_X==NEGATIVEX {
+		t1.conj()
+	}
+
+	t3:=NewFP48copy(t1); t3.conj()
+	t2.Mul(t3)
+	t2.Mul(r)
+
+	r.Mul(t7)
+
+	t1=t2.Pow(x)
+	if SIGN_OF_X==NEGATIVEX {
+		t1.conj()
+	}
+	t3.Copy(t1)
+	t3.frob(f,14)
+	r.Mul(t3)
+	t1=t1.Pow(x)
+	if SIGN_OF_X==NEGATIVEX {
+		t1.conj()
+	}
+
+	t3.Copy(t1)
+	t3.frob(f,13)
+	r.Mul(t3)
+	t1=t1.Pow(x)
+	if SIGN_OF_X==NEGATIVEX {
+		t1.conj()
+	}
+
+	t3.Copy(t1)
+	t3.frob(f,12)
+	r.Mul(t3)
+	t1=t1.Pow(x)
+	if SIGN_OF_X==NEGATIVEX {
+		t1.conj()
+	}
+
+	t3.Copy(t1)
+	t3.frob(f,11)
+	r.Mul(t3)
+	t1=t1.Pow(x)
+	if SIGN_OF_X==NEGATIVEX {
+		t1.conj()
+	}
+
+	t3.Copy(t1)
+	t3.frob(f,10)
+	r.Mul(t3)
+	t1=t1.Pow(x)
+	if SIGN_OF_X==NEGATIVEX {
+		t1.conj()
+	}
+
+	t3.Copy(t1)
+	t3.frob(f,9)
+	r.Mul(t3)
+	t1=t1.Pow(x)
+	if SIGN_OF_X==NEGATIVEX {
+		t1.conj()
+	}
+
+	t3.Copy(t1)
+	t3.frob(f,8)
+	r.Mul(t3)
+	t1=t1.Pow(x)
+	if SIGN_OF_X==NEGATIVEX {
+		t1.conj()
+	}
+
+	t3.Copy(t2); t3.conj()
+	t1.Mul(t3)
+	t3.Copy(t1);
+	t3.frob(f,7)
+	r.Mul(t3)
+	t1=t1.Pow(x)
+	if SIGN_OF_X==NEGATIVEX {
+		t1.conj()
+	}
+
+	t3.Copy(t1)
+	t3.frob(f,6)
+	r.Mul(t3)
+	t1=t1.Pow(x)
+	if SIGN_OF_X==NEGATIVEX {
+		t1.conj()
+	}
+
+	t3.Copy(t1)
+	t3.frob(f,5)
+	r.Mul(t3)
+	t1=t1.Pow(x)
+	if SIGN_OF_X==NEGATIVEX {
+		t1.conj()
+	}
+
+	t3.Copy(t1)
+	t3.frob(f,4)
+	r.Mul(t3)
+	t1=t1.Pow(x)
+	if SIGN_OF_X==NEGATIVEX {
+		t1.conj()
+	}
+
+	t3.Copy(t1)
+	t3.frob(f,3)
+	r.Mul(t3)
+	t1=t1.Pow(x)
+	if SIGN_OF_X==NEGATIVEX {
+		t1.conj()
+	}
+
+	t3.Copy(t1)
+	t3.frob(f,2)
+	r.Mul(t3)
+	t1=t1.Pow(x)
+	if SIGN_OF_X==NEGATIVEX {
+		t1.conj()
+	}
+
+	t3.Copy(t1)
+	t3.frob(f,1)
+	r.Mul(t3)
+	t1=t1.Pow(x)
+	if SIGN_OF_X==NEGATIVEX {
+		t1.conj()
+	}
+	
+	r.Mul(t1)
+	t2.frob(f,15)
+	r.Mul(t2)
+
+	r.reduce();
+
+	return r
+}
+
+/* GLV method */
+func glv(e *BIG) []*BIG {
+	var u []*BIG
+
+	q:=NewBIGints(CURVE_Order)
+	x:=NewBIGints(CURVE_Bnx)
+	x2:=smul(x,x)
+	x=smul(x2,x2)
+	x2=smul(x,x)
+	u=append(u,NewBIGcopy(e))
+	u[0].Mod(x2)
+	u=append(u,NewBIGcopy(e))
+	u[1].div(x2)
+	u[1].rsub(q)
+	return u
+}
+
+/* Galbraith & Scott Method */
+func gs(e *BIG) []*BIG {
+	var u []*BIG
+
+	q:=NewBIGints(CURVE_Order)
+	x:=NewBIGints(CURVE_Bnx)
+	w:=NewBIGcopy(e)
+	for i:=0;i<15;i++ {
+		u=append(u,NewBIGcopy(w))
+		u[i].Mod(x)
+		w.div(x)
+	}
+	u=append(u,NewBIGcopy(w))
+	if SIGN_OF_X==NEGATIVEX {
+		u[1].copy(Modneg(u[1],q));
+		u[3].copy(Modneg(u[3],q));
+		u[5].copy(Modneg(u[5],q));
+		u[7].copy(Modneg(u[7],q));
+		u[9].copy(Modneg(u[9],q));
+		u[11].copy(Modneg(u[11],q));
+		u[13].copy(Modneg(u[13],q));
+		u[15].copy(Modneg(u[15],q));
+	}
+
+	return u
+}
+
+/* Multiply P by e in group G1 */
+func G1mul(P *ECP,e *BIG) *ECP {
+	var R *ECP
+	if (USE_GLV) {
+		//P.Affine()
+		R=NewECP()
+		R.Copy(P)
+		Q:=NewECP()
+		Q.Copy(P); Q.Affine()
+		q:=NewBIGints(CURVE_Order)
+		cru:=NewFPbig(NewBIGints(CURVE_Cru))
+		t:=NewBIGint(0)
+		u:=glv(e)
+		Q.getx().mul(cru)
+
+		np:=u[0].nbits()
+		t.copy(Modneg(u[0],q))
+		nn:=t.nbits()
+		if nn<np {
+			u[0].copy(t)
+			R.neg()
+		}
+
+		np=u[1].nbits()
+		t.copy(Modneg(u[1],q))
+		nn=t.nbits()
+		if nn<np {
+			u[1].copy(t)
+			Q.neg()
+		}
+		u[0].norm()
+		u[1].norm()
+		R=R.Mul2(u[0],Q,u[1])
+			
+	} else {
+		R=P.mul(e)
+	}
+	return R
+}
+
+/* Multiply P by e in group G2 */
+func G2mul(P *ECP8,e *BIG) *ECP8 {
+	var R *ECP8
+	if (USE_GS_G2) {
+		var Q []*ECP8
+
+		F:=ECP8_frob_constants()
+
+		q:=NewBIGints(CURVE_Order)
+		u:=gs(e)
+
+		t:=NewBIGint(0)
+		//P.Affine()
+
+		Q=append(Q,NewECP8());  Q[0].Copy(P);
+		for i:=1;i<16;i++ {
+			Q=append(Q,NewECP8()); Q[i].Copy(Q[i-1])
+			Q[i].frob(F,1)
+		}
+		for i:=0;i<16;i++ {
+			np:=u[i].nbits()
+			t.copy(Modneg(u[i],q))
+			nn:=t.nbits()
+			if nn<np {
+				u[i].copy(t)
+				Q[i].neg()
+			}
+			u[i].norm()
+		}
+
+		R=mul16(Q,u)
+
+	} else {
+		R=P.mul(e)
+	}
+	return R
+}
+
+/* f=f^e */
+/* Note that this method requires a lot of RAM! Better to use compressed XTR method, see FP4.java */
+func GTpow(d *FP48,e *BIG) *FP48 {
+	var r *FP48
+	if USE_GS_GT {
+		var g []*FP48
+		f:=NewFP2bigs(NewBIGints(Fra),NewBIGints(Frb))
+		q:=NewBIGints(CURVE_Order)
+		t:=NewBIGint(0)
+	
+		u:=gs(e)
+
+		g=append(g,NewFP48copy(d))
+		for i:=1;i<16;i++ {
+			g=append(g,NewFP48int(0))
+			g[i].Copy(g[i-1])
+			g[i].frob(f,1)
+		}
+		for i:=0;i<16;i++ {
+			np:=u[i].nbits()
+			t.copy(Modneg(u[i],q))
+			nn:=t.nbits()
+			if nn<np {
+				u[i].copy(t)
+				g[i].conj()
+			}
+			u[i].norm()			
+		}
+		r=pow16(g,u)
+	} else {
+		r=d.Pow(e)
+	}
+	return r
+}
+
diff --git a/version3/go/RAND.go b/version3/go/RAND.go
new file mode 100644
index 0000000..343fd7e
--- /dev/null
+++ b/version3/go/RAND.go
@@ -0,0 +1,153 @@
+/*
+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.
+*/
+
+/*
+ *   Cryptographic strong random number generator 
+ *
+ *   Unguessable seed -> SHA -> PRNG internal state -> SHA -> random numbers
+ *   Slow - but secure
+ *
+ *   See ftp://ftp.rsasecurity.com/pub/pdfs/bull-1.pdf for a justification
+ */
+
+/* Marsaglia & Zaman Random number generator constants */
+
+
+package amcl
+
+//import "fmt"
+
+const rand_NK int=21
+const rand_NJ int=6
+const rand_NV int=8
+
+type RAND struct {
+	ira [rand_NK]uint32  /* random number...   */
+	rndptr int
+	borrow uint32
+	pool_ptr int
+	pool [32]byte
+}
+
+/* Terminate and clean up */
+func (R *RAND) Clean() { /* kill internal state */
+	R.pool_ptr=0; R.rndptr=0;
+	for i:=0;i<32;i++ {R.pool[i]=0}
+	for i:=0;i<rand_NK;i++ {R.ira[i]=0}
+	R.borrow=0;
+}
+
+func NewRAND() *RAND {
+	R:=new(RAND)
+	R.Clean()
+	return R
+}
+
+func (R *RAND) sbrand() uint32 { /* Marsaglia & Zaman random number generator */
+	R.rndptr++
+	if R.rndptr<rand_NK {return R.ira[R.rndptr]}
+	R.rndptr=0
+	k:=rand_NK-rand_NJ
+	for i:=0;i<rand_NK;i++{ /* calculate next NK values */
+		if k==rand_NK {k=0}
+		t:=R.ira[k]
+		pdiff:=t-R.ira[i]-R.borrow
+		if pdiff<t {R.borrow=0}
+		if pdiff>t {R.borrow=1}
+		R.ira[i]=pdiff 
+		k++
+	}
+
+	return R.ira[0];
+}
+
+func (R *RAND) sirand(seed uint32) {
+	var m uint32=1;
+	R.borrow=0
+	R.rndptr=0
+	R.ira[0]^=seed;
+	for i:=1;i<rand_NK;i++ { /* fill initialisation vector */
+		in:=(rand_NV*i)%rand_NK;
+		R.ira[in]^=m;      /* note XOR */
+		t:=m
+		m=seed-m
+		seed=t
+	}
+	for i:=0;i<10000;i++ {R.sbrand()} /* "warm-up" & stir the generator */
+}
+
+func (R *RAND) fill_pool() {
+	sh:=NewHASH256()
+	for i:=0;i<128;i++ {sh.Process(byte(R.sbrand()&0xff))}
+	W:=sh.Hash()
+	for i:=0;i<32;i++ {R.pool[i]=W[i]}
+	R.pool_ptr=0;
+}
+
+func pack(b [4]byte) uint32 { /* pack 4 bytes into a 32-bit Word */
+	return (((uint32(b[3]))&0xff)<<24)|((uint32(b[2])&0xff)<<16)|((uint32(b[1])&0xff)<<8)|(uint32(b[0])&0xff)
+}
+
+/* Initialize RNG with some real entropy from some external source */
+func (R *RAND) Seed(rawlen int,raw []byte) { /* initialise from at least 128 byte string of raw random entropy */
+	var b [4]byte
+	sh:=NewHASH256()
+	R.pool_ptr=0;
+
+	for i:=0;i<rand_NK;i++ {R.ira[i]=0}
+	if rawlen>0 {
+		for i:=0;i<rawlen;i++ {
+			sh.Process(raw[i])
+		}
+		digest:=sh.Hash()
+
+/* initialise PRNG from distilled randomness */
+
+		for i:=0;i<8;i++  {
+			b[0]=digest[4*i]; b[1]=digest[4*i+1]; b[2]=digest[4*i+2]; b[3]=digest[4*i+3]
+			R.sirand(pack(b))
+		}
+	}
+	R.fill_pool()
+}
+
+/* get random byte */
+func (R *RAND) GetByte() byte { 
+	r:=R.pool[R.pool_ptr]
+	R.pool_ptr++
+	if R.pool_ptr>=32 {R.fill_pool()}
+	return byte(r&0xff)
+}
+
+/* test main program */
+/*
+func main() {
+	var raw [100]byte
+	rng:=NewRAND()
+
+	rng.Clean()
+	for i:=0;i<100;i++ {raw[i]=byte(i)}
+
+	rng.Seed(100,raw[:])
+ 
+	for i:=0;i<1000;i++ {
+		fmt.Printf("%03d ",rng.GetByte())
+	}
+}
+*/
diff --git a/version3/go/ROM_ANSSI_32.go b/version3/go/ROM_ANSSI_32.go
new file mode 100644
index 0000000..611d869
--- /dev/null
+++ b/version3/go/ROM_ANSSI_32.go
@@ -0,0 +1,36 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package ANSSI
+
+// Base Bits= 28
+var Modulus= [...]Chunk {0x86E9C03,0xFCF353D,0x8CA6DE8,0xADBCABC,0x35B3961,0xE8CE424,0xF10126D,0xB3AD58,0x1FD178C,0xF}
+var R2modp= [...]Chunk {0x288CC9C,0x18D2374,0x646BD2B,0x4929E67,0xD6F7F2D,0x220E6C1,0xABCE02E,0x751B1FD,0x7401B78,0xE}
+const MConst Chunk=0x64E1155
+
+const CURVE_Cof_I int= 1
+var CURVE_Cof=[...]Chunk {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+const CURVE_A int= -3
+const CURVE_B_I int= 0
+var CURVE_B= [...]Chunk {0xB7BB73F,0x75ED967,0x1A18030,0xC9AE4B,0xFDFEC,0x754A44C,0xD4ABA,0x5428A93,0xE353FCA,0xE}
+var CURVE_Order= [...]Chunk {0x6D655E1,0xFDD459C,0x2BF941F,0x67E140D,0x35B53DC,0xE8CE424,0xF10126D,0xB3AD58,0x1FD178C,0xF}
+var CURVE_Gx= [...]Chunk {0x98F5CFF,0xC97A2DD,0x8B70164,0xD2DCAF9,0x3958C27,0x4749D42,0xB31183D,0x56C139E,0x6B3D4C3,0xB}
+var CURVE_Gy= [...]Chunk {0x4062CFB,0x115A155,0x4C9E183,0xC307E8E,0xF8C2701,0xF0F3ECE,0x11F9271,0xC8B2049,0x142E0F7,0x6}
diff --git a/version3/go/ROM_ANSSI_64.go b/version3/go/ROM_ANSSI_64.go
new file mode 100644
index 0000000..0ad448b
--- /dev/null
+++ b/version3/go/ROM_ANSSI_64.go
@@ -0,0 +1,36 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package ANSSI
+
+// Base Bits= 56
+var Modulus= [...]Chunk {0xFCF353D86E9C03,0xADBCABC8CA6DE8,0xE8CE42435B3961,0xB3AD58F10126D,0xF1FD178C}
+var R2modp= [...]Chunk {0x18D2374288CC9C,0x4929E67646BD2B,0x220E6C1D6F7F2D,0x751B1FDABCE02E,0xE7401B78}
+const MConst Chunk=0x97483A164E1155
+
+const CURVE_Cof_I int= 1
+var CURVE_Cof=[...]Chunk {0x1,0x0,0x0,0x0,0x0}
+const CURVE_A int= -3
+const CURVE_B_I int= 0
+var CURVE_B= [...]Chunk {0x75ED967B7BB73F,0xC9AE4B1A18030,0x754A44C00FDFEC,0x5428A9300D4ABA,0xEE353FCA}
+var CURVE_Order= [...]Chunk {0xFDD459C6D655E1,0x67E140D2BF941F,0xE8CE42435B53DC,0xB3AD58F10126D,0xF1FD178C}
+var CURVE_Gx= [...]Chunk {0xC97A2DD98F5CFF,0xD2DCAF98B70164,0x4749D423958C27,0x56C139EB31183D,0xB6B3D4C3}
+var CURVE_Gy= [...]Chunk {0x115A1554062CFB,0xC307E8E4C9E183,0xF0F3ECEF8C2701,0xC8B204911F9271,0x6142E0F7}
diff --git a/version3/go/ROM_BLS24_32.go b/version3/go/ROM_BLS24_32.go
new file mode 100644
index 0000000..061c0a2
--- /dev/null
+++ b/version3/go/ROM_BLS24_32.go
@@ -0,0 +1,58 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package BLS24
+
+// Base Bits= 29
+var Modulus= [...]Chunk {0xA06152B,0x2260B3A,0xB4C36BE,0x5FFC5D0,0xBDB6A64,0x5B78E2E,0x1C1A28CA,0x10E6441B,0x1F244061,0xB4704F0,0x141E5CCD,0x9837504,0x3F2E77E,0xD763740,0x1316EA0E,0xF0079,0x555C}
+var R2modp= [...]Chunk {0x8533EA9,0x6A02789,0x183B24DE,0x1E45ECF8,0xC8F8F37,0x10CAD209,0x4C0C4B8,0x9B1FABD,0xDEBE4C0,0xDC353F9,0x18A18E26,0x10F489BB,0x31206A5,0x19673BBF,0x6BE69F9,0xB091169,0x9CD}
+const MConst Chunk=0x95FE7D
+var Fra= [...]Chunk {0x1BF96F1D,0xAE53A55,0x31BFEEB,0x183FF17A,0x6237469,0x12A4F4F1,0x12101FE3,0x16E79D94,0xFF59267,0x5EB4EB4,0x78CC49F,0x274BA33,0x149184F3,0x16C6DCBA,0x1C90B694,0x10F729CE,0x4BBC}
+var Frb= [...]Chunk {0xE0CA60E,0x1740D0E4,0x83037D2,0xDBFD456,0x5B7F5FA,0x1312993D,0xA0A08E6,0x19FEA687,0xF2EADF9,0x55BB63C,0xC91982E,0x70EBAD1,0xF61628B,0x16AF5A85,0x16863379,0xF17D6AA,0x99F}
+
+const CURVE_Cof_I int= 0
+const CURVE_A int= 0
+const CURVE_B_I int= 19
+var CURVE_B= [...]Chunk {0x13,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Order= [...]Chunk {0x10000001,0xD047FF,0x1FD54464,0x1E3CE067,0xE322DDA,0x1D356F3F,0x7433B44,0x49091F9,0x1729CC2,0x250286C,0x16E62ED,0xB403E1E,0x1001000,0x80,0x0,0x0,0x0}
+var CURVE_Gx= [...]Chunk {0xBE3CCD4,0x33B07AF,0x1B67D159,0x3DFC5B5,0xEBA1FCC,0x1A3C1F84,0x56BE204,0xEF8DF1B,0x11AE2D84,0x5FEE546,0x161B3BF9,0x183B20EE,0x1EA5D99B,0x14F0C5BF,0xBE521B7,0x17C682F9,0x1AB2}
+var CURVE_Gy= [...]Chunk {0x121E5245,0x65D2E56,0x11577DB1,0x16DACC11,0x14F39746,0x459F694,0x12483FCF,0xC828B04,0xFD63E5A,0x7B1D52,0xAFDE738,0xF349254,0x1A4529FF,0x10E53353,0xF91DEE1,0x16E18D8A,0x47FC}
+
+var CURVE_Bnx= [...]Chunk {0x11FF80,0x80010,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Cof= [...]Chunk {0x19F415AB,0x1E0FFDFF,0x15AAADFF,0xAA,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Cru= [...]Chunk {0xDD794A9,0x1DE138A3,0x2BCCE90,0xC746127,0x15223DDC,0x1DD8890B,0xED08DB7,0xE24B9F,0xE379CE6,0x37011AC,0x11BAC820,0x1EEFAD01,0x200860F,0x147218A6,0xF16A209,0xF0079,0x555C}
+var CURVE_Pxaa= [...]Chunk {0x14E24678,0x1F149A9B,0x9609022,0x1C186868,0xCDEFC69,0x1C87BB2E,0x14A2235F,0x7586755,0x5896747,0x159BFE92,0x3B5572E,0x1710A521,0x71EB14A,0xC643C33,0x12581DE5,0x1BCA747D,0x959}
+var CURVE_Pxab= [...]Chunk {0x1FB099B8,0x3FCF5D7,0x4A91C0E,0xC6EEB40,0x11FC2385,0x11B5AE8D,0x1A9CC3E7,0x194FE144,0x185DB2A5,0x930E1C7,0x14F85F9A,0x1F2ED4E,0x1D1BE5AD,0xF26169C,0xCF7F194,0x1DA1062E,0x3B0D}
+var CURVE_Pxba= [...]Chunk {0x11AD15D3,0xD0E6F38,0x17DB85BB,0x30A62F1,0x1EA3E09A,0x17B25FA1,0x1B7959AC,0x1165B19A,0x6C74FDB,0x18F790E1,0x12278FDA,0x1E008F79,0x103F329,0x14619FF1,0x1EBCAA8,0xFF5A9CA,0x3EC2}
+var CURVE_Pxbb= [...]Chunk {0x1EE0F480,0x3D5943A,0xF5B12E3,0x128AADC8,0x180E1CB9,0x1EFD916F,0x48BC7F,0x1D5EE1FA,0x5698EF5,0x11D6AED9,0x1386BC6E,0x196E900B,0x1CE2E465,0xC2A8ED3,0x1E67DF99,0x71B7940,0xA5B}
+var CURVE_Pyaa= [...]Chunk {0x14781AA0,0xC324C98,0xEDC2AC,0x16C13B46,0x145FC44B,0x12529530,0x1310A8C4,0x1768C5C0,0xE19AE68,0x56E1C1D,0x13DAF93F,0x17E94366,0xF901AD0,0x76800CC,0x10250D8B,0x1E6BAE6D,0x5057}
+var CURVE_Pyab= [...]Chunk {0xEAE08FA,0xDDF62BF,0xA97E5AB,0xF0EE97,0x99A42CA,0x1C326578,0xF33DC11,0x8B913F7,0xFEF8552,0x19F35B90,0x58DDBDE,0xFC32FF2,0x1587B5DF,0xB5EB07A,0x1A258DE0,0x1692CC3D,0x2CE2}
+var CURVE_Pyba= [...]Chunk {0x5F0CC41,0xB9813B5,0x14C2A87D,0xFF1264A,0x19AF8A14,0x6CE6C3,0x2A7F8A2,0x121DCA7D,0x7D37153,0x19D21078,0x15466DC7,0x1362982B,0x1DD3CB5B,0x1CFC0D1C,0x18C69AF8,0x8CC7DC,0x1807}
+var CURVE_Pybb= [...]Chunk {0x115C1CAE,0x78D9732,0x16C26237,0x5A81A6A,0x1C38A777,0x56121FE,0x4DAD9D7,0x1BEBA670,0xA1D72FC,0xD60B274,0x19734258,0x1D621775,0x4691771,0x14206B68,0x17B22DE4,0x29D5B37,0x499D}
+var CURVE_W=[2][17]Chunk {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}
+var CURVE_SB=[2][2][17]Chunk {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}}
+var CURVE_WB=[4][17]Chunk {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}
+var CURVE_BB=[4][4][17]Chunk {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}}
+
+const USE_GLV bool=true
+const USE_GS_G2 bool=true
+const USE_GS_GT bool=true	
+const GT_STRONG bool=false
\ No newline at end of file
diff --git a/version3/go/ROM_BLS24_64.go b/version3/go/ROM_BLS24_64.go
new file mode 100644
index 0000000..7b566c0
--- /dev/null
+++ b/version3/go/ROM_BLS24_64.go
@@ -0,0 +1,58 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package BLS24
+
+// Base Bits= 56
+var Modulus= [...]Chunk {0x44C1674A06152B,0xFFE2E82D30DAF8,0x6F1C5CBDB6A642,0x3220DF068A328B,0xE09E1F24406187,0xBA825079733568,0x6E803F2E77E4C1,0x3CCC5BA839AEC,0x555C0078}
+var R2modp= [...]Chunk {0x6A4A1FE013DF5B,0xE8E46D4D1BDE65,0x1F841391F45C67,0x9148A4516FB28,0x4398524EDF4C88,0x41C0E241B6DCE8,0xE42C208C19411,0xA7FE6FD73A7B1C,0xFCCCA76}
+const MConst Chunk=0xBD5D7D8095FE7D
+var Fra= [...]Chunk {0x5CA74ABBF96F1D,0x1FF8BD0C6FFBAD,0x49E9E26237469C,0x3CECA48407F8E5,0x69D68FF59267B7,0x5D199E33127CBD,0xB97549184F313A,0x4E77242DA52D8D,0x4BBC87B9}
+var Frb= [...]Chunk {0xE81A1C8E0CA60E,0xDFEA2B20C0DF4A,0x25327A5B7F5FA6,0xF5343A828239A6,0x76C78F2EADF9CF,0x5D68B24660B8AB,0xB50AF61628B387,0xB555A18CDE6D5E,0x99F78BE}
+
+const CURVE_Cof_I int= 0
+const CURVE_A int= 0
+const CURVE_B_I int= 19
+var CURVE_B= [...]Chunk {0x13,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Order= [...]Chunk {0x1A08FFF0000001,0x1E7033FF551190,0x6ADE7EE322DDAF,0x848FC9D0CED13A,0x50D81729CC224,0x1F0F05B98BB44A,0x10010010005A0,0x0,0x0}
+var CURVE_Gx= [...]Chunk {0x6760F5EBE3CCD4,0xEFE2DAED9F4564,0x783F08EBA1FCC1,0xC6F8D95AF88134,0xDCA8D1AE2D8477,0x9077586CEFE4BF,0x8B7FEA5D99BC1D,0x17CAF9486DE9E1,0x1AB2BE34}
+var CURVE_Gy= [...]Chunk {0xCBA5CAD21E5245,0x6D6608C55DF6C4,0xB3ED294F39746B,0x145824920FF3C8,0x63AA4FD63E5A64,0x492A2BF79CE00F,0x66A7A4529FF79A,0x6C53E477B861CA,0x47FCB70C}
+
+var CURVE_Bnx= [...]Chunk {0x100020011FF80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Cof= [...]Chunk {0xC1FFBFF9F415AB,0x5556AAB7FF,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Cru= [...]Chunk {0xBC27146DD794A9,0x3A30938AF33A43,0xB112175223DDC6,0x125CFBB4236DFB,0x2358E379CE607,0xD680C6EB20806E,0x314C200860FF77,0x3CBC5A88268E4,0x555C0078}
+var CURVE_Pxaa= [...]Chunk {0xE2935374E24678,0xC34342582408B,0xF765CCDEFC69E,0xC33AAD2888D7F9,0x7FD2458967473A,0x52908ED55CBAB3,0x786671EB14AB88,0xA3EC96077958C8,0x959DE53}
+var CURVE_Pxab= [...]Chunk {0x7F9EBAFFB099B8,0x3775A012A47038,0x6B5D1B1FC23856,0x7F0A26A730F9E3,0x1C38F85DB2A5CA,0x76A753E17E6926,0x2D39D1BE5AD0F9,0x31733DFC651E4C,0x3B0DED08}
+var CURVE_Pxba= [...]Chunk {0xA1CDE711AD15D3,0x853178DF6E16ED,0x64BF43EA3E09A1,0x2D8CD6DE566B2F,0xF21C26C74FDB8B,0x47BCC89E3F6B1E,0x3FE2103F329F00,0x4E507AF2AA28C3,0x3EC27FAD}
+var CURVE_Pxbb= [...]Chunk {0x7AB2875EE0F480,0x4556E43D6C4B8C,0xFB22DF80E1CB99,0xF70FD0122F1FFD,0xD5DB25698EF5EA,0x4805CE1AF1BA3A,0x1DA7CE2E465CB7,0xCA0799F7E65855,0xA5B38DB}
+var CURVE_Pyaa= [...]Chunk {0x86499314781AA0,0x609DA303B70AB1,0xA52A6145FC44BB,0x462E04C42A3124,0xC383AE19AE68BB,0xA1B34F6BE4FCAD,0x198F901AD0BF4,0x736C094362CED0,0x5057F35D}
+var CURVE_Pyab= [...]Chunk {0xBBEC57EEAE08FA,0x78774BAA5F96AD,0x64CAF099A42CA0,0xC89FBBCCF70478,0x6B720FEF855245,0x97F916376F7B3E,0x60F5587B5DF7E1,0x61EE89637816BD,0x2CE2B496}
+var CURVE_Pyba= [...]Chunk {0x730276A5F0CC41,0xF89325530AA1F5,0xD9CD879AF8A147,0xEE53E8A9FE2880,0x420F07D3715390,0x4C15D519B71F3A,0x1A39DD3CB5B9B1,0x3EE631A6BE39F8,0x18070466}
+var CURVE_Pybb= [...]Chunk {0xF1B2E6515C1CAE,0xD40D355B0988DC,0xC243FDC38A7772,0x5D338136B675CA,0x164E8A1D72FCDF,0xBBAE5CD0961AC,0xD6D04691771EB1,0xD9BDEC8B792840,0x499D14EA}
+var CURVE_W=[2][9]Chunk {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}
+var CURVE_SB=[2][2][9]Chunk {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}}
+var CURVE_WB=[4][9]Chunk {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}
+var CURVE_BB=[4][4][9]Chunk {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}}
+
+const USE_GLV bool=true
+const USE_GS_G2 bool=true
+const USE_GS_GT bool=true	
+const GT_STRONG bool=false
\ No newline at end of file
diff --git a/version3/go/ROM_BLS381_32.go b/version3/go/ROM_BLS381_32.go
new file mode 100644
index 0000000..322c179
--- /dev/null
+++ b/version3/go/ROM_BLS381_32.go
@@ -0,0 +1,56 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package BLS381
+
+// Base Bits= 29
+
+var Modulus= [...]Chunk {0x1FFFAAAB,0xFF7FFFF,0x14FFFFEE,0x17FFFD62,0xF6241EA,0x9507B58,0xAFD9CC3,0x109E70A2,0x1764774B,0x121A5D66,0x12C6E9ED,0x12FFCD34,0x111EA3,0xD}
+var R2modp= [...]Chunk {0x15BEF7AE,0x1031CD0E,0x2DD93E8,0x9226323,0xE6E2CD2,0x11684DAA,0x1170E5DB,0x88E25B1,0x1B366399,0x1C536F47,0xD1F9CBC,0x278B67F,0x1EA66A2B,0xC}
+const MConst Chunk=0x1FFCFFFD
+
+const CURVE_Cof_I int= 0
+const CURVE_A int= 0
+const CURVE_B_I int= 4
+var CURVE_B= [...]Chunk {0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Order= [...]Chunk {0x1,0x1FFFFFF8,0x1F96FFBF,0x1B4805FF,0x1D80553B,0xC0404D0,0x1520CCE7,0xA6533AF,0x73EDA7,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Gx= [...]Chunk {0x1B22C6BB,0x19D78056,0x1E86BBFE,0xBD07FF2,0x1AC586C5,0x1D1F8B8D,0x4168538,0x9F2EE97,0xFC3688C,0x27D4D60,0x9A558E3,0x32FAF28,0x1F1D3A73,0xB}
+var CURVE_Gy= [...]Chunk {0x6C5E7E1,0x551194A,0x222B903,0x198E8945,0xB3EDD03,0xC659602,0xBD8036C,0x12BABA01,0x4FCF5E0,0xBA0EC57,0x8278C3B,0x75541E3,0xB3F481E,0x4}
+
+var Fra= [...]Chunk {0x12235FB8,0x83BAF6C,0x19E04F63,0x1D4A7AC7,0xB9C4F67,0x1EBC25D,0x1D3DEC91,0x1FA797AB,0x1F0FD603,0x1016068,0x108C6FAD,0x5760CCF,0x104D3BF0,0xC}
+var Frb= [...]Chunk {0xDDC4AF3,0x7BC5093,0x1B1FB08B,0x1AB5829A,0x3C5F282,0x764B8FB,0xDBFB032,0x10F6D8F6,0x1854A147,0x1118FCFD,0x23A7A40,0xD89C065,0xFC3E2B3,0x0}
+var CURVE_Bnx= [...]Chunk {0x10000,0x10080000,0x34,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Cof= [...]Chunk {0xAAAB,0x55558,0x157855A3,0x191800AA,0x396,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Cru= [...]Chunk {0x1FFEFFFE,0x100FFFFF,0x280008B,0xFB026C4,0x9688DE1,0x149DF37C,0x1FAB76CE,0xED41EE,0x11BA69C6,0x1EFBB672,0x17C659CB,0x0,0x0,0x0}
+
+var CURVE_Pxa= [...]Chunk {0x121BDB8,0x402B646,0x16EFBF5,0x18064D50,0x1D1770BA,0x5B23D71,0xC0AD144,0x1A9F4807,0x11C6E47A,0x196E2882,0x9820149,0x11E1522,0x4AA2B2F,0x1}
+var CURVE_Pxb= [...]Chunk {0x1D042B7E,0xD63E82A,0x51755F9,0x19E22427,0x15049334,0x10DDEE3F,0x186AD769,0x1A132416,0x5596BD0,0x4413A7B,0x1F6B34E8,0x4E33EC0,0x1E02B605,0x9}
+var CURVE_Pya= [...]Chunk {0x8B82801,0xC9AA430,0xB28A278,0x15939877,0xD12C923,0xD34A8B0,0xE9DB50A,0x155197BA,0x1AADFD9B,0x16D171A8,0x3327371,0x4FADC23,0xE5D5277,0x6}
+var CURVE_Pyb= [...]Chunk {0x105F79BE,0x15483AFF,0x1B07686A,0xE1A4EB9,0x99AB3F3,0x955AB97,0xEBC99D2,0xFD0B4EC,0x19CB3E28,0x15E145C,0xCAB34AC,0x1D4E6998,0x6C4A02,0x3}
+var CURVE_W=[2][14]Chunk {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}
+var CURVE_SB=[2][2][14]Chunk {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}}
+var CURVE_WB=[4][14]Chunk {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}
+var CURVE_BB=[4][4][14]Chunk {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}}
+
+const USE_GLV bool=true
+const USE_GS_G2 bool=true
+const USE_GS_GT bool=true	
+const GT_STRONG bool=false
\ No newline at end of file
diff --git a/version3/go/ROM_BLS381_64.go b/version3/go/ROM_BLS381_64.go
new file mode 100644
index 0000000..68ce983
--- /dev/null
+++ b/version3/go/ROM_BLS381_64.go
@@ -0,0 +1,58 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package BLS381
+
+// Base Bits= 58
+
+var Modulus= [...]Chunk {0x1FEFFFFFFFFAAAB,0x2FFFFAC54FFFFEE,0x12A0F6B0F6241EA,0x213CE144AFD9CC3,0x2434BACD764774B,0x25FF9A692C6E9ED,0x1A0111EA3}
+var R2modp= [...]Chunk {0x20639A1D5BEF7AE,0x1244C6462DD93E8,0x22D09B54E6E2CD2,0x111C4B63170E5DB,0x38A6DE8FB366399,0x4F16CFED1F9CBC,0x19EA66A2B}
+const MConst Chunk=0x1F3FFFCFFFCFFFD
+
+const CURVE_Cof_I int= 0
+const CURVE_A int= 0
+const CURVE_B_I int= 4
+var CURVE_B= [...]Chunk {0x4,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Order= [...]Chunk {0x3FFFFFF00000001,0x36900BFFF96FFBF,0x180809A1D80553B,0x14CA675F520CCE7,0x73EDA7,0x0,0x0}
+var CURVE_Gx= [...]Chunk {0x33AF00ADB22C6BB,0x17A0FFE5E86BBFE,0x3A3F171BAC586C5,0x13E5DD2E4168538,0x4FA9AC0FC3688C,0x65F5E509A558E3,0x17F1D3A73}
+var CURVE_Gy= [...]Chunk {0xAA232946C5E7E1,0x331D128A222B903,0x18CB2C04B3EDD03,0x25757402BD8036C,0x1741D8AE4FCF5E0,0xEAA83C68278C3B,0x8B3F481E}
+
+
+var Fra= [...]Chunk {0x10775ED92235FB8,0x3A94F58F9E04F63,0x3D784BAB9C4F67,0x3F4F2F57D3DEC91,0x202C0D1F0FD603,0xAEC199F08C6FAD,0x1904D3BF0}
+var Frb= [...]Chunk {0xF78A126DDC4AF3,0x356B0535B1FB08B,0xEC971F63C5F282,0x21EDB1ECDBFB032,0x2231F9FB854A147,0x1B1380CA23A7A40,0xFC3E2B3}
+var CURVE_Bnx= [...]Chunk {0x201000000010000,0x34,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Cof= [...]Chunk {0xAAAB0000AAAB,0x3230015557855A3,0x396,0x0,0x0,0x0,0x0}
+var CURVE_Cru= [...]Chunk {0x201FFFFFFFEFFFE,0x1F604D88280008B,0x293BE6F89688DE1,0x1DA83DDFAB76CE,0x3DF76CE51BA69C6,0x17C659CB,0x0}
+
+var CURVE_Pxa= [...]Chunk {0x8056C8C121BDB8,0x300C9AA016EFBF5,0xB647AE3D1770BA,0x353E900EC0AD144,0x32DC51051C6E47A,0x23C2A449820149,0x24AA2B2F}
+var CURVE_Pxb= [...]Chunk {0x1AC7D055D042B7E,0x33C4484E51755F9,0x21BBDC7F5049334,0x3426482D86AD769,0x88274F65596BD0,0x9C67D81F6B34E8,0x13E02B605}
+var CURVE_Pya= [...]Chunk {0x193548608B82801,0x2B2730EEB28A278,0x1A695160D12C923,0x2AA32F74E9DB50A,0x2DA2E351AADFD9B,0x9F5B8463327371,0xCE5D5277}
+var CURVE_Pyb= [...]Chunk {0x2A9075FF05F79BE,0x1C349D73B07686A,0x12AB572E99AB3F3,0x1FA169D8EBC99D2,0x2BC28B99CB3E28,0x3A9CD330CAB34AC,0x606C4A02}
+var CURVE_W=[2][7]Chunk {{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0}}
+var CURVE_SB=[2][2][7]Chunk {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0}}}
+var CURVE_WB=[4][7]Chunk {{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0}}
+var CURVE_BB=[4][4][7]Chunk {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0}}}
+
+
+const USE_GLV bool=true
+const USE_GS_G2 bool=true
+const USE_GS_GT bool=true	
+const GT_STRONG bool=false
\ No newline at end of file
diff --git a/version3/go/ROM_BLS383_32.go b/version3/go/ROM_BLS383_32.go
new file mode 100644
index 0000000..5859aa6
--- /dev/null
+++ b/version3/go/ROM_BLS383_32.go
@@ -0,0 +1,55 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package BLS383
+
+// Base Bits= 29
+var Modulus= [...]Chunk {0x5AAB0AB,0x11B8EB24,0x19214AF6,0x187E5314,0x124F47A8,0x1C00B4B0,0x1446B0C6,0x59E6CB4,0x4A0AD46,0xFF5494,0x81B6B71,0x956DD6B,0x16556956,0x2A}
+var R2modp= [...]Chunk {0x116907F4,0x405B700,0x1752AC11,0x67A9E7C,0x1941C581,0x1AEA38C4,0xB1E4D22,0xCE841AE,0xA0FC49B,0xB4B1F48,0x13852312,0x1B3FDCED,0x1FECE397,0x26}
+const MConst Chunk=0x73435FD
+var Fra= [...]Chunk {0x1311DAC1,0x296B969,0x19DCF806,0x126901FC,0xD8C8A36,0x1A2572A8,0xA1A0959,0x1A47F743,0x110E4C6C,0x1608DA97,0xCE2E7F0,0x4FED178,0xACD5BF0,0x11}
+var Frb= [...]Chunk {0x1298D5EA,0xF2231BA,0x1F4452F0,0x6155117,0x4C2BD72,0x1DB4208,0xA2CA76D,0xB567571,0x139260D9,0xAF679FC,0x1B388380,0x4580BF2,0xB880D66,0x19}
+
+
+const CURVE_A int= 0
+const CURVE_Cof_I int= 0
+var CURVE_Cof= [...]Chunk {0x15169EAB,0xA82AB0A,0xAAEFFED,0x15558001,0x555,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+const CURVE_B_I int= 15
+var CURVE_B= [...]Chunk {0xF,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Order= [...]Chunk {0x1EBC0001,0x1904CF5F,0x834E5CE,0xBE12B42,0xB381DE0,0xE40B4C,0x270110,0x10018017,0x1002001,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Gx= [...]Chunk {0x8734573,0x623B9C8,0x1D1DC11E,0xBB7E107,0x1E3445C5,0x1D6C2578,0x10B0BE1E,0xED6103E,0x10F31D9F,0x296ED82,0x18E0D7D0,0x12F3D9C9,0x1FCBA55B,0x20}
+var CURVE_Gy= [...]Chunk {0x3F224,0x968B2F4,0x1FE63F48,0xFA93D90,0x14D2DDE5,0x54A56F5,0x12441D4C,0x18CD76C8,0x199D0DAD,0xE18E236,0x92BA73,0x99F6600,0x8F16727,0x3}
+
+var CURVE_Bnx= [...]Chunk {0x1001200,0x400000,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Cru= [...]Chunk {0xEAAC2A9,0x61B3A81,0x17D974B7,0xBED0345,0xA341BC2,0x17A51A6F,0x5738948,0x69B7BAE,0x14605445,0x374A43,0x8116AD1,0x956DD69,0x16556956,0x2A}
+var CURVE_Pxa= [...]Chunk {0xD7F2D86,0x1E59DB1,0x17474F85,0x1FB56CF2,0x572EE81,0xE487AB1,0x96F51FC,0x190A5AAE,0x6432501,0x13E58F3A,0x101E6425,0xFD807D1,0x34D2240,0x3}
+var CURVE_Pxb= [...]Chunk {0x452DE15,0x1ECF20F6,0x1FF9837B,0x95651AA,0xD5D75B5,0x5D44749,0x12277F66,0x1DB3A0B9,0x1D24F498,0x19441B0E,0x1CDE9DC5,0x2C975,0xD78006,0x18}
+var CURVE_Pya= [...]Chunk {0x1408CB41,0x34785DC,0x3586597,0x13DBC9E4,0x1A2E75B4,0x1D65489,0xCF9A25E,0x1ACE7933,0x1B6E990E,0x19FF31A3,0x12527615,0x1A44A68F,0x1792CF93,0x19}
+var CURVE_Pyb= [...]Chunk {0x1F479093,0x16C2321B,0x1889218E,0x87961BC,0x1BC98B01,0x197A24FB,0xA3DEBC2,0x88D67DF,0x1CE0D,0x1E8AD3D7,0x93B9EE9,0x59B18D6,0xE5247DD,0x10}
+var CURVE_W=[2][14]Chunk {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}
+var CURVE_SB=[2][2][14]Chunk {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}}
+var CURVE_WB=[4][14]Chunk {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}
+var CURVE_BB=[4][4][14]Chunk {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}}
+
+const USE_GLV bool=true
+const USE_GS_G2 bool=true
+const USE_GS_GT bool=true	
+const GT_STRONG bool=true
\ No newline at end of file
diff --git a/version3/go/ROM_BLS383_64.go b/version3/go/ROM_BLS383_64.go
new file mode 100644
index 0000000..e35aa7e
--- /dev/null
+++ b/version3/go/ROM_BLS383_64.go
@@ -0,0 +1,55 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package BLS383
+
+// Base Bits= 58
+var Modulus= [...]Chunk {0x2371D6485AAB0AB,0x30FCA6299214AF6,0x3801696124F47A8,0xB3CD969446B0C6,0x1FEA9284A0AD46,0x12ADBAD681B6B71,0x556556956}
+var R2modp= [...]Chunk {0x80B6E0116907F4,0xCF53CF9752AC11,0x35D47189941C581,0x19D0835CB1E4D22,0x16963E90A0FC49B,0x367FB9DB3852312,0x4DFECE397}
+const MConst Chunk=0x1BC0571073435FD
+var Fra= [...]Chunk {0x52D72D3311DAC1,0x24D203F99DCF806,0x344AE550D8C8A36,0x348FEE86A1A0959,0x2C11B52F10E4C6C,0x9FDA2F0CE2E7F0,0x22ACD5BF0}
+var Frb= [...]Chunk {0x1E446375298D5EA,0xC2AA22FF4452F0,0x3B684104C2BD72,0x16ACEAE2A2CA76D,0x15ECF3F939260D9,0x8B017E5B388380,0x32B880D66}
+
+
+const CURVE_A int= 0
+const CURVE_Cof_I int= 0
+var CURVE_Cof= [...]Chunk {0x150556155169EAB,0x2AAB0002AAEFFED,0x555,0x0,0x0,0x0,0x0}
+const CURVE_B_I int= 15
+var CURVE_B= [...]Chunk {0xF,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Order= [...]Chunk {0x32099EBFEBC0001,0x17C25684834E5CE,0x1C81698B381DE0,0x2003002E0270110,0x1002001,0x0,0x0}
+var CURVE_Gx= [...]Chunk {0xC4773908734573,0x176FC20FD1DC11E,0x3AD84AF1E3445C5,0x1DAC207D0B0BE1E,0x52DDB050F31D9F,0x25E7B3938E0D7D0,0x41FCBA55B}
+var CURVE_Gy= [...]Chunk {0x12D165E8003F224,0x1F527B21FE63F48,0xA94ADEB4D2DDE5,0x319AED912441D4C,0x1C31C46D99D0DAD,0x133ECC00092BA73,0x68F16727}
+
+var CURVE_Bnx= [...]Chunk {0x8000001001200,0x40,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Cru= [...]Chunk {0xC367502EAAC2A9,0x17DA068B7D974B7,0x2F4A34DEA341BC2,0xD36F75C5738948,0x6E94874605445,0x12ADBAD28116AD1,0x556556956}
+var CURVE_Pxa= [...]Chunk {0x3CB3B62D7F2D86,0x3F6AD9E57474F85,0x1C90F562572EE81,0x3214B55C96F51FC,0x27CB1E746432501,0x1FB00FA301E6425,0x634D2240}
+var CURVE_Pxb= [...]Chunk {0x3D9E41EC452DE15,0x12ACA355FF9837B,0xBA88E92D5D75B5,0x3B6741732277F66,0x3288361DD24F498,0x592EBCDE9DC5,0x300D78006}
+var CURVE_Pya= [...]Chunk {0x68F0BB9408CB41,0x27B793C83586597,0x3ACA913A2E75B4,0x359CF266CF9A25E,0x33FE6347B6E990E,0x34894D1F2527615,0x33792CF93}
+var CURVE_Pyb= [...]Chunk {0x2D846437F479093,0x10F2C379889218E,0x32F449F7BC98B01,0x111ACFBEA3DEBC2,0x3D15A7AE001CE0D,0xB3631AC93B9EE9,0x20E5247DD}
+var CURVE_W=[2][7]Chunk {{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0}}
+var CURVE_SB=[2][2][7]Chunk {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0}}}
+var CURVE_WB=[4][7]Chunk {{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0}}
+var CURVE_BB=[4][4][7]Chunk {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0}}}
+
+const USE_GLV bool=true
+const USE_GS_G2 bool=true
+const USE_GS_GT bool=true	
+const GT_STRONG bool=true
\ No newline at end of file
diff --git a/version3/go/ROM_BLS461_32.go b/version3/go/ROM_BLS461_32.go
new file mode 100644
index 0000000..e684b93
--- /dev/null
+++ b/version3/go/ROM_BLS461_32.go
@@ -0,0 +1,54 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package BLS461
+
+// Base Bits= 28
+var Modulus= [...]Chunk {0xAAAAAAB,0xAC0000A,0x54AAAAA,0x5555,0x400020,0x91557F0,0xF26AA,0xFA5C1CC,0xB42A8DF,0x7B14848,0x8BACCA4,0x6F1E32D,0x4935FBD,0x55D6941,0xD5A555A,0x5545554,0x1555}
+var R2modp= [...]Chunk {0xC9B6A33,0x2ECD087,0x3CCB2B1,0xCD461FE,0x8CB5AB2,0xC5B9635,0x5312E92,0xB659F64,0x3B596FA,0x8679006,0xA92E2B3,0x3CE05E3,0x363550F,0x7C07A8E,0x382C083,0x6347FEA,0xBD}
+const MConst Chunk=0xFFFFFFD
+
+const CURVE_Cof_I int= 0
+const CURVE_A int= 0
+const CURVE_B_I int= 9
+var CURVE_B= [...]Chunk {0x9,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Order= [...]Chunk {0x1,0x0,0xFFFFC00,0x7FEFFFE,0x110000,0x7FFC800,0x801FC01,0x5FD000E,0x17FE0,0xFFFC018,0xFFFFFF7,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Gx= [...]Chunk {0xADEE93D,0x4D026A8,0x74B7411,0xD9C00EE,0x31AC7F2,0xC3981B5,0x9218229,0xD3564DC,0xA096650,0x6F7C292,0x9743616,0xBE922B1,0x12CF668,0xC81327,0x463B73A,0xE74E99B,0xAD0}
+var CURVE_Gy= [...]Chunk {0xAD1D465,0xF763157,0xC4FF470,0x17884C8,0xB8D215D,0xA819E66,0xF4959D0,0xE5C3245,0xB84910A,0xB8BFA40,0xBE96EEC,0x8BF9F8C,0xF277ACC,0x5F1C3F2,0x5F68C9,0xCDB14B3,0x77B}
+
+var Fra= [...]Chunk {0xB812A3A,0x7117BF9,0x99C400F,0xC6308A5,0x5BF8A1,0x510E075,0x45FA5A6,0xCE4858D,0x770B31A,0xBC2CB04,0xE2FC61E,0xD073588,0x4366190,0x4DFEFA8,0x69E55E2,0x504B7F,0x12E4}
+var Frb= [...]Chunk {0xF298071,0x3AE8410,0xBAE6A9B,0x39D4CAF,0xFE4077E,0x404777A,0xBAF8104,0x2C13C3E,0x3D1F5C5,0xBEE7D44,0xA8B0685,0x9EAADA4,0x5CFE2C,0x7D7999,0x6BBFF78,0x50409D5,0x271}
+var CURVE_Bnx= [...]Chunk {0x0,0xFBFFFE0,0x1FFFFF,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Cof= [...]Chunk {0xAAAAAAB,0xA7FFFEA,0x1556AA,0xD55AAAB,0x554FFFF,0x1555,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Cru= [...]Chunk {0xFFFFFFE,0x40001F,0xFE00000,0xFFE7FFF,0xF0FFF6F,0x7200C47,0x7BCC604,0x15796DB,0xCF47771,0x9875433,0x613F0E8,0x5000502,0xEBFFF60,0x1FFFFF,0x0,0x0,0x0}
+var CURVE_Pxa= [...]Chunk {0x6D0A37C,0x5B50318,0x75DCC46,0xC2E492E,0xD6878A9,0xE01F919,0xF92F564,0x86DB74F,0x66803F0,0x46D581A,0x7ED78D,0x2F97C29,0xC270C89,0xF679453,0x6A50A9A,0x54138A0,0x10CC}
+var CURVE_Pxb= [...]Chunk {0x2C1C0AD,0xF85CA8C,0x25CADE9,0x6CD66C4,0xA289609,0xC612951,0xEE2401A,0x529ABEB,0xF65B17D,0xBA09D33,0xD4C5AF5,0x4D4371E,0x46A672E,0xA279D22,0xACEA37C,0x1FB4FE5,0x95C}
+var CURVE_Pya= [...]Chunk {0x2FB006,0xCCD0C1B,0xA12A337,0x3D194A4,0xC92C895,0x4960CFC,0x39FC68B,0x3A9B00F,0xED1BA0F,0xA7DBBC5,0xA9CDFD8,0x27CC2F7,0x4E73ED2,0x6070F4F,0xEBA7E67,0xAC848E7,0x226}
+var CURVE_Pyb= [...]Chunk {0xDF1457C,0xA506ADF,0x4C20A8,0xD6A31DC,0x36E3FB4,0xEA9A8F1,0x92F5668,0x3C3BE44,0x67A1297,0x74BEABA,0x56A20BE,0x4C42E38,0x45157F0,0x2AB1D00,0xBB402EA,0x101B4FA,0xE38}
+var CURVE_W=[2][17]Chunk {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}
+var CURVE_SB=[2][2][17]Chunk {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}}
+var CURVE_WB=[4][17]Chunk {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}
+var CURVE_BB=[4][4][17]Chunk {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}}
+
+const USE_GLV bool=true
+const USE_GS_G2 bool=true
+const USE_GS_GT bool=true	
+const GT_STRONG bool=false
\ No newline at end of file
diff --git a/version3/go/ROM_BLS461_64.go b/version3/go/ROM_BLS461_64.go
new file mode 100644
index 0000000..aea77a2
--- /dev/null
+++ b/version3/go/ROM_BLS461_64.go
@@ -0,0 +1,54 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package BLS461
+
+// Base Bits= 60
+var Modulus= [...]Chunk {0xAAC0000AAAAAAAB,0x20000555554AAAA,0x6AA91557F004000,0xA8DFFA5C1CC00F2,0xACCA47B14848B42,0x935FBD6F1E32D8B,0xD5A555A55D69414,0x15555545554}
+var R2modp= [...]Chunk {0x96D08774614DDA8,0xCD45F539225D5BD,0xD712EB760C95AB1,0xB3B687155F30B55,0xC4E62A05C3F5B81,0xBA1151676CA3CD0,0x7EDD8A958F442BE,0x12B89DD3F91}
+const MConst Chunk=0xC0005FFFFFFFD
+
+const CURVE_Cof_I int= 0
+const CURVE_A int= 0
+const CURVE_B_I int= 9
+var CURVE_B= [...]Chunk {0x9,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Order= [...]Chunk {0x1,0x7FEFFFEFFFFC0,0xC017FFC80001100,0x7FE05FD000E801F,0xFFFF7FFFC018001,0xFF,0x0,0x0}
+var CURVE_Gx= [...]Chunk {0x14D026A8ADEE93D,0xF2D9C00EE74B741,0x229C3981B531AC7,0x6650D3564DC9218,0x436166F7C292A09,0x2CF668BE922B197,0x463B73A0C813271,0xAD0E74E99B}
+var CURVE_Gy= [...]Chunk {0xF763157AD1D465,0x5D17884C8C4FF47,0x9D0A819E66B8D21,0x910AE5C3245F495,0x96EECB8BFA40B84,0x277ACC8BF9F8CBE,0x5F68C95F1C3F2F,0x77BCDB14B3}
+
+var Fra= [...]Chunk {0xF7117BF9B812A3A,0xA1C6308A599C400,0x5A6510E07505BF8,0xB31ACE4858D45FA,0xFC61EBC2CB04770,0x366190D073588E2,0x69E55E24DFEFA84,0x12E40504B7F}
+var Frb= [...]Chunk {0xB3AE8410F298071,0x7E39D4CAFBAE6A9,0x104404777AFE407,0xF5C52C13C3EBAF8,0xB0685BEE7D443D1,0x5CFE2C9EAADA4A8,0x6BBFF7807D79990,0x27150409D5}
+var CURVE_Bnx= [...]Chunk {0xFFBFFFE00000000,0x1FFFF,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Cof= [...]Chunk {0xAA7FFFEAAAAAAAB,0xFFD55AAAB01556A,0x1555554FF,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Cru= [...]Chunk {0x40001FFFFFFFE,0x6FFFE7FFFFE0000,0x6047200C47F0FFF,0x777115796DB7BCC,0x3F0E89875433CF4,0xBFFF60500050261,0x1FFFFFE,0x0}
+var CURVE_Pxa= [...]Chunk {0x65B503186D0A37C,0xA9C2E492E75DCC4,0x564E01F919D6878,0x3F086DB74FF92F,0xED78D46D581A668,0x270C892F97C2907,0x6A50A9AF679453C,0x10CC54138A0}
+var CURVE_Pxb= [...]Chunk {0x9F85CA8C2C1C0AD,0x96CD66C425CADE,0x1AC612951A2896,0xB17D529ABEBEE24,0xC5AF5BA09D33F65,0x6A672E4D4371ED4,0xACEA37CA279D224,0x95C1FB4FE5}
+var CURVE_Pya= [...]Chunk {0x7CCD0C1B02FB006,0x953D194A4A12A33,0x68B4960CFCC92C8,0xBA0F3A9B00F39FC,0xCDFD8A7DBBC5ED1,0xE73ED227CC2F7A9,0xEBA7E676070F4F4,0x226AC848E7}
+var CURVE_Pyb= [...]Chunk {0x8A506ADFDF1457C,0xB4D6A31DC04C20A,0x668EA9A8F136E3F,0x12973C3BE4492F5,0xA20BE74BEABA67A,0x5157F04C42E3856,0xBB402EA2AB1D004,0xE38101B4FA}
+var CURVE_W=[2][8]Chunk {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}
+var CURVE_SB=[2][2][8]Chunk {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}}
+var CURVE_WB=[4][8]Chunk {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}
+var CURVE_BB=[4][4][8]Chunk {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}}
+
+const USE_GLV bool=true
+const USE_GS_G2 bool=true
+const USE_GS_GT bool=true	
+const GT_STRONG bool=false
\ No newline at end of file
diff --git a/version3/go/ROM_BLS48_32.go b/version3/go/ROM_BLS48_32.go
new file mode 100644
index 0000000..fe66b69
--- /dev/null
+++ b/version3/go/ROM_BLS48_32.go
@@ -0,0 +1,66 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package BLS48
+
+// Base Bits= 29
+var Modulus= [...]Chunk {0x1CF6AC0B,0x17B7307F,0x19877E7B,0x12CE0134,0x14228402,0x1BD4C386,0x1DACBB04,0x40410D0,0x25A415,0x980B53E,0xDE6E250,0x15D9AAD6,0x5DA950,0x1029B7A,0x54AB351,0x14AD90CE,0x3729047,0x1FE7E2D9,0x145F610B,0x1F}
+var R2modp= [...]Chunk {0xD59D0FA,0x12F01FD0,0xDE8FD41,0x35AAEE1,0xB937F48,0x50700E8,0x1F50EFCE,0x1019B13C,0x3470A2F,0x11094115,0xF9FB72D,0x6AD10E2,0x1CFD9F8,0x44F4785,0x2B48793,0x1148ED3,0xF609E61,0x1EE34BC7,0x1735D29E,0x0}
+const MConst Chunk=0x9DA805D
+var Fra= [...]Chunk {0x1325BF89,0x1311E7EC,0xCD0A56F,0x1A0FD46E,0xE83BCCA,0xCA97DD0,0x18D1D297,0x5F1E137,0x7AB9F2C,0x13FC255F,0x1C9DECEB,0x9DEF4A2,0x3C0F60B,0x1D9909E4,0x1FF27FF7,0x1DBF8208,0x89BB36C,0x40044E0,0x62E01EE,0x5}
+var Frb= [...]Chunk {0x1325BF89,0x1311E7EC,0xCD0A56F,0x1A0FD46E,0xE83BCCA,0xCA97DD0,0x18D1D297,0x5F1E137,0x7AB9F2C,0x13FC255F,0x1C9DECEB,0x9DEF4A2,0x3C0F60B,0x1D9909E4,0x1FF27FF7,0x1DBF8208,0x89BB36C,0x40044E0,0x62E01EE,0x5}
+
+const CURVE_Cof_I int= 0
+const CURVE_A int= 0
+const CURVE_B_I int= 17
+var CURVE_B= [...]Chunk {0x11,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Order= [...]Chunk {0x1,0x17FFF800,0xA769C21,0x8AA813C,0x2029C21,0xA68F58B,0xB6307F4,0x1184DA51,0x6DFED78,0x1A3C85E9,0x571037B,0x1637F1F9,0x1C465FB0,0x98354B9,0x118DF17A,0x1422355D,0x43BF73E,0x6,0x0,0x0}
+var CURVE_Gx= [...]Chunk {0x5D71D33,0x1943697B,0x18CB783F,0x1B00AA9F,0x1711EE0B,0x7F80B23,0x129FD8CC,0x1345E03F,0x9A80F66,0x7038173,0xC056511,0x142801F5,0x42B2C3A,0x1AF09869,0x7924166,0x8381264,0x957EDD7,0xBACAEDC,0xA27A4A1,0x13}
+var CURVE_Gy= [...]Chunk {0xA6ED83A,0x14D2D9FF,0xA29C33D,0x1B8972A9,0x6958677,0x19C8F547,0x1DED7E3E,0x14F9E3DC,0x18FB7229,0x27171C0,0x1551E32D,0xE6184CC,0x6260E3C,0x733D204,0x579C437,0x1534665C,0x2B3349D,0x3162FD7,0xB634253,0x1}
+
+var CURVE_Bnx= [...]Chunk {0x1DE40020,0x3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Cof= [...]Chunk {0x1F12ABEB,0x516887B,0x5,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Cru= [...]Chunk {0xCBBA429,0x1B273F3,0xD3DD160,0x19C61452,0x308093A,0x146E1E34,0xAE0E768,0x1185948,0x1B73BC2D,0x93D855C,0x1B1A639C,0x118C919B,0xFF04AE3,0xF1CCD77,0x91318E5,0x10644780,0x3A79F7,0x1BE77919,0x145F60F3,0x1F}
+var CURVE_Pxaaa= [...]Chunk {0x923CE4A,0x14697474,0xAE04F4A,0x17AE205A,0x1313A20C,0x10B2EC50,0x18DF074F,0x15FE3FE8,0x7C90B98,0x959BF85,0xE57BD37,0x14376C96,0xBF57375,0xE20B625,0x12EE2172,0x1CBBCE85,0x1A5D9487,0xD0E024B,0x195E3602,0x1C}
+var CURVE_Pxaab= [...]Chunk {0xC0A1BE1,0x138E6E2D,0x1DF5FDC,0x151FC760,0x33972C5,0x56AA3C2,0x2491D8C,0x115B9FD7,0x140A11FA,0x1873AE35,0x1F259C26,0x74B0647,0x12D18B04,0x4672431,0x1C27F419,0x1CAA4D35,0x18DB48B6,0x13A54BDA,0x5080497,0x5}
+var CURVE_Pxaba= [...]Chunk {0x170C5DC4,0x11D39263,0x16B3BCB6,0x152C95BB,0x19BEC736,0x8849A12,0x49AB2A8,0xC7162D3,0xC58CD55,0x15C2659,0x11EE8B90,0xB40CAFC,0xE233167,0x7BEC8BE,0x129335BD,0x151C7DBB,0x78B689B,0x1B6B8EED,0x14BFBE3D,0x16}
+var CURVE_Pxabb= [...]Chunk {0x1A64B740,0x6B14B34,0x12481578,0x23FA931,0x323ADD1,0x206B82A,0xD789E1B,0x1FCFA666,0x1F4EEA7,0xF1E39E2,0x1968610,0xAF3EBD3,0x590D3B,0xDA0C35A,0x17306AAF,0xCF9DD2B,0x3F63B1A,0x96FF2F9,0xE102A76,0x12}
+var CURVE_Pxbaa= [...]Chunk {0x12F1E01F,0xDD8630B,0x12C29802,0x186239A6,0x19218788,0x4C87D1,0x16AE2501,0x775C076,0x870C80B,0x1A394429,0x1637D478,0x4A420E8,0x1C3AD4D4,0x10E5E713,0x111E6AD5,0x514FCF0,0x7CC49D3,0xC678A2,0x1787BDFD,0x1B}
+var CURVE_Pxbab= [...]Chunk {0x637383D,0x1851C11C,0x661F866,0x14404A7F,0x15D3D212,0x9AE28F6,0x8051F25,0x1E1CE2BF,0x137D882F,0xB231CEB,0xA8DB8FC,0x18957645,0x5E54DA8,0x1FF41C44,0x1A297414,0x17E1CBC5,0x1014F91F,0x4282AB7,0xB6CE9E3,0x10}
+var CURVE_Pxbba= [...]Chunk {0x1711939C,0xB41ED9E,0x69066BA,0x137CA3AD,0xCF2F6C0,0x5E6DAB9,0x2CE1323,0x946E448,0xF353D1C,0x14D9919F,0x46B7046,0x1A12015,0x3D6070,0x18C3E8D2,0x1F23BA45,0x1F1A337C,0x435A9CC,0x6CA1DF1,0x8A9CE1,0x15}
+var CURVE_Pxbbb= [...]Chunk {0x56F4899,0x196A0854,0xA959750,0x38A3D72,0x190BC9BC,0x145752BC,0x1E9E26DA,0x1403F88,0x71895E3,0x14162F5D,0x19FEC5FF,0x14190B16,0x7597C,0x19A3CF18,0x26A4B00,0x113D1BB6,0x7857A32,0xE0B78AB,0x1DD51E0F,0x1B}
+var CURVE_Pyaaa= [...]Chunk {0x14137844,0x1704BE7D,0x1FD3CCDD,0x189D8C93,0x1C768851,0xF5C37D5,0xE29C659,0x20AB1C1,0xF8896E0,0x1E08663E,0x1D1D539C,0x117E1C47,0x156CDD39,0x161F1017,0x143E8C72,0x174B22FD,0x18706190,0x49AA47E,0x19BB42E1,0xE}
+var CURVE_Pyaab= [...]Chunk {0xDC83190,0x12F19247,0x1AA26424,0x15D55E88,0xC418D32,0xB0E91DD,0x47CBFF7,0x2D992C1,0xDE03C1F,0x7694AE5,0x5C741A2,0x1D423AC6,0x5E02B9E,0x1E903F10,0x4EA6513,0x433A1F1,0x8EFA1C4,0xED54713,0x1E72CE4F,0x4}
+var CURVE_Pyaba= [...]Chunk {0x1985C0D,0xEE2FE82,0x64770FA,0x11A809B4,0x1483ACE9,0x18BCD2FA,0x171F32C,0x1612D58D,0x1E658341,0x1CBE2201,0x186E971,0x73F0E1,0xB0A5F40,0xAC90FB0,0x1635E008,0x237498B,0x1F3140D6,0xBF789A9,0x1166F259,0x1A}
+var CURVE_Pyabb= [...]Chunk {0x159D42F8,0x1B7F0540,0x45895D7,0x14875FA2,0x1E9E7F2B,0x10139D87,0x10F3FD7D,0x11D3717F,0x69E5006,0xF9BB3C4,0x13C9ED8D,0x16516DA,0x102F51DE,0x2725FEC,0x1F125B66,0xFFC324,0x1ED80731,0x1C16C4D,0x383AAA8,0x14}
+var CURVE_Pybaa= [...]Chunk {0x1F38039F,0x6A8959C,0x13C68984,0x11DD12AF,0x58093CF,0x1C8550A0,0xFFA1622,0xFF85979,0x1F2ABB75,0x18862E62,0x1EB6A2C9,0x1EC80B64,0x8EC2F18,0xE7BF713,0xC36B65A,0x19C5DD89,0x18A1D1AB,0xF772C8D,0xC11927C,0x5}
+var CURVE_Pybab= [...]Chunk {0x95F7865,0x134F0379,0x1CE9A0E,0x17E0EADD,0x1DACADD7,0x1B18F9F8,0x181D3943,0x186679A,0x2505BB0,0x1FDF1DC8,0x11B36A49,0x11E254E9,0xA438576,0x102B09AE,0x139984F4,0x15BC0233,0x1B6F180E,0x960562B,0x48CA65B,0x6}
+var CURVE_Pybba= [...]Chunk {0x7CC1979,0xEC1D4FB,0x1D89E6F0,0x955F38E,0x1635FDA9,0x123D8E10,0x10076209,0x494404A,0xD733D7,0x17678BCF,0x153841F9,0x10696FFD,0x5BC9FE8,0x1A20D8B2,0xE22EC9D,0x18449116,0x108C86C5,0x1B4CD720,0x34967,0x19}
+var CURVE_Pybbb= [...]Chunk {0xFC9F25B,0x7E44AB1,0xE9AB5D3,0x589F00D,0x1C9D264F,0xC7478B4,0x16B24A13,0x1D2C146B,0xEF84D9A,0xF47ECDE,0x1BFEE16A,0x1B69071E,0x11AB4C1C,0xBE9D9EF,0x390F005,0x78C8288,0x1B9BF549,0x9320730,0x3D84D97,0x14}
+var CURVE_W=[2][20]Chunk {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}
+var CURVE_SB=[2][2][20]Chunk {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}}
+var CURVE_WB=[4][20]Chunk {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}
+var CURVE_BB=[4][4][20]Chunk {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}}
+
+const USE_GLV bool=true
+const USE_GS_G2 bool=true
+const USE_GS_GT bool=true	
+const GT_STRONG bool=false
\ No newline at end of file
diff --git a/version3/go/ROM_BLS48_64.go b/version3/go/ROM_BLS48_64.go
new file mode 100644
index 0000000..44cf849
--- /dev/null
+++ b/version3/go/ROM_BLS48_64.go
@@ -0,0 +1,66 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package BLS48
+
+// Base Bits= 58
+var Modulus= [...]Chunk {0x2F6E60FFCF6AC0B,0x259C02699877E7B,0x37A9870D4228402,0x80821A1DACBB04,0x13016A7C025A415,0x2BB355ACDE6E250,0x20536F405DA950,0x295B219C54AB351,0x3FCFC5B23729047,0x3F45F610B}
+var R2modp= [...]Chunk {0x25E03FA0D59D0FA,0x6B55DC2DE8FD41,0xA0E01D0B937F48,0x20336279F50EFCE,0x2212822A3470A2F,0xD5A21C4F9FB72D,0x89E8F0A1CFD9F8,0x2291DA62B48793,0x3DC6978EF609E61,0x1735D29E}
+const MConst Chunk=0x21BFCBCA9DA805D
+var Fra= [...]Chunk {0x2623CFD9325BF89,0x341FA8DCCD0A56F,0x1952FBA0E83BCCA,0xBE3C26F8D1D297,0x27F84ABE7AB9F2C,0x13BDE945C9DECEB,0x3B3213C83C0F60B,0x3B7F0411FF27FF7,0x80089C089BB36C,0xA62E01EE}
+var Frb= [...]Chunk {0x2623CFD9325BF89,0x341FA8DCCD0A56F,0x1952FBA0E83BCCA,0xBE3C26F8D1D297,0x27F84ABE7AB9F2C,0x13BDE945C9DECEB,0x3B3213C83C0F60B,0x3B7F0411FF27FF7,0x80089C089BB36C,0xA62E01EE}
+
+const CURVE_Cof_I int= 0
+const CURVE_A int= 0
+const CURVE_B_I int= 17
+var CURVE_B= [...]Chunk {0x11,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Order= [...]Chunk {0x2FFFF0000000001,0x11550278A769C21,0x14D1EB162029C21,0x2309B4A2B6307F4,0x34790BD26DFED78,0x2C6FE3F2571037B,0x1306A973C465FB0,0x28446ABB18DF17A,0xC43BF73E,0x0}
+var CURVE_Gx= [...]Chunk {0x3286D2F65D71D33,0x3601553F8CB783F,0xFF01647711EE0B,0x268BC07F29FD8CC,0xE0702E69A80F66,0x285003EAC056511,0x35E130D242B2C3A,0x107024C87924166,0x17595DB8957EDD7,0x26A27A4A1}
+var CURVE_Gy= [...]Chunk {0x29A5B3FEA6ED83A,0x3712E552A29C33D,0x3391EA8E6958677,0x29F3C7B9DED7E3E,0x4E2E3818FB7229,0x1CC30999551E32D,0xE67A4086260E3C,0x2A68CCB8579C437,0x62C5FAE2B3349D,0x2B634253}
+
+var CURVE_Bnx= [...]Chunk {0x7DE40020,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Cof= [...]Chunk {0xA2D10F7F12ABEB,0x5,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Cru= [...]Chunk {0x364E7E6CBBA429,0x338C28A4D3DD160,0x28DC3C68308093A,0x230B290AE0E768,0x127B0AB9B73BC2D,0x23192337B1A639C,0x1E399AEEFF04AE3,0x20C88F0091318E5,0x37CEF23203A79F7,0x3F45F60F3}
+var CURVE_Pxaaa= [...]Chunk {0x28D2E8E8923CE4A,0x2F5C40B4AE04F4A,0x2165D8A1313A20C,0x2BFC7FD18DF074F,0x12B37F0A7C90B98,0x286ED92CE57BD37,0x1C416C4ABF57375,0x39779D0B2EE2172,0x1A1C0497A5D9487,0x3995E3602}
+var CURVE_Pxaab= [...]Chunk {0x271CDC5AC0A1BE1,0x2A3F8EC01DF5FDC,0xAD5478433972C5,0x22B73FAE2491D8C,0x30E75C6B40A11FA,0xE960C8FF259C26,0x8CE48632D18B04,0x39549A6BC27F419,0x274A97B58DB48B6,0xA5080497}
+var CURVE_Pxaba= [...]Chunk {0x23A724C770C5DC4,0x2A592B776B3BCB6,0x110934259BEC736,0x18E2C5A649AB2A8,0x2B84CB2C58CD55,0x168195F91EE8B90,0xF7D917CE233167,0x2A38FB7729335BD,0x36D71DDA78B689B,0x2D4BFBE3D}
+var CURVE_Pxabb= [...]Chunk {0xD629669A64B740,0x47F52632481578,0x40D7054323ADD1,0x3F9F4CCCD789E1B,0x1E3C73C41F4EEA7,0x15E7D7A61968610,0x1B4186B40590D3B,0x19F3BA577306AAF,0x12DFE5F23F63B1A,0x24E102A76}
+var CURVE_Pxbaa= [...]Chunk {0x1BB0C6172F1E01F,0x30C4734D2C29802,0x990FA39218788,0xEEB80ED6AE2501,0x34728852870C80B,0x94841D1637D478,0x21CBCE27C3AD4D4,0xA29F9E111E6AD5,0x18CF1447CC49D3,0x37787BDFD}
+var CURVE_Pxbab= [...]Chunk {0x30A38238637383D,0x288094FE661F866,0x135C51ED5D3D212,0x3C39C57E8051F25,0x164639D737D882F,0x312AEC8AA8DB8FC,0x3FE838885E54DA8,0x2FC3978BA297414,0x850556F014F91F,0x20B6CE9E3}
+var CURVE_Pxbba= [...]Chunk {0x1683DB3D711939C,0x26F9475A69066BA,0xBCDB572CF2F6C0,0x128DC8902CE1323,0x29B3233EF353D1C,0x342402A46B7046,0x3187D1A403D6070,0x3E3466F9F23BA45,0xD943BE2435A9CC,0x2A08A9CE1}
+var CURVE_Pxbbb= [...]Chunk {0x32D410A856F4899,0x7147AE4A959750,0x28AEA57990BC9BC,0x2807F11E9E26DA,0x282C5EBA71895E3,0x2832162D9FEC5FF,0x33479E30007597C,0x227A376C26A4B00,0x1C16F1567857A32,0x37DD51E0F}
+var CURVE_Pyaaa= [...]Chunk {0x2E097CFB4137844,0x313B1927FD3CCDD,0x1EB86FABC768851,0x4156382E29C659,0x3C10CC7CF8896E0,0x22FC388FD1D539C,0x2C3E202F56CDD39,0x2E9645FB43E8C72,0x93548FD8706190,0x1D9BB42E1}
+var CURVE_Pyaab= [...]Chunk {0x25E3248EDC83190,0x2BAABD11AA26424,0x161D23BAC418D32,0x5B3258247CBFF7,0xED295CADE03C1F,0x3A84758C5C741A2,0x3D207E205E02B9E,0x86743E24EA6513,0x1DAA8E268EFA1C4,0x9E72CE4F}
+var CURVE_Pyaba= [...]Chunk {0x1DC5FD041985C0D,0x2350136864770FA,0x3179A5F5483ACE9,0x2C25AB1A171F32C,0x397C4403E658341,0xE7E1C2186E971,0x15921F60B0A5F40,0x46E9317635E008,0x17EF1353F3140D6,0x35166F259}
+var CURVE_Pyabb= [...]Chunk {0x36FE0A8159D42F8,0x290EBF4445895D7,0x20273B0FE9E7F2B,0x23A6E2FF0F3FD7D,0x1F37678869E5006,0x2CA2DB53C9ED8D,0x4E4BFD902F51DE,0x1FF8649F125B66,0x382D89BED80731,0x28383AAA8}
+var CURVE_Pybaa= [...]Chunk {0xD512B39F38039F,0x23BA255F3C68984,0x390AA14058093CF,0x1FF0B2F2FFA1622,0x310C5CC5F2ABB75,0x3D9016C9EB6A2C9,0x1CF7EE268EC2F18,0x338BBB12C36B65A,0x1EEE591B8A1D1AB,0xAC11927C}
+var CURVE_Pybab= [...]Chunk {0x269E06F295F7865,0x2FC1D5BA1CE9A0E,0x3631F3F1DACADD7,0x30CCF3581D3943,0x3FBE3B902505BB0,0x23C4A9D31B36A49,0x2056135CA438576,0x2B78046739984F4,0x12C0AC57B6F180E,0xC48CA65B}
+var CURVE_Pybba= [...]Chunk {0x1D83A9F67CC1979,0x12ABE71DD89E6F0,0x247B1C21635FDA9,0x92880950076209,0x2ECF179E0D733D7,0x20D2DFFB53841F9,0x3441B1645BC9FE8,0x3089222CE22EC9D,0x3699AE4108C86C5,0x320034967}
+var CURVE_Pybbb= [...]Chunk {0xFC89562FC9F25B,0xB13E01AE9AB5D3,0x18E8F169C9D264F,0x3A5828D76B24A13,0x1E8FD9BCEF84D9A,0x36D20E3DBFEE16A,0x17D3B3DF1AB4C1C,0xF190510390F005,0x12640E61B9BF549,0x283D84D97}
+var CURVE_W=[2][10]Chunk {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}
+var CURVE_SB=[2][2][10]Chunk {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}}
+var CURVE_WB=[4][10]Chunk {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}
+var CURVE_BB=[4][4][10]Chunk {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}}
+
+const USE_GLV bool=true
+const USE_GS_G2 bool=true
+const USE_GS_GT bool=true	
+const GT_STRONG bool=false
\ No newline at end of file
diff --git a/version3/go/ROM_BN254CX_32.go b/version3/go/ROM_BN254CX_32.go
new file mode 100644
index 0000000..942a412
--- /dev/null
+++ b/version3/go/ROM_BN254CX_32.go
@@ -0,0 +1,56 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package BN254CX
+
+// Base Bits= 28
+var Modulus= [...]Chunk {0xC1B55B3,0x6623EF5,0x93EE1BE,0xD6EE180,0x6D3243F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2}
+var R2modp= [...]Chunk {0x8A0800A,0x466A061,0x43056A3,0x2B3A225,0x9C6600,0x148515B,0x6BDF50,0xEC9EA56,0xC992E66,0x1}
+const MConst Chunk=0x9789E85
+var Fra= [...]Chunk {0x5C80EA3,0xD908335,0x3F8215B,0x7326F17,0x8986867,0x8AACA71,0x4AFE18B,0xA63A016,0x359082F,0x1}
+var Frb= [...]Chunk {0x6534710,0x8D1BBC0,0x546C062,0x63C7269,0xE3ABBD8,0xD9CDBC4,0x900DC53,0x623628A,0xA6F7D0,0x1}
+
+const CURVE_Cof_I int= 1
+const CURVE_A int= 0
+const CURVE_B_I int= 2
+var CURVE_B= [...]Chunk {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Order= [...]Chunk {0x6EB1F6D,0x11C0A63,0x906CEBE,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2}
+var CURVE_Gx= [...]Chunk {0xC1B55B2,0x6623EF5,0x93EE1BE,0xD6EE180,0x6D3243F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2}
+var CURVE_Gy= [...]Chunk {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Bnx= [...]Chunk {0x3C012B1,0x0,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Cof= [...]Chunk {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Cru= [...]Chunk {0x4235C97,0xE093179,0xF875631,0xDF6471E,0xF1440BD,0xCA83,0x480000,0x0,0x0,0x0}
+
+var CURVE_Pxa= [...]Chunk {0x4D2EC74,0x851CEEE,0xE2726C0,0x85BFA03,0xBBB907C,0xF5C34,0x6358B25,0x7053B25,0x9682D2C,0x1}
+var CURVE_Pxb= [...]Chunk {0xE29CFE1,0xA58E8B2,0x9C30F47,0x97B0C20,0x743F81B,0x37A8E99,0xAA011C9,0x3E19F64,0x466B9EC,0x1}
+var CURVE_Pya= [...]Chunk {0xF0BE09F,0xFBFCEBC,0xEC1B30C,0xB33D847,0x2096361,0x157DAEE,0xDD81E22,0x72332B8,0xA79EDD9,0x0}
+var CURVE_Pyb= [...]Chunk {0x898EE9D,0x904B228,0x2EDEBED,0x4EA569D,0x461C286,0x512D8D3,0x35C6E4,0xECC4C09,0x6160C39,0x0}
+
+
+var CURVE_W=[2][10]Chunk {{0x62FEB83,0x5463491,0x381200,0xB4,0x6000,0x0,0x0,0x0,0x0,0x0},{0x7802561,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}
+var CURVE_SB=[2][2][10]Chunk {{{0xDB010E4,0x5463491,0x381280,0xB4,0x6000,0x0,0x0,0x0,0x0,0x0},{0x7802561,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x7802561,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xBB33EA,0xBD5D5D2,0x8CEBCBD,0xD6EE018,0x6D2643F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2}}}
+var CURVE_WB=[4][10]Chunk {{0x67A84B0,0x1C21185,0x12B040,0x3C,0x2000,0x0,0x0,0x0,0x0,0x0},{0xE220475,0xCDF995B,0xA7F9A36,0x94EDA8C,0xA0DC07E,0x8702,0x300000,0x0,0x0,0x0},{0xF10B93,0x66FCCAE,0x53FCD3B,0x4A76D46,0x506E03F,0x4381,0x180000,0x0,0x0,0x0},{0xDFAAA11,0x1C21185,0x12B0C0,0x3C,0x2000,0x0,0x0,0x0,0x0,0x0}}
+var CURVE_BB=[4][4][10]Chunk {{{0x32B0CBD,0x11C0A63,0x906CE7E,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2},{0x32B0CBC,0x11C0A63,0x906CE7E,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2},{0x32B0CBC,0x11C0A63,0x906CE7E,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2},{0x7802562,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x7802561,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x32B0CBC,0x11C0A63,0x906CE7E,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2},{0x32B0CBD,0x11C0A63,0x906CE7E,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2},{0x32B0CBC,0x11C0A63,0x906CE7E,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2}},{{0x7802562,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x7802561,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x7802561,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x7802561,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x3C012B2,0x0,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xF004AC2,0x0,0x100,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xF6AFA0A,0x11C0A62,0x906CE3E,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2},{0x3C012B2,0x0,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}}
+
+const USE_GLV bool=true
+const USE_GS_G2 bool=true
+const USE_GS_GT bool=true	
+const GT_STRONG bool=true
\ No newline at end of file
diff --git a/version3/go/ROM_BN254CX_64.go b/version3/go/ROM_BN254CX_64.go
new file mode 100644
index 0000000..a321234
--- /dev/null
+++ b/version3/go/ROM_BN254CX_64.go
@@ -0,0 +1,56 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package BN254CX
+
+// Base Bits= 56
+var Modulus= [...]Chunk {0x6623EF5C1B55B3,0xD6EE18093EE1BE,0x647A6366D3243F,0x8702A0DB0BDDF,0x24000000}
+var R2modp= [...]Chunk {0x466A0618A0800A,0x2B3A22543056A3,0x148515B09C6600,0xEC9EA5606BDF50,0x1C992E66}
+const MConst Chunk=0x4E205BF9789E85
+var Fra= [...]Chunk {0xD9083355C80EA3,0x7326F173F8215B,0x8AACA718986867,0xA63A0164AFE18B,0x1359082F}
+var Frb= [...]Chunk {0x8D1BBC06534710,0x63C7269546C062,0xD9CDBC4E3ABBD8,0x623628A900DC53,0x10A6F7D0}
+
+const CURVE_Cof_I int= 1
+const CURVE_A int= 0
+const CURVE_B_I int= 2
+var CURVE_B= [...]Chunk {0x2,0x0,0x0,0x0,0x0}
+var CURVE_Order= [...]Chunk {0x11C0A636EB1F6D,0xD6EE0CC906CEBE,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000}
+var CURVE_Gx= [...]Chunk {0x6623EF5C1B55B2,0xD6EE18093EE1BE,0x647A6366D3243F,0x8702A0DB0BDDF,0x24000000}
+var CURVE_Gy= [...]Chunk {0x1,0x0,0x0,0x0,0x0}
+var CURVE_Bnx= [...]Chunk {0x3C012B1,0x40,0x0,0x0,0x0}
+var CURVE_Cof= [...]Chunk {0x1,0x0,0x0,0x0,0x0}
+var CURVE_Cru= [...]Chunk {0xE0931794235C97,0xDF6471EF875631,0xCA83F1440BD,0x480000,0x0}
+
+var CURVE_Pxa= [...]Chunk {0x851CEEE4D2EC74,0x85BFA03E2726C0,0xF5C34BBB907C,0x7053B256358B25,0x19682D2C}
+var CURVE_Pxb= [...]Chunk {0xA58E8B2E29CFE1,0x97B0C209C30F47,0x37A8E99743F81B,0x3E19F64AA011C9,0x1466B9EC}
+var CURVE_Pya= [...]Chunk {0xFBFCEBCF0BE09F,0xB33D847EC1B30C,0x157DAEE2096361,0x72332B8DD81E22,0xA79EDD9}
+var CURVE_Pyb= [...]Chunk {0x904B228898EE9D,0x4EA569D2EDEBED,0x512D8D3461C286,0xECC4C09035C6E4,0x6160C39}
+
+
+var CURVE_W=[2][5]Chunk {{0x546349162FEB83,0xB40381200,0x6000,0x0,0x0},{0x7802561,0x80,0x0,0x0,0x0}}
+var CURVE_SB=[2][2][5]Chunk {{{0x5463491DB010E4,0xB40381280,0x6000,0x0,0x0},{0x7802561,0x80,0x0,0x0,0x0}},{{0x7802561,0x80,0x0,0x0,0x0},{0xBD5D5D20BB33EA,0xD6EE0188CEBCBD,0x647A6366D2643F,0x8702A0DB0BDDF,0x24000000}}}
+var CURVE_WB=[4][5]Chunk {{0x1C2118567A84B0,0x3C012B040,0x2000,0x0,0x0},{0xCDF995BE220475,0x94EDA8CA7F9A36,0x8702A0DC07E,0x300000,0x0},{0x66FCCAE0F10B93,0x4A76D4653FCD3B,0x4381506E03F,0x180000,0x0},{0x1C21185DFAAA11,0x3C012B0C0,0x2000,0x0,0x0}}
+var CURVE_BB=[4][4][5]Chunk {{{0x11C0A6332B0CBD,0xD6EE0CC906CE7E,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000},{0x11C0A6332B0CBC,0xD6EE0CC906CE7E,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000},{0x11C0A6332B0CBC,0xD6EE0CC906CE7E,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000},{0x7802562,0x80,0x0,0x0,0x0}},{{0x7802561,0x80,0x0,0x0,0x0},{0x11C0A6332B0CBC,0xD6EE0CC906CE7E,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000},{0x11C0A6332B0CBD,0xD6EE0CC906CE7E,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000},{0x11C0A6332B0CBC,0xD6EE0CC906CE7E,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000}},{{0x7802562,0x80,0x0,0x0,0x0},{0x7802561,0x80,0x0,0x0,0x0},{0x7802561,0x80,0x0,0x0,0x0},{0x7802561,0x80,0x0,0x0,0x0}},{{0x3C012B2,0x40,0x0,0x0,0x0},{0xF004AC2,0x100,0x0,0x0,0x0},{0x11C0A62F6AFA0A,0xD6EE0CC906CE3E,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000},{0x3C012B2,0x40,0x0,0x0,0x0}}}
+
+const USE_GLV bool=true
+const USE_GS_G2 bool=true
+const USE_GS_GT bool=true	
+const GT_STRONG bool=true
\ No newline at end of file
diff --git a/version3/go/ROM_BN254_32.go b/version3/go/ROM_BN254_32.go
new file mode 100644
index 0000000..49c483a
--- /dev/null
+++ b/version3/go/ROM_BN254_32.go
@@ -0,0 +1,56 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package BN254
+
+// BN254 Curve
+
+// Base Bits= 28
+var Modulus= [...]Chunk {0x13,0x0,0x13A7,0x0,0x86121,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2}
+var R2modp= [...]Chunk {0xF5E7E39,0x2F2A96F,0xB96F13C,0x64E8642,0xC7146,0x9926F7B,0x4DACD24,0x8321E7B,0xD127A2E,0x1}
+const MConst Chunk=0x79435E5
+var Fra= [...]Chunk {0xF2A6DE9,0x7DE6C06,0xF77C2E1,0x74924D3,0x53F8509,0x50A8469,0xCB6499B,0x212E7C8,0xB377619,0x1}
+var Frb= [...]Chunk {0xD5922A,0x82193F9,0x8850C5,0x8B6DB2C,0xAC8DC17,0x2F57B96,0x503EAB2,0x1ED1837,0x9EBEE69,0x0}
+
+const CURVE_Cof_I int= 1
+const CURVE_A int= 0
+const CURVE_B_I int= 2
+var CURVE_B= [...]Chunk {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Order= [...]Chunk {0xD,0x0,0x10A1,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2}
+var CURVE_Gx= [...]Chunk {0x12,0x0,0x13A7,0x0,0x86121,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2}
+var CURVE_Gy= [...]Chunk {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Bnx= [...]Chunk {0x1,0x8000000,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Cof= [...]Chunk {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Cru= [...]Chunk {0x7,0x8000000,0x6CD,0x0,0x24909,0x4000000,0x49B362,0x0,0x0,0x0}
+var CURVE_Pxa= [...]Chunk {0x803FB2B,0xEE4224C,0x8BF0D91,0x8BBB489,0xDB6A464,0x7E8C61E,0xFEB8D8C,0x519EB62,0x61A10BB,0x0}
+var CURVE_Pxb= [...]Chunk {0x7D54CF3,0x8C34C1E,0x784B70D,0x746BAE3,0xA5B1F4D,0x8C5982A,0x3310AA7,0xBA73783,0x516AAF9,0x0}
+var CURVE_Pya= [...]Chunk {0x1CD2B9A,0xF0E0789,0xE09BD19,0xAE6BDB,0x22329BD,0x96698C8,0x39A90E0,0x6BAF934,0x21897A0,0x0}
+var CURVE_Pyb= [...]Chunk {0xB3ACE9B,0x2D1AEC6,0x9C9578A,0x6FFD73,0xD37B090,0x56F5F38,0x68F6D44,0x7C8B152,0xEBB2B0E,0x0}
+var CURVE_W=[2][10]Chunk {{0x3,0x0,0x204,0x8000000,0x6181,0x0,0x0,0x0,0x0,0x0},{0x1,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}
+var CURVE_SB=[2][2][10]Chunk {{{0x4,0x0,0x285,0x8000000,0x6181,0x0,0x0,0x0,0x0,0x0},{0x1,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x1,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xA,0x0,0xE9D,0x0,0x79E1E,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2}}}
+var CURVE_WB=[4][10]Chunk {{0x0,0x8000000,0x40,0x8000000,0x2080,0x0,0x0,0x0,0x0,0x0},{0x5,0x8000000,0x54A,0x0,0x1C707,0x8000000,0x312241,0x0,0x0,0x0},{0x3,0x8000000,0x2C5,0x8000000,0xE383,0xC000000,0x189120,0x0,0x0,0x0},{0x1,0x8000000,0xC1,0x8000000,0x2080,0x0,0x0,0x0,0x0,0x0}}
+var CURVE_BB=[4][4][10]Chunk {{{0xD,0x8000000,0x1060,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2},{0xC,0x8000000,0x1060,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2},{0xC,0x8000000,0x1060,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2},{0x2,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x1,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xC,0x8000000,0x1060,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2},{0xD,0x8000000,0x1060,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2},{0xC,0x8000000,0x1060,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2}},{{0x2,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x2,0x8000000,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x2,0x0,0x102,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xA,0x0,0x1020,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2},{0x2,0x8000000,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}}
+
+const USE_GLV bool=true
+const USE_GS_G2 bool=true
+const USE_GS_GT bool=true	
+const GT_STRONG bool=false
+
diff --git a/version3/go/ROM_BN254_64.go b/version3/go/ROM_BN254_64.go
new file mode 100644
index 0000000..92da33d
--- /dev/null
+++ b/version3/go/ROM_BN254_64.go
@@ -0,0 +1,56 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package BN254
+
+//BN254 Curve
+
+// Base Bits= 56
+var Modulus= [...]Chunk {0x13,0x13A7,0x80000000086121,0x40000001BA344D,0x25236482}
+var R2modp= [...]Chunk {0x2F2A96FF5E7E39,0x64E8642B96F13C,0x9926F7B00C7146,0x8321E7B4DACD24,0x1D127A2E}
+const MConst Chunk=0x435E50D79435E5
+
+const CURVE_Cof_I int= 1
+const CURVE_A int= 0
+const CURVE_B_I int= 2
+var CURVE_B= [...]Chunk {0x2,0x0,0x0,0x0,0x0}
+var CURVE_Order= [...]Chunk {0xD,0x800000000010A1,0x8000000007FF9F,0x40000001BA344D,0x25236482}
+var CURVE_Gx= [...]Chunk {0x12,0x13A7,0x80000000086121,0x40000001BA344D,0x25236482}
+var CURVE_Gy= [...]Chunk {0x1,0x0,0x0,0x0,0x0}
+
+var Fra= [...]Chunk {0x7DE6C06F2A6DE9,0x74924D3F77C2E1,0x50A846953F8509,0x212E7C8CB6499B,0x1B377619}
+var Frb= [...]Chunk {0x82193F90D5922A,0x8B6DB2C08850C5,0x2F57B96AC8DC17,0x1ED1837503EAB2,0x9EBEE69}
+var CURVE_Bnx= [...]Chunk {0x80000000000001,0x40,0x0,0x0,0x0}
+var CURVE_Cof= [...]Chunk {0x1,0x0,0x0,0x0,0x0}
+var CURVE_Cru= [...]Chunk {0x80000000000007,0x6CD,0x40000000024909,0x49B362,0x0}
+var CURVE_Pxa= [...]Chunk {0xEE4224C803FB2B,0x8BBB4898BF0D91,0x7E8C61EDB6A464,0x519EB62FEB8D8C,0x61A10BB}
+var CURVE_Pxb= [...]Chunk {0x8C34C1E7D54CF3,0x746BAE3784B70D,0x8C5982AA5B1F4D,0xBA737833310AA7,0x516AAF9}
+var CURVE_Pya= [...]Chunk {0xF0E07891CD2B9A,0xAE6BDBE09BD19,0x96698C822329BD,0x6BAF93439A90E0,0x21897A0}
+var CURVE_Pyb= [...]Chunk {0x2D1AEC6B3ACE9B,0x6FFD739C9578A,0x56F5F38D37B090,0x7C8B15268F6D44,0xEBB2B0E}
+var CURVE_W=[2][5]Chunk {{0x3,0x80000000000204,0x6181,0x0,0x0},{0x1,0x81,0x0,0x0,0x0}}
+var CURVE_SB=[2][2][5]Chunk {{{0x4,0x80000000000285,0x6181,0x0,0x0},{0x1,0x81,0x0,0x0,0x0}},{{0x1,0x81,0x0,0x0,0x0},{0xA,0xE9D,0x80000000079E1E,0x40000001BA344D,0x25236482}}}
+var CURVE_WB=[4][5]Chunk {{0x80000000000000,0x80000000000040,0x2080,0x0,0x0},{0x80000000000005,0x54A,0x8000000001C707,0x312241,0x0},{0x80000000000003,0x800000000002C5,0xC000000000E383,0x189120,0x0},{0x80000000000001,0x800000000000C1,0x2080,0x0,0x0}}
+var CURVE_BB=[4][4][5]Chunk {{{0x8000000000000D,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482},{0x8000000000000C,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482},{0x8000000000000C,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482},{0x2,0x81,0x0,0x0,0x0}},{{0x1,0x81,0x0,0x0,0x0},{0x8000000000000C,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482},{0x8000000000000D,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482},{0x8000000000000C,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482}},{{0x2,0x81,0x0,0x0,0x0},{0x1,0x81,0x0,0x0,0x0},{0x1,0x81,0x0,0x0,0x0},{0x1,0x81,0x0,0x0,0x0}},{{0x80000000000002,0x40,0x0,0x0,0x0},{0x2,0x102,0x0,0x0,0x0},{0xA,0x80000000001020,0x8000000007FF9F,0x40000001BA344D,0x25236482},{0x80000000000002,0x40,0x0,0x0,0x0}}}
+
+const USE_GLV bool=true
+const USE_GS_G2 bool=true
+const USE_GS_GT bool=true	
+const GT_STRONG bool=false
diff --git a/version3/go/ROM_BRAINPOOL_32.go b/version3/go/ROM_BRAINPOOL_32.go
new file mode 100644
index 0000000..dd2879a
--- /dev/null
+++ b/version3/go/ROM_BRAINPOOL_32.go
@@ -0,0 +1,38 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+/* Note that the original curve has been transformed to an isomorphic curve with A=-3 */
+
+package BRAINPOOL
+
+// Base Bits= 28
+var Modulus= [...]Chunk {0xF6E5377,0x13481D1,0x6202820,0xF623D52,0xD726E3B,0x909D838,0xC3E660A,0xA1EEA9B,0x9FB57DB,0xA}
+var R2modp= [...]Chunk {0xB9A3787,0x9E04F49,0x8F3CF49,0x2931721,0xF1DBC89,0x54E8C3C,0xF7559CA,0xBB411A3,0x773E15F,0x9}
+const MConst Chunk=0xEFD89B9
+
+const CURVE_Cof_I int= 1
+var CURVE_Cof=[...]Chunk {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+const CURVE_A int= -3
+const CURVE_B_I int= 0
+var CURVE_B= [...]Chunk {0xEE92B04,0xE58101F,0xF49256A,0xEBC4AF2,0x6B7BF93,0x733D0B7,0x4FE66A7,0x30D84EA,0x62C61C4,0x6}
+var CURVE_Order= [...]Chunk {0x74856A7,0x1E0E829,0x1A6F790,0x7AA3B56,0xD718C39,0x909D838,0xC3E660A,0xA1EEA9B,0x9FB57DB,0xA}
+var CURVE_Gx= [...]Chunk {0xE1305F4,0xA191562,0xFBC2B79,0x42C47AA,0x149AFA1,0xB23A656,0x7732213,0xC1CFE7B,0x3E8EB3C,0xA}
+var CURVE_Gy= [...]Chunk {0xB25C9BE,0xABE8F35,0x27001D,0xB6DE39D,0x17E69BC,0xE146444,0xD7F7B22,0x3439C56,0xD996C82,0x2}
diff --git a/version3/go/ROM_BRAINPOOL_64.go b/version3/go/ROM_BRAINPOOL_64.go
new file mode 100644
index 0000000..0397690
--- /dev/null
+++ b/version3/go/ROM_BRAINPOOL_64.go
@@ -0,0 +1,38 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+/* Note that the original curve has been transformed to an isomorphic curve with A=-3 */
+
+package BRAINPOOL
+
+// Base Bits= 56
+var Modulus= [...]Chunk {0x13481D1F6E5377,0xF623D526202820,0x909D838D726E3B,0xA1EEA9BC3E660A,0xA9FB57DB}
+var R2modp= [...]Chunk {0x9E04F49B9A3787,0x29317218F3CF49,0x54E8C3CF1DBC89,0xBB411A3F7559CA,0x9773E15F}
+const MConst Chunk=0xA75590CEFD89B9
+
+const CURVE_Cof_I int= 1
+var CURVE_Cof=[...]Chunk {0x1,0x0,0x0,0x0,0x0}
+const CURVE_A int= -3
+const CURVE_B_I int= 0
+var CURVE_B= [...]Chunk {0xE58101FEE92B04,0xEBC4AF2F49256A,0x733D0B76B7BF93,0x30D84EA4FE66A7,0x662C61C4}
+var CURVE_Order= [...]Chunk {0x1E0E82974856A7,0x7AA3B561A6F790,0x909D838D718C39,0xA1EEA9BC3E660A,0xA9FB57DB}
+var CURVE_Gx= [...]Chunk {0xA191562E1305F4,0x42C47AAFBC2B79,0xB23A656149AFA1,0xC1CFE7B7732213,0xA3E8EB3C}
+var CURVE_Gy= [...]Chunk {0xABE8F35B25C9BE,0xB6DE39D027001D,0xE14644417E69BC,0x3439C56D7F7B22,0x2D996C82}
diff --git a/version3/go/ROM_C25519_32.go b/version3/go/ROM_C25519_32.go
new file mode 100644
index 0000000..63f5c89
--- /dev/null
+++ b/version3/go/ROM_C25519_32.go
@@ -0,0 +1,36 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package C25519
+
+// Base Bits= 29
+var Modulus= [...]Chunk {0x1FFFFFED,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFFF}
+var R2modp= [...]Chunk {0x169000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+const MConst Chunk=0x13
+
+const CURVE_Cof_I int= 8
+var CURVE_Cof=[...]Chunk {0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+const CURVE_A int= 486662
+const CURVE_B_I int= 0
+var CURVE_B= [...]Chunk {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Order= [...]Chunk {0x1CF5D3ED,0x9318D2,0x1DE73596,0x1DF3BD45,0x14D,0x0,0x0,0x0,0x100000}
+var CURVE_Gx= [...]Chunk {0x9,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Gy= [...]Chunk {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
diff --git a/version3/go/ROM_C25519_64.go b/version3/go/ROM_C25519_64.go
new file mode 100644
index 0000000..5eb088d
--- /dev/null
+++ b/version3/go/ROM_C25519_64.go
@@ -0,0 +1,36 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package C25519
+
+// Base Bits= 56
+var Modulus= [...]Chunk {0xFFFFFFFFFFFFED,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0x7FFFFFFF}
+var R2modp= [...]Chunk {0xA4000000000000,0x5,0x0,0x0,0x0}
+const MConst Chunk=0x13
+
+const CURVE_Cof_I int= 8
+var CURVE_Cof=[...]Chunk {0x8,0x0,0x0,0x0,0x0}
+const CURVE_A int= 486662
+const CURVE_B_I int= 0
+var CURVE_B= [...]Chunk {0x0,0x0,0x0,0x0,0x0}
+var CURVE_Order= [...]Chunk {0x12631A5CF5D3ED,0xF9DEA2F79CD658,0x14DE,0x0,0x10000000}
+var CURVE_Gx= [...]Chunk {0x9,0x0,0x0,0x0,0x0}
+var CURVE_Gy= [...]Chunk {0x0,0x0,0x0,0x0,0x0}
diff --git a/version3/go/ROM_C41417_32.go b/version3/go/ROM_C41417_32.go
new file mode 100644
index 0000000..6785271
--- /dev/null
+++ b/version3/go/ROM_C41417_32.go
@@ -0,0 +1,37 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package C41417
+
+// Base Bits= 60
+var Modulus= [...]Chunk {0xFFFFFFFFFFFFFEF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0x3FFFFFFFFFFFFF}
+var R2modp= [...]Chunk {0x121000,0x0,0x0,0x0,0x0,0x0,0x0}
+const MConst Chunk=0x11
+
+const CURVE_Cof_I int= 8
+var CURVE_Cof=[...]Chunk {0x8,0x0,0x0,0x0,0x0,0x0,0x0}
+const CURVE_A int= 1
+const CURVE_B_I int= 3617
+var CURVE_B= [...]Chunk {0xE21,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Order= [...]Chunk {0xB0E71A5E106AF79,0x1C0338AD63CF181,0x414CF706022B36F,0xFFFFFFFFEB3CC92,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0x7FFFFFFFFFFFF}
+var CURVE_Gx= [...]Chunk {0x4FD3812F3CBC595,0x1A73FAA8537C64C,0x4AB4D6D6BA11130,0x3EC7F57FF35498A,0xE5FCD46369F44C0,0x300218C0631C326,0x1A334905141443}
+var CURVE_Gy= [...]Chunk {0x22,0x0,0x0,0x0,0x0,0x0,0x0}
+
diff --git a/version3/go/ROM_C41417_64.go b/version3/go/ROM_C41417_64.go
new file mode 100644
index 0000000..94d30af
--- /dev/null
+++ b/version3/go/ROM_C41417_64.go
@@ -0,0 +1,36 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package C41417
+
+// Base Bits= 60
+var Modulus= [...]Chunk {0xFFFFFFFFFFFFFEF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0x3FFFFFFFFFFFFF}
+var R2modp= [...]Chunk {0x121000,0x0,0x0,0x0,0x0,0x0,0x0}
+const MConst Chunk=0x11
+
+const CURVE_Cof_I int= 8
+var CURVE_Cof=[...]Chunk {0x8,0x0,0x0,0x0,0x0,0x0,0x0}
+const CURVE_A int= 1
+const CURVE_B_I int= 3617
+var CURVE_B= [...]Chunk {0xE21,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Order= [...]Chunk {0xB0E71A5E106AF79,0x1C0338AD63CF181,0x414CF706022B36F,0xFFFFFFFFEB3CC92,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0x7FFFFFFFFFFFF}
+var CURVE_Gx= [...]Chunk {0x4FD3812F3CBC595,0x1A73FAA8537C64C,0x4AB4D6D6BA11130,0x3EC7F57FF35498A,0xE5FCD46369F44C0,0x300218C0631C326,0x1A334905141443}
+var CURVE_Gy= [...]Chunk {0x22,0x0,0x0,0x0,0x0,0x0,0x0}
diff --git a/version3/go/ROM_ED25519_32.go b/version3/go/ROM_ED25519_32.go
new file mode 100644
index 0000000..c29e251
--- /dev/null
+++ b/version3/go/ROM_ED25519_32.go
@@ -0,0 +1,37 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package ED25519
+
+// Base Bits= 29
+var Modulus= [...]Chunk {0x1FFFFFED,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFFF}
+var R2modp= [...]Chunk {0x169000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+const MConst Chunk= 0x13
+
+const CURVE_Cof_I int= 8
+var CURVE_Cof=[...]Chunk {0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+const CURVE_A int= -1
+const CURVE_B_I int= 0
+var CURVE_B= [...]Chunk {0x135978A3,0xF5A6E50,0x10762ADD,0x149A82,0x1E898007,0x3CBBBC,0x19CE331D,0x1DC56DFF,0x52036C}
+var CURVE_Order= [...]Chunk {0x1CF5D3ED,0x9318D2,0x1DE73596,0x1DF3BD45,0x14D,0x0,0x0,0x0,0x100000}
+var CURVE_Gx= [...]Chunk {0xF25D51A,0xAB16B04,0x969ECB2,0x198EC12A,0xDC5C692,0x1118FEEB,0xFFB0293,0x1A79ADCA,0x216936}
+var CURVE_Gy= [...]Chunk {0x6666658,0x13333333,0x19999999,0xCCCCCCC,0x6666666,0x13333333,0x19999999,0xCCCCCCC,0x666666}
+
diff --git a/version3/go/ROM_ED25519_64.go b/version3/go/ROM_ED25519_64.go
new file mode 100644
index 0000000..073dcd2
--- /dev/null
+++ b/version3/go/ROM_ED25519_64.go
@@ -0,0 +1,38 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package ED25519
+
+// Base Bits= 56
+var Modulus= [...]Chunk {0xFFFFFFFFFFFFED,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0x7FFFFFFF}
+var R2modp= [...]Chunk {0xA4000000000000,0x5,0x0,0x0,0x0}
+const MConst Chunk= 0x13
+
+const CURVE_Cof_I int= 8
+var CURVE_Cof=[...]Chunk {0x8,0x0,0x0,0x0,0x0}
+const CURVE_A int= -1
+const CURVE_B_I int= 0
+var CURVE_B= [...]Chunk {0xEB4DCA135978A3,0xA4D4141D8AB75,0x797779E8980070,0x2B6FFE738CC740,0x52036CEE}
+var CURVE_Order= [...]Chunk {0x12631A5CF5D3ED,0xF9DEA2F79CD658,0x14DE,0x0,0x10000000}
+var CURVE_Gx= [...]Chunk {0x562D608F25D51A,0xC7609525A7B2C9,0x31FDD6DC5C692C,0xCD6E53FEC0A4E2,0x216936D3}
+var CURVE_Gy= [...]Chunk {0x66666666666658,0x66666666666666,0x66666666666666,0x66666666666666,0x66666666}
+
+
diff --git a/version3/go/ROM_FP256BN_32.go b/version3/go/ROM_FP256BN_32.go
new file mode 100644
index 0000000..4dc29d4
--- /dev/null
+++ b/version3/go/ROM_FP256BN_32.go
@@ -0,0 +1,56 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package FP256BN
+
+// Base Bits= 28
+var Modulus= [...]Chunk {0xED33013,0x292DDBA,0x80A82D3,0x65FB129,0x49F0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF}
+var R2modp= [...]Chunk {0x3B9F8B,0xEDE3363,0xFEC54E8,0x92FFEE9,0x3C55F79,0x13C1C06,0xC0123FA,0xA12F2EA,0xE559B2A,0x8}
+const MConst Chunk=0x537E5E5
+
+const CURVE_Cof_I int= 1
+const CURVE_A int= 0
+const CURVE_B_I int= 3
+var CURVE_B= [...]Chunk {0x3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Order= [...]Chunk {0x10B500D,0x2D536CD,0x9921AF6,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF}
+var CURVE_Gx= [...]Chunk {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Gy= [...]Chunk {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+
+var Fra= [...]Chunk {0xF943106,0x760328A,0xAB28F74,0x71511E3,0x7CF39A1,0x8DDB086,0x52D1A6E,0xCA786F3,0xD617662,0x3}
+var Frb= [...]Chunk {0xF3EFF0D,0xB32AB2F,0xD57F35E,0xF4A9F45,0xCCFD33A,0xD113693,0x819CB83,0x3584819,0x29E899D,0xC}
+var CURVE_Bnx= [...]Chunk {0xB0A801,0x82F5C03,0x68,0x0,0x0,0x0,0x0,0x0,0x0,0x0} 
+var CURVE_Cof= [...]Chunk {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Cru= [...]Chunk {0x3A1B807,0x1C0A24A,0x32D1EDB,0xD79DF19,0x8659BCD,0x4092101,0x13988E1,0x0,0x0,0x0}
+var CURVE_Pxa= [...]Chunk {0x9C09EFB,0x2616B68,0xF843CD2,0x539A12B,0x13ACE1C,0x577C289,0x28560F,0xB4C96C2,0xE0C3350,0xF}
+var CURVE_Pxb= [...]Chunk {0x37E6A2B,0x69ED34A,0x3589D2,0x78E287D,0x3B924DD,0xC637D81,0x4DB5AE1,0x738AC05,0xEA66057,0x4}
+var CURVE_Pya= [...]Chunk {0xEDC27FF,0x9B481B,0x15848E9,0x24758D6,0xE51EFCB,0x75124E3,0x376770D,0xC542A3B,0x2046E7,0x7}
+var CURVE_Pyb= [...]Chunk {0xAAD049B,0x1281114,0xA98B3E0,0xBE80821,0x29F8B4C,0x49297EB,0x42EEA6,0xD388C29,0x554E3BC,0x0}
+var CURVE_W=[2][10]Chunk {{0xB054003,0xF0036E1,0xE78663A,0xFFFFFFF,0xFFFF,0x0,0x0,0x0,0x0,0x0},{0x1615001,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}
+var CURVE_SB=[2][2][10]Chunk {{{0xC669004,0xF5EEEE7,0xE78670B,0xFFFFFFF,0xFFFF,0x0,0x0,0x0,0x0,0x0},{0x1615001,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x1615001,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x606100A,0x3D4FFEB,0xB19B4BB,0x65FB129,0x49D0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF}}}
+var CURVE_WB=[4][10]Chunk {{0xD30A800,0x20678F0,0x4D2CC10,0x5555555,0x5555,0x0,0x0,0x0,0x0,0x0},{0xD7DC805,0xD6764C0,0xBC3AD1A,0x8FBEA10,0x4467DE,0x8061601,0xD105EB,0x0,0x0,0x0},{0xF173803,0xACB6061,0x5E1D6C1,0x47DF508,0x82233EF,0xC030B00,0x6882F5,0x0,0x0,0x0},{0xE91F801,0x26530F6,0x4D2CCE1,0x5555555,0x5555,0x0,0x0,0x0,0x0,0x0}}
+var CURVE_BB=[4][4][10]Chunk {{{0x5AA80D,0xAA5DACA,0x9921A8D,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF},{0x5AA80C,0xAA5DACA,0x9921A8D,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF},{0x5AA80C,0xAA5DACA,0x9921A8D,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF},{0x1615002,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x1615001,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x5AA80C,0xAA5DACA,0x9921A8D,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF},{0x5AA80D,0xAA5DACA,0x9921A8D,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF},{0x5AA80C,0xAA5DACA,0x9921A8D,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF}},{{0x1615002,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1615001,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1615001,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1615001,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0xB0A802,0x82F5C03,0x68,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x2C2A002,0xBD700C,0x1A2,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xFAA000A,0x2767EC6,0x9921A25,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF},{0xB0A802,0x82F5C03,0x68,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}}
+
+
+const USE_GLV bool=true
+const USE_GS_G2 bool=true
+const USE_GS_GT bool=true	
+const GT_STRONG bool=false
+
diff --git a/version3/go/ROM_FP256BN_64.go b/version3/go/ROM_FP256BN_64.go
new file mode 100644
index 0000000..1771900
--- /dev/null
+++ b/version3/go/ROM_FP256BN_64.go
@@ -0,0 +1,54 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package FP256BN
+
+// Base Bits= 56
+var Modulus= [...]Chunk {0x292DDBAED33013,0x65FB12980A82D3,0x5EEE71A49F0CDC,0xFFFCF0CD46E5F2,0xFFFFFFFF}
+var R2modp= [...]Chunk {0xEDE336303B9F8B,0x92FFEE9FEC54E8,0x13C1C063C55F79,0xA12F2EAC0123FA,0x8E559B2A}
+const MConst Chunk=0x6C964E0537E5E5
+
+const CURVE_Cof_I int= 1
+const CURVE_A int= 0
+const CURVE_B_I int= 3
+var CURVE_B= [...]Chunk {0x3,0x0,0x0,0x0,0x0}
+var CURVE_Order= [...]Chunk {0x2D536CD10B500D,0x65FB1299921AF6,0x5EEE71A49E0CDC,0xFFFCF0CD46E5F2,0xFFFFFFFF}
+var CURVE_Gx= [...]Chunk {0x1,0x0,0x0,0x0,0x0}
+var CURVE_Gy= [...]Chunk {0x2,0x0,0x0,0x0,0x0}
+
+var Fra= [...]Chunk {0x760328AF943106,0x71511E3AB28F74,0x8DDB0867CF39A1,0xCA786F352D1A6E,0x3D617662}
+var Frb= [...]Chunk {0xB32AB2FF3EFF0D,0xF4A9F45D57F35E,0xD113693CCFD33A,0x3584819819CB83,0xC29E899D}
+var CURVE_Bnx= [...]Chunk {0x82F5C030B0A801,0x68,0x0,0x0,0x0}
+var CURVE_Cof= [...]Chunk {0x1,0x0,0x0,0x0,0x0}
+var CURVE_Cru= [...]Chunk {0x1C0A24A3A1B807,0xD79DF1932D1EDB,0x40921018659BCD,0x13988E1,0x0}
+var CURVE_Pxa= [...]Chunk {0x2616B689C09EFB,0x539A12BF843CD2,0x577C28913ACE1C,0xB4C96C2028560F,0xFE0C3350}
+var CURVE_Pxb= [...]Chunk {0x69ED34A37E6A2B,0x78E287D03589D2,0xC637D813B924DD,0x738AC054DB5AE1,0x4EA66057}
+var CURVE_Pya= [...]Chunk {0x9B481BEDC27FF,0x24758D615848E9,0x75124E3E51EFCB,0xC542A3B376770D,0x702046E7}
+var CURVE_Pyb= [...]Chunk {0x1281114AAD049B,0xBE80821A98B3E0,0x49297EB29F8B4C,0xD388C29042EEA6,0x554E3BC}
+var CURVE_W=[2][5]Chunk {{0xF0036E1B054003,0xFFFFFFFE78663A,0xFFFF,0x0,0x0},{0x5EB8061615001,0xD1,0x0,0x0,0x0}}
+var CURVE_SB=[2][2][5]Chunk {{{0xF5EEEE7C669004,0xFFFFFFFE78670B,0xFFFF,0x0,0x0},{0x5EB8061615001,0xD1,0x0,0x0,0x0}},{{0x5EB8061615001,0xD1,0x0,0x0,0x0},{0x3D4FFEB606100A,0x65FB129B19B4BB,0x5EEE71A49D0CDC,0xFFFCF0CD46E5F2,0xFFFFFFFF}}}
+var CURVE_WB=[4][5]Chunk {{0x20678F0D30A800,0x55555554D2CC10,0x5555,0x0,0x0},{0xD6764C0D7DC805,0x8FBEA10BC3AD1A,0x806160104467DE,0xD105EB,0x0},{0xACB6061F173803,0x47DF5085E1D6C1,0xC030B0082233EF,0x6882F5,0x0},{0x26530F6E91F801,0x55555554D2CCE1,0x5555,0x0,0x0}}
+var CURVE_BB=[4][4][5]Chunk {{{0xAA5DACA05AA80D,0x65FB1299921A8D,0x5EEE71A49E0CDC,0xFFFCF0CD46E5F2,0xFFFFFFFF},{0xAA5DACA05AA80C,0x65FB1299921A8D,0x5EEE71A49E0CDC,0xFFFCF0CD46E5F2,0xFFFFFFFF},{0xAA5DACA05AA80C,0x65FB1299921A8D,0x5EEE71A49E0CDC,0xFFFCF0CD46E5F2,0xFFFFFFFF},{0x5EB8061615002,0xD1,0x0,0x0,0x0}},{{0x5EB8061615001,0xD1,0x0,0x0,0x0},{0xAA5DACA05AA80C,0x65FB1299921A8D,0x5EEE71A49E0CDC,0xFFFCF0CD46E5F2,0xFFFFFFFF},{0xAA5DACA05AA80D,0x65FB1299921A8D,0x5EEE71A49E0CDC,0xFFFCF0CD46E5F2,0xFFFFFFFF},{0xAA5DACA05AA80C,0x65FB1299921A8D,0x5EEE71A49E0CDC,0xFFFCF0CD46E5F2,0xFFFFFFFF}},{{0x5EB8061615002,0xD1,0x0,0x0,0x0},{0x5EB8061615001,0xD1,0x0,0x0,0x0},{0x5EB8061615001,0xD1,0x0,0x0,0x0},{0x5EB8061615001,0xD1,0x0,0x0,0x0}},{{0x82F5C030B0A802,0x68,0x0,0x0,0x0},{0xBD700C2C2A002,0x1A2,0x0,0x0,0x0},{0x2767EC6FAA000A,0x65FB1299921A25,0x5EEE71A49E0CDC,0xFFFCF0CD46E5F2,0xFFFFFFFF},{0x82F5C030B0A802,0x68,0x0,0x0,0x0}}}
+
+const USE_GLV bool=true
+const USE_GS_G2 bool=true
+const USE_GS_GT bool=true	
+const GT_STRONG bool=false
diff --git a/version3/go/ROM_FP512BN_32.go b/version3/go/ROM_FP512BN_32.go
new file mode 100644
index 0000000..bb3675a
--- /dev/null
+++ b/version3/go/ROM_FP512BN_32.go
@@ -0,0 +1,57 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package FP512BN
+
+// Base Bits= 29
+
+var Modulus= [...]Chunk {0x2ADEF33,0x7594049,0x131919ED,0x14AB9CBE,0x16FE1916,0x12EF5591,0x2E39231,0x3D597D3,0x55146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF}
+var R2modp= [...]Chunk {0xFD68B47,0xFCF5D2C,0x437675A,0x1BBC3FBF,0x1411E413,0x13453559,0x10B5639,0x1C34CE79,0x6D476BF,0xFD05F2B,0x15D17C28,0x6C9F76E,0x1C2375B3,0x78CCE9B,0x15F0AB33,0x1960F32E,0x1A8D44E,0x57A38}
+const MConst Chunk=0x1CCC5C05
+
+const CURVE_Cof_I int= 1
+const CURVE_A int= 0
+const CURVE_B_I int= 3
+var CURVE_B= [...]Chunk {0x3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Order= [...]Chunk {0x119A09ED,0x153252FA,0x1E68AD01,0x627C09,0x79A34A1,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF}
+var CURVE_Gx= [...]Chunk {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Gy= [...]Chunk {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+
+var Fra= [...]Chunk {0x14B73AB2,0x4B0BD8F,0xABB47D,0x2A29EC4,0x18681E17,0x104069DE,0x12EED67D,0x1553D0A5,0x398E9F8,0x7971034,0xAC9AF23,0x52DEF23,0x14EA18A5,0x1463E345,0x6DE465A,0x17F212B4,0x1AA9CF5B,0xF7B8}
+var Frb= [...]Chunk {0xDF6B481,0x2A882B9,0x126D6570,0x1208FDFA,0x1E95FAFF,0x2AEEBB2,0xFF4BBB4,0xE81C72D,0x1B85CD6,0xF67746,0x56549CD,0xC68B6EC,0x776A178,0x8925C3B,0x1921B9A5,0x80DED4B,0x55630A4,0x70847}
+var CURVE_Bnx= [...]Chunk {0x1E1BD80F,0x59835DA,0xC3DFC04,0x5EB8061,0x688,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Cof= [...]Chunk {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Cru= [...]Chunk {0x1C79298A,0x1838B104,0x2C5F052,0x1DCCF337,0x6092AEC,0x4B35F29,0x1EB361E,0x11384EA,0x3074B20,0x17BB08FD,0x3A8B3E3,0xD70D66F,0x3D2A614,0x1CF63EE4,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF}
+var CURVE_Pxa= [...]Chunk {0xDB646B5,0x183D4B70,0x1CBFFA3,0x11F0E632,0x1C78F221,0x1F10DE5D,0x171B715E,0xF0C6A29,0x10B02453,0xBE63C66,0xE6D5F69,0x166B1E1B,0x4BBBD29,0x179E750F,0x6E9D04,0xC912B10,0x1339E138,0x1D8B2}
+var CURVE_Pxb= [...]Chunk {0x1A8AE0E9,0xDAE5F7E,0x22446CF,0x1948239B,0x15ADCE40,0xB709C1E,0x18357943,0xE50AA4D,0x19781E22,0x12B35CA6,0x11DAA2C0,0x18D8DDE4,0x5EA656D,0x15F45A41,0xD311A02,0xCFCD913,0x13CBF850,0x240E0}
+var CURVE_Pya= [...]Chunk {0xDDE67A1,0x12401895,0x17BEE178,0x142F5AC2,0xB7BC5CD,0x92A1404,0x1A3B748C,0x17BD82A7,0x14B6CD18,0xAC34CE,0x1740FB97,0x1ECC15F9,0x17085B1D,0x1D1BA793,0x1BD6AC32,0x18F70525,0xC84C827,0x3780F}
+var CURVE_Pyb= [...]Chunk {0x84F8E8B,0xC5B8C36,0xFDD85A1,0xB84449,0x19C08DFF,0x56BF713,0x1C5290C4,0x187C5CA0,0x1DA2897F,0x24B0CA0,0x326D8F4,0x2310CF6,0x1021438C,0xFBAEC8F,0xD9030C5,0x1CF06358,0x1CEC8B04,0x28D1D}
+var CURVE_W=[2][18]Chunk {{0x9834583,0x887C4BA,0x5A85CFC,0xBF7223A,0xF63FE96,0x1FFFFFFE,0x1FFFFFFF,0x1FFFFFFF,0xFFFFFF,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1C37B01F,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}
+var CURVE_SB=[2][2][18]Chunk {{{0xD4B9564,0x1D575904,0xD2C64F3,0x202177,0xF63F186,0x1FFFFFFE,0x1FFFFFFF,0x1FFFFFFF,0xFFFFFF,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x156259CE,0xA01E744,0x5ECB4F9,0x148B7B47,0x79A2790,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF}},{{0x1C37B01F,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x9834583,0x887C4BA,0x5A85CFC,0xBF7223A,0xF63FE96,0x1FFFFFFE,0x1FFFFFFF,0x1FFFFFFF,0xFFFFFF,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}}
+var CURVE_WB=[4][18]Chunk {{0x155A29F0,0x16D59B55,0xF4C305,0x18858C0B,0x5215FBF,0xAAAAAAA,0x15555555,0xAAAAAAA,0x555555,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x2355D4B,0x1758095D,0x1FE13C5F,0x41F83FA,0xBB5E5CF,0x97D4EF1,0xB503D62,0x172C0C9B,0x16315274,0x15E1A9A8,0x859835D,0x2C3DFC0,0x105EB806,0x68,0x0,0x0,0x0,0x0},{0x289AAD,0x1E781F9C,0x60F9C31,0x1505822E,0x15DAF62B,0x4BEA778,0x15A81EB1,0xB96064D,0xB18A93A,0x1AF0D4D4,0x42CC1AE,0x161EFE0,0x82F5C03,0x34,0x0,0x0,0x0,0x0},{0x192279D1,0xBA52F9F,0x878CAFD,0xCAE8B48,0x52152AF,0xAAAAAAA,0x15555555,0xAAAAAAA,0x555555,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}
+var CURVE_BB=[4][4][18]Chunk {{{0x1E1BD810,0x59835DA,0xC3DFC04,0x5EB8061,0x688,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1E1BD80F,0x59835DA,0xC3DFC04,0x5EB8061,0x688,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1E1BD80F,0x59835DA,0xC3DFC04,0x5EB8061,0x688,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x156259CF,0xA01E744,0x5ECB4F9,0x148B7B47,0x79A2790,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF}},{{0x1C37B01F,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x137E31DE,0xF9A1D1F,0x122AB0FD,0x1A76FBA8,0x79A2E18,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF},{0x137E31DD,0xF9A1D1F,0x122AB0FD,0x1A76FBA8,0x79A2E18,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF},{0x137E31DE,0xF9A1D1F,0x122AB0FD,0x1A76FBA8,0x79A2E18,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF}},{{0x1C37B01E,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1C37B01F,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1C37B01F,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1C37B01F,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x137E31DF,0xF9A1D1F,0x122AB0FD,0x1A76FBA8,0x79A2E18,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF},{0x192AA9AF,0x1ED17B8E,0xD70BCF0,0x8B47A84,0x79A1A80,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF},{0x1C37B01D,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x137E31DF,0xF9A1D1F,0x122AB0FD,0x1A76FBA8,0x79A2E18,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF}}}
+
+
+const USE_GLV bool=true
+const USE_GS_G2 bool=true
+const USE_GS_GT bool=true	
+const GT_STRONG bool=false
+
diff --git a/version3/go/ROM_FP512BN_64.go b/version3/go/ROM_FP512BN_64.go
new file mode 100644
index 0000000..6f6ae44
--- /dev/null
+++ b/version3/go/ROM_FP512BN_64.go
@@ -0,0 +1,55 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package FP512BN
+
+
+// Base Bits= 60
+var Modulus= [...]Chunk {0x4EB280922ADEF33,0x6A55CE5F4C6467B,0xC65DEAB236FE191,0xCF1EACBE98B8E48,0x3C111B0EF455146,0xA1D8CB5307C0BBE,0xFFFF9EC7F01C60B,0xFFFFFFFFFFFFFFF,0xFFFFFFFF}
+var R2modp= [...]Chunk {0x1FA6DCEF99812E9,0xAB3452895A0B74E,0xC53EA988C079E1E,0x1E90E033BA630B9,0xF1EA41C0714D8B0,0xE72785387509E28,0xD86794F834DAB00,0x9757C2ACCD342A1,0x44ECB079}
+const MConst Chunk=0x692A189FCCC5C05
+
+const CURVE_Cof_I int= 1
+const CURVE_A int= 0
+const CURVE_B_I int= 3
+var CURVE_B= [...]Chunk {0x3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Order= [...]Chunk {0x6A64A5F519A09ED,0x10313E04F9A2B40,0xC65DEAB2679A34A,0xCF1EACBE98B8E48,0x3C111B0EF445146,0xA1D8CB5307C0BBE,0xFFFF9EC7F01C60B,0xFFFFFFFFFFFFFFF,0xFFFFFFFF}
+var CURVE_Gx= [...]Chunk {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Gy= [...]Chunk {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+
+var Fra= [...]Chunk {0x49617B1F4B73AB2,0x71514F6202AED1F,0xF6080D3BD8681E1,0xF8AA9E852CBBB59,0xC8CF2E2068398E9,0x8A5296F791AB26B,0x196A8C7C68B4EA1,0xCF5BBF9095A1B79,0x1EF71AA9}
+var Frb= [...]Chunk {0x5510572DF6B481,0xF9047EFD49B595C,0xD055DD765E95FAF,0xD6740E396BFD2EE,0x7341ECEE8C1B85C,0x1786345B7615952,0xE695124B876776A,0x30A4406F6A5E486,0xE108E556}
+var CURVE_Bnx= [...]Chunk {0xB306BB5E1BD80F,0x82F5C030B0F7F01,0x68,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Cof= [...]Chunk {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Cru= [...]Chunk {0xB0716209C79298A,0xCEE6799B8B17C14,0x78966BE526092AE,0x20089C27507ACD8,0xF8EF7611FA3074B,0x6146B86B378EA2C,0xFFFF9EC7DC83D2A,0xFFFFFFFFFFFFFFF,0xFFFFFFFF}
+var CURVE_Pxa= [...]Chunk {0xF07A96E0DB646B5,0x18F87319072FFE8,0x7BE21BCBBC78F22,0x537863514DC6DC5,0xDA57CC78CD0B024,0xD29B358F0DB9B57,0x7412F3CEA1E4BBB,0xE138648958801BA,0x3B165339}
+var CURVE_Pxb= [...]Chunk {0xDB5CBEFDA8AE0E9,0xCA411CD88911B3,0xD6E1383D5ADCE4,0x227285526E0D5E5,0xB02566B94D9781E,0x56DC6C6EF2476A8,0x680ABE8B4825EA6,0xF85067E6C89B4C4,0x481C13CB}
+var CURVE_Pya= [...]Chunk {0x2480312ADDE67A1,0xDA17AD615EFB85E,0x312542808B7BC5C,0x18BDEC153E8EDD2,0xE5C158699D4B6CD,0xB1DF660AFCDD03E,0xB0CBA374F277085,0xC827C7B8292EF5A,0x6F01EC84}
+var CURVE_Pyb= [...]Chunk {0x58B7186C84F8E8B,0xF05C2224BF76168,0x10AD7EE279C08DF,0x7FC3E2E50714A43,0x3D04961941DA289,0x38C118867B0C9B6,0xC315F75D91F0214,0x8B04E7831AC3640,0x51A3BCEC}
+var CURVE_W=[2][9]Chunk {{0x110F89749834583,0x65FB911D16A173F,0xFFFFFFFFCF63FE9,0xFFFFFFFFFFFFFFF,0xFFFF,0x0,0x0,0x0,0x0},{0x1660D76BC37B01F,0x5EB806161EFE02,0xD1,0x0,0x0,0x0,0x0,0x0,0x0}}
+var CURVE_SB=[2][2][9]Chunk {{{0xFAAEB208D4B9564,0x601010BBB4B193C,0xFFFFFFFFCF63F18,0xFFFFFFFFFFFFFFF,0xFFFF,0x0,0x0,0x0,0x0},{0x5403CE8956259CE,0xA45BDA397B2D3E,0xC65DEAB2679A279,0xCF1EACBE98B8E48,0x3C111B0EF445146,0xA1D8CB5307C0BBE,0xFFFF9EC7F01C60B,0xFFFFFFFFFFFFFFF,0xFFFFFFFF}},{{0x1660D76BC37B01F,0x5EB806161EFE02,0xD1,0x0,0x0,0x0,0x0,0x0,0x0},{0x110F89749834583,0x65FB911D16A173F,0xFFFFFFFFCF63FE9,0xFFFFFFFFFFFFFFF,0xFFFF,0x0,0x0,0x0,0x0}}}
+var CURVE_WB=[4][9]Chunk {{0x6DAB36AB55A29F0,0xFC42C60583D30C1,0x5555555545215FB,0x555555555555555,0x5555,0x0,0x0,0x0,0x0},{0xEEB012BA2355D4B,0xF20FC1FD7F84F17,0x892FA9DE2BB5E5C,0x74B96064DAD40F5,0xD76BC3535163152,0x806161EFE021660,0xD105EB,0x0,0x0},{0x7CF03F380289AAD,0xBA82C117183E70C,0xC497D4EF15DAF62,0x3A5CB0326D6A07A,0x6BB5E1A9A8B18A9,0xC030B0F7F010B30,0x6882F5,0x0,0x0},{0x574A5F3F92279D1,0xF65745A421E32BF,0x55555555452152A,0x555555555555555,0x5555,0x0,0x0,0x0,0x0}}
+var CURVE_BB=[4][4][9]Chunk {{{0xB306BB5E1BD810,0x82F5C030B0F7F01,0x68,0x0,0x0,0x0,0x0,0x0,0x0},{0xB306BB5E1BD80F,0x82F5C030B0F7F01,0x68,0x0,0x0,0x0,0x0,0x0,0x0},{0xB306BB5E1BD80F,0x82F5C030B0F7F01,0x68,0x0,0x0,0x0,0x0,0x0,0x0},{0x5403CE8956259CF,0xA45BDA397B2D3E,0xC65DEAB2679A279,0xCF1EACBE98B8E48,0x3C111B0EF445146,0xA1D8CB5307C0BBE,0xFFFF9EC7F01C60B,0xFFFFFFFFFFFFFFF,0xFFFFFFFF}},{{0x1660D76BC37B01F,0x5EB806161EFE02,0xD1,0x0,0x0,0x0,0x0,0x0,0x0},{0x5F343A3F37E31DE,0x8D3B7DD448AAC3F,0xC65DEAB2679A2E1,0xCF1EACBE98B8E48,0x3C111B0EF445146,0xA1D8CB5307C0BBE,0xFFFF9EC7F01C60B,0xFFFFFFFFFFFFFFF,0xFFFFFFFF},{0x5F343A3F37E31DD,0x8D3B7DD448AAC3F,0xC65DEAB2679A2E1,0xCF1EACBE98B8E48,0x3C111B0EF445146,0xA1D8CB5307C0BBE,0xFFFF9EC7F01C60B,0xFFFFFFFFFFFFFFF,0xFFFFFFFF},{0x5F343A3F37E31DE,0x8D3B7DD448AAC3F,0xC65DEAB2679A2E1,0xCF1EACBE98B8E48,0x3C111B0EF445146,0xA1D8CB5307C0BBE,0xFFFF9EC7F01C60B,0xFFFFFFFFFFFFFFF,0xFFFFFFFF}},{{0x1660D76BC37B01E,0x5EB806161EFE02,0xD1,0x0,0x0,0x0,0x0,0x0,0x0},{0x1660D76BC37B01F,0x5EB806161EFE02,0xD1,0x0,0x0,0x0,0x0,0x0,0x0},{0x1660D76BC37B01F,0x5EB806161EFE02,0xD1,0x0,0x0,0x0,0x0,0x0,0x0},{0x1660D76BC37B01F,0x5EB806161EFE02,0xD1,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x5F343A3F37E31DF,0x8D3B7DD448AAC3F,0xC65DEAB2679A2E1,0xCF1EACBE98B8E48,0x3C111B0EF445146,0xA1D8CB5307C0BBE,0xFFFF9EC7F01C60B,0xFFFFFFFFFFFFFFF,0xFFFFFFFF},{0x3DA2F71D92AA9AF,0x45A3D4235C2F3C,0xC65DEAB2679A1A8,0xCF1EACBE98B8E48,0x3C111B0EF445146,0xA1D8CB5307C0BBE,0xFFFF9EC7F01C60B,0xFFFFFFFFFFFFFFF,0xFFFFFFFF},{0x1660D76BC37B01D,0x5EB806161EFE02,0xD1,0x0,0x0,0x0,0x0,0x0,0x0},{0x5F343A3F37E31DF,0x8D3B7DD448AAC3F,0xC65DEAB2679A2E1,0xCF1EACBE98B8E48,0x3C111B0EF445146,0xA1D8CB5307C0BBE,0xFFFF9EC7F01C60B,0xFFFFFFFFFFFFFFF,0xFFFFFFFF}}}
+
+const USE_GLV bool=true
+const USE_GS_G2 bool=true
+const USE_GS_GT bool=true	
+const GT_STRONG bool=false
diff --git a/version3/go/ROM_GOLDILOCKS_32.go b/version3/go/ROM_GOLDILOCKS_32.go
new file mode 100644
index 0000000..3d31cba
--- /dev/null
+++ b/version3/go/ROM_GOLDILOCKS_32.go
@@ -0,0 +1,36 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package GOLDILOCKS
+
+// Base Bits= 29
+var Modulus= [...]Chunk {0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FDFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFF}
+var R2modp= [...]Chunk {0x0,0x10,0x0,0x0,0x0,0x0,0x0,0x0,0x3000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+const MConst Chunk=0x1
+
+const CURVE_Cof_I int= 4
+var CURVE_Cof=[...]Chunk {0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+const CURVE_A int= 1
+const CURVE_B_I int= -39081
+var CURVE_B= [...]Chunk {0x1FFF6756,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FDFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFF}
+var CURVE_Order= [...]Chunk {0xB5844F3,0x1BC61495,0x1163D548,0x1984E51B,0x3690216,0xDA4D76B,0xFA7113B,0x1FEF9944,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FF}
+var CURVE_Gx= [...]Chunk {0x15555555,0xAAAAAAA,0x15555555,0xAAAAAAA,0x15555555,0xAAAAAAA,0x15555555,0x152AAAAA,0xAAAAAAA,0x15555555,0xAAAAAAA,0x15555555,0xAAAAAAA,0x15555555,0xAAAAAAA,0x1555}
+var CURVE_Gy= [...]Chunk {0xA9386ED,0x1757DE6F,0x13681AF6,0x19657DA3,0x3098BBB,0x12C19D15,0x12E03595,0xE515B18,0x17B7E36D,0x1AC426E,0xDBB5E8,0x10D8560,0x159D6205,0xB8246D9,0x17A58D2B,0x15C0}
diff --git a/version3/go/ROM_GOLDILOCKS_64.go b/version3/go/ROM_GOLDILOCKS_64.go
new file mode 100644
index 0000000..3536fdf
--- /dev/null
+++ b/version3/go/ROM_GOLDILOCKS_64.go
@@ -0,0 +1,37 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package GOLDILOCKS
+
+// Base Bits= 58
+var Modulus= [...]Chunk {0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FBFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFF}
+var R2modp= [...]Chunk {0x200000000,0x0,0x0,0x0,0x3000000,0x0,0x0,0x0}
+const MConst Chunk=0x1
+
+const CURVE_Cof_I int= 4
+var CURVE_Cof=[...]Chunk {0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+const CURVE_A int= 1
+const CURVE_B_I int= -39081
+var CURVE_B= [...]Chunk {0x3FFFFFFFFFF6756,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FBFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFF}
+var CURVE_Order= [...]Chunk {0x378C292AB5844F3,0x3309CA37163D548,0x1B49AED63690216,0x3FDF3288FA7113B,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0xFFFFFFFFFF}
+var CURVE_Gx= [...]Chunk {0x155555555555555,0x155555555555555,0x155555555555555,0x2A5555555555555,0x2AAAAAAAAAAAAAA,0x2AAAAAAAAAAAAAA,0x2AAAAAAAAAAAAAA,0x2AAAAAAAAAA}
+var CURVE_Gy= [...]Chunk {0x2EAFBCDEA9386ED,0x32CAFB473681AF6,0x25833A2A3098BBB,0x1CA2B6312E03595,0x35884DD7B7E36D,0x21B0AC00DBB5E8,0x17048DB359D6205,0x2B817A58D2B}
+
diff --git a/version3/go/ROM_HIFIVE_32.go b/version3/go/ROM_HIFIVE_32.go
new file mode 100644
index 0000000..99367c1
--- /dev/null
+++ b/version3/go/ROM_HIFIVE_32.go
@@ -0,0 +1,36 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package HIFIVE
+
+// Base Bits= 29
+var Modulus= [...]Chunk {0x1FFFFFFD,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFF}
+var R2modp= [...]Chunk {0x9000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+const MConst Chunk=0x3
+
+const CURVE_Cof_I int= 8
+var CURVE_Cof=[...]Chunk {0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+const CURVE_A int= 1
+const CURVE_B_I int= 11111
+var CURVE_B= [...]Chunk {0x2B67,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Order= [...]Chunk {0x1E9FA805,0x197CACB9,0x1E4EEA9E,0x17AD70F,0x1FA9850C,0x38A0A,0x0,0x0,0x0,0x0,0x0,0x4000}
+var CURVE_Gx= [...]Chunk {0xC,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Gy= [...]Chunk {0x5FE8632,0x15F63428,0xD976C4,0x1AACA194,0x35B6DB5,0x8E3F7A,0x52D1B0E,0xF0A7A36,0x1C161D00,0x8170C70,0x1185AD59,0x181B}
diff --git a/version3/go/ROM_HIFIVE_64.go b/version3/go/ROM_HIFIVE_64.go
new file mode 100644
index 0000000..0990a5d
--- /dev/null
+++ b/version3/go/ROM_HIFIVE_64.go
@@ -0,0 +1,36 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package HIFIVE
+
+// Base Bits= 60
+var Modulus= [...]Chunk {0xFFFFFFFFFFFFFFD,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFF}
+var R2modp= [...]Chunk {0x9000000000000,0x0,0x0,0x0,0x0,0x0}
+const MConst Chunk=0x3
+
+const CURVE_Cof_I int= 8
+var CURVE_Cof=[...]Chunk {0x8,0x0,0x0,0x0,0x0,0x0}
+const CURVE_A int= 1
+const CURVE_B_I int= 11111
+var CURVE_B= [...]Chunk {0x2B67,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Order= [...]Chunk {0xB2F95973E9FA805,0xC0BD6B87F93BAA7,0x71415FA9850,0x0,0x0,0x200000000}
+var CURVE_Gx= [...]Chunk {0xC,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Gy= [...]Chunk {0x2BEC68505FE8632,0x5D5650CA0365DB1,0x3811C7EF435B6DB,0x7853D1B14B46C,0x56502E18E1C161D,0xC0DC616B}
diff --git a/version3/go/ROM_NIST256_32.go b/version3/go/ROM_NIST256_32.go
new file mode 100644
index 0000000..4da5bdf
--- /dev/null
+++ b/version3/go/ROM_NIST256_32.go
@@ -0,0 +1,36 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package NIST256
+
+// Base Bits= 28
+var Modulus= [...]Chunk {0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFF,0x0,0x0,0x1000000,0x0,0xFFFFFFF,0xF}
+var R2modp= [...]Chunk {0x50000,0x300000,0x0,0x0,0xFFFFFFA,0xFFFFFBF,0xFFFFEFF,0xFFFAFFF,0x2FFFF,0x0}
+const MConst Chunk=0x1
+
+const CURVE_Cof_I int= 1
+var CURVE_Cof=[...]Chunk {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+const CURVE_A int= -3
+const CURVE_B_I int= 0
+var CURVE_B= [...]Chunk {0x7D2604B,0xCE3C3E2,0x3B0F63B,0x6B0CC5,0x6BC651D,0x5576988,0x7B3EBBD,0xAA3A93E,0xAC635D8,0x5}
+var CURVE_Order= [...]Chunk {0xC632551,0xB9CAC2F,0x79E84F3,0xFAADA71,0xFFFBCE6,0xFFFFFFF,0xFFFFFF,0x0,0xFFFFFFF,0xF}
+var CURVE_Gx= [...]Chunk {0x898C296,0xA13945D,0xB33A0F4,0x7D812DE,0xF27703,0xE563A44,0x7F8BCE6,0xE12C424,0xB17D1F2,0x6}
+var CURVE_Gy= [...]Chunk {0x7BF51F5,0xB640683,0x15ECECB,0x33576B3,0xE162BCE,0x4A7C0F9,0xB8EE7EB,0xFE1A7F9,0xFE342E2,0x4}
diff --git a/version3/go/ROM_NIST256_64.go b/version3/go/ROM_NIST256_64.go
new file mode 100644
index 0000000..4797ec1
--- /dev/null
+++ b/version3/go/ROM_NIST256_64.go
@@ -0,0 +1,36 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package NIST256
+
+// Base Bits= 56
+var Modulus= [...]Chunk {0xFFFFFFFFFFFFFF,0xFFFFFFFFFF,0x0,0x1000000,0xFFFFFFFF}
+var R2modp= [...]Chunk {0x3000000050000,0x0,0xFFFFFBFFFFFFFA,0xFFFAFFFFFFFEFF,0x2FFFF}
+const MConst Chunk=0x1
+
+const CURVE_Cof_I int= 1
+var CURVE_Cof=[...]Chunk {0x1,0x0,0x0,0x0,0x0}
+const CURVE_A int= -3
+const CURVE_B_I int= 0
+var CURVE_B= [...]Chunk {0xCE3C3E27D2604B,0x6B0CC53B0F63B,0x55769886BC651D,0xAA3A93E7B3EBBD,0x5AC635D8}
+var CURVE_Order= [...]Chunk {0xB9CAC2FC632551,0xFAADA7179E84F3,0xFFFFFFFFFFBCE6,0xFFFFFF,0xFFFFFFFF}
+var CURVE_Gx= [...]Chunk {0xA13945D898C296,0x7D812DEB33A0F4,0xE563A440F27703,0xE12C4247F8BCE6,0x6B17D1F2}
+var CURVE_Gy= [...]Chunk {0xB6406837BF51F5,0x33576B315ECECB,0x4A7C0F9E162BCE,0xFE1A7F9B8EE7EB,0x4FE342E2}
diff --git a/version3/go/ROM_NIST384_32.go b/version3/go/ROM_NIST384_32.go
new file mode 100644
index 0000000..5c37292
--- /dev/null
+++ b/version3/go/ROM_NIST384_32.go
@@ -0,0 +1,36 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package NIST384
+
+// Base Bits= 29
+var Modulus= [...]Chunk {0x1FFFFFFF,0x7,0x0,0x1FFFFE00,0x1FFFEFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F} 
+var R2modp= [...]Chunk {0x0,0x8000,0x1FF80000,0x1FFFFF,0x2000000,0x0,0x0,0x1FFFFFFC,0xF,0x100,0x400,0x0,0x0,0x0}
+const MConst Chunk=0x1
+
+const CURVE_Cof_I int= 1
+var CURVE_Cof=[...]Chunk {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+const CURVE_A int= -3
+const CURVE_B_I int= 0
+var CURVE_B= [...]Chunk {0x13EC2AEF,0x142E476E,0xBB4674A,0xC731B14,0x1875AC65,0x447A809,0x4480C50,0xDDFD028,0x19181D9C,0x1F1FC168,0x623815A,0x47DCFC9,0x1312FA7E,0x59}
+var CURVE_Order= [...]Chunk {0xCC52973,0x760CB56,0xC29DEBB,0x141B6491,0x12DDF581,0x6C0FA1B,0x1FFF1D8D,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F}
+var CURVE_Gx= [...]Chunk {0x12760AB7,0x12A2F1C3,0x154A5B0E,0x5E4BB7E,0x2A38550,0xF0412A,0xE6167DD,0xC5174F3,0x146E1D3B,0x1799056B,0x3AC71C7,0x1D160A6F,0x87CA22B,0x55}
+var CURVE_Gy= [...]Chunk {0x10EA0E5F,0x1218EBE4,0x1FA0675E,0x1639C3A,0xB8C00A6,0x1889DAF8,0x11F3A768,0x17A51342,0x9F8F41D,0x1C9496E1,0x1767A62F,0xC4C58DE,0x17DE4A9,0x1B}
\ No newline at end of file
diff --git a/version3/go/ROM_NIST384_64.go b/version3/go/ROM_NIST384_64.go
new file mode 100644
index 0000000..77b966f
--- /dev/null
+++ b/version3/go/ROM_NIST384_64.go
@@ -0,0 +1,36 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package NIST384
+
+// Base Bits= 56
+var Modulus= [...]Chunk {0xFFFFFFFF,0xFFFF0000000000,0xFFFFFFFFFEFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFF}
+var R2modp= [...]Chunk {0xFE000000010000,0xFFFFFF,0x2,0xFFFFFFFE00,0x1000000020000,0x0,0x0}
+const MConst Chunk=0x100000001
+
+const CURVE_Cof_I int= 1
+var CURVE_Cof=[...]Chunk {0x1,0x0,0x0,0x0,0x0,0x0,0x0}
+const CURVE_A int= -3
+const CURVE_B_I int= 0
+var CURVE_B= [...]Chunk {0x85C8EDD3EC2AEF,0x398D8A2ED19D2A,0x8F5013875AC656,0xFE814112031408,0xF82D19181D9C6E,0xE7E4988E056BE3,0xB3312FA7E23E}
+var CURVE_Order= [...]Chunk {0xEC196ACCC52973,0xDB248B0A77AEC,0x81F4372DDF581A,0xFFFFFFFFC7634D,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFF}
+var CURVE_Gx= [...]Chunk {0x545E3872760AB7,0xF25DBF55296C3A,0xE082542A385502,0x8BA79B9859F741,0x20AD746E1D3B62,0x5378EB1C71EF3,0xAA87CA22BE8B}
+var CURVE_Gy= [...]Chunk {0x431D7C90EA0E5F,0xB1CE1D7E819D7A,0x13B5F0B8C00A60,0x289A147CE9DA31,0x92DC29F8F41DBD,0x2C6F5D9E98BF92,0x3617DE4A9626}
diff --git a/version3/go/ROM_NIST521_32.go b/version3/go/ROM_NIST521_32.go
new file mode 100644
index 0000000..819f569
--- /dev/null
+++ b/version3/go/ROM_NIST521_32.go
@@ -0,0 +1,37 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package NIST521
+
+// Base Bits= 28
+var Modulus= [...]Chunk {0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0x1FFFF}
+var R2modp= [...]Chunk {0x400000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+const MConst Chunk=0x1
+
+const CURVE_Cof_I int= 1
+var CURVE_Cof=[...]Chunk {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+const CURVE_A int= -3
+const CURVE_B_I int= 0
+var CURVE_B= [...]Chunk {0xB503F00,0x451FD46,0xC34F1EF,0xDF883D2,0xF073573,0xBD3BB1B,0xB1652C0,0xEC7E937,0x6193951,0xF109E15,0x489918E,0x15F3B8B,0x25B99B3,0xEEA2DA7,0xB68540,0x929A21A,0xE1C9A1F,0x3EB9618,0x5195}
+var CURVE_Order= [...]Chunk {0x1386409,0x6FB71E9,0xC47AEBB,0xC9B8899,0x5D03BB5,0x48F709A,0xB7FCC01,0xBF2F966,0x1868783,0xFFFFFA5,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0x1FFFF}
+var CURVE_Gx= [...]Chunk {0x2E5BD66,0x7E7E31C,0xA429BF9,0xB3C1856,0x8DE3348,0x27A2FFA,0x8FE1DC1,0xEFE7592,0x14B5E77,0x4D3DBAA,0x8AF606B,0xB521F82,0x139053F,0x429C648,0x62395B4,0x9E3ECB6,0x404E9CD,0x8E06B70,0xC685}
+var CURVE_Gy= [...]Chunk {0xFD16650,0xBE94769,0x2C24088,0x7086A27,0x761353C,0x13FAD0,0xC550B9,0x5EF4264,0x7EE7299,0x3E662C9,0xFBD1727,0x446817A,0x449579B,0xD998F54,0x42C7D1B,0x5C8A5FB,0xA3BC004,0x296A789,0x11839}
+
diff --git a/version3/go/ROM_NIST521_64.go b/version3/go/ROM_NIST521_64.go
new file mode 100644
index 0000000..3821efd
--- /dev/null
+++ b/version3/go/ROM_NIST521_64.go
@@ -0,0 +1,37 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package NIST521
+
+// Base Bits= 60
+var Modulus= [...]Chunk {0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0x1FFFFFFFFFF}
+var R2modp= [...]Chunk {0x4000000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+const MConst Chunk=0x1
+
+const CURVE_Cof_I int= 1
+var CURVE_Cof=[...]Chunk {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+const CURVE_A int= -3
+const CURVE_B_I int= 0
+var CURVE_B= [...]Chunk {0xF451FD46B503F00,0x73DF883D2C34F1E,0x2C0BD3BB1BF0735,0x3951EC7E937B165,0x9918EF109E15619,0x5B99B315F3B8B48,0xB68540EEA2DA72,0x8E1C9A1F929A21A,0x51953EB961}
+var CURVE_Order= [...]Chunk {0xB6FB71E91386409,0xB5C9B8899C47AEB,0xC0148F709A5D03B,0x8783BF2F966B7FC,0xFFFFFFFFFFA5186,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0x1FFFFFFFFFF}
+var CURVE_Gx= [...]Chunk {0x97E7E31C2E5BD66,0x48B3C1856A429BF,0xDC127A2FFA8DE33,0x5E77EFE75928FE1,0xF606B4D3DBAA14B,0x39053FB521F828A,0x62395B4429C6481,0x404E9CD9E3ECB6,0xC6858E06B7}
+var CURVE_Gy= [...]Chunk {0x8BE94769FD16650,0x3C7086A272C2408,0xB9013FAD076135,0x72995EF42640C55,0xD17273E662C97EE,0x49579B446817AFB,0x42C7D1BD998F544,0x9A3BC0045C8A5FB,0x11839296A78}
+
diff --git a/version3/go/ROM_NUMS256E_32.go b/version3/go/ROM_NUMS256E_32.go
new file mode 100644
index 0000000..94aac57
--- /dev/null
+++ b/version3/go/ROM_NUMS256E_32.go
@@ -0,0 +1,36 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package NUMS256E
+
+// Base Bits= 29
+var Modulus= [...]Chunk {0x1FFFFF43,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFFFFFF}
+var R2modp= [...]Chunk {0x22E2400,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+const MConst Chunk=0xBD
+
+const CURVE_Cof_I int= 4
+var CURVE_Cof=[...]Chunk {0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+const CURVE_A int= 1
+const CURVE_B_I int= -15342
+var CURVE_B= [...]Chunk {0x1FFFC355,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFFFFFF}
+var CURVE_Order= [...]Chunk {0xEDD4AF5,0x123D8C87,0x1650E6C6,0xAB54A5E,0x419,0x0,0x0,0x0,0x400000}
+var CURVE_Gx= [...]Chunk {0xEED13DA,0x6F60481,0x20D61A8,0x13141DC6,0x9BD60C3,0x1EAFB490,0xDF73478,0x1F6D5D44,0x8A7514}
+var CURVE_Gy= [...]Chunk {0x198A89E6,0x1D30B73B,0x15BB4CB,0x1EC3B021,0x18010715,0x12ECD325,0x171F3A59,0x13FB3B24,0x44D53E}
diff --git a/version3/go/ROM_NUMS256E_64.go b/version3/go/ROM_NUMS256E_64.go
new file mode 100644
index 0000000..6586131
--- /dev/null
+++ b/version3/go/ROM_NUMS256E_64.go
@@ -0,0 +1,36 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package NUMS256E
+
+// Base Bits= 56
+var Modulus= [...]Chunk {0xFFFFFFFFFFFF43,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFF}
+var R2modp= [...]Chunk {0x89000000000000,0x8B,0x0,0x0,0x0}
+const MConst Chunk=0xBD
+
+const CURVE_Cof_I int= 4
+var CURVE_Cof=[...]Chunk {0x4,0x0,0x0,0x0,0x0}
+const CURVE_A int= 1
+const CURVE_B_I int= -15342
+var CURVE_B= [...]Chunk {0xFFFFFFFFFFC355,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFF}
+var CURVE_Order= [...]Chunk {0x47B190EEDD4AF5,0x5AA52F59439B1A,0x4195,0x0,0x40000000}
+var CURVE_Gx= [...]Chunk {0xDEC0902EED13DA,0x8A0EE3083586A0,0x5F69209BD60C39,0x6AEA237DCD1E3D,0x8A7514FB}
+var CURVE_Gy= [...]Chunk {0xA616E7798A89E6,0x61D810856ED32F,0xD9A64B8010715F,0xD9D925C7CE9665,0x44D53E9F}
\ No newline at end of file
diff --git a/version3/go/ROM_NUMS256W_32.go b/version3/go/ROM_NUMS256W_32.go
new file mode 100644
index 0000000..b7ff8b0
--- /dev/null
+++ b/version3/go/ROM_NUMS256W_32.go
@@ -0,0 +1,36 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package NUMS256W
+
+// Base Bits= 28
+var Modulus= [...]Chunk {0xFFFFF43,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xF}
+var R2modp= [...]Chunk {0x0,0x8900000,0x8B,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+const MConst Chunk=0xBD
+
+const CURVE_Cof_I int= 1
+var CURVE_Cof=[...]Chunk {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+const CURVE_A int= -3
+const CURVE_B_I int= 152961
+var CURVE_B= [...]Chunk {0x25581,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Order= [...]Chunk {0x751A825,0xAB20294,0x65C6020,0x8275EA2,0xFFFE43C,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xF}
+var CURVE_Gx= [...]Chunk {0x21AACB1,0x52EE1EB,0x4C73ABC,0x9B0903D,0xB098357,0xA04F42C,0x1297A95,0x5AAADB6,0xC9ED6B6,0xB}
+var CURVE_Gy= [...]Chunk {0x184DE9F,0xB5B9CB2,0x10FBB80,0xC3D1153,0x35C955,0xF77E04E,0x673448B,0x3399B6A,0x8FC0F1,0xD}
diff --git a/version3/go/ROM_NUMS256W_64.go b/version3/go/ROM_NUMS256W_64.go
new file mode 100644
index 0000000..d10c643
--- /dev/null
+++ b/version3/go/ROM_NUMS256W_64.go
@@ -0,0 +1,37 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package NUMS256W
+
+// Base Bits= 56
+var Modulus= [...]Chunk {0xFFFFFFFFFFFF43,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFF}
+var R2modp= [...]Chunk {0x89000000000000,0x8B,0x0,0x0,0x0}
+const MConst Chunk=0xBD
+
+const CURVE_Cof_I int= 1
+var CURVE_Cof=[...]Chunk {0x1,0x0,0x0,0x0,0x0}
+const CURVE_A int= -3
+const CURVE_B_I int= 152961
+var CURVE_B= [...]Chunk {0x25581,0x0,0x0,0x0,0x0}
+var CURVE_Order= [...]Chunk {0xAB20294751A825,0x8275EA265C6020,0xFFFFFFFFFFE43C,0xFFFFFFFFFFFFFF,0xFFFFFFFF}
+var CURVE_Gx= [...]Chunk {0x52EE1EB21AACB1,0x9B0903D4C73ABC,0xA04F42CB098357,0x5AAADB61297A95,0xBC9ED6B6}
+var CURVE_Gy= [...]Chunk {0xB5B9CB2184DE9F,0xC3D115310FBB80,0xF77E04E035C955,0x3399B6A673448B,0xD08FC0F1}
+
diff --git a/version3/go/ROM_NUMS384E_32.go b/version3/go/ROM_NUMS384E_32.go
new file mode 100644
index 0000000..a8384e7
--- /dev/null
+++ b/version3/go/ROM_NUMS384E_32.go
@@ -0,0 +1,36 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package NUMS384E
+
+// Base Bits= 29
+var Modulus= [...]Chunk {0x1FFFFEC3,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F}
+var R2modp= [...]Chunk {0x0,0x4448000,0x6,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+const MConst Chunk=0x13D
+
+const CURVE_Cof_I int= 4
+var CURVE_Cof=[...]Chunk {0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+const CURVE_A int= 1
+const CURVE_B_I int= -11556
+var CURVE_B= [...]Chunk {0x1FFFD19F,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F}
+var CURVE_Order= [...]Chunk {0x6A3897D,0x5CEE627,0xD721E48,0x8AAB556,0x1E1CF61E,0xD0E5A35,0x1FFF891C,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1F}
+var CURVE_Gx= [...]Chunk {0xC206BDE,0x6AA0723,0x116504D4,0x52562CA,0x163406FF,0x1FD47998,0x10015D8F,0x8DCB7C9,0x15B30BF4,0x14D72AED,0x102DA884,0xB524CD9,0x1B111FB4,0x30}
+var CURVE_Gy= [...]Chunk {0x10729392,0xC681F0F,0x1B123727,0x561F28D,0x1964B007,0xC7BFB22,0x1D5A0C3E,0xE9E284B,0x1716AD82,0x11D886E,0x1CE2C69,0x134DDD61,0x983E67B,0x41}
diff --git a/version3/go/ROM_NUMS384E_64.go b/version3/go/ROM_NUMS384E_64.go
new file mode 100644
index 0000000..2b2c7dc
--- /dev/null
+++ b/version3/go/ROM_NUMS384E_64.go
@@ -0,0 +1,36 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package NUMS384E
+
+// Base Bits= 56
+var Modulus= [...]Chunk {0xFFFFFFFFFFFEC3,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFF}
+var R2modp= [...]Chunk {0x188890000,0x0,0x0,0x0,0x0,0x0,0x0}
+const MConst Chunk=0x13D
+
+const CURVE_Cof_I int= 4
+var CURVE_Cof=[...]Chunk {0x4,0x0,0x0,0x0,0x0,0x0,0x0}
+const CURVE_A int= 1
+const CURVE_B_I int= -11556
+var CURVE_B= [...]Chunk {0xFFFFFFFFFFD19F,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFF}
+var CURVE_Order= [...]Chunk {0xB9DCC4E6A3897D,0x555AAB35C87920,0x1CB46BE1CF61E4,0xFFFFFFFFE2471A,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0x3FFFFFFFFFFF}
+var CURVE_Gx= [...]Chunk {0xD540E46C206BDE,0x92B16545941350,0xA8F33163406FF2,0xE5BE4C005763FF,0xE55DB5B30BF446,0x266CC0B6A2129A,0x61B111FB45A9}
+var CURVE_Gy= [...]Chunk {0x8D03E1F0729392,0xB0F946EC48DC9D,0xF7F645964B0072,0xF1425F56830F98,0xB10DD716AD8274,0xEEB08738B1A423,0x82983E67B9A6}
diff --git a/version3/go/ROM_NUMS384W_32.go b/version3/go/ROM_NUMS384W_32.go
new file mode 100644
index 0000000..f89cc90
--- /dev/null
+++ b/version3/go/ROM_NUMS384W_32.go
@@ -0,0 +1,36 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package NUMS384W
+
+// Base Bits= 29
+var Modulus= [...]Chunk {0x1FFFFEC3,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F}
+var R2modp= [...]Chunk {0x0,0x4448000,0x6,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+const MConst Chunk=0x13D
+
+const CURVE_Cof_I int= 1
+var CURVE_Cof=[...]Chunk {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+const CURVE_A int= -3
+const CURVE_B_I int= -34568
+var CURVE_B= [...]Chunk {0x1FFF77BB,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F}
+var CURVE_Order= [...]Chunk {0x1B0E61B9,0x26C0FB3,0xDF89E98,0x153A7A98,0x16881BED,0x178F75AE,0x1FFF587A,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F}
+var CURVE_Gx= [...]Chunk {0x98152A,0x1CE5D021,0x18711EFA,0x1DDA201E,0xC742522,0x148D9536,0x7D3CEF4,0x19BF703F,0x60225C1,0x12082F8D,0x12203288,0x2DE3038,0x17956F0B,0x3A}
+var CURVE_Gy= [...]Chunk {0x6180716,0x3A5C763,0x1D2B4997,0xD69B77F,0x837EBCD,0x1BE890D,0xE72E482,0xEFF0FEE,0x1EB00469,0x2C267B,0x15F8CF4C,0x3371C71,0xDEE368E,0x56}
diff --git a/version3/go/ROM_NUMS384W_64.go b/version3/go/ROM_NUMS384W_64.go
new file mode 100644
index 0000000..614ef35
--- /dev/null
+++ b/version3/go/ROM_NUMS384W_64.go
@@ -0,0 +1,36 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package NUMS384W
+
+// Base Bits= 58
+var Modulus= [...]Chunk {0x3FFFFFFFFFFFEC3,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0xFFFFFFFFF}
+var R2modp= [...]Chunk {0x88900000000000,0x6,0x0,0x0,0x0,0x0,0x0}
+const MConst Chunk=0x13D
+
+const CURVE_Cof_I int= 1
+var CURVE_Cof=[...]Chunk {0x1,0x0,0x0,0x0,0x0,0x0,0x0}
+const CURVE_A int= -3
+const CURVE_B_I int= -34568
+var CURVE_B= [...]Chunk {0x3FFFFFFFFFF77BB,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0xFFFFFFFFF}
+var CURVE_Order= [...]Chunk {0x4D81F67B0E61B9,0x2A74F530DF89E98,0x2F1EEB5D6881BED,0x3FFFFFFFFFF587A,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0xFFFFFFFFF}
+var CURVE_Gx= [...]Chunk {0x39CBA042098152A,0x3BB4403D8711EFA,0x291B2A6CC742522,0x337EE07E7D3CEF4,0x24105F1A60225C1,0x5BC60712203288,0x757956F0B}
+var CURVE_Gy= [...]Chunk {0x74B8EC66180716,0x1AD36EFFD2B4997,0x37D121A837EBCD,0x1DFE1FDCE72E482,0x584CF7EB00469,0x66E38E35F8CF4C,0xACDEE368E}
diff --git a/version3/go/ROM_NUMS512E_32.go b/version3/go/ROM_NUMS512E_32.go
new file mode 100644
index 0000000..0d87b80
--- /dev/null
+++ b/version3/go/ROM_NUMS512E_32.go
@@ -0,0 +1,36 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package NUMS512E
+
+// Base Bits= 29
+var Modulus= [...]Chunk {0x1FFFFDC7,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF}
+var R2modp= [...]Chunk {0xB100000,0x278,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+const MConst Chunk=0x239
+
+const CURVE_Cof_I int= 4
+var CURVE_Cof=[...]Chunk {0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+const CURVE_A int= 1
+const CURVE_B_I int= -78296
+var CURVE_B= [...]Chunk {0x1FFECBEF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF}
+var CURVE_Order= [...]Chunk {0x1BEED46D,0x1A3467A8,0x1BFB3FD9,0xC0AF0DB,0x86F52A4,0xC64B85B,0x6EA78FF,0xDA5F9F2,0x1FB4F063,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFF}
+var CURVE_Gx= [...]Chunk {0x19EC57FE,0xDCD594C,0x113C0571,0xA4A84F9,0x104AD0FE,0x4C92B44,0xC3DE2F7,0x9DDC8CE,0x74621C1,0x1139DC0A,0x9E85FAF,0x1B894704,0x1D1E79F4,0x9E29997,0x32DE223,0x16D38F43,0x116D128D,0x6FC71}
+var CURVE_Gy= [...]Chunk {0x1E2F5E1,0x136EF606,0x1C7407CC,0xDA71537,0xC1FD026,0x3431576,0x15898068,0x1E5D32C6,0x120CA53,0xC84F41A,0xA4ADAE5,0x104B3A45,0x76F726D,0x1512B772,0x3D5DEA0,0x194E3316,0x1FF39D49,0x3684D}
diff --git a/version3/go/ROM_NUMS512E_64.go b/version3/go/ROM_NUMS512E_64.go
new file mode 100644
index 0000000..75d96be
--- /dev/null
+++ b/version3/go/ROM_NUMS512E_64.go
@@ -0,0 +1,36 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package NUMS512E
+
+// Base Bits= 60
+var Modulus= [...]Chunk {0xFFFFFFFFFFFFDC7,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFF}
+var R2modp= [...]Chunk {0x100000000000000,0x4F0B,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+const MConst Chunk=0x239
+
+const CURVE_Cof_I int= 4
+var CURVE_Cof=[...]Chunk {0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+const CURVE_A int= 1
+const CURVE_B_I int= -78296
+var CURVE_B= [...]Chunk {0xFFFFFFFFFFECBEF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFF}
+var CURVE_Order= [...]Chunk {0x7468CF51BEED46D,0x4605786DEFECFF6,0xFD8C970B686F52A,0x636D2FCF91BA9E3,0xFFFFFFFFFFFB4F0,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0x3FFFFFFF}
+var CURVE_Gx= [...]Chunk {0x5B9AB2999EC57FE,0xE525427CC4F015C,0xDC992568904AD0F,0xC14EEE46730F78B,0xEBE273B81474621,0x9F4DC4A38227A17,0x888D3C5332FD1E7,0x128DB69C7A18CB7,0xDF8E316D}
+var CURVE_Gy= [...]Chunk {0x26DDEC0C1E2F5E1,0x66D38A9BF1D01F3,0xA06862AECC1FD02,0x53F2E9963562601,0xB95909E834120CA,0x26D8259D22A92B6,0x7A82A256EE476F7,0x9D49CA7198B0F57,0x6D09BFF3}
diff --git a/version3/go/ROM_NUMS512W_32.go b/version3/go/ROM_NUMS512W_32.go
new file mode 100644
index 0000000..2e18ee1
--- /dev/null
+++ b/version3/go/ROM_NUMS512W_32.go
@@ -0,0 +1,37 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package NUMS512W
+
+// Base Bits= 29
+var Modulus= [...]Chunk {0x1FFFFDC7,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF}
+var R2modp= [...]Chunk {0xB100000,0x278,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+const MConst Chunk=0x239
+
+const CURVE_Cof_I int= 1
+var CURVE_Cof=[...]Chunk {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+const CURVE_A int= -3
+const CURVE_B_I int= 121243
+var CURVE_B= [...]Chunk {0x1D99B,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Order= [...]Chunk {0x433555D,0x10A9F9C8,0x1F3490F3,0xD166CC0,0xBDC63B5,0xC76CBE8,0xC6D3F09,0x1F729CF0,0x1F5B3CA4,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF}
+var CURVE_Gx= [...]Chunk {0xCABAE57,0x4143CAC,0x1BD778B7,0x1AC026FA,0x15831D5,0x14312AB,0x167A4DE5,0xA20ED66,0x195021A1,0x129836CF,0x1141B830,0xA03ED0A,0xCAD83BB,0x1E9DA94C,0xDC00A80,0x1527B45,0x1447141D,0x1D601}
+var CURVE_Gy= [...]Chunk {0x183527A6,0x1D043B01,0x1F43FA48,0x16B83C99,0x5602CF2,0x1420592D,0x17A70486,0x1B5161DD,0x14A28415,0x3DE8A78,0x3D2C983,0x17797719,0x197DBDEA,0x15D88025,0x1BBB718F,0xAD679C1,0x14CA29AD,0x4A1D2}
+
diff --git a/version3/go/ROM_NUMS512W_64.go b/version3/go/ROM_NUMS512W_64.go
new file mode 100644
index 0000000..320845c
--- /dev/null
+++ b/version3/go/ROM_NUMS512W_64.go
@@ -0,0 +1,36 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package NUMS512W
+
+// Base Bits= 60
+var Modulus= [...]Chunk {0xFFFFFFFFFFFFDC7,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFF}
+var R2modp= [...]Chunk {0x100000000000000,0x4F0B,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+const MConst Chunk=0x239
+
+const CURVE_Cof_I int= 1
+var CURVE_Cof=[...]Chunk {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+const CURVE_A int= -3
+const CURVE_B_I int= 121243
+var CURVE_B= [...]Chunk {0x1D99B,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Order= [...]Chunk {0xE153F390433555D,0x568B36607CD243C,0x258ED97D0BDC63B,0xA4FB94E7831B4FC,0xFFFFFFFFFFF5B3C,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFF}
+var CURVE_Gx= [...]Chunk {0xC8287958CABAE57,0x5D60137D6F5DE2D,0x94286255615831D,0xA151076B359E937,0xC25306D9F95021,0x3BB501F6854506E,0x2A03D3B5298CAD8,0x141D0A93DA2B700,0x3AC03447}
+var CURVE_Gy= [...]Chunk {0x3A08760383527A6,0x2B5C1E4CFD0FE92,0x1A840B25A5602CF,0x15DA8B0EEDE9C12,0x60C7BD14F14A284,0xDEABBCBB8C8F4B2,0xC63EBB1004B97DB,0x29AD56B3CE0EEED,0x943A54CA}
diff --git a/version3/go/ROM_SEC256K1_64.go b/version3/go/ROM_SEC256K1_64.go
new file mode 100644
index 0000000..6ad5756
--- /dev/null
+++ b/version3/go/ROM_SEC256K1_64.go
@@ -0,0 +1,39 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package NIST256
+
+// Base Bits= 56
+
+var Modulus= [...]Chunk {0xFFFFFEFFFFFC2F,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFF}
+var R2modp= [...]Chunk {0xA1000000000000,0x7A2000E90,0x1,0x0,0x0}
+const MConst Chunk=0x38091DD2253531
+
+// Base Bits= 56
+
+const CURVE_A int= 0
+const CURVE_Cof_I int= 1
+var CURVE_Cof= [...]Chunk {0x1,0x0,0x0,0x0,0x0}
+const CURVE_B_I int= 7
+var CURVE_B= [...]Chunk {0x7,0x0,0x0,0x0,0x0}
+var CURVE_Order= [...]Chunk {0xD25E8CD0364141,0xDCE6AF48A03BBF,0xFFFFFFFFFEBAAE,0xFFFFFFFFFFFFFF,0xFFFFFFFF}
+var CURVE_Gx= [...]Chunk {0xF2815B16F81798,0xFCDB2DCE28D959,0x95CE870B07029B,0xF9DCBBAC55A062,0x79BE667E}
+var CURVE_Gy= [...]Chunk {0x47D08FFB10D4B8,0xB448A68554199C,0xFC0E1108A8FD17,0x26A3C4655DA4FB,0x483ADA77}
diff --git a/version3/go/ROM_SECP256K1_32.go b/version3/go/ROM_SECP256K1_32.go
new file mode 100644
index 0000000..72b74bb
--- /dev/null
+++ b/version3/go/ROM_SECP256K1_32.go
@@ -0,0 +1,39 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+package SECP256K1
+
+// Base Bits= 28
+
+var Modulus= [...]Chunk {0xFFFFC2F,0xFFFFFEF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xF} 
+var R2modp= [...]Chunk {0x0,0xA100000,0x2000E90,0x7A,0x1,0x0,0x0,0x0,0x0,0x0}
+const MConst Chunk=0x2253531
+
+// Base Bits= 28
+
+const CURVE_A int= 0
+const CURVE_Cof_I int= 1
+var CURVE_Cof= [...]Chunk {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+const CURVE_B_I int= 7
+var CURVE_B= [...]Chunk {0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
+var CURVE_Order= [...]Chunk {0x364141,0xD25E8CD,0x8A03BBF,0xDCE6AF4,0xFFEBAAE,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xF}
+var CURVE_Gx= [...]Chunk {0x6F81798,0xF2815B1,0xE28D959,0xFCDB2DC,0xB07029B,0x95CE870,0xC55A062,0xF9DCBBA,0x9BE667E,0x7}
+var CURVE_Gy= [...]Chunk {0xB10D4B8,0x47D08FF,0x554199C,0xB448A68,0x8A8FD17,0xFC0E110,0x55DA4FB,0x26A3C46,0x83ADA77,0x4}
diff --git a/version3/go/RSA.go b/version3/go/RSA.go
new file mode 100644
index 0000000..8195e57
--- /dev/null
+++ b/version3/go/RSA.go
@@ -0,0 +1,361 @@
+/*
+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.
+*/
+
+/* RSA API high-level functions  */
+
+package XXX
+
+//import "fmt"
+import "github.com/milagro-crypto/amcl/version3/go/amcl"
+
+const RFS int=int(MODBYTES)*FFLEN
+
+const RSA_HASH_TYPE int=amcl.SHA256
+
+
+type rsa_private_key struct {
+	p,q,dp,dq,c *FF
+}
+
+func New_private_key(n int) *rsa_private_key {
+	SK:=new(rsa_private_key)
+	SK.p=NewFFint(n)
+	SK.q=NewFFint(n)
+	SK.dp=NewFFint(n)
+	SK.dq=NewFFint(n)
+	SK.c=NewFFint(n)
+	return SK
+}
+
+type rsa_public_key struct {
+	e int
+	n *FF
+}
+
+func New_public_key(m int) *rsa_public_key{
+	PK:=new(rsa_public_key)
+	PK.e=0
+	PK.n=NewFFint(m)
+	return PK
+}
+
+func hashit(sha int,A []byte,n int) []byte {
+	var R []byte
+	if sha==amcl.SHA256 {
+		H:=amcl.NewHASH256()
+		if A!=nil {H.Process_array(A)}
+		if n>=0 {H.Process_num(int32(n))}
+		R=H.Hash()
+	}
+	if sha==amcl.SHA384 {
+		H:=amcl.NewHASH384()
+		if A!=nil {H.Process_array(A)}
+		if n>=0 {H.Process_num(int32(n))}
+		R=H.Hash()
+	}
+	if sha==amcl.SHA512 {
+		H:=amcl.NewHASH512()
+		if A!=nil {H.Process_array(A)}
+		if n>=0 {H.Process_num(int32(n))}
+		R=H.Hash()
+	}
+	return R
+}
+
+func RSA_KEY_PAIR(rng *amcl.RAND,e int,PRIV *rsa_private_key,PUB *rsa_public_key) { /* IEEE1363 A16.11/A16.12 more or less */
+	n:=PUB.n.getlen()/2
+	t:=NewFFint(n)
+	p1:=NewFFint(n)
+	q1:=NewFFint(n)
+
+	for true {
+		PRIV.p.random(rng)
+		for PRIV.p.lastbits(2)!=3 {PRIV.p.inc(1)}	
+		for !prime(PRIV.p,rng) {
+			PRIV.p.inc(4)
+		}
+			
+		p1.copy(PRIV.p)
+		p1.dec(1)
+
+		if p1.cfactor(e) {continue}
+		break;
+	}
+
+	for true {
+		PRIV.q.random(rng);
+		for PRIV.q.lastbits(2)!=3 {PRIV.q.inc(1)}
+		for !prime(PRIV.q,rng) {
+			PRIV.q.inc(4)
+		}
+			
+		q1.copy(PRIV.q);
+		q1.dec(1);
+
+		if q1.cfactor(e) {continue}
+
+		break;
+	}
+	
+	PUB.n=ff_mul(PRIV.p,PRIV.q);
+	PUB.e=e;
+
+	t.copy(p1)
+	t.shr()
+	PRIV.dp.set(e)
+	PRIV.dp.invmodp(t)
+	if PRIV.dp.parity()==0 {PRIV.dp.add(t)}
+	PRIV.dp.norm();
+
+	t.copy(q1)
+	t.shr()
+	PRIV.dq.set(e)
+	PRIV.dq.invmodp(t)
+	if PRIV.dq.parity()==0 {PRIV.dq.add(t)}
+	PRIV.dq.norm()
+
+	PRIV.c.copy(PRIV.p)
+	PRIV.c.invmodp(PRIV.q)
+
+}
+
+/* Mask Generation Function */
+
+func MGF1(sha int,Z []byte,olen int,K []byte) {
+	hlen:=sha
+
+	var k int=0
+	for i:=0;i<len(K);i++ {K[i]=0}
+
+	cthreshold:=olen/hlen 
+	if olen%hlen!=0 {cthreshold++}
+	for counter:=0;counter<cthreshold;counter++ {
+		B:=hashit(sha,Z,counter)
+
+		if (k+hlen>olen) {
+			for i:=0;i<olen%hlen;i++ {K[k]=B[i]; k++}
+		} else {
+			for i:=0;i<hlen;i++ {K[k]=B[i]; k++}
+		}
+	}	
+}
+
+/* SHAXXX identifier strings */
+var SHA256ID= [...]byte {0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20}
+var SHA384ID= [...]byte {0x30,0x41,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00,0x04,0x30};
+var SHA512ID= [...]byte {0x30,0x51,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0x04,0x40};
+
+func RSA_PKCS15(sha int,m []byte,w []byte) bool {
+	olen:=FF_BITS/8
+	hlen:=sha
+	idlen:=19
+
+	if olen<idlen+hlen+10 {return false}
+	H:=hashit(sha,m,-1)
+
+	for i:=0;i<len(w);i++ {w[i]=0}
+	i:=0
+	w[i]=0; i++
+	w[i]=1; i++
+	for j:=0;j<olen-idlen-hlen-3;j++ {w[i]=0xff; i++}
+	w[i]=0; i++
+
+	if hlen==amcl.SHA256 {
+		for j:=0;j<idlen;j++ {w[i]=SHA256ID[j]; i++}
+	}
+	if hlen==amcl.SHA384 {
+		for j:=0;j<idlen;j++ {w[i]=SHA384ID[j]; i++}
+	}
+	if hlen==amcl.SHA512 {
+		for j:=0;j<idlen;j++ {w[i]=SHA512ID[j]; i++}
+	}
+	for j:=0;j<hlen;j++ {w[i]=H[j]; i++}
+
+	return true
+}
+
+
+/* OAEP Message Encoding for Encryption */
+func RSA_OAEP_ENCODE(sha int,m []byte,rng *amcl.RAND,p []byte) []byte { 
+	olen:=RFS-1
+	mlen:=len(m)
+	var f [RFS]byte
+
+	hlen:=sha
+
+	SEED:=make([]byte,hlen);
+
+	seedlen:=hlen
+	if (mlen>olen-hlen-seedlen-1) {return nil} 
+
+	DBMASK:=make([]byte,olen-seedlen)
+
+	h:=hashit(sha,p,-1);
+
+	for i:=0;i<hlen;i++ {f[i]=h[i]}
+
+	slen:=olen-mlen-hlen-seedlen-1      
+
+	for i:=0;i<slen;i++ {f[hlen+i]=0}
+	f[hlen+slen]=1
+	for i:=0;i<mlen;i++ {f[hlen+slen+1+i]=m[i]}
+
+	for i:=0;i<seedlen;i++ {SEED[i]=rng.GetByte()}
+	MGF1(sha,SEED,olen-seedlen,DBMASK)
+
+	for i:=0;i<olen-seedlen;i++ {DBMASK[i]^=f[i]}
+
+	MGF1(sha,DBMASK,seedlen,f[:])
+
+	for i:=0;i<seedlen;i++ {f[i]^=SEED[i]}
+
+	for i:=0;i<olen-seedlen;i++ {f[i+seedlen]=DBMASK[i]}
+
+	/* pad to length RFS */
+	d:=1
+	for i:=RFS-1;i>=d;i-- {
+		f[i]=f[i-d]
+	}
+	for i:=d-1;i>=0;i-- {
+		f[i]=0
+	}
+	return f[:]
+}
+
+/* OAEP Message Decoding for Decryption */
+func RSA_OAEP_DECODE(sha int,p []byte,f []byte) [] byte {
+	olen:=RFS-1
+
+	hlen:=sha
+	SEED:=make([]byte,hlen)
+	seedlen:=hlen;
+	CHASH:=make([]byte,hlen)
+	
+	if olen<seedlen+hlen+1 {return nil}
+	DBMASK:=make([]byte,olen-seedlen)
+	for i:=0;i<olen-seedlen;i++ {DBMASK[i]=0}
+
+	if len(f)<RFS {
+		d:=RFS-len(f)
+		for i:=RFS-1;i>=d;i-- {
+			f[i]=f[i-d]
+		}
+		for i:=d-1;i>=0;i-- {
+			f[i]=0
+		}
+	}
+
+	h:=hashit(sha,p,-1)
+	for i:=0;i<hlen;i++ {CHASH[i]=h[i]}
+
+	x:=f[0]
+
+	for i:=seedlen;i<olen;i++ {
+		DBMASK[i-seedlen]=f[i+1]
+	}
+
+	MGF1(sha,DBMASK,seedlen,SEED)
+	for i:=0;i<seedlen;i++ {SEED[i]^=f[i+1]}
+	MGF1(sha,SEED,olen-seedlen,f)
+	for i:=0;i<olen-seedlen;i++ {DBMASK[i]^=f[i]}
+
+	comp:=true
+	for i:=0;i<hlen;i++ {
+		if CHASH[i]!=DBMASK[i] {comp=false}
+	}
+
+	for i:=0;i<olen-seedlen-hlen;i++ {
+		DBMASK[i]=DBMASK[i+hlen]
+	}
+
+	for i:=0;i<hlen;i++ {
+		SEED[i]=0; CHASH[i]=0
+	}
+		
+	var k int
+	for k=0;;k++ {
+		if k>=olen-seedlen-hlen {return nil}
+		if DBMASK[k]!=0 {break}
+	}
+
+	t:=DBMASK[k]
+	if (!comp || x!=0 || t!=0x01) {
+		for i:=0;i<olen-seedlen;i++ {DBMASK[i]=0}
+		return nil
+	}
+
+	var r = make([]byte,olen-seedlen-hlen-k-1)
+
+	for i:=0;i<olen-seedlen-hlen-k-1;i++ {
+		r[i]=DBMASK[i+k+1]
+	}
+	
+	for i:=0;i<olen-seedlen;i++  {DBMASK[i]=0}
+
+	return r
+}
+
+/* destroy the Private Key structure */
+func RSA_PRIVATE_KEY_KILL(PRIV *rsa_private_key) {
+	PRIV.p.zero();
+	PRIV.q.zero();
+	PRIV.dp.zero();
+	PRIV.dq.zero();
+	PRIV.c.zero();
+}
+
+/* RSA encryption with the public key */
+func RSA_ENCRYPT(PUB *rsa_public_key,F []byte,G []byte) {
+	n:=PUB.n.getlen()
+	f:=NewFFint(n)
+
+	ff_fromBytes(f,F)
+	f.power(PUB.e,PUB.n)
+	f.toBytes(G)
+}
+
+/* RSA decryption with the private key */
+func RSA_DECRYPT(PRIV *rsa_private_key,G []byte,F []byte) {
+	n:=PRIV.p.getlen()
+	g:=NewFFint(2*n)
+
+	ff_fromBytes(g,G);
+	jp:=g.dmod(PRIV.p)
+	jq:=g.dmod(PRIV.q)
+
+	jp.skpow(PRIV.dp,PRIV.p)
+	jq.skpow(PRIV.dq,PRIV.q)
+
+	g.zero()
+	g.dscopy(jp)
+	jp.mod(PRIV.q)
+	if ff_comp(jp,jq)>0 {jq.add(PRIV.q)}
+	jq.sub(jp)
+	jq.norm()
+
+	t:=ff_mul(PRIV.c,jq)
+	jq=t.dmod(PRIV.q)
+
+	t=ff_mul(jq,PRIV.p)
+	g.add(t)
+	g.norm()
+
+	g.toBytes(F)
+}
+
diff --git a/version3/go/SHA3.go b/version3/go/SHA3.go
new file mode 100644
index 0000000..16b7327
--- /dev/null
+++ b/version3/go/SHA3.go
@@ -0,0 +1,258 @@
+/*
+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.
+*/
+
+/*
+ * Implementation of the Secure Hashing Algorithm (SHA-384)
+ *
+ * Generates a 384 bit message digest. It should be impossible to come
+ * come up with two messages that hash to the same value ("collision free").
+ *
+ * For use with byte-oriented messages only. 
+ */
+
+//package main
+
+package amcl
+
+//import "fmt"
+
+const SHA3_HASH224 int=28
+const SHA3_HASH256 int=32
+const SHA3_HASH384 int=48
+const SHA3_HASH512 int=64
+const SHA3_SHAKE128 int=16
+const SHA3_SHAKE256 int=32
+
+
+const sha3_ROUNDS int=24
+
+var sha3_RC = [24]uint64 {
+		0x0000000000000001,0x0000000000008082,0x800000000000808A,0x8000000080008000,
+		0x000000000000808B,0x0000000080000001,0x8000000080008081,0x8000000000008009,
+		0x000000000000008A,0x0000000000000088,0x0000000080008009,0x000000008000000A,
+		0x000000008000808B,0x800000000000008B,0x8000000000008089,0x8000000000008003,
+		0x8000000000008002,0x8000000000000080,0x000000000000800A,0x800000008000000A,
+		0x8000000080008081,0x8000000000008080,0x0000000080000001,0x8000000080008008}
+
+
+type SHA3 struct {
+	length uint64
+	rate int
+	len int
+	s [5][5] uint64
+}
+
+/* functions */
+
+func sha3_ROTL(x uint64,n uint64) uint64 {
+	return (((x)<<n) | ((x)>>(64-n)))
+}
+
+func (H *SHA3) transform() { /* basic transformation step */
+
+	var c [5]uint64
+	var d [5]uint64
+	var b [5][5]uint64
+
+	for k:=0;k<sha3_ROUNDS;k++ {
+		c[0]=H.s[0][0]^H.s[0][1]^H.s[0][2]^H.s[0][3]^H.s[0][4];
+		c[1]=H.s[1][0]^H.s[1][1]^H.s[1][2]^H.s[1][3]^H.s[1][4];
+		c[2]=H.s[2][0]^H.s[2][1]^H.s[2][2]^H.s[2][3]^H.s[2][4];
+		c[3]=H.s[3][0]^H.s[3][1]^H.s[3][2]^H.s[3][3]^H.s[3][4];
+		c[4]=H.s[4][0]^H.s[4][1]^H.s[4][2]^H.s[4][3]^H.s[4][4];
+
+		d[0]=c[4]^sha3_ROTL(c[1],1);
+		d[1]=c[0]^sha3_ROTL(c[2],1);
+		d[2]=c[1]^sha3_ROTL(c[3],1);
+		d[3]=c[2]^sha3_ROTL(c[4],1);
+		d[4]=c[3]^sha3_ROTL(c[0],1);
+
+		for i:=0;i<5;i++ {
+			for j:=0;j<5;j++ {
+					H.s[i][j]^=d[i];
+			}
+		}
+
+		b[0][0]=H.s[0][0];
+		b[1][3]=sha3_ROTL(H.s[0][1],36);
+		b[2][1]=sha3_ROTL(H.s[0][2],3);
+		b[3][4]=sha3_ROTL(H.s[0][3],41);
+		b[4][2]=sha3_ROTL(H.s[0][4],18);
+
+		b[0][2]=sha3_ROTL(H.s[1][0],1);
+		b[1][0]=sha3_ROTL(H.s[1][1],44);
+		b[2][3]=sha3_ROTL(H.s[1][2],10);
+		b[3][1]=sha3_ROTL(H.s[1][3],45);
+		b[4][4]=sha3_ROTL(H.s[1][4],2);
+
+		b[0][4]=sha3_ROTL(H.s[2][0],62);
+		b[1][2]=sha3_ROTL(H.s[2][1],6);
+		b[2][0]=sha3_ROTL(H.s[2][2],43);
+		b[3][3]=sha3_ROTL(H.s[2][3],15);
+		b[4][1]=sha3_ROTL(H.s[2][4],61);
+
+		b[0][1]=sha3_ROTL(H.s[3][0],28);
+		b[1][4]=sha3_ROTL(H.s[3][1],55);
+		b[2][2]=sha3_ROTL(H.s[3][2],25);
+		b[3][0]=sha3_ROTL(H.s[3][3],21);
+		b[4][3]=sha3_ROTL(H.s[3][4],56);
+
+		b[0][3]=sha3_ROTL(H.s[4][0],27);
+		b[1][1]=sha3_ROTL(H.s[4][1],20);
+		b[2][4]=sha3_ROTL(H.s[4][2],39);
+		b[3][2]=sha3_ROTL(H.s[4][3],8);
+		b[4][0]=sha3_ROTL(H.s[4][4],14);
+
+		for i:=0;i<5;i++ {
+			for j:=0;j<5;j++ {
+				H.s[i][j]=b[i][j]^(^b[(i+1)%5][j]&b[(i+2)%5][j]);
+			}
+		}
+
+		H.s[0][0]^=sha3_RC[k];
+	}
+} 
+
+/* Initialise Hash function */
+func (H *SHA3) Init(olen int) { 
+	for i:=0;i<5;i++ {
+		for j:=0;j<5;j++ {
+			H.s[i][j]=0;
+		}
+	}
+	H.length=0
+	H.len=olen
+	H.rate=200-2*olen
+}
+
+
+func NewSHA3(olen int) *SHA3 {
+	H:= new(SHA3)
+	H.Init(olen)
+	return H
+}
+
+/* process a single byte */
+func (H *SHA3) Process(byt byte) { /* process the next message byte */
+	cnt:=int(H.length%uint64(H.rate))
+	b:=cnt%8
+	cnt/=8
+	i:=cnt%5
+	j:=cnt/5
+	H.s[i][j]^=uint64(byt&0xff)<<uint(8*b);
+	H.length++;
+	if int(H.length%uint64(H.rate))==0 {
+		H.transform()
+	}
+}
+
+/* squeeze the sponge */
+func (H *SHA3) Squeeze(buff []byte,olen int) {
+//	olen:=len(buff)
+	done:=false
+	m:=0
+/* extract by columns */
+	for {
+		for j:=0;j<5;j++ {
+			for i:=0;i<5;i++ {
+				el:=H.s[i][j]
+				for k:=0;k<8;k++ {
+					buff[m]=byte(el&0xff)
+					m++
+					if m>=olen || (m%H.rate)==0 {
+						done=true
+						break
+					}
+					el>>=8;
+				}
+				if done {break}
+			}
+			if done {break}
+		}
+		if m>=olen {break}
+		done=false
+		H.transform()
+
+	}
+}
+
+/* Generate Hash */
+func (H *SHA3) Hash(hash []byte) { /* generate a SHA3 hash of appropriate size */
+	q:=H.rate-int(H.length%uint64(H.rate))
+	if q==1 {
+		H.Process(0x86)
+	} else {
+		H.Process(0x06)
+		for int(H.length%uint64(H.rate)) != (H.rate-1) {H.Process(0x00)}
+		H.Process(0x80)
+	}
+	H.Squeeze(hash,H.len);
+}
+
+func (H *SHA3) Shake(hash []byte,olen int) { /* generate a SHA3 hash of appropriate size */
+	q:=H.rate-int(H.length%uint64(H.rate))
+	if q==1 {
+		H.Process(0x9f)
+	} else {
+		H.Process(0x1f)
+		for int(H.length%uint64(H.rate))!=H.rate-1 {H.Process(0x00)}
+		H.Process(0x80)
+	}
+	H.Squeeze(hash,olen);
+}
+
+
+
+/* test program: should produce digest */
+//916f6061fe879741ca6469b43971dfdb28b1a32dc36cb3254e812be27aad1d18
+//afebb2ef542e6579c50cad06d2e578f9f8dd6881d7dc824d26360feebf18a4fa73e3261122948efcfd492e74e82e2189ed0fb440d187f382270cb455f21dd185
+//98be04516c04cc73593fef3ed0352ea9f6443942d6950e29a372a681c3deaf4535423709b02843948684e029010badcc0acd8303fc85fdad3eabf4f78cae165635f57afd28810fc2
+
+/*
+func main() {
+
+	test := []byte("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu")
+	var digest [172]byte
+
+	sh:=NewSHA3(SHA3_HASH256)
+	for i:=0;i<len(test);i++ {
+		sh.Process(test[i])
+	}	
+	sh.Hash(digest[:])    
+	for i:=0;i<32;i++ {fmt.Printf("%02x",digest[i])}
+	fmt.Printf("\n");
+
+	sh=NewSHA3(SHA3_HASH512)
+	for i:=0;i<len(test);i++ {
+		sh.Process(test[i])
+	}	
+	sh.Hash(digest[:])    
+	for i:=0;i<64;i++ {fmt.Printf("%02x",digest[i])}
+	fmt.Printf("\n");
+
+	sh=NewSHA3(SHA3_SHAKE256)
+	for i:=0;i<len(test);i++ {
+		sh.Process(test[i])
+	}	
+	sh.Shake(digest[:],72)    
+	for i:=0;i<72;i++ {fmt.Printf("%02x",digest[i])}
+	fmt.Printf("\n");
+
+} */
+
diff --git a/version3/go/TestALL.go b/version3/go/TestALL.go
new file mode 100644
index 0000000..6fa6b70
--- /dev/null
+++ b/version3/go/TestALL.go
@@ -0,0 +1,1315 @@
+/*
+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.
+*/
+
+/* test driver and function exerciser for ECDH/ECIES/ECDSA API Functions */
+
+
+package main
+
+import "fmt"
+
+import "github.com/milagro-crypto/amcl/version3/go/amcl"
+import "github.com/milagro-crypto/amcl/version3/go/amcl/ED25519"
+import "github.com/milagro-crypto/amcl/version3/go/amcl/NIST256"
+import "github.com/milagro-crypto/amcl/version3/go/amcl/GOLDILOCKS"
+import "github.com/milagro-crypto/amcl/version3/go/amcl/BN254"
+import "github.com/milagro-crypto/amcl/version3/go/amcl/BLS383"
+import "github.com/milagro-crypto/amcl/version3/go/amcl/BLS24"
+import "github.com/milagro-crypto/amcl/version3/go/amcl/BLS48"
+import "github.com/milagro-crypto/amcl/version3/go/amcl/RSA2048"
+
+
+//import "amcl"
+//import "amcl/ED25519"
+//import "amcl/BN254"
+//import "amcl/RSA2048"
+
+
+func printBinary(array []byte) {
+	for i:=0;i<len(array);i++ {
+		fmt.Printf("%02x", array[i])
+	}
+	fmt.Printf("\n")
+}  
+
+
+func ecdh_ED25519(rng *amcl.RAND) {
+//	j:=0
+	pp:="M0ng00se"
+	res:=0
+
+	var sha=ED25519.HASH_TYPE
+
+	var S1 [ED25519.EGS]byte
+	var W0 [2*ED25519.EFS+1]byte
+	var W1 [2*ED25519.EFS+1]byte
+	var Z0 [ED25519.EFS]byte
+	var Z1 [ED25519.EFS]byte
+	var SALT [8]byte
+	var P1 [3]byte
+	var P2 [4]byte
+	var V [2*ED25519.EFS+1]byte
+	var M [17]byte
+	var T [12]byte
+	var CS [ED25519.EGS]byte
+	var DS [ED25519.EGS]byte
+
+	for i:=0;i<8;i++ {SALT[i]=byte(i+1)}  // set Salt
+
+	fmt.Printf("\nTesting ECDH/ECDSA/ECIES\n")
+	fmt.Printf("Alice's Passphrase= "+pp)
+	fmt.Printf("\n");
+	PW:=[]byte(pp)
+
+/* private key S0 of size MGS bytes derived from Password and Salt */
+
+	S0:=ED25519.ECDH_PBKDF2(sha,PW,SALT[:],1000,ED25519.EGS)
+
+	fmt.Printf("Alice's private key= 0x")
+	printBinary(S0)
+
+/* Generate Key pair S/W */
+	ED25519.ECDH_KEY_PAIR_GENERATE(nil,S0,W0[:])
+
+	fmt.Printf("Alice's public key= 0x")
+	printBinary(W0[:]);
+
+	res=ED25519.ECDH_PUBLIC_KEY_VALIDATE(W0[:])
+	if res!=0 {
+		fmt.Printf("ECP Public Key is invalid!\n")
+		return
+	}
+
+/* Random private key for other party */
+	ED25519.ECDH_KEY_PAIR_GENERATE(rng,S1[:],W1[:])
+
+	fmt.Printf("Servers private key= 0x");
+	printBinary(S1[:])
+
+	fmt.Printf("Servers public key= 0x")
+	printBinary(W1[:])
+
+
+	res=ED25519.ECDH_PUBLIC_KEY_VALIDATE(W1[:])
+	if res!=0 {
+		fmt.Printf("ECP Public Key is invalid!\n")
+		return
+	}
+/* Calculate common key using DH - IEEE 1363 method */
+
+	ED25519.ECDH_ECPSVDP_DH(S0,W1[:],Z0[:])
+	ED25519.ECDH_ECPSVDP_DH(S1[:],W0[:],Z1[:])
+
+	same:=true
+	for i:=0;i<ED25519.EFS;i++ {
+		if Z0[i]!=Z1[i] {same=false}
+	}
+
+	if !same {
+		fmt.Printf("*** ECPSVDP-DH Failed\n");
+		return
+	}
+
+	KEY:=ED25519.ECDH_KDF2(sha,Z0[:],nil,ED25519.AESKEY);
+
+	fmt.Printf("Alice's DH Key=  0x"); printBinary(KEY)
+	fmt.Printf("Servers DH Key=  0x"); printBinary(KEY)
+	
+	if ED25519.CURVETYPE!=ED25519.MONTGOMERY {
+		fmt.Printf("Testing ECIES\n");
+
+		P1[0]=0x0; P1[1]=0x1; P1[2]=0x2
+		P2[0]=0x0; P2[1]=0x1; P2[2]=0x2; P2[3]=0x3
+
+		for i:=0;i<=16;i++ {M[i]=byte(i)} 
+
+		C:=ED25519.ECDH_ECIES_ENCRYPT(sha,P1[:],P2[:],rng,W1[:],M[:],V[:],T[:])
+
+		fmt.Printf("Ciphertext= \n")
+		fmt.Printf("V= 0x"); printBinary(V[:])
+		fmt.Printf("C= 0x"); printBinary(C)
+		fmt.Printf("T= 0x"); printBinary(T[:])
+
+
+		RM:=ED25519.ECDH_ECIES_DECRYPT(sha,P1[:],P2[:],V[:],C,T[:],S1[:])
+		if RM==nil {
+			fmt.Printf("*** ECIES Decryption Failed\n")
+			return
+		} else {fmt.Printf("Decryption succeeded\n")}
+
+		fmt.Printf("Message is 0x"); printBinary(RM)
+
+		fmt.Printf("Testing ECDSA\n");
+
+		if ED25519.ECDH_ECPSP_DSA(sha,rng,S0,M[:],CS[:],DS[:])!=0 {
+			fmt.Printf("***ECDSA Signature Failed\n")
+			return
+		}
+		fmt.Printf("Signature= \n")
+		fmt.Printf("C= 0x"); printBinary(CS[:])
+		fmt.Printf("D= 0x"); printBinary(DS[:])
+
+		if ED25519.ECDH_ECPVP_DSA(sha,W0[:],M[:],CS[:],DS[:])!=0 {
+			fmt.Printf("***ECDSA Verification Failed\n")
+			return
+		} else {fmt.Printf("ECDSA Signature/Verification succeeded \n")}
+	}
+}
+
+
+func ecdh_NIST256(rng *amcl.RAND) {
+//	j:=0
+	pp:="M0ng00se"
+	res:=0
+
+	var sha=NIST256.HASH_TYPE
+
+	var S1 [NIST256.EGS]byte
+	var W0 [2*NIST256.EFS+1]byte
+	var W1 [2*NIST256.EFS+1]byte
+	var Z0 [NIST256.EFS]byte
+	var Z1 [NIST256.EFS]byte
+	var SALT [8]byte
+	var P1 [3]byte
+	var P2 [4]byte
+	var V [2*NIST256.EFS+1]byte
+	var M [17]byte
+	var T [12]byte
+	var CS [NIST256.EGS]byte
+	var DS [NIST256.EGS]byte
+
+	for i:=0;i<8;i++ {SALT[i]=byte(i+1)}  // set Salt
+
+	fmt.Printf("\nTesting ECDH/ECDSA/ECIES\n")
+	fmt.Printf("Alice's Passphrase= "+pp)
+	fmt.Printf("\n");
+	PW:=[]byte(pp)
+
+/* private key S0 of size MGS bytes derived from Password and Salt */
+
+	S0:=NIST256.ECDH_PBKDF2(sha,PW,SALT[:],1000,NIST256.EGS)
+
+	fmt.Printf("Alice's private key= 0x")
+	printBinary(S0)
+
+/* Generate Key pair S/W */
+	NIST256.ECDH_KEY_PAIR_GENERATE(nil,S0,W0[:])
+
+	fmt.Printf("Alice's public key= 0x")
+	printBinary(W0[:]);
+
+	res=NIST256.ECDH_PUBLIC_KEY_VALIDATE(W0[:])
+	if res!=0 {
+		fmt.Printf("ECP Public Key is invalid!\n")
+		return
+	}
+
+/* Random private key for other party */
+	NIST256.ECDH_KEY_PAIR_GENERATE(rng,S1[:],W1[:])
+
+	fmt.Printf("Servers private key= 0x");
+	printBinary(S1[:])
+
+	fmt.Printf("Servers public key= 0x")
+	printBinary(W1[:])
+
+
+	res=NIST256.ECDH_PUBLIC_KEY_VALIDATE(W1[:])
+	if res!=0 {
+		fmt.Printf("ECP Public Key is invalid!\n")
+		return
+	}
+/* Calculate common key using DH - IEEE 1363 method */
+
+	NIST256.ECDH_ECPSVDP_DH(S0,W1[:],Z0[:])
+	NIST256.ECDH_ECPSVDP_DH(S1[:],W0[:],Z1[:])
+
+	same:=true
+	for i:=0;i<NIST256.EFS;i++ {
+		if Z0[i]!=Z1[i] {same=false}
+	}
+
+	if !same {
+		fmt.Printf("*** ECPSVDP-DH Failed\n");
+		return
+	}
+
+	KEY:=NIST256.ECDH_KDF2(sha,Z0[:],nil,NIST256.AESKEY);
+
+	fmt.Printf("Alice's DH Key=  0x"); printBinary(KEY)
+	fmt.Printf("Servers DH Key=  0x"); printBinary(KEY)
+	
+	if NIST256.CURVETYPE!=NIST256.MONTGOMERY {
+		fmt.Printf("Testing ECIES\n");
+
+		P1[0]=0x0; P1[1]=0x1; P1[2]=0x2
+		P2[0]=0x0; P2[1]=0x1; P2[2]=0x2; P2[3]=0x3
+
+		for i:=0;i<=16;i++ {M[i]=byte(i)} 
+
+		C:=NIST256.ECDH_ECIES_ENCRYPT(sha,P1[:],P2[:],rng,W1[:],M[:],V[:],T[:])
+
+		fmt.Printf("Ciphertext= \n")
+		fmt.Printf("V= 0x"); printBinary(V[:])
+		fmt.Printf("C= 0x"); printBinary(C)
+		fmt.Printf("T= 0x"); printBinary(T[:])
+
+
+		RM:=NIST256.ECDH_ECIES_DECRYPT(sha,P1[:],P2[:],V[:],C,T[:],S1[:])
+		if RM==nil {
+			fmt.Printf("*** ECIES Decryption Failed\n")
+			return
+		} else {fmt.Printf("Decryption succeeded\n")}
+
+		fmt.Printf("Message is 0x"); printBinary(RM)
+
+		fmt.Printf("Testing ECDSA\n");
+
+		if NIST256.ECDH_ECPSP_DSA(sha,rng,S0,M[:],CS[:],DS[:])!=0 {
+			fmt.Printf("***ECDSA Signature Failed\n")
+			return
+		}
+		fmt.Printf("Signature= \n")
+		fmt.Printf("C= 0x"); printBinary(CS[:])
+		fmt.Printf("D= 0x"); printBinary(DS[:])
+
+		if NIST256.ECDH_ECPVP_DSA(sha,W0[:],M[:],CS[:],DS[:])!=0 {
+			fmt.Printf("***ECDSA Verification Failed\n")
+			return
+		} else {fmt.Printf("ECDSA Signature/Verification succeeded \n")}
+	}
+}
+
+
+func ecdh_GOLDILOCKS(rng *amcl.RAND) {
+//	j:=0
+	pp:="M0ng00se"
+	res:=0
+
+	var sha=GOLDILOCKS.HASH_TYPE
+
+	var S1 [GOLDILOCKS.EGS]byte
+	var W0 [2*GOLDILOCKS.EFS+1]byte
+	var W1 [2*GOLDILOCKS.EFS+1]byte
+	var Z0 [GOLDILOCKS.EFS]byte
+	var Z1 [GOLDILOCKS.EFS]byte
+	var SALT [8]byte
+	var P1 [3]byte
+	var P2 [4]byte
+	var V [2*GOLDILOCKS.EFS+1]byte
+	var M [17]byte
+	var T [12]byte
+	var CS [GOLDILOCKS.EGS]byte
+	var DS [GOLDILOCKS.EGS]byte
+
+	for i:=0;i<8;i++ {SALT[i]=byte(i+1)}  // set Salt
+
+	fmt.Printf("\nTesting ECDH/ECDSA/ECIES\n")
+	fmt.Printf("Alice's Passphrase= "+pp)
+	fmt.Printf("\n");
+	PW:=[]byte(pp)
+
+/* private key S0 of size MGS bytes derived from Password and Salt */
+
+	S0:=GOLDILOCKS.ECDH_PBKDF2(sha,PW,SALT[:],1000,GOLDILOCKS.EGS)
+
+	fmt.Printf("Alice's private key= 0x")
+	printBinary(S0)
+
+/* Generate Key pair S/W */
+	GOLDILOCKS.ECDH_KEY_PAIR_GENERATE(nil,S0,W0[:])
+
+	fmt.Printf("Alice's public key= 0x")
+	printBinary(W0[:]);
+
+	res=GOLDILOCKS.ECDH_PUBLIC_KEY_VALIDATE(W0[:])
+	if res!=0 {
+		fmt.Printf("ECP Public Key is invalid!\n")
+		return
+	}
+
+/* Random private key for other party */
+	GOLDILOCKS.ECDH_KEY_PAIR_GENERATE(rng,S1[:],W1[:])
+
+	fmt.Printf("Servers private key= 0x");
+	printBinary(S1[:])
+
+	fmt.Printf("Servers public key= 0x")
+	printBinary(W1[:])
+
+
+	res=GOLDILOCKS.ECDH_PUBLIC_KEY_VALIDATE(W1[:])
+	if res!=0 {
+		fmt.Printf("ECP Public Key is invalid!\n")
+		return
+	}
+/* Calculate common key using DH - IEEE 1363 method */
+
+	GOLDILOCKS.ECDH_ECPSVDP_DH(S0,W1[:],Z0[:])
+	GOLDILOCKS.ECDH_ECPSVDP_DH(S1[:],W0[:],Z1[:])
+
+	same:=true
+	for i:=0;i<GOLDILOCKS.EFS;i++ {
+		if Z0[i]!=Z1[i] {same=false}
+	}
+
+	if !same {
+		fmt.Printf("*** ECPSVDP-DH Failed\n");
+		return
+	}
+
+	KEY:=GOLDILOCKS.ECDH_KDF2(sha,Z0[:],nil,GOLDILOCKS.AESKEY);
+
+	fmt.Printf("Alice's DH Key=  0x"); printBinary(KEY)
+	fmt.Printf("Servers DH Key=  0x"); printBinary(KEY)
+	
+	if GOLDILOCKS.CURVETYPE!=GOLDILOCKS.MONTGOMERY {
+		fmt.Printf("Testing ECIES\n");
+
+		P1[0]=0x0; P1[1]=0x1; P1[2]=0x2
+		P2[0]=0x0; P2[1]=0x1; P2[2]=0x2; P2[3]=0x3
+
+		for i:=0;i<=16;i++ {M[i]=byte(i)} 
+
+		C:=GOLDILOCKS.ECDH_ECIES_ENCRYPT(sha,P1[:],P2[:],rng,W1[:],M[:],V[:],T[:])
+
+		fmt.Printf("Ciphertext= \n")
+		fmt.Printf("V= 0x"); printBinary(V[:])
+		fmt.Printf("C= 0x"); printBinary(C)
+		fmt.Printf("T= 0x"); printBinary(T[:])
+
+
+		RM:=GOLDILOCKS.ECDH_ECIES_DECRYPT(sha,P1[:],P2[:],V[:],C,T[:],S1[:])
+		if RM==nil {
+			fmt.Printf("*** ECIES Decryption Failed\n")
+			return
+		} else {fmt.Printf("Decryption succeeded\n")}
+
+		fmt.Printf("Message is 0x"); printBinary(RM)
+
+		fmt.Printf("Testing ECDSA\n");
+
+		if GOLDILOCKS.ECDH_ECPSP_DSA(sha,rng,S0,M[:],CS[:],DS[:])!=0 {
+			fmt.Printf("***ECDSA Signature Failed\n")
+			return
+		}
+		fmt.Printf("Signature= \n")
+		fmt.Printf("C= 0x"); printBinary(CS[:])
+		fmt.Printf("D= 0x"); printBinary(DS[:])
+
+		if GOLDILOCKS.ECDH_ECPVP_DSA(sha,W0[:],M[:],CS[:],DS[:])!=0 {
+			fmt.Printf("***ECDSA Verification Failed\n")
+			return
+		} else {fmt.Printf("ECDSA Signature/Verification succeeded \n")}
+	}
+}
+
+
+/* Configure mode of operation */
+
+const PERMITS bool=true
+const PINERROR bool=true
+const FULL bool=true
+const SINGLE_PASS bool=false
+
+
+func mpin_BN254(rng *amcl.RAND) {
+
+	var sha=BN254.HASH_TYPE
+
+	const MGS=BN254.MGS
+	const MFS=BN254.MFS
+	const G1S=2*MFS+1 /* Group 1 Size */
+	const G2S=4*MFS; /* Group 2 Size */
+
+	var S [MGS]byte
+	var SST [G2S]byte
+	var TOKEN [G1S]byte
+	var PERMIT [G1S]byte
+	var SEC [G1S]byte
+	var xID [G1S]byte
+	var xCID [G1S]byte
+	var X [MGS]byte
+	var Y [MGS]byte
+	var E [12*MFS]byte
+	var F [12*MFS]byte
+	var HID [G1S]byte
+	var HTID [G1S]byte
+
+	var G1 [12*MFS]byte
+	var G2 [12*MFS]byte
+	var R [MGS]byte
+	var Z [G1S]byte
+	var W [MGS]byte
+	var T [G1S]byte
+	var CK [BN254.AESKEY]byte
+	var SK [BN254.AESKEY]byte
+
+	var HSID []byte
+
+
+/* Trusted Authority set-up */
+
+	fmt.Printf("\nTesting MPIN\n")
+	BN254.MPIN_RANDOM_GENERATE(rng,S[:])
+	fmt.Printf("Master Secret s: 0x");  printBinary(S[:])
+
+ /* Create Client Identity */
+ 	IDstr:= "testUser@miracl.com"
+	CLIENT_ID:=[]byte(IDstr)
+
+	HCID:=BN254.MPIN_HASH_ID(sha,CLIENT_ID)  /* Either Client or TA calculates Hash(ID) - you decide! */
+		
+	fmt.Printf("Client ID= "); printBinary(CLIENT_ID)
+	fmt.Printf("\n")
+
+/* Client and Server are issued secrets by DTA */
+	BN254.MPIN_GET_SERVER_SECRET(S[:],SST[:])
+	fmt.Printf("Server Secret SS: 0x");  printBinary(SST[:])
+
+	BN254.MPIN_GET_CLIENT_SECRET(S[:],HCID,TOKEN[:])
+	fmt.Printf("Client Secret CS: 0x");        
+	printBinary(TOKEN[:])
+
+/* Client extracts PIN from secret to create Token */
+	pin:=1234
+	fmt.Printf("Client extracts PIN= %d",pin)
+	fmt.Printf("\n")
+	rtn:=BN254.MPIN_EXTRACT_PIN(sha,CLIENT_ID,pin,TOKEN[:])
+	if rtn != 0 {
+		fmt.Printf("FAILURE: EXTRACT_PIN rtn: %d",rtn);
+		fmt.Printf("\n")
+	}
+
+	fmt.Printf("Client Token TK: 0x")       
+	printBinary(TOKEN[:]); 
+
+	if FULL {
+		BN254.MPIN_PRECOMPUTE(TOKEN[:],HCID,G1[:],G2[:])
+	}
+
+	date:=0
+	if PERMITS {
+		date=BN254.Today()
+/* Client gets "Time Token" permit from DTA */ 
+		BN254.MPIN_GET_CLIENT_PERMIT(sha,date,S[:],HCID,PERMIT[:])
+		fmt.Printf("Time Permit TP: 0x");  printBinary(PERMIT[:])
+
+/* This encoding makes Time permit look random - Elligator squared */
+		BN254.MPIN_ENCODING(rng,PERMIT[:])
+		fmt.Printf("Encoded Time Permit TP: 0x");  printBinary(PERMIT[:])
+		BN254.MPIN_DECODING(PERMIT[:])
+		fmt.Printf("Decoded Time Permit TP: 0x");  printBinary(PERMIT[:])
+	}
+	pin=0
+	fmt.Printf("\nPIN= ")
+	fmt.Scanf("%d ",&pin)
+
+	pxID:=xID[:]
+	pxCID:=xCID[:]
+	pHID:=HID[:]
+	pHTID:=HTID[:]
+	pE:=E[:]
+	pF:=F[:]
+	pPERMIT:=PERMIT[:]
+	var prHID []byte
+
+	if date!=0 {
+		prHID=pHTID;
+		if !PINERROR {
+			pxID=nil
+			// pHID=nil
+		}
+	} else {
+		prHID=pHID
+		pPERMIT=nil
+		pxCID=nil
+		pHTID=nil
+	}
+	if !PINERROR {
+		pE=nil
+		pF=nil
+	}
+
+	if SINGLE_PASS {
+		fmt.Printf("MPIN Single Pass\n")
+		timeValue:= BN254.MPIN_GET_TIME()
+		rtn=BN254.MPIN_CLIENT(sha,date,CLIENT_ID,rng,X[:],pin,TOKEN[:],SEC[:],pxID,pxCID,pPERMIT,timeValue,Y[:])
+		if rtn != 0 {
+			fmt.Printf("FAILURE: CLIENT rtn: %d\n",rtn)
+		}
+
+		if FULL {
+			HCID=BN254.MPIN_HASH_ID(sha,CLIENT_ID)
+			BN254.MPIN_GET_G1_MULTIPLE(rng,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 {
+  		    fmt.Printf("FAILURE: SERVER rtn: %d\n",rtn)
+		}
+
+		if FULL {
+			HSID=BN254.MPIN_HASH_ID(sha,CLIENT_ID);
+			BN254.MPIN_GET_G1_MULTIPLE(rng,0,W[:],prHID,T[:]);  /* Also send T=w.ID to client, remember random w  */
+		}
+	} else {
+		fmt.Printf("MPIN Multi Pass\n")
+        /* Send U=x.ID to server, and recreate secret from token and pin */
+		rtn=BN254.MPIN_CLIENT_1(sha,date,CLIENT_ID,rng,X[:],pin,TOKEN[:],SEC[:],pxID,pxCID,pPERMIT);
+		if rtn != 0 {
+			fmt.Printf("FAILURE: CLIENT_1 rtn: %d\n",rtn)
+		}
+  
+		if FULL {
+			HCID=BN254.MPIN_HASH_ID(sha,CLIENT_ID)
+			BN254.MPIN_GET_G1_MULTIPLE(rng,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(rng,Y[:]);
+  
+		if FULL {
+			HSID=BN254.MPIN_HASH_ID(sha,CLIENT_ID);
+			BN254.MPIN_GET_G1_MULTIPLE(rng,0,W[:],prHID,T[:])  /* Also send T=w.ID to client, remember random w  */
+		}
+  
+       /* Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC */
+		rtn=BN254.MPIN_CLIENT_2(X[:],Y[:],SEC[:])
+		if rtn != 0 {
+			fmt.Printf("FAILURE: CLIENT_2 rtn: %d\n",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 {
+			fmt.Printf("FAILURE: SERVER_1 rtn: %d\n",rtn)
+		}
+  
+		if rtn == BN254.BAD_PIN {
+			fmt.Printf("Server says - Bad Pin. I don't know you. Feck off.\n")
+			if PINERROR {
+				err:=BN254.MPIN_KANGAROO(E[:],F[:])
+				if err!=0 {fmt.Printf("(Client PIN is out by %d)\n",err)}
+			}
+			return
+		} else {
+			fmt.Printf("Server says - PIN is good! You really are "+IDstr)
+			fmt.Printf("\n")
+		}
+
+		if  FULL {
+			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[:])
+			fmt.Printf("Client Key =  0x");  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[:])
+			fmt.Printf("Server Key =  0x");  printBinary(SK[:])
+		}
+	}
+}
+
+
+func mpin_BLS383(rng *amcl.RAND) {
+
+	var sha=BLS383.HASH_TYPE
+
+	const MGS=BLS383.MGS
+	const MFS=BLS383.MFS
+	const G1S=2*MFS+1 /* Group 1 Size */
+	const G2S=4*MFS; /* Group 2 Size */
+
+	var S [MGS]byte
+	var SST [G2S]byte
+	var TOKEN [G1S]byte
+	var PERMIT [G1S]byte
+	var SEC [G1S]byte
+	var xID [G1S]byte
+	var xCID [G1S]byte
+	var X [MGS]byte
+	var Y [MGS]byte
+	var E [12*MFS]byte
+	var F [12*MFS]byte
+	var HID [G1S]byte
+	var HTID [G1S]byte
+
+	var G1 [12*MFS]byte
+	var G2 [12*MFS]byte
+	var R [MGS]byte
+	var Z [G1S]byte
+	var W [MGS]byte
+	var T [G1S]byte
+	var CK [BLS383.AESKEY]byte
+	var SK [BLS383.AESKEY]byte
+
+	var HSID []byte
+
+
+/* Trusted Authority set-up */
+
+	fmt.Printf("\nTesting MPIN\n")
+	BLS383.MPIN_RANDOM_GENERATE(rng,S[:])
+	fmt.Printf("Master Secret s: 0x");  printBinary(S[:])
+
+ /* Create Client Identity */
+ 	IDstr:= "testUser@miracl.com"
+	CLIENT_ID:=[]byte(IDstr)
+
+	HCID:=BLS383.MPIN_HASH_ID(sha,CLIENT_ID)  /* Either Client or TA calculates Hash(ID) - you decide! */
+		
+	fmt.Printf("Client ID= "); printBinary(CLIENT_ID)
+	fmt.Printf("\n")
+
+/* Client and Server are issued secrets by DTA */
+	BLS383.MPIN_GET_SERVER_SECRET(S[:],SST[:])
+	fmt.Printf("Server Secret SS: 0x");  printBinary(SST[:])
+
+	BLS383.MPIN_GET_CLIENT_SECRET(S[:],HCID,TOKEN[:])
+	fmt.Printf("Client Secret CS: 0x");        
+	printBinary(TOKEN[:])
+
+/* Client extracts PIN from secret to create Token */
+	pin:=1234
+	fmt.Printf("Client extracts PIN= %d",pin)
+	fmt.Printf("\n")
+	rtn:=BLS383.MPIN_EXTRACT_PIN(sha,CLIENT_ID,pin,TOKEN[:])
+	if rtn != 0 {
+		fmt.Printf("FAILURE: EXTRACT_PIN rtn: %d",rtn);
+		fmt.Printf("\n")
+	}
+
+	fmt.Printf("Client Token TK: 0x")       
+	printBinary(TOKEN[:]); 
+
+	if FULL {
+		BLS383.MPIN_PRECOMPUTE(TOKEN[:],HCID,G1[:],G2[:])
+	}
+
+	date:=0
+	if PERMITS {
+		date=BLS383.Today()
+/* Client gets "Time Token" permit from DTA */ 
+		BLS383.MPIN_GET_CLIENT_PERMIT(sha,date,S[:],HCID,PERMIT[:])
+		fmt.Printf("Time Permit TP: 0x");  printBinary(PERMIT[:])
+
+/* This encoding makes Time permit look random - Elligator squared */
+		BLS383.MPIN_ENCODING(rng,PERMIT[:])
+		fmt.Printf("Encoded Time Permit TP: 0x");  printBinary(PERMIT[:])
+		BLS383.MPIN_DECODING(PERMIT[:])
+		fmt.Printf("Decoded Time Permit TP: 0x");  printBinary(PERMIT[:])
+	}
+	pin=0
+	fmt.Printf("\nPIN= ")
+	fmt.Scanf("%d ",&pin)
+
+	pxID:=xID[:]
+	pxCID:=xCID[:]
+	pHID:=HID[:]
+	pHTID:=HTID[:]
+	pE:=E[:]
+	pF:=F[:]
+	pPERMIT:=PERMIT[:]
+	var prHID []byte
+
+	if date!=0 {
+		prHID=pHTID;
+		if !PINERROR {
+			pxID=nil
+			// pHID=nil
+		}
+	} else {
+		prHID=pHID
+		pPERMIT=nil
+		pxCID=nil
+		pHTID=nil
+	}
+	if !PINERROR {
+		pE=nil
+		pF=nil
+	}
+
+	if SINGLE_PASS {
+		fmt.Printf("MPIN Single Pass\n")
+		timeValue:= BLS383.MPIN_GET_TIME()
+		rtn=BLS383.MPIN_CLIENT(sha,date,CLIENT_ID,rng,X[:],pin,TOKEN[:],SEC[:],pxID,pxCID,pPERMIT,timeValue,Y[:])
+		if rtn != 0 {
+			fmt.Printf("FAILURE: CLIENT rtn: %d\n",rtn)
+		}
+
+		if FULL {
+			HCID=BLS383.MPIN_HASH_ID(sha,CLIENT_ID)
+			BLS383.MPIN_GET_G1_MULTIPLE(rng,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 {
+  		    fmt.Printf("FAILURE: SERVER rtn: %d\n",rtn)
+		}
+
+		if FULL {
+			HSID=BLS383.MPIN_HASH_ID(sha,CLIENT_ID);
+			BLS383.MPIN_GET_G1_MULTIPLE(rng,0,W[:],prHID,T[:]);  /* Also send T=w.ID to client, remember random w  */
+		}
+	} else {
+		fmt.Printf("MPIN Multi Pass\n")
+        /* Send U=x.ID to server, and recreate secret from token and pin */
+		rtn=BLS383.MPIN_CLIENT_1(sha,date,CLIENT_ID,rng,X[:],pin,TOKEN[:],SEC[:],pxID,pxCID,pPERMIT);
+		if rtn != 0 {
+			fmt.Printf("FAILURE: CLIENT_1 rtn: %d\n",rtn)
+		}
+  
+		if FULL {
+			HCID=BLS383.MPIN_HASH_ID(sha,CLIENT_ID)
+			BLS383.MPIN_GET_G1_MULTIPLE(rng,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(rng,Y[:]);
+  
+		if FULL {
+			HSID=BLS383.MPIN_HASH_ID(sha,CLIENT_ID);
+			BLS383.MPIN_GET_G1_MULTIPLE(rng,0,W[:],prHID,T[:])  /* Also send T=w.ID to client, remember random w  */
+		}
+  
+       /* Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC */
+		rtn=BLS383.MPIN_CLIENT_2(X[:],Y[:],SEC[:])
+		if rtn != 0 {
+			fmt.Printf("FAILURE: CLIENT_2 rtn: %d\n",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 {
+			fmt.Printf("FAILURE: SERVER_1 rtn: %d\n",rtn)
+		}
+  
+		if rtn == BLS383.BAD_PIN {
+			fmt.Printf("Server says - Bad Pin. I don't know you. Feck off.\n")
+			if PINERROR {
+				err:=BLS383.MPIN_KANGAROO(E[:],F[:])
+				if err!=0 {fmt.Printf("(Client PIN is out by %d)\n",err)}
+			}
+			return
+		} else {
+			fmt.Printf("Server says - PIN is good! You really are "+IDstr)
+			fmt.Printf("\n")
+		}
+
+		if  FULL {
+			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[:])
+			fmt.Printf("Client Key =  0x");  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[:])
+			fmt.Printf("Server Key =  0x");  printBinary(SK[:])
+		}
+	}
+}
+
+
+func mpin_BLS24(rng *amcl.RAND) {
+
+	var sha=BLS24.HASH_TYPE
+
+	const MGS=BLS24.MGS
+	const MFS=BLS24.MFS
+	const G1S=2*MFS+1 /* Group 1 Size */
+	const G2S=8*MFS; /* Group 2 Size */
+
+	var S [MGS]byte
+	var SST [G2S]byte
+	var TOKEN [G1S]byte
+	var PERMIT [G1S]byte
+	var SEC [G1S]byte
+	var xID [G1S]byte
+	var xCID [G1S]byte
+	var X [MGS]byte
+	var Y [MGS]byte
+	var E [24*MFS]byte
+	var F [24*MFS]byte
+	var HID [G1S]byte
+	var HTID [G1S]byte
+
+	var G1 [24*MFS]byte
+	var G2 [24*MFS]byte
+	var R [MGS]byte
+	var Z [G1S]byte
+	var W [MGS]byte
+	var T [G1S]byte
+	var CK [BLS24.AESKEY]byte
+	var SK [BLS24.AESKEY]byte
+
+	var HSID []byte
+
+
+/* Trusted Authority set-up */
+
+	fmt.Printf("\nTesting MPIN\n")
+	BLS24.MPIN_RANDOM_GENERATE(rng,S[:])
+	fmt.Printf("Master Secret s: 0x");  printBinary(S[:])
+
+ /* Create Client Identity */
+ 	IDstr:= "testUser@miracl.com"
+	CLIENT_ID:=[]byte(IDstr)
+
+	HCID:=BLS24.MPIN_HASH_ID(sha,CLIENT_ID)  /* Either Client or TA calculates Hash(ID) - you decide! */
+		
+	fmt.Printf("Client ID= "); printBinary(CLIENT_ID)
+	fmt.Printf("\n")
+
+/* Client and Server are issued secrets by DTA */
+	BLS24.MPIN_GET_SERVER_SECRET(S[:],SST[:])
+	fmt.Printf("Server Secret SS: 0x");  printBinary(SST[:])
+
+	BLS24.MPIN_GET_CLIENT_SECRET(S[:],HCID,TOKEN[:])
+	fmt.Printf("Client Secret CS: 0x");        
+	printBinary(TOKEN[:])
+
+/* Client extracts PIN from secret to create Token */
+	pin:=1234
+	fmt.Printf("Client extracts PIN= %d",pin)
+	fmt.Printf("\n")
+	rtn:=BLS24.MPIN_EXTRACT_PIN(sha,CLIENT_ID,pin,TOKEN[:])
+	if rtn != 0 {
+		fmt.Printf("FAILURE: EXTRACT_PIN rtn: %d",rtn);
+		fmt.Printf("\n")
+	}
+
+	fmt.Printf("Client Token TK: 0x")       
+	printBinary(TOKEN[:]); 
+
+	if FULL {
+		BLS24.MPIN_PRECOMPUTE(TOKEN[:],HCID,G1[:],G2[:])
+	}
+
+	date:=0
+	if PERMITS {
+		date=BLS24.Today()
+/* Client gets "Time Token" permit from DTA */ 
+		BLS24.MPIN_GET_CLIENT_PERMIT(sha,date,S[:],HCID,PERMIT[:])
+		fmt.Printf("Time Permit TP: 0x");  printBinary(PERMIT[:])
+
+/* This encoding makes Time permit look random - Elligator squared */
+		BLS24.MPIN_ENCODING(rng,PERMIT[:])
+		fmt.Printf("Encoded Time Permit TP: 0x");  printBinary(PERMIT[:])
+		BLS24.MPIN_DECODING(PERMIT[:])
+		fmt.Printf("Decoded Time Permit TP: 0x");  printBinary(PERMIT[:])
+	}
+	pin=0
+	fmt.Printf("\nPIN= ")
+	fmt.Scanf("%d ",&pin)
+
+	pxID:=xID[:]
+	pxCID:=xCID[:]
+	pHID:=HID[:]
+	pHTID:=HTID[:]
+	pE:=E[:]
+	pF:=F[:]
+	pPERMIT:=PERMIT[:]
+	var prHID []byte
+
+	if date!=0 {
+		prHID=pHTID;
+		if !PINERROR {
+			pxID=nil
+			// pHID=nil
+		}
+	} else {
+		prHID=pHID
+		pPERMIT=nil
+		pxCID=nil
+		pHTID=nil
+	}
+	if !PINERROR {
+		pE=nil
+		pF=nil
+	}
+
+	if SINGLE_PASS {
+		fmt.Printf("MPIN Single Pass\n")
+		timeValue:= BLS24.MPIN_GET_TIME()
+		rtn=BLS24.MPIN_CLIENT(sha,date,CLIENT_ID,rng,X[:],pin,TOKEN[:],SEC[:],pxID,pxCID,pPERMIT,timeValue,Y[:])
+		if rtn != 0 {
+			fmt.Printf("FAILURE: CLIENT rtn: %d\n",rtn)
+		}
+
+		if FULL {
+			HCID=BLS24.MPIN_HASH_ID(sha,CLIENT_ID)
+			BLS24.MPIN_GET_G1_MULTIPLE(rng,1,R[:],HCID,Z[:])  /* Also Send Z=r.ID to Server, remember random r */
+		}
+
+		rtn=BLS24.MPIN_SERVER(sha,date,pHID,pHTID,Y[:],SST[:],pxID,pxCID,SEC[:],pE,pF,CLIENT_ID,timeValue)
+		if rtn != 0 {
+  		    fmt.Printf("FAILURE: SERVER rtn: %d\n",rtn)
+		}
+
+		if FULL {
+			HSID=BLS24.MPIN_HASH_ID(sha,CLIENT_ID);
+			BLS24.MPIN_GET_G1_MULTIPLE(rng,0,W[:],prHID,T[:]);  /* Also send T=w.ID to client, remember random w  */
+		}
+	} else {
+		fmt.Printf("MPIN Multi Pass\n")
+        /* Send U=x.ID to server, and recreate secret from token and pin */
+		rtn=BLS24.MPIN_CLIENT_1(sha,date,CLIENT_ID,rng,X[:],pin,TOKEN[:],SEC[:],pxID,pxCID,pPERMIT);
+		if rtn != 0 {
+			fmt.Printf("FAILURE: CLIENT_1 rtn: %d\n",rtn)
+		}
+  
+		if FULL {
+			HCID=BLS24.MPIN_HASH_ID(sha,CLIENT_ID)
+			BLS24.MPIN_GET_G1_MULTIPLE(rng,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. */
+		BLS24.MPIN_SERVER_1(sha,date,CLIENT_ID,pHID,pHTID)
+  
+        /* Server generates Random number Y and sends it to Client */
+		BLS24.MPIN_RANDOM_GENERATE(rng,Y[:]);
+  
+		if FULL {
+			HSID=BLS24.MPIN_HASH_ID(sha,CLIENT_ID);
+			BLS24.MPIN_GET_G1_MULTIPLE(rng,0,W[:],prHID,T[:])  /* Also send T=w.ID to client, remember random w  */
+		}
+  
+       /* Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC */
+		rtn=BLS24.MPIN_CLIENT_2(X[:],Y[:],SEC[:])
+		if rtn != 0 {
+			fmt.Printf("FAILURE: CLIENT_2 rtn: %d\n",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=BLS24.MPIN_SERVER_2(date,pHID,pHTID,Y[:],SST[:],pxID,pxCID,SEC[:],pE,pF)
+  
+		if rtn!=0 {
+			fmt.Printf("FAILURE: SERVER_1 rtn: %d\n",rtn)
+		}
+  
+		if rtn == BLS24.BAD_PIN {
+			fmt.Printf("Server says - Bad Pin. I don't know you. Feck off.\n")
+			if PINERROR {
+				err:=BLS24.MPIN_KANGAROO(E[:],F[:])
+				if err!=0 {fmt.Printf("(Client PIN is out by %d)\n",err)}
+			}
+			return
+		} else {
+			fmt.Printf("Server says - PIN is good! You really are "+IDstr)
+			fmt.Printf("\n")
+		}
+
+		if  FULL {
+			H:=BLS24.MPIN_HASH_ALL(sha,HCID[:],pxID,pxCID,SEC[:],Y[:],Z[:],T[:]);
+			BLS24.MPIN_CLIENT_KEY(sha,G1[:],G2[:],pin,R[:],X[:],H[:],T[:],CK[:])
+			fmt.Printf("Client Key =  0x");  printBinary(CK[:])
+
+			H=BLS24.MPIN_HASH_ALL(sha,HSID[:],pxID,pxCID,SEC[:],Y[:],Z[:],T[:]);			
+			BLS24.MPIN_SERVER_KEY(sha,Z[:],SST[:],W[:],H[:],pHID,pxID,pxCID,SK[:])
+			fmt.Printf("Server Key =  0x");  printBinary(SK[:])
+		}
+	}
+}
+
+func mpin_BLS48(rng *amcl.RAND) {
+
+	var sha=BLS48.HASH_TYPE
+
+	const MGS=BLS48.MGS
+	const MFS=BLS48.MFS
+	const G1S=2*MFS+1 /* Group 1 Size */
+	const G2S=16*MFS; /* Group 2 Size */
+
+	var S [MGS]byte
+	var SST [G2S]byte
+	var TOKEN [G1S]byte
+	var PERMIT [G1S]byte
+	var SEC [G1S]byte
+	var xID [G1S]byte
+	var xCID [G1S]byte
+	var X [MGS]byte
+	var Y [MGS]byte
+	var E [48*MFS]byte
+	var F [48*MFS]byte
+	var HID [G1S]byte
+	var HTID [G1S]byte
+
+	var G1 [48*MFS]byte
+	var G2 [48*MFS]byte
+	var R [MGS]byte
+	var Z [G1S]byte
+	var W [MGS]byte
+	var T [G1S]byte
+	var CK [BLS48.AESKEY]byte
+	var SK [BLS48.AESKEY]byte
+
+	var HSID []byte
+
+
+/* Trusted Authority set-up */
+
+	fmt.Printf("\nTesting MPIN\n")
+	BLS48.MPIN_RANDOM_GENERATE(rng,S[:])
+	fmt.Printf("Master Secret s: 0x");  printBinary(S[:])
+
+ /* Create Client Identity */
+ 	IDstr:= "testUser@miracl.com"
+	CLIENT_ID:=[]byte(IDstr)
+
+	HCID:=BLS48.MPIN_HASH_ID(sha,CLIENT_ID)  /* Either Client or TA calculates Hash(ID) - you decide! */
+		
+	fmt.Printf("Client ID= "); printBinary(CLIENT_ID)
+	fmt.Printf("\n")
+
+/* Client and Server are issued secrets by DTA */
+	BLS48.MPIN_GET_SERVER_SECRET(S[:],SST[:])
+	fmt.Printf("Server Secret SS: 0x");  printBinary(SST[:])
+
+	BLS48.MPIN_GET_CLIENT_SECRET(S[:],HCID,TOKEN[:])
+	fmt.Printf("Client Secret CS: 0x");        
+	printBinary(TOKEN[:])
+
+/* Client extracts PIN from secret to create Token */
+	pin:=1234
+	fmt.Printf("Client extracts PIN= %d",pin)
+	fmt.Printf("\n")
+	rtn:=BLS48.MPIN_EXTRACT_PIN(sha,CLIENT_ID,pin,TOKEN[:])
+	if rtn != 0 {
+		fmt.Printf("FAILURE: EXTRACT_PIN rtn: %d",rtn);
+		fmt.Printf("\n")
+	}
+
+	fmt.Printf("Client Token TK: 0x")       
+	printBinary(TOKEN[:]); 
+
+	if FULL {
+		BLS48.MPIN_PRECOMPUTE(TOKEN[:],HCID,G1[:],G2[:])
+	}
+
+	date:=0
+	if PERMITS {
+		date=BLS48.Today()
+/* Client gets "Time Token" permit from DTA */ 
+		BLS48.MPIN_GET_CLIENT_PERMIT(sha,date,S[:],HCID,PERMIT[:])
+		fmt.Printf("Time Permit TP: 0x");  printBinary(PERMIT[:])
+
+/* This encoding makes Time permit look random - Elligator squared */
+		BLS48.MPIN_ENCODING(rng,PERMIT[:])
+		fmt.Printf("Encoded Time Permit TP: 0x");  printBinary(PERMIT[:])
+		BLS48.MPIN_DECODING(PERMIT[:])
+		fmt.Printf("Decoded Time Permit TP: 0x");  printBinary(PERMIT[:])
+	}
+	pin=0
+	fmt.Printf("\nPIN= ")
+	fmt.Scanf("%d ",&pin)
+
+	pxID:=xID[:]
+	pxCID:=xCID[:]
+	pHID:=HID[:]
+	pHTID:=HTID[:]
+	pE:=E[:]
+	pF:=F[:]
+	pPERMIT:=PERMIT[:]
+	var prHID []byte
+
+	if date!=0 {
+		prHID=pHTID;
+		if !PINERROR {
+			pxID=nil
+			// pHID=nil
+		}
+	} else {
+		prHID=pHID
+		pPERMIT=nil
+		pxCID=nil
+		pHTID=nil
+	}
+	if !PINERROR {
+		pE=nil
+		pF=nil
+	}
+
+	if SINGLE_PASS {
+		fmt.Printf("MPIN Single Pass\n")
+		timeValue:= BLS48.MPIN_GET_TIME()
+		rtn=BLS48.MPIN_CLIENT(sha,date,CLIENT_ID,rng,X[:],pin,TOKEN[:],SEC[:],pxID,pxCID,pPERMIT,timeValue,Y[:])
+		if rtn != 0 {
+			fmt.Printf("FAILURE: CLIENT rtn: %d\n",rtn)
+		}
+
+		if FULL {
+			HCID=BLS48.MPIN_HASH_ID(sha,CLIENT_ID)
+			BLS48.MPIN_GET_G1_MULTIPLE(rng,1,R[:],HCID,Z[:])  /* Also Send Z=r.ID to Server, remember random r */
+		}
+
+		rtn=BLS48.MPIN_SERVER(sha,date,pHID,pHTID,Y[:],SST[:],pxID,pxCID,SEC[:],pE,pF,CLIENT_ID,timeValue)
+		if rtn != 0 {
+  		    fmt.Printf("FAILURE: SERVER rtn: %d\n",rtn)
+		}
+
+		if FULL {
+			HSID=BLS48.MPIN_HASH_ID(sha,CLIENT_ID);
+			BLS48.MPIN_GET_G1_MULTIPLE(rng,0,W[:],prHID,T[:]);  /* Also send T=w.ID to client, remember random w  */
+		}
+	} else {
+		fmt.Printf("MPIN Multi Pass\n")
+        /* Send U=x.ID to server, and recreate secret from token and pin */
+		rtn=BLS48.MPIN_CLIENT_1(sha,date,CLIENT_ID,rng,X[:],pin,TOKEN[:],SEC[:],pxID,pxCID,pPERMIT);
+		if rtn != 0 {
+			fmt.Printf("FAILURE: CLIENT_1 rtn: %d\n",rtn)
+		}
+  
+		if FULL {
+			HCID=BLS48.MPIN_HASH_ID(sha,CLIENT_ID)
+			BLS48.MPIN_GET_G1_MULTIPLE(rng,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. */
+		BLS48.MPIN_SERVER_1(sha,date,CLIENT_ID,pHID,pHTID)
+  
+        /* Server generates Random number Y and sends it to Client */
+		BLS48.MPIN_RANDOM_GENERATE(rng,Y[:]);
+  
+		if FULL {
+			HSID=BLS48.MPIN_HASH_ID(sha,CLIENT_ID);
+			BLS48.MPIN_GET_G1_MULTIPLE(rng,0,W[:],prHID,T[:])  /* Also send T=w.ID to client, remember random w  */
+		}
+  
+       /* Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC */
+		rtn=BLS48.MPIN_CLIENT_2(X[:],Y[:],SEC[:])
+		if rtn != 0 {
+			fmt.Printf("FAILURE: CLIENT_2 rtn: %d\n",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=BLS48.MPIN_SERVER_2(date,pHID,pHTID,Y[:],SST[:],pxID,pxCID,SEC[:],pE,pF)
+  
+		if rtn!=0 {
+			fmt.Printf("FAILURE: SERVER_1 rtn: %d\n",rtn)
+		}
+  
+		if rtn == BLS48.BAD_PIN {
+			fmt.Printf("Server says - Bad Pin. I don't know you. Feck off.\n")
+			if PINERROR {
+				err:=BLS48.MPIN_KANGAROO(E[:],F[:])
+				if err!=0 {fmt.Printf("(Client PIN is out by %d)\n",err)}
+			}
+			return
+		} else {
+			fmt.Printf("Server says - PIN is good! You really are "+IDstr)
+			fmt.Printf("\n")
+		}
+
+		if  FULL {
+			H:=BLS48.MPIN_HASH_ALL(sha,HCID[:],pxID,pxCID,SEC[:],Y[:],Z[:],T[:]);
+			BLS48.MPIN_CLIENT_KEY(sha,G1[:],G2[:],pin,R[:],X[:],H[:],T[:],CK[:])
+			fmt.Printf("Client Key =  0x");  printBinary(CK[:])
+
+			H=BLS48.MPIN_HASH_ALL(sha,HSID[:],pxID,pxCID,SEC[:],Y[:],Z[:],T[:]);			
+			BLS48.MPIN_SERVER_KEY(sha,Z[:],SST[:],W[:],H[:],pHID,pxID,pxCID,SK[:])
+			fmt.Printf("Server Key =  0x");  printBinary(SK[:])
+		}
+	}
+}
+
+func rsa_2048(rng *amcl.RAND) {
+	var sha=RSA2048.RSA_HASH_TYPE
+	message:="Hello World\n"
+
+	pub:=RSA2048.New_public_key(RSA2048.FFLEN)
+	priv:=RSA2048.New_private_key(RSA2048.HFLEN)
+
+	var ML [RSA2048.RFS]byte
+	var C [RSA2048.RFS]byte
+	var S [RSA2048.RFS]byte
+
+	fmt.Printf("\nTesting RSA 2048-bit\n")
+	fmt.Printf("Generating public/private key pair\n")
+	RSA2048.RSA_KEY_PAIR(rng,65537,priv,pub)
+
+	M:=[]byte(message)
+
+	fmt.Printf("Encrypting test string\n")
+	E:=RSA2048.RSA_OAEP_ENCODE(sha,M,rng,nil) /* OAEP encode message M to E  */
+
+	RSA2048.RSA_ENCRYPT(pub,E,C[:])    /* encrypt encoded message */
+	fmt.Printf("Ciphertext= 0x"); printBinary(C[:])
+
+	fmt.Printf("Decrypting test string\n");
+	RSA2048.RSA_DECRYPT(priv,C[:],ML[:])
+	MS:=RSA2048.RSA_OAEP_DECODE(sha,nil,ML[:]) /* OAEP decode message  */
+
+	message=string(MS)
+	fmt.Printf(message)
+
+	fmt.Printf("Signing message\n")
+	RSA2048.RSA_PKCS15(sha,M,C[:]); 
+
+	RSA2048.RSA_DECRYPT(priv,C[:],S[:])  /* create signature in S */ 
+
+	fmt.Printf("Signature= 0x"); printBinary(S[:])
+
+	RSA2048.RSA_ENCRYPT(pub,S[:],ML[:])
+
+	cmp:=true
+	if len(C)!=len(ML) {
+		cmp=false
+	} else {
+		for j:=0;j<len(C);j++ {
+			if C[j]!=ML[j] {cmp=false}
+		}
+	}
+	if cmp {
+		fmt.Printf("Signature is valid\n")
+	} else {
+		fmt.Printf("Signature is INVALID\n")
+	}
+
+}
+
+func main() {
+	rng:=amcl.NewRAND()
+	var raw [100]byte
+	for i:=0;i<100;i++ {raw[i]=byte(i+1)}
+	rng.Seed(100,raw[:])
+
+	mpin_BN254(rng)
+	mpin_BLS383(rng)
+	mpin_BLS24(rng)
+	mpin_BLS48(rng)
+	ecdh_ED25519(rng)
+	ecdh_NIST256(rng)
+	ecdh_GOLDILOCKS(rng)
+	rsa_2048(rng)
+}
diff --git a/version3/go/TestNHS.go b/version3/go/TestNHS.go
new file mode 100644
index 0000000..8a1270b
--- /dev/null
+++ b/version3/go/TestNHS.go
@@ -0,0 +1,64 @@
+/*
+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.
+*/
+
+/* test driver and function exerciser for NewHope Simple Functions */
+// See https://eprint.iacr.org/2016/1157 (Alkim, Ducas, Popplemann and Schwabe)
+
+
+package main
+
+import "fmt"
+
+import "github.com/milagro-crypto/amcl/version3/go/amcl"
+//import "amcl"
+
+func main() {
+
+	srng:=amcl.NewRAND()
+	var sraw [100]byte
+	for i:=0;i<100;i++ {sraw[i]=byte(i+1)}
+	srng.Seed(100,sraw[:])
+
+							crng:=amcl.NewRAND()
+							var craw [100]byte
+							for i:=0;i<100;i++ {craw[i]=byte(i+2)}
+							crng.Seed(100,craw[:])
+
+	var S [1792] byte
+
+				var SB [1824] byte	
+	amcl.NHS_SERVER_1(srng,SB[:],S[:])
+				var UC [2176] byte
+							var KEYB [32] byte
+							amcl.NHS_CLIENT(crng,SB[:],UC[:],KEYB[:])
+				
+							fmt.Printf("Bob's Key= ")
+							for i:=0;i<32;i++ {
+								fmt.Printf("%02x", KEYB[i])
+							}
+							fmt.Printf("\n")
+	var KEYA [32] byte
+	amcl.NHS_SERVER_2(S[:],UC[:],KEYA[:])
+
+	fmt.Printf("Alice Key= ")
+	for i:=0;i<32;i++ {
+		fmt.Printf("%02x", KEYA[i])
+	}
+	
+} 
diff --git a/version3/go/config32.py b/version3/go/config32.py
new file mode 100644
index 0000000..fe90f18
--- /dev/null
+++ b/version3/go/config32.py
@@ -0,0 +1,357 @@
+import os
+import sys
+
+deltext=""
+slashtext=""
+copytext=""
+if sys.platform.startswith("darwin")  :
+	copytext="cp "
+	deltext="rm "
+	slashtext="/"
+if sys.platform.startswith("linux")  :
+	copytext="cp "
+	deltext="rm "
+	slashtext="/"
+if sys.platform.startswith("win") :
+	copytext="copy "
+	deltext="del "
+	slashtext="\\"
+
+chosen=[]
+cptr=0
+
+def replace(namefile,oldtext,newtext):
+	f = open(namefile,'r')
+	filedata = f.read()
+	f.close()
+
+	newdata = filedata.replace(oldtext,newtext)
+
+	f = open(namefile,'w')
+	f.write(newdata)
+	f.close()
+
+
+def rsaset(tb,nb,base,ml) :
+	global deltext,slashtext,copytext
+	global cptr,chosen
+
+	chosen.append(tb)
+	cptr=cptr+1
+
+	fpath="amcl"+slashtext+tb+slashtext
+	os.system("mkdir amcl"+slashtext+tb)
+
+	os.system(copytext+"ARCH32.go "+fpath+"ARCH.go")
+	os.system(copytext+"BIG32.go "+fpath+"BIG.go")
+	os.system(copytext+"DBIG.go "+fpath+"DBIG.go")
+	os.system(copytext+"FF32.go "+fpath+"FF.go")
+	os.system(copytext+"RSA.go "+fpath+"RSA.go")
+
+	replace(fpath+"ARCH.go","XXX",tb)
+	replace(fpath+"BIG.go","XXX",tb)
+	replace(fpath+"DBIG.go","XXX",tb)
+	replace(fpath+"FF.go","XXX",tb)
+	replace(fpath+"RSA.go","XXX",tb)
+
+	replace(fpath+"BIG.go","@NB@",nb)
+	replace(fpath+"BIG.go","@BASE@",base)
+
+	replace(fpath+"FF.go","@ML@",ml);
+
+def curveset(tc,nb,base,nbt,m8,mt,ct,pf,stw,sx,cs) :
+	global deltext,slashtext,copytext
+	global cptr,chosen
+
+	chosen.append(tc)
+	cptr=cptr+1
+
+	fpath="amcl"+slashtext+tc+slashtext
+	os.system("mkdir amcl"+slashtext+tc)
+
+	os.system(copytext+"ARCH32.go "+fpath+"ARCH.go")
+	os.system(copytext+"BIG32.go "+fpath+"BIG.go")
+	os.system(copytext+"DBIG.go "+fpath+"DBIG.go")
+	os.system(copytext+"FP.go "+fpath+"FP.go")
+	os.system(copytext+"ECP.go "+fpath+"ECP.go")
+	os.system(copytext+"ECDH.go "+fpath+"ECDH.go")
+	os.system(copytext+"ROM_"+tc+"_32.go "+fpath+"ROM.go")
+
+	replace(fpath+"ARCH.go","XXX",tc)
+	replace(fpath+"BIG.go","XXX",tc)
+	replace(fpath+"DBIG.go","XXX",tc)
+	replace(fpath+"FP.go","XXX",tc)
+	replace(fpath+"ECP.go","XXX",tc)
+	replace(fpath+"ECDH.go","XXX",tc)
+
+	replace(fpath+"BIG.go","@NB@",nb)
+	replace(fpath+"BIG.go","@BASE@",base)
+
+	replace(fpath+"FP.go","@NBT@",nbt)
+	replace(fpath+"FP.go","@M8@",m8)
+	replace(fpath+"FP.go","@MT@",mt)
+
+	ib=int(base)
+	inb=int(nb)
+	inbt=int(nbt)
+	sh=ib*(1+((8*inb-1)//ib))-inbt
+	if sh > 14 :
+		sh=14
+	replace(fpath+"FP.go","@SH@",str(sh))
+
+
+	replace(fpath+"ECP.go","@CT@",ct)
+	replace(fpath+"ECP.go","@PF@",pf)
+
+	replace(fpath+"ECP.go","@ST@",stw)
+	replace(fpath+"ECP.go","@SX@",sx)
+
+	if cs == "128" :
+		replace(fpath+"ECP.go","@HT@","32")
+		replace(fpath+"ECP.go","@AK@","16")
+	if cs == "192" :
+		replace(fpath+"ECP.go","@HT@","48")
+		replace(fpath+"ECP.go","@AK@","24")
+	if cs == "256" :
+		replace(fpath+"ECP.go","@HT@","64")
+		replace(fpath+"ECP.go","@AK@","32")
+
+	if pf != "NOT" :
+
+		os.system(copytext+"FP2.go "+fpath+"FP2.go")
+		os.system(copytext+"FP4.go "+fpath+"FP4.go")
+
+		replace(fpath+"FP2.go","XXX",tc)
+		replace(fpath+"FP4.go","XXX",tc)
+
+		if cs == "128" :
+			os.system(copytext+"ECP2.go "+fpath+"ECP2.go")
+			os.system(copytext+"FP12.go "+fpath+"FP12.go")
+			os.system(copytext+"PAIR.go "+fpath+"PAIR.go")
+			os.system(copytext+"MPIN.go "+fpath+"MPIN.go")
+
+			replace(fpath+"FP12.go","XXX",tc)
+			replace(fpath+"ECP2.go","XXX",tc)
+			replace(fpath+"PAIR.go","XXX",tc)
+			replace(fpath+"MPIN.go","XXX",tc)
+
+		if cs == "192" :
+			os.system(copytext+"FP24.go "+fpath+"FP24.go")
+			os.system(copytext+"FP8.go "+fpath+"FP8.go")
+			os.system(copytext+"ECP4.go "+fpath+"ECP4.go")
+			os.system(copytext+"PAIR192.go "+fpath+"PAIR192.go")
+			os.system(copytext+"MPIN192.go "+fpath+"MPIN192.go")
+
+			replace(fpath+"FP24.go","XXX",tc)
+			replace(fpath+"FP8.go","XXX",tc)
+			replace(fpath+"ECP4.go","XXX",tc)
+			replace(fpath+"PAIR192.go","XXX",tc)
+			replace(fpath+"MPIN192.go","XXX",tc)
+
+		if cs == "256" :
+			os.system(copytext+"FP48.go "+fpath+"FP48.go")
+			os.system(copytext+"FP16.go "+fpath+"FP16.go")
+			os.system(copytext+"FP8.go "+fpath+"FP8.go")
+			os.system(copytext+"ECP8.go "+fpath+"ECP8.go")
+			os.system(copytext+"PAIR256.go "+fpath+"PAIR256.go")
+			os.system(copytext+"MPIN256.go "+fpath+"MPIN256.go")
+
+			replace(fpath+"FP48.go","XXX",tc)
+			replace(fpath+"FP16.go","XXX",tc)
+			replace(fpath+"FP8.go","XXX",tc)
+			replace(fpath+"ECP8.go","XXX",tc)
+			replace(fpath+"PAIR256.go","XXX",tc)
+			replace(fpath+"MPIN256.go","XXX",tc)
+
+
+
+os.system("mkdir amcl")
+os.system(copytext+ "HASH*.go amcl"+slashtext+".")
+os.system(copytext+ "SHA3.go amcl"+slashtext+".")
+os.system(copytext+ "RAND.go amcl"+slashtext+".")
+os.system(copytext+ "AES.go amcl"+slashtext+".")
+os.system(copytext+ "GCM.go amcl"+slashtext+".")
+os.system(copytext+ "NHS.go amcl"+slashtext+".")
+
+print("Elliptic Curves")
+print("1. ED25519")
+print("2. C25519")
+print("3. NIST256")
+print("4. BRAINPOOL")
+print("5. ANSSI")
+print("6. HIFIVE")
+print("7. GOLDILOCKS")
+print("8. NIST384")
+print("9. C41417")
+print("10. NIST521\n")
+print("11. NUMS256W")
+print("12. NUMS256E")
+print("13. NUMS384W")
+print("14. NUMS384E")
+print("15. NUMS512W")
+print("16. NUMS512E")
+print("17. SECP256K1\n")
+
+
+print("Pairing-Friendly Elliptic Curves")
+print("18. BN254")
+print("19. BN254CX")
+print("20. BLS383")
+print("21. BLS381")
+print("22. FP256BN")
+print("23. FP512BN")
+print("24. BLS461\n")
+print("25. BLS24")
+print("26. BLS48\n")
+
+
+print("RSA")
+print("27. RSA2048")
+print("28. RSA3072")
+print("29. RSA4096")
+
+selection=[]
+ptr=0
+max=30
+
+curve_selected=False
+pfcurve_selected=False
+rsa_selected=False
+
+while ptr<max:
+	x=int(input("Choose a Scheme to support - 0 to finish: "))
+	if x == 0:
+		break
+#	print("Choice= ",x)
+	already=False
+	for i in range(0,ptr):
+		if x==selection[i]:
+			already=True
+			break
+	if already:
+		continue
+
+	selection.append(x)
+	ptr=ptr+1
+
+# curveset(curve,big_length_bytes,bits_in_base,modulus_bits,modulus_mod_8,modulus_type,curve_type,pairing_friendly,curve security)
+# where "curve" is the common name for the elliptic curve
+# big_length_bytes is the modulus size rounded up to a number of bytes
+# bits_in_base gives the number base used for 32 bit architectures, as n where the base is 2^n
+# modulus_bits is the actual bit length of the modulus.
+# modulus_mod_8 is the remainder when the modulus is divided by 8
+# modulus_type is NOT_SPECIAL, or PSEUDO_MERSENNE, or MONTGOMERY_Friendly, or GENERALISED_MERSENNE (supported for GOLDILOCKS only)
+# curve_type is WEIERSTRASS, EDWARDS or MONTGOMERY
+# pairing_friendly is BN, BLS or NOT (if not pairing friendly
+# curve security is AES equiavlent, rounded up.
+
+
+	if x==1:
+		curveset("ED25519","32","29","255","5","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==2:
+		curveset("C25519","32","29","255","5","PSEUDO_MERSENNE","MONTGOMERY","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==3:
+		curveset("NIST256","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==4:
+		curveset("BRAINPOOL","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==5:
+		curveset("ANSSI","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+		curve_selected=True
+
+	if x==6:
+		curveset("HIFIVE","42","29","336","5","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","192")
+		curve_selected=True
+	if x==7:
+		curveset("GOLDILOCKS","56","29","448","7","GENERALISED_MERSENNE","EDWARDS","NOT","NOT","NOT","256")
+		curve_selected=True
+	if x==8:
+		curveset("NIST384","48","29","384","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","192")
+		curve_selected=True
+	if x==9:
+		curveset("C41417","52","29","414","7","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","256")
+		curve_selected=True
+	if x==10:
+		curveset("NIST521","66","28","521","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","256")
+		curve_selected=True
+
+	if x==11:
+		curveset("NUMS256W","32","28","256","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==12:
+		curveset("NUMS256E","32","29","256","3","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==13:
+		curveset("NUMS384W","48","29","384","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","192")
+		curve_selected=True
+	if x==14:
+		curveset("NUMS384E","48","29","384","3","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","192")
+		curve_selected=True
+	if x==15:
+		curveset("NUMS512W","64","29","512","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","256")
+		curve_selected=True
+	if x==16:
+		curveset("NUMS512E","64","29","512","7","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","256")
+		curve_selected=True
+
+	if x==17:
+		curveset("SECP256K1","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+		curve_selected=True
+
+	if x==18:
+		curveset("BN254","32","28","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+	if x==19:
+		curveset("BN254CX","32","28","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+	if x==20:
+		curveset("BLS383","48","29","383","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","128")
+		pfcurve_selected=True
+
+	if x==21:
+		curveset("BLS381","48","29","381","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+
+	if x==22:
+		curveset("FP256BN","32","28","256","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+	if x==23:
+		curveset("FP512BN","64","29","512","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","POSITIVEX","128")
+		pfcurve_selected=True
+# https://eprint.iacr.org/2017/334.pdf
+	if x==24:
+		curveset("BLS461","58","28","461","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+
+	if x==25:
+		curveset("BLS24","60","29","479","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","192")
+		pfcurve_selected=True
+
+	if x==26:
+		curveset("BLS48","70","29","556","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","256")
+		pfcurve_selected=True
+
+
+# rsaset(rsaname,big_length_bytes,bits_in_base,multiplier)
+# The RSA name reflects the modulus size, which is a 2^m multiplier
+# of the underlying big length
+
+# There are choices here, different ways of getting the same result, but some faster than others
+	if x==27:
+		#256 is slower but may allow reuse of 256-bit BIGs used for elliptic curve
+		#512 is faster.. but best is 1024
+		rsaset("RSA2048","128","28","2")
+		#rsaset("RSA2048","64","29","4")
+		#rsaset("RSA2048","32","29","8")
+		rsa_selected=True
+	if x==28:
+		rsaset("RSA3072","48","28","8")
+		rsa_selected=True
+	if x==29:
+		#rsaset("RSA4096","32","29","16")
+		rsaset("RSA4096","64","29","8")
+		rsa_selected=True
+
diff --git a/version3/go/config64.py b/version3/go/config64.py
new file mode 100644
index 0000000..7fd616e
--- /dev/null
+++ b/version3/go/config64.py
@@ -0,0 +1,357 @@
+import os
+import sys
+
+deltext=""
+slashtext=""
+copytext=""
+if sys.platform.startswith("darwin")  :
+	copytext="cp "
+	deltext="rm "
+	slashtext="/"
+if sys.platform.startswith("linux")  :
+	copytext="cp "
+	deltext="rm "
+	slashtext="/"
+if sys.platform.startswith("win") :
+	copytext="copy "
+	deltext="del "
+	slashtext="\\"
+
+chosen=[]
+cptr=0
+
+def replace(namefile,oldtext,newtext):
+	f = open(namefile,'r')
+	filedata = f.read()
+	f.close()
+
+	newdata = filedata.replace(oldtext,newtext)
+
+	f = open(namefile,'w')
+	f.write(newdata)
+	f.close()
+
+
+def rsaset(tb,nb,base,ml) :
+	global deltext,slashtext,copytext
+	global cptr,chosen
+
+	chosen.append(tb)
+	cptr=cptr+1
+
+	fpath="amcl"+slashtext+tb+slashtext
+	os.system("mkdir amcl"+slashtext+tb)
+
+	os.system(copytext+"ARCH64.go "+fpath+"ARCH.go")
+	os.system(copytext+"BIG64.go "+fpath+"BIG.go")
+	os.system(copytext+"DBIG.go "+fpath+"DBIG.go")
+	os.system(copytext+"FF64.go "+fpath+"FF.go")
+	os.system(copytext+"RSA.go "+fpath+"RSA.go")
+
+	replace(fpath+"ARCH.go","XXX",tb)
+	replace(fpath+"BIG.go","XXX",tb)
+	replace(fpath+"DBIG.go","XXX",tb)
+	replace(fpath+"FF.go","XXX",tb)
+	replace(fpath+"RSA.go","XXX",tb)
+
+	replace(fpath+"BIG.go","@NB@",nb)
+	replace(fpath+"BIG.go","@BASE@",base)
+
+	replace(fpath+"FF.go","@ML@",ml);
+
+def curveset(tc,nb,base,nbt,m8,mt,ct,pf,stw,sx,cs) :
+	global deltext,slashtext,copytext
+	global cptr,chosen
+
+	chosen.append(tc)
+	cptr=cptr+1
+
+	fpath="amcl"+slashtext+tc+slashtext
+	os.system("mkdir amcl"+slashtext+tc)
+
+	os.system(copytext+"ARCH64.go "+fpath+"ARCH.go")
+	os.system(copytext+"BIG64.go "+fpath+"BIG.go")
+	os.system(copytext+"DBIG.go "+fpath+"DBIG.go")
+	os.system(copytext+"FP.go "+fpath+"FP.go")
+	os.system(copytext+"ECP.go "+fpath+"ECP.go")
+	os.system(copytext+"ECDH.go "+fpath+"ECDH.go")
+	os.system(copytext+"ROM_"+tc+"_64.go "+fpath+"ROM.go")
+
+	replace(fpath+"ARCH.go","XXX",tc)
+	replace(fpath+"BIG.go","XXX",tc)
+	replace(fpath+"DBIG.go","XXX",tc)
+	replace(fpath+"FP.go","XXX",tc)
+	replace(fpath+"ECP.go","XXX",tc)
+	replace(fpath+"ECDH.go","XXX",tc)
+
+	replace(fpath+"BIG.go","@NB@",nb)
+	replace(fpath+"BIG.go","@BASE@",base)
+
+	replace(fpath+"FP.go","@NBT@",nbt)
+	replace(fpath+"FP.go","@M8@",m8)
+	replace(fpath+"FP.go","@MT@",mt)
+
+	ib=int(base)
+	inb=int(nb)
+	inbt=int(nbt)
+	sh=ib*(1+((8*inb-1)//ib))-inbt
+	if sh > 30 :
+		sh=30
+	replace(fpath+"FP.go","@SH@",str(sh))
+
+
+	replace(fpath+"ECP.go","@CT@",ct)
+	replace(fpath+"ECP.go","@PF@",pf)
+
+	replace(fpath+"ECP.go","@ST@",stw)
+	replace(fpath+"ECP.go","@SX@",sx)
+
+	if cs == "128" :
+		replace(fpath+"ECP.go","@HT@","32")
+		replace(fpath+"ECP.go","@AK@","16")
+	if cs == "192" :
+		replace(fpath+"ECP.go","@HT@","48")
+		replace(fpath+"ECP.go","@AK@","24")
+	if cs == "256" :
+		replace(fpath+"ECP.go","@HT@","64")
+		replace(fpath+"ECP.go","@AK@","32")
+
+	if pf != "NOT" :
+
+		os.system(copytext+"FP2.go "+fpath+"FP2.go")
+		os.system(copytext+"FP4.go "+fpath+"FP4.go")
+
+		replace(fpath+"FP2.go","XXX",tc)
+		replace(fpath+"FP4.go","XXX",tc)
+		
+		if cs == "128" :
+
+			os.system(copytext+"ECP2.go "+fpath+"ECP2.go")
+			os.system(copytext+"FP12.go "+fpath+"FP12.go")
+			os.system(copytext+"PAIR.go "+fpath+"PAIR.go")
+			os.system(copytext+"MPIN.go "+fpath+"MPIN.go")
+
+			replace(fpath+"FP12.go","XXX",tc)
+			replace(fpath+"ECP2.go","XXX",tc)
+			replace(fpath+"PAIR.go","XXX",tc)
+			replace(fpath+"MPIN.go","XXX",tc)
+
+		if cs == "192" :
+			os.system(copytext+"FP24.go "+fpath+"FP24.go")
+			os.system(copytext+"FP8.go "+fpath+"FP8.go")
+			os.system(copytext+"ECP4.go "+fpath+"ECP4.go")
+			os.system(copytext+"PAIR192.go "+fpath+"PAIR192.go")
+			os.system(copytext+"MPIN192.go "+fpath+"MPIN192.go")
+
+			replace(fpath+"FP24.go","XXX",tc)
+			replace(fpath+"FP8.go","XXX",tc)
+			replace(fpath+"ECP4.go","XXX",tc)
+			replace(fpath+"PAIR192.go","XXX",tc)
+			replace(fpath+"MPIN192.go","XXX",tc)
+
+		if cs == "256" :
+			os.system(copytext+"FP48.go "+fpath+"FP48.go")
+			os.system(copytext+"FP16.go "+fpath+"FP16.go")
+			os.system(copytext+"FP8.go "+fpath+"FP8.go")
+			os.system(copytext+"ECP8.go "+fpath+"ECP8.go")
+			os.system(copytext+"PAIR256.go "+fpath+"PAIR256.go")
+			os.system(copytext+"MPIN256.go "+fpath+"MPIN256.go")
+
+			replace(fpath+"FP48.go","XXX",tc)
+			replace(fpath+"FP16.go","XXX",tc)
+			replace(fpath+"FP8.go","XXX",tc)
+			replace(fpath+"ECP8.go","XXX",tc)
+			replace(fpath+"PAIR256.go","XXX",tc)
+			replace(fpath+"MPIN256.go","XXX",tc)
+
+
+os.system("mkdir amcl")
+os.system(copytext+ "HASH*.go amcl"+slashtext+".")
+os.system(copytext+ "SHA3.go amcl"+slashtext+".")
+os.system(copytext+ "RAND.go amcl"+slashtext+".")
+os.system(copytext+ "AES.go amcl"+slashtext+".")
+os.system(copytext+ "GCM.go amcl"+slashtext+".")
+os.system(copytext+ "NHS.go amcl"+slashtext+".")
+
+print("Elliptic Curves")
+print("1. ED25519")
+print("2. C25519")
+print("3. NIST256")
+print("4. BRAINPOOL")
+print("5. ANSSI")
+print("6. HIFIVE")
+print("7. GOLDILOCKS")
+print("8. NIST384")
+print("9. C41417")
+print("10. NIST521\n")
+print("11. NUMS256W")
+print("12. NUMS256E")
+print("13. NUMS384W")
+print("14. NUMS384E")
+print("15. NUMS512W")
+print("16. NUMS512E")
+print("17. SECP256K1\n")
+
+
+print("Pairing-Friendly Elliptic Curves")
+print("18. BN254")
+print("19. BN254CX")
+print("20. BLS383")
+print("21. BLS381")
+print("22. FP256BN")
+print("23. FP512BN")
+print("24. BLS461\n")
+print("25. BLS24")
+print("26. BLS48\n")
+
+
+print("RSA")
+print("27. RSA2048")
+print("28. RSA3072")
+print("29. RSA4096")
+
+selection=[]
+ptr=0
+max=30
+
+curve_selected=False
+pfcurve_selected=False
+rsa_selected=False
+
+while ptr<max:
+	x=int(input("Choose a Scheme to support - 0 to finish: "))
+	if x == 0:
+		break
+#	print("Choice= ",x)
+	already=False
+	for i in range(0,ptr):
+		if x==selection[i]:
+			already=True
+			break
+	if already:
+		continue
+
+	selection.append(x)
+	ptr=ptr+1
+
+# curveset(curve,big_length_bytes,bits_in_base,modulus_bits,modulus_mod_8,modulus_type,curve_type,pairing_friendly,curve security)
+# where "curve" is the common name for the elliptic curve
+# big_length_bytes is the modulus size rounded up to a number of bytes
+# bits_in_base gives the number base used for 64 bit architectures, as n where the base is 2^n
+# modulus_bits is the actual bit length of the modulus.
+# modulus_mod_8 is the remainder when the modulus is divided by 8
+# modulus_type is NOT_SPECIAL, or PSEUDO_MERSENNE, or MONTGOMERY_Friendly, or GENERALISED_MERSENNE (supported for GOLDILOCKS only)
+# curve_type is WEIERSTRASS, EDWARDS or MONTGOMERY
+# pairing_friendly is BN, BLS or NOT (if not pairing friendly
+# curve security is AES equiavlent, rounded up.
+
+
+	if x==1:
+		curveset("ED25519","32","56","255","5","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==2:
+		curveset("C25519","32","56","255","5","PSEUDO_MERSENNE","MONTGOMERY","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==3:
+		curveset("NIST256","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==4:
+		curveset("BRAINPOOL","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==5:
+		curveset("ANSSI","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+		curve_selected=True
+
+	if x==6:
+		curveset("HIFIVE","42","60","336","5","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","192")
+		curve_selected=True
+	if x==7:
+		curveset("GOLDILOCKS","56","58","448","7","GENERALISED_MERSENNE","EDWARDS","NOT","NOT","NOT","256")
+		curve_selected=True
+	if x==8:
+		curveset("NIST384","48","56","384","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","192")
+		curve_selected=True
+	if x==9:
+		curveset("C41417","52","60","414","7","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","256")
+		curve_selected=True
+	if x==10:
+		curveset("NIST521","66","60","521","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","256")
+		curve_selected=True
+
+	if x==11:
+		curveset("NUMS256W","32","56","256","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==12:
+		curveset("NUMS256E","32","56","256","3","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==13:
+		curveset("NUMS384W","48","58","384","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","192")
+		curve_selected=True
+	if x==14:
+		curveset("NUMS384E","48","56","384","3","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","192")
+		curve_selected=True
+	if x==15:
+		curveset("NUMS512W","64","60","512","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","256")
+		curve_selected=True
+	if x==16:
+		curveset("NUMS512E","64","60","512","7","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","256")
+		curve_selected=True
+
+	if x==17:
+		curveset("SECP256K1","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+		curve_selected=True
+
+	if x==18:
+		curveset("BN254","32","56","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+	if x==19:
+		curveset("BN254CX","32","56","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+	if x==20:
+		curveset("BLS383","48","58","383","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","128")
+		pfcurve_selected=True
+
+	if x==21:
+		curveset("BLS381","48","58","381","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+
+
+	if x==22:
+		curveset("FP256BN","32","56","256","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+	if x==23:
+		curveset("FP512BN","64","60","512","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","POSITIVEX","128")
+		pfcurve_selected=True
+# https://eprint.iacr.org/2017/334.pdf
+	if x==24:
+		curveset("BLS461","58","60","461","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+
+	if x==25:
+		curveset("BLS24","60","56","479","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","192")
+		pfcurve_selected=True
+
+	if x==26:
+		curveset("BLS48","70","58","556","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","256")
+		pfcurve_selected=True
+
+
+# rsaset(rsaname,big_length_bytes,bits_in_base,multiplier)
+# The RSA name reflects the modulus size, which is a 2^m multiplier
+# of the underlying big length
+
+# There are choices here, different ways of getting the same result, but some faster than others
+	if x==27:
+		#256 is slower but may allow reuse of 256-bit BIGs used for elliptic curve
+		#512 is faster.. but best is 1024
+		rsaset("RSA2048","128","58","2")
+		#rsaset("RSA2048","64","60","4")
+		#rsaset("RSA2048","32","56","8")
+		rsa_selected=True
+	if x==28:
+		rsaset("RSA3072","48","56","8")
+		rsa_selected=True
+	if x==29:
+		#rsaset("RSA4096","32","56","16")
+		rsaset("RSA4096","64","60","8")
+		rsa_selected=True
diff --git a/version3/go/readme.txt b/version3/go/readme.txt
new file mode 100644
index 0000000..49dc5c1
--- /dev/null
+++ b/version3/go/readme.txt
@@ -0,0 +1,49 @@
+Namespaces are used to separate different curves.
+
+So for example to support both ED25519 and the NIST P256 curves, one
+could import into a particular module both "amcl/ED25519" and "amcl/NIST256"
+
+Separate ROM files provide the constants required for each curve. Some
+files (BIG.go, FP.go, ECP.go) also specify certain constants 
+that must be set for the particular curve.
+
+--------------------------------------
+
+Make sure that the GOPATH environmental variable is set.
+
+Then clone the AMCL repository by executing
+
+go get github.com/milagro-crypto/amcl
+
+Ignore the warning message about "no Go files"
+
+This assumes that Git is installed on your machine - see 
+https://git-scm.com/download/
+
+Next navigate to $GOPATH/src/github.com/milagro-crypto/amcl/version3/go
+
+To build the library and see it in action, execute the python3 
+script config32.py or config64.py (depending om whether you want a 
+32 or 64-bit build), and select the curves that you wish to support. 
+
+As a quick example execute
+
+py config64.py
+
+or
+
+python3 config64.py
+
+Then select options 1, 3, 7, 18, 20, 25, 26 and 27 (these are fixed for the example 
+program provided). Select 0 to exit.
+
+Run the test program by executing
+
+go run TestALL.go
+
+The correct PIN is 1234
+
+Next run the Benchmark program by executing
+
+go run BenchtestALL.go
+
diff --git a/version3/java/AES.java b/version3/java/AES.java
new file mode 100644
index 0000000..35d04dc
--- /dev/null
+++ b/version3/java/AES.java
@@ -0,0 +1,695 @@
+/*
+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.
+*/
+
+
+/* AES Encryption */ 
+package org.apache.milagro.amcl;
+
+public class AES {
+	int Nk,Nr;
+	int mode;
+	private int[] fkey=new int[60];
+	private int[] rkey=new int[60];
+	public byte[] f=new byte[16];
+
+
+	public static final int ECB=0;
+	public static final int CBC=1;
+	public static final int CFB1=2;
+	public static final int CFB2=3;
+	public static final int CFB4=5;
+	public static final int OFB1=14;
+	public static final int OFB2=15;
+	public static final int OFB4=17;
+	public static final int OFB8=21;
+	public static final int OFB16=29;
+	public static final int CTR1=30;
+	public static final int CTR2=31;
+	public static final int CTR4=33; 
+	public static final int CTR8=37; 
+	public static final int CTR16=45; 
+
+	private static final byte[] InCo={(byte)0xB,(byte)0xD,(byte)0x9,(byte)0xE};  /* Inverse Coefficients */
+
+	public static final int KS=16; /* Key Size in bytes */
+	public static final int BS=16; /* Block Size */
+
+	private static final byte[] ptab=
+	{(byte)1,(byte)3,(byte)5,(byte)15,(byte)17,(byte)51,(byte)85,(byte)255,(byte)26,(byte)46,(byte)114,(byte)150,(byte)161,(byte)248,(byte)19,(byte)53,
+	(byte)95,(byte)225,(byte)56,(byte)72,(byte)216,(byte)115,(byte)149,(byte)164,(byte)247,(byte)2,(byte)6,(byte)10,(byte)30,(byte)34,(byte)102,(byte)170,
+	(byte)229,(byte)52,(byte)92,(byte)228,(byte)55,(byte)89,(byte)235,(byte)38,(byte)106,(byte)190,(byte)217,(byte)112,(byte)144,(byte)171,(byte)230,(byte)49,
+	(byte)83,(byte)245,(byte)4,(byte)12,(byte)20,(byte)60,(byte)68,(byte)204,(byte)79,(byte)209,(byte)104,(byte)184,(byte)211,(byte)110,(byte)178,(byte)205,
+	(byte)76,(byte)212,(byte)103,(byte)169,(byte)224,(byte)59,(byte)77,(byte)215,(byte)98,(byte)166,(byte)241,(byte)8,(byte)24,(byte)40,(byte)120,(byte)136,
+	(byte)131,(byte)158,(byte)185,(byte)208,(byte)107,(byte)189,(byte)220,(byte)127,(byte)129,(byte)152,(byte)179,(byte)206,(byte)73,(byte)219,(byte)118,(byte)154,
+	(byte)181,(byte)196,(byte)87,(byte)249,(byte)16,(byte)48,(byte)80,(byte)240,(byte)11,(byte)29,(byte)39,(byte)105,(byte)187,(byte)214,(byte)97,(byte)163,
+	(byte)254,(byte)25,(byte)43,(byte)125,(byte)135,(byte)146,(byte)173,(byte)236,(byte)47,(byte)113,(byte)147,(byte)174,(byte)233,(byte)32,(byte)96,(byte)160,
+	(byte)251,(byte)22,(byte)58,(byte)78,(byte)210,(byte)109,(byte)183,(byte)194,(byte)93,(byte)231,(byte)50,(byte)86,(byte)250,(byte)21,(byte)63,(byte)65,
+	(byte)195,(byte)94,(byte)226,(byte)61,(byte)71,(byte)201,(byte)64,(byte)192,(byte)91,(byte)237,(byte)44,(byte)116,(byte)156,(byte)191,(byte)218,(byte)117,
+	(byte)159,(byte)186,(byte)213,(byte)100,(byte)172,(byte)239,(byte)42,(byte)126,(byte)130,(byte)157,(byte)188,(byte)223,(byte)122,(byte)142,(byte)137,(byte)128,
+	(byte)155,(byte)182,(byte)193,(byte)88,(byte)232,(byte)35,(byte)101,(byte)175,(byte)234,(byte)37,(byte)111,(byte)177,(byte)200,(byte)67,(byte)197,(byte)84,
+	(byte)252,(byte)31,(byte)33,(byte)99,(byte)165,(byte)244,(byte)7,(byte)9,(byte)27,(byte)45,(byte)119,(byte)153,(byte)176,(byte)203,(byte)70,(byte)202,
+	(byte)69,(byte)207,(byte)74,(byte)222,(byte)121,(byte)139,(byte)134,(byte)145,(byte)168,(byte)227,(byte)62,(byte)66,(byte)198,(byte)81,(byte)243,(byte)14,
+	(byte)18,(byte)54,(byte)90,(byte)238,(byte)41,(byte)123,(byte)141,(byte)140,(byte)143,(byte)138,(byte)133,(byte)148,(byte)167,(byte)242,(byte)13,(byte)23,
+	(byte)57,(byte)75,(byte)221,(byte)124,(byte)132,(byte)151,(byte)162,(byte)253,(byte)28,(byte)36,(byte)108,(byte)180,(byte)199,(byte)82,(byte)246,(byte)1};
+
+	private static final byte[] ltab=
+	{(byte)0,(byte)255,(byte)25,(byte)1,(byte)50,(byte)2,(byte)26,(byte)198,(byte)75,(byte)199,(byte)27,(byte)104,(byte)51,(byte)238,(byte)223,(byte)3,
+	(byte)100,(byte)4,(byte)224,(byte)14,(byte)52,(byte)141,(byte)129,(byte)239,(byte)76,(byte)113,(byte)8,(byte)200,(byte)248,(byte)105,(byte)28,(byte)193,
+	(byte)125,(byte)194,(byte)29,(byte)181,(byte)249,(byte)185,(byte)39,(byte)106,(byte)77,(byte)228,(byte)166,(byte)114,(byte)154,(byte)201,(byte)9,(byte)120,
+	(byte)101,(byte)47,(byte)138,(byte)5,(byte)33,(byte)15,(byte)225,(byte)36,(byte)18,(byte)240,(byte)130,(byte)69,(byte)53,(byte)147,(byte)218,(byte)142,
+	(byte)150,(byte)143,(byte)219,(byte)189,(byte)54,(byte)208,(byte)206,(byte)148,(byte)19,(byte)92,(byte)210,(byte)241,(byte)64,(byte)70,(byte)131,(byte)56,
+	(byte)102,(byte)221,(byte)253,(byte)48,(byte)191,(byte)6,(byte)139,(byte)98,(byte)179,(byte)37,(byte)226,(byte)152,(byte)34,(byte)136,(byte)145,(byte)16,
+	(byte)126,(byte)110,(byte)72,(byte)195,(byte)163,(byte)182,(byte)30,(byte)66,(byte)58,(byte)107,(byte)40,(byte)84,(byte)250,(byte)133,(byte)61,(byte)186,
+	(byte)43,(byte)121,(byte)10,(byte)21,(byte)155,(byte)159,(byte)94,(byte)202,(byte)78,(byte)212,(byte)172,(byte)229,(byte)243,(byte)115,(byte)167,(byte)87,
+	(byte)175,(byte)88,(byte)168,(byte)80,(byte)244,(byte)234,(byte)214,(byte)116,(byte)79,(byte)174,(byte)233,(byte)213,(byte)231,(byte)230,(byte)173,(byte)232,
+	(byte)44,(byte)215,(byte)117,(byte)122,(byte)235,(byte)22,(byte)11,(byte)245,(byte)89,(byte)203,(byte)95,(byte)176,(byte)156,(byte)169,(byte)81,(byte)160,
+	(byte)127,(byte)12,(byte)246,(byte)111,(byte)23,(byte)196,(byte)73,(byte)236,(byte)216,(byte)67,(byte)31,(byte)45,(byte)164,(byte)118,(byte)123,(byte)183,
+	(byte)204,(byte)187,(byte)62,(byte)90,(byte)251,(byte)96,(byte)177,(byte)134,(byte)59,(byte)82,(byte)161,(byte)108,(byte)170,(byte)85,(byte)41,(byte)157,
+	(byte)151,(byte)178,(byte)135,(byte)144,(byte)97,(byte)190,(byte)220,(byte)252,(byte)188,(byte)149,(byte)207,(byte)205,(byte)55,(byte)63,(byte)91,(byte)209,
+	(byte)83,(byte)57,(byte)132,(byte)60,(byte)65,(byte)162,(byte)109,(byte)71,(byte)20,(byte)42,(byte)158,(byte)93,(byte)86,(byte)242,(byte)211,(byte)171,
+	(byte)68,(byte)17,(byte)146,(byte)217,(byte)35,(byte)32,(byte)46,(byte)137,(byte)180,(byte)124,(byte)184,(byte)38,(byte)119,(byte)153,(byte)227,(byte)165,
+	(byte)103,(byte)74,(byte)237,(byte)222,(byte)197,(byte)49,(byte)254,(byte)24,(byte)13,(byte)99,(byte)140,(byte)128,(byte)192,(byte)247,(byte)112,(byte)7};
+
+	private static final byte[] fbsub=
+	{(byte)99,(byte)124,(byte)119,(byte)123,(byte)242,(byte)107,(byte)111,(byte)197,(byte)48,(byte)1,(byte)103,(byte)43,(byte)254,(byte)215,(byte)171,(byte)118,
+	(byte)202,(byte)130,(byte)201,(byte)125,(byte)250,(byte)89,(byte)71,(byte)240,(byte)173,(byte)212,(byte)162,(byte)175,(byte)156,(byte)164,(byte)114,(byte)192,
+	(byte)183,(byte)253,(byte)147,(byte)38,(byte)54,(byte)63,(byte)247,(byte)204,(byte)52,(byte)165,(byte)229,(byte)241,(byte)113,(byte)216,(byte)49,(byte)21,
+	(byte)4,(byte)199,(byte)35,(byte)195,(byte)24,(byte)150,(byte)5,(byte)154,(byte)7,(byte)18,(byte)128,(byte)226,(byte)235,(byte)39,(byte)178,(byte)117,
+	(byte)9,(byte)131,(byte)44,(byte)26,(byte)27,(byte)110,(byte)90,(byte)160,(byte)82,(byte)59,(byte)214,(byte)179,(byte)41,(byte)227,(byte)47,(byte)132,
+	(byte)83,(byte)209,(byte)0,(byte)237,(byte)32,(byte)252,(byte)177,(byte)91,(byte)106,(byte)203,(byte)190,(byte)57,(byte)74,(byte)76,(byte)88,(byte)207,
+	(byte)208,(byte)239,(byte)170,(byte)251,(byte)67,(byte)77,(byte)51,(byte)133,(byte)69,(byte)249,(byte)2,(byte)127,(byte)80,(byte)60,(byte)159,(byte)168,
+	(byte)81,(byte)163,(byte)64,(byte)143,(byte)146,(byte)157,(byte)56,(byte)245,(byte)188,(byte)182,(byte)218,(byte)33,(byte)16,(byte)255,(byte)243,(byte)210,
+	(byte)205,(byte)12,(byte)19,(byte)236,(byte)95,(byte)151,(byte)68,(byte)23,(byte)196,(byte)167,(byte)126,(byte)61,(byte)100,(byte)93,(byte)25,(byte)115,
+	(byte)96,(byte)129,(byte)79,(byte)220,(byte)34,(byte)42,(byte)144,(byte)136,(byte)70,(byte)238,(byte)184,(byte)20,(byte)222,(byte)94,(byte)11,(byte)219,
+	(byte)224,(byte)50,(byte)58,(byte)10,(byte)73,(byte)6,(byte)36,(byte)92,(byte)194,(byte)211,(byte)172,(byte)98,(byte)145,(byte)149,(byte)228,(byte)121,
+	(byte)231,(byte)200,(byte)55,(byte)109,(byte)141,(byte)213,(byte)78,(byte)169,(byte)108,(byte)86,(byte)244,(byte)234,(byte)101,(byte)122,(byte)174,(byte)8,
+	(byte)186,(byte)120,(byte)37,(byte)46,(byte)28,(byte)166,(byte)180,(byte)198,(byte)232,(byte)221,(byte)116,(byte)31,(byte)75,(byte)189,(byte)139,(byte)138,
+	(byte)112,(byte)62,(byte)181,(byte)102,(byte)72,(byte)3,(byte)246,(byte)14,(byte)97,(byte)53,(byte)87,(byte)185,(byte)134,(byte)193,(byte)29,(byte)158,
+	(byte)225,(byte)248,(byte)152,(byte)17,(byte)105,(byte)217,(byte)142,(byte)148,(byte)155,(byte)30,(byte)135,(byte)233,(byte)206,(byte)85,(byte)40,(byte)223,
+	(byte)140,(byte)161,(byte)137,(byte)13,(byte)191,(byte)230,(byte)66,(byte)104,(byte)65,(byte)153,(byte)45,(byte)15,(byte)176,(byte)84,(byte)187,(byte)22};
+
+	private static final byte[] rbsub=
+	{(byte)82,(byte)9,(byte)106,(byte)213,(byte)48,(byte)54,(byte)165,(byte)56,(byte)191,(byte)64,(byte)163,(byte)158,(byte)129,(byte)243,(byte)215,(byte)251,
+	(byte)124,(byte)227,(byte)57,(byte)130,(byte)155,(byte)47,(byte)255,(byte)135,(byte)52,(byte)142,(byte)67,(byte)68,(byte)196,(byte)222,(byte)233,(byte)203,
+	(byte)84,(byte)123,(byte)148,(byte)50,(byte)166,(byte)194,(byte)35,(byte)61,(byte)238,(byte)76,(byte)149,(byte)11,(byte)66,(byte)250,(byte)195,(byte)78,
+	(byte)8,(byte)46,(byte)161,(byte)102,(byte)40,(byte)217,(byte)36,(byte)178,(byte)118,(byte)91,(byte)162,(byte)73,(byte)109,(byte)139,(byte)209,(byte)37,
+	(byte)114,(byte)248,(byte)246,(byte)100,(byte)134,(byte)104,(byte)152,(byte)22,(byte)212,(byte)164,(byte)92,(byte)204,(byte)93,(byte)101,(byte)182,(byte)146,
+	(byte)108,(byte)112,(byte)72,(byte)80,(byte)253,(byte)237,(byte)185,(byte)218,(byte)94,(byte)21,(byte)70,(byte)87,(byte)167,(byte)141,(byte)157,(byte)132,
+	(byte)144,(byte)216,(byte)171,(byte)0,(byte)140,(byte)188,(byte)211,(byte)10,(byte)247,(byte)228,(byte)88,(byte)5,(byte)184,(byte)179,(byte)69,(byte)6,
+	(byte)208,(byte)44,(byte)30,(byte)143,(byte)202,(byte)63,(byte)15,(byte)2,(byte)193,(byte)175,(byte)189,(byte)3,(byte)1,(byte)19,(byte)138,(byte)107,
+	(byte)58,(byte)145,(byte)17,(byte)65,(byte)79,(byte)103,(byte)220,(byte)234,(byte)151,(byte)242,(byte)207,(byte)206,(byte)240,(byte)180,(byte)230,(byte)115,
+	(byte)150,(byte)172,(byte)116,(byte)34,(byte)231,(byte)173,(byte)53,(byte)133,(byte)226,(byte)249,(byte)55,(byte)232,(byte)28,(byte)117,(byte)223,(byte)110,
+	(byte)71,(byte)241,(byte)26,(byte)113,(byte)29,(byte)41,(byte)197,(byte)137,(byte)111,(byte)183,(byte)98,(byte)14,(byte)170,(byte)24,(byte)190,(byte)27,
+	(byte)252,(byte)86,(byte)62,(byte)75,(byte)198,(byte)210,(byte)121,(byte)32,(byte)154,(byte)219,(byte)192,(byte)254,(byte)120,(byte)205,(byte)90,(byte)244,
+	(byte)31,(byte)221,(byte)168,(byte)51,(byte)136,(byte)7,(byte)199,(byte)49,(byte)177,(byte)18,(byte)16,(byte)89,(byte)39,(byte)128,(byte)236,(byte)95,
+	(byte)96,(byte)81,(byte)127,(byte)169,(byte)25,(byte)181,(byte)74,(byte)13,(byte)45,(byte)229,(byte)122,(byte)159,(byte)147,(byte)201,(byte)156,(byte)239,
+	(byte)160,(byte)224,(byte)59,(byte)77,(byte)174,(byte)42,(byte)245,(byte)176,(byte)200,(byte)235,(byte)187,(byte)60,(byte)131,(byte)83,(byte)153,(byte)97,
+	(byte)23,(byte)43,(byte)4,(byte)126,(byte)186,(byte)119,(byte)214,(byte)38,(byte)225,(byte)105,(byte)20,(byte)99,(byte)85,(byte)33,(byte)12,(byte)125};
+
+	private static final byte[] rco=
+	{(byte)1,(byte)2,(byte)4,(byte)8,(byte)16,(byte)32,(byte)64,(byte)128,(byte)27,(byte)54,(byte)108,(byte)216,(byte)171,(byte)77,(byte)154,(byte)47};
+
+	private static final int[] ftable=
+	{0xa56363c6,0x847c7cf8,0x997777ee,0x8d7b7bf6,0xdf2f2ff,0xbd6b6bd6,
+	0xb16f6fde,0x54c5c591,0x50303060,0x3010102,0xa96767ce,0x7d2b2b56,
+	0x19fefee7,0x62d7d7b5,0xe6abab4d,0x9a7676ec,0x45caca8f,0x9d82821f,
+	0x40c9c989,0x877d7dfa,0x15fafaef,0xeb5959b2,0xc947478e,0xbf0f0fb,
+	0xecadad41,0x67d4d4b3,0xfda2a25f,0xeaafaf45,0xbf9c9c23,0xf7a4a453,
+	0x967272e4,0x5bc0c09b,0xc2b7b775,0x1cfdfde1,0xae93933d,0x6a26264c,
+	0x5a36366c,0x413f3f7e,0x2f7f7f5,0x4fcccc83,0x5c343468,0xf4a5a551,
+	0x34e5e5d1,0x8f1f1f9,0x937171e2,0x73d8d8ab,0x53313162,0x3f15152a,
+	0xc040408,0x52c7c795,0x65232346,0x5ec3c39d,0x28181830,0xa1969637,
+	0xf05050a,0xb59a9a2f,0x907070e,0x36121224,0x9b80801b,0x3de2e2df,
+	0x26ebebcd,0x6927274e,0xcdb2b27f,0x9f7575ea,0x1b090912,0x9e83831d,
+	0x742c2c58,0x2e1a1a34,0x2d1b1b36,0xb26e6edc,0xee5a5ab4,0xfba0a05b,
+	0xf65252a4,0x4d3b3b76,0x61d6d6b7,0xceb3b37d,0x7b292952,0x3ee3e3dd,
+	0x712f2f5e,0x97848413,0xf55353a6,0x68d1d1b9,0x0,0x2cededc1,
+	0x60202040,0x1ffcfce3,0xc8b1b179,0xed5b5bb6,0xbe6a6ad4,0x46cbcb8d,
+	0xd9bebe67,0x4b393972,0xde4a4a94,0xd44c4c98,0xe85858b0,0x4acfcf85,
+	0x6bd0d0bb,0x2aefefc5,0xe5aaaa4f,0x16fbfbed,0xc5434386,0xd74d4d9a,
+	0x55333366,0x94858511,0xcf45458a,0x10f9f9e9,0x6020204,0x817f7ffe,
+	0xf05050a0,0x443c3c78,0xba9f9f25,0xe3a8a84b,0xf35151a2,0xfea3a35d,
+	0xc0404080,0x8a8f8f05,0xad92923f,0xbc9d9d21,0x48383870,0x4f5f5f1,
+	0xdfbcbc63,0xc1b6b677,0x75dadaaf,0x63212142,0x30101020,0x1affffe5,
+	0xef3f3fd,0x6dd2d2bf,0x4ccdcd81,0x140c0c18,0x35131326,0x2fececc3,
+	0xe15f5fbe,0xa2979735,0xcc444488,0x3917172e,0x57c4c493,0xf2a7a755,
+	0x827e7efc,0x473d3d7a,0xac6464c8,0xe75d5dba,0x2b191932,0x957373e6,
+	0xa06060c0,0x98818119,0xd14f4f9e,0x7fdcdca3,0x66222244,0x7e2a2a54,
+	0xab90903b,0x8388880b,0xca46468c,0x29eeeec7,0xd3b8b86b,0x3c141428,
+	0x79dedea7,0xe25e5ebc,0x1d0b0b16,0x76dbdbad,0x3be0e0db,0x56323264,
+	0x4e3a3a74,0x1e0a0a14,0xdb494992,0xa06060c,0x6c242448,0xe45c5cb8,
+	0x5dc2c29f,0x6ed3d3bd,0xefacac43,0xa66262c4,0xa8919139,0xa4959531,
+	0x37e4e4d3,0x8b7979f2,0x32e7e7d5,0x43c8c88b,0x5937376e,0xb76d6dda,
+	0x8c8d8d01,0x64d5d5b1,0xd24e4e9c,0xe0a9a949,0xb46c6cd8,0xfa5656ac,
+	0x7f4f4f3,0x25eaeacf,0xaf6565ca,0x8e7a7af4,0xe9aeae47,0x18080810,
+	0xd5baba6f,0x887878f0,0x6f25254a,0x722e2e5c,0x241c1c38,0xf1a6a657,
+	0xc7b4b473,0x51c6c697,0x23e8e8cb,0x7cdddda1,0x9c7474e8,0x211f1f3e,
+	0xdd4b4b96,0xdcbdbd61,0x868b8b0d,0x858a8a0f,0x907070e0,0x423e3e7c,
+	0xc4b5b571,0xaa6666cc,0xd8484890,0x5030306,0x1f6f6f7,0x120e0e1c,
+	0xa36161c2,0x5f35356a,0xf95757ae,0xd0b9b969,0x91868617,0x58c1c199,
+	0x271d1d3a,0xb99e9e27,0x38e1e1d9,0x13f8f8eb,0xb398982b,0x33111122,
+	0xbb6969d2,0x70d9d9a9,0x898e8e07,0xa7949433,0xb69b9b2d,0x221e1e3c,
+	0x92878715,0x20e9e9c9,0x49cece87,0xff5555aa,0x78282850,0x7adfdfa5,
+	0x8f8c8c03,0xf8a1a159,0x80898909,0x170d0d1a,0xdabfbf65,0x31e6e6d7,
+	0xc6424284,0xb86868d0,0xc3414182,0xb0999929,0x772d2d5a,0x110f0f1e,
+	0xcbb0b07b,0xfc5454a8,0xd6bbbb6d,0x3a16162c};
+
+	private static final int[] rtable=
+	{0x50a7f451,0x5365417e,0xc3a4171a,0x965e273a,0xcb6bab3b,0xf1459d1f,
+	0xab58faac,0x9303e34b,0x55fa3020,0xf66d76ad,0x9176cc88,0x254c02f5,
+	0xfcd7e54f,0xd7cb2ac5,0x80443526,0x8fa362b5,0x495ab1de,0x671bba25,
+	0x980eea45,0xe1c0fe5d,0x2752fc3,0x12f04c81,0xa397468d,0xc6f9d36b,
+	0xe75f8f03,0x959c9215,0xeb7a6dbf,0xda595295,0x2d83bed4,0xd3217458,
+	0x2969e049,0x44c8c98e,0x6a89c275,0x78798ef4,0x6b3e5899,0xdd71b927,
+	0xb64fe1be,0x17ad88f0,0x66ac20c9,0xb43ace7d,0x184adf63,0x82311ae5,
+	0x60335197,0x457f5362,0xe07764b1,0x84ae6bbb,0x1ca081fe,0x942b08f9,
+	0x58684870,0x19fd458f,0x876cde94,0xb7f87b52,0x23d373ab,0xe2024b72,
+	0x578f1fe3,0x2aab5566,0x728ebb2,0x3c2b52f,0x9a7bc586,0xa50837d3,
+	0xf2872830,0xb2a5bf23,0xba6a0302,0x5c8216ed,0x2b1ccf8a,0x92b479a7,
+	0xf0f207f3,0xa1e2694e,0xcdf4da65,0xd5be0506,0x1f6234d1,0x8afea6c4,
+	0x9d532e34,0xa055f3a2,0x32e18a05,0x75ebf6a4,0x39ec830b,0xaaef6040,
+	0x69f715e,0x51106ebd,0xf98a213e,0x3d06dd96,0xae053edd,0x46bde64d,
+	0xb58d5491,0x55dc471,0x6fd40604,0xff155060,0x24fb9819,0x97e9bdd6,
+	0xcc434089,0x779ed967,0xbd42e8b0,0x888b8907,0x385b19e7,0xdbeec879,
+	0x470a7ca1,0xe90f427c,0xc91e84f8,0x0,0x83868009,0x48ed2b32,
+	0xac70111e,0x4e725a6c,0xfbff0efd,0x5638850f,0x1ed5ae3d,0x27392d36,
+	0x64d90f0a,0x21a65c68,0xd1545b9b,0x3a2e3624,0xb1670a0c,0xfe75793,
+	0xd296eeb4,0x9e919b1b,0x4fc5c080,0xa220dc61,0x694b775a,0x161a121c,
+	0xaba93e2,0xe52aa0c0,0x43e0223c,0x1d171b12,0xb0d090e,0xadc78bf2,
+	0xb9a8b62d,0xc8a91e14,0x8519f157,0x4c0775af,0xbbdd99ee,0xfd607fa3,
+	0x9f2601f7,0xbcf5725c,0xc53b6644,0x347efb5b,0x7629438b,0xdcc623cb,
+	0x68fcedb6,0x63f1e4b8,0xcadc31d7,0x10856342,0x40229713,0x2011c684,
+	0x7d244a85,0xf83dbbd2,0x1132f9ae,0x6da129c7,0x4b2f9e1d,0xf330b2dc,
+	0xec52860d,0xd0e3c177,0x6c16b32b,0x99b970a9,0xfa489411,0x2264e947,
+	0xc48cfca8,0x1a3ff0a0,0xd82c7d56,0xef903322,0xc74e4987,0xc1d138d9,
+	0xfea2ca8c,0x360bd498,0xcf81f5a6,0x28de7aa5,0x268eb7da,0xa4bfad3f,
+	0xe49d3a2c,0xd927850,0x9bcc5f6a,0x62467e54,0xc2138df6,0xe8b8d890,
+	0x5ef7392e,0xf5afc382,0xbe805d9f,0x7c93d069,0xa92dd56f,0xb31225cf,
+	0x3b99acc8,0xa77d1810,0x6e639ce8,0x7bbb3bdb,0x97826cd,0xf418596e,
+	0x1b79aec,0xa89a4f83,0x656e95e6,0x7ee6ffaa,0x8cfbc21,0xe6e815ef,
+	0xd99be7ba,0xce366f4a,0xd4099fea,0xd67cb029,0xafb2a431,0x31233f2a,
+	0x3094a5c6,0xc066a235,0x37bc4e74,0xa6ca82fc,0xb0d090e0,0x15d8a733,
+	0x4a9804f1,0xf7daec41,0xe50cd7f,0x2ff69117,0x8dd64d76,0x4db0ef43,
+	0x544daacc,0xdf0496e4,0xe3b5d19e,0x1b886a4c,0xb81f2cc1,0x7f516546,
+	0x4ea5e9d,0x5d358c01,0x737487fa,0x2e410bfb,0x5a1d67b3,0x52d2db92,
+	0x335610e9,0x1347d66d,0x8c61d79a,0x7a0ca137,0x8e14f859,0x893c13eb,
+	0xee27a9ce,0x35c961b7,0xede51ce1,0x3cb1477a,0x59dfd29c,0x3f73f255,
+	0x79ce1418,0xbf37c773,0xeacdf753,0x5baafd5f,0x146f3ddf,0x86db4478,
+	0x81f3afca,0x3ec468b9,0x2c342438,0x5f40a3c2,0x72c31d16,0xc25e2bc,
+	0x8b493c28,0x41950dff,0x7101a839,0xdeb30c08,0x9ce4b4d8,0x90c15664,
+	0x6184cb7b,0x70b632d5,0x745c6c48,0x4257b8d0};
+
+
+/* Rotates 32-bit word left by 1, 2 or 3 byte  */
+
+	private static int ROTL8(int x)
+	{
+		return (((x)<<8)|((x)>>>24));
+	}
+
+	private static int ROTL16(int x)
+	{
+		return (((x)<<16)|((x)>>>16));
+	}
+
+	private static int ROTL24(int x)
+	{
+		return (((x)<<24)|((x)>>>8));
+	}
+
+	private static int pack(byte[] b)
+	{ /* pack bytes into a 32-bit Word */
+		return ((((int)b[3])&0xff)<<24)|(((int)b[2]&0xff)<<16)|(((int)b[1]&0xff)<<8)|((int)b[0]&0xff);
+	}
+
+	private static byte[] unpack(int a)
+	{ /* unpack bytes from a word */
+		byte [] b=new byte[4];
+		b[0]=(byte)(a);
+		b[1]=(byte)(a>>>8);
+		b[2]=(byte)(a>>>16);
+		b[3]=(byte)(a>>>24);
+		return b;
+	}
+
+	private static byte bmul(byte x,byte y)
+	{ /* x.y= AntiLog(Log(x) + Log(y)) */
+
+		int ix=((int)x)&0xff;
+		int iy=((int)y)&0xff;
+		int lx=((int)ltab[ix])&0xff;
+		int ly=((int)ltab[iy])&0xff;
+		if (x!=0 && y!=0) return ptab[(lx+ly)%255];
+		else return (byte)0;
+	}
+
+  //  if (x && y) 
+
+	private static int SubByte(int a)
+	{
+		byte [] b=unpack(a);
+		b[0]=fbsub[(int)b[0]&0xff];
+		b[1]=fbsub[(int)b[1]&0xff];
+		b[2]=fbsub[(int)b[2]&0xff];
+		b[3]=fbsub[(int)b[3]&0xff];
+		return pack(b);    
+	}
+
+	private static byte product(int x,int y)
+	{ /* dot product of two 4-byte arrays */
+		byte [] xb;//=new byte[4];
+		byte [] yb;//=new byte[4];
+		xb=unpack(x);
+		yb=unpack(y); 
+
+		return (byte)(bmul(xb[0],yb[0])^bmul(xb[1],yb[1])^bmul(xb[2],yb[2])^bmul(xb[3],yb[3]));
+	}
+
+	private static int InvMixCol(int x)
+	{ /* matrix Multiplication */
+		int y,m;
+		byte [] b=new byte[4];
+
+		m=pack(InCo);
+		b[3]=product(m,x);
+		m=ROTL24(m);
+		b[2]=product(m,x);
+		m=ROTL24(m);
+		b[1]=product(m,x);
+		m=ROTL24(m);
+		b[0]=product(m,x);
+		y=pack(b);
+		return y;
+	}
+
+	private static void increment(byte [] f)
+	{
+		int i;
+		for (i=0;i<16;i++)
+		{
+			f[i]++;
+			if (f[i]!=0) break;
+		}
+	}
+
+/* reset cipher */
+	public void reset(int m,byte[] iv)
+	{ /* reset mode, or reset iv */
+		mode=m;
+		for (int i=0;i<16;i++)
+			f[i]=0;
+		if (mode!=ECB && iv!=null)
+			for (int i=0;i<16;i++)
+				f[i]=iv[i];
+	}
+
+	public byte[] getreg()
+	{
+		byte [] ir=new byte[16];
+		for (int i=0;i<16;i++) ir[i]=f[i];
+		return ir;
+	}
+
+/* Initialise cipher */
+	public boolean init(int m,int nk,byte[] key,byte[] iv)
+	{	/* Key=16 bytes */
+		/* Key Scheduler. Create expanded encryption key */
+		int i,j,k,N,nr;
+		int [] CipherKey=new int[8];
+		byte [] b=new byte[4];
+		nk/=4;
+
+		if (nk!=4 && nk!=6 && nk!=8) return false;
+
+		nr=6+nk;
+
+		Nk=nk; Nr=nr;
+
+		reset(m,iv);
+		N=4*(nr+1);
+    
+		for (i=j=0;i<nk;i++,j+=4)
+		{
+			for (k=0;k<4;k++) b[k]=key[j+k];
+			CipherKey[i]=pack(b);
+		}
+		for (i=0;i<nk;i++) fkey[i]=CipherKey[i];
+		for (j=nk,k=0;j<N;j+=nk,k++)
+		{
+			fkey[j]=fkey[j-nk]^SubByte(ROTL24(fkey[j-1]))^((int)rco[k])&0xff;
+			for (i=1;i<nk && (i+j)<N;i++)
+				fkey[i+j]=fkey[i+j-nk]^fkey[i+j-1];
+		}
+
+ /* now for the expanded decrypt key in reverse order */
+
+		for (j=0;j<4;j++) rkey[j+N-4]=fkey[j]; 
+		for (i=4;i<N-4;i+=4)
+		{
+			k=N-4-i;
+			for (j=0;j<4;j++) rkey[k+j]=InvMixCol(fkey[i+j]);
+		}
+		for (j=N-4;j<N;j++) rkey[j-N+4]=fkey[j];
+		return true;
+	}
+
+/* Encrypt a single block */
+	public void ecb_encrypt(byte[] buff)
+	{
+		int i,j,k;
+		int t;
+    	byte [] b=new byte[4];
+    	int [] p=new int[4];
+    	int [] q=new int[4];
+
+		for (i=j=0;i<4;i++,j+=4)
+		{
+			for (k=0;k<4;k++) b[k]=buff[j+k];
+			p[i]=pack(b);
+			p[i]^=fkey[i];
+		}
+
+		k=4;
+
+/* State alternates between p and q */
+		for (i=1;i<Nr;i++)
+		{ 
+			q[0]=fkey[k]^ftable[p[0]&0xff]^
+				ROTL8(ftable[(p[1]>>>8)&0xff])^
+				ROTL16(ftable[(p[2]>>>16)&0xff])^
+				ROTL24(ftable[(p[3]>>>24)&0xff]);
+			q[1]=fkey[k+1]^ftable[p[1]&0xff]^
+				ROTL8(ftable[(p[2]>>>8)&0xff])^
+				ROTL16(ftable[(p[3]>>>16)&0xff])^
+				ROTL24(ftable[(p[0]>>>24)&0xff]);
+			q[2]=fkey[k+2]^ftable[p[2]&0xff]^
+				ROTL8(ftable[(p[3]>>>8)&0xff])^
+				ROTL16(ftable[(p[0]>>>16)&0xff])^
+				ROTL24(ftable[(p[1]>>>24)&0xff]);
+			q[3]=fkey[k+3]^ftable[p[3]&0xff]^
+				ROTL8(ftable[(p[0]>>>8)&0xff])^
+				ROTL16(ftable[(p[1]>>>16)&0xff])^
+				ROTL24(ftable[(p[2]>>>24)&0xff]);
+
+			k+=4;
+			for (j=0;j<4;j++)
+			{
+				t=p[j]; p[j]=q[j]; q[j]=t;
+			}
+		}
+
+/* Last Round */ 
+    
+		q[0]=fkey[k]^((int)fbsub[p[0]&0xff]&0xff)^
+			ROTL8((int)fbsub[(p[1]>>>8)&0xff]&0xff)^
+			ROTL16((int)fbsub[(p[2]>>>16)&0xff]&0xff)^
+			ROTL24((int)fbsub[(p[3]>>>24)&0xff]&0xff);
+
+		q[1]=fkey[k+1]^((int)fbsub[p[1]&0xff]&0xff)^
+			ROTL8((int)fbsub[(p[2]>>>8)&0xff]&0xff)^
+			ROTL16((int)fbsub[(p[3]>>>16)&0xff]&0xff)^
+			ROTL24((int)fbsub[(p[0]>>>24)&0xff]&0xff);
+
+		q[2]=fkey[k+2]^((int)fbsub[p[2]&0xff]&0xff)^
+			ROTL8((int)fbsub[(p[3]>>>8)&0xff]&0xff)^
+			ROTL16((int)fbsub[(p[0]>>>16)&0xff]&0xff)^
+			ROTL24((int)fbsub[(p[1]>>>24)&0xff]&0xff);
+
+		q[3]=fkey[k+3]^((int)fbsub[(p[3])&0xff]&0xff)^
+			ROTL8((int)fbsub[(p[0]>>>8)&0xff]&0xff)^
+			ROTL16((int)fbsub[(p[1]>>>16)&0xff]&0xff)^
+			ROTL24((int)fbsub[(p[2]>>>24)&0xff]&0xff);
+
+		for (i=j=0;i<4;i++,j+=4)
+		{
+			b=unpack(q[i]);
+			for (k=0;k<4;k++) buff[j+k]=b[k];
+		}
+	}
+
+/* Decrypt a single block */
+	public void ecb_decrypt(byte[] buff)
+	{
+		int i,j,k;
+		int t;
+    	byte [] b=new byte[4];
+    	int [] p=new int[4];
+    	int [] q=new int[4];
+
+		for (i=j=0;i<4;i++,j+=4)
+		{
+			for (k=0;k<4;k++) b[k]=buff[j+k];
+			p[i]=pack(b);
+			p[i]^=rkey[i];
+		}
+
+		k=4;
+
+/* State alternates between p and q */
+		for (i=1;i<Nr;i++)
+		{ 
+			q[0]=rkey[k]^rtable[p[0]&0xff]^
+				ROTL8(rtable[(p[3]>>>8)&0xff])^
+				ROTL16(rtable[(p[2]>>>16)&0xff])^
+				ROTL24(rtable[(p[1]>>>24)&0xff]);
+			q[1]=rkey[k+1]^rtable[p[1]&0xff]^
+				ROTL8(rtable[(p[0]>>>8)&0xff])^
+				ROTL16(rtable[(p[3]>>>16)&0xff])^
+				ROTL24(rtable[(p[2]>>>24)&0xff]);
+			q[2]=rkey[k+2]^rtable[p[2]&0xff]^
+				ROTL8(rtable[(p[1]>>>8)&0xff])^
+				ROTL16(rtable[(p[0]>>>16)&0xff])^
+				ROTL24(rtable[(p[3]>>>24)&0xff]);
+			q[3]=rkey[k+3]^rtable[p[3]&0xff]^
+				ROTL8(rtable[(p[2]>>>8)&0xff])^
+				ROTL16(rtable[(p[1]>>>16)&0xff])^
+				ROTL24(rtable[(p[0]>>>24)&0xff]);
+
+			k+=4;
+			for (j=0;j<4;j++)
+			{
+				t=p[j]; p[j]=q[j]; q[j]=t;
+			}
+		}
+
+/* Last Round */ 
+
+		q[0]=rkey[k]^((int)rbsub[p[0]&0xff]&0xff)^
+			ROTL8((int)rbsub[(p[3]>>>8)&0xff]&0xff)^
+			ROTL16((int)rbsub[(p[2]>>>16)&0xff]&0xff)^
+			ROTL24((int)rbsub[(p[1]>>>24)&0xff]&0xff);
+		q[1]=rkey[k+1]^((int)rbsub[p[1]&0xff]&0xff)^
+			ROTL8((int)rbsub[(p[0]>>>8)&0xff]&0xff)^
+			ROTL16((int)rbsub[(p[3]>>>16)&0xff]&0xff)^
+			ROTL24((int)rbsub[(p[2]>>>24)&0xff]&0xff);
+		q[2]=rkey[k+2]^((int)rbsub[p[2]&0xff]&0xff)^
+			ROTL8((int)rbsub[(p[1]>>>8)&0xff]&0xff)^
+			ROTL16((int)rbsub[(p[0]>>>16)&0xff]&0xff)^
+			ROTL24((int)rbsub[(p[3]>>>24)&0xff]&0xff);
+		q[3]=rkey[k+3]^((int)rbsub[p[3]&0xff]&0xff)^
+			ROTL8((int)rbsub[(p[2]>>>8)&0xff]&0xff)^
+			ROTL16((int)rbsub[(p[1]>>>16)&0xff]&0xff)^
+			ROTL24((int)rbsub[(p[0]>>>24)&0xff]&0xff);
+
+		for (i=j=0;i<4;i++,j+=4)
+		{
+			b=unpack(q[i]);
+			for (k=0;k<4;k++) buff[j+k]=b[k];
+		}
+
+	}
+
+/* Encrypt using selected mode of operation */
+	public int encrypt(byte[] buff)
+	{
+		int j,bytes;
+		byte[] st=new byte[16];
+		int fell_off;
+
+// Supported Modes of Operation 
+
+		fell_off=0;
+		switch (mode)
+		{
+		case ECB: 
+			ecb_encrypt(buff);
+			return 0;
+		case CBC:
+			for (j=0;j<16;j++) buff[j]^=f[j];
+			ecb_encrypt(buff);
+			for (j=0;j<16;j++) f[j]=buff[j];
+			return 0;
+
+		case CFB1:
+		case CFB2:
+		case CFB4:
+			bytes=mode-CFB1+1;
+			for (j=0;j<bytes;j++) fell_off=(fell_off<<8)|f[j];
+			for (j=0;j<16;j++) st[j]=f[j];
+			for (j=bytes;j<16;j++) f[j-bytes]=f[j];
+			ecb_encrypt(st);
+			for (j=0;j<bytes;j++) 
+			{
+				buff[j]^=st[j];
+				f[16-bytes+j]=buff[j];
+			}
+			return fell_off;
+
+		case OFB1:
+		case OFB2:
+		case OFB4:
+		case OFB8:
+		case OFB16:
+
+			bytes=mode-OFB1+1;
+			ecb_encrypt(f);
+			for (j=0;j<bytes;j++) buff[j]^=f[j];
+			return 0;
+
+		case CTR1:
+		case CTR2:
+		case CTR4:
+		case CTR8:
+		case CTR16:
+
+			bytes=mode-CTR1+1;
+			for (j=0;j<16;j++) st[j]=f[j];
+			ecb_encrypt(st);
+			for (j=0;j<bytes;j++) buff[j]^=st[j];
+			increment(f);
+
+    default:
+			return 0;
+		}
+	}
+
+/* Decrypt using selected mode of operation */
+	public int decrypt(byte[] buff)
+	{
+		int j,bytes;
+		byte[] st=new byte[16];
+		int fell_off;
+
+   // Supported modes of operation 
+		fell_off=0;
+		switch (mode)
+		{
+		case ECB:
+			ecb_decrypt(buff);
+			return 0;
+		case CBC:
+			for (j=0;j<16;j++) 
+			{
+				st[j]=f[j];
+				f[j]=buff[j];
+			}
+			ecb_decrypt(buff);
+			for (j=0;j<16;j++)
+			{	 
+				buff[j]^=st[j];
+				st[j]=0;
+			}
+			return 0;
+		case CFB1:
+		case CFB2:
+		case CFB4:
+			bytes=mode-CFB1+1;
+			for (j=0;j<bytes;j++) fell_off=(fell_off<<8)|f[j];
+			for (j=0;j<16;j++) st[j]=f[j];
+			for (j=bytes;j<16;j++) f[j-bytes]=f[j];
+			ecb_encrypt(st);
+			for (j=0;j<bytes;j++)
+			{
+				f[16-bytes+j]=buff[j];
+				buff[j]^=st[j];
+			}
+			return fell_off;
+		case OFB1:
+		case OFB2:
+		case OFB4:
+		case OFB8:
+		case OFB16:
+			bytes=mode-OFB1+1;
+			ecb_encrypt(f);
+			for (j=0;j<bytes;j++) buff[j]^=f[j];
+			return 0;
+
+		case CTR1:
+		case CTR2:
+		case CTR4:
+		case CTR8:
+		case CTR16:
+
+			bytes=mode-CTR1+1;
+			for (j=0;j<16;j++) st[j]=f[j];
+			ecb_encrypt(st);
+			for (j=0;j<bytes;j++) buff[j]^=st[j];
+			increment(f);
+ 
+		default:
+			return 0;
+		}
+	}
+
+/* Clean up and delete left-overs */
+	public void end()
+	{ // clean up 
+		int i;
+		for (i=0;i<4*(Nr+1);i++)
+			fkey[i]=rkey[i]=0;
+		for (i=0;i<16;i++)
+			f[i]=0;
+	}
+
+	public static void main(String[] args) {
+		int i;
+
+		byte[] key=new byte[32];
+		byte[] block=new byte[16];
+		byte[] iv=new byte[16];
+
+		for (i=0;i<32;i++) key[i]=0;
+		key[0]=1;
+		for (i=0;i<16;i++) iv[i]=(byte)i;
+		for (i=0;i<16;i++) block[i]=(byte)i;
+
+		AES a=new AES();
+
+		a.init(CTR16,32,key,iv);
+		System.out.println("Plain= "); 
+		for (i=0;i<16;i++)  System.out.format("%02X ", block[i]&0xff);
+		System.out.println(""); 
+
+		a.encrypt(block);
+
+		System.out.println("Encrypt= "); 
+		for (i=0;i<16;i++)  System.out.format("%02X ", block[i]&0xff);
+		System.out.println(""); 
+
+		a.reset(CTR16,iv);
+		a.decrypt(block);
+
+		System.out.println("Decrypt= "); 
+		for (i=0;i<16;i++)  System.out.format("%02X ", block[i]&0xff);
+		System.out.println(""); 
+
+		a.end();
+
+	} 
+}
diff --git a/version3/java/BIG32.java b/version3/java/BIG32.java
new file mode 100644
index 0000000..095191d
--- /dev/null
+++ b/version3/java/BIG32.java
@@ -0,0 +1,934 @@
+/*
+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.
+*/
+
+/* AMCL BIG number class */ 
+
+package org.apache.milagro.amcl.XXX;
+import org.apache.milagro.amcl.RAND;
+
+public class BIG {
+
+	public static final int CHUNK=32; /* Set word size */
+
+	public static final int MODBYTES=@NB@; //(1+(MODBITS-1)/8);
+	public static final int BASEBITS=@BASE@; 
+
+	public static final int NLEN=(1+((8*MODBYTES-1)/BASEBITS));
+	public static final int DNLEN=2*NLEN;
+	public static final int BMASK=(((int)1<<BASEBITS)-1);
+
+	public static final int HBITS=BASEBITS/2;
+	public static final int HMASK=(((int)1<<HBITS)-1);
+	public static final int NEXCESS = ((int)1<<(CHUNK-BASEBITS-1));
+	public static final int BIGBITS=(MODBYTES*8);
+
+
+	protected int[] w=new int[NLEN];
+
+
+
+/* Constructors */
+
+	public BIG()
+	{
+		for (int i=0;i<NLEN;i++)
+			w[i]=0;
+	}
+
+	public BIG(int x)
+	{
+		w[0]=x;
+		for (int i=1;i<NLEN;i++)
+			w[i]=0;
+	}
+
+	public BIG(BIG x)
+	{
+		for (int i=0;i<NLEN;i++)
+			w[i]=x.w[i];
+	}
+
+	public BIG(DBIG x)
+	{
+		for (int i=0;i<NLEN;i++)
+			w[i]=x.w[i];
+	}
+
+	public BIG(int[] x)
+	{
+		for (int i=0;i<NLEN;i++)
+			w[i]=x[i];
+	}
+
+	public int get(int i)
+	{
+		return w[i];
+	}
+
+	public void set(int i,int x)
+	{
+		w[i]=x;
+	} 
+
+/* Conditional swap of two bigs depending on d using XOR - no branches */
+	public void cswap(BIG b,int d)
+	{
+		int i;
+		int t,c=d;
+		c=~(c-1);
+
+		for (i=0;i<NLEN;i++)
+		{
+			t=c&(w[i]^b.w[i]);
+			w[i]^=t;
+			b.w[i]^=t;
+		}
+	}
+
+	public void cmove(BIG g,int d)
+	{
+		int i;
+		int b=-d;
+
+		for (i=0;i<NLEN;i++)
+		{
+			w[i]^=(w[i]^g.w[i])&b;
+		}
+	}
+
+    public static int cast_to_chunk(int x)
+	{
+		return (int)x;
+	}
+
+/* normalise BIG - force all digits < 2^BASEBITS */
+	public long norm() {
+		int d,carry=0;
+		for (int i=0;i<NLEN-1;i++)
+		{
+			d=w[i]+carry;
+			w[i]=d&BMASK;
+			carry=d>>BASEBITS;
+		}
+		w[NLEN-1]=(w[NLEN-1]+carry);
+		return (long)(w[NLEN-1]>>((8*MODBYTES)%BASEBITS));  
+	}
+
+/* return number of bits */
+	public int nbits() {
+		BIG t=new BIG(this);
+		int bts,k=NLEN-1;
+		int c;
+		t.norm();
+		while (k>=0 && t.w[k]==0) k--;
+		if (k<0) return 0;
+		bts=BASEBITS*k;
+		c=t.w[k];
+		while (c!=0) {c/=2; bts++;}
+		return bts;
+	}
+
+	public String toRawString()
+	{
+		BIG b=new BIG(this);
+		String s="(";
+		for (int i=0;i<NLEN-1;i++)
+		{
+			s+=Integer.toHexString(b.w[i]); s+=",";
+		}
+		s+=Integer.toHexString(b.w[NLEN-1]); s+=")";
+		return s;
+	}
+
+/* Convert to Hex String */
+	public String toString() {
+		BIG b;
+		String s="";
+		int len=nbits();
+
+		if (len%4==0) len/=4;
+		else {len/=4; len++;}
+		if (len<MODBYTES*2) len=MODBYTES*2;
+
+		for (int i=len-1;i>=0;i--)
+		{
+			b=new BIG(this);
+			b.shr(i*4);
+			s+=Integer.toHexString(b.w[0]&15);
+		}
+		return s;
+	}
+
+	public static int[] muladd(int x,int y,int c,int r)
+	{
+		int[] tb=new int[2];
+		long prod=(long)x*y+c+r;	
+		tb[1]=(int)prod&BMASK;
+		tb[0]=(int)(prod>>BASEBITS);
+		return tb;
+	}
+
+/* this*=x, where x is >NEXCESS */
+	public int pmul(int c)
+	{
+		int ak,carry=0;
+		int[] cr=new int[2];
+
+		for (int i=0;i<NLEN;i++)
+		{
+			ak=w[i];
+			w[i]=0;
+			cr=muladd(ak,c,carry,w[i]);
+			carry=cr[0];
+			w[i]=cr[1];
+		}
+		return carry;
+	}
+
+/* return this*c and catch overflow in DBIG */
+	public DBIG pxmul(int c)
+	{
+		DBIG m=new DBIG(0);	
+		int[] cr=new int[2];	
+		int carry=0;
+		for (int j=0;j<NLEN;j++)
+		{
+			cr=muladd(w[j],c,carry,m.w[j]);
+			carry=cr[0];
+			m.w[j]=cr[1];
+		}
+		m.w[NLEN]=carry;		
+		return m;
+	}
+
+/* divide by 3 */
+	public int div3()
+	{	
+		int ak,base,carry=0;
+		norm();
+		base=((int)1<<BASEBITS);
+		for (int i=NLEN-1;i>=0;i--)
+		{
+			ak=(carry*base+w[i]);
+			w[i]=ak/3;
+			carry=ak%3;
+		}
+		return (int)carry;
+	}
+
+/* return a*b where result fits in a BIG */
+	public static BIG smul(BIG a,BIG b)
+	{
+		int carry;
+		BIG c=new BIG(0);
+		int[] cr=new int[2];			
+		for (int i=0;i<NLEN;i++)
+		{
+			carry=0;
+			for (int j=0;j<NLEN;j++)
+			{
+				if (i+j<NLEN) 
+				{
+					cr=muladd(a.w[i],b.w[j],carry,c.w[i+j]);
+					carry=cr[0];
+					c.w[i+j]=cr[1];
+				}
+			}
+		}
+		return c;
+	}
+
+/* return a*b as DBIG */
+/* Inputs must be normed */
+	public static DBIG mul(BIG a,BIG b)
+	{
+		long t,co;
+		DBIG c=new DBIG(0);
+
+		long[] d=new long[NLEN];
+		long s;
+		int i,k;
+
+		for (i=0;i<NLEN;i++)
+			d[i]=(long)a.w[i]*b.w[i];
+
+		s=d[0];
+		t=s; c.w[0]=(int)t&BMASK; co=t>>BASEBITS;
+
+		for (k=1;k<NLEN;k++)
+		{
+			s+=d[k]; t=co+s; for (i=k;i>=1+k/2;i--) t+=(long)(a.w[i]-a.w[k-i])*(b.w[k-i]-b.w[i]); c.w[k]=(int)t&BMASK; co=t>>BASEBITS;
+		}
+		for (k=NLEN;k<2*NLEN-1;k++)
+		{
+			s-=d[k-NLEN]; t=co+s; for (i=NLEN-1;i>=1+k/2;i--) t+=(long)(a.w[i]-a.w[k-i])*(b.w[k-i]-b.w[i]); c.w[k]=(int)t&BMASK; co=t>>BASEBITS;
+		}
+		c.w[2*NLEN-1]=(int)co;
+
+		return c;
+	}
+
+/* return a^2 as DBIG */
+/* Input must be normed */
+	public static DBIG sqr(BIG a)
+	{
+		int i,j,last;
+		long t,co;
+		DBIG c=new DBIG(0);
+
+		t=(long)a.w[0]*a.w[0]; 
+		c.w[0]=(int)t&BMASK; co=t>>BASEBITS;
+
+		for (j=1;j<NLEN-1; )
+		{
+			t=(long)a.w[j]*a.w[0]; for (i=1; i<(j+1)/2; i++) {t+=(long)a.w[j-i]*a.w[i];} t+=t;  t+=co; 
+			c.w[j]=(int)t&BMASK; co=t>>BASEBITS;
+			j++;
+			t=(long)a.w[j]*a.w[0]; for (i=1; i<(j+1)/2; i++) {t+=(long)a.w[j-i]*a.w[i];} t+=t; t+=co; t+=(long)a.w[j/2]*a.w[j/2]; 
+			c.w[j]=(int)t&BMASK; co=t>>BASEBITS;
+			j++;
+		}
+
+		for (j=NLEN-1+NLEN%2;j<DNLEN-3; )
+		{
+			t=(long)a.w[NLEN-1]*a.w[j-NLEN+1]; for (i=j-NLEN+2; i<(j+1)/2; i++) {t+=(long)a.w[j-i]*a.w[i];} t+=t; t+=co; 
+			c.w[j]=(int)t&BMASK; co=t>>BASEBITS;
+			j++;
+			t=(long)a.w[NLEN-1]*a.w[j-NLEN+1]; for (i=j-NLEN+2; i<(j+1)/2; i++) {t+=(long)a.w[j-i]*a.w[i];} t+=t; t+=co; t+=(long)a.w[j/2]*a.w[j/2]; 
+			c.w[j]=(int)t&BMASK; co=t>>BASEBITS;
+			j++;
+		}
+
+		t=(long)a.w[NLEN-2]*a.w[NLEN-1];
+		t+=t; t+=co;
+		c.w[DNLEN-3]=(int)t&BMASK; co=t>>BASEBITS;
+	
+		t=(long)a.w[NLEN-1]*a.w[NLEN-1]+co; 
+		c.w[DNLEN-2]=(int)t&BMASK; co=t>>BASEBITS;
+		c.w[DNLEN-1]=(int)co;
+
+		return c;
+	}
+
+	static BIG monty(BIG m,int MC,DBIG d)
+	{
+		BIG b;
+		long t,c,s;
+		int i,k;
+		long[] dd=new long[NLEN];
+		int[] v=new int[NLEN];
+		b=new BIG(0);
+
+		t=d.w[0]; v[0]=((int)t*MC)&BMASK; t+=(long)v[0]*m.w[0]; c=(t>>BASEBITS)+d.w[1]; s=0;
+
+		for (k=1;k<NLEN;k++)
+		{
+			t=c+s+(long)v[0]*m.w[k];
+			for (i=k-1;i>k/2;i--) t+=(long)(v[k-i]-v[i])*(m.w[i]-m.w[k-i]);
+			v[k]=((int)t*MC)&BMASK; t+=(long)v[k]*m.w[0]; c=(t>>BASEBITS)+d.w[k+1];
+			dd[k]=(long)v[k]*m.w[k]; s+=dd[k];
+		}
+		for (k=NLEN;k<2*NLEN-1;k++)
+		{
+			t=c+s;
+			for (i=NLEN-1;i>=1+k/2;i--) t+=(long)(v[k-i]-v[i])*(m.w[i]-m.w[k-i]);
+			b.w[k-NLEN]=(int)t&BMASK; c=(t>>BASEBITS)+d.w[k+1]; s-=dd[k-NLEN+1];
+		}
+		b.w[NLEN-1]=(int)c&BMASK;	
+		return b;		
+	}
+
+	public static int ssn(BIG r,BIG a,BIG m)
+	{
+		int n=NLEN-1;
+		m.w[0]=(m.w[0]>>1)|((m.w[1]<<(BASEBITS-1))&BMASK);
+		r.w[0]=a.w[0]-m.w[0];
+		int carry=r.w[0]>>BASEBITS;
+		r.w[0]&=BMASK;
+		for (int i=1;i<n;i++) {
+			m.w[i]=(m.w[i]>>1)|((m.w[i+1]<<(BASEBITS-1))&BMASK);
+			r.w[i]=a.w[i]-m.w[i]+carry;
+			carry=r.w[i]>>BASEBITS;
+			r.w[i]&=BMASK;
+		}
+		m.w[n]>>=1;
+		r.w[n]=a.w[n]-m.w[n]+carry;
+		return (int)((r.w[n]>>(CHUNK-1))&1);
+	}
+
+
+/****************************************************************************/
+	public void xortop(long x)
+	{
+		w[NLEN-1]^=x;
+	}
+
+/* set x = x mod 2^m */
+	public void mod2m(int m)
+	{
+		int i,wd,bt;
+		wd=m/BASEBITS;
+		bt=m%BASEBITS;
+		w[wd]&=((cast_to_chunk(1)<<bt)-1);
+		for (i=wd+1;i<NLEN;i++) w[i]=0;
+	}
+
+/* return n-th bit */
+	public int bit(int n)
+	{
+		if ((w[n/BASEBITS]&(cast_to_chunk(1)<<(n%BASEBITS)))>0) return 1;
+		else return 0;
+	}
+
+/* Shift right by less than a word */
+	public int fshr(int k) {
+		int r=(int)(w[0]&((cast_to_chunk(1)<<k)-1)); /* shifted out part */
+		for (int i=0;i<NLEN-1;i++)
+			w[i]=(w[i]>>k)|((w[i+1]<<(BASEBITS-k))&BMASK);
+		w[NLEN-1]=w[NLEN-1]>>k;
+		return r;
+	}
+
+/* Shift right by less than a word */
+	public int fshl(int k) {
+		w[NLEN-1]=((w[NLEN-1]<<k))|(w[NLEN-2]>>(BASEBITS-k));
+		for (int i=NLEN-2;i>0;i--)
+			w[i]=((w[i]<<k)&BMASK)|(w[i-1]>>(BASEBITS-k));
+		w[0]=(w[0]<<k)&BMASK; 
+		return (int)(w[NLEN-1]>>((8*MODBYTES)%BASEBITS)); /* return excess - only used in FF.java */
+	}
+
+/* test for zero */
+	public boolean iszilch() {
+		for (int i=0;i<NLEN;i++)
+			if (w[i]!=0) return false;
+		return true; 
+	}
+
+/* set to zero */
+	public void zero()
+	{
+		for (int i=0;i<NLEN;i++)
+			w[i]=0;
+	}
+
+/* set to one */
+	public void one()
+	{
+		w[0]=1;
+		for (int i=1;i<NLEN;i++)
+			w[i]=0;
+	}
+
+/* Test for equal to one */
+	public boolean isunity()
+	{
+		for (int i=1;i<NLEN;i++)
+			if (w[i]!=0) return false;
+		if (w[0]!=1) return false;
+		return true;
+	}
+
+/* Copy from another BIG */
+	public void copy(BIG x)
+	{
+		for (int i=0;i<NLEN;i++)
+			w[i]=x.w[i];
+	}
+
+	public void copy(DBIG x)
+	{
+		for (int i=0;i<NLEN;i++)
+			w[i]=x.w[i];
+	}
+
+/* general shift right */
+	public void shr(int k) {
+		int n=k%BASEBITS;
+		int m=k/BASEBITS;	
+		for (int i=0;i<NLEN-m-1;i++)
+			w[i]=(w[m+i]>>n)|((w[m+i+1]<<(BASEBITS-n))&BMASK);
+		if (NLEN>m) w[NLEN-m-1]=w[NLEN-1]>>n;
+		for (int i=NLEN-m;i<NLEN;i++) w[i]=0;
+	}
+
+/* general shift left */
+	public void shl(int k) {
+		int n=k%BASEBITS;
+		int m=k/BASEBITS;
+
+		w[NLEN-1]=((w[NLEN-1-m]<<n));
+		if (NLEN>=m+2) w[NLEN-1]|=(w[NLEN-m-2]>>(BASEBITS-n));
+
+		for (int i=NLEN-2;i>m;i--)
+			w[i]=((w[i-m]<<n)&BMASK)|(w[i-m-1]>>(BASEBITS-n));
+		w[m]=(w[0]<<n)&BMASK;
+		for (int i=0;i<m;i++) w[i]=0;
+	}
+
+/* return this+x */
+	public BIG plus(BIG x) {
+		BIG s=new BIG(0);
+		for (int i=0;i<NLEN;i++)
+			s.w[i]=w[i]+x.w[i];	
+		return s;
+	}
+
+/* this+=x */
+	public void add(BIG x) {
+		for (int i=0;i<NLEN;i++)
+			w[i]+=x.w[i];
+	}
+
+/* this|=x */
+	public void or(BIG x) {
+		for (int i=0;i<NLEN;i++)
+			w[i]|=x.w[i];
+	}
+
+/* this+=x, where x is int */
+	public void inc(int x) {
+		norm();
+		w[0]+=x;
+	}
+
+/* this+=x, where x is long */
+	public void incl(long x) {
+		norm();
+		w[0]+=x;
+	}	
+
+/* return this.x */
+	public BIG minus(BIG x) {
+		BIG d=new BIG(0);
+		for (int i=0;i<NLEN;i++)
+			d.w[i]=w[i]-x.w[i];
+		return d;
+	}
+
+/* this-=x */
+	public void sub(BIG x) {
+		for (int i=0;i<NLEN;i++)
+			w[i]-=x.w[i];
+	}
+
+/* reverse subtract this=x-this */
+	public void rsub(BIG x) {
+		for (int i=0;i<NLEN;i++)
+			w[i]=x.w[i]-w[i];
+	}
+
+/* this-=x where x is int */
+	public void dec(int x) {
+		norm();
+		w[0]-=x;
+	}
+
+/* this*=x, where x is small int<NEXCESS */
+	public void imul(int c)
+	{
+		for (int i=0;i<NLEN;i++) w[i]*=c;
+	}
+
+/* convert this BIG to byte array */
+	public void tobytearray(byte[] b,int n)
+	{
+		BIG c=new BIG(this);
+		c.norm();
+
+		for (int i=MODBYTES-1;i>=0;i--)
+		{
+			b[i+n]=(byte)c.w[0];
+			c.fshr(8);
+		}
+	}
+
+/* convert from byte array to BIG */
+	public static BIG frombytearray(byte[] b,int n)
+	{
+		BIG m=new BIG(0);
+
+		for (int i=0;i<MODBYTES;i++)
+		{
+			m.fshl(8); m.w[0]+=(int)b[i+n]&0xff;
+			//m.inc((int)b[i]&0xff);
+		}
+		return m; 
+	}
+
+	public void toBytes(byte[] b)
+	{
+		tobytearray(b,0);
+	}
+
+	public static BIG fromBytes(byte[] b)
+	{
+		return frombytearray(b,0);
+	}
+
+/* Compare a and b, return 0 if a==b, -1 if a<b, +1 if a>b. Inputs must be normalised */
+	public static int comp(BIG a,BIG b)
+	{
+		for (int i=NLEN-1;i>=0;i--)
+		{
+			if (a.w[i]==b.w[i]) continue;
+			if (a.w[i]>b.w[i]) return 1;
+			else  return -1;
+		}
+		return 0;
+	}
+
+/* Arazi and Qi inversion mod 256 */
+	public static int invmod256(int a)
+	{
+		int U,t1,t2,b,c;
+		t1=0;
+		c=(a>>1)&1;  
+		t1+=c;
+		t1&=1;
+		t1=2-t1;
+		t1<<=1;
+		U=t1+1;
+
+// i=2
+		b=a&3;
+		t1=U*b; t1>>=2;
+		c=(a>>2)&3;
+		t2=(U*c)&3;
+		t1+=t2;
+		t1*=U; t1&=3;
+		t1=4-t1;
+		t1<<=2;
+		U+=t1;
+
+// i=4
+		b=a&15;
+		t1=U*b; t1>>=4;
+		c=(a>>4)&15;
+		t2=(U*c)&15;
+		t1+=t2;
+		t1*=U; t1&=15;
+		t1=16-t1;
+		t1<<=4;
+		U+=t1;
+
+		return U;
+	}
+
+/* a=1/a mod 2^256. This is very fast! */
+	public void invmod2m()
+	{
+		int i;
+		BIG U=new BIG(0);
+		BIG b=new BIG(0);
+		BIG c=new BIG(0);
+
+		U.inc(invmod256(lastbits(8)));
+
+		for (i=8;i<BIGBITS;i<<=1)
+		{
+			U.norm();
+			b.copy(this); b.mod2m(i);
+			BIG t1=BIG.smul(U,b); 
+			t1.shr(i);
+
+			c.copy(this); c.shr(i); c.mod2m(i);
+
+			BIG t2=BIG.smul(U,c); t2.mod2m(i);
+
+			t1.add(t2);
+			t1.norm();
+			b=BIG.smul(t1,U); t1.copy(b);
+			t1.mod2m(i);
+
+			t2.one(); t2.shl(i); t1.rsub(t2); t1.norm();
+
+			t1.shl(i);
+			U.add(t1);
+		}
+		U.mod2m(BIGBITS);
+		copy(U);
+		norm();
+	}
+
+/* reduce this mod m */
+	public void mod(BIG m1)
+	{
+		int k=0;  
+		BIG r=new BIG(0);
+		BIG m=new BIG(m1);
+
+		norm();
+		if (comp(this,m)<0) return;
+		do
+		{
+			m.fshl(1);
+			k++;
+		} while (comp(this,m)>=0);
+
+		while (k>0)
+		{
+			m.fshr(1);
+
+			r.copy(this);
+			r.sub(m);
+			r.norm();
+			cmove(r,(int)(1-((r.w[NLEN-1]>>(CHUNK-1))&1)));
+			k--;
+		}
+	}
+
+/* divide this by m */
+	public void div(BIG m1)
+	{
+		int d,k=0;
+		norm();
+		BIG e=new BIG(1);
+		BIG m=new BIG(m1);
+		BIG b=new BIG(this);
+		BIG r=new BIG(0);
+		zero();
+
+		while (comp(b,m)>=0)
+		{
+			e.fshl(1);
+			m.fshl(1);
+			k++;
+		}
+
+		while (k>0)
+		{
+			m.fshr(1);
+			e.fshr(1);
+
+			r.copy(b);
+			r.sub(m);
+			r.norm();
+			d=(int)(1-((r.w[NLEN-1]>>(CHUNK-1))&1));
+			b.cmove(r,d);
+			r.copy(this);
+			r.add(e);
+			r.norm();
+			cmove(r,d);
+			k--;
+		}
+	}
+
+/* return parity */
+	public int parity()
+	{
+		return (int)(w[0]%2);
+	}
+
+/* return n last bits */
+	public int lastbits(int n)
+	{
+		int msk=(1<<n)-1;
+		norm();
+		return ((int)w[0])&msk;
+	}
+
+/* get 8*MODBYTES size random number */
+	public static BIG random(RAND rng)
+	{
+		BIG m=new BIG(0);
+		int i,b,j=0,r=0;
+
+/* generate random BIG */ 
+		for (i=0;i<8*MODBYTES;i++)   
+		{
+			if (j==0) r=rng.getByte();
+			else r>>=1;
+
+			b=r&1;
+			m.shl(1); m.w[0]+=b;// m.inc(b);
+			j++; j&=7; 
+		}
+		return m;
+	}
+
+/* Create random BIG in portable way, one bit at a time */
+	public static BIG randomnum(BIG q,RAND rng) 
+	{
+		DBIG d=new DBIG(0);
+		int i,b,j=0,r=0;
+		for (i=0;i<2*q.nbits();i++)
+		{
+			if (j==0) r=rng.getByte();
+			else r>>=1;
+
+			b=r&1;
+			d.shl(1); d.w[0]+=b;// m.inc(b);
+			j++; j&=7; 
+		}
+		BIG m=d.mod(q);
+		return m;
+	}
+
+/* return a*b mod m */
+	public static BIG modmul(BIG a1,BIG b1,BIG m)
+	{
+		BIG a=new BIG(a1);
+		BIG b=new BIG(b1);
+		a.mod(m);
+		b.mod(m);
+		DBIG d=mul(a,b);
+		return d.mod(m);
+	}
+
+/* return a^2 mod m */
+	public static BIG modsqr(BIG a1,BIG m)
+	{
+		BIG a=new BIG(a1);
+		a.mod(m);
+		DBIG d=sqr(a);
+		return d.mod(m);
+	}
+
+/* return -a mod m */
+	public static BIG modneg(BIG a1,BIG m)
+	{
+		BIG a=new BIG(a1);
+		a.mod(m);
+		return m.minus(a);
+	}
+
+/* return this^e mod m */
+	public BIG powmod(BIG e1,BIG m)
+	{
+		BIG e=new BIG(e1);
+		int bt;
+		norm();
+		e.norm();
+		BIG a=new BIG(1);
+		BIG z=new BIG(e);
+		BIG s=new BIG(this);
+		while (true)
+		{
+			bt=z.parity();
+			z.fshr(1);
+			if (bt==1) a=modmul(a,s,m);
+			if (z.iszilch()) break;
+			s=modsqr(s,m);
+		}
+		return a;
+	}
+
+/* Jacobi Symbol (this/p). Returns 0, 1 or -1 */
+	public int jacobi(BIG p)
+	{
+		int n8,k,m=0;
+		BIG t=new BIG(0);
+		BIG x=new BIG(0);
+		BIG n=new BIG(0);
+		BIG zilch=new BIG(0);
+		BIG one=new BIG(1);
+		if (p.parity()==0 || comp(this,zilch)==0 || comp(p,one)<=0) return 0;
+		norm();
+		x.copy(this);
+		n.copy(p);
+		x.mod(p);
+
+		while (comp(n,one)>0)
+		{
+			if (comp(x,zilch)==0) return 0;
+			n8=n.lastbits(3);
+			k=0;
+			while (x.parity()==0)
+			{
+				k++;
+				x.shr(1);
+			}
+			if (k%2==1) m+=(n8*n8-1)/8;
+			m+=(n8-1)*(x.lastbits(2)-1)/4;
+			t.copy(n);
+			t.mod(x);
+			n.copy(x);
+			x.copy(t);
+			m%=2;
+
+		}
+		if (m==0) return 1;
+		else return -1;
+	}
+
+/* this=1/this mod p. Binary method */
+	public void invmodp(BIG p)
+	{
+		mod(p);
+		BIG u=new BIG(this);
+		BIG v=new BIG(p);
+		BIG x1=new BIG(1);
+		BIG x2=new BIG(0);
+		BIG t=new BIG(0);
+		BIG one=new BIG(1);
+
+		while (comp(u,one)!=0 && comp(v,one)!=0)
+		{
+			while (u.parity()==0)
+			{
+				u.fshr(1);
+				if (x1.parity()!=0)
+				{
+					x1.add(p);
+					x1.norm();
+				}
+				x1.fshr(1);
+			}
+			while (v.parity()==0)
+			{
+				v.fshr(1);
+				if (x2.parity()!=0)
+				{
+					x2.add(p);
+					x2.norm();
+				}
+				x2.fshr(1);
+			}
+			if (comp(u,v)>=0)
+			{
+				u.sub(v);
+				u.norm();
+				if (comp(x1,x2)>=0) x1.sub(x2);
+				else
+				{
+					t.copy(p);
+					t.sub(x2);
+					x1.add(t);
+				}
+				x1.norm();
+			}
+			else
+			{
+				v.sub(u);
+				v.norm();
+				if (comp(x2,x1)>=0) x2.sub(x1);
+				else
+				{
+					t.copy(p);
+					t.sub(x1);
+					x2.add(t);
+				}
+				x2.norm();
+			}
+		}
+		if (comp(u,one)==0) copy(x1);
+		else copy(x2);
+	}
+}
diff --git a/version3/java/BIG64.java b/version3/java/BIG64.java
new file mode 100644
index 0000000..8de7878
--- /dev/null
+++ b/version3/java/BIG64.java
@@ -0,0 +1,933 @@
+/*
+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.
+*/
+
+/* AMCL BIG number class */ 
+
+package org.apache.milagro.amcl.XXX;
+import org.apache.milagro.amcl.RAND;
+
+public class BIG {
+
+	public static final int CHUNK=64; /* Set word size */
+
+	public static final int MODBYTES=@NB@; //(1+(MODBITS-1)/8);
+	public static final int BASEBITS=@BASE@; 
+
+	public static final int NLEN=(1+((8*MODBYTES-1)/BASEBITS));
+	public static final int DNLEN=2*NLEN;
+	public static final long BMASK=(((long)1<<BASEBITS)-1);
+
+	public static final int HBITS=BASEBITS/2;
+	public static final long HMASK=(((long)1<<HBITS)-1);
+	public static final int NEXCESS = ((int)1<<(CHUNK-BASEBITS-1));
+	public static final int BIGBITS=(MODBYTES*8);
+
+
+
+	protected long[] w=new long[NLEN];
+/* Constructors */
+	public BIG()
+	{
+		for (int i=0;i<NLEN;i++)
+			w[i]=0;
+	}
+
+	public BIG(int x)
+	{
+		w[0]=x;
+		for (int i=1;i<NLEN;i++)
+			w[i]=0;
+	}
+
+	public BIG(BIG x)
+	{
+		for (int i=0;i<NLEN;i++)
+			w[i]=x.w[i];
+	}
+
+	public BIG(DBIG x)
+	{
+		for (int i=0;i<NLEN;i++)
+			w[i]=x.w[i];
+	}
+
+	public BIG(long[] x)
+	{
+			for (int i=0;i<NLEN;i++)
+				w[i]=x[i];
+	}
+
+	public long get(int i)
+	{
+		return w[i];
+	}
+
+	public void set(int i,long x)
+	{
+		w[i]=x;
+	} 
+
+
+/* Conditional swap of two bigs depending on d using XOR - no branches */
+	public void cswap(BIG b,int d)
+	{
+		int i;
+		long t,c=(long)d;
+		c=~(c-1);
+
+		for (i=0;i<NLEN;i++)
+		{
+			t=c&(w[i]^b.w[i]);
+			w[i]^=t;
+			b.w[i]^=t;
+		}
+	}
+
+	public void cmove(BIG g,int d)
+	{
+		int i;
+		long t,b=-d;
+
+		for (i=0;i<NLEN;i++)
+		{
+			w[i]^=(w[i]^g.w[i])&b;
+		}
+	}
+
+    public static long cast_to_chunk(int x)
+	{
+		return (long)x;
+	}
+
+/* normalise BIG - force all digits < 2^BASEBITS */
+	public long norm() {
+		long d,carry=0;
+		for (int i=0;i<NLEN-1;i++)
+		{
+			d=w[i]+carry;
+			w[i]=d&BMASK;
+			carry=(d>>BASEBITS);
+		}
+		w[NLEN-1]=(w[NLEN-1]+carry);
+		return (long)(w[NLEN-1]>>((8*MODBYTES)%BASEBITS));  
+	}
+
+/* return number of bits */
+	public int nbits() {
+		BIG t=new BIG(this);
+		int bts,k=NLEN-1;
+		long c;
+		t.norm();
+		while (k>=0 && t.w[k]==0) k--;
+		if (k<0) return 0;
+		bts=BASEBITS*k;
+		c=t.w[k];
+		while (c!=0) {c/=2; bts++;}
+		return bts;
+	}
+
+	public String toRawString()
+	{
+		BIG b=new BIG(this);
+		String s="(";
+		for (int i=0;i<NLEN-1;i++)
+		{
+			s+=Long.toHexString(b.w[i]); s+=",";
+		}
+		s+=Long.toHexString(b.w[NLEN-1]); s+=")";
+		return s;
+	}
+
+/* Convert to Hex String */
+	public String toString() {
+		BIG b;
+		String s="";
+		int len=nbits();
+
+		if (len%4==0) len/=4;
+		else {len/=4; len++;}
+		if (len<MODBYTES*2) len=MODBYTES*2;
+
+		for (int i=len-1;i>=0;i--)
+		{
+			b=new BIG(this);
+			b.shr(i*4);
+			s+=Long.toHexString(b.w[0]&15);
+		}
+		return s;
+	}
+
+/* set this[i]+=x*y+c, and return high part */
+
+	public static long[] muladd(long a,long b,long c,long r)
+	{
+		long x0,x1,y0,y1;
+		long[] tb=new long[2];
+		x0=a&HMASK;
+		x1=(a>>HBITS);
+		y0=b&HMASK;
+		y1=(b>>HBITS);
+		long bot=x0*y0;
+		long top=x1*y1;
+		long mid=x0*y1+x1*y0;
+		x0=mid&HMASK;
+		x1=(mid>>HBITS);
+		bot+=x0<<HBITS; bot+=c; bot+=r;
+		top+=x1;
+		long carry=bot>>BASEBITS;
+		bot&=BMASK;
+		top+=carry;
+		tb[0]=top;
+		tb[1]=bot;
+		return tb;
+	}
+
+/* this*=x, where x is >NEXCESS */
+	public long pmul(int c)
+	{
+		long ak,carry=0;
+		long[] cr=new long[2];
+
+		for (int i=0;i<NLEN;i++)
+		{
+			ak=w[i];
+			w[i]=0;
+
+			cr=muladd(ak,(long)c,carry,w[i]);
+			carry=cr[0];
+			w[i]=cr[1];
+
+		}
+		return carry;
+	}
+
+/* return this*c and catch overflow in DBIG */
+	public DBIG pxmul(int c)
+	{
+		DBIG m=new DBIG(0);	
+		long[] cr=new long[2];
+		long carry=0;
+		for (int j=0;j<NLEN;j++)
+		{
+			cr=muladd(w[j],(long)c,carry,m.w[j]);
+			carry=cr[0];
+			m.w[j]=cr[1];
+		}
+		m.w[NLEN]=carry;		
+		return m;
+	}
+
+/* divide by 3 */
+	public int div3()
+	{	
+		long ak,base,carry=0;
+		norm();
+		base=((long)1<<BASEBITS);
+		for (int i=NLEN-1;i>=0;i--)
+		{
+			ak=(carry*base+w[i]);
+			w[i]=ak/3;
+			carry=ak%3;
+		}
+		return (int)carry;
+	}
+
+/* return a*b where result fits in a BIG */
+	public static BIG smul(BIG a,BIG b)
+	{
+		long carry;
+		long[] cr=new long[2];
+		BIG c=new BIG(0);
+		for (int i=0;i<NLEN;i++)
+		{
+			carry=0;
+			for (int j=0;j<NLEN;j++)
+				if (i+j<NLEN)
+				{
+					cr=muladd(a.w[i],b.w[j],carry,c.w[i+j]);
+					carry=cr[0];
+					c.w[i+j]=cr[1];
+				}
+		}
+		return c;
+	}
+
+/* return a*b as DBIG */
+/* Inputs must be normed */
+	public static DBIG mul(BIG a,BIG b)
+	{
+		DBIG c=new DBIG(0);
+		long carry;
+		long[] cr=new long[2];
+
+		for (int i=0;i<NLEN;i++)
+		{
+			carry=0;
+			for (int j=0;j<NLEN;j++)
+			{
+				cr=muladd(a.w[i],b.w[j],carry,c.w[i+j]);
+				carry=cr[0];
+				c.w[i+j]=cr[1];
+			}
+			c.w[NLEN+i]=carry;
+		}
+
+		return c;
+	}
+
+/* return a^2 as DBIG */
+/* Input must be normed */
+	public static DBIG sqr(BIG a)
+	{
+		DBIG c=new DBIG(0);
+		long carry;
+		long[] cr=new long[2];
+
+		for (int i=0;i<NLEN;i++)
+		{
+			carry=0;
+			for (int j=i+1;j<NLEN;j++)
+			{
+				cr=muladd(2*a.w[i],a.w[j],carry,c.w[i+j]);
+				carry=cr[0];
+				c.w[i+j]=cr[1];
+			}
+			c.w[NLEN+i]=carry;
+		}
+
+		for (int i=0;i<NLEN;i++)
+		{
+			cr=muladd(a.w[i],a.w[i],0,c.w[2*i]);
+			c.w[2*i+1]+=cr[0];
+			c.w[2*i]=cr[1];
+		}
+		c.norm(); 
+		return c;
+	}
+
+	static BIG monty(BIG md,long MC,DBIG d)
+	{
+		BIG b;
+		long m,carry;
+		long[] cr=new long[2];
+		for (int i=0;i<NLEN;i++) 
+		{
+			if (MC==-1) m=(-d.w[i])&BMASK;
+			else
+			{
+				if (MC==1) m=d.w[i];
+				else m=(MC*d.w[i])&BMASK;
+			}
+
+			carry=0;
+			for (int j=0;j<NLEN;j++)
+			{
+				cr=muladd(m,md.w[j],carry,d.w[i+j]);
+				carry=cr[0];
+				d.w[i+j]=cr[1];
+			}
+			d.w[NLEN+i]+=carry;
+		}
+
+		b=new BIG(0);
+		for (int i=0;i<NLEN;i++ )
+			b.w[i]=d.w[NLEN+i];
+		b.norm();
+		return b;		
+	}
+
+	public static int ssn(BIG r,BIG a,BIG m)
+	{
+		int n=NLEN-1;
+		m.w[0]=(m.w[0]>>1)|((m.w[1]<<(BASEBITS-1))&BMASK);
+		r.w[0]=a.w[0]-m.w[0];
+		long carry=r.w[0]>>BASEBITS;
+		r.w[0]&=BMASK;
+		for (int i=1;i<n;i++) {
+			m.w[i]=(m.w[i]>>1)|((m.w[i+1]<<(BASEBITS-1))&BMASK);
+			r.w[i]=a.w[i]-m.w[i]+carry;
+			carry=r.w[i]>>BASEBITS;
+			r.w[i]&=BMASK;
+		}
+		m.w[n]>>=1;
+		r.w[n]=a.w[n]-m.w[n]+carry;
+		return (int)((r.w[n]>>(CHUNK-1))&1);
+	}
+
+/****************************************************************************/
+
+	public void xortop(long x)
+	{
+		w[NLEN-1]^=x;
+	}
+
+/* set x = x mod 2^m */
+	public void mod2m(int m)
+	{
+		int i,wd,bt;
+		wd=m/BASEBITS;
+		bt=m%BASEBITS;
+		w[wd]&=((cast_to_chunk(1)<<bt)-1);
+		for (i=wd+1;i<NLEN;i++) w[i]=0;
+	}
+
+/* return n-th bit */
+	public int bit(int n)
+	{
+		if ((w[n/BASEBITS]&(cast_to_chunk(1)<<(n%BASEBITS)))>0) return 1;
+		else return 0;
+	}
+
+/* Shift right by less than a word */
+	public int fshr(int k) {
+		int r=(int)(w[0]&((cast_to_chunk(1)<<k)-1)); /* shifted out part */
+		for (int i=0;i<NLEN-1;i++)
+			w[i]=(w[i]>>k)|((w[i+1]<<(BASEBITS-k))&BMASK);
+		w[NLEN-1]=w[NLEN-1]>>k;
+		return r;
+	}
+
+/* Shift right by less than a word */
+	public int fshl(int k) {
+		w[NLEN-1]=((w[NLEN-1]<<k))|(w[NLEN-2]>>(BASEBITS-k));
+		for (int i=NLEN-2;i>0;i--)
+			w[i]=((w[i]<<k)&BMASK)|(w[i-1]>>(BASEBITS-k));
+		w[0]=(w[0]<<k)&BMASK; 
+		return (int)(w[NLEN-1]>>((8*MODBYTES)%BASEBITS)); /* return excess - only used in FF.java */
+	}
+
+/* test for zero */
+	public boolean iszilch() {
+		for (int i=0;i<NLEN;i++)
+			if (w[i]!=0) return false;
+		return true; 
+	}
+
+/* set to zero */
+	public void zero()
+	{
+		for (int i=0;i<NLEN;i++)
+			w[i]=0;
+	}
+
+/* set to one */
+	public void one()
+	{
+		w[0]=1;
+		for (int i=1;i<NLEN;i++)
+			w[i]=0;
+	}
+
+/* Test for equal to one */
+	public boolean isunity()
+	{
+		for (int i=1;i<NLEN;i++)
+			if (w[i]!=0) return false;
+		if (w[0]!=1) return false;
+		return true;
+	}
+
+/* Copy from another BIG */
+	public void copy(BIG x)
+	{
+		for (int i=0;i<NLEN;i++)
+			w[i]=x.w[i];
+	}
+
+	public void copy(DBIG x)
+	{
+		for (int i=0;i<NLEN;i++)
+			w[i]=x.w[i];
+	}
+
+/* general shift right */
+	public void shr(int k) {
+		int n=k%BASEBITS;
+		int m=k/BASEBITS;	
+		for (int i=0;i<NLEN-m-1;i++)
+			w[i]=(w[m+i]>>n)|((w[m+i+1]<<(BASEBITS-n))&BMASK);
+		if (NLEN>m) w[NLEN-m-1]=w[NLEN-1]>>n;
+		for (int i=NLEN-m;i<NLEN;i++) w[i]=0;
+	}
+
+/* general shift left */
+	public void shl(int k) {
+		int n=k%BASEBITS;
+		int m=k/BASEBITS;
+
+		w[NLEN-1]=((w[NLEN-1-m]<<n));
+		if (NLEN>=m+2) w[NLEN-1]|=(w[NLEN-m-2]>>(BASEBITS-n));
+
+		for (int i=NLEN-2;i>m;i--)
+			w[i]=((w[i-m]<<n)&BMASK)|(w[i-m-1]>>(BASEBITS-n));
+		w[m]=(w[0]<<n)&BMASK;
+		for (int i=0;i<m;i++) w[i]=0;
+	}
+
+/* return this+x */
+	public BIG plus(BIG x) {
+		BIG s=new BIG(0);
+		for (int i=0;i<NLEN;i++)
+			s.w[i]=w[i]+x.w[i];
+		return s;
+	}
+
+/* this+=x */
+	public void add(BIG x) {
+		for (int i=0;i<NLEN;i++)
+			w[i]+=x.w[i];
+	}
+
+/* this|=x */
+	public void or(BIG x) {
+		for (int i=0;i<NLEN;i++)
+			w[i]|=x.w[i];
+	}
+
+
+/* this+=x, where x is int */
+	public void inc(int x) {
+		norm();
+		w[0]+=x;
+	}
+
+/* this+=x, where x is long */
+	public void incl(long x) {
+		norm();
+		w[0]+=x;
+	}	
+
+/* return this.x */
+	public BIG minus(BIG x) {
+		BIG d=new BIG(0);
+		for (int i=0;i<NLEN;i++)
+			d.w[i]=w[i]-x.w[i];
+		return d;
+	}
+
+/* this-=x */
+	public void sub(BIG x) {
+		for (int i=0;i<NLEN;i++)
+			w[i]-=x.w[i];
+	}
+
+/* reverse subtract this=x-this */
+	public void rsub(BIG x) {
+		for (int i=0;i<NLEN;i++)
+			w[i]=x.w[i]-w[i];
+	}
+
+/* this-=x where x is int */
+	public void dec(int x) {
+		norm();
+		w[0]-=x;
+	}
+
+/* this*=x, where x is small int<NEXCESS */
+	public void imul(int c)
+	{
+		for (int i=0;i<NLEN;i++) w[i]*=c;
+	}
+
+/* convert this BIG to byte array */
+	public void tobytearray(byte[] b,int n)
+	{
+		
+		BIG c=new BIG(this);
+		c.norm();
+
+		for (int i=MODBYTES-1;i>=0;i--)
+		{
+			b[i+n]=(byte)c.w[0];
+			c.fshr(8);
+		}
+	}
+
+/* convert from byte array to BIG */
+	public static BIG frombytearray(byte[] b,int n)
+	{
+		BIG m=new BIG(0);
+
+		for (int i=0;i<MODBYTES;i++)
+		{
+			m.fshl(8); m.w[0]+=(int)b[i+n]&0xff;
+			//m.inc((int)b[i]&0xff);
+		}
+		return m; 
+	}
+
+	public void toBytes(byte[] b)
+	{
+		tobytearray(b,0);
+	}
+
+	public static BIG fromBytes(byte[] b)
+	{
+		return frombytearray(b,0);
+	}
+
+/* Compare a and b, return 0 if a==b, -1 if a<b, +1 if a>b. Inputs must be normalised */
+	public static int comp(BIG a,BIG b)
+	{
+		for (int i=NLEN-1;i>=0;i--)
+		{
+			if (a.w[i]==b.w[i]) continue;
+			if (a.w[i]>b.w[i]) return 1;
+			else  return -1;
+		}
+		return 0;
+	}
+
+/* Arazi and Qi inversion mod 256 */
+	public static int invmod256(int a)
+	{
+		int U,t1,t2,b,c;
+		t1=0;
+		c=(a>>1)&1;  
+		t1+=c;
+		t1&=1;
+		t1=2-t1;
+		t1<<=1;
+		U=t1+1;
+
+// i=2
+		b=a&3;
+		t1=U*b; t1>>=2;
+		c=(a>>2)&3;
+		t2=(U*c)&3;
+		t1+=t2;
+		t1*=U; t1&=3;
+		t1=4-t1;
+		t1<<=2;
+		U+=t1;
+
+// i=4
+		b=a&15;
+		t1=U*b; t1>>=4;
+		c=(a>>4)&15;
+		t2=(U*c)&15;
+		t1+=t2;
+		t1*=U; t1&=15;
+		t1=16-t1;
+		t1<<=4;
+		U+=t1;
+
+		return U;
+	}
+
+/* a=1/a mod 2^256. This is very fast! */
+	public void invmod2m()
+	{
+		int i;
+		BIG U=new BIG(0);
+		BIG b=new BIG(0);
+		BIG c=new BIG(0);
+
+		U.inc(invmod256(lastbits(8)));
+
+		for (i=8;i<BIGBITS;i<<=1)
+		{
+			U.norm();
+			b.copy(this); b.mod2m(i);
+			BIG t1=BIG.smul(U,b); 
+			t1.shr(i);
+
+			c.copy(this); c.shr(i); c.mod2m(i);
+			BIG t2=BIG.smul(U,c); t2.mod2m(i);
+
+			t1.add(t2);
+			t1.norm();
+			b=BIG.smul(t1,U); t1.copy(b);
+			t1.mod2m(i);
+
+			t2.one(); t2.shl(i); t1.rsub(t2); t1.norm();
+
+			t1.shl(i);
+			U.add(t1);
+		}
+		U.mod2m(BIGBITS);
+		copy(U);
+		norm();
+	}
+
+/* reduce this mod m */
+	public void mod(BIG m1)
+	{
+		int k=0;  
+		BIG r=new BIG(0);
+		BIG m=new BIG(m1);
+
+		norm();
+		if (comp(this,m)<0) return;
+		do
+		{
+			m.fshl(1);
+			k++;
+		} while (comp(this,m)>=0);
+
+		while (k>0)
+		{
+			m.fshr(1);
+
+			r.copy(this);
+			r.sub(m);
+			r.norm();
+			cmove(r,(int)(1-((r.w[NLEN-1]>>(CHUNK-1))&1)));
+			k--;
+		}
+	}
+
+/* divide this by m */
+	public void div(BIG m1)
+	{
+		int d,k=0;
+		norm();
+		BIG e=new BIG(1);
+		BIG m=new BIG(m1);
+		BIG b=new BIG(this);
+		BIG r=new BIG(0);
+		zero();
+
+		while (comp(b,m)>=0)
+		{
+			e.fshl(1);
+			m.fshl(1);
+			k++;
+		}
+
+		while (k>0)
+		{
+			m.fshr(1);
+			e.fshr(1);
+
+			r.copy(b);
+			r.sub(m);
+			r.norm();
+			d=(int)(1-((r.w[NLEN-1]>>(CHUNK-1))&1));
+			b.cmove(r,d);
+			r.copy(this);
+			r.add(e);
+			r.norm();
+			cmove(r,d);
+			k--;
+		}
+	}
+
+/* return parity */
+	public int parity()
+	{
+		return (int)(w[0]%2);
+	}
+
+/* return n last bits */
+	public int lastbits(int n)
+	{
+		int msk=(1<<n)-1;
+		norm();
+		return ((int)w[0])&msk;
+	}
+
+/* get 8*MODBYTES size random number */
+	public static BIG random(RAND rng)
+	{
+		BIG m=new BIG(0);
+		int i,b,j=0,r=0;
+
+/* generate random BIG */ 
+		for (i=0;i<8*MODBYTES;i++)   
+		{
+			if (j==0) r=rng.getByte();
+			else r>>=1;
+
+			b=r&1;
+			m.shl(1); m.w[0]+=b;// m.inc(b);
+			j++; j&=7; 
+		}
+		return m;
+	}
+
+/* Create random BIG in portable way, one bit at a time */
+	public static BIG randomnum(BIG q,RAND rng) 
+	{
+		DBIG d=new DBIG(0);
+		int i,b,j=0,r=0;
+		for (i=0;i<2*q.nbits();i++)
+		{
+			if (j==0) r=rng.getByte();
+			else r>>=1;
+
+			b=r&1;
+			d.shl(1); d.w[0]+=b;// m.inc(b);
+			j++; j&=7; 
+		}
+		BIG m=d.mod(q);
+		return m;
+	}
+
+/* return a*b mod m */
+	public static BIG modmul(BIG a1,BIG b1,BIG m)
+	{
+		BIG a=new BIG(a1);
+		BIG b=new BIG(b1);
+		a.mod(m);
+		b.mod(m);
+		DBIG d=mul(a,b);
+		return d.mod(m);
+	}
+
+/* return a^2 mod m */
+	public static BIG modsqr(BIG a1,BIG m)
+	{
+		BIG a=new BIG(a1);
+		a.mod(m);
+		DBIG d=sqr(a);
+		return d.mod(m);
+	}
+
+/* return -a mod m */
+	public static BIG modneg(BIG a1,BIG m)
+	{
+		BIG a=new BIG(a1);
+		a.mod(m);
+		return m.minus(a);
+	}
+
+/* return this^e mod m */
+	public BIG powmod(BIG e1,BIG m)
+	{
+		BIG e=new BIG(e1);
+		int bt;
+		norm();
+		e.norm();
+		BIG a=new BIG(1);
+		BIG z=new BIG(e);
+		BIG s=new BIG(this);
+		while (true)
+		{
+			bt=z.parity();
+			z.fshr(1);
+			if (bt==1) a=modmul(a,s,m);
+			if (z.iszilch()) break;
+			s=modsqr(s,m);
+		}
+		return a;
+	}
+
+/* Jacobi Symbol (this/p). Returns 0, 1 or -1 */
+	public int jacobi(BIG p)
+	{
+		int n8,k,m=0;
+		BIG t=new BIG(0);
+		BIG x=new BIG(0);
+		BIG n=new BIG(0);
+		BIG zilch=new BIG(0);
+		BIG one=new BIG(1);
+		if (p.parity()==0 || comp(this,zilch)==0 || comp(p,one)<=0) return 0;
+		norm();
+		x.copy(this);
+		n.copy(p);
+		x.mod(p);
+
+		while (comp(n,one)>0)
+		{
+			if (comp(x,zilch)==0) return 0;
+			n8=n.lastbits(3);
+			k=0;
+			while (x.parity()==0)
+			{
+				k++;
+				x.shr(1);
+			}
+			if (k%2==1) m+=(n8*n8-1)/8;
+			m+=(n8-1)*(x.lastbits(2)-1)/4;
+			t.copy(n);
+			t.mod(x);
+			n.copy(x);
+			x.copy(t);
+			m%=2;
+
+		}
+		if (m==0) return 1;
+		else return -1;
+	}
+
+/* this=1/this mod p. Binary method */
+	public void invmodp(BIG p)
+	{
+		mod(p);
+		BIG u=new BIG(this);
+		BIG v=new BIG(p);
+		BIG x1=new BIG(1);
+		BIG x2=new BIG(0);
+		BIG t=new BIG(0);
+		BIG one=new BIG(1);
+
+		while (comp(u,one)!=0 && comp(v,one)!=0)
+		{
+			while (u.parity()==0)
+			{
+				u.fshr(1);
+				if (x1.parity()!=0)
+				{
+					x1.add(p);
+					x1.norm();
+				}
+				x1.fshr(1);
+			}
+			while (v.parity()==0)
+			{
+				v.fshr(1);
+				if (x2.parity()!=0)
+				{
+					x2.add(p);
+					x2.norm();
+				}
+				x2.fshr(1);
+			}
+			if (comp(u,v)>=0)
+			{
+				u.sub(v);
+				u.norm();
+				if (comp(x1,x2)>=0) x1.sub(x2);
+				else
+				{
+					t.copy(p);
+					t.sub(x2);
+					x1.add(t);
+				}
+				x1.norm();
+			}
+			else
+			{
+				v.sub(u);
+				v.norm();
+				if (comp(x2,x1)>=0) x2.sub(x1);
+				else
+				{
+					t.copy(p);
+					t.sub(x1);
+					x2.add(t);
+				}
+				x2.norm();
+			}
+		}
+		if (comp(u,one)==0) copy(x1);
+		else copy(x2);
+	}
+}
diff --git a/version3/java/DBIG32.java b/version3/java/DBIG32.java
new file mode 100644
index 0000000..35aa164
--- /dev/null
+++ b/version3/java/DBIG32.java
@@ -0,0 +1,282 @@
+/*
+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.
+*/
+
+/* AMCL double length DBIG number class */ 
+
+package org.apache.milagro.amcl.XXX;
+
+public class DBIG {
+	protected int[] w=new int[BIG.DNLEN];
+
+/* normalise this */
+	public void norm() {
+		int d,carry=0;
+		for (int i=0;i<BIG.DNLEN-1;i++)
+		{
+			d=w[i]+carry;
+			carry=d>>BIG.BASEBITS;
+			w[i]=d&BIG.BMASK;
+		}
+		w[BIG.DNLEN-1]=(w[BIG.DNLEN-1]+carry);
+	}
+
+
+/*
+	public String toRawString()
+	{
+		DBIG b=new DBIG(this);
+		String s="(";
+		for (int i=0;i<BIG.DNLEN-1;i++)
+		{
+			s+=Integer.toHexString(b.w[i]); s+=",";
+		}
+		s+=Integer.toHexString(b.w[BIG.DNLEN-1]); s+=")";
+		return s;
+	}
+*/
+/* split DBIG at position n, return higher half, keep lower half */
+	public BIG split(int n)
+	{
+		BIG t=new BIG(0);
+		int nw,m=n%BIG.BASEBITS;
+		int carry=w[BIG.DNLEN-1]<<(BIG.BASEBITS-m);
+
+		for (int i=BIG.DNLEN-2;i>=BIG.NLEN-1;i--)
+		{
+			nw=(w[i]>>m)|carry;
+			carry=(w[i]<<(BIG.BASEBITS-m))&BIG.BMASK;
+			t.w[i-BIG.NLEN+1]=nw;
+		//	t.set(i-BIG.NLEN+1,nw);
+		}
+		w[BIG.NLEN-1]&=(((int)1<<m)-1);
+		return t;
+	}
+
+
+/****************************************************************************/
+
+
+/* return number of bits in this */
+	public int nbits() {
+		int bts,k=BIG.DNLEN-1;
+		DBIG t=new DBIG(this);
+		long c;
+		t.norm();
+		while (t.w[k]==0 && k>=0) k--;
+		if (k<0) return 0;
+		bts=BIG.BASEBITS*k;
+		c=t.w[k];
+		while (c!=0) {c/=2; bts++;}
+		return bts;
+	}
+
+/* convert this to string */
+	public String toString() {
+		DBIG b;
+		String s="";
+		int len=nbits();
+		if (len%4==0) len>>=2; //len/=4;
+		else {len>>=2; len++;}
+
+		for (int i=len-1;i>=0;i--)
+		{
+			b=new DBIG(this);
+			b.shr(i*4);
+			s+=Integer.toHexString((int)(b.w[0]&15));
+		}
+		return s;
+	}
+
+	public void cmove(DBIG g,int d)
+	{
+		int i;
+		for (i=0;i<BIG.DNLEN;i++)
+		{
+			w[i]^=(w[i]^g.w[i])&BIG.cast_to_chunk(-d);
+		}
+	}
+
+/* Constructors */
+	public DBIG(int x)
+	{
+		w[0]=x;
+		for (int i=1;i<BIG.DNLEN;i++)
+			w[i]=0;
+	}
+
+	public DBIG(DBIG x)
+	{
+		for (int i=0;i<BIG.DNLEN;i++)
+			w[i]=x.w[i];
+	}
+
+	public DBIG(BIG x)
+	{
+		for (int i=0;i<BIG.NLEN-1;i++)
+			w[i]=x.w[i];//get(i);
+
+		w[BIG.NLEN-1]=x.w[(BIG.NLEN-1)]&BIG.BMASK; /* top word normalized */
+		w[BIG.NLEN]=(x.w[(BIG.NLEN-1)]>>BIG.BASEBITS);
+
+		for (int i=BIG.NLEN+1;i<BIG.DNLEN;i++) w[i]=0;
+	}
+
+
+/* Copy from another DBIG */
+	public void copy(DBIG x)
+	{
+		for (int i=0;i<BIG.DNLEN;i++)
+			w[i]=x.w[i];
+	}
+
+/* Copy into upper part */
+	public void ucopy(BIG x)
+	{
+		for (int i=0;i<BIG.NLEN;i++)
+			w[i]=0;
+		for (int i=BIG.NLEN;i<BIG.DNLEN;i++)
+			w[i]=x.w[i-BIG.NLEN];
+	}
+
+/* test this=0? */
+	public boolean iszilch() {
+		for (int i=0;i<BIG.DNLEN;i++)
+			if (w[i]!=0) return false;
+		return true; 
+	}
+
+/* shift this right by k bits */
+	public void shr(int k) {
+		int n=k%BIG.BASEBITS;
+		int m=k/BIG.BASEBITS;	
+		for (int i=0;i<BIG.DNLEN-m-1;i++)
+			w[i]=(w[m+i]>>n)|((w[m+i+1]<<(BIG.BASEBITS-n))&BIG.BMASK);
+		w[BIG.DNLEN-m-1]=w[BIG.DNLEN-1]>>n;
+		for (int i=BIG.DNLEN-m;i<BIG.DNLEN;i++) w[i]=0;
+	}
+
+/* shift this left by k bits */
+	public void shl(int k) {
+		int n=k%BIG.BASEBITS;
+		int m=k/BIG.BASEBITS;
+
+		w[BIG.DNLEN-1]=((w[BIG.DNLEN-1-m]<<n))|(w[BIG.DNLEN-m-2]>>(BIG.BASEBITS-n));
+		for (int i=BIG.DNLEN-2;i>m;i--)
+			w[i]=((w[i-m]<<n)&BIG.BMASK)|(w[i-m-1]>>(BIG.BASEBITS-n));
+		w[m]=(w[0]<<n)&BIG.BMASK; 
+		for (int i=0;i<m;i++) w[i]=0;
+	}
+
+/* this+=x */
+	public void add(DBIG x) {
+		for (int i=0;i<BIG.DNLEN;i++)
+			w[i]+=x.w[i];	
+	}
+
+/* this-=x */
+	public void sub(DBIG x) {
+		for (int i=0;i<BIG.DNLEN;i++)
+			w[i]-=x.w[i];
+	}
+
+	public void rsub(DBIG x) {
+		for (int i=0;i<BIG.DNLEN;i++)
+			w[i]=x.w[i]-w[i];
+	}
+
+
+/* Compare a and b, return 0 if a==b, -1 if a<b, +1 if a>b. Inputs must be normalised */
+	public static int comp(DBIG a,DBIG b)
+	{
+		for (int i=BIG.DNLEN-1;i>=0;i--)
+		{
+			if (a.w[i]==b.w[i]) continue;
+			if (a.w[i]>b.w[i]) return 1;
+			else  return -1;
+		}
+		return 0;
+	}
+
+/* reduces this DBIG mod a BIG, and returns the BIG */
+	public BIG mod(BIG c)
+	{
+		int k=0;  
+		norm();
+		DBIG m=new DBIG(c);
+		DBIG r=new DBIG(0);
+
+		if (comp(this,m)<0) return new BIG(this);
+		
+		do
+		{
+			m.shl(1);
+			k++;
+		}
+		while (comp(this,m)>=0);
+
+		while (k>0)
+		{
+			m.shr(1);
+
+			r.copy(this);
+			r.sub(m);
+			r.norm();
+			cmove(r,(int)(1-((r.w[BIG.DNLEN-1]>>(BIG.CHUNK-1))&1)));
+			k--;
+		}
+		return new BIG(this);
+	}
+
+/* return this/c */
+	public BIG div(BIG c)
+	{
+		int d,k=0;
+		DBIG m=new DBIG(c);
+		DBIG dr=new DBIG(0);
+		BIG r=new BIG(0);
+		BIG a=new BIG(0);
+		BIG e=new BIG(1);
+		norm();
+
+		while (comp(this,m)>=0)
+		{
+			e.fshl(1);
+			m.shl(1);
+			k++;
+		}
+
+		while (k>0)
+		{
+			m.shr(1);
+			e.shr(1);
+
+			dr.copy(this);
+			dr.sub(m);
+			dr.norm();
+			d=(int)(1-((dr.w[BIG.DNLEN-1]>>(BIG.CHUNK-1))&1));
+			cmove(dr,d);
+			r.copy(a);
+			r.add(e);
+			r.norm();
+			a.cmove(r,d);
+			k--;
+		}
+		return a;
+	}
+}
diff --git a/version3/java/DBIG64.java b/version3/java/DBIG64.java
new file mode 100644
index 0000000..2fd92db
--- /dev/null
+++ b/version3/java/DBIG64.java
@@ -0,0 +1,280 @@
+/*
+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.
+*/
+
+/* AMCL double length DBIG number class */ 
+
+package org.apache.milagro.amcl.XXX;
+
+public class DBIG {
+	protected long[] w=new long[BIG.DNLEN];
+
+/* normalise this */
+	public void norm() {
+		long d,carry=0;
+		for (int i=0;i<BIG.DNLEN-1;i++)
+		{
+			d=w[i]+carry;
+			carry=d>>BIG.BASEBITS;
+			w[i]=d&BIG.BMASK;
+		}
+		w[BIG.DNLEN-1]=(w[BIG.DNLEN-1]+carry);
+	}
+
+
+/*
+	public String toRawString()
+	{
+		DBIG b=new DBIG(this);
+		String s="(";
+		for (int i=0;i<BIG.DNLEN-1;i++)
+		{
+			s+=Long.toHexString(b.w[i]); s+=",";
+		}
+		s+=Long.toHexString(b.w[BIG.DNLEN-1]); s+=")";
+		return s;
+	}
+*/
+
+/* split DBIG at position n, return higher half, keep lower half */
+	public BIG split(int n)
+	{
+		BIG t=new BIG(0);
+		int m=n%BIG.BASEBITS;
+		long nw,carry=w[BIG.DNLEN-1]<<(BIG.BASEBITS-m);
+
+		for (int i=BIG.DNLEN-2;i>=BIG.NLEN-1;i--)
+		{
+			nw=(w[i]>>m)|carry;
+			carry=(w[i]<<(BIG.BASEBITS-m))&BIG.BMASK;
+			t.w[i-BIG.NLEN+1]=nw;
+			//t.set(i-BIG.NLEN+1,nw);
+		}
+		w[BIG.NLEN-1]&=(((long)1<<m)-1);
+		return t;
+	}
+
+/****************************************************************************/
+
+/* return number of bits in this */
+	public int nbits() {
+		int bts,k=BIG.DNLEN-1;
+		DBIG t=new DBIG(this);
+		long c;
+		t.norm();
+		while (t.w[k]==0 && k>=0) k--;
+		if (k<0) return 0;
+		bts=BIG.BASEBITS*k;
+		c=t.w[k];
+		while (c!=0) {c/=2; bts++;}
+		return bts;
+	}
+
+/* convert this to string */
+	public String toString() {
+		DBIG b;
+		String s="";
+		int len=nbits();
+		if (len%4==0) len>>=2; //len/=4;
+		else {len>>=2; len++;}
+
+		for (int i=len-1;i>=0;i--)
+		{
+			b=new DBIG(this);
+			b.shr(i*4);
+			s+=Integer.toHexString((int)(b.w[0]&15));
+		}
+		return s;
+	}
+
+	public void cmove(DBIG g,int d)
+	{
+		int i;
+		for (i=0;i<BIG.DNLEN;i++)
+		{
+			w[i]^=(w[i]^g.w[i])&BIG.cast_to_chunk(-d);
+		}
+	}
+
+/* Constructors */
+	public DBIG(int x)
+	{
+		w[0]=x;
+		for (int i=1;i<BIG.DNLEN;i++)
+			w[i]=0;
+	}
+
+	public DBIG(DBIG x)
+	{
+		for (int i=0;i<BIG.DNLEN;i++)
+			w[i]=x.w[i];
+	}
+
+	public DBIG(BIG x)
+	{
+		for (int i=0;i<BIG.NLEN-1;i++)
+			w[i]=x.w[i]; //get(i);
+
+		w[BIG.NLEN-1]=x.w[(BIG.NLEN-1)]&BIG.BMASK; /* top word normalized */
+		w[BIG.NLEN]=(x.w[(BIG.NLEN-1)]>>BIG.BASEBITS);
+
+		for (int i=BIG.NLEN+1;i<BIG.DNLEN;i++) w[i]=0;
+	}
+
+/* Copy from another DBIG */
+	public void copy(DBIG x)
+	{
+		for (int i=0;i<BIG.DNLEN;i++)
+			w[i]=x.w[i];
+	}
+
+/* Copy into upper part */
+	public void ucopy(BIG x)
+	{
+		for (int i=0;i<BIG.NLEN;i++)
+			w[i]=0;
+		for (int i=BIG.NLEN;i<BIG.DNLEN;i++)
+			w[i]=x.w[i-BIG.NLEN];
+	}
+
+/* test this=0? */
+	public boolean iszilch() {
+		for (int i=0;i<BIG.DNLEN;i++)
+			if (w[i]!=0) return false;
+		return true; 
+	}
+
+/* shift this right by k bits */
+	public void shr(int k) {
+		int n=k%BIG.BASEBITS;
+		int m=k/BIG.BASEBITS;	
+		for (int i=0;i<BIG.DNLEN-m-1;i++)
+			w[i]=(w[m+i]>>n)|((w[m+i+1]<<(BIG.BASEBITS-n))&BIG.BMASK);
+		w[BIG.DNLEN-m-1]=w[BIG.DNLEN-1]>>n;
+		for (int i=BIG.DNLEN-m;i<BIG.DNLEN;i++) w[i]=0;
+	}
+
+/* shift this left by k bits */
+	public void shl(int k) {
+		int n=k%BIG.BASEBITS;
+		int m=k/BIG.BASEBITS;
+
+		w[BIG.DNLEN-1]=((w[BIG.DNLEN-1-m]<<n))|(w[BIG.DNLEN-m-2]>>(BIG.BASEBITS-n));
+		for (int i=BIG.DNLEN-2;i>m;i--)
+			w[i]=((w[i-m]<<n)&BIG.BMASK)|(w[i-m-1]>>(BIG.BASEBITS-n));
+		w[m]=(w[0]<<n)&BIG.BMASK; 
+		for (int i=0;i<m;i++) w[i]=0;
+	}
+
+/* this+=x */
+	public void add(DBIG x) {
+		for (int i=0;i<BIG.DNLEN;i++)
+			w[i]+=x.w[i];	
+	}
+
+/* this-=x */
+	public void sub(DBIG x) {
+		for (int i=0;i<BIG.DNLEN;i++)
+			w[i]-=x.w[i];
+	}
+
+	public void rsub(DBIG x) {
+		for (int i=0;i<BIG.DNLEN;i++)
+			w[i]=x.w[i]-w[i];
+	}
+
+/* Compare a and b, return 0 if a==b, -1 if a<b, +1 if a>b. Inputs must be normalised */
+	public static int comp(DBIG a,DBIG b)
+	{
+		for (int i=BIG.DNLEN-1;i>=0;i--)
+		{
+			if (a.w[i]==b.w[i]) continue;
+			if (a.w[i]>b.w[i]) return 1;
+			else  return -1;
+		}
+		return 0;
+	}
+
+/* reduces this DBIG mod a BIG, and returns the BIG */
+	public BIG mod(BIG c)
+	{
+		int k=0;  
+		norm();
+		DBIG m=new DBIG(c);
+		DBIG r=new DBIG(0);
+
+		if (comp(this,m)<0) return new BIG(this);
+		
+		do
+		{
+			m.shl(1);
+			k++;
+		}
+		while (comp(this,m)>=0);
+
+		while (k>0)
+		{
+			m.shr(1);
+
+			r.copy(this);
+			r.sub(m);
+			r.norm();
+			cmove(r,(int)(1-((r.w[BIG.DNLEN-1]>>(BIG.CHUNK-1))&1)));
+
+			k--;
+		}
+		return new BIG(this);
+	}
+
+/* return this/c */
+	public BIG div(BIG c)
+	{
+		int d,k=0;
+		DBIG m=new DBIG(c);
+		DBIG dr=new DBIG(0);
+		BIG r=new BIG(0);
+		BIG a=new BIG(0);
+		BIG e=new BIG(1);
+		norm();
+
+		while (comp(this,m)>=0)
+		{
+			e.fshl(1);
+			m.shl(1);
+			k++;
+		}
+
+		while (k>0)
+		{
+			m.shr(1);
+			e.shr(1);
+
+			dr.copy(this);
+			dr.sub(m);
+			dr.norm();
+			d=(int)(1-((dr.w[BIG.DNLEN-1]>>(BIG.CHUNK-1))&1));
+			cmove(dr,d);
+			r.copy(a);
+			r.add(e);
+			r.norm();
+			a.cmove(r,d);
+			k--;
+		}
+		return a;
+	}
+}
diff --git a/version3/java/ECDH.java b/version3/java/ECDH.java
new file mode 100644
index 0000000..6b21467
--- /dev/null
+++ b/version3/java/ECDH.java
@@ -0,0 +1,608 @@
+/*
+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.
+*/
+
+/* Elliptic Curve API high-level functions  */
+
+package org.apache.milagro.amcl.XXX;
+
+import org.apache.milagro.amcl.RAND;
+import org.apache.milagro.amcl.HASH256;
+import org.apache.milagro.amcl.HASH384;
+import org.apache.milagro.amcl.HASH512;
+import org.apache.milagro.amcl.AES;
+
+public final class ECDH {
+	public static final int INVALID_PUBLIC_KEY=-2;
+	public static final int ERROR=-3;
+	public static final int INVALID=-4;
+	public static final int EFS=BIG.MODBYTES;
+	public static final int EGS=BIG.MODBYTES;
+//	public static final int EAS=16;
+//	public static final int EBS=16;
+
+//	public static final int SHA256=32;
+//	public static final int SHA384=48;
+//	public static final int SHA512=64;
+
+
+//	public static final int HASH_TYPE=SHA512;
+
+
+/* Convert Integer to n-byte array */
+	public static byte[] inttoBytes(int n,int len)
+	{
+		int i;
+		byte[] b=new byte[len];
+
+		for (i=0;i<len;i++) b[i]=0;
+		i=len; 
+		while (n>0 && i>0)
+		{
+			i--;
+			b[i]=(byte)(n&0xff);
+			n/=256;
+		}	
+		return b;
+	}
+
+	public static byte[] hashit(int sha,byte[] A,int n,byte[] B,int pad)
+	{
+		byte[] R=null;
+
+		if (sha==ECP.SHA256)
+		{
+			HASH256 H=new HASH256();
+			H.process_array(A); if (n>0) H.process_num(n);
+			if (B!=null) H.process_array(B);
+			R=H.hash();
+		}
+		if (sha==ECP.SHA384)
+		{
+			HASH384 H=new HASH384();
+			H.process_array(A); if (n>0) H.process_num(n);
+			if (B!=null) H.process_array(B);
+			R=H.hash();
+		}
+		if (sha==ECP.SHA512)
+		{
+			HASH512 H=new HASH512();
+			H.process_array(A); if (n>0) H.process_num(n);
+			if (B!=null) H.process_array(B);
+			R=H.hash();
+		}
+		if (R==null) return null;
+
+		if (pad==0) return R;
+/* If pad>0 output is truncated or padded to pad bytes */
+		byte[] W=new byte[pad];
+		if (pad<=sha) 
+		{
+			for (int i=0;i<pad;i++) W[i]=R[i];
+		}
+		else
+		{
+			for (int i=0;i<sha;i++) W[i+pad-sha]=R[i];
+            for (int i=0;i<pad-sha;i++) W[i]=0;
+ 
+			//for (int i=0;i<sha;i++) W[i]=R[i];
+			//for (int i=sha;i<pad;i++) W[i]=0;
+		}
+		return W;
+	}
+
+/* Key Derivation Functions */
+/* Input octet Z */
+/* Output key of length olen */
+	public static byte[] KDF1(int sha,byte[] Z,int olen)
+	{
+/* NOTE: the parameter olen is the length of the output K in bytes */
+		int hlen=sha;
+		byte[] K=new byte[olen];
+		byte[] B;
+		int counter,cthreshold,k=0;
+    
+		for (int i=0;i<K.length;i++) K[i]=0;
+
+		cthreshold=olen/hlen; if (olen%hlen!=0) cthreshold++;
+
+		for (counter=0;counter<cthreshold;counter++)
+		{
+			B=hashit(sha,Z,counter,null,0);
+			if (k+hlen>olen) for (int i=0;i<olen%hlen;i++) K[k++]=B[i];
+			else for (int i=0;i<hlen;i++) K[k++]=B[i];
+		}
+		return K;
+	}
+
+	public static byte[] KDF2(int sha,byte[] Z,byte[] P,int olen)
+	{
+/* NOTE: the parameter olen is the length of the output k in bytes */
+		int hlen=sha;
+		byte[] K=new byte[olen];
+		byte[] B;
+		int counter,cthreshold,k=0;
+    
+		for (int i=0;i<K.length;i++) K[i]=0;
+
+		cthreshold=olen/hlen; if (olen%hlen!=0) cthreshold++;
+
+		for (counter=1;counter<=cthreshold;counter++)
+		{
+			B=hashit(sha,Z,counter,P,0);
+			if (k+hlen>olen) for (int i=0;i<olen%hlen;i++) K[k++]=B[i];
+			else for (int i=0;i<hlen;i++) K[k++]=B[i];
+		}
+
+		return K;
+	}
+
+/* Password based Key Derivation Function */
+/* Input password p, salt s, and repeat count */
+/* Output key of length olen */
+	public static byte[] PBKDF2(int sha,byte[] Pass,byte[] Salt,int rep,int olen)
+	{
+		int i,j,k,len,d,opt;
+		d=olen/sha; if (olen%sha!=0) d++;
+		byte[] F=new byte[sha];
+		byte[] U=new byte[sha];
+		byte[] S=new byte[Salt.length+4];
+
+		byte[] K=new byte[d*sha];
+		opt=0;
+
+		for (i=1;i<=d;i++)
+		{
+			for (j=0;j<Salt.length;j++) S[j]=Salt[j];
+			byte[] N=inttoBytes(i,4);
+			for (j=0;j<4;j++) S[Salt.length+j]=N[j];
+
+			HMAC(sha,S,Pass,F);
+
+			for (j=0;j<sha;j++) U[j]=F[j];
+			for (j=2;j<=rep;j++)
+			{
+				HMAC(sha,U,Pass,U);
+				for (k=0;k<sha;k++) F[k]^=U[k];
+			}
+			for (j=0;j<sha;j++) K[opt++]=F[j];
+		}
+		byte[] key=new byte[olen];
+		for (i=0;i<olen;i++) key[i]=K[i];
+		return key;
+	}
+
+/* Calculate HMAC of m using key k. HMAC is tag of length olen */
+	public static int HMAC(int sha,byte[] M,byte[] K,byte[] tag)
+	{
+	/* Input is from an octet m        *
+	* olen is requested output length in bytes. k is the key  *
+	* The output is the calculated tag */
+		int b=64;
+		if (sha>32) b=128;
+		byte[] B;
+		byte[] K0=new byte[b];
+		int olen=tag.length;
+
+		//b=K0.length;
+		if (olen<4 /*|| olen>sha*/) return 0;
+
+		for (int i=0;i<b;i++) K0[i]=0;
+
+		if (K.length > b) 
+		{
+			B=hashit(sha,K,0,null,0);
+			for (int i=0;i<sha;i++) K0[i]=B[i];
+		}
+		else
+			for (int i=0;i<K.length;i++ ) K0[i]=K[i];
+		
+		for (int i=0;i<b;i++) K0[i]^=0x36;
+		B=hashit(sha,K0,0,M,0);
+
+		for (int i=0;i<b;i++) K0[i]^=0x6a;
+		B=hashit(sha,K0,0,B,olen);
+
+		for (int i=0;i<olen;i++) tag[i]=B[i];
+
+		return 1;
+	}
+
+/* AES encryption/decryption. Encrypt byte array M using key K and returns ciphertext */
+	public static byte[] AES_CBC_IV0_ENCRYPT(byte[] K,byte[] M)
+	{ /* AES CBC encryption, with Null IV and key K */
+	/* Input is from an octet string M, output is to an octet string C */
+	/* Input is padded as necessary to make up a full final block */
+		AES a=new AES();
+		boolean fin;
+		int i,j,ipt,opt;
+		byte[] buff=new byte[16];
+		int clen=16+(M.length/16)*16;
+
+		byte[] C=new byte[clen];
+		int padlen;
+
+		a.init(AES.CBC,K.length,K,null);
+
+		ipt=opt=0;
+		fin=false;
+		for(;;)
+		{
+			for (i=0;i<16;i++)
+			{
+				if (ipt<M.length) buff[i]=M[ipt++];
+				else {fin=true; break;}
+			}
+			if (fin) break;
+			a.encrypt(buff);
+			for (i=0;i<16;i++)
+				C[opt++]=buff[i];
+		}    
+
+/* last block, filled up to i-th index */
+
+		padlen=16-i;
+		for (j=i;j<16;j++) buff[j]=(byte)padlen;
+
+		a.encrypt(buff);
+
+		for (i=0;i<16;i++)
+			C[opt++]=buff[i];
+		a.end();    
+		return C;
+	}
+
+/* returns plaintext if all consistent, else returns null string */
+	public static byte[] AES_CBC_IV0_DECRYPT(byte[] K,byte[] C)
+	{ /* padding is removed */
+		AES a=new AES();
+		int i,ipt,opt,ch;
+		byte[] buff=new byte[16];
+		byte[] MM=new byte[C.length];
+		boolean fin,bad;
+		int padlen;
+		ipt=opt=0;
+
+		a.init(AES.CBC,K.length,K,null);
+
+		if (C.length==0) return new byte[0];
+		ch=C[ipt++]; 
+  
+		fin=false;
+
+		for(;;)
+		{
+			for (i=0;i<16;i++)
+			{
+				buff[i]=(byte)ch;      
+				if (ipt>=C.length) {fin=true; break;}  
+				else ch=C[ipt++];  
+			}
+			a.decrypt(buff);
+			if (fin) break;
+			for (i=0;i<16;i++)
+				MM[opt++]=buff[i];
+		}    
+
+		a.end();
+		bad=false;
+		padlen=buff[15];
+		if (i!=15 || padlen<1 || padlen>16) bad=true;
+		if (padlen>=2 && padlen<=16)
+			for (i=16-padlen;i<16;i++) if (buff[i]!=padlen) bad=true;
+    
+		if (!bad) for (i=0;i<16-padlen;i++)
+					MM[opt++]=buff[i];
+
+		if (bad) return new byte[0];
+
+		byte[] M=new byte[opt];
+		for (i=0;i<opt;i++) M[i]=MM[i];
+
+		return M;
+	}
+
+/* Calculate a public/private EC GF(p) key pair W,S where W=S.G mod EC(p),
+ * where S is the secret key and W is the public key
+ * and G is fixed generator.
+ * If RNG is NULL then the private key is provided externally in S
+ * otherwise it is generated randomly internally */
+	public static int KEY_PAIR_GENERATE(RAND RNG,byte[] S,byte[] W)
+	{
+		BIG r,s;
+		ECP G,WP;
+		int res=0;
+	//	byte[] T=new byte[EFS];
+
+		G=ECP.generator();
+
+		r=new BIG(ROM.CURVE_Order);
+
+		if (RNG==null)
+		{
+			s=BIG.fromBytes(S);
+			s.mod(r);
+		}
+		else
+		{
+			s=BIG.randomnum(r,RNG);
+		}
+
+		//if (ROM.AES_S>0)
+		//{
+		//	s.mod2m(2*ROM.AES_S);
+		//}
+		s.toBytes(S);
+
+		WP=G.mul(s);
+		WP.toBytes(W,false);  // To use point compression on public keys, change to true 
+
+		return res;
+	}
+
+/* validate public key. */
+	public static int PUBLIC_KEY_VALIDATE(byte[] W)
+	{
+		BIG r,q,k;
+		ECP WP=ECP.fromBytes(W);
+		int nb,res=0;
+
+		r=new BIG(ROM.CURVE_Order);
+
+		if (WP.is_infinity()) res=INVALID_PUBLIC_KEY;
+
+		if (res==0)
+		{
+
+			q=new BIG(ROM.Modulus);
+			nb=q.nbits();
+			k=new BIG(1); k.shl((nb+4)/2);
+			k.add(q);
+			k.div(r);
+
+			while (k.parity()==0)
+			{
+				k.shr(1);
+				WP.dbl();
+			}
+
+			if (!k.isunity()) WP=WP.mul(k);
+			if (WP.is_infinity()) res=INVALID_PUBLIC_KEY; 
+		}
+		return res;
+	}
+
+/* IEEE-1363 Diffie-Hellman online calculation Z=S.WD */
+	public static int SVDP_DH(byte[] S,byte[] WD,byte[] Z)    
+	{
+		BIG r,s,wx,wy,z;
+		int valid;
+		ECP W;
+		int res=0;
+		byte[] T=new byte[EFS];
+
+		s=BIG.fromBytes(S);
+
+		W=ECP.fromBytes(WD);
+		if (W.is_infinity()) res=ERROR;
+
+		if (res==0)
+		{
+			r=new BIG(ROM.CURVE_Order);
+			s.mod(r);
+
+			W=W.mul(s);
+			if (W.is_infinity()) res=ERROR; 
+			else 
+			{
+				W.getX().toBytes(T);
+				for (int i=0;i<EFS;i++) Z[i]=T[i];
+			}
+		}
+		return res;
+	}
+
+/* IEEE ECDSA Signature, C and D are signature on F using private key S */
+	public static int SP_DSA(int sha,RAND RNG,byte[] S,byte[] F,byte[] C,byte[] D)
+	{
+		byte[] T=new byte[EFS];
+		BIG r,s,f,c,d,u,vx,w;
+		ECP G,V;
+		byte[] B=hashit(sha,F,0,null,BIG.MODBYTES);
+
+		G=ECP.generator();
+		r=new BIG(ROM.CURVE_Order);
+
+		s=BIG.fromBytes(S);
+		f=BIG.fromBytes(B);
+
+		c=new BIG(0);
+		d=new BIG(0);
+		V=new ECP();
+
+		do {
+			u=BIG.randomnum(r,RNG);
+			w=BIG.randomnum(r,RNG); /* side channel masking */
+			//if (ROM.AES_S>0)
+			//{
+			//	u.mod2m(2*ROM.AES_S);
+			//}			
+			V.copy(G);
+			V=V.mul(u);   		
+			vx=V.getX();
+			c.copy(vx);
+			c.mod(r);
+			if (c.iszilch()) continue;
+
+			u.copy(BIG.modmul(u,w,r));
+
+			u.invmodp(r);
+			d.copy(BIG.modmul(s,c,r));
+			d.add(f);
+
+			d.copy(BIG.modmul(d,w,r));
+
+			d.copy(BIG.modmul(u,d,r));
+		} while (d.iszilch());
+       
+		c.toBytes(T);
+		for (int i=0;i<EFS;i++) C[i]=T[i];
+		d.toBytes(T);
+		for (int i=0;i<EFS;i++) D[i]=T[i];
+		return 0;
+	}
+
+/* IEEE1363 ECDSA Signature Verification. Signature C and D on F is verified using public key W */
+	public static int VP_DSA(int sha,byte[] W,byte[] F, byte[] C,byte[] D)
+	{
+		BIG r,f,c,d,h2;
+		int res=0;
+		ECP G,WP,P;
+		int valid; 
+
+		byte[] B=hashit(sha,F,0,null,BIG.MODBYTES);
+
+		G=ECP.generator();
+		r=new BIG(ROM.CURVE_Order);
+
+		c=BIG.fromBytes(C);
+		d=BIG.fromBytes(D);
+		f=BIG.fromBytes(B);
+     
+		if (c.iszilch() || BIG.comp(c,r)>=0 || d.iszilch() || BIG.comp(d,r)>=0) 
+            res=INVALID;
+
+		if (res==0)
+		{
+			d.invmodp(r);
+			f.copy(BIG.modmul(f,d,r));
+			h2=BIG.modmul(c,d,r);
+
+			WP=ECP.fromBytes(W);
+			if (WP.is_infinity()) res=ERROR;
+			else
+			{
+				P=new ECP();
+				P.copy(WP);
+				P=P.mul2(h2,G,f);
+				if (P.is_infinity()) res=INVALID;
+				else
+				{
+					d=P.getX();
+					d.mod(r);
+					if (BIG.comp(d,c)!=0) res=INVALID;
+				}
+			}
+		}
+
+		return res;
+	}
+
+/* IEEE1363 ECIES encryption. Encryption of plaintext M uses public key W and produces ciphertext V,C,T */
+	public static byte[] ECIES_ENCRYPT(int sha,byte[] P1,byte[] P2,RAND RNG,byte[] W,byte[] M,byte[] V,byte[] T)
+	{ 
+		int i,len;
+
+		byte[] Z=new byte[EFS];
+		byte[] VZ=new byte[3*EFS+1];
+		byte[] K1=new byte[ECP.AESKEY];
+		byte[] K2=new byte[ECP.AESKEY];
+		byte[] U=new byte[EGS];
+
+		if (KEY_PAIR_GENERATE(RNG,U,V)!=0) return new byte[0];  
+		if (SVDP_DH(U,W,Z)!=0) return new byte[0];     
+
+		for (i=0;i<2*EFS+1;i++) VZ[i]=V[i];
+		for (i=0;i<EFS;i++) VZ[2*EFS+1+i]=Z[i];
+
+
+		byte[] K=KDF2(sha,VZ,P1,2*ECP.AESKEY);
+
+		for (i=0;i<ECP.AESKEY;i++) {K1[i]=K[i]; K2[i]=K[ECP.AESKEY+i];} 
+
+		byte[] C=AES_CBC_IV0_ENCRYPT(K1,M);
+
+		byte[] L2=inttoBytes(P2.length,8);	
+	
+		byte[] AC=new byte[C.length+P2.length+8];
+		for (i=0;i<C.length;i++) AC[i]=C[i];
+		for (i=0;i<P2.length;i++) AC[C.length+i]=P2[i];
+		for (i=0;i<8;i++) AC[C.length+P2.length+i]=L2[i];
+	
+		HMAC(sha,AC,K2,T);
+
+		return C;
+	}
+
+/* constant time n-byte compare */
+	static boolean ncomp(byte[] T1,byte[] T2,int n)
+	{
+		int res=0;
+		for (int i=0;i<n;i++)
+		{
+			res|=(int)(T1[i]^T2[i]);
+		}
+		if (res==0) return true;
+		return false;
+	}
+
+/* IEEE1363 ECIES decryption. Decryption of ciphertext V,C,T using private key U outputs plaintext M */
+	public static byte[] ECIES_DECRYPT(int sha,byte[] P1,byte[] P2,byte[] V,byte[] C,byte[] T,byte[] U)
+	{ 
+
+		int i,len;
+
+		byte[] Z=new byte[EFS];
+		byte[] VZ=new byte[3*EFS+1];
+		byte[] K1=new byte[ECP.AESKEY];
+		byte[] K2=new byte[ECP.AESKEY];
+		byte[] TAG=new byte[T.length];
+
+		if (SVDP_DH(U,V,Z)!=0) return new byte[0];  
+
+		for (i=0;i<2*EFS+1;i++) VZ[i]=V[i];
+		for (i=0;i<EFS;i++) VZ[2*EFS+1+i]=Z[i];
+
+		byte[] K=KDF2(sha,VZ,P1,2*ECP.AESKEY);
+
+		for (i=0;i<ECP.AESKEY;i++) {K1[i]=K[i]; K2[i]=K[ECP.AESKEY+i];} 
+
+		byte[] M=AES_CBC_IV0_DECRYPT(K1,C); 
+
+		if (M.length==0) return M;
+
+		byte[] L2=inttoBytes(P2.length,8);	
+	
+		byte[] AC=new byte[C.length+P2.length+8];
+
+		for (i=0;i<C.length;i++) AC[i]=C[i];
+		for (i=0;i<P2.length;i++) AC[C.length+i]=P2[i];
+		for (i=0;i<8;i++) AC[C.length+P2.length+i]=L2[i];
+	
+		HMAC(sha,AC,K2,TAG);
+
+		if (!ncomp(T,TAG,T.length)) return new byte[0];
+		
+//		boolean same=true;
+//		for (i=0;i<T.length;i++) if (T[i]!=TAG[i]) same=false;
+//		if (!same) return new byte[0];
+	
+		return M;
+
+	}
+}
diff --git a/version3/java/ECP.java b/version3/java/ECP.java
new file mode 100644
index 0000000..ddb9896
--- /dev/null
+++ b/version3/java/ECP.java
@@ -0,0 +1,1112 @@
+/*
+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.
+*/
+
+/* Elliptic Curve Point class */
+
+package org.apache.milagro.amcl.XXX;
+
+public final class ECP {
+
+	public static final int WEIERSTRASS=0;
+	public static final int EDWARDS=1;
+	public static final int MONTGOMERY=2;
+	public static final int NOT=0;
+	public static final int BN=1;
+	public static final int BLS=2;
+	public static final int D_TYPE=0;
+	public static final int M_TYPE=1;
+	public static final int POSITIVEX=0;
+	public static final int NEGATIVEX=1;
+
+	public static final int CURVETYPE=@CT@;
+	public static final int CURVE_PAIRING_TYPE=@PF@;
+	public static final int SEXTIC_TWIST=@ST@;
+	public static final int SIGN_OF_X=@SX@;
+
+	public static final int SHA256=32;
+	public static final int SHA384=48;
+	public static final int SHA512=64;
+
+	public static final int HASH_TYPE=@HT@;
+	public static final int AESKEY=@AK@;
+
+	private FP x;
+	private FP y;
+	private FP z;
+//	private boolean INF;
+
+/* Constructor - set to O */
+	public ECP() {
+		//INF=true;
+		x=new FP(0);
+		y=new FP(1);
+		if (CURVETYPE==EDWARDS)
+		{
+			z=new FP(1);
+		}
+		else
+		{
+			z=new FP(0);
+		}
+	}
+
+    public ECP(ECP e) {
+        this.x = new FP(e.x);
+        this.y = new FP(e.y);
+        this.z = new FP(e.z);
+    }
+
+/* test for O point-at-infinity */
+	public boolean is_infinity() {
+//		if (INF) return true;                            // Edits made
+		if (CURVETYPE==EDWARDS)
+		{
+			return (x.iszilch() && y.equals(z));
+		}
+		if (CURVETYPE==WEIERSTRASS)
+		{
+			return (x.iszilch() && z.iszilch());
+		}
+		if (CURVETYPE==MONTGOMERY)
+		{
+			return z.iszilch();
+		}
+		return true;
+	}
+/* Conditional swap of P and Q dependant on d */
+	private void cswap(ECP Q,int d)
+	{
+		x.cswap(Q.x,d);
+		if (CURVETYPE!=MONTGOMERY) y.cswap(Q.y,d);
+		z.cswap(Q.z,d);
+	//	if (CURVETYPE!=EDWARDS)
+	//	{
+	//		boolean bd;
+	//		if (d==0) bd=false;
+	//		else bd=true;
+	//		bd=bd&(INF^Q.INF);
+	//		INF^=bd;
+	//		Q.INF^=bd;
+	//	}
+	}
+
+/* Conditional move of Q to P dependant on d */
+	private void cmove(ECP Q,int d)
+	{
+		x.cmove(Q.x,d);
+		if (CURVETYPE!=MONTGOMERY) y.cmove(Q.y,d);
+		z.cmove(Q.z,d);
+	//	if (CURVETYPE!=EDWARDS)
+	//	{
+	//		boolean bd;
+	//		if (d==0) bd=false;
+	//		else bd=true;
+	//		INF^=(INF^Q.INF)&bd;
+	//	}
+	}
+
+/* return 1 if b==c, no branching */
+	private static int teq(int b,int c)
+	{
+		int x=b^c;
+		x-=1;  // if x=0, x now -1
+		return ((x>>31)&1);
+	}
+
+/* Constant time select from pre-computed table */
+	private void select(ECP W[],int b)
+	{
+		ECP MP=new ECP(); 
+		int m=b>>31;
+		int babs=(b^m)-m;
+
+		babs=(babs-1)/2;
+		cmove(W[0],teq(babs,0));  // conditional move
+		cmove(W[1],teq(babs,1));
+		cmove(W[2],teq(babs,2));
+		cmove(W[3],teq(babs,3));
+		cmove(W[4],teq(babs,4));
+		cmove(W[5],teq(babs,5));
+		cmove(W[6],teq(babs,6));
+		cmove(W[7],teq(babs,7));
+ 
+		MP.copy(this);
+		MP.neg();
+		cmove(MP,(int)(m&1));
+	}
+
+/* Test P == Q */
+	public boolean equals(ECP Q) {
+//		if (is_infinity() && Q.is_infinity()) return true;
+//		if (is_infinity() || Q.is_infinity()) return false;
+
+		FP a=new FP(0);                                        // Edits made
+		FP b=new FP(0);
+		a.copy(x); a.mul(Q.z); 
+		b.copy(Q.x); b.mul(z); 
+		if (!a.equals(b)) return false;
+		if (CURVETYPE!=MONTGOMERY)
+		{
+			a.copy(y); a.mul(Q.z); 
+			b.copy(Q.y); b.mul(z); 
+			if (!a.equals(b)) return false;
+		}
+		return true;
+	}
+
+/* this=P */
+	public void copy(ECP P)
+	{
+		x.copy(P.x);
+		if (CURVETYPE!=MONTGOMERY) y.copy(P.y);
+		z.copy(P.z);
+		//INF=P.INF;
+	}
+/* this=-this */
+	public void neg() {
+//		if (is_infinity()) return;
+		if (CURVETYPE==WEIERSTRASS)
+		{
+			y.neg(); y.norm();
+		}
+		if (CURVETYPE==EDWARDS)
+		{
+			x.neg(); x.norm();
+		}
+		return;
+	}
+/* set this=O */
+	public void inf() {
+//		INF=true;
+		x.zero();
+		if (CURVETYPE!=MONTGOMERY) y.one();
+		if (CURVETYPE!=EDWARDS) z.zero();
+		else z.one();
+	}
+
+/* Calculate RHS of curve equation */
+	public static FP RHS(FP x) {
+		//x.norm();
+		FP r=new FP(x);
+		r.sqr();
+
+		if (CURVETYPE==WEIERSTRASS)
+		{ // x^3+Ax+B
+			FP b=new FP(new BIG(ROM.CURVE_B));
+			r.mul(x);
+			if (ROM.CURVE_A==-3)
+			{
+				FP cx=new FP(x);
+				cx.imul(3);
+				cx.neg(); cx.norm();
+				r.add(cx);
+			}
+			r.add(b);
+		}
+		if (CURVETYPE==EDWARDS)
+		{ // (Ax^2-1)/(Bx^2-1) 
+			FP b=new FP(new BIG(ROM.CURVE_B));
+
+			FP one=new FP(1);
+			b.mul(r);
+			b.sub(one);
+			b.norm();
+			if (ROM.CURVE_A==-1) r.neg();
+			r.sub(one); r.norm();
+			b.inverse();
+
+			r.mul(b);
+		}
+		if (CURVETYPE==MONTGOMERY)
+		{ // x^3+Ax^2+x
+			FP x3=new FP(0);
+			x3.copy(r);
+			x3.mul(x);
+			r.imul(ROM.CURVE_A);
+			r.add(x3);
+			r.add(x);
+		}
+		r.reduce();
+		return r;
+	}
+
+/* set (x,y) from two BIGs */
+	public ECP(BIG ix,BIG iy) {
+		x=new FP(ix);
+		y=new FP(iy);
+		z=new FP(1);
+		x.norm();
+		FP rhs=RHS(x);
+
+		if (CURVETYPE==MONTGOMERY)
+		{
+			if (rhs.jacobi()!=1) inf();
+			//if (rhs.jacobi()==1) INF=false;
+			//else inf();
+		}
+		else
+		{
+			FP y2=new FP(y);
+			y2.sqr();
+			if (!y2.equals(rhs)) inf();
+			//if (y2.equals(rhs)) INF=false;
+			//else inf();
+		}
+	}
+/* set (x,y) from BIG and a bit */
+	public ECP(BIG ix,int s) {
+		x=new FP(ix);
+		x.norm();
+		FP rhs=RHS(x);
+		y=new FP(0);
+		z=new FP(1);
+		if (rhs.jacobi()==1)
+		{
+			FP ny=rhs.sqrt();
+			if (ny.redc().parity()!=s) ny.neg();
+			y.copy(ny);
+			//INF=false;
+		}
+		else inf();
+	}
+
+/* set from x - calculate y from curve equation */
+	public ECP(BIG ix) {
+		x=new FP(ix);
+		x.norm();
+		FP rhs=RHS(x);
+		y=new FP(0);
+		z=new FP(1);
+		if (rhs.jacobi()==1)
+		{
+			if (CURVETYPE!=MONTGOMERY) y.copy(rhs.sqrt());
+			//INF=false;
+		}
+		else inf(); //INF=true;
+	}
+
+/* set to affine - from (x,y,z) to (x,y) */
+	public void affine() {
+		if (is_infinity()) return;	// 
+		FP one=new FP(1);
+		if (z.equals(one)) return;
+		z.inverse();
+		x.mul(z); x.reduce();
+		if (CURVETYPE!=MONTGOMERY)            // Edits made
+		{
+			y.mul(z); y.reduce();
+		}
+		z.copy(one);
+	}
+/* extract x as a BIG */
+	public BIG getX()
+	{
+		ECP W=new ECP(this);
+		W.affine();
+		return W.x.redc();
+	}
+/* extract y as a BIG */
+	public BIG getY()
+	{
+		ECP W=new ECP(this);
+		W.affine();
+		return W.y.redc();
+	}
+
+/* get sign of Y */
+	public int getS()
+	{
+		//affine();
+		BIG y=getY();
+		return y.parity();
+	}
+/* extract x as an FP */
+	public FP getx()
+	{
+		return x;
+	}
+/* extract y as an FP */
+	public FP gety()
+	{
+		return y;
+	}
+/* extract z as an FP */
+	public FP getz()
+	{
+		return z;
+	}
+/* convert to byte array */
+	public void toBytes(byte[] b,boolean compress)
+	{
+		byte[] t=new byte[BIG.MODBYTES];
+		ECP W=new ECP(this);
+		W.affine();
+
+		W.x.redc().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) b[i+1]=t[i];
+
+		if (CURVETYPE==MONTGOMERY)
+		{
+			b[0]=0x06;
+			return;
+		}
+
+		if (compress)
+		{
+			b[0]=0x02;
+			if (y.redc().parity()==1) b[0]=0x03;
+			return;
+		}
+
+		b[0]=0x04;
+
+		W.y.redc().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) b[i+BIG.MODBYTES+1]=t[i];
+	}
+/* convert from byte array to point */
+	public static ECP fromBytes(byte[] b)
+	{
+		byte[] t=new byte[BIG.MODBYTES];
+		BIG p=new BIG(ROM.Modulus);
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=b[i+1];
+		BIG px=BIG.fromBytes(t);
+		if (BIG.comp(px,p)>=0) return new ECP();
+
+		if (CURVETYPE==MONTGOMERY)
+		{
+			return new ECP(px);
+		}
+
+		if (b[0]==0x04)
+		{
+			for (int i=0;i<BIG.MODBYTES;i++) t[i]=b[i+BIG.MODBYTES+1];
+			BIG py=BIG.fromBytes(t);
+			if (BIG.comp(py,p)>=0) return new ECP();
+			return new ECP(px,py);
+		}
+
+		if (b[0]==0x02 || b[0]==0x03)
+		{
+			return new ECP(px,(int)(b[0]&1));
+		}
+		return new ECP();
+	}
+/* convert to hex string */
+	public String toString() {
+		ECP W=new ECP(this);	
+		W.affine();
+		if (W.is_infinity()) return "infinity";
+		if (CURVETYPE==MONTGOMERY) return "("+W.x.redc().toString()+")";
+		else return "("+W.x.redc().toString()+","+W.y.redc().toString()+")";
+	}
+
+/* convert to hex string */
+	public String toRawString() {
+		//if (is_infinity()) return "infinity";
+		//affine();
+		ECP W=new ECP(this);	
+		if (CURVETYPE==MONTGOMERY) return "("+W.x.redc().toString()+","+W.z.redc().toString()+")";
+		else return "("+W.x.redc().toString()+","+W.y.redc().toString()+","+W.z.redc().toString()+")";
+	}
+
+/* this*=2 */
+	public void dbl() {
+//		if (INF) return;
+		
+		if (CURVETYPE==WEIERSTRASS)
+		{
+			if (ROM.CURVE_A==0)
+			{
+//System.out.println("Into dbl");
+				FP t0=new FP(y);                      /*** Change ***/    // Edits made
+				t0.sqr();
+				FP t1=new FP(y);
+				t1.mul(z);
+				FP t2=new FP(z);
+				t2.sqr();
+
+				z.copy(t0);
+				z.add(t0); z.norm(); 
+				z.add(z); z.add(z); z.norm();
+				t2.imul(3*ROM.CURVE_B_I);
+
+				FP x3=new FP(t2);
+				x3.mul(z);
+
+				FP y3=new FP(t0);
+				y3.add(t2); y3.norm();
+				z.mul(t1); 
+				t1.copy(t2); t1.add(t2); t2.add(t1);
+				t0.sub(t2); t0.norm(); y3.mul(t0); y3.add(x3);
+				t1.copy(x); t1.mul(y); 
+				x.copy(t0); x.norm(); x.mul(t1); x.add(x);
+				x.norm(); 
+				y.copy(y3); y.norm();
+//System.out.println("Out of dbl");
+			}
+			else
+			{
+				FP t0=new FP(x);
+				FP t1=new FP(y);
+				FP t2=new FP(z);
+				FP t3=new FP(x);
+				FP z3=new FP(z);
+				FP y3=new FP(0);
+				FP x3=new FP(0);
+				FP b=new FP(0);
+
+				if (ROM.CURVE_B_I==0)
+					b.copy(new FP(new BIG(ROM.CURVE_B)));
+
+				t0.sqr();  //1    x^2
+				t1.sqr();  //2    y^2
+				t2.sqr();  //3
+
+				t3.mul(y); //4
+				t3.add(t3); t3.norm();//5
+				z3.mul(x);   //6
+				z3.add(z3);  z3.norm();//7
+				y3.copy(t2); 
+				
+				if (ROM.CURVE_B_I==0)
+					y3.mul(b); //8
+				else
+					y3.imul(ROM.CURVE_B_I);
+				
+				y3.sub(z3); //y3.norm(); //9  ***
+				x3.copy(y3); x3.add(y3); x3.norm();//10
+
+				y3.add(x3); //y3.norm();//11
+				x3.copy(t1); x3.sub(y3); x3.norm();//12
+				y3.add(t1); y3.norm();//13
+				y3.mul(x3); //14
+				x3.mul(t3); //15
+				t3.copy(t2); t3.add(t2); //t3.norm(); //16
+				t2.add(t3); //t2.norm(); //17
+
+				if (ROM.CURVE_B_I==0)
+					z3.mul(b); //18
+				else
+					z3.imul(ROM.CURVE_B_I);
+
+				z3.sub(t2); //z3.norm();//19
+				z3.sub(t0); z3.norm();//20  ***
+				t3.copy(z3); t3.add(z3); //t3.norm();//21
+
+				z3.add(t3); z3.norm(); //22
+				t3.copy(t0); t3.add(t0); //t3.norm(); //23
+				t0.add(t3); //t0.norm();//24
+				t0.sub(t2); t0.norm();//25
+
+				t0.mul(z3);//26
+				y3.add(t0); //y3.norm();//27
+				t0.copy(y); t0.mul(z);//28
+				t0.add(t0); t0.norm(); //29
+				z3.mul(t0);//30
+				x3.sub(z3); //x3.norm();//31
+				t0.add(t0); t0.norm();//32
+				t1.add(t1); t1.norm();//33
+				z3.copy(t0); z3.mul(t1);//34
+
+				x.copy(x3); x.norm(); 
+				y.copy(y3); y.norm();
+				z.copy(z3); z.norm();
+			}
+		}
+		if (CURVETYPE==EDWARDS)
+		{
+//System.out.println("Into dbl");
+			FP C=new FP(x);
+			FP D=new FP(y);
+			FP H=new FP(z);
+			FP J=new FP(0);
+
+			x.mul(y); x.add(x); x.norm();
+			C.sqr();
+			D.sqr();
+
+			if (ROM.CURVE_A==-1) C.neg();	
+
+			y.copy(C); y.add(D); y.norm();
+			H.sqr(); H.add(H);
+
+			z.copy(y);
+			J.copy(y); 
+
+			J.sub(H); J.norm();
+			x.mul(J);
+
+			C.sub(D); C.norm();
+			y.mul(C);
+			z.mul(J);
+//System.out.println("Out of dbl");
+		}
+		if (CURVETYPE==MONTGOMERY)
+		{
+			FP A=new FP(x);
+			FP B=new FP(x);		
+			FP AA=new FP(0);
+			FP BB=new FP(0);
+			FP C=new FP(0);
+
+			A.add(z); A.norm();
+			AA.copy(A); AA.sqr();
+			B.sub(z); B.norm();
+			BB.copy(B); BB.sqr();
+			C.copy(AA); C.sub(BB); C.norm();
+			x.copy(AA); x.mul(BB);
+
+			A.copy(C); A.imul((ROM.CURVE_A+2)/4);
+
+			BB.add(A); BB.norm();
+			z.copy(BB); z.mul(C);
+		}
+		return;
+	}
+
+/* this+=Q */
+	public void add(ECP Q) {
+//		if (INF)
+//		{
+//			copy(Q);
+//			return;
+//		}
+//		if (Q.INF) return;
+
+		if (CURVETYPE==WEIERSTRASS)
+		{
+
+
+			if (ROM.CURVE_A==0)
+			{
+// Edits made
+//System.out.println("Into add");
+				int b=3*ROM.CURVE_B_I;
+				FP t0=new FP(x);
+				t0.mul(Q.x);
+				FP t1=new FP(y);
+				t1.mul(Q.y);
+				FP t2=new FP(z);
+				t2.mul(Q.z);
+				FP t3=new FP(x);
+				t3.add(y); t3.norm();
+				FP t4=new FP(Q.x);
+				t4.add(Q.y); t4.norm();
+				t3.mul(t4);
+				t4.copy(t0); t4.add(t1);
+
+				t3.sub(t4); t3.norm();
+				t4.copy(y);
+				t4.add(z); t4.norm();
+				FP x3=new FP(Q.y);
+				x3.add(Q.z); x3.norm();
+
+				t4.mul(x3);
+				x3.copy(t1);
+				x3.add(t2);
+	
+				t4.sub(x3); t4.norm();
+				x3.copy(x); x3.add(z); x3.norm();
+				FP y3=new FP(Q.x);
+				y3.add(Q.z); y3.norm();
+				x3.mul(y3);
+				y3.copy(t0);
+				y3.add(t2);
+				y3.rsub(x3); y3.norm();
+				x3.copy(t0); x3.add(t0); 
+				t0.add(x3); t0.norm();
+				t2.imul(b);
+
+				FP z3=new FP(t1); z3.add(t2); z3.norm();
+				t1.sub(t2); t1.norm(); 
+				y3.imul(b);
+	
+				x3.copy(y3); x3.mul(t4); t2.copy(t3); t2.mul(t1); x3.rsub(t2);
+				y3.mul(t0); t1.mul(z3); y3.add(t1);
+				t0.mul(t3); z3.mul(t4); z3.add(t0);
+
+				x.copy(x3); x.norm(); 
+				y.copy(y3); y.norm();
+				z.copy(z3); z.norm();
+//System.out.println("Out of add");
+			}
+			else
+			{
+				FP t0=new FP(x);
+				FP t1=new FP(y);
+				FP t2=new FP(z);
+				FP t3=new FP(x);
+				FP t4=new FP(Q.x);
+				FP z3=new FP(0);
+				FP y3=new FP(Q.x);
+				FP x3=new FP(Q.y);
+				FP b=new FP(0);
+
+				if (ROM.CURVE_B_I==0)
+					b.copy(new FP(new BIG(ROM.CURVE_B)));
+
+				t0.mul(Q.x); //1
+				t1.mul(Q.y); //2
+				t2.mul(Q.z); //3
+
+				t3.add(y); t3.norm(); //4
+				t4.add(Q.y); t4.norm();//5
+				t3.mul(t4);//6
+				t4.copy(t0); t4.add(t1); //t4.norm(); //7
+				t3.sub(t4); t3.norm(); //8
+				t4.copy(y); t4.add(z); t4.norm();//9
+				x3.add(Q.z); x3.norm();//10
+				t4.mul(x3); //11
+				x3.copy(t1); x3.add(t2); //x3.norm();//12
+
+				t4.sub(x3); t4.norm();//13
+				x3.copy(x); x3.add(z); x3.norm(); //14
+				y3.add(Q.z); y3.norm();//15
+
+				x3.mul(y3); //16
+				y3.copy(t0); y3.add(t2); //y3.norm();//17
+
+				y3.rsub(x3); y3.norm(); //18
+				z3.copy(t2); 
+				
+
+				if (ROM.CURVE_B_I==0)
+					z3.mul(b); //18
+				else
+					z3.imul(ROM.CURVE_B_I);
+				
+				x3.copy(y3); x3.sub(z3); x3.norm(); //20
+				z3.copy(x3); z3.add(x3); //z3.norm(); //21
+
+				x3.add(z3); //x3.norm(); //22
+				z3.copy(t1); z3.sub(x3); z3.norm(); //23
+				x3.add(t1); x3.norm(); //24
+
+				if (ROM.CURVE_B_I==0)
+					y3.mul(b); //18
+				else
+					y3.imul(ROM.CURVE_B_I);
+
+				t1.copy(t2); t1.add(t2); //t1.norm();//26
+				t2.add(t1); //t2.norm();//27
+
+				y3.sub(t2); //y3.norm(); //28
+
+				y3.sub(t0); y3.norm(); //29
+				t1.copy(y3); t1.add(y3); //t1.norm();//30
+				y3.add(t1); y3.norm(); //31
+
+				t1.copy(t0); t1.add(t0); //t1.norm(); //32
+				t0.add(t1); //t0.norm();//33
+				t0.sub(t2); t0.norm();//34
+				t1.copy(t4); t1.mul(y3);//35
+				t2.copy(t0); t2.mul(y3);//36
+				y3.copy(x3); y3.mul(z3);//37
+				y3.add(t2); //y3.norm();//38
+				x3.mul(t3);//39
+				x3.sub(t1);//40
+				z3.mul(t4);//41
+				t1.copy(t3); t1.mul(t0);//42
+				z3.add(t1); 
+				x.copy(x3); x.norm(); 
+				y.copy(y3); y.norm();
+				z.copy(z3); z.norm();
+			}
+		}
+		if (CURVETYPE==EDWARDS)
+		{
+//System.out.println("Into add");
+			FP A=new FP(z);
+			FP B=new FP(0);
+			FP C=new FP(x);
+			FP D=new FP(y);
+			FP E=new FP(0);
+			FP F=new FP(0);
+			FP G=new FP(0);
+
+			A.mul(Q.z);   
+			B.copy(A); B.sqr();    
+			C.mul(Q.x);      
+			D.mul(Q.y); 
+
+			E.copy(C); E.mul(D);  
+		
+			if (ROM.CURVE_B_I==0)
+			{
+				FP b=new FP(new BIG(ROM.CURVE_B));
+				E.mul(b);
+			}
+			else
+				E.imul(ROM.CURVE_B_I); 
+
+			F.copy(B); F.sub(E);      
+			G.copy(B); G.add(E);       
+
+			if (ROM.CURVE_A==1)
+			{
+				E.copy(D); E.sub(C);
+			}
+			C.add(D); 
+
+			B.copy(x); B.add(y);    
+			D.copy(Q.x); D.add(Q.y); B.norm(); D.norm(); 
+			B.mul(D);                   
+			B.sub(C); B.norm(); F.norm(); 
+			B.mul(F);                     
+			x.copy(A); x.mul(B); G.norm();  
+			if (ROM.CURVE_A==1)
+			{
+				E.norm(); C.copy(E); C.mul(G);  
+			}
+			if (ROM.CURVE_A==-1)
+			{
+				C.norm(); C.mul(G);
+			}
+			y.copy(A); y.mul(C);     
+
+			z.copy(F);	
+			z.mul(G);
+//System.out.println("Out of add");
+		}
+		return;
+	}
+
+/* Differential Add for Montgomery curves. this+=Q where W is this-Q and is affine. */
+	public void dadd(ECP Q,ECP W) {
+		FP A=new FP(x);
+		FP B=new FP(x);
+		FP C=new FP(Q.x);
+		FP D=new FP(Q.x);
+		FP DA=new FP(0);
+		FP CB=new FP(0);	
+			
+		A.add(z); 
+		B.sub(z); 
+
+		C.add(Q.z);
+		D.sub(Q.z);
+		A.norm();
+
+		D.norm();
+		DA.copy(D); DA.mul(A);
+
+		C.norm();
+		B.norm();
+		CB.copy(C); CB.mul(B);
+
+		A.copy(DA); A.add(CB); 
+		A.norm(); A.sqr();
+		B.copy(DA); B.sub(CB); 
+		B.norm(); B.sqr();
+
+		x.copy(A);
+		z.copy(W.x); z.mul(B);
+	}
+/* this-=Q */
+	public void sub(ECP Q) {
+		ECP NQ=new ECP(Q);
+		NQ.neg();
+		add(NQ);
+	}
+
+/* constant time multiply by small integer of length bts - use ladder */
+	public ECP pinmul(int e,int bts) {	
+		if (CURVETYPE==MONTGOMERY)
+			return this.mul(new BIG(e));
+		else
+		{
+			int nb,i,b;
+			ECP P=new ECP();
+			ECP R0=new ECP();
+			ECP R1=new ECP(); R1.copy(this);
+
+			for (i=bts-1;i>=0;i--)
+			{
+				b=(e>>i)&1;
+				P.copy(R1);
+				P.add(R0);
+				R0.cswap(R1,b);
+				R1.copy(P);
+				R0.dbl();
+				R0.cswap(R1,b);
+			}
+			P.copy(R0);
+			P.affine();
+			return P;
+		}
+	}
+
+/* return e.this */
+
+	public ECP mul(BIG e) {
+		if (e.iszilch() || is_infinity()) return new ECP();
+		ECP P=new ECP();
+		if (CURVETYPE==MONTGOMERY)
+		{
+/* use Ladder */
+			int nb,i,b;
+			ECP D=new ECP();
+			ECP R0=new ECP(); R0.copy(this);
+			ECP R1=new ECP(); R1.copy(this);
+			R1.dbl();
+
+			D.copy(this); D.affine();
+			nb=e.nbits();
+			for (i=nb-2;i>=0;i--)
+			{
+				b=e.bit(i);
+				P.copy(R1);
+
+				P.dadd(R0,D);
+				R0.cswap(R1,b);
+				R1.copy(P);
+				R0.dbl();
+				R0.cswap(R1,b);
+
+			}
+
+			P.copy(R0);
+		}
+		else
+		{
+// fixed size windows 
+			int i,b,nb,m,s,ns;
+			BIG mt=new BIG();
+			BIG t=new BIG();
+			ECP Q=new ECP();
+			ECP C=new ECP();
+			ECP[] W=new ECP[8];
+			byte[] w=new byte[1+(BIG.NLEN*BIG.BASEBITS+3)/4];
+
+			//affine();
+
+// precompute table 
+			Q.copy(this);
+
+			Q.dbl();
+			W[0]=new ECP();
+			W[0].copy(this);
+
+			for (i=1;i<8;i++)
+			{
+				W[i]=new ECP();
+				W[i].copy(W[i-1]);
+				W[i].add(Q);
+			}
+
+// make exponent odd - add 2P if even, P if odd 
+			t.copy(e);
+			s=t.parity();
+			t.inc(1); t.norm(); ns=t.parity(); mt.copy(t); mt.inc(1); mt.norm();
+			t.cmove(mt,s);
+			Q.cmove(this,ns);
+			C.copy(Q);
+
+			nb=1+(t.nbits()+3)/4;
+
+// convert exponent to signed 4-bit window 
+			for (i=0;i<nb;i++)
+			{
+				w[i]=(byte)(t.lastbits(5)-16);
+				t.dec(w[i]); t.norm();
+				t.fshr(4);	
+			}
+			w[nb]=(byte)t.lastbits(5);
+	
+			P.copy(W[(w[nb]-1)/2]);  
+			for (i=nb-1;i>=0;i--)
+			{
+				Q.select(W,w[i]);
+				P.dbl();
+				P.dbl();
+				P.dbl();
+				P.dbl();
+				P.add(Q);
+			}
+			P.sub(C); /* apply correction */
+		}
+		P.affine();
+		return P;
+	}
+
+/* Return e.this+f.Q */
+
+	public ECP mul2(BIG e,ECP Q,BIG f) {
+		BIG te=new BIG();
+		BIG tf=new BIG();
+		BIG mt=new BIG();
+		ECP S=new ECP();
+		ECP T=new ECP();
+		ECP C=new ECP();
+		ECP[] W=new ECP[8];
+		byte[] w=new byte[1+(BIG.NLEN*BIG.BASEBITS+1)/2];		
+		int i,s,ns,nb;
+		byte a,b;
+
+		//affine();
+		//Q.affine();
+
+		te.copy(e);
+		tf.copy(f);
+
+// precompute table 
+		W[1]=new ECP(); W[1].copy(this); W[1].sub(Q);
+		W[2]=new ECP(); W[2].copy(this); W[2].add(Q);
+		S.copy(Q); S.dbl();
+		W[0]=new ECP(); W[0].copy(W[1]); W[0].sub(S);
+		W[3]=new ECP(); W[3].copy(W[2]); W[3].add(S);
+		T.copy(this); T.dbl();
+		W[5]=new ECP(); W[5].copy(W[1]); W[5].add(T);
+		W[6]=new ECP(); W[6].copy(W[2]); W[6].add(T);
+		W[4]=new ECP(); W[4].copy(W[5]); W[4].sub(S);
+		W[7]=new ECP(); W[7].copy(W[6]); W[7].add(S);
+
+// if multiplier is odd, add 2, else add 1 to multiplier, and add 2P or P to correction 
+
+		s=te.parity();
+		te.inc(1); te.norm(); ns=te.parity(); mt.copy(te); mt.inc(1); mt.norm();
+		te.cmove(mt,s);
+		T.cmove(this,ns);
+		C.copy(T);
+
+		s=tf.parity();
+		tf.inc(1); tf.norm(); ns=tf.parity(); mt.copy(tf); mt.inc(1); mt.norm();
+		tf.cmove(mt,s);
+		S.cmove(Q,ns);
+		C.add(S);
+
+		mt.copy(te); mt.add(tf); mt.norm();
+		nb=1+(mt.nbits()+1)/2;
+
+// convert exponent to signed 2-bit window 
+		for (i=0;i<nb;i++)
+		{
+			a=(byte)(te.lastbits(3)-4);
+			te.dec(a); te.norm(); 
+			te.fshr(2);
+			b=(byte)(tf.lastbits(3)-4);
+			tf.dec(b); tf.norm(); 
+			tf.fshr(2);
+			w[i]=(byte)(4*a+b);
+		}
+		w[nb]=(byte)(4*te.lastbits(3)+tf.lastbits(3));
+		S.copy(W[(w[nb]-1)/2]);  
+
+		for (i=nb-1;i>=0;i--)
+		{
+			T.select(W,w[i]);
+			S.dbl();
+			S.dbl();
+			S.add(T);
+		}
+		S.sub(C); /* apply correction */
+		S.affine();
+		return S;
+	}
+
+// multiply a point by the curves cofactor
+	public void cfp()
+	{
+		int cf=ROM.CURVE_Cof_I;
+		if (cf==1) return;
+		if (cf==4)
+		{
+			dbl(); dbl();
+			//affine();
+			return;
+		} 
+		if (cf==8)
+		{
+			dbl(); dbl(); dbl();
+			//affine();
+			return;
+		}
+		BIG c=new BIG(ROM.CURVE_Cof);
+		copy(mul(c));
+	}
+
+/* Map byte string to curve point */
+	public static ECP mapit(byte[] h)
+	{
+		BIG q=new BIG(ROM.Modulus);
+		BIG x=BIG.fromBytes(h);
+		x.mod(q);
+		ECP P;
+
+		while (true)
+		{
+			while (true)
+			{
+				if (CURVETYPE!=MONTGOMERY)
+					P=new ECP(x,0);
+				else
+					P=new ECP(x);	
+				x.inc(1); x.norm();
+				if (!P.is_infinity()) break;
+			}
+			P.cfp();
+			if (!P.is_infinity()) break;
+		}
+		return P;
+	}
+
+	public static ECP generator()
+	{
+		ECP G;
+		BIG gx,gy;
+		gx=new BIG(ROM.CURVE_Gx);
+
+		if (ECP.CURVETYPE!=ECP.MONTGOMERY)
+		{
+			gy=new BIG(ROM.CURVE_Gy);
+			G=new ECP(gx,gy);
+		}
+		else
+			G=new ECP(gx);
+		return G;
+	}
+
+/*
+	public static void main(String[] args) {
+
+		BIG Gx=new BIG(ROM.CURVE_Gx);
+		BIG Gy;
+		ECP P;
+		if (CURVETYPE!=MONTGOMERY) Gy=new BIG(ROM.CURVE_Gy);
+		BIG r=new BIG(ROM.CURVE_Order);
+
+		//r.dec(7);
+	
+		System.out.println("Gx= "+Gx.toString());		
+		if (CURVETYPE!=MONTGOMERY) System.out.println("Gy= "+Gy.toString());	
+
+		if (CURVETYPE!=MONTGOMERY) P=new ECP(Gx,Gy);
+		else  P=new ECP(Gx);
+
+		System.out.println("P= "+P.toString());		
+
+		ECP R=P.mul(r);
+		//for (int i=0;i<10000;i++)
+		//	R=P.mul(r);
+	
+		System.out.println("R= "+R.toString());
+    } */
+}
+
diff --git a/version3/java/ECP2.java b/version3/java/ECP2.java
new file mode 100644
index 0000000..f627489
--- /dev/null
+++ b/version3/java/ECP2.java
@@ -0,0 +1,798 @@
+/*
+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.
+*/
+
+/* AMCL Weierstrass elliptic curve functions over FP2 */
+
+package org.apache.milagro.amcl.XXX;
+
+public final class ECP2 {
+	private FP2 x;
+	private FP2 y;
+	private FP2 z;
+//	private boolean INF;
+
+/* Constructor - set this=O */
+	public ECP2() {
+//		INF=true;
+		x=new FP2(0);
+		y=new FP2(1);
+		z=new FP2(0);
+	}
+
+    public ECP2(ECP2 e) {
+        this.x = new FP2(e.x);
+        this.y = new FP2(e.y);
+        this.z = new FP2(e.z);
+    }
+
+/* Test this=O? */
+	public boolean is_infinity() {
+//		if (INF) return true;                    //******
+		return (x.iszilch() && z.iszilch());
+	}
+/* copy this=P */
+	public void copy(ECP2 P)
+	{
+		x.copy(P.x);
+		y.copy(P.y);
+		z.copy(P.z);
+//		INF=P.INF;
+	}
+/* set this=O */
+	public void inf() {
+//		INF=true;
+		x.zero();
+		y.one();
+		z.zero();
+	}
+
+/* Conditional move of Q to P dependant on d */
+	public void cmove(ECP2 Q,int d)
+	{
+		x.cmove(Q.x,d);
+		y.cmove(Q.y,d);
+		z.cmove(Q.z,d);
+
+	//	boolean bd;
+	//	if (d==0) bd=false;
+	//	else bd=true;
+	//	INF^=(INF^Q.INF)&bd;
+	}
+
+/* return 1 if b==c, no branching */
+	public static int teq(int b,int c)
+	{
+		int x=b^c;
+		x-=1;  // if x=0, x now -1
+		return ((x>>31)&1);
+	}
+
+/* Constant time select from pre-computed table */
+	public void select(ECP2 W[],int b)
+	{
+		ECP2 MP=new ECP2(); 
+		int m=b>>31;
+		int babs=(b^m)-m;
+
+		babs=(babs-1)/2;
+
+		cmove(W[0],teq(babs,0));  // conditional move
+		cmove(W[1],teq(babs,1));
+		cmove(W[2],teq(babs,2));
+		cmove(W[3],teq(babs,3));
+		cmove(W[4],teq(babs,4));
+		cmove(W[5],teq(babs,5));
+		cmove(W[6],teq(babs,6));
+		cmove(W[7],teq(babs,7));
+ 
+		MP.copy(this);
+		MP.neg();
+		cmove(MP,(int)(m&1));
+	}
+
+/* Test if P == Q */
+	public boolean equals(ECP2 Q) {
+//		if (is_infinity() && Q.is_infinity()) return true;
+//		if (is_infinity() || Q.is_infinity()) return false;
+
+
+		FP2 a=new FP2(x);                            // *****
+		FP2 b=new FP2(Q.x);
+		a.mul(Q.z); 
+		b.mul(z); 
+		if (!a.equals(b)) return false;
+
+		a.copy(y); a.mul(Q.z); 
+		b.copy(Q.y); b.mul(z); 
+		if (!a.equals(b)) return false;
+
+		return true;
+	}
+/* set this=-this */
+	public void neg() {
+//		if (is_infinity()) return;
+		y.norm();
+		y.neg(); y.norm();
+		return;
+	}
+/* set to Affine - (x,y,z) to (x,y) */
+	public void affine() {
+		if (is_infinity()) return;
+		FP2 one=new FP2(1);
+		if (z.equals(one))
+		{
+			x.reduce();
+			y.reduce();
+			return;
+		}
+		z.inverse();
+
+		x.mul(z); x.reduce();               // *****
+		y.mul(z); y.reduce();
+		z.copy(one);
+	}
+/* extract affine x as FP2 */
+	public FP2 getX()
+	{
+		ECP2 W=new ECP2(this);
+		W.affine();
+		return W.x;
+	}
+/* extract affine y as FP2 */
+	public FP2 getY()
+	{
+		ECP2 W=new ECP2(this);
+		W.affine();
+		return W.y;
+	}
+/* extract projective x */
+	public FP2 getx()
+	{
+		return x;
+	}
+/* extract projective y */
+	public FP2 gety()
+	{
+		return y;
+	}
+/* extract projective z */
+	public FP2 getz()
+	{
+		return z;
+	}
+/* convert to byte array */
+	public void toBytes(byte[] b)
+	{
+		byte[] t=new byte[BIG.MODBYTES];
+		ECP2 W=new ECP2(this);
+		W.affine();
+		W.x.getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++)
+			b[i]=t[i];
+		W.x.getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++)
+			b[i+BIG.MODBYTES]=t[i];
+
+		W.y.getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++)
+			b[i+2*BIG.MODBYTES]=t[i];
+		W.y.getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++)
+			b[i+3*BIG.MODBYTES]=t[i];
+	}
+/* convert from byte array to point */
+	public static ECP2 fromBytes(byte[] b)
+	{
+		byte[] t=new byte[BIG.MODBYTES];
+		BIG ra;
+		BIG rb;
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=b[i];
+		ra=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=b[i+BIG.MODBYTES];
+		rb=BIG.fromBytes(t);
+		FP2 rx=new FP2(ra,rb);
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=b[i+2*BIG.MODBYTES];
+		ra=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=b[i+3*BIG.MODBYTES];
+		rb=BIG.fromBytes(t);
+		FP2 ry=new FP2(ra,rb);
+
+		return new ECP2(rx,ry);
+	}
+/* convert this to hex string */
+	public String toString() {
+		ECP2 W=new ECP2(this);	
+		W.affine();
+		if (W.is_infinity()) return "infinity";
+		return "("+W.x.toString()+","+W.y.toString()+")";
+	}
+
+/* Calculate RHS of twisted curve equation x^3+B/i */
+	public static FP2 RHS(FP2 x) {
+		//x.norm();
+		FP2 r=new FP2(x);
+		r.sqr();
+		FP2 b=new FP2(new BIG(ROM.CURVE_B));
+
+		if (ECP.SEXTIC_TWIST==ECP.D_TYPE)
+		{
+			b.div_ip();
+		}
+		if (ECP.SEXTIC_TWIST==ECP.M_TYPE)
+		{
+			b.norm();
+			b.mul_ip();
+			b.norm();
+		}
+
+
+		r.mul(x);
+		r.add(b);
+
+		r.reduce();
+		return r;
+	}
+
+/* construct this from (x,y) - but set to O if not on curve */
+	public ECP2(FP2 ix,FP2 iy) {
+		x=new FP2(ix);
+		y=new FP2(iy);
+		z=new FP2(1);
+		x.norm();
+		FP2 rhs=RHS(x);
+		FP2 y2=new FP2(y);
+		y2.sqr();
+		if (!y2.equals(rhs)) inf();
+//		if (y2.equals(rhs)) INF=false;
+//		else {x.zero();INF=true;}
+	}
+
+/* construct this from x - but set to O if not on curve */
+	public ECP2(FP2 ix) {
+		x=new FP2(ix);
+		y=new FP2(1);
+		z=new FP2(1);
+		x.norm();
+		FP2 rhs=RHS(x);
+		if (rhs.sqrt()) 
+		{
+			y.copy(rhs);
+			//INF=false;
+		}
+		else {/*x.zero();INF=true;*/ inf();}
+	}
+
+/* this+=this */
+	public int dbl() {
+//		if (INF) return -1;      
+//System.out.println("Into dbl");
+		FP2 iy=new FP2(y);
+		if (ECP.SEXTIC_TWIST==ECP.D_TYPE)
+		{
+			iy.mul_ip(); iy.norm();
+		}
+		FP2 t0=new FP2(y);                  //***** Change 
+		t0.sqr();            
+		if (ECP.SEXTIC_TWIST==ECP.D_TYPE)
+		{		
+			t0.mul_ip();
+		}
+		FP2 t1=new FP2(iy);  
+		t1.mul(z);
+		FP2 t2=new FP2(z);
+		t2.sqr();
+
+		z.copy(t0);
+		z.add(t0); z.norm(); 
+		z.add(z); 
+		z.add(z); 
+		z.norm();  
+
+		t2.imul(3*ROM.CURVE_B_I); 
+		if (ECP.SEXTIC_TWIST==ECP.M_TYPE)
+		{
+			t2.mul_ip();
+			t2.norm();
+		}
+
+		FP2 x3=new FP2(t2);
+		x3.mul(z); 
+
+		FP2 y3=new FP2(t0);   
+
+		y3.add(t2); y3.norm();
+		z.mul(t1);
+		t1.copy(t2); t1.add(t2); t2.add(t1); t2.norm();  
+		t0.sub(t2); t0.norm();                           //y^2-9bz^2
+		y3.mul(t0); y3.add(x3);                          //(y^2+3z*2)(y^2-9z^2)+3b.z^2.8y^2
+		t1.copy(x); t1.mul(iy);						//
+		x.copy(t0); x.norm(); x.mul(t1); x.add(x);       //(y^2-9bz^2)xy2
+
+		x.norm(); 
+		y.copy(y3); y.norm();
+//System.out.println("Out of dbl");
+		return 1;
+	}
+
+/* this+=Q - return 0 for add, 1 for double, -1 for O */
+	public int add(ECP2 Q) {
+//		if (INF)
+//		{
+//			copy(Q);
+//			return -1;
+//		}
+//		if (Q.INF) return -1;
+//System.out.println("Into add");
+		int b=3*ROM.CURVE_B_I;
+		FP2 t0=new FP2(x);
+		t0.mul(Q.x);         // x.Q.x
+		FP2 t1=new FP2(y);
+		t1.mul(Q.y);		 // y.Q.y
+
+		FP2 t2=new FP2(z);
+		t2.mul(Q.z);
+		FP2 t3=new FP2(x);
+		t3.add(y); t3.norm();          //t3=X1+Y1
+		FP2 t4=new FP2(Q.x);            
+		t4.add(Q.y); t4.norm();			//t4=X2+Y2
+		t3.mul(t4);						//t3=(X1+Y1)(X2+Y2)
+		t4.copy(t0); t4.add(t1);		//t4=X1.X2+Y1.Y2
+
+		t3.sub(t4); t3.norm(); 
+		if (ECP.SEXTIC_TWIST==ECP.D_TYPE)
+		{		
+			t3.mul_ip();  t3.norm();         //t3=(X1+Y1)(X2+Y2)-(X1.X2+Y1.Y2) = X1.Y2+X2.Y1
+		}
+		t4.copy(y);                    
+		t4.add(z); t4.norm();			//t4=Y1+Z1
+		FP2 x3=new FP2(Q.y);
+		x3.add(Q.z); x3.norm();			//x3=Y2+Z2
+
+		t4.mul(x3);						//t4=(Y1+Z1)(Y2+Z2)
+		x3.copy(t1);					//
+		x3.add(t2);						//X3=Y1.Y2+Z1.Z2
+	
+		t4.sub(x3); t4.norm(); 
+		if (ECP.SEXTIC_TWIST==ECP.D_TYPE)
+		{	
+			t4.mul_ip(); t4.norm();          //t4=(Y1+Z1)(Y2+Z2) - (Y1.Y2+Z1.Z2) = Y1.Z2+Y2.Z1
+		}
+		x3.copy(x); x3.add(z); x3.norm();	// x3=X1+Z1
+		FP2 y3=new FP2(Q.x);				
+		y3.add(Q.z); y3.norm();				// y3=X2+Z2
+		x3.mul(y3);							// x3=(X1+Z1)(X2+Z2)
+		y3.copy(t0);
+		y3.add(t2);							// y3=X1.X2+Z1+Z2
+		y3.rsub(x3); y3.norm();				// y3=(X1+Z1)(X2+Z2) - (X1.X2+Z1.Z2) = X1.Z2+X2.Z1
+
+		if (ECP.SEXTIC_TWIST==ECP.D_TYPE)
+		{
+			t0.mul_ip(); t0.norm(); // x.Q.x
+			t1.mul_ip(); t1.norm(); // y.Q.y
+		}
+		x3.copy(t0); x3.add(t0); 
+		t0.add(x3); t0.norm();
+		t2.imul(b); 	
+		if (ECP.SEXTIC_TWIST==ECP.M_TYPE)
+		{
+			t2.mul_ip(); t2.norm();
+		}
+		FP2 z3=new FP2(t1); z3.add(t2); z3.norm();
+		t1.sub(t2); t1.norm(); 
+		y3.imul(b); 
+		if (ECP.SEXTIC_TWIST==ECP.M_TYPE)
+		{
+			y3.mul_ip(); 
+			y3.norm();
+		}
+		x3.copy(y3); x3.mul(t4); t2.copy(t3); t2.mul(t1); x3.rsub(t2);
+		y3.mul(t0); t1.mul(z3); y3.add(t1);
+		t0.mul(t3); z3.mul(t4); z3.add(t0);
+
+		x.copy(x3); x.norm(); 
+		y.copy(y3); y.norm();
+		z.copy(z3); z.norm();
+//System.out.println("Out of add");
+		return 0;
+	}
+
+/* set this-=Q */
+	public int sub(ECP2 Q) {
+		ECP2 NQ=new ECP2(Q);
+		NQ.neg();
+		int D=add(NQ);
+		//Q.neg();
+		//int D=add(Q);
+		//Q.neg();
+		return D;
+	}
+/* set this*=q, where q is Modulus, using Frobenius */
+	public void frob(FP2 X)
+	{
+//		if (INF) return;
+		FP2 X2=new FP2(X);
+
+		X2.sqr();
+		x.conj();
+		y.conj();
+		z.conj();
+		z.reduce();
+		x.mul(X2);
+
+		y.mul(X2);
+		y.mul(X);
+	}
+
+/* P*=e */
+	public ECP2 mul(BIG e)
+	{
+/* fixed size windows */
+		int i,b,nb,m,s,ns;
+		BIG mt=new BIG();
+		BIG t=new BIG();
+		ECP2 P=new ECP2();
+		ECP2 Q=new ECP2();
+		ECP2 C=new ECP2();
+		ECP2[] W=new ECP2[8];
+		byte[] w=new byte[1+(BIG.NLEN*BIG.BASEBITS+3)/4];
+
+		if (is_infinity()) return new ECP2();
+
+		//affine();
+
+/* precompute table */
+		Q.copy(this);
+		Q.dbl();
+		W[0]=new ECP2();
+		W[0].copy(this);
+
+		for (i=1;i<8;i++)
+		{
+			W[i]=new ECP2();
+			W[i].copy(W[i-1]);
+			W[i].add(Q);
+		}
+
+/* make exponent odd - add 2P if even, P if odd */
+		t.copy(e);
+		s=t.parity();
+		t.inc(1); t.norm(); ns=t.parity(); mt.copy(t); mt.inc(1); mt.norm();
+		t.cmove(mt,s);
+		Q.cmove(this,ns);
+		C.copy(Q);
+
+		nb=1+(t.nbits()+3)/4;
+/* convert exponent to signed 4-bit window */
+		for (i=0;i<nb;i++)
+		{
+			w[i]=(byte)(t.lastbits(5)-16);
+			t.dec(w[i]); t.norm();
+			t.fshr(4);	
+		}
+		w[nb]=(byte)t.lastbits(5);
+	
+		P.copy(W[(w[nb]-1)/2]);  
+		for (i=nb-1;i>=0;i--)
+		{
+			Q.select(W,w[i]);
+			P.dbl();
+			P.dbl();
+			P.dbl();
+			P.dbl();
+			P.add(Q);
+		}
+		P.sub(C);
+		P.affine();
+		return P;
+	}
+
+/* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3 */
+// Bos & Costello https://eprint.iacr.org/2013/458.pdf
+// Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
+// Side channel attack secure 
+
+	public static ECP2 mul4(ECP2[] Q,BIG[] u)
+	{
+		int i,j,nb,pb;
+		ECP2 W=new ECP2();
+		ECP2 P=new ECP2();
+		ECP2[] T=new ECP2[8];
+
+		BIG mt=new BIG();
+		BIG[] t=new BIG[4];
+
+		byte[] w=new byte[BIG.NLEN*BIG.BASEBITS+1];
+		byte[] s=new byte[BIG.NLEN*BIG.BASEBITS+1];
+
+		for (i=0;i<4;i++)
+		{
+			t[i]=new BIG(u[i]);
+			t[i].norm();
+			//Q[i].affine();
+		}
+
+        T[0] = new ECP2(); T[0].copy(Q[0]);  // Q[0]
+        T[1] = new ECP2(); T[1].copy(T[0]); T[1].add(Q[1]);  // Q[0]+Q[1]
+        T[2] = new ECP2(); T[2].copy(T[0]); T[2].add(Q[2]);  // Q[0]+Q[2]
+        T[3] = new ECP2(); T[3].copy(T[1]); T[3].add(Q[2]);  // Q[0]+Q[1]+Q[2]
+        T[4] = new ECP2(); T[4].copy(T[0]); T[4].add(Q[3]);  // Q[0]+Q[3]
+        T[5] = new ECP2(); T[5].copy(T[1]); T[5].add(Q[3]);  // Q[0]+Q[1]+Q[3]
+        T[6] = new ECP2(); T[6].copy(T[2]); T[6].add(Q[3]);  // Q[0]+Q[2]+Q[3]
+        T[7] = new ECP2(); T[7].copy(T[3]); T[7].add(Q[3]);  // Q[0]+Q[1]+Q[2]+Q[3]
+
+    // Make it odd
+        pb=1-t[0].parity();
+        t[0].inc(pb);
+        t[0].norm();
+
+    // Number of bits
+        mt.zero();
+        for (i=0;i<4;i++) {
+            mt.or(t[i]); 
+        }
+        nb=1+mt.nbits();
+
+    // Sign pivot 
+        s[nb-1]=1;
+        for (i=0;i<nb-1;i++) {
+            t[0].fshr(1);
+            s[i]=(byte)(2*t[0].parity()-1);
+        }
+
+    // Recoded exponent
+        for (i=0; i<nb; i++) {
+            w[i]=0;
+            int k=1;
+            for (j=1; j<4; j++) {
+                byte bt=(byte)(s[i]*t[j].parity());
+                t[j].fshr(1);
+                t[j].dec((int)(bt)>>1);
+                t[j].norm();
+                w[i]+=bt*(byte)k;
+                k*=2;
+            }
+        } 
+
+    // Main loop
+        P.select(T,(int)(2*w[nb-1]+1));  
+        for (i=nb-2;i>=0;i--) {
+            P.dbl();
+            W.select(T,(int)(2*w[i]+s[i]));
+            P.add(W);
+        }
+
+    // apply correction
+        W.copy(P);   
+        W.sub(Q[0]);
+        P.cmove(W,pb);   
+		P.affine();
+		return P;
+	}        
+
+
+/* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3 */
+/*
+	public static ECP2 mul4(ECP2[] Q,BIG[] u)
+	{
+		int i,j,nb;
+		int[] a=new int[4];
+		ECP2 T=new ECP2();
+		ECP2 C=new ECP2();
+		ECP2 P=new ECP2();
+		ECP2[] W=new ECP2[8];
+
+		BIG mt=new BIG();
+		BIG[] t=new BIG[4];
+
+		byte[] w=new byte[BIG.NLEN*BIG.BASEBITS+1];
+
+		for (i=0;i<4;i++)
+		{
+			t[i]=new BIG(u[i]);
+			Q[i].affine();
+		}
+
+// precompute table 
+
+		W[0]=new ECP2(); W[0].copy(Q[0]); W[0].sub(Q[1]);
+
+		W[1]=new ECP2(); W[1].copy(W[0]);
+		W[2]=new ECP2(); W[2].copy(W[0]);
+		W[3]=new ECP2(); W[3].copy(W[0]);
+		W[4]=new ECP2(); W[4].copy(Q[0]); W[4].add(Q[1]);
+		W[5]=new ECP2(); W[5].copy(W[4]);
+		W[6]=new ECP2(); W[6].copy(W[4]);
+		W[7]=new ECP2(); W[7].copy(W[4]);
+		T.copy(Q[2]); T.sub(Q[3]);
+		W[1].sub(T);
+		W[2].add(T);
+		W[5].sub(T);
+		W[6].add(T);
+		T.copy(Q[2]); T.add(Q[3]);
+		W[0].sub(T);
+		W[3].add(T);
+		W[4].sub(T);
+		W[7].add(T);
+
+// if multiplier is even add 1 to multiplier, and add P to correction 
+		mt.zero(); C.inf();
+		for (i=0;i<4;i++)
+		{
+			if (t[i].parity()==0)
+			{
+				t[i].inc(1); t[i].norm();
+				C.add(Q[i]);
+			}
+			mt.add(t[i]); mt.norm();
+		}
+
+		nb=1+mt.nbits();
+
+// convert exponent to signed 1-bit window 
+		for (j=0;j<nb;j++)
+		{
+			for (i=0;i<4;i++)
+			{
+				a[i]=(byte)(t[i].lastbits(2)-2);
+				t[i].dec(a[i]); t[i].norm(); 
+				t[i].fshr(1);
+			}
+			w[j]=(byte)(8*a[0]+4*a[1]+2*a[2]+a[3]);
+		}
+		w[nb]=(byte)(8*t[0].lastbits(2)+4*t[1].lastbits(2)+2*t[2].lastbits(2)+t[3].lastbits(2));
+
+		P.copy(W[(w[nb]-1)/2]);  
+		for (i=nb-1;i>=0;i--)
+		{
+			T.select(W,w[i]);
+			P.dbl();
+			P.add(T);
+		}
+		P.sub(C); // apply correction 
+
+		P.affine();
+		return P;
+	}
+*/
+
+/* needed for SOK */
+	public static ECP2 mapit(byte[] h)
+	{
+		BIG q=new BIG(ROM.Modulus);
+		BIG x=BIG.fromBytes(h);
+		BIG one=new BIG(1);
+		FP2 X;
+		ECP2 Q;
+		x.mod(q);
+		while (true)
+		{
+			X=new FP2(one,x);
+			Q=new ECP2(X);
+			if (!Q.is_infinity()) break;
+			x.inc(1); x.norm();
+		}
+
+		BIG Fra=new BIG(ROM.Fra);
+		BIG Frb=new BIG(ROM.Frb);
+		X=new FP2(Fra,Frb);
+
+		if (ECP.SEXTIC_TWIST==ECP.M_TYPE)
+		{
+			X.inverse();
+			X.norm();
+		}
+
+		x=new BIG(ROM.CURVE_Bnx);
+
+/* Fast Hashing to G2 - Fuentes-Castaneda, Knapp and Rodriguez-Henriquez */
+
+		if (ECP.CURVE_PAIRING_TYPE==ECP.BN)
+		{
+			ECP2 T,K;
+
+			T=new ECP2(); T.copy(Q);
+			T=T.mul(x); 
+			
+			if (ECP.SIGN_OF_X==ECP.NEGATIVEX)
+			{
+				T.neg();
+			}	
+			K=new ECP2(); K.copy(T);
+			K.dbl(); K.add(T); //K.affine();
+
+			K.frob(X);
+			Q.frob(X); Q.frob(X); Q.frob(X);
+			Q.add(T); Q.add(K);
+			T.frob(X); T.frob(X);
+			Q.add(T);
+
+		}
+
+/* Efficient hash maps to G2 on BLS curves - Budroni, Pintore */
+/* Q -> x2Q -xQ -Q +F(xQ -Q) +F(F(2Q)) */
+
+		if (ECP.CURVE_PAIRING_TYPE==ECP.BLS)
+		{
+		//	ECP2 xQ,x2Q;
+		//	xQ=new ECP2();
+		//	x2Q=new ECP2();
+
+			ECP2 xQ=Q.mul(x);
+			ECP2 x2Q=xQ.mul(x);
+
+			if (ECP.SIGN_OF_X==ECP.NEGATIVEX)
+			{
+				xQ.neg();
+			}	
+
+			x2Q.sub(xQ);
+			x2Q.sub(Q);
+
+			xQ.sub(Q);
+			xQ.frob(X);
+
+			Q.dbl();
+			Q.frob(X);
+			Q.frob(X);
+
+			Q.add(x2Q);
+			Q.add(xQ);
+		}
+		Q.affine();
+		return Q;
+	}
+
+	public static ECP2 generator()
+	{
+		return new ECP2(new FP2(new BIG(ROM.CURVE_Pxa),new BIG(ROM.CURVE_Pxb)),new FP2(new BIG(ROM.CURVE_Pya),new BIG(ROM.CURVE_Pyb)));
+	}
+
+/*
+	public static void main(String[] args) {
+		BIG r=new BIG(ROM.Modulus);
+
+		BIG Pxa=new BIG(ROM.CURVE_Pxa);
+		BIG Pxb=new BIG(ROM.CURVE_Pxb);
+		BIG Pya=new BIG(ROM.CURVE_Pya);
+		BIG Pyb=new BIG(ROM.CURVE_Pyb);
+
+		BIG Fra=new BIG(ROM.CURVE_Fra);
+		BIG Frb=new BIG(ROM.CURVE_Frb);
+
+		FP2 f=new FP2(Fra,Frb);
+
+		FP2 Px=new FP2(Pxa,Pxb);
+		FP2 Py=new FP2(Pya,Pyb);
+
+		ECP2 P=new ECP2(Px,Py);
+
+		System.out.println("P= "+P.toString());
+
+		P=P.mul(r);
+		System.out.println("P= "+P.toString());
+
+		ECP2 Q=new ECP2(Px,Py);
+		Q.frob(f);
+		System.out.println("Q= "+Q.toString());
+	} */
+
+
+}
\ No newline at end of file
diff --git a/version3/java/ECP4.java b/version3/java/ECP4.java
new file mode 100644
index 0000000..d37d0a8
--- /dev/null
+++ b/version3/java/ECP4.java
@@ -0,0 +1,770 @@
+/*
+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.
+*/
+
+/* AMCL Weierstrass elliptic curve functions over FP4 */
+
+package org.apache.milagro.amcl.XXX;
+
+public final class ECP4 {
+	private FP4 x;
+	private FP4 y;
+	private FP4 z;
+//	private boolean INF;
+
+/* Constructor - set this=O */
+	public ECP4() {
+//		INF=true;
+		x=new FP4(0);
+		y=new FP4(1);
+		z=new FP4(0);
+	}
+
+    public ECP4(ECP4 e) {
+        this.x = new FP4(e.x);
+        this.y = new FP4(e.y);
+        this.z = new FP4(e.z);
+    }
+
+/* Test this=O? */
+	public boolean is_infinity() {
+//		if (INF) return true;                    //******
+		return (x.iszilch() && z.iszilch());
+	}
+/* copy this=P */
+	public void copy(ECP4 P)
+	{
+		x.copy(P.x);
+		y.copy(P.y);
+		z.copy(P.z);
+//		INF=P.INF;
+	}
+/* set this=O */
+	public void inf() {
+//		INF=true;
+		x.zero();
+		y.one();
+		z.zero();
+	}
+
+/* Conditional move of Q to P dependant on d */
+	public void cmove(ECP4 Q,int d)
+	{
+		x.cmove(Q.x,d);
+		y.cmove(Q.y,d);
+		z.cmove(Q.z,d);
+
+//		boolean bd;
+//		if (d==0) bd=false;
+//		else bd=true;
+//		INF^=(INF^Q.INF)&bd;
+	}
+
+/* return 1 if b==c, no branching */
+	public static int teq(int b,int c)
+	{
+		int x=b^c;
+		x-=1;  // if x=0, x now -1
+		return ((x>>31)&1);
+	}
+
+/* Constant time select from pre-computed table */
+	public void select(ECP4 W[],int b)
+	{
+		ECP4 MP=new ECP4(); 
+		int m=b>>31;
+		int babs=(b^m)-m;
+
+		babs=(babs-1)/2;
+
+		cmove(W[0],teq(babs,0));  // conditional move
+		cmove(W[1],teq(babs,1));
+		cmove(W[2],teq(babs,2));
+		cmove(W[3],teq(babs,3));
+		cmove(W[4],teq(babs,4));
+		cmove(W[5],teq(babs,5));
+		cmove(W[6],teq(babs,6));
+		cmove(W[7],teq(babs,7));
+ 
+		MP.copy(this);
+		MP.neg();
+		cmove(MP,(int)(m&1));
+	}
+
+/* Test if P == Q */
+	public boolean equals(ECP4 Q) {
+//		if (is_infinity() && Q.is_infinity()) return true;
+//		if (is_infinity() || Q.is_infinity()) return false;
+
+
+		FP4 a=new FP4(x);                            // *****
+		FP4 b=new FP4(Q.x);
+		a.mul(Q.z); 
+		b.mul(z); 
+		if (!a.equals(b)) return false;
+
+		a.copy(y); a.mul(Q.z); 
+		b.copy(Q.y); b.mul(z); 
+		if (!a.equals(b)) return false;
+
+		return true;
+	}
+/* set this=-this */
+	public void neg() {
+//		if (is_infinity()) return;
+		y.norm();
+		y.neg(); y.norm();
+		return;
+	}
+/* set to Affine - (x,y,z) to (x,y) */
+	public void affine() {
+		if (is_infinity()) return;
+		FP4 one=new FP4(1);
+		if (z.equals(one))
+		{
+			x.reduce();
+			y.reduce();
+			return;
+		}
+		z.inverse();
+
+		x.mul(z); x.reduce();               // *****
+		y.mul(z); y.reduce();
+		z.copy(one);
+	}
+
+/* extract affine x as FP4 */
+	public FP4 getX()
+	{
+		ECP4 W= new ECP4(this);
+		W.affine();
+		return W.x;
+	}
+/* extract affine y as FP4 */
+	public FP4 getY()
+	{
+		ECP4 W= new ECP4(this);
+		W.affine();
+		return W.y;
+	}
+/* extract projective x */
+	public FP4 getx()
+	{
+		return x;
+	}
+/* extract projective y */
+	public FP4 gety()
+	{
+		return y;
+	}
+/* extract projective z */
+	public FP4 getz()
+	{
+		return z;
+	}
+
+/* convert to byte array */
+	public void toBytes(byte[] b)
+	{
+		byte[] t=new byte[BIG.MODBYTES];
+		ECP4 W=new ECP4(this);
+		//affine();
+		int MB=BIG.MODBYTES;
+
+		W.x.geta().getA().toBytes(t);
+		for (int i=0;i<MB;i++) 
+			b[i]=t[i];
+		W.x.geta().getB().toBytes(t);
+		for (int i=0;i<MB;i++) 
+			b[i+MB]=t[i];
+		W.x.getb().getA().toBytes(t);
+		for (int i=0;i<MB;i++) 
+			b[i+2*MB]=t[i];
+		W.x.getb().getB().toBytes(t);
+		for (int i=0;i<MB;i++) 
+			b[i+3*MB]=t[i];
+
+		W.y.geta().getA().toBytes(t);
+		for (int i=0;i<MB;i++) 
+			b[i+4*MB]=t[i];
+		W.y.geta().getB().toBytes(t);
+		for (int i=0;i<MB;i++) 
+			b[i+5*MB]=t[i];
+		W.y.getb().getA().toBytes(t);
+		for (int i=0;i<MB;i++) 
+			b[i+6*MB]=t[i];
+		W.y.getb().getB().toBytes(t);
+		for (int i=0;i<MB;i++) 
+			b[i+7*MB]=t[i];
+
+	
+	}
+
+/* convert from byte array to point */
+	public static ECP4 fromBytes(byte[] b)
+	{
+		byte[] t=new byte[BIG.MODBYTES];
+		BIG ra;
+		BIG rb;
+		int MB=BIG.MODBYTES;
+
+		for (int i=0;i<MB;i++) {t[i]=b[i];}
+		ra=BIG.fromBytes(t);
+		for (int i=0;i<MB;i++) {t[i]=b[i+MB];}
+		rb=BIG.fromBytes(t);
+
+		FP2 ra4=new FP2(ra,rb);
+
+		for (int i=0;i<MB;i++) {t[i]=b[i+2*MB];}
+		ra=BIG.fromBytes(t);
+		for (int i=0;i<MB;i++) {t[i]=b[i+3*MB];}
+		rb=BIG.fromBytes(t);
+
+		FP2 rb4=new FP2(ra,rb);
+
+		FP4 rx=new FP4(ra4,rb4);
+
+		for (int i=0;i<MB;i++) {t[i]=b[i+4*MB];}
+		ra=BIG.fromBytes(t);
+		for (int i=0;i<MB;i++) {t[i]=b[i+5*MB];}
+		rb=BIG.fromBytes(t);
+
+		ra4=new FP2(ra,rb);
+
+		for (int i=0;i<MB;i++) {t[i]=b[i+6*MB];}
+		ra=BIG.fromBytes(t);
+		for (int i=0;i<MB;i++) {t[i]=b[i+7*MB];}
+		rb=BIG.fromBytes(t);
+
+		rb4=new FP2(ra,rb);
+		FP4 ry=new FP4(ra4,rb4);
+
+
+		return new ECP4(rx,ry);
+	}
+
+/* convert this to hex string */
+	public String toString() {
+		ECP4 W=new ECP4(this);	
+		W.affine();
+		if (W.is_infinity()) return "infinity";
+		return "("+W.x.toString()+","+W.y.toString()+")";
+	}
+
+/* Calculate RHS of twisted curve equation x^3+B/i */
+	public static FP4 RHS(FP4 x) {
+		//x.norm();
+		FP4 r=new FP4(x);
+		r.sqr();
+		FP4 b=new FP4(new FP2(new BIG(ROM.CURVE_B)));
+
+		if (ECP.SEXTIC_TWIST==ECP.D_TYPE)
+		{
+			b.div_i();
+		}
+		if (ECP.SEXTIC_TWIST==ECP.M_TYPE)
+		{
+			b.times_i();
+		}
+
+
+		r.mul(x);
+		r.add(b);
+
+		r.reduce();
+		return r;
+	}
+
+/* construct this from (x,y) - but set to O if not on curve */
+	public ECP4(FP4 ix,FP4 iy) {
+		x=new FP4(ix);
+		y=new FP4(iy);
+		z=new FP4(1);
+		x.norm();
+		FP4 rhs=RHS(x);
+		FP4 y2=new FP4(y);
+		y2.sqr();
+		if (!y2.equals(rhs)) inf();
+		//if (y2.equals(rhs)) INF=false;
+		//else {x.zero();INF=true;}
+	}
+
+/* construct this from x - but set to O if not on curve */
+	public ECP4(FP4 ix) {
+		x=new FP4(ix);
+		y=new FP4(1);
+		z=new FP4(1);
+		x.norm();
+		FP4 rhs=RHS(x);
+		if (rhs.sqrt()) 
+		{
+			y.copy(rhs);
+			//INF=false;
+		}
+		else {inf(); /*x.zero();INF=true;*/}
+	}
+
+/* this+=this */
+	public int dbl() {
+//		if (INF) return -1;      
+
+		FP4 iy=new FP4(y);
+		if (ECP.SEXTIC_TWIST==ECP.D_TYPE)
+		{
+			iy.times_i(); //iy.norm();
+		}
+		FP4 t0=new FP4(y);                  //***** Change 
+		t0.sqr();            
+		if (ECP.SEXTIC_TWIST==ECP.D_TYPE)
+		{		
+			t0.times_i();
+		}
+		FP4 t1=new FP4(iy);  
+		t1.mul(z);
+		FP4 t2=new FP4(z);
+		t2.sqr();
+
+		z.copy(t0);
+		z.add(t0); z.norm(); 
+		z.add(z); 
+		z.add(z); 
+		z.norm();  
+
+		t2.imul(3*ROM.CURVE_B_I); 
+		if (ECP.SEXTIC_TWIST==ECP.M_TYPE)
+		{
+			t2.times_i();
+			//t2.norm();
+		}
+
+		FP4 x3=new FP4(t2);
+		x3.mul(z); 
+
+		FP4 y3=new FP4(t0);   
+
+		y3.add(t2); y3.norm();
+		z.mul(t1);
+		t1.copy(t2); t1.add(t2); t2.add(t1); t2.norm();  
+		t0.sub(t2); t0.norm();                           //y^2-9bz^2
+		y3.mul(t0); y3.add(x3);                          //(y^2+3z*2)(y^2-9z^2)+3b.z^2.8y^2
+		t1.copy(x); t1.mul(iy);						//
+		x.copy(t0); x.norm(); x.mul(t1); x.add(x);       //(y^2-9bz^2)xy2
+
+		x.norm(); 
+		y.copy(y3); y.norm();
+
+		return 1;
+	}
+
+/* this+=Q - return 0 for add, 1 for double, -1 for O */
+	public int add(ECP4 Q) {
+//		if (INF)
+//		{
+//			copy(Q);
+//			return -1;
+//		}
+//		if (Q.INF) return -1;
+
+		int b=3*ROM.CURVE_B_I;
+		FP4 t0=new FP4(x);
+		t0.mul(Q.x);         // x.Q.x
+		FP4 t1=new FP4(y);
+		t1.mul(Q.y);		 // y.Q.y
+
+		FP4 t2=new FP4(z);
+		t2.mul(Q.z);
+		FP4 t3=new FP4(x);
+		t3.add(y); t3.norm();          //t3=X1+Y1
+		FP4 t4=new FP4(Q.x);            
+		t4.add(Q.y); t4.norm();			//t4=X2+Y2
+		t3.mul(t4);						//t3=(X1+Y1)(X2+Y2)
+		t4.copy(t0); t4.add(t1);		//t4=X1.X2+Y1.Y2
+
+		t3.sub(t4); t3.norm(); 
+		if (ECP.SEXTIC_TWIST==ECP.D_TYPE)
+		{		
+			t3.times_i();  //t3.norm();         //t3=(X1+Y1)(X2+Y2)-(X1.X2+Y1.Y2) = X1.Y2+X2.Y1
+		}
+		t4.copy(y);                    
+		t4.add(z); t4.norm();			//t4=Y1+Z1
+		FP4 x3=new FP4(Q.y);
+		x3.add(Q.z); x3.norm();			//x3=Y2+Z2
+
+		t4.mul(x3);						//t4=(Y1+Z1)(Y2+Z2)
+		x3.copy(t1);					//
+		x3.add(t2);						//X3=Y1.Y2+Z1.Z2
+	
+		t4.sub(x3); t4.norm(); 
+		if (ECP.SEXTIC_TWIST==ECP.D_TYPE)
+		{	
+			t4.times_i(); //t4.norm();          //t4=(Y1+Z1)(Y2+Z2) - (Y1.Y2+Z1.Z2) = Y1.Z2+Y2.Z1
+		}
+		x3.copy(x); x3.add(z); x3.norm();	// x3=X1+Z1
+		FP4 y3=new FP4(Q.x);				
+		y3.add(Q.z); y3.norm();				// y3=X2+Z2
+		x3.mul(y3);							// x3=(X1+Z1)(X2+Z2)
+		y3.copy(t0);
+		y3.add(t2);							// y3=X1.X2+Z1+Z2
+		y3.rsub(x3); y3.norm();				// y3=(X1+Z1)(X2+Z2) - (X1.X2+Z1.Z2) = X1.Z2+X2.Z1
+
+		if (ECP.SEXTIC_TWIST==ECP.D_TYPE)
+		{
+			t0.times_i(); //t0.norm(); // x.Q.x
+			t1.times_i(); //t1.norm(); // y.Q.y
+		}
+		x3.copy(t0); x3.add(t0); 
+		t0.add(x3); t0.norm();
+		t2.imul(b); 	
+		if (ECP.SEXTIC_TWIST==ECP.M_TYPE)
+		{
+			t2.times_i();
+		}
+		FP4 z3=new FP4(t1); z3.add(t2); z3.norm();
+		t1.sub(t2); t1.norm(); 
+		y3.imul(b); 
+		if (ECP.SEXTIC_TWIST==ECP.M_TYPE)
+		{
+			y3.times_i(); 
+			//y3.norm();
+		}
+		x3.copy(y3); x3.mul(t4); t2.copy(t3); t2.mul(t1); x3.rsub(t2);
+		y3.mul(t0); t1.mul(z3); y3.add(t1);
+		t0.mul(t3); z3.mul(t4); z3.add(t0);
+
+		x.copy(x3); x.norm(); 
+		y.copy(y3); y.norm();
+		z.copy(z3); z.norm();
+
+		return 0;
+	}
+
+/* set this-=Q */
+	public int sub(ECP4 Q) {
+		ECP4 NQ=new ECP4(Q);
+		NQ.neg();
+		int D=add(NQ);
+
+		//Q.neg();
+		//int D=add(Q);
+		//Q.neg();
+		return D;
+	}
+
+	public static FP2[] frob_constants() {
+			BIG Fra=new BIG(ROM.Fra);
+			BIG Frb=new BIG(ROM.Frb);
+			FP2 X=new FP2(Fra,Frb);
+
+			FP2 F0=new FP2(X); F0.sqr();
+			FP2 F2=new FP2(F0);
+			F2.mul_ip(); F2.norm();
+			FP2 F1=new FP2(F2); F1.sqr();
+			F2.mul(F1);
+			F1.copy(X);
+			if (ECP.SEXTIC_TWIST == ECP.M_TYPE)
+			{
+				F1.mul_ip();
+				F1.inverse();
+				F0.copy(F1); F0.sqr();
+			}
+			F0.mul_ip(); F0.norm();
+			F1.mul(F0);
+			FP2[] F={F0,F1,F2};
+			return F;
+	}
+
+
+/* set this*=q, where q is Modulus, using Frobenius */
+	public void frob(FP2 F[],int n)
+	{
+//		if (INF) return;
+		for (int i=0;i<n;i++) {
+			x.frob(F[2]);
+			x.pmul(F[0]);
+		
+			y.frob(F[2]);
+			y.pmul(F[1]);
+			y.times_i();
+
+			z.frob(F[2]);
+		}
+	}
+
+/* P*=e */
+	public ECP4 mul(BIG e)
+	{
+/* fixed size windows */
+		int i,b,nb,m,s,ns;
+		BIG mt=new BIG();
+		BIG t=new BIG();
+		ECP4 P=new ECP4();
+		ECP4 Q=new ECP4();
+		ECP4 C=new ECP4();
+		ECP4[] W=new ECP4[8];
+		byte[] w=new byte[1+(BIG.NLEN*BIG.BASEBITS+3)/4];
+
+		if (is_infinity()) return new ECP4();
+
+		//affine();
+
+/* precompute table */
+		Q.copy(this);
+		Q.dbl();
+		W[0]=new ECP4();
+		W[0].copy(this);
+
+		for (i=1;i<8;i++)
+		{
+			W[i]=new ECP4();
+			W[i].copy(W[i-1]);
+			W[i].add(Q);
+		}
+
+/* make exponent odd - add 2P if even, P if odd */
+		t.copy(e);
+		s=t.parity();
+		t.inc(1); t.norm(); ns=t.parity(); mt.copy(t); mt.inc(1); mt.norm();
+		t.cmove(mt,s);
+		Q.cmove(this,ns);
+		C.copy(Q);
+
+		nb=1+(t.nbits()+3)/4;
+/* convert exponent to signed 4-bit window */
+		for (i=0;i<nb;i++)
+		{
+			w[i]=(byte)(t.lastbits(5)-16);
+			t.dec(w[i]); t.norm();
+			t.fshr(4);	
+		}
+		w[nb]=(byte)t.lastbits(5);
+	
+		P.copy(W[(w[nb]-1)/2]);  
+		for (i=nb-1;i>=0;i--)
+		{
+			Q.select(W,w[i]);
+			P.dbl();
+			P.dbl();
+			P.dbl();
+			P.dbl();
+			P.add(Q);
+		}
+		P.sub(C);
+		P.affine();
+		return P;
+	}
+
+/* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3... */
+// Bos & Costello https://eprint.iacr.org/2013/458.pdf
+// Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
+// Side channel attack secure 
+
+	public static ECP4 mul8(ECP4[] Q,BIG[] u)
+	{
+		int i,j,k,nb,pb1,pb2;
+		ECP4 W=new ECP4();
+		ECP4 P=new ECP4();
+		ECP4[] T1=new ECP4[8];
+		ECP4[] T2=new ECP4[8];
+
+
+		BIG mt=new BIG();
+		BIG[] t=new BIG[8];
+
+		byte[] w1=new byte[BIG.NLEN*BIG.BASEBITS+1];
+		byte[] s1=new byte[BIG.NLEN*BIG.BASEBITS+1];
+		byte[] w2=new byte[BIG.NLEN*BIG.BASEBITS+1];
+		byte[] s2=new byte[BIG.NLEN*BIG.BASEBITS+1];
+
+		for (i=0;i<8;i++)
+		{
+			t[i]=new BIG(u[i]);
+			//Q[i].affine();
+			t[i].norm();
+		}
+
+        T1[0] = new ECP4(); T1[0].copy(Q[0]);  // Q[0]
+        T1[1] = new ECP4(); T1[1].copy(T1[0]); T1[1].add(Q[1]);  // Q[0]+Q[1]
+        T1[2] = new ECP4(); T1[2].copy(T1[0]); T1[2].add(Q[2]);  // Q[0]+Q[2]
+        T1[3] = new ECP4(); T1[3].copy(T1[1]); T1[3].add(Q[2]);  // Q[0]+Q[1]+Q[2]
+        T1[4] = new ECP4(); T1[4].copy(T1[0]); T1[4].add(Q[3]);  // Q[0]+Q[3]
+        T1[5] = new ECP4(); T1[5].copy(T1[1]); T1[5].add(Q[3]);  // Q[0]+Q[1]+Q[3]
+        T1[6] = new ECP4(); T1[6].copy(T1[2]); T1[6].add(Q[3]);  // Q[0]+Q[2]+Q[3]
+        T1[7] = new ECP4(); T1[7].copy(T1[3]); T1[7].add(Q[3]);  // Q[0]+Q[1]+Q[2]+Q[3]
+
+//  Use Frobenius 
+		FP2[] F=ECP4.frob_constants();
+
+		for (i=0;i<8;i++) {
+			T2[i] = new ECP4(); T2[i].copy(T1[i]);
+			T2[i].frob(F,4);
+		}
+
+    // Make it odd
+        pb1=1-t[0].parity();
+        t[0].inc(pb1);
+        t[0].norm();
+
+        pb2=1-t[4].parity();
+        t[4].inc(pb2);
+        t[4].norm();
+
+
+    // Number of bits
+        mt.zero();
+        for (i=0;i<8;i++) {
+            mt.or(t[i]); 
+        }
+        nb=1+mt.nbits();
+
+    // Sign pivot 
+        s1[nb-1]=1;
+		s2[nb-1]=1;
+        for (i=0;i<nb-1;i++) {
+            t[0].fshr(1);
+            s1[i]=(byte)(2*t[0].parity()-1);
+            t[4].fshr(1);
+            s2[i]=(byte)(2*t[4].parity()-1);
+        }
+
+    // Recoded exponent
+        for (i=0; i<nb; i++) {
+            w1[i]=0;
+            k=1;
+            for (j=1; j<4; j++) {
+                byte bt=(byte)(s1[i]*t[j].parity());
+                t[j].fshr(1);
+                t[j].dec((int)(bt)>>1);
+                t[j].norm();
+                w1[i]+=bt*(byte)k;
+                k*=2;
+            }
+
+            w2[i]=0;
+            k=1;
+            for (j=5; j<8; j++) {
+                byte bt=(byte)(s2[i]*t[j].parity());
+                t[j].fshr(1);
+                t[j].dec((int)(bt)>>1);
+                t[j].norm();
+                w2[i]+=bt*(byte)k;
+                k*=2;
+            }
+        } 
+
+    // Main loop
+        P.select(T1,(int)(2*w1[nb-1]+1));  
+		W.select(T2,(int)(2*w2[nb-1]+1)); 
+		P.add(W);
+        for (i=nb-2;i>=0;i--) {
+            P.dbl();
+            W.select(T1,(int)(2*w1[i]+s1[i]));
+            P.add(W);
+            W.select(T2,(int)(2*w2[i]+s2[i]));
+            P.add(W);
+
+        }
+
+    // apply correction
+        W.copy(P);   
+        W.sub(Q[0]);
+        P.cmove(W,pb1);   
+
+        W.copy(P);   
+        W.sub(Q[4]);
+        P.cmove(W,pb2);  
+
+		P.affine();
+		return P;
+	}        
+
+/* needed for SOK */
+	public static ECP4 mapit(byte[] h)
+	{
+		BIG q=new BIG(ROM.Modulus);
+		BIG x=BIG.fromBytes(h);
+		BIG one=new BIG(1);
+		FP4 X;
+		FP2 X2;
+		ECP4 Q;
+		x.mod(q);
+		while (true)
+		{
+			X2=new FP2(one,x);
+			X=new FP4(X2);
+			Q=new ECP4(X);
+			if (!Q.is_infinity()) break;
+			x.inc(1); x.norm();
+		}
+
+		FP2[] F=ECP4.frob_constants();
+		x=new BIG(ROM.CURVE_Bnx);
+
+/* Efficient hash maps to G2 on BLS curves - Budroni, Pintore */
+
+		ECP4 xQ=Q.mul(x);
+		ECP4 x2Q=xQ.mul(x);
+		ECP4 x3Q=x2Q.mul(x);
+		ECP4 x4Q=x3Q.mul(x);
+
+		if (ECP.SIGN_OF_X==ECP.NEGATIVEX)
+		{
+			xQ.neg();
+			x3Q.neg();
+		}	
+
+		x4Q.sub(x3Q);
+		x4Q.sub(Q);
+
+		x3Q.sub(x2Q);
+		x3Q.frob(F,1);
+
+		x2Q.sub(xQ);
+		x2Q.frob(F,2);
+
+		xQ.sub(Q);
+		xQ.frob(F,3);
+
+		Q.dbl();
+		Q.frob(F,4);
+
+		Q.add(x4Q);
+		Q.add(x3Q);
+		Q.add(x2Q);
+		Q.add(xQ);
+
+		Q.affine();
+		return Q;
+	}
+
+	public static ECP4 generator()
+	{
+
+		return new ECP4(
+			new FP4(
+				new FP2(
+					new BIG(ROM.CURVE_Pxaa),new BIG(ROM.CURVE_Pxab)),
+				new FP2(
+					new BIG(ROM.CURVE_Pxba),new BIG(ROM.CURVE_Pxbb))),
+			new FP4(
+				new FP2(
+					new BIG(ROM.CURVE_Pyaa),new BIG(ROM.CURVE_Pyab)),
+				new FP2(
+					new BIG(ROM.CURVE_Pyba),new BIG(ROM.CURVE_Pybb))));
+	}
+
+}
diff --git a/version3/java/ECP8.java b/version3/java/ECP8.java
new file mode 100644
index 0000000..4d3b3dc
--- /dev/null
+++ b/version3/java/ECP8.java
@@ -0,0 +1,932 @@
+/*
+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.
+*/
+
+/* AMCL Weierstrass elliptic curve functions over FP8 */
+
+package org.apache.milagro.amcl.XXX;
+
+public final class ECP8 {
+	private FP8 x;
+	private FP8 y;
+	private FP8 z;
+//	private boolean INF;
+
+/* Constructor - set this=O */
+	public ECP8() {
+//		INF=true;
+		x=new FP8(0);
+		y=new FP8(1);
+		z=new FP8(0);
+	}
+
+    public ECP8(ECP8 e) {
+        this.x = new FP8(e.x);
+        this.y = new FP8(e.y);
+        this.z = new FP8(e.z);
+    }
+
+/* Test this=O? */
+	public boolean is_infinity() {
+//		if (INF) return true;                    //******
+		return (x.iszilch() && z.iszilch());
+	}
+/* copy this=P */
+	public void copy(ECP8 P)
+	{
+		x.copy(P.x);
+		y.copy(P.y);
+		z.copy(P.z);
+//		INF=P.INF;
+	}
+/* set this=O */
+	public void inf() {
+//		INF=true;
+		x.zero();
+		y.one();
+		z.zero();
+	}
+
+/* Conditional move of Q to P dependant on d */
+	public void cmove(ECP8 Q,int d)
+	{
+		x.cmove(Q.x,d);
+		y.cmove(Q.y,d);
+		z.cmove(Q.z,d);
+
+//		boolean bd;
+//		if (d==0) bd=false;
+//		else bd=true;
+//		INF^=(INF^Q.INF)&bd;
+	}
+
+/* return 1 if b==c, no branching */
+	public static int teq(int b,int c)
+	{
+		int x=b^c;
+		x-=1;  // if x=0, x now -1
+		return ((x>>31)&1);
+	}
+
+/* Constant time select from pre-computed table */
+	public void select(ECP8 W[],int b)
+	{
+		ECP8 MP=new ECP8(); 
+		int m=b>>31;
+		int babs=(b^m)-m;
+
+		babs=(babs-1)/2;
+
+		cmove(W[0],teq(babs,0));  // conditional move
+		cmove(W[1],teq(babs,1));
+		cmove(W[2],teq(babs,2));
+		cmove(W[3],teq(babs,3));
+		cmove(W[4],teq(babs,4));
+		cmove(W[5],teq(babs,5));
+		cmove(W[6],teq(babs,6));
+		cmove(W[7],teq(babs,7));
+ 
+		MP.copy(this);
+		MP.neg();
+		cmove(MP,(int)(m&1));
+	}
+
+/* Test if P == Q */
+	public boolean equals(ECP8 Q) {
+//		if (is_infinity() && Q.is_infinity()) return true;
+//		if (is_infinity() || Q.is_infinity()) return false;
+
+
+		FP8 a=new FP8(x);                            // *****
+		FP8 b=new FP8(Q.x);
+		a.mul(Q.z); 
+		b.mul(z); 
+		if (!a.equals(b)) return false;
+
+		a.copy(y); a.mul(Q.z); 
+		b.copy(Q.y); b.mul(z); 
+		if (!a.equals(b)) return false;
+
+		return true;
+	}
+
+/* set this=-this */
+	public void neg() {
+//		if (is_infinity()) return;
+		y.norm();
+		y.neg(); y.norm();
+		return;
+	}
+/* set to Affine - (x,y,z) to (x,y) */
+	public void affine() {
+		if (is_infinity()) return;
+		FP8 one=new FP8(1);
+		if (z.equals(one))
+		{
+			x.reduce();
+			y.reduce();
+			return;
+		}
+		z.inverse();
+
+		x.mul(z); x.reduce();               // *****
+		y.mul(z); y.reduce();
+		z.copy(one);
+	}
+
+/* extract affine x as FP8 */
+	public FP8 getX()
+	{
+		ECP8 W= new ECP8(this);
+		W.affine();
+		return W.x;
+	}
+/* extract affine y as FP8 */
+	public FP8 getY()
+	{
+		ECP8 W= new ECP8(this);
+		W.affine();
+		return W.y;
+	}
+/* extract projective x */
+	public FP8 getx()
+	{
+		return x;
+	}
+/* extract projective y */
+	public FP8 gety()
+	{
+		return y;
+	}
+/* extract projective z */
+	public FP8 getz()
+	{
+		return z;
+	}
+
+/* convert to byte array */
+	public void toBytes(byte[] b)
+	{
+		byte[] t=new byte[BIG.MODBYTES];
+		ECP8 W=new ECP8(this);
+		W.affine();
+		int MB=BIG.MODBYTES;
+
+		W.x.geta().geta().getA().toBytes(t);
+		for (int i=0;i<MB;i++) { b[i]=t[i];}
+		W.x.geta().geta().getB().toBytes(t);
+		for (int i=0;i<MB;i++) { b[i+MB]=t[i];}
+		W.x.geta().getb().getA().toBytes(t);
+		for (int i=0;i<MB;i++) { b[i+2*MB]=t[i];}
+		W.x.geta().getb().getB().toBytes(t);
+		for (int i=0;i<MB;i++) { b[i+3*MB]=t[i];}
+
+		W.x.getb().geta().getA().toBytes(t);
+		for (int i=0;i<MB;i++) { b[i+4*MB]=t[i];}
+		W.x.getb().geta().getB().toBytes(t);
+		for (int i=0;i<MB;i++) { b[i+5*MB]=t[i];}
+		W.x.getb().getb().getA().toBytes(t);
+		for (int i=0;i<MB;i++) { b[i+6*MB]=t[i];}
+		W.x.getb().getb().getB().toBytes(t);
+		for (int i=0;i<MB;i++) { b[i+7*MB]=t[i];}
+
+
+		W.y.geta().geta().getA().toBytes(t);
+		for (int i=0;i<MB;i++) { b[i+8*MB]=t[i];}
+		W.y.geta().geta().getB().toBytes(t);
+		for (int i=0;i<MB;i++) { b[i+9*MB]=t[i];}
+		W.y.geta().getb().getA().toBytes(t);
+		for (int i=0;i<MB;i++) { b[i+10*MB]=t[i];}
+		W.y.geta().getb().getB().toBytes(t);
+		for (int i=0;i<MB;i++) { b[i+11*MB]=t[i];}
+	
+		W.y.getb().geta().getA().toBytes(t);
+		for (int i=0;i<MB;i++) { b[i+12*MB]=t[i];}
+		W.y.getb().geta().getB().toBytes(t);
+		for (int i=0;i<MB;i++) { b[i+13*MB]=t[i];}
+		W.y.getb().getb().getA().toBytes(t);
+		for (int i=0;i<MB;i++) { b[i+14*MB]=t[i];}
+		W.y.getb().getb().getB().toBytes(t);
+		for (int i=0;i<MB;i++) { b[i+15*MB]=t[i];}
+
+	}
+
+/* convert from byte array to point */
+	public static ECP8 fromBytes(byte[] b)
+	{
+		byte[] t=new byte[BIG.MODBYTES];
+		BIG ra;
+		BIG rb;
+		int MB=BIG.MODBYTES;
+
+		for (int i=0;i<MB;i++) {t[i]=b[i];}
+		ra=BIG.fromBytes(t);
+		for (int i=0;i<MB;i++) {t[i]=b[i+MB];}
+		rb=BIG.fromBytes(t);
+
+		FP2 ra4=new FP2(ra,rb);
+
+		for (int i=0;i<MB;i++) {t[i]=b[i+2*MB];}
+		ra=BIG.fromBytes(t);
+		for (int i=0;i<MB;i++) {t[i]=b[i+3*MB];}
+		rb=BIG.fromBytes(t);
+
+		FP2 rb4=new FP2(ra,rb);
+
+		FP4 ra8=new FP4(ra4,rb4);
+
+		for (int i=0;i<MB;i++) {t[i]=b[i+4*MB];}
+		ra=BIG.fromBytes(t);
+		for (int i=0;i<MB;i++) {t[i]=b[i+5*MB];}
+		rb=BIG.fromBytes(t);
+
+		ra4=new FP2(ra,rb);
+
+		for (int i=0;i<MB;i++) {t[i]=b[i+6*MB];}
+		ra=BIG.fromBytes(t);
+		for (int i=0;i<MB;i++) {t[i]=b[i+7*MB];}
+		rb=BIG.fromBytes(t);
+
+		rb4=new FP2(ra,rb);
+
+		FP4 rb8=new FP4(ra4,rb4);
+
+		FP8 rx=new FP8(ra8,rb8);
+
+
+
+		for (int i=0;i<MB;i++) {t[i]=b[i+8*MB];}
+		ra=BIG.fromBytes(t);
+		for (int i=0;i<MB;i++) {t[i]=b[i+9*MB];}
+		rb=BIG.fromBytes(t);
+
+		ra4=new FP2(ra,rb);
+
+		for (int i=0;i<MB;i++) {t[i]=b[i+10*MB];}
+		ra=BIG.fromBytes(t);
+		for (int i=0;i<MB;i++) {t[i]=b[i+11*MB];}
+		rb=BIG.fromBytes(t);
+
+		rb4=new FP2(ra,rb);
+
+		ra8=new FP4(ra4,rb4);
+
+		for (int i=0;i<MB;i++) {t[i]=b[i+12*MB];}
+		ra=BIG.fromBytes(t);
+		for (int i=0;i<MB;i++) {t[i]=b[i+13*MB];}
+		rb=BIG.fromBytes(t);
+
+		ra4=new FP2(ra,rb);
+
+		for (int i=0;i<MB;i++) {t[i]=b[i+14*MB];}
+		ra=BIG.fromBytes(t);
+		for (int i=0;i<MB;i++) {t[i]=b[i+15*MB];}
+		rb=BIG.fromBytes(t);
+
+		rb4=new FP2(ra,rb);
+
+		rb8=new FP4(ra4,rb4);
+
+		FP8 ry=new FP8(ra8,rb8);
+
+		return new ECP8(rx,ry);
+	}
+
+/* convert this to hex string */
+	public String toString() {
+		ECP8 W=new ECP8(this);		
+		W.affine();
+		if (W.is_infinity()) return "infinity";
+		return "("+W.x.toString()+","+W.y.toString()+")";
+	}
+
+/* Calculate RHS of twisted curve equation x^3+B/i */
+	public static FP8 RHS(FP8 x) {
+		//x.norm();
+		FP8 r=new FP8(x);
+		r.sqr();
+		FP8 b=new FP8(new FP4(new FP2(new BIG(ROM.CURVE_B))));
+
+		if (ECP.SEXTIC_TWIST==ECP.D_TYPE)
+		{
+			b.div_i();
+		}
+		if (ECP.SEXTIC_TWIST==ECP.M_TYPE)
+		{
+			b.times_i();
+		}
+
+
+		r.mul(x);
+		r.add(b);
+
+		r.reduce();
+		return r;
+	}
+
+/* construct this from (x,y) - but set to O if not on curve */
+	public ECP8(FP8 ix,FP8 iy) {
+		x=new FP8(ix);
+		y=new FP8(iy);
+		z=new FP8(1);
+		x.norm();
+		FP8 rhs=RHS(x);
+		FP8 y2=new FP8(y);
+		y2.sqr();
+		if (!y2.equals(rhs)) inf();
+		//if (y2.equals(rhs)) INF=false;
+		//else {x.zero();INF=true;}
+	}
+
+/* construct this from x - but set to O if not on curve */
+	public ECP8(FP8 ix) {
+		x=new FP8(ix);
+		y=new FP8(1);
+		z=new FP8(1);
+		x.norm();
+		FP8 rhs=RHS(x);
+		if (rhs.sqrt()) 
+		{
+			y.copy(rhs);
+		//	INF=false;
+		}
+		else {inf();/*x.zero();INF=true;*/}
+	}
+
+/* this+=this */
+	public int dbl() {
+//		if (INF) return -1;      
+
+		FP8 iy=new FP8(y);
+		if (ECP.SEXTIC_TWIST==ECP.D_TYPE)
+		{
+			iy.times_i(); //iy.norm();
+		}
+		FP8 t0=new FP8(y);                  //***** Change 
+		t0.sqr();            
+		if (ECP.SEXTIC_TWIST==ECP.D_TYPE)
+		{		
+			t0.times_i();
+		}
+		FP8 t1=new FP8(iy);  
+		t1.mul(z);
+		FP8 t2=new FP8(z);
+		t2.sqr();
+
+		z.copy(t0);
+		z.add(t0); z.norm(); 
+		z.add(z); 
+		z.add(z); 
+		z.norm();  
+
+		t2.imul(3*ROM.CURVE_B_I); 
+		if (ECP.SEXTIC_TWIST==ECP.M_TYPE)
+		{
+			t2.times_i();
+			//t2.norm();
+		}
+
+		FP8 x3=new FP8(t2);
+		x3.mul(z); 
+
+		FP8 y3=new FP8(t0);   
+
+		y3.add(t2); y3.norm();
+		z.mul(t1);
+		t1.copy(t2); t1.add(t2); t2.add(t1); t2.norm();  
+		t0.sub(t2); t0.norm();                           //y^2-9bz^2
+		y3.mul(t0); y3.add(x3);                          //(y^2+3z*2)(y^2-9z^2)+3b.z^2.8y^2
+		t1.copy(x); t1.mul(iy);						//
+		x.copy(t0); x.norm(); x.mul(t1); x.add(x);       //(y^2-9bz^2)xy2
+
+		x.norm(); 
+		y.copy(y3); y.norm();
+
+		return 1;
+	}
+
+/* this+=Q - return 0 for add, 1 for double, -1 for O */
+	public int add(ECP8 Q) {
+//		if (INF)
+//		{
+//			copy(Q);
+//			return -1;
+//		}
+//		if (Q.INF) return -1;
+
+		int b=3*ROM.CURVE_B_I;
+		FP8 t0=new FP8(x);
+		t0.mul(Q.x);         // x.Q.x
+		FP8 t1=new FP8(y);
+		t1.mul(Q.y);		 // y.Q.y
+
+		FP8 t2=new FP8(z);
+		t2.mul(Q.z);
+		FP8 t3=new FP8(x);
+		t3.add(y); t3.norm();          //t3=X1+Y1
+		FP8 t4=new FP8(Q.x);            
+		t4.add(Q.y); t4.norm();			//t4=X2+Y2
+		t3.mul(t4);						//t3=(X1+Y1)(X2+Y2)
+		t4.copy(t0); t4.add(t1);		//t4=X1.X2+Y1.Y2
+
+		t3.sub(t4); t3.norm(); 
+		if (ECP.SEXTIC_TWIST==ECP.D_TYPE)
+		{		
+			t3.times_i();  //t3.norm();         //t3=(X1+Y1)(X2+Y2)-(X1.X2+Y1.Y2) = X1.Y2+X2.Y1
+		}
+		t4.copy(y);                    
+		t4.add(z); t4.norm();			//t4=Y1+Z1
+		FP8 x3=new FP8(Q.y);
+		x3.add(Q.z); x3.norm();			//x3=Y2+Z2
+
+		t4.mul(x3);						//t4=(Y1+Z1)(Y2+Z2)
+		x3.copy(t1);					//
+		x3.add(t2);						//X3=Y1.Y2+Z1.Z2
+	
+		t4.sub(x3); t4.norm(); 
+		if (ECP.SEXTIC_TWIST==ECP.D_TYPE)
+		{	
+			t4.times_i(); //t4.norm();          //t4=(Y1+Z1)(Y2+Z2) - (Y1.Y2+Z1.Z2) = Y1.Z2+Y2.Z1
+		}
+		x3.copy(x); x3.add(z); x3.norm();	// x3=X1+Z1
+		FP8 y3=new FP8(Q.x);				
+		y3.add(Q.z); y3.norm();				// y3=X2+Z2
+		x3.mul(y3);							// x3=(X1+Z1)(X2+Z2)
+		y3.copy(t0);
+		y3.add(t2);							// y3=X1.X2+Z1+Z2
+		y3.rsub(x3); y3.norm();				// y3=(X1+Z1)(X2+Z2) - (X1.X2+Z1.Z2) = X1.Z2+X2.Z1
+
+		if (ECP.SEXTIC_TWIST==ECP.D_TYPE)
+		{
+			t0.times_i(); //t0.norm(); // x.Q.x
+			t1.times_i(); //t1.norm(); // y.Q.y
+		}
+		x3.copy(t0); x3.add(t0); 
+		t0.add(x3); t0.norm();
+		t2.imul(b); 	
+		if (ECP.SEXTIC_TWIST==ECP.M_TYPE)
+		{
+			t2.times_i();
+		}
+		FP8 z3=new FP8(t1); z3.add(t2); z3.norm();
+		t1.sub(t2); t1.norm(); 
+		y3.imul(b); 
+		if (ECP.SEXTIC_TWIST==ECP.M_TYPE)
+		{
+			y3.times_i(); 
+			//y3.norm();
+		}
+		x3.copy(y3); x3.mul(t4); t2.copy(t3); t2.mul(t1); x3.rsub(t2);
+		y3.mul(t0); t1.mul(z3); y3.add(t1);
+		t0.mul(t3); z3.mul(t4); z3.add(t0);
+
+		x.copy(x3); x.norm(); 
+		y.copy(y3); y.norm();
+		z.copy(z3); z.norm();
+
+		return 0;
+	}
+
+/* set this-=Q */
+	public int sub(ECP8 Q) {
+		ECP8 NQ=new ECP8(Q);
+		NQ.neg();
+		int D=add(NQ);
+
+//		Q.neg();
+//		int D=add(Q);
+//		Q.neg();
+		return D;
+	}
+
+	public static FP2[] frob_constants() {
+			BIG Fra=new BIG(ROM.Fra);
+			BIG Frb=new BIG(ROM.Frb);
+			FP2 X=new FP2(Fra,Frb);
+
+			FP2 F0=new FP2(X); F0.sqr();
+			FP2 F2=new FP2(F0);
+			F2.mul_ip(); F2.norm();
+			FP2 F1=new FP2(F2); F1.sqr();
+			F2.mul(F1);
+
+			F2.mul_ip(); F2.norm();
+
+			F1.copy(X);
+			if (ECP.SEXTIC_TWIST == ECP.M_TYPE)
+			{
+				F1.mul_ip();
+				F1.inverse();
+				F0.copy(F1); F0.sqr();
+			}
+			F0.mul_ip(); F0.norm();
+			F1.mul(F0);
+			FP2[] F={F0,F1,F2};
+			return F;
+	}
+
+/* set this*=q, where q is Modulus, using Frobenius */
+	public void frob(FP2 F[],int n)
+	{
+//		if (INF) return;
+		for (int i=0;i<n;i++) {
+			x.frob(F[2]);
+			x.qmul(F[0]);
+			if (ECP.SEXTIC_TWIST == ECP.M_TYPE) {
+				x.div_i2();
+			}
+			if (ECP.SEXTIC_TWIST == ECP.D_TYPE) {
+				x.times_i2();
+			}		
+
+			y.frob(F[2]);
+			y.qmul(F[1]);
+
+			if (ECP.SEXTIC_TWIST == ECP.M_TYPE) {
+				y.div_i();
+			}
+			if (ECP.SEXTIC_TWIST == ECP.D_TYPE) {
+				y.times_i2(); y.times_i2(); y.times_i();
+			}
+				z.frob(F[2]);
+		}
+	}
+
+/* P*=e */
+	public ECP8 mul(BIG e)
+	{
+/* fixed size windows */
+		int i,b,nb,m,s,ns;
+		BIG mt=new BIG();
+		BIG t=new BIG();
+		ECP8 P=new ECP8();
+		ECP8 Q=new ECP8();
+		ECP8 C=new ECP8();
+		ECP8[] W=new ECP8[8];
+		byte[] w=new byte[1+(BIG.NLEN*BIG.BASEBITS+3)/4];
+
+		if (is_infinity()) return new ECP8();
+
+		//affine();
+
+/* precompute table */
+		Q.copy(this);
+		Q.dbl();
+		W[0]=new ECP8();
+		W[0].copy(this);
+
+		for (i=1;i<8;i++)
+		{
+			W[i]=new ECP8();
+			W[i].copy(W[i-1]);
+			W[i].add(Q);
+		}
+
+/* make exponent odd - add 2P if even, P if odd */
+		t.copy(e);
+		s=t.parity();
+		t.inc(1); t.norm(); ns=t.parity(); mt.copy(t); mt.inc(1); mt.norm();
+		t.cmove(mt,s);
+		Q.cmove(this,ns);
+		C.copy(Q);
+
+		nb=1+(t.nbits()+3)/4;
+/* convert exponent to signed 4-bit window */
+		for (i=0;i<nb;i++)
+		{
+			w[i]=(byte)(t.lastbits(5)-16);
+			t.dec(w[i]); t.norm();
+			t.fshr(4);	
+		}
+		w[nb]=(byte)t.lastbits(5);
+	
+		P.copy(W[(w[nb]-1)/2]);  
+		for (i=nb-1;i>=0;i--)
+		{
+			Q.select(W,w[i]);
+			P.dbl();
+			P.dbl();
+			P.dbl();
+			P.dbl();
+			P.add(Q);
+		}
+		P.sub(C);
+		P.affine();
+		return P;
+	}
+
+/* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3... */
+// Bos & Costello https://eprint.iacr.org/2013/458.pdf
+// Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
+// Side channel attack secure 
+
+	public static ECP8 mul16(ECP8[] Q,BIG[] u)
+	{
+		int i,j,k,nb,pb1,pb2,pb3,pb4;
+		ECP8 W=new ECP8();
+		ECP8 P=new ECP8();
+		ECP8[] T1=new ECP8[8];
+		ECP8[] T2=new ECP8[8];
+		ECP8[] T3=new ECP8[8];
+		ECP8[] T4=new ECP8[8];
+
+		BIG mt=new BIG();
+		BIG[] t=new BIG[16];
+
+		byte[] w1=new byte[BIG.NLEN*BIG.BASEBITS+1];
+		byte[] s1=new byte[BIG.NLEN*BIG.BASEBITS+1];
+		byte[] w2=new byte[BIG.NLEN*BIG.BASEBITS+1];
+		byte[] s2=new byte[BIG.NLEN*BIG.BASEBITS+1];
+		byte[] w3=new byte[BIG.NLEN*BIG.BASEBITS+1];
+		byte[] s3=new byte[BIG.NLEN*BIG.BASEBITS+1];
+		byte[] w4=new byte[BIG.NLEN*BIG.BASEBITS+1];
+		byte[] s4=new byte[BIG.NLEN*BIG.BASEBITS+1];
+
+		for (i=0;i<16;i++)
+		{
+			t[i]=new BIG(u[i]);
+			//Q[i].affine();
+			t[i].norm();
+		}
+
+        T1[0] = new ECP8(); T1[0].copy(Q[0]);  // Q[0]
+        T1[1] = new ECP8(); T1[1].copy(T1[0]); T1[1].add(Q[1]);  // Q[0]+Q[1]
+        T1[2] = new ECP8(); T1[2].copy(T1[0]); T1[2].add(Q[2]);  // Q[0]+Q[2]
+        T1[3] = new ECP8(); T1[3].copy(T1[1]); T1[3].add(Q[2]);  // Q[0]+Q[1]+Q[2]
+        T1[4] = new ECP8(); T1[4].copy(T1[0]); T1[4].add(Q[3]);  // Q[0]+Q[3]
+        T1[5] = new ECP8(); T1[5].copy(T1[1]); T1[5].add(Q[3]);  // Q[0]+Q[1]+Q[3]
+        T1[6] = new ECP8(); T1[6].copy(T1[2]); T1[6].add(Q[3]);  // Q[0]+Q[2]+Q[3]
+        T1[7] = new ECP8(); T1[7].copy(T1[3]); T1[7].add(Q[3]);  // Q[0]+Q[1]+Q[2]+Q[3]
+
+//  Use Frobenius 
+		FP2[] F=ECP8.frob_constants();
+
+		for (i=0;i<8;i++) {
+			T2[i] = new ECP8(); T2[i].copy(T1[i]);
+			T2[i].frob(F,4);
+			T3[i] = new ECP8(); T3[i].copy(T2[i]);
+			T3[i].frob(F,4);
+			T4[i] = new ECP8(); T4[i].copy(T3[i]);
+			T4[i].frob(F,4);
+
+		}
+
+    // Make it odd
+        pb1=1-t[0].parity();
+        t[0].inc(pb1);
+        t[0].norm();
+
+        pb2=1-t[4].parity();
+        t[4].inc(pb2);
+        t[4].norm();
+
+        pb3=1-t[8].parity();
+        t[8].inc(pb3);
+        t[8].norm();
+
+        pb4=1-t[12].parity();
+        t[12].inc(pb4);
+        t[12].norm();
+
+    // Number of bits
+        mt.zero();
+        for (i=0;i<16;i++) {
+            mt.or(t[i]);
+        }
+        nb=1+mt.nbits();
+
+    // Sign pivot 
+        s1[nb-1]=1;
+		s2[nb-1]=1;
+        s3[nb-1]=1;
+		s4[nb-1]=1;
+        for (i=0;i<nb-1;i++) {
+            t[0].fshr(1);
+            s1[i]=(byte)(2*t[0].parity()-1);
+            t[4].fshr(1);
+            s2[i]=(byte)(2*t[4].parity()-1);
+            t[8].fshr(1);
+            s3[i]=(byte)(2*t[8].parity()-1);
+            t[12].fshr(1);
+            s4[i]=(byte)(2*t[12].parity()-1);
+ 
+        }
+
+    // Recoded exponent
+        for (i=0; i<nb; i++) {
+            w1[i]=0;
+            k=1;
+            for (j=1; j<4; j++) {
+                byte bt=(byte)(s1[i]*t[j].parity());
+                t[j].fshr(1);
+                t[j].dec((int)(bt)>>1);
+                t[j].norm();
+                w1[i]+=bt*(byte)k;
+                k*=2;
+            }
+
+            w2[i]=0;
+            k=1;
+            for (j=5; j<8; j++) {
+                byte bt=(byte)(s2[i]*t[j].parity());
+                t[j].fshr(1);
+                t[j].dec((int)(bt)>>1);
+                t[j].norm();
+                w2[i]+=bt*(byte)k;
+                k*=2;
+            }
+
+            w3[i]=0;
+            k=1;
+            for (j=9; j<12; j++) {
+                byte bt=(byte)(s3[i]*t[j].parity());
+                t[j].fshr(1);
+                t[j].dec((int)(bt)>>1);
+                t[j].norm();
+                w3[i]+=bt*(byte)k;
+                k*=2;
+            }
+
+            w4[i]=0;
+            k=1;
+            for (j=13; j<16; j++) {
+                byte bt=(byte)(s4[i]*t[j].parity());
+                t[j].fshr(1);
+                t[j].dec((int)(bt)>>1);
+                t[j].norm();
+                w4[i]+=bt*(byte)k;
+                k*=2;
+            }
+
+        } 
+
+    // Main loop
+        P.select(T1,(int)(2*w1[nb-1]+1));  
+		W.select(T2,(int)(2*w2[nb-1]+1)); 
+		P.add(W);
+		W.select(T3,(int)(2*w3[nb-1]+1));
+		P.add(W);
+		W.select(T4,(int)(2*w4[nb-1]+1));
+		P.add(W);
+        for (i=nb-2;i>=0;i--) {
+            P.dbl();
+            W.select(T1,(int)(2*w1[i]+s1[i]));
+            P.add(W);
+            W.select(T2,(int)(2*w2[i]+s2[i]));
+            P.add(W);
+            W.select(T3,(int)(2*w3[i]+s3[i]));
+            P.add(W);
+            W.select(T4,(int)(2*w4[i]+s4[i]));
+            P.add(W);
+
+        }
+
+    // apply correction
+        W.copy(P);   
+        W.sub(Q[0]);
+        P.cmove(W,pb1);   
+
+        W.copy(P);   
+        W.sub(Q[4]);
+        P.cmove(W,pb2);  
+
+        W.copy(P);   
+        W.sub(Q[8]);
+        P.cmove(W,pb3);   
+
+        W.copy(P);   
+        W.sub(Q[12]);
+        P.cmove(W,pb4);  
+
+		P.affine();
+		return P;
+	}        
+
+/* needed for SOK */
+	public static ECP8 mapit(byte[] h)
+	{
+		BIG q=new BIG(ROM.Modulus);
+		BIG x=BIG.fromBytes(h);
+		BIG one=new BIG(1);
+		FP8 X;
+		FP2 X2;
+		FP4 X4;
+		ECP8 Q;
+		x.mod(q);
+		while (true)
+		{
+			X2=new FP2(one,x);
+			X4=new FP4(X2);
+			X=new FP8(X4);
+			Q=new ECP8(X);
+			if (!Q.is_infinity()) break;
+			x.inc(1); x.norm();
+		}
+
+		FP2[] F=ECP8.frob_constants();
+		x=new BIG(ROM.CURVE_Bnx);
+
+/* Efficient hash maps to G2 on BLS curves - Budroni, Pintore */
+
+		ECP8 xQ=Q.mul(x);
+		ECP8 x2Q=xQ.mul(x);
+		ECP8 x3Q=x2Q.mul(x);
+		ECP8 x4Q=x3Q.mul(x);
+		ECP8 x5Q=x4Q.mul(x);
+		ECP8 x6Q=x5Q.mul(x);
+		ECP8 x7Q=x6Q.mul(x);
+		ECP8 x8Q=x7Q.mul(x);
+
+		if (ECP.SIGN_OF_X==ECP.NEGATIVEX)
+		{
+			xQ.neg();
+			x3Q.neg();
+			x5Q.neg();
+			x7Q.neg();
+		}	
+
+		x8Q.sub(x7Q);
+		x8Q.sub(Q);
+
+		x7Q.sub(x6Q);
+		x7Q.frob(F,1);
+
+		x6Q.sub(x5Q);
+		x6Q.frob(F,2);
+
+		x5Q.sub(x4Q);
+		x5Q.frob(F,3);
+
+		x4Q.sub(x3Q);
+		x4Q.frob(F,4);
+
+		x3Q.sub(x2Q);
+		x3Q.frob(F,5);
+
+		x2Q.sub(xQ);
+		x2Q.frob(F,6);
+
+		xQ.sub(Q);
+		xQ.frob(F,7);
+
+		Q.dbl();
+		Q.frob(F,8);
+
+		Q.add(x8Q);
+		Q.add(x7Q);
+		Q.add(x6Q);
+		Q.add(x5Q);
+
+		Q.add(x4Q);
+		Q.add(x3Q);
+		Q.add(x2Q);
+		Q.add(xQ);
+
+		Q.affine();
+		return Q;
+	}
+
+	public static ECP8 generator()
+	{
+		return new ECP8(
+			new FP8(
+				new FP4(
+					new FP2(
+						new BIG(ROM.CURVE_Pxaaa),new BIG(ROM.CURVE_Pxaab)),
+					new FP2(
+						new BIG(ROM.CURVE_Pxaba),new BIG(ROM.CURVE_Pxabb))),
+				new FP4(
+					new FP2(
+						new BIG(ROM.CURVE_Pxbaa),new BIG(ROM.CURVE_Pxbab)),
+					new FP2(
+						new BIG(ROM.CURVE_Pxbba),new BIG(ROM.CURVE_Pxbbb)))),
+			new FP8(
+				new FP4(
+					new FP2(
+						new BIG(ROM.CURVE_Pyaaa),new BIG(ROM.CURVE_Pyaab)),
+					new FP2(
+						new BIG(ROM.CURVE_Pyaba),new BIG(ROM.CURVE_Pyabb))),
+				new FP4(
+					new FP2(
+						new BIG(ROM.CURVE_Pybaa),new BIG(ROM.CURVE_Pybab)),
+					new FP2(
+						new BIG(ROM.CURVE_Pybba),new BIG(ROM.CURVE_Pybbb)))));
+
+	}
+
+}
diff --git a/version3/java/FF32.java b/version3/java/FF32.java
new file mode 100644
index 0000000..4ed2a04
--- /dev/null
+++ b/version3/java/FF32.java
@@ -0,0 +1,1029 @@
+/*
+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.
+*/
+
+/* Large Finite Field arithmetic */
+/* AMCL mod p functions */
+
+package org.apache.milagro.amcl.XXX;
+import org.apache.milagro.amcl.RAND;
+
+public final class FF {
+
+/* RSA/DH modulus length as multiple of BIGBITS */
+	public static final int FFLEN=@ML@;
+
+/* Don't Modify from here... */
+
+
+/* Finite field support - for RSA, DH etc. */
+	public static final int FF_BITS=(BIG.BIGBITS*FFLEN); /* Finite Field Size in bits - must be 256.2^n */
+	public static final int HFLEN=(FFLEN/2);  /* Useful for half-size RSA private key operations */
+	public static final int P_MBITS=BIG.MODBYTES*8;
+	public static final int P_TBITS=(P_MBITS%BIG.BASEBITS);
+
+	private final BIG[] v;
+	private final int length;
+
+/**************** 32-bit specific ************************/
+
+	public static final int P_OMASK=((int)(-1)<<(P_MBITS%BIG.BASEBITS));
+	public static final int P_FEXCESS=((int)1<<(BIG.BASEBITS*BIG.NLEN-P_MBITS-1));
+
+	public static int EXCESS(BIG a)
+	{
+		return ((a.get(BIG.NLEN-1)&P_OMASK)>>(P_TBITS))+1;
+	}
+
+/* Check if product causes excess */
+	public static boolean pexceed(BIG a,BIG b)
+	{
+		int ea,eb;
+		ea=EXCESS(a);
+		eb=EXCESS(b);
+		if ((long)(ea+1)*(eb+1)>P_FEXCESS) return true;
+		return false;
+	}
+
+/* Check if square causes excess */
+	public static boolean sexceed(BIG a)
+	{
+		int ea;
+		ea=EXCESS(a);
+		if ((long)(ea+1)*(ea+1)>P_FEXCESS) return true;
+		return false;
+	}
+
+
+/******************************************************/
+
+/* Constructors */
+	public FF(int n)
+	{
+		v=new BIG[n];
+		for (int i=0;i<n;i++)
+			v[i]=new BIG(0);
+		length=n;
+	}
+
+	public int getlen()
+	{
+		return length;
+	}
+
+/* set to integer */
+	public void set(int m)
+	{
+		zero();
+		v[0].set(0,(m&BIG.BMASK));
+		v[0].set(1,(m>>BIG.BASEBITS));
+	}
+
+/* copy from FF b */
+	public void copy(FF b)
+	{
+		for (int i=0;i<length;i++)
+		{
+			v[i].copy(b.v[i]);
+		}
+	}
+
+/* x=y<<n */
+	public void dsucopy(FF b)
+	{
+		for (int i=0;i<b.length;i++)
+		{
+			v[b.length+i].copy(b.v[i]);
+			v[i].zero();
+		}
+	}
+
+/* x=y */
+	public void dscopy(FF b)
+	{
+		for (int i=0;i<b.length;i++)
+		{
+			v[i].copy(b.v[i]);
+			v[b.length+i].zero();
+		}
+	}
+
+/* x=y>>n */
+	public void sducopy(FF b)
+	{
+		for (int i=0;i<length;i++)
+		{
+			v[i].copy(b.v[length+i]);
+		}
+	}
+
+/* set to zero */
+	public void zero()
+	{
+		for (int i=0;i<length;i++)
+		{
+			v[i].zero();
+		}
+	}
+
+	public void one()
+	{
+		v[0].one();
+		for (int i=1;i<length;i++)
+		{
+			v[i].zero();
+		}
+	}
+
+/* test equals 0 */
+	public boolean iszilch() 
+	{
+		for (int i=0;i<length;i++)
+		{
+			if (!v[i].iszilch()) return false;
+		}
+		return true;
+	}
+
+/* shift right by BIGBITS-bit words */
+	public void shrw(int n)
+	{
+		for (int i=0;i<n;i++) 
+		{
+			v[i].copy(v[i+n]);
+			v[i+n].zero();
+		}
+	}
+
+/* shift left by BIGBITS-bit words */
+	public void shlw(int n)
+	{
+		for (int i=0;i<n;i++) 
+		{
+			v[n+i].copy(v[i]);
+			v[i].zero();
+		}
+	}
+
+/* extract last bit */
+	public int parity()
+	{
+		return v[0].parity();
+	}
+
+	public int lastbits(int m)
+	{
+		return v[0].lastbits(m);
+	}
+
+/* compare x and y - must be normalised, and of same length */
+	public static int comp(FF a,FF b)
+	{
+		int i,j;
+		for (i=a.length-1;i>=0;i--)
+		{
+			j=BIG.comp(a.v[i],b.v[i]);
+			if (j!=0) return j;
+		}
+		return 0;
+	}
+
+/* recursive add */
+	public void radd(int vp,FF x,int xp,FF y,int yp,int n)
+	{
+		for (int i=0;i<n;i++)
+		{
+			v[vp+i].copy(x.v[xp+i]);
+			v[vp+i].add(y.v[yp+i]);
+		}
+	}
+
+/* recursive inc */
+	public void rinc(int vp,FF y,int yp,int n)
+	{
+		for (int i=0;i<n;i++)
+		{
+			v[vp+i].add(y.v[yp+i]);
+		}
+	}
+
+/* recursive sub */
+	public void rsub(int vp,FF x,int xp,FF y,int yp,int n)
+	{
+		for (int i=0;i<n;i++)
+		{
+			v[vp+i].copy(x.v[xp+i]);
+			v[vp+i].sub(y.v[yp+i]);
+		}
+	}
+
+/* recursive dec */
+	public void rdec(int vp,FF y,int yp,int n)
+	{
+		for (int i=0;i<n;i++)
+		{
+			v[vp+i].sub(y.v[yp+i]);
+		}
+	}
+
+/* simple add */
+	public void add(FF b)
+	{
+		for (int i=0;i<length;i++)
+			v[i].add(b.v[i]);
+	}
+
+/* simple sub */
+	public void sub(FF b)
+	{
+		for (int i=0;i<length;i++)
+			v[i].sub(b.v[i]);
+	}
+	
+/* reverse sub */
+	public void revsub(FF b)
+	{
+		for (int i=0;i<length;i++)
+			v[i].rsub(b.v[i]);
+	}
+
+/* increment/decrement by a small integer */
+	public void inc(int m)
+	{
+		v[0].inc(m);
+		norm();
+	}
+
+	public void dec(int m)
+	{
+		v[0].dec(m);
+		norm();
+	}
+
+	/* normalise - but hold any overflow in top part unless n<0 */
+	private void rnorm(int vp,int n)
+	{
+		boolean trunc=false;
+		int i;
+		long carry;
+		if (n<0)
+		{ /* -v n signals to do truncation */
+			n=-n;
+			trunc=true;
+		}
+		for (i=0;i<n-1;i++)
+		{
+			carry=v[vp+i].norm();  
+			v[vp+i].xortop(carry<<P_TBITS);
+			v[vp+i+1].incl(carry);
+		}
+		carry=v[vp+n-1].norm();
+		if (trunc) 
+			v[vp+n-1].xortop(carry<<P_TBITS);
+	}
+
+	public void norm()
+	{
+		rnorm(0,length);
+	}
+
+/* shift left by one bit */
+	public void shl()
+	{
+		int i,carry,delay_carry=0;
+		for (i=0;i<length-1;i++)
+		{
+			carry=v[i].fshl(1);
+			v[i].inc(delay_carry);
+			v[i].xortop((long)carry<<P_TBITS);
+			delay_carry=carry;
+		}
+		v[length-1].fshl(1);
+		v[length-1].inc(delay_carry);
+	}
+
+/* shift right by one bit */
+
+	public void shr()
+	{
+		int carry;
+		for (int i=length-1;i>0;i--)
+		{
+			carry=v[i].fshr(1);
+			v[i-1].xortop((long)carry<<P_TBITS);
+		}
+		v[0].fshr(1);
+	}
+
+/* Convert to Hex String */
+	public String toString() 
+	{
+		norm();
+		String s="";
+		for (int i=length-1;i>=0;i--)
+		{
+			s+=v[i].toString(); //s+=" ";
+		}
+		return s;
+	}
+
+/*
+	public String toRawString(int len) 
+	{
+	//	norm(len);
+		String s="";
+		for (int i=len-1;i>=0;i--)
+		{
+			s+=v[i].toRawString(); s+=" ";
+		}
+		return s;
+	}
+*/
+/* Convert FFs to/from byte arrays */
+	public void toBytes(byte[] b)
+	{
+		for (int i=0;i<length;i++)
+		{
+			v[i].tobytearray(b,(length-i-1)*BIG.MODBYTES);
+		}
+	}
+
+	public static void fromBytes(FF x,byte[] b)
+	{
+		for (int i=0;i<x.length;i++)
+		{
+			x.v[i]=BIG.frombytearray(b,(x.length-i-1)*BIG.MODBYTES);
+		}
+	}
+
+/* in-place swapping using xor - side channel resistant - lengths must be the same */
+	private static void cswap(FF a,FF b,int d)
+	{
+		for (int i=0;i<a.length;i++)
+		{
+		//	BIG.cswap(a.v[i],b.v[i],d);
+			a.v[i].cswap(b.v[i],d);
+		}
+	}
+
+/* z=x*y, t is workspace */
+	private void karmul(int vp,FF x,int xp,FF y,int yp,FF t,int tp,int n)
+	{
+		int nd2;
+		if (n==1)
+		{
+			x.v[xp].norm();
+			y.v[yp].norm();
+			DBIG d=BIG.mul(x.v[xp],y.v[yp]);
+			v[vp+1]=d.split(8*BIG.MODBYTES);
+			v[vp].copy(d);
+			return;
+		}
+		nd2=n/2;
+		radd(vp,x,xp,x,xp+nd2,nd2);
+		rnorm(vp,nd2);                   /* Important - required for 32-bit build */
+		radd(vp+nd2,y,yp,y,yp+nd2,nd2);
+		rnorm(vp+nd2,nd2);               /* Important - required for 32-bit build */
+
+		t.karmul(tp,this,vp,this,vp+nd2,t,tp+n,nd2);
+		karmul(vp,x,xp,y,yp,t,tp+n,nd2);
+		karmul(vp+n,x,xp+nd2,y,yp+nd2,t,tp+n,nd2);
+		t.rdec(tp,this,vp,n);
+		t.rdec(tp,this,vp+n,n);
+		rinc(vp+nd2,t,tp,n);
+		rnorm(vp,2*n);
+	}
+
+	private void karsqr(int vp,FF x,int xp,FF t,int tp,int n)
+	{
+		int nd2;
+		if (n==1)
+		{
+			x.v[xp].norm();
+			DBIG d=BIG.sqr(x.v[xp]);
+			v[vp+1].copy(d.split(8*BIG.MODBYTES));
+			v[vp].copy(d);
+			return;
+		}	
+
+		nd2=n/2;
+		karsqr(vp,x,xp,t,tp+n,nd2);
+		karsqr(vp+n,x,xp+nd2,t,tp+n,nd2);
+		t.karmul(tp,x,xp,x,xp+nd2,t,tp+n,nd2);
+		rinc(vp+nd2,t,tp,n);
+		rinc(vp+nd2,t,tp,n);
+		rnorm(vp+nd2,n);
+	}
+
+
+	private void karmul_lower(int vp,FF x,int xp,FF y,int yp,FF t,int tp,int n)
+	{ /* Calculates Least Significant bottom half of x*y */
+		int nd2;
+		if (n==1)
+		{ /* only calculate bottom half of product */
+			v[vp].copy(BIG.smul(x.v[xp],y.v[yp]));
+			return;
+		}
+		nd2=n/2;
+		karmul(vp,x,xp,y,yp,t,tp+n,nd2);
+		t.karmul_lower(tp,x,xp+nd2,y,yp,t,tp+n,nd2);
+		rinc(vp+nd2,t,tp,nd2);
+		t.karmul_lower(tp,x,xp,y,yp+nd2,t,tp+n,nd2);
+
+		rinc(vp+nd2,t,tp,nd2);
+		rnorm(vp+nd2,-nd2);  /* truncate it */
+	}
+
+	private void karmul_upper(FF x,FF y,FF t,int n)
+	{ /* Calculates Most Significant upper half of x*y, given lower part */
+		int nd2;
+ 
+		nd2=n/2;
+		radd(n,x,0,x,nd2,nd2);
+		radd(n+nd2,y,0,y,nd2,nd2);
+		rnorm(n,nd2);
+		rnorm(n+nd2,nd2);
+
+		t.karmul(0,this,n+nd2,this,n,t,n,nd2);  /* t = (a0+a1)(b0+b1) */
+		karmul(n,x,nd2,y,nd2,t,n,nd2); /* z[n]= a1*b1 */
+									/* z[0-nd2]=l(a0b0) z[nd2-n]= h(a0b0)+l(t)-l(a0b0)-l(a1b1) */
+		t.rdec(0,this,n,n);              /* t=t-a1b1  */
+		rinc(nd2,this,0,nd2);   /* z[nd2-n]+=l(a0b0) = h(a0b0)+l(t)-l(a1b1)  */
+		rdec(nd2,t,0,nd2);   /* z[nd2-n]=h(a0b0)+l(t)-l(a1b1)-l(t-a1b1)=h(a0b0) */
+		rnorm(0,-n);					/* a0b0 now in z - truncate it */
+		t.rdec(0,this,0,n);         /* (a0+a1)(b0+b1) - a0b0 */
+		rinc(nd2,t,0,n);
+
+		rnorm(nd2,n);
+	}
+
+	/* z=x*y. Assumes x and y are of same length. */
+	public static FF mul(FF x,FF y)
+	{
+		int n=x.length;
+		FF z=new FF(2*n);
+		FF t=new FF(2*n);
+//		x.norm(); y.norm();
+		z.karmul(0,x,0,y,0,t,0,n);
+		return z;
+	}
+
+	/* z=x^2 */
+	public static FF sqr(FF x)
+	{
+		int n=x.length;
+		FF z=new FF(2*n);
+		FF t=new FF(2*n);
+//		x.norm(); 
+		z.karsqr(0,x,0,t,0,n);
+		return z;
+	}
+
+/* return low part of product this*y */
+	public void lmul(FF y)
+	{
+		int n=length;
+		FF t=new FF(2*n);
+		FF x=new FF(n); x.copy(this);
+//		x.norm(); y.norm();
+		karmul_lower(0,x,0,y,0,t,0,n);
+	}
+
+/* Set b=b mod c */
+	public void mod(FF c)
+	{
+		int k=0;  
+
+		norm();
+		if (comp(this,c)<0) 
+			return;
+		do
+		{
+			c.shl();
+			k++;
+		} while (comp(this,c)>=0);
+
+		while (k>0)
+		{
+			c.shr();
+			if (comp(this,c)>=0)
+			{
+				sub(c);
+				norm();
+			}
+			k--;
+		}
+	}
+
+/* return This mod modulus, N is modulus, ND is Montgomery Constant */
+	public FF reduce(FF N,FF ND)
+	{ /* fast karatsuba Montgomery reduction */
+		int n=N.length;
+		FF t=new FF(2*n);
+		FF r=new FF(n);
+		FF m=new FF(n);
+
+		r.sducopy(this);
+		m.karmul_lower(0,this,0,ND,0,t,0,n);
+		karmul_upper(N,m,t,n);
+		m.sducopy(this);
+
+		r.add(N);
+		r.sub(m);
+		r.norm();
+
+		return r;
+	}
+
+/* Set r=this mod b */
+/* this is of length - 2*n */
+/* r,b is of length - n */
+	public FF dmod(FF b)
+	{
+		int k,n=b.length;
+		FF m=new FF(2*n);
+		FF x=new FF(2*n);
+		FF r=new FF(n);
+
+		x.copy(this);
+		x.norm();
+		m.dsucopy(b); k=BIG.BIGBITS*n;
+
+		while (comp(x,m)>=0)
+		{
+			x.sub(m);
+			x.norm();
+		}
+
+		while (k>0)
+		{	
+			m.shr();
+
+			if (comp(x,m)>=0)
+			{
+				x.sub(m);
+				x.norm();
+			}
+			k--;
+		}
+
+		r.copy(x);
+		r.mod(b);
+		return r;
+	}
+
+/* Set return=1/this mod p. Binary method - a<p on entry */
+
+	public void invmodp(FF p)
+	{
+		int n=p.length;
+
+		FF u=new FF(n);
+		FF v=new FF(n);
+		FF x1=new FF(n);
+		FF x2=new FF(n);
+		FF t=new FF(n);
+		FF one=new FF(n);
+
+		one.one();
+		u.copy(this);
+		v.copy(p);
+		x1.copy(one);
+		x2.zero();
+
+	// reduce n in here as well! 
+		while (comp(u,one)!=0 && comp(v,one)!=0)
+		{
+			while (u.parity()==0)
+			{
+				u.shr();
+				if (x1.parity()!=0)
+				{
+					x1.add(p); 
+					x1.norm();
+				}
+				x1.shr(); 
+			}
+			while (v.parity()==0)
+			{
+				v.shr(); 
+				if (x2.parity()!=0)
+				{
+					x2.add(p);
+					x2.norm();
+				}
+				x2.shr();
+			}
+			if (comp(u,v)>=0)
+			{
+
+				u.sub(v);
+				u.norm();
+				if (comp(x1,x2)>=0) x1.sub(x2);
+				else
+				{
+					t.copy(p);
+					t.sub(x2);
+					x1.add(t);
+				}
+				x1.norm();
+			}
+			else
+			{
+				v.sub(u);
+				v.norm();
+				if (comp(x2,x1)>=0) x2.sub(x1);
+				else
+				{
+					t.copy(p);
+					t.sub(x1);
+					x2.add(t);
+				}
+				x2.norm();
+			}
+		}
+		if (comp(u,one)==0)
+			copy(x1);
+		else
+			copy(x2);
+	}
+
+/* 
+idue mod m */
+	public void nres(FF m)
+	{
+		int n=m.length;
+		if (n==1)
+		{ 
+			DBIG d=new DBIG(this.v[0]);
+			d.shl(BIG.NLEN*BIG.BASEBITS);
+			this.v[0].copy(d.mod(m.v[0]));
+		}
+		else
+		{
+			FF d=new FF(2*n);
+			d.dsucopy(this);
+			copy(d.dmod(m));
+		}
+	}
+
+	public void redc(FF m,FF ND)
+	{
+		int n=m.length;
+		if (n==1)
+		{
+			DBIG d=new DBIG(this.v[0]);
+			this.v[0].copy(BIG.monty(m.v[0],(BIG.cast_to_chunk(1)<<BIG.BASEBITS)-ND.v[0].w[0],d));
+		}
+		else
+		{
+			FF d=new FF(2*n);
+			mod(m);
+			d.dscopy(this);
+			copy(d.reduce(m,ND));
+			mod(m);
+		}
+	}
+
+	private void mod2m(int m)
+	{
+		for (int i=m;i<length;i++)
+			v[i].zero();
+	}
+
+	/* U=1/a mod 2^m - Arazi & Qi */
+	private FF invmod2m()
+	{
+		int i,n=length;
+
+		FF b=new FF(n);
+		FF c=new FF(n);
+		FF U=new FF(n);
+		FF t;
+
+		U.zero();
+		U.v[0].copy(v[0]);
+		U.v[0].invmod2m();
+
+		for (i=1;i<n;i<<=1)
+		{
+			b.copy(this); b.mod2m(i);
+			t=mul(U,b);
+
+			t.shrw(i); b.copy(t);
+			c.copy(this); c.shrw(i); c.mod2m(i);
+			c.lmul(U); c.mod2m(i);
+
+			b.add(c); b.norm();
+			b.lmul(U); b.mod2m(i);
+
+			c.one(); c.shlw(i); b.revsub(c); b.norm();
+			b.shlw(i);
+			U.add(b);
+		}
+		U.norm();
+		return U;
+	}
+
+	public void random(RAND rng)
+	{
+		int n=length;
+		for (int i=0;i<n;i++)
+		{
+			v[i].copy(BIG.random(rng));
+		}
+	/* make sure top bit is 1 */
+		while (v[n-1].nbits()<BIG.MODBYTES*8) v[n-1].copy(BIG.random(rng));
+	}
+
+	/* generate random x */
+	public void randomnum(FF p,RAND rng)
+	{
+		int n=length;
+		FF d=new FF(2*n);
+
+		for (int i=0;i<2*n;i++)
+		{
+			d.v[i].copy(BIG.random(rng));
+		}
+		copy(d.dmod(p));
+	}
+
+	/* this*=y mod p */
+	public void modmul(FF y,FF p,FF nd)
+	{
+		if (pexceed(v[length-1],y.v[y.length-1])) mod(p);
+		int n=p.length;
+		if (n==1)
+		{
+			DBIG d=BIG.mul(this.v[0],y.v[0]);
+			this.v[0].copy(BIG.monty(p.v[0],(BIG.cast_to_chunk(1)<<BIG.BASEBITS)-nd.v[0].w[0],d));
+		}
+		else
+		{
+			FF d=mul(this,y);
+			copy(d.reduce(p,nd));
+		}
+	}
+
+	/* this*=y mod p */
+	public void modsqr(FF p,FF nd)
+	{
+		if (sexceed(v[length-1])) mod(p);
+		int n=p.length;
+		if (n==1)
+		{
+			DBIG d=BIG.sqr(this.v[0]);
+			this.v[0].copy(BIG.monty(p.v[0],(BIG.cast_to_chunk(1)<<BIG.BASEBITS)-nd.v[0].w[0],d));
+
+		}
+		else
+		{
+			FF d=sqr(this);
+			copy(d.reduce(p,nd));
+		}
+	}
+
+	/* this=this^e mod p using side-channel resistant Montgomery Ladder, for large e */
+	public void skpow(FF e,FF p)
+	{
+		int i,b,n=p.length;
+		FF R0=new FF(n);
+		FF R1=new FF(n);
+		FF ND=p.invmod2m();
+
+		mod(p);
+		R0.one();
+		R1.copy(this);
+		R0.nres(p);
+		R1.nres(p);
+
+		for (i=8*BIG.MODBYTES*n-1;i>=0;i--)
+		{
+			b=e.v[i/BIG.BIGBITS].bit(i%BIG.BIGBITS);
+			copy(R0);
+			modmul(R1,p,ND);
+
+			cswap(R0,R1,b);
+			R0.modsqr(p,ND);
+
+			R1.copy(this);
+			cswap(R0,R1,b);
+		}
+		copy(R0);
+		redc(p,ND);
+	}
+
+	/* this =this^e mod p using side-channel resistant Montgomery Ladder, for short e */
+	public void skpow(BIG e,FF p)
+	{
+		int i,b,n=p.length;
+		FF R0=new FF(n);
+		FF R1=new FF(n);
+		FF ND=p.invmod2m();
+
+		mod(p);
+		R0.one();
+		R1.copy(this);
+		R0.nres(p);
+		R1.nres(p);
+
+		for (i=8*BIG.MODBYTES-1;i>=0;i--)
+		{
+			b=e.bit(i);
+			copy(R0);
+			modmul(R1,p,ND);
+
+			cswap(R0,R1,b);
+			R0.modsqr(p,ND);
+
+			R1.copy(this);
+			cswap(R0,R1,b);
+		}
+		copy(R0);
+		redc(p,ND);
+	}
+
+	/* raise to an integer power - right-to-left method */
+	public void power(int e,FF p)
+	{
+		int n=p.length;
+		FF w=new FF(n);
+		FF ND=p.invmod2m();
+		boolean f=true;
+
+		w.copy(this);
+		w.nres(p);
+
+		if (e==2)
+		{
+			copy(w);
+			modsqr(p,ND);
+		}
+		else for (; ; )
+		{
+			if (e%2==1)
+			{
+				if (f) copy(w);
+				else modmul(w,p,ND);
+				f=false;
+			}
+			e>>=1;
+			if (e==0) break;
+			w.modsqr(p,ND);
+		}
+		redc(p,ND);
+	}
+
+	/* this=this^e mod p, faster but not side channel resistant */
+	public void pow(FF e,FF p)
+	{
+		int i,b,n=p.length;
+		FF w=new FF(n);
+		FF ND=p.invmod2m();
+
+		w.copy(this);
+		one();
+		nres(p);
+		w.nres(p);
+		for (i=8*BIG.MODBYTES*n-1;i>=0;i--)
+		{
+			modsqr(p,ND);
+			b=e.v[i/BIG.BIGBITS].bit(i%BIG.BIGBITS);
+			if (b==1) modmul(w,p,ND);
+		}
+		redc(p,ND);
+	}
+
+	/* double exponentiation r=x^e.y^f mod p */
+	public void pow2(BIG e,FF y,BIG f,FF p)
+	{
+		int i,eb,fb,n=p.length;
+		FF xn=new FF(n);
+		FF yn=new FF(n);
+		FF xy=new FF(n);
+		FF ND=p.invmod2m();
+
+		xn.copy(this);
+		yn.copy(y);
+		xn.nres(p);
+		yn.nres(p);
+		xy.copy(xn); xy.modmul(yn,p,ND);
+		one();
+		nres(p);
+
+		for (i=8*BIG.MODBYTES-1;i>=0;i--)
+		{
+			eb=e.bit(i);
+			fb=f.bit(i);
+			modsqr(p,ND);
+			if (eb==1)
+			{
+				if (fb==1) modmul(xy,p,ND);
+				else modmul(xn,p,ND);
+			}
+			else
+			{
+				if (fb==1) modmul(yn,p,ND);
+			}
+		}
+		redc(p,ND);
+	}
+
+	private static int igcd(int x,int y)
+	{ /* integer GCD, returns GCD of x and y */
+		int r;
+		if (y==0) return x;
+		while ((r=x%y)!=0)
+			{x=y;y=r;}
+		return y;
+	}
+
+	/* quick and dirty check for common factor with n */
+	public boolean cfactor(int s)
+	{
+		int r,n=length;
+		int g;
+
+		FF x=new FF(n);
+		FF y=new FF(n);
+
+		y.set(s);
+		x.copy(this);
+		x.norm();
+
+		do
+		{
+			x.sub(y);
+			x.norm();
+			while (!x.iszilch() && x.parity()==0) x.shr();
+		}
+		while (comp(x,y)>0);
+
+		g=(int)x.v[0].get(0);
+		r=igcd(s,g);
+		if (r>1) return true;
+		return false;
+	}
+
+	/* Miller-Rabin test for primality. Slow. */
+	public static boolean prime(FF p,RAND rng)
+	{
+		int i,j,s=0,n=p.length;
+		boolean loop;
+		FF d=new FF(n);
+		FF x=new FF(n);
+		FF unity=new FF(n);
+		FF nm1=new FF(n);
+
+		int sf=4849845; /* 3*5*.. *19 */
+		p.norm();
+
+		if (p.cfactor(sf)) return false;
+		unity.one();
+		nm1.copy(p);
+		nm1.sub(unity);
+		nm1.norm();
+		d.copy(nm1);
+
+		while (d.parity()==0)
+		{
+			d.shr();
+			s++;
+		}
+		if (s==0) return false;
+		for (i=0;i<10;i++)
+		{
+			x.randomnum(p,rng);
+			x.pow(d,p);
+
+			if (comp(x,unity)==0 || comp(x,nm1)==0) continue;
+			loop=false;
+			for (j=1;j<s;j++)
+			{
+				x.power(2,p);
+				if (comp(x,unity)==0) return false;
+				if (comp(x,nm1)==0) {loop=true; break;}
+			}
+			if (loop) continue;
+			return false;
+		}
+		return true;
+	}
+
+}
\ No newline at end of file
diff --git a/version3/java/FF64.java b/version3/java/FF64.java
new file mode 100644
index 0000000..9fde253
--- /dev/null
+++ b/version3/java/FF64.java
@@ -0,0 +1,1028 @@
+/*
+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.
+*/
+
+/* Large Finite Field arithmetic */
+/* AMCL mod p functions */
+
+package org.apache.milagro.amcl.XXX;
+import org.apache.milagro.amcl.RAND;
+
+public final class FF {
+
+/* RSA/DH modulus length as multiple of BIGBITS */
+	public static final int FFLEN=@ML@;
+
+/* Don't Modify from here... */
+
+
+/* Finite field support - for RSA, DH etc. */
+	public static final int FF_BITS=(BIG.BIGBITS*FFLEN); /* Finite Field Size in bits - must be 256.2^n */
+	public static final int HFLEN=(FFLEN/2);  /* Useful for half-size RSA private key operations */
+
+	public static final int P_MBITS=BIG.MODBYTES*8;
+	public static final int P_TBITS=(P_MBITS%BIG.BASEBITS);
+
+	private final BIG[] v;
+	private final int length;
+
+/**************** 64-bit specific ************************/
+
+	public static final long P_OMASK=((long)(-1)<<(P_MBITS%BIG.BASEBITS));
+	public static final long P_FEXCESS=((long)1<<(BIG.BASEBITS*BIG.NLEN-P_MBITS-1));
+
+	public static long EXCESS(BIG a)
+	{
+		return ((a.get(BIG.NLEN-1)&P_OMASK)>>(P_TBITS))+1;
+	}
+
+/* Check if product causes excess */
+	public static boolean pexceed(BIG a,BIG b)
+	{
+		long ea,eb;
+		ea=EXCESS(a);
+		eb=EXCESS(b);
+		if ((ea+1)>P_FEXCESS/(eb+1)) return true;
+		return false;
+	}
+
+/* Check if square causes excess */
+	public static boolean sexceed(BIG a)
+	{
+		long ea;
+		ea=EXCESS(a);
+		if ((ea+1)>P_FEXCESS/(ea+1)) return true;
+		return false;
+	}
+
+/******************************************************/
+
+/* Constructors */
+	public FF(int n)
+	{
+		v=new BIG[n];
+		for (int i=0;i<n;i++)
+			v[i]=new BIG(0);
+		length=n;
+	}
+
+	public int getlen()
+	{
+		return length;
+	}
+
+/* set to integer */
+	public void set(int m)
+	{
+		zero();
+		v[0].set(0,(m&BIG.BMASK));
+		v[0].set(1,(m>>BIG.BASEBITS));
+	}
+
+/* copy from FF b */
+	public void copy(FF b)
+	{
+		for (int i=0;i<length;i++)
+		{
+			v[i].copy(b.v[i]);
+		}
+	}
+
+/* x=y<<n */
+	public void dsucopy(FF b)
+	{
+		for (int i=0;i<b.length;i++)
+		{
+			v[b.length+i].copy(b.v[i]);
+			v[i].zero();
+		}
+	}
+
+/* x=y */
+	public void dscopy(FF b)
+	{
+		for (int i=0;i<b.length;i++)
+		{
+			v[i].copy(b.v[i]);
+			v[b.length+i].zero();
+		}
+	}
+
+/* x=y>>n */
+	public void sducopy(FF b)
+	{
+		for (int i=0;i<length;i++)
+		{
+			v[i].copy(b.v[length+i]);
+		}
+	}
+
+/* set to zero */
+	public void zero()
+	{
+		for (int i=0;i<length;i++)
+		{
+			v[i].zero();
+		}
+	}
+
+	public void one()
+	{
+		v[0].one();
+		for (int i=1;i<length;i++)
+		{
+			v[i].zero();
+		}
+	}
+
+/* test equals 0 */
+	public boolean iszilch() 
+	{
+		for (int i=0;i<length;i++)
+		{
+			if (!v[i].iszilch()) return false;
+		}
+		return true;
+	}
+
+/* shift right by BIGBITS-bit words */
+	public void shrw(int n)
+	{
+		for (int i=0;i<n;i++) 
+		{
+			v[i].copy(v[i+n]);
+			v[i+n].zero();
+		}
+	}
+
+/* shift left by BIGBITS-bit words */
+	public void shlw(int n)
+	{
+		for (int i=0;i<n;i++) 
+		{
+			v[n+i].copy(v[i]);
+			v[i].zero();
+		}
+	}
+
+/* extract last bit */
+	public int parity()
+	{
+		return v[0].parity();
+	}
+
+	public int lastbits(int m)
+	{
+		return v[0].lastbits(m);
+	}
+
+/* compare x and y - must be normalised, and of same length */
+	public static int comp(FF a,FF b)
+	{
+		int i,j;
+		for (i=a.length-1;i>=0;i--)
+		{
+			j=BIG.comp(a.v[i],b.v[i]);
+			if (j!=0) return j;
+		}
+		return 0;
+	}
+
+/* recursive add */
+	public void radd(int vp,FF x,int xp,FF y,int yp,int n)
+	{
+		for (int i=0;i<n;i++)
+		{
+			v[vp+i].copy(x.v[xp+i]);
+			v[vp+i].add(y.v[yp+i]);
+		}
+	}
+
+/* recursive inc */
+	public void rinc(int vp,FF y,int yp,int n)
+	{
+		for (int i=0;i<n;i++)
+		{
+			v[vp+i].add(y.v[yp+i]);
+		}
+	}
+
+/* recursive sub */
+	public void rsub(int vp,FF x,int xp,FF y,int yp,int n)
+	{
+		for (int i=0;i<n;i++)
+		{
+			v[vp+i].copy(x.v[xp+i]);
+			v[vp+i].sub(y.v[yp+i]);
+		}
+	}
+
+/* recursive dec */
+	public void rdec(int vp,FF y,int yp,int n)
+	{
+		for (int i=0;i<n;i++)
+		{
+			v[vp+i].sub(y.v[yp+i]);
+		}
+	}
+
+/* simple add */
+	public void add(FF b)
+	{
+		for (int i=0;i<length;i++)
+			v[i].add(b.v[i]);
+	}
+
+/* simple sub */
+	public void sub(FF b)
+	{
+		for (int i=0;i<length;i++)
+			v[i].sub(b.v[i]);
+	}
+	
+/* reverse sub */
+	public void revsub(FF b)
+	{
+		for (int i=0;i<length;i++)
+			v[i].rsub(b.v[i]);
+	}
+
+/* increment/decrement by a small integer */
+	public void inc(int m)
+	{
+		v[0].inc(m);
+		norm();
+	}
+
+	public void dec(int m)
+	{
+		v[0].dec(m);
+		norm();
+	}
+
+	/* normalise - but hold any overflow in top part unless n<0 */
+	private void rnorm(int vp,int n)
+	{
+		boolean trunc=false;
+		int i;
+		long carry;
+		if (n<0)
+		{ /* -v n signals to do truncation */
+			n=-n;
+			trunc=true;
+		}
+		for (i=0;i<n-1;i++)
+		{
+			carry=v[vp+i].norm();  
+			v[vp+i].xortop(carry<<P_TBITS);
+			v[vp+i+1].incl(carry);
+		}
+		carry=v[vp+n-1].norm();
+		if (trunc) 
+			v[vp+n-1].xortop(carry<<P_TBITS);
+	}
+
+	public void norm()
+	{
+		rnorm(0,length);
+	}
+
+/* shift left by one bit */
+	public void shl()
+	{
+		int i,carry,delay_carry=0;
+		for (i=0;i<length-1;i++)
+		{
+			carry=v[i].fshl(1);
+			v[i].inc(delay_carry);
+			v[i].xortop((long)carry<<P_TBITS);
+			delay_carry=carry;
+		}
+		v[length-1].fshl(1);
+		v[length-1].inc(delay_carry);
+	}
+
+/* shift right by one bit */
+
+	public void shr()
+	{
+		int carry;
+		for (int i=length-1;i>0;i--)
+		{
+			carry=v[i].fshr(1);
+			v[i-1].xortop((long)carry<<P_TBITS);
+		}
+		v[0].fshr(1);
+	}
+
+/* Convert to Hex String */
+	public String toString() 
+	{
+		norm();
+		String s="";
+		for (int i=length-1;i>=0;i--)
+		{
+			s+=v[i].toString(); //s+=" ";
+		}
+		return s;
+	}
+
+/*
+	public String toRawString(int len) 
+	{
+	//	norm(len);
+		String s="";
+		for (int i=len-1;i>=0;i--)
+		{
+			s+=v[i].toRawString(); s+=" ";
+		}
+		return s;
+	}
+*/
+/* Convert FFs to/from byte arrays */
+	public void toBytes(byte[] b)
+	{
+		for (int i=0;i<length;i++)
+		{
+			v[i].tobytearray(b,(length-i-1)*BIG.MODBYTES);
+		}
+	}
+
+	public static void fromBytes(FF x,byte[] b)
+	{
+		for (int i=0;i<x.length;i++)
+		{
+			x.v[i]=BIG.frombytearray(b,(x.length-i-1)*BIG.MODBYTES);
+		}
+	}
+
+/* in-place swapping using xor - side channel resistant - lengths must be the same */
+	private static void cswap(FF a,FF b,int d)
+	{
+		for (int i=0;i<a.length;i++)
+		{
+		//	BIG.cswap(a.v[i],b.v[i],d);
+			a.v[i].cswap(b.v[i],d);
+		}
+	}
+
+/* z=x*y, t is workspace */
+	private void karmul(int vp,FF x,int xp,FF y,int yp,FF t,int tp,int n)
+	{
+		int nd2;
+		if (n==1)
+		{
+			x.v[xp].norm();
+			y.v[yp].norm();
+			DBIG d=BIG.mul(x.v[xp],y.v[yp]);
+			v[vp+1]=d.split(8*BIG.MODBYTES);
+			v[vp].copy(d);
+			return;
+		}
+		nd2=n/2;
+		radd(vp,x,xp,x,xp+nd2,nd2);
+		rnorm(vp,nd2);                   /* Important - required for 32-bit build */
+		radd(vp+nd2,y,yp,y,yp+nd2,nd2);
+		rnorm(vp+nd2,nd2);               /* Important - required for 32-bit build */
+
+		t.karmul(tp,this,vp,this,vp+nd2,t,tp+n,nd2);
+		karmul(vp,x,xp,y,yp,t,tp+n,nd2);
+		karmul(vp+n,x,xp+nd2,y,yp+nd2,t,tp+n,nd2);
+		t.rdec(tp,this,vp,n);
+		t.rdec(tp,this,vp+n,n);
+		rinc(vp+nd2,t,tp,n);
+		rnorm(vp,2*n);
+	}
+
+	private void karsqr(int vp,FF x,int xp,FF t,int tp,int n)
+	{
+		int nd2;
+		if (n==1)
+		{
+			x.v[xp].norm();
+			DBIG d=BIG.sqr(x.v[xp]);
+			v[vp+1].copy(d.split(8*BIG.MODBYTES));
+			v[vp].copy(d);
+			return;
+		}	
+
+		nd2=n/2;
+		karsqr(vp,x,xp,t,tp+n,nd2);
+		karsqr(vp+n,x,xp+nd2,t,tp+n,nd2);
+		t.karmul(tp,x,xp,x,xp+nd2,t,tp+n,nd2);
+		rinc(vp+nd2,t,tp,n);
+		rinc(vp+nd2,t,tp,n);
+		rnorm(vp+nd2,n);
+	}
+
+
+	private void karmul_lower(int vp,FF x,int xp,FF y,int yp,FF t,int tp,int n)
+	{ /* Calculates Least Significant bottom half of x*y */
+		int nd2;
+		if (n==1)
+		{ /* only calculate bottom half of product */
+			v[vp].copy(BIG.smul(x.v[xp],y.v[yp]));
+			return;
+		}
+		nd2=n/2;
+		karmul(vp,x,xp,y,yp,t,tp+n,nd2);
+		t.karmul_lower(tp,x,xp+nd2,y,yp,t,tp+n,nd2);
+		rinc(vp+nd2,t,tp,nd2);
+		t.karmul_lower(tp,x,xp,y,yp+nd2,t,tp+n,nd2);
+
+		rinc(vp+nd2,t,tp,nd2);
+		rnorm(vp+nd2,-nd2);  /* truncate it */
+	}
+
+	private void karmul_upper(FF x,FF y,FF t,int n)
+	{ /* Calculates Most Significant upper half of x*y, given lower part */
+		int nd2;
+ 
+		nd2=n/2;
+		radd(n,x,0,x,nd2,nd2);
+		radd(n+nd2,y,0,y,nd2,nd2);
+		rnorm(n,nd2);
+		rnorm(n+nd2,nd2);
+
+		t.karmul(0,this,n+nd2,this,n,t,n,nd2);  /* t = (a0+a1)(b0+b1) */
+		karmul(n,x,nd2,y,nd2,t,n,nd2); /* z[n]= a1*b1 */
+									/* z[0-nd2]=l(a0b0) z[nd2-n]= h(a0b0)+l(t)-l(a0b0)-l(a1b1) */
+		t.rdec(0,this,n,n);              /* t=t-a1b1  */
+		rinc(nd2,this,0,nd2);   /* z[nd2-n]+=l(a0b0) = h(a0b0)+l(t)-l(a1b1)  */
+		rdec(nd2,t,0,nd2);   /* z[nd2-n]=h(a0b0)+l(t)-l(a1b1)-l(t-a1b1)=h(a0b0) */
+		rnorm(0,-n);					/* a0b0 now in z - truncate it */
+		t.rdec(0,this,0,n);         /* (a0+a1)(b0+b1) - a0b0 */
+		rinc(nd2,t,0,n);
+
+		rnorm(nd2,n);
+	}
+
+	/* z=x*y. Assumes x and y are of same length. */
+	public static FF mul(FF x,FF y)
+	{
+		int n=x.length;
+		FF z=new FF(2*n);
+		FF t=new FF(2*n);
+//		x.norm(); y.norm();
+		z.karmul(0,x,0,y,0,t,0,n);
+		return z;
+	}
+
+	/* z=x^2 */
+	public static FF sqr(FF x)
+	{
+		int n=x.length;
+		FF z=new FF(2*n);
+		FF t=new FF(2*n);
+//		x.norm(); 
+		z.karsqr(0,x,0,t,0,n);
+		return z;
+	}
+
+/* return low part of product this*y */
+	public void lmul(FF y)
+	{
+		int n=length;
+		FF t=new FF(2*n);
+		FF x=new FF(n); x.copy(this);
+//		x.norm(); y.norm();
+		karmul_lower(0,x,0,y,0,t,0,n);
+	}
+
+/* Set b=b mod c */
+	public void mod(FF c)
+	{
+		int k=0;  
+
+		norm();
+		if (comp(this,c)<0) 
+			return;
+		do
+		{
+			c.shl();
+			k++;
+		} while (comp(this,c)>=0);
+
+		while (k>0)
+		{
+			c.shr();
+			if (comp(this,c)>=0)
+			{
+				sub(c);
+				norm();
+			}
+			k--;
+		}
+	}
+
+/* return This mod modulus, N is modulus, ND is Montgomery Constant */
+	public FF reduce(FF N,FF ND)
+	{ /* fast karatsuba Montgomery reduction */
+		int n=N.length;
+		FF t=new FF(2*n);
+		FF r=new FF(n);
+		FF m=new FF(n);
+
+		r.sducopy(this);
+		m.karmul_lower(0,this,0,ND,0,t,0,n);
+		karmul_upper(N,m,t,n);
+		m.sducopy(this);
+
+		r.add(N);
+		r.sub(m);
+		r.norm();
+
+		return r;
+	}
+
+/* Set r=this mod b */
+/* this is of length - 2*n */
+/* r,b is of length - n */
+	public FF dmod(FF b)
+	{
+		int k,n=b.length;
+		FF m=new FF(2*n);
+		FF x=new FF(2*n);
+		FF r=new FF(n);
+
+		x.copy(this);
+		x.norm();
+		m.dsucopy(b); k=BIG.BIGBITS*n;
+
+		while (comp(x,m)>=0)
+		{
+			x.sub(m);
+			x.norm();
+		}
+
+		while (k>0)
+		{	
+			m.shr();
+
+			if (comp(x,m)>=0)
+			{
+				x.sub(m);
+				x.norm();
+			}
+			k--;
+		}
+
+		r.copy(x);
+		r.mod(b);
+		return r;
+	}
+
+/* Set return=1/this mod p. Binary method - a<p on entry */
+
+	public void invmodp(FF p)
+	{
+		int n=p.length;
+
+		FF u=new FF(n);
+		FF v=new FF(n);
+		FF x1=new FF(n);
+		FF x2=new FF(n);
+		FF t=new FF(n);
+		FF one=new FF(n);
+
+		one.one();
+		u.copy(this);
+		v.copy(p);
+		x1.copy(one);
+		x2.zero();
+
+	// reduce n in here as well! 
+		while (comp(u,one)!=0 && comp(v,one)!=0)
+		{
+			while (u.parity()==0)
+			{
+				u.shr();
+				if (x1.parity()!=0)
+				{
+					x1.add(p); 
+					x1.norm();
+				}
+				x1.shr(); 
+			}
+			while (v.parity()==0)
+			{
+				v.shr(); 
+				if (x2.parity()!=0)
+				{
+					x2.add(p);
+					x2.norm();
+				}
+				x2.shr();
+			}
+			if (comp(u,v)>=0)
+			{
+
+				u.sub(v);
+				u.norm();
+				if (comp(x1,x2)>=0) x1.sub(x2);
+				else
+				{
+					t.copy(p);
+					t.sub(x2);
+					x1.add(t);
+				}
+				x1.norm();
+			}
+			else
+			{
+				v.sub(u);
+				v.norm();
+				if (comp(x2,x1)>=0) x2.sub(x1);
+				else
+				{
+					t.copy(p);
+					t.sub(x1);
+					x2.add(t);
+				}
+				x2.norm();
+			}
+		}
+		if (comp(u,one)==0)
+			copy(x1);
+		else
+			copy(x2);
+	}
+
+/* nresidue mod m */
+	public void nres(FF m)
+	{
+		int n=m.length;
+		if (n==1)
+		{ 
+			DBIG d=new DBIG(this.v[0]);
+			d.shl(BIG.NLEN*BIG.BASEBITS);
+			this.v[0].copy(d.mod(m.v[0]));
+		}
+		else
+		{
+			FF d=new FF(2*n);
+			d.dsucopy(this);
+			copy(d.dmod(m));
+		}
+	}
+
+	public void redc(FF m,FF ND)
+	{
+		int n=m.length;
+		if (n==1)
+		{
+			DBIG d=new DBIG(this.v[0]);
+			this.v[0].copy(BIG.monty(m.v[0],(BIG.cast_to_chunk(1)<<BIG.BASEBITS)-ND.v[0].w[0],d));
+		}
+		else
+		{
+			FF d=new FF(2*n);
+			mod(m);
+			d.dscopy(this);
+			copy(d.reduce(m,ND));
+			mod(m);
+		}
+	}
+
+	private void mod2m(int m)
+	{
+		for (int i=m;i<length;i++)
+			v[i].zero();
+	}
+
+	/* U=1/a mod 2^m - Arazi & Qi */
+	private FF invmod2m()
+	{
+		int i,n=length;
+
+		FF b=new FF(n);
+		FF c=new FF(n);
+		FF U=new FF(n);
+		FF t;
+
+		U.zero();
+		U.v[0].copy(v[0]);
+		U.v[0].invmod2m();
+
+		for (i=1;i<n;i<<=1)
+		{
+			b.copy(this); b.mod2m(i);
+			t=mul(U,b);
+
+			t.shrw(i); b.copy(t);
+			c.copy(this); c.shrw(i); c.mod2m(i);
+			c.lmul(U); c.mod2m(i);
+
+			b.add(c); b.norm();
+			b.lmul(U); b.mod2m(i);
+
+			c.one(); c.shlw(i); b.revsub(c); b.norm();
+			b.shlw(i);
+			U.add(b);
+		}
+		U.norm();
+		return U;
+	}
+
+	public void random(RAND rng)
+	{
+		int n=length;
+		for (int i=0;i<n;i++)
+		{
+			v[i].copy(BIG.random(rng));
+		}
+	/* make sure top bit is 1 */
+		while (v[n-1].nbits()<BIG.MODBYTES*8) v[n-1].copy(BIG.random(rng));
+	}
+
+	/* generate random x */
+	public void randomnum(FF p,RAND rng)
+	{
+		int n=length;
+		FF d=new FF(2*n);
+
+		for (int i=0;i<2*n;i++)
+		{
+			d.v[i].copy(BIG.random(rng));
+		}
+		copy(d.dmod(p));
+	}
+
+	/* this*=y mod p */
+	public void modmul(FF y,FF p,FF nd)
+	{
+		if (pexceed(v[length-1],y.v[y.length-1])) mod(p);
+		int n=p.length;
+		if (n==1)
+		{
+			DBIG d=BIG.mul(this.v[0],y.v[0]);
+			this.v[0].copy(BIG.monty(p.v[0],(BIG.cast_to_chunk(1)<<BIG.BASEBITS)-nd.v[0].w[0],d));
+		}
+		else
+		{
+			FF d=mul(this,y);
+			copy(d.reduce(p,nd));
+		}
+	}
+
+	/* this*=y mod p */
+	public void modsqr(FF p,FF nd)
+	{
+		if (sexceed(v[length-1])) mod(p);
+		int n=p.length;
+		if (n==1)
+		{
+			DBIG d=BIG.sqr(this.v[0]);
+			this.v[0].copy(BIG.monty(p.v[0],(BIG.cast_to_chunk(1)<<BIG.BASEBITS)-nd.v[0].w[0],d));
+
+		}
+		else
+		{
+			FF d=sqr(this);
+			copy(d.reduce(p,nd));
+		}
+	}
+
+	/* this=this^e mod p using side-channel resistant Montgomery Ladder, for large e */
+	public void skpow(FF e,FF p)
+	{
+		int i,b,n=p.length;
+		FF R0=new FF(n);
+		FF R1=new FF(n);
+		FF ND=p.invmod2m();
+
+		mod(p);
+		R0.one();
+		R1.copy(this);
+		R0.nres(p);
+		R1.nres(p);
+
+		for (i=8*BIG.MODBYTES*n-1;i>=0;i--)
+		{
+			b=e.v[i/BIG.BIGBITS].bit(i%BIG.BIGBITS);
+			copy(R0);
+			modmul(R1,p,ND);
+
+			cswap(R0,R1,b);
+			R0.modsqr(p,ND);
+
+			R1.copy(this);
+			cswap(R0,R1,b);
+		}
+		copy(R0);
+		redc(p,ND);
+	}
+
+	/* this =this^e mod p using side-channel resistant Montgomery Ladder, for short e */
+	public void skpow(BIG e,FF p)
+	{
+		int i,b,n=p.length;
+		FF R0=new FF(n);
+		FF R1=new FF(n);
+		FF ND=p.invmod2m();
+
+		mod(p);
+		R0.one();
+		R1.copy(this);
+		R0.nres(p);
+		R1.nres(p);
+
+		for (i=8*BIG.MODBYTES-1;i>=0;i--)
+		{
+			b=e.bit(i);
+			copy(R0);
+			modmul(R1,p,ND);
+
+			cswap(R0,R1,b);
+			R0.modsqr(p,ND);
+
+			R1.copy(this);
+			cswap(R0,R1,b);
+		}
+		copy(R0);
+		redc(p,ND);
+	}
+
+	/* raise to an integer power - right-to-left method */
+	public void power(int e,FF p)
+	{
+		int n=p.length;
+		FF w=new FF(n);
+		FF ND=p.invmod2m();
+		boolean f=true;
+
+		w.copy(this);
+		w.nres(p);
+
+		if (e==2)
+		{
+			copy(w);
+			modsqr(p,ND);
+		}
+		else for (; ; )
+		{
+			if (e%2==1)
+			{
+				if (f) copy(w);
+				else modmul(w,p,ND);
+				f=false;
+			}
+			e>>=1;
+			if (e==0) break;
+			w.modsqr(p,ND);
+		}
+		redc(p,ND);
+	}
+
+	/* this=this^e mod p, faster but not side channel resistant */
+	public void pow(FF e,FF p)
+	{
+		int i,b,n=p.length;
+		FF w=new FF(n);
+		FF ND=p.invmod2m();
+
+		w.copy(this);
+		one();
+		nres(p);
+		w.nres(p);
+		for (i=8*BIG.MODBYTES*n-1;i>=0;i--)
+		{
+			modsqr(p,ND);
+			b=e.v[i/BIG.BIGBITS].bit(i%BIG.BIGBITS);
+			if (b==1) modmul(w,p,ND);
+		}
+		redc(p,ND);
+	}
+
+	/* double exponentiation r=x^e.y^f mod p */
+	public void pow2(BIG e,FF y,BIG f,FF p)
+	{
+		int i,eb,fb,n=p.length;
+		FF xn=new FF(n);
+		FF yn=new FF(n);
+		FF xy=new FF(n);
+		FF ND=p.invmod2m();
+
+		xn.copy(this);
+		yn.copy(y);
+		xn.nres(p);
+		yn.nres(p);
+		xy.copy(xn); xy.modmul(yn,p,ND);
+		one();
+		nres(p);
+
+		for (i=8*BIG.MODBYTES-1;i>=0;i--)
+		{
+			eb=e.bit(i);
+			fb=f.bit(i);
+			modsqr(p,ND);
+			if (eb==1)
+			{
+				if (fb==1) modmul(xy,p,ND);
+				else modmul(xn,p,ND);
+			}
+			else
+			{
+				if (fb==1) modmul(yn,p,ND);
+			}
+		}
+		redc(p,ND);
+	}
+
+	private static int igcd(int x,int y)
+	{ /* integer GCD, returns GCD of x and y */
+		int r;
+		if (y==0) return x;
+		while ((r=x%y)!=0)
+			{x=y;y=r;}
+		return y;
+	}
+
+	/* quick and dirty check for common factor with n */
+	public boolean cfactor(int s)
+	{
+		int r,n=length;
+		int g;
+
+		FF x=new FF(n);
+		FF y=new FF(n);
+
+		y.set(s);
+		x.copy(this);
+		x.norm();
+
+		do
+		{
+			x.sub(y);
+			x.norm();
+			while (!x.iszilch() && x.parity()==0) x.shr();
+		}
+		while (comp(x,y)>0);
+
+		g=(int)x.v[0].get(0);
+		r=igcd(s,g);
+		if (r>1) return true;
+		return false;
+	}
+
+	/* Miller-Rabin test for primality. Slow. */
+	public static boolean prime(FF p,RAND rng)
+	{
+		int i,j,s=0,n=p.length;
+		boolean loop;
+		FF d=new FF(n);
+		FF x=new FF(n);
+		FF unity=new FF(n);
+		FF nm1=new FF(n);
+
+		int sf=4849845; /* 3*5*.. *19 */
+		p.norm();
+
+		if (p.cfactor(sf)) return false;
+		unity.one();
+		nm1.copy(p);
+		nm1.sub(unity);
+		nm1.norm();
+		d.copy(nm1);
+
+		while (d.parity()==0)
+		{
+			d.shr();
+			s++;
+		}
+		if (s==0) return false;
+		for (i=0;i<10;i++)
+		{
+			x.randomnum(p,rng);
+			x.pow(d,p);
+
+			if (comp(x,unity)==0 || comp(x,nm1)==0) continue;
+			loop=false;
+			for (j=1;j<s;j++)
+			{
+				x.power(2,p);
+				if (comp(x,unity)==0) return false;
+				if (comp(x,nm1)==0) {loop=true; break;}
+			}
+			if (loop) continue;
+			return false;
+		}
+		return true;
+	}
+
+}
\ No newline at end of file
diff --git a/version3/java/FP12.java b/version3/java/FP12.java
new file mode 100644
index 0000000..aaa1b69
--- /dev/null
+++ b/version3/java/FP12.java
@@ -0,0 +1,910 @@
+/*
+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.
+*/
+
+/* AMCL Fp^12 functions */
+/* FP12 elements are of the form a+i.b+i^2.c */
+
+package org.apache.milagro.amcl.XXX;
+
+public final class FP12 {
+	private final FP4 a;
+	private final FP4 b;
+	private final FP4 c;
+/* reduce all components of this mod Modulus */
+	public void reduce()
+	{
+		a.reduce();
+		b.reduce();
+		c.reduce();
+	}
+/* normalise all components of this */
+	public void norm()
+	{
+		a.norm();
+		b.norm();
+		c.norm();
+	}
+/* test x==0 ? */
+	public boolean iszilch() {
+		//reduce();
+		return (a.iszilch() && b.iszilch() && c.iszilch());
+	}
+
+	public void cmove(FP12 g,int d)
+	{
+		a.cmove(g.a,d);
+		b.cmove(g.b,d);
+		c.cmove(g.c,d);		
+	}
+
+
+/* return 1 if b==c, no branching */
+	public static int teq(int b,int c)
+	{
+		int x=b^c;
+		x-=1;  // if x=0, x now -1
+		return ((x>>31)&1);
+	}
+
+/* Constant time select from pre-computed table */
+	public void select(FP12 g[],int b)
+	{
+		int m=b>>31;
+		int babs=(b^m)-m;
+
+		babs=(babs-1)/2;
+
+		cmove(g[0],teq(babs,0));  // conditional move
+		cmove(g[1],teq(babs,1));
+		cmove(g[2],teq(babs,2));
+		cmove(g[3],teq(babs,3));
+		cmove(g[4],teq(babs,4));
+		cmove(g[5],teq(babs,5));
+		cmove(g[6],teq(babs,6));
+		cmove(g[7],teq(babs,7));
+ 
+		FP12 invf=new FP12(this); 
+		invf.conj();
+		cmove(invf,(int)(m&1));
+	}
+
+
+/* test x==1 ? */
+	public boolean isunity() {
+		FP4 one=new FP4(1);
+		return (a.equals(one) && b.iszilch() && c.iszilch());
+	}
+/* return 1 if x==y, else 0 */
+	public boolean equals(FP12 x)
+	{
+		return (a.equals(x.a) && b.equals(x.b) && c.equals(x.c));
+	}
+/* extract a from this */
+	public FP4 geta()
+	{
+		return a;
+	}
+/* extract b */
+	public FP4 getb()
+	{
+		return b;
+	}
+/* extract c */
+	public FP4 getc()
+	{
+		return c;
+	}
+/* copy this=x */
+	public void copy(FP12 x)
+	{
+		a.copy(x.a);
+		b.copy(x.b);
+		c.copy(x.c);
+	}
+/* set this=1 */
+	public void one()
+	{
+		a.one();
+		b.zero();
+		c.zero();
+	}
+/* this=conj(this) */
+	public void conj()
+	{
+		a.conj();
+		b.nconj();
+		c.conj();
+	}
+/* Constructors */
+	public FP12(FP4 d)
+	{
+		a=new FP4(d);
+		b=new FP4(0);
+		c=new FP4(0);
+	}
+
+	public FP12(int d)
+	{
+		a=new FP4(d);
+		b=new FP4(0);
+		c=new FP4(0);
+	}
+
+	public FP12(FP4 d,FP4 e,FP4 f)
+	{
+		a=new FP4(d);
+		b=new FP4(e);
+		c=new FP4(f);
+	}
+
+	public FP12(FP12 x)
+	{
+		a=new FP4(x.a);
+		b=new FP4(x.b);
+		c=new FP4(x.c);
+	}
+
+/* Granger-Scott Unitary Squaring */
+	public void usqr()
+	{
+//System.out.println("Into usqr");
+		FP4 A=new FP4(a);
+		FP4 B=new FP4(c);
+		FP4 C=new FP4(b);
+		FP4 D=new FP4(0);
+
+		a.sqr();
+		D.copy(a); D.add(a);
+		a.add(D);
+
+		a.norm();
+		A.nconj();
+
+		A.add(A);
+		a.add(A);
+		B.sqr();
+		B.times_i();
+
+		D.copy(B); D.add(B);
+		B.add(D);
+		B.norm();
+
+		C.sqr();
+		D.copy(C); D.add(C);
+		C.add(D);
+		C.norm();
+
+		b.conj();
+		b.add(b);
+		c.nconj();
+
+		c.add(c);
+		b.add(B);
+		c.add(C);
+//System.out.println("Out of usqr 1");
+		reduce();
+//System.out.println("Out of usqr 2");
+	}
+
+/* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
+	public void sqr()
+	{
+//System.out.println("Into sqr");
+		FP4 A=new FP4(a);
+		FP4 B=new FP4(b);
+		FP4 C=new FP4(c);
+		FP4 D=new FP4(a);
+
+		A.sqr();
+		B.mul(c);
+		B.add(B);
+	B.norm();
+		C.sqr();
+		D.mul(b);
+		D.add(D);
+
+		c.add(a);
+		c.add(b);
+	c.norm();
+		c.sqr();
+
+		a.copy(A);
+
+		A.add(B);
+		A.norm();
+		A.add(C);
+		A.add(D);
+		A.norm();
+
+		A.neg();
+		B.times_i();
+		C.times_i();
+
+		a.add(B);
+
+		b.copy(C); b.add(D);
+		c.add(A);
+//System.out.println("Out of sqr");
+		norm();
+	}
+
+/* FP12 full multiplication this=this*y */
+	public void mul(FP12 y)
+	{
+//System.out.println("Into mul");
+		FP4 z0=new FP4(a);
+		FP4 z1=new FP4(0);
+		FP4 z2=new FP4(b);
+		FP4 z3=new FP4(0);
+		FP4 t0=new FP4(a);
+		FP4 t1=new FP4(y.a);
+
+		z0.mul(y.a);
+		z2.mul(y.b);
+
+		t0.add(b);
+		t1.add(y.b);
+
+	t0.norm();
+	t1.norm();
+
+		z1.copy(t0); z1.mul(t1);
+		t0.copy(b); t0.add(c);
+
+		t1.copy(y.b); t1.add(y.c);
+
+	t0.norm();
+	t1.norm();
+
+		z3.copy(t0); z3.mul(t1);
+
+		t0.copy(z0); t0.neg();
+		t1.copy(z2); t1.neg();
+
+		z1.add(t0);
+		//z1.norm();
+		b.copy(z1); b.add(t1);
+
+		z3.add(t1);
+		z2.add(t0);
+
+		t0.copy(a); t0.add(c);
+		t1.copy(y.a); t1.add(y.c);
+
+t0.norm();
+t1.norm();
+	
+		t0.mul(t1);
+		z2.add(t0);
+
+		t0.copy(c); t0.mul(y.c);
+		t1.copy(t0); t1.neg();
+
+//		z2.norm();
+//		z3.norm();
+//		b.norm();
+
+		c.copy(z2); c.add(t1);
+		z3.add(t1);
+		t0.times_i();
+		b.add(t0);
+	z3.norm();
+		z3.times_i();
+		a.copy(z0); a.add(z3);
+		norm();
+//System.out.println("Out of mul");
+	}
+
+/* Special case of multiplication arises from special form of ATE pairing line function */
+	public void smul(FP12 y,int type)
+	{
+//System.out.println("Into smul");
+
+		if (type==ECP.D_TYPE)
+		{
+			FP4 z0=new FP4(a);
+			FP4 z2=new FP4(b);
+			FP4 z3=new FP4(b);
+			FP4 t0=new FP4(0);
+			FP4 t1=new FP4(y.a);
+			z0.mul(y.a);
+			z2.pmul(y.b.real());
+			b.add(a);
+			t1.real().add(y.b.real());
+
+			t1.norm();
+			b.norm();
+			b.mul(t1);
+			z3.add(c);
+			z3.norm();
+			z3.pmul(y.b.real());
+
+			t0.copy(z0); t0.neg();
+			t1.copy(z2); t1.neg();
+
+			b.add(t0);
+
+			b.add(t1);
+			z3.add(t1);
+			z2.add(t0);
+
+			t0.copy(a); t0.add(c);
+			t0.norm();
+			z3.norm();
+			t0.mul(y.a);
+			c.copy(z2); c.add(t0);
+
+			z3.times_i();
+			a.copy(z0); a.add(z3);
+		}
+		if (type==ECP.M_TYPE)
+		{
+			FP4 z0=new FP4(a);
+			FP4 z1=new FP4(0);
+			FP4 z2=new FP4(0);
+			FP4 z3=new FP4(0);
+			FP4 t0=new FP4(a);
+			FP4 t1=new FP4(0);
+		
+			z0.mul(y.a);
+			t0.add(b);
+			t0.norm();
+
+			z1.copy(t0); z1.mul(y.a);
+			t0.copy(b); t0.add(c);
+			t0.norm();
+
+			z3.copy(t0); //z3.mul(y.c);
+			z3.pmul(y.c.getb());
+			z3.times_i();
+
+			t0.copy(z0); t0.neg();
+
+			z1.add(t0);
+			b.copy(z1); 
+			z2.copy(t0);
+
+			t0.copy(a); t0.add(c);
+			t1.copy(y.a); t1.add(y.c);
+
+			t0.norm();
+			t1.norm();
+	
+			t0.mul(t1);
+			z2.add(t0);
+
+			t0.copy(c); 
+			
+			t0.pmul(y.c.getb());
+			t0.times_i();
+
+			t1.copy(t0); t1.neg();
+
+			c.copy(z2); c.add(t1);
+			z3.add(t1);
+			t0.times_i();
+			b.add(t0);
+			z3.norm();
+			z3.times_i();
+			a.copy(z0); a.add(z3);
+		}
+		norm();
+//System.out.println("Out of smul");
+	}
+
+/* this=1/this */
+	public void inverse()
+	{
+		FP4 f0=new FP4(a);
+		FP4 f1=new FP4(b);
+		FP4 f2=new FP4(a);
+		FP4 f3=new FP4(0);
+
+		norm();
+		f0.sqr();
+		f1.mul(c);
+		f1.times_i();
+		f0.sub(f1);
+	f0.norm();
+
+		f1.copy(c); f1.sqr();
+		f1.times_i();
+		f2.mul(b);
+		f1.sub(f2);
+	f1.norm();
+
+		f2.copy(b); f2.sqr();
+		f3.copy(a); f3.mul(c);
+		f2.sub(f3);
+	f2.norm();
+
+		f3.copy(b); f3.mul(f2);
+		f3.times_i();
+		a.mul(f0);
+		f3.add(a);
+		c.mul(f1);
+		c.times_i();
+
+		f3.add(c);
+	f3.norm();
+		f3.inverse();
+		a.copy(f0); a.mul(f3);
+		b.copy(f1); b.mul(f3);
+		c.copy(f2); c.mul(f3);
+	}
+
+/* this=this^p using Frobenius */
+	public void frob(FP2 f)
+	{
+		FP2 f2=new FP2(f);
+		FP2 f3=new FP2(f);
+
+		f2.sqr();
+		f3.mul(f2);
+
+		a.frob(f3);
+		b.frob(f3);
+		c.frob(f3);
+
+		b.pmul(f);
+		c.pmul(f2);
+	}
+
+/* trace function */
+	public FP4 trace()
+	{
+		FP4 t=new FP4(0);
+		t.copy(a);
+		t.imul(3);
+		t.reduce();
+		return t;
+	}
+
+/* convert from byte array to FP12 */
+	public static FP12 fromBytes(byte[] w)
+	{
+		BIG a,b;
+		FP2 c,d;
+		FP4 e,f,g;
+		byte[] t=new byte[BIG.MODBYTES];
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+BIG.MODBYTES];
+		b=BIG.fromBytes(t);
+		c=new FP2(a,b);
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+2*BIG.MODBYTES];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+3*BIG.MODBYTES];
+		b=BIG.fromBytes(t);
+		d=new FP2(a,b);
+
+		e=new FP4(c,d);
+
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+4*BIG.MODBYTES];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+5*BIG.MODBYTES];
+		b=BIG.fromBytes(t);
+		c=new FP2(a,b);
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+6*BIG.MODBYTES];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+7*BIG.MODBYTES];
+		b=BIG.fromBytes(t);
+		d=new FP2(a,b);
+
+		f=new FP4(c,d);
+
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+8*BIG.MODBYTES];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+9*BIG.MODBYTES];
+		b=BIG.fromBytes(t);
+		c=new FP2(a,b);
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+10*BIG.MODBYTES];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+11*BIG.MODBYTES];
+		b=BIG.fromBytes(t);
+		d=new FP2(a,b);
+
+		g=new FP4(c,d);
+
+		return new FP12(e,f,g);
+	}
+
+/* convert this to byte array */
+	public void toBytes(byte[] w)
+	{
+		byte[] t=new byte[BIG.MODBYTES];
+		a.geta().getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i]=t[i];
+		a.geta().getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+BIG.MODBYTES]=t[i];
+		a.getb().getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+2*BIG.MODBYTES]=t[i];
+		a.getb().getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+3*BIG.MODBYTES]=t[i];
+
+		b.geta().getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+4*BIG.MODBYTES]=t[i];
+		b.geta().getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+5*BIG.MODBYTES]=t[i];
+		b.getb().getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+6*BIG.MODBYTES]=t[i];
+		b.getb().getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+7*BIG.MODBYTES]=t[i];
+
+		c.geta().getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+8*BIG.MODBYTES]=t[i];
+		c.geta().getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+9*BIG.MODBYTES]=t[i];
+		c.getb().getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+10*BIG.MODBYTES]=t[i];
+		c.getb().getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+11*BIG.MODBYTES]=t[i];
+	}
+
+/* convert to hex string */
+	public String toString() 
+	{
+		return ("["+a.toString()+","+b.toString()+","+c.toString()+"]");
+	}
+
+/* this=this^e */ 
+/* Note this is simple square and multiply, so not side-channel safe */
+	public FP12 pow(BIG e)
+	{
+		//norm();
+		BIG e1=new BIG(e);
+		e1.norm();
+		BIG e3=new BIG(e1);
+		e3.pmul(3);
+		e3.norm();
+
+		FP12 sf=new FP12(this);
+		sf.norm();
+		FP12 w=new FP12(sf);
+
+		int nb=e3.nbits();
+		for (int i=nb-2;i>=1;i--)
+		{
+			w.usqr();
+			int bt=e3.bit(i)-e1.bit(i);
+			if (bt==1)
+				w.mul(sf);
+			if (bt==-1)
+			{
+				sf.conj(); w.mul(sf); sf.conj();
+			}
+		}
+		w.reduce();
+		return w;
+
+
+/*
+		BIG z=new BIG(e);
+		FP12 r=new FP12(1);
+
+		while (true)
+		{
+			int bt=z.parity();
+			z.fshr(1);
+			if (bt==1) r.mul(w);
+			if (z.iszilch()) break;
+			w.usqr();
+		}
+		r.reduce();
+		return r; */
+	}
+
+/* constant time powering by small integer of max length bts */
+	public void pinpow(int e,int bts)
+	{
+		int i,b;
+		FP12 [] R=new FP12[2];
+		R[0]=new FP12(1);
+		R[1]=new FP12(this);
+		for (i=bts-1;i>=0;i--)
+		{
+			b=(e>>i)&1;
+			R[1-b].mul(R[b]);
+			R[b].usqr();
+		}
+		this.copy(R[0]);
+	}
+
+	public FP4 compow(BIG e,BIG r)
+	{
+		FP12 g1=new FP12(0);
+		FP12 g2=new FP12(0);
+		FP2 f=new FP2(new BIG(ROM.Fra),new BIG(ROM.Frb));
+		BIG q=new BIG(ROM.Modulus);
+
+		BIG m=new BIG(q);
+		m.mod(r);
+
+		BIG a=new BIG(e);
+		a.mod(m);
+
+		BIG b=new BIG(e);
+		b.div(m);
+
+		g1.copy(this);
+		g2.copy(this);
+
+		FP4 c=g1.trace();
+
+		if (b.iszilch())
+		{
+			c=c.xtr_pow(e);
+			return c;
+		}
+
+		g2.frob(f);
+		FP4 cp=g2.trace();
+		g1.conj();
+		g2.mul(g1);
+		FP4 cpm1=g2.trace();
+		g2.mul(g1);
+		FP4 cpm2=g2.trace();
+
+		c=c.xtr_pow2(cp,cpm1,cpm2,a,b);
+
+		return c;
+	}
+
+/* p=q0^u0.q1^u1.q2^u2.q3^u3 */
+// Bos & Costello https://eprint.iacr.org/2013/458.pdf
+// Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
+// Side channel attack secure 
+
+	public static FP12 pow4(FP12[] q,BIG[] u)
+	{
+		int i,j,nb,pb;
+		FP12 [] g=new FP12[8];
+		FP12 r=new FP12(1);
+		FP12 p=new FP12(0);
+		BIG [] t=new BIG[4];
+		BIG mt=new BIG(0);
+		byte[] w=new byte[BIG.NLEN*BIG.BASEBITS+1];
+		byte[] s=new byte[BIG.NLEN*BIG.BASEBITS+1];
+
+		for (i=0;i<4;i++)
+		{
+			t[i]=new BIG(u[i]);
+			t[i].norm();
+		}
+		g[0]=new FP12(q[0]);  // q[0]
+		g[1]=new FP12(g[0]); g[1].mul(q[1]); // q[0].q[1]
+		g[2]=new FP12(g[0]); g[2].mul(q[2]); // q[0].q[2]
+		g[3]=new FP12(g[1]); g[3].mul(q[2]); // q[0].q[1].q[2]
+		g[4]=new FP12(q[0]); g[4].mul(q[3]); // q[0].q[3]
+		g[5]=new FP12(g[1]); g[5].mul(q[3]); // q[0].q[1].q[3]
+		g[6]=new FP12(g[2]); g[6].mul(q[3]); // q[0].q[2].q[3]
+		g[7]=new FP12(g[3]); g[7].mul(q[3]); // q[0].q[1].q[2].q[3]
+
+    // Make it odd
+        pb=1-t[0].parity();
+        t[0].inc(pb);
+        t[0].norm();
+
+    // Number of bits
+        mt.zero();
+        for (i=0;i<4;i++) {
+            mt.or(t[i]); 
+        }
+        nb=1+mt.nbits();
+
+    // Sign pivot 
+        s[nb-1]=1;
+        for (i=0;i<nb-1;i++) {
+            t[0].fshr(1);
+            s[i]=(byte)(2*t[0].parity()-1);
+        }
+
+    // Recoded exponent
+        for (i=0; i<nb; i++) {
+            w[i]=0;
+            int k=1;
+            for (j=1; j<4; j++) {
+                byte bt=(byte)(s[i]*t[j].parity());
+                t[j].fshr(1);
+                t[j].dec((int)(bt)>>1);
+                t[j].norm();
+                w[i]+=bt*(byte)k;
+                k*=2;
+            }
+        } 
+
+     // Main loop
+        p.select(g,(int)(2*w[nb-1]+1)); 
+        for (i=nb-2;i>=0;i--) {
+            p.usqr();
+            r.select(g,(int)(2*w[i]+s[i]));
+            p.mul(r);
+        }
+
+    // apply correction
+        r.copy(q[0]); r.conj();   
+        r.mul(p);
+        p.cmove(r,pb);
+
+ 		p.reduce();
+		return p;
+	}              
+
+/* p=q0^u0.q1^u1.q2^u2.q3^u3 */
+/* Timing attack secure, but not cache attack secure */
+/*
+	public static FP12 pow4(FP12[] q,BIG[] u)
+	{
+		int i,j,nb,m;
+		int[] a=new int[4];
+		FP12 [] g=new FP12[8];
+		FP12 [] s=new FP12[2];
+		FP12 c=new FP12(1);
+		FP12 p=new FP12(0);
+		BIG [] t=new BIG[4];
+		BIG mt=new BIG(0);
+		byte[] w=new byte[BIG.NLEN*BIG.BASEBITS+1];
+
+		for (i=0;i<4;i++)
+			t[i]=new BIG(u[i]);
+
+		s[0]=new FP12(0);
+		s[1]=new FP12(0);
+
+		g[0]=new FP12(q[0]); s[0].copy(q[1]); s[0].conj(); g[0].mul(s[0]);
+		g[1]=new FP12(g[0]);
+		g[2]=new FP12(g[0]);
+		g[3]=new FP12(g[0]);
+		g[4]=new FP12(q[0]); g[4].mul(q[1]);
+		g[5]=new FP12(g[4]);
+		g[6]=new FP12(g[4]);
+		g[7]=new FP12(g[4]);
+
+		s[1].copy(q[2]); s[0].copy(q[3]); s[0].conj(); s[1].mul(s[0]);
+		s[0].copy(s[1]); s[0].conj(); g[1].mul(s[0]);
+		g[2].mul(s[1]);
+		g[5].mul(s[0]);
+		g[6].mul(s[1]);
+		s[1].copy(q[2]); s[1].mul(q[3]);
+		s[0].copy(s[1]); s[0].conj(); g[0].mul(s[0]);
+		g[3].mul(s[1]);
+		g[4].mul(s[0]);
+		g[7].mul(s[1]);
+
+// if power is even add 1 to power, and add q to correction 
+
+		for (i=0;i<4;i++)
+		{
+			if (t[i].parity()==0)
+			{
+				t[i].inc(1); t[i].norm();
+				c.mul(q[i]);
+			}
+			mt.add(t[i]); mt.norm();
+		}
+		c.conj();
+		nb=1+mt.nbits();
+
+// convert exponent to signed 1-bit window 
+		for (j=0;j<nb;j++)
+		{
+			for (i=0;i<4;i++)
+			{
+				a[i]=(t[i].lastbits(2)-2);
+				t[i].dec(a[i]); t[i].norm(); 
+				t[i].fshr(1);
+			}
+			w[j]=(byte)(8*a[0]+4*a[1]+2*a[2]+a[3]);
+		}
+		w[nb]=(byte)(8*t[0].lastbits(2)+4*t[1].lastbits(2)+2*t[2].lastbits(2)+t[3].lastbits(2));
+		p.copy(g[(w[nb]-1)/2]);  
+
+		for (i=nb-1;i>=0;i--)
+		{
+			m=w[i]>>7;
+			j=(w[i]^m)-m;  // j=abs(w[i]) 
+			j=(j-1)/2;
+			s[0].copy(g[j]); s[1].copy(g[j]); s[1].conj();
+			p.usqr();
+			p.mul(s[m&1]);
+		}
+		p.mul(c);  // apply correction 
+		p.reduce();
+		return p;
+	}
+*/
+/*
+	public static void main(String[] args) {
+		BIG p=new BIG(ROM.Modulus);
+		FP2 w0,w1;
+		BIG a=new BIG(0);
+		BIG b=new BIG(0);
+		
+		a.zero(); b.zero(); a.inc(1); b.inc(2);
+		w0=new FP2(a,b);
+		a.zero(); b.zero(); a.inc(3); b.inc(4);
+		w1=new FP2(a,b);
+		FP4 t0=new FP4(w0,w1);
+
+		a.zero(); b.zero(); a.inc(5); b.inc(6);
+		w0=new FP2(a,b);
+		a.zero(); b.zero(); a.inc(7); b.inc(8);
+		w1=new FP2(a,b);
+		FP4 t1=new FP4(w0,w1);
+
+		a.zero(); b.zero(); a.inc(9); b.inc(10);
+		w0=new FP2(a,b);
+		a.zero(); b.zero(); a.inc(11); b.inc(12);
+		w1=new FP2(a,b);
+		FP4 t2=new FP4(w0,w1);
+
+		FP12 w=new FP12(t0,t1,t2);
+		FP12 t=new FP12(w);
+
+		System.out.println("w= "+w.toString());
+
+		a=new BIG(ROM_ZZZ.CURVE_Fra);
+		b=new BIG(ROM_ZZZ.CURVE_Frb);
+
+		FP2 f=new FP2(a,b);
+
+		w.frob(f);
+		System.out.println("w= "+w.toString());
+
+		w=t.pow(p);
+
+		System.out.println("w= "+w.toString());
+
+		w.inverse();
+
+		System.out.println("1/w= "+w.toString());
+
+		w.inverse();
+
+		System.out.println("w= "+w.toString());
+
+		t.copy(w);
+		w.conj();
+		t.inverse();
+		w.mul(t);
+
+		System.out.println("w^(p^6-1)= "+w.toString());
+
+		t.copy(w);
+		w.frob(f);
+		w.frob(f);
+		w.mul(t);
+
+		System.out.println("w^(p^6-1)(p^2+1)= "+w.toString());
+
+		t.copy(w);
+
+		t.inverse();
+		w.conj();
+
+		System.out.println("w= "+w.toString());
+		System.out.println("t= "+t.toString());
+	} */
+}
diff --git a/version3/java/FP16.java b/version3/java/FP16.java
new file mode 100644
index 0000000..30c66c6
--- /dev/null
+++ b/version3/java/FP16.java
@@ -0,0 +1,565 @@
+/*
+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.
+*/
+
+/* Finite Field arithmetic  Fp^16 functions */
+
+/* FP16 elements are of the form a+ib, where i is sqrt(sqrt(sqrt(-1+sqrt(-1))))  */
+
+package org.apache.milagro.amcl.XXX;
+
+public final class FP16 {
+	private final FP8 a;
+	private final FP8 b;
+/* reduce all components of this mod Modulus */
+	public void reduce()
+	{
+		a.reduce();
+		b.reduce();
+	}
+/* normalise all components of this mod Modulus */
+	public void norm()
+	{
+		a.norm();
+		b.norm();
+	}
+/* test this==0 ? */
+	public boolean iszilch() {
+		//reduce();
+		return (a.iszilch() && b.iszilch());
+	}
+
+	public void cmove(FP16 g,int d)
+	{
+		a.cmove(g.a,d);
+		b.cmove(g.b,d);
+	}
+
+/* test this==1 ? */
+	public boolean isunity() {
+		FP8 one=new FP8(1);
+		return (a.equals(one) && b.iszilch());
+	}
+
+/* test is w real? That is in a+ib test b is zero */
+	public boolean isreal()
+	{
+		return b.iszilch();
+	}
+/* extract real part a */
+	public FP8 real()
+	{
+		return a;
+	}
+
+	public FP8 geta()
+	{
+		return a;
+	}
+/* extract imaginary part b */
+	public FP8 getb()
+	{
+		return b;
+	}
+/* test this=x? */
+	public boolean equals(FP16 x)
+	{
+		return (a.equals(x.a) && b.equals(x.b));
+	}
+/* constructors */
+	public FP16(int c)
+	{
+		a=new FP8(c);
+		b=new FP8(0);
+	}
+
+	public FP16(FP16 x)
+	{
+		a=new FP8(x.a);
+		b=new FP8(x.b);
+	}
+
+	public FP16(FP8 c,FP8 d)
+	{
+		a=new FP8(c);
+		b=new FP8(d);
+	}
+
+	public FP16(FP8 c)
+	{
+		a=new FP8(c);
+		b=new FP8(0);
+	}
+/* copy this=x */
+	public void copy(FP16 x)
+	{
+		a.copy(x.a);
+		b.copy(x.b);
+	}
+/* set this=0 */
+	public void zero()
+	{
+		a.zero();
+		b.zero();
+	}
+
+/* set this=1 */
+	public void one()
+	{
+		a.one();
+		b.zero();
+	}
+/* set this=-this */
+	public void neg()
+	{
+		norm();
+		FP8 m=new FP8(a);
+		FP8 t=new FP8(0);
+		m.add(b);
+		m.neg();
+		t.copy(m); t.add(b);
+		b.copy(m);
+		b.add(a);
+		a.copy(t);
+	norm();
+	}
+
+/* this=conjugate(this) */
+	public void conj()
+	{
+		b.neg(); norm();
+	}
+/* this=-conjugate(this) */
+	public void nconj()
+	{
+		a.neg(); norm();
+	}
+/* this+=x */
+	public void add(FP16 x)
+	{
+		a.add(x.a);
+		b.add(x.b);
+	}
+/* this-=x */
+	public void sub(FP16 x)
+	{
+		FP16 m=new FP16(x);
+		m.neg();
+		add(m);
+	}
+
+/* this=x-this */
+	public void rsub(FP16 x)
+	{
+		neg();
+		add(x);
+	}
+
+/* this*=s where s is FP8 */
+	public void pmul(FP8 s)
+	{
+		a.mul(s);
+		b.mul(s);
+	}
+/* this*=s where s is FP2 */
+	public void qmul(FP2 s)
+	{
+		a.qmul(s);
+		b.qmul(s);
+	}
+
+/* this*=c where c is int */
+	public void imul(int c)
+	{
+		a.imul(c);
+		b.imul(c);
+	}
+
+/* this*=this */	
+	public void sqr()
+	{
+//		norm();
+
+		FP8 t1=new FP8(a);
+		FP8 t2=new FP8(b);
+		FP8 t3=new FP8(a);
+
+		t3.mul(b);
+		t1.add(b);
+		t2.times_i();
+
+		t2.add(a);
+
+		t1.norm();
+		t2.norm();
+
+		a.copy(t1);
+
+		a.mul(t2);
+
+		t2.copy(t3);
+		t2.times_i();
+		t2.add(t3);
+		t2.norm();
+		t2.neg();
+		a.add(t2);
+
+		b.copy(t3);
+		b.add(t3);
+
+		norm();
+	}
+
+/* this*=y */
+	public void mul(FP16 y)
+	{
+//		norm();
+
+		FP8 t1=new FP8(a);
+		FP8 t2=new FP8(b);
+		FP8 t3=new FP8(0);
+		FP8 t4=new FP8(b);
+
+		t1.mul(y.a);
+		t2.mul(y.b);
+		t3.copy(y.b);
+		t3.add(y.a);
+		t4.add(a);
+
+		t3.norm();
+		t4.norm();
+
+		t4.mul(t3);
+
+		t3.copy(t1);
+		t3.neg();
+		t4.add(t3);
+		t4.norm();
+
+		t3.copy(t2);
+		t3.neg();
+		b.copy(t4);
+		b.add(t3);
+
+		t2.times_i();
+		a.copy(t2);
+		a.add(t1);
+
+		norm();
+	}
+
+/* convert this to hex string */
+	public String toString() 
+	{
+		return ("["+a.toString()+","+b.toString()+"]");
+	}
+
+/* this=1/this */
+	public void inverse()
+	{
+//		norm();
+
+		FP8 t1=new FP8(a);
+		FP8 t2=new FP8(b);
+
+		t1.sqr();
+		t2.sqr();
+		t2.times_i();
+		t2.norm();
+		t1.sub(t2); t1.norm();
+		t1.inverse();
+		a.mul(t1);
+		t1.neg();
+		t1.norm();
+		b.mul(t1);
+	}
+
+/* this*=i where i = sqrt(-1+sqrt(-1)) */
+	public void times_i()
+	{
+//		norm();
+		FP8 s=new FP8(b);
+		FP8 t=new FP8(a);
+		s.times_i();
+		b.copy(t);
+		a.copy(s);
+		norm();
+	}
+
+	public void times_i2()
+	{
+		a.times_i();
+		b.times_i();
+	}
+
+	public void times_i4()
+	{
+		a.times_i2();
+		b.times_i2();
+	}
+
+/* this=this^p using Frobenius */
+	public void frob(FP2 f)
+	{
+		FP2 ff=new FP2(f); ff.sqr(); ff.norm();
+
+		a.frob(ff);
+		b.frob(ff);
+		b.qmul(f);
+		b.times_i();
+	}
+
+/* this=this^e */
+	public FP16 pow(BIG e)
+	{
+		FP16 w=new FP16(this);
+		w.norm();
+		BIG z=new BIG(e);
+		FP16 r=new FP16(1);
+		z.norm();
+		while (true)
+		{
+			int bt=z.parity();
+			z.fshr(1);
+			if (bt==1) r.mul(w);
+			if (z.iszilch()) break;
+			w.sqr();
+		}
+		r.reduce();
+		return r;
+	}
+
+/* XTR xtr_a function */
+	public void xtr_A(FP16 w,FP16 y,FP16 z) 
+	{
+		FP16 r=new FP16(w);
+		FP16 t=new FP16(w);
+	
+		r.sub(y);
+		r.norm();
+		r.pmul(a);
+		t.add(y);
+		t.norm();
+		t.pmul(b);
+		t.times_i();
+
+		copy(r);
+		add(t);
+		add(z);
+
+		norm();
+	}
+
+/* XTR xtr_d function */
+	public void xtr_D() {
+		FP16 w=new FP16(this);
+		sqr(); w.conj();
+		w.add(w);
+		w.norm();
+		sub(w);
+		reduce();
+	}
+
+/* r=x^n using XTR method on traces of FP12s */
+	public FP16 xtr_pow(BIG n) {
+		FP16 sf=new FP16(this);
+		sf.norm();
+		FP16 a=new FP16(3);
+		FP16 b=new FP16(sf);
+		FP16 c=new FP16(b);
+		c.xtr_D();
+		FP16 t=new FP16(0);
+		FP16 r=new FP16(0);
+
+		
+		int par=n.parity();
+		BIG v=new BIG(n); v.norm(); v.fshr(1);
+		if (par==0) {v.dec(1); v.norm();}
+
+		int nb=v.nbits();
+		for (int i=nb-1;i>=0;i--)
+		{
+			if (v.bit(i)!=1)
+			{
+				t.copy(b);
+				sf.conj();
+				c.conj();
+				b.xtr_A(a,sf,c);
+				sf.conj();
+				c.copy(t);
+				c.xtr_D();
+				a.xtr_D();
+			}
+			else
+			{
+				t.copy(a); t.conj();
+				a.copy(b);
+				a.xtr_D();
+				b.xtr_A(c,sf,t);
+				c.xtr_D();
+			}
+		}
+		if (par==0) r.copy(c);
+		else r.copy(b);
+		r.reduce();
+		return r;
+	}
+
+/* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */
+	public FP16 xtr_pow2(FP16 ck,FP16 ckml,FP16 ckm2l,BIG a,BIG b)
+	{
+
+		BIG e=new BIG(a);
+		BIG d=new BIG(b);
+		BIG w=new BIG(0);
+		d.norm(); d.norm();
+		FP16 cu=new FP16(ck);  // can probably be passed in w/o copying
+		FP16 cv=new FP16(this);
+		FP16 cumv=new FP16(ckml);
+		FP16 cum2v=new FP16(ckm2l);
+		FP16 r=new FP16(0);
+		FP16 t=new FP16(0);
+
+		int f2=0;
+		while (d.parity()==0 && e.parity()==0)
+		{
+			d.fshr(1);
+			e.fshr(1);
+			f2++;
+		}
+
+		while (BIG.comp(d,e)!=0)
+		{
+			if (BIG.comp(d,e)>0)
+			{
+				w.copy(e); w.imul(4); w.norm();
+				if (BIG.comp(d,w)<=0)
+				{
+					w.copy(d); d.copy(e);
+					e.rsub(w); e.norm();
+
+					t.copy(cv); 
+					t.xtr_A(cu,cumv,cum2v);
+					cum2v.copy(cumv); 
+					cum2v.conj();
+					cumv.copy(cv);
+					cv.copy(cu);
+					cu.copy(t);
+
+				}
+				else if (d.parity()==0)
+				{
+					d.fshr(1);
+					r.copy(cum2v); r.conj();
+					t.copy(cumv);
+					t.xtr_A(cu,cv,r);
+					cum2v.copy(cumv);
+					cum2v.xtr_D();
+					cumv.copy(t);
+					cu.xtr_D();
+				}
+				else if (e.parity()==1)
+				{
+					d.sub(e); d.norm();
+					d.fshr(1);
+					t.copy(cv);
+					t.xtr_A(cu,cumv,cum2v);
+					cu.xtr_D();
+					cum2v.copy(cv);
+					cum2v.xtr_D();
+					cum2v.conj();
+					cv.copy(t);
+				}
+				else
+				{
+					w.copy(d);
+					d.copy(e); d.fshr(1);
+					e.copy(w);
+					t.copy(cumv);
+					t.xtr_D();
+					cumv.copy(cum2v); cumv.conj();
+					cum2v.copy(t); cum2v.conj();
+					t.copy(cv);
+					t.xtr_D();
+					cv.copy(cu);
+					cu.copy(t);
+				}
+			}
+			if (BIG.comp(d,e)<0)
+			{
+				w.copy(d); w.imul(4); w.norm();
+				if (BIG.comp(e,w)<=0)
+				{
+					e.sub(d); e.norm();
+					t.copy(cv);
+					t.xtr_A(cu,cumv,cum2v);
+					cum2v.copy(cumv);
+					cumv.copy(cu);
+					cu.copy(t);
+				}
+				else if (e.parity()==0)
+				{
+					w.copy(d);
+					d.copy(e); d.fshr(1);
+					e.copy(w);
+					t.copy(cumv);
+					t.xtr_D();
+					cumv.copy(cum2v); cumv.conj();
+					cum2v.copy(t); cum2v.conj();
+					t.copy(cv);
+					t.xtr_D();
+					cv.copy(cu);
+					cu.copy(t);
+				}
+				else if (d.parity()==1)
+				{
+					w.copy(e);
+					e.copy(d);
+					w.sub(d); w.norm();
+					d.copy(w); d.fshr(1);
+					t.copy(cv);
+					t.xtr_A(cu,cumv,cum2v);
+					cumv.conj();
+					cum2v.copy(cu);
+					cum2v.xtr_D();
+					cum2v.conj();
+					cu.copy(cv);
+					cu.xtr_D();
+					cv.copy(t);
+				}
+				else
+				{
+					d.fshr(1);
+					r.copy(cum2v); r.conj();
+					t.copy(cumv);
+					t.xtr_A(cu,cv,r);
+					cum2v.copy(cumv);
+					cum2v.xtr_D();
+					cumv.copy(t);
+					cu.xtr_D();
+				}
+			}
+		}
+		r.copy(cv);
+		r.xtr_A(cu,cumv,cum2v);
+		for (int i=0;i<f2;i++)
+			r.xtr_D();
+		r=r.xtr_pow(d);
+		return r;
+	}
+}
diff --git a/version3/java/FP2.java b/version3/java/FP2.java
new file mode 100644
index 0000000..74f4944
--- /dev/null
+++ b/version3/java/FP2.java
@@ -0,0 +1,425 @@
+/*
+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.
+*/
+
+/* Finite Field arithmetic  Fp^2 functions */
+
+/* FP2 elements are of the form a+ib, where i is sqrt(-1) */
+
+package org.apache.milagro.amcl.XXX;
+
+public final class FP2 {
+	private final FP a;
+	private final FP b;
+
+/* reduce components mod Modulus */
+	public void reduce()
+	{
+		a.reduce();
+		b.reduce();
+	}
+
+/* normalise components of w */
+	public void norm()
+	{
+		a.norm();
+		b.norm();
+	}
+
+/* test this=0 ? */
+	public boolean iszilch() {
+		//reduce();
+		return (a.iszilch() && b.iszilch());
+	}
+
+	public void cmove(FP2 g,int d)
+	{
+		a.cmove(g.a,d);
+		b.cmove(g.b,d);
+	}
+
+/* test this=1 ? */
+	public boolean isunity() {
+		FP one=new FP(1);
+		return (a.equals(one) && b.iszilch());
+	}
+
+/* test this=x */
+	public boolean equals(FP2 x) {
+		return (a.equals(x.a) && b.equals(x.b));
+	}
+
+/* Constructors */
+	public FP2(int c)
+	{
+		a=new FP(c);
+		b=new FP(0);
+	}
+
+	public FP2(FP2 x)
+	{
+		a=new FP(x.a);
+		b=new FP(x.b);
+	}
+
+	public FP2(FP c,FP d)
+	{
+		a=new FP(c);
+		b=new FP(d);
+	}
+
+	public FP2(BIG c,BIG d)
+	{
+		a=new FP(c);
+		b=new FP(d);
+	}
+
+	public FP2(FP c)
+	{
+		a=new FP(c);
+		b=new FP(0);
+	}
+
+	public FP2(BIG c)
+	{
+		a=new FP(c);
+		b=new FP(0);
+	}
+/*
+	public BIG geta()
+	{
+		return a.tobig();
+	}
+*/
+/* extract a */
+	public BIG getA()
+	{ 
+		return a.redc();
+	}
+
+/* extract b */
+	public BIG getB()
+	{
+		return b.redc();
+	}
+
+/* copy this=x */
+	public void copy(FP2 x)
+	{
+		a.copy(x.a);
+		b.copy(x.b);
+	}
+
+/* set this=0 */
+	public void zero()
+	{
+		a.zero();
+		b.zero();
+	}
+
+/* set this=1 */
+	public void one()
+	{
+		a.one();
+		b.zero();
+	}
+
+/* negate this mod Modulus */
+	public void neg()
+	{
+		FP m=new FP(a);
+		FP t=new FP(0);
+
+		m.add(b);
+		m.neg();
+		t.copy(m); t.add(b);
+		b.copy(m);
+		b.add(a);
+		a.copy(t);
+	}
+
+/* set to a-ib */
+	public void conj()
+	{
+		b.neg();
+		b.norm();
+	}
+
+/* this+=a */
+	public void add(FP2 x)
+	{
+		a.add(x.a);
+		b.add(x.b);
+	}
+
+/* this-=a */
+	public void sub(FP2 x)
+	{
+		FP2 m=new FP2(x);
+		m.neg();
+		add(m);
+	}
+
+	public void rsub(FP2 x)       // *****
+	{
+		neg();
+		add(x);
+	}
+
+/* this*=s, where s is an FP */
+	public void pmul(FP s)
+	{
+		a.mul(s);
+		b.mul(s);
+	}
+
+/* this*=i, where i is an int */
+	public void imul(int c)
+	{
+		a.imul(c);
+		b.imul(c);
+	}
+
+/* this*=this */
+	public void sqr()
+	{
+		FP w1=new FP(a);
+		FP w3=new FP(a);
+		FP mb=new FP(b);
+
+		w1.add(b);
+		mb.neg();
+
+		w3.add(a);
+		w3.norm();
+		b.mul(w3);
+
+		a.add(mb);
+
+		w1.norm();
+		a.norm();
+
+		a.mul(w1);
+	}
+
+/* this*=y */
+/* Now uses Lazy reduction */
+	public void mul(FP2 y)
+	{
+		if ((long)(a.XES+b.XES)*(y.a.XES+y.b.XES)>(long)FP.FEXCESS)
+		{
+			if (a.XES>1) a.reduce();
+			if (b.XES>1) b.reduce();		
+		}
+
+		DBIG pR=new DBIG(0);
+		BIG C=new BIG(a.x);
+		BIG D=new BIG(y.a.x);
+
+		pR.ucopy(new BIG(ROM.Modulus));
+
+		DBIG A=BIG.mul(a.x,y.a.x);
+		DBIG B=BIG.mul(b.x,y.b.x);
+
+		C.add(b.x); C.norm();
+		D.add(y.b.x); D.norm();
+
+		DBIG E=BIG.mul(C,D);
+		DBIG F=new DBIG(A); F.add(B);
+		B.rsub(pR);
+
+		A.add(B); A.norm();
+		E.sub(F); E.norm();
+
+		a.x.copy(FP.mod(A)); a.XES=3;
+		b.x.copy(FP.mod(E)); b.XES=2;
+	}
+
+/* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */
+/* returns true if this is QR */
+	public boolean sqrt()
+	{
+		if (iszilch()) return true;
+		FP w1=new FP(b);
+		FP w2=new FP(a);
+		w1.sqr(); w2.sqr(); w1.add(w2);
+		if (w1.jacobi()!=1) { zero(); return false; }
+		w1=w1.sqrt();
+		w2.copy(a); w2.add(w1); 
+		w2.norm(); w2.div2();
+		if (w2.jacobi()!=1)
+		{
+			w2.copy(a); w2.sub(w1); 
+			w2.norm(); w2.div2();
+			if (w2.jacobi()!=1) { zero(); return false; }
+		}
+		w2=w2.sqrt();
+		a.copy(w2);
+		w2.add(w2);
+		w2.inverse();
+		b.mul(w2);
+		return true;
+	}
+
+/* output to hex string */
+	public String toString() 
+	{
+		return ("["+a.toString()+","+b.toString()+"]");
+	}
+
+	public String toRawString() 
+	{
+		return ("["+a.toRawString()+","+b.toRawString()+"]");
+	}
+
+/* this=1/this */
+	public void inverse()
+	{
+		norm();
+		FP w1=new FP(a);
+		FP w2=new FP(b);
+
+		w1.sqr();
+		w2.sqr();
+		w1.add(w2);
+		w1.inverse();
+		a.mul(w1);
+		w1.neg();
+		w1.norm();
+		b.mul(w1);
+	}
+
+/* this/=2 */
+	public void div2()
+	{
+		a.div2();
+		b.div2();
+	}
+
+/* this*=sqrt(-1) */
+	public void times_i()
+	{
+		FP z=new FP(a);
+		a.copy(b); a.neg();
+		b.copy(z);
+	}
+
+/* w*=(1+sqrt(-1)) */
+/* where X*2-(1+sqrt(-1)) is irreducible for FP4, assumes p=3 mod 8 */
+	public void mul_ip()
+	{
+		FP2 t=new FP2(this);
+		FP z=new FP(a);
+		a.copy(b);
+		a.neg();
+		b.copy(z);
+		add(t);
+	}
+
+	public void div_ip2()
+	{
+		FP2 t=new FP2(0);
+		norm();
+		t.a.copy(a); t.a.add(b);
+		t.b.copy(b); t.b.sub(a);
+		copy(t);
+		norm();
+	}
+
+/* w/=(1+sqrt(-1)) */
+	public void div_ip()
+	{
+		FP2 t=new FP2(0);
+		norm();
+		t.a.copy(a); t.a.add(b);
+		t.b.copy(b); t.b.sub(a);
+		copy(t);
+		norm();
+		div2();
+	}
+/*
+	public FP2 pow(BIG e)
+	{
+		int bt;
+		FP2 r=new FP2(1);
+		e.norm();
+		norm();
+		while (true)
+		{
+			bt=e.parity();
+			e.fshr(1);
+			if (bt==1) r.mul(this);
+			if (e.iszilch()) break;
+			sqr();
+		}
+
+		r.reduce();
+		return r;
+	}
+
+	public static void main(String[] args) {
+		BIG m=new BIG(ROM.Modulus);
+		BIG x=new BIG(3);
+		BIG e=new BIG(27);
+		BIG pp1=new BIG(m);
+		BIG pm1=new BIG(m);
+		BIG a=new BIG(1);
+		BIG b=new BIG(1);
+		FP2 w=new FP2(a,b);
+		FP2 z=new FP2(w);
+
+		byte[] RAW=new byte[100];
+
+		RAND rng=new RAND();
+		for (int i=0;i<100;i++) RAW[i]=(byte)(i);
+
+		rng.seed(100,RAW);
+
+	//	for (int i=0;i<100;i++)
+	//	{
+			a.randomnum(rng);
+			b.randomnum(rng);
+
+			w=new FP2(a,b);
+			System.out.println("w="+w.toString());
+
+			z=new FP2(w);
+			z.inverse();
+			System.out.println("z="+z.toString());
+
+			z.inverse();
+			if (!z.equals(w)) System.out.println("Error");
+	//	}
+
+//		System.out.println("m="+m.toString());
+//		w.sqr();
+//		w.mul(z);
+
+		System.out.println("w="+w.toString());
+
+
+		pp1.inc(1); pp1.norm();
+		pm1.dec(1); pm1.norm();
+		System.out.println("p+1="+pp1.toString());
+		System.out.println("p-1="+pm1.toString());
+		w=w.pow(pp1);
+		w=w.pow(pm1);
+		System.out.println("w="+w.toString());
+	}
+*/
+}
\ No newline at end of file
diff --git a/version3/java/FP24.java b/version3/java/FP24.java
new file mode 100644
index 0000000..b657497
--- /dev/null
+++ b/version3/java/FP24.java
@@ -0,0 +1,854 @@
+/*
+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.
+*/
+
+/* AMCL Fp^24 functions */
+/* FP24 elements are of the form a+i.b+i^2.c */
+
+package org.apache.milagro.amcl.XXX;
+
+public final class FP24 {
+	private final FP8 a;
+	private final FP8 b;
+	private final FP8 c;
+/* reduce all components of this mod Modulus */
+	public void reduce()
+	{
+		a.reduce();
+		b.reduce();
+		c.reduce();
+	}
+
+/* normalise all components of this */
+	public void norm()
+	{
+		a.norm();
+		b.norm();
+		c.norm();
+	}
+/* test x==0 ? */
+	public boolean iszilch() {
+		//reduce();
+		return (a.iszilch() && b.iszilch() && c.iszilch());
+	}
+
+	public void cmove(FP24 g,int d)
+	{
+		a.cmove(g.a,d);
+		b.cmove(g.b,d);
+		c.cmove(g.c,d);		
+	}
+
+
+/* return 1 if b==c, no branching */
+	public static int teq(int b,int c)
+	{
+		int x=b^c;
+		x-=1;  // if x=0, x now -1
+		return ((x>>31)&1);
+	}
+
+/* Constant time select from pre-computed table */
+	public void select(FP24 g[],int b)
+	{
+		int m=b>>31;
+		int babs=(b^m)-m;
+
+		babs=(babs-1)/2;
+
+		cmove(g[0],teq(babs,0));  // conditional move
+		cmove(g[1],teq(babs,1));
+		cmove(g[2],teq(babs,2));
+		cmove(g[3],teq(babs,3));
+		cmove(g[4],teq(babs,4));
+		cmove(g[5],teq(babs,5));
+		cmove(g[6],teq(babs,6));
+		cmove(g[7],teq(babs,7));
+ 
+		FP24 invf=new FP24(this); 
+		invf.conj();
+		cmove(invf,(int)(m&1));
+	}
+
+	/* test x==1 ? */
+	public boolean isunity() {
+		FP8 one=new FP8(1);
+		return (a.equals(one) && b.iszilch() && c.iszilch());
+	}
+/* return 1 if x==y, else 0 */
+	public boolean equals(FP24 x)
+	{
+		return (a.equals(x.a) && b.equals(x.b) && c.equals(x.c));
+	}
+/* extract a from this */
+	public FP8 geta()
+	{
+		return a;
+	}
+/* extract b */
+	public FP8 getb()
+	{
+		return b;
+	}
+/* extract c */
+	public FP8 getc()
+	{
+		return c;
+	}
+/* copy this=x */
+	public void copy(FP24 x)
+	{
+		a.copy(x.a);
+		b.copy(x.b);
+		c.copy(x.c);
+	}
+/* set this=1 */
+	public void one()
+	{
+		a.one();
+		b.zero();
+		c.zero();
+	}
+/* this=conj(this) */
+	public void conj()
+	{
+		a.conj();
+		b.nconj();
+		c.conj();
+	}
+/* Constructors */
+	public FP24(FP8 d)
+	{
+		a=new FP8(d);
+		b=new FP8(0);
+		c=new FP8(0);
+	}
+
+	public FP24(int d)
+	{
+		a=new FP8(d);
+		b=new FP8(0);
+		c=new FP8(0);
+	}
+
+	public FP24(FP8 d,FP8 e,FP8 f)
+	{
+		a=new FP8(d);
+		b=new FP8(e);
+		c=new FP8(f);
+	}
+
+	public FP24(FP24 x)
+	{
+		a=new FP8(x.a);
+		b=new FP8(x.b);
+		c=new FP8(x.c);
+	}
+
+/* Granger-Scott Unitary Squaring */
+	public void usqr()
+	{
+//System.out.println("Into usqr");
+		FP8 A=new FP8(a);
+		FP8 B=new FP8(c);
+		FP8 C=new FP8(b);
+		FP8 D=new FP8(0);
+
+		a.sqr();
+		D.copy(a); D.add(a);
+		a.add(D);
+
+		a.norm();
+		A.nconj();
+
+		A.add(A);
+		a.add(A);
+		B.sqr();
+		B.times_i();
+
+		D.copy(B); D.add(B);
+		B.add(D);
+		B.norm();
+
+		C.sqr();
+		D.copy(C); D.add(C);
+		C.add(D);
+		C.norm();
+
+		b.conj();
+		b.add(b);
+		c.nconj();
+
+		c.add(c);
+		b.add(B);
+		c.add(C);
+		reduce();
+	}
+
+/* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
+	public void sqr()
+	{
+		FP8 A=new FP8(a);
+		FP8 B=new FP8(b);
+		FP8 C=new FP8(c);
+		FP8 D=new FP8(a);
+
+		A.sqr();
+		B.mul(c);
+		B.add(B);
+	B.norm();
+		C.sqr();
+		D.mul(b);
+		D.add(D);
+
+		c.add(a);
+		c.add(b);
+	c.norm();
+		c.sqr();
+
+		a.copy(A);
+
+		A.add(B);
+		A.norm();
+		A.add(C);
+		A.add(D);
+		A.norm();
+
+		A.neg();
+		B.times_i();
+		C.times_i();
+
+		a.add(B);
+
+		b.copy(C); b.add(D);
+		c.add(A);
+
+		norm();
+	}
+
+/* FP12 full multiplication this=this*y */
+	public void mul(FP24 y)
+	{
+//System.out.println("Into mul");
+		FP8 z0=new FP8(a);
+		FP8 z1=new FP8(0);
+		FP8 z2=new FP8(b);
+		FP8 z3=new FP8(0);
+		FP8 t0=new FP8(a);
+		FP8 t1=new FP8(y.a);
+
+		z0.mul(y.a);
+		z2.mul(y.b);
+
+		t0.add(b);
+		t1.add(y.b);
+
+	t0.norm();
+	t1.norm();
+
+		z1.copy(t0); z1.mul(t1);
+		t0.copy(b); t0.add(c);
+
+		t1.copy(y.b); t1.add(y.c);
+
+	t0.norm();
+	t1.norm();
+
+		z3.copy(t0); z3.mul(t1);
+
+		t0.copy(z0); t0.neg();
+		t1.copy(z2); t1.neg();
+
+		z1.add(t0);
+		//z1.norm();
+		b.copy(z1); b.add(t1);
+
+		z3.add(t1);
+		z2.add(t0);
+
+		t0.copy(a); t0.add(c);
+		t1.copy(y.a); t1.add(y.c);
+
+t0.norm();
+t1.norm();
+	
+		t0.mul(t1);
+		z2.add(t0);
+
+		t0.copy(c); t0.mul(y.c);
+		t1.copy(t0); t1.neg();
+
+		c.copy(z2); c.add(t1);
+		z3.add(t1);
+		t0.times_i();
+		b.add(t0);
+	z3.norm();
+		z3.times_i();
+		a.copy(z0); a.add(z3);
+		norm();
+
+	}
+
+/* Special case of multiplication arises from special form of ATE pairing line function */
+	public void smul(FP24 y,int type)
+	{
+		if (type==ECP.D_TYPE)
+		{
+			FP8 z0=new FP8(a);
+			FP8 z2=new FP8(b);
+			FP8 z3=new FP8(b);
+			FP8 t0=new FP8(0);
+			FP8 t1=new FP8(y.a);
+			z0.mul(y.a);
+			z2.pmul(y.b.real());
+			b.add(a);
+			t1.real().add(y.b.real());
+
+			t1.norm();
+			b.norm();
+			b.mul(t1);
+			z3.add(c);
+			z3.norm();
+			z3.pmul(y.b.real());
+
+			t0.copy(z0); t0.neg();
+			t1.copy(z2); t1.neg();
+
+			b.add(t0);
+
+			b.add(t1);
+			z3.add(t1);
+			z2.add(t0);
+
+			t0.copy(a); t0.add(c);
+			t0.norm();
+			z3.norm();
+			t0.mul(y.a);
+			c.copy(z2); c.add(t0);
+
+			z3.times_i();
+			a.copy(z0); a.add(z3);
+		}
+		if (type==ECP.M_TYPE)
+		{
+			FP8 z0=new FP8(a);
+			FP8 z1=new FP8(0);
+			FP8 z2=new FP8(0);
+			FP8 z3=new FP8(0);
+			FP8 t0=new FP8(a);
+			FP8 t1=new FP8(0);
+		
+			z0.mul(y.a);
+			t0.add(b);
+			t0.norm();
+
+			z1.copy(t0); z1.mul(y.a);
+			t0.copy(b); t0.add(c);
+			t0.norm();
+
+			z3.copy(t0); //z3.mul(y.c);
+			z3.pmul(y.c.getb());
+			z3.times_i();
+
+			t0.copy(z0); t0.neg();
+
+			z1.add(t0);
+			b.copy(z1); 
+			z2.copy(t0);
+
+			t0.copy(a); t0.add(c);
+			t1.copy(y.a); t1.add(y.c);
+
+			t0.norm();
+			t1.norm();
+	
+			t0.mul(t1);
+			z2.add(t0);
+
+			t0.copy(c); 
+			
+			t0.pmul(y.c.getb());
+			t0.times_i();
+
+			t1.copy(t0); t1.neg();
+
+			c.copy(z2); c.add(t1);
+			z3.add(t1);
+			t0.times_i();
+			b.add(t0);
+			z3.norm();
+			z3.times_i();
+			a.copy(z0); a.add(z3);
+		}
+		norm();
+	}
+
+/* this=1/this */
+	public void inverse()
+	{
+		FP8 f0=new FP8(a);
+		FP8 f1=new FP8(b);
+		FP8 f2=new FP8(a);
+		FP8 f3=new FP8(0);
+
+		norm();
+		f0.sqr();
+		f1.mul(c);
+		f1.times_i();
+		f0.sub(f1);
+		f0.norm();
+
+		f1.copy(c); f1.sqr();
+		f1.times_i();
+		f2.mul(b);
+		f1.sub(f2);
+		f1.norm();
+
+		f2.copy(b); f2.sqr();
+		f3.copy(a); f3.mul(c);
+		f2.sub(f3);
+		f2.norm();
+
+		f3.copy(b); f3.mul(f2);
+		f3.times_i();
+		a.mul(f0);
+		f3.add(a);
+		c.mul(f1);
+		c.times_i();
+
+		f3.add(c);
+		f3.norm();
+		f3.inverse();
+		a.copy(f0); a.mul(f3);
+		b.copy(f1); b.mul(f3);
+		c.copy(f2); c.mul(f3);
+	}
+
+/* this=this^p using Frobenius */
+	public void frob(FP2 f,int n)
+	{
+		FP2 f2=new FP2(f);
+		FP2 f3=new FP2(f);
+
+		f2.sqr();
+		f3.mul(f2);
+
+		f3.mul_ip(); f3.norm();
+
+		for (int i=0;i<n;i++)
+		{
+			a.frob(f3);
+			b.frob(f3);
+			c.frob(f3);
+
+			b.qmul(f); b.times_i2();
+			c.qmul(f2); c.times_i2(); c.times_i2();
+		}
+	}
+
+/* trace function */
+	public FP8 trace()
+	{
+		FP8 t=new FP8(0);
+		t.copy(a);
+		t.imul(3);
+		t.reduce();
+		return t;
+	}
+
+/* convert from byte array to FP12 */
+	public static FP24 fromBytes(byte[] w)
+	{
+		BIG a,b;
+		FP2 c,d;
+		FP4 ea,eb;
+		FP8 e,f,g;
+		byte[] t=new byte[BIG.MODBYTES];
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+BIG.MODBYTES];
+		b=BIG.fromBytes(t);
+		c=new FP2(a,b);
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+2*BIG.MODBYTES];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+3*BIG.MODBYTES];
+		b=BIG.fromBytes(t);
+		d=new FP2(a,b);
+
+		ea=new FP4(c,d);
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+4*BIG.MODBYTES];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+5*BIG.MODBYTES];
+		b=BIG.fromBytes(t);
+		c=new FP2(a,b);
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+6*BIG.MODBYTES];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+7*BIG.MODBYTES];
+		b=BIG.fromBytes(t);
+		d=new FP2(a,b);
+
+		eb=new FP4(c,d);
+
+		e=new FP8(ea,eb);
+
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+8*BIG.MODBYTES];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+9*BIG.MODBYTES];
+		b=BIG.fromBytes(t);
+		c=new FP2(a,b);
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+10*BIG.MODBYTES];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+11*BIG.MODBYTES];
+		b=BIG.fromBytes(t);
+		d=new FP2(a,b);
+
+		ea=new FP4(c,d);
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+12*BIG.MODBYTES];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+13*BIG.MODBYTES];
+		b=BIG.fromBytes(t);
+		c=new FP2(a,b);
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+14*BIG.MODBYTES];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+15*BIG.MODBYTES];
+		b=BIG.fromBytes(t);
+		d=new FP2(a,b);
+
+		eb=new FP4(c,d);
+
+		f=new FP8(ea,eb);
+
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+16*BIG.MODBYTES];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+17*BIG.MODBYTES];
+		b=BIG.fromBytes(t);
+		c=new FP2(a,b);
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+18*BIG.MODBYTES];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+19*BIG.MODBYTES];
+		b=BIG.fromBytes(t);
+		d=new FP2(a,b);
+
+		ea=new FP4(c,d);
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+20*BIG.MODBYTES];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+21*BIG.MODBYTES];
+		b=BIG.fromBytes(t);
+		c=new FP2(a,b);
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+22*BIG.MODBYTES];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+23*BIG.MODBYTES];
+		b=BIG.fromBytes(t);
+		d=new FP2(a,b);
+
+		eb=new FP4(c,d);
+
+		g=new FP8(ea,eb);
+
+		return new FP24(e,f,g);
+	}
+
+/* convert this to byte array */
+	public void toBytes(byte[] w)
+	{
+		byte[] t=new byte[BIG.MODBYTES];
+
+		a.geta().geta().getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i]=t[i];
+		a.geta().geta().getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+BIG.MODBYTES]=t[i];
+		a.geta().getb().getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+2*BIG.MODBYTES]=t[i];
+		a.geta().getb().getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+3*BIG.MODBYTES]=t[i];
+
+		a.getb().geta().getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+4*BIG.MODBYTES]=t[i];
+		a.getb().geta().getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+5*BIG.MODBYTES]=t[i];
+		a.getb().getb().getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+6*BIG.MODBYTES]=t[i];
+		a.getb().getb().getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+7*BIG.MODBYTES]=t[i];
+
+
+		b.geta().geta().getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+8*BIG.MODBYTES]=t[i];
+		b.geta().geta().getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+9*BIG.MODBYTES]=t[i];
+		b.geta().getb().getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+10*BIG.MODBYTES]=t[i];
+		b.geta().getb().getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+11*BIG.MODBYTES]=t[i];
+
+		b.getb().geta().getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+12*BIG.MODBYTES]=t[i];
+		b.getb().geta().getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+13*BIG.MODBYTES]=t[i];
+		b.getb().getb().getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+14*BIG.MODBYTES]=t[i];
+		b.getb().getb().getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+15*BIG.MODBYTES]=t[i];
+
+		c.geta().geta().getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+16*BIG.MODBYTES]=t[i];
+		c.geta().geta().getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+17*BIG.MODBYTES]=t[i];
+		c.geta().getb().getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+18*BIG.MODBYTES]=t[i];
+		c.geta().getb().getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+19*BIG.MODBYTES]=t[i];
+
+		c.getb().geta().getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+20*BIG.MODBYTES]=t[i];
+		c.getb().geta().getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+21*BIG.MODBYTES]=t[i];
+		c.getb().getb().getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+22*BIG.MODBYTES]=t[i];
+		c.getb().getb().getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+23*BIG.MODBYTES]=t[i];
+
+	}
+
+/* convert to hex string */
+	public String toString() 
+	{
+		return ("["+a.toString()+","+b.toString()+","+c.toString()+"]");
+	}
+
+/* this=this^e */ 
+/* Note this is simple square and multiply, so not side-channel safe */
+	public FP24 pow(BIG e)
+	{
+		FP24 sf=new FP24(this);
+		sf.norm();
+
+		BIG e1=new BIG(e);
+		e1.norm();
+		BIG e3=new BIG(e1);
+		e3.pmul(3);
+		e3.norm();
+
+		FP24 w=new FP24(sf);
+
+		int nb=e3.nbits();
+		for (int i=nb-2;i>=1;i--)
+		{
+			w.usqr();
+			int bt=e3.bit(i)-e1.bit(i);
+			if (bt==1)
+				w.mul(sf);
+			if (bt==-1)
+			{
+				sf.conj(); w.mul(sf); sf.conj();
+			}
+		}
+		w.reduce();
+		return w;
+
+	}
+
+/* constant time powering by small integer of max length bts */
+	public void pinpow(int e,int bts)
+	{
+		int i,b;
+		FP24 [] R=new FP24[2];
+		R[0]=new FP24(1);
+		R[1]=new FP24(this);
+		for (i=bts-1;i>=0;i--)
+		{
+			b=(e>>i)&1;
+			R[1-b].mul(R[b]);
+			R[b].usqr();
+		}
+		this.copy(R[0]);
+	}
+
+	public FP8 compow(BIG e,BIG r)
+	{
+		FP24 g1=new FP24(0);
+		FP24 g2=new FP24(0);
+		FP2 f=new FP2(new BIG(ROM.Fra),new BIG(ROM.Frb));
+		BIG q=new BIG(ROM.Modulus);
+
+		BIG m=new BIG(q);
+		m.mod(r);
+
+		BIG a=new BIG(e);
+		a.mod(m);
+
+		BIG b=new BIG(e);
+		b.div(m);
+
+		g1.copy(this);
+		g2.copy(this);
+
+		FP8 c=g1.trace();
+
+		if (b.iszilch())
+		{
+			c=c.xtr_pow(e);
+			return c;
+		}
+
+		g2.frob(f,1);
+		FP8 cp=g2.trace();
+		g1.conj();
+		g2.mul(g1);
+		FP8 cpm1=g2.trace();
+		g2.mul(g1);
+		FP8 cpm2=g2.trace();
+
+		c=c.xtr_pow2(cp,cpm1,cpm2,a,b);
+
+		return c;
+	}
+
+/* p=q0^u0.q1^u1.q2^u2.q3^u3.... */
+// Bos & Costello https://eprint.iacr.org/2013/458.pdf
+// Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
+// Side channel attack secure 
+
+	public static FP24 pow8(FP24[] q,BIG[] u)
+	{
+		int i,j,k,nb,pb1,pb2;
+		FP24 [] g1=new FP24[8];
+		FP24 [] g2=new FP24[8];
+		FP24 r=new FP24(1);
+		FP24 p=new FP24(0);
+		BIG [] t=new BIG[8];
+		BIG mt=new BIG(0);
+		byte[] w1=new byte[BIG.NLEN*BIG.BASEBITS+1];
+		byte[] s1=new byte[BIG.NLEN*BIG.BASEBITS+1];
+		byte[] w2=new byte[BIG.NLEN*BIG.BASEBITS+1];
+		byte[] s2=new byte[BIG.NLEN*BIG.BASEBITS+1];
+
+		for (i=0;i<8;i++)
+		{
+			t[i]=new BIG(u[i]);
+			t[i].norm();
+		}
+
+		g1[0]=new FP24(q[0]);  // q[0]
+		g1[1]=new FP24(g1[0]); g1[1].mul(q[1]); // q[0].q[1]
+		g1[2]=new FP24(g1[0]); g1[2].mul(q[2]); // q[0].q[2]
+		g1[3]=new FP24(g1[1]); g1[3].mul(q[2]); // q[0].q[1].q[2]
+		g1[4]=new FP24(q[0]);  g1[4].mul(q[3]); // q[0].q[3]
+		g1[5]=new FP24(g1[1]); g1[5].mul(q[3]); // q[0].q[1].q[3]
+		g1[6]=new FP24(g1[2]); g1[6].mul(q[3]); // q[0].q[2].q[3]
+		g1[7]=new FP24(g1[3]); g1[7].mul(q[3]); // q[0].q[1].q[2].q[3]
+
+// Use Frobenius
+		FP2 f=new FP2(new BIG(ROM.Fra),new BIG(ROM.Frb));
+		for (i=0;i<8;i++)
+		{
+			g2[i]=new FP24(g1[i]);
+			g2[i].frob(f,4);
+		}
+
+    // Make it odd
+        pb1=1-t[0].parity();
+        t[0].inc(pb1);
+        t[0].norm();
+
+        pb2=1-t[4].parity();
+        t[4].inc(pb2);
+        t[4].norm();
+
+
+    // Number of bits
+        mt.zero();
+        for (i=0;i<8;i++) {
+            mt.or(t[i]); 
+        }
+        nb=1+mt.nbits();
+
+     // Sign pivot 
+        s1[nb-1]=1;
+		s2[nb-1]=1;
+        for (i=0;i<nb-1;i++) {
+            t[0].fshr(1);
+            s1[i]=(byte)(2*t[0].parity()-1);
+            t[4].fshr(1);
+            s2[i]=(byte)(2*t[4].parity()-1);
+        }
+
+    // Recoded exponent
+        for (i=0; i<nb; i++) {
+            w1[i]=0;
+            k=1;
+            for (j=1; j<4; j++) {
+                byte bt=(byte)(s1[i]*t[j].parity());
+                t[j].fshr(1);
+                t[j].dec((int)(bt)>>1);
+                t[j].norm();
+                w1[i]+=bt*(byte)k;
+                k*=2;
+            }
+
+            w2[i]=0;
+            k=1;
+            for (j=5; j<8; j++) {
+                byte bt=(byte)(s2[i]*t[j].parity());
+                t[j].fshr(1);
+                t[j].dec((int)(bt)>>1);
+                t[j].norm();
+                w2[i]+=bt*(byte)k;
+                k*=2;
+            }
+        } 
+
+     // Main loop
+        p.select(g1,(int)(2*w1[nb-1]+1)); 
+		r.select(g2,(int)(2*w2[nb-1]+1)); 
+		p.mul(r);
+        for (i=nb-2;i>=0;i--) {
+            p.usqr();
+            r.select(g1,(int)(2*w1[i]+s1[i]));
+            p.mul(r);
+            r.select(g2,(int)(2*w2[i]+s2[i]));
+            p.mul(r);
+
+        }
+
+    // apply correction
+        r.copy(q[0]); r.conj();   
+        r.mul(p);
+        p.cmove(r,pb1);
+
+        r.copy(q[4]); r.conj();   
+        r.mul(p);
+        p.cmove(r,pb2);
+
+ 		p.reduce();
+		return p;
+	}              
+
+}
\ No newline at end of file
diff --git a/version3/java/FP32.java b/version3/java/FP32.java
new file mode 100644
index 0000000..dd6262b
--- /dev/null
+++ b/version3/java/FP32.java
@@ -0,0 +1,678 @@
+/*
+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.
+*/
+
+/* Finite Field arithmetic */
+/* AMCL mod p functions */
+
+package org.apache.milagro.amcl.XXX;
+
+public final class FP {
+
+	public static final int NOT_SPECIAL=0;
+	public static final int PSEUDO_MERSENNE=1;
+	public static final int MONTGOMERY_FRIENDLY=2;
+	public static final int GENERALISED_MERSENNE=3;
+
+	public static final int MODBITS=@NBT@; /* Number of bits in Modulus */
+	public static final int MOD8=@M8@;  /* Modulus mod 8 */
+	public static final int MODTYPE=@MT@;
+
+	public static final int FEXCESS = (((int)1<<@SH@)-1); // BASEBITS*NLEN-MODBITS or 2^30 max!
+	public static final int OMASK=(int)(-1)<<(MODBITS%BIG.BASEBITS);
+	public static final int TBITS=MODBITS%BIG.BASEBITS; // Number of active bits in top word 
+	public static final int TMASK=((int)1<<TBITS)-1;
+
+
+	public final BIG x;
+	//public BIG p=new BIG(ROM.Modulus);
+	//public BIG r2modp=new BIG(ROM.R2modp);   /*** Change ***/
+	public int XES;
+
+/**************** 32-bit specific ************************/
+
+
+/* reduce a DBIG to a BIG using the appropriate form of the modulus */
+	public static BIG mod(DBIG d)
+	{
+		if (MODTYPE==PSEUDO_MERSENNE)
+		{
+			BIG b;
+			int v,tw;
+			BIG t=d.split(MODBITS);
+			b=new BIG(d);
+
+			v=t.pmul((int)ROM.MConst);
+
+			t.add(b);
+			t.norm();
+
+			tw=t.w[BIG.NLEN-1];
+			t.w[BIG.NLEN-1]&=TMASK;
+			t.w[0]+=(ROM.MConst*((tw>>TBITS)+(v<<(BIG.BASEBITS-TBITS))));
+
+			t.norm();
+			return t;
+
+		}
+		if (MODTYPE==MONTGOMERY_FRIENDLY)
+		{
+			BIG b;
+			int[] cr=new int[2];				
+			for (int i=0;i<BIG.NLEN;i++)
+			{
+				cr=BIG.muladd(d.w[i],ROM.MConst-1,d.w[i],d.w[BIG.NLEN+i-1]);
+				d.w[BIG.NLEN+i]+=cr[0];
+				d.w[BIG.NLEN+i-1]=cr[1];	
+			}
+			
+			b=new BIG(0);
+			for (int i=0;i<BIG.NLEN;i++ )
+				b.w[i]=d.w[BIG.NLEN+i];
+			b.norm();
+			return b;
+		}
+		if (MODTYPE==GENERALISED_MERSENNE)
+		{ // GoldiLocks Only
+			BIG b;
+			BIG t=d.split(MODBITS);
+			b=new BIG(d);
+			b.add(t);
+			DBIG dd=new DBIG(t);
+			dd.shl(MODBITS/2);
+
+			BIG tt=dd.split(MODBITS);
+			BIG lo=new BIG(dd);
+			b.add(tt);
+			b.add(lo);
+			b.norm();
+			tt.shl(MODBITS/2);
+			b.add(tt);
+
+			int carry=b.w[BIG.NLEN-1]>>TBITS;
+			b.w[BIG.NLEN-1]&=TMASK;
+			b.w[0]+=carry;
+			
+			b.w[224/BIG.BASEBITS]+=carry<<(224%BIG.BASEBITS);
+			b.norm();
+			return b;
+		}
+		if (MODTYPE==NOT_SPECIAL)
+		{
+			return BIG.monty(new BIG(ROM.Modulus),ROM.MConst,d);
+		}
+
+		return new BIG(0);
+	}
+
+	private static int quo(BIG n,BIG m)
+	{
+		int sh;
+		int num,den;
+		int hb=BIG.CHUNK/2;
+		if (TBITS<hb)
+		{
+			sh=hb-TBITS;
+			num=(n.w[BIG.NLEN-1]<<sh)|(n.w[BIG.NLEN-2]>>(BIG.BASEBITS-sh));
+			den=(m.w[BIG.NLEN-1]<<sh)|(m.w[BIG.NLEN-2]>>(BIG.BASEBITS-sh));
+		}
+		else
+		{
+			num=n.w[BIG.NLEN-1];
+			den=m.w[BIG.NLEN-1];
+		}
+		return (int)(num/(den+1));
+	}
+
+/* reduce this mod Modulus */
+	public void reduce()
+	{
+		BIG m=new BIG(ROM.Modulus);
+		BIG r=new BIG(ROM.Modulus);
+		int sr,sb,q,carry;
+		x.norm();
+
+		if (XES>16)
+		{
+			q=quo(x,m);
+			carry=r.pmul(q);
+			r.w[BIG.NLEN-1]+=(carry<<BIG.BASEBITS); // correction - put any carry out back in again
+			x.sub(r);
+			x.norm();
+			sb=2;
+		}
+		else  sb=logb2(XES-1);
+
+		m.fshl(sb);
+		while (sb>0)
+		{
+// constant time...
+			sr=BIG.ssn(r,x,m);  // optimized combined shift, subtract and norm
+			x.cmove(r,1-sr);
+			sb--;
+		}
+
+		XES=1;
+	}
+
+/*********************************************************/
+
+/* Constructors */
+	public FP(int a)
+	{
+		x=new BIG(a);
+		nres();
+	}
+
+	public FP()
+	{
+		x=new BIG(0);
+		XES=1;
+	}
+
+	public FP(BIG a)
+	{
+		x=new BIG(a);
+		nres();
+	}
+	
+	public FP(FP a)
+	{
+		x=new BIG(a.x);
+		XES=a.XES;
+	}
+
+/* convert to string */
+	public String toString() 
+	{
+		String s=redc().toString();
+		return s;
+	}
+
+	public String toRawString() 
+	{
+		String s=x.toRawString();
+		return s;
+	}
+
+/* convert to Montgomery n-residue form */
+	public void nres()
+	{
+		if (MODTYPE!=PSEUDO_MERSENNE && MODTYPE!=GENERALISED_MERSENNE)
+		{
+			DBIG d=BIG.mul(x,new BIG(ROM.R2modp));  /*** Change ***/
+			x.copy(mod(d));
+			XES=2;
+		}
+		else XES=1;
+	}
+
+/* convert back to regular form */
+	public BIG redc()
+	{
+		if (MODTYPE!=PSEUDO_MERSENNE && MODTYPE!=GENERALISED_MERSENNE)
+		{
+			DBIG d=new DBIG(x);
+			return mod(d);
+		}
+		else 
+		{
+			BIG r=new BIG(x);
+			return r;
+		}
+	}
+
+/* test this=0? */
+	public boolean iszilch() {
+		FP z=new FP(this);
+		z.reduce();
+		return z.x.iszilch();
+	}
+
+/* copy from FP b */
+	public void copy(FP b)
+	{
+		x.copy(b.x);
+		XES=b.XES;
+	}
+
+/* set this=0 */
+	public void zero()
+	{
+		x.zero();
+		XES=1;
+	}
+	
+/* set this=1 */
+	public void one()
+	{
+		x.one(); nres(); 
+	}
+
+/* normalise this */
+	public void norm()
+	{
+		x.norm();
+	}
+
+/* swap FPs depending on d */
+	public void cswap(FP b,int d)
+	{
+		x.cswap(b.x,d);
+		int t,c=d;
+		c=~(c-1);
+		t=c&(XES^b.XES);
+		XES^=t;
+		b.XES^=t;
+	}
+
+/* copy FPs depending on d */
+	public void cmove(FP b,int d)
+	{
+		x.cmove(b.x,d);
+		XES^=(XES^b.XES)&(-d);
+	}
+
+/* this*=b mod Modulus */
+	public void mul(FP b)
+	{
+		if ((long)XES*b.XES>(long)FEXCESS) reduce();
+
+		DBIG d=BIG.mul(x,b.x);
+		x.copy(mod(d));
+		XES=2;
+	}
+
+/* this*=c mod Modulus, where c is a small int */
+	public void imul(int c)
+	{
+		boolean s=false;
+		if (c<0)
+		{
+			c=-c;
+			s=true;
+		}
+
+		if (MODTYPE==PSEUDO_MERSENNE || MODTYPE==GENERALISED_MERSENNE)
+		{
+			DBIG d=x.pxmul(c);
+			x.copy(mod(d));
+			XES=2;
+		}
+		else
+		{
+			if (XES*c<=FEXCESS)
+			{
+				x.pmul(c);
+				XES*=c;
+			}
+			else
+			{  // this is not good
+				FP n=new FP(c);
+				mul(n);
+			}
+		}
+				
+
+/*
+		if (c<=BIG.NEXCESS && XES*c<=FEXCESS)
+		{
+			x.imul(c);
+			XES*=c;
+			x.norm();
+		}
+		else
+		{
+			DBIG d=x.pxmul(c);
+			x.copy(mod(d));
+			XES=2;
+		} */
+		if (s) {neg(); norm();}
+	}
+
+/* this*=this mod Modulus */
+	public void sqr()
+	{
+		DBIG d;
+		if ((long)XES*XES>(long)FEXCESS) reduce();
+
+		d=BIG.sqr(x);	
+		x.copy(mod(d));
+		XES=2;
+	}
+
+/* this+=b */
+	public void add(FP b) {
+		x.add(b.x);
+		XES+=b.XES;
+		if (XES>FEXCESS) reduce();
+	}
+
+// https://graphics.stanford.edu/~seander/bithacks.html
+// constant time log to base 2 (or number of bits in)
+
+	private static int logb2(int v)
+	{
+		int r;
+		v |= v >>> 1;
+		v |= v >>> 2;
+		v |= v >>> 4;
+		v |= v >>> 8;
+		v |= v >>> 16;
+
+		v = v - ((v >>> 1) & 0x55555555);                  
+		v = (v & 0x33333333) + ((v >>> 2) & 0x33333333);  
+		r = ((v + (v >>> 4) & 0xF0F0F0F) * 0x1010101) >>> 24; 
+		return r;
+	}
+
+/* this = -this mod Modulus */
+	public void neg()
+	{
+		int sb;
+		BIG m=new BIG(ROM.Modulus);
+
+		sb=logb2(XES-1);
+		m.fshl(sb);
+		x.rsub(m);		
+
+		XES=(1<<sb)+1;
+		if (XES>FEXCESS) reduce();
+	}
+
+/* this-=b */
+	public void sub(FP b)
+	{
+		FP n=new FP(b);
+		n.neg();
+		this.add(n);
+	}
+
+	public void rsub(FP b)
+	{
+		FP n=new FP(this);
+		n.neg();
+		this.copy(b);
+		this.add(n);
+	}
+
+/* this/=2 mod Modulus */
+	public void div2()
+	{
+		if (x.parity()==0)
+			x.fshr(1);
+		else
+		{
+			x.add(new BIG(ROM.Modulus));
+			x.norm();
+			x.fshr(1);
+		}
+	}
+
+// return this^(p-3)/4 or this^(p-5)/8
+	private FP fpow()
+	{
+		int i,j,k,bw,w,c,nw,lo,m,n;
+		FP [] xp=new FP[11];
+		int[]  ac={1,2,3,6,12,15,30,60,120,240,255};
+// phase 1
+			
+		xp[0]=new FP(this);	// 1 
+		xp[1]=new FP(this); xp[1].sqr(); // 2
+		xp[2]=new FP(xp[1]); xp[2].mul(this);  //3
+		xp[3]=new FP(xp[2]); xp[3].sqr();  // 6 
+		xp[4]=new FP(xp[3]); xp[4].sqr();  // 12
+		xp[5]=new FP(xp[4]); xp[5].mul(xp[2]);  // 15
+		xp[6]=new FP(xp[5]); xp[6].sqr();  // 30
+		xp[7]=new FP(xp[6]); xp[7].sqr();  // 60
+		xp[8]=new FP(xp[7]); xp[8].sqr();  // 120
+		xp[9]=new FP(xp[8]); xp[9].sqr();  // 240
+		xp[10]=new FP(xp[9]); xp[10].mul(xp[5]);  // 255		
+			
+		if (MOD8==5)
+		{
+			n=MODBITS-3;
+			c=(ROM.MConst+5)/8;
+		} else {
+			n=MODBITS-2;
+			c=(ROM.MConst+3)/4;
+		}
+
+		bw=0; w=1; while (w<c) {w*=2; bw+=1;}
+		k=w-c;
+
+		FP key=new FP(); i=10;
+		if (k!=0)
+		{
+			while (ac[i]>k) i--;
+			key.copy(xp[i]); 
+			k-=ac[i];
+		}
+		while (k!=0)
+		{
+			i--;
+			if (ac[i]>k) continue;
+			key.mul(xp[i]);
+			k-=ac[i]; 
+		}
+
+// phase 2 
+		xp[1].copy(xp[2]);
+		xp[2].copy(xp[5]);
+		xp[3].copy(xp[10]);
+
+		j=3; m=8;
+		nw=n-bw;
+		FP t=new FP();
+
+		while (2*m<nw)
+		{
+			t.copy(xp[j++]);
+			for (i=0;i<m;i++)
+				t.sqr(); 
+			xp[j].copy(xp[j-1]);
+			xp[j].mul(t);
+			m*=2;
+		}
+
+		lo=nw-m;
+		FP r=new FP(xp[j]);
+
+		while (lo!=0)
+		{
+			m/=2; j--;
+			if (lo<m) continue;
+			lo-=m;
+			t.copy(r);
+			for (i=0;i<m;i++)
+				t.sqr();
+			r.copy(t);
+			r.mul(xp[j]);
+		}
+
+// phase 3
+		for (i=0;i<bw;i++ )
+			r.sqr();
+
+		if (w-c!=0)
+			r.mul(key); 
+		return r;
+	}
+
+/* this=1/this mod Modulus */
+	public void inverse()
+	{
+
+		if (MODTYPE==PSEUDO_MERSENNE)
+		{
+			FP y=fpow();
+			if (MOD8==5)
+			{
+				FP t=new FP(this);
+				t.sqr();
+				mul(t);
+				y.sqr();
+
+			} 
+			y.sqr();
+			y.sqr();
+			mul(y);
+		} else {
+			BIG m2=new BIG(ROM.Modulus);
+			m2.dec(2); m2.norm();
+			copy(pow(m2));
+		}
+	}
+
+/* return TRUE if this==a */
+	public boolean equals(FP a)
+	{
+		FP f=new FP(this);
+		FP s=new FP(a);
+		f.reduce();
+		s.reduce();
+		if (BIG.comp(f.x,s.x)==0) return true;
+		return false;
+	}
+
+	private FP pow(BIG e)
+	{
+		byte[] w=new byte[1+(BIG.NLEN*BIG.BASEBITS+3)/4];
+		FP [] tb=new FP[16];
+		BIG t=new BIG(e);
+		t.norm();
+		int nb=1+(t.nbits()+3)/4;
+
+		for (int i=0;i<nb;i++)
+		{
+			int lsbs=t.lastbits(4);
+			t.dec(lsbs);
+			t.norm();
+			w[i]=(byte)lsbs;
+			t.fshr(4);
+		}
+		tb[0]=new FP(1);
+		tb[1]=new FP(this);
+		for (int i=2;i<16;i++)
+		{
+			tb[i]=new FP(tb[i-1]);
+			tb[i].mul(this);
+		}
+		FP r=new FP(tb[w[nb-1]]);
+		for (int i=nb-2;i>=0;i--)
+		{
+			r.sqr();
+			r.sqr();
+			r.sqr();
+			r.sqr();
+			r.mul(tb[w[i]]);
+		}
+		r.reduce();
+		return r;
+	}
+
+/* return this^e mod Modulus 
+	public FP pow(BIG e)
+	{
+		int bt;
+		FP r=new FP(1);
+		e.norm();
+		x.norm();
+		FP m=new FP(this);
+		while (true)
+		{
+			bt=e.parity();
+			e.fshr(1);
+			if (bt==1) r.mul(m);
+			if (e.iszilch()) break;
+			m.sqr();
+		}
+		r.x.mod(p);
+		return r;
+	} */
+
+/* return sqrt(this) mod Modulus */
+	public FP sqrt()
+	{
+		reduce();
+		if (MOD8==5)
+		{
+			FP i=new FP(this); i.x.shl(1);
+			FP v;
+			if (MODTYPE==PSEUDO_MERSENNE)
+			{
+				v=i.fpow();
+			} else {
+				BIG b=new BIG(ROM.Modulus);
+				b.dec(5); b.norm(); b.shr(3);
+				v=i.pow(b);
+			}
+			i.mul(v); i.mul(v);
+			i.x.dec(1);
+			FP r=new FP(this);
+			r.mul(v); r.mul(i); 
+			r.reduce();
+			return r;
+		}
+		else
+		{
+			if (MODTYPE==PSEUDO_MERSENNE)
+			{
+				FP r=fpow();
+				r.mul(this);
+				return r;
+			} else {
+				BIG b=new BIG(ROM.Modulus);
+				b.inc(1); b.norm(); b.shr(2);
+				return pow(b);
+			}
+		}
+	}
+
+/* return jacobi symbol (this/Modulus) */
+	public int jacobi()
+	{
+		BIG w=redc();
+		return w.jacobi(new BIG(ROM.Modulus));
+	}
+/*
+	public static void main(String[] args) {
+		BIG m=new BIG(ROM.Modulus);
+		BIG x=new BIG(3);
+		BIG e=new BIG(m);
+		e.dec(1);
+
+		System.out.println("m= "+m.nbits());	
+
+
+		BIG r=x.powmod(e,m);
+
+		System.out.println("m= "+m.toString());	
+		System.out.println("r= "+r.toString());	
+
+		BIG.cswap(m,r,0);
+
+		System.out.println("m= "+m.toString());	
+		System.out.println("r= "+r.toString());	
+
+//		FP y=new FP(3);
+//		FP s=y.pow(e);
+//		System.out.println("s= "+s.toString());	
+
+	} */
+}
diff --git a/version3/java/FP4.java b/version3/java/FP4.java
new file mode 100644
index 0000000..ef72602
--- /dev/null
+++ b/version3/java/FP4.java
@@ -0,0 +1,724 @@
+/*
+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.
+*/
+
+/* Finite Field arithmetic  Fp^4 functions */
+
+/* FP4 elements are of the form a+ib, where i is sqrt(-1+sqrt(-1))  */
+
+package org.apache.milagro.amcl.XXX;
+
+public final class FP4 {
+	private final FP2 a;
+	private final FP2 b;
+/* reduce all components of this mod Modulus */
+	public void reduce()
+	{
+		a.reduce();
+		b.reduce();
+	}
+/* normalise all components of this mod Modulus */
+	public void norm()
+	{
+		a.norm();
+		b.norm();
+	}
+/* test this==0 ? */
+	public boolean iszilch() {
+		//reduce();
+		return (a.iszilch() && b.iszilch());
+	}
+
+	public void cmove(FP4 g,int d)
+	{
+		a.cmove(g.a,d);
+		b.cmove(g.b,d);
+	}
+
+/* test this==1 ? */
+	public boolean isunity() {
+		FP2 one=new FP2(1);
+		return (a.equals(one) && b.iszilch());
+	}
+
+/* test is w real? That is in a+ib test b is zero */
+	public boolean isreal()
+	{
+		return b.iszilch();
+	}
+/* extract real part a */
+	public FP2 real()
+	{
+		return a;
+	}
+
+	public FP2 geta()
+	{
+		return a;
+	}
+/* extract imaginary part b */
+	public FP2 getb()
+	{
+		return b;
+	}
+/* test this=x? */
+	public boolean equals(FP4 x)
+	{
+		return (a.equals(x.a) && b.equals(x.b));
+	}
+/* constructors */
+	public FP4(int c)
+	{
+		a=new FP2(c);
+		b=new FP2(0);
+	}
+
+	public FP4(FP4 x)
+	{
+		a=new FP2(x.a);
+		b=new FP2(x.b);
+	}
+
+	public FP4(FP2 c,FP2 d)
+	{
+		a=new FP2(c);
+		b=new FP2(d);
+	}
+
+	public FP4(FP2 c)
+	{
+		a=new FP2(c);
+		b=new FP2(0);
+	}
+/* copy this=x */
+	public void copy(FP4 x)
+	{
+		a.copy(x.a);
+		b.copy(x.b);
+	}
+/* set this=0 */
+	public void zero()
+	{
+		a.zero();
+		b.zero();
+	}
+/* set this=1 */
+	public void one()
+	{
+		a.one();
+		b.zero();
+	}
+/* set this=-this */
+	public void neg()
+	{
+		norm();
+		FP2 m=new FP2(a);
+		FP2 t=new FP2(0);
+		m.add(b);
+//	m.norm();
+		m.neg();
+	//	m.norm();
+		t.copy(m); t.add(b);
+		b.copy(m);
+		b.add(a);
+		a.copy(t);
+	norm();
+	}
+/* this=conjugate(this) */
+	public void conj()
+	{
+		b.neg(); norm();
+	}
+/* this=-conjugate(this) */
+	public void nconj()
+	{
+		a.neg(); norm();
+	}
+/* this+=x */
+	public void add(FP4 x)
+	{
+		a.add(x.a);
+		b.add(x.b);
+	}
+/* this-=x */
+	public void sub(FP4 x)
+	{
+		FP4 m=new FP4(x);
+		m.neg();
+		add(m);
+	}
+
+/* this*=s where s is FP2 */
+	public void pmul(FP2 s)
+	{
+		a.mul(s);
+		b.mul(s);
+	}
+
+/* this=x-this */
+	public void rsub(FP4 x)
+	{
+		neg();
+		add(x);
+	}
+
+
+/* this*=c where c is int */
+	public void imul(int c)
+	{
+		a.imul(c);
+		b.imul(c);
+	}
+/* this*=this */	
+	public void sqr()
+	{
+//		norm();
+
+		FP2 t1=new FP2(a);
+		FP2 t2=new FP2(b);
+		FP2 t3=new FP2(a);
+
+		t3.mul(b);
+		t1.add(b);
+		t2.mul_ip();
+
+		t2.add(a);
+
+		t1.norm();
+		t2.norm();
+
+		a.copy(t1);
+
+		a.mul(t2);
+
+		t2.copy(t3);
+		t2.mul_ip();
+		t2.add(t3);
+		t2.norm();
+		t2.neg();
+		a.add(t2);
+
+		b.copy(t3);
+		b.add(t3);
+
+		norm();
+	}
+/* this*=y */
+	public void mul(FP4 y)
+	{
+//		norm();
+
+		FP2 t1=new FP2(a);
+		FP2 t2=new FP2(b);
+		FP2 t3=new FP2(0);
+		FP2 t4=new FP2(b);
+
+		t1.mul(y.a);
+		t2.mul(y.b);
+		t3.copy(y.b);
+		t3.add(y.a);
+		t4.add(a);
+
+	t3.norm();
+	t4.norm();
+
+		t4.mul(t3);
+
+	t3.copy(t1);
+	t3.neg();
+	t4.add(t3);
+	t4.norm();
+
+	//	t4.sub(t1);
+	//	t4.norm();
+
+	t3.copy(t2);
+	t3.neg();
+	b.copy(t4);
+	b.add(t3);
+
+	//	b.copy(t4);
+	//	b.sub(t2);
+
+		t2.mul_ip();
+		a.copy(t2);
+		a.add(t1);
+
+		norm();
+	}
+/* convert this to hex string */
+	public String toString() 
+	{
+		return ("["+a.toString()+","+b.toString()+"]");
+	}
+
+	public String toRawString() 
+	{
+		return ("["+a.toRawString()+","+b.toRawString()+"]");
+	}
+
+/* this=1/this */
+	public void inverse()
+	{
+//		norm();
+
+		FP2 t1=new FP2(a);
+		FP2 t2=new FP2(b);
+
+		t1.sqr();
+		t2.sqr();
+		t2.mul_ip();
+	t2.norm();
+		t1.sub(t2);
+		t1.inverse();
+		a.mul(t1);
+		t1.neg();
+	t1.norm();
+		b.mul(t1);
+	}
+
+
+/* this*=i where i = sqrt(-1+sqrt(-1)) */
+	public void times_i()
+	{
+//		norm();
+		FP2 s=new FP2(b);
+		FP2 t=new FP2(b);
+		s.times_i();
+		t.add(s);
+	//	t.norm();
+		b.copy(a);
+		a.copy(t);
+		norm();
+	}
+
+/* this=this^p using Frobenius */
+	public void frob(FP2 f)
+	{
+		a.conj();
+		b.conj();
+		b.mul(f);
+	}
+
+/* this=this^e */
+	public FP4 pow(BIG e)
+	{
+		FP4 w=new FP4(this);
+		w.norm();
+		BIG z=new BIG(e);
+		FP4 r=new FP4(1);
+		z.norm();
+		while (true)
+		{
+			int bt=z.parity();
+			z.fshr(1);
+			if (bt==1) r.mul(w);
+			if (z.iszilch()) break;
+			w.sqr();
+		}
+		r.reduce();
+		return r;
+	}
+/* XTR xtr_a function */
+	public void xtr_A(FP4 w,FP4 y,FP4 z) 
+	{
+		FP4 r=new FP4(w);
+		FP4 t=new FP4(w);
+	//y.norm();
+		r.sub(y);
+	r.norm();
+		r.pmul(a);
+		t.add(y);
+	t.norm();
+		t.pmul(b);
+		t.times_i();
+
+		copy(r);
+		add(t);
+		add(z);
+
+		norm();
+	}
+
+/* XTR xtr_d function */
+	public void xtr_D() {
+		FP4 w=new FP4(this);
+		sqr(); w.conj();
+		w.add(w);
+	w.norm();
+		sub(w);
+		reduce();
+	}
+
+/* r=x^n using XTR method on traces of FP12s */
+	public FP4 xtr_pow(BIG n) {
+		FP4 sf=new FP4(this);
+		sf.norm();
+		FP4 a=new FP4(3);
+		FP4 b=new FP4(sf);
+		FP4 c=new FP4(b);
+		c.xtr_D();
+		FP4 t=new FP4(0);
+		FP4 r=new FP4(0);
+
+		//n.norm();
+		int par=n.parity();
+		BIG v=new BIG(n); v.norm(); v.fshr(1);
+		if (par==0) {v.dec(1); v.norm();}
+
+		int nb=v.nbits();
+		for (int i=nb-1;i>=0;i--)
+		{
+			if (v.bit(i)!=1)
+			{
+				t.copy(b);
+				sf.conj();
+				c.conj();
+				b.xtr_A(a,sf,c);
+				sf.conj();
+				c.copy(t);
+				c.xtr_D();
+				a.xtr_D();
+			}
+			else
+			{
+				t.copy(a); t.conj();
+				a.copy(b);
+				a.xtr_D();
+				b.xtr_A(c,sf,t);
+				c.xtr_D();
+			}
+		}
+		if (par==0) r.copy(c);
+		else r.copy(b);
+		r.reduce();
+		return r;
+	}
+
+/* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */
+	public FP4 xtr_pow2(FP4 ck,FP4 ckml,FP4 ckm2l,BIG a,BIG b)
+	{
+
+		BIG e=new BIG(a);
+		BIG d=new BIG(b);
+		BIG w=new BIG(0);
+		e.norm(); d.norm();
+
+		FP4 cu=new FP4(ck);  // can probably be passed in w/o copying
+		FP4 cv=new FP4(this);
+		FP4 cumv=new FP4(ckml);
+		FP4 cum2v=new FP4(ckm2l);
+		FP4 r=new FP4(0);
+		FP4 t=new FP4(0);
+
+		int f2=0;
+		while (d.parity()==0 && e.parity()==0)
+		{
+			d.fshr(1);
+			e.fshr(1);
+			f2++;
+		}
+
+		while (BIG.comp(d,e)!=0)
+		{
+			if (BIG.comp(d,e)>0)
+			{
+				w.copy(e); w.imul(4); w.norm();
+				if (BIG.comp(d,w)<=0)
+				{
+					w.copy(d); d.copy(e);
+					e.rsub(w); e.norm();
+
+					t.copy(cv); 
+					t.xtr_A(cu,cumv,cum2v);
+					cum2v.copy(cumv); 
+					cum2v.conj();
+					cumv.copy(cv);
+					cv.copy(cu);
+					cu.copy(t);
+
+				}
+				else if (d.parity()==0)
+				{
+					d.fshr(1);
+					r.copy(cum2v); r.conj();
+					t.copy(cumv);
+					t.xtr_A(cu,cv,r);
+					cum2v.copy(cumv);
+					cum2v.xtr_D();
+					cumv.copy(t);
+					cu.xtr_D();
+				}
+				else if (e.parity()==1)
+				{
+					d.sub(e); d.norm();
+					d.fshr(1);
+					t.copy(cv);
+					t.xtr_A(cu,cumv,cum2v);
+					cu.xtr_D();
+					cum2v.copy(cv);
+					cum2v.xtr_D();
+					cum2v.conj();
+					cv.copy(t);
+				}
+				else
+				{
+					w.copy(d);
+					d.copy(e); d.fshr(1);
+					e.copy(w);
+					t.copy(cumv);
+					t.xtr_D();
+					cumv.copy(cum2v); cumv.conj();
+					cum2v.copy(t); cum2v.conj();
+					t.copy(cv);
+					t.xtr_D();
+					cv.copy(cu);
+					cu.copy(t);
+				}
+			}
+			if (BIG.comp(d,e)<0)
+			{
+				w.copy(d); w.imul(4); w.norm();
+				if (BIG.comp(e,w)<=0)
+				{
+					e.sub(d); e.norm();
+					t.copy(cv);
+					t.xtr_A(cu,cumv,cum2v);
+					cum2v.copy(cumv);
+					cumv.copy(cu);
+					cu.copy(t);
+				}
+				else if (e.parity()==0)
+				{
+					w.copy(d);
+					d.copy(e); d.fshr(1);
+					e.copy(w);
+					t.copy(cumv);
+					t.xtr_D();
+					cumv.copy(cum2v); cumv.conj();
+					cum2v.copy(t); cum2v.conj();
+					t.copy(cv);
+					t.xtr_D();
+					cv.copy(cu);
+					cu.copy(t);
+				}
+				else if (d.parity()==1)
+				{
+					w.copy(e);
+					e.copy(d);
+					w.sub(d); w.norm();
+					d.copy(w); d.fshr(1);
+					t.copy(cv);
+					t.xtr_A(cu,cumv,cum2v);
+					cumv.conj();
+					cum2v.copy(cu);
+					cum2v.xtr_D();
+					cum2v.conj();
+					cu.copy(cv);
+					cu.xtr_D();
+					cv.copy(t);
+				}
+				else
+				{
+					d.fshr(1);
+					r.copy(cum2v); r.conj();
+					t.copy(cumv);
+					t.xtr_A(cu,cv,r);
+					cum2v.copy(cumv);
+					cum2v.xtr_D();
+					cumv.copy(t);
+					cu.xtr_D();
+				}
+			}
+		}
+		r.copy(cv);
+		r.xtr_A(cu,cumv,cum2v);
+		for (int i=0;i<f2;i++)
+			r.xtr_D();
+		r=r.xtr_pow(d);
+		return r;
+	}
+
+/* this/=2 */
+	public void div2()
+	{
+		a.div2();
+		b.div2();
+	}
+
+	public void div_i()
+	{
+		FP2 u=new FP2(a);
+		FP2 v=new FP2(b);
+		u.div_ip();
+		a.copy(v);
+		b.copy(u);
+	}
+
+	public void div_2i() {
+		FP2 u=new FP2(a);
+		FP2 v=new FP2(b);
+		u.div_ip2();
+		v.add(v); v.norm();
+		a.copy(v);
+		b.copy(u);
+	}
+
+
+/* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */
+/* returns true if this is QR */
+	public boolean sqrt()
+	{
+		if (iszilch()) return true;
+		FP2 wa=new FP2(a);
+		FP2 ws=new FP2(b);
+		FP2 wt=new FP2(a);
+		
+		if (ws.iszilch())
+		{
+			if (wt.sqrt())
+			{
+				a.copy(wt);
+				b.zero();
+			} else {
+				wt.div_ip();
+				wt.sqrt();
+				b.copy(wt);
+				a.zero();
+			}
+			return true;
+		}
+
+		ws.sqr();
+		wa.sqr();
+		ws.mul_ip();
+		ws.norm();
+		wa.sub(ws);
+
+		ws.copy(wa);
+		if (!ws.sqrt()) {
+			return false;
+		}
+
+		wa.copy(wt); wa.add(ws); wa.norm(); wa.div2();
+
+		if (!wa.sqrt()) {
+			wa.copy(wt); wa.sub(ws); wa.norm(); wa.div2();
+			if (!wa.sqrt()) {
+				return false;
+			}
+		}
+		wt.copy(b);
+		ws.copy(wa); ws.add(wa);
+		ws.inverse();
+
+		wt.mul(ws);
+		a.copy(wa);
+		b.copy(wt);
+
+		return true;
+	}
+
+/* this*=s where s is FP */
+	public void qmul(FP s)
+	{
+		a.pmul(s);
+		b.pmul(s);
+	}
+
+
+
+/*
+	public static void main(String[] args) {
+		BIG m=new BIG(ROM.Modulus);
+		BIG e=new BIG(12);
+		BIG a=new BIG(0);
+		BIG b=new BIG(0);
+		
+		a.inc(27); b.inc(45);
+
+		FP2 w0=new FP2(a,b);
+
+		a.zero(); b.zero();
+		a.inc(33); b.inc(54);
+
+		FP2 w1=new FP2(a,b);
+
+
+		FP4 w=new FP4(w0,w1);
+		FP4 t=new FP4(w);
+
+		a=new BIG(ROM_ZZZ.CURVE_Fra);
+		b=new BIG(ROM_ZZZ.CURVE_Frb);
+
+		FP2 f=new FP2(a,b);
+
+		System.out.println("w= "+w.toString());
+
+		w=w.pow(m);
+
+		System.out.println("w^p= "+w.toString());
+
+		t.frob(f);
+
+
+		System.out.println("w^p= "+t.toString());
+
+		w=w.pow(m);
+		w=w.pow(m);
+		w=w.pow(m);
+		System.out.println("w^p4= "+w.toString());
+
+
+	System.out.println("Test Inversion");
+
+		w=new FP4(w0,w1);
+
+		w.inverse();
+
+		System.out.println("1/w mod p^4 = "+w.toString());
+
+		w.inverse();
+
+		System.out.println("1/(1/w) mod p^4 = "+w.toString());
+
+		FP4 ww=new FP4(w);
+
+		w=w.xtr_pow(e);
+		System.out.println("w^e= "+w.toString());
+
+
+		a.zero(); b.zero();
+		a.inc(37); b.inc(17);
+		w0=new FP2(a,b);
+		a.zero(); b.zero();
+		a.inc(49); b.inc(31);
+		w1=new FP2(a,b);
+
+		FP4 c1=new FP4(w0,w1);
+		FP4 c2=new FP4(w0,w1);
+		FP4 c3=new FP4(w0,w1);
+
+		BIG e1=new BIG(3331);
+		BIG e2=new BIG(3372);
+
+		FP4 cr=w.xtr_pow2(c1,c2,c3,e1,e2);
+
+		System.out.println("c^e= "+cr.toString()); 
+	} */
+}
diff --git a/version3/java/FP48.java b/version3/java/FP48.java
new file mode 100644
index 0000000..762f2b3
--- /dev/null
+++ b/version3/java/FP48.java
@@ -0,0 +1,1060 @@
+/*
+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.
+*/
+
+/* AMCL Fp^48 functions */
+/* FP48 elements are of the form a+i.b+i^2.c */
+
+package org.apache.milagro.amcl.XXX;
+
+public final class FP48 {
+	private final FP16 a;
+	private final FP16 b;
+	private final FP16 c;
+/* reduce all components of this mod Modulus */
+	public void reduce()
+	{
+		a.reduce();
+		b.reduce();
+		c.reduce();
+	}
+
+/* normalise all components of this */
+	public void norm()
+	{
+		a.norm();
+		b.norm();
+		c.norm();
+	}
+/* test x==0 ? */
+	public boolean iszilch() {
+		//reduce();
+		return (a.iszilch() && b.iszilch() && c.iszilch());
+	}
+
+	public void cmove(FP48 g,int d)
+	{
+		a.cmove(g.a,d);
+		b.cmove(g.b,d);
+		c.cmove(g.c,d);		
+	}
+
+
+/* return 1 if b==c, no branching */
+	public static int teq(int b,int c)
+	{
+		int x=b^c;
+		x-=1;  // if x=0, x now -1
+		return ((x>>31)&1);
+	}
+
+/* Constant time select from pre-computed table */
+	public void select(FP48 g[],int b)
+	{
+		int m=b>>31;
+		int babs=(b^m)-m;
+
+		babs=(babs-1)/2;
+
+		cmove(g[0],teq(babs,0));  // conditional move
+		cmove(g[1],teq(babs,1));
+		cmove(g[2],teq(babs,2));
+		cmove(g[3],teq(babs,3));
+		cmove(g[4],teq(babs,4));
+		cmove(g[5],teq(babs,5));
+		cmove(g[6],teq(babs,6));
+		cmove(g[7],teq(babs,7));
+ 
+		FP48 invf=new FP48(this); 
+		invf.conj();
+		cmove(invf,(int)(m&1));
+	}
+
+	/* test x==1 ? */
+	public boolean isunity() {
+		FP16 one=new FP16(1);
+		return (a.equals(one) && b.iszilch() && c.iszilch());
+	}
+/* return 1 if x==y, else 0 */
+	public boolean equals(FP48 x)
+	{
+		return (a.equals(x.a) && b.equals(x.b) && c.equals(x.c));
+	}
+/* extract a from this */
+	public FP16 geta()
+	{
+		return a;
+	}
+/* extract b */
+	public FP16 getb()
+	{
+		return b;
+	}
+/* extract c */
+	public FP16 getc()
+	{
+		return c;
+	}
+/* copy this=x */
+	public void copy(FP48 x)
+	{
+		a.copy(x.a);
+		b.copy(x.b);
+		c.copy(x.c);
+	}
+/* set this=1 */
+	public void one()
+	{
+		a.one();
+		b.zero();
+		c.zero();
+	}
+/* this=conj(this) */
+	public void conj()
+	{
+		a.conj();
+		b.nconj();
+		c.conj();
+	}
+/* Constructors */
+	public FP48(FP16 d)
+	{
+		a=new FP16(d);
+		b=new FP16(0);
+		c=new FP16(0);
+	}
+
+	public FP48(int d)
+	{
+		a=new FP16(d);
+		b=new FP16(0);
+		c=new FP16(0);
+	}
+
+	public FP48(FP16 d,FP16 e,FP16 f)
+	{
+		a=new FP16(d);
+		b=new FP16(e);
+		c=new FP16(f);
+	}
+
+	public FP48(FP48 x)
+	{
+		a=new FP16(x.a);
+		b=new FP16(x.b);
+		c=new FP16(x.c);
+	}
+
+/* Granger-Scott Unitary Squaring */
+	public void usqr()
+	{
+		FP16 A=new FP16(a);
+		FP16 B=new FP16(c);
+		FP16 C=new FP16(b);
+		FP16 D=new FP16(0);
+
+		a.sqr();
+		D.copy(a); D.add(a);
+		a.add(D);
+
+		a.norm();
+		A.nconj();
+
+		A.add(A);
+		a.add(A);
+		B.sqr();
+		B.times_i();
+
+		D.copy(B); D.add(B);
+		B.add(D);
+		B.norm();
+
+		C.sqr();
+		D.copy(C); D.add(C);
+		C.add(D);
+		C.norm();
+
+		b.conj();
+		b.add(b);
+		c.nconj();
+
+		c.add(c);
+		b.add(B);
+		c.add(C);
+		reduce();
+	}
+
+/* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
+	public void sqr()
+	{
+		FP16 A=new FP16(a);
+		FP16 B=new FP16(b);
+		FP16 C=new FP16(c);
+		FP16 D=new FP16(a);
+
+		A.sqr();
+		B.mul(c);
+		B.add(B);
+		B.norm();
+		C.sqr();
+		D.mul(b);
+		D.add(D);
+
+		c.add(a);
+		c.add(b);
+		c.norm();
+		c.sqr();
+
+		a.copy(A);
+
+		A.add(B);
+		A.norm();
+		A.add(C);
+		A.add(D);
+		A.norm();
+
+		A.neg();
+		B.times_i();
+		C.times_i();
+
+		a.add(B);
+
+		b.copy(C); b.add(D);
+		c.add(A);
+
+		norm();
+	}
+
+/* FP12 full multiplication this=this*y */
+	public void mul(FP48 y)
+	{
+		FP16 z0=new FP16(a);
+		FP16 z1=new FP16(0);
+		FP16 z2=new FP16(b);
+		FP16 z3=new FP16(0);
+		FP16 t0=new FP16(a);
+		FP16 t1=new FP16(y.a);
+
+		z0.mul(y.a);
+		z2.mul(y.b);
+
+		t0.add(b);
+		t1.add(y.b);
+
+		t0.norm();
+		t1.norm();
+
+		z1.copy(t0); z1.mul(t1);
+		t0.copy(b); t0.add(c);
+
+		t1.copy(y.b); t1.add(y.c);
+
+		t0.norm();
+		t1.norm();
+
+		z3.copy(t0); z3.mul(t1);
+
+		t0.copy(z0); t0.neg();
+		t1.copy(z2); t1.neg();
+
+		z1.add(t0);
+		//z1.norm();
+		b.copy(z1); b.add(t1);
+
+		z3.add(t1);
+		z2.add(t0);
+
+		t0.copy(a); t0.add(c);
+		t1.copy(y.a); t1.add(y.c);
+
+		t0.norm();
+		t1.norm();
+	
+		t0.mul(t1);
+		z2.add(t0);
+
+		t0.copy(c); t0.mul(y.c);
+		t1.copy(t0); t1.neg();
+
+		c.copy(z2); c.add(t1);
+		z3.add(t1);
+		t0.times_i();
+		b.add(t0);
+		z3.norm();
+		z3.times_i();
+		a.copy(z0); a.add(z3);
+		norm();
+
+	}
+
+/* Special case of multiplication arises from special form of ATE pairing line function */
+	public void smul(FP48 y,int type)
+	{
+		if (type==ECP.D_TYPE)
+		{
+			FP16 z0=new FP16(a);
+			FP16 z2=new FP16(b);
+			FP16 z3=new FP16(b);
+			FP16 t0=new FP16(0);
+			FP16 t1=new FP16(y.a);
+			z0.mul(y.a);
+			z2.pmul(y.b.real());
+			b.add(a);
+			t1.real().add(y.b.real());
+
+			t1.norm();
+			b.norm();
+			b.mul(t1);
+			z3.add(c);
+			z3.norm();
+			z3.pmul(y.b.real());
+
+			t0.copy(z0); t0.neg();
+			t1.copy(z2); t1.neg();
+
+			b.add(t0);
+
+			b.add(t1);
+			z3.add(t1);
+			z2.add(t0);
+
+			t0.copy(a); t0.add(c);
+			t0.norm();
+			z3.norm();
+			t0.mul(y.a);
+			c.copy(z2); c.add(t0);
+
+			z3.times_i();
+			a.copy(z0); a.add(z3);
+		}
+		if (type==ECP.M_TYPE)
+		{
+			FP16 z0=new FP16(a);
+			FP16 z1=new FP16(0);
+			FP16 z2=new FP16(0);
+			FP16 z3=new FP16(0);
+			FP16 t0=new FP16(a);
+			FP16 t1=new FP16(0);
+		
+			z0.mul(y.a);
+			t0.add(b);
+			t0.norm();
+
+			z1.copy(t0); z1.mul(y.a);
+			t0.copy(b); t0.add(c);
+			t0.norm();
+
+			z3.copy(t0); //z3.mul(y.c);
+			z3.pmul(y.c.getb());
+			z3.times_i();
+
+			t0.copy(z0); t0.neg();
+
+			z1.add(t0);
+			b.copy(z1); 
+			z2.copy(t0);
+
+			t0.copy(a); t0.add(c);
+			t1.copy(y.a); t1.add(y.c);
+
+			t0.norm();
+			t1.norm();
+	
+			t0.mul(t1);
+			z2.add(t0);
+
+			t0.copy(c); 
+			
+			t0.pmul(y.c.getb());
+			t0.times_i();
+
+			t1.copy(t0); t1.neg();
+
+			c.copy(z2); c.add(t1);
+			z3.add(t1);
+			t0.times_i();
+			b.add(t0);
+			z3.norm();
+			z3.times_i();
+			a.copy(z0); a.add(z3);
+		}
+		norm();
+	}
+
+/* this=1/this */
+	public void inverse()
+	{
+		FP16 f0=new FP16(a);
+		FP16 f1=new FP16(b);
+		FP16 f2=new FP16(a);
+		FP16 f3=new FP16(0);
+
+		norm();
+		f0.sqr();
+		f1.mul(c);
+		f1.times_i();
+		f0.sub(f1);
+		f0.norm();
+
+		f1.copy(c); f1.sqr();
+		f1.times_i();
+		f2.mul(b);
+		f1.sub(f2);
+		f1.norm();
+
+		f2.copy(b); f2.sqr();
+		f3.copy(a); f3.mul(c);
+		f2.sub(f3);
+		f2.norm();
+
+		f3.copy(b); f3.mul(f2);
+		f3.times_i();
+		a.mul(f0);
+		f3.add(a);
+		c.mul(f1);
+		c.times_i();
+
+		f3.add(c);
+		f3.norm();
+		f3.inverse();
+		a.copy(f0); a.mul(f3);
+		b.copy(f1); b.mul(f3);
+		c.copy(f2); c.mul(f3);
+	}
+
+/* this=this^p using Frobenius */
+	public void frob(FP2 f,int n)
+	{
+		FP2 f2=new FP2(f);
+		FP2 f3=new FP2(f);
+
+		f2.sqr();
+		f3.mul(f2);
+
+		f3.mul_ip(); f3.norm();
+		f3.mul_ip(); f3.norm();
+
+		for (int i=0;i<n;i++)
+		{
+			a.frob(f3);
+			b.frob(f3);
+			c.frob(f3);
+
+			b.qmul(f); b.times_i4(); b.times_i2(); 
+			c.qmul(f2); c.times_i4(); c.times_i4(); c.times_i4(); 
+		}
+	}
+
+/* trace function */
+	public FP16 trace()
+	{
+		FP16 t=new FP16(0);
+		t.copy(a);
+		t.imul(3);
+		t.reduce();
+		return t;
+	}
+
+/* convert from byte array to FP12 */
+	public static FP48 fromBytes(byte[] w)
+	{
+		BIG a,b;
+		FP2 c,d;
+		FP4 ea,eb;
+		FP8 fa,fb;
+		FP16 e,f,g;
+		byte[] t=new byte[BIG.MODBYTES];
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+BIG.MODBYTES];
+		b=BIG.fromBytes(t);
+		c=new FP2(a,b);
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+2*BIG.MODBYTES];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+3*BIG.MODBYTES];
+		b=BIG.fromBytes(t);
+		d=new FP2(a,b);
+
+		ea=new FP4(c,d);
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+4*BIG.MODBYTES];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+5*BIG.MODBYTES];
+		b=BIG.fromBytes(t);
+		c=new FP2(a,b);
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+6*BIG.MODBYTES];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+7*BIG.MODBYTES];
+		b=BIG.fromBytes(t);
+		d=new FP2(a,b);
+
+		eb=new FP4(c,d);
+
+		fa=new FP8(ea,eb);
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+8*BIG.MODBYTES];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+9*BIG.MODBYTES];
+		b=BIG.fromBytes(t);
+		c=new FP2(a,b);
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+10*BIG.MODBYTES];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+11*BIG.MODBYTES];
+		b=BIG.fromBytes(t);
+		d=new FP2(a,b);
+
+		ea=new FP4(c,d);
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+12*BIG.MODBYTES];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+13*BIG.MODBYTES];
+		b=BIG.fromBytes(t);
+		c=new FP2(a,b);
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+14*BIG.MODBYTES];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+15*BIG.MODBYTES];
+		b=BIG.fromBytes(t);
+		d=new FP2(a,b);
+
+		eb=new FP4(c,d);
+
+		fb=new FP8(ea,eb);
+
+		e=new FP16(fa,fb);
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+16*BIG.MODBYTES];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+17*BIG.MODBYTES];
+		b=BIG.fromBytes(t);
+		c=new FP2(a,b);
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+18*BIG.MODBYTES];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+19*BIG.MODBYTES];
+		b=BIG.fromBytes(t);
+		d=new FP2(a,b);
+
+		ea=new FP4(c,d);
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+20*BIG.MODBYTES];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+21*BIG.MODBYTES];
+		b=BIG.fromBytes(t);
+		c=new FP2(a,b);
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+22*BIG.MODBYTES];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+23*BIG.MODBYTES];
+		b=BIG.fromBytes(t);
+		d=new FP2(a,b);
+
+		eb=new FP4(c,d);
+
+		fa=new FP8(ea,eb);
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+24*BIG.MODBYTES];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+25*BIG.MODBYTES];
+		b=BIG.fromBytes(t);
+		c=new FP2(a,b);
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+26*BIG.MODBYTES];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+27*BIG.MODBYTES];
+		b=BIG.fromBytes(t);
+		d=new FP2(a,b);
+
+		ea=new FP4(c,d);
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+28*BIG.MODBYTES];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+29*BIG.MODBYTES];
+		b=BIG.fromBytes(t);
+		c=new FP2(a,b);
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+30*BIG.MODBYTES];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+31*BIG.MODBYTES];
+		b=BIG.fromBytes(t);
+		d=new FP2(a,b);
+
+		eb=new FP4(c,d);
+
+		fb=new FP8(ea,eb);
+
+		f=new FP16(fa,fb);
+
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+32*BIG.MODBYTES];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+33*BIG.MODBYTES];
+		b=BIG.fromBytes(t);
+		c=new FP2(a,b);
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+34*BIG.MODBYTES];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+35*BIG.MODBYTES];
+		b=BIG.fromBytes(t);
+		d=new FP2(a,b);
+
+		ea=new FP4(c,d);
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+36*BIG.MODBYTES];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+37*BIG.MODBYTES];
+		b=BIG.fromBytes(t);
+		c=new FP2(a,b);
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+38*BIG.MODBYTES];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+39*BIG.MODBYTES];
+		b=BIG.fromBytes(t);
+		d=new FP2(a,b);
+
+		eb=new FP4(c,d);
+
+		fa=new FP8(ea,eb);
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+40*BIG.MODBYTES];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+41*BIG.MODBYTES];
+		b=BIG.fromBytes(t);
+		c=new FP2(a,b);
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+42*BIG.MODBYTES];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+43*BIG.MODBYTES];
+		b=BIG.fromBytes(t);
+		d=new FP2(a,b);
+
+		ea=new FP4(c,d);
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+44*BIG.MODBYTES];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+45*BIG.MODBYTES];
+		b=BIG.fromBytes(t);
+		c=new FP2(a,b);
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+46*BIG.MODBYTES];
+		a=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=w[i+47*BIG.MODBYTES];
+		b=BIG.fromBytes(t);
+		d=new FP2(a,b);
+
+		eb=new FP4(c,d);
+
+		fb=new FP8(ea,eb);
+
+		g=new FP16(fa,fb);
+
+		return new FP48(e,f,g);
+	}
+
+/* convert this to byte array */
+	public void toBytes(byte[] w)
+	{
+		byte[] t=new byte[BIG.MODBYTES];
+
+		a.geta().geta().geta().getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i]=t[i];
+		a.geta().geta().geta().getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+BIG.MODBYTES]=t[i];
+		a.geta().geta().getb().getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+2*BIG.MODBYTES]=t[i];
+		a.geta().geta().getb().getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+3*BIG.MODBYTES]=t[i];
+
+		a.geta().getb().geta().getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+4*BIG.MODBYTES]=t[i];
+		a.geta().getb().geta().getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+5*BIG.MODBYTES]=t[i];
+		a.geta().getb().getb().getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+6*BIG.MODBYTES]=t[i];
+		a.geta().getb().getb().getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+7*BIG.MODBYTES]=t[i];
+		a.getb().geta().geta().getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+8*BIG.MODBYTES]=t[i];
+		a.getb().geta().geta().getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+9*BIG.MODBYTES]=t[i];
+		a.getb().geta().getb().getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+10*BIG.MODBYTES]=t[i];
+		a.getb().geta().getb().getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+11*BIG.MODBYTES]=t[i];
+		a.getb().getb().geta().getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+12*BIG.MODBYTES]=t[i];
+		a.getb().getb().geta().getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+13*BIG.MODBYTES]=t[i];
+		a.getb().getb().getb().getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+14*BIG.MODBYTES]=t[i];
+		a.getb().getb().getb().getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+15*BIG.MODBYTES]=t[i];
+
+		b.geta().geta().geta().getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+16*BIG.MODBYTES]=t[i];
+		b.geta().geta().geta().getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+17*BIG.MODBYTES]=t[i];
+		b.geta().geta().getb().getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+18*BIG.MODBYTES]=t[i];
+		b.geta().geta().getb().getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+19*BIG.MODBYTES]=t[i];
+
+		b.geta().getb().geta().getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+20*BIG.MODBYTES]=t[i];
+		b.geta().getb().geta().getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+21*BIG.MODBYTES]=t[i];
+		b.geta().getb().getb().getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+22*BIG.MODBYTES]=t[i];
+		b.geta().getb().getb().getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+23*BIG.MODBYTES]=t[i];
+		b.getb().geta().geta().getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+24*BIG.MODBYTES]=t[i];
+		b.getb().geta().geta().getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+25*BIG.MODBYTES]=t[i];
+		b.getb().geta().getb().getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+26*BIG.MODBYTES]=t[i];
+		b.getb().geta().getb().getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+27*BIG.MODBYTES]=t[i];
+		b.getb().getb().geta().getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+28*BIG.MODBYTES]=t[i];
+		b.getb().getb().geta().getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+29*BIG.MODBYTES]=t[i];
+		b.getb().getb().getb().getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+30*BIG.MODBYTES]=t[i];
+		b.getb().getb().getb().getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+31*BIG.MODBYTES]=t[i];
+
+
+		c.geta().geta().geta().getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+32*BIG.MODBYTES]=t[i];
+		c.geta().geta().geta().getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+33*BIG.MODBYTES]=t[i];
+		c.geta().geta().getb().getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+34*BIG.MODBYTES]=t[i];
+		c.geta().geta().getb().getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+35*BIG.MODBYTES]=t[i];
+		c.geta().getb().geta().getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+36*BIG.MODBYTES]=t[i];
+		c.geta().getb().geta().getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+37*BIG.MODBYTES]=t[i];
+		c.geta().getb().getb().getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+38*BIG.MODBYTES]=t[i];
+		c.geta().getb().getb().getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+39*BIG.MODBYTES]=t[i];
+		c.getb().geta().geta().getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+40*BIG.MODBYTES]=t[i];
+		c.getb().geta().geta().getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+41*BIG.MODBYTES]=t[i];
+		c.getb().geta().getb().getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+42*BIG.MODBYTES]=t[i];
+		c.getb().geta().getb().getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+43*BIG.MODBYTES]=t[i];
+		c.getb().getb().geta().getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+44*BIG.MODBYTES]=t[i];
+		c.getb().getb().geta().getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+45*BIG.MODBYTES]=t[i];
+		c.getb().getb().getb().getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+46*BIG.MODBYTES]=t[i];
+		c.getb().getb().getb().getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) w[i+47*BIG.MODBYTES]=t[i];
+	}
+
+/* convert to hex string */
+	public String toString() 
+	{
+		return ("["+a.toString()+","+b.toString()+","+c.toString()+"]");
+	}
+
+/* this=this^e */ 
+/* Note this is simple square and multiply, so not side-channel safe */
+	public FP48 pow(BIG e)
+	{
+		FP48 sf=new FP48(this);
+
+		sf.norm();
+		BIG e1=new BIG(e);
+		e1.norm();
+		BIG e3=new BIG(e1);
+		e3.pmul(3);
+		e3.norm();
+
+		FP48 w=new FP48(sf);
+
+		int nb=e3.nbits();
+		for (int i=nb-2;i>=1;i--)
+		{
+			w.usqr();
+			int bt=e3.bit(i)-e1.bit(i);
+			if (bt==1)
+				w.mul(sf);
+			if (bt==-1)
+			{
+				sf.conj(); w.mul(sf); sf.conj();
+			}
+		}
+		w.reduce();
+		return w;
+
+	}
+
+/* constant time powering by small integer of max length bts */
+	public void pinpow(int e,int bts)
+	{
+		int i,b;
+		FP48 [] R=new FP48[2];
+		R[0]=new FP48(1);
+		R[1]=new FP48(this);
+		for (i=bts-1;i>=0;i--)
+		{
+			b=(e>>i)&1;
+			R[1-b].mul(R[b]);
+			R[b].usqr();
+		}
+		this.copy(R[0]);
+	}
+
+	public FP16 compow(BIG e,BIG r)
+	{
+		FP48 g1=new FP48(0);
+		FP48 g2=new FP48(0);
+		FP2 f=new FP2(new BIG(ROM.Fra),new BIG(ROM.Frb));
+		BIG q=new BIG(ROM.Modulus);
+
+		BIG m=new BIG(q);
+		m.mod(r);
+
+		BIG a=new BIG(e);
+		a.mod(m);
+
+		BIG b=new BIG(e);
+		b.div(m);
+
+		g1.copy(this);
+		g2.copy(this);
+
+		FP16 c=g1.trace();
+
+		if (b.iszilch())
+		{
+			c=c.xtr_pow(e);
+			return c;
+		}
+
+		g2.frob(f,1);
+		FP16 cp=g2.trace();
+		g1.conj();
+		g2.mul(g1);
+		FP16 cpm1=g2.trace();
+		g2.mul(g1);
+		FP16 cpm2=g2.trace();
+
+		c=c.xtr_pow2(cp,cpm1,cpm2,a,b);
+
+		return c;
+	}
+
+/* p=q0^u0.q1^u1.q2^u2.q3^u3.... */
+// Bos & Costello https://eprint.iacr.org/2013/458.pdf
+// Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
+// Side channel attack secure 
+
+	public static FP48 pow16(FP48[] q,BIG[] u)
+	{
+		int i,j,k,nb,pb1,pb2,pb3,pb4;
+		FP48 [] g1=new FP48[8];
+		FP48 [] g2=new FP48[8];
+		FP48 [] g3=new FP48[8];
+		FP48 [] g4=new FP48[8];
+		FP48 r=new FP48(1);
+		FP48 p=new FP48(0);
+		BIG [] t=new BIG[16];
+		BIG mt=new BIG(0);
+		byte[] w1=new byte[BIG.NLEN*BIG.BASEBITS+1];
+		byte[] s1=new byte[BIG.NLEN*BIG.BASEBITS+1];
+		byte[] w2=new byte[BIG.NLEN*BIG.BASEBITS+1];
+		byte[] s2=new byte[BIG.NLEN*BIG.BASEBITS+1];
+		byte[] w3=new byte[BIG.NLEN*BIG.BASEBITS+1];
+		byte[] s3=new byte[BIG.NLEN*BIG.BASEBITS+1];
+		byte[] w4=new byte[BIG.NLEN*BIG.BASEBITS+1];
+		byte[] s4=new byte[BIG.NLEN*BIG.BASEBITS+1];
+
+		for (i=0;i<16;i++)
+		{
+			t[i]=new BIG(u[i]);
+			t[i].norm();
+		}
+
+		g1[0]=new FP48(q[0]);  // q[0]
+		g1[1]=new FP48(g1[0]); g1[1].mul(q[1]); // q[0].q[1]
+		g1[2]=new FP48(g1[0]); g1[2].mul(q[2]); // q[0].q[2]
+		g1[3]=new FP48(g1[1]); g1[3].mul(q[2]); // q[0].q[1].q[2]
+		g1[4]=new FP48(q[0]);  g1[4].mul(q[3]); // q[0].q[3]
+		g1[5]=new FP48(g1[1]); g1[5].mul(q[3]); // q[0].q[1].q[3]
+		g1[6]=new FP48(g1[2]); g1[6].mul(q[3]); // q[0].q[2].q[3]
+		g1[7]=new FP48(g1[3]); g1[7].mul(q[3]); // q[0].q[1].q[2].q[3]
+
+// Use Frobenius
+		FP2 f=new FP2(new BIG(ROM.Fra),new BIG(ROM.Frb));
+		for (i=0;i<8;i++)
+		{
+			g2[i]=new FP48(g1[i]);
+			g2[i].frob(f,4);
+			g3[i]=new FP48(g2[i]);
+			g3[i].frob(f,4);
+			g4[i]=new FP48(g3[i]);
+			g4[i].frob(f,4);
+		}
+
+    // Make it odd
+        pb1=1-t[0].parity();
+        t[0].inc(pb1);
+        t[0].norm();
+
+        pb2=1-t[4].parity();
+        t[4].inc(pb2);
+        t[4].norm();
+
+        pb3=1-t[8].parity();
+        t[8].inc(pb3);
+        t[8].norm();
+
+        pb4=1-t[12].parity();
+        t[12].inc(pb4);
+        t[12].norm();
+
+
+    // Number of bits
+        mt.zero();
+        for (i=0;i<16;i++) {
+            mt.or(t[i]);
+        }
+        nb=1+mt.nbits();
+
+    // Sign pivot 
+        s1[nb-1]=1;
+		s2[nb-1]=1;
+        s3[nb-1]=1;
+		s4[nb-1]=1;
+        for (i=0;i<nb-1;i++) {
+            t[0].fshr(1);
+            s1[i]=(byte)(2*t[0].parity()-1);
+            t[4].fshr(1);
+            s2[i]=(byte)(2*t[4].parity()-1);
+            t[8].fshr(1);
+            s3[i]=(byte)(2*t[8].parity()-1);
+            t[12].fshr(1);
+            s4[i]=(byte)(2*t[12].parity()-1);
+ 
+        }
+
+    // Recoded exponent
+        for (i=0; i<nb; i++) {
+            w1[i]=0;
+            k=1;
+            for (j=1; j<4; j++) {
+                byte bt=(byte)(s1[i]*t[j].parity());
+                t[j].fshr(1);
+                t[j].dec((int)(bt)>>1);
+                t[j].norm();
+                w1[i]+=bt*(byte)k;
+                k*=2;
+            }
+
+            w2[i]=0;
+            k=1;
+            for (j=5; j<8; j++) {
+                byte bt=(byte)(s2[i]*t[j].parity());
+                t[j].fshr(1);
+                t[j].dec((int)(bt)>>1);
+                t[j].norm();
+                w2[i]+=bt*(byte)k;
+                k*=2;
+            }
+
+            w3[i]=0;
+            k=1;
+            for (j=9; j<12; j++) {
+                byte bt=(byte)(s3[i]*t[j].parity());
+                t[j].fshr(1);
+                t[j].dec((int)(bt)>>1);
+                t[j].norm();
+                w3[i]+=bt*(byte)k;
+                k*=2;
+            }
+
+            w4[i]=0;
+            k=1;
+            for (j=13; j<16; j++) {
+                byte bt=(byte)(s4[i]*t[j].parity());
+                t[j].fshr(1);
+                t[j].dec((int)(bt)>>1);
+                t[j].norm();
+                w4[i]+=bt*(byte)k;
+                k*=2;
+            }
+
+        } 
+
+
+     // Main loop
+        p.select(g1,(int)(2*w1[nb-1]+1)); 
+		r.select(g2,(int)(2*w2[nb-1]+1)); 
+		p.mul(r);
+		r.select(g3,(int)(2*w3[nb-1]+1)); 
+		p.mul(r);
+		r.select(g4,(int)(2*w4[nb-1]+1)); 
+		p.mul(r);
+
+        for (i=nb-2;i>=0;i--) {
+            p.usqr();
+            r.select(g1,(int)(2*w1[i]+s1[i]));
+            p.mul(r);
+            r.select(g2,(int)(2*w2[i]+s2[i]));
+            p.mul(r);
+            r.select(g3,(int)(2*w3[i]+s3[i]));
+            p.mul(r);
+            r.select(g4,(int)(2*w4[i]+s4[i]));
+            p.mul(r);
+
+        }
+
+    // apply correction
+        r.copy(q[0]); r.conj();   
+        r.mul(p);
+        p.cmove(r,pb1);
+
+        r.copy(q[4]); r.conj();   
+        r.mul(p);
+        p.cmove(r,pb2);
+
+        r.copy(q[8]); r.conj();   
+        r.mul(p);
+        p.cmove(r,pb3);
+
+        r.copy(q[12]); r.conj();   
+        r.mul(p);
+        p.cmove(r,pb4);
+
+ 		p.reduce();
+		return p;
+	}              
+}
diff --git a/version3/java/FP64.java b/version3/java/FP64.java
new file mode 100644
index 0000000..170f02a
--- /dev/null
+++ b/version3/java/FP64.java
@@ -0,0 +1,682 @@
+/*
+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.
+*/
+
+/* Finite Field arithmetic */
+/* AMCL mod p functions */
+
+package org.apache.milagro.amcl.XXX;
+
+public final class FP {
+
+	public static final int NOT_SPECIAL=0;
+	public static final int PSEUDO_MERSENNE=1;
+	public static final int MONTGOMERY_FRIENDLY=2;
+	public static final int GENERALISED_MERSENNE=3;
+
+	public static final int MODBITS=@NBT@; /* Number of bits in Modulus */
+	public static final int MOD8=@M8@;  /* Modulus mod 8 */
+	public static final int MODTYPE=@MT@;
+
+	public static final int FEXCESS = (((int)1<<@SH@)-1);  // BASEBITS*NLEN-MODBITS or 2^30 max!
+	public static final long OMASK=(long)(-1)<<(MODBITS%BIG.BASEBITS);
+	public static final int TBITS=MODBITS%BIG.BASEBITS; // Number of active bits in top word 
+	public static final long TMASK=((long)1<<TBITS)-1;
+
+
+	public final BIG x;
+	//public BIG p=new BIG(ROM.Modulus);
+	//public BIG r2modp=new BIG(ROM.R2modp);
+	public int XES;
+
+/**************** 64-bit specific ************************/
+
+/* reduce a DBIG to a BIG using the appropriate form of the modulus */
+	public static BIG mod(DBIG d)
+	{
+		if (MODTYPE==PSEUDO_MERSENNE)
+		{
+			BIG b;		
+			long v,tw;
+			BIG t=d.split(MODBITS);
+			b=new BIG(d);
+
+			v=t.pmul((int)ROM.MConst);
+
+			t.add(b);
+			t.norm();
+
+			tw=t.w[BIG.NLEN-1];
+			t.w[BIG.NLEN-1]&=FP.TMASK;
+			t.w[0]+=(ROM.MConst*((tw>>TBITS)+(v<<(BIG.BASEBITS-TBITS))));
+
+			t.norm();
+			return t;			
+		}
+		if (FP.MODTYPE==MONTGOMERY_FRIENDLY)
+		{
+			BIG b;		
+			long[] cr=new long[2];
+			for (int i=0;i<BIG.NLEN;i++)
+			{
+				cr=BIG.muladd(d.w[i],ROM.MConst-1,d.w[i],d.w[BIG.NLEN+i-1]);
+				d.w[BIG.NLEN+i]+=cr[0];
+				d.w[BIG.NLEN+i-1]=cr[1];
+			}
+			
+			b=new BIG(0);
+			for (int i=0;i<BIG.NLEN;i++ )
+				b.w[i]=d.w[BIG.NLEN+i];
+			b.norm();
+			return b;		
+		}
+		if (MODTYPE==GENERALISED_MERSENNE)
+		{ // GoldiLocks Only
+			BIG b;		
+			BIG t=d.split(MODBITS);
+			b=new BIG(d);
+			b.add(t);
+			DBIG dd=new DBIG(t);
+			dd.shl(MODBITS/2);
+
+			BIG tt=dd.split(MODBITS);
+			BIG lo=new BIG(dd);
+			b.add(tt);
+			b.add(lo);
+			b.norm();
+			tt.shl(MODBITS/2);
+			b.add(tt);
+
+			long carry=b.w[BIG.NLEN-1]>>TBITS;
+			b.w[BIG.NLEN-1]&=FP.TMASK;
+			b.w[0]+=carry;
+			
+			b.w[224/BIG.BASEBITS]+=carry<<(224%BIG.BASEBITS);
+			b.norm();
+			return b;		
+		}
+		if (MODTYPE==NOT_SPECIAL)
+		{
+			return BIG.monty(new BIG(ROM.Modulus),ROM.MConst,d);
+		}
+
+		return new BIG(0);
+	}
+
+	private static int quo(BIG n,BIG m)
+	{
+		int sh;
+		long num,den;
+		int hb=BIG.CHUNK/2;
+		if (TBITS<hb)
+		{
+			sh=hb-TBITS;
+			num=(n.w[BIG.NLEN-1]<<sh)|(n.w[BIG.NLEN-2]>>(BIG.BASEBITS-sh));
+			den=(m.w[BIG.NLEN-1]<<sh)|(m.w[BIG.NLEN-2]>>(BIG.BASEBITS-sh));
+		}
+		else
+		{
+			num=n.w[BIG.NLEN-1];
+			den=m.w[BIG.NLEN-1];
+		}
+		return (int)(num/(den+1));
+	}
+
+/* reduce this mod Modulus */
+	public void reduce()
+	{
+		BIG m=new BIG(ROM.Modulus);
+		BIG r=new BIG(ROM.Modulus);
+		int sr,sb,q;
+		long carry;
+		x.norm();
+
+		if (XES>16)
+		{
+			q=quo(x,m);
+			carry=r.pmul(q);
+			r.w[BIG.NLEN-1]+=(carry<<BIG.BASEBITS); // correction - put any carry out back in again
+			x.sub(r);
+			x.norm();
+			sb=2;
+		}
+		else  sb=logb2(XES-1);
+
+		m.fshl(sb);
+		while (sb>0)
+		{
+// constant time...
+			sr=BIG.ssn(r,x,m);  // optimized combined shift, subtract and norm
+			x.cmove(r,1-sr);
+			sb--;
+		}
+
+		XES=1;
+	}
+
+/*********************************************************/
+
+
+/* Constructors */
+	public FP(int a)
+	{
+		x=new BIG(a);
+		nres();
+	}
+
+	public FP()
+	{
+		x=new BIG(0);
+		XES=1;
+	}
+
+	public FP(BIG a)
+	{
+		x=new BIG(a);
+		nres();
+	}
+	
+	public FP(FP a)
+	{
+		x=new BIG(a.x);
+		XES=a.XES;
+	}
+
+/* convert to string */
+	public String toString() 
+	{
+		String s=redc().toString();
+		return s;
+	}
+
+	public String toRawString() 
+	{
+		String s=x.toRawString();
+		return s;
+	}
+
+/* convert to Montgomery n-residue form */
+	public void nres()
+	{
+		if (MODTYPE!=PSEUDO_MERSENNE && MODTYPE!=GENERALISED_MERSENNE)
+		{
+			DBIG d=BIG.mul(x,new BIG(ROM.R2modp));  /*** Change ***/
+			x.copy(mod(d));
+			XES=2;
+		}
+		else XES=1;
+	}
+
+/* convert back to regular form */
+	public BIG redc()
+	{
+		if (MODTYPE!=PSEUDO_MERSENNE && MODTYPE!=GENERALISED_MERSENNE)
+		{
+			DBIG d=new DBIG(x);
+			return mod(d);
+		}
+		else 
+		{
+			BIG r=new BIG(x);
+			return r;
+		}
+	}
+
+/* test this=0? */
+	public boolean iszilch() {
+		FP z=new FP(this);
+		z.reduce();
+		return z.x.iszilch();
+
+	}
+
+/* copy from FP b */
+	public void copy(FP b)
+	{
+		x.copy(b.x);
+		XES=b.XES;
+	}
+
+/* set this=0 */
+	public void zero()
+	{
+		x.zero();
+		XES=1;
+	}
+	
+/* set this=1 */
+	public void one()
+	{
+		x.one(); nres();
+	}
+
+/* normalise this */
+	public void norm()
+	{
+		x.norm();
+	}
+
+/* swap FPs depending on d */
+	public void cswap(FP b,int d)
+	{
+		x.cswap(b.x,d);
+		int t,c=d;
+		c=~(c-1);
+		t=c&(XES^b.XES);
+		XES^=t;
+		b.XES^=t;
+	}
+
+/* copy FPs depending on d */
+	public void cmove(FP b,int d)
+	{
+		x.cmove(b.x,d);
+		XES^=(XES^b.XES)&(-d);
+
+	}
+
+/* this*=b mod Modulus */
+	public void mul(FP b)
+	{
+		if ((long)XES*b.XES>(long)FEXCESS) reduce();
+
+		DBIG d=BIG.mul(x,b.x);
+		x.copy(mod(d));
+		XES=2;
+	}
+
+/* this*=c mod Modulus, where c is a small int */
+	public void imul(int c)
+	{
+//		norm();
+		boolean s=false;
+		if (c<0)
+		{
+			c=-c;
+			s=true;
+		}
+
+		if (MODTYPE==PSEUDO_MERSENNE || MODTYPE==GENERALISED_MERSENNE)
+		{
+			DBIG d=x.pxmul(c);
+			x.copy(mod(d));
+			XES=2;
+		}
+		else
+		{
+			if (XES*c<=FEXCESS)
+			{
+				x.pmul(c);
+				XES*=c;
+			}
+			else
+			{  // this is not good
+				FP n=new FP(c);
+				mul(n);
+			}
+		}
+		
+/*
+		if (c<=BIG.NEXCESS && XES*c<=FEXCESS)
+		{
+			x.imul(c);
+			XES*=c;
+			x.norm();
+		}
+		else
+		{
+			DBIG d=x.pxmul(c);
+			x.copy(mod(d));
+			XES=2;
+		}
+*/
+		if (s) {neg(); norm();}
+
+	}
+
+/* this*=this mod Modulus */
+	public void sqr()
+	{
+		DBIG d;
+		if ((long)XES*XES>(long)FEXCESS) reduce();
+
+		d=BIG.sqr(x);	
+		x.copy(mod(d));
+		XES=2;
+	}
+
+/* this+=b */
+	public void add(FP b) {
+		x.add(b.x);
+		XES+=b.XES;
+		if (XES>FEXCESS) reduce();
+	}
+
+// https://graphics.stanford.edu/~seander/bithacks.html
+// constant time log to base 2 (or number of bits in)
+
+	private static int logb2(int v)
+	{
+		int r;
+		v |= v >>> 1;
+		v |= v >>> 2;
+		v |= v >>> 4;
+		v |= v >>> 8;
+		v |= v >>> 16;
+
+		v = v - ((v >>> 1) & 0x55555555);                  
+		v = (v & 0x33333333) + ((v >>> 2) & 0x33333333);  
+		r = ((v + (v >>> 4) & 0xF0F0F0F) * 0x1010101) >>> 24; 
+		return r;
+	}
+
+/* this = -this mod Modulus */
+	public void neg()
+	{
+		int sb;
+		BIG m=new BIG(ROM.Modulus);
+
+		sb=logb2(XES-1);
+		m.fshl(sb);
+		x.rsub(m);		
+
+		XES=(1<<sb)+1;
+		if (XES>FEXCESS) reduce();
+	}
+
+/* this-=b */
+	public void sub(FP b)
+	{
+		FP n=new FP(b);
+		n.neg();
+		this.add(n);
+	}
+
+	public void rsub(FP b)
+	{
+		FP n=new FP(this);
+		n.neg();
+		this.copy(b);
+		this.add(n);
+	}
+
+/* this/=2 mod Modulus */
+	public void div2()
+	{
+		if (x.parity()==0)
+			x.fshr(1);
+		else
+		{
+			x.add(new BIG(ROM.Modulus));
+			x.norm();
+			x.fshr(1);
+		}
+	}
+
+// this^(p-3)/4 or this^(p-5)/8
+	private FP fpow()
+	{
+		int i,j,k,bw,w,c,nw,lo,m,n;
+		FP [] xp=new FP[11];
+		int[]  ac={1,2,3,6,12,15,30,60,120,240,255};
+// phase 1
+			
+		xp[0]=new FP(this);	// 1 
+		xp[1]=new FP(this); xp[1].sqr(); // 2
+		xp[2]=new FP(xp[1]); xp[2].mul(this);  //3
+		xp[3]=new FP(xp[2]); xp[3].sqr();  // 6 
+		xp[4]=new FP(xp[3]); xp[4].sqr();  // 12
+		xp[5]=new FP(xp[4]); xp[5].mul(xp[2]);  // 15
+		xp[6]=new FP(xp[5]); xp[6].sqr();  // 30
+		xp[7]=new FP(xp[6]); xp[7].sqr();  // 60
+		xp[8]=new FP(xp[7]); xp[8].sqr();  // 120
+		xp[9]=new FP(xp[8]); xp[9].sqr();  // 240
+		xp[10]=new FP(xp[9]); xp[10].mul(xp[5]);  // 255		
+			
+		if (MOD8==5)
+		{
+			n=MODBITS-3;
+			c=(int)(ROM.MConst+5)/8;
+		} else {
+			n=MODBITS-2;
+			c=(int)(ROM.MConst+3)/4;
+		}
+
+		bw=0; w=1; while (w<c) {w*=2; bw+=1;}
+		k=w-c;
+
+		FP key=new FP(); i=10;
+		if (k!=0)
+		{
+			while (ac[i]>k) i--;
+			key.copy(xp[i]); 
+			k-=ac[i];
+		}
+		while (k!=0)
+		{
+			i--;
+			if (ac[i]>k) continue;
+			key.mul(xp[i]);
+			k-=ac[i]; 
+		}
+
+// phase 2 
+		xp[1].copy(xp[2]);
+		xp[2].copy(xp[5]);
+		xp[3].copy(xp[10]);
+
+		j=3; m=8;
+		nw=n-bw;
+		FP t=new FP();
+
+		while (2*m<nw)
+		{
+			t.copy(xp[j++]);
+			for (i=0;i<m;i++)
+				t.sqr(); 
+			xp[j].copy(xp[j-1]);
+			xp[j].mul(t);
+			m*=2;
+		}
+
+		lo=nw-m;
+		FP r=new FP(xp[j]);
+
+		while (lo!=0)
+		{
+			m/=2; j--;
+			if (lo<m) continue;
+			lo-=m;
+			t.copy(r);
+			for (i=0;i<m;i++)
+				t.sqr();
+			r.copy(t);
+			r.mul(xp[j]);
+		}
+
+// phase 3
+		for (i=0;i<bw;i++ )
+			r.sqr();
+
+		if (w-c!=0)
+			r.mul(key); 
+		return r;
+	}
+
+/* this=1/this mod Modulus */
+	public void inverse()
+	{
+
+		if (MODTYPE==PSEUDO_MERSENNE)
+		{
+			FP y=fpow();
+			if (MOD8==5)
+			{
+				FP t=new FP(this);
+				t.sqr();
+				mul(t);
+				y.sqr();
+
+			} 
+			y.sqr();
+			y.sqr();
+			mul(y);
+		} else {
+			BIG m2=new BIG(ROM.Modulus);
+			m2.dec(2); m2.norm();
+			copy(pow(m2));
+		}
+	}
+
+/* return TRUE if this==a */
+	public boolean equals(FP a)
+	{
+		FP f=new FP(this);
+		FP s=new FP(a);
+		f.reduce();
+		s.reduce();
+		if (BIG.comp(f.x,s.x)==0) return true;
+		return false;
+	}
+
+	private FP pow(BIG e)
+	{
+		byte[] w=new byte[1+(BIG.NLEN*BIG.BASEBITS+3)/4];
+		FP [] tb=new FP[16];
+		BIG t=new BIG(e);
+		t.norm();
+		int nb=1+(t.nbits()+3)/4;
+
+		for (int i=0;i<nb;i++)
+		{
+			int lsbs=t.lastbits(4);
+			t.dec(lsbs);
+			t.norm();
+			w[i]=(byte)lsbs;
+			t.fshr(4);
+		}
+		tb[0]=new FP(1);
+		tb[1]=new FP(this);
+		for (int i=2;i<16;i++)
+		{
+			tb[i]=new FP(tb[i-1]);
+			tb[i].mul(this);
+		}
+		FP r=new FP(tb[w[nb-1]]);
+		for (int i=nb-2;i>=0;i--)
+		{
+			r.sqr();
+			r.sqr();
+			r.sqr();
+			r.sqr();
+			r.mul(tb[w[i]]);
+		}
+		r.reduce();
+		return r;
+	}
+
+/* return this^e mod Modulus 
+	public FP pow(BIG e)
+	{
+		int bt;
+		FP r=new FP(1);
+		e.norm();
+		x.norm();
+		FP m=new FP(this);
+		while (true)
+		{
+			bt=e.parity();
+			e.fshr(1);
+			if (bt==1) r.mul(m);
+			if (e.iszilch()) break;
+			m.sqr();
+		}
+		r.x.mod(p);
+		return r;
+	} */
+
+/* return sqrt(this) mod Modulus */
+	public FP sqrt()
+	{
+		reduce();
+		if (MOD8==5)
+		{
+			FP i=new FP(this); i.x.shl(1);
+			FP v;
+			if (MODTYPE==PSEUDO_MERSENNE)
+			{
+				v=i.fpow();
+			} else {
+				BIG b=new BIG(ROM.Modulus);
+				b.dec(5); b.norm(); b.shr(3);
+				v=i.pow(b);
+			}
+			i.mul(v); i.mul(v);
+			i.x.dec(1);
+			FP r=new FP(this);
+			r.mul(v); r.mul(i); 
+			r.reduce();
+			return r;
+		}
+		else
+		{
+			if (MODTYPE==PSEUDO_MERSENNE)
+			{
+				FP r=fpow();
+				r.mul(this);
+				return r;
+			} else {
+				BIG b=new BIG(ROM.Modulus);
+				b.inc(1); b.norm(); b.shr(2);
+				return pow(b);
+			}
+		}
+	}
+
+/* return jacobi symbol (this/Modulus) */
+	public int jacobi()
+	{
+		BIG w=redc();
+		return w.jacobi(new BIG(ROM.Modulus));
+	}
+/*
+	public static void main(String[] args) {
+		BIG m=new BIG(ROM.Modulus);
+		BIG x=new BIG(3);
+		BIG e=new BIG(m);
+		e.dec(1);
+
+		System.out.println("m= "+m.nbits());	
+
+
+		BIG r=x.powmod(e,m);
+
+		System.out.println("m= "+m.toString());	
+		System.out.println("r= "+r.toString());	
+
+		BIG.cswap(m,r,0);
+
+		System.out.println("m= "+m.toString());	
+		System.out.println("r= "+r.toString());	
+
+//		FP y=new FP(3);
+//		FP s=y.pow(e);
+//		System.out.println("s= "+s.toString());	
+
+	} */
+}
diff --git a/version3/java/FP8.java b/version3/java/FP8.java
new file mode 100644
index 0000000..7bb5b1a
--- /dev/null
+++ b/version3/java/FP8.java
@@ -0,0 +1,658 @@
+/*
+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.
+*/
+
+/* Finite Field arithmetic  Fp^8 functions */
+
+/* FP8 elements are of the form a+ib, where i is sqrt(sqrt(-1+sqrt(-1)))  */
+
+package org.apache.milagro.amcl.XXX;
+
+public final class FP8 {
+	private final FP4 a;
+	private final FP4 b;
+/* reduce all components of this mod Modulus */
+	public void reduce()
+	{
+		a.reduce();
+		b.reduce();
+	}
+/* normalise all components of this mod Modulus */
+	public void norm()
+	{
+		a.norm();
+		b.norm();
+	}
+/* test this==0 ? */
+	public boolean iszilch() {
+		//reduce();
+		return (a.iszilch() && b.iszilch());
+	}
+
+	public void cmove(FP8 g,int d)
+	{
+		a.cmove(g.a,d);
+		b.cmove(g.b,d);
+	}
+
+/* test this==1 ? */
+	public boolean isunity() {
+		FP4 one=new FP4(1);
+		return (a.equals(one) && b.iszilch());
+	}
+
+/* test is w real? That is in a+ib test b is zero */
+	public boolean isreal()
+	{
+		return b.iszilch();
+	}
+/* extract real part a */
+	public FP4 real()
+	{
+		return a;
+	}
+
+	public FP4 geta()
+	{
+		return a;
+	}
+/* extract imaginary part b */
+	public FP4 getb()
+	{
+		return b;
+	}
+/* test this=x? */
+	public boolean equals(FP8 x)
+	{
+		return (a.equals(x.a) && b.equals(x.b));
+	}
+/* constructors */
+	public FP8(int c)
+	{
+		a=new FP4(c);
+		b=new FP4(0);
+	}
+
+	public FP8(FP8 x)
+	{
+		a=new FP4(x.a);
+		b=new FP4(x.b);
+	}
+
+	public FP8(FP4 c,FP4 d)
+	{
+		a=new FP4(c);
+		b=new FP4(d);
+	}
+
+	public FP8(FP4 c)
+	{
+		a=new FP4(c);
+		b=new FP4(0);
+	}
+/* copy this=x */
+	public void copy(FP8 x)
+	{
+		a.copy(x.a);
+		b.copy(x.b);
+	}
+/* set this=0 */
+	public void zero()
+	{
+		a.zero();
+		b.zero();
+	}
+/* set this=1 */
+	public void one()
+	{
+		a.one();
+		b.zero();
+	}
+/* set this=-this */
+	public void neg()
+	{
+		norm();
+		FP4 m=new FP4(a);
+		FP4 t=new FP4(0);
+		m.add(b);
+//	m.norm();
+		m.neg();
+	//	m.norm();
+		t.copy(m); t.add(b);
+		b.copy(m);
+		b.add(a);
+		a.copy(t);
+	norm();
+	}
+
+/* this=conjugate(this) */
+	public void conj()
+	{
+		b.neg(); norm();
+	}
+/* this=-conjugate(this) */
+	public void nconj()
+	{
+		a.neg(); norm();
+	}
+/* this+=x */
+	public void add(FP8 x)
+	{
+		a.add(x.a);
+		b.add(x.b);
+	}
+/* this-=x */
+	public void sub(FP8 x)
+	{
+		FP8 m=new FP8(x);
+		m.neg();
+		add(m);
+	}
+
+/* this=x-this */
+	public void rsub(FP8 x)
+	{
+		neg();
+		add(x);
+	}
+
+
+/* this*=s where s is FP4 */
+	public void pmul(FP4 s)
+	{
+		a.mul(s);
+		b.mul(s);
+	}
+/* this*=s where s is FP2 */
+	public void qmul(FP2 s)
+	{
+		a.pmul(s);
+		b.pmul(s);
+	}
+/* this*=s where s is FP */
+	public void tmul(FP s)
+	{
+		a.qmul(s);
+		b.qmul(s);
+	}
+/* this*=c where c is int */
+	public void imul(int c)
+	{
+		a.imul(c);
+		b.imul(c);
+	}
+
+/* this*=this */	
+	public void sqr()
+	{
+//		norm();
+
+		FP4 t1=new FP4(a);
+		FP4 t2=new FP4(b);
+		FP4 t3=new FP4(a);
+
+		t3.mul(b);
+		t1.add(b);
+		t2.times_i();
+
+		t2.add(a);
+
+		t1.norm();
+		t2.norm();
+
+		a.copy(t1);
+
+		a.mul(t2);
+
+		t2.copy(t3);
+		t2.times_i();
+		t2.add(t3);
+		t2.norm();
+		t2.neg();
+		a.add(t2);
+
+		b.copy(t3);
+		b.add(t3);
+
+		norm();
+	}
+
+/* this*=y */
+	public void mul(FP8 y)
+	{
+//		norm();
+
+		FP4 t1=new FP4(a);
+		FP4 t2=new FP4(b);
+		FP4 t3=new FP4(0);
+		FP4 t4=new FP4(b);
+
+		t1.mul(y.a);
+		t2.mul(y.b);
+		t3.copy(y.b);
+		t3.add(y.a);
+		t4.add(a);
+
+		t3.norm();
+		t4.norm();
+
+		t4.mul(t3);
+
+		t3.copy(t1);
+		t3.neg();
+		t4.add(t3);
+		t4.norm();
+
+	//	t4.sub(t1);
+	//	t4.norm();
+
+		t3.copy(t2);
+		t3.neg();
+		b.copy(t4);
+		b.add(t3);
+
+	//	b.copy(t4);
+	//	b.sub(t2);
+
+		t2.times_i();
+		a.copy(t2);
+		a.add(t1);
+
+		norm();
+	}
+
+/* convert this to hex string */
+	public String toString() 
+	{
+		return ("["+a.toString()+","+b.toString()+"]");
+	}
+
+/* this=1/this */
+	public void inverse()
+	{
+//		norm();
+
+		FP4 t1=new FP4(a);
+		FP4 t2=new FP4(b);
+
+		t1.sqr();
+		t2.sqr();
+		t2.times_i();
+		t2.norm();
+		t1.sub(t2); t1.norm();
+		t1.inverse();
+		a.mul(t1);
+		t1.neg();
+		t1.norm();
+		b.mul(t1);
+	}
+
+/* this*=i where i = sqrt(-1+sqrt(-1)) */
+	public void times_i()
+	{
+//		norm();
+		FP4 s=new FP4(b);
+		FP4 t=new FP4(a);
+		s.times_i();
+
+		b.copy(t);
+		a.copy(s);
+		norm();
+	}
+
+	public void times_i2()
+	{
+		a.times_i();
+		b.times_i();
+	}
+
+/* this=this^p using Frobenius */
+	public void frob(FP2 f)
+	{
+		FP2 ff=new FP2(f); ff.sqr(); ff.mul_ip(); ff.norm();
+
+		a.frob(ff);
+		b.frob(ff);
+		b.pmul(f);
+		b.times_i();
+
+	}
+
+/* this=this^e */
+	public FP8 pow(BIG e)
+	{
+		FP8 w=new FP8(this);
+		w.norm();
+		BIG z=new BIG(e);
+		FP8 r=new FP8(1);
+		z.norm();
+		while (true)
+		{
+			int bt=z.parity();
+			z.fshr(1);
+			if (bt==1) r.mul(w);
+			if (z.iszilch()) break;
+			w.sqr();
+		}
+		r.reduce();
+		return r;
+	}
+
+/* XTR xtr_a function */
+	public void xtr_A(FP8 w,FP8 y,FP8 z) 
+	{
+		FP8 r=new FP8(w);
+		FP8 t=new FP8(w);
+	
+		r.sub(y);
+		r.norm();
+		r.pmul(a);
+		t.add(y);
+		t.norm();
+		t.pmul(b);
+		t.times_i();
+
+		copy(r);
+		add(t);
+		add(z);
+
+		norm();
+	}
+
+/* XTR xtr_d function */
+	public void xtr_D() {
+		FP8 w=new FP8(this);
+		sqr(); w.conj();
+		w.add(w);
+		w.norm();
+		sub(w);
+		reduce();
+	}
+
+/* r=x^n using XTR method on traces of FP12s */
+	public FP8 xtr_pow(BIG n) {
+		FP8 sf=new FP8(this);
+		sf.norm();
+		FP8 a=new FP8(3);
+		FP8 b=new FP8(sf);
+		FP8 c=new FP8(b);
+		c.xtr_D();
+		FP8 t=new FP8(0);
+		FP8 r=new FP8(0);
+		
+		int par=n.parity();
+		BIG v=new BIG(n); v.norm(); v.fshr(1);
+		if (par==0) {v.dec(1); v.norm();}
+
+		int nb=v.nbits();
+		for (int i=nb-1;i>=0;i--)
+		{
+			if (v.bit(i)!=1)
+			{
+				t.copy(b);
+				sf.conj();
+				c.conj();
+				b.xtr_A(a,sf,c);
+				sf.conj();
+				c.copy(t);
+				c.xtr_D();
+				a.xtr_D();
+			}
+			else
+			{
+				t.copy(a); t.conj();
+				a.copy(b);
+				a.xtr_D();
+				b.xtr_A(c,sf,t);
+				c.xtr_D();
+			}
+		}
+		if (par==0) r.copy(c);
+		else r.copy(b);
+		r.reduce();
+		return r;
+	}
+
+/* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */
+	public FP8 xtr_pow2(FP8 ck,FP8 ckml,FP8 ckm2l,BIG a,BIG b)
+	{
+
+		BIG e=new BIG(a);
+		BIG d=new BIG(b);
+		BIG w=new BIG(0);
+		e.norm(); d.norm();
+
+		FP8 cu=new FP8(ck);  // can probably be passed in w/o copying
+		FP8 cv=new FP8(this);
+		FP8 cumv=new FP8(ckml);
+		FP8 cum2v=new FP8(ckm2l);
+		FP8 r=new FP8(0);
+		FP8 t=new FP8(0);
+
+		int f2=0;
+		while (d.parity()==0 && e.parity()==0)
+		{
+			d.fshr(1);
+			e.fshr(1);
+			f2++;
+		}
+
+		while (BIG.comp(d,e)!=0)
+		{
+			if (BIG.comp(d,e)>0)
+			{
+				w.copy(e); w.imul(4); w.norm();
+				if (BIG.comp(d,w)<=0)
+				{
+					w.copy(d); d.copy(e);
+					e.rsub(w); e.norm();
+
+					t.copy(cv); 
+					t.xtr_A(cu,cumv,cum2v);
+					cum2v.copy(cumv); 
+					cum2v.conj();
+					cumv.copy(cv);
+					cv.copy(cu);
+					cu.copy(t);
+
+				}
+				else if (d.parity()==0)
+				{
+					d.fshr(1);
+					r.copy(cum2v); r.conj();
+					t.copy(cumv);
+					t.xtr_A(cu,cv,r);
+					cum2v.copy(cumv);
+					cum2v.xtr_D();
+					cumv.copy(t);
+					cu.xtr_D();
+				}
+				else if (e.parity()==1)
+				{
+					d.sub(e); d.norm();
+					d.fshr(1);
+					t.copy(cv);
+					t.xtr_A(cu,cumv,cum2v);
+					cu.xtr_D();
+					cum2v.copy(cv);
+					cum2v.xtr_D();
+					cum2v.conj();
+					cv.copy(t);
+				}
+				else
+				{
+					w.copy(d);
+					d.copy(e); d.fshr(1);
+					e.copy(w);
+					t.copy(cumv);
+					t.xtr_D();
+					cumv.copy(cum2v); cumv.conj();
+					cum2v.copy(t); cum2v.conj();
+					t.copy(cv);
+					t.xtr_D();
+					cv.copy(cu);
+					cu.copy(t);
+				}
+			}
+			if (BIG.comp(d,e)<0)
+			{
+				w.copy(d); w.imul(4); w.norm();
+				if (BIG.comp(e,w)<=0)
+				{
+					e.sub(d); e.norm();
+					t.copy(cv);
+					t.xtr_A(cu,cumv,cum2v);
+					cum2v.copy(cumv);
+					cumv.copy(cu);
+					cu.copy(t);
+				}
+				else if (e.parity()==0)
+				{
+					w.copy(d);
+					d.copy(e); d.fshr(1);
+					e.copy(w);
+					t.copy(cumv);
+					t.xtr_D();
+					cumv.copy(cum2v); cumv.conj();
+					cum2v.copy(t); cum2v.conj();
+					t.copy(cv);
+					t.xtr_D();
+					cv.copy(cu);
+					cu.copy(t);
+				}
+				else if (d.parity()==1)
+				{
+					w.copy(e);
+					e.copy(d);
+					w.sub(d); w.norm();
+					d.copy(w); d.fshr(1);
+					t.copy(cv);
+					t.xtr_A(cu,cumv,cum2v);
+					cumv.conj();
+					cum2v.copy(cu);
+					cum2v.xtr_D();
+					cum2v.conj();
+					cu.copy(cv);
+					cu.xtr_D();
+					cv.copy(t);
+				}
+				else
+				{
+					d.fshr(1);
+					r.copy(cum2v); r.conj();
+					t.copy(cumv);
+					t.xtr_A(cu,cv,r);
+					cum2v.copy(cumv);
+					cum2v.xtr_D();
+					cumv.copy(t);
+					cu.xtr_D();
+				}
+			}
+		}
+		r.copy(cv);
+		r.xtr_A(cu,cumv,cum2v);
+		for (int i=0;i<f2;i++)
+			r.xtr_D();
+		r=r.xtr_pow(d);
+		return r;
+	}
+
+/* this/=2 */
+	public void div2()
+	{
+		a.div2();
+		b.div2();
+	}
+
+	public void div_i()
+	{
+		FP4 u=new FP4(a);
+		FP4 v=new FP4(b);
+		u.div_i();
+		a.copy(v);
+		b.copy(u);
+	}
+
+	public void div_i2() {
+		a.div_i();
+		b.div_i();
+	}
+
+	public void div_2i() {
+		FP4 u=new FP4(a);
+		FP4 v=new FP4(b);
+		u.div_2i();
+		v.add(v); v.norm();
+		a.copy(v);
+		b.copy(u);
+	}
+
+/* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */
+/* returns true if this is QR */
+	public boolean sqrt()
+	{
+		if (iszilch()) return true;
+		FP4 wa=new FP4(a);
+		FP4 ws=new FP4(b);
+		FP4 wt=new FP4(a);
+		
+		if (ws.iszilch())
+		{
+			if (wt.sqrt())
+			{
+				a.copy(wt);
+				b.zero();
+			} else {
+				wt.div_i();
+				wt.sqrt();
+				b.copy(wt);
+				a.zero();
+			}
+			return true;
+		}
+
+		ws.sqr();
+		wa.sqr();
+		ws.times_i();
+		ws.norm();
+		wa.sub(ws);
+
+		ws.copy(wa);
+		if (!ws.sqrt()) {
+			return false;
+		}
+
+		wa.copy(wt); wa.add(ws); wa.norm(); wa.div2();
+
+		if (!wa.sqrt()) {
+			wa.copy(wt); wa.sub(ws); wa.norm(); wa.div2();
+			if (!wa.sqrt()) {
+				return false;
+			}
+		}
+		wt.copy(b);
+		ws.copy(wa); ws.add(wa);
+		ws.inverse();
+
+		wt.mul(ws);
+		a.copy(wa);
+		b.copy(wt);
+
+		return true;
+	}
+}
diff --git a/version3/java/GCM.java b/version3/java/GCM.java
new file mode 100644
index 0000000..3cafa82
--- /dev/null
+++ b/version3/java/GCM.java
@@ -0,0 +1,376 @@
+/*
+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.
+*/
+
+
+/*
+ * Implementation of the AES-GCM Encryption/Authentication
+ *
+ * Some restrictions.. 
+ * 1. Only for use with AES
+ * 2. Returned tag is always 128-bits. Truncate at your own risk.
+ * 3. The order of function calls must follow some rules
+ *
+ * Typical sequence of calls..
+ * 1. call GCM_init
+ * 2. call GCM_add_header any number of times, as long as length of header is multiple of 16 bytes (block size)
+ * 3. call GCM_add_header one last time with any length of header
+ * 4. call GCM_add_cipher any number of times, as long as length of cipher/plaintext is multiple of 16 bytes
+ * 5. call GCM_add_cipher one last time with any length of cipher/plaintext
+ * 6. call GCM_finish to extract the tag.
+ *
+ * See http://www.mindspring.com/~dmcgrew/gcm-nist-6.pdf
+ */
+
+package org.apache.milagro.amcl;
+
+public class GCM {
+	public static final int NB=4;
+	public static final int GCM_ACCEPTING_HEADER=0;
+	public static final int GCM_ACCEPTING_CIPHER=1;
+	public static final int GCM_NOT_ACCEPTING_MORE=2;
+	public static final int GCM_FINISHED=3;
+	public static final int GCM_ENCRYPTING=0;
+	public static final int GCM_DECRYPTING=1;
+
+	private int[][] table=new int[128][4]; /* 2k bytes */
+	private byte[] stateX=new byte[16];
+	private byte[]Y_0=new byte[16];
+	private int counter;
+	private int[] lenA=new int[2];
+	private int[] lenC=new int[2];
+	private int status;
+	private AES a=new AES();
+
+	private static int pack(byte[] b)
+	{ /* pack bytes into a 32-bit Word */
+		return ((((int)b[0])&0xff)<<24)|(((int)b[1]&0xff)<<16)|(((int)b[2]&0xff)<<8)|((int)b[3]&0xff);
+	}
+
+	private static byte[] unpack(int a)
+	{ /* unpack bytes from a word */
+		byte [] b=new byte[4];
+		b[3]=(byte)(a);
+		b[2]=(byte)(a>>>8);
+		b[1]=(byte)(a>>>16);
+		b[0]=(byte)(a>>>24);
+		return b;
+	}
+
+	private void precompute(byte[] H)
+	{
+		int i,j,c;
+		byte[] b=new byte[4];
+
+		for (i=j=0;i<NB;i++,j+=4) 
+		{
+			b[0]=H[j]; b[1]=H[j+1]; b[2]=H[j+2]; b[3]=H[j+3];
+			table[0][i]=pack(b);
+		}
+		for (i=1;i<128;i++)
+		{
+			c=0;
+			for (j=0;j<NB;j++) {table[i][j]=c|(table[i-1][j])>>>1; c=table[i-1][j]<<31;}
+			if (c!=0) table[i][0]^=0xE1000000; /* irreducible polynomial */
+		}
+	}
+
+	private void gf2mul()
+	{ /* gf2m mul - Z=H*X mod 2^128 */
+		int i,j,m,k;
+		int[] P=new int[4];
+		int c;
+		byte[] b;//=new byte[4];
+
+		P[0]=P[1]=P[2]=P[3]=0;
+		j=8; m=0;
+		for (i=0;i<128;i++)
+		{
+			c=(stateX[m]>>>(--j))&1; c=~c+1;
+			for (k=0;k<NB;k++) P[k]^=(table[i][k]&c);
+			if (j==0)
+			{
+				j=8; m++;
+				if (m==16) break;
+			}
+		}
+		for (i=j=0;i<NB;i++,j+=4) 
+		{
+			b=unpack(P[i]);
+			stateX[j]=b[0]; stateX[j+1]=b[1]; stateX[j+2]=b[2]; stateX[j+3]=b[3];
+		}
+	}
+
+	private void wrap()
+	{ /* Finish off GHASH */
+		int i,j;
+		int[] F=new int[4];
+		byte[] L=new byte[16];
+		byte[] b;//=new byte[4];
+
+/* convert lengths from bytes to bits */
+		F[0]=(lenA[0]<<3)|(lenA[1]&0xE0000000)>>>29;
+		F[1]=lenA[1]<<3;
+		F[2]=(lenC[0]<<3)|(lenC[1]&0xE0000000)>>>29;
+		F[3]=lenC[1]<<3;
+		for (i=j=0;i<NB;i++,j+=4)
+		{
+			b=unpack(F[i]);
+			L[j]=b[0]; L[j+1]=b[1]; L[j+2]=b[2]; L[j+3]=b[3];
+		}
+		for (i=0;i<16;i++) stateX[i]^=L[i];
+		gf2mul();
+	}
+
+/* Initialize GCM mode */
+	public void init(int nk,byte[] key,int niv,byte[] iv)
+	{ /* iv size niv is usually 12 bytes (96 bits). AES key size nk can be 16,24 or 32 bytes */
+		int i;
+		byte[] H=new byte[16];
+		byte[] b;//=new byte[4];
+
+		for (i=0;i<16;i++) {H[i]=0; stateX[i]=0;}
+
+		a.init(AES.ECB,nk,key,iv);
+		a.ecb_encrypt(H);     /* E(K,0) */
+		precompute(H);
+	
+		lenA[0]=lenC[0]=lenA[1]=lenC[1]=0;
+		if (niv==12)
+		{
+			for (i=0;i<12;i++) a.f[i]=iv[i];
+			b=unpack((int)1);
+			a.f[12]=b[0]; a.f[13]=b[1]; a.f[14]=b[2]; a.f[15]=b[3];  /* initialise IV */
+			for (i=0;i<16;i++) Y_0[i]=a.f[i];
+		}
+		else
+		{
+			status=GCM_ACCEPTING_CIPHER;
+			ghash(iv,niv); /* GHASH(H,0,IV) */
+			wrap();
+			for (i=0;i<16;i++) {a.f[i]=stateX[i];Y_0[i]=a.f[i];stateX[i]=0;}
+			lenA[0]=lenC[0]=lenA[1]=lenC[1]=0;
+		}
+		status=GCM_ACCEPTING_HEADER;
+	}
+
+/* Add Header data - included but not encrypted */
+	public boolean add_header(byte[] header,int len)
+	{ /* Add some header. Won't be encrypted, but will be authenticated. len is length of header */
+		int i,j=0;
+		if (status!=GCM_ACCEPTING_HEADER) return false;
+
+		while (j<len)
+		{
+			for (i=0;i<16 && j<len;i++)
+			{
+				stateX[i]^=header[j++];
+				lenA[1]++; if (lenA[1]==0) lenA[0]++;
+			}
+			gf2mul();
+		}
+		if (len%16!=0) status=GCM_ACCEPTING_CIPHER;
+		return true;
+	}
+
+	private boolean ghash(byte[] plain,int len)
+	{
+		int i,j=0;
+		int counter;
+	//	byte[] B=new byte[16];
+	//	byte[] b=new byte[4];
+
+		if (status==GCM_ACCEPTING_HEADER) status=GCM_ACCEPTING_CIPHER;
+		if (status!=GCM_ACCEPTING_CIPHER) return false;
+		
+		while (j<len)
+		{
+			for (i=0;i<16 && j<len;i++)
+			{
+				stateX[i]^=plain[j++];
+				lenC[1]++; if (lenC[1]==0) lenC[0]++;
+			}
+			gf2mul();
+		}
+		if (len%16!=0) status=GCM_NOT_ACCEPTING_MORE;
+		return true;
+	}
+
+/* Add Plaintext - included and encrypted */
+	public byte[] add_plain(byte[] plain,int len)
+	{
+		int i,j=0;
+		int counter;
+		byte[] B=new byte[16];
+		byte[] b=new byte[4];
+		byte[] cipher=new byte[len];
+
+		if (status==GCM_ACCEPTING_HEADER) status=GCM_ACCEPTING_CIPHER;
+		if (status!=GCM_ACCEPTING_CIPHER) return new byte[0];
+		
+		while (j<len)
+		{
+
+			b[0]=a.f[12]; b[1]=a.f[13]; b[2]=a.f[14]; b[3]=a.f[15];
+			counter=pack(b);
+			counter++;
+			b=unpack(counter);
+			a.f[12]=b[0]; a.f[13]=b[1]; a.f[14]=b[2]; a.f[15]=b[3]; /* increment counter */
+			for (i=0;i<16;i++) B[i]=a.f[i];
+			a.ecb_encrypt(B);        /* encrypt it  */
+		
+			for (i=0;i<16 && j<len;i++)
+			{
+				cipher[j]=(byte)(plain[j]^B[i]);
+				stateX[i]^=cipher[j++];
+				lenC[1]++; if (lenC[1]==0) lenC[0]++;
+			}
+			gf2mul();
+		}
+		if (len%16!=0) status=GCM_NOT_ACCEPTING_MORE;
+		return cipher;
+	}
+
+/* Add Ciphertext - decrypts to plaintext */
+	public byte[] add_cipher(byte[] cipher,int len)
+	{
+		int i,j=0;
+		int counter;
+		byte[] B=new byte[16];
+		byte[] b=new byte[4];
+		byte[] plain=new byte[len];
+
+		if (status==GCM_ACCEPTING_HEADER) status=GCM_ACCEPTING_CIPHER;
+		if (status!=GCM_ACCEPTING_CIPHER) return new byte[0];
+	
+		while (j<len)
+		{
+
+			b[0]=a.f[12]; b[1]=a.f[13]; b[2]=a.f[14]; b[3]=a.f[15];
+			counter=pack(b);
+			counter++;
+			b=unpack(counter);
+			a.f[12]=b[0]; a.f[13]=b[1]; a.f[14]=b[2]; a.f[15]=b[3]; /* increment counter */
+			for (i=0;i<16;i++) B[i]=a.f[i];
+			a.ecb_encrypt(B);        /* encrypt it  */
+			for (i=0;i<16 && j<len;i++)
+			{
+				byte oc=cipher[j];
+				plain[j]=(byte)(cipher[j]^B[i]);
+				stateX[i]^=oc; j++;
+				lenC[1]++; if (lenC[1]==0) lenC[0]++;
+			}
+			gf2mul();
+		}
+		if (len%16!=0) status=GCM_NOT_ACCEPTING_MORE;
+		return plain;
+	}
+
+/* Finish and extract Tag */
+	public byte[] finish(boolean extract)
+	{ /* Finish off GHASH and extract tag (MAC) */
+		int i;
+		byte[] tag=new byte[16];
+
+		wrap();
+/* extract tag */
+		if (extract)
+		{
+			a.ecb_encrypt(Y_0);        /* E(K,Y0) */
+			for (i=0;i<16;i++) Y_0[i]^=stateX[i];
+			for (i=0;i<16;i++) {tag[i]=Y_0[i];Y_0[i]=stateX[i]=0;}
+		}
+		status=GCM_FINISHED;
+		a.end();
+		return tag;
+	}
+
+	public static byte[] hex2bytes(String s) {
+		int len = s.length();
+		byte[] data = new byte[len / 2];
+		for (int i = 0; i < len; i += 2) {
+			data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+                             + Character.digit(s.charAt(i+1), 16));
+		}
+		return data;
+	}
+/*
+	public static void main(String[] args) {
+		int i;
+
+		String KT="feffe9928665731c6d6a8f9467308308";
+		String MT="d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39";
+		String HT="feedfacedeadbeeffeedfacedeadbeefabaddad2";
+//	char* NT="cafebabefacedbaddecaf888";
+// Tag should be 5bc94fbc3221a5db94fae95ae7121a47
+		String NT="9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b";
+// Tag should be 619cc5aefffe0bfa462af43c1699d050
+
+
+		byte[] T=new byte[16];   // Tag
+		byte[] K=new byte[16];   // AES Key
+		byte[] H=new byte[64];   // Header - to be included in Authentication, but not encrypted
+		byte[] N=new byte[100];   // IV - Initialisation vector
+		byte[] M=new byte[100];  // Plaintext to be encrypted/authenticated
+		byte[] C=new byte[100];  // Ciphertext
+		byte[] P=new byte[100];  // Recovered Plaintext 
+
+		GCM g=new GCM();
+
+		M=hex2bytes(MT);
+		H=hex2bytes(HT);
+		N=hex2bytes(NT);
+		K=hex2bytes(KT);
+
+		int len=M.length;
+		int lenH=H.length;
+		int lenK=K.length;
+		int lenIV=N.length;
+
+ 		System.out.format("Plaintext=\n");
+		for (i=0;i<len;i++) System.out.format("%02x",M[i]);
+		System.out.format("\n");
+
+		g.init(16,K,lenIV,N);
+		g.add_header(H,lenH);
+		C=g.add_plain(M,len);
+		T=g.finish(true);
+
+		System.out.format("Ciphertext=\n");
+		for (i=0;i<len;i++) System.out.format("%02x",C[i]);
+		System.out.format("\n");
+        
+		System.out.format("Tag=\n");
+		for (i=0;i<16;i++) System.out.format("%02x",T[i]);
+		System.out.format("\n");
+
+		g.init(16,K,lenIV,N);
+		g.add_header(H,lenH);
+		P=g.add_cipher(C,len);
+		T=g.finish(true);
+
+ 		System.out.format("Plaintext=\n");
+		for (i=0;i<len;i++) System.out.format("%02x",P[i]);
+		System.out.format("\n");
+
+		System.out.format("Tag=\n");
+		for (i=0;i<16;i++) System.out.format("%02x",T[i]);
+		System.out.format("\n");
+	}
+*/	
+}
diff --git a/version3/java/HASH256.java b/version3/java/HASH256.java
new file mode 100644
index 0000000..915642e
--- /dev/null
+++ b/version3/java/HASH256.java
@@ -0,0 +1,218 @@
+/*
+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.
+*/
+
+/*
+ * Implementation of the Secure Hashing Algorithm (SHA-256)
+ *
+ * Generates a 256 bit message digest. It should be impossible to come
+ * come up with two messages that hash to the same value ("collision free").
+ *
+ * For use with byte-oriented messages only. 
+ */
+
+package org.apache.milagro.amcl;
+
+public class HASH256 {
+	private int[] length=new int[2];
+	private int[] h=new int[8];
+	private int[] w=new int[80];
+
+	public static final int H0=0x6A09E667;
+	public static final int H1=0xBB67AE85;
+	public static final int H2=0x3C6EF372;
+	public static final int H3=0xA54FF53A;
+	public static final int H4=0x510E527F;
+	public static final int H5=0x9B05688C;
+	public static final int H6=0x1F83D9AB;
+	public static final int H7=0x5BE0CD19;
+
+	public static final int len=32;
+
+	public static final int[] K={
+	0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,
+	0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,
+	0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,
+	0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,
+	0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
+	0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070,
+	0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,
+	0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2};
+
+
+/* functions */
+	private static int S(int n,int x)
+	{
+		return (((x)>>>n) | ((x)<<(32-n)));
+	}
+
+	private static int R(int n,int x)
+	{
+		return ((x)>>>n);
+	}
+
+	private static int Ch(int x,int y,int z)
+	{
+		return ((x&y)^(~(x)&z));
+	}
+
+	private static int Maj(int x,int y,int z)
+	{
+		return ((x&y)^(x&z)^(y&z));
+	}
+
+	private static int Sig0(int x)
+	{
+		return (S(2,x)^S(13,x)^S(22,x));
+	}
+
+	private static int Sig1(int x)
+	{
+		return (S(6,x)^S(11,x)^S(25,x));
+	}
+
+	private static int theta0(int x)
+	{
+		return (S(7,x)^S(18,x)^R(3,x));
+	}
+
+	private static int theta1(int x)
+	{
+		return (S(17,x)^S(19,x)^R(10,x));
+	}
+
+
+	private void transform()
+	{ /* basic transformation step */
+		int a,b,c,d,e,f,g,hh,t1,t2;
+		int j;
+		for (j=16;j<64;j++) 
+			w[j]=theta1(w[j-2])+w[j-7]+theta0(w[j-15])+w[j-16];
+		a=h[0]; b=h[1]; c=h[2]; d=h[3]; 
+		e=h[4]; f=h[5]; g=h[6]; hh=h[7];
+
+		for (j=0;j<64;j++)
+		{ /* 64 times - mush it up */
+			t1=hh+Sig1(e)+Ch(e,f,g)+K[j]+w[j];
+			t2=Sig0(a)+Maj(a,b,c);
+			hh=g; g=f; f=e;
+			e=d+t1;
+			d=c;
+			c=b;
+			b=a;
+			a=t1+t2;   
+		
+		}
+		h[0]+=a; h[1]+=b; h[2]+=c; h[3]+=d; 
+		h[4]+=e; h[5]+=f; h[6]+=g; h[7]+=hh; 
+	} 
+
+/* Initialise Hash function */
+	public void init()
+	{ /* initialise */
+		int i;
+		for (i=0;i<64;i++) w[i]=0;
+		length[0]=length[1]=0;
+		h[0]=H0;
+		h[1]=H1;
+		h[2]=H2;
+		h[3]=H3;
+		h[4]=H4;
+		h[5]=H5;
+		h[6]=H6;
+		h[7]=H7;
+	}
+
+/* Constructor */
+	public HASH256()
+	{
+		init();
+	}
+
+/* process a single byte */
+	public void process(int byt)
+	{ /* process the next message byte */
+		int cnt;
+		cnt=(length[0]/32)%16;
+    
+		w[cnt]<<=8;
+		w[cnt]|=(byt&0xFF);
+		length[0]+=8;
+		if (length[0]==0) { length[1]++; length[0]=0; }
+		if ((length[0]%512)==0) transform();
+	}
+
+/* process an array of bytes */	
+	public void process_array(byte[] b)
+	{
+		for (int i=0;i<b.length;i++) process((int)b[i]);
+	}
+
+/* process a 32-bit integer */
+	public void process_num(int n)
+	{
+		process((n>>24)&0xff);
+		process((n>>16)&0xff);
+		process((n>>8)&0xff);
+		process(n&0xff);
+	}
+
+/* Generate 32-byte Hash */
+	public byte[] hash()
+	{ /* pad message and finish - supply digest */
+		int i;
+		byte[] digest=new byte[32];
+		int len0,len1;
+		len0=length[0];
+		len1=length[1];
+		process(0x80);
+		while ((length[0]%512)!=448) process(0);
+		w[14]=len1;
+		w[15]=len0;    
+		transform();
+		for (i=0;i<len;i++)
+		{ /* convert to bytes */
+			digest[i]=(byte)((h[i/4]>>(8*(3-i%4))) & 0xff);
+		}
+		init();
+		return digest;
+	}
+
+/* test program: should produce digest */
+
+//248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1
+
+	public static void main(String[] args) {
+		byte[] test="abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq".getBytes();
+		byte[] digest;
+		int i;
+		HASH256 sh=new HASH256();
+  
+		for (i=0;i<test.length;i++)
+			sh.process(test[i]);
+		
+		digest=sh.hash();    
+		for (i=0;i<32;i++) System.out.format("%02x",digest[i]);
+
+	//	for (i=0;i<32;i++) System.out.format("%d ",digest[i]);
+
+		System.out.println("");
+	} 
+}
+
+
diff --git a/version3/java/HASH384.java b/version3/java/HASH384.java
new file mode 100644
index 0000000..6fc50fc
--- /dev/null
+++ b/version3/java/HASH384.java
@@ -0,0 +1,229 @@
+/*
+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.
+*/
+
+/*
+ * Implementation of the Secure Hashing Algorithm (SHA-512)
+ *
+ * Generates a 512 bit message digest. It should be impossible to come
+ * come up with two messages that hash to the same value ("collision free").
+ *
+ * For use with byte-oriented messages only. 
+ */
+
+package org.apache.milagro.amcl;
+
+public class HASH384 {
+	private long[] length=new long[2];
+	private long[] h=new long[8];
+	private long[] w=new long[80];
+
+	public static final long H0=0xcbbb9d5dc1059ed8L;
+	public static final long H1=0x629a292a367cd507L;
+	public static final long H2=0x9159015a3070dd17L;
+	public static final long H3=0x152fecd8f70e5939L;
+	public static final long H4=0x67332667ffc00b31L;
+	public static final long H5=0x8eb44a8768581511L;
+	public static final long H6=0xdb0c2e0d64f98fa7L;
+	public static final long H7=0x47b5481dbefa4fa4L;
+
+	public static final int len=48;
+
+	public static final long[] K=
+	{0x428a2f98d728ae22L,0x7137449123ef65cdL,0xb5c0fbcfec4d3b2fL,0xe9b5dba58189dbbcL,
+	0x3956c25bf348b538L,0x59f111f1b605d019L,0x923f82a4af194f9bL,0xab1c5ed5da6d8118L,
+	0xd807aa98a3030242L,0x12835b0145706fbeL,0x243185be4ee4b28cL,0x550c7dc3d5ffb4e2L,
+	0x72be5d74f27b896fL,0x80deb1fe3b1696b1L,0x9bdc06a725c71235L,0xc19bf174cf692694L,
+	0xe49b69c19ef14ad2L,0xefbe4786384f25e3L,0x0fc19dc68b8cd5b5L,0x240ca1cc77ac9c65L,
+	0x2de92c6f592b0275L,0x4a7484aa6ea6e483L,0x5cb0a9dcbd41fbd4L,0x76f988da831153b5L,
+	0x983e5152ee66dfabL,0xa831c66d2db43210L,0xb00327c898fb213fL,0xbf597fc7beef0ee4L,
+	0xc6e00bf33da88fc2L,0xd5a79147930aa725L,0x06ca6351e003826fL,0x142929670a0e6e70L,
+	0x27b70a8546d22ffcL,0x2e1b21385c26c926L,0x4d2c6dfc5ac42aedL,0x53380d139d95b3dfL,
+	0x650a73548baf63deL,0x766a0abb3c77b2a8L,0x81c2c92e47edaee6L,0x92722c851482353bL,
+	0xa2bfe8a14cf10364L,0xa81a664bbc423001L,0xc24b8b70d0f89791L,0xc76c51a30654be30L,
+	0xd192e819d6ef5218L,0xd69906245565a910L,0xf40e35855771202aL,0x106aa07032bbd1b8L,
+	0x19a4c116b8d2d0c8L,0x1e376c085141ab53L,0x2748774cdf8eeb99L,0x34b0bcb5e19b48a8L,
+	0x391c0cb3c5c95a63L,0x4ed8aa4ae3418acbL,0x5b9cca4f7763e373L,0x682e6ff3d6b2b8a3L,
+	0x748f82ee5defb2fcL,0x78a5636f43172f60L,0x84c87814a1f0ab72L,0x8cc702081a6439ecL,
+	0x90befffa23631e28L,0xa4506cebde82bde9L,0xbef9a3f7b2c67915L,0xc67178f2e372532bL,
+	0xca273eceea26619cL,0xd186b8c721c0c207L,0xeada7dd6cde0eb1eL,0xf57d4f7fee6ed178L,
+	0x06f067aa72176fbaL,0x0a637dc5a2c898a6L,0x113f9804bef90daeL,0x1b710b35131c471bL,
+	0x28db77f523047d84L,0x32caab7b40c72493L,0x3c9ebe0a15c9bebcL,0x431d67c49c100d4cL,
+	0x4cc5d4becb3e42b6L,0x597f299cfc657e2aL,0x5fcb6fab3ad6faecL,0x6c44198c4a475817L};
+
+/* functions */
+	private static long S(int n,long x)
+	{
+		return (((x)>>>n) | ((x)<<(64-n)));
+	}
+
+	private static long R(int n,long x)
+	{
+		return ((x)>>>n);
+	}
+
+	private static long Ch(long x,long y,long z)
+	{
+		return ((x&y)^(~(x)&z));
+	}
+
+	private static long Maj(long x,long y,long z)
+	{
+		return ((x&y)^(x&z)^(y&z));
+	}
+
+	private static long Sig0(long x)
+	{
+		return (S(28,x)^S(34,x)^S(39,x));
+	}
+
+	private static long Sig1(long x)
+	{
+		return (S(14,x)^S(18,x)^S(41,x));
+	}
+
+	private static long theta0(long x)
+	{
+		return (S(1,x)^S(8,x)^R(7,x));
+	}
+
+	private static long theta1(long x)
+	{
+		return (S(19,x)^S(61,x)^R(6,x));
+	}
+
+	private void transform()
+	{ /* basic transformation step */
+		long a,b,c,d,e,f,g,hh,t1,t2;
+		int j;
+		for (j=16;j<80;j++) 
+			w[j]=theta1(w[j-2])+w[j-7]+theta0(w[j-15])+w[j-16];
+		a=h[0]; b=h[1]; c=h[2]; d=h[3]; 
+		e=h[4]; f=h[5]; g=h[6]; hh=h[7];
+
+		for (j=0;j<80;j++)
+		{ /* 80 times - mush it up */
+			t1=hh+Sig1(e)+Ch(e,f,g)+K[j]+w[j];
+			t2=Sig0(a)+Maj(a,b,c);
+			hh=g; g=f; f=e;
+			e=d+t1;
+			d=c;
+			c=b;
+			b=a;
+			a=t1+t2;   
+		
+		}
+		h[0]+=a; h[1]+=b; h[2]+=c; h[3]+=d; 
+		h[4]+=e; h[5]+=f; h[6]+=g; h[7]+=hh; 
+	} 
+
+/* Initialise Hash function */
+	public void init()
+	{ /* initialise */
+		int i;
+		for (i=0;i<80;i++) w[i]=0L;
+		length[0]=length[1]=0L;
+		h[0]=H0;
+		h[1]=H1;
+		h[2]=H2;
+		h[3]=H3;
+		h[4]=H4;
+		h[5]=H5;
+		h[6]=H6;
+		h[7]=H7;
+	}
+
+/* Constructor */
+	public HASH384()
+	{
+		init();
+	}
+
+/* process a single byte */
+	public void process(int byt)
+	{ /* process the next message byte */
+		int cnt;
+		cnt=(int)(length[0]/64)%16;
+    
+		w[cnt]<<=8;
+		w[cnt]|=(byt&0xFF);
+		length[0]+=8;
+		if (length[0]==0L) { length[1]++; length[0]=0L; }
+		if ((length[0]%1024)==0) transform();
+	}
+
+/* process an array of bytes */	
+	public void process_array(byte[] b)
+	{
+		for (int i=0;i<b.length;i++) process((int)b[i]);
+	}
+
+/* process a 32-bit integer */
+	public void process_num(int n)
+	{
+		process((n>>24)&0xff);
+		process((n>>16)&0xff);
+		process((n>>8)&0xff);
+		process(n&0xff);
+	}
+
+/* Generate 48-byte Hash */
+	public byte[] hash()
+	{ /* pad message and finish - supply digest */
+		int i;
+		byte[] digest=new byte[48];
+		long len0,len1;
+		len0=length[0];
+		len1=length[1];
+		process(0x80);
+		while ((length[0]%1024)!=896) process(0);
+		w[14]=len1;
+		w[15]=len0;    
+		transform();
+		for (i=0;i<len;i++)
+		{ /* convert to bytes */
+			digest[i]=(byte)((h[i/8]>>(8*(7-i%8))) & 0xffL);
+		}
+		init();
+		return digest;
+	}
+
+/* test program: should produce digest */
+
+//09330c33f71147e8 3d192fc782cd1b47 53111b173b3b05d2 2fa08086e3b0f712 fcc7c71a557e2db9 66c3e9fa91746039
+
+	public static void main(String[] args) {
+
+		byte[] test="abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu".getBytes();
+		byte[] digest;
+		int i;
+		HASH384 sh=new HASH384();
+  
+		for (i=0;i<test.length;i++)
+			sh.process(test[i]);
+		
+		digest=sh.hash();    
+		for (i=0;i<48;i++) System.out.format("%02x",digest[i]);
+
+	//	for (i=0;i<32;i++) System.out.format("%d ",digest[i]);
+
+		System.out.println("");
+
+	} 
+}
+
diff --git a/version3/java/HASH512.java b/version3/java/HASH512.java
new file mode 100644
index 0000000..686ab22
--- /dev/null
+++ b/version3/java/HASH512.java
@@ -0,0 +1,232 @@
+/*
+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.
+*/
+
+/*
+ * Implementation of the Secure Hashing Algorithm (SHA-512)
+ *
+ * Generates a 512 bit message digest. It should be impossible to come
+ * come up with two messages that hash to the same value ("collision free").
+ *
+ * For use with byte-oriented messages only. 
+ */
+
+
+package org.apache.milagro.amcl;
+
+public class HASH512 {
+
+	private long[] length=new long[2];
+	private long[] h=new long[8];
+	private long[] w=new long[80];
+
+	public static final long H0=0x6a09e667f3bcc908L;
+	public static final long H1=0xbb67ae8584caa73bL;
+	public static final long H2=0x3c6ef372fe94f82bL;
+	public static final long H3=0xa54ff53a5f1d36f1L;
+	public static final long H4=0x510e527fade682d1L;
+	public static final long H5=0x9b05688c2b3e6c1fL;
+	public static final long H6=0x1f83d9abfb41bd6bL;
+	public static final long H7=0x5be0cd19137e2179L;
+
+	public static final int len=64;
+
+	public static final long[] K=
+	{0x428a2f98d728ae22L,0x7137449123ef65cdL,0xb5c0fbcfec4d3b2fL,0xe9b5dba58189dbbcL,
+	0x3956c25bf348b538L,0x59f111f1b605d019L,0x923f82a4af194f9bL,0xab1c5ed5da6d8118L,
+	0xd807aa98a3030242L,0x12835b0145706fbeL,0x243185be4ee4b28cL,0x550c7dc3d5ffb4e2L,
+	0x72be5d74f27b896fL,0x80deb1fe3b1696b1L,0x9bdc06a725c71235L,0xc19bf174cf692694L,
+	0xe49b69c19ef14ad2L,0xefbe4786384f25e3L,0x0fc19dc68b8cd5b5L,0x240ca1cc77ac9c65L,
+	0x2de92c6f592b0275L,0x4a7484aa6ea6e483L,0x5cb0a9dcbd41fbd4L,0x76f988da831153b5L,
+	0x983e5152ee66dfabL,0xa831c66d2db43210L,0xb00327c898fb213fL,0xbf597fc7beef0ee4L,
+	0xc6e00bf33da88fc2L,0xd5a79147930aa725L,0x06ca6351e003826fL,0x142929670a0e6e70L,
+	0x27b70a8546d22ffcL,0x2e1b21385c26c926L,0x4d2c6dfc5ac42aedL,0x53380d139d95b3dfL,
+	0x650a73548baf63deL,0x766a0abb3c77b2a8L,0x81c2c92e47edaee6L,0x92722c851482353bL,
+	0xa2bfe8a14cf10364L,0xa81a664bbc423001L,0xc24b8b70d0f89791L,0xc76c51a30654be30L,
+	0xd192e819d6ef5218L,0xd69906245565a910L,0xf40e35855771202aL,0x106aa07032bbd1b8L,
+	0x19a4c116b8d2d0c8L,0x1e376c085141ab53L,0x2748774cdf8eeb99L,0x34b0bcb5e19b48a8L,
+	0x391c0cb3c5c95a63L,0x4ed8aa4ae3418acbL,0x5b9cca4f7763e373L,0x682e6ff3d6b2b8a3L,
+	0x748f82ee5defb2fcL,0x78a5636f43172f60L,0x84c87814a1f0ab72L,0x8cc702081a6439ecL,
+	0x90befffa23631e28L,0xa4506cebde82bde9L,0xbef9a3f7b2c67915L,0xc67178f2e372532bL,
+	0xca273eceea26619cL,0xd186b8c721c0c207L,0xeada7dd6cde0eb1eL,0xf57d4f7fee6ed178L,
+	0x06f067aa72176fbaL,0x0a637dc5a2c898a6L,0x113f9804bef90daeL,0x1b710b35131c471bL,
+	0x28db77f523047d84L,0x32caab7b40c72493L,0x3c9ebe0a15c9bebcL,0x431d67c49c100d4cL,
+	0x4cc5d4becb3e42b6L,0x597f299cfc657e2aL,0x5fcb6fab3ad6faecL,0x6c44198c4a475817L};
+
+/* functions */
+	private static long S(int n,long x)
+	{
+		return (((x)>>>n) | ((x)<<(64-n)));
+	}
+
+	private static long R(int n,long x)
+	{
+		return ((x)>>>n);
+	}
+
+	private static long Ch(long x,long y,long z)
+	{
+		return ((x&y)^(~(x)&z));
+	}
+
+	private static long Maj(long x,long y,long z)
+	{
+		return ((x&y)^(x&z)^(y&z));
+	}
+
+	private static long Sig0(long x)
+	{
+		return (S(28,x)^S(34,x)^S(39,x));
+	}
+
+	private static long Sig1(long x)
+	{
+		return (S(14,x)^S(18,x)^S(41,x));
+	}
+
+	private static long theta0(long x)
+	{
+		return (S(1,x)^S(8,x)^R(7,x));
+	}
+
+	private static long theta1(long x)
+	{
+		return (S(19,x)^S(61,x)^R(6,x));
+	}
+
+
+	private void transform()
+	{ /* basic transformation step */
+		long a,b,c,d,e,f,g,hh,t1,t2;
+		int j;
+		for (j=16;j<80;j++) 
+			w[j]=theta1(w[j-2])+w[j-7]+theta0(w[j-15])+w[j-16];
+		a=h[0]; b=h[1]; c=h[2]; d=h[3]; 
+		e=h[4]; f=h[5]; g=h[6]; hh=h[7];
+
+		for (j=0;j<80;j++)
+		{ /* 80 times - mush it up */
+			t1=hh+Sig1(e)+Ch(e,f,g)+K[j]+w[j];
+			t2=Sig0(a)+Maj(a,b,c);
+			hh=g; g=f; f=e;
+			e=d+t1;
+			d=c;
+			c=b;
+			b=a;
+			a=t1+t2;   
+		
+		}
+		h[0]+=a; h[1]+=b; h[2]+=c; h[3]+=d; 
+		h[4]+=e; h[5]+=f; h[6]+=g; h[7]+=hh; 
+	} 
+
+/* Initialise Hash function */
+	public void init()
+	{ /* initialise */
+		int i;
+		for (i=0;i<80;i++) w[i]=0L;
+		length[0]=length[1]=0L;
+		h[0]=H0;
+		h[1]=H1;
+		h[2]=H2;
+		h[3]=H3;
+		h[4]=H4;
+		h[5]=H5;
+		h[6]=H6;
+		h[7]=H7;
+	}
+
+/* Constructor */
+	public HASH512()
+	{
+		init();
+	}
+
+/* process a single byte */
+	public void process(int byt)
+	{ /* process the next message byte */
+		int cnt;
+		cnt=(int)(length[0]/64)%16;
+    
+		w[cnt]<<=8;
+		w[cnt]|=(byt&0xFF);
+		length[0]+=8;
+		if (length[0]==0L) { length[1]++; length[0]=0L; }
+		if ((length[0]%1024)==0) transform();
+	}
+
+/* process an array of bytes */	
+	public void process_array(byte[] b)
+	{
+		for (int i=0;i<b.length;i++) process((int)b[i]);
+	}
+
+/* process a 32-bit integer */
+	public void process_num(int n)
+	{
+		process((n>>24)&0xff);
+		process((n>>16)&0xff);
+		process((n>>8)&0xff);
+		process(n&0xff);
+	}
+
+/* Generate 64-byte Hash */
+	public byte[] hash()
+	{ /* pad message and finish - supply digest */
+		int i;
+		byte[] digest=new byte[64];
+		long len0,len1;
+		len0=length[0];
+		len1=length[1];
+		process(0x80);
+		while ((length[0]%1024)!=896) process(0);
+		w[14]=len1;
+		w[15]=len0;    
+		transform();
+		for (i=0;i<len;i++)
+		{ /* convert to bytes */
+			digest[i]=(byte)((h[i/8]>>(8*(7-i%8))) & 0xffL);
+		}
+		init();
+		return digest;
+	}
+
+/* test program: should produce digest */
+
+//8e959b75dae313da 8cf4f72814fc143f 8f7779c6eb9f7fa1 7299aeadb6889018 501d289e4900f7e4 331b99dec4b5433a c7d329eeb6dd2654 5e96e55b874be909
+
+	public static void main(String[] args) {
+
+		byte[] test="abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu".getBytes();
+		byte[] digest;
+		int i;
+		HASH512 sh=new HASH512();
+  
+		for (i=0;i<test.length;i++)
+			sh.process(test[i]);
+		
+		digest=sh.hash();    
+		for (i=0;i<64;i++) System.out.format("%02x",digest[i]);
+
+	//	for (i=0;i<32;i++) System.out.format("%d ",digest[i]);
+
+		System.out.println("");
+
+	} 
+}
+
diff --git a/version3/java/MPIN.java b/version3/java/MPIN.java
new file mode 100644
index 0000000..6700e70
--- /dev/null
+++ b/version3/java/MPIN.java
@@ -0,0 +1,823 @@
+/*
+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.
+*/
+
+/* MPIN API Functions */
+
+package org.apache.milagro.amcl.XXX;
+
+import java.util.Date;
+
+import org.apache.milagro.amcl.RAND;
+import org.apache.milagro.amcl.HASH256;
+import org.apache.milagro.amcl.HASH384;
+import org.apache.milagro.amcl.HASH512;
+import org.apache.milagro.amcl.AES;
+
+public class MPIN
+{
+
+//	public static final int SHA256=32;
+//	public static final int SHA384=48;
+//	public static final int SHA512=64;
+
+	public static final int EFS=BIG.MODBYTES;
+	public static final int EGS=BIG.MODBYTES;
+//	public static final int PAS=16;
+	public static final int INVALID_POINT=-14;
+	public static final int BAD_PARAMS=-11;
+	public static final int WRONG_ORDER=-18;
+	public static final int BAD_PIN=-19;
+
+/* Configure your PIN here */
+
+	public static final int MAXPIN=10000;  /* PIN less than this */
+	public static final int PBLEN=14;      /* Number of bits in PIN */
+	public static final int TS=10;         /* 10 for 4 digit PIN, 14 for 6-digit PIN - 2^TS/TS approx = sqrt(MAXPIN) */
+	public static final int TRAP=200;      /* 200 for 4 digit PIN, 2000 for 6-digit PIN  - approx 2*sqrt(MAXPIN) */
+
+//	public static final int HASH_TYPE=SHA256;
+
+
+/* Hash number (optional) and string to array size of Bigs */
+
+	public static byte[] hashit(int sha,int n,byte[] B,int len)
+	{
+		byte[] R=null;
+
+		if (sha==ECP.SHA256)
+		{
+			HASH256 H=new HASH256();
+			if (n>0) H.process_num(n);
+
+			H.process_array(B);
+			R=H.hash();
+		}
+		if (sha==ECP.SHA384)
+		{
+			HASH384 H=new HASH384();
+			if (n>0) H.process_num(n);
+			H.process_array(B);
+			R=H.hash();
+		}
+		if (sha==ECP.SHA512)
+		{
+			HASH512 H=new HASH512();
+			if (n>0) H.process_num(n);
+			H.process_array(B);
+			R=H.hash();
+		}
+		if (R==null) return null;
+		byte[] W=new byte[len];
+
+		if (sha>=len)
+			for (int i=0;i<len;i++) W[i]=R[i];
+		else
+		{
+			for (int i=0;i<sha;i++) W[i+len-sha]=R[i];
+            for (int i=0;i<len-sha;i++) W[i]=0;
+
+			//for (int i=0;i<sha;i++) W[i]=R[i];
+			//for (int i=sha;i<len;i++) W[i]=0;
+		}
+		return W;
+	}
+
+	/* return time in slots since epoch */
+	public static int today() {
+		Date date=new Date();
+		return (int) (date.getTime()/(1000*60*1440));
+	}
+
+	public static byte[] HASH_ID(int sha,byte[] ID,int len)
+	{
+		return hashit(sha,0,ID,len);
+	}
+
+/* Hash the M-Pin transcript - new */
+
+	public static byte[] HASH_ALL(int sha,byte[] HID,byte[] xID,byte[] xCID,byte[] SEC,byte[] Y,byte[] R,byte[] W,int len)
+	{
+		int i,ilen,tlen=0;
+
+		ilen=HID.length+SEC.length+Y.length+R.length+W.length;
+		if (xCID!=null) ilen+=xCID.length;
+		else ilen+=xID.length;
+
+		byte[] T = new byte[ilen];
+
+		for (i=0;i<HID.length;i++) T[i]=HID[i];
+		tlen+=HID.length;
+		if (xCID!=null)
+		{
+			for (i=0;i<xCID.length;i++) T[i+tlen]=xCID[i];
+			tlen+=xCID.length;
+		}	
+		else
+		{
+			for (i=0;i<xID.length;i++) T[i+tlen]=xID[i];
+			tlen+=xID.length;
+		}	
+		for (i=0;i<SEC.length;i++) T[i+tlen]=SEC[i];
+		tlen+=SEC.length;		
+		for (i=0;i<Y.length;i++) T[i+tlen]=Y[i];
+		tlen+=Y.length;	
+		for (i=0;i<R.length;i++) T[i+tlen]=R[i];
+		tlen+=R.length;		
+		for (i=0;i<W.length;i++) T[i+tlen]=W[i];
+		tlen+=W.length;		
+
+		return hashit(sha,0,T,len);
+	}
+
+/* return time since epoch */
+	public static int GET_TIME() {
+		Date date=new Date();
+		return (int) (date.getTime()/1000);
+	}
+
+	public static byte[] mpin_hash(int sha,FP4 c,ECP U)
+	{
+		byte[] w=new byte[EFS];
+		byte[] t=new byte[6*EFS];
+		byte[] h=null;
+		c.geta().getA().toBytes(w); for (int i=0;i<EFS;i++) t[i]=w[i];
+		c.geta().getB().toBytes(w); for (int i=EFS;i<2*EFS;i++) t[i]=w[i-EFS];
+		c.getb().getA().toBytes(w); for (int i=2*EFS;i<3*EFS;i++) t[i]=w[i-2*EFS];
+		c.getb().getB().toBytes(w); for (int i=3*EFS;i<4*EFS;i++) t[i]=w[i-3*EFS];
+
+		U.getX().toBytes(w); for (int i=4*EFS;i<5*EFS;i++) t[i]=w[i-4*EFS];
+		U.getY().toBytes(w); for (int i=5*EFS;i<6*EFS;i++) t[i]=w[i-5*EFS];
+		
+		if (sha==ECP.SHA256)
+		{
+			HASH256 H=new HASH256();
+			H.process_array(t);
+			h=H.hash();
+		}
+		if (sha==ECP.SHA384)
+		{
+			HASH384 H=new HASH384();
+			H.process_array(t);
+			h=H.hash();
+		}
+		if (sha==ECP.SHA512)
+		{
+			HASH512 H=new HASH512();
+			H.process_array(t);
+			h=H.hash();
+		}
+		if (h==null) return null;
+		byte[] R=new byte[ECP.AESKEY];
+		for (int i=0;i<ECP.AESKEY;i++) R[i]=h[i];
+		return R;
+	}
+
+/* these next two functions help to implement elligator squared - http://eprint.iacr.org/2014/043 */
+/* maps a random u to a point on the curve */
+	public static ECP map(BIG u,int cb)
+	{
+		ECP P;
+		BIG x=new BIG(u);
+		BIG p=new BIG(ROM.Modulus);
+		x.mod(p);
+		while (true)
+		{
+			P=new ECP(x,cb);
+			if (!P.is_infinity()) break;
+			x.inc(1);  x.norm();
+		}
+		return P;
+	}
+
+/* returns u derived from P. Random value in range 1 to return value should then be added to u */
+	public static int unmap(BIG u,ECP P)
+	{
+		int s=P.getS();
+		ECP R;
+		int r=0;
+		BIG x=P.getX();
+		u.copy(x);
+		while (true)
+		{
+			u.dec(1); u.norm();
+			r++;
+			R=new ECP(u,s);
+			if (!R.is_infinity()) break;
+		}
+		return r;
+	}
+
+
+
+/* these next two functions implement elligator squared - http://eprint.iacr.org/2014/043 */
+/* Elliptic curve point E in format (0x04,x,y} is converted to form {0x0-,u,v} */
+/* Note that u and v are indistinguisible from random strings */
+	public static int ENCODING(RAND rng,byte[] E)
+	{
+		int rn,m,su,sv;
+		byte[] T=new byte[EFS];
+
+		for (int i=0;i<EFS;i++) T[i]=E[i+1];
+		BIG u=BIG.fromBytes(T);
+		for (int i=0;i<EFS;i++) T[i]=E[i+EFS+1];
+		BIG v=BIG.fromBytes(T);
+		
+		ECP P=new ECP(u,v);
+		if (P.is_infinity()) return INVALID_POINT;
+
+		BIG p=new BIG(ROM.Modulus);
+		u=BIG.randomnum(p,rng);
+
+		su=rng.getByte(); /*if (su<0) su=-su;*/ su%=2;
+		
+		ECP W=map(u,su);
+		P.sub(W); //P.affine();
+		sv=P.getS();
+		rn=unmap(v,P);
+		m=rng.getByte(); /*if (m<0) m=-m;*/ m%=rn;
+		v.inc(m+1);
+		E[0]=(byte)(su+2*sv);
+		u.toBytes(T);
+		for (int i=0;i<EFS;i++) E[i+1]=T[i];
+		v.toBytes(T);
+		for (int i=0;i<EFS;i++) E[i+EFS+1]=T[i];		
+		
+		return 0;
+	}
+
+	public static int DECODING(byte[] D)
+	{
+		int su,sv;
+		byte[] T=new byte[EFS];
+
+		if ((D[0]&0x04)!=0) return INVALID_POINT;
+
+		for (int i=0;i<EFS;i++) T[i]=D[i+1];
+		BIG u=BIG.fromBytes(T);
+		for (int i=0;i<EFS;i++) T[i]=D[i+EFS+1];
+		BIG v=BIG.fromBytes(T);
+
+		su=D[0]&1;
+		sv=(D[0]>>1)&1;
+		ECP W=map(u,su);
+		ECP P=map(v,sv);
+		P.add(W); //P.affine();
+		u=P.getX();
+		v=P.getY();
+		D[0]=0x04;
+		u.toBytes(T);
+		for (int i=0;i<EFS;i++) D[i+1]=T[i];
+		v.toBytes(T);
+		for (int i=0;i<EFS;i++) D[i+EFS+1]=T[i];		
+		
+		return 0;
+	}
+
+/* R=R1+R2 in group G1 */
+	public static int RECOMBINE_G1(byte[] R1,byte[] R2,byte[] R)
+	{
+		ECP P=ECP.fromBytes(R1);
+		ECP Q=ECP.fromBytes(R2);
+
+		if (P.is_infinity() || Q.is_infinity()) return INVALID_POINT;
+
+		P.add(Q); //P.affine();
+
+		P.toBytes(R,false);
+		return 0;
+	}
+
+/* W=W1+W2 in group G2 */
+	public static int RECOMBINE_G2(byte[] W1,byte[] W2,byte[] W)
+	{
+		ECP2 P=ECP2.fromBytes(W1);
+		ECP2 Q=ECP2.fromBytes(W2);
+
+		if (P.is_infinity() || Q.is_infinity()) return INVALID_POINT;
+
+		P.add(Q); //P.affine();
+	
+		P.toBytes(W);
+		return 0;
+	}
+	
+/* create random secret S */
+	public static int RANDOM_GENERATE(RAND rng,byte[] S)
+	{
+		BIG s;
+		BIG r=new BIG(ROM.CURVE_Order);
+		s=BIG.randomnum(r,rng);
+		//if (ROM.AES_S>0)
+		//{
+		//	s.mod2m(2*ROM.AES_S);
+		//}
+		s.toBytes(S);
+		return 0;
+	}
+
+/* Extract PIN from TOKEN for identity CID */
+	public static int EXTRACT_PIN(int sha,byte[] CID,int pin,byte[] TOKEN)
+	{
+		ECP P=ECP.fromBytes(TOKEN);
+		if (P.is_infinity()) return INVALID_POINT;
+		byte[] h=hashit(sha,0,CID,EFS);
+		ECP R=ECP.mapit(h);
+
+
+		pin%=MAXPIN;
+
+		R=R.pinmul(pin,PBLEN);
+		P.sub(R); //P.affine();
+
+		P.toBytes(TOKEN,false);
+
+		return 0;
+	}
+
+/* Implement step 2 on client side of MPin protocol */
+	public static int CLIENT_2(byte[] X,byte[] Y,byte[] SEC)
+	{
+		BIG r=new BIG(ROM.CURVE_Order);
+		ECP P=ECP.fromBytes(SEC);
+		if (P.is_infinity()) return INVALID_POINT;
+
+		BIG px=BIG.fromBytes(X);
+		BIG py=BIG.fromBytes(Y);
+		px.add(py);
+		px.mod(r);
+	//	px.rsub(r);
+
+		P=PAIR.G1mul(P,px);
+		P.neg();
+		P.toBytes(SEC,false);
+		return 0;
+	}
+
+/* Implement step 1 on client side of MPin protocol */
+	public static int CLIENT_1(int sha,int date,byte[] CLIENT_ID,RAND rng,byte[] X,int pin,byte[] TOKEN,byte[] SEC,byte[] xID,byte[] xCID,byte[] PERMIT)
+	{
+		BIG r=new BIG(ROM.CURVE_Order);
+		BIG x;
+		if (rng!=null)
+		{
+			x=BIG.randomnum(r,rng);
+			//if (ROM.AES_S>0)
+			//{
+			//	x.mod2m(2*ROM.AES_S);
+			//}
+			x.toBytes(X);
+		}
+		else
+		{
+			x=BIG.fromBytes(X);
+		}
+		ECP P,T,W;
+		BIG px;
+//		byte[] t=new byte[EFS];
+
+		byte[] h=hashit(sha,0,CLIENT_ID,EFS);
+		P=ECP.mapit(h);
+	
+		T=ECP.fromBytes(TOKEN);
+		if (T.is_infinity()) return INVALID_POINT;
+
+		pin%=MAXPIN;
+		W=P.pinmul(pin,PBLEN);
+		T.add(W);
+		if (date!=0)
+		{
+			W=ECP.fromBytes(PERMIT);
+			if (W.is_infinity()) return INVALID_POINT;
+			T.add(W);
+			h=hashit(sha,date,h,EFS);
+			W=ECP.mapit(h);
+			if (xID!=null)
+			{
+				P=PAIR.G1mul(P,x);
+				P.toBytes(xID,false);
+				W=PAIR.G1mul(W,x);
+				P.add(W);
+				//P.affine();
+			}
+			else
+			{
+				P.add(W); //P.affine();
+				P=PAIR.G1mul(P,x);
+			}
+			if (xCID!=null) P.toBytes(xCID,false);
+		}
+		else
+		{
+			if (xID!=null)
+			{
+				P=PAIR.G1mul(P,x);
+				P.toBytes(xID,false);
+			}
+		}
+
+		//T.affine();
+		T.toBytes(SEC,false);
+		return 0;
+	}
+
+/* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */
+	public static int GET_SERVER_SECRET(byte[] S,byte[] SST)
+	{
+		ECP2 Q=ECP2.generator();
+		BIG s=BIG.fromBytes(S);
+		Q=PAIR.G2mul(Q,s);
+		Q.toBytes(SST);
+		return 0;
+	}
+
+/*
+ W=x*H(G);
+ if RNG == NULL then X is passed in 
+ if RNG != NULL the X is passed out 
+ if type=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve
+*/
+	public static int GET_G1_MULTIPLE(RAND rng, int type,byte[] X,byte[] G,byte[] W)
+	{
+		BIG x;
+		BIG r=new BIG(ROM.CURVE_Order);
+		if (rng!=null)
+		{
+			x=BIG.randomnum(r,rng);
+			//if (ROM.AES_S>0)
+			//{
+			//	x.mod2m(2*ROM.AES_S);
+			//}
+			x.toBytes(X);
+		}
+		else
+		{
+			x=BIG.fromBytes(X);
+		}
+		ECP P;
+		if (type==0)
+		{
+			P=ECP.fromBytes(G);
+			if (P.is_infinity()) return INVALID_POINT;
+		}
+		else
+			P=ECP.mapit(G);
+
+		PAIR.G1mul(P,x).toBytes(W,false);
+		return 0;
+	}
+
+/* Client secret CST=S*H(CID) where CID is client ID and S is master secret */
+/* CID is hashed externally */
+	public static int GET_CLIENT_SECRET(byte[] S,byte[] CID,byte[] CST)
+	{
+		return GET_G1_MULTIPLE(null,1,S,CID,CST);
+	}
+
+/* Time Permit CTT=S*(date|H(CID)) where S is master secret */
+	public static int GET_CLIENT_PERMIT(int sha,int date,byte[] S,byte[] CID,byte[] CTT)
+	{
+		byte[] h=hashit(sha,date,CID,EFS);
+		ECP P=ECP.mapit(h);
+
+		BIG s=BIG.fromBytes(S);
+		ECP OP=PAIR.G1mul(P,s);
+
+		OP.toBytes(CTT,false);
+		return 0;
+	}
+
+/* Outputs H(CID) and H(T|H(CID)) for time permits. If no time permits set HID=HTID */
+	public static void SERVER_1(int sha,int date,byte[] CID,byte[] HID,byte[] HTID)
+	{
+		byte[] h=hashit(sha,0,CID,EFS);
+		ECP R,P=ECP.mapit(h);
+
+		P.toBytes(HID,false);   // new
+		if (date!=0)
+		{
+	//		if (HID!=null) P.toBytes(HID);
+			h=hashit(sha,date,h,EFS);
+			R=ECP.mapit(h);
+			P.add(R); //P.affine();
+			P.toBytes(HTID,false);
+		}
+	//	else P.toBytes(HID,false);
+	}
+
+/* Implement step 2 of MPin protocol on server side */
+	public static int SERVER_2(int date,byte[] HID,byte[] HTID,byte[] Y,byte[] SST,byte[] xID,byte[] xCID,byte[] mSEC,byte[] E,byte[] F)
+	{
+		BIG q=new BIG(ROM.Modulus);
+		ECP2 Q=ECP2.generator();
+
+		ECP2 sQ=ECP2.fromBytes(SST);
+		if (sQ.is_infinity()) return INVALID_POINT;	
+
+		ECP R;
+		if (date!=0)
+			R=ECP.fromBytes(xCID);
+		else 
+		{
+			if (xID==null) return BAD_PARAMS;
+			R=ECP.fromBytes(xID);
+		}
+		if (R.is_infinity()) return INVALID_POINT;
+
+		BIG y=BIG.fromBytes(Y);
+		ECP P;
+		if (date!=0) P=ECP.fromBytes(HTID);
+		else 
+		{
+			if (HID==null) return BAD_PARAMS;
+			P=ECP.fromBytes(HID);
+		}
+	
+		if (P.is_infinity()) return INVALID_POINT;
+
+		P=PAIR.G1mul(P,y);
+		P.add(R); //P.affine();
+		R=ECP.fromBytes(mSEC);
+		if (R.is_infinity()) return INVALID_POINT;
+
+		FP12 g;
+
+		g=PAIR.ate2(Q,R,sQ,P);
+		g=PAIR.fexp(g);
+
+		if (!g.isunity())
+		{
+			if (HID!=null && xID!=null && E!=null && F!=null)
+			{
+				g.toBytes(E);
+				if (date!=0)
+				{
+					P=ECP.fromBytes(HID);
+					if (P.is_infinity()) return INVALID_POINT;
+					R=ECP.fromBytes(xID);
+					if (R.is_infinity()) return INVALID_POINT;
+
+					P=PAIR.G1mul(P,y);
+					P.add(R); //P.affine();
+				}
+				g=PAIR.ate(Q,P);
+				g=PAIR.fexp(g);
+				g.toBytes(F);
+			}
+			return BAD_PIN;
+		}
+
+		return 0;
+	}
+
+/* Pollards kangaroos used to return PIN error */
+	public static int KANGAROO(byte[] E,byte[] F)
+	{
+		FP12 ge=FP12.fromBytes(E);
+		FP12 gf=FP12.fromBytes(F);
+		int[] distance = new int[TS];
+		FP12 t=new FP12(gf);
+		FP12[] table=new FP12[TS];
+		int i,j,m,s,dn,dm,res,steps;
+
+		s=1;
+		for (m=0;m<TS;m++)
+		{
+			distance[m]=s;
+			table[m]=new FP12(t);
+			s*=2;
+			t.usqr();
+		}
+		t.one();
+		dn=0;
+		for (j=0;j<TRAP;j++)
+		{
+			i=t.geta().geta().getA().lastbits(20)%TS;
+			t.mul(table[i]);
+			dn+=distance[i];
+		}
+		gf.copy(t); gf.conj();
+		steps=0; dm=0;
+		res=0;
+		while (dm-dn<MAXPIN)
+		{
+			steps++;
+			if (steps>4*TRAP) break;
+			i=ge.geta().geta().getA().lastbits(20)%TS;
+			ge.mul(table[i]);
+			dm+=distance[i];
+			if (ge.equals(t))
+			{
+				res=dm-dn;
+				break;
+			}
+			if (ge.equals(gf))
+			{
+				res=dn-dm;
+				break;
+			}
+
+		}
+		if (steps>4*TRAP || dm-dn>=MAXPIN) {res=0; }    // Trap Failed  - probable invalid token
+		return res;
+	}
+
+/* Functions to support M-Pin Full */
+
+	public static int PRECOMPUTE(byte[] TOKEN,byte[] CID,byte[] G1,byte[] G2)
+	{
+		ECP P,T;
+		FP12 g;
+
+		T=ECP.fromBytes(TOKEN);
+		if (T.is_infinity()) return INVALID_POINT; 
+
+		P=ECP.mapit(CID);
+
+		ECP2 Q=ECP2.generator();
+
+		g=PAIR.ate(Q,T);
+		g=PAIR.fexp(g);
+		g.toBytes(G1);
+
+		g=PAIR.ate(Q,P);
+		g=PAIR.fexp(g);
+		g.toBytes(G2);
+
+		return 0;
+	}
+
+
+
+/* calculate common key on client side */
+/* wCID = w.(A+AT) */
+	public static int CLIENT_KEY(int sha,byte[] G1,byte[] G2,int pin,byte[] R,byte[] X,byte[] H,byte[] wCID,byte[] CK)
+	{
+		byte[] t;
+
+		FP12 g1=FP12.fromBytes(G1);
+		FP12 g2=FP12.fromBytes(G2);
+		BIG z=BIG.fromBytes(R);
+		BIG x=BIG.fromBytes(X);
+		BIG h=BIG.fromBytes(H);
+
+		ECP W=ECP.fromBytes(wCID);
+		if (W.is_infinity()) return INVALID_POINT; 
+
+		W=PAIR.G1mul(W,x);
+
+//		FP2 f=new FP2(new BIG(ROM.Fra),new BIG(ROM.Frb));
+		BIG r=new BIG(ROM.CURVE_Order);
+//		BIG q=new BIG(ROM.Modulus);
+
+		z.add(h);	//new
+		z.mod(r);
+
+		g2.pinpow(pin,PBLEN);
+		g1.mul(g2);
+
+		FP4 c=g1.compow(z,r);
+/*
+		BIG m=new BIG(q);
+		m.mod(r);
+
+		BIG a=new BIG(z);
+		a.mod(m);
+
+		BIG b=new BIG(z);
+		b.div(m);
+
+
+		FP4 c=g1.trace();
+		g2.copy(g1);
+		g2.frob(f);
+		FP4 cp=g2.trace();
+		g1.conj();
+		g2.mul(g1);
+		FP4 cpm1=g2.trace();
+		g2.mul(g1);
+		FP4 cpm2=g2.trace();
+
+		c=c.xtr_pow2(cp,cpm1,cpm2,a,b);
+*/
+		t=mpin_hash(sha,c,W);
+
+		for (int i=0;i<ECP.AESKEY;i++) CK[i]=t[i];
+
+		return 0;
+	}
+
+/* calculate common key on server side */
+/* Z=r.A - no time permits involved */
+
+	public static int SERVER_KEY(int sha,byte[] Z,byte[] SST,byte[] W,byte[] H,byte[] HID,byte[] xID,byte[] xCID,byte[] SK)
+	{
+		byte[] t;
+
+		ECP2 sQ=ECP2.fromBytes(SST);
+		if (sQ.is_infinity()) return INVALID_POINT; 
+		ECP R=ECP.fromBytes(Z);
+		if (R.is_infinity()) return INVALID_POINT; 
+		ECP A=ECP.fromBytes(HID);
+		if (A.is_infinity()) return INVALID_POINT; 
+
+		ECP U;
+		if (xCID!=null)
+			U=ECP.fromBytes(xCID);
+		else
+			U=ECP.fromBytes(xID);
+		if (U.is_infinity()) return INVALID_POINT; 
+
+		BIG w=BIG.fromBytes(W);
+		BIG h=BIG.fromBytes(H);
+		A=PAIR.G1mul(A,h);	// new
+		R.add(A); //R.affine();
+
+		U=PAIR.G1mul(U,w);
+		FP12 g=PAIR.ate(sQ,R);
+		g=PAIR.fexp(g);
+
+		FP4 c=g.trace();
+
+		t=mpin_hash(sha,c,U);
+
+		for (int i=0;i<ECP.AESKEY;i++) SK[i]=t[i];
+
+		return 0;
+	}
+
+/* Generate Y = H(epoch, xCID/xID) */
+	public static void GET_Y(int sha,int TimeValue,byte[] xCID,byte[] Y)
+	{
+		byte[] h = hashit(sha,TimeValue,xCID,EFS);
+		BIG y = BIG.fromBytes(h);
+		BIG q=new BIG(ROM.CURVE_Order);
+		y.mod(q);
+		//if (ROM.AES_S>0)
+		//{
+		//	y.mod2m(2*ROM.AES_S);
+		//}
+		y.toBytes(Y);
+	}
+        
+/* One pass MPIN Client */
+	public static int CLIENT(int sha,int date,byte[] CLIENT_ID,RAND RNG,byte[] X,int pin,byte[] TOKEN,byte[] SEC,byte[] xID,byte[] xCID,byte[] PERMIT, int TimeValue, byte[] Y)
+	{
+		int rtn=0;
+        
+		byte[] pID;
+		if (date == 0)
+			pID = xID;
+		else
+			pID = xCID;
+          
+		rtn = CLIENT_1(sha,date,CLIENT_ID,RNG,X,pin,TOKEN,SEC,xID,xCID,PERMIT);
+		if (rtn != 0)
+			return rtn;
+        
+		GET_Y(sha,TimeValue,pID,Y);
+        
+		rtn = CLIENT_2(X,Y,SEC);
+		if (rtn != 0)
+		return rtn;
+        
+		return 0;
+	}
+        
+/* One pass MPIN Server */
+	public static int SERVER(int sha,int date,byte[] HID,byte[] HTID,byte[] Y,byte[] SST,byte[] xID,byte[] xCID,byte[] SEC,byte[] E,byte[] F,byte[] CID, int TimeValue)
+	{
+		int rtn=0;
+        
+		byte[] pID;
+		if (date == 0)
+			pID = xID;
+		else
+			pID = xCID;
+          
+		SERVER_1(sha,date,CID,HID,HTID);
+        
+		GET_Y(sha,TimeValue,pID,Y);
+          
+		rtn = SERVER_2(date,HID,HTID,Y,SST,xID,xCID,SEC,E,F);
+		if (rtn != 0)
+			return rtn;
+        
+		return 0;
+	}
+}
diff --git a/version3/java/MPIN192.java b/version3/java/MPIN192.java
new file mode 100644
index 0000000..ce4d61a
--- /dev/null
+++ b/version3/java/MPIN192.java
@@ -0,0 +1,806 @@
+/*
+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.
+*/
+
+/* MPIN API Functions */
+
+package org.apache.milagro.amcl.XXX;
+
+import java.util.Date;
+
+import org.apache.milagro.amcl.RAND;
+import org.apache.milagro.amcl.HASH256;
+import org.apache.milagro.amcl.HASH384;
+import org.apache.milagro.amcl.HASH512;
+import org.apache.milagro.amcl.AES;
+
+public class MPIN192
+{
+
+//	public static final int SHA256=32;
+//	public static final int SHA384=48;
+//	public static final int SHA512=64;
+
+	public static final int EFS=BIG.MODBYTES;
+	public static final int EGS=BIG.MODBYTES;
+//	public static final int PAS=16;
+	public static final int INVALID_POINT=-14;
+	public static final int BAD_PARAMS=-11;
+	public static final int WRONG_ORDER=-18;
+	public static final int BAD_PIN=-19;
+
+/* Configure your PIN here */
+
+	public static final int MAXPIN=10000;  /* PIN less than this */
+	public static final int PBLEN=14;      /* Number of bits in PIN */
+	public static final int TS=10;         /* 10 for 4 digit PIN, 14 for 6-digit PIN - 2^TS/TS approx = sqrt(MAXPIN) */
+	public static final int TRAP=200;      /* 200 for 4 digit PIN, 2000 for 6-digit PIN  - approx 2*sqrt(MAXPIN) */
+
+//	public static final int HASH_TYPE=SHA256;
+
+
+/* Hash number (optional) and string to array size of Bigs */
+
+	public static byte[] hashit(int sha,int n,byte[] B,int len)
+	{
+		byte[] R=null;
+
+		if (sha==ECP.SHA256)
+		{
+			HASH256 H=new HASH256();
+			if (n>0) H.process_num(n);
+
+			H.process_array(B);
+			R=H.hash();
+		}
+		if (sha==ECP.SHA384)
+		{
+			HASH384 H=new HASH384();
+			if (n>0) H.process_num(n);
+			H.process_array(B);
+			R=H.hash();
+		}
+		if (sha==ECP.SHA512)
+		{
+			HASH512 H=new HASH512();
+			if (n>0) H.process_num(n);
+			H.process_array(B);
+			R=H.hash();
+		}
+		if (R==null) return null;
+		byte[] W=new byte[len];
+
+		if (sha>=len)
+			for (int i=0;i<len;i++) W[i]=R[i];
+		else
+		{
+			for (int i=0;i<sha;i++) W[i+len-sha]=R[i];
+            for (int i=0;i<len-sha;i++) W[i]=0;
+
+			//for (int i=0;i<sha;i++) W[i]=R[i];
+			//for (int i=sha;i<len;i++) W[i]=0;
+		}
+		return W;
+	}
+
+	/* return time in slots since epoch */
+	public static int today() {
+		Date date=new Date();
+		return (int) (date.getTime()/(1000*60*1440));
+	}
+
+	public static byte[] HASH_ID(int sha,byte[] ID,int len)
+	{
+		return hashit(sha,0,ID,len);
+	}
+
+/* Hash the M-Pin transcript - new */
+
+	public static byte[] HASH_ALL(int sha,byte[] HID,byte[] xID,byte[] xCID,byte[] SEC,byte[] Y,byte[] R,byte[] W,int len)
+	{
+		int i,ilen,tlen=0;
+
+		ilen=HID.length+SEC.length+Y.length+R.length+W.length;
+		if (xCID!=null) ilen+=xCID.length;
+		else ilen+=xID.length;
+
+		byte[] T = new byte[ilen];
+
+		for (i=0;i<HID.length;i++) T[i]=HID[i];
+		tlen+=HID.length;
+		if (xCID!=null)
+		{
+			for (i=0;i<xCID.length;i++) T[i+tlen]=xCID[i];
+			tlen+=xCID.length;
+		}	
+		else
+		{
+			for (i=0;i<xID.length;i++) T[i+tlen]=xID[i];
+			tlen+=xID.length;
+		}	
+		for (i=0;i<SEC.length;i++) T[i+tlen]=SEC[i];
+		tlen+=SEC.length;		
+		for (i=0;i<Y.length;i++) T[i+tlen]=Y[i];
+		tlen+=Y.length;	
+		for (i=0;i<R.length;i++) T[i+tlen]=R[i];
+		tlen+=R.length;		
+		for (i=0;i<W.length;i++) T[i+tlen]=W[i];
+		tlen+=W.length;		
+
+		return hashit(sha,0,T,len);
+	}
+
+/* return time since epoch */
+	public static int GET_TIME() {
+		Date date=new Date();
+		return (int) (date.getTime()/1000);
+	}
+
+	public static byte[] mpin_hash(int sha,FP8 c,ECP U)
+	{
+		byte[] w=new byte[EFS];
+		byte[] t=new byte[10*EFS];
+		byte[] h=null;
+		c.geta().geta().getA().toBytes(w); for (int i=0;i<EFS;i++) t[i]=w[i];
+		c.geta().geta().getB().toBytes(w); for (int i=EFS;i<2*EFS;i++) t[i]=w[i-EFS];
+		c.geta().getb().getA().toBytes(w); for (int i=2*EFS;i<3*EFS;i++) t[i]=w[i-2*EFS];
+		c.geta().getb().getB().toBytes(w); for (int i=3*EFS;i<4*EFS;i++) t[i]=w[i-3*EFS];
+	
+		c.getb().geta().getA().toBytes(w); for (int i=4*EFS;i<5*EFS;i++) t[i]=w[i-4*EFS];
+		c.getb().geta().getB().toBytes(w); for (int i=5*EFS;i<6*EFS;i++) t[i]=w[i-5*EFS];
+		c.getb().getb().getA().toBytes(w); for (int i=6*EFS;i<7*EFS;i++) t[i]=w[i-6*EFS];
+		c.getb().getb().getB().toBytes(w); for (int i=7*EFS;i<8*EFS;i++) t[i]=w[i-7*EFS];
+
+		
+		U.getX().toBytes(w); for (int i=8*EFS;i<9*EFS;i++) t[i]=w[i-8*EFS];
+		U.getY().toBytes(w); for (int i=9*EFS;i<10*EFS;i++) t[i]=w[i-9*EFS];
+		
+		if (sha==ECP.SHA256)
+		{
+			HASH256 H=new HASH256();
+			H.process_array(t);
+			h=H.hash();
+		}
+		if (sha==ECP.SHA384)
+		{
+			HASH384 H=new HASH384();
+			H.process_array(t);
+			h=H.hash();
+		}
+		if (sha==ECP.SHA512)
+		{
+			HASH512 H=new HASH512();
+			H.process_array(t);
+			h=H.hash();
+		}
+		if (h==null) return null;
+		byte[] R=new byte[ECP.AESKEY];
+		for (int i=0;i<ECP.AESKEY;i++) R[i]=h[i];
+		return R;
+	}
+
+/* these next two functions help to implement elligator squared - http://eprint.iacr.org/2014/043 */
+/* maps a random u to a point on the curve */
+	public static ECP map(BIG u,int cb)
+	{
+		ECP P;
+		BIG x=new BIG(u);
+		BIG p=new BIG(ROM.Modulus);
+		x.mod(p);
+		while (true)
+		{
+			P=new ECP(x,cb);
+			if (!P.is_infinity()) break;
+			x.inc(1);  x.norm();
+		}
+		return P;
+	}
+
+/* returns u derived from P. Random value in range 1 to return value should then be added to u */
+	public static int unmap(BIG u,ECP P)
+	{
+		int s=P.getS();
+		ECP R;
+		int r=0;
+		BIG x=P.getX();
+		u.copy(x);
+		while (true)
+		{
+			u.dec(1); u.norm();
+			r++;
+			R=new ECP(u,s);
+			if (!R.is_infinity()) break;
+		}
+		return r;
+	}
+
+
+
+/* these next two functions implement elligator squared - http://eprint.iacr.org/2014/043 */
+/* Elliptic curve point E in format (0x04,x,y} is converted to form {0x0-,u,v} */
+/* Note that u and v are indistinguisible from random strings */
+	public static int ENCODING(RAND rng,byte[] E)
+	{
+		int rn,m,su,sv;
+		byte[] T=new byte[EFS];
+
+		for (int i=0;i<EFS;i++) T[i]=E[i+1];
+		BIG u=BIG.fromBytes(T);
+		for (int i=0;i<EFS;i++) T[i]=E[i+EFS+1];
+		BIG v=BIG.fromBytes(T);
+		
+		ECP P=new ECP(u,v);
+		if (P.is_infinity()) return INVALID_POINT;
+
+		BIG p=new BIG(ROM.Modulus);
+		u=BIG.randomnum(p,rng);
+
+		su=rng.getByte(); /*if (su<0) su=-su;*/ su%=2;
+		
+		ECP W=map(u,su);
+		P.sub(W); //P.affine();
+		sv=P.getS();
+		rn=unmap(v,P);
+		m=rng.getByte(); /*if (m<0) m=-m;*/ m%=rn;
+		v.inc(m+1);
+		E[0]=(byte)(su+2*sv);
+		u.toBytes(T);
+		for (int i=0;i<EFS;i++) E[i+1]=T[i];
+		v.toBytes(T);
+		for (int i=0;i<EFS;i++) E[i+EFS+1]=T[i];		
+		
+		return 0;
+	}
+
+	public static int DECODING(byte[] D)
+	{
+		int su,sv;
+		byte[] T=new byte[EFS];
+
+		if ((D[0]&0x04)!=0) return INVALID_POINT;
+
+		for (int i=0;i<EFS;i++) T[i]=D[i+1];
+		BIG u=BIG.fromBytes(T);
+		for (int i=0;i<EFS;i++) T[i]=D[i+EFS+1];
+		BIG v=BIG.fromBytes(T);
+
+		su=D[0]&1;
+		sv=(D[0]>>1)&1;
+		ECP W=map(u,su);
+		ECP P=map(v,sv);
+		P.add(W); //P.affine();
+		u=P.getX();
+		v=P.getY();
+		D[0]=0x04;
+		u.toBytes(T);
+		for (int i=0;i<EFS;i++) D[i+1]=T[i];
+		v.toBytes(T);
+		for (int i=0;i<EFS;i++) D[i+EFS+1]=T[i];		
+		
+		return 0;
+	}
+
+/* R=R1+R2 in group G1 */
+	public static int RECOMBINE_G1(byte[] R1,byte[] R2,byte[] R)
+	{
+		ECP P=ECP.fromBytes(R1);
+		ECP Q=ECP.fromBytes(R2);
+
+		if (P.is_infinity() || Q.is_infinity()) return INVALID_POINT;
+
+		P.add(Q); //P.affine();
+
+		P.toBytes(R,false);
+		return 0;
+	}
+
+/* W=W1+W2 in group G2 */
+	public static int RECOMBINE_G2(byte[] W1,byte[] W2,byte[] W)
+	{
+		ECP4 P=ECP4.fromBytes(W1);
+		ECP4 Q=ECP4.fromBytes(W2);
+
+		if (P.is_infinity() || Q.is_infinity()) return INVALID_POINT;
+
+		P.add(Q); //P.affine();
+	
+		P.toBytes(W);
+		return 0;
+	}
+	
+/* create random secret S */
+	public static int RANDOM_GENERATE(RAND rng,byte[] S)
+	{
+		BIG s;
+		BIG r=new BIG(ROM.CURVE_Order);
+		s=BIG.randomnum(r,rng);
+		//if (ROM.AES_S>0)
+		//{
+		//	s.mod2m(2*ROM.AES_S);
+		//}
+		s.toBytes(S);
+		return 0;
+	}
+
+/* Extract PIN from TOKEN for identity CID */
+	public static int EXTRACT_PIN(int sha,byte[] CID,int pin,byte[] TOKEN)
+	{
+		ECP P=ECP.fromBytes(TOKEN);
+		if (P.is_infinity()) return INVALID_POINT;
+		byte[] h=hashit(sha,0,CID,EFS);
+		ECP R=ECP.mapit(h);
+
+
+		pin%=MAXPIN;
+
+		R=R.pinmul(pin,PBLEN);
+		P.sub(R); //P.affine();
+
+		P.toBytes(TOKEN,false);
+
+		return 0;
+	}
+
+/* Implement step 2 on client side of MPin protocol */
+	public static int CLIENT_2(byte[] X,byte[] Y,byte[] SEC)
+	{
+		BIG r=new BIG(ROM.CURVE_Order);
+		ECP P=ECP.fromBytes(SEC);
+		if (P.is_infinity()) return INVALID_POINT;
+
+		BIG px=BIG.fromBytes(X);
+		BIG py=BIG.fromBytes(Y);
+		px.add(py);
+		px.mod(r);
+	//	px.rsub(r);
+
+		P=PAIR192.G1mul(P,px);
+		P.neg();
+		P.toBytes(SEC,false);
+		return 0;
+	}
+
+/* Implement step 1 on client side of MPin protocol */
+	public static int CLIENT_1(int sha,int date,byte[] CLIENT_ID,RAND rng,byte[] X,int pin,byte[] TOKEN,byte[] SEC,byte[] xID,byte[] xCID,byte[] PERMIT)
+	{
+		BIG r=new BIG(ROM.CURVE_Order);
+		BIG x;
+		if (rng!=null)
+		{
+			x=BIG.randomnum(r,rng);
+			//if (ROM.AES_S>0)
+			//{
+			//	x.mod2m(2*ROM.AES_S);
+			//}
+			x.toBytes(X);
+		}
+		else
+		{
+			x=BIG.fromBytes(X);
+		}
+		ECP P,T,W;
+		BIG px;
+//		byte[] t=new byte[EFS];
+
+		byte[] h=hashit(sha,0,CLIENT_ID,EFS);
+		P=ECP.mapit(h);
+	
+		T=ECP.fromBytes(TOKEN);
+		if (T.is_infinity()) return INVALID_POINT;
+
+		pin%=MAXPIN;
+		W=P.pinmul(pin,PBLEN);
+		T.add(W);
+		if (date!=0)
+		{
+			W=ECP.fromBytes(PERMIT);
+			if (W.is_infinity()) return INVALID_POINT;
+			T.add(W);
+			h=hashit(sha,date,h,EFS);
+			W=ECP.mapit(h);
+			if (xID!=null)
+			{
+				P=PAIR192.G1mul(P,x);
+				P.toBytes(xID,false);
+				W=PAIR192.G1mul(W,x);
+				P.add(W); //P.affine();
+			}
+			else
+			{
+				P.add(W); //P.affine();
+				P=PAIR192.G1mul(P,x);
+			}
+			if (xCID!=null) P.toBytes(xCID,false);
+		}
+		else
+		{
+			if (xID!=null)
+			{
+				P=PAIR192.G1mul(P,x);
+				P.toBytes(xID,false);
+			}
+		}
+
+		//T.affine();
+		T.toBytes(SEC,false);
+		return 0;
+	}
+
+/* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */
+	public static int GET_SERVER_SECRET(byte[] S,byte[] SST)
+	{
+		ECP4 Q=ECP4.generator();
+		BIG s=BIG.fromBytes(S);
+		Q=PAIR192.G2mul(Q,s);
+		Q.toBytes(SST);
+		return 0;
+	}
+
+/*
+ W=x*H(G);
+ if RNG == NULL then X is passed in 
+ if RNG != NULL the X is passed out 
+ if type=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve
+*/
+	public static int GET_G1_MULTIPLE(RAND rng, int type,byte[] X,byte[] G,byte[] W)
+	{
+		BIG x;
+		BIG r=new BIG(ROM.CURVE_Order);
+		if (rng!=null)
+		{
+			x=BIG.randomnum(r,rng);
+			//if (ROM.AES_S>0)
+			//{
+			//	x.mod2m(2*ROM.AES_S);
+			//}
+			x.toBytes(X);
+		}
+		else
+		{
+			x=BIG.fromBytes(X);
+		}
+		ECP P;
+		if (type==0)
+		{
+			P=ECP.fromBytes(G);
+			if (P.is_infinity()) return INVALID_POINT;
+		}
+		else
+			P=ECP.mapit(G);
+
+		PAIR192.G1mul(P,x).toBytes(W,false);
+		return 0;
+	}
+
+/* Client secret CST=S*H(CID) where CID is client ID and S is master secret */
+/* CID is hashed externally */
+	public static int GET_CLIENT_SECRET(byte[] S,byte[] CID,byte[] CST)
+	{
+		return GET_G1_MULTIPLE(null,1,S,CID,CST);
+	}
+
+/* Time Permit CTT=S*(date|H(CID)) where S is master secret */
+	public static int GET_CLIENT_PERMIT(int sha,int date,byte[] S,byte[] CID,byte[] CTT)
+	{
+		byte[] h=hashit(sha,date,CID,EFS);
+		ECP P=ECP.mapit(h);
+
+		BIG s=BIG.fromBytes(S);
+		ECP OP=PAIR192.G1mul(P,s);
+
+		OP.toBytes(CTT,false);
+		return 0;
+	}
+
+/* Outputs H(CID) and H(T|H(CID)) for time permits. If no time permits set HID=HTID */
+	public static void SERVER_1(int sha,int date,byte[] CID,byte[] HID,byte[] HTID)
+	{
+		byte[] h=hashit(sha,0,CID,EFS);
+		ECP R,P=ECP.mapit(h);
+
+		P.toBytes(HID,false);   // new
+		if (date!=0)
+		{
+	//		if (HID!=null) P.toBytes(HID,false);
+			h=hashit(sha,date,h,EFS);
+			R=ECP.mapit(h);
+			P.add(R); //P.affine();
+			P.toBytes(HTID,false);
+		}
+	//	else P.toBytes(HID,false);
+	}
+
+/* Implement step 2 of MPin protocol on server side */
+	public static int SERVER_2(int date,byte[] HID,byte[] HTID,byte[] Y,byte[] SST,byte[] xID,byte[] xCID,byte[] mSEC,byte[] E,byte[] F)
+	{
+		BIG q=new BIG(ROM.Modulus);
+		ECP4 Q=ECP4.generator();
+
+		ECP4 sQ=ECP4.fromBytes(SST);
+		if (sQ.is_infinity()) return INVALID_POINT;	
+
+		ECP R;
+		if (date!=0)
+			R=ECP.fromBytes(xCID);
+		else 
+		{
+			if (xID==null) return BAD_PARAMS;
+			R=ECP.fromBytes(xID);
+		}
+		if (R.is_infinity()) return INVALID_POINT;
+
+		BIG y=BIG.fromBytes(Y);
+		ECP P;
+		if (date!=0) P=ECP.fromBytes(HTID);
+		else 
+		{
+			if (HID==null) return BAD_PARAMS;
+			P=ECP.fromBytes(HID);
+		}
+	
+		if (P.is_infinity()) return INVALID_POINT;
+
+		P=PAIR192.G1mul(P,y);
+		P.add(R); //P.affine();
+		R=ECP.fromBytes(mSEC);
+		if (R.is_infinity()) return INVALID_POINT;
+
+		FP24 g;
+
+		g=PAIR192.ate2(Q,R,sQ,P);
+		g=PAIR192.fexp(g);
+
+		if (!g.isunity())
+		{
+			if (HID!=null && xID!=null && E!=null && F!=null)
+			{
+				g.toBytes(E);
+				if (date!=0)
+				{
+					P=ECP.fromBytes(HID);
+					if (P.is_infinity()) return INVALID_POINT;
+					R=ECP.fromBytes(xID);
+					if (R.is_infinity()) return INVALID_POINT;
+
+					P=PAIR192.G1mul(P,y);
+					P.add(R); //P.affine();
+				}
+				g=PAIR192.ate(Q,P);
+				g=PAIR192.fexp(g);
+				g.toBytes(F);
+			}
+			return BAD_PIN;
+		}
+
+		return 0;
+	}
+
+/* Pollards kangaroos used to return PIN error */
+	public static int KANGAROO(byte[] E,byte[] F)
+	{
+		FP24 ge=FP24.fromBytes(E);
+		FP24 gf=FP24.fromBytes(F);
+		int[] distance = new int[TS];
+		FP24 t=new FP24(gf);
+		FP24[] table=new FP24[TS];
+		int i,j,m,s,dn,dm,res,steps;
+
+		s=1;
+		for (m=0;m<TS;m++)
+		{
+			distance[m]=s;
+			table[m]=new FP24(t);
+			s*=2;
+			t.usqr();
+		}
+		t.one();
+		dn=0;
+		for (j=0;j<TRAP;j++)
+		{
+			i=t.geta().geta().geta().getA().lastbits(20)%TS;
+			t.mul(table[i]);
+			dn+=distance[i];
+		}
+		gf.copy(t); gf.conj();
+		steps=0; dm=0;
+		res=0;
+		while (dm-dn<MAXPIN)
+		{
+			steps++;
+			if (steps>4*TRAP) break;
+			i=ge.geta().geta().geta().getA().lastbits(20)%TS;
+			ge.mul(table[i]);
+			dm+=distance[i];
+			if (ge.equals(t))
+			{
+				res=dm-dn;
+				break;
+			}
+			if (ge.equals(gf))
+			{
+				res=dn-dm;
+				break;
+			}
+
+		}
+		if (steps>4*TRAP || dm-dn>=MAXPIN) {res=0; }    // Trap Failed  - probable invalid token
+		return res;
+	}
+
+/* Functions to support M-Pin Full */
+
+	public static int PRECOMPUTE(byte[] TOKEN,byte[] CID,byte[] G1,byte[] G2)
+	{
+		ECP P,T;
+		FP24 g;
+
+		T=ECP.fromBytes(TOKEN);
+		if (T.is_infinity()) return INVALID_POINT; 
+
+		P=ECP.mapit(CID);
+
+		ECP4 Q=ECP4.generator();
+
+		g=PAIR192.ate(Q,T);
+		g=PAIR192.fexp(g);
+		g.toBytes(G1);
+
+		g=PAIR192.ate(Q,P);
+		g=PAIR192.fexp(g);
+		g.toBytes(G2);
+
+		return 0;
+	}
+
+
+
+/* calculate common key on client side */
+/* wCID = w.(A+AT) */
+	public static int CLIENT_KEY(int sha,byte[] G1,byte[] G2,int pin,byte[] R,byte[] X,byte[] H,byte[] wCID,byte[] CK)
+	{
+		byte[] t;
+
+		FP24 g1=FP24.fromBytes(G1);
+		FP24 g2=FP24.fromBytes(G2);
+		BIG z=BIG.fromBytes(R);
+		BIG x=BIG.fromBytes(X);
+		BIG h=BIG.fromBytes(H);
+
+		ECP W=ECP.fromBytes(wCID);
+		if (W.is_infinity()) return INVALID_POINT; 
+
+		W=PAIR192.G1mul(W,x);
+
+//		FP2 f=new FP2(new BIG(ROM.Fra),new BIG(ROM.Frb));
+		BIG r=new BIG(ROM.CURVE_Order);
+//		BIG q=new BIG(ROM.Modulus);
+
+		z.add(h);	//new
+		z.mod(r);
+
+		g2.pinpow(pin,PBLEN);
+		g1.mul(g2);
+
+		FP8 c=g1.compow(z,r);
+
+		t=mpin_hash(sha,c,W);
+
+		for (int i=0;i<ECP.AESKEY;i++) CK[i]=t[i];
+
+		return 0;
+	}
+
+/* calculate common key on server side */
+/* Z=r.A - no time permits involved */
+
+	public static int SERVER_KEY(int sha,byte[] Z,byte[] SST,byte[] W,byte[] H,byte[] HID,byte[] xID,byte[] xCID,byte[] SK)
+	{
+		byte[] t;
+
+		ECP4 sQ=ECP4.fromBytes(SST);
+		if (sQ.is_infinity()) return INVALID_POINT; 
+		ECP R=ECP.fromBytes(Z);
+		if (R.is_infinity()) return INVALID_POINT; 
+		ECP A=ECP.fromBytes(HID);
+		if (A.is_infinity()) return INVALID_POINT; 
+
+		ECP U;
+		if (xCID!=null)
+			U=ECP.fromBytes(xCID);
+		else
+			U=ECP.fromBytes(xID);
+		if (U.is_infinity()) return INVALID_POINT; 
+
+		BIG w=BIG.fromBytes(W);
+		BIG h=BIG.fromBytes(H);
+		A=PAIR192.G1mul(A,h);	// new
+		R.add(A); //R.affine();
+
+		U=PAIR192.G1mul(U,w);
+		FP24 g=PAIR192.ate(sQ,R);
+		g=PAIR192.fexp(g);
+
+		FP8 c=g.trace();
+
+		t=mpin_hash(sha,c,U);
+
+		for (int i=0;i<ECP.AESKEY;i++) SK[i]=t[i];
+
+		return 0;
+	}
+
+/* Generate Y = H(epoch, xCID/xID) */
+	public static void GET_Y(int sha,int TimeValue,byte[] xCID,byte[] Y)
+	{
+		byte[] h = hashit(sha,TimeValue,xCID,EFS);
+		BIG y = BIG.fromBytes(h);
+		BIG q=new BIG(ROM.CURVE_Order);
+		y.mod(q);
+		//if (ROM.AES_S>0)
+		//{
+		//	y.mod2m(2*ROM.AES_S);
+		//}
+		y.toBytes(Y);
+	}
+        
+/* One pass MPIN Client */
+	public static int CLIENT(int sha,int date,byte[] CLIENT_ID,RAND RNG,byte[] X,int pin,byte[] TOKEN,byte[] SEC,byte[] xID,byte[] xCID,byte[] PERMIT, int TimeValue, byte[] Y)
+	{
+		int rtn=0;
+        
+		byte[] pID;
+		if (date == 0)
+			pID = xID;
+		else
+			pID = xCID;
+          
+		rtn = CLIENT_1(sha,date,CLIENT_ID,RNG,X,pin,TOKEN,SEC,xID,xCID,PERMIT);
+		if (rtn != 0)
+			return rtn;
+        
+		GET_Y(sha,TimeValue,pID,Y);
+        
+		rtn = CLIENT_2(X,Y,SEC);
+		if (rtn != 0)
+		return rtn;
+        
+		return 0;
+	}
+        
+/* One pass MPIN Server */
+	public static int SERVER(int sha,int date,byte[] HID,byte[] HTID,byte[] Y,byte[] SST,byte[] xID,byte[] xCID,byte[] SEC,byte[] E,byte[] F,byte[] CID, int TimeValue)
+	{
+		int rtn=0;
+        
+		byte[] pID;
+		if (date == 0)
+			pID = xID;
+		else
+			pID = xCID;
+          
+		SERVER_1(sha,date,CID,HID,HTID);
+        
+		GET_Y(sha,TimeValue,pID,Y);
+          
+		rtn = SERVER_2(date,HID,HTID,Y,SST,xID,xCID,SEC,E,F);
+		if (rtn != 0)
+			return rtn;
+        
+		return 0;
+	}
+}
diff --git a/version3/java/MPIN256.java b/version3/java/MPIN256.java
new file mode 100644
index 0000000..c50d1ae
--- /dev/null
+++ b/version3/java/MPIN256.java
@@ -0,0 +1,815 @@
+/*
+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.
+*/
+
+/* MPIN API Functions */
+
+package org.apache.milagro.amcl.XXX;
+
+import java.util.Date;
+
+import org.apache.milagro.amcl.RAND;
+import org.apache.milagro.amcl.HASH256;
+import org.apache.milagro.amcl.HASH384;
+import org.apache.milagro.amcl.HASH512;
+import org.apache.milagro.amcl.AES;
+
+public class MPIN256
+{
+
+//	public static final int SHA256=32;
+//	public static final int SHA384=48;
+//	public static final int SHA512=64;
+
+	public static final int EFS=BIG.MODBYTES;
+	public static final int EGS=BIG.MODBYTES;
+//	public static final int PAS=16;
+	public static final int INVALID_POINT=-14;
+	public static final int BAD_PARAMS=-11;
+	public static final int WRONG_ORDER=-18;
+	public static final int BAD_PIN=-19;
+
+/* Configure your PIN here */
+
+	public static final int MAXPIN=10000;  /* PIN less than this */
+	public static final int PBLEN=14;      /* Number of bits in PIN */
+	public static final int TS=10;         /* 10 for 4 digit PIN, 14 for 6-digit PIN - 2^TS/TS approx = sqrt(MAXPIN) */
+	public static final int TRAP=200;      /* 200 for 4 digit PIN, 2000 for 6-digit PIN  - approx 2*sqrt(MAXPIN) */
+
+//	public static final int HASH_TYPE=SHA256;
+
+
+/* Hash number (optional) and string to array size of Bigs */
+
+	public static byte[] hashit(int sha,int n,byte[] B,int len)
+	{
+		byte[] R=null;
+
+		if (sha==ECP.SHA256)
+		{
+			HASH256 H=new HASH256();
+			if (n>0) H.process_num(n);
+
+			H.process_array(B);
+			R=H.hash();
+		}
+		if (sha==ECP.SHA384)
+		{
+			HASH384 H=new HASH384();
+			if (n>0) H.process_num(n);
+			H.process_array(B);
+			R=H.hash();
+		}
+		if (sha==ECP.SHA512)
+		{
+			HASH512 H=new HASH512();
+			if (n>0) H.process_num(n);
+			H.process_array(B);
+			R=H.hash();
+		}
+		if (R==null) return null;
+		byte[] W=new byte[len];
+
+		if (sha>=len)
+			for (int i=0;i<len;i++) W[i]=R[i];
+		else
+		{
+			for (int i=0;i<sha;i++) W[i+len-sha]=R[i];
+            for (int i=0;i<len-sha;i++) W[i]=0;
+
+			//for (int i=0;i<sha;i++) W[i]=R[i];
+			//for (int i=sha;i<len;i++) W[i]=0;
+		}
+		return W;
+	}
+
+	/* return time in slots since epoch */
+	public static int today() {
+		Date date=new Date();
+		return (int) (date.getTime()/(1000*60*1440));
+	}
+
+	public static byte[] HASH_ID(int sha,byte[] ID,int len)
+	{
+		return hashit(sha,0,ID,len);
+	}
+
+/* Hash the M-Pin transcript - new */
+
+	public static byte[] HASH_ALL(int sha,byte[] HID,byte[] xID,byte[] xCID,byte[] SEC,byte[] Y,byte[] R,byte[] W,int len)
+	{
+		int i,ilen,tlen=0;
+
+		ilen=HID.length+SEC.length+Y.length+R.length+W.length;
+		if (xCID!=null) ilen+=xCID.length;
+		else ilen+=xID.length;
+
+		byte[] T = new byte[ilen];
+
+		for (i=0;i<HID.length;i++) T[i]=HID[i];
+		tlen+=HID.length;
+		if (xCID!=null)
+		{
+			for (i=0;i<xCID.length;i++) T[i+tlen]=xCID[i];
+			tlen+=xCID.length;
+		}	
+		else
+		{
+			for (i=0;i<xID.length;i++) T[i+tlen]=xID[i];
+			tlen+=xID.length;
+		}	
+		for (i=0;i<SEC.length;i++) T[i+tlen]=SEC[i];
+		tlen+=SEC.length;		
+		for (i=0;i<Y.length;i++) T[i+tlen]=Y[i];
+		tlen+=Y.length;	
+		for (i=0;i<R.length;i++) T[i+tlen]=R[i];
+		tlen+=R.length;		
+		for (i=0;i<W.length;i++) T[i+tlen]=W[i];
+		tlen+=W.length;		
+
+		return hashit(sha,0,T,len);
+	}
+
+/* return time since epoch */
+	public static int GET_TIME() {
+		Date date=new Date();
+		return (int) (date.getTime()/1000);
+	}
+
+	public static byte[] mpin_hash(int sha,FP16 c,ECP U)
+	{
+		byte[] w=new byte[EFS];
+		byte[] t=new byte[18*EFS];
+		byte[] h=null;
+		c.geta().geta().geta().getA().toBytes(w); for (int i=0;i<EFS;i++) t[i]=w[i];
+		c.geta().geta().geta().getB().toBytes(w); for (int i=EFS;i<2*EFS;i++) t[i]=w[i-EFS];
+		c.geta().geta().getb().getA().toBytes(w); for (int i=2*EFS;i<3*EFS;i++) t[i]=w[i-2*EFS];
+		c.geta().geta().getb().getB().toBytes(w); for (int i=3*EFS;i<4*EFS;i++) t[i]=w[i-3*EFS];
+		c.geta().getb().geta().getA().toBytes(w); for (int i=4*EFS;i<5*EFS;i++) t[i]=w[i-4*EFS];
+		c.geta().getb().geta().getB().toBytes(w); for (int i=5*EFS;i<6*EFS;i++) t[i]=w[i-5*EFS];
+		c.geta().getb().getb().getA().toBytes(w); for (int i=6*EFS;i<7*EFS;i++) t[i]=w[i-6*EFS];
+		c.geta().getb().getb().getB().toBytes(w); for (int i=7*EFS;i<8*EFS;i++) t[i]=w[i-7*EFS];
+
+		c.getb().geta().geta().getA().toBytes(w); for (int i=8*EFS;i<9*EFS;i++) t[i]=w[i-8*EFS];
+		c.getb().geta().geta().getB().toBytes(w); for (int i=9*EFS;i<10*EFS;i++) t[i]=w[i-9*EFS];
+		c.getb().geta().getb().getA().toBytes(w); for (int i=10*EFS;i<11*EFS;i++) t[i]=w[i-10*EFS];
+		c.getb().geta().getb().getB().toBytes(w); for (int i=11*EFS;i<12*EFS;i++) t[i]=w[i-11*EFS];
+		c.getb().getb().geta().getA().toBytes(w); for (int i=12*EFS;i<13*EFS;i++) t[i]=w[i-12*EFS];
+		c.getb().getb().geta().getB().toBytes(w); for (int i=13*EFS;i<14*EFS;i++) t[i]=w[i-13*EFS];
+		c.getb().getb().getb().getA().toBytes(w); for (int i=14*EFS;i<15*EFS;i++) t[i]=w[i-14*EFS];
+		c.getb().getb().getb().getB().toBytes(w); for (int i=15*EFS;i<16*EFS;i++) t[i]=w[i-15*EFS];
+	
+		
+
+		U.getX().toBytes(w); for (int i=16*EFS;i<17*EFS;i++) t[i]=w[i-16*EFS];
+		U.getY().toBytes(w); for (int i=17*EFS;i<18*EFS;i++) t[i]=w[i-17*EFS];
+		
+		if (sha==ECP.SHA256)
+		{
+			HASH256 H=new HASH256();
+			H.process_array(t);
+			h=H.hash();
+		}
+		if (sha==ECP.SHA384)
+		{
+			HASH384 H=new HASH384();
+			H.process_array(t);
+			h=H.hash();
+		}
+		if (sha==ECP.SHA512)
+		{
+			HASH512 H=new HASH512();
+			H.process_array(t);
+			h=H.hash();
+		}
+		if (h==null) return null;
+		byte[] R=new byte[ECP.AESKEY];
+		for (int i=0;i<ECP.AESKEY;i++) R[i]=h[i];
+		return R;
+	}
+
+/* these next two functions help to implement elligator squared - http://eprint.iacr.org/2014/043 */
+/* maps a random u to a point on the curve */
+	public static ECP map(BIG u,int cb)
+	{
+		ECP P;
+		BIG x=new BIG(u);
+		BIG p=new BIG(ROM.Modulus);
+		x.mod(p);
+		while (true)
+		{
+			P=new ECP(x,cb);
+			if (!P.is_infinity()) break;
+			x.inc(1);  x.norm();
+		}
+		return P;
+	}
+
+/* returns u derived from P. Random value in range 1 to return value should then be added to u */
+	public static int unmap(BIG u,ECP P)
+	{
+		int s=P.getS();
+		ECP R;
+		int r=0;
+		BIG x=P.getX();
+		u.copy(x);
+		while (true)
+		{
+			u.dec(1); u.norm();
+			r++;
+			R=new ECP(u,s);
+			if (!R.is_infinity()) break;
+		}
+		return r;
+	}
+
+
+
+/* these next two functions implement elligator squared - http://eprint.iacr.org/2014/043 */
+/* Elliptic curve point E in format (0x04,x,y} is converted to form {0x0-,u,v} */
+/* Note that u and v are indistinguisible from random strings */
+	public static int ENCODING(RAND rng,byte[] E)
+	{
+		int rn,m,su,sv;
+		byte[] T=new byte[EFS];
+
+		for (int i=0;i<EFS;i++) T[i]=E[i+1];
+		BIG u=BIG.fromBytes(T);
+		for (int i=0;i<EFS;i++) T[i]=E[i+EFS+1];
+		BIG v=BIG.fromBytes(T);
+		
+		ECP P=new ECP(u,v);
+		if (P.is_infinity()) return INVALID_POINT;
+
+		BIG p=new BIG(ROM.Modulus);
+		u=BIG.randomnum(p,rng);
+
+		su=rng.getByte(); /*if (su<0) su=-su;*/ su%=2;
+		
+		ECP W=map(u,su);
+		P.sub(W); //P.affine();
+		sv=P.getS();
+		rn=unmap(v,P);
+		m=rng.getByte(); /*if (m<0) m=-m;*/ m%=rn;
+		v.inc(m+1);
+		E[0]=(byte)(su+2*sv);
+		u.toBytes(T);
+		for (int i=0;i<EFS;i++) E[i+1]=T[i];
+		v.toBytes(T);
+		for (int i=0;i<EFS;i++) E[i+EFS+1]=T[i];		
+		
+		return 0;
+	}
+
+	public static int DECODING(byte[] D)
+	{
+		int su,sv;
+		byte[] T=new byte[EFS];
+
+		if ((D[0]&0x04)!=0) return INVALID_POINT;
+
+		for (int i=0;i<EFS;i++) T[i]=D[i+1];
+		BIG u=BIG.fromBytes(T);
+		for (int i=0;i<EFS;i++) T[i]=D[i+EFS+1];
+		BIG v=BIG.fromBytes(T);
+
+		su=D[0]&1;
+		sv=(D[0]>>1)&1;
+		ECP W=map(u,su);
+		ECP P=map(v,sv);
+		P.add(W); //P.affine();
+		u=P.getX();
+		v=P.getY();
+		D[0]=0x04;
+		u.toBytes(T);
+		for (int i=0;i<EFS;i++) D[i+1]=T[i];
+		v.toBytes(T);
+		for (int i=0;i<EFS;i++) D[i+EFS+1]=T[i];		
+		
+		return 0;
+	}
+
+/* R=R1+R2 in group G1 */
+	public static int RECOMBINE_G1(byte[] R1,byte[] R2,byte[] R)
+	{
+		ECP P=ECP.fromBytes(R1);
+		ECP Q=ECP.fromBytes(R2);
+
+		if (P.is_infinity() || Q.is_infinity()) return INVALID_POINT;
+
+		P.add(Q); //P.affine();
+
+		P.toBytes(R,false);
+		return 0;
+	}
+
+/* W=W1+W2 in group G2 */
+	public static int RECOMBINE_G2(byte[] W1,byte[] W2,byte[] W)
+	{
+		ECP8 P=ECP8.fromBytes(W1);
+		ECP8 Q=ECP8.fromBytes(W2);
+
+		if (P.is_infinity() || Q.is_infinity()) return INVALID_POINT;
+
+		P.add(Q); //P.affine();
+	
+		P.toBytes(W);
+		return 0;
+	}
+	
+/* create random secret S */
+	public static int RANDOM_GENERATE(RAND rng,byte[] S)
+	{
+		BIG s;
+		BIG r=new BIG(ROM.CURVE_Order);
+		s=BIG.randomnum(r,rng);
+		//if (ROM.AES_S>0)
+		//{
+		//	s.mod2m(2*ROM.AES_S);
+		//}
+		s.toBytes(S);
+		return 0;
+	}
+
+/* Extract PIN from TOKEN for identity CID */
+	public static int EXTRACT_PIN(int sha,byte[] CID,int pin,byte[] TOKEN)
+	{
+		ECP P=ECP.fromBytes(TOKEN);
+		if (P.is_infinity()) return INVALID_POINT;
+		byte[] h=hashit(sha,0,CID,EFS);
+		ECP R=ECP.mapit(h);
+
+
+		pin%=MAXPIN;
+
+		R=R.pinmul(pin,PBLEN);
+		P.sub(R); //P.affine();
+
+		P.toBytes(TOKEN,false);
+
+		return 0;
+	}
+
+/* Implement step 2 on client side of MPin protocol */
+	public static int CLIENT_2(byte[] X,byte[] Y,byte[] SEC)
+	{
+		BIG r=new BIG(ROM.CURVE_Order);
+		ECP P=ECP.fromBytes(SEC);
+		if (P.is_infinity()) return INVALID_POINT;
+
+		BIG px=BIG.fromBytes(X);
+		BIG py=BIG.fromBytes(Y);
+		px.add(py);
+		px.mod(r);
+	//	px.rsub(r);
+
+		P=PAIR256.G1mul(P,px);
+		P.neg();
+		P.toBytes(SEC,false);
+		return 0;
+	}
+
+/* Implement step 1 on client side of MPin protocol */
+	public static int CLIENT_1(int sha,int date,byte[] CLIENT_ID,RAND rng,byte[] X,int pin,byte[] TOKEN,byte[] SEC,byte[] xID,byte[] xCID,byte[] PERMIT)
+	{
+		BIG r=new BIG(ROM.CURVE_Order);
+		BIG x;
+		if (rng!=null)
+		{
+			x=BIG.randomnum(r,rng);
+			//if (ROM.AES_S>0)
+			//{
+			//	x.mod2m(2*ROM.AES_S);
+			//}
+			x.toBytes(X);
+		}
+		else
+		{
+			x=BIG.fromBytes(X);
+		}
+		ECP P,T,W;
+		BIG px;
+//		byte[] t=new byte[EFS];
+
+		byte[] h=hashit(sha,0,CLIENT_ID,EFS);
+		P=ECP.mapit(h);
+	
+		T=ECP.fromBytes(TOKEN);
+		if (T.is_infinity()) return INVALID_POINT;
+
+		pin%=MAXPIN;
+		W=P.pinmul(pin,PBLEN);
+		T.add(W);
+		if (date!=0)
+		{
+			W=ECP.fromBytes(PERMIT);
+			if (W.is_infinity()) return INVALID_POINT;
+			T.add(W);
+			h=hashit(sha,date,h,EFS);
+			W=ECP.mapit(h);
+			if (xID!=null)
+			{
+				P=PAIR256.G1mul(P,x);
+				P.toBytes(xID,false);
+				W=PAIR256.G1mul(W,x);
+				P.add(W); //P.affine();
+			}
+			else
+			{
+				P.add(W); //P.affine();
+				P=PAIR256.G1mul(P,x);
+			}
+			if (xCID!=null) P.toBytes(xCID,false);
+		}
+		else
+		{
+			if (xID!=null)
+			{
+				P=PAIR256.G1mul(P,x);
+				P.toBytes(xID,false);
+			}
+		}
+
+		//T.affine();
+		T.toBytes(SEC,false);
+		return 0;
+	}
+
+/* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */
+	public static int GET_SERVER_SECRET(byte[] S,byte[] SST)
+	{
+		ECP8 Q=ECP8.generator();
+		BIG s=BIG.fromBytes(S);
+		Q=PAIR256.G2mul(Q,s);
+		Q.toBytes(SST);
+		return 0;
+	}
+
+/*
+ W=x*H(G);
+ if RNG == NULL then X is passed in 
+ if RNG != NULL the X is passed out 
+ if type=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve
+*/
+	public static int GET_G1_MULTIPLE(RAND rng, int type,byte[] X,byte[] G,byte[] W)
+	{
+		BIG x;
+		BIG r=new BIG(ROM.CURVE_Order);
+		if (rng!=null)
+		{
+			x=BIG.randomnum(r,rng);
+			//if (ROM.AES_S>0)
+			//{
+			//	x.mod2m(2*ROM.AES_S);
+			//}
+			x.toBytes(X);
+		}
+		else
+		{
+			x=BIG.fromBytes(X);
+		}
+		ECP P;
+		if (type==0)
+		{
+			P=ECP.fromBytes(G);
+			if (P.is_infinity()) return INVALID_POINT;
+		}
+		else
+			P=ECP.mapit(G);
+
+		PAIR256.G1mul(P,x).toBytes(W,false);
+		return 0;
+	}
+
+/* Client secret CST=S*H(CID) where CID is client ID and S is master secret */
+/* CID is hashed externally */
+	public static int GET_CLIENT_SECRET(byte[] S,byte[] CID,byte[] CST)
+	{
+		return GET_G1_MULTIPLE(null,1,S,CID,CST);
+	}
+
+/* Time Permit CTT=S*(date|H(CID)) where S is master secret */
+	public static int GET_CLIENT_PERMIT(int sha,int date,byte[] S,byte[] CID,byte[] CTT)
+	{
+		byte[] h=hashit(sha,date,CID,EFS);
+		ECP P=ECP.mapit(h);
+
+		BIG s=BIG.fromBytes(S);
+		ECP OP=PAIR256.G1mul(P,s);
+
+		OP.toBytes(CTT,false);
+		return 0;
+	}
+
+/* Outputs H(CID) and H(T|H(CID)) for time permits. If no time permits set HID=HTID */
+	public static void SERVER_1(int sha,int date,byte[] CID,byte[] HID,byte[] HTID)
+	{
+		byte[] h=hashit(sha,0,CID,EFS);
+		ECP R,P=ECP.mapit(h);
+
+		P.toBytes(HID,false);   // new
+		if (date!=0)
+		{
+	//		if (HID!=null) P.toBytes(HID,false);
+			h=hashit(sha,date,h,EFS);
+			R=ECP.mapit(h);
+			P.add(R); //P.affine();
+			P.toBytes(HTID,false);
+		}
+	//	else P.toBytes(HID,false);
+	}
+
+/* Implement step 2 of MPin protocol on server side */
+	public static int SERVER_2(int date,byte[] HID,byte[] HTID,byte[] Y,byte[] SST,byte[] xID,byte[] xCID,byte[] mSEC,byte[] E,byte[] F)
+	{
+		BIG q=new BIG(ROM.Modulus);
+		ECP8 Q=ECP8.generator();
+
+		ECP8 sQ=ECP8.fromBytes(SST);
+		if (sQ.is_infinity()) return INVALID_POINT;	
+
+		ECP R;
+		if (date!=0)
+			R=ECP.fromBytes(xCID);
+		else 
+		{
+			if (xID==null) return BAD_PARAMS;
+			R=ECP.fromBytes(xID);
+		}
+		if (R.is_infinity()) return INVALID_POINT;
+
+		BIG y=BIG.fromBytes(Y);
+		ECP P;
+		if (date!=0) P=ECP.fromBytes(HTID);
+		else 
+		{
+			if (HID==null) return BAD_PARAMS;
+			P=ECP.fromBytes(HID);
+		}
+	
+		if (P.is_infinity()) return INVALID_POINT;
+
+		P=PAIR256.G1mul(P,y);
+		P.add(R); //P.affine();
+		R=ECP.fromBytes(mSEC);
+		if (R.is_infinity()) return INVALID_POINT;
+
+		FP48 g;
+
+		g=PAIR256.ate2(Q,R,sQ,P);
+		g=PAIR256.fexp(g);
+
+		if (!g.isunity())
+		{
+			if (HID!=null && xID!=null && E!=null && F!=null)
+			{
+				g.toBytes(E);
+				if (date!=0)
+				{
+					P=ECP.fromBytes(HID);
+					if (P.is_infinity()) return INVALID_POINT;
+					R=ECP.fromBytes(xID);
+					if (R.is_infinity()) return INVALID_POINT;
+
+					P=PAIR256.G1mul(P,y);
+					P.add(R); //P.affine();
+				}
+				g=PAIR256.ate(Q,P);
+				g=PAIR256.fexp(g);
+				g.toBytes(F);
+			}
+			return BAD_PIN;
+		}
+
+		return 0;
+	}
+
+/* Pollards kangaroos used to return PIN error */
+	public static int KANGAROO(byte[] E,byte[] F)
+	{
+		FP48 ge=FP48.fromBytes(E);
+		FP48 gf=FP48.fromBytes(F);
+		int[] distance = new int[TS];
+		FP48 t=new FP48(gf);
+		FP48[] table=new FP48[TS];
+		int i,j,m,s,dn,dm,res,steps;
+
+		s=1;
+		for (m=0;m<TS;m++)
+		{
+			distance[m]=s;
+			table[m]=new FP48(t);
+			s*=2;
+			t.usqr();
+		}
+		t.one();
+		dn=0;
+		for (j=0;j<TRAP;j++)
+		{
+			i=t.geta().geta().geta().geta().getA().lastbits(20)%TS;
+			t.mul(table[i]);
+			dn+=distance[i];
+		}
+		gf.copy(t); gf.conj();
+		steps=0; dm=0;
+		res=0;
+		while (dm-dn<MAXPIN)
+		{
+			steps++;
+			if (steps>4*TRAP) break;
+			i=ge.geta().geta().geta().geta().getA().lastbits(20)%TS;
+			ge.mul(table[i]);
+			dm+=distance[i];
+			if (ge.equals(t))
+			{
+				res=dm-dn;
+				break;
+			}
+			if (ge.equals(gf))
+			{
+				res=dn-dm;
+				break;
+			}
+
+		}
+		if (steps>4*TRAP || dm-dn>=MAXPIN) {res=0; }    // Trap Failed  - probable invalid token
+		return res;
+	}
+
+/* Functions to support M-Pin Full */
+
+	public static int PRECOMPUTE(byte[] TOKEN,byte[] CID,byte[] G1,byte[] G2)
+	{
+		ECP P,T;
+		FP48 g;
+
+		T=ECP.fromBytes(TOKEN);
+		if (T.is_infinity()) return INVALID_POINT; 
+
+		P=ECP.mapit(CID);
+
+		ECP8 Q=ECP8.generator();
+
+		g=PAIR256.ate(Q,T);
+		g=PAIR256.fexp(g);
+		g.toBytes(G1);
+
+		g=PAIR256.ate(Q,P);
+		g=PAIR256.fexp(g);
+		g.toBytes(G2);
+
+		return 0;
+	}
+
+
+
+/* calculate common key on client side */
+/* wCID = w.(A+AT) */
+	public static int CLIENT_KEY(int sha,byte[] G1,byte[] G2,int pin,byte[] R,byte[] X,byte[] H,byte[] wCID,byte[] CK)
+	{
+		byte[] t;
+
+		FP48 g1=FP48.fromBytes(G1);
+		FP48 g2=FP48.fromBytes(G2);
+		BIG z=BIG.fromBytes(R);
+		BIG x=BIG.fromBytes(X);
+		BIG h=BIG.fromBytes(H);
+
+		ECP W=ECP.fromBytes(wCID);
+		if (W.is_infinity()) return INVALID_POINT; 
+
+		W=PAIR256.G1mul(W,x);
+
+//		FP2 f=new FP2(new BIG(ROM.Fra),new BIG(ROM.Frb));
+		BIG r=new BIG(ROM.CURVE_Order);
+//		BIG q=new BIG(ROM.Modulus);
+
+		z.add(h);	//new
+		z.mod(r);
+
+		g2.pinpow(pin,PBLEN);
+		g1.mul(g2);
+
+		FP16 c=g1.compow(z,r);
+
+		t=mpin_hash(sha,c,W);
+
+		for (int i=0;i<ECP.AESKEY;i++) CK[i]=t[i];
+
+		return 0;
+	}
+
+/* calculate common key on server side */
+/* Z=r.A - no time permits involved */
+
+	public static int SERVER_KEY(int sha,byte[] Z,byte[] SST,byte[] W,byte[] H,byte[] HID,byte[] xID,byte[] xCID,byte[] SK)
+	{
+		byte[] t;
+
+		ECP8 sQ=ECP8.fromBytes(SST);
+		if (sQ.is_infinity()) return INVALID_POINT; 
+		ECP R=ECP.fromBytes(Z);
+		if (R.is_infinity()) return INVALID_POINT; 
+		ECP A=ECP.fromBytes(HID);
+		if (A.is_infinity()) return INVALID_POINT; 
+
+		ECP U;
+		if (xCID!=null)
+			U=ECP.fromBytes(xCID);
+		else
+			U=ECP.fromBytes(xID);
+		if (U.is_infinity()) return INVALID_POINT; 
+
+		BIG w=BIG.fromBytes(W);
+		BIG h=BIG.fromBytes(H);
+		A=PAIR256.G1mul(A,h);	// new
+		R.add(A); //R.affine();
+
+		U=PAIR256.G1mul(U,w);
+		FP48 g=PAIR256.ate(sQ,R);
+		g=PAIR256.fexp(g);
+
+		FP16 c=g.trace();
+
+		t=mpin_hash(sha,c,U);
+
+		for (int i=0;i<ECP.AESKEY;i++) SK[i]=t[i];
+
+		return 0;
+	}
+
+/* Generate Y = H(epoch, xCID/xID) */
+	public static void GET_Y(int sha,int TimeValue,byte[] xCID,byte[] Y)
+	{
+		byte[] h = hashit(sha,TimeValue,xCID,EFS);
+		BIG y = BIG.fromBytes(h);
+		BIG q=new BIG(ROM.CURVE_Order);
+		y.mod(q);
+		//if (ROM.AES_S>0)
+		//{
+		//	y.mod2m(2*ROM.AES_S);
+		//}
+		y.toBytes(Y);
+	}
+        
+/* One pass MPIN Client */
+	public static int CLIENT(int sha,int date,byte[] CLIENT_ID,RAND RNG,byte[] X,int pin,byte[] TOKEN,byte[] SEC,byte[] xID,byte[] xCID,byte[] PERMIT, int TimeValue, byte[] Y)
+	{
+		int rtn=0;
+        
+		byte[] pID;
+		if (date == 0)
+			pID = xID;
+		else
+			pID = xCID;
+          
+		rtn = CLIENT_1(sha,date,CLIENT_ID,RNG,X,pin,TOKEN,SEC,xID,xCID,PERMIT);
+		if (rtn != 0)
+			return rtn;
+        
+		GET_Y(sha,TimeValue,pID,Y);
+        
+		rtn = CLIENT_2(X,Y,SEC);
+		if (rtn != 0)
+		return rtn;
+        
+		return 0;
+	}
+        
+/* One pass MPIN Server */
+	public static int SERVER(int sha,int date,byte[] HID,byte[] HTID,byte[] Y,byte[] SST,byte[] xID,byte[] xCID,byte[] SEC,byte[] E,byte[] F,byte[] CID, int TimeValue)
+	{
+		int rtn=0;
+        
+		byte[] pID;
+		if (date == 0)
+			pID = xID;
+		else
+			pID = xCID;
+          
+		SERVER_1(sha,date,CID,HID,HTID);
+        
+		GET_Y(sha,TimeValue,pID,Y);
+          
+		rtn = SERVER_2(date,HID,HTID,Y,SST,xID,xCID,SEC,E,F);
+		if (rtn != 0)
+			return rtn;
+        
+		return 0;
+	}
+}
diff --git a/version3/java/NHS.java b/version3/java/NHS.java
new file mode 100644
index 0000000..66b764e
--- /dev/null
+++ b/version3/java/NHS.java
@@ -0,0 +1,577 @@
+/*
+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.
+*/
+
+/* NewHope API high-level functions  */
+
+//import amcl.SHA3;
+//import amcl.RAND;
+
+package org.apache.milagro.amcl;
+
+public final class NHS {
+
+	public static final int RLWE_PRIME=0x3001;	// q in Hex
+	public final static int RLWE_LGN=10;		// Degree n=2^LGN
+	public final static long RLWE_ND=0xF7002FFFL;	// 1/(R-q) mod R
+	public final static int RLWE_ONE=0x2AC8;		// R mod q
+	public final static int RLWE_R2MODP=0x1620;	// R^2 mod q
+
+	public final static int DEGREE=(1<<RLWE_LGN);
+	public final static int WL=32;
+
+	public final static int[] roots ={0x2ac8,0x2baf,0x299b,0x685,0x2f04,0x158d,0x2d49,0x24b5,0x1edc,0xab3,0x2a95,0x24d,0x3cb,0x6a8,0x12f9,0x15ba,0x1861,0x2a89,0x1c5c,0xbe6,0xc1e,0x2024,0x207,0x19ce,0x2710,0x1744,0x18bc,0x2cd7,0x396,0x18d5,0x1c45,0xc4,0x21a6,0xe03,0x2b3c,0x2d91,0xc5d,0x432,0x1fbc,0xcae,0x2512,0x2979,0x3b2,0x714,0xb2e,0x1a97,0x1a03,0x1bcd,0x2216,0x2701,0xa,0x263c,0x1179,0x200c,0x2d08,0x1c34,0x291,0x2c99,0x2a5a,0x723,0xb1d,0x1ccc,0x1fb6,0x2f58,0x2bfe,0x1cda,0x2a0,0x5f1,0x2de,0x1fc7,0x1ea8,0x1719,0x2fa7,0x27ec,0x20ff,0x12c0,0x1ac1,0x2232,0x2f9b,0xd3e,0x2aed,0x15f0,0x11e8,0xed0,0x26a,0x1de5,0xa3f,0xf43,0xebf,0x204e,0xac7,0x2d9c,0x5ea,0x25d1,0xb6,0x49c,0x995,0x2555,0x26e2,0x100,0x1878,0x5aa,0x2e10,0x271c,0xcb,0x1b4c,0x2fb8,0x25b7,0x1543,0x2c7b,0x241a,0x2223,0x20ca,0x24ed,0x137,0x1b65,0x1dc2,0x7c7,0x2ec3,0xd0c,0x1169,0x1c7a,0x1ea1,0xf89,0x2199,0x291d,0x1088,0x2046,0x256d,0x2bc7,0x2e9b,0x41f,0x1b55,0x2b38,0xd0,0x2e6a,0x1755,0x6bc,0x2724,0x3ba,0x222e,0x2c5c,0x2da5,0x213c,0x10fe,0x169a,0x1552,0x5d3,0x300,0x1b5d,0x1342,0x2004,0x256f,0x2039,0x667,0x23b5,0x1123,0xdb,0x2da0,0xe1e,0x2f54,0x2767,0x154a,0x40a,0x11d3,0x2821,0xc09,0x974,0x694,0xfbf,0x27ba,0x132,0x83f,0x2d06,0x10e,0x183f,0x29ae,0x28c3,0x2dc9,0x1144,0x2c70,0x2a4a,0xf3c,0x1e32,0x1171,0x1e43,0xdd4,0x2ddf,0x28d2,0xfac,0x3c4,0x2f19,0x10a6,0x2f7,0xe1d,0x828,0x138f,0x1332,0xfab,0xcf6,0x13f8,0x24a0,0x112d,0x2717,0x6e7,0x1044,0x36e,0xfe8,0x6a,0xba7,0x1d69,0x29ec,0x23b2,0xaee,0x16df,0x1068,0x1a7e,0x253f,0x24c,0xb33,0x2683,0x15ce,0x1ad3,0x1a36,0xc96,0xaea,0x260a,0xce,0x28b1,0xe4f,0x2b11,0x5f8,0x1fc4,0xe77,0x2366,0x11f9,0x153c,0x24eb,0x20cd,0x1398,0x22,0x2b97,0x249b,0x8eb,0x12b2,0x2fe3,0x29c1,0x1b00,0x2663,0xeaa,0x2e06,0xe0,0x1569,0x10f5,0x284e,0xa38,0x201d,0x1c53,0x1681,0x1f6f,0x2f95,0x2fe8,0xacb,0x1680,0x17fd,0x2c39,0x165a,0x10bb,0x29d8,0x2622,0x1196,0x884,0x2a79,0x140e,0x2d80,0x6fa,0x11b2,0x26c4,0x355,0x1054,0x29e9,0x23ed,0xbe3,0x24fa,0x1fb3,0x10ac,0x2919,0x2584,0x10a4,0xe85,0x650,0x1893,0x1dc1,0xd8e,0x12dc,0x2d42,0x284d,0xfff,0x250f,0xacd,0x13c3,0x6cc,0x1a79,0x1221,0x2614,0x270a,0x1ea,0x155,0x2818,0x222c,0x2e5b,0x25d8,0x1dbf,0x191c,0xb0f,0xdac,0x1082,0x12ef,0x11b6,0xfa8,0x2b72,0x159d,0x209e,0x31b,0x2c7c,0x14f7,0xe09,0x1bb2,0x1ec7,0x2404,0x20ae,0x6ad,0xed6,0x2b70,0x1c7b,0x18d1,0x2732,0x12da,0xd56,0x5c1,0x1648,0x18b7,0x1605,0x1bc4,0x280,0x2ece,0xc,0x1aae,0x1c4,0x1cdb,0x22d6,0x21d8,0x257c,0x51f,0x211b,0xff,0x2ee0,0x2585,0xe1,0x2c35,0x26db,0x2971,0x2208,0x17e1,0x21be,0x135e,0x28d6,0x2891,0x1689,0x2138,0xb86,0x2e3a,0x1204,0x2d10,0x2324,0xf3f,0x2508,0x33d,0xcb2,0x292a,0xe27,0x2e64,0x29f8,0x2d46,0x9b7,0x20eb,0x1b7c,0x9eb,0x2b2a,0x58c,0x27d0,0x121b,0x272e,0x29f6,0x2dbd,0x2697,0x2aac,0xd6f,0x1c67,0x2c5b,0x108d,0x363,0x249d,0x2d5e,0x2fd,0x2cb2,0x1f8f,0x20a4,0xa19,0x2ac9,0x19b1,0x1581,0x17a2,0x29eb,0x1b72,0x13b0,0xee4,0xa8f,0x2315,0x5e6,0x951,0x2e29,0xdad,0x1f2b,0x224e,0x37f,0x1a72,0xa91,0x1407,0x2df9,0x3ad,0x23f7,0x1a24,0x1d2a,0x234b,0x1df3,0x1143,0x7ff,0x1a6d,0x2774,0x2690,0x2ab5,0x586,0x2781,0x2009,0x2fdd,0x2881,0x399,0x2fb6,0x144,0x137f,0xfa0,0x2e4c,0x1c7f,0x2fac,0xb09,0x1264,0x127b,0x198c,0x2b40,0x230,0x1cf4,0x180b,0xb58,0x144a,0x2aec,0xfb,0x2602,0x14ee,0x783,0x1098,0x23d8,0x203,0xe9,0x108a,0x14b8,0xeec,0xc58,0x1248,0x243c,0x28aa,0x6bf,0x27c4,0x276e,0x19b8,0x1d11,0x2e16,0x472,0x1464,0x24b9,0x662,0x1097,0x2067,0x20d6,0x171c,0x4,0x682,0x17bb,0x1186,0x4f2,0x3ff,0x2a43,0x1dc7,0x1ae5,0x8cc,0x2e7c,0x2ef8,0x2ae0,0x2904,0xed4,0x6c5,0x14ae,0xb72,0x11c3,0x337,0x2da3,0x2916,0x6d8,0x1cf9,0x10ee,0x1800,0x1ae4,0xa0d,0x101b,0x1a8d,0x2e98,0x24cd,0x813,0x1aa4,0x9b9,0x680,0x2349,0x24d1,0x20f8,0xe31,0x249f,0x216b,0x12d9,0x1d21,0x19db,0x191a,0x1dd0,0x5df,0x55c,0x2b86,0x213,0xe9e,0x1ef1,0x268a,0x1d5e,0x1e20,0x28c1,0x1379,0x249,0x19de,0x18b,0x1e41,0x2a1e,0x2612,0x297,0x2e96,0x2102,0x46,0x1b9f,0x1a4d,0x2050,0x1b32,0x568,0x11f7,0x1829,0x870,0x1f4,0x1dca,0x990,0x1df6,0x2b62,0x13ec,0x9f2,0x1260,0x2997,0x1412,0x1e6d,0x1694,0x11ac,0x2d8b,0x276f,0x26f5,0x233e,0x2b44,0x2f5a,0x2d37,0x2cb1,0xc75,0x98d,0x1d56,0x7ae,0x10e6,0x113f,0x17b8,0xad3,0x737,0x221e,0x1b70,0x1f3e,0x2966,0x18b2,0x4fa,0x2044,0x1312,0x154e,0x2029,0x700,0x1b45,0x27a6,0x226a,0x21bf,0x58d,0x2f11,0x2e02,0x17fc,0x4d2,0x1757,0xcb1,0x2ef1,0x2582,0x1276,0x881,0x2fc0,0x104a,0x670,0x274f,0x2b53,0x19dd,0x752,0x1663,0xcbd,0x2b2b,0x2fc6,0x13b6,0x21e6,0x15f6,0x126b,0x2637,0x1cd9,0x2f50,0xe82,0x5b0,0x24e0,0x1350,0x2f24,0x21f7,0x1a16,0x2f3e,0x167e,0x1f7d,0x28a0,0x16f0,0xe33,0x53b,0x28c5,0x1500,0x2f88,0x26cc,0x2018,0x1604,0x218b,0x2cd1,0x9ee,0x17f3,0x5fd,0x1f5a,0x2d0,0x2b46,0x23cc,0x503,0x1c46,0x1cc3,0x28e2,0x243e,0x122b,0x2e0c,0xe37,0x2611,0x85e,0x9b8,0x1b24,0x762,0x19b6,0x3bc,0x2d50,0x2079,0x18da,0x170a,0x800,0xaa2,0x135a,0x1a15,0x13d1,0xca,0x2113,0x2db9,0xdb2,0x1a5c,0x29a9,0x1488,0x14c1,0x2c9,0x917,0x28e7,0x265c,0xdab,0x2ab9,0x2bc6,0x105b,0x1839,0x219c,0x50,0x11da,0x1802,0xf56,0x2e6,0x2190,0xddb,0x56e,0x9d9,0x1c81,0x1016,0x12d6,0x296f,0x14b4,0x1014,0x1e64,0x1d90,0x89f,0x2bc2,0x2777,0x2819,0x1c65,0x1a41,0x5a2,0x2cd2,0x427,0xd71,0x29c8,0x1e58,0x53f,0x7c5,0x1dcd,0x4a1,0x1268,0x2597,0x2926,0xee,0x111b,0x1038,0xe6c,0x22dc,0x2f2f,0x441,0x2cfd,0x1cb0,0x6a4,0x2224,0x620,0x5dc,0x16b1,0x2a1d,0x1787,0x20c7,0x641,0xd84,0x1c05,0x2d0d,0x2f52,0x1b8c,0xd7d,0x17e8,0x1589,0xc73,0x151b,0x4e2,0x1ae9,0x1b18,0xb9b,0x949,0x2c60,0x1e7a,0xd5,0x1bdc,0x1f57,0x1753,0x124a,0x559,0xb76,0x2334,0x12d1,0x1de1,0x14b2,0x2faa,0x1697,0x147a,0x5a1,0x2c30,0x1c02,0x1043,0x2ee1,0x2402,0x1cc8,0x2a16,0xff7,0x1364,0x1b9a,0x2a53,0x2f94,0x294c,0x1ee5,0x1a87,0x2141,0xd66,0x953,0x28a3,0x2f30,0x2477,0x18e3,0x1035,0x1fc1,0x1d68,0x2fb3,0x138c,0x2487,0x1bf8,0xd96,0x1018,0x748,0x244e,0x15bd,0x175e,0x2be,0x23d,0x1da,0x176d,0xc17,0x24be,0x2ebb,0x7d8,0x100a,0x759,0x1db4,0x2259,0x23f4,0x2d59,0x2847,0xbf5,0x1cfe,0xa20,0x258,0x1180,0x279c,0x54,0x2abf,0xc5c,0x9f9,0x3d5,0x2ce4,0x165f,0x23d9,0x27b9,0x6f9,0x281a,0x169e,0x627,0x156d,0x1ff8,0x211,0x2e34,0x1724,0x2c2e,0x2790,0x2dd5,0x2bf2,0xdbc,0x2884,0x20a9,0x2390,0x1e1a,0x1b6a,0x5f7,0xab7,0x1333,0x16ab,0x28dd,0x20,0x30f,0x24b6,0x5c2,0x1ce4,0x1400,0x2669,0x60,0x156c,0xe20,0x26d4,0x26ab,0x1ebb,0x223d,0x5b4,0x2025,0x1e1c,0xaae,0x2e08,0x6cd,0x1677,0x13d9,0x17b5,0x1046,0x1d8c,0x14eb,0x18d8,0x1ce5,0x2478,0x16ae,0xb79,0x23d4,0x684,0x156b,0x567,0x1a,0x29ce,0x83a,0x19e8,0x58e,0x294a,0x1136,0x2319,0x2fba,0x1a29,0x1d,0x1879,0x291b,0x19f6,0x2c2f,0x21c9,0x19bb,0xbbc,0x26f9,0xc22,0x708,0x11a1,0x18d3,0x7f8,0x28f8,0x2427,0x1deb,0xaed,0x26aa,0x2482,0x203b,0x2f05,0x2b82,0x192f,0x2df4,0x8dc,0x2877,0xd5e,0x240e,0x775,0x2dae,0x1d3e,0x20ba,0x215b,0x22d1,0xeba,0xf50,0xaa8,0x184a,0x1f67,0x2e04,0xc6e,0x6dd,0x1a09,0x27f,0x494,0x1426,0xae3,0xe15,0x65f,0x13c4,0x105,0x872,0x2667,0x1ff6,0xd9f,0x2ca1,0x2f39,0x2657,0x23fd,0x2405,0xb73,0x2294,0x1f1e,0x2eba,0x110a,0x2cae,0x141f,0x22cd,0x25d6,0x11c1,0x1c,0x2d8e,0x161a,0x1aa8,0x229e,0x1bf9,0x7cf,0x106d,0x2c40,0xd93,0x255e,0x28c2,0xc1a,0x2f17,0x7ca,0x2f63,0xbf};
+	public final static int[] iroots= {0x2ac8,0x452,0x297c,0x666,0xb4c,0x2b8,0x1a74,0xfd,0x1a47,0x1d08,0x2959,0x2c36,0x2db4,0x56c,0x254e,0x1125,0x2f3d,0x13bc,0x172c,0x2c6b,0x32a,0x1745,0x18bd,0x8f1,0x1633,0x2dfa,0xfdd,0x23e3,0x241b,0x13a5,0x578,0x17a0,0xa9,0x104b,0x1335,0x24e4,0x28de,0x5a7,0x368,0x2d70,0x13cd,0x2f9,0xff5,0x1e88,0x9c5,0x2ff7,0x900,0xdeb,0x1434,0x15fe,0x156a,0x24d3,0x28ed,0x2c4f,0x688,0xaef,0x2353,0x1045,0x2bcf,0x23a4,0x270,0x4c5,0x21fe,0xe5b,0xfbb,0x1f79,0x6e4,0xe68,0x2078,0x1160,0x1387,0x1e98,0x22f5,0x13e,0x283a,0x123f,0x149c,0x2eca,0xb14,0xf37,0xdde,0xbe7,0x386,0x1abe,0xa4a,0x49,0x14b5,0x2f36,0x8e5,0x1f1,0x2a57,0x1789,0x2f01,0x91f,0xaac,0x266c,0x2b65,0x2f4b,0xa30,0x2a17,0x265,0x253a,0xfb3,0x2142,0x20be,0x25c2,0x121c,0x2d97,0x2131,0x1e19,0x1a11,0x514,0x22c3,0x66,0xdcf,0x1540,0x1d41,0xf02,0x815,0x5a,0x18e8,0x1159,0x103a,0x2d23,0x2a10,0x2d61,0x1327,0x403,0x25c9,0x7b3,0x1f0c,0x1a98,0x2f21,0x1fb,0x2157,0x99e,0x1501,0x640,0x1e,0x1d4f,0x2716,0xb66,0x46a,0x2fdf,0x1c69,0xf34,0xb16,0x1ac5,0x1e08,0xc9b,0x218a,0x103d,0x2a09,0x4f0,0x21b2,0x750,0x2f33,0x9f7,0x2517,0x236b,0x15cb,0x152e,0x1a33,0x97e,0x24ce,0x2db5,0xac2,0x1583,0x1f99,0x1922,0x2513,0xc4f,0x615,0x1298,0x245a,0x2f97,0x2019,0x2c93,0x1fbd,0x291a,0x8ea,0x1ed4,0xb61,0x1c09,0x230b,0x2056,0x1ccf,0x1c72,0x27d9,0x21e4,0x2d0a,0x1f5b,0xe8,0x2c3d,0x2055,0x72f,0x222,0x222d,0x11be,0x1e90,0x11cf,0x20c5,0x5b7,0x391,0x1ebd,0x238,0x73e,0x653,0x17c2,0x2ef3,0x2fb,0x27c2,0x2ecf,0x847,0x2042,0x296d,0x268d,0x23f8,0x7e0,0x1e2e,0x2bf7,0x1ab7,0x89a,0xad,0x21e3,0x261,0x2f26,0x1ede,0xc4c,0x299a,0xfc8,0xa92,0xffd,0x1cbf,0x14a4,0x2d01,0x2a2e,0x1aaf,0x1967,0x1f03,0xec5,0x25c,0x3a5,0xdd3,0x2c47,0x8dd,0x2945,0x18ac,0x197,0x2f31,0x4c9,0x14ac,0x2be2,0x166,0x43a,0xa94,0x1b53,0x293c,0x212d,0x6fd,0x521,0x109,0x185,0x2735,0x151c,0x123a,0x5be,0x2c02,0x2b0f,0x1e7b,0x1846,0x297f,0x2ffd,0x18e5,0xf2b,0xf9a,0x1f6a,0x299f,0xb48,0x1b9d,0x2b8f,0x1eb,0x12f0,0x1649,0x893,0x83d,0x2942,0x757,0xbc5,0x1db9,0x23a9,0x2115,0x1b49,0x1f77,0x2f18,0x2dfe,0xc29,0x1f69,0x287e,0x1b13,0x9ff,0x2f06,0x515,0x1bb7,0x24a9,0x17f6,0x130d,0x2dd1,0x4c1,0x1675,0x1d86,0x1d9d,0x24f8,0x55,0x1382,0x1b5,0x2061,0x1c82,0x2ebd,0x4b,0x2c68,0x780,0x24,0xff8,0x880,0x2a7b,0x54c,0x971,0x88d,0x1594,0x2802,0x1ebe,0x120e,0xcb6,0x12d7,0x15dd,0xc0a,0x2c54,0x208,0x1bfa,0x2570,0x158f,0x2c82,0xdb3,0x10d6,0x2254,0x1d8,0x26b0,0x2a1b,0xcec,0x2572,0x211d,0x1c51,0x148f,0x616,0x185f,0x1a80,0x1650,0x538,0x25e8,0xf5d,0x1072,0x34f,0x2d04,0x2a3,0xb64,0x2c9e,0x1f74,0x3a6,0x139a,0x2292,0x555,0x96a,0x244,0x60b,0x8d3,0x1de6,0x831,0x2a75,0x4d7,0x2616,0x1485,0xf16,0x264a,0x2bb,0x609,0x19d,0x21da,0x6d7,0x234f,0x2cc4,0xaf9,0x20c2,0xcdd,0x2f1,0x1dfd,0x1c7,0x247b,0xec9,0x1978,0x770,0x72b,0x1ca3,0xe43,0x1820,0xdf9,0x690,0x926,0x3cc,0x2f20,0xa7c,0x121,0x2f02,0xee6,0x2ae2,0xa85,0xe29,0xd2b,0x1326,0x2e3d,0x1553,0x2ff5,0x133,0x2d81,0x143d,0x19fc,0x174a,0x19b9,0x2a40,0x22ab,0x1d27,0x8cf,0x1730,0x1386,0x491,0x212b,0x2954,0xf53,0xbfd,0x113a,0x144f,0x21f8,0x1b0a,0x385,0x2ce6,0xf63,0x1a64,0x48f,0x2059,0x1e4b,0x1d12,0x1f7f,0x2255,0x24f2,0x16e5,0x1242,0xa29,0x1a6,0xdd5,0x7e9,0x2eac,0x2e17,0x8f7,0x9ed,0x1de0,0x1588,0x2935,0x1c3e,0x2534,0xaf2,0x2002,0x7b4,0x2bf,0x1d25,0x2273,0x1240,0x176e,0x29b1,0x217c,0x1f5d,0xa7d,0x6e8,0x1f55,0x104e,0xb07,0x241e,0xc14,0x618,0x1fad,0x2cac,0x93d,0x1e4f,0x2907,0x281,0x1bf3,0x588,0x277d,0x1e6b,0x9df,0x629,0x1f46,0x19a7,0x3c8,0x1804,0x1981,0x2536,0x19,0x6c,0x1092,0x1980,0x13ae,0xfe4,0x2f42,0x9e,0x2837,0xea,0x23e7,0x73f,0xaa3,0x226e,0x3c1,0x1f94,0x2832,0x1408,0xd63,0x1559,0x19e7,0x273,0x2fe5,0x1e40,0xa2b,0xd34,0x1be2,0x353,0x1ef7,0x147,0x10e3,0xd6d,0x248e,0xbfc,0xc04,0x9aa,0xc8,0x360,0x2262,0x100b,0x99a,0x278f,0x2efc,0x1c3d,0x29a2,0x21ec,0x251e,0x1bdb,0x2b6d,0x2d82,0x15f8,0x2924,0x2393,0x1fd,0x109a,0x17b7,0x2559,0x20b1,0x2147,0xd30,0xea6,0xf47,0x12c3,0x253,0x288c,0xbf3,0x22a3,0x78a,0x2725,0x20d,0x16d2,0x47f,0xfc,0xfc6,0xb7f,0x957,0x2514,0x1216,0xbda,0x709,0x2809,0x172e,0x1e60,0x28f9,0x23df,0x908,0x2445,0x1646,0xe38,0x3d2,0x160b,0x6e6,0x1788,0x2fe4,0x15d8,0x47,0xce8,0x1ecb,0x6b7,0x2a73,0x1619,0x27c7,0x633,0x2fe7,0x2a9a,0x1a96,0x297d,0xc2d,0x2488,0x1953,0xb89,0x131c,0x1729,0x1b16,0x1275,0x1fbb,0x184c,0x1c28,0x198a,0x2934,0x1f9,0x2553,0x11e5,0xfdc,0x2a4d,0xdc4,0x1146,0x956,0x92d,0x21e1,0x1a95,0x2fa1,0x998,0x1c01,0x131d,0x2a3f,0xb4b,0x2cf2,0x2fe1,0x724,0x1956,0x1cce,0x254a,0x2a0a,0x1497,0x11e7,0xc71,0xf58,0x77d,0x2245,0x40f,0x22c,0x871,0x3d3,0x18dd,0x1cd,0x2df0,0x1009,0x1a94,0x29da,0x1963,0x7e7,0x2908,0x848,0xc28,0x19a2,0x31d,0x2c2c,0x2608,0x23a5,0x542,0x2fad,0x865,0x1e81,0x2da9,0x25e1,0x1303,0x240c,0x7ba,0x2a8,0xc0d,0xda8,0x124d,0x28a8,0x1ff7,0x2829,0x146,0xb43,0x23ea,0x1894,0x2e27,0x2dc4,0x2d43,0x18a3,0x1a44,0xbb3,0x28b9,0x1fe9,0x226b,0x1409,0xb7a,0x1c75,0x4e,0x1299,0x1040,0x1fcc,0x171e,0xb8a,0xd1,0x75e,0x26ae,0x229b,0xec0,0x157a,0x111c,0x6b5,0x6d,0x5ae,0x1467,0x1c9d,0x200a,0x5eb,0x1339,0xbff,0x120,0x1fbe,0x13ff,0x3d1,0x2a60,0x1b87,0x196a,0x57,0x1b4f,0x1220,0x1d30,0xccd,0x248b,0x2aa8,0x1db7,0x18ae,0x10aa,0x1425,0x2f2c,0x1187,0x3a1,0x26b8,0x2466,0x14e9,0x1518,0x2b1f,0x1ae6,0x238e,0x1a78,0x1819,0x2284,0x1475,0xaf,0x2f4,0x13fc,0x227d,0x29c0,0xf3a,0x187a,0x5e4,0x1950,0x2a25,0x29e1,0xddd,0x295d,0x1351,0x304,0x2bc0,0xd2,0xd25,0x2195,0x1fc9,0x1ee6,0x2f13,0x6db,0xa6a,0x1d99,0x2b60,0x1234,0x283c,0x2ac2,0x11a9,0x639,0x2290,0x2bda,0x32f,0x2a5f,0x15c0,0x139c,0x7e8,0x88a,0x43f,0x2762,0x1271,0x119d,0x1fed,0x1b4d,0x692,0x1d2b,0x1feb,0x1380,0x2628,0x2a93,0x2226,0xe71,0x2d1b,0x20ab,0x17ff,0x1e27,0x2fb1,0xe65,0x17c8,0x1fa6,0x43b,0x548,0x2256,0x9a5,0x71a,0x26ea,0x2d38,0x1b40,0x1b79,0x658,0x15a5,0x224f,0x248,0xeee,0x2f37,0x1c30,0x15ec,0x1ca7,0x255f,0x2801,0x18f7,0x1727,0xf88,0x2b1,0x2c45,0x164b,0x289f,0x14dd,0x2649,0x27a3,0x9f0,0x21ca,0x1f5,0x1dd6,0xbc3,0x71f,0x133e,0x13bb,0x2afe,0xc35,0x4bb,0x2d31,0x10a7,0x2a04,0x180e,0x2613,0x330,0xe76,0x19fd,0xfe9,0x935,0x79,0x1b01,0x73c,0x2ac6,0x21ce,0x1911,0x761,0x1084,0x1983,0xc3,0x15eb,0xe0a,0xdd,0x1cb1,0xb21,0x2a51,0x217f,0xb1,0x1328,0x9ca,0x1d96,0x1a0b,0xe1b,0x1c4b,0x3b,0x4d6,0x2344,0x199e,0x28af,0x1624,0x4ae,0x8b2,0x2991,0x1fb7,0x41,0x2780,0x1d8b,0xa7f,0x110,0x2350,0x18aa,0x2b2f,0x1805,0x1ff,0xf0,0x2a74,0xe42,0xd97,0x85b,0x14bc,0x2901,0xfd8,0x1ab3,0x1cef,0xfbd,0x2b07,0x174f,0x69b,0x10c3,0x1491,0xde3,0x28ca,0x252e,0x1849,0x1ec2,0x1f1b,0x2853,0x12ab,0x2674,0x238c,0x350,0x2ca,0xa7,0x4bd,0xcc3,0x90c,0x892,0x276,0x1e55,0x196d,0x1194,0x1bef,0x66a,0x1da1,0x260f,0x1c15,0x49f,0x120b,0x2671,0x1237,0x2e0d,0x2791,0x17d8,0x1e0a,0x2a99,0x14cf,0xfb1,0x15b4,0x1462,0x2fbb,0xeff,0x16b,0x2d6a,0x9ef,0x5e3,0x11c0,0x2e76,0x1623,0x2db8,0x1c88,0x740,0x11e1,0x12a3,0x977,0x1110,0x2163,0x2dee,0x47b,0x2aa5,0x2a22,0x1231,0x16e7,0x1626,0x12e0,0x1d28,0xe96,0xb62,0x21d0,0xf09,0xb30,0xcb8,0x2981,0x2648,0x155d,0x27ee,0xb34,0x169,0x1574,0x1fe6,0x25f4,0x151d,0x1801,0x1f13,0x1308,0x2929,0x6eb,0x25e,0x2cca,0x1e3e,0x248f};
+	public final static int inv= 0xeab;
+	public final static int invpr= 0x2c2a;
+
+	static int round(int a,int b)
+	{
+		return (a+b/2)/b;
+	}
+	
+/* constant time absolute vaue */
+	static int nabs(int x)
+	{
+		int mask=(x>>31);
+		return (x+mask)^mask;
+	}
+
+/* Montgomery stuff */
+
+	static int redc(long T)
+	{
+		long m=(T*RLWE_ND)&0xffffffffL;
+		return (int)((m*RLWE_PRIME+T)>>>WL);
+	}
+
+	static int nres(int x)
+	{
+		return redc((long)x*RLWE_R2MODP);
+	}
+
+	static int modmul(int a,int b)
+	{
+		return redc((long)a*b);
+	}
+
+/* NTT code */
+/* Cooley-Tukey NTT */
+
+	static void ntt(int[] x)
+	{
+		int m,i,j,k,t=DEGREE/2;
+		int S,U,V,W,q=RLWE_PRIME;
+
+/* Convert to Montgomery form */
+		for (j=0;j<DEGREE;j++)
+			x[j]=nres(x[j]);
+
+		m=1;
+		while (m<DEGREE)
+		{
+			k=0;
+			for (i=0;i<m;i++)
+			{
+				S=roots[m+i];
+				for (j=k;j<k+t;j++)
+				{
+					U=x[j];   
+					V=modmul(x[j+t],S);
+					x[j]=U+V;
+					x[j+t]=U+2*q-V;
+				}
+				k+=2*t;
+			}
+			t/=2;
+			m*=2;
+		}
+	}
+
+/* Gentleman-Sande INTT */
+
+	static void intt(int[] x)
+	{
+		int m,i,j,k,t=1;
+		int S,U,V,W,q=RLWE_PRIME;
+
+		m=DEGREE/2;
+		while (m>1)
+		{
+			k=0;
+			for (i=0;i<m;i++)
+			{
+				S=iroots[m+i];
+				for (j=k;j<k+t;j++)
+				{	
+					U=x[j]; 
+					V=x[j+t];
+					x[j]=U+V;	
+					W=U+DEGREE*q-V; 
+					x[j+t]=modmul(W,S); 
+				}
+				k+=2*t;
+			}
+			t*=2;
+			m/=2;
+		}
+
+/* Last iteration merged with n^-1 */
+
+		t=DEGREE/2;
+		for (j=0;j<t;j++)
+		{
+			U=x[j];
+			V=x[j+t];
+			W=U+DEGREE*q-V; 
+			x[j+t]=modmul(W,invpr); 
+			x[j]=modmul(U+V,inv);
+		}
+/* convert back from Montgomery to "normal" form */
+		for (j=0;j<DEGREE;j++)
+		{
+			x[j]=redc(x[j]);  
+			x[j]-=q;
+			x[j]+=(x[j]>>(WL-1))&q;
+		} 
+	}
+
+/* See https://eprint.iacr.org/2016/1157.pdf */ 
+
+	static void Encode(byte[] key,int[] poly)
+	{
+		int i,j,b,k,kj,q2;
+
+		q2=RLWE_PRIME/2;
+		for (i=j=0;i<256;)
+		{
+			kj=key[j++];
+			for (k=0;k<8;k++)
+			{
+				b=kj&1;
+				poly[i]=b*q2;
+				poly[i+256]=b*q2;
+				poly[i+512]=b*q2;
+				poly[i+768]=b*q2;
+				kj>>=1;
+				i++;
+			}
+		}		
+	}
+
+	static void Decode(int[] poly,byte[] key)
+	{
+		int i,j,k;
+		int b,t,q2;
+		q2=RLWE_PRIME/2;
+		for (i=0;i<32;i++)
+			key[i]=0;
+
+		for (i=j=0;i<256;)
+		{
+			for (k=0;k<8;k++)
+			{
+				t=nabs(poly[i]-q2)+nabs(poly[i+256]-q2)+nabs(poly[i+512]-q2)+nabs(poly[i+768]-q2);
+
+				b=t-RLWE_PRIME;
+				b=(b>>31)&1;
+				key[j]=(byte)((((int)key[j]&0xff)>>1) + (b<<7));
+				i++;
+			}
+			j++;
+		}
+	}
+
+/* convert 32-byte seed to random polynomial */
+
+	static void Parse(byte[] seed,int[] poly)
+	{
+		int i,j;
+		int n;
+		byte[] hash=new byte[4*DEGREE];
+		SHA3 sh=new SHA3(SHA3.SHAKE128);
+
+		for (i=0;i<32;i++)
+			sh.process(seed[i]);
+		sh.shake(hash,4*DEGREE);
+
+		for (i=j=0;i<DEGREE;i++)
+		{
+			n=(int)hash[j]&0x7f; n<<=8;
+			n+=(int)hash[j+1]&0xff; n<<=8;
+			n+=(int)hash[j+2]&0xff; n<<=8;
+			n+=(int)hash[j+3]&0xff; j+=4;
+			poly[i]=nres(n);
+			//poly[i]=modmul(n,RLWE_ONE); // reduce 31-bit random number mod q
+		}
+	} 
+
+/* Compress 14 bits polynomial coefficients into byte array */
+/* 7 bytes is 3x14 */
+	static void pack(int[] poly,byte[] array)
+	{
+		int i,j,k;
+		int a,b,c,d;
+
+		for (i=j=0;i<DEGREE; )
+		{
+			a=poly[i++]; b=poly[i++]; c=poly[i++]; d=poly[i++];
+			array[j++]=(byte)(a&0xff);
+			array[j++]=(byte)(((a>>8)|(b<<6))&0xff);
+			array[j++]=(byte)((b>>2)&0xff);
+			array[j++]=(byte)(((b>>10)|(c<<4))&0xff);
+			array[j++]=(byte)((c>>4)&0xff);
+			array[j++]=(byte)(((c>>12)|(d<<2))&0xff);
+			array[j++]=(byte)(d>>6);
+		}
+	}
+
+	static void unpack(byte[] array,int[] poly)
+	{
+		int i,j,k;
+		int a,b,c,d,e,f,g;
+
+		for (i=j=0;i<DEGREE; )
+		{
+			a=((int)array[j++])&0xff; b=((int)array[j++])&0xff; c=((int)array[j++])&0xff; d=((int)array[j++])&0xff; e=((int)array[j++])&0xff; f=((int)array[j++])&0xff; g=((int)array[j++])&0xff;
+			poly[i++]=a|((b&0x3f)<<8);
+			poly[i++]=(b>>6)|(c<<2)|((d&0xf)<<10);
+			poly[i++]=(d>>4)|(e<<4)|((f&3)<<12);
+			poly[i++]=(f>>2)|(g<<6);
+		}
+	}
+
+
+/* See https://eprint.iacr.org/2016/1157.pdf */ 
+
+	static void Compress(int[] poly,byte[] array)
+	{
+		int i,j,k,b;
+		int col=0;
+
+		for (i=j=0;i<DEGREE;)
+		{
+			for (k=0;k<8;k++)
+			{
+				b=round((poly[i]*8),RLWE_PRIME)&7; 
+				col=(col<<3)+b;
+				i++;
+			}
+			array[j]=(byte)(col&0xff);
+			array[j+1]=(byte)((col>>>8)&0xff);
+			array[j+2]=(byte)((col>>>16)&0xff);
+			j+=3; col=0;
+		}
+	}
+
+	static void Decompress(byte[] array,int[] poly)
+	{
+		int i,j,k,b;
+		int col=0;
+
+		for (i=j=0;i<DEGREE;)
+		{
+			col=(int)array[j+2]&0xff;
+			col=(col<<8)+((int)array[j+1]&0xff);
+			col=(col<<8)+((int)array[j]&0xff);
+			j+=3;
+			for (k=0;k<8;k++)
+			{
+				b=(col&0xe00000)>>>21; col<<=3;
+				poly[i]=round((b*RLWE_PRIME),8);
+				i++;
+			}
+		}
+	}
+
+/* generate centered binomial distribution */ 
+
+	static void Error(RAND RNG,int[] poly)
+	{
+		int i,j;
+		int n1,n2,r;
+		for (i=0;i<DEGREE;i++)
+		{
+			n1=RNG.getByte()+(RNG.getByte()<<8);
+			n2=RNG.getByte()+(RNG.getByte()<<8);
+			r=0;
+			for (j=0;j<16;j++)
+			{
+				r+=(n1&1)-(n2&1);
+				n1>>=1; n2>>=1;
+			}
+			poly[i]=(r+RLWE_PRIME);
+		}
+	}
+
+	static void redc_it(int[] p)
+	{
+		int i;
+		for (i=0;i<DEGREE;i++)
+			p[i]=redc(p[i]);
+	}
+
+	static void nres_it(int[] p)
+	{
+		int i;
+		for (i=0;i<DEGREE;i++)
+			p[i]=nres(p[i]);
+	}
+
+	static void poly_mul(int[] p1,int[] p2,int[] p3)
+	{
+		int i;
+		for (i=0;i<DEGREE;i++)
+			p1[i]=modmul(p2[i],p3[i]);
+	}
+
+	static void poly_add(int[] p1,int[] p2,int[] p3)
+	{
+		int i;
+		for (i=0;i<DEGREE;i++)
+			p1[i]=(p2[i]+p3[i]);
+	}
+
+	static void poly_sub(int[] p1,int[] p2,int[] p3)
+	{
+		int i;
+		for (i=0;i<DEGREE;i++)
+			p1[i]=(p2[i]+RLWE_PRIME-p3[i]);
+	}	
+
+/* reduces inputs < 2q */
+	static void poly_soft_reduce(int[] poly)
+	{
+		int i;
+		int e;
+		for (i=0;i<DEGREE;i++)
+		{
+			e=poly[i]-RLWE_PRIME;
+			poly[i]=e+((e>>(WL-1))&RLWE_PRIME);
+		}
+	}
+
+/* fully reduces modulo q */
+	static void poly_hard_reduce(int[] poly)
+	{
+		int i;
+		int e;
+		for (i=0;i<DEGREE;i++)
+		{
+			e=modmul(poly[i],RLWE_ONE);
+			e=e-RLWE_PRIME;
+			poly[i]=e+((e>>(WL-1))&RLWE_PRIME);
+		}
+	}
+
+/* API files */
+
+	public static void SERVER_1(RAND RNG,byte[] SB,byte[] S)
+	{
+		int i;
+		byte[] seed=new byte[32];
+		byte[] array=new byte[1792];
+
+		int[] s=new int[DEGREE];
+		int[] e=new int[DEGREE];
+		int[] b=new int[DEGREE];
+
+		for (i=0;i<32;i++)
+			seed[i]=(byte)RNG.getByte();
+
+		Parse(seed,b);
+
+		Error(RNG,e);
+		Error(RNG,s);
+
+		ntt(s);
+		ntt(e);
+		poly_mul(b,b,s);
+		poly_add(b,b,e);
+		poly_hard_reduce(b);
+
+		redc_it(b);
+		pack(b,array);
+		
+		for (i=0;i<32;i++)
+			SB[i]=seed[i];
+		for (i=0;i<1792;i++)
+			SB[i+32]=array[i];
+
+		poly_hard_reduce(s);
+
+		pack(s,array);
+
+		for (i=0;i<1792;i++)
+			S[i]=array[i];
+
+	}
+
+	public static void CLIENT(RAND RNG,byte[] SB,byte[] UC,byte[] KEY)
+	{
+		int i;
+		SHA3 sh=new SHA3(SHA3.HASH256);
+
+		byte[] seed=new byte[32];
+		byte[] array=new byte[1792];
+		byte[] key=new byte[32];
+		byte[] cc=new byte[384];
+
+		int[] sd=new int[DEGREE];
+		int[] ed=new int[DEGREE];
+		int[] u=new int[DEGREE];
+		int[] k=new int[DEGREE];
+		int[] c=new int[DEGREE];
+		
+		Error(RNG,sd);
+		Error(RNG,ed);
+
+		ntt(sd);
+		ntt(ed);
+
+		for (i=0;i<32;i++)
+			seed[i]=SB[i];
+
+		for (i=0;i<1792;i++)
+			array[i]=SB[i+32];
+
+		Parse(seed,u);
+
+		poly_mul(u,u,sd);
+		poly_add(u,u,ed);
+		poly_hard_reduce(u);
+
+		for (i=0;i<32;i++)
+			key[i]=(byte)RNG.getByte();
+
+		for (i=0;i<32;i++)
+			sh.process(key[i]);
+		sh.hash(key);
+
+		Encode(key,k);
+
+		unpack(array,c);
+		nres_it(c);
+
+		poly_mul(c,c,sd);
+		intt(c);
+		Error(RNG,ed);
+		poly_add(c,c,ed);
+		poly_add(c,c,k);
+
+		Compress(c,cc);
+
+		sh.init(SHA3.HASH256);
+		for (i=0;i<32;i++)
+			sh.process(key[i]);
+		sh.hash(key);
+
+		for (i=0;i<32;i++)
+			KEY[i]=key[i];
+
+		redc_it(u);
+		pack(u,array);
+
+		for (i=0;i<1792;i++)
+			UC[i]=array[i];
+		for (i=0;i<384;i++)
+			UC[i+1792]=cc[i];
+
+	}
+
+	public static void SERVER_2(byte[] S,byte[] UC,byte[] KEY)
+	{
+		int i;
+		SHA3 sh=new SHA3(SHA3.HASH256);
+
+		int[] c=new int[DEGREE];
+		int[] s=new int[DEGREE];
+		int[] k=new int[DEGREE];
+
+		byte[] array=new byte[1792];
+		byte[] key=new byte[32];
+		byte[] cc=new byte[384];
+
+		for (i=0;i<1792;i++)
+			array[i]=UC[i];
+
+		unpack(array,k);
+		nres_it(k);
+
+		for (i=0;i<384;i++)
+			cc[i]=UC[i+1792];
+
+		Decompress(cc,c);
+
+		for (i=0;i<1792;i++)
+			array[i]=S[i];
+
+		unpack(array,s);
+
+		poly_mul(k,k,s);
+		intt(k);
+		poly_sub(k,c,k);
+		poly_soft_reduce(k);
+
+		Decode(k,key);
+
+		for (i=0;i<32;i++)
+			sh.process(key[i]);
+		sh.hash(key);
+
+		for (i=0;i<32;i++)
+			KEY[i]=key[i];
+	}
+/*
+	public static void main(String[] args) {
+		int i;
+		byte[] RAW=new byte[100];
+		byte[] S=new byte[1792];
+		byte[] SB=new byte[1824];
+		byte[] UC=new byte[2176];
+		byte[] KEYA=new byte[32];
+		byte[] KEYB=new byte[32];
+
+		RAND SRNG=new RAND();
+		RAND CRNG=new RAND();
+		SRNG.clean(); CRNG.clean();
+
+		for (i=0;i<100;i++) RAW[i]=(byte)(i+1);
+		SRNG.seed(100,RAW);
+
+										for (i=0;i<100;i++) RAW[i]=(byte)(i+2);
+										CRNG.seed(100,RAW);
+
+// NewHope Simple key exchange
+
+		SERVER_1(SRNG,SB,S);
+										CLIENT(CRNG,SB,UC,KEYB);
+		SERVER_2(S,UC,KEYA);
+
+		System.out.printf("Alice key= 0x");
+		for (i=0;i<KEYA.length;i++)
+			System.out.printf("%02x", KEYA[i]);
+		System.out.println();
+
+
+										System.out.printf("Bob's key= 0x");
+										for (i=0;i<KEYA.length;i++)
+											System.out.printf("%02x", KEYB[i]);
+										System.out.println();
+	} */
+}
\ No newline at end of file
diff --git a/version3/java/OLDECP.java b/version3/java/OLDECP.java
new file mode 100644
index 0000000..6d5bb2e
--- /dev/null
+++ b/version3/java/OLDECP.java
@@ -0,0 +1,1044 @@
+/*
+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.
+*/
+
+/* Elliptic Curve Point class */
+
+package org.apache.milagro.amcl.XXX;
+
+public final class ECP {
+
+	public static final int WEIERSTRASS=0;
+	public static final int EDWARDS=1;
+	public static final int MONTGOMERY=2;
+	public static final int NOT=0;
+	public static final int BN=1;
+	public static final int BLS=2;
+	public static final int D_TYPE=0;
+	public static final int M_TYPE=1;
+	public static final int POSITIVEX=0;
+	public static final int NEGATIVEX=1;
+
+	public static final int CURVETYPE=@CT@;
+	public static final int CURVE_PAIRING_TYPE=@PF@;
+	public static final int SEXTIC_TWIST=@ST@;
+	public static final int SIGN_OF_X=@SX@;
+
+	public static final int SHA256=32;
+	public static final int SHA384=48;
+	public static final int SHA512=64;
+
+	public static final int HASH_TYPE=@HT@;
+	public static final int AESKEY=@AK@;
+
+	private FP x;
+	private FP y;
+	private FP z;
+	private boolean INF;
+
+/* Constructor - set to O */
+	public ECP() {
+		INF=true;
+		x=new FP(0);
+		y=new FP(1);
+		z=new FP(0);
+	}
+/* test for O point-at-infinity */
+	public boolean is_infinity() {
+		if (INF) return true;                            // Edits made
+		if (CURVETYPE==EDWARDS)
+		{
+			return (x.iszilch() && y.equals(z));
+		}
+		if (CURVETYPE==WEIERSTRASS)
+		{
+			return (x.iszilch() && z.iszilch());
+		}
+		if (CURVETYPE==MONTGOMERY)
+		{
+			return z.iszilch();
+		}
+		return true;
+	}
+/* Conditional swap of P and Q dependant on d */
+	private void cswap(ECP Q,int d)
+	{
+		x.cswap(Q.x,d);
+		if (CURVETYPE!=MONTGOMERY) y.cswap(Q.y,d);
+		z.cswap(Q.z,d);
+	//	if (CURVETYPE!=EDWARDS)
+	//	{
+			boolean bd;
+			if (d==0) bd=false;
+			else bd=true;
+			bd=bd&(INF^Q.INF);
+			INF^=bd;
+			Q.INF^=bd;
+	//	}
+	}
+
+/* Conditional move of Q to P dependant on d */
+	private void cmove(ECP Q,int d)
+	{
+		x.cmove(Q.x,d);
+		if (CURVETYPE!=MONTGOMERY) y.cmove(Q.y,d);
+		z.cmove(Q.z,d);
+	//	if (CURVETYPE!=EDWARDS)
+	//	{
+			boolean bd;
+			if (d==0) bd=false;
+			else bd=true;
+			INF^=(INF^Q.INF)&bd;
+	//	}
+	}
+
+/* return 1 if b==c, no branching */
+	private static int teq(int b,int c)
+	{
+		int x=b^c;
+		x-=1;  // if x=0, x now -1
+		return ((x>>31)&1);
+	}
+
+/* Constant time select from pre-computed table */
+	private void select(ECP W[],int b)
+	{
+		ECP MP=new ECP(); 
+		int m=b>>31;
+		int babs=(b^m)-m;
+
+		babs=(babs-1)/2;
+		cmove(W[0],teq(babs,0));  // conditional move
+		cmove(W[1],teq(babs,1));
+		cmove(W[2],teq(babs,2));
+		cmove(W[3],teq(babs,3));
+		cmove(W[4],teq(babs,4));
+		cmove(W[5],teq(babs,5));
+		cmove(W[6],teq(babs,6));
+		cmove(W[7],teq(babs,7));
+ 
+		MP.copy(this);
+		MP.neg();
+		cmove(MP,(int)(m&1));
+	}
+
+/* Test P == Q */
+	public boolean equals(ECP Q) {
+		if (is_infinity() && Q.is_infinity()) return true;
+		if (is_infinity() || Q.is_infinity()) return false;
+
+		FP a=new FP(0);                                        // Edits made
+		FP b=new FP(0);
+		a.copy(x); a.mul(Q.z); 
+		b.copy(Q.x); b.mul(z); 
+		if (!a.equals(b)) return false;
+		if (CURVETYPE!=MONTGOMERY)
+		{
+			a.copy(y); a.mul(Q.z); 
+			b.copy(Q.y); b.mul(z); 
+			if (!a.equals(b)) return false;
+		}
+		return true;
+	}
+
+/* this=P */
+	public void copy(ECP P)
+	{
+		x.copy(P.x);
+		if (CURVETYPE!=MONTGOMERY) y.copy(P.y);
+		z.copy(P.z);
+		INF=P.INF;
+	}
+/* this=-this */
+	public void neg() {
+//		if (is_infinity()) return;
+		if (CURVETYPE==WEIERSTRASS)
+		{
+			y.neg(); y.norm();
+		}
+		if (CURVETYPE==EDWARDS)
+		{
+			x.neg(); x.norm();
+		}
+		return;
+	}
+/* set this=O */
+	public void inf() {
+		INF=true;
+		x.zero();
+		if (CURVETYPE!=MONTGOMERY) y.one();
+		if (CURVETYPE!=EDWARDS) z.zero();
+		else z.one();
+	}
+
+/* Calculate RHS of curve equation */
+	public static FP RHS(FP x) {
+		x.norm();
+		FP r=new FP(x);
+		r.sqr();
+
+		if (CURVETYPE==WEIERSTRASS)
+		{ // x^3+Ax+B
+			FP b=new FP(new BIG(ROM.CURVE_B));
+			r.mul(x);
+			if (ROM.CURVE_A==-3)
+			{
+				FP cx=new FP(x);
+				cx.imul(3);
+				cx.neg(); cx.norm();
+				r.add(cx);
+			}
+			r.add(b);
+		}
+		if (CURVETYPE==EDWARDS)
+		{ // (Ax^2-1)/(Bx^2-1) 
+			FP b=new FP(new BIG(ROM.CURVE_B));
+
+			FP one=new FP(1);
+			b.mul(r);
+			b.sub(one);
+			b.norm();
+			if (ROM.CURVE_A==-1) r.neg();
+			r.sub(one); r.norm();
+			b.inverse();
+
+			r.mul(b);
+		}
+		if (CURVETYPE==MONTGOMERY)
+		{ // x^3+Ax^2+x
+			FP x3=new FP(0);
+			x3.copy(r);
+			x3.mul(x);
+			r.imul(ROM.CURVE_A);
+			r.add(x3);
+			r.add(x);
+		}
+		r.reduce();
+		return r;
+	}
+
+/* set (x,y) from two BIGs */
+	public ECP(BIG ix,BIG iy) {
+		x=new FP(ix);
+		y=new FP(iy);
+		z=new FP(1);
+		FP rhs=RHS(x);
+
+		if (CURVETYPE==MONTGOMERY)
+		{
+			if (rhs.jacobi()==1) INF=false;
+			else inf();
+		}
+		else
+		{
+			FP y2=new FP(y);
+			y2.sqr();
+			if (y2.equals(rhs)) INF=false;
+			else inf();
+		}
+	}
+/* set (x,y) from BIG and a bit */
+	public ECP(BIG ix,int s) {
+		x=new FP(ix);
+		FP rhs=RHS(x);
+		y=new FP(0);
+		z=new FP(1);
+		if (rhs.jacobi()==1)
+		{
+			FP ny=rhs.sqrt();
+			if (ny.redc().parity()!=s) ny.neg();
+			y.copy(ny);
+			INF=false;
+		}
+		else inf();
+	}
+
+/* set from x - calculate y from curve equation */
+	public ECP(BIG ix) {
+		x=new FP(ix);
+		FP rhs=RHS(x);
+		y=new FP(0);
+		z=new FP(1);
+		if (rhs.jacobi()==1)
+		{
+			if (CURVETYPE!=MONTGOMERY) y.copy(rhs.sqrt());
+			INF=false;
+		}
+		else INF=true;
+	}
+
+/* set to affine - from (x,y,z) to (x,y) */
+	public void affine() {
+		if (is_infinity()) return;
+		FP one=new FP(1);
+		if (z.equals(one)) return;
+		z.inverse();
+		x.mul(z); x.reduce();
+		if (CURVETYPE!=MONTGOMERY)            // Edits made
+		{
+			y.mul(z); y.reduce();
+		}
+		z.copy(one);
+	}
+/* extract x as a BIG */
+	public BIG getX()
+	{
+		affine();
+		return x.redc();
+	}
+/* extract y as a BIG */
+	public BIG getY()
+	{
+		affine();
+		return y.redc();
+	}
+
+/* get sign of Y */
+	public int getS()
+	{
+		affine();
+		BIG y=getY();
+		return y.parity();
+	}
+/* extract x as an FP */
+	public FP getx()
+	{
+		return x;
+	}
+/* extract y as an FP */
+	public FP gety()
+	{
+		return y;
+	}
+/* extract z as an FP */
+	public FP getz()
+	{
+		return z;
+	}
+/* convert to byte array */
+	public void toBytes(byte[] b)
+	{
+		byte[] t=new byte[BIG.MODBYTES];
+		if (CURVETYPE!=MONTGOMERY) b[0]=0x04;
+		else b[0]=0x02;
+	
+		affine();
+		x.redc().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) b[i+1]=t[i];
+		if (CURVETYPE!=MONTGOMERY)
+		{
+			y.redc().toBytes(t);
+			for (int i=0;i<BIG.MODBYTES;i++) b[i+BIG.MODBYTES+1]=t[i];
+		}
+	}
+/* convert from byte array to point */
+	public static ECP fromBytes(byte[] b)
+	{
+		byte[] t=new byte[BIG.MODBYTES];
+		BIG p=new BIG(ROM.Modulus);
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=b[i+1];
+		BIG px=BIG.fromBytes(t);
+		if (BIG.comp(px,p)>=0) return new ECP();
+
+		if (b[0]==0x04)
+		{
+			for (int i=0;i<BIG.MODBYTES;i++) t[i]=b[i+BIG.MODBYTES+1];
+			BIG py=BIG.fromBytes(t);
+			if (BIG.comp(py,p)>=0) return new ECP();
+			return new ECP(px,py);
+		}
+		else return new ECP(px);
+	}
+/* convert to hex string */
+	public String toString() {
+		if (is_infinity()) return "infinity";
+		affine();
+		if (CURVETYPE==MONTGOMERY) return "("+x.redc().toString()+")";
+		else return "("+x.redc().toString()+","+y.redc().toString()+")";
+	}
+
+/* convert to hex string */
+	public String toRawString() {
+		//if (is_infinity()) return "infinity";
+		//affine();
+		if (CURVETYPE==MONTGOMERY) return "("+x.redc().toString()+","+z.redc().toString()+")";
+		else return "("+x.redc().toString()+","+y.redc().toString()+","+z.redc().toString()+")";
+	}
+
+/* this*=2 */
+	public void dbl() {
+		if (INF) return;
+		
+		if (CURVETYPE==WEIERSTRASS)
+		{
+			if (ROM.CURVE_A==0)
+			{
+//System.out.println("Into dbl");
+				FP t0=new FP(y);                      /*** Change ***/    // Edits made
+				t0.sqr();
+				FP t1=new FP(y);
+				t1.mul(z);
+				FP t2=new FP(z);
+				t2.sqr();
+
+				z.copy(t0);
+				z.add(t0); z.norm(); 
+				z.add(z); z.add(z); z.norm();
+				t2.imul(3*ROM.CURVE_B_I);
+
+				FP x3=new FP(t2);
+				x3.mul(z);
+
+				FP y3=new FP(t0);
+				y3.add(t2); y3.norm();
+				z.mul(t1); 
+				t1.copy(t2); t1.add(t2); t2.add(t1);
+				t0.sub(t2); t0.norm(); y3.mul(t0); y3.add(x3);
+				t1.copy(x); t1.mul(y); 
+				x.copy(t0); x.norm(); x.mul(t1); x.add(x);
+				x.norm(); 
+				y.copy(y3); y.norm();
+//System.out.println("Out of dbl");
+			}
+			else
+			{
+				FP t0=new FP(x);
+				FP t1=new FP(y);
+				FP t2=new FP(z);
+				FP t3=new FP(x);
+				FP z3=new FP(z);
+				FP y3=new FP(0);
+				FP x3=new FP(0);
+				FP b=new FP(0);
+
+				if (ROM.CURVE_B_I==0)
+					b.copy(new FP(new BIG(ROM.CURVE_B)));
+
+				t0.sqr();  //1    x^2
+				t1.sqr();  //2    y^2
+				t2.sqr();  //3
+
+				t3.mul(y); //4
+				t3.add(t3); t3.norm();//5
+				z3.mul(x);   //6
+				z3.add(z3);  z3.norm();//7
+				y3.copy(t2); 
+				
+				if (ROM.CURVE_B_I==0)
+					y3.mul(b); //8
+				else
+					y3.imul(ROM.CURVE_B_I);
+				
+				y3.sub(z3); //y3.norm(); //9  ***
+				x3.copy(y3); x3.add(y3); x3.norm();//10
+
+				y3.add(x3); //y3.norm();//11
+				x3.copy(t1); x3.sub(y3); x3.norm();//12
+				y3.add(t1); y3.norm();//13
+				y3.mul(x3); //14
+				x3.mul(t3); //15
+				t3.copy(t2); t3.add(t2); //t3.norm(); //16
+				t2.add(t3); //t2.norm(); //17
+
+				if (ROM.CURVE_B_I==0)
+					z3.mul(b); //18
+				else
+					z3.imul(ROM.CURVE_B_I);
+
+				z3.sub(t2); //z3.norm();//19
+				z3.sub(t0); z3.norm();//20  ***
+				t3.copy(z3); t3.add(z3); //t3.norm();//21
+
+				z3.add(t3); z3.norm(); //22
+				t3.copy(t0); t3.add(t0); //t3.norm(); //23
+				t0.add(t3); //t0.norm();//24
+				t0.sub(t2); t0.norm();//25
+
+				t0.mul(z3);//26
+				y3.add(t0); //y3.norm();//27
+				t0.copy(y); t0.mul(z);//28
+				t0.add(t0); t0.norm(); //29
+				z3.mul(t0);//30
+				x3.sub(z3); //x3.norm();//31
+				t0.add(t0); t0.norm();//32
+				t1.add(t1); t1.norm();//33
+				z3.copy(t0); z3.mul(t1);//34
+
+				x.copy(x3); x.norm(); 
+				y.copy(y3); y.norm();
+				z.copy(z3); z.norm();
+			}
+		}
+		if (CURVETYPE==EDWARDS)
+		{
+//System.out.println("Into dbl");
+			FP C=new FP(x);
+			FP D=new FP(y);
+			FP H=new FP(z);
+			FP J=new FP(0);
+
+			x.mul(y); x.add(x); x.norm();
+			C.sqr();
+			D.sqr();
+
+			if (ROM.CURVE_A==-1) C.neg();	
+
+			y.copy(C); y.add(D); y.norm();
+			H.sqr(); H.add(H);
+
+			z.copy(y);
+			J.copy(y); 
+
+			J.sub(H); J.norm();
+			x.mul(J);
+
+			C.sub(D); C.norm();
+			y.mul(C);
+			z.mul(J);
+//System.out.println("Out of dbl");
+		}
+		if (CURVETYPE==MONTGOMERY)
+		{
+			FP A=new FP(x);
+			FP B=new FP(x);		
+			FP AA=new FP(0);
+			FP BB=new FP(0);
+			FP C=new FP(0);
+
+			A.add(z); A.norm();
+			AA.copy(A); AA.sqr();
+			B.sub(z); B.norm();
+			BB.copy(B); BB.sqr();
+			C.copy(AA); C.sub(BB); C.norm();
+			x.copy(AA); x.mul(BB);
+
+			A.copy(C); A.imul((ROM.CURVE_A+2)/4);
+
+			BB.add(A); BB.norm();
+			z.copy(BB); z.mul(C);
+		}
+		return;
+	}
+
+/* this+=Q */
+	public void add(ECP Q) {
+		if (INF)
+		{
+			copy(Q);
+			return;
+		}
+		if (Q.INF) return;
+
+		if (CURVETYPE==WEIERSTRASS)
+		{
+
+
+			if (ROM.CURVE_A==0)
+			{
+// Edits made
+//System.out.println("Into add");
+				int b=3*ROM.CURVE_B_I;
+				FP t0=new FP(x);
+				t0.mul(Q.x);
+				FP t1=new FP(y);
+				t1.mul(Q.y);
+				FP t2=new FP(z);
+				t2.mul(Q.z);
+				FP t3=new FP(x);
+				t3.add(y); t3.norm();
+				FP t4=new FP(Q.x);
+				t4.add(Q.y); t4.norm();
+				t3.mul(t4);
+				t4.copy(t0); t4.add(t1);
+
+				t3.sub(t4); t3.norm();
+				t4.copy(y);
+				t4.add(z); t4.norm();
+				FP x3=new FP(Q.y);
+				x3.add(Q.z); x3.norm();
+
+				t4.mul(x3);
+				x3.copy(t1);
+				x3.add(t2);
+	
+				t4.sub(x3); t4.norm();
+				x3.copy(x); x3.add(z); x3.norm();
+				FP y3=new FP(Q.x);
+				y3.add(Q.z); y3.norm();
+				x3.mul(y3);
+				y3.copy(t0);
+				y3.add(t2);
+				y3.rsub(x3); y3.norm();
+				x3.copy(t0); x3.add(t0); 
+				t0.add(x3); t0.norm();
+				t2.imul(b);
+
+				FP z3=new FP(t1); z3.add(t2); z3.norm();
+				t1.sub(t2); t1.norm(); 
+				y3.imul(b);
+	
+				x3.copy(y3); x3.mul(t4); t2.copy(t3); t2.mul(t1); x3.rsub(t2);
+				y3.mul(t0); t1.mul(z3); y3.add(t1);
+				t0.mul(t3); z3.mul(t4); z3.add(t0);
+
+				x.copy(x3); x.norm(); 
+				y.copy(y3); y.norm();
+				z.copy(z3); z.norm();
+//System.out.println("Out of add");
+			}
+			else
+			{
+				FP t0=new FP(x);
+				FP t1=new FP(y);
+				FP t2=new FP(z);
+				FP t3=new FP(x);
+				FP t4=new FP(Q.x);
+				FP z3=new FP(0);
+				FP y3=new FP(Q.x);
+				FP x3=new FP(Q.y);
+				FP b=new FP(0);
+
+				if (ROM.CURVE_B_I==0)
+					b.copy(new FP(new BIG(ROM.CURVE_B)));
+
+				t0.mul(Q.x); //1
+				t1.mul(Q.y); //2
+				t2.mul(Q.z); //3
+
+				t3.add(y); t3.norm(); //4
+				t4.add(Q.y); t4.norm();//5
+				t3.mul(t4);//6
+				t4.copy(t0); t4.add(t1); //t4.norm(); //7
+				t3.sub(t4); t3.norm(); //8
+				t4.copy(y); t4.add(z); t4.norm();//9
+				x3.add(Q.z); x3.norm();//10
+				t4.mul(x3); //11
+				x3.copy(t1); x3.add(t2); //x3.norm();//12
+
+				t4.sub(x3); t4.norm();//13
+				x3.copy(x); x3.add(z); x3.norm(); //14
+				y3.add(Q.z); y3.norm();//15
+
+				x3.mul(y3); //16
+				y3.copy(t0); y3.add(t2); //y3.norm();//17
+
+				y3.rsub(x3); y3.norm(); //18
+				z3.copy(t2); 
+				
+
+				if (ROM.CURVE_B_I==0)
+					z3.mul(b); //18
+				else
+					z3.imul(ROM.CURVE_B_I);
+				
+				x3.copy(y3); x3.sub(z3); x3.norm(); //20
+				z3.copy(x3); z3.add(x3); //z3.norm(); //21
+
+				x3.add(z3); //x3.norm(); //22
+				z3.copy(t1); z3.sub(x3); z3.norm(); //23
+				x3.add(t1); x3.norm(); //24
+
+				if (ROM.CURVE_B_I==0)
+					y3.mul(b); //18
+				else
+					y3.imul(ROM.CURVE_B_I);
+
+				t1.copy(t2); t1.add(t2); //t1.norm();//26
+				t2.add(t1); //t2.norm();//27
+
+				y3.sub(t2); //y3.norm(); //28
+
+				y3.sub(t0); y3.norm(); //29
+				t1.copy(y3); t1.add(y3); //t1.norm();//30
+				y3.add(t1); y3.norm(); //31
+
+				t1.copy(t0); t1.add(t0); //t1.norm(); //32
+				t0.add(t1); //t0.norm();//33
+				t0.sub(t2); t0.norm();//34
+				t1.copy(t4); t1.mul(y3);//35
+				t2.copy(t0); t2.mul(y3);//36
+				y3.copy(x3); y3.mul(z3);//37
+				y3.add(t2); //y3.norm();//38
+				x3.mul(t3);//39
+				x3.sub(t1);//40
+				z3.mul(t4);//41
+				t1.copy(t3); t1.mul(t0);//42
+				z3.add(t1); 
+				x.copy(x3); x.norm(); 
+				y.copy(y3); y.norm();
+				z.copy(z3); z.norm();
+			}
+		}
+		if (CURVETYPE==EDWARDS)
+		{
+//System.out.println("Into add");
+			FP A=new FP(z);
+			FP B=new FP(0);
+			FP C=new FP(x);
+			FP D=new FP(y);
+			FP E=new FP(0);
+			FP F=new FP(0);
+			FP G=new FP(0);
+
+			A.mul(Q.z);   
+			B.copy(A); B.sqr();    
+			C.mul(Q.x);      
+			D.mul(Q.y); 
+
+			E.copy(C); E.mul(D);  
+		
+			if (ROM.CURVE_B_I==0)
+			{
+				FP b=new FP(new BIG(ROM.CURVE_B));
+				E.mul(b);
+			}
+			else
+				E.imul(ROM.CURVE_B_I); 
+
+			F.copy(B); F.sub(E);      
+			G.copy(B); G.add(E);       
+
+			if (ROM.CURVE_A==1)
+			{
+				E.copy(D); E.sub(C);
+			}
+			C.add(D); 
+
+			B.copy(x); B.add(y);    
+			D.copy(Q.x); D.add(Q.y); B.norm(); D.norm(); 
+			B.mul(D);                   
+			B.sub(C); B.norm(); F.norm(); 
+			B.mul(F);                     
+			x.copy(A); x.mul(B); G.norm();  
+			if (ROM.CURVE_A==1)
+			{
+				E.norm(); C.copy(E); C.mul(G);  
+			}
+			if (ROM.CURVE_A==-1)
+			{
+				C.norm(); C.mul(G);
+			}
+			y.copy(A); y.mul(C);     
+
+			z.copy(F);	
+			z.mul(G);
+//System.out.println("Out of add");
+		}
+		return;
+	}
+
+/* Differential Add for Montgomery curves. this+=Q where W is this-Q and is affine. */
+	public void dadd(ECP Q,ECP W) {
+		FP A=new FP(x);
+		FP B=new FP(x);
+		FP C=new FP(Q.x);
+		FP D=new FP(Q.x);
+		FP DA=new FP(0);
+		FP CB=new FP(0);	
+			
+		A.add(z); 
+		B.sub(z); 
+
+		C.add(Q.z);
+		D.sub(Q.z);
+		A.norm();
+
+		D.norm();
+		DA.copy(D); DA.mul(A);
+
+		C.norm();
+		B.norm();
+		CB.copy(C); CB.mul(B);
+
+		A.copy(DA); A.add(CB); 
+		A.norm(); A.sqr();
+		B.copy(DA); B.sub(CB); 
+		B.norm(); B.sqr();
+
+		x.copy(A);
+		z.copy(W.x); z.mul(B);
+	}
+/* this-=Q */
+	public void sub(ECP Q) {
+		Q.neg();
+		add(Q);
+		Q.neg();
+	}
+
+/* constant time multiply by small integer of length bts - use ladder */
+	public ECP pinmul(int e,int bts) {	
+		if (CURVETYPE==MONTGOMERY)
+			return this.mul(new BIG(e));
+		else
+		{
+			int nb,i,b;
+			ECP P=new ECP();
+			ECP R0=new ECP();
+			ECP R1=new ECP(); R1.copy(this);
+
+			for (i=bts-1;i>=0;i--)
+			{
+				b=(e>>i)&1;
+				P.copy(R1);
+				P.add(R0);
+				R0.cswap(R1,b);
+				R1.copy(P);
+				R0.dbl();
+				R0.cswap(R1,b);
+			}
+			P.copy(R0);
+			P.affine();
+			return P;
+		}
+	}
+
+/* return e.this */
+
+	public ECP mul(BIG e) {
+		if (e.iszilch() || is_infinity()) return new ECP();
+		ECP P=new ECP();
+		if (CURVETYPE==MONTGOMERY)
+		{
+/* use Ladder */
+			int nb,i,b;
+			ECP D=new ECP();
+			ECP R0=new ECP(); R0.copy(this);
+			ECP R1=new ECP(); R1.copy(this);
+			R1.dbl();
+
+			D.copy(this); D.affine();
+			nb=e.nbits();
+			for (i=nb-2;i>=0;i--)
+			{
+				b=e.bit(i);
+				P.copy(R1);
+
+				P.dadd(R0,D);
+				R0.cswap(R1,b);
+				R1.copy(P);
+				R0.dbl();
+				R0.cswap(R1,b);
+
+			}
+
+			P.copy(R0);
+		}
+		else
+		{
+// fixed size windows 
+			int i,b,nb,m,s,ns;
+			BIG mt=new BIG();
+			BIG t=new BIG();
+			ECP Q=new ECP();
+			ECP C=new ECP();
+			ECP[] W=new ECP[8];
+			byte[] w=new byte[1+(BIG.NLEN*BIG.BASEBITS+3)/4];
+
+			affine();
+
+// precompute table 
+			Q.copy(this);
+
+			Q.dbl();
+			W[0]=new ECP();
+			W[0].copy(this);
+
+			for (i=1;i<8;i++)
+			{
+				W[i]=new ECP();
+				W[i].copy(W[i-1]);
+				W[i].add(Q);
+			}
+
+// make exponent odd - add 2P if even, P if odd 
+			t.copy(e);
+			s=t.parity();
+			t.inc(1); t.norm(); ns=t.parity(); mt.copy(t); mt.inc(1); mt.norm();
+			t.cmove(mt,s);
+			Q.cmove(this,ns);
+			C.copy(Q);
+
+			nb=1+(t.nbits()+3)/4;
+
+// convert exponent to signed 4-bit window 
+			for (i=0;i<nb;i++)
+			{
+				w[i]=(byte)(t.lastbits(5)-16);
+				t.dec(w[i]); t.norm();
+				t.fshr(4);	
+			}
+			w[nb]=(byte)t.lastbits(5);
+	
+			P.copy(W[(w[nb]-1)/2]);  
+			for (i=nb-1;i>=0;i--)
+			{
+				Q.select(W,w[i]);
+				P.dbl();
+				P.dbl();
+				P.dbl();
+				P.dbl();
+				P.add(Q);
+			}
+			P.sub(C); /* apply correction */
+		}
+		P.affine();
+		return P;
+	}
+
+/* Return e.this+f.Q */
+
+	public ECP mul2(BIG e,ECP Q,BIG f) {
+		BIG te=new BIG();
+		BIG tf=new BIG();
+		BIG mt=new BIG();
+		ECP S=new ECP();
+		ECP T=new ECP();
+		ECP C=new ECP();
+		ECP[] W=new ECP[8];
+		byte[] w=new byte[1+(BIG.NLEN*BIG.BASEBITS+1)/2];		
+		int i,s,ns,nb;
+		byte a,b;
+
+		affine();
+		Q.affine();
+
+		te.copy(e);
+		tf.copy(f);
+
+// precompute table 
+		W[1]=new ECP(); W[1].copy(this); W[1].sub(Q);
+		W[2]=new ECP(); W[2].copy(this); W[2].add(Q);
+		S.copy(Q); S.dbl();
+		W[0]=new ECP(); W[0].copy(W[1]); W[0].sub(S);
+		W[3]=new ECP(); W[3].copy(W[2]); W[3].add(S);
+		T.copy(this); T.dbl();
+		W[5]=new ECP(); W[5].copy(W[1]); W[5].add(T);
+		W[6]=new ECP(); W[6].copy(W[2]); W[6].add(T);
+		W[4]=new ECP(); W[4].copy(W[5]); W[4].sub(S);
+		W[7]=new ECP(); W[7].copy(W[6]); W[7].add(S);
+
+// if multiplier is odd, add 2, else add 1 to multiplier, and add 2P or P to correction 
+
+		s=te.parity();
+		te.inc(1); te.norm(); ns=te.parity(); mt.copy(te); mt.inc(1); mt.norm();
+		te.cmove(mt,s);
+		T.cmove(this,ns);
+		C.copy(T);
+
+		s=tf.parity();
+		tf.inc(1); tf.norm(); ns=tf.parity(); mt.copy(tf); mt.inc(1); mt.norm();
+		tf.cmove(mt,s);
+		S.cmove(Q,ns);
+		C.add(S);
+
+		mt.copy(te); mt.add(tf); mt.norm();
+		nb=1+(mt.nbits()+1)/2;
+
+// convert exponent to signed 2-bit window 
+		for (i=0;i<nb;i++)
+		{
+			a=(byte)(te.lastbits(3)-4);
+			te.dec(a); te.norm(); 
+			te.fshr(2);
+			b=(byte)(tf.lastbits(3)-4);
+			tf.dec(b); tf.norm(); 
+			tf.fshr(2);
+			w[i]=(byte)(4*a+b);
+		}
+		w[nb]=(byte)(4*te.lastbits(3)+tf.lastbits(3));
+		S.copy(W[(w[nb]-1)/2]);  
+
+		for (i=nb-1;i>=0;i--)
+		{
+			T.select(W,w[i]);
+			S.dbl();
+			S.dbl();
+			S.add(T);
+		}
+		S.sub(C); /* apply correction */
+		S.affine();
+		return S;
+	}
+
+/* Hash byte string to curve point */
+	public static ECP mapit(byte[] h)
+	{
+		BIG q=new BIG(ROM.Modulus);
+		BIG x=BIG.fromBytes(h);
+		x.mod(q);
+		ECP P;
+
+		while (true)
+		{
+			P=new ECP(x,0);
+			if (!P.is_infinity()) break;
+			x.inc(1); x.norm();
+		}
+
+		if (ECP.CURVE_PAIRING_TYPE!=ECP.BN)
+		{
+			BIG c=new BIG(ROM.CURVE_Cof);
+			P=P.mul(c);
+		}
+		return P;
+	}
+
+	public static ECP generator()
+	{
+		ECP G;
+		BIG gx,gy;
+		gx=new BIG(ROM.CURVE_Gx);
+
+		if (ECP.CURVETYPE!=ECP.MONTGOMERY)
+		{
+			gy=new BIG(ROM.CURVE_Gy);
+			G=new ECP(gx,gy);
+		}
+		else
+			G=new ECP(gx);
+		return G;
+	}
+
+/*
+	public static void main(String[] args) {
+
+		BIG Gx=new BIG(ROM.CURVE_Gx);
+		BIG Gy;
+		ECP P;
+		if (CURVETYPE!=MONTGOMERY) Gy=new BIG(ROM.CURVE_Gy);
+		BIG r=new BIG(ROM.CURVE_Order);
+
+		//r.dec(7);
+	
+		System.out.println("Gx= "+Gx.toString());		
+		if (CURVETYPE!=MONTGOMERY) System.out.println("Gy= "+Gy.toString());	
+
+		if (CURVETYPE!=MONTGOMERY) P=new ECP(Gx,Gy);
+		else  P=new ECP(Gx);
+
+		System.out.println("P= "+P.toString());		
+
+		ECP R=P.mul(r);
+		//for (int i=0;i<10000;i++)
+		//	R=P.mul(r);
+	
+		System.out.println("R= "+R.toString());
+    } */
+}
+
diff --git a/version3/java/OLDECP2.java b/version3/java/OLDECP2.java
new file mode 100644
index 0000000..fb11645
--- /dev/null
+++ b/version3/java/OLDECP2.java
@@ -0,0 +1,781 @@
+/*
+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.
+*/
+
+/* AMCL Weierstrass elliptic curve functions over FP2 */
+
+package org.apache.milagro.amcl.XXX;
+
+public final class ECP2 {
+	private FP2 x;
+	private FP2 y;
+	private FP2 z;
+	private boolean INF;
+
+/* Constructor - set this=O */
+	public ECP2() {
+		INF=true;
+		x=new FP2(0);
+		y=new FP2(1);
+		z=new FP2(0);
+	}
+
+/* Test this=O? */
+	public boolean is_infinity() {
+		if (INF) return true;                    //******
+		return (x.iszilch() && z.iszilch());
+	}
+/* copy this=P */
+	public void copy(ECP2 P)
+	{
+		x.copy(P.x);
+		y.copy(P.y);
+		z.copy(P.z);
+		INF=P.INF;
+	}
+/* set this=O */
+	public void inf() {
+		INF=true;
+		x.zero();
+		y.one();
+		z.zero();
+	}
+
+/* Conditional move of Q to P dependant on d */
+	public void cmove(ECP2 Q,int d)
+	{
+		x.cmove(Q.x,d);
+		y.cmove(Q.y,d);
+		z.cmove(Q.z,d);
+
+		boolean bd;
+		if (d==0) bd=false;
+		else bd=true;
+		INF^=(INF^Q.INF)&bd;
+	}
+
+/* return 1 if b==c, no branching */
+	public static int teq(int b,int c)
+	{
+		int x=b^c;
+		x-=1;  // if x=0, x now -1
+		return ((x>>31)&1);
+	}
+
+/* Constant time select from pre-computed table */
+	public void select(ECP2 W[],int b)
+	{
+		ECP2 MP=new ECP2(); 
+		int m=b>>31;
+		int babs=(b^m)-m;
+
+		babs=(babs-1)/2;
+
+		cmove(W[0],teq(babs,0));  // conditional move
+		cmove(W[1],teq(babs,1));
+		cmove(W[2],teq(babs,2));
+		cmove(W[3],teq(babs,3));
+		cmove(W[4],teq(babs,4));
+		cmove(W[5],teq(babs,5));
+		cmove(W[6],teq(babs,6));
+		cmove(W[7],teq(babs,7));
+ 
+		MP.copy(this);
+		MP.neg();
+		cmove(MP,(int)(m&1));
+	}
+
+/* Test if P == Q */
+	public boolean equals(ECP2 Q) {
+		if (is_infinity() && Q.is_infinity()) return true;
+		if (is_infinity() || Q.is_infinity()) return false;
+
+
+		FP2 a=new FP2(x);                            // *****
+		FP2 b=new FP2(Q.x);
+		a.mul(Q.z); 
+		b.mul(z); 
+		if (!a.equals(b)) return false;
+
+		a.copy(y); a.mul(Q.z); 
+		b.copy(Q.y); b.mul(z); 
+		if (!a.equals(b)) return false;
+
+		return true;
+	}
+/* set this=-this */
+	public void neg() {
+//		if (is_infinity()) return;
+		y.norm();
+		y.neg(); y.norm();
+		return;
+	}
+/* set to Affine - (x,y,z) to (x,y) */
+	public void affine() {
+		if (is_infinity()) return;
+		FP2 one=new FP2(1);
+		if (z.equals(one))
+		{
+			x.reduce();
+			y.reduce();
+			return;
+		}
+		z.inverse();
+
+		x.mul(z); x.reduce();               // *****
+		y.mul(z); y.reduce();
+		z.copy(one);
+	}
+/* extract affine x as FP2 */
+	public FP2 getX()
+	{
+		affine();
+		return x;
+	}
+/* extract affine y as FP2 */
+	public FP2 getY()
+	{
+		affine();
+		return y;
+	}
+/* extract projective x */
+	public FP2 getx()
+	{
+		return x;
+	}
+/* extract projective y */
+	public FP2 gety()
+	{
+		return y;
+	}
+/* extract projective z */
+	public FP2 getz()
+	{
+		return z;
+	}
+/* convert to byte array */
+	public void toBytes(byte[] b)
+	{
+		byte[] t=new byte[BIG.MODBYTES];
+		affine();
+		x.getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++)
+			b[i]=t[i];
+		x.getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++)
+			b[i+BIG.MODBYTES]=t[i];
+
+		y.getA().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++)
+			b[i+2*BIG.MODBYTES]=t[i];
+		y.getB().toBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++)
+			b[i+3*BIG.MODBYTES]=t[i];
+	}
+/* convert from byte array to point */
+	public static ECP2 fromBytes(byte[] b)
+	{
+		byte[] t=new byte[BIG.MODBYTES];
+		BIG ra;
+		BIG rb;
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=b[i];
+		ra=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=b[i+BIG.MODBYTES];
+		rb=BIG.fromBytes(t);
+		FP2 rx=new FP2(ra,rb);
+
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=b[i+2*BIG.MODBYTES];
+		ra=BIG.fromBytes(t);
+		for (int i=0;i<BIG.MODBYTES;i++) t[i]=b[i+3*BIG.MODBYTES];
+		rb=BIG.fromBytes(t);
+		FP2 ry=new FP2(ra,rb);
+
+		return new ECP2(rx,ry);
+	}
+/* convert this to hex string */
+	public String toString() {
+		if (is_infinity()) return "infinity";
+		affine();
+		return "("+x.toString()+","+y.toString()+")";
+	}
+
+/* Calculate RHS of twisted curve equation x^3+B/i */
+	public static FP2 RHS(FP2 x) {
+		x.norm();
+		FP2 r=new FP2(x);
+		r.sqr();
+		FP2 b=new FP2(new BIG(ROM.CURVE_B));
+
+		if (ECP.SEXTIC_TWIST==ECP.D_TYPE)
+		{
+			b.div_ip();
+		}
+		if (ECP.SEXTIC_TWIST==ECP.M_TYPE)
+		{
+			b.norm();
+			b.mul_ip();
+			b.norm();
+		}
+
+
+		r.mul(x);
+		r.add(b);
+
+		r.reduce();
+		return r;
+	}
+
+/* construct this from (x,y) - but set to O if not on curve */
+	public ECP2(FP2 ix,FP2 iy) {
+		x=new FP2(ix);
+		y=new FP2(iy);
+		z=new FP2(1);
+		FP2 rhs=RHS(x);
+		FP2 y2=new FP2(y);
+		y2.sqr();
+		if (y2.equals(rhs)) INF=false;
+		else {x.zero();INF=true;}
+	}
+
+/* construct this from x - but set to O if not on curve */
+	public ECP2(FP2 ix) {
+		x=new FP2(ix);
+		y=new FP2(1);
+		z=new FP2(1);
+		FP2 rhs=RHS(x);
+		if (rhs.sqrt()) 
+		{
+			y.copy(rhs);
+			INF=false;
+		}
+		else {x.zero();INF=true;}
+	}
+
+/* this+=this */
+	public int dbl() {
+		if (INF) return -1;      
+//System.out.println("Into dbl");
+		FP2 iy=new FP2(y);
+		if (ECP.SEXTIC_TWIST==ECP.D_TYPE)
+		{
+			iy.mul_ip(); iy.norm();
+		}
+		FP2 t0=new FP2(y);                  //***** Change 
+		t0.sqr();            
+		if (ECP.SEXTIC_TWIST==ECP.D_TYPE)
+		{		
+			t0.mul_ip();
+		}
+		FP2 t1=new FP2(iy);  
+		t1.mul(z);
+		FP2 t2=new FP2(z);
+		t2.sqr();
+
+		z.copy(t0);
+		z.add(t0); z.norm(); 
+		z.add(z); 
+		z.add(z); 
+		z.norm();  
+
+		t2.imul(3*ROM.CURVE_B_I); 
+		if (ECP.SEXTIC_TWIST==ECP.M_TYPE)
+		{
+			t2.mul_ip();
+			t2.norm();
+		}
+
+		FP2 x3=new FP2(t2);
+		x3.mul(z); 
+
+		FP2 y3=new FP2(t0);   
+
+		y3.add(t2); y3.norm();
+		z.mul(t1);
+		t1.copy(t2); t1.add(t2); t2.add(t1); t2.norm();  
+		t0.sub(t2); t0.norm();                           //y^2-9bz^2
+		y3.mul(t0); y3.add(x3);                          //(y^2+3z*2)(y^2-9z^2)+3b.z^2.8y^2
+		t1.copy(x); t1.mul(iy);						//
+		x.copy(t0); x.norm(); x.mul(t1); x.add(x);       //(y^2-9bz^2)xy2
+
+		x.norm(); 
+		y.copy(y3); y.norm();
+//System.out.println("Out of dbl");
+		return 1;
+	}
+
+/* this+=Q - return 0 for add, 1 for double, -1 for O */
+	public int add(ECP2 Q) {
+		if (INF)
+		{
+			copy(Q);
+			return -1;
+		}
+		if (Q.INF) return -1;
+//System.out.println("Into add");
+		int b=3*ROM.CURVE_B_I;
+		FP2 t0=new FP2(x);
+		t0.mul(Q.x);         // x.Q.x
+		FP2 t1=new FP2(y);
+		t1.mul(Q.y);		 // y.Q.y
+
+		FP2 t2=new FP2(z);
+		t2.mul(Q.z);
+		FP2 t3=new FP2(x);
+		t3.add(y); t3.norm();          //t3=X1+Y1
+		FP2 t4=new FP2(Q.x);            
+		t4.add(Q.y); t4.norm();			//t4=X2+Y2
+		t3.mul(t4);						//t3=(X1+Y1)(X2+Y2)
+		t4.copy(t0); t4.add(t1);		//t4=X1.X2+Y1.Y2
+
+		t3.sub(t4); t3.norm(); 
+		if (ECP.SEXTIC_TWIST==ECP.D_TYPE)
+		{		
+			t3.mul_ip();  t3.norm();         //t3=(X1+Y1)(X2+Y2)-(X1.X2+Y1.Y2) = X1.Y2+X2.Y1
+		}
+		t4.copy(y);                    
+		t4.add(z); t4.norm();			//t4=Y1+Z1
+		FP2 x3=new FP2(Q.y);
+		x3.add(Q.z); x3.norm();			//x3=Y2+Z2
+
+		t4.mul(x3);						//t4=(Y1+Z1)(Y2+Z2)
+		x3.copy(t1);					//
+		x3.add(t2);						//X3=Y1.Y2+Z1.Z2
+	
+		t4.sub(x3); t4.norm(); 
+		if (ECP.SEXTIC_TWIST==ECP.D_TYPE)
+		{	
+			t4.mul_ip(); t4.norm();          //t4=(Y1+Z1)(Y2+Z2) - (Y1.Y2+Z1.Z2) = Y1.Z2+Y2.Z1
+		}
+		x3.copy(x); x3.add(z); x3.norm();	// x3=X1+Z1
+		FP2 y3=new FP2(Q.x);				
+		y3.add(Q.z); y3.norm();				// y3=X2+Z2
+		x3.mul(y3);							// x3=(X1+Z1)(X2+Z2)
+		y3.copy(t0);
+		y3.add(t2);							// y3=X1.X2+Z1+Z2
+		y3.rsub(x3); y3.norm();				// y3=(X1+Z1)(X2+Z2) - (X1.X2+Z1.Z2) = X1.Z2+X2.Z1
+
+		if (ECP.SEXTIC_TWIST==ECP.D_TYPE)
+		{
+			t0.mul_ip(); t0.norm(); // x.Q.x
+			t1.mul_ip(); t1.norm(); // y.Q.y
+		}
+		x3.copy(t0); x3.add(t0); 
+		t0.add(x3); t0.norm();
+		t2.imul(b); 	
+		if (ECP.SEXTIC_TWIST==ECP.M_TYPE)
+		{
+			t2.mul_ip();
+		}
+		FP2 z3=new FP2(t1); z3.add(t2); z3.norm();
+		t1.sub(t2); t1.norm(); 
+		y3.imul(b); 
+		if (ECP.SEXTIC_TWIST==ECP.M_TYPE)
+		{
+			y3.mul_ip(); 
+			y3.norm();
+		}
+		x3.copy(y3); x3.mul(t4); t2.copy(t3); t2.mul(t1); x3.rsub(t2);
+		y3.mul(t0); t1.mul(z3); y3.add(t1);
+		t0.mul(t3); z3.mul(t4); z3.add(t0);
+
+		x.copy(x3); x.norm(); 
+		y.copy(y3); y.norm();
+		z.copy(z3); z.norm();
+//System.out.println("Out of add");
+		return 0;
+	}
+
+/* set this-=Q */
+	public int sub(ECP2 Q) {
+		Q.neg();
+		int D=add(Q);
+		Q.neg();
+		return D;
+	}
+/* set this*=q, where q is Modulus, using Frobenius */
+	public void frob(FP2 X)
+	{
+		if (INF) return;
+		FP2 X2=new FP2(X);
+
+		X2.sqr();
+		x.conj();
+		y.conj();
+		z.conj();
+		z.reduce();
+		x.mul(X2);
+
+		y.mul(X2);
+		y.mul(X);
+	}
+
+/* P*=e */
+	public ECP2 mul(BIG e)
+	{
+/* fixed size windows */
+		int i,b,nb,m,s,ns;
+		BIG mt=new BIG();
+		BIG t=new BIG();
+		ECP2 P=new ECP2();
+		ECP2 Q=new ECP2();
+		ECP2 C=new ECP2();
+		ECP2[] W=new ECP2[8];
+		byte[] w=new byte[1+(BIG.NLEN*BIG.BASEBITS+3)/4];
+
+		if (is_infinity()) return new ECP2();
+
+		affine();
+
+/* precompute table */
+		Q.copy(this);
+		Q.dbl();
+		W[0]=new ECP2();
+		W[0].copy(this);
+
+		for (i=1;i<8;i++)
+		{
+			W[i]=new ECP2();
+			W[i].copy(W[i-1]);
+			W[i].add(Q);
+		}
+
+/* make exponent odd - add 2P if even, P if odd */
+		t.copy(e);
+		s=t.parity();
+		t.inc(1); t.norm(); ns=t.parity(); mt.copy(t); mt.inc(1); mt.norm();
+		t.cmove(mt,s);
+		Q.cmove(this,ns);
+		C.copy(Q);
+
+		nb=1+(t.nbits()+3)/4;
+/* convert exponent to signed 4-bit window */
+		for (i=0;i<nb;i++)
+		{
+			w[i]=(byte)(t.lastbits(5)-16);
+			t.dec(w[i]); t.norm();
+			t.fshr(4);	
+		}
+		w[nb]=(byte)t.lastbits(5);
+	
+		P.copy(W[(w[nb]-1)/2]);  
+		for (i=nb-1;i>=0;i--)
+		{
+			Q.select(W,w[i]);
+			P.dbl();
+			P.dbl();
+			P.dbl();
+			P.dbl();
+			P.add(Q);
+		}
+		P.sub(C);
+		P.affine();
+		return P;
+	}
+
+/* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3 */
+// Bos & Costello https://eprint.iacr.org/2013/458.pdf
+// Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
+// Side channel attack secure 
+
+	public static ECP2 mul4(ECP2[] Q,BIG[] u)
+	{
+		int i,j,nb,pb;
+		ECP2 W=new ECP2();
+		ECP2 P=new ECP2();
+		ECP2[] T=new ECP2[8];
+
+		BIG mt=new BIG();
+		BIG[] t=new BIG[4];
+
+		byte[] w=new byte[BIG.NLEN*BIG.BASEBITS+1];
+		byte[] s=new byte[BIG.NLEN*BIG.BASEBITS+1];
+
+		for (i=0;i<4;i++)
+		{
+			t[i]=new BIG(u[i]);
+			Q[i].affine();
+		}
+
+        T[0] = new ECP2(); T[0].copy(Q[0]);  // Q[0]
+        T[1] = new ECP2(); T[1].copy(T[0]); T[1].add(Q[1]);  // Q[0]+Q[1]
+        T[2] = new ECP2(); T[2].copy(T[0]); T[2].add(Q[2]);  // Q[0]+Q[2]
+        T[3] = new ECP2(); T[3].copy(T[1]); T[3].add(Q[2]);  // Q[0]+Q[1]+Q[2]
+        T[4] = new ECP2(); T[4].copy(T[0]); T[4].add(Q[3]);  // Q[0]+Q[3]
+        T[5] = new ECP2(); T[5].copy(T[1]); T[5].add(Q[3]);  // Q[0]+Q[1]+Q[3]
+        T[6] = new ECP2(); T[6].copy(T[2]); T[6].add(Q[3]);  // Q[0]+Q[2]+Q[3]
+        T[7] = new ECP2(); T[7].copy(T[3]); T[7].add(Q[3]);  // Q[0]+Q[1]+Q[2]+Q[3]
+
+    // Make it odd
+        pb=1-t[0].parity();
+        t[0].inc(pb);
+        t[0].norm();
+
+    // Number of bits
+        mt.zero();
+        for (i=0;i<4;i++) {
+            mt.add(t[i]); mt.norm();
+        }
+        nb=1+mt.nbits();
+
+    // Sign pivot 
+        s[nb-1]=1;
+        for (i=0;i<nb-1;i++) {
+            t[0].fshr(1);
+            s[i]=(byte)(2*t[0].parity()-1);
+        }
+
+    // Recoded exponent
+        for (i=0; i<nb; i++) {
+            w[i]=0;
+            int k=1;
+            for (j=1; j<4; j++) {
+                byte bt=(byte)(s[i]*t[j].parity());
+                t[j].fshr(1);
+                t[j].dec((int)(bt)>>1);
+                t[j].norm();
+                w[i]+=bt*(byte)k;
+                k*=2;
+            }
+        } 
+
+    // Main loop
+        P.select(T,(int)(2*w[nb-1]+1));  
+        for (i=nb-2;i>=0;i--) {
+            P.dbl();
+            W.select(T,(int)(2*w[i]+s[i]));
+            P.add(W);
+        }
+
+    // apply correction
+        W.copy(P);   
+        W.sub(Q[0]);
+        P.cmove(W,pb);   
+		P.affine();
+		return P;
+	}        
+
+
+/* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3 */
+/*
+	public static ECP2 mul4(ECP2[] Q,BIG[] u)
+	{
+		int i,j,nb;
+		int[] a=new int[4];
+		ECP2 T=new ECP2();
+		ECP2 C=new ECP2();
+		ECP2 P=new ECP2();
+		ECP2[] W=new ECP2[8];
+
+		BIG mt=new BIG();
+		BIG[] t=new BIG[4];
+
+		byte[] w=new byte[BIG.NLEN*BIG.BASEBITS+1];
+
+		for (i=0;i<4;i++)
+		{
+			t[i]=new BIG(u[i]);
+			Q[i].affine();
+		}
+
+// precompute table 
+
+		W[0]=new ECP2(); W[0].copy(Q[0]); W[0].sub(Q[1]);
+
+		W[1]=new ECP2(); W[1].copy(W[0]);
+		W[2]=new ECP2(); W[2].copy(W[0]);
+		W[3]=new ECP2(); W[3].copy(W[0]);
+		W[4]=new ECP2(); W[4].copy(Q[0]); W[4].add(Q[1]);
+		W[5]=new ECP2(); W[5].copy(W[4]);
+		W[6]=new ECP2(); W[6].copy(W[4]);
+		W[7]=new ECP2(); W[7].copy(W[4]);
+		T.copy(Q[2]); T.sub(Q[3]);
+		W[1].sub(T);
+		W[2].add(T);
+		W[5].sub(T);
+		W[6].add(T);
+		T.copy(Q[2]); T.add(Q[3]);
+		W[0].sub(T);
+		W[3].add(T);
+		W[4].sub(T);
+		W[7].add(T);
+
+// if multiplier is even add 1 to multiplier, and add P to correction 
+		mt.zero(); C.inf();
+		for (i=0;i<4;i++)
+		{
+			if (t[i].parity()==0)
+			{
+				t[i].inc(1); t[i].norm();
+				C.add(Q[i]);
+			}
+			mt.add(t[i]); mt.norm();
+		}
+
+		nb=1+mt.nbits();
+
+// convert exponent to signed 1-bit window 
+		for (j=0;j<nb;j++)
+		{
+			for (i=0;i<4;i++)
+			{
+				a[i]=(byte)(t[i].lastbits(2)-2);
+				t[i].dec(a[i]); t[i].norm(); 
+				t[i].fshr(1);
+			}
+			w[j]=(byte)(8*a[0]+4*a[1]+2*a[2]+a[3]);
+		}
+		w[nb]=(byte)(8*t[0].lastbits(2)+4*t[1].lastbits(2)+2*t[2].lastbits(2)+t[3].lastbits(2));
+
+		P.copy(W[(w[nb]-1)/2]);  
+		for (i=nb-1;i>=0;i--)
+		{
+			T.select(W,w[i]);
+			P.dbl();
+			P.add(T);
+		}
+		P.sub(C); // apply correction 
+
+		P.affine();
+		return P;
+	}
+*/
+
+/* needed for SOK */
+	public static ECP2 mapit(byte[] h)
+	{
+		BIG q=new BIG(ROM.Modulus);
+		BIG x=BIG.fromBytes(h);
+		BIG one=new BIG(1);
+		FP2 X;
+		ECP2 Q;
+		x.mod(q);
+		while (true)
+		{
+			X=new FP2(one,x);
+			Q=new ECP2(X);
+			if (!Q.is_infinity()) break;
+			x.inc(1); x.norm();
+		}
+
+		BIG Fra=new BIG(ROM.Fra);
+		BIG Frb=new BIG(ROM.Frb);
+		X=new FP2(Fra,Frb);
+
+		if (ECP.SEXTIC_TWIST==ECP.M_TYPE)
+		{
+			X.inverse();
+			X.norm();
+		}
+
+		x=new BIG(ROM.CURVE_Bnx);
+
+/* Fast Hashing to G2 - Fuentes-Castaneda, Knapp and Rodriguez-Henriquez */
+
+		if (ECP.CURVE_PAIRING_TYPE==ECP.BN)
+		{
+			ECP2 T,K;
+
+			T=new ECP2(); T.copy(Q);
+			T=T.mul(x); 
+			
+			if (ECP.SIGN_OF_X==ECP.NEGATIVEX)
+			{
+				T.neg();
+			}	
+			K=new ECP2(); K.copy(T);
+			K.dbl(); K.add(T); //K.affine();
+
+			K.frob(X);
+			Q.frob(X); Q.frob(X); Q.frob(X);
+			Q.add(T); Q.add(K);
+			T.frob(X); T.frob(X);
+			Q.add(T);
+
+		}
+
+/* Efficient hash maps to G2 on BLS curves - Budroni, Pintore */
+/* Q -> x2Q -xQ -Q +F(xQ -Q) +F(F(2Q)) */
+
+		if (ECP.CURVE_PAIRING_TYPE==ECP.BLS)
+		{
+			ECP2 xQ,x2Q;
+			xQ=new ECP2();
+			x2Q=new ECP2();
+
+			xQ=Q.mul(x);
+			x2Q=xQ.mul(x);
+
+			if (ECP.SIGN_OF_X==ECP.NEGATIVEX)
+			{
+				xQ.neg();
+			}	
+
+			x2Q.sub(xQ);
+			x2Q.sub(Q);
+
+			xQ.sub(Q);
+			xQ.frob(X);
+
+			Q.dbl();
+			Q.frob(X);
+			Q.frob(X);
+
+			Q.add(x2Q);
+			Q.add(xQ);
+		}
+		Q.affine();
+		return Q;
+	}
+
+	public static ECP2 generator()
+	{
+		return new ECP2(new FP2(new BIG(ROM.CURVE_Pxa),new BIG(ROM.CURVE_Pxb)),new FP2(new BIG(ROM.CURVE_Pya),new BIG(ROM.CURVE_Pyb)));
+	}
+
+/*
+	public static void main(String[] args) {
+		BIG r=new BIG(ROM.Modulus);
+
+		BIG Pxa=new BIG(ROM.CURVE_Pxa);
+		BIG Pxb=new BIG(ROM.CURVE_Pxb);
+		BIG Pya=new BIG(ROM.CURVE_Pya);
+		BIG Pyb=new BIG(ROM.CURVE_Pyb);
+
+		BIG Fra=new BIG(ROM.CURVE_Fra);
+		BIG Frb=new BIG(ROM.CURVE_Frb);
+
+		FP2 f=new FP2(Fra,Frb);
+
+		FP2 Px=new FP2(Pxa,Pxb);
+		FP2 Py=new FP2(Pya,Pyb);
+
+		ECP2 P=new ECP2(Px,Py);
+
+		System.out.println("P= "+P.toString());
+
+		P=P.mul(r);
+		System.out.println("P= "+P.toString());
+
+		ECP2 Q=new ECP2(Px,Py);
+		Q.frob(f);
+		System.out.println("Q= "+Q.toString());
+	} */
+
+
+}
\ No newline at end of file
diff --git a/version3/java/PAIR.java b/version3/java/PAIR.java
new file mode 100644
index 0000000..0ca70b2
--- /dev/null
+++ b/version3/java/PAIR.java
@@ -0,0 +1,817 @@
+/*
+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.
+*/
+
+/* AMCL BN Curve Pairing functions */
+
+package org.apache.milagro.amcl.XXX;
+
+public final class PAIR {
+
+	public static final boolean USE_GLV =true;
+	public static final boolean USE_GS_G2 =true;
+	public static final boolean USE_GS_GT =true;	
+	public static final boolean GT_STRONG=false;
+
+
+/* Line function */
+	public static FP12 line(ECP2 A,ECP2 B,FP Qx,FP Qy)
+	{
+//System.out.println("Into line");
+		FP4 a,b,c;                            // Edits here
+//		c=new FP4(0);
+		if (A==B)
+		{ // Doubling
+			FP2 XX=new FP2(A.getx());  //X
+			FP2 YY=new FP2(A.gety());  //Y
+			FP2 ZZ=new FP2(A.getz());  //Z
+			FP2 YZ=new FP2(YY);        //Y 
+			YZ.mul(ZZ);                //YZ
+			XX.sqr();	               //X^2
+			YY.sqr();	               //Y^2
+			ZZ.sqr();			       //Z^2
+			
+			YZ.imul(4);
+			YZ.neg(); YZ.norm();       //-2YZ
+			YZ.pmul(Qy);               //-2YZ.Ys
+
+			XX.imul(6);                //3X^2
+			XX.pmul(Qx);               //3X^2.Xs
+
+			int sb=3*ROM.CURVE_B_I;
+			ZZ.imul(sb); 	
+			
+			if (ECP.SEXTIC_TWIST==ECP.D_TYPE)
+			{
+				ZZ.div_ip2();
+			}
+			if (ECP.SEXTIC_TWIST==ECP.M_TYPE)
+			{
+				ZZ.mul_ip();
+				ZZ.add(ZZ);
+				YZ.mul_ip();
+				YZ.norm();
+			}
+			
+			ZZ.norm(); // 3b.Z^2 
+
+			YY.add(YY);
+			ZZ.sub(YY); ZZ.norm();     // 3b.Z^2-Y^2
+
+			a=new FP4(YZ,ZZ);          // -2YZ.Ys | 3b.Z^2-Y^2 | 3X^2.Xs 
+			if (ECP.SEXTIC_TWIST==ECP.D_TYPE)
+			{			
+				b=new FP4(XX);             // L(0,1) | L(0,0) | L(1,0)
+				c=new FP4(0);
+			}
+			if (ECP.SEXTIC_TWIST==ECP.M_TYPE)
+			{
+				b=new FP4(0);
+				c=new FP4(XX); c.times_i();
+			}
+			A.dbl();
+		}
+		else
+		{ // Addition - assume B is affine
+
+			FP2 X1=new FP2(A.getx());    // X1
+			FP2 Y1=new FP2(A.gety());    // Y1
+			FP2 T1=new FP2(A.getz());    // Z1
+			FP2 T2=new FP2(A.getz());    // Z1
+			
+			T1.mul(B.gety());    // T1=Z1.Y2 
+			T2.mul(B.getx());    // T2=Z1.X2
+
+			X1.sub(T2); X1.norm();  // X1=X1-Z1.X2
+			Y1.sub(T1); Y1.norm();  // Y1=Y1-Z1.Y2
+
+			T1.copy(X1);            // T1=X1-Z1.X2
+			X1.pmul(Qy);            // X1=(X1-Z1.X2).Ys
+
+			if (ECP.SEXTIC_TWIST==ECP.M_TYPE)
+			{
+				X1.mul_ip();
+				X1.norm();
+			}
+
+			T1.mul(B.gety());       // T1=(X1-Z1.X2).Y2
+
+			T2.copy(Y1);            // T2=Y1-Z1.Y2
+			T2.mul(B.getx());       // T2=(Y1-Z1.Y2).X2
+			T2.sub(T1); T2.norm();          // T2=(Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2
+			Y1.pmul(Qx);  Y1.neg(); Y1.norm(); // Y1=-(Y1-Z1.Y2).Xs
+
+			a=new FP4(X1,T2);       // (X1-Z1.X2).Ys  |  (Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2  | - (Y1-Z1.Y2).Xs
+			if (ECP.SEXTIC_TWIST==ECP.D_TYPE)
+			{
+				b=new FP4(Y1);
+				c=new FP4(0);
+			}
+			if (ECP.SEXTIC_TWIST==ECP.M_TYPE)
+			{
+				b=new FP4(0);
+				c=new FP4(Y1); c.times_i();
+			}
+			A.add(B);
+		}
+//System.out.println("Out of line");
+		return new FP12(a,b,c);
+	}
+
+/* Optimal R-ate pairing */
+	public static FP12 ate(ECP2 P1,ECP Q1)
+	{
+		FP2 f;
+		BIG x=new BIG(ROM.CURVE_Bnx);
+		BIG n=new BIG(x);
+		ECP2 K=new ECP2();
+		FP12 lv;
+		int bt;
+
+// P is needed in affine form for line function, Q for (Qx,Qy) extraction
+		ECP2 P=new ECP2(P1);
+		ECP Q=new ECP(Q1);
+
+		P.affine();
+		Q.affine();
+
+		if (ECP.CURVE_PAIRING_TYPE==ECP.BN)
+		{
+			f=new FP2(new BIG(ROM.Fra),new BIG(ROM.Frb));
+			if (ECP.SEXTIC_TWIST==ECP.M_TYPE)
+			{
+				f.inverse();
+				f.norm();
+			}
+			n.pmul(6);
+			if (ECP.SIGN_OF_X==ECP.POSITIVEX)
+			{
+				n.inc(2);
+			} else {
+				n.dec(2);
+			}
+		}
+		else
+			n.copy(x);
+		n.norm();
+		
+		BIG n3=new BIG(n);
+		n3.pmul(3);
+		n3.norm();
+
+		FP Qx=new FP(Q.getx());
+		FP Qy=new FP(Q.gety());
+
+		ECP2 A=new ECP2();
+		FP12 r=new FP12(1);
+		A.copy(P);
+
+		ECP2 MP=new ECP2();
+		MP.copy(P); MP.neg();
+
+		int nb=n3.nbits();
+
+		for (int i=nb-2;i>=1;i--)
+		{
+			r.sqr();
+			lv=line(A,A,Qx,Qy);
+			r.smul(lv,ECP.SEXTIC_TWIST);
+
+			bt=n3.bit(i)-n.bit(i); // bt=n.bit(i);
+			if (bt==1)
+			{
+				lv=line(A,P,Qx,Qy);
+				r.smul(lv,ECP.SEXTIC_TWIST);
+			}
+			if (bt==-1)
+			{
+				//P.neg();
+				lv=line(A,MP,Qx,Qy);
+				r.smul(lv,ECP.SEXTIC_TWIST);
+				//P.neg();
+			}
+		}
+
+		if (ECP.SIGN_OF_X==ECP.NEGATIVEX)
+		{
+			r.conj();
+		}
+
+/* R-ate fixup required for BN curves */
+		if (ECP.CURVE_PAIRING_TYPE==ECP.BN)
+		{
+			if (ECP.SIGN_OF_X==ECP.NEGATIVEX)
+			{
+				//r.conj();
+				A.neg();
+			}
+			K.copy(P);
+			K.frob(f);
+			lv=line(A,K,Qx,Qy);
+			r.smul(lv,ECP.SEXTIC_TWIST);
+			K.frob(f);
+			K.neg();
+			lv=line(A,K,Qx,Qy);
+			r.smul(lv,ECP.SEXTIC_TWIST);
+		} 
+		return r;
+	}
+
+/* Optimal R-ate double pairing e(P,Q).e(R,S) */
+	public static FP12 ate2(ECP2 P1,ECP Q1,ECP2 R1,ECP S1)
+	{
+		FP2 f;
+		BIG x=new BIG(ROM.CURVE_Bnx);
+		BIG n=new BIG(x);
+		ECP2 K=new ECP2();
+		FP12 lv;
+		int bt;
+
+		ECP2 P=new ECP2(P1);
+		ECP Q=new ECP(Q1);
+
+		P.affine();
+		Q.affine();
+
+		ECP2 R=new ECP2(R1);
+		ECP S=new ECP(S1);
+
+		R.affine();
+		S.affine();
+
+		if (ECP.CURVE_PAIRING_TYPE==ECP.BN)
+		{
+			f=new FP2(new BIG(ROM.Fra),new BIG(ROM.Frb));
+			if (ECP.SEXTIC_TWIST==ECP.M_TYPE)
+			{
+				f.inverse();
+				f.norm();
+			}
+			n.pmul(6); 
+			if (ECP.SIGN_OF_X==ECP.POSITIVEX)
+			{
+				n.inc(2);
+			} else {
+				n.dec(2);
+			}
+		}
+		else
+			n.copy(x);
+		n.norm();
+
+		BIG n3=new BIG(n);
+		n3.pmul(3);
+		n3.norm();
+
+		FP Qx=new FP(Q.getx());
+		FP Qy=new FP(Q.gety());
+		FP Sx=new FP(S.getx());
+		FP Sy=new FP(S.gety());
+
+		ECP2 A=new ECP2();
+		ECP2 B=new ECP2();
+		FP12 r=new FP12(1);
+
+		A.copy(P);
+		B.copy(R);
+
+		ECP2 MP=new ECP2();
+		MP.copy(P); MP.neg();
+		ECP2 MR=new ECP2();
+		MR.copy(R); MR.neg();
+
+
+		int nb=n3.nbits();
+
+		for (int i=nb-2;i>=1;i--)
+		{
+			r.sqr();
+			lv=line(A,A,Qx,Qy);
+			r.smul(lv,ECP.SEXTIC_TWIST);
+
+			lv=line(B,B,Sx,Sy);
+			r.smul(lv,ECP.SEXTIC_TWIST);
+
+			bt=n3.bit(i)-n.bit(i); // bt=n.bit(i);
+			if (bt==1)
+			{
+				lv=line(A,P,Qx,Qy);
+				r.smul(lv,ECP.SEXTIC_TWIST);
+				lv=line(B,R,Sx,Sy);
+				r.smul(lv,ECP.SEXTIC_TWIST);
+			}
+			if (bt==-1)
+			{
+				//P.neg(); 
+				lv=line(A,MP,Qx,Qy);
+				r.smul(lv,ECP.SEXTIC_TWIST);
+				//P.neg(); 
+				//R.neg();
+				lv=line(B,MR,Sx,Sy);
+				r.smul(lv,ECP.SEXTIC_TWIST);
+				//R.neg();
+			}
+		}
+
+		if (ECP.SIGN_OF_X==ECP.NEGATIVEX)
+		{
+			r.conj();
+		}
+
+/* R-ate fixup required for BN curves */
+		if (ECP.CURVE_PAIRING_TYPE==ECP.BN)
+		{
+			if (ECP.SIGN_OF_X==ECP.NEGATIVEX)
+			{
+			//	r.conj();
+				A.neg();
+				B.neg();
+			}
+
+			K.copy(P);
+			K.frob(f);
+
+			lv=line(A,K,Qx,Qy);
+			r.smul(lv,ECP.SEXTIC_TWIST);
+			K.frob(f);
+			K.neg();
+			lv=line(A,K,Qx,Qy);
+			r.smul(lv,ECP.SEXTIC_TWIST);
+			K.copy(R);
+			K.frob(f);
+			lv=line(B,K,Sx,Sy);
+			r.smul(lv,ECP.SEXTIC_TWIST);
+			K.frob(f);
+			K.neg();
+			lv=line(B,K,Sx,Sy);
+			r.smul(lv,ECP.SEXTIC_TWIST);
+		}
+		return r;
+	}
+
+/* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */
+	public static FP12 fexp(FP12 m)
+	{
+		FP2 f=new FP2(new BIG(ROM.Fra),new BIG(ROM.Frb));
+		BIG x=new BIG(ROM.CURVE_Bnx);
+		FP12 r=new FP12(m);
+
+/* Easy part of final exp */
+		FP12 lv=new FP12(r);
+		lv.inverse();
+		r.conj();
+
+		r.mul(lv);
+		lv.copy(r);
+		r.frob(f);
+		r.frob(f);
+		r.mul(lv);
+/* Hard part of final exp */
+		if (ECP.CURVE_PAIRING_TYPE==ECP.BN)
+		{
+			FP12 x0,x1,x2,x3,x4,x5;			
+			lv.copy(r);
+			lv.frob(f);
+			x0=new FP12(lv);
+			x0.frob(f);
+			lv.mul(r);
+			x0.mul(lv);
+			x0.frob(f);
+			x1=new FP12(r);
+			x1.conj();
+			x4=r.pow(x);
+			if (ECP.SIGN_OF_X==ECP.POSITIVEX)
+			{
+				x4.conj();
+			}
+
+			x3=new FP12(x4);
+			x3.frob(f);
+
+			x2=x4.pow(x);
+			if (ECP.SIGN_OF_X==ECP.POSITIVEX)
+			{
+				x2.conj();
+			}
+			x5=new FP12(x2); x5.conj();
+			lv=x2.pow(x);
+			if (ECP.SIGN_OF_X==ECP.POSITIVEX)
+			{
+				lv.conj();
+			}
+			x2.frob(f);
+			r.copy(x2); r.conj();
+
+			x4.mul(r);
+			x2.frob(f);
+
+			r.copy(lv);
+			r.frob(f);
+			lv.mul(r);
+
+			lv.usqr();
+			lv.mul(x4);
+			lv.mul(x5);
+			r.copy(x3);
+			r.mul(x5);
+			r.mul(lv);
+			lv.mul(x2);
+			r.usqr();
+			r.mul(lv);
+			r.usqr();
+			lv.copy(r);
+			lv.mul(x1);
+			r.mul(x0);
+			lv.usqr();
+			r.mul(lv);
+			r.reduce();
+		}
+		else
+		{
+
+			FP12 y0,y1,y2,y3;
+// Ghamman & Fouotsa Method
+			y0=new FP12(r); y0.usqr();
+			y1=y0.pow(x);
+			if (ECP.SIGN_OF_X==ECP.NEGATIVEX)
+			{
+				y1.conj();
+			}
+			x.fshr(1); y2=y1.pow(x); 
+			if (ECP.SIGN_OF_X==ECP.NEGATIVEX)
+			{
+				y2.conj();
+			}			
+			
+			x.fshl(1);
+			y3=new FP12(r); y3.conj();
+			y1.mul(y3);
+
+			y1.conj();
+			y1.mul(y2);
+
+			y2=y1.pow(x);
+			if (ECP.SIGN_OF_X==ECP.NEGATIVEX)
+			{
+				y2.conj();
+			}
+			y3=y2.pow(x);
+			if (ECP.SIGN_OF_X==ECP.NEGATIVEX)
+			{
+				y3.conj();
+			}
+			y1.conj();
+			y3.mul(y1);
+
+			y1.conj();
+			y1.frob(f); y1.frob(f); y1.frob(f);
+			y2.frob(f); y2.frob(f);
+			y1.mul(y2);
+
+			y2=y3.pow(x);
+			if (ECP.SIGN_OF_X==ECP.NEGATIVEX)
+			{
+				y2.conj();
+			}
+			y2.mul(y0);
+			y2.mul(r);
+
+			y1.mul(y2);
+			y2.copy(y3); y2.frob(f);
+			y1.mul(y2);
+			r.copy(y1);
+			r.reduce();
+		}
+		
+		return r;
+	}
+
+/* GLV method */
+	public static BIG[] glv(BIG e)
+	{
+		BIG[] u=new BIG[2];
+		if (ECP.CURVE_PAIRING_TYPE==ECP.BN)
+		{
+			int i,j;
+			BIG t=new BIG(0);
+			BIG q=new BIG(ROM.CURVE_Order);
+
+			BIG[] v=new BIG[2];
+			for (i=0;i<2;i++)
+			{
+				t.copy(new BIG(ROM.CURVE_W[i]));  // why not just t=new BIG(ROM.CURVE_W[i]); 
+				DBIG d=BIG.mul(t,e);
+				v[i]=new BIG(d.div(q));
+				u[i]=new BIG(0);
+			}
+			u[0].copy(e);
+			for (i=0;i<2;i++)
+				for (j=0;j<2;j++)
+				{
+					t.copy(new BIG(ROM.CURVE_SB[j][i]));
+					t.copy(BIG.modmul(v[j],t,q));
+					u[i].add(q);
+					u[i].sub(t);
+					u[i].mod(q);
+				}
+		}
+		else
+		{ // -(x^2).P = (Beta.x,y)
+			BIG q=new BIG(ROM.CURVE_Order);
+			BIG x=new BIG(ROM.CURVE_Bnx);
+			BIG x2=BIG.smul(x,x);
+			u[0]=new BIG(e);
+			u[0].mod(x2);
+			u[1]=new BIG(e);
+			u[1].div(x2);
+			u[1].rsub(q);
+		}
+		return u;
+	}
+
+/* Galbraith & Scott Method */
+	public static BIG[] gs(BIG e)
+	{
+		BIG[] u=new BIG[4];
+		if (ECP.CURVE_PAIRING_TYPE==ECP.BN)
+		{
+			int i,j;
+			BIG t=new BIG(0);
+			BIG q=new BIG(ROM.CURVE_Order);
+			BIG[] v=new BIG[4];
+			for (i=0;i<4;i++)
+			{
+				t.copy(new BIG(ROM.CURVE_WB[i]));
+				DBIG d=BIG.mul(t,e);
+				v[i]=new BIG(d.div(q));
+				u[i]=new BIG(0);
+			}
+			u[0].copy(e);
+			for (i=0;i<4;i++)
+				for (j=0;j<4;j++)
+				{
+					t.copy(new BIG(ROM.CURVE_BB[j][i]));
+					t.copy(BIG.modmul(v[j],t,q));
+					u[i].add(q);
+					u[i].sub(t);
+					u[i].mod(q);
+				}
+		}
+		else
+		{
+			BIG q=new BIG(ROM.CURVE_Order);
+			BIG x=new BIG(ROM.CURVE_Bnx);
+			BIG w=new BIG(e);
+			for (int i=0;i<3;i++)
+			{
+				u[i]=new BIG(w);
+				u[i].mod(x);
+				w.div(x);
+			}
+			u[3]=new BIG(w);
+			if (ECP.SIGN_OF_X==ECP.NEGATIVEX)
+			{
+				u[1].copy(BIG.modneg(u[1],q));
+				u[3].copy(BIG.modneg(u[3],q));
+			}
+		}
+		return u;
+	}	
+
+/* Multiply P by e in group G1 */
+	public static ECP G1mul(ECP P,BIG e)
+	{
+		ECP R;
+		if (USE_GLV)
+		{
+			//P.affine();
+			R=new ECP();
+			R.copy(P);
+			int i,np,nn;
+			ECP Q=new ECP();
+			Q.copy(P); Q.affine();
+			BIG q=new BIG(ROM.CURVE_Order);
+			FP cru=new FP(new BIG(ROM.CURVE_Cru));
+			BIG t=new BIG(0);
+			BIG[] u=glv(e);
+			Q.getx().mul(cru);
+
+			np=u[0].nbits();
+			t.copy(BIG.modneg(u[0],q));
+			nn=t.nbits();
+			if (nn<np)
+			{
+				u[0].copy(t);
+				R.neg();
+			}
+
+			np=u[1].nbits();
+			t.copy(BIG.modneg(u[1],q));
+			nn=t.nbits();
+			if (nn<np)
+			{
+				u[1].copy(t);
+				Q.neg();
+			}
+			u[0].norm();
+			u[1].norm();
+			R=R.mul2(u[0],Q,u[1]);
+			
+		}
+		else
+		{
+			R=P.mul(e);
+		}
+		return R;
+	}
+
+/* Multiply P by e in group G2 */
+	public static ECP2 G2mul(ECP2 P,BIG e)
+	{
+		ECP2 R;
+		if (USE_GS_G2)
+		{
+			ECP2[] Q=new ECP2[4];
+			FP2 f=new FP2(new BIG(ROM.Fra),new BIG(ROM.Frb));
+
+			if (ECP.SEXTIC_TWIST==ECP.M_TYPE)
+			{
+				f.inverse();
+				f.norm();
+			}
+
+			BIG q=new BIG(ROM.CURVE_Order);
+			BIG[] u=gs(e);
+
+			BIG t=new BIG(0);
+			int i,np,nn;
+			//P.affine();
+
+			Q[0]=new ECP2(); Q[0].copy(P);
+			for (i=1;i<4;i++)
+			{
+				Q[i]=new ECP2(); Q[i].copy(Q[i-1]);
+				Q[i].frob(f);
+			}
+			for (i=0;i<4;i++)
+			{
+				np=u[i].nbits();
+				t.copy(BIG.modneg(u[i],q));
+				nn=t.nbits();
+				if (nn<np)
+				{
+					u[i].copy(t);
+					Q[i].neg();
+				}
+				u[i].norm();	
+				//Q[i].affine();
+			}
+
+			R=ECP2.mul4(Q,u);
+		}
+		else
+		{
+			R=P.mul(e);
+		}
+		return R;
+	}
+
+/* f=f^e */
+/* Note that this method requires a lot of RAM! Better to use compressed XTR method, see FP4.java */
+	public static FP12 GTpow(FP12 d,BIG e)
+	{
+		FP12 r;
+		if (USE_GS_GT)
+		{
+			FP12[] g=new FP12[4];
+			FP2 f=new FP2(new BIG(ROM.Fra),new BIG(ROM.Frb));
+			BIG q=new BIG(ROM.CURVE_Order);
+			BIG t=new BIG(0);
+			int i,np,nn;
+			BIG[] u=gs(e);
+
+			g[0]=new FP12(d);
+			for (i=1;i<4;i++)
+			{
+				g[i]=new FP12(0); g[i].copy(g[i-1]);
+				g[i].frob(f);
+			}
+			for (i=0;i<4;i++)
+			{
+				np=u[i].nbits();
+				t.copy(BIG.modneg(u[i],q));
+				nn=t.nbits();
+				if (nn<np)
+				{
+					u[i].copy(t);
+					g[i].conj();
+				}
+				u[i].norm();
+			}
+			r=FP12.pow4(g,u);
+		}
+		else
+		{
+			r=d.pow(e);
+		}
+		return r;
+	}
+
+/* test group membership - no longer needed */
+/* with GT-Strong curve, now only check that m!=1, conj(m)*m==1, and m.m^{p^4}=m^{p^2} */
+/*
+	public static boolean GTmember(FP12 m)
+	{
+		if (m.isunity()) return false;
+		FP12 r=new FP12(m);
+		r.conj();
+		r.mul(m);
+		if (!r.isunity()) return false;
+
+		FP2 f=new FP2(new BIG(ROM.Fra),new BIG(ROM.Frb));
+
+		r.copy(m); r.frob(f); r.frob(f);
+		FP12 w=new FP12(r); w.frob(f); w.frob(f);
+		w.mul(m);
+		if (!ROM.GT_STRONG)
+		{
+			if (!w.equals(r)) return false;
+			BIG x=new BIG(ROM.CURVE_Bnx);
+			r.copy(m); w=r.pow(x); w=w.pow(x);
+			r.copy(w); r.sqr(); r.mul(w); r.sqr();
+			w.copy(m); w.frob(f);
+		}
+		return w.equals(r);
+	}
+*/
+/*
+	public static void main(String[] args) {
+		ECP Q=new ECP(new BIG(ROM.CURVE_Gx),new BIG(ROM.CURVE_Gy));
+		ECP2 P=new ECP2(new FP2(new BIG(ROM.CURVE_Pxa),new BIG(ROM.CURVE_Pxb)),new FP2(new BIG(ROM.CURVE_Pya),new BIG(ROM.CURVE_Pyb)));
+
+		BIG r=new BIG(ROM.CURVE_Order);
+		BIG xa=new BIG(ROM.CURVE_Pxa);
+
+		System.out.println("P= "+P.toString());
+		System.out.println("Q= "+Q.toString());
+
+		BIG m=new BIG(17);
+
+		FP12 e=ate(P,Q);
+		System.out.println("\ne= "+e.toString());
+
+		e=fexp(e);
+
+		for (int i=1;i<1000;i++)
+		{
+			e=ate(P,Q);
+			e=fexp(e);
+		}
+	//	e=GTpow(e,m);
+
+		System.out.println("\ne= "+e.toString());
+
+		BIG [] GLV=glv(r);
+
+		System.out.println("GLV[0]= "+GLV[0].toString());
+		System.out.println("GLV[0]= "+GLV[1].toString());
+
+		ECP G=new ECP(); G.copy(Q);
+		ECP2 R=new ECP2(); R.copy(P);
+
+
+		e=ate(R,Q);
+		e=fexp(e);
+
+		e=GTpow(e,xa);
+		System.out.println("\ne= "+e.toString()); 
+
+
+		R=G2mul(R,xa);
+		e=ate(R,G);
+		e=fexp(e);
+
+		System.out.println("\ne= "+e.toString());
+
+		G=G1mul(G,xa);
+		e=ate(P,G);
+		e=fexp(e);
+		System.out.println("\ne= "+e.toString()); 
+	} */
+}
+
diff --git a/version3/java/PAIR192.java b/version3/java/PAIR192.java
new file mode 100644
index 0000000..99a19d1
--- /dev/null
+++ b/version3/java/PAIR192.java
@@ -0,0 +1,550 @@
+/*
+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.
+*/
+
+/* AMCL BN Curve Pairing functions */
+
+package org.apache.milagro.amcl.XXX;
+
+public final class PAIR192 {
+
+	public static final boolean USE_GLV =true;
+	public static final boolean USE_GS_G2 =true;
+	public static final boolean USE_GS_GT =true;	
+	public static final boolean GT_STRONG=false;
+
+
+/* Line function */
+	public static FP24 line(ECP4 A,ECP4 B,FP Qx,FP Qy)
+	{
+//System.out.println("Into line");
+		FP8 a,b,c;                            // Edits here
+//		c=new FP8(0);
+		if (A==B)
+		{ // Doubling
+			FP4 XX=new FP4(A.getx());  //X
+			FP4 YY=new FP4(A.gety());  //Y
+			FP4 ZZ=new FP4(A.getz());  //Z
+			FP4 YZ=new FP4(YY);        //Y 
+			YZ.mul(ZZ);                //YZ
+			XX.sqr();	               //X^2
+			YY.sqr();	               //Y^2
+			ZZ.sqr();			       //Z^2
+			
+			YZ.imul(4);
+			YZ.neg(); YZ.norm();       //-2YZ
+			YZ.qmul(Qy);               //-2YZ.Ys
+
+			XX.imul(6);                //3X^2
+			XX.qmul(Qx);               //3X^2.Xs
+
+			int sb=3*ROM.CURVE_B_I;
+			ZZ.imul(sb); 	
+			
+			if (ECP.SEXTIC_TWIST==ECP.D_TYPE)
+			{
+				ZZ.div_2i();
+			}
+			if (ECP.SEXTIC_TWIST==ECP.M_TYPE)
+			{
+				ZZ.times_i();
+				ZZ.add(ZZ);
+				YZ.times_i();
+				YZ.norm();
+			}
+			
+			ZZ.norm(); // 3b.Z^2 
+
+			YY.add(YY);
+			ZZ.sub(YY); ZZ.norm();     // 3b.Z^2-Y^2
+
+			a=new FP8(YZ,ZZ);          // -2YZ.Ys | 3b.Z^2-Y^2 | 3X^2.Xs 
+			if (ECP.SEXTIC_TWIST==ECP.D_TYPE)
+			{			
+				b=new FP8(XX);             // L(0,1) | L(0,0) | L(1,0)
+				c=new FP8(0);
+			}
+			if (ECP.SEXTIC_TWIST==ECP.M_TYPE)
+			{
+				b=new FP8(0);
+				c=new FP8(XX); c.times_i();
+			}
+			A.dbl();
+		}
+		else
+		{ // Addition - assume B is affine
+
+			FP4 X1=new FP4(A.getx());    // X1
+			FP4 Y1=new FP4(A.gety());    // Y1
+			FP4 T1=new FP4(A.getz());    // Z1
+			FP4 T2=new FP4(A.getz());    // Z1
+			
+			T1.mul(B.gety());    // T1=Z1.Y2 
+			T2.mul(B.getx());    // T2=Z1.X2
+
+			X1.sub(T2); X1.norm();  // X1=X1-Z1.X2
+			Y1.sub(T1); Y1.norm();  // Y1=Y1-Z1.Y2
+
+			T1.copy(X1);            // T1=X1-Z1.X2
+			X1.qmul(Qy);            // X1=(X1-Z1.X2).Ys
+
+			if (ECP.SEXTIC_TWIST==ECP.M_TYPE)
+			{
+				X1.times_i();
+				X1.norm();
+			}
+
+			T1.mul(B.gety());       // T1=(X1-Z1.X2).Y2
+
+			T2.copy(Y1);            // T2=Y1-Z1.Y2
+			T2.mul(B.getx());       // T2=(Y1-Z1.Y2).X2
+			T2.sub(T1); T2.norm();          // T2=(Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2
+			Y1.qmul(Qx);  Y1.neg(); Y1.norm(); // Y1=-(Y1-Z1.Y2).Xs
+
+			a=new FP8(X1,T2);       // (X1-Z1.X2).Ys  |  (Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2  | - (Y1-Z1.Y2).Xs
+			if (ECP.SEXTIC_TWIST==ECP.D_TYPE)
+			{
+				b=new FP8(Y1);
+				c=new FP8(0);
+			}
+			if (ECP.SEXTIC_TWIST==ECP.M_TYPE)
+			{
+				b=new FP8(0);
+				c=new FP8(Y1); c.times_i();
+			}
+			A.add(B);
+		}
+//System.out.println("Out of line");
+		return new FP24(a,b,c);
+	}
+
+/* Optimal R-ate pairing */
+	public static FP24 ate(ECP4 P1,ECP Q1)
+	{
+		FP2 f;
+		BIG x=new BIG(ROM.CURVE_Bnx);
+		BIG n=new BIG(x);
+		FP24 lv;
+		int bt;
+		
+		ECP4 P=new ECP4(P1);
+		ECP Q=new ECP(Q1);
+
+		P.affine();
+		Q.affine();
+
+		BIG n3=new BIG(n);
+		n3.pmul(3);
+		n3.norm();
+
+		FP Qx=new FP(Q.getx());
+		FP Qy=new FP(Q.gety());
+
+		ECP4 A=new ECP4();
+		FP24 r=new FP24(1);
+		A.copy(P);
+
+		ECP4 MP=new ECP4();
+		MP.copy(P); MP.neg();
+
+		int nb=n3.nbits();
+
+		for (int i=nb-2;i>=1;i--)
+		{
+			r.sqr();
+			lv=line(A,A,Qx,Qy);
+			r.smul(lv,ECP.SEXTIC_TWIST);
+
+			bt=n3.bit(i)-n.bit(i); // bt=n.bit(i);
+			if (bt==1)
+			{
+				lv=line(A,P,Qx,Qy);
+				r.smul(lv,ECP.SEXTIC_TWIST);
+			}
+			if (bt==-1)
+			{
+				//P.neg();
+				lv=line(A,MP,Qx,Qy);
+				r.smul(lv,ECP.SEXTIC_TWIST);
+				//P.neg();
+			}
+		}
+
+		if (ECP.SIGN_OF_X==ECP.NEGATIVEX)
+		{
+			r.conj();
+		}
+
+		return r;
+	}
+
+/* Optimal R-ate double pairing e(P,Q).e(R,S) */
+	public static FP24 ate2(ECP4 P1,ECP Q1,ECP4 R1,ECP S1)
+	{
+		FP2 f;
+		BIG x=new BIG(ROM.CURVE_Bnx);
+		BIG n=new BIG(x);
+		FP24 lv;
+		int bt;
+
+		ECP4 P=new ECP4(P1);
+		ECP Q=new ECP(Q1);
+
+		P.affine();
+		Q.affine();
+
+		ECP4 R=new ECP4(R1);
+		ECP S=new ECP(S1);
+
+		R.affine();
+		S.affine();
+
+
+		BIG n3=new BIG(n);
+		n3.pmul(3);
+		n3.norm();
+
+		FP Qx=new FP(Q.getx());
+		FP Qy=new FP(Q.gety());
+		FP Sx=new FP(S.getx());
+		FP Sy=new FP(S.gety());
+
+		ECP4 A=new ECP4();
+		ECP4 B=new ECP4();
+		FP24 r=new FP24(1);
+
+		A.copy(P);
+		B.copy(R);
+
+		ECP4 MP=new ECP4();
+		MP.copy(P); MP.neg();
+		ECP4 MR=new ECP4();
+		MR.copy(R); MR.neg();
+
+
+		int nb=n3.nbits();
+
+		for (int i=nb-2;i>=1;i--)
+		{
+			r.sqr();
+			lv=line(A,A,Qx,Qy);
+			r.smul(lv,ECP.SEXTIC_TWIST);
+
+			lv=line(B,B,Sx,Sy);
+			r.smul(lv,ECP.SEXTIC_TWIST);
+
+			bt=n3.bit(i)-n.bit(i); // bt=n.bit(i);
+			if (bt==1)
+			{
+				lv=line(A,P,Qx,Qy);
+				r.smul(lv,ECP.SEXTIC_TWIST);
+				lv=line(B,R,Sx,Sy);
+				r.smul(lv,ECP.SEXTIC_TWIST);
+			}
+			if (bt==-1)
+			{
+				//P.neg(); 
+				lv=line(A,MP,Qx,Qy);
+				r.smul(lv,ECP.SEXTIC_TWIST);
+				//P.neg(); 
+				//R.neg();
+				lv=line(B,MR,Sx,Sy);
+				r.smul(lv,ECP.SEXTIC_TWIST);
+				//R.neg();
+			}
+		}
+
+		if (ECP.SIGN_OF_X==ECP.NEGATIVEX)
+		{
+			r.conj();
+		}
+
+		return r;
+	}
+
+/* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */
+	public static FP24 fexp(FP24 m)
+	{
+		FP2 f=new FP2(new BIG(ROM.Fra),new BIG(ROM.Frb));
+		BIG x=new BIG(ROM.CURVE_Bnx);
+		FP24 r=new FP24(m);
+
+/* Easy part of final exp */
+		FP24 lv=new FP24(r);
+		lv.inverse();
+		r.conj();
+
+		r.mul(lv);
+		lv.copy(r);
+		r.frob(f,4);
+		r.mul(lv);
+
+		FP24 t0,t1,t2,t3,t4,t5,t6,t7;
+/* Hard part of final exp */	
+// Ghamman & Fouotsa Method
+
+		t7=new FP24(r); t7.usqr();
+		t1=t7.pow(x);
+
+		x.fshr(1);
+		t2=t1.pow(x);
+		x.fshl(1);
+
+		if (ECP.SIGN_OF_X==ECP.NEGATIVEX) {
+			t1.conj();
+		}
+		t3=new FP24(t1); t3.conj();
+		t2.mul(t3);
+		t2.mul(r);
+
+		t3=t2.pow(x);
+		t4=t3.pow(x);
+		t5=t4.pow(x);
+
+		if (ECP.SIGN_OF_X==ECP.NEGATIVEX) {
+			t3.conj(); t5.conj();
+		}
+
+		t3.frob(f,6); t4.frob(f,5);
+		t3.mul(t4);
+
+		t6=t5.pow(x);
+		if (ECP.SIGN_OF_X==ECP.NEGATIVEX) {
+			t6.conj();
+		}
+
+		t5.frob(f,4);
+		t3.mul(t5);
+
+		t0=new FP24(t2); t0.conj();
+		t6.mul(t0);
+
+		t5.copy(t6);
+		t5.frob(f,3);
+
+		t3.mul(t5);
+		t5=t6.pow(x);
+		t6=t5.pow(x);
+
+		if (ECP.SIGN_OF_X==ECP.NEGATIVEX) {
+			t5.conj();
+		}
+
+		t0.copy(t5);
+		t0.frob(f,2);
+		t3.mul(t0);
+		t0.copy(t6);
+		t0.frob(f,1);
+
+		t3.mul(t0);
+		t5=t6.pow(x);
+
+		if (ECP.SIGN_OF_X==ECP.NEGATIVEX) {
+			t5.conj();
+		}
+		t2.frob(f,7);
+
+		t5.mul(t7);
+		t3.mul(t2);
+		t3.mul(t5);
+
+		r.mul(t3);
+
+		r.reduce();
+		return r;
+	}
+
+/* GLV method */
+	public static BIG[] glv(BIG e)
+	{
+		BIG[] u=new BIG[2];
+// -(x^4).P = (Beta.x,y)
+		BIG q=new BIG(ROM.CURVE_Order);
+		BIG x=new BIG(ROM.CURVE_Bnx);
+		BIG x2=BIG.smul(x,x);
+		x=BIG.smul(x2,x2);
+		u[0]=new BIG(e);
+		u[0].mod(x);
+		u[1]=new BIG(e);
+		u[1].div(x);
+		u[1].rsub(q);
+
+		return u;
+	}
+
+/* Galbraith & Scott Method */
+	public static BIG[] gs(BIG e)
+	{
+		BIG[] u=new BIG[8];
+
+		BIG q=new BIG(ROM.CURVE_Order);
+		BIG x=new BIG(ROM.CURVE_Bnx);
+		BIG w=new BIG(e);
+		for (int i=0;i<7;i++)
+		{
+			u[i]=new BIG(w);
+			u[i].mod(x);
+			w.div(x);
+		}
+		u[7]=new BIG(w);
+		if (ECP.SIGN_OF_X==ECP.NEGATIVEX)
+		{
+			u[1].copy(BIG.modneg(u[1],q));
+			u[3].copy(BIG.modneg(u[3],q));
+			u[5].copy(BIG.modneg(u[5],q));
+			u[7].copy(BIG.modneg(u[7],q));
+		}
+
+		return u;
+	}	
+
+/* Multiply P by e in group G1 */
+	public static ECP G1mul(ECP P,BIG e)
+	{
+		ECP R;
+		if (USE_GLV)
+		{
+			//P.affine();
+			R=new ECP();
+			R.copy(P);
+			int i,np,nn;
+			ECP Q=new ECP();
+			Q.copy(P); Q.affine();
+			BIG q=new BIG(ROM.CURVE_Order);
+			FP cru=new FP(new BIG(ROM.CURVE_Cru));
+			BIG t=new BIG(0);
+			BIG[] u=glv(e);
+			Q.getx().mul(cru);
+
+			np=u[0].nbits();
+			t.copy(BIG.modneg(u[0],q));
+			nn=t.nbits();
+			if (nn<np)
+			{
+				u[0].copy(t);
+				R.neg();
+			}
+
+			np=u[1].nbits();
+			t.copy(BIG.modneg(u[1],q));
+			nn=t.nbits();
+			if (nn<np)
+			{
+				u[1].copy(t);
+				Q.neg();
+			}
+			u[0].norm();
+			u[1].norm();
+			R=R.mul2(u[0],Q,u[1]);
+			
+		}
+		else
+		{
+			R=P.mul(e);
+		}
+		return R;
+	}
+
+/* Multiply P by e in group G2 */
+	public static ECP4 G2mul(ECP4 P,BIG e)
+	{
+		ECP4 R;
+		if (USE_GS_G2)
+		{
+			ECP4[] Q=new ECP4[8];
+			FP2[] F=ECP4.frob_constants();
+
+			BIG q=new BIG(ROM.CURVE_Order);
+			BIG[] u=gs(e);
+
+			BIG t=new BIG(0);
+			int i,np,nn;
+			//P.affine();
+
+			Q[0]=new ECP4(); Q[0].copy(P);
+			for (i=1;i<8;i++)
+			{
+				Q[i]=new ECP4(); Q[i].copy(Q[i-1]);
+				Q[i].frob(F,1);
+			}
+			for (i=0;i<8;i++)
+			{
+				np=u[i].nbits();
+				t.copy(BIG.modneg(u[i],q));
+				nn=t.nbits();
+				if (nn<np)
+				{
+					u[i].copy(t);
+					Q[i].neg();
+				}
+				u[i].norm();	
+				//Q[i].affine();
+			}
+
+			R=ECP4.mul8(Q,u);
+		}
+		else
+		{
+			R=P.mul(e);
+		}
+		return R;
+	}
+
+/* f=f^e */
+/* Note that this method requires a lot of RAM! Better to use compressed XTR method, see FP8.java */
+	public static FP24 GTpow(FP24 d,BIG e)
+	{
+		FP24 r;
+		if (USE_GS_GT)
+		{
+			FP24[] g=new FP24[8];
+			FP2 f=new FP2(new BIG(ROM.Fra),new BIG(ROM.Frb));
+			BIG q=new BIG(ROM.CURVE_Order);
+			BIG t=new BIG(0);
+			int i,np,nn;
+			BIG[] u=gs(e);
+
+			g[0]=new FP24(d);
+			for (i=1;i<8;i++)
+			{
+				g[i]=new FP24(0); g[i].copy(g[i-1]);
+				g[i].frob(f,1);
+			}
+			for (i=0;i<8;i++)
+			{
+				np=u[i].nbits();
+				t.copy(BIG.modneg(u[i],q));
+				nn=t.nbits();
+				if (nn<np)
+				{
+					u[i].copy(t);
+					g[i].conj();
+				}
+				u[i].norm();
+			}
+			r=FP24.pow8(g,u);
+		}
+		else
+		{
+			r=d.pow(e);
+		}
+		return r;
+	}
+
+}
+
diff --git a/version3/java/PAIR256.java b/version3/java/PAIR256.java
new file mode 100644
index 0000000..cdf2f02
--- /dev/null
+++ b/version3/java/PAIR256.java
@@ -0,0 +1,628 @@
+/*
+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.
+*/
+
+/* AMCL BN Curve Pairing functions */
+
+package org.apache.milagro.amcl.XXX;
+
+public final class PAIR256 {
+
+	public static final boolean USE_GLV =true;
+	public static final boolean USE_GS_G2 =true;
+	public static final boolean USE_GS_GT =true;	
+	public static final boolean GT_STRONG=false;
+
+
+/* Line function */
+	public static FP48 line(ECP8 A,ECP8 B,FP Qx,FP Qy)
+	{
+//System.out.println("Into line");
+		FP16 a,b,c;                            // Edits here
+//		c=new FP16(0);
+		if (A==B)
+		{ // Doubling
+			FP8 XX=new FP8(A.getx());  //X
+			FP8 YY=new FP8(A.gety());  //Y
+			FP8 ZZ=new FP8(A.getz());  //Z
+			FP8 YZ=new FP8(YY);        //Y 
+			YZ.mul(ZZ);                //YZ
+			XX.sqr();	               //X^2
+			YY.sqr();	               //Y^2
+			ZZ.sqr();			       //Z^2
+			
+			YZ.imul(4);
+			YZ.neg(); YZ.norm();       //-2YZ
+			YZ.tmul(Qy);               //-2YZ.Ys
+
+			XX.imul(6);                //3X^2
+			XX.tmul(Qx);               //3X^2.Xs
+
+			int sb=3*ROM.CURVE_B_I;
+			ZZ.imul(sb); 	
+			
+			if (ECP.SEXTIC_TWIST==ECP.D_TYPE)
+			{
+				ZZ.div_2i();
+			}
+			if (ECP.SEXTIC_TWIST==ECP.M_TYPE)
+			{
+				ZZ.times_i();
+				ZZ.add(ZZ);
+				YZ.times_i();
+				YZ.norm();
+			}
+			
+			ZZ.norm(); // 3b.Z^2 
+
+			YY.add(YY);
+			ZZ.sub(YY); ZZ.norm();     // 3b.Z^2-Y^2
+
+			a=new FP16(YZ,ZZ);          // -2YZ.Ys | 3b.Z^2-Y^2 | 3X^2.Xs 
+			if (ECP.SEXTIC_TWIST==ECP.D_TYPE)
+			{			
+				b=new FP16(XX);             // L(0,1) | L(0,0) | L(1,0)
+				c=new FP16(0);
+			}
+			if (ECP.SEXTIC_TWIST==ECP.M_TYPE)
+			{
+				b=new FP16(0);
+				c=new FP16(XX); c.times_i();
+			}
+			A.dbl();
+		}
+		else
+		{ // Addition - assume B is affine
+
+			FP8 X1=new FP8(A.getx());    // X1
+			FP8 Y1=new FP8(A.gety());    // Y1
+			FP8 T1=new FP8(A.getz());    // Z1
+			FP8 T2=new FP8(A.getz());    // Z1
+			
+			T1.mul(B.gety());    // T1=Z1.Y2 
+			T2.mul(B.getx());    // T2=Z1.X2
+
+			X1.sub(T2); X1.norm();  // X1=X1-Z1.X2
+			Y1.sub(T1); Y1.norm();  // Y1=Y1-Z1.Y2
+
+			T1.copy(X1);            // T1=X1-Z1.X2
+			X1.tmul(Qy);            // X1=(X1-Z1.X2).Ys
+
+			if (ECP.SEXTIC_TWIST==ECP.M_TYPE)
+			{
+				X1.times_i();
+				X1.norm();
+			}
+
+			T1.mul(B.gety());       // T1=(X1-Z1.X2).Y2
+
+			T2.copy(Y1);            // T2=Y1-Z1.Y2
+			T2.mul(B.getx());       // T2=(Y1-Z1.Y2).X2
+			T2.sub(T1); T2.norm();          // T2=(Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2
+			Y1.tmul(Qx);  Y1.neg(); Y1.norm(); // Y1=-(Y1-Z1.Y2).Xs
+
+			a=new FP16(X1,T2);       // (X1-Z1.X2).Ys  |  (Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2  | - (Y1-Z1.Y2).Xs
+			if (ECP.SEXTIC_TWIST==ECP.D_TYPE)
+			{
+				b=new FP16(Y1);
+				c=new FP16(0);
+			}
+			if (ECP.SEXTIC_TWIST==ECP.M_TYPE)
+			{
+				b=new FP16(0);
+				c=new FP16(Y1); c.times_i();
+			}
+			A.add(B);
+		}
+//System.out.println("Out of line");
+		return new FP48(a,b,c);
+	}
+
+/* Optimal R-ate pairing */
+	public static FP48 ate(ECP8 P1,ECP Q1)
+	{
+		FP2 f;
+		BIG x=new BIG(ROM.CURVE_Bnx);
+		BIG n=new BIG(x);
+		FP48 lv;
+		int bt;
+		
+		ECP8 P=new ECP8(P1);
+		ECP Q=new ECP(Q1);
+
+		P.affine();
+		Q.affine();
+
+
+		BIG n3=new BIG(n);
+		n3.pmul(3);
+		n3.norm();
+
+		FP Qx=new FP(Q.getx());
+		FP Qy=new FP(Q.gety());
+
+		ECP8 A=new ECP8();
+		FP48 r=new FP48(1);
+		A.copy(P);
+
+		ECP8 MP=new ECP8();
+		MP.copy(P); MP.neg();
+
+		int nb=n3.nbits();
+
+		for (int i=nb-2;i>=1;i--)
+		{
+			r.sqr();
+			lv=line(A,A,Qx,Qy);
+			r.smul(lv,ECP.SEXTIC_TWIST);
+
+			bt=n3.bit(i)-n.bit(i); // bt=n.bit(i);
+			if (bt==1)
+			{
+				lv=line(A,P,Qx,Qy);
+				r.smul(lv,ECP.SEXTIC_TWIST);
+			}
+			if (bt==-1)
+			{
+				//P.neg();
+				lv=line(A,MP,Qx,Qy);
+				r.smul(lv,ECP.SEXTIC_TWIST);
+				//P.neg();
+			}
+		}
+
+		if (ECP.SIGN_OF_X==ECP.NEGATIVEX)
+		{
+			r.conj();
+		}
+
+		return r;
+	}
+
+/* Optimal R-ate double pairing e(P,Q).e(R,S) */
+	public static FP48 ate2(ECP8 P1,ECP Q1,ECP8 R1,ECP S1)
+	{
+		FP2 f;
+		BIG x=new BIG(ROM.CURVE_Bnx);
+		BIG n=new BIG(x);
+		FP48 lv;
+		int bt;
+
+		ECP8 P=new ECP8(P1);
+		ECP Q=new ECP(Q1);
+
+		P.affine();
+		Q.affine();
+
+		ECP8 R=new ECP8(R1);
+		ECP S=new ECP(S1);
+
+		R.affine();
+		S.affine();
+
+		BIG n3=new BIG(n);
+		n3.pmul(3);
+		n3.norm();
+
+		FP Qx=new FP(Q.getx());
+		FP Qy=new FP(Q.gety());
+		FP Sx=new FP(S.getx());
+		FP Sy=new FP(S.gety());
+
+		ECP8 A=new ECP8();
+		ECP8 B=new ECP8();
+		FP48 r=new FP48(1);
+
+		A.copy(P);
+		B.copy(R);
+
+		ECP8 MP=new ECP8();
+		MP.copy(P); MP.neg();
+		ECP8 MR=new ECP8();
+		MR.copy(R); MR.neg();
+
+
+		int nb=n3.nbits();
+
+		for (int i=nb-2;i>=1;i--)
+		{
+			r.sqr();
+			lv=line(A,A,Qx,Qy);
+			r.smul(lv,ECP.SEXTIC_TWIST);
+
+			lv=line(B,B,Sx,Sy);
+			r.smul(lv,ECP.SEXTIC_TWIST);
+
+			bt=n3.bit(i)-n.bit(i); // bt=n.bit(i);
+			if (bt==1)
+			{
+				lv=line(A,P,Qx,Qy);
+				r.smul(lv,ECP.SEXTIC_TWIST);
+				lv=line(B,R,Sx,Sy);
+				r.smul(lv,ECP.SEXTIC_TWIST);
+			}
+			if (bt==-1)
+			{
+				//P.neg(); 
+				lv=line(A,MP,Qx,Qy);
+				r.smul(lv,ECP.SEXTIC_TWIST);
+				//P.neg(); 
+				//R.neg();
+				lv=line(B,MR,Sx,Sy);
+				r.smul(lv,ECP.SEXTIC_TWIST);
+				//R.neg();
+			}
+		}
+
+		if (ECP.SIGN_OF_X==ECP.NEGATIVEX)
+		{
+			r.conj();
+		}
+
+		return r;
+	}
+
+/* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */
+	public static FP48 fexp(FP48 m)
+	{
+		FP2 f=new FP2(new BIG(ROM.Fra),new BIG(ROM.Frb));
+		BIG x=new BIG(ROM.CURVE_Bnx);
+		FP48 r=new FP48(m);
+
+/* Easy part of final exp */
+		FP48 lv=new FP48(r);
+		lv.inverse();
+		r.conj();
+
+		r.mul(lv);
+		lv.copy(r);
+		r.frob(f,8);
+		r.mul(lv);
+
+		FP48 t0,t1,t2,t3,t4,t5,t6,t7;
+/* Hard part of final exp */	
+// Ghamman & Fouotsa Method
+
+		t7=new FP48(r); t7.usqr();
+		t1=t7.pow(x);
+
+		x.fshr(1);
+		t2=t1.pow(x);
+		x.fshl(1);
+
+		if (ECP.SIGN_OF_X==ECP.NEGATIVEX) {
+			t1.conj();
+		}
+
+		t3=new FP48(t1); t3.conj();
+		t2.mul(t3);
+		t2.mul(r);
+
+		r.mul(t7);
+
+		t1=t2.pow(x);
+		if (ECP.SIGN_OF_X==ECP.NEGATIVEX) {
+			t1.conj();
+		}
+		t3.copy(t1);
+		t3.frob(f,14);
+		r.mul(t3);
+		t1=t1.pow(x);
+		if (ECP.SIGN_OF_X==ECP.NEGATIVEX) {
+			t1.conj();
+		}
+
+		t3.copy(t1);
+		t3.frob(f,13);
+		r.mul(t3);
+		t1=t1.pow(x);
+		if (ECP.SIGN_OF_X==ECP.NEGATIVEX) {
+			t1.conj();
+		}
+
+		t3.copy(t1);
+		t3.frob(f,12);
+		r.mul(t3);
+		t1=t1.pow(x);
+		if (ECP.SIGN_OF_X==ECP.NEGATIVEX) {
+			t1.conj();
+		}
+
+		t3.copy(t1);
+		t3.frob(f,11);
+		r.mul(t3);
+		t1=t1.pow(x);
+		if (ECP.SIGN_OF_X==ECP.NEGATIVEX) {
+			t1.conj();
+		}
+
+		t3.copy(t1);
+		t3.frob(f,10);
+		r.mul(t3);
+		t1=t1.pow(x);
+		if (ECP.SIGN_OF_X==ECP.NEGATIVEX) {
+			t1.conj();
+		}
+
+		t3.copy(t1);
+		t3.frob(f,9);
+		r.mul(t3);
+		t1=t1.pow(x);
+		if (ECP.SIGN_OF_X==ECP.NEGATIVEX) {
+			t1.conj();
+		}
+
+		t3.copy(t1);
+		t3.frob(f,8);
+		r.mul(t3);
+		t1=t1.pow(x);
+		if (ECP.SIGN_OF_X==ECP.NEGATIVEX) {
+			t1.conj();
+		}
+
+		t3.copy(t2); t3.conj();
+		t1.mul(t3);
+		t3.copy(t1);
+		t3.frob(f,7);
+		r.mul(t3);
+		t1=t1.pow(x);
+		if (ECP.SIGN_OF_X==ECP.NEGATIVEX) {
+			t1.conj();
+		}
+
+		t3.copy(t1);
+		t3.frob(f,6);
+		r.mul(t3);
+		t1=t1.pow(x);
+		if (ECP.SIGN_OF_X==ECP.NEGATIVEX) {
+			t1.conj();
+		}
+
+		t3.copy(t1);
+		t3.frob(f,5);
+		r.mul(t3);
+		t1=t1.pow(x);
+		if (ECP.SIGN_OF_X==ECP.NEGATIVEX) {
+			t1.conj();
+		}
+
+		t3.copy(t1);
+		t3.frob(f,4);
+		r.mul(t3);
+		t1=t1.pow(x);
+		if (ECP.SIGN_OF_X==ECP.NEGATIVEX) {
+			t1.conj();
+		}
+
+		t3.copy(t1);
+		t3.frob(f,3);
+		r.mul(t3);
+		t1=t1.pow(x);
+		if (ECP.SIGN_OF_X==ECP.NEGATIVEX) {
+			t1.conj();
+		}
+
+		t3.copy(t1);
+		t3.frob(f,2);
+		r.mul(t3);
+		t1=t1.pow(x);
+		if (ECP.SIGN_OF_X==ECP.NEGATIVEX) {
+			t1.conj();
+		}
+
+		t3.copy(t1);
+		t3.frob(f,1);
+		r.mul(t3);
+		t1=t1.pow(x);
+		if (ECP.SIGN_OF_X==ECP.NEGATIVEX) {
+			t1.conj();
+		}
+	
+		r.mul(t1);
+		t2.frob(f,15);
+		r.mul(t2);
+
+		r.reduce();
+		return r;
+	}
+
+/* GLV method */
+	public static BIG[] glv(BIG e)
+	{
+		BIG[] u=new BIG[2];
+// -(x^8).P = (Beta.x,y)
+		BIG q=new BIG(ROM.CURVE_Order);
+		BIG x=new BIG(ROM.CURVE_Bnx);
+		BIG x2=BIG.smul(x,x);
+		x=BIG.smul(x2,x2);
+		x2=BIG.smul(x,x);
+		u[0]=new BIG(e);
+		u[0].mod(x2);
+		u[1]=new BIG(e);
+		u[1].div(x2);
+		u[1].rsub(q);
+
+		return u;
+	}
+
+/* Galbraith & Scott Method */
+	public static BIG[] gs(BIG e)
+	{
+		BIG[] u=new BIG[16];
+
+		BIG q=new BIG(ROM.CURVE_Order);
+		BIG x=new BIG(ROM.CURVE_Bnx);
+		BIG w=new BIG(e);
+		for (int i=0;i<15;i++)
+		{
+			u[i]=new BIG(w);
+			u[i].mod(x);
+			w.div(x);
+		}
+		u[15]=new BIG(w);
+		if (ECP.SIGN_OF_X==ECP.NEGATIVEX)
+		{
+			u[1].copy(BIG.modneg(u[1],q));
+			u[3].copy(BIG.modneg(u[3],q));
+			u[5].copy(BIG.modneg(u[5],q));
+			u[7].copy(BIG.modneg(u[7],q));
+			u[9].copy(BIG.modneg(u[9],q));
+			u[11].copy(BIG.modneg(u[11],q));
+			u[13].copy(BIG.modneg(u[13],q));
+			u[15].copy(BIG.modneg(u[15],q));
+		}
+
+		return u;
+	}	
+
+/* Multiply P by e in group G1 */
+	public static ECP G1mul(ECP P,BIG e)
+	{
+		ECP R;
+		if (USE_GLV)
+		{
+			//P.affine();
+			R=new ECP();
+			R.copy(P);
+			int i,np,nn;
+			ECP Q=new ECP(); 
+			Q.copy(P); Q.affine();
+			BIG q=new BIG(ROM.CURVE_Order);
+			FP cru=new FP(new BIG(ROM.CURVE_Cru));
+			BIG t=new BIG(0);
+			BIG[] u=glv(e);
+			Q.getx().mul(cru);
+
+			np=u[0].nbits();
+			t.copy(BIG.modneg(u[0],q));
+			nn=t.nbits();
+			if (nn<np)
+			{
+				u[0].copy(t);
+				R.neg();
+			}
+
+			np=u[1].nbits();
+			t.copy(BIG.modneg(u[1],q));
+			nn=t.nbits();
+			if (nn<np)
+			{
+				u[1].copy(t);
+				Q.neg();
+			}
+			u[0].norm();
+			u[1].norm();
+			R=R.mul2(u[0],Q,u[1]);
+			
+		}
+		else
+		{
+			R=P.mul(e);
+		}
+		return R;
+	}
+
+/* Multiply P by e in group G2 */
+	public static ECP8 G2mul(ECP8 P,BIG e)
+	{
+		ECP8 R;
+		if (USE_GS_G2)
+		{
+			ECP8[] Q=new ECP8[16];
+			FP2[] F=ECP8.frob_constants();
+
+			BIG q=new BIG(ROM.CURVE_Order);
+			BIG[] u=gs(e);
+
+			BIG t=new BIG(0);
+			int i,np,nn;
+			//P.affine();
+
+			Q[0]=new ECP8(); Q[0].copy(P);
+			for (i=1;i<16;i++)
+			{
+				Q[i]=new ECP8(); Q[i].copy(Q[i-1]);
+				Q[i].frob(F,1);
+			}
+			for (i=0;i<16;i++)
+			{
+				np=u[i].nbits();
+				t.copy(BIG.modneg(u[i],q));
+				nn=t.nbits();
+				if (nn<np)
+				{
+					u[i].copy(t);
+					Q[i].neg();
+				}
+				u[i].norm();
+				//Q[i].affine();
+			}
+
+			R=ECP8.mul16(Q,u);
+		}
+		else
+		{
+			R=P.mul(e);
+		}
+		return R;
+	}
+
+/* f=f^e */
+/* Note that this method requires a lot of RAM! Better to use compressed XTR method, see FP16.java */
+	public static FP48 GTpow(FP48 d,BIG e)
+	{
+		FP48 r;
+		if (USE_GS_GT)
+		{
+			FP48[] g=new FP48[16];
+			FP2 f=new FP2(new BIG(ROM.Fra),new BIG(ROM.Frb));
+			BIG q=new BIG(ROM.CURVE_Order);
+			BIG t=new BIG(0);
+			int i,np,nn;
+			BIG[] u=gs(e);
+
+			g[0]=new FP48(d);
+			for (i=1;i<16;i++)
+			{
+				g[i]=new FP48(0); g[i].copy(g[i-1]);
+				g[i].frob(f,1);
+			}
+			for (i=0;i<16;i++)
+			{
+				np=u[i].nbits();
+				t.copy(BIG.modneg(u[i],q));
+				nn=t.nbits();
+				if (nn<np)
+				{
+					u[i].copy(t);
+					g[i].conj();
+				}
+				u[i].norm();
+			}
+			r=FP48.pow16(g,u);
+		}
+		else
+		{
+			r=d.pow(e);
+		}
+		return r;
+	}
+
+
+}
+
diff --git a/version3/java/RAND.java b/version3/java/RAND.java
new file mode 100644
index 0000000..7ba7064
--- /dev/null
+++ b/version3/java/RAND.java
@@ -0,0 +1,163 @@
+/*
+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.
+*/
+
+/*
+ *   Cryptographic strong random number generator 
+ *
+ *   Unguessable seed -> SHA -> PRNG internal state -> SHA -> random numbers
+ *   Slow - but secure
+ *
+ *   See ftp://ftp.rsasecurity.com/pub/pdfs/bull-1.pdf for a justification
+ */
+
+/* Marsaglia & Zaman Random number generator constants */
+
+
+package org.apache.milagro.amcl;
+
+public class RAND {
+/* Cryptographically strong pseudo-random number generator */
+
+	private static final int NK=21;
+	private static final int NJ=6;
+	private static final int NV=8;
+	private int[] ira=new int[NK];  /* random number...   */
+	private int rndptr;   /* ...array & pointer */
+	private int borrow;
+	private int pool_ptr;
+	private byte[] pool=new byte[32];    /* random pool */
+
+	public RAND()
+	{
+		clean();
+	}
+
+	private int sbrand()
+	{ /* Marsaglia & Zaman random number generator */
+		int i,k;
+		long pdiff,t;
+
+		rndptr++;
+		if (rndptr<NK) return ira[rndptr];
+		rndptr=0;
+		for (i=0,k=NK-NJ;i<NK;i++,k++)
+		{ /* calculate next NK values */
+			if (k==NK) k=0;
+			t=((long)ira[k])&0xffffffffL;
+			pdiff=(t - (((long)ira[i])&0xffffffffL) - (long)borrow)&0xffffffffL;
+			if (pdiff<t) borrow=0;
+			if (pdiff>t) borrow=1;
+			ira[i]=(int)(pdiff&0xffffffffL); 
+		}
+
+		return ira[0];
+	}
+
+	public void sirand(int seed)
+	{
+		int i,in;
+		int t,m=1;
+		borrow=0;
+		rndptr=0;
+		ira[0]^=seed;
+		for (i=1;i<NK;i++)
+		{ /* fill initialisation vector */
+			in=(NV*i)%NK;
+			ira[in]^=m;      /* note XOR */
+			t=m;
+			m=seed-m;
+			seed=t;
+		}
+		for (i=0;i<10000;i++) sbrand(); /* "warm-up" & stir the generator */
+	}
+
+	private void fill_pool()
+	{
+		HASH256 sh=new HASH256();
+		for (int i=0;i<128;i++) sh.process(sbrand());
+		pool=sh.hash();
+		pool_ptr=0;
+	}
+
+	private static int pack(byte[] b)
+	{ /* pack 4 bytes into a 32-bit Word */
+		return ((((int)b[3])&0xff)<<24)|(((int)b[2]&0xff)<<16)|(((int)b[1]&0xff)<<8)|((int)b[0]&0xff);
+	}
+
+/* Initialize RNG with some real entropy from some external source */
+	public void seed(int rawlen,byte[] raw)
+	{ /* initialise from at least 128 byte string of raw random entropy */
+		int i;
+		byte [] digest;
+		byte [] b=new byte[4];
+		HASH256 sh=new HASH256();
+		pool_ptr=0;
+		for (i=0;i<NK;i++) ira[i]=0;
+		if (rawlen>0)
+		{
+			for (i=0;i<rawlen;i++)
+				sh.process(raw[i]);
+			digest=sh.hash();
+
+/* initialise PRNG from distilled randomness */
+
+			for (i=0;i<8;i++) 
+			{
+				b[0]=digest[4*i]; b[1]=digest[4*i+1]; b[2]=digest[4*i+2]; b[3]=digest[4*i+3];
+				sirand(pack(b));
+			}
+		}
+		fill_pool();
+	}
+
+/* Terminate and clean up */
+	public void clean()
+	{ /* kill internal state */
+		int i;
+		pool_ptr=rndptr=0;
+		for (i=0;i<32;i++) pool[i]=0;
+		for (i=0;i<NK;i++) ira[i]=0;
+		borrow=0;
+	}
+
+/* get random byte */
+	public int getByte()
+	{ 
+		int r;
+		r=pool[pool_ptr++];
+		if (pool_ptr>=32) fill_pool();
+		return (r&0xff);
+	}
+
+/* test main program */
+/*
+	public static void main(String[] args) {
+		int i;
+		byte[] raw=new byte[100];
+		RAND rng=new RAND();
+
+		rng.clean();
+		for (i=0;i<100;i++) raw[i]=(byte)i;
+
+		rng.seed(100,raw);
+ 
+		for (i=0;i<1000;i++)
+			System.out.format("%03d ",rng.getByte());
+	} */
+}
diff --git a/version3/java/README.md b/version3/java/README.md
new file mode 100644
index 0000000..4b3d853
--- /dev/null
+++ b/version3/java/README.md
@@ -0,0 +1,27 @@
+Namespaces are used to separate different curves.
+
+To build the library and see it in action, execute the python3 scripts 
+config32.py or config64.py (depending on whether you want a 32 or 
+64-bit build), and select the curves that you wish to support. The 
+configured library can be built using maven. 
+
+Tests will take a while to  run.
+
+As a quick example copy to a working directory and execute
+
+py config64.py
+
+or perhaps
+
+python3 config64.py
+
+Choose options 1, 3, 7, 18, 20, 25, 26 and 27, for example.
+
+Once the library is configured, you can compile and install with maven:
+
+cd amcl
+mvn clean install
+
+Testing will be carried out during the installation process.
+
+*New* This library is now available directly on maven central
diff --git a/version3/java/ROM_ANSSI_32.java b/version3/java/ROM_ANSSI_32.java
new file mode 100644
index 0000000..ffd273c
--- /dev/null
+++ b/version3/java/ROM_ANSSI_32.java
@@ -0,0 +1,42 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.ANSSI;
+
+public class ROM
+{
+
+// Base Bits= 28
+	public static final int[] Modulus= {0x86E9C03,0xFCF353D,0x8CA6DE8,0xADBCABC,0x35B3961,0xE8CE424,0xF10126D,0xB3AD58,0x1FD178C,0xF};
+	public static final int[] R2modp= {0x288CC9C,0x18D2374,0x646BD2B,0x4929E67,0xD6F7F2D,0x220E6C1,0xABCE02E,0x751B1FD,0x7401B78,0xE};
+	public static final int MConst= 0x64E1155;
+
+	public static final int CURVE_Cof_I= 1;
+	public static final int[] CURVE_Cof= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int CURVE_A= -3;
+	public static final int CURVE_B_I= 0;
+	public static final int[] CURVE_B= {0xB7BB73F,0x75ED967,0x1A18030,0xC9AE4B,0xFDFEC,0x754A44C,0xD4ABA,0x5428A93,0xE353FCA,0xE};
+	public static final int[] CURVE_Order= {0x6D655E1,0xFDD459C,0x2BF941F,0x67E140D,0x35B53DC,0xE8CE424,0xF10126D,0xB3AD58,0x1FD178C,0xF};
+	public static final int[] CURVE_Gx= {0x98F5CFF,0xC97A2DD,0x8B70164,0xD2DCAF9,0x3958C27,0x4749D42,0xB31183D,0x56C139E,0x6B3D4C3,0xB};
+	public static final int[] CURVE_Gy= {0x4062CFB,0x115A155,0x4C9E183,0xC307E8E,0xF8C2701,0xF0F3ECE,0x11F9271,0xC8B2049,0x142E0F7,0x6};
+
+}
diff --git a/version3/java/ROM_ANSSI_64.java b/version3/java/ROM_ANSSI_64.java
new file mode 100644
index 0000000..5f0510f
--- /dev/null
+++ b/version3/java/ROM_ANSSI_64.java
@@ -0,0 +1,43 @@
+/*
+	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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.ANSSI;
+
+public class ROM
+{
+
+// Base Bits= 56
+	public static final long[] Modulus= {0xFCF353D86E9C03L,0xADBCABC8CA6DE8L,0xE8CE42435B3961L,0xB3AD58F10126DL,0xF1FD178CL};
+	public static final long[] R2modp= {0x18D2374288CC9CL,0x4929E67646BD2BL,0x220E6C1D6F7F2DL,0x751B1FDABCE02EL,0xE7401B78L};
+	public static final long MConst= 0x97483A164E1155L;
+
+	public static final int CURVE_Cof_I= 1;
+	public static final long[] CURVE_Cof= {0x1L,0x0L,0x0L,0x0L,0x0L};
+	public static final int CURVE_A= -3;
+	public static final int CURVE_B_I= 0;
+	public static final long[] CURVE_B= {0x75ED967B7BB73FL,0xC9AE4B1A18030L,0x754A44C00FDFECL,0x5428A9300D4ABAL,0xEE353FCAL};
+	public static final long[] CURVE_Order= {0xFDD459C6D655E1L,0x67E140D2BF941FL,0xE8CE42435B53DCL,0xB3AD58F10126DL,0xF1FD178CL};
+	public static final long[] CURVE_Gx= {0xC97A2DD98F5CFFL,0xD2DCAF98B70164L,0x4749D423958C27L,0x56C139EB31183DL,0xB6B3D4C3L};
+	public static final long[] CURVE_Gy= {0x115A1554062CFBL,0xC307E8E4C9E183L,0xF0F3ECEF8C2701L,0xC8B204911F9271L,0x6142E0F7L};
+
+}
+
diff --git a/version3/java/ROM_BLS24_32.java b/version3/java/ROM_BLS24_32.java
new file mode 100644
index 0000000..0ceb171
--- /dev/null
+++ b/version3/java/ROM_BLS24_32.java
@@ -0,0 +1,60 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.BLS24;
+
+public class ROM
+{
+
+// Base Bits= 29
+	public static final int[] Modulus= {0xA06152B,0x2260B3A,0xB4C36BE,0x5FFC5D0,0xBDB6A64,0x5B78E2E,0x1C1A28CA,0x10E6441B,0x1F244061,0xB4704F0,0x141E5CCD,0x9837504,0x3F2E77E,0xD763740,0x1316EA0E,0xF0079,0x555C};
+	public static final int[] R2modp= {0x8533EA9,0x6A02789,0x183B24DE,0x1E45ECF8,0xC8F8F37,0x10CAD209,0x4C0C4B8,0x9B1FABD,0xDEBE4C0,0xDC353F9,0x18A18E26,0x10F489BB,0x31206A5,0x19673BBF,0x6BE69F9,0xB091169,0x9CD};
+	public static final int MConst= 0x95FE7D;
+	public static final int[] Fra= {0x1BF96F1D,0xAE53A55,0x31BFEEB,0x183FF17A,0x6237469,0x12A4F4F1,0x12101FE3,0x16E79D94,0xFF59267,0x5EB4EB4,0x78CC49F,0x274BA33,0x149184F3,0x16C6DCBA,0x1C90B694,0x10F729CE,0x4BBC};
+	public static final int[] Frb= {0xE0CA60E,0x1740D0E4,0x83037D2,0xDBFD456,0x5B7F5FA,0x1312993D,0xA0A08E6,0x19FEA687,0xF2EADF9,0x55BB63C,0xC91982E,0x70EBAD1,0xF61628B,0x16AF5A85,0x16863379,0xF17D6AA,0x99F};
+
+	public static final int CURVE_A= 0;
+	public static final int CURVE_B_I= 19;
+	public static final int CURVE_Cof_I= 0;
+	public static final int[] CURVE_B= {0x13,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int[] CURVE_Order= {0x10000001,0xD047FF,0x1FD54464,0x1E3CE067,0xE322DDA,0x1D356F3F,0x7433B44,0x49091F9,0x1729CC2,0x250286C,0x16E62ED,0xB403E1E,0x1001000,0x80,0x0,0x0,0x0};
+	public static final int[] CURVE_Gx= {0xBE3CCD4,0x33B07AF,0x1B67D159,0x3DFC5B5,0xEBA1FCC,0x1A3C1F84,0x56BE204,0xEF8DF1B,0x11AE2D84,0x5FEE546,0x161B3BF9,0x183B20EE,0x1EA5D99B,0x14F0C5BF,0xBE521B7,0x17C682F9,0x1AB2};
+	public static final int[] CURVE_Gy= {0x121E5245,0x65D2E56,0x11577DB1,0x16DACC11,0x14F39746,0x459F694,0x12483FCF,0xC828B04,0xFD63E5A,0x7B1D52,0xAFDE738,0xF349254,0x1A4529FF,0x10E53353,0xF91DEE1,0x16E18D8A,0x47FC};
+
+	public static final int[] CURVE_Bnx= {0x11FF80,0x80010,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int[] CURVE_Cof= {0x19F415AB,0x1E0FFDFF,0x15AAADFF,0xAA,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int[] CURVE_Cru= {0xDD794A9,0x1DE138A3,0x2BCCE90,0xC746127,0x15223DDC,0x1DD8890B,0xED08DB7,0xE24B9F,0xE379CE6,0x37011AC,0x11BAC820,0x1EEFAD01,0x200860F,0x147218A6,0xF16A209,0xF0079,0x555C};
+	public static final int[] CURVE_Pxaa= {0x14E24678,0x1F149A9B,0x9609022,0x1C186868,0xCDEFC69,0x1C87BB2E,0x14A2235F,0x7586755,0x5896747,0x159BFE92,0x3B5572E,0x1710A521,0x71EB14A,0xC643C33,0x12581DE5,0x1BCA747D,0x959};
+	public static final int[] CURVE_Pxab= {0x1FB099B8,0x3FCF5D7,0x4A91C0E,0xC6EEB40,0x11FC2385,0x11B5AE8D,0x1A9CC3E7,0x194FE144,0x185DB2A5,0x930E1C7,0x14F85F9A,0x1F2ED4E,0x1D1BE5AD,0xF26169C,0xCF7F194,0x1DA1062E,0x3B0D};
+	public static final int[] CURVE_Pxba= {0x11AD15D3,0xD0E6F38,0x17DB85BB,0x30A62F1,0x1EA3E09A,0x17B25FA1,0x1B7959AC,0x1165B19A,0x6C74FDB,0x18F790E1,0x12278FDA,0x1E008F79,0x103F329,0x14619FF1,0x1EBCAA8,0xFF5A9CA,0x3EC2};
+	public static final int[] CURVE_Pxbb= {0x1EE0F480,0x3D5943A,0xF5B12E3,0x128AADC8,0x180E1CB9,0x1EFD916F,0x48BC7F,0x1D5EE1FA,0x5698EF5,0x11D6AED9,0x1386BC6E,0x196E900B,0x1CE2E465,0xC2A8ED3,0x1E67DF99,0x71B7940,0xA5B};
+	public static final int[] CURVE_Pyaa= {0x14781AA0,0xC324C98,0xEDC2AC,0x16C13B46,0x145FC44B,0x12529530,0x1310A8C4,0x1768C5C0,0xE19AE68,0x56E1C1D,0x13DAF93F,0x17E94366,0xF901AD0,0x76800CC,0x10250D8B,0x1E6BAE6D,0x5057};
+	public static final int[] CURVE_Pyab= {0xEAE08FA,0xDDF62BF,0xA97E5AB,0xF0EE97,0x99A42CA,0x1C326578,0xF33DC11,0x8B913F7,0xFEF8552,0x19F35B90,0x58DDBDE,0xFC32FF2,0x1587B5DF,0xB5EB07A,0x1A258DE0,0x1692CC3D,0x2CE2};
+	public static final int[] CURVE_Pyba= {0x5F0CC41,0xB9813B5,0x14C2A87D,0xFF1264A,0x19AF8A14,0x6CE6C3,0x2A7F8A2,0x121DCA7D,0x7D37153,0x19D21078,0x15466DC7,0x1362982B,0x1DD3CB5B,0x1CFC0D1C,0x18C69AF8,0x8CC7DC,0x1807};
+	public static final int[] CURVE_Pybb= {0x115C1CAE,0x78D9732,0x16C26237,0x5A81A6A,0x1C38A777,0x56121FE,0x4DAD9D7,0x1BEBA670,0xA1D72FC,0xD60B274,0x19734258,0x1D621775,0x4691771,0x14206B68,0x17B22DE4,0x29D5B37,0x499D};
+	public static final int[][] CURVE_W= {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+	public static final int[][][] CURVE_SB= {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+	public static final int[][] CURVE_WB= {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+	public static final int[][][] CURVE_BB= {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+
+}
+
diff --git a/version3/java/ROM_BLS24_64.java b/version3/java/ROM_BLS24_64.java
new file mode 100644
index 0000000..14658f9
--- /dev/null
+++ b/version3/java/ROM_BLS24_64.java
@@ -0,0 +1,60 @@
+/*
+	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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.BLS24;
+
+public class ROM
+{
+
+// Base Bits= 56
+	public static final long[] Modulus= {0x44C1674A06152BL,0xFFE2E82D30DAF8L,0x6F1C5CBDB6A642L,0x3220DF068A328BL,0xE09E1F24406187L,0xBA825079733568L,0x6E803F2E77E4C1L,0x3CCC5BA839AECL,0x555C0078L};
+	public static final long[] R2modp= {0x6A4A1FE013DF5BL,0xE8E46D4D1BDE65L,0x1F841391F45C67L,0x9148A4516FB28L,0x4398524EDF4C88L,0x41C0E241B6DCE8L,0xE42C208C19411L,0xA7FE6FD73A7B1CL,0xFCCCA76L};
+	public static final long MConst= 0xBD5D7D8095FE7DL;
+	public static final long[] Fra= {0x5CA74ABBF96F1DL,0x1FF8BD0C6FFBADL,0x49E9E26237469CL,0x3CECA48407F8E5L,0x69D68FF59267B7L,0x5D199E33127CBDL,0xB97549184F313AL,0x4E77242DA52D8DL,0x4BBC87B9L};
+	public static final long[] Frb= {0xE81A1C8E0CA60EL,0xDFEA2B20C0DF4AL,0x25327A5B7F5FA6L,0xF5343A828239A6L,0x76C78F2EADF9CFL,0x5D68B24660B8ABL,0xB50AF61628B387L,0xB555A18CDE6D5EL,0x99F78BEL};
+
+	public static final int CURVE_A= 0;
+	public static final int CURVE_B_I= 19;
+	public static final int CURVE_Cof_I= 0;
+	public static final long[] CURVE_B= {0x13L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+	public static final long[] CURVE_Order= {0x1A08FFF0000001L,0x1E7033FF551190L,0x6ADE7EE322DDAFL,0x848FC9D0CED13AL,0x50D81729CC224L,0x1F0F05B98BB44AL,0x10010010005A0L,0x0L,0x0L};
+	public static final long[] CURVE_Gx= {0x6760F5EBE3CCD4L,0xEFE2DAED9F4564L,0x783F08EBA1FCC1L,0xC6F8D95AF88134L,0xDCA8D1AE2D8477L,0x9077586CEFE4BFL,0x8B7FEA5D99BC1DL,0x17CAF9486DE9E1L,0x1AB2BE34L};
+	public static final long[] CURVE_Gy= {0xCBA5CAD21E5245L,0x6D6608C55DF6C4L,0xB3ED294F39746BL,0x145824920FF3C8L,0x63AA4FD63E5A64L,0x492A2BF79CE00FL,0x66A7A4529FF79AL,0x6C53E477B861CAL,0x47FCB70CL};
+
+	public static final long[] CURVE_Bnx= {0x100020011FF80L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+	public static final long[] CURVE_Cof= {0xC1FFBFF9F415ABL,0x5556AAB7FFL,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+	public static final long[] CURVE_Cru= {0xBC27146DD794A9L,0x3A30938AF33A43L,0xB112175223DDC6L,0x125CFBB4236DFBL,0x2358E379CE607L,0xD680C6EB20806EL,0x314C200860FF77L,0x3CBC5A88268E4L,0x555C0078L};
+	public static final long[] CURVE_Pxaa= {0xE2935374E24678L,0xC34342582408BL,0xF765CCDEFC69EL,0xC33AAD2888D7F9L,0x7FD2458967473AL,0x52908ED55CBAB3L,0x786671EB14AB88L,0xA3EC96077958C8L,0x959DE53L};
+	public static final long[] CURVE_Pxab= {0x7F9EBAFFB099B8L,0x3775A012A47038L,0x6B5D1B1FC23856L,0x7F0A26A730F9E3L,0x1C38F85DB2A5CAL,0x76A753E17E6926L,0x2D39D1BE5AD0F9L,0x31733DFC651E4CL,0x3B0DED08L};
+	public static final long[] CURVE_Pxba= {0xA1CDE711AD15D3L,0x853178DF6E16EDL,0x64BF43EA3E09A1L,0x2D8CD6DE566B2FL,0xF21C26C74FDB8BL,0x47BCC89E3F6B1EL,0x3FE2103F329F00L,0x4E507AF2AA28C3L,0x3EC27FADL};
+	public static final long[] CURVE_Pxbb= {0x7AB2875EE0F480L,0x4556E43D6C4B8CL,0xFB22DF80E1CB99L,0xF70FD0122F1FFDL,0xD5DB25698EF5EAL,0x4805CE1AF1BA3AL,0x1DA7CE2E465CB7L,0xCA0799F7E65855L,0xA5B38DBL};
+	public static final long[] CURVE_Pyaa= {0x86499314781AA0L,0x609DA303B70AB1L,0xA52A6145FC44BBL,0x462E04C42A3124L,0xC383AE19AE68BBL,0xA1B34F6BE4FCADL,0x198F901AD0BF4L,0x736C094362CED0L,0x5057F35DL};
+	public static final long[] CURVE_Pyab= {0xBBEC57EEAE08FAL,0x78774BAA5F96ADL,0x64CAF099A42CA0L,0xC89FBBCCF70478L,0x6B720FEF855245L,0x97F916376F7B3EL,0x60F5587B5DF7E1L,0x61EE89637816BDL,0x2CE2B496L};
+	public static final long[] CURVE_Pyba= {0x730276A5F0CC41L,0xF89325530AA1F5L,0xD9CD879AF8A147L,0xEE53E8A9FE2880L,0x420F07D3715390L,0x4C15D519B71F3AL,0x1A39DD3CB5B9B1L,0x3EE631A6BE39F8L,0x18070466L};
+	public static final long[] CURVE_Pybb= {0xF1B2E6515C1CAEL,0xD40D355B0988DCL,0xC243FDC38A7772L,0x5D338136B675CAL,0x164E8A1D72FCDFL,0xBBAE5CD0961ACL,0xD6D04691771EB1L,0xD9BDEC8B792840L,0x499D14EAL};
+	public static final long[][] CURVE_W= {{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}};
+	public static final long[][][] CURVE_SB= {{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}}};
+	public static final long[][] CURVE_WB= {{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}};
+	public static final long[][][] CURVE_BB= {{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}}};
+
+}
+
diff --git a/version3/java/ROM_BLS381_32.java b/version3/java/ROM_BLS381_32.java
new file mode 100644
index 0000000..5ce7e03
--- /dev/null
+++ b/version3/java/ROM_BLS381_32.java
@@ -0,0 +1,57 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.BLS381;
+
+public class ROM
+{
+
+// Base Bits= 29
+
+// Base Bits= 29
+public static final int[] Modulus= {0x1FFFAAAB,0xFF7FFFF,0x14FFFFEE,0x17FFFD62,0xF6241EA,0x9507B58,0xAFD9CC3,0x109E70A2,0x1764774B,0x121A5D66,0x12C6E9ED,0x12FFCD34,0x111EA3,0xD};
+public static final int[] R2modp= {0x15BEF7AE,0x1031CD0E,0x2DD93E8,0x9226323,0xE6E2CD2,0x11684DAA,0x1170E5DB,0x88E25B1,0x1B366399,0x1C536F47,0xD1F9CBC,0x278B67F,0x1EA66A2B,0xC};
+public static final int MConst= 0x1FFCFFFD;
+
+public static final int CURVE_A= 0;
+public static final int CURVE_B_I= 4;
+public static final int CURVE_Cof_I= 0;
+public static final int[] CURVE_B= {0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+public static final int[] CURVE_Order= {0x1,0x1FFFFFF8,0x1F96FFBF,0x1B4805FF,0x1D80553B,0xC0404D0,0x1520CCE7,0xA6533AF,0x73EDA7,0x0,0x0,0x0,0x0,0x0};
+public static final int[] CURVE_Gx= {0x1B22C6BB,0x19D78056,0x1E86BBFE,0xBD07FF2,0x1AC586C5,0x1D1F8B8D,0x4168538,0x9F2EE97,0xFC3688C,0x27D4D60,0x9A558E3,0x32FAF28,0x1F1D3A73,0xB};
+public static final int[] CURVE_Gy= {0x6C5E7E1,0x551194A,0x222B903,0x198E8945,0xB3EDD03,0xC659602,0xBD8036C,0x12BABA01,0x4FCF5E0,0xBA0EC57,0x8278C3B,0x75541E3,0xB3F481E,0x4};
+
+public static final int[] Fra= {0x12235FB8,0x83BAF6C,0x19E04F63,0x1D4A7AC7,0xB9C4F67,0x1EBC25D,0x1D3DEC91,0x1FA797AB,0x1F0FD603,0x1016068,0x108C6FAD,0x5760CCF,0x104D3BF0,0xC};
+public static final int[] Frb= {0xDDC4AF3,0x7BC5093,0x1B1FB08B,0x1AB5829A,0x3C5F282,0x764B8FB,0xDBFB032,0x10F6D8F6,0x1854A147,0x1118FCFD,0x23A7A40,0xD89C065,0xFC3E2B3,0x0};
+public static final int[] CURVE_Bnx= {0x10000,0x10080000,0x34,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+public static final int[] CURVE_Cof= {0xAAAB,0x55558,0x157855A3,0x191800AA,0x396,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+public static final int[] CURVE_Cru= {0x1FFEFFFE,0x100FFFFF,0x280008B,0xFB026C4,0x9688DE1,0x149DF37C,0x1FAB76CE,0xED41EE,0x11BA69C6,0x1EFBB672,0x17C659CB,0x0,0x0,0x0};
+public static final int[] CURVE_Pxa= {0x121BDB8,0x402B646,0x16EFBF5,0x18064D50,0x1D1770BA,0x5B23D71,0xC0AD144,0x1A9F4807,0x11C6E47A,0x196E2882,0x9820149,0x11E1522,0x4AA2B2F,0x1};
+public static final int[] CURVE_Pxb= {0x1D042B7E,0xD63E82A,0x51755F9,0x19E22427,0x15049334,0x10DDEE3F,0x186AD769,0x1A132416,0x5596BD0,0x4413A7B,0x1F6B34E8,0x4E33EC0,0x1E02B605,0x9};
+public static final int[] CURVE_Pya= {0x8B82801,0xC9AA430,0xB28A278,0x15939877,0xD12C923,0xD34A8B0,0xE9DB50A,0x155197BA,0x1AADFD9B,0x16D171A8,0x3327371,0x4FADC23,0xE5D5277,0x6};
+public static final int[] CURVE_Pyb= {0x105F79BE,0x15483AFF,0x1B07686A,0xE1A4EB9,0x99AB3F3,0x955AB97,0xEBC99D2,0xFD0B4EC,0x19CB3E28,0x15E145C,0xCAB34AC,0x1D4E6998,0x6C4A02,0x3};
+public static final int[][] CURVE_W= {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+public static final int[][][] CURVE_SB= {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+public static final int[][] CURVE_WB= {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+public static final int[][][] CURVE_BB= {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+
+}
diff --git a/version3/java/ROM_BLS381_64.java b/version3/java/ROM_BLS381_64.java
new file mode 100644
index 0000000..b59e7a1
--- /dev/null
+++ b/version3/java/ROM_BLS381_64.java
@@ -0,0 +1,57 @@
+/*
+	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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.BLS381;
+
+public class ROM
+{
+
+// Base Bits= 58
+public static final long[] Modulus= {0x1FEFFFFFFFFAAABL,0x2FFFFAC54FFFFEEL,0x12A0F6B0F6241EAL,0x213CE144AFD9CC3L,0x2434BACD764774BL,0x25FF9A692C6E9EDL,0x1A0111EA3L};
+public static final long[] R2modp= {0x20639A1D5BEF7AEL,0x1244C6462DD93E8L,0x22D09B54E6E2CD2L,0x111C4B63170E5DBL,0x38A6DE8FB366399L,0x4F16CFED1F9CBCL,0x19EA66A2BL};
+public static final long MConst= 0x1F3FFFCFFFCFFFDL;
+
+public static final int CURVE_A= 0;
+public static final int CURVE_B_I= 4;
+public static final int CURVE_Cof_I= 0;
+public static final long[] CURVE_B= {0x4L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+public static final long[] CURVE_Order= {0x3FFFFFF00000001L,0x36900BFFF96FFBFL,0x180809A1D80553BL,0x14CA675F520CCE7L,0x73EDA7L,0x0L,0x0L};
+public static final long[] CURVE_Gx= {0x33AF00ADB22C6BBL,0x17A0FFE5E86BBFEL,0x3A3F171BAC586C5L,0x13E5DD2E4168538L,0x4FA9AC0FC3688CL,0x65F5E509A558E3L,0x17F1D3A73L};
+public static final long[] CURVE_Gy= {0xAA232946C5E7E1L,0x331D128A222B903L,0x18CB2C04B3EDD03L,0x25757402BD8036CL,0x1741D8AE4FCF5E0L,0xEAA83C68278C3BL,0x8B3F481EL};
+
+
+public static final long[] Fra= {0x10775ED92235FB8L,0x3A94F58F9E04F63L,0x3D784BAB9C4F67L,0x3F4F2F57D3DEC91L,0x202C0D1F0FD603L,0xAEC199F08C6FADL,0x1904D3BF0L};
+public static final long[] Frb= {0xF78A126DDC4AF3L,0x356B0535B1FB08BL,0xEC971F63C5F282L,0x21EDB1ECDBFB032L,0x2231F9FB854A147L,0x1B1380CA23A7A40L,0xFC3E2B3L};
+public static final long[] CURVE_Bnx= {0x201000000010000L,0x34L,0x0L,0x0L,0x0L,0x0L,0x0L};
+public static final long[] CURVE_Cof= {0xAAAB0000AAABL,0x3230015557855A3L,0x396L,0x0L,0x0L,0x0L,0x0L};
+public static final long[] CURVE_Cru= {0x201FFFFFFFEFFFEL,0x1F604D88280008BL,0x293BE6F89688DE1L,0x1DA83DDFAB76CEL,0x3DF76CE51BA69C6L,0x17C659CBL,0x0L};
+public static final long[] CURVE_Pxa= {0x8056C8C121BDB8L,0x300C9AA016EFBF5L,0xB647AE3D1770BAL,0x353E900EC0AD144L,0x32DC51051C6E47AL,0x23C2A449820149L,0x24AA2B2FL};
+public static final long[] CURVE_Pxb= {0x1AC7D055D042B7EL,0x33C4484E51755F9L,0x21BBDC7F5049334L,0x3426482D86AD769L,0x88274F65596BD0L,0x9C67D81F6B34E8L,0x13E02B605L};
+public static final long[] CURVE_Pya= {0x193548608B82801L,0x2B2730EEB28A278L,0x1A695160D12C923L,0x2AA32F74E9DB50AL,0x2DA2E351AADFD9BL,0x9F5B8463327371L,0xCE5D5277L};
+public static final long[] CURVE_Pyb= {0x2A9075FF05F79BEL,0x1C349D73B07686AL,0x12AB572E99AB3F3L,0x1FA169D8EBC99D2L,0x2BC28B99CB3E28L,0x3A9CD330CAB34ACL,0x606C4A02L};
+public static final long[][] CURVE_W= {{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}};
+public static final long[][][] CURVE_SB= {{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}}};
+public static final long[][] CURVE_WB= {{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}};
+public static final long[][][] CURVE_BB= {{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}}};
+
+}
+
diff --git a/version3/java/ROM_BLS383_32.java b/version3/java/ROM_BLS383_32.java
new file mode 100644
index 0000000..860236f
--- /dev/null
+++ b/version3/java/ROM_BLS383_32.java
@@ -0,0 +1,58 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.BLS383;
+
+public class ROM
+{
+
+// Base Bits= 29
+public static final int[] Modulus= {0x5AAB0AB,0x11B8EB24,0x19214AF6,0x187E5314,0x124F47A8,0x1C00B4B0,0x1446B0C6,0x59E6CB4,0x4A0AD46,0xFF5494,0x81B6B71,0x956DD6B,0x16556956,0x2A};
+public static final int[] R2modp= {0x116907F4,0x405B700,0x1752AC11,0x67A9E7C,0x1941C581,0x1AEA38C4,0xB1E4D22,0xCE841AE,0xA0FC49B,0xB4B1F48,0x13852312,0x1B3FDCED,0x1FECE397,0x26};
+public static final int MConst= 0x73435FD;
+public static final int[] Fra= {0x1311DAC1,0x296B969,0x19DCF806,0x126901FC,0xD8C8A36,0x1A2572A8,0xA1A0959,0x1A47F743,0x110E4C6C,0x1608DA97,0xCE2E7F0,0x4FED178,0xACD5BF0,0x11};
+public static final int[] Frb= {0x1298D5EA,0xF2231BA,0x1F4452F0,0x6155117,0x4C2BD72,0x1DB4208,0xA2CA76D,0xB567571,0x139260D9,0xAF679FC,0x1B388380,0x4580BF2,0xB880D66,0x19};
+
+//*** rom curve parameters *****
+// Base Bits= 29
+
+public static final int CURVE_A= 0;
+public static final int CURVE_Cof_I= 0;
+public static final int[] CURVE_Cof= {0x15169EAB,0xA82AB0A,0xAAEFFED,0x15558001,0x555,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+public static final int CURVE_B_I= 15;
+public static final int[] CURVE_B= {0xF,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+public static final int[] CURVE_Order= {0x1EBC0001,0x1904CF5F,0x834E5CE,0xBE12B42,0xB381DE0,0xE40B4C,0x270110,0x10018017,0x1002001,0x0,0x0,0x0,0x0,0x0};
+public static final int[] CURVE_Gx= {0x8734573,0x623B9C8,0x1D1DC11E,0xBB7E107,0x1E3445C5,0x1D6C2578,0x10B0BE1E,0xED6103E,0x10F31D9F,0x296ED82,0x18E0D7D0,0x12F3D9C9,0x1FCBA55B,0x20};
+public static final int[] CURVE_Gy= {0x3F224,0x968B2F4,0x1FE63F48,0xFA93D90,0x14D2DDE5,0x54A56F5,0x12441D4C,0x18CD76C8,0x199D0DAD,0xE18E236,0x92BA73,0x99F6600,0x8F16727,0x3};
+
+public static final int[] CURVE_Bnx= {0x1001200,0x400000,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+public static final int[] CURVE_Cru= {0xEAAC2A9,0x61B3A81,0x17D974B7,0xBED0345,0xA341BC2,0x17A51A6F,0x5738948,0x69B7BAE,0x14605445,0x374A43,0x8116AD1,0x956DD69,0x16556956,0x2A};
+public static final int[] CURVE_Pxa= {0xD7F2D86,0x1E59DB1,0x17474F85,0x1FB56CF2,0x572EE81,0xE487AB1,0x96F51FC,0x190A5AAE,0x6432501,0x13E58F3A,0x101E6425,0xFD807D1,0x34D2240,0x3};
+public static final int[] CURVE_Pxb= {0x452DE15,0x1ECF20F6,0x1FF9837B,0x95651AA,0xD5D75B5,0x5D44749,0x12277F66,0x1DB3A0B9,0x1D24F498,0x19441B0E,0x1CDE9DC5,0x2C975,0xD78006,0x18};
+public static final int[] CURVE_Pya= {0x1408CB41,0x34785DC,0x3586597,0x13DBC9E4,0x1A2E75B4,0x1D65489,0xCF9A25E,0x1ACE7933,0x1B6E990E,0x19FF31A3,0x12527615,0x1A44A68F,0x1792CF93,0x19};
+public static final int[] CURVE_Pyb= {0x1F479093,0x16C2321B,0x1889218E,0x87961BC,0x1BC98B01,0x197A24FB,0xA3DEBC2,0x88D67DF,0x1CE0D,0x1E8AD3D7,0x93B9EE9,0x59B18D6,0xE5247DD,0x10};
+public static final int[][] CURVE_W= {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+public static final int[][][] CURVE_SB= {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+public static final int[][] CURVE_WB= {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+public static final int[][][] CURVE_BB= {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+
+}
diff --git a/version3/java/ROM_BLS383_64.java b/version3/java/ROM_BLS383_64.java
new file mode 100644
index 0000000..15b0dc2
--- /dev/null
+++ b/version3/java/ROM_BLS383_64.java
@@ -0,0 +1,55 @@
+/*
+	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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.BLS383;
+
+public class ROM
+{
+
+// Base Bits= 58
+public static final long[] Modulus= {0x2371D6485AAB0ABL,0x30FCA6299214AF6L,0x3801696124F47A8L,0xB3CD969446B0C6L,0x1FEA9284A0AD46L,0x12ADBAD681B6B71L,0x556556956L};
+public static final long[] R2modp= {0x80B6E0116907F4L,0xCF53CF9752AC11L,0x35D47189941C581L,0x19D0835CB1E4D22L,0x16963E90A0FC49BL,0x367FB9DB3852312L,0x4DFECE397L};
+public static final long MConst= 0x1BC0571073435FDL;
+public static final long[] Fra= {0x52D72D3311DAC1L,0x24D203F99DCF806L,0x344AE550D8C8A36L,0x348FEE86A1A0959L,0x2C11B52F10E4C6CL,0x9FDA2F0CE2E7F0L,0x22ACD5BF0L};
+public static final long[] Frb= {0x1E446375298D5EAL,0xC2AA22FF4452F0L,0x3B684104C2BD72L,0x16ACEAE2A2CA76DL,0x15ECF3F939260D9L,0x8B017E5B388380L,0x32B880D66L};
+
+public static final int CURVE_A= 0;
+public static final int CURVE_Cof_I= 0;
+public static final long[] CURVE_Cof= {0x150556155169EABL,0x2AAB0002AAEFFEDL,0x555L,0x0L,0x0L,0x0L,0x0L};
+public static final int CURVE_B_I= 15;
+public static final long[] CURVE_B= {0xFL,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+public static final long[] CURVE_Order= {0x32099EBFEBC0001L,0x17C25684834E5CEL,0x1C81698B381DE0L,0x2003002E0270110L,0x1002001L,0x0L,0x0L};
+public static final long[] CURVE_Gx= {0xC4773908734573L,0x176FC20FD1DC11EL,0x3AD84AF1E3445C5L,0x1DAC207D0B0BE1EL,0x52DDB050F31D9FL,0x25E7B3938E0D7D0L,0x41FCBA55BL};
+public static final long[] CURVE_Gy= {0x12D165E8003F224L,0x1F527B21FE63F48L,0xA94ADEB4D2DDE5L,0x319AED912441D4CL,0x1C31C46D99D0DADL,0x133ECC00092BA73L,0x68F16727L};
+
+public static final long[] CURVE_Bnx= {0x8000001001200L,0x40L,0x0L,0x0L,0x0L,0x0L,0x0L};
+public static final long[] CURVE_Cru= {0xC367502EAAC2A9L,0x17DA068B7D974B7L,0x2F4A34DEA341BC2L,0xD36F75C5738948L,0x6E94874605445L,0x12ADBAD28116AD1L,0x556556956L};
+public static final long[] CURVE_Pxa= {0x3CB3B62D7F2D86L,0x3F6AD9E57474F85L,0x1C90F562572EE81L,0x3214B55C96F51FCL,0x27CB1E746432501L,0x1FB00FA301E6425L,0x634D2240L};
+public static final long[] CURVE_Pxb= {0x3D9E41EC452DE15L,0x12ACA355FF9837BL,0xBA88E92D5D75B5L,0x3B6741732277F66L,0x3288361DD24F498L,0x592EBCDE9DC5L,0x300D78006L};
+public static final long[] CURVE_Pya= {0x68F0BB9408CB41L,0x27B793C83586597L,0x3ACA913A2E75B4L,0x359CF266CF9A25EL,0x33FE6347B6E990EL,0x34894D1F2527615L,0x33792CF93L};
+public static final long[] CURVE_Pyb= {0x2D846437F479093L,0x10F2C379889218EL,0x32F449F7BC98B01L,0x111ACFBEA3DEBC2L,0x3D15A7AE001CE0DL,0xB3631AC93B9EE9L,0x20E5247DDL};
+public static final long[][] CURVE_W= {{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}};
+public static final long[][][] CURVE_SB= {{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}}};
+public static final long[][] CURVE_WB= {{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}};
+public static final long[][][] CURVE_BB= {{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}}};
+}
+
diff --git a/version3/java/ROM_BLS461_32.java b/version3/java/ROM_BLS461_32.java
new file mode 100644
index 0000000..8f30445
--- /dev/null
+++ b/version3/java/ROM_BLS461_32.java
@@ -0,0 +1,56 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.BLS461;
+
+public class ROM
+{
+
+// Base Bits= 28
+public static final int[] Modulus={0xAAAAAAB,0xAC0000A,0x54AAAAA,0x5555,0x400020,0x91557F0,0xF26AA,0xFA5C1CC,0xB42A8DF,0x7B14848,0x8BACCA4,0x6F1E32D,0x4935FBD,0x55D6941,0xD5A555A,0x5545554,0x1555};
+public static final int[] R2modp={0xC9B6A33,0x2ECD087,0x3CCB2B1,0xCD461FE,0x8CB5AB2,0xC5B9635,0x5312E92,0xB659F64,0x3B596FA,0x8679006,0xA92E2B3,0x3CE05E3,0x363550F,0x7C07A8E,0x382C083,0x6347FEA,0xBD};
+public static final int MConst= 0xFFFFFFD;
+
+public static final int CURVE_A= 0;
+public static final int CURVE_B_I= 9;
+public static final int CURVE_Cof_I= 0;
+public static final int[] CURVE_B= {0x9,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+public static final int[] CURVE_Order= {0x1,0x0,0xFFFFC00,0x7FEFFFE,0x110000,0x7FFC800,0x801FC01,0x5FD000E,0x17FE0,0xFFFC018,0xFFFFFF7,0x0,0x0,0x0,0x0,0x0,0x0};
+public static final int[] CURVE_Gx= {0xADEE93D,0x4D026A8,0x74B7411,0xD9C00EE,0x31AC7F2,0xC3981B5,0x9218229,0xD3564DC,0xA096650,0x6F7C292,0x9743616,0xBE922B1,0x12CF668,0xC81327,0x463B73A,0xE74E99B,0xAD0};
+public static final int[] CURVE_Gy= {0xAD1D465,0xF763157,0xC4FF470,0x17884C8,0xB8D215D,0xA819E66,0xF4959D0,0xE5C3245,0xB84910A,0xB8BFA40,0xBE96EEC,0x8BF9F8C,0xF277ACC,0x5F1C3F2,0x5F68C9,0xCDB14B3,0x77B};
+
+public static final int[] Fra= {0xB812A3A,0x7117BF9,0x99C400F,0xC6308A5,0x5BF8A1,0x510E075,0x45FA5A6,0xCE4858D,0x770B31A,0xBC2CB04,0xE2FC61E,0xD073588,0x4366190,0x4DFEFA8,0x69E55E2,0x504B7F,0x12E4};
+public static final int[] Frb= {0xF298071,0x3AE8410,0xBAE6A9B,0x39D4CAF,0xFE4077E,0x404777A,0xBAF8104,0x2C13C3E,0x3D1F5C5,0xBEE7D44,0xA8B0685,0x9EAADA4,0x5CFE2C,0x7D7999,0x6BBFF78,0x50409D5,0x271};
+public static final int[] CURVE_Bnx= {0x0,0xFBFFFE0,0x1FFFFF,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+public static final int[] CURVE_Cof= {0xAAAAAAB,0xA7FFFEA,0x1556AA,0xD55AAAB,0x554FFFF,0x1555,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+public static final int[] CURVE_Cru= {0xFFFFFFE,0x40001F,0xFE00000,0xFFE7FFF,0xF0FFF6F,0x7200C47,0x7BCC604,0x15796DB,0xCF47771,0x9875433,0x613F0E8,0x5000502,0xEBFFF60,0x1FFFFF,0x0,0x0,0x0};
+public static final int[] CURVE_Pxa= {0x6D0A37C,0x5B50318,0x75DCC46,0xC2E492E,0xD6878A9,0xE01F919,0xF92F564,0x86DB74F,0x66803F0,0x46D581A,0x7ED78D,0x2F97C29,0xC270C89,0xF679453,0x6A50A9A,0x54138A0,0x10CC};
+public static final int[] CURVE_Pxb= {0x2C1C0AD,0xF85CA8C,0x25CADE9,0x6CD66C4,0xA289609,0xC612951,0xEE2401A,0x529ABEB,0xF65B17D,0xBA09D33,0xD4C5AF5,0x4D4371E,0x46A672E,0xA279D22,0xACEA37C,0x1FB4FE5,0x95C};
+public static final int[] CURVE_Pya= {0x2FB006,0xCCD0C1B,0xA12A337,0x3D194A4,0xC92C895,0x4960CFC,0x39FC68B,0x3A9B00F,0xED1BA0F,0xA7DBBC5,0xA9CDFD8,0x27CC2F7,0x4E73ED2,0x6070F4F,0xEBA7E67,0xAC848E7,0x226};
+public static final int[] CURVE_Pyb= {0xDF1457C,0xA506ADF,0x4C20A8,0xD6A31DC,0x36E3FB4,0xEA9A8F1,0x92F5668,0x3C3BE44,0x67A1297,0x74BEABA,0x56A20BE,0x4C42E38,0x45157F0,0x2AB1D00,0xBB402EA,0x101B4FA,0xE38};
+public static final int[][] CURVE_W= {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+public static final int[][][] CURVE_SB= {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+public static final int[][] CURVE_WB= {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+public static final int[][][] CURVE_BB= {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+
+
+}
diff --git a/version3/java/ROM_BLS461_64.java b/version3/java/ROM_BLS461_64.java
new file mode 100644
index 0000000..c5c5ed1
--- /dev/null
+++ b/version3/java/ROM_BLS461_64.java
@@ -0,0 +1,56 @@
+/*
+	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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.BLS461;
+
+public class ROM
+{
+
+// Base Bits= 60
+public static final long[] Modulus= {0xAAC0000AAAAAAABL,0x20000555554AAAAL,0x6AA91557F004000L,0xA8DFFA5C1CC00F2L,0xACCA47B14848B42L,0x935FBD6F1E32D8BL,0xD5A555A55D69414L,0x15555545554L};
+public static final long[] R2modp= {0x96D08774614DDA8L,0xCD45F539225D5BDL,0xD712EB760C95AB1L,0xB3B687155F30B55L,0xC4E62A05C3F5B81L,0xBA1151676CA3CD0L,0x7EDD8A958F442BEL,0x12B89DD3F91L};
+public static final long MConst= 0xC0005FFFFFFFDL;
+
+public static final int CURVE_A= 0;
+public static final int CURVE_B_I= 9;
+public static final int CURVE_Cof_I= 0;
+public static final long[] CURVE_B= {0x9L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+public static final long[] CURVE_Order= {0x1L,0x7FEFFFEFFFFC0L,0xC017FFC80001100L,0x7FE05FD000E801FL,0xFFFF7FFFC018001L,0xFFL,0x0L,0x0L};
+public static final long[] CURVE_Gx= {0x14D026A8ADEE93DL,0xF2D9C00EE74B741L,0x229C3981B531AC7L,0x6650D3564DC9218L,0x436166F7C292A09L,0x2CF668BE922B197L,0x463B73A0C813271L,0xAD0E74E99BL};
+public static final long[] CURVE_Gy= {0xF763157AD1D465L,0x5D17884C8C4FF47L,0x9D0A819E66B8D21L,0x910AE5C3245F495L,0x96EECB8BFA40B84L,0x277ACC8BF9F8CBEL,0x5F68C95F1C3F2FL,0x77BCDB14B3L};
+
+public static final long[] Fra= {0xF7117BF9B812A3AL,0xA1C6308A599C400L,0x5A6510E07505BF8L,0xB31ACE4858D45FAL,0xFC61EBC2CB04770L,0x366190D073588E2L,0x69E55E24DFEFA84L,0x12E40504B7FL};
+public static final long[] Frb= {0xB3AE8410F298071L,0x7E39D4CAFBAE6A9L,0x104404777AFE407L,0xF5C52C13C3EBAF8L,0xB0685BEE7D443D1L,0x5CFE2C9EAADA4A8L,0x6BBFF7807D79990L,0x27150409D5L};
+public static final long[] CURVE_Bnx= {0xFFBFFFE00000000L,0x1FFFFL,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+public static final long[] CURVE_Cof= {0xAA7FFFEAAAAAAABL,0xFFD55AAAB01556AL,0x1555554FFL,0x0L,0x0L,0x0L,0x0L,0x0L};
+public static final long[] CURVE_Cru= {0x40001FFFFFFFEL,0x6FFFE7FFFFE0000L,0x6047200C47F0FFFL,0x777115796DB7BCCL,0x3F0E89875433CF4L,0xBFFF60500050261L,0x1FFFFFEL,0x0L};
+public static final long[] CURVE_Pxa= {0x65B503186D0A37CL,0xA9C2E492E75DCC4L,0x564E01F919D6878L,0x3F086DB74FF92FL,0xED78D46D581A668L,0x270C892F97C2907L,0x6A50A9AF679453CL,0x10CC54138A0L};
+public static final long[] CURVE_Pxb= {0x9F85CA8C2C1C0ADL,0x96CD66C425CADEL,0x1AC612951A2896L,0xB17D529ABEBEE24L,0xC5AF5BA09D33F65L,0x6A672E4D4371ED4L,0xACEA37CA279D224L,0x95C1FB4FE5L};
+public static final long[] CURVE_Pya= {0x7CCD0C1B02FB006L,0x953D194A4A12A33L,0x68B4960CFCC92C8L,0xBA0F3A9B00F39FCL,0xCDFD8A7DBBC5ED1L,0xE73ED227CC2F7A9L,0xEBA7E676070F4F4L,0x226AC848E7L};
+public static final long[] CURVE_Pyb= {0x8A506ADFDF1457CL,0xB4D6A31DC04C20AL,0x668EA9A8F136E3FL,0x12973C3BE4492F5L,0xA20BE74BEABA67AL,0x5157F04C42E3856L,0xBB402EA2AB1D004L,0xE38101B4FAL};
+public static final long[][] CURVE_W= {{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}};
+public static final long[][][] CURVE_SB= {{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}}};
+public static final long[][] CURVE_WB= {{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}};
+public static final long[][][] CURVE_BB= {{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}}};
+
+}
+
diff --git a/version3/java/ROM_BLS48_32.java b/version3/java/ROM_BLS48_32.java
new file mode 100644
index 0000000..dca6f6d
--- /dev/null
+++ b/version3/java/ROM_BLS48_32.java
@@ -0,0 +1,68 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.BLS48;
+
+public class ROM
+{
+
+// Base Bits= 29
+	public static final int[] Modulus= {0x1CF6AC0B,0x17B7307F,0x19877E7B,0x12CE0134,0x14228402,0x1BD4C386,0x1DACBB04,0x40410D0,0x25A415,0x980B53E,0xDE6E250,0x15D9AAD6,0x5DA950,0x1029B7A,0x54AB351,0x14AD90CE,0x3729047,0x1FE7E2D9,0x145F610B,0x1F};
+	public static final int[] R2modp= {0xD59D0FA,0x12F01FD0,0xDE8FD41,0x35AAEE1,0xB937F48,0x50700E8,0x1F50EFCE,0x1019B13C,0x3470A2F,0x11094115,0xF9FB72D,0x6AD10E2,0x1CFD9F8,0x44F4785,0x2B48793,0x1148ED3,0xF609E61,0x1EE34BC7,0x1735D29E,0x0};
+	public static final int MConst= 0x9DA805D;
+	public static final int[] Fra= {0x1325BF89,0x1311E7EC,0xCD0A56F,0x1A0FD46E,0xE83BCCA,0xCA97DD0,0x18D1D297,0x5F1E137,0x7AB9F2C,0x13FC255F,0x1C9DECEB,0x9DEF4A2,0x3C0F60B,0x1D9909E4,0x1FF27FF7,0x1DBF8208,0x89BB36C,0x40044E0,0x62E01EE,0x5};
+	public static final int[] Frb= {0x1325BF89,0x1311E7EC,0xCD0A56F,0x1A0FD46E,0xE83BCCA,0xCA97DD0,0x18D1D297,0x5F1E137,0x7AB9F2C,0x13FC255F,0x1C9DECEB,0x9DEF4A2,0x3C0F60B,0x1D9909E4,0x1FF27FF7,0x1DBF8208,0x89BB36C,0x40044E0,0x62E01EE,0x5};
+
+	public static final int CURVE_A= 0;
+	public static final int CURVE_B_I= 17;
+	public static final int CURVE_Cof_I= 0;
+	public static final int[] CURVE_B= {0x11,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int[] CURVE_Order= {0x1,0x17FFF800,0xA769C21,0x8AA813C,0x2029C21,0xA68F58B,0xB6307F4,0x1184DA51,0x6DFED78,0x1A3C85E9,0x571037B,0x1637F1F9,0x1C465FB0,0x98354B9,0x118DF17A,0x1422355D,0x43BF73E,0x6,0x0,0x0};
+	public static final int[] CURVE_Gx= {0x5D71D33,0x1943697B,0x18CB783F,0x1B00AA9F,0x1711EE0B,0x7F80B23,0x129FD8CC,0x1345E03F,0x9A80F66,0x7038173,0xC056511,0x142801F5,0x42B2C3A,0x1AF09869,0x7924166,0x8381264,0x957EDD7,0xBACAEDC,0xA27A4A1,0x13};
+	public static final int[] CURVE_Gy= {0xA6ED83A,0x14D2D9FF,0xA29C33D,0x1B8972A9,0x6958677,0x19C8F547,0x1DED7E3E,0x14F9E3DC,0x18FB7229,0x27171C0,0x1551E32D,0xE6184CC,0x6260E3C,0x733D204,0x579C437,0x1534665C,0x2B3349D,0x3162FD7,0xB634253,0x1};
+
+	public static final int[] CURVE_Bnx= {0x1DE40020,0x3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int[] CURVE_Cof= {0x1F12ABEB,0x516887B,0x5,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int[] CURVE_Cru= {0xCBBA429,0x1B273F3,0xD3DD160,0x19C61452,0x308093A,0x146E1E34,0xAE0E768,0x1185948,0x1B73BC2D,0x93D855C,0x1B1A639C,0x118C919B,0xFF04AE3,0xF1CCD77,0x91318E5,0x10644780,0x3A79F7,0x1BE77919,0x145F60F3,0x1F};
+	public static final int[] CURVE_Pxaaa= {0x923CE4A,0x14697474,0xAE04F4A,0x17AE205A,0x1313A20C,0x10B2EC50,0x18DF074F,0x15FE3FE8,0x7C90B98,0x959BF85,0xE57BD37,0x14376C96,0xBF57375,0xE20B625,0x12EE2172,0x1CBBCE85,0x1A5D9487,0xD0E024B,0x195E3602,0x1C};
+	public static final int[] CURVE_Pxaab= {0xC0A1BE1,0x138E6E2D,0x1DF5FDC,0x151FC760,0x33972C5,0x56AA3C2,0x2491D8C,0x115B9FD7,0x140A11FA,0x1873AE35,0x1F259C26,0x74B0647,0x12D18B04,0x4672431,0x1C27F419,0x1CAA4D35,0x18DB48B6,0x13A54BDA,0x5080497,0x5};
+	public static final int[] CURVE_Pxaba= {0x170C5DC4,0x11D39263,0x16B3BCB6,0x152C95BB,0x19BEC736,0x8849A12,0x49AB2A8,0xC7162D3,0xC58CD55,0x15C2659,0x11EE8B90,0xB40CAFC,0xE233167,0x7BEC8BE,0x129335BD,0x151C7DBB,0x78B689B,0x1B6B8EED,0x14BFBE3D,0x16};
+	public static final int[] CURVE_Pxabb= {0x1A64B740,0x6B14B34,0x12481578,0x23FA931,0x323ADD1,0x206B82A,0xD789E1B,0x1FCFA666,0x1F4EEA7,0xF1E39E2,0x1968610,0xAF3EBD3,0x590D3B,0xDA0C35A,0x17306AAF,0xCF9DD2B,0x3F63B1A,0x96FF2F9,0xE102A76,0x12};
+	public static final int[] CURVE_Pxbaa= {0x12F1E01F,0xDD8630B,0x12C29802,0x186239A6,0x19218788,0x4C87D1,0x16AE2501,0x775C076,0x870C80B,0x1A394429,0x1637D478,0x4A420E8,0x1C3AD4D4,0x10E5E713,0x111E6AD5,0x514FCF0,0x7CC49D3,0xC678A2,0x1787BDFD,0x1B};
+	public static final int[] CURVE_Pxbab= {0x637383D,0x1851C11C,0x661F866,0x14404A7F,0x15D3D212,0x9AE28F6,0x8051F25,0x1E1CE2BF,0x137D882F,0xB231CEB,0xA8DB8FC,0x18957645,0x5E54DA8,0x1FF41C44,0x1A297414,0x17E1CBC5,0x1014F91F,0x4282AB7,0xB6CE9E3,0x10};
+	public static final int[] CURVE_Pxbba= {0x1711939C,0xB41ED9E,0x69066BA,0x137CA3AD,0xCF2F6C0,0x5E6DAB9,0x2CE1323,0x946E448,0xF353D1C,0x14D9919F,0x46B7046,0x1A12015,0x3D6070,0x18C3E8D2,0x1F23BA45,0x1F1A337C,0x435A9CC,0x6CA1DF1,0x8A9CE1,0x15};
+	public static final int[] CURVE_Pxbbb= {0x56F4899,0x196A0854,0xA959750,0x38A3D72,0x190BC9BC,0x145752BC,0x1E9E26DA,0x1403F88,0x71895E3,0x14162F5D,0x19FEC5FF,0x14190B16,0x7597C,0x19A3CF18,0x26A4B00,0x113D1BB6,0x7857A32,0xE0B78AB,0x1DD51E0F,0x1B};
+	public static final int[] CURVE_Pyaaa= {0x14137844,0x1704BE7D,0x1FD3CCDD,0x189D8C93,0x1C768851,0xF5C37D5,0xE29C659,0x20AB1C1,0xF8896E0,0x1E08663E,0x1D1D539C,0x117E1C47,0x156CDD39,0x161F1017,0x143E8C72,0x174B22FD,0x18706190,0x49AA47E,0x19BB42E1,0xE};
+	public static final int[] CURVE_Pyaab= {0xDC83190,0x12F19247,0x1AA26424,0x15D55E88,0xC418D32,0xB0E91DD,0x47CBFF7,0x2D992C1,0xDE03C1F,0x7694AE5,0x5C741A2,0x1D423AC6,0x5E02B9E,0x1E903F10,0x4EA6513,0x433A1F1,0x8EFA1C4,0xED54713,0x1E72CE4F,0x4};
+	public static final int[] CURVE_Pyaba= {0x1985C0D,0xEE2FE82,0x64770FA,0x11A809B4,0x1483ACE9,0x18BCD2FA,0x171F32C,0x1612D58D,0x1E658341,0x1CBE2201,0x186E971,0x73F0E1,0xB0A5F40,0xAC90FB0,0x1635E008,0x237498B,0x1F3140D6,0xBF789A9,0x1166F259,0x1A};
+	public static final int[] CURVE_Pyabb= {0x159D42F8,0x1B7F0540,0x45895D7,0x14875FA2,0x1E9E7F2B,0x10139D87,0x10F3FD7D,0x11D3717F,0x69E5006,0xF9BB3C4,0x13C9ED8D,0x16516DA,0x102F51DE,0x2725FEC,0x1F125B66,0xFFC324,0x1ED80731,0x1C16C4D,0x383AAA8,0x14};
+	public static final int[] CURVE_Pybaa= {0x1F38039F,0x6A8959C,0x13C68984,0x11DD12AF,0x58093CF,0x1C8550A0,0xFFA1622,0xFF85979,0x1F2ABB75,0x18862E62,0x1EB6A2C9,0x1EC80B64,0x8EC2F18,0xE7BF713,0xC36B65A,0x19C5DD89,0x18A1D1AB,0xF772C8D,0xC11927C,0x5};
+	public static final int[] CURVE_Pybab= {0x95F7865,0x134F0379,0x1CE9A0E,0x17E0EADD,0x1DACADD7,0x1B18F9F8,0x181D3943,0x186679A,0x2505BB0,0x1FDF1DC8,0x11B36A49,0x11E254E9,0xA438576,0x102B09AE,0x139984F4,0x15BC0233,0x1B6F180E,0x960562B,0x48CA65B,0x6};
+	public static final int[] CURVE_Pybba= {0x7CC1979,0xEC1D4FB,0x1D89E6F0,0x955F38E,0x1635FDA9,0x123D8E10,0x10076209,0x494404A,0xD733D7,0x17678BCF,0x153841F9,0x10696FFD,0x5BC9FE8,0x1A20D8B2,0xE22EC9D,0x18449116,0x108C86C5,0x1B4CD720,0x34967,0x19};
+	public static final int[] CURVE_Pybbb= {0xFC9F25B,0x7E44AB1,0xE9AB5D3,0x589F00D,0x1C9D264F,0xC7478B4,0x16B24A13,0x1D2C146B,0xEF84D9A,0xF47ECDE,0x1BFEE16A,0x1B69071E,0x11AB4C1C,0xBE9D9EF,0x390F005,0x78C8288,0x1B9BF549,0x9320730,0x3D84D97,0x14};
+	public static final int[][] CURVE_W= {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+	public static final int[][][] CURVE_SB= {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+	public static final int[][] CURVE_WB= {{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+	public static final int[][][] CURVE_BB= {{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+
+}
+
diff --git a/version3/java/ROM_BLS48_64.java b/version3/java/ROM_BLS48_64.java
new file mode 100644
index 0000000..cbe6fa7
--- /dev/null
+++ b/version3/java/ROM_BLS48_64.java
@@ -0,0 +1,68 @@
+/*
+	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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.BLS48;
+
+public class ROM
+{
+
+// Base Bits= 58
+	public static final long[] Modulus= {0x2F6E60FFCF6AC0BL,0x259C02699877E7BL,0x37A9870D4228402L,0x80821A1DACBB04L,0x13016A7C025A415L,0x2BB355ACDE6E250L,0x20536F405DA950L,0x295B219C54AB351L,0x3FCFC5B23729047L,0x3F45F610BL};
+	public static final long[] R2modp= {0x25E03FA0D59D0FAL,0x6B55DC2DE8FD41L,0xA0E01D0B937F48L,0x20336279F50EFCEL,0x2212822A3470A2FL,0xD5A21C4F9FB72DL,0x89E8F0A1CFD9F8L,0x2291DA62B48793L,0x3DC6978EF609E61L,0x1735D29EL};
+	public static final long MConst= 0x21BFCBCA9DA805DL;
+	public static final long[] Fra= {0x2623CFD9325BF89L,0x341FA8DCCD0A56FL,0x1952FBA0E83BCCAL,0xBE3C26F8D1D297L,0x27F84ABE7AB9F2CL,0x13BDE945C9DECEBL,0x3B3213C83C0F60BL,0x3B7F0411FF27FF7L,0x80089C089BB36CL,0xA62E01EEL};
+	public static final long[] Frb= {0x2623CFD9325BF89L,0x341FA8DCCD0A56FL,0x1952FBA0E83BCCAL,0xBE3C26F8D1D297L,0x27F84ABE7AB9F2CL,0x13BDE945C9DECEBL,0x3B3213C83C0F60BL,0x3B7F0411FF27FF7L,0x80089C089BB36CL,0xA62E01EEL};
+
+	public static final int CURVE_A= 0;
+	public static final int CURVE_B_I= 17;
+	public static final int CURVE_Cof_I= 0;
+	public static final long[] CURVE_B= {0x11L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+	public static final long[] CURVE_Order= {0x2FFFF0000000001L,0x11550278A769C21L,0x14D1EB162029C21L,0x2309B4A2B6307F4L,0x34790BD26DFED78L,0x2C6FE3F2571037BL,0x1306A973C465FB0L,0x28446ABB18DF17AL,0xC43BF73EL,0x0L};
+	public static final long[] CURVE_Gx= {0x3286D2F65D71D33L,0x3601553F8CB783FL,0xFF01647711EE0BL,0x268BC07F29FD8CCL,0xE0702E69A80F66L,0x285003EAC056511L,0x35E130D242B2C3AL,0x107024C87924166L,0x17595DB8957EDD7L,0x26A27A4A1L};
+	public static final long[] CURVE_Gy= {0x29A5B3FEA6ED83AL,0x3712E552A29C33DL,0x3391EA8E6958677L,0x29F3C7B9DED7E3EL,0x4E2E3818FB7229L,0x1CC30999551E32DL,0xE67A4086260E3CL,0x2A68CCB8579C437L,0x62C5FAE2B3349DL,0x2B634253L};
+
+	public static final long[] CURVE_Bnx= {0x7DE40020L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+	public static final long[] CURVE_Cof= {0xA2D10F7F12ABEBL,0x5L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+	public static final long[] CURVE_Cru= {0x364E7E6CBBA429L,0x338C28A4D3DD160L,0x28DC3C68308093AL,0x230B290AE0E768L,0x127B0AB9B73BC2DL,0x23192337B1A639CL,0x1E399AEEFF04AE3L,0x20C88F0091318E5L,0x37CEF23203A79F7L,0x3F45F60F3L};
+	public static final long[] CURVE_Pxaaa= {0x28D2E8E8923CE4AL,0x2F5C40B4AE04F4AL,0x2165D8A1313A20CL,0x2BFC7FD18DF074FL,0x12B37F0A7C90B98L,0x286ED92CE57BD37L,0x1C416C4ABF57375L,0x39779D0B2EE2172L,0x1A1C0497A5D9487L,0x3995E3602L};
+	public static final long[] CURVE_Pxaab= {0x271CDC5AC0A1BE1L,0x2A3F8EC01DF5FDCL,0xAD5478433972C5L,0x22B73FAE2491D8CL,0x30E75C6B40A11FAL,0xE960C8FF259C26L,0x8CE48632D18B04L,0x39549A6BC27F419L,0x274A97B58DB48B6L,0xA5080497L};
+	public static final long[] CURVE_Pxaba= {0x23A724C770C5DC4L,0x2A592B776B3BCB6L,0x110934259BEC736L,0x18E2C5A649AB2A8L,0x2B84CB2C58CD55L,0x168195F91EE8B90L,0xF7D917CE233167L,0x2A38FB7729335BDL,0x36D71DDA78B689BL,0x2D4BFBE3DL};
+	public static final long[] CURVE_Pxabb= {0xD629669A64B740L,0x47F52632481578L,0x40D7054323ADD1L,0x3F9F4CCCD789E1BL,0x1E3C73C41F4EEA7L,0x15E7D7A61968610L,0x1B4186B40590D3BL,0x19F3BA577306AAFL,0x12DFE5F23F63B1AL,0x24E102A76L};
+	public static final long[] CURVE_Pxbaa= {0x1BB0C6172F1E01FL,0x30C4734D2C29802L,0x990FA39218788L,0xEEB80ED6AE2501L,0x34728852870C80BL,0x94841D1637D478L,0x21CBCE27C3AD4D4L,0xA29F9E111E6AD5L,0x18CF1447CC49D3L,0x37787BDFDL};
+	public static final long[] CURVE_Pxbab= {0x30A38238637383DL,0x288094FE661F866L,0x135C51ED5D3D212L,0x3C39C57E8051F25L,0x164639D737D882FL,0x312AEC8AA8DB8FCL,0x3FE838885E54DA8L,0x2FC3978BA297414L,0x850556F014F91FL,0x20B6CE9E3L};
+	public static final long[] CURVE_Pxbba= {0x1683DB3D711939CL,0x26F9475A69066BAL,0xBCDB572CF2F6C0L,0x128DC8902CE1323L,0x29B3233EF353D1CL,0x342402A46B7046L,0x3187D1A403D6070L,0x3E3466F9F23BA45L,0xD943BE2435A9CCL,0x2A08A9CE1L};
+	public static final long[] CURVE_Pxbbb= {0x32D410A856F4899L,0x7147AE4A959750L,0x28AEA57990BC9BCL,0x2807F11E9E26DAL,0x282C5EBA71895E3L,0x2832162D9FEC5FFL,0x33479E30007597CL,0x227A376C26A4B00L,0x1C16F1567857A32L,0x37DD51E0FL};
+	public static final long[] CURVE_Pyaaa= {0x2E097CFB4137844L,0x313B1927FD3CCDDL,0x1EB86FABC768851L,0x4156382E29C659L,0x3C10CC7CF8896E0L,0x22FC388FD1D539CL,0x2C3E202F56CDD39L,0x2E9645FB43E8C72L,0x93548FD8706190L,0x1D9BB42E1L};
+	public static final long[] CURVE_Pyaab= {0x25E3248EDC83190L,0x2BAABD11AA26424L,0x161D23BAC418D32L,0x5B3258247CBFF7L,0xED295CADE03C1FL,0x3A84758C5C741A2L,0x3D207E205E02B9EL,0x86743E24EA6513L,0x1DAA8E268EFA1C4L,0x9E72CE4FL};
+	public static final long[] CURVE_Pyaba= {0x1DC5FD041985C0DL,0x2350136864770FAL,0x3179A5F5483ACE9L,0x2C25AB1A171F32CL,0x397C4403E658341L,0xE7E1C2186E971L,0x15921F60B0A5F40L,0x46E9317635E008L,0x17EF1353F3140D6L,0x35166F259L};
+	public static final long[] CURVE_Pyabb= {0x36FE0A8159D42F8L,0x290EBF4445895D7L,0x20273B0FE9E7F2BL,0x23A6E2FF0F3FD7DL,0x1F37678869E5006L,0x2CA2DB53C9ED8DL,0x4E4BFD902F51DEL,0x1FF8649F125B66L,0x382D89BED80731L,0x28383AAA8L};
+	public static final long[] CURVE_Pybaa= {0xD512B39F38039FL,0x23BA255F3C68984L,0x390AA14058093CFL,0x1FF0B2F2FFA1622L,0x310C5CC5F2ABB75L,0x3D9016C9EB6A2C9L,0x1CF7EE268EC2F18L,0x338BBB12C36B65AL,0x1EEE591B8A1D1ABL,0xAC11927CL};
+	public static final long[] CURVE_Pybab= {0x269E06F295F7865L,0x2FC1D5BA1CE9A0EL,0x3631F3F1DACADD7L,0x30CCF3581D3943L,0x3FBE3B902505BB0L,0x23C4A9D31B36A49L,0x2056135CA438576L,0x2B78046739984F4L,0x12C0AC57B6F180EL,0xC48CA65BL};
+	public static final long[] CURVE_Pybba= {0x1D83A9F67CC1979L,0x12ABE71DD89E6F0L,0x247B1C21635FDA9L,0x92880950076209L,0x2ECF179E0D733D7L,0x20D2DFFB53841F9L,0x3441B1645BC9FE8L,0x3089222CE22EC9DL,0x3699AE4108C86C5L,0x320034967L};
+	public static final long[] CURVE_Pybbb= {0xFC89562FC9F25BL,0xB13E01AE9AB5D3L,0x18E8F169C9D264FL,0x3A5828D76B24A13L,0x1E8FD9BCEF84D9AL,0x36D20E3DBFEE16AL,0x17D3B3DF1AB4C1CL,0xF190510390F005L,0x12640E61B9BF549L,0x283D84D97L};
+	public static final long[][] CURVE_W= {{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}};
+	public static final long[][][] CURVE_SB= {{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}}};
+	public static final long[][] CURVE_WB= {{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}};
+	public static final long[][][] CURVE_BB= {{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}}};
+
+}
+
diff --git a/version3/java/ROM_BN254CX_32.java b/version3/java/ROM_BN254CX_32.java
new file mode 100644
index 0000000..ce1553a
--- /dev/null
+++ b/version3/java/ROM_BN254CX_32.java
@@ -0,0 +1,57 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.BN254CX;
+
+public class ROM
+{
+// Base Bits= 28
+	public static final int[] Modulus= {0xC1B55B3,0x6623EF5,0x93EE1BE,0xD6EE180,0x6D3243F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2};
+	public static final int[] R2modp= {0x8A0800A,0x466A061,0x43056A3,0x2B3A225,0x9C6600,0x148515B,0x6BDF50,0xEC9EA56,0xC992E66,0x1};
+	public static final int MConst= 0x9789E85;
+
+	public static final int CURVE_A= 0;
+	public static final int CURVE_B_I= 2;
+	public static final int CURVE_Cof_I= 1;
+	public static final int[] CURVE_B= {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int[] CURVE_Order= {0x6EB1F6D,0x11C0A63,0x906CEBE,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2};
+	public static final int[] CURVE_Gx= {0xC1B55B2,0x6623EF5,0x93EE1BE,0xD6EE180,0x6D3243F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2};
+	public static final int[] CURVE_Gy= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+
+	public static final int[] CURVE_Bnx= {0x3C012B1,0x0,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int[] CURVE_Cof= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int[] CURVE_Cru= {0x4235C97,0xE093179,0xF875631,0xDF6471E,0xF1440BD,0xCA83,0x480000,0x0,0x0,0x0};
+	public static final int[] Fra= {0x5C80EA3,0xD908335,0x3F8215B,0x7326F17,0x8986867,0x8AACA71,0x4AFE18B,0xA63A016,0x359082F,0x1};
+	public static final int[] Frb= {0x6534710,0x8D1BBC0,0x546C062,0x63C7269,0xE3ABBD8,0xD9CDBC4,0x900DC53,0x623628A,0xA6F7D0,0x1};
+
+	public static final int[] CURVE_Pxa= {0x4D2EC74,0x851CEEE,0xE2726C0,0x85BFA03,0xBBB907C,0xF5C34,0x6358B25,0x7053B25,0x9682D2C,0x1};
+	public static final int[] CURVE_Pxb= {0xE29CFE1,0xA58E8B2,0x9C30F47,0x97B0C20,0x743F81B,0x37A8E99,0xAA011C9,0x3E19F64,0x466B9EC,0x1};	
+	public static final int[] CURVE_Pya= {0xF0BE09F,0xFBFCEBC,0xEC1B30C,0xB33D847,0x2096361,0x157DAEE,0xDD81E22,0x72332B8,0xA79EDD9,0x0};
+	public static final int[] CURVE_Pyb= {0x898EE9D,0x904B228,0x2EDEBED,0x4EA569D,0x461C286,0x512D8D3,0x35C6E4,0xECC4C09,0x6160C39,0x0};
+
+
+	public static final int[][] CURVE_W= {{0x62FEB83,0x5463491,0x381200,0xB4,0x6000,0x0,0x0,0x0,0x0,0x0},{0x7802561,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+	public static final int[][][] CURVE_SB= {{{0xDB010E4,0x5463491,0x381280,0xB4,0x6000,0x0,0x0,0x0,0x0,0x0},{0x7802561,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x7802561,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xBB33EA,0xBD5D5D2,0x8CEBCBD,0xD6EE018,0x6D2643F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2}}};
+	public static final int[][] CURVE_WB= {{0x67A84B0,0x1C21185,0x12B040,0x3C,0x2000,0x0,0x0,0x0,0x0,0x0},{0xE220475,0xCDF995B,0xA7F9A36,0x94EDA8C,0xA0DC07E,0x8702,0x300000,0x0,0x0,0x0},{0xF10B93,0x66FCCAE,0x53FCD3B,0x4A76D46,0x506E03F,0x4381,0x180000,0x0,0x0,0x0},{0xDFAAA11,0x1C21185,0x12B0C0,0x3C,0x2000,0x0,0x0,0x0,0x0,0x0}};
+	public static final int[][][] CURVE_BB= {{{0x32B0CBD,0x11C0A63,0x906CE7E,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2},{0x32B0CBC,0x11C0A63,0x906CE7E,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2},{0x32B0CBC,0x11C0A63,0x906CE7E,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2},{0x7802562,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x7802561,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x32B0CBC,0x11C0A63,0x906CE7E,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2},{0x32B0CBD,0x11C0A63,0x906CE7E,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2},{0x32B0CBC,0x11C0A63,0x906CE7E,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2}},{{0x7802562,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x7802561,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x7802561,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x7802561,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x3C012B2,0x0,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xF004AC2,0x0,0x100,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xF6AFA0A,0x11C0A62,0x906CE3E,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2},{0x3C012B2,0x0,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+
+}
diff --git a/version3/java/ROM_BN254CX_64.java b/version3/java/ROM_BN254CX_64.java
new file mode 100644
index 0000000..0e837f0
--- /dev/null
+++ b/version3/java/ROM_BN254CX_64.java
@@ -0,0 +1,58 @@
+/*
+	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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.BN254CX;
+
+public class ROM
+{
+// Base Bits= 56
+	public static final long[] Modulus= {0x6623EF5C1B55B3L,0xD6EE18093EE1BEL,0x647A6366D3243FL,0x8702A0DB0BDDFL,0x24000000L};
+	public static final long[] R2modp= {0x466A0618A0800AL,0x2B3A22543056A3L,0x148515B09C6600L,0xEC9EA5606BDF50L,0x1C992E66L};
+	public static final long MConst= 0x4E205BF9789E85L;
+
+	public static final int CURVE_A= 0;
+	public static final int CURVE_B_I= 2;
+	public static final int CURVE_Cof_I= 1;
+	public static final long[] CURVE_B= {0x2L,0x0L,0x0L,0x0L,0x0L};
+	public static final long[] CURVE_Order= {0x11C0A636EB1F6DL,0xD6EE0CC906CEBEL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L};
+	public static final long[] CURVE_Gx= {0x6623EF5C1B55B2L,0xD6EE18093EE1BEL,0x647A6366D3243FL,0x8702A0DB0BDDFL,0x24000000L};
+	public static final long[] CURVE_Gy= {0x1L,0x0L,0x0L,0x0L,0x0L};
+
+	public static final long[] CURVE_Bnx= {0x3C012B1L,0x40L,0x0L,0x0L,0x0L};
+	public static final long[] CURVE_Cof= {0x1L,0x0L,0x0L,0x0L,0x0L};
+	public static final long[] CURVE_Cru= {0xE0931794235C97L,0xDF6471EF875631L,0xCA83F1440BDL,0x480000L,0x0L};
+	public static final long[] Fra= {0xD9083355C80EA3L,0x7326F173F8215BL,0x8AACA718986867L,0xA63A0164AFE18BL,0x1359082FL};
+	public static final long[] Frb= {0x8D1BBC06534710L,0x63C7269546C062L,0xD9CDBC4E3ABBD8L,0x623628A900DC53L,0x10A6F7D0L};
+
+	public static final long[] CURVE_Pxa= {0x851CEEE4D2EC74L,0x85BFA03E2726C0L,0xF5C34BBB907CL,0x7053B256358B25L,0x19682D2CL};
+	public static final long[] CURVE_Pxb= {0xA58E8B2E29CFE1L,0x97B0C209C30F47L,0x37A8E99743F81BL,0x3E19F64AA011C9L,0x1466B9ECL};
+	public static final long[] CURVE_Pya= {0xFBFCEBCF0BE09FL,0xB33D847EC1B30CL,0x157DAEE2096361L,0x72332B8DD81E22L,0xA79EDD9L};
+	public static final long[] CURVE_Pyb= {0x904B228898EE9DL,0x4EA569D2EDEBEDL,0x512D8D3461C286L,0xECC4C09035C6E4L,0x6160C39L};
+
+
+	public static final long[][] CURVE_W= {{0x546349162FEB83L,0xB40381200L,0x6000L,0x0L,0x0L},{0x7802561L,0x80L,0x0L,0x0L,0x0L}};
+	public static final long[][][] CURVE_SB= {{{0x5463491DB010E4L,0xB40381280L,0x6000L,0x0L,0x0L},{0x7802561L,0x80L,0x0L,0x0L,0x0L}},{{0x7802561L,0x80L,0x0L,0x0L,0x0L},{0xBD5D5D20BB33EAL,0xD6EE0188CEBCBDL,0x647A6366D2643FL,0x8702A0DB0BDDFL,0x24000000L}}};
+	public static final long[][] CURVE_WB= {{0x1C2118567A84B0L,0x3C012B040L,0x2000L,0x0L,0x0L},{0xCDF995BE220475L,0x94EDA8CA7F9A36L,0x8702A0DC07EL,0x300000L,0x0L},{0x66FCCAE0F10B93L,0x4A76D4653FCD3BL,0x4381506E03FL,0x180000L,0x0L},{0x1C21185DFAAA11L,0x3C012B0C0L,0x2000L,0x0L,0x0L}};
+	public static final long[][][] CURVE_BB= {{{0x11C0A6332B0CBDL,0xD6EE0CC906CE7EL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L},{0x11C0A6332B0CBCL,0xD6EE0CC906CE7EL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L},{0x11C0A6332B0CBCL,0xD6EE0CC906CE7EL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L},{0x7802562L,0x80L,0x0L,0x0L,0x0L}},{{0x7802561L,0x80L,0x0L,0x0L,0x0L},{0x11C0A6332B0CBCL,0xD6EE0CC906CE7EL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L},{0x11C0A6332B0CBDL,0xD6EE0CC906CE7EL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L},{0x11C0A6332B0CBCL,0xD6EE0CC906CE7EL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L}},{{0x7802562L,0x80L,0x0L,0x0L,0x0L},{0x7802561L,0x80L,0x0L,0x0L,0x0L},{0x7802561L,0x80L,0x0L,0x0L,0x0L},{0x7802561L,0x80L,0x0L,0x0L,0x0L}},{{0x3C012B2L,0x40L,0x0L,0x0L,0x0L},{0xF004AC2L,0x100L,0x0L,0x0L,0x0L},{0x11C0A62F6AFA0AL,0xD6EE0CC906CE3EL,0x647A6366D2C43FL,0x8702A0DB0BDDFL,0x24000000L},{0x3C012B2L,0x40L,0x0L,0x0L,0x0L}}};
+
+}
+
diff --git a/version3/java/ROM_BN254_32.java b/version3/java/ROM_BN254_32.java
new file mode 100644
index 0000000..3d97916
--- /dev/null
+++ b/version3/java/ROM_BN254_32.java
@@ -0,0 +1,55 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.BN254;
+
+public class ROM
+{
+
+	public static final int[] Modulus= {0x13,0x0,0x13A7,0x0,0x86121,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2};
+	public static final int[] R2modp= {0xF5E7E39,0x2F2A96F,0xB96F13C,0x64E8642,0xC7146,0x9926F7B,0x4DACD24,0x8321E7B,0xD127A2E,0x1};
+	public static final int MConst= 0x79435E5;
+
+	public static final int CURVE_Cof_I= 1;
+	public static final int CURVE_A= 0;
+	public static final int CURVE_B_I= 2;
+	public static final int[] CURVE_B= {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int[] CURVE_Order= {0xD,0x0,0x10A1,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2};
+	public static final int[] CURVE_Gx= {0x12,0x0,0x13A7,0x0,0x86121,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2};
+	public static final int[] CURVE_Gy= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+
+	public static final int[] CURVE_Bnx= {0x1,0x8000000,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int[] CURVE_Cof= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int[] CURVE_Cru= {0x7,0x8000000,0x6CD,0x0,0x24909,0x4000000,0x49B362,0x0,0x0,0x0};
+	public static final int[] Fra= {0xF2A6DE9,0x7DE6C06,0xF77C2E1,0x74924D3,0x53F8509,0x50A8469,0xCB6499B,0x212E7C8,0xB377619,0x1};
+	public static final int[] Frb= {0xD5922A,0x82193F9,0x8850C5,0x8B6DB2C,0xAC8DC17,0x2F57B96,0x503EAB2,0x1ED1837,0x9EBEE69,0x0};
+	public static final int[] CURVE_Pxa= {0x803FB2B,0xEE4224C,0x8BF0D91,0x8BBB489,0xDB6A464,0x7E8C61E,0xFEB8D8C,0x519EB62,0x61A10BB,0x0};
+	public static final int[] CURVE_Pxb= {0x7D54CF3,0x8C34C1E,0x784B70D,0x746BAE3,0xA5B1F4D,0x8C5982A,0x3310AA7,0xBA73783,0x516AAF9,0x0};
+	public static final int[] CURVE_Pya= {0x1CD2B9A,0xF0E0789,0xE09BD19,0xAE6BDB,0x22329BD,0x96698C8,0x39A90E0,0x6BAF934,0x21897A0,0x0};
+	public static final int[] CURVE_Pyb= {0xB3ACE9B,0x2D1AEC6,0x9C9578A,0x6FFD73,0xD37B090,0x56F5F38,0x68F6D44,0x7C8B152,0xEBB2B0E,0x0};
+	public static final int[][] CURVE_W= {{0x3,0x0,0x204,0x8000000,0x6181,0x0,0x0,0x0,0x0,0x0},{0x1,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+	public static final int[][][] CURVE_SB= {{{0x4,0x0,0x285,0x8000000,0x6181,0x0,0x0,0x0,0x0,0x0},{0x1,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x1,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xA,0x0,0xE9D,0x0,0x79E1E,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2}}};
+	public static final int[][] CURVE_WB= {{0x0,0x8000000,0x40,0x8000000,0x2080,0x0,0x0,0x0,0x0,0x0},{0x5,0x8000000,0x54A,0x0,0x1C707,0x8000000,0x312241,0x0,0x0,0x0},{0x3,0x8000000,0x2C5,0x8000000,0xE383,0xC000000,0x189120,0x0,0x0,0x0},{0x1,0x8000000,0xC1,0x8000000,0x2080,0x0,0x0,0x0,0x0,0x0}};
+	public static final int[][][] CURVE_BB= {{{0xD,0x8000000,0x1060,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2},{0xC,0x8000000,0x1060,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2},{0xC,0x8000000,0x1060,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2},{0x2,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x1,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xC,0x8000000,0x1060,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2},{0xD,0x8000000,0x1060,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2},{0xC,0x8000000,0x1060,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2}},{{0x2,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x2,0x8000000,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x2,0x0,0x102,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xA,0x0,0x1020,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2},{0x2,0x8000000,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+
+}
+
diff --git a/version3/java/ROM_BN254_64.java b/version3/java/ROM_BN254_64.java
new file mode 100644
index 0000000..f1927c1
--- /dev/null
+++ b/version3/java/ROM_BN254_64.java
@@ -0,0 +1,55 @@
+/*
+	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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.BN254;
+
+public class ROM
+{
+
+	public static final long[] Modulus= {0x13L,0x13A7L,0x80000000086121L,0x40000001BA344DL,0x25236482L};
+	public static final long[] R2modp= {0x2F2A96FF5E7E39L,0x64E8642B96F13CL,0x9926F7B00C7146L,0x8321E7B4DACD24L,0x1D127A2EL};
+	public static final long MConst= 0x435E50D79435E5L;
+
+	public static final int CURVE_Cof_I= 1;
+	public static final int CURVE_A= 0;
+	public static final int CURVE_B_I= 2;
+	public static final long[] CURVE_B= {0x2L,0x0L,0x0L,0x0L,0x0L};
+	public static final long[] CURVE_Order= {0xDL,0x800000000010A1L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L};
+	public static final long[] CURVE_Gx= {0x12L,0x13A7L,0x80000000086121L,0x40000001BA344DL,0x25236482L};
+	public static final long[] CURVE_Gy= {0x1L,0x0L,0x0L,0x0L,0x0L};
+
+	public static final long[] CURVE_Bnx= {0x80000000000001L,0x40L,0x0L,0x0L,0x0L};
+	public static final long[] CURVE_Cof= {0x1L,0x0L,0x0L,0x0L,0x0L};
+	public static final long[] CURVE_Cru= {0x80000000000007L,0x6CDL,0x40000000024909L,0x49B362L,0x0L};
+	public static final long[] Fra= {0x7DE6C06F2A6DE9L,0x74924D3F77C2E1L,0x50A846953F8509L,0x212E7C8CB6499BL,0x1B377619L};
+	public static final long[] Frb= {0x82193F90D5922AL,0x8B6DB2C08850C5L,0x2F57B96AC8DC17L,0x1ED1837503EAB2L,0x9EBEE69L};
+	public static final long[] CURVE_Pxa= {0xEE4224C803FB2BL,0x8BBB4898BF0D91L,0x7E8C61EDB6A464L,0x519EB62FEB8D8CL,0x61A10BBL};
+	public static final long[] CURVE_Pxb= {0x8C34C1E7D54CF3L,0x746BAE3784B70DL,0x8C5982AA5B1F4DL,0xBA737833310AA7L,0x516AAF9L};
+	public static final long[] CURVE_Pya= {0xF0E07891CD2B9AL,0xAE6BDBE09BD19L,0x96698C822329BDL,0x6BAF93439A90E0L,0x21897A0L};
+	public static final long[] CURVE_Pyb= {0x2D1AEC6B3ACE9BL,0x6FFD739C9578AL,0x56F5F38D37B090L,0x7C8B15268F6D44L,0xEBB2B0EL};
+	public static final long[][] CURVE_W= {{0x3L,0x80000000000204L,0x6181L,0x0L,0x0L},{0x1L,0x81L,0x0L,0x0L,0x0L}};
+	public static final long[][][] CURVE_SB= {{{0x4L,0x80000000000285L,0x6181L,0x0L,0x0L},{0x1L,0x81L,0x0L,0x0L,0x0L}},{{0x1L,0x81L,0x0L,0x0L,0x0L},{0xAL,0xE9DL,0x80000000079E1EL,0x40000001BA344DL,0x25236482L}}};
+	public static final long[][] CURVE_WB= {{0x80000000000000L,0x80000000000040L,0x2080L,0x0L,0x0L},{0x80000000000005L,0x54AL,0x8000000001C707L,0x312241L,0x0L},{0x80000000000003L,0x800000000002C5L,0xC000000000E383L,0x189120L,0x0L},{0x80000000000001L,0x800000000000C1L,0x2080L,0x0L,0x0L}};
+	public static final long[][][] CURVE_BB= {{{0x8000000000000DL,0x80000000001060L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L},{0x8000000000000CL,0x80000000001060L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L},{0x8000000000000CL,0x80000000001060L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L},{0x2L,0x81L,0x0L,0x0L,0x0L}},{{0x1L,0x81L,0x0L,0x0L,0x0L},{0x8000000000000CL,0x80000000001060L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L},{0x8000000000000DL,0x80000000001060L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L},{0x8000000000000CL,0x80000000001060L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L}},{{0x2L,0x81L,0x0L,0x0L,0x0L},{0x1L,0x81L,0x0L,0x0L,0x0L},{0x1L,0x81L,0x0L,0x0L,0x0L},{0x1L,0x81L,0x0L,0x0L,0x0L}},{{0x80000000000002L,0x40L,0x0L,0x0L,0x0L},{0x2L,0x102L,0x0L,0x0L,0x0L},{0xAL,0x80000000001020L,0x8000000007FF9FL,0x40000001BA344DL,0x25236482L},{0x80000000000002L,0x40L,0x0L,0x0L,0x0L}}};
+
+}
+
diff --git a/version3/java/ROM_BRAINPOOL_32.java b/version3/java/ROM_BRAINPOOL_32.java
new file mode 100644
index 0000000..2b5afda
--- /dev/null
+++ b/version3/java/ROM_BRAINPOOL_32.java
@@ -0,0 +1,44 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+/* Note that the original curve has been transformed to an isomorphic curve with A=-3 */
+
+
+package org.apache.milagro.amcl.BRAINPOOL;
+
+public class ROM
+{
+
+// Base Bits= 28
+	public static final int[] Modulus= {0xF6E5377,0x13481D1,0x6202820,0xF623D52,0xD726E3B,0x909D838,0xC3E660A,0xA1EEA9B,0x9FB57DB,0xA};
+	public static final int[] R2modp= {0xB9A3787,0x9E04F49,0x8F3CF49,0x2931721,0xF1DBC89,0x54E8C3C,0xF7559CA,0xBB411A3,0x773E15F,0x9};
+	public static final int MConst= 0xEFD89B9;
+
+	public static final int CURVE_Cof_I= 1;
+	public static final int[] CURVE_Cof= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int CURVE_A= -3;
+	public static final int CURVE_B_I= 0;
+	public static final int[] CURVE_B= {0xEE92B04,0xE58101F,0xF49256A,0xEBC4AF2,0x6B7BF93,0x733D0B7,0x4FE66A7,0x30D84EA,0x62C61C4,0x6};
+	public static final int[] CURVE_Order= {0x74856A7,0x1E0E829,0x1A6F790,0x7AA3B56,0xD718C39,0x909D838,0xC3E660A,0xA1EEA9B,0x9FB57DB,0xA};
+	public static final int[] CURVE_Gx= {0xE1305F4,0xA191562,0xFBC2B79,0x42C47AA,0x149AFA1,0xB23A656,0x7732213,0xC1CFE7B,0x3E8EB3C,0xA};
+	public static final int[] CURVE_Gy= {0xB25C9BE,0xABE8F35,0x27001D,0xB6DE39D,0x17E69BC,0xE146444,0xD7F7B22,0x3439C56,0xD996C82,0x2};
+
+}
diff --git a/version3/java/ROM_BRAINPOOL_64.java b/version3/java/ROM_BRAINPOOL_64.java
new file mode 100644
index 0000000..e234556
--- /dev/null
+++ b/version3/java/ROM_BRAINPOOL_64.java
@@ -0,0 +1,43 @@
+/*
+	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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+/* Note that the original curve has been transformed to an isomorphic curve with A=-3 */
+
+package org.apache.milagro.amcl.BRAINPOOL;
+
+public class ROM
+{
+
+// Base Bits= 56
+	public static final long[] Modulus= {0x13481D1F6E5377L,0xF623D526202820L,0x909D838D726E3BL,0xA1EEA9BC3E660AL,0xA9FB57DBL};
+	public static final long[] R2modp= {0x9E04F49B9A3787L,0x29317218F3CF49L,0x54E8C3CF1DBC89L,0xBB411A3F7559CAL,0x9773E15FL};
+	public static final long MConst= 0xA75590CEFD89B9L;
+
+	public static final int CURVE_Cof_I= 1;
+	public static final long[] CURVE_Cof= {0x1L,0x0L,0x0L,0x0L,0x0L};
+	public static final int CURVE_A= -3;
+	public static final int CURVE_B_I= 0;
+	public static final long[] CURVE_B= {0xE58101FEE92B04L,0xEBC4AF2F49256AL,0x733D0B76B7BF93L,0x30D84EA4FE66A7L,0x662C61C4L};
+	public static final long[] CURVE_Order= {0x1E0E82974856A7L,0x7AA3B561A6F790L,0x909D838D718C39L,0xA1EEA9BC3E660AL,0xA9FB57DBL};
+	public static final long[] CURVE_Gx= {0xA191562E1305F4L,0x42C47AAFBC2B79L,0xB23A656149AFA1L,0xC1CFE7B7732213L,0xA3E8EB3CL};
+	public static final long[] CURVE_Gy= {0xABE8F35B25C9BEL,0xB6DE39D027001DL,0xE14644417E69BCL,0x3439C56D7F7B22L,0x2D996C82L};
+}
+
diff --git a/version3/java/ROM_C25519_32.java b/version3/java/ROM_C25519_32.java
new file mode 100644
index 0000000..51b6249
--- /dev/null
+++ b/version3/java/ROM_C25519_32.java
@@ -0,0 +1,41 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.C25519;
+
+public class ROM
+{
+// Base Bits= 29
+public static final int[] Modulus= {0x1FFFFFED,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFFF};
+public static final int[] R2modp= {0x169000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+public static final int MConst= 0x13;
+
+public static final int CURVE_Cof_I= 8;
+public static final int[] CURVE_Cof= {0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+public static final int CURVE_A= 486662;
+public static final int CURVE_B_I= 0;
+public static final int[] CURVE_B= {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+public static final int[] CURVE_Order= {0x1CF5D3ED,0x9318D2,0x1DE73596,0x1DF3BD45,0x14D,0x0,0x0,0x0,0x100000};
+public static final int[] CURVE_Gx= {0x9,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+public static final int[] CURVE_Gy= {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+
+}
diff --git a/version3/java/ROM_C25519_64.java b/version3/java/ROM_C25519_64.java
new file mode 100644
index 0000000..dc3c95a
--- /dev/null
+++ b/version3/java/ROM_C25519_64.java
@@ -0,0 +1,42 @@
+/*
+	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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.C25519;
+
+public class ROM
+{
+
+// Base Bits= 56
+public static final long[] Modulus= {0xFFFFFFFFFFFFEDL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0x7FFFFFFFL};
+public static final long[] R2modp= {0xA4000000000000L,0x5L,0x0L,0x0L,0x0L};
+public static final long MConst= 0x13L;
+
+public static final int CURVE_Cof_I= 8;
+public static final long[] CURVE_Cof= {0x8L,0x0L,0x0L,0x0L,0x0L};
+public static final int CURVE_A= 486662;
+public static final int CURVE_B_I= 0;
+public static final long[] CURVE_B= {0x0L,0x0L,0x0L,0x0L,0x0L};
+public static final long[] CURVE_Order= {0x12631A5CF5D3EDL,0xF9DEA2F79CD658L,0x14DEL,0x0L,0x10000000L};
+public static final long[] CURVE_Gx= {0x9L,0x0L,0x0L,0x0L,0x0L};
+public static final long[] CURVE_Gy= {0x0L,0x0L,0x0L,0x0L,0x0L};
+}
+
diff --git a/version3/java/ROM_C41417_32.java b/version3/java/ROM_C41417_32.java
new file mode 100644
index 0000000..8f18ffe
--- /dev/null
+++ b/version3/java/ROM_C41417_32.java
@@ -0,0 +1,41 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.C41417;
+
+public class ROM
+{
+
+// Base Bits= 29
+	public static final int[] Modulus= {0x1FFFFFEF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFF};
+	public static final int[] R2modp= {0x0,0x242000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int MConst= 0x11;
+
+	public static final int CURVE_Cof_I= 8;
+	public static final int[] CURVE_Cof= {0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int CURVE_A= 1;
+	public static final int CURVE_B_I= 3617;
+	public static final int[] CURVE_B= {0xE21,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int[] CURVE_Order= {0x106AF79,0x18738D2F,0x18F3C606,0x1806715A,0x22B36F1,0xA67B830,0xCF32490,0x1FFFFFFD,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1F};
+	public static final int[] CURVE_Gx= {0x13CBC595,0x7E9C097,0x14DF1931,0x14E7F550,0x1A111301,0x15A6B6B5,0xD526292,0x18FEAFFE,0x1F44C03E,0x1E6A31B4,0x70C9B97,0x43180C6,0x1443300,0x19A4828A,0x68};
+	public static final int[] CURVE_Gy= {0x22,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+}
diff --git a/version3/java/ROM_C41417_64.java b/version3/java/ROM_C41417_64.java
new file mode 100644
index 0000000..f23f20f
--- /dev/null
+++ b/version3/java/ROM_C41417_64.java
@@ -0,0 +1,44 @@
+/*
+	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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.C41417;
+
+public class ROM
+{
+
+// Base Bits= 60
+	public static final long[] Modulus= {0xFFFFFFFFFFFFFEFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFL};
+	public static final long[] R2modp= {0x121000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+	public static final long MConst= 0x11L;
+
+
+	public static final int CURVE_Cof_I= 8;
+	public static final long[] CURVE_Cof= {0x8L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+	public static final int CURVE_A= 1;
+	public static final int CURVE_B_I= 3617;
+	public static final long[] CURVE_B= {0xE21L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+	public static final long[] CURVE_Order= {0xB0E71A5E106AF79L,0x1C0338AD63CF181L,0x414CF706022B36FL,0xFFFFFFFFEB3CC92L,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0x7FFFFFFFFFFFFL};
+	public static final long[] CURVE_Gx= {0x4FD3812F3CBC595L,0x1A73FAA8537C64CL,0x4AB4D6D6BA11130L,0x3EC7F57FF35498AL,0xE5FCD46369F44C0L,0x300218C0631C326L,0x1A334905141443L};
+	public static final long[] CURVE_Gy= {0x22L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+
+}
+
diff --git a/version3/java/ROM_ED25519_32.java b/version3/java/ROM_ED25519_32.java
new file mode 100644
index 0000000..25fe27e
--- /dev/null
+++ b/version3/java/ROM_ED25519_32.java
@@ -0,0 +1,41 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.ED25519;
+
+public class ROM
+{
+
+public static final int[] Modulus= {0x1FFFFFED,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFFF};
+public static final int[] R2modp= {0x169000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+public static final int MConst= 0x13;
+
+public static final int CURVE_Cof_I= 8;
+public static final int[] CURVE_Cof= {0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+public static final int CURVE_A= -1;
+public static final int CURVE_B_I= 0;
+public static final int[] CURVE_B= {0x135978A3,0xF5A6E50,0x10762ADD,0x149A82,0x1E898007,0x3CBBBC,0x19CE331D,0x1DC56DFF,0x52036C};
+public static final int[] CURVE_Order= {0x1CF5D3ED,0x9318D2,0x1DE73596,0x1DF3BD45,0x14D,0x0,0x0,0x0,0x100000};
+public static final int[] CURVE_Gx= {0xF25D51A,0xAB16B04,0x969ECB2,0x198EC12A,0xDC5C692,0x1118FEEB,0xFFB0293,0x1A79ADCA,0x216936};
+public static final int[] CURVE_Gy= {0x6666658,0x13333333,0x19999999,0xCCCCCCC,0x6666666,0x13333333,0x19999999,0xCCCCCCC,0x666666};
+
+}
diff --git a/version3/java/ROM_ED25519_64.java b/version3/java/ROM_ED25519_64.java
new file mode 100644
index 0000000..a50866a
--- /dev/null
+++ b/version3/java/ROM_ED25519_64.java
@@ -0,0 +1,43 @@
+/*
+	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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.ED25519;
+
+public class ROM
+{
+
+public static final long[] Modulus= {0xFFFFFFFFFFFFEDL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0x7FFFFFFFL};
+public static final long[] R2modp= {0xA4000000000000L,0x5L,0x0L,0x0L,0x0L};
+public static final long MConst= 0x13;
+
+
+public static final int CURVE_Cof_I= 8;
+public static final long[] CURVE_Cof= {0x8L,0x0L,0x0L,0x0L,0x0L};
+public static final int CURVE_A= -1;
+public static final int CURVE_B_I= 0;
+public static final long[] CURVE_B= {0xEB4DCA135978A3L,0xA4D4141D8AB75L,0x797779E8980070L,0x2B6FFE738CC740L,0x52036CEEL};
+public static final long[] CURVE_Order= {0x12631A5CF5D3EDL,0xF9DEA2F79CD658L,0x14DEL,0x0L,0x10000000L};
+public static final long[] CURVE_Gx= {0x562D608F25D51AL,0xC7609525A7B2C9L,0x31FDD6DC5C692CL,0xCD6E53FEC0A4E2L,0x216936D3L};
+public static final long[] CURVE_Gy= {0x66666666666658L,0x66666666666666L,0x66666666666666L,0x66666666666666L,0x66666666L};
+
+}
+
diff --git a/version3/java/ROM_FP256BN_32.java b/version3/java/ROM_FP256BN_32.java
new file mode 100644
index 0000000..fb5c7a7
--- /dev/null
+++ b/version3/java/ROM_FP256BN_32.java
@@ -0,0 +1,56 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.FP256BN;
+
+public class ROM
+{
+
+// Base Bits= 28
+public static final int[] Modulus={0xED33013,0x292DDBA,0x80A82D3,0x65FB129,0x49F0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF};
+public static final int[] R2modp={0x3B9F8B,0xEDE3363,0xFEC54E8,0x92FFEE9,0x3C55F79,0x13C1C06,0xC0123FA,0xA12F2EA,0xE559B2A,0x8};
+public static final int MConst= 0x537E5E5;
+
+public static final int CURVE_A= 0;
+public static final int CURVE_B_I= 3;
+public static final int CURVE_Cof_I= 1;
+public static final int[] CURVE_B= {0x3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+public static final int[] CURVE_Order= {0x10B500D,0x2D536CD,0x9921AF6,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF};
+public static final int[] CURVE_Gx= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+public static final int[] CURVE_Gy= {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+
+public static final int[] Fra={0xF943106,0x760328A,0xAB28F74,0x71511E3,0x7CF39A1,0x8DDB086,0x52D1A6E,0xCA786F3,0xD617662,0x3};
+public static final int[] Frb={0xF3EFF0D,0xB32AB2F,0xD57F35E,0xF4A9F45,0xCCFD33A,0xD113693,0x819CB83,0x3584819,0x29E899D,0xC};
+public static final int[] CURVE_Bnx= {0xB0A801,0x82F5C03,0x68,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+public static final int[] CURVE_Cof= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+public static final int[] CURVE_Cru= {0x3A1B807,0x1C0A24A,0x32D1EDB,0xD79DF19,0x8659BCD,0x4092101,0x13988E1,0x0,0x0,0x0};
+public static final int[] CURVE_Pxa= {0x9C09EFB,0x2616B68,0xF843CD2,0x539A12B,0x13ACE1C,0x577C289,0x28560F,0xB4C96C2,0xE0C3350,0xF};
+public static final int[] CURVE_Pxb= {0x37E6A2B,0x69ED34A,0x3589D2,0x78E287D,0x3B924DD,0xC637D81,0x4DB5AE1,0x738AC05,0xEA66057,0x4};
+public static final int[] CURVE_Pya= {0xEDC27FF,0x9B481B,0x15848E9,0x24758D6,0xE51EFCB,0x75124E3,0x376770D,0xC542A3B,0x2046E7,0x7};
+public static final int[] CURVE_Pyb= {0xAAD049B,0x1281114,0xA98B3E0,0xBE80821,0x29F8B4C,0x49297EB,0x42EEA6,0xD388C29,0x554E3BC,0x0};
+public static final int[][] CURVE_W= {{0xB054003,0xF0036E1,0xE78663A,0xFFFFFFF,0xFFFF,0x0,0x0,0x0,0x0,0x0},{0x1615001,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+public static final int[][][] CURVE_SB= {{{0xC669004,0xF5EEEE7,0xE78670B,0xFFFFFFF,0xFFFF,0x0,0x0,0x0,0x0,0x0},{0x1615001,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x1615001,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x606100A,0x3D4FFEB,0xB19B4BB,0x65FB129,0x49D0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF}}};
+public static final int[][] CURVE_WB= {{0xD30A800,0x20678F0,0x4D2CC10,0x5555555,0x5555,0x0,0x0,0x0,0x0,0x0},{0xD7DC805,0xD6764C0,0xBC3AD1A,0x8FBEA10,0x4467DE,0x8061601,0xD105EB,0x0,0x0,0x0},{0xF173803,0xACB6061,0x5E1D6C1,0x47DF508,0x82233EF,0xC030B00,0x6882F5,0x0,0x0,0x0},{0xE91F801,0x26530F6,0x4D2CCE1,0x5555555,0x5555,0x0,0x0,0x0,0x0,0x0}};
+public static final int[][][] CURVE_BB= {{{0x5AA80D,0xAA5DACA,0x9921A8D,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF},{0x5AA80C,0xAA5DACA,0x9921A8D,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF},{0x5AA80C,0xAA5DACA,0x9921A8D,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF},{0x1615002,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x1615001,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x5AA80C,0xAA5DACA,0x9921A8D,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF},{0x5AA80D,0xAA5DACA,0x9921A8D,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF},{0x5AA80C,0xAA5DACA,0x9921A8D,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF}},{{0x1615002,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1615001,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1615001,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1615001,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0xB0A802,0x82F5C03,0x68,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x2C2A002,0xBD700C,0x1A2,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0xFAA000A,0x2767EC6,0x9921A25,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF},{0xB0A802,0x82F5C03,0x68,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+
+}
+
diff --git a/version3/java/ROM_FP256BN_64.java b/version3/java/ROM_FP256BN_64.java
new file mode 100644
index 0000000..7a8a637
--- /dev/null
+++ b/version3/java/ROM_FP256BN_64.java
@@ -0,0 +1,55 @@
+/*
+	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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.FP256BN;
+
+public class ROM
+{
+// Base Bits= 56
+public static final long[] Modulus={0x292DDBAED33013L,0x65FB12980A82D3L,0x5EEE71A49F0CDCL,0xFFFCF0CD46E5F2L,0xFFFFFFFFL};
+public static final long[] R2modp={0xEDE336303B9F8BL,0x92FFEE9FEC54E8L,0x13C1C063C55F79L,0xA12F2EAC0123FAL,0x8E559B2AL};
+public static final long MConst= 0x6C964E0537E5E5L;
+
+public static final int CURVE_A= 0;
+public static final int CURVE_B_I= 3;
+public static final int CURVE_Cof_I= 1;
+public static final long[] CURVE_B= {0x3L,0x0L,0x0L,0x0L,0x0L};
+public static final long[] CURVE_Order= {0x2D536CD10B500DL,0x65FB1299921AF6L,0x5EEE71A49E0CDCL,0xFFFCF0CD46E5F2L,0xFFFFFFFFL};
+public static final long[] CURVE_Gx= {0x1L,0x0L,0x0L,0x0L,0x0L};
+public static final long[] CURVE_Gy= {0x2L,0x0L,0x0L,0x0L,0x0L};
+
+public static final long[] Fra={0x760328AF943106L,0x71511E3AB28F74L,0x8DDB0867CF39A1L,0xCA786F352D1A6EL,0x3D617662L};
+public static final long[] Frb={0xB32AB2FF3EFF0DL,0xF4A9F45D57F35EL,0xD113693CCFD33AL,0x3584819819CB83L,0xC29E899DL};
+public static final long[] CURVE_Bnx= {0x82F5C030B0A801L,0x68L,0x0L,0x0L,0x0L};
+public static final long[] CURVE_Cof= {0x1L,0x0L,0x0L,0x0L,0x0L};
+public static final long[] CURVE_Cru= {0x1C0A24A3A1B807L,0xD79DF1932D1EDBL,0x40921018659BCDL,0x13988E1L,0x0L};
+public static final long[] CURVE_Pxa= {0x2616B689C09EFBL,0x539A12BF843CD2L,0x577C28913ACE1CL,0xB4C96C2028560FL,0xFE0C3350L};
+public static final long[] CURVE_Pxb= {0x69ED34A37E6A2BL,0x78E287D03589D2L,0xC637D813B924DDL,0x738AC054DB5AE1L,0x4EA66057L};
+public static final long[] CURVE_Pya= {0x9B481BEDC27FFL,0x24758D615848E9L,0x75124E3E51EFCBL,0xC542A3B376770DL,0x702046E7L};
+public static final long[] CURVE_Pyb= {0x1281114AAD049BL,0xBE80821A98B3E0L,0x49297EB29F8B4CL,0xD388C29042EEA6L,0x554E3BCL};
+public static final long[][] CURVE_W= {{0xF0036E1B054003L,0xFFFFFFFE78663AL,0xFFFFL,0x0L,0x0L},{0x5EB8061615001L,0xD1L,0x0L,0x0L,0x0L}};
+public static final long[][][] CURVE_SB= {{{0xF5EEEE7C669004L,0xFFFFFFFE78670BL,0xFFFFL,0x0L,0x0L},{0x5EB8061615001L,0xD1L,0x0L,0x0L,0x0L}},{{0x5EB8061615001L,0xD1L,0x0L,0x0L,0x0L},{0x3D4FFEB606100AL,0x65FB129B19B4BBL,0x5EEE71A49D0CDCL,0xFFFCF0CD46E5F2L,0xFFFFFFFFL}}};
+public static final long[][] CURVE_WB= {{0x20678F0D30A800L,0x55555554D2CC10L,0x5555L,0x0L,0x0L},{0xD6764C0D7DC805L,0x8FBEA10BC3AD1AL,0x806160104467DEL,0xD105EBL,0x0L},{0xACB6061F173803L,0x47DF5085E1D6C1L,0xC030B0082233EFL,0x6882F5L,0x0L},{0x26530F6E91F801L,0x55555554D2CCE1L,0x5555L,0x0L,0x0L}};
+public static final long[][][] CURVE_BB= {{{0xAA5DACA05AA80DL,0x65FB1299921A8DL,0x5EEE71A49E0CDCL,0xFFFCF0CD46E5F2L,0xFFFFFFFFL},{0xAA5DACA05AA80CL,0x65FB1299921A8DL,0x5EEE71A49E0CDCL,0xFFFCF0CD46E5F2L,0xFFFFFFFFL},{0xAA5DACA05AA80CL,0x65FB1299921A8DL,0x5EEE71A49E0CDCL,0xFFFCF0CD46E5F2L,0xFFFFFFFFL},{0x5EB8061615002L,0xD1L,0x0L,0x0L,0x0L}},{{0x5EB8061615001L,0xD1L,0x0L,0x0L,0x0L},{0xAA5DACA05AA80CL,0x65FB1299921A8DL,0x5EEE71A49E0CDCL,0xFFFCF0CD46E5F2L,0xFFFFFFFFL},{0xAA5DACA05AA80DL,0x65FB1299921A8DL,0x5EEE71A49E0CDCL,0xFFFCF0CD46E5F2L,0xFFFFFFFFL},{0xAA5DACA05AA80CL,0x65FB1299921A8DL,0x5EEE71A49E0CDCL,0xFFFCF0CD46E5F2L,0xFFFFFFFFL}},{{0x5EB8061615002L,0xD1L,0x0L,0x0L,0x0L},{0x5EB8061615001L,0xD1L,0x0L,0x0L,0x0L},{0x5EB8061615001L,0xD1L,0x0L,0x0L,0x0L},{0x5EB8061615001L,0xD1L,0x0L,0x0L,0x0L}},{{0x82F5C030B0A802L,0x68L,0x0L,0x0L,0x0L},{0xBD700C2C2A002L,0x1A2L,0x0L,0x0L,0x0L},{0x2767EC6FAA000AL,0x65FB1299921A25L,0x5EEE71A49E0CDCL,0xFFFCF0CD46E5F2L,0xFFFFFFFFL},{0x82F5C030B0A802L,0x68L,0x0L,0x0L,0x0L}}};
+
+}
+
diff --git a/version3/java/ROM_FP512BN_32.java b/version3/java/ROM_FP512BN_32.java
new file mode 100644
index 0000000..0f62d06
--- /dev/null
+++ b/version3/java/ROM_FP512BN_32.java
@@ -0,0 +1,55 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.FP512BN;
+
+public class ROM
+{
+// Base Bits= 29
+public static final int[] Modulus= {0x2ADEF33,0x7594049,0x131919ED,0x14AB9CBE,0x16FE1916,0x12EF5591,0x2E39231,0x3D597D3,0x55146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF};
+public static final int[] R2modp= {0xFD68B47,0xFCF5D2C,0x437675A,0x1BBC3FBF,0x1411E413,0x13453559,0x10B5639,0x1C34CE79,0x6D476BF,0xFD05F2B,0x15D17C28,0x6C9F76E,0x1C2375B3,0x78CCE9B,0x15F0AB33,0x1960F32E,0x1A8D44E,0x57A38};
+public static final int MConst= 0x1CCC5C05;
+
+public static final int CURVE_A= 0;
+public static final int CURVE_B_I= 3;
+public static final int CURVE_Cof_I= 1;
+public static final int[] CURVE_B= {0x3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+public static final int[] CURVE_Order= {0x119A09ED,0x153252FA,0x1E68AD01,0x627C09,0x79A34A1,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF};
+public static final int[] CURVE_Gx= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+public static final int[] CURVE_Gy= {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+
+public static final int[] Fra= {0x14B73AB2,0x4B0BD8F,0xABB47D,0x2A29EC4,0x18681E17,0x104069DE,0x12EED67D,0x1553D0A5,0x398E9F8,0x7971034,0xAC9AF23,0x52DEF23,0x14EA18A5,0x1463E345,0x6DE465A,0x17F212B4,0x1AA9CF5B,0xF7B8};
+public static final int[] Frb= {0xDF6B481,0x2A882B9,0x126D6570,0x1208FDFA,0x1E95FAFF,0x2AEEBB2,0xFF4BBB4,0xE81C72D,0x1B85CD6,0xF67746,0x56549CD,0xC68B6EC,0x776A178,0x8925C3B,0x1921B9A5,0x80DED4B,0x55630A4,0x70847};
+public static final int[] CURVE_Bnx= {0x1E1BD80F,0x59835DA,0xC3DFC04,0x5EB8061,0x688,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+public static final int[] CURVE_Cof= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+public static final int[] CURVE_Cru= {0x1C79298A,0x1838B104,0x2C5F052,0x1DCCF337,0x6092AEC,0x4B35F29,0x1EB361E,0x11384EA,0x3074B20,0x17BB08FD,0x3A8B3E3,0xD70D66F,0x3D2A614,0x1CF63EE4,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF};
+public static final int[] CURVE_Pxa= {0xDB646B5,0x183D4B70,0x1CBFFA3,0x11F0E632,0x1C78F221,0x1F10DE5D,0x171B715E,0xF0C6A29,0x10B02453,0xBE63C66,0xE6D5F69,0x166B1E1B,0x4BBBD29,0x179E750F,0x6E9D04,0xC912B10,0x1339E138,0x1D8B2};
+public static final int[] CURVE_Pxb= {0x1A8AE0E9,0xDAE5F7E,0x22446CF,0x1948239B,0x15ADCE40,0xB709C1E,0x18357943,0xE50AA4D,0x19781E22,0x12B35CA6,0x11DAA2C0,0x18D8DDE4,0x5EA656D,0x15F45A41,0xD311A02,0xCFCD913,0x13CBF850,0x240E0};
+public static final int[] CURVE_Pya= {0xDDE67A1,0x12401895,0x17BEE178,0x142F5AC2,0xB7BC5CD,0x92A1404,0x1A3B748C,0x17BD82A7,0x14B6CD18,0xAC34CE,0x1740FB97,0x1ECC15F9,0x17085B1D,0x1D1BA793,0x1BD6AC32,0x18F70525,0xC84C827,0x3780F};
+public static final int[] CURVE_Pyb= {0x84F8E8B,0xC5B8C36,0xFDD85A1,0xB84449,0x19C08DFF,0x56BF713,0x1C5290C4,0x187C5CA0,0x1DA2897F,0x24B0CA0,0x326D8F4,0x2310CF6,0x1021438C,0xFBAEC8F,0xD9030C5,0x1CF06358,0x1CEC8B04,0x28D1D};
+public static final int[][] CURVE_W= {{0x9834583,0x887C4BA,0x5A85CFC,0xBF7223A,0xF63FE96,0x1FFFFFFE,0x1FFFFFFF,0x1FFFFFFF,0xFFFFFF,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1C37B01F,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+public static final int[][][] CURVE_SB= {{{0xD4B9564,0x1D575904,0xD2C64F3,0x202177,0xF63F186,0x1FFFFFFE,0x1FFFFFFF,0x1FFFFFFF,0xFFFFFF,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x156259CE,0xA01E744,0x5ECB4F9,0x148B7B47,0x79A2790,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF}},{{0x1C37B01F,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x9834583,0x887C4BA,0x5A85CFC,0xBF7223A,0xF63FE96,0x1FFFFFFE,0x1FFFFFFF,0x1FFFFFFF,0xFFFFFF,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}};
+public static final int[][] CURVE_WB= {{0x155A29F0,0x16D59B55,0xF4C305,0x18858C0B,0x5215FBF,0xAAAAAAA,0x15555555,0xAAAAAAA,0x555555,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x2355D4B,0x1758095D,0x1FE13C5F,0x41F83FA,0xBB5E5CF,0x97D4EF1,0xB503D62,0x172C0C9B,0x16315274,0x15E1A9A8,0x859835D,0x2C3DFC0,0x105EB806,0x68,0x0,0x0,0x0,0x0},{0x289AAD,0x1E781F9C,0x60F9C31,0x1505822E,0x15DAF62B,0x4BEA778,0x15A81EB1,0xB96064D,0xB18A93A,0x1AF0D4D4,0x42CC1AE,0x161EFE0,0x82F5C03,0x34,0x0,0x0,0x0,0x0},{0x192279D1,0xBA52F9F,0x878CAFD,0xCAE8B48,0x52152AF,0xAAAAAAA,0x15555555,0xAAAAAAA,0x555555,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}};
+public static final int[][][] CURVE_BB= {{{0x1E1BD810,0x59835DA,0xC3DFC04,0x5EB8061,0x688,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1E1BD80F,0x59835DA,0xC3DFC04,0x5EB8061,0x688,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1E1BD80F,0x59835DA,0xC3DFC04,0x5EB8061,0x688,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x156259CF,0xA01E744,0x5ECB4F9,0x148B7B47,0x79A2790,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF}},{{0x1C37B01F,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x137E31DE,0xF9A1D1F,0x122AB0FD,0x1A76FBA8,0x79A2E18,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF},{0x137E31DD,0xF9A1D1F,0x122AB0FD,0x1A76FBA8,0x79A2E18,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF},{0x137E31DE,0xF9A1D1F,0x122AB0FD,0x1A76FBA8,0x79A2E18,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF}},{{0x1C37B01E,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1C37B01F,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1C37B01F,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x1C37B01F,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}},{{0x137E31DF,0xF9A1D1F,0x122AB0FD,0x1A76FBA8,0x79A2E18,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF},{0x192AA9AF,0x1ED17B8E,0xD70BCF0,0x8B47A84,0x79A1A80,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF},{0x1C37B01D,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},{0x137E31DF,0xF9A1D1F,0x122AB0FD,0x1A76FBA8,0x79A2E18,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF}}};
+
+}
+
diff --git a/version3/java/ROM_FP512BN_64.java b/version3/java/ROM_FP512BN_64.java
new file mode 100644
index 0000000..0d2db45
--- /dev/null
+++ b/version3/java/ROM_FP512BN_64.java
@@ -0,0 +1,56 @@
+/*
+	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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.FP512BN;
+
+public class ROM
+{
+
+// Base Bits= 60
+public static final long[] Modulus= {0x4EB280922ADEF33L,0x6A55CE5F4C6467BL,0xC65DEAB236FE191L,0xCF1EACBE98B8E48L,0x3C111B0EF455146L,0xA1D8CB5307C0BBEL,0xFFFF9EC7F01C60BL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFL};
+public static final long[] R2modp= {0x1FA6DCEF99812E9L,0xAB3452895A0B74EL,0xC53EA988C079E1EL,0x1E90E033BA630B9L,0xF1EA41C0714D8B0L,0xE72785387509E28L,0xD86794F834DAB00L,0x9757C2ACCD342A1L,0x44ECB079L};
+public static final long MConst= 0x692A189FCCC5C05L;
+
+public static final int CURVE_A= 0;
+public static final int CURVE_B_I= 3;
+public static final int CURVE_Cof_I= 1;
+public static final long[] CURVE_B= {0x3L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+public static final long[] CURVE_Order= {0x6A64A5F519A09EDL,0x10313E04F9A2B40L,0xC65DEAB2679A34AL,0xCF1EACBE98B8E48L,0x3C111B0EF445146L,0xA1D8CB5307C0BBEL,0xFFFF9EC7F01C60BL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFL};
+public static final long[] CURVE_Gx= {0x1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+public static final long[] CURVE_Gy= {0x2L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+
+public static final long[] Fra= {0x49617B1F4B73AB2L,0x71514F6202AED1FL,0xF6080D3BD8681E1L,0xF8AA9E852CBBB59L,0xC8CF2E2068398E9L,0x8A5296F791AB26BL,0x196A8C7C68B4EA1L,0xCF5BBF9095A1B79L,0x1EF71AA9L};
+public static final long[] Frb= {0x5510572DF6B481L,0xF9047EFD49B595CL,0xD055DD765E95FAFL,0xD6740E396BFD2EEL,0x7341ECEE8C1B85CL,0x1786345B7615952L,0xE695124B876776AL,0x30A4406F6A5E486L,0xE108E556L};
+public static final long[] CURVE_Bnx= {0xB306BB5E1BD80FL,0x82F5C030B0F7F01L,0x68L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+public static final long[] CURVE_Cof= {0x1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+public static final long[] CURVE_Cru= {0xB0716209C79298AL,0xCEE6799B8B17C14L,0x78966BE526092AEL,0x20089C27507ACD8L,0xF8EF7611FA3074BL,0x6146B86B378EA2CL,0xFFFF9EC7DC83D2AL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFL};
+public static final long[] CURVE_Pxa= {0xF07A96E0DB646B5L,0x18F87319072FFE8L,0x7BE21BCBBC78F22L,0x537863514DC6DC5L,0xDA57CC78CD0B024L,0xD29B358F0DB9B57L,0x7412F3CEA1E4BBBL,0xE138648958801BAL,0x3B165339L};
+public static final long[] CURVE_Pxb= {0xDB5CBEFDA8AE0E9L,0xCA411CD88911B3L,0xD6E1383D5ADCE4L,0x227285526E0D5E5L,0xB02566B94D9781EL,0x56DC6C6EF2476A8L,0x680ABE8B4825EA6L,0xF85067E6C89B4C4L,0x481C13CBL};
+public static final long[] CURVE_Pya= {0x2480312ADDE67A1L,0xDA17AD615EFB85EL,0x312542808B7BC5CL,0x18BDEC153E8EDD2L,0xE5C158699D4B6CDL,0xB1DF660AFCDD03EL,0xB0CBA374F277085L,0xC827C7B8292EF5AL,0x6F01EC84L};
+public static final long[] CURVE_Pyb= {0x58B7186C84F8E8BL,0xF05C2224BF76168L,0x10AD7EE279C08DFL,0x7FC3E2E50714A43L,0x3D04961941DA289L,0x38C118867B0C9B6L,0xC315F75D91F0214L,0x8B04E7831AC3640L,0x51A3BCECL};
+public static final long[][] CURVE_W= {{0x110F89749834583L,0x65FB911D16A173FL,0xFFFFFFFFCF63FE9L,0xFFFFFFFFFFFFFFFL,0xFFFFL,0x0L,0x0L,0x0L,0x0L},{0x1660D76BC37B01FL,0x5EB806161EFE02L,0xD1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}};
+public static final long[][][] CURVE_SB= {{{0xFAAEB208D4B9564L,0x601010BBB4B193CL,0xFFFFFFFFCF63F18L,0xFFFFFFFFFFFFFFFL,0xFFFFL,0x0L,0x0L,0x0L,0x0L},{0x5403CE8956259CEL,0xA45BDA397B2D3EL,0xC65DEAB2679A279L,0xCF1EACBE98B8E48L,0x3C111B0EF445146L,0xA1D8CB5307C0BBEL,0xFFFF9EC7F01C60BL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFL}},{{0x1660D76BC37B01FL,0x5EB806161EFE02L,0xD1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x110F89749834583L,0x65FB911D16A173FL,0xFFFFFFFFCF63FE9L,0xFFFFFFFFFFFFFFFL,0xFFFFL,0x0L,0x0L,0x0L,0x0L}}};
+public static final long[][] CURVE_WB= {{0x6DAB36AB55A29F0L,0xFC42C60583D30C1L,0x5555555545215FBL,0x555555555555555L,0x5555L,0x0L,0x0L,0x0L,0x0L},{0xEEB012BA2355D4BL,0xF20FC1FD7F84F17L,0x892FA9DE2BB5E5CL,0x74B96064DAD40F5L,0xD76BC3535163152L,0x806161EFE021660L,0xD105EBL,0x0L,0x0L},{0x7CF03F380289AADL,0xBA82C117183E70CL,0xC497D4EF15DAF62L,0x3A5CB0326D6A07AL,0x6BB5E1A9A8B18A9L,0xC030B0F7F010B30L,0x6882F5L,0x0L,0x0L},{0x574A5F3F92279D1L,0xF65745A421E32BFL,0x55555555452152AL,0x555555555555555L,0x5555L,0x0L,0x0L,0x0L,0x0L}};
+public static final long[][][] CURVE_BB= {{{0xB306BB5E1BD810L,0x82F5C030B0F7F01L,0x68L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0xB306BB5E1BD80FL,0x82F5C030B0F7F01L,0x68L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0xB306BB5E1BD80FL,0x82F5C030B0F7F01L,0x68L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x5403CE8956259CFL,0xA45BDA397B2D3EL,0xC65DEAB2679A279L,0xCF1EACBE98B8E48L,0x3C111B0EF445146L,0xA1D8CB5307C0BBEL,0xFFFF9EC7F01C60BL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFL}},{{0x1660D76BC37B01FL,0x5EB806161EFE02L,0xD1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x5F343A3F37E31DEL,0x8D3B7DD448AAC3FL,0xC65DEAB2679A2E1L,0xCF1EACBE98B8E48L,0x3C111B0EF445146L,0xA1D8CB5307C0BBEL,0xFFFF9EC7F01C60BL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFL},{0x5F343A3F37E31DDL,0x8D3B7DD448AAC3FL,0xC65DEAB2679A2E1L,0xCF1EACBE98B8E48L,0x3C111B0EF445146L,0xA1D8CB5307C0BBEL,0xFFFF9EC7F01C60BL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFL},{0x5F343A3F37E31DEL,0x8D3B7DD448AAC3FL,0xC65DEAB2679A2E1L,0xCF1EACBE98B8E48L,0x3C111B0EF445146L,0xA1D8CB5307C0BBEL,0xFFFF9EC7F01C60BL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFL}},{{0x1660D76BC37B01EL,0x5EB806161EFE02L,0xD1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x1660D76BC37B01FL,0x5EB806161EFE02L,0xD1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x1660D76BC37B01FL,0x5EB806161EFE02L,0xD1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x1660D76BC37B01FL,0x5EB806161EFE02L,0xD1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L}},{{0x5F343A3F37E31DFL,0x8D3B7DD448AAC3FL,0xC65DEAB2679A2E1L,0xCF1EACBE98B8E48L,0x3C111B0EF445146L,0xA1D8CB5307C0BBEL,0xFFFF9EC7F01C60BL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFL},{0x3DA2F71D92AA9AFL,0x45A3D4235C2F3CL,0xC65DEAB2679A1A8L,0xCF1EACBE98B8E48L,0x3C111B0EF445146L,0xA1D8CB5307C0BBEL,0xFFFF9EC7F01C60BL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFL},{0x1660D76BC37B01DL,0x5EB806161EFE02L,0xD1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L},{0x5F343A3F37E31DFL,0x8D3B7DD448AAC3FL,0xC65DEAB2679A2E1L,0xCF1EACBE98B8E48L,0x3C111B0EF445146L,0xA1D8CB5307C0BBEL,0xFFFF9EC7F01C60BL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFL}}};
+
+}
+
diff --git a/version3/java/ROM_GOLDILOCKS_32.java b/version3/java/ROM_GOLDILOCKS_32.java
new file mode 100644
index 0000000..f4f3473
--- /dev/null
+++ b/version3/java/ROM_GOLDILOCKS_32.java
@@ -0,0 +1,43 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.GOLDILOCKS;
+
+public class ROM
+{
+
+// Base Bits= 29
+public static final int[] Modulus= {0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FDFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFF};
+public static final int[] R2modp= {0x0,0x10,0x0,0x0,0x0,0x0,0x0,0x0,0x3000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+public static final int MConst=0x1;
+
+public static final int CURVE_Cof_I= 4;
+public static final int[] CURVE_Cof= {0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+public static final int CURVE_A= 1;
+public static final int CURVE_B_I= -39081;
+public static final int[] CURVE_B= {0x1FFF6756,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FDFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFF};
+public static final int[] CURVE_Order= {0xB5844F3,0x1BC61495,0x1163D548,0x1984E51B,0x3690216,0xDA4D76B,0xFA7113B,0x1FEF9944,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FF};
+public static final int[] CURVE_Gx= {0x15555555,0xAAAAAAA,0x15555555,0xAAAAAAA,0x15555555,0xAAAAAAA,0x15555555,0x152AAAAA,0xAAAAAAA,0x15555555,0xAAAAAAA,0x15555555,0xAAAAAAA,0x15555555,0xAAAAAAA,0x1555};
+public static final int[] CURVE_Gy= {0xA9386ED,0x1757DE6F,0x13681AF6,0x19657DA3,0x3098BBB,0x12C19D15,0x12E03595,0xE515B18,0x17B7E36D,0x1AC426E,0xDBB5E8,0x10D8560,0x159D6205,0xB8246D9,0x17A58D2B,0x15C0};
+
+
+}
diff --git a/version3/java/ROM_GOLDILOCKS_64.java b/version3/java/ROM_GOLDILOCKS_64.java
new file mode 100644
index 0000000..b402de7
--- /dev/null
+++ b/version3/java/ROM_GOLDILOCKS_64.java
@@ -0,0 +1,44 @@
+/*
+	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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.GOLDILOCKS;
+
+public class ROM
+{
+
+// Base Bits= 58
+public static final long[] Modulus= {0x3FFFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFFL,0x3FBFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFFL,0x3FFFFFFFFFFL};
+public static final long[] R2modp= {0x200000000L,0x0L,0x0L,0x0L,0x3000000L,0x0L,0x0L,0x0L};
+public static final long MConst= 0x1L;
+
+
+public static final int CURVE_Cof_I= 4;
+public static final long[] CURVE_Cof= {0x4L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+public static final int CURVE_A= 1;
+public static final int CURVE_B_I= -39081;
+public static final long[] CURVE_B= {0x3FFFFFFFFFF6756L,0x3FFFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFFL,0x3FBFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFFL,0x3FFFFFFFFFFL};
+public static final long[] CURVE_Order= {0x378C292AB5844F3L,0x3309CA37163D548L,0x1B49AED63690216L,0x3FDF3288FA7113BL,0x3FFFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFFL,0xFFFFFFFFFFL};
+public static final long[] CURVE_Gx= {0x155555555555555L,0x155555555555555L,0x155555555555555L,0x2A5555555555555L,0x2AAAAAAAAAAAAAAL,0x2AAAAAAAAAAAAAAL,0x2AAAAAAAAAAAAAAL,0x2AAAAAAAAAAL};
+public static final long[] CURVE_Gy= {0x2EAFBCDEA9386EDL,0x32CAFB473681AF6L,0x25833A2A3098BBBL,0x1CA2B6312E03595L,0x35884DD7B7E36DL,0x21B0AC00DBB5E8L,0x17048DB359D6205L,0x2B817A58D2BL};
+
+}
+
diff --git a/version3/java/ROM_HIFIVE_32.java b/version3/java/ROM_HIFIVE_32.java
new file mode 100644
index 0000000..86b9b5a
--- /dev/null
+++ b/version3/java/ROM_HIFIVE_32.java
@@ -0,0 +1,42 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.HIFIVE;
+
+public class ROM
+{
+
+// Base Bits= 29
+	public static final int[] Modulus= {0x1FFFFFFD,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFF};
+	public static final int[] R2modp= {0x9000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int MConst= 0x3;
+
+	public static final int CURVE_Cof_I= 8;
+	public static final int[] CURVE_Cof= {0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int CURVE_A= 1;
+	public static final int CURVE_B_I= 11111;
+	public static final int[] CURVE_B= {0x2B67,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int[] CURVE_Order= {0x1E9FA805,0x197CACB9,0x1E4EEA9E,0x17AD70F,0x1FA9850C,0x38A0A,0x0,0x0,0x0,0x0,0x0,0x4000};
+	public static final int[] CURVE_Gx= {0xC,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int[] CURVE_Gy= {0x5FE8632,0x15F63428,0xD976C4,0x1AACA194,0x35B6DB5,0x8E3F7A,0x52D1B0E,0xF0A7A36,0x1C161D00,0x8170C70,0x1185AD59,0x181B};
+
+}
diff --git a/version3/java/ROM_HIFIVE_64.java b/version3/java/ROM_HIFIVE_64.java
new file mode 100644
index 0000000..bed83e6
--- /dev/null
+++ b/version3/java/ROM_HIFIVE_64.java
@@ -0,0 +1,43 @@
+/*
+	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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.HIFIVE;
+
+public class ROM
+{
+
+// Base Bits= 60
+	public static final long[] Modulus= {0xFFFFFFFFFFFFFFDL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFL};
+	public static final long[] R2modp= {0x9000000000000L,0x0L,0x0L,0x0L,0x0L,0x0L};
+	public static final long MConst= 0x3L;
+
+	public static final int CURVE_Cof_I= 8;
+	public static final long[] CURVE_Cof= {0x8L,0x0L,0x0L,0x0L,0x0L,0x0L};
+	public static final int CURVE_A= 1;
+	public static final int CURVE_B_I= 11111;
+	public static final long[] CURVE_B= {0x2B67L,0x0L,0x0L,0x0L,0x0L,0x0L};
+	public static final long[] CURVE_Order= {0xB2F95973E9FA805L,0xC0BD6B87F93BAA7L,0x71415FA9850L,0x0L,0x0L,0x200000000L};
+	public static final long[] CURVE_Gx= {0xCL,0x0L,0x0L,0x0L,0x0L,0x0L};
+	public static final long[] CURVE_Gy= {0x2BEC68505FE8632L,0x5D5650CA0365DB1L,0x3811C7EF435B6DBL,0x7853D1B14B46CL,0x56502E18E1C161DL,0xC0DC616BL};
+
+}
+
diff --git a/version3/java/ROM_NIST256_32.java b/version3/java/ROM_NIST256_32.java
new file mode 100644
index 0000000..fcae488
--- /dev/null
+++ b/version3/java/ROM_NIST256_32.java
@@ -0,0 +1,45 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.NIST256;
+
+
+public class ROM
+{
+
+// Base Bits= 28
+	public static final int[] Modulus= {0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFF,0x0,0x0,0x1000000,0x0,0xFFFFFFF,0xF};
+	public static final int[] R2modp= {0x50000,0x300000,0x0,0x0,0xFFFFFFA,0xFFFFFBF,0xFFFFEFF,0xFFFAFFF,0x2FFFF,0x0};
+	public static final int MConst= 0x1;
+
+	public static final int CURVE_Cof_I= 1;
+	public static final int[] CURVE_Cof= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int CURVE_A= -3;
+	public static final int CURVE_B_I= 0;
+	public static final int[] CURVE_B= {0x7D2604B,0xCE3C3E2,0x3B0F63B,0x6B0CC5,0x6BC651D,0x5576988,0x7B3EBBD,0xAA3A93E,0xAC635D8,0x5};
+	public static final int[] CURVE_Order= {0xC632551,0xB9CAC2F,0x79E84F3,0xFAADA71,0xFFFBCE6,0xFFFFFFF,0xFFFFFF,0x0,0xFFFFFFF,0xF};
+	public static final int[] CURVE_Gx= {0x898C296,0xA13945D,0xB33A0F4,0x7D812DE,0xF27703,0xE563A44,0x7F8BCE6,0xE12C424,0xB17D1F2,0x6};
+	public static final int[] CURVE_Gy= {0x7BF51F5,0xB640683,0x15ECECB,0x33576B3,0xE162BCE,0x4A7C0F9,0xB8EE7EB,0xFE1A7F9,0xFE342E2,0x4};
+
+}
+
+
diff --git a/version3/java/ROM_NIST256_64.java b/version3/java/ROM_NIST256_64.java
new file mode 100644
index 0000000..6cbdddf
--- /dev/null
+++ b/version3/java/ROM_NIST256_64.java
@@ -0,0 +1,43 @@
+/*
+	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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.NIST256;
+
+public class ROM
+{
+
+// Base Bits= 56
+	public static final long[] Modulus= {0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFL,0x0L,0x1000000L,0xFFFFFFFFL};
+	public static final long[] R2modp= {0x3000000050000L,0x0L,0xFFFFFBFFFFFFFAL,0xFFFAFFFFFFFEFFL,0x2FFFFL};
+	public static final long MConst= 0x1L;
+
+	public static final int CURVE_Cof_I= 1;
+	public static final long[] CURVE_Cof= {0x1L,0x0L,0x0L,0x0L,0x0L};
+	public static final int CURVE_A= -3;
+	public static final int CURVE_B_I= 0;
+	public static final long[] CURVE_B= {0xCE3C3E27D2604BL,0x6B0CC53B0F63BL,0x55769886BC651DL,0xAA3A93E7B3EBBDL,0x5AC635D8L};
+	public static final long[] CURVE_Order= {0xB9CAC2FC632551L,0xFAADA7179E84F3L,0xFFFFFFFFFFBCE6L,0xFFFFFFL,0xFFFFFFFFL};
+	public static final long[] CURVE_Gx= {0xA13945D898C296L,0x7D812DEB33A0F4L,0xE563A440F27703L,0xE12C4247F8BCE6L,0x6B17D1F2L};
+	public static final long[] CURVE_Gy= {0xB6406837BF51F5L,0x33576B315ECECBL,0x4A7C0F9E162BCEL,0xFE1A7F9B8EE7EBL,0x4FE342E2L};
+
+}
+
diff --git a/version3/java/ROM_NIST384_32.java b/version3/java/ROM_NIST384_32.java
new file mode 100644
index 0000000..3f70c6e
--- /dev/null
+++ b/version3/java/ROM_NIST384_32.java
@@ -0,0 +1,43 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.NIST384;
+
+public class ROM
+{
+
+// Base Bits= 29
+	public static final int[] Modulus= {0x1FFFFFFF,0x7,0x0,0x1FFFFE00,0x1FFFEFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F};
+	public static final int[] R2modp= {0x0,0x8000,0x1FF80000,0x1FFFFF,0x2000000,0x0,0x0,0x1FFFFFFC,0xF,0x100,0x400,0x0,0x0,0x0};
+	public static final int MConst= 0x1;
+
+	public static final int CURVE_Cof_I= 1;
+	public static final int[] CURVE_Cof= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int CURVE_A= -3;
+	public static final int CURVE_B_I= 0;
+	public static final int[] CURVE_B= {0x13EC2AEF,0x142E476E,0xBB4674A,0xC731B14,0x1875AC65,0x447A809,0x4480C50,0xDDFD028,0x19181D9C,0x1F1FC168,0x623815A,0x47DCFC9,0x1312FA7E,0x59};
+	public static final int[] CURVE_Order= {0xCC52973,0x760CB56,0xC29DEBB,0x141B6491,0x12DDF581,0x6C0FA1B,0x1FFF1D8D,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F};
+	public static final int[] CURVE_Gx= {0x12760AB7,0x12A2F1C3,0x154A5B0E,0x5E4BB7E,0x2A38550,0xF0412A,0xE6167DD,0xC5174F3,0x146E1D3B,0x1799056B,0x3AC71C7,0x1D160A6F,0x87CA22B,0x55};
+	public static final int[] CURVE_Gy= {0x10EA0E5F,0x1218EBE4,0x1FA0675E,0x1639C3A,0xB8C00A6,0x1889DAF8,0x11F3A768,0x17A51342,0x9F8F41D,0x1C9496E1,0x1767A62F,0xC4C58DE,0x17DE4A9,0x1B};
+
+
+}
diff --git a/version3/java/ROM_NIST384_64.java b/version3/java/ROM_NIST384_64.java
new file mode 100644
index 0000000..94ca0e7
--- /dev/null
+++ b/version3/java/ROM_NIST384_64.java
@@ -0,0 +1,44 @@
+/*
+	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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.NIST384;
+
+public class ROM
+{
+
+// Base Bits= 56
+	public static final long[] Modulus= {0xFFFFFFFFL,0xFFFF0000000000L,0xFFFFFFFFFEFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFL};
+	public static final long[] R2modp= {0xFE000000010000L,0xFFFFFFL,0x2L,0xFFFFFFFE00L,0x1000000020000L,0x0L,0x0L};
+	public static final long MConst= 0x100000001L;
+
+	public static final int CURVE_Cof_I= 1;
+	public static final long[] CURVE_Cof= {0x1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+	public static final int CURVE_A= -3;
+	public static final int CURVE_B_I= 0;
+	public static final long[] CURVE_B= {0x85C8EDD3EC2AEFL,0x398D8A2ED19D2AL,0x8F5013875AC656L,0xFE814112031408L,0xF82D19181D9C6EL,0xE7E4988E056BE3L,0xB3312FA7E23EL};
+	public static final long[] CURVE_Order= {0xEC196ACCC52973L,0xDB248B0A77AECL,0x81F4372DDF581AL,0xFFFFFFFFC7634DL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFL};
+	public static final long[] CURVE_Gx= {0x545E3872760AB7L,0xF25DBF55296C3AL,0xE082542A385502L,0x8BA79B9859F741L,0x20AD746E1D3B62L,0x5378EB1C71EF3L,0xAA87CA22BE8BL};
+	public static final long[] CURVE_Gy= {0x431D7C90EA0E5FL,0xB1CE1D7E819D7AL,0x13B5F0B8C00A60L,0x289A147CE9DA31L,0x92DC29F8F41DBDL,0x2C6F5D9E98BF92L,0x3617DE4A9626L};
+
+
+}
+
diff --git a/version3/java/ROM_NIST521_32.java b/version3/java/ROM_NIST521_32.java
new file mode 100644
index 0000000..86f7530
--- /dev/null
+++ b/version3/java/ROM_NIST521_32.java
@@ -0,0 +1,43 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.NIST521;
+
+public class ROM
+{
+
+// Base Bits= 28
+	public static final int[] Modulus= {0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0x1FFFF};
+	public static final int[] R2modp= {0x400000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int MConst= 0x1;
+
+	public static final int CURVE_Cof_I= 1;
+	public static final int[] CURVE_Cof= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int CURVE_A= -3;
+	public static final int CURVE_B_I= 0;
+	public static final int[] CURVE_B= {0xB503F00,0x451FD46,0xC34F1EF,0xDF883D2,0xF073573,0xBD3BB1B,0xB1652C0,0xEC7E937,0x6193951,0xF109E15,0x489918E,0x15F3B8B,0x25B99B3,0xEEA2DA7,0xB68540,0x929A21A,0xE1C9A1F,0x3EB9618,0x5195};
+	public static final int[] CURVE_Order= {0x1386409,0x6FB71E9,0xC47AEBB,0xC9B8899,0x5D03BB5,0x48F709A,0xB7FCC01,0xBF2F966,0x1868783,0xFFFFFA5,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0x1FFFF};
+	public static final int[] CURVE_Gx= {0x2E5BD66,0x7E7E31C,0xA429BF9,0xB3C1856,0x8DE3348,0x27A2FFA,0x8FE1DC1,0xEFE7592,0x14B5E77,0x4D3DBAA,0x8AF606B,0xB521F82,0x139053F,0x429C648,0x62395B4,0x9E3ECB6,0x404E9CD,0x8E06B70,0xC685};
+	public static final int[] CURVE_Gy= {0xFD16650,0xBE94769,0x2C24088,0x7086A27,0x761353C,0x13FAD0,0xC550B9,0x5EF4264,0x7EE7299,0x3E662C9,0xFBD1727,0x446817A,0x449579B,0xD998F54,0x42C7D1B,0x5C8A5FB,0xA3BC004,0x296A789,0x11839};
+
+
+}
diff --git a/version3/java/ROM_NIST521_64.java b/version3/java/ROM_NIST521_64.java
new file mode 100644
index 0000000..a7b4e42
--- /dev/null
+++ b/version3/java/ROM_NIST521_64.java
@@ -0,0 +1,44 @@
+/*
+	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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.NIST521;
+
+public class ROM
+{
+
+// Base Bits= 60
+	public static final long[] Modulus= {0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0x1FFFFFFFFFFL};
+	public static final long[] R2modp= {0x4000000000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+	public static final long MConst= 0x1L;
+
+
+	public static final int CURVE_Cof_I= 1;
+	public static final long[] CURVE_Cof= {0x1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+	public static final int CURVE_A= -3;
+	public static final int CURVE_B_I= 0;
+	public static final long[] CURVE_B= {0xF451FD46B503F00L,0x73DF883D2C34F1EL,0x2C0BD3BB1BF0735L,0x3951EC7E937B165L,0x9918EF109E15619L,0x5B99B315F3B8B48L,0xB68540EEA2DA72L,0x8E1C9A1F929A21AL,0x51953EB961L};
+	public static final long[] CURVE_Order= {0xB6FB71E91386409L,0xB5C9B8899C47AEBL,0xC0148F709A5D03BL,0x8783BF2F966B7FCL,0xFFFFFFFFFFA5186L,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0x1FFFFFFFFFFL};
+	public static final long[] CURVE_Gx= {0x97E7E31C2E5BD66L,0x48B3C1856A429BFL,0xDC127A2FFA8DE33L,0x5E77EFE75928FE1L,0xF606B4D3DBAA14BL,0x39053FB521F828AL,0x62395B4429C6481L,0x404E9CD9E3ECB6L,0xC6858E06B7L};
+	public static final long[] CURVE_Gy= {0x8BE94769FD16650L,0x3C7086A272C2408L,0xB9013FAD076135L,0x72995EF42640C55L,0xD17273E662C97EEL,0x49579B446817AFBL,0x42C7D1BD998F544L,0x9A3BC0045C8A5FBL,0x11839296A78L};
+
+}
+
diff --git a/version3/java/ROM_NUMS256E_32.java b/version3/java/ROM_NUMS256E_32.java
new file mode 100644
index 0000000..eaf9d41
--- /dev/null
+++ b/version3/java/ROM_NUMS256E_32.java
@@ -0,0 +1,39 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.NUMS256E;
+
+public class ROM
+{
+	public static final int[] Modulus= {0x1FFFFF43,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFFFFFF};
+	public static final int[] R2modp= {0x22E2400,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int MConst= 0xBD;
+
+	public static final int CURVE_Cof_I= 4;
+	public static final int[] CURVE_Cof= {0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int CURVE_A= 1;
+	public static final int CURVE_B_I= -15342;
+	public static final int[] CURVE_B= {0x1FFFC355,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFFFFFF};
+	public static final int[] CURVE_Order= {0xEDD4AF5,0x123D8C87,0x1650E6C6,0xAB54A5E,0x419,0x0,0x0,0x0,0x400000};
+	public static final int[] CURVE_Gx= {0xEED13DA,0x6F60481,0x20D61A8,0x13141DC6,0x9BD60C3,0x1EAFB490,0xDF73478,0x1F6D5D44,0x8A7514};
+	public static final int[] CURVE_Gy= {0x198A89E6,0x1D30B73B,0x15BB4CB,0x1EC3B021,0x18010715,0x12ECD325,0x171F3A59,0x13FB3B24,0x44D53E};
+}
diff --git a/version3/java/ROM_NUMS256E_64.java b/version3/java/ROM_NUMS256E_64.java
new file mode 100644
index 0000000..dada8b2
--- /dev/null
+++ b/version3/java/ROM_NUMS256E_64.java
@@ -0,0 +1,42 @@
+/*
+	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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.NUMS256E;
+
+public class ROM
+{
+	public static final long[] Modulus= {0xFFFFFFFFFFFF43L,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFL};
+	public static final long[] R2modp= {0x89000000000000L,0x8BL,0x0L,0x0L,0x0L};
+	public static final long MConst= 0xBDL;
+
+	public static final int CURVE_Cof_I= 4;
+	public static final long[] CURVE_Cof= {0x4L,0x0L,0x0L,0x0L,0x0L};
+	public static final int CURVE_A= 1;
+	public static final int CURVE_B_I= -15342;
+	public static final long[] CURVE_B= {0xFFFFFFFFFFC355L,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFL};
+	public static final long[] CURVE_Order= {0x47B190EEDD4AF5L,0x5AA52F59439B1AL,0x4195L,0x0L,0x40000000L};
+	public static final long[] CURVE_Gx= {0xDEC0902EED13DAL,0x8A0EE3083586A0L,0x5F69209BD60C39L,0x6AEA237DCD1E3DL,0x8A7514FBL};
+	public static final long[] CURVE_Gy= {0xA616E7798A89E6L,0x61D810856ED32FL,0xD9A64B8010715FL,0xD9D925C7CE9665L,0x44D53E9FL};
+
+
+}
+
diff --git a/version3/java/ROM_NUMS256W_32.java b/version3/java/ROM_NUMS256W_32.java
new file mode 100644
index 0000000..a3e47bc
--- /dev/null
+++ b/version3/java/ROM_NUMS256W_32.java
@@ -0,0 +1,44 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.NUMS256W;
+
+public class ROM
+{
+
+// Modulus
+	public static final int[] Modulus= {0xFFFFF43,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xF};
+	public static final int[] R2modp= {0x0,0x8900000,0x8B,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int MConst= 0xBD;
+// Curve
+
+	public static final int CURVE_Cof_I= 1;
+	public static final int[] CURVE_Cof= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int CURVE_A= -3;
+	public static final int CURVE_B_I= 152961;
+	public static final int[] CURVE_B= {0x25581,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int[] CURVE_Order= {0x751A825,0xAB20294,0x65C6020,0x8275EA2,0xFFFE43C,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xF};
+	public static final int[] CURVE_Gx= {0x21AACB1,0x52EE1EB,0x4C73ABC,0x9B0903D,0xB098357,0xA04F42C,0x1297A95,0x5AAADB6,0xC9ED6B6,0xB};
+	public static final int[] CURVE_Gy= {0x184DE9F,0xB5B9CB2,0x10FBB80,0xC3D1153,0x35C955,0xF77E04E,0x673448B,0x3399B6A,0x8FC0F1,0xD};
+
+
+}
diff --git a/version3/java/ROM_NUMS256W_64.java b/version3/java/ROM_NUMS256W_64.java
new file mode 100644
index 0000000..1fa94d6
--- /dev/null
+++ b/version3/java/ROM_NUMS256W_64.java
@@ -0,0 +1,45 @@
+/*
+	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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.NUMS256W;
+
+public class ROM
+{
+
+// Modulus
+	public static final long[] Modulus= {0xFFFFFFFFFFFF43L,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFL};
+	public static final long[] R2modp= {0x89000000000000L,0x8BL,0x0L,0x0L,0x0L};
+	public static final long MConst= 0xBDL;
+
+// Curve
+
+	public static final int CURVE_Cof_I= 1;
+	public static final long[] CURVE_Cof= {0x1L,0x0L,0x0L,0x0L,0x0L};
+	public static final int CURVE_A= -3;
+	public static final int CURVE_B_I= 152961;
+	public static final long[] CURVE_B= {0x25581L,0x0L,0x0L,0x0L,0x0L};
+	public static final long[] CURVE_Order= {0xAB20294751A825L,0x8275EA265C6020L,0xFFFFFFFFFFE43CL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFL};
+	public static final long[] CURVE_Gx= {0x52EE1EB21AACB1L,0x9B0903D4C73ABCL,0xA04F42CB098357L,0x5AAADB61297A95L,0xBC9ED6B6L};
+	public static final long[] CURVE_Gy= {0xB5B9CB2184DE9FL,0xC3D115310FBB80L,0xF77E04E035C955L,0x3399B6A673448BL,0xD08FC0F1L};
+
+}
+
diff --git a/version3/java/ROM_NUMS384E_32.java b/version3/java/ROM_NUMS384E_32.java
new file mode 100644
index 0000000..f2eae88
--- /dev/null
+++ b/version3/java/ROM_NUMS384E_32.java
@@ -0,0 +1,40 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.NUMS384E;
+
+public class ROM
+{
+// Base Bits= 29
+public static final int[] Modulus= {0x1FFFFEC3,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F};
+public static final int[] R2modp= {0x0,0x4448000,0x6,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+public static final int MConst= 0x13D;
+
+public static final int CURVE_Cof_I= 4;
+public static final int[] CURVE_Cof= {0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+public static final int CURVE_A= 1;
+public static final int CURVE_B_I= -11556;
+public static final int[] CURVE_B= {0x1FFFD19F,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F};
+public static final int[] CURVE_Order= {0x6A3897D,0x5CEE627,0xD721E48,0x8AAB556,0x1E1CF61E,0xD0E5A35,0x1FFF891C,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1F};
+public static final int[] CURVE_Gx= {0xC206BDE,0x6AA0723,0x116504D4,0x52562CA,0x163406FF,0x1FD47998,0x10015D8F,0x8DCB7C9,0x15B30BF4,0x14D72AED,0x102DA884,0xB524CD9,0x1B111FB4,0x30};
+public static final int[] CURVE_Gy= {0x10729392,0xC681F0F,0x1B123727,0x561F28D,0x1964B007,0xC7BFB22,0x1D5A0C3E,0xE9E284B,0x1716AD82,0x11D886E,0x1CE2C69,0x134DDD61,0x983E67B,0x41};
+}
diff --git a/version3/java/ROM_NUMS384E_64.java b/version3/java/ROM_NUMS384E_64.java
new file mode 100644
index 0000000..54f142d
--- /dev/null
+++ b/version3/java/ROM_NUMS384E_64.java
@@ -0,0 +1,40 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.NUMS384E;
+
+public class ROM
+{
+// Base Bits= 56
+	public static final long[] Modulus= {0xFFFFFFFFFFFEC3L,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFL};
+	public static final long[] R2modp= {0x188890000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+	public static final long MConst= 0x13DL;
+
+	public static final int CURVE_Cof_I= 4;
+	public static final long[] CURVE_Cof= {0x4L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+	public static final int CURVE_A= 1;
+	public static final int CURVE_B_I= -11556;
+	public static final long[] CURVE_B= {0xFFFFFFFFFFD19FL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFL};
+	public static final long[] CURVE_Order= {0xB9DCC4E6A3897DL,0x555AAB35C87920L,0x1CB46BE1CF61E4L,0xFFFFFFFFE2471AL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0x3FFFFFFFFFFFL};
+	public static final long[] CURVE_Gx= {0xD540E46C206BDEL,0x92B16545941350L,0xA8F33163406FF2L,0xE5BE4C005763FFL,0xE55DB5B30BF446L,0x266CC0B6A2129AL,0x61B111FB45A9L};
+	public static final long[] CURVE_Gy= {0x8D03E1F0729392L,0xB0F946EC48DC9DL,0xF7F645964B0072L,0xF1425F56830F98L,0xB10DD716AD8274L,0xEEB08738B1A423L,0x82983E67B9A6L};
+}
diff --git a/version3/java/ROM_NUMS384W_32.java b/version3/java/ROM_NUMS384W_32.java
new file mode 100644
index 0000000..ba34a3c
--- /dev/null
+++ b/version3/java/ROM_NUMS384W_32.java
@@ -0,0 +1,43 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.NUMS384W;
+
+public class ROM
+{
+
+// Base Bits= 29
+	public static final int[] Modulus= {0x1FFFFEC3,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F};
+	public static final int[] R2modp= {0x0,0x4448000,0x6,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int MConst= 0x13D;
+
+	public static final int CURVE_Cof_I= 1;
+	public static final int[] CURVE_Cof= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int CURVE_A= -3;
+	public static final int CURVE_B_I= -34568;
+	public static final int[] CURVE_B= {0x1FFF77BB,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F};
+	public static final int[] CURVE_Order= {0x1B0E61B9,0x26C0FB3,0xDF89E98,0x153A7A98,0x16881BED,0x178F75AE,0x1FFF587A,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F};
+	public static final int[] CURVE_Gx= {0x98152A,0x1CE5D021,0x18711EFA,0x1DDA201E,0xC742522,0x148D9536,0x7D3CEF4,0x19BF703F,0x60225C1,0x12082F8D,0x12203288,0x2DE3038,0x17956F0B,0x3A};
+	public static final int[] CURVE_Gy= {0x6180716,0x3A5C763,0x1D2B4997,0xD69B77F,0x837EBCD,0x1BE890D,0xE72E482,0xEFF0FEE,0x1EB00469,0x2C267B,0x15F8CF4C,0x3371C71,0xDEE368E,0x56};
+
+
+}
diff --git a/version3/java/ROM_NUMS384W_64.java b/version3/java/ROM_NUMS384W_64.java
new file mode 100644
index 0000000..314efd0
--- /dev/null
+++ b/version3/java/ROM_NUMS384W_64.java
@@ -0,0 +1,55 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.NUMS384W;
+
+public class ROM
+{
+/*
+// Base Bits= 56
+	public static final long[] Modulus= {0xFFFFFFFFFFFEC3L,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFL};
+	public static final long[] R2modp= {0x188890000L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+	public static final long MConst= 0x13DL;
+
+	public static final int CURVE_A= -3;
+	public static final int CURVE_B_I= -34568;
+	public static final long[] CURVE_B= {0xFFFFFFFFFF77BBL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFL};
+	public static final long[] CURVE_Order= {0x4D81F67B0E61B9L,0x9D3D4C37E27A60L,0x1EEB5D6881BEDAL,0xFFFFFFFFD61EAFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFL};
+	public static final long[] CURVE_Gx= {0x9CBA042098152AL,0xED100F61C47BEBL,0x1B2A6CC742522EL,0xFB81F9F4F3BD29L,0x5F1A60225C1CDL,0x181C4880CA2241L,0x757956F0B16FL};
+	public static final long[] CURVE_Gy= {0x74B8EC66180716L,0xB4DBBFF4AD265CL,0x7D121A837EBCD6L,0xF87F739CB92083L,0x84CF7EB0046977L,0x8E38D7E33D3005L,0xACDEE368E19BL};
+*/
+// Base Bits= 58
+	public static final long[] Modulus= {0x3FFFFFFFFFFFEC3L,0x3FFFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFFL,0xFFFFFFFFFL};
+	public static final long[] R2modp= {0x88900000000000L,0x6L,0x0L,0x0L,0x0L,0x0L,0x0L};
+	public static final long MConst= 0x13DL;
+
+	public static final int CURVE_Cof_I= 1;
+	public static final long[] CURVE_Cof= {0x1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+	public static final int CURVE_A= -3;
+	public static final int CURVE_B_I= -34568;
+	public static final long[] CURVE_B= {0x3FFFFFFFFFF77BBL,0x3FFFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFFL,0xFFFFFFFFFL};
+	public static final long[] CURVE_Order= {0x4D81F67B0E61B9L,0x2A74F530DF89E98L,0x2F1EEB5D6881BEDL,0x3FFFFFFFFFF587AL,0x3FFFFFFFFFFFFFFL,0x3FFFFFFFFFFFFFFL,0xFFFFFFFFFL};
+	public static final long[] CURVE_Gx= {0x39CBA042098152AL,0x3BB4403D8711EFAL,0x291B2A6CC742522L,0x337EE07E7D3CEF4L,0x24105F1A60225C1L,0x5BC60712203288L,0x757956F0BL};
+	public static final long[] CURVE_Gy= {0x74B8EC66180716L,0x1AD36EFFD2B4997L,0x37D121A837EBCDL,0x1DFE1FDCE72E482L,0x584CF7EB00469L,0x66E38E35F8CF4CL,0xACDEE368EL};
+
+
+}
diff --git a/version3/java/ROM_NUMS512E_32.java b/version3/java/ROM_NUMS512E_32.java
new file mode 100644
index 0000000..4f1520b
--- /dev/null
+++ b/version3/java/ROM_NUMS512E_32.java
@@ -0,0 +1,40 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.NUMS512E;
+
+public class ROM
+{
+// Base Bits= 29
+	public static final int[] Modulus= {0x1FFFFDC7,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF};
+	public static final int[] R2modp= {0xB100000,0x278,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int MConst= 0x239;
+
+	public static final int CURVE_Cof_I= 4;
+	public static final int[] CURVE_Cof= {0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int CURVE_A= 1;
+	public static final int CURVE_B_I= -78296;
+	public static final int[] CURVE_B= {0x1FFECBEF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF};
+	public static final int[] CURVE_Order= {0x1BEED46D,0x1A3467A8,0x1BFB3FD9,0xC0AF0DB,0x86F52A4,0xC64B85B,0x6EA78FF,0xDA5F9F2,0x1FB4F063,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFF};
+	public static final int[] CURVE_Gx= {0x19EC57FE,0xDCD594C,0x113C0571,0xA4A84F9,0x104AD0FE,0x4C92B44,0xC3DE2F7,0x9DDC8CE,0x74621C1,0x1139DC0A,0x9E85FAF,0x1B894704,0x1D1E79F4,0x9E29997,0x32DE223,0x16D38F43,0x116D128D,0x6FC71};
+	public static final int[] CURVE_Gy= {0x1E2F5E1,0x136EF606,0x1C7407CC,0xDA71537,0xC1FD026,0x3431576,0x15898068,0x1E5D32C6,0x120CA53,0xC84F41A,0xA4ADAE5,0x104B3A45,0x76F726D,0x1512B772,0x3D5DEA0,0x194E3316,0x1FF39D49,0x3684D};
+}
diff --git a/version3/java/ROM_NUMS512E_64.java b/version3/java/ROM_NUMS512E_64.java
new file mode 100644
index 0000000..32f63a3
--- /dev/null
+++ b/version3/java/ROM_NUMS512E_64.java
@@ -0,0 +1,40 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.NUMS512E;
+
+public class ROM
+{
+// Base Bits= 56
+	public static final long[] Modulus= {0xFFFFFFFFFFFDC7L,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFL};
+	public static final long[] R2modp= {0x0L,0xF0B10000000000L,0x4L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+	public static final long MConst= 0x239L;
+
+	public static final int CURVE_Cof_I= 4;
+	public static final long[] CURVE_Cof= {0x4L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+	public static final int CURVE_A= 1;
+	public static final int CURVE_B_I= -78296;
+	public static final long[] CURVE_B= {0xFFFFFFFFFECBEFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFL};
+	public static final long[] CURVE_Order= {0x468CF51BEED46DL,0x5786DEFECFF67L,0xC970B686F52A46L,0x2FCF91BA9E3FD8L,0xFFFFFFB4F0636DL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0x3FL};
+	public static final long[] CURVE_Gx= {0xB9AB2999EC57FEL,0x25427CC4F015C5L,0x92568904AD0FE5L,0xEE46730F78BDC9L,0x3B81474621C14EL,0xA38227A17EBE27L,0x332FD1E79F4DC4L,0x7A18CB7888D3C5L,0x8E316D128DB69CL,0xDFL};
+	public static final long[] CURVE_Gy= {0x6DDEC0C1E2F5E1L,0xD38A9BF1D01F32L,0x862AECC1FD0266L,0xE9963562601A06L,0x9E834120CA53F2L,0x9D22A92B6B9590L,0x6EE476F726D825L,0x98B0F577A82A25L,0x9BFF39D49CA71L,0x6DL};
+}
diff --git a/version3/java/ROM_NUMS512W_32.java b/version3/java/ROM_NUMS512W_32.java
new file mode 100644
index 0000000..ab1fbf8
--- /dev/null
+++ b/version3/java/ROM_NUMS512W_32.java
@@ -0,0 +1,40 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.NUMS512W;
+
+public class ROM
+{
+// Base Bits= 29
+	public static final int[] Modulus= {0x1FFFFDC7,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF};
+	public static final int[] R2modp= {0xB100000,0x278,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int MConst= 0x239;
+
+	public static final int CURVE_Cof_I= 1;
+	public static final int[] CURVE_Cof= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int CURVE_A= -3;
+	public static final int CURVE_B_I= 121243;
+	public static final int[] CURVE_B= {0x1D99B,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+	public static final int[] CURVE_Order= {0x433555D,0x10A9F9C8,0x1F3490F3,0xD166CC0,0xBDC63B5,0xC76CBE8,0xC6D3F09,0x1F729CF0,0x1F5B3CA4,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF};
+	public static final int[] CURVE_Gx= {0xCABAE57,0x4143CAC,0x1BD778B7,0x1AC026FA,0x15831D5,0x14312AB,0x167A4DE5,0xA20ED66,0x195021A1,0x129836CF,0x1141B830,0xA03ED0A,0xCAD83BB,0x1E9DA94C,0xDC00A80,0x1527B45,0x1447141D,0x1D601};
+	public static final int[] CURVE_Gy= {0x183527A6,0x1D043B01,0x1F43FA48,0x16B83C99,0x5602CF2,0x1420592D,0x17A70486,0x1B5161DD,0x14A28415,0x3DE8A78,0x3D2C983,0x17797719,0x197DBDEA,0x15D88025,0x1BBB718F,0xAD679C1,0x14CA29AD,0x4A1D2};
+}
diff --git a/version3/java/ROM_NUMS512W_64.java b/version3/java/ROM_NUMS512W_64.java
new file mode 100644
index 0000000..ef267dc
--- /dev/null
+++ b/version3/java/ROM_NUMS512W_64.java
@@ -0,0 +1,41 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.NUMS512W;
+
+public class ROM
+{
+
+// Base Bits= 60
+	public static final long[] Modulus= {0xFFFFFFFFFFFFDC7L,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFL};
+	public static final long[] R2modp= {0x100000000000000L,0x4F0BL,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+	public static final long MConst= 0x239L;
+
+	public static final int CURVE_Cof_I= 1;
+	public static final long[] CURVE_Cof= {0x1L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+	public static final int CURVE_A= -3;
+	public static final int CURVE_B_I= 121243;
+	public static final long[] CURVE_B= {0x1D99BL,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L,0x0L};
+	public static final long[] CURVE_Order= {0xE153F390433555DL,0x568B36607CD243CL,0x258ED97D0BDC63BL,0xA4FB94E7831B4FCL,0xFFFFFFFFFFF5B3CL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFFL,0xFFFFFFFFL};
+	public static final long[] CURVE_Gx= {0xC8287958CABAE57L,0x5D60137D6F5DE2DL,0x94286255615831DL,0xA151076B359E937L,0xC25306D9F95021L,0x3BB501F6854506EL,0x2A03D3B5298CAD8L,0x141D0A93DA2B700L,0x3AC03447L};
+	public static final long[] CURVE_Gy= {0x3A08760383527A6L,0x2B5C1E4CFD0FE92L,0x1A840B25A5602CFL,0x15DA8B0EEDE9C12L,0x60C7BD14F14A284L,0xDEABBCBB8C8F4B2L,0xC63EBB1004B97DBL,0x29AD56B3CE0EEEDL,0x943A54CAL};
+}
diff --git a/version3/java/ROM_SECP256K1_32.java b/version3/java/ROM_SECP256K1_32.java
new file mode 100644
index 0000000..584f96e
--- /dev/null
+++ b/version3/java/ROM_SECP256K1_32.java
@@ -0,0 +1,45 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.SECP256K1;
+
+
+public class ROM
+{
+
+// Base Bits= 28
+public static final int[] Modulus= {0xFFFFC2F,0xFFFFFEF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xF};
+public static final int[] R2modp= {0x0,0xA100000,0x2000E90,0x7A,0x1,0x0,0x0,0x0,0x0,0x0};
+public static final int MConst= 0x2253531;
+
+public static final int CURVE_Cof_I= 1;
+public static final int[] CURVE_Cof= {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+public static final int CURVE_A= 0;
+public static final int CURVE_B_I= 7;
+public static final int[] CURVE_B= {0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+public static final int[] CURVE_Order= {0x364141,0xD25E8CD,0x8A03BBF,0xDCE6AF4,0xFFEBAAE,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xF};
+public static final int[] CURVE_Gx= {0x6F81798,0xF2815B1,0xE28D959,0xFCDB2DC,0xB07029B,0x95CE870,0xC55A062,0xF9DCBBA,0x9BE667E,0x7};
+public static final int[] CURVE_Gy= {0xB10D4B8,0x47D08FF,0x554199C,0xB448A68,0x8A8FD17,0xFC0E110,0x55DA4FB,0x26A3C46,0x83ADA77,0x4};
+
+}
+
+
diff --git a/version3/java/ROM_SECP256K1_64.java b/version3/java/ROM_SECP256K1_64.java
new file mode 100644
index 0000000..014ebc9
--- /dev/null
+++ b/version3/java/ROM_SECP256K1_64.java
@@ -0,0 +1,43 @@
+/*
+	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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+
+package org.apache.milagro.amcl.SECP256K1;
+
+public class ROM
+{
+
+// Base Bits= 56
+public static final long[] Modulus= {0xFFFFFEFFFFFC2FL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFL};
+public static final long[] R2modp= {0xA1000000000000L,0x7A2000E90L,0x1L,0x0L,0x0L};
+public static final long MConst= 0x38091DD2253531L;
+
+public static final int CURVE_Cof_I= 1;
+public static final long[] CURVE_Cof= {0x1L,0x0L,0x0L,0x0L,0x0L};
+public static final int CURVE_A= 0;
+public static final int CURVE_B_I= 7;
+public static final long[] CURVE_B= {0x7L,0x0L,0x0L,0x0L,0x0L};
+public static final long[] CURVE_Order= {0xD25E8CD0364141L,0xDCE6AF48A03BBFL,0xFFFFFFFFFEBAAEL,0xFFFFFFFFFFFFFFL,0xFFFFFFFFL};
+public static final long[] CURVE_Gx= {0xF2815B16F81798L,0xFCDB2DCE28D959L,0x95CE870B07029BL,0xF9DCBBAC55A062L,0x79BE667EL};
+public static final long[] CURVE_Gy= {0x47D08FFB10D4B8L,0xB448A68554199CL,0xFC0E1108A8FD17L,0x26A3C4655DA4FBL,0x483ADA77L};
+
+}
+
diff --git a/version3/java/RSA.java b/version3/java/RSA.java
new file mode 100644
index 0000000..0adb376
--- /dev/null
+++ b/version3/java/RSA.java
@@ -0,0 +1,369 @@
+/*
+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.
+*/
+
+/* RSA API high-level functions  */
+
+package org.apache.milagro.amcl.XXX;
+
+import org.apache.milagro.amcl.RAND;
+import org.apache.milagro.amcl.HASH256;
+import org.apache.milagro.amcl.HASH384;
+import org.apache.milagro.amcl.HASH512;
+
+public final class RSA {
+
+	public static final int RFS=BIG.MODBYTES*FF.FFLEN;
+	public static final int SHA256=32;
+	public static final int SHA384=48;
+	public static final int SHA512=64;
+
+	public static final int HASH_TYPE=SHA256;
+
+/* Hash number (optional) and string to array size of Bigs */
+
+	public static byte[] hashit(int sha,byte[] A,int n)
+	{
+		byte[] R=null;
+
+		if (sha==SHA256)
+		{
+			HASH256 H=new HASH256();
+			if (A!=null) H.process_array(A);
+			if (n>=0) H.process_num(n);
+			R=H.hash();
+		}
+		if (sha==SHA384)
+		{
+			HASH384 H=new HASH384();
+			if (A!=null) H.process_array(A);
+			if (n>=0) H.process_num(n);
+			R=H.hash();
+		}
+		if (sha==SHA512)
+		{
+			HASH512 H=new HASH512();
+			if (A!=null) H.process_array(A);
+			if (n>=0) H.process_num(n);
+			R=H.hash();
+		}
+		return R;
+	}
+
+/* generate an RSA key pair */
+
+	public static void KEY_PAIR(RAND rng,int e,private_key PRIV,public_key PUB)
+	{ /* IEEE1363 A16.11/A16.12 more or less */
+
+		int n=PUB.n.getlen()/2;
+		FF t = new FF(n);
+		FF p1=new FF(n);
+		FF q1=new FF(n);
+
+		for (;;)
+		{
+			PRIV.p.random(rng);
+			while (PRIV.p.lastbits(2)!=3) PRIV.p.inc(1);
+			while (!FF.prime(PRIV.p,rng)) PRIV.p.inc(4);
+
+			p1.copy(PRIV.p);
+			p1.dec(1);
+
+			if (p1.cfactor(e)) continue;
+			break;
+		}
+
+		for (;;)
+		{
+			PRIV.q.random(rng);
+			while (PRIV.q.lastbits(2)!=3) PRIV.q.inc(1);
+			while (!FF.prime(PRIV.q,rng)) PRIV.q.inc(4);
+			
+			q1.copy(PRIV.q);
+			q1.dec(1);
+
+			if (q1.cfactor(e)) continue;
+
+			break;
+		}
+
+		PUB.n=FF.mul(PRIV.p,PRIV.q);
+		PUB.e=e;
+
+		t.copy(p1);
+		t.shr();
+		PRIV.dp.set(e);
+		PRIV.dp.invmodp(t);
+		if (PRIV.dp.parity()==0) PRIV.dp.add(t);
+		PRIV.dp.norm();
+
+		t.copy(q1);
+		t.shr();
+		PRIV.dq.set(e);
+		PRIV.dq.invmodp(t);
+		if (PRIV.dq.parity()==0) PRIV.dq.add(t);
+		PRIV.dq.norm();
+
+		PRIV.c.copy(PRIV.p);
+		PRIV.c.invmodp(PRIV.q);
+
+		return;
+	}
+
+/* Mask Generation Function */
+
+	public static void MGF1(int sha,byte[] Z,int olen,byte[] K)
+	{
+		int hlen=sha;
+		byte[] B;
+
+		int counter,cthreshold,k=0;
+
+		for (int i=0;i<K.length;i++) K[i]=0;
+
+		cthreshold=olen/hlen; if (olen%hlen!=0) cthreshold++;
+		for (counter=0;counter<cthreshold;counter++)
+		{
+			B=hashit(sha,Z,counter);
+			if (k+hlen>olen) for (int i=0;i<olen%hlen;i++) K[k++]=B[i];
+			else for (int i=0;i<hlen;i++) K[k++]=B[i];
+		}	
+	}
+
+	public static void printBinary(byte[] array)
+	{
+		int i;
+		for (i=0;i<array.length;i++)
+		{
+			System.out.printf("%02x", array[i]);
+		}
+		System.out.println();
+	}  
+
+
+
+/* SHAXXX identifier strings */
+	private static final byte[] SHA256ID={0x30,0x31,0x30,0x0d,0x06,0x09,0x60,(byte)0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20};
+	private static final byte[] SHA384ID={0x30,0x41,0x30,0x0d,0x06,0x09,0x60,(byte)0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00,0x04,0x30};
+	private static final byte[] SHA512ID={0x30,0x51,0x30,0x0d,0x06,0x09,0x60,(byte)0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0x04,0x40};
+
+/* PKCS 1.5 padding of a message to be signed */
+
+	public static boolean PKCS15(int sha,byte[] m,byte[] w)
+	{
+		int olen=FF.FF_BITS/8;
+		int i,hlen=sha;
+		int idlen=19; 
+
+		if (olen<idlen+hlen+10) return false;
+		byte[] H=hashit(sha,m,-1);
+
+		for (i=0;i<w.length;i++) w[i]=0;
+		i=0;
+		w[i++]=0;
+		w[i++]=1;
+		for (int j=0;j<olen-idlen-hlen-3;j++)
+			w[i++]=(byte)0xff;
+		w[i++]=0;
+
+
+		if (hlen==SHA256) for (int j=0;j<idlen;j++) w[i++]=SHA256ID[j];
+		if (hlen==SHA384) for (int j=0;j<idlen;j++) w[i++]=SHA384ID[j];
+		if (hlen==SHA512) for (int j=0;j<idlen;j++) w[i++]=SHA512ID[j];
+
+		for (int j=0;j<hlen;j++)
+			w[i++]=H[j];
+
+		return true;
+	}
+
+
+	/* OAEP Message Encoding for Encryption */
+	public static byte[] OAEP_ENCODE(int sha,byte[] m,RAND rng,byte[] p)
+	{ 
+		int i,slen,olen=RFS-1;
+		int mlen=m.length;
+		int hlen,seedlen;
+		byte[] f=new byte[RFS];
+
+		hlen=sha;
+		byte[] SEED=new byte[hlen];
+		seedlen=hlen;
+
+		if (mlen>olen-hlen-seedlen-1) return new byte[0]; 
+
+		byte[] DBMASK=new byte[olen-seedlen];
+
+		byte[] h=hashit(sha,p,-1);
+
+		for (i=0;i<hlen;i++) f[i]=h[i];
+
+		slen=olen-mlen-hlen-seedlen-1;      
+
+		for (i=0;i<slen;i++) f[hlen+i]=0;
+		f[hlen+slen]=1;
+		for (i=0;i<mlen;i++) f[hlen+slen+1+i]=m[i];
+
+		for (i=0;i<seedlen;i++) SEED[i]=(byte)rng.getByte();
+
+		MGF1(sha,SEED,olen-seedlen,DBMASK);
+
+		for (i=0;i<olen-seedlen;i++) DBMASK[i]^=f[i];
+
+		MGF1(sha,DBMASK,seedlen,f);
+
+		for (i=0;i<seedlen;i++) f[i]^=SEED[i];
+
+		for (i=0;i<olen-seedlen;i++) f[i+seedlen]=DBMASK[i];
+
+		/* pad to length RFS */
+		int d=1;
+		for (i=RFS-1;i>=d;i--)
+			f[i]=f[i-d];
+		for (i=d-1;i>=0;i--)
+			f[i]=0;
+
+		return f;
+	}
+
+	/* OAEP Message Decoding for Decryption */
+	public static byte[] OAEP_DECODE(int sha,byte[] p,byte[] f)
+	{
+		int x,t;
+		boolean comp;
+		int i,k,olen=RFS-1;
+		int hlen,seedlen;
+
+		hlen=sha;
+		byte[] SEED=new byte[hlen];
+		seedlen=hlen;
+		byte[] CHASH=new byte[hlen];
+	
+		if (olen<seedlen+hlen+1) return new byte[0];
+		byte[] DBMASK=new byte[olen-seedlen];
+		for (i=0;i<olen-seedlen;i++) DBMASK[i]=0;
+
+		if (f.length<RFS)
+		{
+			int d=RFS-f.length;
+			for (i=RFS-1;i>=d;i--)
+				f[i]=f[i-d];
+			for (i=d-1;i>=0;i--)
+				f[i]=0;
+
+		}
+
+		byte[] h=hashit(sha,p,-1);
+
+		for (i=0;i<hlen;i++) CHASH[i]=h[i];
+
+		x=f[0];
+
+		for (i=seedlen;i<olen;i++)
+			DBMASK[i-seedlen]=f[i+1]; 
+
+		MGF1(sha,DBMASK,seedlen,SEED);
+		for (i=0;i<seedlen;i++) SEED[i]^=f[i+1];
+		MGF1(sha,SEED,olen-seedlen,f);
+		for (i=0;i<olen-seedlen;i++) DBMASK[i]^=f[i];
+
+		comp=true;
+		for (i=0;i<hlen;i++)
+		{
+			if (CHASH[i]!=DBMASK[i]) comp=false;
+		}
+
+		for (i=0;i<olen-seedlen-hlen;i++)
+			DBMASK[i]=DBMASK[i+hlen];
+
+		for (i=0;i<hlen;i++)
+			SEED[i]=CHASH[i]=0;
+		
+		for (k=0;;k++)
+		{
+			if (k>=olen-seedlen-hlen) return new byte[0];
+			if (DBMASK[k]!=0) break;
+		}
+
+		t=DBMASK[k];
+		if (!comp || x!=0 || t!=0x01) 
+		{
+			for (i=0;i<olen-seedlen;i++) DBMASK[i]=0;
+			return new byte[0];
+		}
+
+		byte[] r=new byte[olen-seedlen-hlen-k-1];
+
+		for (i=0;i<olen-seedlen-hlen-k-1;i++)
+			r[i]=DBMASK[i+k+1];
+	
+		for (i=0;i<olen-seedlen;i++) DBMASK[i]=0;
+
+		return r;
+	}
+
+	/* destroy the Private Key structure */
+	public static void PRIVATE_KEY_KILL(private_key PRIV)
+	{
+		PRIV.p.zero();
+		PRIV.q.zero();
+		PRIV.dp.zero();
+		PRIV.dq.zero();
+		PRIV.c.zero();
+	}
+
+	/* RSA encryption with the public key */
+	public static void ENCRYPT(public_key PUB,byte[] F,byte[] G)
+	{
+		int n=PUB.n.getlen();
+		FF f=new FF(n);
+		FF.fromBytes(f,F);
+		f.power(PUB.e,PUB.n);
+		f.toBytes(G);
+	}
+
+	/* RSA decryption with the private key */
+	public static void DECRYPT(private_key PRIV,byte[] G,byte[] F)
+	{
+		int n=PRIV.p.getlen();
+		FF g=new FF(2*n);
+
+		FF.fromBytes(g,G);
+		FF jp=g.dmod(PRIV.p);
+		FF jq=g.dmod(PRIV.q);
+
+		jp.skpow(PRIV.dp,PRIV.p);
+		jq.skpow(PRIV.dq,PRIV.q);
+
+		g.zero();
+		g.dscopy(jp);
+		jp.mod(PRIV.q);
+		if (FF.comp(jp,jq)>0) jq.add(PRIV.q);
+		jq.sub(jp);
+		jq.norm();
+
+		FF t=FF.mul(PRIV.c,jq);
+		jq=t.dmod(PRIV.q);
+
+		t=FF.mul(jq,PRIV.p);
+		g.add(t);
+		g.norm();
+
+		g.toBytes(F);
+	}
+}
diff --git a/version3/java/SHA3.java b/version3/java/SHA3.java
new file mode 100644
index 0000000..cf335cd
--- /dev/null
+++ b/version3/java/SHA3.java
@@ -0,0 +1,255 @@
+/*
+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.
+*/
+
+/*
+ * Implementation of the Secure Hashing Algorithm SHA-3
+
+ * Generates a message digest. It should be impossible to come
+ * come up with two messages that hash to the same value ("collision free").
+ *
+ * For use with byte-oriented messages only. 
+ */
+
+
+package org.apache.milagro.amcl;
+
+public class SHA3 {
+	private long length;
+	private int rate,len;
+	private long[][] S=new long[5][5];
+
+/* Constructor */
+	public SHA3(int olen)
+	{
+		init(olen);
+	}
+
+	public static final int HASH224=28; 
+	public static final int HASH256=32;
+	public static final int HASH384=48;
+	public static final int HASH512=64;
+
+	public static final int SHAKE128=16; 
+	public static final int SHAKE256=32; 
+
+	public static final long[] RC={
+		0x0000000000000001L,0x0000000000008082L,0x800000000000808AL,0x8000000080008000L,
+		0x000000000000808BL,0x0000000080000001L,0x8000000080008081L,0x8000000000008009L,
+		0x000000000000008AL,0x0000000000000088L,0x0000000080008009L,0x000000008000000AL,
+		0x000000008000808BL,0x800000000000008BL,0x8000000000008089L,0x8000000000008003L,
+		0x8000000000008002L,0x8000000000000080L,0x000000000000800AL,0x800000008000000AL,
+		0x8000000080008081L,0x8000000000008080L,0x0000000080000001L,0x8000000080008008L};
+
+	private static final int ROUNDS=24;
+
+
+	private static long rotl(long x,int n)
+	{
+		return (((x)<<n) | ((x)>>>(64-n)));
+	}
+
+	private void transform()
+	{ /* basic transformation step */
+		int i,j,k;
+		long[] C=new long[5];
+		long[] D=new long[5];
+		long[][] B=new long[5][5];
+
+		for (k=0;k<ROUNDS;k++)
+		{
+			C[0]=S[0][0]^S[0][1]^S[0][2]^S[0][3]^S[0][4];
+			C[1]=S[1][0]^S[1][1]^S[1][2]^S[1][3]^S[1][4];
+			C[2]=S[2][0]^S[2][1]^S[2][2]^S[2][3]^S[2][4];
+			C[3]=S[3][0]^S[3][1]^S[3][2]^S[3][3]^S[3][4];
+			C[4]=S[4][0]^S[4][1]^S[4][2]^S[4][3]^S[4][4];
+
+			D[0]=C[4]^rotl(C[1],1);
+			D[1]=C[0]^rotl(C[2],1);
+			D[2]=C[1]^rotl(C[3],1);
+			D[3]=C[2]^rotl(C[4],1);
+			D[4]=C[3]^rotl(C[0],1);
+
+			for (i=0;i<5;i++)
+				for (j=0;j<5;j++)
+					S[i][j]^=D[i];  
+
+			B[0][0]=S[0][0];
+			B[1][3]=rotl(S[0][1],36);
+			B[2][1]=rotl(S[0][2],3);
+			B[3][4]=rotl(S[0][3],41);
+			B[4][2]=rotl(S[0][4],18);
+
+			B[0][2]=rotl(S[1][0],1);
+			B[1][0]=rotl(S[1][1],44);
+			B[2][3]=rotl(S[1][2],10);
+			B[3][1]=rotl(S[1][3],45);
+			B[4][4]=rotl(S[1][4],2);
+
+			B[0][4]=rotl(S[2][0],62);
+			B[1][2]=rotl(S[2][1],6);
+			B[2][0]=rotl(S[2][2],43);
+			B[3][3]=rotl(S[2][3],15);
+			B[4][1]=rotl(S[2][4],61);
+
+			B[0][1]=rotl(S[3][0],28);
+			B[1][4]=rotl(S[3][1],55);
+			B[2][2]=rotl(S[3][2],25);
+			B[3][0]=rotl(S[3][3],21);
+			B[4][3]=rotl(S[3][4],56);
+
+			B[0][3]=rotl(S[4][0],27);
+			B[1][1]=rotl(S[4][1],20);
+			B[2][4]=rotl(S[4][2],39);
+			B[3][2]=rotl(S[4][3],8);
+			B[4][0]=rotl(S[4][4],14);
+
+			for (i=0;i<5;i++)
+				for (j=0;j<5;j++)
+					S[i][j]=B[i][j]^(~B[(i+1)%5][j]&B[(i+2)%5][j]);
+
+			S[0][0]^=RC[k];
+		}
+	} 
+
+/* Re-Initialize. olen is output length in bytes - 
+   should be 28, 32, 48 or 64 (224, 256, 384, 512 bits resp.) */
+
+
+/* Initialise Hash function */
+	public void init(int olen)
+	{ /* initialise */
+		int i,j;
+		for (i=0;i<5;i++) 
+			for (j=0;j<5;j++)
+				S[i][j]=0;    /* 5x5x8 bytes = 200 bytes of state */
+		length=0;
+		len=olen;
+		rate=200-2*olen; /* number of bytes consumed in one gulp. Note that some bytes in the 
+	                        state ("capacity") are not touched. Gulps are smaller for larger digests. 
+							Important that olen<rate */
+	}
+
+/* process a single byte */
+	public void process(int byt)
+	{ /* process the next message byte */
+		int i,j,b,cnt;
+		cnt=(int)(length%rate);
+		b=cnt%8;
+		cnt/=8;
+		i=cnt%5; j=cnt/5;  /* process by columns! */
+		S[i][j]^=((long)(byt&0xff)<<(8*b));
+		length++;
+		if ((length%rate)==0) transform();
+	}
+
+/* squeeze the sponge */
+	public byte[] squeeze(byte[] buff,int olen)
+	{
+		boolean done;
+		int i,j,k,m=0;
+		long el;
+/* extract by columns */
+		done=false;
+		for (;;)
+		{
+			for (j=0;j<5;j++)
+			{
+				for (i=0;i<5;i++)
+				{
+					el=S[i][j];
+					for (k=0;k<8;k++)
+					{
+						buff[m++]=(byte)(el&0xff);
+						if (m>=olen || (m%rate)==0) {done=true; break;} 
+						el>>>=8;
+					}
+					if (done) break;
+				}
+				if (done) break;
+			}
+			if (m>=olen) break;
+			done=false;
+			transform();
+		}
+		return buff;
+	}
+
+	public void hash(byte[] digest)
+	{ /* generate a SHA3 hash of appropriate size */
+		int q=rate-(int)(length%rate);
+		if (q==1) process(0x86); 
+		else
+		{
+			process(0x06);   /* 0x06 for SHA-3 */
+			while (length%rate!=rate-1) process(0x00);
+			process(0x80); /* this will force a final transform */
+		}
+		squeeze(digest,len);
+	}
+
+	public void shake(byte[] digest,int olen)
+	{ /* SHAKE out a buffer of variable length olen */
+		int q=rate-(int)(length%rate);
+		if (q==1) process(0x9f); 
+		else
+		{
+			process(0x1f);   // 0x06 for SHA-3 !!!!
+			while (length%rate!=rate-1) process(0x00);
+			process(0x80); /* this will force a final transform */
+		}
+		squeeze(digest,olen);
+	}
+
+/* test program: should produce digests */
+
+//916f6061fe879741ca6469b43971dfdb28b1a32dc36cb3254e812be27aad1d18
+//afebb2ef542e6579c50cad06d2e578f9f8dd6881d7dc824d26360feebf18a4fa73e3261122948efcfd492e74e82e2189ed0fb440d187f382270cb455f21dd185
+//98be04516c04cc73593fef3ed0352ea9f6443942d6950e29a372a681c3deaf4535423709b02843948684e029010badcc0acd8303fc85fdad3eabf4f78cae165635f57afd28810fc2
+
+/*
+	public static void main(String[] args) {
+
+		byte[] test="abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu".getBytes();
+		byte[] digest=new byte[100];
+		int i;
+
+		SHA3 sh256=new SHA3(SHA3.HASH256);
+		for (i=0;i<test.length;i++)
+			sh256.process(test[i]);
+		sh256.hash(digest);    
+		for (i=0;i<32;i++) System.out.format("%02x",digest[i]);
+		System.out.println("");
+
+		SHA3 sh512=new SHA3(SHA3.HASH512);
+		for (i=0;i<test.length;i++)
+			sh512.process(test[i]);
+		sh512.hash(digest);    
+		for (i=0;i<64;i++) System.out.format("%02x",digest[i]);
+		System.out.println("");
+
+		SHA3 sk256=new SHA3(SHA3.SHAKE256);
+		for (i=0;i<test.length;i++)
+			sk256.process(test[i]);
+		sk256.shake(digest,72);    
+		for (i=0;i<72;i++) System.out.format("%02x",digest[i]);
+		System.out.println("");
+
+	}  
+*/
+}
\ No newline at end of file
diff --git a/version3/java/TestECDH.java b/version3/java/TestECDH.java
new file mode 100644
index 0000000..fdbafab
--- /dev/null
+++ b/version3/java/TestECDH.java
@@ -0,0 +1,192 @@
+/*
+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.
+*/
+
+/* test driver and function exerciser for ECDH/ECIES/ECDSA API Functions */
+
+package org.apache.milagro.amcl.XXX;  //
+
+import java.util.Scanner;
+import junit.framework.TestCase;       //
+import org.apache.milagro.amcl.RAND;
+import org.apache.milagro.amcl.AES;
+
+public class TestECDH extends TestCase   //
+{
+	private static void printBinary(byte[] array)
+	{
+		int i;
+		for (i=0;i<array.length;i++)
+		{
+			System.out.printf("%02x", array[i]);
+		}
+		System.out.println();
+	}    
+
+	public static void testECDH()
+	{
+		byte[] RAW=new byte[100];
+		RAND rng=new RAND();
+		int i,j=0,res;
+		int result;
+		String pp=new String("M0ng00se");
+
+		rng.clean();
+		for (i=0;i<100;i++) RAW[i]=(byte)(i);
+		rng.seed(100,RAW);
+
+		int EGS=ECDH.EGS;
+		int EFS=ECDH.EFS;
+		int EAS=AES.KS;
+		int sha=ECP.HASH_TYPE;
+
+		byte[] S1=new byte[EGS];
+		byte[] W0=new byte[2*EFS+1];
+		byte[] W1=new byte[2*EFS+1];
+		byte[] Z0=new byte[EFS];
+		byte[] Z1=new byte[EFS];
+
+		byte[] SALT=new byte[8];
+		byte[] P1=new byte[3];
+		byte[] P2=new byte[4];
+		byte[] V=new byte[2*EFS+1];
+		byte[] M=new byte[17];
+		byte[] T=new byte[12];
+		byte[] CS=new byte[EGS];
+		byte[] DS=new byte[EGS];
+
+		for (i=0;i<8;i++) SALT[i]=(byte)(i+1);  // set Salt
+
+		System.out.println("Testing ECDH code");
+		System.out.println("Alice's Passphrase= "+pp);
+		byte[] PW=pp.getBytes();
+
+/* private key S0 of size EGS bytes derived from Password and Salt */
+
+		byte[] S0=ECDH.PBKDF2(sha,PW,SALT,1000,EGS);
+
+		System.out.print("Alice's private key= 0x");
+		printBinary(S0);
+
+/* Generate Key pair S/W */
+		ECDH.KEY_PAIR_GENERATE(null,S0,W0); 
+
+		System.out.print("Alice's public key= 0x");
+		printBinary(W0);
+
+		res=ECDH.PUBLIC_KEY_VALIDATE(W0);
+		if (res!=0)
+		{
+			fail("ECP Public Key is invalid!");
+		}
+/* Random private key for other party */
+		ECDH.KEY_PAIR_GENERATE(rng,S1,W1);
+
+		System.out.print("Servers private key= 0x");
+		printBinary(S1);
+
+		System.out.print("Servers public key= 0x");
+		printBinary(W1);
+
+
+		res=ECDH.PUBLIC_KEY_VALIDATE(W1);
+		if (res!=0)
+		{
+			fail("ECP Public Key is invalid!");
+		}
+
+/* Calculate common key using DH - IEEE 1363 method */
+
+		ECDH.SVDP_DH(S0,W1,Z0);
+		ECDH.SVDP_DH(S1,W0,Z1);
+
+		boolean same=true;
+		for (i=0;i<EFS;i++)
+			if (Z0[i]!=Z1[i]) same=false;
+
+		if (!same)
+		{
+			fail("*** ECPSVDP-DH Failed");
+		}
+
+		byte[] KEY=ECDH.KDF2(sha,Z0,null,EAS);
+
+		System.out.print("Alice's DH Key=  0x"); printBinary(KEY);
+		System.out.print("Servers DH Key=  0x"); printBinary(KEY);
+
+		if (ECP.CURVETYPE!=ECP.MONTGOMERY)
+		{
+			System.out.println("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=0;i<=16;i++) M[i]=(byte)i; 
+
+			byte[] C=ECDH.ECIES_ENCRYPT(sha,P1,P2,rng,W1,M,V,T);
+
+			System.out.println("Ciphertext= ");
+			System.out.print("V= 0x"); printBinary(V);
+			System.out.print("C= 0x"); printBinary(C);
+			System.out.print("T= 0x"); printBinary(T);
+
+
+			M=ECDH.ECIES_DECRYPT(sha,P1,P2,V,C,T,S1);
+			if (M.length==0)
+			{
+				fail("*** ECIES Decryption Failed");
+			}
+			else System.out.println("Decryption succeeded");
+
+			System.out.print("Message is 0x"); printBinary(M);
+
+			System.out.println("Testing ECDSA");
+
+			if (ECDH.SP_DSA(sha,rng,S0,M,CS,DS)!=0)
+			{
+				fail("***ECDSA Signature Failed");
+			}
+			System.out.println("Signature= ");
+			System.out.print("C= 0x"); printBinary(CS);
+			System.out.print("D= 0x"); printBinary(DS);
+
+			if (ECDH.VP_DSA(sha,W0,M,CS,DS)!=0)
+			{
+				fail("***ECDSA Verification Failed");
+			}
+			else System.out.println("ECDSA Signature/Verification succeeded "+j);
+			System.out.println("");
+
+		}
+	}
+
+/*
+	public static void main(String[] args) 
+	{
+
+		byte[] RAW=new byte[100];
+		RAND rng=new RAND();
+
+		rng.clean();
+		for (int i=0;i<100;i++) RAW[i]=(byte)(i);
+
+		rng.seed(100,RAW);
+		ecdh(rng);
+
+	} */
+}
diff --git a/version3/java/TestMPIN.java b/version3/java/TestMPIN.java
new file mode 100644
index 0000000..27d55ab
--- /dev/null
+++ b/version3/java/TestMPIN.java
@@ -0,0 +1,297 @@
+/*
+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.
+*/
+
+/* test driver and function exerciser for ECDH/ECIES/ECDSA API Functions */
+package org.apache.milagro.amcl.XXX;  //
+
+import java.util.Scanner;
+import junit.framework.TestCase;      //
+import org.apache.milagro.amcl.RAND;
+
+public class TestMPIN extends TestCase //
+{
+	private static void printBinary(byte[] array)
+	{
+		int i;
+		for (i=0;i<array.length;i++)
+		{
+			System.out.printf("%02x", array[i]);
+		}
+		System.out.println();
+	}    
+
+
+	static boolean PERMITS=true;
+	static boolean PINERROR=true;
+	static boolean FULL=true;
+	static boolean SINGLE_PASS=false;
+
+	public static void testMPIN()
+	{
+		RAND rng=new RAND();
+		int EGS=MPIN.EGS;
+		int EFS=MPIN.EFS;
+		int G1S=2*EFS+1; /* Group 1 Size */
+		int G2S=4*EFS; /* Group 2 Size */
+
+		int sha=ECP.HASH_TYPE;
+
+		byte[] S = new byte[EGS];
+		byte[] SST = new byte[G2S];
+		byte[] TOKEN = new byte[G1S];
+		byte[] PERMIT = new byte[G1S];
+		byte[] SEC = new byte[G1S];
+		byte[] xID = new byte[G1S];
+		byte[] xCID = new byte[G1S];
+		byte[] X= new byte[EGS];
+		byte[] Y= new byte[EGS];
+		byte[] E=new byte[12*EFS];
+		byte[] F=new byte[12*EFS];
+		byte[] HID=new byte[G1S];
+		byte[] HTID=new byte[G1S];
+
+		byte[] G1=new byte[12*EFS];
+		byte[] G2=new byte[12*EFS];
+		byte[] R=new byte[EGS];
+		byte[] Z=new byte[G1S];
+		byte[] W=new byte[EGS];
+		byte[] T=new byte[G1S];
+		byte[] CK=new byte[ECP.AESKEY];
+		byte[] SK=new byte[ECP.AESKEY];
+
+		byte[] HSID=null;
+		byte[] RAW=new byte[100];
+
+		rng.clean();
+		for (int i=0;i<100;i++) RAW[i]=(byte)(i);
+		rng.seed(100,RAW);
+
+		System.out.println("Testing MPIN code");
+
+/* Trusted Authority set-up */
+
+		MPIN.RANDOM_GENERATE(rng,S);
+		System.out.print("Master Secret s: 0x");  printBinary(S);
+ 
+ /* Create Client Identity */
+ 		String IDstr = "testUser@miracl.com";
+		byte[] CLIENT_ID = IDstr.getBytes();   
+
+		byte[] HCID=MPIN.HASH_ID(sha,CLIENT_ID,EFS);  /* Either Client or TA calculates Hash(ID) - you decide! */
+
+		System.out.print("Client ID Hash= "); printBinary(HCID);
+		System.out.print("Client ID= "); printBinary(CLIENT_ID);
+
+/* Client and Server are issued secrets by DTA */
+
+		MPIN.GET_CLIENT_SECRET(S,HCID,TOKEN);
+		System.out.print("Client Secret CS: 0x");        
+		printBinary(TOKEN); 
+
+		MPIN.GET_SERVER_SECRET(S,SST);
+		System.out.print("Server Secret SS: 0x");  printBinary(SST); 
+
+
+/* Client extracts PIN from secret to create Token */
+		int pin=1234;
+		System.out.println("Client extracts PIN= "+pin); 
+		int rtn=MPIN.EXTRACT_PIN(sha,CLIENT_ID,pin,TOKEN);
+		if (rtn != 0)
+			fail("FAILURE: EXTRACT_PIN rtn: " + rtn);
+
+		System.out.print("Client Token TK: 0x"); printBinary(TOKEN);
+
+		if (FULL)
+		{
+			MPIN.PRECOMPUTE(TOKEN,HCID,G1,G2);
+		}
+		int date;
+		if (PERMITS)
+		{
+			date=MPIN.today();
+/* Client gets "Time Token" permit from DTA */ 
+			MPIN.GET_CLIENT_PERMIT(sha,date,S,HCID,PERMIT);
+			System.out.print("Time Permit TP: 0x");  printBinary(PERMIT); 
+
+/* This encoding makes Time permit look random - Elligator squared */
+			MPIN.ENCODING(rng,PERMIT);
+			System.out.print("Encoded Time Permit TP: 0x");  printBinary(PERMIT); 
+			MPIN.DECODING(PERMIT);
+			System.out.print("Decoded Time Permit TP: 0x");  printBinary(PERMIT); 
+		}
+		else date=0;
+
+//		System.out.print("\nPIN= ");
+//		Scanner scan=new Scanner(System.in);
+//		pin=scan.nextInt();
+
+		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.
+
+
+*/
+
+		byte[] pxID=xID;
+		byte[] pxCID=xCID;
+		byte[] pHID=HID;
+		byte[] pHTID=HTID;
+		byte[] pE=E;
+		byte[] pF=F;
+		byte[] pPERMIT=PERMIT;
+		byte[] prHID;
+
+		if (date!=0)
+		{
+
+			prHID=pHTID;
+			if (!PINERROR)
+			{
+				pxID=null;
+		//		pHID=null;  // new
+			}
+		}
+		else
+		{
+			prHID=pHID;
+			pPERMIT=null;
+			pxCID=null;
+			pHTID=null;
+		}
+		if (!PINERROR)
+		{
+			pE=null;
+			pF=null;
+		}
+                 
+		if (SINGLE_PASS)
+		{
+  			System.out.println("MPIN Single Pass");
+			int timeValue = MPIN.GET_TIME();
+			rtn=MPIN.CLIENT(sha,date,CLIENT_ID,rng,X,pin,TOKEN,SEC,pxID,pxCID,pPERMIT,timeValue,Y);
+			if (rtn != 0)
+  				fail("FAILURE: CLIENT rtn: " + rtn);
+
+			if (FULL)
+			{
+				HCID=MPIN.HASH_ID(sha,CLIENT_ID,EFS);
+				MPIN.GET_G1_MULTIPLE(rng,1,R,HCID,Z);  /* Also Send Z=r.ID to Server, remember random r */
+			}
+
+			rtn=MPIN.SERVER(sha,date,pHID,pHTID,Y,SST,pxID,pxCID,SEC,pE,pF,CLIENT_ID,timeValue);
+			if (rtn != 0)
+  				fail("FAILURE: SERVER rtn: " + rtn);
+
+			if (FULL)
+			{
+				HSID=MPIN.HASH_ID(sha,CLIENT_ID,EFS);
+				MPIN.GET_G1_MULTIPLE(rng,0,W,prHID,T);  /* Also send T=w.ID to client, remember random w  */
+			}
+		}
+		else
+		{
+  			System.out.println("MPIN Multi Pass");
+                  /* Send U=x.ID to server, and recreate secret from token and pin */
+  			rtn=MPIN.CLIENT_1(sha,date,CLIENT_ID,rng,X,pin,TOKEN,SEC,pxID,pxCID,pPERMIT);
+  			if (rtn != 0)
+  				fail("FAILURE: CLIENT_1 rtn: " + rtn);
+  
+  			if (FULL)
+  			{
+  				HCID=MPIN.HASH_ID(sha,CLIENT_ID,EFS);
+  				MPIN.GET_G1_MULTIPLE(rng,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. */
+  			MPIN.SERVER_1(sha,date,CLIENT_ID,pHID,pHTID);
+  
+                  /* Server generates Random number Y and sends it to Client */
+  			MPIN.RANDOM_GENERATE(rng,Y);
+  
+			if (FULL)
+			{
+				HSID=MPIN.HASH_ID(sha,CLIENT_ID,EFS);
+  				MPIN.GET_G1_MULTIPLE(rng,0,W,prHID,T);  /* Also send T=w.ID to client, remember random w  */
+			}
+  
+                  /* Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC */
+  			rtn=MPIN.CLIENT_2(X,Y,SEC);
+  			if (rtn != 0)
+  				fail("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=MPIN.SERVER_2(date,pHID,pHTID,Y,SST,pxID,pxCID,SEC,pE,pF);
+  
+  			if (rtn != 0)
+  				fail("FAILURE: SERVER_2 rtn: " + rtn);
+		}
+  
+		if (rtn == MPIN.BAD_PIN)
+		{
+			if (PINERROR)
+			{
+				int err=MPIN.KANGAROO(E,F);
+				if (err!=0) fail("Client PIN is out by "+err);
+				else fail("Server says - Bad Pin. I don't know you. Feck off");
+			}
+			else fail("Server says - Bad Pin. I don't know you. Feck off");
+
+		}
+		else System.out.println("Server says - PIN is good! You really are "+IDstr);
+
+
+		if (FULL)
+		{
+			byte[] H=MPIN.HASH_ALL(sha,HCID,pxID,pxCID,SEC,Y,Z,T,EFS);
+			MPIN.CLIENT_KEY(sha,G1,G2,pin,R,X,H,T,CK);
+			System.out.print("Client Key =  0x");  printBinary(CK); 
+
+			H=MPIN.HASH_ALL(sha,HSID,pxID,pxCID,SEC,Y,Z,T,EFS);
+			MPIN.SERVER_KEY(sha,Z,SST,W,H,pHID,pxID,pxCID,SK);
+			System.out.print("Server Key =  0x");  printBinary(SK); 
+		}
+		System.out.println("");
+	}
+/*
+	public static void main(String[] args) 
+	{
+
+		byte[] RAW=new byte[100];
+		RAND rng=new RAND();
+
+		rng.clean();
+		for (int i=0;i<100;i++) RAW[i]=(byte)(i);
+
+		rng.seed(100,RAW);
+
+		mpin(rng);
+
+	} */
+}
diff --git a/version3/java/TestMPIN192.java b/version3/java/TestMPIN192.java
new file mode 100644
index 0000000..5342df5
--- /dev/null
+++ b/version3/java/TestMPIN192.java
@@ -0,0 +1,297 @@
+/*
+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.
+*/
+
+/* test driver and function exerciser for ECDH/ECIES/ECDSA API Functions */
+package org.apache.milagro.amcl.XXX;  //
+
+import java.util.Scanner;
+import junit.framework.TestCase;      //
+import org.apache.milagro.amcl.RAND;
+
+public class TestMPIN192 extends TestCase //
+{
+	private static void printBinary(byte[] array)
+	{
+		int i;
+		for (i=0;i<array.length;i++)
+		{
+			System.out.printf("%02x", array[i]);
+		}
+		System.out.println();
+	}    
+
+
+	static boolean PERMITS=true;
+	static boolean PINERROR=true;
+	static boolean FULL=true;
+	static boolean SINGLE_PASS=false;
+
+	public static void testMPIN()
+	{
+		RAND rng=new RAND();
+		int EGS=MPIN192.EGS;
+		int EFS=MPIN192.EFS;
+		int G1S=2*EFS+1; /* Group 1 Size */
+		int G2S=8*EFS; /* Group 2 Size */
+
+		int sha=ECP.HASH_TYPE;
+
+		byte[] S = new byte[EGS];
+		byte[] SST = new byte[G2S];
+		byte[] TOKEN = new byte[G1S];
+		byte[] PERMIT = new byte[G1S];
+		byte[] SEC = new byte[G1S];
+		byte[] xID = new byte[G1S];
+		byte[] xCID = new byte[G1S];
+		byte[] X= new byte[EGS];
+		byte[] Y= new byte[EGS];
+		byte[] E=new byte[24*EFS];
+		byte[] F=new byte[24*EFS];
+		byte[] HID=new byte[G1S];
+		byte[] HTID=new byte[G1S];
+
+		byte[] G1=new byte[24*EFS];
+		byte[] G2=new byte[24*EFS];
+		byte[] R=new byte[EGS];
+		byte[] Z=new byte[G1S];
+		byte[] W=new byte[EGS];
+		byte[] T=new byte[G1S];
+		byte[] CK=new byte[ECP.AESKEY];
+		byte[] SK=new byte[ECP.AESKEY];
+
+		byte[] HSID=null;
+		byte[] RAW=new byte[100];
+
+		rng.clean();
+		for (int i=0;i<100;i++) RAW[i]=(byte)(i);
+		rng.seed(100,RAW);
+
+		System.out.println("Testing MPIN code");
+
+/* Trusted Authority set-up */
+
+		MPIN192.RANDOM_GENERATE(rng,S);
+		System.out.print("Master Secret s: 0x");  printBinary(S);
+ 
+ /* Create Client Identity */
+ 		String IDstr = "testUser@miracl.com";
+		byte[] CLIENT_ID = IDstr.getBytes();   
+
+		byte[] HCID=MPIN192.HASH_ID(sha,CLIENT_ID,EFS);  /* Either Client or TA calculates Hash(ID) - you decide! */
+
+		System.out.print("Client ID Hash= "); printBinary(HCID);
+		System.out.print("Client ID= "); printBinary(CLIENT_ID);
+
+/* Client and Server are issued secrets by DTA */
+
+		MPIN192.GET_CLIENT_SECRET(S,HCID,TOKEN);
+		System.out.print("Client Secret CS: 0x");        
+		printBinary(TOKEN); 
+
+		MPIN192.GET_SERVER_SECRET(S,SST);
+		System.out.print("Server Secret SS: 0x");  printBinary(SST); 
+
+
+/* Client extracts PIN from secret to create Token */
+		int pin=1234;
+		System.out.println("Client extracts PIN= "+pin); 
+		int rtn=MPIN192.EXTRACT_PIN(sha,CLIENT_ID,pin,TOKEN);
+		if (rtn != 0)
+			fail("FAILURE: EXTRACT_PIN rtn: " + rtn);
+
+		System.out.print("Client Token TK: 0x"); printBinary(TOKEN);
+
+		if (FULL)
+		{
+			MPIN192.PRECOMPUTE(TOKEN,HCID,G1,G2);
+		}
+		int date;
+		if (PERMITS)
+		{
+			date=MPIN192.today();
+/* Client gets "Time Token" permit from DTA */ 
+			MPIN192.GET_CLIENT_PERMIT(sha,date,S,HCID,PERMIT);
+			System.out.print("Time Permit TP: 0x");  printBinary(PERMIT); 
+
+/* This encoding makes Time permit look random - Elligator squared */
+			MPIN192.ENCODING(rng,PERMIT);
+			System.out.print("Encoded Time Permit TP: 0x");  printBinary(PERMIT); 
+			MPIN192.DECODING(PERMIT);
+			System.out.print("Decoded Time Permit TP: 0x");  printBinary(PERMIT); 
+		}
+		else date=0;
+
+//		System.out.print("\nPIN= ");
+//		Scanner scan=new Scanner(System.in);
+//		pin=scan.nextInt();
+
+		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.
+
+
+*/
+
+		byte[] pxID=xID;
+		byte[] pxCID=xCID;
+		byte[] pHID=HID;
+		byte[] pHTID=HTID;
+		byte[] pE=E;
+		byte[] pF=F;
+		byte[] pPERMIT=PERMIT;
+		byte[] prHID;
+
+		if (date!=0)
+		{
+
+			prHID=pHTID;
+			if (!PINERROR)
+			{
+				pxID=null;
+		//		pHID=null;  // new
+			}
+		}
+		else
+		{
+			prHID=pHID;
+			pPERMIT=null;
+			pxCID=null;
+			pHTID=null;
+		}
+		if (!PINERROR)
+		{
+			pE=null;
+			pF=null;
+		}
+                 
+		if (SINGLE_PASS)
+		{
+  			System.out.println("MPIN Single Pass");
+			int timeValue = MPIN192.GET_TIME();
+			rtn=MPIN192.CLIENT(sha,date,CLIENT_ID,rng,X,pin,TOKEN,SEC,pxID,pxCID,pPERMIT,timeValue,Y);
+			if (rtn != 0)
+  				fail("FAILURE: CLIENT rtn: " + rtn);
+
+			if (FULL)
+			{
+				HCID=MPIN192.HASH_ID(sha,CLIENT_ID,EFS);
+				MPIN192.GET_G1_MULTIPLE(rng,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)
+  				fail("FAILURE: SERVER rtn: " + rtn);
+
+			if (FULL)
+			{
+				HSID=MPIN192.HASH_ID(sha,CLIENT_ID,EFS);
+				MPIN192.GET_G1_MULTIPLE(rng,0,W,prHID,T);  /* Also send T=w.ID to client, remember random w  */
+			}
+		}
+		else
+		{
+  			System.out.println("MPIN Multi Pass");
+                  /* Send U=x.ID to server, and recreate secret from token and pin */
+  			rtn=MPIN192.CLIENT_1(sha,date,CLIENT_ID,rng,X,pin,TOKEN,SEC,pxID,pxCID,pPERMIT);
+  			if (rtn != 0)
+  				fail("FAILURE: CLIENT_1 rtn: " + rtn);
+  
+  			if (FULL)
+  			{
+  				HCID=MPIN192.HASH_ID(sha,CLIENT_ID,EFS);
+  				MPIN192.GET_G1_MULTIPLE(rng,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(rng,Y);
+  
+			if (FULL)
+			{
+				HSID=MPIN192.HASH_ID(sha,CLIENT_ID,EFS);
+  				MPIN192.GET_G1_MULTIPLE(rng,0,W,prHID,T);  /* Also send T=w.ID to client, remember random w  */
+			}
+  
+                  /* Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC */
+  			rtn=MPIN192.CLIENT_2(X,Y,SEC);
+  			if (rtn != 0)
+  				fail("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)
+  				fail("FAILURE: SERVER_2 rtn: " + rtn);
+		}
+  
+		if (rtn == MPIN192.BAD_PIN)
+		{
+			if (PINERROR)
+			{
+				int err=MPIN192.KANGAROO(E,F);
+				if (err!=0) fail("Client PIN is out by "+err);
+				else fail("Server says - Bad Pin. I don't know you. Feck off");
+			}
+			else fail("Server says - Bad Pin. I don't know you. Feck off");
+
+		}
+		else System.out.println("Server says - PIN is good! You really are "+IDstr);
+
+
+		if (FULL)
+		{
+			byte[] H=MPIN192.HASH_ALL(sha,HCID,pxID,pxCID,SEC,Y,Z,T,EFS);
+			MPIN192.CLIENT_KEY(sha,G1,G2,pin,R,X,H,T,CK);
+			System.out.print("Client Key =  0x");  printBinary(CK); 
+
+			H=MPIN192.HASH_ALL(sha,HSID,pxID,pxCID,SEC,Y,Z,T,EFS);
+			MPIN192.SERVER_KEY(sha,Z,SST,W,H,pHID,pxID,pxCID,SK);
+			System.out.print("Server Key =  0x");  printBinary(SK); 
+		}
+		System.out.println("");
+	}
+/*
+	public static void main(String[] args) 
+	{
+
+		byte[] RAW=new byte[100];
+		RAND rng=new RAND();
+
+		rng.clean();
+		for (int i=0;i<100;i++) RAW[i]=(byte)(i);
+
+		rng.seed(100,RAW);
+
+		mpin(rng);
+
+	} */
+}
diff --git a/version3/java/TestMPIN256.java b/version3/java/TestMPIN256.java
new file mode 100644
index 0000000..bdea4b4
--- /dev/null
+++ b/version3/java/TestMPIN256.java
@@ -0,0 +1,297 @@
+/*
+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.
+*/
+
+/* test driver and function exerciser for ECDH/ECIES/ECDSA API Functions */
+package org.apache.milagro.amcl.XXX;  //
+
+import java.util.Scanner;
+import junit.framework.TestCase;      //
+import org.apache.milagro.amcl.RAND;
+
+public class TestMPIN256 extends TestCase //
+{
+	private static void printBinary(byte[] array)
+	{
+		int i;
+		for (i=0;i<array.length;i++)
+		{
+			System.out.printf("%02x", array[i]);
+		}
+		System.out.println();
+	}    
+
+
+	static boolean PERMITS=true;
+	static boolean PINERROR=true;
+	static boolean FULL=true;
+	static boolean SINGLE_PASS=false;
+
+	public static void testMPIN()
+	{
+		RAND rng=new RAND();
+		int EGS=MPIN256.EGS;
+		int EFS=MPIN256.EFS;
+		int G1S=2*EFS+1; /* Group 1 Size */
+		int G2S=16*EFS; /* Group 2 Size */
+
+		int sha=ECP.HASH_TYPE;
+
+		byte[] S = new byte[EGS];
+		byte[] SST = new byte[G2S];
+		byte[] TOKEN = new byte[G1S];
+		byte[] PERMIT = new byte[G1S];
+		byte[] SEC = new byte[G1S];
+		byte[] xID = new byte[G1S];
+		byte[] xCID = new byte[G1S];
+		byte[] X= new byte[EGS];
+		byte[] Y= new byte[EGS];
+		byte[] E=new byte[48*EFS];
+		byte[] F=new byte[48*EFS];
+		byte[] HID=new byte[G1S];
+		byte[] HTID=new byte[G1S];
+
+		byte[] G1=new byte[48*EFS];
+		byte[] G2=new byte[48*EFS];
+		byte[] R=new byte[EGS];
+		byte[] Z=new byte[G1S];
+		byte[] W=new byte[EGS];
+		byte[] T=new byte[G1S];
+		byte[] CK=new byte[ECP.AESKEY];
+		byte[] SK=new byte[ECP.AESKEY];
+
+		byte[] HSID=null;
+		byte[] RAW=new byte[100];
+
+		rng.clean();
+		for (int i=0;i<100;i++) RAW[i]=(byte)(i);
+		rng.seed(100,RAW);
+
+		System.out.println("Testing MPIN code");
+
+/* Trusted Authority set-up */
+
+		MPIN256.RANDOM_GENERATE(rng,S);
+		System.out.print("Master Secret s: 0x");  printBinary(S);
+ 
+ /* Create Client Identity */
+ 		String IDstr = "testUser@miracl.com";
+		byte[] CLIENT_ID = IDstr.getBytes();   
+
+		byte[] HCID=MPIN256.HASH_ID(sha,CLIENT_ID,EFS);  /* Either Client or TA calculates Hash(ID) - you decide! */
+
+		System.out.print("Client ID Hash= "); printBinary(HCID);
+		System.out.print("Client ID= "); printBinary(CLIENT_ID);
+
+/* Client and Server are issued secrets by DTA */
+
+		MPIN256.GET_CLIENT_SECRET(S,HCID,TOKEN);
+		System.out.print("Client Secret CS: 0x");        
+		printBinary(TOKEN); 
+
+		MPIN256.GET_SERVER_SECRET(S,SST);
+		System.out.print("Server Secret SS: 0x");  printBinary(SST); 
+
+
+/* Client extracts PIN from secret to create Token */
+		int pin=1234;
+		System.out.println("Client extracts PIN= "+pin); 
+		int rtn=MPIN256.EXTRACT_PIN(sha,CLIENT_ID,pin,TOKEN);
+		if (rtn != 0)
+			fail("FAILURE: EXTRACT_PIN rtn: " + rtn);
+
+		System.out.print("Client Token TK: 0x"); printBinary(TOKEN);
+
+		if (FULL)
+		{
+			MPIN256.PRECOMPUTE(TOKEN,HCID,G1,G2);
+		}
+		int date;
+		if (PERMITS)
+		{
+			date=MPIN256.today();
+/* Client gets "Time Token" permit from DTA */ 
+			MPIN256.GET_CLIENT_PERMIT(sha,date,S,HCID,PERMIT);
+			System.out.print("Time Permit TP: 0x");  printBinary(PERMIT); 
+
+/* This encoding makes Time permit look random - Elligator squared */
+			MPIN256.ENCODING(rng,PERMIT);
+			System.out.print("Encoded Time Permit TP: 0x");  printBinary(PERMIT); 
+			MPIN256.DECODING(PERMIT);
+			System.out.print("Decoded Time Permit TP: 0x");  printBinary(PERMIT); 
+		}
+		else date=0;
+
+//		System.out.print("\nPIN= ");
+//		Scanner scan=new Scanner(System.in);
+//		pin=scan.nextInt();
+
+		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.
+
+
+*/
+
+		byte[] pxID=xID;
+		byte[] pxCID=xCID;
+		byte[] pHID=HID;
+		byte[] pHTID=HTID;
+		byte[] pE=E;
+		byte[] pF=F;
+		byte[] pPERMIT=PERMIT;
+		byte[] prHID;
+
+		if (date!=0)
+		{
+
+			prHID=pHTID;
+			if (!PINERROR)
+			{
+				pxID=null;
+		//		pHID=null;  // new
+			}
+		}
+		else
+		{
+			prHID=pHID;
+			pPERMIT=null;
+			pxCID=null;
+			pHTID=null;
+		}
+		if (!PINERROR)
+		{
+			pE=null;
+			pF=null;
+		}
+                 
+		if (SINGLE_PASS)
+		{
+  			System.out.println("MPIN Single Pass");
+			int timeValue = MPIN256.GET_TIME();
+			rtn=MPIN256.CLIENT(sha,date,CLIENT_ID,rng,X,pin,TOKEN,SEC,pxID,pxCID,pPERMIT,timeValue,Y);
+			if (rtn != 0)
+  				fail("FAILURE: CLIENT rtn: " + rtn);
+
+			if (FULL)
+			{
+				HCID=MPIN256.HASH_ID(sha,CLIENT_ID,EFS);
+				MPIN256.GET_G1_MULTIPLE(rng,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)
+  				fail("FAILURE: SERVER rtn: " + rtn);
+
+			if (FULL)
+			{
+				HSID=MPIN256.HASH_ID(sha,CLIENT_ID,EFS);
+				MPIN256.GET_G1_MULTIPLE(rng,0,W,prHID,T);  /* Also send T=w.ID to client, remember random w  */
+			}
+		}
+		else
+		{
+  			System.out.println("MPIN Multi Pass");
+                  /* Send U=x.ID to server, and recreate secret from token and pin */
+  			rtn=MPIN256.CLIENT_1(sha,date,CLIENT_ID,rng,X,pin,TOKEN,SEC,pxID,pxCID,pPERMIT);
+  			if (rtn != 0)
+  				fail("FAILURE: CLIENT_1 rtn: " + rtn);
+  
+  			if (FULL)
+  			{
+  				HCID=MPIN256.HASH_ID(sha,CLIENT_ID,EFS);
+  				MPIN256.GET_G1_MULTIPLE(rng,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(rng,Y);
+  
+			if (FULL)
+			{
+				HSID=MPIN256.HASH_ID(sha,CLIENT_ID,EFS);
+  				MPIN256.GET_G1_MULTIPLE(rng,0,W,prHID,T);  /* Also send T=w.ID to client, remember random w  */
+			}
+  
+                  /* Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC */
+  			rtn=MPIN256.CLIENT_2(X,Y,SEC);
+  			if (rtn != 0)
+  				fail("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)
+  				fail("FAILURE: SERVER_2 rtn: " + rtn);
+		}
+  
+		if (rtn == MPIN256.BAD_PIN)
+		{
+			if (PINERROR)
+			{
+				int err=MPIN256.KANGAROO(E,F);
+				if (err!=0) fail("Client PIN is out by "+err);
+				else fail("Server says - Bad Pin. I don't know you. Feck off");
+			}
+			else fail("Server says - Bad Pin. I don't know you. Feck off");
+
+		}
+		else System.out.println("Server says - PIN is good! You really are "+IDstr);
+
+
+		if (FULL)
+		{
+			byte[] H=MPIN256.HASH_ALL(sha,HCID,pxID,pxCID,SEC,Y,Z,T,EFS);
+			MPIN256.CLIENT_KEY(sha,G1,G2,pin,R,X,H,T,CK);
+			System.out.print("Client Key =  0x");  printBinary(CK); 
+
+			H=MPIN256.HASH_ALL(sha,HSID,pxID,pxCID,SEC,Y,Z,T,EFS);
+			MPIN256.SERVER_KEY(sha,Z,SST,W,H,pHID,pxID,pxCID,SK);
+			System.out.print("Server Key =  0x");  printBinary(SK); 
+		}
+		System.out.println("");
+	}
+/*
+	public static void main(String[] args) 
+	{
+
+		byte[] RAW=new byte[100];
+		RAND rng=new RAND();
+
+		rng.clean();
+		for (int i=0;i<100;i++) RAW[i]=(byte)(i);
+
+		rng.seed(100,RAW);
+
+		mpin(rng);
+
+	} */
+}
diff --git a/version3/java/TestNHS.java b/version3/java/TestNHS.java
new file mode 100644
index 0000000..18cef73
--- /dev/null
+++ b/version3/java/TestNHS.java
@@ -0,0 +1,70 @@
+/*
+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.
+*/
+
+/* test driver and function exerciser for NewHope API Functions */
+
+// See https://eprint.iacr.org/2016/1157 (Alkim, Ducas, Popplemann and Schwabe)
+
+// javac -cp amcl.jar; TestNHS.java
+// java -cp amcl.jar; TestNHS
+
+package org.apache.milagro;
+
+import org.apache.milagro.amcl.RAND;
+import org.apache.milagro.amcl.NHS;
+
+public class TestNHS
+{	
+		public static void main(String[] args) {
+		int i;
+		byte[] RAW=new byte[100];
+		byte[] S=new byte[1792];
+		byte[] SB=new byte[1824];
+		byte[] UC=new byte[2176];
+		byte[] KEYA=new byte[32];
+		byte[] KEYB=new byte[32];
+
+		RAND SRNG=new RAND();
+		RAND CRNG=new RAND();
+		SRNG.clean(); CRNG.clean();
+
+		for (i=0;i<100;i++) RAW[i]=(byte)(i+1);
+		SRNG.seed(100,RAW);
+
+										for (i=0;i<100;i++) RAW[i]=(byte)(i+2);
+										CRNG.seed(100,RAW);
+
+// NewHope Simple key exchange
+
+		NHS.SERVER_1(SRNG,SB,S);
+										NHS.CLIENT(CRNG,SB,UC,KEYB);
+		NHS.SERVER_2(S,UC,KEYA);
+
+		System.out.printf("Alice key= 0x");
+		for (i=0;i<KEYA.length;i++)
+			System.out.printf("%02x", KEYA[i]);
+		System.out.println();
+
+
+										System.out.printf("Bob's key= 0x");
+										for (i=0;i<KEYA.length;i++)
+											System.out.printf("%02x", KEYB[i]);
+										System.out.println();
+	}
+}
\ No newline at end of file
diff --git a/version3/java/TestRSA.java b/version3/java/TestRSA.java
new file mode 100644
index 0000000..cbe9f44
--- /dev/null
+++ b/version3/java/TestRSA.java
@@ -0,0 +1,111 @@
+/*
+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.
+*/
+
+/* test driver and function exerciser for ECDH/ECIES/ECDSA API Functions */
+package org.apache.milagro.amcl.XXX;
+
+import java.util.Scanner;
+import junit.framework.TestCase;
+import org.apache.milagro.amcl.RAND;
+
+public class TestRSA extends TestCase
+{
+	private static void printBinary(byte[] array)
+	{
+		int i;
+		for (i=0;i<array.length;i++)
+		{
+			System.out.printf("%02x", array[i]);
+		}
+		System.out.println();
+	}    
+
+	public static void testRSA()
+	{
+		byte[] RAW=new byte[100];
+		RAND rng=new RAND();
+
+		rng.clean();
+		for (int i=0;i<100;i++) RAW[i]=(byte)(i);
+
+		rng.seed(100,RAW);
+		
+		int i;
+		int RFS=RSA.RFS;
+		int sha=RSA.HASH_TYPE;
+
+		String message="Hello World\n";
+
+		public_key pub=new public_key(FF.FFLEN);
+		private_key priv=new private_key(FF.HFLEN);
+
+		byte[] ML=new byte[RFS];
+		byte[] C=new byte[RFS];
+		byte[] S=new byte[RFS];
+
+
+		System.out.println("Testing RSA code");
+
+		System.out.println("Generating public/private key pair");
+		RSA.KEY_PAIR(rng,65537,priv,pub);
+
+		byte[] M=message.getBytes();
+		System.out.print("Encrypting test string\n");
+
+
+		byte[] E=RSA.OAEP_ENCODE(sha,M,rng,null); /* OAEP encode message M to E  */
+
+		if (E.length==0) {
+			fail("Encoding failed");
+		}
+
+		RSA.ENCRYPT(pub,E,C);     /* encrypt encoded message */
+		System.out.print("Ciphertext= 0x"); printBinary(C);
+
+		System.out.print("Decrypting test string\n");
+		RSA.DECRYPT(priv,C,ML); 
+		byte[] MS=RSA.OAEP_DECODE(sha,null,ML); /* OAEP decode message  */
+
+		message=new String(MS);
+		System.out.print(message);
+
+		System.out.println("Signing message");
+		RSA.PKCS15(sha,M,C);
+
+		RSA.DECRYPT(priv,C,S); /* create signature in S */ 
+
+		System.out.print("Signature= 0x"); printBinary(S);
+
+		RSA.ENCRYPT(pub,S,ML); 
+
+		boolean cmp=true;
+		if (C.length!=ML.length) cmp=false;
+		else
+		{
+			for (int j=0;j<C.length;j++)
+				if (C[j]!=ML[j]) cmp=false;
+		}
+		if (cmp) System.out.println("Signature is valid");
+		else fail("Signature is INVALID");
+
+		RSA.PRIVATE_KEY_KILL(priv);
+		System.out.println("");
+
+	}
+}
diff --git a/version3/java/TesttimeECDH.java b/version3/java/TesttimeECDH.java
new file mode 100644
index 0000000..2eedccc
--- /dev/null
+++ b/version3/java/TesttimeECDH.java
@@ -0,0 +1,103 @@
+/*
+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.
+*/
+
+/* test driver and function exerciser for ECDH/ECIES/ECDSA API Functions */
+package org.apache.milagro.amcl.XXX;
+
+import java.util.Scanner;
+import junit.framework.TestCase;
+import org.apache.milagro.amcl.RAND;
+
+public class TesttimeECDH extends TestCase
+{
+	public static final int MIN_TIME=10; /* seconds */
+	public static final int MIN_ITERS=10; 
+
+	public static void testtimeECDH()
+	{
+		byte[] RAW=new byte[100];
+		RAND rng=new RAND();
+		int i,iterations;
+		long start,elapsed;
+		double dur;
+
+		rng.clean();
+		for (i=0;i<100;i++) RAW[i]=(byte)(i);
+		rng.seed(100,RAW);
+
+		System.out.println("\nTesting/Timing ECC");
+		if (ECP.CURVETYPE==ECP.WEIERSTRASS)
+		{
+			System.out.print("Weierstrass parameterization\n");
+		}		
+		if (ECP.CURVETYPE==ECP.EDWARDS)
+		{
+			System.out.print("Edwards parameterization\n");
+		}
+		if (ECP.CURVETYPE==ECP.MONTGOMERY)
+		{
+			System.out.print("Montgomery parameterization\n");
+		}
+
+		if (FP.MODTYPE==FP.PSEUDO_MERSENNE)
+		{
+			System.out.print("Pseudo-Mersenne Modulus\n");
+		}
+		if (FP.MODTYPE==FP.MONTGOMERY_FRIENDLY)
+		{
+			System.out.print("Montgomery friendly Modulus\n");
+		}
+		if (FP.MODTYPE==FP.GENERALISED_MERSENNE)
+		{
+			System.out.print("Generalised-Mersenne Modulus\n");
+		}
+		if (FP.MODTYPE==FP.NOT_SPECIAL)
+		{
+			System.out.print("Not special Modulus\n");
+		}
+
+		System.out.format("Modulus size %d bits\n",FP.MODBITS); 
+		System.out.format("%d bit build\n",BIG.CHUNK); 
+		BIG r,s,wx,wy;
+		ECP G,WP;
+
+		G=ECP.generator();
+
+		r=new BIG(ROM.CURVE_Order);
+		s=BIG.randomnum(r,rng);
+
+		WP=G.mul(r);
+		if (!WP.is_infinity())
+		{
+			fail("FAILURE - rG!=O");
+		}
+
+		start = System.currentTimeMillis();
+		iterations=0;
+		do {
+			WP=G.mul(s);
+			iterations++;
+			elapsed=(System.currentTimeMillis()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=(double)elapsed/iterations;
+		System.out.format("EC  mul - %8d iterations  ",iterations);
+		System.out.format(" %8.2f ms per iteration\n",dur);
+
+	}
+}
diff --git a/version3/java/TesttimeMPIN.java b/version3/java/TesttimeMPIN.java
new file mode 100644
index 0000000..8b95c44
--- /dev/null
+++ b/version3/java/TesttimeMPIN.java
@@ -0,0 +1,195 @@
+/*
+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.
+*/
+
+/* test driver and function exerciser for ECDH/ECIES/ECDSA API Functions */
+package org.apache.milagro.amcl.XXX;
+
+import java.util.Scanner;
+import junit.framework.TestCase;
+import org.apache.milagro.amcl.RAND;
+
+public class TesttimeMPIN extends TestCase
+{
+	public static final int MIN_TIME=10; /* seconds */
+	public static final int MIN_ITERS=10; 
+
+	static boolean PERMITS=true;
+	static boolean PINERROR=true;
+	static boolean FULL=true;
+	static boolean SINGLE_PASS=false;
+
+	public static void testtimeMPIN()
+	{
+		byte[] RAW=new byte[100];
+		RAND rng=new RAND();
+
+		int i,iterations;
+		long start,elapsed;
+		double dur;
+
+		rng.clean();
+		for (i=0;i<100;i++) RAW[i]=(byte)(i);
+		rng.seed(100,RAW);
+
+
+		System.out.println("\nTesting/Timing Pairings");
+		if (ECP.CURVE_PAIRING_TYPE==ECP.BN)
+		{
+			System.out.print("BN Pairing-Friendly Curve\n");
+		}
+		if (ECP.CURVE_PAIRING_TYPE==ECP.BLS)
+		{
+			System.out.print("BLS Pairing-Friendly Curve\n");
+		}
+
+		System.out.format("Modulus size %d bits\n",FP.MODBITS); 
+		System.out.format("%d bit build\n",BIG.CHUNK); 
+
+		ECP G=ECP.generator();
+
+		BIG r=new BIG(ROM.CURVE_Order);
+		BIG s=BIG.randomnum(r,rng);
+
+		ECP P=PAIR.G1mul(G,r);
+
+		if (!P.is_infinity())
+		{
+			fail("FAILURE - rP!=O");
+		}
+
+		iterations=0;
+		start=System.currentTimeMillis();
+		do {
+			P=PAIR.G1mul(G,s);
+			iterations++;
+			elapsed=(System.currentTimeMillis()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=(double)elapsed/iterations;
+		System.out.format("G1 mul              - %8d iterations  ",iterations);
+		System.out.format(" %8.2f ms per iteration\n",dur);
+	
+		ECP2 Q=ECP2.generator();
+		ECP2 W=PAIR.G2mul(Q,r);
+
+		if (!W.is_infinity())
+		{
+			fail("FAILURE - rQ!=O");
+		}
+
+		iterations=0;
+		start=System.currentTimeMillis();
+		do {
+			W=PAIR.G2mul(Q,s);
+			iterations++;
+			elapsed=(System.currentTimeMillis()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=(double)elapsed/iterations;
+		System.out.format("G2 mul              - %8d iterations  ",iterations);
+		System.out.format(" %8.2f ms per iteration\n",dur);
+
+		FP12 w=PAIR.ate(Q,P);
+		w=PAIR.fexp(w);
+
+		FP12 g=PAIR.GTpow(w,r);
+
+		if (!g.isunity())
+		{
+			fail("FAILURE - g^r!=1");
+		}
+
+		iterations=0;
+		start=System.currentTimeMillis();
+		do {
+			g=PAIR.GTpow(w,s);
+			iterations++;
+			elapsed=(System.currentTimeMillis()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=(double)elapsed/iterations;
+		System.out.format("GT pow              - %8d iterations  ",iterations);
+		System.out.format(" %8.2f ms per iteration\n",dur);
+	
+		g.copy(w);
+		FP4 cr;
+		iterations=0;
+		start=System.currentTimeMillis();
+		do {
+			cr=g.compow(s,r);
+
+			iterations++;
+			elapsed=(System.currentTimeMillis()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=(double)elapsed/iterations;
+		System.out.format("GT pow (compressed) - %8d iterations  ",iterations);
+		System.out.format(" %8.2f ms per iteration\n",dur);
+
+		iterations=0;
+		start=System.currentTimeMillis();
+		do {
+			w=PAIR.ate(Q,P);
+			iterations++;
+			elapsed=(System.currentTimeMillis()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=(double)elapsed/iterations;
+		System.out.format("PAIRing ATE         - %8d iterations  ",iterations);
+		System.out.format(" %8.2f ms per iteration\n",dur);
+
+		iterations=0;
+		start=System.currentTimeMillis();
+		do {
+			g=PAIR.fexp(w);
+			iterations++;
+			elapsed=(System.currentTimeMillis()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=(double)elapsed/iterations;
+		System.out.format("PAIRing FEXP        - %8d iterations  ",iterations);
+		System.out.format(" %8.2f ms per iteration\n",dur);
+
+		P.copy(G);
+		Q.copy(W);
+
+		P=PAIR.G1mul(P,s);
+
+		g=PAIR.ate(Q,P);
+		g=PAIR.fexp(g);
+
+		P.copy(G);
+		Q=PAIR.G2mul(Q,s);
+
+		w=PAIR.ate(Q,P);
+		w=PAIR.fexp(w);
+
+		if (!g.equals(w))
+		{
+			fail("FAILURE - e(sQ,p)!=e(Q,sP) ");
+		}
+
+		Q.copy(W);
+		g=PAIR.ate(Q,P);
+		g=PAIR.fexp(g);
+		g=PAIR.GTpow(g,s);
+
+		if (!g.equals(w))
+		{
+			fail("FAILURE - e(sQ,p)!=e(Q,P)^s ");
+		}
+
+		System.out.print("All tests pass\n"); 
+	}
+
+}
diff --git a/version3/java/TesttimeMPIN192.java b/version3/java/TesttimeMPIN192.java
new file mode 100644
index 0000000..496343c
--- /dev/null
+++ b/version3/java/TesttimeMPIN192.java
@@ -0,0 +1,195 @@
+/*
+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.
+*/
+
+/* test driver and function exerciser for ECDH/ECIES/ECDSA API Functions */
+package org.apache.milagro.amcl.XXX;
+
+import java.util.Scanner;
+import junit.framework.TestCase;
+import org.apache.milagro.amcl.RAND;
+
+public class TesttimeMPIN192 extends TestCase
+{
+	public static final int MIN_TIME=10; /* seconds */
+	public static final int MIN_ITERS=10; 
+
+	static boolean PERMITS=true;
+	static boolean PINERROR=true;
+	static boolean FULL=true;
+	static boolean SINGLE_PASS=false;
+
+	public static void testtimeMPIN()
+	{
+		byte[] RAW=new byte[100];
+		RAND rng=new RAND();
+
+		int i,iterations;
+		long start,elapsed;
+		double dur;
+
+		rng.clean();
+		for (i=0;i<100;i++) RAW[i]=(byte)(i);
+		rng.seed(100,RAW);
+
+
+		System.out.println("\nTesting/Timing Pairings");
+		if (ECP.CURVE_PAIRING_TYPE==ECP.BN)
+		{
+			System.out.print("BN Pairing-Friendly Curve\n");
+		}
+		if (ECP.CURVE_PAIRING_TYPE==ECP.BLS)
+		{
+			System.out.print("BLS24 Pairing-Friendly Curve\n");
+		}
+
+		System.out.format("Modulus size %d bits\n",FP.MODBITS); 
+		System.out.format("%d bit build\n",BIG.CHUNK); 
+
+		ECP G=ECP.generator();
+
+		BIG r=new BIG(ROM.CURVE_Order);
+		BIG s=BIG.randomnum(r,rng);
+
+		ECP P=PAIR192.G1mul(G,r);
+
+		if (!P.is_infinity())
+		{
+			fail("FAILURE - rP!=O");
+		}
+
+		iterations=0;
+		start=System.currentTimeMillis();
+		do {
+			P=PAIR192.G1mul(G,s);
+			iterations++;
+			elapsed=(System.currentTimeMillis()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=(double)elapsed/iterations;
+		System.out.format("G1 mul              - %8d iterations  ",iterations);
+		System.out.format(" %8.2f ms per iteration\n",dur);
+	
+		ECP4 Q=ECP4.generator();
+		ECP4 W=PAIR192.G2mul(Q,r);
+
+		if (!W.is_infinity())
+		{
+			fail("FAILURE - rQ!=O");
+		}
+
+		iterations=0;
+		start=System.currentTimeMillis();
+		do {
+			W=PAIR192.G2mul(Q,s);
+			iterations++;
+			elapsed=(System.currentTimeMillis()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=(double)elapsed/iterations;
+		System.out.format("G2 mul              - %8d iterations  ",iterations);
+		System.out.format(" %8.2f ms per iteration\n",dur);
+
+		FP24 w=PAIR192.ate(Q,P);
+		w=PAIR192.fexp(w);
+
+		FP24 g=PAIR192.GTpow(w,r);
+
+		if (!g.isunity())
+		{
+			fail("FAILURE - g^r!=1");
+		}
+
+		iterations=0;
+		start=System.currentTimeMillis();
+		do {
+			g=PAIR192.GTpow(w,s);
+			iterations++;
+			elapsed=(System.currentTimeMillis()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=(double)elapsed/iterations;
+		System.out.format("GT pow              - %8d iterations  ",iterations);
+		System.out.format(" %8.2f ms per iteration\n",dur);
+	
+		g.copy(w);
+		FP8 cr;
+		iterations=0;
+		start=System.currentTimeMillis();
+		do {
+			cr=g.compow(s,r);
+
+			iterations++;
+			elapsed=(System.currentTimeMillis()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=(double)elapsed/iterations;
+		System.out.format("GT pow (compressed) - %8d iterations  ",iterations);
+		System.out.format(" %8.2f ms per iteration\n",dur);
+
+		iterations=0;
+		start=System.currentTimeMillis();
+		do {
+			w=PAIR192.ate(Q,P);
+			iterations++;
+			elapsed=(System.currentTimeMillis()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=(double)elapsed/iterations;
+		System.out.format("PAIRing ATE         - %8d iterations  ",iterations);
+		System.out.format(" %8.2f ms per iteration\n",dur);
+
+		iterations=0;
+		start=System.currentTimeMillis();
+		do {
+			g=PAIR192.fexp(w);
+			iterations++;
+			elapsed=(System.currentTimeMillis()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=(double)elapsed/iterations;
+		System.out.format("PAIRing FEXP        - %8d iterations  ",iterations);
+		System.out.format(" %8.2f ms per iteration\n",dur);
+
+		P.copy(G);
+		Q.copy(W);
+
+		P=PAIR192.G1mul(P,s);
+
+		g=PAIR192.ate(Q,P);
+		g=PAIR192.fexp(g);
+
+		P.copy(G);
+		Q=PAIR192.G2mul(Q,s);
+
+		w=PAIR192.ate(Q,P);
+		w=PAIR192.fexp(w);
+
+		if (!g.equals(w))
+		{
+			fail("FAILURE - e(sQ,p)!=e(Q,sP) ");
+		}
+
+		Q.copy(W);
+		g=PAIR192.ate(Q,P);
+		g=PAIR192.fexp(g);
+		g=PAIR192.GTpow(g,s);
+
+		if (!g.equals(w))
+		{
+			fail("FAILURE - e(sQ,p)!=e(Q,P)^s ");
+		}
+
+		System.out.print("All tests pass\n"); 
+	}
+
+}
diff --git a/version3/java/TesttimeMPIN256.java b/version3/java/TesttimeMPIN256.java
new file mode 100644
index 0000000..21fea6f
--- /dev/null
+++ b/version3/java/TesttimeMPIN256.java
@@ -0,0 +1,195 @@
+/*
+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.
+*/
+
+/* test driver and function exerciser for ECDH/ECIES/ECDSA API Functions */
+package org.apache.milagro.amcl.XXX;
+
+import java.util.Scanner;
+import junit.framework.TestCase;
+import org.apache.milagro.amcl.RAND;
+
+public class TesttimeMPIN256 extends TestCase
+{
+	public static final int MIN_TIME=10; /* seconds */
+	public static final int MIN_ITERS=10; 
+
+	static boolean PERMITS=true;
+	static boolean PINERROR=true;
+	static boolean FULL=true;
+	static boolean SINGLE_PASS=false;
+
+	public static void testtimeMPIN()
+	{
+		byte[] RAW=new byte[100];
+		RAND rng=new RAND();
+
+		int i,iterations;
+		long start,elapsed;
+		double dur;
+
+		rng.clean();
+		for (i=0;i<100;i++) RAW[i]=(byte)(i);
+		rng.seed(100,RAW);
+
+
+		System.out.println("\nTesting/Timing Pairings");
+		if (ECP.CURVE_PAIRING_TYPE==ECP.BN)
+		{
+			System.out.print("BN Pairing-Friendly Curve\n");
+		}
+		if (ECP.CURVE_PAIRING_TYPE==ECP.BLS)
+		{
+			System.out.print("BLS48 Pairing-Friendly Curve\n");
+		}
+
+		System.out.format("Modulus size %d bits\n",FP.MODBITS); 
+		System.out.format("%d bit build\n",BIG.CHUNK); 
+
+		ECP G=ECP.generator();
+
+		BIG r=new BIG(ROM.CURVE_Order);
+		BIG s=BIG.randomnum(r,rng);
+
+		ECP P=PAIR256.G1mul(G,r);
+
+		if (!P.is_infinity())
+		{
+			fail("FAILURE - rP!=O");
+		}
+
+		iterations=0;
+		start=System.currentTimeMillis();
+		do {
+			P=PAIR256.G1mul(G,s);
+			iterations++;
+			elapsed=(System.currentTimeMillis()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=(double)elapsed/iterations;
+		System.out.format("G1 mul              - %8d iterations  ",iterations);
+		System.out.format(" %8.2f ms per iteration\n",dur);
+	
+		ECP8 Q=ECP8.generator();
+		ECP8 W=PAIR256.G2mul(Q,r);
+
+		if (!W.is_infinity())
+		{
+			fail("FAILURE - rQ!=O");
+		}
+
+		iterations=0;
+		start=System.currentTimeMillis();
+		do {
+			W=PAIR256.G2mul(Q,s);
+			iterations++;
+			elapsed=(System.currentTimeMillis()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=(double)elapsed/iterations;
+		System.out.format("G2 mul              - %8d iterations  ",iterations);
+		System.out.format(" %8.2f ms per iteration\n",dur);
+
+		FP48 w=PAIR256.ate(Q,P);
+		w=PAIR256.fexp(w);
+
+		FP48 g=PAIR256.GTpow(w,r);
+
+		if (!g.isunity())
+		{
+			fail("FAILURE - g^r!=1");
+		}
+
+		iterations=0;
+		start=System.currentTimeMillis();
+		do {
+			g=PAIR256.GTpow(w,s);
+			iterations++;
+			elapsed=(System.currentTimeMillis()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=(double)elapsed/iterations;
+		System.out.format("GT pow              - %8d iterations  ",iterations);
+		System.out.format(" %8.2f ms per iteration\n",dur);
+	
+		g.copy(w);
+		FP16 cr;
+		iterations=0;
+		start=System.currentTimeMillis();
+		do {
+			cr=g.compow(s,r);
+
+			iterations++;
+			elapsed=(System.currentTimeMillis()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=(double)elapsed/iterations;
+		System.out.format("GT pow (compressed) - %8d iterations  ",iterations);
+		System.out.format(" %8.2f ms per iteration\n",dur);
+
+		iterations=0;
+		start=System.currentTimeMillis();
+		do {
+			w=PAIR256.ate(Q,P);
+			iterations++;
+			elapsed=(System.currentTimeMillis()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=(double)elapsed/iterations;
+		System.out.format("PAIRing ATE         - %8d iterations  ",iterations);
+		System.out.format(" %8.2f ms per iteration\n",dur);
+
+		iterations=0;
+		start=System.currentTimeMillis();
+		do {
+			g=PAIR256.fexp(w);
+			iterations++;
+			elapsed=(System.currentTimeMillis()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=(double)elapsed/iterations;
+		System.out.format("PAIRing FEXP        - %8d iterations  ",iterations);
+		System.out.format(" %8.2f ms per iteration\n",dur);
+
+		P.copy(G);
+		Q.copy(W);
+
+		P=PAIR256.G1mul(P,s);
+
+		g=PAIR256.ate(Q,P);
+		g=PAIR256.fexp(g);
+
+		P.copy(G);
+		Q=PAIR256.G2mul(Q,s);
+
+		w=PAIR256.ate(Q,P);
+		w=PAIR256.fexp(w);
+
+		if (!g.equals(w))
+		{
+			fail("FAILURE - e(sQ,p)!=e(Q,sP) ");
+		}
+
+		Q.copy(W);
+		g=PAIR256.ate(Q,P);
+		g=PAIR256.fexp(g);
+		g=PAIR256.GTpow(g,s);
+
+		if (!g.equals(w))
+		{
+			fail("FAILURE - e(sQ,p)!=e(Q,P)^s ");
+		}
+
+		System.out.print("All tests pass\n"); 
+	}
+
+}
diff --git a/version3/java/TesttimeRSA.java b/version3/java/TesttimeRSA.java
new file mode 100644
index 0000000..6762302
--- /dev/null
+++ b/version3/java/TesttimeRSA.java
@@ -0,0 +1,99 @@
+/*
+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.
+*/
+
+/* test driver and function exerciser for ECDH/ECIES/ECDSA API Functions */
+
+package org.apache.milagro.amcl.XXX;
+
+import java.util.Scanner;
+import junit.framework.TestCase;
+import org.apache.milagro.amcl.RAND;
+
+public class TesttimeRSA extends TestCase
+{   
+	public static final int MIN_TIME=10; /* seconds */
+	public static final int MIN_ITERS=10; 
+
+	public static void testtimeRSA()
+	{
+		byte[] RAW=new byte[100];
+		RAND rng=new RAND();
+		int i,iterations;
+		long start,elapsed;
+		double dur;
+		public_key pub=new public_key(FF.FFLEN);
+		private_key priv=new private_key(FF.HFLEN);
+
+		rng.clean();
+		for (i=0;i<100;i++) RAW[i]=(byte)(i);
+		rng.seed(100,RAW);
+
+		byte[] P=new byte[RSA.RFS];
+		byte[] M=new byte[RSA.RFS];
+		byte[] C=new byte[RSA.RFS];
+
+		System.out.println("Testing/Timing  RSA");
+		System.out.println("Generating RSA public/private key pair");
+
+		iterations=0;
+		start=System.currentTimeMillis();
+		do {
+			RSA.KEY_PAIR(rng,65537,priv,pub);
+			iterations++;
+			elapsed=(System.currentTimeMillis()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=(double)elapsed/iterations;
+		System.out.format("RSA gen - %8d iterations  ",iterations);
+		System.out.format(" %8.2f ms per iteration\n",dur);
+
+		for (i=0;i<RSA.RFS;i++) M[i]=(byte)(i%128);
+
+		iterations=0;
+		start=System.currentTimeMillis();
+		do {
+			RSA.ENCRYPT(pub,M,C);
+			iterations++;
+			elapsed=(System.currentTimeMillis()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=(double)elapsed/iterations;
+    	System.out.format("RSA enc - %8d iterations  ",iterations);
+    	System.out.format(" %8.2f ms per iteration\n",dur);
+
+		iterations=0;
+		start=System.currentTimeMillis();
+		do {
+			RSA.DECRYPT(priv,C,P);
+			iterations++;
+			elapsed=(System.currentTimeMillis()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=(double)elapsed/iterations;
+    	System.out.format("RSA dec - %8d iterations  ",iterations);
+    	System.out.format(" %8.2f ms per iteration\n",dur);
+
+		for (i=0;i<RSA.RFS;i++)
+		{
+			if (P[i]!=M[i])
+			{
+				fail("FAILURE - RSA decryption");
+			}
+		}
+
+		System.out.print("All tests pass\n");
+	}
+}
diff --git a/version3/java/config32.py b/version3/java/config32.py
new file mode 100644
index 0000000..160bb7f
--- /dev/null
+++ b/version3/java/config32.py
@@ -0,0 +1,387 @@
+import os
+import sys
+
+deltext=""
+slashtext=""
+copytext=""
+makedir=""
+org1text="org"
+org2text="apache"
+org3text="milagro"
+
+if sys.platform.startswith("linux")  :
+	copytext="cp "
+	deltext="rm "
+	slashtext="/"
+	makedir="mkdir -p "
+if sys.platform.startswith("win") :
+	copytext="copy "
+	deltext="del "
+	slashtext="\\"
+	makedir="md "
+
+amclpath = "amcl" + slashtext + "src" + slashtext + "main" + slashtext + "java" + slashtext + org1text + slashtext + org2text + slashtext + org3text +slashtext + "amcl"
+amclTestPath = "amcl" + slashtext + "src" + slashtext + "test" + slashtext + "java" + slashtext + org1text + slashtext + org2text + slashtext + org3text +slashtext + "amcl"
+chosen=[]
+cptr=0
+
+def replace(namefile,oldtext,newtext):
+	f = open(namefile,'r')
+	filedata = f.read()
+	f.close()
+
+	newdata = filedata.replace(oldtext,newtext)
+
+	f = open(namefile,'w')
+	f.write(newdata)
+	f.close()
+
+
+def rsaset(tb,nb,base,ml) :
+	global deltext,slashtext,copytext
+	global cptr,chosen
+
+	chosen.append(tb)
+	cptr=cptr+1
+
+	fpath=amclpath+slashtext+tb+slashtext
+	fpathTest=amclTestPath+slashtext+tb+slashtext  #ms
+	os.system(makedir+amclpath+slashtext+tb)
+	os.system(makedir+amclTestPath+slashtext+tb)  #ms
+
+	os.system(copytext+"BIG32.java "+fpath+"BIG.java")
+	os.system(copytext+"DBIG32.java "+fpath+"DBIG.java")
+	os.system(copytext+"FF32.java "+fpath+"FF.java")
+	os.system(copytext+"RSA.java "+fpath+"RSA.java")
+	os.system(copytext+"private_key.java "+fpath+"private_key.java")
+	os.system(copytext+"public_key.java "+fpath+"public_key.java")	
+	os.system(copytext+"TestRSA.java "+fpathTest+"TestRSA.java")	#ms
+	os.system(copytext+"TesttimeRSA.java "+fpathTest+"TesttimeRSA.java")	#ms
+	
+	replace(fpath+"BIG.java","XXX",tb)
+	replace(fpath+"DBIG.java","XXX",tb)
+	replace(fpath+"FF.java","XXX",tb)
+	replace(fpath+"RSA.java","XXX",tb)
+	replace(fpath+"private_key.java","XXX",tb)
+	replace(fpath+"public_key.java","XXX",tb)
+	replace(fpathTest+"TestRSA.java","XXX",tb)  #ms
+	replace(fpathTest+"TesttimeRSA.java","XXX",tb)  #ms
+
+	replace(fpath+"BIG.java","@NB@",nb)
+	replace(fpath+"BIG.java","@BASE@",base)
+
+	replace(fpath+"FF.java","@ML@",ml);
+
+
+def curveset(tc,nb,base,nbt,m8,mt,ct,pf,stw,sx,cs) :
+	global deltext,slashtext,copytext
+	global cptr,chosen
+
+	chosen.append(tc)
+	cptr=cptr+1
+
+	fpath=amclpath+slashtext+tc+slashtext
+	fpathTest=amclTestPath+slashtext+tc+slashtext  #ms
+	os.system(makedir+amclpath+slashtext+tc)
+	os.system(makedir+amclTestPath+slashtext+tc)  #ms
+
+	os.system(copytext+"BIG32.java "+fpath+"BIG.java")
+	os.system(copytext+"DBIG32.java "+fpath+"DBIG.java")
+	os.system(copytext+"FP32.java "+fpath+"FP.java")
+	os.system(copytext+"ECP.java "+fpath+"ECP.java")
+	os.system(copytext+"ECDH.java "+fpath+"ECDH.java")
+	os.system(copytext+"ROM_"+tc+"_32.java "+fpath+"ROM.java")
+	os.system(copytext+"TestECDH.java "+fpathTest+"TestECDH.java")	#ms
+	os.system(copytext+"TesttimeECDH.java "+fpathTest+"TesttimeECDH.java")	#ms
+
+	
+	replace(fpath+"BIG.java","XXX",tc)
+	replace(fpath+"DBIG.java","XXX",tc)
+	replace(fpath+"FP.java","XXX",tc)
+	replace(fpath+"ECP.java","XXX",tc)
+	replace(fpath+"ECDH.java","XXX",tc)
+	replace(fpathTest+"TestECDH.java","XXX",tc)  #ms
+	replace(fpathTest+"TesttimeECDH.java","XXX",tc)  #ms
+
+	replace(fpath+"BIG.java","@NB@",nb)
+	replace(fpath+"BIG.java","@BASE@",base)
+
+	replace(fpath+"FP.java","@NBT@",nbt)
+	replace(fpath+"FP.java","@M8@",m8)
+	replace(fpath+"FP.java","@MT@",mt)
+
+	ib=int(base)
+	inb=int(nb)
+	inbt=int(nbt)
+	sh=ib*(1+((8*inb-1)//ib))-inbt
+	if sh > 14 :
+		sh=14
+	replace(fpath+"FP.java","@SH@",str(sh))
+
+
+	replace(fpath+"ECP.java","@CT@",ct)
+	replace(fpath+"ECP.java","@PF@",pf)
+
+	replace(fpath+"ECP.java","@ST@",stw)
+	replace(fpath+"ECP.java","@SX@",sx)
+
+	if cs == "128" :
+		replace(fpath+"ECP.java","@HT@","32")
+		replace(fpath+"ECP.java","@AK@","16")
+	if cs == "192" :
+		replace(fpath+"ECP.java","@HT@","48")
+		replace(fpath+"ECP.java","@AK@","24")
+	if cs == "256" :
+		replace(fpath+"ECP.java","@HT@","64")
+		replace(fpath+"ECP.java","@AK@","32")
+
+	if pf != "NOT" :
+		os.system(copytext+"FP2.java "+fpath+"FP2.java")
+		os.system(copytext+"FP4.java "+fpath+"FP4.java")
+
+		replace(fpath+"FP2.java","XXX",tc)
+		replace(fpath+"FP4.java","XXX",tc)
+
+		if cs == "128" :
+
+			os.system(copytext+"ECP2.java "+fpath+"ECP2.java")
+			os.system(copytext+"FP12.java "+fpath+"FP12.java")
+			os.system(copytext+"PAIR.java "+fpath+"PAIR.java")
+			os.system(copytext+"MPIN.java "+fpath+"MPIN.java")
+			os.system(copytext+"TestMPIN.java "+fpathTest+"TestMPIN.java")	#ms
+			os.system(copytext+"TesttimeMPIN.java "+fpathTest+"TesttimeMPIN.java")	#ms
+
+			replace(fpath+"FP12.java","XXX",tc)
+			replace(fpath+"ECP2.java","XXX",tc)
+			replace(fpath+"PAIR.java","XXX",tc)
+			replace(fpath+"MPIN.java","XXX",tc)
+			replace(fpathTest+"TestMPIN.java","XXX",tc)  #ms
+			replace(fpathTest+"TesttimeMPIN.java","XXX",tc)  #ms
+
+		if cs == "192" :
+			os.system(copytext+"ECP4.java "+fpath+"ECP4.java")
+			os.system(copytext+"FP8.java "+fpath+"FP8.java")
+			os.system(copytext+"FP24.java "+fpath+"FP24.java")
+			os.system(copytext+"PAIR192.java "+fpath+"PAIR192.java")
+			os.system(copytext+"MPIN192.java "+fpath+"MPIN192.java")
+			os.system(copytext+"TestMPIN192.java "+fpathTest+"TestMPIN192.java")	#ms
+			os.system(copytext+"TesttimeMPIN192.java "+fpathTest+"TesttimeMPIN192.java")	#ms
+
+			replace(fpath+"FP8.java","XXX",tc)
+			replace(fpath+"FP24.java","XXX",tc)
+			replace(fpath+"ECP4.java","XXX",tc)
+			replace(fpath+"PAIR192.java","XXX",tc)
+			replace(fpath+"MPIN192.java","XXX",tc)
+			replace(fpathTest+"TestMPIN192.java","XXX",tc)  #ms
+			replace(fpathTest+"TesttimeMPIN192.java","XXX",tc)  #ms
+
+		if cs == "256" :
+			os.system(copytext+"FP8.java "+fpath+"FP8.java")
+			os.system(copytext+"ECP8.java "+fpath+"ECP8.java")
+			os.system(copytext+"FP16.java "+fpath+"FP16.java")
+			os.system(copytext+"FP48.java "+fpath+"FP48.java")
+			os.system(copytext+"PAIR256.java "+fpath+"PAIR256.java")
+			os.system(copytext+"MPIN256.java "+fpath+"MPIN256.java")
+			os.system(copytext+"TestMPIN256.java "+fpathTest+"TestMPIN256.java")	#ms
+			os.system(copytext+"TesttimeMPIN256.java "+fpathTest+"TesttimeMPIN256.java")	#ms
+
+			replace(fpath+"FP8.java","XXX",tc)
+			replace(fpath+"FP16.java","XXX",tc)
+			replace(fpath+"FP48.java","XXX",tc)
+			replace(fpath+"ECP8.java","XXX",tc)
+			replace(fpath+"PAIR256.java","XXX",tc)
+			replace(fpath+"MPIN256.java","XXX",tc)
+			replace(fpathTest+"TestMPIN256.java","XXX",tc)  #ms
+			replace(fpathTest+"TesttimeMPIN256.java","XXX",tc)  #ms
+
+
+os.system(makedir + amclpath)
+
+os.system(copytext + "pom.xml " + "amcl" + slashtext + ".")
+for file in ['HASH*.java', 'SHA3.java', 'RAND.java', 'AES.java', 'GCM.java', 'NHS.java']:
+	os.system(copytext + file + " " + amclpath+slashtext+".")
+
+print("Elliptic Curves")
+print("1. ED25519")
+print("2. C25519")
+print("3. NIST256")
+print("4. BRAINPOOL")
+print("5. ANSSI")
+print("6. HIFIVE")
+print("7. GOLDILOCKS")
+print("8. NIST384")
+print("9. C41417")
+print("10. NIST521\n")
+print("11. NUMS256W")
+print("12. NUMS256E")
+print("13. NUMS384W")
+print("14. NUMS384E")
+print("15. NUMS512W")
+print("16. NUMS512E")
+print("17. SECP256K1\n")
+
+
+print("Pairing-Friendly Elliptic Curves")
+print("18. BN254")
+print("19. BN254CX")
+print("20. BLS383")
+print("21. BLS381")
+print("22. FP256BN")
+print("23. FP512BN")
+print("24. BLS461\n")
+
+print("25. BLS24")
+print("26. BLS48\n")
+
+print("RSA")
+print("27. RSA2048")
+print("28. RSA3072")
+print("29. RSA4096")
+
+selection=[]
+ptr=0
+max=30
+
+curve_selected=False
+pfcurve_selected=False
+rsa_selected=False
+
+while ptr<max:
+	x=int(input("Choose a Scheme to support - 0 to finish: "))
+	if x == 0:
+		break
+#	print("Choice= ",x)
+	already=False
+	for i in range(0,ptr):
+		if x==selection[i]:
+			already=True
+			break
+	if already:
+		continue
+	
+	selection.append(x)
+	ptr=ptr+1
+
+# curveset(curve,big_length_bytes,bits_in_base,modulus_bits,modulus_mod_8,modulus_type,curve_type,pairing_friendly,sextic twist,sign of x,curve security)
+# where "curve" is the common name for the elliptic curve   
+# big_length_bytes is the modulus size rounded up to a number of bytes
+# bits_in_base gives the number base used for 32 bit architectures, as n where the base is 2^n
+# modulus_bits is the actual bit length of the modulus.
+# modulus_mod_8 is the remainder when the modulus is divided by 8
+# modulus_type is NOT_SPECIAL, or PSEUDO_MERSENNE, or MONTGOMERY_Friendly, or GENERALISED_MERSENNE (supported for GOLDILOCKS only)
+# curve_type is WEIERSTRASS, EDWARDS or MONTGOMERY
+# pairing_friendly is BN, BLS or NOT (if not pairing friendly)
+# if pairing friendly. M or D type twist, and sign of the family parameter x
+# curve security is AES equiavlent, rounded up.
+
+
+	if x==1:
+		curveset("ED25519","32","29","255","5","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==2:
+		curveset("C25519","32","29","255","5","PSEUDO_MERSENNE","MONTGOMERY","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==3:
+		curveset("NIST256","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")   # Change to 28
+		curve_selected=True
+	if x==4:
+		curveset("BRAINPOOL","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128") # Change to 28
+		curve_selected=True
+	if x==5:
+		curveset("ANSSI","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128") # Change to 28
+		curve_selected=True
+
+	if x==6:
+		curveset("HIFIVE","42","29","336","5","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","192")
+		curve_selected=True
+	if x==7:
+		curveset("GOLDILOCKS","56","29","448","7","GENERALISED_MERSENNE","EDWARDS","NOT","NOT","NOT","256")
+		curve_selected=True
+	if x==8:
+		curveset("NIST384","48","29","384","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","192")  # change to 29
+		curve_selected=True
+	if x==9:
+		curveset("C41417","52","29","414","7","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","256")
+		curve_selected=True
+	if x==10:
+		curveset("NIST521","66","28","521","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","256")
+		curve_selected=True
+
+	if x==11:
+		curveset("NUMS256W","32","28","256","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==12:
+		curveset("NUMS256E","32","29","256","3","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==13:
+		curveset("NUMS384W","48","29","384","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","192")
+		curve_selected=True
+	if x==14:
+		curveset("NUMS384E","48","29","384","3","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","192")
+		curve_selected=True
+	if x==15:
+		curveset("NUMS512W","64","29","512","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","256")
+		curve_selected=True
+	if x==16:
+		curveset("NUMS512E","64","29","512","7","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","256")
+		curve_selected=True
+	if x==17:
+		curveset("SECP256K1","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")   # Change to 28
+		curve_selected=True
+
+	if x==18:
+		curveset("BN254","32","28","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")  
+		pfcurve_selected=True
+	if x==19:
+		curveset("BN254CX","32","28","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")  
+		pfcurve_selected=True
+	if x==20:
+		curveset("BLS383","48","29","383","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","128") 
+		pfcurve_selected=True
+
+	if x==21:
+		curveset("BLS381","48","29","381","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128") 
+		pfcurve_selected=True
+
+
+	if x==22:
+		curveset("FP256BN","32","28","256","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","NEGATIVEX","128") 
+		pfcurve_selected=True
+	if x==23:
+		curveset("FP512BN","64","29","512","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","POSITIVEX","128")
+		pfcurve_selected=True
+# https://eprint.iacr.org/2017/334.pdf
+	if x==24:
+		curveset("BLS461","58","28","461","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+
+
+	if x==25:
+		curveset("BLS24","60","29","479","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","192")
+		pfcurve_selected=True
+	if x==26:
+		curveset("BLS48","70","29","556","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","256")
+		pfcurve_selected=True
+
+
+
+# rsaset(rsaname,big_length_bytes,bits_in_base,multiplier)
+# The RSA name reflects the modulus size, which is a 2^m multiplier
+# of the underlying big length
+
+# There are choices here, different ways of getting the same result, but some faster than others
+	if x==27:
+		#256 is slower but may allow reuse of 256-bit BIGs used for elliptic curve
+		#512 is faster.. but best is 1024
+		rsaset("RSA2048","128","28","2")
+		#rsaset("RSA2048","64","29","4")
+		#rsaset("RSA2048","32","29","8")
+		rsa_selected=True
+	if x==28:
+		rsaset("RSA3072","48","28","8")
+		rsa_selected=True
+	if x==29:
+		#rsaset("RSA4096","32","29","16")
+		rsaset("RSA4096","64","29","8")
+		rsa_selected=True
+
diff --git a/version3/java/config64.py b/version3/java/config64.py
new file mode 100644
index 0000000..6d73137
--- /dev/null
+++ b/version3/java/config64.py
@@ -0,0 +1,386 @@
+import os
+import sys
+
+deltext=""
+slashtext=""
+copytext=""
+makedir=""
+org1text="org"
+org2text="apache"
+org3text="milagro"
+
+if sys.platform.startswith("linux")  :
+	copytext="cp "
+	deltext="rm "
+	slashtext="/"
+	makedir="mkdir -p "
+if sys.platform.startswith("win") :
+	copytext="copy "
+	deltext="del "
+	slashtext="\\"
+	makedir="md "
+
+amclpath = "amcl" + slashtext + "src" + slashtext + "main" + slashtext + "java" + slashtext + org1text + slashtext + org2text + slashtext + org3text +slashtext + "amcl"
+amclTestPath = "amcl" + slashtext + "src" + slashtext + "test" + slashtext + "java" + slashtext + org1text + slashtext + org2text + slashtext + org3text +slashtext + "amcl"
+chosen=[]
+cptr=0
+
+def replace(namefile,oldtext,newtext):
+	f = open(namefile,'r')
+	filedata = f.read()
+	f.close()
+
+	newdata = filedata.replace(oldtext,newtext)
+
+	f = open(namefile,'w')
+	f.write(newdata)
+	f.close()
+
+
+def rsaset(tb,nb,base,ml) :
+	global deltext,slashtext,copytext
+	global cptr,chosen
+
+	chosen.append(tb)
+	cptr=cptr+1
+
+	fpath=amclpath+slashtext+tb+slashtext
+	fpathTest=amclTestPath+slashtext+tb+slashtext #ms
+	os.system(makedir+amclpath+slashtext+tb)
+	os.system(makedir+amclTestPath+slashtext+tb) #ms
+	
+	os.system(copytext+"BIG64.java "+fpath+"BIG.java")
+	os.system(copytext+"DBIG64.java "+fpath+"DBIG.java")
+	os.system(copytext+"FF64.java "+fpath+"FF.java")
+	os.system(copytext+"RSA.java "+fpath+"RSA.java")
+	os.system(copytext+"private_key.java "+fpath+"private_key.java")
+	os.system(copytext+"public_key.java "+fpath+"public_key.java")	
+	os.system(copytext+"TestRSA.java "+fpathTest+"TestRSA.java") #ms
+	os.system(copytext+"TesttimeRSA.java "+fpathTest+"TesttimeRSA.java")	#ms
+
+	replace(fpath+"BIG.java","XXX",tb)
+	replace(fpath+"DBIG.java","XXX",tb)
+	replace(fpath+"FF.java","XXX",tb)
+	replace(fpath+"RSA.java","XXX",tb)
+	replace(fpath+"private_key.java","XXX",tb)
+	replace(fpath+"public_key.java","XXX",tb)
+	replace(fpathTest+"TestRSA.java","XXX",tb)  #ms
+	replace(fpathTest+"TesttimeRSA.java","XXX",tb)  #ms
+
+
+	replace(fpath+"BIG.java","@NB@",nb)
+	replace(fpath+"BIG.java","@BASE@",base)
+
+	replace(fpath+"FF.java","@ML@",ml);
+
+
+def curveset(tc,nb,base,nbt,m8,mt,ct,pf,stw,sx,cs) :
+	global deltext,slashtext,copytext
+	global cptr,chosen
+
+	chosen.append(tc)
+	cptr=cptr+1
+
+	fpath=amclpath+slashtext+tc+slashtext
+	fpathTest=amclTestPath+slashtext+tc+slashtext  #ms
+	os.system(makedir+amclpath+slashtext+tc)
+	os.system(makedir+amclTestPath+slashtext+tc)  #ms
+
+	os.system(copytext+"BIG64.java "+fpath+"BIG.java")
+	os.system(copytext+"DBIG64.java "+fpath+"DBIG.java")
+	os.system(copytext+"FP64.java "+fpath+"FP.java")
+	os.system(copytext+"ECP.java "+fpath+"ECP.java")
+	os.system(copytext+"ECDH.java "+fpath+"ECDH.java")
+	os.system(copytext+"ROM_"+tc+"_64.java "+fpath+"ROM.java")
+	os.system(copytext+"TestECDH.java "+fpathTest+"TestECDH.java")	#ms
+	os.system(copytext+"TesttimeECDH.java "+fpathTest+"TesttimeECDH.java")	#ms
+	
+	replace(fpath+"BIG.java","XXX",tc)
+	replace(fpath+"DBIG.java","XXX",tc)
+	replace(fpath+"FP.java","XXX",tc)
+	replace(fpath+"ECP.java","XXX",tc)
+	replace(fpath+"ECDH.java","XXX",tc)
+	replace(fpathTest+"TestECDH.java","XXX",tc)  #ms
+	replace(fpathTest+"TesttimeECDH.java","XXX",tc)  #ms
+
+	replace(fpath+"BIG.java","@NB@",nb)
+	replace(fpath+"BIG.java","@BASE@",base)
+
+	replace(fpath+"FP.java","@NBT@",nbt)
+	replace(fpath+"FP.java","@M8@",m8)
+	replace(fpath+"FP.java","@MT@",mt)
+
+	ib=int(base)
+	inb=int(nb)
+	inbt=int(nbt)
+	sh=ib*(1+((8*inb-1)//ib))-inbt
+	if sh > 30 :
+		sh=30
+	replace(fpath+"FP.java","@SH@",str(sh))
+
+
+	replace(fpath+"ECP.java","@CT@",ct)
+	replace(fpath+"ECP.java","@PF@",pf)
+	replace(fpath+"ECP.java","@ST@",stw)
+	replace(fpath+"ECP.java","@SX@",sx)
+
+	if cs == "128" :
+		replace(fpath+"ECP.java","@HT@","32")
+		replace(fpath+"ECP.java","@AK@","16")
+	if cs == "192" :
+		replace(fpath+"ECP.java","@HT@","48")
+		replace(fpath+"ECP.java","@AK@","24")
+	if cs == "256" :
+		replace(fpath+"ECP.java","@HT@","64")
+		replace(fpath+"ECP.java","@AK@","32")
+
+	if pf != "NOT" :
+		os.system(copytext+"FP2.java "+fpath+"FP2.java")
+		os.system(copytext+"FP4.java "+fpath+"FP4.java")
+
+		replace(fpath+"FP2.java","XXX",tc)
+		replace(fpath+"FP4.java","XXX",tc)
+
+		if cs == "128" :
+
+			os.system(copytext+"ECP2.java "+fpath+"ECP2.java")
+			os.system(copytext+"FP12.java "+fpath+"FP12.java")
+			os.system(copytext+"PAIR.java "+fpath+"PAIR.java")
+			os.system(copytext+"MPIN.java "+fpath+"MPIN.java")
+			os.system(copytext+"TestMPIN.java "+fpathTest+"TestMPIN.java")	#ms
+			os.system(copytext+"TesttimeMPIN.java "+fpathTest+"TesttimeMPIN.java")	#ms
+
+			replace(fpath+"FP12.java","XXX",tc)
+			replace(fpath+"ECP2.java","XXX",tc)
+			replace(fpath+"PAIR.java","XXX",tc)
+			replace(fpath+"MPIN.java","XXX",tc)
+			replace(fpathTest+"TestMPIN.java","XXX",tc)  #ms
+			replace(fpathTest+"TesttimeMPIN.java","XXX",tc)  #ms
+
+		if cs == "192" :
+			os.system(copytext+"ECP4.java "+fpath+"ECP4.java")
+			os.system(copytext+"FP8.java "+fpath+"FP8.java")
+			os.system(copytext+"FP24.java "+fpath+"FP24.java")
+			os.system(copytext+"PAIR192.java "+fpath+"PAIR192.java")
+			os.system(copytext+"MPIN192.java "+fpath+"MPIN192.java")
+			os.system(copytext+"TestMPIN192.java "+fpathTest+"TestMPIN192.java")	#ms
+			os.system(copytext+"TesttimeMPIN192.java "+fpathTest+"TesttimeMPIN192.java")	#ms
+
+			replace(fpath+"FP8.java","XXX",tc)
+			replace(fpath+"FP24.java","XXX",tc)
+			replace(fpath+"ECP4.java","XXX",tc)
+			replace(fpath+"PAIR192.java","XXX",tc)
+			replace(fpath+"MPIN192.java","XXX",tc)
+			replace(fpathTest+"TestMPIN192.java","XXX",tc)  #ms
+			replace(fpathTest+"TesttimeMPIN192.java","XXX",tc)  #ms
+
+		if cs == "256" :
+			os.system(copytext+"FP8.java "+fpath+"FP8.java")
+			os.system(copytext+"ECP8.java "+fpath+"ECP8.java")
+			os.system(copytext+"FP16.java "+fpath+"FP16.java")
+			os.system(copytext+"FP48.java "+fpath+"FP48.java")
+			os.system(copytext+"PAIR256.java "+fpath+"PAIR256.java")
+			os.system(copytext+"MPIN256.java "+fpath+"MPIN256.java")
+			os.system(copytext+"TestMPIN256.java "+fpathTest+"TestMPIN256.java")	#ms
+			os.system(copytext+"TesttimeMPIN256.java "+fpathTest+"TesttimeMPIN256.java")	#ms
+
+			replace(fpath+"FP8.java","XXX",tc)
+			replace(fpath+"FP16.java","XXX",tc)
+			replace(fpath+"FP48.java","XXX",tc)
+			replace(fpath+"ECP8.java","XXX",tc)
+			replace(fpath+"PAIR256.java","XXX",tc)
+			replace(fpath+"MPIN256.java","XXX",tc)
+			replace(fpathTest+"TestMPIN256.java","XXX",tc)  #ms
+			replace(fpathTest+"TesttimeMPIN256.java","XXX",tc)  #ms
+
+
+
+os.system(makedir + amclpath)
+
+os.system(copytext + "pom.xml " + "amcl" + slashtext + ".")
+for file in ['HASH*.java', 'SHA3.java', 'RAND.java', 'AES.java', 'GCM.java', 'NHS.java']:
+	os.system(copytext + file + " " + amclpath+slashtext+".")
+
+print("Elliptic Curves")
+print("1. ED25519")
+print("2. C25519")
+print("3. NIST256")
+print("4. BRAINPOOL")
+print("5. ANSSI")
+print("6. HIFIVE")
+print("7. GOLDILOCKS")
+print("8. NIST384")
+print("9. C41417")
+print("10. NIST521\n")
+print("11. NUMS256W")
+print("12. NUMS256E")
+print("13. NUMS384W")
+print("14. NUMS384E")
+print("15. NUMS512W")
+print("16. NUMS512E")
+print("17. SECP256K1\n")
+
+
+print("Pairing-Friendly Elliptic Curves")
+print("18. BN254")
+print("19. BN254CX")
+print("20. BLS383")
+print("21. BLS381")
+print("22. FP256BN")
+print("23. FP512BN")
+print("24. BLS461\n")
+
+print("25. BLS24")
+print("26. BLS48\n")
+
+print("RSA")
+print("27. RSA2048")
+print("28. RSA3072")
+print("29. RSA4096")
+
+selection=[]
+ptr=0
+max=30
+
+curve_selected=False
+pfcurve_selected=False
+rsa_selected=False
+
+while ptr<max:
+	x=int(input("Choose a Scheme to support - 0 to finish: "))
+	if x == 0:
+		break
+#	print("Choice= ",x)
+	already=False
+	for i in range(0,ptr):
+		if x==selection[i]:
+			already=True
+			break
+	if already:
+		continue
+	
+	selection.append(x)
+	ptr=ptr+1
+
+# curveset(curve,big_length_bytes,bits_in_base,modulus_bits,modulus_mod_8,modulus_type,curve_type,pairing_friendly,sextic twist,sign of x,curve security)
+# where "curve" is the common name for the elliptic curve   
+# big_length_bytes is the modulus size rounded up to a number of bytes
+# bits_in_base gives the number base used for 64 bit architectures, as n where the base is 2^n
+# modulus_bits is the actual bit length of the modulus.
+# modulus_mod_8 is the remainder when the modulus is divided by 8
+# modulus_type is NOT_SPECIAL, or PSEUDO_MERSENNE, or MONTGOMERY_Friendly, or GENERALISED_MERSENNE (supported for GOLDILOCKS only)
+# curve_type is WEIERSTRASS, EDWARDS or MONTGOMERY
+# pairing_friendly is BN, BLS or NOT (if not pairing friendly)
+# if pairing friendly. M or D type twist, and sign of the family parameter x
+# curve security is AES equiavlent, rounded up.
+
+
+	if x==1:
+		curveset("ED25519","32","56","255","5","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==2:
+		curveset("C25519","32","56","255","5","PSEUDO_MERSENNE","MONTGOMERY","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==3:
+		curveset("NIST256","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==4:
+		curveset("BRAINPOOL","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==5:
+		curveset("ANSSI","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+		curve_selected=True
+
+	if x==6:
+		curveset("HIFIVE","42","60","336","5","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","192")
+		curve_selected=True
+	if x==7:
+		curveset("GOLDILOCKS","56","58","448","7","GENERALISED_MERSENNE","EDWARDS","NOT","NOT","NOT","256")   # change to 58
+		curve_selected=True
+	if x==8:
+		curveset("NIST384","48","56","384","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","192")
+		curve_selected=True
+	if x==9:
+		curveset("C41417","52","60","414","7","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","256")
+		curve_selected=True
+	if x==10:
+		curveset("NIST521","66","60","521","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","256")
+		curve_selected=True
+
+	if x==11:
+		curveset("NUMS256W","32","56","256","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==12:
+		curveset("NUMS256E","32","56","256","3","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==13:
+		curveset("NUMS384W","48","58","384","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","192")
+		curve_selected=True
+	if x==14:
+		curveset("NUMS384E","48","56","384","3","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","192")
+		curve_selected=True
+	if x==15:
+		curveset("NUMS512W","64","60","512","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","256")
+		curve_selected=True
+	if x==16:
+		curveset("NUMS512E","64","56","512","7","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","256")
+		curve_selected=True
+	if x==17:
+		curveset("SECP256K1","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+		curve_selected=True
+
+	if x==18:
+		curveset("BN254","32","56","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+	if x==19:
+		curveset("BN254CX","32","56","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+	if x==20:
+		curveset("BLS383","48","58","383","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","128")  # change to 58
+		pfcurve_selected=True
+
+	if x==21:
+		curveset("BLS381","48","58","381","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128")  # change to 58
+		pfcurve_selected=True
+
+	if x==22:
+		curveset("FP256BN","32","56","256","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","NEGATIVEX","128")  
+		pfcurve_selected=True
+	if x==23:
+		curveset("FP512BN","64","60","512","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","POSITIVEX","128")
+		pfcurve_selected=True
+# https://eprint.iacr.org/2017/334.pdf
+	if x==24:
+		curveset("BLS461","58","60","461","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+
+	if x==25:
+		curveset("BLS24","60","56","479","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","192")
+		pfcurve_selected=True
+
+	if x==26:
+		curveset("BLS48","70","58","556","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","256")
+		pfcurve_selected=True
+
+
+# rsaset(rsaname,big_length_bytes,bits_in_base,multiplier)
+# The RSA name reflects the modulus size, which is a 2^m multiplier
+# of the underlying big length
+
+# There are choices here, different ways of getting the same result, but some faster than others
+	if x==27:
+		#256 is slower but may allow reuse of 256-bit BIGs used for elliptic curve
+		#512 is faster.. but best is 1024
+		rsaset("RSA2048","128","58","2")
+		#rsaset("RSA2048","64","60","4")
+		#rsaset("RSA2048","32","56","8")
+		rsa_selected=True
+	if x==28:
+		rsaset("RSA3072","48","56","8")
+		rsa_selected=True
+	if x==29:
+		#rsaset("RSA4096","32","56","16")
+		rsaset("RSA4096","64","60","8")
+		rsa_selected=True
+
+
diff --git a/version3/java/pom.xml b/version3/java/pom.xml
new file mode 100644
index 0000000..77d2905
--- /dev/null
+++ b/version3/java/pom.xml
@@ -0,0 +1,19 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+	<groupId>org.apache.milagro</groupId>
+	<artifactId>amcl</artifactId>
+	<version>3.2-SNAPSHOT</version>
+	<dependencies>
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>3.8.1</version>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
+<properties>
+<maven.compiler.source>1.6</maven.compiler.source>
+<maven.compiler.target>1.6</maven.compiler.target>
+ </properties>
+</project>
diff --git a/version3/java/private_key.java b/version3/java/private_key.java
new file mode 100644
index 0000000..c6bcc55
--- /dev/null
+++ b/version3/java/private_key.java
@@ -0,0 +1,16 @@
+
+package org.apache.milagro.amcl.XXX;
+
+public final class private_key
+{
+    public FF p,q,dp,dq,c;
+	
+	public private_key(int n)
+	{
+		p=new FF(n);
+		q=new FF(n);
+		dp=new FF(n);
+		dq=new FF(n);
+		c=new FF(n);
+	}
+}
\ No newline at end of file
diff --git a/version3/java/public_key.java b/version3/java/public_key.java
new file mode 100644
index 0000000..75fc695
--- /dev/null
+++ b/version3/java/public_key.java
@@ -0,0 +1,14 @@
+
+package org.apache.milagro.amcl.XXX;
+
+public final class public_key
+{
+    public int e;
+    public FF n;
+
+	public public_key(int m)
+	{
+		e=0;
+		n=new FF(m);
+	}
+}
diff --git a/version3/js/BenchtestALL.html b/version3/js/BenchtestALL.html
new file mode 100644
index 0000000..4dc3cd3
--- /dev/null
+++ b/version3/js/BenchtestALL.html
@@ -0,0 +1,1076 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>JavaScript AMCL Benchtest</title>
+</head>
+<body>
+<h1>JavaScript Benchmarks - each takes a few seconds to complete</h1>
+
+<script type="text/javascript" src=./rand.js></script>
+<script type="text/javascript" src=./rom_curve.js></script>
+<script type="text/javascript" src=./rom_field.js></script>
+<script type="text/javascript" src=./uint64.js></script>
+<script type="text/javascript" src=./aes.js></script>
+<script type="text/javascript" src=./big.js></script>
+<script type="text/javascript" src=./gcm.js></script>
+<script type="text/javascript" src=./hash256.js></script>
+<script type="text/javascript" src=./hash384.js></script>
+<script type="text/javascript" src=./hash512.js></script>
+<script type="text/javascript" src=./sha3.js></script>
+<script type="text/javascript" src=./nhs.js></script>
+<script type="text/javascript" src=./fp.js></script>
+<script type="text/javascript" src=./fp2.js></script>
+<script type="text/javascript" src=./fp4.js></script>
+<script type="text/javascript" src=./fp12.js></script>
+<script type="text/javascript" src=./ff.js></script>
+<script type="text/javascript" src=./rsa.js></script>
+<script type="text/javascript" src=./ecp.js></script>
+<script type="text/javascript" src=./ecp2.js></script>
+<script type="text/javascript" src=./ecdh.js></script>
+<script type="text/javascript" src=./pair.js></script>
+<script type="text/javascript" src=./mpin.js></script>
+<script type="text/javascript" src=./ctx.js></script>
+
+<script type="text/javascript" src=./fp8.js></script>
+<script type="text/javascript" src=./fp16.js></script>
+<script type="text/javascript" src=./fp24.js></script>
+<script type="text/javascript" src=./fp48.js></script>
+<script type="text/javascript" src=./ecp4.js></script>
+<script type="text/javascript" src=./ecp8.js></script>
+<script type="text/javascript" src=./pair192.js></script>
+<script type="text/javascript" src=./pair256.js></script>
+<script type="text/javascript" src=./mpin192.js></script>
+<script type="text/javascript" src=./mpin256.js></script>
+
+<p><a id="myLink1" href="#" onclick="location.reload(false);ed25519();">ED25519 255-bit Edwards Elliptic Curve</a></p>
+<p><a id="myLink2" href="#" onclick="location.reload(false);nist256();">NIST256 256-bit Weierstrass Elliptic Curve</a></p>
+<p><a id="myLink3" href="#" onclick="location.reload(false);goldilocks();">GOLDILOCKS 448-bit Edwards Elliptic Curve</a></p>
+<p><a id="myLink4" href="#" onclick="location.reload(false);bn254();">BN254 254-bit k=12 Pairing-Friendly BN Curve</a></p>
+<p><a id="myLink5" href="#" onclick="location.reload(false);bls383();">BLS383 383-bit k=12 Pairing-Friendly BLS Curve</a></p>
+<p><a id="myLink6" href="#" onclick="location.reload(false);bls24();">BLS24 479-bit k=24 Pairing-Friendly BLS Curve</a></p>
+<p><a id="myLink7" href="#" onclick="location.reload(false);bls48();">BLS48 556-bit k=48 Pairing-Friendly BLS Curve</a></p>
+<p><a id="myLink8" href="#" onclick="location.reload(false);rsa2048();">RSA2048 2048-bit RSA Method</a></p>
+
+
+<script>
+/* test driver and function exerciser ECC functions */
+
+// NOTE: In the above the location.reload(false) is required as modified JS code must be reloaded before setting a new context
+// otherwise the optimizer may bail out on subsequent calls (it doesn't like it when code is modified at runtime).
+
+// ED25519 context
+	function ed25519() {
+		var ctx = new CTX('ED25519');
+		var i,j;
+		var result;
+		var MIN_ITERS=5;
+		var MIN_TIME=3;
+		var fail=false;
+		var RAW=[];
+
+		var rng=new ctx.RAND();
+
+		rng.clean();
+		for (i=0;i<100;i++) RAW[i]=i;
+
+		rng.seed(100,RAW);
+
+		mywindow=window.open();
+
+		mywindow.document.write("<br> Curve ED25519"+ "<br>");
+		if (ctx.ECP.CURVETYPE==ctx.ECP.WEIERSTRASS)
+		{
+			mywindow.document.write("Weierstrass parameterization "+ "<br>");
+		}		
+		if (ctx.ECP.CURVETYPE==ctx.ECP.EDWARDS)
+		{
+			mywindow.document.write("Edwards parameterization"+ "<br>");
+		}
+		if (ctx.ECP.CURVETYPE==ctx.ECP.MONTGOMERY)
+		{
+			mywindow.document.write("Montgomery parameterization"+ "<br>");
+		}
+
+		if (ctx.FP.MODTYPE==ctx.FP.PSEUDO_MERSENNE)
+		{
+			mywindow.document.write("Pseudo-Mersenne Modulus"+ "<br>");
+		}
+		if (ctx.FP.MODTYPE==ctx.FP.MONTGOMERY_FRIENDLY)
+		{
+			mywindow.document.write("Montgomery friendly Modulus"+ "<br>");
+		}
+		if (ctx.FP.MODTYPE==ctx.FP.GENERALISED_MERSENNE)
+		{
+			mywindow.document.write("Generalised-Mersenne Modulus"+ "<br>");
+		}
+		if (ctx.FP.MODTYPE==ctx.FP.NOT_SPECIAL)
+		{
+			mywindow.document.write("Not special Modulus"+ "<br>");
+		}
+
+		mywindow.document.write("Modulus size "+ctx.FP.MODBITS+ " bits"+ "<br>"); 
+
+		var r,gx,gy,s;
+		var G,WP;
+		var res=0;
+
+		G=ctx.ECP.generator();
+
+		r=new ctx.BIG(0); r.rcopy(ctx.ROM_CURVE.CURVE_Order);
+		s=ctx.BIG.randomnum(r,rng);
+			
+		WP=G.mul(r);
+		if (!WP.is_infinity())
+		{
+			alert("FAILURE - rG!=O");
+			fail=true;
+		}
+		var elapsed;
+		var start = performance.now();
+		var iterations=0;
+		do {
+			WP=G.mul(s);
+			iterations++;
+			elapsed=(performance.now()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=elapsed/iterations;
+		mywindow.document.write("EC  mul - " + iterations + " iterations  ");
+		mywindow.document.write(dur.toFixed(2) + " ms per iteration"+ "<br>");
+			
+	}
+
+// BLS383 context
+
+	function bls383() {
+		var ctx = new CTX('BLS383');
+		var i;
+		var result;
+		var MIN_ITERS=5;
+		var MIN_TIME=3;
+		var G;
+		var Q;
+		var RAW=[];
+
+		var rng=new ctx.RAND();
+
+		rng.clean();
+		for (i=0;i<100;i++) RAW[i]=i;
+
+		rng.seed(100,RAW);
+
+		mywindow=window.open();
+
+		mywindow.document.write("<br> Curve BLS383"+ "<br>");
+		if (ctx.ECP.CURVE_PAIRING_TYPE==ctx.ECP.BN)
+		{
+			mywindow.document.write("BN Pairing-Friendly Curve"+ "<br>");
+		}
+		if (ctx.ECP.CURVE_PAIRING_TYPE==ctx.ECP.BLS)
+		{
+			mywindow.document.write("BLS Pairing-Friendly Curve"+ "<br>");
+		}
+
+		mywindow.document.write("Modulus size " + ctx.FP.MODBITS + " bits"+ "<br>"); 
+
+		G=ctx.ECP.generator();
+
+		r=new ctx.BIG(0); r.rcopy(ctx.ROM_CURVE.CURVE_Order);
+		s=ctx.BIG.randomnum(r,rng);
+
+		var P=ctx.PAIR.G1mul(G,r);
+
+		if (!P.is_infinity())
+		{
+			alert("FAILURE - rP!=O");
+			fail=true;
+		}	
+
+		var elapsed;
+		var start = performance.now();
+		var iterations=0;
+		do {
+			P=ctx.PAIR.G1mul(G,s);
+			iterations++;
+			elapsed=(performance.now()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=elapsed/iterations;
+		mywindow.document.write("G1 mul -                " + iterations + " iterations  ");
+		mywindow.document.write(dur.toFixed(2) + " ms per iteration"+ "<br>");
+
+		Q=ctx.ECP2.generator();
+		W=ctx.PAIR.G2mul(Q,r);
+
+		if (!W.is_infinity())
+		{
+			alert("FAILURE - rQ!=O");
+			fail=true;
+		}
+
+		start = performance.now();
+		iterations=0;
+		do {
+			W=ctx.PAIR.G2mul(Q,s);
+			iterations++;
+			elapsed=(performance.now()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=elapsed/iterations;
+		mywindow.document.write("G2 mul -                " + iterations + " iteration  ");
+		mywindow.document.write(dur.toFixed(2) + " ms per iteration"+ "<br>");
+
+		var w=ctx.PAIR.ate(Q,P);
+		w=ctx.PAIR.fexp(w);
+
+		var g=ctx.PAIR.GTpow(w,r);
+
+		if (!g.isunity())
+		{
+			alert("FAILURE - g^r!=1");
+			fail=true;
+		}
+
+		start = performance.now();
+		iterations=0;
+		do {
+			g=ctx.PAIR.GTpow(w,s);
+			iterations++;
+			elapsed=(performance.now()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=elapsed/iterations;
+		mywindow.document.write("GT pow -                " + iterations + " iteration  ");
+		mywindow.document.write(dur.toFixed(2) + " ms per iteration"+ "<br>");
+
+
+		var cr;
+		start = performance.now();
+		iterations=0;
+		do {
+			cr=w.compow(s,r); 
+			iterations++;
+			elapsed=(performance.now()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=elapsed/iterations;
+		mywindow.document.write("GT pow (compressed) -   " + iterations + " iteration  ");
+		mywindow.document.write(dur.toFixed(2) + " ms per iteration"+ "<br>");
+
+		start = performance.now();
+		iterations=0;
+		do {
+			w=ctx.PAIR.ate(Q,P);
+			iterations++;
+			elapsed=(performance.now()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=elapsed/iterations;
+		mywindow.document.write("PAIRing ATE   -         " + iterations + " iteration  ");
+		mywindow.document.write(dur.toFixed(2) + " ms per iteration"+ "<br>");
+
+		start = performance.now();
+		iterations=0;
+		do {
+			g=ctx.PAIR.fexp(w);
+			iterations++;
+			elapsed=(performance.now()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=elapsed/iterations;
+		mywindow.document.write("PAIRing FEXP -          " + iterations + " iteration  ");
+		mywindow.document.write(dur.toFixed(2) + " ms per iteration"+ "<br>");
+
+		P.copy(G);
+		Q.copy(W);
+
+		P=ctx.PAIR.G1mul(P,s);
+		g=ctx.PAIR.ate(Q,P);
+		g=ctx.PAIR.fexp(g);
+
+		P.copy(G);
+		Q=ctx.PAIR.G2mul(Q,s);
+		w=ctx.PAIR.ate(Q,P);
+		w=ctx.PAIR.fexp(w);
+
+		if (!g.equals(w))
+		{
+			alert("FAILURE - e(sQ,p)!=e(Q,sP)");
+			fail=true;
+		}
+
+		Q.copy(W);
+		g=ctx.PAIR.ate(Q,P);
+		g=ctx.PAIR.fexp(g);
+		g=ctx.PAIR.GTpow(g,s);
+
+		if (!g.equals(w))
+		{
+			alert("FAILURE - e(sQ,p)!=e(Q,P)^s");
+			fail=true;
+		}
+
+	}
+
+// NIST256 context
+	function nist256() {
+
+		var ctx = new CTX('NIST256');
+		var i,j;
+		var result;
+		var MIN_ITERS=5;
+		var MIN_TIME=3;
+		var fail=false;
+		var RAW=[];
+
+		var rng=new ctx.RAND();
+
+		rng.clean();
+		for (i=0;i<100;i++) RAW[i]=i;
+
+		rng.seed(100,RAW);
+
+		mywindow=window.open();
+
+		mywindow.document.write("<br> Curve NIST256"+ "<br>");
+		if (ctx.ECP.CURVETYPE==ctx.ECP.WEIERSTRASS)
+		{
+			mywindow.document.write("Weierstrass parameterization "+ "<br>");
+		}		
+		if (ctx.ECP.CURVETYPE==ctx.ECP.EDWARDS)
+		{
+			mywindow.document.write("Edwards parameterization"+ "<br>");
+		}
+		if (ctx.ECP.CURVETYPE==ctx.ECP.MONTGOMERY)
+		{
+			mywindow.document.write("Montgomery parameterization"+ "<br>");
+		}
+
+		if (ctx.FP.MODTYPE==ctx.FP.PSEUDO_MERSENNE)
+		{
+			mywindow.document.write("Pseudo-Mersenne Modulus"+ "<br>");
+		}
+		if (ctx.FP.MODTYPE==ctx.FP.MONTGOMERY_FRIENDLY)
+		{
+			mywindow.document.write("Montgomery friendly Modulus"+ "<br>");
+		}
+		if (ctx.FP.MODTYPE==ctx.FP.GENERALISED_MERSENNE)
+		{
+			mywindow.document.write("Generalised-Mersenne Modulus"+ "<br>");
+		}
+		if (ctx.FP.MODTYPE==ctx.FP.NOT_SPECIAL)
+		{
+			mywindow.document.write("Not special Modulus"+ "<br>");
+		}
+
+		mywindow.document.write("Modulus size "+ctx.FP.MODBITS+ " bits"+ "<br>"); 
+
+		var r,gx,gy,s;
+		var G,WP;
+		var res=0;
+
+		G=ctx.ECP.generator();
+
+		r=new ctx.BIG(0); r.rcopy(ctx.ROM_CURVE.CURVE_Order);
+		s=ctx.BIG.randomnum(r,rng);
+			
+		WP=G.mul(r);
+		if (!WP.is_infinity())
+		{
+			alert("FAILURE - rG!=O");
+			fail=true;
+		}
+		var elapsed;
+		var start = performance.now();
+		var iterations=0;
+		do {
+			WP=G.mul(s);
+			iterations++;
+			elapsed=(performance.now()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=elapsed/iterations;
+		mywindow.document.write("EC  mul - " + iterations + " iterations  ");
+		mywindow.document.write(dur.toFixed(2) + " ms per iteration"+ "<br>");
+
+	}
+
+
+// GOLDILOCKS context
+	function goldilocks() {
+
+		var ctx = new CTX('GOLDILOCKS');
+		var i,j;
+		var result;
+		var MIN_ITERS=5;
+		var MIN_TIME=3;
+		var fail=false;
+		var RAW=[];
+
+		var rng=new ctx.RAND();
+
+		rng.clean();
+		for (i=0;i<100;i++) RAW[i]=i;
+
+		rng.seed(100,RAW);
+
+		mywindow=window.open();
+
+		mywindow.document.write("<br> Curve GOLDILOCKS"+ "<br>");
+		if (ctx.ECP.CURVETYPE==ctx.ECP.WEIERSTRASS)
+		{
+			mywindow.document.write("Weierstrass parameterization "+ "<br>");
+		}		
+		if (ctx.ECP.CURVETYPE==ctx.ECP.EDWARDS)
+		{
+			mywindow.document.write("Edwards parameterization"+ "<br>");
+		}
+		if (ctx.ECP.CURVETYPE==ctx.ECP.MONTGOMERY)
+		{
+			mywindow.document.write("Montgomery parameterization"+ "<br>");
+		}
+
+		if (ctx.FP.MODTYPE==ctx.FP.PSEUDO_MERSENNE)
+		{
+			mywindow.document.write("Pseudo-Mersenne Modulus"+ "<br>");
+		}
+		if (ctx.FP.MODTYPE==ctx.FP.MONTGOMERY_FRIENDLY)
+		{
+			mywindow.document.write("Montgomery friendly Modulus"+ "<br>");
+		}
+		if (ctx.FP.MODTYPE==ctx.FP.GENERALISED_MERSENNE)
+		{
+			mywindow.document.write("Generalised-Mersenne Modulus"+ "<br>");
+		}
+		if (ctx.FP.MODTYPE==ctx.FP.NOT_SPECIAL)
+		{
+			mywindow.document.write("Not special Modulus"+ "<br>");
+		}
+
+		mywindow.document.write("Modulus size "+ctx.FP.MODBITS+ " bits"+ "<br>"); 
+
+		var r,gx,gy,s;
+		var G,WP;
+		var res=0;
+
+		G=ctx.ECP.generator();
+
+		r=new ctx.BIG(0); r.rcopy(ctx.ROM_CURVE.CURVE_Order);
+		s=ctx.BIG.randomnum(r,rng);
+			
+		WP=G.mul(r);
+		if (!WP.is_infinity())
+		{
+			alert("FAILURE - rG!=O");
+			fail=true;
+		}
+		var elapsed;
+		var start = performance.now();
+		var iterations=0;
+		do {
+			WP=G.mul(s);
+			iterations++;
+			elapsed=(performance.now()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=elapsed/iterations;
+		mywindow.document.write("EC  mul - " + iterations + " iterations  ");
+		mywindow.document.write(dur.toFixed(2) + " ms per iteration"+ "<br>");
+
+	}
+
+
+// BN254 context
+	function bn254() {
+
+		var ctx = new CTX('BN254');
+		var i;
+		var result;
+		var MIN_ITERS=5;
+		var MIN_TIME=3;
+		var G;
+		var Q;
+		var RAW=[];
+
+		var rng=new ctx.RAND();
+
+		rng.clean();
+		for (i=0;i<100;i++) RAW[i]=i;
+
+		rng.seed(100,RAW);
+
+		mywindow=window.open();
+
+		mywindow.document.write("<br> Curve BN254"+ "<br>");
+		if (ctx.ECP.CURVE_PAIRING_TYPE==ctx.ECP.BN)
+		{
+			mywindow.document.write("BN Pairing-Friendly Curve"+ "<br>");
+		}
+		if (ctx.ECP.CURVE_PAIRING_TYPE==ctx.ECP.BLS)
+		{
+			mywindow.document.write("BLS Pairing-Friendly Curve"+ "<br>");
+		}
+
+		mywindow.document.write("Modulus size " + ctx.FP.MODBITS + " bits"+ "<br>"); 
+
+		G=ctx.ECP.generator();
+
+		r=new ctx.BIG(0); r.rcopy(ctx.ROM_CURVE.CURVE_Order);
+		s=ctx.BIG.randomnum(r,rng);
+
+		var P=ctx.PAIR.G1mul(G,r);
+
+		if (!P.is_infinity())
+		{
+			alert("FAILURE - rP!=O");
+			fail=true;
+		}	
+
+		var elapsed;
+		var start = performance.now();
+		var iterations=0;
+		do {
+			P=ctx.PAIR.G1mul(G,s);
+			iterations++;
+			elapsed=(performance.now()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=elapsed/iterations;
+		mywindow.document.write("G1 mul -                " + iterations + " iterations  ");
+		mywindow.document.write(dur.toFixed(2) + " ms per iteration"+ "<br>");
+
+		Q=ctx.ECP2.generator();
+		W=ctx.PAIR.G2mul(Q,r);
+
+		if (!W.is_infinity())
+		{
+			alert("FAILURE - rQ!=O");
+			fail=true;
+		}
+
+		start = performance.now();
+		iterations=0;
+		do {
+			W=ctx.PAIR.G2mul(Q,s);
+			iterations++;
+			elapsed=(performance.now()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=elapsed/iterations;
+		mywindow.document.write("G2 mul -                " + iterations + " iteration  ");
+		mywindow.document.write(dur.toFixed(2) + " ms per iteration"+ "<br>");
+
+		var w=ctx.PAIR.ate(Q,P);
+		w=ctx.PAIR.fexp(w);
+
+		var g=ctx.PAIR.GTpow(w,r);
+
+		if (!g.isunity())
+		{
+			alert("FAILURE - g^r!=1");
+			fail=true;
+		}
+
+		start = performance.now();
+		iterations=0;
+		do {
+			g=ctx.PAIR.GTpow(w,s);
+			iterations++;
+			elapsed=(performance.now()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=elapsed/iterations;
+		mywindow.document.write("GT pow -                " + iterations + " iteration  ");
+		mywindow.document.write(dur.toFixed(2) + " ms per iteration"+ "<br>");
+
+
+		var cr;
+		start = performance.now();
+		iterations=0;
+		do {
+			cr=w.compow(s,r); 
+			iterations++;
+			elapsed=(performance.now()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=elapsed/iterations;
+		mywindow.document.write("GT pow (compressed) -   " + iterations + " iteration  ");
+		mywindow.document.write(dur.toFixed(2) + " ms per iteration"+ "<br>");
+
+		start = performance.now();
+		iterations=0;
+		do {
+			w=ctx.PAIR.ate(Q,P);
+			iterations++;
+			elapsed=(performance.now()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=elapsed/iterations;
+		mywindow.document.write("PAIRing ATE   -         " + iterations + " iteration  ");
+		mywindow.document.write(dur.toFixed(2) + " ms per iteration"+ "<br>");
+
+		start = performance.now();
+		iterations=0;
+		do {
+			g=ctx.PAIR.fexp(w);
+			iterations++;
+			elapsed=(performance.now()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=elapsed/iterations;
+		mywindow.document.write("PAIRing FEXP -          " + iterations + " iteration  ");
+		mywindow.document.write(dur.toFixed(2) + " ms per iteration"+ "<br>");
+
+		P.copy(G);
+		Q.copy(W);
+
+		P=ctx.PAIR.G1mul(P,s);
+		g=ctx.PAIR.ate(Q,P);
+		g=ctx.PAIR.fexp(g);
+
+		P.copy(G);
+		Q=ctx.PAIR.G2mul(Q,s);
+		w=ctx.PAIR.ate(Q,P);
+		w=ctx.PAIR.fexp(w);
+
+		if (!g.equals(w))
+		{
+			alert("FAILURE - e(sQ,p)!=e(Q,sP)");
+			fail=true;
+		}
+
+		Q.copy(W);
+		g=ctx.PAIR.ate(Q,P);
+		g=ctx.PAIR.fexp(g);
+		g=ctx.PAIR.GTpow(g,s);
+
+		if (!g.equals(w))
+		{
+			alert("FAILURE - e(sQ,p)!=e(Q,P)^s");
+			fail=true;
+		}
+	}
+
+// BLS24 context
+	function bls24() {
+
+		var ctx = new CTX('BLS24');
+		var i;
+		var result;
+		var MIN_ITERS=3;
+		var MIN_TIME=3;
+		var G;
+		var Q;
+		var RAW=[];
+
+		var rng=new ctx.RAND();
+
+		rng.clean();
+		for (i=0;i<100;i++) RAW[i]=i;
+
+		rng.seed(100,RAW);
+
+		mywindow=window.open();
+
+		mywindow.document.write("<br> Curve BLS24"+ "<br>");
+		if (ctx.ECP.CURVE_PAIRING_TYPE==ctx.ECP.BN)
+		{
+			mywindow.document.write("BN Pairing-Friendly Curve"+ "<br>");
+		}
+		if (ctx.ECP.CURVE_PAIRING_TYPE==ctx.ECP.BLS)
+		{
+			mywindow.document.write("BLS24 Pairing-Friendly Curve"+ "<br>");
+		}
+
+		mywindow.document.write("Modulus size " + ctx.FP.MODBITS + " bits"+ "<br>"); 
+
+		G=ctx.ECP.generator();
+
+		r=new ctx.BIG(0); r.rcopy(ctx.ROM_CURVE.CURVE_Order);
+		s=ctx.BIG.randomnum(r,rng);
+
+		var P=ctx.PAIR192.G1mul(G,r);
+
+		if (!P.is_infinity())
+		{
+			alert("FAILURE - rP!=O");
+			fail=true;
+		}	
+
+		var elapsed;
+		var start = performance.now();
+		var iterations=0;
+		do {
+			P=ctx.PAIR192.G1mul(G,s);
+			iterations++;
+			elapsed=(performance.now()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=elapsed/iterations;
+		mywindow.document.write("G1 mul -                " + iterations + " iterations  ");
+		mywindow.document.write(dur.toFixed(2) + " ms per iteration"+ "<br>");
+
+		Q=ctx.ECP4.generator();
+		W=ctx.PAIR192.G2mul(Q,r);
+
+		if (!W.is_infinity())
+		{
+			alert("FAILURE - rQ!=O");
+			fail=true;
+		}
+
+		start = performance.now();
+		iterations=0;
+		do {
+			W=ctx.PAIR192.G2mul(Q,s);
+			iterations++;
+			elapsed=(performance.now()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=elapsed/iterations;
+		mywindow.document.write("G2 mul -                " + iterations + " iteration  ");
+		mywindow.document.write(dur.toFixed(2) + " ms per iteration"+ "<br>");
+
+		var w=ctx.PAIR192.ate(Q,P);
+		w=ctx.PAIR192.fexp(w);
+
+		var g=ctx.PAIR192.GTpow(w,r);
+
+		if (!g.isunity())
+		{
+			alert("FAILURE - g^r!=1");
+			fail=true;
+		}
+
+		start = performance.now();
+		iterations=0;
+		do {
+			g=ctx.PAIR192.GTpow(w,s);
+			iterations++;
+			elapsed=(performance.now()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=elapsed/iterations;
+		mywindow.document.write("GT pow -                " + iterations + " iteration  ");
+		mywindow.document.write(dur.toFixed(2) + " ms per iteration"+ "<br>");
+
+
+		var cr;
+		start = performance.now();
+		iterations=0;
+		do {
+			cr=w.compow(s,r); 
+			iterations++;
+			elapsed=(performance.now()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=elapsed/iterations;
+		mywindow.document.write("GT pow (compressed) -   " + iterations + " iteration  ");
+		mywindow.document.write(dur.toFixed(2) + " ms per iteration"+ "<br>");
+
+		start = performance.now();
+		iterations=0;
+		do {
+			w=ctx.PAIR192.ate(Q,P);
+			iterations++;
+			elapsed=(performance.now()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=elapsed/iterations;
+		mywindow.document.write("PAIRing ATE   -         " + iterations + " iteration  ");
+		mywindow.document.write(dur.toFixed(2) + " ms per iteration"+ "<br>");
+
+		start = performance.now();
+		iterations=0;
+		do {
+			g=ctx.PAIR192.fexp(w);
+			iterations++;
+			elapsed=(performance.now()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=elapsed/iterations;
+		mywindow.document.write("PAIRing FEXP -          " + iterations + " iteration  ");
+		mywindow.document.write(dur.toFixed(2) + " ms per iteration"+ "<br>");
+
+		P.copy(G);
+		Q.copy(W);
+
+		P=ctx.PAIR192.G1mul(P,s);
+		g=ctx.PAIR192.ate(Q,P);
+		g=ctx.PAIR192.fexp(g);
+
+		P.copy(G);
+		Q=ctx.PAIR192.G2mul(Q,s);
+		w=ctx.PAIR192.ate(Q,P);
+		w=ctx.PAIR192.fexp(w);
+
+		if (!g.equals(w))
+		{
+			alert("FAILURE - e(sQ,p)!=e(Q,sP)");
+			fail=true;
+		}
+
+		Q.copy(W);
+		g=ctx.PAIR192.ate(Q,P);
+		g=ctx.PAIR192.fexp(g);
+		g=ctx.PAIR192.GTpow(g,s);
+
+		if (!g.equals(w))
+		{
+			alert("FAILURE - e(sQ,p)!=e(Q,P)^s");
+			fail=true;
+		}
+	}
+
+// BLS48 context
+	function bls48() {
+
+		var ctx = new CTX('BLS48');
+		var i;
+		var result;
+		var MIN_ITERS=1;
+		var MIN_TIME=3;
+		var G;
+		var Q;
+		var RAW=[];
+
+		var rng=new ctx.RAND();
+
+		rng.clean();
+		for (i=0;i<100;i++) RAW[i]=i;
+
+		rng.seed(100,RAW);
+
+		mywindow=window.open();
+
+		mywindow.document.write("<br> Curve BLS48"+ "<br>");
+		if (ctx.ECP.CURVE_PAIRING_TYPE==ctx.ECP.BN)
+		{
+			mywindow.document.write("BN Pairing-Friendly Curve"+ "<br>");
+		}
+		if (ctx.ECP.CURVE_PAIRING_TYPE==ctx.ECP.BLS)
+		{
+			mywindow.document.write("BLS48 Pairing-Friendly Curve"+ "<br>");
+		}
+
+		mywindow.document.write("Modulus size " + ctx.FP.MODBITS + " bits"+ "<br>"); 
+
+		G=ctx.ECP.generator();
+
+		r=new ctx.BIG(0); r.rcopy(ctx.ROM_CURVE.CURVE_Order);
+		s=ctx.BIG.randomnum(r,rng);
+
+		var P=ctx.PAIR256.G1mul(G,r);
+
+		if (!P.is_infinity())
+		{
+			alert("FAILURE - rP!=O");
+			fail=true;
+		}	
+
+		var elapsed;
+		var start = performance.now();
+		var iterations=0;
+		do {
+			P=ctx.PAIR256.G1mul(G,s);
+			iterations++;
+			elapsed=(performance.now()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=elapsed/iterations;
+		mywindow.document.write("G1 mul -                " + iterations + " iterations  ");
+		mywindow.document.write(dur.toFixed(2) + " ms per iteration"+ "<br>");
+
+		Q=ctx.ECP8.generator();
+		W=ctx.PAIR256.G2mul(Q,r);
+
+		if (!W.is_infinity())
+		{
+			alert("FAILURE - rQ!=O");
+			fail=true;
+		}
+
+		start = performance.now();
+		iterations=0;
+		do {
+			W=ctx.PAIR256.G2mul(Q,s);
+			iterations++;
+			elapsed=(performance.now()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=elapsed/iterations;
+		mywindow.document.write("G2 mul -                " + iterations + " iteration  ");
+		mywindow.document.write(dur.toFixed(2) + " ms per iteration"+ "<br>");
+
+		var w=ctx.PAIR256.ate(Q,P);
+		w=ctx.PAIR256.fexp(w);
+
+		var g=ctx.PAIR256.GTpow(w,r);
+
+		if (!g.isunity())
+		{
+			alert("FAILURE - g^r!=1");
+			fail=true;
+		}
+
+		start = performance.now();
+		iterations=0;
+		do {
+			g=ctx.PAIR256.GTpow(w,s);
+			iterations++;
+			elapsed=(performance.now()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=elapsed/iterations;
+		mywindow.document.write("GT pow -                " + iterations + " iteration  ");
+		mywindow.document.write(dur.toFixed(2) + " ms per iteration"+ "<br>");
+
+
+		var cr;
+		start = performance.now();
+		iterations=0;
+		do {
+			cr=w.compow(s,r); 
+			iterations++;
+			elapsed=(performance.now()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=elapsed/iterations;
+		mywindow.document.write("GT pow (compressed) -   " + iterations + " iteration  ");
+		mywindow.document.write(dur.toFixed(2) + " ms per iteration"+ "<br>");
+
+		start = performance.now();
+		iterations=0;
+		do {
+			w=ctx.PAIR256.ate(Q,P);
+			iterations++;
+			elapsed=(performance.now()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=elapsed/iterations;
+		mywindow.document.write("PAIRing ATE   -         " + iterations + " iteration  ");
+		mywindow.document.write(dur.toFixed(2) + " ms per iteration"+ "<br>");
+
+		start = performance.now();
+		iterations=0;
+		do {
+			g=ctx.PAIR256.fexp(w);
+			iterations++;
+			elapsed=(performance.now()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=elapsed/iterations;
+		mywindow.document.write("PAIRing FEXP -          " + iterations + " iteration  ");
+		mywindow.document.write(dur.toFixed(2) + " ms per iteration"+ "<br>");
+
+		P.copy(G);
+		Q.copy(W);
+
+		P=ctx.PAIR256.G1mul(P,s);
+		g=ctx.PAIR256.ate(Q,P);
+		g=ctx.PAIR256.fexp(g);
+
+		P.copy(G);
+		Q=ctx.PAIR256.G2mul(Q,s);
+		w=ctx.PAIR256.ate(Q,P);
+		w=ctx.PAIR256.fexp(w);
+
+		if (!g.equals(w))
+		{
+			alert("FAILURE - e(sQ,p)!=e(Q,sP)");
+			fail=true;
+		}
+
+		Q.copy(W);
+		g=ctx.PAIR256.ate(Q,P);
+		g=ctx.PAIR256.fexp(g);
+		g=ctx.PAIR256.GTpow(g,s);
+
+		if (!g.equals(w))
+		{
+			alert("FAILURE - e(sQ,p)!=e(Q,P)^s");
+			fail=true;
+		}
+	}
+
+// RSA2048 context
+	function rsa2048() {
+
+		var ctx = new CTX('RSA2048');
+
+		mywindow=window.open();
+
+		mywindow.document.write("<br> Generating 2048 bit RSA public/private key pair"+ "<br>");
+		var fail=false;
+		var RAW=[];
+
+		var rng=new ctx.RAND();
+
+		rng.clean();
+		for (i=0;i<100;i++) RAW[i]=i;
+
+		rng.seed(100,RAW);
+
+		var pub=new ctx.rsa_public_key(ctx.FF.FFLEN);
+		var priv=new ctx.rsa_private_key(ctx.FF.HFLEN);
+
+		var M=[];
+		var C=[];
+		var P=[];
+
+		var MIN_ITERS=1;
+		var MIN_TIME=3;
+		var elapsed;
+		var start = performance.now();
+		var iterations=0;
+		do {
+			ctx.RSA.KEY_PAIR(rng,65537,priv,pub);
+			iterations++;
+			elapsed=(performance.now()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=elapsed/iterations;
+		mywindow.document.write("RSA gen - " + iterations + " iteration  ");
+		mywindow.document.write(dur.toFixed(2) + " ms per iteration"+ "<br>");
+
+		MIN_ITERS=5;
+
+		for (i=0;i<ctx.RSA.RFS;i++) M[i]=(i%128);
+
+		start = performance.now();
+		iterations=0;
+		do {
+			ctx.RSA.ENCRYPT(pub,M,C);
+			iterations++;
+			elapsed=(performance.now()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=elapsed/iterations;
+		mywindow.document.write("RSA enc - " + iterations + " iterations  ");
+		mywindow.document.write(dur.toFixed(2) + " ms per iteration"+ "<br>");
+
+		start = performance.now();
+		iterations=0;
+		do {
+			ctx.RSA.DECRYPT(priv,C,P);
+			iterations++;
+			elapsed=(performance.now()-start);
+		} while (elapsed<MIN_TIME*1000 || iterations<MIN_ITERS);
+		dur=elapsed/iterations;
+		mywindow.document.write("RSA dec - " + iterations + " iterations  ");
+		mywindow.document.write(dur.toFixed(2) + " ms per iteration"+ "<br>");
+
+		var cmp=true;
+		for (i=0;i<ctx.RSA.RFS;i++)
+		{
+			if (P[i]!=M[i]) cmp=false;
+		}
+
+		if (!cmp)
+		{
+			alert("FAILURE - RSA decryption");
+			fail=true;
+		}
+		if (!fail) mywindow.document.write("All tests pass"+ "<br>");
+	}
+
+
+	//rsa2048();
+	//bls48();
+	//bls24();
+	//bls383();
+	//bn254();
+	//goldilocks();
+	//nist256();
+	//ed25519();
+
+	//bls383();
+	//ed25519();
+
+	//nist256();
+	//goldilocks();
+	//bn254();
+	//bls383();
+	//bls24();
+	//bls48();
+	//rsa2048();
+
+</script>
+
+
+
+</body>
+
+</html>
+
diff --git a/version3/js/TestALL.html b/version3/js/TestALL.html
new file mode 100644
index 0000000..657046f
--- /dev/null
+++ b/version3/js/TestALL.html
@@ -0,0 +1,1527 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>JavaScript Test ALL</title>
+</head>
+<body>
+<h1>JavaScript Test All Examples</h1>
+<script type="text/javascript"src=./rand.js></script>
+<script type="text/javascript"src=./rom_curve.js></script>
+<script type="text/javascript"src=./rom_field.js></script>
+<script type="text/javascript"src=./uint64.js></script>
+<script type="text/javascript"src=./aes.js></script>
+<script type="text/javascript"src=./big.js></script>
+<script type="text/javascript"src=./gcm.js></script>
+<script type="text/javascript"src=./hash256.js></script>
+<script type="text/javascript"src=./hash384.js></script>
+<script type="text/javascript"src=./hash512.js></script>
+<script type="text/javascript"src=./sha3.js></script>
+<script type="text/javascript"src=./nhs.js></script>
+<script type="text/javascript"src=./fp.js></script>
+<script type="text/javascript"src=./fp2.js></script>
+<script type="text/javascript"src=./fp4.js></script>
+<script type="text/javascript"src=./fp12.js></script>
+<script type="text/javascript"src=./ff.js></script>
+<script type="text/javascript"src=./rsa.js></script>
+<script type="text/javascript"src=./ecp.js></script>
+<script type="text/javascript"src=./ecp2.js></script>
+<script type="text/javascript"src=./ecdh.js></script>
+<script type="text/javascript"src=./pair.js></script>
+<script type="text/javascript"src=./mpin.js></script>
+<script type="text/javascript"src=./ctx.js></script>
+
+<script type="text/javascript"src=./fp8.js></script>
+<script type="text/javascript"src=./fp16.js></script>
+<script type="text/javascript"src=./fp24.js></script>
+<script type="text/javascript"src=./fp48.js></script>
+<script type="text/javascript"src=./ecp4.js></script>
+<script type="text/javascript"src=./ecp8.js></script>
+<script type="text/javascript"src=./pair192.js></script>
+<script type="text/javascript"src=./pair256.js></script>
+<script type="text/javascript"src=./mpin192.js></script>
+<script type="text/javascript"src=./mpin256.js></script>
+
+<p><a id="myLink1" href="#" onclick="location.reload(false);ed25519();">ED25519 255-bit Edwards Elliptic Curve ECDH/ECIES/ECDSA</a></p>
+<p><a id="myLink2" href="#" onclick="location.reload(false);nist256();">NIST256 256-bit Weierstrass Elliptic Curve ECDH/ECIES/ECDSA</a></p>
+<p><a id="myLink3" href="#" onclick="location.reload(false);goldilocks();">GOLDILOCKS 448-bit Edwards Elliptic Curve ECDH/ECIES/ECDSA</a></p>
+<p><a id="myLink4" href="#" onclick="location.reload(false);bn254();">BN254 254-bit k=12 Pairing-Friendly BN Curve MPIN</a></p>
+<p><a id="myLink5" href="#" onclick="location.reload(false);bls383();">BLS383 383-bit k=12 Pairing-Friendly BLS Curve MPIN</a></p>
+<p><a id="myLink6" href="#" onclick="location.reload(false);bls24();">BLS24 479-bit k=24 Pairing-Friendly BLS Curve MPIN</a></p>
+<p><a id="myLink7" href="#" onclick="location.reload(false);bls48();">BLS48 556-bit k=48 Pairing-Friendly BLS Curve MPIN</a></p>
+<p><a id="myLink8" href="#" onclick="location.reload(false);rsa2048();">RSA2048 2048-bit RSA Key generation/Encryption/Decryption</a></p>
+
+
+<script>
+
+/* Test ECC */
+/* test driver and function exerciser for ECDH/ECIES/ECDSA API Functions */
+
+// ED25519 context
+function ed25519() {
+	var ctx = new CTX('ED25519');
+
+	mywindow=window.open();
+
+	mywindow.document.write("<br> ED25519 Curve "+  "<br>");
+
+	var i,j=0,res;
+	var result;
+	var pp="M0ng00se";
+
+	var EGS=ctx.ECDH.EGS;
+	var EFS=ctx.ECDH.EFS;
+	var EAS=ctx.ECP.AESKEY;
+	var sha=ctx.ECP.HASH_TYPE;
+
+	var S1=[];
+	var W0=[];
+	var W1=[];
+	var Z0=[];
+	var Z1=[];
+	var RAW=[];
+	var SALT=[];
+	var P1=[];
+	var P2=[];
+	var V=[];
+	var M=[];
+	var T=new Array(12);  // must specify required length
+	var CS=[];
+	var DS=[];
+
+	var rng=new ctx.RAND();
+
+	rng.clean();
+	for (i=0;i<100;i++) RAW[i]=i;
+
+	rng.seed(100,RAW);
+
+	for (i=0;i<8;i++) SALT[i]=(i+1);  // set Salt
+
+	mywindow.document.write("Alice's Passphrase= " + pp + "<br>");
+
+	var PW=ctx.ECDH.stringtobytes(pp);
+/* private key S0 of size EGS bytes derived from Password and Salt */
+	var S0=ctx.ECDH.PBKDF2(sha,PW,SALT,1000,EGS);
+
+	mywindow.document.write("Alice's private key= 0x"+ctx.ECDH.bytestostring(S0)+ "<br>");
+/* Generate Key pair S/W */
+	ctx.ECDH.KEY_PAIR_GENERATE(null,S0,W0); 
+
+	mywindow.document.write("Alice's public key= 0x"+ctx.ECDH.bytestostring(W0)+ "<br>");
+
+	res=ctx.ECDH.PUBLIC_KEY_VALIDATE(W0);
+	if (res!=0)
+		alert("ECP Public Key is invalid!");
+/* Random private key for other party */
+	ctx.ECDH.KEY_PAIR_GENERATE(rng,S1,W1);
+
+	mywindow.document.write("Servers private key= 0x"+ctx.ECDH.bytestostring(S1)+ "<br>");
+	mywindow.document.write("Servers public key= 0x"+ctx.ECDH.bytestostring(W1)+ "<br>");
+
+	res=ctx.ECDH.PUBLIC_KEY_VALIDATE(W1);
+	if (res!=0)
+		alert("ECP Public Key is invalid!");
+			
+
+/* Calculate common key using DH - IEEE 1363 method */
+
+	ctx.ECDH.ECPSVDP_DH(S0,W1,Z0);
+	ctx.ECDH.ECPSVDP_DH(S1,W0,Z1);
+
+	var same=true;
+	for (i=0;i<ctx.ECDH.EFS;i++)
+		if (Z0[i]!=Z1[i]) same=false;
+
+	if (!same)
+		alert("*** ECPSVDP-DH Failed");
+
+	var KEY=ctx.ECDH.KDF2(sha,Z0,null,ctx.ECP.AESKEY);
+
+	mywindow.document.write("Alice's ECDH Key=  0x"+ctx.ECDH.bytestostring(KEY)+ "<br>");
+	mywindow.document.write("Servers ECDH Key=  0x"+ctx.ECDH.bytestostring(KEY)+ "<br>");
+
+	if (ctx.ECP.CURVETYPE!=ctx.ECP.MONTGOMERY)
+	{
+		mywindow.document.write("Testing ECIES"+ "<br>");
+
+		P1[0]=0x0; P1[1]=0x1; P1[2]=0x2; 
+		P2[0]=0x0; P2[1]=0x1; P2[2]=0x2; P2[3]=0x3; 
+
+		for (i=0;i<=16;i++) M[i]=i; 
+
+		var C=ctx.ECDH.ECIES_ENCRYPT(sha,P1,P2,rng,W1,M,V,T);
+
+		mywindow.document.write("Ciphertext= "+ "<br>");
+		mywindow.document.write("V= 0x"+ctx.ECDH.bytestostring(V)+ "<br>");
+		mywindow.document.write("C= 0x"+ctx.ECDH.bytestostring(C)+ "<br>");
+		mywindow.document.write("T= 0x"+ctx.ECDH.bytestostring(T)+ "<br>");
+
+
+		M=ctx.ECDH.ECIES_DECRYPT(sha,P1,P2,V,C,T,S1);
+		if (M.length==0)
+			alert("*** ECIES Decryption Failed ");
+		else mywindow.document.write("Decryption succeeded"+ "<br>");
+
+		mywindow.document.write("Message is 0x"+ctx.ECDH.bytestostring(M)+ "<br>");
+
+		mywindow.document.write("Testing ECDSA"+ "<br>");
+
+		if (ctx.ECDH.ECPSP_DSA(sha,rng,S0,M,CS,DS)!=0)
+			alert("***ECDSA Signature Failed");
+		
+		mywindow.document.write("Signature= "+ "<br>");
+		mywindow.document.write("C= 0x"+ctx.ECDH.bytestostring(CS)+ "<br>");
+		mywindow.document.write("D= 0x"+ctx.ECDH.bytestostring(DS)+ "<br>");
+
+		if (ctx.ECDH.ECPVP_DSA(sha,W0,M,CS,DS)!=0)
+			alert("***ECDSA Verification Failed");
+		else mywindow.document.write("ECDSA Signature/Verification succeeded "+  "<br>");
+	}
+
+}
+// NIST256 context
+
+function nist256() {
+	var ctx = new CTX('NIST256');
+	mywindow=window.open();
+
+	mywindow.document.write("<br> NIST256 Curve "+  "<br>");
+	var i,j=0,res;
+	var result;
+	var pp="M0ng00se";
+
+	var EGS=ctx.ECDH.EGS;
+	var EFS=ctx.ECDH.EFS;
+	var EAS=ctx.ECP.AESKEY;
+	var sha=ctx.ECP.HASH_TYPE;
+
+	var S1=[];
+	var W0=[];
+	var W1=[];
+	var Z0=[];
+	var Z1=[];
+	var RAW=[];
+	var SALT=[];
+	var P1=[];
+	var P2=[];
+	var V=[];
+	var M=[];
+	var T=new Array(12);  // must specify required length
+	var CS=[];
+	var DS=[];
+
+	var rng=new ctx.RAND();
+
+	rng.clean();
+	for (i=0;i<100;i++) RAW[i]=i;
+
+	rng.seed(100,RAW);
+
+
+	for (i=0;i<8;i++) SALT[i]=(i+1);  // set Salt
+
+	mywindow.document.write("Alice's Passphrase= " + pp + "<br>");
+
+	var PW=ctx.ECDH.stringtobytes(pp);
+/* private key S0 of size EGS bytes derived from Password and Salt */
+	var S0=ctx.ECDH.PBKDF2(sha,PW,SALT,1000,EGS);
+
+	mywindow.document.write("Alice's private key= 0x"+ctx.ECDH.bytestostring(S0)+ "<br>");
+/* Generate Key pair S/W */
+	ctx.ECDH.KEY_PAIR_GENERATE(null,S0,W0); 
+
+	mywindow.document.write("Alice's public key= 0x"+ctx.ECDH.bytestostring(W0)+ "<br>");
+
+	res=ctx.ECDH.PUBLIC_KEY_VALIDATE(W0);
+	if (res!=0)
+		alert("ECP Public Key is invalid!");
+/* Random private key for other party */
+	ctx.ECDH.KEY_PAIR_GENERATE(rng,S1,W1);
+
+	mywindow.document.write("Servers private key= 0x"+ctx.ECDH.bytestostring(S1)+ "<br>");
+	mywindow.document.write("Servers public key= 0x"+ctx.ECDH.bytestostring(W1)+ "<br>");
+
+	res=ctx.ECDH.PUBLIC_KEY_VALIDATE(W1);
+	if (res!=0)
+		alert("ECP Public Key is invalid!");
+			
+
+/* Calculate common key using DH - IEEE 1363 method */
+
+	ctx.ECDH.ECPSVDP_DH(S0,W1,Z0);
+	ctx.ECDH.ECPSVDP_DH(S1,W0,Z1);
+
+	var same=true;
+	for (i=0;i<ctx.ECDH.EFS;i++)
+		if (Z0[i]!=Z1[i]) same=false;
+
+	if (!same)
+		alert("*** ECPSVDP-DH Failed");
+
+	var KEY=ctx.ECDH.KDF2(sha,Z0,null,ctx.ECP.AESKEY);
+
+	mywindow.document.write("Alice's ECDH Key=  0x"+ctx.ECDH.bytestostring(KEY)+ "<br>");
+	mywindow.document.write("Servers ECDH Key=  0x"+ctx.ECDH.bytestostring(KEY)+ "<br>");
+
+	if (ctx.ECP.CURVETYPE!=ctx.ECP.MONTGOMERY)
+	{
+		mywindow.document.write("Testing ECIES"+ "<br>");
+
+		P1[0]=0x0; P1[1]=0x1; P1[2]=0x2; 
+		P2[0]=0x0; P2[1]=0x1; P2[2]=0x2; P2[3]=0x3; 
+
+		for (i=0;i<=16;i++) M[i]=i; 
+
+		var C=ctx.ECDH.ECIES_ENCRYPT(sha,P1,P2,rng,W1,M,V,T);
+
+		mywindow.document.write("Ciphertext= "+ "<br>");
+		mywindow.document.write("V= 0x"+ctx.ECDH.bytestostring(V)+ "<br>");
+		mywindow.document.write("C= 0x"+ctx.ECDH.bytestostring(C)+ "<br>");
+		mywindow.document.write("T= 0x"+ctx.ECDH.bytestostring(T)+ "<br>");
+
+
+		M=ctx.ECDH.ECIES_DECRYPT(sha,P1,P2,V,C,T,S1);
+		if (M.length==0)
+			alert("*** ECIES Decryption Failed ");
+		else mywindow.document.write("Decryption succeeded"+ "<br>");
+
+		mywindow.document.write("Message is 0x"+ctx.ECDH.bytestostring(M)+ "<br>");
+
+		mywindow.document.write("Testing ECDSA"+ "<br>");
+
+		if (ctx.ECDH.ECPSP_DSA(sha,rng,S0,M,CS,DS)!=0)
+			alert("***ECDSA Signature Failed");
+		
+		mywindow.document.write("Signature= "+ "<br>");
+		mywindow.document.write("C= 0x"+ctx.ECDH.bytestostring(CS)+ "<br>");
+		mywindow.document.write("D= 0x"+ctx.ECDH.bytestostring(DS)+ "<br>");
+
+		if (ctx.ECDH.ECPVP_DSA(sha,W0,M,CS,DS)!=0)
+			alert("***ECDSA Verification Failed");
+		else mywindow.document.write("ECDSA Signature/Verification succeeded "+  "<br>");
+	}
+
+}
+
+
+// GOLDILOCKS context
+function goldilocks() {
+	var ctx = new CTX('GOLDILOCKS');
+	mywindow=window.open();
+
+	mywindow.document.write("<br> GOLDILOCKS Curve "+  "<br>");
+
+	var i,j=0,res;
+	var result;
+	var pp="M0ng00se";
+
+	var EGS=ctx.ECDH.EGS;
+	var EFS=ctx.ECDH.EFS;
+	var EAS=ctx.ECP.AESKEY;
+	var sha=ctx.ECP.HASH_TYPE;
+
+	var S1=[];
+	var W0=[];
+	var W1=[];
+	var Z0=[];
+	var Z1=[];
+	
+	var SALT=[];
+	var P1=[];
+	var P2=[];
+	var V=[];
+	var M=[];
+	var T=new Array(12);  // must specify required length
+	var CS=[];
+	var DS=[];
+
+	var RAW=[];
+	var rng=new ctx.RAND();
+
+	rng.clean();
+	for (i=0;i<100;i++) RAW[i]=i;
+
+	rng.seed(100,RAW);
+
+
+	for (i=0;i<8;i++) SALT[i]=(i+1);  // set Salt
+
+	mywindow.document.write("Alice's Passphrase= " + pp + "<br>");
+
+	var PW=ctx.ECDH.stringtobytes(pp);
+/* private key S0 of size EGS bytes derived from Password and Salt */
+	var S0=ctx.ECDH.PBKDF2(sha,PW,SALT,1000,EGS);
+
+	mywindow.document.write("Alice's private key= 0x"+ctx.ECDH.bytestostring(S0)+ "<br>");
+/* Generate Key pair S/W */
+	ctx.ECDH.KEY_PAIR_GENERATE(null,S0,W0); 
+
+	mywindow.document.write("Alice's public key= 0x"+ctx.ECDH.bytestostring(W0)+ "<br>");
+
+	res=ctx.ECDH.PUBLIC_KEY_VALIDATE(W0);
+	if (res!=0)
+		alert("ECP Public Key is invalid!");
+/* Random private key for other party */
+	ctx.ECDH.KEY_PAIR_GENERATE(rng,S1,W1);
+
+	mywindow.document.write("Servers private key= 0x"+ctx.ECDH.bytestostring(S1)+ "<br>");
+	mywindow.document.write("Servers public key= 0x"+ctx.ECDH.bytestostring(W1)+ "<br>");
+
+	res=ctx.ECDH.PUBLIC_KEY_VALIDATE(W1);
+	if (res!=0)
+		alert("ECP Public Key is invalid!");
+			
+
+/* Calculate common key using DH - IEEE 1363 method */
+
+	ctx.ECDH.ECPSVDP_DH(S0,W1,Z0);
+	ctx.ECDH.ECPSVDP_DH(S1,W0,Z1);
+
+	var same=true;
+	for (i=0;i<ctx.ECDH.EFS;i++)
+		if (Z0[i]!=Z1[i]) same=false;
+
+	if (!same)
+		alert("*** ECPSVDP-DH Failed");
+
+	var KEY=ctx.ECDH.KDF2(sha,Z0,null,ctx.ECP.AESKEY);
+
+	mywindow.document.write("Alice's ECDH Key=  0x"+ctx.ECDH.bytestostring(KEY)+ "<br>");
+	mywindow.document.write("Servers ECDH Key=  0x"+ctx.ECDH.bytestostring(KEY)+ "<br>");
+
+	if (ctx.ECP.CURVETYPE!=ctx.ECP.MONTGOMERY)
+	{
+		mywindow.document.write("Testing ECIES"+ "<br>");
+
+		P1[0]=0x0; P1[1]=0x1; P1[2]=0x2; 
+		P2[0]=0x0; P2[1]=0x1; P2[2]=0x2; P2[3]=0x3; 
+
+		for (i=0;i<=16;i++) M[i]=i; 
+
+		var C=ctx.ECDH.ECIES_ENCRYPT(sha,P1,P2,rng,W1,M,V,T);
+
+		mywindow.document.write("Ciphertext= "+ "<br>");
+		mywindow.document.write("V= 0x"+ctx.ECDH.bytestostring(V)+ "<br>");
+		mywindow.document.write("C= 0x"+ctx.ECDH.bytestostring(C)+ "<br>");
+		mywindow.document.write("T= 0x"+ctx.ECDH.bytestostring(T)+ "<br>");
+
+
+		M=ctx.ECDH.ECIES_DECRYPT(sha,P1,P2,V,C,T,S1);
+		if (M.length==0)
+			alert("*** ECIES Decryption Failed ");
+		else mywindow.document.write("Decryption succeeded"+ "<br>");
+
+		mywindow.document.write("Message is 0x"+ctx.ECDH.bytestostring(M)+ "<br>");
+
+		mywindow.document.write("Testing ECDSA"+ "<br>");
+
+		if (ctx.ECDH.ECPSP_DSA(sha,rng,S0,M,CS,DS)!=0)
+			alert("***ECDSA Signature Failed");
+		
+		mywindow.document.write("Signature= "+ "<br>");
+		mywindow.document.write("C= 0x"+ctx.ECDH.bytestostring(CS)+ "<br>");
+		mywindow.document.write("D= 0x"+ctx.ECDH.bytestostring(DS)+ "<br>");
+
+		if (ctx.ECDH.ECPVP_DSA(sha,W0,M,CS,DS)!=0)
+			alert("***ECDSA Verification Failed");
+		else mywindow.document.write("ECDSA Signature/Verification succeeded "+  "<br>");
+	}
+}
+
+
+/* Test RSA */
+/* test driver and function exerciser for RSA API Functions */
+
+
+// RSA2048 context
+function rsa2048() {
+	var ctx = new CTX('RSA2048');
+
+	var i,j=0,res;
+	var result;
+
+	var sha=ctx.RSA.HASH_TYPE;
+
+	var message="Hello World\n";
+
+	var pub=new ctx.rsa_public_key(ctx.FF.FFLEN);
+	var priv=new ctx.rsa_private_key(ctx.FF.HFLEN);
+
+	var ML=[];
+	var C=[];
+	var S=[];
+	
+	var RAW=[];
+	var rng=new ctx.RAND();
+
+	rng.clean();
+	for (i=0;i<100;i++) RAW[i]=i;
+
+	rng.seed(100,RAW);
+
+	mywindow=window.open();
+
+	var start,end,time;
+	start=new Date().getTime();
+	mywindow.document.write("<br> Generating RSA public/private key pair (slow!)  <br>");
+	ctx.RSA.KEY_PAIR(rng,65537,priv,pub);
+	end=new Date().getTime();
+	time=end-start;
+	mywindow.document.write("Time in ms= "+time+"<br>");
+
+	var M=ctx.RSA.stringtobytes(message);  
+	mywindow.document.write("Encrypting test string <br>");
+
+	var E=ctx.RSA.OAEP_ENCODE(sha,M,rng,null); /* OAEP encode message m to e  */
+	mywindow.document.write("Encoding= 0x" + ctx.RSA.bytestohex(E) + "<br>");  
+
+	mywindow.document.write("Public key= 0x"+pub.n.toString() + "<br>"); 
+
+	start=new Date().getTime();	
+	ctx.RSA.ENCRYPT(pub,E,C);     /* encrypt encoded message */
+	end=new Date().getTime();	
+	time=end-start;
+	mywindow.document.write("Time in ms= "+time+"<br>");
+
+	mywindow.document.write("Ciphertext= 0x" + ctx.RSA.bytestohex(C) + "<br>");  
+
+	mywindow.document.write("Decrypting test string <br>");
+	start=new Date().getTime();	
+	ctx.RSA.DECRYPT(priv,C,ML); 
+	end=new Date().getTime();
+	time=end-start;
+	mywindow.document.write("Time in ms= "+time+"<br>");
+
+	var cmp=true;
+	if (E.length!=ML.length) cmp=false;
+	else
+	{
+		for (var j=0;j<E.length;j++)
+			if (E[j]!=ML[j]) cmp=false;
+	}
+	if (cmp) mywindow.document.write("Decryption is OK <br>");
+	else mywindow.document.write("Decryption Failed <br>");
+
+	var MS=ctx.RSA.OAEP_DECODE(sha,null,ML); /* OAEP decode message  */
+	mywindow.document.write("Decoding= 0x" + ctx.RSA.bytestohex(MS) + "<br>");  
+
+	mywindow.document.write("message= "+ctx.RSA.bytestostring(MS) + "<br>");  
+
+
+	mywindow.document.write("Signing message <br>");
+	ctx.RSA.PKCS15(sha,M,C);
+
+	ctx.RSA.DECRYPT(priv,C,S); /* create signature in S */ 
+
+	mywindow.document.write("Signature= 0x" + ctx.RSA.bytestohex(S) + "<br>");  
+
+	ctx.RSA.ENCRYPT(pub,S,ML); 
+
+	cmp=true;
+	if (C.length!=ML.length) cmp=false;
+	else
+	{
+		for (var j=0;j<C.length;j++)
+			if (C[j]!=ML[j]) cmp=false;
+	}
+	if (cmp) mywindow.document.write("Signature is valid <br>");
+	else mywindow.document.write("Signature is INVALID <br>");
+
+	ctx.RSA.PRIVATE_KEY_KILL(priv);
+
+
+}
+
+/* Test M-Pin */
+
+// BN254 context
+function bn254() {
+	var ctx = new CTX('BN254');
+	mywindow=window.open();
+
+	mywindow.document.write("<br> BN254 Pairing-Friendly Curve "+  "<br>");
+
+	var i,res;
+	var result;
+
+	var EGS=ctx.MPIN.EGS;
+	var EFS=ctx.MPIN.EFS;
+	var EAS=ctx.ECP.AESKEY;
+
+	var sha=ctx.ECP.HASH_TYPE;
+
+	var G1S=2*EFS+1; /* Group 1 Size */
+	var G2S=4*EFS; /* Group 2 Size */
+
+	var S=[];
+	var SST=[];
+	var TOKEN = [];
+	var PERMIT = [];
+	var SEC = [];
+	var xID = [];
+	var xCID = [];
+	var X= [];
+	var Y= [];
+	var E=[];
+	var F=[];
+	var HCID=[];
+	var HID=[];
+	var HTID=[];
+
+	var G1=[];
+	var G2=[];
+	var R=[];
+	var Z=[];
+	var W=[];
+	var T=[];
+	var CK=[];
+	var SK=[];
+
+	var HSID=[];
+
+/* Set configuration */
+	var PERMITS=true;
+	var PINERROR=true;
+	var FULL=true;
+    var ONE_PASS=false;
+
+	var RAW=[];
+	var rng=new ctx.RAND();
+
+	rng.clean();
+	for (i=0;i<100;i++) RAW[i]=i;
+
+	rng.seed(100,RAW);
+
+/* Trusted Authority set-up */
+	ctx.MPIN.RANDOM_GENERATE(rng,S);
+	mywindow.document.write("M-Pin Master Secret s: 0x"+ctx.MPIN.bytestostring(S) + "<br>");
+ 
+ /* Create Client Identity */
+ 	var IDstr = "testUser@miracl.com";
+	var CLIENT_ID = ctx.MPIN.stringtobytes(IDstr);  
+	HCID=ctx.MPIN.HASH_ID(sha,CLIENT_ID);  /* Either Client or TA calculates Hash(ID) - you decide! */
+		
+	mywindow.document.write("Client ID= "+ctx.MPIN.bytestostring(CLIENT_ID) + "<br>");
+
+/* Client and Server are issued secrets by DTA */
+	ctx.MPIN.GET_SERVER_SECRET(S,SST);
+	mywindow.document.write("Server Secret SS: 0x"+ctx.MPIN.bytestostring(SST) + "<br>");
+
+	ctx.MPIN.GET_CLIENT_SECRET(S,HCID,TOKEN);
+	mywindow.document.write("Client Secret CS: 0x"+ctx.MPIN.bytestostring(TOKEN) + "<br>");     
+	
+/* Client extracts PIN from secret to create Token */
+	var pin=1234;
+	mywindow.document.write("Client extracts PIN= "+pin + "<br>"); 
+	var rtn=ctx.MPIN.EXTRACT_PIN(sha,CLIENT_ID,pin,TOKEN);
+	if (rtn != 0)
+		mywindow.document.write("Failed to extract PIN " + "<br>");  
+
+	mywindow.document.write("Client Token TK: 0x"+ctx.MPIN.bytestostring(TOKEN) + "<br>");        
+
+	if (FULL)
+	{
+		ctx.MPIN.PRECOMPUTE(TOKEN,HCID,G1,G2);
+	}
+
+	var date;
+	if (PERMITS)
+	{
+		date=ctx.MPIN.today();
+/* Client gets "Time Token" permit from DTA */ 	
+		ctx.MPIN.GET_CLIENT_PERMIT(sha,date,S,HCID,PERMIT);
+		mywindow.document.write("Time Permit TP: 0x"+ctx.MPIN.bytestostring(PERMIT) + "<br>");   
+
+/* This encoding makes Time permit look random - Elligator squared */
+		ctx.MPIN.ENCODING(rng,PERMIT);
+		mywindow.document.write("Encoded Time Permit TP: 0x"+ctx.MPIN.bytestostring(PERMIT) + "<br>");   
+		ctx.MPIN.DECODING(PERMIT);
+		mywindow.document.write("Decoded Time Permit TP: 0x"+ctx.MPIN.bytestostring(PERMIT) + "<br>");   
+	}
+	else date=0;
+
+	pin=parseInt(mywindow.prompt("Enter PIN= "));
+
+/* 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_T(date|H(CLIENT_ID)))
+Random value x is supplied externally if RNG=null, otherwise generated and passed out by RNG
+
+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=xID;
+	var pxCID=xCID;
+	var pHID=HID;
+	var pHTID=HTID;
+	var pE=E;
+	var pF=F;
+	var pPERMIT=PERMIT;
+	var prHID;
+
+	if (date!=0)
+	{
+		prHID=pHTID;
+		if (!PINERROR)
+		{
+			pxID=null;
+			//	pHID=null;
+		}
+	}
+	else
+	{
+		prHID=pHID;
+		pPERMIT=null;
+		pxCID=null;
+		pHTID=null;
+	}
+	if (!PINERROR)
+	{
+		pE=null;
+		pF=null;
+	}
+
+	if (ONE_PASS)
+	{
+		mywindow.document.write("MPIN Single Pass " + "<br>");   
+		timeValue = ctx.MPIN.GET_TIME();
+		mywindow.document.write("Epoch " + timeValue + "<br>");   
+
+		rtn=ctx.MPIN.CLIENT(sha,date,CLIENT_ID,rng,X,pin,TOKEN,SEC,pxID,pxCID,pPERMIT,timeValue,Y);
+
+		if (rtn != 0)
+		mywindow.document.write("FAILURE: CLIENT rtn: " + rtn + "<br>");   
+
+		if (FULL)
+		{
+			HCID=ctx.MPIN.HASH_ID(sha,CLIENT_ID);
+			ctx.MPIN.GET_G1_MULTIPLE(rng,1,R,HCID,Z);  /* Also Send Z=r.ID to Server, remember random r */
+		}
+
+		rtn=ctx.MPIN.SERVER(sha,date,pHID,pHTID,Y,SST,pxID,pxCID,SEC,pE,pF,CLIENT_ID,timeValue);
+		if (rtn != 0)
+			mywindow.document.write("FAILURE: SERVER rtn: " + rtn+ "<br>");  
+
+		if (FULL)
+		{
+			HSID=ctx.MPIN.HASH_ID(sha,CLIENT_ID);
+			ctx.MPIN.GET_G1_MULTIPLE(rng,0,W,prHID,T);  /* Also send T=w.ID to client, remember random w  */
+		}
+	}
+	else 
+	{
+		mywindow.document.write("MPIN Multi Pass " + "<br>");   
+		rtn=ctx.MPIN.CLIENT_1(sha,date,CLIENT_ID,rng,X,pin,TOKEN,SEC,pxID,pxCID,pPERMIT);
+		if (rtn != 0)
+			mywindow.document.write("FAILURE: CLIENT_1 rtn: " + rtn + "<br>");   
+  
+		if (FULL)
+		{
+			HCID=ctx.MPIN.HASH_ID(sha,CLIENT_ID);
+			ctx.MPIN.GET_G1_MULTIPLE(rng,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. */
+		ctx.MPIN.SERVER_1(sha,date,CLIENT_ID,pHID,pHTID);
+    
+  /* Server generates Random number Y and sends it to Client */
+		ctx.MPIN.RANDOM_GENERATE(rng,Y);
+    
+		if (FULL)
+		{
+			HSID=ctx.MPIN.HASH_ID(sha,CLIENT_ID);
+			ctx.MPIN.GET_G1_MULTIPLE(rng,0,W,prHID,T);  /* Also send T=w.ID to client, remember random w  */
+		}
+    
+  /* Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC */
+		rtn=ctx.MPIN.CLIENT_2(X,Y,SEC);
+		if (rtn != 0)
+			mywindow.document.write("FAILURE: CLIENT_2 rtn: " + rtn + "<br>");  
+  /* 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=ctx.MPIN.SERVER_2(date,pHID,pHTID,Y,SST,pxID,pxCID,SEC,pE,pF);
+    
+		if (rtn != 0)
+			mywindow.document.write("FAILURE: SERVER_2 rtn: " + rtn+ "<br>");  
+    
+	}
+    		  
+
+	if (rtn == ctx.MPIN.BAD_PIN)
+	{
+		mywindow.document.write("Server says - Bad Pin. I don't know you. Feck off." + "<br>"); 
+		if (PINERROR)
+		{
+			var err=ctx.MPIN.KANGAROO(E,F);
+			if (err!=0) mywindow.document.write("(Client PIN is out by "+err + ")<br>");
+		}
+	}
+	else 
+	{
+		mywindow.document.write("Server says - PIN is good! You really are "+IDstr + "<br>"); 
+		if (FULL)
+		{
+			H=ctx.MPIN.HASH_ALL(sha,HCID,pxID,pxCID,SEC,Y,Z,T);
+			ctx.MPIN.CLIENT_KEY(sha,G1,G2,pin,R,X,H,T,CK);
+			
+			mywindow.document.write("Client Key =  0x"+ctx.MPIN.bytestostring(CK) + "<br>");    
+			H=ctx.MPIN.HASH_ALL(sha,HSID,pxID,pxCID,SEC,Y,Z,T);
+			ctx.MPIN.SERVER_KEY(sha,Z,SST,W,H,pHID,pxID,pxCID,SK);
+			mywindow.document.write("Server Key =  0x"+ctx.MPIN.bytestostring(SK) + "<br>");    
+		}
+	}
+
+}
+
+// BLS383 context
+function bls383() {
+	var ctx = new CTX('BLS383');
+	mywindow=window.open();
+
+	mywindow.document.write("<br> BLS383 Pairing-Friendly Curve "+  "<br>");
+
+	var i,res;
+	var result;
+
+	var EGS=ctx.MPIN.EGS;
+	var EFS=ctx.MPIN.EFS;
+	var EAS=ctx.ECP.AESKEY;
+
+	var sha=ctx.ECP.HASH_TYPE;
+
+	var G1S=2*EFS+1; /* Group 1 Size */
+	var G2S=4*EFS; /* Group 2 Size */
+
+	var S=[];
+	var SST=[];
+	var TOKEN = [];
+	var PERMIT = [];
+	var SEC = [];
+	var xID = [];
+	var xCID = [];
+	var X= [];
+	var Y= [];
+	var E=[];
+	var F=[];
+	var HCID=[];
+	var HID=[];
+	var HTID=[];
+
+	var G1=[];
+	var G2=[];
+	var R=[];
+	var Z=[];
+	var W=[];
+	var T=[];
+	var CK=[];
+	var SK=[];
+
+	var HSID=[];
+
+/* Set configuration */
+	var PERMITS=true;
+	var PINERROR=true;
+	var FULL=true;
+    var ONE_PASS=false;
+
+	var RAW=[];
+	var rng=new ctx.RAND();
+
+	rng.clean();
+	for (i=0;i<100;i++) RAW[i]=i;
+
+	rng.seed(100,RAW);
+
+
+/* Trusted Authority set-up */
+	ctx.MPIN.RANDOM_GENERATE(rng,S);
+	mywindow.document.write("M-Pin Master Secret s: 0x"+ctx.MPIN.bytestostring(S) + "<br>");
+ 
+ /* Create Client Identity */
+ 	var IDstr = "testUser@miracl.com";
+	var CLIENT_ID = ctx.MPIN.stringtobytes(IDstr);  
+	HCID=ctx.MPIN.HASH_ID(sha,CLIENT_ID);  /* Either Client or TA calculates Hash(ID) - you decide! */
+		
+	mywindow.document.write("Client ID= "+ctx.MPIN.bytestostring(CLIENT_ID) + "<br>");
+
+/* Client and Server are issued secrets by DTA */
+	ctx.MPIN.GET_SERVER_SECRET(S,SST);
+	mywindow.document.write("Server Secret SS: 0x"+ctx.MPIN.bytestostring(SST) + "<br>");
+
+	ctx.MPIN.GET_CLIENT_SECRET(S,HCID,TOKEN);
+	mywindow.document.write("Client Secret CS: 0x"+ctx.MPIN.bytestostring(TOKEN) + "<br>");     
+	
+/* Client extracts PIN from secret to create Token */
+	var pin=1234;
+	mywindow.document.write("Client extracts PIN= "+pin + "<br>"); 
+	var rtn=ctx.MPIN.EXTRACT_PIN(sha,CLIENT_ID,pin,TOKEN);
+	if (rtn != 0)
+		mywindow.document.write("Failed to extract PIN " + "<br>");  
+
+	mywindow.document.write("Client Token TK: 0x"+ctx.MPIN.bytestostring(TOKEN) + "<br>");        
+
+	if (FULL)
+	{
+		ctx.MPIN.PRECOMPUTE(TOKEN,HCID,G1,G2);
+	}
+
+	var date;
+	if (PERMITS)
+	{
+		date=ctx.MPIN.today();
+/* Client gets "Time Token" permit from DTA */ 	
+		ctx.MPIN.GET_CLIENT_PERMIT(sha,date,S,HCID,PERMIT);
+		mywindow.document.write("Time Permit TP: 0x"+ctx.MPIN.bytestostring(PERMIT) + "<br>");   
+
+/* This encoding makes Time permit look random - Elligator squared */
+		ctx.MPIN.ENCODING(rng,PERMIT);
+		mywindow.document.write("Encoded Time Permit TP: 0x"+ctx.MPIN.bytestostring(PERMIT) + "<br>");   
+		ctx.MPIN.DECODING(PERMIT);
+		mywindow.document.write("Decoded Time Permit TP: 0x"+ctx.MPIN.bytestostring(PERMIT) + "<br>");   
+	}
+	else date=0;
+
+	pin=parseInt(mywindow.prompt("Enter PIN= "));
+
+/* 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_T(date|H(CLIENT_ID)))
+Random value x is supplied externally if RNG=null, otherwise generated and passed out by RNG
+
+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=xID;
+	var pxCID=xCID;
+	var pHID=HID;
+	var pHTID=HTID;
+	var pE=E;
+	var pF=F;
+	var pPERMIT=PERMIT;
+	var prHID;
+
+	if (date!=0)
+	{
+		prHID=pHTID;
+		if (!PINERROR)
+		{
+			pxID=null;
+			//	pHID=null;
+		}
+	}
+	else
+	{
+		prHID=pHID;
+		pPERMIT=null;
+		pxCID=null;
+		pHTID=null;
+	}
+	if (!PINERROR)
+	{
+		pE=null;
+		pF=null;
+	}
+
+	if (ONE_PASS)
+	{
+		mywindow.document.write("MPIN Single Pass " + "<br>");   
+		timeValue = ctx.MPIN.GET_TIME();
+		mywindow.document.write("Epoch " + timeValue + "<br>");   
+
+		rtn=ctx.MPIN.CLIENT(sha,date,CLIENT_ID,rng,X,pin,TOKEN,SEC,pxID,pxCID,pPERMIT,timeValue,Y);
+
+		if (rtn != 0)
+		mywindow.document.write("FAILURE: CLIENT rtn: " + rtn + "<br>");   
+
+		if (FULL)
+		{
+			HCID=ctx.MPIN.HASH_ID(sha,CLIENT_ID);
+			ctx.MPIN.GET_G1_MULTIPLE(rng,1,R,HCID,Z);  /* Also Send Z=r.ID to Server, remember random r */
+		}
+
+		rtn=ctx.MPIN.SERVER(sha,date,pHID,pHTID,Y,SST,pxID,pxCID,SEC,pE,pF,CLIENT_ID,timeValue);
+		if (rtn != 0)
+			mywindow.document.write("FAILURE: SERVER rtn: " + rtn+ "<br>");  
+
+		if (FULL)
+		{
+			HSID=ctx.MPIN.HASH_ID(sha,CLIENT_ID);
+			ctx.MPIN.GET_G1_MULTIPLE(rng,0,W,prHID,T);  /* Also send T=w.ID to client, remember random w  */
+		}
+	}
+	else 
+	{
+		mywindow.document.write("MPIN Multi Pass " + "<br>");   
+		rtn=ctx.MPIN.CLIENT_1(sha,date,CLIENT_ID,rng,X,pin,TOKEN,SEC,pxID,pxCID,pPERMIT);
+		if (rtn != 0)
+			mywindow.document.write("FAILURE: CLIENT_1 rtn: " + rtn + "<br>");   
+  
+		if (FULL)
+		{
+			HCID=ctx.MPIN.HASH_ID(sha,CLIENT_ID);
+			ctx.MPIN.GET_G1_MULTIPLE(rng,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. */
+		ctx.MPIN.SERVER_1(sha,date,CLIENT_ID,pHID,pHTID);
+    
+  /* Server generates Random number Y and sends it to Client */
+		ctx.MPIN.RANDOM_GENERATE(rng,Y);
+    
+		if (FULL)
+		{
+			HSID=ctx.MPIN.HASH_ID(sha,CLIENT_ID);
+			ctx.MPIN.GET_G1_MULTIPLE(rng,0,W,prHID,T);  /* Also send T=w.ID to client, remember random w  */
+		}
+    
+  /* Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC */
+		rtn=ctx.MPIN.CLIENT_2(X,Y,SEC);
+		if (rtn != 0)
+			mywindow.document.write("FAILURE: CLIENT_2 rtn: " + rtn + "<br>");  
+  /* 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=ctx.MPIN.SERVER_2(date,pHID,pHTID,Y,SST,pxID,pxCID,SEC,pE,pF);
+    
+		if (rtn != 0)
+			mywindow.document.write("FAILURE: SERVER_2 rtn: " + rtn+ "<br>");  
+    
+	}
+    		  
+
+	if (rtn == ctx.MPIN.BAD_PIN)
+	{
+		mywindow.document.write("Server says - Bad Pin. I don't know you. Feck off." + "<br>"); 
+		if (PINERROR)
+		{
+			var err=ctx.MPIN.KANGAROO(E,F);
+			if (err!=0) mywindow.document.write("(Client PIN is out by "+err + ")<br>");
+		}
+	}
+	else 
+	{
+		mywindow.document.write("Server says - PIN is good! You really are "+IDstr + "<br>"); 
+		if (FULL)
+		{
+			H=ctx.MPIN.HASH_ALL(sha,HCID,pxID,pxCID,SEC,Y,Z,T);
+			ctx.MPIN.CLIENT_KEY(sha,G1,G2,pin,R,X,H,T,CK);
+			
+			mywindow.document.write("Client Key =  0x"+ctx.MPIN.bytestostring(CK) + "<br>");    
+			H=ctx.MPIN.HASH_ALL(sha,HSID,pxID,pxCID,SEC,Y,Z,T);
+			ctx.MPIN.SERVER_KEY(sha,Z,SST,W,H,pHID,pxID,pxCID,SK);
+			mywindow.document.write("Server Key =  0x"+ctx.MPIN.bytestostring(SK) + "<br>");    
+		}
+	}
+
+}
+
+
+
+// BLS24 context
+function bls24() {
+	var ctx = new CTX('BLS24');
+	mywindow=window.open();
+
+	mywindow.document.write("<br> BLS24 Pairing-Friendly Curve "+  "<br>");
+
+	var i,res;
+	var result;
+
+	var EGS=ctx.MPIN192.EGS;
+	var EFS=ctx.MPIN192.EFS;
+	var EAS=ctx.ECP.AESKEY;
+
+	var sha=ctx.ECP.HASH_TYPE;
+
+	var G1S=2*EFS+1; /* Group 1 Size */
+	var G2S=8*EFS; /* Group 2 Size */   /**/
+
+	var S=[];
+	var SST=[];
+	var TOKEN = [];
+	var PERMIT = [];
+	var SEC = [];
+	var xID = [];
+	var xCID = [];
+	var X= [];
+	var Y= [];
+	var E=[];
+	var F=[];
+	var HCID=[];
+	var HID=[];
+	var HTID=[];
+
+	var G1=[];
+	var G2=[];
+	var R=[];
+	var Z=[];
+	var W=[];
+	var T=[];
+	var CK=[];
+	var SK=[];
+
+	var HSID=[];
+
+/* Set configuration */
+	var PERMITS=true;
+	var PINERROR=true;
+	var FULL=true;
+    var ONE_PASS=false;
+
+	var RAW=[];
+	var rng=new ctx.RAND();
+
+	rng.clean();
+	for (i=0;i<100;i++) RAW[i]=i;
+
+	rng.seed(100,RAW);
+
+/* Trusted Authority set-up */
+	ctx.MPIN192.RANDOM_GENERATE(rng,S);
+	mywindow.document.write("M-Pin Master Secret s: 0x"+ctx.MPIN192.bytestostring(S) + "<br>");
+ 
+ /* Create Client Identity */
+ 	var IDstr = "testUser@miracl.com";
+	var CLIENT_ID = ctx.MPIN192.stringtobytes(IDstr);  
+	HCID=ctx.MPIN192.HASH_ID(sha,CLIENT_ID);  /* Either Client or TA calculates Hash(ID) - you decide! */
+		
+	mywindow.document.write("Client ID= "+ctx.MPIN192.bytestostring(CLIENT_ID) + "<br>");
+
+/* Client and Server are issued secrets by DTA */
+	ctx.MPIN192.GET_SERVER_SECRET(S,SST);
+	mywindow.document.write("Server Secret SS: 0x"+ctx.MPIN192.bytestostring(SST) + "<br>");
+
+	ctx.MPIN192.GET_CLIENT_SECRET(S,HCID,TOKEN);
+	mywindow.document.write("Client Secret CS: 0x"+ctx.MPIN192.bytestostring(TOKEN) + "<br>");     
+	
+/* Client extracts PIN from secret to create Token */
+	var pin=1234;
+	mywindow.document.write("Client extracts PIN= "+pin + "<br>"); 
+	var rtn=ctx.MPIN192.EXTRACT_PIN(sha,CLIENT_ID,pin,TOKEN);
+	if (rtn != 0)
+		mywindow.document.write("Failed to extract PIN " + "<br>");  
+
+	mywindow.document.write("Client Token TK: 0x"+ctx.MPIN192.bytestostring(TOKEN) + "<br>");        
+
+	if (FULL)
+	{
+		ctx.MPIN192.PRECOMPUTE(TOKEN,HCID,G1,G2);
+	}
+
+	var date;
+	if (PERMITS)
+	{
+		date=ctx.MPIN192.today();
+/* Client gets "Time Token" permit from DTA */ 	
+		ctx.MPIN192.GET_CLIENT_PERMIT(sha,date,S,HCID,PERMIT);
+		mywindow.document.write("Time Permit TP: 0x"+ctx.MPIN192.bytestostring(PERMIT) + "<br>");   
+
+/* This encoding makes Time permit look random - Elligator squared */
+		ctx.MPIN192.ENCODING(rng,PERMIT);
+		mywindow.document.write("Encoded Time Permit TP: 0x"+ctx.MPIN192.bytestostring(PERMIT) + "<br>");   
+		ctx.MPIN192.DECODING(PERMIT);
+		mywindow.document.write("Decoded Time Permit TP: 0x"+ctx.MPIN192.bytestostring(PERMIT) + "<br>");   
+	}
+	else date=0;
+
+	pin=parseInt(mywindow.prompt("Enter PIN= "));
+
+/* 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_T(date|H(CLIENT_ID)))
+Random value x is supplied externally if RNG=null, otherwise generated and passed out by RNG
+
+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=xID;
+	var pxCID=xCID;
+	var pHID=HID;
+	var pHTID=HTID;
+	var pE=E;
+	var pF=F;
+	var pPERMIT=PERMIT;
+	var prHID;
+
+	if (date!=0)
+	{
+		prHID=pHTID;
+		if (!PINERROR)
+		{
+			pxID=null;
+			//	pHID=null;
+		}
+	}
+	else
+	{
+		prHID=pHID;
+		pPERMIT=null;
+		pxCID=null;
+		pHTID=null;
+	}
+	if (!PINERROR)
+	{
+		pE=null;
+		pF=null;
+	}
+
+	if (ONE_PASS)
+	{
+		mywindow.document.write("MPIN Single Pass " + "<br>");   
+		timeValue = ctx.MPIN192.GET_TIME();
+		mywindow.document.write("Epoch " + timeValue + "<br>");   
+
+		rtn=ctx.MPIN192.CLIENT(sha,date,CLIENT_ID,rng,X,pin,TOKEN,SEC,pxID,pxCID,pPERMIT,timeValue,Y);
+
+		if (rtn != 0)
+		mywindow.document.write("FAILURE: CLIENT rtn: " + rtn + "<br>");   
+
+		if (FULL)
+		{
+			HCID=ctx.MPIN192.HASH_ID(sha,CLIENT_ID);
+			ctx.MPIN192.GET_G1_MULTIPLE(rng,1,R,HCID,Z);  /* Also Send Z=r.ID to Server, remember random r */
+		}
+
+		rtn=ctx.MPIN192.SERVER(sha,date,pHID,pHTID,Y,SST,pxID,pxCID,SEC,pE,pF,CLIENT_ID,timeValue);
+		if (rtn != 0)
+			mywindow.document.write("FAILURE: SERVER rtn: " + rtn+ "<br>");  
+
+		if (FULL)
+		{
+			HSID=ctx.MPIN192.HASH_ID(sha,CLIENT_ID);
+			ctx.MPIN192.GET_G1_MULTIPLE(rng,0,W,prHID,T);  /* Also send T=w.ID to client, remember random w  */
+		}
+	}
+	else 
+	{
+		mywindow.document.write("MPIN Multi Pass " + "<br>");   
+		rtn=ctx.MPIN192.CLIENT_1(sha,date,CLIENT_ID,rng,X,pin,TOKEN,SEC,pxID,pxCID,pPERMIT);
+		if (rtn != 0)
+			mywindow.document.write("FAILURE: CLIENT_1 rtn: " + rtn + "<br>");   
+  
+		if (FULL)
+		{
+			HCID=ctx.MPIN192.HASH_ID(sha,CLIENT_ID);
+			ctx.MPIN192.GET_G1_MULTIPLE(rng,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. */
+		ctx.MPIN192.SERVER_1(sha,date,CLIENT_ID,pHID,pHTID);
+    
+  /* Server generates Random number Y and sends it to Client */
+		ctx.MPIN192.RANDOM_GENERATE(rng,Y);
+    
+		if (FULL)
+		{
+			HSID=ctx.MPIN192.HASH_ID(sha,CLIENT_ID);
+			ctx.MPIN192.GET_G1_MULTIPLE(rng,0,W,prHID,T);  /* Also send T=w.ID to client, remember random w  */
+		}
+    
+  /* Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC */
+		rtn=ctx.MPIN192.CLIENT_2(X,Y,SEC);
+		if (rtn != 0)
+			mywindow.document.write("FAILURE: CLIENT_2 rtn: " + rtn + "<br>");  
+  /* 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=ctx.MPIN192.SERVER_2(date,pHID,pHTID,Y,SST,pxID,pxCID,SEC,pE,pF);
+    
+		if (rtn != 0)
+			mywindow.document.write("FAILURE: SERVER_2 rtn: " + rtn+ "<br>");  
+    
+	}
+    		  
+
+	if (rtn == ctx.MPIN192.BAD_PIN)
+	{
+		mywindow.document.write("Server says - Bad Pin. I don't know you. Feck off." + "<br>"); 
+		if (PINERROR)
+		{
+			var err=ctx.MPIN192.KANGAROO(E,F);
+			if (err!=0) mywindow.document.write("(Client PIN is out by "+err + ")<br>");
+		}
+	}
+	else 
+	{
+		mywindow.document.write("Server says - PIN is good! You really are "+IDstr + "<br>"); 
+		if (FULL)
+		{
+			H=ctx.MPIN192.HASH_ALL(sha,HCID,pxID,pxCID,SEC,Y,Z,T);
+			ctx.MPIN192.CLIENT_KEY(sha,G1,G2,pin,R,X,H,T,CK);
+			
+			mywindow.document.write("Client Key =  0x"+ctx.MPIN192.bytestostring(CK) + "<br>");    
+			H=ctx.MPIN192.HASH_ALL(sha,HSID,pxID,pxCID,SEC,Y,Z,T);
+			ctx.MPIN192.SERVER_KEY(sha,Z,SST,W,H,pHID,pxID,pxCID,SK);
+			mywindow.document.write("Server Key =  0x"+ctx.MPIN192.bytestostring(SK) + "<br>");    
+		}
+	}
+
+} 
+
+// BLS48 context
+function bls48() {
+	var ctx = new CTX('BLS48');
+	mywindow=window.open();
+
+	mywindow.document.write("<br> BLS48 Pairing-Friendly Curve "+  "<br>");
+
+	var i,res;
+	var result;
+
+	var EGS=ctx.MPIN256.EGS;
+	var EFS=ctx.MPIN256.EFS;
+	var EAS=ctx.ECP.AESKEY;
+
+	var sha=ctx.ECP.HASH_TYPE;
+
+	var G1S=2*EFS+1; // Group 1 Size 
+	var G2S=16*EFS; // Group 2 Size    **
+
+	var S=[];
+	var SST=[];
+	var TOKEN = [];
+	var PERMIT = [];
+	var SEC = [];
+	var xID = [];
+	var xCID = [];
+	var X= [];
+	var Y= [];
+	var E=[];
+	var F=[];
+	var HCID=[];
+	var HID=[];
+	var HTID=[];
+
+	var G1=[];
+	var G2=[];
+	var R=[];
+	var Z=[];
+	var W=[];
+	var T=[];
+	var CK=[];
+	var SK=[];
+
+	var HSID=[];
+
+// Set configuration 
+	var PERMITS=true;
+	var PINERROR=true;
+	var FULL=true;
+    var ONE_PASS=false;
+
+	var RAW=[];
+	var rng=new ctx.RAND();
+
+	rng.clean();
+	for (i=0;i<100;i++) RAW[i]=i;
+
+	rng.seed(100,RAW);
+
+// Trusted Authority set-up 
+	ctx.MPIN256.RANDOM_GENERATE(rng,S);
+
+	mywindow.document.write("M-Pin Master Secret s: 0x"+ctx.MPIN256.bytestostring(S) + "<br>");
+ // Create Client Identity 
+ 	var IDstr = "testUser@miracl.com";
+	var CLIENT_ID = ctx.MPIN256.stringtobytes(IDstr);  
+	HCID=ctx.MPIN256.HASH_ID(sha,CLIENT_ID);  // Either Client or TA calculates Hash(ID) - you decide! 
+		
+	mywindow.document.write("Client ID= "+ctx.MPIN256.bytestostring(CLIENT_ID) + "<br>");
+
+// Client and Server are issued secrets by DTA 
+	ctx.MPIN256.GET_SERVER_SECRET(S,SST);
+	mywindow.document.write("Server Secret SS: 0x"+ctx.MPIN256.bytestostring(SST) + "<br>");
+
+	ctx.MPIN256.GET_CLIENT_SECRET(S,HCID,TOKEN);
+	mywindow.document.write("Client Secret CS: 0x"+ctx.MPIN256.bytestostring(TOKEN) + "<br>");     
+	
+// Client extracts PIN from secret to create Token 
+	var pin=1234;
+	mywindow.document.write("Client extracts PIN= "+pin + "<br>"); 
+	var rtn=ctx.MPIN256.EXTRACT_PIN(sha,CLIENT_ID,pin,TOKEN);
+	if (rtn != 0)
+		mywindow.document.write("Failed to extract PIN " + "<br>");  
+
+	mywindow.document.write("Client Token TK: 0x"+ctx.MPIN256.bytestostring(TOKEN) + "<br>");        
+
+	if (FULL)
+	{
+		ctx.MPIN256.PRECOMPUTE(TOKEN,HCID,G1,G2);
+	}
+
+	var date;
+	if (PERMITS)
+	{
+		date=ctx.MPIN256.today();
+// Client gets "Time Token" permit from DTA  	
+		ctx.MPIN256.GET_CLIENT_PERMIT(sha,date,S,HCID,PERMIT);
+		mywindow.document.write("Time Permit TP: 0x"+ctx.MPIN256.bytestostring(PERMIT) + "<br>");   
+
+// This encoding makes Time permit look random - Elligator squared 
+		ctx.MPIN256.ENCODING(rng,PERMIT);
+		mywindow.document.write("Encoded Time Permit TP: 0x"+ctx.MPIN256.bytestostring(PERMIT) + "<br>");   
+		ctx.MPIN256.DECODING(PERMIT);
+		mywindow.document.write("Decoded Time Permit TP: 0x"+ctx.MPIN256.bytestostring(PERMIT) + "<br>");   
+	}
+	else date=0;
+
+	pin=parseInt(mywindow.prompt("Enter PIN= "));
+
+// 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_T(date|H(CLIENT_ID)))
+//Random value x is supplied externally if RNG=null, otherwise generated and passed out by RNG
+
+//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=xID;
+	var pxCID=xCID;
+	var pHID=HID;
+	var pHTID=HTID;
+	var pE=E;
+	var pF=F;
+	var pPERMIT=PERMIT;
+	var prHID;
+
+	if (date!=0)
+	{
+		prHID=pHTID;
+		if (!PINERROR)
+		{
+			pxID=null;
+			//	pHID=null;
+		}
+	}
+	else
+	{
+		prHID=pHID;
+		pPERMIT=null;
+		pxCID=null;
+		pHTID=null;
+	}
+	if (!PINERROR)
+	{
+		pE=null;
+		pF=null;
+	}
+
+	if (ONE_PASS)
+	{
+		mywindow.document.write("MPIN Single Pass " + "<br>");   
+		timeValue = ctx.MPIN256.GET_TIME();
+		mywindow.document.write("Epoch " + timeValue + "<br>");   
+
+		rtn=ctx.MPIN256.CLIENT(sha,date,CLIENT_ID,rng,X,pin,TOKEN,SEC,pxID,pxCID,pPERMIT,timeValue,Y);
+
+		if (rtn != 0)
+		mywindow.document.write("FAILURE: CLIENT rtn: " + rtn + "<br>");   
+
+		if (FULL)
+		{
+			HCID=ctx.MPIN256.HASH_ID(sha,CLIENT_ID);
+			ctx.MPIN256.GET_G1_MULTIPLE(rng,1,R,HCID,Z);  // Also Send Z=r.ID to Server, remember random r 
+		}
+
+		rtn=ctx.MPIN256.SERVER(sha,date,pHID,pHTID,Y,SST,pxID,pxCID,SEC,pE,pF,CLIENT_ID,timeValue);
+		if (rtn != 0)
+			mywindow.document.write("FAILURE: SERVER rtn: " + rtn+ "<br>");  
+
+		if (FULL)
+		{
+			HSID=ctx.MPIN256.HASH_ID(sha,CLIENT_ID);
+			ctx.MPIN256.GET_G1_MULTIPLE(rng,0,W,prHID,T);  // Also send T=w.ID to client, remember random w  
+		}
+	}
+	else 
+	{
+		mywindow.document.write("MPIN Multi Pass " + "<br>");   
+		rtn=ctx.MPIN256.CLIENT_1(sha,date,CLIENT_ID,rng,X,pin,TOKEN,SEC,pxID,pxCID,pPERMIT);
+		if (rtn != 0)
+			mywindow.document.write("FAILURE: CLIENT_1 rtn: " + rtn + "<br>");   
+  
+		if (FULL)
+		{
+			HCID=ctx.MPIN256.HASH_ID(sha,CLIENT_ID);
+			ctx.MPIN256.GET_G1_MULTIPLE(rng,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. 
+		ctx.MPIN256.SERVER_1(sha,date,CLIENT_ID,pHID,pHTID);
+    
+  // Server generates Random number Y and sends it to Client 
+		ctx.MPIN256.RANDOM_GENERATE(rng,Y);
+    
+		if (FULL)
+		{
+			HSID=ctx.MPIN256.HASH_ID(sha,CLIENT_ID);
+			ctx.MPIN256.GET_G1_MULTIPLE(rng,0,W,prHID,T);  // Also send T=w.ID to client, remember random w  
+		}
+    
+  // Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC 
+		rtn=ctx.MPIN256.CLIENT_2(X,Y,SEC);
+		if (rtn != 0)
+			mywindow.document.write("FAILURE: CLIENT_2 rtn: " + rtn + "<br>");  
+  // 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=ctx.MPIN256.SERVER_2(date,pHID,pHTID,Y,SST,pxID,pxCID,SEC,pE,pF);
+    
+		if (rtn != 0)
+			mywindow.document.write("FAILURE: SERVER_2 rtn: " + rtn+ "<br>");  
+    
+	}
+    		  
+
+	if (rtn == ctx.MPIN256.BAD_PIN)
+	{
+		mywindow.document.write("Server says - Bad Pin. I don't know you. Feck off." + "<br>"); 
+		if (PINERROR)
+		{
+			var err=ctx.MPIN256.KANGAROO(E,F);
+			if (err!=0) mywindow.document.write("(Client PIN is out by "+err + ")<br>");
+		}
+	}
+	else 
+	{
+		mywindow.document.write("Server says - PIN is good! You really are "+IDstr + "<br>"); 
+		if (FULL)
+		{
+			H=ctx.MPIN256.HASH_ALL(sha,HCID,pxID,pxCID,SEC,Y,Z,T);
+			ctx.MPIN256.CLIENT_KEY(sha,G1,G2,pin,R,X,H,T,CK);
+			
+			mywindow.document.write("Client Key =  0x"+ctx.MPIN256.bytestostring(CK) + "<br>");    
+			H=ctx.MPIN256.HASH_ALL(sha,HSID,pxID,pxCID,SEC,Y,Z,T);
+			ctx.MPIN256.SERVER_KEY(sha,Z,SST,W,H,pHID,pxID,pxCID,SK);
+			mywindow.document.write("Server Key =  0x"+ctx.MPIN256.bytestostring(SK) + "<br>");    
+		}
+	}
+
+}
+
+
+//bls48();
+//bls24();
+//bls383();
+//bn254();
+//goldilocks();
+//nist256();
+//ed25519();
+//rsa2048();
+
+</script>
+</body>
+</html>
diff --git a/version3/js/TestNHS.html b/version3/js/TestNHS.html
new file mode 100644
index 0000000..1353186
--- /dev/null
+++ b/version3/js/TestNHS.html
@@ -0,0 +1,56 @@
+
+
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>JavaScript Test NHS</title>
+</head>
+<body>
+<h1>JavaScript Test NHS</h1>
+<script type="text/javascript"src=./rand.js></script>
+<script type="text/javascript"src=./uint64.js></script>
+<script type="text/javascript"src=./aes.js></script>
+<script type="text/javascript"src=./big.js></script>
+<script type="text/javascript"src=./gcm.js></script>
+<script type="text/javascript"src=./hash256.js></script>
+<script type="text/javascript"src=./hash384.js></script>
+<script type="text/javascript"src=./hash512.js></script>
+<script type="text/javascript"src=./sha3.js></script>
+<script type="text/javascript"src=./nhs.js></script>
+<script type="text/javascript"src=./ctx.js></script>
+
+<script>
+
+// Test NewHope Simple 
+// See https://eprint.iacr.org/2016/1157 (Alkim, Ducas, Popplemann and Schwabe)
+
+	var ctx = new CTX();
+
+	var RAW=[];
+	var srng=new ctx.RAND(); srng.clean();
+								var crng=new ctx.RAND(); crng.clean(); 
+
+	for (i=0;i<100;i++) RAW[i]=i+1;
+	srng.seed(100,RAW);
+
+								for (i=0;i<100;i++) RAW[i]=i+2;
+								crng.seed(100,RAW);
+	var S=[];
+								var SB=[];
+								var UC=[];
+	var KEYA=[];
+								var KEYB=[];
+
+	ctx.NHS.SERVER_1(srng,SB,S);
+
+								ctx.NHS.CLIENT(crng,SB,UC,KEYB);
+
+	ctx.NHS.SERVER_2(S,UC,KEYA);
+
+	window.document.write("Alice Key= 0x"+ctx.NHS.bytestostring(KEYA)+ "<br>");
+	window.document.write("Bob's Key= 0x"+ctx.NHS.bytestostring(KEYB)+ "<br>");
+
+
+</script>
+</body>
+</html>
diff --git a/version3/js/aes.js b/version3/js/aes.js
new file mode 100644
index 0000000..59a53dc
--- /dev/null
+++ b/version3/js/aes.js
@@ -0,0 +1,705 @@
+/*
+    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.
+*/
+
+var AES = function() {
+    "use strict";
+
+    var AES = function() {
+        this.Nk = 0;
+        this.Nr = 0;
+        this.mode = 0;
+        this.fkey = [];
+        this.rkey = [];
+        this.f = [];
+    };
+
+    // AES constants
+    AES.ECB = 0;
+    AES.CBC = 1;
+    AES.CFB1 = 2;
+    AES.CFB2 = 3;
+    AES.CFB4 = 5;
+    AES.OFB1 = 14;
+    AES.OFB2 = 15;
+    AES.OFB4 = 17;
+    AES.OFB8 = 21;
+    AES.OFB16 = 29;
+    AES.CTR1 = 30;
+    AES.CTR2 = 31;
+    AES.CTR4 = 33;
+    AES.CTR8 = 37;
+    AES.CTR16 = 45;
+
+    AES.prototype = {
+        /* reset cipher */
+        reset: function(m, iv) { /* reset mode, or reset iv */
+            var i;
+
+            this.mode = m;
+
+            for (i = 0; i < 16; i++) {
+                this.f[i] = 0;
+            }
+
+            if (this.mode != AES.ECB && iv !== null) {
+                for (i = 0; i < 16; i++) {
+                    this.f[i] = iv[i];
+                }
+            }
+        },
+
+        getreg: function() {
+            var ir = [],
+                i;
+
+            for (i = 0; i < 16; i++) {
+                ir[i] = this.f[i];
+            }
+
+            return ir;
+        },
+
+        increment: function() {
+            var i;
+
+            for (i = 0; i < 16; i++) {
+                this.f[i]++;
+
+                if ((this.f[i] & 0xff) != 0) {
+                    break;
+                }
+            }
+        },
+
+        /* Initialise cipher */
+        init: function(m, nk, key, iv) { /* Key=16 bytes */
+            /* Key Scheduler. Create expanded encryption key */
+            var CipherKey = [],
+                b = [],
+                i, j, k, N, nr;
+
+            nk /= 4;
+
+            if (nk != 4 && nk != 6 && nk != 8) {
+                return false;
+            }
+
+            nr = 6 + nk;
+
+            this.Nk = nk;
+            this.Nr = nr;
+
+
+            this.reset(m, iv);
+            N = 4 * (nr + 1);
+
+            for (i = j = 0; i < nk; i++, j += 4) {
+                for (k = 0; k < 4; k++) {
+                    b[k] = key[j + k];
+                }
+                CipherKey[i] = AES.pack(b);
+            }
+
+            for (i = 0; i < nk; i++) {
+                this.fkey[i] = CipherKey[i];
+            }
+
+            for (j = nk, k = 0; j < N; j += nk, k++) {
+                this.fkey[j] = this.fkey[j - nk] ^ AES.SubByte(AES.ROTL24(this.fkey[j - 1])) ^ (AES.rco[k]) & 0xff;
+                for (i = 1; i < nk && (i + j) < N; i++) {
+                    this.fkey[i + j] = this.fkey[i + j - nk] ^ this.fkey[i + j - 1];
+                }
+            }
+
+            /* now for the expanded decrypt key in reverse order */
+
+            for (j = 0; j < 4; j++) {
+                this.rkey[j + N - 4] = this.fkey[j];
+            }
+
+            for (i = 4; i < N - 4; i += 4) {
+                k = N - 4 - i;
+                for (j = 0; j < 4; j++) {
+                    this.rkey[k + j] = AES.InvMixCol(this.fkey[i + j]);
+                }
+            }
+
+            for (j = N - 4; j < N; j++) {
+                this.rkey[j - N + 4] = this.fkey[j];
+            }
+        },
+
+        /* Encrypt a single block */
+        ecb_encrypt: function(buff) {
+            var b = [],
+                p = [],
+                q = [],
+                t, i, j, k;
+
+            for (i = j = 0; i < 4; i++, j += 4) {
+                for (k = 0; k < 4; k++) {
+                    b[k] = buff[j + k];
+                }
+                p[i] = AES.pack(b);
+                p[i] ^= this.fkey[i];
+            }
+
+            k = 4;
+
+            /* State alternates between p and q */
+            for (i = 1; i < this.Nr; i++) {
+                q[0] = this.fkey[k] ^ AES.ftable[p[0] & 0xff] ^
+                    AES.ROTL8(AES.ftable[(p[1] >>> 8) & 0xff]) ^
+                    AES.ROTL16(AES.ftable[(p[2] >>> 16) & 0xff]) ^
+                    AES.ROTL24(AES.ftable[(p[3] >>> 24) & 0xff]);
+                q[1] = this.fkey[k + 1] ^ AES.ftable[p[1] & 0xff] ^
+                    AES.ROTL8(AES.ftable[(p[2] >>> 8) & 0xff]) ^
+                    AES.ROTL16(AES.ftable[(p[3] >>> 16) & 0xff]) ^
+                    AES.ROTL24(AES.ftable[(p[0] >>> 24) & 0xff]);
+                q[2] = this.fkey[k + 2] ^ AES.ftable[p[2] & 0xff] ^
+                    AES.ROTL8(AES.ftable[(p[3] >>> 8) & 0xff]) ^
+                    AES.ROTL16(AES.ftable[(p[0] >>> 16) & 0xff]) ^
+                    AES.ROTL24(AES.ftable[(p[1] >>> 24) & 0xff]);
+                q[3] = this.fkey[k + 3] ^ AES.ftable[p[3] & 0xff] ^
+                    AES.ROTL8(AES.ftable[(p[0] >>> 8) & 0xff]) ^
+                    AES.ROTL16(AES.ftable[(p[1] >>> 16) & 0xff]) ^
+                    AES.ROTL24(AES.ftable[(p[2] >>> 24) & 0xff]);
+
+                k += 4;
+                for (j = 0; j < 4; j++) {
+                    t = p[j];
+                    p[j] = q[j];
+                    q[j] = t;
+                }
+            }
+
+            /* Last Round */
+
+            q[0] = this.fkey[k] ^ (AES.fbsub[p[0] & 0xff] & 0xff) ^
+                AES.ROTL8(AES.fbsub[(p[1] >>> 8) & 0xff] & 0xff) ^
+                AES.ROTL16(AES.fbsub[(p[2] >>> 16) & 0xff] & 0xff) ^
+                AES.ROTL24(AES.fbsub[(p[3] >>> 24) & 0xff] & 0xff);
+
+            q[1] = this.fkey[k + 1] ^ (AES.fbsub[p[1] & 0xff] & 0xff) ^
+                AES.ROTL8(AES.fbsub[(p[2] >>> 8) & 0xff] & 0xff) ^
+                AES.ROTL16(AES.fbsub[(p[3] >>> 16) & 0xff] & 0xff) ^
+                AES.ROTL24(AES.fbsub[(p[0] >>> 24) & 0xff] & 0xff);
+
+            q[2] = this.fkey[k + 2] ^ (AES.fbsub[p[2] & 0xff] & 0xff) ^
+                AES.ROTL8(AES.fbsub[(p[3] >>> 8) & 0xff] & 0xff) ^
+                AES.ROTL16(AES.fbsub[(p[0] >>> 16) & 0xff] & 0xff) ^
+                AES.ROTL24(AES.fbsub[(p[1] >>> 24) & 0xff] & 0xff);
+
+            q[3] = this.fkey[k + 3] ^ (AES.fbsub[(p[3]) & 0xff] & 0xff) ^
+                AES.ROTL8(AES.fbsub[(p[0] >>> 8) & 0xff] & 0xff) ^
+                AES.ROTL16(AES.fbsub[(p[1] >>> 16) & 0xff] & 0xff) ^
+                AES.ROTL24(AES.fbsub[(p[2] >>> 24) & 0xff] & 0xff);
+
+            for (i = j = 0; i < 4; i++, j += 4) {
+                b = AES.unpack(q[i]);
+                for (k = 0; k < 4; k++) {
+                    buff[j + k] = b[k];
+                }
+            }
+        },
+
+        /* Decrypt a single block */
+        ecb_decrypt: function(buff) {
+            var b = [],
+                p = [],
+                q = [],
+                t, i, j, k;
+
+            for (i = j = 0; i < 4; i++, j += 4) {
+                for (k = 0; k < 4; k++) {
+                    b[k] = buff[j + k];
+                }
+                p[i] = AES.pack(b);
+                p[i] ^= this.rkey[i];
+            }
+
+            k = 4;
+
+            /* State alternates between p and q */
+            for (i = 1; i < this.Nr; i++) {
+                q[0] = this.rkey[k] ^ AES.rtable[p[0] & 0xff] ^
+                    AES.ROTL8(AES.rtable[(p[3] >>> 8) & 0xff]) ^
+                    AES.ROTL16(AES.rtable[(p[2] >>> 16) & 0xff]) ^
+                    AES.ROTL24(AES.rtable[(p[1] >>> 24) & 0xff]);
+                q[1] = this.rkey[k + 1] ^ AES.rtable[p[1] & 0xff] ^
+                    AES.ROTL8(AES.rtable[(p[0] >>> 8) & 0xff]) ^
+                    AES.ROTL16(AES.rtable[(p[3] >>> 16) & 0xff]) ^
+                    AES.ROTL24(AES.rtable[(p[2] >>> 24) & 0xff]);
+                q[2] = this.rkey[k + 2] ^ AES.rtable[p[2] & 0xff] ^
+                    AES.ROTL8(AES.rtable[(p[1] >>> 8) & 0xff]) ^
+                    AES.ROTL16(AES.rtable[(p[0] >>> 16) & 0xff]) ^
+                    AES.ROTL24(AES.rtable[(p[3] >>> 24) & 0xff]);
+                q[3] = this.rkey[k + 3] ^ AES.rtable[p[3] & 0xff] ^
+                    AES.ROTL8(AES.rtable[(p[2] >>> 8) & 0xff]) ^
+                    AES.ROTL16(AES.rtable[(p[1] >>> 16) & 0xff]) ^
+                    AES.ROTL24(AES.rtable[(p[0] >>> 24) & 0xff]);
+
+                k += 4;
+
+                for (j = 0; j < 4; j++) {
+                    t = p[j];
+                    p[j] = q[j];
+                    q[j] = t;
+                }
+            }
+
+            /* Last Round */
+
+            q[0] = this.rkey[k] ^ (AES.rbsub[p[0] & 0xff] & 0xff) ^
+                AES.ROTL8(AES.rbsub[(p[3] >>> 8) & 0xff] & 0xff) ^
+                AES.ROTL16(AES.rbsub[(p[2] >>> 16) & 0xff] & 0xff) ^
+                AES.ROTL24(AES.rbsub[(p[1] >>> 24) & 0xff] & 0xff);
+            q[1] = this.rkey[k + 1] ^ (AES.rbsub[p[1] & 0xff] & 0xff) ^
+                AES.ROTL8(AES.rbsub[(p[0] >>> 8) & 0xff] & 0xff) ^
+                AES.ROTL16(AES.rbsub[(p[3] >>> 16) & 0xff] & 0xff) ^
+                AES.ROTL24(AES.rbsub[(p[2] >>> 24) & 0xff] & 0xff);
+            q[2] = this.rkey[k + 2] ^ (AES.rbsub[p[2] & 0xff] & 0xff) ^
+                AES.ROTL8(AES.rbsub[(p[1] >>> 8) & 0xff] & 0xff) ^
+                AES.ROTL16(AES.rbsub[(p[0] >>> 16) & 0xff] & 0xff) ^
+                AES.ROTL24(AES.rbsub[(p[3] >>> 24) & 0xff] & 0xff);
+            q[3] = this.rkey[k + 3] ^ (AES.rbsub[p[3] & 0xff] & 0xff) ^
+                AES.ROTL8(AES.rbsub[(p[2] >>> 8) & 0xff] & 0xff) ^
+                AES.ROTL16(AES.rbsub[(p[1] >>> 16) & 0xff] & 0xff) ^
+                AES.ROTL24(AES.rbsub[(p[0] >>> 24) & 0xff] & 0xff);
+
+            for (i = j = 0; i < 4; i++, j += 4) {
+                b = AES.unpack(q[i]);
+                for (k = 0; k < 4; k++) {
+                    buff[j + k] = b[k];
+                }
+            }
+
+        },
+
+        /* Encrypt using selected mode of operation */
+        encrypt: function(buff) {
+            var st = [],
+                bytes, fell_off, j;
+
+            // Supported Modes of Operation
+
+            fell_off = 0;
+
+            switch (this.mode) {
+                case AES.ECB:
+                    this.ecb_encrypt(buff);
+                    return 0;
+
+                case AES.CBC:
+                    for (j = 0; j < 16; j++) {
+                        buff[j] ^= this.f[j];
+                    }
+                    this.ecb_encrypt(buff);
+                    for (j = 0; j < 16; j++) {
+                        this.f[j] = buff[j];
+                    }
+                    return 0;
+
+                case AES.CFB1:
+                case AES.CFB2:
+                case AES.CFB4:
+                    bytes = this.mode - AES.CFB1 + 1;
+                    for (j = 0; j < bytes; j++) {
+                        fell_off = (fell_off << 8) | this.f[j];
+                    }
+                    for (j = 0; j < 16; j++) {
+                        st[j] = this.f[j];
+                    }
+                    for (j = bytes; j < 16; j++) {
+                        this.f[j - bytes] = this.f[j];
+                    }
+                    this.ecb_encrypt(st);
+                    for (j = 0; j < bytes; j++) {
+                        buff[j] ^= st[j];
+                        this.f[16 - bytes + j] = buff[j];
+                    }
+                    return fell_off;
+
+                case AES.OFB1:
+                case AES.OFB2:
+                case AES.OFB4:
+                case AES.OFB8:
+                case AES.OFB16:
+                    bytes = this.mode - AES.OFB1 + 1;
+                    this.ecb_encrypt(this.f);
+                    for (j = 0; j < bytes; j++) {
+                        buff[j] ^= this.f[j];
+                    }
+                    return 0;
+
+                case AES.CTR1:
+                case AES.CTR2:
+                case AES.CTR4:
+                case AES.CTR8:
+                case AES.CTR16:
+                    bytes = this.mode - AES.CTR1 + 1;
+                    for (j = 0; j < 16; j++) {
+                        st[j] = this.f[j];
+                    }
+                    this.ecb_encrypt(st);
+                    for (j = 0; j < bytes; j++) {
+                        buff[j] ^= st[j];
+                    }
+                    this.increment();
+                    return 0;
+
+                default:
+                    return 0;
+            }
+        },
+
+        /* Decrypt using selected mode of operation */
+        decrypt: function(buff) {
+            var st = [],
+                bytes,fell_off, j;
+
+            // Supported modes of operation
+            fell_off = 0;
+            switch (this.mode) {
+                case AES.ECB:
+                    this.ecb_decrypt(buff);
+                    return 0;
+
+                case AES.CBC:
+                    for (j = 0; j < 16; j++) {
+                        st[j] = this.f[j];
+                        this.f[j] = buff[j];
+                    }
+                    this.ecb_decrypt(buff);
+                    for (j = 0; j < 16; j++) {
+                        buff[j] ^= st[j];
+                        st[j] = 0;
+                    }
+                    return 0;
+
+                case AES.CFB1:
+                case AES.CFB2:
+                case AES.CFB4:
+                    bytes = this.mode - AES.CFB1 + 1;
+                    for (j = 0; j < bytes; j++) {
+                        fell_off = (fell_off << 8) | this.f[j];
+                    }
+                    for (j = 0; j < 16; j++) {
+                        st[j] = this.f[j];
+                    }
+                    for (j = bytes; j < 16; j++) {
+                        this.f[j - bytes] = this.f[j];
+                    }
+                    this.ecb_encrypt(st);
+                    for (j = 0; j < bytes; j++) {
+                        this.f[16 - bytes + j] = buff[j];
+                        buff[j] ^= st[j];
+                    }
+                    return fell_off;
+
+                case AES.OFB1:
+                case AES.OFB2:
+                case AES.OFB4:
+                case AES.OFB8:
+                case AES.OFB16:
+                    bytes = this.mode - AES.OFB1 + 1;
+                    this.ecb_encrypt(this.f);
+                    for (j = 0; j < bytes; j++) {
+                        buff[j] ^= this.f[j];
+                    }
+                    return 0;
+
+                case AES.CTR1:
+                case AES.CTR2:
+                case AES.CTR4:
+                case AES.CTR8:
+                case AES.CTR16:
+                    bytes = this.mode - AES.CTR1 + 1;
+                    for (j = 0; j < 16; j++) {
+                        st[j] = this.f[j];
+                    }
+                    this.ecb_encrypt(st);
+                    for (j = 0; j < bytes; j++) {
+                        buff[j] ^= st[j];
+                    }
+                    this.increment();
+                    return 0;
+
+                default:
+                    return 0;
+            }
+        },
+
+        /* Clean up and delete left-overs */
+        end: function() { // clean up
+            var i;
+
+            for (i = 0; i < 4 * (this.Nr + 1); i++) {
+                this.fkey[i] = this.rkey[i] = 0;
+            }
+
+            for (i = 0; i < 16; i++) {
+                this.f[i] = 0;
+            }
+        }
+    };
+
+    /* static functions */
+
+    AES.ROTL8 = function(x) {
+        return (((x) << 8) | ((x) >>> 24));
+    };
+
+    AES.ROTL16 = function(x) {
+        return (((x) << 16) | ((x) >>> 16));
+    };
+
+    AES.ROTL24 = function(x) {
+        return (((x) << 24) | ((x) >>> 8));
+    };
+
+    AES.pack = function(b) { /* pack 4 bytes into a 32-bit Word */
+        return (((b[3]) & 0xff) << 24) | ((b[2] & 0xff) << 16) | ((b[1] & 0xff) << 8) | (b[0] & 0xff);
+    };
+
+    AES.unpack = function(a) { /* unpack bytes from a word */
+        var b = [];
+        b[0] = (a & 0xff);
+        b[1] = ((a >>> 8) & 0xff);
+        b[2] = ((a >>> 16) & 0xff);
+        b[3] = ((a >>> 24) & 0xff);
+        return b;
+    };
+
+    AES.bmul = function(x, y) { /* x.y= AntiLog(Log(x) + Log(y)) */
+        var ix = (x & 0xff),
+            iy = (y & 0xff),
+            lx = (AES.ltab[ix]) & 0xff,
+            ly = (AES.ltab[iy]) & 0xff;
+
+        if (x !== 0 && y !== 0) {
+            return AES.ptab[(lx + ly) % 255];
+        } else {
+            return 0;
+        }
+    };
+
+    //  if (x && y)
+
+    AES.SubByte = function(a) {
+        var b = AES.unpack(a);
+        b[0] = AES.fbsub[b[0] & 0xff];
+        b[1] = AES.fbsub[b[1] & 0xff];
+        b[2] = AES.fbsub[b[2] & 0xff];
+        b[3] = AES.fbsub[b[3] & 0xff];
+        return AES.pack(b);
+    };
+
+    AES.product = function(x, y) { /* dot product of two 4-byte arrays */
+        var xb = AES.unpack(x),
+            yb = AES.unpack(y);
+
+        return (AES.bmul(xb[0], yb[0]) ^ AES.bmul(xb[1], yb[1]) ^ AES.bmul(xb[2], yb[2]) ^ AES.bmul(xb[3], yb[3])) & 0xff;
+    };
+
+    AES.InvMixCol = function(x) { /* matrix Multiplication */
+        var b = [],
+            y, m;
+
+        m = AES.pack(AES.InCo);
+        b[3] = AES.product(m, x);
+        m = AES.ROTL24(m);
+        b[2] = AES.product(m, x);
+        m = AES.ROTL24(m);
+        b[1] = AES.product(m, x);
+        m = AES.ROTL24(m);
+        b[0] = AES.product(m, x);
+        y = AES.pack(b);
+
+        return y;
+    };
+
+    AES.InCo = [0xB, 0xD, 0x9, 0xE]; /* Inverse Coefficients */
+    AES.rco = [1, 2, 4, 8, 16, 32, 64, 128, 27, 54, 108, 216, 171, 77, 154, 47];
+
+    AES.ptab = [
+        1, 3, 5, 15, 17, 51, 85, 255, 26, 46, 114, 150, 161, 248, 19, 53,
+        95, 225, 56, 72, 216, 115, 149, 164, 247, 2, 6, 10, 30, 34, 102, 170,
+        229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217, 112, 144, 171, 230, 49,
+        83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104, 184, 211, 110, 178, 205,
+        76, 212, 103, 169, 224, 59, 77, 215, 98, 166, 241, 8, 24, 40, 120, 136,
+        131, 158, 185, 208, 107, 189, 220, 127, 129, 152, 179, 206, 73, 219, 118, 154,
+        181, 196, 87, 249, 16, 48, 80, 240, 11, 29, 39, 105, 187, 214, 97, 163,
+        254, 25, 43, 125, 135, 146, 173, 236, 47, 113, 147, 174, 233, 32, 96, 160,
+        251, 22, 58, 78, 210, 109, 183, 194, 93, 231, 50, 86, 250, 21, 63, 65,
+        195, 94, 226, 61, 71, 201, 64, 192, 91, 237, 44, 116, 156, 191, 218, 117,
+        159, 186, 213, 100, 172, 239, 42, 126, 130, 157, 188, 223, 122, 142, 137, 128,
+        155, 182, 193, 88, 232, 35, 101, 175, 234, 37, 111, 177, 200, 67, 197, 84,
+        252, 31, 33, 99, 165, 244, 7, 9, 27, 45, 119, 153, 176, 203, 70, 202,
+        69, 207, 74, 222, 121, 139, 134, 145, 168, 227, 62, 66, 198, 81, 243, 14,
+        18, 54, 90, 238, 41, 123, 141, 140, 143, 138, 133, 148, 167, 242, 13, 23,
+        57, 75, 221, 124, 132, 151, 162, 253, 28, 36, 108, 180, 199, 82, 246, 1
+    ];
+    AES.ltab = [
+        0, 255, 25, 1, 50, 2, 26, 198, 75, 199, 27, 104, 51, 238, 223, 3,
+        100, 4, 224, 14, 52, 141, 129, 239, 76, 113, 8, 200, 248, 105, 28, 193,
+        125, 194, 29, 181, 249, 185, 39, 106, 77, 228, 166, 114, 154, 201, 9, 120,
+        101, 47, 138, 5, 33, 15, 225, 36, 18, 240, 130, 69, 53, 147, 218, 142,
+        150, 143, 219, 189, 54, 208, 206, 148, 19, 92, 210, 241, 64, 70, 131, 56,
+        102, 221, 253, 48, 191, 6, 139, 98, 179, 37, 226, 152, 34, 136, 145, 16,
+        126, 110, 72, 195, 163, 182, 30, 66, 58, 107, 40, 84, 250, 133, 61, 186,
+        43, 121, 10, 21, 155, 159, 94, 202, 78, 212, 172, 229, 243, 115, 167, 87,
+        175, 88, 168, 80, 244, 234, 214, 116, 79, 174, 233, 213, 231, 230, 173, 232,
+        44, 215, 117, 122, 235, 22, 11, 245, 89, 203, 95, 176, 156, 169, 81, 160,
+        127, 12, 246, 111, 23, 196, 73, 236, 216, 67, 31, 45, 164, 118, 123, 183,
+        204, 187, 62, 90, 251, 96, 177, 134, 59, 82, 161, 108, 170, 85, 41, 157,
+        151, 178, 135, 144, 97, 190, 220, 252, 188, 149, 207, 205, 55, 63, 91, 209,
+        83, 57, 132, 60, 65, 162, 109, 71, 20, 42, 158, 93, 86, 242, 211, 171,
+        68, 17, 146, 217, 35, 32, 46, 137, 180, 124, 184, 38, 119, 153, 227, 165,
+        103, 74, 237, 222, 197, 49, 254, 24, 13, 99, 140, 128, 192, 247, 112, 7
+    ];
+    AES.fbsub = [
+        99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118,
+        202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192,
+        183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21,
+        4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117,
+        9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132,
+        83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207,
+        208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168,
+        81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210,
+        205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115,
+        96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219,
+        224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121,
+        231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8,
+        186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138,
+        112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158,
+        225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223,
+        140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22
+    ];
+    AES.rbsub = [
+        82, 9, 106, 213, 48, 54, 165, 56, 191, 64, 163, 158, 129, 243, 215, 251,
+        124, 227, 57, 130, 155, 47, 255, 135, 52, 142, 67, 68, 196, 222, 233, 203,
+        84, 123, 148, 50, 166, 194, 35, 61, 238, 76, 149, 11, 66, 250, 195, 78,
+        8, 46, 161, 102, 40, 217, 36, 178, 118, 91, 162, 73, 109, 139, 209, 37,
+        114, 248, 246, 100, 134, 104, 152, 22, 212, 164, 92, 204, 93, 101, 182, 146,
+        108, 112, 72, 80, 253, 237, 185, 218, 94, 21, 70, 87, 167, 141, 157, 132,
+        144, 216, 171, 0, 140, 188, 211, 10, 247, 228, 88, 5, 184, 179, 69, 6,
+        208, 44, 30, 143, 202, 63, 15, 2, 193, 175, 189, 3, 1, 19, 138, 107,
+        58, 145, 17, 65, 79, 103, 220, 234, 151, 242, 207, 206, 240, 180, 230, 115,
+        150, 172, 116, 34, 231, 173, 53, 133, 226, 249, 55, 232, 28, 117, 223, 110,
+        71, 241, 26, 113, 29, 41, 197, 137, 111, 183, 98, 14, 170, 24, 190, 27,
+        252, 86, 62, 75, 198, 210, 121, 32, 154, 219, 192, 254, 120, 205, 90, 244,
+        31, 221, 168, 51, 136, 7, 199, 49, 177, 18, 16, 89, 39, 128, 236, 95,
+        96, 81, 127, 169, 25, 181, 74, 13, 45, 229, 122, 159, 147, 201, 156, 239,
+        160, 224, 59, 77, 174, 42, 245, 176, 200, 235, 187, 60, 131, 83, 153, 97,
+        23, 43, 4, 126, 186, 119, 214, 38, 225, 105, 20, 99, 85, 33, 12, 125
+    ];
+    AES.ftable = [
+        0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, 0xdf2f2ff, 0xbd6b6bd6,
+        0xb16f6fde, 0x54c5c591, 0x50303060, 0x3010102, 0xa96767ce, 0x7d2b2b56,
+        0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec, 0x45caca8f, 0x9d82821f,
+        0x40c9c989, 0x877d7dfa, 0x15fafaef, 0xeb5959b2, 0xc947478e, 0xbf0f0fb,
+        0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45, 0xbf9c9c23, 0xf7a4a453,
+        0x967272e4, 0x5bc0c09b, 0xc2b7b775, 0x1cfdfde1, 0xae93933d, 0x6a26264c,
+        0x5a36366c, 0x413f3f7e, 0x2f7f7f5, 0x4fcccc83, 0x5c343468, 0xf4a5a551,
+        0x34e5e5d1, 0x8f1f1f9, 0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a,
+        0xc040408, 0x52c7c795, 0x65232346, 0x5ec3c39d, 0x28181830, 0xa1969637,
+        0xf05050a, 0xb59a9a2f, 0x907070e, 0x36121224, 0x9b80801b, 0x3de2e2df,
+        0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea, 0x1b090912, 0x9e83831d,
+        0x742c2c58, 0x2e1a1a34, 0x2d1b1b36, 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b,
+        0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d, 0x7b292952, 0x3ee3e3dd,
+        0x712f2f5e, 0x97848413, 0xf55353a6, 0x68d1d1b9, 0x0, 0x2cededc1,
+        0x60202040, 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6, 0xbe6a6ad4, 0x46cbcb8d,
+        0xd9bebe67, 0x4b393972, 0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85,
+        0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed, 0xc5434386, 0xd74d4d9a,
+        0x55333366, 0x94858511, 0xcf45458a, 0x10f9f9e9, 0x6020204, 0x817f7ffe,
+        0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b, 0xf35151a2, 0xfea3a35d,
+        0xc0404080, 0x8a8f8f05, 0xad92923f, 0xbc9d9d21, 0x48383870, 0x4f5f5f1,
+        0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142, 0x30101020, 0x1affffe5,
+        0xef3f3fd, 0x6dd2d2bf, 0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3,
+        0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e, 0x57c4c493, 0xf2a7a755,
+        0x827e7efc, 0x473d3d7a, 0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6,
+        0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3, 0x66222244, 0x7e2a2a54,
+        0xab90903b, 0x8388880b, 0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428,
+        0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad, 0x3be0e0db, 0x56323264,
+        0x4e3a3a74, 0x1e0a0a14, 0xdb494992, 0xa06060c, 0x6c242448, 0xe45c5cb8,
+        0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4, 0xa8919139, 0xa4959531,
+        0x37e4e4d3, 0x8b7979f2, 0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda,
+        0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949, 0xb46c6cd8, 0xfa5656ac,
+        0x7f4f4f3, 0x25eaeacf, 0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810,
+        0xd5baba6f, 0x887878f0, 0x6f25254a, 0x722e2e5c, 0x241c1c38, 0xf1a6a657,
+        0xc7b4b473, 0x51c6c697, 0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e,
+        0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f, 0x907070e0, 0x423e3e7c,
+        0xc4b5b571, 0xaa6666cc, 0xd8484890, 0x5030306, 0x1f6f6f7, 0x120e0e1c,
+        0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969, 0x91868617, 0x58c1c199,
+        0x271d1d3a, 0xb99e9e27, 0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122,
+        0xbb6969d2, 0x70d9d9a9, 0x898e8e07, 0xa7949433, 0xb69b9b2d, 0x221e1e3c,
+        0x92878715, 0x20e9e9c9, 0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5,
+        0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a, 0xdabfbf65, 0x31e6e6d7,
+        0xc6424284, 0xb86868d0, 0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e,
+        0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c
+    ];
+    AES.rtable = [
+        0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a, 0xcb6bab3b, 0xf1459d1f,
+        0xab58faac, 0x9303e34b, 0x55fa3020, 0xf66d76ad, 0x9176cc88, 0x254c02f5,
+        0xfcd7e54f, 0xd7cb2ac5, 0x80443526, 0x8fa362b5, 0x495ab1de, 0x671bba25,
+        0x980eea45, 0xe1c0fe5d, 0x2752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b,
+        0xe75f8f03, 0x959c9215, 0xeb7a6dbf, 0xda595295, 0x2d83bed4, 0xd3217458,
+        0x2969e049, 0x44c8c98e, 0x6a89c275, 0x78798ef4, 0x6b3e5899, 0xdd71b927,
+        0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d, 0x184adf63, 0x82311ae5,
+        0x60335197, 0x457f5362, 0xe07764b1, 0x84ae6bbb, 0x1ca081fe, 0x942b08f9,
+        0x58684870, 0x19fd458f, 0x876cde94, 0xb7f87b52, 0x23d373ab, 0xe2024b72,
+        0x578f1fe3, 0x2aab5566, 0x728ebb2, 0x3c2b52f, 0x9a7bc586, 0xa50837d3,
+        0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed, 0x2b1ccf8a, 0x92b479a7,
+        0xf0f207f3, 0xa1e2694e, 0xcdf4da65, 0xd5be0506, 0x1f6234d1, 0x8afea6c4,
+        0x9d532e34, 0xa055f3a2, 0x32e18a05, 0x75ebf6a4, 0x39ec830b, 0xaaef6040,
+        0x69f715e, 0x51106ebd, 0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d,
+        0xb58d5491, 0x55dc471, 0x6fd40604, 0xff155060, 0x24fb9819, 0x97e9bdd6,
+        0xcc434089, 0x779ed967, 0xbd42e8b0, 0x888b8907, 0x385b19e7, 0xdbeec879,
+        0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x0, 0x83868009, 0x48ed2b32,
+        0xac70111e, 0x4e725a6c, 0xfbff0efd, 0x5638850f, 0x1ed5ae3d, 0x27392d36,
+        0x64d90f0a, 0x21a65c68, 0xd1545b9b, 0x3a2e3624, 0xb1670a0c, 0xfe75793,
+        0xd296eeb4, 0x9e919b1b, 0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c,
+        0xaba93e2, 0xe52aa0c0, 0x43e0223c, 0x1d171b12, 0xb0d090e, 0xadc78bf2,
+        0xb9a8b62d, 0xc8a91e14, 0x8519f157, 0x4c0775af, 0xbbdd99ee, 0xfd607fa3,
+        0x9f2601f7, 0xbcf5725c, 0xc53b6644, 0x347efb5b, 0x7629438b, 0xdcc623cb,
+        0x68fcedb6, 0x63f1e4b8, 0xcadc31d7, 0x10856342, 0x40229713, 0x2011c684,
+        0x7d244a85, 0xf83dbbd2, 0x1132f9ae, 0x6da129c7, 0x4b2f9e1d, 0xf330b2dc,
+        0xec52860d, 0xd0e3c177, 0x6c16b32b, 0x99b970a9, 0xfa489411, 0x2264e947,
+        0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, 0xef903322, 0xc74e4987, 0xc1d138d9,
+        0xfea2ca8c, 0x360bd498, 0xcf81f5a6, 0x28de7aa5, 0x268eb7da, 0xa4bfad3f,
+        0xe49d3a2c, 0xd927850, 0x9bcc5f6a, 0x62467e54, 0xc2138df6, 0xe8b8d890,
+        0x5ef7392e, 0xf5afc382, 0xbe805d9f, 0x7c93d069, 0xa92dd56f, 0xb31225cf,
+        0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb, 0x97826cd, 0xf418596e,
+        0x1b79aec, 0xa89a4f83, 0x656e95e6, 0x7ee6ffaa, 0x8cfbc21, 0xe6e815ef,
+        0xd99be7ba, 0xce366f4a, 0xd4099fea, 0xd67cb029, 0xafb2a431, 0x31233f2a,
+        0x3094a5c6, 0xc066a235, 0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733,
+        0x4a9804f1, 0xf7daec41, 0xe50cd7f, 0x2ff69117, 0x8dd64d76, 0x4db0ef43,
+        0x544daacc, 0xdf0496e4, 0xe3b5d19e, 0x1b886a4c, 0xb81f2cc1, 0x7f516546,
+        0x4ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb, 0x5a1d67b3, 0x52d2db92,
+        0x335610e9, 0x1347d66d, 0x8c61d79a, 0x7a0ca137, 0x8e14f859, 0x893c13eb,
+        0xee27a9ce, 0x35c961b7, 0xede51ce1, 0x3cb1477a, 0x59dfd29c, 0x3f73f255,
+        0x79ce1418, 0xbf37c773, 0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478,
+        0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2, 0x72c31d16, 0xc25e2bc,
+        0x8b493c28, 0x41950dff, 0x7101a839, 0xdeb30c08, 0x9ce4b4d8, 0x90c15664,
+        0x6184cb7b, 0x70b632d5, 0x745c6c48, 0x4257b8d0
+    ];
+
+    return AES;
+};
diff --git a/version3/js/big.js b/version3/js/big.js
new file mode 100644
index 0000000..3ae724a
--- /dev/null
+++ b/version3/js/big.js
@@ -0,0 +1,1552 @@
+/*
+    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.
+*/
+
+/* AMCL BIG number class */
+var BIG,
+    DBIG;
+
+BIG = function(ctx) {
+    "use strict";
+
+    /* General purpose Constructor */
+    var BIG = function(x) {
+        this.w = new Array(BIG.NLEN);
+
+        switch (typeof(x)) {
+            case "object":
+                this.copy(x);
+                break;
+
+            case "number":
+                this.zero();
+                this.w[0] = x;
+                break;
+
+            default:
+                this.zero();
+        }
+    };
+
+    BIG.CHUNK = 32;
+    BIG.MODBYTES = ctx.config["@NB"];
+    BIG.BASEBITS = ctx.config["@BASE"];
+    BIG.NLEN = (1 + (Math.floor((8 * BIG.MODBYTES - 1) / BIG.BASEBITS)));
+    BIG.DNLEN = 2 * BIG.NLEN;
+    BIG.BMASK = (1 << BIG.BASEBITS) - 1;
+    BIG.BIGBITS = (8 * BIG.MODBYTES);
+    BIG.NEXCESS = (1 << (BIG.CHUNK - BIG.BASEBITS - 1));
+    BIG.MODINV = (Math.pow(2, -BIG.BASEBITS));
+
+    BIG.prototype = {
+        /* set to zero */
+        zero: function() {
+            var i;
+
+            for (i = 0; i < BIG.NLEN; i++) {
+                this.w[i] = 0;
+            }
+
+            return this;
+        },
+
+        /* set to one */
+        one: function() {
+            var i;
+
+            this.w[0] = 1;
+            for (i = 1; i < BIG.NLEN; i++) {
+                this.w[i] = 0;
+            }
+
+            return this;
+        },
+
+        get: function(i) {
+            return this.w[i];
+        },
+
+        set: function(i, x) {
+            this.w[i] = x;
+        },
+
+        /* test for zero */
+        iszilch: function() {
+            var i;
+
+            for (i = 0; i < BIG.NLEN; i++) {
+                if (this.w[i] !== 0) {
+                    return false;
+                }
+            }
+
+            return true;
+        },
+
+        /* test for unity */
+        isunity: function() {
+            var i;
+
+            for (i = 1; i < BIG.NLEN; i++) {
+                if (this.w[i] !== 0) {
+                    return false;
+                }
+            }
+
+            if (this.w[0] != 1) {
+                return false;
+            }
+
+            return true;
+        },
+
+        /* Conditional swap of two BIGs depending on d using XOR - no branches */
+        cswap: function(b, d) {
+            var c = d,
+                t, i;
+
+            c = ~(c - 1);
+
+            for (i = 0; i < BIG.NLEN; i++) {
+                t = c & (this.w[i] ^ b.w[i]);
+                this.w[i] ^= t;
+                b.w[i] ^= t;
+            }
+        },
+
+        /* Conditional move of BIG depending on d using XOR - no branches */
+        cmove: function(b, d) {
+            var c = d,
+                i;
+
+            c = ~(c - 1);
+
+            for (i = 0; i < BIG.NLEN; i++) {
+                this.w[i] ^= (this.w[i] ^ b.w[i]) & c;
+            }
+        },
+
+        /* copy from another BIG */
+        copy: function(y) {
+            var i;
+
+            for (i = 0; i < BIG.NLEN; i++) {
+                this.w[i] = y.w[i];
+            }
+
+            return this;
+        },
+
+        /* copy from bottom half of ctx.DBIG */
+        hcopy: function(y) {
+            var i;
+
+            for (i = 0; i < BIG.NLEN; i++) {
+                this.w[i] = y.w[i];
+            }
+
+            return this;
+        },
+
+        /* copy from ROM */
+        rcopy: function(y) {
+            var i;
+
+            for (i = 0; i < BIG.NLEN; i++) {
+                this.w[i] = y[i];
+            }
+
+            return this;
+        },
+
+        xortop: function(x) {
+            this.w[BIG.NLEN - 1] ^= x;
+        },
+
+        ortop: function(x) {
+            this.w[BIG.NLEN - 1] |= x;
+        },
+
+        /* normalise BIG - force all digits < 2^BASEBITS */
+        norm: function() {
+            var carry = 0,
+                d, i;
+
+            for (i = 0; i < BIG.NLEN - 1; i++) {
+                d = this.w[i] + carry;
+                this.w[i] = d & BIG.BMASK;
+                carry = d >> BIG.BASEBITS;
+            }
+
+            this.w[BIG.NLEN - 1] = (this.w[BIG.NLEN - 1] + carry);
+
+            return (this.w[BIG.NLEN - 1] >> ((8 * BIG.MODBYTES) % BIG.BASEBITS));
+        },
+
+        /* quick shift right by less than a word */
+        fshr: function(k) {
+            var r, i;
+
+            r = this.w[0] & ((1 << k) - 1); /* shifted out part */
+
+            for (i = 0; i < BIG.NLEN - 1; i++) {
+                this.w[i] = (this.w[i] >> k) | ((this.w[i + 1] << (BIG.BASEBITS - k)) & BIG.BMASK);
+            }
+
+            this.w[BIG.NLEN - 1] = this.w[BIG.NLEN - 1] >> k;
+
+            return r;
+        },
+
+        /* General shift right by k bits */
+        shr: function(k) {
+            var n = k % BIG.BASEBITS,
+                m = Math.floor(k / BIG.BASEBITS),
+                i;
+
+            for (i = 0; i < BIG.NLEN - m - 1; i++) {
+                this.w[i] = (this.w[m + i] >> n) | ((this.w[m + i + 1] << (BIG.BASEBITS - n)) & BIG.BMASK);
+            }
+
+            this.w[BIG.NLEN - m - 1] = this.w[BIG.NLEN - 1] >> n;
+
+            for (i = BIG.NLEN - m; i < BIG.NLEN; i++) {
+                this.w[i] = 0;
+            }
+
+            return this;
+        },
+
+        /* quick shift left by less than a word */
+        fshl: function(k) {
+            var i;
+
+            this.w[BIG.NLEN - 1] = ((this.w[BIG.NLEN - 1] << k)) | (this.w[BIG.NLEN - 2] >> (BIG.BASEBITS - k));
+
+            for (i = BIG.NLEN - 2; i > 0; i--) {
+                this.w[i] = ((this.w[i] << k) & BIG.BMASK) | (this.w[i - 1] >> (BIG.BASEBITS - k));
+            }
+
+            this.w[0] = (this.w[0] << k) & BIG.BMASK;
+
+            return (this.w[BIG.NLEN - 1] >> ((8 * BIG.MODBYTES) % BIG.BASEBITS)); /* return excess - only used in FF.java */
+        },
+
+        /* General shift left by k bits */
+        shl: function(k) {
+            var n = k % BIG.BASEBITS,
+                m = Math.floor(k / BIG.BASEBITS),
+                i;
+
+            this.w[BIG.NLEN - 1] = (this.w[BIG.NLEN - 1 - m] << n);
+
+            if (BIG.NLEN > m + 2) {
+                this.w[BIG.NLEN - 1] |= (this.w[BIG.NLEN - m - 2] >> (BIG.BASEBITS - n));
+            }
+
+            for (i = BIG.NLEN - 2; i > m; i--) {
+                this.w[i] = ((this.w[i - m] << n) & BIG.BMASK) | (this.w[i - m - 1] >> (BIG.BASEBITS - n));
+            }
+
+            this.w[m] = (this.w[0] << n) & BIG.BMASK;
+
+            for (i = 0; i < m; i++) {
+                this.w[i] = 0;
+            }
+
+            return this;
+        },
+
+        /* return length in bits */
+        nbits: function() {
+            var k = BIG.NLEN - 1,
+                bts, c;
+
+			var t=new BIG(0); t.copy(this);
+            t.norm();
+
+            while (k >= 0 && t.w[k] === 0) {
+                k--;
+            }
+
+            if (k < 0) {
+                return 0;
+            }
+
+            bts = BIG.BASEBITS * k;
+            c = t.w[k];
+
+            while (c !== 0) {
+                c = Math.floor(c / 2);
+                bts++;
+            }
+
+            return bts;
+        },
+
+        /* convert this to string */
+        toString: function() {
+            var s = "",
+                len = this.nbits(),
+                b, i;
+
+            if (len % 4 === 0) {
+                len = Math.floor(len / 4);
+            } else {
+                len = Math.floor(len / 4);
+                len++;
+            }
+
+            if (len < BIG.MODBYTES * 2) {
+                len = BIG.MODBYTES * 2;
+            }
+
+            for (i = len - 1; i >= 0; i--) {
+                b = new BIG(0);
+                b.copy(this);
+                b.shr(i * 4);
+                s += (b.w[0] & 15).toString(16);
+            }
+
+            return s;
+        },
+
+        /* this+=y */
+        add: function(y) {
+            var i;
+
+            for (i = 0; i < BIG.NLEN; i++) {
+                this.w[i] += y.w[i];
+            }
+
+            return this;
+        },
+
+
+        /* this|=y */
+        or: function(y) {
+            var i;
+
+            for (i = 0; i < BIG.NLEN; i++) {
+                this.w[i] |= y.w[i];
+            }
+
+            return this;
+        },
+
+
+        /* return this+x */
+        plus: function(x) {
+            var s = new BIG(0),
+                i;
+
+            for (i = 0; i < BIG.NLEN; i++) {
+                s.w[i] = this.w[i] + x.w[i];
+            }
+
+            return s;
+        },
+
+        /* this+=i, where i is int */
+        inc: function(i) {
+            this.norm();
+            this.w[0] += i;
+            return this;
+        },
+
+        /* this-=y */
+        sub: function(y) {
+            var i;
+
+            for (i = 0; i < BIG.NLEN; i++) {
+                this.w[i] -= y.w[i];
+            }
+
+            return this;
+        },
+
+        /* reverse subtract this=x-this */
+        rsub: function(x) {
+            var i;
+
+            for (i = 0; i < BIG.NLEN; i++) {
+                this.w[i] = x.w[i] - this.w[i];
+            }
+
+            return this;
+        },
+
+        /* this-=i, where i is int */
+        dec: function(i) {
+            this.norm();
+            this.w[0] -= i;
+            return this;
+        },
+
+        /* return this-x */
+        minus: function(x) {
+            var d = new BIG(0),
+                i;
+
+            for (i = 0; i < BIG.NLEN; i++) {
+                d.w[i] = this.w[i] - x.w[i];
+            }
+
+            return d;
+        },
+
+        /* multiply by small integer */
+        imul: function(c) {
+            var i;
+
+            for (i = 0; i < BIG.NLEN; i++) {
+                this.w[i] *= c;
+            }
+
+            return this;
+        },
+
+        /* convert this BIG to byte array */
+        tobytearray: function(b, n) {
+            var c = new BIG(0),
+                i;
+
+            //this.norm();
+            c.copy(this);
+			c.norm();
+
+            for (i = BIG.MODBYTES - 1; i >= 0; i--) {
+                b[i + n] = c.w[0] & 0xff;
+                c.fshr(8);
+            }
+
+            return this;
+        },
+
+        /* convert this to byte array */
+        toBytes: function(b) {
+            this.tobytearray(b, 0);
+        },
+
+        /* set this[i]+=x*y+c, and return high part */
+        muladd: function(x, y, c, i) {
+            var prod = x * y + c + this.w[i];
+            this.w[i] = prod & BIG.BMASK;
+            return ((prod - this.w[i]) * BIG.MODINV);
+        },
+
+        /* multiply by larger int */
+        pmul: function(c) {
+            var carry = 0,
+                ak, i;
+
+            //  this.norm();
+
+            for (i = 0; i < BIG.NLEN; i++) {
+                ak = this.w[i];
+                this.w[i] = 0;
+                carry = this.muladd(ak, c, carry, i);
+            }
+
+            return carry;
+        },
+
+        /* multiply by still larger int - results requires a ctx.DBIG */
+        pxmul: function(c) {
+            var m = new ctx.DBIG(0),
+                carry = 0,
+                j;
+
+            for (j = 0; j < BIG.NLEN; j++) {
+                carry = m.muladd(this.w[j], c, carry, j);
+            }
+
+            m.w[BIG.NLEN] = carry;
+
+            return m;
+        },
+
+        /* divide by 3 */
+        div3: function() {
+            var carry = 0,
+                ak, base, i;
+
+            this.norm();
+            base = (1 << BIG.BASEBITS);
+
+            for (i = BIG.NLEN - 1; i >= 0; i--) {
+                ak = (carry * base + this.w[i]);
+                this.w[i] = Math.floor(ak / 3);
+                carry = ak % 3;
+            }
+            return carry;
+        },
+
+        /* set x = x mod 2^m */
+        mod2m: function(m) {
+            var i, wd, bt, msk;
+
+            wd = Math.floor(m / BIG.BASEBITS);
+            bt = m % BIG.BASEBITS;
+            msk = (1 << bt) - 1;
+            this.w[wd] &= msk;
+
+            for (i = wd + 1; i < BIG.NLEN; i++) {
+                this.w[i] = 0;
+            }
+        },
+
+        /* a=1/a mod 2^256. This is very fast! */
+        invmod2m: function() {
+            var U = new BIG(0),
+                b = new BIG(0),
+                c = new BIG(0),
+                i, t1, t2;
+
+            U.inc(BIG.invmod256(this.lastbits(8)));
+
+            for (i = 8; i < BIG.BIGBITS; i <<= 1) {
+                U.norm();
+                b.copy(this);
+                b.mod2m(i);
+                t1 = BIG.smul(U, b);
+                t1.shr(i);
+                c.copy(this);
+                c.shr(i);
+                c.mod2m(i);
+
+                t2 = BIG.smul(U, c);
+                t2.mod2m(i);
+                t1.add(t2);
+                t1.norm();
+                b = BIG.smul(t1, U);
+                t1.copy(b);
+                t1.mod2m(i);
+
+                t2.one();
+                t2.shl(i);
+                t1.rsub(t2);
+                t1.norm();
+                t1.shl(i);
+                U.add(t1);
+            }
+
+            U.mod2m(BIG.BIGBITS);
+            this.copy(U);
+            this.norm();
+        },
+
+        /* reduce this mod m */
+        mod: function(m1) {
+            var k = 0,
+                r = new BIG(0);
+			var m=new BIG(0); m.copy(m1);
+
+            this.norm();
+
+            if (BIG.comp(this, m) < 0) {
+                return;
+            }
+
+            do {
+                m.fshl(1);
+                k++;
+            } while (BIG.comp(this, m) >= 0);
+
+            while (k > 0) {
+                m.fshr(1);
+
+                r.copy(this);
+                r.sub(m);
+                r.norm();
+                this.cmove(r, (1 - ((r.w[BIG.NLEN - 1] >> (BIG.CHUNK - 1)) & 1)));
+
+                // if (BIG.comp(this,m)>=0)
+                // {
+                //     this.sub(m);
+                //     this.norm();
+                // }
+
+                k--;
+            }
+        },
+        /* this/=m */
+        div: function(m1) {
+            var k = 0,
+                d = 0,
+                e = new BIG(1),
+                b = new BIG(0),
+                r = new BIG(0);
+			var m=new BIG(0); m.copy(m1);
+
+            this.norm();
+            b.copy(this);
+            this.zero();
+
+            while (BIG.comp(b, m) >= 0) {
+                e.fshl(1);
+                m.fshl(1);
+                k++;
+            }
+
+            while (k > 0) {
+                m.fshr(1);
+                e.fshr(1);
+
+                r.copy(b);
+                r.sub(m);
+                r.norm();
+                d = (1 - ((r.w[BIG.NLEN - 1] >> (BIG.CHUNK - 1)) & 1));
+                b.cmove(r, d);
+                r.copy(this);
+                r.add(e);
+                r.norm();
+                this.cmove(r, d);
+
+                // if (BIG.comp(b,m)>=0)
+                // {
+                //     this.add(e);
+                //     this.norm();
+                //     b.sub(m);
+                //     b.norm();
+                // }
+
+                k--;
+            }
+        },
+        /* return parity of this */
+        parity: function() {
+            return this.w[0] % 2;
+        },
+
+        /* return n-th bit of this */
+        bit: function(n) {
+            if ((this.w[Math.floor(n / BIG.BASEBITS)] & (1 << (n % BIG.BASEBITS))) > 0) {
+                return 1;
+            } else {
+                return 0;
+            }
+        },
+
+        /* return last n bits of this */
+        lastbits: function(n) {
+            var msk = (1 << n) - 1;
+            this.norm();
+            return (this.w[0]) & msk;
+        },
+
+        isok: function() {
+            var ok = true,
+                i;
+
+            for (i = 0; i < BIG.NLEN; i++) {
+                if ((this.w[i] >> BIG.BASEBITS) != 0) {
+                    ok = false;
+                }
+            }
+
+            return ok;
+        },
+
+        /* Jacobi Symbol (this/p). Returns 0, 1 or -1 */
+        jacobi: function(p) {
+            var m = 0,
+                t = new BIG(0),
+                x = new BIG(0),
+                n = new BIG(0),
+                zilch = new BIG(0),
+                one = new BIG(1),
+                n8, k;
+
+            if (p.parity() === 0 || BIG.comp(this, zilch) === 0 || BIG.comp(p, one) <= 0) {
+                return 0;
+            }
+
+            this.norm();
+            x.copy(this);
+            n.copy(p);
+            x.mod(p);
+
+            while (BIG.comp(n, one) > 0) {
+                if (BIG.comp(x, zilch) === 0) {
+                    return 0;
+                }
+
+                n8 = n.lastbits(3);
+                k = 0;
+
+                while (x.parity() === 0) {
+                    k++;
+                    x.shr(1);
+                }
+
+                if (k % 2 == 1) {
+                    m += (n8 * n8 - 1) / 8;
+                }
+
+                m += (n8 - 1) * (x.lastbits(2) - 1) / 4;
+                t.copy(n);
+                t.mod(x);
+                n.copy(x);
+                x.copy(t);
+                m %= 2;
+            }
+
+            if (m === 0) {
+                return 1;
+            } else {
+                return -1;
+            }
+        },
+
+        /* this=1/this mod p. Binary method */
+        invmodp: function(p) {
+            var u = new BIG(0),
+                v = new BIG(0),
+                x1 = new BIG(1),
+                x2 = new BIG(0),
+                t = new BIG(0),
+                one = new BIG(1);
+
+            this.mod(p);
+            u.copy(this);
+            v.copy(p);
+
+            while (BIG.comp(u, one) !== 0 && BIG.comp(v, one) !== 0) {
+                while (u.parity() === 0) {
+                    u.fshr(1);
+                    if (x1.parity() !== 0) {
+                        x1.add(p);
+                        x1.norm();
+                    }
+                    x1.fshr(1);
+                }
+
+                while (v.parity() === 0) {
+                    v.fshr(1);
+                    if (x2.parity() !== 0) {
+                        x2.add(p);
+                        x2.norm();
+                    }
+                    x2.fshr(1);
+                }
+
+                if (BIG.comp(u, v) >= 0) {
+                    u.sub(v);
+                    u.norm();
+                    if (BIG.comp(x1, x2) >= 0) {
+                        x1.sub(x2);
+                    } else {
+                        t.copy(p);
+                        t.sub(x2);
+                        x1.add(t);
+                    }
+                    x1.norm();
+                } else {
+                    v.sub(u);
+                    v.norm();
+                    if (BIG.comp(x2, x1) >= 0) {
+                        x2.sub(x1);
+                    } else {
+                        t.copy(p);
+                        t.sub(x1);
+                        x2.add(t);
+                    }
+                    x2.norm();
+                }
+            }
+
+            if (BIG.comp(u, one) === 0) {
+                this.copy(x1);
+            } else {
+                this.copy(x2);
+            }
+        },
+
+        /* return this^e mod m */
+        powmod: function(e1, m) {
+            var a = new BIG(1),
+                z = new BIG(0),
+                s = new BIG(0),
+                bt;
+
+			var e=new BIG(0); e.copy(e1);
+            this.norm();
+            e.norm();
+            z.copy(e);
+            s.copy(this);
+
+            for (;;) {
+                bt = z.parity();
+                z.fshr(1);
+                if (bt == 1) {
+                    a = BIG.modmul(a, s, m);
+                }
+
+                if (z.iszilch()) {
+                    break;
+                }
+
+                s = BIG.modsqr(s, m);
+            }
+
+            return a;
+        }
+    };
+
+	BIG.ssn = function(r,a,m) {
+		var n=BIG.NLEN-1;
+		m.w[0]=(m.w[0]>>1)|((m.w[1]<<(BIG.BASEBITS-1))&BIG.BMASK);
+		r.w[0]=a.w[0]-m.w[0];
+		var carry=r.w[0]>>BIG.BASEBITS;
+		r.w[0]&=BIG.BMASK;
+		for (var i=1;i<n;i++) {
+			m.w[i]=(m.w[i]>>1)|((m.w[i+1]<<(BIG.BASEBITS-1))&BIG.BMASK);
+			r.w[i]=a.w[i]-m.w[i]+carry;
+			carry=r.w[i]>>BIG.BASEBITS;
+			r.w[i]&=BIG.BMASK;
+		}
+		m.w[n]>>=1;
+		r.w[n]=a.w[n]-m.w[n]+carry;
+		return ((r.w[n]>>(BIG.CHUNK-1))&1);
+	};
+
+    /* convert from byte array to BIG */
+    BIG.frombytearray = function(b, n) {
+        var m = new BIG(0),
+            i;
+
+        for (i = 0; i < BIG.MODBYTES; i++) {
+            m.fshl(8);
+            m.w[0] += b[i + n] & 0xff;
+            //m.inc(b[i]&0xff);
+        }
+
+        return m;
+    };
+
+    BIG.fromBytes = function(b) {
+        return BIG.frombytearray(b, 0);
+    };
+
+    /* return a*b where product fits a BIG */
+    BIG.smul = function(a, b) {
+        var c = new BIG(0),
+            carry, i, j;
+
+        for (i = 0; i < BIG.NLEN; i++) {
+            carry = 0;
+
+            for (j = 0; j < BIG.NLEN; j++) {
+                if (i + j < BIG.NLEN) {
+                    carry = c.muladd(a.w[i], b.w[j], carry, i + j);
+                }
+            }
+        }
+
+        return c;
+    };
+
+    /* Compare a and b, return 0 if a==b, -1 if a<b, +1 if a>b. Inputs must be normalised */
+    BIG.comp = function(a, b) {
+        var i;
+
+        for (i = BIG.NLEN - 1; i >= 0; i--) {
+            if (a.w[i] == b.w[i]) {
+                continue;
+            }
+
+            if (a.w[i] > b.w[i]) {
+                return 1;
+            } else {
+                return -1;
+            }
+        }
+
+        return 0;
+    };
+
+    /* get 8*MODBYTES size random number */
+    BIG.random = function(rng) {
+        var m = new BIG(0),
+            j = 0,
+            r = 0,
+            i, b;
+
+        /* generate random BIG */
+        for (i = 0; i < 8 * BIG.MODBYTES; i++) {
+            if (j === 0) {
+                r = rng.getByte();
+            } else {
+                r >>= 1;
+            }
+
+            b = r & 1;
+            m.shl(1);
+            m.w[0] += b; // m.inc(b);
+            j++;
+            j &= 7;
+        }
+        return m;
+    };
+
+    /* Create random BIG in portable way, one bit at a time */
+    BIG.randomnum = function(q, rng) {
+        var d = new ctx.DBIG(0),
+            j = 0,
+            r = 0,
+            i, b, m;
+
+        for (i = 0; i < 2 * q.nbits(); i++) {
+            if (j === 0) {
+                r = rng.getByte();
+            } else {
+                r >>= 1;
+            }
+
+            b = r & 1;
+            d.shl(1);
+            d.w[0] += b;
+            j++;
+            j &= 7;
+        }
+
+        m = d.mod(q);
+
+        return m;
+    };
+
+    /* return NAF value as +/- 1, 3 or 5. x and x3 should be normed.
+    nbs is number of bits processed, and nzs is number of trailing 0s detected */
+    /*
+    BIG.nafbits=function(x,x3,i)
+    {
+        var n=[];
+        var nb=x3.bit(i)-x.bit(i);
+        var j;
+        n[1]=1;
+        n[0]=0;
+        if (nb===0) {n[0]=0; return n;}
+        if (i===0) {n[0]=nb; return n;}
+        if (nb>0) n[0]=1;
+        else      n[0]=(-1);
+
+        for (j=i-1;j>0;j--)
+        {
+            n[1]++;
+            n[0]*=2;
+            nb=x3.bit(j)-x.bit(j);
+            if (nb>0) n[0]+=1;
+            if (nb<0) n[0]-=1;
+            if (n[0]>5 || n[0]<-5) break;
+        }
+
+        if (n[0]%2!==0 && j!==0)
+        { // backtrack
+            if (nb>0) n[0]=(n[0]-1)/2;
+            if (nb<0) n[0]=(n[0]+1)/2;
+            n[1]--;
+        }
+        while (n[0]%2===0)
+        { // remove trailing zeros
+            n[0]/=2;
+            n[2]++;
+            n[1]--;
+        }
+        return n;
+    };
+    */
+
+    /* return a*b as ctx.DBIG */
+    BIG.mul = function(a, b) {
+        var c = new ctx.DBIG(0),
+            d = new Array(BIG.NLEN), //[],
+            n, s, t, i, k, co;
+
+        //  a.norm();
+        //  b.norm();
+
+        //if (!a.isok()) alert("Problem in mul a");
+        //if (!b.isok()) alert("Problem in mul b");
+
+        for (i = 0; i < BIG.NLEN; i++) {
+            d[i] = a.w[i] * b.w[i];
+        }
+
+        s = d[0];
+        t = s;
+        c.w[0] = t;
+
+        for (k = 1; k < BIG.NLEN; k++) {
+            s += d[k];
+            t = s;
+            for (i = k; i >= 1 + Math.floor(k / 2); i--) {
+                t += (a.w[i] - a.w[k - i]) * (b.w[k - i] - b.w[i]);
+            }
+            c.w[k] = t;
+        }
+        for (k = BIG.NLEN; k < 2 * BIG.NLEN - 1; k++) {
+            s -= d[k - BIG.NLEN];
+            t = s;
+            for (i = BIG.NLEN - 1; i >= 1 + Math.floor(k / 2); i--) {
+                t += (a.w[i] - a.w[k - i]) * (b.w[k - i] - b.w[i]);
+            }
+            c.w[k] = t;
+        }
+
+        co = 0;
+        for (i = 0; i < BIG.DNLEN - 1; i++) {
+            n = c.w[i] + co;
+            c.w[i] = n & BIG.BMASK;
+            co = (n - c.w[i]) * BIG.MODINV;
+        }
+        c.w[BIG.DNLEN - 1] = co;
+
+        // for (var j=0;j<BIG.NLEN;j++)
+        // {
+        //     t=0; for (var i=0;i<=j;i++) t+=a.w[j-i]*b.w[i];
+        //     c.w[j]=t;
+        // }
+        // for (var j=BIG.NLEN;j<BIG.DNLEN-2;j++)
+        // {
+        //     t=0; for (var i=j-BIG.NLEN+1;i<BIG.NLEN;i++) t+=a.w[j-i]*b.w[i];
+        //     c.w[j]=t;
+        // }
+        // t=a.w[BIG.NLEN-1]*b.w[BIG.NLEN-1];
+        // c.w[BIG.DNLEN-2]=t;
+        // var co=0;
+        // for (var i=0;i<BIG.DNLEN-1;i++)
+        // {
+        //     n=c.w[i]+co;
+        //     c.w[i]=n&BIG.BMASK;
+        //     co=(n-c.w[i])*BIG.MODINV;
+        // }
+        // c.w[BIG.DNLEN-1]=co;
+
+        return c;
+    };
+
+    /* return a^2 as ctx.DBIG */
+    BIG.sqr = function(a) {
+        var c = new ctx.DBIG(0),
+            n, t, j, i, co;
+        //  a.norm();
+
+        //if (!a.isok()) alert("Problem in sqr");
+
+        c.w[0] = a.w[0] * a.w[0];
+
+        for (j = 1; j < BIG.NLEN - 1;) {
+            t = a.w[j] * a.w[0];
+            for (i = 1; i < (j + 1) >> 1; i++) {
+                t += a.w[j - i] * a.w[i];
+            }
+            t += t;
+            c.w[j] = t;
+            j++;
+            t = a.w[j] * a.w[0];
+            for (i = 1; i < (j + 1) >> 1; i++) {
+                t += a.w[j - i] * a.w[i];
+            }
+            t += t;
+            t += a.w[j >> 1] * a.w[j >> 1];
+            c.w[j] = t;
+            j++;
+        }
+
+        for (j = BIG.NLEN - 1 + BIG.NLEN % 2; j < BIG.DNLEN - 3;) {
+            t = a.w[BIG.NLEN - 1] * a.w[j - BIG.NLEN + 1];
+            for (i = j - BIG.NLEN + 2; i < (j + 1) >> 1; i++) {
+                t += a.w[j - i] * a.w[i];
+            }
+            t += t;
+            c.w[j] = t;
+            j++;
+            t = a.w[BIG.NLEN - 1] * a.w[j - BIG.NLEN + 1];
+            for (i = j - BIG.NLEN + 2; i < (j + 1) >> 1; i++) {
+                t += a.w[j - i] * a.w[i];
+            }
+            t += t;
+            t += a.w[j >> 1] * a.w[j >> 1];
+            c.w[j] = t;
+            j++;
+        }
+
+        t = a.w[BIG.NLEN - 2] * a.w[BIG.NLEN - 1];
+        t += t;
+        c.w[BIG.DNLEN - 3] = t;
+
+        t = a.w[BIG.NLEN - 1] * a.w[BIG.NLEN - 1];
+        c.w[BIG.DNLEN - 2] = t;
+
+        co = 0;
+        for (i = 0; i < BIG.DNLEN - 1; i++) {
+            n = c.w[i] + co;
+            c.w[i] = n & BIG.BMASK;
+            co = (n - c.w[i]) * BIG.MODINV;
+        }
+        c.w[BIG.DNLEN - 1] = co;
+
+        return c;
+    };
+
+    BIG.monty = function(m, nd, d) {
+        var b = new BIG(0),
+            v = new Array(BIG.NLEN),//[],
+            dd = new Array(BIG.NLEN),//[],
+            s, c, t, i, k;
+
+        t = d.w[0];
+        v[0] = ((t & BIG.BMASK) * nd) & BIG.BMASK;
+        t += v[0] * m.w[0];
+        c = d.w[1] + (t * BIG.MODINV);
+        s = 0;
+
+        for (k = 1; k < BIG.NLEN; k++) {
+            t = c + s + v[0] * m.w[k];
+            for (i = k - 1; i > Math.floor(k / 2); i--) {
+                t += (v[k - i] - v[i]) * (m.w[i] - m.w[k - i]);
+            }
+            v[k] = ((t & BIG.BMASK) * nd) & BIG.BMASK;
+            t += v[k] * m.w[0];
+            c = (t * BIG.MODINV) + d.w[k + 1];
+
+            dd[k] = v[k] * m.w[k];
+            s += dd[k];
+        }
+
+        for (k = BIG.NLEN; k < 2 * BIG.NLEN - 1; k++) {
+            t = c + s;
+            for (i = BIG.NLEN - 1; i >= 1 + Math.floor(k / 2); i--) {
+                t += (v[k - i] - v[i]) * (m.w[i] - m.w[k - i]);
+            }
+            b.w[k - BIG.NLEN] = t & BIG.BMASK;
+            c = ((t - b.w[k - BIG.NLEN]) * BIG.MODINV) + d.w[k + 1];
+
+            s -= dd[k - BIG.NLEN + 1];
+        }
+
+        b.w[BIG.NLEN - 1] = c & BIG.BMASK;
+
+        return b;
+    };
+
+    /* return a*b mod m */
+    BIG.modmul = function(a1, b1, m) {
+        var d;
+		var a=new BIG(0); a.copy(a1);
+		var b=new BIG(0); b.copy(b1);
+        a.mod(m);
+        b.mod(m);
+        d = BIG.mul(a, b);
+
+        return d.mod(m);
+    };
+
+    /* return a^2 mod m */
+    BIG.modsqr = function(a1, m) {
+        var d;
+		var a=new BIG(0); a.copy(a1);
+        a.mod(m);
+        d = BIG.sqr(a);
+
+        return d.mod(m);
+    };
+
+    /* return -a mod m */
+    BIG.modneg = function(a1, m) {
+		var a=new BIG(0); a.copy(a1);
+        a.mod(m);
+        return m.minus(a);
+    };
+
+    /* Arazi and Qi inversion mod 256 */
+    BIG.invmod256 = function(a) {
+        var U, t1, t2, b, c;
+
+        t1 = 0;
+        c = (a >> 1) & 1;
+        t1 += c;
+        t1 &= 1;
+        t1 = 2 - t1;
+        t1 <<= 1;
+        U = t1 + 1;
+
+        // i=2
+        b = a & 3;
+        t1 = U * b;
+        t1 >>= 2;
+        c = (a >> 2) & 3;
+        t2 = (U * c) & 3;
+        t1 += t2;
+        t1 *= U;
+        t1 &= 3;
+        t1 = 4 - t1;
+        t1 <<= 2;
+        U += t1;
+
+        // i=4
+        b = a & 15;
+        t1 = U * b;
+        t1 >>= 4;
+        c = (a >> 4) & 15;
+        t2 = (U * c) & 15;
+        t1 += t2;
+        t1 *= U;
+        t1 &= 15;
+        t1 = 16 - t1;
+        t1 <<= 4;
+        U += t1;
+
+        return U;
+    };
+    return BIG;
+};
+
+/* AMCL double length DBIG number class */
+DBIG = function(ctx) {
+    "use strict";
+
+    /* constructor */
+    var DBIG = function(x) {
+        this.w = new Array(BIG.DNLEN);
+        this.zero();
+        this.w[0] = x;
+    };
+
+    DBIG.prototype = {
+
+        /* set this=0 */
+        zero: function() {
+            for (var i = 0; i < ctx.BIG.DNLEN; i++) {
+                this.w[i] = 0;
+            }
+            return this;
+        },
+
+        /* set this=b */
+        copy: function(b) {
+            for (var i = 0; i < ctx.BIG.DNLEN; i++) {
+                this.w[i] = b.w[i];
+            }
+            return this;
+        },
+
+
+        /* copy from ctx.BIG */
+        hcopy: function(b) {
+            var i;
+
+            for (i = 0; i < ctx.BIG.NLEN; i++) {
+                this.w[i] = b.w[i];
+            }
+
+            for (i = ctx.BIG.NLEN; i < ctx.BIG.DNLEN; i++) {
+                this.w[i] = 0;
+            }
+
+            return this;
+        },
+
+        ucopy: function(b) {
+            var i;
+
+            for (i = 0; i < ctx.BIG.NLEN; i++) {
+                this.w[i] = 0;
+            }
+
+            for (i = ctx.BIG.NLEN; i < ctx.BIG.DNLEN; i++) {
+                this.w[i] = b.w[i - ctx.BIG.NLEN];
+            }
+
+            return this;
+        },
+
+        /* normalise this */
+        norm: function() {
+            var carry = 0,
+                d, i;
+
+            for (i = 0; i < ctx.BIG.DNLEN - 1; i++) {
+                d = this.w[i] + carry;
+                this.w[i] = d & ctx.BIG.BMASK;
+                carry = d >> ctx.BIG.BASEBITS;
+            }
+            this.w[ctx.BIG.DNLEN - 1] = (this.w[ctx.BIG.DNLEN - 1] + carry);
+
+            return this;
+        },
+
+        /* set this[i]+=x*y+c, and return high part */
+        muladd: function(x, y, c, i) {
+            var prod = x * y + c + this.w[i];
+            this.w[i] = prod & ctx.BIG.BMASK;
+            return ((prod - this.w[i]) * ctx.BIG.MODINV);
+        },
+
+        /* shift this right by k bits */
+        shr: function(k) {
+            var n = k % ctx.BIG.BASEBITS,
+                m = Math.floor(k / ctx.BIG.BASEBITS),
+                i;
+
+            for (i = 0; i < ctx.BIG.DNLEN - m - 1; i++) {
+                this.w[i] = (this.w[m + i] >> n) | ((this.w[m + i + 1] << (ctx.BIG.BASEBITS - n)) & ctx.BIG.BMASK);
+            }
+
+            this.w[ctx.BIG.DNLEN - m - 1] = this.w[ctx.BIG.DNLEN - 1] >> n;
+
+            for (i = ctx.BIG.DNLEN - m; i < ctx.BIG.DNLEN; i++) {
+                this.w[i] = 0;
+            }
+
+            return this;
+        },
+
+        /* shift this left by k bits */
+        shl: function(k) {
+            var n = k % ctx.BIG.BASEBITS,
+                m = Math.floor(k / ctx.BIG.BASEBITS),
+                i;
+
+            this.w[ctx.BIG.DNLEN - 1] = ((this.w[ctx.BIG.DNLEN - 1 - m] << n)) | (this.w[ctx.BIG.DNLEN - m - 2] >> (ctx.BIG.BASEBITS - n));
+
+            for (i = ctx.BIG.DNLEN - 2; i > m; i--) {
+                this.w[i] = ((this.w[i - m] << n) & ctx.BIG.BMASK) | (this.w[i - m - 1] >> (ctx.BIG.BASEBITS - n));
+            }
+
+            this.w[m] = (this.w[0] << n) & ctx.BIG.BMASK;
+
+            for (i = 0; i < m; i++) {
+                this.w[i] = 0;
+            }
+
+            return this;
+        },
+
+        /* Conditional move of ctx.BIG depending on d using XOR - no branches */
+        cmove: function(b, d) {
+            var c = d,
+                i;
+
+            c = ~(c - 1);
+
+            for (i = 0; i < ctx.BIG.DNLEN; i++) {
+                this.w[i] ^= (this.w[i] ^ b.w[i]) & c;
+            }
+        },
+
+        /* this+=x */
+        add: function(x) {
+            for (var i = 0; i < ctx.BIG.DNLEN; i++) {
+                this.w[i] += x.w[i];
+            }
+        },
+
+        /* this-=x */
+        sub: function(x) {
+            for (var i = 0; i < ctx.BIG.DNLEN; i++) {
+                this.w[i] -= x.w[i];
+            }
+        },
+
+        rsub: function(x) {
+            for (var i = 0; i < ctx.BIG.DNLEN; i++) {
+                this.w[i] = x.w[i] - this.w[i];
+            }
+        },
+
+        /* return number of bits in this */
+        nbits: function() {
+            var k = ctx.BIG.DNLEN - 1,
+                bts, c;
+
+			var t=new DBIG(0); t.copy(this);
+            t.norm();
+
+            while (k >= 0 && t.w[k] === 0) {
+                k--;
+            }
+
+            if (k < 0) {
+                return 0;
+            }
+
+            bts = ctx.BIG.BASEBITS * k;
+            c = t.w[k];
+
+            while (c !== 0) {
+                c = Math.floor(c / 2);
+                bts++;
+            }
+
+            return bts;
+        },
+
+        /* convert this to string */
+        toString: function() {
+            var s = "",
+                len = this.nbits(),
+                b, i;
+
+            if (len % 4 === 0) {
+                len = Math.floor(len / 4);
+            } else {
+                len = Math.floor(len / 4);
+                len++;
+            }
+
+            for (i = len - 1; i >= 0; i--) {
+                b = new DBIG(0);
+                b.copy(this);
+                b.shr(i * 4);
+                s += (b.w[0] & 15).toString(16);
+            }
+
+            return s;
+        },
+
+        /* reduces this DBIG mod a ctx.BIG, and returns the ctx.BIG */
+        mod: function(c) {
+            var k = 0,
+                m = new DBIG(0),
+                dr = new DBIG(0),
+                r = new ctx.BIG(0);
+
+            this.norm();
+            m.hcopy(c);
+            r.hcopy(this);
+
+            if (DBIG.comp(this, m) < 0) {
+                return r;
+            }
+
+            do {
+                m.shl(1);
+                k++;
+            } while (DBIG.comp(this, m) >= 0);
+
+            while (k > 0) {
+                m.shr(1);
+
+                dr.copy(this);
+                dr.sub(m);
+                dr.norm();
+                this.cmove(dr, (1 - ((dr.w[ctx.BIG.DNLEN - 1] >> (ctx.BIG.CHUNK - 1)) & 1)));
+
+                // if (DBIG.comp(this,m)>=0)
+                // {
+                //     this.sub(m);
+                //     this.norm();
+                // }
+
+                k--;
+            }
+
+            r.hcopy(this);
+
+            return r;
+        },
+
+        /* this/=c */
+        div: function(c) {
+            var d = 0,
+                k = 0,
+                m = new DBIG(0),
+                dr = new DBIG(0),
+                r = new ctx.BIG(0),
+                a = new ctx.BIG(0),
+                e = new ctx.BIG(1);
+
+            m.hcopy(c);
+            this.norm();
+
+            while (DBIG.comp(this, m) >= 0) {
+                e.fshl(1);
+                m.shl(1);
+                k++;
+            }
+
+            while (k > 0) {
+                m.shr(1);
+                e.shr(1);
+
+                dr.copy(this);
+                dr.sub(m);
+                dr.norm();
+                d = (1 - ((dr.w[ctx.BIG.DNLEN - 1] >> (ctx.BIG.CHUNK - 1)) & 1));
+                this.cmove(dr, d);
+                r.copy(a);
+                r.add(e);
+                r.norm();
+                a.cmove(r, d);
+
+                // if (DBIG.comp(this,m)>0)
+                // {
+                //     a.add(e);
+                //     a.norm();
+                //     this.sub(m);
+                //     this.norm();
+                // }
+
+                k--;
+            }
+            return a;
+        },
+
+        /* split this DBIG at position n, return higher half, keep lower half */
+        split: function(n) {
+            var t = new ctx.BIG(0),
+                m = n % ctx.BIG.BASEBITS,
+                carry = this.w[ctx.BIG.DNLEN - 1] << (ctx.BIG.BASEBITS - m),
+                nw, i;
+
+            for (i = ctx.BIG.DNLEN - 2; i >= ctx.BIG.NLEN - 1; i--) {
+                nw = (this.w[i] >> m) | carry;
+                carry = (this.w[i] << (ctx.BIG.BASEBITS - m)) & ctx.BIG.BMASK;
+                t.w[i - ctx.BIG.NLEN + 1] = nw;
+            }
+
+            this.w[ctx.BIG.NLEN - 1] &= ((1 << m) - 1);
+
+            return t;
+        }
+
+    };
+
+    /* Compare a and b, return 0 if a==b, -1 if a<b, +1 if a>b. Inputs must be normalised */
+    DBIG.comp = function(a, b) {
+        var i;
+
+        for (i = ctx.BIG.DNLEN - 1; i >= 0; i--) {
+            if (a.w[i] == b.w[i]) {
+                continue;
+            }
+
+            if (a.w[i] > b.w[i]) {
+                return 1;
+            } else {
+                return -1;
+            }
+        }
+
+        return 0;
+    };
+
+    return DBIG;
+};
diff --git a/version3/js/ctx.js b/version3/js/ctx.js
new file mode 100644
index 0000000..17f08b5
--- /dev/null
+++ b/version3/js/ctx.js
@@ -0,0 +1,611 @@
+/*
+    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.
+*/
+
+var CTX = function(input_parameter) {
+    "use strict";
+
+    var ctx = this,
+        CTXLIST,
+        prepareModule;
+
+    CTXLIST = {
+        "ED25519": {
+            "BITS": "256",
+            "FIELD": "25519",
+            "CURVE": "ED25519",
+            "@NB": 32,      /* Number of bytes in Modulus */
+            "@BASE": 24,    /* Number base as power of 2 */
+            "@NBT": 255,    /* Number of bits in modulus */
+            "@M8": 5,       /* Modulus mod 8 */
+            "@MT": 1,       /* Modulus Type (pseudo-mersenne,...) */
+            "@CT": 1,       /* Curve Type (Weierstrass,...) */
+            "@PF": 0,       /* Pairing Friendly */
+            "@ST": 0,       /* Sextic Twist Type */
+            "@SX": 0,       /* Sign of x parameter */
+            "@HT": 32,      /* Hash output size */
+			"@SH": 9,       /* Maximum field excess */
+            "@AK": 16       /* AES key size */
+        },
+
+        "C25519": {
+            "BITS": "256",
+            "FIELD": "25519",
+            "CURVE": "C25519",
+            "@NB": 32,
+            "@BASE": 24,
+            "@NBT": 255,
+            "@M8": 5,
+            "@MT": 1,
+            "@CT": 2,
+            "@PF": 0,
+            "@ST": 0,
+            "@SX": 0,
+            "@HT": 32,
+			"@SH": 9, 
+            "@AK": 16
+        },
+
+
+        "SECP256K1": {
+            "BITS": "256",
+            "FIELD": "SECP256K1",
+            "CURVE": "SECP256K1",
+            "@NB": 32,
+            "@BASE": 24,
+            "@NBT": 256,
+            "@M8": 7,
+            "@MT": 0,
+            "@CT": 0,
+            "@PF": 0,
+            "@ST": 0,
+            "@SX": 0,
+            "@HT": 32,
+			"@SH": 8, 
+            "@AK": 16
+        },
+
+        "NIST256": {
+            "BITS": "256",
+            "FIELD": "NIST256",
+            "CURVE": "NIST256",
+            "@NB": 32,
+            "@BASE": 24,
+            "@NBT": 256,
+            "@M8": 7,
+            "@MT": 0,
+            "@CT": 0,
+            "@PF": 0,
+            "@ST": 0,
+            "@SX": 0,
+            "@HT": 32,
+			"@SH": 8, 
+            "@AK": 16
+        },
+
+        "NIST384": {
+            "BITS": "384",
+            "FIELD": "NIST384",
+            "CURVE": "NIST384",
+            "@NB": 48,
+            "@BASE": 23,
+            "@NBT": 384,
+            "@M8": 7,
+            "@MT": 0,
+            "@CT": 0,
+            "@PF": 0,
+            "@ST": 0,
+            "@SX": 0,
+            "@HT": 48,
+			"@SH": 7, 
+            "@AK": 24
+        },
+
+        "BRAINPOOL": {
+            "BITS": "256",
+            "FIELD": "BRAINPOOL",
+            "CURVE": "BRAINPOOL",
+            "@NB": 32,
+            "@BASE": 24,
+            "@NBT": 256,
+            "@M8": 7,
+            "@MT": 0,
+            "@CT": 0,
+            "@PF": 0,
+            "@ST": 0,
+            "@SX": 0,
+            "@HT": 32,
+			"@SH": 8, 
+            "@AK": 16
+        },
+
+        "ANSSI": {
+            "BITS": "256",
+            "FIELD": "ANSSI",
+            "CURVE": "ANSSI",
+            "@NB": 32,
+            "@BASE": 24,
+            "@NBT": 256,
+            "@M8": 7,
+            "@MT": 0,
+            "@CT": 0,
+            "@PF": 0,
+            "@ST": 0,
+            "@SX": 0,
+            "@HT": 32,
+			"@SH": 8, 
+            "@AK": 16
+        },
+
+        "HIFIVE": {
+            "BITS": "336",
+            "FIELD": "HIFIVE",
+            "CURVE": "HIFIVE",
+            "@NB": 42,
+            "@BASE": 23,
+            "@NBT": 336,
+            "@M8": 5,
+            "@MT": 1,
+            "@CT": 1,
+            "@PF": 0,
+            "@ST": 0,
+            "@SX": 0,
+            "@HT": 48,
+			"@SH": 9, 
+            "@AK": 24
+        },
+
+        "GOLDILOCKS": {
+            "BITS": "448",
+            "FIELD": "GOLDILOCKS",
+            "CURVE": "GOLDILOCKS",
+            "@NB": 56,
+            "@BASE": 23,
+            "@NBT": 448,
+            "@M8": 7,
+            "@MT": 2,
+            "@CT": 1,
+            "@PF": 0,
+            "@ST": 0,
+            "@SX": 0,
+            "@HT": 64,
+			"@SH": 11, 
+            "@AK": 32
+        },
+
+        "C41417": {
+            "BITS": "416",
+            "FIELD": "C41417",
+            "CURVE": "C41417",
+            "@NB": 52,
+            "@BASE": 22,
+            "@NBT": 414,
+            "@M8": 7,
+            "@MT": 1,
+            "@CT": 1,
+            "@PF": 0,
+            "@ST": 0,
+            "@SX": 0,
+            "@HT": 64,
+			"@SH": 4, 
+            "@AK": 32
+        },
+
+        "NIST521": {
+            "BITS": "528",
+            "FIELD": "NIST521",
+            "CURVE": "NIST521",
+            "@NB": 66,
+            "@BASE": 23,
+            "@NBT": 521,
+            "@M8": 7,
+            "@MT": 1,
+            "@CT": 0,
+            "@PF": 0,
+            "@ST": 0,
+            "@SX": 0,
+            "@HT": 64,
+			"@SH": 8, 
+            "@AK": 32
+        },
+
+        "NUMS256W": {
+            "BITS": "256",
+            "FIELD": "256PM",
+            "CURVE": "NUMS256W",
+            "@NB": 32,
+            "@BASE": 24,
+            "@NBT": 256,
+            "@M8": 3,
+            "@MT": 1,
+            "@CT": 0,
+            "@PF": 0,
+            "@ST": 0,
+            "@SX": 0,
+            "@HT": 32,
+			"@SH": 8, 
+            "@AK": 16
+        },
+
+        "NUMS256E": {
+            "BITS": "256",
+            "FIELD": "256PM",
+            "CURVE": "NUMS256E",
+            "@NB": 32,
+            "@BASE": 24,
+            "@NBT": 256,
+            "@M8": 3,
+            "@MT": 1,
+            "@CT": 1,
+            "@PF": 0,
+            "@ST": 0,
+            "@SX": 0,
+            "@HT": 32,
+			"@SH": 8, 
+            "@AK": 16
+        },
+
+        "NUMS384W": {
+            "BITS": "384",
+            "FIELD": "384PM",
+            "CURVE": "NUMS384W",
+            "@NB": 48,
+            "@BASE": 23,
+            "@NBT": 384,
+            "@M8": 3,
+            "@MT": 1,
+            "@CT": 0,
+            "@PF": 0,
+            "@ST": 0,
+            "@SX": 0,
+            "@HT": 48,
+			"@SH": 7, 
+            "@AK": 24
+        },
+
+        "NUMS384E": {
+            "BITS": "384",
+            "FIELD": "384PM",
+            "CURVE": "NUMS384E",
+            "@NB": 48,
+            "@BASE": 23,
+            "@NBT": 384,
+            "@M8": 3,
+            "@MT": 1,
+            "@CT": 1,
+            "@PF": 0,
+            "@ST": 0,
+            "@SX": 0,
+            "@HT": 48,
+			"@SH": 7, 
+            "@AK": 24
+        },
+
+        "NUMS512W": {
+            "BITS": "512",
+            "FIELD": "512PM",
+            "CURVE": "NUMS512W",
+            "@NB": 64,
+            "@BASE": 23,
+            "@NBT": 512,
+            "@M8": 7,
+            "@MT": 1,
+            "@CT": 0,
+            "@PF": 0,
+            "@ST": 0,
+            "@SX": 0,
+            "@HT": 64,
+			"@SH": 11, 
+            "@AK": 32
+        },
+
+        "NUMS512E": {
+            "BITS": "512",
+            "FIELD": "512PM",
+            "CURVE": "NUMS512E",
+            "@NB": 64,
+            "@BASE": 23,
+            "@NBT": 512,
+            "@M8": 7,
+            "@MT": 1,
+            "@CT": 1,
+            "@PF": 0,
+            "@ST": 0,
+            "@SX": 0,
+            "@HT": 64,
+			"@SH": 11, 
+            "@AK": 32
+        },
+
+        "FP256BN": {
+            "BITS": "256",
+            "FIELD": "FP256BN",
+            "CURVE": "FP256BN",
+            "@NB": 32,
+            "@BASE": 24,
+            "@NBT": 256,
+            "@M8": 3,
+            "@MT": 0,
+            "@CT": 0,
+            "@PF": 1,
+            "@ST": 1,
+            "@SX": 1,
+            "@HT": 32,
+			"@SH": 8, 
+            "@AK": 16
+        },
+
+        "FP512BN": {
+            "BITS": "512",
+            "FIELD": "FP512BN",
+            "CURVE": "FP512BN",
+            "@NB": 64,
+            "@BASE": 23,
+            "@NBT": 512,
+            "@M8": 3,
+            "@MT": 0,
+            "@CT": 0,
+            "@PF": 1,
+            "@ST": 1,
+            "@SX": 0,
+            "@HT": 32,
+			"@SH": 11, 
+            "@AK": 16
+        },
+
+        "BN254": {
+            "BITS": "256",
+            "FIELD": "BN254",
+            "CURVE": "BN254",
+            "@NB": 32,
+            "@BASE": 24,
+            "@NBT": 254,
+            "@M8": 3,
+            "@MT": 0,
+            "@CT": 0,
+            "@PF": 1,
+            "@ST": 0,
+            "@SX": 1,
+            "@HT": 32,
+			"@SH": 10, 
+            "@AK": 16
+        },
+
+        "BN254CX": {
+            "BITS": "256",
+            "FIELD": "BN254CX",
+            "CURVE": "BN254CX",
+            "@NB": 32,
+            "@BASE": 24,
+            "@NBT": 254,
+            "@M8": 3,
+            "@MT": 0,
+            "@CT": 0,
+            "@PF": 1,
+            "@ST": 0,
+            "@SX": 1,
+            "@HT": 32,
+			"@SH": 10, 
+            "@AK": 16
+        },
+
+        "BLS383": {
+            "BITS": "384",
+            "FIELD": "BLS383",
+            "CURVE": "BLS383",
+            "@NB": 48,
+            "@BASE": 23,
+            "@NBT": 383,
+            "@M8": 3,
+            "@MT": 0,
+            "@CT": 0,
+            "@PF": 2,
+            "@ST": 1,
+            "@SX": 0,
+            "@HT": 32,
+			"@SH": 8, 
+            "@AK": 16
+        },
+
+        "BLS24": {
+            "BITS": "480",
+            "FIELD": "BLS24",
+            "CURVE": "BLS24",
+            "@NB": 60,
+            "@BASE": 23,
+            "@NBT": 479,
+            "@M8": 3,
+            "@MT": 0,
+            "@CT": 0,
+            "@PF": 3,
+            "@ST": 1,
+            "@SX": 0,
+            "@HT": 48,
+			"@SH": 4, 
+            "@AK": 24
+        },
+
+        "BLS48": {
+            "BITS": "560",
+            "FIELD": "BLS48",
+            "CURVE": "BLS48",
+            "@NB": 70,
+            "@BASE": 23,
+            "@NBT": 556,
+            "@M8": 3,
+            "@MT": 0,
+            "@CT": 0,
+            "@PF": 4,
+            "@ST": 1,
+            "@SX": 0,
+            "@HT": 64,
+			"@SH": 11, 
+            "@AK": 32
+        },
+
+        "BLS381": {
+            "BITS": "381",
+            "FIELD": "BLS381",
+            "CURVE": "BLS381",
+            "@NB": 48,
+            "@BASE": 23,
+            "@NBT": 381,
+            "@M8": 3,
+            "@MT": 0,
+            "@CT": 0,
+            "@PF": 2,
+            "@ST": 1,
+            "@SX": 1,
+            "@HT": 32,
+			"@SH": 10, 
+            "@AK": 16
+        },
+
+        "BLS461": {
+            "BITS": "464",
+            "FIELD": "BLS461",
+            "CURVE": "BLS461",
+            "@NB": 58,
+            "@BASE": 23,
+            "@NBT": 461,
+            "@M8": 3,
+            "@MT": 0,
+            "@CT": 0,
+            "@PF": 2,
+            "@ST": 1,
+            "@SX": 1,
+            "@HT": 32,
+			"@SH": 11, 
+            "@AK": 16
+        },
+
+        "RSA2048": {
+            "BITS": "1024",
+            "TFF": "2048",
+            "@NB": 128,
+            "@BASE": 22,
+            "@ML": 2,
+        },
+
+        "RSA3072": {
+            "BITS": "384",
+            "TFF": "3072",
+            "@NB": 48,
+            "@BASE": 23,
+            "@ML": 8,
+        },
+
+        "RSA4096": {
+            "BITS": "512",
+            "TFF": "4096",
+            "@NB": 64,
+            "@BASE": 23,
+            "@ML": 8,
+        },
+    };
+
+    prepareModule = function (moduleName, fileName, propertyName) {
+        if (!propertyName) {
+            propertyName = moduleName;
+        }
+
+        if (typeof require !== "undefined") {
+            if (!fileName) {
+                fileName = moduleName.toLowerCase();
+            }
+
+            ctx[propertyName] = require("./" + fileName)[moduleName](ctx);
+        } else {
+            ctx[propertyName] = window[moduleName](ctx);
+        }
+    };
+
+    prepareModule("AES");
+    prepareModule("GCM");
+    prepareModule("UInt64");
+    prepareModule("HASH256");
+    prepareModule("HASH384");
+    prepareModule("HASH512");
+    prepareModule("SHA3");
+    prepareModule("RAND");
+    //prepareModule("NewHope");
+    prepareModule("NHS");
+
+    if (typeof input_parameter === "undefined") {
+        return;
+    }
+
+    ctx.config = CTXLIST[input_parameter];
+
+    // Set BIG parameters
+    prepareModule("BIG");
+    prepareModule("DBIG", "big");
+
+    // Set RSA parameters
+    if (typeof ctx.config["TFF"] !== "undefined") {
+        prepareModule("FF");
+        prepareModule("RSA");
+        prepareModule("rsa_public_key", "rsa");
+        prepareModule("rsa_private_key", "rsa");
+        return;
+    }
+
+    // Set Elliptic Curve parameters
+    if (typeof ctx.config["CURVE"] !== "undefined") {
+        prepareModule("ROM_CURVE_" + ctx.config["CURVE"], "rom_curve", "ROM_CURVE");
+
+        prepareModule("ROM_FIELD_" + ctx.config["FIELD"], "rom_field", "ROM_FIELD");
+
+        prepareModule("FP");
+        prepareModule("ECP");
+        prepareModule("ECDH");
+
+        if (ctx.config["@PF"] == 1   || ctx.config["@PF"] == 2) {
+            prepareModule("FP2");
+            prepareModule("FP4");
+            prepareModule("FP12");
+            prepareModule("ECP2");
+            prepareModule("PAIR");
+            prepareModule("MPIN");
+        }
+
+        if (ctx.config["@PF"] == 3) {
+            prepareModule("FP2");
+            prepareModule("FP4");
+            prepareModule("FP8");
+            prepareModule("FP24");
+            prepareModule("ECP4");
+            prepareModule("PAIR192");
+            prepareModule("MPIN192");
+        }
+
+        if (ctx.config["@PF"] == 4) {
+            prepareModule("FP2");
+            prepareModule("FP4");
+            prepareModule("FP8");
+            prepareModule("FP16");
+            prepareModule("FP48");
+            prepareModule("ECP8");
+            prepareModule("PAIR256");
+            prepareModule("MPIN256");
+        }
+
+        return;
+    }
+
+};
diff --git a/version3/js/ecdh.js b/version3/js/ecdh.js
new file mode 100644
index 0000000..8c49bef
--- /dev/null
+++ b/version3/js/ecdh.js
@@ -0,0 +1,771 @@
+/*
+    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.
+*/
+
+var ECDH = function(ctx) {
+    "use strict";
+
+    var ECDH = {
+
+        INVALID_PUBLIC_KEY: -2,
+        ERROR: -3,
+        INVALID: -4,
+        EFS: ctx.BIG.MODBYTES,
+        EGS: ctx.BIG.MODBYTES,
+        //EAS: 16,
+        //EBS: 16,
+        SHA256: 32,
+        SHA384: 48,
+        SHA512: 64,
+
+        //HASH_TYPE: 64,
+
+        /* Convert Integer to n-byte array */
+        inttobytes: function(n, len) {
+            var b = [],
+                i;
+
+            for (i = 0; i < len; i++) {
+                b[i] = 0;
+            }
+
+            i = len;
+            while (n > 0 && i > 0) {
+                i--;
+                b[i] = (n & 0xff);
+                n = Math.floor(n / 256);
+            }
+
+            return b;
+        },
+
+        bytestostring: function(b) {
+            var s = "",
+                len = b.length,
+                ch, i;
+
+            for (i = 0; i < len; i++) {
+                ch = b[i];
+                //s += String.fromCharCode(ch);
+                s += ((ch >>> 4) & 15).toString(16);
+                s += (ch & 15).toString(16);
+            }
+
+            return s;
+        },
+
+        stringtobytes: function(s) {
+            var b = [],
+                i;
+
+            for (i = 0; i < s.length; i++) {
+                b.push(s.charCodeAt(i));
+            }
+
+            return b;
+        },
+
+        hashit: function(sha, A, n, B, pad) {
+            var R = [],
+                H, W, i, len;
+
+            if (sha == this.SHA256) {
+                H = new ctx.HASH256();
+            } else if (sha == this.SHA384) {
+                H = new ctx.HASH384();
+            } else if (sha == this.SHA512) {
+                H = new ctx.HASH512();
+            }
+
+            if (n > 0) {
+                H.process_num(n);
+            }
+            if (B != null) {
+                H.process_array(B);
+            }
+            R = H.hash();
+
+            if (R.length == 0) {
+                return null;
+            }
+
+            if (pad == 0) {
+                return R;
+            }
+
+            W = [];
+
+            len = pad; // ctx.BIG.MODBYTES;
+
+            if (sha >= len) {
+                for (i = 0; i < len; i++) {
+                    W[i] = R[i];
+                }
+            } else {
+                for (i = 0; i < sha; i++) {
+                    W[i + len - sha] = R[i];
+                }
+
+                for (i = 0; i < len - sha; i++) {
+                    W[i] = 0;
+                }
+            }
+
+            return W;
+        },
+
+        KDF1: function(sha, Z, olen) {
+            /* NOTE: the parameter olen is the length of the output K in bytes */
+            var hlen = sha,
+                K = [],
+                B = [],
+                k = 0,
+                counter, cthreshold, i;
+
+            for (i = 0; i < K.length; i++) {
+                K[i] = 0; // redundant?
+            }
+
+            cthreshold = Math.floor(olen / hlen);
+            if (olen % hlen !== 0) {
+                cthreshold++;
+            }
+
+            for (counter = 0; counter < cthreshold; counter++) {
+                B = this.hashit(sha, Z, counter, null, 0);
+
+                if (k + hlen > olen) {
+                    for (i = 0; i < olen % hlen; i++) {
+                        K[k++] = B[i];
+                    }
+                } else {
+                    for (i = 0; i < hlen; i++) {
+                        K[k++] = B[i];
+                    }
+                }
+            }
+
+            return K;
+        },
+
+        KDF2: function(sha, Z, P, olen) {
+            /* NOTE: the parameter olen is the length of the output k in bytes */
+            var hlen = sha,
+                K = [],
+                B = [],
+                k = 0,
+                counter, cthreshold, i;
+
+            for (i = 0; i < K.length; i++) {
+                K[i] = 0; // redundant?
+            }
+
+            cthreshold = Math.floor(olen / hlen);
+            if (olen % hlen !== 0) {
+                cthreshold++;
+            }
+
+            for (counter = 1; counter <= cthreshold; counter++) {
+                B = this.hashit(sha, Z, counter, P, 0);
+
+                if (k + hlen > olen) {
+                    for (i = 0; i < olen % hlen; i++) {
+                        K[k++] = B[i];
+                    }
+                } else {
+                    for (i = 0; i < hlen; i++) {
+                        K[k++] = B[i];
+                    }
+                }
+            }
+
+            return K;
+        },
+
+        /* Password based Key Derivation Function */
+        /* Input password p, salt s, and repeat count */
+        /* Output key of length olen */
+
+        PBKDF2: function(sha, Pass, Salt, rep, olen) {
+            var F = new Array(sha),
+                U = [],
+                S = [],
+                K = [],
+                opt = 0,
+                i, j, k, d, N, key;
+
+            d = Math.floor(olen / sha);
+
+            if (olen % sha !== 0) {
+                d++;
+            }
+
+            opt = 0;
+
+            for (i = 1; i <= d; i++) {
+                for (j = 0; j < Salt.length; j++) {
+                    S[j] = Salt[j];
+                }
+
+                N = this.inttobytes(i, 4);
+
+                for (j = 0; j < 4; j++) {
+                    S[Salt.length + j] = N[j];
+                }
+
+                this.HMAC(sha, S, Pass, F);
+
+                for (j = 0; j < sha; j++) {
+                    U[j] = F[j];
+                }
+
+                for (j = 2; j <= rep; j++) {
+                    this.HMAC(sha, U, Pass, U);
+                    for (k = 0; k < sha; k++) {
+                        F[k] ^= U[k];
+                    }
+                }
+
+                for (j = 0; j < sha; j++) {
+                    K[opt++] = F[j];
+                }
+            }
+
+            key = [];
+            for (i = 0; i < olen; i++) {
+                key[i] = K[i];
+            }
+
+            return key;
+        },
+
+        HMAC: function(sha, M, K, tag) {
+            /* Input is from an octet m        *
+             * olen is requested output length in bytes. k is the key  *
+             * The output is the calculated tag */
+            var olen = tag.length,
+                B = [],
+                b = 64,
+                K0, i;
+
+            if (sha > 32) {
+                b = 128;
+            }
+
+            K0 = new Array(b);
+
+            //b=K0.length;
+            if (olen < 4) {
+                return 0;
+            }
+
+            for (i = 0; i < b; i++) {
+                K0[i] = 0;
+            }
+
+            if (K.length > b) {
+                B = this.hashit(sha, K, 0, null, 0);
+                for (i = 0; i < sha; i++) {
+                    K0[i] = B[i];
+                }
+            } else {
+                for (i = 0; i < K.length; i++) {
+                    K0[i] = K[i];
+                }
+            }
+
+            for (i = 0; i < b; i++) {
+                K0[i] ^= 0x36;
+            }
+
+            B = this.hashit(sha, K0, 0, M, 0);
+
+            for (i = 0; i < b; i++) {
+                K0[i] ^= 0x6a;
+            }
+
+            B = this.hashit(sha, K0, 0, B, olen);
+
+            for (i = 0; i < olen; i++) {
+                tag[i] = B[i];
+            }
+
+            return 1;
+        },
+
+        /* ctx.AES encryption/decryption */
+
+        AES_CBC_IV0_ENCRYPT: function(K, M) { /* ctx.AES CBC encryption, with Null IV and key K */
+            /* Input is from an octet string M, output is to an octet string C */
+            /* Input is padded as necessary to make up a full final block */
+            var a = new ctx.AES(),
+                buff = [],
+                C = [],
+                fin, padlen, i, j, ipt, opt;
+            /*var clen=16+(Math.floor(M.length/16))*16;*/
+
+            a.init(ctx.AES.CBC, K.length, K, null);
+
+            ipt = opt = 0;
+            fin = false;
+
+            for (;;) {
+                for (i = 0; i < 16; i++) {
+                    if (ipt < M.length) {
+                        buff[i] = M[ipt++];
+                    } else {
+                        fin = true;
+                        break;
+                    }
+                }
+
+                if (fin) {
+                    break;
+                }
+
+                a.encrypt(buff);
+
+                for (i = 0; i < 16; i++) {
+                    C[opt++] = buff[i];
+                }
+            }
+
+            /* last block, filled up to i-th index */
+
+            padlen = 16 - i;
+            for (j = i; j < 16; j++) {
+                buff[j] = padlen;
+            }
+            a.encrypt(buff);
+            for (i = 0; i < 16; i++) {
+                C[opt++] = buff[i];
+            }
+            a.end();
+
+            return C;
+        },
+
+        AES_CBC_IV0_DECRYPT: function(K, C) { /* padding is removed */
+            var a = new ctx.AES(),
+                buff = [],
+                MM = [],
+                ipt = 0,
+                opt = 0,
+                M, ch, fin, bad, padlen, i;
+
+            a.init(ctx.AES.CBC, K.length, K, null);
+
+            if (C.length === 0) {
+                return [];
+            }
+            ch = C[ipt++];
+
+            fin = false;
+
+            for (;;) {
+                for (i = 0; i < 16; i++) {
+                    buff[i] = ch;
+                    if (ipt >= C.length) {
+                        fin = true;
+                        break;
+                    } else {
+                        ch = C[ipt++];
+                    }
+                }
+                a.decrypt(buff);
+                if (fin) {
+                    break;
+                }
+
+                for (i = 0; i < 16; i++) {
+                    MM[opt++] = buff[i];
+                }
+            }
+
+            a.end();
+            bad = false;
+            padlen = buff[15];
+
+            if (i != 15 || padlen < 1 || padlen > 16) {
+                bad = true;
+            }
+
+            if (padlen >= 2 && padlen <= 16) {
+                for (i = 16 - padlen; i < 16; i++) {
+                    if (buff[i] != padlen) {
+                        bad = true;
+                    }
+                }
+            }
+
+            if (!bad) {
+                for (i = 0; i < 16 - padlen; i++) {
+                    MM[opt++] = buff[i];
+                }
+            }
+
+            M = [];
+            if (bad) {
+                return M;
+            }
+
+            for (i = 0; i < opt; i++) {
+                M[i] = MM[i];
+            }
+
+            return M;
+        },
+
+        KEY_PAIR_GENERATE: function(RNG, S, W) {
+            var res = 0,
+                r, s, G, WP;
+            // var T=[];
+
+            G = ctx.ECP.generator();
+
+            r = new ctx.BIG(0);
+            r.rcopy(ctx.ROM_CURVE.CURVE_Order);
+
+            if (RNG === null) {
+                s = ctx.BIG.fromBytes(S);
+                s.mod(r);
+            } else {
+                s = ctx.BIG.randomnum(r, RNG);
+                // s.toBytes(T);
+                // for (var i=0;i<this.EGS;i++) S[i]=T[i];
+            }
+
+            // if (ROM.AES_S>0)
+            // {
+            //  s.mod2m(2*ROM.AES_S);
+            // }
+
+            s.toBytes(S);
+
+            WP = G.mul(s);
+            WP.toBytes(W,false);  // To use point compression on public keys, change to true 
+
+            return res;
+        },
+
+        PUBLIC_KEY_VALIDATE: function(W) {
+            var WP = ctx.ECP.fromBytes(W),
+                res = 0,
+                r, q, nb, k;
+
+            r = new ctx.BIG(0);
+            r.rcopy(ctx.ROM_CURVE.CURVE_Order);
+
+            if (WP.is_infinity()) {
+                res = this.INVALID_PUBLIC_KEY;
+            }
+
+            if (res === 0) {
+                q = new ctx.BIG(0);
+                q.rcopy(ctx.ROM_FIELD.Modulus);
+                nb = q.nbits();
+                k = new ctx.BIG(1);
+                k.shl(Math.floor((nb + 4) / 2));
+                k.add(q);
+                k.div(r);
+
+                while (k.parity() == 0) {
+                    k.shr(1);
+                    WP.dbl();
+                }
+
+                if (!k.isunity()) {
+                    WP = WP.mul(k);
+                }
+
+                if (WP.is_infinity()) {
+                    res = this.INVALID_PUBLIC_KEY;
+                }
+            }
+
+            return res;
+        },
+
+        ECPSVDP_DH: function(S, WD, Z) {
+            var T = [],
+                res = 0,
+                r, s, i,
+                W;
+
+            s = ctx.BIG.fromBytes(S);
+
+            W = ctx.ECP.fromBytes(WD);
+            if (W.is_infinity()) {
+                res = this.ERROR;
+            }
+
+            if (res === 0) {
+                r = new ctx.BIG(0);
+                r.rcopy(ctx.ROM_CURVE.CURVE_Order);
+                s.mod(r);
+                W = W.mul(s);
+
+                if (W.is_infinity()) {
+                    res = this.ERROR;
+                } else {
+                    W.getX().toBytes(T);
+                    for (i = 0; i < this.EFS; i++) {
+                        Z[i] = T[i];
+                    }
+                }
+            }
+
+            return res;
+        },
+
+        ECPSP_DSA: function(sha, RNG, S, F, C, D) {
+            var T = [],
+                i, r, s, f, c, d, u, vx, w,
+                G, V, B;
+
+            B = this.hashit(sha, F, 0, null, ctx.BIG.MODBYTES);
+
+            G = ctx.ECP.generator();
+
+            r = new ctx.BIG(0);
+            r.rcopy(ctx.ROM_CURVE.CURVE_Order);
+
+            s = ctx.BIG.fromBytes(S);
+            f = ctx.BIG.fromBytes(B);
+
+            c = new ctx.BIG(0);
+            d = new ctx.BIG(0);
+            V = new ctx.ECP();
+
+            do {
+                u = ctx.BIG.randomnum(r, RNG);
+                w = ctx.BIG.randomnum(r, RNG);  /* side channel masking */
+                // if (ROM.AES_S>0)
+                // {
+                //  u.mod2m(2*ROM.AES_S);
+                // }
+                V.copy(G);
+                V = V.mul(u);
+                vx = V.getX();
+                c.copy(vx);
+                c.mod(r);
+                if (c.iszilch()) {
+                    continue;
+                }
+                u = ctx.BIG.modmul(u, w, r);
+                u.invmodp(r);
+                d = ctx.BIG.modmul(s, c, r);
+                d.add(f);
+                d = ctx.BIG.modmul(d, w, r);
+                d = ctx.BIG.modmul(u, d, r);
+            } while (d.iszilch());
+
+            c.toBytes(T);
+            for (i = 0; i < this.EFS; i++) {
+                C[i] = T[i];
+            }
+            d.toBytes(T);
+            for (i = 0; i < this.EFS; i++) {
+                D[i] = T[i];
+            }
+
+            return 0;
+        },
+
+        ECPVP_DSA: function(sha, W, F, C, D) {
+            var B = [],
+                res = 0,
+                r, f, c, d, h2,
+                G, WP, P;
+
+            B = this.hashit(sha, F, 0, null, ctx.BIG.MODBYTES);
+
+            G = ctx.ECP.generator();
+
+            r = new ctx.BIG(0);
+            r.rcopy(ctx.ROM_CURVE.CURVE_Order);
+
+            c = ctx.BIG.fromBytes(C);
+            d = ctx.BIG.fromBytes(D);
+            f = ctx.BIG.fromBytes(B);
+
+            if (c.iszilch() || ctx.BIG.comp(c, r) >= 0 || d.iszilch() || ctx.BIG.comp(d, r) >= 0) {
+                res = this.INVALID;
+            }
+
+            if (res === 0) {
+                d.invmodp(r);
+                f = ctx.BIG.modmul(f, d, r);
+                h2 = ctx.BIG.modmul(c, d, r);
+
+                WP = ctx.ECP.fromBytes(W);
+                if (WP.is_infinity()) {
+                    res = this.ERROR;
+                } else {
+                    P = new ctx.ECP();
+                    P.copy(WP);
+                    P = P.mul2(h2, G, f);
+
+                    if (P.is_infinity()) {
+                        res = this.INVALID;
+                    } else {
+                        d = P.getX();
+                        d.mod(r);
+                        if (ctx.BIG.comp(d, c) !== 0) {
+                            res = this.INVALID;
+                        }
+                    }
+                }
+            }
+
+            return res;
+        },
+
+        ECIES_ENCRYPT: function(sha, P1, P2, RNG, W, M, V, T) {
+            var Z = [],
+                VZ = [],
+                K1 = [],
+                K2 = [],
+                U = [],
+                C = [],
+                K, L2, AC, i;
+
+            if (this.KEY_PAIR_GENERATE(RNG, U, V) !== 0) {
+                return C;
+            }
+
+            if (this.ECPSVDP_DH(U, W, Z) !== 0) {
+                return C;
+            }
+
+            for (i = 0; i < 2 * this.EFS + 1; i++) {
+                VZ[i] = V[i];
+            }
+
+            for (i = 0; i < this.EFS; i++) {
+                VZ[2 * this.EFS + 1 + i] = Z[i];
+            }
+
+            K = this.KDF2(sha, VZ, P1, 2*ctx.ECP.AESKEY);
+
+            for (i = 0; i < ctx.ECP.AESKEY; i++) {
+                K1[i] = K[i];
+                K2[i] = K[ctx.ECP.AESKEY + i];
+            }
+
+            C = this.AES_CBC_IV0_ENCRYPT(K1, M);
+
+            L2 = this.inttobytes(P2.length, 8);
+
+            AC = [];
+            for (i = 0; i < C.length; i++) {
+                AC[i] = C[i];
+            }
+            for (i = 0; i < P2.length; i++) {
+                AC[C.length + i] = P2[i];
+            }
+            for (i = 0; i < 8; i++) {
+                AC[C.length + P2.length + i] = L2[i];
+            }
+
+            this.HMAC(sha, AC, K2, T);
+
+            return C;
+        },
+
+		ncomp: function(T1,T2,n) {
+			var res=0;
+			for (var i=0;i<n;i++)
+			{
+				res|=(T1[i]^T2[i]);
+			}
+			if (res==0) return true;
+			return false;
+		},
+
+        ECIES_DECRYPT: function(sha, P1, P2, V, C, T, U) {
+            var Z = [],
+                VZ = [],
+                K1 = [],
+                K2 = [],
+                TAG = new Array(T.length),
+                M = [],
+                K, L2, AC, same, i;
+
+            if (this.ECPSVDP_DH(U, V, Z) !== 0) {
+                return M;
+            }
+
+            for (i = 0; i < 2 * this.EFS + 1; i++) {
+                VZ[i] = V[i];
+            }
+
+            for (i = 0; i < this.EFS; i++) {
+                VZ[2 * this.EFS + 1 + i] = Z[i];
+            }
+
+            K = this.KDF2(sha, VZ, P1, 2*ctx.ECP.AESKEY);
+
+            for (i = 0; i < ctx.ECP.AESKEY; i++) {
+                K1[i] = K[i];
+                K2[i] = K[ctx.ECP.AESKEY + i];
+            }
+
+            M = this.AES_CBC_IV0_DECRYPT(K1, C);
+
+            if (M.length === 0) {
+                return M;
+            }
+
+            L2 = this.inttobytes(P2.length, 8);
+
+            AC = [];
+
+            for (i = 0; i < C.length; i++) {
+                AC[i] = C[i];
+            }
+            for (i = 0; i < P2.length; i++) {
+                AC[C.length + i] = P2[i];
+            }
+            for (i = 0; i < 8; i++) {
+                AC[C.length + P2.length + i] = L2[i];
+            }
+
+            this.HMAC(sha, AC, K2, TAG);
+
+			if (!this.ncomp(T,TAG,T.length)) {
+				return [];
+			}
+		
+  //          same = true;
+  //          for (i = 0; i < T.length; i++) {
+  //              if (T[i] != TAG[i]) {
+  //                  same = false;
+  //              }
+  //          }
+
+  //          if (!same) {
+  //              return [];
+  //          }
+
+            return M;
+        }
+    };
+
+    return ECDH;
+};
diff --git a/version3/js/ecp.js b/version3/js/ecp.js
new file mode 100644
index 0000000..b49fdd9
--- /dev/null
+++ b/version3/js/ecp.js
@@ -0,0 +1,1398 @@
+/*
+    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.
+*/
+
+/* Elliptic Curve Point class */
+
+var ECP = function(ctx) {
+    "use strict";
+
+    /* Constructor */
+    var ECP = function() {
+        this.x = new ctx.FP(0);
+        this.y = new ctx.FP(1);
+        if (ECP.CURVETYPE != ECP.EDWARDS) {
+            this.z = new ctx.FP(0);
+        } else {
+            this.z = new ctx.FP(1);
+        }
+    };
+
+    ECP.WEIERSTRASS = 0;
+    ECP.EDWARDS = 1;
+    ECP.MONTGOMERY = 2;
+    ECP.NOT = 0;
+    ECP.BN = 1;
+    ECP.BLS = 2;
+    ECP.D_TYPE = 0;
+    ECP.M_TYPE = 1;
+    ECP.POSITIVEX = 0;
+    ECP.NEGATIVEX = 1;
+
+    ECP.CURVETYPE = ctx.config["@CT"];
+    ECP.CURVE_PAIRING_TYPE = ctx.config["@PF"];
+    ECP.SEXTIC_TWIST = ctx.config["@ST"];
+    ECP.SIGN_OF_X = ctx.config["@SX"];
+
+    ECP.HASH_TYPE = ctx.config["@HT"];
+    ECP.AESKEY = ctx.config["@AK"];
+
+    ECP.prototype = {
+        /* test this=O point-at-infinity */
+        is_infinity: function() {
+            // if (this.INF) {
+            //    return true;
+            // }
+            this.x.reduce();
+            this.z.reduce();
+
+            if (ECP.CURVETYPE == ECP.EDWARDS) {
+
+                this.y.reduce();
+
+                return (this.x.iszilch() && this.y.equals(this.z));
+            } else if (ECP.CURVETYPE == ECP.WEIERSTRASS) {
+                this.y.reduce();
+                return (this.x.iszilch() && this.z.iszilch());
+            } else if (ECP.CURVETYPE == ECP.MONTGOMERY) {
+                return (this.z.iszilch());
+            }
+
+            return true;
+        },
+
+        /* conditional swap of this and Q dependant on d */
+        cswap: function(Q, d) {
+            // var bd;
+
+            this.x.cswap(Q.x, d);
+            if (ECP.CURVETYPE != ECP.MONTGOMERY) {
+                this.y.cswap(Q.y, d);
+            }
+            this.z.cswap(Q.z, d);
+
+            // bd = (d !== 0) ? true : false;
+            // bd = bd & (this.INF ^ Q.INF);
+            // this.INF ^= bd;
+            // Q.INF ^= bd;
+
+        },
+
+        /* conditional move of Q to P dependant on d */
+        cmove: function(Q, d) {
+            // var bd;
+
+            this.x.cmove(Q.x, d);
+            if (ECP.CURVETYPE != ECP.MONTGOMERY) {
+                this.y.cmove(Q.y, d);
+            }
+            this.z.cmove(Q.z, d);
+
+            // bd = (d !== 0) ? true : false;
+            // this.INF ^= (this.INF ^ Q.INF) & bd;
+        },
+
+        /* Constant time select from pre-computed table */
+        select: function(W, b) {
+            var MP = new ECP(),
+                m = b >> 31,
+                babs = (b ^ m) - m;
+
+            babs = (babs - 1) / 2;
+
+            this.cmove(W[0], ECP.teq(babs, 0)); // conditional move
+            this.cmove(W[1], ECP.teq(babs, 1));
+            this.cmove(W[2], ECP.teq(babs, 2));
+            this.cmove(W[3], ECP.teq(babs, 3));
+            this.cmove(W[4], ECP.teq(babs, 4));
+            this.cmove(W[5], ECP.teq(babs, 5));
+            this.cmove(W[6], ECP.teq(babs, 6));
+            this.cmove(W[7], ECP.teq(babs, 7));
+
+            MP.copy(this);
+            MP.neg();
+            this.cmove(MP, (m & 1));
+        },
+
+        /* Test P == Q */
+
+        equals: function(Q) {
+            var a, b;
+
+            // if (this.is_infinity() && Q.is_infinity()) {
+            //    return true;
+            // }
+
+            // if (this.is_infinity() || Q.is_infinity()) {
+            //    return false;
+            // }
+
+            a = new ctx.FP(0);
+            b = new ctx.FP(0);
+            a.copy(this.x);
+            a.mul(Q.z);
+            a.reduce();
+            b.copy(Q.x);
+            b.mul(this.z);
+            b.reduce();
+
+            if (!a.equals(b)) {
+                return false;
+            }
+
+            if (ECP.CURVETYPE != ECP.MONTGOMERY) {
+                a.copy(this.y);
+                a.mul(Q.z);
+                a.reduce();
+                b.copy(Q.y);
+                b.mul(this.z);
+                b.reduce();
+                if (!a.equals(b)) {
+                    return false;
+                }
+            }
+
+            return true;
+        },
+
+        /* copy this=P */
+        copy: function(P) {
+            this.x.copy(P.x);
+            if (ECP.CURVETYPE != ECP.MONTGOMERY) {
+                this.y.copy(P.y);
+            }
+            this.z.copy(P.z);
+            // this.INF = P.INF;
+        },
+
+        /* this=-this */
+        neg: function() {
+            // if (this.is_infinity()) return;
+            if (ECP.CURVETYPE == ECP.WEIERSTRASS) {
+                this.y.neg();
+                this.y.norm();
+            } else if (ECP.CURVETYPE == ECP.EDWARDS) {
+                this.x.neg();
+                this.x.norm();
+            }
+
+            return;
+        },
+
+        /* set this=O */
+        inf: function() {
+            // this.INF = true;
+            this.x.zero();
+
+            if (ECP.CURVETYPE != ECP.MONTGOMERY) {
+                this.y.one();
+            }
+
+            if (ECP.CURVETYPE != ECP.EDWARDS) {
+                this.z.zero();
+            } else {
+                this.z.one();
+            }
+        },
+
+        /* set this=(x,y) where x and y are BIGs */
+        setxy: function(ix, iy) {
+            var rhs, y2;
+
+            this.x = new ctx.FP(0);
+            this.x.bcopy(ix);
+
+            this.y = new ctx.FP(0);
+            this.y.bcopy(iy);
+            this.z = new ctx.FP(1);
+			this.x.norm();
+            rhs = ECP.RHS(this.x);
+
+            if (ECP.CURVETYPE == ECP.MONTGOMERY) {
+                if (rhs.jacobi() != 1) {
+                    this.inf();
+                }
+                // if (rhs.jacobi() == 1) {
+                //    this.INF = false;
+                // } else {
+                //    this.inf();
+                // }
+            } else {
+                y2 = new ctx.FP(0);
+                y2.copy(this.y);
+                y2.sqr();
+
+                if (!y2.equals(rhs)) {
+                    this.inf();
+                }
+                // if (y2.equals(rhs)) {
+                //    this.INF = false;
+                // } else {
+                //    this.inf();
+                // }
+            }
+        },
+
+        /* set this=x, where x is ctx.BIG, y is derived from sign s */
+        setxi: function(ix, s) {
+            var rhs, ny;
+
+            this.x = new ctx.FP(0);
+            this.x.bcopy(ix);
+			this.x.norm();
+            rhs = ECP.RHS(this.x);
+            this.z = new ctx.FP(1);
+
+            if (rhs.jacobi() == 1) {
+                ny = rhs.sqrt();
+                if (ny.redc().parity() != s) {
+                    ny.neg();
+                }
+                this.y = ny;
+                // this.INF = false;
+            } else {
+                this.inf();
+            }
+        },
+
+        /* set this=x, y calculated from curve equation */
+        setx: function(ix) {
+            var rhs;
+
+            this.x = new ctx.FP(0);
+            this.x.bcopy(ix);
+			this.x.norm();
+            rhs = ECP.RHS(this.x);
+            this.z = new ctx.FP(1);
+
+            if (rhs.jacobi() == 1) {
+                if (ECP.CURVETYPE != ECP.MONTGOMERY) {
+                    this.y = rhs.sqrt();
+                }
+            // this.INF = false;
+            } else {
+                this.inf();
+            }
+        },
+
+        /* set this to affine - from (x,y,z) to (x,y) */
+        affine: function() {
+            var one;
+
+            if (this.is_infinity()) {
+                return;
+            }
+
+            one = new ctx.FP(1);
+
+            if (this.z.equals(one)) {
+                return;
+            }
+
+            this.z.inverse();
+
+            if (ECP.CURVETYPE == ECP.EDWARDS || ECP.CURVETYPE == ECP.WEIERSTRASS) {
+                this.x.mul(this.z);
+                this.x.reduce();
+                this.y.mul(this.z);
+                this.y.reduce();
+                this.z = one;
+            }
+            if (ECP.CURVETYPE == ECP.MONTGOMERY) {
+                this.x.mul(this.z);
+                this.x.reduce();
+                this.z = one;
+            }
+        },
+
+        /* extract x as ctx.BIG */
+        getX: function() {
+			var W=new ECP(); W.copy(this); W.affine();
+            //this.affine();
+            return W.x.redc();
+        },
+
+        /* extract y as ctx.BIG */
+        getY: function() {
+			var W=new ECP(); W.copy(this); W.affine();
+            //this.affine();
+            return W.y.redc();
+        },
+
+        /* get sign of Y */
+        getS: function() {
+            //this.affine();
+            var y = this.getY();
+            return y.parity();
+        },
+
+        /* extract x as ctx.FP */
+        getx: function() {
+            return this.x;
+        },
+
+        /* extract y as ctx.FP */
+        gety: function() {
+            return this.y;
+        },
+
+        /* extract z as ctx.FP */
+        getz: function() {
+            return this.z;
+        },
+
+        /* convert to byte array */
+        toBytes: function(b,compress) {
+            var t = [],
+                i;
+			var W=new ECP(); W.copy(this);
+            W.affine();
+            W.x.redc().toBytes(t);
+
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                b[i + 1] = t[i];
+            }
+
+            if (ECP.CURVETYPE == ECP.MONTGOMERY) {
+                b[0] = 0x06;
+                return;
+            }
+
+            if (compress) {
+                b[0]=0x02;
+                if (W.y.redc().parity()==1) {
+                    b[0]=0x03;
+                }
+                return;
+            }
+
+            b[0]=0x04;
+
+            W.y.redc().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                b[i + ctx.BIG.MODBYTES + 1] = t[i];
+            }
+        },
+        /* convert to hex string */
+        toString: function() {
+			var W=new ECP(); W.copy(this);
+            if (W.is_infinity()) {
+                return "infinity";
+            }
+
+            W.affine();
+
+            if (ECP.CURVETYPE == ECP.MONTGOMERY) {
+                return "(" + W.x.redc().toString() + ")";
+            } else {
+                return "(" + W.x.redc().toString() + "," + W.y.redc().toString() + ")";
+            }
+        },
+
+        /* this+=this */
+        dbl: function() {
+            var t0, t1, t2, t3, x3, y3, z3, b,
+                C, D, H, J,
+                A, B, AA, BB;
+
+            if (ECP.CURVETYPE == ECP.WEIERSTRASS) {
+                // if (this.INF) {
+                //     return;
+                // }
+
+                if (ctx.ROM_CURVE.CURVE_A == 0) {
+                    t0 = new ctx.FP(0);
+                    t0.copy(this.y); //FP t0=new FP(y);                      /*** Change ***/    // Edits made
+                    t0.sqr();
+                    t1 = new ctx.FP(0);
+                    t1.copy(this.y); //FP t1=new FP(y);
+                    t1.mul(this.z);
+                    t2 = new ctx.FP(0);
+                    t2.copy(this.z); //FP t2=new FP(z);
+                    t2.sqr();
+
+                    this.z.copy(t0);
+                    this.z.add(t0);
+                    this.z.norm();
+                    this.z.add(this.z);
+                    this.z.add(this.z);
+                    this.z.norm();
+
+                    t2.imul(3 * ctx.ROM_CURVE.CURVE_B_I);
+
+                    x3 = new ctx.FP(0);
+                    x3.copy(t2); //FP x3=new FP(t2);
+                    x3.mul(this.z);
+                    y3 = new ctx.FP(0);
+                    y3.copy(t0); //FP y3=new FP(t0);
+                    y3.add(t2);
+                    y3.norm();
+                    this.z.mul(t1);
+                    t1.copy(t2);
+                    t1.add(t2);
+                    t2.add(t1);
+                    t0.sub(t2);
+                    t0.norm();
+                    y3.mul(t0);
+                    y3.add(x3);
+                    t1.copy(this.x);
+                    t1.mul(this.y);
+                    this.x.copy(t0);
+                    this.x.norm();
+                    this.x.mul(t1);
+                    this.x.add(this.x);
+
+                    this.x.norm();
+                    this.y.copy(y3);
+                    this.y.norm();
+                } else {
+                    t0 = new ctx.FP(0);
+                    t0.copy(this.x); //FP t0=new FP(x);
+                    t1 = new ctx.FP(0);
+                    t1.copy(this.y); //FP t1=new FP(y);
+                    t2 = new ctx.FP(0);
+                    t2.copy(this.z); //FP t2=new FP(z);
+                    t3 = new ctx.FP(0);
+                    t3.copy(this.x); //FP t3=new FP(x);
+                    z3 = new ctx.FP(0);
+                    z3.copy(this.z); //FP z3=new FP(z);
+                    y3 = new ctx.FP(0); //FP y3=new FP(0);
+                    x3 = new ctx.FP(0); //FP x3=new FP(0);
+                    b = new ctx.FP(0); //FP b=new FP(0);
+                    // System.out.println("Into dbl");
+                    if (ctx.ROM_CURVE.CURVE_B_I == 0) {
+                        b.rcopy(ctx.ROM_CURVE.CURVE_B);
+                    }
+                    // System.out.println("b= "+b.toString());
+                    t0.sqr(); //1    x^2
+                    t1.sqr(); //2    y^2
+                    t2.sqr(); //3
+
+                    t3.mul(this.y); //4
+                    t3.add(t3);
+                    t3.norm(); //5
+                    z3.mul(this.x); //6
+                    z3.add(z3);
+                    z3.norm(); //7
+                    y3.copy(t2);
+
+                    if (ctx.ROM_CURVE.CURVE_B_I == 0) {
+                        y3.mul(b); //8
+                    } else {
+                        y3.imul(ctx.ROM_CURVE.CURVE_B_I);
+                    }
+
+                    y3.sub(z3); //y3.norm(); //9  ***
+                    x3.copy(y3);
+                    x3.add(y3);
+                    x3.norm(); //10
+
+                    y3.add(x3); //y3.norm();//11
+                    x3.copy(t1);
+                    x3.sub(y3);
+                    x3.norm(); //12
+                    y3.add(t1);
+                    y3.norm(); //13
+                    y3.mul(x3); //14
+                    x3.mul(t3); //15
+                    t3.copy(t2);
+                    t3.add(t2); //t3.norm(); //16
+                    t2.add(t3); //t2.norm(); //17
+
+                    if (ctx.ROM_CURVE.CURVE_B_I == 0) {
+                        z3.mul(b); //18
+                    } else {
+                        z3.imul(ctx.ROM_CURVE.CURVE_B_I);
+                    }
+
+                    z3.sub(t2); //z3.norm();//19
+                    z3.sub(t0);
+                    z3.norm(); //20  ***
+                    t3.copy(z3);
+                    t3.add(z3); //t3.norm();//21
+
+                    z3.add(t3);
+                    z3.norm(); //22
+                    t3.copy(t0);
+                    t3.add(t0); //t3.norm(); //23
+                    t0.add(t3); //t0.norm();//24
+                    t0.sub(t2);
+                    t0.norm(); //25
+
+                    t0.mul(z3); //26
+                    y3.add(t0); //y3.norm();//27
+                    t0.copy(this.y);
+                    t0.mul(this.z); //28
+                    t0.add(t0);
+                    t0.norm(); //29
+                    z3.mul(t0); //30
+                    x3.sub(z3); //x3.norm();//31
+                    t0.add(t0);
+                    t0.norm(); //32
+                    t1.add(t1);
+                    t1.norm(); //33
+                    z3.copy(t0);
+                    z3.mul(t1); //34
+                    // System.out.println("Out of dbl");
+                    this.x.copy(x3);
+                    this.x.norm();
+                    this.y.copy(y3);
+                    this.y.norm();
+                    this.z.copy(z3);
+                    this.z.norm();
+                }
+            }
+
+            if (ECP.CURVETYPE == ECP.EDWARDS) {
+                C = new ctx.FP(0);
+                C.copy(this.x); //FP C=new FP(x);
+                D = new ctx.FP(0);
+                D.copy(this.y); //FP D=new FP(y);
+                H = new ctx.FP(0);
+                H.copy(this.z); //FP H=new FP(z);
+                J = new ctx.FP(0); //FP J=new FP(0);
+                // System.out.println("Into dbl");
+                this.x.mul(this.y);
+                this.x.add(this.x);
+                this.x.norm();
+                C.sqr();
+                D.sqr();
+                if (ctx.ROM_CURVE.CURVE_A == -1) {
+                    C.neg();
+                }
+
+                this.y.copy(C);
+                this.y.add(D);
+                this.y.norm();
+                H.sqr();
+                H.add(H);
+
+                this.z.copy(this.y);
+                J.copy(this.y);
+
+                J.sub(H);
+                J.norm();
+
+                this.x.mul(J);
+                C.sub(D);
+                C.norm();
+                this.y.mul(C);
+                this.z.mul(J);
+                // System.out.println("Out of dbl");
+            }
+
+            if (ECP.CURVETYPE == ECP.MONTGOMERY) {
+                A = new ctx.FP(0);
+                A.copy(this.x); //FP A=new FP(x);
+                B = new ctx.FP(0);
+                B.copy(this.x); //FP B=new FP(x);
+                AA = new ctx.FP(0); //FP AA=new FP(0);
+                BB = new ctx.FP(0); //FP BB=new FP(0);
+                C = new ctx.FP(0); //FP C=new FP(0);
+
+                A.add(this.z);
+                A.norm();
+                AA.copy(A);
+                AA.sqr();
+                B.sub(this.z);
+                B.norm();
+                BB.copy(B);
+                BB.sqr();
+                C.copy(AA);
+                C.sub(BB);
+                C.norm();
+                this.x.copy(AA);
+                this.x.mul(BB);
+
+                A.copy(C);
+                A.imul((ctx.ROM_CURVE.CURVE_A + 2) >> 2);
+
+                BB.add(A);
+                BB.norm();
+                this.z.copy(BB);
+                this.z.mul(C);
+            }
+
+            return;
+        },
+
+        /* this+=Q */
+        add: function(Q) {
+            var b, t0, t1, t2, t3, t4, x3, y3, z3,
+                A, B, C, D, E, F, G;
+
+            // if (this.INF) {
+            //     this.copy(Q);
+            //     return;
+            // }
+
+            // if (Q.INF) {
+            //     return;
+            // }
+
+            if (ECP.CURVETYPE == ECP.WEIERSTRASS) {
+                // System.out.println("Into add");
+                if (ctx.ROM_CURVE.CURVE_A == 0) {
+                    //  System.out.println("Into add");                      // Edits made
+
+                    b = 3 * ctx.ROM_CURVE.CURVE_B_I;
+                    t0 = new ctx.FP(0);
+                    t0.copy(this.x); //FP t0=new FP(x);
+                    t0.mul(Q.x);
+                    t1 = new ctx.FP(0);
+                    t1.copy(this.y); //FP t1=new FP(y);
+                    t1.mul(Q.y);
+                    t2 = new ctx.FP(0);
+                    t2.copy(this.z); //FP t2=new FP(z);
+                    t2.mul(Q.z);
+                    t3 = new ctx.FP(0);
+                    t3.copy(this.x); //FP t3=new FP(x);
+                    t3.add(this.y);
+                    t3.norm();
+                    t4 = new ctx.FP(0);
+                    t4.copy(Q.x); //FP t4=new FP(Q.x);
+                    t4.add(Q.y);
+                    t4.norm();
+                    t3.mul(t4);
+                    t4.copy(t0);
+                    t4.add(t1);
+
+                    t3.sub(t4);
+                    t3.norm();
+                    t4.copy(this.y);
+                    t4.add(this.z);
+                    t4.norm();
+                    x3 = new ctx.FP(0);
+                    x3.copy(Q.y); //FP x3=new FP(Q.y);
+                    x3.add(Q.z);
+                    x3.norm();
+
+                    t4.mul(x3);
+                    x3.copy(t1);
+                    x3.add(t2);
+
+                    t4.sub(x3);
+                    t4.norm();
+                    x3.copy(this.x);
+                    x3.add(this.z);
+                    x3.norm();
+                    y3 = new ctx.FP(0);
+                    y3.copy(Q.x); //FP y3=new FP(Q.x);
+                    y3.add(Q.z);
+                    y3.norm();
+                    x3.mul(y3);
+                    y3.copy(t0);
+                    y3.add(t2);
+                    y3.rsub(x3);
+                    y3.norm();
+                    x3.copy(t0);
+                    x3.add(t0);
+                    t0.add(x3);
+                    t0.norm();
+                    t2.imul(b);
+
+                    z3 = new ctx.FP(0);
+                    z3.copy(t1); //FP z3=new FP(t1);
+                    z3.add(t2);
+                    z3.norm();
+                    t1.sub(t2);
+                    t1.norm();
+                    y3.imul(b);
+
+                    x3.copy(y3);
+                    x3.mul(t4);
+                    t2.copy(t3);
+                    t2.mul(t1);
+                    x3.rsub(t2);
+                    y3.mul(t0);
+                    t1.mul(z3);
+                    y3.add(t1);
+                    t0.mul(t3);
+                    z3.mul(t4);
+                    z3.add(t0);
+
+                    // System.out.println("Out of add");
+
+                    this.x.copy(x3);
+                    this.x.norm();
+                    this.y.copy(y3);
+                    this.y.norm();
+                    this.z.copy(z3);
+                    this.z.norm();
+                } else {
+                    t0 = new ctx.FP(0);
+                    t0.copy(this.x); //FP t0=new FP(x);
+                    t1 = new ctx.FP(0);
+                    t1.copy(this.y); //FP t1=new FP(y);
+                    t2 = new ctx.FP(0);
+                    t2.copy(this.z); //FP t2=new FP(z);
+                    t3 = new ctx.FP(0);
+                    t3.copy(this.x); //FP t3=new FP(x);
+                    t4 = new ctx.FP(0);
+                    t4.copy(Q.x); //FP t4=new FP(Q.x);
+                    z3 = new ctx.FP(0); //FP z3=new FP(0);
+                    y3 = new ctx.FP(0);
+                    y3.copy(Q.x); //FP y3=new FP(Q.x);
+                    x3 = new ctx.FP(0);
+                    x3.copy(Q.y); //FP x3=new FP(Q.y);
+                    b = new ctx.FP(0); //FP b=new FP(0);
+
+                    if (ctx.ROM_CURVE.CURVE_B_I == 0) {
+                        b.rcopy(ctx.ROM_CURVE.CURVE_B);
+                    }
+                    t0.mul(Q.x); //1
+                    t1.mul(Q.y); //2
+                    t2.mul(Q.z); //3
+
+                    t3.add(this.y);
+                    t3.norm(); //4
+                    t4.add(Q.y);
+                    t4.norm(); //5
+                    t3.mul(t4); //6
+                    t4.copy(t0);
+                    t4.add(t1); //t4.norm(); //7
+                    t3.sub(t4);
+                    t3.norm(); //8
+                    t4.copy(this.y);
+                    t4.add(this.z);
+                    t4.norm(); //9
+                    x3.add(Q.z);
+                    x3.norm(); //10
+                    t4.mul(x3); //11
+                    x3.copy(t1);
+                    x3.add(t2); //x3.norm();//12
+
+                    t4.sub(x3);
+                    t4.norm(); //13
+                    x3.copy(this.x);
+                    x3.add(this.z);
+                    x3.norm(); //14
+                    y3.add(Q.z);
+                    y3.norm(); //15
+
+                    x3.mul(y3); //16
+                    y3.copy(t0);
+                    y3.add(t2); //y3.norm();//17
+
+                    y3.rsub(x3);
+                    y3.norm(); //18
+                    z3.copy(t2);
+
+                    if (ctx.ROM_CURVE.CURVE_B_I == 0) {
+                        z3.mul(b); //18
+                    } else {
+                        z3.imul(ctx.ROM_CURVE.CURVE_B_I);
+                    }
+
+                    x3.copy(y3);
+                    x3.sub(z3);
+                    x3.norm(); //20
+                    z3.copy(x3);
+                    z3.add(x3); //z3.norm(); //21
+
+                    x3.add(z3); //x3.norm(); //22
+                    z3.copy(t1);
+                    z3.sub(x3);
+                    z3.norm(); //23
+                    x3.add(t1);
+                    x3.norm(); //24
+
+                    if (ctx.ROM_CURVE.CURVE_B_I == 0) {
+                        y3.mul(b); //18
+                    } else {
+                        y3.imul(ctx.ROM_CURVE.CURVE_B_I);
+                    }
+
+                    t1.copy(t2);
+                    t1.add(t2); //t1.norm();//26
+                    t2.add(t1); //t2.norm();//27
+
+                    y3.sub(t2); //y3.norm(); //28
+
+                    y3.sub(t0);
+                    y3.norm(); //29
+                    t1.copy(y3);
+                    t1.add(y3); //t1.norm();//30
+                    y3.add(t1);
+                    y3.norm(); //31
+
+                    t1.copy(t0);
+                    t1.add(t0); //t1.norm(); //32
+                    t0.add(t1); //t0.norm();//33
+                    t0.sub(t2);
+                    t0.norm(); //34
+                    t1.copy(t4);
+                    t1.mul(y3); //35
+                    t2.copy(t0);
+                    t2.mul(y3); //36
+                    y3.copy(x3);
+                    y3.mul(z3); //37
+                    y3.add(t2); //y3.norm();//38
+                    x3.mul(t3); //39
+                    x3.sub(t1); //40
+                    z3.mul(t4); //41
+                    t1.copy(t3);
+                    t1.mul(t0); //42
+                    z3.add(t1); //z3.norm();
+                    //System.out.println("Out of add");
+                    this.x.copy(x3);
+                    this.x.norm();
+                    this.y.copy(y3);
+                    this.y.norm();
+                    this.z.copy(z3);
+                    this.z.norm();
+                }
+            }
+
+            if (ECP.CURVETYPE == ECP.EDWARDS) {
+                A = new ctx.FP(0);
+                A.copy(this.z); //FP A=new FP(z);
+                B = new ctx.FP(0); //FP B=new FP(0);
+                C = new ctx.FP(0);
+                C.copy(this.x); //FP C=new FP(x);
+                D = new ctx.FP(0);
+                D.copy(this.y); //FP D=new FP(y);
+                E = new ctx.FP(0); //FP E=new FP(0);
+                F = new ctx.FP(0); //FP F=new FP(0);
+                G = new ctx.FP(0); //FP G=new FP(0);
+
+                A.mul(Q.z); //A=2
+                B.copy(A);
+                B.sqr(); //B=2
+                C.mul(Q.x); //C=2
+                D.mul(Q.y); //D=2
+
+                E.copy(C);
+                E.mul(D); //E=2
+
+                if (ctx.ROM_CURVE.CURVE_B_I == 0) {
+                    b = new ctx.FP(0);
+                    b.rcopy(ctx.ROM_CURVE.CURVE_B);
+                    E.mul(b);
+                } else {
+                    E.imul(ctx.ROM_CURVE.CURVE_B_I); //E=22222
+                }
+
+                F.copy(B);
+                F.sub(E); //F=22224
+                G.copy(B);
+                G.add(E); //G=22224
+
+                if (ctx.ROM_CURVE.CURVE_A == 1) {
+                    E.copy(D);
+                    E.sub(C); //E=4
+                }
+                C.add(D); //C=4
+
+                B.copy(this.x);
+                B.add(this.y); //B=4
+                D.copy(Q.x);
+                D.add(Q.y);
+                B.norm();
+                D.norm(); //D=4
+                B.mul(D); //B=2
+                B.sub(C);
+                B.norm();
+                F.norm(); // B=6
+                B.mul(F); //B=2
+                this.x.copy(A);
+                this.x.mul(B);
+                G.norm(); // x=2
+
+                if (ctx.ROM_CURVE.CURVE_A == 1) {
+                    E.norm();
+                    C.copy(E);
+                    C.mul(G); //C=2
+                }
+
+                if (ctx.ROM_CURVE.CURVE_A == -1) {
+                    C.norm();
+                    C.mul(G);
+                }
+
+                this.y.copy(A);
+                this.y.mul(C); //y=2
+                this.z.copy(F);
+                this.z.mul(G);
+            }
+
+            return;
+        },
+
+        /* Differential Add for Montgomery curves. this+=Q where W is this-Q and is affine. */
+        dadd: function(Q, W) {
+            var A, B, C, D, DA, CB;
+
+            A = new ctx.FP(0);
+            A.copy(this.x);
+            B = new ctx.FP(0);
+            B.copy(this.x);
+            C = new ctx.FP(0);
+            C.copy(Q.x);
+            D = new ctx.FP(0);
+            D.copy(Q.x);
+            DA = new ctx.FP(0);
+            CB = new ctx.FP(0);
+
+            A.add(this.z);
+            B.sub(this.z);
+
+            C.add(Q.z);
+            D.sub(Q.z);
+
+            D.norm();
+            A.norm();
+            DA.copy(D);
+            DA.mul(A);
+            C.norm();
+            B.norm();
+            CB.copy(C);
+            CB.mul(B);
+
+            A.copy(DA);
+            A.add(CB);
+            A.norm();
+            A.sqr();
+            B.copy(DA);
+            B.sub(CB);
+            B.norm();
+            B.sqr();
+
+            this.x.copy(A);
+            this.z.copy(W.x);
+            this.z.mul(B);
+
+            //  this.x.norm();
+        },
+
+        /* this-=Q */
+        sub: function(Q) {
+			var NQ = new ECP(); NQ.copy(Q);
+            NQ.neg();
+            this.add(NQ);
+            //Q.neg();
+        },
+
+        /* constant time multiply by small integer of length bts - use ladder */
+        pinmul: function(e, bts) {
+            var i, b, P, R0, R1;
+
+            if (ECP.CURVETYPE == ECP.MONTGOMERY) {
+                return this.mul(new ctx.BIG(e));
+            } else {
+                P = new ECP();
+                R0 = new ECP();
+                R1 = new ECP();
+                R1.copy(this);
+
+                for (i = bts - 1; i >= 0; i--) {
+                    b = (e >> i) & 1;
+                    P.copy(R1);
+                    P.add(R0);
+                    R0.cswap(R1, b);
+                    R1.copy(P);
+                    R0.dbl();
+                    R0.cswap(R1, b);
+                }
+
+                P.copy(R0);
+                P.affine();
+
+                return P;
+            }
+        },
+
+        // multiply this by the curves cofactor
+        cfp: function() {
+            var cf=ctx.ROM_CURVE.CURVE_Cof_I,
+                c = new ctx.BIG(0);
+            if (cf==1) {
+                return;
+            }
+            if (cf==4) {
+                this.dbl(); this.dbl();
+                //this.affine();
+                return;
+            }
+            if (cf==8) {
+                this.dbl(); this.dbl(); this.dbl();
+                //this.affine();
+                return;
+            }
+            c.rcopy(ctx.ROM_CURVE.CURVE_Cof);
+            this.copy(this.mul(c));
+        },
+
+
+        /* return e.this - SPA immune, using Ladder */
+        mul: function(e) {
+            var P, D, R0, R1, mt, t, Q, C, W, w,
+                i, b, nb, s, ns;
+
+            if (e.iszilch() || this.is_infinity()) {
+                return new ECP();
+            }
+
+            P = new ECP();
+
+            if (ECP.CURVETYPE == ECP.MONTGOMERY) { /* use ladder */
+                D = new ECP();
+                R0 = new ECP();
+                R0.copy(this);
+                R1 = new ECP();
+                R1.copy(this);
+                R1.dbl();
+                D.copy(this);
+                D.affine();
+                nb = e.nbits();
+                for (i = nb - 2; i >= 0; i--) {
+                    b = e.bit(i);
+                    P.copy(R1);
+                    P.dadd(R0, D);
+
+                    R0.cswap(R1, b);
+                    R1.copy(P);
+                    R0.dbl();
+                    R0.cswap(R1, b);
+                }
+                P.copy(R0);
+            } else {
+                // fixed size windows
+                mt = new ctx.BIG();
+                t = new ctx.BIG();
+                Q = new ECP();
+                C = new ECP();
+                W = [];
+                w = [];
+
+                //this.affine();
+
+                // precompute table
+                Q.copy(this);
+                Q.dbl();
+                W[0] = new ECP();
+                W[0].copy(this);
+
+                for (i = 1; i < 8; i++) {
+                    W[i] = new ECP();
+                    W[i].copy(W[i - 1]);
+                    W[i].add(Q);
+                }
+
+                // make exponent odd - add 2P if even, P if odd
+                t.copy(e);
+                s = t.parity();
+                t.inc(1);
+                t.norm();
+                ns = t.parity();
+                mt.copy(t);
+                mt.inc(1);
+                mt.norm();
+                t.cmove(mt, s);
+                Q.cmove(this, ns);
+                C.copy(Q);
+
+                nb = 1 + Math.floor((t.nbits() + 3) / 4);
+
+                // convert exponent to signed 4-bit window
+                for (i = 0; i < nb; i++) {
+                    w[i] = (t.lastbits(5) - 16);
+                    t.dec(w[i]);
+                    t.norm();
+                    t.fshr(4);
+                }
+                w[nb] = t.lastbits(5);
+
+                P.copy(W[Math.floor((w[nb] - 1) / 2)]);
+                for (i = nb - 1; i >= 0; i--) {
+                    Q.select(W, w[i]);
+                    P.dbl();
+                    P.dbl();
+                    P.dbl();
+                    P.dbl();
+                    P.add(Q);
+                }
+                P.sub(C);
+            }
+
+            P.affine();
+
+            return P;
+        },
+
+        /* Return e.this+f.Q */
+
+        mul2: function(e, Q, f) {
+            var te = new ctx.BIG(),
+                tf = new ctx.BIG(),
+                mt = new ctx.BIG(),
+                S = new ECP(),
+                T = new ECP(),
+                C = new ECP(),
+                W = [],
+                w = [],
+                i, s, ns, nb,
+                a, b;
+
+            //this.affine();
+            //Q.affine();
+
+            te.copy(e);
+            tf.copy(f);
+
+            // precompute table
+            W[1] = new ECP();
+            W[1].copy(this);
+            W[1].sub(Q);
+            W[2] = new ECP();
+            W[2].copy(this);
+            W[2].add(Q);
+            S.copy(Q);
+            S.dbl();
+            W[0] = new ECP();
+            W[0].copy(W[1]);
+            W[0].sub(S);
+            W[3] = new ECP();
+            W[3].copy(W[2]);
+            W[3].add(S);
+            T.copy(this);
+            T.dbl();
+            W[5] = new ECP();
+            W[5].copy(W[1]);
+            W[5].add(T);
+            W[6] = new ECP();
+            W[6].copy(W[2]);
+            W[6].add(T);
+            W[4] = new ECP();
+            W[4].copy(W[5]);
+            W[4].sub(S);
+            W[7] = new ECP();
+            W[7].copy(W[6]);
+            W[7].add(S);
+
+            // if multiplier is odd, add 2, else add 1 to multiplier, and add 2P or P to correction
+
+            s = te.parity();
+            te.inc(1);
+            te.norm();
+            ns = te.parity();
+            mt.copy(te);
+            mt.inc(1);
+            mt.norm();
+            te.cmove(mt, s);
+            T.cmove(this, ns);
+            C.copy(T);
+
+            s = tf.parity();
+            tf.inc(1);
+            tf.norm();
+            ns = tf.parity();
+            mt.copy(tf);
+            mt.inc(1);
+            mt.norm();
+            tf.cmove(mt, s);
+            S.cmove(Q, ns);
+            C.add(S);
+
+            mt.copy(te);
+            mt.add(tf);
+            mt.norm();
+            nb = 1 + Math.floor((mt.nbits() + 1) / 2);
+
+            // convert exponent to signed 2-bit window
+            for (i = 0; i < nb; i++) {
+                a = (te.lastbits(3) - 4);
+                te.dec(a);
+                te.norm();
+                te.fshr(2);
+                b = (tf.lastbits(3) - 4);
+                tf.dec(b);
+                tf.norm();
+                tf.fshr(2);
+                w[i] = (4 * a + b);
+            }
+            w[nb] = (4 * te.lastbits(3) + tf.lastbits(3));
+            S.copy(W[Math.floor((w[nb] - 1) / 2)]);
+
+            for (i = nb - 1; i >= 0; i--) {
+                T.select(W, w[i]);
+                S.dbl();
+                S.dbl();
+                S.add(T);
+            }
+            S.sub(C); /* apply correction */
+            S.affine();
+
+            return S;
+        }
+    };
+
+    // set to group generator
+    ECP.generator = function() {
+        var G=new ECP(),
+            gx = new ctx.BIG(0),
+            gy = new ctx.BIG(0);
+
+        gx.rcopy(ctx.ROM_CURVE.CURVE_Gx);
+
+        if (ctx.ECP.CURVETYPE != ctx.ECP.MONTGOMERY) {
+            gy.rcopy(ctx.ROM_CURVE.CURVE_Gy);
+            G.setxy(gx, gy);
+        } else {
+            G.setx(gx);
+        }
+        return G;
+    };
+
+    /* return 1 if b==c, no branching */
+    ECP.teq = function(b, c) {
+        var x = b ^ c;
+        x -= 1; // if x=0, x now -1
+        return ((x >> 31) & 1);
+    };
+
+    /* convert from byte array to ECP */
+    ECP.fromBytes = function(b) {
+        var t = [],
+            P = new ECP(),
+            p = new ctx.BIG(0),
+            px, py, i;
+
+        p.rcopy(ctx.ROM_FIELD.Modulus);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = b[i + 1];
+        }
+
+        px = ctx.BIG.fromBytes(t);
+        if (ctx.BIG.comp(px, p) >= 0) {
+            return P;
+        }
+
+        if (ECP.CURVETYPE == ECP.MONTGOMERY) {
+            P.setx(px);
+            return P;
+        }
+
+        if (b[0] == 0x04) {
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                t[i] = b[i + ctx.BIG.MODBYTES + 1];
+            }
+
+            py = ctx.BIG.fromBytes(t);
+
+            if (ctx.BIG.comp(py, p) >= 0) {
+                return P;
+            }
+
+            P.setxy(px, py);
+
+            return P;
+        }
+
+        if (b[0]==0x02 || b[0]==0x03) {
+            P.setxi(px,b[0]&1);
+            return P;
+        }
+
+        return P;
+    };
+
+    /* Calculate RHS of curve equation */
+    ECP.RHS = function(x) {
+        var r = new ctx.FP(0),
+            b, cx, one, x3;
+
+        //x.norm();
+        r.copy(x);
+        r.sqr();
+
+        if (ECP.CURVETYPE == ECP.WEIERSTRASS) { // x^3+Ax+B
+            b = new ctx.FP(0);
+            b.rcopy(ctx.ROM_CURVE.CURVE_B);
+            r.mul(x);
+            if (ctx.ROM_CURVE.CURVE_A == -3) {
+                cx = new ctx.FP(0);
+                cx.copy(x);
+                cx.imul(3);
+                cx.neg();
+                cx.norm();
+                r.add(cx);
+            }
+            r.add(b);
+        } else if (ECP.CURVETYPE == ECP.EDWARDS) { // (Ax^2-1)/(Bx^2-1)
+            b = new ctx.FP(0);
+            b.rcopy(ctx.ROM_CURVE.CURVE_B);
+
+            one = new ctx.FP(1);
+            b.mul(r);
+            b.sub(one);
+            b.norm();
+            if (ctx.ROM_CURVE.CURVE_A == -1) {
+                r.neg();
+            }
+            r.sub(one);
+            r.norm();
+            b.inverse();
+
+            r.mul(b);
+        } else if (ECP.CURVETYPE == ECP.MONTGOMERY) { // x^3+Ax^2+x
+            x3 = new ctx.FP(0);
+            x3.copy(r);
+            x3.mul(x);
+            r.imul(ctx.ROM_CURVE.CURVE_A);
+            r.add(x3);
+            r.add(x);
+        }
+
+        r.reduce();
+
+        return r;
+    };
+
+    ECP.mapit = function(h) {
+        var q = new ctx.BIG(0),
+            x = ctx.BIG.fromBytes(h),
+            P = new ECP();
+
+        q.rcopy(ctx.ROM_FIELD.Modulus);
+        x.mod(q);
+
+        for (;;) {
+            for (;;) {
+                if (ECP.CURVETYPE != ECP.MONTGOMERY) {
+                    P.setxi(x,0);
+                } else {
+                    P.setx(x);
+                }
+                x.inc(1); x.norm();
+                if (!P.is_infinity()){
+                    break;
+                }
+
+            }
+            P.cfp();
+            if (!P.is_infinity()) {
+                break;
+            }
+        }
+        return P;
+    };
+
+    return ECP;
+};
diff --git a/version3/js/ecp2.js b/version3/js/ecp2.js
new file mode 100644
index 0000000..22d3979
--- /dev/null
+++ b/version3/js/ecp2.js
@@ -0,0 +1,921 @@
+/*
+    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.
+*/
+
+/* AMCL Weierstrass elliptic curve functions over ctx.FP2 */
+
+var ECP2 = function(ctx) {
+    "use strict";
+
+    /* Constructor, set this=O */
+    var ECP2 = function() {
+        this.x = new ctx.FP2(0);
+        this.y = new ctx.FP2(1);
+        this.z = new ctx.FP2(0);
+        // this.INF = true;
+    };
+
+    ECP2.prototype = {
+        /* Test this=O? */
+        is_infinity: function() {
+            // if (this.INF) {
+            //    return true;
+            // }
+
+            this.x.reduce();
+            this.y.reduce();
+            this.z.reduce();
+            return (this.x.iszilch() && this.z.iszilch());
+        },
+
+        /* copy this=P */
+        copy: function(P) {
+            this.x.copy(P.x);
+            this.y.copy(P.y);
+            this.z.copy(P.z);
+            // this.INF = P.INF;
+        },
+
+        /* set this=O */
+        inf: function() {
+            // this.INF = true;
+            this.x.zero();
+            this.y.one();
+            this.z.zero();
+        },
+
+        /* conditional move of Q to P dependant on d */
+        cmove: function(Q, d) {
+            this.x.cmove(Q.x, d);
+            this.y.cmove(Q.y, d);
+            this.z.cmove(Q.z, d);
+
+            // bd = (d !== 0) ? true : false;
+            // this.INF ^= (this.INF ^ Q.INF) & bd;
+        },
+
+        /* Constant time select from pre-computed table */
+        select: function(W, b) {
+            var MP = new ECP2(),
+                m, babs;
+
+            m = b >> 31,
+            babs = (b ^ m) - m;
+            babs = (babs - 1) / 2;
+
+            this.cmove(W[0], ECP2.teq(babs, 0)); // conditional move
+            this.cmove(W[1], ECP2.teq(babs, 1));
+            this.cmove(W[2], ECP2.teq(babs, 2));
+            this.cmove(W[3], ECP2.teq(babs, 3));
+            this.cmove(W[4], ECP2.teq(babs, 4));
+            this.cmove(W[5], ECP2.teq(babs, 5));
+            this.cmove(W[6], ECP2.teq(babs, 6));
+            this.cmove(W[7], ECP2.teq(babs, 7));
+
+            MP.copy(this);
+            MP.neg();
+            this.cmove(MP, (m & 1));
+        },
+
+        /* Test P == Q */
+        equals: function(Q) {
+            var a, b;
+
+            // if (this.is_infinity() && Q.is_infinity()) {
+            //    return true;
+            // }
+
+            // if (this.is_infinity() || Q.is_infinity()) {
+            //    return false;
+            // }
+
+            a = new ctx.FP2(0);
+            a.copy(this.x);
+            b = new ctx.FP2(0);
+            b.copy(Q.x);
+
+            a.copy(this.x);
+            a.mul(Q.z);
+            a.reduce();
+            b.copy(Q.x);
+            b.mul(this.z);
+            b.reduce();
+            if (!a.equals(b)) {
+                return false;
+            }
+
+            a.copy(this.y);
+            a.mul(Q.z);
+            a.reduce();
+            b.copy(Q.y);
+            b.mul(this.z);
+            b.reduce();
+            if (!a.equals(b)) {
+                return false;
+            }
+
+            return true;
+        },
+
+        /* set this=-this */
+        neg: function() {
+            // if (this.is_infinity()) return;
+            this.y.norm();
+            this.y.neg();
+            this.y.norm();
+            return;
+        },
+
+        /* convert this to affine, from (x,y,z) to (x,y) */
+        affine: function() {
+            var one;
+
+            if (this.is_infinity()) {
+                return;
+            }
+
+            one = new ctx.FP2(1);
+
+            if (this.z.equals(one)) {
+                this.x.reduce();
+                this.y.reduce();
+                return;
+            }
+
+            this.z.inverse();
+
+            this.x.mul(this.z);
+            this.x.reduce();
+            this.y.mul(this.z);
+            this.y.reduce();
+            this.z.copy(one);
+        },
+
+        /* extract affine x as ctx.FP2 */
+        getX: function() {
+			var W=new ECP2(); W.copy(this); W.affine();
+            //this.affine();
+            return W.x;
+        },
+
+        /* extract affine y as ctx.FP2 */
+        getY: function() {
+			var W=new ECP2(); W.copy(this); W.affine();
+            //this.affine();
+            return W.y;
+        },
+
+        /* extract projective x */
+        getx: function() {
+            return this.x;
+        },
+
+        /* extract projective y */
+        gety: function() {
+            return this.y;
+        },
+
+        /* extract projective z */
+        getz: function() {
+            return this.z;
+        },
+
+        /* convert this to byte array */
+        toBytes: function(b) {
+            var t = [],
+                i;
+			var W=new ECP2(); W.copy(this);
+            W.affine();
+            W.x.getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                b[i] = t[i];
+            }
+            W.x.getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                b[i + ctx.BIG.MODBYTES] = t[i];
+            }
+
+            W.y.getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                b[i + 2 * ctx.BIG.MODBYTES] = t[i];
+            }
+            W.y.getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                b[i + 3 * ctx.BIG.MODBYTES] = t[i];
+            }
+        },
+
+        /* convert this to hex string */
+        toString: function() {
+			var W=new ECP2(); W.copy(this);
+            if (W.is_infinity()) {
+                return "infinity";
+            }
+            W.affine();
+            return "(" + W.x.toString() + "," + W.y.toString() + ")";
+        },
+
+        /* set this=(x,y) */
+        setxy: function(ix, iy) {
+            var rhs, y2;
+
+            this.x.copy(ix);
+            this.y.copy(iy);
+            this.z.one();
+			this.x.norm();
+
+            rhs = ECP2.RHS(this.x);
+
+            y2 = new ctx.FP2(this.y); //y2.copy(this.y);
+            y2.sqr();
+
+            if (!y2.equals(rhs)) {
+                this.inf();
+            }
+            // if (y2.equals(rhs)) {
+            //    this.INF = false;
+            // } else {
+            //    this.inf();
+            // }
+        },
+
+        /* set this=(x,.) */
+        setx: function(ix) {
+            var rhs;
+
+            this.x.copy(ix);
+            this.z.one();
+			this.x.norm();
+
+            rhs = ECP2.RHS(this.x);
+
+            if (rhs.sqrt()) {
+                this.y.copy(rhs);
+                // this.INF = false;
+            } else {
+                this.inf();
+            }
+        },
+
+        /* set this*=q, where q is Modulus, using Frobenius */
+        frob: function(X) {
+            var X2;
+
+            // if (this.INF) {
+            //    return;
+            // }
+
+            X2 = new ctx.FP2(X); //X2.copy(X);
+            X2.sqr();
+            this.x.conj();
+            this.y.conj();
+            this.z.conj();
+            this.z.reduce();
+            this.x.mul(X2);
+            this.y.mul(X2);
+            this.y.mul(X);
+        },
+
+        /* this+=this */
+        dbl: function() {
+            var iy, t0, t1, t2, x3, y3;
+
+            // if (this.INF) {
+            //    return -1;
+            // }
+
+            iy = new ctx.FP2(0);
+            iy.copy(this.y); //FP2 iy=new FP2(y);
+            if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) {
+                iy.mul_ip();
+                iy.norm();
+            }
+
+            t0 = new ctx.FP2(0);
+            t0.copy(this.y); //FP2 t0=new FP2(y);                  //***** Change
+            t0.sqr();
+            if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) {
+                t0.mul_ip();
+            }
+            t1 = new ctx.FP2(0);
+            t1.copy(iy); //FP2 t1=new FP2(iy);
+            t1.mul(this.z);
+            t2 = new ctx.FP2(0);
+            t2.copy(this.z); //FP2 t2=new FP2(z);
+            t2.sqr();
+
+            this.z.copy(t0);
+            this.z.add(t0);
+            this.z.norm();
+            this.z.add(this.z);
+            this.z.add(this.z);
+            this.z.norm();
+
+            t2.imul(3 * ctx.ROM_CURVE.CURVE_B_I);
+            if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) {
+                t2.mul_ip();
+                t2.norm();
+            }
+
+            x3 = new ctx.FP2(0);
+            x3.copy(t2); //FP2 x3=new FP2(t2);
+            x3.mul(this.z);
+
+            y3 = new ctx.FP2(0);
+            y3.copy(t0); //FP2 y3=new FP2(t0);
+
+            y3.add(t2);
+            y3.norm();
+            this.z.mul(t1);
+            t1.copy(t2);
+            t1.add(t2);
+            t2.add(t1);
+            t2.norm();
+            t0.sub(t2);
+            t0.norm(); //y^2-9bz^2
+            y3.mul(t0);
+            y3.add(x3); //(y^2+3z*2)(y^2-9z^2)+3b.z^2.8y^2
+            t1.copy(this.x);
+            t1.mul(iy); //
+            this.x.copy(t0);
+            this.x.norm();
+            this.x.mul(t1);
+            this.x.add(this.x); //(y^2-9bz^2)xy2
+
+            this.x.norm();
+            this.y.copy(y3);
+            this.y.norm();
+
+            return 1;
+        },
+
+        /* this+=Q - return 0 for add, 1 for double, -1 for O */
+        /* this+=Q */
+        add: function(Q) {
+            var b, t0, t1, t2, t3, t4, x3, y3, z3;
+
+            // if (this.INF) {
+            //     this.copy(Q);
+            //     return -1;
+            // }
+
+            // if (Q.INF) {
+            //     return -1;
+            // }
+
+            b = 3 * ctx.ROM_CURVE.CURVE_B_I;
+            t0 = new ctx.FP2(0);
+            t0.copy(this.x); //FP2 t0=new FP2(x);
+            t0.mul(Q.x); // x.Q.x
+            t1 = new ctx.FP2(0);
+            t1.copy(this.y); //FP2 t1=new FP2(y);
+            t1.mul(Q.y); // y.Q.y
+
+            t2 = new ctx.FP2(0);
+            t2.copy(this.z); //FP2 t2=new FP2(z);
+            t2.mul(Q.z);
+            t3 = new ctx.FP2(0);
+            t3.copy(this.x); //FP2 t3=new FP2(x);
+            t3.add(this.y);
+            t3.norm(); //t3=X1+Y1
+            t4 = new ctx.FP2(0);
+            t4.copy(Q.x); //FP2 t4=new FP2(Q.x);
+            t4.add(Q.y);
+            t4.norm(); //t4=X2+Y2
+            t3.mul(t4); //t3=(X1+Y1)(X2+Y2)
+            t4.copy(t0);
+            t4.add(t1); //t4=X1.X2+Y1.Y2
+
+            t3.sub(t4);
+            t3.norm();
+            if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) {
+                t3.mul_ip();
+                t3.norm(); //t3=(X1+Y1)(X2+Y2)-(X1.X2+Y1.Y2) = X1.Y2+X2.Y1
+            }
+
+            t4.copy(this.y);
+            t4.add(this.z);
+            t4.norm(); //t4=Y1+Z1
+            x3 = new ctx.FP2(0);
+            x3.copy(Q.y); //FP2 x3=new FP2(Q.y);
+            x3.add(Q.z);
+            x3.norm(); //x3=Y2+Z2
+
+            t4.mul(x3); //t4=(Y1+Z1)(Y2+Z2)
+            x3.copy(t1); //
+            x3.add(t2); //X3=Y1.Y2+Z1.Z2
+
+            t4.sub(x3);
+            t4.norm();
+            if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) {
+                t4.mul_ip();
+                t4.norm(); //t4=(Y1+Z1)(Y2+Z2) - (Y1.Y2+Z1.Z2) = Y1.Z2+Y2.Z1
+            }
+
+            x3.copy(this.x);
+            x3.add(this.z);
+            x3.norm(); // x3=X1+Z1
+            y3 = new ctx.FP2(0);
+            y3.copy(Q.x); //FP2 y3=new FP2(Q.x);
+            y3.add(Q.z);
+            y3.norm(); // y3=X2+Z2
+            x3.mul(y3); // x3=(X1+Z1)(X2+Z2)
+            y3.copy(t0);
+            y3.add(t2); // y3=X1.X2+Z1+Z2
+            y3.rsub(x3);
+            y3.norm(); // y3=(X1+Z1)(X2+Z2) - (X1.X2+Z1.Z2) = X1.Z2+X2.Z1
+
+            if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) {
+                t0.mul_ip();
+                t0.norm(); // x.Q.x
+                t1.mul_ip();
+                t1.norm(); // y.Q.y
+            }
+
+            x3.copy(t0);
+            x3.add(t0);
+            t0.add(x3);
+            t0.norm();
+            t2.imul(b);
+            if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) {
+                t2.mul_ip(); t2.norm();
+            }
+
+            z3 = new ctx.FP2(0);
+            z3.copy(t1); //FP2 z3=new FP2(t1);
+            z3.add(t2);
+            z3.norm();
+            t1.sub(t2);
+            t1.norm();
+            y3.imul(b);
+            if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) {
+                y3.mul_ip();
+                y3.norm();
+            }
+
+            x3.copy(y3);
+            x3.mul(t4);
+            t2.copy(t3);
+            t2.mul(t1);
+            x3.rsub(t2);
+            y3.mul(t0);
+            t1.mul(z3);
+            y3.add(t1);
+            t0.mul(t3);
+            z3.mul(t4);
+            z3.add(t0);
+
+            this.x.copy(x3);
+            this.x.norm();
+            this.y.copy(y3);
+            this.y.norm();
+            this.z.copy(z3);
+            this.z.norm();
+
+            return 0;
+        },
+
+        /* this-=Q */
+        sub: function(Q) {
+            var D;
+			var NQ=new ECP2(); NQ.copy(Q);
+            NQ.neg();
+            D = this.add(NQ);
+            //Q.neg();
+
+            return D;
+        },
+
+        /* P*=e */
+        mul: function(e) {
+            /* fixed size windows */
+            var mt = new ctx.BIG(),
+                t = new ctx.BIG(),
+                C = new ECP2(),
+                P = new ECP2(),
+                Q = new ECP2(),
+                W = [],
+                w = [],
+                i, nb, s, ns;
+
+            if (this.is_infinity()) {
+                return new ECP2();
+            }
+
+            //this.affine();
+
+            // precompute table
+            Q.copy(this);
+            Q.dbl();
+            W[0] = new ECP2();
+            W[0].copy(this);
+
+            for (i = 1; i < 8; i++) {
+                W[i] = new ECP2();
+                W[i].copy(W[i - 1]);
+                W[i].add(Q);
+            }
+
+            // make exponent odd - add 2P if even, P if odd
+            t.copy(e);
+            s = t.parity();
+            t.inc(1);
+            t.norm();
+            ns = t.parity();
+            mt.copy(t);
+            mt.inc(1);
+            mt.norm();
+            t.cmove(mt, s);
+            Q.cmove(this, ns);
+            C.copy(Q);
+
+            nb = 1 + Math.floor((t.nbits() + 3) / 4);
+
+            // convert exponent to signed 4-bit window
+            for (i = 0; i < nb; i++) {
+                w[i] = (t.lastbits(5) - 16);
+                t.dec(w[i]);
+                t.norm();
+                t.fshr(4);
+            }
+            w[nb] = t.lastbits(5);
+
+            P.copy(W[Math.floor((w[nb] - 1) / 2)]);
+            for (i = nb - 1; i >= 0; i--) {
+                Q.select(W, w[i]);
+                P.dbl();
+                P.dbl();
+                P.dbl();
+                P.dbl();
+                P.add(Q);
+            }
+            P.sub(C);
+            P.affine();
+
+            return P;
+        }
+    };
+
+    // set to group generator
+    ECP2.generator = function() {
+        var G=new ECP2(),
+            A = new ctx.BIG(0),
+            B = new ctx.BIG(0),
+            QX, QY;
+
+        A.rcopy(ctx.ROM_CURVE.CURVE_Pxa);
+        B.rcopy(ctx.ROM_CURVE.CURVE_Pxb);
+        QX = new ctx.FP2(0);
+        QX.bset(A, B);
+        A.rcopy(ctx.ROM_CURVE.CURVE_Pya);
+        B.rcopy(ctx.ROM_CURVE.CURVE_Pyb);
+        QY = new ctx.FP2(0);
+        QY.bset(A, B);
+        G.setxy(QX, QY);
+        return G;
+    };
+
+    /* convert from byte array to point */
+    ECP2.fromBytes = function(b) {
+        var t = [],
+            ra, rb, i, rx, ry, P;
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = b[i];
+        }
+        ra = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = b[i + ctx.BIG.MODBYTES];
+        }
+        rb = ctx.BIG.fromBytes(t);
+
+        rx = new ctx.FP2(ra, rb); //rx.bset(ra,rb);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = b[i + 2 * ctx.BIG.MODBYTES];
+        }
+        ra = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = b[i + 3 * ctx.BIG.MODBYTES];
+        }
+        rb = ctx.BIG.fromBytes(t);
+
+        ry = new ctx.FP2(ra, rb); //ry.bset(ra,rb);
+
+        P = new ECP2();
+        P.setxy(rx, ry);
+
+        return P;
+    };
+
+    /* Calculate RHS of curve equation x^3+B */
+    ECP2.RHS = function(x) {
+        var r, c, b;
+
+        //x.norm();
+        r = new ctx.FP2(x); //r.copy(x);
+        r.sqr();
+
+        c = new ctx.BIG(0);
+        c.rcopy(ctx.ROM_CURVE.CURVE_B);
+        b = new ctx.FP2(c); //b.bseta(c);
+
+        if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) {
+            b.div_ip();
+        }
+        if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) {
+            b.norm();
+            b.mul_ip();
+            b.norm();
+        }
+
+        r.mul(x);
+        r.add(b);
+
+        r.reduce();
+
+        return r;
+    };
+
+    /* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3 */
+    // Bos & Costello https://eprint.iacr.org/2013/458.pdf
+    // Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
+    // Side channel attack secure
+    ECP2.mul4 = function(Q, u) {
+        var W = new ECP2(),
+            P = new ECP2(),
+            T = [],
+            mt = new ctx.BIG(),
+            t = [],
+            w = [],
+            s = [],
+            i, j, k, nb, bt, pb;
+
+        for (i = 0; i < 4; i++) {
+            t[i] = new ctx.BIG(u[i]); t[i].norm();
+            //Q[i].affine();
+        }
+
+        T[0] = new ECP2(); T[0].copy(Q[0]); // Q[0]
+        T[1] = new ECP2(); T[1].copy(T[0]); T[1].add(Q[1]); // Q[0]+Q[1]
+        T[2] = new ECP2(); T[2].copy(T[0]); T[2].add(Q[2]); // Q[0]+Q[2]
+        T[3] = new ECP2(); T[3].copy(T[1]); T[3].add(Q[2]); // Q[0]+Q[1]+Q[2]
+        T[4] = new ECP2(); T[4].copy(T[0]); T[4].add(Q[3]); // Q[0]+Q[3]
+        T[5] = new ECP2(); T[5].copy(T[1]); T[5].add(Q[3]); // Q[0]+Q[1]+Q[3]
+        T[6] = new ECP2(); T[6].copy(T[2]); T[6].add(Q[3]); // Q[0]+Q[2]+Q[3]
+        T[7] = new ECP2(); T[7].copy(T[3]); T[7].add(Q[3]); // Q[0]+Q[1]+Q[2]+Q[3]
+
+        // Make it odd
+        pb=1-t[0].parity();
+        t[0].inc(pb);
+        t[0].norm();
+
+        // Number of bits
+        mt.zero();
+        for (i=0;i<4;i++) {
+            mt.or(t[i]);
+        }
+
+        nb=1+mt.nbits();
+
+        // Sign pivot
+        s[nb-1]=1;
+        for (i=0;i<nb-1;i++) {
+            t[0].fshr(1);
+            s[i]=2*t[0].parity()-1;
+        }
+
+        // Recoded exponent
+        for (i=0; i<nb; i++) {
+            w[i]=0;
+            k=1;
+            for (j=1; j<4; j++) {
+                bt=s[i]*t[j].parity();
+                t[j].fshr(1);
+                t[j].dec(bt>>1);
+                t[j].norm();
+                w[i]+=bt*k;
+                k*=2;
+            }
+        }
+
+        // Main loop
+        P.select(T,2*w[nb-1]+1);
+        for (i=nb-2;i>=0;i--) {
+            P.dbl();
+            W.select(T,2*w[i]+s[i]);
+            P.add(W);
+        }
+
+        // apply correction
+        W.copy(P);
+        W.sub(Q[0]);
+        P.cmove(W,pb);
+        P.affine();
+        return P;
+    };
+
+    /* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3 */
+    /*
+    ECP2.mul4 = function(Q, u) {
+        var a = [],
+            T = new ECP2(),
+            C = new ECP2(),
+            P = new ECP2(),
+            W = [],
+            mt = new ctx.BIG(),
+            t = [],
+            w = [],
+            i, j, nb;
+
+        for (i = 0; i < 4; i++) {
+            t[i] = new ctx.BIG(u[i]);
+            Q[i].affine();
+        }
+
+        // precompute table
+
+        W[0] = new ECP2();
+        W[0].copy(Q[0]);
+        W[0].sub(Q[1]);
+        W[1] = new ECP2();
+        W[1].copy(W[0]);
+        W[2] = new ECP2();
+        W[2].copy(W[0]);
+        W[3] = new ECP2();
+        W[3].copy(W[0]);
+        W[4] = new ECP2();
+        W[4].copy(Q[0]);
+        W[4].add(Q[1]);
+        W[5] = new ECP2();
+        W[5].copy(W[4]);
+        W[6] = new ECP2();
+        W[6].copy(W[4]);
+        W[7] = new ECP2();
+        W[7].copy(W[4]);
+        T.copy(Q[2]);
+        T.sub(Q[3]);
+        W[1].sub(T);
+        W[2].add(T);
+        W[5].sub(T);
+        W[6].add(T);
+        T.copy(Q[2]);
+        T.add(Q[3]);
+        W[0].sub(T);
+        W[3].add(T);
+        W[4].sub(T);
+        W[7].add(T);
+
+        // if multiplier is even add 1 to multiplier, and add P to correction
+        mt.zero();
+        C.inf();
+
+        for (i = 0; i < 4; i++) {
+            if (t[i].parity() == 0) {
+                t[i].inc(1);
+                t[i].norm();
+                C.add(Q[i]);
+            }
+            mt.add(t[i]);
+            mt.norm();
+        }
+
+        nb = 1 + mt.nbits();
+
+        // convert exponent to signed 1-bit window
+        for (j = 0; j < nb; j++) {
+            for (i = 0; i < 4; i++) {
+                a[i] = (t[i].lastbits(2) - 2);
+                t[i].dec(a[i]);
+                t[i].norm();
+                t[i].fshr(1);
+            }
+            w[j] = (8 * a[0] + 4 * a[1] + 2 * a[2] + a[3]);
+        }
+        w[nb] = (8 * t[0].lastbits(2) + 4 * t[1].lastbits(2) + 2 * t[2].lastbits(2) + t[3].lastbits(2));
+
+        P.copy(W[Math.floor((w[nb] - 1) / 2)]);
+
+        for (i = nb - 1; i >= 0; i--) {
+            T.select(W, w[i]);
+            P.dbl();
+            P.add(T);
+        }
+        P.sub(C); // apply correction
+
+        P.affine();
+
+        return P;
+    };
+    */
+    /* return 1 if b==c, no branching */
+    ECP2.teq = function(b, c) {
+        var x = b ^ c;
+        x -= 1; // if x=0, x now -1
+        return ((x >> 31) & 1);
+    };
+
+    /* needed for SOK */
+    ECP2.mapit = function(h) {
+        var fa = new ctx.BIG(0),
+            fb = new ctx.BIG(0),
+            q, x, one, Q, T, K, X, xQ, x2Q;
+
+        q = new ctx.BIG(0);
+        q.rcopy(ctx.ROM_FIELD.Modulus);
+        x = ctx.BIG.fromBytes(h);
+        one = new ctx.BIG(1);
+        x.mod(q);
+
+        for (;;) {
+            X = new ctx.FP2(one, x);
+            Q = new ECP2();
+            Q.setx(X);
+            if (!Q.is_infinity()) {
+                break;
+            }
+            x.inc(1);
+            x.norm();
+        }
+        /* Fast Hashing to G2 - Fuentes-Castaneda, Knapp and Rodriguez-Henriquez */
+        fa.rcopy(ctx.ROM_FIELD.Fra);
+        fb.rcopy(ctx.ROM_FIELD.Frb);
+        X = new ctx.FP2(fa, fb);
+        if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) {
+            X.inverse();
+            X.norm();
+        }
+
+        x = new ctx.BIG(0);
+        x.rcopy(ctx.ROM_CURVE.CURVE_Bnx);
+
+        if (ctx.ECP.CURVE_PAIRING_TYPE == ctx.ECP.BN) {
+            T = new ECP2();
+            T.copy(Q);
+            T = T.mul(x);
+            if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) {
+                T.neg();
+            }
+            K = new ECP2();
+            K.copy(T);
+            K.dbl();
+            K.add(T); //K.affine();
+
+            K.frob(X);
+            Q.frob(X);
+            Q.frob(X);
+            Q.frob(X);
+            Q.add(T);
+            Q.add(K);
+            T.frob(X);
+            T.frob(X);
+            Q.add(T);
+        }
+
+        if (ctx.ECP.CURVE_PAIRING_TYPE == ctx.ECP.BLS) {
+            // xQ = new ECP2();
+            // x2Q = new ECP2();
+
+            xQ = Q.mul(x);
+            x2Q = xQ.mul(x);
+
+            if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) {
+                xQ.neg();
+            }
+
+            x2Q.sub(xQ);
+            x2Q.sub(Q);
+
+            xQ.sub(Q);
+            xQ.frob(X);
+
+            Q.dbl();
+            Q.frob(X);
+            Q.frob(X);
+
+            Q.add(x2Q);
+            Q.add(xQ);
+        }
+
+        Q.affine();
+
+        return Q;
+    };
+
+    return ECP2;
+};
diff --git a/version3/js/ecp4.js b/version3/js/ecp4.js
new file mode 100644
index 0000000..422c800
--- /dev/null
+++ b/version3/js/ecp4.js
@@ -0,0 +1,885 @@
+/*
+    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.
+*/
+
+/* AMCL Weierstrass elliptic curve functions over ctx.FP4 */
+
+var ECP4 = function(ctx) {
+    "use strict";
+
+    /* Constructor, set this=O */
+    var ECP4 = function() {
+        this.x = new ctx.FP4(0);
+        this.y = new ctx.FP4(1);
+        this.z = new ctx.FP4(0);
+        // this.INF = true;
+    };
+
+    ECP4.prototype = {
+        /* Test this=O? */
+        is_infinity: function() {
+            // if (this.INF) {
+            //     return true;
+            // }
+
+            this.x.reduce();
+            this.y.reduce();
+            this.z.reduce();
+            return (this.x.iszilch() && this.z.iszilch());
+        },
+
+        /* copy this=P */
+        copy: function(P) {
+            this.x.copy(P.x);
+            this.y.copy(P.y);
+            this.z.copy(P.z);
+            // this.INF = P.INF;
+        },
+
+        /* set this=O */
+        inf: function() {
+            // this.INF = true;
+            this.x.zero();
+            this.y.one();
+            this.z.zero();
+        },
+
+        /* conditional move of Q to P dependant on d */
+        cmove: function(Q, d) {
+            this.x.cmove(Q.x, d);
+            this.y.cmove(Q.y, d);
+            this.z.cmove(Q.z, d);
+
+            // bd = (d !== 0) ? true : false;
+            // this.INF ^= (this.INF ^ Q.INF) & bd;
+        },
+
+        /* Constant time select from pre-computed table */
+        select: function(W, b) {
+            var MP = new ECP4(),
+                m = b >> 31,
+                babs = (b ^ m) - m;
+
+            babs = (babs - 1) / 2;
+
+            this.cmove(W[0], ECP4.teq(babs, 0)); // conditional move
+            this.cmove(W[1], ECP4.teq(babs, 1));
+            this.cmove(W[2], ECP4.teq(babs, 2));
+            this.cmove(W[3], ECP4.teq(babs, 3));
+            this.cmove(W[4], ECP4.teq(babs, 4));
+            this.cmove(W[5], ECP4.teq(babs, 5));
+            this.cmove(W[6], ECP4.teq(babs, 6));
+            this.cmove(W[7], ECP4.teq(babs, 7));
+
+            MP.copy(this);
+            MP.neg();
+            this.cmove(MP, (m & 1));
+        },
+
+        /* Test P == Q */
+        equals: function(Q) {
+            var a, b;
+
+            // if (this.is_infinity() && Q.is_infinity()) {
+            //    return true;
+            // }
+
+            // if (this.is_infinity() || Q.is_infinity()) {
+            //    return false;
+            // }
+
+            a = new ctx.FP4(this.x);
+            b = new ctx.FP4(Q.x);
+
+            a.mul(Q.z);
+            b.mul(this.z);
+            if (!a.equals(b)) {
+                return false;
+            }
+
+            a.copy(this.y);
+            a.mul(Q.z);
+            b.copy(Q.y);
+            b.mul(this.z);
+            if (!a.equals(b)) {
+                return false;
+            }
+
+            return true;
+        },
+
+        /* set this=-this */
+        neg: function() {
+            this.y.norm();
+            this.y.neg();
+            this.y.norm();
+            return;
+        },
+
+        /* convert this to affine, from (x,y,z) to (x,y) */
+        affine: function() {
+            var one;
+
+            if (this.is_infinity()) {
+                return;
+            }
+
+            one = new ctx.FP4(1);
+
+            if (this.z.equals(one)) {
+                this.x.reduce();
+                this.y.reduce();
+                return;
+            }
+
+            this.z.inverse();
+
+            this.x.mul(this.z);
+            this.x.reduce();
+            this.y.mul(this.z);
+            this.y.reduce();
+            this.z.copy(one);
+        },
+
+        /* extract affine x as ctx.FP4 */
+        getX: function() {
+			var W=new ECP4(); W.copy(this); W.affine();
+            //this.affine();
+            return W.x;
+        },
+
+        /* extract affine y as ctx.FP4 */
+        getY: function() {
+			var W=new ECP4(); W.copy(this); W.affine();
+            //this.affine();
+            return W.y;
+        },
+
+        /* extract projective x */
+        getx: function() {
+            return this.x;
+        },
+
+        /* extract projective y */
+        gety: function() {
+            return this.y;
+        },
+
+        /* extract projective z */
+        getz: function() {
+            return this.z;
+        },
+
+        /* convert this to byte array */
+        toBytes: function(b) {
+            var t = [],
+                i;
+			var W=new ECP4(); W.copy(this);
+            W.affine();
+            W.x.geta().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                b[i] = t[i];
+            }
+            W.x.geta().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                b[i + ctx.BIG.MODBYTES] = t[i];
+            }
+            W.x.getb().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                b[i + 2*ctx.BIG.MODBYTES] = t[i];
+            }
+            W.x.getb().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                b[i + 3*ctx.BIG.MODBYTES] = t[i];
+            }
+
+
+            W.y.geta().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                b[i + 4 * ctx.BIG.MODBYTES] = t[i];
+            }
+            W.y.geta().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                b[i + 5 * ctx.BIG.MODBYTES] = t[i];
+            }
+            W.y.getb().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                b[i + 6 * ctx.BIG.MODBYTES] = t[i];
+            }
+            W.y.getb().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                b[i + 7 * ctx.BIG.MODBYTES] = t[i];
+            }
+        },
+
+        /* convert this to hex string */
+        toString: function() {
+			var W=new ECP4(); W.copy(this);
+            if (W.is_infinity()) {
+                return "infinity";
+            }
+            W.affine();
+            return "(" + W.x.toString() + "," + W.y.toString() + ")";
+        },
+
+        /* set this=(x,y) */
+        setxy: function(ix, iy) {
+            var rhs, y2;
+
+            this.x.copy(ix);
+            this.y.copy(iy);
+            this.z.one();
+			this.x.norm();
+
+            rhs = ECP4.RHS(this.x);
+
+            y2 = new ctx.FP4(this.y); //y2.copy(this.y);
+            y2.sqr();
+
+            if (!y2.equals(rhs)) {
+                this.inf();
+            }
+
+            // if (y2.equals(rhs)) {
+            //     this.INF = false;
+            // } else {
+            //     this.inf();
+            // }
+        },
+
+        /* set this=(x,.) */
+        setx: function(ix) {
+            var rhs;
+
+            this.x.copy(ix);
+            this.z.one();
+			this.x.norm();
+            rhs = ECP4.RHS(this.x);
+
+            if (rhs.sqrt()) {
+                this.y.copy(rhs);
+                // this.INF = false;
+            } else {
+                this.inf();
+            }
+        },
+
+        /* set this*=q, where q is Modulus, using Frobenius */
+        frob: function(F,n) {
+            // if (this.INF) {
+            //    return;
+            // }
+            for (var i=0;i<n;i++) {
+                this.x.frob(F[2]);
+                this.x.pmul(F[0]);
+
+                this.y.frob(F[2]);
+                this.y.pmul(F[1]);
+                this.y.times_i();
+
+                this.z.frob(F[2]);
+            }
+        },
+
+        /* this+=this */
+        dbl: function() {
+            var iy, t0, t1, t2, x3, y3;
+
+            // if (this.INF) {
+            //    return -1;
+            // }
+
+            iy = new ctx.FP4(this.y);
+            if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) {
+                iy.times_i();
+                iy.norm();
+            }
+
+            t0 = new ctx.FP4(this.y);
+            t0.sqr();
+            if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) {
+                t0.times_i();
+            }
+            t1 = new ctx.FP4(iy);
+            t1.mul(this.z);
+            t2 = new ctx.FP4(this.z);
+            t2.sqr();
+
+            this.z.copy(t0);
+            this.z.add(t0);
+            this.z.norm();
+            this.z.add(this.z);
+            this.z.add(this.z);
+            this.z.norm();
+
+            t2.imul(3 * ctx.ROM_CURVE.CURVE_B_I);
+            if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) {
+                t2.times_i();
+            }
+
+            x3 = new ctx.FP4(t2);
+            x3.mul(this.z);
+
+            y3 = new ctx.FP4(t0);
+
+            y3.add(t2);
+            y3.norm();
+            this.z.mul(t1);
+            t1.copy(t2);
+            t1.add(t2);
+            t2.add(t1);
+            t2.norm();
+            t0.sub(t2);
+            t0.norm(); //y^2-9bz^2
+            y3.mul(t0);
+            y3.add(x3); //(y^2+3z*2)(y^2-9z^2)+3b.z^2.8y^2
+            t1.copy(this.x);
+            t1.mul(iy); //
+            this.x.copy(t0);
+            this.x.norm();
+            this.x.mul(t1);
+            this.x.add(this.x); //(y^2-9bz^2)xy2
+
+            this.x.norm();
+            this.y.copy(y3);
+            this.y.norm();
+
+            return 1;
+        },
+
+        /* this+=Q */
+        add: function(Q) {
+            var b, t0, t1, t2, t3, t4, x3, y3, z3;
+
+            // if (this.INF) {
+            //    this.copy(Q);
+            //    return -1;
+            // }
+
+            // if (Q.INF) {
+            //    return -1;
+            // }
+
+            b = 3 * ctx.ROM_CURVE.CURVE_B_I;
+            t0 = new ctx.FP4(this.x);
+            t0.mul(Q.x); // x.Q.x
+            t1 = new ctx.FP4(this.y);
+            t1.mul(Q.y); // y.Q.y
+
+            t2 = new ctx.FP4(this.z);
+            t2.mul(Q.z);
+            t3 = new ctx.FP4(this.x);
+            t3.add(this.y);
+            t3.norm(); //t3=X1+Y1
+            t4 = new ctx.FP4(Q.x);
+            t4.add(Q.y);
+            t4.norm(); //t4=X2+Y2
+            t3.mul(t4); //t3=(X1+Y1)(X2+Y2)
+            t4.copy(t0);
+            t4.add(t1); //t4=X1.X2+Y1.Y2
+
+            t3.sub(t4);
+            t3.norm();
+            if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) {
+                t3.times_i();  //t3=(X1+Y1)(X2+Y2)-(X1.X2+Y1.Y2) = X1.Y2+X2.Y1
+            }
+
+            t4.copy(this.y);
+            t4.add(this.z);
+            t4.norm(); //t4=Y1+Z1
+            x3 = new ctx.FP4(Q.y);
+            x3.add(Q.z);
+            x3.norm(); //x3=Y2+Z2
+
+            t4.mul(x3); //t4=(Y1+Z1)(Y2+Z2)
+            x3.copy(t1); //
+            x3.add(t2); //X3=Y1.Y2+Z1.Z2
+
+            t4.sub(x3);
+            t4.norm();
+            if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) {
+                t4.times_i();  //t4=(Y1+Z1)(Y2+Z2) - (Y1.Y2+Z1.Z2) = Y1.Z2+Y2.Z1
+            }
+
+            x3.copy(this.x);
+            x3.add(this.z);
+            x3.norm(); // x3=X1+Z1
+            y3 = new ctx.FP4(Q.x);
+            y3.add(Q.z);
+            y3.norm(); // y3=X2+Z2
+            x3.mul(y3); // x3=(X1+Z1)(X2+Z2)
+            y3.copy(t0);
+            y3.add(t2); // y3=X1.X2+Z1+Z2
+            y3.rsub(x3);
+            y3.norm(); // y3=(X1+Z1)(X2+Z2) - (X1.X2+Z1.Z2) = X1.Z2+X2.Z1
+
+            if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) {
+                t0.times_i();
+                t1.times_i();
+            }
+
+            x3.copy(t0);
+            x3.add(t0);
+            t0.add(x3);
+            t0.norm();
+            t2.imul(b);
+            if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) {
+                t2.times_i();
+            }
+
+            z3 = new ctx.FP4(t1);
+            z3.add(t2);
+            z3.norm();
+            t1.sub(t2);
+            t1.norm();
+            y3.imul(b);
+            if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) {
+                y3.times_i();
+            }
+
+            x3.copy(y3);
+            x3.mul(t4);
+            t2.copy(t3);
+            t2.mul(t1);
+            x3.rsub(t2);
+            y3.mul(t0);
+            t1.mul(z3);
+            y3.add(t1);
+            t0.mul(t3);
+            z3.mul(t4);
+            z3.add(t0);
+
+            this.x.copy(x3);
+            this.x.norm();
+            this.y.copy(y3);
+            this.y.norm();
+            this.z.copy(z3);
+            this.z.norm();
+
+            return 0;
+        },
+
+        /* this-=Q */
+        sub: function(Q) {
+            var D;
+
+			var NQ=new ECP4(); NQ.copy(Q);
+            NQ.neg();
+            D = this.add(NQ);
+            //Q.neg();
+
+            return D;
+        },
+
+        /* P*=e */
+        mul: function(e) {
+            /* fixed size windows */
+            var mt = new ctx.BIG(),
+                t = new ctx.BIG(),
+                C = new ECP4(),
+                P = new ECP4(),
+                Q = new ECP4(),
+                W = [],
+                w = [],
+                i, nb, s, ns;
+
+            if (this.is_infinity()) {
+                return new ECP4();
+            }
+
+            //this.affine();
+
+            // precompute table
+            Q.copy(this);
+            Q.dbl();
+            W[0] = new ECP4();
+            W[0].copy(this);
+
+            for (i = 1; i < 8; i++) {
+                W[i] = new ECP4();
+                W[i].copy(W[i - 1]);
+                W[i].add(Q);
+            }
+
+            // make exponent odd - add 2P if even, P if odd
+            t.copy(e);
+            s = t.parity();
+            t.inc(1);
+            t.norm();
+            ns = t.parity();
+            mt.copy(t);
+            mt.inc(1);
+            mt.norm();
+            t.cmove(mt, s);
+            Q.cmove(this, ns);
+            C.copy(Q);
+
+            nb = 1 + Math.floor((t.nbits() + 3) / 4);
+
+            // convert exponent to signed 4-bit window
+            for (i = 0; i < nb; i++) {
+                w[i] = (t.lastbits(5) - 16);
+                t.dec(w[i]);
+                t.norm();
+                t.fshr(4);
+            }
+            w[nb] = t.lastbits(5);
+
+            P.copy(W[Math.floor((w[nb] - 1) / 2)]);
+            for (i = nb - 1; i >= 0; i--) {
+                Q.select(W, w[i]);
+                P.dbl();
+                P.dbl();
+                P.dbl();
+                P.dbl();
+                P.add(Q);
+            }
+            P.sub(C);
+            P.affine();
+
+            return P;
+        }
+    };
+
+    // set to group generator
+    ECP4.generator = function() {
+        var G=new ECP4(),
+            A = new ctx.BIG(0),
+            B = new ctx.BIG(0),
+            XA, XB, X, YA, YB, Y;
+
+        A.rcopy(ctx.ROM_CURVE.CURVE_Pxaa);
+        B.rcopy(ctx.ROM_CURVE.CURVE_Pxab);
+        XA= new ctx.FP2(A,B);
+
+        A.rcopy(ctx.ROM_CURVE.CURVE_Pxba);
+        B.rcopy(ctx.ROM_CURVE.CURVE_Pxbb);
+
+        XB= new ctx.FP2(A,B);
+        X=new ctx.FP4(XA,XB);
+
+        A.rcopy(ctx.ROM_CURVE.CURVE_Pyaa);
+        B.rcopy(ctx.ROM_CURVE.CURVE_Pyab);
+        YA= new ctx.FP2(A,B);
+
+        A.rcopy(ctx.ROM_CURVE.CURVE_Pyba);
+        B.rcopy(ctx.ROM_CURVE.CURVE_Pybb);
+
+        YB= new ctx.FP2(A,B);
+        Y=new ctx.FP4(YA,YB);
+
+        G.setxy(X,Y);
+
+        return G;
+    };
+
+    /* convert from byte array to point */
+    ECP4.fromBytes = function(b) {
+        var t = [],
+            ra, rb, ra4, rb4, i, rx, ry, P;
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = b[i];
+        }
+        ra = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = b[i + ctx.BIG.MODBYTES];
+        }
+        rb = ctx.BIG.fromBytes(t);
+        ra4=new ctx.FP2(ra,rb);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = b[i  + 2*ctx.BIG.MODBYTES];
+        }
+        ra = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = b[i + 3*ctx.BIG.MODBYTES];
+        }
+        rb = ctx.BIG.fromBytes(t);
+        rb4=new ctx.FP2(ra,rb);
+
+        rx = new ctx.FP4(ra4, rb4); //rx.bset(ra,rb);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = b[i + 4 * ctx.BIG.MODBYTES];
+        }
+        ra = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = b[i + 5 * ctx.BIG.MODBYTES];
+        }
+        rb = ctx.BIG.fromBytes(t);
+        ra4=new ctx.FP2(ra,rb);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = b[i + 6 * ctx.BIG.MODBYTES];
+        }
+        ra = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = b[i + 7 * ctx.BIG.MODBYTES];
+        }
+        rb = ctx.BIG.fromBytes(t);
+        rb4=new ctx.FP2(ra,rb);
+
+
+        ry = new ctx.FP4(ra4, rb4); //ry.bset(ra,rb);
+
+        P = new ECP4();
+        P.setxy(rx, ry);
+
+        return P;
+    };
+
+    /* Calculate RHS of curve equation x^3+B */
+    ECP4.RHS = function(x) {
+        var r, c, b;
+
+        //x.norm();
+        r = new ctx.FP4(x); //r.copy(x);
+        r.sqr();
+
+        c = new ctx.BIG(0);
+        c.rcopy(ctx.ROM_CURVE.CURVE_B);
+        b = new ctx.FP4(c); //b.bseta(c);
+
+        if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) {
+            b.div_i();
+        }
+        if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) {
+            b.times_i();
+        }
+
+        r.mul(x);
+        r.add(b);
+
+        r.reduce();
+        return r;
+    };
+
+    /* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3... */
+    // Bos & Costello https://eprint.iacr.org/2013/458.pdf
+    // Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
+    // Side channel attack secure
+    ECP4.mul8 = function(Q, u) {
+        var W = new ECP4(),
+            P = new ECP4(),
+            T1 = [],
+            T2 = [],
+            mt = new ctx.BIG(),
+            t = [],
+            w1 = [],
+            s1 = [],
+            w2 = [],
+            s2 = [],
+            F=ECP4.frob_constants(),
+            i, j, k, nb, bt, pb1, pb2;
+
+        for (i = 0; i < 8; i++) {
+            t[i] = new ctx.BIG(u[i]); t[i].norm();
+            //Q[i].affine();
+        }
+
+        T1[0] = new ECP4(); T1[0].copy(Q[0]); // Q[0]
+        T1[1] = new ECP4(); T1[1].copy(T1[0]); T1[1].add(Q[1]); // Q[0]+Q[1]
+        T1[2] = new ECP4(); T1[2].copy(T1[0]); T1[2].add(Q[2]); // Q[0]+Q[2]
+        T1[3] = new ECP4(); T1[3].copy(T1[1]); T1[3].add(Q[2]); // Q[0]+Q[1]+Q[2]
+        T1[4] = new ECP4(); T1[4].copy(T1[0]); T1[4].add(Q[3]); // Q[0]+Q[3]
+        T1[5] = new ECP4(); T1[5].copy(T1[1]); T1[5].add(Q[3]); // Q[0]+Q[1]+Q[3]
+        T1[6] = new ECP4(); T1[6].copy(T1[2]); T1[6].add(Q[3]); // Q[0]+Q[2]+Q[3]
+        T1[7] = new ECP4(); T1[7].copy(T1[3]); T1[7].add(Q[3]); // Q[0]+Q[1]+Q[2]+Q[3]
+
+        //  Use Frobenius
+        for (i=0;i<8;i++) {
+            T2[i] = new ECP4(); T2[i].copy(T1[i]);
+            T2[i].frob(F,4);
+        }
+
+        // Make it odd
+        pb1=1-t[0].parity();
+        t[0].inc(pb1);
+        t[0].norm();
+
+        pb2=1-t[4].parity();
+        t[4].inc(pb2);
+        t[4].norm();
+
+        // Number of bits
+        mt.zero();
+        for (i=0;i<8;i++) {
+            mt.or(t[i]);
+        }
+
+        nb=1+mt.nbits();
+
+        // Sign pivot
+        s1[nb-1]=1;
+        s2[nb-1]=1;
+        for (i=0;i<nb-1;i++) {
+            t[0].fshr(1);
+            s1[i]=2*t[0].parity()-1;
+            t[4].fshr(1);
+            s2[i]=2*t[4].parity()-1;
+        }
+
+        // Recoded exponent
+        for (i=0; i<nb; i++) {
+            w1[i]=0;
+            k=1;
+            for (j=1; j<4; j++) {
+                bt=s1[i]*t[j].parity();
+                t[j].fshr(1);
+                t[j].dec(bt>>1);
+                t[j].norm();
+                w1[i]+=bt*k;
+                k*=2;
+            }
+            w2[i]=0;
+            k=1;
+            for (j=5; j<8; j++) {
+                bt=s2[i]*t[j].parity();
+                t[j].fshr(1);
+                t[j].dec(bt>>1);
+                t[j].norm();
+                w2[i]+=bt*k;
+                k*=2;
+            }
+        }
+
+        // Main loop
+        P.select(T1,2*w1[nb-1]+1);
+        W.select(T2,2*w2[nb-1]+1);
+        P.add(W);
+        for (i=nb-2;i>=0;i--) {
+            P.dbl();
+            W.select(T1,2*w1[i]+s1[i]);
+            P.add(W);
+            W.select(T2,2*w2[i]+s2[i]);
+            P.add(W);
+        }
+
+        // apply correction
+        W.copy(P);
+        W.sub(Q[0]);
+        P.cmove(W,pb1);
+
+        W.copy(P);
+        W.sub(Q[4]);
+        P.cmove(W,pb2);
+
+        P.affine();
+        return P;
+    };
+
+    /* return 1 if b==c, no branching */
+    ECP4.teq = function(b, c) {
+        var x = b ^ c;
+        x -= 1; // if x=0, x now -1
+        return ((x >> 31) & 1);
+    };
+
+    /* needed for SOK */
+    ECP4.mapit = function(h) {
+        var F=ECP4.frob_constants(),
+            q, x, one, Q, X, X2, xQ, x2Q, x3Q, x4Q;
+
+        q = new ctx.BIG(0);
+        q.rcopy(ctx.ROM_FIELD.Modulus);
+        x = ctx.BIG.fromBytes(h);
+        one = new ctx.BIG(1);
+        x.mod(q);
+
+        for (;;) {
+            X2 = new ctx.FP2(one, x);
+            X = new ctx.FP4(X2);
+            Q = new ECP4();
+            Q.setx(X);
+            if (!Q.is_infinity()) {
+                break;
+            }
+            x.inc(1);
+            x.norm();
+        }
+
+        /* Fast Hashing to G2 - Fuentes-Castaneda, Knapp and Rodriguez-Henriquez */
+        x = new ctx.BIG(0);
+        x.rcopy(ctx.ROM_CURVE.CURVE_Bnx);
+
+
+        xQ = Q.mul(x);
+        x2Q = xQ.mul(x);
+        x3Q = x2Q.mul(x);
+        x4Q = x3Q.mul(x);
+
+        if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) {
+            xQ.neg();
+            x3Q.neg();
+        }
+
+        x4Q.sub(x3Q);
+        x4Q.sub(Q);
+
+        x3Q.sub(x2Q);
+        x3Q.frob(F,1);
+
+        x2Q.sub(xQ);
+        x2Q.frob(F,2);
+
+        xQ.sub(Q);
+        xQ.frob(F,3);
+
+        Q.dbl();
+        Q.frob(F,4);
+
+        Q.add(x4Q);
+        Q.add(x3Q);
+        Q.add(x2Q);
+        Q.add(xQ);
+
+        Q.affine();
+        return Q;
+    };
+
+    ECP4.frob_constants = function() {
+        var fa = new ctx.BIG(0),
+            fb = new ctx.BIG(0),
+            F=[],
+            X, F0, F1, F2;
+
+        fa.rcopy(ctx.ROM_FIELD.Fra);
+        fb.rcopy(ctx.ROM_FIELD.Frb);
+        X = new ctx.FP2(fa, fb);
+
+        F0=new ctx.FP2(X); F0.sqr();
+        F2=new ctx.FP2(F0);
+        F2.mul_ip(); F2.norm();
+        F1=new ctx.FP2(F2); F1.sqr();
+        F2.mul(F1);
+        F1.copy(X);
+        if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) {
+            F1.mul_ip();
+            F1.inverse();
+            F0.copy(F1); F0.sqr();
+        }
+        F0.mul_ip(); F0.norm();
+        F1.mul(F0);
+
+        F[0]=new ctx.FP2(F0); F[1]=new ctx.FP2(F1); F[2]=new ctx.FP2(F2);
+        return F;
+    };
+
+    return ECP4;
+};
diff --git a/version3/js/ecp8.js b/version3/js/ecp8.js
new file mode 100644
index 0000000..b4ba6c6
--- /dev/null
+++ b/version3/js/ecp8.js
@@ -0,0 +1,1061 @@
+/*
+    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.
+*/
+
+/* AMCL Weierstrass elliptic curve functions over ctx.FP8 */
+
+var ECP8 = function(ctx) {
+    "use strict";
+
+    /* Constructor, set this=O */
+    var ECP8 = function() {
+        this.x = new ctx.FP8(0);
+        this.y = new ctx.FP8(1);
+        this.z = new ctx.FP8(0);
+        // this.INF = true;
+    };
+
+    ECP8.prototype = {
+        /* Test this=O? */
+        is_infinity: function() {
+            // if (this.INF) {
+            //     return true;
+            // }
+
+            this.x.reduce();
+            this.y.reduce();
+            this.z.reduce();
+            return (this.x.iszilch() && this.z.iszilch());
+        },
+
+        /* copy this=P */
+        copy: function(P) {
+            this.x.copy(P.x);
+            this.y.copy(P.y);
+            this.z.copy(P.z);
+            // this.INF = P.INF;
+        },
+
+        /* set this=O */
+        inf: function() {
+            // this.INF = true;
+            this.x.zero();
+            this.y.one();
+            this.z.zero();
+        },
+
+        /* conditional move of Q to P dependant on d */
+        cmove: function(Q, d) {
+            this.x.cmove(Q.x, d);
+            this.y.cmove(Q.y, d);
+            this.z.cmove(Q.z, d);
+
+            // bd = (d !== 0) ? true : false;
+            // this.INF ^= (this.INF ^ Q.INF) & bd;
+        },
+
+        /* Constant time select from pre-computed table */
+        select: function(W, b) {
+            var MP = new ECP8(),
+                m = b >> 31,
+                babs = (b ^ m) - m;
+
+            babs = (babs - 1) / 2;
+
+            this.cmove(W[0], ECP8.teq(babs, 0)); // conditional move
+            this.cmove(W[1], ECP8.teq(babs, 1));
+            this.cmove(W[2], ECP8.teq(babs, 2));
+            this.cmove(W[3], ECP8.teq(babs, 3));
+            this.cmove(W[4], ECP8.teq(babs, 4));
+            this.cmove(W[5], ECP8.teq(babs, 5));
+            this.cmove(W[6], ECP8.teq(babs, 6));
+            this.cmove(W[7], ECP8.teq(babs, 7));
+
+            MP.copy(this);
+            MP.neg();
+            this.cmove(MP, (m & 1));
+        },
+
+        /* Test P == Q */
+        equals: function(Q) {
+            var a, b;
+
+            a = new ctx.FP8(this.x);
+            b = new ctx.FP8(Q.x);
+
+            a.mul(Q.z);
+            b.mul(this.z);
+            if (!a.equals(b)) {
+                return false;
+            }
+
+            a.copy(this.y);
+            a.mul(Q.z);
+            b.copy(Q.y);
+            b.mul(this.z);
+            if (!a.equals(b)) {
+                return false;
+            }
+
+            return true;
+        },
+
+        /* set this=-this */
+        neg: function() {
+            this.y.norm();
+            this.y.neg();
+            this.y.norm();
+            return;
+        },
+
+        /* convert this to affine, from (x,y,z) to (x,y) */
+        affine: function() {
+            var one;
+
+            if (this.is_infinity()) {
+                return;
+            }
+
+            one = new ctx.FP8(1);
+
+            if (this.z.equals(one)) {
+                this.x.reduce();
+                this.y.reduce();
+                return;
+            }
+
+            this.z.inverse();
+            this.x.mul(this.z);
+            this.x.reduce();
+            this.y.mul(this.z);
+            this.y.reduce();
+            this.z.copy(one);
+        },
+
+        /* extract affine x as ctx.FP8 */
+        getX: function() {
+			var W=new ECP8(); W.copy(this); W.affine();
+            //this.affine();
+            return W.x;
+        },
+
+        /* extract affine y as ctx.FP8 */
+        getY: function() {
+			var W=new ECP8(); W.copy(this); W.affine();
+            //this.affine();
+            return W.y;
+        },
+
+        /* extract projective x */
+        getx: function() {
+            return this.x;
+        },
+
+        /* extract projective y */
+        gety: function() {
+            return this.y;
+        },
+
+        /* extract projective z */
+        getz: function() {
+            return this.z;
+        },
+
+        /* convert this to byte array */
+        toBytes: function(b) {
+            var t = [],
+                i;
+			var W=new ECP8(); W.copy(this);
+            W.affine();
+            W.x.geta().geta().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                b[i] = t[i];
+            }
+            W.x.geta().geta().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                b[i + ctx.BIG.MODBYTES] = t[i];
+            }
+            W.x.geta().getb().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                b[i + 2*ctx.BIG.MODBYTES] = t[i];
+            }
+            W.x.geta().getb().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                b[i + 3*ctx.BIG.MODBYTES] = t[i];
+            }
+
+            W.x.getb().geta().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                b[i + 4*ctx.BIG.MODBYTES] = t[i];
+            }
+            W.x.getb().geta().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                b[i + 5*ctx.BIG.MODBYTES] = t[i];
+            }
+            W.x.getb().getb().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                b[i + 6*ctx.BIG.MODBYTES] = t[i];
+            }
+            W.x.getb().getb().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                b[i + 7*ctx.BIG.MODBYTES] = t[i];
+            }
+
+            W.y.geta().geta().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                b[i + 8 * ctx.BIG.MODBYTES] = t[i];
+            }
+            W.y.geta().geta().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                b[i + 9 * ctx.BIG.MODBYTES] = t[i];
+            }
+            W.y.geta().getb().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                b[i + 10 * ctx.BIG.MODBYTES] = t[i];
+            }
+            W.y.geta().getb().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                b[i + 11 * ctx.BIG.MODBYTES] = t[i];
+            }
+
+            W.y.getb().geta().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                b[i + 12 * ctx.BIG.MODBYTES] = t[i];
+            }
+            W.y.getb().geta().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                b[i + 13 * ctx.BIG.MODBYTES] = t[i];
+            }
+            W.y.getb().getb().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                b[i + 14 * ctx.BIG.MODBYTES] = t[i];
+            }
+            W.y.getb().getb().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                b[i + 15 * ctx.BIG.MODBYTES] = t[i];
+            }
+        },
+
+        /* convert this to hex string */
+        toString: function() {
+			var W=new ECP8(); W.copy(this);
+            if (W.is_infinity()) {
+                return "infinity";
+            }
+            W.affine();
+            return "(" + W.x.toString() + "," + W.y.toString() + ")";
+        },
+
+        /* set this=(x,y) */
+        setxy: function(ix, iy) {
+            var rhs, y2;
+
+            this.x.copy(ix);
+            this.y.copy(iy);
+            this.z.one();
+			this.x.norm();
+
+            rhs = ECP8.RHS(this.x);
+
+            y2 = new ctx.FP8(this.y); //y2.copy(this.y);
+            y2.sqr();
+
+            if (!y2.equals(rhs)) {
+                this.inf();
+            }
+        },
+
+        /* set this=(x,.) */
+        setx: function(ix) {
+            var rhs;
+
+            this.x.copy(ix);
+            this.z.one();
+			this.x.norm();
+            rhs = ECP8.RHS(this.x);
+
+            if (rhs.sqrt()) {
+                this.y.copy(rhs);
+            } else {
+                this.inf();
+            }
+        },
+
+        /* set this*=q, where q is Modulus, using Frobenius */
+        frob: function(F,n) {
+            for (var i=0;i<n;i++) {
+                this.x.frob(F[2]);
+                this.x.qmul(F[0]);
+                if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) {
+                    this.x.div_i2();
+                }
+                if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) {
+                    this.x.times_i2();
+                }
+
+                this.y.frob(F[2]);
+                this.y.qmul(F[1]);
+
+                if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) {
+                    this.y.div_i();
+                }
+                if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) {
+                    this.y.times_i2(); this.y.times_i2(); this.y.times_i();
+                }
+                this.z.frob(F[2]);
+            }
+        },
+
+        /* this+=this */
+        dbl: function() {
+            var iy, t0, t1, t2, x3, y3;
+
+            iy = new ctx.FP8(this.y);
+            if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) {
+                iy.times_i();
+                iy.norm();
+            }
+
+            t0 = new ctx.FP8(this.y);
+            t0.sqr();
+            if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) {
+                t0.times_i();
+            }
+            t1 = new ctx.FP8(iy);
+            t1.mul(this.z);
+            t2 = new ctx.FP8(this.z);
+            t2.sqr();
+
+            this.z.copy(t0);
+            this.z.add(t0);
+            this.z.norm();
+            this.z.add(this.z);
+            this.z.add(this.z);
+            this.z.norm();
+
+            t2.imul(3 * ctx.ROM_CURVE.CURVE_B_I);
+            if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) {
+                t2.times_i();
+            }
+
+            x3 = new ctx.FP8(t2);
+            x3.mul(this.z);
+
+            y3 = new ctx.FP8(t0);
+
+            y3.add(t2);
+            y3.norm();
+            this.z.mul(t1);
+            t1.copy(t2);
+            t1.add(t2);
+            t2.add(t1);
+            t2.norm();
+            t0.sub(t2);
+            t0.norm(); //y^2-9bz^2
+            y3.mul(t0);
+            y3.add(x3); //(y^2+3z*2)(y^2-9z^2)+3b.z^2.8y^2
+            t1.copy(this.x);
+            t1.mul(iy); //
+            this.x.copy(t0);
+            this.x.norm();
+            this.x.mul(t1);
+            this.x.add(this.x); //(y^2-9bz^2)xy2
+
+            this.x.norm();
+            this.y.copy(y3);
+            this.y.norm();
+
+            return 1;
+        },
+
+        /* this+=Q */
+        add: function(Q) {
+            var b, t0, t1, t2, t3, t4, x3, y3, z3;
+
+            b = 3 * ctx.ROM_CURVE.CURVE_B_I;
+            t0 = new ctx.FP8(this.x);
+            t0.mul(Q.x); // x.Q.x
+            t1 = new ctx.FP8(this.y);
+            t1.mul(Q.y); // y.Q.y
+
+            t2 = new ctx.FP8(this.z);
+            t2.mul(Q.z);
+            t3 = new ctx.FP8(this.x);
+            t3.add(this.y);
+            t3.norm(); //t3=X1+Y1
+            t4 = new ctx.FP8(Q.x);
+            t4.add(Q.y);
+            t4.norm(); //t4=X2+Y2
+            t3.mul(t4); //t3=(X1+Y1)(X2+Y2)
+            t4.copy(t0);
+            t4.add(t1); //t4=X1.X2+Y1.Y2
+
+            t3.sub(t4);
+            t3.norm();
+            if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) {
+                t3.times_i();  //t3=(X1+Y1)(X2+Y2)-(X1.X2+Y1.Y2) = X1.Y2+X2.Y1
+            }
+
+            t4.copy(this.y);
+            t4.add(this.z);
+            t4.norm(); //t4=Y1+Z1
+            x3 = new ctx.FP8(Q.y);
+            x3.add(Q.z);
+            x3.norm(); //x3=Y2+Z2
+
+            t4.mul(x3); //t4=(Y1+Z1)(Y2+Z2)
+            x3.copy(t1); //
+            x3.add(t2); //X3=Y1.Y2+Z1.Z2
+
+            t4.sub(x3);
+            t4.norm();
+            if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) {
+                t4.times_i();  //t4=(Y1+Z1)(Y2+Z2) - (Y1.Y2+Z1.Z2) = Y1.Z2+Y2.Z1
+            }
+
+            x3.copy(this.x);
+            x3.add(this.z);
+            x3.norm(); // x3=X1+Z1
+            y3 = new ctx.FP8(Q.x);
+            y3.add(Q.z);
+            y3.norm(); // y3=X2+Z2
+            x3.mul(y3); // x3=(X1+Z1)(X2+Z2)
+            y3.copy(t0);
+            y3.add(t2); // y3=X1.X2+Z1+Z2
+            y3.rsub(x3);
+            y3.norm(); // y3=(X1+Z1)(X2+Z2) - (X1.X2+Z1.Z2) = X1.Z2+X2.Z1
+
+            if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) {
+                t0.times_i();
+                t1.times_i();
+            }
+
+            x3.copy(t0);
+            x3.add(t0);
+            t0.add(x3);
+            t0.norm();
+            t2.imul(b);
+            if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) {
+                t2.times_i();
+            }
+
+            z3 = new ctx.FP8(t1);
+            z3.add(t2);
+            z3.norm();
+            t1.sub(t2);
+            t1.norm();
+            y3.imul(b);
+            if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) {
+                y3.times_i();
+            }
+
+            x3.copy(y3);
+            x3.mul(t4);
+            t2.copy(t3);
+            t2.mul(t1);
+            x3.rsub(t2);
+            y3.mul(t0);
+            t1.mul(z3);
+            y3.add(t1);
+            t0.mul(t3);
+            z3.mul(t4);
+            z3.add(t0);
+
+            this.x.copy(x3);
+            this.x.norm();
+            this.y.copy(y3);
+            this.y.norm();
+            this.z.copy(z3);
+            this.z.norm();
+
+            return 0;
+        },
+
+        /* this-=Q */
+        sub: function(Q) {
+            var D;
+
+			var NQ=new ECP8(); NQ.copy(Q);
+            NQ.neg();
+            D = this.add(NQ);
+            //Q.neg();
+
+            return D;
+        },
+
+        /* P*=e */
+        mul: function(e) {
+            /* fixed size windows */
+            var mt = new ctx.BIG(),
+                t = new ctx.BIG(),
+                C = new ECP8(),
+                P = new ECP8(),
+                Q = new ECP8(),
+                W = [],
+                w = [],
+                i, nb, s, ns;
+
+            if (this.is_infinity()) {
+                return new ECP8();
+            }
+
+            //this.affine();
+
+            // precompute table
+            Q.copy(this);
+            Q.dbl();
+            W[0] = new ECP8();
+            W[0].copy(this);
+
+            for (i = 1; i < 8; i++) {
+                W[i] = new ECP8();
+                W[i].copy(W[i - 1]);
+                W[i].add(Q);
+            }
+
+            // make exponent odd - add 2P if even, P if odd
+            t.copy(e);
+            s = t.parity();
+            t.inc(1);
+            t.norm();
+            ns = t.parity();
+            mt.copy(t);
+            mt.inc(1);
+            mt.norm();
+            t.cmove(mt, s);
+            Q.cmove(this, ns);
+            C.copy(Q);
+
+            nb = 1 + Math.floor((t.nbits() + 3) / 4);
+
+            // convert exponent to signed 4-bit window
+            for (i = 0; i < nb; i++) {
+                w[i] = (t.lastbits(5) - 16);
+                t.dec(w[i]);
+                t.norm();
+                t.fshr(4);
+            }
+            w[nb] = t.lastbits(5);
+
+            P.copy(W[Math.floor((w[nb] - 1) / 2)]);
+            for (i = nb - 1; i >= 0; i--) {
+                Q.select(W, w[i]);
+                P.dbl();
+                P.dbl();
+                P.dbl();
+                P.dbl();
+                P.add(Q);
+            }
+            P.sub(C);
+            P.affine();
+
+            return P;
+        }
+    };
+
+    // set to group generator
+    ECP8.generator = function() {
+        var G=new ECP8(),
+            A = new ctx.BIG(0),
+            B = new ctx.BIG(0),
+            XAA, XAB, XA, XBA, XBB, XB, X,
+            YAA, YAB, YA, YBA, YBB, YB, Y;
+
+        A.rcopy(ctx.ROM_CURVE.CURVE_Pxaaa);
+        B.rcopy(ctx.ROM_CURVE.CURVE_Pxaab);
+        XAA= new ctx.FP2(A,B);
+
+        A.rcopy(ctx.ROM_CURVE.CURVE_Pxaba);
+        B.rcopy(ctx.ROM_CURVE.CURVE_Pxabb);
+
+        XAB= new ctx.FP2(A,B);
+        XA=new ctx.FP4(XAA,XAB);
+
+        A.rcopy(ctx.ROM_CURVE.CURVE_Pxbaa);
+        B.rcopy(ctx.ROM_CURVE.CURVE_Pxbab);
+        XBA= new ctx.FP2(A,B);
+
+        A.rcopy(ctx.ROM_CURVE.CURVE_Pxbba);
+        B.rcopy(ctx.ROM_CURVE.CURVE_Pxbbb);
+
+        XBB= new ctx.FP2(A,B);
+        XB=new ctx.FP4(XBA,XBB);
+
+        X=new ctx.FP8(XA,XB);
+
+
+        A.rcopy(ctx.ROM_CURVE.CURVE_Pyaaa);
+        B.rcopy(ctx.ROM_CURVE.CURVE_Pyaab);
+        YAA= new ctx.FP2(A,B);
+
+        A.rcopy(ctx.ROM_CURVE.CURVE_Pyaba);
+        B.rcopy(ctx.ROM_CURVE.CURVE_Pyabb);
+
+        YAB= new ctx.FP2(A,B);
+        YA=new ctx.FP4(YAA,YAB);
+
+        A.rcopy(ctx.ROM_CURVE.CURVE_Pybaa);
+        B.rcopy(ctx.ROM_CURVE.CURVE_Pybab);
+        YBA= new ctx.FP2(A,B);
+
+        A.rcopy(ctx.ROM_CURVE.CURVE_Pybba);
+        B.rcopy(ctx.ROM_CURVE.CURVE_Pybbb);
+
+        YBB= new ctx.FP2(A,B);
+        YB=new ctx.FP4(YBA,YBB);
+
+        Y=new ctx.FP8(YA,YB);
+
+        G.setxy(X,Y);
+
+        return G;
+    };
+
+    /* convert from byte array to point */
+    ECP8.fromBytes = function(b) {
+        var t = [],
+            ra, rb, ra4, rb4, ra8, rb8, i, rx, ry, P;
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = b[i];
+        }
+        ra = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = b[i + ctx.BIG.MODBYTES];
+        }
+        rb = ctx.BIG.fromBytes(t);
+        ra4=new ctx.FP2(ra,rb);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = b[i  + 2*ctx.BIG.MODBYTES];
+        }
+        ra = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = b[i + 3*ctx.BIG.MODBYTES];
+        }
+        rb = ctx.BIG.fromBytes(t);
+        rb4=new ctx.FP2(ra,rb);
+
+        ra8=new ctx.FP4(ra4,rb4);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = b[i + 4*ctx.BIG.MODBYTES];
+        }
+        ra = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = b[i + 5*ctx.BIG.MODBYTES];
+        }
+        rb = ctx.BIG.fromBytes(t);
+        ra4=new ctx.FP2(ra,rb);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = b[i  + 6*ctx.BIG.MODBYTES];
+        }
+        ra = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = b[i + 7*ctx.BIG.MODBYTES];
+        }
+        rb = ctx.BIG.fromBytes(t);
+        rb4=new ctx.FP2(ra,rb);
+
+        rb8=new ctx.FP4(ra4,rb4);
+
+        rx = new ctx.FP8(ra8, rb8); //rx.bset(ra,rb);
+
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = b[i + 8 * ctx.BIG.MODBYTES];
+        }
+        ra = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = b[i + 9 * ctx.BIG.MODBYTES];
+        }
+        rb = ctx.BIG.fromBytes(t);
+        ra4=new ctx.FP2(ra,rb);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = b[i + 10 * ctx.BIG.MODBYTES];
+        }
+        ra = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = b[i + 11 * ctx.BIG.MODBYTES];
+        }
+        rb = ctx.BIG.fromBytes(t);
+        rb4=new ctx.FP2(ra,rb);
+
+        ra8=new ctx.FP4(ra4,rb4);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = b[i + 12 * ctx.BIG.MODBYTES];
+        }
+        ra = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = b[i + 13 * ctx.BIG.MODBYTES];
+        }
+        rb = ctx.BIG.fromBytes(t);
+        ra4=new ctx.FP2(ra,rb);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = b[i + 14 * ctx.BIG.MODBYTES];
+        }
+        ra = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = b[i + 15 * ctx.BIG.MODBYTES];
+        }
+        rb = ctx.BIG.fromBytes(t);
+        rb4=new ctx.FP2(ra,rb);
+
+        rb8=new ctx.FP4(ra4,rb4);
+
+        ry = new ctx.FP8(ra8, rb8); //ry.bset(ra,rb);
+
+        P = new ECP8();
+        P.setxy(rx, ry);
+
+        return P;
+    };
+
+    /* Calculate RHS of curve equation x^3+B */
+    ECP8.RHS = function(x) {
+        var r, c, b;
+
+        //x.norm();
+        r = new ctx.FP8(x); //r.copy(x);
+        r.sqr();
+
+        c = new ctx.BIG(0);
+        c.rcopy(ctx.ROM_CURVE.CURVE_B);
+        b = new ctx.FP8(c); //b.bseta(c);
+
+        if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) {
+            b.div_i();
+        }
+        if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) {
+            b.times_i();
+        }
+
+        r.mul(x);
+        r.add(b);
+
+        r.reduce();
+        return r;
+    };
+
+    /* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3... */
+    // Bos & Costello https://eprint.iacr.org/2013/458.pdf
+    // Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
+    // Side channel attack secure
+    ECP8.mul16 = function(Q, u) {
+        var W = new ECP8(),
+            P = new ECP8(),
+            T1 = [],
+            T2 = [],
+            T3 = [],
+            T4 = [],
+            mt = new ctx.BIG(),
+            t = [],
+            w1 = [],
+            s1 = [],
+            w2 = [],
+            s2 = [],
+            w3 = [],
+            s3 = [],
+            w4 = [],
+            s4 = [],
+            F=ECP8.frob_constants(),
+            i, j, k, nb, bt, pb1, pb2, pb3, pb4;
+
+        for (i = 0; i < 16; i++) {
+            t[i] = new ctx.BIG(u[i]); t[i].norm();
+            //Q[i].affine();
+        }
+
+        T1[0] = new ECP8(); T1[0].copy(Q[0]); // Q[0]
+        T1[1] = new ECP8(); T1[1].copy(T1[0]); T1[1].add(Q[1]); // Q[0]+Q[1]
+        T1[2] = new ECP8(); T1[2].copy(T1[0]); T1[2].add(Q[2]); // Q[0]+Q[2]
+        T1[3] = new ECP8(); T1[3].copy(T1[1]); T1[3].add(Q[2]); // Q[0]+Q[1]+Q[2]
+        T1[4] = new ECP8(); T1[4].copy(T1[0]); T1[4].add(Q[3]); // Q[0]+Q[3]
+        T1[5] = new ECP8(); T1[5].copy(T1[1]); T1[5].add(Q[3]); // Q[0]+Q[1]+Q[3]
+        T1[6] = new ECP8(); T1[6].copy(T1[2]); T1[6].add(Q[3]); // Q[0]+Q[2]+Q[3]
+        T1[7] = new ECP8(); T1[7].copy(T1[3]); T1[7].add(Q[3]); // Q[0]+Q[1]+Q[2]+Q[3]
+
+        //  Use Frobenius
+        for (i=0;i<8;i++) {
+            T2[i] = new ECP8(); T2[i].copy(T1[i]);
+            T2[i].frob(F,4);
+            T3[i] = new ECP8(); T3[i].copy(T2[i]);
+            T3[i].frob(F,4);
+            T4[i] = new ECP8(); T4[i].copy(T3[i]);
+            T4[i].frob(F,4);
+        }
+
+        // Make it odd
+        pb1=1-t[0].parity();
+        t[0].inc(pb1);
+        t[0].norm();
+
+        pb2=1-t[4].parity();
+        t[4].inc(pb2);
+        t[4].norm();
+
+        pb3=1-t[8].parity();
+        t[8].inc(pb3);
+        t[8].norm();
+
+        pb4=1-t[12].parity();
+        t[12].inc(pb4);
+        t[12].norm();
+
+        // Number of bits
+        mt.zero();
+        for (i=0;i<16;i++) {
+            mt.or(t[i]);
+        }
+
+        nb=1+mt.nbits();
+
+        // Sign pivot
+        s1[nb-1]=1;
+        s2[nb-1]=1;
+        s3[nb-1]=1;
+        s4[nb-1]=1;
+        for (i=0;i<nb-1;i++) {
+            t[0].fshr(1);
+            s1[i]=2*t[0].parity()-1;
+            t[4].fshr(1);
+            s2[i]=2*t[4].parity()-1;
+
+            t[8].fshr(1);
+            s3[i]=2*t[8].parity()-1;
+            t[12].fshr(1);
+            s4[i]=2*t[12].parity()-1;
+        }
+
+        // Recoded exponent
+        for (i=0; i<nb; i++) {
+            w1[i]=0;
+            k=1;
+            for (j=1; j<4; j++) {
+                bt=s1[i]*t[j].parity();
+                t[j].fshr(1);
+                t[j].dec(bt>>1);
+                t[j].norm();
+                w1[i]+=bt*k;
+                k*=2;
+            }
+            w2[i]=0;
+            k=1;
+            for (j=5; j<8; j++) {
+                bt=s2[i]*t[j].parity();
+                t[j].fshr(1);
+                t[j].dec(bt>>1);
+                t[j].norm();
+                w2[i]+=bt*k;
+                k*=2;
+            }
+
+            w3[i]=0;
+            k=1;
+            for (j=9; j<12; j++) {
+                bt=s3[i]*t[j].parity();
+                t[j].fshr(1);
+                t[j].dec(bt>>1);
+                t[j].norm();
+                w3[i]+=bt*k;
+                k*=2;
+            }
+            w4[i]=0;
+            k=1;
+            for (j=13; j<16; j++) {
+                bt=s4[i]*t[j].parity();
+                t[j].fshr(1);
+                t[j].dec(bt>>1);
+                t[j].norm();
+                w4[i]+=bt*k;
+                k*=2;
+            }
+        }
+
+        // Main loop
+        P.select(T1,2*w1[nb-1]+1);
+        W.select(T2,2*w2[nb-1]+1);
+        P.add(W);
+        W.select(T3,2*w3[nb-1]+1);
+        P.add(W);
+        W.select(T4,2*w4[nb-1]+1);
+        P.add(W);
+        for (i=nb-2;i>=0;i--) {
+            P.dbl();
+            W.select(T1,2*w1[i]+s1[i]);
+            P.add(W);
+            W.select(T2,2*w2[i]+s2[i]);
+            P.add(W);
+            W.select(T3,2*w3[i]+s3[i]);
+            P.add(W);
+            W.select(T4,2*w4[i]+s4[i]);
+            P.add(W);
+        }
+
+        // apply correction
+        W.copy(P);
+        W.sub(Q[0]);
+        P.cmove(W,pb1);
+
+        W.copy(P);
+        W.sub(Q[4]);
+        P.cmove(W,pb2);
+
+        W.copy(P);
+        W.sub(Q[8]);
+        P.cmove(W,pb3);
+
+        W.copy(P);
+        W.sub(Q[12]);
+        P.cmove(W,pb4);
+
+        P.affine();
+        return P;
+    };
+
+    /* return 1 if b==c, no branching */
+    ECP8.teq = function(b, c) {
+        var x = b ^ c;
+        x -= 1; // if x=0, x now -1
+        return ((x >> 31) & 1);
+    };
+
+    /* needed for SOK */
+    ECP8.mapit = function(h) {
+        var F=ECP8.frob_constants(),
+            q, x, one, Q, X, X2, X4,
+            xQ, x2Q, x3Q, x4Q, x5Q, x6Q, x7Q, x8Q;
+
+        q = new ctx.BIG(0);
+        q.rcopy(ctx.ROM_FIELD.Modulus);
+        x = ctx.BIG.fromBytes(h);
+        one = new ctx.BIG(1);
+        x.mod(q);
+
+        for (;;) {
+            X2 = new ctx.FP2(one, x);
+            X4 = new ctx.FP4(X2);
+            X = new ctx.FP8(X4);
+            Q = new ECP8();
+            Q.setx(X);
+            if (!Q.is_infinity()) {
+                break;
+            }
+            x.inc(1);
+            x.norm();
+        }
+
+        /* Fast Hashing to G2 - Fuentes-Castaneda, Knapp and Rodriguez-Henriquez */
+        x = new ctx.BIG(0);
+        x.rcopy(ctx.ROM_CURVE.CURVE_Bnx);
+
+
+        xQ = Q.mul(x);
+        x2Q = xQ.mul(x);
+        x3Q = x2Q.mul(x);
+        x4Q = x3Q.mul(x);
+        x5Q = x4Q.mul(x);
+        x6Q = x5Q.mul(x);
+        x7Q = x6Q.mul(x);
+        x8Q = x7Q.mul(x);
+
+        if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) {
+            xQ.neg();
+            x3Q.neg();
+            x5Q.neg();
+            x7Q.neg();
+        }
+
+        x8Q.sub(x7Q);
+        x8Q.sub(Q);
+
+        x7Q.sub(x6Q);
+        x7Q.frob(F,1);
+
+        x6Q.sub(x5Q);
+        x6Q.frob(F,2);
+
+        x5Q.sub(x4Q);
+        x5Q.frob(F,3);
+
+        x4Q.sub(x3Q);
+        x4Q.frob(F,4);
+
+        x3Q.sub(x2Q);
+        x3Q.frob(F,5);
+
+        x2Q.sub(xQ);
+        x2Q.frob(F,6);
+
+        xQ.sub(Q);
+        xQ.frob(F,7);
+
+        Q.dbl();
+        Q.frob(F,8);
+
+        Q.add(x8Q);
+        Q.add(x7Q);
+        Q.add(x6Q);
+        Q.add(x5Q);
+
+        Q.add(x4Q);
+        Q.add(x3Q);
+        Q.add(x2Q);
+        Q.add(xQ);
+
+        Q.affine();
+        return Q;
+    };
+
+    ECP8.frob_constants = function() {
+        var fa = new ctx.BIG(0),
+            fb = new ctx.BIG(0),
+            F=[],
+            X, F0, F1, F2;
+
+        fa.rcopy(ctx.ROM_FIELD.Fra);
+        fb.rcopy(ctx.ROM_FIELD.Frb);
+        X = new ctx.FP2(fa, fb);
+
+        F0=new ctx.FP2(X); F0.sqr();
+        F2=new ctx.FP2(F0);
+        F2.mul_ip(); F2.norm();
+        F1=new ctx.FP2(F2); F1.sqr();
+        F2.mul(F1);
+
+        F2.mul_ip(); F2.norm();
+
+        F1.copy(X);
+        if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) {
+            F1.mul_ip();
+            F1.inverse();
+            F0.copy(F1); F0.sqr();
+        }
+        F0.mul_ip(); F0.norm();
+        F1.mul(F0);
+
+        F[0]=new ctx.FP2(F0); F[1]=new ctx.FP2(F1); F[2]=new ctx.FP2(F2);
+        return F;
+    };
+
+    return ECP8;
+};
diff --git a/version3/js/ff.js b/version3/js/ff.js
new file mode 100644
index 0000000..f7b82a5
--- /dev/null
+++ b/version3/js/ff.js
@@ -0,0 +1,1002 @@
+/*
+    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.
+*/
+
+/* AMCL FF number class */
+
+var FF = function(ctx) {
+    "use strict";
+
+    /* General purpose Constructor */
+    var FF = function(n) {
+        this.v = new Array(n);
+        this.length = n;
+        for (var i = 0; i < n; i++) {
+            this.v[i] = new ctx.BIG(0);
+        }
+    };
+
+    FF.FFLEN = ctx.config["@ML"];
+    FF.P_MBITS = ctx.BIG.MODBYTES * 8;
+    FF.P_OMASK = ((-1) << (FF.P_MBITS % ctx.BIG.BASEBITS));
+    FF.P_FEXCESS = (1 << (ctx.BIG.BASEBITS * ctx.BIG.NLEN - FF.P_MBITS - 1));
+    FF.P_TBITS = (FF.P_MBITS % ctx.BIG.BASEBITS);
+    FF.FF_BITS = (ctx.BIG.BIGBITS * FF.FFLEN);
+    FF.HFLEN = (FF.FFLEN / 2); /* Useful for half-size RSA private key operations */
+
+    FF.prototype = {
+        /* set to zero */
+
+        P_EXCESS: function() {
+            return ((this.v[this.length - 1].get(ctx.BIG.NLEN - 1) & FF.P_OMASK) >> (FF.P_TBITS)) + 1;
+        },
+
+        zero: function() {
+            for (var i = 0; i < this.length; i++) {
+                this.v[i].zero();
+            }
+
+            return this;
+        },
+
+        getlen: function() {
+            return this.length;
+        },
+
+        /* set to integer */
+        set: function(m) {
+            this.zero();
+            this.v[0].set(0, (m & ctx.BIG.BMASK));
+            this.v[0].set(1, (m >> ctx.BIG.BASEBITS));
+        },
+        /* copy from FF b */
+        copy: function(b) {
+            for (var i = 0; i < this.length; i++) {
+                this.v[i].copy(b.v[i]);
+            }
+        },
+        /* copy from FF b */
+        rcopy: function(b) {
+            for (var i = 0; i < this.length; i++) {
+                this.v[i].rcopy(b[i]);
+            }
+        },
+        /* x=y<<n */
+        dsucopy: function(b) {
+            for (var i = 0; i < b.length; i++) {
+                this.v[b.length + i].copy(b.v[i]);
+                this.v[i].zero();
+            }
+        },
+        /* x=y */
+        dscopy: function(b) {
+            for (var i = 0; i < b.length; i++) {
+                this.v[i].copy(b.v[i]);
+                this.v[b.length + i].zero();
+            }
+        },
+
+        /* x=y>>n */
+        sducopy: function(b) {
+            for (var i = 0; i < this.length; i++) {
+                this.v[i].copy(b.v[this.length + i]);
+            }
+        },
+        one: function() {
+            this.v[0].one();
+            for (var i = 1; i < this.length; i++) {
+                this.v[i].zero();
+            }
+        },
+        /* test equals 0 */
+        iszilch: function() {
+            for (var i = 0; i < this.length; i++) {
+                if (!this.v[i].iszilch()) {
+                    return false;
+                }
+            }
+
+            return true;
+        },
+        /* shift right by BIGBITS-bit words */
+        shrw: function(n) {
+            for (var i = 0; i < n; i++) {
+                this.v[i].copy(this.v[i + n]);
+                this.v[i + n].zero();
+            }
+        },
+
+        /* shift left by BIGBITS-bit words */
+        shlw: function(n) {
+            for (var i = 0; i < n; i++) {
+                this.v[n + i].copy(this.v[i]);
+                this.v[i].zero();
+            }
+        },
+        /* extract last bit */
+        parity: function() {
+            return this.v[0].parity();
+        },
+
+        lastbits: function(m) {
+            return this.v[0].lastbits(m);
+        },
+
+        /* recursive add */
+        radd: function(vp, x, xp, y, yp, n) {
+            for (var i = 0; i < n; i++) {
+                this.v[vp + i].copy(x.v[xp + i]);
+                this.v[vp + i].add(y.v[yp + i]);
+            }
+        },
+
+        /* recursive inc */
+        rinc: function(vp, y, yp, n) {
+            for (var i = 0; i < n; i++) {
+                this.v[vp + i].add(y.v[yp + i]);
+            }
+        },
+
+        /* recursive sub */
+        rsub: function(vp, x, xp, y, yp, n) {
+            for (var i = 0; i < n; i++) {
+                this.v[vp + i].copy(x.v[xp + i]);
+                this.v[vp + i].sub(y.v[yp + i]);
+            }
+        },
+
+        /* recursive dec */
+        rdec: function(vp, y, yp, n) {
+            for (var i = 0; i < n; i++) {
+                this.v[vp + i].sub(y.v[yp + i]);
+            }
+        },
+
+        /* simple add */
+        add: function(b) {
+            for (var i = 0; i < this.length; i++) {
+                this.v[i].add(b.v[i]);
+            }
+        },
+
+        /* simple sub */
+        sub: function(b) {
+            for (var i = 0; i < this.length; i++) {
+                this.v[i].sub(b.v[i]);
+            }
+        },
+
+        /* reverse sub */
+        revsub: function(b) {
+            for (var i = 0; i < this.length; i++) {
+                this.v[i].rsub(b.v[i]);
+            }
+        },
+
+        /* increment/decrement by a small integer */
+        inc: function(m) {
+            this.v[0].inc(m);
+            this.norm();
+        },
+
+        dec: function(m) {
+            this.v[0].dec(m);
+            this.norm();
+        },
+
+        /* normalise - but hold any overflow in top part unless n<0 */
+        rnorm: function(vp, n) {
+            var trunc = false,
+                i, carry;
+
+            if (n < 0) { /* -v n signals to do truncation */
+                n = -n;
+                trunc = true;
+            }
+
+            for (i = 0; i < n - 1; i++) {
+                carry = this.v[vp + i].norm();
+                this.v[vp + i].xortop(carry << FF.P_TBITS);
+                this.v[vp + i + 1].inc(carry);
+            }
+            carry = this.v[vp + n - 1].norm();
+
+            if (trunc) {
+                this.v[vp + n - 1].xortop(carry << FF.P_TBITS);
+            }
+
+            return this;
+        },
+
+        norm: function() {
+            this.rnorm(0, this.length);
+        },
+
+        /* shift left by one bit */
+        shl: function() {
+            var delay_carry = 0,
+                i, carry;
+
+            for (i = 0; i < this.length - 1; i++) {
+                carry = this.v[i].fshl(1);
+                this.v[i].inc(delay_carry);
+                this.v[i].xortop(carry << FF.P_TBITS);
+                delay_carry = carry;
+            }
+
+            this.v[this.length - 1].fshl(1);
+            this.v[this.length - 1].inc(delay_carry);
+        },
+
+        /* shift right by one bit */
+        shr: function() {
+            var i, carry;
+
+            for (i = this.length - 1; i > 0; i--) {
+                carry = this.v[i].fshr(1);
+                this.v[i - 1].ortop(carry << FF.P_TBITS);
+            }
+
+            this.v[0].fshr(1);
+        },
+
+        /* Convert to Hex String */
+        toString: function() {
+            var s = "",
+                i;
+
+            this.norm();
+
+            for (i = this.length - 1; i >= 0; i--) {
+                s += this.v[i].toString();
+            }
+
+            return s;
+        },
+        /* Convert FFs to/from byte arrays */
+        toBytes: function(b) {
+            var i;
+
+            for (i = 0; i < this.length; i++) {
+                this.v[i].tobytearray(b, (this.length - i - 1) * ctx.BIG.MODBYTES);
+            }
+        },
+
+        /* z=x*y, t is workspace */
+        karmul: function(vp, x, xp, y, yp, t, tp, n) {
+            var nd2, d;
+
+            if (n === 1) {
+                x.v[xp].norm();
+                y.v[yp].norm();
+                d = ctx.BIG.mul(x.v[xp], y.v[yp]);
+                this.v[vp + 1] = d.split(8 * ctx.BIG.MODBYTES);
+                this.v[vp].copy(d);
+
+                return;
+            }
+
+            nd2 = n / 2;
+            this.radd(vp, x, xp, x, xp + nd2, nd2);
+            this.rnorm(vp, nd2); /* Important - required for 32-bit build */
+            this.radd(vp + nd2, y, yp, y, yp + nd2, nd2);
+            this.rnorm(vp + nd2, nd2); /* Important - required for 32-bit build */
+            t.karmul(tp, this, vp, this, vp + nd2, t, tp + n, nd2);
+            this.karmul(vp, x, xp, y, yp, t, tp + n, nd2);
+            this.karmul(vp + n, x, xp + nd2, y, yp + nd2, t, tp + n, nd2);
+            t.rdec(tp, this, vp, n);
+            t.rdec(tp, this, vp + n, n);
+            this.rinc(vp + nd2, t, tp, n);
+            this.rnorm(vp, 2 * n);
+        },
+
+        karsqr: function(vp, x, xp, t, tp, n) {
+            var nd2, d;
+
+            if (n === 1) {
+                x.v[xp].norm();
+                d = ctx.BIG.sqr(x.v[xp]);
+                this.v[vp + 1].copy(d.split(8 * ctx.BIG.MODBYTES));
+                this.v[vp].copy(d);
+
+                return;
+            }
+
+            nd2 = n / 2;
+            this.karsqr(vp, x, xp, t, tp + n, nd2);
+            this.karsqr(vp + n, x, xp + nd2, t, tp + n, nd2);
+            t.karmul(tp, x, xp, x, xp + nd2, t, tp + n, nd2);
+            this.rinc(vp + nd2, t, tp, n);
+            this.rinc(vp + nd2, t, tp, n);
+            this.rnorm(vp + nd2, n);
+        },
+
+        karmul_lower: function(vp, x, xp, y, yp, t, tp, n) { /* Calculates Least Significant bottom half of x*y */
+            var nd2;
+
+            if (n === 1) { /* only calculate bottom half of product */
+                this.v[vp].copy(ctx.BIG.smul(x.v[xp], y.v[yp]));
+
+                return;
+            }
+
+            nd2 = n / 2;
+
+            this.karmul(vp, x, xp, y, yp, t, tp + n, nd2);
+            t.karmul_lower(tp, x, xp + nd2, y, yp, t, tp + n, nd2);
+            this.rinc(vp + nd2, t, tp, nd2);
+            t.karmul_lower(tp, x, xp, y, yp + nd2, t, tp + n, nd2);
+
+            this.rinc(vp + nd2, t, tp, nd2);
+            this.rnorm(vp + nd2, -nd2); /* truncate it */
+        },
+
+        karmul_upper: function(x, y, t, n) { /* Calculates Most Significant upper half of x*y, given lower part */
+            var nd2;
+
+            nd2 = n / 2;
+            this.radd(n, x, 0, x, nd2, nd2);
+            this.radd(n + nd2, y, 0, y, nd2, nd2);
+            this.rnorm(n, nd2);
+            this.rnorm(n + nd2, nd2);
+
+            t.karmul(0, this, n + nd2, this, n, t, n, nd2); /* t = (a0+a1)(b0+b1) */
+            this.karmul(n, x, nd2, y, nd2, t, n, nd2); /* z[n]= a1*b1 */
+            /* z[0-nd2]=l(a0b0) z[nd2-n]= h(a0b0)+l(t)-l(a0b0)-l(a1b1) */
+            t.rdec(0, this, n, n); /* t=t-a1b1  */
+            this.rinc(nd2, this, 0, nd2); /* z[nd2-n]+=l(a0b0) = h(a0b0)+l(t)-l(a1b1)  */
+            this.rdec(nd2, t, 0, nd2); /* z[nd2-n]=h(a0b0)+l(t)-l(a1b1)-l(t-a1b1)=h(a0b0) */
+            this.rnorm(0, -n); /* a0b0 now in z - truncate it */
+            t.rdec(0, this, 0, n); /* (a0+a1)(b0+b1) - a0b0 */
+            this.rinc(nd2, t, 0, n);
+
+            this.rnorm(nd2, n);
+        },
+
+        /* return low part of product this*y */
+        lmul: function(y) {
+            var n = this.length,
+                t = new FF(2 * n),
+                x = new FF(n);
+
+            x.copy(this);
+            this.karmul_lower(0, x, 0, y, 0, t, 0, n);
+        },
+
+        /* Set b=b mod c */
+        mod: function(c) {
+            var k = 0;
+
+            this.norm();
+            if (FF.comp(this, c) < 0) {
+                return;
+            }
+
+            do {
+                c.shl();
+                k++;
+            } while (FF.comp(this, c) >= 0);
+
+            while (k > 0) {
+                c.shr();
+
+                if (FF.comp(this, c) >= 0) {
+                    this.sub(c);
+                    this.norm();
+                }
+
+                k--;
+            }
+        },
+
+        /* return This mod modulus, N is modulus, ND is Montgomery Constant */
+        reduce: function(N, ND) { /* fast karatsuba Montgomery reduction */
+            var n = N.length,
+                t = new FF(2 * n),
+                r = new FF(n),
+                m = new FF(n);
+
+            r.sducopy(this);
+            m.karmul_lower(0, this, 0, ND, 0, t, 0, n);
+            this.karmul_upper(N, m, t, n);
+            m.sducopy(this);
+
+            r.add(N);
+            r.sub(m);
+            r.norm();
+
+            return r;
+        },
+
+        /* Set r=this mod b */
+        /* this is of length - 2*n */
+        /* r,b is of length - n */
+        dmod: function(b) {
+            var n = b.length,
+                m = new FF(2 * n),
+                x = new FF(2 * n),
+                r = new FF(n),
+                k;
+
+            x.copy(this);
+            x.norm();
+            m.dsucopy(b);
+            k = ctx.BIG.BIGBITS * n;
+
+            while (FF.comp(x, m) >= 0) {
+                x.sub(m);
+                x.norm();
+            }
+
+            while (k > 0) {
+                m.shr();
+
+                if (FF.comp(x, m) >= 0) {
+                    x.sub(m);
+                    x.norm();
+                }
+
+                k--;
+            }
+
+            r.copy(x);
+            r.mod(b);
+
+            return r;
+        },
+
+        /* Set return=1/this mod p. Binary method - a<p on entry */
+        invmodp: function(p) {
+            var n = p.length,
+                u = new FF(n),
+                v = new FF(n),
+                x1 = new FF(n),
+                x2 = new FF(n),
+                t = new FF(n),
+                one = new FF(n);
+
+            one.one();
+            u.copy(this);
+            v.copy(p);
+            x1.copy(one);
+            x2.zero();
+
+            // reduce n in here as well!
+            while (FF.comp(u, one) !== 0 && FF.comp(v, one) !== 0) {
+                while (u.parity() === 0) {
+                    u.shr();
+                    if (x1.parity() !== 0) {
+                        x1.add(p);
+                        x1.norm();
+                    }
+                    x1.shr();
+                }
+
+                while (v.parity() === 0) {
+                    v.shr();
+                    if (x2.parity() !== 0) {
+                        x2.add(p);
+                        x2.norm();
+                    }
+                    x2.shr();
+                }
+
+                if (FF.comp(u, v) >= 0) {
+                    u.sub(v);
+                    u.norm();
+
+                    if (FF.comp(x1, x2) >= 0) {
+                        x1.sub(x2);
+                    } else {
+                        t.copy(p);
+                        t.sub(x2);
+                        x1.add(t);
+                    }
+
+                    x1.norm();
+                } else {
+                    v.sub(u);
+                    v.norm();
+
+                    if (FF.comp(x2, x1) >= 0) {
+                        x2.sub(x1);
+                    } else {
+                        t.copy(p);
+                        t.sub(x1);
+                        x2.add(t);
+                    }
+
+                    x2.norm();
+                }
+            }
+
+            if (FF.comp(u, one) === 0) {
+                this.copy(x1);
+            } else {
+                this.copy(x2);
+            }
+        },
+
+        /* nresidue mod m */
+        nres: function(m) {
+            var n = m.length,
+                d;
+
+            if (n === 1) {
+                d = new ctx.DBIG(0);
+                d.hcopy(this.v[0]);
+                d.shl(ctx.BIG.NLEN * ctx.BIG.BASEBITS);
+                this.v[0].copy(d.mod(m.v[0]));
+            } else {
+                d = new FF(2 * n);
+                d.dsucopy(this);
+                this.copy(d.dmod(m));
+            }
+        },
+
+        redc: function(m, ND) {
+            var n = m.length,
+                d;
+
+            if (n === 1) {
+                d = new ctx.DBIG(0);
+                d.hcopy(this.v[0]);
+                this.v[0].copy(ctx.BIG.monty(m.v[0], (1 << ctx.BIG.BASEBITS) - ND.v[0].w[0], d));
+            } else {
+                d = new FF(2 * n);
+                this.mod(m);
+                d.dscopy(this);
+                this.copy(d.reduce(m, ND));
+                this.mod(m);
+            }
+        },
+
+        mod2m: function(m) {
+            for (var i = m; i < this.length; i++) {
+                this.v[i].zero();
+            }
+        },
+
+        /* U=1/a mod 2^m - Arazi & Qi */
+        invmod2m: function() {
+            var n = this.length,
+                b = new FF(n),
+                c = new FF(n),
+                U = new FF(n),
+                t, i;
+
+            U.zero();
+            U.v[0].copy(this.v[0]);
+            U.v[0].invmod2m();
+
+            for (i = 1; i < n; i <<= 1) {
+                b.copy(this);
+                b.mod2m(i);
+                t = FF.mul(U, b);
+                t.shrw(i);
+                b.copy(t);
+                c.copy(this);
+                c.shrw(i);
+                c.mod2m(i);
+                c.lmul(U);
+                c.mod2m(i);
+
+                b.add(c);
+                b.norm();
+                b.lmul(U);
+                b.mod2m(i);
+
+                c.one();
+                c.shlw(i);
+                b.revsub(c);
+                b.norm();
+                b.shlw(i);
+                U.add(b);
+            }
+            U.norm();
+
+            return U;
+        },
+
+        random: function(rng) {
+            var n = this.length,
+                i;
+
+            for (i = 0; i < n; i++) {
+                this.v[i].copy(ctx.BIG.random(rng));
+            }
+
+            /* make sure top bit is 1 */
+            while (this.v[n - 1].nbits() < ctx.BIG.MODBYTES * 8) {
+                this.v[n - 1].copy(ctx.BIG.random(rng));
+            }
+        },
+
+        /* generate random x */
+        randomnum: function(p, rng) {
+            var n = this.length,
+                d = new FF(2 * n),
+                i;
+
+            for (i = 0; i < 2 * n; i++) {
+                d.v[i].copy(ctx.BIG.random(rng));
+            }
+
+            this.copy(d.dmod(p));
+        },
+
+        /* this*=y mod p */
+        modmul: function(y, p, nd) {
+            var ex = this.P_EXCESS(),
+                ey = y.P_EXCESS(),
+                n = p.length,
+                d;
+
+            if ((ex + 1) >= Math.floor((FF.P_FEXCESS - 1) / (ey + 1))) {
+                this.mod(p);
+            }
+
+            if (n === 1) {
+                d = ctx.BIG.mul(this.v[0], y.v[0]);
+                this.v[0].copy(ctx.BIG.monty(p.v[0], (1 << ctx.BIG.BASEBITS) - nd.v[0].w[0], d));
+            } else {
+                d = FF.mul(this, y);
+                this.copy(d.reduce(p, nd));
+            }
+        },
+
+        /* this*=y mod p */
+        modsqr: function(p, nd) {
+            var ex = this.P_EXCESS(),
+                n, d;
+
+            if ((ex + 1) >= Math.floor((FF.P_FEXCESS - 1) / (ex + 1))) {
+                this.mod(p);
+            }
+            n = p.length;
+
+            if (n === 1) {
+                d = ctx.BIG.sqr(this.v[0]);
+                this.v[0].copy(ctx.BIG.monty(p.v[0], (1 << ctx.BIG.BASEBITS) - nd.v[0].w[0], d));
+            } else {
+                d = FF.sqr(this);
+                this.copy(d.reduce(p, nd));
+            }
+        },
+
+        /* this=this^e mod p using side-channel resistant Montgomery Ladder, for large e */
+        skpow: function(e, p) {
+            var n = p.length,
+                R0 = new FF(n),
+                R1 = new FF(n),
+                ND = p.invmod2m(),
+                i, b;
+
+            this.mod(p);
+            R0.one();
+            R1.copy(this);
+            R0.nres(p);
+            R1.nres(p);
+
+            for (i = 8 * ctx.BIG.MODBYTES * n - 1; i >= 0; i--) {
+                b = e.v[Math.floor(i / ctx.BIG.BIGBITS)].bit(i % ctx.BIG.BIGBITS);
+
+                this.copy(R0);
+                this.modmul(R1, p, ND);
+
+                FF.cswap(R0, R1, b);
+                R0.modsqr(p, ND);
+
+                R1.copy(this);
+                FF.cswap(R0, R1, b);
+            }
+
+            this.copy(R0);
+            this.redc(p, ND);
+        },
+
+        /* this =this^e mod p using side-channel resistant Montgomery Ladder, for short e */
+        skspow: function(e, p) {
+            var n = p.length,
+                R0 = new FF(n),
+                R1 = new FF(n),
+                ND = p.invmod2m(),
+                i, b;
+
+            this.mod(p);
+            R0.one();
+            R1.copy(this);
+            R0.nres(p);
+            R1.nres(p);
+
+            for (i = 8 * ctx.BIG.MODBYTES - 1; i >= 0; i--) {
+                b = e.bit(i);
+                this.copy(R0);
+                this.modmul(R1, p, ND);
+
+                FF.cswap(R0, R1, b);
+                R0.modsqr(p, ND);
+
+                R1.copy(this);
+                FF.cswap(R0, R1, b);
+            }
+            this.copy(R0);
+            this.redc(p, ND);
+        },
+
+        /* raise to an integer power - right-to-left method */
+        power: function(e, p) {
+            var n = p.length,
+                f = true,
+                w = new FF(n),
+                ND = p.invmod2m();
+
+            w.copy(this);
+            w.nres(p);
+
+            if (e == 2) {
+                this.copy(w);
+                this.modsqr(p, ND);
+            } else {
+                for (;;) {
+                    if (e % 2 == 1) {
+                        if (f) {
+                            this.copy(w);
+                        } else {
+                            this.modmul(w, p, ND);
+                        }
+                        f = false;
+                    }
+                    e >>= 1;
+                    if (e === 0) {
+                        break;
+                    }
+                    w.modsqr(p, ND);
+                }
+            }
+
+            this.redc(p, ND);
+        },
+
+        /* this=this^e mod p, faster but not side channel resistant */
+        pow: function(e, p) {
+            var n = p.length,
+                w = new FF(n),
+                ND = p.invmod2m(),
+                i, b;
+
+            w.copy(this);
+            this.one();
+            this.nres(p);
+            w.nres(p);
+
+            for (i = 8 * ctx.BIG.MODBYTES * n - 1; i >= 0; i--) {
+                this.modsqr(p, ND);
+                b = e.v[Math.floor(i / ctx.BIG.BIGBITS)].bit(i % ctx.BIG.BIGBITS);
+                if (b === 1) {
+                    this.modmul(w, p, ND);
+                }
+            }
+
+            this.redc(p, ND);
+        },
+
+        /* double exponentiation r=x^e.y^f mod p */
+        pow2: function(e, y, f, p) {
+            var n = p.length,
+                xn = new FF(n),
+                yn = new FF(n),
+                xy = new FF(n),
+                ND = p.invmod2m(),
+                i, eb, fb;
+
+            xn.copy(this);
+            yn.copy(y);
+            xn.nres(p);
+            yn.nres(p);
+            xy.copy(xn);
+            xy.modmul(yn, p, ND);
+            this.one();
+            this.nres(p);
+
+            for (i = 8 * ctx.BIG.MODBYTES - 1; i >= 0; i--) {
+                eb = e.bit(i);
+                fb = f.bit(i);
+                this.modsqr(p, ND);
+
+                if (eb == 1) {
+                    if (fb == 1) {
+                        this.modmul(xy, p, ND);
+                    } else {
+                        this.modmul(xn, p, ND);
+                    }
+                } else {
+                    if (fb == 1) {
+                        this.modmul(yn, p, ND);
+                    }
+                }
+            }
+            this.redc(p, ND);
+        },
+
+        /* quick and dirty check for common factor with n */
+        cfactor: function(s) {
+            var n = this.length,
+                x = new FF(n),
+                y = new FF(n),
+                r, g;
+
+            y.set(s);
+
+            x.copy(this);
+            x.norm();
+
+            do {
+                x.sub(y);
+                x.norm();
+                while (!x.iszilch() && x.parity() === 0) {
+                    x.shr();
+                }
+            } while (FF.comp(x, y) > 0);
+
+            g = x.v[0].get(0);
+            r = FF.igcd(s, g);
+            if (r > 1) {
+                return true;
+            }
+
+            return false;
+        }
+    };
+
+    /* compare x and y - must be normalised, and of same length */
+    FF.comp = function(a, b) {
+        var i, j;
+
+        for (i = a.length - 1; i >= 0; i--) {
+            j = ctx.BIG.comp(a.v[i], b.v[i]);
+            if (j !== 0) {
+                return j;
+            }
+        }
+
+        return 0;
+    };
+
+    FF.fromBytes = function(x, b) {
+        var i;
+
+        for (i = 0; i < x.length; i++) {
+            x.v[i] = ctx.BIG.frombytearray(b, (x.length - i - 1) * ctx.BIG.MODBYTES);
+        }
+    };
+
+    /* in-place swapping using xor - side channel resistant - lengths must be the same */
+    FF.cswap = function(a, b, d) {
+        var i;
+
+        for (i = 0; i < a.length; i++) {
+            //  ctx.BIG.cswap(a.v[i],b.v[i],d);
+            a.v[i].cswap(b.v[i], d);
+        }
+    };
+
+    /* z=x*y. Assumes x and y are of same length. */
+    FF.mul = function(x, y) {
+        var n = x.length,
+            z = new FF(2 * n),
+            t = new FF(2 * n);
+
+        z.karmul(0, x, 0, y, 0, t, 0, n);
+
+        return z;
+    };
+
+    /* z=x^2 */
+    FF.sqr = function(x) {
+        var n = x.length,
+            z = new FF(2 * n),
+            t = new FF(2 * n);
+
+        z.karsqr(0, x, 0, t, 0, n);
+
+        return z;
+    };
+
+    FF.igcd = function(x, y) { /* integer GCD, returns GCD of x and y */
+        var r;
+
+        if (y === 0) {
+            return x;
+        }
+
+        while ((r = x % y) !== 0) {
+            x = y;
+            y = r;
+        }
+
+        return y;
+    };
+
+    /* Miller-Rabin test for primality. Slow. */
+    FF.prime = function(p, rng) {
+        var n = p.length,
+            s = 0,
+            loop,
+            d = new FF(n),
+            x = new FF(n),
+            unity = new FF(n),
+            nm1 = new FF(n),
+            sf = 4849845, /* 3*5*.. *19 */
+            i, j;
+
+        p.norm();
+
+        if (p.cfactor(sf)) {
+            return false;
+        }
+
+        unity.one();
+        nm1.copy(p);
+        nm1.sub(unity);
+        nm1.norm();
+        d.copy(nm1);
+
+        while (d.parity() === 0) {
+            d.shr();
+            s++;
+        }
+
+        if (s === 0) {
+            return false;
+        }
+
+        for (i = 0; i < 10; i++) {
+            x.randomnum(p, rng);
+            x.pow(d, p);
+
+            if (FF.comp(x, unity) === 0 || FF.comp(x, nm1) === 0) {
+                continue;
+            }
+
+            loop = false;
+
+            for (j = 1; j < s; j++) {
+                x.power(2, p);
+
+                if (FF.comp(x, unity) === 0) {
+                    return false;
+                }
+
+                if (FF.comp(x, nm1) === 0) {
+                    loop = true;
+                    break;
+                }
+            }
+            if (loop) {
+                continue;
+            }
+
+            return false;
+        }
+
+        return true;
+    };
+
+    return FF;
+};
diff --git a/version3/js/fp.js b/version3/js/fp.js
new file mode 100644
index 0000000..8e2026f
--- /dev/null
+++ b/version3/js/fp.js
@@ -0,0 +1,708 @@
+/*
+    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.
+*/
+
+/* Finite Field arithmetic */
+/* AMCL mod p functions */
+
+var FP = function(ctx) {
+    "use strict";
+
+    /* General purpose Constructor */
+    var FP = function(x) {
+        if (x instanceof FP) {
+            this.f = new ctx.BIG(x.f);
+            this.XES = x.XES;
+        } else {
+            this.f = new ctx.BIG(x);
+            this.nres();
+        }
+    };
+
+    FP.NOT_SPECIAL = 0;
+    FP.PSEUDO_MERSENNE = 1;
+    FP.GENERALISED_MERSENNE = 2;
+    FP.MONTGOMERY_FRIENDLY = 3;
+
+    FP.MODBITS = ctx.config["@NBT"];
+    FP.MOD8 = ctx.config["@M8"];
+    FP.MODTYPE = ctx.config["@MT"];
+
+    FP.FEXCESS = ((1 << ctx.config["@SH"])-1); // 2^(BASEBITS*NLEN-MODBITS)-1
+    FP.OMASK = (-1) << FP.TBITS;
+    FP.TBITS = FP.MODBITS % ctx.BIG.BASEBITS;
+    FP.TMASK = (1 << FP.TBITS) - 1;
+
+    FP.prototype = {
+        /* set this=0 */
+        zero: function() {
+            this.XES = 1;
+            this.f.zero();
+        },
+
+        /* copy from a ctx.BIG in ROM */
+        rcopy: function(y) {
+            this.f.rcopy(y);
+            this.nres();
+        },
+
+        /* copy from another ctx.BIG */
+        bcopy: function(y) {
+            this.f.copy(y);
+            this.nres();
+            //alert("4. f= "+this.f.toString());
+        },
+
+        /* copy from another FP */
+        copy: function(y) {
+            this.XES = y.XES;
+            this.f.copy(y.f);
+        },
+
+        /* conditional swap of a and b depending on d */
+        cswap: function(b, d) {
+            this.f.cswap(b.f, d);
+            var t, c = d;
+            c = ~(c - 1);
+            t = c & (this.XES ^ b.XES);
+            this.XES ^= t;
+            b.XES ^= t;
+        },
+
+        /* conditional copy of b to a depending on d */
+        cmove: function(b, d) {
+            var c = d;
+
+            c = ~(c - 1);
+
+            this.f.cmove(b.f, d);
+            this.XES ^= (this.XES ^ b.XES) & c;
+        },
+
+        /* convert to Montgomery n-residue form */
+        nres: function() {
+            var r, d;
+
+            if (FP.MODTYPE != FP.PSEUDO_MERSENNE && FP.MODTYPE != FP.GENERALISED_MERSENNE) {
+                r = new ctx.BIG();
+                r.rcopy(ctx.ROM_FIELD.R2modp);
+
+                d = ctx.BIG.mul(this.f, r);
+                this.f.copy(FP.mod(d));
+                this.XES = 2;
+            } else {
+                this.XES = 1;
+            }
+
+            return this;
+        },
+
+        /* convert back to regular form */
+        redc: function() {
+            var r = new ctx.BIG(0),
+                d, w;
+
+            r.copy(this.f);
+
+            if (FP.MODTYPE != FP.PSEUDO_MERSENNE && FP.MODTYPE != FP.GENERALISED_MERSENNE) {
+                d = new ctx.DBIG(0);
+                d.hcopy(this.f);
+                w = FP.mod(d);
+                r.copy(w);
+            }
+
+            return r;
+        },
+
+        /* convert this to string */
+        toString: function() {
+            var s = this.redc().toString();
+            return s;
+        },
+
+        /* test this=0 */
+        iszilch: function() {
+			var c=new FP(0); c.copy(this);
+            c.reduce();
+            return c.f.iszilch();
+        },
+
+        /* reduce this mod Modulus */
+        reduce: function() {
+            var q,carry,sr,sb,m = new ctx.BIG(0);
+            m.rcopy(ctx.ROM_FIELD.Modulus);
+			var r = new ctx.BIG(0);
+            r.rcopy(ctx.ROM_FIELD.Modulus);
+			this.f.norm();
+
+			if (this.XES>16)
+			{
+				q=FP.quo(this.f,m);
+				carry=r.pmul(q);
+				r.w[ctx.BIG.NLEN-1]+=(carry<<ctx.BIG.BASEBITS); // correction - put any carry out back in again
+				this.f.sub(r);
+				this.f.norm();
+				sb=2;
+			}
+			else {
+					sb=FP.logb2(this.XES-1);
+			}
+			m.fshl(sb);
+
+			while (sb>0)
+			{
+// constant time...
+				sr=ctx.BIG.ssn(r,this.f,m);  // optimized combined shift, subtract and norm
+				this.f.cmove(r,1-sr);
+				sb--;
+			}			
+/*
+    m.rcopy(ctx.ROM_FIELD.Modulus);
+	if (ctx.BIG.comp(this.f,m)>0)
+	{
+		alert("NOT fully reduced q= "+q+" carry= "+carry+" XES= "+this.XES+" FEXCESS= "+FP.FEXCESS+ " quo= "+FP.quo(this.f,m)+" FP.TBITS= "+FP.TBITS);
+	}
+*/
+
+            this.XES = 1;
+        },
+
+        /* set this=1 */
+        one: function() {
+            this.f.one();
+            return this.nres();
+        },
+
+        /* normalise this */
+        norm: function() {
+            return this.f.norm();
+        },
+
+        /* this*=b mod Modulus */
+        mul: function(b) {
+            var d;
+
+            if (this.XES * b.XES > FP.FEXCESS) {
+                this.reduce();
+            }
+
+            d = ctx.BIG.mul(this.f, b.f);
+            this.f.copy(FP.mod(d));
+            this.XES = 2;
+
+            return this;
+        },
+
+        /* this*=c mod Modulus where c is an int */
+        imul: function(c) {
+            var s = false,
+                d, n;
+
+            //this.norm();
+            if (c < 0) {
+                c = -c;
+                s = true;
+            }
+
+            if (FP.MODTYPE == FP.PSEUDO_MERSENNE || FP.MODTYPE == FP.GENERALISED_MERSENNE) {
+                d = this.f.pxmul(c);
+                this.f.copy(FP.mod(d));
+                this.XES = 2;
+            } else {
+                if (this.XES * c <= FP.FEXCESS) {
+                    this.f.pmul(c);
+                    this.XES *= c;
+                } else {
+                    n = new FP(c);
+                    this.mul(n);
+                }
+            }
+
+            /*
+                    if (c<=ctx.BIG.NEXCESS && this.XES*c<=FP.FEXCESS)
+                    {
+                        this.f.imul(c);
+                        this.XES*=c;
+                        this.norm();
+                    }
+                    else
+                    {
+            //          var p=new ctx.BIG(0);
+            //          p.rcopy(ctx.ROM_FIELD.Modulus);
+                        var d=this.f.pxmul(c);
+                        this.f.copy(FP.mod(d));
+                    }
+            */
+            if (s) {
+                this.neg();
+                this.norm();
+            }
+            return this;
+        },
+
+        /* this*=this mod Modulus */
+        sqr: function() {
+            var d, t;
+
+            if (this.XES * this.XES > FP.FEXCESS) {
+                this.reduce();
+            }
+            //if ((ea+1)>= Math.floor((FP.FEXCESS-1)/(ea+1))) this.reduce();
+
+            d = ctx.BIG.sqr(this.f);
+            t = FP.mod(d);
+            this.f.copy(t);
+            this.XES = 2;
+
+            return this;
+        },
+
+        /* this+=b */
+        add: function(b) {
+            this.f.add(b.f);
+            this.XES += b.XES;
+
+            if (this.XES > FP.FEXCESS) {
+                this.reduce();
+            }
+
+            return this;
+        },
+        /* this=-this mod Modulus */
+        neg: function() {
+            var m = new ctx.BIG(0),
+                sb;
+
+            m.rcopy(ctx.ROM_FIELD.Modulus);
+
+            sb = FP.logb2(this.XES - 1);
+
+            m.fshl(sb);
+            this.XES = (1 << sb)+1;
+            this.f.rsub(m);
+
+            if (this.XES > FP.FEXCESS) {
+                this.reduce();
+            }
+
+            return this;
+        },
+
+        /* this-=b */
+        sub: function(b) {
+            var n = new FP(0);
+
+            n.copy(b);
+            n.neg();
+            this.add(n);
+
+            return this;
+        },
+
+        rsub: function(b) {
+            var n = new FP(0);
+
+            n.copy(this);
+            n.neg();
+            this.copy(b);
+            this.add(n);
+        },
+
+        /* this/=2 mod Modulus */
+        div2: function() {
+            var p;
+
+            if (this.f.parity() === 0) {
+                this.f.fshr(1);
+            } else {
+                p = new ctx.BIG(0);
+                p.rcopy(ctx.ROM_FIELD.Modulus);
+
+                this.f.add(p);
+                this.f.norm();
+                this.f.fshr(1);
+            }
+
+            return this;
+        },
+
+// return this^(p-3)/4 or this^(p-5)/8
+// See https://eprint.iacr.org/2018/1038
+		fpow: function() {
+			var i,j,k,bw,w,c,nw,lo,m,n;
+			var xp=[];
+			var ac=[1,2,3,6,12,15,30,60,120,240,255];
+// phase 1
+			
+			xp[0]=new FP(this);	// 1 
+			xp[1]=new FP(this); xp[1].sqr(); // 2
+			xp[2]=new FP(xp[1]); xp[2].mul(this);  //3
+			xp[3]=new FP(xp[2]); xp[3].sqr();  // 6 
+			xp[4]=new FP(xp[3]); xp[4].sqr();  // 12
+			xp[5]=new FP(xp[4]); xp[5].mul(xp[2]);  // 15
+			xp[6]=new FP(xp[5]); xp[6].sqr();  // 30
+			xp[7]=new FP(xp[6]); xp[7].sqr();  // 60
+			xp[8]=new FP(xp[7]); xp[8].sqr();  // 120
+			xp[9]=new FP(xp[8]); xp[9].sqr();  // 240
+			xp[10]=new FP(xp[9]); xp[10].mul(xp[5]);  // 255		
+			
+			if (FP.MOD8==5)
+			{
+				n=FP.MODBITS-3;
+				c=(ctx.ROM_FIELD.MConst+5)/8;
+			} else {
+				n=FP.MODBITS-2;
+				c=(ctx.ROM_FIELD.MConst+3)/4;
+			}
+
+			bw=0; w=1; while (w<c) {w*=2; bw+=1;}
+			k=w-c;
+
+			i=10; var key=new FP(0);
+			if (k!=0)
+			{
+				while (ac[i]>k) i--;
+				key.copy(xp[i]); 
+				k-=ac[i];
+			}
+			while (k!=0)
+			{
+				i--;
+				if (ac[i]>k) continue;
+				key.mul(xp[i]);
+				k-=ac[i]; 
+			}
+
+// phase 2 
+			xp[1].copy(xp[2]);
+			xp[2].copy(xp[5]);
+			xp[3].copy(xp[10]);
+	
+			j=3; m=8;
+			nw=n-bw;
+			var t=new FP(0);
+			while (2*m<nw)
+			{
+				t.copy(xp[j++]);
+				for (i=0;i<m;i++)
+					t.sqr(); 
+				xp[j].copy(xp[j-1]);
+				xp[j].mul(t);
+				m*=2;
+			}
+			lo=nw-m;
+			var r=new FP(xp[j]);
+
+			while (lo!=0)
+			{
+				m/=2; j--;
+				if (lo<m) continue;
+				lo-=m;
+				t.copy(r);
+				for (i=0;i<m;i++)
+					t.sqr();
+				r.copy(t);
+				r.mul(xp[j]);
+			}
+
+// phase 3
+			for (i=0;i<bw;i++ )
+				r.sqr();
+
+			if (w-c!=0)
+				r.mul(key); 
+			return r;
+		},
+
+        /* this=1/this mod Modulus */
+        inverse: function() {
+
+			if (FP.MODTYPE == FP.PSEUDO_MERSENNE)
+			{
+				var y=this.fpow();
+				if (FP.MOD8==5)
+				{
+					var t=new FP(this);
+					t.sqr();
+					this.mul(t);
+					y.sqr();
+
+				} 
+				y.sqr();
+				y.sqr();
+				this.mul(y);
+				return this;
+			} else {
+				var m2=new ctx.BIG(0);
+				m2.rcopy(ctx.ROM_FIELD.Modulus);
+				m2.dec(2); m2.norm();
+				this.copy(this.pow(m2));
+				return this;
+			}
+        },
+
+        /* return TRUE if this==a */
+        equals: function(a) {
+			var ft=new FP(0); ft.copy(this);
+			var sd=new FP(0); sd.copy(a);
+            ft.reduce();
+            sd.reduce();
+
+            if (ctx.BIG.comp(ft.f, sd.f) === 0) {
+                return true;
+            }
+
+            return false;
+        },
+
+        /* return this^e mod Modulus */
+        pow: function(e) {
+            var i,w=[],
+                tb=[],
+                t=new ctx.BIG(e),
+                nb, lsbs, r;
+
+            t.norm();
+            nb= 1 + Math.floor((t.nbits() + 3) / 4);
+
+            for (i=0;i<nb;i++) {
+                lsbs=t.lastbits(4);
+                t.dec(lsbs);
+                t.norm();
+                w[i]=lsbs;
+                t.fshr(4);
+            }
+            tb[0]=new FP(1);
+            tb[1]=new FP(this);
+            for (i=2;i<16;i++) {
+                tb[i]=new FP(tb[i-1]);
+                tb[i].mul(this);
+            }
+            r=new FP(tb[w[nb-1]]);
+            for (i=nb-2;i>=0;i--) {
+                r.sqr();
+                r.sqr();
+                r.sqr();
+                r.sqr();
+                r.mul(tb[w[i]]);
+            }
+            r.reduce();
+            return r;
+        },
+
+        /* return this^e mod Modulus
+        pow: function(e) {
+            var bt,
+                r = new FP(1),
+                m = new FP(0);
+
+            e.norm();
+            this.norm();
+            m.copy(this);
+
+            for (;;) {
+                bt = e.parity();
+                e.fshr(1);
+
+                if (bt == 1) {
+                    r.mul(m);
+                }
+
+                if (e.iszilch()) {
+                    break;
+                }
+
+                m.sqr();
+            }
+
+            r.reduce();
+
+            return r;
+        }, */
+
+        /* return jacobi symbol (this/Modulus) */
+        jacobi: function() {
+            var p = new ctx.BIG(0),
+                w = this.redc();
+
+            p.rcopy(ctx.ROM_FIELD.Modulus);
+
+            return w.jacobi(p);
+        },
+
+        /* return sqrt(this) mod Modulus */
+        sqrt: function() {
+            var i, v, r;
+
+            this.reduce();
+            if (FP.MOD8 == 5) {
+                i = new FP(0);
+                i.copy(this);
+                i.f.shl(1);
+				if (FP.MODTYPE == FP.PSEUDO_MERSENNE) {
+					v=i.fpow();
+				} else {
+					var b = new ctx.BIG(0);
+					b.rcopy(ctx.ROM_FIELD.Modulus);
+					b.dec(5);
+					b.norm();
+					b.shr(3);
+					v = i.pow(b);
+				}
+                i.mul(v);
+                i.mul(v);
+                i.f.dec(1);
+                r = new FP(0);
+                r.copy(this);
+                r.mul(v);
+                r.mul(i);
+                r.reduce();
+
+                return r;
+            } else {
+				if (FP.MODTYPE == FP.PSEUDO_MERSENNE) {
+					var r=this.fpow();
+					r.mul(this);
+					return r;
+				} else {
+					var b = new ctx.BIG(0);
+					b.rcopy(ctx.ROM_FIELD.Modulus);
+					b.inc(1);
+					b.norm();
+					b.shr(2);
+					return this.pow(b);
+				}
+            }
+        }
+
+    };
+
+    FP.logb2 = function(v) {
+        var r;
+
+        v |= v >>> 1;
+        v |= v >>> 2;
+        v |= v >>> 4;
+        v |= v >>> 8;
+        v |= v >>> 16;
+
+        v = v - ((v >>> 1) & 0x55555555);
+        v = (v & 0x33333333) + ((v >>> 2) & 0x33333333);
+        r = ((v + (v >>> 4) & 0xF0F0F0F) * 0x1010101) >>> 24;
+
+        return r;
+    };
+
+	FP.quo = function(n,m) {
+		var num,den,hb=ctx.BIG.CHUNK>>1;
+		if (FP.TBITS<hb)
+		{
+			var sh=hb-FP.TBITS;
+			num=(n.w[ctx.BIG.NLEN-1]<<sh)|(n.w[ctx.BIG.NLEN-2]>>(ctx.BIG.BASEBITS-sh));
+			den=(m.w[ctx.BIG.NLEN-1]<<sh)|(m.w[ctx.BIG.NLEN-2]>>(ctx.BIG.BASEBITS-sh));
+		} else {
+			num=n.w[ctx.BIG.NLEN-1];
+			den=m.w[ctx.BIG.NLEN-1];			
+		}
+		return Math.floor(num/(den+1))
+	};
+
+    /* calculate Field Excess
+    FP.EXCESS=function(a)
+    {
+        return ((a.w[ctx.BIG.NLEN-1]&FP.OMASK)>>(FP.MODBITS%ctx.BIG.BASEBITS))+1;
+    };
+    */
+
+    /* reduce a ctx.DBIG to a ctx.BIG using a "special" modulus */
+    FP.mod = function(d) {
+        var b = new ctx.BIG(0),
+            i, t, v, tw, tt, lo, carry, m, dd;
+
+        if (FP.MODTYPE == FP.PSEUDO_MERSENNE) {
+            t = d.split(FP.MODBITS);
+            b.hcopy(d);
+
+            if (ctx.ROM_FIELD.MConst != 1) {
+                v = t.pmul(ctx.ROM_FIELD.MConst);
+            } else {
+                v = 0;
+            }
+
+            t.add(b);
+            t.norm();
+
+            tw = t.w[ctx.BIG.NLEN - 1];
+            t.w[ctx.BIG.NLEN - 1] &= FP.TMASK;
+            t.inc(ctx.ROM_FIELD.MConst * ((tw >> FP.TBITS) + (v << (ctx.BIG.BASEBITS - FP.TBITS))));
+            //      b.add(t);
+            t.norm();
+
+            return t;
+        }
+
+        if (FP.MODTYPE == FP.MONTGOMERY_FRIENDLY) {
+            for (i = 0; i < ctx.BIG.NLEN; i++) {
+                d.w[ctx.BIG.NLEN + i] += d.muladd(d.w[i], ctx.ROM_FIELD.MConst - 1, d.w[i], ctx.BIG.NLEN + i - 1);
+            }
+
+            for (i = 0; i < ctx.BIG.NLEN; i++) {
+                b.w[i] = d.w[ctx.BIG.NLEN + i];
+            }
+
+            b.norm();
+        }
+
+        if (FP.MODTYPE == FP.GENERALISED_MERSENNE) { // GoldiLocks Only
+            t = d.split(FP.MODBITS);
+            b.hcopy(d);
+            b.add(t);
+            dd = new ctx.DBIG(0);
+            dd.hcopy(t);
+            dd.shl(FP.MODBITS / 2);
+
+            tt = dd.split(FP.MODBITS);
+            lo = new ctx.BIG();
+            lo.hcopy(dd);
+
+            b.add(tt);
+            b.add(lo);
+            //b.norm();
+            tt.shl(FP.MODBITS / 2);
+            b.add(tt);
+
+            carry = b.w[ctx.BIG.NLEN - 1] >> FP.TBITS;
+            b.w[ctx.BIG.NLEN - 1] &= FP.TMASK;
+            b.w[0] += carry;
+
+            b.w[Math.floor(224 / ctx.BIG.BASEBITS)] += carry << (224 % ctx.BIG.BASEBITS);
+            b.norm();
+        }
+
+        if (FP.MODTYPE == FP.NOT_SPECIAL) {
+            m = new ctx.BIG(0);
+            m.rcopy(ctx.ROM_FIELD.Modulus);
+
+            b.copy(ctx.BIG.monty(m, ctx.ROM_FIELD.MConst, d));
+        }
+
+        return b;
+    };
+
+    return FP;
+};
diff --git a/version3/js/fp12.js b/version3/js/fp12.js
new file mode 100644
index 0000000..4c6078f
--- /dev/null
+++ b/version3/js/fp12.js
@@ -0,0 +1,893 @@
+/*
+    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.
+*/
+
+/* AMCL Fp^12 functions */
+
+/* FP12 elements are of the form a+i.b+i^2.c */
+
+var FP12 = function(ctx) {
+    "use strict";
+
+    /* general purpose constructor */
+    var FP12 = function(d, e, f) {
+        if (d instanceof FP12) {
+            this.a = new ctx.FP4(d.a);
+            this.b = new ctx.FP4(d.b);
+            this.c = new ctx.FP4(d.c);
+        } else {
+            this.a = new ctx.FP4(d);
+            this.b = new ctx.FP4(e);
+            this.c = new ctx.FP4(f);
+        }
+    };
+
+    FP12.prototype = {
+        /* reduce all components of this mod Modulus */
+        reduce: function() {
+            this.a.reduce();
+            this.b.reduce();
+            this.c.reduce();
+        },
+
+        /* normalize all components of this mod Modulus */
+        norm: function() {
+            this.a.norm();
+            this.b.norm();
+            this.c.norm();
+        },
+
+        /* test x==0 ? */
+        iszilch: function() {
+            //this.reduce();
+            return (this.a.iszilch() && this.b.iszilch() && this.c.iszilch());
+        },
+
+        /* test x==1 ? */
+        isunity: function() {
+            var one = new ctx.FP4(1);
+            return (this.a.equals(one) && this.b.iszilch() && this.c.iszilch());
+        },
+
+
+        /* conditional copy of g to this depending on d */
+        cmove: function(g, d) {
+            this.a.cmove(g.a, d);
+            this.b.cmove(g.b, d);
+            this.c.cmove(g.c, d);
+        },
+
+
+        /* Constant time select from pre-computed table */
+        select: function(g, b) {
+            var invf = new FP12(0),
+                m, babs;
+
+            m = b >> 31;
+            babs = (b ^ m) - m;
+            babs = (babs - 1) / 2;
+
+            this.cmove(g[0], FP12.teq(babs, 0)); // conditional move
+            this.cmove(g[1], FP12.teq(babs, 1));
+            this.cmove(g[2], FP12.teq(babs, 2));
+            this.cmove(g[3], FP12.teq(babs, 3));
+            this.cmove(g[4], FP12.teq(babs, 4));
+            this.cmove(g[5], FP12.teq(babs, 5));
+            this.cmove(g[6], FP12.teq(babs, 6));
+            this.cmove(g[7], FP12.teq(babs, 7));
+
+            invf.copy(this);
+            invf.conj();
+            this.cmove(invf, (m & 1));
+        },
+
+        /* extract a from this */
+        geta: function() {
+            return this.a;
+        },
+
+        /* extract b */
+        getb: function() {
+            return this.b;
+        },
+
+        /* extract c */
+        getc: function() {
+            return this.c;
+        },
+
+        /* return 1 if x==y, else 0 */
+        equals: function(x) {
+            return (this.a.equals(x.a) && this.b.equals(x.b) && this.c.equals(x.c));
+        },
+
+        /* copy this=x */
+        copy: function(x) {
+            this.a.copy(x.a);
+            this.b.copy(x.b);
+            this.c.copy(x.c);
+        },
+
+        /* set this=1 */
+        one: function() {
+            this.a.one();
+            this.b.zero();
+            this.c.zero();
+        },
+
+        /* this=conj(this) */
+        conj: function() {
+            this.a.conj();
+            this.b.nconj();
+            this.c.conj();
+        },
+
+        /* set this from 3 FP4s */
+        set: function(d, e, f) {
+            this.a.copy(d);
+            this.b.copy(e);
+            this.c.copy(f);
+        },
+
+        /* set this from one ctx.FP4 */
+        seta: function(d) {
+            this.a.copy(d);
+            this.b.zero();
+            this.c.zero();
+        },
+
+        /* Granger-Scott Unitary Squaring */
+        usqr: function() {
+            var A = new ctx.FP4(this.a), //A.copy(this.a)
+                B = new ctx.FP4(this.c), //B.copy(this.c)
+                C = new ctx.FP4(this.b), //C.copy(this.b)
+                D = new ctx.FP4(0);
+
+            this.a.sqr();
+            D.copy(this.a);
+            D.add(this.a);
+            this.a.add(D);
+
+            A.nconj();
+
+            A.add(A);
+            this.a.add(A);
+            B.sqr();
+            B.times_i();
+
+            D.copy(B);
+            D.add(B);
+            B.add(D);
+
+            C.sqr();
+            D.copy(C);
+            D.add(C);
+            C.add(D);
+
+            this.b.conj();
+            this.b.add(this.b);
+            this.c.nconj();
+
+            this.c.add(this.c);
+            this.b.add(B);
+            this.c.add(C);
+            this.reduce();
+        },
+
+        /* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
+        sqr: function() {
+            var A = new ctx.FP4(this.a), //A.copy(this.a)
+                B = new ctx.FP4(this.b), //B.copy(this.b)
+                C = new ctx.FP4(this.c), //C.copy(this.c)
+                D = new ctx.FP4(this.a); //D.copy(this.a)
+
+            A.sqr();
+            B.mul(this.c);
+            B.add(B); //B.norm();
+            C.sqr();
+            D.mul(this.b);
+            D.add(D);
+
+            this.c.add(this.a);
+            this.c.add(this.b);
+            this.c.norm();
+            this.c.sqr();
+
+            this.a.copy(A);
+
+            A.add(B);
+            A.add(C);
+            A.add(D);
+            A.neg();
+            B.times_i();
+            C.times_i();
+
+            this.a.add(B);
+            this.b.copy(C);
+            this.b.add(D);
+            this.c.add(A);
+
+            this.norm();
+        },
+
+        /* FP12 full multiplication this=this*y */
+        mul: function(y) {
+            var z0 = new ctx.FP4(this.a), //z0.copy(this.a)
+                z1 = new ctx.FP4(0),
+                z2 = new ctx.FP4(this.b), //z2.copy(this.b)
+                z3 = new ctx.FP4(0),
+                t0 = new ctx.FP4(this.a), //t0.copy(this.a)
+                t1 = new ctx.FP4(y.a); //t1.copy(y.a)
+
+            z0.mul(y.a);
+            z2.mul(y.b);
+
+            t0.add(this.b);
+            t1.add(y.b);
+
+            t0.norm();
+            t1.norm();
+
+            z1.copy(t0);
+            z1.mul(t1);
+            t0.copy(this.b);
+            t0.add(this.c);
+
+            t1.copy(y.b);
+            t1.add(y.c);
+
+            t0.norm();
+            t1.norm();
+            z3.copy(t0);
+            z3.mul(t1);
+
+            t0.copy(z0);
+            t0.neg();
+            t1.copy(z2);
+            t1.neg();
+
+            z1.add(t0);
+            this.b.copy(z1);
+            this.b.add(t1);
+
+            z3.add(t1);
+            z2.add(t0);
+
+            t0.copy(this.a);
+            t0.add(this.c);
+            t1.copy(y.a);
+            t1.add(y.c);
+
+            t0.norm();
+            t1.norm();
+
+            t0.mul(t1);
+            z2.add(t0);
+
+            t0.copy(this.c);
+            t0.mul(y.c);
+            t1.copy(t0);
+            t1.neg();
+
+            this.c.copy(z2);
+            this.c.add(t1);
+            z3.add(t1);
+            t0.times_i();
+            this.b.add(t0);
+            // z3.norm();
+            z3.times_i();
+            this.a.copy(z0);
+            this.a.add(z3);
+
+            this.norm();
+        },
+
+        /* Special case this*=y that arises from special form of ATE pairing line function */
+        smul: function(y, twist) {
+            var z0, z1, z2, z3, t0, t1;
+
+            if (twist == ctx.ECP.D_TYPE) {
+
+                z0 = new ctx.FP4(this.a); //z0.copy(this.a);
+                z2 = new ctx.FP4(this.b); //z2.copy(this.b);
+                z3 = new ctx.FP4(this.b); //z3.copy(this.b);
+                t0 = new ctx.FP4(0);
+                t1 = new ctx.FP4(y.a); //t1.copy(y.a);
+
+                z0.mul(y.a);
+                z2.pmul(y.b.real());
+                this.b.add(this.a);
+                t1.real().add(y.b.real());
+
+                this.b.norm();
+                t1.norm();
+
+                this.b.mul(t1);
+                z3.add(this.c);
+                z3.norm();
+                z3.pmul(y.b.real());
+
+                t0.copy(z0);
+                t0.neg();
+                t1.copy(z2);
+                t1.neg();
+
+                this.b.add(t0);
+
+                this.b.add(t1);
+                z3.add(t1);
+                z2.add(t0);
+
+                t0.copy(this.a);
+                t0.add(this.c);
+                t0.norm();
+                t0.mul(y.a);
+                this.c.copy(z2);
+                this.c.add(t0);
+
+                z3.times_i();
+                this.a.copy(z0);
+                this.a.add(z3);
+            }
+
+            if (twist == ctx.ECP.M_TYPE) {
+                z0=new ctx.FP4(this.a);
+                z1=new ctx.FP4(0);
+                z2=new ctx.FP4(0);
+                z3=new ctx.FP4(0);
+                t0=new ctx.FP4(this.a);
+                t1=new ctx.FP4(0);
+
+                z0.mul(y.a);
+                t0.add(this.b);
+                t0.norm();
+
+                z1.copy(t0); z1.mul(y.a);
+                t0.copy(this.b); t0.add(this.c);
+                t0.norm();
+
+                z3.copy(t0); //z3.mul(y.c);
+                z3.pmul(y.c.getb());
+                z3.times_i();
+
+                t0.copy(z0); t0.neg();
+
+                z1.add(t0);
+                this.b.copy(z1);
+                z2.copy(t0);
+
+                t0.copy(this.a); t0.add(this.c);
+                t1.copy(y.a); t1.add(y.c);
+
+                t0.norm();
+                t1.norm();
+
+                t0.mul(t1);
+                z2.add(t0);
+
+                t0.copy(this.c);
+
+                t0.pmul(y.c.getb());
+                t0.times_i();
+
+                t1.copy(t0); t1.neg();
+
+                this.c.copy(z2); this.c.add(t1);
+                z3.add(t1);
+                t0.times_i();
+                this.b.add(t0);
+                z3.norm();
+                z3.times_i();
+                this.a.copy(z0); this.a.add(z3);
+            }
+
+            this.norm();
+        },
+
+        /* this=1/this */
+        inverse: function() {
+            var f0 = new ctx.FP4(this.a), //f0.copy(this.a)
+                f1 = new ctx.FP4(this.b), //f1.copy(this.b)
+                f2 = new ctx.FP4(this.a), //f2.copy(this.a)
+                f3 = new ctx.FP4(0);
+
+            f0.sqr();
+            f1.mul(this.c);
+            f1.times_i();
+            f0.sub(f1);
+            f0.norm();
+
+            f1.copy(this.c);
+            f1.sqr();
+            f1.times_i();
+            f2.mul(this.b);
+            f1.sub(f2);
+            f1.norm();
+
+            f2.copy(this.b);
+            f2.sqr();
+            f3.copy(this.a);
+            f3.mul(this.c);
+            f2.sub(f3);
+            f2.norm();
+
+            f3.copy(this.b);
+            f3.mul(f2);
+            f3.times_i();
+            this.a.mul(f0);
+            f3.add(this.a);
+            this.c.mul(f1);
+            this.c.times_i();
+
+            f3.add(this.c);
+            f3.norm();
+            f3.inverse();
+            this.a.copy(f0);
+            this.a.mul(f3);
+            this.b.copy(f1);
+            this.b.mul(f3);
+            this.c.copy(f2);
+            this.c.mul(f3);
+        },
+
+        /* this=this^p, where p=Modulus, using Frobenius */
+        frob: function(f) {
+            var f2 = new ctx.FP2(f),
+                f3 = new ctx.FP2(f);
+
+            f2.sqr();
+            f3.mul(f2);
+
+            this.a.frob(f3);
+            this.b.frob(f3);
+            this.c.frob(f3);
+
+            this.b.pmul(f);
+            this.c.pmul(f2);
+        },
+
+        /* trace function */
+        trace: function() {
+            var t = new ctx.FP4(0);
+
+            t.copy(this.a);
+            t.imul(3);
+            t.reduce();
+
+            return t;
+        },
+
+        /* convert this to hex string */
+        toString: function() {
+            return ("[" + this.a.toString() + "," + this.b.toString() + "," + this.c.toString() + "]");
+        },
+
+        /* convert this to byte array */
+        toBytes: function(w) {
+            var t = [],
+                i;
+
+            this.a.geta().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i] = t[i];
+            }
+            this.a.geta().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + ctx.BIG.MODBYTES] = t[i];
+            }
+            this.a.getb().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 2 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.a.getb().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 3 * ctx.BIG.MODBYTES] = t[i];
+            }
+
+            this.b.geta().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 4 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.b.geta().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 5 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.b.getb().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 6 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.b.getb().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 7 * ctx.BIG.MODBYTES] = t[i];
+            }
+
+            this.c.geta().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 8 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.c.geta().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 9 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.c.getb().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 10 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.c.getb().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 11 * ctx.BIG.MODBYTES] = t[i];
+            }
+        },
+
+        /* set this=this^e */
+        pow: function(e) {
+            var e1, e3, w, nb, i, bt, sf;
+			e1 = new ctx.BIG(e);
+			e1.norm();
+            e3 = new ctx.BIG(e1);
+            e3.pmul(3);
+            e3.norm();
+
+			sf = new FP12(this);
+			sf.norm();
+            w = new FP12(sf); //w.copy(this);
+            nb = e3.nbits();
+
+            for (i = nb - 2; i >= 1; i--) {
+                w.usqr();
+                bt = e3.bit(i) - e1.bit(i);
+
+                if (bt == 1) {
+                    w.mul(sf);
+                }
+                if (bt == -1) {
+                    sf.conj();
+                    w.mul(sf);
+                    sf.conj();
+                }
+            }
+            w.reduce();
+
+            return w;
+        },
+
+        /* constant time powering by small integer of max length bts */
+        pinpow: function(e, bts) {
+            var R = [],
+                i, b;
+
+            R[0] = new FP12(1);
+            R[1] = new FP12(this);
+
+            for (i = bts - 1; i >= 0; i--) {
+                b = (e >> i) & 1;
+                R[1 - b].mul(R[b]);
+                R[b].usqr();
+            }
+
+            this.copy(R[0]);
+        },
+
+        /* Faster compressed powering for unitary elements */
+        compow: function(e, r) {
+            var fa, fb, f, q, m, a, b, g1, g2, c, cp, cpm1, cpm2;
+
+            fa = new ctx.BIG(0);
+            fa.rcopy(ctx.ROM_FIELD.Fra);
+            fb = new ctx.BIG(0);
+            fb.rcopy(ctx.ROM_FIELD.Frb);
+            f = new ctx.FP2(fa, fb);
+
+            q = new ctx.BIG(0);
+            q.rcopy(ctx.ROM_FIELD.Modulus);
+
+            m = new ctx.BIG(q);
+            m.mod(r);
+
+            a = new ctx.BIG(e);
+            a.mod(m);
+
+            b = new ctx.BIG(e);
+            b.div(m);
+
+            g1 = new FP12(0);
+            g2 = new FP12(0);
+            g1.copy(this);
+
+            c = g1.trace();
+
+            if (b.iszilch()) {
+                c=c.xtr_pow(e);
+                return c;
+            }
+
+            g2.copy(g1);
+            g2.frob(f);
+            cp = g2.trace();
+            g1.conj();
+            g2.mul(g1);
+            cpm1 = g2.trace();
+            g2.mul(g1);
+            cpm2 = g2.trace();
+
+            c = c.xtr_pow2(cp, cpm1, cpm2, a, b);
+            return c;
+        }
+    };
+
+    /* convert from byte array to FP12 */
+    FP12.fromBytes = function(w) {
+        var t = [],
+            i, a, b, c, d, e, f, g, r;
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i];
+        }
+        a = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + ctx.BIG.MODBYTES];
+        }
+        b = ctx.BIG.fromBytes(t);
+        c = new ctx.FP2(a, b); //c.bset(a,b);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 2 * ctx.BIG.MODBYTES];
+        }
+        a = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 3 * ctx.BIG.MODBYTES];
+        }
+        b = ctx.BIG.fromBytes(t);
+        d = new ctx.FP2(a, b); //d.bset(a,b);
+
+        e = new ctx.FP4(c, d); //e.set(c,d);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 4 * ctx.BIG.MODBYTES];
+        }
+        a = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 5 * ctx.BIG.MODBYTES];
+        }
+        b = ctx.BIG.fromBytes(t);
+        c = new ctx.FP2(a, b); //c.bset(a,b);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 6 * ctx.BIG.MODBYTES];
+        }
+        a = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 7 * ctx.BIG.MODBYTES];
+        }
+        b = ctx.BIG.fromBytes(t);
+        d = new ctx.FP2(a, b);
+
+        f = new ctx.FP4(c, d); //f.set(c,d);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 8 * ctx.BIG.MODBYTES];
+        }
+        a = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 9 * ctx.BIG.MODBYTES];
+        }
+        b = ctx.BIG.fromBytes(t);
+        c = new ctx.FP2(a, b); //c.bset(a,b);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 10 * ctx.BIG.MODBYTES];
+        }
+        a = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 11 * ctx.BIG.MODBYTES];
+        }
+        b = ctx.BIG.fromBytes(t);
+        d = new ctx.FP2(a, b); //d.bset(a,b);
+
+        g = new ctx.FP4(c, d); //g.set(c,d);
+
+        r = new FP12(e, f, g); //r.set(e,f,g);
+
+        return r;
+    };
+
+
+    /* return 1 if b==c, no branching */
+    FP12.teq = function(b, c) {
+        var x = b ^ c;
+        x -= 1; // if x=0, x now -1
+        return ((x >> 31) & 1);
+    };
+
+    /* p=q0^u0.q1^u1.q2^u2.q3^u3 */
+    // Bos & Costello https://eprint.iacr.org/2013/458.pdf
+    // Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
+    // Side channel attack secure
+    FP12.pow4 = function(q, u) {
+        var g = [],
+            r = new FP12(0),
+            p = new FP12(0),
+            t = [],
+            mt = new ctx.BIG(0),
+            w = [],
+            s = [],
+            i, j, k, nb, bt, pb;
+
+        for (i = 0; i < 4; i++) {
+            t[i] = new ctx.BIG(u[i]); t[i].norm();
+        }
+
+        g[0] = new FP12(q[0]);  // q[0]
+        g[1] = new FP12(g[0]); g[1].mul(q[1]);  // q[0].q[1]
+        g[2] = new FP12(g[0]); g[2].mul(q[2]);  // q[0].q[2]
+        g[3] = new FP12(g[1]); g[3].mul(q[2]);  // q[0].q[1].q[2]
+        g[4] = new FP12(q[0]); g[4].mul(q[3]);  // q[0].q[3]
+        g[5] = new FP12(g[1]); g[5].mul(q[3]);  // q[0].q[1].q[3]
+        g[6] = new FP12(g[2]); g[6].mul(q[3]);  // q[0].q[2].q[3]
+        g[7] = new FP12(g[3]); g[7].mul(q[3]);  // q[0].q[1].q[2].q[3]
+
+        // Make it odd
+        pb=1-t[0].parity();
+        t[0].inc(pb);
+        t[0].norm();
+
+        // Number of bits
+        mt.zero();
+        for (i=0;i<4;i++) {
+            mt.or(t[i]);
+        }
+
+        nb=1+mt.nbits();
+
+        // Sign pivot
+        s[nb-1]=1;
+        for (i=0;i<nb-1;i++) {
+            t[0].fshr(1);
+            s[i]=2*t[0].parity()-1;
+        }
+
+        // Recoded exponent
+        for (i=0; i<nb; i++) {
+            w[i]=0;
+            k=1;
+            for (j=1; j<4; j++) {
+                bt=s[i]*t[j].parity();
+                t[j].fshr(1);
+                t[j].dec(bt>>1);
+                t[j].norm();
+                w[i]+=bt*k;
+                k*=2;
+            }
+        }
+
+        // Main loop
+        p.select(g,2*w[nb-1]+1);
+        for (i=nb-2;i>=0;i--) {
+            p.usqr();
+            r.select(g,2*w[i]+s[i]);
+            p.mul(r);
+        }
+
+        // apply correction
+        r.copy(q[0]); r.conj();
+        r.mul(p);
+        p.cmove(r,pb);
+
+        p.reduce();
+        return p;
+    };
+
+
+    /* p=q0^u0.q1^u1.q2^u2.q3^u3 */
+    /* Timing attack secure, but not cache attack secure */
+    /*
+    FP12.pow4 = function(q, u) {
+        var a = [],
+            g = [],
+            s = [],
+            c = new FP12(1),
+            p = new FP12(0),
+            t = [],
+            mt = new ctx.BIG(0),
+            w = [],
+            i, j, nb, m;
+
+        for (i = 0; i < 4; i++) {
+            t[i] = new ctx.BIG(u[i]);
+        }
+
+        s[0] = new FP12(0);
+        s[1] = new FP12(0);
+
+        g[0] = new FP12(q[0]);
+        s[0].copy(q[1]);
+        s[0].conj();
+        g[0].mul(s[0]);
+        g[1] = new FP12(g[0]);
+        g[2] = new FP12(g[0]);
+        g[3] = new FP12(g[0]);
+        g[4] = new FP12(q[0]);
+        g[4].mul(q[1]);
+        g[5] = new FP12(g[4]);
+        g[6] = new FP12(g[4]);
+        g[7] = new FP12(g[4]);
+
+        s[1].copy(q[2]);
+        s[0].copy(q[3]);
+        s[0].conj();
+        s[1].mul(s[0]);
+        s[0].copy(s[1]);
+        s[0].conj();
+        g[1].mul(s[0]);
+        g[2].mul(s[1]);
+        g[5].mul(s[0]);
+        g[6].mul(s[1]);
+        s[1].copy(q[2]);
+        s[1].mul(q[3]);
+        s[0].copy(s[1]);
+        s[0].conj();
+        g[0].mul(s[0]);
+        g[3].mul(s[1]);
+        g[4].mul(s[0]);
+        g[7].mul(s[1]);
+
+        // if power is even add 1 to power, and add q to correction
+
+        for (i = 0; i < 4; i++) {
+            if (t[i].parity() == 0) {
+                t[i].inc(1);
+                t[i].norm();
+                c.mul(q[i]);
+            }
+            mt.add(t[i]);
+            mt.norm();
+        }
+        c.conj();
+        nb = 1 + mt.nbits();
+
+        // convert exponent to signed 1-bit window
+        for (j = 0; j < nb; j++) {
+            for (i = 0; i < 4; i++) {
+                a[i] = (t[i].lastbits(2) - 2);
+                t[i].dec(a[i]);
+                t[i].norm();
+                t[i].fshr(1);
+            }
+            w[j] = (8 * a[0] + 4 * a[1] + 2 * a[2] + a[3]);
+        }
+        w[nb] = (8 * t[0].lastbits(2) + 4 * t[1].lastbits(2) + 2 * t[2].lastbits(2) + t[3].lastbits(2));
+        p.copy(g[Math.floor((w[nb] - 1) / 2)]);
+
+        for (i = nb - 1; i >= 0; i--) {
+            m = w[i] >> 31;
+            j = (w[i] ^ m) - m; // j=abs(w[i])
+            j = (j - 1) / 2;
+            s[0].copy(g[j]);
+            s[1].copy(g[j]);
+            s[1].conj();
+            p.usqr();
+            p.mul(s[m & 1]);
+        }
+        p.mul(c); // apply correction
+        p.reduce();
+
+        return p;
+    };
+*/
+    return FP12;
+};
diff --git a/version3/js/fp16.js b/version3/js/fp16.js
new file mode 100644
index 0000000..a3edceb
--- /dev/null
+++ b/version3/js/fp16.js
@@ -0,0 +1,573 @@
+/*
+    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.
+*/
+
+/* Finite Field arithmetic  Fp^16 functions */
+
+/* FP16 elements are of the form a+ib, where i is sqrt(sqrt(-1+sqrt(-1)))  */
+
+var FP16 = function(ctx) {
+    "use strict";
+
+    /* general purpose constructor */
+    var FP16 = function(c, d) {
+        if (c instanceof FP16) {
+            this.a = new ctx.FP8(c.a);
+            this.b = new ctx.FP8(c.b);
+        } else {
+            this.a = new ctx.FP8(c);
+            this.b = new ctx.FP8(d);
+        }
+    };
+
+    FP16.prototype = {
+        /* reduce all components of this mod Modulus */
+        reduce: function() {
+            this.a.reduce();
+            this.b.reduce();
+        },
+
+        /* normalise all components of this mod Modulus */
+        norm: function() {
+            this.a.norm();
+            this.b.norm();
+        },
+
+        /* test this==0 ? */
+        iszilch: function() {
+            //this.reduce();
+            return (this.a.iszilch() && this.b.iszilch());
+        },
+
+        /* test this==1 ? */
+        isunity: function() {
+            var one = new ctx.FP8(1);
+            return (this.a.equals(one) && this.b.iszilch());
+        },
+
+        /* conditional copy of g to this depending on d */
+        cmove: function(g, d) {
+            this.a.cmove(g.a, d);
+            this.b.cmove(g.b, d);
+        },
+
+        /* test is w real? That is in a+ib test b is zero */
+        isreal: function() {
+            return this.b.iszilch();
+        },
+
+        /* extract real part a */
+        real: function() {
+            return this.a;
+        },
+
+        geta: function() {
+            return this.a;
+        },
+
+        /* extract imaginary part b */
+        getb: function() {
+            return this.b;
+        },
+
+        /* test this=x? */
+        equals: function(x) {
+            return (this.a.equals(x.a) && this.b.equals(x.b));
+        },
+
+        /* copy this=x */
+        copy: function(x) {
+            this.a.copy(x.a);
+            this.b.copy(x.b);
+        },
+
+        /* this=0 */
+        zero: function() {
+            this.a.zero();
+            this.b.zero();
+        },
+
+        /* this=1 */
+        one: function() {
+            this.a.one();
+            this.b.zero();
+        },
+
+        /* set from two FP8s */
+        set: function(c, d) {
+            this.a.copy(c);
+            this.b.copy(d);
+        },
+
+        /* set a */
+        seta: function(c) {
+            this.a.copy(c);
+            this.b.zero();
+        },
+
+        /* this=-this */
+        neg: function() {
+            var m = new ctx.FP8(this.a), //m.copy(this.a);
+                t = new ctx.FP8(0);
+
+            this.norm();
+
+            m.add(this.b);
+            m.neg();
+            //  m.norm();
+            t.copy(m);
+            t.add(this.b);
+            this.b.copy(m);
+            this.b.add(this.a);
+            this.a.copy(t);
+            this.norm();
+        },
+
+        /* this=conjugate(this) */
+        conj: function() {
+            this.b.neg();
+            this.norm();
+        },
+
+        /* this=-conjugate(this) */
+        nconj: function() {
+            this.a.neg();
+            this.norm();
+        },
+
+        /* this+=x */
+        add: function(x) {
+            this.a.add(x.a);
+            this.b.add(x.b);
+        },
+
+        /* this-=x */
+        sub: function(x) {
+            var m = new FP16(x); // m.copy(x);
+            m.neg();
+            this.add(m);
+        },
+
+        /* this*=s where s is FP8 */
+        pmul: function(s) {
+            this.a.mul(s);
+            this.b.mul(s);
+        },
+
+        /* this*=s where s is FP2 */
+        qmul: function(s) {
+            this.a.qmul(s);
+            this.b.qmul(s);
+        },
+
+        /* this*=c where s is int */
+        imul: function(c) {
+            this.a.imul(c);
+            this.b.imul(c);
+        },
+
+        /* this*=this */
+        sqr: function() {
+            //      this.norm();
+
+            var t1 = new ctx.FP8(this.a), //t1.copy(this.a)
+                t2 = new ctx.FP8(this.b), //t2.copy(this.b)
+                t3 = new ctx.FP8(this.a); //t3.copy(this.a)
+
+            t3.mul(this.b);
+            t1.add(this.b);
+            t1.norm();
+            t2.times_i();
+
+            t2.add(this.a);
+            t2.norm();
+            this.a.copy(t1);
+
+            this.a.mul(t2);
+
+            t2.copy(t3);
+            t2.times_i();
+            t2.add(t3);
+
+            t2.neg();
+
+            this.a.add(t2);
+
+            this.b.copy(t3);
+            this.b.add(t3);
+
+            this.norm();
+        },
+
+        /* this*=y */
+        mul: function(y) {
+
+            var t1 = new ctx.FP8(this.a), //t1.copy(this.a)
+                t2 = new ctx.FP8(this.b), //t2.copy(this.b)
+                t3 = new ctx.FP8(0),
+                t4 = new ctx.FP8(this.b); //t4.copy(this.b)
+
+            t1.mul(y.a);
+            t2.mul(y.b);
+            t3.copy(y.b);
+            t3.add(y.a);
+            t4.add(this.a);
+
+            t3.norm();
+            t4.norm();
+
+            t4.mul(t3);
+
+            t3.copy(t1);
+            t3.neg();
+            t4.add(t3);
+
+            t3.copy(t2);
+            t3.neg();
+            this.b.copy(t4);
+            this.b.add(t3);
+
+            t2.times_i();
+            this.a.copy(t2);
+            this.a.add(t1);
+
+            this.norm();
+        },
+
+        /* convert to hex string */
+        toString: function() {
+            return ("[" + this.a.toString() + "," + this.b.toString() + "]");
+        },
+
+        /* this=1/this */
+        inverse: function() {
+            this.norm();
+
+            var t1 = new ctx.FP8(this.a), //t1.copy(this.a);
+                t2 = new ctx.FP8(this.b); // t2.copy(this.b);
+
+            t1.sqr();
+            t2.sqr();
+            t2.times_i();
+            t2.norm(); // ??
+            t1.sub(t2);
+            t1.inverse();
+            this.a.mul(t1);
+            t1.neg();
+            t1.norm();
+            this.b.mul(t1);
+        },
+
+        /* this*=i where i = sqrt(-1+sqrt(-1)) */
+        times_i: function() {
+            var s = new ctx.FP8(this.b),
+                t = new ctx.FP8(this.a);
+
+            s.times_i();
+            this.b.copy(t);
+
+            this.a.copy(s);
+            this.norm();
+        },
+
+        times_i2: function() {
+            this.a.times_i();
+            this.b.times_i();
+        },
+
+        times_i4: function() {
+            this.a.times_i2();
+            this.b.times_i2();
+        },
+
+
+        /* this=this^q using Frobenius, where q is Modulus */
+        frob: function(f) {
+            var ff=new ctx.FP2(f); ff.sqr(); ff.norm();
+            this.a.frob(ff);
+            this.b.frob(ff);
+            this.b.qmul(f);
+            this.b.times_i();
+        },
+
+        /* this=this^e */
+        pow: function(e) {
+            
+            var w = new FP16(this), //w.copy(this);
+                z = new ctx.BIG(e), //z.copy(e);
+                r = new FP16(1),
+                bt;
+			w.norm();
+			z.norm();
+            for (;;) {
+                bt = z.parity();
+                z.fshr(1);
+
+                if (bt === 1) {
+                    r.mul(w);
+                }
+
+                if (z.iszilch()) {
+                    break;
+                }
+
+                w.sqr();
+            }
+            r.reduce();
+
+            return r;
+        },
+
+        /* XTR xtr_a function */
+        xtr_A: function(w, y, z) {
+            var r = new FP16(w), //r.copy(w);
+                t = new FP16(w); //t.copy(w);
+
+            //y.norm(); // ??
+            r.sub(y);
+            r.norm();
+            r.pmul(this.a);
+            t.add(y);
+            t.norm();
+            t.pmul(this.b);
+            t.times_i();
+
+            this.copy(r);
+            this.add(t);
+            this.add(z);
+
+            this.reduce();
+        },
+
+        /* XTR xtr_d function */
+        xtr_D: function() {
+            var w = new FP16(this); //w.copy(this);
+            this.sqr();
+            w.conj();
+            w.add(w); //w.norm(); // ??
+            this.sub(w);
+            this.reduce();
+        },
+
+        /* r=x^n using XTR method on traces of FP12s */
+        xtr_pow: function(n) {
+			var sf = new FP16(this);
+			sf.norm();
+            var a = new FP16(3),
+                b = new FP16(sf),
+                c = new FP16(b),
+                t = new FP16(0),
+                r = new FP16(0),
+                par, v, nb, i;
+
+            c.xtr_D();
+
+            
+            par = n.parity();
+            v = new ctx.BIG(n);
+			v.norm();
+            v.fshr(1);
+
+            if (par === 0) {
+                v.dec(1);
+                v.norm();
+            }
+
+            nb = v.nbits();
+            for (i = nb - 1; i >= 0; i--) {
+                if (v.bit(i) != 1) {
+                    t.copy(b);
+                    sf.conj();
+                    c.conj();
+                    b.xtr_A(a, sf, c);
+                    sf.conj();
+                    c.copy(t);
+                    c.xtr_D();
+                    a.xtr_D();
+                } else {
+                    t.copy(a);
+                    t.conj();
+                    a.copy(b);
+                    a.xtr_D();
+                    b.xtr_A(c, sf, t);
+                    c.xtr_D();
+                }
+            }
+
+            if (par === 0) {
+                r.copy(c);
+            } else {
+                r.copy(b);
+            }
+            r.reduce();
+
+            return r;
+        },
+
+        /* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */
+        xtr_pow2: function(ck, ckml, ckm2l, a, b) {
+
+            var e = new ctx.BIG(a), //e.copy(a)
+                d = new ctx.BIG(b), //d.copy(b)
+                w = new ctx.BIG(0),
+                cu = new FP16(ck), //cu.copy(ck), // can probably be passed in w/o copying
+                cv = new FP16(this), //cv.copy(this),
+                cumv = new FP16(ckml), //cumv.copy(ckml),
+                cum2v = new FP16(ckm2l), //cum2v.copy(ckm2l),
+                r = new FP16(0),
+                t = new FP16(0),
+                f2 = 0,
+                i;
+
+            d.norm();
+            e.norm();
+
+            while (d.parity() === 0 && e.parity() === 0) {
+                d.fshr(1);
+                e.fshr(1);
+                f2++;
+            }
+
+            while (ctx.BIG.comp(d, e) !== 0) {
+                if (ctx.BIG.comp(d, e) > 0) {
+                    w.copy(e);
+                    w.imul(4);
+                    w.norm();
+
+                    if (ctx.BIG.comp(d, w) <= 0) {
+                        w.copy(d);
+                        d.copy(e);
+                        e.rsub(w);
+                        e.norm();
+
+                        t.copy(cv);
+                        t.xtr_A(cu, cumv, cum2v);
+                        cum2v.copy(cumv);
+                        cum2v.conj();
+                        cumv.copy(cv);
+                        cv.copy(cu);
+                        cu.copy(t);
+
+                    } else if (d.parity() === 0) {
+                        d.fshr(1);
+                        r.copy(cum2v);
+                        r.conj();
+                        t.copy(cumv);
+                        t.xtr_A(cu, cv, r);
+                        cum2v.copy(cumv);
+                        cum2v.xtr_D();
+                        cumv.copy(t);
+                        cu.xtr_D();
+                    } else if (e.parity() == 1) {
+                        d.sub(e);
+                        d.norm();
+                        d.fshr(1);
+                        t.copy(cv);
+                        t.xtr_A(cu, cumv, cum2v);
+                        cu.xtr_D();
+                        cum2v.copy(cv);
+                        cum2v.xtr_D();
+                        cum2v.conj();
+                        cv.copy(t);
+                    } else {
+                        w.copy(d);
+                        d.copy(e);
+                        d.fshr(1);
+                        e.copy(w);
+                        t.copy(cumv);
+                        t.xtr_D();
+                        cumv.copy(cum2v);
+                        cumv.conj();
+                        cum2v.copy(t);
+                        cum2v.conj();
+                        t.copy(cv);
+                        t.xtr_D();
+                        cv.copy(cu);
+                        cu.copy(t);
+                    }
+                }
+                if (ctx.BIG.comp(d, e) < 0) {
+                    w.copy(d);
+                    w.imul(4);
+                    w.norm();
+
+                    if (ctx.BIG.comp(e, w) <= 0) {
+                        e.sub(d);
+                        e.norm();
+                        t.copy(cv);
+                        t.xtr_A(cu, cumv, cum2v);
+                        cum2v.copy(cumv);
+                        cumv.copy(cu);
+                        cu.copy(t);
+                    } else if (e.parity() === 0) {
+                        w.copy(d);
+                        d.copy(e);
+                        d.fshr(1);
+                        e.copy(w);
+                        t.copy(cumv);
+                        t.xtr_D();
+                        cumv.copy(cum2v);
+                        cumv.conj();
+                        cum2v.copy(t);
+                        cum2v.conj();
+                        t.copy(cv);
+                        t.xtr_D();
+                        cv.copy(cu);
+                        cu.copy(t);
+                    } else if (d.parity() == 1) {
+                        w.copy(e);
+                        e.copy(d);
+                        w.sub(d);
+                        w.norm();
+                        d.copy(w);
+                        d.fshr(1);
+                        t.copy(cv);
+                        t.xtr_A(cu, cumv, cum2v);
+                        cumv.conj();
+                        cum2v.copy(cu);
+                        cum2v.xtr_D();
+                        cum2v.conj();
+                        cu.copy(cv);
+                        cu.xtr_D();
+                        cv.copy(t);
+                    } else {
+                        d.fshr(1);
+                        r.copy(cum2v);
+                        r.conj();
+                        t.copy(cumv);
+                        t.xtr_A(cu, cv, r);
+                        cum2v.copy(cumv);
+                        cum2v.xtr_D();
+                        cumv.copy(t);
+                        cu.xtr_D();
+                    }
+                }
+            }
+            r.copy(cv);
+            r.xtr_A(cu, cumv, cum2v);
+            for (i = 0; i < f2; i++) {
+                r.xtr_D();
+            }
+            r = r.xtr_pow(d);
+            return r;
+        }
+
+    };
+
+    return FP16;
+};
diff --git a/version3/js/fp2.js b/version3/js/fp2.js
new file mode 100644
index 0000000..1fa9af2
--- /dev/null
+++ b/version3/js/fp2.js
@@ -0,0 +1,405 @@
+/*
+    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.
+*/
+
+/* Finite Field arithmetic  Fp^2 functions */
+
+/* FP2 elements are of the form a+ib, where i is sqrt(-1) */
+
+var FP2 = function(ctx) {
+    "use strict";
+
+    /* general purpose constructor */
+    var FP2 = function(c, d) {
+        if (c instanceof FP2) {
+            this.a = new ctx.FP(c.a);
+            this.b = new ctx.FP(c.b);
+        } else {
+            this.a = new ctx.FP(c);
+            this.b = new ctx.FP(d);
+        }
+    };
+
+    FP2.prototype = {
+        /* reduce components mod Modulus */
+        reduce: function() {
+            this.a.reduce();
+            this.b.reduce();
+        },
+
+        /* normalise components of w */
+        norm: function() {
+            this.a.norm();
+            this.b.norm();
+        },
+
+        /* test this=0 ? */
+        iszilch: function() {
+            //this.reduce();
+            return (this.a.iszilch() && this.b.iszilch());
+        },
+
+        /* test this=1 ? */
+        isunity: function() {
+            var one = new ctx.FP(1);
+            return (this.a.equals(one) && this.b.iszilch());
+        },
+
+        /* conditional copy of g to this depending on d */
+        cmove: function(g, d) {
+            this.a.cmove(g.a, d);
+            this.b.cmove(g.b, d);
+        },
+
+        /* test this=x */
+        equals: function(x) {
+            return (this.a.equals(x.a) && this.b.equals(x.b));
+        },
+
+        /* extract a */
+        getA: function() {
+            return this.a.redc();
+        },
+
+        /* extract b */
+        getB: function() {
+            return this.b.redc();
+        },
+
+        /* set from pair of FPs */
+        set: function(c, d) {
+            this.a.copy(c);
+            this.b.copy(d);
+        },
+
+        /* set a */
+        seta: function(c) {
+            this.a.copy(c);
+            this.b.zero();
+        },
+
+        /* set from two BIGs */
+        bset: function(c, d) {
+            this.a.bcopy(c);
+            this.b.bcopy(d);
+        },
+
+        /* set from one ctx.BIG */
+        bseta: function(c) {
+            this.a.bcopy(c);
+            this.b.zero();
+        },
+
+        /* copy this=x */
+        copy: function(x) {
+            this.a.copy(x.a);
+            this.b.copy(x.b);
+        },
+
+        /* set this=0 */
+        zero: function() {
+            this.a.zero();
+            this.b.zero();
+        },
+
+        /* set this=1 */
+        one: function() {
+            this.a.one();
+            this.b.zero();
+        },
+
+        /* negate this */
+        neg: function() {
+            //      this.norm();
+            var m = new ctx.FP(this.a),
+                t = new ctx.FP(0);
+
+            m.add(this.b);
+            m.neg();
+            //      m.norm();
+            t.copy(m);
+            t.add(this.b);
+            this.b.copy(m);
+            this.b.add(this.a);
+            this.a.copy(t);
+            //this.norm();
+        },
+
+        /* conjugate this */
+        conj: function() {
+            this.b.neg();
+            this.b.norm();
+        },
+
+        /* this+=a */
+        add: function(x) {
+            this.a.add(x.a);
+            this.b.add(x.b);
+        },
+
+        /* this-=x */
+        sub: function(x) {
+            var m = new FP2(x); //var m=new FP2(0); m.copy(x);
+            m.neg();
+            this.add(m);
+        },
+
+        rsub: function(x) {
+            this.neg();
+            this.add(x);
+        },
+
+        /* this*=s, where s is FP */
+        pmul: function(s) {
+            this.a.mul(s);
+            this.b.mul(s);
+        },
+
+        /* this*=c, where s is int */
+        imul: function(c) {
+            this.a.imul(c);
+            this.b.imul(c);
+        },
+
+        /* this*=this */
+        sqr: function() {
+            //      this.norm();
+
+            var w1 = new ctx.FP(this.a),
+                w3 = new ctx.FP(this.a),
+                mb = new ctx.FP(this.b);
+
+            //      w3.mul(this.b);
+            w1.add(this.b);
+
+
+            w3.add(this.a);
+            w3.norm();
+            this.b.mul(w3);
+
+            mb.neg();
+            this.a.add(mb);
+
+            this.a.norm();
+            w1.norm();
+
+            this.a.mul(w1);
+            //      this.b.copy(w3); this.b.add(w3);
+            //      this.b.norm();
+        },
+
+        /* this*=y */
+        /* Now using Lazy reduction - inputs must be normed */
+        mul: function(y) {
+            var p = new ctx.BIG(0),
+                pR = new ctx.DBIG(0),
+                A, B, C, D, E, F;
+
+            p.rcopy(ctx.ROM_FIELD.Modulus);
+            pR.ucopy(p);
+
+            if ((this.a.XES + this.b.XES) * (y.a.XES + y.b.XES) > ctx.FP.FEXCESS) {
+                if (this.a.XES > 1) {
+                    this.a.reduce();
+                }
+
+                if (this.b.XES > 1) {
+                    this.b.reduce();
+                }
+            }
+
+            A = ctx.BIG.mul(this.a.f, y.a.f);
+            B = ctx.BIG.mul(this.b.f, y.b.f);
+
+            C = new ctx.BIG(this.a.f);
+            D = new ctx.BIG(y.a.f);
+
+            C.add(this.b.f);
+            C.norm();
+            D.add(y.b.f);
+            D.norm();
+
+            E = ctx.BIG.mul(C, D);
+            F = new ctx.DBIG(0);
+            F.copy(A);
+            F.add(B);
+            B.rsub(pR);
+
+            A.add(B);
+            A.norm();
+            E.sub(F);
+            E.norm();
+
+            this.a.f.copy(ctx.FP.mod(A));
+            this.a.XES = 3;
+            this.b.f.copy(ctx.FP.mod(E));
+            this.b.XES = 2;
+        },
+
+        /* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */
+        /* returns true if this is QR */
+        sqrt: function() {
+            var w1, w2;
+
+            if (this.iszilch()) {
+                return true;
+            }
+
+            w1 = new ctx.FP(this.b);
+            w2 = new ctx.FP(this.a);
+
+            w1.sqr();
+            w2.sqr();
+            w1.add(w2);
+            if (w1.jacobi() != 1) {
+                this.zero();
+                return false;
+            }
+            w1 = w1.sqrt();
+            w2.copy(this.a);
+            w2.add(w1);
+            w2.norm();
+            w2.div2();
+            if (w2.jacobi() != 1) {
+                w2.copy(this.a);
+                w2.sub(w1);
+                w2.norm();
+                w2.div2();
+                if (w2.jacobi() != 1) {
+                    this.zero();
+                    return false;
+                }
+            }
+            w2 = w2.sqrt();
+            this.a.copy(w2);
+            w2.add(w2);
+            w2.inverse();
+            this.b.mul(w2);
+
+            return true;
+        },
+
+        /* convert this to hex string */
+        toString: function() {
+            return ("[" + this.a.toString() + "," + this.b.toString() + "]");
+        },
+
+        /* this=1/this */
+        inverse: function() {
+            var w1, w2;
+
+            this.norm();
+
+            w1 = new ctx.FP(this.a);
+            w2 = new ctx.FP(this.b);
+
+            w1.sqr();
+            w2.sqr();
+            w1.add(w2);
+            w1.inverse();
+            this.a.mul(w1);
+            w1.neg();
+            w1.norm();
+            this.b.mul(w1);
+        },
+
+        /* this/=2 */
+        div2: function() {
+            this.a.div2();
+            this.b.div2();
+        },
+
+        /* this*=sqrt(-1) */
+        times_i: function() {
+            var z = new ctx.FP(this.a); //z.copy(this.a);
+            this.a.copy(this.b);
+            this.a.neg();
+            this.b.copy(z);
+        },
+
+        /* w*=(1+sqrt(-1)) */
+        /* where X*2-(1+sqrt(-1)) is irreducible for FP4, assumes p=3 mod 8 */
+        mul_ip: function() {
+            //      this.norm();
+            var t = new FP2(this), // t.copy(this);
+                z = new ctx.FP(this.a); //z.copy(this.a);
+
+            this.a.copy(this.b);
+            this.a.neg();
+            this.b.copy(z);
+            this.add(t);
+            //      this.norm();
+        },
+
+        div_ip2: function() {
+            var t = new FP2(0);
+            this.norm();
+            t.a.copy(this.a);
+            t.a.add(this.b);
+            t.b.copy(this.b);
+            t.b.sub(this.a);
+            this.copy(t);
+            this.norm();
+        },
+
+        /* w/=(1+sqrt(-1)) */
+        div_ip: function() {
+            var t = new FP2(0);
+            this.norm();
+            t.a.copy(this.a);
+            t.a.add(this.b);
+            t.b.copy(this.b);
+            t.b.sub(this.a);
+            this.copy(t);
+            this.norm();
+            this.div2();
+        },
+
+        /* this=this^e */
+        pow: function(e) {
+            this.norm();
+
+            var r = new FP2(1),
+                x = new FP2(this), //x.copy(this);
+                bt;
+
+            e.norm();
+
+            for (;;) {
+                bt = e.parity();
+                e.fshr(1);
+
+                if (bt == 1) {
+                    r.mul(x);
+                }
+
+                if (e.iszilch()) {
+                    break;
+                }
+                x.sqr();
+            }
+
+            r.reduce();
+
+            return r;
+        }
+
+    };
+
+    return FP2;
+};
diff --git a/version3/js/fp24.js b/version3/js/fp24.js
new file mode 100644
index 0000000..8b05f20
--- /dev/null
+++ b/version3/js/fp24.js
@@ -0,0 +1,963 @@
+/*
+    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.
+*/
+
+/* AMCL Fp^24 functions */
+
+/* FP24 elements are of the form a+i.b+i^2.c */
+
+var FP24 = function(ctx) {
+    "use strict";
+
+    /* general purpose constructor */
+    var FP24 = function(d, e, f) {
+        if (d instanceof FP24) {
+            this.a = new ctx.FP8(d.a);
+            this.b = new ctx.FP8(d.b);
+            this.c = new ctx.FP8(d.c);
+        } else {
+            this.a = new ctx.FP8(d);
+            this.b = new ctx.FP8(e);
+            this.c = new ctx.FP8(f);
+        }
+    };
+
+    FP24.prototype = {
+        /* reduce all components of this mod Modulus */
+        reduce: function() {
+            this.a.reduce();
+            this.b.reduce();
+            this.c.reduce();
+        },
+
+        /* normalize all components of this mod Modulus */
+        norm: function() {
+            this.a.norm();
+            this.b.norm();
+            this.c.norm();
+        },
+
+        /* test x==0 ? */
+        iszilch: function() {
+            //this.reduce();
+            return (this.a.iszilch() && this.b.iszilch() && this.c.iszilch());
+        },
+
+        /* test x==1 ? */
+        isunity: function() {
+            var one = new ctx.FP8(1);
+            return (this.a.equals(one) && this.b.iszilch() && this.c.iszilch());
+        },
+
+        /* conditional copy of g to this depending on d */
+        cmove: function(g, d) {
+            this.a.cmove(g.a, d);
+            this.b.cmove(g.b, d);
+            this.c.cmove(g.c, d);
+        },
+
+        /* Constant time select from pre-computed table */
+        select: function(g, b) {
+            var invf = new FP24(0),
+                m, babs;
+
+            m = b >> 31;
+            babs = (b ^ m) - m;
+            babs = (babs - 1) / 2;
+
+            this.cmove(g[0], FP24.teq(babs, 0)); // conditional move
+            this.cmove(g[1], FP24.teq(babs, 1));
+            this.cmove(g[2], FP24.teq(babs, 2));
+            this.cmove(g[3], FP24.teq(babs, 3));
+            this.cmove(g[4], FP24.teq(babs, 4));
+            this.cmove(g[5], FP24.teq(babs, 5));
+            this.cmove(g[6], FP24.teq(babs, 6));
+            this.cmove(g[7], FP24.teq(babs, 7));
+
+            invf.copy(this);
+            invf.conj();
+            this.cmove(invf, (m & 1));
+        },
+
+        /* extract a from this */
+        geta: function() {
+            return this.a;
+        },
+
+        /* extract b */
+        getb: function() {
+            return this.b;
+        },
+
+        /* extract c */
+        getc: function() {
+            return this.c;
+        },
+
+        /* return 1 if x==y, else 0 */
+        equals: function(x) {
+            return (this.a.equals(x.a) && this.b.equals(x.b) && this.c.equals(x.c));
+        },
+
+        /* copy this=x */
+        copy: function(x) {
+            this.a.copy(x.a);
+            this.b.copy(x.b);
+            this.c.copy(x.c);
+        },
+
+        /* set this=1 */
+        one: function() {
+            this.a.one();
+            this.b.zero();
+            this.c.zero();
+        },
+
+        /* this=conj(this) */
+        conj: function() {
+            this.a.conj();
+            this.b.nconj();
+            this.c.conj();
+        },
+
+        /* set this from 3 FP8s */
+        set: function(d, e, f) {
+            this.a.copy(d);
+            this.b.copy(e);
+            this.c.copy(f);
+        },
+
+        /* set this from one ctx.FP8 */
+        seta: function(d) {
+            this.a.copy(d);
+            this.b.zero();
+            this.c.zero();
+        },
+
+        /* Granger-Scott Unitary Squaring */
+        usqr: function() {
+            var A = new ctx.FP8(this.a), //A.copy(this.a)
+                B = new ctx.FP8(this.c), //B.copy(this.c)
+                C = new ctx.FP8(this.b), //C.copy(this.b)
+                D = new ctx.FP8(0);
+
+            this.a.sqr();
+            D.copy(this.a);
+            D.add(this.a);
+            this.a.add(D);
+
+            A.nconj();
+
+            A.add(A);
+            this.a.add(A);
+            B.sqr();
+            B.times_i();
+
+            D.copy(B);
+            D.add(B);
+            B.add(D);
+
+            C.sqr();
+            D.copy(C);
+            D.add(C);
+            C.add(D);
+
+            this.b.conj();
+            this.b.add(this.b);
+            this.c.nconj();
+
+            this.c.add(this.c);
+            this.b.add(B);
+            this.c.add(C);
+            this.reduce();
+        },
+
+        /* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
+        sqr: function() {
+            var A = new ctx.FP8(this.a), //A.copy(this.a)
+                B = new ctx.FP8(this.b), //B.copy(this.b)
+                C = new ctx.FP8(this.c), //C.copy(this.c)
+                D = new ctx.FP8(this.a); //D.copy(this.a)
+
+            A.sqr();
+            B.mul(this.c);
+            B.add(B); //B.norm();
+            C.sqr();
+            D.mul(this.b);
+            D.add(D);
+
+            this.c.add(this.a);
+            this.c.add(this.b);
+            this.c.norm();
+            this.c.sqr();
+
+            this.a.copy(A);
+
+            A.add(B);
+            A.add(C);
+            A.add(D);
+            A.neg();
+            B.times_i();
+            C.times_i();
+
+            this.a.add(B);
+            this.b.copy(C);
+            this.b.add(D);
+            this.c.add(A);
+
+            this.norm();
+        },
+
+        /* FP24 full multiplication this=this*y */
+        mul: function(y) {
+            var z0 = new ctx.FP8(this.a), //z0.copy(this.a)
+                z1 = new ctx.FP8(0),
+                z2 = new ctx.FP8(this.b), //z2.copy(this.b)
+                z3 = new ctx.FP8(0),
+                t0 = new ctx.FP8(this.a), //t0.copy(this.a)
+                t1 = new ctx.FP8(y.a); //t1.copy(y.a)
+
+            z0.mul(y.a);
+            z2.mul(y.b);
+
+            t0.add(this.b);
+            t1.add(y.b);
+
+            t0.norm();
+            t1.norm();
+
+            z1.copy(t0);
+            z1.mul(t1);
+            t0.copy(this.b);
+            t0.add(this.c);
+
+            t1.copy(y.b);
+            t1.add(y.c);
+
+            t0.norm();
+            t1.norm();
+            z3.copy(t0);
+            z3.mul(t1);
+
+            t0.copy(z0);
+            t0.neg();
+            t1.copy(z2);
+            t1.neg();
+
+            z1.add(t0);
+            this.b.copy(z1);
+            this.b.add(t1);
+
+            z3.add(t1);
+            z2.add(t0);
+
+            t0.copy(this.a);
+            t0.add(this.c);
+            t1.copy(y.a);
+            t1.add(y.c);
+
+            t0.norm();
+            t1.norm();
+
+            t0.mul(t1);
+            z2.add(t0);
+
+            t0.copy(this.c);
+            t0.mul(y.c);
+            t1.copy(t0);
+            t1.neg();
+
+            this.c.copy(z2);
+            this.c.add(t1);
+            z3.add(t1);
+            t0.times_i();
+            this.b.add(t0);
+            // z3.norm();
+            z3.times_i();
+            this.a.copy(z0);
+            this.a.add(z3);
+
+            this.norm();
+        },
+
+        /* Special case this*=y that arises from special form of ATE pairing line function */
+        smul: function(y, twist) {
+            var z0, z1, z2, z3, t0, t1;
+
+            if (twist == ctx.ECP.D_TYPE) {
+                z0 = new ctx.FP8(this.a); //z0.copy(this.a);
+                z2 = new ctx.FP8(this.b); //z2.copy(this.b);
+                z3 = new ctx.FP8(this.b); //z3.copy(this.b);
+                t0 = new ctx.FP8(0);
+                t1 = new ctx.FP8(y.a); //t1.copy(y.a);
+
+                z0.mul(y.a);
+                z2.pmul(y.b.real());
+                this.b.add(this.a);
+                t1.real().add(y.b.real());
+
+                this.b.norm();
+                t1.norm();
+
+                this.b.mul(t1);
+                z3.add(this.c);
+                z3.norm();
+                z3.pmul(y.b.real());
+
+                t0.copy(z0);
+                t0.neg();
+                t1.copy(z2);
+                t1.neg();
+
+                this.b.add(t0);
+
+                this.b.add(t1);
+                z3.add(t1);
+                z2.add(t0);
+
+                t0.copy(this.a);
+                t0.add(this.c);
+                t0.norm();
+                t0.mul(y.a);
+                this.c.copy(z2);
+                this.c.add(t0);
+
+                z3.times_i();
+                this.a.copy(z0);
+                this.a.add(z3);
+            }
+
+            if (twist == ctx.ECP.M_TYPE) {
+                z0=new ctx.FP8(this.a);
+                z1=new ctx.FP8(0);
+                z2=new ctx.FP8(0);
+                z3=new ctx.FP8(0);
+                t0=new ctx.FP8(this.a);
+                t1=new ctx.FP8(0);
+
+                z0.mul(y.a);
+                t0.add(this.b);
+                t0.norm();
+
+                z1.copy(t0); z1.mul(y.a);
+                t0.copy(this.b); t0.add(this.c);
+                t0.norm();
+
+                z3.copy(t0); //z3.mul(y.c);
+                z3.pmul(y.c.getb());
+                z3.times_i();
+
+                t0.copy(z0); t0.neg();
+
+                z1.add(t0);
+                this.b.copy(z1);
+                z2.copy(t0);
+
+                t0.copy(this.a); t0.add(this.c);
+                t1.copy(y.a); t1.add(y.c);
+
+                t0.norm();
+                t1.norm();
+
+                t0.mul(t1);
+                z2.add(t0);
+
+                t0.copy(this.c);
+
+                t0.pmul(y.c.getb());
+                t0.times_i();
+
+                t1.copy(t0); t1.neg();
+
+                this.c.copy(z2); this.c.add(t1);
+                z3.add(t1);
+                t0.times_i();
+                this.b.add(t0);
+                z3.norm();
+                z3.times_i();
+                this.a.copy(z0); this.a.add(z3);
+            }
+
+            this.norm();
+        },
+
+        /* this=1/this */
+        inverse: function() {
+            var f0 = new ctx.FP8(this.a), //f0.copy(this.a)
+                f1 = new ctx.FP8(this.b), //f1.copy(this.b)
+                f2 = new ctx.FP8(this.a), //f2.copy(this.a)
+                f3 = new ctx.FP8(0);
+
+            f0.sqr();
+            f1.mul(this.c);
+            f1.times_i();
+            f0.sub(f1);
+            f0.norm();
+
+            f1.copy(this.c);
+            f1.sqr();
+            f1.times_i();
+            f2.mul(this.b);
+            f1.sub(f2);
+            f1.norm();
+
+            f2.copy(this.b);
+            f2.sqr();
+            f3.copy(this.a);
+            f3.mul(this.c);
+            f2.sub(f3);
+            f2.norm();
+
+            f3.copy(this.b);
+            f3.mul(f2);
+            f3.times_i();
+            this.a.mul(f0);
+            f3.add(this.a);
+            this.c.mul(f1);
+            this.c.times_i();
+
+            f3.add(this.c);
+            f3.norm();
+            f3.inverse();
+            this.a.copy(f0);
+            this.a.mul(f3);
+            this.b.copy(f1);
+            this.b.mul(f3);
+            this.c.copy(f2);
+            this.c.mul(f3);
+        },
+
+        /* this=this^p, where p=Modulus, using Frobenius */
+        frob: function(f,n) {
+            var f2 = new ctx.FP2(f),
+                f3 = new ctx.FP2(f),
+                i;
+
+            f2.sqr();
+            f3.mul(f2);
+
+            f3.mul_ip(); f3.norm();
+
+            for (i=0;i<n;i++) {
+                this.a.frob(f3);
+                this.b.frob(f3);
+                this.c.frob(f3);
+
+                this.b.qmul(f); this.b.times_i2();
+                this.c.qmul(f2); this.c.times_i2(); this.c.times_i2();
+            }
+        },
+
+        /* trace function */
+        trace: function() {
+            var t = new ctx.FP8(0);
+
+            t.copy(this.a);
+            t.imul(3);
+            t.reduce();
+
+            return t;
+        },
+
+        /* convert this to hex string */
+        toString: function() {
+            return ("[" + this.a.toString() + "," + this.b.toString() + "," + this.c.toString() + "]");
+        },
+
+        /* convert this to byte array */
+        toBytes: function(w) {
+            var t = [],
+                i;
+
+            this.a.geta().geta().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i] = t[i];
+            }
+            this.a.geta().geta().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + ctx.BIG.MODBYTES] = t[i];
+            }
+            this.a.geta().getb().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 2 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.a.geta().getb().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 3 * ctx.BIG.MODBYTES] = t[i];
+            }
+
+            this.a.getb().geta().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 4 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.a.getb().geta().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 5 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.a.getb().getb().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 6 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.a.getb().getb().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 7 * ctx.BIG.MODBYTES] = t[i];
+            }
+
+            this.b.geta().geta().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 8 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.b.geta().geta().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 9 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.b.geta().getb().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 10 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.b.geta().getb().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 11 * ctx.BIG.MODBYTES] = t[i];
+            }
+
+            this.b.getb().geta().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 12 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.b.getb().geta().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 13 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.b.getb().getb().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 14 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.b.getb().getb().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 15 * ctx.BIG.MODBYTES] = t[i];
+            }
+
+            this.c.geta().geta().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 16 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.c.geta().geta().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 17 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.c.geta().getb().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 18 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.c.geta().getb().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 19 * ctx.BIG.MODBYTES] = t[i];
+            }
+
+            this.c.getb().geta().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 20 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.c.getb().geta().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 21 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.c.getb().getb().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 22 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.c.getb().getb().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 23 * ctx.BIG.MODBYTES] = t[i];
+            }
+        },
+
+        /* set this=this^e */
+        pow: function(e) {
+            var e1, e3, w, nb, i, bt, sf;
+
+			sf = new FP24(this);
+            sf.norm();
+			e1 = new ctx.BIG(e);
+            e1.norm();
+
+            e3 = new ctx.BIG(e1);
+            e3.pmul(3);
+            e3.norm();
+
+            w = new FP24(sf);
+            nb = e3.nbits();
+
+            for (i = nb - 2; i >= 1; i--) {
+                w.usqr();
+                bt = e3.bit(i) - e1.bit(i);
+
+                if (bt == 1) {
+                    w.mul(sf);
+                }
+                if (bt == -1) {
+                    sf.conj();
+                    w.mul(sf);
+                    sf.conj();
+                }
+            }
+            w.reduce();
+
+            return w;
+        },
+
+        /* constant time powering by small integer of max length bts */
+        pinpow: function(e, bts) {
+            var R = [],
+                i, b;
+
+            R[0] = new FP24(1);
+            R[1] = new FP24(this);
+
+            for (i = bts - 1; i >= 0; i--) {
+                b = (e >> i) & 1;
+                R[1 - b].mul(R[b]);
+                R[b].usqr();
+            }
+
+            this.copy(R[0]);
+        },
+
+        /* Faster compressed powering for unitary elements */
+        compow: function(e, r) {
+            var fa, fb, f, q, m, a, b, g1, g2, c, cp, cpm1, cpm2;
+
+            fa = new ctx.BIG(0);
+            fa.rcopy(ctx.ROM_FIELD.Fra);
+            fb = new ctx.BIG(0);
+            fb.rcopy(ctx.ROM_FIELD.Frb);
+            f = new ctx.FP2(fa, fb);
+
+            q = new ctx.BIG(0);
+            q.rcopy(ctx.ROM_FIELD.Modulus);
+
+            m = new ctx.BIG(q);
+            m.mod(r);
+
+            a = new ctx.BIG(e);
+            a.mod(m);
+
+            b = new ctx.BIG(e);
+            b.div(m);
+
+            g1 = new FP24(0);
+            g2 = new FP24(0);
+            g1.copy(this);
+
+            c = g1.trace();
+
+            if (b.iszilch()) {
+                c=c.xtr_pow(e);
+                return c;
+            }
+
+            g2.copy(g1);
+            g2.frob(f,1);
+            cp = g2.trace();
+            g1.conj();
+            g2.mul(g1);
+            cpm1 = g2.trace();
+            g2.mul(g1);
+            cpm2 = g2.trace();
+
+            c = c.xtr_pow2(cp, cpm1, cpm2, a, b);
+            return c;
+        }
+    };
+
+    /* convert from byte array to FP12 */
+    FP24.fromBytes = function(w) {
+        var t = [],
+            i, a, b, c, d, e, f, g, r, ea, eb;
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i];
+        }
+        a = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + ctx.BIG.MODBYTES];
+        }
+        b = ctx.BIG.fromBytes(t);
+        c = new ctx.FP2(a, b); //c.bset(a,b);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 2 * ctx.BIG.MODBYTES];
+        }
+        a = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 3 * ctx.BIG.MODBYTES];
+        }
+        b = ctx.BIG.fromBytes(t);
+        d = new ctx.FP2(a, b); //d.bset(a,b);
+
+        ea = new ctx.FP4(c, d); //e.set(c,d);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 4 * ctx.BIG.MODBYTES];
+        }
+        a = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 5 * ctx.BIG.MODBYTES];
+        }
+        b = ctx.BIG.fromBytes(t);
+        c = new ctx.FP2(a, b); //c.bset(a,b);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 6 * ctx.BIG.MODBYTES];
+        }
+        a = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 7 * ctx.BIG.MODBYTES];
+        }
+        b = ctx.BIG.fromBytes(t);
+        d = new ctx.FP2(a, b); //d.bset(a,b);
+
+        eb = new ctx.FP4(c, d); //e.set(c,d);
+
+        e = new ctx.FP8(ea,eb);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 8 * ctx.BIG.MODBYTES];
+        }
+        a = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 9 * ctx.BIG.MODBYTES];
+        }
+        b = ctx.BIG.fromBytes(t);
+        c = new ctx.FP2(a, b); //c.bset(a,b);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 10 * ctx.BIG.MODBYTES];
+        }
+        a = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 11 * ctx.BIG.MODBYTES];
+        }
+        b = ctx.BIG.fromBytes(t);
+        d = new ctx.FP2(a, b);
+
+        ea = new ctx.FP4(c, d); //e.set(c,d);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 12 * ctx.BIG.MODBYTES];
+        }
+        a = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 13 * ctx.BIG.MODBYTES];
+        }
+        b = ctx.BIG.fromBytes(t);
+        c = new ctx.FP2(a, b); //c.bset(a,b);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 14 * ctx.BIG.MODBYTES];
+        }
+        a = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 15 * ctx.BIG.MODBYTES];
+        }
+        b = ctx.BIG.fromBytes(t);
+        d = new ctx.FP2(a, b);
+
+        eb = new ctx.FP4(c, d); //e.set(c,d);
+
+        f = new ctx.FP8(ea, eb); //f.set(c,d);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 16 * ctx.BIG.MODBYTES];
+        }
+        a = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 17 * ctx.BIG.MODBYTES];
+        }
+        b = ctx.BIG.fromBytes(t);
+        c = new ctx.FP2(a, b); //c.bset(a,b);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 18 * ctx.BIG.MODBYTES];
+        }
+        a = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 19 * ctx.BIG.MODBYTES];
+        }
+        b = ctx.BIG.fromBytes(t);
+        d = new ctx.FP2(a, b); //d.bset(a,b);
+
+        ea = new ctx.FP4(c, d); //e.set(c,d);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 20 * ctx.BIG.MODBYTES];
+        }
+        a = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 21 * ctx.BIG.MODBYTES];
+        }
+        b = ctx.BIG.fromBytes(t);
+        c = new ctx.FP2(a, b); //c.bset(a,b);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 22 * ctx.BIG.MODBYTES];
+        }
+        a = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 23 * ctx.BIG.MODBYTES];
+        }
+        b = ctx.BIG.fromBytes(t);
+        d = new ctx.FP2(a, b); //d.bset(a,b);
+
+        eb = new ctx.FP4(c, d); //e.set(c,d);
+
+        g = new ctx.FP8(ea, eb); //g.set(c,d);
+
+        r = new FP24(e, f, g); //r.set(e,f,g);
+
+        return r;
+    };
+
+    /* return 1 if b==c, no branching */
+    FP24.teq = function(b, c) {
+        var x = b ^ c;
+        x -= 1; // if x=0, x now -1
+        return ((x >> 31) & 1);
+    };
+
+    /* p=q0^u0.q1^u1.q2^u2.q3^u3... */
+    // Bos & Costello https://eprint.iacr.org/2013/458.pdf
+    // Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
+    // Side channel attack secure
+    FP24.pow8 = function(q, u) {
+        var g1 = [],
+            g2 = [],
+            r = new FP24(0),
+            p = new FP24(0),
+            t = [],
+            mt = new ctx.BIG(0),
+            fa = new ctx.BIG(0),
+            fb = new ctx.BIG(0),
+            w1 = [],
+            s1 = [],
+            w2 = [],
+            s2 = [],
+            i, j, k, nb, bt, pb1, pb2, f;
+
+        for (i = 0; i < 8; i++) {
+            t[i] = new ctx.BIG(u[i]); t[i].norm();
+        }
+
+        g1[0] = new FP24(q[0]);  // q[0]
+        g1[1] = new FP24(g1[0]); g1[1].mul(q[1]);   // q[0].q[1]
+        g1[2] = new FP24(g1[0]); g1[2].mul(q[2]);   // q[0].q[2]
+        g1[3] = new FP24(g1[1]); g1[3].mul(q[2]);   // q[0].q[1].q[2]
+        g1[4] = new FP24(q[0]);  g1[4].mul(q[3]);   // q[0].q[3]
+        g1[5] = new FP24(g1[1]); g1[5].mul(q[3]);   // q[0].q[1].q[3]
+        g1[6] = new FP24(g1[2]); g1[6].mul(q[3]);   // q[0].q[2].q[3]
+        g1[7] = new FP24(g1[3]); g1[7].mul(q[3]);   // q[0].q[1].q[2].q[3]
+
+        //  Use Frobenius
+        fa.rcopy(ctx.ROM_FIELD.Fra);
+        fb.rcopy(ctx.ROM_FIELD.Frb);
+        f = new ctx.FP2(fa, fb);
+
+        for (i=0;i<8;i++) {
+            g2[i]=new FP24(g1[i]);
+            g2[i].frob(f,4);
+        }
+
+        // Make it odd
+        pb1=1-t[0].parity();
+        t[0].inc(pb1);
+        t[0].norm();
+
+        pb2=1-t[4].parity();
+        t[4].inc(pb2);
+        t[4].norm();
+
+        // Number of bits
+        mt.zero();
+        for (i=0;i<8;i++) {
+            mt.or(t[i]);
+        }
+
+        nb=1+mt.nbits();
+
+        // Sign pivot
+        s1[nb-1]=1;
+        s2[nb-1]=1;
+        for (i=0;i<nb-1;i++) {
+            t[0].fshr(1);
+            s1[i]=2*t[0].parity()-1;
+            t[4].fshr(1);
+            s2[i]=2*t[4].parity()-1;
+
+        }
+
+        // Recoded exponent
+        for (i=0; i<nb; i++) {
+            w1[i]=0;
+            k=1;
+            for (j=1; j<4; j++) {
+                bt=s1[i]*t[j].parity();
+                t[j].fshr(1);
+                t[j].dec(bt>>1);
+                t[j].norm();
+                w1[i]+=bt*k;
+                k*=2;
+            }
+            w2[i]=0;
+            k=1;
+            for (j=5; j<8; j++) {
+                bt=s2[i]*t[j].parity();
+                t[j].fshr(1);
+                t[j].dec(bt>>1);
+                t[j].norm();
+                w2[i]+=bt*k;
+                k*=2;
+            }
+        }
+
+        // Main loop
+        p.select(g1,2*w1[nb-1]+1);
+        r.select(g2,2*w2[nb-1]+1);
+        p.mul(r);
+        for (i=nb-2;i>=0;i--) {
+            p.usqr();
+            r.select(g1,2*w1[i]+s1[i]);
+            p.mul(r);
+            r.select(g2,2*w2[i]+s2[i]);
+            p.mul(r);
+        }
+
+        // apply correction
+        r.copy(q[0]); r.conj();
+        r.mul(p);
+        p.cmove(r,pb1);
+
+        r.copy(q[4]); r.conj();
+        r.mul(p);
+        p.cmove(r,pb2);
+
+        p.reduce();
+        return p;
+    };
+
+    return FP24;
+};
diff --git a/version3/js/fp4.js b/version3/js/fp4.js
new file mode 100644
index 0000000..ae2a58f
--- /dev/null
+++ b/version3/js/fp4.js
@@ -0,0 +1,642 @@
+/*
+    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.
+*/
+
+/* Finite Field arithmetic  Fp^4 functions */
+
+/* FP4 elements are of the form a+ib, where i is sqrt(-1+sqrt(-1))  */
+
+var FP4 = function(ctx) {
+    "use strict";
+
+    /* general purpose constructor */
+    var FP4 = function(c, d) {
+        if (c instanceof FP4) {
+            this.a = new ctx.FP2(c.a);
+            this.b = new ctx.FP2(c.b);
+        } else {
+            this.a = new ctx.FP2(c);
+            this.b = new ctx.FP2(d);
+        }
+    };
+
+    FP4.prototype = {
+        /* reduce all components of this mod Modulus */
+        reduce: function() {
+            this.a.reduce();
+            this.b.reduce();
+        },
+
+        /* normalise all components of this mod Modulus */
+        norm: function() {
+            this.a.norm();
+            this.b.norm();
+        },
+
+        /* test this==0 ? */
+        iszilch: function() {
+            //this.reduce();
+            return (this.a.iszilch() && this.b.iszilch());
+        },
+
+        /* test this==1 ? */
+        isunity: function() {
+            var one = new ctx.FP2(1);
+            return (this.a.equals(one) && this.b.iszilch());
+        },
+
+        /* conditional copy of g to this depending on d */
+        cmove: function(g, d) {
+            this.a.cmove(g.a, d);
+            this.b.cmove(g.b, d);
+        },
+
+        /* test is w real? That is in a+ib test b is zero */
+        isreal: function() {
+            return this.b.iszilch();
+        },
+
+        /* extract real part a */
+        real: function() {
+            return this.a;
+        },
+
+        geta: function() {
+            return this.a;
+        },
+
+        /* extract imaginary part b */
+        getb: function() {
+            return this.b;
+        },
+
+        /* test this=x? */
+        equals: function(x) {
+            return (this.a.equals(x.a) && this.b.equals(x.b));
+        },
+
+        /* copy this=x */
+        copy: function(x) {
+            this.a.copy(x.a);
+            this.b.copy(x.b);
+        },
+
+        /* this=0 */
+        zero: function() {
+            this.a.zero();
+            this.b.zero();
+        },
+
+        /* this=1 */
+        one: function() {
+            this.a.one();
+            this.b.zero();
+        },
+
+        /* set from two FP2s */
+        set: function(c, d) {
+            this.a.copy(c);
+            this.b.copy(d);
+        },
+
+        /* set a */
+        seta: function(c) {
+            this.a.copy(c);
+            this.b.zero();
+        },
+
+        /* this=-this */
+        neg: function() {
+            this.norm();
+            var m = new ctx.FP2(this.a), //m.copy(this.a);
+                t = new ctx.FP2(0);
+
+            m.add(this.b);
+            m.neg();
+            //  m.norm();
+            t.copy(m);
+            t.add(this.b);
+            this.b.copy(m);
+            this.b.add(this.a);
+            this.a.copy(t);
+            this.norm();
+        },
+
+        /* this=conjugate(this) */
+        conj: function() {
+            this.b.neg();
+            this.norm();
+        },
+
+        /* this=-conjugate(this) */
+        nconj: function() {
+            this.a.neg();
+            this.norm();
+        },
+
+        /* this+=x */
+        add: function(x) {
+            this.a.add(x.a);
+            this.b.add(x.b);
+        },
+
+        /* this-=x */
+        sub: function(x) {
+            var m = new FP4(x); // m.copy(x);
+            m.neg();
+            this.add(m);
+        },
+
+        rsub: function(x) {
+            this.neg();
+            this.add(x);
+        },
+
+        /* this*=s where s is FP2 */
+        pmul: function(s) {
+            this.a.mul(s);
+            this.b.mul(s);
+        },
+
+        /* this*=c where s is int */
+        imul: function(c) {
+            this.a.imul(c);
+            this.b.imul(c);
+        },
+
+        /* this*=this */
+        sqr: function() {
+            // this.norm();
+
+            var t1 = new ctx.FP2(this.a), //t1.copy(this.a)
+                t2 = new ctx.FP2(this.b), //t2.copy(this.b)
+                t3 = new ctx.FP2(this.a); //t3.copy(this.a)
+
+            t3.mul(this.b);
+            t1.add(this.b);
+            t1.norm();
+            t2.mul_ip();
+
+            t2.add(this.a);
+            t2.norm();
+            this.a.copy(t1);
+
+            this.a.mul(t2);
+
+            t2.copy(t3);
+            t2.mul_ip();
+            t2.add(t3);
+            t2.norm();  // ??
+
+            t2.neg();
+
+            this.a.add(t2);
+
+            this.b.copy(t3);
+            this.b.add(t3);
+
+            this.norm();
+        },
+
+        /* this*=y */
+        mul: function(y) {
+            // this.norm();
+
+            var t1 = new ctx.FP2(this.a), //t1.copy(this.a)
+                t2 = new ctx.FP2(this.b), //t2.copy(this.b)
+                t3 = new ctx.FP2(0),
+                t4 = new ctx.FP2(this.b); //t4.copy(this.b)
+
+            t1.mul(y.a);
+            t2.mul(y.b);
+            t3.copy(y.b);
+            t3.add(y.a);
+            t4.add(this.a);
+
+            t3.norm();
+            t4.norm();
+
+            t4.mul(t3);
+
+            t3.copy(t1);
+            t3.neg();
+            t4.add(t3);
+            // t4.norm(); // ??
+
+            // t4.sub(t1);
+
+            t3.copy(t2);
+            t3.neg();
+            this.b.copy(t4);
+            this.b.add(t3);
+
+            t2.mul_ip();
+            this.a.copy(t2);
+            this.a.add(t1);
+
+            this.norm();
+        },
+
+        /* convert to hex string */
+        toString: function() {
+            return ("[" + this.a.toString() + "," + this.b.toString() + "]");
+        },
+
+        /* this=1/this */
+        inverse: function() {
+            this.norm();
+
+            var t1 = new ctx.FP2(this.a), //t1.copy(this.a);
+                t2 = new ctx.FP2(this.b); // t2.copy(this.b);
+
+            t1.sqr();
+            t2.sqr();
+            t2.mul_ip();
+            t2.norm(); // ??
+            t1.sub(t2);
+            t1.inverse();
+            this.a.mul(t1);
+            t1.neg();
+            t1.norm();
+            this.b.mul(t1);
+        },
+
+        /* this*=i where i = sqrt(-1+sqrt(-1)) */
+        times_i: function() {
+            var s = new ctx.FP2(this.b), //s.copy(this.b);
+                t = new ctx.FP2(this.b); //t.copy(this.b);
+
+            s.times_i();
+            t.add(s);
+            this.b.copy(this.a);
+            this.a.copy(t);
+            this.norm();
+        },
+
+        /* this=this^q using Frobenius, where q is Modulus */
+        frob: function(f) {
+            this.a.conj();
+            this.b.conj();
+            this.b.mul(f);
+        },
+
+        /* this=this^e */
+        pow: function(e) {
+            var w = new FP4(this), //w.copy(this);
+                z = new ctx.BIG(e), //z.copy(e);
+                r = new FP4(1),
+                bt;
+			w.norm();
+			z.norm();
+            for (;;) {
+                bt = z.parity();
+                z.fshr(1);
+
+                if (bt === 1) {
+                    r.mul(w);
+                }
+
+                if (z.iszilch()) {
+                    break;
+                }
+
+                w.sqr();
+            }
+            r.reduce();
+
+            return r;
+        },
+
+        /* XTR xtr_a function */
+        xtr_A: function(w, y, z) {
+            var r = new FP4(w), //r.copy(w);
+                t = new FP4(w); //t.copy(w);
+
+            //y.norm(); // ??
+            r.sub(y);
+            r.norm();
+            r.pmul(this.a);
+            t.add(y);
+            t.norm();
+            t.pmul(this.b);
+            t.times_i();
+
+            this.copy(r);
+            this.add(t);
+            this.add(z);
+
+            this.reduce();
+        },
+
+        /* XTR xtr_d function */
+        xtr_D: function() {
+            var w = new FP4(this); //w.copy(this);
+            this.sqr();
+            w.conj();
+            w.add(w); //w.norm(); // ??
+            this.sub(w);
+            this.reduce();
+        },
+
+        /* r=x^n using XTR method on traces of FP12s */
+        xtr_pow: function(n) {
+			var sf = new FP4(this);
+			sf.norm();
+            var a = new FP4(3),
+                b = new FP4(sf),
+                c = new FP4(b),
+                t = new FP4(0),
+                r = new FP4(0),
+                par, v, nb, i;
+
+
+            c.xtr_D();
+
+            //n.norm();
+            par = n.parity();
+            v = new ctx.BIG(n);
+			v.norm();
+            v.fshr(1);
+
+            if (par === 0) {
+                v.dec(1);
+                v.norm();
+            }
+
+            nb = v.nbits();
+            for (i = nb - 1; i >= 0; i--) {
+                if (v.bit(i) != 1) {
+                    t.copy(b);
+                    sf.conj();
+                    c.conj();
+                    b.xtr_A(a, sf, c);
+                    sf.conj();
+                    c.copy(t);
+                    c.xtr_D();
+                    a.xtr_D();
+                } else {
+                    t.copy(a);
+                    t.conj();
+                    a.copy(b);
+                    a.xtr_D();
+                    b.xtr_A(c, sf, t);
+                    c.xtr_D();
+                }
+            }
+
+            if (par === 0) {
+                r.copy(c);
+            } else {
+                r.copy(b);
+            }
+            r.reduce();
+
+            return r;
+        },
+
+        /* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */
+        xtr_pow2: function(ck, ckml, ckm2l, a, b) {
+ 
+            var e = new ctx.BIG(a), //e.copy(a)
+                d = new ctx.BIG(b), //d.copy(b)
+                w = new ctx.BIG(0),
+                cu = new FP4(ck), //cu.copy(ck), // can probably be passed in w/o copying
+                cv = new FP4(this), //cv.copy(this),
+                cumv = new FP4(ckml), //cumv.copy(ckml),
+                cum2v = new FP4(ckm2l), //cum2v.copy(ckm2l),
+                r = new FP4(0),
+                t = new FP4(0),
+                f2 = 0,
+                i;
+
+			e.norm();
+			d.norm();
+
+            while (d.parity() === 0 && e.parity() === 0) {
+                d.fshr(1);
+                e.fshr(1);
+                f2++;
+            }
+
+            while (ctx.BIG.comp(d, e) !== 0) {
+                if (ctx.BIG.comp(d, e) > 0) {
+                    w.copy(e);
+                    w.imul(4);
+                    w.norm();
+
+                    if (ctx.BIG.comp(d, w) <= 0) {
+                        w.copy(d);
+                        d.copy(e);
+                        e.rsub(w);
+                        e.norm();
+
+                        t.copy(cv);
+                        t.xtr_A(cu, cumv, cum2v);
+                        cum2v.copy(cumv);
+                        cum2v.conj();
+                        cumv.copy(cv);
+                        cv.copy(cu);
+                        cu.copy(t);
+
+                    } else if (d.parity() === 0) {
+                        d.fshr(1);
+                        r.copy(cum2v);
+                        r.conj();
+                        t.copy(cumv);
+                        t.xtr_A(cu, cv, r);
+                        cum2v.copy(cumv);
+                        cum2v.xtr_D();
+                        cumv.copy(t);
+                        cu.xtr_D();
+                    } else if (e.parity() == 1) {
+                        d.sub(e);
+                        d.norm();
+                        d.fshr(1);
+                        t.copy(cv);
+                        t.xtr_A(cu, cumv, cum2v);
+                        cu.xtr_D();
+                        cum2v.copy(cv);
+                        cum2v.xtr_D();
+                        cum2v.conj();
+                        cv.copy(t);
+                    } else {
+                        w.copy(d);
+                        d.copy(e);
+                        d.fshr(1);
+                        e.copy(w);
+                        t.copy(cumv);
+                        t.xtr_D();
+                        cumv.copy(cum2v);
+                        cumv.conj();
+                        cum2v.copy(t);
+                        cum2v.conj();
+                        t.copy(cv);
+                        t.xtr_D();
+                        cv.copy(cu);
+                        cu.copy(t);
+                    }
+                }
+                if (ctx.BIG.comp(d, e) < 0) {
+                    w.copy(d);
+                    w.imul(4);
+                    w.norm();
+
+                    if (ctx.BIG.comp(e, w) <= 0) {
+                        e.sub(d);
+                        e.norm();
+                        t.copy(cv);
+                        t.xtr_A(cu, cumv, cum2v);
+                        cum2v.copy(cumv);
+                        cumv.copy(cu);
+                        cu.copy(t);
+                    } else if (e.parity() === 0) {
+                        w.copy(d);
+                        d.copy(e);
+                        d.fshr(1);
+                        e.copy(w);
+                        t.copy(cumv);
+                        t.xtr_D();
+                        cumv.copy(cum2v);
+                        cumv.conj();
+                        cum2v.copy(t);
+                        cum2v.conj();
+                        t.copy(cv);
+                        t.xtr_D();
+                        cv.copy(cu);
+                        cu.copy(t);
+                    } else if (d.parity() == 1) {
+                        w.copy(e);
+                        e.copy(d);
+                        w.sub(d);
+                        w.norm();
+                        d.copy(w);
+                        d.fshr(1);
+                        t.copy(cv);
+                        t.xtr_A(cu, cumv, cum2v);
+                        cumv.conj();
+                        cum2v.copy(cu);
+                        cum2v.xtr_D();
+                        cum2v.conj();
+                        cu.copy(cv);
+                        cu.xtr_D();
+                        cv.copy(t);
+                    } else {
+                        d.fshr(1);
+                        r.copy(cum2v);
+                        r.conj();
+                        t.copy(cumv);
+                        t.xtr_A(cu, cv, r);
+                        cum2v.copy(cumv);
+                        cum2v.xtr_D();
+                        cumv.copy(t);
+                        cu.xtr_D();
+                    }
+                }
+            }
+            r.copy(cv);
+            r.xtr_A(cu, cumv, cum2v);
+            for (i = 0; i < f2; i++) {
+                r.xtr_D();
+            }
+            r = r.xtr_pow(d);
+            return r;
+        },
+
+        /* New stuff for ecp4.js */
+
+        div2: function() {
+            this.a.div2();
+            this.b.div2();
+        },
+
+        div_i: function() {
+            var u=new ctx.FP2(this.a),
+                v=new ctx.FP2(this.b);
+            u.div_ip();
+            this.a.copy(v);
+            this.b.copy(u);
+        },
+
+        div_2i: function() {
+            var u=new ctx.FP2(this.a),
+                v=new ctx.FP2(this.b);
+            u.div_ip2();
+            v.add(v); v.norm();
+            this.a.copy(v);
+            this.b.copy(u);
+        },
+
+        qmul: function(s) {
+            this.a.pmul(s);
+            this.b.pmul(s);
+        },
+
+        sqrt: function() {
+            if (this.iszilch()) {
+                return true;
+            }
+            var wa=new ctx.FP2(this.a),
+                ws=new ctx.FP2(this.b),
+                wt=new ctx.FP2(this.a);
+            if (ws.iszilch()) {
+                if (wt.sqrt()) {
+                    this.a.copy(wt);
+                    this.b.zero();
+                } else {
+                    wt.div_ip();
+                    wt.sqrt();
+                    this.b.copy(wt);
+                    this.a.zero();
+                }
+                return true;
+            }
+
+            ws.sqr();
+            wa.sqr();
+            ws.mul_ip();
+            ws.norm();
+            wa.sub(ws);
+
+            ws.copy(wa);
+            if (!ws.sqrt()) {
+                return false;
+            }
+
+            wa.copy(wt); wa.add(ws); wa.norm(); wa.div2();
+
+            if (!wa.sqrt()) {
+                wa.copy(wt); wa.sub(ws); wa.norm(); wa.div2();
+                if (!wa.sqrt()) {
+                    return false;
+                }
+            }
+            wt.copy(this.b);
+            ws.copy(wa); ws.add(wa);
+            ws.inverse();
+
+            wt.mul(ws);
+            this.a.copy(wa);
+            this.b.copy(wt);
+
+            return true;
+        }
+
+    };
+
+    return FP4;
+};
diff --git a/version3/js/fp48.js b/version3/js/fp48.js
new file mode 100644
index 0000000..9fe7c05
--- /dev/null
+++ b/version3/js/fp48.js
@@ -0,0 +1,1271 @@
+/*
+    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.
+*/
+
+/* AMCL Fp^48 functions */
+
+/* FP48 elements are of the form a+i.b+i^2.c */
+
+var FP48 = function(ctx) {
+    "use strict";
+
+    /* general purpose constructor */
+    var FP48 = function(d, e, f) {
+        if (d instanceof FP48) {
+            this.a = new ctx.FP16(d.a);
+            this.b = new ctx.FP16(d.b);
+            this.c = new ctx.FP16(d.c);
+        } else {
+            this.a = new ctx.FP16(d);
+            this.b = new ctx.FP16(e);
+            this.c = new ctx.FP16(f);
+        }
+    };
+
+    FP48.prototype = {
+        /* reduce all components of this mod Modulus */
+        reduce: function() {
+            this.a.reduce();
+            this.b.reduce();
+            this.c.reduce();
+        },
+
+        /* normalize all components of this mod Modulus */
+        norm: function() {
+            this.a.norm();
+            this.b.norm();
+            this.c.norm();
+        },
+
+        /* test x==0 ? */
+        iszilch: function() {
+            //this.reduce();
+            return (this.a.iszilch() && this.b.iszilch() && this.c.iszilch());
+        },
+
+        /* test x==1 ? */
+        isunity: function() {
+            var one = new ctx.FP16(1);
+            return (this.a.equals(one) && this.b.iszilch() && this.c.iszilch());
+        },
+
+        /* conditional copy of g to this depending on d */
+        cmove: function(g, d) {
+            this.a.cmove(g.a, d);
+            this.b.cmove(g.b, d);
+            this.c.cmove(g.c, d);
+        },
+
+        /* Constant time select from pre-computed table */
+        select: function(g, b) {
+            var invf = new FP48(0),
+                m, babs;
+
+            m = b >> 31;
+            babs = (b ^ m) - m;
+            babs = (babs - 1) / 2;
+
+            this.cmove(g[0], FP48.teq(babs, 0)); // conditional move
+            this.cmove(g[1], FP48.teq(babs, 1));
+            this.cmove(g[2], FP48.teq(babs, 2));
+            this.cmove(g[3], FP48.teq(babs, 3));
+            this.cmove(g[4], FP48.teq(babs, 4));
+            this.cmove(g[5], FP48.teq(babs, 5));
+            this.cmove(g[6], FP48.teq(babs, 6));
+            this.cmove(g[7], FP48.teq(babs, 7));
+
+            invf.copy(this);
+            invf.conj();
+            this.cmove(invf, (m & 1));
+        },
+
+        /* extract a from this */
+        geta: function() {
+            return this.a;
+        },
+
+        /* extract b */
+        getb: function() {
+            return this.b;
+        },
+
+        /* extract c */
+        getc: function() {
+            return this.c;
+        },
+
+        /* return 1 if x==y, else 0 */
+        equals: function(x) {
+            return (this.a.equals(x.a) && this.b.equals(x.b) && this.c.equals(x.c));
+        },
+
+        /* copy this=x */
+        copy: function(x) {
+            this.a.copy(x.a);
+            this.b.copy(x.b);
+            this.c.copy(x.c);
+        },
+
+        /* set this=1 */
+        one: function() {
+            this.a.one();
+            this.b.zero();
+            this.c.zero();
+        },
+
+        /* this=conj(this) */
+        conj: function() {
+            this.a.conj();
+            this.b.nconj();
+            this.c.conj();
+        },
+
+        /* set this from 3 FP16s */
+        set: function(d, e, f) {
+            this.a.copy(d);
+            this.b.copy(e);
+            this.c.copy(f);
+        },
+
+        /* set this from one ctx.FP16 */
+        seta: function(d) {
+            this.a.copy(d);
+            this.b.zero();
+            this.c.zero();
+        },
+
+        /* Granger-Scott Unitary Squaring */
+        usqr: function() {
+            var A = new ctx.FP16(this.a), //A.copy(this.a)
+                B = new ctx.FP16(this.c), //B.copy(this.c)
+                C = new ctx.FP16(this.b), //C.copy(this.b)
+                D = new ctx.FP16(0);
+
+            this.a.sqr();
+            D.copy(this.a);
+            D.add(this.a);
+            this.a.add(D);
+
+            A.nconj();
+
+            A.add(A);
+            this.a.add(A);
+            B.sqr();
+            B.times_i();
+
+            D.copy(B);
+            D.add(B);
+            B.add(D);
+
+            C.sqr();
+            D.copy(C);
+            D.add(C);
+            C.add(D);
+
+            this.b.conj();
+            this.b.add(this.b);
+            this.c.nconj();
+
+            this.c.add(this.c);
+            this.b.add(B);
+            this.c.add(C);
+            this.reduce();
+        },
+
+        /* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
+        sqr: function() {
+            var A = new ctx.FP16(this.a), //A.copy(this.a)
+                B = new ctx.FP16(this.b), //B.copy(this.b)
+                C = new ctx.FP16(this.c), //C.copy(this.c)
+                D = new ctx.FP16(this.a); //D.copy(this.a)
+
+            A.sqr();
+            B.mul(this.c);
+            B.add(B); //B.norm();
+            C.sqr();
+            D.mul(this.b);
+            D.add(D);
+
+            this.c.add(this.a);
+            this.c.add(this.b);
+            this.c.norm();
+            this.c.sqr();
+
+            this.a.copy(A);
+
+            A.add(B);
+            A.add(C);
+            A.add(D);
+            A.neg();
+            B.times_i();
+            C.times_i();
+
+            this.a.add(B);
+            this.b.copy(C);
+            this.b.add(D);
+            this.c.add(A);
+
+            this.norm();
+        },
+
+        /* FP48 full multiplication this=this*y */
+        mul: function(y) {
+            var z0 = new ctx.FP16(this.a), //z0.copy(this.a)
+                z1 = new ctx.FP16(0),
+                z2 = new ctx.FP16(this.b), //z2.copy(this.b)
+                z3 = new ctx.FP16(0),
+                t0 = new ctx.FP16(this.a), //t0.copy(this.a)
+                t1 = new ctx.FP16(y.a); //t1.copy(y.a)
+
+            z0.mul(y.a);
+            z2.mul(y.b);
+
+            t0.add(this.b);
+            t1.add(y.b);
+
+            t0.norm();
+            t1.norm();
+
+            z1.copy(t0);
+            z1.mul(t1);
+            t0.copy(this.b);
+            t0.add(this.c);
+
+            t1.copy(y.b);
+            t1.add(y.c);
+
+            t0.norm();
+            t1.norm();
+            z3.copy(t0);
+            z3.mul(t1);
+
+            t0.copy(z0);
+            t0.neg();
+            t1.copy(z2);
+            t1.neg();
+
+            z1.add(t0);
+            this.b.copy(z1);
+            this.b.add(t1);
+
+            z3.add(t1);
+            z2.add(t0);
+
+            t0.copy(this.a);
+            t0.add(this.c);
+            t1.copy(y.a);
+            t1.add(y.c);
+
+            t0.norm();
+            t1.norm();
+
+            t0.mul(t1);
+            z2.add(t0);
+
+            t0.copy(this.c);
+            t0.mul(y.c);
+            t1.copy(t0);
+            t1.neg();
+
+            this.c.copy(z2);
+            this.c.add(t1);
+            z3.add(t1);
+            t0.times_i();
+            this.b.add(t0);
+            // z3.norm();
+            z3.times_i();
+            this.a.copy(z0);
+            this.a.add(z3);
+
+            this.norm();
+        },
+
+        /* Special case this*=y that arises from special form of ATE pairing line function */
+        smul: function(y, twist) {
+            var z0, z1, z2, z3, t0, t1;
+
+            if (twist == ctx.ECP.D_TYPE) {
+                z0 = new ctx.FP16(this.a), //z0.copy(this.a);
+                z2 = new ctx.FP16(this.b), //z2.copy(this.b);
+                z3 = new ctx.FP16(this.b), //z3.copy(this.b);
+                t0 = new ctx.FP16(0),
+                t1 = new ctx.FP16(y.a); //t1.copy(y.a);
+
+                z0.mul(y.a);
+                z2.pmul(y.b.real());
+                this.b.add(this.a);
+                t1.real().add(y.b.real());
+
+                this.b.norm();
+                t1.norm();
+
+                this.b.mul(t1);
+                z3.add(this.c);
+                z3.norm();
+                z3.pmul(y.b.real());
+
+                t0.copy(z0);
+                t0.neg();
+                t1.copy(z2);
+                t1.neg();
+
+                this.b.add(t0);
+
+                this.b.add(t1);
+                z3.add(t1);
+                z2.add(t0);
+
+                t0.copy(this.a);
+                t0.add(this.c);
+                t0.norm();
+                t0.mul(y.a);
+                this.c.copy(z2);
+                this.c.add(t0);
+
+                z3.times_i();
+                this.a.copy(z0);
+                this.a.add(z3);
+            }
+
+            if (twist == ctx.ECP.M_TYPE) {
+                z0=new ctx.FP16(this.a);
+                z1=new ctx.FP16(0);
+                z2=new ctx.FP16(0);
+                z3=new ctx.FP16(0);
+                t0=new ctx.FP16(this.a);
+                t1=new ctx.FP16(0);
+
+                z0.mul(y.a);
+                t0.add(this.b);
+                t0.norm();
+
+                z1.copy(t0); z1.mul(y.a);
+                t0.copy(this.b); t0.add(this.c);
+                t0.norm();
+
+                z3.copy(t0); //z3.mul(y.c);
+                z3.pmul(y.c.getb());
+                z3.times_i();
+
+                t0.copy(z0); t0.neg();
+
+                z1.add(t0);
+                this.b.copy(z1);
+                z2.copy(t0);
+
+                t0.copy(this.a); t0.add(this.c);
+                t1.copy(y.a); t1.add(y.c);
+
+                t0.norm();
+                t1.norm();
+
+                t0.mul(t1);
+                z2.add(t0);
+
+                t0.copy(this.c);
+
+                t0.pmul(y.c.getb());
+                t0.times_i();
+
+                t1.copy(t0); t1.neg();
+
+                this.c.copy(z2); this.c.add(t1);
+                z3.add(t1);
+                t0.times_i();
+                this.b.add(t0);
+                z3.norm();
+                z3.times_i();
+                this.a.copy(z0); this.a.add(z3);
+            }
+
+            this.norm();
+        },
+
+        /* this=1/this */
+        inverse: function() {
+            var f0 = new ctx.FP16(this.a), //f0.copy(this.a)
+                f1 = new ctx.FP16(this.b), //f1.copy(this.b)
+                f2 = new ctx.FP16(this.a), //f2.copy(this.a)
+                f3 = new ctx.FP16(0);
+
+            f0.sqr();
+            f1.mul(this.c);
+            f1.times_i();
+            f0.sub(f1);
+            f0.norm();
+
+            f1.copy(this.c);
+            f1.sqr();
+            f1.times_i();
+            f2.mul(this.b);
+            f1.sub(f2);
+            f1.norm();
+
+            f2.copy(this.b);
+            f2.sqr();
+            f3.copy(this.a);
+            f3.mul(this.c);
+            f2.sub(f3);
+            f2.norm();
+
+            f3.copy(this.b);
+            f3.mul(f2);
+            f3.times_i();
+            this.a.mul(f0);
+            f3.add(this.a);
+            this.c.mul(f1);
+            this.c.times_i();
+
+            f3.add(this.c);
+            f3.norm();
+            f3.inverse();
+            this.a.copy(f0);
+            this.a.mul(f3);
+            this.b.copy(f1);
+            this.b.mul(f3);
+            this.c.copy(f2);
+            this.c.mul(f3);
+        },
+
+        /* this=this^p, where p=Modulus, using Frobenius */
+        frob: function(f,n) {
+            var f2 = new ctx.FP2(f),
+                f3 = new ctx.FP2(f),
+                i;
+
+            f2.sqr();
+            f3.mul(f2);
+
+            f3.mul_ip(); f3.norm();
+            f3.mul_ip(); f3.norm();
+
+            for (i=0;i<n;i++) {
+                this.a.frob(f3);
+                this.b.frob(f3);
+                this.c.frob(f3);
+
+                this.b.qmul(f); this.b.times_i4(); this.b.times_i2();
+                this.c.qmul(f2); this.c.times_i4(); this.c.times_i4(); this.c.times_i4();
+            }
+        },
+
+        /* trace function */
+        trace: function() {
+            var t = new ctx.FP16(0);
+
+            t.copy(this.a);
+            t.imul(3);
+            t.reduce();
+
+            return t;
+        },
+
+        /* convert this to hex string */
+        toString: function() {
+            return ("[" + this.a.toString() + "," + this.b.toString() + "," + this.c.toString() + "]");
+        },
+
+        /* convert this to byte array */
+        toBytes: function(w) {
+            var t = [],
+                i;
+
+            this.a.geta().geta().geta().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i] = t[i];
+            }
+            this.a.geta().geta().geta().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + ctx.BIG.MODBYTES] = t[i];
+            }
+            this.a.geta().geta().getb().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 2 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.a.geta().geta().getb().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 3 * ctx.BIG.MODBYTES] = t[i];
+            }
+
+            this.a.geta().getb().geta().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 4 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.a.geta().getb().geta().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 5 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.a.geta().getb().getb().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 6 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.a.geta().getb().getb().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 7 * ctx.BIG.MODBYTES] = t[i];
+            }
+
+            this.a.getb().geta().geta().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 8 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.a.getb().geta().geta().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 9 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.a.getb().geta().getb().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 10 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.a.getb().geta().getb().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 11 * ctx.BIG.MODBYTES] = t[i];
+            }
+
+            this.a.getb().getb().geta().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 12 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.a.getb().getb().geta().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 13 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.a.getb().getb().getb().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 14 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.a.getb().getb().getb().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 15 * ctx.BIG.MODBYTES] = t[i];
+            }
+
+            this.b.geta().geta().geta().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 16 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.b.geta().geta().geta().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 17 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.b.geta().geta().getb().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 18 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.b.geta().geta().getb().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 19 * ctx.BIG.MODBYTES] = t[i];
+            }
+
+            this.b.geta().getb().geta().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 20 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.b.geta().getb().geta().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 21 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.b.geta().getb().getb().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 22 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.b.geta().getb().getb().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 23 * ctx.BIG.MODBYTES] = t[i];
+            }
+
+            this.b.getb().geta().geta().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 24 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.b.getb().geta().geta().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 25 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.b.getb().geta().getb().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 26 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.b.getb().geta().getb().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 27 * ctx.BIG.MODBYTES] = t[i];
+            }
+
+            this.b.getb().getb().geta().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 28 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.b.getb().getb().geta().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 29 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.b.getb().getb().getb().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 30 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.b.getb().getb().getb().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 31 * ctx.BIG.MODBYTES] = t[i];
+            }
+
+            this.c.geta().geta().geta().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 32 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.c.geta().geta().geta().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 33 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.c.geta().geta().getb().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 34 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.c.geta().geta().getb().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 35 * ctx.BIG.MODBYTES] = t[i];
+            }
+
+            this.c.geta().getb().geta().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 36 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.c.geta().getb().geta().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 37 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.c.geta().getb().getb().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 38 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.c.geta().getb().getb().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 39 * ctx.BIG.MODBYTES] = t[i];
+            }
+
+            this.c.getb().geta().geta().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 40 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.c.getb().geta().geta().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 41 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.c.getb().geta().getb().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 42 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.c.getb().geta().getb().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 43 * ctx.BIG.MODBYTES] = t[i];
+            }
+
+            this.c.getb().getb().geta().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 44 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.c.getb().getb().geta().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 45 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.c.getb().getb().getb().getA().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 46 * ctx.BIG.MODBYTES] = t[i];
+            }
+            this.c.getb().getb().getb().getB().toBytes(t);
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+                w[i + 47 * ctx.BIG.MODBYTES] = t[i];
+            }
+        },
+
+        /* set this=this^e */
+        pow: function(e) {
+            var e1, e3, w, nb, i, bt, sf;
+
+			sf = new FP48(this);
+            sf.norm();
+			e1 = new ctx.BIG(e);
+            e1.norm();
+
+            e3 = new ctx.BIG(e1);
+            e3.pmul(3);
+            e3.norm();
+
+            w = new FP48(sf); //w.copy(this);
+            nb = e3.nbits();
+
+            for (i = nb - 2; i >= 1; i--) {
+                w.usqr();
+                bt = e3.bit(i) - e1.bit(i);
+
+                if (bt == 1) {
+                    w.mul(sf);
+                }
+                if (bt == -1) {
+                    sf.conj();
+                    w.mul(sf);
+                    sf.conj();
+                }
+            }
+            w.reduce();
+
+            return w;
+        },
+
+        /* constant time powering by small integer of max length bts */
+        pinpow: function(e, bts) {
+            var R = [],
+                i, b;
+
+            R[0] = new FP48(1);
+            R[1] = new FP48(this);
+
+            for (i = bts - 1; i >= 0; i--) {
+                b = (e >> i) & 1;
+                R[1 - b].mul(R[b]);
+                R[b].usqr();
+            }
+
+            this.copy(R[0]);
+        },
+
+        /* Faster compressed powering for unitary elements */
+        compow: function(e, r) {
+            var fa, fb, f, q, m, a, b, g1, g2, c, cp, cpm1, cpm2;
+
+            fa = new ctx.BIG(0);
+            fa.rcopy(ctx.ROM_FIELD.Fra);
+            fb = new ctx.BIG(0);
+            fb.rcopy(ctx.ROM_FIELD.Frb);
+            f = new ctx.FP2(fa, fb);
+
+            q = new ctx.BIG(0);
+            q.rcopy(ctx.ROM_FIELD.Modulus);
+
+            m = new ctx.BIG(q);
+            m.mod(r);
+
+            a = new ctx.BIG(e);
+            a.mod(m);
+
+            b = new ctx.BIG(e);
+            b.div(m);
+
+            g1 = new FP48(0);
+            g2 = new FP48(0);
+            g1.copy(this);
+
+            c = g1.trace();
+
+            if (b.iszilch()) {
+                c=c.xtr_pow(e);
+                return c;
+            }
+
+            g2.copy(g1);
+            g2.frob(f,1);
+            cp = g2.trace();
+            g1.conj();
+            g2.mul(g1);
+            cpm1 = g2.trace();
+            g2.mul(g1);
+            cpm2 = g2.trace();
+
+            c = c.xtr_pow2(cp, cpm1, cpm2, a, b);
+            return c;
+        }
+    };
+
+    /* convert from byte array to FP12 */
+    FP48.fromBytes = function(w) {
+        var t = [],
+            i, a, b, c, d, e, f, g, r, ea, eb, fa, fb;
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i];
+        }
+        a = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + ctx.BIG.MODBYTES];
+        }
+        b = ctx.BIG.fromBytes(t);
+        c = new ctx.FP2(a, b); //c.bset(a,b);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 2 * ctx.BIG.MODBYTES];
+        }
+        a = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 3 * ctx.BIG.MODBYTES];
+        }
+        b = ctx.BIG.fromBytes(t);
+        d = new ctx.FP2(a, b); //d.bset(a,b);
+
+        ea = new ctx.FP4(c, d); //e.set(c,d);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 4 * ctx.BIG.MODBYTES];
+        }
+        a = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 5 * ctx.BIG.MODBYTES];
+        }
+        b = ctx.BIG.fromBytes(t);
+        c = new ctx.FP2(a, b); //c.bset(a,b);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 6 * ctx.BIG.MODBYTES];
+        }
+        a = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 7 * ctx.BIG.MODBYTES];
+        }
+        b = ctx.BIG.fromBytes(t);
+        d = new ctx.FP2(a, b); //d.bset(a,b);
+
+        eb = new ctx.FP4(c, d); //e.set(c,d);
+
+        fa = new ctx.FP8(ea,eb);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 8 * ctx.BIG.MODBYTES];
+        }
+        a = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 9 * ctx.BIG.MODBYTES];
+        }
+        b = ctx.BIG.fromBytes(t);
+        c = new ctx.FP2(a, b); //c.bset(a,b);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 10 * ctx.BIG.MODBYTES];
+        }
+        a = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 11 * ctx.BIG.MODBYTES];
+        }
+        b = ctx.BIG.fromBytes(t);
+        d = new ctx.FP2(a, b); //d.bset(a,b);
+
+        ea = new ctx.FP4(c, d); //e.set(c,d);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 12 * ctx.BIG.MODBYTES];
+        }
+        a = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 13 * ctx.BIG.MODBYTES];
+        }
+        b = ctx.BIG.fromBytes(t);
+        c = new ctx.FP2(a, b); //c.bset(a,b);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 14 * ctx.BIG.MODBYTES];
+        }
+        a = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 15 * ctx.BIG.MODBYTES];
+        }
+        b = ctx.BIG.fromBytes(t);
+        d = new ctx.FP2(a, b); //d.bset(a,b);
+
+        eb = new ctx.FP4(c, d); //e.set(c,d);
+
+        fb = new ctx.FP8(ea,eb);
+
+        e = new ctx.FP16(fa,fb);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 16 * ctx.BIG.MODBYTES];
+        }
+        a = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 17 * ctx.BIG.MODBYTES];
+        }
+        b = ctx.BIG.fromBytes(t);
+        c = new ctx.FP2(a, b); //c.bset(a,b);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 18 * ctx.BIG.MODBYTES];
+        }
+        a = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 19 * ctx.BIG.MODBYTES];
+        }
+        b = ctx.BIG.fromBytes(t);
+        d = new ctx.FP2(a, b);
+
+        ea = new ctx.FP4(c, d); //e.set(c,d);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 20 * ctx.BIG.MODBYTES];
+        }
+        a = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 21 * ctx.BIG.MODBYTES];
+        }
+        b = ctx.BIG.fromBytes(t);
+        c = new ctx.FP2(a, b); //c.bset(a,b);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 22 * ctx.BIG.MODBYTES];
+        }
+        a = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 23 * ctx.BIG.MODBYTES];
+        }
+        b = ctx.BIG.fromBytes(t);
+        d = new ctx.FP2(a, b);
+
+        eb = new ctx.FP4(c, d); //e.set(c,d);
+
+        fa = new ctx.FP8(ea,eb);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 24 * ctx.BIG.MODBYTES];
+        }
+        a = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 25 * ctx.BIG.MODBYTES];
+        }
+        b = ctx.BIG.fromBytes(t);
+        c = new ctx.FP2(a, b); //c.bset(a,b);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 26 * ctx.BIG.MODBYTES];
+        }
+        a = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 27 * ctx.BIG.MODBYTES];
+        }
+        b = ctx.BIG.fromBytes(t);
+        d = new ctx.FP2(a, b);
+
+        ea = new ctx.FP4(c, d); //e.set(c,d);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 28 * ctx.BIG.MODBYTES];
+        }
+        a = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 29 * ctx.BIG.MODBYTES];
+        }
+        b = ctx.BIG.fromBytes(t);
+        c = new ctx.FP2(a, b); //c.bset(a,b);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 30 * ctx.BIG.MODBYTES];
+        }
+        a = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 31 * ctx.BIG.MODBYTES];
+        }
+        b = ctx.BIG.fromBytes(t);
+        d = new ctx.FP2(a, b);
+
+        eb = new ctx.FP4(c, d); //e.set(c,d);
+
+        fb = new ctx.FP8(ea,eb);
+
+        f = new ctx.FP16(fa, fb); //f.set(c,d);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 32 * ctx.BIG.MODBYTES];
+        }
+        a = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 33 * ctx.BIG.MODBYTES];
+        }
+        b = ctx.BIG.fromBytes(t);
+        c = new ctx.FP2(a, b); //c.bset(a,b);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 34 * ctx.BIG.MODBYTES];
+        }
+        a = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 35 * ctx.BIG.MODBYTES];
+        }
+        b = ctx.BIG.fromBytes(t);
+        d = new ctx.FP2(a, b); //d.bset(a,b);
+
+        ea = new ctx.FP4(c, d); //e.set(c,d);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 36 * ctx.BIG.MODBYTES];
+        }
+        a = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 37 * ctx.BIG.MODBYTES];
+        }
+        b = ctx.BIG.fromBytes(t);
+        c = new ctx.FP2(a, b); //c.bset(a,b);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 38 * ctx.BIG.MODBYTES];
+        }
+        a = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 39 * ctx.BIG.MODBYTES];
+        }
+        b = ctx.BIG.fromBytes(t);
+        d = new ctx.FP2(a, b); //d.bset(a,b);
+
+        eb = new ctx.FP4(c, d); //e.set(c,d);
+
+        fa = new ctx.FP8(ea,eb);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 40 * ctx.BIG.MODBYTES];
+        }
+        a = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 41 * ctx.BIG.MODBYTES];
+        }
+        b = ctx.BIG.fromBytes(t);
+        c = new ctx.FP2(a, b); //c.bset(a,b);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 42 * ctx.BIG.MODBYTES];
+        }
+        a = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 43 * ctx.BIG.MODBYTES];
+        }
+        b = ctx.BIG.fromBytes(t);
+        d = new ctx.FP2(a, b); //d.bset(a,b);
+
+        ea = new ctx.FP4(c, d); //e.set(c,d);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 44 * ctx.BIG.MODBYTES];
+        }
+        a = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 45 * ctx.BIG.MODBYTES];
+        }
+        b = ctx.BIG.fromBytes(t);
+        c = new ctx.FP2(a, b); //c.bset(a,b);
+
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 46 * ctx.BIG.MODBYTES];
+        }
+        a = ctx.BIG.fromBytes(t);
+        for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+            t[i] = w[i + 47 * ctx.BIG.MODBYTES];
+        }
+        b = ctx.BIG.fromBytes(t);
+        d = new ctx.FP2(a, b); //d.bset(a,b);
+
+        eb = new ctx.FP4(c, d); //e.set(c,d);
+
+        fb = new ctx.FP8(ea,eb);
+
+        g = new ctx.FP16(fa, fb); //g.set(c,d);
+
+        r = new FP48(e, f, g); //r.set(e,f,g);
+
+        return r;
+    };
+
+    /* return 1 if b==c, no branching */
+    FP48.teq = function(b, c) {
+        var x = b ^ c;
+        x -= 1; // if x=0, x now -1
+        return ((x >> 31) & 1);
+    };
+
+    /* p=q0^u0.q1^u1.q2^u2.q3^u3... */
+    // Bos & Costello https://eprint.iacr.org/2013/458.pdf
+    // Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
+    // Side channel attack secure
+    FP48.pow16 = function(q, u) {
+        var g1 = [],
+            g2 = [],
+            g3 = [],
+            g4 = [],
+            r = new FP48(0),
+            p = new FP48(0),
+            t = [],
+            mt = new ctx.BIG(0),
+            fa = new ctx.BIG(0),
+            fb = new ctx.BIG(0),
+            w1 = [],
+            s1 = [],
+            w2 = [],
+            s2 = [],
+            w3 = [],
+            s3 = [],
+            w4 = [],
+            s4 = [],
+            i, j, k, nb, bt, pb1, pb2, pb3, pb4, f;
+
+        for (i = 0; i < 16; i++) {
+            t[i] = new ctx.BIG(u[i]); t[i].norm();
+        }
+
+        g1[0] = new FP48(q[0]);  // q[0]
+        g1[1] = new FP48(g1[0]); g1[1].mul(q[1]);   // q[0].q[1]
+        g1[2] = new FP48(g1[0]); g1[2].mul(q[2]);   // q[0].q[2]
+        g1[3] = new FP48(g1[1]); g1[3].mul(q[2]);   // q[0].q[1].q[2]
+        g1[4] = new FP48(q[0]);  g1[4].mul(q[3]);   // q[0].q[3]
+        g1[5] = new FP48(g1[1]); g1[5].mul(q[3]);   // q[0].q[1].q[3]
+        g1[6] = new FP48(g1[2]); g1[6].mul(q[3]);   // q[0].q[2].q[3]
+        g1[7] = new FP48(g1[3]); g1[7].mul(q[3]);   // q[0].q[1].q[2].q[3]
+
+        //  Use Frobenius
+        fa.rcopy(ctx.ROM_FIELD.Fra);
+        fb.rcopy(ctx.ROM_FIELD.Frb);
+        f = new ctx.FP2(fa, fb);
+
+        for (i=0;i<8;i++) {
+            g2[i]=new FP48(g1[i]);
+            g2[i].frob(f,4);
+            g3[i]=new FP48(g2[i]);
+            g3[i].frob(f,4);
+            g4[i]=new FP48(g3[i]);
+            g4[i].frob(f,4);
+
+        }
+
+        // Make it odd
+        pb1=1-t[0].parity();
+        t[0].inc(pb1);
+        t[0].norm();
+
+        pb2=1-t[4].parity();
+        t[4].inc(pb2);
+        t[4].norm();
+
+        pb3=1-t[8].parity();
+        t[8].inc(pb3);
+        t[8].norm();
+
+        pb4=1-t[12].parity();
+        t[12].inc(pb4);
+        t[12].norm();
+
+        // Number of bits
+        mt.zero();
+        for (i=0;i<16;i++) {
+            mt.or(t[i]);
+        }
+
+        nb=1+mt.nbits();
+
+        // Sign pivot
+        s1[nb-1]=1;
+        s2[nb-1]=1;
+        s3[nb-1]=1;
+        s4[nb-1]=1;
+        for (i=0;i<nb-1;i++) {
+            t[0].fshr(1);
+            s1[i]=2*t[0].parity()-1;
+            t[4].fshr(1);
+            s2[i]=2*t[4].parity()-1;
+            t[8].fshr(1);
+            s3[i]=2*t[8].parity()-1;
+            t[12].fshr(1);
+            s4[i]=2*t[12].parity()-1;
+
+        }
+
+        // Recoded exponent
+        for (i=0; i<nb; i++) {
+            w1[i]=0;
+            k=1;
+            for (j=1; j<4; j++) {
+                bt=s1[i]*t[j].parity();
+                t[j].fshr(1);
+                t[j].dec(bt>>1);
+                t[j].norm();
+                w1[i]+=bt*k;
+                k*=2;
+            }
+            w2[i]=0;
+            k=1;
+            for (j=5; j<8; j++) {
+                bt=s2[i]*t[j].parity();
+                t[j].fshr(1);
+                t[j].dec(bt>>1);
+                t[j].norm();
+                w2[i]+=bt*k;
+                k*=2;
+            }
+            w3[i]=0;
+            k=1;
+            for (j=9; j<12; j++) {
+                bt=s3[i]*t[j].parity();
+                t[j].fshr(1);
+                t[j].dec(bt>>1);
+                t[j].norm();
+                w3[i]+=bt*k;
+                k*=2;
+            }
+            w4[i]=0;
+            k=1;
+            for (j=13; j<16; j++) {
+                bt=s4[i]*t[j].parity();
+                t[j].fshr(1);
+                t[j].dec(bt>>1);
+                t[j].norm();
+                w4[i]+=bt*k;
+                k*=2;
+            }
+        }
+
+        // Main loop
+        p.select(g1,2*w1[nb-1]+1);
+        r.select(g2,2*w2[nb-1]+1);
+        p.mul(r);
+        r.select(g3,2*w3[nb-1]+1);
+        p.mul(r);
+        r.select(g4,2*w4[nb-1]+1);
+        p.mul(r);
+        for (i=nb-2;i>=0;i--) {
+            p.usqr();
+            r.select(g1,2*w1[i]+s1[i]);
+            p.mul(r);
+            r.select(g2,2*w2[i]+s2[i]);
+            p.mul(r);
+            r.select(g3,2*w3[i]+s3[i]);
+            p.mul(r);
+            r.select(g4,2*w4[i]+s4[i]);
+            p.mul(r);
+        }
+
+        // apply correction
+        r.copy(q[0]); r.conj();
+        r.mul(p);
+        p.cmove(r,pb1);
+
+        r.copy(q[4]); r.conj();
+        r.mul(p);
+        p.cmove(r,pb2);
+
+        r.copy(q[8]); r.conj();
+        r.mul(p);
+        p.cmove(r,pb3);
+
+        r.copy(q[12]); r.conj();
+        r.mul(p);
+        p.cmove(r,pb4);
+
+        p.reduce();
+        return p;
+    };
+
+    return FP48;
+};
diff --git a/version3/js/fp8.js b/version3/js/fp8.js
new file mode 100644
index 0000000..aff6621
--- /dev/null
+++ b/version3/js/fp8.js
@@ -0,0 +1,660 @@
+/*
+    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.
+*/
+
+/* Finite Field arithmetic  Fp^8 functions */
+
+/* FP8 elements are of the form a+ib, where i is sqrt(sqrt(-1+sqrt(-1)))  */
+
+var FP8 = function(ctx) {
+    "use strict";
+
+    /* general purpose constructor */
+    var FP8 = function(c, d) {
+        if (c instanceof FP8) {
+            this.a = new ctx.FP4(c.a);
+            this.b = new ctx.FP4(c.b);
+        } else {
+            this.a = new ctx.FP4(c);
+            this.b = new ctx.FP4(d);
+        }
+    };
+
+    FP8.prototype = {
+        /* reduce all components of this mod Modulus */
+        reduce: function() {
+            this.a.reduce();
+            this.b.reduce();
+        },
+
+        /* normalise all components of this mod Modulus */
+        norm: function() {
+            this.a.norm();
+            this.b.norm();
+        },
+
+        /* test this==0 ? */
+        iszilch: function() {
+            //this.reduce();
+            return (this.a.iszilch() && this.b.iszilch());
+        },
+
+        /* test this==1 ? */
+        isunity: function() {
+            var one = new ctx.FP4(1);
+            return (this.a.equals(one) && this.b.iszilch());
+        },
+
+        /* conditional copy of g to this depending on d */
+        cmove: function(g, d) {
+            this.a.cmove(g.a, d);
+            this.b.cmove(g.b, d);
+        },
+
+        /* test is w real? That is in a+ib test b is zero */
+        isreal: function() {
+            return this.b.iszilch();
+        },
+
+        /* extract real part a */
+        real: function() {
+            return this.a;
+        },
+
+        geta: function() {
+            return this.a;
+        },
+
+        /* extract imaginary part b */
+        getb: function() {
+            return this.b;
+        },
+
+        /* test this=x? */
+        equals: function(x) {
+            return (this.a.equals(x.a) && this.b.equals(x.b));
+        },
+
+        /* copy this=x */
+        copy: function(x) {
+            this.a.copy(x.a);
+            this.b.copy(x.b);
+        },
+
+        /* this=0 */
+        zero: function() {
+            this.a.zero();
+            this.b.zero();
+        },
+
+        /* this=1 */
+        one: function() {
+            this.a.one();
+            this.b.zero();
+        },
+
+        /* set from two FP4s */
+        set: function(c, d) {
+            this.a.copy(c);
+            this.b.copy(d);
+        },
+
+        /* set a */
+        seta: function(c) {
+            this.a.copy(c);
+            this.b.zero();
+        },
+
+        /* this=-this */
+        neg: function() {
+            this.norm();
+            var m = new ctx.FP4(this.a), //m.copy(this.a);
+                t = new ctx.FP4(0);
+
+            m.add(this.b);
+            m.neg();
+            //  m.norm();
+            t.copy(m);
+            t.add(this.b);
+            this.b.copy(m);
+            this.b.add(this.a);
+            this.a.copy(t);
+            this.norm();
+        },
+
+        /* this=conjugate(this) */
+        conj: function() {
+            this.b.neg();
+            this.norm();
+        },
+
+        /* this=-conjugate(this) */
+        nconj: function() {
+            this.a.neg();
+            this.norm();
+        },
+
+        /* this+=x */
+        add: function(x) {
+            this.a.add(x.a);
+            this.b.add(x.b);
+        },
+
+        /* this-=x */
+        sub: function(x) {
+            var m = new FP8(x); // m.copy(x);
+            m.neg();
+            this.add(m);
+        },
+
+        rsub: function(x) {
+            this.neg();
+            this.add(x);
+        },
+
+        /* this*=s where s is FP4 */
+        pmul: function(s) {
+            this.a.mul(s);
+            this.b.mul(s);
+        },
+
+        /* this*=c where s is int */
+        imul: function(c) {
+            this.a.imul(c);
+            this.b.imul(c);
+        },
+
+        /* this*=this */
+        sqr: function() {
+            //      this.norm();
+
+            var t1 = new ctx.FP4(this.a), //t1.copy(this.a)
+                t2 = new ctx.FP4(this.b), //t2.copy(this.b)
+                t3 = new ctx.FP4(this.a); //t3.copy(this.a)
+
+            t3.mul(this.b);
+            t1.add(this.b);
+            t1.norm();
+            t2.times_i();
+
+            t2.add(this.a);
+            t2.norm();
+            this.a.copy(t1);
+
+            this.a.mul(t2);
+
+            t2.copy(t3);
+            t2.times_i();
+            t2.add(t3);
+            //t2.norm();  // ??
+
+            t2.neg();
+
+            this.a.add(t2);
+
+            this.b.copy(t3);
+            this.b.add(t3);
+
+            this.norm();
+        },
+
+        /* this*=y */
+        mul: function(y) {
+            //      this.norm();
+
+            var t1 = new ctx.FP4(this.a), //t1.copy(this.a)
+                t2 = new ctx.FP4(this.b), //t2.copy(this.b)
+                t3 = new ctx.FP4(0),
+                t4 = new ctx.FP4(this.b); //t4.copy(this.b)
+
+            t1.mul(y.a);
+            t2.mul(y.b);
+            t3.copy(y.b);
+            t3.add(y.a);
+            t4.add(this.a);
+
+            t3.norm();
+            t4.norm();
+
+            t4.mul(t3);
+
+            t3.copy(t1);
+            t3.neg();
+            t4.add(t3);
+            //      t4.norm(); // ??
+
+            // t4.sub(t1);
+
+            t3.copy(t2);
+            t3.neg();
+            this.b.copy(t4);
+            this.b.add(t3);
+
+            t2.times_i();
+            this.a.copy(t2);
+            this.a.add(t1);
+
+            this.norm();
+        },
+
+        /* convert to hex string */
+        toString: function() {
+            return ("[" + this.a.toString() + "," + this.b.toString() + "]");
+        },
+
+        /* this=1/this */
+        inverse: function() {
+            this.norm();
+
+            var t1 = new ctx.FP4(this.a), //t1.copy(this.a);
+                t2 = new ctx.FP4(this.b); // t2.copy(this.b);
+
+            t1.sqr();
+            t2.sqr();
+            t2.times_i();
+            t2.norm(); // ??
+            t1.sub(t2);
+            t1.inverse();
+            this.a.mul(t1);
+            t1.neg();
+            t1.norm();
+            this.b.mul(t1);
+        },
+
+        /* this*=i where i = sqrt(-1+sqrt(-1)) */
+        times_i: function() {
+            var s = new ctx.FP4(this.b),
+                t = new ctx.FP4(this.a);
+
+            s.times_i();
+            this.b.copy(t);
+
+            this.a.copy(s);
+            this.norm();
+        },
+
+        times_i2: function() {
+            this.a.times_i();
+            this.b.times_i();
+        },
+
+        /* this=this^q using Frobenius, where q is Modulus */
+        frob: function(f) {
+            var ff=new ctx.FP2(f); ff.sqr(); ff.mul_ip(); ff.norm();
+            this.a.frob(ff);
+            this.b.frob(ff);
+            this.b.pmul(f);
+            this.b.times_i();
+        },
+
+        /* this=this^e */
+        pow: function(e) {
+            //this.norm();
+
+            var w = new FP8(this), //w.copy(this);
+                z = new ctx.BIG(e), //z.copy(e);
+                r = new FP8(1),
+                bt;
+			w.norm();
+			z.norm();
+            for (;;) {
+                bt = z.parity();
+                z.fshr(1);
+
+                if (bt === 1) {
+                    r.mul(w);
+                }
+
+                if (z.iszilch()) {
+                    break;
+                }
+
+                w.sqr();
+            }
+            r.reduce();
+
+            return r;
+        },
+
+        /* XTR xtr_a function */
+        xtr_A: function(w, y, z) {
+            var r = new FP8(w), //r.copy(w);
+                t = new FP8(w); //t.copy(w);
+
+            //y.norm(); // ??
+            r.sub(y);
+            r.norm();
+            r.pmul(this.a);
+            t.add(y);
+            t.norm();
+            t.pmul(this.b);
+            t.times_i();
+
+            this.copy(r);
+            this.add(t);
+            this.add(z);
+
+            this.reduce();
+        },
+
+        /* XTR xtr_d function */
+        xtr_D: function() {
+            var w = new FP8(this); //w.copy(this);
+            this.sqr();
+            w.conj();
+            w.add(w); //w.norm(); // ??
+            this.sub(w);
+            this.reduce();
+        },
+
+        /* r=x^n using XTR method on traces of FP12s */
+        xtr_pow: function(n) {
+			var sf = new FP8(this);
+			sf.norm();
+            var a = new FP8(3),
+                b = new FP8(sf),
+                c = new FP8(b),
+                t = new FP8(0),
+                r = new FP8(0),
+                par, v, nb, i;
+	
+            c.xtr_D();
+
+            
+            par = n.parity();
+            v = new ctx.BIG(n);
+			v.norm();
+            v.fshr(1);
+
+            if (par === 0) {
+                v.dec(1);
+                v.norm();
+            }
+
+            nb = v.nbits();
+            for (i = nb - 1; i >= 0; i--) {
+                if (v.bit(i) != 1) {
+                    t.copy(b);
+                    sf.conj();
+                    c.conj();
+                    b.xtr_A(a, sf, c);
+                    sf.conj();
+                    c.copy(t);
+                    c.xtr_D();
+                    a.xtr_D();
+                } else {
+                    t.copy(a);
+                    t.conj();
+                    a.copy(b);
+                    a.xtr_D();
+                    b.xtr_A(c, sf, t);
+                    c.xtr_D();
+                }
+            }
+
+            if (par === 0) {
+                r.copy(c);
+            } else {
+                r.copy(b);
+            }
+            r.reduce();
+
+            return r;
+        },
+
+        /* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */
+        xtr_pow2: function(ck, ckml, ckm2l, a, b) {
+
+            var e = new ctx.BIG(a), //e.copy(a)
+                d = new ctx.BIG(b), //d.copy(b)
+                w = new ctx.BIG(0),
+                cu = new FP8(ck), //cu.copy(ck), // can probably be passed in w/o copying
+                cv = new FP8(this), //cv.copy(this),
+                cumv = new FP8(ckml), //cumv.copy(ckml),
+                cum2v = new FP8(ckm2l), //cum2v.copy(ckm2l),
+                r = new FP8(0),
+                t = new FP8(0),
+                f2 = 0,
+                i;
+
+            e.norm();
+            d.norm();
+
+            while (d.parity() === 0 && e.parity() === 0) {
+                d.fshr(1);
+                e.fshr(1);
+                f2++;
+            }
+
+            while (ctx.BIG.comp(d, e) !== 0) {
+                if (ctx.BIG.comp(d, e) > 0) {
+                    w.copy(e);
+                    w.imul(4);
+                    w.norm();
+
+                    if (ctx.BIG.comp(d, w) <= 0) {
+                        w.copy(d);
+                        d.copy(e);
+                        e.rsub(w);
+                        e.norm();
+
+                        t.copy(cv);
+                        t.xtr_A(cu, cumv, cum2v);
+                        cum2v.copy(cumv);
+                        cum2v.conj();
+                        cumv.copy(cv);
+                        cv.copy(cu);
+                        cu.copy(t);
+
+                    } else if (d.parity() === 0) {
+                        d.fshr(1);
+                        r.copy(cum2v);
+                        r.conj();
+                        t.copy(cumv);
+                        t.xtr_A(cu, cv, r);
+                        cum2v.copy(cumv);
+                        cum2v.xtr_D();
+                        cumv.copy(t);
+                        cu.xtr_D();
+                    } else if (e.parity() == 1) {
+                        d.sub(e);
+                        d.norm();
+                        d.fshr(1);
+                        t.copy(cv);
+                        t.xtr_A(cu, cumv, cum2v);
+                        cu.xtr_D();
+                        cum2v.copy(cv);
+                        cum2v.xtr_D();
+                        cum2v.conj();
+                        cv.copy(t);
+                    } else {
+                        w.copy(d);
+                        d.copy(e);
+                        d.fshr(1);
+                        e.copy(w);
+                        t.copy(cumv);
+                        t.xtr_D();
+                        cumv.copy(cum2v);
+                        cumv.conj();
+                        cum2v.copy(t);
+                        cum2v.conj();
+                        t.copy(cv);
+                        t.xtr_D();
+                        cv.copy(cu);
+                        cu.copy(t);
+                    }
+                }
+                if (ctx.BIG.comp(d, e) < 0) {
+                    w.copy(d);
+                    w.imul(4);
+                    w.norm();
+
+                    if (ctx.BIG.comp(e, w) <= 0) {
+                        e.sub(d);
+                        e.norm();
+                        t.copy(cv);
+                        t.xtr_A(cu, cumv, cum2v);
+                        cum2v.copy(cumv);
+                        cumv.copy(cu);
+                        cu.copy(t);
+                    } else if (e.parity() === 0) {
+                        w.copy(d);
+                        d.copy(e);
+                        d.fshr(1);
+                        e.copy(w);
+                        t.copy(cumv);
+                        t.xtr_D();
+                        cumv.copy(cum2v);
+                        cumv.conj();
+                        cum2v.copy(t);
+                        cum2v.conj();
+                        t.copy(cv);
+                        t.xtr_D();
+                        cv.copy(cu);
+                        cu.copy(t);
+                    } else if (d.parity() == 1) {
+                        w.copy(e);
+                        e.copy(d);
+                        w.sub(d);
+                        w.norm();
+                        d.copy(w);
+                        d.fshr(1);
+                        t.copy(cv);
+                        t.xtr_A(cu, cumv, cum2v);
+                        cumv.conj();
+                        cum2v.copy(cu);
+                        cum2v.xtr_D();
+                        cum2v.conj();
+                        cu.copy(cv);
+                        cu.xtr_D();
+                        cv.copy(t);
+                    } else {
+                        d.fshr(1);
+                        r.copy(cum2v);
+                        r.conj();
+                        t.copy(cumv);
+                        t.xtr_A(cu, cv, r);
+                        cum2v.copy(cumv);
+                        cum2v.xtr_D();
+                        cumv.copy(t);
+                        cu.xtr_D();
+                    }
+                }
+            }
+            r.copy(cv);
+            r.xtr_A(cu, cumv, cum2v);
+            for (i = 0; i < f2; i++) {
+                r.xtr_D();
+            }
+            r = r.xtr_pow(d);
+            return r;
+        },
+
+        /* New stuff for ecp4.js */
+
+        div2: function() {
+            this.a.div2();
+            this.b.div2();
+        },
+
+        div_i: function() {
+            var u=new ctx.FP4(this.a),
+                v=new ctx.FP4(this.b);
+            u.div_i();
+            this.a.copy(v);
+            this.b.copy(u);
+        },
+
+        div_i2: function() {
+            this.a.div_i();
+            this.b.div_i();
+        },
+
+        div_2i: function() {
+            var u=new ctx.FP4(this.a),
+                v=new ctx.FP4(this.b);
+            u.div_2i();
+            v.add(v); v.norm();
+            this.a.copy(v);
+            this.b.copy(u);
+        },
+
+        qmul: function(s) {
+            this.a.pmul(s);
+            this.b.pmul(s);
+        },
+
+        tmul: function(s) {
+            this.a.qmul(s);
+            this.b.qmul(s);
+        },
+
+        sqrt: function() {
+            if (this.iszilch()) {
+                return true;
+            }
+            var wa=new ctx.FP4(this.a),
+                ws=new ctx.FP4(this.b),
+                wt=new ctx.FP4(this.a);
+            if (ws.iszilch()) {
+                if (wt.sqrt()) {
+                    this.a.copy(wt);
+                    this.b.zero();
+                } else {
+                    wt.div_i();
+                    wt.sqrt();
+                    this.b.copy(wt);
+                    this.a.zero();
+                }
+                return true;
+            }
+
+            ws.sqr();
+            wa.sqr();
+            ws.times_i();
+            ws.norm();
+            wa.sub(ws);
+
+            ws.copy(wa);
+            if (!ws.sqrt()) {
+                return false;
+            }
+
+            wa.copy(wt); wa.add(ws); wa.norm(); wa.div2();
+
+            if (!wa.sqrt()) {
+                wa.copy(wt); wa.sub(ws); wa.norm(); wa.div2();
+                if (!wa.sqrt()) {
+                    return false;
+                }
+            }
+            wt.copy(this.b);
+            ws.copy(wa); ws.add(wa);
+            ws.inverse();
+
+            wt.mul(ws);
+            this.a.copy(wa);
+            this.b.copy(wt);
+
+            return true;
+        }
+
+    };
+
+    return FP8;
+};
diff --git a/version3/js/gcm.js b/version3/js/gcm.js
new file mode 100644
index 0000000..b1621f0
--- /dev/null
+++ b/version3/js/gcm.js
@@ -0,0 +1,428 @@
+/*
+    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.
+*/
+
+/*
+ * Implementation of the ctx.AES-GCM Encryption/Authentication
+ *
+ * Some restrictions..
+ * 1. Only for use with ctx.AES
+ * 2. Returned tag is always 128-bits. Truncate at your own risk.
+ * 3. The order of function calls must follow some rules
+ *
+ * Typical sequence of calls..
+ * 1. call GCM_init
+ * 2. call GCM_add_header any number of times, as long as length of header is multiple of 16 bytes (block size)
+ * 3. call GCM_add_header one last time with any length of header
+ * 4. call GCM_add_cipher any number of times, as long as length of cipher/plaintext is multiple of 16 bytes
+ * 5. call GCM_add_cipher one last time with any length of cipher/plaintext
+ * 6. call GCM_finish to extract the tag.
+ *
+ * See http://www.mindspring.com/~dmcgrew/gcm-nist-6.pdf
+ */
+
+var GCM = function(ctx) {
+    "use strict";
+
+    var GCM = function() {
+        this.table = new Array(128);
+        for (var i = 0; i < 128; i++) {
+            this.table[i] = new Array(4); /* 2k bytes */
+        }
+        this.stateX = [];
+        this.Y_0 = [];
+        this.counter = 0;
+        this.lenA = [];
+        this.lenC = [];
+        this.status = 0;
+        this.a = new ctx.AES();
+    };
+
+    // GCM constants
+
+    GCM.ACCEPTING_HEADER = 0;
+    GCM.ACCEPTING_CIPHER = 1;
+    GCM.NOT_ACCEPTING_MORE = 2;
+    GCM.FINISHED = 3;
+    GCM.ENCRYPTING = 0;
+    GCM.DECRYPTING = 1;
+
+    GCM.prototype = {
+        precompute: function(H) {
+            var b = [],
+                i, j, c;
+
+            for (i = j = 0; i < 4; i++, j += 4) {
+                b[0] = H[j];
+                b[1] = H[j + 1];
+                b[2] = H[j + 2];
+                b[3] = H[j + 3];
+                this.table[0][i] = GCM.pack(b);
+            }
+            for (i = 1; i < 128; i++) {
+                c = 0;
+                for (j = 0; j < 4; j++) {
+                    this.table[i][j] = c | (this.table[i - 1][j]) >>> 1;
+                    c = this.table[i - 1][j] << 31;
+                }
+
+                if (c !== 0) {
+                    this.table[i][0] ^= 0xE1000000; /* irreducible polynomial */
+                }
+            }
+        },
+
+        gf2mul: function() { /* gf2m mul - Z=H*X mod 2^128 */
+            var P = [],
+                b = [],
+                i, j, m, k, c;
+
+            P[0] = P[1] = P[2] = P[3] = 0;
+            j = 8;
+            m = 0;
+
+            for (i = 0; i < 128; i++) {
+                c = (this.stateX[m] >>> (--j)) & 1;
+                c = ~c + 1;
+                for (k = 0; k < 4; k++) {
+                    P[k] ^= (this.table[i][k] & c);
+                }
+
+                if (j === 0) {
+                    j = 8;
+                    m++;
+                    if (m == 16) {
+                        break;
+                    }
+                }
+            }
+
+            for (i = j = 0; i < 4; i++, j += 4) {
+                b = GCM.unpack(P[i]);
+                this.stateX[j] = b[0];
+                this.stateX[j + 1] = b[1];
+                this.stateX[j + 2] = b[2];
+                this.stateX[j + 3] = b[3];
+            }
+        },
+
+        wrap: function() { /* Finish off GHASH */
+            var F = [],
+                L = [],
+                b = [],
+                i, j;
+
+            /* convert lengths from bytes to bits */
+            F[0] = (this.lenA[0] << 3) | (this.lenA[1] & 0xE0000000) >>> 29;
+            F[1] = this.lenA[1] << 3;
+            F[2] = (this.lenC[0] << 3) | (this.lenC[1] & 0xE0000000) >>> 29;
+            F[3] = this.lenC[1] << 3;
+
+            for (i = j = 0; i < 4; i++, j += 4) {
+                b = GCM.unpack(F[i]);
+                L[j] = b[0];
+                L[j + 1] = b[1];
+                L[j + 2] = b[2];
+                L[j + 3] = b[3];
+            }
+
+            for (i = 0; i < 16; i++) {
+                this.stateX[i] ^= L[i];
+            }
+
+            this.gf2mul();
+        },
+
+        /* Initialize GCM mode */
+        init: function(nk, key, niv, iv) { /* iv size niv is usually 12 bytes (96 bits). ctx.AES key size nk can be 16,24 or 32 bytes */
+            var H = [],
+                b = [],
+                i;
+
+            for (i = 0; i < 16; i++) {
+                H[i] = 0;
+                this.stateX[i] = 0;
+            }
+
+            this.a.init(ctx.AES.ECB, nk, key, iv);
+            this.a.ecb_encrypt(H); /* E(K,0) */
+            this.precompute(H);
+
+            this.lenA[0] = this.lenC[0] = this.lenA[1] = this.lenC[1] = 0;
+
+            if (niv == 12) {
+                for (i = 0; i < 12; i++) {
+                    this.a.f[i] = iv[i];
+                }
+
+                b = GCM.unpack(1);
+                this.a.f[12] = b[0];
+                this.a.f[13] = b[1];
+                this.a.f[14] = b[2];
+                this.a.f[15] = b[3]; /* initialise IV */
+
+                for (i = 0; i < 16; i++) {
+                    this.Y_0[i] = this.a.f[i];
+                }
+            } else {
+                this.status = GCM.ACCEPTING_CIPHER;
+                this.ghash(iv, niv); /* GHASH(H,0,IV) */
+                this.wrap();
+
+                for (i = 0; i < 16; i++) {
+                    this.a.f[i] = this.stateX[i];
+                    this.Y_0[i] = this.a.f[i];
+                    this.stateX[i] = 0;
+                }
+
+                this.lenA[0] = this.lenC[0] = this.lenA[1] = this.lenC[1] = 0;
+            }
+
+            this.status = GCM.ACCEPTING_HEADER;
+        },
+
+        /* Add Header data - included but not encrypted */
+        add_header: function(header, len) { /* Add some header. Won't be encrypted, but will be authenticated. len is length of header */
+            var i, j = 0;
+
+            if (this.status != GCM.ACCEPTING_HEADER) {
+                return false;
+            }
+
+            while (j < len) {
+                for (i = 0; i < 16 && j < len; i++) {
+                    this.stateX[i] ^= header[j++];
+                    this.lenA[1]++;
+                    this.lenA[1] |= 0;
+
+                    if (this.lenA[1] === 0) {
+                        this.lenA[0]++;
+                    }
+                }
+
+                this.gf2mul();
+            }
+
+            if (len % 16 !== 0) {
+                this.status = GCM.ACCEPTING_CIPHER;
+            }
+
+            return true;
+        },
+
+        ghash: function(plain, len) {
+            var i, j = 0;
+
+            if (this.status == GCM.ACCEPTING_HEADER) {
+                this.status = GCM.ACCEPTING_CIPHER;
+            }
+
+            if (this.status != GCM.ACCEPTING_CIPHER) {
+                return false;
+            }
+
+            while (j < len) {
+                for (i = 0; i < 16 && j < len; i++) {
+                    this.stateX[i] ^= plain[j++];
+                    this.lenC[1]++;
+                    this.lenC[1] |= 0;
+
+                    if (this.lenC[1] === 0) {
+                        this.lenC[0]++;
+                    }
+                }
+                this.gf2mul();
+            }
+
+            if (len % 16 !== 0) {
+                this.status = GCM.NOT_ACCEPTING_MORE;
+            }
+
+            return true;
+        },
+
+        /* Add Plaintext - included and encrypted */
+        add_plain: function(plain, len) {
+            var B = [],
+                b = [],
+                cipher = [],
+                i, j = 0;
+
+            if (this.status == GCM.ACCEPTING_HEADER) {
+                this.status = GCM.ACCEPTING_CIPHER;
+            }
+
+            if (this.status != GCM.ACCEPTING_CIPHER) {
+                return cipher;
+            }
+
+            while (j < len) {
+                b[0] = this.a.f[12];
+                b[1] = this.a.f[13];
+                b[2] = this.a.f[14];
+                b[3] = this.a.f[15];
+                this.counter = GCM.pack(b);
+                this.counter++;
+                b = GCM.unpack(this.counter);
+                this.a.f[12] = b[0];
+                this.a.f[13] = b[1];
+                this.a.f[14] = b[2];
+                this.a.f[15] = b[3]; /* increment counter */
+
+                for (i = 0; i < 16; i++) {
+                    B[i] = this.a.f[i];
+                }
+
+                this.a.ecb_encrypt(B); /* encrypt it  */
+
+                for (i = 0; i < 16 && j < len; i++) {
+                    cipher[j] = (plain[j] ^ B[i]);
+                    this.stateX[i] ^= cipher[j++];
+                    this.lenC[1]++;
+                    this.lenC[1] |= 0;
+
+                    if (this.lenC[1] === 0) {
+                        this.lenC[0]++;
+                    }
+                }
+
+                this.gf2mul();
+            }
+
+            if (len % 16 !== 0) {
+                this.status = GCM.NOT_ACCEPTING_MORE;
+            }
+
+            return cipher;
+        },
+
+        /* Add Ciphertext - decrypts to plaintext */
+        add_cipher: function(cipher, len) {
+            var B = [],
+                b = [],
+                plain = [],
+                j = 0,
+                i, oc;
+
+            if (this.status == GCM.ACCEPTING_HEADER) {
+                this.status = GCM.ACCEPTING_CIPHER;
+            }
+
+            if (this.status != GCM.ACCEPTING_CIPHER) {
+                return plain;
+            }
+
+            while (j < len) {
+                b[0] = this.a.f[12];
+                b[1] = this.a.f[13];
+                b[2] = this.a.f[14];
+                b[3] = this.a.f[15];
+                this.counter = GCM.pack(b);
+                this.counter++;
+                b = GCM.unpack(this.counter);
+                this.a.f[12] = b[0];
+                this.a.f[13] = b[1];
+                this.a.f[14] = b[2];
+                this.a.f[15] = b[3]; /* increment counter */
+
+                for (i = 0; i < 16; i++) {
+                    B[i] = this.a.f[i];
+                }
+
+                this.a.ecb_encrypt(B); /* encrypt it  */
+
+                for (i = 0; i < 16 && j < len; i++) {
+                    oc = cipher[j];
+                    plain[j] = (cipher[j] ^ B[i]);
+                    this.stateX[i] ^= oc;
+                    j++;
+                    this.lenC[1]++;
+                    this.lenC[1] |= 0;
+
+                    if (this.lenC[1] === 0) {
+                        this.lenC[0]++;
+                    }
+                }
+
+                this.gf2mul();
+            }
+
+            if (len % 16 !== 0) {
+                this.status = GCM.NOT_ACCEPTING_MORE;
+            }
+
+            return plain;
+        },
+
+        /* Finish and extract Tag */
+        finish: function(extract) { /* Finish off GHASH and extract tag (MAC) */
+            var tag = [],
+                i;
+
+            this.wrap();
+            /* extract tag */
+            if (extract) {
+                this.a.ecb_encrypt(this.Y_0); /* E(K,Y0) */
+
+                for (i = 0; i < 16; i++) {
+                    this.Y_0[i] ^= this.stateX[i];
+                }
+
+                for (i = 0; i < 16; i++) {
+                    tag[i] = this.Y_0[i];
+                    this.Y_0[i] = this.stateX[i] = 0;
+                }
+            }
+
+            this.status = GCM.FINISHED;
+            this.a.end();
+
+            return tag;
+        }
+
+    };
+
+    GCM.pack = function(b) { /* pack 4 bytes into a 32-bit Word */
+        return (((b[0]) & 0xff) << 24) | ((b[1] & 0xff) << 16) | ((b[2] & 0xff) << 8) | (b[3] & 0xff);
+    };
+
+    GCM.unpack = function(a) { /* unpack bytes from a word */
+        var b = [];
+
+        b[3] = (a & 0xff);
+        b[2] = ((a >>> 8) & 0xff);
+        b[1] = ((a >>> 16) & 0xff);
+        b[0] = ((a >>> 24) & 0xff);
+
+        return b;
+    };
+
+    GCM.hex2bytes = function(s) {
+        var len = s.length,
+            data = [],
+            i;
+
+        for (i = 0; i < len; i += 2) {
+            data[i / 2] = parseInt(s.substr(i, 2), 16);
+        }
+
+        return data;
+    };
+
+    return GCM;
+};
diff --git a/version3/js/hash256.js b/version3/js/hash256.js
new file mode 100644
index 0000000..72a3b5d
--- /dev/null
+++ b/version3/js/hash256.js
@@ -0,0 +1,198 @@
+/*
+    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.
+*/
+
+var HASH256 = function() {
+    "use strict";
+
+    var HASH256 = function() {
+        this.length = [];
+        this.h = [];
+        this.w = [];
+        this.init();
+    };
+
+    HASH256.prototype = {
+        transform: function() { /* basic transformation step */
+            var a, b, c, d, e, f, g, hh, t1, t2, j;
+
+            for (j = 16; j < 64; j++) {
+                this.w[j] = (HASH256.theta1(this.w[j - 2]) + this.w[j - 7] + HASH256.theta0(this.w[j - 15]) + this.w[j - 16]) | 0;
+            }
+
+            a = this.h[0];
+            b = this.h[1];
+            c = this.h[2];
+            d = this.h[3];
+            e = this.h[4];
+            f = this.h[5];
+            g = this.h[6];
+            hh = this.h[7];
+
+            for (j = 0; j < 64; j++) { /* 64 times - mush it up */
+                t1 = (hh + HASH256.Sig1(e) + HASH256.Ch(e, f, g) + HASH256.HK[j] + this.w[j]) | 0;
+                t2 = (HASH256.Sig0(a) + HASH256.Maj(a, b, c)) | 0;
+                hh = g;
+                g = f;
+                f = e;
+                e = (d + t1) | 0; // Need to knock these back down to prevent 52-bit overflow
+                d = c;
+                c = b;
+                b = a;
+                a = (t1 + t2) | 0;
+
+            }
+            this.h[0] += a;
+            this.h[1] += b;
+            this.h[2] += c;
+            this.h[3] += d;
+            this.h[4] += e;
+            this.h[5] += f;
+            this.h[6] += g;
+            this.h[7] += hh;
+
+        },
+
+        /* Initialise Hash function */
+        init: function() { /* initialise */
+            var i;
+
+            for (i = 0; i < 64; i++) {
+                this.w[i] = 0;
+            }
+            this.length[0] = this.length[1] = 0;
+            this.h[0] = HASH256.H[0];
+            this.h[1] = HASH256.H[1];
+            this.h[2] = HASH256.H[2];
+            this.h[3] = HASH256.H[3];
+            this.h[4] = HASH256.H[4];
+            this.h[5] = HASH256.H[5];
+            this.h[6] = HASH256.H[6];
+            this.h[7] = HASH256.H[7];
+        },
+
+        /* process a single byte */
+        process: function(byt) { /* process the next message byte */
+            var cnt;
+
+            cnt = (this.length[0] >>> 5) % 16;
+            this.w[cnt] <<= 8;
+            this.w[cnt] |= (byt & 0xFF);
+            this.length[0] += 8;
+
+            if ((this.length[0] & 0xffffffff) === 0) {
+                this.length[1]++;
+                this.length[0] = 0;
+            }
+
+            if ((this.length[0] % 512) === 0) {
+                this.transform();
+            }
+        },
+
+        /* process an array of bytes */
+        process_array: function(b) {
+            for (var i = 0; i < b.length; i++) {
+                this.process(b[i]);
+            }
+        },
+
+        /* process a 32-bit integer */
+        process_num: function(n) {
+            this.process((n >> 24) & 0xff);
+            this.process((n >> 16) & 0xff);
+            this.process((n >> 8) & 0xff);
+            this.process(n & 0xff);
+        },
+
+        hash: function() { /* pad message and finish - supply digest */
+            var digest = [],
+                len0, len1, i;
+
+            len0 = this.length[0];
+            len1 = this.length[1];
+            this.process(0x80);
+
+            while ((this.length[0] % 512) != 448) {
+                this.process(0);
+            }
+
+            this.w[14] = len1;
+            this.w[15] = len0;
+            this.transform();
+
+            for (i = 0; i < HASH256.len; i++) { /* convert to bytes */
+                digest[i] = ((this.h[i >>> 2] >> (8 * (3 - i % 4))) & 0xff);
+            }
+            this.init();
+
+            return digest;
+        }
+    };
+
+    /* static functions */
+
+    HASH256.S = function(n, x) {
+        return (((x) >>> n) | ((x) << (32 - n)));
+    };
+
+    HASH256.R = function(n, x) {
+        return ((x) >>> n);
+    };
+
+    HASH256.Ch = function(x, y, z) {
+        return ((x & y) ^ (~(x) & z));
+    };
+
+    HASH256.Maj = function(x, y, z) {
+        return ((x & y) ^ (x & z) ^ (y & z));
+    };
+
+    HASH256.Sig0 = function(x) {
+        return (HASH256.S(2, x) ^ HASH256.S(13, x) ^ HASH256.S(22, x));
+    };
+
+    HASH256.Sig1 = function(x) {
+        return (HASH256.S(6, x) ^ HASH256.S(11, x) ^ HASH256.S(25, x));
+    };
+
+    HASH256.theta0 = function(x) {
+        return (HASH256.S(7, x) ^ HASH256.S(18, x) ^ HASH256.R(3, x));
+    };
+
+    HASH256.theta1 = function(x) {
+        return (HASH256.S(17, x) ^ HASH256.S(19, x) ^ HASH256.R(10, x));
+    };
+
+    /* constants */
+    HASH256.len = 32;
+
+    HASH256.H = [0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19];
+
+    HASH256.HK = [0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+        0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+        0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+        0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+        0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+        0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+        0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+        0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+    ];
+
+    return HASH256;
+};
diff --git a/version3/js/hash384.js b/version3/js/hash384.js
new file mode 100644
index 0000000..b348afe
--- /dev/null
+++ b/version3/js/hash384.js
@@ -0,0 +1,275 @@
+/*
+    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.
+*/
+
+var HASH384 = function(ctx) {
+    "use strict";
+
+    var HASH384 = function() {
+        this.length = [];
+        this.h = [];
+        this.w = [];
+        this.init();
+    };
+
+    HASH384.prototype = {
+        transform: function() { /* basic transformation step */
+            var a, b, c, d, e, f, g, hh, t1, t2, j;
+
+            for (j = 16; j < 80; j++) {
+                this.w[j] = HASH384.theta1(this.w[j - 2]).add(this.w[j - 7]).add(HASH384.theta0(this.w[j - 15])).add(this.w[j - 16]);
+            }
+
+            a = this.h[0].copy();
+            b = this.h[1].copy();
+            c = this.h[2].copy();
+            d = this.h[3].copy();
+            e = this.h[4].copy();
+            f = this.h[5].copy();
+            g = this.h[6].copy();
+            hh = this.h[7].copy();
+
+            for (j = 0; j < 80; j++) { /* 80 times - mush it up */
+                t1 = hh.copy();
+                t1.add(HASH384.Sig1(e)).add(HASH384.Ch(e, f, g)).add(HASH384.HK[j]).add(this.w[j]);
+
+                t2 = HASH384.Sig0(a);
+                t2.add(HASH384.Maj(a, b, c));
+                hh = g;
+                g = f;
+                f = e;
+                e = d.copy();
+                e.add(t1);
+
+                d = c;
+                c = b;
+                b = a;
+                a = t1.copy();
+                a.add(t2);
+            }
+
+            this.h[0].add(a);
+            this.h[1].add(b);
+            this.h[2].add(c);
+            this.h[3].add(d);
+            this.h[4].add(e);
+            this.h[5].add(f);
+            this.h[6].add(g);
+            this.h[7].add(hh);
+        },
+
+        /* Initialise Hash function */
+        init: function() { /* initialise */
+            var i;
+
+            for (i = 0; i < 80; i++) {
+                this.w[i] = new ctx.UInt64(0, 0);
+            }
+            this.length[0] = new ctx.UInt64(0, 0);
+            this.length[1] = new ctx.UInt64(0, 0);
+            this.h[0] = HASH384.H[0].copy();
+            this.h[1] = HASH384.H[1].copy();
+            this.h[2] = HASH384.H[2].copy();
+            this.h[3] = HASH384.H[3].copy();
+            this.h[4] = HASH384.H[4].copy();
+            this.h[5] = HASH384.H[5].copy();
+            this.h[6] = HASH384.H[6].copy();
+            this.h[7] = HASH384.H[7].copy();
+        },
+
+        /* process a single byte */
+        process: function(byt) { /* process the next message byte */
+            var cnt, e;
+
+            cnt = (this.length[0].bot >>> 6) % 16;
+            this.w[cnt].shlb();
+            this.w[cnt].bot |= (byt & 0xFF);
+
+            e = new ctx.UInt64(0, 8);
+            this.length[0].add(e);
+
+            if (this.length[0].top === 0 && this.length[0].bot == 0) {
+                e = new ctx.UInt64(0, 1);
+                this.length[1].add(e);
+            }
+
+            if ((this.length[0].bot % 1024) === 0) {
+                this.transform();
+            }
+        },
+
+        /* process an array of bytes */
+        process_array: function(b) {
+            for (var i = 0; i < b.length; i++) {
+                this.process(b[i]);
+            }
+        },
+
+        /* process a 32-bit integer */
+        process_num: function(n) {
+            this.process((n >> 24) & 0xff);
+            this.process((n >> 16) & 0xff);
+            this.process((n >> 8) & 0xff);
+            this.process(n & 0xff);
+        },
+
+        hash: function() { /* pad message and finish - supply digest */
+            var digest = [],
+                len0, len1,
+                i;
+
+            len0 = this.length[0].copy();
+            len1 = this.length[1].copy();
+            this.process(0x80);
+            while ((this.length[0].bot % 1024) != 896) {
+                this.process(0);
+            }
+
+            this.w[14] = len1;
+            this.w[15] = len0;
+            this.transform();
+
+            for (i = 0; i < HASH384.len; i++) { /* convert to bytes */
+                digest[i] = HASH384.R(8 * (7 - i % 8), this.h[i >>> 3]).bot & 0xff;
+            }
+
+            this.init();
+
+            return digest;
+        }
+    };
+
+
+    /* static  functions */
+    HASH384.S = function(n, x) {
+        if (n == 0) {
+            return x;
+        }
+
+        if (n < 32) {
+            return new ctx.UInt64((x.top >>> n) | (x.bot << (32 - n)), (x.bot >>> n) | (x.top << (32 - n)));
+        } else {
+            return new ctx.UInt64((x.bot >>> (n - 32)) | (x.top << (64 - n)), (x.top >>> (n - 32)) | (x.bot << (64 - n)));
+        }
+
+    };
+
+    HASH384.R = function(n, x) {
+        if (n == 0) {
+            return x;
+        }
+
+        if (n < 32) {
+            return new ctx.UInt64((x.top >>> n), (x.bot >>> n | (x.top << (32 - n))));
+        } else {
+            return new ctx.UInt64(0, x.top >>> (n - 32));
+        }
+    };
+
+    HASH384.Ch = function(x, y, z) {
+        return new ctx.UInt64((x.top & y.top) ^ (~(x.top) & z.top), (x.bot & y.bot) ^ (~(x.bot) & z.bot));
+    };
+
+    HASH384.Maj = function(x, y, z) {
+        return new ctx.UInt64((x.top & y.top) ^ (x.top & z.top) ^ (y.top & z.top), (x.bot & y.bot) ^ (x.bot & z.bot) ^ (y.bot & z.bot));
+    };
+
+    HASH384.Sig0 = function(x) {
+        var r1 = HASH384.S(28, x),
+            r2 = HASH384.S(34, x),
+            r3 = HASH384.S(39, x);
+
+        return new ctx.UInt64(r1.top ^ r2.top ^ r3.top, r1.bot ^ r2.bot ^ r3.bot);
+    };
+
+    HASH384.Sig1 = function(x) {
+        var r1 = HASH384.S(14, x),
+            r2 = HASH384.S(18, x),
+            r3 = HASH384.S(41, x);
+
+        return new ctx.UInt64(r1.top ^ r2.top ^ r3.top, r1.bot ^ r2.bot ^ r3.bot);
+    };
+
+    HASH384.theta0 = function(x) {
+        var r1 = HASH384.S(1, x),
+            r2 = HASH384.S(8, x),
+            r3 = HASH384.R(7, x);
+
+        return new ctx.UInt64(r1.top ^ r2.top ^ r3.top, r1.bot ^ r2.bot ^ r3.bot);
+    };
+
+    HASH384.theta1 = function(x) {
+        var r1 = HASH384.S(19, x),
+            r2 = HASH384.S(61, x),
+            r3 = HASH384.R(6, x);
+
+        return new ctx.UInt64(r1.top ^ r2.top ^ r3.top, r1.bot ^ r2.bot ^ r3.bot);
+    };
+
+    HASH384.len = 48;
+
+    HASH384.H = [new ctx.UInt64(0xcbbb9d5d, 0xc1059ed8), new ctx.UInt64(0x629a292a, 0x367cd507),
+        new ctx.UInt64(0x9159015a, 0x3070dd17), new ctx.UInt64(0x152fecd8, 0xf70e5939),
+        new ctx.UInt64(0x67332667, 0xffc00b31), new ctx.UInt64(0x8eb44a87, 0x68581511),
+        new ctx.UInt64(0xdb0c2e0d, 0x64f98fa7), new ctx.UInt64(0x47b5481d, 0xbefa4fa4)
+    ];
+
+    HASH384.HK = [new ctx.UInt64(0x428a2f98, 0xd728ae22), new ctx.UInt64(0x71374491, 0x23ef65cd),
+        new ctx.UInt64(0xb5c0fbcf, 0xec4d3b2f), new ctx.UInt64(0xe9b5dba5, 0x8189dbbc),
+        new ctx.UInt64(0x3956c25b, 0xf348b538), new ctx.UInt64(0x59f111f1, 0xb605d019),
+        new ctx.UInt64(0x923f82a4, 0xaf194f9b), new ctx.UInt64(0xab1c5ed5, 0xda6d8118),
+        new ctx.UInt64(0xd807aa98, 0xa3030242), new ctx.UInt64(0x12835b01, 0x45706fbe),
+        new ctx.UInt64(0x243185be, 0x4ee4b28c), new ctx.UInt64(0x550c7dc3, 0xd5ffb4e2),
+        new ctx.UInt64(0x72be5d74, 0xf27b896f), new ctx.UInt64(0x80deb1fe, 0x3b1696b1),
+        new ctx.UInt64(0x9bdc06a7, 0x25c71235), new ctx.UInt64(0xc19bf174, 0xcf692694),
+        new ctx.UInt64(0xe49b69c1, 0x9ef14ad2), new ctx.UInt64(0xefbe4786, 0x384f25e3),
+        new ctx.UInt64(0x0fc19dc6, 0x8b8cd5b5), new ctx.UInt64(0x240ca1cc, 0x77ac9c65),
+        new ctx.UInt64(0x2de92c6f, 0x592b0275), new ctx.UInt64(0x4a7484aa, 0x6ea6e483),
+        new ctx.UInt64(0x5cb0a9dc, 0xbd41fbd4), new ctx.UInt64(0x76f988da, 0x831153b5),
+        new ctx.UInt64(0x983e5152, 0xee66dfab), new ctx.UInt64(0xa831c66d, 0x2db43210),
+        new ctx.UInt64(0xb00327c8, 0x98fb213f), new ctx.UInt64(0xbf597fc7, 0xbeef0ee4),
+        new ctx.UInt64(0xc6e00bf3, 0x3da88fc2), new ctx.UInt64(0xd5a79147, 0x930aa725),
+        new ctx.UInt64(0x06ca6351, 0xe003826f), new ctx.UInt64(0x14292967, 0x0a0e6e70),
+        new ctx.UInt64(0x27b70a85, 0x46d22ffc), new ctx.UInt64(0x2e1b2138, 0x5c26c926),
+        new ctx.UInt64(0x4d2c6dfc, 0x5ac42aed), new ctx.UInt64(0x53380d13, 0x9d95b3df),
+        new ctx.UInt64(0x650a7354, 0x8baf63de), new ctx.UInt64(0x766a0abb, 0x3c77b2a8),
+        new ctx.UInt64(0x81c2c92e, 0x47edaee6), new ctx.UInt64(0x92722c85, 0x1482353b),
+        new ctx.UInt64(0xa2bfe8a1, 0x4cf10364), new ctx.UInt64(0xa81a664b, 0xbc423001),
+        new ctx.UInt64(0xc24b8b70, 0xd0f89791), new ctx.UInt64(0xc76c51a3, 0x0654be30),
+        new ctx.UInt64(0xd192e819, 0xd6ef5218), new ctx.UInt64(0xd6990624, 0x5565a910),
+        new ctx.UInt64(0xf40e3585, 0x5771202a), new ctx.UInt64(0x106aa070, 0x32bbd1b8),
+        new ctx.UInt64(0x19a4c116, 0xb8d2d0c8), new ctx.UInt64(0x1e376c08, 0x5141ab53),
+        new ctx.UInt64(0x2748774c, 0xdf8eeb99), new ctx.UInt64(0x34b0bcb5, 0xe19b48a8),
+        new ctx.UInt64(0x391c0cb3, 0xc5c95a63), new ctx.UInt64(0x4ed8aa4a, 0xe3418acb),
+        new ctx.UInt64(0x5b9cca4f, 0x7763e373), new ctx.UInt64(0x682e6ff3, 0xd6b2b8a3),
+        new ctx.UInt64(0x748f82ee, 0x5defb2fc), new ctx.UInt64(0x78a5636f, 0x43172f60),
+        new ctx.UInt64(0x84c87814, 0xa1f0ab72), new ctx.UInt64(0x8cc70208, 0x1a6439ec),
+        new ctx.UInt64(0x90befffa, 0x23631e28), new ctx.UInt64(0xa4506ceb, 0xde82bde9),
+        new ctx.UInt64(0xbef9a3f7, 0xb2c67915), new ctx.UInt64(0xc67178f2, 0xe372532b),
+        new ctx.UInt64(0xca273ece, 0xea26619c), new ctx.UInt64(0xd186b8c7, 0x21c0c207),
+        new ctx.UInt64(0xeada7dd6, 0xcde0eb1e), new ctx.UInt64(0xf57d4f7f, 0xee6ed178),
+        new ctx.UInt64(0x06f067aa, 0x72176fba), new ctx.UInt64(0x0a637dc5, 0xa2c898a6),
+        new ctx.UInt64(0x113f9804, 0xbef90dae), new ctx.UInt64(0x1b710b35, 0x131c471b),
+        new ctx.UInt64(0x28db77f5, 0x23047d84), new ctx.UInt64(0x32caab7b, 0x40c72493),
+        new ctx.UInt64(0x3c9ebe0a, 0x15c9bebc), new ctx.UInt64(0x431d67c4, 0x9c100d4c),
+        new ctx.UInt64(0x4cc5d4be, 0xcb3e42b6), new ctx.UInt64(0x597f299c, 0xfc657e2a),
+        new ctx.UInt64(0x5fcb6fab, 0x3ad6faec), new ctx.UInt64(0x6c44198c, 0x4a475817)
+    ];
+
+    return HASH384;
+};
diff --git a/version3/js/hash512.js b/version3/js/hash512.js
new file mode 100644
index 0000000..08eb593
--- /dev/null
+++ b/version3/js/hash512.js
@@ -0,0 +1,277 @@
+/*
+    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.
+*/
+
+var HASH512 = function(ctx) {
+    "use strict";
+
+    var HASH512 = function() {
+        this.length = [];
+        this.h = [];
+        this.w = [];
+        this.init();
+    };
+
+    HASH512.prototype = {
+
+        transform: function() { /* basic transformation step */
+            var a, b, c, d, e, f, g, hh, t1, t2, j;
+
+            for (j = 16; j < 80; j++) {
+                this.w[j] = HASH512.theta1(this.w[j - 2]).add(this.w[j - 7]).add(HASH512.theta0(this.w[j - 15])).add(this.w[j - 16]);
+            }
+
+            a = this.h[0].copy();
+            b = this.h[1].copy();
+            c = this.h[2].copy();
+            d = this.h[3].copy();
+            e = this.h[4].copy();
+            f = this.h[5].copy();
+            g = this.h[6].copy();
+            hh = this.h[7].copy();
+
+            for (j = 0; j < 80; j++) { /* 80 times - mush it up */
+                t1 = hh.copy();
+                t1.add(HASH512.Sig1(e)).add(HASH512.Ch(e, f, g)).add(HASH512.HK[j]).add(this.w[j]);
+
+                t2 = HASH512.Sig0(a);
+                t2.add(HASH512.Maj(a, b, c));
+                hh = g;
+                g = f;
+                f = e;
+                e = d.copy();
+                e.add(t1);
+
+                d = c;
+                c = b;
+                b = a;
+                a = t1.copy();
+                a.add(t2);
+            }
+
+            this.h[0].add(a);
+            this.h[1].add(b);
+            this.h[2].add(c);
+            this.h[3].add(d);
+            this.h[4].add(e);
+            this.h[5].add(f);
+            this.h[6].add(g);
+            this.h[7].add(hh);
+        },
+
+        /* Initialise Hash function */
+        init: function() { /* initialise */
+            var i;
+
+            for (i = 0; i < 80; i++) {
+                this.w[i] = new ctx.UInt64(0, 0);
+            }
+
+            this.length[0] = new ctx.UInt64(0, 0);
+            this.length[1] = new ctx.UInt64(0, 0);
+            this.h[0] = HASH512.H[0].copy();
+            this.h[1] = HASH512.H[1].copy();
+            this.h[2] = HASH512.H[2].copy();
+            this.h[3] = HASH512.H[3].copy();
+            this.h[4] = HASH512.H[4].copy();
+            this.h[5] = HASH512.H[5].copy();
+            this.h[6] = HASH512.H[6].copy();
+            this.h[7] = HASH512.H[7].copy();
+        },
+
+        /* process a single byte */
+        process: function(byt) { /* process the next message byte */
+            var cnt, e;
+
+            cnt = (this.length[0].bot >>> 6) % 16;
+            this.w[cnt].shlb();
+            this.w[cnt].bot |= (byt & 0xFF);
+
+            e = new ctx.UInt64(0, 8);
+            this.length[0].add(e);
+
+            if (this.length[0].top === 0 && this.length[0].bot == 0) {
+                e = new ctx.UInt64(0, 1);
+                this.length[1].add(e);
+            }
+
+            if ((this.length[0].bot % 1024) === 0) {
+                this.transform();
+            }
+        },
+
+        /* process an array of bytes */
+        process_array: function(b) {
+            for (var i = 0; i < b.length; i++) {
+                this.process(b[i]);
+            }
+        },
+
+        /* process a 32-bit integer */
+        process_num: function(n) {
+            this.process((n >> 24) & 0xff);
+            this.process((n >> 16) & 0xff);
+            this.process((n >> 8) & 0xff);
+            this.process(n & 0xff);
+        },
+
+        hash: function() { /* pad message and finish - supply digest */
+            var digest = [],
+                len0, len1, i;
+
+            len0 = this.length[0].copy();
+            len1 = this.length[1].copy();
+            this.process(0x80);
+
+            while ((this.length[0].bot % 1024) != 896) {
+                this.process(0);
+            }
+
+            this.w[14] = len1;
+            this.w[15] = len0;
+            this.transform();
+
+            for (i = 0; i < HASH512.len; i++) { /* convert to bytes */
+                digest[i] = HASH512.R(8 * (7 - i % 8), this.h[i >>> 3]).bot & 0xff;
+            }
+
+            this.init();
+
+            return digest;
+        }
+    };
+
+    /* static functions */
+    HASH512.S = function(n, x) {
+        if (n == 0) {
+            return x;
+        }
+
+        if (n < 32) {
+            return new ctx.UInt64((x.top >>> n) | (x.bot << (32 - n)), (x.bot >>> n) | (x.top << (32 - n)));
+        } else {
+            return new ctx.UInt64((x.bot >>> (n - 32)) | (x.top << (64 - n)), (x.top >>> (n - 32)) | (x.bot << (64 - n)));
+        }
+
+    };
+
+    HASH512.R = function(n, x) {
+        if (n == 0) {
+            return x;
+        }
+
+        if (n < 32) {
+            return new ctx.UInt64((x.top >>> n), (x.bot >>> n | (x.top << (32 - n))));
+        } else {
+            return new ctx.UInt64(0, x.top >>> (n - 32));
+        }
+    };
+
+    HASH512.Ch = function(x, y, z) {
+        return new ctx.UInt64((x.top & y.top) ^ (~(x.top) & z.top), (x.bot & y.bot) ^ (~(x.bot) & z.bot));
+    };
+
+    HASH512.Maj = function(x, y, z) {
+        return new ctx.UInt64((x.top & y.top) ^ (x.top & z.top) ^ (y.top & z.top), (x.bot & y.bot) ^ (x.bot & z.bot) ^ (y.bot & z.bot));
+    };
+
+    HASH512.Sig0 = function(x) {
+        var r1 = HASH512.S(28, x),
+            r2 = HASH512.S(34, x),
+            r3 = HASH512.S(39, x);
+
+        return new ctx.UInt64(r1.top ^ r2.top ^ r3.top, r1.bot ^ r2.bot ^ r3.bot);
+    };
+
+    HASH512.Sig1 = function(x) {
+        var r1 = HASH512.S(14, x),
+            r2 = HASH512.S(18, x),
+            r3 = HASH512.S(41, x);
+
+        return new ctx.UInt64(r1.top ^ r2.top ^ r3.top, r1.bot ^ r2.bot ^ r3.bot);
+    };
+
+    HASH512.theta0 = function(x) {
+        var r1 = HASH512.S(1, x),
+            r2 = HASH512.S(8, x),
+            r3 = HASH512.R(7, x);
+
+        return new ctx.UInt64(r1.top ^ r2.top ^ r3.top, r1.bot ^ r2.bot ^ r3.bot);
+    };
+
+    HASH512.theta1 = function(x) {
+        var r1 = HASH512.S(19, x),
+            r2 = HASH512.S(61, x),
+            r3 = HASH512.R(6, x);
+
+        return new ctx.UInt64(r1.top ^ r2.top ^ r3.top, r1.bot ^ r2.bot ^ r3.bot);
+    };
+
+    /* constants */
+    HASH512.len = 64;
+
+    HASH512.H = [new ctx.UInt64(0x6a09e667, 0xf3bcc908), new ctx.UInt64(0xbb67ae85, 0x84caa73b),
+        new ctx.UInt64(0x3c6ef372, 0xfe94f82b), new ctx.UInt64(0xa54ff53a, 0x5f1d36f1),
+        new ctx.UInt64(0x510e527f, 0xade682d1), new ctx.UInt64(0x9b05688c, 0x2b3e6c1f),
+        new ctx.UInt64(0x1f83d9ab, 0xfb41bd6b), new ctx.UInt64(0x5be0cd19, 0x137e2179)
+    ];
+
+    HASH512.HK = [new ctx.UInt64(0x428a2f98, 0xd728ae22), new ctx.UInt64(0x71374491, 0x23ef65cd),
+        new ctx.UInt64(0xb5c0fbcf, 0xec4d3b2f), new ctx.UInt64(0xe9b5dba5, 0x8189dbbc),
+        new ctx.UInt64(0x3956c25b, 0xf348b538), new ctx.UInt64(0x59f111f1, 0xb605d019),
+        new ctx.UInt64(0x923f82a4, 0xaf194f9b), new ctx.UInt64(0xab1c5ed5, 0xda6d8118),
+        new ctx.UInt64(0xd807aa98, 0xa3030242), new ctx.UInt64(0x12835b01, 0x45706fbe),
+        new ctx.UInt64(0x243185be, 0x4ee4b28c), new ctx.UInt64(0x550c7dc3, 0xd5ffb4e2),
+        new ctx.UInt64(0x72be5d74, 0xf27b896f), new ctx.UInt64(0x80deb1fe, 0x3b1696b1),
+        new ctx.UInt64(0x9bdc06a7, 0x25c71235), new ctx.UInt64(0xc19bf174, 0xcf692694),
+        new ctx.UInt64(0xe49b69c1, 0x9ef14ad2), new ctx.UInt64(0xefbe4786, 0x384f25e3),
+        new ctx.UInt64(0x0fc19dc6, 0x8b8cd5b5), new ctx.UInt64(0x240ca1cc, 0x77ac9c65),
+        new ctx.UInt64(0x2de92c6f, 0x592b0275), new ctx.UInt64(0x4a7484aa, 0x6ea6e483),
+        new ctx.UInt64(0x5cb0a9dc, 0xbd41fbd4), new ctx.UInt64(0x76f988da, 0x831153b5),
+        new ctx.UInt64(0x983e5152, 0xee66dfab), new ctx.UInt64(0xa831c66d, 0x2db43210),
+        new ctx.UInt64(0xb00327c8, 0x98fb213f), new ctx.UInt64(0xbf597fc7, 0xbeef0ee4),
+        new ctx.UInt64(0xc6e00bf3, 0x3da88fc2), new ctx.UInt64(0xd5a79147, 0x930aa725),
+        new ctx.UInt64(0x06ca6351, 0xe003826f), new ctx.UInt64(0x14292967, 0x0a0e6e70),
+        new ctx.UInt64(0x27b70a85, 0x46d22ffc), new ctx.UInt64(0x2e1b2138, 0x5c26c926),
+        new ctx.UInt64(0x4d2c6dfc, 0x5ac42aed), new ctx.UInt64(0x53380d13, 0x9d95b3df),
+        new ctx.UInt64(0x650a7354, 0x8baf63de), new ctx.UInt64(0x766a0abb, 0x3c77b2a8),
+        new ctx.UInt64(0x81c2c92e, 0x47edaee6), new ctx.UInt64(0x92722c85, 0x1482353b),
+        new ctx.UInt64(0xa2bfe8a1, 0x4cf10364), new ctx.UInt64(0xa81a664b, 0xbc423001),
+        new ctx.UInt64(0xc24b8b70, 0xd0f89791), new ctx.UInt64(0xc76c51a3, 0x0654be30),
+        new ctx.UInt64(0xd192e819, 0xd6ef5218), new ctx.UInt64(0xd6990624, 0x5565a910),
+        new ctx.UInt64(0xf40e3585, 0x5771202a), new ctx.UInt64(0x106aa070, 0x32bbd1b8),
+        new ctx.UInt64(0x19a4c116, 0xb8d2d0c8), new ctx.UInt64(0x1e376c08, 0x5141ab53),
+        new ctx.UInt64(0x2748774c, 0xdf8eeb99), new ctx.UInt64(0x34b0bcb5, 0xe19b48a8),
+        new ctx.UInt64(0x391c0cb3, 0xc5c95a63), new ctx.UInt64(0x4ed8aa4a, 0xe3418acb),
+        new ctx.UInt64(0x5b9cca4f, 0x7763e373), new ctx.UInt64(0x682e6ff3, 0xd6b2b8a3),
+        new ctx.UInt64(0x748f82ee, 0x5defb2fc), new ctx.UInt64(0x78a5636f, 0x43172f60),
+        new ctx.UInt64(0x84c87814, 0xa1f0ab72), new ctx.UInt64(0x8cc70208, 0x1a6439ec),
+        new ctx.UInt64(0x90befffa, 0x23631e28), new ctx.UInt64(0xa4506ceb, 0xde82bde9),
+        new ctx.UInt64(0xbef9a3f7, 0xb2c67915), new ctx.UInt64(0xc67178f2, 0xe372532b),
+        new ctx.UInt64(0xca273ece, 0xea26619c), new ctx.UInt64(0xd186b8c7, 0x21c0c207),
+        new ctx.UInt64(0xeada7dd6, 0xcde0eb1e), new ctx.UInt64(0xf57d4f7f, 0xee6ed178),
+        new ctx.UInt64(0x06f067aa, 0x72176fba), new ctx.UInt64(0x0a637dc5, 0xa2c898a6),
+        new ctx.UInt64(0x113f9804, 0xbef90dae), new ctx.UInt64(0x1b710b35, 0x131c471b),
+        new ctx.UInt64(0x28db77f5, 0x23047d84), new ctx.UInt64(0x32caab7b, 0x40c72493),
+        new ctx.UInt64(0x3c9ebe0a, 0x15c9bebc), new ctx.UInt64(0x431d67c4, 0x9c100d4c),
+        new ctx.UInt64(0x4cc5d4be, 0xcb3e42b6), new ctx.UInt64(0x597f299c, 0xfc657e2a),
+        new ctx.UInt64(0x5fcb6fab, 0x3ad6faec), new ctx.UInt64(0x6c44198c, 0x4a475817)
+    ];
+
+    return HASH512;
+};
diff --git a/version3/js/include.html b/version3/js/include.html
new file mode 100644
index 0000000..0a3bcaa
--- /dev/null
+++ b/version3/js/include.html
@@ -0,0 +1,25 @@
+<script type="text/javascript"src=./rand.js></script>
+<script type="text/javascript"src=./rom_curve.js></script>
+<script type="text/javascript"src=./rom_field.js></script>
+<script type="text/javascript"src=./uint64.js></script>
+<script type="text/javascript"src=./aes.js></script>
+<script type="text/javascript"src=./big.js></script>
+<script type="text/javascript"src=./gcm.js></script>
+<script type="text/javascript"src=./hash256.js></script>
+<script type="text/javascript"src=./hash384.js></script>
+<script type="text/javascript"src=./hash512.js></script>
+<script type="text/javascript"src=./sha3.js></script>
+<script type="text/javascript"src=./newhope.js></script>
+<script type="text/javascript"src=./nhs.js></script>
+<script type="text/javascript"src=./fp.js></script>
+<script type="text/javascript"src=./fp2.js></script>
+<script type="text/javascript"src=./fp4.js></script>
+<script type="text/javascript"src=./fp12.js></script>
+<script type="text/javascript"src=./ff.js></script>
+<script type="text/javascript"src=./rsa.js></script>
+<script type="text/javascript"src=./ecp.js></script>
+<script type="text/javascript"src=./ecp2.js></script>
+<script type="text/javascript"src=./ecdh.js></script>
+<script type="text/javascript"src=./pair.js></script>
+<script type="text/javascript"src=./mpin.js></script>
+<script type="text/javascript"src=./ctx.js></script>
diff --git a/version3/js/mpin.js b/version3/js/mpin.js
new file mode 100644
index 0000000..f2e3fbc
--- /dev/null
+++ b/version3/js/mpin.js
@@ -0,0 +1,1059 @@
+/*
+    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.
+*/
+
+/* MPIN API Functions */
+
+var MPIN = function(ctx) {
+    "use strict";
+
+    var MPIN = {
+        BAD_PARAMS: -11,
+        INVALID_POINT: -14,
+        WRONG_ORDER: -18,
+        BAD_PIN: -19,
+        /* configure PIN here */
+        MAXPIN: 10000,
+        /* max PIN */
+        PBLEN: 14,
+        /* MAXPIN length in bits */
+        TS: 12,
+        /* 10 for 4 digit PIN, 14 for 6-digit PIN - 2^TS/TS approx = sqrt(MAXPIN) */
+        TRAP: 2000,
+        /* 200 for 4 digit PIN, 2000 for 6-digit PIN  - approx 2*sqrt(MAXPIN) */
+        EFS: ctx.BIG.MODBYTES,
+        EGS: ctx.BIG.MODBYTES,
+        //PAS: 16,
+
+        SHA256: 32,
+        SHA384: 48,
+        SHA512: 64,
+
+        //HASH_TYPE: 32,
+
+        /* return time in slots since epoch */
+        today: function() {
+            var now = new Date();
+            return Math.floor(now.getTime() / (60000 * 1440)); // for daily tokens
+        },
+
+        bytestostring: function(b) {
+            var s = "",
+                len = b.length,
+                ch, i;
+
+            for (i = 0; i < len; i++) {
+                ch = b[i];
+                s += ((ch >>> 4) & 15).toString(16);
+                s += (ch & 15).toString(16);
+
+            }
+
+            return s;
+        },
+
+        stringtobytes: function(s) {
+            var b = [],
+                i;
+
+            for (i = 0; i < s.length; i++) {
+                b.push(s.charCodeAt(i));
+            }
+
+            return b;
+        },
+
+        comparebytes: function(a, b) {
+            if (a.length != b.length) {
+                return false;
+            }
+
+            for (var i = 0; i < a.length; i++) {
+                if (a[i] != b[i]) {
+                    return false;
+                }
+            }
+
+            return true;
+        },
+
+        mpin_hash: function(sha, c, U) {
+            var t = [],
+                w = [],
+                h = [],
+                H, R, i;
+
+            c.geta().getA().toBytes(w);
+            for (i = 0; i < this.EFS; i++) {
+                t[i] = w[i];
+            }
+            c.geta().getB().toBytes(w);
+            for (i = this.EFS; i < 2 * this.EFS; i++) {
+                t[i] = w[i - this.EFS];
+            }
+            c.getb().getA().toBytes(w);
+            for (i = 2 * this.EFS; i < 3 * this.EFS; i++) {
+                t[i] = w[i - 2 * this.EFS];
+            }
+            c.getb().getB().toBytes(w);
+            for (i = 3 * this.EFS; i < 4 * this.EFS; i++) {
+                t[i] = w[i - 3 * this.EFS];
+            }
+
+            U.getX().toBytes(w);
+            for (i = 4 * this.EFS; i < 5 * this.EFS; i++) {
+                t[i] = w[i - 4 * this.EFS];
+            }
+            U.getY().toBytes(w);
+            for (i = 5 * this.EFS; i < 6 * this.EFS; i++) {
+                t[i] = w[i - 5 * this.EFS];
+            }
+
+            if (sha == this.SHA256) {
+                H = new ctx.HASH256();
+            } else if (sha == this.SHA384) {
+                H = new ctx.HASH384();
+            } else if (sha == this.SHA512) {
+                H = new ctx.HASH512();
+            }
+
+            H.process_array(t);
+            h = H.hash();
+
+            if (h.length == 0) {
+                return null;
+            }
+
+            R = [];
+            for (i = 0; i < ctx.ECP.AESKEY; i++) {
+                R[i] = h[i];
+            }
+
+            return R;
+        },
+
+        /* Hash number (optional) and string to point on curve */
+        hashit: function(sha, n, B) {
+            var R = [],
+                H, W, i, len;
+
+            if (sha == this.SHA256) {
+                H = new ctx.HASH256();
+            } else if (sha == this.SHA384) {
+                H = new ctx.HASH384();
+            } else if (sha == this.SHA512) {
+                H = new ctx.HASH512();
+            }
+
+            if (n > 0) {
+                H.process_num(n);
+            }
+            H.process_array(B);
+            R = H.hash();
+
+            if (R.length == 0) {
+                return null;
+            }
+
+            W = [];
+
+            len = ctx.BIG.MODBYTES;
+
+            if (sha >= len) {
+                for (i = 0; i < len; i++) {
+                    W[i] = R[i];
+                }
+            } else {
+                for (i = 0; i < sha; i++) {
+                    W[i + len - sha] = R[i];
+                }
+
+                for (i = 0; i < len - sha; i++) {
+                    W[i] = 0;
+                }
+            }
+
+            return W;
+        },
+
+        /* these next two functions help to implement elligator squared - http://eprint.iacr.org/2014/043 */
+        /* maps a random u to a point on the curve */
+        map: function(u, cb) {
+            var P = new ctx.ECP(),
+                x = new ctx.BIG(u),
+                p = new ctx.BIG(0);
+
+            p.rcopy(ctx.ROM_FIELD.Modulus);
+            x.mod(p);
+
+            for (;;) {
+                P.setxi(x, cb);
+                if (!P.is_infinity()) {
+                    break;
+                }
+                x.inc(1);
+                x.norm();
+            }
+
+            return P;
+        },
+
+        /* returns u derived from P. Random value in range 1 to return value should then be added to u */
+        unmap: function(u, P) {
+            var s = P.getS(),
+                R = new ctx.ECP(),
+                r = 0,
+                x = P.getX();
+
+            u.copy(x);
+
+            for (;;) {
+                u.dec(1);
+                u.norm();
+                r++;
+                R.setxi(u, s); //=new ECP(u,s);
+                if (!R.is_infinity()) {
+                    break;
+                }
+            }
+
+            return r;
+        },
+
+        /* these next two functions implement elligator squared - http://eprint.iacr.org/2014/043 */
+        /* Elliptic curve point E in format (0x04,x,y} is converted to form {0x0-,u,v} */
+        /* Note that u and v are indistinguishable from random strings */
+        ENCODING: function(rng, E) {
+            var T = [],
+                i, rn, m, su, sv,
+                u, v, P, p, W;
+
+            for (i = 0; i < this.EFS; i++) {
+                T[i] = E[i + 1];
+            }
+            u = ctx.BIG.fromBytes(T);
+            for (i = 0; i < this.EFS; i++) {
+                T[i] = E[i + this.EFS + 1];
+            }
+            v = ctx.BIG.fromBytes(T);
+
+            P = new ctx.ECP(0);
+            P.setxy(u, v);
+            if (P.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            p = new ctx.BIG(0);
+            p.rcopy(ctx.ROM_FIELD.Modulus);
+            u = ctx.BIG.randomnum(p, rng);
+
+            su = rng.getByte();
+            if (su < 0) {
+                su = -su;
+            }
+            su %= 2;
+
+            W = this.map(u, su);
+            P.sub(W);
+            sv = P.getS();
+            rn = this.unmap(v, P);
+            m = rng.getByte();
+            if (m < 0) {
+                m = -m;
+            }
+            m %= rn;
+            v.inc(m + 1);
+            E[0] = (su + 2 * sv);
+            u.toBytes(T);
+            for (i = 0; i < this.EFS; i++) {
+                E[i + 1] = T[i];
+            }
+            v.toBytes(T);
+            for (i = 0; i < this.EFS; i++) {
+                E[i + this.EFS + 1] = T[i];
+            }
+
+            return 0;
+        },
+
+        DECODING: function(D) {
+            var T = [],
+                i, su, sv, u, v, W, P;
+
+            if ((D[0] & 0x04) !== 0) {
+                return this.INVALID_POINT;
+            }
+
+            for (i = 0; i < this.EFS; i++) {
+                T[i] = D[i + 1];
+            }
+            u = ctx.BIG.fromBytes(T);
+            for (i = 0; i < this.EFS; i++) {
+                T[i] = D[i + this.EFS + 1];
+            }
+            v = ctx.BIG.fromBytes(T);
+
+            su = D[0] & 1;
+            sv = (D[0] >> 1) & 1;
+            W = this.map(u, su);
+            P = this.map(v, sv);
+            P.add(W);
+            u = P.getX();
+            v = P.getY();
+            D[0] = 0x04;
+            u.toBytes(T);
+            for (i = 0; i < this.EFS; i++) {
+                D[i + 1] = T[i];
+            }
+            v.toBytes(T);
+            for (i = 0; i < this.EFS; i++) {
+                D[i + this.EFS + 1] = T[i];
+            }
+
+            return 0;
+        },
+
+        /* R=R1+R2 in group G1 */
+        RECOMBINE_G1: function(R1, R2, R) {
+            var P = ctx.ECP.fromBytes(R1),
+                Q = ctx.ECP.fromBytes(R2);
+
+            if (P.is_infinity() || Q.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            P.add(Q);
+
+            P.toBytes(R,false);
+
+            return 0;
+        },
+
+        /* W=W1+W2 in group G2 */
+        RECOMBINE_G2: function(W1, W2, W) {
+            var P = ctx.ECP2.fromBytes(W1),
+                Q = ctx.ECP2.fromBytes(W2);
+
+            if (P.is_infinity() || Q.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            P.add(Q);
+
+            P.toBytes(W);
+
+            return 0;
+        },
+
+        HASH_ID: function(sha, ID) {
+            return this.hashit(sha, 0, ID);
+        },
+
+        /* create random secret S */
+        RANDOM_GENERATE: function(rng, S) {
+            var r = new ctx.BIG(0),
+                s;
+
+            r.rcopy(ctx.ROM_CURVE.CURVE_Order);
+
+            s = ctx.BIG.randomnum(r, rng);
+            //if (ROM.AES_S>0)
+            //{
+            //  s.mod2m(2*ROM.AES_S);
+            //}
+            s.toBytes(S);
+
+            return 0;
+        },
+
+        /* Extract PIN from TOKEN for identity CID */
+        EXTRACT_PIN: function(sha, CID, pin, TOKEN) {
+            return this.EXTRACT_FACTOR(sha,CID,pin%this.MAXPIN,this.PBLEN,TOKEN);
+        },
+
+        /* Extract factor from TOKEN for identity CID */
+        EXTRACT_FACTOR: function(sha, CID, factor, facbits, TOKEN) {
+            var P, R, h;
+
+            P = ctx.ECP.fromBytes(TOKEN);
+
+            if (P.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            h = this.hashit(sha, 0, CID);
+            R = ctx.ECP.mapit(h);
+
+            R = R.pinmul(factor, facbits);
+            P.sub(R);
+
+            P.toBytes(TOKEN,false);
+
+            return 0;
+        },
+
+        /* Restore factor to TOKEN for identity CID */
+        RESTORE_FACTOR: function(sha, CID, factor, facbits, TOKEN) {
+            var P, R, h;
+
+            P = ctx.ECP.fromBytes(TOKEN);
+
+            if (P.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            h = this.hashit(sha, 0, CID),
+            R = ctx.ECP.mapit(h);
+
+            R = R.pinmul(factor, facbits);
+            P.add(R);
+
+            P.toBytes(TOKEN,false);
+
+            return 0;
+        },
+
+        /* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */
+        GET_SERVER_SECRET: function(S, SST) {
+            var s,Q;
+
+            Q = ctx.ECP2.generator();
+
+            s = ctx.BIG.fromBytes(S);
+            Q = ctx.PAIR.G2mul(Q, s);
+            Q.toBytes(SST);
+
+            return 0;
+        },
+
+        /*
+         W=x*H(G);
+         if RNG == NULL then X is passed in
+         if RNG != NULL the X is passed out
+         if type=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve
+        */
+        GET_G1_MULTIPLE: function(rng, type, X, G, W) {
+            var r = new ctx.BIG(0),
+                x, P;
+
+            r.rcopy(ctx.ROM_CURVE.CURVE_Order);
+
+            if (rng != null) {
+                x = ctx.BIG.randomnum(r, rng);
+                //if (ROM.AES_S>0)
+                //{
+                //  x.mod2m(2*ROM.AES_S);
+                //}
+                x.toBytes(X);
+            } else {
+                x = ctx.BIG.fromBytes(X);
+            }
+
+            if (type == 0) {
+                P = ctx.ECP.fromBytes(G);
+                if (P.is_infinity()) {
+                    return this.INVALID_POINT;
+                }
+            } else {
+                P = ctx.ECP.mapit(G);
+            }
+
+            ctx.PAIR.G1mul(P, x).toBytes(W,false);
+
+            return 0;
+        },
+
+
+        /* Client secret CST=S*H(CID) where CID is client ID and S is master secret */
+        GET_CLIENT_SECRET: function(S, CID, CST) {
+            return this.GET_G1_MULTIPLE(null, 1, S, CID, CST);
+        },
+
+        /* Time Permit CTT=S*(date|H(CID)) where S is master secret */
+        GET_CLIENT_PERMIT: function(sha, date, S, CID, CTT) {
+            var h = this.hashit(sha, date, CID),
+                P = ctx.ECP.mapit(h),
+                s = ctx.BIG.fromBytes(S);
+
+            P = ctx.PAIR.G1mul(P, s);
+            P.toBytes(CTT,false);
+
+            return 0;
+        },
+
+        /* Implement step 1 on client side of MPin protocol */
+        CLIENT_1: function(sha, date, CLIENT_ID, rng, X, pin, TOKEN, SEC, xID, xCID, PERMIT) {
+            var r = new ctx.BIG(0),
+                x, P, T, W, h;
+
+            r.rcopy(ctx.ROM_CURVE.CURVE_Order);
+
+            //  var q=new ctx.BIG(0); q.rcopy(ctx.ROM_FIELD.Modulus);
+            if (rng !== null) {
+                x = ctx.BIG.randomnum(r, rng);
+                //if (ROM.AES_S>0)
+                //{
+                //  x.mod2m(2*ROM.AES_S);
+                //}
+                x.toBytes(X);
+            } else {
+                x = ctx.BIG.fromBytes(X);
+            }
+
+            h = this.hashit(sha, 0, CLIENT_ID);
+            P = ctx.ECP.mapit(h);
+            T = ctx.ECP.fromBytes(TOKEN);
+            if (T.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            pin %= this.MAXPIN;
+            W = P.pinmul(pin, this.PBLEN);
+            T.add(W);
+
+            if (date != 0) {
+                W = ctx.ECP.fromBytes(PERMIT);
+
+                if (W.is_infinity()) {
+                    return this.INVALID_POINT;
+                }
+
+                T.add(W);
+                h = this.hashit(sha, date, h);
+                W = ctx.ECP.mapit(h);
+
+                if (xID != null) {
+                    P = ctx.PAIR.G1mul(P, x);
+                    P.toBytes(xID,false);
+                    W = ctx.PAIR.G1mul(W, x);
+                    P.add(W);
+                } else {
+                    P.add(W);
+                    P = ctx.PAIR.G1mul(P, x);
+                }
+
+                if (xCID != null) {
+                    P.toBytes(xCID,false);
+                }
+            } else {
+                if (xID != null) {
+                    P = ctx.PAIR.G1mul(P, x);
+                    P.toBytes(xID,false);
+                }
+            }
+
+            T.toBytes(SEC,false);
+
+            return 0;
+        },
+
+        /* Implement step 2 on client side of MPin protocol */
+        CLIENT_2: function(X, Y, SEC) {
+            var r = new ctx.BIG(0),
+                P, px, py;
+
+            r.rcopy(ctx.ROM_CURVE.CURVE_Order);
+
+            P = ctx.ECP.fromBytes(SEC);
+            if (P.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            px = ctx.BIG.fromBytes(X);
+            py = ctx.BIG.fromBytes(Y);
+            px.add(py);
+            px.mod(r);
+            //  px.rsub(r);
+
+            P = ctx.PAIR.G1mul(P, px);
+            P.neg();
+            P.toBytes(SEC,false);
+            //ctx.PAIR.G1mul(P,px).toBytes(SEC,false);
+
+            return 0;
+        },
+
+        /* Outputs H(CID) and H(T|H(CID)) for time permits. If no time permits set HID=HTID */
+        SERVER_1: function(sha, date, CID, HID, HTID) {
+            var h = this.hashit(sha, 0, CID),
+                P = ctx.ECP.mapit(h),
+                R;
+
+            P.toBytes(HID,false);
+            if (date !== 0) {
+                //if (HID!=null) P.toBytes(HID,false);
+                h = this.hashit(sha, date, h);
+                R = ctx.ECP.mapit(h);
+                P.add(R);
+                P.toBytes(HTID,false);
+            }
+            //else P.toBytes(HID,false);
+        },
+
+        /* Implement step 1 of MPin protocol on server side. Pa is the client public key in case of DVS, otherwise must be set to null */
+        SERVER_2: function(date, HID, HTID, Y, SST, xID, xCID, mSEC, E, F, Pa) {
+            var Q, sQ, R, y, P, g;
+
+            if (typeof Pa === "undefined" || Pa == null) {
+                Q = ctx.ECP2.generator();
+
+            } else {
+                Q = ctx.ECP2.fromBytes(Pa);
+                if (Q.is_infinity()) {
+                    return this.INVALID_POINT;
+                }
+            }
+
+            sQ = ctx.ECP2.fromBytes(SST);
+            if (sQ.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            if (date !== 0) {
+                R = ctx.ECP.fromBytes(xCID);
+            } else {
+                if (xID == null) {
+                    return this.BAD_PARAMS;
+                }
+                R = ctx.ECP.fromBytes(xID);
+            }
+
+            if (R.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            y = ctx.BIG.fromBytes(Y);
+
+            if (date != 0) {
+                P = ctx.ECP.fromBytes(HTID);
+            } else {
+                if (HID == null) {
+                    return this.BAD_PARAMS;
+                }
+                P = ctx.ECP.fromBytes(HID);
+            }
+
+            if (P.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            P = ctx.PAIR.G1mul(P, y);
+            P.add(R);
+            //P.affine();
+            R = ctx.ECP.fromBytes(mSEC);
+            if (R.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            g = ctx.PAIR.ate2(Q, R, sQ, P);
+            g = ctx.PAIR.fexp(g);
+
+            if (!g.isunity()) {
+                if (HID != null && xID != null && E != null && F != null) {
+                    g.toBytes(E);
+
+                    if (date !== 0) {
+                        P = ctx.ECP.fromBytes(HID);
+                        if (P.is_infinity()) {
+                            return this.INVALID_POINT;
+                        }
+
+                        R = ctx.ECP.fromBytes(xID);
+                        if (R.is_infinity()) {
+                            return this.INVALID_POINT;
+                        }
+
+                        P = ctx.PAIR.G1mul(P, y);
+                        P.add(R);
+                        //P.affine();
+                    }
+                    g = ctx.PAIR.ate(Q, P);
+                    g = ctx.PAIR.fexp(g);
+
+                    g.toBytes(F);
+                }
+
+                return this.BAD_PIN;
+            }
+
+            return 0;
+        },
+
+        /* Pollards kangaroos used to return PIN error */
+        KANGAROO: function(E, F) {
+            var ge = ctx.FP12.fromBytes(E),
+                gf = ctx.FP12.fromBytes(F),
+                distance = [],
+                t = new ctx.FP12(gf),
+                table = [],
+                i, j, m, s, dn, dm, res, steps;
+
+            s = 1;
+            for (m = 0; m < this.TS; m++) {
+                distance[m] = s;
+                table[m] = new ctx.FP12(t);
+                s *= 2;
+                t.usqr();
+            }
+            t.one();
+            dn = 0;
+            for (j = 0; j < this.TRAP; j++) {
+                i = t.geta().geta().getA().lastbits(20) % this.TS;
+                t.mul(table[i]);
+                dn += distance[i];
+            }
+            gf.copy(t);
+            gf.conj();
+            steps = 0;
+            dm = 0;
+            res = 0;
+            while (dm - dn < this.MAXPIN) {
+                steps++;
+                if (steps > 4 * this.TRAP) {
+                    break;
+                }
+                i = ge.geta().geta().getA().lastbits(20) % this.TS;
+                ge.mul(table[i]);
+                dm += distance[i];
+                if (ge.equals(t)) {
+                    res = dm - dn;
+                    break;
+                }
+                if (ge.equals(gf)) {
+                    res = dn - dm;
+                    break;
+                }
+
+            }
+            if (steps > 4 * this.TRAP || dm - dn >= this.MAXPIN) {
+                res = 0;
+            } // Trap Failed  - probable invalid token
+
+            return res;
+        },
+
+        /* return time  since epoch */
+        GET_TIME: function() {
+            var now = new Date();
+            return Math.floor(now.getTime() / (1000));
+        },
+
+        /* y = H(time,xCID) */
+        GET_Y: function(sha, TimeValue, xCID, Y) {
+            var q = new ctx.BIG(0),
+                h = this.hashit(sha, TimeValue, xCID),
+                y = ctx.BIG.fromBytes(h);
+
+            q.rcopy(ctx.ROM_CURVE.CURVE_Order);
+
+            y.mod(q);
+            //if (ROM.AES_S>0)
+            //{
+            //  y.mod2m(2*ROM.AES_S);
+            //}
+            y.toBytes(Y);
+
+            return 0;
+        },
+
+        /* One pass MPIN Client - DVS signature. Message must be null in case of One pass MPIN. */
+        CLIENT: function(sha, date, CLIENT_ID, rng, X, pin, TOKEN, SEC, xID, xCID, PERMIT, TimeValue, Y, Message) {
+            var rtn = 0,
+                M = [],
+                pID, i;
+
+            if (date == 0) {
+                pID = xID;
+            } else {
+                pID = xCID;
+                xID = null;
+            }
+
+            rtn = this.CLIENT_1(sha, date, CLIENT_ID, rng, X, pin, TOKEN, SEC, xID, xCID, PERMIT);
+            if (rtn != 0) {
+                return rtn;
+            }
+
+            M = pID.slice();
+
+            if (typeof Message !== "undefined" || Message != null) {
+                for (i = 0; i < Message.length; i++) {
+                    M.push(Message[i]);
+                }
+            }
+
+            this.GET_Y(sha, TimeValue, M, Y);
+
+            rtn = this.CLIENT_2(X, Y, SEC);
+            if (rtn != 0) {
+                return rtn;
+            }
+
+            return 0;
+        },
+
+        /* One pass MPIN Server */
+        SERVER: function(sha, date, HID, HTID, Y, SST, xID, xCID, mSEC, E, F, CID, TimeValue, Message, Pa) {
+            var rtn = 0,
+                M = [],
+                pID, i;
+
+            if (date == 0) {
+                pID = xID;
+            } else {
+                pID = xCID;
+            }
+
+            this.SERVER_1(sha, date, CID, HID, HTID);
+
+            M = pID.slice();
+
+            if (typeof Message !== "undefined" || Message != null) {
+                for (i = 0; i < Message.length; i++) {
+                    M.push(Message[i]);
+                }
+            }
+
+            this.GET_Y(sha, TimeValue, M, Y);
+
+            rtn = this.SERVER_2(date, HID, HTID, Y, SST, xID, xCID, mSEC, E, F, Pa);
+            if (rtn != 0) {
+                return rtn;
+            }
+
+            return 0;
+        },
+
+        /* Functions to support M-Pin Full */
+        PRECOMPUTE: function(TOKEN, CID, G1, G2) {
+            var P, T, g, Q;
+
+            T = ctx.ECP.fromBytes(TOKEN);
+            if (T.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            P = ctx.ECP.mapit(CID);
+            Q = ctx.ECP2.generator();
+
+            g = ctx.PAIR.ate(Q, T);
+            g = ctx.PAIR.fexp(g);
+            g.toBytes(G1);
+
+            g = ctx.PAIR.ate(Q, P);
+            g = ctx.PAIR.fexp(g);
+            g.toBytes(G2);
+
+            return 0;
+        },
+
+        /* Hash the M-Pin transcript - new */
+
+        HASH_ALL: function(sha, HID, xID, xCID, SEC, Y, R, W) {
+            var tlen = 0,
+                T = [],
+                i;
+
+            for (i = 0; i < HID.length; i++) {
+                T[i] = HID[i];
+            }
+            tlen += HID.length;
+
+            if (xCID != null) {
+                for (i = 0; i < xCID.length; i++) {
+                    T[i + tlen] = xCID[i];
+                }
+                tlen += xCID.length;
+            } else {
+                for (i = 0; i < xID.length; i++) {
+                    T[i + tlen] = xID[i];
+                }
+                tlen += xID.length;
+            }
+
+            for (i = 0; i < SEC.length; i++) {
+                T[i + tlen] = SEC[i];
+            }
+            tlen += SEC.length;
+
+            for (i = 0; i < Y.length; i++) {
+                T[i + tlen] = Y[i];
+            }
+            tlen += Y.length;
+
+            for (i = 0; i < R.length; i++) {
+                T[i + tlen] = R[i];
+            }
+            tlen += R.length;
+
+            for (i = 0; i < W.length; i++) {
+                T[i + tlen] = W[i];
+            }
+            tlen += W.length;
+
+            return this.hashit(sha, 0, T);
+        },
+
+        /* calculate common key on client side */
+        /* wCID = w.(A+AT) */
+        CLIENT_KEY: function(sha, G1, G2, pin, R, X, H, wCID, CK) {
+            var t = [],
+                g1 = ctx.FP12.fromBytes(G1),
+                g2 = ctx.FP12.fromBytes(G2),
+                z = ctx.BIG.fromBytes(R),
+                x = ctx.BIG.fromBytes(X),
+                h = ctx.BIG.fromBytes(H),
+                W = ctx.ECP.fromBytes(wCID),
+                r, c, i;
+
+            if (W.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            W = ctx.PAIR.G1mul(W, x);
+
+            //  var fa=new ctx.BIG(0); fa.rcopy(ctx.ROM_FIELD.Fra);
+            //  var fb=new ctx.BIG(0); fb.rcopy(ctx.ROM_FIELD.Frb);
+            //  var f=new ctx.FP2(fa,fb); //f.bset(fa,fb);
+
+            r = new ctx.BIG(0);
+            r.rcopy(ctx.ROM_CURVE.CURVE_Order);
+            //  var q=new ctx.BIG(0); q.rcopy(ctx.ROM_FIELD.Modulus);
+
+            z.add(h);
+            z.mod(r);
+
+            g2.pinpow(pin, this.PBLEN);
+            g1.mul(g2);
+
+            c = g1.compow(z, r);
+            // var m=new ctx.BIG(q);
+            // m.mod(r);
+
+            // var a=new ctx.BIG(z);
+            // a.mod(m);
+
+            // var b=new ctx.BIG(z);
+            // b.div(m);
+
+
+            // var c=g1.trace();
+            // g2.copy(g1);
+            // g2.frob(f);
+            // var cp=g2.trace();
+            // g1.conj();
+            // g2.mul(g1);
+            // var cpm1=g2.trace();
+            // g2.mul(g1);
+            // var cpm2=g2.trace();
+
+            // c=c.xtr_pow2(cp,cpm1,cpm2,a,b);
+
+            t = this.mpin_hash(sha, c, W);
+
+            for (i = 0; i < ctx.ECP.AESKEY; i++) {
+                CK[i] = t[i];
+            }
+
+            return 0;
+        },
+
+        /* calculate common key on server side */
+        /* Z=r.A - no time permits involved */
+
+        SERVER_KEY: function(sha, Z, SST, W, H, HID, xID, xCID, SK) {
+            var t = [],
+                sQ, R, A, U, w, h, g, c, i;
+
+            sQ = ctx.ECP2.fromBytes(SST);
+            if (sQ.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            R = ctx.ECP.fromBytes(Z);
+            if (R.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            A = ctx.ECP.fromBytes(HID);
+            if (A.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            if (xCID != null) {
+                U = ctx.ECP.fromBytes(xCID);
+            } else {
+                U = ctx.ECP.fromBytes(xID);
+            }
+
+            if (U.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            w = ctx.BIG.fromBytes(W);
+            h = ctx.BIG.fromBytes(H);
+            A = ctx.PAIR.G1mul(A, h);
+            R.add(A);
+            //R.affine();
+
+            U = ctx.PAIR.G1mul(U, w);
+            g = ctx.PAIR.ate(sQ, R);
+            g = ctx.PAIR.fexp(g);
+
+            c = g.trace();
+
+            t = this.mpin_hash(sha, c, U);
+
+            for (i = 0; i < ctx.ECP.AESKEY; i++) {
+                SK[i] = t[i];
+            }
+
+            return 0;
+        },
+
+        /* Generate a public key and the corresponding z for the key-escrow less scheme */
+        /*
+            if R==NULL then Z is passed in
+            if R!=NULL then Z is passed out
+            Pa=(z^-1).Q
+        */
+        GET_DVS_KEYPAIR: function(rng, Z, Pa) {
+            var r = new ctx.BIG(0),
+                z, Q;
+
+            r.rcopy(ctx.ROM_CURVE.CURVE_Order);
+
+            if (rng != null) {
+                z = ctx.BIG.randomnum(r, rng);
+                z.toBytes(Z);
+            } else {
+                z = ctx.BIG.fromBytes(Z);
+            }
+            z.invmodp(r);
+
+            Q = ctx.ECP2.generator();
+
+            Q = ctx.PAIR.G2mul(Q, z);
+            Q.toBytes(Pa);
+
+            return 0;
+        }
+    };
+
+    return MPIN;
+};
diff --git a/version3/js/mpin192.js b/version3/js/mpin192.js
new file mode 100644
index 0000000..3d30505
--- /dev/null
+++ b/version3/js/mpin192.js
@@ -0,0 +1,1046 @@
+/*
+    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.
+*/
+
+/* MPIN API Functions */
+
+var MPIN192 = function(ctx) {
+    "use strict";
+
+    var MPIN192 = {
+        BAD_PARAMS: -11,
+        INVALID_POINT: -14,
+        WRONG_ORDER: -18,
+        BAD_PIN: -19,
+        /* configure PIN here */
+        MAXPIN: 10000,
+        /* max PIN */
+        PBLEN: 14,
+        /* MAXPIN length in bits */
+        TS: 12,
+        /* 10 for 4 digit PIN, 14 for 6-digit PIN - 2^TS/TS approx = sqrt(MAXPIN) */
+        TRAP: 2000,
+        /* 200 for 4 digit PIN, 2000 for 6-digit PIN  - approx 2*sqrt(MAXPIN) */
+        EFS: ctx.BIG.MODBYTES,
+        EGS: ctx.BIG.MODBYTES,
+        //PAS: 16,
+
+        SHA256: 32,
+        SHA384: 48,
+        SHA512: 64,
+
+        //HASH_TYPE: 32,
+
+        /* return time in slots since epoch */
+        today: function() {
+            var now = new Date();
+            return Math.floor(now.getTime() / (60000 * 1440)); // for daily tokens
+        },
+
+        bytestostring: function(b) {
+            var s = "",
+                len = b.length,
+                ch, i;
+
+            for (i = 0; i < len; i++) {
+                ch = b[i];
+                s += ((ch >>> 4) & 15).toString(16);
+                s += (ch & 15).toString(16);
+
+            }
+
+            return s;
+        },
+
+        stringtobytes: function(s) {
+            var b = [],
+                i;
+
+            for (i = 0; i < s.length; i++) {
+                b.push(s.charCodeAt(i));
+            }
+
+            return b;
+        },
+
+        comparebytes: function(a, b) {
+            if (a.length != b.length) {
+                return false;
+            }
+
+            for (var i = 0; i < a.length; i++) {
+                if (a[i] != b[i]) {
+                    return false;
+                }
+            }
+
+            return true;
+        },
+
+        mpin_hash: function(sha, c, U) {
+            var t = [],
+                w = [],
+                h = [],
+                H, R, i;
+
+            c.geta().geta().getA().toBytes(w);
+            for (i = 0; i < this.EFS; i++) {
+                t[i] = w[i];
+            }
+            c.geta().geta().getB().toBytes(w);
+            for (i = this.EFS; i < 2 * this.EFS; i++) {
+                t[i] = w[i - this.EFS];
+            }
+            c.geta().getb().getA().toBytes(w);
+            for (i = 2 * this.EFS; i < 3 * this.EFS; i++) {
+                t[i] = w[i - 2 * this.EFS];
+            }
+            c.geta().getb().getB().toBytes(w);
+            for (i = 3 * this.EFS; i < 4 * this.EFS; i++) {
+                t[i] = w[i - 3 * this.EFS];
+            }
+
+            c.getb().geta().getA().toBytes(w);
+            for (i = 4 * this.EFS; i < 5 * this.EFS; i++) {
+                t[i] = w[i - 4 * this.EFS];
+            }
+            c.getb().geta().getB().toBytes(w);
+            for (i = 5 * this.EFS; i < 6 * this.EFS; i++) {
+                t[i] = w[i - 5 * this.EFS];
+            }
+            c.getb().getb().getA().toBytes(w);
+            for (i = 6 * this.EFS; i < 7 * this.EFS; i++) {
+                t[i] = w[i - 6 * this.EFS];
+            }
+            c.getb().getb().getB().toBytes(w);
+            for (i = 7 * this.EFS; i < 8 * this.EFS; i++) {
+                t[i] = w[i - 7 * this.EFS];
+            }
+
+
+            U.getX().toBytes(w);
+            for (i = 8 * this.EFS; i < 9 * this.EFS; i++) {
+                t[i] = w[i - 8 * this.EFS];
+            }
+            U.getY().toBytes(w);
+            for (i = 9 * this.EFS; i < 10 * this.EFS; i++) {
+                t[i] = w[i - 9 * this.EFS];
+            }
+
+            if (sha == this.SHA256) {
+                H = new ctx.HASH256();
+            } else if (sha == this.SHA384) {
+                H = new ctx.HASH384();
+            } else if (sha == this.SHA512) {
+                H = new ctx.HASH512();
+            }
+
+            H.process_array(t);
+            h = H.hash();
+
+            if (h.length == 0) {
+                return null;
+            }
+
+            R = [];
+            for (i = 0; i < ctx.ECP.AESKEY; i++) {
+                R[i] = h[i];
+            }
+
+            return R;
+        },
+
+        /* Hash number (optional) and string to point on curve */
+        hashit: function(sha, n, B) {
+            var R = [],
+                H, W, i, len;
+
+            if (sha == this.SHA256) {
+                H = new ctx.HASH256();
+            } else if (sha == this.SHA384) {
+                H = new ctx.HASH384();
+            } else if (sha == this.SHA512) {
+                H = new ctx.HASH512();
+            }
+
+            if (n > 0) {
+                H.process_num(n);
+            }
+            H.process_array(B);
+            R = H.hash();
+
+            if (R.length == 0) {
+                return null;
+            }
+
+            W = [];
+
+            len = ctx.BIG.MODBYTES;
+
+            if (sha >= len) {
+                for (i = 0; i < len; i++) {
+                    W[i] = R[i];
+                }
+            } else {
+                for (i = 0; i < sha; i++) {
+                    W[i + len - sha] = R[i];
+                }
+
+                for (i = 0; i < len - sha; i++) {
+                    W[i] = 0;
+                }
+            }
+
+            return W;
+        },
+
+        /* these next two functions help to implement elligator squared - http://eprint.iacr.org/2014/043 */
+        /* maps a random u to a point on the curve */
+        map: function(u, cb) {
+            var P = new ctx.ECP(),
+                x = new ctx.BIG(u),
+                p = new ctx.BIG(0);
+
+            p.rcopy(ctx.ROM_FIELD.Modulus);
+            x.mod(p);
+
+            for (;;) {
+                P.setxi(x, cb);
+                if (!P.is_infinity()) {
+                    break;
+                }
+                x.inc(1);
+                x.norm();
+            }
+
+            return P;
+        },
+
+        /* returns u derived from P. Random value in range 1 to return value should then be added to u */
+        unmap: function(u, P) {
+            var s = P.getS(),
+                R = new ctx.ECP(),
+                r = 0,
+                x = P.getX();
+
+            u.copy(x);
+
+            for (;;) {
+                u.dec(1);
+                u.norm();
+                r++;
+                R.setxi(u, s); //=new ECP(u,s);
+                if (!R.is_infinity()) {
+                    break;
+                }
+            }
+
+            return r;
+        },
+
+        /* these next two functions implement elligator squared - http://eprint.iacr.org/2014/043 */
+        /* Elliptic curve point E in format (0x04,x,y} is converted to form {0x0-,u,v} */
+        /* Note that u and v are indistinguishable from random strings */
+        ENCODING: function(rng, E) {
+            var T = [],
+                i, rn, m, su, sv,
+                u, v, P, p, W;
+
+            for (i = 0; i < this.EFS; i++) {
+                T[i] = E[i + 1];
+            }
+            u = ctx.BIG.fromBytes(T);
+            for (i = 0; i < this.EFS; i++) {
+                T[i] = E[i + this.EFS + 1];
+            }
+            v = ctx.BIG.fromBytes(T);
+
+            P = new ctx.ECP(0);
+            P.setxy(u, v);
+            if (P.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            p = new ctx.BIG(0);
+            p.rcopy(ctx.ROM_FIELD.Modulus);
+            u = ctx.BIG.randomnum(p, rng);
+
+            su = rng.getByte();
+            if (su < 0) {
+                su = -su;
+            }
+            su %= 2;
+
+            W = this.map(u, su);
+            P.sub(W);
+            sv = P.getS();
+            rn = this.unmap(v, P);
+            m = rng.getByte();
+            if (m < 0) {
+                m = -m;
+            }
+            m %= rn;
+            v.inc(m + 1);
+            E[0] = (su + 2 * sv);
+            u.toBytes(T);
+            for (i = 0; i < this.EFS; i++) {
+                E[i + 1] = T[i];
+            }
+            v.toBytes(T);
+            for (i = 0; i < this.EFS; i++) {
+                E[i + this.EFS + 1] = T[i];
+            }
+
+            return 0;
+        },
+
+        DECODING: function(D) {
+            var T = [],
+                i, su, sv, u, v, W, P;
+
+            if ((D[0] & 0x04) !== 0) {
+                return this.INVALID_POINT;
+            }
+
+            for (i = 0; i < this.EFS; i++) {
+                T[i] = D[i + 1];
+            }
+            u = ctx.BIG.fromBytes(T);
+            for (i = 0; i < this.EFS; i++) {
+                T[i] = D[i + this.EFS + 1];
+            }
+            v = ctx.BIG.fromBytes(T);
+
+            su = D[0] & 1;
+            sv = (D[0] >> 1) & 1;
+            W = this.map(u, su);
+            P = this.map(v, sv);
+            P.add(W);
+            u = P.getX();
+            v = P.getY();
+            D[0] = 0x04;
+            u.toBytes(T);
+            for (i = 0; i < this.EFS; i++) {
+                D[i + 1] = T[i];
+            }
+            v.toBytes(T);
+            for (i = 0; i < this.EFS; i++) {
+                D[i + this.EFS + 1] = T[i];
+            }
+
+            return 0;
+        },
+
+        /* R=R1+R2 in group G1 */
+        RECOMBINE_G1: function(R1, R2, R) {
+            var P = ctx.ECP.fromBytes(R1),
+                Q = ctx.ECP.fromBytes(R2);
+
+            if (P.is_infinity() || Q.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            P.add(Q);
+
+            P.toBytes(R,false);
+
+            return 0;
+        },
+
+        /* W=W1+W2 in group G2 */
+        RECOMBINE_G2: function(W1, W2, W) {
+            var P = ctx.ECP4.fromBytes(W1),
+                Q = ctx.ECP4.fromBytes(W2);
+
+            if (P.is_infinity() || Q.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            P.add(Q);
+
+            P.toBytes(W);
+
+            return 0;
+        },
+
+        HASH_ID: function(sha, ID) {
+            return this.hashit(sha, 0, ID);
+        },
+
+        /* create random secret S */
+        RANDOM_GENERATE: function(rng, S) {
+            var r = new ctx.BIG(0),
+                s;
+
+            r.rcopy(ctx.ROM_CURVE.CURVE_Order);
+
+            s = ctx.BIG.randomnum(r, rng);
+            //if (ROM.AES_S>0)
+            //{
+            //  s.mod2m(2*ROM.AES_S);
+            //}
+            s.toBytes(S);
+
+            return 0;
+        },
+
+        /* Extract PIN from TOKEN for identity CID */
+        EXTRACT_PIN: function(sha, CID, pin, TOKEN) {
+            return this.EXTRACT_FACTOR(sha,CID,pin%this.MAXPIN,this.PBLEN,TOKEN);
+        },
+
+        /* Extract factor from TOKEN for identity CID */
+        EXTRACT_FACTOR: function(sha, CID, factor, facbits, TOKEN) {
+            var P, R, h;
+
+            P = ctx.ECP.fromBytes(TOKEN);
+
+            if (P.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            h = this.hashit(sha, 0, CID);
+            R = ctx.ECP.mapit(h);
+
+            R = R.pinmul(factor, facbits);
+            P.sub(R);
+
+            P.toBytes(TOKEN,false);
+
+            return 0;
+        },
+
+        /* Restore factor to TOKEN for identity CID */
+        RESTORE_FACTOR: function(sha, CID, factor, facbits, TOKEN) {
+            var P, R, h;
+
+            P = ctx.ECP.fromBytes(TOKEN);
+
+            if (P.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            h = this.hashit(sha, 0, CID),
+            R = ctx.ECP.mapit(h);
+
+            R = R.pinmul(factor, facbits);
+            P.add(R);
+
+            P.toBytes(TOKEN,false);
+
+            return 0;
+        },
+
+        /* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */
+        GET_SERVER_SECRET: function(S, SST) {
+            var s,Q;
+
+            Q = ctx.ECP4.generator();
+
+            s = ctx.BIG.fromBytes(S);
+            Q = ctx.PAIR192.G2mul(Q, s);
+            Q.toBytes(SST);
+
+            return 0;
+        },
+
+        /*
+         W=x*H(G);
+         if RNG == NULL then X is passed in
+         if RNG != NULL the X is passed out
+         if type=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve
+        */
+        GET_G1_MULTIPLE: function(rng, type, X, G, W) {
+            var r = new ctx.BIG(0),
+                x, P;
+
+            r.rcopy(ctx.ROM_CURVE.CURVE_Order);
+
+            if (rng != null) {
+                x = ctx.BIG.randomnum(r, rng);
+                //if (ROM.AES_S>0)
+                //{
+                //  x.mod2m(2*ROM.AES_S);
+                //}
+                x.toBytes(X);
+            } else {
+                x = ctx.BIG.fromBytes(X);
+            }
+
+            if (type == 0) {
+                P = ctx.ECP.fromBytes(G);
+                if (P.is_infinity()) {
+                    return this.INVALID_POINT;
+                }
+            } else {
+                P = ctx.ECP.mapit(G);
+            }
+
+            ctx.PAIR192.G1mul(P, x).toBytes(W,false);
+
+            return 0;
+        },
+
+
+        /* Client secret CST=S*H(CID) where CID is client ID and S is master secret */
+        GET_CLIENT_SECRET: function(S, CID, CST) {
+            return this.GET_G1_MULTIPLE(null, 1, S, CID, CST);
+        },
+
+        /* Time Permit CTT=S*(date|H(CID)) where S is master secret */
+        GET_CLIENT_PERMIT: function(sha, date, S, CID, CTT) {
+            var h = this.hashit(sha, date, CID),
+                P = ctx.ECP.mapit(h),
+                s = ctx.BIG.fromBytes(S);
+
+            P = ctx.PAIR192.G1mul(P, s);
+            P.toBytes(CTT,false);
+
+            return 0;
+        },
+
+        /* Implement step 1 on client side of MPin protocol */
+        CLIENT_1: function(sha, date, CLIENT_ID, rng, X, pin, TOKEN, SEC, xID, xCID, PERMIT) {
+            var r = new ctx.BIG(0),
+                x, P, T, W, h;
+
+            r.rcopy(ctx.ROM_CURVE.CURVE_Order);
+
+            //  var q=new ctx.BIG(0); q.rcopy(ctx.ROM_FIELD.Modulus);
+            if (rng !== null) {
+                x = ctx.BIG.randomnum(r, rng);
+                //if (ROM.AES_S>0)
+                //{
+                //  x.mod2m(2*ROM.AES_S);
+                //}
+                x.toBytes(X);
+            } else {
+                x = ctx.BIG.fromBytes(X);
+            }
+
+            h = this.hashit(sha, 0, CLIENT_ID);
+            P = ctx.ECP.mapit(h);
+            T = ctx.ECP.fromBytes(TOKEN);
+            if (T.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            pin %= this.MAXPIN;
+            W = P.pinmul(pin, this.PBLEN);
+            T.add(W);
+
+            if (date != 0) {
+                W = ctx.ECP.fromBytes(PERMIT);
+
+                if (W.is_infinity()) {
+                    return this.INVALID_POINT;
+                }
+
+                T.add(W);
+                h = this.hashit(sha, date, h);
+                W = ctx.ECP.mapit(h);
+
+                if (xID != null) {
+                    P = ctx.PAIR192.G1mul(P, x);
+                    P.toBytes(xID,false);
+                    W = ctx.PAIR192.G1mul(W, x);
+                    P.add(W);
+                } else {
+                    P.add(W);
+                    P = ctx.PAIR192.G1mul(P, x);
+                }
+
+                if (xCID != null) {
+                    P.toBytes(xCID,false);
+                }
+            } else {
+                if (xID != null) {
+                    P = ctx.PAIR192.G1mul(P, x);
+                    P.toBytes(xID,false);
+                }
+            }
+
+            T.toBytes(SEC,false);
+
+            return 0;
+        },
+
+        /* Implement step 2 on client side of MPin protocol */
+        CLIENT_2: function(X, Y, SEC) {
+            var r = new ctx.BIG(0),
+                P, px, py;
+
+            r.rcopy(ctx.ROM_CURVE.CURVE_Order);
+
+            P = ctx.ECP.fromBytes(SEC);
+            if (P.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            px = ctx.BIG.fromBytes(X);
+            py = ctx.BIG.fromBytes(Y);
+            px.add(py);
+            px.mod(r);
+            //  px.rsub(r);
+
+            P = ctx.PAIR192.G1mul(P, px);
+            P.neg();
+            P.toBytes(SEC,false);
+            //ctx.PAIR192.G1mul(P,px).toBytes(SEC,false);
+
+            return 0;
+        },
+
+        /* Outputs H(CID) and H(T|H(CID)) for time permits. If no time permits set HID=HTID */
+        SERVER_1: function(sha, date, CID, HID, HTID) {
+            var h = this.hashit(sha, 0, CID),
+                P = ctx.ECP.mapit(h),
+                R;
+
+            P.toBytes(HID,false);
+            if (date !== 0) {
+                //if (HID!=null) P.toBytes(HID,false);
+                h = this.hashit(sha, date, h);
+                R = ctx.ECP.mapit(h);
+                P.add(R);
+                P.toBytes(HTID,false);
+            }
+            //else P.toBytes(HID,false);
+        },
+
+        /* Implement step 1 of MPin protocol on server side. Pa is the client public key in case of DVS, otherwise must be set to null */
+        SERVER_2: function(date, HID, HTID, Y, SST, xID, xCID, mSEC, E, F, Pa) {
+            var Q, sQ, R, y, P, g;
+
+            if (typeof Pa === "undefined" || Pa == null) {
+                Q = ctx.ECP4.generator();
+
+            } else {
+                Q = ctx.ECP4.fromBytes(Pa);
+                if (Q.is_infinity()) {
+                    return this.INVALID_POINT;
+                }
+            }
+
+            sQ = ctx.ECP4.fromBytes(SST);
+            if (sQ.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            if (date !== 0) {
+                R = ctx.ECP.fromBytes(xCID);
+            } else {
+                if (xID == null) {
+                    return this.BAD_PARAMS;
+                }
+                R = ctx.ECP.fromBytes(xID);
+            }
+
+            if (R.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            y = ctx.BIG.fromBytes(Y);
+
+            if (date != 0) {
+                P = ctx.ECP.fromBytes(HTID);
+            } else {
+                if (HID == null) {
+                    return this.BAD_PARAMS;
+                }
+                P = ctx.ECP.fromBytes(HID);
+            }
+
+            if (P.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            P = ctx.PAIR192.G1mul(P, y);
+            P.add(R);
+            //P.affine();
+            R = ctx.ECP.fromBytes(mSEC);
+            if (R.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            g = ctx.PAIR192.ate2(Q, R, sQ, P);
+            g = ctx.PAIR192.fexp(g);
+
+            if (!g.isunity()) {
+                if (HID != null && xID != null && E != null && F != null) {
+                    g.toBytes(E);
+
+                    if (date !== 0) {
+                        P = ctx.ECP.fromBytes(HID);
+                        if (P.is_infinity()) {
+                            return this.INVALID_POINT;
+                        }
+
+                        R = ctx.ECP.fromBytes(xID);
+                        if (R.is_infinity()) {
+                            return this.INVALID_POINT;
+                        }
+
+                        P = ctx.PAIR192.G1mul(P, y);
+                        P.add(R);
+                        //P.affine();
+                    }
+                    g = ctx.PAIR192.ate(Q, P);
+                    g = ctx.PAIR192.fexp(g);
+
+                    g.toBytes(F);
+                }
+
+                return this.BAD_PIN;
+            }
+
+            return 0;
+        },
+
+        /* Pollards kangaroos used to return PIN error */
+        KANGAROO: function(E, F) {
+            var ge = ctx.FP24.fromBytes(E),
+                gf = ctx.FP24.fromBytes(F),
+                distance = [],
+                t = new ctx.FP24(gf),
+                table = [],
+                i, j, m, s, dn, dm, res, steps;
+
+            s = 1;
+            for (m = 0; m < this.TS; m++) {
+                distance[m] = s;
+                table[m] = new ctx.FP24(t);
+                s *= 2;
+                t.usqr();
+            }
+            t.one();
+            dn = 0;
+            for (j = 0; j < this.TRAP; j++) {
+                i = t.geta().geta().geta().getA().lastbits(20) % this.TS;
+                t.mul(table[i]);
+                dn += distance[i];
+            }
+            gf.copy(t);
+            gf.conj();
+            steps = 0;
+            dm = 0;
+            res = 0;
+            while (dm - dn < this.MAXPIN) {
+                steps++;
+                if (steps > 4 * this.TRAP) {
+                    break;
+                }
+                i = ge.geta().geta().geta().getA().lastbits(20) % this.TS;
+                ge.mul(table[i]);
+                dm += distance[i];
+                if (ge.equals(t)) {
+                    res = dm - dn;
+                    break;
+                }
+                if (ge.equals(gf)) {
+                    res = dn - dm;
+                    break;
+                }
+
+            }
+            if (steps > 4 * this.TRAP || dm - dn >= this.MAXPIN) {
+                res = 0;
+            } // Trap Failed  - probable invalid token
+
+            return res;
+        },
+
+        /* return time  since epoch */
+        GET_TIME: function() {
+            var now = new Date();
+            return Math.floor(now.getTime() / (1000));
+        },
+
+        /* y = H(time,xCID) */
+        GET_Y: function(sha, TimeValue, xCID, Y) {
+            var q = new ctx.BIG(0),
+                h = this.hashit(sha, TimeValue, xCID),
+                y = ctx.BIG.fromBytes(h);
+
+            q.rcopy(ctx.ROM_CURVE.CURVE_Order);
+
+            y.mod(q);
+            //if (ROM.AES_S>0)
+            //{
+            //  y.mod2m(2*ROM.AES_S);
+            //}
+            y.toBytes(Y);
+
+            return 0;
+        },
+
+        /* One pass MPIN Client - DVS signature. Message must be null in case of One pass MPIN. */
+        CLIENT: function(sha, date, CLIENT_ID, rng, X, pin, TOKEN, SEC, xID, xCID, PERMIT, TimeValue, Y, Message) {
+            var rtn = 0,
+                M = [],
+                pID, i;
+
+            if (date == 0) {
+                pID = xID;
+            } else {
+                pID = xCID;
+                xID = null;
+            }
+
+            rtn = this.CLIENT_1(sha, date, CLIENT_ID, rng, X, pin, TOKEN, SEC, xID, xCID, PERMIT);
+            if (rtn != 0) {
+                return rtn;
+            }
+
+            M = pID.slice();
+
+            if (typeof Message !== "undefined" || Message != null) {
+                for (i = 0; i < Message.length; i++) {
+                    M.push(Message[i]);
+                }
+            }
+
+            this.GET_Y(sha, TimeValue, M, Y);
+
+            rtn = this.CLIENT_2(X, Y, SEC);
+            if (rtn != 0) {
+                return rtn;
+            }
+
+            return 0;
+        },
+
+        /* One pass MPIN Server */
+        SERVER: function(sha, date, HID, HTID, Y, SST, xID, xCID, mSEC, E, F, CID, TimeValue, Message, Pa) {
+            var rtn = 0,
+                M = [],
+                pID, i;
+
+            if (date == 0) {
+                pID = xID;
+            } else {
+                pID = xCID;
+            }
+
+            this.SERVER_1(sha, date, CID, HID, HTID);
+
+            M = pID.slice();
+
+            if (typeof Message !== "undefined" || Message != null) {
+                for (i = 0; i < Message.length; i++) {
+                    M.push(Message[i]);
+                }
+            }
+
+            this.GET_Y(sha, TimeValue, M, Y);
+
+            rtn = this.SERVER_2(date, HID, HTID, Y, SST, xID, xCID, mSEC, E, F, Pa);
+            if (rtn != 0) {
+                return rtn;
+            }
+
+            return 0;
+        },
+
+        /* Functions to support M-Pin Full */
+        PRECOMPUTE: function(TOKEN, CID, G1, G2) {
+            var P, T, g, Q;
+
+            T = ctx.ECP.fromBytes(TOKEN);
+            if (T.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            P = ctx.ECP.mapit(CID);
+            Q = ctx.ECP4.generator();
+
+            g = ctx.PAIR192.ate(Q, T);
+            g = ctx.PAIR192.fexp(g);
+            g.toBytes(G1);
+
+            g = ctx.PAIR192.ate(Q, P);
+            g = ctx.PAIR192.fexp(g);
+            g.toBytes(G2);
+
+            return 0;
+        },
+
+        /* Hash the M-Pin transcript - new */
+
+        HASH_ALL: function(sha, HID, xID, xCID, SEC, Y, R, W) {
+            var tlen = 0,
+                T = [],
+                i;
+
+            for (i = 0; i < HID.length; i++) {
+                T[i] = HID[i];
+            }
+            tlen += HID.length;
+
+            if (xCID != null) {
+                for (i = 0; i < xCID.length; i++) {
+                    T[i + tlen] = xCID[i];
+                }
+                tlen += xCID.length;
+            } else {
+                for (i = 0; i < xID.length; i++) {
+                    T[i + tlen] = xID[i];
+                }
+                tlen += xID.length;
+            }
+
+            for (i = 0; i < SEC.length; i++) {
+                T[i + tlen] = SEC[i];
+            }
+            tlen += SEC.length;
+
+            for (i = 0; i < Y.length; i++) {
+                T[i + tlen] = Y[i];
+            }
+            tlen += Y.length;
+
+            for (i = 0; i < R.length; i++) {
+                T[i + tlen] = R[i];
+            }
+            tlen += R.length;
+
+            for (i = 0; i < W.length; i++) {
+                T[i + tlen] = W[i];
+            }
+            tlen += W.length;
+
+            return this.hashit(sha, 0, T);
+        },
+
+        /* calculate common key on client side */
+        /* wCID = w.(A+AT) */
+        CLIENT_KEY: function(sha, G1, G2, pin, R, X, H, wCID, CK) {
+            var t = [],
+                g1 = ctx.FP24.fromBytes(G1),
+                g2 = ctx.FP24.fromBytes(G2),
+                z = ctx.BIG.fromBytes(R),
+                x = ctx.BIG.fromBytes(X),
+                h = ctx.BIG.fromBytes(H),
+                W = ctx.ECP.fromBytes(wCID),
+                r, c, i;
+
+            if (W.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            W = ctx.PAIR192.G1mul(W, x);
+
+            r = new ctx.BIG(0);
+            r.rcopy(ctx.ROM_CURVE.CURVE_Order);
+            //  var q=new ctx.BIG(0); q.rcopy(ctx.ROM_FIELD.Modulus);
+
+            z.add(h);
+            z.mod(r);
+
+            g2.pinpow(pin, this.PBLEN);
+            g1.mul(g2);
+
+            c = g1.compow(z, r);
+
+            t = this.mpin_hash(sha, c, W);
+
+            for (i = 0; i < ctx.ECP.AESKEY; i++) {
+                CK[i] = t[i];
+            }
+
+            return 0;
+        },
+
+        /* calculate common key on server side */
+        /* Z=r.A - no time permits involved */
+
+        SERVER_KEY: function(sha, Z, SST, W, H, HID, xID, xCID, SK) {
+            var t = [],
+                sQ, R, A, U, w, h, g, c, i;
+
+            sQ = ctx.ECP4.fromBytes(SST);
+            if (sQ.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            R = ctx.ECP.fromBytes(Z);
+            if (R.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            A = ctx.ECP.fromBytes(HID);
+            if (A.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            if (xCID != null) {
+                U = ctx.ECP.fromBytes(xCID);
+            } else {
+                U = ctx.ECP.fromBytes(xID);
+            }
+
+            if (U.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            w = ctx.BIG.fromBytes(W);
+            h = ctx.BIG.fromBytes(H);
+            A = ctx.PAIR192.G1mul(A, h);
+            R.add(A);
+            //R.affine();
+
+            U = ctx.PAIR192.G1mul(U, w);
+            g = ctx.PAIR192.ate(sQ, R);
+            g = ctx.PAIR192.fexp(g);
+
+            c = g.trace();
+
+            t = this.mpin_hash(sha, c, U);
+
+            for (i = 0; i < ctx.ECP.AESKEY; i++) {
+                SK[i] = t[i];
+            }
+
+            return 0;
+        },
+
+        GET_DVS_KEYPAIR: function(rng, Z, Pa) {
+            var r = new ctx.BIG(0),
+                z, Q;
+
+            r.rcopy(ctx.ROM_CURVE.CURVE_Order);
+
+            if (rng != null) {
+                z = ctx.BIG.randomnum(r, rng);
+                z.toBytes(Z);
+            } else {
+                z = ctx.BIG.fromBytes(Z);
+            }
+            z.invmodp(r);
+
+            Q = ctx.ECP4.generator();
+
+            Q = ctx.PAIR192.G2mul(Q, z);
+            Q.toBytes(Pa);
+
+            return 0;
+        }
+    };
+
+    return MPIN192;
+};
diff --git a/version3/js/mpin256.js b/version3/js/mpin256.js
new file mode 100644
index 0000000..5ff8b2f
--- /dev/null
+++ b/version3/js/mpin256.js
@@ -0,0 +1,1080 @@
+/*
+    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.
+*/
+
+/* MPIN API Functions */
+
+var MPIN256 = function(ctx) {
+    "use strict";
+
+    var MPIN256 = {
+        BAD_PARAMS: -11,
+        INVALID_POINT: -14,
+        WRONG_ORDER: -18,
+        BAD_PIN: -19,
+        /* configure PIN here */
+        MAXPIN: 10000,
+        /* max PIN */
+        PBLEN: 14,
+        /* MAXPIN length in bits */
+        TS: 12,
+        /* 10 for 4 digit PIN, 14 for 6-digit PIN - 2^TS/TS approx = sqrt(MAXPIN) */
+        TRAP: 2000,
+        /* 200 for 4 digit PIN, 2000 for 6-digit PIN  - approx 2*sqrt(MAXPIN) */
+        EFS: ctx.BIG.MODBYTES,
+        EGS: ctx.BIG.MODBYTES,
+        //PAS: 16,
+
+        SHA256: 32,
+        SHA384: 48,
+        SHA512: 64,
+
+        //HASH_TYPE: 32,
+
+        /* return time in slots since epoch */
+        today: function() {
+            var now = new Date();
+            return Math.floor(now.getTime() / (60000 * 1440)); // for daily tokens
+        },
+
+        bytestostring: function(b) {
+            var s = "",
+                len = b.length,
+                ch, i;
+
+            for (i = 0; i < len; i++) {
+                ch = b[i];
+                s += ((ch >>> 4) & 15).toString(16);
+                s += (ch & 15).toString(16);
+
+            }
+
+            return s;
+        },
+
+        stringtobytes: function(s) {
+            var b = [],
+                i;
+
+            for (i = 0; i < s.length; i++) {
+                b.push(s.charCodeAt(i));
+            }
+
+            return b;
+        },
+
+        comparebytes: function(a, b) {
+            if (a.length != b.length) {
+                return false;
+            }
+
+            for (var i = 0; i < a.length; i++) {
+                if (a[i] != b[i]) {
+                    return false;
+                }
+            }
+
+            return true;
+        },
+
+        mpin_hash: function(sha, c, U) {
+            var t = [],
+                w = [],
+                h = [],
+                H, R, i;
+
+            c.geta().geta().geta().getA().toBytes(w);
+            for (i = 0; i < this.EFS; i++) {
+                t[i] = w[i];
+            }
+            c.geta().geta().geta().getB().toBytes(w);
+            for (i = this.EFS; i < 2 * this.EFS; i++) {
+                t[i] = w[i - this.EFS];
+            }
+            c.geta().geta().getb().getA().toBytes(w);
+            for (i = 2 * this.EFS; i < 3 * this.EFS; i++) {
+                t[i] = w[i - 2 * this.EFS];
+            }
+            c.geta().geta().getb().getB().toBytes(w);
+            for (i = 3 * this.EFS; i < 4 * this.EFS; i++) {
+                t[i] = w[i - 3 * this.EFS];
+            }
+
+            c.geta().getb().geta().getA().toBytes(w);
+            for (i = 4 * this.EFS; i < 5 * this.EFS; i++) {
+                t[i] = w[i - 4 * this.EFS];
+            }
+            c.geta().getb().geta().getB().toBytes(w);
+            for (i = 5 * this.EFS; i < 6 * this.EFS; i++) {
+                t[i] = w[i - 5 * this.EFS];
+            }
+            c.geta().getb().getb().getA().toBytes(w);
+            for (i = 6 * this.EFS; i < 7 * this.EFS; i++) {
+                t[i] = w[i - 6 * this.EFS];
+            }
+            c.geta().getb().getb().getB().toBytes(w);
+            for (i = 7 * this.EFS; i < 8 * this.EFS; i++) {
+                t[i] = w[i - 7 * this.EFS];
+            }
+
+            c.getb().geta().geta().getA().toBytes(w);
+            for (i = 8 * this.EFS; i < 9 * this.EFS; i++) {
+                t[i] = w[i - 8 * this.EFS];
+            }
+            c.getb().geta().geta().getB().toBytes(w);
+            for (i = 9 *this.EFS; i < 10 * this.EFS; i++) {
+                t[i] = w[i - 9 * this.EFS];
+            }
+            c.getb().geta().getb().getA().toBytes(w);
+            for (i = 10 * this.EFS; i < 11 * this.EFS; i++) {
+                t[i] = w[i - 10 * this.EFS];
+            }
+            c.getb().geta().getb().getB().toBytes(w);
+            for (i = 11 * this.EFS; i < 12 * this.EFS; i++) {
+                t[i] = w[i - 11 * this.EFS];
+            }
+
+            c.getb().getb().geta().getA().toBytes(w);
+            for (i = 12 * this.EFS; i < 13 * this.EFS; i++) {
+                t[i] = w[i - 12 * this.EFS];
+            }
+            c.getb().getb().geta().getB().toBytes(w);
+            for (i = 13 * this.EFS; i < 14 * this.EFS; i++) {
+                t[i] = w[i - 13 * this.EFS];
+            }
+            c.getb().getb().getb().getA().toBytes(w);
+            for (i = 14 * this.EFS; i < 15 * this.EFS; i++) {
+                t[i] = w[i - 14 * this.EFS];
+            }
+            c.getb().getb().getb().getB().toBytes(w);
+            for (i = 15 * this.EFS; i < 16 * this.EFS; i++) {
+                t[i] = w[i - 15 * this.EFS];
+            }
+
+
+            U.getX().toBytes(w);
+            for (i = 16 * this.EFS; i < 17 * this.EFS; i++) {
+                t[i] = w[i - 16 * this.EFS];
+            }
+            U.getY().toBytes(w);
+            for (i = 17 * this.EFS; i < 18 * this.EFS; i++) {
+                t[i] = w[i - 17 * this.EFS];
+            }
+
+            if (sha == this.SHA256) {
+                H = new ctx.HASH256();
+            } else if (sha == this.SHA384) {
+                H = new ctx.HASH384();
+            } else if (sha == this.SHA512) {
+                H = new ctx.HASH512();
+            }
+
+            H.process_array(t);
+            h = H.hash();
+
+            if (h.length == 0) {
+                return null;
+            }
+
+            R = [];
+            for (i = 0; i < ctx.ECP.AESKEY; i++) {
+                R[i] = h[i];
+            }
+
+            return R;
+        },
+
+        /* Hash number (optional) and string to point on curve */
+        hashit: function(sha, n, B) {
+            var R = [],
+                H, W, i, len;
+
+            if (sha == this.SHA256) {
+                H = new ctx.HASH256();
+            } else if (sha == this.SHA384) {
+                H = new ctx.HASH384();
+            } else if (sha == this.SHA512) {
+                H = new ctx.HASH512();
+            }
+
+            if (n > 0) {
+                H.process_num(n);
+            }
+            H.process_array(B);
+            R = H.hash();
+
+            if (R.length == 0) {
+                return null;
+            }
+
+            W = [];
+
+            len = ctx.BIG.MODBYTES;
+
+            if (sha >= len) {
+                for (i = 0; i < len; i++) {
+                    W[i] = R[i];
+                }
+            } else {
+                for (i = 0; i < sha; i++) {
+                    W[i + len - sha] = R[i];
+                }
+
+                for (i = 0; i < len - sha; i++) {
+                    W[i] = 0;
+                }
+            }
+
+            return W;
+        },
+
+        /* these next two functions help to implement elligator squared - http://eprint.iacr.org/2014/043 */
+        /* maps a random u to a point on the curve */
+        map: function(u, cb) {
+            var P = new ctx.ECP(),
+                x = new ctx.BIG(u),
+                p = new ctx.BIG(0);
+
+            p.rcopy(ctx.ROM_FIELD.Modulus);
+            x.mod(p);
+
+            for (;;) {
+                P.setxi(x, cb);
+                if (!P.is_infinity()) {
+                    break;
+                }
+                x.inc(1);
+                x.norm();
+            }
+
+            return P;
+        },
+
+        /* returns u derived from P. Random value in range 1 to return value should then be added to u */
+        unmap: function(u, P) {
+            var s = P.getS(),
+                R = new ctx.ECP(),
+                r = 0,
+                x = P.getX();
+
+            u.copy(x);
+
+            for (;;) {
+                u.dec(1);
+                u.norm();
+                r++;
+                R.setxi(u, s); //=new ECP(u,s);
+                if (!R.is_infinity()) {
+                    break;
+                }
+            }
+
+            return r;
+        },
+
+        /* these next two functions implement elligator squared - http://eprint.iacr.org/2014/043 */
+        /* Elliptic curve point E in format (0x04,x,y} is converted to form {0x0-,u,v} */
+        /* Note that u and v are indistinguishable from random strings */
+        ENCODING: function(rng, E) {
+            var T = [],
+                i, rn, m, su, sv,
+                u, v, P, p, W;
+
+            for (i = 0; i < this.EFS; i++) {
+                T[i] = E[i + 1];
+            }
+            u = ctx.BIG.fromBytes(T);
+            for (i = 0; i < this.EFS; i++) {
+                T[i] = E[i + this.EFS + 1];
+            }
+            v = ctx.BIG.fromBytes(T);
+
+            P = new ctx.ECP(0);
+            P.setxy(u, v);
+            if (P.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            p = new ctx.BIG(0);
+            p.rcopy(ctx.ROM_FIELD.Modulus);
+            u = ctx.BIG.randomnum(p, rng);
+
+            su = rng.getByte();
+            if (su < 0) {
+                su = -su;
+            }
+            su %= 2;
+
+            W = this.map(u, su);
+            P.sub(W);
+            sv = P.getS();
+            rn = this.unmap(v, P);
+            m = rng.getByte();
+            if (m < 0) {
+                m = -m;
+            }
+            m %= rn;
+            v.inc(m + 1);
+            E[0] = (su + 2 * sv);
+            u.toBytes(T);
+            for (i = 0; i < this.EFS; i++) {
+                E[i + 1] = T[i];
+            }
+            v.toBytes(T);
+            for (i = 0; i < this.EFS; i++) {
+                E[i + this.EFS + 1] = T[i];
+            }
+
+            return 0;
+        },
+
+        DECODING: function(D) {
+            var T = [],
+                i, su, sv, u, v, W, P;
+
+            if ((D[0] & 0x04) !== 0) {
+                return this.INVALID_POINT;
+            }
+
+            for (i = 0; i < this.EFS; i++) {
+                T[i] = D[i + 1];
+            }
+            u = ctx.BIG.fromBytes(T);
+            for (i = 0; i < this.EFS; i++) {
+                T[i] = D[i + this.EFS + 1];
+            }
+            v = ctx.BIG.fromBytes(T);
+
+            su = D[0] & 1;
+            sv = (D[0] >> 1) & 1;
+            W = this.map(u, su);
+            P = this.map(v, sv);
+            P.add(W);
+            u = P.getX();
+            v = P.getY();
+            D[0] = 0x04;
+            u.toBytes(T);
+            for (i = 0; i < this.EFS; i++) {
+                D[i + 1] = T[i];
+            }
+            v.toBytes(T);
+            for (i = 0; i < this.EFS; i++) {
+                D[i + this.EFS + 1] = T[i];
+            }
+
+            return 0;
+        },
+
+        /* R=R1+R2 in group G1 */
+        RECOMBINE_G1: function(R1, R2, R) {
+            var P = ctx.ECP.fromBytes(R1),
+                Q = ctx.ECP.fromBytes(R2);
+
+            if (P.is_infinity() || Q.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            P.add(Q);
+
+            P.toBytes(R,false);
+
+            return 0;
+        },
+
+        /* W=W1+W2 in group G2 */
+        RECOMBINE_G2: function(W1, W2, W) {
+            var P = ctx.ECP8.fromBytes(W1),
+                Q = ctx.ECP8.fromBytes(W2);
+
+            if (P.is_infinity() || Q.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            P.add(Q);
+
+            P.toBytes(W);
+
+            return 0;
+        },
+
+        HASH_ID: function(sha, ID) {
+            return this.hashit(sha, 0, ID);
+        },
+
+        /* create random secret S */
+        RANDOM_GENERATE: function(rng, S) {
+            var r = new ctx.BIG(0),
+                s;
+
+            r.rcopy(ctx.ROM_CURVE.CURVE_Order);
+
+            s = ctx.BIG.randomnum(r, rng);
+            //if (ROM.AES_S>0)
+            //{
+            //  s.mod2m(2*ROM.AES_S);
+            //}
+            s.toBytes(S);
+
+            return 0;
+        },
+
+        /* Extract PIN from TOKEN for identity CID */
+        EXTRACT_PIN: function(sha, CID, pin, TOKEN) {
+            return this.EXTRACT_FACTOR(sha,CID,pin%this.MAXPIN,this.PBLEN,TOKEN);
+        },
+
+        /* Extract factor from TOKEN for identity CID */
+        EXTRACT_FACTOR: function(sha, CID, factor, facbits, TOKEN) {
+            var P, R, h;
+
+            P = ctx.ECP.fromBytes(TOKEN);
+
+            if (P.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            h = this.hashit(sha, 0, CID);
+            R = ctx.ECP.mapit(h);
+
+            R = R.pinmul(factor, facbits);
+            P.sub(R);
+
+            P.toBytes(TOKEN,false);
+
+            return 0;
+        },
+
+        /* Restore factor to TOKEN for identity CID */
+        RESTORE_FACTOR: function(sha, CID, factor, facbits, TOKEN) {
+            var P, R, h;
+
+            P = ctx.ECP.fromBytes(TOKEN);
+
+            if (P.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            h = this.hashit(sha, 0, CID),
+            R = ctx.ECP.mapit(h);
+
+            R = R.pinmul(factor, facbits);
+            P.add(R);
+
+            P.toBytes(TOKEN,false);
+
+            return 0;
+        },
+
+        /* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */
+        GET_SERVER_SECRET: function(S, SST) {
+            var s,Q;
+
+            Q = ctx.ECP8.generator();
+
+            s = ctx.BIG.fromBytes(S);
+            Q = ctx.PAIR256.G2mul(Q, s);
+            Q.toBytes(SST);
+
+            return 0;
+        },
+
+        /*
+         * W=x*H(G);
+         * if RNG == NULL then X is passed in
+         * if RNG != NULL the X is passed out
+         * if type=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve
+        */
+        GET_G1_MULTIPLE: function(rng, type, X, G, W) {
+            var r = new ctx.BIG(0),
+                x, P;
+
+            r.rcopy(ctx.ROM_CURVE.CURVE_Order);
+
+            if (rng != null) {
+                x = ctx.BIG.randomnum(r, rng);
+                //if (ROM.AES_S>0)
+                //{
+                //  x.mod2m(2*ROM.AES_S);
+                //}
+                x.toBytes(X);
+            } else {
+                x = ctx.BIG.fromBytes(X);
+            }
+
+            if (type == 0) {
+                P = ctx.ECP.fromBytes(G);
+                if (P.is_infinity()) {
+                    return this.INVALID_POINT;
+                }
+            } else {
+                P = ctx.ECP.mapit(G);
+            }
+
+            ctx.PAIR256.G1mul(P, x).toBytes(W,false);
+
+            return 0;
+        },
+
+
+        /* Client secret CST=S*H(CID) where CID is client ID and S is master secret */
+        GET_CLIENT_SECRET: function(S, CID, CST) {
+            return this.GET_G1_MULTIPLE(null, 1, S, CID, CST);
+        },
+
+        /* Time Permit CTT=S*(date|H(CID)) where S is master secret */
+        GET_CLIENT_PERMIT: function(sha, date, S, CID, CTT) {
+            var h = this.hashit(sha, date, CID),
+                P = ctx.ECP.mapit(h),
+                s = ctx.BIG.fromBytes(S);
+
+            P = ctx.PAIR256.G1mul(P, s);
+            P.toBytes(CTT,false);
+
+            return 0;
+        },
+
+        /* Implement step 1 on client side of MPin protocol */
+        CLIENT_1: function(sha, date, CLIENT_ID, rng, X, pin, TOKEN, SEC, xID, xCID, PERMIT) {
+            var r = new ctx.BIG(0),
+                x, P, T, W, h;
+
+            r.rcopy(ctx.ROM_CURVE.CURVE_Order);
+
+            //  var q=new ctx.BIG(0); q.rcopy(ctx.ROM_FIELD.Modulus);
+            if (rng !== null) {
+                x = ctx.BIG.randomnum(r, rng);
+                //if (ROM.AES_S>0)
+                //{
+                //  x.mod2m(2*ROM.AES_S);
+                //}
+                x.toBytes(X);
+            } else {
+                x = ctx.BIG.fromBytes(X);
+            }
+
+            h = this.hashit(sha, 0, CLIENT_ID);
+            P = ctx.ECP.mapit(h);
+            T = ctx.ECP.fromBytes(TOKEN);
+            if (T.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            pin %= this.MAXPIN;
+            W = P.pinmul(pin, this.PBLEN);
+            T.add(W);
+
+            if (date != 0) {
+                W = ctx.ECP.fromBytes(PERMIT);
+
+                if (W.is_infinity()) {
+                    return this.INVALID_POINT;
+                }
+
+                T.add(W);
+                h = this.hashit(sha, date, h);
+                W = ctx.ECP.mapit(h);
+
+                if (xID != null) {
+                    P = ctx.PAIR256.G1mul(P, x);
+                    P.toBytes(xID,false);
+                    W = ctx.PAIR256.G1mul(W, x);
+                    P.add(W);
+                } else {
+                    P.add(W);
+                    P = ctx.PAIR256.G1mul(P, x);
+                }
+
+                if (xCID != null) {
+                    P.toBytes(xCID,false);
+                }
+            } else {
+                if (xID != null) {
+                    P = ctx.PAIR256.G1mul(P, x);
+                    P.toBytes(xID,false);
+                }
+            }
+
+            T.toBytes(SEC,false);
+
+            return 0;
+        },
+
+        /* Implement step 2 on client side of MPin protocol */
+        CLIENT_2: function(X, Y, SEC) {
+            var r = new ctx.BIG(0),
+                P, px, py;
+
+            r.rcopy(ctx.ROM_CURVE.CURVE_Order);
+
+            P = ctx.ECP.fromBytes(SEC);
+            if (P.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            px = ctx.BIG.fromBytes(X);
+            py = ctx.BIG.fromBytes(Y);
+            px.add(py);
+            px.mod(r);
+            //  px.rsub(r);
+
+            P = ctx.PAIR256.G1mul(P, px);
+            P.neg();
+            P.toBytes(SEC,false);
+            //ctx.PAIR256.G1mul(P,px).toBytes(SEC,false);
+
+            return 0;
+        },
+
+        /* Outputs H(CID) and H(T|H(CID)) for time permits. If no time permits set HID=HTID */
+        SERVER_1: function(sha, date, CID, HID, HTID) {
+            var h = this.hashit(sha, 0, CID),
+                P = ctx.ECP.mapit(h),
+                R;
+
+            P.toBytes(HID,false);
+            if (date !== 0) {
+                //if (HID!=null) P.toBytes(HID,false);
+                h = this.hashit(sha, date, h);
+                R = ctx.ECP.mapit(h);
+                P.add(R);
+                P.toBytes(HTID,false);
+            }
+            //else P.toBytes(HID,false);
+        },
+
+        /* Implement step 1 of MPin protocol on server side. Pa is the client public key in case of DVS, otherwise must be set to null */
+        SERVER_2: function(date, HID, HTID, Y, SST, xID, xCID, mSEC, E, F, Pa) {
+            var Q, sQ, R, y, P, g;
+
+            if (typeof Pa === "undefined" || Pa == null) {
+                Q = ctx.ECP8.generator();
+
+            } else {
+                Q = ctx.ECP8.fromBytes(Pa);
+                if (Q.is_infinity()) {
+                    return this.INVALID_POINT;
+                }
+            }
+
+            sQ = ctx.ECP8.fromBytes(SST);
+            if (sQ.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            if (date !== 0) {
+                R = ctx.ECP.fromBytes(xCID);
+            } else {
+                if (xID == null) {
+                    return this.BAD_PARAMS;
+                }
+                R = ctx.ECP.fromBytes(xID);
+            }
+
+            if (R.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            y = ctx.BIG.fromBytes(Y);
+
+            if (date != 0) {
+                P = ctx.ECP.fromBytes(HTID);
+            } else {
+                if (HID == null) {
+                    return this.BAD_PARAMS;
+                }
+                P = ctx.ECP.fromBytes(HID);
+            }
+
+            if (P.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            P = ctx.PAIR256.G1mul(P, y);
+            P.add(R);
+            //P.affine();
+            R = ctx.ECP.fromBytes(mSEC);
+            if (R.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            g = ctx.PAIR256.ate2(Q, R, sQ, P);
+            g = ctx.PAIR256.fexp(g);
+
+            if (!g.isunity()) {
+                if (HID != null && xID != null && E != null && F != null) {
+                    g.toBytes(E);
+
+                    if (date !== 0) {
+                        P = ctx.ECP.fromBytes(HID);
+                        if (P.is_infinity()) {
+                            return this.INVALID_POINT;
+                        }
+
+                        R = ctx.ECP.fromBytes(xID);
+                        if (R.is_infinity()) {
+                            return this.INVALID_POINT;
+                        }
+
+                        P = ctx.PAIR256.G1mul(P, y);
+                        P.add(R);
+                        //P.affine();
+                    }
+                    g = ctx.PAIR256.ate(Q, P);
+                    g = ctx.PAIR256.fexp(g);
+
+                    g.toBytes(F);
+                }
+
+                return this.BAD_PIN;
+            }
+
+            return 0;
+        },
+
+        /* Pollards kangaroos used to return PIN error */
+        KANGAROO: function(E, F) {
+            var ge = ctx.FP48.fromBytes(E),
+                gf = ctx.FP48.fromBytes(F),
+                distance = [],
+                t = new ctx.FP48(gf),
+                table = [],
+                i, j, m, s, dn, dm, res, steps;
+
+            s = 1;
+            for (m = 0; m < this.TS; m++) {
+                distance[m] = s;
+                table[m] = new ctx.FP48(t);
+                s *= 2;
+                t.usqr();
+            }
+            t.one();
+            dn = 0;
+            for (j = 0; j < this.TRAP; j++) {
+                i = t.geta().geta().geta().geta().getA().lastbits(20) % this.TS;
+                t.mul(table[i]);
+                dn += distance[i];
+            }
+            gf.copy(t);
+            gf.conj();
+            steps = 0;
+            dm = 0;
+            res = 0;
+            while (dm - dn < this.MAXPIN) {
+                steps++;
+                if (steps > 4 * this.TRAP) {
+                    break;
+                }
+                i = ge.geta().geta().geta().geta().getA().lastbits(20) % this.TS;
+                ge.mul(table[i]);
+                dm += distance[i];
+                if (ge.equals(t)) {
+                    res = dm - dn;
+                    break;
+                }
+                if (ge.equals(gf)) {
+                    res = dn - dm;
+                    break;
+                }
+
+            }
+            if (steps > 4 * this.TRAP || dm - dn >= this.MAXPIN) {
+                res = 0;
+            } // Trap Failed  - probable invalid token
+
+            return res;
+        },
+
+        /* return time  since epoch */
+        GET_TIME: function() {
+            var now = new Date();
+            return Math.floor(now.getTime() / (1000));
+        },
+
+        /* y = H(time,xCID) */
+        GET_Y: function(sha, TimeValue, xCID, Y) {
+            var q = new ctx.BIG(0),
+                h = this.hashit(sha, TimeValue, xCID),
+                y = ctx.BIG.fromBytes(h);
+
+            q.rcopy(ctx.ROM_CURVE.CURVE_Order);
+
+            y.mod(q);
+            //if (ROM.AES_S>0)
+            //{
+            //  y.mod2m(2*ROM.AES_S);
+            //}
+            y.toBytes(Y);
+
+            return 0;
+        },
+
+        /* One pass MPIN Client - DVS signature. Message must be null in case of One pass MPIN. */
+        CLIENT: function(sha, date, CLIENT_ID, rng, X, pin, TOKEN, SEC, xID, xCID, PERMIT, TimeValue, Y, Message) {
+            var rtn = 0,
+                M = [],
+                pID, i;
+
+            if (date == 0) {
+                pID = xID;
+            } else {
+                pID = xCID;
+                xID = null;
+            }
+
+            rtn = this.CLIENT_1(sha, date, CLIENT_ID, rng, X, pin, TOKEN, SEC, xID, xCID, PERMIT);
+            if (rtn != 0) {
+                return rtn;
+            }
+
+            M = pID.slice();
+
+            if (typeof Message !== "undefined" || Message != null) {
+                for (i = 0; i < Message.length; i++) {
+                    M.push(Message[i]);
+                }
+            }
+
+            this.GET_Y(sha, TimeValue, M, Y);
+
+            rtn = this.CLIENT_2(X, Y, SEC);
+            if (rtn != 0) {
+                return rtn;
+            }
+
+            return 0;
+        },
+
+        /* One pass MPIN Server */
+        SERVER: function(sha, date, HID, HTID, Y, SST, xID, xCID, mSEC, E, F, CID, TimeValue, Message, Pa) {
+            var rtn = 0,
+                M = [],
+                pID, i;
+
+            if (date == 0) {
+                pID = xID;
+            } else {
+                pID = xCID;
+            }
+
+            this.SERVER_1(sha, date, CID, HID, HTID);
+
+            M = pID.slice();
+
+            if (typeof Message !== "undefined" || Message != null) {
+                for (i = 0; i < Message.length; i++) {
+                    M.push(Message[i]);
+                }
+            }
+
+            this.GET_Y(sha, TimeValue, M, Y);
+
+            rtn = this.SERVER_2(date, HID, HTID, Y, SST, xID, xCID, mSEC, E, F, Pa);
+            if (rtn != 0) {
+                return rtn;
+            }
+
+            return 0;
+        },
+
+        /* Functions to support M-Pin Full */
+        PRECOMPUTE: function(TOKEN, CID, G1, G2) {
+            var P, T, g, Q;
+
+            T = ctx.ECP.fromBytes(TOKEN);
+            if (T.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            P = ctx.ECP.mapit(CID);
+            Q = ctx.ECP8.generator();
+
+            g = ctx.PAIR256.ate(Q, T);
+            g = ctx.PAIR256.fexp(g);
+            g.toBytes(G1);
+
+            g = ctx.PAIR256.ate(Q, P);
+            g = ctx.PAIR256.fexp(g);
+            g.toBytes(G2);
+
+            return 0;
+        },
+
+        /* Hash the M-Pin transcript - new */
+
+        HASH_ALL: function(sha, HID, xID, xCID, SEC, Y, R, W) {
+            var tlen = 0,
+                T = [],
+                i;
+
+            for (i = 0; i < HID.length; i++) {
+                T[i] = HID[i];
+            }
+            tlen += HID.length;
+
+            if (xCID != null) {
+                for (i = 0; i < xCID.length; i++) {
+                    T[i + tlen] = xCID[i];
+                }
+                tlen += xCID.length;
+            } else {
+                for (i = 0; i < xID.length; i++) {
+                    T[i + tlen] = xID[i];
+                }
+                tlen += xID.length;
+            }
+
+            for (i = 0; i < SEC.length; i++) {
+                T[i + tlen] = SEC[i];
+            }
+            tlen += SEC.length;
+
+            for (i = 0; i < Y.length; i++) {
+                T[i + tlen] = Y[i];
+            }
+            tlen += Y.length;
+
+            for (i = 0; i < R.length; i++) {
+                T[i + tlen] = R[i];
+            }
+            tlen += R.length;
+
+            for (i = 0; i < W.length; i++) {
+                T[i + tlen] = W[i];
+            }
+            tlen += W.length;
+
+            return this.hashit(sha, 0, T);
+        },
+
+        /* calculate common key on client side */
+        /* wCID = w.(A+AT) */
+        CLIENT_KEY: function(sha, G1, G2, pin, R, X, H, wCID, CK) {
+            var t = [],
+                g1 = ctx.FP48.fromBytes(G1),
+                g2 = ctx.FP48.fromBytes(G2),
+                z = ctx.BIG.fromBytes(R),
+                x = ctx.BIG.fromBytes(X),
+                h = ctx.BIG.fromBytes(H),
+                W = ctx.ECP.fromBytes(wCID),
+                r, c, i;
+
+            if (W.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            W = ctx.PAIR256.G1mul(W, x);
+
+            r = new ctx.BIG(0);
+            r.rcopy(ctx.ROM_CURVE.CURVE_Order);
+            //  var q=new ctx.BIG(0); q.rcopy(ctx.ROM_FIELD.Modulus);
+
+            z.add(h);
+            z.mod(r);
+
+            g2.pinpow(pin, this.PBLEN);
+            g1.mul(g2);
+
+            c = g1.compow(z, r);
+
+            t = this.mpin_hash(sha, c, W);
+
+            for (i = 0; i < ctx.ECP.AESKEY; i++) {
+                CK[i] = t[i];
+            }
+
+            return 0;
+        },
+
+        /* calculate common key on server side */
+        /* Z=r.A - no time permits involved */
+
+        SERVER_KEY: function(sha, Z, SST, W, H, HID, xID, xCID, SK) {
+            var t = [],
+                sQ, R, A, U, w, h, g, c, i;
+
+            sQ = ctx.ECP8.fromBytes(SST);
+            if (sQ.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            R = ctx.ECP.fromBytes(Z);
+            if (R.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            A = ctx.ECP.fromBytes(HID);
+            if (A.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            if (xCID != null) {
+                U = ctx.ECP.fromBytes(xCID);
+            } else {
+                U = ctx.ECP.fromBytes(xID);
+            }
+
+            if (U.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            w = ctx.BIG.fromBytes(W);
+            h = ctx.BIG.fromBytes(H);
+            A = ctx.PAIR256.G1mul(A, h);
+            R.add(A);
+            //R.affine();
+
+            U = ctx.PAIR256.G1mul(U, w);
+            g = ctx.PAIR256.ate(sQ, R);
+            g = ctx.PAIR256.fexp(g);
+
+            c = g.trace();
+
+            t = this.mpin_hash(sha, c, U);
+
+            for (i = 0; i < ctx.ECP.AESKEY; i++) {
+                SK[i] = t[i];
+            }
+
+            return 0;
+        },
+
+        GET_DVS_KEYPAIR: function(rng, Z, Pa) {
+            var r = new ctx.BIG(0),
+                z, Q;
+
+            r.rcopy(ctx.ROM_CURVE.CURVE_Order);
+
+            if (rng != null) {
+                z = ctx.BIG.randomnum(r, rng);
+                z.toBytes(Z);
+            } else {
+                z = ctx.BIG.fromBytes(Z);
+            }
+            z.invmodp(r);
+
+            Q = ctx.ECP8.generator();
+
+            Q = ctx.PAIR256.G2mul(Q, z);
+            Q.toBytes(Pa);
+
+            return 0;
+        }
+    };
+
+    return MPIN256;
+};
diff --git a/version3/js/nhs.js b/version3/js/nhs.js
new file mode 100644
index 0000000..4b55020
--- /dev/null
+++ b/version3/js/nhs.js
@@ -0,0 +1,565 @@
+/*
+    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.
+*/
+
+/* NewHope API high-level functions  */
+
+var NHS = function(ctx) {
+    "use strict";
+
+    var NHS = {
+
+        round: function(a, b) {
+            return Math.floor((a + (b >> 1)) / b);
+        },
+
+        /* constant time absolute value */
+        nabs: function(x) {
+            var mask = (x >> 31);
+            return (x + mask) ^ mask;
+        },
+
+        /* Montgomery stuff */
+
+        redc: function(T) {
+            var m = ((T & 0x3ffffff) * NHS.ND) & 0x3ffffff;
+            return ((m * NHS.PRIME + T) * NHS.MODINV);
+        },
+
+        nres: function(x) {
+            return NHS.redc(x * NHS.R2MODP);
+        },
+
+        modmul: function(a, b) {
+            return NHS.redc(a * b);
+        },
+
+        /* NTT code */
+        /* Cooley-Tukey NTT */
+
+        ntt: function(x) {
+            var t = NHS.DEGREE / 2,
+                q = NHS.PRIME,
+                m, i, j, k,
+                S, U, V;
+
+            /* Convert to Montgomery form */
+            for (j = 0; j < NHS.DEGREE; j++) {
+                x[j] = NHS.nres(x[j]);
+            }
+
+            m = 1;
+            while (m < NHS.DEGREE) {
+                k = 0;
+
+                for (i = 0; i < m; i++) {
+                    S = NHS.roots[m + i];
+
+                    for (j = k; j < k + t; j++) {
+                        U = x[j];
+                        V = NHS.modmul(x[j + t], S);
+                        x[j] = U + V;
+                        x[j + t] = U + 2 * q - V;
+                    }
+
+                    k += 2 * t;
+                }
+
+                t /= 2;
+                m *= 2;
+            }
+        },
+
+        /* Gentleman-Sande INTT */
+        intt: function(x) {
+            var q = NHS.PRIME,
+                t = 1,
+                m, i, j, k,
+                S, U, V, W;
+
+            m = NHS.DEGREE / 2;
+            while (m > 1) {
+                k = 0;
+
+                for (i = 0; i < m; i++) {
+                    S = NHS.iroots[m + i];
+
+                    for (j = k; j < k + t; j++) {
+                        U = x[j];
+                        V = x[j + t];
+                        x[j] = U + V;
+                        W = U + NHS.DEGREE * q - V;
+                        x[j + t] = NHS.modmul(W, S);
+                    }
+
+                    k += 2 * t;
+                }
+
+                t *= 2;
+                m /= 2;
+            }
+            /* Last iteration merged with n^-1 */
+
+            t = NHS.DEGREE / 2;
+            for (j = 0; j < t; j++) {
+                U = x[j];
+                V = x[j + t];
+                W = U + NHS.DEGREE * q - V;
+                x[j + t] = NHS.modmul(W, NHS.invpr);
+                x[j] = NHS.modmul(U + V, NHS.inv);
+            }
+
+            /* convert back from Montgomery to "normal" form */
+            for (j = 0; j < NHS.DEGREE; j++) {
+                x[j] = NHS.redc(x[j]);
+                x[j] -= q;
+                x[j] += (x[j] >> (NHS.WL - 1)) & q;
+            }
+        },
+
+        /* See https://eprint.iacr.org/2016/1157.pdf */
+
+        Encode: function(key, poly) {
+            var i, j, b, k, kj, q2;
+
+            q2 = NHS.PRIME / 2;
+            for (i = j = 0; i < 256;) {
+                kj = key[j++];
+
+                for (k = 0; k < 8; k++) {
+                    b = kj & 1;
+                    poly[i] = b * q2;
+                    poly[i + 256] = b * q2;
+                    poly[i + 512] = b * q2;
+                    poly[i + 768] = b * q2;
+                    kj >>= 1;
+                    i++;
+                }
+            }
+        },
+
+        Decode: function(poly, key) {
+            var q2 = NHS.PRIME / 2,
+                i, j, k, b, t;
+
+            for (i = 0; i < 32; i++) {
+                key[i] = 0;
+            }
+
+            for (i = j = 0; i < 256;) {
+                for (k = 0; k < 8; k++) {
+                    t = NHS.nabs(poly[i] - q2) + NHS.nabs(poly[i + 256] - q2) + NHS.nabs(poly[i + 512] - q2) + NHS.nabs(poly[i + 768] - q2);
+
+                    b = t - NHS.PRIME;
+                    b = (b >> 31) & 1;
+                    key[j] = (((key[j] & 0xff) >> 1) + (b << 7));
+                    i++;
+                }
+
+                j++;
+            }
+        },
+
+        /* convert 32-byte seed to random polynomial */
+
+        Parse: function(seed, poly) {
+            var sh = new ctx.SHA3(ctx.SHA3.SHAKE128),
+                hash = [],
+                i, j, n;
+
+            for (i = 0; i < 32; i++) {
+                sh.process(seed[i]);
+            }
+            sh.shake(hash, 4 * NHS.DEGREE);
+
+            for (i = j = 0; i < NHS.DEGREE; i++) {
+                n = hash[j] & 0x7f;
+                n <<= 8;
+                n += hash[j + 1] & 0xff;
+                n <<= 8;
+                n += hash[j + 2] & 0xff;
+                n <<= 8;
+                n += hash[j + 3] & 0xff;
+                j += 4;
+                poly[i]=NHS.nres(n);
+                //poly[i] = NHS.modmul(n, NHS.ONE); // reduce 31-bit random number mod q
+            }
+        },
+
+        /* Compress 14 bits polynomial coefficients into byte array */
+        /* 7 bytes is 3x14 */
+        pack: function(poly, array) {
+            var i, j, a, b, c, d;
+
+            for (i = j = 0; i < NHS.DEGREE;) {
+                a = poly[i++];
+                b = poly[i++];
+                c = poly[i++];
+                d = poly[i++];
+                array[j++] = a & 0xff;
+                array[j++] = ((a >> 8) | (b << 6)) & 0xff;
+                array[j++] = (b >> 2) & 0xff;
+                array[j++] = ((b >> 10) | (c << 4)) & 0xff;
+                array[j++] = (c >> 4) & 0xff;
+                array[j++] = ((c >> 12) | (d << 2)) & 0xff;
+                array[j++] = (d >> 6);
+            }
+        },
+
+        unpack: function(array, poly) {
+            var i, j, a, b, c, d, e, f, g;
+
+            for (i = j = 0; i < NHS.DEGREE;) {
+                a = array[j++] & 0xff;
+                b = array[j++] & 0xff;
+                c = array[j++] & 0xff;
+                d = array[j++] & 0xff;
+                e = array[j++] & 0xff;
+                f = array[j++] & 0xff;
+                g = array[j++] & 0xff;
+                poly[i++] = a | ((b & 0x3f) << 8);
+                poly[i++] = (b >> 6) | (c << 2) | ((d & 0xf) << 10);
+                poly[i++] = (d >> 4) | (e << 4) | ((f & 3) << 12);
+                poly[i++] = (f >> 2) | (g << 6);
+            }
+        },
+
+
+        /* See https://eprint.iacr.org/2016/1157.pdf */
+
+        Compress: function(poly, array) {
+            var col = 0,
+                i, j, k, b;
+
+            for (i = j = 0; i < NHS.DEGREE;) {
+                for (k = 0; k < 8; k++) {
+                    b = NHS.round((poly[i] * 8), NHS.PRIME) & 7;
+                    col = (col << 3) + b;
+                    i++;
+                }
+
+                array[j] = (col & 0xff);
+                array[j + 1] = ((col >>> 8) & 0xff);
+                array[j + 2] = ((col >>> 16) & 0xff);
+                j += 3;
+                col = 0;
+            }
+        },
+
+        Decompress: function(array, poly) {
+            var col = 0,
+                i, j, k, b;
+
+            for (i = j = 0; i < NHS.DEGREE;) {
+                col = array[j + 2] & 0xff;
+                col = (col << 8) + (array[j + 1] & 0xff);
+                col = (col << 8) + (array[j] & 0xff);
+                j += 3;
+
+                for (k = 0; k < 8; k++) {
+                    b = (col & 0xe00000) >>> 21;
+                    col <<= 3;
+                    poly[i] = NHS.round((b * NHS.PRIME), 8);
+                    i++;
+                }
+            }
+        },
+
+        /* generate centered binomial distribution */
+
+        Error: function(RNG, poly) {
+            var n1, n2, r, i, j;
+
+            for (i = 0; i < NHS.DEGREE; i++) {
+                n1 = RNG.getByte() + (RNG.getByte() << 8);
+                n2 = RNG.getByte() + (RNG.getByte() << 8);
+                r = 0;
+
+                for (j = 0; j < 16; j++) {
+                    r += (n1 & 1) - (n2 & 1);
+                    n1 >>= 1;
+                    n2 >>= 1;
+                }
+
+                poly[i] = (r + NHS.PRIME);
+            }
+        },
+
+        redc_it: function(p) {
+            var i;
+            for (i = 0; i < NHS.DEGREE; i++) {
+                p[i] = NHS.redc(p[i]);
+            }
+        },
+
+        nres_it: function(p) {
+            var i;
+            for (i = 0; i < NHS.DEGREE; i++) {
+                p[i] = NHS.nres(p[i]);
+            }
+        },
+
+        poly_mul: function(p1, p2, p3) {
+            var i;
+
+            for (i = 0; i < NHS.DEGREE; i++) {
+                p1[i] = NHS.modmul(p2[i], p3[i]);
+            }
+        },
+
+        poly_add: function(p1, p2, p3) {
+            var i;
+
+            for (i = 0; i < NHS.DEGREE; i++) {
+                p1[i] = (p2[i] + p3[i]);
+            }
+        },
+
+        poly_sub: function(p1, p2, p3) {
+            var i;
+
+            for (i = 0; i < NHS.DEGREE; i++) {
+                p1[i] = (p2[i] + NHS.PRIME - p3[i]);
+            }
+        },
+
+        /* reduces inputs < 2q */
+        poly_soft_reduce: function(poly) {
+            var i, e;
+
+            for (i = 0; i < NHS.DEGREE; i++) {
+                e = poly[i] - NHS.PRIME;
+                poly[i] = e + ((e >> (NHS.WL - 1)) & NHS.PRIME);
+            }
+        },
+
+        /* fully reduces modulo q */
+        poly_hard_reduce: function(poly) {
+            var i, e;
+
+            for (i = 0; i < NHS.DEGREE; i++) {
+                e = NHS.modmul(poly[i], NHS.ONE);
+                e = e - NHS.PRIME;
+                poly[i] = e + ((e >> (NHS.WL - 1)) & NHS.PRIME);
+            }
+        },
+
+        bytestostring: function(b) {
+            var s = "",
+                len = b.length,
+                ch, i;
+
+            for (i = 0; i < len; i++) {
+                ch = b[i];
+                s += ((ch >>> 4) & 15).toString(16);
+                s += (ch & 15).toString(16);
+            }
+
+            return s;
+        },
+        /* API files */
+
+        SERVER_1: function(RNG, SB, S) {
+            var seed = new Uint8Array(32),
+                array = new Uint8Array(1792),
+                s = new Int32Array(NHS.DEGREE),
+                e = new Int32Array(NHS.DEGREE),
+                b = new Int32Array(NHS.DEGREE),
+                i;
+
+            for (i = 0; i < 32; i++) {
+                seed[i] = RNG.getByte();
+            }
+
+            NHS.Parse(seed, b);
+
+            NHS.Error(RNG, e);
+            NHS.Error(RNG, s);
+
+            NHS.ntt(s);
+            NHS.ntt(e);
+            NHS.poly_mul(b, b, s);
+            NHS.poly_add(b, b, e);
+            NHS.poly_hard_reduce(b);
+
+            NHS.redc_it(b);
+            NHS.pack(b, array);
+
+            for (i = 0; i < 32; i++) {
+                SB[i] = seed[i];
+            }
+
+            for (i = 0; i < 1792; i++) {
+                SB[i + 32] = array[i];
+            }
+
+            NHS.poly_hard_reduce(s);
+
+            NHS.pack(s, array);
+
+            for (i = 0; i < 1792; i++) {
+                S[i] = array[i];
+            }
+        },
+
+        CLIENT: function(RNG, SB, UC, KEY) {
+            var sh = new ctx.SHA3(ctx.SHA3.HASH256),
+                seed = new Uint8Array(32),
+                array = new Uint8Array(1792),
+                key = new Uint8Array(32),
+                cc = new Uint8Array(384),
+                sd = new Int32Array(NHS.DEGREE),
+                ed = new Int32Array(NHS.DEGREE),
+                u = new Int32Array(NHS.DEGREE),
+                k = new Int32Array(NHS.DEGREE),
+                c = new Int32Array(NHS.DEGREE),
+                i;
+
+            NHS.Error(RNG, sd);
+            NHS.Error(RNG, ed);
+
+            NHS.ntt(sd);
+            NHS.ntt(ed);
+
+            for (i = 0; i < 32; i++) {
+                seed[i] = SB[i];
+            }
+
+            for (i = 0; i < 1792; i++) {
+                array[i] = SB[i + 32];
+            }
+
+            NHS.Parse(seed, u);
+
+            NHS.poly_mul(u, u, sd);
+            NHS.poly_add(u, u, ed);
+            NHS.poly_hard_reduce(u);
+
+            for (i = 0; i < 32; i++) {
+                key[i] = RNG.getByte();
+            }
+
+            for (i = 0; i < 32; i++) {
+                sh.process(key[i]);
+            }
+
+            sh.hash(key);
+
+            NHS.Encode(key, k);
+
+            NHS.unpack(array, c);
+            NHS.nres_it(c);
+
+            NHS.poly_mul(c, c, sd);
+            NHS.intt(c);
+            NHS.Error(RNG, ed);
+            NHS.poly_add(c, c, ed);
+            NHS.poly_add(c, c, k);
+
+            NHS.Compress(c, cc);
+
+            sh.init(ctx.SHA3.HASH256);
+            for (i = 0; i < 32; i++) {
+                sh.process(key[i]);
+            }
+            sh.hash(key);
+
+            for (i = 0; i < 32; i++) {
+                KEY[i] = key[i];
+            }
+
+            NHS.redc_it(u);
+            NHS.pack(u, array);
+
+            for (i = 0; i < 1792; i++) {
+                UC[i] = array[i];
+            }
+
+            for (i = 0; i < 384; i++) {
+                UC[i + 1792] = cc[i];
+            }
+        },
+
+        SERVER_2: function(S, UC, KEY) {
+            var sh = new ctx.SHA3(ctx.SHA3.HASH256),
+                c = new Int32Array(NHS.DEGREE),
+                s = new Int32Array(NHS.DEGREE),
+                k = new Int32Array(NHS.DEGREE),
+                array = new Uint8Array(1792),
+                key = new Uint8Array(32),
+                cc = new Uint8Array(384),
+                i;
+
+            for (i = 0; i < 1792; i++) {
+                array[i] = UC[i];
+            }
+
+            NHS.unpack(array, k);
+            NHS.nres_it(k);
+
+            for (i = 0; i < 384; i++) {
+                cc[i] = UC[i + 1792];
+            }
+
+            NHS.Decompress(cc, c);
+
+            for (i = 0; i < 1792; i++) {
+                array[i] = S[i];
+            }
+
+            NHS.unpack(array, s);
+
+            NHS.poly_mul(k, k, s);
+            NHS.intt(k);
+            NHS.poly_sub(k, c, k);
+            NHS.poly_soft_reduce(k);
+
+            NHS.Decode(k, key);
+
+            for (i = 0; i < 32; i++) {
+                sh.process(key[i]);
+            }
+            sh.hash(key);
+
+            for (i = 0; i < 32; i++) {
+                KEY[i] = key[i];
+            }
+        }
+
+    };
+
+    //q=12289
+    NHS.PRIME = 0x3001; // q in Hex
+    NHS.LGN = 10; // Degree n=2^LGN
+    NHS.ND = 0x3002FFF; // 1/(R-q) mod R
+    NHS.ONE = 0x2AAC; // R mod q
+    NHS.R2MODP = 0x1DA2; // R^2 mod q
+
+    NHS.MODINV = Math.pow(2, -26);
+
+    NHS.DEGREE = 1024; // 1<< LGN
+    NHS.WL = 26;
+
+    NHS.inv = 0xffb;
+    NHS.invpr = 0x1131;
+
+    NHS.roots = [0x2aac, 0xd6f, 0x1c67, 0x2c5b, 0x2dbd, 0x2697, 0x29f6, 0x8d3, 0x1b7c, 0x9eb, 0x20eb, 0x264a, 0x27d0, 0x121b, 0x58c, 0x4d7, 0x17a2, 0x29eb, 0x1b72, 0x13b0, 0x19b1, 0x1581, 0x2ac9, 0x25e8, 0x249d, 0x2d5e, 0x363, 0x1f74, 0x1f8f, 0x20a4, 0x2cb2, 0x2d04, 0x1407, 0x2df9, 0x3ad, 0x23f7, 0x1a72, 0xa91, 0x37f, 0xdb3, 0x2315, 0x5e6, 0xa8f, 0x211d, 0xdad, 0x1f2b, 0x2e29, 0x26b0, 0x2009, 0x2fdd, 0x2881, 0x399, 0x586, 0x2781, 0x2ab5, 0x971, 0x234b, 0x1df3, 0x1d2a, 0x15dd, 0x1a6d, 0x2774, 0x7ff, 0x1ebe, 0x230, 0x1cf4, 0x180b, 0xb58, 0x198c, 0x2b40, 0x127b, 0x1d9d, 0x137f, 0xfa0, 0x144, 0x4b, 0x2fac, 0xb09, 0x1c7f, 0x1b5, 0xeec, 0xc58, 0x1248, 0x243c, 0x108a, 0x14b8, 0xe9, 0x2dfe, 0xfb, 0x2602, 0x2aec, 0x1bb7, 0x1098, 0x23d8, 0x783, 0x1b13, 0x2067, 0x20d6, 0x171c, 0x4, 0x662, 0x1097, 0x24b9, 0x1b9d, 0x27c4, 0x276e, 0x6bf, 0x757, 0x2e16, 0x472, 0x1d11, 0x1649, 0x2904, 0xed4, 0x6c5, 0x14ae, 0x2ef8, 0x2ae0, 0x2e7c, 0x2735, 0x1186, 0x4f2, 0x17bb, 0x297f, 0x1dc7, 0x1ae5, 0x2a43, 0x2c02, 0xed6, 0x2b70, 0x1c7b, 0x18d1, 0x20ae, 0x6ad, 0x2404, 0x113a, 0x209e, 0x31b, 0x159d, 0x48f, 0xe09, 0x1bb2, 0x14f7, 0x385, 0x1c4, 0x1cdb, 0x22d6, 0x21d8, 0xc, 0x1aae, 0x2ece, 0x2d81, 0xd56, 0x5c1, 0x12da, 0x8cf, 0x1605, 0x1bc4, 0x18b7, 0x19b9, 0x21be, 0x135e, 0x28d6, 0x2891, 0x2208, 0x17e1, 0x2971, 0x926, 0x211b, 0xff, 0x51f, 0xa85, 0xe1, 0x2c35, 0x2585, 0x121, 0xe27, 0x2e64, 0x29f8, 0x2d46, 0xcb2, 0x292a, 0x33d, 0xaf9, 0xb86, 0x2e3a, 0x2138, 0x1978, 0x2324, 0xf3f, 0x2d10, 0x1dfd, 0x13c3, 0x6cc, 0x1a79, 0x1221, 0x250f, 0xacd, 0xfff, 0x7b4, 0x650, 0x1893, 0xe85, 0x1f5d, 0x12dc, 0x2d42, 0xd8e, 0x1240, 0x1082, 0x12ef, 0x11b6, 0xfa8, 0xb0f, 0xdac, 0x191c, 0x1242, 0x1ea, 0x155, 0x270a, 0x9ed, 0x2e5b, 0x25d8, 0x222c, 0x7e9, 0x1fb3, 0x10ac, 0x2919, 0x2584, 0xbe3, 0x24fa, 0x23ed, 0x618, 0x2d80, 0x6fa, 0x140e, 0x588, 0x355, 0x1054, 0x26c4, 0x1e4f, 0x1681, 0x1f6f, 0x1c53, 0xfe4, 0xacb, 0x1680, 0x2fe8, 0x6c, 0x165a, 0x10bb, 0x2c39, 0x1804, 0x1196, 0x884, 0x2622, 0x629, 0x1ac1, 0x2232, 0x2f9b, 0xd3e, 0x20ff, 0x12c0, 0x27ec, 0x5a, 0x2a0, 0x5f1, 0x1cda, 0x403, 0x1ea8, 0x1719, 0x1fc7, 0x2d23, 0x5ea, 0x25d1, 0xb6, 0x49c, 0xac7, 0x2d9c, 0x204e, 0x2142, 0x11e8, 0xed0, 0x15f0, 0x514, 0xa3f, 0xf43, 0x1de5, 0x2d97, 0x1543, 0x2c7b, 0x241a, 0x2223, 0x2fb8, 0x25b7, 0x1b4c, 0x2f36, 0x26e2, 0x100, 0x2555, 0x266c, 0x2e10, 0x271c, 0x5aa, 0x1789, 0x2199, 0x291d, 0x1088, 0x2046, 0x1ea1, 0xf89, 0x1c7a, 0x1e98, 0x137, 0x1b65, 0x24ed, 0xf37, 0x2ec3, 0xd0c, 0x7c7, 0x123f, 0xb2e, 0x1a97, 0x1a03, 0x1bcd, 0x3b2, 0x714, 0x2979, 0xaef, 0x2b3c, 0x2d91, 0xe03, 0xe5b, 0x1fbc, 0xcae, 0x432, 0x23a4, 0xb1d, 0x1ccc, 0x1fb6, 0x2f58, 0x2a5a, 0x723, 0x2c99, 0x2d70, 0xa, 0x263c, 0x2701, 0xdeb, 0x2d08, 0x1c34, 0x200c, 0x1e88, 0x396, 0x18d5, 0x1c45, 0xc4, 0x18bc, 0x2cd7, 0x1744, 0x8f1, 0x1c5c, 0xbe6, 0x2a89, 0x17a0, 0x207, 0x19ce, 0x2024, 0x23e3, 0x299b, 0x685, 0x2baf, 0x539, 0x2d49, 0x24b5, 0x158d, 0xfd, 0x2a95, 0x24d, 0xab3, 0x1125, 0x12f9, 0x15ba, 0x6a8, 0x2c36, 0x6e7, 0x1044, 0x36e, 0xfe8, 0x112d, 0x2717, 0x24a0, 0x1c09, 0xe1d, 0x828, 0x2f7, 0x1f5b, 0xfab, 0xcf6, 0x1332, 0x1c72, 0x2683, 0x15ce, 0x1ad3, 0x1a36, 0x24c, 0xb33, 0x253f, 0x1583, 0x1d69, 0x29ec, 0xba7, 0x2f97, 0x16df, 0x1068, 0xaee, 0xc4f, 0x153c, 0x24eb, 0x20cd, 0x1398, 0x2366, 0x11f9, 0xe77, 0x103d, 0x260a, 0xce, 0xaea, 0x236b, 0x2b11, 0x5f8, 0xe4f, 0x750, 0x1569, 0x10f5, 0x284e, 0xa38, 0x2e06, 0xe0, 0xeaa, 0x99e, 0x249b, 0x8eb, 0x2b97, 0x2fdf, 0x29c1, 0x1b00, 0x2fe3, 0x1d4f, 0x83f, 0x2d06, 0x10e, 0x183f, 0x27ba, 0x132, 0xfbf, 0x296d, 0x154a, 0x40a, 0x2767, 0xad, 0xc09, 0x974, 0x2821, 0x1e2e, 0x28d2, 0xfac, 0x3c4, 0x2f19, 0xdd4, 0x2ddf, 0x1e43, 0x1e90, 0x2dc9, 0x1144, 0x28c3, 0x653, 0xf3c, 0x1e32, 0x2a4a, 0x391, 0x1123, 0xdb, 0x2da0, 0xe1e, 0x667, 0x23b5, 0x2039, 0xa92, 0x1552, 0x5d3, 0x169a, 0x1f03, 0x1342, 0x2004, 0x1b5d, 0x2d01, 0x2e9b, 0x41f, 0x2bc7, 0xa94, 0xd0, 0x2e6a, 0x2b38, 0x14ac, 0x2724, 0x3ba, 0x6bc, 0x18ac, 0x2da5, 0x213c, 0x2c5c, 0xdd3, 0xaae, 0x2e08, 0x6cd, 0x1677, 0x2025, 0x1e1c, 0x5b4, 0xdc4, 0x60, 0x156c, 0x2669, 0x1c01, 0x26ab, 0x1ebb, 0x26d4, 0x21e1, 0x156b, 0x567, 0x1a, 0x29ce, 0x23d4, 0x684, 0xb79, 0x1953, 0x1046, 0x1d8c, 0x17b5, 0x1c28, 0x1ce5, 0x2478, 0x18d8, 0x1b16, 0x2c2f, 0x21c9, 0x19bb, 0xbbc, 0x291b, 0x19f6, 0x1879, 0x2fe4, 0x58e, 0x294a, 0x19e8, 0x27c7, 0x2fba, 0x1a29, 0x2319, 0x1ecb, 0x203b, 0x2f05, 0x2b82, 0x192f, 0x26aa, 0x2482, 0xaed, 0x1216, 0x708, 0x11a1, 0xc22, 0x908, 0x28f8, 0x2427, 0x7f8, 0x172e, 0xf50, 0xaa8, 0x184a, 0x1f67, 0x22d1, 0xeba, 0x215b, 0xf47, 0x2877, 0xd5e, 0x8dc, 0x20d, 0x2dae, 0x1d3e, 0x775, 0xbf3, 0x872, 0x2667, 0x1ff6, 0xd9f, 0x13c4, 0x105, 0x65f, 0x21ec, 0x6dd, 0x1a09, 0xc6e, 0x1fd, 0x1426, 0xae3, 0x494, 0x2d82, 0x22cd, 0x25d6, 0x11c1, 0x1c, 0x2cae, 0x141f, 0x110a, 0x147, 0x2657, 0x23fd, 0x2f39, 0x360, 0x2294, 0x1f1e, 0xb73, 0xbfc, 0x2f17, 0x7ca, 0x2f63, 0xbf, 0x28c2, 0xc1a, 0x255e, 0x226e, 0x1aa8, 0x229e, 0x161a, 0x273, 0x106d, 0x2c40, 0x7cf, 0x1408, 0x7d8, 0x100a, 0x759, 0x1db4, 0x24be, 0x2ebb, 0xc17, 0x1894, 0x244e, 0x15bd, 0x748, 0x1fe9, 0x23d, 0x1da, 0x2be, 0x18a3, 0xc5c, 0x9f9, 0x3d5, 0x2ce4, 0x54, 0x2abf, 0x279c, 0x1e81, 0x2d59, 0x2847, 0x23f4, 0xda8, 0xa20, 0x258, 0x1cfe, 0x240c, 0x2c2e, 0x2790, 0x2dd5, 0x2bf2, 0x2e34, 0x1724, 0x211, 0x1009, 0x27b9, 0x6f9, 0x23d9, 0x19a2, 0x627, 0x156d, 0x169e, 0x7e7, 0x30f, 0x24b6, 0x5c2, 0x1ce4, 0x28dd, 0x20, 0x16ab, 0x1cce, 0x20a9, 0x2390, 0x2884, 0x2245, 0x5f7, 0xab7, 0x1b6a, 0x11e7, 0x2a53, 0x2f94, 0x294c, 0x1ee5, 0x1364, 0x1b9a, 0xff7, 0x5eb, 0x2c30, 0x1c02, 0x5a1, 0x1b87, 0x2402, 0x1cc8, 0x2ee1, 0x1fbe, 0x138c, 0x2487, 0x1bf8, 0xd96, 0x1d68, 0x2fb3, 0x1fc1, 0x1fcc, 0xd66, 0x953, 0x2141, 0x157a, 0x2477, 0x18e3, 0x2f30, 0x75e, 0x1de1, 0x14b2, 0x2faa, 0x1697, 0x2334, 0x12d1, 0xb76, 0x2aa8, 0x1e7a, 0xd5, 0x2c60, 0x26b8, 0x1753, 0x124a, 0x1f57, 0x1425, 0xd84, 0x1c05, 0x641, 0xf3a, 0x1b8c, 0xd7d, 0x2f52, 0x2f4, 0xc73, 0x151b, 0x1589, 0x1819, 0x1b18, 0xb9b, 0x1ae9, 0x2b1f, 0x2b44, 0x2f5a, 0x2d37, 0x2cb1, 0x26f5, 0x233e, 0x276f, 0x276, 0x1260, 0x2997, 0x9f2, 0x1c15, 0x1694, 0x11ac, 0x1e6d, 0x1bef, 0x2966, 0x18b2, 0x4fa, 0x2044, 0x1b70, 0x1f3e, 0x221e, 0x28ca, 0x1d56, 0x7ae, 0x98d, 0x238c, 0x17b8, 0xad3, 0x113f, 0x1f1b, 0x4d2, 0x1757, 0xcb1, 0x2ef1, 0x2e02, 0x17fc, 0x2f11, 0x2a74, 0x2029, 0x700, 0x154e, 0x1cef, 0x226a, 0x21bf, 0x27a6, 0x14bc, 0x2b2b, 0x2fc6, 0x13b6, 0x21e6, 0x1663, 0xcbd, 0x752, 0x1624, 0x881, 0x2fc0, 0x1276, 0xa7f, 0x274f, 0x2b53, 0x670, 0x1fb7, 0x1e41, 0x2a1e, 0x2612, 0x297, 0x19de, 0x18b, 0x249, 0x1c88, 0xe9e, 0x1ef1, 0x213, 0x47b, 0x1e20, 0x28c1, 0x1d5e, 0x977, 0x1dca, 0x990, 0x1df6, 0x2b62, 0x870, 0x1f4, 0x1829, 0x1e0a, 0x46, 0x1b9f, 0x2102, 0x16b, 0x1b32, 0x568, 0x2050, 0x15b4, 0x191a, 0x1dd0, 0x5df, 0x55c, 0x1d21, 0x19db, 0x12d9, 0xe96, 0x680, 0x2349, 0x9b9, 0x155d, 0xe31, 0x249f, 0x20f8, 0xb30, 0x337, 0x2da3, 0x11c3, 0x248f, 0x1cf9, 0x10ee, 0x6d8, 0x6eb, 0xa0d, 0x101b, 0x1ae4, 0x1801, 0x24cd, 0x813, 0x2e98, 0x1574, 0x50, 0x11da, 0x1802, 0xf56, 0x1839, 0x219c, 0x105b, 0x43b, 0x2c9, 0x917, 0x14c1, 0x1b79, 0xdab, 0x2ab9, 0x265c, 0x71a, 0x1d90, 0x89f, 0x2bc2, 0x2777, 0x1014, 0x1e64, 0x14b4, 0x692, 0xddb, 0x56e, 0x2190, 0x2d1b, 0x1016, 0x12d6, 0x1c81, 0x2628, 0x4a1, 0x1268, 0x2597, 0x2926, 0x7c5, 0x1dcd, 0x53f, 0x11a9, 0x1a41, 0x5a2, 0x1c65, 0x7e8, 0xd71, 0x29c8, 0x427, 0x32f, 0x5dc, 0x16b1, 0x2a1d, 0x1787, 0x2224, 0x620, 0x6a4, 0x1351, 0x1038, 0xe6c, 0x111b, 0x2f13, 0x441, 0x2cfd, 0x2f2f, 0xd25, 0x9b8, 0x1b24, 0x762, 0x19b6, 0x2611, 0x85e, 0xe37, 0x1f5, 0x503, 0x1c46, 0x23cc, 0x4bb, 0x243e, 0x122b, 0x28e2, 0x133e, 0x2db9, 0xdb2, 0x1a5c, 0x29a9, 0xca, 0x2113, 0x13d1, 0x15ec, 0x2079, 0x18da, 0x2d50, 0x2c45, 0xaa2, 0x135a, 0x800, 0x18f7, 0x17f3, 0x5fd, 0x1f5a, 0x2d0, 0x2cd1, 0x9ee, 0x218b, 0x19fd, 0x53b, 0x28c5, 0xe33, 0x1911, 0x26cc, 0x2018, 0x2f88, 0x1b01, 0x2637, 0x1cd9, 0x126b, 0x1a0b, 0x5b0, 0x24e0, 0xe82, 0xb1, 0x21f7, 0x1a16, 0x2f24, 0x1cb1, 0x1f7d, 0x28a0, 0x167e, 0xc3];
+    NHS.iroots = [0x2aac, 0x2292, 0x3a6, 0x139a, 0x272e, 0x60b, 0x96a, 0x244, 0x2b2a, 0x2a75, 0x1de6, 0x831, 0x9b7, 0xf16, 0x2616, 0x1485, 0x2fd, 0x34f, 0xf5d, 0x1072, 0x108d, 0x2c9e, 0x2a3, 0xb64, 0xa19, 0x538, 0x1a80, 0x1650, 0x1c51, 0x148f, 0x616, 0x185f, 0x1143, 0x2802, 0x88d, 0x1594, 0x1a24, 0x12d7, 0x120e, 0xcb6, 0x2690, 0x54c, 0x880, 0x2a7b, 0x2c68, 0x780, 0x24, 0xff8, 0x951, 0x1d8, 0x10d6, 0x2254, 0xee4, 0x2572, 0x2a1b, 0xcec, 0x224e, 0x2c82, 0x2570, 0x158f, 0xc0a, 0x2c54, 0x208, 0x1bfa, 0x3ff, 0x5be, 0x151c, 0x123a, 0x682, 0x1846, 0x2b0f, 0x1e7b, 0x8cc, 0x185, 0x521, 0x109, 0x1b53, 0x293c, 0x212d, 0x6fd, 0x19b8, 0x12f0, 0x2b8f, 0x1eb, 0x28aa, 0x2942, 0x893, 0x83d, 0x1464, 0xb48, 0x1f6a, 0x299f, 0x2ffd, 0x18e5, 0xf2b, 0xf9a, 0x14ee, 0x287e, 0xc29, 0x1f69, 0x144a, 0x515, 0x9ff, 0x2f06, 0x203, 0x2f18, 0x1b49, 0x1f77, 0xbc5, 0x1db9, 0x23a9, 0x2115, 0x2e4c, 0x1382, 0x24f8, 0x55, 0x2fb6, 0x2ebd, 0x2061, 0x1c82, 0x1264, 0x1d86, 0x4c1, 0x1675, 0x24a9, 0x17f6, 0x130d, 0x2dd1, 0x29d8, 0x9df, 0x277d, 0x1e6b, 0x17fd, 0x3c8, 0x1f46, 0x19a7, 0x2f95, 0x19, 0x1981, 0x2536, 0x201d, 0x13ae, 0x1092, 0x1980, 0x11b2, 0x93d, 0x1fad, 0x2cac, 0x2a79, 0x1bf3, 0x2907, 0x281, 0x29e9, 0xc14, 0xb07, 0x241e, 0xa7d, 0x6e8, 0x1f55, 0x104e, 0x2818, 0xdd5, 0xa29, 0x1a6, 0x2614, 0x8f7, 0x2eac, 0x2e17, 0x1dbf, 0x16e5, 0x2255, 0x24f2, 0x2059, 0x1e4b, 0x1d12, 0x1f7f, 0x1dc1, 0x2273, 0x2bf, 0x1d25, 0x10a4, 0x217c, 0x176e, 0x29b1, 0x284d, 0x2002, 0x2534, 0xaf2, 0x1de0, 0x1588, 0x2935, 0x1c3e, 0x1204, 0x2f1, 0x20c2, 0xcdd, 0x1689, 0xec9, 0x1c7, 0x247b, 0x2508, 0x2cc4, 0x6d7, 0x234f, 0x2bb, 0x609, 0x19d, 0x21da, 0x2ee0, 0xa7c, 0x3cc, 0x2f20, 0x257c, 0x2ae2, 0x2f02, 0xee6, 0x26db, 0x690, 0x1820, 0xdf9, 0x770, 0x72b, 0x1ca3, 0xe43, 0x1648, 0x174a, 0x143d, 0x19fc, 0x2732, 0x1d27, 0x2a40, 0x22ab, 0x280, 0x133, 0x1553, 0x2ff5, 0xe29, 0xd2b, 0x1326, 0x2e3d, 0x2c7c, 0x1b0a, 0x144f, 0x21f8, 0x2b72, 0x1a64, 0x2ce6, 0xf63, 0x1ec7, 0xbfd, 0x2954, 0xf53, 0x1730, 0x1386, 0x491, 0x212b, 0x222e, 0x3a5, 0xec5, 0x25c, 0x1755, 0x2945, 0x2c47, 0x8dd, 0x1b55, 0x4c9, 0x197, 0x2f31, 0x256d, 0x43a, 0x2be2, 0x166, 0x300, 0x14a4, 0xffd, 0x1cbf, 0x10fe, 0x1967, 0x2a2e, 0x1aaf, 0x256f, 0xfc8, 0xc4c, 0x299a, 0x21e3, 0x261, 0x2f26, 0x1ede, 0x2c70, 0x5b7, 0x11cf, 0x20c5, 0x29ae, 0x73e, 0x1ebd, 0x238, 0x1171, 0x11be, 0x222, 0x222d, 0xe8, 0x2c3d, 0x2055, 0x72f, 0x11d3, 0x7e0, 0x268d, 0x23f8, 0x2f54, 0x89a, 0x2bf7, 0x1ab7, 0x694, 0x2042, 0x2ecf, 0x847, 0x17c2, 0x2ef3, 0x2fb, 0x27c2, 0x12b2, 0x1e, 0x1501, 0x640, 0x22, 0x46a, 0x2716, 0xb66, 0x2663, 0x2157, 0x2f21, 0x1fb, 0x25c9, 0x7b3, 0x1f0c, 0x1a98, 0x28b1, 0x21b2, 0x2a09, 0x4f0, 0xc96, 0x2517, 0x2f33, 0x9f7, 0x1fc4, 0x218a, 0x1e08, 0xc9b, 0x1c69, 0xf34, 0xb16, 0x1ac5, 0x23b2, 0x2513, 0x1f99, 0x1922, 0x6a, 0x245a, 0x615, 0x1298, 0x1a7e, 0xac2, 0x24ce, 0x2db5, 0x15cb, 0x152e, 0x1a33, 0x97e, 0x138f, 0x1ccf, 0x230b, 0x2056, 0x10a6, 0x2d0a, 0x27d9, 0x21e4, 0x13f8, 0xb61, 0x8ea, 0x1ed4, 0x2019, 0x2c93, 0x1fbd, 0x291a, 0x3cb, 0x2959, 0x1a47, 0x1d08, 0x1edc, 0x254e, 0x2db4, 0x56c, 0x2f04, 0x1a74, 0xb4c, 0x2b8, 0x2ac8, 0x452, 0x297c, 0x666, 0xc1e, 0xfdd, 0x1633, 0x2dfa, 0x1861, 0x578, 0x241b, 0x13a5, 0x2710, 0x18bd, 0x32a, 0x1745, 0x2f3d, 0x13bc, 0x172c, 0x2c6b, 0x1179, 0xff5, 0x13cd, 0x2f9, 0x2216, 0x900, 0x9c5, 0x2ff7, 0x291, 0x368, 0x28de, 0x5a7, 0xa9, 0x104b, 0x1335, 0x24e4, 0xc5d, 0x2bcf, 0x2353, 0x1045, 0x21a6, 0x21fe, 0x270, 0x4c5, 0x2512, 0x688, 0x28ed, 0x2c4f, 0x1434, 0x15fe, 0x156a, 0x24d3, 0x1dc2, 0x283a, 0x22f5, 0x13e, 0x20ca, 0xb14, 0x149c, 0x2eca, 0x1169, 0x1387, 0x2078, 0x1160, 0xfbb, 0x1f79, 0x6e4, 0xe68, 0x1878, 0x2a57, 0x8e5, 0x1f1, 0x995, 0xaac, 0x2f01, 0x91f, 0xcb, 0x14b5, 0xa4a, 0x49, 0xdde, 0xbe7, 0x386, 0x1abe, 0x26a, 0x121c, 0x20be, 0x25c2, 0x2aed, 0x1a11, 0x2131, 0x1e19, 0xebf, 0xfb3, 0x265, 0x253a, 0x2b65, 0x2f4b, 0xa30, 0x2a17, 0x2de, 0x103a, 0x18e8, 0x1159, 0x2bfe, 0x1327, 0x2a10, 0x2d61, 0x2fa7, 0x815, 0x1d41, 0xf02, 0x22c3, 0x66, 0xdcf, 0x1540, 0x2f3e, 0x1983, 0x761, 0x1084, 0x1350, 0xdd, 0x15eb, 0xe0a, 0x2f50, 0x217f, 0xb21, 0x2a51, 0x15f6, 0x1d96, 0x1328, 0x9ca, 0x1500, 0x79, 0xfe9, 0x935, 0x16f0, 0x21ce, 0x73c, 0x2ac6, 0x1604, 0xe76, 0x2613, 0x330, 0x2d31, 0x10a7, 0x2a04, 0x180e, 0x170a, 0x2801, 0x1ca7, 0x255f, 0x3bc, 0x2b1, 0x1727, 0xf88, 0x1a15, 0x1c30, 0xeee, 0x2f37, 0x658, 0x15a5, 0x224f, 0x248, 0x1cc3, 0x71f, 0x1dd6, 0xbc3, 0x2b46, 0xc35, 0x13bb, 0x2afe, 0x2e0c, 0x21ca, 0x27a3, 0x9f0, 0x164b, 0x289f, 0x14dd, 0x2649, 0x22dc, 0xd2, 0x304, 0x2bc0, 0xee, 0x1ee6, 0x2195, 0x1fc9, 0x1cb0, 0x295d, 0x29e1, 0xddd, 0x187a, 0x5e4, 0x1950, 0x2a25, 0x2cd2, 0x2bda, 0x639, 0x2290, 0x2819, 0x139c, 0x2a5f, 0x15c0, 0x1e58, 0x2ac2, 0x1234, 0x283c, 0x6db, 0xa6a, 0x1d99, 0x2b60, 0x9d9, 0x1380, 0x1d2b, 0x1feb, 0x2e6, 0xe71, 0x2a93, 0x2226, 0x296f, 0x1b4d, 0x119d, 0x1fed, 0x88a, 0x43f, 0x2762, 0x1271, 0x28e7, 0x9a5, 0x548, 0x2256, 0x1488, 0x1b40, 0x26ea, 0x2d38, 0x2bc6, 0x1fa6, 0xe65, 0x17c8, 0x20ab, 0x17ff, 0x1e27, 0x2fb1, 0x1a8d, 0x169, 0x27ee, 0xb34, 0x1800, 0x151d, 0x1fe6, 0x25f4, 0x2916, 0x2929, 0x1f13, 0x1308, 0xb72, 0x1e3e, 0x25e, 0x2cca, 0x24d1, 0xf09, 0xb62, 0x21d0, 0x1aa4, 0x2648, 0xcb8, 0x2981, 0x216b, 0x1d28, 0x1626, 0x12e0, 0x2aa5, 0x2a22, 0x1231, 0x16e7, 0x1a4d, 0xfb1, 0x2a99, 0x14cf, 0x2e96, 0xeff, 0x1462, 0x2fbb, 0x11f7, 0x17d8, 0x2e0d, 0x2791, 0x49f, 0x120b, 0x2671, 0x1237, 0x268a, 0x12a3, 0x740, 0x11e1, 0x2b86, 0x2dee, 0x1110, 0x2163, 0x1379, 0x2db8, 0x2e76, 0x1623, 0x2d6a, 0x9ef, 0x5e3, 0x11c0, 0x104a, 0x2991, 0x4ae, 0x8b2, 0x2582, 0x1d8b, 0x41, 0x2780, 0x19dd, 0x28af, 0x2344, 0x199e, 0xe1b, 0x1c4b, 0x3b, 0x4d6, 0x1b45, 0x85b, 0xe42, 0xd97, 0x1312, 0x1ab3, 0x2901, 0xfd8, 0x58d, 0xf0, 0x1805, 0x1ff, 0x110, 0x2350, 0x18aa, 0x2b2f, 0x10e6, 0x1ec2, 0x252e, 0x1849, 0xc75, 0x2674, 0x2853, 0x12ab, 0x737, 0xde3, 0x10c3, 0x1491, 0xfbd, 0x2b07, 0x174f, 0x69b, 0x1412, 0x1194, 0x1e55, 0x196d, 0x13ec, 0x260f, 0x66a, 0x1da1, 0x2d8b, 0x892, 0xcc3, 0x90c, 0x350, 0x2ca, 0xa7, 0x4bd, 0x4e2, 0x1518, 0x2466, 0x14e9, 0x17e8, 0x1a78, 0x1ae6, 0x238e, 0x2d0d, 0xaf, 0x2284, 0x1475, 0x20c7, 0x29c0, 0x13fc, 0x227d, 0x1bdc, 0x10aa, 0x1db7, 0x18ae, 0x949, 0x3a1, 0x2f2c, 0x1187, 0x559, 0x248b, 0x1d30, 0xccd, 0x196a, 0x57, 0x1b4f, 0x1220, 0x28a3, 0xd1, 0x171e, 0xb8a, 0x1a87, 0xec0, 0x26ae, 0x229b, 0x1035, 0x1040, 0x4e, 0x1299, 0x226b, 0x1409, 0xb7a, 0x1c75, 0x1043, 0x120, 0x1339, 0xbff, 0x147a, 0x2a60, 0x13ff, 0x3d1, 0x2a16, 0x200a, 0x1467, 0x1c9d, 0x111c, 0x6b5, 0x6d, 0x5ae, 0x1e1a, 0x1497, 0x254a, 0x2a0a, 0xdbc, 0x77d, 0xc71, 0xf58, 0x1333, 0x1956, 0x2fe1, 0x724, 0x131d, 0x2a3f, 0xb4b, 0x2cf2, 0x281a, 0x1963, 0x1a94, 0x29da, 0x165f, 0xc28, 0x2908, 0x848, 0x1ff8, 0x2df0, 0x18dd, 0x1cd, 0x40f, 0x22c, 0x871, 0x3d3, 0xbf5, 0x1303, 0x2da9, 0x25e1, 0x2259, 0xc0d, 0x7ba, 0x2a8, 0x1180, 0x865, 0x542, 0x2fad, 0x31d, 0x2c2c, 0x2608, 0x23a5, 0x175e, 0x2d43, 0x2e27, 0x2dc4, 0x1018, 0x28b9, 0x1a44, 0xbb3, 0x176d, 0x23ea, 0x146, 0xb43, 0x124d, 0x28a8, 0x1ff7, 0x2829, 0x1bf9, 0x2832, 0x3c1, 0x1f94, 0x2d8e, 0x19e7, 0xd63, 0x1559, 0xd93, 0xaa3, 0x23e7, 0x73f, 0x2f42, 0x9e, 0x2837, 0xea, 0x2405, 0x248e, 0x10e3, 0xd6d, 0x2ca1, 0xc8, 0xc04, 0x9aa, 0x2eba, 0x1ef7, 0x1be2, 0x353, 0x2fe5, 0x1e40, 0xa2b, 0xd34, 0x27f, 0x2b6d, 0x251e, 0x1bdb, 0x2e04, 0x2393, 0x15f8, 0x2924, 0xe15, 0x29a2, 0x2efc, 0x1c3d, 0x2262, 0x100b, 0x99a, 0x278f, 0x240e, 0x288c, 0x12c3, 0x253, 0x2df4, 0x2725, 0x22a3, 0x78a, 0x20ba, 0xea6, 0x2147, 0xd30, 0x109a, 0x17b7, 0x2559, 0x20b1, 0x18d3, 0x2809, 0xbda, 0x709, 0x26f9, 0x23df, 0x1e60, 0x28f9, 0x1deb, 0x2514, 0xb7f, 0x957, 0x16d2, 0x47f, 0xfc, 0xfc6, 0x1136, 0xce8, 0x15d8, 0x47, 0x83a, 0x1619, 0x6b7, 0x2a73, 0x1d, 0x1788, 0x160b, 0x6e6, 0x2445, 0x1646, 0xe38, 0x3d2, 0x14eb, 0x1729, 0xb89, 0x131c, 0x13d9, 0x184c, 0x1275, 0x1fbb, 0x16ae, 0x2488, 0x297d, 0xc2d, 0x633, 0x2fe7, 0x2a9a, 0x1a96, 0xe20, 0x92d, 0x1146, 0x956, 0x1400, 0x998, 0x1a95, 0x2fa1, 0x223d, 0x2a4d, 0x11e5, 0xfdc, 0x198a, 0x2934, 0x1f9, 0x2553];
+
+    return NHS;
+};
diff --git a/version3/js/pair.js b/version3/js/pair.js
new file mode 100644
index 0000000..6e2cfb1
--- /dev/null
+++ b/version3/js/pair.js
@@ -0,0 +1,774 @@
+/*
+    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.
+*/
+
+var PAIR = function(ctx) {
+    "use strict";
+
+    var PAIR = {
+        /* Line function */
+        line: function(A, B, Qx, Qy) {
+            var r = new ctx.FP12(1),
+                c = new ctx.FP4(0),
+                XX, YY, ZZ, YZ, sb,
+                X1, Y1, T1, T2,
+                a, b;
+
+            if (A == B) { /* Doubling */
+                XX = new ctx.FP2(A.getx());
+                YY = new ctx.FP2(A.gety());
+                ZZ = new ctx.FP2(A.getz());
+                YZ = new ctx.FP2(YY);
+
+                YZ.mul(ZZ); //YZ
+                XX.sqr(); //X^2
+                YY.sqr(); //Y^2
+                ZZ.sqr(); //Z^2
+
+                YZ.imul(4);
+                YZ.neg();
+                YZ.norm(); //-2YZ
+                YZ.pmul(Qy); //-2YZ.Ys
+
+                XX.imul(6); //3X^2
+                XX.pmul(Qx); //3X^2.Xs
+
+                sb = 3 * ctx.ROM_CURVE.CURVE_B_I;
+                ZZ.imul(sb);
+                if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) {
+                    ZZ.div_ip2();
+                }
+                if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) {
+                    ZZ.mul_ip();
+                    ZZ.add(ZZ);
+                    YZ.mul_ip();
+                    YZ.norm();
+                }
+                ZZ.norm(); // 3b.Z^2
+
+                YY.add(YY);
+                ZZ.sub(YY);
+                ZZ.norm(); // 3b.Z^2-Y^2
+
+                a = new ctx.FP4(YZ, ZZ); // -2YZ.Ys | 3b.Z^2-Y^2 | 3X^2.Xs
+                if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) {
+                    b = new ctx.FP4(XX); // L(0,1) | L(0,0) | L(1,0)
+                    c = new ctx.FP4(0);
+                }
+                if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) {
+                    b = new ctx.FP4(0);
+                    c = new ctx.FP4(XX); c.times_i();
+                }
+
+                A.dbl();
+            } else { /* Addition */
+                X1 = new ctx.FP2(A.getx()); // X1
+                Y1 = new ctx.FP2(A.gety()); // Y1
+                T1 = new ctx.FP2(A.getz()); // Z1
+                T2 = new ctx.FP2(A.getz()); // Z1
+
+                T1.mul(B.gety()); // T1=Z1.Y2
+                T2.mul(B.getx()); // T2=Z1.X2
+
+                X1.sub(T2);
+                X1.norm(); // X1=X1-Z1.X2
+                Y1.sub(T1);
+                Y1.norm(); // Y1=Y1-Z1.Y2
+
+                T1.copy(X1); // T1=X1-Z1.X2
+                X1.pmul(Qy); // X1=(X1-Z1.X2).Ys
+
+                if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) {
+                    X1.mul_ip();
+                    X1.norm();
+                }
+
+                T1.mul(B.gety()); // T1=(X1-Z1.X2).Y2
+
+                T2.copy(Y1); // T2=Y1-Z1.Y2
+                T2.mul(B.getx()); // T2=(Y1-Z1.Y2).X2
+                T2.sub(T1);
+                T2.norm(); // T2=(Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2
+                Y1.pmul(Qx);
+                Y1.neg();
+                Y1.norm(); // Y1=-(Y1-Z1.Y2).Xs
+
+                a = new ctx.FP4(X1, T2); // (X1-Z1.X2).Ys  |  (Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2  | - (Y1-Z1.Y2).Xs
+                if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) {
+                    b = new ctx.FP4(Y1);
+                    c = new ctx.FP4(0);
+                }
+                if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) {
+                    b = new ctx.FP4(0);
+                    c = new ctx.FP4(Y1); c.times_i();
+                }
+
+                A.add(B);
+            }
+
+            r.set(a, b, c);
+
+            return r;
+        },
+
+        /* Optimal R-ate pairing */
+        ate: function(P1, Q1) {
+            var fa, fb, f, x, n, n3, K, lv,
+                Qx, Qy, A, NP, r, nb, bt,
+                i;
+
+            x = new ctx.BIG(0);
+            x.rcopy(ctx.ROM_CURVE.CURVE_Bnx);
+            n = new ctx.BIG(x); //n.copy(x);
+            K = new ctx.ECP2();
+
+            if (ctx.ECP.CURVE_PAIRING_TYPE == ctx.ECP.BN) {
+
+                fa = new ctx.BIG(0);
+                fa.rcopy(ctx.ROM_FIELD.Fra);
+                fb = new ctx.BIG(0);
+                fb.rcopy(ctx.ROM_FIELD.Frb);
+                f = new ctx.FP2(fa, fb); //f.bset(fa,fb);
+
+                if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) {
+                    f.inverse();
+                    f.norm();
+                }
+
+                n.pmul(6);
+                if (ctx.ECP.SIGN_OF_X == ctx.ECP.POSITIVEX) {
+                    n.inc(2);
+                } else {
+                    n.dec(2);
+                }
+            } else {
+                n.copy(x);
+            }
+            n.norm();
+
+            n3 = new ctx.BIG(n);
+            n3.pmul(3);
+            n3.norm();
+
+			var P=new ctx.ECP2(); P.copy(P1); P.affine();
+			var Q=new ctx.ECP(); Q.copy(Q1); Q.affine();
+
+            //  P.affine();
+            //  Q.affine();
+            Qx = new ctx.FP(Q.getx()); //Qx.copy(Q.getx());
+            Qy = new ctx.FP(Q.gety()); //Qy.copy(Q.gety());
+
+            A = new ctx.ECP2();
+            r = new ctx.FP12(1);
+            A.copy(P);
+
+			NP = new ctx.ECP2();
+			NP.copy(P);
+			NP.neg();
+
+            nb = n3.nbits();
+
+            for (i = nb - 2; i >= 1; i--) {
+                r.sqr();
+                lv = PAIR.line(A, A, Qx, Qy);
+
+                r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+
+                bt=n3.bit(i)-n.bit(i);
+
+                if (bt == 1) {
+                    lv = PAIR.line(A, P, Qx, Qy);
+                    r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+                }
+                if (bt == -1) {
+                    //P.neg();
+                    lv = PAIR.line(A, NP, Qx, Qy);
+                    r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+                    //P.neg();
+                }
+            }
+
+            if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) {
+                r.conj();
+            }
+
+            /* R-ate fixup */
+            if (ctx.ECP.CURVE_PAIRING_TYPE == ctx.ECP.BN) {
+                if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) {
+                    //r.conj();
+                    A.neg();
+                }
+
+                K.copy(P);
+                K.frob(f);
+
+                lv = PAIR.line(A, K, Qx, Qy);
+                r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+                K.frob(f);
+                K.neg();
+                lv = PAIR.line(A, K, Qx, Qy);
+                r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+            }
+
+            return r;
+        },
+
+        /* Optimal R-ate double pairing e(P,Q).e(R,S) */
+        ate2: function(P1, Q1, R1, S1) {
+            var fa, fb, f, x, n, n3, K, lv,
+                Qx, Qy, Sx, Sy, A, B, NP,NR,r, nb, bt,
+                i;
+
+
+            x = new ctx.BIG(0);
+            x.rcopy(ctx.ROM_CURVE.CURVE_Bnx);
+
+            n = new ctx.BIG(x); //n.copy(x);
+            K = new ctx.ECP2();
+
+            if (ctx.ECP.CURVE_PAIRING_TYPE == ctx.ECP.BN) {
+                fa = new ctx.BIG(0);
+                fa.rcopy(ctx.ROM_FIELD.Fra);
+                fb = new ctx.BIG(0);
+                fb.rcopy(ctx.ROM_FIELD.Frb);
+                f = new ctx.FP2(fa, fb); //f.bset(fa,fb);
+
+                if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) {
+                    f.inverse();
+                    f.norm();
+                }
+
+                n.pmul(6);
+                if (ctx.ECP.SIGN_OF_X == ctx.ECP.POSITIVEX) {
+                    n.inc(2);
+                } else {
+                    n.dec(2);
+                }
+            } else {
+                n.copy(x);
+            }
+            n.norm();
+
+            n3 = new ctx.BIG(n);
+            n3.pmul(3);
+            n3.norm();
+
+			var P=new ctx.ECP2(); P.copy(P1); P.affine();
+			var Q=new ctx.ECP(); Q.copy(Q1); Q.affine();
+			var R=new ctx.ECP2(); R.copy(R1); R.affine();
+			var S=new ctx.ECP(); S.copy(S1); S.affine();
+
+
+            Qx = new ctx.FP(Q.getx()); //Qx.copy(Q.getx());
+            Qy = new ctx.FP(Q.gety()); //Qy.copy(Q.gety());
+
+            Sx = new ctx.FP(S.getx()); //Sx.copy(S.getx());
+            Sy = new ctx.FP(S.gety()); //Sy.copy(S.gety());
+
+            A = new ctx.ECP2();
+            B = new ctx.ECP2();
+            r = new ctx.FP12(1);
+
+            A.copy(P);
+            B.copy(R);
+
+			NP = new ctx.ECP2();
+			NP.copy(P);
+			NP.neg();
+			NR = new ctx.ECP2();
+			NR.copy(R);
+			NR.neg();
+
+            nb = n3.nbits();
+
+            for (i = nb - 2; i >= 1; i--) {
+                r.sqr();
+                lv = PAIR.line(A, A, Qx, Qy);
+                r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+                lv = PAIR.line(B, B, Sx, Sy);
+                r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+
+                bt=n3.bit(i)-n.bit(i);
+
+                if (bt == 1) {
+                    lv = PAIR.line(A, P, Qx, Qy);
+                    r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+                    lv = PAIR.line(B, R, Sx, Sy);
+                    r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+                }
+                if (bt == -1) {
+                    //P.neg();
+                    lv = PAIR.line(A, NP, Qx, Qy);
+                    r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+                    //P.neg();
+                    //R.neg();
+                    lv = PAIR.line(B, NR, Sx, Sy);
+                    r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+                    //R.neg();
+                }
+            }
+
+            if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) {
+                r.conj();
+            }
+
+
+            /* R-ate fixup required for BN curves */
+            if (ctx.ECP.CURVE_PAIRING_TYPE == ctx.ECP.BN) {
+                if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) {
+                    // r.conj();
+                    A.neg();
+                    B.neg();
+                }
+                K.copy(P);
+                K.frob(f);
+
+                lv = PAIR.line(A, K, Qx, Qy);
+                r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+                K.frob(f);
+                K.neg();
+                lv = PAIR.line(A, K, Qx, Qy);
+                r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+
+                K.copy(R);
+                K.frob(f);
+
+                lv = PAIR.line(B, K, Sx, Sy);
+                r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+                K.frob(f);
+                K.neg();
+                lv = PAIR.line(B, K, Sx, Sy);
+                r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+            }
+
+            return r;
+        },
+
+        /* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */
+        fexp: function(m) {
+            var fa, fb, f, x, r, lv,
+                x0, x1, x2, x3, x4, x5,
+                y0, y1, y2, y3;
+
+            fa = new ctx.BIG(0);
+            fa.rcopy(ctx.ROM_FIELD.Fra);
+            fb = new ctx.BIG(0);
+            fb.rcopy(ctx.ROM_FIELD.Frb);
+            f = new ctx.FP2(fa, fb);
+            x = new ctx.BIG(0);
+            x.rcopy(ctx.ROM_CURVE.CURVE_Bnx);
+
+            r = new ctx.FP12(m); //r.copy(m);
+
+            /* Easy part of final exp */
+            lv = new ctx.FP12(r); //lv.copy(r);
+            lv.inverse();
+            r.conj();
+            r.mul(lv);
+            lv.copy(r);
+            r.frob(f);
+            r.frob(f);
+            r.mul(lv);
+
+            /* Hard part of final exp */
+            if (ctx.ECP.CURVE_PAIRING_TYPE == ctx.ECP.BN) {
+                lv.copy(r);
+                lv.frob(f);
+                x0 = new ctx.FP12(lv); //x0.copy(lv);
+                x0.frob(f);
+                lv.mul(r);
+                x0.mul(lv);
+                x0.frob(f);
+                x1 = new ctx.FP12(r); //x1.copy(r);
+                x1.conj();
+
+                x4 = r.pow(x);
+                if (ctx.ECP.SIGN_OF_X == ctx.ECP.POSITIVEX) {
+                    x4.conj();
+                }
+
+                x3 = new ctx.FP12(x4); //x3.copy(x4);
+                x3.frob(f);
+                x2 = x4.pow(x);
+                if (ctx.ECP.SIGN_OF_X == ctx.ECP.POSITIVEX) {
+                    x2.conj();
+                }
+                x5 = new ctx.FP12(x2); /*x5.copy(x2);*/
+                x5.conj();
+                lv = x2.pow(x);
+                if (ctx.ECP.SIGN_OF_X == ctx.ECP.POSITIVEX) {
+                    lv.conj();
+                }
+                x2.frob(f);
+                r.copy(x2);
+                r.conj();
+
+                x4.mul(r);
+                x2.frob(f);
+
+                r.copy(lv);
+                r.frob(f);
+                lv.mul(r);
+
+                lv.usqr();
+                lv.mul(x4);
+                lv.mul(x5);
+                r.copy(x3);
+                r.mul(x5);
+                r.mul(lv);
+                lv.mul(x2);
+                r.usqr();
+                r.mul(lv);
+                r.usqr();
+                lv.copy(r);
+                lv.mul(x1);
+                r.mul(x0);
+                lv.usqr();
+                r.mul(lv);
+                r.reduce();
+            } else {
+                // Ghamman & Fouotsa Method
+                y0 = new ctx.FP12(r);
+                y0.usqr();
+                y1 = y0.pow(x);
+                if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) {
+                    y1.conj();
+                }
+                x.fshr(1);
+                y2 = y1.pow(x);
+                if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) {
+                    y2.conj();
+                }
+                x.fshl(1);
+                y3 = new ctx.FP12(r);
+                y3.conj();
+                y1.mul(y3);
+
+                y1.conj();
+                y1.mul(y2);
+
+                y2 = y1.pow(x);
+                if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) {
+                    y2.conj();
+                }
+
+                y3 = y2.pow(x);
+                if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) {
+                    y3.conj();
+                }
+                y1.conj();
+                y3.mul(y1);
+
+                y1.conj();
+                y1.frob(f);
+                y1.frob(f);
+                y1.frob(f);
+                y2.frob(f);
+                y2.frob(f);
+                y1.mul(y2);
+
+                y2 = y3.pow(x);
+                if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) {
+                    y2.conj();
+                }
+                y2.mul(y0);
+                y2.mul(r);
+
+                y1.mul(y2);
+                y2.copy(y3);
+                y2.frob(f);
+                y1.mul(y2);
+                r.copy(y1);
+                r.reduce();
+            }
+
+            return r;
+        }
+    };
+
+    /* GLV method */
+    PAIR.glv = function(e) {
+        var u = [],
+            t, q, v, d, x, x2, i, j;
+
+        if (ctx.ECP.CURVE_PAIRING_TYPE == ctx.ECP.BN) {
+            t = new ctx.BIG(0);
+            q = new ctx.BIG(0);
+            v = [];
+
+            q.rcopy(ctx.ROM_CURVE.CURVE_Order);
+
+            for (i = 0; i < 2; i++) {
+                t.rcopy(ctx.ROM_CURVE.CURVE_W[i]);
+                d = ctx.BIG.mul(t, e);
+                v[i] = new ctx.BIG(d.div(q));
+                u[i] = new ctx.BIG(0);
+            }
+
+            u[0].copy(e);
+
+            for (i = 0; i < 2; i++) {
+                for (j = 0; j < 2; j++) {
+                    t.rcopy(ctx.ROM_CURVE.CURVE_SB[j][i]);
+                    t.copy(ctx.BIG.modmul(v[j], t, q));
+                    u[i].add(q);
+                    u[i].sub(t);
+                    u[i].mod(q);
+                }
+            }
+        } else { // -(x^2).P = (Beta.x,y)
+            q = new ctx.BIG(0);
+            q.rcopy(ctx.ROM_CURVE.CURVE_Order);
+            x = new ctx.BIG(0);
+            x.rcopy(ctx.ROM_CURVE.CURVE_Bnx);
+            x2 = ctx.BIG.smul(x, x);
+            u[0] = new ctx.BIG(e);
+            u[0].mod(x2);
+            u[1] = new ctx.BIG(e);
+            u[1].div(x2);
+            u[1].rsub(q);
+        }
+
+        return u;
+    };
+
+    /* Galbraith & Scott Method */
+    PAIR.gs = function(e) {
+        var u = [],
+            i, j, t, q, v, d, x, w;
+
+        if (ctx.ECP.CURVE_PAIRING_TYPE == ctx.ECP.BN) {
+            t = new ctx.BIG(0);
+            q = new ctx.BIG(0);
+            q.rcopy(ctx.ROM_CURVE.CURVE_Order);
+
+            v = [];
+
+            for (i = 0; i < 4; i++) {
+                t.rcopy(ctx.ROM_CURVE.CURVE_WB[i]);
+                d = ctx.BIG.mul(t, e);
+                v[i] = new ctx.BIG(d.div(q));
+                u[i] = new ctx.BIG(0);
+            }
+
+            u[0].copy(e);
+
+            for (i = 0; i < 4; i++) {
+                for (j = 0; j < 4; j++) {
+                    t.rcopy(ctx.ROM_CURVE.CURVE_BB[j][i]);
+                    t.copy(ctx.BIG.modmul(v[j], t, q));
+                    u[i].add(q);
+                    u[i].sub(t);
+                    u[i].mod(q);
+                }
+            }
+        } else {
+            x = new ctx.BIG(0);
+            x.rcopy(ctx.ROM_CURVE.CURVE_Bnx);
+            q = new ctx.BIG(0);
+            q.rcopy(ctx.ROM_CURVE.CURVE_Order);
+            w = new ctx.BIG(e);
+
+            for (i = 0; i < 3; i++) {
+                u[i] = new ctx.BIG(w);
+                u[i].mod(x);
+                w.div(x);
+            }
+
+            u[3] = new ctx.BIG(w);
+            if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) {
+                u[1].copy(ctx.BIG.modneg(u[1], q));
+                u[3].copy(ctx.BIG.modneg(u[3], q));
+            }
+        }
+
+        return u;
+    };
+
+    /* Multiply P by e in group G1 */
+    PAIR.G1mul = function(P, e) {
+        var R, Q, q, bcru, cru, t, u, np, nn;
+
+        if (ctx.ROM_CURVE.USE_GLV) {
+            //P.affine();
+            R = new ctx.ECP();
+            R.copy(P);
+            Q = new ctx.ECP();
+            Q.copy(P); Q.affine();
+            q = new ctx.BIG(0);
+            q.rcopy(ctx.ROM_CURVE.CURVE_Order);
+            bcru = new ctx.BIG(0);
+            bcru.rcopy(ctx.ROM_CURVE.CURVE_Cru);
+            cru = new ctx.FP(bcru);
+            t = new ctx.BIG(0);
+            u = PAIR.glv(e);
+
+            Q.getx().mul(cru);
+
+            np = u[0].nbits();
+            t.copy(ctx.BIG.modneg(u[0], q));
+            nn = t.nbits();
+            if (nn < np) {
+                u[0].copy(t);
+                R.neg();
+            }
+
+            np = u[1].nbits();
+            t.copy(ctx.BIG.modneg(u[1], q));
+            nn = t.nbits();
+            if (nn < np) {
+                u[1].copy(t);
+                Q.neg();
+            }
+            u[0].norm();
+            u[1].norm();
+            R = R.mul2(u[0], Q, u[1]);
+        } else {
+            R = P.mul(e);
+        }
+
+        return R;
+    };
+
+    /* Multiply P by e in group G2 */
+    PAIR.G2mul = function(P, e) {
+        var R, Q, fa, fb, f, q, u, t, i, np, nn;
+
+        if (ctx.ROM_CURVE.USE_GS_G2) {
+            Q = [];
+            fa = new ctx.BIG(0);
+            fa.rcopy(ctx.ROM_FIELD.Fra);
+            fb = new ctx.BIG(0);
+            fb.rcopy(ctx.ROM_FIELD.Frb);
+            f = new ctx.FP2(fa, fb); //f.bset(fa,fb);
+
+            if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) {
+                f.inverse();
+                f.norm();
+            }
+
+            q = new ctx.BIG(0);
+            q.rcopy(ctx.ROM_CURVE.CURVE_Order);
+
+            u = PAIR.gs(e);
+            t = new ctx.BIG(0);
+            //P.affine();
+            Q[0] = new ctx.ECP2();
+            Q[0].copy(P);
+
+            for (i = 1; i < 4; i++) {
+                Q[i] = new ctx.ECP2();
+                Q[i].copy(Q[i - 1]);
+                Q[i].frob(f);
+            }
+
+            for (i = 0; i < 4; i++) {
+                np = u[i].nbits();
+                t.copy(ctx.BIG.modneg(u[i], q));
+                nn = t.nbits();
+
+                if (nn < np) {
+                    u[i].copy(t);
+                    Q[i].neg();
+                }
+                u[i].norm();
+            }
+
+            R = ctx.ECP2.mul4(Q, u);
+        } else {
+            R = P.mul(e);
+        }
+        return R;
+    };
+
+    /* Note that this method requires a lot of RAM! Better to use compressed XTR method, see ctx.FP4.js */
+    PAIR.GTpow = function(d, e) {
+        var r, g, fa, fb, f, q, t, u, i, np, nn;
+
+        if (ctx.ROM_CURVE.USE_GS_GT) {
+            g = [];
+            fa = new ctx.BIG(0);
+            fa.rcopy(ctx.ROM_FIELD.Fra);
+            fb = new ctx.BIG(0);
+            fb.rcopy(ctx.ROM_FIELD.Frb);
+            f = new ctx.FP2(fa, fb);
+            q = new ctx.BIG(0);
+            q.rcopy(ctx.ROM_CURVE.CURVE_Order);
+            t = new ctx.BIG(0);
+            u = PAIR.gs(e);
+
+            g[0] = new ctx.FP12(d);
+
+            for (i = 1; i < 4; i++) {
+                g[i] = new ctx.FP12(0);
+                g[i].copy(g[i - 1]);
+                g[i].frob(f);
+            }
+
+            for (i = 0; i < 4; i++) {
+                np = u[i].nbits();
+                t.copy(ctx.BIG.modneg(u[i], q));
+                nn = t.nbits();
+
+                if (nn < np) {
+                    u[i].copy(t);
+                    g[i].conj();
+                }
+                u[i].norm();
+            }
+
+            r = ctx.FP12.pow4(g, u);
+        } else {
+            r = d.pow(e);
+        }
+
+        return r;
+    };
+
+    /* test group membership - no longer needed */
+    /* with GT-Strong curve, now only check that m!=1, conj(m)*m==1, and m.m^{p^4}=m^{p^2} */
+    /*
+    PAIR.GTmember= function(m)
+    {
+        if (m.isunity()) return false;
+        var r=new ctx.FP12(m);
+        r.conj();
+        r.mul(m);
+        if (!r.isunity()) return false;
+
+        var fa=new ctx.BIG(0); fa.rcopy(ctx.ROM_FIELD.Fra);
+        var fb=new ctx.BIG(0); fb.rcopy(ctx.ROM_FIELD.Frb);
+        var f=new ctx.FP2(fa,fb); //f.bset(fa,fb);
+
+        r.copy(m); r.frob(f); r.frob(f);
+        var w=new ctx.FP12(r); w.frob(f); w.frob(f);
+        w.mul(m);
+        if (!ctx.ROM_CURVE.GT_STRONG)
+        {
+            if (!w.equals(r)) return false;
+            var x=new ctx.BIG(0); x.rcopy(ctx.ROM_CURVE.CURVE_Bnx);
+            r.copy(m); w=r.pow(x); w=w.pow(x);
+            r.copy(w); r.sqr(); r.mul(w); r.sqr();
+            w.copy(m); w.frob(f);
+        }
+        return w.equals(r);
+    };
+    */
+
+    return PAIR;
+};
diff --git a/version3/js/pair192.js b/version3/js/pair192.js
new file mode 100644
index 0000000..47eea4a
--- /dev/null
+++ b/version3/js/pair192.js
@@ -0,0 +1,545 @@
+/*
+    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.
+*/
+
+var PAIR192 = function(ctx) {
+    "use strict";
+
+    var PAIR192 = {
+        /* Line function */
+        line: function(A, B, Qx, Qy) {
+            var r = new ctx.FP24(1),
+                XX, YY, ZZ, YZ, sb,
+                X1, Y1, T1, T2,
+                a, b, c;
+
+            if (A == B) { /* Doubling */
+                XX = new ctx.FP4(A.getx());
+                YY = new ctx.FP4(A.gety());
+                ZZ = new ctx.FP4(A.getz());
+                YZ = new ctx.FP4(YY);
+
+                YZ.mul(ZZ); //YZ
+                XX.sqr(); //X^2
+                YY.sqr(); //Y^2
+                ZZ.sqr(); //Z^2
+
+                YZ.imul(4);
+                YZ.neg();
+                YZ.norm(); //-2YZ
+                YZ.qmul(Qy); //-2YZ.Ys
+
+                XX.imul(6); //3X^2
+                XX.qmul(Qx); //3X^2.Xs
+
+                sb = 3 * ctx.ROM_CURVE.CURVE_B_I;
+                ZZ.imul(sb);
+                if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) {
+                    ZZ.div_2i();
+                }
+                if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) {
+                    ZZ.times_i();
+                    ZZ.add(ZZ);
+                    YZ.times_i();
+                    YZ.norm();
+                }
+                ZZ.norm(); // 3b.Z^2
+
+                YY.add(YY);
+                ZZ.sub(YY);
+                ZZ.norm(); // 3b.Z^2-Y^2
+
+                a = new ctx.FP8(YZ, ZZ); // -2YZ.Ys | 3b.Z^2-Y^2 | 3X^2.Xs
+                if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) {
+                    b = new ctx.FP8(XX); // L(0,1) | L(0,0) | L(1,0)
+                    c = new ctx.FP8(0);
+                }
+                if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) {
+                    b = new ctx.FP8(0);
+                    c = new ctx.FP8(XX); c.times_i();
+                }
+
+                A.dbl();
+            } else { /* Addition */
+                X1 = new ctx.FP4(A.getx()); // X1
+                Y1 = new ctx.FP4(A.gety()); // Y1
+                T1 = new ctx.FP4(A.getz()); // Z1
+                T2 = new ctx.FP4(A.getz()); // Z1
+
+                T1.mul(B.gety()); // T1=Z1.Y2
+                T2.mul(B.getx()); // T2=Z1.X2
+
+                X1.sub(T2);
+                X1.norm(); // X1=X1-Z1.X2
+                Y1.sub(T1);
+                Y1.norm(); // Y1=Y1-Z1.Y2
+
+                T1.copy(X1); // T1=X1-Z1.X2
+                X1.qmul(Qy); // X1=(X1-Z1.X2).Ys
+
+                if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) {
+                    X1.times_i();
+                    X1.norm();
+                }
+
+                T1.mul(B.gety()); // T1=(X1-Z1.X2).Y2
+
+                T2.copy(Y1); // T2=Y1-Z1.Y2
+                T2.mul(B.getx()); // T2=(Y1-Z1.Y2).X2
+                T2.sub(T1);
+                T2.norm(); // T2=(Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2
+                Y1.qmul(Qx);
+                Y1.neg();
+                Y1.norm(); // Y1=-(Y1-Z1.Y2).Xs
+
+                a = new ctx.FP8(X1, T2); // (X1-Z1.X2).Ys  |  (Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2  | - (Y1-Z1.Y2).Xs
+                if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) {
+                    b = new ctx.FP8(Y1);
+                    c = new ctx.FP8(0);
+                }
+                if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) {
+                    b = new ctx.FP8(0);
+                    c = new ctx.FP8(Y1); c.times_i();
+                }
+
+                A.add(B);
+            }
+
+            r.set(a, b, c);
+
+            return r;
+        },
+
+        /* Optimal R-ate pairing */
+        ate: function(P1, Q1) {
+            var x, n, n3, lv,
+                Qx, Qy, A, NP, r, nb, bt,
+                i;
+
+            x = new ctx.BIG(0);
+            x.rcopy(ctx.ROM_CURVE.CURVE_Bnx);
+            n = new ctx.BIG(x); //n.copy(x);
+
+            n3 = new ctx.BIG(n);
+            n3.pmul(3);
+            n3.norm();
+
+			var P=new ctx.ECP4(); P.copy(P1); P.affine();
+			var Q=new ctx.ECP(); Q.copy(Q1); Q.affine();
+
+            //  P.affine();
+            //  Q.affine();
+            Qx = new ctx.FP(Q.getx()); //Qx.copy(Q.getx());
+            Qy = new ctx.FP(Q.gety()); //Qy.copy(Q.gety());
+
+            A = new ctx.ECP4();
+            r = new ctx.FP24(1);
+
+            A.copy(P);
+			NP = new ctx.ECP4();
+			NP.copy(P);
+			NP.neg();
+
+
+            nb = n3.nbits();
+
+            for (i = nb - 2; i >= 1; i--) {
+                r.sqr();
+                lv = PAIR192.line(A, A, Qx, Qy);
+
+                r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+
+                bt=n3.bit(i)-n.bit(i);
+
+                if (bt == 1) {
+                    lv = PAIR192.line(A, P, Qx, Qy);
+                    r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+                }
+                if (bt == -1) {
+                    //P.neg();
+                    lv = PAIR192.line(A, NP, Qx, Qy);
+                    r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+                    //P.neg();
+                }
+            }
+
+            if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) {
+                r.conj();
+            }
+
+            return r;
+        },
+
+        /* Optimal R-ate double pairing e(P,Q).e(R,S) */
+        ate2: function(P1, Q1, R1, S1) {
+            var x, n, n3, lv,
+                Qx, Qy, Sx, Sy, A, B, NP, NR, r, nb, bt,
+                i;
+
+
+            x = new ctx.BIG(0);
+            x.rcopy(ctx.ROM_CURVE.CURVE_Bnx);
+
+            n = new ctx.BIG(x); //n.copy(x);
+            n3 = new ctx.BIG(n);
+            n3.pmul(3);
+            n3.norm();
+
+			var P=new ctx.ECP4(); P.copy(P1); P.affine();
+			var Q=new ctx.ECP(); Q.copy(Q1); Q.affine();
+			var R=new ctx.ECP4(); R.copy(R1); R.affine();
+			var S=new ctx.ECP(); S.copy(S1); S.affine();
+
+
+            Qx = new ctx.FP(Q.getx()); //Qx.copy(Q.getx());
+            Qy = new ctx.FP(Q.gety()); //Qy.copy(Q.gety());
+
+            Sx = new ctx.FP(S.getx()); //Sx.copy(S.getx());
+            Sy = new ctx.FP(S.gety()); //Sy.copy(S.gety());
+
+            A = new ctx.ECP4();
+            B = new ctx.ECP4();
+            r = new ctx.FP24(1);
+
+            A.copy(P);
+            B.copy(R);
+			NP = new ctx.ECP4();
+			NP.copy(P);
+			NP.neg();
+			NR = new ctx.ECP4();
+			NR.copy(R);
+			NR.neg();
+
+
+            nb = n3.nbits();
+
+            for (i = nb - 2; i >= 1; i--) {
+                r.sqr();
+                lv = PAIR192.line(A, A, Qx, Qy);
+                r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+                lv = PAIR192.line(B, B, Sx, Sy);
+                r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+
+                bt=n3.bit(i)-n.bit(i);
+
+                if (bt == 1) {
+                    lv = PAIR192.line(A, P, Qx, Qy);
+                    r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+                    lv = PAIR192.line(B, R, Sx, Sy);
+                    r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+                }
+                if (bt == -1) {
+                    //P.neg();
+                    lv = PAIR192.line(A, NP, Qx, Qy);
+                    r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+                    //P.neg();
+                    //R.neg();
+                    lv = PAIR192.line(B, NR, Sx, Sy);
+                    r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+                    //R.neg();
+                }
+            }
+
+            if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) {
+                r.conj();
+            }
+
+            return r;
+        },
+
+        /* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */
+        fexp: function(m) {
+            var fa, fb, f, x, r, lv,
+                t0,t1,t2,t3,t4,t5,t6,t7;
+
+            fa = new ctx.BIG(0);
+            fa.rcopy(ctx.ROM_FIELD.Fra);
+            fb = new ctx.BIG(0);
+            fb.rcopy(ctx.ROM_FIELD.Frb);
+            f = new ctx.FP2(fa, fb);
+            x = new ctx.BIG(0);
+            x.rcopy(ctx.ROM_CURVE.CURVE_Bnx);
+
+            r = new ctx.FP24(m); //r.copy(m);
+
+            /* Easy part of final exp */
+            lv = new ctx.FP24(r); //lv.copy(r);
+            lv.inverse();
+            r.conj();
+            r.mul(lv);
+            lv.copy(r);
+            r.frob(f,4);
+            r.mul(lv);
+
+            /* Hard part of final exp */
+            // Ghamman & Fouotsa Method
+            t7=new ctx.FP24(r); t7.usqr();
+            t1=t7.pow(x);
+
+            x.fshr(1);
+            t2=t1.pow(x);
+            x.fshl(1);
+
+            if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) {
+                t1.conj();
+            }
+            t3=new ctx.FP24(t1); t3.conj();
+            t2.mul(t3);
+            t2.mul(r);
+
+            t3=t2.pow(x);
+            t4=t3.pow(x);
+            t5=t4.pow(x);
+
+            if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) {
+                t3.conj(); t5.conj();
+            }
+
+            t3.frob(f,6); t4.frob(f,5);
+            t3.mul(t4);
+
+            t6=t5.pow(x);
+            if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) {
+                t6.conj();
+            }
+
+            t5.frob(f,4);
+            t3.mul(t5);
+
+            t0=new ctx.FP24(t2); t0.conj();
+            t6.mul(t0);
+
+            t5.copy(t6);
+            t5.frob(f,3);
+
+            t3.mul(t5);
+            t5=t6.pow(x);
+            t6=t5.pow(x);
+
+            if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) {
+                t5.conj();
+            }
+
+            t0.copy(t5);
+            t0.frob(f,2);
+            t3.mul(t0);
+            t0.copy(t6);
+            t0.frob(f,1);
+
+            t3.mul(t0);
+            t5=t6.pow(x);
+
+            if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) {
+                t5.conj();
+            }
+            t2.frob(f,7);
+
+            t5.mul(t7);
+            t3.mul(t2);
+            t3.mul(t5);
+
+            r.mul(t3);
+
+            r.reduce();
+
+            return r;
+        }
+    };
+
+    /* GLV method */
+    PAIR192.glv = function(e) {
+        var u = [],
+            q, x, x2;
+
+        // -(x^2).P = (Beta.x,y)
+        q = new ctx.BIG(0);
+        q.rcopy(ctx.ROM_CURVE.CURVE_Order);
+        x = new ctx.BIG(0);
+        x.rcopy(ctx.ROM_CURVE.CURVE_Bnx);
+        x2 = ctx.BIG.smul(x, x);
+        x = ctx.BIG.smul(x2,x2);
+        u[0] = new ctx.BIG(e);
+        u[0].mod(x);
+        u[1] = new ctx.BIG(e);
+        u[1].div(x);
+        u[1].rsub(q);
+
+        return u;
+    };
+
+    /* Galbraith & Scott Method */
+    PAIR192.gs = function(e) {
+        var u = [],
+            i, q, x, w;
+
+        x = new ctx.BIG(0);
+        x.rcopy(ctx.ROM_CURVE.CURVE_Bnx);
+        q = new ctx.BIG(0);
+        q.rcopy(ctx.ROM_CURVE.CURVE_Order);
+        w = new ctx.BIG(e);
+
+        for (i = 0; i < 7; i++) {
+            u[i] = new ctx.BIG(w);
+            u[i].mod(x);
+            w.div(x);
+        }
+
+        u[7] = new ctx.BIG(w);
+        if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) {
+            u[1].copy(ctx.BIG.modneg(u[1], q));
+            u[3].copy(ctx.BIG.modneg(u[3], q));
+            u[5].copy(ctx.BIG.modneg(u[5], q));
+            u[7].copy(ctx.BIG.modneg(u[7], q));
+        }
+
+        return u;
+    };
+
+    /* Multiply P by e in group G1 */
+    PAIR192.G1mul = function(P, e) {
+        var R, Q, q, bcru, cru, t, u, np, nn;
+
+        if (ctx.ROM_CURVE.USE_GLV) {
+            //P.affine();
+            R = new ctx.ECP();
+            R.copy(P);
+            Q = new ctx.ECP();
+            Q.copy(P); Q.affine();
+            q = new ctx.BIG(0);
+            q.rcopy(ctx.ROM_CURVE.CURVE_Order);
+            bcru = new ctx.BIG(0);
+            bcru.rcopy(ctx.ROM_CURVE.CURVE_Cru);
+            cru = new ctx.FP(bcru);
+            t = new ctx.BIG(0);
+            u = PAIR192.glv(e);
+
+            Q.getx().mul(cru);
+
+            np = u[0].nbits();
+            t.copy(ctx.BIG.modneg(u[0], q));
+            nn = t.nbits();
+            if (nn < np) {
+                u[0].copy(t);
+                R.neg();
+            }
+
+            np = u[1].nbits();
+            t.copy(ctx.BIG.modneg(u[1], q));
+            nn = t.nbits();
+            if (nn < np) {
+                u[1].copy(t);
+                Q.neg();
+            }
+            u[0].norm();
+            u[1].norm();
+            R = R.mul2(u[0], Q, u[1]);
+        } else {
+            R = P.mul(e);
+        }
+
+        return R;
+    };
+
+    /* Multiply P by e in group G2 */
+    PAIR192.G2mul = function(P, e) {
+        var R, Q, F, q, u, t, i, np, nn;
+
+        if (ctx.ROM_CURVE.USE_GS_G2) {
+            Q = [];
+            F = ctx.ECP4.frob_constants();
+
+            q = new ctx.BIG(0);
+            q.rcopy(ctx.ROM_CURVE.CURVE_Order);
+
+            u = PAIR192.gs(e);
+            t = new ctx.BIG(0);
+            //P.affine();
+            Q[0] = new ctx.ECP4();
+            Q[0].copy(P);
+
+            for (i = 1; i < 8; i++) {
+                Q[i] = new ctx.ECP4();
+                Q[i].copy(Q[i - 1]);
+                Q[i].frob(F,1);
+            }
+
+            for (i = 0; i < 8; i++) {
+                np = u[i].nbits();
+                t.copy(ctx.BIG.modneg(u[i], q));
+                nn = t.nbits();
+
+                if (nn < np) {
+                    u[i].copy(t);
+                    Q[i].neg();
+                }
+                u[i].norm();
+            }
+
+            R = ctx.ECP4.mul8(Q, u);
+        } else {
+            R = P.mul(e);
+        }
+        return R;
+    };
+
+    /* Note that this method requires a lot of RAM! Better to use compressed XTR method, see ctx.FP4.js */
+    PAIR192.GTpow = function(d, e) {
+        var r, g, fa, fb, f, q, t, u, i, np, nn;
+
+        if (ctx.ROM_CURVE.USE_GS_GT) {
+            g = [];
+            fa = new ctx.BIG(0);
+            fa.rcopy(ctx.ROM_FIELD.Fra);
+            fb = new ctx.BIG(0);
+            fb.rcopy(ctx.ROM_FIELD.Frb);
+            f = new ctx.FP2(fa, fb);
+            q = new ctx.BIG(0);
+            q.rcopy(ctx.ROM_CURVE.CURVE_Order);
+            t = new ctx.BIG(0);
+            u = PAIR192.gs(e);
+
+            g[0] = new ctx.FP24(d);
+
+            for (i = 1; i < 8; i++) {
+                g[i] = new ctx.FP24(0);
+                g[i].copy(g[i - 1]);
+                g[i].frob(f,1);
+            }
+
+            for (i = 0; i < 8; i++) {
+                np = u[i].nbits();
+                t.copy(ctx.BIG.modneg(u[i], q));
+                nn = t.nbits();
+
+                if (nn < np) {
+                    u[i].copy(t);
+                    g[i].conj();
+                }
+                u[i].norm();
+            }
+
+            r = ctx.FP24.pow8(g, u);
+        } else {
+            r = d.pow(e);
+        }
+
+        return r;
+    };
+
+    return PAIR192;
+};
diff --git a/version3/js/pair256.js b/version3/js/pair256.js
new file mode 100644
index 0000000..8627998
--- /dev/null
+++ b/version3/js/pair256.js
@@ -0,0 +1,622 @@
+/*
+    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.
+*/
+
+var PAIR256 = function(ctx) {
+    "use strict";
+
+    var PAIR256 = {
+        /* Line function */
+        line: function(A, B, Qx, Qy) {
+            var r = new ctx.FP48(1),
+                XX, YY, ZZ, YZ, sb,
+                X1, Y1, T1, T2,
+                a, b, c;
+
+            if (A == B) { /* Doubling */
+                XX = new ctx.FP8(A.getx());
+                YY = new ctx.FP8(A.gety());
+                ZZ = new ctx.FP8(A.getz());
+                YZ = new ctx.FP8(YY);
+
+                YZ.mul(ZZ); //YZ
+                XX.sqr(); //X^2
+                YY.sqr(); //Y^2
+                ZZ.sqr(); //Z^2
+
+                YZ.imul(4);
+                YZ.neg();
+                YZ.norm(); //-2YZ
+                YZ.tmul(Qy); //-2YZ.Ys
+
+                XX.imul(6); //3X^2
+                XX.tmul(Qx); //3X^2.Xs
+
+                sb = 3 * ctx.ROM_CURVE.CURVE_B_I;
+                ZZ.imul(sb);
+                if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) {
+                    ZZ.div_2i();
+                }
+                if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) {
+                    ZZ.times_i();
+                    ZZ.add(ZZ);
+                    YZ.times_i();
+                    YZ.norm();
+                }
+                ZZ.norm(); // 3b.Z^2
+
+                YY.add(YY);
+                ZZ.sub(YY);
+                ZZ.norm(); // 3b.Z^2-Y^2
+
+                a = new ctx.FP16(YZ, ZZ); // -2YZ.Ys | 3b.Z^2-Y^2 | 3X^2.Xs
+                if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) {
+                    b = new ctx.FP16(XX); // L(0,1) | L(0,0) | L(1,0)
+                    c = new ctx.FP16(0);
+                }
+                if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) {
+                    b = new ctx.FP16(0);
+                    c = new ctx.FP16(XX); c.times_i();
+                }
+
+                A.dbl();
+            } else { /* Addition */
+                X1 = new ctx.FP8(A.getx()); // X1
+                Y1 = new ctx.FP8(A.gety()); // Y1
+                T1 = new ctx.FP8(A.getz()); // Z1
+                T2 = new ctx.FP8(A.getz()); // Z1
+
+                T1.mul(B.gety()); // T1=Z1.Y2
+                T2.mul(B.getx()); // T2=Z1.X2
+
+                X1.sub(T2);
+                X1.norm(); // X1=X1-Z1.X2
+                Y1.sub(T1);
+                Y1.norm(); // Y1=Y1-Z1.Y2
+
+                T1.copy(X1); // T1=X1-Z1.X2
+                X1.tmul(Qy); // X1=(X1-Z1.X2).Ys
+
+                if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) {
+                    X1.times_i();
+                    X1.norm();
+                }
+
+                T1.mul(B.gety()); // T1=(X1-Z1.X2).Y2
+
+                T2.copy(Y1); // T2=Y1-Z1.Y2
+                T2.mul(B.getx()); // T2=(Y1-Z1.Y2).X2
+                T2.sub(T1);
+                T2.norm(); // T2=(Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2
+                Y1.tmul(Qx);
+                Y1.neg();
+                Y1.norm(); // Y1=-(Y1-Z1.Y2).Xs
+
+                a = new ctx.FP16(X1, T2); // (X1-Z1.X2).Ys  |  (Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2  | - (Y1-Z1.Y2).Xs
+                if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) {
+                    b = new ctx.FP16(Y1);
+                    c = new ctx.FP16(0);
+                }
+                if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) {
+                    b = new ctx.FP16(0);
+                    c = new ctx.FP16(Y1); c.times_i();
+                }
+
+                A.add(B);
+            }
+
+            r.set(a, b, c);
+
+            return r;
+        },
+
+        /* Optimal R-ate pairing */
+        ate: function(P1, Q1) {
+            var x, n, n3, lv,
+                Qx, Qy, A, NP, r, nb, bt,
+                i;
+
+            x = new ctx.BIG(0);
+            x.rcopy(ctx.ROM_CURVE.CURVE_Bnx);
+            n = new ctx.BIG(x); //n.copy(x);
+
+            n3 = new ctx.BIG(n);
+            n3.pmul(3);
+            n3.norm();
+
+			var P=new ctx.ECP8(); P.copy(P1); P.affine();
+			var Q=new ctx.ECP(); Q.copy(Q1); Q.affine();
+
+            //  P.affine();
+            //  Q.affine();
+            Qx = new ctx.FP(Q.getx()); //Qx.copy(Q.getx());
+            Qy = new ctx.FP(Q.gety()); //Qy.copy(Q.gety());
+
+            A = new ctx.ECP8();
+            r = new ctx.FP48(1);
+
+            A.copy(P);
+			NP = new ctx.ECP8();
+			NP.copy(P);
+			NP.neg();
+
+
+            nb = n3.nbits();
+
+            for (i = nb - 2; i >= 1; i--) {
+                r.sqr();
+                lv = PAIR256.line(A, A, Qx, Qy);
+
+                r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+
+                bt=n3.bit(i)-n.bit(i);
+
+                if (bt == 1) {
+                    lv = PAIR256.line(A, P, Qx, Qy);
+                    r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+                }
+                if (bt == -1) {
+                    //P.neg();
+                    lv = PAIR256.line(A, NP, Qx, Qy);
+                    r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+                    //P.neg();
+                }
+            }
+
+            if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) {
+                r.conj();
+            }
+
+            return r;
+        },
+
+        /* Optimal R-ate double pairing e(P,Q).e(R,S) */
+        ate2: function(P1, Q1, R1, S1) {
+            var x, n, n3, lv,
+                Qx, Qy, Sx, Sy, A, B, NP, NR, r, nb, bt,
+                i;
+
+
+            x = new ctx.BIG(0);
+            x.rcopy(ctx.ROM_CURVE.CURVE_Bnx);
+
+            n = new ctx.BIG(x); //n.copy(x);
+            n3 = new ctx.BIG(n);
+            n3.pmul(3);
+            n3.norm();
+
+			var P=new ctx.ECP8(); P.copy(P1); P.affine();
+			var Q=new ctx.ECP(); Q.copy(Q1); Q.affine();
+			var R=new ctx.ECP8(); R.copy(R1); R.affine();
+			var S=new ctx.ECP(); S.copy(S1); S.affine();
+
+
+            Qx = new ctx.FP(Q.getx()); //Qx.copy(Q.getx());
+            Qy = new ctx.FP(Q.gety()); //Qy.copy(Q.gety());
+
+            Sx = new ctx.FP(S.getx()); //Sx.copy(S.getx());
+            Sy = new ctx.FP(S.gety()); //Sy.copy(S.gety());
+
+            A = new ctx.ECP8();
+            B = new ctx.ECP8();
+            r = new ctx.FP48(1);
+
+            A.copy(P);
+            B.copy(R);
+			NP = new ctx.ECP8();
+			NP.copy(P);
+			NP.neg();
+			NR = new ctx.ECP8();
+			NR.copy(R);
+			NR.neg();
+
+
+            nb = n3.nbits();
+
+            for (i = nb - 2; i >= 1; i--) {
+                r.sqr();
+                lv = PAIR256.line(A, A, Qx, Qy);
+                r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+                lv = PAIR256.line(B, B, Sx, Sy);
+                r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+
+                bt=n3.bit(i)-n.bit(i);
+
+                if (bt == 1) {
+                    lv = PAIR256.line(A, P, Qx, Qy);
+                    r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+                    lv = PAIR256.line(B, R, Sx, Sy);
+                    r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+                }
+                if (bt == -1) {
+                    //P.neg();
+                    lv = PAIR256.line(A, NP, Qx, Qy);
+                    r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+                    //P.neg();
+                    //R.neg();
+                    lv = PAIR256.line(B, NR, Sx, Sy);
+                    r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+                    //R.neg();
+                }
+            }
+
+            if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) {
+                r.conj();
+            }
+
+            return r;
+        },
+
+        /* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */
+        fexp: function(m) {
+            var fa, fb, f, x, r, lv,
+                t1,t2,t3,t7;
+
+            fa = new ctx.BIG(0);
+            fa.rcopy(ctx.ROM_FIELD.Fra);
+            fb = new ctx.BIG(0);
+            fb.rcopy(ctx.ROM_FIELD.Frb);
+            f = new ctx.FP2(fa, fb);
+            x = new ctx.BIG(0);
+            x.rcopy(ctx.ROM_CURVE.CURVE_Bnx);
+
+            r = new ctx.FP48(m); //r.copy(m);
+
+            /* Easy part of final exp */
+            lv = new ctx.FP48(r); //lv.copy(r);
+            lv.inverse();
+            r.conj();
+            r.mul(lv);
+            lv.copy(r);
+            r.frob(f,8);
+            r.mul(lv);
+
+            /* Hard part of final exp */
+            // Ghamman & Fouotsa Method
+            t7=new ctx.FP48(r); t7.usqr();
+            t1=t7.pow(x);
+
+            x.fshr(1);
+            t2=t1.pow(x);
+            x.fshl(1);
+
+            if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) {
+                t1.conj();
+            }
+
+            t3=new ctx.FP48(t1); t3.conj();
+            t2.mul(t3);
+            t2.mul(r);
+
+            r.mul(t7);
+
+            t1=t2.pow(x);
+            if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) {
+                t1.conj();
+            }
+            t3.copy(t1);
+            t3.frob(f,14);
+            r.mul(t3);
+            t1=t1.pow(x);
+            if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) {
+                t1.conj();
+            }
+
+            t3.copy(t1);
+            t3.frob(f,13);
+            r.mul(t3);
+            t1=t1.pow(x);
+            if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) {
+                t1.conj();
+            }
+
+            t3.copy(t1);
+            t3.frob(f,12);
+            r.mul(t3);
+            t1=t1.pow(x);
+            if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) {
+                t1.conj();
+            }
+
+            t3.copy(t1);
+            t3.frob(f,11);
+            r.mul(t3);
+            t1=t1.pow(x);
+            if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) {
+                t1.conj();
+            }
+
+            t3.copy(t1);
+            t3.frob(f,10);
+            r.mul(t3);
+            t1=t1.pow(x);
+            if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) {
+                t1.conj();
+            }
+
+            t3.copy(t1);
+            t3.frob(f,9);
+            r.mul(t3);
+            t1=t1.pow(x);
+            if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) {
+                t1.conj();
+            }
+
+            t3.copy(t1);
+            t3.frob(f,8);
+            r.mul(t3);
+            t1=t1.pow(x);
+            if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) {
+                t1.conj();
+            }
+
+            t3.copy(t2); t3.conj();
+            t1.mul(t3);
+            t3.copy(t1);
+            t3.frob(f,7);
+            r.mul(t3);
+            t1=t1.pow(x);
+            if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) {
+                t1.conj();
+            }
+
+            t3.copy(t1);
+            t3.frob(f,6);
+            r.mul(t3);
+            t1=t1.pow(x);
+            if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) {
+                t1.conj();
+            }
+
+            t3.copy(t1);
+            t3.frob(f,5);
+            r.mul(t3);
+            t1=t1.pow(x);
+            if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) {
+                t1.conj();
+            }
+
+            t3.copy(t1);
+            t3.frob(f,4);
+            r.mul(t3);
+            t1=t1.pow(x);
+            if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) {
+                t1.conj();
+            }
+
+            t3.copy(t1);
+            t3.frob(f,3);
+            r.mul(t3);
+            t1=t1.pow(x);
+            if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) {
+                t1.conj();
+            }
+
+            t3.copy(t1);
+            t3.frob(f,2);
+            r.mul(t3);
+            t1=t1.pow(x);
+            if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) {
+                t1.conj();
+            }
+
+            t3.copy(t1);
+            t3.frob(f,1);
+            r.mul(t3);
+            t1=t1.pow(x);
+            if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) {
+                t1.conj();
+            }
+
+            r.mul(t1);
+            t2.frob(f,15);
+            r.mul(t2);
+
+            r.reduce();
+            return r;
+        }
+    };
+
+    /* GLV method */
+    PAIR256.glv = function(e) {
+        var u = [],
+            q, x, x2;
+
+        // -(x^2).P = (Beta.x,y)
+        q = new ctx.BIG(0);
+        q.rcopy(ctx.ROM_CURVE.CURVE_Order);
+        x = new ctx.BIG(0);
+        x.rcopy(ctx.ROM_CURVE.CURVE_Bnx);
+        x2 = ctx.BIG.smul(x, x);
+        x = ctx.BIG.smul(x2,x2);
+        x2 = ctx.BIG.smul(x,x);
+        u[0] = new ctx.BIG(e);
+        u[0].mod(x2);
+        u[1] = new ctx.BIG(e);
+        u[1].div(x2);
+        u[1].rsub(q);
+
+        return u;
+    };
+
+    /* Galbraith & Scott Method */
+    PAIR256.gs = function(e) {
+        var u = [],
+            i, q, x, w;
+
+        x = new ctx.BIG(0);
+        x.rcopy(ctx.ROM_CURVE.CURVE_Bnx);
+        q = new ctx.BIG(0);
+        q.rcopy(ctx.ROM_CURVE.CURVE_Order);
+        w = new ctx.BIG(e);
+
+        for (i = 0; i < 15; i++) {
+            u[i] = new ctx.BIG(w);
+            u[i].mod(x);
+            w.div(x);
+        }
+
+        u[15] = new ctx.BIG(w);
+        if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) {
+            u[1].copy(ctx.BIG.modneg(u[1], q));
+            u[3].copy(ctx.BIG.modneg(u[3], q));
+            u[5].copy(ctx.BIG.modneg(u[5], q));
+            u[7].copy(ctx.BIG.modneg(u[7], q));
+            u[9].copy(ctx.BIG.modneg(u[9],q));
+            u[11].copy(ctx.BIG.modneg(u[11],q));
+            u[13].copy(ctx.BIG.modneg(u[13],q));
+            u[15].copy(ctx.BIG.modneg(u[15],q));
+
+        }
+
+        return u;
+    };
+
+    /* Multiply P by e in group G1 */
+    PAIR256.G1mul = function(P, e) {
+        var R, Q, q, bcru, cru, t, u, np, nn;
+
+        if (ctx.ROM_CURVE.USE_GLV) {
+            //P.affine();
+            R = new ctx.ECP();
+            R.copy(P);
+            Q = new ctx.ECP();
+            Q.copy(P); Q.affine();
+            q = new ctx.BIG(0);
+            q.rcopy(ctx.ROM_CURVE.CURVE_Order);
+            bcru = new ctx.BIG(0);
+            bcru.rcopy(ctx.ROM_CURVE.CURVE_Cru);
+            cru = new ctx.FP(bcru);
+            t = new ctx.BIG(0);
+            u = PAIR256.glv(e);
+
+            Q.getx().mul(cru);
+
+            np = u[0].nbits();
+            t.copy(ctx.BIG.modneg(u[0], q));
+            nn = t.nbits();
+            if (nn < np) {
+                u[0].copy(t);
+                R.neg();
+            }
+
+            np = u[1].nbits();
+            t.copy(ctx.BIG.modneg(u[1], q));
+            nn = t.nbits();
+            if (nn < np) {
+                u[1].copy(t);
+                Q.neg();
+            }
+            u[0].norm();
+            u[1].norm();
+            R = R.mul2(u[0], Q, u[1]);
+        } else {
+            R = P.mul(e);
+        }
+
+        return R;
+    };
+
+    /* Multiply P by e in group G2 */
+    PAIR256.G2mul = function(P, e) {
+        var R, Q, F, q, u, t, i, np, nn;
+
+        if (ctx.ROM_CURVE.USE_GS_G2) {
+            Q = [];
+            F = ctx.ECP8.frob_constants();
+
+            q = new ctx.BIG(0);
+            q.rcopy(ctx.ROM_CURVE.CURVE_Order);
+
+            u = PAIR256.gs(e);
+            t = new ctx.BIG(0);
+            //P.affine();
+            Q[0] = new ctx.ECP8();
+            Q[0].copy(P);
+
+            for (i = 1; i < 16; i++) {
+                Q[i] = new ctx.ECP8();
+                Q[i].copy(Q[i - 1]);
+                Q[i].frob(F,1);
+            }
+
+            for (i = 0; i < 16; i++) {
+                np = u[i].nbits();
+                t.copy(ctx.BIG.modneg(u[i], q));
+                nn = t.nbits();
+
+                if (nn < np) {
+                    u[i].copy(t);
+                    Q[i].neg();
+                }
+                u[i].norm();
+            }
+
+            R = ctx.ECP8.mul16(Q, u);
+        } else {
+            R = P.mul(e);
+        }
+        return R;
+    };
+
+    /* Note that this method requires a lot of RAM! Better to use compressed XTR method, see ctx.FP4.js */
+    PAIR256.GTpow = function(d, e) {
+        var r, g, fa, fb, f, q, t, u, i, np, nn;
+
+        if (ctx.ROM_CURVE.USE_GS_GT) {
+            g = [];
+            fa = new ctx.BIG(0);
+            fa.rcopy(ctx.ROM_FIELD.Fra);
+            fb = new ctx.BIG(0);
+            fb.rcopy(ctx.ROM_FIELD.Frb);
+            f = new ctx.FP2(fa, fb);
+            q = new ctx.BIG(0);
+            q.rcopy(ctx.ROM_CURVE.CURVE_Order);
+            t = new ctx.BIG(0);
+            u = PAIR256.gs(e);
+
+            g[0] = new ctx.FP48(d);
+
+            for (i = 1; i < 16; i++) {
+                g[i] = new ctx.FP48(0);
+                g[i].copy(g[i - 1]);
+                g[i].frob(f,1);
+            }
+
+            for (i = 0; i < 16; i++) {
+                np = u[i].nbits();
+                t.copy(ctx.BIG.modneg(u[i], q));
+                nn = t.nbits();
+
+                if (nn < np) {
+                    u[i].copy(t);
+                    g[i].conj();
+                }
+                u[i].norm();
+            }
+
+            r = ctx.FP48.pow16(g, u);
+        } else {
+            r = d.pow(e);
+        }
+
+        return r;
+    };
+
+    return PAIR256;
+};
diff --git a/version3/js/rand.js b/version3/js/rand.js
new file mode 100644
index 0000000..36b2869
--- /dev/null
+++ b/version3/js/rand.js
@@ -0,0 +1,184 @@
+/*
+    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.
+*/
+
+/*
+ *   Cryptographic strong random number generator
+ *
+ *   Unguessable seed -> SHA -> PRNG internal state -> SHA -> random numbers
+ *   Slow - but secure
+ *
+ *   See ftp://ftp.rsasecurity.com/pub/pdfs/bull-1.pdf for a justification
+ */
+
+/* Marsaglia & Zaman Random number generator constants */
+
+var RAND = function(ctx) {
+    "use strict";
+
+    var RAND = function() {
+        /* Cryptographically strong pseudo-random number generator */
+        this.ira = []; /* random number...   */
+        this.rndptr = 0; /* ...array & pointer */
+        this.borrow = 0;
+        this.pool_ptr = 0;
+        this.pool = []; /* random pool */
+        this.clean();
+    };
+
+    RAND.prototype = {
+        NK: 21,
+        NJ: 6,
+        NV: 8,
+
+        /* Terminate and clean up */
+        clean: function() {
+            var i;
+
+            for (i = 0; i < 32; i++) {
+                this.pool[i] = 0;
+            }
+
+            for (i = 0; i < this.NK; i++) {
+                this.ira[i] = 0;
+            }
+
+            this.rndptr = 0;
+            this.borrow = 0;
+            this.pool_ptr = 0;
+        },
+
+        sbrand: function() { /* Marsaglia & Zaman random number generator */
+            var i, k, pdiff, t;
+
+            this.rndptr++;
+            if (this.rndptr < this.NK) {
+                return this.ira[this.rndptr];
+            }
+
+            this.rndptr = 0;
+
+            for (i = 0, k = this.NK - this.NJ; i < this.NK; i++, k++) { /* calculate next NK values */
+                if (k == this.NK) {
+                    k = 0;
+                }
+
+                t = this.ira[k] >>> 0;
+                pdiff = (t - this.ira[i] - this.borrow) | 0;
+                pdiff >>>= 0; /* This is seriously weird shit. I got to do this to get a proper unsigned comparison... */
+
+                if (pdiff < t) {
+                    this.borrow = 0;
+                }
+
+                if (pdiff > t) {
+                    this.borrow = 1;
+                }
+
+                this.ira[i] = (pdiff | 0);
+            }
+
+            return this.ira[0];
+        },
+
+        sirand: function(seed) {
+            var m = 1,
+                i, inn, t;
+
+            this.borrow = 0;
+            this.rndptr = 0;
+            seed >>>= 0;
+            this.ira[0] ^= seed;
+
+            for (i = 1; i < this.NK; i++) { /* fill initialisation vector */
+                inn = (this.NV * i) % this.NK;
+                this.ira[inn] ^= m; /* note XOR */
+                t = m;
+                m = (seed - m) | 0;
+                seed = t;
+            }
+
+            /* "warm-up" & stir the generator */
+            for (i = 0; i < 10000; i++) {
+                this.sbrand();
+            }
+        },
+
+        fill_pool: function() {
+            var sh = new ctx.HASH256(),
+                i;
+
+            for (i = 0; i < 128; i++) {
+                sh.process(this.sbrand());
+            }
+
+            this.pool = sh.hash();
+            this.pool_ptr = 0;
+        },
+
+        /* Initialize RNG with some real entropy from some external source */
+        seed: function(rawlen, raw) { /* initialise from at least 128 byte string of raw random entropy */
+            var sh = new ctx.HASH256(),
+                digest = [],
+                b = [],
+                i;
+
+            this.pool_ptr = 0;
+
+            for (i = 0; i < this.NK; i++) {
+                this.ira[i] = 0;
+            }
+
+            if (rawlen > 0) {
+                for (i = 0; i < rawlen; i++) {
+                    sh.process(raw[i]);
+                }
+
+                digest = sh.hash();
+
+                /* initialise PRNG from distilled randomness */
+                for (i = 0; i < 8; i++) {
+                    b[0] = digest[4 * i];
+                    b[1] = digest[4 * i + 1];
+                    b[2] = digest[4 * i + 2];
+                    b[3] = digest[4 * i + 3];
+                    this.sirand(RAND.pack(b));
+                }
+            }
+
+            this.fill_pool();
+        },
+
+        /* get random byte */
+        getByte: function() {
+            var r = this.pool[this.pool_ptr++];
+
+            if (this.pool_ptr >= 32) {
+                this.fill_pool();
+            }
+
+            return (r & 0xff);
+        }
+    };
+
+    RAND.pack = function(b) { /* pack 4 bytes into a 32-bit Word */
+        return (((b[3]) & 0xff) << 24) | ((b[2] & 0xff) << 16) | ((b[1] & 0xff) << 8) | (b[0] & 0xff);
+    };
+
+    return RAND;
+};
diff --git a/version3/js/readme.txt b/version3/js/readme.txt
new file mode 100644
index 0000000..12ee31e
--- /dev/null
+++ b/version3/js/readme.txt
@@ -0,0 +1,48 @@
+Suppose you want to implement ECDH with NIST256 elliptic curve. First you need to initialize the context:
+
+```
+var ctx = new CTX("NIST256");
+```
+then you can call the functions as follows:
+```
+ctx.ECDH.KEY_PAIR_GENERATE(...);
+ctx.ECDH.ECPSVDP_DH(...);
+```
+If you need to use more than one elliptic curve in the same script you only need to initialize two different contexts, for example
+```
+var ctx1 = new CTX("NIST256");
+var ctx2 = new CTX("C25519");
+```
+The following is the list of all elliptic curves supported by MCJS
+```
+['ED25519', 'C25519', 'C41417', 'GOLDILOCKS', 'NIST256', 'NIST384','NIST521', 'BRAINPOOL', 'ANSSI', 'HIFIVE', 'NUMS256W', 'SECP256K1'
+'NUMS256E', 'NUMS384W', 'NUMS384E', 'NUMS512W', 'NUMS512E', 'BN254', 'BN254CX', 'BLS383', 'BLS381', 'FP256BN', 'FP512BN', 'BLS461', 'BLS24', 'BLS48'];
+```
+
+This library supports also RSA encryption/decryption and RSA signature. The following is a quick example on how to use RSA. First initialize the context
+```
+var ctx = new CTX("RSA2048");
+```
+then you can call the RSA functions as follows:
+```
+ctx.RSA.ENCRYPT(...);
+ctx.RSA.DECRYPT(...);
+```
+The following is the list of all the RSA security level supported by *MCJS*
+```
+['RSA2048','RSA3072','RSA4096'];
+```
+
+MCJS supports also SHA256, SHA384, SHA512, AES-GCM encryption and Marsaglia & Zaman random number generator. Those functions are contained in every context initialized with RSA or with an elliptic curve. If you want to create a context supporting only those general functions then initialize it with no parameter as follows:
+```
+var ctx = new CTX();
+```
+
+--------------------------------------
+
+
+To see some running examples, load TestALL.html or BenchtestALL.html into your favourite browser.
+You might have to wait a few seconds for the benchmarking scripts to complete.
+
+For TestALL.html the correct PIN number is 1234.
+
diff --git a/version3/js/rom_curve.js b/version3/js/rom_curve.js
new file mode 100644
index 0000000..9ca24fa
--- /dev/null
+++ b/version3/js/rom_curve.js
@@ -0,0 +1,1127 @@
+/*
+    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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+var ROM_CURVE_ANSSI,
+    ROM_CURVE_BLS383,
+    ROM_CURVE_BLS24,
+    ROM_CURVE_BLS48,
+    ROM_CURVE_BLS381,
+    ROM_CURVE_BLS461,
+    ROM_CURVE_FP256BN,
+    ROM_CURVE_FP512BN,
+    ROM_CURVE_BN254,
+    ROM_CURVE_BN254CX,
+    ROM_CURVE_BRAINPOOL,
+    ROM_CURVE_C25519,
+    ROM_CURVE_C41417,
+    ROM_CURVE_ED25519,
+    ROM_CURVE_GOLDILOCKS,
+    ROM_CURVE_HIFIVE,
+    ROM_CURVE_NIST256,
+    ROM_CURVE_NIST384,
+    ROM_CURVE_NIST521,
+    ROM_CURVE_NUMS256E,
+    ROM_CURVE_NUMS256W,
+    ROM_CURVE_NUMS384E,
+    ROM_CURVE_NUMS384W,
+    ROM_CURVE_NUMS512E,
+    ROM_CURVE_NUMS512W,
+    ROM_CURVE_SECP256K1;
+
+ROM_CURVE_ANSSI = function() {
+
+    var ROM_CURVE_ANSSI = {
+
+        // ANSSI curve
+
+        Curve_Cof_I: 1,
+        CURVE_A: -3,
+        CURVE_B_I: 0,
+        CURVE_B: [0x7BB73F, 0xED967B, 0x803075, 0xE4B1A1, 0xEC0C9A, 0xC00FDF, 0x754A44, 0xD4ABA, 0x28A930, 0x3FCA54, 0xEE35],
+        CURVE_Order: [0xD655E1, 0xD459C6, 0x941FFD, 0x40D2BF, 0xDC67E1, 0x435B53, 0xE8CE42, 0x10126D, 0x3AD58F, 0x178C0B, 0xF1FD],
+        CURVE_Gx: [0x8F5CFF, 0x7A2DD9, 0x164C9, 0xAF98B7, 0x27D2DC, 0x23958C, 0x4749D4, 0x31183D, 0xC139EB, 0xD4C356, 0xB6B3],
+        CURVE_Gy: [0x62CFB, 0x5A1554, 0xE18311, 0xE8E4C9, 0x1C307, 0xEF8C27, 0xF0F3EC, 0x1F9271, 0xB20491, 0xE0F7C8, 0x6142],
+
+    };
+    return ROM_CURVE_ANSSI;
+};
+
+ROM_CURVE_BLS383 = function() {
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    var ROM_CURVE_BLS383 = {
+
+        // BLS383 Curve
+        // Base Bits= 23
+
+        CURVE_Cof_I: 0,
+        CURVE_A: 0,
+        CURVE_B_I: 15,
+        CURVE_B: [0xF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        CURVE_Order: [0x3C0001, 0x33D7FD, 0x5CEC82, 0x9069C, 0x5F095A, 0x703BC0, 0x5A62C, 0x2200E4, 0x3809C0, 0x1801, 0x8006, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0],
+        CURVE_Gx: [0x734573, 0x6E7210, 0x11E311, 0x1FA3B8, 0x5DBF08, 0x688B8A, 0x12BC78, 0x43DD6C, 0x742C2F, 0x6D6103, 0x4C767D, 0x6D8287, 0x74052D, 0x1C706B, 0x5E7B39, 0x5D2ADC, 0x41FC],
+        CURVE_Gy: [0x3F224, 0x2CBD00, 0x7484B4, 0x43FCC7, 0x7D49EC, 0x25BBCA, 0x2B7AD3, 0x29854A, 0x449107, 0xCD76C, 0x7436B7, 0x6236CC, 0x1CDC31, 0x495D, 0x33ECC0, 0xB393A, 0x68F],
+
+        CURVE_Bnx: [0x1200, 0x2, 0x40020, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        CURVE_Cof: [0x169EAB, 0x2AC2AA, 0x7ED541, 0x555DF, 0x2AAC00, 0xAAB, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        CURVE_Cru: [0x2AC2A9, 0x4EA05D, 0x4B730D, 0x16FB2E, 0x5F681A, 0x683784, 0xD37A8, 0x2917A5, 0x715CE2, 0x69B7BA, 0x15114, 0x4A43A3, 0x34406E, 0x1408B5, 0x2ADBAD, 0x2B4AB2, 0x5565],
+        CURVE_Pxa: [0x7F2D86, 0x676C5A, 0x7850F2, 0x4AE8E9, 0x7DAB67, 0x65DD03, 0x3D5895, 0x3F8E48, 0x725BD4, 0x10A5AA, 0xC9407, 0xF3A32, 0x967CB, 0x180F32, 0x7B00FA, 0x691203, 0x634],
+        CURVE_Pxb: [0x52DE15, 0x483D88, 0x37BF67, 0x2BFF30, 0x4AB28D, 0x3AEB6A, 0x23A4B5, 0x6CC5D4, 0x4C89DF, 0x5B3A0B, 0x13D263, 0x1B0EE9, 0x717288, 0x5E6F4E, 0x592E, 0x3C0030, 0x300D],
+        CURVE_Pya: [0x8CB41, 0x617728, 0x5971A3, 0x106B0C, 0x1EDE4F, 0x5CEB69, 0x2A44E8, 0x4BC1D6, 0x1B3E68, 0x2CE793, 0x3A643B, 0x31A3DB, 0x573FE, 0x79293B, 0x4894D1, 0x167C9E, 0x3379],
+        CURVE_Pyb: [0x479093, 0xC86FE, 0x18EB61, 0x731124, 0x43CB0D, 0x131602, 0x127DEF, 0x78597A, 0x7A8F7A, 0x8D67D, 0x73835, 0x53D700, 0x3A7D15, 0x649DCF, 0x33631A, 0x123EE9, 0x20E5],
+        CURVE_W: [
+            [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+            [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+        ],
+        CURVE_SB: [
+            [
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+            ],
+            [
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+            ]
+        ],
+        CURVE_WB: [
+            [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+            [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+            [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+            [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+        ],
+        CURVE_BB: [
+            [
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+            ],
+            [
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+            ],
+            [
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+            ],
+            [
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+            ]
+        ],
+
+        USE_GLV: true,
+        USE_GS_G2: true,
+        USE_GS_GT: true,
+        GT_STRONG: true,
+
+        //debug: false,
+
+    };
+
+    return ROM_CURVE_BLS383;
+};
+
+
+ROM_CURVE_BLS24 = function() {
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    var ROM_CURVE_BLS24 = {
+
+        // BLS24 Curve
+        // Base Bits= 23
+        CURVE_Cof_I: 0,
+        CURVE_A: 0,
+        CURVE_B_I: 19,
+        CURVE_B: [0x13, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        CURVE_Order: [0x1, 0x11FFE0, 0x464068, 0x1FFAA8, 0x71E703, 0x645BB5, 0x379FB8, 0x689D35, 0x49D0CE, 0x49091F, 0x4A7308, 0x286C0B, 0x3B44A0, 0x60B731, 0x6807C3, 0x8002, 0x10010, 0x0, 0x0, 0x0, 0x0],
+        CURVE_Gx: [0x63CCD4, 0x41EBD7, 0x15919D, 0x576CFA, 0x1EFE2D, 0x743F98, 0xFC23A, 0x409A3C, 0x595AF8, 0x6F8DF1, 0x38B611, 0x65468D, 0x7E4BFD, 0x6B0D9D, 0x7641D, 0x2ECCDE, 0xB7FEA, 0x5BD3C3, 0x2BE521, 0x71A0BE, 0x1AB2B],
+        CURVE_Gy: [0x1E5245, 0x4B95A4, 0x5B132E, 0x462AEF, 0x36D660, 0x672E8D, 0x7B4A53, 0x79E459, 0x24920F, 0x4828B0, 0x58F969, 0x1D527E, 0x4E00F6, 0x457EF3, 0x66924A, 0x294FFB, 0x66A7A4, 0x70C394, 0x4F91DE, 0x386362, 0x47FCB],
+
+        CURVE_Bnx: [0x11FF80, 0x400, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        CURVE_Cof: [0x7415AB, 0x7F7FF3, 0x5FFF07, 0x2AB555, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        CURVE_Cru: [0x5794A9, 0x4E28DB, 0x690EF0, 0x1C5799, 0x63A309, 0x447BB8, 0x4485D4, 0x36FDD8, 0x7BB423, 0xE24B9, 0x5E7398, 0x11AC71, 0x806E0, 0x18DD64, 0x5DF5A0, 0x4307F, 0x314C20, 0x4D1C8, 0x2F16A2, 0x3C01E, 0x555C0],
+        CURVE_Pxaa: [0x624678, 0x26A6E9, 0x22F8A, 0x212C12, 0x60C343, 0x3DF8D3, 0x5D9733, 0x6BFC87, 0x2D2888, 0x758675, 0x259D1C, 0x7E922C, 0x4BAB37, 0x11DAAB, 0x6214A4, 0x758A55, 0x786671, 0x72B190, 0x32581D, 0x729D1F, 0x959D],
+        CURVE_Pxab: [0x3099B8, 0x3D75FF, 0x40E1FE, 0x9523, 0x63775A, 0x78470A, 0x5746C7, 0x7CF1B5, 0x26A730, 0x14FE14, 0x76CA97, 0x61C7C2, 0x669261, 0x6A7C2F, 0x3E5DA9, 0x5F2D68, 0x2D39D1, 0x4A3C98, 0x4CF7F1, 0x68418B, 0x3B0DE],
+        CURVE_Pxba: [0x2D15D3, 0x1BCE23, 0x5BB687, 0x46FB70, 0x185317, 0x47C134, 0x2FD0FA, 0x3597B2, 0x56DE56, 0x165B19, 0x1D3F6E, 0x10E136, 0x76B1EF, 0x1913C7, 0x4011EF, 0x1F994F, 0x3FE210, 0x545186, 0x41EBCA, 0x7D6A72, 0x3EC27],
+        CURVE_Pxbb: [0x60F480, 0x650EBD, 0x2E31EA, 0x21EB62, 0x14556E, 0x1C3973, 0x48B7E0, 0xFFEFD, 0x50122F, 0x55EE1F, 0x263BD7, 0x2ED92B, 0x1BA3AD, 0x39C35E, 0x2DD201, 0x17232E, 0x1DA7CE, 0x4CB0AA, 0x1E67DF, 0x46DE50, 0xA5B3],
+        CURVE_Pyaa: [0x781AA0, 0x132628, 0x2AC619, 0x181DB8, 0x3609DA, 0x3F8897, 0x4A9851, 0x189252, 0x4C42A, 0x768C5C, 0x66B9A2, 0x1C1D70, 0x4FCADC, 0x69ED7C, 0x7D286C, 0xD685, 0x198F9, 0x459DA0, 0x30250D, 0x1AEB9B, 0x5057F],
+        CURVE_Pyab: [0x2E08FA, 0x58AFDD, 0x5AB6EF, 0x5D52FC, 0x78774, 0x348594, 0x32BC26, 0x23C32, 0x3BCCF7, 0xB913F, 0x3E1549, 0x5B907F, 0x77B3E6, 0x22C6ED, 0x7865FE, 0x3DAEFB, 0x60F558, 0x702D7A, 0x3A258D, 0x24B30F, 0x2CE2B],
+        CURVE_Pyba: [0x70CC41, 0x4ED4B, 0x7D5CC, 0x2A9855, 0x7F8932, 0x5F1428, 0x7361E6, 0x14406C, 0x68A9FE, 0x21DCA7, 0x4DC54E, 0x10783E, 0x71F3A4, 0x3AA336, 0x6C5305, 0x1E5ADC, 0x1A39DD, 0x7C73F0, 0x18C69A, 0x2331F7, 0x18070],
+        CURVE_Pybb: [0x5C1CAE, 0x65CCA2, 0x2373C6, 0x2AD84C, 0x2D40D3, 0x714EEE, 0x10FF70, 0x3AE561, 0x136B6, 0x3EBA67, 0x75CBF3, 0x327450, 0x161AC1, 0x5CB9A1, 0x2C42EE, 0x48BB8F, 0x56D046, 0x725081, 0x77B22D, 0x2756CD, 0x499D1],
+        CURVE_W: [
+            [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+            [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+        ],
+        CURVE_SB: [
+            [
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+            ],
+            [
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+            ]
+        ],
+        CURVE_WB: [
+            [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+            [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+            [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+            [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+        ],
+        CURVE_BB: [
+            [
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+            ],
+            [
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+            ],
+            [
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+            ],
+            [
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+            ]
+        ],
+
+        USE_GLV: true,
+        USE_GS_G2: true,
+        USE_GS_GT: true,
+        GT_STRONG: true,
+
+        //debug: false,
+    };
+
+    return ROM_CURVE_BLS24;
+};
+
+ROM_CURVE_BLS48 = function() {
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    var ROM_CURVE_BLS48 = {
+
+        // BLS48 Curve
+        // Base Bits= 23
+        CURVE_Cof_I: 0,
+        CURVE_A: 0,
+        CURVE_B_I: 17,
+        CURVE_B: [0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        CURVE_Order: [0x1, 0x7E0000, 0x421BFF, 0x714ED3, 0x455409, 0x53842, 0x7AC588, 0x7E8A68, 0xAD8C1, 0x184DA5, 0x7FB5E2, 0x5E936, 0x5EF479, 0x12B881, 0x46FE3F, 0x32FD85, 0x2973C4, 0x3D260D, 0x318DF1, 0x88D57, 0x3F73EA, 0x1887, 0x0, 0x0, 0x0],
+        CURVE_Gx: [0x571D33, 0x5A5ECB, 0x3FCA1, 0x7F196F, 0x580554, 0x23DC17, 0x591DC, 0x1987F8, 0x7CA7F6, 0x345E03, 0x203D9A, 0x1734D, 0x444E07, 0x5602B2, 0x5003E, 0x5961D5, 0x30D242, 0x336BC2, 0x79241, 0xE0499, 0x7EDD74, 0x3B712A, 0x215D65, 0x544F49, 0x9],
+        CURVE_Gy: [0x6ED83A, 0x367FD4, 0x33DA69, 0x254538, 0x5C4B95, 0x2B0CEF, 0x7AA39A, 0x47D9C8, 0x677B5F, 0x4F9E3D, 0x6DC8A6, 0x71C0C7, 0x4B44E2, 0x4AA8F1, 0x4C3099, 0x3071E3, 0x240862, 0x1B9CCF, 0x579C4, 0x4D1997, 0x3349DA, 0x3F5C56, 0x5318B1, 0x56C684, 0x0],
+
+        CURVE_Bnx: [0x640020, 0xFB, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        CURVE_Cof: [0x12ABEB, 0x221EFE, 0x528B, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        CURVE_Cru: [0x3BA429, 0x1CFCD9, 0x1600D9, 0x49A7BA, 0x4E30A2, 0x101275, 0xF1A0C, 0x6D146E, 0x42B839, 0x118594, 0x4EF0B4, 0x55CDB, 0x67127B, 0x3D8D31, 0x319233, 0x2571C, 0x1AEEFF, 0x72BC73, 0x91318, 0x1911E0, 0x279F78, 0x646407, 0x73DF3B, 0x68BEC1, 0xF],
+        CURVE_Pxaaa: [0x23CE4A, 0x5D1D12, 0x74AA34, 0x695C09, 0x3D7102, 0x274419, 0x76284C, 0x69F0B2, 0x4637C1, 0x5FE3FE, 0x242E62, 0x3F853E, 0x4DD2B3, 0x672BDE, 0x6ED92, 0x2B9BAD, 0x6C4ABF, 0x393882, 0x32EE21, 0x2EF3A1, 0x59487E, 0x92F4B, 0x26870, 0x32BC6C, 0xE],
+        CURVE_Pxaab: [0xA1BE1, 0x1B8B58, 0x7DC9C7, 0x3BEB, 0x28FE3B, 0x72E58B, 0x51E10C, 0x31856A, 0x389247, 0x15B9FD, 0x2847EA, 0x2E35A0, 0x9B0E7, 0x7F92CE, 0x6960C8, 0xC5821, 0x48632D, 0xC919C, 0x3C27F4, 0x2A934D, 0x348B6E, 0x2F6B1B, 0x179D2A, 0x4A1009, 0x2],
+        CURVE_Pxaba: [0xC5DC4, 0x6498EE, 0x4B68E9, 0x6ED677, 0x2964AD, 0x7D8E6D, 0x4D0966, 0x550884, 0x1926AC, 0x47162D, 0x633555, 0x265962, 0x6402B8, 0x48F745, 0x68195F, 0x198B3A, 0x117CE2, 0x5E9EFB, 0x729335, 0x471F6E, 0x3689BA, 0x3BB4F1, 0x3DDB5C, 0x297F7C, 0xB],
+        CURVE_Pxabb: [0x64B740, 0x52CD34, 0x578358, 0x464902, 0x11FD49, 0x475BA2, 0x5C150C, 0x436206, 0x335E27, 0x7CFA66, 0x53BA9F, 0x39E20F, 0x41E3C, 0x30CB43, 0x5E7D7A, 0x4869DA, 0x6B405, 0x57B683, 0x77306A, 0x3E774A, 0x63B1A6, 0x4BE47E, 0x764B7F, 0x1C2054, 0x9],
+        CURVE_Pxbaa: [0x71E01F, 0x18C2E5, 0x26EC, 0x1A5853, 0x4311CD, 0x430F11, 0x43E8E4, 0x20204C, 0x35AB89, 0x775C07, 0x43202C, 0x442943, 0x1E3472, 0xB1BEA, 0x14841D, 0x56A6A1, 0x4E27C3, 0x6AC397, 0x111E6A, 0x453F3C, 0x449D32, 0x6288F9, 0x7D0633, 0x6F0F7B, 0xD],
+        CURVE_Pxbab: [0x37383D, 0x70470C, 0x66C28, 0x7CCC3F, 0x220253, 0x27A425, 0x147B57, 0x64A9AE, 0x7A0147, 0x61CE2B, 0x7620BF, 0x1CEB9B, 0x3F1646, 0x5546DC, 0x12AEC8, 0x2A6D46, 0x38885E, 0xA7FD0, 0x3A2974, 0x7872F1, 0x4F91FB, 0x2ADE02, 0x632141, 0x16D9D3, 0x8],
+        CURVE_Pxbba: [0x11939C, 0x7B67AE, 0x6BA5A0, 0x34D20C, 0x1BE51D, 0x65ED81, 0x6D5CB3, 0x6465E6, 0x40B384, 0x146E44, 0x54F471, 0x119F79, 0x11A9B3, 0x5235B8, 0x342402, 0x6B0380, 0x51A403, 0x22E30F, 0x1F23BA, 0x468CDF, 0x5A9CCF, 0x77C486, 0x613650, 0x411539, 0xA],
+        CURVE_Pxbbb: [0x6F4899, 0x2150A, 0x750CB5, 0x4952B2, 0x1C51EB, 0x179378, 0x295E64, 0x5B5457, 0x47A789, 0x1403F8, 0x62578C, 0x2F5D38, 0x7FE82C, 0x6CFF62, 0x32162, 0x3ACBE5, 0x1E3000, 0x668F, 0x426A4B, 0x4F46ED, 0x57A328, 0x62ACF0, 0xF705B, 0x7BAA3C, 0xD],
+        CURVE_Pyaaa: [0x137844, 0x2F9F68, 0x4DDB82, 0x4FFA79, 0x44EC64, 0x6D10A3, 0x1BEAF1, 0x4B2F5C, 0xB8A71, 0x20AB1C, 0x225B80, 0x663E7C, 0x673C10, 0x7E8EA9, 0x2FC388, 0x66E9CC, 0x202F56, 0x39587C, 0x343E8C, 0x52C8BF, 0x6190B, 0x11FB0E, 0x6124D5, 0x337685, 0x7],
+        CURVE_Pyaab: [0x483190, 0x6491DB, 0x424978, 0x23544C, 0x2EAAF4, 0x31A65, 0x48EEB1, 0x7EEB0E, 0x91F2F, 0x2D992C, 0xF07C, 0x4AE56F, 0x688ED2, 0x62E3A0, 0x284758, 0x15CF7, 0x7E205E, 0x9FA40, 0x24EA65, 0xCE87C, 0x7A1C42, 0x1C4D1D, 0x4F76AA, 0x3CE59C, 0x2],
+        CURVE_Pyaba: [0x185C0D, 0x3FA083, 0xFA771, 0x50C8EE, 0xD404D, 0x759D3, 0x697D52, 0x6598BC, 0x685C7C, 0x612D58, 0x160D06, 0x2201F3, 0x5C797C, 0x10C374, 0xE7E1C, 0x52FA00, 0x1F60B0, 0x42B24, 0x7635E0, 0xDD262, 0x140D61, 0x26A7E6, 0x595FBC, 0x22CDE4, 0xD],
+        CURVE_Pyabb: [0x1D42F8, 0x41502B, 0x5D7DBF, 0x88B12, 0x243AFD, 0x3CFE57, 0x4EC3FA, 0x2FB013, 0x7C3CFF, 0x1D3717, 0x79401A, 0x33C434, 0x635F37, 0x29E4F6, 0x2CA2DB, 0x7A8EF0, 0x3FD902, 0x3309C9, 0x1F125B, 0x3FF0C9, 0x7310, 0x3137DB, 0x280E0B, 0x70755, 0xA],
+        CURVE_Pybaa: [0x38039F, 0x25673E, 0x184354, 0x3E78D1, 0xEE895, 0x1279F, 0x285016, 0x445C85, 0x4BFE85, 0x7F8597, 0x2AEDD5, 0x2E62F9, 0x32710C, 0x4F5B51, 0x59016C, 0x6178C7, 0x6E268E, 0x2D39EF, 0x2C36B6, 0x717762, 0x1D1ABC, 0x323714, 0x7C7BB9, 0x582324, 0x2],
+        CURVE_Pybab: [0x5F7865, 0x40DE52, 0x20E9A7, 0x7439D3, 0x3F0756, 0x595BAF, 0x7CFC76, 0x287B18, 0x56074E, 0x186679, 0x416EC0, 0x1DC812, 0x127FBE, 0x18D9B5, 0x3C4A9D, 0x1C2BB4, 0x135CA4, 0x7A40AC, 0x739984, 0x6F008C, 0x7180EA, 0x58AF6D, 0x5B4B02, 0x9194C, 0x3],
+        CURVE_Pybba: [0x4C1979, 0x753ECF, 0x6F0760, 0x3BB13C, 0x4AAF9C, 0x6BFB52, 0x470858, 0x41323D, 0x5401D8, 0x494404, 0x5CCF5C, 0xBCF06, 0x7E6ECF, 0x5A9C20, 0xD2DFF, 0x64FF44, 0x31645B, 0x4EE883, 0x4E22EC, 0x112445, 0x486C5C, 0x5C8211, 0x67DA66, 0x400692, 0xC],
+        CURVE_Pybbb: [0x49F25B, 0x12AC5F, 0x5D33F2, 0x35D356, 0x2C4F80, 0x3A4C9E, 0x3C5A72, 0x426C74, 0x5DAC92, 0x52C146, 0x61366B, 0x6CDE77, 0x5A9E8F, 0x6DFF70, 0x6D20E3, 0x5A60E6, 0x33DF1A, 0x2AFA7, 0x390F0, 0x6320A2, 0x3F5493, 0x1CC373, 0x174990, 0x7B09B, 0xA],
+        CURVE_W: [
+            [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+            [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+        ],
+        CURVE_SB: [
+            [
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+            ],
+            [
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+            ]
+        ],
+        CURVE_WB: [
+            [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+            [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+            [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+            [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+        ],
+        CURVE_BB: [
+            [
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+            ],
+            [
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+            ],
+            [
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+            ],
+            [
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+            ]
+        ],
+
+        USE_GLV: true,
+        USE_GS_G2: true,
+        USE_GS_GT: true,
+        GT_STRONG: true,
+
+        //debug: false,
+
+
+    };
+
+    return ROM_CURVE_BLS48;
+};
+
+
+ROM_CURVE_BLS381 = function() {
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    var ROM_CURVE_BLS381 = {
+
+        // BLS381 Curve
+        // Base Bits= 23
+
+        CURVE_Cof_I: 0,
+        CURVE_A: 0,
+        CURVE_B_I: 4,
+        CURVE_B: [0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        CURVE_Order: [0x1, 0x7FFE00, 0x7BFFFF, 0x7FF2DF, 0x5A402F, 0xAA77, 0x26876, 0x1CEC04, 0x7D4833, 0x26533A, 0x4FB69D, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0],
+        CURVE_Gx: [0x22C6BB, 0x6015B6, 0x3FECEB, 0x4BD0D7, 0x5E83FF, 0xB0D8A, 0x45C6EB, 0x271D1F, 0x3905A1, 0x1F2EE9, 0xDA231, 0x4D607E, 0x38C4FA, 0x4D2AC, 0x65F5E5, 0x69D398, 0x17F1],
+        CURVE_Gy: [0x45E7E1, 0x46528D, 0x1032A8, 0x144457, 0x4C744A, 0x7DBA07, 0x4B012C, 0x6D8C65, 0xAF600, 0x2BABA0, 0x73D782, 0x6C5727, 0xED741, 0x3413C6, 0x6AA83C, 0x7A40F1, 0x8B3],
+
+        CURVE_Bnx: [0x10000, 0x0, 0x34804, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        CURVE_Cof: [0xAAAB, 0x555600, 0x5A3002, 0x2AAF0A, 0x48C005, 0x72D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        CURVE_Cru: [0x7EFFFE, 0x7FFFFF, 0x8B807, 0x105000, 0x7D8136, 0x511BC2, 0x79BE25, 0x59D49D, 0x77EADD, 0xED41E, 0x69A718, 0x36728D, 0x72FDF7, 0xBE32C, 0x0, 0x0, 0x0],
+
+        CURVE_Pxa: [0x21BDB8, 0x2D9182, 0x3F5201, 0x402DDF, 0x40326A, 0x2EE175, 0x1EB8F4, 0x2885B2, 0x3B02B4, 0x29F480, 0x1B91EB, 0x28828E, 0x5272DC, 0x24C100, 0x23C2A4, 0x515978, 0x24A],
+        CURVE_Pxb: [0x42B7E, 0x7A0ABA, 0x5F96B1, 0x1CA2EA, 0x4F1121, 0x92669, 0x771FD4, 0x6D30DD, 0x361AB5, 0x213241, 0x65AF43, 0x3A7B2A, 0x3A0882, 0xFB59A, 0x1C67D8, 0x15B029, 0x13E0],
+        CURVE_Pya: [0x382801, 0x290C11, 0x27864D, 0x5D6514, 0x2C9CC3, 0x259247, 0x545834, 0x214D34, 0x53A76D, 0x55197B, 0x37F66E, 0x71A8D5, 0x5C6DA2, 0x319939, 0x1F5B84, 0x6A93B9, 0xCE5],
+        CURVE_Pyb: [0x5F79BE, 0xEBFE0, 0x6AAA4, 0x6760ED, 0x70D275, 0x3567E6, 0x55CBA6, 0x3A4955, 0x63AF26, 0x7D0B4E, 0x2CF8A1, 0x145CCE, 0x2B02BC, 0x6559A, 0x29CD33, 0x625017, 0x606],
+        CURVE_W: [
+            [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+            [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+        ],
+        CURVE_SB: [
+            [
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+            ],
+            [
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+            ]
+        ],
+        CURVE_WB: [
+            [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+            [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+            [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+            [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+        ],
+        CURVE_BB: [
+            [
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+            ],
+            [
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+            ],
+            [
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+            ],
+            [
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+            ]
+        ],
+
+        USE_GLV: true,
+        USE_GS_G2: true,
+        USE_GS_GT: true,
+        GT_STRONG: false,
+
+        //debug: false,
+
+    };
+
+    return ROM_CURVE_BLS381;
+};
+
+
+ROM_CURVE_BLS461 = function() {
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    var ROM_CURVE_BLS461 = {
+
+        // BLS461 Curve
+        // Base Bits= 23
+
+        Curve_Cof_I : 0,
+        CURVE_A: 0,
+        CURVE_B_I: 9,
+        CURVE_B: [0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        CURVE_Order: [0x1, 0x0, 0x700000, 0x7F7FFF, 0x7FEFF, 0x22000, 0x7F2000, 0x7E00BF, 0xE801, 0x40BFA0, 0x5FF, 0x7FE00C, 0x7FFF7F, 0x1FF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        CURVE_Gx: [0x5EE93D, 0x4D515, 0x504534, 0x773A5B, 0x2D9C00, 0x6358FE, 0x6606D4, 0x4114E1, 0x4DC921, 0x21A6AC, 0x282599, 0x7BE149, 0x436166, 0x45632E, 0x1A2FA4, 0x38967B, 0xC8132, 0x476E74, 0x3A66D1, 0x56873A, 0x0],
+        CURVE_Gy: [0x51D465, 0x462AF5, 0x51C3DD, 0x64627F, 0x517884, 0x71A42B, 0x6799A, 0x2CE854, 0x245F49, 0x15CB86, 0x2E1244, 0x45FD20, 0x16EECB, 0x3F197D, 0x3322FE, 0x1793BD, 0x5F1C3F, 0x3ED192, 0x452CC1, 0x3BDE6D, 0x0],
+
+        CURVE_Bnx: [0x0, 0x7FFC00, 0x7FFFEF, 0xFF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        CURVE_Cof: [0x2AAAAB, 0x7FFD55, 0x5AAA9F, 0x5580AA, 0x7D55AA, 0x2A9FFF, 0x5555, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        CURVE_Cru: [0x7FFFFE, 0x3FF, 0x10, 0x7FFF00, 0x7FFE7F, 0x61FFED, 0x311F, 0x630239, 0x6DB7BC, 0x622AF2, 0x73D1DD, 0x43AA19, 0x3F0E89, 0xA04C2, 0x581400, 0x7F5FFF, 0x1FFFF, 0x0, 0x0, 0x0, 0x0],
+        CURVE_Pxa: [0x50A37C, 0x20630D, 0x31196D, 0x173AEE, 0x1C2E49, 0x2D0F15, 0x7E467, 0x7AB270, 0x74FF92, 0x610DB6, 0x19A00F, 0x36AC0D, 0x6D78D4, 0x78520F, 0x224BE5, 0x1E1386, 0x767945, 0x4A1535, 0x4E281A, 0x662A0, 0x1],
+        CURVE_Pxb: [0x41C0AD, 0x395185, 0x37A7E1, 0x6212E5, 0x16CD66, 0x4512C1, 0x4A546, 0x200D63, 0x3EBEE2, 0x7AA535, 0x7D96C5, 0x504E99, 0x45AF5B, 0x6E3DA9, 0x4B9350, 0x123533, 0x2279D2, 0x1D46F9, 0x53F96B, 0x4AE0FD, 0x0],
+        CURVE_Pya: [0x2FB006, 0x218360, 0xCDF33, 0x525095, 0x53D194, 0x125912, 0x5833F3, 0x6345A4, 0xF39F, 0x1E7536, 0x7B46E8, 0x3EDDE2, 0x4DFD8A, 0x5EF53, 0x3489F3, 0x7A739F, 0x6070F4, 0x74FCCE, 0x1239FA, 0x113564, 0x0],
+        CURVE_Pyb: [0x71457C, 0xD5BFB, 0x2A294, 0x6E0261, 0x4D6A31, 0x6DC7F6, 0x26A3C4, 0x2B3475, 0x64492F, 0x2E7877, 0x19E84A, 0x25F55D, 0x220BE7, 0x5C70AD, 0x7C1310, 0x228AB, 0x2AB1D0, 0x6805D4, 0x6D3EAE, 0x71C080, 0x0],
+        CURVE_W: [
+            [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+            [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+        ],
+        CURVE_SB: [
+            [
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+            ],
+            [
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+            ]
+        ],
+        CURVE_WB: [
+            [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+            [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+            [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+            [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+        ],
+        CURVE_BB: [
+            [
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+            ],
+            [
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+            ],
+            [
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+            ],
+            [
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+            ]
+        ],
+
+        USE_GLV: true,
+        USE_GS_G2: true,
+        USE_GS_GT: true,
+        GT_STRONG: false,
+
+        //debug: false,
+
+    };
+
+    return ROM_CURVE_BLS461;
+};
+
+ROM_CURVE_FP256BN = function() {
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    var ROM_CURVE_FP256BN = {
+
+        // FP256BN Curve
+        // Base Bits= 24
+
+        Curve_Cof_I : 1,
+        CURVE_A: 0,
+        CURVE_B_I: 3,
+        CURVE_B: [0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        CURVE_Order: [0xB500D, 0x536CD1, 0x1AF62D, 0x129992, 0xDC65FB, 0xA49E0C, 0x5EEE71, 0x46E5F2, 0xFCF0CD, 0xFFFFFF, 0xFFFF],
+        CURVE_Gx: [0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        CURVE_Gy: [0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+
+        CURVE_Bnx: [0xB0A801, 0xF5C030, 0x6882, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        CURVE_Cof: [0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        CURVE_Cru: [0xA1B807, 0xA24A3, 0x1EDB1C, 0xF1932D, 0xCDD79D, 0x18659B, 0x409210, 0x3988E1, 0x1, 0x0, 0x0],
+        CURVE_Pxa: [0xC09EFB, 0x16B689, 0x3CD226, 0x12BF84, 0x1C539A, 0x913ACE, 0x577C28, 0x28560F, 0xC96C20, 0x3350B4, 0xFE0C],
+        CURVE_Pxb: [0x7E6A2B, 0xED34A3, 0x89D269, 0x87D035, 0xDD78E2, 0x13B924, 0xC637D8, 0xDB5AE1, 0x8AC054, 0x605773, 0x4EA6],
+        CURVE_Pya: [0xDC27FF, 0xB481BE, 0x48E909, 0x8D6158, 0xCB2475, 0x3E51EF, 0x75124E, 0x76770D, 0x42A3B3, 0x46E7C5, 0x7020],
+        CURVE_Pyb: [0xAD049B, 0x81114A, 0xB3E012, 0x821A98, 0x4CBE80, 0xB29F8B, 0x49297E, 0x42EEA6, 0x88C290, 0xE3BCD3, 0x554],
+
+        CURVE_W: [
+            [0x54003, 0x36E1B, 0x663AF0, 0xFFFE78, 0xFFFFFF, 0xFF, 0x0, 0x0, 0x0, 0x0, 0x0],
+            [0x615001, 0xEB8061, 0xD105, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+        ],
+        CURVE_SB: [
+            [
+                [0x669004, 0xEEEE7C, 0x670BF5, 0xFFFE78, 0xFFFFFF, 0xFF, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x615001, 0xEB8061, 0xD105, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+            ],
+            [
+                [0x615001, 0xEB8061, 0xD105, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x6100A, 0x4FFEB6, 0xB4BB3D, 0x129B19, 0xDC65FB, 0xA49D0C, 0x5EEE71, 0x46E5F2, 0xFCF0CD, 0xFFFFFF, 0xFFFF]
+            ]
+        ],
+        CURVE_WB: [
+            [0x30A800, 0x678F0D, 0xCC1020, 0x5554D2, 0x555555, 0x55, 0x0, 0x0, 0x0, 0x0, 0x0],
+            [0x7DC805, 0x764C0D, 0xAD1AD6, 0xA10BC3, 0xDE8FBE, 0x104467, 0x806160, 0xD105EB, 0x0, 0x0, 0x0],
+            [0x173803, 0xB6061F, 0xD6C1AC, 0x5085E1, 0xEF47DF, 0x82233, 0xC030B0, 0x6882F5, 0x0, 0x0, 0x0],
+            [0x91F801, 0x530F6E, 0xCCE126, 0x5554D2, 0x555555, 0x55, 0x0, 0x0, 0x0, 0x0, 0x0]
+        ],
+        CURVE_BB: [
+            [
+                [0x5AA80D, 0x5DACA0, 0x1A8DAA, 0x129992, 0xDC65FB, 0xA49E0C, 0x5EEE71, 0x46E5F2, 0xFCF0CD, 0xFFFFFF, 0xFFFF],
+                [0x5AA80C, 0x5DACA0, 0x1A8DAA, 0x129992, 0xDC65FB, 0xA49E0C, 0x5EEE71, 0x46E5F2, 0xFCF0CD, 0xFFFFFF, 0xFFFF],
+                [0x5AA80C, 0x5DACA0, 0x1A8DAA, 0x129992, 0xDC65FB, 0xA49E0C, 0x5EEE71, 0x46E5F2, 0xFCF0CD, 0xFFFFFF, 0xFFFF],
+                [0x615002, 0xEB8061, 0xD105, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+            ],
+            [
+                [0x615001, 0xEB8061, 0xD105, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x5AA80C, 0x5DACA0, 0x1A8DAA, 0x129992, 0xDC65FB, 0xA49E0C, 0x5EEE71, 0x46E5F2, 0xFCF0CD, 0xFFFFFF, 0xFFFF],
+                [0x5AA80D, 0x5DACA0, 0x1A8DAA, 0x129992, 0xDC65FB, 0xA49E0C, 0x5EEE71, 0x46E5F2, 0xFCF0CD, 0xFFFFFF, 0xFFFF],
+                [0x5AA80C, 0x5DACA0, 0x1A8DAA, 0x129992, 0xDC65FB, 0xA49E0C, 0x5EEE71, 0x46E5F2, 0xFCF0CD, 0xFFFFFF, 0xFFFF]
+            ],
+            [
+                [0x615002, 0xEB8061, 0xD105, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x615001, 0xEB8061, 0xD105, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x615001, 0xEB8061, 0xD105, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x615001, 0xEB8061, 0xD105, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+            ],
+            [
+                [0xB0A802, 0xF5C030, 0x6882, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0xC2A002, 0xD700C2, 0x1A20B, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0xAA000A, 0x67EC6F, 0x1A2527, 0x129992, 0xDC65FB, 0xA49E0C, 0x5EEE71, 0x46E5F2, 0xFCF0CD, 0xFFFFFF, 0xFFFF],
+                [0xB0A802, 0xF5C030, 0x6882, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+            ]
+        ],
+
+        USE_GLV: true,
+        USE_GS_G2: true,
+        USE_GS_GT: true,
+        GT_STRONG: false,
+
+        //debug: false,
+
+    };
+
+    return ROM_CURVE_FP256BN;
+};
+
+ROM_CURVE_FP512BN = function() {
+
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    var ROM_CURVE_FP512BN = {
+
+        // FP512BN Curve
+
+        // Base Bits= 23
+
+
+        Curve_Cof_I : 1,
+        CURVE_A: 0,
+        CURVE_B_I: 3,
+        CURVE_B: [0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        CURVE_Order: [0x1A09ED, 0x14BEA3, 0x501A99, 0x27CD15, 0x313E0, 0x346942, 0x2AC99E, 0x4632EF, 0x18B8E4, 0x3D597D, 0x451B3C, 0x77A22, 0x3C111B, 0x78177C, 0x32D4C1, 0x5D0EC, 0x7F01C6, 0x7FF3D8, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x3F],
+        CURVE_Gx: [0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        CURVE_Gy: [0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+
+        CURVE_Bnx: [0x1BD80F, 0xD76BC, 0x4042CC, 0x587BF, 0x2F5C03, 0xD10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        CURVE_Cof: [0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        CURVE_Cru: [0x79298A, 0x2C4138, 0x52C1C, 0x5C58BE, 0x6E6799, 0x1255D9, 0x2F9498, 0x43C4B3, 0x507ACD, 0x11384E, 0x1D2C80, 0x8FD18, 0x78EF76, 0x71D459, 0x2E1ACD, 0x1530A3, 0x7DC83D, 0x7FF3D8, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x3F],
+        CURVE_Pxa: [0x3646B5, 0x52DC1B, 0x7A3C1E, 0x48397F, 0xF8731, 0x71E443, 0x6F2EF1, 0x2BDF10, 0x4DC6DC, 0x70C6A2, 0x40914D, 0x3C6685, 0x5A57CC, 0x3736AF, 0x4D63C3, 0x5DE94D, 0x6A1E4B, 0x25E79, 0x6E9D, 0x244AC4, 0x1E1386, 0x62CA67, 0xE],
+        CURVE_Pxb: [0xAE0E9, 0x17DFB5, 0x6CF6D7, 0x6C4488, 0x4A411C, 0x5B9C81, 0x4E0F56, 0x286B70, 0x6E0D5E, 0x650AA4, 0x607889, 0x5CA6CB, 0x302566, 0x48ED51, 0x1B1BBC, 0x532B6E, 0x34825E, 0x157D1, 0x6D311A, 0x3F3644, 0x3F8506, 0x38279, 0x12],
+        CURVE_Pya: [0x5E67A1, 0x6255B, 0x178920, 0xAF7DC, 0x217AD6, 0x778B9B, 0xA022D, 0x11892A, 0x3E8EDD, 0x7BD82A, 0x5B3462, 0x34CEA5, 0x65C158, 0x1BA07D, 0x5982BF, 0x42D8EF, 0x4F2770, 0x19746E, 0x3BD6AC, 0x3DC149, 0x4C827C, 0x603D90, 0x1B],
+        CURVE_Pyb: [0x4F8E8B, 0x630D90, 0x5A162D, 0x25FBB0, 0x5C222, 0x11BFE, 0x7B89E7, 0x18856B, 0x714A4, 0x7C5CA, 0xA25FF, 0xCA0ED, 0x3D0496, 0x61936C, 0x46219E, 0xA1C60, 0x591F02, 0x62BEEB, 0xD9030, 0x3C18D6, 0x48B04E, 0x34779D, 0x14],
+        CURVE_W: [
+            [0x34583, 0x712E93, 0x4FC443, 0x68B50B, 0x5FB911, 0x47FD2C, 0x7FFF3D, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+            [0x37B01F, 0x1AED78, 0x8598, 0xB0F7F, 0x5EB806, 0x1A20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+        ],
+        CURVE_SB: [
+            [
+                [0x4B9564, 0x56411A, 0x4F3EAB, 0x5DA58C, 0x1010B, 0x47E30C, 0x7FFF3D, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x6259CE, 0x79D12A, 0x4F9500, 0x1CBD96, 0x245BDA, 0x344F21, 0x2AC99E, 0x4632EF, 0x18B8E4, 0x3D597D, 0x451B3C, 0x77A22, 0x3C111B, 0x78177C, 0x32D4C1, 0x5D0EC, 0x7F01C6, 0x7FF3D8, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x3F]
+            ],
+            [
+                [0x37B01F, 0x1AED78, 0x8598, 0xB0F7F, 0x5EB806, 0x1A20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x34583, 0x712E93, 0x4FC443, 0x68B50B, 0x5FB911, 0x47FD2C, 0x7FFF3D, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+            ]
+        ],
+        CURVE_WB: [
+            [0x5A29F0, 0x66D56A, 0x305B6A, 0x2C1E98, 0x442C60, 0x42BF7F, 0x555514, 0x2AAAAA, 0x555555, 0x2AAAAA, 0x555555, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+            [0x355D4B, 0x25744, 0x45FBAC, 0x6BFC27, 0x20FC1F, 0x6BCB9E, 0x2778AE, 0x2C497D, 0x5AD40F, 0x72C0C9, 0x4549D2, 0x29A8B1, 0x576BC3, 0x42CC1, 0x587BF8, 0x75C030, 0xD105, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+            [0x289AAD, 0x7E700, 0x431F3C, 0x38C1F3, 0x282C11, 0x35EC57, 0x53BC57, 0x5624BE, 0x6D6A07, 0x396064, 0x62A4E9, 0x54D458, 0x6BB5E1, 0x21660, 0x2C3DFC, 0x7AE018, 0x6882, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+            [0x2279D1, 0x4BE7F2, 0x2FD5D2, 0x210F19, 0x65745A, 0x42A55E, 0x555514, 0x2AAAAA, 0x555555, 0x2AAAAA, 0x555555, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+        ],
+        CURVE_BB: [
+            [
+                [0x1BD810, 0xD76BC, 0x4042CC, 0x587BF, 0x2F5C03, 0xD10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x1BD80F, 0xD76BC, 0x4042CC, 0x587BF, 0x2F5C03, 0xD10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x1BD80F, 0xD76BC, 0x4042CC, 0x587BF, 0x2F5C03, 0xD10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x6259CF, 0x79D12A, 0x4F9500, 0x1CBD96, 0x245BDA, 0x344F21, 0x2AC99E, 0x4632EF, 0x18B8E4, 0x3D597D, 0x451B3C, 0x77A22, 0x3C111B, 0x78177C, 0x32D4C1, 0x5D0EC, 0x7F01C6, 0x7FF3D8, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x3F]
+            ],
+            [
+                [0x37B01F, 0x1AED78, 0x8598, 0xB0F7F, 0x5EB806, 0x1A20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x7E31DE, 0x747E6, 0xFD7CD, 0x224556, 0x53B7DD, 0x345C31, 0x2AC99E, 0x4632EF, 0x18B8E4, 0x3D597D, 0x451B3C, 0x77A22, 0x3C111B, 0x78177C, 0x32D4C1, 0x5D0EC, 0x7F01C6, 0x7FF3D8, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x3F],
+                [0x7E31DD, 0x747E6, 0xFD7CD, 0x224556, 0x53B7DD, 0x345C31, 0x2AC99E, 0x4632EF, 0x18B8E4, 0x3D597D, 0x451B3C, 0x77A22, 0x3C111B, 0x78177C, 0x32D4C1, 0x5D0EC, 0x7F01C6, 0x7FF3D8, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x3F],
+                [0x7E31DE, 0x747E6, 0xFD7CD, 0x224556, 0x53B7DD, 0x345C31, 0x2AC99E, 0x4632EF, 0x18B8E4, 0x3D597D, 0x451B3C, 0x77A22, 0x3C111B, 0x78177C, 0x32D4C1, 0x5D0EC, 0x7F01C6, 0x7FF3D8, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x3F]
+            ],
+            [
+                [0x37B01E, 0x1AED78, 0x8598, 0xB0F7F, 0x5EB806, 0x1A20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x37B01F, 0x1AED78, 0x8598, 0xB0F7F, 0x5EB806, 0x1A20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x37B01F, 0x1AED78, 0x8598, 0xB0F7F, 0x5EB806, 0x1A20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x37B01F, 0x1AED78, 0x8598, 0xB0F7F, 0x5EB806, 0x1A20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+            ],
+            [
+                [0x7E31DF, 0x0747E6, 0x0FD7CD, 0x224556, 0x53B7DD, 0x345C31, 0x2AC99E, 0x4632EF, 0x18B8E4, 0x3D597D, 0x451B3C, 0x77A22, 0x3C111B, 0x78177C, 0x32D4C1, 0x5D0EC, 0x7F01C6, 0x7FF3D8, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x3F],
+                [0x2AA9AF, 0x5EE3B2, 0x4F0F68, 0x11AE17, 0x45A3D4, 0x343500, 0x2AC99E, 0x4632EF, 0x18B8E4, 0x3D597D, 0x451B3C, 0x77A22, 0x3C111B, 0x78177C, 0x32D4C1, 0x5D0EC, 0x7F01C6, 0x7FF3D8, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x3F],
+                [0x37B01D, 0x1AED78, 0x008598, 0x0B0F7F, 0x5EB806, 0x001A20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x7E31DF, 0x0747E6, 0x0FD7CD, 0x224556, 0x53B7DD, 0x345C31, 0x2AC99E, 0x4632EF, 0x18B8E4, 0x3D597D, 0x451B3C, 0x77A22, 0x3C111B, 0x78177C, 0x32D4C1, 0x5D0EC, 0x7F01C6, 0x7FF3D8, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x3F]
+            ]
+        ],
+
+        USE_GLV: true,
+        USE_GS_G2: true,
+        USE_GS_GT: true,
+        GT_STRONG: false,
+
+        //debug: false,
+
+    };
+
+    return ROM_CURVE_FP512BN;
+};
+
+ROM_CURVE_BN254 = function() {
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    var ROM_CURVE_BN254 = {
+
+        // BN254 Curve
+
+        // Base Bits= 24
+
+        Curve_Cof_I : 1,
+        CURVE_A: 0,
+        CURVE_B_I: 2,
+        CURVE_B: [0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        CURVE_Order: [0xD, 0x0, 0x10A100, 0x0, 0x9F8000, 0x7FF, 0x800000, 0xBA344D, 0x1, 0x648240, 0x2523],
+        CURVE_Gx: [0x12, 0x0, 0x13A700, 0x0, 0x210000, 0x861, 0x800000, 0xBA344D, 0x1, 0x648240, 0x2523],
+        CURVE_Gy: [0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+
+        CURVE_Bnx: [0x1, 0x0, 0x4080, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        CURVE_Cof: [0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        CURVE_Cru: [0x7, 0x0, 0x6CD80, 0x0, 0x90000, 0x249, 0x400000, 0x49B362, 0x0, 0x0, 0x0],
+        CURVE_Pxa: [0x3FB2B, 0x4224C8, 0xD91EE, 0x4898BF, 0x648BBB, 0xEDB6A4, 0x7E8C61, 0xEB8D8C, 0x9EB62F, 0x10BB51, 0x61A],
+        CURVE_Pxb: [0xD54CF3, 0x34C1E7, 0xB70D8C, 0xAE3784, 0x4D746B, 0xAA5B1F, 0x8C5982, 0x310AA7, 0x737833, 0xAAF9BA, 0x516],
+        CURVE_Pya: [0xCD2B9A, 0xE07891, 0xBD19F0, 0xBDBE09, 0xBD0AE6, 0x822329, 0x96698C, 0x9A90E0, 0xAF9343, 0x97A06B, 0x218],
+        CURVE_Pyb: [0x3ACE9B, 0x1AEC6B, 0x578A2D, 0xD739C9, 0x9006FF, 0x8D37B0, 0x56F5F3, 0x8F6D44, 0x8B1526, 0x2B0E7C, 0xEBB],
+        CURVE_W: [
+            [0x3, 0x0, 0x20400, 0x0, 0x818000, 0x61, 0x0, 0x0, 0x0, 0x0, 0x0],
+            [0x1, 0x0, 0x8100, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+        ],
+        CURVE_SB: [
+            [
+                [0x4, 0x0, 0x28500, 0x0, 0x818000, 0x61, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x1, 0x0, 0x8100, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+            ],
+            [
+                [0x1, 0x0, 0x8100, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0xA, 0x0, 0xE9D00, 0x0, 0x1E0000, 0x79E, 0x800000, 0xBA344D, 0x1, 0x648240, 0x2523]
+            ]
+        ],
+        CURVE_WB: [
+            [0x0, 0x0, 0x4080, 0x0, 0x808000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0],
+            [0x5, 0x0, 0x54A80, 0x0, 0x70000, 0x1C7, 0x800000, 0x312241, 0x0, 0x0, 0x0],
+            [0x3, 0x0, 0x2C580, 0x0, 0x838000, 0xE3, 0xC00000, 0x189120, 0x0, 0x0, 0x0],
+            [0x1, 0x0, 0xC180, 0x0, 0x808000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0]
+        ],
+        CURVE_BB: [
+            [
+                [0xD, 0x0, 0x106080, 0x0, 0x9F8000, 0x7FF, 0x800000, 0xBA344D, 0x1, 0x648240, 0x2523],
+                [0xC, 0x0, 0x106080, 0x0, 0x9F8000, 0x7FF, 0x800000, 0xBA344D, 0x1, 0x648240, 0x2523],
+                [0xC, 0x0, 0x106080, 0x0, 0x9F8000, 0x7FF, 0x800000, 0xBA344D, 0x1, 0x648240, 0x2523],
+                [0x2, 0x0, 0x8100, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+            ],
+            [
+                [0x1, 0x0, 0x8100, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0xC, 0x0, 0x106080, 0x0, 0x9F8000, 0x7FF, 0x800000, 0xBA344D, 0x1, 0x648240, 0x2523],
+                [0xD, 0x0, 0x106080, 0x0, 0x9F8000, 0x7FF, 0x800000, 0xBA344D, 0x1, 0x648240, 0x2523],
+                [0xC, 0x0, 0x106080, 0x0, 0x9F8000, 0x7FF, 0x800000, 0xBA344D, 0x1, 0x648240, 0x2523]
+            ],
+            [
+                [0x2, 0x0, 0x8100, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x1, 0x0, 0x8100, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x1, 0x0, 0x8100, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x1, 0x0, 0x8100, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+            ],
+            [
+                [0x2, 0x0, 0x4080, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x2, 0x0, 0x10200, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0xA, 0x0, 0x102000, 0x0, 0x9F8000, 0x7FF, 0x800000, 0xBA344D, 0x1, 0x648240, 0x2523],
+                [0x2, 0x0, 0x4080, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+            ]
+        ],
+
+        USE_GLV: true,
+        USE_GS_G2: true,
+        USE_GS_GT: true,
+        GT_STRONG: false,
+
+        //debug: false,
+    };
+
+    return ROM_CURVE_BN254;
+};
+
+ROM_CURVE_BN254CX = function() {
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    var ROM_CURVE_BN254CX = {
+
+        // BN254CX Curve
+        // Base Bits= 24
+
+        Curve_Cof_I : 1,
+        CURVE_A: 0,
+        CURVE_B_I: 2,
+        CURVE_B: [0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        CURVE_Order: [0xEB1F6D, 0xC0A636, 0xCEBE11, 0xCC906, 0x3FD6EE, 0x66D2C4, 0x647A63, 0xB0BDDF, 0x702A0D, 0x8, 0x2400],
+        CURVE_Gx: [0x1B55B2, 0x23EF5C, 0xE1BE66, 0x18093E, 0x3FD6EE, 0x66D324, 0x647A63, 0xB0BDDF, 0x702A0D, 0x8, 0x2400],
+        CURVE_Gy: [0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+
+        CURVE_Bnx: [0xC012B1, 0x3, 0x4000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        CURVE_Cof: [0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        CURVE_Cru: [0x235C97, 0x931794, 0x5631E0, 0x71EF87, 0xBDDF64, 0x3F1440, 0xCA8, 0x480000, 0x0, 0x0, 0x0],
+
+        CURVE_Pxa: [0xD2EC74,0x1CEEE4,0x26C085,0xA03E27,0x7C85BF,0x4BBB90,0xF5C3,0x358B25,0x53B256,0x2D2C70,0x1968],
+        CURVE_Pxb: [0x29CFE1,0x8E8B2E,0xF47A5,0xC209C3,0x1B97B0,0x9743F8,0x37A8E9,0xA011C9,0x19F64A,0xB9EC3E,0x1466],
+        CURVE_Pya: [0xBE09F,0xFCEBCF,0xB30CFB,0x847EC1,0x61B33D,0xE20963,0x157DAE,0xD81E22,0x332B8D,0xEDD972,0xA79],
+        CURVE_Pyb: [0x98EE9D,0x4B2288,0xEBED90,0x69D2ED,0x864EA5,0x3461C2,0x512D8D,0x35C6E4,0xC4C090,0xC39EC,0x616],
+
+
+        CURVE_W: [
+            [0x2FEB83, 0x634916, 0x120054, 0xB4038, 0x0, 0x60, 0x0, 0x0, 0x0, 0x0, 0x0],
+            [0x802561, 0x7, 0x8000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+        ],
+        CURVE_SB: [
+            [
+                [0xB010E4, 0x63491D, 0x128054, 0xB4038, 0x0, 0x60, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x802561, 0x7, 0x8000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+            ],
+            [
+                [0x802561, 0x7, 0x8000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0xBB33EA, 0x5D5D20, 0xBCBDBD, 0x188CE, 0x3FD6EE, 0x66D264, 0x647A63, 0xB0BDDF, 0x702A0D, 0x8, 0x2400]
+            ]
+        ],
+        CURVE_WB: [
+            [0x7A84B0, 0x211856, 0xB0401C, 0x3C012, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0],
+            [0x220475, 0xF995BE, 0x9A36CD, 0xA8CA7F, 0x7E94ED, 0x2A0DC0, 0x870, 0x300000, 0x0, 0x0, 0x0],
+            [0xF10B93, 0xFCCAE0, 0xCD3B66, 0xD4653F, 0x3F4A76, 0x1506E0, 0x438, 0x180000, 0x0, 0x0, 0x0],
+            [0xFAAA11, 0x21185D, 0xB0C01C, 0x3C012, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0]
+        ],
+        CURVE_BB: [
+            [
+                [0x2B0CBD, 0xC0A633, 0xCE7E11, 0xCC906, 0x3FD6EE, 0x66D2C4, 0x647A63, 0xB0BDDF, 0x702A0D, 0x8, 0x2400],
+                [0x2B0CBC, 0xC0A633, 0xCE7E11, 0xCC906, 0x3FD6EE, 0x66D2C4, 0x647A63, 0xB0BDDF, 0x702A0D, 0x8, 0x2400],
+                [0x2B0CBC, 0xC0A633, 0xCE7E11, 0xCC906, 0x3FD6EE, 0x66D2C4, 0x647A63, 0xB0BDDF, 0x702A0D, 0x8, 0x2400],
+                [0x802562, 0x7, 0x8000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+            ],
+            [
+                [0x802561, 0x7, 0x8000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x2B0CBC, 0xC0A633, 0xCE7E11, 0xCC906, 0x3FD6EE, 0x66D2C4, 0x647A63, 0xB0BDDF, 0x702A0D, 0x8, 0x2400],
+                [0x2B0CBD, 0xC0A633, 0xCE7E11, 0xCC906, 0x3FD6EE, 0x66D2C4, 0x647A63, 0xB0BDDF, 0x702A0D, 0x8, 0x2400],
+                [0x2B0CBC, 0xC0A633, 0xCE7E11, 0xCC906, 0x3FD6EE, 0x66D2C4, 0x647A63, 0xB0BDDF, 0x702A0D, 0x8, 0x2400]
+            ],
+            [
+                [0x802562, 0x7, 0x8000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x802561, 0x7, 0x8000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x802561, 0x7, 0x8000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x802561, 0x7, 0x8000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+            ],
+            [
+                [0xC012B2, 0x3, 0x4000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x4AC2, 0xF, 0x10000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+                [0x6AFA0A, 0xC0A62F, 0xCE3E11, 0xCC906, 0x3FD6EE, 0x66D2C4, 0x647A63, 0xB0BDDF, 0x702A0D, 0x8, 0x2400],
+                [0xC012B2, 0x3, 0x4000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
+            ]
+        ],
+
+        USE_GLV: true,
+        USE_GS_G2: true,
+        USE_GS_GT: true,
+        GT_STRONG: false,
+
+        //debug: false,
+
+    };
+
+    return ROM_CURVE_BN254CX;
+};
+
+ROM_CURVE_BRAINPOOL = function() {
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    /* Note that the original curve has been transformed to an isomorphic curve with A=-3 */
+
+
+    var ROM_CURVE_BRAINPOOL = {
+
+        // Brainpool curve
+        // Base Bits= 24
+
+        Curve_Cof_I : 1,
+        CURVE_A: -3,
+        CURVE_B_I: 0,
+        CURVE_B: [0xE92B04, 0x8101FE, 0x256AE5, 0xAF2F49, 0x93EBC4, 0x76B7BF, 0x733D0B, 0xFE66A7, 0xD84EA4, 0x61C430, 0x662C],
+        CURVE_Order: [0x4856A7, 0xE8297, 0xF7901E, 0xB561A6, 0x397AA3, 0x8D718C, 0x909D83, 0x3E660A, 0xEEA9BC, 0x57DBA1, 0xA9FB],
+        CURVE_Gx: [0x1305F4, 0x91562E, 0x2B79A1, 0x7AAFBC, 0xA142C4, 0x6149AF, 0xB23A65, 0x732213, 0xCFE7B7, 0xEB3CC1, 0xA3E8],
+        CURVE_Gy: [0x25C9BE, 0xE8F35B, 0x1DAB, 0x39D027, 0xBCB6DE, 0x417E69, 0xE14644, 0x7F7B22, 0x39C56D, 0x6C8234, 0x2D99],
+    };
+    return ROM_CURVE_BRAINPOOL;
+};
+
+ROM_CURVE_C25519 = function() {
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    var ROM_CURVE_C25519 = {
+
+        // C25519 Curve
+
+        Curve_Cof_I : 8,
+        CURVE_A: 486662,
+        CURVE_B_I: 0,
+        CURVE_B: [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        CURVE_Order: [0xF5D3ED, 0x631A5C, 0xD65812, 0xA2F79C, 0xDEF9DE, 0x14, 0x0, 0x0, 0x0, 0x0, 0x1000],
+        CURVE_Gx: [0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        CURVE_Gy: [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+    };
+    return ROM_CURVE_C25519;
+};
+
+ROM_CURVE_C41417 = function() {
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    var ROM_CURVE_C41417 = {
+
+        // C41417 curve
+        Curve_Cof_I : 8,
+        CURVE_A: 1,
+        CURVE_B_I: 3617,
+        CURVE_B: [0xE21, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        CURVE_Order: [0x6AF79, 0x69784, 0x1B0E7, 0x18F3C6, 0x338AD, 0xDBC70, 0x6022B, 0x533DC, 0x3CC924, 0x3FFFAC, 0x3FFFFF, 0x3FFFFF, 0x3FFFFF, 0x3FFFFF, 0x3FFFFF, 0x3FFFFF, 0x3FFFFF, 0x3FFFFF, 0x7FFF],
+        CURVE_Gx: [0xBC595, 0x204BCF, 0xC4FD3, 0x14DF19, 0x33FAA8, 0x4C069, 0x16BA11, 0x2AD35B, 0x1498A4, 0x15FFCD, 0x3EC7F, 0x27D130, 0xD4636, 0x9B97F, 0x631C3, 0x8630, 0x144330, 0x241450, 0x1A334],
+        CURVE_Gy: [0x22, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+
+    };
+
+    return ROM_CURVE_C41417;
+};
+
+ROM_CURVE_ED25519 = function() {
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    var ROM_CURVE_ED25519 = {
+
+        // ED25519 Curve
+
+        Curve_Cof_I : 8,
+        CURVE_A: -1,
+        CURVE_B_I: 0,
+        CURVE_B: [0x5978A3, 0x4DCA13, 0xAB75EB, 0x4141D8, 0x700A4D, 0xE89800, 0x797779, 0x8CC740, 0x6FFE73, 0x6CEE2B, 0x5203],
+        CURVE_Order: [0xF5D3ED, 0x631A5C, 0xD65812, 0xA2F79C, 0xDEF9DE, 0x14, 0x0, 0x0, 0x0, 0x0, 0x1000],
+        CURVE_Gx: [0x25D51A, 0x2D608F, 0xB2C956, 0x9525A7, 0x2CC760, 0xDC5C69, 0x31FDD6, 0xC0A4E2, 0x6E53FE, 0x36D3CD, 0x2169],
+        CURVE_Gy: [0x666658, 0x666666, 0x666666, 0x666666, 0x666666, 0x666666, 0x666666, 0x666666, 0x666666, 0x666666, 0x6666],
+
+
+    };
+    return ROM_CURVE_ED25519;
+};
+
+ROM_CURVE_GOLDILOCKS = function() {
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    var ROM_CURVE_GOLDILOCKS = {
+
+        // GOLDILOCKS curve
+        Curve_Cof_I : 4,
+        CURVE_A: 1,
+        CURVE_B_I: -39081,
+        CURVE_B: [0x7F6756, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7DFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FF],
+        CURVE_Order: [0x5844F3, 0x52556, 0x548DE3, 0x6E2C7A, 0x4C2728, 0x52042D, 0x6BB58D, 0x276DA4, 0x23E9C4, 0x7EF994, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x1FF],
+        CURVE_Gx: [0x555555, 0x2AAAAA, 0x555555, 0x2AAAAA, 0x555555, 0x2AAAAA, 0x555555, 0x2AAAAA, 0x555555, 0x52AAAA, 0x2AAAAA, 0x555555, 0x2AAAAA, 0x555555, 0x2AAAAA, 0x555555, 0x2AAAAA, 0x555555, 0x2AAAAA, 0x555],
+        CURVE_Gy: [0x1386ED, 0x779BD5, 0x2F6BAB, 0xE6D03, 0x4B2BED, 0x131777, 0x4E8A8C, 0x32B2C1, 0x44B80D, 0x6515B1, 0x5F8DB5, 0x426EBD, 0x7A0358, 0x6DDA, 0x21B0AC, 0x6B1028, 0xDB359, 0x15AE09, 0x17A58D, 0x570],
+    };
+    return ROM_CURVE_GOLDILOCKS;
+};
+
+ROM_CURVE_HIFIVE = function() {
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    var ROM_CURVE_HIFIVE = {
+
+        // HIFIVE curve
+
+        Curve_Cof_I : 8,
+        CURVE_A: 1,
+        CURVE_B_I: 11111,
+        CURVE_B: [0x2B67, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        CURVE_Order: [0x1FA805, 0x2B2E7D, 0x29ECBE, 0x3FC9DD, 0xBD6B8, 0x530A18, 0x45057E, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x800],
+        CURVE_Gx: [0xC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        CURVE_Gy: [0x7E8632, 0xD0A0B, 0x6C4AFB, 0x501B2E, 0x55650C, 0x36DB6B, 0x1FBD0D, 0x61C08E, 0x314B46, 0x70A7A3, 0x587401, 0xC70E0, 0x56502E, 0x38C2D6, 0x303],
+
+    };
+    return ROM_CURVE_HIFIVE;
+};
+
+ROM_CURVE_NIST256 = function() {
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    var ROM_CURVE_NIST256 = {
+
+        // NIST256 Curve
+        Curve_Cof_I : 1,
+        CURVE_A: -3,
+        CURVE_B_I: 0,
+        CURVE_B: [0xD2604B, 0x3C3E27, 0xF63BCE, 0xCC53B0, 0x1D06B0, 0x86BC65, 0x557698, 0xB3EBBD, 0x3A93E7, 0x35D8AA, 0x5AC6],
+        CURVE_Order: [0x632551, 0xCAC2FC, 0x84F3B9, 0xA7179E, 0xE6FAAD, 0xFFFFBC, 0xFFFFFF, 0xFFFFFF, 0x0, 0xFFFF00, 0xFFFF],
+        CURVE_Gx: [0x98C296, 0x3945D8, 0xA0F4A1, 0x2DEB33, 0x37D81, 0x40F277, 0xE563A4, 0xF8BCE6, 0x2C4247, 0xD1F2E1, 0x6B17],
+        CURVE_Gy: [0xBF51F5, 0x406837, 0xCECBB6, 0x6B315E, 0xCE3357, 0x9E162B, 0x4A7C0F, 0x8EE7EB, 0x1A7F9B, 0x42E2FE, 0x4FE3],
+
+    };
+    return ROM_CURVE_NIST256;
+};
+
+ROM_CURVE_NIST384 = function() {
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    var ROM_CURVE_NIST384 = {
+
+        // NIST384 curve
+        Curve_Cof_I : 1,
+        CURVE_A: -3,
+        CURVE_B_I: 0,
+        CURVE_B: [0x6C2AEF, 0x11DBA7, 0x74AA17, 0x51768C, 0x6398D8, 0x6B58CA, 0x5404E1, 0xA0447, 0x411203, 0x5DFD02, 0x607671, 0x4168C8, 0x56BE3F, 0x1311C0, 0xFB9F9, 0x17D3F1, 0xB331],
+        CURVE_Order: [0x452973, 0x32D599, 0x6BB3B0, 0x45853B, 0x20DB24, 0x3BEB03, 0x7D0DCB, 0x31A6C0, 0x7FFFC7, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0xFFFF],
+        CURVE_Gx: [0x760AB7, 0x3C70E4, 0x30E951, 0x7AA94B, 0x2F25DB, 0x470AA0, 0x20950A, 0x7BA0F0, 0x1B9859, 0x45174F, 0x3874ED, 0x56BA3, 0x71EF32, 0x71D638, 0x22C14D, 0x65115F, 0xAA87],
+        CURVE_Gy: [0x6A0E5F, 0x3AF921, 0x75E90C, 0x6BF40C, 0xB1CE1, 0x18014C, 0x6D7C2E, 0x6D1889, 0x147CE9, 0x7A5134, 0x63D076, 0x16E14F, 0xBF929, 0x6BB3D3, 0x98B1B, 0x6F254B, 0x3617],
+    };
+    return ROM_CURVE_NIST384;
+};
+
+ROM_CURVE_NIST521 = function() {
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    var ROM_CURVE_NIST521 = {
+
+        // NIST521 curve
+
+        Curve_Cof_I : 1,
+        CURVE_A: -3,
+        CURVE_B_I: 0,
+        CURVE_B: [0x503F00, 0x3FA8D6, 0x47BD14, 0x6961A7, 0x3DF883, 0x60E6AE, 0x4EEC6F, 0x29605E, 0x137B16, 0x23D8FD, 0x5864E5, 0x84F0A, 0x1918EF, 0x771691, 0x6CC57C, 0x392DCC, 0x6EA2DA, 0x6D0A81, 0x688682, 0x50FC94, 0x18E1C9, 0x27D72C, 0x1465],
+        CURVE_Order: [0x386409, 0x6E3D22, 0x3AEDBE, 0x4CE23D, 0x5C9B88, 0x3A0776, 0x3DC269, 0x6600A4, 0x166B7F, 0x77E5F, 0x461A1E, 0x7FFFD2, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFF],
+        CURVE_Gx: [0x65BD66, 0x7C6385, 0x6FE5F9, 0x2B5214, 0xB3C18, 0x1BC669, 0x68BFEA, 0xEE093, 0x5928FE, 0x6FDFCE, 0x52D79, 0x69EDD5, 0x7606B4, 0x3F0515, 0x4FED48, 0x409C82, 0x429C64, 0x472B68, 0x7B2D98, 0x4E6CF1, 0x70404E, 0x31C0D6, 0x31A1],
+        CURVE_Gy: [0x516650, 0x28ED3F, 0x222FA, 0x139612, 0x47086A, 0x6C26A7, 0x4FEB41, 0x285C80, 0x2640C5, 0x32BDE8, 0x5FB9CA, 0x733164, 0x517273, 0x2F5F7, 0x66D11A, 0x2224AB, 0x5998F5, 0x58FA37, 0x297ED0, 0x22E4, 0x9A3BC, 0x252D4F, 0x460E],
+    };
+    return ROM_CURVE_NIST521;
+};
+
+ROM_CURVE_NUMS256E = function() {
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    var ROM_CURVE_NUMS256E = {
+
+        // NUMS256E Curve
+        Curve_Cof_I : 4,
+        CURVE_A: 1,
+        CURVE_B_I: -15342,
+        CURVE_B: [0xFFC355, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFF],
+        CURVE_Order: [0xDD4AF5, 0xB190EE, 0x9B1A47, 0x2F5943, 0x955AA5, 0x41, 0x0, 0x0, 0x0, 0x0, 0x4000],
+        CURVE_Gx: [0xED13DA, 0xC0902E, 0x86A0DE, 0xE30835, 0x398A0E, 0x9BD60C, 0x5F6920, 0xCD1E3D, 0xEA237D, 0x14FB6A, 0x8A75],
+        CURVE_Gy: [0x8A89E6, 0x16E779, 0xD32FA6, 0x10856E, 0x5F61D8, 0x801071, 0xD9A64B, 0xCE9665, 0xD925C7, 0x3E9FD9, 0x44D5],
+
+
+    };
+    return ROM_CURVE_NUMS256E;
+};
+
+ROM_CURVE_NUMS256W = function() {
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    var ROM_CURVE_NUMS256W = {
+
+        // NUMS256W Curve
+        Curve_Cof_I : 1,
+        CURVE_A: -3,
+        CURVE_B_I: 152961,
+        CURVE_B: [0x25581, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        CURVE_Order: [0x51A825, 0x202947, 0x6020AB, 0xEA265C, 0x3C8275, 0xFFFFE4, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFF],
+        CURVE_Gx: [0x1AACB1, 0xEE1EB2, 0x3ABC52, 0x3D4C7, 0x579B09, 0xCB0983, 0xA04F42, 0x297A95, 0xAADB61, 0xD6B65A, 0xBC9E],
+        CURVE_Gy: [0x84DE9F, 0xB9CB21, 0xBB80B5, 0x15310F, 0x55C3D1, 0xE035C9, 0xF77E04, 0x73448B, 0x99B6A6, 0xC0F133, 0xD08F],
+
+
+    };
+    return ROM_CURVE_NUMS256W;
+};
+
+ROM_CURVE_NUMS384E = function() {
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    var ROM_CURVE_NUMS384E = {
+
+        // NUMS384E Curve
+        Curve_Cof_I : 4,
+        CURVE_A: 1,
+        CURVE_B_I: -11556,
+        CURVE_B: [0x7FD19F, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0xFFFF],
+        CURVE_Order: [0x23897D, 0x3989CD, 0x6482E7, 0x59AE43, 0x4555AA, 0x39EC3C, 0x2D1AF8, 0x238D0E, 0x7FFFE2, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x3FFF],
+        CURVE_Gx: [0x206BDE, 0x1C8D8, 0x4D4355, 0x2A2CA0, 0x292B16, 0x680DFE, 0x3CCC58, 0x31FFD4, 0x4C0057, 0xDCB7C, 0x4C2FD1, 0x2AEDAD, 0x2129AE, 0x1816D4, 0x6A499B, 0x8FDA2, 0x61B1],
+        CURVE_Gy: [0x729392, 0x7C3E0, 0x727634, 0x376246, 0x2B0F94, 0x49600E, 0x7D9165, 0x7CC7B, 0x5F5683, 0x69E284, 0x5AB609, 0x86EB8, 0x1A423B, 0x10E716, 0x69BBAC, 0x1F33DC, 0x8298],
+
+    };
+    return ROM_CURVE_NUMS384E;
+};
+
+ROM_CURVE_NUMS384W = function() {
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    var ROM_CURVE_NUMS384W = {
+
+        // NUMS384W Curve
+        Curve_Cof_I : 1,
+        CURVE_A: -3,
+        CURVE_B_I: -34568,
+        CURVE_B: [0x7F77BB, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0xFFFF],
+        CURVE_Order: [0xE61B9, 0x3ECF6, 0x698136, 0x61BF13, 0x29D3D4, 0x1037DB, 0x3AD75A, 0xF578F, 0x7FFFD6, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0xFFFF],
+        CURVE_Gx: [0x18152A, 0x740841, 0x6FAE72, 0x7B0E23, 0x6ED100, 0x684A45, 0x4A9B31, 0x5E948D, 0x79F4F3, 0x1BF703, 0x89707, 0x2F8D30, 0x222410, 0x91019, 0x5BC607, 0x2B7858, 0x7579],
+        CURVE_Gy: [0x180716, 0x71D8CC, 0x1971D2, 0x7FA569, 0x6B4DBB, 0x6FD79A, 0x4486A0, 0x1041BE, 0x739CB9, 0x6FF0FE, 0x4011A5, 0x267BF5, 0x530058, 0x1AFC67, 0x66E38E, 0x71B470, 0xACDE],
+
+
+    };
+    return ROM_CURVE_NUMS384W;
+};
+
+ROM_CURVE_NUMS512E = function() {
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    var ROM_CURVE_NUMS512E = {
+
+        // NUMS512E Curve
+        Curve_Cof_I : 4,
+        CURVE_A: 1,
+        CURVE_B_I: -78296,
+        CURVE_B: [0x7ECBEF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x3F],
+        CURVE_Order: [0x6ED46D, 0x19EA37, 0x7D9D1A, 0x6F7F67, 0x605786, 0x5EA548, 0x5C2DA1, 0x1FEC64, 0x11BA9E, 0x5A5F9F, 0x53C18D, 0x7FFFFD, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0xF],
+        CURVE_Gx: [0x6C57FE, 0x565333, 0x5716E6, 0x662780, 0x525427, 0x15A1FC, 0x15A241, 0x5EE4C9, 0x730F78, 0x1DDC8C, 0x188705, 0x5C0A3A, 0x6BE273, 0x44F42F, 0x7128E0, 0x73CFA6, 0x332FD1, 0x11A78A, 0x632DE2, 0x34E3D0, 0x5128DB, 0x71C62D, 0x37],
+        CURVE_Gy: [0x62F5E1, 0x3D8183, 0x7CC9B7, 0x5F8E80, 0x6D38A9, 0x3FA04C, 0xABB30, 0xD0343, 0x356260, 0x65D32C, 0x3294F, 0x741A09, 0x395909, 0x55256D, 0x96748, 0x7B936C, 0x6EE476, 0x50544A, 0x43D5DE, 0x538CC5, 0x39D49C, 0x2137FE, 0x1B],
+
+    };
+    return ROM_CURVE_NUMS512E;
+};
+
+ROM_CURVE_NUMS512W = function() {
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    var ROM_CURVE_NUMS512W = {
+
+        // NUMS512W Curve
+        Curve_Cof_I : 1,
+        CURVE_A: -3,
+        CURVE_B_I: 121243,
+        CURVE_B: [0x1D99B, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        CURVE_Order: [0x33555D, 0x7E7208, 0xF3854, 0x3E692, 0x68B366, 0x38C76A, 0x65F42F, 0x612C76, 0x31B4F, 0x7729CF, 0x6CF293, 0x7FFFFA, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x3F],
+        CURVE_Gx: [0x2BAE57, 0xF2B19, 0xB720A, 0x6B7AEF, 0x560137, 0x3063AB, 0x95585, 0x3CA143, 0x359E93, 0x220ED6, 0x408685, 0x36CFCA, 0xC2530, 0x28A0DC, 0x407DA1, 0x6C1DDA, 0x5298CA, 0x407A76, 0x2DC00A, 0x549ED1, 0x7141D0, 0x580688, 0xE],
+        CURVE_Gy: [0x3527A6, 0xEC070, 0x248E82, 0x67E87F, 0x35C1E4, 0x4059E5, 0x2C9695, 0x10D420, 0x6DE9C1, 0x35161D, 0xA1057, 0xA78A5, 0x60C7BD, 0x11E964, 0x6F2EE3, 0x6DEF55, 0x4B97, 0x47D762, 0x3BBB71, 0x359E70, 0x229AD5, 0x74A99, 0x25],
+
+    };
+    return ROM_CURVE_NUMS512W;
+};
+
+ROM_CURVE_SECP256K1 = function() {
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    var ROM_CURVE_SECP256K1 = {
+
+        // SECP256K1 Curve
+        // Base Bits= 24
+
+        CURVE_Cof_I: 1,
+        CURVE_A: 0,
+        CURVE_B_I: 7,
+        CURVE_B: [0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        CURVE_Order: [0x364141, 0x5E8CD0, 0x3BBFD2, 0xAF48A0, 0xAEDCE6, 0xFFFEBA, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFF],
+        CURVE_Gx: [0xF81798, 0x815B16, 0xD959F2, 0x2DCE28, 0x9BFCDB, 0xB0702, 0x95CE87, 0x55A062, 0xDCBBAC, 0x667EF9, 0x79BE],
+        CURVE_Gy: [0x10D4B8, 0xD08FFB, 0x199C47, 0xA68554, 0x17B448, 0x8A8FD, 0xFC0E11, 0x5DA4FB, 0xA3C465, 0xDA7726, 0x483A],
+
+    };
+    return ROM_CURVE_SECP256K1;
+};
diff --git a/version3/js/rom_field.js b/version3/js/rom_field.js
new file mode 100644
index 0000000..0618471
--- /dev/null
+++ b/version3/js/rom_field.js
@@ -0,0 +1,425 @@
+/*
+    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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+var ROM_FIELD_25519,
+    ROM_FIELD_256PM,
+    ROM_FIELD_384PM,
+    ROM_FIELD_512PM,
+    ROM_FIELD_ANSSI,
+    ROM_FIELD_BLS383,
+    ROM_FIELD_BLS24,
+    ROM_FIELD_BLS48,
+    ROM_FIELD_BLS381,
+    ROM_FIELD_BLS461,
+    ROM_FIELD_FP256BN,
+    ROM_FIELD_FP512BN,
+    ROM_FIELD_BN254,
+    ROM_FIELD_BN254CX,
+    ROM_FIELD_BRAINPOOL,
+    ROM_FIELD_C41417,
+    ROM_FIELD_GOLDILOCKS,
+    ROM_FIELD_HIFIVE,
+    ROM_FIELD_NIST256,
+    ROM_FIELD_NIST384,
+    ROM_FIELD_NIST521,
+    ROM_FIELD_SECP256K1;
+
+ROM_FIELD_25519 = function() {
+    "use strict";
+
+    var ROM_FIELD_25519 = {
+
+        // 25519 Curve Modulus
+        Modulus: [0xFFFFED, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0x7FFF],
+        R2modp: [0xA40000, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        MConst: 0x13,
+
+    };
+    return ROM_FIELD_25519;
+};
+
+ROM_FIELD_256PM = function() {
+    "use strict";
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    var ROM_FIELD_256PM = {
+
+        // NUMS256 Curve Modulus
+        // Base Bits= 24
+        Modulus: [0xFFFF43, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFF],
+        R2modp: [0x890000, 0x8B, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        MConst: 0xBD,
+
+    };
+    return ROM_FIELD_256PM;
+};
+
+ROM_FIELD_384PM = function() {
+    "use strict";
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    var ROM_FIELD_384PM = {
+
+        // NUMS384 Curve Modulus
+        // Base Bits= 23
+        Modulus: [0x7FFEC3, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0xFFFF],
+        R2modp: [0x224000, 0xC4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        MConst: 0x13D,
+
+    };
+    return ROM_FIELD_384PM;
+};
+
+ROM_FIELD_512PM = function() {
+    "use strict";
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    var ROM_FIELD_512PM = {
+
+        // NUMS512 Curve Modulus
+        // Base Bits= 23
+        Modulus: [0x7FFDC7, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x3F],
+        R2modp: [0x0, 0x58800, 0x4F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        MConst: 0x239,
+
+    };
+    return ROM_FIELD_512PM;
+};
+
+ROM_FIELD_ANSSI = function() {
+    "use strict";
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    var ROM_FIELD_ANSSI = {
+
+        // ANSSI modulus
+        // Base Bits= 24
+        Modulus: [0x6E9C03, 0xF353D8, 0x6DE8FC, 0xABC8CA, 0x61ADBC, 0x435B39, 0xE8CE42, 0x10126D, 0x3AD58F, 0x178C0B, 0xF1FD],
+        R2modp: [0xACECE3, 0x924166, 0xB10FCE, 0x6CFBB6, 0x87EC2, 0x3DE43D, 0xD2CF67, 0xA67DDE, 0xAD30F2, 0xBCAAE, 0xDF98],
+        MConst: 0x4E1155,
+
+    };
+    return ROM_FIELD_ANSSI;
+};
+
+ROM_FIELD_BLS383 = function() {
+    "use strict";
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    var ROM_FIELD_BLS383 = {
+
+        // BLS383 Modulus
+        // Base Bits= 23
+        Modulus: [0x2AB0AB,0x3AC90B,0x2F68DC,0x532429,0x43F298,0x1E8F51,0x5A5849,0x18DC00,0x2511AC,0x59E6CB,0x2B518,0x549425,0x5C41FE,0x340DB5,0x2ADBAD,0x2B4AB2,0x5565],
+        R2modp: [0x250A44,0x68F66F,0xE3C74,0x791772,0x3525E3,0xE1E15,0x356616,0x54F624,0x508069,0x272663,0x4A4CB0,0x359293,0x5B6573,0x9F27F,0x5EA3B4,0x60FD2D,0x5167],
+        MConst: 0x3435FD,
+        Fra: [0x11DAC1,0x2E5A66,0x614B,0x733B9F,0x13480F,0x19146D,0x395436,0x2B3A25,0x1A8682,0x247F74,0x3931B3,0x5A9788,0x7C2C11,0x67173,0x1FDA2F,0x6ADF81,0x22AC],
+        Frb: [0x18D5EA,0xC6EA5,0x2F0791,0x5FE88A,0x30AA88,0x57AE4,0x210413,0x6DA1DB,0xA8B29,0x356757,0x498365,0x79FC9C,0x6015EC,0x2D9C41,0xB017E,0x406B31,0x32B8],
+
+
+    };
+
+    return ROM_FIELD_BLS383;
+};
+
+
+ROM_FIELD_BLS24 = function() {
+    "use strict";
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    var ROM_FIELD_BLS24 = {
+
+        // BLS24 Modulus
+        // Base Bits= 23
+
+        Modulus: [0x6152B,0x2CE94,0x6BE113,0x416986,0x2FFE2E,0x36D4C8,0x47172F,0x1945B7,0x5F068A,0xE6441,0x110186,0x4F0F9,0x33568E,0x4A0F2E,0x306EA0,0x173BF2,0x6E803F,0x735D8,0x3316EA,0x3C01E,0x555C0],
+        R2modp: [0x22D6FA,0x7AA299,0x4C307E,0x68E711,0x7DA4AE,0x383CC3,0x12048C,0x11B7D,0x3CA412,0x2CE421,0x4932AC,0x27A306,0x340B6A,0x666E,0x3F6575,0x2F823C,0xA0DE6,0x137EC5,0x37D4BC,0x48A54E,0x4C28B],
+        MConst: 0x15FE7D,
+        Fra: [0x796F1D,0x4E9577,0x6EB572,0x68637F,0x41FF8B,0x46E8D3,0x7A7898,0x7C72A4,0x248407,0x6E79D9,0x56499E,0x4EB47F,0x27CBD6,0x33C662,0x4E9746,0xC2798,0x397549,0x4A5B1B,0x5C90B6,0x3DCA73,0x4BBC8],
+        Frb: [0xCA60E,0x34391C,0x7D2BA0,0x590606,0x6DFEA2,0x6FEBF4,0x4C9E96,0x1CD312,0x3A8282,0x1FEA68,0x3AB7E7,0x363C79,0xB8AB7,0x1648CC,0x61D75A,0xB1459,0x350AF6,0x3CDABD,0x568633,0x45F5AA,0x99F7],
+
+    };
+
+    return ROM_FIELD_BLS24;
+};
+
+
+ROM_FIELD_BLS48 = function() {
+    "use strict";
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    var ROM_FIELD_BLS48 = {
+
+        // BLS48 Modulus
+        // Base Bits= 23
+
+        Modulus: [0x76AC0B,0x4C1FF9,0x67BBDB,0x5330EF,0x167009,0x450805,0x61C350,0x609BD4,0x76B2E,0x40410D,0x169054,0x353E01,0x141301,0x66F371,0x3B355A,0x6D4A85,0x36F405,0x28840A,0x454AB3,0x2B6433,0x29047A,0xB646E,0xBFF3F,0x68BEC2,0xF],
+        R2modp: [0x5F42C2,0x596E88,0x2ED8FA,0x15C970,0x2518B4,0x2A75E7,0x62CE53,0x431C50,0x3CF507,0x620E44,0xD6FCD,0x21A7D,0x1FDA3F,0x6A099,0x53487,0x53EEBF,0x54E2D0,0x48437D,0x2233D8,0x63296F,0x21EE21,0x611417,0x619D35,0x13A61A,0xB],
+        MConst: 0x5A805D,
+        Fra: [0x25BF89,0x79FB26,0x56F988,0x399A14,0x507EA3,0x77995,0x3EE83A,0x52ECA9,0x3E3474,0x5F1E13,0x2E7CB0,0x255F3D,0x3AE7F8,0x2E4EF6,0x3BDE94,0x7B05A,0x13C83C,0x7BF664,0x1FF27F,0x6FE082,0x3B36CE,0x138113,0x6E2002,0x4C5C03,0x2],
+        Frb: [0x25BF89,0x79FB26,0x56F988,0x399A14,0x507EA3,0x77995,0x3EE83A,0x52ECA9,0x3E3474,0x5F1E13,0x2E7CB0,0x255F3D,0x3AE7F8,0x2E4EF6,0x3BDE94,0x7B05A,0x13C83C,0x7BF664,0x1FF27F,0x6FE082,0x3B36CE,0x138113,0x6E2002,0x4C5C03,0x2],
+    };
+
+    return ROM_FIELD_BLS48;
+};
+
+
+ROM_FIELD_BLS381 = function() {
+    "use strict";
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    var ROM_FIELD_BLS381 = {
+
+        // BLS381 Modulus
+        // Base Bits= 23
+
+        Modulus: [0x7FAAAB,0x7FFFFF,0x7EE7FB,0xA9FFF,0x3FFFEB,0x4483D5,0x3DAC3D,0x186950,0x12BF67,0x9E70A,0x11DD2E,0x5D66BB,0x7B6434,0x496374,0x5FF9A6,0x8F51C,0x1A01],
+        R2modp: [0x40C6E6,0xE1A28,0x3D1C6C,0x6D2448,0x1BB111,0x4EAFA8,0x229C8C,0x4CEE55,0x46D2AD,0x7BA87C,0x708835,0x2413D1,0x6702E3,0x390116,0xD9E3F,0x4BD65C,0x9A3],
+        MConst: 0x7CFFFD,
+        Fra: [0x235FB8,0x6BDB24,0x76341D,0x1F3C09,0x6A53D6,0x389ECF,0x612EAE,0x1221EB,0x5F4F7B,0x7A797A,0x3F580F,0x6068F8,0x6B4202,0x784637,0x2EC199,0x69DF81,0x1904],
+        Frb: [0x5C4AF3,0x1424DB,0x8B3DE,0x6B63F6,0x55AC14,0xBE505,0x5C7D8F,0x64764,0x336FEC,0xF6D8F,0x52851E,0x7CFDC2,0x102231,0x511D3D,0x31380C,0x1F159B,0xFC],
+
+    };
+
+    return ROM_FIELD_BLS381;
+};
+
+
+ROM_FIELD_BLS461 = function() {
+    "use strict";
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    var ROM_FIELD_BLS461 = {
+
+        // BLS461 Modulus
+        // Base Bits= 23
+        Modulus: [0x2AAAAB, 0x155, 0x2AAAB0, 0x2AAA55, 0x55, 0x80004, 0x555FC0, 0x135548, 0x1CC00F, 0x3FF4B8, 0x2D0AA3, 0x58A424, 0x2CCA47, 0x465B17, 0x6F5BC7, 0xA49AF, 0x55D694, 0x34AAB4, 0x155535, 0x2AAAAA, 0x1],
+        R2modp: [0x621498, 0x3B585F, 0x41688, 0x6F780D, 0x17C239, 0x158D8A, 0x491A92, 0x737DF1, 0x22A06, 0x460263, 0x275FF2, 0x5496C3, 0x6D4AD2, 0x3A7B46, 0x3A6323, 0x1723B1, 0x76204B, 0x66FD26, 0x4E743E, 0x1BE66E, 0x0],
+        MConst: 0x7FFFFD,
+        Fra: [0x12A3A, 0x2F7F37, 0x3DC4, 0x52CCE2, 0x1C6308, 0xB7F14, 0x4381D4, 0x52D328, 0x58D45F, 0x359C90, 0x1DC2CC, 0x616582, 0x7C61EB, 0x6B11C5, 0x64341C, 0x421B30, 0x4DFEFA, 0x3CABC4, 0x12DFDA, 0x172028, 0x1],
+        Frb: [0x298071, 0x50821E, 0x2A6CEB, 0x57DD73, 0x639D4C, 0x7C80EF, 0x11DDEB, 0x408220, 0x43EBAF, 0xA5827, 0xF47D7, 0x773EA2, 0x30685B, 0x5B4951, 0xB27AA, 0x482E7F, 0x7D799, 0x77FEF0, 0x2755A, 0x138A82, 0x0],
+
+    };
+
+    return ROM_FIELD_BLS461;
+};
+
+
+ROM_FIELD_FP256BN = function() {
+    "use strict";
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    var ROM_FIELD_FP256BN = {
+
+        // FP256BN Modulus
+        // Base Bits= 24
+        Modulus: [0xD33013, 0x2DDBAE, 0x82D329, 0x12980A, 0xDC65FB, 0xA49F0C, 0x5EEE71, 0x46E5F2, 0xFCF0CD, 0xFFFFFF, 0xFFFF],
+        R2modp: [0x2F4801, 0xF779D1, 0x3E7F6E, 0xB42A3A, 0xC919C9, 0xC26C08, 0x1BB715, 0xCA2ED6, 0x54293E, 0xE578E, 0x78EA],
+        MConst: 0x37E5E5,
+        Fra: [0x943106, 0x328AF, 0x8F7476, 0x1E3AB2, 0xA17151, 0x67CF39, 0x8DDB08, 0x2D1A6E, 0x786F35, 0x7662CA, 0x3D61],
+        Frb: [0x3EFF0D, 0x2AB2FF, 0xF35EB3, 0xF45D57, 0x3AF4A9, 0x3CCFD3, 0xD11369, 0x19CB83, 0x848198, 0x899D35, 0xC29E],
+    };
+
+    return ROM_FIELD_FP256BN;
+};
+
+ROM_FIELD_FP512BN = function() {
+    "use strict";
+
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    var ROM_FIELD_FP512BN = {
+
+        // FP512BN Modulus
+        // Base Bits= 23
+        Modulus: [0x2DEF33, 0x501245, 0x1ED3AC, 0x7A6323, 0x255CE5, 0x7C322D, 0x2AC8DB, 0x4632EF, 0x18B8E4, 0x3D597D, 0x451B3C, 0x77A2A, 0x3C111B, 0x78177C, 0x32D4C1, 0x5D0EC, 0x7F01C6, 0x7FF3D8, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x3F],
+        R2modp: [0x23E65D, 0x575A37, 0x411CD0, 0x295FB3, 0x640669, 0x375C69, 0x92395, 0x738492, 0x780D6D, 0x1BCD9D, 0x417CAA, 0x2DC6FB, 0x7EACFB, 0x327043, 0x7F2FC7, 0xF268C, 0x73D733, 0x2147C9, 0x2ACCD3, 0x32EAF8, 0x3B2C1E, 0xD46A2, 0x30],
+        MConst: 0x4C5C05,
+        Fra: [0x373AB2, 0x2F63E9, 0x47D258, 0x101576, 0x1514F6, 0x503C2E, 0x34EF61, 0x4FB040, 0x2CBBB5, 0x553D0A, 0x63A7E2, 0x10341C, 0x48CF2E, 0x3564D7, 0x25BDE4, 0x50C529, 0x468B4E, 0x2D518F, 0x6DE46, 0x7C84AD, 0x1CF5BB, 0x5EE355, 0x7],
+        Frb: [0x76B481, 0x20AE5B, 0x570154, 0x6A4DAC, 0x1047EF, 0x2BF5FF, 0x75D97A, 0x7682AE, 0x6BFD2E, 0x681C72, 0x617359, 0x77460D, 0x7341EC, 0x42B2A4, 0xD16DD, 0x350BC3, 0x387677, 0x52A249, 0x7921B9, 0x37B52, 0x630A44, 0x211CAA, 0x38],
+
+    };
+
+    return ROM_FIELD_FP512BN;
+};
+
+
+ROM_FIELD_BN254 = function() {
+    "use strict";
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    var ROM_FIELD_BN254 = {
+
+        // BN254 Modulus
+        // Base Bits= 24
+        Modulus: [0x13, 0x0, 0x13A700, 0x0, 0x210000, 0x861, 0x800000, 0xBA344D, 0x1, 0x648240, 0x2523],
+        R2modp: [0x2F2AA7, 0x537047, 0xF8F174, 0xC3E364, 0xAB8C1C, 0x3C2035, 0x69549, 0x379287, 0x3BE629, 0x75617A, 0x1F47],
+        MConst: 0x9435E5,
+        Fra: [0x2A6DE9, 0xE6C06F, 0xC2E17D, 0x4D3F77, 0x97492, 0x953F85, 0x50A846, 0xB6499B, 0x2E7C8C, 0x761921, 0x1B37],
+        Frb: [0xD5922A, 0x193F90, 0x50C582, 0xB2C088, 0x178B6D, 0x6AC8DC, 0x2F57B9, 0x3EAB2, 0xD18375, 0xEE691E, 0x9EB],
+
+    };
+
+    return ROM_FIELD_BN254;
+};
+
+ROM_FIELD_BN254CX = function() {
+    "use strict";
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    var ROM_FIELD_BN254CX = {
+
+        // BN254CX Modulus
+        // Base Bits= 24
+        Modulus: [0x1B55B3, 0x23EF5C, 0xE1BE66, 0x18093E, 0x3FD6EE, 0x66D324, 0x647A63, 0xB0BDDF, 0x702A0D, 0x8, 0x2400],
+        R2modp: [0x8EE63D, 0x721FDE, 0xCC0891, 0x10C28B, 0xD4F5A, 0x4C18FB, 0x9036FA, 0x3F845F, 0xA507E4, 0x78EB29, 0x1587],
+        MConst: 0x789E85,
+        Fra: [0xC80EA3, 0x83355, 0x215BD9, 0xF173F8, 0x677326, 0x189868, 0x8AACA7, 0xAFE18B, 0x3A0164, 0x82FA6, 0x1359],
+        Frb: [0x534710, 0x1BBC06, 0xC0628D, 0x269546, 0xD863C7, 0x4E3ABB, 0xD9CDBC, 0xDC53, 0x3628A9, 0xF7D062, 0x10A6],
+    };
+
+    return ROM_FIELD_BN254CX;
+};
+
+ROM_FIELD_BRAINPOOL = function() {
+    "use strict";
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    var ROM_FIELD_BRAINPOOL = {
+
+        // Brainpool modulus
+        // Base Bits= 24
+        Modulus: [0x6E5377, 0x481D1F, 0x282013, 0xD52620, 0x3BF623, 0x8D726E, 0x909D83, 0x3E660A, 0xEEA9BC, 0x57DBA1, 0xA9FB],
+        R2modp: [0x35B819, 0xB03428, 0xECAF0F, 0x3854A4, 0x4A0ED5, 0x2421EA, 0xAA562C, 0xF9C45, 0xDDAE58, 0x4350FD, 0x52B8],
+        MConst: 0xFD89B9,
+
+    };
+    return ROM_FIELD_BRAINPOOL;
+};
+
+ROM_FIELD_C41417 = function() {
+    "use strict";
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+
+    var ROM_FIELD_C41417 = {
+
+        // C41417 modulus
+        // Base Bits= 2
+        Modulus: [0x3FFFEF, 0x3FFFFF, 0x3FFFFF, 0x3FFFFF, 0x3FFFFF, 0x3FFFFF, 0x3FFFFF, 0x3FFFFF, 0x3FFFFF, 0x3FFFFF, 0x3FFFFF, 0x3FFFFF, 0x3FFFFF, 0x3FFFFF, 0x3FFFFF, 0x3FFFFF, 0x3FFFFF, 0x3FFFFF, 0x3FFFF],
+        R2modp: [0x12100, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        MConst: 0x11,
+    };
+    return ROM_FIELD_C41417;
+};
+
+ROM_FIELD_GOLDILOCKS = function() {
+    "use strict";
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    var ROM_FIELD_GOLDILOCKS = {
+
+        // GOLDILOCKS modulus
+        // Base Bits= 23
+        Modulus: [0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7DFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FF],
+        R2modp: [0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC0000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        MConst: 0x1,
+    };
+    return ROM_FIELD_GOLDILOCKS;
+};
+
+ROM_FIELD_HIFIVE = function() {
+    "use strict";
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    var ROM_FIELD_HIFIVE = {
+
+        // HIFIVE modulus
+        // Base Bits= 23
+        Modulus: [0x7FFFFD, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x3FFF],
+        R2modp: [0x240000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        MConst: 0x3,
+    };
+    return ROM_FIELD_HIFIVE;
+};
+
+ROM_FIELD_NIST256 = function() {
+    "use strict";
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    var ROM_FIELD_NIST256 = {
+
+        // NIST256 Modulus
+        // Base Bits= 24
+        Modulus: [0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0x0, 0x0, 0x0, 0x0, 0x1, 0xFFFF00, 0xFFFF],
+        R2modp: [0x30000, 0x0, 0x0, 0xFFFF00, 0xFBFFFF, 0xFFFFFF, 0xFFFFFE, 0xFFFFFF, 0xFDFFFF, 0xFFFFFF, 0x4],
+        MConst: 0x1,
+
+    };
+    return ROM_FIELD_NIST256;
+};
+
+ROM_FIELD_NIST384 = function() {
+    "use strict";
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    var ROM_FIELD_NIST384 = {
+
+        // NIST384 modulus
+        // Base Bits= 23
+        Modulus: [0x7FFFFF, 0x1FF, 0x0, 0x0, 0x7FFFF0, 0x7FDFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0xFFFF],
+        R2modp: [0x4000, 0x0, 0x7FFFFE, 0x1FF, 0x80000, 0x0, 0x0, 0x7FC000, 0x3FFFFF, 0x0, 0x200, 0x20000, 0x0, 0x0, 0x0, 0x0, 0x0],
+        MConst: 0x1,
+
+    };
+    return ROM_FIELD_NIST384;
+};
+
+ROM_FIELD_NIST521 = function() {
+    "use strict";
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    var ROM_FIELD_NIST521 = {
+
+        // NIST521 modulus
+        // Base Bits= 23
+        Modulus: [0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFFFF, 0x7FFF],
+        R2modp: [0x10000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
+        MConst: 0x1,
+    };
+    return ROM_FIELD_NIST521;
+};
+
+
+ROM_FIELD_SECP256K1 = function() {
+    "use strict";
+    /* Fixed Data in ROM - Field and Curve parameters */
+
+    var ROM_FIELD_SECP256K1 = {
+
+        // SECP256K1 modulus
+        // Base Bits= 24
+        Modulus: [0xFFFC2F,0xFFFEFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFF],
+        R2modp: [0xA10000,0xE90,0x7A2,0x100,0x0,0x0,0x0,0x0,0x0,0x0,0x0],
+        MConst: 0x253531,
+    };
+    return ROM_FIELD_SECP256K1;
+};
diff --git a/version3/js/rsa.js b/version3/js/rsa.js
new file mode 100644
index 0000000..d06cee4
--- /dev/null
+++ b/version3/js/rsa.js
@@ -0,0 +1,515 @@
+/*
+    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.
+*/
+
+/* RSA API Functions */
+var RSA,
+    rsa_private_key,
+    rsa_public_key;
+
+RSA = function(ctx) {
+    "use strict";
+
+    var RSA = {
+        RFS: ctx.BIG.MODBYTES * ctx.FF.FFLEN,
+        SHA256: 32,
+        SHA384: 48,
+        SHA512: 64,
+
+        HASH_TYPE: 32,
+
+        /* SHAXXX identifier strings */
+        SHA256ID: [0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20],
+        SHA384ID: [0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30],
+        SHA512ID: [0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40],
+
+        bytestohex: function(b) {
+            var s = "",
+                len = b.length,
+                ch, i;
+
+            for (i = 0; i < len; i++) {
+                ch = b[i];
+                s += ((ch >>> 4) & 15).toString(16);
+                s += (ch & 15).toString(16);
+
+            }
+            return s;
+        },
+
+        bytestostring: function(b) {
+            var s = "",
+                i;
+
+            for (i = 0; i < b.length; i++) {
+                s += String.fromCharCode(b[i]);
+            }
+
+            return s;
+        },
+
+        stringtobytes: function(s) {
+            var b = [],
+                i;
+
+            for (i = 0; i < s.length; i++) {
+                b.push(s.charCodeAt(i));
+            }
+
+            return b;
+        },
+
+        hashit: function(sha, A, n) {
+            var R = [],
+                H;
+
+            if (sha == this.SHA256) {
+                H = new ctx.HASH256();
+
+                if (A != null) {
+                    H.process_array(A);
+                }
+
+                if (n >= 0) {
+                    H.process_num(n);
+                }
+
+                R = H.hash();
+            } else if (sha == this.SHA384) {
+                H = new ctx.HASH384();
+
+                if (A != null) {
+                    H.process_array(A);
+                }
+
+                if (n >= 0) {
+                    H.process_num(n);
+                }
+
+                R = H.hash();
+            } else if (sha == this.SHA512) {
+                H = new ctx.HASH512();
+
+                if (A != null) {
+                    H.process_array(A);
+                }
+
+                if (n >= 0) {
+                    H.process_num(n);
+                }
+
+                R = H.hash();
+            }
+
+            return R;
+        },
+
+        KEY_PAIR: function(rng, e, PRIV, PUB) { /* IEEE1363 A16.11/A16.12 more or less */
+            var n = PUB.n.length >> 1,
+                t = new ctx.FF(n),
+                p1 = new ctx.FF(n),
+                q1 = new ctx.FF(n);
+
+            for (;;) {
+                PRIV.p.random(rng);
+
+                while (PRIV.p.lastbits(2) != 3) {
+                    PRIV.p.inc(1);
+                }
+
+                while (!ctx.FF.prime(PRIV.p, rng)) {
+                    PRIV.p.inc(4);
+                }
+
+                p1.copy(PRIV.p);
+                p1.dec(1);
+
+                if (p1.cfactor(e)) {
+                    continue;
+                }
+
+                break;
+            }
+
+            for (;;) {
+                PRIV.q.random(rng);
+
+                while (PRIV.q.lastbits(2) != 3) {
+                    PRIV.q.inc(1);
+                }
+
+                while (!ctx.FF.prime(PRIV.q, rng)) {
+                    PRIV.q.inc(4);
+                }
+
+                q1.copy(PRIV.q);
+                q1.dec(1);
+
+                if (q1.cfactor(e)) {
+                    continue;
+                }
+
+                break;
+            }
+
+            PUB.n = ctx.FF.mul(PRIV.p, PRIV.q);
+            PUB.e = e;
+
+            t.copy(p1);
+            t.shr();
+            PRIV.dp.set(e);
+            PRIV.dp.invmodp(t);
+            if (PRIV.dp.parity() === 0) {
+                PRIV.dp.add(t);
+            }
+            PRIV.dp.norm();
+
+            t.copy(q1);
+            t.shr();
+            PRIV.dq.set(e);
+            PRIV.dq.invmodp(t);
+            if (PRIV.dq.parity() === 0) {
+                PRIV.dq.add(t);
+            }
+            PRIV.dq.norm();
+
+            PRIV.c.copy(PRIV.p);
+            PRIV.c.invmodp(PRIV.q);
+
+            return;
+        },
+
+        /* Mask Generation Function */
+        MGF1: function(sha, Z, olen, K) {
+            var hlen = sha,
+                B = [],
+                k = 0,
+                counter, cthreshold, i;
+
+            for (i = 0; i < K.length; i++) {
+                K[i] = 0;
+            }
+
+            cthreshold = Math.floor(olen / hlen);
+            if (olen % hlen !== 0) {
+                cthreshold++;
+            }
+
+            for (counter = 0; counter < cthreshold; counter++) {
+                B = this.hashit(sha, Z, counter);
+
+                if (k + hlen > olen) {
+                    for (i = 0; i < olen % hlen; i++) {
+                        K[k++] = B[i];
+                    }
+                } else {
+                    for (i = 0; i < hlen; i++) {
+                        K[k++] = B[i];
+                    }
+                }
+            }
+        },
+
+        PKCS15: function(sha, m, w) {
+            var olen = ctx.FF.FF_BITS / 8,
+                hlen = sha,
+                idlen = 19,
+                H, i, j;
+
+            if (olen < idlen + hlen + 10) {
+                return false;
+            }
+
+            H = this.hashit(sha, m, -1);
+
+            for (i = 0; i < w.length; i++) {
+                w[i] = 0;
+            }
+
+            i = 0;
+            w[i++] = 0;
+            w[i++] = 1;
+            for (j = 0; j < olen - idlen - hlen - 3; j++) {
+                w[i++] = 0xFF;
+            }
+            w[i++] = 0;
+
+            if (hlen == this.SHA256) {
+                for (j = 0; j < idlen; j++) {
+                    w[i++] = this.SHA256ID[j];
+                }
+            } else if (hlen == this.SHA384) {
+                for (j = 0; j < idlen; j++) {
+                    w[i++] = this.SHA384ID[j];
+                }
+            } else if (hlen == this.SHA512) {
+                for (j = 0; j < idlen; j++) {
+                    w[i++] = this.SHA512ID[j];
+                }
+            }
+
+            for (j = 0; j < hlen; j++) {
+                w[i++] = H[j];
+            }
+
+            return true;
+        },
+
+        /* OAEP Message Encoding for Encryption */
+        OAEP_ENCODE: function(sha, m, rng, p) {
+            var olen = RSA.RFS - 1,
+                mlen = m.length,
+                SEED = [],
+                DBMASK = [],
+                f = [],
+                hlen,
+                seedlen,
+                slen,
+                i, d, h;
+
+            seedlen = hlen = sha;
+
+            if (mlen > olen - hlen - seedlen - 1) {
+                return null;
+            }
+
+            h = this.hashit(sha, p, -1);
+            for (i = 0; i < hlen; i++) {
+                f[i] = h[i];
+            }
+
+            slen = olen - mlen - hlen - seedlen - 1;
+
+            for (i = 0; i < slen; i++) {
+                f[hlen + i] = 0;
+            }
+            f[hlen + slen] = 1;
+            for (i = 0; i < mlen; i++) {
+                f[hlen + slen + 1 + i] = m[i];
+            }
+
+            for (i = 0; i < seedlen; i++) {
+                SEED[i] = rng.getByte();
+            }
+            this.MGF1(sha, SEED, olen - seedlen, DBMASK);
+
+            for (i = 0; i < olen - seedlen; i++) {
+                DBMASK[i] ^= f[i];
+            }
+            this.MGF1(sha, DBMASK, seedlen, f);
+
+            for (i = 0; i < seedlen; i++) {
+                f[i] ^= SEED[i];
+            }
+
+            for (i = 0; i < olen - seedlen; i++) {
+                f[i + seedlen] = DBMASK[i];
+            }
+
+            /* pad to length RFS */
+            d = 1;
+            for (i = RSA.RFS - 1; i >= d; i--) {
+                f[i] = f[i - d];
+            }
+            for (i = d - 1; i >= 0; i--) {
+                f[i] = 0;
+            }
+
+            return f;
+        },
+
+        /* OAEP Message Decoding for Decryption */
+        OAEP_DECODE: function(sha, p, f) {
+            var olen = RSA.RFS - 1,
+                SEED = [],
+                CHASH = [],
+                DBMASK = [],
+                comp,
+                hlen,
+                seedlen,
+                x, t, d, i, k, h, r;
+
+            seedlen = hlen = sha;
+
+            if (olen < seedlen + hlen + 1) {
+                return null;
+            }
+
+            for (i = 0; i < olen - seedlen; i++) {
+                DBMASK[i] = 0;
+            }
+
+            if (f.length < RSA.RFS) {
+                d = RSA.RFS - f.length;
+                for (i = RSA.RFS - 1; i >= d; i--) {
+                    f[i] = f[i - d];
+                }
+                for (i = d - 1; i >= 0; i--) {
+                    f[i] = 0;
+                }
+            }
+
+            h = this.hashit(sha, p, -1);
+            for (i = 0; i < hlen; i++) {
+                CHASH[i] = h[i];
+            }
+
+            x = f[0];
+
+            for (i = seedlen; i < olen; i++) {
+                DBMASK[i - seedlen] = f[i + 1];
+            }
+
+            this.MGF1(sha, DBMASK, seedlen, SEED);
+            for (i = 0; i < seedlen; i++) {
+                SEED[i] ^= f[i + 1];
+            }
+            this.MGF1(sha, SEED, olen - seedlen, f);
+            for (i = 0; i < olen - seedlen; i++) {
+                DBMASK[i] ^= f[i];
+            }
+
+            comp = true;
+            for (i = 0; i < hlen; i++) {
+                if (CHASH[i] != DBMASK[i]) {
+                    comp = false;
+                }
+            }
+
+            for (i = 0; i < olen - seedlen - hlen; i++) {
+                DBMASK[i] = DBMASK[i + hlen];
+            }
+
+            for (i = 0; i < hlen; i++) {
+                SEED[i] = CHASH[i] = 0;
+            }
+
+            for (k = 0;; k++) {
+                if (k >= olen - seedlen - hlen) {
+                    return null;
+                }
+
+                if (DBMASK[k] !== 0) {
+                    break;
+                }
+            }
+
+            t = DBMASK[k];
+
+            if (!comp || x !== 0 || t != 0x01) {
+                for (i = 0; i < olen - seedlen; i++) {
+                    DBMASK[i] = 0;
+                }
+                return null;
+            }
+
+            r = [];
+
+            for (i = 0; i < olen - seedlen - hlen - k - 1; i++) {
+                r[i] = DBMASK[i + k + 1];
+            }
+
+            for (i = 0; i < olen - seedlen; i++) {
+                DBMASK[i] = 0;
+            }
+
+            return r;
+        },
+
+        /* destroy the Private Key structure */
+        PRIVATE_KEY_KILL: function(PRIV) {
+            PRIV.p.zero();
+            PRIV.q.zero();
+            PRIV.dp.zero();
+            PRIV.dq.zero();
+            PRIV.c.zero();
+        },
+
+        /* RSA encryption with the public key */
+        ENCRYPT: function(PUB, F, G) {
+            var n = PUB.n.getlen(),
+                f = new ctx.FF(n);
+
+            ctx.FF.fromBytes(f, F);
+
+            f.power(PUB.e, PUB.n);
+
+            f.toBytes(G);
+        },
+
+        /* RSA decryption with the private key */
+        DECRYPT: function(PRIV, G, F) {
+            var n = PRIV.p.getlen(),
+                g = new ctx.FF(2 * n),
+                jp, jq, t;
+
+            ctx.FF.fromBytes(g, G);
+
+            jp = g.dmod(PRIV.p);
+            jq = g.dmod(PRIV.q);
+
+            jp.skpow(PRIV.dp, PRIV.p);
+            jq.skpow(PRIV.dq, PRIV.q);
+
+            g.zero();
+            g.dscopy(jp);
+            jp.mod(PRIV.q);
+            if (ctx.FF.comp(jp, jq) > 0) {
+                jq.add(PRIV.q);
+            }
+            jq.sub(jp);
+            jq.norm();
+
+            t = ctx.FF.mul(PRIV.c, jq);
+            jq = t.dmod(PRIV.q);
+
+            t = ctx.FF.mul(jq, PRIV.p);
+            g.add(t);
+            g.norm();
+
+            g.toBytes(F);
+        }
+    };
+
+    return RSA;
+};
+
+rsa_private_key = function(ctx) {
+    "use strict";
+
+    var rsa_private_key = function(n) {
+        this.p = new ctx.FF(n);
+        this.q = new ctx.FF(n);
+        this.dp = new ctx.FF(n);
+        this.dq = new ctx.FF(n);
+        this.c = new ctx.FF(n);
+    };
+
+    return rsa_private_key;
+};
+
+rsa_public_key = function(ctx) {
+    "use strict";
+
+    var rsa_public_key = function(m) {
+        this.e = 0;
+        this.n = new ctx.FF(m);
+    };
+
+    return rsa_public_key;
+};
diff --git a/version3/js/sha3.js b/version3/js/sha3.js
new file mode 100644
index 0000000..9380736
--- /dev/null
+++ b/version3/js/sha3.js
@@ -0,0 +1,264 @@
+/*
+    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.
+*/
+
+/*
+ * Implementation of the Secure Hashing Algorithm SHA-3
+
+ * Generates a message digest. It should be impossible to come
+ * come up with two messages that hash to the same value ("collision free").
+ *
+ * For use with byte-oriented messages only.
+ */
+
+var SHA3 = function(ctx) {
+    "use strict";
+
+    var SHA3 = function(olen) {
+        this.length = 0;
+        this.rate = 0;
+        this.len = 0;
+        this.S = [];
+        this.init(olen);
+    };
+
+    SHA3.prototype = {
+
+        transform: function() {
+            var C = [],
+                D = [],
+                B = [],
+                i, j, k;
+
+            for (k = 0; k < SHA3.ROUNDS; k++) {
+                C[0] = new ctx.UInt64(this.S[0][0].top ^ this.S[0][1].top ^ this.S[0][2].top ^ this.S[0][3].top ^ this.S[0][4].top, this.S[0][0].bot ^ this.S[0][1].bot ^ this.S[0][2].bot ^ this.S[0][3].bot ^ this.S[0][4].bot);
+                C[1] = new ctx.UInt64(this.S[1][0].top ^ this.S[1][1].top ^ this.S[1][2].top ^ this.S[1][3].top ^ this.S[1][4].top, this.S[1][0].bot ^ this.S[1][1].bot ^ this.S[1][2].bot ^ this.S[1][3].bot ^ this.S[1][4].bot);
+                C[2] = new ctx.UInt64(this.S[2][0].top ^ this.S[2][1].top ^ this.S[2][2].top ^ this.S[2][3].top ^ this.S[2][4].top, this.S[2][0].bot ^ this.S[2][1].bot ^ this.S[2][2].bot ^ this.S[2][3].bot ^ this.S[2][4].bot);
+                C[3] = new ctx.UInt64(this.S[3][0].top ^ this.S[3][1].top ^ this.S[3][2].top ^ this.S[3][3].top ^ this.S[3][4].top, this.S[3][0].bot ^ this.S[3][1].bot ^ this.S[3][2].bot ^ this.S[3][3].bot ^ this.S[3][4].bot);
+                C[4] = new ctx.UInt64(this.S[4][0].top ^ this.S[4][1].top ^ this.S[4][2].top ^ this.S[4][3].top ^ this.S[4][4].top, this.S[4][0].bot ^ this.S[4][1].bot ^ this.S[4][2].bot ^ this.S[4][3].bot ^ this.S[4][4].bot);
+
+                D[0] = SHA3.xor(C[4], SHA3.rotl(C[1], 1));
+                D[1] = SHA3.xor(C[0], SHA3.rotl(C[2], 1));
+                D[2] = SHA3.xor(C[1], SHA3.rotl(C[3], 1));
+                D[3] = SHA3.xor(C[2], SHA3.rotl(C[4], 1));
+                D[4] = SHA3.xor(C[3], SHA3.rotl(C[0], 1));
+
+                for (i = 0; i < 5; i++) {
+                    B[i] = [];
+                    for (j = 0; j < 5; j++) {
+                        B[i][j] = new ctx.UInt64(0, 0);
+                        this.S[i][j] = SHA3.xor(this.S[i][j], D[i]);
+                    }
+                }
+
+                B[0][0] = this.S[0][0].copy();
+                B[1][3] = SHA3.rotl(this.S[0][1], 36);
+                B[2][1] = SHA3.rotl(this.S[0][2], 3);
+                B[3][4] = SHA3.rotl(this.S[0][3], 41);
+                B[4][2] = SHA3.rotl(this.S[0][4], 18);
+
+                B[0][2] = SHA3.rotl(this.S[1][0], 1);
+                B[1][0] = SHA3.rotl(this.S[1][1], 44);
+                B[2][3] = SHA3.rotl(this.S[1][2], 10);
+                B[3][1] = SHA3.rotl(this.S[1][3], 45);
+                B[4][4] = SHA3.rotl(this.S[1][4], 2);
+
+                B[0][4] = SHA3.rotl(this.S[2][0], 62);
+                B[1][2] = SHA3.rotl(this.S[2][1], 6);
+                B[2][0] = SHA3.rotl(this.S[2][2], 43);
+                B[3][3] = SHA3.rotl(this.S[2][3], 15);
+                B[4][1] = SHA3.rotl(this.S[2][4], 61);
+
+                B[0][1] = SHA3.rotl(this.S[3][0], 28);
+                B[1][4] = SHA3.rotl(this.S[3][1], 55);
+                B[2][2] = SHA3.rotl(this.S[3][2], 25);
+                B[3][0] = SHA3.rotl(this.S[3][3], 21);
+                B[4][3] = SHA3.rotl(this.S[3][4], 56);
+
+                B[0][3] = SHA3.rotl(this.S[4][0], 27);
+                B[1][1] = SHA3.rotl(this.S[4][1], 20);
+                B[2][4] = SHA3.rotl(this.S[4][2], 39);
+                B[3][2] = SHA3.rotl(this.S[4][3], 8);
+                B[4][0] = SHA3.rotl(this.S[4][4], 14);
+
+                for (i = 0; i < 5; i++) {
+                    for (j = 0; j < 5; j++) {
+                        this.S[i][j] = SHA3.xor(B[i][j], SHA3.and(SHA3.not(B[(i + 1) % 5][j]), B[(i + 2) % 5][j]));
+                    }
+                }
+
+                this.S[0][0] = SHA3.xor(this.S[0][0], SHA3.RC[k]);
+            }
+        },
+
+        /* Initialise Hash function */
+        init: function(olen) { /* initialise */
+            var i, j;
+            for (i = 0; i < 5; i++) {
+                this.S[i] = [];
+                for (j = 0; j < 5; j++) {
+                    this.S[i][j] = new ctx.UInt64(0, 0);
+                }
+            }
+            this.length = 0;
+            this.len = olen;
+            this.rate = 200 - 2 * olen;
+        },
+
+        /* process a single byte */
+        process: function(byt) { /* process the next message byte */
+            var i, j, k, b, cnt, el;
+
+            cnt = (this.length % this.rate);
+            b = cnt % 8;
+            cnt >>= 3;
+            i = cnt % 5;
+            j = Math.floor(cnt / 5); /* process by columns! */
+
+            el = new ctx.UInt64(0, byt);
+            for (k = 0; k < b; k++) {
+                el.shlb();
+            }
+            this.S[i][j] = SHA3.xor(this.S[i][j], el);
+
+            this.length++;
+            if ((this.length % this.rate) == 0) {
+                this.transform();
+            }
+        },
+
+        /* squeeze the sponge */
+        squeeze: function(buff, olen) {
+            var done,
+                m = 0,
+                i, j, k, el;
+
+            /* extract by columns */
+            done = false;
+
+            for (;;) {
+                for (j = 0; j < 5; j++) {
+                    for (i = 0; i < 5; i++) {
+                        el = this.S[i][j].copy();
+                        for (k = 0; k < 8; k++) {
+                            buff[m++] = (el.bot & 0xff);
+                            if (m >= olen || (m % this.rate) == 0) {
+                                done = true;
+                                break;
+                            }
+                            el = SHA3.rotl(el, 56);
+                        }
+
+                        if (done) {
+                            break;
+                        }
+                    }
+
+                    if (done) {
+                        break;
+                    }
+                }
+
+                if (m >= olen) {
+                    break;
+                }
+
+                done = false;
+                this.transform();
+            }
+        },
+
+        hash: function(buff) { /* pad message and finish - supply digest */
+            var q = this.rate - (this.length % this.rate);
+            if (q == 1) {
+                this.process(0x86);
+            } else {
+                this.process(0x06); /* 0x06 for SHA-3 */
+                while (this.length % this.rate != this.rate - 1) {
+                    this.process(0x00);
+                }
+                this.process(0x80); /* this will force a final transform */
+            }
+            this.squeeze(buff, this.len);
+        },
+
+        shake: function(buff, olen) { /* pad message and finish - supply digest */
+            var q = this.rate - (this.length % this.rate);
+            if (q == 1) {
+                this.process(0x9f);
+            } else {
+                this.process(0x1f); /* 0x06 for SHA-3 */
+                while (this.length % this.rate != this.rate - 1) {
+                    this.process(0x00);
+                }
+                this.process(0x80); /* this will force a final transform */
+            }
+            this.squeeze(buff, olen);
+        }
+    };
+
+    /* static functions */
+    SHA3.rotl = function(x, n) {
+        if (n == 0) {
+            return x;
+        }
+
+        if (n < 32) {
+            return new ctx.UInt64((x.top << n) | (x.bot >>> (32 - n)), (x.bot << n) | (x.top >>> (32 - n)));
+        } else {
+            return new ctx.UInt64((x.bot << (n - 32)) | (x.top >>> (64 - n)), (x.top << (n - 32)) | (x.bot >>> (64 - n)));
+        }
+    };
+
+    SHA3.xor = function(a, b) {
+        return new ctx.UInt64(a.top ^ b.top, a.bot ^ b.bot);
+    };
+
+    SHA3.and = function(a, b) {
+        return new ctx.UInt64(a.top & b.top, a.bot & b.bot);
+    };
+
+    SHA3.not = function(a) {
+        return new ctx.UInt64(~a.top, ~a.bot);
+    };
+
+    /* constants */
+    SHA3.ROUNDS = 24;
+    SHA3.HASH224 = 28;
+    SHA3.HASH256 = 32;
+    SHA3.HASH384 = 48;
+    SHA3.HASH512 = 64;
+    SHA3.SHAKE128 = 16;
+    SHA3.SHAKE256 = 32;
+
+    SHA3.RC = [new ctx.UInt64(0x00000000, 0x00000001), new ctx.UInt64(0x00000000, 0x00008082),
+        new ctx.UInt64(0x80000000, 0x0000808A), new ctx.UInt64(0x80000000, 0x80008000),
+        new ctx.UInt64(0x00000000, 0x0000808B), new ctx.UInt64(0x00000000, 0x80000001),
+        new ctx.UInt64(0x80000000, 0x80008081), new ctx.UInt64(0x80000000, 0x00008009),
+        new ctx.UInt64(0x00000000, 0x0000008A), new ctx.UInt64(0x00000000, 0x00000088),
+        new ctx.UInt64(0x00000000, 0x80008009), new ctx.UInt64(0x00000000, 0x8000000A),
+        new ctx.UInt64(0x00000000, 0x8000808B), new ctx.UInt64(0x80000000, 0x0000008B),
+        new ctx.UInt64(0x80000000, 0x00008089), new ctx.UInt64(0x80000000, 0x00008003),
+        new ctx.UInt64(0x80000000, 0x00008002), new ctx.UInt64(0x80000000, 0x00000080),
+        new ctx.UInt64(0x00000000, 0x0000800A), new ctx.UInt64(0x80000000, 0x8000000A),
+        new ctx.UInt64(0x80000000, 0x80008081), new ctx.UInt64(0x80000000, 0x00008080),
+        new ctx.UInt64(0x00000000, 0x80000001), new ctx.UInt64(0x80000000, 0x80008008),
+    ];
+
+    return SHA3;
+};
diff --git a/version3/js/uint64.js b/version3/js/uint64.js
new file mode 100644
index 0000000..4236cbe
--- /dev/null
+++ b/version3/js/uint64.js
@@ -0,0 +1,61 @@
+/*
+    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.
+*/
+
+/* rudimentary unsigned 64-bit type for SHA384 and SHA512 */
+
+var UInt64 = function() {
+    "use strict";
+
+    var UInt64 = function(top, bot) {
+        this.top = top;
+        this.bot = bot;
+    };
+
+    UInt64.prototype = {
+        add: function(y) {
+            var t = (this.bot >>> 0) + (y.bot >>> 0),
+                low = t >>> 0,
+                high = (this.top >>> 0) + (y.top >>> 0);
+
+            this.bot = low;
+
+            if (low != t) {
+                this.top = (high + 1) >>> 0;
+            } else {
+                this.top = high;
+            }
+
+            return this;
+        },
+
+        copy: function() {
+            var r = new UInt64(this.top, this.bot);
+            return r;
+        },
+
+        shlb: function() {
+            var t = this.bot >>> 24;
+            this.top = t + (this.top << 8);
+            this.bot <<= 8;
+            return this;
+        }
+    };
+
+    return UInt64;
+};
diff --git a/version3/python/big.py b/version3/python/big.py
new file mode 100644
index 0000000..280db1c
--- /dev/null
+++ b/version3/python/big.py
@@ -0,0 +1,159 @@
+
+#
+# Number Theoretic functions
+# M Scott August 2013
+#
+
+import math
+import types
+import random
+
+from XXX import curve
+
+
+def to_bytes(b):
+    return b.to_bytes(curve.EFS, byteorder='big')
+
+
+def from_bytes(B):
+    return int.from_bytes(B, byteorder='big')
+
+# extract i-th bit
+
+
+def bit(k, i):
+    if i == 0:
+        return k & 1
+    return ((k >> i) & 1)
+# gcd
+
+
+def gcd(x, y):
+    a = x
+    b = y
+    while b != 0:
+        a, b = b, a % b
+    return a
+
+# inverse mod prime p
+
+
+def invmodp(a, p):
+    n = p
+    x = a % n
+    kn = n
+    if x < 0:
+        x += n
+    if gcd(x, n) != 1:
+        return 0
+    a = 1
+    la = 0
+    while x > 1:
+        q, r = divmod(n, x)
+        t = la - a * q
+        la = a
+        a = t
+        n = x
+        x = r
+    if a < 0:
+        a += kn
+    return a
+
+# Modular arithmetic
+
+
+def modmul(a1, b1, p):
+
+    a = a1 % p
+    b = b1 % p
+
+    if a < 0:
+        a += p
+    if b < 0:
+        b += p
+    return a * b % p
+
+
+def modadd(a, b, p):
+    c = a + b
+    if c >= p:
+        c -= p
+    return c
+
+
+def modsub(a, b, p):
+    c = a - b
+    if c < 0:
+        c += p
+    return c
+
+
+def moddiv(a, b, p):
+    i = invmodp(b, p)
+    if i != 0:
+        return modmul(a, i, p)
+    return 0
+
+# modular square root. Fails spectacularly if p!=3 mod 4
+
+
+def sqrtmodp(a, p):
+    if p % 4 == 3:
+        return pow(a, (p + 1) // 4, p)
+
+    if p % 8 == 5:
+        b = (p - 5) / 8
+        i = a * 2
+        v = pow(i, b, p)
+        i = modmul(i, v, p)
+        i = modmul(i, v, p)
+        i -= 1
+        r = modmul(a, v, p)
+        r = modmul(r, i, p)
+        return r
+
+    return 0
+
+
+# chinese remainder theorem
+
+
+def crt(rp, p, rq, q):
+    c = inverse(p, q)
+    t = modmult(c, rq - rp, q)
+    return t * p + rp
+
+# find jacobi symbol for (x/p). Only defined for
+# positive x and p, p odd. Otherwise returns 0
+
+
+def jacobi(a, p):
+    if a < 1 or p < 2 or p % 2 == 0:
+        return 0
+    n = p
+    x = a % n
+    m = 0
+    while n > 1:
+        if x == 0:
+            return 0
+        n8 = n % 8
+        k = 0
+        while x % 2 == 0:
+            k += 1
+            x //= 2
+        if k % 2 == 1:
+            m += (n8 * n8 - 1) // 8
+        m += (n8 - 1) * (x % 4 - 1) // 4
+        t = n
+        t %= x
+        n = x
+        x = t
+        m %= 2
+    if m == 0:
+        return 1
+    else:
+        return -1
+
+
+def rand(m):
+    return random.SystemRandom().randint(2, m - 1)
diff --git a/version3/python/bls381.py b/version3/python/bls381.py
new file mode 100644
index 0000000..c646eab
--- /dev/null
+++ b/version3/python/bls381.py
@@ -0,0 +1,40 @@
+# BLS381 curve constants
+
+from constants import *
+
+SHA = 'sha256'   # hash type to use with this curve
+EFS = 48   # Elliptic curve Field Size in bytes
+CurveType = WEIERSTRASS
+
+SexticTwist = M_TYPE
+SignOfX = NEGATIVEX
+PairingFriendly = BLS
+
+x = 0xd201000000010000
+
+if SignOfX == NEGATIVEX:
+    p = (x**6 + 2 * x**5 - 2 * x**3 - x + 1) // 3
+    t = -x + 1
+else:
+    p = (x**6 - 2 * x**5 + 2 * x**3 + x + 1) // 3
+    t = x + 1
+
+r = x * x * x * x - x * x + 1
+
+# elliptic curve
+A = 0
+B = 4
+
+# generator point on G1
+Gx = 0x17F1D3A73197D7942695638C4FA9AC0FC3688C4F9774B905A14E3A3F171BAC586C55E83FF97A1AEFFB3AF00ADB22C6BB
+Gy = 0x8B3F481E3AAA0F1A09E30ED741D8AE4FCF5E095D5D00AF600DB18CB2C04B3EDD03CC744A2888AE40CAA232946C5E7E1
+
+# Frobenius constant
+Fra = 0x1904D3BF02BB0667C231BEB4202C0D1F0FD603FD3CBD5F4F7B2443D784BAB9C4F67EA53D63E7813D8D0775ED92235FB8
+Frb = 0xFC3E2B36C4E03288E9E902231F9FB854A14787B6C7B36FEC0C8EC971F63C5F282D5AC14D6C7EC22CF78A126DDC4AF3
+
+# Generator point on G2
+Pxa = 0x24AA2B2F08F0A91260805272DC51051C6E47AD4FA403B02B4510B647AE3D1770BAC0326A805BBEFD48056C8C121BDB8
+Pxb = 0x13E02B6052719F607DACD3A088274F65596BD0D09920B61AB5DA61BBDC7F5049334CF11213945D57E5AC7D055D042B7E
+Pya = 0xCE5D527727D6E118CC9CDC6DA2E351AADFD9BAA8CBDD3A76D429A695160D12C923AC9CC3BACA289E193548608B82801
+Pyb = 0x606C4A02EA734CC32ACD2B02BC28B99CB3E287E85A763AF267492AB572E99AB3F370D275CEC1DA1AAA9075FF05F79BE
diff --git a/version3/python/bls383.py b/version3/python/bls383.py
new file mode 100644
index 0000000..2dd1b82
--- /dev/null
+++ b/version3/python/bls383.py
@@ -0,0 +1,40 @@
+# BLS383 curve constants
+
+from constants import *
+
+SHA = 'sha256'   # hash type to use with this curve
+EFS = 48   # Elliptic curve Field Size in bytes
+CurveType = WEIERSTRASS
+
+SexticTwist = M_TYPE
+SignOfX = POSITIVEX
+PairingFriendly = BLS
+
+x = 0x10008000001001200
+
+if SignOfX == NEGATIVEX:
+    p = (x**6 + 2 * x**5 - 2 * x**3 - x + 1) // 3
+    t = -x + 1
+else:
+    p = (x**6 - 2 * x**5 + 2 * x**3 + x + 1) // 3
+    t = x + 1
+
+r = x * x * x * x - x * x + 1
+
+# elliptic curve
+A = 0
+B = 15
+
+# generator point on G1
+Gx = 0x41FCBA55B979ECE4E3835F4052DDB050F31D9F76B081F42C2F87BAD84AF1E3445C55DBF083F4770478C4773908734573
+Gy = 0x68F167274CFB300024AE9CDC31C46D99D0DADC66BB6449107530A94ADEB4D2DDE57D49EC87F98FD212D165E8003F224
+
+# Frobenius constant
+Fra = 0x22ACD5BF027F68BC338B9FC2C11B52F10E4C6CD23FBA1A868256744AE550D8C8A3693480FE6773E01852D72D3311DAC1
+Frb = 0x32B880D6622C05F96CE20E015ECF3F939260D95AB3AB8A8B29DB43B684104C2BD7230AA88BFD114BC1E446375298D5EA
+
+# Generator point on G2
+Pxa = 0x634D22407EC03E8C07990967CB1E746432501C852D5725BD47F1C90F562572EE81FDAB6795D1D3E143CB3B62D7F2D86
+Pxb = 0x300D7800600164BAF37A7717288361DD24F498ED9D05CC89DFD98BA88E92D5D75B54AB28D57FE60DEFD9E41EC452DE15
+Pya = 0x33792CF93D225347C949D8573FE6347B6E990ED673C99B3E689783ACA913A2E75B49EDE4F20D61965C68F0BB9408CB41
+Pyb = 0x20E5247DD2CD8C6B24EE7BA7D15A7AE001CE0D446B3EFA8F7AF0B2F449F7BC98B0143CB0DE6224863AD846437F479093
diff --git a/version3/python/bn254.py b/version3/python/bn254.py
new file mode 100644
index 0000000..620c339
--- /dev/null
+++ b/version3/python/bn254.py
@@ -0,0 +1,38 @@
+# BN254 curve constants
+
+from constants import *
+
+SHA = 'sha256'   # hash type to use with this curve
+EFS = 32   # Elliptic curve Field Size in bytes
+CurveType = WEIERSTRASS
+
+SexticTwist = D_TYPE
+SignOfX = NEGATIVEX
+PairingFriendly = BN
+
+x = 0x4080000000000001
+if SignOfX == NEGATIVEX:
+    p = 36 * x * x * x * x - 36 * x * x * x + 24 * x * x - 6 * x + 1
+else:
+    p = 36 * x * x * x * x + 36 * x * x * x + 24 * x * x + 6 * x + 1
+
+t = 6 * x * x + 1
+r = p + 1 - t
+
+# elliptic curve
+A = 0
+B = 2
+
+# generator point on G1
+Gx = p - 1
+Gy = 1
+
+# Frobenius constant
+Fra = 0x1B377619212E7C8CB6499B50A846953F850974924D3F77C2E17DE6C06F2A6DE9
+Frb = 0x9EBEE691ED1837503EAB22F57B96AC8DC178B6DB2C08850C582193F90D5922A
+
+# Generator point on G2
+Pxa = 0x61A10BB519EB62FEB8D8C7E8C61EDB6A4648BBB4898BF0D91EE4224C803FB2B
+Pxb = 0x516AAF9BA737833310AA78C5982AA5B1F4D746BAE3784B70D8C34C1E7D54CF3
+Pya = 0x21897A06BAF93439A90E096698C822329BD0AE6BDBE09BD19F0E07891CD2B9A
+Pyb = 0xEBB2B0E7C8B15268F6D4456F5F38D37B09006FFD739C9578A2D1AEC6B3ACE9B
diff --git a/version3/python/bn254cx.py b/version3/python/bn254cx.py
new file mode 100644
index 0000000..9fcc487
--- /dev/null
+++ b/version3/python/bn254cx.py
@@ -0,0 +1,39 @@
+# BN254 curve constants
+
+from constants import *
+
+SHA = 'sha256'   # hash type to use with this curve
+EFS = 32   # Elliptic curve Field Size in bytes
+CurveType = WEIERSTRASS
+
+SexticTwist = D_TYPE
+SignOfX = NEGATIVEX
+PairingFriendly = BN
+
+x = 0x4000000003C012B1
+if SignOfX == NEGATIVEX:
+    p = 36 * x * x * x * x - 36 * x * x * x + 24 * x * x - 6 * x + 1
+else:
+    p = 36 * x * x * x * x + 36 * x * x * x + 24 * x * x + 6 * x + 1
+
+t = 6 * x * x + 1
+r = p + 1 - t
+
+# elliptic curve
+A = 0
+B = 2
+
+# generator point on G1
+Gx = p - 1
+Gy = 1
+
+# Frobenius constant
+Fra = 0x1359082FA63A0164AFE18B8AACA7189868677326F173F8215BD9083355C80EA3
+Frb = 0x10A6F7D0623628A900DC53D9CDBC4E3ABBD863C7269546C0628D1BBC06534710
+
+# Generator point on G2
+
+Pxa = 0x1AC95A5B7F9A9B4FA7121C73CB19C2F0944FB8E61B99362851C3E806CB5FAAF5
+Pxb = 0x53D3001036566043F11C2D1681F364C1BBA33A1ABDA094DEDE50060FC15F433
+Pya = 0x15727970B09E6FB2EE06BBFEF918406479DFF0936EA3484E6833216A9772A299
+Pyb = 0x11BCB56C02AC189FD57BD77F56070166D320056091A061ADC41BC11F9C49E8CD
diff --git a/version3/python/c25519.py b/version3/python/c25519.py
new file mode 100644
index 0000000..16b80b3
--- /dev/null
+++ b/version3/python/c25519.py
@@ -0,0 +1,19 @@
+# C25519 curve constants
+
+from constants import *
+
+SHA = 'sha256'   # hash type to use with this curve
+EFS = 32   # elliptic curve field size in bytes
+CurveType = MONTGOMERY
+
+# field modulus
+p = 2**255 - 19
+r = 2**252 + 27742317777372353535851937790883648493
+
+# elliptic curve
+A = 486662
+B = 0
+
+# generator point
+Gx = 9
+Gy = 0
diff --git a/version3/python/config.py b/version3/python/config.py
new file mode 100644
index 0000000..cf6f030
--- /dev/null
+++ b/version3/python/config.py
@@ -0,0 +1,175 @@
+import os
+import sys
+
+deltext = ""
+slashtext = ""
+copytext = ""
+org1text = "org"
+org2text = "apache"
+org3text = "milagro"
+
+if sys.platform.startswith("linux"):
+    copytext = "cp "
+    deltext = "rm "
+    slashtext = "/"
+if sys.platform.startswith("win"):
+    copytext = "copy "
+    deltext = "del "
+    slashtext = "\\"
+
+
+chosen = []
+cptr = 0
+
+
+def replace(namefile, oldtext, newtext):
+    f = open(namefile, 'r')
+    filedata = f.read()
+    f.close()
+
+    newdata = filedata.replace(oldtext, newtext)
+
+    f = open(namefile, 'w')
+    f.write(newdata)
+    f.close()
+
+
+def curveset(tc, pf):
+    global deltext, slashtext, copytext
+    global cptr, chosen
+
+    chosen.append(tc)
+    cptr = cptr + 1
+
+    fpath = tc + slashtext
+    os.system("mkdir " + tc)
+
+    os.system(copytext + "big.py " + fpath + "big.py")
+    os.system(copytext + "fp.py " + fpath + "fp.py")
+    os.system(copytext + "ecp.py " + fpath + "ecp.py")
+    os.system(copytext + "ecdh.py " + fpath + "ecdh.py")
+    os.system(copytext + tc + ".py " + fpath + "curve.py")
+
+    replace(fpath + "big.py", "XXX", tc)
+    replace(fpath + "fp.py", "XXX", tc)
+    replace(fpath + "ecp.py", "XXX", tc)
+    replace(fpath + "ecdh.py", "XXX", tc)
+
+    if pf != "NOT":
+        os.system(copytext + "fp2.py " + fpath + "fp2.py")
+        os.system(copytext + "fp4.py " + fpath + "fp4.py")
+
+        replace(fpath + "fp2.py", "XXX", tc)
+        replace(fpath + "fp4.py", "XXX", tc)
+
+        os.system(copytext + "ecp2.py " + fpath + "ecp2.py")
+        os.system(copytext + "fp12.py " + fpath + "fp12.py")
+        os.system(copytext + "pair.py " + fpath + "pair.py")
+        os.system(copytext + "mpin.py " + fpath + "mpin.py")
+
+        replace(fpath + "fp12.py", "XXX", tc)
+        replace(fpath + "ecp2.py", "XXX", tc)
+        replace(fpath + "pair.py", "XXX", tc)
+        replace(fpath + "mpin.py", "XXX", tc)
+
+
+print("Elliptic Curves")
+print("1. ED25519")
+print("2. C25519")
+print("3. NIST256")
+print("4. GOLDILOCKS")
+print("5. NIST384")
+print("6. NIST521")
+print("7. SEC256K1")
+
+
+print("Pairing-Friendly Elliptic Curves")
+print("8. BN254")
+print("9. BN254CX")
+print("10. BLS383")
+print("11. BLS381")
+
+selection = []
+ptr = 0
+max = 12
+
+curve_selected = False
+pfcurve_selected = False
+
+while ptr < max:
+    x = int(input("Choose a Scheme to support - 0 to finish: "))
+    if x == 0:
+        break
+#	print("Choice= ",x)
+    already = False
+    for i in range(0, ptr):
+        if x == selection[i]:
+            already = True
+            break
+    if already:
+        continue
+
+    selection.append(x)
+    ptr = ptr + 1
+
+# curveset(curve,pairing_friendly)
+# where "curve" is the common name for the elliptic curve
+# pairing_friendly is BN, BLS or NOT (if not pairing friendly)
+
+    if x == 1:
+        curveset("ed25519", "NOT")
+        curve_selected = True
+    if x == 2:
+        curveset("c25519", "NOT")
+        curve_selected = True
+    if x == 3:
+        curveset("nist256", "NOT")
+        curve_selected = True
+    if x == 4:
+        curveset("goldilocks", "NOT")
+        curve_selected = True
+    if x == 5:
+        curveset("nist384", "NOT")
+        curve_selected = True
+    if x == 6:
+        curveset("nist521", "NOT")
+        curve_selected = True
+    if x == 6:
+        curveset("sec256k1", "NOT")
+        curve_selected = True
+
+    if x == 8:
+        curveset("bn254", "BN")
+        pfcurve_selected = True
+    if x == 9:
+        curveset("bn254cx", "BN")
+        pfcurve_selected = True
+    if x == 10:
+        curveset("bls383", "BLS")
+        pfcurve_selected = True
+    if x == 11:
+        curveset("bls381", "BLS")
+        pfcurve_selected = True
+
+
+os.system(deltext + " big.py")
+os.system(deltext + " fp.py")
+os.system(deltext + " ecp.py")
+os.system(deltext + " ecdh.py")
+os.system(deltext + " fp2.py")
+os.system(deltext + " fp4.py")
+os.system(deltext + " fp12.py")
+os.system(deltext + " mpin.py")
+os.system(deltext + " pair.py")
+os.system(deltext + " ecp2.py")
+os.system(deltext + " c25519.py")
+os.system(deltext + " ed25519.py")
+os.system(deltext + " nist256.py")
+os.system(deltext + " bn254.py")
+os.system(deltext + " bn254cx.py")
+os.system(deltext + " bls383.py")
+os.system(deltext + " goldilocks.py")
+os.system(deltext + " bls381.py")
+os.system(deltext + " nist384.py")
+os.system(deltext + " nist521.py")
+os.system(deltext + " sec256k1.py")
diff --git a/version3/python/constants.py b/version3/python/constants.py
new file mode 100644
index 0000000..f941c25
--- /dev/null
+++ b/version3/python/constants.py
@@ -0,0 +1,17 @@
+# fixed constants
+
+WEIERSTRASS = 0
+EDWARDS = 1
+MONTGOMERY = 2
+
+D_TYPE = 0
+M_TYPE = 1
+
+NEGATIVEX = 0
+POSITIVEX = 1
+
+BN = 0
+BLS = 1
+
+ECDH_INVALID_PUBLIC_KEY = -2
+ECDH_ERROR = -3
diff --git a/version3/python/ecdh.py b/version3/python/ecdh.py
new file mode 100644
index 0000000..f331426
--- /dev/null
+++ b/version3/python/ecdh.py
@@ -0,0 +1,162 @@
+#
+# Python 3.7 Code to implement basic ECDH/ECDSA protocol API
+# M.Scott August 2018
+#
+
+import hashlib
+from constants import *
+
+from XXX import big
+from XXX import curve
+from XXX.ecp import *
+
+# Calculate a public/private EC GF(p) key pair.
+
+
+def ECP_KeyPairGenerate(S):
+    G = generator()
+
+    if S is None:
+        s = big.rand(curve.r)
+    else:
+        s = big.from_bytes(S) % curve.r
+
+    Y = s * G
+
+    SK = big.to_bytes(s)
+
+    PK = Y.toBytes(False)
+    return (SK, PK)
+
+# Validate public key
+
+
+def ECP_PublicKeyValidate(W):
+    r = curve.r
+    p = curve.p
+
+    WP = ECp()
+    if not WP.fromBytes(W):
+        return ECDH_INVALID_PUBLIC_KEY
+
+    nb = p.bit_length()
+    k = 1
+    k = k << (nb + 4) // 2
+    k += p
+    k //= r
+    while k % 2 == 0:
+        WP.dbl()
+        k //= 2
+    if k != 1:
+        WP = k * WP
+    if WP.isinf():
+        return ECDH_INVALID_PUBLIC_KEY
+    return 0
+
+# Get Diffie-Hellman shared key
+
+
+def ECP_SvdpDH(S, W):
+    s = big.from_bytes(S)
+    WP = ECp()
+    if not WP.fromBytes(W):
+        return ECDH_ERROR
+
+    r = curve.r
+    s %= r
+    WP = s * WP
+
+    if WP.isinf():
+        return ECDH_ERROR
+    x = WP.getx()
+
+    K = big.to_bytes(x)
+
+    return K
+
+# create ECDSA signature
+
+
+def ECP_SpDSA(S, F):
+    FS = curve.EFS
+    G = generator()
+    m = hashlib.new(curve.SHA)
+    m.update(F)
+    H = m.digest()
+    HS = m.digest_size
+    if HS >= FS:
+        B = H[0:FS]
+    else:
+        B = bytearray(FS)
+        for i in range(0, HS):
+            B[i + FS - HS] = H[i]
+
+    C = bytearray(FS)
+    D = bytearray(FS)
+
+    r = curve.r
+    s = big.from_bytes(S)
+    f = big.from_bytes(B)
+
+    c = 0
+    d = 0
+    while d == 0:
+        u = big.rand(curve.r)
+        w = big.rand(curve.r)  # masking
+        V = G.copy()
+        V = u * V
+        vx = V.getx()
+        c = vx % r
+        if c == 0:
+            continue
+        u = big.modmul(u, w, r)
+        u = big.invmodp(u, r)
+        d = big.modmul(s, c, r)
+        d += f
+        d = big.modmul(d, w, r)
+        d = big.modmul(d, u, r)
+
+    C = big.to_bytes(c)
+    D = big.to_bytes(d)
+
+    return C, D
+
+# verify signature
+
+
+def ECP_SvDSA(P, F, C, D):
+    FS = curve.EFS
+    G = generator()
+
+    m = hashlib.new(curve.SHA)
+    m.update(F)
+    H = m.digest()
+    HS = m.digest_size
+    if HS >= FS:
+        B = H[0:FS]
+    else:
+        B = bytearray(FS)
+        for i in range(0, HS):
+            B[i + FS - HS] = H[i]
+    c = big.from_bytes(C)
+    d = big.from_bytes(D)
+    f = big.from_bytes(B)
+
+    r = curve.r
+    if c == 0 or c >= r or d == 0 or d >= r:
+        return False
+    d = big.invmodp(d, r)
+    f = big.modmul(f, d, r)
+    h2 = big.modmul(c, d, r)
+
+    WP = ECp()
+    if not WP.fromBytes(P):
+        return False
+    P = ECp.mul(WP, h2, G, f)
+
+    if P.isinf():
+        return False
+    d = P.getx() % r
+    if c != d:
+        return False
+    return True
diff --git a/version3/python/ecp.py b/version3/python/ecp.py
new file mode 100644
index 0000000..8268ef7
--- /dev/null
+++ b/version3/python/ecp.py
@@ -0,0 +1,634 @@
+
+#
+# Elliptic Curve Points
+# Projective Weierstrass coordinates
+# M.Scott August 2013
+#
+import copy
+from constants import *
+
+from XXX import big
+from XXX import curve
+from XXX.fp import *
+
+
+class ECp:
+    A = Fp(curve.A)
+    B = Fp(curve.B)
+
+    def __init__(self):
+        self.x = Fp(0)
+        self.y = Fp(1)
+        if curve.CurveType == EDWARDS:
+            self.z = Fp(1)
+        else:
+            self.z = Fp(0)
+
+    def copy(self):
+        return copy.deepcopy(self)
+
+# convert to affine coordinates
+    def affine(self):
+        if self.isinf() or self.z.isone():
+            return
+        iz = self.z.inverse()  # iz / self.z
+        self.x *= iz
+        if curve.CurveType != MONTGOMERY:
+            self.y *= iz
+        self.z = Fp(1)
+        return self
+
+# check if point-at-infinity
+    def isinf(self):
+        if curve.CurveType == WEIERSTRASS:
+            if self.x.iszero() and self.z.iszero():
+                return True
+        if curve.CurveType == EDWARDS:
+            if self.x.iszero() and self.y == self.z:
+                return True
+        if curve.CurveType == MONTGOMERY:
+            if self.z.iszero():
+                return True
+        return False
+
+# set to point-at-infinity
+    def inf(self):
+        self.x = Fp(0)
+        self.y = Fp(1)
+        if curve.CurveType == EDWARDS:
+            self.z = Fp(1)
+        else:
+            self.z = Fp(0)
+        return self
+
+    def set(self, x, s=0):			# set point from x and LSB of y
+        mx = Fp(x)
+        rhs = RHS(mx)
+        if rhs.jacobi() != 1:
+            return False
+        self.x = mx
+        self.z = Fp(1)
+
+        if curve.CurveType != MONTGOMERY:
+            self.y = rhs.sqrt()
+            if big.bit(self.y.int(), 0) != s:
+                self.y = -self.y
+        return True
+
+    def setxy(self, x, y):
+        mx = Fp(x)
+        my = Fp(y)
+        if my * my != RHS(mx):
+            return False
+        self.x = mx
+        self.y = my
+        self.z = Fp(1)
+        return True
+
+    def get(self):				# return tuple Fp x and Fp y
+        W = self.copy()
+        if W.isinf():
+            return (0, 0)
+        W.affine()
+        if curve.CurveType == MONTGOMERY:
+            return W.x.int()
+        return(W.x.int(), W.y.int())
+
+    def getxs(self):				# return tuple integer x and LSB of y
+        W = self.copy()
+        if W.isinf():
+            return (0, 0)
+        W.affine()
+        if curve.CurveType == MONTGOMERY:
+            return (W.x.int(), 0)
+        return (W.x.int(), big.bit(W.y.int(), 0))
+
+    def getx(self):				# return just integer x
+        W = self.copy()
+        if W.isinf():
+            return 0
+        W.affine()
+        return W.x.int()
+
+# Return as Fps
+    def getxy(self):
+        W = self.copy()
+        if (W.isinf()):
+            return (Fp(0), Fp(0))
+        W.affine()
+        if curve.CurveType == MONTGOMERY:
+            return W.x.copy()
+        return (W.x.copy(), W.y.copy())
+
+    def __eq__(self, other):
+        zs = self.z
+        zo = other.z
+        if self.x * zo != other.x * zs:
+            return False
+        if curve.CurveType != MONTGOMERY:
+            if self.y * zo != other.y * zs:
+                return False
+        return True
+
+    def __ne__(self, other):
+        return not(self == other)
+
+    def __neg__(self):
+        s = self.copy()
+        if not s.isinf():
+            if curve.CurveType == WEIERSTRASS:
+                s.y = -s.y
+            if curve.CurveType == EDWARDS:
+                s.x = -s.x
+        return s
+
+# use exception-free formulae
+    def dbl(self):
+        if curve.CurveType == WEIERSTRASS:
+            if ECp.A.iszero():
+                t0 = self.y.copy()
+                t0 = t0 * t0
+                t1 = self.y.copy()
+                t1 = t1 * self.z
+                t2 = self.z.copy()
+                t2 = t2 * t2
+                self.z = t0 + t0
+
+                self.z += self.z
+                self.z += self.z
+                t2 *= (ECp.B + ECp.B + ECp.B)
+                x3 = t2 * self.z
+                y3 = t0 + t2
+                self.z *= t1
+                t1 = t2 + t2
+                t2 += t1
+                t0 -= t2
+                y3 *= t0
+                y3 += x3
+                t1 = self.x * self.y
+                self.x = t0
+                self.x *= t1
+                self.x += self.x
+                self.y = y3
+            else:
+                t0 = self.x.copy()
+                t1 = self.y.copy()
+                t2 = self.z.copy()
+                t3 = self.x.copy()
+                z3 = self.z.copy()
+                y3 = Fp(0)
+                x3 = Fp(0)
+                b = ECp.B
+
+                t0 *= t0
+                t1 *= t1
+                t2 *= t2
+
+                t3 *= self.y
+                t3 += t3
+
+                z3 *= self.x
+                z3 += z3
+
+                y3 = t2 * b
+
+                y3 -= z3
+                x3 = y3 + y3
+
+                y3 += x3
+                x3 = t1 - y3
+                y3 += t1
+                y3 *= x3
+                x3 *= t3
+                t3 = t2 + t2
+                t2 += t3
+                z3 *= b
+
+                z3 -= t2
+                z3 -= t0
+                t3 = z3 + z3
+
+                z3 += t3
+                t3 = t0 + t0
+                t0 += t3
+                t0 -= t2
+
+                t0 *= z3
+                y3 += t0
+                t0 = self.y * self.z
+                t0 += t0
+                z3 *= t0
+                x3 -= z3
+                t0 += t0
+                t1 += t1
+                z3 = t0 * t1
+
+                self.x = x3
+                self.y = y3
+                self.z = z3
+
+        if curve.CurveType == EDWARDS:
+            C = self.x.copy()
+            D = self.y.copy()
+            H = self.z.copy()
+            J = Fp(0)
+
+            self.x *= self.y
+            self.x += self.x
+            C *= C
+            D *= D
+
+            if ECp.A == Fp(-1):
+                C = -C
+
+            self.y = C + D
+            H *= H
+            H += H
+
+            self.z = self.y.copy()
+            J = self.y.copy()
+
+            J -= H
+            self.x *= J
+
+            C -= D
+            self.y *= C
+            self.z *= J
+
+        if curve.CurveType == MONTGOMERY:
+            A = self.x.copy()
+            B = self.x.copy()
+            AA = Fp(0)
+            BB = Fp(0)
+            C = Fp(0)
+
+            A += self.z
+            AA = A * A
+            B -= self.z
+            BB = B * B
+            C = AA
+            C = AA - BB
+            self.x = AA * BB
+
+            A = C * ((ECp.A + Fp(2)).div2().div2())
+
+            BB += A
+            self.z = BB * C
+
+        return self
+
+    def add(self, other):
+        if curve.CurveType == WEIERSTRASS:
+            if ECp.A.iszero():
+                b = (ECp.B + ECp.B + ECp.B)
+                t0 = self.x.copy()
+                t0 *= other.x
+                t1 = self.y.copy()
+                t1 *= other.y
+                t2 = self.z.copy()
+                t2 = t2 * other.z
+                t3 = self.x.copy()
+                t3 += self.y
+                t4 = other.x + other.y
+                t3 *= t4
+                t4 = t0 + t1
+
+                t3 -= t4
+                t4 = self.y + self.z
+                x3 = other.y + other.z
+
+                t4 *= x3
+                x3 = t1 + t2
+
+                t4 -= x3
+                x3 = self.x + self.z
+                y3 = other.x + other.z
+                x3 *= y3
+                y3 = t0 + t2
+                y3 = x3 - y3
+                x3 = t0 + t0
+                t0 += x3
+                t2 *= b
+
+                z3 = t1 + t2
+                t1 -= t2
+                y3 *= b
+
+                x3 = y3 * t4
+                t2 = t3 * t1
+                x3 = t2 - x3
+                y3 *= t0
+                t1 *= z3
+                y3 += t1
+                t0 *= t3
+                z3 *= t4
+                z3 += t0
+
+                self.x = x3
+                self.y = y3
+                self.z = z3
+
+            else:
+
+                t0 = self.x.copy()
+                t1 = self.y.copy()
+                t2 = self.z.copy()
+                t3 = self.x.copy()
+                t4 = other.x.copy()
+                z3 = Fp(0)
+                y3 = other.x.copy()
+                x3 = other.y.copy()
+                b = ECp.B
+
+                t0 *= other.x
+                t1 *= other.y
+                t2 *= other.z
+
+                t3 += self.y
+                t4 += other.y
+                t3 *= t4
+                t4 = t0 + t1
+                t3 -= t4
+
+                t4 = self.y + self.z
+                x3 += other.z
+                t4 *= x3
+                x3 = t1 + t2
+
+                t4 -= x3
+                x3 = self.x + self.z
+                y3 += other.z
+
+                x3 *= y3
+                y3 = t0 + t2
+
+                y3 = x3 - y3
+                z3 = t2 * b
+
+                x3 = y3 - z3
+                z3 = x3 + x3
+
+                x3 += z3
+                z3 = t1 - x3
+                x3 += t1
+
+                y3 *= b
+
+                t1 = t2 + t2
+                t2 += t1
+
+                y3 -= t2
+
+                y3 -= t0
+                t1 = y3 + y3
+                y3 += t1
+
+                t1 = t0 + t0
+                t0 += t1
+                t0 -= t2
+                t1 = t4 * y3
+                t2 = t0 * y3
+                y3 = x3 * z3
+                y3 += t2
+                x3 *= t3
+                x3 -= t1
+                z3 *= t4
+                t1 = t3 * t0
+                z3 += t1
+                self.x = x3
+                self.y = y3
+                self.z = z3
+
+        if curve.CurveType == EDWARDS:
+            A = self.z.copy()
+            B = Fp(0)
+            C = self.x.copy()
+            D = self.y.copy()
+            E = Fp(0)
+            F = Fp(0)
+            G = Fp(0)
+            b = ECp.B
+
+            # print(self.z.int())
+
+            A *= (other.z)
+            B = A * A
+            C *= (other.x)
+            D *= (other.y)
+            # print(other.z.int())
+            E = C * D
+            E *= b
+
+            F = B - E
+            G = B + E
+
+            if (ECp.A == Fp(1)):
+                E = D - C
+
+            C += D
+
+            B = self.x + self.y
+            D = other.x + other.y
+            B *= D
+            B -= C
+            B *= F
+            self.x = A * B
+
+            if ECp.A == Fp(1):
+                C = E * G
+            if ECp.A == Fp(-1):
+                C *= G
+
+            self.y = A * C
+
+            self.z = F
+            self.z *= G
+
+        return self
+
+# For Montgomery use only
+    def dadd(self, Q, W):
+        A = self.x.copy()
+        B = self.x.copy()
+        C = Q.x.copy()
+        D = Q.x.copy()
+        DA = Fp(0)
+        CB = Fp(0)
+
+        A += self.z
+        B -= self.z
+
+        C += Q.z
+        D -= Q.z
+
+        DA = D * A
+
+        CB = C * B
+
+        A = DA + CB
+        A *= A
+        B = DA - CB
+        B *= B
+
+        self.x = A
+        self.z = W.x * B
+
+        return self
+
+    def __rmul__(self, other):   # use NAF
+        R = ECp()
+        if curve.CurveType == MONTGOMERY:
+            e = other
+            D = ECp()
+            R0 = self.copy()
+            R1 = self.copy()
+            R1.dbl()
+
+            D = self.copy()
+            D.affine()
+            nb = e.bit_length()
+            # nb=curve.r.bit_length()
+            for i in range(nb - 2, -1, -1):
+                b = big.bit(e, i)
+                R = R1.copy()
+
+                R.dadd(R0, D)
+                if b == 1:
+                    R0, R1 = R1, R0
+                R1 = R.copy()
+                R0.dbl()
+                if b == 1:
+                    R0, R1 = R1, R0
+            R = R0.copy()
+
+        else:
+            b = other
+            b3 = 3 * b
+            k = b3.bit_length()
+            # k=curve.r.bit_length()+2;
+
+            mself = -self
+            for i in range(k - 1, 0, -1):
+                R.dbl()
+                if big.bit(b3, i) == 1 and big.bit(b, i) == 0:
+                    R.add(self)
+                if big.bit(b3, i) == 0 and big.bit(b, i) == 1:
+                    R.add(mself)
+        R.affine()
+        return R
+
+    def mul(P, a, Q, b):  # double multiplication a*P+b*Q
+        # P.affine()
+        # Q.affine()
+        if a < 0:
+            a = -a
+            P = -P
+        if b < 0:
+            b = -b
+            Q = -Q
+        R = ECp()
+        ia = a.bit_length()
+        ib = b.bit_length()
+        k = ia
+        if (ib > ia):
+            k = ib
+        k = curve.r.bit_length()
+        W = P.copy()
+        W.add(Q)
+        # W.affine()
+        for i in range(k - 1, -1, -1):
+            R.dbl()
+            if (big.bit(a, i) == 1):
+                if (big.bit(b, i) == 1):
+                    R.add(W)
+                else:
+                    R.add(P)
+            else:
+                if (big.bit(b, i) == 1):
+                    R.add(Q)
+        return R
+
+    def __str__(self):			# pretty print
+        W = self.copy()
+        if W.isinf():
+            return "infinity"
+        W.affine()
+        if curve.CurveType == MONTGOMERY:
+            return "(%x)" % (W.x.int())
+        return "(%x,%x)" % (W.x.int(), W.y.int())
+
+# convert from and to an array of bytes
+    def fromBytes(self, W):
+        t = W[0]  # ord(W[0])
+        sp1 = curve.EFS + 1	  # splits
+        sp2 = sp1 + curve.EFS
+        x = big.from_bytes(W[1:sp1])
+        if curve.CurveType == MONTGOMERY:
+            return self.set(x)
+        if t == 4:
+            y = big.from_bytes(W[sp1:sp2])
+            return self.setxy(x, y)
+        else:
+            if t == 2:
+                return self.set(x, 0)
+            if t == 3:
+                return self.set(x, 1)
+        self.inf()
+        return False
+
+# Can be compressed to just x
+    def toBytes(self, compress):
+        FS = curve.EFS
+        if curve.CurveType == MONTGOMERY:
+            PK = bytearray(FS + 1)
+            PK[0] = 6
+            x = self.get()
+            W = big.to_bytes(x)
+            for i in range(0, FS):
+                PK[1 + i] = W[i]
+            return PK
+        if compress:
+            PK = bytearray(FS + 1)
+            x, b = self.getx()
+            if b == 0:
+                PK[0] = 2
+            else:
+                PK[0] = 3
+            W = big.to_bytes(x)
+            for i in range(0, FS):
+                PK[1 + i] = W[i]
+        else:
+            PK = bytearray(2 * FS + 1)
+            x, y = self.get()
+            PK[0] = 4
+            W = big.to_bytes(x)
+            for i in range(0, FS):
+                PK[1 + i] = W[i]
+            W = big.to_bytes(y)
+            for i in range(0, FS):
+                PK[1 + i + FS] = W[i]
+
+        return PK
+
+# calculate Right Hand Side of elliptic curve equation y^2=RHS(x)
+
+
+def RHS(x):
+    if curve.CurveType == WEIERSTRASS:
+        return x * x * x + ECp.A * x + ECp.B
+    if curve.CurveType == EDWARDS:
+        return (ECp.A * x * x - Fp(1)) * ((ECp.B * x * x - Fp(1)).inverse())
+    if curve.CurveType == MONTGOMERY:
+        return x * x * x + ECp.A * x * x + x
+
+# get group generator point
+
+
+def generator():
+    G = ECp()
+    if curve.CurveType == MONTGOMERY:
+        G.set(curve.Gx)
+    else:
+        G.setxy(curve.Gx, curve.Gy)
+
+    return G
diff --git a/version3/python/ecp2.py b/version3/python/ecp2.py
new file mode 100644
index 0000000..cc36a0f
--- /dev/null
+++ b/version3/python/ecp2.py
@@ -0,0 +1,290 @@
+
+#
+# Elliptic Curve Points over Fp^2
+# Projective Weierstrass coordinates
+# M.Scott August 2013
+#
+
+import copy
+
+from XXX import big
+from XXX import curve
+from XXX.fp2 import *
+from XXX.ecp import *
+
+
+class ECp2:
+
+    def __init__(self):
+        self.x = Fp2()
+        self.y = Fp2(Fp(1))
+        self.z = Fp2()
+
+    def copy(self):
+        return copy.deepcopy(self)
+
+# convert to affine coordinates
+    def affine(self):
+        if self.isinf() or self.z.isone():
+            return self
+        iz = self.z.inverse()
+        self.x *= iz
+        self.y *= iz
+        self.z = Fp2(Fp(1))
+        return self
+
+# check if point-at-infinity
+    def isinf(self):
+        if self.x.iszero() and self.z.iszero():
+            return True
+        return False
+
+# set point to (x,y)
+    def set(self, x, y):
+        mx = x.copy()
+        my = y.copy()
+        if my * my != RHS(mx):
+            return False
+        self.x = mx
+        self.y = my
+        self.z = Fp2(Fp(1))
+        return True
+
+    def get(self):				# return tuple Fp2 x and Fp2 y
+        W = self.copy()
+        if (W.isinf()):
+            return (Fp2(), Fp2())
+        W.affine()
+        return(W.x, W.y)
+
+    def getZ(self):
+        return self.z.copy()
+
+    def getxyz(self):
+        return (self.x.copy(), self.y.copy(), self.z.copy())
+
+    def getxy(self):
+        return (self.x.copy(), self.y.copy())
+
+    def __eq__(self, other):
+        zs = self.z
+        zo = other.z
+        if self.x * zo != other.x * zs:
+            return False
+        if self.y * zo != other.y * zs:
+            return False
+        return True
+
+    def __ne__(self, other):
+        return not(self == other)
+
+    def __neg__(self):
+        s = self.copy()
+        s.y = -s.y
+        return s
+
+# use exeption free formulae
+    def dbl(self):
+        iy = self.y.copy()
+        if curve.SexticTwist == D_TYPE:
+            iy = iy.mulQNR()
+        t0 = self.y.copy()
+        t0.sqr()
+        if curve.SexticTwist == D_TYPE:
+            t0 = t0.mulQNR()
+
+        t1 = iy.copy()
+        t1 = t1 * self.z
+        t2 = self.z.copy()
+        t2.sqr()
+
+        self.z = t0 + t0
+        self.z += self.z
+        self.z += self.z
+
+        t2 = t2.muli(3 * curve.B)
+        if curve.SexticTwist == M_TYPE:
+            t2 = t2.mulQNR()
+        x3 = t2 * self.z
+
+        y3 = t0 + t2
+        self.z *= t1
+        t1 = t2 + t2
+        t2 += t1
+        t0 -= t2
+        y3 *= t0
+        y3 += x3
+        t1 = self.x * iy
+        self.x = t0
+        self.x *= t1
+        self.x += self.x
+        self.y = y3
+        return self
+
+    def add(self, other):
+        t0 = self.x.copy()
+        t0 *= other.x
+        t1 = self.y.copy()
+        t1 *= other.y
+        t2 = self.z.copy()
+        t2 = t2 * other.z
+        t3 = self.x.copy()
+        t3 += self.y
+        t4 = other.x + other.y
+        t3 *= t4
+        t4 = t0 + t1
+
+        t3 -= t4
+        if curve.SexticTwist == D_TYPE:
+            t3 = t3.mulQNR()
+        t4 = self.y + self.z
+        x3 = other.y + other.z
+
+        t4 *= x3
+        x3 = t1 + t2
+
+        t4 -= x3
+        if curve.SexticTwist == D_TYPE:
+            t4 = t4.mulQNR()
+
+        x3 = self.x + self.z
+        y3 = other.x + other.z
+        x3 *= y3
+        y3 = t0 + t2
+        y3 = x3 - y3
+
+        if curve.SexticTwist == D_TYPE:
+            t0 = t0.mulQNR()
+            t1 = t1.mulQNR()
+
+        x3 = t0 + t0
+        t0 += x3
+        t2 = t2.muli(3 * curve.B)
+        if curve.SexticTwist == M_TYPE:
+            t2 = t2.mulQNR()
+        z3 = t1 + t2
+        t1 -= t2
+        y3 = y3.muli(3 * curve.B)
+        if curve.SexticTwist == M_TYPE:
+            y3 = y3.mulQNR()
+        x3 = y3 * t4
+        t2 = t3 * t1
+        x3 = t2 - x3
+        y3 *= t0
+        t1 *= z3
+        y3 += t1
+        t0 *= t3
+        z3 *= t4
+        z3 += t0
+
+        self.x = x3
+        self.y = y3
+        self.z = z3
+        return self
+
+    def __rmul__(self, other):   # use NAF
+        b = other
+        b3 = 3 * b
+        k = b3.bit_length()
+        #k = curve.r.bit_length()+2
+        # self.affine()
+        mself = -self
+        R = ECp2()
+        for i in range(k - 1, 0, -1):
+            R.dbl()
+            if big.bit(b3, i) == 1 and big.bit(b, i) == 0:
+                R.add(self)
+            if big.bit(b3, i) == 0 and big.bit(b, i) == 1:
+                R.add(mself)
+        return R
+
+# calculate p.P(x,y) using frobenius
+    def frobenius(self):
+        X = Fp2(Fp(curve.Fra), Fp(curve.Frb))
+        if curve.SexticTwist == M_TYPE:
+            X = X.inverse()
+        X2 = X.copy()
+        X2.sqr()
+        # self.affine()
+        self.x = self.x.conj()
+        self.y = self.y.conj()
+        self.z = self.z.conj()
+        self.x *= X2
+        self.y *= X2
+        self.y *= X
+        return self
+
+    def __str__(self):			# pretty print
+        W = self.copy()
+        if W.isinf():
+            return "infinity"
+        W.affine()
+        return "[%s,%s]" % (W.x, W.y)
+
+# convert from and to an array of bytes
+    def fromBytes(self, W):
+        FS = curve.EFS
+        xa = big.from_bytes(W[0:FS])
+        xb = big.from_bytes(W[FS:2 * FS])
+        ya = big.from_bytes(W[2 * FS:3 * FS])
+        yb = big.from_bytes(W[3 * FS:4 * FS])
+        x = Fp2(Fp(xa), Fp(xb))
+        y = Fp2(Fp(ya), Fp(yb))
+        return self.set(x, y)
+
+    def toBytes(self):
+        FS = curve.EFS
+        PK = bytearray(4 * FS)
+        x, y = self.get()
+        xa, xb = x.get()
+        ya, yb = y.get()
+        W = big.to_bytes(xa)
+        for i in range(0, FS):
+            PK[i] = W[i]
+        W = big.to_bytes(xb)
+        for i in range(0, FS):
+            PK[FS + i] = W[i]
+        W = big.to_bytes(ya)
+        for i in range(0, FS):
+            PK[2 * FS + i] = W[i]
+        W = big.to_bytes(yb)
+        for i in range(0, FS):
+            PK[3 * FS + i] = W[i]
+        return PK
+
+# calculate Right Hand Side of elliptic curve equation y^2=RHS(x)
+
+
+def RHS(x):
+    if curve.SexticTwist == D_TYPE:
+        return x * x * x + Fp2(ECp.B).divQNR()  # on the sextic twist
+    else:
+        return x * x * x + Fp2(ECp.B).mulQNR()  # on the sextic twist
+
+# get group generator point
+
+
+def generator():
+    P = ECp2()
+    P.set(Fp2(Fp(curve.Pxa), Fp(curve.Pxb)), Fp2(Fp(curve.Pya), Fp(curve.Pyb)))
+    return P
+
+# P=generator()
+# print(curve.r*P)
+# P.dbl()
+# XX,YY,ZZ=P.getxyz()
+#print("P= ",XX,YY,ZZ)
+
+# XX,YY,ZZ=P.getxyz()
+#print("P= ",XX,YY,ZZ)
+# P.dbl()
+# XX,YY,ZZ=P.getxyz()
+#print("P= ",XX,YY,ZZ)
+
+
+# print(P.frobenius())
+
+#X=Fp2(Fp(curve.Fra), Fp(curve.Frb))
+# X2=X*X
+# X3=X*X*X
+# print(X3)
diff --git a/version3/python/ed25519.py b/version3/python/ed25519.py
new file mode 100644
index 0000000..8eb5592
--- /dev/null
+++ b/version3/python/ed25519.py
@@ -0,0 +1,19 @@
+# ED25519 curve constants
+
+from constants import *
+
+SHA = 'sha256'   # hash type to use with this curve
+EFS = 32   # elliptic curve field size in bytes
+CurveType = EDWARDS
+
+# field modulus
+p = 2**255 - 19
+r = 2**252 + 27742317777372353535851937790883648493
+
+# elliptic curve
+A = -1
+B = 0x52036CEE2B6FFE738CC740797779E89800700A4D4141D8AB75EB4DCA135978A3
+
+# generator point
+Gx = 0x216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A
+Gy = 0x6666666666666666666666666666666666666666666666666666666666666658
diff --git a/version3/python/fp.py b/version3/python/fp.py
new file mode 100644
index 0000000..4938d78
--- /dev/null
+++ b/version3/python/fp.py
@@ -0,0 +1,97 @@
+
+#
+# bigs modulo n
+# M.Scott August 2013
+#
+
+import copy
+from XXX import big
+from XXX import curve
+
+
+class Fp:
+    p = curve.p
+
+    def __init__(self, x=None):
+        if (x is None or x == 0):
+            self.x = 0
+        else:
+            if (x < 0):
+                y = -x
+                self.x = Fp.p - (y % Fp.p)
+            else:
+                self.x = x % Fp.p
+
+    def copy(self):
+        return copy.copy(self)
+
+    def __add__(self, other):
+        return Fp(big.modadd(self.x, other.x, Fp.p))
+
+    def __iadd__(self, other):
+        self.x = big.modadd(self.x, other.x, Fp.p)
+        return self
+
+    def __sub__(self, other):
+        return Fp(big.modsub(self.x, other.x, Fp.p))
+
+    def __isub__(self, other):
+        self.x = big.modsub(self.x, other.x, Fp.p)
+        return self
+
+    def __mul__(self, other):
+        return Fp(big.modmul(self.x, other.x, Fp.p))
+
+    def __imul__(self, other):
+        self.x = big.modmul(self.x, other.x, Fp.p)
+        return self
+
+    def __neg__(self):
+        return Fp(Fp.p - self.x)
+
+    def muli(self, other):
+        return Fp((other * self.x) % Fp.p)
+
+    def inverse(self):
+        return Fp(big.invmodp(self.x, Fp.p))
+
+    def div2(self):
+        if self.x % 2 == 1:
+            return Fp((Fp.p + self.x) // 2)
+        else:
+            return Fp(self.x // 2)
+
+    def __eq__(self, other):
+        return self.x == other.x
+
+    def __ne__(self, other):
+        return self.x != other.x
+
+    def iszero(self):
+        if self.x == 0:
+            return True
+        return False
+
+    def isone(self):
+        if self.x == 1:
+            return True
+        return False
+
+    def pow(self, other):
+        return Fp(pow(self.x, other, Fp.p))
+
+    def jacobi(self):
+        return big.jacobi(self.x, Fp.p)
+
+    def gcd(self):
+        return big.gcd(self.x, Fp.p)
+
+    def sqrt(self):
+        return Fp(big.sqrtmodp(self.x, Fp.p))
+
+    def int(self):
+        return self.x
+
+    def rand(self):
+        self.x = big.rand(Fp.p)
+        return self
diff --git a/version3/python/fp12.py b/version3/python/fp12.py
new file mode 100644
index 0000000..11bfa81
--- /dev/null
+++ b/version3/python/fp12.py
@@ -0,0 +1,314 @@
+
+#
+# Fp^12 CLass -  towered over Fp^4
+# M.Scott August 2018
+#
+
+import copy
+from XXX import curve
+from XXX.fp4 import *
+
+
+class Fp12:
+
+    def __init__(self, a=None, b=None, c=None):
+        if b is None:
+            if a is None:
+                self.a = Fp4()
+                self.b = Fp4()
+                self.c = Fp4()
+            else:
+                self.a = a.copy()
+                self.b = Fp4()
+                self.c = Fp4()
+        else:
+            self.a = a.copy()
+            self.b = b.copy()
+            self.c = c.copy()
+
+    def copy(self):
+        return copy.deepcopy(self)
+
+    def one():
+        return Fp12(Fp4(Fp2(Fp(1))))
+
+    def get(self):
+        return(self.a, self.b, self.c)
+
+    def set(self, a, b, c):
+        self.a = a
+        self.b = b
+        self.c = c
+        return self
+
+    def __add__(self, other):
+        R = Fp12(self.a + other.a, self.b + other.b, self.c + other.c)
+        return R
+
+    def __iadd__(self, other):
+        self.a += other.a
+        self.b += other.b
+        self.c += other.c
+        return self
+
+    def __sub__(self, other):
+        R = Fp12(self.a - other.a, self.b - other.b, self.c - other.c)
+        return R
+
+    def __isub__(self, other):
+        self.a -= other.a
+        self.b -= other.b
+        self.c -= other.c
+        return self
+
+    def __eq__(self, other):
+        return (self.a == other.a and self.b == other.b and self.c == other.c)
+
+    def __ne__(self, other):
+        return (self.a != other.a or self.b != other.b or self.c != other.c)
+
+    def conj(self):
+        self.a = self.a.conj()
+        self.b = -self.b.conj()
+        self.c = self.c.conj()
+        return self
+
+# unitary squaring
+    def usqr(self):
+        A = self.a.copy()
+        self.a.sqr()
+        D = self.a.copy()
+        self.a += self.a
+        self.a += D
+        A = A.conj()
+        A += A
+        self.a -= A
+        B = self.c.copy()
+        B.sqr()
+        B = B.mulQNR()
+        D = B.copy()
+        B += B
+        B += D
+        C = self.b.copy()
+        C.sqr()
+        D = C.copy()
+        C += C
+        C += D
+        self.b = self.b.conj()
+        self.b += self.b
+        self.c = self.c.conj()
+        self.c += self.c
+        self.c = -self.c
+        self.b += B
+        self.c += C
+        return self
+
+# regular squaring
+    def sqr(self):  # mutable
+        A = self.a.copy()
+        A.sqr()
+        B = self.b * self.c
+        B += B
+        C = self.c.copy()
+        C.sqr()
+        D = self.a * self.b
+        D += D
+        self.c += (self.a + self.b)
+        self.c.sqr()
+        self.a = A + B.mulQNR()
+        self.b = D + C.mulQNR()
+        self.c -= (A + B + C + D)
+        return self
+
+# optimized to take advantage of sparse multiplier
+    def __imul__(self, other):
+        zero_c = other.c.iszero()
+        zero_b = other.b.iszero()
+        Z0 = self.a * other.a
+        if not zero_b:
+            Z2 = self.b * other.b
+        T0 = self.a + self.b
+        T1 = other.a + other.b
+        Z1 = T0 * T1
+        Z1 -= Z0
+        if not zero_b:
+            Z1 -= Z2
+        T0 = self.b + self.c
+        T1 = other.b + other.c
+        Z3 = T0 * T1
+        if not zero_b:
+            Z3 -= Z2
+        T0 = self.a + self.c
+        T1 = other.a + other.c
+        T0 *= T1
+        if not zero_b:
+            Z2 += T0
+        else:
+            Z2 = T0.copy()
+        Z2 -= Z0
+        self.b = Z1.copy()
+        if not zero_c:
+            T0 = self.c * other.c
+            Z2 -= T0
+            Z3 -= T0
+            self.b += T0.mulQNR()
+        self.a = Z0 + Z3.mulQNR()
+        self.c = Z2.copy()
+
+        return self
+
+    def __mul__(self, other):
+        R = self.copy()
+        if R == other:
+            R.sqr()
+        else:
+            R *= other
+        return R
+
+    def muls(self, other):  # multiple Fp12 by Fp4
+        R = Fp12(self.a * other, self.b * other, self.c * other)
+        return R
+
+    def __neg__(self):
+        R = Fp12(-self.a, -self.b, -self.c)
+        return R
+
+    def iszero(self):
+        if self.a.iszero() and self.b.iszero() and self.c.iszero():
+            return True
+        return False
+
+    def isone(self):
+        if self.a.isone() and self.b.iszero() and self.c.iszero():
+            return True
+        return False
+
+    def rand(self):  # mutable
+        r = Fp4()
+        r.rand()
+        self.a = r.copy()
+        r.rand()
+        self.b = r.copy()
+        r.rand()
+        self.c = r.copy()
+        return self
+
+    def pow(self, other):  # unitary only
+        e = other
+        e3 = e * 3
+        k = e3.bit_length()
+        x = self.copy()
+        r = self.copy()
+
+        for i in range(k - 2, 0, -1):
+            r.usqr()
+            if big.bit(e3, i) == 1 and big.bit(e, i) == 0:
+                r *= x
+            if big.bit(e3, i) == 0 and big.bit(e, i) == 1:
+                x.conj()
+                r *= x
+                x.conj()
+        return r
+
+    def __str__(self):			# pretty print
+        return "[%s,%s,%s]" % (self.a, self.b, self.c)
+
+    def mulQNR(self):				# assume p=3 mod 8, QNR=1+i
+        return Fp12(self.c.mulQNR(), self.a, self.b)
+
+    def inverse(self):
+        wa = self.a * self.a - (self.b * self.c).mulQNR()
+        wb = (self.c * self.c).mulQNR() - self.a * self.b
+        wc = self.b * self.b - self.a * self.c
+        f = ((self.b * wc).mulQNR() + self.a *
+             wa + (self.c * wb).mulQNR()).inverse()
+        return Fp12(wa * f, wb * f, wc * f)
+
+    def powq(self):
+        X = Fp2(Fp(curve.Fra), Fp(curve.Frb))
+        X2 = Fp2(Fp(curve.Fra), Fp(curve.Frb))
+        X2.sqr()
+        self.a = self.a.powq()
+        self.b = self.b.powq().muls(X)
+        self.c = self.c.powq().muls(X2)
+        return self
+
+    def trace(self):
+        R = self.a.copy()
+        R += R
+        R += self.a
+        return R
+
+    def fromBytes(self, E):
+        FS = curve.EFS
+        a = Fp4(Fp2(Fp(big.from_bytes(E[0:FS])),
+                    Fp(big.from_bytes(E[FS:2 * FS]))),
+                Fp2(Fp(big.from_bytes(E[2 * FS:3 * FS])),
+                    Fp(big.from_bytes(E[3 * FS:4 * FS]))))
+        b = Fp4(Fp2(Fp(big.from_bytes(E[4 * FS:5 * FS])),
+                    Fp(big.from_bytes(E[5 * FS:6 * FS]))),
+                Fp2(Fp(big.from_bytes(E[6 * FS:7 * FS])),
+                    Fp(big.from_bytes(E[7 * FS:8 * FS]))))
+        c = Fp4(Fp2(Fp(big.from_bytes(E[8 * FS:9 * FS])),
+                    Fp(big.from_bytes(E[9 * FS:10 * FS]))),
+                Fp2(Fp(big.from_bytes(E[10 * FS:11 * FS])),
+                    Fp(big.from_bytes(E[11 * FS:12 * FS]))))
+
+        self.set(a, b, c)
+
+    def toBytes(self):
+        FS = curve.EFS
+        a, b, c = self.get()
+
+        aa, ab = a.get()
+        aaa, aab = aa.get()
+        aba, abb = ab.get()
+
+        ba, bb = b.get()
+        baa, bab = ba.get()
+        bba, bbb = bb.get()
+
+        ca, cb = c.get()
+        caa, cab = ca.get()
+        cba, cbb = cb.get()
+
+        E = bytearray(12 * FS)
+
+        W = big.to_bytes(aaa)
+        for i in range(0, FS):
+            E[i] = W[i]
+        W = big.to_bytes(aab)
+        for i in range(0, FS):
+            E[FS + i] = W[i]
+        W = big.to_bytes(aba)
+        for i in range(0, FS):
+            E[2 * FS + i] = W[i]
+        W = big.to_bytes(abb)
+        for i in range(0, FS):
+            E[3 * FS + i] = W[i]
+        W = big.to_bytes(baa)
+        for i in range(0, FS):
+            E[4 * FS + i] = W[i]
+        W = big.to_bytes(bab)
+        for i in range(0, FS):
+            E[5 * FS + i] = W[i]
+        W = big.to_bytes(bba)
+        for i in range(0, FS):
+            E[6 * FS + i] = W[i]
+        W = big.to_bytes(bbb)
+        for i in range(0, FS):
+            E[7 * FS + i] = W[i]
+        W = big.to_bytes(caa)
+        for i in range(0, FS):
+            E[8 * FS + i] = W[i]
+        W = big.to_bytes(cab)
+        for i in range(0, FS):
+            E[9 * FS + i] = W[i]
+        W = big.to_bytes(cba)
+        for i in range(0, FS):
+            E[10 * FS + i] = W[i]
+        W = big.to_bytes(cbb)
+        for i in range(0, FS):
+            E[11 * FS + i] = W[i]
+
+        return E
diff --git a/version3/python/fp2.py b/version3/python/fp2.py
new file mode 100644
index 0000000..db47bd6
--- /dev/null
+++ b/version3/python/fp2.py
@@ -0,0 +1,153 @@
+
+#
+# Fp^2 CLass
+# M.Scott August 2018
+#
+
+import copy
+from XXX.fp import *
+
+# a+ib, where a,b are Fp, i is "imaginary" sqrt(-1) mod p
+
+
+class Fp2:
+
+    def __init__(self, a=None, b=None):
+        if b is None:
+            if a is None:
+                self.a = Fp(0)
+                self.b = Fp(0)
+            else:
+                self.a = a.copy()
+                self.b = Fp(0)
+        else:
+            self.a = a.copy()
+            self.b = b.copy()
+
+    def copy(self):
+        return copy.deepcopy(self)
+
+    def get(self):
+        return(self.a.int(), self.b.int())
+
+    def set(self, a, b):
+        self.a = Fp(a)
+        self.b = Fp(b)
+        return self
+
+    def __add__(self, other):
+        return Fp2(self.a + other.a, self.b + other.b)
+
+    def __iadd__(self, other):
+        self.a += other.a
+        self.b += other.b
+        return self
+
+    def __sub__(self, other):
+        return Fp2(self.a - other.a, self.b - other.b)
+
+    def __isub__(self, other):
+        self.a -= other.a
+        self.b -= other.b
+        return self
+
+    def __eq__(self, other):
+        return (self.a == other.a and self.b == other.b)
+
+    def __ne__(self, other):
+        return (self.a != other.a or self.b != other.b)
+
+    def conj(self):
+        return Fp2(self.a, -self.b)
+
+    def sqr(self):
+        newa = (self.a + self.b) * (self.a - self.b)
+        self.b *= self.a
+        self.b += self.b
+        self.a = newa.copy()
+        return self
+
+    def times_i(self):
+        x = self.a.copy()
+        self.a = self.b
+        self.b = x
+        return self
+
+    def __imul__(self, other):
+        t1 = self.a * other.a
+        t2 = self.b * other.b
+        t3 = other.a + other.b
+        self.b += self.a
+        self.b *= t3
+        self.b -= t1
+        self.b -= t2
+        self.a = t1 - t2
+        return self
+
+    def __mul__(self, other):
+        R = self.copy()
+        if R == other:
+            R.sqr()
+        else:
+            R *= other
+        return R
+
+    def muli(self, other):
+        return Fp2(self.a.muli(other), self.b.muli(other))
+
+    def muls(self, other):
+        return Fp2(self.a * other, self.b * other)
+
+    def __neg__(self):
+        return Fp2(-self.a, -self.b)
+
+    def real(self):
+        return self.a
+
+    def imaginary(self):
+        return self.b
+
+    def iszero(self):
+        if self.a.iszero() and self.b.iszero():
+            return True
+        return False
+
+    def isone(self):
+        if self.a.isone() and self.b.iszero():
+            return True
+        return False
+
+    def rand(self):
+        r = Fp()
+        r.rand()
+        self.a = r.copy()
+        r.rand()
+        self.b = r.copy()
+        return self
+
+    def __str__(self):			# pretty print
+        return "[%x,%x]" % (self.a.int(), self.b.int())
+
+    def mulQNR(self):				# assume p=3 mod 8, QNR=1+i
+        return Fp2(self.a - self.b, self.a + self.b)
+
+    def inverse(self):
+        w = self.conj()
+        c = self.a * self.a + self.b * self.b
+        c = c.inverse()
+        w.a *= c
+        w.b *= c
+        return w
+
+    def div2(self):
+        newa = self.a.div2()
+        newb = self.b.div2()
+        return Fp2(newa, newb)
+
+    def divQNR(self):				# assume p=3 mod 8, QNR=1+i
+        r = Fp2(self.a + self.b, self.b - self.a)
+        return r.div2()
+
+    def divQNR2(self):				# assume p=3 mod 8, QNR=1+i
+        r = Fp2(self.a + self.b, self.b - self.a)
+        return r
diff --git a/version3/python/fp4.py b/version3/python/fp4.py
new file mode 100644
index 0000000..61fb53a
--- /dev/null
+++ b/version3/python/fp4.py
@@ -0,0 +1,144 @@
+#
+# Fp^4 CLass - towered over Fp^2
+# M.Scott August 2018
+#
+
+import copy
+from XXX import curve
+from XXX.fp2 import *
+
+
+class Fp4:
+    def __init__(self, a=None, b=None):
+        if b is None:
+            if a is None:
+                self.a = Fp2()
+                self.b = Fp2()
+            else:
+                self.a = a.copy()
+                self.b = Fp2()
+        else:
+            self.a = a.copy()
+            self.b = b.copy()
+
+    def copy(self):
+        return copy.deepcopy(self)
+
+    def get(self):
+        return(self.a, self.b)
+
+    def set(self, a, b):
+        self.a = a
+        self.b = b
+        return self
+
+    def __add__(self, other):
+        return Fp4(self.a + other.a, self.b + other.b)
+
+    def __iadd__(self, other):
+        self.a += other.a
+        self.b += other.b
+        return self
+
+    def __sub__(self, other):
+        return Fp4(self.a - other.a, self.b - other.b)
+
+    def __isub__(self, other):
+        self.a -= other.a
+        self.b -= other.b
+        return self
+
+    def __eq__(self, other):
+        return (self.a == other.a and self.b == other.b)
+
+    def __ne__(self, other):
+        return (self.a != other.a or self.b != other.b)
+
+    def conj(self):
+        return Fp4(self.a, -self.b)
+
+    def sqr(self):
+        newa = (self.a + self.b) * (self.a + self.b.mulQNR())
+        self.b *= self.a
+        newa -= self.b
+        newa -= self.b.mulQNR()
+        self.b += self.b
+        self.a = newa.copy()
+        return self
+
+    def times_i(self):
+        s = self.b.copy()
+        t = self.b.copy()
+        s.times_i()
+        t += s
+        self.b = self.a
+        self.a = t
+        return self
+
+    def __imul__(self, other):
+        t1 = self.a * other.a
+        t2 = self.b * other.b
+        t3 = other.a + other.b
+        self.b += self.a
+        self.b *= t3
+        self.b -= t1
+        self.b -= t2
+        self.a = t1 + t2.mulQNR()
+        return self
+
+    def __mul__(self, other):
+        R = self.copy()
+        if R == other:
+            R.sqr()
+        else:
+            R *= other
+        return R
+
+    def muls(self, other):  # multiple Fp4	 by Fp2
+        return Fp4(self.a * other, self.b * other)
+
+    def __neg__(self):
+        return Fp4(-self.a, -self.b)
+
+    def real(self):
+        return self.a
+
+    def imaginary(self):
+        return self.b
+
+    def iszero(self):
+        if self.a.iszero() and self.b.iszero():
+            return True
+        return False
+
+    def isone(self):
+        if self.a.isone() and self.b.iszero():
+            return True
+        return False
+
+    def rand(self):
+        r = Fp2()
+        r.rand()
+        self.a = r.copy()
+        r.rand()
+        self.b = r.copy()
+        return self
+
+    def __str__(self):		# pretty print
+        return "[%s,%s]" % (self.a, self.b)
+
+    def mulQNR(self):		# assume p=3 mod 8, QNR=1+i
+        return Fp4(self.b.mulQNR(), self.a)
+
+    def inverse(self):
+        w = self.conj()
+        c = self.a * self.a - (self.b * self.b).mulQNR()
+        c = c.inverse()
+        w.a *= c
+        w.b *= c
+        return w
+
+    def powq(self):
+        X = Fp2(Fp(curve.Fra), Fp(curve.Frb))
+        X3 = X * X * X
+        return Fp4(self.a.conj(), self.b.conj() * X3)
diff --git a/version3/python/goldilocks.py b/version3/python/goldilocks.py
new file mode 100644
index 0000000..2356767
--- /dev/null
+++ b/version3/python/goldilocks.py
@@ -0,0 +1,19 @@
+# GOLDILOCKS curve constants
+
+from constants import *
+
+SHA = 'sha512'   # hash type to use with this curve
+EFS = 56   # elliptic curve field size in bytes
+CurveType = EDWARDS
+
+# field modulus
+p = 2**448 - 2**224 - 1
+r = 2**446 - 0x8335dc163bb124b65129c96fde933d8d723a70aadc873d6d54a7bb0d
+
+# elliptic curve
+A = 1
+B = -39081
+
+# generator point
+Gx = 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa955555555555555555555555555555555555555555555555555555555
+Gy = 0xae05e9634ad7048db359d6205086c2b0036ed7a035884dd7b7e36d728ad8c4b80d6565833a2a3098bbbcb2bed1cda06bdaeafbcdea9386ed
diff --git a/version3/python/mpin.py b/version3/python/mpin.py
new file mode 100644
index 0000000..4fbec4c
--- /dev/null
+++ b/version3/python/mpin.py
@@ -0,0 +1,227 @@
+
+#
+# Python 3.7 Code to implement basic MPIN protocol API
+# M.Scott August 2018
+#
+
+import hashlib
+from XXX import ecp
+from XXX import ecp2
+from XXX import curve
+from XXX import big
+from XXX.ecp import *
+from XXX.ecp2 import *
+from XXX import pair
+from XXX.fp12 import *
+
+# hash ID to point on curve
+
+
+def H(mpin_id):
+    r = curve.r
+    p = curve.p
+    h = hashlib.new(curve.SHA)
+    h.update(bytes(mpin_id, 'utf-8'))
+    x = big.from_bytes(h.digest())
+    x %= p
+    P = ECp()
+    while not P.set(x):
+        x = x + 1
+# work out co-factor
+    nb = p.bit_length()
+    cf = 1
+    cf = cf << (nb + 4) // 2
+    cf += p
+    cf //= r
+
+    if cf != 1:
+        P = cf * P
+
+    return P
+
+
+def random_generate():
+    FS = curve.EFS
+    s = big.rand(curve.r)
+    Z = big.to_bytes(s)
+    return Z
+
+
+def get_server_secret(Z):
+    Q = ecp2.generator()
+    s = big.from_bytes(Z)
+    Q = s * Q
+    return Q.toBytes()
+
+
+def get_client_secret(Z, ID):
+    P = H(ID)
+    s = big.from_bytes(Z)
+    P = s * P
+    return P.toBytes(False)
+
+# subtract pin.ID from Secret key SK to create Token
+
+
+def extract_pin(ID, PIN, SK):
+    P = H(ID)
+    P = -(PIN * P)
+    S = ECp()
+    if not S.fromBytes(SK):
+        return bytearray(0)
+    S.add(P)
+    # S.affine()
+    return S.toBytes(False)
+
+# U=xH(ID)
+
+
+def client_1(ID, X):
+    P = H(ID)
+    if X:
+        w = big.from_bytes(X)
+    else:
+        w = big.rand(curve.r)
+        X = big.to_bytes(w)
+    P = w * P
+    return (X, P.toBytes(False))
+
+# reconstitute Client secret S from Token and PIN
+# V=(x+y)S
+
+
+def client_2(X, Y, ID, PIN, TK):
+    P = H(ID)
+
+    S = ECp()
+    if not S.fromBytes(TK):
+        return bytearray(0)
+    x = big.from_bytes(X)
+    y = big.from_bytes(Y)
+
+    x = (x + y) % curve.r
+    x = curve.r - x
+
+    S.add(PIN * P)
+
+    S = x * S
+    return S.toBytes(False)
+
+# authenticate
+
+
+def server(ID, Y, SS, U, V):
+    P = H(ID)
+    y = big.from_bytes(Y)
+
+    Q = ecp2.generator()
+
+    P = y * P
+
+    sQ = ECp2()
+    if not sQ.fromBytes(SS):
+        return (False, Fp12(), Fp12())
+
+    TU = ECp()
+    if not TU.fromBytes(U):
+        return (False, bytearray(0), bytearray(0))
+
+    TV = ECp()
+    if not TV.fromBytes(V):
+        return (False, bytearray(0), bytearray(0))
+
+    TU.add(P)
+    # TU.affine()
+
+    r = pair.double_miller(Q, TV, sQ, TU)
+    r = pair.fexp(r)
+
+    if r.isone():
+        return (True, bytearray(0), bytearray(0))
+
+# failed - diagnose it
+    E = r.toBytes()
+    r = pair.e(Q, TU)
+    F = r.toBytes()
+    return (False, E, F)
+
+
+MAXPIN = 10000
+TS = 10
+TRAP = 200
+
+
+def kangaroo(E, F):
+    FS = curve.EFS
+
+    e = Fp12()
+    e.fromBytes(E)
+    f = Fp12()
+    f.fromBytes(F)
+
+# Pollards Kangaroos
+    t = f.copy()
+
+    distance = []
+    table = []
+    s = 1
+    for m in range(0, TS):
+        distance.append(s)
+        table.append(t.copy())
+        s *= 2
+        t.usqr()
+
+    t = Fp12.one()
+# set trap
+    dn = 0
+    for j in range(0, TRAP):
+        i = t.a.a.a.int() % TS
+        t *= table[i]
+        dn += distance[i]
+
+# release wild kangaroo
+    f = t.copy()
+    f.conj()
+    steps = 0
+    dm = 0
+    while dm - dn < MAXPIN:
+        steps = steps + 1
+        if steps > 4 * TRAP:
+            break
+        i = e.a.a.a.int() % TS
+        e *= table[i]
+        dm += distance[i]
+        if e == t:
+            res = dm - dn
+            break
+        if e == f:
+            res = dn - dm
+            break
+
+    if steps > 4 * TRAP or dm - dn >= MAXPIN:
+        res = 0
+    return res
+
+
+def add_G1(A, B):
+    """ Add two points in G1: C = A + B """
+    A1 = ECp()
+    B1 = ECp()
+    if not A1.fromBytes(A):
+        return None
+    if not B1.fromBytes(B):
+        return None
+    A1.add(B1)
+    return A1.toBytes(False)
+
+
+def add_G2(A, B):
+    """ Add two points in G2: C = A + B """
+    A1 = ECp2()
+    B1 = ECp2()
+    if not A1.fromBytes(A):
+        return None
+    if not B1.fromBytes(B):
+        return None
+    A1.add(B1)
+    return A1.toBytes()
diff --git a/version3/python/nist256.py b/version3/python/nist256.py
new file mode 100644
index 0000000..55418a2
--- /dev/null
+++ b/version3/python/nist256.py
@@ -0,0 +1,19 @@
+# NIST256 curve constants
+
+from constants import *
+
+SHA = 'sha256'   # hash type to use with this curve
+EFS = 32   # elliptic curve field size in bytes
+CurveType = WEIERSTRASS
+
+# field modulus
+p = 115792089210356248762697446949407573530086143415290314195533631308867097853951
+r = 115792089210356248762697446949407573529996955224135760342422259061068512044369   # group order
+
+# elliptic curve
+A = -3
+B = 0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b
+
+# generator point
+Gx = 0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296
+Gy = 0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5
diff --git a/version3/python/nist384.py b/version3/python/nist384.py
new file mode 100644
index 0000000..6ebcd38
--- /dev/null
+++ b/version3/python/nist384.py
@@ -0,0 +1,19 @@
+# NIST384 curve constants
+
+from constants import *
+
+SHA = 'sha384'   # hash type to use with this curve
+EFS = 48   # elliptic curve field size in bytes
+CurveType = WEIERSTRASS
+
+# field modulus
+p = 39402006196394479212279040100143613805079739270465446667948293404245721771496870329047266088258938001861606973112319
+r = 39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942643    # group order
+
+# elliptic curve
+A = -3
+B = 27580193559959705877849011840389048093056905856361568521428707301988689241309860865136260764883745107765439761230575
+
+# generator point
+Gx = 26247035095799689268623156744566981891852923491109213387815615900925518854738050089022388053975719786650872476732087
+Gy = 8325710961489029985546751289520108179287853048861315594709205902480503199884419224438643760392947333078086511627871
diff --git a/version3/python/nist521.py b/version3/python/nist521.py
new file mode 100644
index 0000000..242f7de
--- /dev/null
+++ b/version3/python/nist521.py
@@ -0,0 +1,20 @@
+# NIST521 curve constants
+
+from constants import *
+
+SHA = 'sha512'   # hash type to use with this curve
+EFS = 66   # elliptic curve field size in bytes
+CurveType = WEIERSTRASS
+
+# field modulus
+p = 2**521 - 1
+r = 0x1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409    # group order
+
+# elliptic curve
+A = -3
+B = 0x51953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00
+
+# generator point
+Gx = 0xc6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66
+
+Gy = 0x11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650
diff --git a/version3/python/pair.py b/version3/python/pair.py
new file mode 100644
index 0000000..e8a5323
--- /dev/null
+++ b/version3/python/pair.py
@@ -0,0 +1,317 @@
+#
+# Optimal Ate Pairing
+# M.Scott August 2018
+#
+
+from constants import *
+
+from XXX import curve
+from XXX import big
+from XXX.fp2 import *
+from XXX.fp4 import *
+from XXX.fp12 import *
+
+from XXX import ecp
+from XXX import ecp2
+
+# line function
+
+
+def g(A, B, Qx, Qy):
+    if A == B:
+        XX, YY, ZZ = A.getxyz()
+        YZ = YY * ZZ
+        XX.sqr()
+        YY.sqr()
+        ZZ.sqr()
+
+        ZZ = ZZ.muli(3 * curve.B)
+        if curve.SexticTwist == D_TYPE:
+            ZZ = ZZ.divQNR2()
+        else:
+            ZZ = ZZ.mulQNR()
+            ZZ += ZZ
+            YZ = YZ.mulQNR()
+
+        a = Fp4(-YZ.muls(Qy).muli(4), ZZ - (YY + YY))
+        if curve.SexticTwist == D_TYPE:
+            b = Fp4(XX.muli(6).muls(Qx))
+            c = Fp4()
+        else:
+            b = Fp4()
+            c = Fp4(XX.muli(6).muls(Qx))
+            c.times_i()
+        A.dbl()
+        return Fp12(a, b, c)
+    else:
+        X1, Y1, Z1 = A.getxyz()
+        X2, Y2 = B.getxy()
+        T1 = (X1 - Z1 * X2)
+        T2 = (Y1 - Z1 * Y2)
+
+        if curve.SexticTwist == D_TYPE:
+            a = Fp4(T1.muls(Qy), T2 * X2 - T1 * Y2)
+            b = Fp4(-T2.muls(Qx))
+            c = Fp4()
+        else:
+            a = Fp4(T1.muls(Qy).mulQNR(), T2 * X2 - T1 * Y2)
+            b = Fp4()
+            c = Fp4(-T2.muls(Qx))
+            c.times_i()
+        A.add(B)
+        return Fp12(a, b, c)
+
+# full pairing - miller loop followed by final exponentiation
+
+
+def e(P, Q):
+    r = miller(P, Q)
+    return fexp(r)
+
+
+def miller(P1, Q1):
+    x = curve.x
+    if curve.PairingFriendly == BN:
+        n = 6 * x
+        if curve.SignOfX == POSITIVEX:
+            n += 2
+        else:
+            n -= 2
+    else:
+        n = x
+    n3 = 3 * n
+
+    P = P1.copy()
+    Q = Q1.copy()
+
+    P.affine()
+    Q.affine()
+    A = P.copy()
+    Qx, Qy = Q.getxy()
+    nb = n3.bit_length()
+    r = Fp12.one()
+# miller loop
+    for i in range(nb - 2, 0, -1):
+        r.sqr()
+        r *= g(A, A, Qx, Qy)
+
+        if big.bit(n3, i) == 1 and big.bit(n, i) == 0:
+            r *= g(A, P, Qx, Qy)
+        if big.bit(n3, i) == 0 and big.bit(n, i) == 1:
+            r *= g(A, -P, Qx, Qy)
+
+# adjustment
+    if curve.SignOfX == NEGATIVEX:
+        r.conj()
+
+    if curve.PairingFriendly == BN:
+        KA = P.copy()
+        KA.frobenius()
+        if curve.SignOfX == NEGATIVEX:
+            A = -A
+        r *= g(A, KA, Qx, Qy)
+        KA.frobenius()
+        KA = -KA
+        r *= g(A, KA, Qx, Qy)
+
+    return r
+
+
+def double_miller(P1, Q1, U1, V1):
+    x = curve.x
+
+    if curve.PairingFriendly == BN:
+        n = 6 * x
+        if curve.SignOfX == POSITIVEX:
+            n += 2
+        else:
+            n -= 2
+    else:
+        n = x
+
+    n3 = 3 * n
+
+    P = P1.copy()
+    Q = Q1.copy()
+    U = U1.copy()
+    V = V1.copy()
+
+    P.affine()
+    Q.affine()
+    U.affine()
+    V.affine()
+    A = P.copy()
+    Qx, Qy = Q.getxy()
+    B = U.copy()
+    Wx, Wy = V.getxy()
+    nb = n3.bit_length()
+    r = Fp12.one()
+# miller loop
+    for i in range(nb - 2, 0, -1):
+        r.sqr()
+        r *= g(A, A, Qx, Qy)
+        r *= g(B, B, Wx, Wy)
+        if big.bit(n3, i) == 1 and big.bit(n, i) == 0:
+            r *= g(A, P, Qx, Qy)
+            r *= g(B, U, Wx, Wy)
+        if big.bit(n3, i) == 0 and big.bit(n, i) == 1:
+            r *= g(A, -P, Qx, Qy)
+            r *= g(B, -U, Wx, Wy)
+# adjustment
+    if curve.SignOfX == NEGATIVEX:
+        r.conj()
+
+    if curve.PairingFriendly == BN:
+        KA = P.copy()
+        KA.frobenius()
+        if curve.SignOfX == NEGATIVEX:
+            A = -A
+            B = -B
+        r *= g(A, KA, Qx, Qy)
+        KA.frobenius()
+        KA = -KA
+        r *= g(A, KA, Qx, Qy)
+
+        KB = U.copy()
+        KB.frobenius()
+
+        r *= g(B, KB, Wx, Wy)
+        KB.frobenius()
+        KB = -KB
+        r *= g(B, KB, Wx, Wy)
+
+    return r
+
+
+def fexp(r):
+    # final exp - easy part
+    t0 = r.copy()
+    r.conj()
+    r *= t0.inverse()
+
+    t0 = r.copy()
+    r.powq()
+    r.powq()
+    r *= t0
+# final exp - hard part
+    x = curve.x
+
+    if curve.PairingFriendly == BN:
+
+        res = r.copy()
+
+        t0 = res.copy()
+        t0.powq()
+        x0 = t0.copy()
+        x0.powq()
+
+        x0 *= (res * t0)
+        x0.powq()
+
+        x1 = res.copy()
+        x1.conj()
+        x4 = res.pow(x)
+        if curve.SignOfX == POSITIVEX:
+            x4.conj()
+        x3 = x4.copy()
+        x3.powq()
+
+        x2 = x4.pow(x)
+        if curve.SignOfX == POSITIVEX:
+            x2.conj()
+
+        x5 = x2.copy()
+        x5.conj()
+        t0 = x2.pow(x)
+        if curve.SignOfX == POSITIVEX:
+            t0.conj()
+
+        x2.powq()
+        res = x2.copy()
+        res.conj()
+        x4 = x4 * res
+        x2.powq()
+
+        res = t0.copy()
+        res.powq()
+        t0 *= res
+
+        t0.usqr()
+        t0 *= x4
+        t0 *= x5
+        res = x3 * x5
+        res *= t0
+        t0 *= x2
+        res.usqr()
+        res *= t0
+        res.usqr()
+        t0 = res * x1
+        res *= x0
+        t0.usqr()
+        res *= t0
+
+    else:  # its a BLS curve
+
+        # Ghamman & Fouotsa Method
+        y0 = r.copy()
+        y0.usqr()
+        y1 = y0.pow(x)
+        if curve.SignOfX == NEGATIVEX:
+            y1.conj()
+        x //= 2
+        y2 = y1.pow(x)
+        if curve.SignOfX == NEGATIVEX:
+            y2.conj()
+        x *= 2
+
+        y3 = r.copy()
+        y3.conj()
+        y1 *= y3
+        y1.conj()
+        y1 *= y2
+
+        y2 = y1.pow(x)
+        if curve.SignOfX == NEGATIVEX:
+            y2.conj()
+        y3 = y2.pow(x)
+        if curve.SignOfX == NEGATIVEX:
+            y3.conj()
+        y1.conj()
+        y3 *= y1
+
+        y1.conj()
+        y1.powq()
+        y1.powq()
+        y1.powq()
+
+        y2.powq()
+        y2.powq()
+
+        y1 *= y2
+
+        y2 = y3.pow(x)
+        if curve.SignOfX == NEGATIVEX:
+            y2.conj()
+        y2 *= y0
+        y2 *= r
+        y1 *= y2
+        y3.powq()
+        y1 *= y3
+        res = y1
+
+    return res
+
+# G=ecp.generator()
+# P=ecp2.generator()
+# pr=e(P,G)
+# print(pr)
+
+# print(pr.pow(curve.r))
+
+# P7=7*P
+# pr=e(P7,G)
+# print(pr)
+
+# G7=7*G
+# pr=e(P,G7)
+# print(pr)
diff --git a/version3/python/readme.txt b/version3/python/readme.txt
new file mode 100644
index 0000000..1cb5f32
--- /dev/null
+++ b/version3/python/readme.txt
@@ -0,0 +1,39 @@
+This Python version of the library is ideal for beginners, or for people
+interested in quickly putting together a "proof of concept" implementation
+that requires Elliptic curve or pairing based cryptography.
+
+Note this Python version is NOT for serious production use. Since the
+handling of big numbers is outside of our control, side-channel attacks
+cannot be prevented, so we have not even attempted to make this version 
+side-channel secure. Also since Python will never be fast, no extreme attempts
+at optimization have been made, and some optimizations which result in larger 
+code size have been omitted. Once the Proof of Concept has been established,
+the programmer should switch to one of the other supported languages.
+
+Some limitations: RSA is not currently supported. Also larger pairing-friendly
+curves like BLS24 and BLS48 are not supported. The curves files are not 
+currently automatically generated by the romgen utility. 
+
+Curve parameters are provided in individual files like ed25519.py and
+bn254.py. It is a simple matter to support more curves.
+
+This Python version is very small, accessible, and easy to use.
+
+--------------------------------------
+
+To see it in action, copy all of the files in this directory to a fresh directory. 
+Then execute the python3 script config.py and select the curves that you wish 
+to support. (On Linux use python3 instead of py).
+
+py config.py
+
+Select options 1 and 8, which are fixed for the example program. Select 0 
+to exit.
+
+Then run the test program 
+
+py test.py
+
+or
+
+python3 test.py
diff --git a/version3/python/sec256k1.py b/version3/python/sec256k1.py
new file mode 100644
index 0000000..d7d07d4
--- /dev/null
+++ b/version3/python/sec256k1.py
@@ -0,0 +1,19 @@
+# SEC256k1 curve constants
+
+from constants import *
+
+SHA = 'sha256'   # hash type to use with this curve
+EFS = 32   # elliptic curve field size in bytes
+CurveType = WEIERSTRASS
+
+# field modulus
+p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F
+r = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141   # group order
+
+# elliptic curve
+A = 0
+B = 7
+
+# generator point
+Gx = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798
+Gy = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8
diff --git a/version3/python/test.py b/version3/python/test.py
new file mode 100644
index 0000000..baf79cc
--- /dev/null
+++ b/version3/python/test.py
@@ -0,0 +1,122 @@
+#
+# test driver for ECDH/ECDSA and MPIN APIs
+#
+
+import sys
+import hashlib
+from constants import *
+
+import ed25519.ecdh
+import ed25519.curve
+import bn254.mpin
+
+# first test ECDH/ECDSA on curve ed25519
+
+print("Test ECDH/ECDSA on curve ED25519\n")
+salt = bytearray(8)
+for i in range(0, 8):
+    salt[i] = i + 1
+password = bytearray("mongoose".encode())
+
+AS = hashlib.pbkdf2_hmac(ed25519.curve.SHA, password, salt, 1000, 32)
+
+AS, AP = ed25519.ecdh.ECP_KeyPairGenerate(AS)
+print("Alices private key  = ", bytes(AS).hex())
+print("Alices public key   = ", bytes(AP).hex())
+
+res = ed25519.ecdh.ECP_PublicKeyValidate(AP)
+if res != 0:
+    print("Alices public Key is invalid")
+    exit
+
+SS, SP = ed25519.ecdh.ECP_KeyPairGenerate(None)
+print("Servers private key = ", bytes(SS).hex())
+print("Servers public key  = ", bytes(SP).hex())
+
+res = ed25519.ecdh.ECP_PublicKeyValidate(SP)
+if res != 0:
+    print("Servers public Key is invalid")
+    exit
+
+
+KA = ed25519.ecdh.ECP_SvdpDH(AS, SP)
+KS = ed25519.ecdh.ECP_SvdpDH(SS, AP)
+
+if KA != KS:
+    print("SVDP_DH Failed")
+    exit
+
+print("Alice's DH key = ", bytes(KA).hex())
+print("Servers DH key = ", bytes(KS).hex())
+
+M = bytearray(16)
+for i in range(0, 8):
+    M[i] = i
+
+if ed25519.curve.CurveType != MONTGOMERY:
+    print("Testing ECDSA")
+    print("Signature= ")
+    C, D = ed25519.ecdh.ECP_SpDSA(AS, M)
+
+    print("C= ", bytes(C).hex())
+    print("D= ", bytes(D).hex())
+
+    if ed25519.ecdh.ECP_SvDSA(AP, M, C, D):
+        print("Signature is Valid")
+    else:
+        print("Signature is NOT Valid")
+
+
+# Now test a simple Pairing-based protocol MPIN on curve bn254
+
+# Assign the User an ID
+print("\nNow test MPIN on curve bn254\n")
+MPIN_ID = "testuser@miracl.com"
+print("MPIN_ID: ", MPIN_ID)
+
+MS = bn254.mpin.random_generate()
+print("Master Secret: ", bytes(MS).hex())
+
+SS = bn254.mpin.get_server_secret(MS)
+print("Server Secret: ", bytes(SS).hex())
+
+# TA: Generate client secret : token is the full client secret
+CS = bn254.mpin.get_client_secret(MS, MPIN_ID)
+
+print("Client Secret: ", bytes(CS).hex())
+
+PIN = int(input("Please enter your four digit PIN to create M-Pin Token: "))
+
+TOKEN = bn254.mpin.extract_pin(MPIN_ID, PIN, CS)
+print("Token: ", bytes(TOKEN).hex())
+
+# Client first pass
+
+PIN = int(input("Please enter four digit PIN to authenticate: "))
+
+X, U = bn254.mpin.client_1(MPIN_ID,None)
+
+print("X: ", bytes(X).hex())
+print("U: ", bytes(U).hex())
+
+# Server generates Random number Y and sends it to Client
+
+Y = bn254.mpin.random_generate()
+print("Y: ", bytes(Y).hex())
+
+# Client second pass
+
+V = bn254.mpin.client_2(X, Y, MPIN_ID, PIN, TOKEN)
+print("V: ", bytes(V).hex())
+
+rtn, E, F = bn254.mpin.server(MPIN_ID, Y, SS, U, V)
+
+if rtn:
+    print("SUCCESS: Client is authenticated")
+else:
+    print("ERROR: Client is not authenticated")
+    err = bn254.mpin.kangaroo(E, F)
+    if err == 0:
+        print("Client has invalid Token")
+    else:
+        print("Client PIN is out by ", err)
diff --git a/version3/readme.txt b/version3/readme.txt
new file mode 100644
index 0000000..e648fc1
--- /dev/null
+++ b/version3/readme.txt
@@ -0,0 +1,17 @@
+**New** August 2018. A Python version of the library is now available.
+
+Several helper programs are provided to assist with the addition of
+new elliptic curves. Note that these programs will not be needed if using
+one of the supported curves. These programs must be build using the MIRACL
+library. See source code for compilation instructions
+
+bigtobig.cpp - converts to BIG number format
+
+check.cpp - checks for optimal choice of number base
+
+bestpair.cpp - finds best BN, BLS12 and BLS24 pairing-friendly curves
+(Note - the library does not currently support BLS24 curves)
+
+romgen.cpp - rough-and-ready program used to help generate ROM files for
+all of the different languages.
+
diff --git a/version3/romgen.cpp b/version3/romgen.cpp
new file mode 100644
index 0000000..507ff1b
--- /dev/null
+++ b/version3/romgen.cpp
@@ -0,0 +1,1561 @@
+/*
+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.
+*/
+
+/* ECGEN - Helper MIRACL program to generate ROM constants for curves 
+
+A bit rough-and-ready - the output might need minor syntactical corrections
+
+(MINGW build)
+
+g++ -O3 romgen.cpp big.cpp zzn.cpp ecn.cpp zzn2.cpp ecn2.cpp zzn4.cpp ecn4.cpp zzn8.cpp ecn8.cpp miracl.a -o romgen.exe
+
+
+*/
+
+#include <iostream>
+#include "big.h"
+#include "ecn.h"
+#include "zzn2.h"
+#include "ecn2.h"
+#include "ecn4.h"
+#include "ecn8.h"
+
+using namespace std;
+
+Miracl precision(100,0);
+
+char open,close,term,el=0;
+
+Big output(int chunk,int w,Big t,Big m)
+{
+	Big last,y=t;
+
+	cout << open;
+	for (int i=0;i<w;i++)
+	{
+		last=y%m;
+		cout << "0x" << last;
+		y/=m;
+		if (i==w-1) break;
+		if (el!=0) cout << el << ",";
+		else cout << ",";
+	}
+
+	if (el!=0) cout << el << close;
+	else cout << close;
+	return last;
+}
+
+#define NOT_SPECIAL 0
+#define PSEUDO_MERSENNE 1
+#define GENERALISED_MERSENNE 2
+#define MONTGOMERY_FRIENDLY 3
+
+#define WEIERSTRASS 0
+#define EDWARDS 1
+#define MONTGOMERY 2
+
+// set Frobenius constant - depends on embedding degree
+void set_frobenius_constant(ZZn2 &X, int ed)
+{
+    Big p=get_modulus();
+    switch (get_mip()->pmod8)
+    {
+    case 5:
+         X.set((Big)0,(Big)1); // = (sqrt(-2)^(p-1)/2     
+         break;
+    case 3:                    // = (1+sqrt(-1))^(p-1)/2                                
+         X.set((Big)1,(Big)1);      
+         break;
+   case 7: 
+         X.set((Big)2,(Big)1); // = (2+sqrt(-1))^(p-1)/2
+    default: break;
+    }
+	if (ed==12) X=pow(X,(p-1)/6);
+	if (ed==24) X=pow(X,(p-7)/12);
+	if (ed==48) X=pow(X,(p-19)/24);
+}
+
+void q_power_frobenius(ECn2 &A,ZZn2 &F)
+{ 
+// Fast multiplication of A by q (for Trace-Zero group members only)
+    ZZn2 x,y,z,w,r;
+
+    A.get(x,y);
+
+	w=F*F;
+	r=F;
+
+	if (get_mip()->TWIST==MR_SEXTIC_M) r=inverse(F);  // could be precalculated
+	if (get_mip()->TWIST==MR_SEXTIC_D) r=F;
+
+	w=r*r;
+	x=w*conj(x);
+	y=r*w*conj(y);
+
+    A.set(x,y);
+
+}
+
+//
+// Faster Hashing to G2 - Fuentes-Castaneda, Knapp and Rodriguez-Henriquez
+//
+
+void cofactor(ECn2& S,ZZn2 &F,Big& x)
+{
+	ECn2 T,K;
+	T=S;
+	T*=(-x);
+	T.norm();
+	K=(T+T)+T;
+	K.norm();
+	q_power_frobenius(K,F);
+	q_power_frobenius(S,F); q_power_frobenius(S,F); q_power_frobenius(S,F); 
+	S+=T; S+=K;
+	q_power_frobenius(T,F); q_power_frobenius(T,F);
+	S+=T;
+	S.norm();
+}
+
+void help()
+{
+		printf("Elliptic Curves\n");
+		printf("1. ED25519\n");
+		printf("2. C25519\n");
+		printf("3. NIST256\n");
+		printf("4. BRAINPOOL\n");
+		printf("5. ANSSI\n");
+		printf("6. HIFIVE\n");
+		printf("7. GOLDILOCKS\n");
+		printf("8. NIST384\n");
+		printf("9. C41417\n");
+		printf("10. NIST521\n");
+		printf("11. NUMS256W\n");
+		printf("12. NUMS256E\n");
+		printf("13. NUMS384W\n");
+		printf("14. NUMS384E\n");
+		printf("15. NUMS512W\n");
+		printf("16. NUMS512E\n");
+		printf("17. SECP256K1\n\n");
+
+		printf("18. BN254\n");
+		printf("19. BN254CX\n");
+		printf("20. BLS383\n");
+		printf("21. BLS381\n");
+		printf("22. FP256BN\n");
+		printf("23. FP512BN\n");
+		printf("24. BLS461\n");
+
+		printf("25. BLS24\n");
+		printf("26. BLS48\n");
+
+		printf("\nromgen curve wordlength basebits language\n");
+		printf("where wordlength is 16, 32 or 64\n");
+		printf("basebits is less than wordlength\n\n");
+		printf("Use check utility to determine best choice for basebits\n");
+		printf("language is c, cpp, java, javascript, go, rust or swift\n\n");
+}
+
+char* toupperit(char *s,int lang)
+{
+	int i;
+	static char t[50];
+	if (lang!=5) return s;
+	for (i=0;;i++)
+	{
+		t[i]=s[i];
+		if (t[i]==0) break;
+		t[i]=toupper(t[i]);
+	}
+
+	return t;
+}
+
+int main(int argc, char **argv)
+{
+	miracl *mip=&precision;
+	Big p,R,B,mc,curve_b,cru,cof,tau[9];
+	Big m,x,y,w,t,c,n,r,a,b,gx,gy,r2modp;
+	Big np,PP,TT,FF;
+	int i,A,curve,bb,chunk,words,mbits,bytes,ip=0;
+	int modtype,curvetype,curve_a,curve_b_i,cof_i,lang=0;
+	ZZn2 X;
+	ECn P;
+	ECn2 Q;
+	ECn4 QQ;
+	ECn8 Q8;
+	ZZn4 XA,YA,AA,BB;
+	ZZn8 X8,Y8;
+	ZZn2 Aa,Ab,Ba,Bb;
+	ZZn2 Xa,Ya;
+	ZZn zcru;
+	char pre0[50],pre1[50],pre2[50],pre3[50],pre4[50],pre5[50],pre6[50];
+	char post0[50],post1[50],post2[50],post3[50],post4[50],post5[50],post6[50];
+	char pre7[50],post7[50],lg[50];
+
+	char xxx[20],yyy[20],zzz[20];
+	
+	char curvename[30],fieldname[30];
+
+	argv++; argc--;
+
+	if (argc<4)
+	{
+		help();
+		return 0;
+	}
+ 
+	strcpy(curvename,argv[0]);
+
+//	curve=atoi(argv[ip++]);
+	for (i=0;;i++)
+	{
+		if (curvename[i]==0) break;
+		curvename[i]=toupper(curvename[i]);
+	}
+
+	//cout << "curvename= " << curvename << " " << strlen(curvename) << endl;
+
+	curve=0; ip++;
+	chunk=atoi(argv[ip++]);
+	bb=atoi(argv[ip++]);
+
+	strcpy(lg,argv[ip]);
+
+	if (chunk !=16 && chunk!=32 && chunk!=64) {help(); return 0;}
+	if (bb<0 || bb>=chunk) {help(); return 0;}
+
+// Specify curve constants
+
+	if (strcmp(curvename,"ED25519")==0)
+	{ // ED25519
+		curve=1;
+		printf("Curve= ED25519\n");
+		strcpy(fieldname,"25519");
+		mbits=255;                 // bits in modulus
+		words=(1+((mbits-1)/bb));  // words per Big
+		curvetype=EDWARDS;
+		modtype=PSEUDO_MERSENNE;
+		curve_a=-1;			     // Curve A parameter
+		cof=8;
+		p=pow((Big)2,mbits)-19;  // Modulus
+		r=pow((Big)2,252)+(char *)"27742317777372353535851937790883648493";   // group order
+		mip->IOBASE=16;
+		curve_b=(char *)"52036CEE2B6FFE738CC740797779E89800700A4D4141D8AB75EB4DCA135978A3";  // curve B parameter
+		gx=(char *)"216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A";       // generator point
+		gy=(char *)"6666666666666666666666666666666666666666666666666666666666666658";
+	}
+
+	if (strcmp(curvename,"C25519")==0)
+	{
+		curve=2;
+		printf("Curve= C25519\n");
+		strcpy(fieldname,"25519");
+		mbits=255;
+		words=(1+((mbits-1)/bb));
+		curvetype=MONTGOMERY;
+		modtype=PSEUDO_MERSENNE;
+		curve_a=486662;
+		cof=8;
+		p=pow((Big)2,mbits)-19;
+		r=pow((Big)2,252)+(char *)"27742317777372353535851937790883648493";
+
+		curve_b=0;
+		mip->IOBASE=16;
+		gx=(char *)"9";
+		gy=0;
+	}
+
+	if (strcmp(curvename,"NIST256")==0)
+	{
+		curve=3;
+		printf("Curve= NIST256\n");
+		strcpy(fieldname,curvename);
+		mbits=256;
+		words=(1+((mbits-1)/bb));
+		curvetype=WEIERSTRASS;
+		modtype=NOT_SPECIAL;
+		curve_a=-3;
+		cof=1;
+		p=(char *)"115792089210356248762697446949407573530086143415290314195533631308867097853951";
+		r=(char *)"115792089210356248762697446949407573529996955224135760342422259061068512044369";
+		mip->IOBASE=16;
+		curve_b=(char *)"5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b";
+		gx=(char *)"6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296";
+		gy=(char *)"4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5";
+	}
+
+	if (strcmp(curvename,"BRAINPOOL")==0)
+	{
+		curve=4;
+		printf("Curve= BRAINPOOL\n");
+		strcpy(fieldname,curvename);
+		mbits=256;
+		words=(1+((mbits-1)/bb));
+		curvetype=WEIERSTRASS;
+		modtype=NOT_SPECIAL;
+		curve_a=-3;
+		cof=1;
+		p=(char *)"76884956397045344220809746629001649093037950200943055203735601445031516197751";
+		mip->IOBASE=16;
+		r=(char *)"A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7";
+		mip->IOBASE=10;
+		curve_b=(char *)"46214326585032579593829631435610129746736367449296220983687490401182983727876";
+		mip->IOBASE=16;
+		gx=(char *)"a3e8eb3cc1cfe7b7732213b23a656149afa142c47aafbc2b79a191562e1305f4";
+		gy=(char *)"2d996c823439c56d7f7b22e14644417e69bcb6de39d027001dabe8f35b25c9be";
+	}
+
+	if (strcmp(curvename,"ANSSI")==0)
+	{
+		curve=5;
+		printf("Curve= ANSSI\n");
+		strcpy(fieldname,curvename);
+		mbits=256;
+		words=(1+((mbits-1)/bb));
+		curvetype=WEIERSTRASS;
+		modtype=NOT_SPECIAL;
+		curve_a=-3;
+		cof=1;
+		p=(char *)"109454571331697278617670725030735128145969349647868738157201323556196022393859";
+		mip->IOBASE=16;
+		r=(char *)"F1FD178C0B3AD58F10126DE8CE42435B53DC67E140D2BF941FFDD459C6D655E1";
+		mip->IOBASE=10;
+		curve_b=(char *)"107744541122042688792155207242782455150382764043089114141096634497567301547839";
+		mip->IOBASE=16;
+		gx=(char *)"b6b3d4c356c139eb31183d4749d423958c27d2dcaf98b70164c97a2dd98f5cff";
+		gy=(char *)"6142e0f7c8b204911f9271f0f3ecef8c2701c307e8e4c9e183115a1554062cfb";
+	}
+
+	if (strcmp(curvename,"HIFIVE")==0)
+	{
+		curve=6;
+		printf("Curve= HIFIVE\n");
+		strcpy(fieldname,curvename);
+		mbits=336;
+		words=(1+((mbits-1)/bb));
+		curvetype=EDWARDS;
+		modtype=PSEUDO_MERSENNE;
+		curve_a=1;
+		cof=8;
+		p=pow((Big)2,336)-3;
+		mip->IOBASE=16;
+		r=(char *)"200000000000000000000000000000000000000000071415FA9850C0BD6B87F93BAA7B2F95973E9FA805";
+		mip->IOBASE=10;
+		curve_b=(char *)"11111";
+		mip->IOBASE=16;
+		gx=(char *)"C";
+		gy=(char *)"C0DC616B56502E18E1C161D007853D1B14B46C3811C7EF435B6DB5D5650CA0365DB12BEC68505FE8632";
+	}
+
+	if (strcmp(curvename,"GOLDILOCKS")==0)
+	{
+		curve=7;
+		printf("Curve= GOLDILOCKS\n");
+		strcpy(fieldname,curvename);
+		mbits=448;
+		words=(1+((mbits-1)/bb));
+		curvetype=EDWARDS;
+		modtype=GENERALISED_MERSENNE;
+		curve_a=1;
+		cof=4;
+		p=pow((Big)2,448)-pow((Big)2,224)-1;
+		r=(p+1-(char *)"28312320572429821613362531907042076847709625476988141958474579766324")/4;
+		mip->IOBASE=10;
+		curve_b=p-39081;
+		mip->IOBASE=16;
+
+		gx=(char *)"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa955555555555555555555555555555555555555555555555555555555";
+		gy=(char *)"ae05e9634ad7048db359d6205086c2b0036ed7a035884dd7b7e36d728ad8c4b80d6565833a2a3098bbbcb2bed1cda06bdaeafbcdea9386ed";
+	}
+
+	if (strcmp(curvename,"NIST384")==0)
+	{
+		curve=8;
+		printf("Curve= NIST384\n");
+		strcpy(fieldname,curvename);
+		mbits=384;
+		words=(1+((mbits-1)/bb));
+		curvetype=WEIERSTRASS;
+		modtype=NOT_SPECIAL;
+		curve_a=-3;
+		cof=1;
+		p=(char *)"39402006196394479212279040100143613805079739270465446667948293404245721771496870329047266088258938001861606973112319";
+		r=p+1-(char *)"1388124618062372383606759648309780106643088307173319169677";
+
+		curve_b=(char *)"27580193559959705877849011840389048093056905856361568521428707301988689241309860865136260764883745107765439761230575";
+		mip->IOBASE=16;
+		gx=(char *)"aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7";
+		gy=(char *)"3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f";
+	}
+
+	if (strcmp(curvename,"C41417")==0)
+	{
+		curve=9;
+		printf("Curve= C41417\n");
+		strcpy(fieldname,curvename);
+		mbits=414;
+		words=(1+((mbits-1)/bb));
+		curvetype=EDWARDS;
+		modtype=PSEUDO_MERSENNE;
+		curve_a=1;
+		p=pow((Big)2,mbits)-17; 
+		cof=8;
+		r=pow((Big)2,411)-(char *)"33364140863755142520810177694098385178984727200411208589594759"; // Group Order
+
+		curve_b=(char *)"3617";
+		mip->IOBASE=16;
+		gx=(char *)"1a334905141443300218c0631c326e5fcd46369f44c03ec7f57ff35498a4ab4d6d6ba111301a73faa8537c64c4fd3812f3cbc595";
+		gy=(char *)"22";
+	}
+
+	if (strcmp(curvename,"NIST521")==0)
+	{
+		curve=10;
+		printf("Curve= NIST521\n");
+		strcpy(fieldname,curvename);
+		mbits=521;
+		words=(1+((mbits-1)/bb));
+		curvetype=WEIERSTRASS;
+		modtype=NOT_SPECIAL;
+		curve_a=-3;
+		cof=1;
+		p=pow((Big)2,mbits)-1; 
+
+		mip->IOBASE=16;
+		r=(char *)"1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409"; // Group Order
+		curve_b=(char *)"51953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00";
+
+		gx=(char *)"C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66";
+		gy=(char *)"11839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650";
+	}
+	
+	if (strcmp(curvename,"NUMS256W")==0)
+	{
+		curve=11;
+		printf("Curve= NUMS256W\n");
+		strcpy(fieldname,"256PMW");
+		mbits=256;
+		words=(1+((mbits-1)/bb));
+		curvetype=WEIERSTRASS;
+		modtype=PSEUDO_MERSENNE;
+		curve_a=-3;
+		cof=1;
+		p=pow((Big)2,mbits)-189; 
+
+		mip->IOBASE=16;
+		r=(char *)"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE43C8275EA265C6020AB20294751A825"; // Group Order
+		curve_b=(char *)"25581";
+		gx=(char *)"BC9ED6B65AAADB61297A95A04F42CB0983579B0903D4C73ABC52EE1EB21AACB1";
+		gy=(char *)"D08FC0F13399B6A673448BF77E04E035C955C3D115310FBB80B5B9CB2184DE9F";
+	}
+
+	if (strcmp(curvename,"NUMS256E")==0)
+	{
+		curve=12;
+		printf("Curve= NUMS256E\n");
+		strcpy(fieldname,"256PME");
+		mbits=256;
+		words=(1+((mbits-1)/bb));
+		curvetype=EDWARDS;
+		modtype=PSEUDO_MERSENNE;
+		curve_a=1;
+		cof=4;
+		p=pow((Big)2,mbits)-189; 
+
+		mip->IOBASE=16;
+		r=(char *)"4000000000000000000000000000000041955AA52F59439B1A47B190EEDD4AF5"; // Group Order
+		curve_b=(char *)"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC355";
+		gx=(char *)"8A7514FB6AEA237DCD1E3D5F69209BD60C398A0EE3083586A0DEC0902EED13DA";
+		gy=(char *)"44D53E9FD9D925C7CE9665D9A64B8010715F61D810856ED32FA616E7798A89E6";
+	}
+
+
+	if (strcmp(curvename,"NUMS384W")==0)
+	{
+		curve=13;
+		printf("Curve= NUMS384W\n");
+		strcpy(fieldname,"384PM");
+		mbits=384;
+		words=(1+((mbits-1)/bb));
+		curvetype=WEIERSTRASS;
+		modtype=PSEUDO_MERSENNE;
+		curve_a=-3;
+		cof=1;
+		p=pow((Big)2,mbits)-317; 
+
+		mip->IOBASE=16;
+		r=(char *)"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD61EAF1EEB5D6881BEDA9D3D4C37E27A604D81F67B0E61B9"; // Group Order
+		curve_b=(char *)"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF77BB";
+		gx=(char *)"757956F0B16F181C4880CA224105F1A60225C1CDFB81F9F4F3BD291B2A6CC742522EED100F61C47BEB9CBA042098152A";
+		gy=(char *)"ACDEE368E19B8E38D7E33D300584CF7EB0046977F87F739CB920837D121A837EBCD6B4DBBFF4AD265C74B8EC66180716";
+	}
+
+	if (strcmp(curvename,"NUMS384E")==0)
+	{
+		curve=14;
+		printf("Curve= NUMS384E\n");
+		strcpy(fieldname,"384PM");
+		mbits=384;
+		words=(1+((mbits-1)/bb));
+		curvetype=EDWARDS;
+		modtype=PSEUDO_MERSENNE;
+		curve_a=1;
+		cof=4;
+		p=pow((Big)2,mbits)-317; 
+
+		mip->IOBASE=16;
+		r=(char *)"3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE2471A1CB46BE1CF61E4555AAB35C87920B9DCC4E6A3897D"; // Group Order
+		curve_b=(char *)"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD19F";
+		gx=(char *)"61B111FB45A9266CC0B6A2129AE55DB5B30BF446E5BE4C005763FFA8F33163406FF292B16545941350D540E46C206BDE";
+		gy=(char *)"82983E67B9A6EEB08738B1A423B10DD716AD8274F1425F56830F98F7F645964B0072B0F946EC48DC9D8D03E1F0729392";
+	}
+
+	if (strcmp(curvename,"NUMS512W")==0)
+	{
+		curve=15;
+		printf("Curve= NUMS512W\n");
+		strcpy(fieldname,"512PM");
+		mbits=512;
+		words=(1+((mbits-1)/bb));
+		curvetype=WEIERSTRASS;
+		modtype=PSEUDO_MERSENNE;
+		curve_a=-3;
+		cof=1;
+		p=pow((Big)2,mbits)-569; 
+
+		mip->IOBASE=16;
+		r=(char *)"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5B3CA4FB94E7831B4FC258ED97D0BDC63B568B36607CD243CE153F390433555D"; // Group Order
+		curve_b=(char *)"1D99B";
+		gx=(char *)"3AC03447141D0A93DA2B7002A03D3B5298CAD83BB501F6854506E0C25306D9F95021A151076B359E93794286255615831D5D60137D6F5DE2DC8287958CABAE57";
+		gy=(char *)"943A54CA29AD56B3CE0EEEDC63EBB1004B97DBDEABBCBB8C8F4B260C7BD14F14A28415DA8B0EEDE9C121A840B25A5602CF2B5C1E4CFD0FE923A08760383527A6";
+	}
+
+	if (strcmp(curvename,"NUMS512E")==0)
+	{
+		curve=16;
+		printf("Curve= NUMS512E\n");
+		strcpy(fieldname,"512PM");
+		mbits=512;
+		words=(1+((mbits-1)/bb));
+		curvetype=EDWARDS;
+		modtype=PSEUDO_MERSENNE;
+		curve_a=1;
+		cof=4;
+		p=pow((Big)2,mbits)-569; 
+
+		mip->IOBASE=16;
+		r=(char *)"3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB4F0636D2FCF91BA9E3FD8C970B686F52A4605786DEFECFF67468CF51BEED46D"; // Group Order
+		curve_b=(char *)"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFECBEF";
+		gx=(char *)"DF8E316D128DB69C7A18CB7888D3C5332FD1E79F4DC4A38227A17EBE273B81474621C14EEE46730F78BDC992568904AD0FE525427CC4F015C5B9AB2999EC57FE";
+		gy=(char *)"6D09BFF39D49CA7198B0F577A82A256EE476F726D8259D22A92B6B95909E834120CA53F2E9963562601A06862AECC1FD0266D38A9BF1D01F326DDEC0C1E2F5E1";
+	}
+
+
+	if (strcmp(curvename,"SECP256K1")==0)
+	{ // SECP256K1
+		curve=17;
+		printf("Curve= SECP256K1\n");
+		strcpy(fieldname,"SECP256K1");
+		mbits=256;                 // bits in modulus
+		words=(1+((mbits-1)/bb));  // words per Big
+		curvetype=WEIERSTRASS;
+		/*if (chunk<64)*/ modtype=NOT_SPECIAL;
+		//modtype=PSEUDO_MERSENNE;
+		curve_a=0;			     // Curve A parameter
+		cof=1;
+		p=pow((Big)2,mbits)-pow((Big)2,32)-977;  // Modulus
+		mip->IOBASE=16;
+		r=(char *)"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141";   // group order
+
+		curve_b=(char *)"7";  // curve B parameter
+		gx=(char *)"79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798";       // generator point
+		gy=(char *)"483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8";
+	}
+
+
+	if (strcmp(curvename,"BN254")==0)
+	{
+		curve=18;
+		printf("Curve= BN254\n");
+		strcpy(fieldname,curvename);
+		mbits=254;
+		words=(1+((mbits-1)/bb));
+		curvetype=WEIERSTRASS;
+		modtype=NOT_SPECIAL;
+		curve_a=0;
+		mip->IOBASE=16;
+		x=(char *)"4080000000000001";    // Fast but not GT_STRONG parameter
+
+		p=36*pow(x,4)-36*pow(x,3)+24*x*x-6*x+1;  // Modulus
+		t=6*x*x+1;
+		r=p+1-t;                       // Group order
+		curve_b=2;
+		gx=p-1;                        // generator point in G1
+		gy=1;
+		cof=1;
+		ecurve((Big)0,curve_b,p,MR_AFFINE);
+		mip->TWIST=MR_SEXTIC_D;        // twist type
+
+		Xa.set((ZZn)0,(ZZn)-1);
+		Ya.set((ZZn)1,ZZn(0));
+		Q.set(Xa,Ya);
+
+		Q=(p-1+t)*Q;                   // generator point in G2
+		cru=(18*pow(x,3)-18*x*x+9*x-2); // cube root of unity for GLV method
+	}
+
+
+	if (strcmp(curvename,"BN254CX")==0)
+	{
+		curve=19;
+		printf("Curve= BN254CX\n");
+		strcpy(fieldname,curvename);
+		mbits=254;
+		words=(1+((mbits-1)/bb));
+		curvetype=WEIERSTRASS;
+		modtype=NOT_SPECIAL;
+		curve_a=0;
+		mip->IOBASE=16;
+		x=(char *)"4000000003C012B1";
+
+		p=36*pow(x,4)-36*pow(x,3)+24*x*x-6*x+1;
+		t=6*x*x+1;
+		r=p+1-t;
+		curve_b=2;
+		gx=p-1;
+		gy=1;
+		cof=1;
+		ecurve((Big)0,curve_b,p,MR_AFFINE);
+		mip->TWIST=MR_SEXTIC_D;
+
+		Xa.set((ZZn)0,(ZZn)-1);
+		Ya.set((ZZn)1,ZZn(0));
+		Q.set(Xa,Ya);
+
+		Q=(p-1+t)*Q;                   // generator point in G2
+		cru=(18*pow(x,3)-18*x*x+9*x-2);
+	}
+
+	if (strcmp(curvename,"BLS383")==0)
+	{
+		curve=20;
+		printf("Curve= BLS383\n");
+		strcpy(fieldname,curvename);
+		mbits=383;
+		words=(1+((mbits-1)/bb));
+		curvetype=WEIERSTRASS;
+		modtype=NOT_SPECIAL;
+		curve_a=0;
+	
+		mip->IOBASE=16;
+	//	x=(char *)"11000001000000040";              
+		x=(char *)"10008000001001200";	// SIGN_OF_X is POSITIVE
+		p=(pow(x,6)-2*pow(x,5)+2*pow(x,3)+x+1)/3;
+		t=x+1;
+		r=pow(x,4)-x*x+1;
+		cof=(p+1-t)/r;
+
+	//	gx=-2; gy=-1;
+	//	curve_b=9;
+		gx=1; gy=4;
+		curve_b=15;
+		ecurve((Big)0,curve_b,p,MR_AFFINE);
+	//	mip->TWIST=MR_SEXTIC_D;
+		mip->TWIST=MR_SEXTIC_M;
+
+		P.set(gx,gy);
+		P*=cof;
+		P.get(gx,gy);
+
+		//cout << "gx= " << gx << endl;
+		//cout << "gy= " << gy << endl;
+		//cout << "y^2= " << (gy*gy)%p << endl;
+		//cout << "x^3+b= " << (gx*gx*gx+15)%p << endl;
+
+		//while (!Q.set(randn2())) ; // probably not best way to choose this
+
+		Xa=1;
+		while (!Q.set(Xa))
+		{
+			Xa=Xa+(ZZn2)1;
+		}
+
+		TT=t*t-2*p;
+		PP=p*p;
+		FF=sqrt((4*PP-TT*TT)/3);
+		np=PP+1-(-3*FF+TT)/2;  // 2 possibilities...
+
+		Q=(np/r)*Q;
+
+		zcru=pow((ZZn)2,(p-1)/3);
+	//	zcru*=zcru;   // right cube root of unity
+		cru=(Big)zcru;
+	}
+
+	if (strcmp(curvename,"BLS381")==0)
+	{
+		curve=21;
+		printf("Curve= BLS381\n");
+		strcpy(fieldname,curvename);
+		mbits=381;
+		words=(1+((mbits-1)/bb));
+		curvetype=WEIERSTRASS;
+		modtype=NOT_SPECIAL;
+		curve_a=0;
+		mip->IOBASE=16;
+		x=(char *)"d201000000010000";              // SIGN_OF_X is NEGATIVE
+		p=(pow(x,6)+2*pow(x,5)-2*pow(x,3)-x+1)/3;
+		t=-x+1;
+		r=pow(x,4)-x*x+1;
+		cof=(p+1-t)/r;
+
+		curve_b=4;
+		ecurve((Big)0,curve_b,p,MR_AFFINE);
+		mip->TWIST=MR_SEXTIC_M;
+
+		gx=1;
+		while (!P.set(gx))
+		{
+			gx=gx+1;
+		}
+		P*=cof;
+		P.get(gx,gy);
+
+		Xa=1;
+		while (!Q.set(Xa))
+		{
+			Xa=Xa+(ZZn2)1;
+		}
+		Q.get(Xa,Ya);
+		Ya=-Ya;
+		Q.set(Xa,Ya);
+
+		TT=t*t-2*p;
+		PP=p*p;
+		FF=sqrt((4*PP-TT*TT)/3);
+		np=PP+1-(-3*FF+TT)/2;  // 2 possibilities...
+
+		Q=(np/r)*Q;
+
+		zcru=pow((ZZn)2,(p-1)/3);
+		//zcru*=zcru;   // right cube root of unity ?? if x>0 do this??
+		cru=(Big)zcru;
+	}
+
+
+	if (strcmp(curvename,"BLS461")==0)
+	{
+		curve=24;
+		printf("Curve= BLS461\n");
+		strcpy(fieldname,curvename);
+		mbits=461;
+		words=(1+((mbits-1)/bb));
+		curvetype=WEIERSTRASS;
+		modtype=NOT_SPECIAL;
+		curve_a=0;
+		mip->IOBASE=16;
+		x=(char *)"1FFFFFFBFFFE00000000";              // SIGN_OF_X is NEGATIVE
+		p=(pow(x,6)+2*pow(x,5)-2*pow(x,3)-x+1)/3;
+		t=-x+1;
+		r=pow(x,4)-x*x+1;
+		cof=(p+1-t)/r;
+
+		gx=-2; gy=-1;
+		curve_b=9;
+		ecurve((Big)0,curve_b,p,MR_AFFINE);
+		mip->TWIST=MR_SEXTIC_M;
+
+		P.set(gx,gy);
+		P*=cof;
+		P.get(gx,gy);
+
+		while (!Q.set(randn2())) ;  // probably not best way to choose this
+
+		TT=t*t-2*p;
+		PP=p*p;
+		FF=sqrt((4*PP-TT*TT)/3);
+		np=PP+1-(-3*FF+TT)/2;  // 2 possibilities...
+
+		Q=(np/r)*Q;
+
+		zcru=pow((ZZn)2,(p-1)/3);
+		//zcru*=zcru;   // right cube root of unity
+		cru=(Big)zcru;
+
+	}
+
+	if (strcmp(curvename,"FP256BN")==0)
+	{
+		curve=22;
+		printf("Curve= FP256BN\n");
+		strcpy(fieldname,curvename);
+		mbits=256;
+		words=(1+((mbits-1)/bb));
+		curvetype=WEIERSTRASS;
+		modtype=NOT_SPECIAL;
+		curve_a=0;
+		mip->IOBASE=16;
+		x=(char *)"6882F5C030B0A801";    // Slow!
+
+		p=36*pow(x,4)-36*pow(x,3)+24*x*x-6*x+1;
+		t=6*x*x+1;
+		r=p+1-t;
+		curve_b=3;
+		gx=1;
+		gy=2;
+		cof=1;
+		ecurve((Big)0,curve_b,p,MR_AFFINE);
+		mip->TWIST=MR_SEXTIC_M;
+
+
+		Q.set((ZZn2)1);
+		//while (!Q.set(randn2())) ;
+		Q=(p-1+t)*Q;
+
+		cru=(18*pow(x,3)-18*x*x+9*x-2);
+		cout << pre1 << toupperit((char *)"CURVE_Cru",lang) << post1; output(chunk,words,cru,m); cout << term << endl;
+
+	}
+
+	if (strcmp(curvename,"FP512BN")==0)
+	{
+		curve=23;
+		printf("Curve= FP512BN\n");
+		strcpy(fieldname,curvename);
+		mbits=512;
+		words=(1+((mbits-1)/bb));
+		curvetype=WEIERSTRASS;
+		modtype=NOT_SPECIAL;
+		curve_a=0;
+		mip->IOBASE=16;
+		x=(char *)"6882F5C030B0F7F010B306BB5E1BD80F";    // Slow!
+
+		p=36*pow(x,4)+36*pow(x,3)+24*x*x+6*x+1;
+		t=6*x*x+1;
+		r=p+1-t;
+		curve_b=3;
+		gx=1;
+		gy=2;
+		cof=1;
+		ecurve((Big)0,curve_b,p,MR_AFFINE);
+		mip->TWIST=MR_SEXTIC_M;
+
+		Q.set((ZZn2)1);
+		//while (!Q.set(randn2())) ;
+		Q=(p-1+t)*Q;
+
+		cru=p-(18*pow(x,3)+18*x*x+9*x+2);
+	}
+
+
+	if (strcmp(curvename,"BLS24")==0)
+	{
+		curve=25;
+		printf("Curve= BLS24\n");
+		strcpy(fieldname,curvename);
+
+		mbits=479;
+
+		words=(1+((mbits-1)/bb));
+		curvetype=WEIERSTRASS;
+		modtype=NOT_SPECIAL;
+		curve_a=0;
+		mip->IOBASE=16;
+
+// Note - this is GT-Strong curve
+
+		x=(char *)"100020011FF80";				// SIGN_OF_X is POSITIVE
+
+		//x=-x;
+
+		p=(1+x+x*x-pow(x,4)+2*pow(x,5)-pow(x,6)+pow(x,8)-2*pow(x,9)+pow(x,10))/3;
+		t=x+1;
+		r=pow(x,8)-pow(x,4)+1;
+		cof=(p+1-t)/r;
+
+		//x=-x;
+
+		gx=5; gy=12;
+		curve_b=19;
+		ecurve((Big)0,curve_b,p,MR_AFFINE);
+
+		mip->TWIST=MR_SEXTIC_M;
+
+		P.set(gx,gy);
+		P*=cof;
+
+		P.get(gx,gy);
+
+		Big x0=0;
+	
+		forever
+		{
+			ZZn4 X;
+			ZZn2 t;
+
+			x0+=1;
+			t.set((ZZn)0,(ZZn)x0);
+			X.set(t,(ZZn2)0);
+			if (!QQ.set(X)) continue;
+			break;
+		}
+
+		TT=t*t*t*t-4*p*t*t+2*p*p;
+		PP=pow(p,4);
+		FF=sqrt((4*PP-TT*TT)/3);
+		np=PP+1-(3*FF+TT)/2;
+
+		QQ=(np/r)*QQ;
+
+//cout << "QQ= " << QQ << endl;
+//cout << "2*QQ= " << QQ+QQ << endl;
+//cout << "3*QQ= " << (QQ+QQ)+QQ << endl;
+
+		zcru=pow((ZZn)2,(p-1)/3);
+		//zcru*=zcru;   // right cube root of unity -  not for M-TYPE
+		cru=(Big)zcru;
+	}
+
+
+	if (strcmp(curvename,"BLS48")==0)
+	{
+		curve=26;
+		printf("Curve= BLS48\n");
+		strcpy(fieldname,curvename);
+
+		mbits=556;
+
+		words=(1+((mbits-1)/bb));
+		curvetype=WEIERSTRASS;
+		modtype=NOT_SPECIAL;
+		curve_a=0;
+		mip->IOBASE=16;
+
+// Note - this is GT-Strong curve
+
+		x=(char *)"7DE40020";				// SIGN_OF_X is POSITIVE
+
+		r=pow(x,16)-pow(x,8)+1;
+		p=r*(((x-1)*(x-1))/3)+x;
+		t=x+1;
+		cof=(p+1-t)/r;
+
+// p=19 mod 24
+
+		gx=2; gy=5;
+		curve_b=17;
+		ecurve((Big)0,curve_b,p,MR_AFFINE);
+
+		mip->TWIST=MR_SEXTIC_M;
+
+		P.set(gx,gy);
+		P*=cof;
+
+		P.get(gx,gy);
+
+		Big x0=0;
+	
+		forever
+		{
+			ZZn8 XX;
+			ZZn4 X;
+			ZZn2 t;
+
+			x0+=1;
+			t.set((ZZn)0,(ZZn)x0);
+			X.set(t,(ZZn2)0);
+			XX.set(X,(ZZn4)0);
+			if (!Q8.set(X)) continue;
+			break;
+		}
+
+
+		tau[0]=2;  // count points on twist over extension p^8
+		tau[1]=t;
+		for (int jj=1;jj<8;jj++ ) tau[jj+1]=t*tau[jj]-p*tau[jj-1];
+
+		TT=tau[8];
+
+		PP=pow(p,8);
+		FF=sqrt((4*PP-TT*TT)/3);
+		np=PP+1-(3*FF+TT)/2;  //?
+
+		Q8=(np/r)*Q8;
+
+//cout << "Q8= " << Q8 << endl;
+//cout << "r*Q8= " << r*Q8 << endl;
+//cout << "2*QQ= " << QQ+QQ << endl;
+//cout << "3*QQ= " << (QQ+QQ)+QQ << endl;
+
+		zcru=pow((ZZn)2,(p-1)/3);
+		//zcru*=zcru;   // right cube root of unity -  not for M-TYPE
+		cru=(Big)zcru;
+	}
+
+	if (curve==0) {help(); return 0;}
+
+	bytes=mbits/8;
+	if (mbits%8!=0) bytes++;
+	bytes*=8;
+
+
+	lang=0;
+	if (strcmp(lg,"c")==0)
+	{
+		open='{';
+		close='}';
+		term=';';
+		lang=1;
+		if (chunk==64) el='L';
+
+		sprintf(xxx,"_%d_%d ",bytes,bb);
+
+		sprintf(pre0,"const int ");
+		sprintf(pre1,"const BIG%s",xxx);
+		sprintf(pre2,"const chunk ");
+		sprintf(pre3,"const BIG%s",xxx);
+		sprintf(pre4,"const BIG%s",xxx);
+		sprintf(pre5,"const BIG%s",xxx);
+		sprintf(pre6,"const BIG%s",xxx);
+		sprintf(pre7,"const BIG%s",xxx);
+
+		sprintf(zzz,"_%s",curvename);
+		sprintf(yyy,"_%s",fieldname);
+
+		sprintf(post0,"%s= ",zzz);
+		sprintf(post1,"%s= ",zzz);
+		sprintf(post2,"%s= ",yyy);
+		sprintf(post3,"%s[2]= ",zzz);
+		sprintf(post4,"%s[2][2]= ",zzz);
+		sprintf(post5,"%s[4]= ",zzz);
+		sprintf(post6,"%s[4][4]= ",zzz);
+		sprintf(post7,"%s= ",yyy);
+
+	}
+
+	if (strcmp(lg,"cpp")==0)
+	{
+		open='{';
+		close='}';
+		term=';';
+		lang=7;
+		if (chunk==64) el='L';
+
+		strcpy(pre0,"const int ");
+		strcpy(pre1,"const BIG ");
+		strcpy(pre2,"const chunk ");
+		strcpy(pre3,"const BIG ");
+		strcpy(pre4,"const BIG ");
+		strcpy(pre5,"const BIG ");
+		strcpy(pre6,"const BIG ");
+		strcpy(pre7,"const BIG ");
+
+		strcpy(post0,"= ");
+		strcpy(post1,"= ");
+		strcpy(post2,"= ");
+		strcpy(post3,"[2]= ");
+		strcpy(post4,"[2][2]= ");
+		strcpy(post5,"[4]= ");
+		strcpy(post6,"[4][4]= ");
+		strcpy(post7,"= ");
+
+	}
+
+	if (strcmp(lg,"java")==0)
+	{
+		open='{';
+		close='}';
+		term=';';
+		lang=2;
+		if (chunk==64) 
+		{	
+			el='L';
+			strcpy(pre0,"public static final int ");
+			strcpy(pre1,"public static final long[] ");
+			strcpy(pre2,"public static final long ");
+			strcpy(pre3,"public static final long[][] ");
+			strcpy(pre4,"public static final long[][][] ");
+			strcpy(pre5,"public static final long[][] ");
+			strcpy(pre6,"public static final long[][][] ");
+			strcpy(pre7,"public static final long[] ");
+		}
+		else
+		{
+			strcpy(pre0,"public static final int ");
+			strcpy(pre1,"public static final int[] ");
+			strcpy(pre2,"public static final int ");
+			strcpy(pre3,"public static final int[][] ");
+			strcpy(pre4,"public static final int[][][] ");
+			strcpy(pre5,"public static final int[][] ");
+			strcpy(pre6,"public static final int[][][] ");
+			strcpy(pre7,"public static final int[] ");
+
+		}
+		strcpy(post0,"= ");
+		strcpy(post1,"= ");
+		strcpy(post2,"= ");
+		strcpy(post3,"= ");
+		strcpy(post4,"= ");
+		strcpy(post5,"= ");
+		strcpy(post6,"= ");
+		strcpy(post7,"= ");
+
+	}
+
+	if (strcmp(lg,"javascript")==0)
+	{
+		open='[';
+		close=']';
+		term=',';
+		lang=3;
+		strcpy(pre0,"");
+		strcpy(pre1,"");
+		strcpy(pre2,"");
+		strcpy(pre3,"");
+		strcpy(pre4,"");
+		strcpy(pre5,"");
+		strcpy(pre6,"");
+		strcpy(pre7,"");
+		strcpy(post0,": ");
+		strcpy(post1,": ");
+		strcpy(post2,": ");
+		strcpy(post3,": ");
+		strcpy(post4,": ");
+		strcpy(post5,": ");
+		strcpy(post6,": ");
+		strcpy(post7,": ");
+	}
+
+	if (strcmp(lg,"go")==0)
+	{
+		open='{';
+		close='}';
+		term=' ';
+		lang=4;
+		strcpy(pre0,"const ");
+		strcpy(pre1,"var ");
+		strcpy(pre2,"const ");
+		strcpy(pre3,"var ");
+		strcpy(pre4,"var ");
+		strcpy(pre5,"var ");
+		strcpy(pre6,"var ");
+		strcpy(pre7,"var ");
+		strcpy(post0," int= ");
+		strcpy(post1,"= [...]Chunk ");
+		strcpy(post2," Chunk=");
+		sprintf(post3,"=[2][%d]Chunk ",words);
+		sprintf(post4,"=[2][2][%d]Chunk ",words);
+		sprintf(post5,"=[4][%d]Chunk ",words);
+		sprintf(post6,"=[4][4][%d]Chunk ",words);
+		strcpy(post7,"= [...]Chunk ");
+	}
+
+	if (strcmp(lg,"rust")==0)
+	{
+		open='[';
+		close=']';
+		term=';';
+		lang=5;
+		strcpy(pre0,"pub const ");
+		strcpy(pre1,"pub const ");
+		strcpy(pre2,"pub const ");
+		strcpy(pre3,"pub const ");
+		strcpy(pre4,"pub const ");
+		strcpy(pre5,"pub const ");
+		strcpy(pre6,"pub const ");
+		strcpy(pre7,"pub const ");
+		strcpy(post0,":isize = ");
+		strcpy(post1,":[Chunk;NLEN]=");
+		strcpy(post2,":Chunk=");
+		strcpy(post3,":[[Chunk;NLEN];2]=");
+		strcpy(post4,":[[[Chunk;NLEN];2];2]=");
+		strcpy(post5,":[[Chunk;NLEN];4]=");
+		strcpy(post6,":[[[Chunk;NLEN];4];4]=");
+		strcpy(post7,":[Chunk;NLEN]=");
+
+	}
+
+	if (strcmp(lg,"swift")==0)
+	{
+		open='[';
+		close=']';
+		term=' ';
+		lang=6;
+		strcpy(pre0,"static let ");
+		strcpy(pre1,"static public let ");
+		strcpy(pre2,"static let ");
+		strcpy(pre3,"static let ");
+		strcpy(pre4,"static let ");
+		strcpy(pre5,"static let ");
+		strcpy(pre6,"static let ");
+		strcpy(pre7,"static let ");
+		strcpy(post0,":Int = ");
+		strcpy(post1,":[Chunk] = ");
+		strcpy(post2,":Chunk = ");
+		strcpy(post3,":[[Chunk]] = ");
+		strcpy(post4,":[[[Chunk]]] = ");
+		strcpy(post5,":[[Chunk]] = ");
+		strcpy(post6,":[[[Chunk]]] = ");
+		strcpy(post7,":[Chunk] = ");
+	}
+
+
+	if (lang==0) {help(); return 0;}
+
+	//cout << "\nMOD8 = " << p%8 << endl;
+
+	m=pow((Big)2,bb);
+
+	cout << "*** rom field parameters*****" << endl;
+	cout << "// Base Bits= " << bb << endl; 
+
+	cout << pre7 << toupperit((char *)"Modulus",lang) << post7; mc=output(chunk,words,p,m); cout << term << endl;
+	r2modp=pow((Big)2,2*words*bb)%p;
+
+
+//cout << "\ngx*R2modp= " << r2modp*gx << endl;
+//cout << "mod p = " << redc(r2modp*gx) << endl << endl;
+
+	cout << pre7 << toupperit((char *)"R2modp",lang) << post7; output(chunk,words,r2modp,m); cout << term << endl;
+
+
+
+	if (modtype==NOT_SPECIAL)
+		cout << pre2 << toupperit((char *)"MConst",lang)  << post2 << "0x" << inverse(m-p%m,m);	
+
+	if (modtype==MONTGOMERY_FRIENDLY)
+		cout << pre2 << toupperit((char *)"MConst",lang) << post2 << "0x" << mc+1;	
+
+	if (modtype==PSEUDO_MERSENNE)
+		cout << pre2 << toupperit((char *)"MConst",lang)  << post2 << "0x" << pow((Big)2,mbits)-p;	
+	
+	if (modtype==GENERALISED_MERSENNE)
+		cout << pre2 << toupperit((char *)"MConst",lang)  << post2 << "0x1";	
+	
+	if (el!=0) cout << "L;" << endl;
+	else cout << term << endl;
+
+
+	if (curve>17)
+	{ // Frobenius constants -  depend on embedding degree
+		if (curve<25)
+			set_frobenius_constant(X,12);
+		else
+		{
+			if (curve==25) set_frobenius_constant(X,24);
+			if (curve==26) set_frobenius_constant(X,48);
+		}
+
+		X.get(a,b);
+		cout << pre1 << toupperit((char *)"Fra",lang) << post7; output(chunk,words,a,m); cout << term << endl;
+		cout << pre1 << toupperit((char *)"Frb",lang) << post7; output(chunk,words,b,m); cout << term << endl;
+
+	}
+
+	cout << endl;
+	cout << "//*** rom curve parameters *****" << endl;
+	cout << "// Base Bits= " << bb << endl; 
+	cout << "\n" << pre0 << "CURVE_A"  << post0 << curve_a << term << endl;
+
+	curve_b_i=toint(curve_b);
+	if (curve_b_i==MR_TOOBIG) 
+	{
+		curve_b_i=toint(p-curve_b);
+		if (curve_b_i==MR_TOOBIG)
+			curve_b_i=0;
+		else curve_b_i=-curve_b_i;
+	}
+
+	cof_i=toint(cof);
+	if (cof_i==MR_TOOBIG) 
+		cof_i=0;
+
+
+	cout << pre0 << toupperit((char *)"CURVE_Cof_I",lang) << post0 << cof_i << term << endl;
+	cout << pre1 << toupperit((char *)"CURVE_Cof",lang) << post1; output(chunk,words,cof,m); cout << term << endl;
+	cout << pre0 << "CURVE_B_I" << post0 << curve_b_i << term << endl;
+	cout << pre1 << "CURVE_B" << post1; output(chunk,words,curve_b,m); cout << term << endl;
+	cout << pre1 << toupperit((char *)"CURVE_Order",lang) << post1; output(chunk,words,r,m); cout << term << endl;
+	cout << pre1 << toupperit((char *)"CURVE_Gx",lang) << post1; output(chunk,words,gx,m); cout << term << endl;
+	cout << pre1 << toupperit((char *)"CURVE_Gy",lang) << post1; output(chunk,words,gy,m); cout << term << endl;
+	
+// BN curves
+	if (curve==18 || curve==19 || curve==22 || curve==23)
+	{
+		cout << endl;
+
+		cout << pre1 << toupperit((char *)"CURVE_Bnx",lang) << post1; output(chunk,words,x,m); cout << term << endl;
+		cout << pre1 << toupperit((char *)"CURVE_Cru",lang) << post1; output(chunk,words,cru,m); cout << term << endl;
+
+		Q.get(Xa,Ya);
+		Xa.get(a,b);
+		cout << pre1 << toupperit((char *)"CURVE_Pxa",lang) << post1; output(chunk,words,a,m); cout << term << endl;
+		cout << pre1 << toupperit((char *)"CURVE_Pxb",lang) << post1; output(chunk,words,b,m); cout << term << endl;
+		Ya.get(a,b);
+		cout << pre1 << toupperit((char *)"CURVE_Pya",lang) << post1; output(chunk,words,a,m); cout << term << endl;
+		cout << pre1 << toupperit((char *)"CURVE_Pyb",lang) << post1; output(chunk,words,b,m); cout << term << endl;
+
+		cout << pre3 << "CURVE_W"  << post3 << open; output(chunk,words,6*x*x-4*x+1,m);cout << ","; output(chunk,words,(2*x-1),m); cout << close << term << endl;
+		cout << pre4 << "CURVE_SB" << post4 << open; cout << open; output(chunk,words,6*x*x-2*x,m); cout << ","; output(chunk,words,(2*x-1),m); cout << close;cout << ","; cout << open; output(chunk,words,(2*x-1),m); cout << ","; output(chunk,words,r-(6*x*x-4*x+1),m); cout << close; cout << close << term  << endl;
+
+		cout << pre5 << "CURVE_WB" << post5 << open; output(chunk,words,2*x*x-3*x+1,m); cout << ","; output(chunk,words,12*x*x*x-8*x*x+x,m); 
+		cout << ","; output(chunk,words,6*x*x*x-4*x*x+x,m); cout << ","; output(chunk,words,2*x*x-x,m); cout << close << term << endl;
+	
+		cout << pre6 << "CURVE_BB" << post6 << open; 
+		cout << open;
+		output(chunk,words,r-x+1,m); 
+		cout << ","; output(chunk,words,r-x,m); 
+		cout << ","; output(chunk,words,r-x,m); 
+		cout << ","; output(chunk,words,2*x,m); 
+		cout << close;
+
+		cout << ","; cout << open;output(chunk,words,2*x-1,m); 
+		cout << ","; output(chunk,words,r-x,m); 
+		cout << ","; output(chunk,words,r-x+1,m); 
+		cout << ","; output(chunk,words,r-x,m); 
+		cout << close;
+		cout << ","; cout << open; output(chunk,words,2*x,m); 
+		cout << ","; output(chunk,words,2*x-1,m); 
+		cout << ","; output(chunk,words,2*x-1,m); 
+		cout << ","; output(chunk,words,2*x-1,m); 
+		cout << close;
+
+		cout << ","; cout << open; output(chunk,words,x+1,m); 
+		cout << ","; output(chunk,words,4*x-2,m); 
+		cout << ","; output(chunk,words,r-2*x-1,m); 
+		cout << ","; output(chunk,words,x+1,m); 
+		cout << close;
+		cout << close << term << endl;
+
+	}
+
+//BLS curves
+	if (curve==20 || curve==21 || curve==24)
+	{
+		cout << endl;
+
+		cout << pre1 << toupperit((char *)"CURVE_Bnx",lang) << post1 ; output(chunk,words,x,m); cout << term << endl;
+		cout << pre1 << toupperit((char *)"CURVE_Cru",lang) << post1; output(chunk,words,cru,m); cout << term << endl;
+
+		Q.get(Xa,Ya);
+		Xa.get(a,b);
+		cout << pre1 << toupperit((char *)"CURVE_Pxa",lang) << post1; output(chunk,words,a,m); cout << term << endl;
+		cout << pre1 << toupperit((char *)"CURVE_Pxb",lang) << post1; output(chunk,words,b,m); cout << term << endl;
+		Ya.get(a,b);
+		cout << pre1 << toupperit((char *)"CURVE_Pya",lang) << post1; output(chunk,words,a,m); cout << term << endl;
+		cout << pre1 << toupperit((char *)"CURVE_Pyb",lang) << post1; output(chunk,words,b,m); cout << term << endl;
+
+		Q*=r;
+		if (!Q.iszero())
+		{
+			cout << "**** Failed ****" << endl;
+			cout << "\nQ= " << Q << endl << endl;
+		}
+
+		cout << pre3 << "CURVE_W" << post3 << open; output(chunk,words,(Big)0,m);cout << ","; output(chunk,words,(Big)0,m); cout << close << term << endl;
+		cout << pre4 << "CURVE_SB" << post4 << open; cout << open; output(chunk,words,(Big)0,m); cout << ","; output(chunk,words,(Big)0,m); cout << close;cout << ","; cout << open; output(chunk,words,(Big)0,m); cout << ","; output(chunk,words,(Big)0,m); cout << close; cout << close << term << endl;
+
+		cout << pre5 << "CURVE_WB" << post5 << open; output(chunk,words,(Big)0,m); cout << ","; output(chunk,words,(Big)0,m); 
+		cout << ","; output(chunk,words,(Big)0,m); cout << ","; output(chunk,words,(Big)0,m); cout << close << term << endl;
+	
+		cout << pre6 << "CURVE_BB" << post6 << open; 
+		cout << open;
+		output(chunk,words,(Big)0,m); 
+		cout << ","; output(chunk,words,(Big)0,m); 
+		cout << ","; output(chunk,words,(Big)0,m); 
+		cout << ","; output(chunk,words,(Big)0,m); 
+		cout << close;
+
+		cout << ","; cout << open;output(chunk,words,(Big)0,m); 
+		cout << ","; output(chunk,words,(Big)0,m); 
+		cout << ","; output(chunk,words,(Big)0,m); 
+		cout << ","; output(chunk,words,(Big)0,m); 
+		cout << close;
+		cout << ","; cout << open; output(chunk,words,(Big)0,m); 
+		cout << ","; output(chunk,words,(Big)0,m); 
+		cout << ","; output(chunk,words,(Big)0,m); 
+		cout << ","; output(chunk,words,(Big)0,m); 
+		cout << close;
+
+		cout << ","; cout << open; output(chunk,words,(Big)0,m); 
+		cout << ","; output(chunk,words,(Big)0,m); 
+		cout << ","; output(chunk,words,(Big)0,m); 
+		cout << ","; output(chunk,words,(Big)0,m); 
+		cout << close;
+		cout << close << term << endl;
+
+	}
+
+
+
+	if (curve==25)
+	{
+		cout << endl;
+
+		cout << pre1 << toupperit((char *)"CURVE_Bnx",lang) << post1 ; output(chunk,words,x,m); cout << term << endl;
+		cout << pre1 << toupperit((char *)"CURVE_Cru",lang) << post1; output(chunk,words,cru,m); cout << term << endl;
+
+		QQ.get(XA,YA);
+		XA.get(Aa,Bb);
+		Aa.get(a,b);
+		cout << pre1 << toupperit((char *)"CURVE_Pxaa",lang) << post1; output(chunk,words,a,m); cout << term << endl;
+		cout << pre1 << toupperit((char *)"CURVE_Pxab",lang) << post1; output(chunk,words,b,m); cout << term << endl;
+		Bb.get(a,b);
+		cout << pre1 << toupperit((char *)"CURVE_Pxba",lang) << post1; output(chunk,words,a,m); cout << term << endl;
+		cout << pre1 << toupperit((char *)"CURVE_Pxbb",lang) << post1; output(chunk,words,b,m); cout << term << endl;
+
+		YA.get(Aa,Bb);
+		Aa.get(a,b);
+		cout << pre1 << toupperit((char *)"CURVE_Pyaa",lang) << post1; output(chunk,words,a,m); cout << term << endl;
+		cout << pre1 << toupperit((char *)"CURVE_Pyab",lang) << post1; output(chunk,words,b,m); cout << term << endl;
+		Bb.get(a,b);
+		cout << pre1 << toupperit((char *)"CURVE_Pyba",lang) << post1; output(chunk,words,a,m); cout << term << endl;
+		cout << pre1 << toupperit((char *)"CURVE_Pybb",lang) << post1; output(chunk,words,b,m); cout << term << endl;
+		
+
+		QQ*=r;
+		if (!Q.iszero())
+		{
+			cout << "**** Failed ****" << endl;
+			cout << "\nQQ= " << QQ << endl << endl;
+		}
+
+		cout << pre3 << "CURVE_W" << post3 << open; output(chunk,words,(Big)0,m);cout << ","; output(chunk,words,(Big)0,m); cout << close << term << endl;
+		cout << pre4 << "CURVE_SB" << post4 << open; cout << open; output(chunk,words,(Big)0,m); cout << ","; output(chunk,words,(Big)0,m); cout << close;cout << ","; cout << open; output(chunk,words,(Big)0,m); cout << ","; output(chunk,words,(Big)0,m); cout << close; cout << close << term << endl;
+
+		cout << pre5 << "CURVE_WB" << post5 << open; output(chunk,words,(Big)0,m); cout << ","; output(chunk,words,(Big)0,m); 
+		cout << ","; output(chunk,words,(Big)0,m); cout << ","; output(chunk,words,(Big)0,m); cout << close << term << endl;
+	
+		cout << pre6 << "CURVE_BB" << post6 << open; 
+		cout << open;
+		output(chunk,words,(Big)0,m); 
+		cout << ","; output(chunk,words,(Big)0,m); 
+		cout << ","; output(chunk,words,(Big)0,m); 
+		cout << ","; output(chunk,words,(Big)0,m); 
+		cout << close;
+
+		cout << ","; cout << open;output(chunk,words,(Big)0,m); 
+		cout << ","; output(chunk,words,(Big)0,m); 
+		cout << ","; output(chunk,words,(Big)0,m); 
+		cout << ","; output(chunk,words,(Big)0,m); 
+		cout << close;
+		cout << ","; cout << open; output(chunk,words,(Big)0,m); 
+		cout << ","; output(chunk,words,(Big)0,m); 
+		cout << ","; output(chunk,words,(Big)0,m); 
+		cout << ","; output(chunk,words,(Big)0,m); 
+		cout << close;
+
+		cout << ","; cout << open; output(chunk,words,(Big)0,m); 
+		cout << ","; output(chunk,words,(Big)0,m); 
+		cout << ","; output(chunk,words,(Big)0,m); 
+		cout << ","; output(chunk,words,(Big)0,m); 
+		cout << close;
+		cout << close << term << endl;
+
+	}
+
+	if (curve==26)
+	{
+		cout << endl;
+
+		cout << pre1 << toupperit((char *)"CURVE_Bnx",lang) << post1 ; output(chunk,words,x,m); cout << term << endl;
+		cout << pre1 << toupperit((char *)"CURVE_Cru",lang) << post1; output(chunk,words,cru,m); cout << term << endl;
+
+		Q8.get(X8,Y8);
+		X8.get(AA,BB);
+
+		AA.get(Aa,Bb);
+		Aa.get(a,b);
+		cout << pre1 << toupperit((char *)"CURVE_Pxaaa",lang) << post1; output(chunk,words,a,m); cout << term << endl;
+		cout << pre1 << toupperit((char *)"CURVE_Pxaab",lang) << post1; output(chunk,words,b,m); cout << term << endl;
+		Bb.get(a,b);
+		cout << pre1 << toupperit((char *)"CURVE_Pxaba",lang) << post1; output(chunk,words,a,m); cout << term << endl;
+		cout << pre1 << toupperit((char *)"CURVE_Pxabb",lang) << post1; output(chunk,words,b,m); cout << term << endl;
+
+		BB.get(Aa,Bb);
+		Aa.get(a,b);
+		cout << pre1 << toupperit((char *)"CURVE_Pxbaa",lang) << post1; output(chunk,words,a,m); cout << term << endl;
+		cout << pre1 << toupperit((char *)"CURVE_Pxbab",lang) << post1; output(chunk,words,b,m); cout << term << endl;
+		Bb.get(a,b);
+		cout << pre1 << toupperit((char *)"CURVE_Pxbba",lang) << post1; output(chunk,words,a,m); cout << term << endl;
+		cout << pre1 << toupperit((char *)"CURVE_Pxbbb",lang) << post1; output(chunk,words,b,m); cout << term << endl;
+
+		Y8.get(AA,BB);
+
+		AA.get(Aa,Bb);
+		Aa.get(a,b);
+		cout << pre1 << toupperit((char *)"CURVE_Pyaaa",lang) << post1; output(chunk,words,a,m); cout << term << endl;
+		cout << pre1 << toupperit((char *)"CURVE_Pyaab",lang) << post1; output(chunk,words,b,m); cout << term << endl;
+		Bb.get(a,b);
+		cout << pre1 << toupperit((char *)"CURVE_Pyaba",lang) << post1; output(chunk,words,a,m); cout << term << endl;
+		cout << pre1 << toupperit((char *)"CURVE_Pyabb",lang) << post1; output(chunk,words,b,m); cout << term << endl;
+
+		BB.get(Aa,Bb);
+		Aa.get(a,b);
+		cout << pre1 << toupperit((char *)"CURVE_Pybaa",lang) << post1; output(chunk,words,a,m); cout << term << endl;
+		cout << pre1 << toupperit((char *)"CURVE_Pybab",lang) << post1; output(chunk,words,b,m); cout << term << endl;
+		Bb.get(a,b);
+		cout << pre1 << toupperit((char *)"CURVE_Pybba",lang) << post1; output(chunk,words,a,m); cout << term << endl;
+		cout << pre1 << toupperit((char *)"CURVE_Pybbb",lang) << post1; output(chunk,words,b,m); cout << term << endl;
+		
+
+		Q8*=r;
+		if (!Q.iszero())
+		{
+			cout << "**** Failed ****" << endl;
+			cout << "\nQQ= " << QQ << endl << endl;
+		}
+
+		cout << pre3 << "CURVE_W" << post3 << open; output(chunk,words,(Big)0,m);cout << ","; output(chunk,words,(Big)0,m); cout << close << term << endl;
+		cout << pre4 << "CURVE_SB" << post4 << open; cout << open; output(chunk,words,(Big)0,m); cout << ","; output(chunk,words,(Big)0,m); cout << close;cout << ","; cout << open; output(chunk,words,(Big)0,m); cout << ","; output(chunk,words,(Big)0,m); cout << close; cout << close << term << endl;
+
+		cout << pre5 << "CURVE_WB" << post5 << open; output(chunk,words,(Big)0,m); cout << ","; output(chunk,words,(Big)0,m); 
+		cout << ","; output(chunk,words,(Big)0,m); cout << ","; output(chunk,words,(Big)0,m); cout << close << term << endl;
+	
+		cout << pre6 << "CURVE_BB" << post6 << open; 
+		cout << open;
+		output(chunk,words,(Big)0,m); 
+		cout << ","; output(chunk,words,(Big)0,m); 
+		cout << ","; output(chunk,words,(Big)0,m); 
+		cout << ","; output(chunk,words,(Big)0,m); 
+		cout << close;
+
+		cout << ","; cout << open;output(chunk,words,(Big)0,m); 
+		cout << ","; output(chunk,words,(Big)0,m); 
+		cout << ","; output(chunk,words,(Big)0,m); 
+		cout << ","; output(chunk,words,(Big)0,m); 
+		cout << close;
+		cout << ","; cout << open; output(chunk,words,(Big)0,m); 
+		cout << ","; output(chunk,words,(Big)0,m); 
+		cout << ","; output(chunk,words,(Big)0,m); 
+		cout << ","; output(chunk,words,(Big)0,m); 
+		cout << close;
+
+		cout << ","; cout << open; output(chunk,words,(Big)0,m); 
+		cout << ","; output(chunk,words,(Big)0,m); 
+		cout << ","; output(chunk,words,(Big)0,m); 
+		cout << ","; output(chunk,words,(Big)0,m); 
+		cout << close;
+		cout << close << term << endl;
+
+	}
+
+
+}
diff --git a/version3/rust/BenchtestALL.rs b/version3/rust/BenchtestALL.rs
new file mode 100644
index 0000000..7c0cf91
--- /dev/null
+++ b/version3/rust/BenchtestALL.rs
@@ -0,0 +1,970 @@
+/*
+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.
+*/
+
+extern crate amcl;
+
+use std::str;
+use std::io;
+
+use amcl::arch;
+use amcl::rand::RAND;
+
+use std::time::Instant;
+
+const MIN_ITERS:isize=10;
+const MIN_TIME: isize=10;
+
+
+fn ed25519(mut rng: &mut RAND)
+{
+	use amcl::ed25519;
+	use amcl::ed25519::ecp;
+	use amcl::ed25519::fp;
+	use amcl::ed25519::big;	
+	use amcl::ed25519::rom;
+	let mut fail=false;	
+	println!("\nTesting/Timing ed25519 ECC");
+
+	if ecp::CURVETYPE==ecp::WEIERSTRASS {
+		println!("Weierstrass parameterization");
+	}		
+	if ecp::CURVETYPE==ecp::EDWARDS {
+		println!("Edwards parameterization");
+	}
+	if ecp::CURVETYPE==ecp::MONTGOMERY {
+		println!("Montgomery parameterization");
+	}
+
+	if fp::MODTYPE==fp::PSEUDO_MERSENNE {
+		println!("Pseudo-Mersenne Modulus");
+	}
+	if fp::MODTYPE==fp::MONTGOMERY_FRIENDLY {
+		println!("Montgomery friendly Modulus");
+	}
+	if fp::MODTYPE==fp::GENERALISED_MERSENNE {
+		println!("Generalised-Mersenne Modulus");
+	}
+	if fp::MODTYPE==fp::NOT_SPECIAL {
+		println!("Not special Modulus");
+	}
+
+	println!("Modulus size {:} bits",fp::MODBITS); 
+	println!("{:} bit build",arch::CHUNK); 
+
+	let G=ecp::ECP::generator();
+
+	let mut r=big::BIG::new_ints(&rom::CURVE_ORDER);
+	let mut s=big::BIG::randomnum(&r,&mut rng);
+
+	let mut P=G.mul(&mut r);
+	if !P.is_infinity() {
+		println!("FAILURE - rG!=O");
+		fail=true;
+	} 
+
+	let start = Instant::now();
+	let mut iterations=0;
+	let mut dur=0 as u64;
+	while dur<(MIN_TIME as u64)*1000 || iterations<MIN_ITERS {
+		P=G.mul(&mut s);
+		iterations+=1;
+		let elapsed=start.elapsed();
+		dur=(elapsed.as_secs() * 1_000) + (elapsed.subsec_nanos() / 1_000_000) as u64;
+	} 
+	let duration=(dur as f64)/(iterations as f64);
+	print!("EC  mul - {:} iterations  ",iterations);
+	println!(" {:0.2} ms per iteration",duration);
+	if !fail {
+		println!("All tests pass");
+	}	
+}
+
+
+fn nist256(mut rng: &mut RAND)
+{
+	use amcl::nist256;
+	use amcl::nist256::ecp;
+	use amcl::nist256::fp;
+	use amcl::nist256::big;	
+	use amcl::nist256::rom;
+	let mut fail=false;	
+	println!("\nTesting/Timing nist256 ECC");
+
+	if ecp::CURVETYPE==ecp::WEIERSTRASS {
+		println!("Weierstrass parameterization");
+	}		
+	if ecp::CURVETYPE==ecp::EDWARDS {
+		println!("Edwards parameterization");
+	}
+	if ecp::CURVETYPE==ecp::MONTGOMERY {
+		println!("Montgomery parameterization");
+	}
+
+	if fp::MODTYPE==fp::PSEUDO_MERSENNE {
+		println!("Pseudo-Mersenne Modulus");
+	}
+	if fp::MODTYPE==fp::MONTGOMERY_FRIENDLY {
+		println!("Montgomery friendly Modulus");
+	}
+	if fp::MODTYPE==fp::GENERALISED_MERSENNE {
+		println!("Generalised-Mersenne Modulus");
+	}
+	if fp::MODTYPE==fp::NOT_SPECIAL {
+		println!("Not special Modulus");
+	}
+
+	println!("Modulus size {:} bits",fp::MODBITS); 
+	println!("{:} bit build",arch::CHUNK); 
+
+	let G=ecp::ECP::generator();
+
+	let mut r=big::BIG::new_ints(&rom::CURVE_ORDER);
+	let mut s=big::BIG::randomnum(&r,&mut rng);
+
+	let mut P=G.mul(&mut r);
+	if !P.is_infinity() {
+		println!("FAILURE - rG!=O");
+		fail=true;
+	} 
+
+	let start = Instant::now();
+	let mut iterations=0;
+	let mut dur=0 as u64;
+	while dur<(MIN_TIME as u64)*1000 || iterations<MIN_ITERS {
+		P=G.mul(&mut s);
+		iterations+=1;
+		let elapsed=start.elapsed();
+		dur=(elapsed.as_secs() * 1_000) + (elapsed.subsec_nanos() / 1_000_000) as u64;
+	} 
+	let duration=(dur as f64)/(iterations as f64);
+	print!("EC  mul - {:} iterations  ",iterations);
+	println!(" {:0.2} ms per iteration",duration);
+	if !fail {
+		println!("All tests pass");
+	}	
+}
+
+fn goldilocks(mut rng: &mut RAND)
+{
+	use amcl::goldilocks;
+	use amcl::goldilocks::ecp;
+	use amcl::goldilocks::fp;
+	use amcl::goldilocks::big;	
+	use amcl::goldilocks::rom;
+	let mut fail=false;	
+	println!("\nTesting/Timing goldilocks ECC");
+
+	if ecp::CURVETYPE==ecp::WEIERSTRASS {
+		println!("Weierstrass parameterization");
+	}		
+	if ecp::CURVETYPE==ecp::EDWARDS {
+		println!("Edwards parameterization");
+	}
+	if ecp::CURVETYPE==ecp::MONTGOMERY {
+		println!("Montgomery parameterization");
+	}
+
+	if fp::MODTYPE==fp::PSEUDO_MERSENNE {
+		println!("Pseudo-Mersenne Modulus");
+	}
+	if fp::MODTYPE==fp::MONTGOMERY_FRIENDLY {
+		println!("Montgomery friendly Modulus");
+	}
+	if fp::MODTYPE==fp::GENERALISED_MERSENNE {
+		println!("Generalised-Mersenne Modulus");
+	}
+	if fp::MODTYPE==fp::NOT_SPECIAL {
+		println!("Not special Modulus");
+	}
+
+	println!("Modulus size {:} bits",fp::MODBITS); 
+	println!("{:} bit build",arch::CHUNK); 
+
+	let G=ecp::ECP::generator();
+
+	let mut r=big::BIG::new_ints(&rom::CURVE_ORDER);
+	let mut s=big::BIG::randomnum(&r,&mut rng);
+
+	let mut P=G.mul(&mut r);
+	if !P.is_infinity() {
+		println!("FAILURE - rG!=O");
+		fail=true;
+	} 
+
+	let start = Instant::now();
+	let mut iterations=0;
+	let mut dur=0 as u64;
+	while dur<(MIN_TIME as u64)*1000 || iterations<MIN_ITERS {
+		P=G.mul(&mut s);
+		iterations+=1;
+		let elapsed=start.elapsed();
+		dur=(elapsed.as_secs() * 1_000) + (elapsed.subsec_nanos() / 1_000_000) as u64;
+	} 
+	let duration=(dur as f64)/(iterations as f64);
+	print!("EC  mul - {:} iterations  ",iterations);
+	println!(" {:0.2} ms per iteration",duration);
+	if !fail {
+		println!("All tests pass");
+	}	
+}
+
+fn bn254(mut rng: &mut RAND)
+{
+	use amcl::bn254;
+	use amcl::bn254::ecp;
+	use amcl::bn254::ecp2;	
+	use amcl::bn254::fp;	
+	use amcl::bn254::big;	
+	use amcl::bn254::pair;	
+	use amcl::bn254::rom;	
+	let mut fail=false;
+	println!("\nTesting/Timing BN254 Pairings");
+
+	if ecp::CURVE_PAIRING_TYPE==ecp::BN {
+		println!("BN Pairing-Friendly Curve");
+	}
+	if ecp::CURVE_PAIRING_TYPE==ecp::BLS {
+		println!("BLS Pairing-Friendly Curve");
+	}
+
+	println!("Modulus size {:} bits",fp::MODBITS); 
+	println!("{:} bit build",arch::CHUNK); 
+
+	let mut G =ecp::ECP::generator();
+
+	let mut r=big::BIG::new_ints(&rom::CURVE_ORDER);
+	let mut s=big::BIG::randomnum(&r,&mut rng);
+
+	let mut P=pair::g1mul(&mut G,&mut r);
+
+	if !P.is_infinity() {
+		println!("FAILURE - rP!=O");
+		fail=true;
+	}
+
+	let start = Instant::now();
+	let mut iterations=0;
+	let mut dur=0 as u64;
+	while dur<(MIN_TIME as u64)*1000 || iterations<MIN_ITERS {
+		P=pair::g1mul(&mut G,&mut s);
+		iterations+=1;
+		let elapsed=start.elapsed();
+		dur=(elapsed.as_secs() * 1_000) + (elapsed.subsec_nanos() / 1_000_000) as u64;
+	} 
+	let duration=(dur as f64)/(iterations as f64);
+	print!("G1  mul              - {:} iterations  ",iterations);
+	println!(" {:0.2} ms per iteration",duration);
+
+	let mut Q=ecp2::ECP2::generator();
+	let mut W=pair::g2mul(&mut Q,&mut r);
+
+	if !W.is_infinity() {
+		println!("FAILURE - rQ!=O");
+		fail=true;
+	}
+
+	let start = Instant::now();
+	let mut iterations=0;
+	let mut dur=0 as u64;
+	while dur<(MIN_TIME as u64)*1000 || iterations<MIN_ITERS {
+		W=pair::g2mul(&mut Q,&mut s);
+		iterations+=1;
+		let elapsed=start.elapsed();
+		dur=(elapsed.as_secs() * 1_000) + (elapsed.subsec_nanos() / 1_000_000) as u64;
+	} 
+	let duration=(dur as f64)/(iterations as f64);
+	print!("G2  mul              - {:} iterations  ",iterations);
+	println!(" {:0.2} ms per iteration",duration);
+
+	let mut w=pair::ate(&mut Q,&mut P);
+	w=pair::fexp(&w);
+
+	let mut g=pair::gtpow(&mut w,&mut r);
+
+	if !g.isunity() {
+		println!("FAILURE - g^r!=1");
+		return;
+	}
+
+	let start = Instant::now();
+	let mut iterations=0;
+	let mut dur=0 as u64;
+	while dur<(MIN_TIME as u64)*1000 || iterations<MIN_ITERS {
+		g=pair::gtpow(&mut w,&mut s);
+		iterations+=1;
+		let elapsed=start.elapsed();
+		dur=(elapsed.as_secs() * 1_000) + (elapsed.subsec_nanos() / 1_000_000) as u64;
+	} 
+	let duration=(dur as f64)/(iterations as f64);
+	print!("GT  pow              - {:} iterations  ",iterations);
+	println!(" {:0.2} ms per iteration",duration);
+
+	let start = Instant::now();
+	let mut iterations=0;
+	let mut dur=0 as u64;
+	while dur<(MIN_TIME as u64)*1000 || iterations<MIN_ITERS {
+		let c=w.compow(&s,&mut r);
+		iterations+=1;
+		let elapsed=start.elapsed();
+		dur=(elapsed.as_secs() * 1_000) + (elapsed.subsec_nanos() / 1_000_000) as u64;
+	} 
+	let duration=(dur as f64)/(iterations as f64);
+	print!("GT  pow (compressed) - {:} iterations  ",iterations);
+	println!(" {:0.2} ms per iteration",duration);
+
+	let start = Instant::now();
+	let mut iterations=0;
+	let mut dur=0 as u64;
+	while dur<(MIN_TIME as u64)*1000 || iterations<MIN_ITERS {
+		w=pair::ate(&mut Q,&mut P);
+		iterations+=1;
+		let elapsed=start.elapsed();
+		dur=(elapsed.as_secs() * 1_000) + (elapsed.subsec_nanos() / 1_000_000) as u64;
+	} 
+	let duration=(dur as f64)/(iterations as f64);
+	print!("PAIRing ATE          - {:} iterations  ",iterations);
+	println!(" {:0.2} ms per iteration",duration);
+
+
+	let start = Instant::now();
+	let mut iterations=0;
+	let mut dur=0 as u64;
+	while dur<(MIN_TIME as u64)*1000 || iterations<MIN_ITERS {
+		g=pair::fexp(&w);
+		iterations+=1;
+		let elapsed=start.elapsed();
+		dur=(elapsed.as_secs() * 1_000) + (elapsed.subsec_nanos() / 1_000_000) as u64;
+	} 
+	let duration=(dur as f64)/(iterations as f64);
+	print!("PAIRing FEXP         - {:} iterations  ",iterations);
+	println!(" {:0.2} ms per iteration",duration);
+
+	P.copy(&G);
+	Q.copy(&W);
+
+	P=pair::g1mul(&mut P,&mut s);
+	g=pair::ate(&mut Q,&mut P);
+	g=pair::fexp(&g);
+
+	P.copy(&G);
+	Q=pair::g2mul(&mut Q,&mut s);
+	w=pair::ate(&mut Q,&mut P);
+	w=pair::fexp(&w);
+
+	if !g.equals(&mut w) {
+		println!("FAILURE - e(sQ,p)!=e(Q,sP) ");
+		fail=true;
+	}
+
+	Q.copy(&W);
+	g=pair::ate(&mut Q,&mut P);
+	g=pair::fexp(&g);
+	g=pair::gtpow(&mut g,&mut s);
+
+	if !g.equals(&mut w) {
+		println!("FAILURE - e(sQ,p)!=e(Q,P)^s ");
+		fail=true;
+	}
+	if !fail {
+		println!("All tests pass");
+	}			
+}
+
+
+fn bls383(mut rng: &mut RAND)
+{
+	use amcl::bls383;
+	use amcl::bls383::ecp;
+	use amcl::bls383::ecp2;	
+	use amcl::bls383::fp;	
+	use amcl::bls383::big;	
+	use amcl::bls383::pair;	
+	use amcl::bls383::rom;		
+	let mut fail=false;
+	println!("\nTesting/Timing BLS383 Pairings");
+
+	if ecp::CURVE_PAIRING_TYPE==ecp::BN {
+		println!("BN Pairing-Friendly Curve");
+	}
+	if ecp::CURVE_PAIRING_TYPE==ecp::BLS {
+		println!("BLS Pairing-Friendly Curve");
+	}
+
+	println!("Modulus size {:} bits",fp::MODBITS); 
+	println!("{:} bit build",arch::CHUNK); 
+
+	let mut G =ecp::ECP::generator();
+
+	let mut r=big::BIG::new_ints(&rom::CURVE_ORDER);
+	let mut s=big::BIG::randomnum(&r,&mut rng);
+
+	let mut P=pair::g1mul(&mut G,&mut r);
+
+	if !P.is_infinity() {
+		println!("FAILURE - rP!=O");
+		fail=true;
+	}
+
+	let start = Instant::now();
+	let mut iterations=0;
+	let mut dur=0 as u64;
+	while dur<(MIN_TIME as u64)*1000 || iterations<MIN_ITERS {
+		P=pair::g1mul(&mut G,&mut s);
+		iterations+=1;
+		let elapsed=start.elapsed();
+		dur=(elapsed.as_secs() * 1_000) + (elapsed.subsec_nanos() / 1_000_000) as u64;
+	} 
+	let duration=(dur as f64)/(iterations as f64);
+	print!("G1  mul              - {:} iterations  ",iterations);
+	println!(" {:0.2} ms per iteration",duration);
+
+	let mut Q=ecp2::ECP2::generator();
+	let mut W=pair::g2mul(&mut Q,&mut r);
+
+	if !W.is_infinity() {
+		println!("FAILURE - rQ!=O");
+		fail=true;
+	}
+
+	let start = Instant::now();
+	let mut iterations=0;
+	let mut dur=0 as u64;
+	while dur<(MIN_TIME as u64)*1000 || iterations<MIN_ITERS {
+		W=pair::g2mul(&mut Q,&mut s);
+		iterations+=1;
+		let elapsed=start.elapsed();
+		dur=(elapsed.as_secs() * 1_000) + (elapsed.subsec_nanos() / 1_000_000) as u64;
+	} 
+	let duration=(dur as f64)/(iterations as f64);
+	print!("G2  mul              - {:} iterations  ",iterations);
+	println!(" {:0.2} ms per iteration",duration);
+
+	let mut w=pair::ate(&mut Q,&mut P);
+	w=pair::fexp(&w);
+
+	let mut g=pair::gtpow(&mut w,&mut r);
+
+	if !g.isunity() {
+		println!("FAILURE - g^r!=1");
+		return;
+	}
+
+	let start = Instant::now();
+	let mut iterations=0;
+	let mut dur=0 as u64;
+	while dur<(MIN_TIME as u64)*1000 || iterations<MIN_ITERS {
+		g=pair::gtpow(&mut w,&mut s);
+		iterations+=1;
+		let elapsed=start.elapsed();
+		dur=(elapsed.as_secs() * 1_000) + (elapsed.subsec_nanos() / 1_000_000) as u64;
+	} 
+	let duration=(dur as f64)/(iterations as f64);
+	print!("GT  pow              - {:} iterations  ",iterations);
+	println!(" {:0.2} ms per iteration",duration);
+
+	let start = Instant::now();
+	let mut iterations=0;
+	let mut dur=0 as u64;
+	while dur<(MIN_TIME as u64)*1000 || iterations<MIN_ITERS {
+		let c=w.compow(&s,&mut r);
+		iterations+=1;
+		let elapsed=start.elapsed();
+		dur=(elapsed.as_secs() * 1_000) + (elapsed.subsec_nanos() / 1_000_000) as u64;
+	} 
+	let duration=(dur as f64)/(iterations as f64);
+	print!("GT  pow (compressed) - {:} iterations  ",iterations);
+	println!(" {:0.2} ms per iteration",duration);
+
+	let start = Instant::now();
+	let mut iterations=0;
+	let mut dur=0 as u64;
+	while dur<(MIN_TIME as u64)*1000 || iterations<MIN_ITERS {
+		w=pair::ate(&mut Q,&mut P);
+		iterations+=1;
+		let elapsed=start.elapsed();
+		dur=(elapsed.as_secs() * 1_000) + (elapsed.subsec_nanos() / 1_000_000) as u64;
+	} 
+	let duration=(dur as f64)/(iterations as f64);
+	print!("PAIRing ATE          - {:} iterations  ",iterations);
+	println!(" {:0.2} ms per iteration",duration);
+
+
+	let start = Instant::now();
+	let mut iterations=0;
+	let mut dur=0 as u64;
+	while dur<(MIN_TIME as u64)*1000 || iterations<MIN_ITERS {
+		g=pair::fexp(&w);
+		iterations+=1;
+		let elapsed=start.elapsed();
+		dur=(elapsed.as_secs() * 1_000) + (elapsed.subsec_nanos() / 1_000_000) as u64;
+	} 
+	let duration=(dur as f64)/(iterations as f64);
+	print!("PAIRing FEXP         - {:} iterations  ",iterations);
+	println!(" {:0.2} ms per iteration",duration);
+
+	P.copy(&G);
+	Q.copy(&W);
+
+	P=pair::g1mul(&mut P,&mut s);
+	g=pair::ate(&mut Q,&mut P);
+	g=pair::fexp(&g);
+
+	P.copy(&G);
+	Q=pair::g2mul(&mut Q,&mut s);
+	w=pair::ate(&mut Q,&mut P);
+	w=pair::fexp(&w);
+
+	if !g.equals(&mut w) {
+		println!("FAILURE - e(sQ,p)!=e(Q,sP) ");
+		fail=true;
+	}
+
+	Q.copy(&W);
+	g=pair::ate(&mut Q,&mut P);
+	g=pair::fexp(&g);
+	g=pair::gtpow(&mut g,&mut s);
+
+	if !g.equals(&mut w) {
+		println!("FAILURE - e(sQ,p)!=e(Q,P)^s ");
+		fail=true;
+	}
+	if !fail {
+		println!("All tests pass");
+	}			
+}
+
+fn bls24(mut rng: &mut RAND)
+{
+	use amcl::bls24;
+	use amcl::bls24::ecp;
+	use amcl::bls24::ecp4;	
+	use amcl::bls24::fp;	
+	use amcl::bls24::big;	
+	use amcl::bls24::pair192;	
+	use amcl::bls24::rom;		
+	let mut fail=false;
+	println!("\nTesting/Timing BLS24 Pairings");
+
+	if ecp::CURVE_PAIRING_TYPE==ecp::BN {
+		println!("BN Pairing-Friendly Curve");
+	}
+	if ecp::CURVE_PAIRING_TYPE==ecp::BLS {
+		println!("BLS24 Pairing-Friendly Curve");
+	}
+
+	println!("Modulus size {:} bits",fp::MODBITS); 
+	println!("{:} bit build",arch::CHUNK); 
+
+	let mut G =ecp::ECP::generator();
+
+	let mut r=big::BIG::new_ints(&rom::CURVE_ORDER);
+	let mut s=big::BIG::randomnum(&r,&mut rng);
+
+	let mut P=pair192::g1mul(&mut G,&mut r);
+
+	if !P.is_infinity() {
+		println!("FAILURE - rP!=O");
+		fail=true;
+	}
+
+	let start = Instant::now();
+	let mut iterations=0;
+	let mut dur=0 as u64;
+	while dur<(MIN_TIME as u64)*1000 || iterations<MIN_ITERS {
+		P=pair192::g1mul(&mut G,&mut s);
+		iterations+=1;
+		let elapsed=start.elapsed();
+		dur=(elapsed.as_secs() * 1_000) + (elapsed.subsec_nanos() / 1_000_000) as u64;
+	} 
+	let duration=(dur as f64)/(iterations as f64);
+	print!("G1  mul              - {:} iterations  ",iterations);
+	println!(" {:0.2} ms per iteration",duration);
+
+	let mut Q=ecp4::ECP4::generator();
+	let mut W=pair192::g2mul(&mut Q,&mut r);
+
+	if !W.is_infinity() {
+		println!("FAILURE - rQ!=O");
+		fail=true;
+	}
+
+	let start = Instant::now();
+	let mut iterations=0;
+	let mut dur=0 as u64;
+	while dur<(MIN_TIME as u64)*1000 || iterations<MIN_ITERS {
+		W=pair192::g2mul(&mut Q,&mut s);
+		iterations+=1;
+		let elapsed=start.elapsed();
+		dur=(elapsed.as_secs() * 1_000) + (elapsed.subsec_nanos() / 1_000_000) as u64;
+	} 
+	let duration=(dur as f64)/(iterations as f64);
+	print!("G2  mul              - {:} iterations  ",iterations);
+	println!(" {:0.2} ms per iteration",duration);
+
+	let mut w=pair192::ate(&mut Q,&mut P);
+	w=pair192::fexp(&w);
+
+	let mut g=pair192::gtpow(&mut w,&mut r);
+
+	if !g.isunity() {
+		println!("FAILURE - g^r!=1");
+		return;
+	}
+
+	let start = Instant::now();
+	let mut iterations=0;
+	let mut dur=0 as u64;
+	while dur<(MIN_TIME as u64)*1000 || iterations<MIN_ITERS {
+		g=pair192::gtpow(&mut w,&mut s);
+		iterations+=1;
+		let elapsed=start.elapsed();
+		dur=(elapsed.as_secs() * 1_000) + (elapsed.subsec_nanos() / 1_000_000) as u64;
+	} 
+	let duration=(dur as f64)/(iterations as f64);
+	print!("GT  pow              - {:} iterations  ",iterations);
+	println!(" {:0.2} ms per iteration",duration);
+
+	let start = Instant::now();
+	let mut iterations=0;
+	let mut dur=0 as u64;
+	while dur<(MIN_TIME as u64)*1000 || iterations<MIN_ITERS {
+		let c=w.compow(&s,&mut r);
+		iterations+=1;
+		let elapsed=start.elapsed();
+		dur=(elapsed.as_secs() * 1_000) + (elapsed.subsec_nanos() / 1_000_000) as u64;
+	} 
+	let duration=(dur as f64)/(iterations as f64);
+	print!("GT  pow (compressed) - {:} iterations  ",iterations);
+	println!(" {:0.2} ms per iteration",duration);
+
+	let start = Instant::now();
+	let mut iterations=0;
+	let mut dur=0 as u64;
+	while dur<(MIN_TIME as u64)*1000 || iterations<MIN_ITERS {
+		w=pair192::ate(&mut Q,&mut P);
+		iterations+=1;
+		let elapsed=start.elapsed();
+		dur=(elapsed.as_secs() * 1_000) + (elapsed.subsec_nanos() / 1_000_000) as u64;
+	} 
+	let duration=(dur as f64)/(iterations as f64);
+	print!("PAIRing ATE          - {:} iterations  ",iterations);
+	println!(" {:0.2} ms per iteration",duration);
+
+
+	let start = Instant::now();
+	let mut iterations=0;
+	let mut dur=0 as u64;
+	while dur<(MIN_TIME as u64)*1000 || iterations<MIN_ITERS {
+		g=pair192::fexp(&w);
+		iterations+=1;
+		let elapsed=start.elapsed();
+		dur=(elapsed.as_secs() * 1_000) + (elapsed.subsec_nanos() / 1_000_000) as u64;
+	} 
+	let duration=(dur as f64)/(iterations as f64);
+	print!("PAIRing FEXP         - {:} iterations  ",iterations);
+	println!(" {:0.2} ms per iteration",duration);
+
+	P.copy(&G);
+	Q.copy(&W);
+
+	P=pair192::g1mul(&mut P,&mut s);
+	g=pair192::ate(&mut Q,&mut P);
+	g=pair192::fexp(&g);
+
+	P.copy(&G);
+	Q=pair192::g2mul(&mut Q,&mut s);
+	w=pair192::ate(&mut Q,&mut P);
+	w=pair192::fexp(&w);
+
+	if !g.equals(&mut w) {
+		println!("FAILURE - e(sQ,p)!=e(Q,sP) ");
+		fail=true;
+	}
+
+	Q.copy(&W);
+	g=pair192::ate(&mut Q,&mut P);
+	g=pair192::fexp(&g);
+	g=pair192::gtpow(&mut g,&mut s);
+
+	if !g.equals(&mut w) {
+		println!("FAILURE - e(sQ,p)!=e(Q,P)^s ");
+		fail=true;
+	}	
+	if !fail {
+		println!("All tests pass");
+	}
+}
+
+
+fn bls48(mut rng: &mut RAND)
+{
+	use amcl::bls48;
+	use amcl::bls48::ecp;
+	use amcl::bls48::ecp8;	
+	use amcl::bls48::fp;	
+	use amcl::bls48::big;	
+	use amcl::bls48::pair256;	
+	use amcl::bls48::rom;		
+	let mut fail=false;
+	println!("\nTesting/Timing BLS48 Pairings");
+
+	if ecp::CURVE_PAIRING_TYPE==ecp::BN {
+		println!("BN Pairing-Friendly Curve");
+	}
+	if ecp::CURVE_PAIRING_TYPE==ecp::BLS {
+		println!("BLS24 Pairing-Friendly Curve");
+	}
+
+	println!("Modulus size {:} bits",fp::MODBITS); 
+	println!("{:} bit build",arch::CHUNK); 
+
+	let mut G =ecp::ECP::generator();
+
+	let mut r=big::BIG::new_ints(&rom::CURVE_ORDER);
+	let mut s=big::BIG::randomnum(&r,&mut rng);
+
+	let mut P=pair256::g1mul(&mut G,&mut r);
+
+	if !P.is_infinity() {
+		println!("FAILURE - rP!=O");
+		fail=true;
+	}
+
+	let start = Instant::now();
+	let mut iterations=0;
+	let mut dur=0 as u64;
+	while dur<(MIN_TIME as u64)*1000 || iterations<MIN_ITERS {
+		P=pair256::g1mul(&mut G,&mut s);
+		iterations+=1;
+		let elapsed=start.elapsed();
+		dur=(elapsed.as_secs() * 1_000) + (elapsed.subsec_nanos() / 1_000_000) as u64;
+	} 
+	let duration=(dur as f64)/(iterations as f64);
+	print!("G1  mul              - {:} iterations  ",iterations);
+	println!(" {:0.2} ms per iteration",duration);
+
+	let mut Q=ecp8::ECP8::generator();
+	let mut W=pair256::g2mul(&mut Q,&mut r);
+
+	if !W.is_infinity() {
+		println!("FAILURE - rQ!=O");
+		fail=true;
+	}
+
+	let start = Instant::now();
+	let mut iterations=0;
+	let mut dur=0 as u64;
+	while dur<(MIN_TIME as u64)*1000 || iterations<MIN_ITERS {
+		W=pair256::g2mul(&mut Q,&mut s);
+		iterations+=1;
+		let elapsed=start.elapsed();
+		dur=(elapsed.as_secs() * 1_000) + (elapsed.subsec_nanos() / 1_000_000) as u64;
+	} 
+	let duration=(dur as f64)/(iterations as f64);
+	print!("G2  mul              - {:} iterations  ",iterations);
+	println!(" {:0.2} ms per iteration",duration);
+
+	let mut w=pair256::ate(&mut Q,&mut P);
+	w=pair256::fexp(&w);
+
+	let mut g=pair256::gtpow(&mut w,&mut r);
+
+	if !g.isunity() {
+		println!("FAILURE - g^r!=1");
+		return;
+	}
+
+	let start = Instant::now();
+	let mut iterations=0;
+	let mut dur=0 as u64;
+	while dur<(MIN_TIME as u64)*1000 || iterations<MIN_ITERS {
+		g=pair256::gtpow(&mut w,&mut s);
+		iterations+=1;
+		let elapsed=start.elapsed();
+		dur=(elapsed.as_secs() * 1_000) + (elapsed.subsec_nanos() / 1_000_000) as u64;
+	} 
+	let duration=(dur as f64)/(iterations as f64);
+	print!("GT  pow              - {:} iterations  ",iterations);
+	println!(" {:0.2} ms per iteration",duration);
+
+	let start = Instant::now();
+	let mut iterations=0;
+	let mut dur=0 as u64;
+	while dur<(MIN_TIME as u64)*1000 || iterations<MIN_ITERS {
+		let c=w.compow(&s,&mut r);
+		iterations+=1;
+		let elapsed=start.elapsed();
+		dur=(elapsed.as_secs() * 1_000) + (elapsed.subsec_nanos() / 1_000_000) as u64;
+	} 
+	let duration=(dur as f64)/(iterations as f64);
+	print!("GT  pow (compressed) - {:} iterations  ",iterations);
+	println!(" {:0.2} ms per iteration",duration);
+
+	let start = Instant::now();
+	let mut iterations=0;
+	let mut dur=0 as u64;
+	while dur<(MIN_TIME as u64)*1000 || iterations<MIN_ITERS {
+		w=pair256::ate(&mut Q,&mut P);
+		iterations+=1;
+		let elapsed=start.elapsed();
+		dur=(elapsed.as_secs() * 1_000) + (elapsed.subsec_nanos() / 1_000_000) as u64;
+	} 
+	let duration=(dur as f64)/(iterations as f64);
+	print!("PAIRing ATE          - {:} iterations  ",iterations);
+	println!(" {:0.2} ms per iteration",duration);
+
+
+	let start = Instant::now();
+	let mut iterations=0;
+	let mut dur=0 as u64;
+	while dur<(MIN_TIME as u64)*1000 || iterations<MIN_ITERS {
+		g=pair256::fexp(&w);
+		iterations+=1;
+		let elapsed=start.elapsed();
+		dur=(elapsed.as_secs() * 1_000) + (elapsed.subsec_nanos() / 1_000_000) as u64;
+	} 
+	let duration=(dur as f64)/(iterations as f64);
+	print!("PAIRing FEXP         - {:} iterations  ",iterations);
+	println!(" {:0.2} ms per iteration",duration);
+
+	P.copy(&G);
+	Q.copy(&W);
+
+	P=pair256::g1mul(&mut P,&mut s);
+	g=pair256::ate(&mut Q,&mut P);
+	g=pair256::fexp(&g);
+
+	P.copy(&G);
+	Q=pair256::g2mul(&mut Q,&mut s);
+	w=pair256::ate(&mut Q,&mut P);
+	w=pair256::fexp(&w);
+
+	if !g.equals(&mut w) {
+		println!("FAILURE - e(sQ,p)!=e(Q,sP) ");
+		fail=true;
+	}
+
+	Q.copy(&W);
+	g=pair256::ate(&mut Q,&mut P);
+	g=pair256::fexp(&g);
+	g=pair256::gtpow(&mut g,&mut s);
+
+	if !g.equals(&mut w) {
+		println!("FAILURE - e(sQ,p)!=e(Q,P)^s ");
+		fail=true;
+	}	
+	if !fail {
+		println!("All tests pass");
+	}
+}
+
+
+
+fn rsa2048(mut rng: &mut RAND)
+{
+	use amcl::rsa2048::rsa;
+	use amcl::rsa2048::ff;	
+	let mut pbc=rsa::new_public_key(ff::FFLEN);
+	let mut prv=rsa::new_private_key(ff::HFLEN);	
+	let mut c: [u8;rsa::RFS]=[0;rsa::RFS];
+	let mut m: [u8;rsa::RFS]=[0;rsa::RFS];
+	let mut p: [u8;rsa::RFS]=[0;rsa::RFS];	
+
+	let mut fail=false;
+	println!("\nTesting/Timing 2048-bit RSA");
+	println!("Generating 2048 -bit RSA public/private key pair");
+
+	let start = Instant::now();
+	let mut iterations=0;
+	let mut dur=0 as u64;
+	while dur<(MIN_TIME as u64)*1000 || iterations<MIN_ITERS {
+		rsa::key_pair(&mut rng,65537,&mut prv,&mut pbc);
+		iterations+=1;
+		let elapsed=start.elapsed();
+		dur=(elapsed.as_secs() * 1_000) + (elapsed.subsec_nanos() / 1_000_000) as u64;
+	} 
+	let duration=(dur as f64)/(iterations as f64);
+	print!("RSA gen - {:} iterations  ",iterations);
+	println!(" {:0.2} ms per iteration",duration);
+
+	for i in 0..rsa::RFS {m[i]=(i%128) as u8;}
+
+	let start = Instant::now();
+	let mut iterations=0;
+	let mut dur=0 as u64;
+	while dur<(MIN_TIME as u64)*1000 || iterations<MIN_ITERS {
+		rsa::encrypt(&pbc,&m,&mut c); 
+		iterations+=1;
+		let elapsed=start.elapsed();
+		dur=(elapsed.as_secs() * 1_000) + (elapsed.subsec_nanos() / 1_000_000) as u64;
+	} 
+	let duration=(dur as f64)/(iterations as f64);
+	print!("RSA enc - {:} iterations  ",iterations);
+	println!(" {:0.2} ms per iteration",duration);
+
+	let start = Instant::now();
+	let mut iterations=0;
+	let mut dur=0 as u64;
+	while dur<(MIN_TIME as u64)*1000 || iterations<MIN_ITERS {
+		rsa::decrypt(&prv,&c,&mut p); 
+		iterations+=1;
+		let elapsed=start.elapsed();
+		dur=(elapsed.as_secs() * 1_000) + (elapsed.subsec_nanos() / 1_000_000) as u64;
+	} 
+	let duration=(dur as f64)/(iterations as f64);
+	print!("RSA dec - {:} iterations  ",iterations);
+	println!(" {:0.2} ms per iteration",duration);
+
+	let mut cmp=true;
+	for i in 0..rsa::RFS {
+			if p[i]!=m[i] {cmp=false;}
+		}
+
+	if !cmp {
+		println!("FAILURE - RSA decryption");
+		fail=true;
+	}
+
+	if !fail {
+		println!("All tests pass");
+	}
+}
+
+
+#[allow(non_snake_case)]
+fn main()
+{
+	let mut raw:[u8;100]=[0;100];	
+
+	let mut rng=RAND::new();
+	rng.clean();
+	for i in 0..100 {raw[i]=i as u8}
+
+	rng.seed(100,&raw);	
+
+	ed25519(&mut rng);	
+	nist256(&mut rng);
+	goldilocks(&mut rng);		
+	bn254(&mut rng);
+	bls383(&mut rng);
+	bls24(&mut rng);
+	bls48(&mut rng);
+	rsa2048(&mut rng);
+
+}
diff --git a/version3/rust/TestALL.rs b/version3/rust/TestALL.rs
new file mode 100644
index 0000000..fe3fcac
--- /dev/null
+++ b/version3/rust/TestALL.rs
@@ -0,0 +1,1235 @@
+/*
+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.
+*/
+
+extern crate amcl;
+
+use std::str;
+use std::io;
+
+use amcl::rand::RAND;
+
+
+pub fn printbinary(array: &[u8]) {
+	for i in 0..array.len() {
+		print!("{:02X}", array[i])
+	}
+	println!("")
+} 
+
+fn ecdh_ed25519(mut rng: &mut RAND)
+{
+	use amcl::ed25519;
+	use amcl::ed25519::ecdh;
+	use amcl::ed25519::ecp;
+
+	let pw="M0ng00se";
+	let pp:&[u8] = b"M0ng00se";
+	const EFS:usize=ecdh::EFS;	
+	const EGS:usize=ecdh::EGS;
+	const EAS:usize=ecp::AESKEY;
+
+	let sha=ecp::HASH_TYPE;
+	let mut salt:[u8;8]=[0;8];
+	let mut s1:[u8;EGS]=[0;EGS];
+	let mut w0:[u8;2*EFS+1]=[0;2*EFS+1];
+	let mut w1:[u8;2*EFS+1]=[0;2*EFS+1];
+	let mut z0:[u8;EFS]=[0;EFS];
+	let mut z1:[u8;EFS]=[0;EFS];
+	let mut key:[u8;EAS]=[0;EAS];
+	let mut cs: [u8;EGS]=[0;EGS];
+	let mut ds: [u8;EGS]=[0;EGS];	
+	let mut m: Vec<u8> = vec![0;32];   // array that could be of any length. So use heap.
+	let mut p1: [u8;3]=[0;3];
+	let mut p2: [u8;4]=[0;4];	
+	let mut v: [u8;2*EFS+1]=[0;2*EFS+1];
+	let mut t: [u8;12]=[0;12];
+
+
+	for i in 0..8 {salt[i]=(i+1) as u8}  // set Salt	
+
+	println!("\nTesting ECDH/ECDSA/ECIES");
+	println!("Alice's Passphrase= {}",pw);
+
+	let mut s0:[u8;EFS]=[0;EGS];
+	ecdh::pbkdf2(sha,pp,&salt,1000,EGS,&mut s0);
+
+	print!("Alice's private key= 0x");
+	printbinary(&s0);
+
+/* Generate Key pair S/W */
+	ecdh::key_pair_generate(None,&mut s0,&mut w0);
+
+	print!("Alice's public key= 0x");
+	printbinary(&w0);
+
+	let mut res=ecdh::public_key_validate(&w0);
+	if res!=0 {
+		println!("ECP Public Key is invalid!");
+		return;
+	}
+
+/* Random private key for other party */
+	ecdh::key_pair_generate(Some(&mut rng),&mut s1,&mut w1);
+
+	print!("Servers private key= 0x");
+	printbinary(&s1);
+
+	print!("Servers public key= 0x");
+	printbinary(&w1);
+
+
+	res=ecdh::public_key_validate(&w1);
+	if res!=0 {
+		println!("ECP Public Key is invalid!");
+		return;
+	}
+/* Calculate common key using DH - IEEE 1363 method */
+
+	ecdh::ecpsvdp_dh(&s0,&w1,&mut z0);
+	ecdh::ecpsvdp_dh(&s1,&w0,&mut z1);
+
+	let mut same=true;
+	for i in 0..EFS {
+		if z0[i]!=z1[i] {same=false}
+	}
+
+	if !same {
+		println!("*** ECPSVDP-DH Failed");
+		return;
+	}
+
+	ecdh::kdf2(sha,&z0,None,EAS,&mut key);
+
+	print!("Alice's DH Key=  0x"); printbinary(&key);
+	print!("Servers DH Key=  0x"); printbinary(&key);
+
+	if ecp::CURVETYPE!=ecp::MONTGOMERY {
+
+		for i in 0..17 {m[i]=i as u8} 
+
+		println!("Testing ECIES");
+
+		p1[0]=0x0; p1[1]=0x1; p1[2]=0x2;
+		p2[0]=0x0; p2[1]=0x1; p2[2]=0x2; p2[3]=0x3;
+
+		let cc=ecdh::ecies_encrypt(sha,&p1,&p2,&mut rng,&w1,&m[0..17],&mut v,&mut t);
+
+		if let Some(mut c)=cc {
+			println!("Ciphertext= ");
+			print!("V= 0x"); printbinary(&v);
+			print!("C= 0x"); printbinary(&c);
+			print!("T= 0x"); printbinary(&t);
+		
+
+			let mm=ecdh::ecies_decrypt(sha,&p1,&p2,&v,&mut c,&t,&s1);
+			if let Some(rm)=mm {
+				println!("Decryption succeeded");
+				print!("Message is 0x"); printbinary(&rm);				
+			}
+			else {
+				println!("*** ECIES Decryption Failed");
+				return;
+			} 
+		}
+		else {
+			println!("*** ECIES Encryption Failed");
+			return;
+		} 
+
+		println!("Testing ECDSA");
+
+		if ecdh::ecpsp_dsa(sha,&mut rng,&s0,&m[0..17],&mut cs,&mut ds)!=0 {
+			println!("***ECDSA Signature Failed");
+			return;
+		}
+		println!("Signature= ");
+		print!("C= 0x"); printbinary(&cs);
+		print!("D= 0x"); printbinary(&ds);
+
+		if ecdh::ecpvp_dsa(sha,&w0,&m[0..17],&cs,&ds)!=0 {
+			println!("***ECDSA Verification Failed");
+			return;
+		} else {println!("ECDSA Signature/Verification succeeded ")}
+	}
+
+}
+
+
+fn ecdh_nist256(mut rng: &mut RAND)
+{
+	use amcl::nist256;
+	use amcl::nist256::ecdh;
+	use amcl::nist256::ecp;
+
+	let pw="M0ng00se";
+	let pp:&[u8] = b"M0ng00se";
+	const EFS:usize=ecdh::EFS;	
+	const EGS:usize=ecdh::EGS;
+	const EAS:usize=ecp::AESKEY;
+
+	let sha=ecp::HASH_TYPE;
+	let mut salt:[u8;8]=[0;8];
+	let mut s1:[u8;EGS]=[0;EGS];
+	let mut w0:[u8;2*EFS+1]=[0;2*EFS+1];
+	let mut w1:[u8;2*EFS+1]=[0;2*EFS+1];
+	let mut z0:[u8;EFS]=[0;EFS];
+	let mut z1:[u8;EFS]=[0;EFS];
+	let mut key:[u8;EAS]=[0;EAS];
+	let mut cs: [u8;EGS]=[0;EGS];
+	let mut ds: [u8;EGS]=[0;EGS];	
+	let mut m: Vec<u8> = vec![0;32];   // array that could be of any length. So use heap.
+	let mut p1: [u8;3]=[0;3];
+	let mut p2: [u8;4]=[0;4];	
+	let mut v: [u8;2*EFS+1]=[0;2*EFS+1];
+	let mut t: [u8;12]=[0;12];
+
+
+	for i in 0..8 {salt[i]=(i+1) as u8}  // set Salt	
+
+	println!("\nTesting ECDH/ECDSA/ECIES");
+	println!("Alice's Passphrase= {}",pw);
+
+	let mut s0:[u8;EFS]=[0;EGS];
+	ecdh::pbkdf2(sha,pp,&salt,1000,EGS,&mut s0);
+
+	print!("Alice's private key= 0x");
+	printbinary(&s0);
+
+/* Generate Key pair S/W */
+	ecdh::key_pair_generate(None,&mut s0,&mut w0);
+
+	print!("Alice's public key= 0x");
+	printbinary(&w0);
+
+	let mut res=ecdh::public_key_validate(&w0);
+	if res!=0 {
+		println!("ECP Public Key is invalid!");
+		return;
+	}
+
+/* Random private key for other party */
+	ecdh::key_pair_generate(Some(&mut rng),&mut s1,&mut w1);
+
+	print!("Servers private key= 0x");
+	printbinary(&s1);
+
+	print!("Servers public key= 0x");
+	printbinary(&w1);
+
+
+	res=ecdh::public_key_validate(&w1);
+	if res!=0 {
+		println!("ECP Public Key is invalid!");
+		return;
+	}
+/* Calculate common key using DH - IEEE 1363 method */
+
+	ecdh::ecpsvdp_dh(&s0,&w1,&mut z0);
+	ecdh::ecpsvdp_dh(&s1,&w0,&mut z1);
+
+	let mut same=true;
+	for i in 0..EFS {
+		if z0[i]!=z1[i] {same=false}
+	}
+
+	if !same {
+		println!("*** ECPSVDP-DH Failed");
+		return;
+	}
+
+	ecdh::kdf2(sha,&z0,None,EAS,&mut key);
+
+	print!("Alice's DH Key=  0x"); printbinary(&key);
+	print!("Servers DH Key=  0x"); printbinary(&key);
+
+	if ecp::CURVETYPE!=ecp::MONTGOMERY {
+
+		for i in 0..17 {m[i]=i as u8} 
+
+		println!("Testing ECIES");
+
+		p1[0]=0x0; p1[1]=0x1; p1[2]=0x2;
+		p2[0]=0x0; p2[1]=0x1; p2[2]=0x2; p2[3]=0x3;
+
+		let cc=ecdh::ecies_encrypt(sha,&p1,&p2,&mut rng,&w1,&m[0..17],&mut v,&mut t);
+
+		if let Some(mut c)=cc {
+			println!("Ciphertext= ");
+			print!("V= 0x"); printbinary(&v);
+			print!("C= 0x"); printbinary(&c);
+			print!("T= 0x"); printbinary(&t);
+		
+
+			let mm=ecdh::ecies_decrypt(sha,&p1,&p2,&v,&mut c,&t,&s1);
+			if let Some(rm)=mm {
+				println!("Decryption succeeded");
+				print!("Message is 0x"); printbinary(&rm);				
+			}
+			else {
+				println!("*** ECIES Decryption Failed");
+				return;
+			} 
+		}
+		else {
+			println!("*** ECIES Encryption Failed");
+			return;
+		} 
+
+		println!("Testing ECDSA");
+
+		if ecdh::ecpsp_dsa(sha,&mut rng,&s0,&m[0..17],&mut cs,&mut ds)!=0 {
+			println!("***ECDSA Signature Failed");
+			return;
+		}
+		println!("Signature= ");
+		print!("C= 0x"); printbinary(&cs);
+		print!("D= 0x"); printbinary(&ds);
+
+		if ecdh::ecpvp_dsa(sha,&w0,&m[0..17],&cs,&ds)!=0 {
+			println!("***ECDSA Verification Failed");
+			return;
+		} else {println!("ECDSA Signature/Verification succeeded ")}
+	}
+
+}
+
+fn ecdh_goldilocks(mut rng: &mut RAND)
+{
+	use amcl::goldilocks;
+	use amcl::goldilocks::ecdh;
+	use amcl::goldilocks::ecp;
+
+	let pw="M0ng00se";
+	let pp:&[u8] = b"M0ng00se";
+	const EFS:usize=ecdh::EFS;	
+	const EGS:usize=ecdh::EGS;
+	const EAS:usize=ecp::AESKEY;
+
+	let sha=ecp::HASH_TYPE;
+	let mut salt:[u8;8]=[0;8];
+	let mut s1:[u8;EGS]=[0;EGS];
+	let mut w0:[u8;2*EFS+1]=[0;2*EFS+1];
+	let mut w1:[u8;2*EFS+1]=[0;2*EFS+1];
+	let mut z0:[u8;EFS]=[0;EFS];
+	let mut z1:[u8;EFS]=[0;EFS];
+	let mut key:[u8;EAS]=[0;EAS];
+	let mut cs: [u8;EGS]=[0;EGS];
+	let mut ds: [u8;EGS]=[0;EGS];	
+	let mut m: Vec<u8> = vec![0;32];   // array that could be of any length. So use heap.
+	let mut p1: [u8;3]=[0;3];
+	let mut p2: [u8;4]=[0;4];	
+	let mut v: [u8;2*EFS+1]=[0;2*EFS+1];
+	let mut t: [u8;12]=[0;12];
+
+
+	for i in 0..8 {salt[i]=(i+1) as u8}  // set Salt	
+
+	println!("\nTesting ECDH/ECDSA/ECIES");
+	println!("Alice's Passphrase= {}",pw);
+
+	let mut s0:[u8;EFS]=[0;EGS];
+	ecdh::pbkdf2(sha,pp,&salt,1000,EGS,&mut s0);
+
+	print!("Alice's private key= 0x");
+	printbinary(&s0);
+
+/* Generate Key pair S/W */
+	ecdh::key_pair_generate(None,&mut s0,&mut w0);
+
+	print!("Alice's public key= 0x");
+	printbinary(&w0);
+
+	let mut res=ecdh::public_key_validate(&w0);
+	if res!=0 {
+		println!("ECP Public Key is invalid!");
+		return;
+	}
+
+/* Random private key for other party */
+	ecdh::key_pair_generate(Some(&mut rng),&mut s1,&mut w1);
+
+	print!("Servers private key= 0x");
+	printbinary(&s1);
+
+	print!("Servers public key= 0x");
+	printbinary(&w1);
+
+
+	res=ecdh::public_key_validate(&w1);
+	if res!=0 {
+		println!("ECP Public Key is invalid!");
+		return;
+	}
+/* Calculate common key using DH - IEEE 1363 method */
+
+	ecdh::ecpsvdp_dh(&s0,&w1,&mut z0);
+	ecdh::ecpsvdp_dh(&s1,&w0,&mut z1);
+
+	let mut same=true;
+	for i in 0..EFS {
+		if z0[i]!=z1[i] {same=false}
+	}
+
+	if !same {
+		println!("*** ECPSVDP-DH Failed");
+		return;
+	}
+
+	ecdh::kdf2(sha,&z0,None,EAS,&mut key);
+
+	print!("Alice's DH Key=  0x"); printbinary(&key);
+	print!("Servers DH Key=  0x"); printbinary(&key);
+
+	if ecp::CURVETYPE!=ecp::MONTGOMERY {
+
+		for i in 0..17 {m[i]=i as u8} 
+
+		println!("Testing ECIES");
+
+		p1[0]=0x0; p1[1]=0x1; p1[2]=0x2;
+		p2[0]=0x0; p2[1]=0x1; p2[2]=0x2; p2[3]=0x3;
+
+		let cc=ecdh::ecies_encrypt(sha,&p1,&p2,&mut rng,&w1,&m[0..17],&mut v,&mut t);
+
+		if let Some(mut c)=cc {
+			println!("Ciphertext= ");
+			print!("V= 0x"); printbinary(&v);
+			print!("C= 0x"); printbinary(&c);
+			print!("T= 0x"); printbinary(&t);
+		
+
+			let mm=ecdh::ecies_decrypt(sha,&p1,&p2,&v,&mut c,&t,&s1);
+			if let Some(rm)=mm {
+				println!("Decryption succeeded");
+				print!("Message is 0x"); printbinary(&rm);				
+			}
+			else {
+				println!("*** ECIES Decryption Failed");
+				return;
+			} 
+		}
+		else {
+			println!("*** ECIES Encryption Failed");
+			return;
+		} 
+
+		println!("Testing ECDSA");
+
+		if ecdh::ecpsp_dsa(sha,&mut rng,&s0,&m[0..17],&mut cs,&mut ds)!=0 {
+			println!("***ECDSA Signature Failed");
+			return;
+		}
+		println!("Signature= ");
+		print!("C= 0x"); printbinary(&cs);
+		print!("D= 0x"); printbinary(&ds);
+
+		if ecdh::ecpvp_dsa(sha,&w0,&m[0..17],&cs,&ds)!=0 {
+			println!("***ECDSA Verification Failed");
+			return;
+		} else {println!("ECDSA Signature/Verification succeeded ")}
+	}
+
+}
+
+
+fn mpin_bn254(mut rng: &mut RAND)
+{
+	use amcl::bn254;
+	use amcl::bn254::ecp;	
+	use amcl::bn254::mpin;
+	pub const PERMITS:bool=true;
+	pub const PINERROR:bool=true;
+	pub const FULL: bool=true;
+	pub const SINGLE_PASS:bool=false;
+
+	const EFS:usize=mpin::EFS;	
+	const EGS:usize=mpin::EGS;
+
+	let mut s:[u8;EGS]=[0;EGS];
+	const RM:usize=EFS as usize;
+	let mut hcid:[u8;RM]=[0;RM];
+	let mut hsid:[u8;RM]=[0;RM];
+
+	const G1S:usize=2*EFS+1; /* Group 1 Size */
+	const G2S:usize=4*EFS; /* Group 2 Size */
+	const EAS:usize=ecp::AESKEY;
+
+	let mut sst:[u8;G2S]=[0;G2S];
+	let mut token: [u8;G1S]=[0;G1S];	
+	let mut permit:[u8;G1S]=[0;G1S];	
+	let mut g1: [u8;12*EFS]=[0;12*EFS];
+	let mut g2: [u8;12*EFS]=[0;12*EFS];	
+	let mut xid: [u8;G1S]=[0;G1S];
+	let mut xcid: [u8;G1S]=[0;G1S];	
+	let mut x: [u8;EGS]=[0;EGS];	
+	let mut y: [u8;EGS]=[0;EGS];
+	let mut sec: [u8;G1S]=[0;G1S];	
+	let mut r: [u8;EGS]=[0;EGS];
+	let mut z: [u8;G1S]=[0;G1S];	
+	let mut hid: [u8;G1S]=[0;G1S];
+	let mut htid: [u8;G1S]=[0;G1S];
+	let mut rhid: [u8;G1S]=[0;G1S];
+	let mut w: [u8;EGS]=[0;EGS];
+	let mut t: [u8;G1S]=[0;G1S];
+	let mut e: [u8;12*EFS]=[0;12*EFS];
+	let mut f: [u8;12*EFS]=[0;12*EFS];
+	let mut h: [u8;RM]=[0;RM];
+	let mut ck: [u8;EAS]=[0;EAS];
+	let mut sk: [u8;EAS]=[0;EAS];	
+
+
+	let sha=ecp::HASH_TYPE;
+
+	println!("\nTesting MPIN - PIN is 1234");
+/* Trusted Authority set-up */
+
+	mpin::random_generate(&mut rng,&mut s);
+	print!("Master Secret s: 0x");  printbinary(&s);
+
+/* Create Client Identity */
+ 	let name= "testUser@miracl.com";
+ 	let client_id=name.as_bytes();
+
+	print!("Client ID= "); printbinary(&client_id); 
+
+
+	mpin::hash_id(sha,&client_id,&mut hcid);  /* Either Client or TA calculates Hash(ID) - you decide! */
+		
+/* Client and Server are issued secrets by DTA */
+	mpin::get_server_secret(&s,&mut sst);
+	print!("Server Secret SS: 0x");  printbinary(&sst);	
+
+	mpin::get_client_secret(&mut s,&hcid,&mut token);
+	print!("Client Secret CS: 0x"); printbinary(&token); 
+
+/* Client extracts PIN from secret to create Token */
+	let pin:i32=1234;
+	println!("Client extracts PIN= {}",pin);
+	let mut rtn=mpin::extract_pin(sha,&client_id,pin,&mut token);
+	if rtn != 0 {
+		println!("FAILURE: EXTRACT_PIN rtn: {}",rtn);
+	}
+
+	print!("Client Token TK: 0x"); printbinary(&token); 
+
+	if FULL {
+		mpin::precompute(&token,&hcid,&mut g1,&mut g2);
+	}
+
+	let mut date=0;
+	if PERMITS {
+		date=mpin::today();
+/* Client gets "Time Token" permit from DTA */ 
+		mpin::get_client_permit(sha,date,&s,&hcid,&mut permit);
+		print!("Time Permit TP: 0x");  printbinary(&permit);
+
+/* This encoding makes Time permit look random - Elligator squared */
+		mpin::encoding(&mut rng,&mut permit);
+		print!("Encoded Time Permit TP: 0x"); printbinary(&permit);
+		mpin::decoding(&mut permit);
+		print!("Decoded Time Permit TP: 0x"); printbinary(&permit);
+	}
+
+	print!("\nPIN= "); let _ =io::Write::flush(&mut io::stdout());
+    let mut input_text = String::new();
+    let _ = io::stdin().read_line(&mut input_text);
+
+    let pin=input_text.trim().parse::<usize>().unwrap();
+
+	println!("MPIN Multi Pass");
+/* Send U=x.ID to server, and recreate secret from token and pin */
+	rtn=mpin::client_1(sha,date,&client_id,Some(&mut rng),&mut x,pin,&token,&mut sec,Some(&mut xid[..]),Some(&mut xcid[..]),Some(&permit[..]));
+	if rtn != 0 {
+		println!("FAILURE: CLIENT_1 rtn: {}",rtn);
+	}
+  
+	if FULL {
+		mpin::hash_id(sha,&client_id,&mut hcid);
+		mpin::get_g1_multiple(Some(&mut rng),1,&mut r,&hcid,&mut z);  /* Also Send Z=r.ID to Server, remember random r */
+	}
+  
+/* Server calculates H(ID) and H(T|H(ID)) (if time mpin::PERMITS enabled), and maps them to points on the curve HID and HTID resp. */
+		
+	mpin::server_1(sha,date,&client_id,&mut hid,Some(&mut htid[..]));
+
+
+    if date!=0 {rhid.clone_from_slice(&htid[..]);}
+    else {rhid.clone_from_slice(&hid[..]);}
+    	
+/* Server generates Random number Y and sends it to Client */
+	mpin::random_generate(&mut rng,&mut y);
+  
+	if FULL {
+		mpin::hash_id(sha,&client_id,&mut hsid);
+		mpin::get_g1_multiple(Some(&mut rng),0,&mut w,&rhid,&mut t);  /* Also send T=w.ID to client, remember random w  */
+	}
+  
+/* Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC */
+	rtn=mpin::client_2(&x,&y,&mut sec);
+	if rtn != 0 {
+		println!("FAILURE: CLIENT_2 rtn: {}",rtn);
+	}
+  
+/* Server Second pass. Inputs hashed client id, random Y, -(x+y)*SEC, xID and xCID and Server secret SST. E and F help kangaroos to find error. */
+/* If PIN error not required, set E and F = null */
+  
+	if !PINERROR {
+		rtn=mpin::server_2(date,&hid,Some(&htid[..]),&y,&sst,Some(&xid[..]),Some(&xcid[..]),&sec,None,None);
+	} else {
+		rtn=mpin::server_2(date,&hid,Some(&htid[..]),&y,&sst,Some(&xid[..]),Some(&xcid[..]),&sec,Some(&mut e),Some(&mut f));
+	}
+
+	if rtn == mpin::BAD_PIN {
+		println!("Server says - Bad Pin. I don't know you. Feck off.");
+		if PINERROR {
+			let err=mpin::kangaroo(&e,&f);
+			if err!=0 {println!("(Client PIN is out by {})",err)}
+		}
+		return;
+	} else {
+		println!("Server says - PIN is good! You really are {}",name);
+	}
+
+	if  FULL {
+
+		let mut pxcid=None;
+		if PERMITS {pxcid=Some(&xcid[..])};
+
+		mpin::hash_all(sha,&hcid,&xid,pxcid,&sec,&y,&z,&t,&mut h);	
+		mpin::client_key(sha,&g1,&g2,pin,&r,&x,&h,&t,&mut ck);
+		print!("Client Key =  0x");  printbinary(&ck);
+
+		mpin::hash_all(sha,&hsid,&xid,pxcid,&sec,&y,&z,&t,&mut h);			
+		mpin::server_key(sha,&z,&sst,&w,&h,&hid,&xid,pxcid,&mut sk);
+		print!("Server Key =  0x"); printbinary(&sk);
+	}
+
+}
+
+
+fn mpin_bls383(mut rng: &mut RAND)
+{
+	use amcl::bls383;
+	use amcl::bls383::ecp;	
+	use amcl::bls383::mpin;
+	pub const PERMITS:bool=true;
+	pub const PINERROR:bool=true;
+	pub const FULL: bool=true;
+	pub const SINGLE_PASS:bool=false;
+
+	const EFS:usize=mpin::EFS;	
+	const EGS:usize=mpin::EGS;
+
+	let mut s:[u8;EGS]=[0;EGS];
+	const RM:usize=EFS as usize;
+	let mut hcid:[u8;RM]=[0;RM];
+	let mut hsid:[u8;RM]=[0;RM];
+
+	const G1S:usize=2*EFS+1; /* Group 1 Size */
+	const G2S:usize=4*EFS; /* Group 2 Size */
+	const EAS:usize=ecp::AESKEY;
+
+	let mut sst:[u8;G2S]=[0;G2S];
+	let mut token: [u8;G1S]=[0;G1S];	
+	let mut permit:[u8;G1S]=[0;G1S];	
+	let mut g1: [u8;12*EFS]=[0;12*EFS];
+	let mut g2: [u8;12*EFS]=[0;12*EFS];	
+	let mut xid: [u8;G1S]=[0;G1S];
+	let mut xcid: [u8;G1S]=[0;G1S];	
+	let mut x: [u8;EGS]=[0;EGS];	
+	let mut y: [u8;EGS]=[0;EGS];
+	let mut sec: [u8;G1S]=[0;G1S];	
+	let mut r: [u8;EGS]=[0;EGS];
+	let mut z: [u8;G1S]=[0;G1S];	
+	let mut hid: [u8;G1S]=[0;G1S];
+	let mut htid: [u8;G1S]=[0;G1S];
+	let mut rhid: [u8;G1S]=[0;G1S];
+	let mut w: [u8;EGS]=[0;EGS];
+	let mut t: [u8;G1S]=[0;G1S];
+	let mut e: [u8;12*EFS]=[0;12*EFS];
+	let mut f: [u8;12*EFS]=[0;12*EFS];
+	let mut h: [u8;RM]=[0;RM];
+	let mut ck: [u8;EAS]=[0;EAS];
+	let mut sk: [u8;EAS]=[0;EAS];	
+
+
+	let sha=ecp::HASH_TYPE;
+
+	println!("\nTesting MPIN - PIN is 1234");
+/* Trusted Authority set-up */
+
+	mpin::random_generate(&mut rng,&mut s);
+	print!("Master Secret s: 0x");  printbinary(&s);
+
+/* Create Client Identity */
+ 	let name= "testUser@miracl.com";
+ 	let client_id=name.as_bytes();
+
+	print!("Client ID= "); printbinary(&client_id); 
+
+
+	mpin::hash_id(sha,&client_id,&mut hcid);  /* Either Client or TA calculates Hash(ID) - you decide! */
+		
+/* Client and Server are issued secrets by DTA */
+	mpin::get_server_secret(&s,&mut sst);
+	print!("Server Secret SS: 0x");  printbinary(&sst);	
+
+	mpin::get_client_secret(&mut s,&hcid,&mut token);
+	print!("Client Secret CS: 0x"); printbinary(&token); 
+
+/* Client extracts PIN from secret to create Token */
+	let pin:i32=1234;
+	println!("Client extracts PIN= {}",pin);
+	let mut rtn=mpin::extract_pin(sha,&client_id,pin,&mut token);
+	if rtn != 0 {
+		println!("FAILURE: EXTRACT_PIN rtn: {}",rtn);
+	}
+
+	print!("Client Token TK: 0x"); printbinary(&token); 
+
+	if FULL {
+		mpin::precompute(&token,&hcid,&mut g1,&mut g2);
+	}
+
+	let mut date=0;
+	if PERMITS {
+		date=mpin::today();
+/* Client gets "Time Token" permit from DTA */ 
+		mpin::get_client_permit(sha,date,&s,&hcid,&mut permit);
+		print!("Time Permit TP: 0x");  printbinary(&permit);
+
+/* This encoding makes Time permit look random - Elligator squared */
+		mpin::encoding(&mut rng,&mut permit);
+		print!("Encoded Time Permit TP: 0x"); printbinary(&permit);
+		mpin::decoding(&mut permit);
+		print!("Decoded Time Permit TP: 0x"); printbinary(&permit);
+	}
+
+	print!("\nPIN= "); let _ =io::Write::flush(&mut io::stdout());
+    let mut input_text = String::new();
+    let _ = io::stdin().read_line(&mut input_text);
+
+    let pin=input_text.trim().parse::<usize>().unwrap();
+
+	println!("MPIN Multi Pass");
+/* Send U=x.ID to server, and recreate secret from token and pin */
+	rtn=mpin::client_1(sha,date,&client_id,Some(&mut rng),&mut x,pin,&token,&mut sec,Some(&mut xid[..]),Some(&mut xcid[..]),Some(&permit[..]));
+	if rtn != 0 {
+		println!("FAILURE: CLIENT_1 rtn: {}",rtn);
+	}
+  
+	if FULL {
+		mpin::hash_id(sha,&client_id,&mut hcid);
+		mpin::get_g1_multiple(Some(&mut rng),1,&mut r,&hcid,&mut z);  /* Also Send Z=r.ID to Server, remember random r */
+	}
+  
+/* Server calculates H(ID) and H(T|H(ID)) (if time mpin::PERMITS enabled), and maps them to points on the curve HID and HTID resp. */
+		
+	mpin::server_1(sha,date,&client_id,&mut hid,Some(&mut htid[..]));
+
+
+    if date!=0 {rhid.clone_from_slice(&htid[..]);}
+    else {rhid.clone_from_slice(&hid[..]);}
+    	
+/* Server generates Random number Y and sends it to Client */
+	mpin::random_generate(&mut rng,&mut y);
+  
+	if FULL {
+		mpin::hash_id(sha,&client_id,&mut hsid);
+		mpin::get_g1_multiple(Some(&mut rng),0,&mut w,&rhid,&mut t);  /* Also send T=w.ID to client, remember random w  */
+	}
+  
+/* Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC */
+	rtn=mpin::client_2(&x,&y,&mut sec);
+	if rtn != 0 {
+		println!("FAILURE: CLIENT_2 rtn: {}",rtn);
+	}
+  
+/* Server Second pass. Inputs hashed client id, random Y, -(x+y)*SEC, xID and xCID and Server secret SST. E and F help kangaroos to find error. */
+/* If PIN error not required, set E and F = null */
+  
+	if !PINERROR {
+		rtn=mpin::server_2(date,&hid,Some(&htid[..]),&y,&sst,Some(&xid[..]),Some(&xcid[..]),&sec,None,None);
+	} else {
+		rtn=mpin::server_2(date,&hid,Some(&htid[..]),&y,&sst,Some(&xid[..]),Some(&xcid[..]),&sec,Some(&mut e),Some(&mut f));
+	}
+
+	if rtn == mpin::BAD_PIN {
+		println!("Server says - Bad Pin. I don't know you. Feck off.");
+		if PINERROR {
+			let err=mpin::kangaroo(&e,&f);
+			if err!=0 {println!("(Client PIN is out by {})",err)}
+		}
+		return;
+	} else {
+		println!("Server says - PIN is good! You really are {}",name);
+	}
+
+	if  FULL {
+
+		let mut pxcid=None;
+		if PERMITS {pxcid=Some(&xcid[..])};
+
+		mpin::hash_all(sha,&hcid,&xid,pxcid,&sec,&y,&z,&t,&mut h);	
+		mpin::client_key(sha,&g1,&g2,pin,&r,&x,&h,&t,&mut ck);
+		print!("Client Key =  0x");  printbinary(&ck);
+
+		mpin::hash_all(sha,&hsid,&xid,pxcid,&sec,&y,&z,&t,&mut h);			
+		mpin::server_key(sha,&z,&sst,&w,&h,&hid,&xid,pxcid,&mut sk);
+		print!("Server Key =  0x"); printbinary(&sk);
+	}
+
+}
+
+fn mpin_bls24(mut rng: &mut RAND)
+{
+	use amcl::bls24;
+	use amcl::bls24::ecp;	
+	use amcl::bls24::mpin192;
+
+	pub const PERMITS:bool=true;
+	pub const PINERROR:bool=true;
+	pub const FULL: bool=true;
+	pub const SINGLE_PASS:bool=false;
+
+	const EFS:usize=mpin192::EFS;	
+	const EGS:usize=mpin192::EGS;
+
+	let mut s:[u8;EGS]=[0;EGS];
+	const RM:usize=EFS as usize;
+	let mut hcid:[u8;RM]=[0;RM];
+	let mut hsid:[u8;RM]=[0;RM];
+
+	const G1S:usize=2*EFS+1; /* Group 1 Size */
+	const G2S:usize=8*EFS; /* Group 2 Size */
+	const EAS:usize=ecp::AESKEY;
+
+	let mut sst:[u8;G2S]=[0;G2S];
+	let mut token: [u8;G1S]=[0;G1S];	
+	let mut permit:[u8;G1S]=[0;G1S];	
+	let mut g1: [u8;24*EFS]=[0;24*EFS];
+	let mut g2: [u8;24*EFS]=[0;24*EFS];	
+	let mut xid: [u8;G1S]=[0;G1S];
+	let mut xcid: [u8;G1S]=[0;G1S];	
+	let mut x: [u8;EGS]=[0;EGS];	
+	let mut y: [u8;EGS]=[0;EGS];
+	let mut sec: [u8;G1S]=[0;G1S];	
+	let mut r: [u8;EGS]=[0;EGS];
+	let mut z: [u8;G1S]=[0;G1S];	
+	let mut hid: [u8;G1S]=[0;G1S];
+	let mut htid: [u8;G1S]=[0;G1S];
+	let mut rhid: [u8;G1S]=[0;G1S];
+	let mut w: [u8;EGS]=[0;EGS];
+	let mut t: [u8;G1S]=[0;G1S];
+	let mut e: [u8;24*EFS]=[0;24*EFS];
+	let mut f: [u8;24*EFS]=[0;24*EFS];
+	let mut h: [u8;RM]=[0;RM];
+	let mut ck: [u8;EAS]=[0;EAS];
+	let mut sk: [u8;EAS]=[0;EAS];	
+
+
+	let sha=ecp::HASH_TYPE;
+
+	println!("\nTesting MPIN - PIN is 1234");
+/* Trusted Authority set-up */
+
+	mpin192::random_generate(&mut rng,&mut s);
+	print!("Master Secret s: 0x");  printbinary(&s);
+
+/* Create Client Identity */
+ 	let name= "testUser@miracl.com";
+ 	let client_id=name.as_bytes();
+
+	print!("Client ID= "); printbinary(&client_id); 
+
+
+	mpin192::hash_id(sha,&client_id,&mut hcid);  /* Either Client or TA calculates Hash(ID) - you decide! */
+		
+/* Client and Server are issued secrets by DTA */
+	mpin192::get_server_secret(&s,&mut sst);
+	print!("Server Secret SS: 0x");  printbinary(&sst);	
+
+	mpin192::get_client_secret(&mut s,&hcid,&mut token);
+	print!("Client Secret CS: 0x"); printbinary(&token); 
+
+/* Client extracts PIN from secret to create Token */
+	let pin:i32=1234;
+	println!("Client extracts PIN= {}",pin);
+	let mut rtn=mpin192::extract_pin(sha,&client_id,pin,&mut token);
+	if rtn != 0 {
+		println!("FAILURE: EXTRACT_PIN rtn: {}",rtn);
+	}
+
+	print!("Client Token TK: 0x"); printbinary(&token); 
+
+	if FULL {
+		mpin192::precompute(&token,&hcid,&mut g1,&mut g2);
+	}
+
+	let mut date=0;
+	if PERMITS {
+		date=mpin192::today();
+/* Client gets "Time Token" permit from DTA */ 
+		mpin192::get_client_permit(sha,date,&s,&hcid,&mut permit);
+		print!("Time Permit TP: 0x");  printbinary(&permit);
+
+/* This encoding makes Time permit look random - Elligator squared */
+		mpin192::encoding(&mut rng,&mut permit);
+		print!("Encoded Time Permit TP: 0x"); printbinary(&permit);
+		mpin192::decoding(&mut permit);
+		print!("Decoded Time Permit TP: 0x"); printbinary(&permit);
+	}
+
+	print!("\nPIN= "); let _ =io::Write::flush(&mut io::stdout());
+    let mut input_text = String::new();
+    let _ = io::stdin().read_line(&mut input_text);
+
+    let pin=input_text.trim().parse::<usize>().unwrap();
+
+	println!("MPIN Multi Pass");
+/* Send U=x.ID to server, and recreate secret from token and pin */
+	rtn=mpin192::client_1(sha,date,&client_id,Some(&mut rng),&mut x,pin,&token,&mut sec,Some(&mut xid[..]),Some(&mut xcid[..]),Some(&permit[..]));
+	if rtn != 0 {
+		println!("FAILURE: CLIENT_1 rtn: {}",rtn);
+	}
+  
+	if FULL {
+		mpin192::hash_id(sha,&client_id,&mut hcid);
+		mpin192::get_g1_multiple(Some(&mut rng),1,&mut r,&hcid,&mut z);  /* Also Send Z=r.ID to Server, remember random r */
+	}
+  
+/* Server calculates H(ID) and H(T|H(ID)) (if time mpin192::PERMITS enabled), and maps them to points on the curve HID and HTID resp. */
+		
+	mpin192::server_1(sha,date,&client_id,&mut hid,Some(&mut htid[..]));
+
+
+    if date!=0 {rhid.clone_from_slice(&htid[..]);}
+    else {rhid.clone_from_slice(&hid[..]);}
+    	
+/* Server generates Random number Y and sends it to Client */
+	mpin192::random_generate(&mut rng,&mut y);
+  
+	if FULL {
+		mpin192::hash_id(sha,&client_id,&mut hsid);
+		mpin192::get_g1_multiple(Some(&mut rng),0,&mut w,&rhid,&mut t);  /* Also send T=w.ID to client, remember random w  */
+	}
+  
+/* Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC */
+	rtn=mpin192::client_2(&x,&y,&mut sec);
+	if rtn != 0 {
+		println!("FAILURE: CLIENT_2 rtn: {}",rtn);
+	}
+  
+/* Server Second pass. Inputs hashed client id, random Y, -(x+y)*SEC, xID and xCID and Server secret SST. E and F help kangaroos to find error. */
+/* If PIN error not required, set E and F = null */
+  
+	if !PINERROR {
+		rtn=mpin192::server_2(date,&hid,Some(&htid[..]),&y,&sst,Some(&xid[..]),Some(&xcid[..]),&sec,None,None);
+	} else {
+		rtn=mpin192::server_2(date,&hid,Some(&htid[..]),&y,&sst,Some(&xid[..]),Some(&xcid[..]),&sec,Some(&mut e),Some(&mut f));
+	}
+
+	if rtn == mpin192::BAD_PIN {
+		println!("Server says - Bad Pin. I don't know you. Feck off.");
+		if PINERROR {
+			let err=mpin192::kangaroo(&e,&f);
+			if err!=0 {println!("(Client PIN is out by {})",err)}
+		}
+		return;
+	} else {
+		println!("Server says - PIN is good! You really are {}",name);
+	}
+
+	if  FULL {
+
+		let mut pxcid=None;
+		if PERMITS {pxcid=Some(&xcid[..])};
+
+		mpin192::hash_all(sha,&hcid,&xid,pxcid,&sec,&y,&z,&t,&mut h);	
+		mpin192::client_key(sha,&g1,&g2,pin,&r,&x,&h,&t,&mut ck);
+		print!("Client Key =  0x");  printbinary(&ck);
+
+		mpin192::hash_all(sha,&hsid,&xid,pxcid,&sec,&y,&z,&t,&mut h);			
+		mpin192::server_key(sha,&z,&sst,&w,&h,&hid,&xid,pxcid,&mut sk);
+		print!("Server Key =  0x"); printbinary(&sk);
+	}
+
+}
+
+
+fn mpin_bls48(mut rng: &mut RAND)
+{
+	use amcl::bls48;
+	use amcl::bls48::ecp;	
+	use amcl::bls48::mpin256;
+
+	pub const PERMITS:bool=true;
+	pub const PINERROR:bool=true;
+	pub const FULL: bool=true;
+	pub const SINGLE_PASS:bool=false;
+
+	const EFS:usize=mpin256::EFS;	
+	const EGS:usize=mpin256::EGS;
+
+	let mut s:[u8;EGS]=[0;EGS];
+	const RM:usize=EFS as usize;
+	let mut hcid:[u8;RM]=[0;RM];
+	let mut hsid:[u8;RM]=[0;RM];
+
+	const G1S:usize=2*EFS+1; /* Group 1 Size */
+	const G2S:usize=16*EFS; /* Group 2 Size */
+	const EAS:usize=ecp::AESKEY;
+
+	let mut sst:[u8;G2S]=[0;G2S];
+	let mut token: [u8;G1S]=[0;G1S];	
+	let mut permit:[u8;G1S]=[0;G1S];	
+	let mut g1: [u8;48*EFS]=[0;48*EFS];
+	let mut g2: [u8;48*EFS]=[0;48*EFS];	
+	let mut xid: [u8;G1S]=[0;G1S];
+	let mut xcid: [u8;G1S]=[0;G1S];	
+	let mut x: [u8;EGS]=[0;EGS];	
+	let mut y: [u8;EGS]=[0;EGS];
+	let mut sec: [u8;G1S]=[0;G1S];	
+	let mut r: [u8;EGS]=[0;EGS];
+	let mut z: [u8;G1S]=[0;G1S];	
+	let mut hid: [u8;G1S]=[0;G1S];
+	let mut htid: [u8;G1S]=[0;G1S];
+	let mut rhid: [u8;G1S]=[0;G1S];
+	let mut w: [u8;EGS]=[0;EGS];
+	let mut t: [u8;G1S]=[0;G1S];
+	let mut e: [u8;48*EFS]=[0;48*EFS];
+	let mut f: [u8;48*EFS]=[0;48*EFS];
+	let mut h: [u8;RM]=[0;RM];
+	let mut ck: [u8;EAS]=[0;EAS];
+	let mut sk: [u8;EAS]=[0;EAS];	
+
+
+	let sha=ecp::HASH_TYPE;
+
+	println!("\nTesting MPIN - PIN is 1234");
+/* Trusted Authority set-up */
+
+	mpin256::random_generate(&mut rng,&mut s);
+	print!("Master Secret s: 0x");  printbinary(&s);
+
+/* Create Client Identity */
+ 	let name= "testUser@miracl.com";
+ 	let client_id=name.as_bytes();
+
+	print!("Client ID= "); printbinary(&client_id); 
+
+
+	mpin256::hash_id(sha,&client_id,&mut hcid);  /* Either Client or TA calculates Hash(ID) - you decide! */
+		
+/* Client and Server are issued secrets by DTA */
+	mpin256::get_server_secret(&s,&mut sst);
+	print!("Server Secret SS: 0x");  printbinary(&sst);	
+
+	mpin256::get_client_secret(&mut s,&hcid,&mut token);
+	print!("Client Secret CS: 0x"); printbinary(&token); 
+
+/* Client extracts PIN from secret to create Token */
+	let pin:i32=1234;
+	println!("Client extracts PIN= {}",pin);
+	let mut rtn=mpin256::extract_pin(sha,&client_id,pin,&mut token);
+	if rtn != 0 {
+		println!("FAILURE: EXTRACT_PIN rtn: {}",rtn);
+	}
+
+	print!("Client Token TK: 0x"); printbinary(&token); 
+
+	if FULL {
+		mpin256::precompute(&token,&hcid,&mut g1,&mut g2);
+	}
+
+	let mut date=0;
+	if PERMITS {
+		date=mpin256::today();
+/* Client gets "Time Token" permit from DTA */ 
+		mpin256::get_client_permit(sha,date,&s,&hcid,&mut permit);
+		print!("Time Permit TP: 0x");  printbinary(&permit);
+
+/* This encoding makes Time permit look random - Elligator squared */
+		mpin256::encoding(&mut rng,&mut permit);
+		print!("Encoded Time Permit TP: 0x"); printbinary(&permit);
+		mpin256::decoding(&mut permit);
+		print!("Decoded Time Permit TP: 0x"); printbinary(&permit);
+	}
+
+	print!("\nPIN= "); let _ =io::Write::flush(&mut io::stdout());
+    let mut input_text = String::new();
+    let _ = io::stdin().read_line(&mut input_text);
+
+    let pin=input_text.trim().parse::<usize>().unwrap();
+
+	println!("MPIN Multi Pass");
+/* Send U=x.ID to server, and recreate secret from token and pin */
+	rtn=mpin256::client_1(sha,date,&client_id,Some(&mut rng),&mut x,pin,&token,&mut sec,Some(&mut xid[..]),Some(&mut xcid[..]),Some(&permit[..]));
+	if rtn != 0 {
+		println!("FAILURE: CLIENT_1 rtn: {}",rtn);
+	}
+  
+	if FULL {
+		mpin256::hash_id(sha,&client_id,&mut hcid);
+		mpin256::get_g1_multiple(Some(&mut rng),1,&mut r,&hcid,&mut z);  /* Also Send Z=r.ID to Server, remember random r */
+	}
+  
+/* Server calculates H(ID) and H(T|H(ID)) (if time mpin256::PERMITS enabled), and maps them to points on the curve HID and HTID resp. */
+		
+	mpin256::server_1(sha,date,&client_id,&mut hid,Some(&mut htid[..]));
+
+
+    if date!=0 {rhid.clone_from_slice(&htid[..]);}
+    else {rhid.clone_from_slice(&hid[..]);}
+    	
+/* Server generates Random number Y and sends it to Client */
+	mpin256::random_generate(&mut rng,&mut y);
+  
+	if FULL {
+		mpin256::hash_id(sha,&client_id,&mut hsid);
+		mpin256::get_g1_multiple(Some(&mut rng),0,&mut w,&rhid,&mut t);  /* Also send T=w.ID to client, remember random w  */
+	}
+  
+/* Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC */
+	rtn=mpin256::client_2(&x,&y,&mut sec);
+	if rtn != 0 {
+		println!("FAILURE: CLIENT_2 rtn: {}",rtn);
+	}
+  
+/* Server Second pass. Inputs hashed client id, random Y, -(x+y)*SEC, xID and xCID and Server secret SST. E and F help kangaroos to find error. */
+/* If PIN error not required, set E and F = null */
+  
+	if !PINERROR {
+		rtn=mpin256::server_2(date,&hid,Some(&htid[..]),&y,&sst,Some(&xid[..]),Some(&xcid[..]),&sec,None,None);
+	} else {
+		rtn=mpin256::server_2(date,&hid,Some(&htid[..]),&y,&sst,Some(&xid[..]),Some(&xcid[..]),&sec,Some(&mut e),Some(&mut f));
+	}
+
+	if rtn == mpin256::BAD_PIN {
+		println!("Server says - Bad Pin. I don't know you. Feck off.");
+		if PINERROR {
+			let err=mpin256::kangaroo(&e,&f);
+			if err!=0 {println!("(Client PIN is out by {})",err)}
+		}
+		return;
+	} else {
+		println!("Server says - PIN is good! You really are {}",name);
+	}
+
+	if  FULL {
+
+		let mut pxcid=None;
+		if PERMITS {pxcid=Some(&xcid[..])};
+
+		mpin256::hash_all(sha,&hcid,&xid,pxcid,&sec,&y,&z,&t,&mut h);	
+		mpin256::client_key(sha,&g1,&g2,pin,&r,&x,&h,&t,&mut ck);
+		print!("Client Key =  0x");  printbinary(&ck);
+
+		mpin256::hash_all(sha,&hsid,&xid,pxcid,&sec,&y,&z,&t,&mut h);			
+		mpin256::server_key(sha,&z,&sst,&w,&h,&hid,&xid,pxcid,&mut sk);
+		print!("Server Key =  0x"); printbinary(&sk);
+	}
+
+}
+
+
+
+fn rsa_2048(mut rng: &mut RAND)
+{
+	use amcl::rsa2048;
+	use amcl::rsa2048::ff;
+	use amcl::rsa2048::rsa;
+
+	let sha=rsa::HASH_TYPE;
+	let message:&[u8] = b"Hello World\n";
+	const RFS:usize=rsa::RFS;
+
+	let mut pbc=rsa::new_public_key(ff::FFLEN);
+	let mut prv=rsa::new_private_key(ff::HFLEN);
+
+	let mut ml:[u8;RFS]=[0;RFS];
+	let mut ms:[u8;RFS]=[0;RFS];	
+	let mut c: [u8;RFS]=[0;RFS];
+	let mut s: [u8;RFS]=[0;RFS];
+	let mut e: [u8;RFS]=[0;RFS];
+
+	println!("\nTesting RSA");
+	println!("Generating public/private key pair");
+	rsa::key_pair(&mut rng,65537,&mut prv,&mut pbc);
+
+	println!("Encrypting test string\n");
+	rsa::oaep_encode(sha,&message,&mut rng,None,&mut e); /* OAEP encode message M to E  */
+
+	rsa::encrypt(&pbc,&e,&mut c);    /* encrypt encoded message */
+	print!("Ciphertext= 0x"); printbinary(&c);
+
+	println!("Decrypting test string");
+	rsa::decrypt(&prv,&c,&mut ml);
+	let mlen=rsa::oaep_decode(sha,None,&mut ml); /* OAEP decode message  */
+
+	let mess=str::from_utf8(&ml[0..mlen]).unwrap();
+	print!("{}",&mess);
+
+	println!("Signing message");
+	rsa::pkcs15(sha,message,&mut c); 
+
+	rsa::decrypt(&prv,&c,&mut s);  /* create signature in S */ 
+
+	print!("Signature= 0x"); printbinary(&s);
+
+	rsa::encrypt(&pbc,&s,&mut ms);
+
+	let mut cmp=true;
+	if c.len()!=ms.len() {
+		cmp=false;
+	} else {
+		for j in 0..c.len() {
+			if c[j]!=ms[j] {cmp=false}
+		}
+	}
+	if cmp {
+		println!("Signature is valid");
+	} else {
+		println!("Signature is INVALID");
+	}
+
+	rsa::private_key_kill(&mut prv);
+}
+
+
+fn main()
+{
+	let mut raw:[u8;100]=[0;100];	
+
+	let mut rng=RAND::new();
+	rng.clean();
+	for i in 0..100 {raw[i]=i as u8}
+
+	rng.seed(100,&raw);	
+
+	ecdh_ed25519(&mut rng);	
+	ecdh_nist256(&mut rng);
+	ecdh_goldilocks(&mut rng);
+	mpin_bn254(&mut rng);	
+	mpin_bls383(&mut rng);		
+	mpin_bls24(&mut rng);
+	mpin_bls48(&mut rng);
+	rsa_2048(&mut rng);
+
+}
diff --git a/version3/rust/TestNHS.rs b/version3/rust/TestNHS.rs
new file mode 100644
index 0000000..0303060
--- /dev/null
+++ b/version3/rust/TestNHS.rs
@@ -0,0 +1,76 @@
+/*
+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.
+*/
+
+//  TestNHS.rs - Tests NewHope Simple API
+
+// See https://eprint.iacr.org/2016/1157 (Alkim, Ducas, Popplemann and Schwabe)
+
+// rustc TestNHS.rs --extern amcl=libamcl.rlib
+
+extern crate amcl;
+
+use std::str;
+use std::io;
+
+use amcl::rand::RAND;
+use amcl::aes;
+use amcl::nhs;
+
+fn main()
+{
+	let mut raw:[u8;100]=[0;100];	
+
+	let mut srng=RAND::new();
+	srng.clean();
+	for i in 0..100 {raw[i]=(i+1) as u8}
+
+	srng.seed(100,&raw);	
+
+
+									let mut crng=RAND::new();
+									crng.clean();
+									for i in 0..100 {raw[i]=(i+2) as u8}
+
+									crng.seed(100,&raw);	
+
+
+	let mut ss:[u8;1792]=[0;1792];
+					let mut sb:[u8;1824]=[0;1824];
+					let mut uc:[u8;2176]=[0;2176];
+
+	let mut keya:[u8;32]=[0;32];
+									let mut keyb:[u8;32]=[0;32];
+
+	nhs::server_1(&mut srng,&mut sb,&mut ss);
+
+									nhs::client(&mut crng,&sb,&mut uc,&mut keyb);
+
+	nhs::server_2(&ss,&uc,&mut keya);
+
+	for i in 0..keya.len() {
+		print!("{:02X}", keya[i]);
+	}
+	println!("");	
+
+									for i in 0..keyb.len() {
+										print!("{:02X}", keyb[i]);
+									}
+									println!("");		
+
+}
\ No newline at end of file
diff --git a/version3/rust/aes.rs b/version3/rust/aes.rs
new file mode 100644
index 0000000..2aab45f
--- /dev/null
+++ b/version3/rust/aes.rs
@@ -0,0 +1,628 @@
+/*
+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.
+*/
+
+pub const ECB: usize=0;
+pub const CBC: usize=1;
+pub const CFB1: usize=2;
+pub const CFB2: usize=3;
+pub const CFB4: usize=5;
+pub const OFB1: usize=14;
+pub const OFB2: usize=15;
+pub const OFB4: usize=17;
+pub const OFB8:usize=21;
+pub const OFB16: usize=29;
+pub const CTR1: usize=30;
+pub const CTR2: usize=31;
+pub const CTR4: usize=33;
+pub const CTR8: usize=37;
+pub const CTR16: usize=45;
+
+const INCO : [u8;4] = [0xB,0xD,0x9,0xE];  /* Inverse Coefficients */
+
+const PTAB : [u8;256] = [
+     1, 3, 5, 15, 17, 51, 85, 255, 26, 46, 114, 150, 161, 248, 19, 53,
+     95, 225, 56, 72, 216, 115, 149, 164, 247, 2, 6, 10, 30, 34, 102, 170,
+     229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217, 112, 144, 171, 230, 49,
+     83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104, 184, 211, 110, 178, 205,
+     76, 212, 103, 169, 224, 59, 77, 215, 98, 166, 241, 8, 24, 40, 120, 136,
+     131, 158, 185, 208, 107, 189, 220, 127, 129, 152, 179, 206, 73, 219, 118, 154,
+     181, 196, 87, 249, 16, 48, 80, 240, 11, 29, 39, 105, 187, 214, 97, 163,
+     254, 25, 43, 125, 135, 146, 173, 236, 47, 113, 147, 174, 233, 32, 96, 160,
+     251, 22, 58, 78, 210, 109, 183, 194, 93, 231, 50, 86, 250, 21, 63, 65,
+     195, 94, 226, 61, 71, 201, 64, 192, 91, 237, 44, 116, 156, 191, 218, 117,
+     159, 186, 213, 100, 172, 239, 42, 126, 130, 157, 188, 223, 122, 142, 137, 128,
+     155, 182, 193, 88, 232, 35, 101, 175, 234, 37, 111, 177, 200, 67, 197, 84,
+     252, 31, 33, 99, 165, 244, 7, 9, 27, 45, 119, 153, 176, 203, 70, 202,
+     69, 207, 74, 222, 121, 139, 134, 145, 168, 227, 62, 66, 198, 81, 243, 14,
+     18, 54, 90, 238, 41, 123, 141, 140, 143, 138, 133, 148, 167, 242, 13, 23,
+     57, 75, 221, 124, 132, 151, 162, 253, 28, 36, 108, 180, 199, 82, 246, 1];
+
+const LTAB : [u8;256] = [
+      0, 255, 25, 1, 50, 2, 26, 198, 75, 199, 27, 104, 51, 238, 223, 3,
+     100, 4, 224, 14, 52, 141, 129, 239, 76, 113, 8, 200, 248, 105, 28, 193,
+     125, 194, 29, 181, 249, 185, 39, 106, 77, 228, 166, 114, 154, 201, 9, 120,
+     101, 47, 138, 5, 33, 15, 225, 36, 18, 240, 130, 69, 53, 147, 218, 142,
+     150, 143, 219, 189, 54, 208, 206, 148, 19, 92, 210, 241, 64, 70, 131, 56,
+     102, 221, 253, 48, 191, 6, 139, 98, 179, 37, 226, 152, 34, 136, 145, 16,
+     126, 110, 72, 195, 163, 182, 30, 66, 58, 107, 40, 84, 250, 133, 61, 186,
+     43, 121, 10, 21, 155, 159, 94, 202, 78, 212, 172, 229, 243, 115, 167, 87,
+     175, 88, 168, 80, 244, 234, 214, 116, 79, 174, 233, 213, 231, 230, 173, 232,
+     44, 215, 117, 122, 235, 22, 11, 245, 89, 203, 95, 176, 156, 169, 81, 160,
+     127, 12, 246, 111, 23, 196, 73, 236, 216, 67, 31, 45, 164, 118, 123, 183,
+     204, 187, 62, 90, 251, 96, 177, 134, 59, 82, 161, 108, 170, 85, 41, 157,
+     151, 178, 135, 144, 97, 190, 220, 252, 188, 149, 207, 205, 55, 63, 91, 209,
+     83, 57, 132, 60, 65, 162, 109, 71, 20, 42, 158, 93, 86, 242, 211, 171,
+     68, 17, 146, 217, 35, 32, 46, 137, 180, 124, 184, 38, 119, 153, 227, 165,
+     103, 74, 237, 222, 197, 49, 254, 24, 13, 99, 140, 128, 192, 247, 112, 7];
+
+
+const FBSUB : [u8;256] = [
+     99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118,
+     202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192,
+     183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21,
+     4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117,
+     9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132,
+     83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207,
+     208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168,
+     81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210,
+     205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115,
+     96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219,
+     224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121,
+     231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8,
+     186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138,
+     112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158,
+     225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223,
+     140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22];
+
+const RBSUB : [u8;256] = [
+     82, 9, 106, 213, 48, 54, 165, 56, 191, 64, 163, 158, 129, 243, 215, 251,
+     124, 227, 57, 130, 155, 47, 255, 135, 52, 142, 67, 68, 196, 222, 233, 203,
+     84, 123, 148, 50, 166, 194, 35, 61, 238, 76, 149, 11, 66, 250, 195, 78,
+     8, 46, 161, 102, 40, 217, 36, 178, 118, 91, 162, 73, 109, 139, 209, 37,
+     114, 248, 246, 100, 134, 104, 152, 22, 212, 164, 92, 204, 93, 101, 182, 146,
+     108, 112, 72, 80, 253, 237, 185, 218, 94, 21, 70, 87, 167, 141, 157, 132,
+     144, 216, 171, 0, 140, 188, 211, 10, 247, 228, 88, 5, 184, 179, 69, 6,
+     208, 44, 30, 143, 202, 63, 15, 2, 193, 175, 189, 3, 1, 19, 138, 107,
+     58, 145, 17, 65, 79, 103, 220, 234, 151, 242, 207, 206, 240, 180, 230, 115,
+     150, 172, 116, 34, 231, 173, 53, 133, 226, 249, 55, 232, 28, 117, 223, 110,
+     71, 241, 26, 113, 29, 41, 197, 137, 111, 183, 98, 14, 170, 24, 190, 27,
+     252, 86, 62, 75, 198, 210, 121, 32, 154, 219, 192, 254, 120, 205, 90, 244,
+     31, 221, 168, 51, 136, 7, 199, 49, 177, 18, 16, 89, 39, 128, 236, 95,
+     96, 81, 127, 169, 25, 181, 74, 13, 45, 229, 122, 159, 147, 201, 156, 239,
+     160, 224, 59, 77, 174, 42, 245, 176, 200, 235, 187, 60, 131, 83, 153, 97,
+     23, 43, 4, 126, 186, 119, 214, 38, 225, 105, 20, 99, 85, 33, 12, 125];
+
+const RCO : [u8;16] = [1,2,4,8,16,32,64,128,27,54,108,216,171,77,154,47];
+
+const FTABLE : [u32;256] = [
+    0xa56363c6,0x847c7cf8,0x997777ee,0x8d7b7bf6,0xdf2f2ff,0xbd6b6bd6,
+    0xb16f6fde,0x54c5c591,0x50303060,0x3010102,0xa96767ce,0x7d2b2b56,
+    0x19fefee7,0x62d7d7b5,0xe6abab4d,0x9a7676ec,0x45caca8f,0x9d82821f,
+    0x40c9c989,0x877d7dfa,0x15fafaef,0xeb5959b2,0xc947478e,0xbf0f0fb,
+    0xecadad41,0x67d4d4b3,0xfda2a25f,0xeaafaf45,0xbf9c9c23,0xf7a4a453,
+    0x967272e4,0x5bc0c09b,0xc2b7b775,0x1cfdfde1,0xae93933d,0x6a26264c,
+    0x5a36366c,0x413f3f7e,0x2f7f7f5,0x4fcccc83,0x5c343468,0xf4a5a551,
+    0x34e5e5d1,0x8f1f1f9,0x937171e2,0x73d8d8ab,0x53313162,0x3f15152a,
+    0xc040408,0x52c7c795,0x65232346,0x5ec3c39d,0x28181830,0xa1969637,
+    0xf05050a,0xb59a9a2f,0x907070e,0x36121224,0x9b80801b,0x3de2e2df,
+    0x26ebebcd,0x6927274e,0xcdb2b27f,0x9f7575ea,0x1b090912,0x9e83831d,
+    0x742c2c58,0x2e1a1a34,0x2d1b1b36,0xb26e6edc,0xee5a5ab4,0xfba0a05b,
+    0xf65252a4,0x4d3b3b76,0x61d6d6b7,0xceb3b37d,0x7b292952,0x3ee3e3dd,
+    0x712f2f5e,0x97848413,0xf55353a6,0x68d1d1b9,0x0,0x2cededc1,
+    0x60202040,0x1ffcfce3,0xc8b1b179,0xed5b5bb6,0xbe6a6ad4,0x46cbcb8d,
+    0xd9bebe67,0x4b393972,0xde4a4a94,0xd44c4c98,0xe85858b0,0x4acfcf85,
+    0x6bd0d0bb,0x2aefefc5,0xe5aaaa4f,0x16fbfbed,0xc5434386,0xd74d4d9a,
+    0x55333366,0x94858511,0xcf45458a,0x10f9f9e9,0x6020204,0x817f7ffe,
+    0xf05050a0,0x443c3c78,0xba9f9f25,0xe3a8a84b,0xf35151a2,0xfea3a35d,
+    0xc0404080,0x8a8f8f05,0xad92923f,0xbc9d9d21,0x48383870,0x4f5f5f1,
+    0xdfbcbc63,0xc1b6b677,0x75dadaaf,0x63212142,0x30101020,0x1affffe5,
+    0xef3f3fd,0x6dd2d2bf,0x4ccdcd81,0x140c0c18,0x35131326,0x2fececc3,
+    0xe15f5fbe,0xa2979735,0xcc444488,0x3917172e,0x57c4c493,0xf2a7a755,
+    0x827e7efc,0x473d3d7a,0xac6464c8,0xe75d5dba,0x2b191932,0x957373e6,
+    0xa06060c0,0x98818119,0xd14f4f9e,0x7fdcdca3,0x66222244,0x7e2a2a54,
+    0xab90903b,0x8388880b,0xca46468c,0x29eeeec7,0xd3b8b86b,0x3c141428,
+    0x79dedea7,0xe25e5ebc,0x1d0b0b16,0x76dbdbad,0x3be0e0db,0x56323264,
+    0x4e3a3a74,0x1e0a0a14,0xdb494992,0xa06060c,0x6c242448,0xe45c5cb8,
+    0x5dc2c29f,0x6ed3d3bd,0xefacac43,0xa66262c4,0xa8919139,0xa4959531,
+    0x37e4e4d3,0x8b7979f2,0x32e7e7d5,0x43c8c88b,0x5937376e,0xb76d6dda,
+    0x8c8d8d01,0x64d5d5b1,0xd24e4e9c,0xe0a9a949,0xb46c6cd8,0xfa5656ac,
+    0x7f4f4f3,0x25eaeacf,0xaf6565ca,0x8e7a7af4,0xe9aeae47,0x18080810,
+    0xd5baba6f,0x887878f0,0x6f25254a,0x722e2e5c,0x241c1c38,0xf1a6a657,
+    0xc7b4b473,0x51c6c697,0x23e8e8cb,0x7cdddda1,0x9c7474e8,0x211f1f3e,
+    0xdd4b4b96,0xdcbdbd61,0x868b8b0d,0x858a8a0f,0x907070e0,0x423e3e7c,
+    0xc4b5b571,0xaa6666cc,0xd8484890,0x5030306,0x1f6f6f7,0x120e0e1c,
+    0xa36161c2,0x5f35356a,0xf95757ae,0xd0b9b969,0x91868617,0x58c1c199,
+    0x271d1d3a,0xb99e9e27,0x38e1e1d9,0x13f8f8eb,0xb398982b,0x33111122,
+    0xbb6969d2,0x70d9d9a9,0x898e8e07,0xa7949433,0xb69b9b2d,0x221e1e3c,
+    0x92878715,0x20e9e9c9,0x49cece87,0xff5555aa,0x78282850,0x7adfdfa5,
+    0x8f8c8c03,0xf8a1a159,0x80898909,0x170d0d1a,0xdabfbf65,0x31e6e6d7,
+    0xc6424284,0xb86868d0,0xc3414182,0xb0999929,0x772d2d5a,0x110f0f1e,
+    0xcbb0b07b,0xfc5454a8,0xd6bbbb6d,0x3a16162c];
+
+const RTABLE : [u32;256] = [
+    0x50a7f451,0x5365417e,0xc3a4171a,0x965e273a,0xcb6bab3b,0xf1459d1f,
+    0xab58faac,0x9303e34b,0x55fa3020,0xf66d76ad,0x9176cc88,0x254c02f5,
+    0xfcd7e54f,0xd7cb2ac5,0x80443526,0x8fa362b5,0x495ab1de,0x671bba25,
+    0x980eea45,0xe1c0fe5d,0x2752fc3,0x12f04c81,0xa397468d,0xc6f9d36b,
+    0xe75f8f03,0x959c9215,0xeb7a6dbf,0xda595295,0x2d83bed4,0xd3217458,
+    0x2969e049,0x44c8c98e,0x6a89c275,0x78798ef4,0x6b3e5899,0xdd71b927,
+    0xb64fe1be,0x17ad88f0,0x66ac20c9,0xb43ace7d,0x184adf63,0x82311ae5,
+    0x60335197,0x457f5362,0xe07764b1,0x84ae6bbb,0x1ca081fe,0x942b08f9,
+    0x58684870,0x19fd458f,0x876cde94,0xb7f87b52,0x23d373ab,0xe2024b72,
+    0x578f1fe3,0x2aab5566,0x728ebb2,0x3c2b52f,0x9a7bc586,0xa50837d3,
+    0xf2872830,0xb2a5bf23,0xba6a0302,0x5c8216ed,0x2b1ccf8a,0x92b479a7,
+    0xf0f207f3,0xa1e2694e,0xcdf4da65,0xd5be0506,0x1f6234d1,0x8afea6c4,
+    0x9d532e34,0xa055f3a2,0x32e18a05,0x75ebf6a4,0x39ec830b,0xaaef6040,
+    0x69f715e,0x51106ebd,0xf98a213e,0x3d06dd96,0xae053edd,0x46bde64d,
+    0xb58d5491,0x55dc471,0x6fd40604,0xff155060,0x24fb9819,0x97e9bdd6,
+    0xcc434089,0x779ed967,0xbd42e8b0,0x888b8907,0x385b19e7,0xdbeec879,
+    0x470a7ca1,0xe90f427c,0xc91e84f8,0x0,0x83868009,0x48ed2b32,
+    0xac70111e,0x4e725a6c,0xfbff0efd,0x5638850f,0x1ed5ae3d,0x27392d36,
+    0x64d90f0a,0x21a65c68,0xd1545b9b,0x3a2e3624,0xb1670a0c,0xfe75793,
+    0xd296eeb4,0x9e919b1b,0x4fc5c080,0xa220dc61,0x694b775a,0x161a121c,
+    0xaba93e2,0xe52aa0c0,0x43e0223c,0x1d171b12,0xb0d090e,0xadc78bf2,
+    0xb9a8b62d,0xc8a91e14,0x8519f157,0x4c0775af,0xbbdd99ee,0xfd607fa3,
+    0x9f2601f7,0xbcf5725c,0xc53b6644,0x347efb5b,0x7629438b,0xdcc623cb,
+    0x68fcedb6,0x63f1e4b8,0xcadc31d7,0x10856342,0x40229713,0x2011c684,
+    0x7d244a85,0xf83dbbd2,0x1132f9ae,0x6da129c7,0x4b2f9e1d,0xf330b2dc,
+    0xec52860d,0xd0e3c177,0x6c16b32b,0x99b970a9,0xfa489411,0x2264e947,
+    0xc48cfca8,0x1a3ff0a0,0xd82c7d56,0xef903322,0xc74e4987,0xc1d138d9,
+    0xfea2ca8c,0x360bd498,0xcf81f5a6,0x28de7aa5,0x268eb7da,0xa4bfad3f,
+    0xe49d3a2c,0xd927850,0x9bcc5f6a,0x62467e54,0xc2138df6,0xe8b8d890,
+    0x5ef7392e,0xf5afc382,0xbe805d9f,0x7c93d069,0xa92dd56f,0xb31225cf,
+    0x3b99acc8,0xa77d1810,0x6e639ce8,0x7bbb3bdb,0x97826cd,0xf418596e,
+    0x1b79aec,0xa89a4f83,0x656e95e6,0x7ee6ffaa,0x8cfbc21,0xe6e815ef,
+    0xd99be7ba,0xce366f4a,0xd4099fea,0xd67cb029,0xafb2a431,0x31233f2a,
+    0x3094a5c6,0xc066a235,0x37bc4e74,0xa6ca82fc,0xb0d090e0,0x15d8a733,
+    0x4a9804f1,0xf7daec41,0xe50cd7f,0x2ff69117,0x8dd64d76,0x4db0ef43,
+    0x544daacc,0xdf0496e4,0xe3b5d19e,0x1b886a4c,0xb81f2cc1,0x7f516546,
+    0x4ea5e9d,0x5d358c01,0x737487fa,0x2e410bfb,0x5a1d67b3,0x52d2db92,
+    0x335610e9,0x1347d66d,0x8c61d79a,0x7a0ca137,0x8e14f859,0x893c13eb,
+    0xee27a9ce,0x35c961b7,0xede51ce1,0x3cb1477a,0x59dfd29c,0x3f73f255,
+    0x79ce1418,0xbf37c773,0xeacdf753,0x5baafd5f,0x146f3ddf,0x86db4478,
+    0x81f3afca,0x3ec468b9,0x2c342438,0x5f40a3c2,0x72c31d16,0xc25e2bc,
+    0x8b493c28,0x41950dff,0x7101a839,0xdeb30c08,0x9ce4b4d8,0x90c15664,
+    0x6184cb7b,0x70b632d5,0x745c6c48,0x4257b8d0];
+
+
+pub struct AES {
+	nk: usize,
+	nr: usize,
+	mode: usize,
+	fkey: [u32;60],
+	rkey: [u32;60],
+	pub f: [u8;16]
+}
+
+impl AES {
+
+	fn rotl8(x: u32) -> u32 {
+		return ((x)<<8)|((x)>>24);
+	}
+
+	fn rotl16(x: u32) -> u32 {
+		return ((x)<<16)|((x)>>16);
+	}
+
+	fn rotl24(x: u32) -> u32 {
+		return ((x)<<24)|((x)>>8);
+	}
+
+	fn pack(b: [u8;4]) -> u32 { /* pack bytes into a 32-bit Word */
+        return ((((b[3])&0xff) as u32)<<24)|((((b[2])&0xff) as u32)<<16)|((((b[1])&0xff) as u32)<<8)|(((b[0])&0xff) as u32);
+	}
+  
+	fn unpack(a: u32) -> [u8;4] { /* unpack bytes from a word */
+        let b:[u8;4]=[(a&0xff) as u8,((a>>8)&0xff) as u8,((a>>16)&0xff) as u8,((a>>24)&0xff) as u8];
+		return b;
+	}
+
+	fn bmul(x: u8,y: u8) -> u8 { /* x.y= AntiLog(Log(x) + Log(y)) */
+        let ix=(x as usize)&0xff;
+        let iy=(y as usize)&0xff;
+        let lx=(LTAB[ix] as usize)&0xff;
+        let ly=(LTAB[iy] as usize)&0xff;
+    
+        if x != 0 && y != 0 {
+			return PTAB[(lx+ly)%255];
+		} else {return 0}
+	}	
+
+	fn subbyte(a: u32) -> u32 {
+        let mut b=AES::unpack(a);
+        b[0]=FBSUB[b[0] as usize];
+        b[1]=FBSUB[b[1] as usize];
+        b[2]=FBSUB[b[2] as usize];
+        b[3]=FBSUB[b[3] as usize];
+        return AES::pack(b);
+	}   
+
+	fn product(x: u32,y: u32) -> u8 { /* dot product of two 4-byte arrays */
+        let xb=AES::unpack(x);
+        let yb=AES::unpack(y);
+    
+        return AES::bmul(xb[0],yb[0])^AES::bmul(xb[1],yb[1])^AES::bmul(xb[2],yb[2])^AES::bmul(xb[3],yb[3]);
+	}
+
+	fn invmixcol(x: u32) -> u32 { /* matrix Multiplication */
+        let mut b:[u8;4]=[0;4];
+        let mut m=AES::pack(INCO);
+        b[3]=AES::product(m,x);
+        m=AES::rotl24(m);
+        b[2]=AES::product(m,x);
+        m=AES::rotl24(m);
+        b[1]=AES::product(m,x);
+        m=AES::rotl24(m);
+        b[0]=AES::product(m,x);
+        let y=AES::pack(b);
+        return y;
+	}
+
+	fn increment(f: &mut [u8;16]) {
+		for i in 0..16 {
+			f[i]+=1;
+			if f[i]!=0 {break}
+		}
+	}
+
+	pub fn new() -> AES {
+		AES {
+			nk:0,
+			nr:0,
+			mode:0,
+			fkey:[0;60],
+			rkey:[0;60],
+			f:[0;16]
+
+		}
+	}
+
+/* reset cipher */
+	pub fn reset(&mut self,m: usize,iv: Option<[u8;16]>) { /* reset mode, or reset iv */
+		self.mode=m;
+        for i in 0..16 {self.f[i]=0}
+        if self.mode != ECB
+        {
+        	if let Some(x) = iv {
+        		for i in 0..16 {self.f[i]=x[i]}
+        	}
+		}
+	}	
+
+	pub fn init(&mut self,m: usize,nkey: usize,key: &[u8],iv: Option<[u8;16]>) -> bool {   
+/* Key Scheduler. Create expanded encryption key */
+		let mut cipherkey:[u32;8]=[0;8];
+        let mut b:[u8;4]=[0;4];
+        let nk=nkey/4;
+		if nk!=4 && nk!=6 && nk!=8 {return false}
+		let nr=6+nk;
+		self.nk=nk;
+		self.nr=nr;
+        self.reset(m,iv);
+        let n=4*(nr+1);
+        
+        let mut j=0;
+        for  i in 0..nk {
+            for k in 0..4 {b[k]=key[j+k]}
+            cipherkey[i]=AES::pack(b);
+            j+=4;
+        }
+
+        for i in 0..nk {self.fkey[i]=cipherkey[i]}
+        j=nk;
+		let mut k=0;    
+        while j<n  {      	
+            self.fkey[j]=self.fkey[j-nk]^AES::subbyte(AES::rotl24(self.fkey[j-1]))^(RCO[k] as u32);
+            for i in 1..nk {
+            	if (i+j) >= n {break}       	
+                self.fkey[i+j]=self.fkey[i+j-nk]^self.fkey[i+j-1];             
+            }
+            j+=nk;
+            k+=1;
+        }
+     
+        /* now for the expanded decrypt key in reverse order */
+        
+        for j in 0..4 {self.rkey[j+n-4]=self.fkey[j]}
+        let mut i=4;
+        while i<n-4 {
+            let k=n-4-i;
+            for j in 0..4 {self.rkey[k+j]=AES::invmixcol(self.fkey[i+j])}
+            i+=4;
+        }
+        for j in n-4..n {self.rkey[j+4-n]=self.fkey[j]}
+		return true;
+	}
+
+	pub fn getreg(&mut self) -> [u8;16] {
+        let mut ir:[u8;16]=[0;16];
+        for i in 0..16 {ir[i]=self.f[i]}
+        return ir;
+	}
+
+    /* Encrypt a single block */
+	pub fn ecb_encrypt(&mut self,buff: &mut [u8;16]) {
+        let mut b:[u8;4]=[0;4]; 
+        let mut p:[u32;4]=[0;4]; 
+        let mut q:[u32;4]=[0;4]; 
+    
+        let mut j=0;
+        for i in 0..4 {
+            for k in 0..4 {b[k]=buff[j+k]}
+            p[i]=AES::pack(b);
+            p[i]^=self.fkey[i];
+            j+=4;
+        }
+    
+        let mut k=4;
+    
+    /* State alternates between p and q */
+        for _ in 1..self.nr {
+            q[0]=self.fkey[k]^FTABLE[(p[0]&0xff) as usize]^AES::rotl8(FTABLE[((p[1]>>8)&0xff) as usize])^AES::rotl16(FTABLE[((p[2]>>16)&0xff) as usize])^AES::rotl24(FTABLE[((p[3]>>24)&0xff) as usize]);
+            
+            q[1]=self.fkey[k+1]^FTABLE[(p[1]&0xff) as usize]^AES::rotl8(FTABLE[((p[2]>>8)&0xff) as usize])^AES::rotl16(FTABLE[((p[3]>>16)&0xff) as usize])^AES::rotl24(FTABLE[((p[0]>>24)&0xff) as usize]);
+            
+            q[2]=self.fkey[k+2]^FTABLE[(p[2]&0xff) as usize]^AES::rotl8(FTABLE[((p[3]>>8)&0xff) as usize])^AES::rotl16(FTABLE[((p[0]>>16)&0xff) as usize])^AES::rotl24(FTABLE[((p[1]>>24)&0xff) as usize]);
+            
+            q[3]=self.fkey[k+3]^FTABLE[(p[3]&0xff) as usize]^AES::rotl8(FTABLE[((p[0]>>8)&0xff) as usize])^AES::rotl16(FTABLE[((p[1]>>16)&0xff) as usize])^AES::rotl24(FTABLE[((p[2]>>24)&0xff) as usize]);
+            
+            k+=4;
+            for j in 0..4 {
+				let t=p[j]; p[j]=q[j]; q[j]=t;
+            }
+        }
+    
+    /* Last Round */
+    
+        q[0]=self.fkey[k]^(FBSUB[(p[0]&0xff) as usize] as u32)^AES::rotl8((FBSUB[((p[1]>>8)&0xff) as usize]) as u32)^AES::rotl16((FBSUB[((p[2]>>16)&0xff) as usize]) as u32)^AES::rotl24((FBSUB[((p[3]>>24)&0xff) as usize]) as u32);
+    
+        q[1]=self.fkey[k+1]^(FBSUB[(p[1]&0xff) as usize] as u32)^AES::rotl8((FBSUB[((p[2]>>8)&0xff) as usize]) as u32)^AES::rotl16((FBSUB[((p[3]>>16)&0xff) as usize]) as u32)^AES::rotl24((FBSUB[((p[0]>>24)&0xff) as usize]) as u32);
+    
+        q[2]=self.fkey[k+2]^(FBSUB[(p[2]&0xff) as usize] as u32)^AES::rotl8((FBSUB[((p[3]>>8)&0xff) as usize]) as u32)^AES::rotl16((FBSUB[((p[0]>>16)&0xff) as usize]) as u32)^AES::rotl24((FBSUB[((p[1]>>24)&0xff) as usize]) as u32);
+    
+        q[3]=self.fkey[k+3]^(FBSUB[(p[3]&0xff) as usize] as u32)^AES::rotl8((FBSUB[((p[0]>>8)&0xff) as usize]) as u32)^AES::rotl16((FBSUB[((p[1]>>16)&0xff) as usize]) as u32)^AES::rotl24((FBSUB[((p[2]>>24)&0xff) as usize]) as u32);
+    
+        j=0;
+        for i in 0..4 {
+            b=AES::unpack(q[i]);
+            for k in 0..4 {buff[j+k]=b[k]}
+            j+=4;
+        }
+	}
+
+    /* Decrypt a single block */
+	pub fn ecb_decrypt(&mut self,buff: &mut [u8;16]) {
+        let mut b:[u8;4]=[0;4]; 
+        let mut p:[u32;4]=[0;4]; 
+        let mut q:[u32;4]=[0;4]; 
+    
+        let mut j=0;
+        for i in 0..4 {
+            for k in 0..4 {b[k]=buff[j+k]}
+            p[i]=AES::pack(b);
+            p[i]^=self.rkey[i];
+            j+=4;
+        }
+    
+         let mut k=4;
+    
+    /* State alternates between p and q */
+        for _ in 1..self.nr {
+            
+            q[0]=self.rkey[k]^RTABLE[(p[0]&0xff) as usize]^AES::rotl8(RTABLE[((p[3]>>8)&0xff) as usize])^AES::rotl16(RTABLE[((p[2]>>16)&0xff) as usize])^AES::rotl24(RTABLE[((p[1]>>24)&0xff) as usize]);
+            
+            q[1]=self.rkey[k+1]^RTABLE[(p[1]&0xff) as usize]^AES::rotl8(RTABLE[((p[0]>>8)&0xff) as usize])^AES::rotl16(RTABLE[((p[3]>>16)&0xff) as usize])^AES::rotl24(RTABLE[((p[2]>>24)&0xff) as usize]);
+            
+        
+            q[2]=self.rkey[k+2]^RTABLE[(p[2]&0xff) as usize]^AES::rotl8(RTABLE[((p[1]>>8)&0xff) as usize])^AES::rotl16(RTABLE[((p[0]>>16)&0xff) as usize])^AES::rotl24(RTABLE[((p[3]>>24)&0xff) as usize]);
+       
+            q[3]=self.rkey[k+3]^RTABLE[(p[3]&0xff) as usize]^AES::rotl8(RTABLE[((p[2]>>8)&0xff) as usize])^AES::rotl16(RTABLE[((p[1]>>16)&0xff) as usize])^AES::rotl24(RTABLE[((p[0]>>24)&0xff) as usize]);
+            
+    
+            k+=4;
+            for j in 0..4 {
+				let t=p[j]; p[j]=q[j]; q[j]=t;
+            }
+        }
+    
+    /* Last Round */
+        
+        q[0]=self.rkey[k]^(RBSUB[(p[0]&0xff) as usize] as u32)^AES::rotl8((RBSUB[((p[3]>>8)&0xff) as usize]) as u32)^AES::rotl16((RBSUB[((p[2]>>16)&0xff) as usize]) as u32)^AES::rotl24((RBSUB[((p[1]>>24)&0xff) as usize]) as u32);
+        
+        q[1]=self.rkey[k+1]^(RBSUB[(p[1]&0xff) as usize] as u32)^AES::rotl8((RBSUB[((p[0]>>8)&0xff) as usize]) as u32)^AES::rotl16((RBSUB[((p[3]>>16)&0xff) as usize]) as u32)^AES::rotl24((RBSUB[((p[2]>>24)&0xff) as usize]) as u32);
+        
+        
+        q[2]=self.rkey[k+2]^(RBSUB[(p[2]&0xff) as usize] as u32)^AES::rotl8((RBSUB[((p[1]>>8)&0xff) as usize]) as u32)^AES::rotl16((RBSUB[((p[0]>>16)&0xff) as usize]) as u32)^AES::rotl24((RBSUB[((p[3]>>24)&0xff) as usize]) as u32);
+
+        q[3]=self.rkey[k+3]^(RBSUB[((p[3])&0xff) as usize] as u32)^AES::rotl8((RBSUB[((p[2]>>8)&0xff) as usize]) as u32)^AES::rotl16((RBSUB[((p[1]>>16)&0xff) as usize]) as u32)^AES::rotl24((RBSUB[((p[0]>>24)&0xff) as usize]) as u32);
+    
+        j=0;
+        for i in 0..4 {
+            b=AES::unpack(q[i]);
+            for k in 0..4 {buff[j+k]=b[k]}
+            j+=4;
+        }
+	}
+
+/* Encrypt using selected mode of operation */
+	pub fn encrypt(&mut self,buff: &mut [u8;16]) -> u32 {
+		let mut st:[u8;16]=[0;16]; 
+    
+    // Supported Modes of Operation
+    
+        let mut fell_off: u32=0;
+
+        match self.mode {
+        	ECB => {
+            	self.ecb_encrypt(buff);
+            	return 0;
+        	},
+        	CBC => {
+            	for j in 0..16 {buff[j]^=self.f[j]}
+            	self.ecb_encrypt(buff);
+            	for j in 0..16 {self.f[j]=buff[j]}
+            	return 0;
+        	},
+    
+        	CFB1 | CFB2 | CFB4 => {
+            	let bytes=self.mode-CFB1+1;
+            	for j in 0..bytes {fell_off=(fell_off<<8)|(self.f[j] as u32)}
+            	for j in 0..16 {st[j]=self.f[j]}
+            	for j in bytes..16 {self.f[j-bytes]=self.f[j]}
+            	self.ecb_encrypt(&mut st);
+            	for j in 0..bytes {
+					buff[j]^=st[j];
+				self.f[16-bytes+j]=buff[j];
+            	}
+            	return fell_off;
+        	},
+    
+        	OFB1 | OFB2 | OFB4 | OFB8 | OFB16 => {
+           		let bytes=self.mode-OFB1+1;
+             	for j in 0..16 {st[j]=self.f[j]}
+            	self.ecb_encrypt(&mut st);
+           		for j in 0..bytes {buff[j]^=st[j]}       
+              	for j in 0..16 {self.f[j]=st[j]}          		     	            	
+
+            	//self.ecb_encrypt(&mut (self.f));
+            	//for j in 0..bytes {buff[j]^=self.f[j]}
+            	return 0;
+        	},
+    
+			CTR1 | CTR2 | CTR4 | CTR8 | CTR16 => {
+	    		let bytes=self.mode-CTR1+1;
+	    		for j in 0..16 {st[j]=self.f[j]}
+	    		self.ecb_encrypt(&mut st);
+	    		for j in 0..bytes {buff[j]^=st[j]}
+	    		AES::increment(&mut (self.f));
+	    		return 0;
+	    	},
+
+        	_ => {
+            	return 0;
+        	}
+        }
+    }
+
+    /* Decrypt using selected mode of operation */
+	pub fn decrypt(&mut self,buff: &mut [u8;16]) -> u32 {
+
+		let mut st:[u8;16]=[0;16]; 
+        
+        // Supported Modes of Operation
+        
+       	let mut fell_off: u32=0;
+
+        match self.mode {
+        	ECB => {
+            	self.ecb_decrypt(buff);
+            	return 0;
+            },
+        	CBC => {
+            	for j in 0..16 {
+					st[j]=self.f[j];
+					self.f[j]=buff[j];
+            	}
+            	self.ecb_decrypt(buff);
+            	for j in 0..16 {
+					buff[j]^=st[j];
+					st[j]=0;
+            	}
+            	return 0;
+           	},
+        	CFB1 | CFB2 | CFB4 => {
+            	let bytes=self.mode-CFB1+1;
+            	for j in 0..bytes {fell_off=(fell_off<<8)|(self.f[j] as u32)}
+            	for j in 0..16 {st[j]=self.f[j]}
+            	for j in bytes..16 {self.f[j-bytes]=self.f[j]}
+            	self.ecb_encrypt(&mut st);
+            	for j in 0..bytes {
+					self.f[16-bytes+j]=buff[j];
+					buff[j]^=st[j];
+            	}
+            	return fell_off;
+            },
+        	OFB1 | OFB2 | OFB4 | OFB8 | OFB16 => {
+           		let bytes=self.mode-OFB1+1;
+             	for j in 0..16 {st[j]=self.f[j]}
+            	self.ecb_encrypt(&mut st);
+           		for j in 0..bytes {buff[j]^=st[j]}       
+              	for j in 0..16 {self.f[j]=st[j]}          		
+            //	self.ecb_encrypt(A.f[:]);
+            //	for j in 0..bytes {buff[j]^=self.f[j]}
+            	return 0;
+            },
+
+			CTR1 | CTR2 | CTR4 | CTR8 | CTR16 => {
+	    		let bytes=self.mode-CTR1+1;
+	    		for j in 0..16 {st[j]=self.f[j]}
+	    		self.ecb_encrypt(&mut st);
+	    		for j in 0..bytes {buff[j]^=st[j]}
+	    		AES::increment(&mut (self.f));
+	    		return 0;
+	    	},
+
+        	_ => {
+            	return 0;
+        	}
+        }
+    } 
+
+/* Clean up and delete left-overs */
+	pub fn end(&mut self) { // clean up
+    	for i in 0..4*(self.nr+1) {self.fkey[i]=0; self.rkey[i]=0}
+    	for i in 0..16 {self.f[i]=0}
+	}
+}
+
+/*
+fn main()
+{
+	let mut key:[u8;32]=[0;32];
+	let mut block:[u8;16]=[0;16];
+	let mut iv: [u8;16] = [0;16];
+
+	for i in 0..32 {key[i]=0}
+	key[0]=1;
+	for i in 0..16 {iv[i]=i as u8}
+	for i in 0..16 {block[i]=i as u8}
+
+	let mut aes=AES::new();
+	aes.init(CTR16,32,&key,Some(iv));
+
+	println!("Plain= ");
+	for i in 0..16 {print!("{:02x} ",block[i])}
+	println!("");	
+
+	aes.encrypt(&mut block);
+
+	println!("Encrypt= ");
+	for i in 0..16 {print!("{:02x} ",block[i])}
+	println!("");	
+
+	aes.reset(CTR16,Some(iv));
+	aes.decrypt(&mut block);
+
+	println!("Decrypt= ");
+	for i in 0..16 {print!("{:02x} ",block[i])}
+	println!("");	
+
+	aes.end();
+}
+*/
diff --git a/version3/rust/arch32.rs b/version3/rust/arch32.rs
new file mode 100644
index 0000000..bf39471
--- /dev/null
+++ b/version3/rust/arch32.rs
@@ -0,0 +1,22 @@
+/*
+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.
+*/
+
+pub type Chunk=i32;
+pub type DChunk=i64;
+pub const CHUNK:usize=32;
diff --git a/version3/rust/arch64.rs b/version3/rust/arch64.rs
new file mode 100644
index 0000000..79c7f2e
--- /dev/null
+++ b/version3/rust/arch64.rs
@@ -0,0 +1,22 @@
+/*
+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.
+*/
+
+pub type Chunk=i64;
+pub type DChunk=i128;
+pub const CHUNK:usize=64;
diff --git a/version3/rust/big.rs b/version3/rust/big.rs
new file mode 100644
index 0000000..eb03e29
--- /dev/null
+++ b/version3/rust/big.rs
@@ -0,0 +1,1078 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use arch;
+use arch::Chunk;
+
+//#[cfg(D32)]
+use arch::DChunk;
+
+use xxx::dbig::DBIG;
+use rand::RAND;
+
+pub const MODBYTES:usize = @NB@;
+pub const BASEBITS:usize = @BASE@;
+
+pub const NLEN: usize = (1+((8*MODBYTES-1)/BASEBITS));
+pub const DNLEN: usize = 2*NLEN;
+pub const BMASK: Chunk= ((1<<BASEBITS)-1);
+pub const HBITS: usize=(BASEBITS/2);
+pub const HMASK: Chunk= ((1<<HBITS)-1);
+pub const NEXCESS:isize = (1<<((arch::CHUNK)-BASEBITS-1));
+pub const BIGBITS:usize = (MODBYTES*8);
+
+
+#[derive(Copy)]
+pub struct BIG {
+    pub w: [Chunk; NLEN]
+}
+
+impl Clone for BIG {
+    fn clone(&self) -> BIG { *self }
+}
+/*
+#[derive(Copy, Clone)]
+pub struct BIG {
+    pub w: [Chunk; NLEN]
+}
+*/
+
+impl BIG {
+
+   pub fn new() -> BIG {
+        BIG {
+        	w: [0; NLEN]
+         }
+    }
+
+    pub fn new_int(x:isize) -> BIG {
+    	let mut s= BIG::new();
+    	s.w[0]=x as Chunk;
+    	return s;
+    }
+
+    pub fn new_ints(a:&[Chunk]) -> BIG {
+    	let mut s= BIG::new();
+    	for i in 0..NLEN {s.w[i]=a[i]}
+    	return s;
+    }
+
+    pub fn new_copy(y:&BIG) -> BIG {
+    	let mut s= BIG::new();   
+    	for i in 0..NLEN {s.w[i]=y.w[i]}
+    	return s;	
+    }
+
+    pub fn new_big(y:&BIG) -> BIG {
+        let mut s= BIG::new();   
+        for i in 0..NLEN {s.w[i]=y.w[i]}
+        return s;   
+    }
+
+    pub fn new_dcopy(y:&DBIG) -> BIG {
+    	let mut s= BIG::new();   
+    	for i in 0..NLEN {s.w[i]=y.w[i]}
+    	return s;	
+    } 
+
+	pub fn get(&self,i:usize) -> Chunk {
+		return self.w[i]; 
+	}
+
+	pub fn set(&mut self,i:usize,x:Chunk) {
+		self.w[i]=x;	
+	}
+
+	pub fn xortop(&mut self,x:Chunk) {
+		self.w[NLEN-1]^=x;
+	}
+
+	pub fn ortop(&mut self,x:Chunk) {
+		self.w[NLEN-1]|=x;
+	}
+
+/* test for zero */
+	pub fn iszilch(&self) -> bool {
+		for i in 0 ..NLEN {
+			if self.w[i]!=0 {return false}
+		}
+		return true; 
+	}
+
+/* set to zero */
+	pub fn zero(&mut self) {
+		for i in 0 ..NLEN {
+			self.w[i]=0
+		}
+	}
+
+/* Test for equal to one */
+	pub fn isunity(&self) -> bool {
+		for i in 0 ..NLEN {
+			if self.w[i]!=0 {return false}
+		}
+		if self.w[0]!=1 {return false}
+		return true;
+	}
+
+/* set to one */
+	pub fn one(&mut self) {
+		self.w[0]=1;
+		for i in 1 ..NLEN {
+			self.w[i]=0;
+		}
+	}
+
+/* Copy from another BIG */
+	pub fn copy(&mut self,x: &BIG) {
+		for i in 0 ..NLEN {
+			self.w[i]=x.w[i]
+		}
+	}
+
+    pub fn dcopy(&mut self,x: &DBIG)
+    {
+        for i in 0 ..NLEN {self.w[i] = x.w[i]}
+    }
+
+
+/* Get top and bottom half of =x*y+c+r */
+//#[cfg(D32)]
+    pub fn muladd(a: Chunk,b: Chunk,c: Chunk,r: Chunk) -> (Chunk,Chunk) {
+        let prod:DChunk = (a as DChunk)*(b as DChunk)+(c as DChunk)+(r as DChunk);
+        let bot=(prod&(BMASK as DChunk)) as Chunk;
+        let top=(prod>>BASEBITS) as Chunk;   
+        return (top,bot);     
+    }
+
+/*
+#[cfg(D64)]
+    pub fn muladd(a: Chunk,b: Chunk,c: Chunk,r: Chunk) -> (Chunk,Chunk) {
+        let x0=a&HMASK;
+        let x1=a>>HBITS;
+        let y0=b&HMASK;
+        let y1=b>>HBITS;
+        let mut bot=x0*y0;
+        let mut top=x1*y1;
+        let mid=x0*y1+x1*y0;
+        let u0=mid&HMASK;
+        let u1=mid>>HBITS;
+        bot+= u0<<HBITS;
+        bot+=c; bot+=r;
+        top+=u1;
+        let carry=bot>>BASEBITS;
+        bot&=BMASK;
+        top+=carry;
+        return (top,bot);
+    }
+*/
+
+/* normalise BIG - force all digits < 2^BASEBITS */
+    pub fn norm(&mut self) -> Chunk
+    {
+        let mut carry=0 as Chunk;
+        for i in 0 ..NLEN-1 {
+            let d=self.w[i]+carry;
+            self.w[i]=d&BMASK;
+            carry=d>>BASEBITS;
+        }
+        self.w[NLEN-1]+=carry;
+        return (self.w[NLEN-1]>>((8*MODBYTES)%BASEBITS)) as Chunk;
+    }
+
+/* Conditional swap of two bigs depending on d using XOR - no branches */
+	pub fn cswap(&mut self,b: &mut BIG,d: isize) {
+		let mut c= d as Chunk;
+		c=!(c-1);
+		for i in 0 ..NLEN {
+			let t=c&(self.w[i]^b.w[i]);
+			self.w[i]^=t;
+			b.w[i]^=t;
+		}
+	}
+
+	pub fn cmove(&mut self,g:&BIG,d: isize) {
+		let b= -d as Chunk;
+		for i in 0 ..NLEN {
+			self.w[i]^=(self.w[i]^g.w[i])&b;
+		}
+	}
+
+
+/* Shift right by less than a word */
+	pub fn fshr(&mut self, k: usize) -> isize {
+		let n = k;
+		let w=self.w[0]&((1<<n)-1); /* shifted out part */
+		for i in 0 ..NLEN-1 {
+			self.w[i]=(self.w[i]>>k)|((self.w[i+1]<<(BASEBITS-n))&BMASK);
+		}
+		self.w[NLEN-1]=self.w[NLEN-1]>>k;
+		return w as isize;
+	}
+
+ /* general shift right */
+	pub fn shr(&mut self,k:usize) {
+		let n=k%BASEBITS;
+		let m=k/BASEBITS;
+		for i in 0 ..NLEN-m-1 {
+			self.w[i]=(self.w[m+i]>>n)|((self.w[m+i+1]<<(BASEBITS-n))&BMASK)
+		}
+		self.w[NLEN-m-1]=self.w[NLEN-1]>>n;
+		for i in NLEN-m ..NLEN 
+			{self.w[i]=0}
+	}	
+
+/* Shift right by less than a word */
+	pub fn fshl(&mut self,k:usize) -> isize {
+		let n=k;
+		self.w[NLEN-1]=((self.w[NLEN-1]<<n))|(self.w[NLEN-2]>>(BASEBITS-n));
+		for i in (1 ..NLEN-1).rev() {
+			self.w[i]=((self.w[i]<<k)&BMASK)|(self.w[i-1]>>(BASEBITS-n));
+		}
+		self.w[0]=(self.w[0]<<n)&BMASK;
+		return (self.w[NLEN-1]>>((8*MODBYTES)%BASEBITS)) as isize /* return excess - only used in ff.c */
+	}
+
+/* general shift left */
+	pub fn shl(&mut self,k: usize) {
+		let n=k%BASEBITS;
+		let m=k/BASEBITS;
+
+		self.w[NLEN-1]=self.w[NLEN-1-m]<<n;
+		if NLEN>=m+2 {self.w[NLEN-1]|=self.w[NLEN-m-2]>>(BASEBITS-n)}
+		for i in (m+1 ..NLEN-1).rev() {
+			self.w[i]=((self.w[i-m]<<n)&BMASK)|(self.w[i-m-1]>>(BASEBITS-n));
+		}
+		self.w[m]=(self.w[0]<<n)&BMASK; 
+		for i in 0 ..m {self.w[i]=0}
+	}
+
+/* return number of bits */
+	pub fn nbits(&self) -> usize {
+		let mut k=NLEN-1;
+		let mut s=BIG::new_copy(&self);        
+		s.norm();
+		while (k as isize)>=0 && s.w[k]==0 {k=k.wrapping_sub(1)}
+		if (k as isize) <0 {return 0}
+		let mut bts=BASEBITS*k;
+		let mut c=s.w[k];
+		while c!=0 {c/=2; bts+=1;}
+		return bts;
+	}
+
+/* Convert to Hex String */
+	pub fn tostring(&mut self) -> String {
+		let mut s = String::new();
+		let mut len=self.nbits();
+
+		if len%4==0 {
+			len/=4;
+		} else {
+			len/=4;
+			len+=1;
+		}
+		let mb=(MODBYTES*2) as usize;
+		if len<mb {len=mb}
+
+		for i in (0 ..len).rev() {
+			let mut b=BIG::new_copy(&self);
+			b.shr(i*4);
+			s=s + &format!("{:X}", b.w[0]&15);
+		}
+		return s;
+	}	
+
+    pub fn add(&mut self,r:&BIG) {
+		for i in 0 ..NLEN {
+			self.w[i]+=r.w[i] 
+		}
+	}
+
+    pub fn or(&mut self,r:&BIG) {
+        for i in 0 ..NLEN {
+            self.w[i]|=r.w[i] 
+        }
+    }
+
+    pub fn dbl(&mut self) {
+        for i in 0 ..NLEN {
+            self.w[i]+=self.w[i]
+        }        
+    }
+
+/* return this+x */
+	pub fn plus(&self,x: &BIG) -> BIG {
+		let mut s=BIG::new();
+		for i in 0 ..NLEN {
+			s.w[i]=self.w[i]+x.w[i];
+		}
+		return s;
+	}
+
+    pub fn inc(&mut self,x:isize) {
+    	self.norm();
+    	self.w[0]+=x as Chunk; 
+    }
+
+//    pub fn incl(&mut self,x:Chunk) {
+//        self.norm();
+//        self.w[0]+=x; 
+//    }
+
+/* return self-x */
+	pub fn minus(&self,x:& BIG) -> BIG {
+		let mut d=BIG::new();
+		for i in 0 ..NLEN {
+			d.w[i]=self.w[i]-x.w[i];
+		}
+		return d;
+	}
+
+/* self-=x */
+	pub fn sub(&mut self,x:&BIG) {
+		for i in 0 ..NLEN {
+			self.w[i]-=x.w[i]; 
+		}
+	} 
+
+/* reverse subtract this=x-this */ 
+	pub fn rsub(&mut self,x:&BIG) {
+		for i in 0 ..NLEN {
+			self.w[i]=x.w[i]-self.w[i] 
+		}
+	} 
+
+/* self-=x, where x is int */
+	pub fn dec(&mut self,x:isize) {
+		self.norm();
+		self.w[0]-= x as Chunk;
+	} 
+
+/* self*=x, where x is small int<NEXCESS */
+	pub fn imul(&mut self,c: isize) {
+		for i in 0 ..NLEN { 
+			self.w[i]*=c as Chunk;
+		}
+	}
+
+/* convert this BIG to byte array */
+	pub fn tobytearray(&mut self,b: &mut [u8],n:usize) {
+		//self.norm();
+		let mut c=BIG::new_copy(self);
+		c.norm();
+
+		for i in (0 ..(MODBYTES as usize)).rev() {
+			b[i+n]=(c.w[0]&0xff) as u8;
+			c.fshr(8);
+		}
+	}
+
+/* convert from byte array to BIG */
+	pub fn frombytearray(b: &[u8],n:usize) -> BIG {
+		let mut m=BIG::new();
+		for i in 0 ..(MODBYTES as usize) {
+			m.fshl(8); m.w[0]+=(b[i+n]&0xff) as Chunk;
+		}
+		return m; 
+	}
+
+	pub fn tobytes(&mut self,b: &mut [u8]) {
+		self.tobytearray(b,0)
+	}
+
+	pub fn frombytes(b: &[u8]) -> BIG {
+		return BIG::frombytearray(b,0)
+	}
+
+
+/* self*=x, where x is >NEXCESS */
+    pub fn pmul(&mut self,c: isize) -> Chunk {
+        let mut carry=0 as Chunk;
+        //self.norm();
+        for i in 0 ..NLEN {
+            let ak=self.w[i];
+            let tuple=BIG::muladd(ak,c as Chunk,carry,0 as Chunk);
+            carry=tuple.0; self.w[i]=tuple.1;
+        }
+        return carry;
+    }  
+
+/* self*=c and catch overflow in DBIG */
+    pub fn pxmul(&mut self,c: isize) -> DBIG
+    {
+        let mut m=DBIG::new();
+        let mut carry=0 as Chunk;
+        for j in 0 ..NLEN {
+            let tuple=BIG::muladd(self.w[j],c as Chunk,carry,m.w[j]);
+            carry=tuple.0; m.w[j]=tuple.1; 
+        }
+        m.w[NLEN]=carry;
+        return m;
+    }
+
+/* divide by 3 */
+    pub fn div3(&mut self) -> Chunk
+    {
+        let mut carry=0 as Chunk;
+        self.norm();
+        let base=1<<BASEBITS;
+        for i in (0 ..NLEN).rev() {
+            let ak=carry*base+self.w[i];
+            self.w[i]=ak/3;
+            carry=ak%3;
+        }
+        return carry;
+    }
+
+/* return a*b where result fits in a BIG */
+    pub fn smul(a: &BIG,b: &BIG) -> BIG {
+        let mut c=BIG::new();
+        for i in 0 ..NLEN {
+            let mut carry=0 as Chunk; 
+            for j in 0 ..NLEN {
+                if i+j<NLEN {
+                    let tuple=BIG::muladd(a.w[i],b.w[j],carry,c.w[i+j]);
+                    carry=tuple.0; c.w[i+j]=tuple.1;
+                }
+            }
+        }
+        return c;
+    }
+
+/* Compare a and b, return 0 if a==b, -1 if a<b, +1 if a>b. Inputs must be normalised */
+    pub fn comp(a: &BIG,b: &BIG) -> isize {
+        for i in (0 ..NLEN).rev() {
+            if a.w[i]==b.w[i] {continue}
+            if a.w[i]>b.w[i] {return 1}
+            else  {return -1}
+        }
+        return 0;
+    }
+
+/* set x = x mod 2^m */
+    pub fn mod2m(&mut self,m: usize)
+    {
+        let wd=m/BASEBITS;
+        let bt=m%BASEBITS;
+        let msk=(1<<bt)-1;
+        self.w[wd]&=msk;
+        for i in wd+1 ..NLEN {self.w[i]=0}
+    }
+
+/* Arazi and Qi inversion mod 256 */
+    pub fn invmod256(a: isize) -> isize {
+        let mut t1:isize=0;
+        let mut c=(a>>1)&1;
+        t1+=c;
+        t1&=1;
+        t1=2-t1;
+        t1<<=1;
+        let mut u=t1+1;
+    
+    // i=2
+        let mut b=a&3;
+        t1=u*b; t1>>=2;
+        c=(a>>2)&3;
+        let mut t2=(u*c)&3;
+        t1+=t2;
+        t1*=u; t1&=3;
+        t1=4-t1;
+        t1<<=2;
+        u+=t1;
+    
+    // i=4
+        b=a&15;
+        t1=u*b; t1>>=4;
+        c=(a>>4)&15;
+        t2=(u*c)&15;
+        t1+=t2;
+        t1*=u; t1&=15;
+        t1=16-t1;
+        t1<<=4;
+        u+=t1;
+    
+        return u;
+    }
+
+/* return parity */
+    pub fn parity(&self) -> isize {
+        return (self.w[0]%2) as isize;
+    }
+
+/* return n-th bit */
+    pub fn bit(&self,n: usize) -> isize {
+        if (self.w[n/(BASEBITS as usize)]&(1<<(n%BASEBITS)))>0 {return 1;}
+        else {return 0;}
+    }
+
+/* return n last bits */
+    pub fn lastbits(&mut self,n: usize) -> isize
+    {
+        let msk =  ((1<<n)-1) as Chunk; 
+        self.norm();
+        return (self.w[0]&msk) as isize;
+    }
+
+/* a=1/a mod 2^256. This is very fast! */
+    pub fn invmod2m(&mut self) {
+        let mut u=BIG::new();
+        let mut b=BIG::new();
+        let mut c=BIG::new();
+    
+        u.inc(BIG::invmod256(self.lastbits(8)));
+    
+        let mut i=8;
+        while i<BIGBITS {
+            u.norm();
+            b.copy(self);
+            b.mod2m(i);
+            let mut t1=BIG::smul(&u,&b);
+            t1.shr(i);
+            c.copy(self);
+            c.shr(i);
+            c.mod2m(i);
+    
+            let mut t2=BIG::smul(&u,&c);
+            t2.mod2m(i);
+            t1.add(&t2); t1.norm();
+            b=BIG::smul(&t1,&u);
+            t1.copy(&b);
+            t1.mod2m(i);
+    
+            t2.one(); t2.shl(i); t1.rsub(&t2); t1.norm();
+            t1.shl(i);
+            u.add(&t1);
+            i<<=1;
+        }
+        u.mod2m(BIGBITS);
+        self.copy(&u);
+        self.norm();
+    }
+
+/* reduce self mod m */
+    pub fn rmod(&mut self,n: &BIG) {
+        let mut k=0;
+        let mut m=BIG::new_copy(n);
+	    let mut r=BIG::new();
+        self.norm();
+        if BIG::comp(self,&m)<0 {return}
+        loop {
+            m.fshl(1);
+            k += 1;
+            if BIG::comp(self,&m)<0 {break}
+        }
+    
+        while k>0 {
+            m.fshr(1);
+
+		r.copy(self);
+		r.sub(&m);
+		r.norm();
+		self.cmove(&r,(1-((r.w[NLEN-1]>>(arch::CHUNK-1))&1)) as isize);
+/*
+            if BIG::comp(self,&m)>=0 {
+				self.sub(&m);
+				self.norm();
+            } */
+            k -= 1;
+        }
+    }
+
+/* divide self by m */
+    pub fn div(&mut self,n: &BIG) {
+        let mut k=0;
+        self.norm();
+        let mut e=BIG::new_int(1);
+        let mut b=BIG::new_copy(self);
+        let mut m=BIG::new_copy(n);
+        let mut r=BIG::new();
+        self.zero();
+    
+        while BIG::comp(&b,&m)>=0 {
+            e.fshl(1);
+            m.fshl(1);
+            k += 1;
+        }
+    
+        while k>0 {
+            m.fshr(1);
+            e.fshr(1);
+
+		r.copy(&b);
+		r.sub(&m);
+		r.norm();
+		let d=(1-((r.w[NLEN-1]>>(arch::CHUNK-1))&1)) as isize;
+		b.cmove(&r,d);
+		r.copy(self);
+		r.add(&e);
+		r.norm();
+		self.cmove(&r,d);
+/*
+            if BIG::comp(&b,&m)>=0 {
+				self.add(&e);
+				self.norm();
+				b.sub(&m);
+				b.norm();
+            } */
+            k -= 1;
+        }
+    }
+
+/* get 8*MODBYTES size random number */
+    pub fn random(rng: &mut RAND) -> BIG {
+        let mut m=BIG::new();
+        let mut j=0;
+        let mut r:u8=0;
+/* generate random BIG */ 
+        for _ in 0..8*(MODBYTES as usize)  {
+            if j==0 {
+                r=rng.getbyte()
+            } else {r>>=1}
+
+            let b= (r as Chunk)&1; 
+            m.shl(1); m.w[0]+=b;// m.inc(b)
+            j+=1; j&=7; 
+        }
+        return m;
+    }
+
+/* Create random BIG in portable way, one bit at a time */
+    pub fn randomnum(q: &BIG,rng: &mut RAND) -> BIG {
+        let mut d=DBIG::new();
+        let mut j=0;
+        let mut r:u8=0;
+        let t=BIG::new_copy(q);
+        for _ in 0..2*t.nbits() {
+            if j==0 {
+                r=rng.getbyte();
+            } else {r>>=1}
+
+            let b= (r as Chunk)&1;
+            d.shl(1); d.w[0]+=b; // m.inc(b);
+            j+=1; j&=7; 
+        }
+        let m=d.dmod(q);
+        return m;
+    }
+
+
+   /* Jacobi Symbol (this/p). Returns 0, 1 or -1 */
+    pub fn jacobi(&mut self,p: &BIG) -> isize {
+        let mut m:usize=0;
+        let mut t=BIG::new();
+        let mut x=BIG::new();
+        let mut n=BIG::new();
+        let zilch=BIG::new();
+        let one=BIG::new_int(1);
+        if p.parity()==0 || BIG::comp(self,&zilch)==0 || BIG::comp(p,&one)<=0 {return 0}
+        self.norm();
+
+        x.copy(self);
+        n.copy(p);
+        x.rmod(p);
+
+        while BIG::comp(&n,&one)>0 {
+            if BIG::comp(&x,&zilch)==0 {return 0}
+            let n8=n.lastbits(3) as usize;
+            let mut k=0;
+            while x.parity()==0 {
+				k += 1;
+				x.shr(1);
+            }
+            if k%2==1 {m+=(n8*n8-1)/8}
+            m+=(n8-1)*((x.lastbits(2) as usize)-1)/4;
+            t.copy(&n);
+            t.rmod(&x);
+            n.copy(&x);
+            x.copy(&t);
+            m%=2;
+    
+        }
+        if m==0 {return 1}
+        else {return -1}
+    }
+
+/* self=1/self mod p. Binary method */
+    pub fn invmodp(&mut self,p: &BIG) {
+        self.rmod(p);
+        let mut u=BIG::new_copy(self);
+        let mut v=BIG::new_copy(p);
+        let mut x1=BIG::new_int(1);
+        let mut x2=BIG::new();
+        let mut t=BIG::new();
+        let one=BIG::new_int(1);
+    
+        while (BIG::comp(&u,&one) != 0 ) && (BIG::comp(&v,&one) != 0 ) {
+            while u.parity()==0 {
+				u.fshr(1);
+				if x1.parity() != 0 {
+                    x1.add(p);
+                    x1.norm();
+				}
+				x1.fshr(1);
+            }
+            while v.parity()==0 {
+				v.fshr(1);
+				if x2.parity() != 0  {
+                    x2.add(p);
+                    x2.norm();
+				}
+				x2.fshr(1);
+            }
+            if BIG::comp(&u,&v)>=0 {
+				u.sub(&v);
+				u.norm();
+                if BIG::comp(&x1,&x2)>=0 {x1.sub(&x2)}
+				else
+				{
+                    t.copy(p);
+                    t.sub(&x2);
+                    x1.add(&t);
+				}
+				x1.norm();
+            }
+            else
+            {
+				v.sub(&u);
+				v.norm();
+                if BIG::comp(&x2,&x1)>=0 {x2.sub(&x1)}
+				else
+				{
+                    t.copy(p);
+                    t.sub(&x1);
+                    x2.add(&t);
+				}
+				x2.norm();
+            }
+        }
+        if BIG::comp(&u,&one)==0 {self.copy(&x1)}
+        else {self.copy(&x2)}
+    }
+/*
+    pub fn isok(&self) ->bool {
+        let mut ok=true;
+        for i in 0 ..NLEN {
+            if (self.w[i]>>BASEBITS)!=0 {ok=false;}
+        }
+        return ok;
+    }
+*/
+   /* return a*b as DBIG */
+//#[cfg(D32)]
+    pub fn mul(a: &BIG,b: &BIG) -> DBIG {
+        let mut c=DBIG::new();
+        let rm=BMASK as DChunk;
+        let rb=BASEBITS;
+     //if !a.isok() {println!("a not normalised in mul");}
+     //if !b.isok() {println!("b not normalised in mul");}
+
+        let mut d: [DChunk; DNLEN] = [0; DNLEN];
+        for i in 0 ..NLEN {
+            d[i]=(a.w[i] as DChunk)*(b.w[i] as DChunk);
+        }
+        let mut s=d[0];
+        let mut t=s; c.w[0]=(t&rm) as Chunk; 
+        let mut co=t>>rb;
+        for k in 1 ..NLEN {
+            s+=d[k]; t=co+s;
+            for i in 1+k/2..k+1
+                {t+=((a.w[i]-a.w[k-i]) as DChunk)*((b.w[k-i]-b.w[i]) as DChunk)}
+            c.w[k]=(t&rm) as Chunk; co=t>>rb;
+        }
+        for k in NLEN ..2*NLEN-1 {
+            s-=d[k-NLEN]; t=co+s;
+            let mut i=1+k/2;
+            while i<NLEN {
+                t+=((a.w[i]-a.w[k-i]) as DChunk)*((b.w[k-i]-b.w[i]) as DChunk);
+                i+=1;
+            }
+        
+            c.w[k]=(t&rm) as Chunk; co=t>>rb;
+        }
+        c.w[2*NLEN-1]=co as Chunk;
+        return c;
+    }
+
+/* return a^2 as DBIG */
+//#[cfg(D32)]  
+    pub fn sqr(a: &BIG) -> DBIG {
+        let mut c=DBIG::new();
+        let rm=BMASK as DChunk;
+        let rb=BASEBITS;
+ 
+        //if !a.isok() {println!("a not normalised in sqr");}
+
+        let mut t=(a.w[0] as DChunk)*(a.w[0] as DChunk); 
+        c.w[0]=(t&rm) as Chunk; let mut co=t>>rb;
+
+        let mut j=1;
+        while j<NLEN-1
+        {
+            t=(a.w[j] as DChunk)*(a.w[0] as DChunk); for  i in 1..(j+1)/2 {t+=(a.w[j-i] as DChunk)*(a.w[i] as DChunk);} t+=t;  t+=co; 
+            c.w[j]=(t&rm) as Chunk; co=t>>rb;
+            j+=1;
+            t=(a.w[j] as DChunk)*(a.w[0] as DChunk); for  i in 1..(j+1)/2 {t+=(a.w[j-i] as DChunk)*(a.w[i] as DChunk);} t+=t; t+=co; t+=(a.w[j/2] as DChunk)*(a.w[j/2] as DChunk); 
+            c.w[j]=(t&rm) as Chunk; co=t>>rb;
+            j+=1;
+        }
+
+        j=NLEN+(NLEN%2)-1;
+        while j<DNLEN-3
+        {
+            t=(a.w[NLEN-1] as DChunk)*(a.w[j+1-NLEN] as DChunk); for i in j+2-NLEN ..(j+1)/2 {t+=(a.w[j-i] as DChunk)*(a.w[i] as DChunk);} t+=t; t+=co; 
+            c.w[j]=(t&rm) as Chunk; co=t>>rb;
+            j+=1;
+            t=(a.w[NLEN-1] as DChunk)*(a.w[j+1-NLEN] as DChunk); for i in j+2-NLEN ..(j+1)/2 {t+=(a.w[j-i] as DChunk)*(a.w[i] as DChunk);} t+=t; t+=co; t+=(a.w[j/2] as DChunk)*(a.w[j/2] as DChunk); 
+            c.w[j]=(t&rm) as Chunk; co=t>>rb;
+            j+=1;
+        }
+
+        t=(a.w[NLEN-2] as DChunk)*(a.w[NLEN-1] as DChunk);
+        t+=t; t+=co;
+        c.w[DNLEN-3]=(t&rm) as Chunk; co=t>>rb;
+    
+        t=(a.w[NLEN-1] as DChunk)*(a.w[NLEN-1] as DChunk)+co; 
+        c.w[DNLEN-2]=(t&rm) as Chunk; co=t>>rb;
+        c.w[DNLEN-1]=co as Chunk;
+
+        return c;
+    }
+
+
+//#[cfg(D32)]
+    pub fn monty(md: &BIG,mc: Chunk,d: &mut DBIG) -> BIG {
+        let mut b=BIG::new();           
+        let rm=BMASK as DChunk;
+        let rb=BASEBITS;
+
+        let mut dd: [DChunk; NLEN] = [0; NLEN];
+        let mut v: [Chunk; NLEN] = [0; NLEN];
+            
+        b.zero();
+            
+        let mut t=d.w[0] as DChunk; v[0]=(((t&rm) as Chunk).wrapping_mul(mc))&BMASK; 
+        t+=(v[0] as DChunk)*(md.w[0] as DChunk); let mut c=(d.w[1] as DChunk)+(t>>rb); let mut s:DChunk=0;
+        for k in 1 ..NLEN {
+            t=c+s+(v[0] as DChunk)*(md.w[k] as DChunk);
+            let mut i=1+k/2;
+            while i<k {
+                t+=((v[k-i]-v[i]) as DChunk)*((md.w[i]-md.w[k-i]) as DChunk);
+                i+=1;
+            }
+            v[k]=(((t&rm) as Chunk).wrapping_mul(mc))&BMASK; 
+            t+=(v[k] as DChunk)*(md.w[0] as DChunk); c=(d.w[k+1] as DChunk)+(t>>rb);
+            dd[k]=(v[k] as DChunk)*(md.w[k] as DChunk); s+=dd[k];
+        }
+            
+        for k in NLEN ..2*NLEN-1
+        {
+            t=c+s;
+            let mut i=1+k/2;
+            while i<NLEN {
+                t+=((v[k-i]-v[i]) as DChunk)*((md.w[i]-md.w[k-i]) as DChunk);
+                i+=1;
+            }
+            b.w[k-NLEN]=(t&rm) as Chunk; c=(d.w[k+1] as DChunk)+(t>>rb); s-=dd[k+1-NLEN];
+        }
+        b.w[NLEN-1]=(c&rm) as Chunk;  
+   //     b.norm();
+        return b;
+    }
+    
+
+
+/* return a*b as DBIG 
+#[cfg(D64)]
+    pub fn mul(a: &BIG,b: &BIG) -> DBIG {
+        let mut c=DBIG::new();
+        //let mut carry = 0 as Chunk;
+        let mut carry:Chunk;
+        for i in 0 ..NLEN {
+            carry=0;
+            for j in 0 ..NLEN {
+                let tuple=BIG::muladd(a.w[i],b.w[j],carry,c.w[i+j]);
+                carry=tuple.0; c.w[i+j]=tuple.1;
+            }
+            c.w[NLEN+i]=carry;
+        }
+        return c;
+    } 
+
+// return a^2 as DBIG 
+#[cfg(D64)]
+    pub fn sqr(a: &BIG) -> DBIG {
+        let mut c=DBIG::new();
+        //let mut carry = 0 as Chunk;
+        let mut carry:Chunk;
+        for i in 0 ..NLEN {
+            carry=0;
+            for j in i+1 ..NLEN {
+                let tuple=BIG::muladd(2*a.w[i],a.w[j],carry,c.w[i+j]);
+                carry=tuple.0; c.w[i+j]=tuple.1;
+            //carry,c.w[i+j]=muladd(2*a.w[i],a.w[j],carry,c.w[i+j])
+            //carry=c.muladd(2*a.w[i],a.w[j],carry,i+j)
+            }
+            c.w[NLEN+i]=carry;
+        }
+
+        for i in 0 ..NLEN {
+            let tuple=BIG::muladd(a.w[i],a.w[i],0,c.w[2*i]);
+            c.w[2*i]=tuple.1;
+            c.w[2*i+1]+=tuple.0;
+        //c.w[2*i+1]+=c.muladd(a.w[i],a.w[i],0,2*i)
+        }
+        c.norm();
+        return c;
+    } 
+
+#[cfg(D64)]
+    pub fn monty(md: &BIG,mc: Chunk,d: &mut DBIG) -> BIG {
+        let mut b=BIG::new();     
+        //let mut carry=0 as Chunk; 
+        let mut carry:Chunk;
+        //let mut m=0 as Chunk;
+        let mut m:Chunk;
+        for i in 0 ..NLEN {
+            if mc==-1 { 
+                m=(-d.w[i])&BMASK;
+            } else {
+                if mc==1 {
+                    m=d.w[i];
+                } else {
+                    m=(mc*d.w[i])&BMASK;
+                }
+            }
+
+            carry=0;
+            for j in 0 ..NLEN {
+                let tuple=BIG::muladd(m,md.w[j],carry,d.w[i+j]);
+                carry=tuple.0; d.w[i+j]=tuple.1;
+            }
+            d.w[NLEN+i]+=carry;
+        }
+
+        for i in 0 ..NLEN {
+            b.w[i]=d.w[NLEN+i];
+        } 
+        b.norm();
+        return b;  
+    }
+
+*/
+
+    pub fn ssn(r: &mut BIG,a: &BIG,m: &mut BIG) -> isize {
+        let n=NLEN-1;
+        m.w[0]=(m.w[0]>>1)|((m.w[1]<<(BASEBITS-1))&BMASK);
+	r.w[0]=a.w[0]-m.w[0];
+	let mut carry=r.w[0]>>BASEBITS;
+	r.w[0]&=BMASK;
+	for i in 1 ..n {
+            m.w[i]=(m.w[i]>>1)|((m.w[i+1]<<(BASEBITS-1))&BMASK);
+            r.w[i]=a.w[i]-m.w[i]+carry;
+            carry=r.w[i]>>BASEBITS;
+            r.w[i]&=BMASK;
+        }
+	m.w[n]>>=1;
+	r.w[n]=a.w[n]-m.w[n]+carry;
+	return ((r.w[n]>>(arch::CHUNK-1))&1) as isize;
+    }
+
+    /* return a*b mod m */
+    pub fn modmul(a1: &BIG,b1: &BIG,m: &BIG) -> BIG {
+        let mut a=BIG::new_copy(a1);
+        let mut b=BIG::new_copy(b1);
+        a.rmod(m);
+        b.rmod(m);
+        let mut d=BIG::mul(&a,&b);
+        return d.dmod(m);
+    }
+    
+    /* return a^2 mod m */
+    pub fn modsqr(a1: &BIG,m: &BIG) -> BIG {
+        let mut a=BIG::new_copy(a1);
+        a.rmod(m);
+        let mut d=BIG::sqr(&a);
+        return d.dmod(m);
+    }
+    
+    /* return -a mod m */
+    pub fn modneg(a1: &BIG,m: &BIG) -> BIG {
+        let mut a=BIG::new_copy(a1);
+        a.rmod(m);
+        return m.minus(&a);
+    }
+
+    /* return this^e mod m */
+    pub fn powmod(&mut self,e1: &BIG,m: &BIG) -> BIG {
+        self.norm();
+        let mut e=BIG::new_copy(e1);
+        e.norm();
+        let mut a=BIG::new_int(1);
+        let mut z=BIG::new_copy(&e);
+        let mut s=BIG::new_copy(self);
+        loop {      
+            let bt=z.parity();       
+            z.fshr(1);    
+            if bt==1 {a=BIG::modmul(&a,&s,m)}
+            if z.iszilch() {break}
+            s=BIG::modsqr(&mut s,m);         
+        }
+        return a;
+    }
+
+}
+ 
+/*
+fn main() {
+	let fd: [i32; NLEN as usize] = [1, 2, 3, 4, 5, 6, 7, 8, 9];	
+	let mut x= BIG::new();
+	x.inc(3);
+ 	println!("{}", x.w[0]);	
+ 	let mut y= BIG::new_int(7);
+ 	println!("{}", y.w[0]);	
+ 	y=BIG::new_copy(&x);
+	println!("{}", y.w[0]); 	
+	x.add(&y);
+	x.add(&y);
+	println!("{}", x.w[0]); 	
+	let mut z= BIG::new_ints(&fd);
+	println!("{}", z.w[0]); 	
+	z.shr(3);
+	z.norm();
+	println!("{:X}", z.w[0]); 	
+
+	println!("{}",z.tostring());
+
+    let mut a = BIG::new_int(3);
+    let mut m = BIG::new_ints(&MODULUS);
+
+    println!("rom::MODULUS= {}",m.tostring());
+
+    let mut e = BIG::new_copy(&m);
+    e.dec(1); e.norm();
+    println!("Exponent= {}",e.tostring());
+//    for i in 0..20
+//    {
+        a=a.powmod(&mut e,&mut m);
+//        a.inc(2);
+//    }
+    println!("Result= {}",a.tostring());
+
+}
+*/
diff --git a/version3/rust/config32.py b/version3/rust/config32.py
new file mode 100644
index 0000000..ce19300
--- /dev/null
+++ b/version3/rust/config32.py
@@ -0,0 +1,400 @@
+import os
+import sys
+
+deltext=""
+slashtext=""
+copytext=""
+if sys.platform.startswith("linux") or sys.platform.startswith("darwin") :
+	copytext="cp "
+	deltext="rm "
+	slashtext="/"
+if sys.platform.startswith("win") :
+	copytext="copy "
+	deltext="del "
+	slashtext="\\"
+
+chosen=[]
+cptr=0
+
+def replace(namefile,oldtext,newtext):
+	f = open(namefile,'r')
+	filedata = f.read()
+	f.close()
+
+	newdata = filedata.replace(oldtext,newtext)
+
+	f = open(namefile,'w')
+	f.write(newdata)
+	f.close()
+
+
+def rsaset(tb,nb,base,ml) :
+	global deltext,slashtext,copytext
+	global cptr,chosen
+
+	chosen.append(tb)
+	cptr=cptr+1
+
+	fpath="amcl"+slashtext+"src"+slashtext+tb+slashtext
+	os.system("mkdir amcl"+slashtext+"src"+slashtext+tb)
+
+	with open("amcl"+slashtext+"src"+slashtext+"lib.rs","a") as libfile:
+		libfile.write("pub mod "+tb+";\n")
+
+	os.system(copytext+"modrsa.rs "+fpath+"mod.rs")
+	os.system(copytext+"big.rs "+fpath+"big.rs")
+	os.system(copytext+"dbig.rs "+fpath+"dbig.rs")
+	os.system(copytext+"ff.rs "+fpath+"ff.rs")
+	os.system(copytext+"rsa.rs "+fpath+"rsa.rs")
+
+	replace(fpath+"big.rs","xxx",tb)
+	replace(fpath+"dbig.rs","xxx",tb)
+	replace(fpath+"ff.rs","xxx",tb)
+	replace(fpath+"rsa.rs","xxx",tb)
+
+	replace(fpath+"big.rs","@NB@",nb)
+	replace(fpath+"big.rs","@BASE@",base)
+
+	replace(fpath+"ff.rs","@ML@",ml)
+
+	#os.system("go install amcl"+slashtext+tb)
+
+
+def curveset(tc,nb,base,nbt,m8,mt,ct,pf,stw,sx,cs) :
+	global deltext,slashtext,copytext
+	global cptr,chosen
+
+	chosen.append(tc)
+	cptr=cptr+1
+
+	fpath="amcl"+slashtext+"src"+slashtext+tc+slashtext
+	os.system("mkdir amcl"+slashtext+"src"+slashtext+tc)
+
+	with open("amcl"+slashtext+"src"+slashtext+"lib.rs","a") as libfile:
+		libfile.write("pub mod "+tc+";\n")
+
+
+	os.system(copytext+"big.rs "+fpath+"big.rs")
+	os.system(copytext+"dbig.rs "+fpath+"dbig.rs")
+	os.system(copytext+"fp.rs "+fpath+"fp.rs")
+	os.system(copytext+"ecp.rs "+fpath+"ecp.rs")
+	os.system(copytext+"ecdh.rs "+fpath+"ecdh.rs")
+	os.system(copytext+"rom_"+tc+"_32.rs "+fpath+"rom.rs")
+
+	replace(fpath+"big.rs","xxx",tc)
+	replace(fpath+"dbig.rs","xxx",tc)
+	replace(fpath+"fp.rs","xxx",tc)
+	replace(fpath+"ecp.rs","xxx",tc)
+	replace(fpath+"ecdh.rs","xxx",tc)
+
+	replace(fpath+"big.rs","@NB@",nb)
+	replace(fpath+"big.rs","@BASE@",base)
+
+	replace(fpath+"fp.rs","@NBT@",nbt)
+	replace(fpath+"fp.rs","@M8@",m8)
+	replace(fpath+"fp.rs","@MT@",mt)
+
+	ib=int(base)
+	inb=int(nb)
+	inbt=int(nbt)
+	sh=ib*(1+((8*inb-1)//ib))-inbt
+	if sh > 14 :
+		sh=14
+	replace(fpath+"fp.rs","@SH@",str(sh))
+
+
+	replace(fpath+"ecp.rs","@CT@",ct)
+	replace(fpath+"ecp.rs","@PF@",pf)
+
+	replace(fpath+"ecp.rs","@ST@",stw)
+	replace(fpath+"ecp.rs","@SX@",sx)
+
+	if cs == "128" :
+		replace(fpath+"ecp.rs","@HT@","32")
+		replace(fpath+"ecp.rs","@AK@","16")
+	if cs == "192" :
+		replace(fpath+"ecp.rs","@HT@","48")
+		replace(fpath+"ecp.rs","@AK@","24")
+	if cs == "256" :
+		replace(fpath+"ecp.rs","@HT@","64")
+		replace(fpath+"ecp.rs","@AK@","32")
+
+	if pf != "NOT" :
+
+		os.system(copytext+"fp2.rs "+fpath+"fp2.rs")
+		os.system(copytext+"fp4.rs "+fpath+"fp4.rs")
+		replace(fpath+"fp2.rs","xxx",tc)
+		replace(fpath+"fp4.rs","xxx",tc)
+		
+		if cs == "128" :
+			os.system(copytext+"ecp2.rs "+fpath+"ecp2.rs")
+			os.system(copytext+"fp12.rs "+fpath+"fp12.rs")
+			os.system(copytext+"pair.rs "+fpath+"pair.rs")
+			os.system(copytext+"mpin.rs "+fpath+"mpin.rs")
+
+			replace(fpath+"fp12.rs","xxx",tc)
+			replace(fpath+"ecp2.rs","xxx",tc)
+			replace(fpath+"pair.rs","xxx",tc)
+			replace(fpath+"mpin.rs","xxx",tc)
+
+			os.system(copytext+"modpf.rs "+fpath+"mod.rs")
+
+
+		if cs == "192" :
+			os.system(copytext+"fp8.rs "+fpath+"fp8.rs")
+			os.system(copytext+"ecp4.rs "+fpath+"ecp4.rs")
+			os.system(copytext+"fp24.rs "+fpath+"fp24.rs")
+			os.system(copytext+"pair192.rs "+fpath+"pair192.rs")
+			os.system(copytext+"mpin192.rs "+fpath+"mpin192.rs")
+
+			replace(fpath+"fp8.rs","xxx",tc)
+			replace(fpath+"fp24.rs","xxx",tc)
+			replace(fpath+"ecp4.rs","xxx",tc)
+			replace(fpath+"pair192.rs","xxx",tc)
+			replace(fpath+"mpin192.rs","xxx",tc)
+
+			os.system(copytext+"modpf192.rs "+fpath+"mod.rs")
+
+		if cs == "256" :
+			os.system(copytext+"fp8.rs "+fpath+"fp8.rs")
+			os.system(copytext+"fp16.rs "+fpath+"fp16.rs")
+			os.system(copytext+"ecp8.rs "+fpath+"ecp8.rs")
+			os.system(copytext+"fp48.rs "+fpath+"fp48.rs")
+			os.system(copytext+"pair256.rs "+fpath+"pair256.rs")
+			os.system(copytext+"mpin256.rs "+fpath+"mpin256.rs")
+
+			replace(fpath+"fp8.rs","xxx",tc)
+			replace(fpath+"fp16.rs","xxx",tc)
+			replace(fpath+"fp48.rs","xxx",tc)
+			replace(fpath+"ecp8.rs","xxx",tc)
+			replace(fpath+"pair256.rs","xxx",tc)
+			replace(fpath+"mpin256.rs","xxx",tc)
+
+			os.system(copytext+"modpf256.rs "+fpath+"mod.rs")
+
+	else :
+		os.system(copytext+"modecc.rs "+fpath+"mod.rs")
+
+
+os.system("cargo new amcl")
+#os.system("mkdir amcl"+slashtext+"src")
+os.system(copytext+ "hash*.rs amcl"+slashtext+"src"+slashtext+".")
+os.system(copytext+ "sha3.rs amcl"+slashtext+"src"+slashtext+".")
+os.system(copytext+ "rand.rs amcl"+slashtext+"src"+slashtext+".")
+os.system(copytext+ "aes.rs amcl"+slashtext+"src"+slashtext+".")
+os.system(copytext+ "gcm.rs amcl"+slashtext+"src"+slashtext+".")
+os.system(copytext+ "nhs.rs amcl"+slashtext+"src"+slashtext+".")
+os.system(copytext+ "arch32.rs amcl"+slashtext+"src"+slashtext+"arch.rs")
+os.system(copytext+ "lib.rs amcl"+slashtext+"src"+slashtext+"lib.rs")
+
+
+print("Elliptic Curves")
+print("1. ed25519")
+print("2. c25519")
+print("3. nist256")
+print("4. brainpool")
+print("5. anssi")
+print("6. hifive")
+print("7. goldilocks")
+print("8. nist384")
+print("9. c41417")
+print("10. nist521\n")
+print("11. nums256w")
+print("12. nums256e")
+print("13. nums384w")
+print("14. nums384e")
+print("15. nums512w")
+print("16. nums512e")
+print("17. secp256k1\n")
+
+print("Pairing-Friendly Elliptic Curves")
+print("18. bn254")
+print("19. bn254CX")
+print("20. bls383")
+print("21. bls381")
+print("22. fp256BN")
+print("23. fp512BN")
+print("24. bls461\n")
+print("25. bls24")
+print("26. bls48\n")
+
+print("RSA")
+print("27. rsa2048")
+print("28. rsa3072")
+print("29. rsa4096")
+
+selection=[]
+ptr=0
+max=30
+
+curve_selected=False
+pfcurve_selected=False
+rsa_selected=False
+
+while ptr<max:
+	x=int(input("Choose a Scheme to support - 0 to finish: "))
+	if x == 0:
+		break
+#	print("Choice= ",x)
+	already=False
+	for i in range(0,ptr):
+		if x==selection[i]:
+			already=True
+			break
+	if already:
+		continue
+	
+	selection.append(x)
+	ptr=ptr+1
+
+# curveset(curve,big_length_bytes,bits_in_base,modulus_bits,modulus_mod_8,modulus_type,curve_type,pairing_friendly,curve security)
+# where "curve" is the common name for the elliptic curve   
+# big_length_bytes is the modulus size rounded up to a number of bytes
+# bits_in_base gives the number base used for 32 bit architectures, as n where the base is 2^n
+# modulus_bits is the actual bit length of the modulus.
+# modulus_mod_8 is the remainder when the modulus is divided by 8
+# modulus_type is NOT_SPECIAL, or PSEUDO_MERSENNE, or MONTGOMERY_Friendly, or GENERALISED_MERSENNE (supported for GOLDILOCKS only)
+# curve_type is WEIERSTRASS, EDWARDS or MONTGOMERY
+# pairing_friendly is BN, BLS or NOT (if not pairing friendly
+# curve security is AES equiavlent, rounded up.
+
+
+	if x==1:
+		curveset("ed25519","32","29","255","5","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==2:
+		curveset("c25519","32","29","255","5","PSEUDO_MERSENNE","MONTGOMERY","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==3:
+		curveset("nist256","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==4:
+		curveset("brainpool","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==5:
+		curveset("anssi","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+		curve_selected=True
+
+	if x==6:
+		curveset("hifive","42","29","336","5","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","192")
+		curve_selected=True
+	if x==7:
+		curveset("goldilocks","56","29","448","7","GENERALISED_MERSENNE","EDWARDS","NOT","NOT","NOT","256")
+		curve_selected=True
+	if x==8:
+		curveset("nist384","48","29","384","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","192")
+		curve_selected=True
+	if x==9:
+		curveset("c41417","52","29","414","7","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","256")
+		curve_selected=True
+	if x==10:
+		curveset("nist521","66","28","521","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","256")
+		curve_selected=True
+
+	if x==11:
+		curveset("nums256w","32","28","256","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==12:
+		curveset("nums256e","32","29","256","3","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==13:
+		curveset("nums384w","48","29","384","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","192")
+		curve_selected=True
+	if x==14:
+		curveset("nums384e","48","29","384","3","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","192")
+		curve_selected=True
+	if x==15:
+		curveset("nums512w","64","29","512","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","256")
+		curve_selected=True
+	if x==16:
+		curveset("nums512e","64","29","512","7","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","256")
+		curve_selected=True
+
+	if x==17:
+		curveset("secp256k1","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+		curve_selected=True
+
+
+	if x==18:
+		curveset("bn254","32","28","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+	if x==19:
+		curveset("bn254CX","32","28","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+	if x==20:
+		curveset("bls383","48","29","383","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","128")
+		pfcurve_selected=True
+
+	if x==21:
+		curveset("bls381","48","29","381","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+
+	if x==22:
+		curveset("fp256bn","32","28","256","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+	if x==23:
+		curveset("fp512bn","64","29","512","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","POSITIVEX","128")
+		pfcurve_selected=True
+# https://eprint.iacr.org/2017/334.pdf
+	if x==24:
+		curveset("bls461","58","28","461","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+
+	if x==25:
+		curveset("bls24","60","29","479","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","192")
+		pfcurve_selected=True
+
+	if x==26:
+		curveset("bls48","70","29","556","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","256")
+		pfcurve_selected=True
+
+
+# rsaset(rsaname,big_length_bytes,bits_in_base,multiplier)
+# The RSA name reflects the modulus size, which is a 2^m multiplier
+# of the underlying big length
+
+# There are choices here, different ways of getting the same result, but some faster than others
+	if x==27:
+		#256 is slower but may allow reuse of 256-bit BIGs used for elliptic curve
+		#512 is faster.. but best is 1024
+		rsaset("rsa2048","128","28","2")
+		#rsaset("RSA2048","64","29","4")
+		#rsaset("RSA2048","32","29","8")
+		rsa_selected=True
+	if x==28:
+		rsaset("rsa3072","48","28","8")
+		rsa_selected=True
+	if x==29:
+		#rsaset("RSA4096","32","29","16")
+		rsaset("rsa4096","64","29","8")
+		rsa_selected=True
+
+os.system("cargo rustc --manifest-path amcl"+slashtext+"Cargo.toml --release --lib -- --cfg D32")
+
+#os.system("cargo rustc --target wasm32-unknown-emscripten --manifest-path amcl"+slashtext+"Cargo.toml --release --lib -- --cfg D32")
+
+os.system(deltext+" hash*.rs")
+os.system(deltext+" sha3.rs")
+os.system(deltext+" aes.rs")
+os.system(deltext+" rand.rs")
+os.system(deltext+" gcm.rs")
+os.system(deltext+" nhs.rs")
+
+os.system(deltext+" arch*.rs")
+os.system(deltext+" big.rs")
+os.system(deltext+" dbig.rs")
+os.system(deltext+" fp*.rs")
+os.system(deltext+" mod*.rs")
+os.system(deltext+" lib.rs")
+
+os.system(deltext+" ecdh.rs")
+os.system(deltext+" ff.rs")
+os.system(deltext+" rsa.rs")
+os.system(deltext+" ecp*.rs")
+os.system(deltext+" pair*.rs")
+os.system(deltext+" mpin*.rs")
+os.system(deltext+" rom*.rs")
+
+# create library
+
+
diff --git a/version3/rust/config64.py b/version3/rust/config64.py
new file mode 100644
index 0000000..4a9846d
--- /dev/null
+++ b/version3/rust/config64.py
@@ -0,0 +1,399 @@
+import os
+import sys
+
+deltext=""
+slashtext=""
+copytext=""
+if sys.platform.startswith("linux") or sys.platform.startswith("darwin") :
+	copytext="cp "
+	deltext="rm "
+	slashtext="/"
+if sys.platform.startswith("win") :
+	copytext="copy "
+	deltext="del "
+	slashtext="\\"
+
+chosen=[]
+cptr=0
+
+def replace(namefile,oldtext,newtext):
+	f = open(namefile,'r')
+	filedata = f.read()
+	f.close()
+
+	newdata = filedata.replace(oldtext,newtext)
+
+	f = open(namefile,'w')
+	f.write(newdata)
+	f.close()
+
+
+def rsaset(tb,nb,base,ml) :
+	global deltext,slashtext,copytext
+	global cptr,chosen
+
+	chosen.append(tb)
+	cptr=cptr+1
+
+	fpath="amcl"+slashtext+"src"+slashtext+tb+slashtext
+	os.system("mkdir amcl"+slashtext+"src"+slashtext+tb)
+
+	with open("amcl"+slashtext+"src"+slashtext+"lib.rs","a") as libfile:
+		libfile.write("pub mod "+tb+";\n")
+
+	os.system(copytext+"modrsa.rs "+fpath+"mod.rs")
+	os.system(copytext+"big.rs "+fpath+"big.rs")
+	os.system(copytext+"dbig.rs "+fpath+"dbig.rs")
+	os.system(copytext+"ff.rs "+fpath+"ff.rs")
+	os.system(copytext+"rsa.rs "+fpath+"rsa.rs")
+
+	replace(fpath+"big.rs","xxx",tb)
+	replace(fpath+"dbig.rs","xxx",tb)
+	replace(fpath+"ff.rs","xxx",tb)
+	replace(fpath+"rsa.rs","xxx",tb)
+
+	replace(fpath+"big.rs","@NB@",nb)
+	replace(fpath+"big.rs","@BASE@",base)
+
+	replace(fpath+"ff.rs","@ML@",ml)
+
+	#os.system("go install amcl"+slashtext+tb)
+
+
+def curveset(tc,nb,base,nbt,m8,mt,ct,pf,stw,sx,cs) :
+	global deltext,slashtext,copytext
+	global cptr,chosen
+
+	chosen.append(tc)
+	cptr=cptr+1
+
+	fpath="amcl"+slashtext+"src"+slashtext+tc+slashtext
+	os.system("mkdir amcl"+slashtext+"src"+slashtext+tc)
+
+	with open("amcl"+slashtext+"src"+slashtext+"lib.rs","a") as libfile:
+		libfile.write("pub mod "+tc+";\n")
+
+
+	os.system(copytext+"big.rs "+fpath+"big.rs")
+	os.system(copytext+"dbig.rs "+fpath+"dbig.rs")
+	os.system(copytext+"fp.rs "+fpath+"fp.rs")
+	os.system(copytext+"ecp.rs "+fpath+"ecp.rs")
+	os.system(copytext+"ecdh.rs "+fpath+"ecdh.rs")
+	os.system(copytext+"rom_"+tc+"_64.rs "+fpath+"rom.rs")
+
+	replace(fpath+"big.rs","xxx",tc)
+	replace(fpath+"dbig.rs","xxx",tc)
+	replace(fpath+"fp.rs","xxx",tc)
+	replace(fpath+"ecp.rs","xxx",tc)
+	replace(fpath+"ecdh.rs","xxx",tc)
+
+	replace(fpath+"big.rs","@NB@",nb)
+	replace(fpath+"big.rs","@BASE@",base)
+
+	replace(fpath+"fp.rs","@NBT@",nbt)
+	replace(fpath+"fp.rs","@M8@",m8)
+	replace(fpath+"fp.rs","@MT@",mt)
+
+	ib=int(base)
+	inb=int(nb)
+	inbt=int(nbt)
+	sh=ib*(1+((8*inb-1)//ib))-inbt
+	if sh > 30 :
+		sh=30
+	replace(fpath+"fp.rs","@SH@",str(sh))
+
+
+	replace(fpath+"ecp.rs","@CT@",ct)
+	replace(fpath+"ecp.rs","@PF@",pf)
+
+	replace(fpath+"ecp.rs","@ST@",stw)
+	replace(fpath+"ecp.rs","@SX@",sx)
+
+	if cs == "128" :
+		replace(fpath+"ecp.rs","@HT@","32")
+		replace(fpath+"ecp.rs","@AK@","16")
+	if cs == "192" :
+		replace(fpath+"ecp.rs","@HT@","48")
+		replace(fpath+"ecp.rs","@AK@","24")
+	if cs == "256" :
+		replace(fpath+"ecp.rs","@HT@","64")
+		replace(fpath+"ecp.rs","@AK@","32")
+
+
+	if pf != "NOT" :
+
+		os.system(copytext+"fp2.rs "+fpath+"fp2.rs")
+		os.system(copytext+"fp4.rs "+fpath+"fp4.rs")
+		replace(fpath+"fp2.rs","xxx",tc)
+		replace(fpath+"fp4.rs","xxx",tc)
+
+		if cs == "128" :
+			os.system(copytext+"ecp2.rs "+fpath+"ecp2.rs")
+			os.system(copytext+"fp12.rs "+fpath+"fp12.rs")
+			os.system(copytext+"pair.rs "+fpath+"pair.rs")
+			os.system(copytext+"mpin.rs "+fpath+"mpin.rs")
+
+			replace(fpath+"fp12.rs","xxx",tc)
+			replace(fpath+"ecp2.rs","xxx",tc)
+			replace(fpath+"pair.rs","xxx",tc)
+			replace(fpath+"mpin.rs","xxx",tc)
+
+			os.system(copytext+"modpf.rs "+fpath+"mod.rs")
+
+
+		if cs == "192" :
+			os.system(copytext+"fp8.rs "+fpath+"fp8.rs")
+			os.system(copytext+"ecp4.rs "+fpath+"ecp4.rs")
+			os.system(copytext+"fp24.rs "+fpath+"fp24.rs")
+			os.system(copytext+"pair192.rs "+fpath+"pair192.rs")
+			os.system(copytext+"mpin192.rs "+fpath+"mpin192.rs")
+
+			replace(fpath+"fp8.rs","xxx",tc)
+			replace(fpath+"fp24.rs","xxx",tc)
+			replace(fpath+"ecp4.rs","xxx",tc)
+			replace(fpath+"pair192.rs","xxx",tc)
+			replace(fpath+"mpin192.rs","xxx",tc)
+
+			os.system(copytext+"modpf192.rs "+fpath+"mod.rs")
+
+		if cs == "256" :
+			os.system(copytext+"fp8.rs "+fpath+"fp8.rs")
+			os.system(copytext+"fp16.rs "+fpath+"fp16.rs")
+			os.system(copytext+"ecp8.rs "+fpath+"ecp8.rs")
+			os.system(copytext+"fp48.rs "+fpath+"fp48.rs")
+			os.system(copytext+"pair256.rs "+fpath+"pair256.rs")
+			os.system(copytext+"mpin256.rs "+fpath+"mpin256.rs")
+
+			replace(fpath+"fp8.rs","xxx",tc)
+			replace(fpath+"fp16.rs","xxx",tc)
+			replace(fpath+"fp48.rs","xxx",tc)
+			replace(fpath+"ecp8.rs","xxx",tc)
+			replace(fpath+"pair256.rs","xxx",tc)
+			replace(fpath+"mpin256.rs","xxx",tc)
+
+			os.system(copytext+"modpf256.rs "+fpath+"mod.rs")
+
+	else :
+		os.system(copytext+"modecc.rs "+fpath+"mod.rs")	
+
+os.system("cargo new amcl")
+#os.system("mkdir amcl"+slashtext+"src")
+os.system(copytext+ "hash*.rs amcl"+slashtext+"src"+slashtext+".")
+os.system(copytext+ "sha3.rs amcl"+slashtext+"src"+slashtext+".")
+os.system(copytext+ "rand.rs amcl"+slashtext+"src"+slashtext+".")
+os.system(copytext+ "aes.rs amcl"+slashtext+"src"+slashtext+".")
+os.system(copytext+ "gcm.rs amcl"+slashtext+"src"+slashtext+".")
+os.system(copytext+ "nhs.rs amcl"+slashtext+"src"+slashtext+".")
+os.system(copytext+ "arch64.rs amcl"+slashtext+"src"+slashtext+"arch.rs")
+os.system(copytext+ "lib.rs amcl"+slashtext+"src"+slashtext+"lib.rs")
+
+
+print("Elliptic Curves")
+print("1. ed25519")
+print("2. c25519")
+print("3. nist256")
+print("4. brainpool")
+print("5. anssi")
+print("6. hifive")
+print("7. goldilocks")
+print("8. nist384")
+print("9. c41417")
+print("10. nist521\n")
+print("11. nums256w")
+print("12. nums256e")
+print("13. nums384w")
+print("14. nums384e")
+print("15. nums512w")
+print("16. nums512e")
+print("17. secp256k1\n")
+
+print("Pairing-Friendly Elliptic Curves")
+print("18. bn254")
+print("19. bn254CX")
+print("20. bls383")
+print("21. bls381")
+print("22. fp256BN")
+print("23. fp512BN")
+print("24. bls461\n")
+print("25. bls24")
+print("26. bls48\n")
+
+print("RSA")
+print("27. rsa2048")
+print("28. rsa3072")
+print("29. rsa4096")
+
+selection=[]
+ptr=0
+max=30
+
+curve_selected=False
+pfcurve_selected=False
+rsa_selected=False
+
+while ptr<max:
+	x=int(input("Choose a Scheme to support - 0 to finish: "))
+	if x == 0:
+		break
+#	print("Choice= ",x)
+	already=False
+	for i in range(0,ptr):
+		if x==selection[i]:
+			already=True
+			break
+	if already:
+		continue
+	
+	selection.append(x)
+	ptr=ptr+1
+
+# curveset(curve,big_length_bytes,bits_in_base,modulus_bits,modulus_mod_8,modulus_type,curve_type,pairing_friendly,curve security)
+# where "curve" is the common name for the elliptic curve   
+# big_length_bytes is the modulus size rounded up to a number of bytes
+# bits_in_base gives the number base used for 64 bit architectures, as n where the base is 2^n
+# modulus_bits is the actual bit length of the modulus.
+# modulus_mod_8 is the remainder when the modulus is divided by 8
+# modulus_type is NOT_SPECIAL, or PSEUDO_MERSENNE, or MONTGOMERY_Friendly, or GENERALISED_MERSENNE (supported for GOLDILOCKS only)
+# curve_type is WEIERSTRASS, EDWARDS or MONTGOMERY
+# pairing_friendly is BN, BLS or NOT (if not pairing friendly
+# curve security is AES equiavlent, rounded up.
+
+
+	if x==1:
+		curveset("ed25519","32","56","255","5","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==2:
+		curveset("c25519","32","56","255","5","PSEUDO_MERSENNE","MONTGOMERY","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==3:
+		curveset("nist256","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==4:
+		curveset("brainpool","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==5:
+		curveset("anssi","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+		curve_selected=True
+
+	if x==6:
+		curveset("hifive","42","60","336","5","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","192")
+		curve_selected=True
+	if x==7:
+		curveset("goldilocks","56","58","448","7","GENERALISED_MERSENNE","EDWARDS","NOT","NOT","NOT","256")
+		curve_selected=True
+	if x==8:
+		curveset("nist384","48","56","384","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","192")
+		curve_selected=True
+	if x==9:
+		curveset("c41417","52","60","414","7","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","256")
+		curve_selected=True
+	if x==10:
+		curveset("nist521","66","60","521","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","256")
+		curve_selected=True
+
+	if x==11:
+		curveset("nums256w","32","56","256","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==12:
+		curveset("nums256e","32","56","256","3","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==13:
+		curveset("nums384w","48","58","384","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","192")
+		curve_selected=True
+	if x==14:
+		curveset("nums384e","48","56","384","3","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","192")
+		curve_selected=True
+	if x==15:
+		curveset("nums512w","64","60","512","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","256")
+		curve_selected=True
+	if x==16:
+		curveset("nums512e","64","60","512","7","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","256")
+		curve_selected=True
+
+	if x==17:
+		curveset("secp256k1","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+		curve_selected=True
+
+	if x==18:
+		curveset("bn254","32","56","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+	if x==19:
+		curveset("bn254CX","32","56","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+	if x==20:
+		curveset("bls383","48","58","383","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","128")
+		pfcurve_selected=True
+
+	if x==21:
+		curveset("bls381","48","58","381","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+
+	if x==22:
+		curveset("fp256bn","32","56","256","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+	if x==23:
+		curveset("fp512bn","64","60","512","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","POSITIVEX","128")
+		pfcurve_selected=True
+# https://eprint.iacr.org/2017/334.pdf
+	if x==24:
+		curveset("bls461","58","60","461","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+
+	if x==25:
+		curveset("bls24","60","56","479","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","192")
+		pfcurve_selected=True
+
+	if x==26:
+		curveset("bls48","70","58","556","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","256")
+		pfcurve_selected=True
+
+
+# rsaset(rsaname,big_length_bytes,bits_in_base,multiplier)
+# The RSA name reflects the modulus size, which is a 2^m multiplier
+# of the underlying big length
+
+# There are choices here, different ways of getting the same result, but some faster than others
+	if x==27:
+		#256 is slower but may allow reuse of 256-bit BIGs used for elliptic curve
+		#512 is faster.. but best is 1024
+		rsaset("rsa2048","128","58","2")
+		#rsaset("RSA2048","64","60","4")
+		#rsaset("RSA2048","32","56","8")
+		rsa_selected=True
+	if x==28:
+		rsaset("rsa3072","48","56","8")
+		rsa_selected=True
+	if x==29:
+		#rsaset("RSA4096","32","56","16")
+		rsaset("rsa4096","64","60","8")
+		rsa_selected=True
+
+os.system("cargo rustc --manifest-path amcl"+slashtext+"Cargo.toml --release --lib -- --cfg D64")
+
+#os.system("cargo rustc --target wasm64-unknown-emscripten --manifest-path amcl"+slashtext+"Cargo.toml --release --lib -- --cfg D64")
+
+os.system(deltext+" hash*.rs")
+os.system(deltext+" sha3.rs")
+os.system(deltext+" aes.rs")
+os.system(deltext+" rand.rs")
+os.system(deltext+" gcm.rs")
+os.system(deltext+" nhs.rs")
+
+os.system(deltext+" arch*.rs")
+os.system(deltext+" big.rs")
+os.system(deltext+" dbig.rs")
+os.system(deltext+" fp*.rs")
+os.system(deltext+" mod*.rs")
+os.system(deltext+" lib.rs")
+
+os.system(deltext+" ecdh.rs")
+os.system(deltext+" ff.rs")
+os.system(deltext+" rsa.rs")
+os.system(deltext+" ecp*.rs")
+os.system(deltext+" pair*.rs")
+os.system(deltext+" mpin*.rs")
+os.system(deltext+" rom*.rs")
+
+# create library
+
+
diff --git a/version3/rust/dbig.rs b/version3/rust/dbig.rs
new file mode 100644
index 0000000..2c5b680
--- /dev/null
+++ b/version3/rust/dbig.rs
@@ -0,0 +1,272 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use arch;
+use xxx::big;
+use xxx::big::BIG;
+use arch::Chunk;
+
+//#[derive(Copy, Clone)]
+pub struct DBIG {
+ 	pub w: [Chunk; big::DNLEN]
+}
+
+impl DBIG {
+   pub fn new() -> DBIG {
+        DBIG {
+        	w: [0; big::DNLEN as usize]
+         }
+    }	
+
+    pub fn new_copy(y:&DBIG) -> DBIG {
+    	let mut s= DBIG::new();   
+    	for i in 0..big::DNLEN {s.w[i]=y.w[i]}
+    	return s;	
+    }
+
+    pub fn new_scopy(x:&BIG) -> DBIG {
+    	let mut b= DBIG::new();   
+		for i in 0 ..big::NLEN {
+			b.w[i]=x.w[i];
+		}
+		b.w[big::NLEN-1]=x.get(big::NLEN-1)&big::BMASK; /* top word normalized */
+		b.w[big::NLEN]=x.get(big::NLEN-1)>>big::BASEBITS;
+
+		for i in big::NLEN+1 ..big::DNLEN {b.w[i]=0}
+    	return b; 	
+    }
+
+/* split DBIG at position n, return higher half, keep lower half */
+    pub fn split(&mut self,n: usize) -> BIG
+    {
+        let mut t=BIG::new();
+        let m=n%big::BASEBITS;
+        let mut carry=self.w[big::DNLEN-1]<<(big::BASEBITS-m);
+    
+        for i in (big::NLEN-1..big::DNLEN-1).rev() {
+            let nw=(self.w[i]>>m)|carry;
+            carry= (self.w[i]<<(big::BASEBITS-m))&big::BMASK;
+            t.set(i+1-big::NLEN,nw);
+        }
+        self.w[big::NLEN-1]&=((1 as Chunk)<<m)-1;
+        return t;
+    }
+
+/* general shift left */
+    pub fn shl(&mut self,k: usize)
+    {
+        let n=k%big::BASEBITS; 
+        let m=k/big::BASEBITS; 
+        self.w[big::DNLEN-1]=((self.w[big::DNLEN-1-m]<<n))|(self.w[big::DNLEN-m-2]>>(big::BASEBITS-n));
+        for i in (m+1..big::DNLEN-1).rev() {
+            self.w[i]=((self.w[i-m]<<n)&big::BMASK)|(self.w[i-m-1]>>(big::BASEBITS-n));
+        }
+  
+        self.w[m]=(self.w[0]<<n)&big::BMASK;
+        for i in 0 ..m {self.w[i]=0}
+    }
+
+/* general shift right */
+    pub fn shr(&mut self,k: usize) {
+		let n=k%big::BASEBITS;
+		let m=k/big::BASEBITS;
+        for i in 0 ..big::DNLEN-m-1 {
+            self.w[i]=(self.w[m+i]>>n)|((self.w[m+i+1]<<(big::BASEBITS-n))&big::BMASK);
+        }
+        self.w[big::DNLEN-m-1]=self.w[big::DNLEN-1]>>n;
+        for i in big::DNLEN - m ..big::DNLEN {self.w[i]=0}
+    }
+
+/* Copy from another DBIG */
+	pub fn copy(&mut self,x: &DBIG) {
+		for i in 0 ..big::DNLEN {
+			self.w[i]=x.w[i];
+		}
+	}
+
+    pub fn ucopy(&mut self,x: &BIG) {
+        for i in 0 ..big::NLEN {
+            self.w[i]=0;
+        }
+        for i in big::NLEN ..big::DNLEN {
+            self.w[i]=x.w[i-big::NLEN];
+        }        
+    }    
+
+	pub fn cmove(&mut self,g:&DBIG,d: isize) {
+		let b=-d as Chunk;
+		for i in 0 ..big::DNLEN {
+			self.w[i]^=(self.w[i]^g.w[i])&b;
+		}
+	}
+
+/* self+=x */
+    pub fn add(&mut self,x:&DBIG) {
+        for i in 0 ..big::DNLEN {
+            self.w[i]+=x.w[i]; 
+        }
+    } 
+
+/* self-=x */
+	pub fn sub(&mut self,x:&DBIG) {
+		for i in 0 ..big::DNLEN {
+			self.w[i]-=x.w[i]; 
+		}
+	} 
+
+/* self=x-self */
+    pub fn rsub(&mut self,x:&DBIG) {
+        for i in 0 ..big::DNLEN {
+            self.w[i]=x.w[i]-self.w[i]; 
+        }
+    } 
+
+
+/* Compare a and b, return 0 if a==b, -1 if a<b, +1 if a>b. Inputs must be normalised */
+    pub fn comp(a: &DBIG,b: &DBIG) -> isize {
+        for i in (0 ..big::DNLEN).rev() {
+            if a.w[i]==b.w[i] {continue}
+            if a.w[i]>b.w[i] {return 1}
+            else  {return -1}
+        }
+        return 0;
+    }
+
+/* normalise BIG - force all digits < 2^big::BASEBITS */
+    pub fn norm(&mut self) {
+        let mut carry=0 as Chunk;
+        for i in 0 ..big::DNLEN-1 {
+            let d=self.w[i]+carry;
+            self.w[i]=d&big::BMASK;
+            carry=d>>big::BASEBITS;
+        }
+        self.w[big::DNLEN-1]+=carry
+    }
+
+/* reduces self DBIG mod a BIG, and returns the BIG */
+    pub fn dmod(&mut self,c: &BIG) -> BIG {
+        let mut k=0;
+        self.norm();
+        let mut m=DBIG::new_scopy(c);
+        let mut dr=DBIG::new();
+    
+        if DBIG::comp(self,&m)<0 {
+        	let r=BIG::new_dcopy(self);
+        	return r;
+        }
+    
+        loop {
+            m.shl(1);
+            k += 1;
+            if DBIG::comp(self,&m)<0 {break;}
+        }
+    
+        while k>0 {
+            m.shr(1);
+
+		dr.copy(self);
+		dr.sub(&m);
+		dr.norm();
+		self.cmove(&dr,(1-((dr.w[big::DNLEN-1]>>(arch::CHUNK-1))&1)) as isize);
+/*
+            if DBIG::comp(self,&m)>=0 {
+				self.sub(&m);
+				self.norm();
+            } */
+            k -= 1;
+        }
+        let r=BIG::new_dcopy(self);
+        return r;
+    }
+
+/* return this/c */
+    pub fn div(&mut self,c: &BIG) -> BIG {
+        let mut k=0;
+        let mut m=DBIG::new_scopy(c);
+        let mut a=BIG::new();
+        let mut e=BIG::new_int(1);
+	let mut dr=DBIG::new();
+	let mut r=BIG::new();
+        self.norm();
+
+        while DBIG::comp(self,&m)>=0 {
+            e.fshl(1);
+            m.shl(1);
+            k+=1;
+        }
+
+        while k>0 {
+            m.shr(1);
+            e.shr(1);
+
+		dr.copy(self);
+		dr.sub(&m);
+		dr.norm();
+		let d=(1-((dr.w[big::DNLEN-1]>>(arch::CHUNK-1))&1)) as isize;
+		self.cmove(&dr,d);
+		r.copy(&a);
+		r.add(&e);
+		r.norm();
+		a.cmove(&r,d);
+/*
+            if DBIG::comp(self,&m)>0 {
+                a.add(&e);
+                a.norm();
+                self.sub(&m);
+                self.norm();
+            } */
+            k-=1;
+        }
+        return a;
+    }
+
+/* return number of bits */
+	pub fn nbits(&mut self) -> usize {
+		let mut k=big::DNLEN-1;
+		let mut s=DBIG::new_copy(&self);        
+		s.norm();
+		while (k as isize)>=0 && s.w[k]==0 {k=k.wrapping_sub(1)}
+		if (k as isize) <0 {return 0}
+		let mut bts=(big::BASEBITS as usize)*k;
+		let mut c=s.w[k];
+		while c!=0 {c/=2; bts+=1;}
+		return bts;
+	}
+
+/* Convert to Hex String */
+	pub fn to_string(&mut self) -> String {
+		let mut s = String::new();
+		let mut len=self.nbits();
+
+		if len%4==0 {
+			len/=4;
+		} else {
+			len/=4;
+			len+=1;
+		}
+
+		for i in (0 ..len).rev() {
+			let mut b=DBIG::new_copy(&self);
+			b.shr(i*4);
+			s=s + &format!("{:X}", b.w[0]&15);
+		}
+		return s;
+	}	
+
+}
diff --git a/version3/rust/ecdh.rs b/version3/rust/ecdh.rs
new file mode 100644
index 0000000..10c30e5
--- /dev/null
+++ b/version3/rust/ecdh.rs
@@ -0,0 +1,604 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use xxx::ecp;
+use xxx::ecp::ECP;
+use xxx::big::BIG;
+use xxx::rom;
+use xxx::big;
+
+use rand::RAND;
+use hash256::HASH256;
+use hash384::HASH384;
+use hash512::HASH512;
+use aes;
+use aes::AES;
+
+
+pub const INVALID_PUBLIC_KEY:isize=-2;
+pub const ERROR:  isize=-3;
+pub const INVALID: isize=-4;
+pub const EFS: usize=big::MODBYTES as usize;
+pub const EGS: usize=big::MODBYTES as usize;
+//pub const EAS: usize=16;
+//pub const EBS: usize=16;
+pub const SHA256: usize=32;
+pub const SHA384: usize=48;
+pub const SHA512: usize=64;
+
+//pub const HASH_TYPE: usize=SHA512;
+
+#[allow(non_snake_case)]
+
+fn inttobytes(n: usize,b:&mut [u8]) {
+	let mut i=b.len();
+	let mut m=n;
+	while m>0 && i>0 {
+		i-=1;
+		b[i]=(m&0xff) as u8;
+		m/=256;
+	}	
+}
+
+fn hashit(sha: usize, a: &[u8],n: usize,b: Option<&[u8]>,pad: usize,w: &mut [u8])  {
+	let mut r:[u8;64]=[0;64];
+	if sha==SHA256 {
+		let mut h=HASH256::new();
+		h.process_array(a);
+		if n>0 {h.process_num(n as i32)}
+		if let Some(x) = b {
+			h.process_array(x);
+        }
+        let hs=h.hash();	
+        for i in 0..sha {r[i]=hs[i];}	
+	}
+	if sha==SHA384 {
+		let mut h=HASH384::new();
+		h.process_array(a);
+		if n>0 {h.process_num(n as i32)}		
+		if let Some(x) = b {
+			h.process_array(x);
+        }
+        let hs=h.hash();	
+        for i in 0..sha {r[i]=hs[i];}	        
+	}
+	if sha==SHA512 {
+		let mut h=HASH512::new();
+		h.process_array(a);
+		if n>0 {h.process_num(n as i32)}
+		if let Some(x) = b {
+			h.process_array(x);
+        }
+        let hs=h.hash();
+        for i in 0..sha {r[i]=hs[i];}	        	
+	}
+
+	if pad==0 {
+		for i in 0..sha {w[i]=r[i]}
+	} else {
+
+		if pad<=sha {
+			for i in 0..pad {w[i]=r[i]}
+		} else {
+			for i in 0..sha {w[i+pad-sha]=r[i]}
+			for i in 0..(pad-sha) {w[i]=0}
+ 
+
+			//for i in 0..sha {w[i]=r[i]}
+			//for i in sha..pad {w[i]=0}
+		}
+	}
+}
+
+/* Key Derivation Functions */
+/* Input octet Z */
+/* Output key of length olen */
+pub fn kdf1(sha: usize,z: &[u8],olen: usize,k: &mut [u8])  {
+/* NOTE: the parameter olen is the length of the output K in bytes */
+	let hlen=sha;
+	let mut lk=0;
+
+	let mut cthreshold=olen/hlen; if olen%hlen!=0 {cthreshold+=1}
+
+	for counter in 0..cthreshold {
+		let mut b:[u8;64]=[0;64];
+		hashit(sha,z,counter,None,0,&mut b);
+		if lk+hlen>olen {
+			for i in 0..(olen%hlen) {k[lk]=b[i]; lk+=1}
+		} else {
+			for i in 0..hlen {k[lk]=b[i]; lk+=1}
+		}
+	}
+}
+
+pub fn kdf2(sha: usize,z: &[u8],p: Option<&[u8]>,olen: usize,k: &mut [u8])  {
+/* NOTE: the parameter olen is the length of the output K in bytes */
+	let hlen=sha;
+	let mut lk=0;
+
+	let mut cthreshold=olen/hlen; if olen%hlen!=0 {cthreshold+=1}
+
+	for counter in 1..cthreshold+1 {
+		let mut b:[u8;64]=[0;64];
+		hashit(sha,z,counter,p,0,&mut b);
+		if lk+hlen>olen {
+			for i in 0..(olen%hlen) {k[lk]=b[i]; lk+=1}
+		} else {
+			for i in 0..hlen {k[lk]=b[i]; lk+=1}
+		}
+	}
+}
+
+/* Password based Key Derivation Function */
+/* Input password p, salt s, and repeat count */
+/* Output key of length olen */
+pub fn pbkdf2(sha: usize,pass: &[u8],salt: &[u8],rep: usize,olen: usize,k: &mut [u8]) {
+	let mut d=olen/sha; if olen%sha!=0 {d+=1}
+	let mut f:[u8;64]=[0;64];
+	let mut u:[u8;64]=[0;64];
+	let mut ku:[u8;64]=[0;64];	
+	let mut s:[u8;36]=[0;36];    // Maximum salt of 32 bytes + 4
+	let mut n:[u8;4]=[0;4];
+
+	let sl=salt.len();
+	let mut kp=0;
+	for i in 0..d {
+		for j in 0..sl {s[j]=salt[j]} 
+		inttobytes(i+1,&mut n);
+		for j in 0..4 {s[sl+j]=n[j]}   
+
+		hmac(sha,&s[0..sl+4],pass,sha,&mut f);
+
+		for j in 0..sha {u[j]=f[j]}
+		for _ in 1..rep {
+			hmac(sha,&mut u,pass,sha,&mut ku);
+			for k in 0..sha {u[k]=ku[k]; f[k]^=u[k]}
+		}
+		for j in 0..EFS {if kp<olen {k[kp]=f[j]} kp+=1} 
+	}
+}
+
+/* Calculate HMAC of m using key k. HMAC is tag of length olen (which is length of tag) */
+pub fn hmac(sha: usize,m: &[u8],k: &[u8],olen: usize,tag: &mut [u8]) -> bool {
+	/* Input is from an octet m        *
+	* olen is requested output length in bytes. k is the key  *
+	* The output is the calculated tag */
+	let mut b:[u8;64]=[0;64];  /* Not good */
+	let mut k0:[u8;128]=[0;128];
+//	let olen=tag.len();    /* length of HMAC */
+
+	if olen<4 /*|| olen>sha */ {return false}
+
+	let mut lb=64;
+	if sha>32 {lb=128}
+
+	for i in 0..lb {k0[i]=0}
+
+	if k.len() > lb {
+		hashit(sha,k,0,None,0,&mut b); 
+		for i in 0..sha {k0[i]=b[i]}
+	} else {
+		for i in 0..k.len()  {k0[i]=k[i]}
+	}
+		
+	for i in 0..lb {k0[i]^=0x36}
+	hashit(sha,&mut k0[0..lb],0,Some(m),0,&mut b);
+
+	for i in 0..lb {k0[i]^=0x6a}
+	hashit(sha,&mut k0[0..lb],0,Some(&b[0..sha]),olen,tag); 
+
+	return true;
+}
+
+/* AES encryption/decryption. Encrypt byte array m using key k and returns ciphertext c */
+pub fn cbc_iv0_encrypt(k: &[u8],m: &[u8]) -> Vec<u8> { /* AES CBC encryption, with Null IV and key K */
+	/* Input is from an octet string m, output is to an octet string c */
+	/* Input is padded as necessary to make up a full final block */
+	let mut a=AES::new();	
+	let mut fin=false;
+	let mut c:Vec<u8>=Vec::new();
+
+	let mut buff:[u8;16]=[0;16];
+
+	a.init(aes::CBC,k.len(),k,None);
+
+	let mut ipt=0; 
+//	let mut opt=0;
+	let mut i;
+	loop {
+		i=0;
+		while i<16 {
+			if ipt<m.len() {
+				buff[i]=m[ipt]; i+=1; ipt+=1;
+			} else {fin=true; break;}
+		}
+		if fin {break}
+		a.encrypt(&mut buff);
+		for j in 0..16 {
+			c.push(buff[j]);
+			//c[opt]=buff[j]; opt+=1;
+		}
+	}    
+
+/* last block, filled up to i-th index */
+
+	let padlen=16-i;
+	for j in i..16 {buff[j]=padlen as u8}
+
+	a.encrypt(&mut buff);
+
+	for j in 0..16 {
+		c.push(buff[j]);
+		//c[opt]=buff[j]; opt+=1;
+	}
+	a.end();   
+	return c;
+}
+
+/* returns plaintext if all consistent, else returns null string */
+pub fn cbc_iv0_decrypt(k: &[u8],c: &[u8]) -> Option<Vec<u8>> { /* padding is removed */
+	let mut a=AES::new();	
+	let mut fin=false;
+	let mut m:Vec<u8>=Vec::new();
+
+	let mut buff:[u8;16]=[0;16];
+
+	a.init(aes::CBC,k.len(),k,None);
+
+	let mut ipt=0; 
+	//let mut opt=0;
+	let mut i;
+
+	if c.len()==0 {return None}
+	let mut ch=c[ipt]; ipt+=1;
+
+	loop {
+		i=0;
+		while i<16 {
+			buff[i]=ch;    
+			if ipt>=c.len() {
+				fin=true; break;
+			}  else {ch=c[ipt]; ipt+=1 }
+			i+=1;
+		}
+		a.decrypt(&mut buff);
+		if fin {break}
+		for j in 0..16 {
+			m.push(buff[j]);
+			//m[opt]=buff[j]; opt+=1;
+		}
+	}    
+
+	a.end();
+	let mut bad=false;
+	let padlen=buff[15] as usize;
+	if i!=15 || padlen<1 || padlen>16 {bad=true}
+	if padlen>=2 && padlen<=16 {
+		for j in 16-padlen..16 {
+			if buff[j]!=padlen as u8 {bad=true}
+		}
+	}
+    
+	if !bad { 
+		for i in 0..16-padlen {
+			m.push(buff[i]);
+			//m[opt]=buff[j]; opt+=1;
+		}
+	}
+
+	if bad {return None}
+	return Some(m);
+}
+
+/* Calculate a public/private EC GF(p) key pair w,s where W=s.G mod EC(p),
+ * where s is the secret key and W is the public key
+ * and G is fixed generator.
+ * If RNG is NULL then the private key is provided externally in s
+ * otherwise it is generated randomly internally */
+ #[allow(non_snake_case)]
+pub fn key_pair_generate(rng: Option<&mut RAND>,s: &mut [u8],w: &mut [u8]) -> isize {
+	let res=0;
+	let mut sc:BIG;
+	let G=ECP::generator();
+
+	let r=BIG::new_ints(&rom::CURVE_ORDER);
+
+	if let Some(mut x)=rng {
+		sc=BIG::randomnum(&r,&mut x);
+	} else {
+		sc=BIG::frombytes(&s);
+		sc.rmod(&r);		
+	}
+
+	//if rom::AES_S>0 {
+	//	sc.mod2m(2*rom::AES_S)
+	//}
+	sc.tobytes(s);
+
+	let WP=G.mul(&mut sc);
+
+	WP.tobytes(w,false);   // To use point compression on public keys, change to true 
+
+	return res;
+}
+
+/* validate public key */
+#[allow(non_snake_case)]
+pub fn public_key_validate(w: &[u8]) -> isize {
+	let mut WP=ECP::frombytes(w);
+	let mut res=0;
+
+	let r=BIG::new_ints(&rom::CURVE_ORDER);
+
+	if WP.is_infinity() {res=INVALID_PUBLIC_KEY}
+	if res==0  {
+
+		let q=BIG::new_ints(&rom::MODULUS);
+		let nb=q.nbits();
+		let mut k=BIG::new(); k.one(); k.shl((nb+4)/2);
+		k.add(&q);
+		k.div(&r);
+
+		while k.parity()==0 {
+				k.shr(1);
+				WP.dbl();
+		}
+
+		if !k.isunity() {WP=WP.mul(&mut k)}
+		if WP.is_infinity() {res=INVALID_PUBLIC_KEY} 		
+
+	}
+	return res;
+}
+
+/* IEEE-1363 Diffie-Hellman online calculation Z=S.WD */
+#[allow(non_snake_case)]
+pub fn ecpsvdp_dh(s: &[u8],wd: &[u8],z: &mut [u8]) -> isize {
+	let mut res=0;
+	let mut t:[u8;EFS]=[0;EFS];
+
+	let mut sc=BIG::frombytes(&s);
+
+	let mut W=ECP::frombytes(&wd);
+	if W.is_infinity() {res=ERROR}
+
+	if res==0 {
+		let r=BIG::new_ints(&rom::CURVE_ORDER);
+		sc.rmod(&r);
+		W=W.mul(&mut sc);
+		if W.is_infinity() { 
+			res=ERROR;
+		} else {
+			W.getx().tobytes(&mut t);
+			for i in 0..EFS {z[i]=t[i]}
+		}
+	}
+	return res;
+}
+
+/* IEEE ECDSA Signature, C and D are signature on F using private key S */
+#[allow(non_snake_case)]
+pub fn ecpsp_dsa(sha: usize,rng: &mut RAND,s: &[u8],f: &[u8],c: &mut [u8],d: &mut [u8]) -> isize {
+	let mut t:[u8;EFS]=[0;EFS];
+	let mut b:[u8;big::MODBYTES as usize]=[0;big::MODBYTES as usize];
+
+	hashit(sha,f,0,None,big::MODBYTES as usize,&mut b);
+
+	let G=ECP::generator();
+
+
+	let r=BIG::new_ints(&rom::CURVE_ORDER);
+
+	let mut sc=BIG::frombytes(s);  /* s or &s? */
+	let fb=BIG::frombytes(&b);
+
+	let mut cb=BIG::new();
+	let mut db=BIG::new();
+	let mut tb=BIG::new();	
+	let mut V=ECP::new();
+
+	while db.iszilch() {
+		let mut u=BIG::randomnum(&r,rng);
+		let mut w=BIG::randomnum(&r,rng);   /* side channel masking */
+		//if rom::AES_S>0 {
+		//	u.mod2m(2*rom::AES_S);
+		//}			
+		V.copy(&G);
+		V=V.mul(&mut u);   		
+		let vx=V.getx();
+		cb.copy(&vx);
+		cb.rmod(&r);
+		if cb.iszilch() {continue}
+
+		tb.copy(&BIG::modmul(&mut u,&mut w,&r));
+		u.copy(&tb);
+
+		u.invmodp(&r);
+		db.copy(&BIG::modmul(&mut sc,&mut cb,&r));
+		db.add(&fb);
+
+		tb.copy(&BIG::modmul(&mut db,&mut w,&r));
+		db.copy(&tb);
+
+		tb.copy(&BIG::modmul(&mut u,&mut db,&r));
+		db.copy(&tb);
+	} 
+       
+	cb.tobytes(&mut t);
+	for i in 0..EFS {c[i]=t[i]}
+	db.tobytes(&mut t);
+	for i in 0..EFS {d[i]=t[i]}
+	return 0;
+}
+
+/* IEEE1363 ECDSA Signature Verification. Signature C and D on F is verified using public key W */
+#[allow(non_snake_case)]
+pub fn ecpvp_dsa(sha: usize,w: &[u8],f: &[u8],c: &[u8],d: &[u8]) -> isize {
+	let mut res=0;
+
+	let mut b:[u8;big::MODBYTES as usize]=[0;big::MODBYTES as usize];
+
+	hashit(sha,f,0,None,big::MODBYTES as usize,&mut b);
+
+	let mut G=ECP::generator();
+
+	let r=BIG::new_ints(&rom::CURVE_ORDER);
+
+	let mut cb=BIG::frombytes(c);  /* c or &c ? */
+	let mut db=BIG::frombytes(d);  /* d or &d ? */
+	let mut fb=BIG::frombytes(&b);
+	let mut tb=BIG::new();		
+     
+	if cb.iszilch() || BIG::comp(&cb,&r)>=0 || db.iszilch() || BIG::comp(&db,&r)>=0 {
+            res=INVALID;
+	}
+
+	if res==0 {
+		db.invmodp(&r);
+		tb.copy(&BIG::modmul(&mut fb,&mut db,&r));
+		fb.copy(&tb);
+		let h2=BIG::modmul(&mut cb,&mut db,&r);
+
+		let WP=ECP::frombytes(&w);
+		if WP.is_infinity() {
+			res=ERROR;
+		} else {
+			let mut P=ECP::new();
+			P.copy(&WP);
+
+			P=P.mul2(&h2,&mut G,&fb);
+
+			if P.is_infinity() {
+				res=INVALID;
+			} else {
+				db=P.getx();
+				db.rmod(&r);
+
+				if BIG::comp(&db,&cb)!=0 {res=INVALID}
+			}
+		}
+	}
+
+	return res;
+}
+
+/* IEEE1363 ECIES encryption. Encryption of plaintext M uses public key W and produces ciphertext V,C,T */
+#[allow(non_snake_case)]
+pub fn ecies_encrypt(sha: usize,p1: &[u8],p2: &[u8],rng: &mut RAND,w: &[u8],m: &[u8],v: &mut [u8],t: &mut [u8]) -> Option<Vec<u8>> { 
+	let mut z:[u8;EFS]=[0;EFS];
+	let mut k1:[u8;ecp::AESKEY]=[0;ecp::AESKEY];
+	let mut k2:[u8;ecp::AESKEY]=[0;ecp::AESKEY];
+	let mut u:[u8;EGS]=[0;EGS];
+	let mut vz:[u8;3*EFS+1]=[0;3*EFS+1];	
+	let mut k:[u8;2*ecp::AESKEY]=[0;2*ecp::AESKEY];
+
+	if key_pair_generate(Some(rng),&mut u,v)!=0 {return None}
+	if ecpsvdp_dh(&u,&w,&mut z)!=0 {return None}     
+
+	for i in 0..2*EFS+1 {vz[i]=v[i]}
+	for i in 0..EFS {vz[2*EFS+1+i]=z[i]}
+
+	kdf2(sha,&vz,Some(p1),2*ecp::AESKEY,&mut k);
+
+	for i in 0..ecp::AESKEY {k1[i]=k[i]; k2[i]=k[ecp::AESKEY+i]} 
+
+	let mut c=cbc_iv0_encrypt(&k1,m);
+
+	let mut l2:[u8;8]=[0;8];
+	let p2l=p2.len();
+
+	inttobytes(p2l,&mut l2);	
+
+	for i in 0..p2l {
+		c.push(p2[i]);
+	}
+	for i in 0..8 {
+		c.push(l2[i]);
+	}
+
+	hmac(sha,&c,&k2,t.len(),t);
+
+	for _ in 0..p2l+8 {c.pop();}
+	
+	return Some(c);
+}
+
+/* constant time n-byte compare */
+fn ncomp(t1: &[u8],t2: &[u8],n: usize) -> bool {
+	let mut res=0;
+	for i in 0..n {
+		res|=(t1[i]^t2[i]) as isize;
+	}
+	if res==0 {return true;}
+	return false;
+}
+
+/* IEEE1363 ECIES decryption. Decryption of ciphertext V,C,T using private key U outputs plaintext M */
+#[allow(non_snake_case)]
+pub fn ecies_decrypt(sha: usize,p1: &[u8],p2: &[u8],v: &[u8],c: &mut Vec<u8>,t: &[u8],u: &[u8]) -> Option<Vec<u8>>  { 
+	let mut z:[u8;EFS]=[0;EFS];
+	let mut k1:[u8;ecp::AESKEY]=[0;ecp::AESKEY];
+	let mut k2:[u8;ecp::AESKEY]=[0;ecp::AESKEY];
+	let mut vz:[u8;3*EFS+1]=[0;3*EFS+1];	
+	let mut k:[u8;2*ecp::AESKEY]=[0;2*ecp::AESKEY];
+
+	let mut tag:[u8;32]=[0;32];  /* 32 is max length of tag */
+
+	for i in 0..t.len() {tag[i]=t[i]}
+
+	if ecpsvdp_dh(&u,&v,&mut z)!=0 {return None}
+
+	for i in 0..2*EFS+1 {vz[i]=v[i]}
+	for i in 0..EFS {vz[2*EFS+1+i]=z[i]}
+
+	kdf2(sha,&vz,Some(p1),2*ecp::AESKEY,&mut k);
+
+	for i in 0..ecp::AESKEY {k1[i]=k[i]; k2[i]=k[ecp::AESKEY+i]} 
+
+	let m=cbc_iv0_decrypt(&k1,&c);
+
+	if m==None {return None}
+
+	let mut l2:[u8;8]=[0;8];
+	let p2l=p2.len();
+
+	inttobytes(p2l,&mut l2);	
+
+	for i in 0..p2l {
+		c.push(p2[i]);
+	}
+	for i in 0..8 {
+		c.push(l2[i]);
+	}
+
+	hmac(sha,&c,&k2,t.len(),&mut tag);
+
+	for _ in 0..p2l+8 {c.pop();}
+
+	if !ncomp(&t,&tag,t.len()) {return None}
+
+	//let mut same=true;
+	//for i in 0..t.len() {
+	//	if t[i]!=tag[i] {same=false}
+	//}
+	//if !same {return None}
+	
+	return m;
+}
+
diff --git a/version3/rust/ecp.rs b/version3/rust/ecp.rs
new file mode 100644
index 0000000..7c2509a
--- /dev/null
+++ b/version3/rust/ecp.rs
@@ -0,0 +1,1065 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use xxx::fp::FP;
+use xxx::big::BIG;
+use xxx::big;
+use xxx::rom;
+
+pub struct ECP {
+	x:FP,
+	y:FP,
+	z:FP,
+//	inf: bool
+}
+
+pub const WEIERSTRASS:usize=0;
+pub const EDWARDS:usize=1;
+pub const MONTGOMERY:usize=2;
+pub const NOT: usize=0;
+pub const BN: usize=1;
+pub const BLS: usize=2;
+pub const D_TYPE: usize=0;
+pub const M_TYPE: usize=1;
+pub const POSITIVEX: usize=0;
+pub const NEGATIVEX: usize=1;
+
+pub const CURVETYPE:usize=@CT@;
+pub const CURVE_PAIRING_TYPE:usize=@PF@;
+pub const SEXTIC_TWIST:usize=@ST@;
+pub const SIGN_OF_X:usize=@SX@;
+
+pub const HASH_TYPE:usize=@HT@;
+pub const AESKEY:usize=@AK@;
+
+#[allow(non_snake_case)]
+impl ECP {
+
+	pub fn pnew() -> ECP {
+		ECP {
+				x: FP::new(),
+				y: FP::new_int(1),
+				z: FP::new(),
+//				inf: true
+		}
+
+	}
+
+	pub fn new() -> ECP {
+		let mut E=ECP::pnew();
+		if CURVETYPE==EDWARDS {
+			E.z.one();
+		}
+		return E;
+	}
+
+/* set (x,y) from two BIGs */
+	pub fn new_bigs(ix: &BIG,iy: &BIG) -> ECP {
+		let mut E=ECP::new();
+		E.x.bcopy(ix); 
+		E.y.bcopy(iy); 
+		E.z.one(); 
+		E.x.norm();
+		let mut rhs=ECP::rhs(&E.x);
+		if CURVETYPE==MONTGOMERY {
+			if rhs.jacobi()==1 {
+			//	E.inf=false;
+			} else {E.inf()}
+		} else {
+			let mut y2=FP::new_copy(&E.y);
+			y2.sqr();	
+			if y2.equals(&mut rhs) {
+			//	E.inf=false
+			} else {E.inf()}
+		}
+		return E;
+	}
+
+/* set (x,y) from BIG and a bit */
+	pub fn new_bigint(ix: &BIG,s: isize) -> ECP {
+		let mut E=ECP::new();
+		E.x.bcopy(ix); 
+		E.x.norm();
+		E.z.one(); 
+
+		let mut rhs=ECP::rhs(&E.x);
+
+		if rhs.jacobi()==1 {
+			let mut ny=rhs.sqrt();
+			if ny.redc().parity()!=s {ny.neg()}
+			E.y.copy(&ny);
+		//	E.inf=false;
+		} else {E.inf()}
+		return E;
+	}
+
+#[allow(non_snake_case)]
+/* set from x - calculate y from curve equation */
+	pub fn new_big(ix: &BIG) -> ECP {
+		let mut E=ECP::new();
+		E.x.bcopy(ix); 
+		E.x.norm();
+		E.z.one(); 
+		let mut rhs=ECP::rhs(&E.x);
+		if rhs.jacobi()==1 {
+			if CURVETYPE!=MONTGOMERY {E.y.copy(&rhs.sqrt())}
+		//	E.inf=false;
+		} else {E.inf();}
+		return E;
+	}
+
+/* set this=O */
+	pub fn inf(&mut self) {
+	//	self.inf=true;
+		self.x.zero();
+		if CURVETYPE!=MONTGOMERY {
+			self.y.one();
+		}
+		if CURVETYPE!=EDWARDS {
+			self.z.zero();
+		} else {self.z.one()}
+	}
+
+/* Calculate RHS of curve equation */
+	fn rhs(x: &FP) -> FP {
+		//x.norm();
+		let mut r=FP::new_copy(x);
+		r.sqr();
+
+		if CURVETYPE==WEIERSTRASS { // x^3+Ax+B
+			let b=FP::new_big(&BIG::new_ints(&rom::CURVE_B));
+			r.mul(x);
+			if rom::CURVE_A==-3 {
+				let mut cx=FP::new_copy(x);
+				cx.imul(3);
+				cx.neg(); cx.norm();
+				r.add(&cx);
+			}
+			r.add(&b);
+		}
+		if CURVETYPE==EDWARDS { // (Ax^2-1)/(Bx^2-1) 
+			let mut b=FP::new_big(&BIG::new_ints(&rom::CURVE_B));
+			let one=FP::new_int(1);
+			b.mul(&r);
+			b.sub(&one);
+			b.norm();
+			if rom::CURVE_A==-1 {r.neg()}
+			r.sub(&one); r.norm();
+			b.inverse();
+			r.mul(&b);
+		}
+		if CURVETYPE==MONTGOMERY { // x^3+Ax^2+x
+			let mut x3=FP::new();
+			x3.copy(&r);
+			x3.mul(x);
+			r.imul(rom::CURVE_A);
+			r.add(&x3);
+			r.add(&x);
+		}
+		r.reduce();
+		return r;
+	}
+
+/* test for O point-at-infinity */
+	pub fn is_infinity(&self) -> bool {
+	//	if self.inf {return true}
+		let xx=FP::new_copy(&self.x);
+		let zz=FP::new_copy(&self.z);
+
+		if CURVETYPE==EDWARDS {
+			let yy=FP::new_copy(&self.y);
+			return xx.iszilch() && yy.equals(&zz);
+		}
+		if CURVETYPE==WEIERSTRASS {
+			return xx.iszilch() && zz.iszilch();
+		}
+		if CURVETYPE==MONTGOMERY {
+			return zz.iszilch();
+		}
+		return true;
+ 	}
+
+/* Conditional swap of P and Q dependant on d */
+	pub fn cswap(&mut self,Q: &mut ECP,d: isize) {
+		self.x.cswap(&mut Q.x,d);
+		if CURVETYPE!=MONTGOMERY {self.y.cswap(&mut Q.y,d)}
+		self.z.cswap(&mut Q.z,d);
+/*		
+		let mut bd=true;
+		if d==0 {bd=false}
+		bd=bd&&(self.inf!=Q.inf);
+		self.inf=bd!=self.inf;
+		Q.inf=bd!=Q.inf; */
+	}
+
+/* Conditional move of Q to P dependant on d */
+	pub fn cmove(&mut self,Q: &ECP,d: isize) {
+		self.x.cmove(&Q.x,d);
+		if CURVETYPE!=MONTGOMERY {self.y.cmove(&Q.y,d)}
+		self.z.cmove(&Q.z,d);
+	/*	
+		let mut bd=true;
+		if d==0 {bd=false}
+		self.inf=(self.inf!=((self.inf!=Q.inf)&&bd)); */
+	}
+
+/* return 1 if b==c, no branching */
+	fn teq(b: i32,c: i32) -> isize {
+		let mut x=b^c;
+		x-=1;  // if x=0, x now -1
+		return ((x>>31)&1) as isize;
+	}
+
+/* this=P */
+	pub fn copy(&mut self,P: & ECP) {
+		self.x.copy(&P.x);
+		if CURVETYPE!=MONTGOMERY {self.y.copy(&P.y)}
+		self.z.copy(&P.z);
+	//	self.inf=P.inf;
+}
+
+/* this=-this */
+	pub fn neg(&mut self) {
+	//	if self.is_infinity() {return}
+		if CURVETYPE==WEIERSTRASS {
+			self.y.neg(); self.y.norm();
+		}
+		if CURVETYPE==EDWARDS {
+			self.x.neg(); self.x.norm();
+		}
+		return;
+	}
+/* multiply x coordinate */
+	pub fn mulx(&mut self,c: &mut FP) {
+		self.x.mul(c);
+	}
+
+/* Constant time select from pre-computed table */
+	fn selector(&mut self, W: &[ECP],b: i32) {   // unsure about &[& syntax. An array of pointers I hope..
+		let mut MP=ECP::new();
+		let m=b>>31;
+		let mut babs=(b^m)-m;
+
+		babs=(babs-1)/2;
+
+		self.cmove(&W[0],ECP::teq(babs,0));  // conditional move
+		self.cmove(&W[1],ECP::teq(babs,1));
+		self.cmove(&W[2],ECP::teq(babs,2));
+		self.cmove(&W[3],ECP::teq(babs,3));
+		self.cmove(&W[4],ECP::teq(babs,4));
+		self.cmove(&W[5],ECP::teq(babs,5));
+		self.cmove(&W[6],ECP::teq(babs,6));
+		self.cmove(&W[7],ECP::teq(babs,7));
+ 
+		MP.copy(self);
+		MP.neg();
+		self.cmove(&MP,(m&1) as isize);
+	}
+
+/* Test P == Q */
+	pub fn equals(&mut self,Q: &mut ECP) -> bool {
+	//	if self.is_infinity() && Q.is_infinity() {return true}
+	//	if self.is_infinity() || Q.is_infinity() {return false}
+
+		let mut a=FP::new();
+		let mut b=FP::new();
+		a.copy(&self.x); a.mul(&Q.z); 
+		b.copy(&Q.x); b.mul(&self.z); 
+		if !a.equals(&mut b) {return false}
+		if CURVETYPE!=MONTGOMERY {
+			a.copy(&self.y); a.mul(&Q.z); 
+			b.copy(&Q.y); b.mul(&self.z); 
+			if !a.equals(&mut b) {return false}
+		}
+		return true;
+	}
+
+/* set to affine - from (x,y,z) to (x,y) */
+	pub fn affine(&mut self) {
+		if self.is_infinity() { return}
+		let mut one=FP::new_int(1);
+		if self.z.equals(&mut one) {return}
+		self.z.inverse();
+
+		self.x.mul(&self.z); self.x.reduce();
+		if CURVETYPE!=MONTGOMERY {
+			self.y.mul(&self.z); self.y.reduce();
+		}
+		self.z.copy(&one);
+	}
+
+/* extract x as a BIG */
+	pub fn getx(&self) -> BIG {
+		let mut W=ECP::new(); W.copy(self);
+		W.affine();
+		return W.x.redc();
+	}
+
+/* extract y as a BIG */
+	pub fn gety(&self) -> BIG {
+		let mut W=ECP::new(); W.copy(self);
+		W.affine();
+		return W.y.redc();
+	}
+
+/* get sign of Y */
+	pub fn gets(&self) -> isize {
+		let y=self.gety();
+		return y.parity();
+	}
+
+/* extract x as an FP */
+	pub fn getpx(&self) -> FP {
+		let w=FP::new_copy(&self.x);
+		return w;
+	}
+/* extract y as an FP */
+	pub fn getpy(&self) -> FP {
+		let w=FP::new_copy(&self.y);
+		return w;
+	}
+
+/* extract z as an FP */
+	pub fn getpz(&self) -> FP {
+		let w=FP::new_copy(&self.z);
+		return w;
+	}
+
+/* convert to byte array */
+	pub fn tobytes(&self,b: &mut [u8],compress: bool) {
+		let mb=big::MODBYTES as usize;
+		let mut t:[u8;big::MODBYTES as usize]=[0;big::MODBYTES as usize];
+		let mut W=ECP::new(); W.copy(self);
+
+		W.affine();
+		W.x.redc().tobytes(&mut t);
+		for i in 0..mb {b[i+1]=t[i]}
+
+		if CURVETYPE==MONTGOMERY {
+			b[0]=0x06;
+			return;
+		} 
+	
+		if compress {
+			b[0]=0x02;
+			if W.y.redc().parity()==1 {b[0]=0x03}
+			return;
+		}
+
+		b[0]=0x04;
+		
+		W.y.redc().tobytes(&mut t);
+		for i in 0..mb {b[i+mb+1]=t[i]}
+	}
+
+/* convert from byte array to point */
+	pub fn frombytes(b: &[u8]) -> ECP {
+		let mut t:[u8;big::MODBYTES as usize]=[0;big::MODBYTES as usize];
+		let mb=big::MODBYTES as usize;
+		let p=BIG::new_ints(&rom::MODULUS);
+
+		for i in 0..mb {t[i]=b[i+1]}
+		let px=BIG::frombytes(&t);
+		if BIG::comp(&px,&p)>=0 {return ECP::new()}
+
+		if CURVETYPE==MONTGOMERY {
+			return ECP::new_big(&px)
+		}
+
+		if b[0]==0x04 {
+			for i in 0..mb {t[i]=b[i+mb+1]}
+			let py=BIG::frombytes(&t);
+			if BIG::comp(&py,&p)>=0 {return ECP::new()}
+			return ECP::new_bigs(&px,&py);
+		} 
+
+		if b[0]==0x02 || b[0]==0x03 {
+			return ECP::new_bigint(&px,(b[0]&1) as isize)
+		}
+
+		return ECP::new()
+	}
+
+/* convert to hex string */
+	pub fn tostring(&self) -> String {
+		let mut W=ECP::new(); W.copy(self);
+	 	if W.is_infinity() {return String::from("infinity")}
+		//self.affine();
+		if CURVETYPE==MONTGOMERY {
+			return format!("({})",W.x.redc().tostring());
+		} else {return format!("({},{})",W.x.redc().tostring(),W.y.redc().tostring())} ; 
+	}
+
+/* this*=2 */
+	pub fn dbl(&mut self) {
+	//	if self.inf {return}
+
+		if CURVETYPE==WEIERSTRASS {
+
+			if rom::CURVE_A==0 {
+				let mut t0=FP::new_copy(&self.y);     
+				t0.sqr();
+				let mut t1=FP::new_copy(&self.y);
+				t1.mul(&self.z);
+				let mut t2=FP::new_copy(&self.z);
+				t2.sqr();
+
+				self.z.copy(&t0);
+				self.z.add(&t0); self.z.norm(); 
+				self.z.dbl(); self.z.dbl(); self.z.norm();
+				t2.imul(3*rom::CURVE_B_I);
+
+				let mut x3=FP::new_copy(&t2);
+				x3.mul(&self.z);
+
+				let mut y3=FP::new_copy(&t0);
+				y3.add(&t2); y3.norm();
+				self.z.mul(&t1); 
+				t1.copy(&t2); t1.add(&t2); t2.add(&t1);
+				t0.sub(&t2); t0.norm(); y3.mul(&t0); y3.add(&x3);
+				t1.copy(&self.x); t1.mul(&self.y); 
+				self.x.copy(&t0); self.x.norm(); self.x.mul(&t1); self.x.dbl();
+				self.x.norm(); 
+				self.y.copy(&y3); self.y.norm();
+
+			} else {
+
+				let mut t0=FP::new_copy(&self.x);
+				let mut t1=FP::new_copy(&self.y);
+				let mut t2=FP::new_copy(&self.z);
+				let mut t3=FP::new_copy(&self.x);
+				let mut z3=FP::new_copy(&self.z);
+				let mut y3=FP::new();
+				let mut x3=FP::new();
+				let mut b=FP::new();
+
+				if rom::CURVE_B_I==0 {
+					b.copy(&FP::new_big(&BIG::new_ints(&rom::CURVE_B)));
+				}
+
+				t0.sqr();  //1    x^2
+				t1.sqr();  //2    y^2
+				t2.sqr();  //3
+
+				t3.mul(&self.y); //4
+				t3.dbl(); t3.norm();//5
+				z3.mul(&self.x);   //6
+				z3.dbl();  z3.norm();//7
+				y3.copy(&t2); 
+				
+				if rom::CURVE_B_I==0 {
+					y3.mul(&b); //8
+				} else {
+					y3.imul(rom::CURVE_B_I);
+				}
+				
+				y3.sub(&z3); //y3.norm(); //9  ***
+				x3.copy(&y3); x3.add(&y3); x3.norm();//10
+
+				y3.add(&x3); //y3.norm();//11
+				x3.copy(&t1); x3.sub(&y3); x3.norm();//12
+				y3.add(&t1); y3.norm();//13
+				y3.mul(&x3); //14
+				x3.mul(&t3); //15
+				t3.copy(&t2); t3.add(&t2); //t3.norm(); //16
+				t2.add(&t3); //t2.norm(); //17
+
+				if rom::CURVE_B_I==0 {
+					z3.mul(&b); //18
+				} else {
+					z3.imul(rom::CURVE_B_I);
+				}
+
+				z3.sub(&t2); //z3.norm();//19
+				z3.sub(&t0); z3.norm();//20  ***
+				t3.copy(&z3); t3.add(&z3); //t3.norm();//21
+
+				z3.add(&t3); z3.norm(); //22
+				t3.copy(&t0); t3.add(&t0); //t3.norm(); //23
+				t0.add(&t3); //t0.norm();//24
+				t0.sub(&t2); t0.norm();//25
+
+				t0.mul(&z3);//26
+				y3.add(&t0); //y3.norm();//27
+				t0.copy(&self.y); t0.mul(&self.z);//28
+				t0.dbl(); t0.norm(); //29
+				z3.mul(&t0);//30
+				x3.sub(&z3); //x3.norm();//31
+				t0.dbl(); t0.norm();//32
+				t1.dbl(); t1.norm();//33
+				z3.copy(&t0); z3.mul(&t1);//34
+
+				self.x.copy(&x3); self.x.norm(); 
+				self.y.copy(&y3); self.y.norm();
+				self.z.copy(&z3); self.z.norm();
+
+			}
+
+        }
+        if CURVETYPE==EDWARDS {
+            let mut c=FP::new_copy(&self.x);
+            let mut d=FP::new_copy(&self.y);
+            let mut h=FP::new_copy(&self.z);
+            let mut j=FP::new();
+    
+            self.x.mul(&self.y); self.x.dbl(); self.x.norm();
+            c.sqr();
+            d.sqr();
+            if rom::CURVE_A == -1 {c.neg()}
+            self.y.copy(&c); self.y.add(&d);
+            self.y.norm();
+            h.sqr(); h.dbl(); 
+            self.z.copy(&self.y);
+            j.copy(&self.y); j.sub(&h); j.norm();
+            self.x.mul(&j);
+            c.sub(&d); c.norm();
+            self.y.mul(&c);
+            self.z.mul(&j);
+    
+        //    self.x.norm();
+        //    self.y.norm();
+        //    self.z.norm();
+        }
+        if CURVETYPE==MONTGOMERY {
+            let mut a=FP::new_copy(&self.x);
+            let mut b=FP::new_copy(&self.x);
+            let mut aa=FP::new();
+            let mut bb=FP::new();
+            let mut c=FP::new();
+    
+    
+            a.add(&self.z); a.norm();
+            aa.copy(&a); aa.sqr();
+            b.sub(&self.z); b.norm();
+            bb.copy(&b); bb.sqr();
+            c.copy(&aa); c.sub(&bb); c.norm();
+    
+            self.x.copy(&aa); self.x.mul(&bb);
+    
+            a.copy(&c); a.imul((rom::CURVE_A+2)/4);
+    
+            bb.add(&a); bb.norm();
+            self.z.copy(&bb); self.z.mul(&c);
+ 
+        }
+        return;
+    }
+
+    /* self+=Q */
+    pub fn add(&mut self,Q:&ECP)
+    {
+    /*    if self.inf {
+			self.copy(&Q);
+			return;
+        }
+        if Q.inf {return}  */
+
+        if CURVETYPE==WEIERSTRASS {
+ 
+			if rom::CURVE_A==0 {
+				let b=3*rom::CURVE_B_I;
+				let mut t0=FP::new_copy(&self.x); 
+				t0.mul(&Q.x);
+				let mut t1=FP::new_copy(&self.y);
+				t1.mul(&Q.y);
+				let mut t2=FP::new_copy(&self.z);
+				t2.mul(&Q.z);
+				let mut t3=FP::new_copy(&self.x);
+				t3.add(&self.y); t3.norm();
+				let mut t4=FP::new_copy(&Q.x);
+				t4.add(&Q.y); t4.norm();
+				t3.mul(&t4);
+				t4.copy(&t0); t4.add(&t1);
+
+				t3.sub(&t4); t3.norm();
+				t4.copy(&self.y);
+				t4.add(&self.z); t4.norm();
+				let mut x3=FP::new_copy(&Q.y);
+				x3.add(&Q.z); x3.norm();
+
+				t4.mul(&x3);
+				x3.copy(&t1);
+				x3.add(&t2);
+	
+				t4.sub(&x3); t4.norm();
+				x3.copy(&self.x); x3.add(&self.z); x3.norm();
+				let mut y3=FP::new_copy(&Q.x);
+				y3.add(&Q.z); y3.norm();
+				x3.mul(&y3);
+				y3.copy(&t0);
+				y3.add(&t2);
+				y3.rsub(&x3); y3.norm();
+				x3.copy(&t0); x3.add(&t0); 
+				t0.add(&x3); t0.norm();
+				t2.imul(b);
+
+				let mut z3=FP::new_copy(&t1); z3.add(&t2); z3.norm();
+				t1.sub(&t2); t1.norm(); 
+				y3.imul(b);
+	
+				x3.copy(&y3); x3.mul(&t4); t2.copy(&t3); t2.mul(&t1); x3.rsub(&t2);
+				y3.mul(&t0); t1.mul(&z3); y3.add(&t1);
+				t0.mul(&t3); z3.mul(&t4); z3.add(&t0);
+
+				self.x.copy(&x3); self.x.norm(); 
+				self.y.copy(&y3); self.y.norm();
+				self.z.copy(&z3); self.z.norm();
+			} else {
+
+				let mut t0=FP::new_copy(&self.x);
+				let mut t1=FP::new_copy(&self.y);
+				let mut t2=FP::new_copy(&self.z);
+				let mut t3=FP::new_copy(&self.x);
+				let mut t4=FP::new_copy(&Q.x);
+				let mut z3=FP::new();
+				let mut y3=FP::new_copy(&Q.x);
+				let mut x3=FP::new_copy(&Q.y);
+				let mut b=FP::new();
+
+				if rom::CURVE_B_I==0 {
+					b.copy(&FP::new_big(&BIG::new_ints(&rom::CURVE_B)));
+				}
+
+				t0.mul(&Q.x); //1
+				t1.mul(&Q.y); //2
+				t2.mul(&Q.z); //3
+
+				t3.add(&self.y); t3.norm(); //4
+				t4.add(&Q.y); t4.norm();//5
+				t3.mul(&t4);//6
+				t4.copy(&t0); t4.add(&t1); //t4.norm(); //7
+				t3.sub(&t4); t3.norm(); //8
+				t4.copy(&self.y); t4.add(&self.z); t4.norm();//9
+				x3.add(&Q.z); x3.norm();//10
+				t4.mul(&x3); //11
+				x3.copy(&t1); x3.add(&t2); //x3.norm();//12
+
+				t4.sub(&x3); t4.norm();//13
+				x3.copy(&self.x); x3.add(&self.z); x3.norm(); //14
+				y3.add(&Q.z); y3.norm();//15
+
+				x3.mul(&y3); //16
+				y3.copy(&t0); y3.add(&t2); //y3.norm();//17
+
+				y3.rsub(&x3); y3.norm(); //18
+				z3.copy(&t2); 
+				
+
+				if rom::CURVE_B_I==0 {
+					z3.mul(&b); //18
+				} else {
+					z3.imul(rom::CURVE_B_I);
+				}
+				
+				x3.copy(&y3); x3.sub(&z3); x3.norm(); //20
+				z3.copy(&x3); z3.add(&x3); //z3.norm(); //21
+
+				x3.add(&z3); //x3.norm(); //22
+				z3.copy(&t1); z3.sub(&x3); z3.norm(); //23
+				x3.add(&t1); x3.norm(); //24
+
+				if rom::CURVE_B_I==0 {
+					y3.mul(&b); //18
+				} else {
+					y3.imul(rom::CURVE_B_I);
+				}
+
+				t1.copy(&t2); t1.add(&t2); //t1.norm();//26
+				t2.add(&t1); //t2.norm();//27
+
+				y3.sub(&t2); //y3.norm(); //28
+
+				y3.sub(&t0); y3.norm(); //29
+				t1.copy(&y3); t1.add(&y3); //t1.norm();//30
+				y3.add(&t1); y3.norm(); //31
+
+				t1.copy(&t0); t1.add(&t0); //t1.norm(); //32
+				t0.add(&t1); //t0.norm();//33
+				t0.sub(&t2); t0.norm();//34
+				t1.copy(&t4); t1.mul(&y3);//35
+				t2.copy(&t0); t2.mul(&y3);//36
+				y3.copy(&x3); y3.mul(&z3);//37
+				y3.add(&t2); //y3.norm();//38
+				x3.mul(&t3);//39
+				x3.sub(&t1);//40
+				z3.mul(&t4);//41
+				t1.copy(&t3); t1.mul(&t0);//42
+				z3.add(&t1); 
+				self.x.copy(&x3); self.x.norm(); 
+				self.y.copy(&y3); self.y.norm();
+				self.z.copy(&z3); self.z.norm();
+
+			}
+        }
+        if CURVETYPE==EDWARDS {
+            let bb=FP::new_big(&BIG::new_ints(&rom::CURVE_B));
+            let mut a=FP::new_copy(&self.z);
+            let mut b=FP::new();
+            let mut c=FP::new_copy(&self.x);
+            let mut d=FP::new_copy(&self.y);
+            let mut e=FP::new();
+            let mut f=FP::new();
+            let mut g=FP::new();
+    
+            a.mul(&Q.z);
+            b.copy(&a); b.sqr();
+            c.mul(&Q.x);
+            d.mul(&Q.y);
+    
+            e.copy(&c); e.mul(&d); e.mul(&bb);
+            f.copy(&b); f.sub(&e);
+            g.copy(&b); g.add(&e);
+    
+            if rom::CURVE_A==1 {
+				e.copy(&d); e.sub(&c);
+            }
+            c.add(&d);
+    
+            b.copy(&self.x); b.add(&self.y);
+            d.copy(&Q.x); d.add(&Q.y); 
+            b.norm(); d.norm();
+            b.mul(&d);
+            b.sub(&c);
+            b.norm(); f.norm();
+            b.mul(&f);
+            self.x.copy(&a); self.x.mul(&b);
+            g.norm();
+            if rom::CURVE_A==1 {
+				e.norm(); c.copy(&e); c.mul(&g);
+            }
+            if rom::CURVE_A == -1 {
+				c.norm(); c.mul(&g);
+            }
+            self.y.copy(&a); self.y.mul(&c);
+            self.z.copy(&f); self.z.mul(&g);
+        }
+        return;
+    }
+
+/* Differential Add for Montgomery curves. this+=Q where W is this-Q and is affine. */
+	pub fn dadd(&mut self,Q: &ECP,W: &ECP) {
+		let mut a=FP::new_copy(&self.x);
+		let mut b=FP::new_copy(&self.x);
+		let mut c=FP::new_copy(&Q.x);
+		let mut d=FP::new_copy(&Q.x);
+		let mut da=FP::new();
+		let mut cb=FP::new();
+			
+		a.add(&self.z);
+		b.sub(&self.z);
+
+		c.add(&Q.z);
+		d.sub(&Q.z);
+
+		a.norm(); d.norm();
+
+		da.copy(&d); da.mul(&a);
+
+		c.norm(); b.norm();
+
+		cb.copy(&c); cb.mul(&b);
+
+		a.copy(&da); a.add(&cb); a.norm(); a.sqr();
+		b.copy(&da); b.sub(&cb); b.norm(); b.sqr();
+
+		self.x.copy(&a);
+		self.z.copy(&W.x); self.z.mul(&b);
+	}
+
+/* self-=Q */
+	pub fn sub(&mut self,Q:&ECP) {
+		let mut NQ=ECP::new(); NQ.copy(Q);
+		NQ.neg();
+		self.add(&NQ);
+	}
+
+/* constant time multiply by small integer of length bts - use ladder */
+	pub fn pinmul(&self,e: i32,bts: i32) -> ECP {	
+		if CURVETYPE==MONTGOMERY {
+			return self.mul(&mut BIG::new_int(e as isize));
+		} else {
+			let mut P=ECP::new();
+			let mut R0=ECP::new();
+			let mut R1=ECP::new(); R1.copy(&self);
+
+			for i in (0..bts).rev() {
+				let b=((e>>i)&1) as isize;
+				P.copy(&R1);
+				P.add(&mut R0);
+				R0.cswap(&mut R1,b);
+				R1.copy(&P);
+				R0.dbl();
+				R0.cswap(&mut R1,b);
+			}
+			P.copy(&R0);
+			P.affine();
+			return P;
+		}
+	}
+
+/* return e.self */
+
+	pub fn mul(&self,e:&BIG) -> ECP {
+		if e.iszilch() || self.is_infinity() {return ECP::new()}
+		let mut P=ECP::new();
+		if CURVETYPE==MONTGOMERY {
+/* use Ladder */
+			let mut D=ECP::new();
+			let mut R0=ECP::new(); R0.copy(&self);
+			let mut R1=ECP::new(); R1.copy(&self);
+			R1.dbl();
+			D.copy(&self); D.affine();
+			let nb=e.nbits();
+
+			for i in (0..nb-1).rev() {
+				let b=e.bit(i);
+				P.copy(&R1);
+				P.dadd(&mut R0,&D);
+				R0.cswap(&mut R1,b);
+				R1.copy(&P);
+				R0.dbl();
+				R0.cswap(&mut R1,b);
+			}
+			P.copy(&R0)
+		} else {
+// fixed size windows 
+			let mut mt=BIG::new();
+			let mut t=BIG::new();
+			let mut Q=ECP::new();
+			let mut C=ECP::new();
+
+		 	let mut W:[ECP;8]=[ECP::new(),ECP::new(),ECP::new(),ECP::new(),ECP::new(),ECP::new(),ECP::new(),ECP::new()];
+
+		 	const CT:usize=1+(big::NLEN*(big::BASEBITS as usize)+3)/4;
+			let mut w:[i8;CT]=[0;CT];
+
+		//	self.affine();
+
+			Q.copy(&self);
+			Q.dbl();
+
+			W[0].copy(&self);
+
+			for i in 1..8 {
+				C.copy(&W[i-1]);
+				W[i].copy(&C);
+				W[i].add(&mut Q);
+			}
+
+// make exponent odd - add 2P if even, P if odd 
+			t.copy(&e);
+			let s=t.parity();
+			t.inc(1); t.norm(); let ns=t.parity(); mt.copy(&t); mt.inc(1); mt.norm();
+			t.cmove(&mt,s);
+			Q.cmove(&self,ns);
+			C.copy(&Q);
+
+			let nb=1+(t.nbits()+3)/4;
+
+// convert exponent to signed 4-bit window 
+			for i in 0..nb {
+				w[i]=(t.lastbits(5)-16) as i8;
+				t.dec(w[i] as isize); t.norm();
+				t.fshr(4);	
+			}
+			w[nb]=t.lastbits(5) as i8;
+
+			P.copy(&W[((w[nb] as usize)-1)/2]); 
+			for i in (0..nb).rev() {
+				Q.selector(&W,w[i] as i32);
+				P.dbl();
+				P.dbl();
+				P.dbl();
+				P.dbl();
+				P.add(&mut Q);
+			}
+			P.sub(&mut C); /* apply correction */
+		}
+		P.affine();
+		return P;
+	}
+
+/* Return e.this+f.Q */
+
+	pub fn mul2(&self,e: &BIG,Q: &ECP,f: &BIG) -> ECP {
+		let mut te=BIG::new();
+		let mut tf=BIG::new();
+		let mut mt=BIG::new();
+		let mut S=ECP::new();
+		let mut T=ECP::new();
+		let mut C=ECP::new();
+
+		let mut W:[ECP;8]=[ECP::new(),ECP::new(),ECP::new(),ECP::new(),ECP::new(),ECP::new(),ECP::new(),ECP::new()];
+
+		const CT:usize=1+(big::NLEN*(big::BASEBITS as usize)+1)/2;
+		let mut w: [i8;CT]=[0;CT];		
+
+	//	self.affine();
+	//	Q.affine();
+
+		te.copy(e);
+		tf.copy(f);
+
+// precompute table 
+
+		W[1].copy(&self); W[1].sub(Q);
+		W[2].copy(&self); W[2].add(Q);
+		S.copy(&Q); S.dbl();
+		C.copy(&W[1]); W[0].copy(&C); W[0].sub(&mut S); // copy to C is stupid Rust thing..
+		C.copy(&W[2]); W[3].copy(&C); W[3].add(&mut S);
+		T.copy(&self); T.dbl();
+		C.copy(&W[1]); W[5].copy(&C); W[5].add(&mut T);
+		C.copy(&W[2]); W[6].copy(&C); W[6].add(&mut T);
+		C.copy(&W[5]); W[4].copy(&C); W[4].sub(&mut S);
+		C.copy(&W[6]); W[7].copy(&C); W[7].add(&mut S);
+
+// if multiplier is odd, add 2, else add 1 to multiplier, and add 2P or P to correction 
+
+		let mut s=te.parity();
+		te.inc(1); te.norm(); let mut ns=te.parity(); mt.copy(&te); mt.inc(1); mt.norm();
+		te.cmove(&mt,s);
+		T.cmove(&self,ns);
+		C.copy(&T);
+
+		s=tf.parity();
+		tf.inc(1); tf.norm(); ns=tf.parity(); mt.copy(&tf); mt.inc(1); mt.norm();
+		tf.cmove(&mt,s);
+		S.cmove(&Q,ns);
+		C.add(&mut S);
+
+		mt.copy(&te); mt.add(&tf); mt.norm();
+		let nb=1+(mt.nbits()+1)/2;
+
+// convert exponent to signed 2-bit window 
+		for i in 0..nb {
+			let a=te.lastbits(3)-4;
+			te.dec(a); te.norm();
+			te.fshr(2);
+			let b=tf.lastbits(3)-4;
+			tf.dec(b); tf.norm();
+			tf.fshr(2);
+			w[i]=(4*a+b) as i8;
+		}
+		w[nb]=(4*te.lastbits(3)+tf.lastbits(3)) as i8;
+		S.copy(&W[((w[nb] as usize)-1)/2]);  
+
+		for i in (0..nb).rev() {
+			T.selector(&W,w[i] as i32);
+			S.dbl();
+			S.dbl();
+			S.add(&mut T);
+		}
+		S.sub(&mut C); /* apply correction */
+		S.affine();
+		return S;
+	}
+
+	pub fn cfp(&mut self) {
+		let cf=rom::CURVE_COF_I;
+		if cf==1 {return}
+		if cf==4 {
+			self.dbl(); self.dbl();
+			//self.affine();
+			return;
+		} 
+		if cf==8 {
+			self.dbl(); self.dbl(); self.dbl();
+			//self.affine();
+			return;
+		}
+		let c=BIG::new_ints(&rom::CURVE_COF);
+		let P=self.mul(&c);
+		self.copy(&P);	
+	}
+
+
+#[allow(non_snake_case)]
+	pub fn mapit(h: &[u8]) -> ECP {
+		let mut q=BIG::new_ints(&rom::MODULUS);
+		let mut x=BIG::frombytes(h);
+		x.rmod(&mut q);
+		let mut P:ECP;
+
+		loop {
+			loop {
+				if CURVETYPE!=MONTGOMERY {
+					P=ECP::new_bigint(&x,0);
+				} else {
+					P=ECP::new_big(&x);
+				}
+				x.inc(1); x.norm();
+				if !P.is_infinity() {break}
+			}
+			P.cfp();
+			if !P.is_infinity() {break}
+		}
+			
+		return P;	
+	}
+
+	pub fn generator() -> ECP {
+		let G:ECP;
+
+		let gx=BIG::new_ints(&rom::CURVE_GX);
+	
+		if CURVETYPE!=MONTGOMERY {
+			let gy=BIG::new_ints(&rom::CURVE_GY);
+			G=ECP::new_bigs(&gx,&gy);
+		} else {
+			G=ECP::new_big(&gx);
+		}
+		return G;		
+	}
+
+}
+/*
+fn main()
+{
+	let mut E=ECP::new();
+
+	let mut W:[&ECP;8]=[&ECP::new(),&ECP::new(),&ECP::new(),&ECP::new(),&ECP::new(),&ECP::new(),&ECP::new(),&ECP::new()];
+
+	let mut gx=BIG::new_ints(&rom::CURVE_GX);
+	let mut gy=BIG::new();
+	let mut P=ECP::new();
+
+	if CURVETYPE!=MONTGOMERY {gy.copy(&BIG::new_ints(&rom::CURVE_GY))}
+	let mut r=BIG::new_ints(&rom::CURVE_ORDER);
+
+	//r.dec(7);
+	
+	println!("gx= {}",gx.tostring());
+
+	if CURVETYPE!=MONTGOMERY {
+		println!("gy= {}",gy.tostring());
+	}	
+
+	if CURVETYPE!=MONTGOMERY {
+		P.copy(&ECP::new_bigs(&gx,&gy))}
+	else  {P.copy(&ECP::new_big(&gx))}
+
+	println!("P= {}",P.tostring());		
+
+	let mut R=P.mul(&mut r);
+		//for i in 0..10000	(R=P.mul(r));
+	
+	println!("R= {}",R.tostring());
+
+}
+*/
diff --git a/version3/rust/ecp2.rs b/version3/rust/ecp2.rs
new file mode 100644
index 0000000..4b0bb17
--- /dev/null
+++ b/version3/rust/ecp2.rs
@@ -0,0 +1,671 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use xxx::rom;
+use xxx::big;
+use xxx::ecp;
+use xxx::fp2::FP2;
+use xxx::big::BIG;
+
+//#[derive(Copy, Clone)]
+pub struct ECP2 {
+	x:FP2,
+	y:FP2,
+	z:FP2,
+//	inf: bool
+}
+
+#[allow(non_snake_case)]
+impl ECP2 {
+
+	pub fn new() -> ECP2 {
+		ECP2 {
+				x: FP2::new(),
+				y: FP2::new_int(1),
+				z: FP2::new(),
+//				inf: true
+		}
+	}
+#[allow(non_snake_case)]
+/* construct this from (x,y) - but set to O if not on curve */
+	pub fn new_fp2s(ix:&FP2,iy:&FP2) -> ECP2 {
+		let mut E=ECP2::new();
+		E.x.copy(&ix);
+		E.y.copy(&iy);
+		E.z.one();
+		E.x.norm();
+
+		let mut rhs=ECP2::rhs(&E.x);
+		let mut y2=FP2::new_copy(&E.y);
+		y2.sqr();
+		if !y2.equals(&mut rhs) {
+			E.inf();
+		}
+		return E;
+}
+
+/* construct this from x - but set to O if not on curve */
+	pub fn new_fp2(ix:&FP2) -> ECP2 {	
+		let mut E=ECP2::new();
+		E.x.copy(&ix);
+		E.y.one();
+		E.z.one();
+		E.x.norm();
+		let mut rhs=ECP2::rhs(&E.x);
+		if rhs.sqrt() {
+			E.y.copy(&rhs);
+		//	E.inf=false;
+		} else {E.inf();}
+		return E;
+	}
+
+/* Test this=O? */
+	pub fn is_infinity(&self) -> bool {
+	//	if self.inf {return true}
+		let xx=FP2::new_copy(&self.x);
+		let zz=FP2::new_copy(&self.z);
+		return xx.iszilch() && zz.iszilch();
+	}
+
+/* copy self=P */
+	pub fn copy(&mut self,P: &ECP2) {
+		self.x.copy(&P.x);
+		self.y.copy(&P.y);
+		self.z.copy(&P.z);
+	//	self.inf=P.inf;
+	}
+
+/* set self=O */
+	pub fn inf(&mut self) {
+	//	self.inf=true;
+		self.x.zero();
+		self.y.one();
+		self.z.zero();
+	}
+
+/* set self=-self */
+	pub fn neg(&mut self) {
+	//	if self.is_infinity() {return}
+		self.y.norm(); self.y.neg(); self.y.norm();
+	}	
+
+/* Conditional move of Q to self dependant on d */
+	pub fn cmove(&mut self,Q: &ECP2,d: isize) {
+		self.x.cmove(&Q.x,d);
+		self.y.cmove(&Q.y,d);
+		self.z.cmove(&Q.z,d);
+/*
+		let bd:bool;
+		if d==0 {bd=false}
+		else {bd=true}
+
+		self.inf=(self.inf!=(self.inf!=Q.inf)&&bd); */
+	}
+
+/* return 1 if b==c, no branching */
+	fn teq(b: i32,c: i32) -> isize {
+		let mut x=b^c;
+		x-=1;  // if x=0, x now -1
+		return ((x>>31)&1) as isize;
+	}
+
+/* Constant time select from pre-computed table */
+	pub fn selector(&mut self,W: &[ECP2],b: i32) {
+		let mut MP=ECP2::new(); 
+		let m=b>>31;
+		let mut babs=(b^m)-m;
+
+		babs=(babs-1)/2;
+
+		self.cmove(&W[0],ECP2::teq(babs,0));  // conditional move
+		self.cmove(&W[1],ECP2::teq(babs,1));
+		self.cmove(&W[2],ECP2::teq(babs,2));
+		self.cmove(&W[3],ECP2::teq(babs,3));
+		self.cmove(&W[4],ECP2::teq(babs,4));
+		self.cmove(&W[5],ECP2::teq(babs,5));
+		self.cmove(&W[6],ECP2::teq(babs,6));
+		self.cmove(&W[7],ECP2::teq(babs,7));
+ 
+		MP.copy(self);
+		MP.neg();
+		self.cmove(&MP,(m&1) as isize);
+	}	
+
+/* Test if P == Q */
+	pub fn equals(&mut self,Q :&mut ECP2) -> bool {
+	//	if self.is_infinity() && Q.is_infinity() {return true}
+	//	if self.is_infinity() || Q.is_infinity() {return false}
+
+		let mut a=FP2::new_copy(&self.x);
+		let mut b=FP2::new_copy(&Q.x); 
+
+		a.mul(&Q.z);
+		b.mul(&self.z);
+		if !a.equals(&mut b) {return false}
+		a.copy(&self.y); a.mul(&Q.z);
+		b.copy(&Q.y); b.mul(&self.z);
+		if !a.equals(&mut b) {return false}
+
+		return true;
+	}
+
+/* set to Affine - (x,y,z) to (x,y) */
+	pub fn affine(&mut self) {
+		if self.is_infinity() {return}
+		let mut one=FP2::new_int(1);
+		if self.z.equals(&mut one) {return}
+		self.z.inverse();
+
+		self.x.mul(&self.z); self.x.reduce(); 
+		self.y.mul(&self.z); self.y.reduce();
+		self.z.copy(&one);
+	}
+
+/* extract affine x as FP2 */
+	pub fn getx(&self) -> FP2 {
+		let mut W=ECP2::new(); W.copy(self);
+		W.affine();
+		return FP2::new_copy(&W.x);
+	}
+
+/* extract affine y as FP2 */
+	pub fn gety(&self) -> FP2 {
+		let mut W=ECP2::new(); W.copy(self);
+		W.affine();
+		return FP2::new_copy(&W.y);
+	}
+
+/* extract projective x */
+	pub fn getpx(&self) -> FP2 {
+		return FP2::new_copy(&self.x);
+	}
+/* extract projective y */
+	pub fn getpy(&self) -> FP2 {
+		return FP2::new_copy(&self.y);
+	}
+/* extract projective z */
+	pub fn getpz(&self) -> FP2 {
+		return FP2::new_copy(&self.z);
+	}
+
+/* convert to byte array */
+	pub fn tobytes(&self,b: &mut [u8]) {
+		let mut t:[u8;big::MODBYTES as usize]=[0;big::MODBYTES as usize];
+		let mb=big::MODBYTES as usize;
+		let mut W=ECP2::new(); W.copy(self);
+
+		W.affine();
+		W.x.geta().tobytes(&mut t);
+		for i in 0..mb { b[i]=t[i]}
+		W.x.getb().tobytes(&mut t);
+		for i in 0..mb { b[i+mb]=t[i]}
+
+		W.y.geta().tobytes(&mut t);
+		for i in 0..mb {b[i+2*mb]=t[i]}
+		W.y.getb().tobytes(&mut t);
+		for i in 0..mb {b[i+3*mb]=t[i]}
+	}
+
+/* convert from byte array to point */
+	pub fn frombytes(b: &[u8]) -> ECP2 {
+		let mut t:[u8;big::MODBYTES as usize]=[0;big::MODBYTES as usize];
+		let mb=big::MODBYTES as usize;
+
+		for i in 0..mb {t[i]=b[i]}
+		let mut ra=BIG::frombytes(&t);
+		for i in 0..mb {t[i]=b[i+mb]}
+		let mut rb=BIG::frombytes(&t);
+		let rx=FP2::new_bigs(&ra,&rb);
+
+		for i in 0..mb {t[i]=b[i+2*mb]}
+		ra.copy(&BIG::frombytes(&t));
+		for i in 0..mb {t[i]=b[i+3*mb]}
+		rb.copy(&BIG::frombytes(&t));
+		let ry=FP2::new_bigs(&ra,&rb);
+
+		return ECP2::new_fp2s(&rx,&ry);
+	}
+
+/* convert this to hex string */
+	pub fn tostring(&self) -> String {
+		let mut W=ECP2::new(); W.copy(self); W.affine();
+		if W.is_infinity() {return String::from("infinity")}
+		//self.affine();
+		return format!("({},{})",W.x.tostring(),W.y.tostring());
+}	
+
+/* Calculate RHS of twisted curve equation x^3+B/i */
+	pub fn rhs(x:&FP2) -> FP2 {
+		//x.norm();
+		let mut r=FP2::new_copy(x);
+		r.sqr();
+		let mut b=FP2::new_big(&BIG::new_ints(&rom::CURVE_B));
+		if ecp::SEXTIC_TWIST==ecp::D_TYPE {
+			b.div_ip();
+		}
+		if ecp::SEXTIC_TWIST==ecp::M_TYPE {
+			b.norm();
+			b.mul_ip();
+			b.norm();
+		}
+
+		r.mul(x);
+		r.add(&b);
+
+		r.reduce();
+		return r;
+	}
+
+/* self+=self */
+	pub fn dbl(&mut self) -> isize {
+	//	if self.inf {return -1}
+
+		let mut iy=FP2::new_copy(&self.y);
+		if ecp::SEXTIC_TWIST==ecp::D_TYPE {		
+			iy.mul_ip(); iy.norm();
+		}
+
+		let mut t0=FP2::new_copy(&self.y);                  //***** Change 
+		t0.sqr();
+		if ecp::SEXTIC_TWIST==ecp::D_TYPE {		  
+			t0.mul_ip();
+		}   
+		let mut t1=FP2::new_copy(&iy);  
+		t1.mul(&self.z);
+		let mut t2=FP2::new_copy(&self.z);
+		t2.sqr();
+
+		self.z.copy(&t0);
+		self.z.add(&t0); self.z.norm(); 
+		self.z.dbl(); 
+		self.z.dbl(); 
+		self.z.norm();  
+
+		t2.imul(3*rom::CURVE_B_I); 
+		if ecp::SEXTIC_TWIST==ecp::M_TYPE {	
+			t2.mul_ip();
+			t2.norm();	
+		}
+		let mut x3=FP2::new_copy(&t2);
+		x3.mul(&self.z); 
+
+		let mut y3=FP2::new_copy(&t0);   
+
+		y3.add(&t2); y3.norm();
+		self.z.mul(&t1);
+		t1.copy(&t2); t1.add(&t2); t2.add(&t1); t2.norm();  
+		t0.sub(&t2); t0.norm();                           //y^2-9bz^2
+		y3.mul(&t0); y3.add(&x3);                          //(y^2+3z*2)(y^2-9z^2)+3b.z^2.8y^2
+		t1.copy(&self.x); t1.mul(&iy);						//
+		self.x.copy(&t0); self.x.norm(); self.x.mul(&t1); self.x.dbl();       //(y^2-9bz^2)xy2
+
+		self.x.norm(); 
+		self.y.copy(&y3); self.y.norm();
+
+		return 1;
+
+	}
+
+/* self+=Q - return 0 for add, 1 for double, -1 for O */
+	pub fn add(&mut self,Q:&ECP2) -> isize {
+		/*if self.inf {
+			self.copy(Q);
+			return -1;
+		}
+		if Q.inf {return -1}*/
+
+
+		let b=3*rom::CURVE_B_I;
+		let mut t0=FP2::new_copy(&self.x);
+		t0.mul(&Q.x);         // x.Q.x
+		let mut t1=FP2::new_copy(&self.y);
+		t1.mul(&Q.y);		 // y.Q.y
+
+		let mut t2=FP2::new_copy(&self.z);
+		t2.mul(&Q.z);
+		let mut t3=FP2::new_copy(&self.x);
+		t3.add(&self.y); t3.norm();          //t3=X1+Y1
+		let mut t4=FP2::new_copy(&Q.x);            
+		t4.add(&Q.y); t4.norm();			//t4=X2+Y2
+		t3.mul(&t4);						//t3=(X1+Y1)(X2+Y2)
+		t4.copy(&t0); t4.add(&t1);		//t4=X1.X2+Y1.Y2
+
+		t3.sub(&t4); t3.norm(); 
+		if ecp::SEXTIC_TWIST==ecp::D_TYPE {
+			t3.mul_ip();  t3.norm();         //t3=(X1+Y1)(X2+Y2)-(X1.X2+Y1.Y2) = X1.Y2+X2.Y1
+		}
+		t4.copy(&self.y);                    
+		t4.add(&self.z); t4.norm();			//t4=Y1+Z1
+		let mut x3=FP2::new_copy(&Q.y);
+		x3.add(&Q.z); x3.norm();			//x3=Y2+Z2
+
+		t4.mul(&x3);						//t4=(Y1+Z1)(Y2+Z2)
+		x3.copy(&t1);					//
+		x3.add(&t2);						//X3=Y1.Y2+Z1.Z2
+	
+		t4.sub(&x3); t4.norm(); 
+		if ecp::SEXTIC_TWIST==ecp::D_TYPE {
+			t4.mul_ip(); t4.norm();          //t4=(Y1+Z1)(Y2+Z2) - (Y1.Y2+Z1.Z2) = Y1.Z2+Y2.Z1
+		}
+		x3.copy(&self.x); x3.add(&self.z); x3.norm();	// x3=X1+Z1
+		let mut y3=FP2::new_copy(&Q.x);				
+		y3.add(&Q.z); y3.norm();				// y3=X2+Z2
+		x3.mul(&y3);							// x3=(X1+Z1)(X2+Z2)
+		y3.copy(&t0);
+		y3.add(&t2);							// y3=X1.X2+Z1+Z2
+		y3.rsub(&x3); y3.norm();				// y3=(X1+Z1)(X2+Z2) - (X1.X2+Z1.Z2) = X1.Z2+X2.Z1
+
+		if ecp::SEXTIC_TWIST==ecp::D_TYPE {
+			t0.mul_ip(); t0.norm(); // x.Q.x
+			t1.mul_ip(); t1.norm(); // y.Q.y
+		}
+		x3.copy(&t0); x3.add(&t0); 
+		t0.add(&x3); t0.norm();
+		t2.imul(b); 	
+		if ecp::SEXTIC_TWIST==ecp::M_TYPE {	
+			t2.mul_ip(); t2.norm();
+		}
+		let mut z3=FP2::new_copy(&t1); z3.add(&t2); z3.norm();
+		t1.sub(&t2); t1.norm(); 
+		y3.imul(b); 
+		if ecp::SEXTIC_TWIST==ecp::M_TYPE {		
+			y3.mul_ip();
+			y3.norm();
+		}
+		x3.copy(&y3); x3.mul(&t4); t2.copy(&t3); t2.mul(&t1); x3.rsub(&t2);
+		y3.mul(&t0); t1.mul(&z3); y3.add(&t1);
+		t0.mul(&t3); z3.mul(&t4); z3.add(&t0);
+
+		self.x.copy(&x3); self.x.norm(); 
+		self.y.copy(&y3); self.y.norm();
+		self.z.copy(&z3); self.z.norm();
+
+		return 0;
+	}
+
+/* set this-=Q */
+	pub fn sub(&mut self,Q :&ECP2) -> isize {
+		let mut NQ=ECP2::new(); NQ.copy(Q);
+		NQ.neg();
+		let d=self.add(&NQ);
+		return d;
+	}
+
+/* set this*=q, where q is Modulus, using Frobenius */
+	pub fn frob(&mut self,x:&FP2) {
+	// 	if self.inf {return}
+		let mut x2=FP2::new_copy(x);
+		x2.sqr();
+		self.x.conj();
+		self.y.conj();
+		self.z.conj();
+		self.z.reduce();
+		self.x.mul(&x2);
+		self.y.mul(&x2);
+		self.y.mul(x);
+	}
+
+/* self*=e */
+	pub fn mul(&self,e: &BIG) -> ECP2 {
+/* fixed size windows */
+		let mut mt=BIG::new();
+		let mut t=BIG::new();
+		let mut P=ECP2::new();
+		let mut Q=ECP2::new();
+		let mut C=ECP2::new();
+
+		if self.is_infinity() {return P}
+
+		let mut W:[ECP2;8]=[ECP2::new(),ECP2::new(),ECP2::new(),ECP2::new(),ECP2::new(),ECP2::new(),ECP2::new(),ECP2::new()];
+
+		const CT:usize=1+(big::NLEN*(big::BASEBITS as usize)+3)/4;
+		let mut w:[i8;CT]=[0;CT]; 
+
+	//	self.affine();
+
+/* precompute table */
+		Q.copy(&self);
+		Q.dbl();
+		
+		W[0].copy(&self);
+
+		for i in 1..8 {
+			C.copy(&W[i-1]);
+			W[i].copy(&C);
+			W[i].add(&mut Q);
+		}
+
+/* make exponent odd - add 2P if even, P if odd */
+		t.copy(&e);
+		let s=t.parity();
+		t.inc(1); t.norm(); let ns=t.parity(); mt.copy(&t); mt.inc(1); mt.norm();
+		t.cmove(&mt,s);
+		Q.cmove(&self,ns);
+		C.copy(&Q);
+
+		let nb=1+(t.nbits()+3)/4;
+
+/* convert exponent to signed 4-bit window */
+		for i in 0..nb {
+			w[i]=(t.lastbits(5)-16) as i8;
+			t.dec(w[i] as isize); t.norm();
+			t.fshr(4);	
+		}
+		w[nb]=(t.lastbits(5)) as i8;
+		
+		P.copy(&W[((w[nb] as usize) -1)/2]);
+		for i in (0..nb).rev() {
+			Q.selector(&W,w[i] as i32);
+			P.dbl();
+			P.dbl();
+			P.dbl();
+			P.dbl();
+			P.add(&mut Q);
+		}
+		P.sub(&mut C);
+		P.affine();
+		return P;
+	}
+
+
+/* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3 */
+// Bos & Costello https://eprint.iacr.org/2013/458.pdf
+// Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
+// Side channel attack secure 
+
+	pub fn mul4(Q: &mut [ECP2],u: &[BIG]) -> ECP2 {
+		let mut W=ECP2::new();
+		let mut P=ECP2::new();
+
+		let mut T:[ECP2;8]=[ECP2::new(),ECP2::new(),ECP2::new(),ECP2::new(),ECP2::new(),ECP2::new(),ECP2::new(),ECP2::new()];
+
+		let mut mt=BIG::new();
+
+		let mut t:[BIG;4]=[BIG::new_copy(&u[0]),BIG::new_copy(&u[1]),BIG::new_copy(&u[2]),BIG::new_copy(&u[3])];
+
+		const CT:usize=1+big::NLEN*(big::BASEBITS as usize);
+		let mut w:[i8;CT]=[0;CT];
+		let mut s:[i8;CT]=[0;CT];
+
+		for i in 0..4 {
+			//Q[i].affine();
+			t[i].norm();
+		}
+
+		T[0].copy(&Q[0]); W.copy(&T[0]);
+		T[1].copy(&W); T[1].add(&mut Q[1]);  // Q[0]+Q[1]
+		T[2].copy(&W); T[2].add(&mut Q[2]); W.copy(&T[1]); // Q[0]+Q[2]
+		T[3].copy(&W); T[3].add(&mut Q[2]);	W.copy(&T[0]); // Q[0]+Q[1]+Q[2]
+		T[4].copy(&W); T[4].add(&mut Q[3]); W.copy(&T[1]); // Q[0]+Q[3]
+		T[5].copy(&W); T[5].add(&mut Q[3]); W.copy(&T[2]); // Q[0]+Q[1]+Q[3]
+		T[6].copy(&W); T[6].add(&mut Q[3]); W.copy(&T[3]); // Q[0]+Q[2]+Q[3]
+		T[7].copy(&W); T[7].add(&mut Q[3]); // Q[0]+Q[1]+Q[2]+Q[3]
+
+// Make it odd
+		let pb=1-t[0].parity();
+		t[0].inc(pb);
+		t[0].norm();	
+
+// Number of bits
+		mt.zero();
+		for i in 0..4 {
+			mt.or(&t[i]);
+		}
+
+		let nb=1+mt.nbits();
+
+// Sign pivot 
+
+		s[nb-1]=1;
+		for i in 0..nb-1 {
+			t[0].fshr(1);
+			s[i]=(2*t[0].parity()-1) as i8;
+			//println!("s={}",s[i]);	
+		}
+
+// Recoded exponent
+		for i in 0..nb {
+			w[i]=0;
+			let mut k=1;
+			for j in 1..4 {
+				let bt=s[i]*(t[j].parity() as i8);
+				t[j].fshr(1);
+				t[j].dec((bt>>1) as isize);
+				t[j].norm();
+				w[i]+=bt*(k as i8);
+				k=2*k;
+			}
+		}	
+
+// Main loop
+		P.selector(&T,(2*w[nb-1]+1) as i32);
+		for i in (0..nb-1).rev() {
+
+			P.dbl();
+			W.selector(&T,(2*w[i]+s[i]) as i32);
+			P.add(&mut W);
+		}		
+
+// apply correction
+		W.copy(&P);   
+		W.sub(&mut Q[0]);
+		P.cmove(&W,pb);	
+		P.affine();
+
+		return P;
+	}
+
+
+#[allow(non_snake_case)]
+	pub fn mapit(h: &[u8]) -> ECP2 {
+		let mut q=BIG::new_ints(&rom::MODULUS);
+		let mut x=BIG::frombytes(h);
+		x.rmod(&mut q);
+		let mut Q:ECP2;
+		let one=BIG::new_int(1);
+
+		loop {
+			let X=FP2::new_bigs(&one,&x);
+			Q=ECP2::new_fp2(&X);
+			if !Q.is_infinity() {break}
+			x.inc(1); x.norm();
+		}
+		let mut X = FP2::new_bigs(&BIG::new_ints(&rom::FRA),&BIG::new_ints(&rom::FRB));
+		if ecp::SEXTIC_TWIST==ecp::M_TYPE {
+			X.inverse();
+			X.norm();
+		}
+		x = BIG::new_ints(&rom::CURVE_BNX);
+
+		if ecp::CURVE_PAIRING_TYPE==ecp::BN {
+
+			let mut T=Q.mul(&mut x);
+			if ecp::SIGN_OF_X==ecp::NEGATIVEX {
+				T.neg();
+			}
+        		let mut K=ECP2::new(); K.copy(&T);
+        		K.dbl(); K.add(&T); 
+    
+        		K.frob(&X);
+        		Q.frob(&X); Q.frob(&X); Q.frob(&X);
+        		Q.add(&T); Q.add(&K);
+        		T.frob(&X); T.frob(&X);
+        		Q.add(&T);
+		}	
+		if ecp::CURVE_PAIRING_TYPE==ecp::BLS {
+
+        	let mut xQ=Q.mul(&mut x);
+        	let mut x2Q=xQ.mul(&mut x);
+
+			if ecp::SIGN_OF_X==ecp::NEGATIVEX {
+				xQ.neg();
+			}
+        	x2Q.sub(&xQ);
+        	x2Q.sub(&Q);
+
+        	xQ.sub(&Q);
+        	xQ.frob(&X);
+
+        	Q.dbl();
+        	Q.frob(&X);
+        	Q.frob(&X);
+
+        	Q.add(&x2Q);
+        	Q.add(&xQ);
+		}	
+
+		Q.affine();
+		return Q;
+	}
+
+	pub fn generator() -> ECP2 {
+		return ECP2::new_fp2s(&FP2::new_bigs(&BIG::new_ints(&rom::CURVE_PXA),&BIG::new_ints(&rom::CURVE_PXB)),&FP2::new_bigs(&BIG::new_ints(&rom::CURVE_PYA),&BIG::new_ints(&rom::CURVE_PYB)));
+	}
+
+}
+/*
+fn main()
+{
+	let mut r=BIG::new_ints(&rom::MODULUS);
+
+	let pxa=BIG::new_ints(&rom::CURVE_PXA);
+	let pxb=BIG::new_ints(&rom::CURVE_PXB);
+	let pya=BIG::new_ints(&rom::CURVE_PYA);
+	let pyb=BIG::new_ints(&rom::CURVE_PYB);
+
+	let fra=BIG::new_ints(&rom::CURVE_FRA);
+	let frb=BIG::new_ints(&rom::CURVE_FRB);
+
+	let mut f=FP2::new_bigs(&fra,&frb);
+
+	let px=FP2::new_bigs(&pxa,&pxb);
+	let py=FP2::new_bigs(&pya,&pyb);
+
+	let mut P=ECP2::new_fp2s(&px,&py);
+
+	println!("P= {}",P.tostring());
+
+	P=P.mul(&mut r);
+	println!("P= {}",P.tostring());
+
+	let mut  Q=ECP2::new_fp2s(&px,&py);
+	Q.frob(&mut f);
+	println!("Q= {}",Q.tostring());
+}
+*/
diff --git a/version3/rust/ecp4.rs b/version3/rust/ecp4.rs
new file mode 100644
index 0000000..011fc95
--- /dev/null
+++ b/version3/rust/ecp4.rs
@@ -0,0 +1,702 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use xxx::rom;
+use xxx::big;
+use xxx::ecp;
+use xxx::fp2::FP2;
+use xxx::fp4::FP4;
+use xxx::big::BIG;
+
+pub struct ECP4 {
+	x:FP4,
+	y:FP4,
+	z:FP4,
+}
+
+#[allow(non_snake_case)]
+impl ECP4 {
+
+	pub fn new() -> ECP4 {
+		ECP4 {
+				x: FP4::new(),
+				y: FP4::new_int(1),
+				z: FP4::new(),
+		}
+	}
+#[allow(non_snake_case)]
+/* construct this from (x,y) - but set to O if not on curve */
+	pub fn new_fp4s(ix:&FP4,iy:&FP4) -> ECP4 {
+		let mut E=ECP4::new();
+		E.x.copy(&ix);
+		E.y.copy(&iy);
+		E.z.one();
+		E.x.norm();
+
+		let mut rhs=ECP4::rhs(&E.x);
+		let mut y2=FP4::new_copy(&E.y);
+		y2.sqr();
+		if !y2.equals(&mut rhs) {
+			E.inf();
+		}
+		return E;
+}
+
+/* construct this from x - but set to O if not on curve */
+	pub fn new_fp4(ix:&FP4) -> ECP4 {	
+		let mut E=ECP4::new();
+		E.x.copy(&ix);
+		E.y.one();
+		E.z.one();
+		E.x.norm();
+
+		let mut rhs=ECP4::rhs(&E.x);
+		if rhs.sqrt() {
+			E.y.copy(&rhs);
+		} else {E.inf();}
+		return E;
+	}
+
+/* Test this=O? */
+	pub fn is_infinity(&self) -> bool {
+		let xx=FP4::new_copy(&self.x);
+		let zz=FP4::new_copy(&self.z);
+		return xx.iszilch() && zz.iszilch();
+	}
+
+/* copy self=P */
+	pub fn copy(&mut self,P: &ECP4) {
+		self.x.copy(&P.x);
+		self.y.copy(&P.y);
+		self.z.copy(&P.z);
+	}
+
+/* set self=O */
+	pub fn inf(&mut self) {
+		self.x.zero();
+		self.y.one();
+		self.z.zero();
+	}
+
+/* set self=-self */
+	pub fn neg(&mut self) {
+		self.y.norm(); self.y.neg(); self.y.norm();
+	}	
+
+/* Conditional move of Q to self dependant on d */
+	pub fn cmove(&mut self,Q: &ECP4,d: isize) {
+		self.x.cmove(&Q.x,d);
+		self.y.cmove(&Q.y,d);
+		self.z.cmove(&Q.z,d);
+	}
+
+/* return 1 if b==c, no branching */
+	fn teq(b: i32,c: i32) -> isize {
+		let mut x=b^c;
+		x-=1;  // if x=0, x now -1
+		return ((x>>31)&1) as isize;
+	}
+
+/* Constant time select from pre-computed table */
+	pub fn selector(&mut self,W: &[ECP4],b: i32) {
+		let mut MP=ECP4::new(); 
+		let m=b>>31;
+		let mut babs=(b^m)-m;
+
+		babs=(babs-1)/2;
+
+		self.cmove(&W[0],ECP4::teq(babs,0));  // conditional move
+		self.cmove(&W[1],ECP4::teq(babs,1));
+		self.cmove(&W[2],ECP4::teq(babs,2));
+		self.cmove(&W[3],ECP4::teq(babs,3));
+		self.cmove(&W[4],ECP4::teq(babs,4));
+		self.cmove(&W[5],ECP4::teq(babs,5));
+		self.cmove(&W[6],ECP4::teq(babs,6));
+		self.cmove(&W[7],ECP4::teq(babs,7));
+ 
+		MP.copy(self);
+		MP.neg();
+		self.cmove(&MP,(m&1) as isize);
+	}	
+
+/* Test if P == Q */
+	pub fn equals(&mut self,Q :&mut ECP4) -> bool {
+
+		let mut a=FP4::new_copy(&self.x);
+		let mut b=FP4::new_copy(&Q.x); 
+
+		a.mul(&Q.z);
+		b.mul(&self.z);
+		if !a.equals(&mut b) {return false}
+		a.copy(&self.y); a.mul(&Q.z);
+		b.copy(&Q.y); b.mul(&self.z);
+		if !a.equals(&mut b) {return false}
+
+		return true;
+	}
+
+/* set to Affine - (x,y,z) to (x,y) */
+	pub fn affine(&mut self) {
+		if self.is_infinity() {return}
+		let mut one=FP4::new_int(1);
+		if self.z.equals(&mut one) {return}
+		self.z.inverse();
+
+		self.x.mul(&self.z); self.x.reduce(); 
+		self.y.mul(&self.z); self.y.reduce();
+		self.z.copy(&one);
+	}
+
+/* extract affine x as FP4 */
+	pub fn getx(&self) -> FP4 {
+		let mut W=ECP4::new(); W.copy(self);
+		W.affine();
+		return FP4::new_copy(&self.x);
+	}
+
+/* extract affine y as FP4 */
+	pub fn gety(&self) -> FP4 {
+		let mut W=ECP4::new(); W.copy(self);
+		W.affine();
+		return FP4::new_copy(&W.y);
+	}
+
+/* extract projective x */
+	pub fn getpx(&self) -> FP4 {
+		return FP4::new_copy(&self.x);
+	}
+/* extract projective y */
+	pub fn getpy(&self) -> FP4 {
+		return FP4::new_copy(&self.y);
+	}
+/* extract projective z */
+	pub fn getpz(&self) -> FP4 {
+		return FP4::new_copy(&self.z);
+	}
+
+/* convert to byte array */
+	pub fn tobytes(&self,b: &mut [u8]) {
+		let mut t:[u8;big::MODBYTES as usize]=[0;big::MODBYTES as usize];
+		let mb=big::MODBYTES as usize;
+
+		let mut W=ECP4::new(); W.copy(self);
+
+		W.affine();
+
+		W.x.geta().geta().tobytes(&mut t);
+		for i in 0..mb { b[i]=t[i]}
+		W.x.geta().getb().tobytes(&mut t);
+		for i in 0..mb { b[i+mb]=t[i]}
+
+		W.x.getb().geta().tobytes(&mut t);
+		for i in 0..mb { b[i+2*mb]=t[i]}
+		W.x.getb().getb().tobytes(&mut t);
+		for i in 0..mb { b[i+3*mb]=t[i]}
+
+
+
+		W.y.geta().geta().tobytes(&mut t);
+		for i in 0..mb {b[i+4*mb]=t[i]}
+		W.y.geta().getb().tobytes(&mut t);
+		for i in 0..mb {b[i+5*mb]=t[i]}
+
+		W.y.getb().geta().tobytes(&mut t);
+		for i in 0..mb {b[i+6*mb]=t[i]}
+		W.y.getb().getb().tobytes(&mut t);
+		for i in 0..mb {b[i+7*mb]=t[i]}
+	}
+
+/* convert from byte array to point */
+	pub fn frombytes(b: &[u8]) -> ECP4 {
+		let mut t:[u8;big::MODBYTES as usize]=[0;big::MODBYTES as usize];
+		let mb=big::MODBYTES as usize;
+
+		for i in 0..mb {t[i]=b[i]}
+		let mut ra=BIG::frombytes(&t);
+		for i in 0..mb {t[i]=b[i+mb]}
+		let mut rb=BIG::frombytes(&t);
+
+		let mut ra4 = FP2::new_bigs(&ra,&rb);
+
+		for i in 0..mb {t[i]=b[i+2*mb]}
+		ra.copy(&BIG::frombytes(&t));
+		for i in 0..mb {t[i]=b[i+3*mb]}
+		rb.copy(&BIG::frombytes(&t));
+
+		let mut rb4 = FP2::new_bigs(&ra,&rb);
+
+
+		let rx=FP4::new_fp2s(&ra4,&rb4);
+
+
+		for i in 0..mb {t[i]=b[i+4*mb]}
+		ra.copy(&BIG::frombytes(&t));
+		for i in 0..mb {t[i]=b[i+5*mb]}
+		rb.copy(&BIG::frombytes(&t));
+
+		ra4.copy(&FP2::new_bigs(&ra,&rb));
+
+		for i in 0..mb {t[i]=b[i+6*mb]}
+		ra.copy(&BIG::frombytes(&t));
+		for i in 0..mb {t[i]=b[i+7*mb]}
+		rb.copy(&BIG::frombytes(&t));
+
+		rb4.copy(&FP2::new_bigs(&ra,&rb));
+
+		let ry=FP4::new_fp2s(&ra4,&rb4);
+
+		return ECP4::new_fp4s(&rx,&ry);
+	}
+
+/* convert this to hex string */
+	pub fn tostring(&self) -> String {
+		let mut W=ECP4::new(); W.copy(self); W.affine();
+		if W.is_infinity() {return String::from("infinity")}
+		return format!("({},{})",W.x.tostring(),W.y.tostring());
+}	
+
+/* Calculate RHS of twisted curve equation x^3+B/i */
+	pub fn rhs(x:&FP4) -> FP4 {
+		//x.norm();
+		let mut r=FP4::new_copy(x);
+		r.sqr();
+		let mut b=FP4::new_fp2(&FP2::new_big(&BIG::new_ints(&rom::CURVE_B)));
+		if ecp::SEXTIC_TWIST==ecp::D_TYPE {
+			b.div_i();
+		}
+		if ecp::SEXTIC_TWIST==ecp::M_TYPE {
+			b.times_i();
+		}
+
+		r.mul(x);
+		r.add(&b);
+
+		r.reduce();
+		return r;
+	}
+
+/* self+=self */
+	pub fn dbl(&mut self) -> isize {
+
+		let mut iy=FP4::new_copy(&self.y);
+		if ecp::SEXTIC_TWIST==ecp::D_TYPE {		
+			iy.times_i(); //iy.norm();
+		}
+
+		let mut t0=FP4::new_copy(&self.y);                  //***** Change 
+		t0.sqr();
+		if ecp::SEXTIC_TWIST==ecp::D_TYPE {		  
+			t0.times_i();
+		}   
+		let mut t1=FP4::new_copy(&iy);  
+		t1.mul(&self.z);
+		let mut t2=FP4::new_copy(&self.z);
+		t2.sqr();
+
+		self.z.copy(&t0);
+		self.z.add(&t0); self.z.norm(); 
+		self.z.dbl(); 
+		self.z.dbl(); 
+		self.z.norm();  
+
+		t2.imul(3*rom::CURVE_B_I); 
+		if ecp::SEXTIC_TWIST==ecp::M_TYPE {	
+			t2.times_i();
+			//t2.norm();	
+		}
+		let mut x3=FP4::new_copy(&t2);
+		x3.mul(&self.z); 
+
+		let mut y3=FP4::new_copy(&t0);   
+
+		y3.add(&t2); y3.norm();
+		self.z.mul(&t1);
+		t1.copy(&t2); t1.add(&t2); t2.add(&t1); t2.norm();  
+		t0.sub(&t2); t0.norm();                           //y^2-9bz^2
+		y3.mul(&t0); y3.add(&x3);                          //(y^2+3z*2)(y^2-9z^2)+3b.z^2.8y^2
+		t1.copy(&self.x); t1.mul(&iy);						//
+		self.x.copy(&t0); self.x.norm(); self.x.mul(&t1); self.x.dbl();       //(y^2-9bz^2)xy2
+
+		self.x.norm(); 
+		self.y.copy(&y3); self.y.norm();
+
+		return 1;
+
+	}
+
+/* self+=Q - return 0 for add, 1 for double, -1 for O */
+	pub fn add(&mut self,Q:&ECP4) -> isize {
+
+
+		let b=3*rom::CURVE_B_I;
+		let mut t0=FP4::new_copy(&self.x);
+		t0.mul(&Q.x);         // x.Q.x
+		let mut t1=FP4::new_copy(&self.y);
+		t1.mul(&Q.y);		 // y.Q.y
+
+		let mut t2=FP4::new_copy(&self.z);
+		t2.mul(&Q.z);
+		let mut t3=FP4::new_copy(&self.x);
+		t3.add(&self.y); t3.norm();          //t3=X1+Y1
+		let mut t4=FP4::new_copy(&Q.x);            
+		t4.add(&Q.y); t4.norm();			//t4=X2+Y2
+		t3.mul(&t4);						//t3=(X1+Y1)(X2+Y2)
+		t4.copy(&t0); t4.add(&t1);		//t4=X1.X2+Y1.Y2
+
+		t3.sub(&t4); t3.norm(); 
+		if ecp::SEXTIC_TWIST==ecp::D_TYPE {
+			t3.times_i();  //t3.norm();         //t3=(X1+Y1)(X2+Y2)-(X1.X2+Y1.Y2) = X1.Y2+X2.Y1
+		}
+		t4.copy(&self.y);                    
+		t4.add(&self.z); t4.norm();			//t4=Y1+Z1
+		let mut x3=FP4::new_copy(&Q.y);
+		x3.add(&Q.z); x3.norm();			//x3=Y2+Z2
+
+		t4.mul(&x3);						//t4=(Y1+Z1)(Y2+Z2)
+		x3.copy(&t1);					//
+		x3.add(&t2);						//X3=Y1.Y2+Z1.Z2
+	
+		t4.sub(&x3); t4.norm(); 
+		if ecp::SEXTIC_TWIST==ecp::D_TYPE {
+			t4.times_i(); //t4.norm();          //t4=(Y1+Z1)(Y2+Z2) - (Y1.Y2+Z1.Z2) = Y1.Z2+Y2.Z1
+		}
+		x3.copy(&self.x); x3.add(&self.z); x3.norm();	// x3=X1+Z1
+		let mut y3=FP4::new_copy(&Q.x);				
+		y3.add(&Q.z); y3.norm();				// y3=X2+Z2
+		x3.mul(&y3);							// x3=(X1+Z1)(X2+Z2)
+		y3.copy(&t0);
+		y3.add(&t2);							// y3=X1.X2+Z1+Z2
+		y3.rsub(&x3); y3.norm();				// y3=(X1+Z1)(X2+Z2) - (X1.X2+Z1.Z2) = X1.Z2+X2.Z1
+
+		if ecp::SEXTIC_TWIST==ecp::D_TYPE {
+			t0.times_i(); //t0.norm(); // x.Q.x
+			t1.times_i();// t1.norm(); // y.Q.y
+		}
+		x3.copy(&t0); x3.add(&t0); 
+		t0.add(&x3); t0.norm();
+		t2.imul(b); 	
+		if ecp::SEXTIC_TWIST==ecp::M_TYPE {	
+			t2.times_i();
+		}
+		let mut z3=FP4::new_copy(&t1); z3.add(&t2); z3.norm();
+		t1.sub(&t2); t1.norm(); 
+		y3.imul(b); 
+		if ecp::SEXTIC_TWIST==ecp::M_TYPE {		
+			y3.times_i();
+			//y3.norm();
+		}
+		x3.copy(&y3); x3.mul(&t4); t2.copy(&t3); t2.mul(&t1); x3.rsub(&t2);
+		y3.mul(&t0); t1.mul(&z3); y3.add(&t1);
+		t0.mul(&t3); z3.mul(&t4); z3.add(&t0);
+
+		self.x.copy(&x3); self.x.norm(); 
+		self.y.copy(&y3); self.y.norm();
+		self.z.copy(&z3); self.z.norm();
+
+		return 0;
+	}
+
+/* set this-=Q */
+	pub fn sub(&mut self,Q :&ECP4) -> isize {
+		let mut NQ=ECP4::new(); NQ.copy(Q);
+		NQ.neg();
+		let d=self.add(&NQ);
+		return d;
+	}
+ 
+	pub fn frob_constants() -> [FP2;3] {
+		let f = FP2::new_bigs(&BIG::new_ints(&rom::FRA),&BIG::new_ints(&rom::FRB));
+
+		let mut f0=FP2::new_copy(&f); f0.sqr();
+		let mut f2=FP2::new_copy(&f0);
+		f2.mul_ip(); f2.norm();
+		let mut f1=FP2::new_copy(&f2); f1.sqr();
+		f2.mul(&f1);
+		f1.copy(&f);
+		if ecp::SEXTIC_TWIST == ecp::M_TYPE {
+			f1.mul_ip();
+			f1.inverse();
+			f0.copy(&f1); f0.sqr();
+		}
+		f0.mul_ip(); f0.norm();
+		f1.mul(&f0);
+
+
+		let F:[FP2;3]=[f0,f1,f2];
+		return F;
+	}
+
+	/* set this*=q, where q is Modulus, using Frobenius */
+	pub fn frob(&mut self,f:&[FP2;3],n:isize) {
+
+		for _i in 0..n {
+			self.x.frob(&f[2]);
+			self.x.pmul(&f[0]);
+		
+			self.y.frob(&f[2]);
+			self.y.pmul(&f[1]);
+			self.y.times_i();
+
+			self.z.frob(&f[2]);
+		}
+	}
+
+/* self*=e */
+	pub fn mul(&self,e: &BIG) -> ECP4 {
+/* fixed size windows */
+		let mut mt=BIG::new();
+		let mut t=BIG::new();
+		let mut P=ECP4::new();
+		let mut Q=ECP4::new();
+		let mut C=ECP4::new();
+
+		if self.is_infinity() {return P}
+
+		let mut W:[ECP4;8]=[ECP4::new(),ECP4::new(),ECP4::new(),ECP4::new(),ECP4::new(),ECP4::new(),ECP4::new(),ECP4::new()];
+
+		const CT:usize=1+(big::NLEN*(big::BASEBITS as usize)+3)/4;
+		let mut w:[i8;CT]=[0;CT]; 
+
+	//	self.affine();
+
+/* precompute table */
+		Q.copy(&self);
+		Q.dbl();
+		
+		W[0].copy(&self);
+
+		for i in 1..8 {
+			C.copy(&W[i-1]);
+			W[i].copy(&C);
+			W[i].add(&mut Q);
+		}
+
+/* make exponent odd - add 2P if even, P if odd */
+		t.copy(&e);
+		let s=t.parity();
+		t.inc(1); t.norm(); let ns=t.parity(); mt.copy(&t); mt.inc(1); mt.norm();
+		t.cmove(&mt,s);
+		Q.cmove(&self,ns);
+		C.copy(&Q);
+
+		let nb=1+(t.nbits()+3)/4;
+
+/* convert exponent to signed 4-bit window */
+		for i in 0..nb {
+			w[i]=(t.lastbits(5)-16) as i8;
+			t.dec(w[i] as isize); t.norm();
+			t.fshr(4);	
+		}
+		w[nb]=(t.lastbits(5)) as i8;
+		
+		P.copy(&W[((w[nb] as usize) -1)/2]);
+		for i in (0..nb).rev() {
+			Q.selector(&W,w[i] as i32);
+			P.dbl();
+			P.dbl();
+			P.dbl();
+			P.dbl();
+			P.add(&mut Q);
+		}
+		P.sub(&mut C);
+		P.affine();
+		return P;
+	}
+
+/* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3.. */
+// Bos & Costello https://eprint.iacr.org/2013/458.pdf
+// Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
+// Side channel attack secure 
+
+	pub fn mul8(Q: &mut [ECP4],u: &[BIG]) -> ECP4 {
+		let mut W=ECP4::new();
+		let mut P=ECP4::new();
+
+		let mut T1:[ECP4;8]=[ECP4::new(),ECP4::new(),ECP4::new(),ECP4::new(),ECP4::new(),ECP4::new(),ECP4::new(),ECP4::new()];
+		let mut T2:[ECP4;8]=[ECP4::new(),ECP4::new(),ECP4::new(),ECP4::new(),ECP4::new(),ECP4::new(),ECP4::new(),ECP4::new()];
+
+		let mut mt=BIG::new();
+
+		let mut t:[BIG;8]=[BIG::new_copy(&u[0]),BIG::new_copy(&u[1]),BIG::new_copy(&u[2]),BIG::new_copy(&u[3]),BIG::new_copy(&u[4]),BIG::new_copy(&u[5]),BIG::new_copy(&u[6]),BIG::new_copy(&u[7])];
+
+		const CT:usize=1+big::NLEN*(big::BASEBITS as usize);
+		let mut w1:[i8;CT]=[0;CT];
+		let mut s1:[i8;CT]=[0;CT];
+		let mut w2:[i8;CT]=[0;CT];
+		let mut s2:[i8;CT]=[0;CT];
+
+		for i in 0..8 {
+			//Q[i].affine();
+			t[i].norm();
+		}
+
+		T1[0].copy(&Q[0]); W.copy(&T1[0]);
+		T1[1].copy(&W); T1[1].add(&mut Q[1]);  // Q[0]+Q[1]
+		T1[2].copy(&W); T1[2].add(&mut Q[2]); W.copy(&T1[1]); // Q[0]+Q[2]
+		T1[3].copy(&W); T1[3].add(&mut Q[2]); W.copy(&T1[0]); // Q[0]+Q[1]+Q[2]
+		T1[4].copy(&W); T1[4].add(&mut Q[3]); W.copy(&T1[1]); // Q[0]+Q[3]
+		T1[5].copy(&W); T1[5].add(&mut Q[3]); W.copy(&T1[2]); // Q[0]+Q[1]+Q[3]
+		T1[6].copy(&W); T1[6].add(&mut Q[3]); W.copy(&T1[3]); // Q[0]+Q[2]+Q[3]
+		T1[7].copy(&W); T1[7].add(&mut Q[3]); // Q[0]+Q[1]+Q[2]+Q[3]
+
+// Use frobenius
+		let f=ECP4::frob_constants();
+		for i in 0..8 {
+			T2[i].copy(&T1[i]); T2[i].frob(&f,4);
+		}	
+
+// Make it odd
+		let pb1=1-t[0].parity();
+		t[0].inc(pb1);
+		t[0].norm();	
+
+		let pb2=1-t[4].parity();
+		t[4].inc(pb2);
+		t[4].norm();	
+
+// Number of bits
+		mt.zero();
+		for i in 0..8 {
+			mt.or(&t[i]);
+		}
+
+		let nb=1+mt.nbits();
+
+// Sign pivot 
+
+		s1[nb-1]=1;
+		s2[nb-1]=1;
+		for i in 0..nb-1 {
+			t[0].fshr(1);
+			s1[i]=(2*t[0].parity()-1) as i8;
+			t[4].fshr(1);
+			s2[i]=(2*t[4].parity()-1) as i8;
+
+		}
+
+// Recoded exponent
+		for i in 0..nb {
+			w1[i]=0;
+			let mut k=1;
+			for j in 1..4 {
+				let bt=s1[i]*(t[j].parity() as i8);
+				t[j].fshr(1);
+				t[j].dec((bt>>1) as isize);
+				t[j].norm();
+				w1[i]+=bt*(k as i8);
+				k=2*k;
+			}
+
+			w2[i]=0;
+			k=1;
+			for j in 5..8 {
+				let bt=s2[i]*(t[j].parity() as i8);
+				t[j].fshr(1);
+				t[j].dec((bt>>1) as isize);
+				t[j].norm();
+				w2[i]+=bt*(k as i8);
+				k=2*k;
+			}			
+		}	
+
+// Main loop
+		P.selector(&T1,(2*w1[nb-1]+1) as i32);
+		W.selector(&T2,(2*w2[nb-1]+1) as i32);
+		P.add(&mut W);
+		for i in (0..nb-1).rev() {
+			P.dbl();
+			W.selector(&T1,(2*w1[i]+s1[i]) as i32);
+			P.add(&mut W);
+			W.selector(&T2,(2*w2[i]+s2[i]) as i32);
+			P.add(&mut W);			
+		}		
+
+// apply correction
+		W.copy(&P);   
+		W.sub(&mut Q[0]);
+		P.cmove(&W,pb1);	
+
+		W.copy(&P);   
+		W.sub(&mut Q[4]);
+		P.cmove(&W,pb2);	
+
+
+		P.affine();
+
+		return P;
+	}
+
+	pub fn generator() -> ECP4 {
+		return ECP4::new_fp4s(&FP4::new_fp2s(&FP2::new_bigs(&BIG::new_ints(&rom::CURVE_PXAA),&BIG::new_ints(&rom::CURVE_PXAB)),&FP2::new_bigs(&BIG::new_ints(&rom::CURVE_PXBA),&BIG::new_ints(&rom::CURVE_PXBB))),&FP4::new_fp2s(&FP2::new_bigs(&BIG::new_ints(&rom::CURVE_PYAA),&BIG::new_ints(&rom::CURVE_PYAB)),&FP2::new_bigs(&BIG::new_ints(&rom::CURVE_PYBA),&BIG::new_ints(&rom::CURVE_PYBB))));
+	}	
+
+#[allow(non_snake_case)]
+	pub fn mapit(h: &[u8]) -> ECP4 {
+		let mut q=BIG::new_ints(&rom::MODULUS);
+		let mut x=BIG::frombytes(h);
+		x.rmod(&mut q);
+		let mut Q:ECP4;
+		let one=BIG::new_int(1);
+
+		loop {
+			let X=FP4::new_fp2(&FP2::new_bigs(&one,&x));
+			Q=ECP4::new_fp4(&X);
+			if !Q.is_infinity() {break}
+			x.inc(1); x.norm();
+		}
+		
+		let f = ECP4::frob_constants();
+		x = BIG::new_ints(&rom::CURVE_BNX);
+
+
+        let mut xQ=Q.mul(&mut x);
+        let mut x2Q=xQ.mul(&mut x);
+        let mut x3Q=x2Q.mul(&mut x);
+        let mut x4Q=x3Q.mul(&mut x);
+
+		if ecp::SIGN_OF_X==ecp::NEGATIVEX {
+			xQ.neg();
+			x3Q.neg();
+		}
+
+		x4Q.sub(&x3Q);
+		x4Q.sub(&Q);
+
+		x3Q.sub(&x2Q);
+		x3Q.frob(&f,1);
+
+		x2Q.sub(&xQ);
+		x2Q.frob(&f,2);
+
+		xQ.sub(&Q);
+		xQ.frob(&f,3);
+
+		Q.dbl();
+		Q.frob(&f,4);
+
+		Q.add(&x4Q);
+		Q.add(&x3Q);
+		Q.add(&x2Q);
+		Q.add(&xQ);
+
+		Q.affine();
+		return Q;
+	}
+
+}	
\ No newline at end of file
diff --git a/version3/rust/ecp8.rs b/version3/rust/ecp8.rs
new file mode 100644
index 0000000..4992f2f
--- /dev/null
+++ b/version3/rust/ecp8.rs
@@ -0,0 +1,873 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use xxx::rom;
+use xxx::big;
+use xxx::ecp;
+use xxx::fp2::FP2;
+use xxx::fp4::FP4;
+use xxx::fp8::FP8;
+use xxx::big::BIG;
+
+pub struct ECP8 {
+	x:FP8,
+	y:FP8,
+	z:FP8,
+}
+
+#[allow(non_snake_case)]
+impl ECP8 {
+
+	pub fn new() -> ECP8 {
+		ECP8 {
+				x: FP8::new(),
+				y: FP8::new_int(1),
+				z: FP8::new(),
+		}
+	}
+#[allow(non_snake_case)]
+/* construct this from (x,y) - but set to O if not on curve */
+	pub fn new_fp8s(ix:&FP8,iy:&FP8) -> ECP8 {
+		let mut E=ECP8::new();
+		E.x.copy(&ix);
+		E.y.copy(&iy);
+		E.z.one();
+		E.x.norm();
+
+		let mut rhs=ECP8::rhs(&E.x);
+		let mut y2=FP8::new_copy(&E.y);
+		y2.sqr();
+		if !y2.equals(&mut rhs) {
+			E.inf();
+		}
+		return E;
+}
+
+/* construct this from x - but set to O if not on curve */
+	pub fn new_fp8(ix:&FP8) -> ECP8 {	
+		let mut E=ECP8::new();
+		E.x.copy(&ix);
+		E.y.one();
+		E.z.one();
+		E.x.norm();
+
+		let mut rhs=ECP8::rhs(&E.x);
+		if rhs.sqrt() {
+			E.y.copy(&rhs);
+		} else {E.inf();}
+		return E;
+	}
+
+/* Test this=O? */
+	pub fn is_infinity(&self) -> bool {
+		let xx=FP8::new_copy(&self.x);
+		let zz=FP8::new_copy(&self.z);
+		return xx.iszilch() && zz.iszilch();
+	}
+
+/* copy self=P */
+	pub fn copy(&mut self,P: &ECP8) {
+		self.x.copy(&P.x);
+		self.y.copy(&P.y);
+		self.z.copy(&P.z);
+	}
+
+/* set self=O */
+	pub fn inf(&mut self) {
+		self.x.zero();
+		self.y.one();
+		self.z.zero();
+	}
+
+/* set self=-self */
+	pub fn neg(&mut self) {
+		self.y.norm(); self.y.neg(); self.y.norm();
+	}	
+
+/* Conditional move of Q to self dependant on d */
+	pub fn cmove(&mut self,Q: &ECP8,d: isize) {
+		self.x.cmove(&Q.x,d);
+		self.y.cmove(&Q.y,d);
+		self.z.cmove(&Q.z,d);
+	}
+
+/* return 1 if b==c, no branching */
+	fn teq(b: i32,c: i32) -> isize {
+		let mut x=b^c;
+		x-=1;  // if x=0, x now -1
+		return ((x>>31)&1) as isize;
+	}
+
+/* Constant time select from pre-computed table */
+	pub fn selector(&mut self,W: &[ECP8],b: i32) {
+		let mut MP=ECP8::new(); 
+		let m=b>>31;
+		let mut babs=(b^m)-m;
+
+		babs=(babs-1)/2;
+
+		self.cmove(&W[0],ECP8::teq(babs,0));  // conditional move
+		self.cmove(&W[1],ECP8::teq(babs,1));
+		self.cmove(&W[2],ECP8::teq(babs,2));
+		self.cmove(&W[3],ECP8::teq(babs,3));
+		self.cmove(&W[4],ECP8::teq(babs,4));
+		self.cmove(&W[5],ECP8::teq(babs,5));
+		self.cmove(&W[6],ECP8::teq(babs,6));
+		self.cmove(&W[7],ECP8::teq(babs,7));
+ 
+		MP.copy(self);
+		MP.neg();
+		self.cmove(&MP,(m&1) as isize);
+	}	
+
+/* Test if P == Q */
+	pub fn equals(&mut self,Q :&mut ECP8) -> bool {
+
+		let mut a=FP8::new_copy(&self.x);
+		let mut b=FP8::new_copy(&Q.x); 
+
+		a.mul(&Q.z);
+		b.mul(&self.z);
+		if !a.equals(&mut b) {return false}
+		a.copy(&self.y); a.mul(&Q.z);
+		b.copy(&Q.y); b.mul(&self.z);
+		if !a.equals(&mut b) {return false}
+
+		return true;
+	}
+
+/* set to Affine - (x,y,z) to (x,y) */
+	pub fn affine(&mut self) {
+		if self.is_infinity() {return}
+		let mut one=FP8::new_int(1);
+		if self.z.equals(&mut one) {return}
+		self.z.inverse();
+
+		self.x.mul(&self.z); self.x.reduce(); 
+		self.y.mul(&self.z); self.y.reduce();
+		self.z.copy(&one);
+	}
+
+/* extract affine x as FP8 */
+	pub fn getx(&self) -> FP8 {
+		let mut W=ECP8::new(); W.copy(self);
+		W.affine();
+		return FP8::new_copy(&W.x);
+	}
+
+/* extract affine y as FP8 */
+	pub fn gety(&self) -> FP8 {
+		let mut W=ECP8::new(); W.copy(self);
+		W.affine();
+		return FP8::new_copy(&W.y);
+	}
+
+/* extract projective x */
+	pub fn getpx(&self) -> FP8 {
+		return FP8::new_copy(&self.x);
+	}
+/* extract projective y */
+	pub fn getpy(&self) -> FP8 {
+		return FP8::new_copy(&self.y);
+	}
+/* extract projective z */
+	pub fn getpz(&self) -> FP8 {
+		return FP8::new_copy(&self.z);
+	}
+
+/* convert to byte array */
+	pub fn tobytes(&self,b: &mut [u8]) {
+		let mut t:[u8;big::MODBYTES as usize]=[0;big::MODBYTES as usize];
+		let mb=big::MODBYTES as usize;
+		let mut W=ECP8::new(); W.copy(self);
+
+		W.affine();
+
+		W.x.geta().geta().geta().tobytes(&mut t);
+		for i in 0..mb { b[i]=t[i]}
+		W.x.geta().geta().getb().tobytes(&mut t);
+		for i in 0..mb { b[i+mb]=t[i]}
+
+		W.x.geta().getb().geta().tobytes(&mut t);
+		for i in 0..mb { b[i+2*mb]=t[i]}
+		W.x.geta().getb().getb().tobytes(&mut t);
+		for i in 0..mb { b[i+3*mb]=t[i]}
+
+		W.x.getb().geta().geta().tobytes(&mut t);
+		for i in 0..mb { b[i+4*mb]=t[i]}
+		W.x.getb().geta().getb().tobytes(&mut t);
+		for i in 0..mb { b[i+5*mb]=t[i]}
+
+		W.x.getb().getb().geta().tobytes(&mut t);
+		for i in 0..mb { b[i+6*mb]=t[i]}
+		W.x.getb().getb().getb().tobytes(&mut t);
+		for i in 0..mb { b[i+7*mb]=t[i]}
+
+
+
+		W.y.geta().geta().geta().tobytes(&mut t);
+		for i in 0..mb {b[i+8*mb]=t[i]}
+		W.y.geta().geta().getb().tobytes(&mut t);
+		for i in 0..mb {b[i+9*mb]=t[i]}
+
+		W.y.geta().getb().geta().tobytes(&mut t);
+		for i in 0..mb {b[i+10*mb]=t[i]}
+		W.y.geta().getb().getb().tobytes(&mut t);
+		for i in 0..mb {b[i+11*mb]=t[i]}
+
+		W.y.getb().geta().geta().tobytes(&mut t);
+		for i in 0..mb {b[i+12*mb]=t[i]}
+		W.y.getb().geta().getb().tobytes(&mut t);
+		for i in 0..mb {b[i+13*mb]=t[i]}
+
+		W.y.getb().getb().geta().tobytes(&mut t);
+		for i in 0..mb {b[i+14*mb]=t[i]}
+		W.y.getb().getb().getb().tobytes(&mut t);
+		for i in 0..mb {b[i+15*mb]=t[i]}		
+	}
+
+/* convert from byte array to point */
+	pub fn frombytes(b: &[u8]) -> ECP8 {
+		let mut t:[u8;big::MODBYTES as usize]=[0;big::MODBYTES as usize];
+		let mb=big::MODBYTES as usize;
+
+		for i in 0..mb {t[i]=b[i]}
+		let mut ra=BIG::frombytes(&t);
+		for i in 0..mb {t[i]=b[i+mb]}
+		let mut rb=BIG::frombytes(&t);
+
+		let mut ra4 = FP2::new_bigs(&ra,&rb);
+
+		for i in 0..mb {t[i]=b[i+2*mb]}
+		ra.copy(&BIG::frombytes(&t));
+		for i in 0..mb {t[i]=b[i+3*mb]}
+		rb.copy(&BIG::frombytes(&t));
+
+		let mut rb4 = FP2::new_bigs(&ra,&rb);
+
+		let mut ra8 = FP4::new_fp2s(&ra4,&rb4);
+
+		for i in 0..mb {t[i]=b[i+4*mb]}
+		let mut ra=BIG::frombytes(&t);
+		for i in 0..mb {t[i]=b[i+5*mb]}
+		let mut rb=BIG::frombytes(&t);
+
+		ra4.copy(&FP2::new_bigs(&ra,&rb));
+
+		for i in 0..mb {t[i]=b[i+6*mb]}
+		ra.copy(&BIG::frombytes(&t));
+		for i in 0..mb {t[i]=b[i+7*mb]}
+		rb.copy(&BIG::frombytes(&t));
+
+		rb4.copy(&FP2::new_bigs(&ra,&rb));
+
+		let mut rb8 = FP4::new_fp2s(&ra4,&rb4);
+
+		let rx=FP8::new_fp4s(&ra8,&rb8);
+
+
+		for i in 0..mb {t[i]=b[i+8*mb]}
+		ra.copy(&BIG::frombytes(&t));
+		for i in 0..mb {t[i]=b[i+9*mb]}
+		rb.copy(&BIG::frombytes(&t));
+
+		ra4.copy(&FP2::new_bigs(&ra,&rb));
+
+		for i in 0..mb {t[i]=b[i+10*mb]}
+		ra.copy(&BIG::frombytes(&t));
+		for i in 0..mb {t[i]=b[i+11*mb]}
+		rb.copy(&BIG::frombytes(&t));
+
+		rb4.copy(&FP2::new_bigs(&ra,&rb));
+
+		ra8.copy(&FP4::new_fp2s(&ra4,&rb4));
+
+
+		for i in 0..mb {t[i]=b[i+12*mb]}
+		ra.copy(&BIG::frombytes(&t));
+		for i in 0..mb {t[i]=b[i+13*mb]}
+		rb.copy(&BIG::frombytes(&t));
+
+		ra4.copy(&FP2::new_bigs(&ra,&rb));
+
+		for i in 0..mb {t[i]=b[i+14*mb]}
+		ra.copy(&BIG::frombytes(&t));
+		for i in 0..mb {t[i]=b[i+15*mb]}
+		rb.copy(&BIG::frombytes(&t));
+
+		rb4.copy(&FP2::new_bigs(&ra,&rb));
+
+		rb8.copy(&FP4::new_fp2s(&ra4,&rb4));
+
+		let ry=FP8::new_fp4s(&ra8,&rb8);
+
+
+		return ECP8::new_fp8s(&rx,&ry);
+	}
+
+/* convert this to hex string */
+	pub fn tostring(&self) -> String {
+		let mut W=ECP8::new(); W.copy(self); W.affine();
+		if W.is_infinity() {return String::from("infinity")}
+		return format!("({},{})",W.x.tostring(),W.y.tostring());
+}	
+
+/* Calculate RHS of twisted curve equation x^3+B/i */
+	pub fn rhs(x:&FP8) -> FP8 {
+		//x.norm();
+		let mut r=FP8::new_copy(x);
+		r.sqr();
+		let mut b=FP8::new_fp4(&FP4::new_fp2(&FP2::new_big(&BIG::new_ints(&rom::CURVE_B))));
+		if ecp::SEXTIC_TWIST==ecp::D_TYPE {
+			b.div_i();
+		}
+		if ecp::SEXTIC_TWIST==ecp::M_TYPE {
+			b.times_i();
+		}
+
+		r.mul(x);
+		r.add(&b);
+
+		r.reduce();
+		return r;
+	}
+
+	/* self+=self */
+	pub fn dbl(&mut self) -> isize {
+
+		let mut iy=FP8::new_copy(&self.y);
+		if ecp::SEXTIC_TWIST==ecp::D_TYPE {		
+			iy.times_i(); //iy.norm();
+		}
+
+		let mut t0=FP8::new_copy(&self.y);                  //***** Change 
+		t0.sqr();
+		if ecp::SEXTIC_TWIST==ecp::D_TYPE {		  
+			t0.times_i();
+		}   
+		let mut t1=FP8::new_copy(&iy);  
+		t1.mul(&self.z);
+		let mut t2=FP8::new_copy(&self.z);
+		t2.sqr();
+
+		self.z.copy(&t0);
+		self.z.add(&t0); self.z.norm(); 
+		self.z.dbl(); 
+		self.z.dbl(); 
+		self.z.norm();  
+
+		t2.imul(3*rom::CURVE_B_I); 
+		if ecp::SEXTIC_TWIST==ecp::M_TYPE {	
+			t2.times_i();
+			//t2.norm();	
+		}
+		let mut x3=FP8::new_copy(&t2);
+		x3.mul(&self.z); 
+
+		let mut y3=FP8::new_copy(&t0);   
+
+		y3.add(&t2); y3.norm();
+		self.z.mul(&t1);
+		t1.copy(&t2); t1.add(&t2); t2.add(&t1); t2.norm();  
+		t0.sub(&t2); t0.norm();                           //y^2-9bz^2
+		y3.mul(&t0); y3.add(&x3);                          //(y^2+3z*2)(y^2-9z^2)+3b.z^2.8y^2
+		t1.copy(&self.x); t1.mul(&iy);						//
+		self.x.copy(&t0); self.x.norm(); self.x.mul(&t1); self.x.dbl();       //(y^2-9bz^2)xy2
+
+		self.x.norm(); 
+		self.y.copy(&y3); self.y.norm();
+
+		return 1;
+
+	}
+
+/* self+=Q - return 0 for add, 1 for double, -1 for O */
+	pub fn add(&mut self,Q:&ECP8) -> isize {
+
+
+		let b=3*rom::CURVE_B_I;
+		let mut t0=FP8::new_copy(&self.x);
+		t0.mul(&Q.x);         // x.Q.x
+		let mut t1=FP8::new_copy(&self.y);
+		t1.mul(&Q.y);		 // y.Q.y
+
+		let mut t2=FP8::new_copy(&self.z);
+		t2.mul(&Q.z);
+		let mut t3=FP8::new_copy(&self.x);
+		t3.add(&self.y); t3.norm();          //t3=X1+Y1
+		let mut t4=FP8::new_copy(&Q.x);            
+		t4.add(&Q.y); t4.norm();			//t4=X2+Y2
+		t3.mul(&t4);						//t3=(X1+Y1)(X2+Y2)
+		t4.copy(&t0); t4.add(&t1);		//t4=X1.X2+Y1.Y2
+
+		t3.sub(&t4); t3.norm(); 
+		if ecp::SEXTIC_TWIST==ecp::D_TYPE {
+			t3.times_i();  //t3.norm();         //t3=(X1+Y1)(X2+Y2)-(X1.X2+Y1.Y2) = X1.Y2+X2.Y1
+		}
+		t4.copy(&self.y);                    
+		t4.add(&self.z); t4.norm();			//t4=Y1+Z1
+		let mut x3=FP8::new_copy(&Q.y);
+		x3.add(&Q.z); x3.norm();			//x3=Y2+Z2
+
+		t4.mul(&x3);						//t4=(Y1+Z1)(Y2+Z2)
+		x3.copy(&t1);					//
+		x3.add(&t2);						//X3=Y1.Y2+Z1.Z2
+	
+		t4.sub(&x3); t4.norm(); 
+		if ecp::SEXTIC_TWIST==ecp::D_TYPE {
+			t4.times_i(); //t4.norm();          //t4=(Y1+Z1)(Y2+Z2) - (Y1.Y2+Z1.Z2) = Y1.Z2+Y2.Z1
+		}
+		x3.copy(&self.x); x3.add(&self.z); x3.norm();	// x3=X1+Z1
+		let mut y3=FP8::new_copy(&Q.x);				
+		y3.add(&Q.z); y3.norm();				// y3=X2+Z2
+		x3.mul(&y3);							// x3=(X1+Z1)(X2+Z2)
+		y3.copy(&t0);
+		y3.add(&t2);							// y3=X1.X2+Z1+Z2
+		y3.rsub(&x3); y3.norm();				// y3=(X1+Z1)(X2+Z2) - (X1.X2+Z1.Z2) = X1.Z2+X2.Z1
+
+		if ecp::SEXTIC_TWIST==ecp::D_TYPE {
+			t0.times_i(); //t0.norm(); // x.Q.x
+			t1.times_i();// t1.norm(); // y.Q.y
+		}
+		x3.copy(&t0); x3.add(&t0); 
+		t0.add(&x3); t0.norm();
+		t2.imul(b); 	
+		if ecp::SEXTIC_TWIST==ecp::M_TYPE {	
+			t2.times_i();
+		}
+		let mut z3=FP8::new_copy(&t1); z3.add(&t2); z3.norm();
+		t1.sub(&t2); t1.norm(); 
+		y3.imul(b); 
+		if ecp::SEXTIC_TWIST==ecp::M_TYPE {		
+			y3.times_i();
+			//y3.norm();
+		}
+		x3.copy(&y3); x3.mul(&t4); t2.copy(&t3); t2.mul(&t1); x3.rsub(&t2);
+		y3.mul(&t0); t1.mul(&z3); y3.add(&t1);
+		t0.mul(&t3); z3.mul(&t4); z3.add(&t0);
+
+		self.x.copy(&x3); self.x.norm(); 
+		self.y.copy(&y3); self.y.norm();
+		self.z.copy(&z3); self.z.norm();
+
+		return 0;
+	}
+
+/* set this-=Q */
+	pub fn sub(&mut self,Q :&ECP8) -> isize {
+		let mut NQ=ECP8::new(); NQ.copy(Q);
+		NQ.neg();
+		let d=self.add(&NQ);
+		return d;
+	}
+
+	pub fn frob_constants() -> [FP2;3] {
+		let f = FP2::new_bigs(&BIG::new_ints(&rom::FRA),&BIG::new_ints(&rom::FRB));
+
+		let mut f0=FP2::new_copy(&f); f0.sqr();
+		let mut f2=FP2::new_copy(&f0);
+		f2.mul_ip(); f2.norm();
+		let mut f1=FP2::new_copy(&f2); f1.sqr();
+		f2.mul(&f1);
+
+		f2.mul_ip(); f2.norm();
+
+		f1.copy(&f);
+		if ecp::SEXTIC_TWIST == ecp::M_TYPE {
+			f1.mul_ip();
+			f1.inverse();
+			f0.copy(&f1); f0.sqr();
+		}
+		f0.mul_ip(); f0.norm();
+		f1.mul(&f0);
+
+
+		let F:[FP2;3]=[f0,f1,f2];
+		return F;
+	}
+
+	/* set this*=q, where q is Modulus, using Frobenius */
+	pub fn frob(&mut self,f:&[FP2;3],n:isize) {
+
+		for _i in 0..n {
+			self.x.frob(&f[2]);
+			self.x.qmul(&f[0]);
+			if ecp::SEXTIC_TWIST == ecp::M_TYPE {
+				self.x.div_i2();
+			}
+			if ecp::SEXTIC_TWIST == ecp::D_TYPE {
+				self.x.times_i2();
+			}			
+			self.y.frob(&f[2]);
+			self.y.qmul(&f[1]);
+			if ecp::SEXTIC_TWIST == ecp::M_TYPE {
+				self.y.div_i();
+			}		
+			if ecp::SEXTIC_TWIST == ecp::D_TYPE {				
+				self.y.times_i2(); self.y.times_i2(); self.y.times_i();
+			}
+
+			self.z.frob(&f[2]);
+		}
+	}
+
+/* self*=e */
+	pub fn mul(&self,e: &BIG) -> ECP8 {
+/* fixed size windows */
+		let mut mt=BIG::new();
+		let mut t=BIG::new();
+		let mut P=ECP8::new();
+		let mut Q=ECP8::new();
+		let mut C=ECP8::new();
+
+		if self.is_infinity() {return P}
+
+		let mut W:[ECP8;8]=[ECP8::new(),ECP8::new(),ECP8::new(),ECP8::new(),ECP8::new(),ECP8::new(),ECP8::new(),ECP8::new()];
+
+		const CT:usize=1+(big::NLEN*(big::BASEBITS as usize)+3)/4;
+		let mut w:[i8;CT]=[0;CT]; 
+
+	//	self.affine();
+
+/* precompute table */
+		Q.copy(&self);
+		Q.dbl();
+		
+		W[0].copy(&self);
+
+		for i in 1..8 {
+			C.copy(&W[i-1]);
+			W[i].copy(&C);
+			W[i].add(&mut Q);
+		}
+
+/* make exponent odd - add 2P if even, P if odd */
+		t.copy(&e);
+		let s=t.parity();
+		t.inc(1); t.norm(); let ns=t.parity(); mt.copy(&t); mt.inc(1); mt.norm();
+		t.cmove(&mt,s);
+		Q.cmove(&self,ns);
+		C.copy(&Q);
+
+		let nb=1+(t.nbits()+3)/4;
+
+/* convert exponent to signed 4-bit window */
+		for i in 0..nb {
+			w[i]=(t.lastbits(5)-16) as i8;
+			t.dec(w[i] as isize); t.norm();
+			t.fshr(4);	
+		}
+		w[nb]=(t.lastbits(5)) as i8;
+		
+		P.copy(&W[((w[nb] as usize) -1)/2]);
+		for i in (0..nb).rev() {
+			Q.selector(&W,w[i] as i32);
+			P.dbl();
+			P.dbl();
+			P.dbl();
+			P.dbl();
+			P.add(&mut Q);
+		}
+		P.sub(&mut C);
+		P.affine();
+		return P;
+	}
+
+/* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3.. */
+// Bos & Costello https://eprint.iacr.org/2013/458.pdf
+// Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
+// Side channel attack secure 
+
+	pub fn mul16(Q: &mut [ECP8],u: &[BIG]) -> ECP8 {
+		let mut W=ECP8::new();
+		let mut P=ECP8::new();
+
+		let mut T1:[ECP8;8]=[ECP8::new(),ECP8::new(),ECP8::new(),ECP8::new(),ECP8::new(),ECP8::new(),ECP8::new(),ECP8::new()];
+		let mut T2:[ECP8;8]=[ECP8::new(),ECP8::new(),ECP8::new(),ECP8::new(),ECP8::new(),ECP8::new(),ECP8::new(),ECP8::new()];
+		let mut T3:[ECP8;8]=[ECP8::new(),ECP8::new(),ECP8::new(),ECP8::new(),ECP8::new(),ECP8::new(),ECP8::new(),ECP8::new()];
+		let mut T4:[ECP8;8]=[ECP8::new(),ECP8::new(),ECP8::new(),ECP8::new(),ECP8::new(),ECP8::new(),ECP8::new(),ECP8::new()];
+
+
+		let mut mt=BIG::new();
+
+		let mut t:[BIG;16]=[BIG::new_copy(&u[0]),BIG::new_copy(&u[1]),BIG::new_copy(&u[2]),BIG::new_copy(&u[3]),BIG::new_copy(&u[4]),BIG::new_copy(&u[5]),BIG::new_copy(&u[6]),BIG::new_copy(&u[7]),BIG::new_copy(&u[8]),BIG::new_copy(&u[9]),BIG::new_copy(&u[10]),BIG::new_copy(&u[11]),BIG::new_copy(&u[12]),BIG::new_copy(&u[13]),BIG::new_copy(&u[14]),BIG::new_copy(&u[15])];
+
+		const CT:usize=1+big::NLEN*(big::BASEBITS as usize);
+		let mut w1:[i8;CT]=[0;CT];
+		let mut s1:[i8;CT]=[0;CT];
+		let mut w2:[i8;CT]=[0;CT];
+		let mut s2:[i8;CT]=[0;CT];
+		let mut w3:[i8;CT]=[0;CT];
+		let mut s3:[i8;CT]=[0;CT];
+		let mut w4:[i8;CT]=[0;CT];
+		let mut s4:[i8;CT]=[0;CT];
+
+
+		for i in 0..16 {
+			//Q[i].affine();
+			t[i].norm();
+		}
+
+		T1[0].copy(&Q[0]); W.copy(&T1[0]);
+		T1[1].copy(&W); T1[1].add(&mut Q[1]);  // Q[0]+Q[1]
+		T1[2].copy(&W); T1[2].add(&mut Q[2]); W.copy(&T1[1]); // Q[0]+Q[2]
+		T1[3].copy(&W); T1[3].add(&mut Q[2]); W.copy(&T1[0]); // Q[0]+Q[1]+Q[2]
+		T1[4].copy(&W); T1[4].add(&mut Q[3]); W.copy(&T1[1]); // Q[0]+Q[3]
+		T1[5].copy(&W); T1[5].add(&mut Q[3]); W.copy(&T1[2]); // Q[0]+Q[1]+Q[3]
+		T1[6].copy(&W); T1[6].add(&mut Q[3]); W.copy(&T1[3]); // Q[0]+Q[2]+Q[3]
+		T1[7].copy(&W); T1[7].add(&mut Q[3]); // Q[0]+Q[1]+Q[2]+Q[3]
+
+// Use frobenius
+		let f=ECP8::frob_constants();
+		for i in 0..8 {
+			T2[i].copy(&T1[i]); T2[i].frob(&f,4);
+			T3[i].copy(&T2[i]); T3[i].frob(&f,4);
+			T4[i].copy(&T3[i]); T4[i].frob(&f,4);						
+		}	
+
+// Make it odd
+		let pb1=1-t[0].parity();
+		t[0].inc(pb1);
+		t[0].norm();	
+
+		let pb2=1-t[4].parity();
+		t[4].inc(pb2);
+		t[4].norm();	
+
+		let pb3=1-t[8].parity();
+		t[8].inc(pb3);
+		t[8].norm();	
+
+		let pb4=1-t[12].parity();
+		t[12].inc(pb4);
+		t[12].norm();	
+
+// Number of bits
+		mt.zero();
+		for i in 0..16 {
+			mt.or(&t[i]);
+		}
+
+		let nb=1+mt.nbits();
+
+// Sign pivot 
+
+		s1[nb-1]=1;
+		s2[nb-1]=1;
+		s3[nb-1]=1;
+		s4[nb-1]=1;		
+		for i in 0..nb-1 {
+			t[0].fshr(1);
+			s1[i]=(2*t[0].parity()-1) as i8;
+			t[4].fshr(1);
+			s2[i]=(2*t[4].parity()-1) as i8;
+			t[8].fshr(1);
+			s3[i]=(2*t[8].parity()-1) as i8;
+			t[12].fshr(1);
+			s4[i]=(2*t[12].parity()-1) as i8;			
+
+		}
+
+// Recoded exponent
+		for i in 0..nb {
+			w1[i]=0;
+			let mut k=1;
+			for j in 1..4 {
+				let bt=s1[i]*(t[j].parity() as i8);
+				t[j].fshr(1);
+				t[j].dec((bt>>1) as isize);
+				t[j].norm();
+				w1[i]+=bt*(k as i8);
+				k=2*k;
+			}
+
+			w2[i]=0;
+			k=1;
+			for j in 5..8 {
+				let bt=s2[i]*(t[j].parity() as i8);
+				t[j].fshr(1);
+				t[j].dec((bt>>1) as isize);
+				t[j].norm();
+				w2[i]+=bt*(k as i8);
+				k=2*k;
+			}			
+
+			w3[i]=0;
+			k=1;
+			for j in 9..12 {
+				let bt=s3[i]*(t[j].parity() as i8);
+				t[j].fshr(1);
+				t[j].dec((bt>>1) as isize);
+				t[j].norm();
+				w3[i]+=bt*(k as i8);
+				k=2*k;
+			}			
+
+
+			w4[i]=0;
+			k=1;
+			for j in 13..16 {
+				let bt=s4[i]*(t[j].parity() as i8);
+				t[j].fshr(1);
+				t[j].dec((bt>>1) as isize);
+				t[j].norm();
+				w4[i]+=bt*(k as i8);
+				k=2*k;
+			}			
+
+		}	
+
+// Main loop
+		P.selector(&T1,(2*w1[nb-1]+1) as i32);
+		W.selector(&T2,(2*w2[nb-1]+1) as i32);
+		P.add(&mut W);
+		W.selector(&T3,(2*w3[nb-1]+1) as i32);
+		P.add(&mut W);
+		W.selector(&T4,(2*w4[nb-1]+1) as i32);
+		P.add(&mut W);				
+		for i in (0..nb-1).rev() {
+			P.dbl();
+			W.selector(&T1,(2*w1[i]+s1[i]) as i32);
+			P.add(&mut W);
+			W.selector(&T2,(2*w2[i]+s2[i]) as i32);
+			P.add(&mut W);			
+			W.selector(&T3,(2*w3[i]+s3[i]) as i32);
+			P.add(&mut W);
+			W.selector(&T4,(2*w4[i]+s4[i]) as i32);
+			P.add(&mut W);				
+		}		
+
+// apply correction
+		W.copy(&P);   
+		W.sub(&mut Q[0]);
+		P.cmove(&W,pb1);	
+
+		W.copy(&P);   
+		W.sub(&mut Q[4]);
+		P.cmove(&W,pb2);	
+
+		W.copy(&P);   
+		W.sub(&mut Q[8]);
+		P.cmove(&W,pb3);	
+
+		W.copy(&P);   
+		W.sub(&mut Q[12]);
+		P.cmove(&W,pb4);	
+
+		P.affine();
+
+		return P;
+	}
+
+	pub fn generator() -> ECP8 {
+		return ECP8::new_fp8s(
+			&FP8::new_fp4s(
+				&FP4::new_fp2s(
+					&FP2::new_bigs(&BIG::new_ints(&rom::CURVE_PXAAA),&BIG::new_ints(&rom::CURVE_PXAAB)),
+					&FP2::new_bigs(&BIG::new_ints(&rom::CURVE_PXABA),&BIG::new_ints(&rom::CURVE_PXABB))),
+				&FP4::new_fp2s(
+					&FP2::new_bigs(&BIG::new_ints(&rom::CURVE_PXBAA),&BIG::new_ints(&rom::CURVE_PXBAB)),
+					&FP2::new_bigs(&BIG::new_ints(&rom::CURVE_PXBBA),&BIG::new_ints(&rom::CURVE_PXBBB)))),
+
+			&FP8::new_fp4s(
+				&FP4::new_fp2s(
+					&FP2::new_bigs(&BIG::new_ints(&rom::CURVE_PYAAA),&BIG::new_ints(&rom::CURVE_PYAAB)),
+					&FP2::new_bigs(&BIG::new_ints(&rom::CURVE_PYABA),&BIG::new_ints(&rom::CURVE_PYABB))),
+				&FP4::new_fp2s(
+					&FP2::new_bigs(&BIG::new_ints(&rom::CURVE_PYBAA),&BIG::new_ints(&rom::CURVE_PYBAB)),
+					&FP2::new_bigs(&BIG::new_ints(&rom::CURVE_PYBBA),&BIG::new_ints(&rom::CURVE_PYBBB)))));
+	}
+
+#[allow(non_snake_case)]
+	pub fn mapit(h: &[u8]) -> ECP8 {
+		let mut q=BIG::new_ints(&rom::MODULUS);
+		let mut x=BIG::frombytes(h);
+		x.rmod(&mut q);
+		let mut Q:ECP8;
+		let one=BIG::new_int(1);
+
+		loop {
+			let X=FP8::new_fp4(&FP4::new_fp2(&FP2::new_bigs(&one,&x)));
+			Q=ECP8::new_fp8(&X);
+			if !Q.is_infinity() {break}
+			x.inc(1); x.norm();
+		}
+		
+		let f = ECP8::frob_constants();
+		x = BIG::new_ints(&rom::CURVE_BNX);
+
+
+        let mut xQ=Q.mul(&mut x);
+        let mut x2Q=xQ.mul(&mut x);
+        let mut x3Q=x2Q.mul(&mut x);
+        let mut x4Q=x3Q.mul(&mut x);
+        let mut x5Q=x4Q.mul(&mut x);
+        let mut x6Q=x5Q.mul(&mut x);
+        let mut x7Q=x6Q.mul(&mut x);
+        let mut x8Q=x7Q.mul(&mut x);        
+
+		if ecp::SIGN_OF_X==ecp::NEGATIVEX {
+			xQ.neg();
+			x3Q.neg();
+			x5Q.neg();
+			x7Q.neg();			
+		}
+
+		x8Q.sub(&x7Q);
+		x8Q.sub(&Q);
+
+		x7Q.sub(&x6Q);
+		x7Q.frob(&f,1);
+
+		x6Q.sub(&x5Q);
+		x6Q.frob(&f,2);
+
+		x5Q.sub(&x4Q);
+		x5Q.frob(&f,3);
+
+		x4Q.sub(&x3Q);
+		x4Q.frob(&f,4);
+
+		x3Q.sub(&x2Q);
+		x3Q.frob(&f,5);
+
+		x2Q.sub(&xQ);
+		x2Q.frob(&f,6);
+
+		xQ.sub(&Q);
+		xQ.frob(&f,7);
+
+		Q.dbl();
+		Q.frob(&f,8);
+
+		Q.add(&x8Q);
+		Q.add(&x7Q);
+		Q.add(&x6Q);
+		Q.add(&x5Q);
+
+		Q.add(&x4Q);
+		Q.add(&x3Q);
+		Q.add(&x2Q);
+		Q.add(&xQ);
+
+		Q.affine();
+		return Q;
+	}
+
+}	
diff --git a/version3/rust/ff.rs b/version3/rust/ff.rs
new file mode 100644
index 0000000..ebe2746
--- /dev/null
+++ b/version3/rust/ff.rs
@@ -0,0 +1,1018 @@
+/*
+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
+if debug {println!("sf2= {}",self.tostring())}	
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use xxx::big;
+//use WWW::big::{BIG::muladd};
+use xxx::dbig::DBIG;
+use xxx::big::BIG;
+use arch::Chunk;
+use rand::RAND;
+
+//#[cfg(D32)]
+use arch::DChunk;
+
+/* Finite field support - for RSA, DH etc. */
+/* RSA/DH modulus length as multiple of BIGBITS */
+
+pub const FFLEN:usize=@ML@;
+
+pub const FF_BITS:usize=(big::BIGBITS*FFLEN); /* Finite Field Size in bits - must be 256.2^n */
+pub const HFLEN:usize=(FFLEN/2);  /* Useful for half-size RSA private key operations */
+
+pub const P_MBITS:usize=(big::MODBYTES as usize)*8;
+pub const P_OMASK:Chunk=((-1)<<(P_MBITS%big::BASEBITS));
+pub const P_FEXCESS: Chunk=(1<<(big::BASEBITS*big::NLEN-P_MBITS-1));
+pub const P_TBITS: usize=(P_MBITS%big::BASEBITS);
+
+
+//#[derive(Copy, Clone)]
+pub struct FF {
+	v:Vec<BIG>,
+	length:usize
+}
+
+//static mut debug:bool=false;
+
+impl FF { 
+
+
+    pub fn excess(a:&BIG) -> Chunk {
+        return ((a.w[big::NLEN-1]&P_OMASK)>>(P_TBITS))+1;
+    }
+
+
+//#[cfg(D32)]
+    pub fn pexceed(a: &BIG,b: &BIG) -> bool {
+        let ea=FF::excess(a);
+        let eb=FF::excess(b);
+        if ((ea+1) as DChunk)*((eb+1) as DChunk) > P_FEXCESS as DChunk {return true}
+        return false;
+    }
+
+//#[cfg(D32)]
+    pub fn sexceed(a: &BIG) -> bool {
+        let ea=FF::excess(a);
+        if ((ea+1) as DChunk)*((ea+1) as DChunk) > P_FEXCESS as DChunk {return true}
+        return false;
+    }
+/*
+#[cfg(D64)]
+    pub fn pexceed(a: &BIG,b: &BIG) -> bool {
+        let ea=FF::excess(a);
+        let eb=FF::excess(b);
+        if (ea+1) > P_FEXCESS/(eb+1) {return true}
+        return false;
+    }
+
+#[cfg(D64)]
+    pub fn sexceed(a: &BIG) -> bool {
+        let ea=FF::excess(a);
+        if (ea+1) > P_FEXCESS/(ea+1) {return true}
+        return false;
+    }    
+*/
+
+/* Constructors */
+	pub fn new_int(n:usize) -> FF {
+		let mut f=FF{v:Vec::new(),length:0};
+		for _ in 0..n {
+			f.v.push(BIG::new());
+		}
+		f.length=n;
+		return f;
+	}
+/*
+	pub fn new_ints(x: &[&[i32];big::NLEN],n: usize) -> FF {
+		let mut f=FF{v:Vec::new(),length:0};
+		for i in 0..n {
+			f.v.push(BIG::new_ints(x[i]));
+		}
+		f.length=n;
+		return f;
+	}
+*/
+	pub fn zero(&mut self) {
+		for i in 0..self.length {
+			self.v[i].zero();
+		}
+	}
+
+	pub fn getlen(&self) -> usize {
+		return self.length;
+	}
+
+/* set to integer */
+	pub fn set(&mut self,m:isize) {
+		self.zero();
+		self.v[0].set(0,m as Chunk);
+	}
+
+/* copy from FF b */
+	pub fn copy(&mut self,b: &FF) {
+		for i in 0..self.length {
+			self.v[i].copy(&b.v[i]);
+	 	}
+ 	}
+
+/* x=y<<n */
+	pub fn dsucopy(&mut self,b: &FF) {
+		for i in 0..b.length {
+			self.v[b.length+i].copy(&b.v[i]);
+			self.v[i].zero();
+		}
+	}
+
+/* x=y */
+	pub fn dscopy(&mut self,b: &FF) {
+		for i in 0..b.length {
+			self.v[i].copy(&b.v[i]);
+			self.v[b.length+i].zero();
+		}
+	}
+
+/* x=y>>n */
+	pub fn sducopy(&mut self,b: &FF) {
+		for i in 0..self.length {
+			self.v[i].copy(&b.v[self.length+i]);
+		}
+	}
+
+	pub fn one(&mut self) {
+		self.v[0].one();
+		for i in 1..self.length {
+			self.v[i].zero();
+		}
+	}
+
+/* test equals 0 */
+	pub fn iszilch(&mut self) -> bool {
+		for i in 0..self.length {
+			if !self.v[i].iszilch() {return false}
+		}
+		return true;
+	}
+
+/* shift right by BIGBITS-bit words */
+	pub fn shrw(&mut self,n: usize) {
+    	let mut t= BIG::new(); 
+		for i in 0..n {
+			t.copy(&self.v[i+n]);
+			self.v[i].copy(&t);
+			self.v[i+n].zero();
+		}
+	}
+
+/* shift left by BIGBITS-bit words */
+	pub fn shlw(&mut self,n: usize) {
+    	let mut t= BIG::new(); 		
+		for i in 0..n {
+			t.copy(&self.v[i]);
+			self.v[n+i].copy(&t);
+			self.v[i].zero();
+		}
+	}
+
+/* extract last bit */
+	pub fn parity(&self) -> isize {
+		return self.v[0].parity();
+	}
+
+	pub fn lastbits(&mut self,m: usize) -> isize {
+		return self.v[0].lastbits(m);
+	}
+
+/* compare x and y - must be normalised, and of same length */
+	pub fn comp(a: &FF,b: &FF) -> isize {
+		let mut i=a.length-1;
+
+		loop {
+			let j=BIG::comp(&a.v[i],&b.v[i]);
+			if j!=0 {return j}
+			if i==0 {break;}
+			i-=1;
+		}
+		return 0;
+	}	
+
+/* recursive add */
+	pub fn radd(&mut self,vp: usize,x: &FF,xp: usize,y: &FF,yp: usize,n: usize) {
+		for i in 0..n {
+			self.v[vp+i].copy(&x.v[xp+i]);
+			self.v[vp+i].add(&y.v[yp+i]);
+		}
+	}	
+
+/* recursive inc */
+	pub fn rinc(&mut self,vp: usize,y: &FF,yp: usize,n: usize) {
+		for i in 0..n {
+			self.v[vp+i].add(&y.v[yp+i]);
+		}
+	}
+
+	pub fn rsinc(&mut self,n: usize) {
+		let mut t=BIG::new();
+		for i in 0..n {
+			t.copy(&self.v[i]);
+			self.v[n+i].add(&t);
+		}		
+	}
+
+/* recursive sub */
+	pub fn rsub(&mut self,vp: usize,x: &FF,xp: usize,y: &FF,yp: usize,n: usize) {
+		for i in 0..n {
+			self.v[vp+i].copy(&x.v[xp+i]);
+			self.v[vp+i].sub(&y.v[yp+i]);
+		}
+	}
+
+/* recursive dec */
+	pub fn rdec(&mut self,vp: usize,y: &FF,yp: usize,n: usize) {
+		for i in 0..n {
+			self.v[vp+i].sub(&y.v[yp+i]);
+		}
+	}
+
+/* simple add */
+	pub fn add(&mut self,b: &FF) {
+		for i in 0..self.length {
+			self.v[i].add(&b.v[i]);
+		}
+	}
+
+/* simple sub */
+	pub fn sub(&mut self,b: &FF) {
+		for i in 0..self.length {
+			self.v[i].sub(&b.v[i]);
+		}
+	}
+	
+/* reverse sub */
+	pub fn revsub(&mut self,b: &FF) {
+		for i in 0..self.length {
+			self.v[i].rsub(&b.v[i]);
+		}
+	}
+
+/* normalise - but hold any overflow in top part unless n<0 */
+	pub fn rnorm(&mut self,vp: usize,n: isize) {
+		let mut trunc=false;
+		let mut carry:Chunk;
+		let mut nn:usize=n as usize; 
+		if n<0 { /* -v n signals to do truncation */
+			nn=(-n) as usize;
+			trunc=true;
+		}
+		for i in 0..nn-1 {
+			carry=self.v[vp+i].norm();
+			self.v[vp+i].xortop(carry<<P_TBITS);
+			self.v[vp+i+1].w[0]+=carry; //incl(carry);
+		}
+		carry=self.v[vp+nn-1].norm();
+		if trunc {
+			self.v[vp+nn-1].xortop(carry<<P_TBITS);
+		}
+	}
+
+	pub fn norm(&mut self) {
+		let n:isize=self.length as isize;
+		self.rnorm(0,n);
+	}
+
+/* increment/decrement by a small integer */
+	pub fn inc(&mut self,m: isize) {
+		self.v[0].inc(m);
+		self.norm();
+	}
+
+	pub fn dec(&mut self,m: isize) {
+		self.v[0].dec(m);
+		self.norm();
+	}
+
+/* shift left by one bit */
+	pub fn shl(&mut self) {
+		let mut delay_carry:isize=0;
+		for i in 0..self.length-1 {
+			let carry=self.v[i].fshl(1);
+			self.v[i].inc(delay_carry);
+			self.v[i].xortop((carry as Chunk)<<P_TBITS);
+			delay_carry=carry;
+		}
+		self.v[self.length-1].fshl(1);
+		self.v[self.length-1].inc(delay_carry);
+	}
+
+/* shift right by one bit */
+
+	pub fn shr(&mut self) {
+		let mut i=self.length-1;
+		while i>0 {
+			let carry=self.v[i].fshr(1);
+			self.v[i-1].xortop((carry as Chunk)<<P_TBITS);
+			i-=1;
+		}
+		self.v[0].fshr(1);
+	}
+
+/* Convert to Hex String */
+	pub fn tostring(&mut self) -> String {
+		self.norm();
+		let mut s = String::new();
+		let mut i:usize=self.length-1;
+		loop {
+			s=s+self.v[i].tostring().as_ref();
+			if i==0 {break}
+			i-=1;
+		}
+		return s;
+	}
+
+/* Convert to Hex String 
+	pub fn tostr(&mut self,n:usize) -> String {
+		let mut t=FF::new_int(n);
+		for i in 0..n {
+			t.v[i].copy(&self.v[i]);
+		}
+		t.norm();
+		let mut s = String::new();
+		let mut i:usize=t.length-1;
+		loop {
+			s=s+t.v[i].tostring().as_ref();
+			if i==0 {break}
+			i-=1;
+		}
+		return s;
+	}*/
+
+/* Convert FFs to/from byte arrays */
+	pub fn tobytes(&mut self,b: &mut [u8]) {
+		for i in 0..self.length {
+			self.v[i].tobytearray(b,(self.length-i-1)*(big::MODBYTES as usize))
+		}
+	}
+
+	pub fn frombytes(x: &mut FF,b: &[u8]) {
+		for i in 0..x.length {
+			x.v[i]=BIG::frombytearray(b,(x.length-i-1)*(big::MODBYTES as usize))
+		}
+	}
+
+/* in-place swapping using xor - side channel resistant - lengths must be the same */
+	pub fn cswap(a: &mut FF,b: &mut FF,d: isize) {
+		for i in 0..a.length {
+			a.v[i].cswap(&mut b.v[i],d);
+		}
+	}
+
+/* z=x*y, t is workspace */
+	fn karmul(&mut self,vp: usize,x: &FF,xp: usize,y: &FF,yp: usize,t: *mut FF,tp: usize,n: usize) {
+		if n==1 {
+			let xx= BIG::new_copy(&x.v[xp]);
+			let yy= BIG::new_copy(&y.v[yp]);
+			let mut d=BIG::mul(&xx,&yy);
+			self.v[vp+1]=d.split(8*big::MODBYTES);
+			self.v[vp].dcopy(&d);
+			return;
+		}
+		let nd2=n/2;
+		self.radd(vp,x,xp,x,xp+nd2,nd2);
+		self.rnorm(vp,nd2 as isize);       /* Important - required for 32-bit build */
+		self.radd(vp+nd2,y,yp,y,yp+nd2,nd2);
+		self.rnorm(vp+nd2,nd2 as isize);    /* Important - required for 32-bit build */
+		unsafe{
+			(*t).karmul(tp,self,vp,self,vp+nd2,t,tp+n,nd2);
+		}
+		self.karmul(vp,x,xp,y,yp,t,tp+n,nd2);
+		self.karmul(vp+n,x,xp+nd2,y,yp+nd2,t,tp+n,nd2);
+		unsafe {
+			(*t).rdec(tp,self,vp,n);
+			(*t).rdec(tp,self,vp+n,n);
+			self.rinc(vp+nd2,&(*t),tp,n);
+		}
+		self.rnorm(vp,(2*n) as isize);
+	}
+
+	fn karsqr(&mut self,vp: usize,x: &FF,xp: usize,t: *mut FF,tp: usize,n: usize) {
+		if n==1 {
+			let xx= BIG::new_copy(&x.v[xp]);	
+			let mut d=BIG::sqr(&xx);
+			self.v[vp+1].copy(&d.split(8*big::MODBYTES));
+			self.v[vp].dcopy(&d);
+			return;
+		}	
+
+		let nd2=n/2;
+		self.karsqr(vp,x,xp,t,tp+n,nd2);
+		self.karsqr(vp+n,x,xp+nd2,t,tp+n,nd2);
+		unsafe {
+			(*t).karmul(tp,x,xp,x,xp+nd2,t,tp+n,nd2);
+			self.rinc(vp+nd2,&(*t),tp,n);
+			self.rinc(vp+nd2,&(*t),tp,n);
+		}
+		self.rnorm(vp+nd2,n as isize);
+	}
+
+/* Calculates Least Significant bottom half of x*y */
+	fn karmul_lower(&mut self,vp: usize,x: &FF,xp: usize,y: &FF,yp: usize,t: *mut FF,tp: usize,n: usize) { 
+		if n==1 { /* only calculate bottom half of product */
+			self.v[vp].copy(&BIG::smul(&x.v[xp],&y.v[yp]));
+			return;
+		}
+		let nd2=n/2;
+
+		self.karmul(vp,x,xp,y,yp,t,tp+n,nd2);
+		unsafe {
+			(*t).karmul_lower(tp,x,xp+nd2,y,yp,t,tp+n,nd2);
+			self.rinc(vp+nd2,&(*t),tp,nd2);
+			(*t).karmul_lower(tp,x,xp,y,yp+nd2,t,tp+n,nd2);
+			self.rinc(vp+nd2,&(*t),tp,nd2);
+		}
+		let sn:isize=nd2 as isize;
+		self.rnorm(vp+nd2,-sn);  /* truncate it */
+	}
+
+/* Calculates Most Significant upper half of x*y, given lower part */
+	fn karmul_upper(&mut self,x: &FF,y: &FF,t: *mut FF,n: usize) { 
+		let nd2=n/2;
+		self.radd(n,x,0,x,nd2,nd2);
+		self.radd(n+nd2,y,0,y,nd2,nd2);
+		self.rnorm(n,nd2 as isize);
+		self.rnorm(n+nd2,nd2 as isize);
+
+		unsafe {			
+			(*t).karmul(0,self,n+nd2,self,n,t,n,nd2);  /* t = (a0+a1)(b0+b1) */
+
+		}
+		self.karmul(n,x,nd2,y,nd2,t,n,nd2); /* z[n]= a1*b1 */
+					/* z[0-nd2]=l(a0b0) z[nd2-n]= h(a0b0)+l(t)-l(a0b0)-l(a1b1) */
+		unsafe {
+			(*t).rdec(0,self,n,n);              /* t=t-a1b1  */										
+			self.rsinc(nd2);  /* z[nd2-n]+=l(a0b0) = h(a0b0)+l(t)-l(a1b1)  */
+			self.rdec(nd2,&(*t),0,nd2);   /* z[nd2-n]=h(a0b0)+l(t)-l(a1b1)-l(t-a1b1)=h(a0b0) */			
+		}
+
+		let sn:isize=n as isize;
+		self.rnorm(0,-sn);		/* a0b0 now in z - truncate it */
+		unsafe {
+			(*t).rdec(0,self,0,n);         /* (a0+a1)(b0+b1) - a0b0 */
+			self.rinc(nd2,&(*t),0,n);
+		}
+		self.rnorm(nd2,sn);
+	}
+
+/* z=x*y. Assumes x and y are of same length. */
+	pub fn mul(x: &FF,y: &FF) -> FF {
+		let n=x.length;
+		let mut z=FF::new_int(2*n);
+		let mut t=FF::new_int(2*n);
+	//	x.norm(); y.norm();
+		z.karmul(0,&x,0,&y,0,&mut t,0,n);
+		return z;
+	}
+
+/* return low part of product this*y */
+	pub fn lmul(&mut self,y: &FF) {
+		let n=self.length;
+		let mut t=FF::new_int(2*n);
+		let mut x=FF::new_int(n); x.copy(&self);
+	//	x.norm(); y.norm();		
+		self.karmul_lower(0,&x,0,&y,0,&mut t,0,n);
+	}
+
+/* Set b=b mod c */
+	pub fn rmod(&mut self,m: &FF) {
+		let mut k=1;  
+		let n=m.length;
+		let mut c=FF::new_int(n); c.copy(m);
+
+		self.norm();
+		if FF::comp(&self,&c)<0 {return}
+
+		c.shl();
+		while FF::comp(&self,&c)>=0 {
+			c.shl();
+			k+=1;
+		}
+
+		while k>0 {
+			c.shr();
+			if FF::comp(&self,&c)>=0 {
+				self.sub(&c);
+				self.norm();
+			}
+			k-=1;
+		}
+	}
+
+/* z=x^2 */
+	pub fn sqr(x: &FF) -> FF {
+		let n=x.length;
+		let mut z=FF::new_int(2*n);
+		let mut t=FF::new_int(2*n);
+	//	x.norm();
+		z.karsqr(0,&x,0,&mut t,0,n);
+		return z;
+	}
+
+/* return This mod modulus, ms is modulus, md is Montgomery Constant */
+	pub fn reduce(&mut self,ms: &FF,md: &FF) -> FF { /* fast karatsuba Montgomery reduction */
+		let n=ms.length;
+		let mut t=FF::new_int(2*n);
+		let mut r=FF::new_int(n);
+		let mut m=FF::new_int(n);
+
+		r.sducopy(&self);
+		m.karmul_lower(0,&self,0,&md,0,&mut t,0,n);
+		self.karmul_upper(&ms,&m,&mut t,n);
+	
+		m.sducopy(self);
+		r.add(&ms);	
+		r.sub(&m);	
+		r.norm();
+
+		return r;
+	}
+
+/* Set r=this mod b */
+/* this is of length - 2*n */
+/* r,b is of length - n */
+	pub fn dmod(&mut self,b: &FF) -> FF {
+		let n=b.length;
+		let mut m=FF::new_int(2*n);
+		let mut x=FF::new_int(2*n);
+		let mut r=FF::new_int(n);
+
+		x.copy(&self);
+		x.norm();
+		m.dsucopy(&b); let mut k=big::BIGBITS*n;
+
+		while FF::comp(&x,&m)>=0 {
+			x.sub(&m);
+			x.norm();
+		}
+
+		while k>0 {	
+			m.shr();
+
+			if FF::comp(&x,&m)>=0 {
+				x.sub(&m);
+				x.norm();
+			}
+			k-=1;
+		}
+
+		r.copy(&x);
+		r.rmod(b);
+		return r;
+	}
+
+/* Set return=1/this mod p. Binary method - a<p on entry */
+
+	pub fn invmodp(&mut self,p: &FF) {
+		let n=p.length;
+
+		let mut u=FF::new_int(n);
+		let mut v=FF::new_int(n);
+		let mut x1=FF::new_int(n);
+		let mut x2=FF::new_int(n);
+		let mut t=FF::new_int(n);
+		let mut one=FF::new_int(n);
+
+		one.one();
+		u.copy(&self);
+		v.copy(&p);
+		x1.copy(&one);
+		x2.zero();
+
+	// reduce n in here as well! 
+		while FF::comp(&u,&one)!=0 && FF::comp(&v,&one)!=0 {
+			while u.parity()==0 {
+				u.shr();
+				if x1.parity()!=0 {
+					x1.add(&p);
+					x1.norm();
+				}
+				x1.shr();
+			}
+			while v.parity()==0 {
+				v.shr(); 
+				if x2.parity()!=0 {
+					x2.add(&p);
+					x2.norm();
+				}
+				x2.shr();
+			}
+			if FF::comp(&u,&v)>=0 {
+				u.sub(&v);
+				u.norm();
+				if FF::comp(&x1,&x2)>=0 {
+					x1.sub(&x2);
+				} else {
+					t.copy(&p);
+					t.sub(&x2);
+					x1.add(&t);
+				}
+				x1.norm();
+			} else {
+				v.sub(&u);
+				v.norm();
+				if FF::comp(&x2,&x1)>=0 { 
+					x2.sub(&x1);
+				} else {
+					t.copy(&p);
+					t.sub(&x1);
+					x2.add(&t);
+				}
+				x2.norm();
+			}
+		}
+		if FF::comp(&u,&one)==0 {
+			self.copy(&x1);
+		} else {
+			self.copy(&x2);
+		}
+	}
+
+/* nresidue mod m */
+	pub fn nres(&mut self,m: &FF) {
+		let n=m.length;
+		if n==1 {
+			let mut d=DBIG::new_scopy(&(self.v[0]));
+			d.shl(big::NLEN*(big::BASEBITS as usize));
+			self.v[0].copy(&d.dmod(&(m.v[0])));
+		} else {
+			let mut d=FF::new_int(2*n);
+			d.dsucopy(&self);
+			self.copy(&d.dmod(m));
+		}
+	}
+
+	pub fn redc(&mut self,m: &FF,md: &FF) {
+		let n=m.length;
+		if n==1 {
+			let mut d=DBIG::new_scopy(&(self.v[0]));
+			self.v[0].copy(&BIG::monty(&(m.v[0]),((1 as Chunk)<<big::BASEBITS)-md.v[0].w[0],&mut d));			
+		} else {
+			let mut d=FF::new_int(2*n);
+			self.rmod(m);
+			d.dscopy(&self);
+			self.copy(&d.reduce(&m,&md));
+			self.rmod(m);
+		}
+	}
+
+	pub fn mod2m(&mut self,m: usize) {
+	 	for i in m..self.length {
+			self.v[i].zero()
+		}
+	}
+
+/* U=1/a mod 2^m - Arazi & Qi */
+	pub fn invmod2m(&self) -> FF {
+		let n=self.length;
+
+		let mut b=FF::new_int(n);
+		let mut c=FF::new_int(n);
+		let mut u=FF::new_int(n);
+
+		u.zero();
+		u.v[0].copy(&self.v[0]);
+		u.v[0].invmod2m();
+
+		let mut i=1;
+		while i<n {
+			b.copy(&self); b.mod2m(i);
+			let mut t=FF::mul(&u,&b); t.shrw(i); b.copy(&t);
+			c.copy(&self); c.shrw(i); c.mod2m(i);
+			c.lmul(&u); c.mod2m(i);
+
+			b.add(&c); b.norm();
+			b.lmul(&u); b.mod2m(i);
+
+			c.one(); c.shlw(i); b.revsub(&c); b.norm();
+			b.shlw(i);
+			u.add(&b);
+			i<<=1;
+		}
+		u.norm();
+		return u;
+	}	
+
+	pub fn random(&mut self,rng: &mut RAND) {
+		let n=self.length;
+		for i in 0..n {
+			self.v[i].copy(&BIG::random(rng))
+		}
+	/* make sure top bit is 1 */
+		while self.v[n-1].nbits()<(big::MODBYTES as usize)*8 {
+			self.v[n-1].copy(&BIG::random(rng));
+		}
+	}
+
+/* generate random x less than p */
+	pub fn randomnum(&mut self,p: &FF,rng: &mut RAND) {
+		let n=self.length;
+		let mut d=FF::new_int(2*n);
+
+		for i in 0..2*n {
+			d.v[i].copy(&BIG::random(rng));
+		}
+		self.copy(&d.dmod(p));
+	}
+
+/* this*=y mod p */
+	pub fn modmul(&mut self,y: &FF,p: &FF,nd: &FF) {
+		if FF::pexceed(&self.v[self.length-1],&y.v[y.length-1]) {
+			self.rmod(p)
+		}
+		let n=p.length;
+		if n==1 {
+			let mut d=BIG::mul(&self.v[0],&y.v[0]);
+			self.v[0].copy(&BIG::monty(&(p.v[0]),((1 as Chunk)<<big::BASEBITS)-nd.v[0].w[0],&mut d));				
+		} else {
+			let mut d=FF::mul(&self,y);
+			self.copy(&d.reduce(p,nd));
+		}
+	}
+
+/* this*=y mod p */
+	pub fn modsqr(&mut self,p: &FF,nd: &FF) {
+		if FF::sexceed(&self.v[self.length-1]) {
+			self.rmod(p);
+		}
+		let n=p.length;
+		if n==1 {
+			let mut d=BIG::sqr(&self.v[0]);
+			self.v[0].copy(&BIG::monty(&(p.v[0]),((1 as Chunk)<<big::BASEBITS)-nd.v[0].w[0],&mut d));			
+		} else {		
+			let mut d=FF::sqr(&self);
+			d.norm();
+			self.copy(&d.reduce(p,nd));
+		}
+	}
+
+/* this=this^e mod p using side-channel resistant Montgomery Ladder, for large e */
+	pub fn skpow(&mut self,e: &FF,p: &FF) {
+		let n=p.length;
+		let mut r0=FF::new_int(n);
+		let mut r1=FF::new_int(n);
+		let nd=p.invmod2m();
+
+		self.rmod(p);
+		r0.one();
+		r1.copy(&self);
+		r0.nres(p);
+		r1.nres(p);
+
+		let mut i=8*(big::MODBYTES as usize)*n-1;
+		loop {
+			let b=(e.v[i/(big::BIGBITS as usize)]).bit(i%(big::BIGBITS as usize)) as isize;
+			self.copy(&r0);
+			self.modmul(&r1,p,&nd);
+
+			FF::cswap(&mut r0,&mut r1,b);
+			r0.modsqr(p,&nd);
+
+			r1.copy(&self);
+			FF::cswap(&mut r0,&mut r1,b);
+			if i==0 {break}
+			i-=1;
+		}
+		self.copy(&r0);
+		self.redc(p,&nd);
+	}
+
+/* this =this^e mod p using side-channel resistant Montgomery Ladder, for short e */
+	pub fn skpows(&mut self,e: &BIG,p: &FF) {
+		let n=p.length;
+		let mut r0=FF::new_int(n);
+		let mut r1=FF::new_int(n);
+		let nd=p.invmod2m();
+
+		self.rmod(p);
+		r0.one();
+		r1.copy(&self);
+		r0.nres(p);
+		r1.nres(p);
+
+		let mut i=8*(big::MODBYTES as usize)-1;
+		loop {
+			let b=e.bit(i);
+			self.copy(&r0);
+			self.modmul(&r1,p,&nd);
+
+			FF::cswap(&mut r0,&mut r1,b);
+			r0.modsqr(p,&nd);
+
+			r1.copy(&self);
+			FF::cswap(&mut r0,&mut r1,b);
+			if i==0 {break}
+			i-=1;			
+		}
+		self.copy(&r0);
+		self.redc(p,&nd);
+	}
+
+
+
+
+/* raise to an integer power - right-to-left method */
+	pub fn power(&mut self,e: isize,p: &FF) {
+		let n=p.length;
+		let mut w=FF::new_int(n);
+		let nd=p.invmod2m();
+		let mut f=true;
+		let mut ee=e;
+
+		w.copy(&self);
+		w.nres(p);
+
+		if ee==2 {
+			self.copy(&w);
+			self.modsqr(p,&nd);
+		} else {
+			loop {
+				if ee%2==1 {
+					if f {
+						self.copy(&w);
+					} else {self.modmul(&w,p,&nd)}
+					f=false;
+				}
+				ee>>=1;
+				if ee==0 {break}
+				w.modsqr(p,&nd);	
+			}
+		}
+
+		self.redc(p,&nd);
+	}
+
+/* this=this^e mod p, faster but not side channel resistant */
+	pub fn pow(&mut self,e: &FF,p: &FF) {
+		let n=p.length;
+		let mut w=FF::new_int(n);
+		let nd=p.invmod2m();
+
+		w.copy(&self);
+		self.one();
+		self.nres(p);
+		w.nres(p);
+		let mut i=8*(big::MODBYTES as usize)*n-1;
+		loop {
+			self.modsqr(p,&nd);
+			let b=(e.v[i/(big::BIGBITS as usize)]).bit(i%(big::BIGBITS as usize)) as isize;			
+			if b==1 {self.modmul(&w,p,&nd)}
+			if i==0 {break}
+			i-=1;				
+		}
+		self.redc(p,&nd);
+	}
+
+/* double exponentiation r=x^e.y^f mod p */
+	pub fn pow2(&mut self,e: &BIG,y: &FF,f: &BIG,p: &FF) {
+		let n=p.length;
+		let mut xn=FF::new_int(n);
+		let mut yn=FF::new_int(n);
+		let mut xy=FF::new_int(n);
+		let nd=p.invmod2m();
+
+		xn.copy(&self);
+		yn.copy(y);
+		xn.nres(p);
+		yn.nres(p);
+		xy.copy(&xn); xy.modmul(&yn,p,&nd);
+		self.one();
+		self.nres(p);
+
+		let mut i=8*(big::MODBYTES as usize)-1;
+		loop {
+			let eb=e.bit(i);
+			let fb=f.bit(i);
+			self.modsqr(p,&nd);
+			if eb==1 {
+				if fb==1 {
+					self.modmul(&xy,p,&nd);
+				} else {self.modmul(&xn,p,&nd)}
+			} else	{
+				if fb==1 {self.modmul(&yn,p,&nd)}
+			}
+			if i==0 {break}
+			i-=1;				
+		}
+		self.redc(p,&nd);
+	}
+
+	pub fn igcd(x: isize,y: isize) -> isize { /* integer GCD, returns GCD of x and y */
+
+		if y==0 {return x}	
+		let mut xx=x;
+		let mut yy=y;		
+		loop {
+			let r=xx%yy;
+			if r==0 {break}
+			xx=yy;yy=r;
+		}
+		return yy;
+	}
+
+/* quick and dirty check for common factor with n */
+	pub fn cfactor(&self,s: isize) -> bool {
+		let n=self.length;
+
+		let mut x=FF::new_int(n);
+		let mut y=FF::new_int(n);
+
+		y.set(s);
+		x.copy(&self);
+		x.norm();
+
+		x.sub(&y);
+		x.norm();
+
+		while !x.iszilch() && x.parity()==0 {x.shr()}
+
+		while FF::comp(&x,&y)>0 {
+			x.sub(&y);
+			x.norm();
+			while !x.iszilch() && x.parity()==0 {x.shr()}
+		}
+
+		let g=x.v[0].get(0) as isize;
+		let r=FF::igcd(s,g);
+		if r>1 {return true}
+		return false
+	}
+
+/* Miller-Rabin test for primality. Slow. */
+	pub fn prime(pp: &FF,rng: &mut RAND) -> bool {
+		let mut s=0;
+		let n=pp.length;
+		let mut d=FF::new_int(n);
+		let mut x=FF::new_int(n);
+		let mut unity=FF::new_int(n);
+		let mut nm1=FF::new_int(n);
+		let mut p=FF::new_int(n); p.copy(pp);
+
+		let sf=4849845; /* 3*5*.. *19 */
+		p.norm();
+
+		if p.cfactor(sf) {return false}
+		unity.one();
+		nm1.copy(&p);
+		nm1.sub(&unity);
+		nm1.norm();
+		d.copy(&nm1);
+
+		while d.parity()==0 {
+			d.shr();
+			s+=1;
+		}
+		if s==0 {return false}
+		for _ in 0..10 {
+			x.randomnum(&p,rng);
+
+			x.pow(&d,&p);
+		
+			if FF::comp(&x,&unity)==0 || FF::comp(&x,&nm1)==0 {continue}
+			let mut looper=false;
+			for _ in 1..s {
+				x.power(2,&p);
+				if FF::comp(&x,&unity)==0 {return false}
+				if FF::comp(&x,&nm1)==0 {looper=true; break}
+			}
+			if looper {continue}
+			return false;
+		}
+
+		return true;
+	}
+
+}
+/*
+fn main()
+{
+	let mut x=FF::new_int(4);
+	let mut y=FF::new_int(4);
+
+	x.one(); y.one();
+	let mut z=FF::mul(&mut x,&mut y);
+
+	println!("z= {}",z.tostring());
+}
+*/
diff --git a/version3/rust/fp.rs b/version3/rust/fp.rs
new file mode 100644
index 0000000..f9b77da
--- /dev/null
+++ b/version3/rust/fp.rs
@@ -0,0 +1,625 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use xxx::big;
+use xxx::big::BIG;
+use xxx::dbig::DBIG;
+use xxx::rom;
+use arch::Chunk;
+use arch;
+
+//#[cfg(D32)]
+//use arch::DChunk;
+
+#[derive(Copy, Clone)]
+pub struct FP {
+ 	pub x:BIG,
+    pub xes:i32
+}
+
+pub const NOT_SPECIAL:usize =0;
+pub const PSEUDO_MERSENNE:usize=1;
+pub const MONTGOMERY_FRIENDLY:usize=2;
+pub const GENERALISED_MERSENNE:usize=3;
+
+pub const MODBITS:usize = @NBT@; /* Number of bits in Modulus */
+pub const MOD8: usize = @M8@;  /* Modulus mod 8 */
+pub const MODTYPE:usize=@MT@;
+
+pub const FEXCESS:i32 = (((1 as i32)<<@SH@)-1);
+pub const OMASK:Chunk = (-1)<<(MODBITS%big::BASEBITS);
+pub const TBITS:usize=MODBITS%big::BASEBITS; // Number of active bits in top word
+pub const TMASK:Chunk=(1<<TBITS)-1;
+
+
+impl FP {
+
+/* Constructors */
+	pub fn new() -> FP {
+		FP {
+				x: BIG::new(),
+                xes:1
+            }
+	}
+
+	pub fn new_int(a:isize) -> FP {
+		let mut f=FP::new(); 
+		f.x.inc(a);
+		f.nres();
+		return f;		
+	}
+
+	pub fn new_copy(y:&FP) -> FP {
+		let mut f=FP::new(); 
+		f.x.copy(&(y.x));
+        f.xes=y.xes;
+		return f;
+	}
+
+	pub fn new_big(y:&BIG) -> FP {
+		let mut f=FP::new(); 
+		f.x.copy(y);
+        f.nres();
+		return f;		
+	}
+
+    pub fn nres(&mut self) {
+        if MODTYPE != PSEUDO_MERSENNE && MODTYPE != GENERALISED_MERSENNE {
+            let r=BIG::new_ints(&rom::R2MODP);
+            let mut d=BIG::mul(&(self.x),&r);
+            self.x.copy(&FP::modulo(&mut d));
+            self.xes=2;
+        } else {
+            self.xes=1;
+        }
+
+    }
+
+/* convert back to regular form */
+    pub fn redc(&mut self) -> BIG {
+        if MODTYPE != PSEUDO_MERSENNE && MODTYPE != GENERALISED_MERSENNE {
+            let mut d=DBIG::new_scopy(&(self.x));
+            return FP::modulo(&mut d);
+        } else {
+            let r=BIG::new_copy(&(self.x));
+            return r;
+        }
+    }
+
+
+/* reduce a DBIG to a BIG using the appropriate form of the modulus */
+/* dd */
+    pub fn modulo(d: &mut DBIG) -> BIG {
+    
+        if MODTYPE==PSEUDO_MERSENNE {
+            let mut b=BIG::new();
+            let mut t=d.split(MODBITS);
+            b.dcopy(&d);
+            let v=t.pmul(rom::MCONST as isize);
+
+            t.add(&b);
+            t.norm();
+
+
+            let tw=t.w[big::NLEN-1];
+            t.w[big::NLEN-1] &= TMASK;
+            t.w[0]+=rom::MCONST*((tw>>TBITS)+(v<<(big::BASEBITS-TBITS)));
+            t.norm();
+            return t;
+        }
+    
+        if MODTYPE==MONTGOMERY_FRIENDLY
+        {
+            let mut b=BIG::new();
+            for i in 0 ..big::NLEN {
+                let x=d.w[i];
+
+                let tuple=BIG::muladd(x,rom::MCONST-1,x,d.w[big::NLEN+i-1]);
+                d.w[big::NLEN+i]+=tuple.0; d.w[big::NLEN+i-1]=tuple.1;
+            }
+    
+            b.zero();
+    
+            for i in 0 ..big::NLEN {
+                b.w[i]=d.w[big::NLEN+i];
+            }
+            b.norm();
+            return b;
+        }
+            
+        if MODTYPE==GENERALISED_MERSENNE
+        { // GoldiLocks Only
+            let mut b=BIG::new();            
+            let t=d.split(MODBITS);
+            let rm2=(MODBITS/2) as usize;
+            b.dcopy(&d);
+            b.add(&t);
+            let mut dd=DBIG::new_scopy(&t);
+            dd.shl(rm2);
+            
+            let mut tt=dd.split(MODBITS);
+            let lo=BIG::new_dcopy(&dd);
+            b.add(&tt);
+            b.add(&lo);
+            b.norm();
+            tt.shl(rm2);
+            b.add(&tt);
+            
+            let carry=b.w[big::NLEN-1]>>TBITS;
+            b.w[big::NLEN-1]&=TMASK;
+            b.w[0]+=carry;
+            
+            b.w[(224/big::BASEBITS) as usize]+=carry<<(224%big::BASEBITS);
+            b.norm();
+            return b;
+        }
+       
+        if MODTYPE==NOT_SPECIAL {
+            let m = BIG::new_ints(&rom::MODULUS);              
+            return BIG::monty(&m,rom::MCONST,d);
+        }     
+        return BIG::new();
+    }
+
+   /* convert to string */
+	pub fn tostring(&mut self) -> String {
+        let s=self.redc().tostring();
+        return s;
+    }
+
+/* reduce this mod Modulus */
+    pub fn reduce(&mut self) {
+        let mut m = BIG::new_ints(&rom::MODULUS);
+	let mut r = BIG::new_copy(&m);
+        let mut sb : usize;
+	self.x.norm();
+	if self.xes>16 {
+		let q=FP::quo(&self.x,&m);
+		let carry=r.pmul(q);
+		r.w[big::NLEN-1]+=carry<<big::BASEBITS; // correction - put any carry out back in again
+		self.x.sub(&r);
+		self.x.norm();
+		sb=2;
+	} else { 
+		sb=FP::logb2((self.xes-1) as u32);
+	}
+        m.fshl(sb);
+
+        while sb>0 {
+            let sr=BIG::ssn(&mut r,&self.x,&mut m);
+	    self.x.cmove(&r,1-sr);
+            sb=sb-1;
+	}
+
+        self.xes=1;
+    }
+    
+/* test this=0? */
+    pub fn iszilch(&self) -> bool {
+        let mut a=FP::new_copy(self);
+        a.reduce();
+        return a.x.iszilch();
+    }
+    
+/* copy from FP b */
+    pub fn copy(&mut self,b: &FP) {
+        self.x.copy(&(b.x));
+        self.xes=b.xes;
+    }
+    
+/* copy from BIG b */
+    pub fn bcopy(&mut self,b: &BIG) {
+        self.x.copy(&b);
+        self.nres();
+    }
+
+/* set this=0 */
+    pub fn zero(&mut self) {
+        self.x.zero();
+        self.xes=1;
+    }
+    
+/* set this=1 */
+    pub fn one(&mut self) {
+        self.x.one(); self.nres()
+    }
+    
+/* normalise this */
+    pub fn norm(&mut self) {
+        self.x.norm();
+    }
+/* swap FPs depending on d */
+    pub fn cswap(&mut self,b: &mut FP,d: isize) {
+        self.x.cswap(&mut (b.x),d);
+        let mut c=d as i32;
+        c=!(c-1);
+        let t=c&(self.xes^b.xes);
+        self.xes^=t;
+        b.xes^=t;
+    }
+    
+/* copy FPs depending on d */
+    pub fn cmove(&mut self,b: &FP,d: isize) {
+        self.x.cmove(&(b.x),d);
+        let c=d as i32;
+        self.xes^=(self.xes^b.xes)&(-c);
+    }
+
+/* this*=b mod Modulus */
+    pub fn mul(&mut self,b: &FP)
+    {
+        if (self.xes as i64)*(b.xes as i64) > FEXCESS as i64 {self.reduce()}
+
+        let mut d=BIG::mul(&(self.x),&(b.x));
+        self.x.copy(&FP::modulo(&mut d));
+        self.xes=2;
+    }
+
+    fn logb2(w: u32) -> usize {
+        let mut v=w;
+        v |= v >> 1;
+        v |= v >> 2;
+        v |= v >> 4;
+        v |= v >> 8;
+        v |= v >> 16;
+
+        v = v - ((v >> 1) & 0x55555555);                 
+        v = (v & 0x33333333) + ((v >> 2) & 0x33333333);  
+        let r= ((   ((v + (v >> 4)) & 0xF0F0F0F).wrapping_mul(0x1010101)) >> 24) as usize;
+        return r;    
+    }
+
+// find appoximation to quotient of a/m
+// Out by at most 2.
+// Note that MAXXES is bounded to be 2-bits less than half a word
+    fn quo(n: &BIG,m: &BIG) -> isize {
+	let hb=arch::CHUNK/2;
+
+	if TBITS < hb {
+		let sh=hb-TBITS;
+		let num=((n.w[big::NLEN-1]<<sh))|(n.w[big::NLEN-2]>>(big::BASEBITS-sh));
+		let den=((m.w[big::NLEN-1]<<sh))|(m.w[big::NLEN-2]>>(big::BASEBITS-sh));
+		return (num/(den+1)) as isize;
+	} else {
+		let num=n.w[big::NLEN-1];
+		let den=m.w[big::NLEN-1];
+		return (num/(den+1)) as isize;
+	}
+    }
+
+/* this = -this mod Modulus */
+    pub fn neg(&mut self) {
+  	let mut p = BIG::new_ints(&rom::MODULUS);   
+        let sb=FP::logb2((self.xes-1) as u32);
+    
+        p.fshl(sb);
+        self.x.rsub(&p);
+        self.xes=1<<(sb as i32)+1;
+        if self.xes>FEXCESS {self.reduce()}
+
+    }
+
+    /* this*=c mod Modulus, where c is a small int */
+    pub fn imul(&mut self,c: isize) {
+        let mut cc=c;
+    //    self.norm();
+        let mut s=false;
+        if cc<0 {
+            cc = -cc;
+            s=true;
+        }
+
+        if MODTYPE==PSEUDO_MERSENNE || MODTYPE==GENERALISED_MERSENNE {
+            let mut d=self.x.pxmul(cc);
+            self.x.copy(&FP::modulo(&mut d));
+            self.xes=2
+        } else {
+            if self.xes*(cc as i32) <= FEXCESS {
+                self.x.pmul(cc);
+                self.xes*=cc as i32;
+            } else {
+                let n=FP::new_int(cc);
+                self.mul(&n);
+            }
+
+        }
+
+        if s {self.neg(); self.norm();}
+    }
+
+/* self*=self mod Modulus */
+    pub fn sqr(&mut self) {
+    //    self.norm();
+        if (self.xes as i64)*(self.xes as i64) > FEXCESS as i64 {self.reduce()}
+
+
+        let mut d=BIG::sqr(&(self.x));
+        self.x.copy(&FP::modulo(&mut d));
+        self.xes=2
+    }
+
+/* self+=b */
+    pub fn add(&mut self,b: &FP) {
+        self.x.add(&(b.x));
+        self.xes+=b.xes;
+        if self.xes>FEXCESS {self.reduce()}
+    }
+
+/* self+=self */
+    pub fn dbl(&mut self) {
+        self.x.dbl();
+        self.xes+=self.xes;        
+        if self.xes>FEXCESS {self.reduce()}
+    }
+    
+/* self-=b */
+    pub fn sub(&mut self,b: &FP)
+    {
+        let mut n=FP::new_copy(b);
+        n.neg();
+        self.add(&n);
+    }    
+
+/* self=b-self */
+    pub fn rsub(&mut self,b: &FP)
+    {
+        self.neg();
+        self.add(&b);
+    }  
+
+/* self/=2 mod Modulus */
+    pub fn div2(&mut self) {
+    //    self.x.norm();
+        if self.x.parity()==0 {
+        	self.x.fshr(1);
+        } else {
+  			let p = BIG::new_ints(&rom::MODULUS);           	
+            self.x.add(&p);
+            self.x.norm();
+            self.x.fshr(1);
+        }
+    }
+
+// return this^(p-3)/4 or this^(p-5)/8
+    pub fn fpow(&mut self) -> FP {
+	let ac:[isize;11]=[1,2,3,6,12,15,30,60,120,240,255];
+	let mut xp:[FP;11]=[FP::new(),FP::new(),FP::new(),FP::new(),FP::new(),FP::new(),FP::new(),FP::new(),FP::new(),FP::new(),FP::new()];
+// phase 1
+	let mut t=FP::new();
+	xp[0].copy(&self);  // 1
+	xp[1].copy(&self); xp[1].sqr(); // 2
+	t.copy(&xp[1]); xp[2].copy(&t); xp[2].mul(&self); // 3
+	t.copy(&xp[2]); xp[3].copy(&t); xp[3].sqr(); // 6
+	t.copy(&xp[3]); xp[4].copy(&t); xp[4].sqr(); // 12
+	t.copy(&xp[4]); t.mul(&xp[2]);  xp[5].copy(&t);  // 15
+	t.copy(&xp[5]); xp[6].copy(&t); xp[6].sqr(); // 30
+	t.copy(&xp[6]); xp[7].copy(&t); xp[7].sqr(); // 60
+	t.copy(&xp[7]); xp[8].copy(&t); xp[8].sqr(); // 120
+	t.copy(&xp[8]); xp[9].copy(&t); xp[9].sqr(); // 240
+	t.copy(&xp[9]); t.mul(&xp[5]); xp[10].copy(&t); // 255
+
+	let n : isize;
+	let c : isize;
+
+	if MOD8==5 {
+		n=(MODBITS as isize)-3;
+		c=((rom::MCONST as isize)+5)/8;
+	} else {
+		n=(MODBITS as isize)-2;
+		c=((rom::MCONST as isize)+3)/4;
+
+	}
+	let mut bw=0; let mut w=1; while w<c {w*=2; bw+=1;}
+	let mut k=w-c;
+
+	let mut i=10; let mut key=FP::new();
+	if k != 0 {
+		while ac[i]>k {i-=1;}
+		key.copy(&xp[i]); 
+		k-=ac[i];
+	}
+	while k != 0 {
+		i-=1;
+		if ac[i]>k {continue;}
+		key.mul(&xp[i]);
+		k-=ac[i]; 
+	}
+// phase 2
+	t.copy(&xp[2]); xp[1].copy(&t);
+	t.copy(&xp[5]); xp[2].copy(&t);
+	t.copy(&xp[10]); xp[3].copy(&t);
+
+	let mut j=3; let mut m=8;
+	let nw=n-bw;
+	let mut r=FP::new();
+
+	while 2*m<nw {
+		t.copy(&xp[j]); j+=1;
+		for _ in 0..m {t.sqr();} 
+		r.copy(&xp[j-1]);
+		r.mul(&t);
+		xp[j].copy(&r);
+		m*=2;
+	}
+	let mut lo=nw-m;
+	r.copy(&xp[j]);
+
+	while lo != 0 {
+		m/=2; j-=1;
+		if lo<m {continue;}
+		lo-=m;
+		t.copy(&r);
+		for _ in 0..m {t.sqr();}
+		r.copy(&t);
+		r.mul(&xp[j]);
+	}
+// phase 3
+	for _ in 0..bw {r.sqr();}
+
+	if w-c != 0 {
+		r.mul(&key);
+	}
+	return r;
+    }
+/* self=1/self mod Modulus */
+    pub fn inverse(&mut self) {
+	if MODTYPE==PSEUDO_MERSENNE {
+		let mut y=self.fpow();
+		if MOD8==5 {
+			let mut t=FP::new_copy(self);
+			t.sqr();
+			self.mul(&t);
+			y.sqr();
+		} 
+		y.sqr();
+		y.sqr();
+		self.mul(&y);	
+
+        } else {
+		let mut m2 = BIG::new_ints(&rom::MODULUS); 
+		m2.dec(2); m2.norm();
+		let inv=self.pow(&mut m2);
+		self.copy(&inv);
+	}
+    }
+
+/* return TRUE if self==a */
+    pub fn equals(&self,a: &FP) -> bool {
+	let mut f=FP::new_copy(self);
+        let mut s=FP::new_copy(a);
+        f.reduce();
+        s.reduce();
+        if BIG::comp(&(f.x),&(s.x))==0 {return true}
+        return false;
+    }   
+
+
+/* return self^e mod Modulus */
+    pub fn pow(&mut self,e: &mut BIG) -> FP {
+        let mut tb:[FP;16]=[FP::new(),FP::new(),FP::new(),FP::new(),FP::new(),FP::new(),FP::new(),FP::new(),FP::new(),FP::new(),FP::new(),FP::new(),FP::new(),FP::new(),FP::new(),FP::new()];
+        const CT:usize=1+(big::NLEN*(big::BASEBITS as usize)+3)/4;
+        let mut w:[i8;CT]=[0;CT];
+
+        self.norm();
+        let mut t=BIG::new_copy(e);
+        t.norm();
+        let nb=1+(t.nbits()+3)/4;
+
+        for i in 0..nb {
+            let lsbs=t.lastbits(4);
+            t.dec(lsbs);
+            t.norm();
+            w[i]=lsbs as i8;
+            t.fshr(4);
+        }
+        tb[0].one();
+        tb[1].copy(&self);
+
+        let mut c=FP::new();
+        for i in 2..16 {
+            c.copy(&tb[i-1]);
+            tb[i].copy(&c);
+            tb[i].mul(&self);
+        }
+        let mut r=FP::new_copy(&tb[w[nb-1] as usize]);
+        for i in  (0..nb-1).rev() {
+            r.sqr();
+            r.sqr();
+            r.sqr();
+            r.sqr();
+            r.mul(&tb[w[i] as usize])
+        }
+        r.reduce();
+        return r;
+}
+
+/* return self^e mod Modulus 
+    pub fn pow(&mut self,e: &mut BIG) -> FP {
+      	let p = BIG::new_ints(&rom::MODULUS);   	
+        let mut r=FP::new_int(1);
+        e.norm();
+        self.x.norm();
+		let mut m=FP::new_copy(self);
+        loop {
+            let bt=e.parity();
+            e.fshr(1);
+            if bt==1 {r.mul(&m)}
+            if e.iszilch() {break}
+            m.sqr();
+        }
+        r.x.rmod(&p);
+        return r;
+    } */
+
+/* return sqrt(this) mod Modulus */
+    pub fn sqrt(&mut self) -> FP {
+        self.reduce();
+
+        if MOD8==5 {
+	    let v : FP;
+            let mut i=FP::new_copy(self); i.x.shl(1);
+	    if MODTYPE==PSEUDO_MERSENNE {
+		v=i.fpow();
+	    } else {
+      		let mut p = BIG::new_ints(&rom::MODULUS);  
+		p.dec(5); p.norm(); p.shr(3);
+		v=i.pow(&mut p);
+	    }
+            i.mul(&v); i.mul(&v);
+            i.x.dec(1);
+            let mut r=FP::new_copy(self);
+            r.mul(&v); r.mul(&i);
+            r.reduce();
+            return r;
+        }
+        else
+        {
+	    let mut r : FP;
+	    if MODTYPE==PSEUDO_MERSENNE {
+		r=self.fpow();
+		r.mul(self);
+	    } else {
+     		let mut p = BIG::new_ints(&rom::MODULUS);  
+		p.inc(1); p.norm(); p.shr(2);
+		r=self.pow(&mut p);
+	    }
+	    return r;
+        }
+    }
+/* return jacobi symbol (this/Modulus) */
+    pub fn jacobi(&mut self) -> isize
+    {
+     	let mut p = BIG::new_ints(&rom::MODULUS);      	
+        let mut w=self.redc();
+        return w.jacobi(&mut p);
+    }
+
+}
+/*
+fn main() {
+    let p = BIG::new_ints(&rom::MODULUS);  
+	let mut e = BIG::new_copy(&p);
+	e.dec(1);
+
+    let mut x = FP::new_int(3);
+    let mut s=x.pow(&mut e);
+
+    println!("s= {}",s.tostring());
+}
+*/
diff --git a/version3/rust/fp12.rs b/version3/rust/fp12.rs
new file mode 100644
index 0000000..d22982a
--- /dev/null
+++ b/version3/rust/fp12.rs
@@ -0,0 +1,798 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use xxx::big;
+use xxx::ecp;
+use xxx::fp2::FP2;
+use xxx::fp4::FP4;
+use xxx::big::BIG;
+use xxx::rom;
+
+#[derive(Copy, Clone)]
+pub struct FP12 {
+	a:FP4,
+	b:FP4,
+	c:FP4
+}
+
+impl FP12 {
+
+	pub fn new() -> FP12 {
+		FP12 {
+				a: FP4::new(),
+				b: FP4::new(),
+				c: FP4::new()
+		}
+	}
+
+	pub fn new_int(a: isize) -> FP12 {
+		let mut f=FP12::new();
+		f.a.copy(&FP4::new_int(a));
+		f.b.zero();
+		f.c.zero();
+		return f;
+	}	
+
+	pub fn new_copy(x: &FP12) -> FP12 {
+		let mut f=FP12::new();
+		f.a.copy(&x.a);
+		f.b.copy(&x.b);
+		f.c.copy(&x.c);
+		return f;
+	}
+
+	pub fn new_fp4s(d: &FP4,e: &FP4,f: &FP4) -> FP12 {
+		let mut g=FP12::new();
+		g.a.copy(d);
+		g.b.copy(e);
+		g.c.copy(f);
+		return g;
+	}	
+
+	pub fn new_fp4(d: &FP4) -> FP12 {
+		let mut g=FP12::new();
+		g.a.copy(d);
+		g.b.zero();
+		g.c.zero();
+		return g;
+	}
+
+/* reduce components mod Modulus */
+	pub fn reduce(&mut self) {
+		self.a.reduce();
+		self.b.reduce();
+		self.c.reduce();
+	}
+
+/* normalise components of w */
+	pub fn norm(&mut self) {
+		self.a.norm();
+		self.b.norm();
+		self.c.norm();
+	}	
+
+/* test self=0 ? */
+	pub fn iszilch(&self) -> bool {
+		//self.reduce();
+		return self.a.iszilch() && self.b.iszilch() && self.c.iszilch();
+	}	
+
+/* Conditional move of g to self dependant on d */
+	pub fn cmove(&mut self,g:&FP12,d: isize) {
+		self.a.cmove(&g.a,d);
+		self.b.cmove(&g.b,d);
+		self.c.cmove(&g.c,d);
+	}	
+
+/* return 1 if b==c, no branching */
+	fn teq(b: i32,c: i32) -> isize {
+		let mut x=b^c;
+		x-=1;  // if x=0, x now -1
+		return ((x>>31)&1) as isize;
+	}
+
+/* Constant time select from pre-computed table */
+	pub fn selector(&mut self,g: &[FP12],b: i32) {
+		let m=b>>31;
+		let mut babs=(b^m)-m;
+
+		babs=(babs-1)/2;
+
+		self.cmove(&g[0],FP12::teq(babs,0));  // conditional move
+		self.cmove(&g[1],FP12::teq(babs,1));
+		self.cmove(&g[2],FP12::teq(babs,2));
+		self.cmove(&g[3],FP12::teq(babs,3));
+		self.cmove(&g[4],FP12::teq(babs,4));
+		self.cmove(&g[5],FP12::teq(babs,5));
+		self.cmove(&g[6],FP12::teq(babs,6));
+		self.cmove(&g[7],FP12::teq(babs,7));
+ 
+ 		let mut invf=FP12::new_copy(self);
+		invf.conj();
+		self.cmove(&invf,(m&1) as isize);
+	}		
+
+
+/* test self=1 ? */
+	pub fn isunity(&self) -> bool {
+		let one=FP4::new_int(1);
+		return self.a.equals(&one) && self.b.iszilch() && self.c.iszilch();
+	}
+
+/* test self=x */
+	pub fn equals(&self,x:&FP12) -> bool {
+		return self.a.equals(&x.a) && self.b.equals(&x.b) && self.c.equals(&x.c);
+	}
+
+	pub fn geta(&mut self) -> FP4 {
+		let f=FP4::new_copy(&self.a);
+		return f;
+	}
+
+	pub fn getb(&mut self) -> FP4 {
+		let f=FP4::new_copy(&self.b);
+		return f;
+	}
+
+	pub fn getc(&mut self) -> FP4 {
+		let f=FP4::new_copy(&self.c);
+		return f;
+	}	
+
+/* copy self=x */
+	pub fn copy(&mut self,x :&FP12) {
+		self.a.copy(&x.a);
+		self.b.copy(&x.b);
+		self.c.copy(&x.c);
+	}
+
+/* set self=1 */
+	pub fn one(&mut self) {
+		self.a.one();
+		self.b.zero();
+		self.c.zero();
+	}
+
+/* this=conj(this) */
+	pub fn conj(&mut self) {
+		self.a.conj();
+		self.b.nconj();
+		self.c.conj();
+	}
+
+/* Granger-Scott Unitary Squaring */
+	pub fn usqr(&mut self) {
+		let mut a=FP4::new_copy(&self.a);
+		let mut b=FP4::new_copy(&self.c);
+		let mut c=FP4::new_copy(&self.b);
+		let mut d=FP4::new();
+
+		self.a.sqr();
+		d.copy(&self.a); d.add(&self.a);
+		self.a.add(&d);
+
+		self.a.norm();
+		a.nconj();
+
+		a.dbl();
+		self.a.add(&a);
+		b.sqr();
+		b.times_i();
+
+		d.copy(&b); d.add(&b);
+		b.add(&d);
+		b.norm();
+
+		c.sqr();
+		d.copy(&c); d.add(&c);
+		c.add(&d);
+		c.norm();
+
+		self.b.conj();
+		self.b.dbl();
+		self.c.nconj();
+
+		self.c.dbl();
+		self.b.add(&b);
+		self.c.add(&c);
+		self.reduce();
+
+	}
+
+/* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
+	pub fn sqr(&mut self) {
+		let mut a=FP4::new_copy(&self.a);
+		let mut b=FP4::new_copy(&self.b);
+		let mut c=FP4::new_copy(&self.c);
+		let mut d=FP4::new_copy(&self.a);
+
+		a.sqr();
+		b.mul(&self.c);
+		b.dbl(); b.norm();
+		c.sqr();
+		d.mul(&self.b);
+		d.dbl();
+
+		self.c.add(&self.a);
+		self.c.add(&self.b); self.c.norm();
+		self.c.sqr();
+
+		self.a.copy(&a);
+		a.add(&b);
+		a.norm();
+		a.add(&c);
+		a.add(&d);
+		a.norm();
+
+		a.neg();
+		b.times_i();
+		c.times_i();
+
+		self.a.add(&b);
+
+		self.b.copy(&c); self.b.add(&d);
+		self.c.add(&a);
+		self.norm();
+	}
+
+
+/* FP12 full multiplication self=self*y */
+	pub fn mul(&mut self,y: &FP12) {
+		let mut z0=FP4::new_copy(&self.a);
+		let mut z1=FP4::new();
+		let mut z2=FP4::new_copy(&mut self.b);
+		let mut z3=FP4::new();
+		let mut t0=FP4::new_copy(&self.a);
+		let mut t1=FP4::new_copy(&y.a);
+
+		z0.mul(&y.a);
+		z2.mul(&y.b);
+
+		t0.add(&self.b);
+		t1.add(&y.b);
+
+		t0.norm(); t1.norm();
+
+		z1.copy(&t0); z1.mul(&t1);
+		t0.copy(&self.b); t0.add(&self.c);
+		t1.copy(&y.b); t1.add(&y.c);
+
+		t0.norm(); t1.norm();	
+
+		z3.copy(&t0); z3.mul(&t1);
+
+		t0.copy(&z0); t0.neg();
+		t1.copy(&z2); t1.neg();
+
+		z1.add(&t0);
+		//z1.norm();
+		self.b.copy(&z1); self.b.add(&t1);
+
+		z3.add(&t1);
+		z2.add(&t0);
+
+		t0.copy(&self.a); t0.add(&self.c); t0.norm();
+		t1.copy(&y.a); t1.add(&y.c); t1.norm();
+		t0.mul(&t1);
+		z2.add(&t0);
+
+		t0.copy(&self.c); t0.mul(&y.c);
+		t1.copy(&t0); t1.neg();
+
+
+		self.c.copy(&z2); self.c.add(&t1);
+		z3.add(&t1);
+		t0.times_i();
+		self.b.add(&t0);
+		z3.norm();
+
+		z3.times_i();
+		self.a.copy(&z0); self.a.add(&z3);
+		self.norm();
+	}
+
+/* Special case of multiplication arises from special form of ATE pairing line function */
+	pub fn smul(&mut self,y: &FP12,twist: usize) {
+
+		if twist==ecp::D_TYPE {
+			let mut z0=FP4::new_copy(&self.a);
+			let mut z2=FP4::new_copy(&self.b);
+			let mut z3=FP4::new_copy(&self.b);
+			let mut t0=FP4::new();
+			let mut t1=FP4::new_copy(&y.a);
+		
+			z0.mul(&y.a);
+			z2.pmul(&y.b.real());
+			self.b.add(&self.a);
+			t1.padd(&y.b.real());
+
+			self.b.norm(); t1.norm();
+
+			self.b.mul(&t1);
+			z3.add(&self.c); z3.norm();
+			z3.pmul(&y.b.real());
+
+			t0.copy(&z0); t0.neg();
+			t1.copy(&z2); t1.neg();
+	
+			self.b.add(&t0);
+		//self.b.norm();
+
+			self.b.add(&t1);
+			z3.add(&t1);
+			z2.add(&t0);
+
+			t0.copy(&self.a); t0.add(&self.c);
+			t0.norm(); z3.norm();
+			
+			t0.mul(&y.a);
+			self.c.copy(&z2); self.c.add(&t0);
+
+			z3.times_i();
+			self.a.copy(&z0); self.a.add(&z3);
+		}
+		if twist==ecp::M_TYPE {
+			let mut z0=FP4::new_copy(&self.a);
+			let mut z1=FP4::new();
+			let mut z2=FP4::new();
+			let mut z3=FP4::new();
+			let mut t0=FP4::new_copy(&self.a);
+			let mut t1=FP4::new();
+		
+			z0.mul(&y.a);
+			t0.add(&self.b);
+			t0.norm();
+
+			z1.copy(&t0); z1.mul(&y.a);
+			t0.copy(&self.b); t0.add(&self.c);
+			t0.norm();
+
+			z3.copy(&t0); //z3.mul(y.c);
+			z3.pmul(&y.c.getb());
+			z3.times_i();
+
+			t0.copy(&z0); t0.neg();
+
+			z1.add(&t0);
+			self.b.copy(&z1); 
+			z2.copy(&t0);
+
+			t0.copy(&self.a); t0.add(&self.c);
+			t1.copy(&y.a); t1.add(&y.c);
+
+			t0.norm();
+			t1.norm();
+	
+			t0.mul(&t1);
+			z2.add(&t0);
+
+			t0.copy(&self.c);
+			
+			t0.pmul(&y.c.getb());
+			t0.times_i();
+
+			t1.copy(&t0); t1.neg();
+
+			self.c.copy(&z2); self.c.add(&t1);
+			z3.add(&t1);
+			t0.times_i();
+			self.b.add(&t0);
+			z3.norm();
+			z3.times_i();
+			self.a.copy(&z0); self.a.add(&z3);
+		}
+		self.norm();		
+	}
+
+/* self=1/self */
+	pub fn inverse(&mut self) {
+		let mut f0=FP4::new_copy(&self.a);
+		let mut f1=FP4::new_copy(&self.b);
+		let mut f2=FP4::new_copy(&self.a);
+		let mut f3=FP4::new();
+
+		self.norm();
+		f0.sqr();
+		f1.mul(&self.c);
+		f1.times_i();
+		f0.sub(&f1); f0.norm();
+
+		f1.copy(&self.c); f1.sqr();
+		f1.times_i();
+		f2.mul(&self.b);
+		f1.sub(&f2); f1.norm();
+
+		f2.copy(&self.b); f2.sqr();
+		f3.copy(&self.a); f3.mul(&self.c);
+		f2.sub(&f3); f2.norm();
+
+		f3.copy(&self.b); f3.mul(&f2);
+		f3.times_i();
+		self.a.mul(&f0);
+		f3.add(&self.a);
+		self.c.mul(&f1);
+		self.c.times_i();
+
+		f3.add(&self.c); f3.norm();
+		f3.inverse();
+		self.a.copy(&f0); self.a.mul(&f3);
+		self.b.copy(&f1); self.b.mul(&f3);
+		self.c.copy(&f2); self.c.mul(&f3);
+	}
+
+/* self=self^p using Frobenius */
+	pub fn frob(&mut self,f: &FP2) {
+		let mut f2=FP2::new_copy(f);
+		let mut f3=FP2::new_copy(f);
+
+		f2.sqr();
+		f3.mul(&f2);
+
+		self.a.frob(&f3);
+		self.b.frob(&f3);
+		self.c.frob(&f3);
+
+		self.b.pmul(f);
+		self.c.pmul(&f2);
+	}
+
+/* trace function */
+	pub fn trace(&mut self) -> FP4 {
+		let mut t=FP4::new();
+		t.copy(&self.a);
+		t.imul(3);
+		t.reduce();
+		return t;
+	}
+
+/* convert from byte array to FP12 */
+	pub fn frombytes(w: &[u8]) -> FP12 {
+		let mut t:[u8;big::MODBYTES as usize]=[0;big::MODBYTES as usize];
+		let mb=big::MODBYTES as usize;
+
+		for i in 0..mb {t[i]=w[i]}
+		let mut a=BIG::frombytes(&t);
+		for i in 0..mb {t[i]=w[i+mb]}
+		let mut b=BIG::frombytes(&t);
+		let mut c=FP2::new_bigs(&a,&b);
+
+		for i in 0..mb {t[i]=w[i+2*mb]}
+		a=BIG::frombytes(&t);
+		for i in 0..mb {t[i]=w[i+3*mb]}
+		b=BIG::frombytes(&t);
+		let mut d=FP2::new_bigs(&a,&b);
+
+		let e=FP4::new_fp2s(&c,&d);
+
+
+		for i in 0..mb {t[i]=w[i+4*mb]}
+		a=BIG::frombytes(&t);
+		for i in 0..mb {t[i]=w[i+5*mb]}
+		b=BIG::frombytes(&t);
+		c=FP2::new_bigs(&a,&b);
+
+		for i in 0..mb {t[i]=w[i+6*mb]}
+		a=BIG::frombytes(&t);
+		for i in 0..mb {t[i]=w[i+7*mb]}
+		b=BIG::frombytes(&t);
+		d=FP2::new_bigs(&a,&b);
+
+		let f=FP4::new_fp2s(&c,&d);
+
+
+		for i in 0..mb {t[i]=w[i+8*mb]}
+		a=BIG::frombytes(&t);
+		for i in 0..mb {t[i]=w[i+9*mb]}
+		b=BIG::frombytes(&t);
+		
+		c=FP2::new_bigs(&a,&b);
+
+		for i in 0..mb {t[i]=w[i+10*mb]}
+		a=BIG::frombytes(&t);
+		for i in 0..mb {t[i]=w[i+11*mb]}
+		b=BIG::frombytes(&t);
+		d=FP2::new_bigs(&a,&b);
+
+		let g=FP4::new_fp2s(&c,&d);
+
+		return FP12::new_fp4s(&e,&f,&g);
+	}
+
+/* convert this to byte array */
+	pub fn tobytes(&mut self,w: &mut [u8]) {
+		let mut t:[u8;big::MODBYTES as usize]=[0;big::MODBYTES as usize];
+		let mb=big::MODBYTES as usize;
+
+		self.a.geta().geta().tobytes(&mut t);
+		for i in 0..mb {w[i]=t[i]}
+		self.a.geta().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+mb]=t[i]}
+		self.a.getb().geta().tobytes(&mut t);
+		for i in 0..mb {w[i+2*mb]=t[i]}
+		self.a.getb().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+3*mb]=t[i]}
+
+		self.b.geta().geta().tobytes(&mut t);
+		for i in 0..mb {w[i+4*mb]=t[i]}
+		self.b.geta().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+5*mb]=t[i]}
+		self.b.getb().geta().tobytes(&mut t);
+		for i in 0..mb {w[i+6*mb]=t[i]}
+		self.b.getb().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+7*mb]=t[i]}
+
+		self.c.geta().geta().tobytes(&mut t);
+		for i in 0..mb {w[i+8*mb]=t[i]}
+		self.c.geta().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+9*mb]=t[i]}
+		self.c.getb().geta().tobytes(&mut t);
+		for i in 0..mb {w[i+10*mb]=t[i]}
+		self.c.getb().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+11*mb]=t[i]}
+	}
+
+/* output to hex string */
+	pub fn tostring(&mut self) -> String {
+		return format!("[{},{},{}]",self.a.tostring(),self.b.tostring(),self.c.tostring());		
+	}
+
+/* self=self^e */
+	pub fn pow(&self,e: &BIG) -> FP12 {
+		let mut r=FP12::new_copy(self);	
+		r.norm();
+		let mut e1=BIG::new_copy(e);
+		e1.norm();
+		let mut e3=BIG::new_copy(&e1);
+		e3.pmul(3);
+		e3.norm();
+		let mut w=FP12::new_copy(&r);
+
+		let nb=e3.nbits();
+		for i in (1..nb-1).rev() {
+			w.usqr();
+			let bt=e3.bit(i)-e1.bit(i);
+			if bt==1 {
+				w.mul(&r);
+			}
+			if bt == -1 {
+				r.conj(); w.mul(&r); r.conj();
+			}
+		}
+
+		w.reduce();
+		return w;
+	}	
+
+/* constant time powering by small integer of max length bts */
+	pub fn pinpow(&mut self,e: i32,bts: i32) {
+		let mut r:[FP12;2]=[FP12::new_int(1),FP12::new_copy(self)];
+		let mut t=FP12::new();
+
+		for i in (0..bts).rev() {
+			let b:usize=((e>>i)&1) as usize;
+			t.copy(&r[b]);
+			r[1-b].mul(&t);
+			r[b].usqr();
+		}
+		self.copy(&r[0]);
+	}
+
+	pub fn compow(&mut self,e: &BIG, r: &BIG) -> FP4 {
+		let f=FP2::new_bigs(&BIG::new_ints(&rom::FRA),&BIG::new_ints(&rom::FRB));
+		let q=BIG::new_ints(&rom::MODULUS);
+
+		let mut g1=FP12::new_copy(self);
+		let mut g2=FP12::new_copy(self);
+
+
+		let mut m=BIG::new_copy(&q);
+		m.rmod(&r);
+
+		let mut a=BIG::new_copy(&e);
+		a.rmod(&mut m);
+
+		let mut b=BIG::new_copy(&e);
+		b.div(&mut m);
+
+		let mut c=g1.trace();
+
+		if b.iszilch() {
+			c=c.xtr_pow(&mut a);
+			return c;
+		}
+
+		g2.frob(&f);
+		let cp=g2.trace();
+		g1.conj();
+		g2.mul(&g1);
+		let cpm1=g2.trace();
+		g2.mul(&g1);
+		let cpm2=g2.trace();
+
+		c=c.xtr_pow2(&cp,&cpm1,&cpm2,&mut a,&mut b);
+
+		return c;
+	}
+
+/* p=q0^u0.q1^u1.q2^u2.q3^u3 */
+// Bos & Costello https://eprint.iacr.org/2013/458.pdf
+// Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
+// Side channel attack secure 
+ 	pub fn pow4(q:&[FP12],u:&[BIG]) -> FP12 {
+		let mut g:[FP12;8]=[FP12::new(),FP12::new(),FP12::new(),FP12::new(),FP12::new(),FP12::new(),FP12::new(),FP12::new()];
+
+		let mut r=FP12::new();
+		let mut p=FP12::new();
+		const CT:usize=1+big::NLEN*(big::BASEBITS as usize);		
+		let mut w:[i8;CT]=[0;CT];
+		let mut s:[i8;CT]=[0;CT];
+
+		let mut mt=BIG::new();
+		let mut t:[BIG;4]=[BIG::new_copy(&u[0]),BIG::new_copy(&u[1]),BIG::new_copy(&u[2]),BIG::new_copy(&u[3])];
+
+		for i in 0..4 {
+			t[i].norm();
+		}
+
+// precomputation
+		g[0].copy(&q[0]); r.copy(&g[0]);
+		g[1].copy(&r); g[1].mul(&q[1]);  // q[0].q[1]
+		g[2].copy(&r); g[2].mul(&q[2]); r.copy(&g[1]); // q[0].q[2]
+		g[3].copy(&r); g[3].mul(&q[2]);	r.copy(&g[0]); // q[0].q[1].q[2]
+		g[4].copy(&r); g[4].mul(&q[3]); r.copy(&g[1]); // q[0].q[3]
+		g[5].copy(&r); g[5].mul(&q[3]); r.copy(&g[2]); // q[0].q[1].q[3]
+		g[6].copy(&r); g[6].mul(&q[3]); r.copy(&g[3]); // q[0].q[2].q[3]
+		g[7].copy(&r); g[7].mul(&q[3]); // q[0].q[1].q[2].q[3]
+
+
+// Make it odd
+		let pb=1-t[0].parity();
+		t[0].inc(pb);
+		t[0].norm();	
+
+// Number of bits
+		mt.zero();
+		for i in 0..4 {
+			mt.or(&t[i]);
+		}
+
+		let nb=1+mt.nbits();
+
+// Sign pivot 
+		s[nb-1]=1;
+		for i in 0..nb-1 {
+			t[0].fshr(1);
+			s[i]=(2*t[0].parity()-1) as i8;
+			//println!("s={}",s[i]);	
+		}
+
+// Recoded exponent
+		for i in 0..nb {
+			w[i]=0;
+			let mut k=1;
+			for j in 1..4 {
+				let bt=s[i]*(t[j].parity() as i8);
+				t[j].fshr(1);
+				t[j].dec((bt>>1) as isize);
+				t[j].norm();
+				w[i]+=bt*(k as i8);
+				k=2*k;
+			}
+		}
+
+// Main loop
+		p.selector(&g,(2*w[nb-1]+1) as i32);
+		for i in (0..nb-1).rev() {
+			p.usqr();
+			r.selector(&g,(2*w[i]+s[i]) as i32);
+			p.mul(&r);
+		}
+
+// apply correction
+		r.copy(&q[0]); r.conj();   
+		r.mul(&p);
+		p.cmove(&r,pb);
+		p.reduce();
+		return p;
+	}
+
+/* p=q0^u0.q1^u1.q2^u2.q3^u3 */
+/* Timing attack secure, but not cache attack secure */
+/*
+ 	pub fn pow4(q:&[FP12],u:&[BIG]) -> FP12 {
+		let mut a:[i8;4]=[0;4];
+		let mut s:[FP12;2]=[FP12::new(),FP12::new()];
+		let mut g:[FP12;8]=[FP12::new(),FP12::new(),FP12::new(),FP12::new(),FP12::new(),FP12::new(),FP12::new(),FP12::new()];
+
+		let mut c=FP12::new_int(1);
+		let mut p=FP12::new();
+		const CT:usize=1+big::NLEN*(big::BASEBITS as usize);		
+		let mut w:[i8;CT]=[0;CT];
+
+		let mut mt=BIG::new();
+		let mut t:[BIG;4]=[BIG::new_copy(&u[0]),BIG::new_copy(&u[1]),BIG::new_copy(&u[2]),BIG::new_copy(&u[3])];
+
+		g[0].copy(&q[0]); s[0].copy(&q[1]); s[0].conj(); g[0].mul(&s[0]);
+		p.copy(&g[0]);
+		g[1].copy(&p);
+		g[2].copy(&p);
+		g[3].copy(&p);
+		g[4].copy(&q[0]); g[4].mul(&q[1]);
+		p.copy(&g[4]);
+		g[5].copy(&p);
+		g[6].copy(&p);
+		g[7].copy(&p);
+
+
+		s[1].copy(&q[2]); s[0].copy(&q[3]); s[0].conj(); p.copy(&s[0]); s[1].mul(&p);
+		p.copy(&s[1]); s[0].copy(&p); s[0].conj(); g[1].mul(&s[0]);
+		g[2].mul(&s[1]);
+		g[5].mul(&s[0]);
+		g[6].mul(&s[1]);
+		s[1].copy(&q[2]); s[1].mul(&q[3]);
+		p.copy(&s[1]); s[0].copy(&p); s[0].conj(); g[0].mul(&s[0]);
+		g[3].mul(&s[1]);
+		g[4].mul(&s[0]);
+		g[7].mul(&s[1]);
+
+// if power is even add 1 to power, and add q to correction 
+
+		for i in 0..4 {
+			if t[i].parity()==0 {
+				t[i].inc(1); t[i].norm();
+				c.mul(&q[i]);
+			}
+			mt.add(&t[i]); mt.norm();
+		}
+		c.conj();
+		let nb=1+mt.nbits();
+
+// convert exponent to signed 1-bit window 
+		for j in 0..nb {
+			for i in 0..4 {
+				a[i]=(t[i].lastbits(2)-2) as i8;
+				t[i].dec(a[i] as isize); t[i].norm();
+				t[i].fshr(1);
+			}
+			w[j]=8*a[0]+4*a[1]+2*a[2]+a[3];
+		}
+		w[nb]=(8*t[0].lastbits(2)+4*t[1].lastbits(2)+2*t[2].lastbits(2)+t[3].lastbits(2)) as i8;
+		p.copy(&g[((w[nb] as usize)-1)/2]);
+
+		for i in (0..nb).rev() {
+			let m=w[i]>>7;
+			let mut j=((w[i]^m)-m) as usize;  // j=abs(w[i]) 
+			j=(j-1)/2;
+			s[0].copy(&g[j]); s[1].copy(&g[j]); s[1].conj();
+			p.usqr();
+			p.mul(&s[(m&1) as usize]);
+		}
+		p.mul(&c);  // apply correction 
+		p.reduce();
+		return p;
+	}
+*/
+
+}
+/*
+fn main()
+{
+	let mut w=FP12::new();
+}
+*/
diff --git a/version3/rust/fp16.rs b/version3/rust/fp16.rs
new file mode 100644
index 0000000..d29fd3f
--- /dev/null
+++ b/version3/rust/fp16.rs
@@ -0,0 +1,553 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use xxx::fp2::FP2;
+use xxx::fp8::FP8;
+use xxx::big::BIG;
+
+#[derive(Copy, Clone)]
+pub struct FP16 {
+	a:FP8,
+	b:FP8,
+}
+
+impl FP16 {
+
+	pub fn new() -> FP16 {
+		FP16 {
+				a: FP8::new(),
+				b: FP8::new(),
+		}
+	}
+
+	pub fn new_int(a: isize) -> FP16 {
+		let mut f=FP16::new();
+		f.a.copy(&FP8::new_int(a));
+		f.b.zero();
+		return f;
+	}	
+
+	pub fn new_copy(x: &FP16) -> FP16 {
+		let mut f=FP16::new();
+		f.a.copy(&x.a);
+		f.b.copy(&x.b);
+		return f;
+	}	
+
+	pub fn new_fp8s(c: &FP8,d: &FP8) -> FP16 {
+		let mut f=FP16::new();
+		f.a.copy(c);
+		f.b.copy(d);
+		return f;
+	}	
+
+	pub fn new_fp8(c: &FP8) -> FP16 {
+		let mut f=FP16::new();
+		f.a.copy(c);
+		f.b.zero();
+		return f;
+	}	
+
+/* reduce components mod Modulus */
+	pub fn reduce(&mut self) {
+		self.a.reduce();
+		self.b.reduce();
+	}
+
+/* normalise components of w */
+	pub fn norm(&mut self) {
+		self.a.norm();
+		self.b.norm();
+	}	
+
+	pub fn cmove(&mut self,g:&FP16,d: isize) {
+		self.a.cmove(&g.a,d);
+		self.b.cmove(&g.b,d);
+	}	
+
+/* test self=0 ? */
+	pub fn iszilch(&self) -> bool {
+		//self.reduce();
+		return self.a.iszilch() && self.b.iszilch();
+	}	
+
+/* test self=1 ? */
+	pub fn isunity(&self) -> bool {
+		let one=FP8::new_int(1);
+		return self.a.equals(&one) && self.b.iszilch();
+	}
+
+/* test is w real? That is in a+ib test b is zero */
+	pub fn isreal(&mut self) -> bool {
+		return self.b.iszilch();
+	}
+/* extract real part a */
+	pub fn real(&self) -> FP8 {
+		let f=FP8::new_copy(&self.a);
+		return f;
+	}
+
+	pub fn geta(&self) -> FP8 {
+		let f=FP8::new_copy(&self.a);
+		return f;
+	}
+/* extract imaginary part b */
+	pub fn getb(&self) -> FP8 {
+		let f=FP8::new_copy(&self.b);
+		return f;
+	}
+
+/* test self=x */
+	pub fn equals(&self,x:&FP16) -> bool {
+		return self.a.equals(&x.a) && self.b.equals(&x.b);
+	}
+/* copy self=x */
+	pub fn copy(&mut self,x :&FP16) {
+		self.a.copy(&x.a);
+		self.b.copy(&x.b);
+	}
+
+/* set self=0 */
+	pub fn zero(&mut self) {
+		self.a.zero();
+		self.b.zero();
+	}
+
+/* set self=1 */
+	pub fn one(&mut self) {
+		self.a.one();
+		self.b.zero();
+	}	
+
+	/* negate self mod Modulus */
+	pub fn neg(&mut self) {
+		self.norm();
+		let mut m=FP8::new_copy(&self.a);
+		let mut t=FP8::new();
+
+		m.add(&self.b);
+		m.neg();
+	//	m.norm();
+		t.copy(&m); t.add(&self.b);
+		self.b.copy(&m);
+		self.b.add(&self.a);
+		self.a.copy(&t);
+		self.norm();
+	}	
+
+/* set to a-ib */
+	pub fn conj(&mut self) {
+		self.b.neg();
+		self.norm();
+	}
+
+/* self=-conjugate(self) */
+	pub fn nconj(&mut self) {
+		self.a.neg(); self.norm();
+	}
+
+/* self+=a */
+	pub fn add(&mut self,x:&FP16) {
+		self.a.add(&x.a);
+		self.b.add(&x.b);
+	}
+
+	pub fn padd(&mut self,x:&FP8) {
+		self.a.add(x);
+	}
+
+	pub fn dbl(&mut self) {
+		self.a.dbl();
+		self.b.dbl();
+	}
+
+/* self-=a */
+	pub fn sub(&mut self,x:&FP16) {
+		let mut m=FP16::new_copy(x);
+		m.neg();
+		self.add(&m);
+	}
+
+/* this-=x */
+	pub fn rsub(&mut self,x:&FP16) {
+		self.neg();
+		self.add(x);
+}
+
+/* self*=s, where s is an FP8 */
+	pub fn pmul(&mut self,s:&FP8) {
+		self.a.mul(s);
+		self.b.mul(s);
+	}
+
+/* self*=s, where s is an FP2 */
+	pub fn qmul(&mut self,s:&FP2) {
+		self.a.qmul(s);
+		self.b.qmul(s);
+	}
+
+
+/* self*=i, where i is an int */
+	pub fn imul(&mut self,c: isize) {
+		self.a.imul(c);
+		self.b.imul(c);
+	}
+
+/* self*=self */	
+	pub fn sqr(&mut self) {
+	//	self.norm();
+
+		let mut t1=FP8::new_copy(&self.a);
+		let mut t2=FP8::new_copy(&self.b);
+		let mut t3=FP8::new_copy(&self.a);
+
+
+		t3.mul(&self.b);
+		t1.add(&self.b);
+		t2.times_i();
+
+		t2.add(&self.a);
+
+		t1.norm();
+		t2.norm();
+
+		self.a.copy(&t1);
+
+		self.a.mul(&t2);
+
+		t2.copy(&t3);
+		t2.times_i();
+		t2.add(&t3); t2.norm();
+		t2.neg();
+		self.a.add(&t2);
+
+		t3.dbl();
+		self.b.copy(&t3);
+
+		self.norm();
+	}
+
+/* self*=y */
+	pub fn mul(&mut self,y :&FP16) {
+		self.norm();
+
+		let mut t1=FP8::new_copy(&self.a);
+		let mut t2=FP8::new_copy(&self.b);
+		let mut t3=FP8::new();
+		let mut t4=FP8::new_copy(&self.b);
+
+		t1.mul(&y.a);
+		t2.mul(&y.b);
+		t3.copy(&y.b);
+		t3.add(&y.a);
+		t4.add(&self.a);
+
+		t3.norm(); t4.norm();
+
+		t4.mul(&t3);
+
+		t3.copy(&t1);
+		t3.neg();
+		t4.add(&t3);
+		t4.norm();
+
+		t3.copy(&t2);
+		t3.neg();
+		self.b.copy(&t4);
+		self.b.add(&t3);	
+
+		t2.times_i();
+		self.a.copy(&t2);
+		self.a.add(&t1);
+
+		self.norm();
+	}	
+
+/* output to hex string */
+	pub fn tostring(&mut self) -> String {
+		return format!("[{},{}]",self.a.tostring(),self.b.tostring());		
+	}	
+
+/* self=1/self */
+	pub fn inverse(&mut self) {
+		self.norm();
+
+		let mut t1=FP8::new_copy(&self.a);
+		let mut t2=FP8::new_copy(&self.b);
+
+		t1.sqr();
+		t2.sqr();
+		t2.times_i(); t2.norm();
+		t1.sub(&t2); t1.norm();
+		t1.inverse();
+		self.a.mul(&t1);
+		t1.neg(); t1.norm();
+		self.b.mul(&t1);
+	}	
+
+/* self*=i where i = sqrt(-1+sqrt(-1)) */
+	pub fn times_i(&mut self) {
+	//	self.norm();
+		let mut s=FP8::new_copy(&self.b);
+		let t=FP8::new_copy(&self.a);
+		s.times_i();
+		self.a.copy(&s);	
+		self.b.copy(&t);
+
+		self.norm();
+	}	
+
+	pub fn times_i2(&mut self) {
+		self.a.times_i();
+		self.b.times_i();
+	}
+
+	pub fn times_i4(&mut self) {
+		self.a.times_i2();
+		self.b.times_i2();
+	}
+
+	/* self=self^p using Frobenius */
+	pub fn frob(&mut self,f: &FP2) {
+		let mut ff=FP2::new_copy(f);
+		ff.sqr();  ff.norm();
+		self.a.frob(&ff);
+		self.b.frob(&ff);
+		self.b.qmul(f);
+		self.b.times_i();	
+
+	}
+
+/* self=self^e */
+	pub fn pow(&self,e: &BIG) -> FP16 {
+		let mut w=FP16::new_copy(self);
+		w.norm();
+		let mut z=BIG::new_copy(&e);
+		let mut r=FP16::new_int(1);
+		z.norm();
+		loop {
+			let bt=z.parity();
+			z.fshr(1);
+			if bt==1 {r.mul(&mut w)};
+			if z.iszilch() {break}
+			w.sqr();
+		}
+		r.reduce();
+		return r;
+	}	
+
+/* XTR xtr_a function */
+	pub fn xtr_a(&mut self,w:&FP16,y:&FP16,z:&FP16) {
+		let mut r=FP16::new_copy(w);
+		let mut t=FP16::new_copy(w);
+	//	y.norm();
+		r.sub(y); r.norm();
+		r.pmul(&self.a);
+		t.add(y); t.norm();
+		t.pmul(&self.b);
+		t.times_i();
+
+		self.copy(&r);
+		self.add(&t);	
+		self.add(z);
+
+		self.norm();
+	}
+
+/* XTR xtr_d function */
+	pub fn xtr_d(&mut self) {
+		let mut w=FP16::new_copy(self);
+		self.sqr(); w.conj();
+		w.dbl(); w.norm();
+		self.sub(&w);
+		self.reduce();
+	}
+
+/* r=x^n using XTR method on traces of FP24s */
+	pub fn xtr_pow(&self,n: &BIG) -> FP16 {
+		let mut sf=FP16::new_copy(self);
+		sf.norm();
+		let mut a=FP16::new_int(3);
+		let mut b=FP16::new_copy(&sf);
+		let mut c=FP16::new_copy(&b);
+		c.xtr_d();
+		let mut t=FP16::new();
+		let mut r=FP16::new();
+
+		let par=n.parity();
+		let mut v=BIG::new_copy(n); v.norm(); v.fshr(1);
+		if par==0 {v.dec(1); v.norm(); }
+
+		let nb=v.nbits();
+		for i in (0..nb).rev() {
+			if v.bit(i)!=1 {
+				t.copy(&b);
+				sf.conj();
+				c.conj();
+				b.xtr_a(&a,&sf,&c);
+				sf.conj();
+				c.copy(&t);
+				c.xtr_d();
+				a.xtr_d();
+			} else {
+				t.copy(&a); t.conj();
+				a.copy(&b);
+				a.xtr_d();
+				b.xtr_a(&c,&sf,&t);
+				c.xtr_d();
+			}
+		}
+		if par==0 {
+			r.copy(&c)
+		} else {r.copy(&b)}
+		r.reduce();
+		return r;
+	}
+
+/* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */
+	pub fn xtr_pow2(&mut self,ck: &FP16,ckml: &FP16,ckm2l: &FP16,a: &BIG,b: &BIG) -> FP16 {
+
+		let mut e=BIG::new_copy(a);
+		let mut d=BIG::new_copy(b);
+		let mut w=BIG::new();
+		d.norm(); e.norm();
+
+		let mut cu=FP16::new_copy(ck);  // can probably be passed in w/o copying
+		let mut cv=FP16::new_copy(self);
+		let mut cumv=FP16::new_copy(ckml);
+		let mut cum2v=FP16::new_copy(ckm2l);
+		let mut r=FP16::new();
+		let mut t=FP16::new();
+
+		let mut f2:usize=0;
+		while d.parity()==0 && e.parity()==0 {
+			d.fshr(1);
+			e.fshr(1);
+			f2+=1;
+		}
+
+		while BIG::comp(&d,&e)!=0 {
+			if BIG::comp(&d,&e)>0 {
+				w.copy(&e); w.imul(4); w.norm();
+				if BIG::comp(&d,&w)<=0 {
+					w.copy(&d); d.copy(&e);
+					e.rsub(&w); e.norm();
+
+					t.copy(&cv);
+					t.xtr_a(&cu,&cumv,&cum2v);
+					cum2v.copy(&cumv);
+					cum2v.conj();
+					cumv.copy(&cv);
+					cv.copy(&cu);
+					cu.copy(&t);
+				} else {
+					if d.parity()==0 {
+						d.fshr(1);
+						r.copy(&cum2v); r.conj();
+						t.copy(&cumv);
+						t.xtr_a(&cu,&cv,&r);
+						cum2v.copy(&cumv);
+						cum2v.xtr_d();
+						cumv.copy(&t);
+						cu.xtr_d();
+					} else {
+						if e.parity()==1 {
+							d.sub(&e); d.norm();
+							d.fshr(1);
+							t.copy(&cv);
+							t.xtr_a(&cu,&cumv,&cum2v);
+							cu.xtr_d();
+							cum2v.copy(&cv);
+							cum2v.xtr_d();
+							cum2v.conj();
+							cv.copy(&t);
+						} else {
+							w.copy(&d);
+							d.copy(&e); d.fshr(1);
+							e.copy(&w);
+							t.copy(&cumv);
+							t.xtr_d();
+							cumv.copy(&cum2v); cumv.conj();
+							cum2v.copy(&t); cum2v.conj();
+							t.copy(&cv);
+							t.xtr_d();
+							cv.copy(&cu);
+							cu.copy(&t);
+						}
+					}	
+				}
+			}
+			if BIG::comp(&d,&e)<0 {
+				w.copy(&d); w.imul(4); w.norm();
+				if BIG::comp(&e,&w)<=0 {
+					e.sub(&d); e.norm();
+					t.copy(&cv);
+					t.xtr_a(&cu,&cumv,&cum2v);
+					cum2v.copy(&cumv);
+					cumv.copy(&cu);
+					cu.copy(&t);
+				} else {
+					if e.parity()==0 {
+						w.copy(&d);
+						d.copy(&e); d.fshr(1);
+						e.copy(&w);
+						t.copy(&cumv);
+						t.xtr_d();
+						cumv.copy(&cum2v); cumv.conj();
+						cum2v.copy(&t); cum2v.conj();
+						t.copy(&cv);
+						t.xtr_d();
+						cv.copy(&cu);
+						cu.copy(&t);
+					} else {
+						if d.parity()==1 {
+							w.copy(&e);
+							e.copy(&d);
+							w.sub(&d); w.norm();
+							d.copy(&w); d.fshr(1);
+							t.copy(&cv);
+							t.xtr_a(&cu,&cumv,&cum2v);
+							cumv.conj();
+							cum2v.copy(&cu);
+							cum2v.xtr_d();
+							cum2v.conj();
+							cu.copy(&cv);
+							cu.xtr_d();
+							cv.copy(&t);
+						} else {
+							d.fshr(1);
+							r.copy(&cum2v); r.conj();
+							t.copy(&cumv);
+							t.xtr_a(&cu,&cv,&r);
+							cum2v.copy(&cumv);
+							cum2v.xtr_d();
+							cumv.copy(&t);
+							cu.xtr_d();
+						}
+					}
+				}
+			}
+		}
+		r.copy(&cv);
+		r.xtr_a(&cu,&cumv,&cum2v);
+		for _ in 0..f2 {r.xtr_d()}
+		r=r.xtr_pow(&mut d);
+		return r;
+	}
+}
diff --git a/version3/rust/fp2.rs b/version3/rust/fp2.rs
new file mode 100644
index 0000000..8e67e31
--- /dev/null
+++ b/version3/rust/fp2.rs
@@ -0,0 +1,353 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use xxx::fp;
+use xxx::fp::FP;
+use xxx::big::BIG;
+use xxx::dbig::DBIG;
+use xxx::rom;
+
+#[derive(Copy, Clone)]
+pub struct FP2 {
+	a:FP,
+	b:FP,
+}
+
+impl FP2 {
+
+	pub fn new() -> FP2 {
+		FP2 {
+				a: FP::new(),
+				b: FP::new(),
+		}
+	}
+
+	pub fn new_int(a: isize) -> FP2 {
+		let mut f=FP2::new();
+		f.a.copy(&FP::new_int(a));
+		f.b.zero();
+		return f;
+	}	
+
+	pub fn new_copy(x: &FP2) -> FP2 {
+		let mut f=FP2::new();
+		f.a.copy(&x.a);
+		f.b.copy(&x.b);
+		return f
+	}	
+
+	pub fn new_fps(c: &FP,d: &FP) -> FP2 {
+		let mut f=FP2::new();
+		f.a.copy(c);
+		f.b.copy(d);
+		return f;
+	}	
+
+	pub fn new_bigs(c: &BIG,d: &BIG) -> FP2 {
+		let mut f=FP2::new();
+		f.a.copy(&FP::new_big(c));
+		f.b.copy(&FP::new_big(d));
+		return f;
+	}	
+
+	pub fn new_fp(c: &FP) -> FP2 {
+		let mut f=FP2::new();
+		f.a.copy(c);
+		f.b.zero();
+		return f;
+	}	
+
+	pub fn new_big(c: &BIG) -> FP2 {
+		let mut f=FP2::new();
+		f.a.copy(&FP::new_big(c));
+		f.b.zero();
+		return f;
+	}	
+
+/* reduce components mod Modulus */
+	pub fn reduce(&mut self) {
+		self.a.reduce();
+		self.b.reduce();
+	}
+
+/* normalise components of w */
+	pub fn norm(&mut self) {
+		self.a.norm();
+		self.b.norm();
+	}	
+
+/* test self=0 ? */
+	pub fn iszilch(&self) -> bool {
+		//self.reduce();
+		return self.a.iszilch() && self.b.iszilch();
+	}	
+
+	pub fn cmove(&mut self,g:&FP2,d: isize) {
+		self.a.cmove(&g.a,d);
+		self.b.cmove(&g.b,d);
+	}		
+
+/* test self=1 ? */
+	pub fn isunity(&self) -> bool {
+		let one=FP::new_int(1);
+		return self.a.equals(&one) && self.b.iszilch();
+	}
+
+/* test self=x */
+	pub fn equals(&self,x:&FP2) -> bool {
+		return self.a.equals(&x.a) && self.b.equals(&x.b);
+	}
+
+/* extract a */
+	pub fn geta(&mut self) -> BIG { 
+		return self.a.redc();
+	}
+
+/* extract b */
+	pub fn getb(&mut self) -> BIG {
+		return self.b.redc();
+	}
+
+/* copy self=x */
+	pub fn copy(&mut self,x :&FP2) {
+		self.a.copy(&x.a);
+		self.b.copy(&x.b);
+	}
+
+/* set self=0 */
+	pub fn zero(&mut self) {
+		self.a.zero();
+		self.b.zero();
+	}
+
+/* set self=1 */
+	pub fn one(&mut self) {
+		self.a.one();
+		self.b.zero();
+	}	
+
+/* negate self mod Modulus */
+	pub fn neg(&mut self) {
+	//	self.norm();
+		let mut m=FP::new_copy(&self.a);
+		let mut t=FP::new();
+
+		m.add(&self.b);
+		m.neg();
+	//	m.norm();
+		t.copy(&m); t.add(&self.b);
+		self.b.copy(&m);
+		self.b.add(&self.a);
+		self.a.copy(&t);
+	}	
+
+/* set to a-ib */
+	pub fn conj(&mut self) {
+		self.b.neg();
+		self.b.norm();
+	}
+
+/* self+=a */
+	pub fn add(&mut self,x:&FP2) {
+		self.a.add(&x.a);
+		self.b.add(&x.b);
+	}
+
+	pub fn dbl(&mut self) {
+		self.a.dbl();
+		self.b.dbl();
+	}
+
+/* self-=a */
+	pub fn sub(&mut self,x:&FP2) {
+		let mut m=FP2::new_copy(x);
+		m.neg();
+		self.add(&m);
+	}
+
+/* self=a-self */
+	pub fn rsub(&mut self,x:&FP2) {
+		self.neg();
+		self.add(x);
+	}
+
+/* self*=s, where s is an FP */
+	pub fn pmul(&mut self,s:&FP) {
+		self.a.mul(s);
+		self.b.mul(s);
+	}
+
+/* self*=i, where i is an int */
+	pub fn imul(&mut self,c: isize) {
+		self.a.imul(c);
+		self.b.imul(c);
+	}
+
+/* self*=self */
+	pub fn sqr(&mut self) {
+		let mut w1=FP::new_copy(&self.a);
+		let mut w3=FP::new_copy(&self.a);
+		let mut mb=FP::new_copy(&self.b);
+
+	//	w3.mul(&self.b);
+		w1.add(&self.b);
+
+		w3.add(&self.a);
+		w3.norm();
+		self.b.mul(&w3);
+
+		mb.neg();
+		self.a.add(&mb);
+
+		w1.norm();
+		self.a.norm();
+
+		self.a.mul(&w1);
+	}	
+
+/* this*=y */
+	pub fn mul(&mut self,y :&FP2) {
+
+
+		if ((self.a.xes+self.b.xes) as i64)*((y.a.xes+y.b.xes) as i64) > fp::FEXCESS as i64 {
+			if self.a.xes>1 {self.a.reduce()}
+			if self.b.xes>1 {self.b.reduce()}
+		}
+
+
+  		let p = BIG::new_ints(&rom::MODULUS);    
+  		let mut pr=DBIG::new();
+
+  		pr.ucopy(&p);
+
+		let mut c=BIG::new_copy(&(self.a.x));
+		let mut d=BIG::new_copy(&(y.a.x));
+
+		let mut a=BIG::mul(&self.a.x,&y.a.x);
+		let mut b=BIG::mul(&self.b.x,&y.b.x);
+
+		c.add(&self.b.x); c.norm();
+		d.add(&y.b.x); d.norm();
+
+		let mut e=BIG::mul(&c,&d);
+		let mut f=DBIG::new_copy(&a); f.add(&b);
+		b.rsub(&pr);
+
+		a.add(&b); a.norm();
+		e.sub(&f); e.norm();
+
+		self.a.x.copy(&FP::modulo(&mut a)); self.a.xes=3;
+		self.b.x.copy(&FP::modulo(&mut e)); self.b.xes=2;
+
+	}
+
+/* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */
+/* returns true if this is QR */
+	pub fn sqrt(&mut self) -> bool {
+		if self.iszilch() {return true}
+		let mut w1=FP::new_copy(&self.b);
+		let mut w2=FP::new_copy(&self.a);
+		w1.sqr(); w2.sqr(); w1.add(&w2);
+		if w1.jacobi()!=1 { self.zero(); return false }
+		w2.copy(&w1.sqrt()); w1.copy(&w2);
+		w2.copy(&self.a); w2.add(&w1); w2.norm(); w2.div2();
+		if w2.jacobi()!=1 {
+			w2.copy(&self.a); w2.sub(&w1); w2.norm(); w2.div2();
+			if w2.jacobi()!=1 { self.zero(); return false }
+		}
+		w1.copy(&w2.sqrt());
+		self.a.copy(&w1);
+		w1.dbl();
+		w1.inverse();
+		self.b.mul(&w1);
+		return true;
+	}
+
+/* output to hex string */
+	pub fn tostring(&mut self) -> String {
+		return format!("[{},{}]",self.a.tostring(),self.b.tostring());		
+	}
+
+/* self=1/self */
+	pub fn inverse(&mut self) {
+		self.norm();
+		let mut w1=FP::new_copy(&self.a);
+		let mut w2=FP::new_copy(&self.b);
+
+		w1.sqr();
+		w2.sqr();
+		w1.add(&w2);
+		w1.inverse();
+		self.a.mul(&w1);
+		w1.neg(); w1.norm();
+		self.b.mul(&w1);
+	}
+
+/* self/=2 */
+	pub fn div2(&mut self) {
+		self.a.div2();
+		self.b.div2();
+	}
+
+/* self*=sqrt(-1) */
+	pub fn times_i(&mut self) {
+	//	a.norm();
+		let z=FP::new_copy(&self.a);
+		self.a.copy(&self.b); self.a.neg();
+		self.b.copy(&z);
+	}
+
+/* w*=(1+sqrt(-1)) */
+/* where X*2-(1+sqrt(-1)) is irreducible for FP4, assumes p=3 mod 8 */
+	pub fn mul_ip(&mut self) {
+	//	self.norm();
+		let t=FP2::new_copy(self);
+		let z=FP::new_copy(&self.a);
+		self.a.copy(&self.b);
+		self.a.neg();
+		self.b.copy(&z);
+		self.add(&t);
+	//	self.norm();
+	}
+
+	pub fn div_ip2(&mut self) {
+		let mut t=FP2::new();
+		self.norm();
+		t.a.copy(&self.a); t.a.add(&self.b);
+		t.b.copy(&self.b); t.b.sub(&self.a);
+		t.norm(); self.copy(&t); 
+	}
+
+/* w/=(1+sqrt(-1)) */
+	pub fn div_ip(&mut self) {
+		let mut t=FP2::new();
+		self.norm();
+		t.a.copy(&self.a); t.a.add(&self.b);
+		t.b.copy(&self.b); t.b.sub(&self.a);
+		t.norm(); self.copy(&t); 
+		self.div2();
+	}
+
+}
+/*
+fn main()
+{
+	let mut x=FP2::new();
+}
+*/
diff --git a/version3/rust/fp24.rs b/version3/rust/fp24.rs
new file mode 100644
index 0000000..94f753f
--- /dev/null
+++ b/version3/rust/fp24.rs
@@ -0,0 +1,840 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use xxx::big;
+use xxx::ecp;
+use xxx::fp2::FP2;
+use xxx::fp4::FP4;
+use xxx::fp8::FP8;
+use xxx::big::BIG;
+use xxx::rom;
+
+#[derive(Copy, Clone)]
+pub struct FP24 {
+	a:FP8,
+	b:FP8,
+	c:FP8
+}
+
+impl FP24 {
+
+	pub fn new() -> FP24 {
+		FP24 {
+				a: FP8::new(),
+				b: FP8::new(),
+				c: FP8::new()
+		}
+	}
+
+	pub fn new_int(a: isize) -> FP24 {
+		let mut f=FP24::new();
+		f.a.copy(&FP8::new_int(a));
+		f.b.zero();
+		f.c.zero();
+		return f;
+	}	
+
+	pub fn new_copy(x: &FP24) -> FP24 {
+		let mut f=FP24::new();
+		f.a.copy(&x.a);
+		f.b.copy(&x.b);
+		f.c.copy(&x.c);
+		return f;
+	}
+
+	pub fn new_fp8s(d: &FP8,e: &FP8,f: &FP8) -> FP24 {
+		let mut g=FP24::new();
+		g.a.copy(d);
+		g.b.copy(e);
+		g.c.copy(f);
+		return g;
+	}	
+
+	pub fn new_fp8(d: &FP8) -> FP24 {
+		let mut g=FP24::new();
+		g.a.copy(d);
+		g.b.zero();
+		g.c.zero();
+		return g;
+	}
+
+/* reduce components mod Modulus */
+	pub fn reduce(&mut self) {
+		self.a.reduce();
+		self.b.reduce();
+		self.c.reduce();
+	}
+
+/* normalise components of w */
+	pub fn norm(&mut self) {
+		self.a.norm();
+		self.b.norm();
+		self.c.norm();
+	}	
+
+/* test self=0 ? */
+	pub fn iszilch(&self) -> bool {
+		//self.reduce();
+		return self.a.iszilch() && self.b.iszilch() && self.c.iszilch();
+	}	
+
+/* Conditional move of g to self dependant on d */
+	pub fn cmove(&mut self,g:&FP24,d: isize) {
+		self.a.cmove(&g.a,d);
+		self.b.cmove(&g.b,d);
+		self.c.cmove(&g.c,d);
+	}	
+
+/* return 1 if b==c, no branching */
+	fn teq(b: i32,c: i32) -> isize {
+		let mut x=b^c;
+		x-=1;  // if x=0, x now -1
+		return ((x>>31)&1) as isize;
+	}
+
+/* Constant time select from pre-computed table */
+	pub fn selector(&mut self,g: &[FP24],b: i32) {
+		let m=b>>31;
+		let mut babs=(b^m)-m;
+
+		babs=(babs-1)/2;
+
+		self.cmove(&g[0],FP24::teq(babs,0));  // conditional move
+		self.cmove(&g[1],FP24::teq(babs,1));
+		self.cmove(&g[2],FP24::teq(babs,2));
+		self.cmove(&g[3],FP24::teq(babs,3));
+		self.cmove(&g[4],FP24::teq(babs,4));
+		self.cmove(&g[5],FP24::teq(babs,5));
+		self.cmove(&g[6],FP24::teq(babs,6));
+		self.cmove(&g[7],FP24::teq(babs,7));
+ 
+ 		let mut invf=FP24::new_copy(self);
+		invf.conj();
+		self.cmove(&invf,(m&1) as isize);
+	}		
+
+
+/* test self=1 ? */
+	pub fn isunity(&self) -> bool {
+		let one=FP8::new_int(1);
+		return self.a.equals(&one) && self.b.iszilch() && self.c.iszilch();
+	}
+
+/* test self=x */
+	pub fn equals(&self,x:&FP24) -> bool {
+		return self.a.equals(&x.a) && self.b.equals(&x.b) && self.c.equals(&x.c);
+	}
+
+	pub fn geta(&mut self) -> FP8 {
+		let f=FP8::new_copy(&self.a);
+		return f;
+	}
+
+	pub fn getb(&mut self) -> FP8 {
+		let f=FP8::new_copy(&self.b);
+		return f;
+	}
+
+	pub fn getc(&mut self) -> FP8 {
+		let f=FP8::new_copy(&self.c);
+		return f;
+	}	
+
+/* copy self=x */
+	pub fn copy(&mut self,x :&FP24) {
+		self.a.copy(&x.a);
+		self.b.copy(&x.b);
+		self.c.copy(&x.c);
+	}
+
+/* set self=1 */
+	pub fn one(&mut self) {
+		self.a.one();
+		self.b.zero();
+		self.c.zero();
+	}
+
+/* this=conj(this) */
+	pub fn conj(&mut self) {
+		self.a.conj();
+		self.b.nconj();
+		self.c.conj();
+	}
+
+/* Granger-Scott Unitary Squaring */
+	pub fn usqr(&mut self) {
+		let mut a=FP8::new_copy(&self.a);
+		let mut b=FP8::new_copy(&self.c);
+		let mut c=FP8::new_copy(&self.b);
+		let mut d=FP8::new();
+
+		self.a.sqr();
+		d.copy(&self.a); d.add(&self.a);
+		self.a.add(&d);
+
+		self.a.norm();
+		a.nconj();
+
+		a.dbl();
+		self.a.add(&a);
+		b.sqr();
+		b.times_i();
+
+		d.copy(&b); d.add(&b);
+		b.add(&d);
+		b.norm();
+
+		c.sqr();
+		d.copy(&c); d.add(&c);
+		c.add(&d);
+		c.norm();
+
+		self.b.conj();
+		self.b.dbl();
+		self.c.nconj();
+
+		self.c.dbl();
+		self.b.add(&b);
+		self.c.add(&c);
+		self.reduce();
+
+	}
+
+/* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
+	pub fn sqr(&mut self) {
+		let mut a=FP8::new_copy(&self.a);
+		let mut b=FP8::new_copy(&self.b);
+		let mut c=FP8::new_copy(&self.c);
+		let mut d=FP8::new_copy(&self.a);
+
+		a.sqr();
+		b.mul(&self.c);
+		b.dbl(); b.norm();
+		c.sqr();
+		d.mul(&self.b);
+		d.dbl();
+
+		self.c.add(&self.a);
+		self.c.add(&self.b); self.c.norm();
+		self.c.sqr();
+
+		self.a.copy(&a);
+		a.add(&b);
+		a.norm();
+		a.add(&c);
+		a.add(&d);
+		a.norm();
+
+		a.neg();
+		b.times_i();
+		c.times_i();
+
+		self.a.add(&b);
+
+		self.b.copy(&c); self.b.add(&d);
+		self.c.add(&a);
+		self.norm();
+	}
+
+/* FP24 full multiplication self=self*y */
+	pub fn mul(&mut self,y: &FP24) {
+		let mut z0=FP8::new_copy(&self.a);
+		let mut z1=FP8::new();
+		let mut z2=FP8::new_copy(&mut self.b);
+		let mut z3=FP8::new();
+		let mut t0=FP8::new_copy(&self.a);
+		let mut t1=FP8::new_copy(&y.a);
+
+		z0.mul(&y.a);
+		z2.mul(&y.b);
+
+		t0.add(&self.b);
+		t1.add(&y.b);
+
+		t0.norm(); t1.norm();
+
+		z1.copy(&t0); z1.mul(&t1);
+		t0.copy(&self.b); t0.add(&self.c);
+		t1.copy(&y.b); t1.add(&y.c);
+
+		t0.norm(); t1.norm();	
+
+		z3.copy(&t0); z3.mul(&t1);
+
+		t0.copy(&z0); t0.neg();
+		t1.copy(&z2); t1.neg();
+
+		z1.add(&t0);
+		//z1.norm();
+		self.b.copy(&z1); self.b.add(&t1);
+
+		z3.add(&t1);
+		z2.add(&t0);
+
+		t0.copy(&self.a); t0.add(&self.c); t0.norm();
+		t1.copy(&y.a); t1.add(&y.c); t1.norm();
+		t0.mul(&t1);
+		z2.add(&t0);
+
+		t0.copy(&self.c); t0.mul(&y.c);
+		t1.copy(&t0); t1.neg();
+
+
+		self.c.copy(&z2); self.c.add(&t1);
+		z3.add(&t1);
+		t0.times_i();
+		self.b.add(&t0);
+		z3.norm();
+
+		z3.times_i();
+		self.a.copy(&z0); self.a.add(&z3);
+		self.norm();
+	}
+
+/* Special case of multiplication arises from special form of ATE pairing line function */
+	pub fn smul(&mut self,y: &FP24,twist: usize) {
+
+		if twist==ecp::D_TYPE {
+			let mut z0=FP8::new_copy(&self.a);
+			let mut z2=FP8::new_copy(&self.b);
+			let mut z3=FP8::new_copy(&self.b);
+			let mut t0=FP8::new();
+			let mut t1=FP8::new_copy(&y.a);
+		
+			z0.mul(&y.a);
+			z2.pmul(&y.b.real());
+			self.b.add(&self.a);
+			t1.padd(&y.b.real());
+
+			self.b.norm(); t1.norm();
+
+			self.b.mul(&t1);
+			z3.add(&self.c); z3.norm();
+			z3.pmul(&y.b.real());
+
+			t0.copy(&z0); t0.neg();
+			t1.copy(&z2); t1.neg();
+	
+			self.b.add(&t0);
+		//self.b.norm();
+
+			self.b.add(&t1);
+			z3.add(&t1);
+			z2.add(&t0);
+
+			t0.copy(&self.a); t0.add(&self.c);
+			t0.norm(); z3.norm();
+			
+			t0.mul(&y.a);
+			self.c.copy(&z2); self.c.add(&t0);
+
+			z3.times_i();
+			self.a.copy(&z0); self.a.add(&z3);
+		}
+		if twist==ecp::M_TYPE {
+			let mut z0=FP8::new_copy(&self.a);
+			let mut z1=FP8::new();
+			let mut z2=FP8::new();
+			let mut z3=FP8::new();
+			let mut t0=FP8::new_copy(&self.a);
+			let mut t1=FP8::new();
+		
+			z0.mul(&y.a);
+			t0.add(&self.b);
+			t0.norm();
+
+			z1.copy(&t0); z1.mul(&y.a);
+			t0.copy(&self.b); t0.add(&self.c);
+			t0.norm();
+
+			z3.copy(&t0); //z3.mul(y.c);
+			z3.pmul(&y.c.getb());
+			z3.times_i();
+
+			t0.copy(&z0); t0.neg();
+
+			z1.add(&t0);
+			self.b.copy(&z1); 
+			z2.copy(&t0);
+
+			t0.copy(&self.a); t0.add(&self.c);
+			t1.copy(&y.a); t1.add(&y.c);
+
+			t0.norm();
+			t1.norm();
+	
+			t0.mul(&t1);
+			z2.add(&t0);
+
+			t0.copy(&self.c);
+			
+			t0.pmul(&y.c.getb());
+			t0.times_i();
+
+			t1.copy(&t0); t1.neg();
+
+			self.c.copy(&z2); self.c.add(&t1);
+			z3.add(&t1);
+			t0.times_i();
+			self.b.add(&t0);
+			z3.norm();
+			z3.times_i();
+			self.a.copy(&z0); self.a.add(&z3);
+		}
+		self.norm();		
+	}
+
+/* self=1/self */
+	pub fn inverse(&mut self) {
+		let mut f0=FP8::new_copy(&self.a);
+		let mut f1=FP8::new_copy(&self.b);
+		let mut f2=FP8::new_copy(&self.a);
+		let mut f3=FP8::new();
+
+		self.norm();
+		f0.sqr();
+		f1.mul(&self.c);
+		f1.times_i();
+		f0.sub(&f1); f0.norm();
+
+		f1.copy(&self.c); f1.sqr();
+		f1.times_i();
+		f2.mul(&self.b);
+		f1.sub(&f2); f1.norm();
+
+		f2.copy(&self.b); f2.sqr();
+		f3.copy(&self.a); f3.mul(&self.c);
+		f2.sub(&f3); f2.norm();
+
+		f3.copy(&self.b); f3.mul(&f2);
+		f3.times_i();
+		self.a.mul(&f0);
+		f3.add(&self.a);
+		self.c.mul(&f1);
+		self.c.times_i();
+
+		f3.add(&self.c); f3.norm();
+		f3.inverse();
+		self.a.copy(&f0); self.a.mul(&f3);
+		self.b.copy(&f1); self.b.mul(&f3);
+		self.c.copy(&f2); self.c.mul(&f3);
+	}
+
+	/* self=self^p using Frobenius */
+	pub fn frob(&mut self,f: &FP2,n:isize) {
+		let mut f2=FP2::new_copy(f);
+		let mut f3=FP2::new_copy(f);
+
+		f2.sqr();
+		f3.mul(&f2);
+
+		f3.mul_ip(); f3.norm();
+
+		for _i in 0..n {
+			self.a.frob(&f3);
+			self.b.frob(&f3);
+			self.c.frob(&f3);
+
+			self.b.qmul(f); self.b.times_i2();
+			self.c.qmul(&f2); self.c.times_i2(); self.c.times_i2();
+		}
+	}
+
+/* trace function */
+	pub fn trace(&mut self) -> FP8 {
+		let mut t=FP8::new();
+		t.copy(&self.a);
+		t.imul(3);
+		t.reduce();
+		return t;
+	}
+
+/* convert from byte array to FP24 */
+	pub fn frombytes(w: &[u8]) -> FP24 {
+		let mut t:[u8;big::MODBYTES as usize]=[0;big::MODBYTES as usize];
+		let mb=big::MODBYTES as usize;
+
+		for i in 0..mb {t[i]=w[i]}
+		let mut a=BIG::frombytes(&t);
+		for i in 0..mb {t[i]=w[i+mb]}
+		let mut b=BIG::frombytes(&t);
+		let mut c=FP2::new_bigs(&a,&b);
+
+		for i in 0..mb {t[i]=w[i+2*mb]}
+		a.copy(&BIG::frombytes(&t));
+		for i in 0..mb {t[i]=w[i+3*mb]}
+		b.copy(&BIG::frombytes(&t));
+		let mut d=FP2::new_bigs(&a,&b);
+
+		let mut ea=FP4::new_fp2s(&c,&d);
+
+		for i in 0..mb {t[i]=w[i+4*mb]}
+		a.copy(&BIG::frombytes(&t));
+		for i in 0..mb {t[i]=w[i+5*mb]}
+		b.copy(&BIG::frombytes(&t));
+		c.copy(&FP2::new_bigs(&a,&b));
+
+		for i in 0..mb {t[i]=w[i+6*mb]}
+		a.copy(&BIG::frombytes(&t));
+		for i in 0..mb {t[i]=w[i+7*mb]}
+		b.copy(&BIG::frombytes(&t));
+		d.copy(&FP2::new_bigs(&a,&b));
+
+		let mut eb=FP4::new_fp2s(&c,&d);
+
+
+		let e=FP8::new_fp4s(&ea,&eb);
+
+
+		for i in 0..mb {t[i]=w[i+8*mb]}
+		a.copy(&BIG::frombytes(&t));
+		for i in 0..mb {t[i]=w[i+9*mb]}
+		b.copy(&BIG::frombytes(&t));
+		c.copy(&FP2::new_bigs(&a,&b));
+
+		for i in 0..mb {t[i]=w[i+10*mb]}
+		a.copy(&BIG::frombytes(&t));
+		for i in 0..mb {t[i]=w[i+11*mb]}
+		b.copy(&BIG::frombytes(&t));
+		d.copy(&FP2::new_bigs(&a,&b));
+
+		ea.copy(&FP4::new_fp2s(&c,&d));
+
+		for i in 0..mb {t[i]=w[i+12*mb]}
+		a.copy(&BIG::frombytes(&t));
+		for i in 0..mb {t[i]=w[i+13*mb]}
+		b.copy(&BIG::frombytes(&t));
+		c.copy(&FP2::new_bigs(&a,&b));
+
+		for i in 0..mb {t[i]=w[i+14*mb]}
+		a.copy(&BIG::frombytes(&t));
+		for i in 0..mb {t[i]=w[i+15*mb]}
+		b.copy(&BIG::frombytes(&t));
+		d.copy(&FP2::new_bigs(&a,&b));
+
+		eb.copy(&FP4::new_fp2s(&c,&d));
+
+
+		let f=FP8::new_fp4s(&ea,&eb);
+
+
+		for i in 0..mb {t[i]=w[i+16*mb]}
+		a.copy(&BIG::frombytes(&t));
+		for i in 0..mb {t[i]=w[i+17*mb]}
+		b.copy(&BIG::frombytes(&t));
+		
+		c.copy(&FP2::new_bigs(&a,&b));
+
+		for i in 0..mb {t[i]=w[i+18*mb]}
+		a.copy(&BIG::frombytes(&t));
+		for i in 0..mb {t[i]=w[i+19*mb]}
+		b.copy(&BIG::frombytes(&t));
+		d.copy(&FP2::new_bigs(&a,&b));
+
+		ea.copy(&FP4::new_fp2s(&c,&d));
+
+		for i in 0..mb {t[i]=w[i+20*mb]}
+		a.copy(&BIG::frombytes(&t));
+		for i in 0..mb {t[i]=w[i+21*mb]}
+		b.copy(&BIG::frombytes(&t));
+		
+		c.copy(&FP2::new_bigs(&a,&b));
+
+		for i in 0..mb {t[i]=w[i+22*mb]}
+		a.copy(&BIG::frombytes(&t));
+		for i in 0..mb {t[i]=w[i+23*mb]}
+		b.copy(&BIG::frombytes(&t));
+		d.copy(&FP2::new_bigs(&a,&b));
+
+		eb.copy(&FP4::new_fp2s(&c,&d));
+
+
+		let g=FP8::new_fp4s(&ea,&eb);
+
+		return FP24::new_fp8s(&e,&f,&g);
+	}
+
+/* convert this to byte array */
+	pub fn tobytes(&mut self,w: &mut [u8]) {
+		let mut t:[u8;big::MODBYTES as usize]=[0;big::MODBYTES as usize];
+		let mb=big::MODBYTES as usize;
+
+		self.a.geta().geta().geta().tobytes(&mut t);
+		for i in 0..mb {w[i]=t[i]}
+		self.a.geta().geta().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+mb]=t[i]}
+		self.a.geta().getb().geta().tobytes(&mut t);
+		for i in 0..mb {w[i+2*mb]=t[i]}
+		self.a.geta().getb().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+3*mb]=t[i]}
+
+		self.a.getb().geta().geta().tobytes(&mut t);
+		for i in 0..mb {w[i+4*mb]=t[i]}
+		self.a.getb().geta().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+5*mb]=t[i]}
+		self.a.getb().getb().geta().tobytes(&mut t);
+		for i in 0..mb {w[i+6*mb]=t[i]}
+		self.a.getb().getb().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+7*mb]=t[i]}
+
+
+
+		self.b.geta().geta().geta().tobytes(&mut t);
+		for i in 0..mb {w[i+8*mb]=t[i]}
+		self.b.geta().geta().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+9*mb]=t[i]}
+		self.b.geta().getb().geta().tobytes(&mut t);
+		for i in 0..mb {w[i+10*mb]=t[i]}
+		self.b.geta().getb().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+11*mb]=t[i]}
+
+		self.b.getb().geta().geta().tobytes(&mut t);
+		for i in 0..mb {w[i+12*mb]=t[i]}
+		self.b.getb().geta().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+13*mb]=t[i]}
+		self.b.getb().getb().geta().tobytes(&mut t);
+		for i in 0..mb {w[i+14*mb]=t[i]}
+		self.b.getb().getb().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+15*mb]=t[i]}
+
+
+
+		self.c.geta().geta().geta().tobytes(&mut t);
+		for i in 0..mb {w[i+16*mb]=t[i]}
+		self.c.geta().geta().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+17*mb]=t[i]}
+		self.c.geta().getb().geta().tobytes(&mut t);
+		for i in 0..mb {w[i+18*mb]=t[i]}
+		self.c.geta().getb().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+19*mb]=t[i]}
+
+		self.c.getb().geta().geta().tobytes(&mut t);
+		for i in 0..mb {w[i+20*mb]=t[i]}
+		self.c.getb().geta().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+21*mb]=t[i]}
+		self.c.getb().getb().geta().tobytes(&mut t);
+		for i in 0..mb {w[i+22*mb]=t[i]}
+		self.c.getb().getb().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+23*mb]=t[i]}		
+	}
+
+/* output to hex string */
+	pub fn tostring(&mut self) -> String {
+		return format!("[{},{},{}]",self.a.tostring(),self.b.tostring(),self.c.tostring());		
+	}
+
+/* self=self^e */
+	pub fn pow(&self,e: &BIG) -> FP24 {
+		let mut r=FP24::new_copy(self);	
+		r.norm();
+		let mut e1=BIG::new_copy(e);
+		e1.norm();
+		let mut e3=BIG::new_copy(&e1);
+		e3.pmul(3);
+		e3.norm();
+		let mut w=FP24::new_copy(&r);
+
+		let nb=e3.nbits();
+		for i in (1..nb-1).rev() {
+			w.usqr();
+			let bt=e3.bit(i)-e1.bit(i);
+			if bt==1 {
+				w.mul(&r);
+			}
+			if bt == -1 {
+				r.conj(); w.mul(&r); r.conj();
+			}
+		}
+
+		w.reduce();
+		return w;
+	}	
+
+/* constant time powering by small integer of max length bts */
+	pub fn pinpow(&mut self,e: i32,bts: i32) {
+		let mut r:[FP24;2]=[FP24::new_int(1),FP24::new_copy(self)];
+		let mut t=FP24::new();
+
+		for i in (0..bts).rev() {
+			let b:usize=((e>>i)&1) as usize;
+			t.copy(&r[b]);
+			r[1-b].mul(&t);
+			r[b].usqr();
+		}
+		self.copy(&r[0]);
+	}
+
+	pub fn compow(&mut self,e: &BIG, r: &BIG) -> FP8 {
+		let f=FP2::new_bigs(&BIG::new_ints(&rom::FRA),&BIG::new_ints(&rom::FRB));
+		let q=BIG::new_ints(&rom::MODULUS);
+
+		let mut g1=FP24::new_copy(self);
+		let mut g2=FP24::new_copy(self);
+
+
+		let mut m=BIG::new_copy(&q);
+		m.rmod(&r);
+
+		let mut a=BIG::new_copy(&e);
+		a.rmod(&mut m);
+
+		let mut b=BIG::new_copy(&e);
+		b.div(&mut m);
+
+		let mut c=g1.trace();
+
+		if b.iszilch() {
+			c=c.xtr_pow(&mut a);
+			return c;
+		}
+
+		g2.frob(&f,1);
+		let cp=g2.trace();
+		g1.conj();
+		g2.mul(&g1);
+		let cpm1=g2.trace();
+		g2.mul(&g1);
+		let cpm2=g2.trace();
+
+		c=c.xtr_pow2(&cp,&cpm1,&cpm2,&mut a,&mut b);
+
+		return c;
+	}
+
+/* p=q0^u0.q1^u1.q2^u2.q3^u3... */
+// Bos & Costello https://eprint.iacr.org/2013/458.pdf
+// Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
+// Side channel attack secure 
+ 	pub fn pow8(q:&[FP24],u:&[BIG]) -> FP24 {
+		let mut g1:[FP24;8]=[FP24::new(),FP24::new(),FP24::new(),FP24::new(),FP24::new(),FP24::new(),FP24::new(),FP24::new()];
+		let mut g2:[FP24;8]=[FP24::new(),FP24::new(),FP24::new(),FP24::new(),FP24::new(),FP24::new(),FP24::new(),FP24::new()];
+
+		let mut r=FP24::new();
+		let mut p=FP24::new();
+		const CT:usize=1+big::NLEN*(big::BASEBITS as usize);		
+		let mut w1:[i8;CT]=[0;CT];
+		let mut s1:[i8;CT]=[0;CT];
+		let mut w2:[i8;CT]=[0;CT];
+		let mut s2:[i8;CT]=[0;CT];
+
+
+		let mut mt=BIG::new();
+		let mut t:[BIG;8]=[BIG::new_copy(&u[0]),BIG::new_copy(&u[1]),BIG::new_copy(&u[2]),BIG::new_copy(&u[3]),BIG::new_copy(&u[4]),BIG::new_copy(&u[5]),BIG::new_copy(&u[6]),BIG::new_copy(&u[7])];
+
+		for i in 0..8 {
+			t[i].norm();
+		}
+
+// precomputation
+		g1[0].copy(&q[0]); r.copy(&g1[0]);
+		g1[1].copy(&r); g1[1].mul(&q[1]);  // q[0].q[1]
+		g1[2].copy(&r); g1[2].mul(&q[2]); r.copy(&g1[1]); // q[0].q[2]
+		g1[3].copy(&r); g1[3].mul(&q[2]); r.copy(&g1[0]); // q[0].q[1].q[2]
+		g1[4].copy(&r); g1[4].mul(&q[3]); r.copy(&g1[1]); // q[0].q[3]
+		g1[5].copy(&r); g1[5].mul(&q[3]); r.copy(&g1[2]); // q[0].q[1].q[3]
+		g1[6].copy(&r); g1[6].mul(&q[3]); r.copy(&g1[3]); // q[0].q[2].q[3]
+		g1[7].copy(&r); g1[7].mul(&q[3]); // q[0].q[1].q[2].q[3]
+
+// Use Frobenius
+		let f=FP2::new_bigs(&BIG::new_ints(&rom::FRA),&BIG::new_ints(&rom::FRB));
+		for i in 0..8 {
+			g2[i].copy(&g1[i]); g2[i].frob(&f,4);
+		}
+
+
+// Make it odd
+		let pb1=1-t[0].parity();
+		t[0].inc(pb1);
+		t[0].norm();	
+
+		let pb2=1-t[4].parity();
+		t[4].inc(pb2);
+		t[4].norm();		
+
+// Number of bits
+		mt.zero();
+		for i in 0..8 {
+			mt.or(&t[i]);
+		}
+
+		let nb=1+mt.nbits();
+
+// Sign pivot 
+
+		s1[nb-1]=1;
+		s2[nb-1]=1;
+		for i in 0..nb-1 {
+			t[0].fshr(1);
+			s1[i]=(2*t[0].parity()-1) as i8;
+			t[4].fshr(1);
+			s2[i]=(2*t[4].parity()-1) as i8;
+
+		}
+
+// Recoded exponent
+		for i in 0..nb {
+			w1[i]=0;
+			let mut k=1;
+			for j in 1..4 {
+				let bt=s1[i]*(t[j].parity() as i8);
+				t[j].fshr(1);
+				t[j].dec((bt>>1) as isize);
+				t[j].norm();
+				w1[i]+=bt*(k as i8);
+				k=2*k;
+			}
+
+			w2[i]=0;
+			k=1;
+			for j in 5..8 {
+				let bt=s2[i]*(t[j].parity() as i8);
+				t[j].fshr(1);
+				t[j].dec((bt>>1) as isize);
+				t[j].norm();
+				w2[i]+=bt*(k as i8);
+				k=2*k;
+			}			
+		}	
+
+
+// Main loop
+		p.selector(&g1,(2*w1[nb-1]+1) as i32);
+		r.selector(&g2,(2*w2[nb-1]+1) as i32);
+		p.mul(&r);
+		for i in (0..nb-1).rev() {
+			p.usqr();
+			r.selector(&g1,(2*w1[i]+s1[i]) as i32);
+			p.mul(&r);
+			r.selector(&g2,(2*w2[i]+s2[i]) as i32);
+			p.mul(&r);			
+		}
+
+// apply correction
+		r.copy(&q[0]); r.conj();   
+		r.mul(&p);
+		p.cmove(&r,pb1);
+
+		r.copy(&q[4]); r.conj();   
+		r.mul(&p);
+		p.cmove(&r,pb2);
+
+		p.reduce();
+		return p;
+	}
+}
diff --git a/version3/rust/fp4.rs b/version3/rust/fp4.rs
new file mode 100644
index 0000000..9eb0421
--- /dev/null
+++ b/version3/rust/fp4.rs
@@ -0,0 +1,624 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use xxx::fp::FP;
+use xxx::fp2::FP2;
+use xxx::big::BIG;
+
+#[derive(Copy, Clone)]
+pub struct FP4 {
+	a:FP2,
+	b:FP2,
+}
+
+impl FP4 {
+
+	pub fn new() -> FP4 {
+		FP4 {
+				a: FP2::new(),
+				b: FP2::new(),
+		}
+	}
+
+	pub fn new_int(a: isize) -> FP4 {
+		let mut f=FP4::new();
+		f.a.copy(&FP2::new_int(a));
+		f.b.zero();
+		return f;
+	}	
+
+	pub fn new_copy(x: &FP4) -> FP4 {
+		let mut f=FP4::new();
+		f.a.copy(&x.a);
+		f.b.copy(&x.b);
+		return f;
+	}	
+
+	pub fn new_fp2s(c: &FP2,d: &FP2) -> FP4 {
+		let mut f=FP4::new();
+		f.a.copy(c);
+		f.b.copy(d);
+		return f;
+	}	
+
+	pub fn new_fp2(c: &FP2) -> FP4 {
+		let mut f=FP4::new();
+		f.a.copy(c);
+		f.b.zero();
+		return f;
+	}	
+
+/* reduce components mod Modulus */
+	pub fn reduce(&mut self) {
+		self.a.reduce();
+		self.b.reduce();
+	}
+
+/* normalise components of w */
+	pub fn norm(&mut self) {
+		self.a.norm();
+		self.b.norm();
+	}	
+
+	pub fn cmove(&mut self,g:&FP4,d: isize) {
+		self.a.cmove(&g.a,d);
+		self.b.cmove(&g.b,d);
+	}	
+
+/* test self=0 ? */
+	pub fn iszilch(&self) -> bool {
+		//self.reduce();
+		return self.a.iszilch() && self.b.iszilch();
+	}	
+
+/* test self=1 ? */
+	pub fn isunity(&self) -> bool {
+		let one=FP2::new_int(1);
+		return self.a.equals(&one) && self.b.iszilch();
+	}
+
+/* test is w real? That is in a+ib test b is zero */
+	pub fn isreal(&mut self) -> bool {
+		return self.b.iszilch();
+	}
+/* extract real part a */
+	pub fn real(&self) -> FP2 {
+		let f=FP2::new_copy(&self.a);
+		return f;
+	}
+
+	pub fn geta(&self) -> FP2 {
+		let f=FP2::new_copy(&self.a);
+		return f;
+	}
+/* extract imaginary part b */
+	pub fn getb(&self) -> FP2 {
+		let f=FP2::new_copy(&self.b);
+		return f;
+	}
+
+/* test self=x */
+	pub fn equals(&self,x:&FP4) -> bool {
+		return self.a.equals(&x.a) && self.b.equals(&x.b);
+	}
+/* copy self=x */
+	pub fn copy(&mut self,x :&FP4) {
+		self.a.copy(&x.a);
+		self.b.copy(&x.b);
+	}
+
+/* set self=0 */
+	pub fn zero(&mut self) {
+		self.a.zero();
+		self.b.zero();
+	}
+
+/* set self=1 */
+	pub fn one(&mut self) {
+		self.a.one();
+		self.b.zero();
+	}	
+
+/* negate self mod Modulus */
+	pub fn neg(&mut self) {
+		self.norm();
+		let mut m=FP2::new_copy(&self.a);
+		let mut t=FP2::new();
+
+		m.add(&self.b);
+		m.neg();
+	//	m.norm();
+		t.copy(&m); t.add(&self.b);
+		self.b.copy(&m);
+		self.b.add(&self.a);
+		self.a.copy(&t);
+		self.norm();
+	}	
+
+/* set to a-ib */
+	pub fn conj(&mut self) {
+		self.b.neg();
+		self.norm();
+	}
+
+/* self=-conjugate(self) */
+	pub fn nconj(&mut self) {
+		self.a.neg(); self.norm();
+	}
+
+/* self+=a */
+	pub fn add(&mut self,x:&FP4) {
+		self.a.add(&x.a);
+		self.b.add(&x.b);
+	}
+
+	pub fn padd(&mut self,x:&FP2) {
+		self.a.add(x);
+	}
+
+	pub fn dbl(&mut self) {
+		self.a.dbl();
+		self.b.dbl();
+	}
+
+/* self-=a */
+	pub fn sub(&mut self,x:&FP4) {
+		let mut m=FP4::new_copy(x);
+		m.neg();
+		self.add(&m);
+	}
+
+/* self-=a */
+	pub fn rsub(&mut self,x:&FP4) {
+		self.neg();
+		self.add(x);
+	}	
+
+/* self*=s, where s is an FP2 */
+	pub fn pmul(&mut self,s:&FP2) {
+		self.a.mul(s);
+		self.b.mul(s);
+	}
+
+/* self*=s, where s is an FP */
+	pub fn qmul(&mut self,s:&FP) {
+		self.a.pmul(s);
+		self.b.pmul(s);
+	}
+
+/* self*=i, where i is an int */
+	pub fn imul(&mut self,c: isize) {
+		self.a.imul(c);
+		self.b.imul(c);
+	}
+
+/* self*=self */	
+	pub fn sqr(&mut self) {
+	//	self.norm();
+
+		let mut t1=FP2::new_copy(&self.a);
+		let mut t2=FP2::new_copy(&self.b);
+		let mut t3=FP2::new_copy(&self.a);
+
+
+		t3.mul(&self.b);
+		t1.add(&self.b);
+		t2.mul_ip();
+
+		t2.add(&self.a);
+
+		t1.norm();
+		t2.norm();
+
+		self.a.copy(&t1);
+
+		self.a.mul(&t2);
+
+		t2.copy(&t3);
+		t2.mul_ip();
+		t2.add(&t3); t2.norm();
+		t2.neg();
+		self.a.add(&t2);
+
+		t3.dbl();
+		self.b.copy(&t3);
+
+		self.norm();
+	}
+
+/* self*=y */
+	pub fn mul(&mut self,y :&FP4) {
+		self.norm();
+
+		let mut t1=FP2::new_copy(&self.a);
+		let mut t2=FP2::new_copy(&self.b);
+		let mut t3=FP2::new();
+		let mut t4=FP2::new_copy(&self.b);
+
+		t1.mul(&y.a);
+		t2.mul(&y.b);
+		t3.copy(&y.b);
+		t3.add(&y.a);
+		t4.add(&self.a);
+
+		t3.norm(); t4.norm();
+
+		t4.mul(&t3);
+
+		t3.copy(&t1);
+		t3.neg();
+		t4.add(&t3);
+		t4.norm();
+
+		t3.copy(&t2);
+		t3.neg();
+		self.b.copy(&t4);
+		self.b.add(&t3);	
+
+		t2.mul_ip();
+		self.a.copy(&t2);
+		self.a.add(&t1);
+
+		self.norm();
+	}	
+
+/* output to hex string */
+	pub fn tostring(&mut self) -> String {
+		return format!("[{},{}]",self.a.tostring(),self.b.tostring());		
+	}	
+
+/* self=1/self */
+	pub fn inverse(&mut self) {
+		self.norm();
+
+		let mut t1=FP2::new_copy(&self.a);
+		let mut t2=FP2::new_copy(&self.b);
+
+		t1.sqr();
+		t2.sqr();
+		t2.mul_ip(); t2.norm();
+		t1.sub(&t2);
+		t1.inverse();
+		self.a.mul(&t1);
+		t1.neg(); t1.norm();
+		self.b.mul(&t1);
+	}	
+
+/* self*=i where i = sqrt(-1+sqrt(-1)) */
+	pub fn times_i(&mut self) {
+	//	self.norm();
+		let mut s=FP2::new_copy(&self.b);
+		let mut t=FP2::new_copy(&self.b);
+		s.times_i();
+		t.add(&s);
+	//	t.norm();
+		self.b.copy(&self.a);
+		self.a.copy(&t);
+		self.norm();
+	}	
+
+/* self=self^p using Frobenius */
+	pub fn frob(&mut self,f: &FP2) {
+		self.a.conj();
+		self.b.conj();
+		self.b.mul(f);
+	}	
+
+/* self=self^e */
+	pub fn pow(&self,e: &BIG) -> FP4 {
+		//self.norm();
+		let mut w=FP4::new_copy(self);
+		w.norm();
+		let mut z=BIG::new_copy(&e);
+		let mut r=FP4::new_int(1);
+		z.norm();
+		loop {
+			let bt=z.parity();
+			z.fshr(1);
+			if bt==1 {r.mul(&mut w)};
+			if z.iszilch() {break}
+			w.sqr();
+		}
+		r.reduce();
+		return r;
+	}	
+
+/* XTR xtr_a function */
+	pub fn xtr_a(&mut self,w:&FP4,y:&FP4,z:&FP4) {
+		let mut r=FP4::new_copy(w);
+		let mut t=FP4::new_copy(w);
+	//	y.norm();
+		r.sub(y); r.norm();
+		r.pmul(&self.a);
+		t.add(y); t.norm();
+		t.pmul(&self.b);
+		t.times_i();
+
+		self.copy(&r);
+		self.add(&t);	
+		self.add(z);
+
+		self.norm();
+	}
+
+/* XTR xtr_d function */
+	pub fn xtr_d(&mut self) {
+		let mut w=FP4::new_copy(self);
+		self.sqr(); w.conj();
+		w.dbl(); w.norm();
+		self.sub(&w);
+		self.reduce();
+	}
+
+/* r=x^n using XTR method on traces of FP12s */
+	pub fn xtr_pow(&self,n: &BIG) -> FP4 {
+		let mut sf=FP4::new_copy(self);
+		sf.norm();
+		let mut a=FP4::new_int(3);
+		let mut b=FP4::new_copy(&sf);
+		let mut c=FP4::new_copy(&b);
+		c.xtr_d();
+		let mut t=FP4::new();
+		let mut r=FP4::new();
+
+		//n.norm();
+		let par=n.parity();
+		let mut v=BIG::new_copy(n); v.norm(); v.fshr(1);
+		if par==0 {v.dec(1); v.norm(); }
+
+		let nb=v.nbits();
+		for i in (0..nb).rev() {
+			if v.bit(i)!=1 {
+				t.copy(&b);
+				sf.conj();
+				c.conj();
+				b.xtr_a(&a,&sf,&c);
+				sf.conj();
+				c.copy(&t);
+				c.xtr_d();
+				a.xtr_d();
+			} else {
+				t.copy(&a); t.conj();
+				a.copy(&b);
+				a.xtr_d();
+				b.xtr_a(&c,&sf,&t);
+				c.xtr_d();
+			}
+		}
+		if par==0 {
+			r.copy(&c)
+		} else {r.copy(&b)}
+		r.reduce();
+		return r;
+	}
+
+/* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */
+	pub fn xtr_pow2(&mut self,ck: &FP4,ckml: &FP4,ckm2l: &FP4,a: &BIG,b: &BIG) -> FP4 {
+
+		let mut e=BIG::new_copy(a);
+		let mut d=BIG::new_copy(b);
+		let mut w=BIG::new();
+		e.norm(); d.norm();
+
+		let mut cu=FP4::new_copy(ck);  // can probably be passed in w/o copying
+		let mut cv=FP4::new_copy(self);
+		let mut cumv=FP4::new_copy(ckml);
+		let mut cum2v=FP4::new_copy(ckm2l);
+		let mut r=FP4::new();
+		let mut t=FP4::new();
+
+		let mut f2:usize=0;
+		while d.parity()==0 && e.parity()==0 {
+			d.fshr(1);
+			e.fshr(1);
+			f2+=1;
+		}
+
+		while BIG::comp(&d,&e)!=0 {
+			if BIG::comp(&d,&e)>0 {
+				w.copy(&e); w.imul(4); w.norm();
+				if BIG::comp(&d,&w)<=0 {
+					w.copy(&d); d.copy(&e);
+					e.rsub(&w); e.norm();
+
+					t.copy(&cv);
+					t.xtr_a(&cu,&cumv,&cum2v);
+					cum2v.copy(&cumv);
+					cum2v.conj();
+					cumv.copy(&cv);
+					cv.copy(&cu);
+					cu.copy(&t);
+				} else {
+					if d.parity()==0 {
+						d.fshr(1);
+						r.copy(&cum2v); r.conj();
+						t.copy(&cumv);
+						t.xtr_a(&cu,&cv,&r);
+						cum2v.copy(&cumv);
+						cum2v.xtr_d();
+						cumv.copy(&t);
+						cu.xtr_d();
+					} else {
+						if e.parity()==1 {
+							d.sub(&e); d.norm();
+							d.fshr(1);
+							t.copy(&cv);
+							t.xtr_a(&cu,&cumv,&cum2v);
+							cu.xtr_d();
+							cum2v.copy(&cv);
+							cum2v.xtr_d();
+							cum2v.conj();
+							cv.copy(&t);
+						} else {
+							w.copy(&d);
+							d.copy(&e); d.fshr(1);
+							e.copy(&w);
+							t.copy(&cumv);
+							t.xtr_d();
+							cumv.copy(&cum2v); cumv.conj();
+							cum2v.copy(&t); cum2v.conj();
+							t.copy(&cv);
+							t.xtr_d();
+							cv.copy(&cu);
+							cu.copy(&t);
+						}
+					}	
+				}
+			}
+			if BIG::comp(&d,&e)<0 {
+				w.copy(&d); w.imul(4); w.norm();
+				if BIG::comp(&e,&w)<=0 {
+					e.sub(&d); e.norm();
+					t.copy(&cv);
+					t.xtr_a(&cu,&cumv,&cum2v);
+					cum2v.copy(&cumv);
+					cumv.copy(&cu);
+					cu.copy(&t);
+				} else {
+					if e.parity()==0 {
+						w.copy(&d);
+						d.copy(&e); d.fshr(1);
+						e.copy(&w);
+						t.copy(&cumv);
+						t.xtr_d();
+						cumv.copy(&cum2v); cumv.conj();
+						cum2v.copy(&t); cum2v.conj();
+						t.copy(&cv);
+						t.xtr_d();
+						cv.copy(&cu);
+						cu.copy(&t);
+					} else {
+						if d.parity()==1 {
+							w.copy(&e);
+							e.copy(&d);
+							w.sub(&d); w.norm();
+							d.copy(&w); d.fshr(1);
+							t.copy(&cv);
+							t.xtr_a(&cu,&cumv,&cum2v);
+							cumv.conj();
+							cum2v.copy(&cu);
+							cum2v.xtr_d();
+							cum2v.conj();
+							cu.copy(&cv);
+							cu.xtr_d();
+							cv.copy(&t);
+						} else {
+							d.fshr(1);
+							r.copy(&cum2v); r.conj();
+							t.copy(&cumv);
+							t.xtr_a(&cu,&cv,&r);
+							cum2v.copy(&cumv);
+							cum2v.xtr_d();
+							cumv.copy(&t);
+							cu.xtr_d();
+						}
+					}
+				}
+			}
+		}
+		r.copy(&cv);
+		r.xtr_a(&cu,&cumv,&cum2v);
+		for _ in 0..f2 {r.xtr_d()}
+		r=r.xtr_pow(&mut d);
+		return r;
+	}
+
+
+/* this/=2 */
+	pub fn div2(&mut self) {
+		self.a.div2();
+		self.b.div2();
+	}
+
+	pub fn div_i(&mut self) {
+		let mut u=FP2::new_copy(&self.a);
+		let v=FP2::new_copy(&self.b);
+		u.div_ip();
+		self.a.copy(&v);
+		self.b.copy(&u);
+	}	
+
+	pub fn div_2i(&mut self) {
+		let mut u=FP2::new_copy(&self.a);
+		let mut v=FP2::new_copy(&self.b);
+		u.div_ip2();
+		v.dbl(); v.norm();
+		self.a.copy(&v);
+		self.b.copy(&u);
+	}
+
+/* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */
+/* returns true if this is QR */
+	pub fn sqrt(&mut self) -> bool {
+		if self.iszilch() {return true;}
+
+		let mut a=FP2::new_copy(&self.a);
+		let mut s=FP2::new_copy(&self.b);
+		let mut t=FP2::new_copy(&self.a);
+
+		if s.iszilch() {
+			if t.sqrt() {
+				self.a.copy(&t);
+				self.b.zero();
+			} else {
+				t.div_ip();
+				t.sqrt();
+				self.b.copy(&t);
+				self.a.zero();
+			}
+			return true;
+		}
+		s.sqr();
+		a.sqr();
+		s.mul_ip();
+		s.norm();
+		a.sub(&s);   
+
+		s.copy(&a);
+		if !s.sqrt() {
+			return false;
+		}
+
+		a.copy(&t); a.add(&s); a.norm(); a.div2();
+
+		if !a.sqrt() {
+			a.copy(&t); a.sub(&s); a.norm(); a.div2();
+			if !a.sqrt() {
+				return false
+			}
+		}
+		t.copy(&self.b);
+		s.copy(&a); s.add(&a);
+		s.inverse();
+
+		t.mul(&s);
+		self.a.copy(&a);
+		self.b.copy(&t);
+
+		return true;
+	}
+
+
+}
+/*
+fn main()
+{
+	let mut w=FP4::new();
+}
+*/
diff --git a/version3/rust/fp48.rs b/version3/rust/fp48.rs
new file mode 100644
index 0000000..a4f3bb4
--- /dev/null
+++ b/version3/rust/fp48.rs
@@ -0,0 +1,1069 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use xxx::big;
+use xxx::ecp;
+use xxx::fp2::FP2;
+use xxx::fp4::FP4;
+use xxx::fp8::FP8;
+use xxx::fp16::FP16;
+use xxx::big::BIG;
+use xxx::rom;
+
+#[derive(Copy, Clone)]
+pub struct FP48 {
+	a:FP16,
+	b:FP16,
+	c:FP16
+}
+
+impl FP48 {
+
+	pub fn new() -> FP48 {
+		FP48 {
+				a: FP16::new(),
+				b: FP16::new(),
+				c: FP16::new()
+		}
+	}
+
+	pub fn new_int(a: isize) -> FP48 {
+		let mut f=FP48::new();
+		f.a.copy(&FP16::new_int(a));
+		f.b.zero();
+		f.c.zero();
+		return f;
+	}	
+
+	pub fn new_copy(x: &FP48) -> FP48 {
+		let mut f=FP48::new();
+		f.a.copy(&x.a);
+		f.b.copy(&x.b);
+		f.c.copy(&x.c);
+		return f;
+	}
+
+	pub fn new_fp16s(d: &FP16,e: &FP16,f: &FP16) -> FP48 {
+		let mut g=FP48::new();
+		g.a.copy(d);
+		g.b.copy(e);
+		g.c.copy(f);
+		return g;
+	}	
+
+	pub fn new_fp16(d: &FP16) -> FP48 {
+		let mut g=FP48::new();
+		g.a.copy(d);
+		g.b.zero();
+		g.c.zero();
+		return g;
+	}
+
+/* reduce components mod Modulus */
+	pub fn reduce(&mut self) {
+		self.a.reduce();
+		self.b.reduce();
+		self.c.reduce();
+	}
+
+/* normalise components of w */
+	pub fn norm(&mut self) {
+		self.a.norm();
+		self.b.norm();
+		self.c.norm();
+	}	
+
+/* test self=0 ? */
+	pub fn iszilch(&self) -> bool {
+		//self.reduce();
+		return self.a.iszilch() && self.b.iszilch() && self.c.iszilch();
+	}	
+
+/* Conditional move of g to self dependant on d */
+	pub fn cmove(&mut self,g:&FP48,d: isize) {
+		self.a.cmove(&g.a,d);
+		self.b.cmove(&g.b,d);
+		self.c.cmove(&g.c,d);
+	}	
+
+/* return 1 if b==c, no branching */
+	fn teq(b: i32,c: i32) -> isize {
+		let mut x=b^c;
+		x-=1;  // if x=0, x now -1
+		return ((x>>31)&1) as isize;
+	}
+
+/* Constant time select from pre-computed table */
+	pub fn selector(&mut self,g: &[FP48],b: i32) {
+		let m=b>>31;
+		let mut babs=(b^m)-m;
+
+		babs=(babs-1)/2;
+
+		self.cmove(&g[0],FP48::teq(babs,0));  // conditional move
+		self.cmove(&g[1],FP48::teq(babs,1));
+		self.cmove(&g[2],FP48::teq(babs,2));
+		self.cmove(&g[3],FP48::teq(babs,3));
+		self.cmove(&g[4],FP48::teq(babs,4));
+		self.cmove(&g[5],FP48::teq(babs,5));
+		self.cmove(&g[6],FP48::teq(babs,6));
+		self.cmove(&g[7],FP48::teq(babs,7));
+ 
+ 		let mut invf=FP48::new_copy(self);
+		invf.conj();
+		self.cmove(&invf,(m&1) as isize);
+	}		
+
+
+/* test self=1 ? */
+	pub fn isunity(&self) -> bool {
+		let one=FP16::new_int(1);
+		return self.a.equals(&one) && self.b.iszilch() && self.c.iszilch();
+	}
+
+/* test self=x */
+	pub fn equals(&self,x:&FP48) -> bool {
+		return self.a.equals(&x.a) && self.b.equals(&x.b) && self.c.equals(&x.c);
+	}
+
+	pub fn geta(&mut self) -> FP16 {
+		let f=FP16::new_copy(&self.a);
+		return f;
+	}
+
+	pub fn getb(&mut self) -> FP16 {
+		let f=FP16::new_copy(&self.b);
+		return f;
+	}
+
+	pub fn getc(&mut self) -> FP16 {
+		let f=FP16::new_copy(&self.c);
+		return f;
+	}	
+
+/* copy self=x */
+	pub fn copy(&mut self,x :&FP48) {
+		self.a.copy(&x.a);
+		self.b.copy(&x.b);
+		self.c.copy(&x.c);
+	}
+
+/* set self=1 */
+	pub fn one(&mut self) {
+		self.a.one();
+		self.b.zero();
+		self.c.zero();
+	}
+
+/* this=conj(this) */
+	pub fn conj(&mut self) {
+		self.a.conj();
+		self.b.nconj();
+		self.c.conj();
+	}
+
+/* Granger-Scott Unitary Squaring */
+	pub fn usqr(&mut self) {
+		let mut a=FP16::new_copy(&self.a);
+		let mut b=FP16::new_copy(&self.c);
+		let mut c=FP16::new_copy(&self.b);
+		let mut d=FP16::new();
+
+		self.a.sqr();
+		d.copy(&self.a); d.add(&self.a);
+		self.a.add(&d);
+
+		self.a.norm();
+		a.nconj();
+
+		a.dbl();
+		self.a.add(&a);
+		b.sqr();
+		b.times_i();
+
+		d.copy(&b); d.add(&b);
+		b.add(&d);
+		b.norm();
+
+		c.sqr();
+		d.copy(&c); d.add(&c);
+		c.add(&d);
+		c.norm();
+
+		self.b.conj();
+		self.b.dbl();
+		self.c.nconj();
+
+		self.c.dbl();
+		self.b.add(&b);
+		self.c.add(&c);
+		self.reduce();
+
+	}
+
+/* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
+	pub fn sqr(&mut self) {
+		let mut a=FP16::new_copy(&self.a);
+		let mut b=FP16::new_copy(&self.b);
+		let mut c=FP16::new_copy(&self.c);
+		let mut d=FP16::new_copy(&self.a);
+
+		a.sqr();
+		b.mul(&self.c);
+		b.dbl(); b.norm();
+		c.sqr();
+		d.mul(&self.b);
+		d.dbl();
+
+		self.c.add(&self.a);
+		self.c.add(&self.b); self.c.norm();
+		self.c.sqr();
+
+		self.a.copy(&a);
+		a.add(&b);
+		a.norm();
+		a.add(&c);
+		a.add(&d);
+		a.norm();
+
+		a.neg();
+		b.times_i();
+		c.times_i();
+
+		self.a.add(&b);
+
+		self.b.copy(&c); self.b.add(&d);
+		self.c.add(&a);
+		self.norm();
+	}
+
+/* FP48 full multiplication self=self*y */
+	pub fn mul(&mut self,y: &FP48) {
+		let mut z0=FP16::new_copy(&self.a);
+		let mut z1=FP16::new();
+		let mut z2=FP16::new_copy(&mut self.b);
+		let mut z3=FP16::new();
+		let mut t0=FP16::new_copy(&self.a);
+		let mut t1=FP16::new_copy(&y.a);
+
+		z0.mul(&y.a);
+		z2.mul(&y.b);
+
+		t0.add(&self.b);
+		t1.add(&y.b);
+
+		t0.norm(); t1.norm();
+
+		z1.copy(&t0); z1.mul(&t1);
+		t0.copy(&self.b); t0.add(&self.c);
+		t1.copy(&y.b); t1.add(&y.c);
+
+		t0.norm(); t1.norm();	
+
+		z3.copy(&t0); z3.mul(&t1);
+
+		t0.copy(&z0); t0.neg();
+		t1.copy(&z2); t1.neg();
+
+		z1.add(&t0);
+		//z1.norm();
+		self.b.copy(&z1); self.b.add(&t1);
+
+		z3.add(&t1);
+		z2.add(&t0);
+
+		t0.copy(&self.a); t0.add(&self.c); t0.norm();
+		t1.copy(&y.a); t1.add(&y.c); t1.norm();
+		t0.mul(&t1);
+		z2.add(&t0);
+
+		t0.copy(&self.c); t0.mul(&y.c);
+		t1.copy(&t0); t1.neg();
+
+
+		self.c.copy(&z2); self.c.add(&t1);
+		z3.add(&t1);
+		t0.times_i();
+		self.b.add(&t0);
+		z3.norm();
+
+		z3.times_i();
+		self.a.copy(&z0); self.a.add(&z3);
+		self.norm();
+	}
+
+/* Special case of multiplication arises from special form of ATE pairing line function */
+	pub fn smul(&mut self,y: &FP48,twist: usize) {
+
+		if twist==ecp::D_TYPE {
+			let mut z0=FP16::new_copy(&self.a);
+			let mut z2=FP16::new_copy(&self.b);
+			let mut z3=FP16::new_copy(&self.b);
+			let mut t0=FP16::new();
+			let mut t1=FP16::new_copy(&y.a);
+		
+			z0.mul(&y.a);
+			z2.pmul(&y.b.real());
+			self.b.add(&self.a);
+			t1.padd(&y.b.real());
+
+			self.b.norm(); t1.norm();
+
+			self.b.mul(&t1);
+			z3.add(&self.c); z3.norm();
+			z3.pmul(&y.b.real());
+
+			t0.copy(&z0); t0.neg();
+			t1.copy(&z2); t1.neg();
+	
+			self.b.add(&t0);
+		//self.b.norm();
+
+			self.b.add(&t1);
+			z3.add(&t1);
+			z2.add(&t0);
+
+			t0.copy(&self.a); t0.add(&self.c);
+			t0.norm(); z3.norm();
+			
+			t0.mul(&y.a);
+			self.c.copy(&z2); self.c.add(&t0);
+
+			z3.times_i();
+			self.a.copy(&z0); self.a.add(&z3);
+		}
+		if twist==ecp::M_TYPE {
+			let mut z0=FP16::new_copy(&self.a);
+			let mut z1=FP16::new();
+			let mut z2=FP16::new();
+			let mut z3=FP16::new();
+			let mut t0=FP16::new_copy(&self.a);
+			let mut t1=FP16::new();
+		
+			z0.mul(&y.a);
+			t0.add(&self.b);
+			t0.norm();
+
+			z1.copy(&t0); z1.mul(&y.a);
+			t0.copy(&self.b); t0.add(&self.c);
+			t0.norm();
+
+			z3.copy(&t0); //z3.mul(y.c);
+			z3.pmul(&y.c.getb());
+			z3.times_i();
+
+			t0.copy(&z0); t0.neg();
+
+			z1.add(&t0);
+			self.b.copy(&z1); 
+			z2.copy(&t0);
+
+			t0.copy(&self.a); t0.add(&self.c);
+			t1.copy(&y.a); t1.add(&y.c);
+
+			t0.norm();
+			t1.norm();
+	
+			t0.mul(&t1);
+			z2.add(&t0);
+
+			t0.copy(&self.c);
+			
+			t0.pmul(&y.c.getb());
+			t0.times_i();
+
+			t1.copy(&t0); t1.neg();
+
+			self.c.copy(&z2); self.c.add(&t1);
+			z3.add(&t1);
+			t0.times_i();
+			self.b.add(&t0);
+			z3.norm();
+			z3.times_i();
+			self.a.copy(&z0); self.a.add(&z3);
+		}
+		self.norm();		
+	}
+
+/* self=1/self */
+	pub fn inverse(&mut self) {
+		let mut f0=FP16::new_copy(&self.a);
+		let mut f1=FP16::new_copy(&self.b);
+		let mut f2=FP16::new_copy(&self.a);
+		let mut f3=FP16::new();
+
+		self.norm();
+		f0.sqr();
+		f1.mul(&self.c);
+		f1.times_i();
+		f0.sub(&f1); f0.norm();
+
+		f1.copy(&self.c); f1.sqr();
+		f1.times_i();
+		f2.mul(&self.b);
+		f1.sub(&f2); f1.norm();
+
+		f2.copy(&self.b); f2.sqr();
+		f3.copy(&self.a); f3.mul(&self.c);
+		f2.sub(&f3); f2.norm();
+
+		f3.copy(&self.b); f3.mul(&f2);
+		f3.times_i();
+		self.a.mul(&f0);
+		f3.add(&self.a);
+		self.c.mul(&f1);
+		self.c.times_i();
+
+		f3.add(&self.c); f3.norm();
+		f3.inverse();
+		self.a.copy(&f0); self.a.mul(&f3);
+		self.b.copy(&f1); self.b.mul(&f3);
+		self.c.copy(&f2); self.c.mul(&f3);
+	}
+
+	/* self=self^p using Frobenius */
+	pub fn frob(&mut self,f: &FP2,n:isize) {
+		let mut f2=FP2::new_copy(f);
+		let mut f3=FP2::new_copy(f);
+
+		f2.sqr();
+		f3.mul(&f2);
+
+		f3.mul_ip(); f3.norm();
+		f3.mul_ip(); f3.norm();		
+
+		for _i in 0..n {
+			self.a.frob(&f3);
+			self.b.frob(&f3);
+			self.c.frob(&f3);
+
+			self.b.qmul(f); self.b.times_i4(); self.b.times_i2();
+			self.c.qmul(&f2); self.c.times_i4(); self.c.times_i4(); self.c.times_i4();
+		}
+	}
+
+/* trace function */
+	pub fn trace(&mut self) -> FP16 {
+		let mut t=FP16::new();
+		t.copy(&self.a);
+		t.imul(3);
+		t.reduce();
+		return t;
+	}
+
+/* convert from byte array to FP48 */
+	pub fn frombytes(w: &[u8]) -> FP48 {
+		let mut t:[u8;big::MODBYTES as usize]=[0;big::MODBYTES as usize];
+		let mb=big::MODBYTES as usize;
+
+		for i in 0..mb {t[i]=w[i]}
+		let mut a=BIG::frombytes(&t);
+		for i in 0..mb {t[i]=w[i+mb]}
+		let mut b=BIG::frombytes(&t);
+		let mut c=FP2::new_bigs(&a,&b);
+
+		for i in 0..mb {t[i]=w[i+2*mb]}
+		a.copy(&BIG::frombytes(&t));
+		for i in 0..mb {t[i]=w[i+3*mb]}
+		b.copy(&BIG::frombytes(&t));
+		let mut d=FP2::new_bigs(&a,&b);
+
+		let mut ea=FP4::new_fp2s(&c,&d);
+
+		for i in 0..mb {t[i]=w[i+4*mb]}
+		a.copy(&BIG::frombytes(&t));
+		for i in 0..mb {t[i]=w[i+5*mb]}
+		b.copy(&BIG::frombytes(&t));
+		c.copy(&FP2::new_bigs(&a,&b));
+
+		for i in 0..mb {t[i]=w[i+6*mb]}
+		a.copy(&BIG::frombytes(&t));
+		for i in 0..mb {t[i]=w[i+7*mb]}
+		b.copy(&BIG::frombytes(&t));
+		d.copy(&FP2::new_bigs(&a,&b));
+
+		let mut eb=FP4::new_fp2s(&c,&d);
+
+		let mut ea8=FP8::new_fp4s(&ea,&eb);
+
+		for i in 0..mb {t[i]=w[i+8*mb]}
+		let mut a=BIG::frombytes(&t);
+		for i in 0..mb {t[i]=w[i+9*mb]}
+		let mut b=BIG::frombytes(&t);
+		let mut c=FP2::new_bigs(&a,&b);
+
+		for i in 0..mb {t[i]=w[i+10*mb]}
+		a.copy(&BIG::frombytes(&t));
+		for i in 0..mb {t[i]=w[i+11*mb]}
+		b.copy(&BIG::frombytes(&t));
+		let mut d=FP2::new_bigs(&a,&b);
+
+		ea.copy(&FP4::new_fp2s(&c,&d));
+
+		for i in 0..mb {t[i]=w[i+12*mb]}
+		a.copy(&BIG::frombytes(&t));
+		for i in 0..mb {t[i]=w[i+13*mb]}
+		b.copy(&BIG::frombytes(&t));
+		c.copy(&FP2::new_bigs(&a,&b));
+
+		for i in 0..mb {t[i]=w[i+14*mb]}
+		a.copy(&BIG::frombytes(&t));
+		for i in 0..mb {t[i]=w[i+15*mb]}
+		b.copy(&BIG::frombytes(&t));
+		d.copy(&FP2::new_bigs(&a,&b));
+
+		eb.copy(&FP4::new_fp2s(&c,&d));
+
+		let mut eb8=FP8::new_fp4s(&ea,&eb);
+
+		let e=FP16::new_fp8s(&ea8,&eb8);
+
+
+
+
+
+		for i in 0..mb {t[i]=w[i+16*mb]}
+		a.copy(&BIG::frombytes(&t));
+		for i in 0..mb {t[i]=w[i+17*mb]}
+		b.copy(&BIG::frombytes(&t));
+		c.copy(&FP2::new_bigs(&a,&b));
+
+		for i in 0..mb {t[i]=w[i+18*mb]}
+		a.copy(&BIG::frombytes(&t));
+		for i in 0..mb {t[i]=w[i+19*mb]}
+		b.copy(&BIG::frombytes(&t));
+		d.copy(&FP2::new_bigs(&a,&b));
+
+		ea.copy(&FP4::new_fp2s(&c,&d));
+
+		for i in 0..mb {t[i]=w[i+20*mb]}
+		a.copy(&BIG::frombytes(&t));
+		for i in 0..mb {t[i]=w[i+21*mb]}
+		b.copy(&BIG::frombytes(&t));
+		c.copy(&FP2::new_bigs(&a,&b));
+
+		for i in 0..mb {t[i]=w[i+22*mb]}
+		a.copy(&BIG::frombytes(&t));
+		for i in 0..mb {t[i]=w[i+23*mb]}
+		b.copy(&BIG::frombytes(&t));
+		d.copy(&FP2::new_bigs(&a,&b));
+
+		eb.copy(&FP4::new_fp2s(&c,&d));
+
+		ea8.copy(&FP8::new_fp4s(&ea,&eb));
+
+
+		for i in 0..mb {t[i]=w[i+24*mb]}
+		a.copy(&BIG::frombytes(&t));
+		for i in 0..mb {t[i]=w[i+25*mb]}
+		b.copy(&BIG::frombytes(&t));
+		c.copy(&FP2::new_bigs(&a,&b));
+
+		for i in 0..mb {t[i]=w[i+26*mb]}
+		a.copy(&BIG::frombytes(&t));
+		for i in 0..mb {t[i]=w[i+27*mb]}
+		b.copy(&BIG::frombytes(&t));
+		d.copy(&FP2::new_bigs(&a,&b));
+
+		ea.copy(&FP4::new_fp2s(&c,&d));
+
+		for i in 0..mb {t[i]=w[i+28*mb]}
+		a.copy(&BIG::frombytes(&t));
+		for i in 0..mb {t[i]=w[i+29*mb]}
+		b.copy(&BIG::frombytes(&t));
+		c.copy(&FP2::new_bigs(&a,&b));
+
+		for i in 0..mb {t[i]=w[i+30*mb]}
+		a.copy(&BIG::frombytes(&t));
+		for i in 0..mb {t[i]=w[i+31*mb]}
+		b.copy(&BIG::frombytes(&t));
+		d.copy(&FP2::new_bigs(&a,&b));
+
+		eb.copy(&FP4::new_fp2s(&c,&d));
+
+		eb8.copy(&FP8::new_fp4s(&ea,&eb));
+
+
+		let f=FP16::new_fp8s(&ea8,&eb8);
+
+
+
+		for i in 0..mb {t[i]=w[i+32*mb]}
+		a.copy(&BIG::frombytes(&t));
+		for i in 0..mb {t[i]=w[i+33*mb]}
+		b.copy(&BIG::frombytes(&t));
+		
+		c.copy(&FP2::new_bigs(&a,&b));
+
+		for i in 0..mb {t[i]=w[i+34*mb]}
+		a.copy(&BIG::frombytes(&t));
+		for i in 0..mb {t[i]=w[i+35*mb]}
+		b.copy(&BIG::frombytes(&t));
+		d.copy(&FP2::new_bigs(&a,&b));
+
+		ea.copy(&FP4::new_fp2s(&c,&d));
+
+		for i in 0..mb {t[i]=w[i+36*mb]}
+		a.copy(&BIG::frombytes(&t));
+		for i in 0..mb {t[i]=w[i+37*mb]}
+		b.copy(&BIG::frombytes(&t));
+		
+		c.copy(&FP2::new_bigs(&a,&b));
+
+		for i in 0..mb {t[i]=w[i+38*mb]}
+		a.copy(&BIG::frombytes(&t));
+		for i in 0..mb {t[i]=w[i+39*mb]}
+		b.copy(&BIG::frombytes(&t));
+		d.copy(&FP2::new_bigs(&a,&b));
+
+		eb.copy(&FP4::new_fp2s(&c,&d));
+
+		ea8.copy(&FP8::new_fp4s(&ea,&eb));
+
+		for i in 0..mb {t[i]=w[i+40*mb]}
+		a.copy(&BIG::frombytes(&t));
+		for i in 0..mb {t[i]=w[i+41*mb]}
+		b.copy(&BIG::frombytes(&t));
+		
+		c.copy(&FP2::new_bigs(&a,&b));
+
+		for i in 0..mb {t[i]=w[i+42*mb]}
+		a.copy(&BIG::frombytes(&t));
+		for i in 0..mb {t[i]=w[i+43*mb]}
+		b.copy(&BIG::frombytes(&t));
+		d.copy(&FP2::new_bigs(&a,&b));
+
+		ea.copy(&FP4::new_fp2s(&c,&d));
+
+		for i in 0..mb {t[i]=w[i+44*mb]}
+		a.copy(&BIG::frombytes(&t));
+		for i in 0..mb {t[i]=w[i+45*mb]}
+		b.copy(&BIG::frombytes(&t));
+		
+		c.copy(&FP2::new_bigs(&a,&b));
+
+		for i in 0..mb {t[i]=w[i+46*mb]}
+		a.copy(&BIG::frombytes(&t));
+		for i in 0..mb {t[i]=w[i+47*mb]}
+		b.copy(&BIG::frombytes(&t));
+		d.copy(&FP2::new_bigs(&a,&b));
+
+		eb.copy(&FP4::new_fp2s(&c,&d));
+
+		eb8.copy(&FP8::new_fp4s(&ea,&eb));
+
+
+		let g=FP16::new_fp8s(&ea8,&eb8);
+
+		return FP48::new_fp16s(&e,&f,&g);
+	}
+
+/* convert this to byte array */
+	pub fn tobytes(&mut self,w: &mut [u8]) {
+		let mut t:[u8;big::MODBYTES as usize]=[0;big::MODBYTES as usize];
+		let mb=big::MODBYTES as usize;
+
+		self.a.geta().geta().geta().geta().tobytes(&mut t);
+		for i in 0..mb {w[i]=t[i]}
+		self.a.geta().geta().geta().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+mb]=t[i]}
+		self.a.geta().geta().getb().geta().tobytes(&mut t);
+		for i in 0..mb {w[i+2*mb]=t[i]}
+		self.a.geta().geta().getb().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+3*mb]=t[i]}
+
+		self.a.geta().getb().geta().geta().tobytes(&mut t);
+		for i in 0..mb {w[i+4*mb]=t[i]}
+		self.a.geta().getb().geta().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+5*mb]=t[i]}
+		self.a.geta().getb().getb().geta().tobytes(&mut t);
+		for i in 0..mb {w[i+6*mb]=t[i]}
+		self.a.geta().getb().getb().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+7*mb]=t[i]}
+
+
+		self.a.getb().geta().geta().geta().tobytes(&mut t);
+		for i in 0..mb {w[i+8*mb]=t[i]}
+		self.a.getb().geta().geta().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+9*mb]=t[i]}
+		self.a.getb().geta().getb().geta().tobytes(&mut t);
+		for i in 0..mb {w[i+10*mb]=t[i]}
+		self.a.getb().geta().getb().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+11*mb]=t[i]}
+
+		self.a.getb().getb().geta().geta().tobytes(&mut t);
+		for i in 0..mb {w[i+12*mb]=t[i]}
+		self.a.getb().getb().geta().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+13*mb]=t[i]}
+		self.a.getb().getb().getb().geta().tobytes(&mut t);
+		for i in 0..mb {w[i+14*mb]=t[i]}
+		self.a.getb().getb().getb().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+15*mb]=t[i]}
+
+
+
+
+
+
+		self.b.geta().geta().geta().geta().tobytes(&mut t);
+		for i in 0..mb {w[i+16*mb]=t[i]}
+		self.b.geta().geta().geta().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+17*mb]=t[i]}
+		self.b.geta().geta().getb().geta().tobytes(&mut t);
+		for i in 0..mb {w[i+18*mb]=t[i]}
+		self.b.geta().geta().getb().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+19*mb]=t[i]}
+
+		self.b.geta().getb().geta().geta().tobytes(&mut t);
+		for i in 0..mb {w[i+20*mb]=t[i]}
+		self.b.geta().getb().geta().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+21*mb]=t[i]}
+		self.b.geta().getb().getb().geta().tobytes(&mut t);
+		for i in 0..mb {w[i+22*mb]=t[i]}
+		self.b.geta().getb().getb().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+23*mb]=t[i]}
+
+
+		self.b.getb().geta().geta().geta().tobytes(&mut t);
+		for i in 0..mb {w[i+24*mb]=t[i]}
+		self.b.getb().geta().geta().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+25*mb]=t[i]}
+		self.b.getb().geta().getb().geta().tobytes(&mut t);
+		for i in 0..mb {w[i+26*mb]=t[i]}
+		self.b.getb().geta().getb().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+27*mb]=t[i]}
+
+		self.b.getb().getb().geta().geta().tobytes(&mut t);
+		for i in 0..mb {w[i+28*mb]=t[i]}
+		self.b.getb().getb().geta().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+29*mb]=t[i]}
+		self.b.getb().getb().getb().geta().tobytes(&mut t);
+		for i in 0..mb {w[i+30*mb]=t[i]}
+		self.b.getb().getb().getb().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+31*mb]=t[i]}
+
+
+
+
+
+		self.c.geta().geta().geta().geta().tobytes(&mut t);
+		for i in 0..mb {w[i+32*mb]=t[i]}
+		self.c.geta().geta().geta().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+33*mb]=t[i]}
+		self.c.geta().geta().getb().geta().tobytes(&mut t);
+		for i in 0..mb {w[i+34*mb]=t[i]}
+		self.c.geta().geta().getb().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+35*mb]=t[i]}
+
+		self.c.geta().getb().geta().geta().tobytes(&mut t);
+		for i in 0..mb {w[i+36*mb]=t[i]}
+		self.c.geta().getb().geta().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+37*mb]=t[i]}
+		self.c.geta().getb().getb().geta().tobytes(&mut t);
+		for i in 0..mb {w[i+38*mb]=t[i]}
+		self.c.geta().getb().getb().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+39*mb]=t[i]}		
+
+
+		self.c.getb().geta().geta().geta().tobytes(&mut t);
+		for i in 0..mb {w[i+40*mb]=t[i]}
+		self.c.getb().geta().geta().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+41*mb]=t[i]}
+		self.c.getb().geta().getb().geta().tobytes(&mut t);
+		for i in 0..mb {w[i+42*mb]=t[i]}
+		self.c.getb().geta().getb().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+43*mb]=t[i]}
+
+		self.c.getb().getb().geta().geta().tobytes(&mut t);
+		for i in 0..mb {w[i+44*mb]=t[i]}
+		self.c.getb().getb().geta().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+45*mb]=t[i]}
+		self.c.getb().getb().getb().geta().tobytes(&mut t);
+		for i in 0..mb {w[i+46*mb]=t[i]}
+		self.c.getb().getb().getb().getb().tobytes(&mut t);
+		for i in 0..mb {w[i+47*mb]=t[i]}		
+
+	}
+
+/* output to hex string */
+	pub fn tostring(&mut self) -> String {
+		return format!("[{},{},{}]",self.a.tostring(),self.b.tostring(),self.c.tostring());		
+	}
+
+/* self=self^e */
+	pub fn pow(&self,e: &BIG) -> FP48 {
+		let mut r=FP48::new_copy(self);	
+		r.norm();
+		let mut e1=BIG::new_copy(e);
+		e1.norm();
+		let mut e3=BIG::new_copy(&e1);
+		e3.pmul(3);
+		e3.norm();
+		let mut w=FP48::new_copy(&r);
+
+		let nb=e3.nbits();
+		for i in (1..nb-1).rev() {
+			w.usqr();
+			let bt=e3.bit(i)-e1.bit(i);
+			if bt==1 {
+				w.mul(&r);
+			}
+			if bt == -1 {
+				r.conj(); w.mul(&r); r.conj();
+			}
+		}
+
+		w.reduce();
+		return w;
+	}	
+
+/* constant time powering by small integer of max length bts */
+	pub fn pinpow(&mut self,e: i32,bts: i32) {
+		let mut r:[FP48;2]=[FP48::new_int(1),FP48::new_copy(self)];
+		let mut t=FP48::new();
+
+		for i in (0..bts).rev() {
+			let b:usize=((e>>i)&1) as usize;
+			t.copy(&r[b]);
+			r[1-b].mul(&t);
+			r[b].usqr();
+		}
+		self.copy(&r[0]);
+	}
+
+	pub fn compow(&mut self,e: &BIG, r: &BIG) -> FP16 {
+		let f=FP2::new_bigs(&BIG::new_ints(&rom::FRA),&BIG::new_ints(&rom::FRB));
+		let q=BIG::new_ints(&rom::MODULUS);
+
+		let mut g1=FP48::new_copy(self);
+		let mut g2=FP48::new_copy(self);
+
+
+		let mut m=BIG::new_copy(&q);
+		m.rmod(&r);
+
+		let mut a=BIG::new_copy(&e);
+		a.rmod(&mut m);
+
+		let mut b=BIG::new_copy(&e);
+		b.div(&mut m);
+
+		let mut c=g1.trace();
+
+		if b.iszilch() {
+			c=c.xtr_pow(&mut a);
+			return c;
+		}
+
+		g2.frob(&f,1);
+		let cp=g2.trace();
+		g1.conj();
+		g2.mul(&g1);
+		let cpm1=g2.trace();
+		g2.mul(&g1);
+		let cpm2=g2.trace();
+
+		c=c.xtr_pow2(&cp,&cpm1,&cpm2,&mut a,&mut b);
+
+		return c;
+	}
+
+/* p=q0^u0.q1^u1.q2^u2.q3^u3... */
+// Bos & Costello https://eprint.iacr.org/2013/458.pdf
+// Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
+// Side channel attack secure 
+ 	pub fn pow16(q:&[FP48],u:&[BIG]) -> FP48 {
+		let mut g1:[FP48;8]=[FP48::new(),FP48::new(),FP48::new(),FP48::new(),FP48::new(),FP48::new(),FP48::new(),FP48::new()];
+		let mut g2:[FP48;8]=[FP48::new(),FP48::new(),FP48::new(),FP48::new(),FP48::new(),FP48::new(),FP48::new(),FP48::new()];
+		let mut g3:[FP48;8]=[FP48::new(),FP48::new(),FP48::new(),FP48::new(),FP48::new(),FP48::new(),FP48::new(),FP48::new()];
+		let mut g4:[FP48;8]=[FP48::new(),FP48::new(),FP48::new(),FP48::new(),FP48::new(),FP48::new(),FP48::new(),FP48::new()];
+
+		let mut r=FP48::new();
+		let mut p=FP48::new();
+		const CT:usize=1+big::NLEN*(big::BASEBITS as usize);		
+		let mut w1:[i8;CT]=[0;CT];
+		let mut s1:[i8;CT]=[0;CT];
+		let mut w2:[i8;CT]=[0;CT];
+		let mut s2:[i8;CT]=[0;CT];
+		let mut w3:[i8;CT]=[0;CT];
+		let mut s3:[i8;CT]=[0;CT];
+		let mut w4:[i8;CT]=[0;CT];
+		let mut s4:[i8;CT]=[0;CT];
+
+
+		let mut mt=BIG::new();
+		let mut t:[BIG;16]=[BIG::new_copy(&u[0]),BIG::new_copy(&u[1]),BIG::new_copy(&u[2]),BIG::new_copy(&u[3]),BIG::new_copy(&u[4]),BIG::new_copy(&u[5]),BIG::new_copy(&u[6]),BIG::new_copy(&u[7]),BIG::new_copy(&u[8]),BIG::new_copy(&u[9]),BIG::new_copy(&u[10]),BIG::new_copy(&u[11]),BIG::new_copy(&u[12]),BIG::new_copy(&u[13]),BIG::new_copy(&u[14]),BIG::new_copy(&u[15])];
+
+		for i in 0..16 {
+			t[i].norm();
+		}
+
+// precomputation
+		g1[0].copy(&q[0]); r.copy(&g1[0]);
+		g1[1].copy(&r); g1[1].mul(&q[1]);  // q[0].q[1]
+		g1[2].copy(&r); g1[2].mul(&q[2]); r.copy(&g1[1]); // q[0].q[2]
+		g1[3].copy(&r); g1[3].mul(&q[2]); r.copy(&g1[0]); // q[0].q[1].q[2]
+		g1[4].copy(&r); g1[4].mul(&q[3]); r.copy(&g1[1]); // q[0].q[3]
+		g1[5].copy(&r); g1[5].mul(&q[3]); r.copy(&g1[2]); // q[0].q[1].q[3]
+		g1[6].copy(&r); g1[6].mul(&q[3]); r.copy(&g1[3]); // q[0].q[2].q[3]
+		g1[7].copy(&r); g1[7].mul(&q[3]); // q[0].q[1].q[2].q[3]
+
+// Use Frobenius
+		let f=FP2::new_bigs(&BIG::new_ints(&rom::FRA),&BIG::new_ints(&rom::FRB));
+		for i in 0..8 {
+			g2[i].copy(&g1[i]); g2[i].frob(&f,4);
+			g3[i].copy(&g2[i]); g3[i].frob(&f,4);
+			g4[i].copy(&g3[i]); g4[i].frob(&f,4);						
+		}
+
+
+// Make it odd
+		let pb1=1-t[0].parity();
+		t[0].inc(pb1);
+		t[0].norm();	
+
+		let pb2=1-t[4].parity();
+		t[4].inc(pb2);
+		t[4].norm();		
+
+		let pb3=1-t[8].parity();
+		t[8].inc(pb3);
+		t[8].norm();	
+
+		let pb4=1-t[12].parity();
+		t[12].inc(pb4);
+		t[12].norm();
+
+// Number of bits
+		mt.zero();
+		for i in 0..16 {
+			mt.or(&t[i]);
+		}
+
+		let nb=1+mt.nbits();
+
+// Sign pivot 
+
+		s1[nb-1]=1;
+		s2[nb-1]=1;
+		s3[nb-1]=1;
+		s4[nb-1]=1;		
+		for i in 0..nb-1 {
+			t[0].fshr(1);
+			s1[i]=(2*t[0].parity()-1) as i8;
+			t[4].fshr(1);
+			s2[i]=(2*t[4].parity()-1) as i8;
+			t[8].fshr(1);
+			s3[i]=(2*t[8].parity()-1) as i8;
+			t[12].fshr(1);
+			s4[i]=(2*t[12].parity()-1) as i8;			
+
+		}
+
+// Recoded exponent
+		for i in 0..nb {
+			w1[i]=0;
+			let mut k=1;
+			for j in 1..4 {
+				let bt=s1[i]*(t[j].parity() as i8);
+				t[j].fshr(1);
+				t[j].dec((bt>>1) as isize);
+				t[j].norm();
+				w1[i]+=bt*(k as i8);
+				k=2*k;
+			}
+
+			w2[i]=0;
+			k=1;
+			for j in 5..8 {
+				let bt=s2[i]*(t[j].parity() as i8);
+				t[j].fshr(1);
+				t[j].dec((bt>>1) as isize);
+				t[j].norm();
+				w2[i]+=bt*(k as i8);
+				k=2*k;
+			}			
+
+			w3[i]=0;
+			k=1;
+			for j in 9..12 {
+				let bt=s3[i]*(t[j].parity() as i8);
+				t[j].fshr(1);
+				t[j].dec((bt>>1) as isize);
+				t[j].norm();
+				w3[i]+=bt*(k as i8);
+				k=2*k;
+			}			
+
+
+			w4[i]=0;
+			k=1;
+			for j in 13..16 {
+				let bt=s4[i]*(t[j].parity() as i8);
+				t[j].fshr(1);
+				t[j].dec((bt>>1) as isize);
+				t[j].norm();
+				w4[i]+=bt*(k as i8);
+				k=2*k;
+			}			
+
+		}	
+
+
+// Main loop
+		p.selector(&g1,(2*w1[nb-1]+1) as i32);
+		r.selector(&g2,(2*w2[nb-1]+1) as i32);
+		p.mul(&r);
+		r.selector(&g3,(2*w3[nb-1]+1) as i32);
+		p.mul(&r);		
+		r.selector(&g4,(2*w4[nb-1]+1) as i32);
+		p.mul(&r);		
+		for i in (0..nb-1).rev() {
+			p.usqr();
+			r.selector(&g1,(2*w1[i]+s1[i]) as i32);
+			p.mul(&r);
+			r.selector(&g2,(2*w2[i]+s2[i]) as i32);
+			p.mul(&r);			
+			r.selector(&g3,(2*w3[i]+s3[i]) as i32);
+			p.mul(&r);
+			r.selector(&g4,(2*w4[i]+s4[i]) as i32);
+			p.mul(&r);						
+		}
+
+// apply correction
+		r.copy(&q[0]); r.conj();   
+		r.mul(&p);
+		p.cmove(&r,pb1);
+
+		r.copy(&q[4]); r.conj();   
+		r.mul(&p);
+		p.cmove(&r,pb2);
+
+		r.copy(&q[8]); r.conj();   
+		r.mul(&p);
+		p.cmove(&r,pb3);
+
+		r.copy(&q[12]); r.conj();   
+		r.mul(&p);
+		p.cmove(&r,pb4);
+
+		p.reduce();
+		return p;
+	}
+}
diff --git a/version3/rust/fp8.rs b/version3/rust/fp8.rs
new file mode 100644
index 0000000..c80e2f3
--- /dev/null
+++ b/version3/rust/fp8.rs
@@ -0,0 +1,635 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use xxx::fp::FP;
+use xxx::fp2::FP2;
+use xxx::fp4::FP4;
+use xxx::big::BIG;
+
+#[derive(Copy, Clone)]
+pub struct FP8 {
+	a:FP4,
+	b:FP4,
+}
+
+impl FP8 {
+
+	pub fn new() -> FP8 {
+		FP8 {
+				a: FP4::new(),
+				b: FP4::new(),
+		}
+	}
+
+	pub fn new_int(a: isize) -> FP8 {
+		let mut f=FP8::new();
+		f.a.copy(&FP4::new_int(a));
+		f.b.zero();
+		return f;
+	}	
+
+	pub fn new_copy(x: &FP8) -> FP8 {
+		let mut f=FP8::new();
+		f.a.copy(&x.a);
+		f.b.copy(&x.b);
+		return f;
+	}	
+
+	pub fn new_fp4s(c: &FP4,d: &FP4) -> FP8 {
+		let mut f=FP8::new();
+		f.a.copy(c);
+		f.b.copy(d);
+		return f;
+	}	
+
+	pub fn new_fp4(c: &FP4) -> FP8 {
+		let mut f=FP8::new();
+		f.a.copy(c);
+		f.b.zero();
+		return f;
+	}	
+
+/* reduce components mod Modulus */
+	pub fn reduce(&mut self) {
+		self.a.reduce();
+		self.b.reduce();
+	}
+
+/* normalise components of w */
+	pub fn norm(&mut self) {
+		self.a.norm();
+		self.b.norm();
+	}	
+
+	pub fn cmove(&mut self,g:&FP8,d: isize) {
+		self.a.cmove(&g.a,d);
+		self.b.cmove(&g.b,d);
+	}	
+
+/* test self=0 ? */
+	pub fn iszilch(&self) -> bool {
+		//self.reduce();
+		return self.a.iszilch() && self.b.iszilch();
+	}	
+
+/* test self=1 ? */
+	pub fn isunity(&self) -> bool {
+		let one=FP4::new_int(1);
+		return self.a.equals(&one) && self.b.iszilch();
+	}
+
+/* test is w real? That is in a+ib test b is zero */
+	pub fn isreal(&mut self) -> bool {
+		return self.b.iszilch();
+	}
+/* extract real part a */
+	pub fn real(&self) -> FP4 {
+		let f=FP4::new_copy(&self.a);
+		return f;
+	}
+
+	pub fn geta(&self) -> FP4 {
+		let f=FP4::new_copy(&self.a);
+		return f;
+	}
+/* extract imaginary part b */
+	pub fn getb(&self) -> FP4 {
+		let f=FP4::new_copy(&self.b);
+		return f;
+	}
+
+/* test self=x */
+	pub fn equals(&self,x:&FP8) -> bool {
+		return self.a.equals(&x.a) && self.b.equals(&x.b);
+	}
+/* copy self=x */
+	pub fn copy(&mut self,x :&FP8) {
+		self.a.copy(&x.a);
+		self.b.copy(&x.b);
+	}
+
+/* set self=0 */
+	pub fn zero(&mut self) {
+		self.a.zero();
+		self.b.zero();
+	}
+
+/* set self=1 */
+	pub fn one(&mut self) {
+		self.a.one();
+		self.b.zero();
+	}	
+
+/* negate self mod Modulus */
+	pub fn neg(&mut self) {
+		self.norm();
+		let mut m=FP4::new_copy(&self.a);
+		let mut t=FP4::new();
+
+		m.add(&self.b);
+		m.neg();
+	//	m.norm();
+		t.copy(&m); t.add(&self.b);
+		self.b.copy(&m);
+		self.b.add(&self.a);
+		self.a.copy(&t);
+		self.norm();
+	}	
+
+/* set to a-ib */
+	pub fn conj(&mut self) {
+		self.b.neg();
+		self.norm();
+	}
+
+/* self=-conjugate(self) */
+	pub fn nconj(&mut self) {
+		self.a.neg(); self.norm();
+	}
+
+/* self+=a */
+	pub fn add(&mut self,x:&FP8) {
+		self.a.add(&x.a);
+		self.b.add(&x.b);
+	}
+
+	pub fn padd(&mut self,x:&FP4) {
+		self.a.add(x);
+	}
+
+	pub fn dbl(&mut self) {
+		self.a.dbl();
+		self.b.dbl();
+	}
+
+/* self-=a */
+	pub fn sub(&mut self,x:&FP8) {
+		let mut m=FP8::new_copy(x);
+		m.neg();
+		self.add(&m);
+	}
+
+/* this-=x */
+	pub fn rsub(&mut self,x:&FP8) {
+		self.neg();
+		self.add(x);
+}
+
+/* self*=s, where s is an FP4 */
+	pub fn pmul(&mut self,s:&FP4) {
+		self.a.mul(s);
+		self.b.mul(s);
+	}
+
+/* self*=s, where s is an FP2 */
+	pub fn qmul(&mut self,s:&FP2) {
+		self.a.pmul(s);
+		self.b.pmul(s);
+	}
+
+/* self*=s, where s is an FP */
+	pub fn tmul(&mut self,s:&FP) {
+		self.a.qmul(s);
+		self.b.qmul(s);
+	}
+
+/* self*=i, where i is an int */
+	pub fn imul(&mut self,c: isize) {
+		self.a.imul(c);
+		self.b.imul(c);
+	}
+
+/* self*=self */	
+	pub fn sqr(&mut self) {
+	//	self.norm();
+
+		let mut t1=FP4::new_copy(&self.a);
+		let mut t2=FP4::new_copy(&self.b);
+		let mut t3=FP4::new_copy(&self.a);
+
+
+		t3.mul(&self.b);
+		t1.add(&self.b);
+		t2.times_i();
+
+		t2.add(&self.a);
+
+		t1.norm();
+		t2.norm();
+
+		self.a.copy(&t1);
+
+		self.a.mul(&t2);
+
+		t2.copy(&t3);
+		t2.times_i();
+		t2.add(&t3); t2.norm();
+		t2.neg();
+		self.a.add(&t2);
+
+		t3.dbl();
+		self.b.copy(&t3);
+
+		self.norm();
+	}
+
+/* self*=y */
+	pub fn mul(&mut self,y :&FP8) {
+		self.norm();
+
+		let mut t1=FP4::new_copy(&self.a);
+		let mut t2=FP4::new_copy(&self.b);
+		let mut t3=FP4::new();
+		let mut t4=FP4::new_copy(&self.b);
+
+		t1.mul(&y.a);
+		t2.mul(&y.b);
+		t3.copy(&y.b);
+		t3.add(&y.a);
+		t4.add(&self.a);
+
+		t3.norm(); t4.norm();
+
+		t4.mul(&t3);
+
+		t3.copy(&t1);
+		t3.neg();
+		t4.add(&t3);
+		t4.norm();
+
+		t3.copy(&t2);
+		t3.neg();
+		self.b.copy(&t4);
+		self.b.add(&t3);	
+
+		t2.times_i();
+		self.a.copy(&t2);
+		self.a.add(&t1);
+
+		self.norm();
+	}	
+
+/* output to hex string */
+	pub fn tostring(&mut self) -> String {
+		return format!("[{},{}]",self.a.tostring(),self.b.tostring());		
+	}	
+
+/* self=1/self */
+	pub fn inverse(&mut self) {
+		self.norm();
+
+		let mut t1=FP4::new_copy(&self.a);
+		let mut t2=FP4::new_copy(&self.b);
+
+		t1.sqr();
+		t2.sqr();
+		t2.times_i(); t2.norm();
+		t1.sub(&t2); t1.norm();
+		t1.inverse();
+		self.a.mul(&t1);
+		t1.neg(); t1.norm();
+		self.b.mul(&t1);
+	}	
+
+/* self*=i where i = sqrt(-1+sqrt(-1)) */
+	pub fn times_i(&mut self) {
+	//	self.norm();
+		let mut s=FP4::new_copy(&self.b);
+		let t=FP4::new_copy(&self.a);
+		s.times_i();
+		self.a.copy(&s);	
+		self.b.copy(&t);
+
+		self.norm();
+	}	
+
+	pub fn times_i2(&mut self) {
+		self.a.times_i();
+		self.b.times_i();
+	}
+
+	/* self=self^p using Frobenius */
+	pub fn frob(&mut self,f: &FP2) {
+		let mut ff=FP2::new_copy(f);
+		ff.sqr(); ff.mul_ip(); ff.norm();
+		self.a.frob(&ff);
+		self.b.frob(&ff);
+		self.b.pmul(f);
+		self.b.times_i();	
+
+	}
+
+/* self=self^e */
+	pub fn pow(&self,e: &BIG) -> FP8 {
+		//self.norm();
+		let mut w=FP8::new_copy(self);
+		w.norm();
+		let mut z=BIG::new_copy(&e);
+		let mut r=FP8::new_int(1);
+		z.norm();
+		loop {
+			let bt=z.parity();
+			z.fshr(1);
+			if bt==1 {r.mul(&mut w)};
+			if z.iszilch() {break}
+			w.sqr();
+		}
+		r.reduce();
+		return r;
+	}	
+
+/* XTR xtr_a function */
+	pub fn xtr_a(&mut self,w:&FP8,y:&FP8,z:&FP8) {
+		let mut r=FP8::new_copy(w);
+		let mut t=FP8::new_copy(w);
+	//	y.norm();
+		r.sub(y); r.norm();
+		r.pmul(&self.a);
+		t.add(y); t.norm();
+		t.pmul(&self.b);
+		t.times_i();
+
+		self.copy(&r);
+		self.add(&t);	
+		self.add(z);
+
+		self.norm();
+	}
+
+/* XTR xtr_d function */
+	pub fn xtr_d(&mut self) {
+		let mut w=FP8::new_copy(self);
+		self.sqr(); w.conj();
+		w.dbl(); w.norm();
+		self.sub(&w);
+		self.reduce();
+	}
+
+/* r=x^n using XTR method on traces of FP24s */
+	pub fn xtr_pow(&self,n: &BIG) -> FP8 {
+		let mut sf=FP8::new_copy(self);
+		sf.norm();
+		let mut a=FP8::new_int(3);
+		let mut b=FP8::new_copy(&sf);
+		let mut c=FP8::new_copy(&b);
+		c.xtr_d();
+		let mut t=FP8::new();
+		let mut r=FP8::new();
+		
+		let par=n.parity();
+		let mut v=BIG::new_copy(n); v.norm(); v.fshr(1);
+		if par==0 {v.dec(1); v.norm(); }
+
+		let nb=v.nbits();
+		for i in (0..nb).rev() {
+			if v.bit(i)!=1 {
+				t.copy(&b);
+				sf.conj();
+				c.conj();
+				b.xtr_a(&a,&sf,&c);
+				sf.conj();
+				c.copy(&t);
+				c.xtr_d();
+				a.xtr_d();
+			} else {
+				t.copy(&a); t.conj();
+				a.copy(&b);
+				a.xtr_d();
+				b.xtr_a(&c,&sf,&t);
+				c.xtr_d();
+			}
+		}
+		if par==0 {
+			r.copy(&c)
+		} else {r.copy(&b)}
+		r.reduce();
+		return r;
+	}
+
+/* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */
+	pub fn xtr_pow2(&mut self,ck: &FP8,ckml: &FP8,ckm2l: &FP8,a: &BIG,b: &BIG) -> FP8 {
+
+		let mut e=BIG::new_copy(a);
+		let mut d=BIG::new_copy(b);
+		let mut w=BIG::new();
+		e.norm(); d.norm();
+
+		let mut cu=FP8::new_copy(ck);  // can probably be passed in w/o copying
+		let mut cv=FP8::new_copy(self);
+		let mut cumv=FP8::new_copy(ckml);
+		let mut cum2v=FP8::new_copy(ckm2l);
+		let mut r=FP8::new();
+		let mut t=FP8::new();
+
+		let mut f2:usize=0;
+		while d.parity()==0 && e.parity()==0 {
+			d.fshr(1);
+			e.fshr(1);
+			f2+=1;
+		}
+
+		while BIG::comp(&d,&e)!=0 {
+			if BIG::comp(&d,&e)>0 {
+				w.copy(&e); w.imul(4); w.norm();
+				if BIG::comp(&d,&w)<=0 {
+					w.copy(&d); d.copy(&e);
+					e.rsub(&w); e.norm();
+
+					t.copy(&cv);
+					t.xtr_a(&cu,&cumv,&cum2v);
+					cum2v.copy(&cumv);
+					cum2v.conj();
+					cumv.copy(&cv);
+					cv.copy(&cu);
+					cu.copy(&t);
+				} else {
+					if d.parity()==0 {
+						d.fshr(1);
+						r.copy(&cum2v); r.conj();
+						t.copy(&cumv);
+						t.xtr_a(&cu,&cv,&r);
+						cum2v.copy(&cumv);
+						cum2v.xtr_d();
+						cumv.copy(&t);
+						cu.xtr_d();
+					} else {
+						if e.parity()==1 {
+							d.sub(&e); d.norm();
+							d.fshr(1);
+							t.copy(&cv);
+							t.xtr_a(&cu,&cumv,&cum2v);
+							cu.xtr_d();
+							cum2v.copy(&cv);
+							cum2v.xtr_d();
+							cum2v.conj();
+							cv.copy(&t);
+						} else {
+							w.copy(&d);
+							d.copy(&e); d.fshr(1);
+							e.copy(&w);
+							t.copy(&cumv);
+							t.xtr_d();
+							cumv.copy(&cum2v); cumv.conj();
+							cum2v.copy(&t); cum2v.conj();
+							t.copy(&cv);
+							t.xtr_d();
+							cv.copy(&cu);
+							cu.copy(&t);
+						}
+					}	
+				}
+			}
+			if BIG::comp(&d,&e)<0 {
+				w.copy(&d); w.imul(4); w.norm();
+				if BIG::comp(&e,&w)<=0 {
+					e.sub(&d); e.norm();
+					t.copy(&cv);
+					t.xtr_a(&cu,&cumv,&cum2v);
+					cum2v.copy(&cumv);
+					cumv.copy(&cu);
+					cu.copy(&t);
+				} else {
+					if e.parity()==0 {
+						w.copy(&d);
+						d.copy(&e); d.fshr(1);
+						e.copy(&w);
+						t.copy(&cumv);
+						t.xtr_d();
+						cumv.copy(&cum2v); cumv.conj();
+						cum2v.copy(&t); cum2v.conj();
+						t.copy(&cv);
+						t.xtr_d();
+						cv.copy(&cu);
+						cu.copy(&t);
+					} else {
+						if d.parity()==1 {
+							w.copy(&e);
+							e.copy(&d);
+							w.sub(&d); w.norm();
+							d.copy(&w); d.fshr(1);
+							t.copy(&cv);
+							t.xtr_a(&cu,&cumv,&cum2v);
+							cumv.conj();
+							cum2v.copy(&cu);
+							cum2v.xtr_d();
+							cum2v.conj();
+							cu.copy(&cv);
+							cu.xtr_d();
+							cv.copy(&t);
+						} else {
+							d.fshr(1);
+							r.copy(&cum2v); r.conj();
+							t.copy(&cumv);
+							t.xtr_a(&cu,&cv,&r);
+							cum2v.copy(&cumv);
+							cum2v.xtr_d();
+							cumv.copy(&t);
+							cu.xtr_d();
+						}
+					}
+				}
+			}
+		}
+		r.copy(&cv);
+		r.xtr_a(&cu,&cumv,&cum2v);
+		for _ in 0..f2 {r.xtr_d()}
+		r=r.xtr_pow(&mut d);
+		return r;
+	}
+
+/* this/=2 */
+	pub fn div2(&mut self) {
+		self.a.div2();
+		self.b.div2();
+	}
+
+	pub fn div_i(&mut self) {
+		let mut u=FP4::new_copy(&self.a);
+		let v=FP4::new_copy(&self.b);
+		u.div_i();
+		self.a.copy(&v);
+		self.b.copy(&u);
+	}	
+
+	pub fn div_i2(&mut self) {
+		self.a.div_i();
+		self.b.div_i();
+	}
+
+	pub fn div_2i(&mut self) {
+		let mut u=FP4::new_copy(&self.a);
+		let mut v=FP4::new_copy(&self.b);
+		u.div_2i();
+		v.dbl(); v.norm();
+		self.a.copy(&v);
+		self.b.copy(&u);
+	}
+
+/* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */
+/* returns true if this is QR */
+	pub fn sqrt(&mut self) -> bool {
+		if self.iszilch() {return true;}
+
+		let mut a=FP4::new_copy(&self.a);
+		let mut s=FP4::new_copy(&self.b);
+		let mut t=FP4::new_copy(&self.a);
+
+		if s.iszilch() {
+			if t.sqrt() {
+				self.a.copy(&t);
+				self.b.zero();
+			} else {
+				t.div_i();
+				t.sqrt();
+				self.b.copy(&t);
+				self.a.zero();
+			}
+			return true;
+		}
+		s.sqr();
+		a.sqr();
+		s.times_i();
+		s.norm();
+		a.sub(&s);   
+
+		s.copy(&a);
+		if !s.sqrt() {
+			return false;
+		}
+
+		a.copy(&t); a.add(&s); a.norm(); a.div2();
+
+		if !a.sqrt() {
+			a.copy(&t); a.sub(&s); a.norm(); a.div2();
+			if !a.sqrt() {
+				return false
+			}
+		}
+		t.copy(&self.b);
+		s.copy(&a); s.add(&a);
+		s.inverse();
+
+		t.mul(&s);
+		self.a.copy(&a);
+		self.b.copy(&t);
+
+		return true;
+	}
+
+}
diff --git a/version3/rust/gcm.rs b/version3/rust/gcm.rs
new file mode 100644
index 0000000..32e2749
--- /dev/null
+++ b/version3/rust/gcm.rs
@@ -0,0 +1,356 @@
+/*
+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.
+*/
+
+const GCM_NB:usize=4;
+const GCM_ACCEPTING_HEADER:usize=0;
+const GCM_ACCEPTING_CIPHER:usize=1;
+const GCM_NOT_ACCEPTING_MORE:usize=2;
+const GCM_FINISHED:usize=3;
+const GCM_ENCRYPTING:usize=0;
+const GCM_DECRYPTING:usize=1;
+
+use aes;
+use aes::AES;
+
+pub struct GCM {
+	table: [[u32;4];128],
+	statex: [u8;16],
+	y_0: [u8;16],
+//	counter: usize,
+	lena:[u32;2],
+	lenc:[u32;2],
+	status:usize,
+	a:AES
+}
+
+impl GCM {
+
+	fn pack(b: [u8;4]) -> u32 { /* pack bytes into a 32-bit Word */
+        return ((((b[0])&0xff) as u32)<<24)|((((b[1])&0xff) as u32)<<16)|((((b[2])&0xff) as u32)<<8)|(((b[3])&0xff) as u32);
+	}
+  
+	fn unpack(a: u32) -> [u8;4] { /* unpack bytes from a word */
+        let b:[u8;4]=[((a>>24)&0xff) as u8,((a>>16)&0xff) as u8,((a>>8)&0xff) as u8,(a&0xff) as u8];
+		return b;
+	}
+
+	fn precompute(&mut self,h: &[u8]) {
+		let mut b:[u8;4]=[0;4];
+        let mut j=0;
+        for i in 0..GCM_NB {
+            b[0]=h[j]; b[1]=h[j+1]; b[2]=h[j+2]; b[3]=h[j+3];
+            self.table[0][i]=GCM::pack(b);
+            j+=4;
+        }
+        for i in 1..128 {
+	    	let mut c:u32=0;
+            for j in 0..GCM_NB {self.table[i][j]=c|(self.table[i-1][j])>>1; c=self.table[i-1][j]<<31;}
+            if c != 0  {self.table[i][0]^=0xE1000000} /* irreducible polynomial */
+        }          
+	}
+
+	fn gf2mul(&mut self) { /* gf2m mul - Z=H*X mod 2^128 */
+        let mut p:[u32;4]=[0;4]; 
+    
+        for i in 0..4 {p[i]=0}
+        let mut j:usize=8; 
+        let mut m=0;
+        for i in 0..128 {
+	    	j-=1;
+            let mut c=((self.statex[m]>>j)&1) as u32; c= (!c) +1;
+	    	for k in 0..GCM_NB {p[k]^=self.table[i][k]&c}
+            if j==0 {
+				j=8; m+=1;
+                if m==16 {break}
+            }
+        }
+        j=0;
+        for i in 0..GCM_NB {
+            let b=GCM::unpack(p[i]);
+            self.statex[j]=b[0]; self.statex[j+1]=b[1]; self.statex[j+2]=b[2]; self.statex[j+3]=b[3];
+            j+=4;
+        }
+	}
+
+	fn wrap(&mut self) { /* Finish off GHASH */
+        let mut f:[u32;4]=[0;4]; 
+        let mut el:[u8;16]=[0;16];  
+   
+    /* convert lengths from bytes to bits */
+        f[0]=(self.lena[0]<<3)|(self.lena[1]&0xE0000000)>>29;
+        f[1]=self.lena[1]<<3;
+        f[2]=(self.lenc[0]<<3)|(self.lenc[1]&0xE0000000)>>29;
+        f[3]=self.lenc[1]<<3;
+        let mut j=0;
+        for i in 0..GCM_NB {
+            let b=GCM::unpack(f[i]);
+            el[j]=b[0]; el[j+1]=b[1]; el[j+2]=b[2]; el[j+3]=b[3];
+            j+=4;
+        }
+        for i in 0..16 {self.statex[i]^=el[i]}
+        self.gf2mul();
+	}
+
+	fn ghash(&mut self,plain: &[u8],len: usize) -> bool {
+        if self.status==GCM_ACCEPTING_HEADER {self.status=GCM_ACCEPTING_CIPHER}
+        if self.status != GCM_ACCEPTING_CIPHER {return false}
+        
+        let mut j=0;
+        while j<len {
+            for i in 0..16 {
+            	if j>=len {break}
+				self.statex[i]^=plain[j]; j+=1;
+                self.lenc[1]+=1; if self.lenc[1]==0 {self.lenc[0]+=1}
+            }
+            self.gf2mul();
+        }
+        if len%16 != 0 {self.status=GCM_NOT_ACCEPTING_MORE}
+        return true;
+    }
+
+    /* Initialize GCM mode */
+	pub fn init(&mut self,nk: usize,key: &[u8],niv: usize,iv: &[u8]) { /* iv size niv is usually 12 bytes (96 bits). AES key size nk can be 16,24 or 32 bytes */
+		let mut h:[u8;16]=[0;16];
+    
+        for i in 0..16 {h[i]=0; self.statex[i]=0}
+        
+		self.a=AES::new();
+
+        self.a.init(aes::ECB,nk,key,None);
+        self.a.ecb_encrypt(&mut h);    /* E(K,0) */
+        self.precompute(&h);
+        
+        self.lena[0]=0;self.lenc[0]=0;self.lena[1]=0;self.lenc[1]=0;
+        if niv==12 {
+            for i in 0..12 {self.a.f[i]=iv[i]}
+            let b=GCM::unpack(1);
+            self.a.f[12]=b[0]; self.a.f[13]=b[1]; self.a.f[14]=b[2]; self.a.f[15]=b[3];  /* initialise IV */
+            for i in 0..16 {self.y_0[i]=self.a.f[i]}
+        } else {
+            self.status=GCM_ACCEPTING_CIPHER;
+            self.ghash(iv,niv); /* GHASH(H,0,IV) */
+            self.wrap();
+            for i in 0..16 {self.a.f[i]=self.statex[i];self.y_0[i]=self.a.f[i];self.statex[i]=0}
+            self.lena[0]=0;self.lenc[0]=0;self.lena[1]=0;self.lenc[1]=0;
+        }
+        self.status=GCM_ACCEPTING_HEADER;
+	}
+
+	pub fn new() -> GCM {
+		GCM {
+			table:[[0;4];128],
+			statex:[0;16],
+			y_0:[0;16],
+			//counter:0,
+			lena:[0;2],
+			lenc:[0;2],
+			status:0,
+			a:AES::new()
+		}
+	}
+
+/* Add Header data - included but not encrypted */
+	pub fn add_header(&mut self,header: &[u8],len: usize) -> bool { /* Add some header. Won't be encrypted, but will be authenticated. len is length of header */
+        if self.status != GCM_ACCEPTING_HEADER {return false}
+        let mut j=0;
+        while j<len {
+            for i in 0..16 {
+            	if j>=len {break}
+				self.statex[i]^=header[j]; j+=1;
+                self.lena[1]+=1; if self.lena[1]==0 {self.lena[0]+=1}
+            }
+            self.gf2mul();
+        }
+        if len%16 != 0 {self.status=GCM_ACCEPTING_CIPHER}
+        return true;
+    }
+
+/* Add Plaintext - included and encrypted */
+	pub fn add_plain(&mut self,cipher: &mut [u8],plain: &[u8],len: usize) -> bool {
+		let mut cb:[u8;16]=[0;16]; 
+		let mut b:[u8;4]=[0;4];
+       
+        let mut counter: u32;
+        if self.status == GCM_ACCEPTING_HEADER {self.status=GCM_ACCEPTING_CIPHER}
+        if self.status != GCM_ACCEPTING_CIPHER {return false}
+        
+        let mut j=0;
+        while j<len {
+            b[0]=self.a.f[12]; b[1]=self.a.f[13]; b[2]=self.a.f[14]; b[3]=self.a.f[15];
+            counter=GCM::pack(b);
+            counter+=1;
+            b=GCM::unpack(counter);
+            self.a.f[12]=b[0]; self.a.f[13]=b[1]; self.a.f[14]=b[2]; self.a.f[15]=b[3]; /* increment counter */
+            for i in 0..16 {cb[i]=self.a.f[i]}
+            self.a.ecb_encrypt(&mut cb);        /* encrypt it  */
+    
+            for i in 0..16 {
+            	if j>=len {break}
+				cipher[j]=plain[j]^cb[i];
+				self.statex[i]^=cipher[j]; j+=1;
+                self.lenc[1]+=1; if self.lenc[1]==0 {self.lenc[0]+=1}
+            }
+            self.gf2mul()
+        }
+        if len%16 != 0 {self.status=GCM_NOT_ACCEPTING_MORE}
+        return true;
+	}
+
+/* Add Ciphertext - decrypts to plaintext */
+	pub fn add_cipher(&mut self,plain: &mut [u8],cipher: &[u8],len: usize) -> bool {
+		let mut cb:[u8;16]=[0;16]; 
+		let mut b:[u8;4]=[0;4];
+        
+       let mut counter: u32;
+        
+        if self.status==GCM_ACCEPTING_HEADER {self.status=GCM_ACCEPTING_CIPHER}
+        if self.status != GCM_ACCEPTING_CIPHER {return false}
+    
+        let mut j=0;
+        while j<len {
+            b[0]=self.a.f[12]; b[1]=self.a.f[13]; b[2]=self.a.f[14]; b[3]=self.a.f[15];
+            counter=GCM::pack(b);
+            counter+=1;
+            b=GCM::unpack(counter);
+            self.a.f[12]=b[0]; self.a.f[13]=b[1]; self.a.f[14]=b[2]; self.a.f[15]=b[3]; /* increment counter */
+            for i in 0..16 {cb[i]=self.a.f[i]}
+            self.a.ecb_encrypt(&mut cb);        /* encrypt it  */
+            for i in 0..16 {
+            	if j>=len {break}
+				let oc=cipher[j];
+				plain[j]=cipher[j]^cb[i];
+				self.statex[i]^=oc; j+=1;
+                self.lenc[1]+=1; if self.lenc[1]==0 {self.lenc[0]+=1}
+            }
+            self.gf2mul()
+        }
+        if len%16 != 0 {self.status=GCM_NOT_ACCEPTING_MORE}
+        return true;
+	}
+
+/* Finish and extract Tag */
+	pub fn finish(&mut self,extract: bool) -> [u8;16]  { /* Finish off GHASH and extract tag (MAC) */
+		let mut tag:[u8;16]=[0;16]; 
+    
+        self.wrap();
+        /* extract tag */
+        if extract {
+            self.a.ecb_encrypt(&mut (self.y_0));        /* E(K,Y0) */
+            for i in 0..16 {self.y_0[i]^=self.statex[i]}
+            for i in 0..16 {tag[i]=self.y_0[i];self.y_0[i]=0;self.statex[i]=0}
+        }
+        self.status=GCM_FINISHED;
+        self.a.end();
+        return tag;
+	}
+
+	pub fn hex2bytes(hex: &[u8],bin: &mut [u8]) {
+		let len=hex.len();
+
+		for i in 0..len/2 {
+			let mut v:u8;
+        	let mut c = hex[2*i];
+        	if c >= b'0' && c <= b'9' {
+            	v = c - b'0';
+        	} else if c >= b'A' && c <= b'F' {
+            	v = c - b'A' + 10;
+        	} else if c >= b'a' && c <= b'f' {
+            	v = c - b'a' + 10;
+        	} else {
+            	v = 0;
+        	}
+        	v <<= 4;
+        	c = hex[2*i + 1];
+        	if c >= b'0' && c <= b'9' {
+            	v += c - b'0';
+        	} else if c >= b'A' && c <= b'F' {
+            	v += c - b'A' + 10;
+        	} else if c >= b'a' && c <= b'f' {
+            	v += c - b'a' + 10;
+        	} else {
+            	v = 0;
+        	}
+        	bin[i] = v;
+    	}
+	}
+
+}
+/*
+fn main()
+{
+	let kt=b"feffe9928665731c6d6a8f9467308308";
+	let mt=b"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39";
+	let ht=b"feedfacedeadbeeffeedfacedeadbeefabaddad2";
+	let nt=b"9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b";
+// Tag should be 619cc5aefffe0bfa462af43c1699d050
+
+	let mut gcm=GCM::new();
+
+	let len=mt.len()/2;
+	let lenh=ht.len()/2;
+	let lenk=kt.len()/2;
+	let leniv=nt.len()/2;
+
+	//let mut t:[u8;16]=[0;16];	// Tag
+	let mut k:[u8;16]=[0;16];   // AES Key
+	let mut h:[u8;64]=[0;64];  	// Header - to be included in Authentication, but not encrypted
+	let mut n:[u8;100]=[0;100];	// IV - Initialisation vector
+	let mut m:[u8;100]=[0;100];	// Plaintext to be encrypted/authenticated
+	let mut c:[u8;100]=[0;100];	// Ciphertext
+	let mut p:[u8;100]=[0;100];	// Recovered Plaintext 
+
+	GCM::hex2bytes(mt,&mut m);
+	GCM::hex2bytes(ht,&mut h);
+	GCM::hex2bytes(kt,&mut k);
+	GCM::hex2bytes(nt,&mut n);
+
+ 	println!("Plaintext=");
+	for i in 0..len {print!("{:02x}",m[i])}
+	println!("");
+
+	gcm.init(lenk,&k,leniv,&n);
+	
+	gcm.add_header(&h,lenh);
+	gcm.add_plain(&mut c,&m,len);
+	let mut t=gcm.finish(true);
+
+ 	println!("Ciphertext=");
+	for i in 0..len {print!("{:02x}",c[i])}
+	println!("");
+  
+ 	println!("Tag=");
+	for i in 0..16 {print!("{:02x}",t[i])}
+	println!("");
+
+	gcm.init(lenk,&k,leniv,&n);
+	
+	gcm.add_header(&h,lenh);
+	gcm.add_cipher(&mut p,&c,len);
+	t=gcm.finish(true);
+
+ 	println!("Plaintext=");
+	for i in 0..len {print!("{:02x}",p[i])}
+	println!("");
+
+	println!("Tag=");
+	for i in 0..16 {print!("{:02x}",t[i])}
+	println!("");
+
+}
+*/
diff --git a/version3/rust/hash256.rs b/version3/rust/hash256.rs
new file mode 100644
index 0000000..2e079e4
--- /dev/null
+++ b/version3/rust/hash256.rs
@@ -0,0 +1,177 @@
+/*
+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.
+*/
+
+const HASH256_H0: u32=0x6A09E667;
+const HASH256_H1: u32=0xBB67AE85;
+const HASH256_H2: u32=0x3C6EF372;
+const HASH256_H3: u32=0xA54FF53A;
+const HASH256_H4: u32=0x510E527F;
+const HASH256_H5: u32=0x9B05688C;
+const HASH256_H6: u32=0x1F83D9AB;
+const HASH256_H7: u32=0x5BE0CD19;
+
+const HASH256_K : [u32;64]=[
+	0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,
+	0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,
+	0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,
+	0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,
+	0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
+	0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070,
+	0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,
+	0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2];
+
+
+pub struct HASH256 {
+	length: [u32;2],
+	h: [u32;8],
+	w: [u32;64]
+}
+
+impl HASH256 {
+	fn s(n: u32,x: u32) -> u32 {
+		return ((x)>>n) | ((x)<<(32-n));
+	}
+	fn r(n: u32,x: u32) -> u32 {
+		return (x)>>n;
+	}
+
+	fn ch(x: u32,y: u32,z: u32) -> u32 {
+		return (x&y)^(!(x)&z);
+	}
+
+	fn maj(x: u32,y: u32,z: u32) -> u32 {
+		return (x&y)^(x&z)^(y&z);
+	}
+	fn sig0(x: u32) -> u32 {
+		return HASH256::s(2,x)^HASH256::s(13,x)^HASH256::s(22,x);
+	}
+
+	fn sig1(x: u32) -> u32 {
+		return HASH256::s(6,x)^HASH256::s(11,x)^HASH256::s(25,x);
+	}
+
+	fn theta0(x: u32) -> u32 {
+		return HASH256::s(7,x)^HASH256::s(18,x)^HASH256::r(3,x);
+	}
+
+	fn theta1(x: u32) -> u32 {
+		return HASH256::s(17,x)^HASH256::s(19,x)^HASH256::r(10,x);
+	}
+
+	fn transform(&mut self) { /* basic transformation step */
+		for j in 16..64 {
+			self.w[j]=HASH256::theta1(self.w[j-2]).wrapping_add(self.w[j-7]).wrapping_add(HASH256::theta0(self.w[j-15])).wrapping_add(self.w[j-16]);
+		}
+		let mut a=self.h[0]; let mut b=self.h[1]; let mut c=self.h[2]; let mut d=self.h[3]; 
+		let mut e=self.h[4]; let mut f=self.h[5]; let mut g=self.h[6]; let mut hh=self.h[7];
+		for j in 0..64 { /* 64 times - mush it up */
+			let t1=hh.wrapping_add(HASH256::sig1(e)).wrapping_add(HASH256::ch(e,f,g)).wrapping_add(HASH256_K[j]).wrapping_add(self.w[j]);
+			let t2=HASH256::sig0(a).wrapping_add(HASH256::maj(a,b,c));
+			hh=g; g=f; f=e;
+			e=d.wrapping_add(t1);
+			d=c;
+			c=b;
+			b=a;
+			a=t1.wrapping_add(t2) ; 
+		}
+		self.h[0]=self.h[0].wrapping_add(a); self.h[1]=self.h[1].wrapping_add(b); self.h[2]=self.h[2].wrapping_add(c); self.h[3]=self.h[3].wrapping_add(d);
+		self.h[4]=self.h[4].wrapping_add(e); self.h[5]=self.h[5].wrapping_add(f); self.h[6]=self.h[6].wrapping_add(g); self.h[7]=self.h[7].wrapping_add(hh);
+
+	} 	
+
+/* Initialise Hash function */
+	pub fn init(&mut self) { /* initialise */
+		for i in 0..64 {self.w[i]=0}
+		self.length[0]=0; self.length[1]=0;
+		self.h[0]=HASH256_H0;
+		self.h[1]=HASH256_H1;
+		self.h[2]=HASH256_H2;
+		self.h[3]=HASH256_H3;
+		self.h[4]=HASH256_H4;
+		self.h[5]=HASH256_H5;
+		self.h[6]=HASH256_H6;
+		self.h[7]=HASH256_H7;
+	}	
+
+	pub fn new() -> HASH256 {
+		let mut nh=HASH256 {
+			length: [0;2],
+			h: [0;8],
+			w: [0;64]
+		};
+		nh.init();
+		return nh;
+	}
+
+/* process a single byte */
+	pub fn process(&mut self,byt: u8) { /* process the next message byte */
+		let cnt=((self.length[0]/32)%16) as usize;
+		self.w[cnt]<<=8;
+		self.w[cnt]|=(byt&0xFF) as u32;
+		self.length[0]+=8;
+		if self.length[0]==0 {self.length[1]+=1; self.length[0]=0}
+		if (self.length[0]%512)==0 {self.transform()}
+	}
+
+/* process an array of bytes */	
+	pub fn process_array(&mut self,b: &[u8]) {
+		for i in 0..b.len() {self.process(b[i])}
+	}
+
+/* process a 32-bit integer */
+	pub fn process_num(&mut self,n: i32) {
+		self.process(((n>>24)&0xff) as u8);
+		self.process(((n>>16)&0xff) as u8);
+		self.process(((n>>8)&0xff) as u8);
+		self.process((n&0xff) as u8);
+	}
+
+/* Generate 32-byte Hash */
+	pub fn hash(&mut self) -> [u8;32] { /* pad message and finish - supply digest */
+		let mut digest:[u8;32]=[0;32];
+		let len0=self.length[0];
+		let len1=self.length[1];
+		self.process(0x80);
+		while (self.length[0]%512)!=448 {self.process(0)}
+		self.w[14]=len1;
+		self.w[15]=len0;    
+		self.transform();
+		for i in 0..32 { /* convert to bytes */
+			digest[i]=((self.h[i/4]>>(8*(3-i%4))) & 0xff) as u8;
+		}
+		self.init();
+		return digest;
+	}
+}
+
+//248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1
+/*
+fn main() {
+	let s = String::from("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");	
+	let test = s.into_bytes();
+	let mut sh=HASH256::new();
+
+	for i in 0..test.len(){
+		sh.process(test[i]);
+	}
+		
+	let digest=sh.hash();    
+	for i in 0..32 {print!("{:02x}",digest[i])}
+}
+*/
diff --git a/version3/rust/hash384.rs b/version3/rust/hash384.rs
new file mode 100644
index 0000000..7130927
--- /dev/null
+++ b/version3/rust/hash384.rs
@@ -0,0 +1,189 @@
+/*
+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.
+*/
+
+const HASH384_H0: u64=0xcbbb9d5dc1059ed8;
+const HASH384_H1: u64=0x629a292a367cd507;
+const HASH384_H2: u64=0x9159015a3070dd17;
+const HASH384_H3: u64=0x152fecd8f70e5939;
+const HASH384_H4: u64=0x67332667ffc00b31;
+const HASH384_H5: u64=0x8eb44a8768581511;
+const HASH384_H6: u64=0xdb0c2e0d64f98fa7;
+const HASH384_H7: u64=0x47b5481dbefa4fa4;
+
+const HASH384_K : [u64;80]=[
+	0x428a2f98d728ae22,0x7137449123ef65cd,0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc,
+	0x3956c25bf348b538,0x59f111f1b605d019,0x923f82a4af194f9b,0xab1c5ed5da6d8118,
+	0xd807aa98a3030242,0x12835b0145706fbe,0x243185be4ee4b28c,0x550c7dc3d5ffb4e2,
+	0x72be5d74f27b896f,0x80deb1fe3b1696b1,0x9bdc06a725c71235,0xc19bf174cf692694,
+	0xe49b69c19ef14ad2,0xefbe4786384f25e3,0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65,
+	0x2de92c6f592b0275,0x4a7484aa6ea6e483,0x5cb0a9dcbd41fbd4,0x76f988da831153b5,
+	0x983e5152ee66dfab,0xa831c66d2db43210,0xb00327c898fb213f,0xbf597fc7beef0ee4,
+	0xc6e00bf33da88fc2,0xd5a79147930aa725,0x06ca6351e003826f,0x142929670a0e6e70,
+	0x27b70a8546d22ffc,0x2e1b21385c26c926,0x4d2c6dfc5ac42aed,0x53380d139d95b3df,
+	0x650a73548baf63de,0x766a0abb3c77b2a8,0x81c2c92e47edaee6,0x92722c851482353b,
+	0xa2bfe8a14cf10364,0xa81a664bbc423001,0xc24b8b70d0f89791,0xc76c51a30654be30,
+	0xd192e819d6ef5218,0xd69906245565a910,0xf40e35855771202a,0x106aa07032bbd1b8,
+	0x19a4c116b8d2d0c8,0x1e376c085141ab53,0x2748774cdf8eeb99,0x34b0bcb5e19b48a8,
+	0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb,0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3,
+	0x748f82ee5defb2fc,0x78a5636f43172f60,0x84c87814a1f0ab72,0x8cc702081a6439ec,
+	0x90befffa23631e28,0xa4506cebde82bde9,0xbef9a3f7b2c67915,0xc67178f2e372532b,
+	0xca273eceea26619c,0xd186b8c721c0c207,0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178,
+	0x06f067aa72176fba,0x0a637dc5a2c898a6,0x113f9804bef90dae,0x1b710b35131c471b,
+	0x28db77f523047d84,0x32caab7b40c72493,0x3c9ebe0a15c9bebc,0x431d67c49c100d4c,
+	0x4cc5d4becb3e42b6,0x597f299cfc657e2a,0x5fcb6fab3ad6faec,0x6c44198c4a475817];
+
+
+pub struct HASH384 {
+	length: [u64;2],
+	h: [u64;8],
+	w: [u64;80]
+}
+
+impl HASH384 {
+	fn s(n: u64,x: u64) -> u64 {
+		return ((x)>>n) | ((x)<<(64-n));
+	}
+	fn r(n: u64,x: u64) -> u64 {
+		return (x)>>n;
+	}
+
+	fn ch(x: u64,y: u64,z: u64) -> u64 {
+		return (x&y)^(!(x)&z);
+	}
+
+	fn maj(x: u64,y: u64,z: u64) -> u64 {
+		return (x&y)^(x&z)^(y&z);
+	}
+
+	fn sig0(x: u64) -> u64 {
+		return HASH384::s(28,x)^HASH384::s(34,x)^HASH384::s(39,x);
+	}
+
+	fn sig1(x: u64) -> u64 {
+		return HASH384::s(14,x)^HASH384::s(18,x)^HASH384::s(41,x);
+	}
+
+	fn theta0(x: u64) -> u64 {
+		return HASH384::s(1,x)^HASH384::s(8,x)^HASH384::r(7,x);
+	}
+
+	fn theta1(x: u64) -> u64 {
+		return HASH384::s(19,x)^HASH384::s(61,x)^HASH384::r(6,x);
+	}
+
+	fn transform(&mut self) { /* basic transformation step */
+		for j in 16..80 {
+			self.w[j]=HASH384::theta1(self.w[j-2]).wrapping_add(self.w[j-7]).wrapping_add(HASH384::theta0(self.w[j-15])).wrapping_add(self.w[j-16]);
+		}
+		let mut a=self.h[0]; let mut b=self.h[1]; let mut c=self.h[2]; let mut d=self.h[3]; 
+		let mut e=self.h[4]; let mut f=self.h[5]; let mut g=self.h[6]; let mut hh=self.h[7];
+		for j in 0..80 { /* 64 times - mush it up */
+			let t1=hh.wrapping_add(HASH384::sig1(e)).wrapping_add(HASH384::ch(e,f,g)).wrapping_add(HASH384_K[j]).wrapping_add(self.w[j]);
+			let t2=HASH384::sig0(a).wrapping_add(HASH384::maj(a,b,c));
+			hh=g; g=f; f=e;
+			e=d.wrapping_add(t1);
+			d=c;
+			c=b;
+			b=a;
+			a=t1.wrapping_add(t2) ; 
+		}
+		self.h[0]=self.h[0].wrapping_add(a); self.h[1]=self.h[1].wrapping_add(b); self.h[2]=self.h[2].wrapping_add(c); self.h[3]=self.h[3].wrapping_add(d);
+		self.h[4]=self.h[4].wrapping_add(e); self.h[5]=self.h[5].wrapping_add(f); self.h[6]=self.h[6].wrapping_add(g); self.h[7]=self.h[7].wrapping_add(hh);
+
+	} 	
+
+/* Initialise Hash function */
+	pub fn init(&mut self) { /* initialise */
+		for i in 0..64 {self.w[i]=0}
+		self.length[0]=0; self.length[1]=0;
+		self.h[0]=HASH384_H0;
+		self.h[1]=HASH384_H1;
+		self.h[2]=HASH384_H2;
+		self.h[3]=HASH384_H3;
+		self.h[4]=HASH384_H4;
+		self.h[5]=HASH384_H5;
+		self.h[6]=HASH384_H6;
+		self.h[7]=HASH384_H7;
+	}	
+
+	pub fn new() -> HASH384 {
+		let mut nh=HASH384 {
+			length: [0;2],
+			h: [0;8],
+			w: [0;80]
+		};
+		nh.init();
+		return nh;
+	}
+
+/* process a single byte */
+	pub fn process(&mut self,byt: u8) { /* process the next message byte */
+		let cnt=((self.length[0]/64)%16) as usize;
+		self.w[cnt]<<=8;
+		self.w[cnt]|=(byt&0xFF) as u64;
+		self.length[0]+=8;
+		if self.length[0]==0 {self.length[1]+=1; self.length[0]=0}
+		if (self.length[0]%1024)==0 {self.transform()}
+	}
+
+/* process an array of bytes */	
+	pub fn process_array(&mut self,b: &[u8]) {
+		for i in 0..b.len() {self.process(b[i])}
+	}
+
+/* process a 32-bit integer */
+	pub fn process_num(&mut self,n: i32) {
+		self.process(((n>>24)&0xff) as u8);
+		self.process(((n>>16)&0xff) as u8);
+		self.process(((n>>8)&0xff) as u8);
+		self.process((n&0xff) as u8);
+	}
+
+/* Generate 32-byte Hash */
+	pub fn hash(&mut self) -> [u8;48] { /* pad message and finish - supply digest */
+		let mut digest:[u8;48]=[0;48];
+		let len0=self.length[0];
+		let len1=self.length[1];
+		self.process(0x80);
+		while (self.length[0]%1024)!=896 {self.process(0)}
+		self.w[14]=len1;
+		self.w[15]=len0;    
+		self.transform();
+		for i in 0..48 { /* convert to bytes */
+			digest[i]=((self.h[i/8]>>(8*(7-i%8))) & 0xff) as u8;
+		}
+		self.init();
+		return digest;
+	}
+}
+
+//09330c33f71147e8 3d192fc782cd1b47 53111b173b3b05d2 2fa08086e3b0f712 fcc7c71a557e2db9 66c3e9fa91746039
+/*
+fn main() {
+	let s = String::from("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu");	
+	let test = s.into_bytes();
+	let mut sh=HASH384::new();
+
+	for i in 0..test.len(){
+		sh.process(test[i]);
+	}
+		
+	let digest=sh.hash();    
+	for i in 0..48 {print!("{:02x}",digest[i])}
+} */
diff --git a/version3/rust/hash512.rs b/version3/rust/hash512.rs
new file mode 100644
index 0000000..73a4d34
--- /dev/null
+++ b/version3/rust/hash512.rs
@@ -0,0 +1,190 @@
+/*
+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.
+*/
+
+
+const HASH512_H0: u64=0x6a09e667f3bcc908;
+const HASH512_H1: u64=0xbb67ae8584caa73b;
+const HASH512_H2: u64=0x3c6ef372fe94f82b;
+const HASH512_H3: u64=0xa54ff53a5f1d36f1;
+const HASH512_H4: u64=0x510e527fade682d1;
+const HASH512_H5: u64=0x9b05688c2b3e6c1f;
+const HASH512_H6: u64=0x1f83d9abfb41bd6b;
+const HASH512_H7: u64=0x5be0cd19137e2179;
+
+const HASH512_K : [u64;80]=[
+	0x428a2f98d728ae22,0x7137449123ef65cd,0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc,
+	0x3956c25bf348b538,0x59f111f1b605d019,0x923f82a4af194f9b,0xab1c5ed5da6d8118,
+	0xd807aa98a3030242,0x12835b0145706fbe,0x243185be4ee4b28c,0x550c7dc3d5ffb4e2,
+	0x72be5d74f27b896f,0x80deb1fe3b1696b1,0x9bdc06a725c71235,0xc19bf174cf692694,
+	0xe49b69c19ef14ad2,0xefbe4786384f25e3,0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65,
+	0x2de92c6f592b0275,0x4a7484aa6ea6e483,0x5cb0a9dcbd41fbd4,0x76f988da831153b5,
+	0x983e5152ee66dfab,0xa831c66d2db43210,0xb00327c898fb213f,0xbf597fc7beef0ee4,
+	0xc6e00bf33da88fc2,0xd5a79147930aa725,0x06ca6351e003826f,0x142929670a0e6e70,
+	0x27b70a8546d22ffc,0x2e1b21385c26c926,0x4d2c6dfc5ac42aed,0x53380d139d95b3df,
+	0x650a73548baf63de,0x766a0abb3c77b2a8,0x81c2c92e47edaee6,0x92722c851482353b,
+	0xa2bfe8a14cf10364,0xa81a664bbc423001,0xc24b8b70d0f89791,0xc76c51a30654be30,
+	0xd192e819d6ef5218,0xd69906245565a910,0xf40e35855771202a,0x106aa07032bbd1b8,
+	0x19a4c116b8d2d0c8,0x1e376c085141ab53,0x2748774cdf8eeb99,0x34b0bcb5e19b48a8,
+	0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb,0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3,
+	0x748f82ee5defb2fc,0x78a5636f43172f60,0x84c87814a1f0ab72,0x8cc702081a6439ec,
+	0x90befffa23631e28,0xa4506cebde82bde9,0xbef9a3f7b2c67915,0xc67178f2e372532b,
+	0xca273eceea26619c,0xd186b8c721c0c207,0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178,
+	0x06f067aa72176fba,0x0a637dc5a2c898a6,0x113f9804bef90dae,0x1b710b35131c471b,
+	0x28db77f523047d84,0x32caab7b40c72493,0x3c9ebe0a15c9bebc,0x431d67c49c100d4c,
+	0x4cc5d4becb3e42b6,0x597f299cfc657e2a,0x5fcb6fab3ad6faec,0x6c44198c4a475817];
+
+
+pub struct HASH512 {
+	length: [u64;2],
+	h: [u64;8],
+	w: [u64;80]
+}
+
+impl HASH512 {
+	fn s(n: u64,x: u64) -> u64 {
+		return ((x)>>n) | ((x)<<(64-n));
+	}
+	fn r(n: u64,x: u64) -> u64 {
+		return (x)>>n;
+	}
+
+	fn ch(x: u64,y: u64,z: u64) -> u64 {
+		return (x&y)^(!(x)&z);
+	}
+
+	fn maj(x: u64,y: u64,z: u64) -> u64 {
+		return (x&y)^(x&z)^(y&z);
+	}
+
+	fn sig0(x: u64) -> u64 {
+		return HASH512::s(28,x)^HASH512::s(34,x)^HASH512::s(39,x);
+	}
+
+	fn sig1(x: u64) -> u64 {
+		return HASH512::s(14,x)^HASH512::s(18,x)^HASH512::s(41,x);
+	}
+
+	fn theta0(x: u64) -> u64 {
+		return HASH512::s(1,x)^HASH512::s(8,x)^HASH512::r(7,x);
+	}
+
+	fn theta1(x: u64) -> u64 {
+		return HASH512::s(19,x)^HASH512::s(61,x)^HASH512::r(6,x);
+	}
+
+	fn transform(&mut self) { /* basic transformation step */
+		for j in 16..80 {
+			self.w[j]=HASH512::theta1(self.w[j-2]).wrapping_add(self.w[j-7]).wrapping_add(HASH512::theta0(self.w[j-15])).wrapping_add(self.w[j-16]);
+		}
+		let mut a=self.h[0]; let mut b=self.h[1]; let mut c=self.h[2]; let mut d=self.h[3]; 
+		let mut e=self.h[4]; let mut f=self.h[5]; let mut g=self.h[6]; let mut hh=self.h[7];
+		for j in 0..80 { /* 64 times - mush it up */
+			let t1=hh.wrapping_add(HASH512::sig1(e)).wrapping_add(HASH512::ch(e,f,g)).wrapping_add(HASH512_K[j]).wrapping_add(self.w[j]);
+			let t2=HASH512::sig0(a).wrapping_add(HASH512::maj(a,b,c));
+			hh=g; g=f; f=e;
+			e=d.wrapping_add(t1);
+			d=c;
+			c=b;
+			b=a;
+			a=t1.wrapping_add(t2) ; 
+		}
+		self.h[0]=self.h[0].wrapping_add(a); self.h[1]=self.h[1].wrapping_add(b); self.h[2]=self.h[2].wrapping_add(c); self.h[3]=self.h[3].wrapping_add(d);
+		self.h[4]=self.h[4].wrapping_add(e); self.h[5]=self.h[5].wrapping_add(f); self.h[6]=self.h[6].wrapping_add(g); self.h[7]=self.h[7].wrapping_add(hh);
+
+	} 	
+
+/* Initialise Hash function */
+	pub fn init(&mut self) { /* initialise */
+		for i in 0..64 {self.w[i]=0}
+		self.length[0]=0; self.length[1]=0;
+		self.h[0]=HASH512_H0;
+		self.h[1]=HASH512_H1;
+		self.h[2]=HASH512_H2;
+		self.h[3]=HASH512_H3;
+		self.h[4]=HASH512_H4;
+		self.h[5]=HASH512_H5;
+		self.h[6]=HASH512_H6;
+		self.h[7]=HASH512_H7;
+	}	
+
+	pub fn new() -> HASH512 {
+		let mut nh=HASH512 {
+			length: [0;2],
+			h: [0;8],
+			w: [0;80]
+		};
+		nh.init();
+		return nh;
+	}
+
+/* process a single byte */
+	pub fn process(&mut self,byt: u8) { /* process the next message byte */
+		let cnt=((self.length[0]/64)%16) as usize;
+		self.w[cnt]<<=8;
+		self.w[cnt]|=(byt&0xFF) as u64;
+		self.length[0]+=8;
+		if self.length[0]==0 {self.length[1]+=1; self.length[0]=0}
+		if (self.length[0]%1024)==0 {self.transform()}
+	}
+
+/* process an array of bytes */	
+	pub fn process_array(&mut self,b: &[u8]) {
+		for i in 0..b.len() {self.process(b[i])}
+	}
+
+/* process a 32-bit integer */
+	pub fn process_num(&mut self,n: i32) {
+		self.process(((n>>24)&0xff) as u8);
+		self.process(((n>>16)&0xff) as u8);
+		self.process(((n>>8)&0xff) as u8);
+		self.process((n&0xff) as u8);
+	}
+
+/* Generate 32-byte Hash */
+	pub fn hash(&mut self) -> [u8;64] { /* pad message and finish - supply digest */
+		let mut digest:[u8;64]=[0;64];
+		let len0=self.length[0];
+		let len1=self.length[1];
+		self.process(0x80);
+		while (self.length[0]%1024)!=896 {self.process(0)}
+		self.w[14]=len1;
+		self.w[15]=len0;    
+		self.transform();
+		for i in 0..64 { /* convert to bytes */
+			digest[i]=((self.h[i/8]>>(8*(7-i%8))) & 0xff) as u8;
+		}
+		self.init();
+		return digest;
+	}
+}
+
+//8e959b75dae313da 8cf4f72814fc143f 8f7779c6eb9f7fa1 7299aeadb6889018 501d289e4900f7e4 331b99dec4b5433a c7d329eeb6dd2654 5e96e55b874be909
+/*
+fn main() {
+	let s = String::from("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu");	
+	let test = s.into_bytes();
+	let mut sh=HASH512::new();
+
+	for i in 0..test.len(){
+		sh.process(test[i]);
+	}
+		
+	let digest=sh.hash();    
+	for i in 0..64 {print!("{:02x}",digest[i])}
+} */
diff --git a/version3/rust/lib.rs b/version3/rust/lib.rs
new file mode 100644
index 0000000..52fdd45
--- /dev/null
+++ b/version3/rust/lib.rs
@@ -0,0 +1,10 @@
+pub mod arch;
+pub mod aes;
+pub mod gcm;
+pub mod hash256;
+pub mod hash384;
+pub mod hash512;
+pub mod rand;
+pub mod sha3;
+pub mod nhs;
+
diff --git a/version3/rust/mod.rs b/version3/rust/mod.rs
new file mode 100644
index 0000000..03e2d27
--- /dev/null
+++ b/version3/rust/mod.rs
@@ -0,0 +1,11 @@
+pub mod big;
+pub mod dbig;
+pub mod fp;
+pub mod ecp;
+pub mod ecp2;
+pub mod fp2;
+pub mod fp4;
+pub mod fp12;
+pub mod pair;
+pub mod mpin;
+pub mod rom;
diff --git a/version3/rust/modecc.rs b/version3/rust/modecc.rs
new file mode 100644
index 0000000..4ea045c
--- /dev/null
+++ b/version3/rust/modecc.rs
@@ -0,0 +1,8 @@
+pub mod big;
+pub mod dbig;
+pub mod fp;
+pub mod ecp;
+pub mod ecdh;
+pub mod rom;
+
+
diff --git a/version3/rust/modpf.rs b/version3/rust/modpf.rs
new file mode 100644
index 0000000..03e2d27
--- /dev/null
+++ b/version3/rust/modpf.rs
@@ -0,0 +1,11 @@
+pub mod big;
+pub mod dbig;
+pub mod fp;
+pub mod ecp;
+pub mod ecp2;
+pub mod fp2;
+pub mod fp4;
+pub mod fp12;
+pub mod pair;
+pub mod mpin;
+pub mod rom;
diff --git a/version3/rust/modpf192.rs b/version3/rust/modpf192.rs
new file mode 100644
index 0000000..1809b4f
--- /dev/null
+++ b/version3/rust/modpf192.rs
@@ -0,0 +1,12 @@
+pub mod big;
+pub mod dbig;
+pub mod fp;
+pub mod ecp;
+pub mod ecp4;
+pub mod fp2;
+pub mod fp4;
+pub mod fp8;
+pub mod fp24;
+pub mod pair192;
+pub mod mpin192;
+pub mod rom;
diff --git a/version3/rust/modpf256.rs b/version3/rust/modpf256.rs
new file mode 100644
index 0000000..4cd7312
--- /dev/null
+++ b/version3/rust/modpf256.rs
@@ -0,0 +1,13 @@
+pub mod big;
+pub mod dbig;
+pub mod fp;
+pub mod ecp;
+pub mod ecp8;
+pub mod fp2;
+pub mod fp4;
+pub mod fp8;
+pub mod fp16;
+pub mod fp48;
+pub mod pair256;
+pub mod mpin256;
+pub mod rom;
diff --git a/version3/rust/modrsa.rs b/version3/rust/modrsa.rs
new file mode 100644
index 0000000..833d1ea
--- /dev/null
+++ b/version3/rust/modrsa.rs
@@ -0,0 +1,6 @@
+pub mod big;
+pub mod dbig;
+pub mod ff;
+pub mod rsa;
+
+
diff --git a/version3/rust/mpin.rs b/version3/rust/mpin.rs
new file mode 100644
index 0000000..04b903c
--- /dev/null
+++ b/version3/rust/mpin.rs
@@ -0,0 +1,800 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use std::time::{SystemTime};
+use std::time::UNIX_EPOCH;
+
+use xxx::ecp;
+use xxx::ecp::ECP;
+use xxx::ecp2::ECP2;
+use xxx::fp4::FP4;
+use xxx::fp12::FP12;
+use xxx::big::BIG;
+use xxx::pair;
+use xxx::big;
+use xxx::rom;
+
+use rand::RAND;
+use hash256::HASH256;
+use hash384::HASH384;
+use hash512::HASH512;
+
+
+/* MPIN API Functions */
+
+/* Configure mode of operation */
+
+pub const EFS: usize=big::MODBYTES as usize;
+pub const EGS: usize=big::MODBYTES as usize;
+//pub const PAS: usize=16;
+pub const BAD_PARAMS: isize=-11;
+pub const INVALID_POINT: isize=-14;
+pub const WRONG_ORDER: isize=-18;
+pub const BAD_PIN: isize=-19;
+pub const SHA256: usize=32;
+pub const SHA384: usize=48;
+pub const SHA512: usize=64;
+
+/* Configure your PIN here */
+
+pub const MAXPIN: i32=10000;  /* PIN less than this */
+pub const PBLEN: i32=14;      /* Number of bits in PIN */
+pub const TS: usize=10;         /* 10 for 4 digit PIN, 14 for 6-digit PIN - 2^TS/TS approx = sqrt(MAXPIN) */
+pub const TRAP:usize=200;      /* 200 for 4 digit PIN, 2000 for 6-digit PIN  - approx 2*sqrt(MAXPIN) */
+
+//pub const HASH_TYPE: usize=SHA256;
+
+#[allow(non_snake_case)]
+fn hash(sha: usize,c: &mut FP4,U: &mut ECP,r: &mut [u8]) -> bool {
+	let mut w:[u8;EFS]=[0;EFS];
+	let mut t:[u8;6*EFS]=[0;6*EFS];
+
+	c.geta().geta().tobytes(&mut w); for i in 0..EFS {t[i]=w[i]}
+	c.geta().getb().tobytes(&mut w); for i in EFS..2*EFS {t[i]=w[i-EFS]}
+	c.getb().geta().tobytes(&mut w); for i in 2*EFS..3*EFS {t[i]=w[i-2*EFS]}
+	c.getb().getb().tobytes(&mut w); for i in 3*EFS..4*EFS {t[i]=w[i-3*EFS]}
+
+	U.getx().tobytes(&mut w); for i in 4*EFS..5*EFS {t[i]=w[i-4*EFS]}
+	U.gety().tobytes(&mut w); for i in 5*EFS..6*EFS {t[i]=w[i-5*EFS]}
+
+	if sha==SHA256 {
+		let mut h=HASH256::new();
+		h.process_array(&t);
+		let sh=h.hash();
+		for i in 0..ecp::AESKEY {r[i]=sh[i]}	
+		return true;	
+	}
+	if sha==SHA384 {
+		let mut h=HASH384::new();
+		h.process_array(&t);
+		let sh=h.hash();
+		for i in 0..ecp::AESKEY {r[i]=sh[i]}		
+		return true;
+	}
+	if sha==SHA512 {
+		let mut h=HASH512::new();
+		h.process_array(&t);
+		let sh=h.hash();
+		for i in 0..ecp::AESKEY {r[i]=sh[i]}
+		return true;		
+	}
+	return false;
+
+}
+
+/* Hash number (optional) and string to point on curve */
+
+fn hashit(sha: usize,n: usize,id: &[u8],w: &mut [u8]) -> bool {
+	let mut r:[u8;64]=[0;64];
+	let mut didit=false;
+	if sha==SHA256 {
+		let mut h=HASH256::new();
+		if n>0 {h.process_num(n as i32)}
+		h.process_array(id);
+        let hs=h.hash();	
+        for i in 0..sha {r[i]=hs[i];}	
+        didit=true;
+	}
+	if sha==SHA384 {
+		let mut h=HASH384::new();
+		if n>0 {h.process_num(n as i32)}
+		h.process_array(id);
+		let hs=h.hash();
+        for i in 0..sha {r[i]=hs[i];}			
+		didit=true;
+	}
+	if sha==SHA512 {
+		let mut h=HASH512::new();
+		if n>0 {h.process_num(n as i32)}
+		h.process_array(id);
+		let hs=h.hash();
+        for i in 0..sha {r[i]=hs[i];}	
+        didit=true;		
+	}
+	if !didit {return false}
+
+	let rm=big::MODBYTES as usize;
+
+	if sha>rm {
+		for i in 0..rm {w[i]=r[i]}
+	} else {
+		for i in 0..sha {w[i+rm-sha]=r[i]}
+		for i in 0..(rm-sha) {w[i]=0}
+
+
+		//for i in 0..sha {w[i]=r[i]}	
+		//for i in sha..rm {w[i]=0}
+	}
+
+	return true;
+}
+
+/* return time in slots since epoch */
+pub fn today() -> usize {
+  	return (SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()/(60*1440)) as usize;
+}
+
+/* these next two functions help to implement elligator squared - http://eprint.iacr.org/2014/043 */
+/* maps a random u to a point on the curve */
+#[allow(non_snake_case)]
+fn emap(u: &BIG,cb: isize) -> ECP {
+	let mut P:ECP;
+	let mut x=BIG::new_copy(u);
+	let mut p=BIG::new_ints(&rom::MODULUS);
+	x.rmod(&mut p);
+	loop {
+		P=ECP::new_bigint(&x,cb);
+		if !P.is_infinity() {break}
+		x.inc(1);  x.norm();
+	}
+	return P;
+}
+
+/* returns u derived from P. Random value in range 1 to return value should then be added to u */
+#[allow(non_snake_case)]
+fn unmap(u: &mut BIG,P: &mut ECP) -> isize {
+	let s=P.gets();
+	let mut R:ECP;
+	let mut r=0;
+	let x=P.getx();
+	u.copy(&x);
+	loop {
+		u.dec(1); u.norm();
+		r+=1;
+		R=ECP::new_bigint(u,s);
+		if !R.is_infinity() {break}
+	}
+	return r as isize;
+}
+
+pub fn hash_id(sha: usize,id: &[u8],w: &mut [u8]) -> bool {
+	return hashit(sha,0,id,w);
+}
+
+/* these next two functions implement elligator squared - http://eprint.iacr.org/2014/043 */
+/* Elliptic curve point E in format (0x04,x,y} is converted to form {0x0-,u,v} */
+/* Note that u and v are indistinguisible from random strings */
+#[allow(non_snake_case)]
+pub fn encoding(rng: &mut RAND,e: &mut [u8]) ->isize {
+	let mut t:[u8;EFS]=[0;EFS];
+
+	for i in 0..EFS {t[i]=e[i+1]}
+	let mut u=BIG::frombytes(&t);
+	for i in 0..EFS {t[i]=e[i+EFS+1]}
+	let mut v=BIG::frombytes(&t);
+		
+	let mut P=ECP::new_bigs(&u,&v);
+	if P.is_infinity() {return INVALID_POINT}
+
+	let p=BIG::new_ints(&rom::MODULUS);
+	u=BIG::randomnum(&p,rng);
+
+	let mut su=rng.getbyte() as isize; /*if (su<0) su=-su;*/ su%=2;
+		
+	let mut W=emap(&mut u,su);
+	P.sub(&mut W);
+	let sv=P.gets();
+	let rn=unmap(&mut v,&mut P);
+	let mut m=rng.getbyte() as isize; /*if (m<0) m=-m;*/ m%=rn;
+	v.inc(m+1);
+	e[0]=(su+2*sv) as u8;
+	u.tobytes(&mut t);
+	for i in 0..EFS {e[i+1]=t[i]}
+	v.tobytes(&mut t);
+	for i in 0..EFS {e[i+EFS+1]=t[i]}		
+		
+	return 0;
+}
+
+#[allow(non_snake_case)]
+pub fn decoding(d: &mut [u8]) -> isize {
+	let mut t:[u8;EFS]=[0;EFS];
+
+	if (d[0]&0x04)!=0 {return INVALID_POINT}
+
+	for i in 0..EFS {t[i]=d[i+1]}
+	let mut u=BIG::frombytes(&t);
+	for i in 0..EFS {t[i]=d[i+EFS+1]}
+	let mut v=BIG::frombytes(&t);
+
+	let su=(d[0]&1) as isize;
+	let sv=((d[0]>>1)&1) as isize;
+	let mut W=emap(&mut u,su);
+	let mut P=emap(&mut v,sv);
+	P.add(&mut W);
+	u=P.getx();
+	v=P.gety();
+	d[0]=0x04;
+	u.tobytes(&mut t);
+	for i in 0..EFS {d[i+1]=t[i]}
+	v.tobytes(&mut t);
+	for i in 0..EFS {d[i+EFS+1]=t[i]}		
+		
+	return 0;
+}
+
+/* R=R1+R2 in group G1 */
+#[allow(non_snake_case)]
+pub fn recombine_g1(r1: &[u8],r2: &[u8],r: &mut [u8]) -> isize {
+	let mut P=ECP::frombytes(&r1);
+	let mut Q=ECP::frombytes(&r2);
+
+	if P.is_infinity() || Q.is_infinity() {return INVALID_POINT}
+
+	P.add(&mut Q);
+
+	P.tobytes(r,false);
+	return 0;
+}
+
+/* W=W1+W2 in group G2 */
+#[allow(non_snake_case)]
+pub fn recombine_g2(w1: &[u8],w2: &[u8],w: &mut [u8]) -> isize {
+	let mut P=ECP2::frombytes(&w1);
+	let mut Q=ECP2::frombytes(&w2);
+
+	if P.is_infinity() || Q.is_infinity() {return INVALID_POINT}
+
+	P.add(&mut Q);
+	
+	P.tobytes(w);
+	return 0;
+}
+	
+/* create random secret S */
+pub fn random_generate(rng: &mut RAND,s: &mut [u8]) -> isize {
+	let r=BIG::new_ints(&rom::CURVE_ORDER);
+	let mut sc=BIG::randomnum(&r,rng);
+	//if rom::AES_S>0 {
+	//	sc.mod2m(2*rom::AES_S);
+	//}		
+	sc.tobytes(s);
+	return 0;
+}
+
+/* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */
+#[allow(non_snake_case)]
+pub fn get_server_secret(s: &[u8],sst: &mut [u8]) -> isize {
+
+	let mut Q=ECP2::generator();
+
+	let mut sc=BIG::frombytes(s);
+	Q=pair::g2mul(&mut Q,&mut sc);
+	Q.tobytes(sst);
+	return 0;
+}
+
+/*
+ W=x*H(G);
+ if RNG == NULL then X is passed in 
+ if RNG != NULL the X is passed out 
+ if type=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve
+*/
+#[allow(non_snake_case)]
+pub fn get_g1_multiple(rng: Option<&mut RAND>,typ: usize,x: &mut [u8],g: &[u8],w: &mut [u8]) -> isize {
+	let mut sx:BIG;
+	let r=BIG::new_ints(&rom::CURVE_ORDER);
+
+	if let Some(rd)=rng
+	{
+		sx=BIG::randomnum(&r,rd);
+		//if rom::AES_S>0 {
+		//	sx.mod2m(2*rom::AES_S);
+		//}
+		sx.tobytes(x);
+	} else {
+		sx=BIG::frombytes(x);
+	}
+	let mut P:ECP;
+
+	if typ==0 {
+		P=ECP::frombytes(g);
+		if P.is_infinity() {return INVALID_POINT}
+	} else {
+		P=ECP::mapit(g)
+	}
+
+
+
+	pair::g1mul(&mut P,&mut sx).tobytes(w,false);
+	return 0;
+}
+
+
+/* Client secret CST=S*H(CID) where CID is client ID and S is master secret */
+/* CID is hashed externally */
+pub fn get_client_secret(s: &mut [u8],cid: &[u8],cst: &mut [u8]) -> isize {
+	return get_g1_multiple(None,1,s,cid,cst);
+}
+
+/* Extract PIN from TOKEN for identity CID */
+#[allow(non_snake_case)]
+pub fn extract_pin(sha: usize,cid: &[u8],pin: i32,token: &mut [u8]) -> isize {
+	return extract_factor(sha,cid,pin%MAXPIN,PBLEN,token);
+}
+
+/* Extract factor from TOKEN for identity CID */
+#[allow(non_snake_case)]
+pub fn extract_factor(sha: usize,cid: &[u8],factor: i32,facbits: i32,token: &mut [u8]) -> isize {
+	let mut P=ECP::frombytes(&token);
+	const RM:usize=big::MODBYTES as usize;
+	let mut h:[u8;RM]=[0;RM];
+	if P.is_infinity() {return INVALID_POINT}
+	hashit(sha,0,cid,&mut h);
+	let mut R=ECP::mapit(&h);
+
+	R=R.pinmul(factor,facbits);
+	P.sub(&mut R);
+
+	P.tobytes(token,false);
+
+	return 0;
+}
+
+/* Restore factor to TOKEN for identity CID */
+#[allow(non_snake_case)]
+pub fn restore_factor(sha: usize,cid: &[u8],factor: i32,facbits: i32,token: &mut [u8]) -> isize {
+	let mut P=ECP::frombytes(&token);
+	const RM:usize=big::MODBYTES as usize;
+	let mut h:[u8;RM]=[0;RM];
+	if P.is_infinity() {return INVALID_POINT}
+	hashit(sha,0,cid,&mut h);
+	let mut R=ECP::mapit(&h);
+
+	R=R.pinmul(factor,facbits);
+	P.add(&mut R);
+
+	P.tobytes(token,false);
+
+	return 0;
+}
+
+/* Extract PIN from TOKEN for identity CID 
+#[allow(non_snake_case)]
+pub fn extract_pin(sha: usize,cid: &[u8],pin: i32,token: &mut [u8]) -> isize {
+	let mut P=ECP::frombytes(&token);
+	const RM:usize=big::MODBYTES as usize;
+	let mut h:[u8;RM]=[0;RM];
+	if P.is_infinity() {return INVALID_POINT}
+	hashit(sha,0,cid,&mut h);
+	let mut R=ECP::mapit(&h);
+
+	R=R.pinmul(pin%MAXPIN,PBLEN);
+	P.sub(&mut R);
+
+	P.tobytes(token,false);
+
+	return 0;
+}
+*/
+
+
+/* Functions to support M-Pin Full */
+#[allow(non_snake_case)]
+pub fn precompute(token: &[u8],cid: &[u8],g1: &mut [u8],g2: &mut [u8]) -> isize {
+	let T=ECP::frombytes(&token);
+	if T.is_infinity() {return INVALID_POINT} 
+
+	let P=ECP::mapit(&cid);
+
+	let Q=ECP2::generator();
+
+	let mut g=pair::ate(&Q,&T);
+	g=pair::fexp(&g);
+	g.tobytes(g1);
+
+	g=pair::ate(&Q,&P);
+	g=pair::fexp(&g);
+	g.tobytes(g2);
+
+	return 0;
+}
+
+/* Time Permit CTT=S*(date|H(CID)) where S is master secret */
+#[allow(non_snake_case)]
+pub fn get_client_permit(sha: usize,date: usize,s: &[u8],cid: &[u8],ctt: &mut [u8]) ->isize {
+	const RM:usize=big::MODBYTES as usize;
+	let mut h:[u8;RM]=[0;RM];	
+	hashit(sha,date,cid,&mut h);
+	let mut P=ECP::mapit(&h);
+
+	let mut sc=BIG::frombytes(s);
+	pair::g1mul(&mut P,&mut sc).tobytes(ctt,false);
+	return 0;
+}
+
+/* Implement step 1 on client side of MPin protocol */
+#[allow(non_snake_case)]
+pub fn client_1(sha: usize,date: usize,client_id: &[u8],rng: Option<&mut RAND>,x: &mut [u8],pin: usize,token: &[u8],sec: &mut [u8],xid: Option<&mut [u8]>,xcid: Option<&mut [u8]>,permit: Option<&[u8]>) ->isize {
+	let r=BIG::new_ints(&rom::CURVE_ORDER);
+		
+	let mut sx:BIG;
+
+	if let Some(rd)=rng
+	{
+		sx=BIG::randomnum(&r,rd);
+		//if rom::AES_S>0 {
+		//	sx.mod2m(2*rom::AES_S);
+		//}
+		sx.tobytes(x);
+	} else {
+		sx=BIG::frombytes(x);
+	}
+
+	const RM:usize=big::MODBYTES as usize;
+	let mut h:[u8;RM]=[0;RM];
+
+	hashit(sha,0,&client_id,&mut h);
+	let mut P=ECP::mapit(&h);
+	
+	let mut T=ECP::frombytes(&token);
+	if T.is_infinity() {return INVALID_POINT}
+
+	let mut W=P.pinmul((pin as i32)%MAXPIN,PBLEN);
+	T.add(&mut W);
+	if date!=0 {
+		if let Some(rpermit)=permit {W=ECP::frombytes(&rpermit);}
+		if W.is_infinity() {return INVALID_POINT}
+		T.add(&mut W);
+		let mut h2:[u8;RM]=[0;RM];		
+		hashit(sha,date,&h,&mut h2);
+		W=ECP::mapit(&h2);
+		if let Some(mut rxid)=xid {
+			P=pair::g1mul(&mut P,&mut sx);
+			P.tobytes(&mut rxid,false);
+			W=pair::g1mul(&mut W,&mut sx);
+			P.add(&mut W);
+		} else {
+			P.add(&mut W);
+			P=pair::g1mul(&mut P,&mut sx);
+		}
+		if let Some(mut rxcid)=xcid {P.tobytes(&mut rxcid,false)}
+	} else {
+		if let Some(mut rxid)=xid {
+			P=pair::g1mul(&mut P,&mut sx);
+			P.tobytes(&mut rxid,false);
+		}
+	}
+
+	T.tobytes(sec,false);
+	return 0;
+}
+
+/* Outputs H(CID) and H(T|H(CID)) for time permits. If no time permits set HID=HTID */
+#[allow(non_snake_case)]
+pub fn server_1(sha: usize,date: usize,cid: &[u8],hid: &mut [u8],htid: Option<&mut [u8]>) {
+	const RM:usize=big::MODBYTES as usize;
+	let mut h:[u8;RM]=[0;RM];
+
+	hashit(sha,0,cid,&mut h);	
+
+	let mut P=ECP::mapit(&h);
+	
+	P.tobytes(hid,false);
+	if date!=0 {
+		let mut h2:[u8;RM]=[0;RM];		
+		hashit(sha,date,&h,&mut h2);
+		let mut R=ECP::mapit(&h2);
+		P.add(&mut R);
+		if let Some(rhtid)=htid {P.tobytes(rhtid,false);}
+	} 
+}
+
+/* Implement step 2 on client side of MPin protocol */
+#[allow(non_snake_case)]
+pub fn client_2(x: &[u8],y: &[u8],sec: &mut [u8]) -> isize {
+	let mut r=BIG::new_ints(&rom::CURVE_ORDER);
+	let mut P=ECP::frombytes(sec);
+	if P.is_infinity() {return INVALID_POINT}
+
+	let mut px=BIG::frombytes(x);
+	let py=BIG::frombytes(y);
+	px.add(&py);
+	px.rmod(&mut r);
+	//px.rsub(r)
+
+	P=pair::g1mul(&mut P,&mut px);
+	P.neg();
+	P.tobytes(sec,false);
+	
+	return 0;
+}
+
+/* return time since epoch */
+pub fn get_time() -> usize {
+  	return (SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) as usize;	
+}
+
+/* Generate Y = H(epoch, xCID/xID) */
+pub fn get_y(sha: usize,timevalue: usize,xcid: &[u8],y: &mut [u8]) {
+	const RM:usize=big::MODBYTES as usize;
+	let mut h:[u8;RM]=[0;RM];
+
+	hashit(sha,timevalue,xcid,&mut h);	
+
+	let mut sy= BIG::frombytes(&h);
+	let mut q=BIG::new_ints(&rom::CURVE_ORDER);
+	sy.rmod(&mut q);
+	//if rom::AES_S>0 {
+	//	sy.mod2m(2*rom::AES_S);
+	//}
+	sy.tobytes(y);
+}
+
+/* Implement step 2 of MPin protocol on server side */
+#[allow(non_snake_case)]
+pub fn server_2(date: usize,hid: &[u8],htid: Option<&[u8]>,y: &[u8],sst: &[u8],xid: Option<&[u8]>,xcid: Option<&[u8]>,msec: &[u8],e: Option<&mut [u8]>,f: Option<&mut [u8]>) -> isize {
+//	q:=NewBIGints(Modulus)
+	let Q=ECP2::generator();
+
+	let sQ=ECP2::frombytes(&sst);
+	if sQ.is_infinity() {return INVALID_POINT}	
+
+	let mut R:ECP;
+	if date!=0 {
+		if let Some(rxcid)=xcid {R=ECP::frombytes(&rxcid);}
+		else {return BAD_PARAMS}
+	} else {
+		if let Some(rxid)=xid {R=ECP::frombytes(&rxid)}
+		else {return BAD_PARAMS}
+	}
+	if R.is_infinity() {return INVALID_POINT}
+
+	let mut sy=BIG::frombytes(&y);
+	let mut P:ECP;
+	if date!=0 {
+		if let Some(rhtid)=htid {P=ECP::frombytes(&rhtid)}
+		else {return BAD_PARAMS}
+	} else {
+		P=ECP::frombytes(&hid);
+	}
+	
+	if P.is_infinity() {return INVALID_POINT}
+
+	P=pair::g1mul(&mut P,&mut sy);
+	P.add(&mut R); //P.affine();
+	R=ECP::frombytes(&msec);
+	if R.is_infinity() {return INVALID_POINT}
+
+	let mut g:FP12;
+//		FP12 g1=new FP12(0);
+
+	g=pair::ate2(&Q,&R,&sQ,&P);
+	g=pair::fexp(&g);
+
+	if !g.isunity() {
+		
+		if let Some(rxid)=xid {
+			if let Some(re)=e {
+				if let Some(rf)=f {
+
+					g.tobytes(re);
+					if date!=0 {
+						P=ECP::frombytes(&hid);
+						if P.is_infinity() {return INVALID_POINT}		
+						R=ECP::frombytes(&rxid);
+						if R.is_infinity() {return INVALID_POINT}			
+						P=pair::g1mul(&mut P,&mut sy);
+						P.add(&mut R);	//P.affine();								
+					}
+					g=pair::ate(&Q,&P);
+					g=pair::fexp(&g);
+					g.tobytes(rf);
+
+				}
+			}
+		}
+	
+		return BAD_PIN;
+	}
+
+	return 0;
+}
+
+/* Pollards kangaroos used to return PIN error */
+pub fn kangaroo(e: &[u8],f: &[u8]) -> isize {
+	let mut ge=FP12::frombytes(e);
+	let mut gf=FP12::frombytes(f);
+	let mut distance: [isize;TS]=[0;TS];
+	let mut t=FP12::new_copy(&gf);
+
+	let mut table: [FP12;TS]=[FP12::new();TS];
+	let mut s:isize=1;
+	for m in 0..TS {
+		distance[m]=s;
+		table[m]=FP12::new_copy(&t);
+		s*=2;
+		t.usqr();
+	}
+	t.one();
+	let mut dn:isize=0;
+	let mut i:usize;
+	for _ in 0..TRAP {
+		i=(t.geta().geta().geta().lastbits(20)%(TS as isize)) as usize;
+		t.mul(&mut table[i]);
+		dn+=distance[i];
+	}
+	gf.copy(&t); gf.conj();
+	let mut steps:usize=0; let mut dm:isize=0;
+	let mut res:isize=0;
+	while dm-dn<MAXPIN as isize {
+		steps+=1;
+		if steps>4*TRAP {break}
+		i=(ge.geta().geta().geta().lastbits(20)%(TS as isize)) as usize;
+		ge.mul(&mut table[i]);
+		dm+=distance[i];
+		if ge.equals(&mut t) {
+			res=dm-dn;
+			break;
+		}
+		if ge.equals(&mut gf) {
+			res=dn-dm;
+			break;
+		}
+
+	}
+	if steps>4*TRAP || dm-dn>=MAXPIN as isize {res=0 }    // Trap Failed  - probable invalid token
+	return res;
+}
+
+/* Hash the M-Pin transcript - new */
+
+pub fn hash_all(sha: usize,hid: &[u8],xid: &[u8],xcid: Option<&[u8]>,sec: &[u8],y: &[u8],r: &[u8],w: &[u8],h: &mut[u8]) -> bool {
+	let mut tlen:usize=0;
+	const RM:usize=big::MODBYTES as usize;	
+	let mut t: [u8;10*RM+4]=[0;10*RM+4];
+
+	for i in 0 .. hid.len() {t[i]=hid[i]}
+	tlen+=hid.len();
+
+	if let Some(rxcid)=xcid {
+		for i in 0..rxcid.len() {t[i+tlen]=rxcid[i]}
+		tlen+=rxcid.len();
+	} else {
+		for i in 0..xid.len() {t[i+tlen]=xid[i]}
+		tlen+=xid.len();
+	}	
+
+	for i in 0..sec.len() {t[i+tlen]=sec[i]}
+	tlen+=sec.len();		
+	for i in 0..y.len() {t[i+tlen]=y[i]}
+	tlen+=y.len();
+	for i in 0..r.len() {t[i+tlen]=r[i]}
+	tlen+=r.len();		
+	for i in 0..w.len() {t[i+tlen]=w[i]}
+	tlen+=w.len();	
+	if tlen!=10*RM+4 {return false}
+
+	return hashit(sha,0,&t,h);
+}
+
+/* calculate common key on client side */
+/* wCID = w.(A+AT) */
+#[allow(non_snake_case)]
+pub fn client_key(sha: usize,g1: &[u8],g2: &[u8],pin: usize,r: &[u8],x: &[u8],h: &[u8],wcid: &[u8],ck: &mut [u8]) -> isize {
+
+	let mut g1=FP12::frombytes(&g1);
+	let mut g2=FP12::frombytes(&g2);
+	let mut z=BIG::frombytes(&r);
+	let mut x=BIG::frombytes(&x);
+	let h=BIG::frombytes(&h);
+
+	let mut W=ECP::frombytes(&wcid);
+	if W.is_infinity() {return INVALID_POINT} 
+
+	W=pair::g1mul(&mut W,&mut x);
+
+//	let mut f=FP2::new_bigs(&BIG::new_ints(&rom::FRA),&BIG::new_ints(&rom::FRB));
+	let mut r=BIG::new_ints(&rom::CURVE_ORDER);
+//	let q=BIG::new_ints(&rom::MODULUS);
+
+	z.add(&h);	//new
+	z.rmod(&mut r);
+
+	g2.pinpow(pin as i32,PBLEN);
+	g1.mul(&mut g2);
+
+	let mut c=g1.compow(&z,&mut r);
+
+/*	
+
+	let mut m=BIG::new_copy(&q);
+	m.rmod(&mut r);
+
+	let mut a=BIG::new_copy(&z);
+	a.rmod(&mut m);
+
+	let mut b=BIG::new_copy(&z);
+	b.div(&mut m);
+
+
+	let mut c=g1.trace();
+	g2.copy(&g1);
+	g2.frob(&mut f);
+	let cp=g2.trace();
+	g1.conj();
+	g2.mul(&mut g1);
+	let cpm1=g2.trace();
+	g2.mul(&mut g1);
+	let cpm2=g2.trace();
+
+	c=c.xtr_pow2(&cp,&cpm1,&cpm2,&mut a,&mut b);
+*/
+	hash(sha,&mut c,&mut W,ck);
+
+	return 0
+}
+
+/* calculate common key on server side */
+/* Z=r.A - no time permits involved */
+#[allow(non_snake_case)]
+pub fn server_key(sha: usize,z: &[u8],sst: &[u8],w: &[u8],h: &[u8],hid: &[u8],xid: &[u8],xcid: Option<&[u8]>,sk: &mut [u8]) -> isize {
+	let sQ=ECP2::frombytes(&sst);
+	if sQ.is_infinity() {return INVALID_POINT} 
+	let mut R=ECP::frombytes(&z);
+	if R.is_infinity() {return INVALID_POINT} 
+	let mut A=ECP::frombytes(&hid);
+	if A.is_infinity() {return INVALID_POINT} 
+
+	let mut U=ECP::new();
+	if let Some(rxcid)=xcid {
+		U.copy(&ECP::frombytes(&rxcid));
+	} else {
+		U.copy(&ECP::frombytes(&xid));
+	}
+	
+	if U.is_infinity() {return INVALID_POINT} 
+
+	let mut w=BIG::frombytes(&w);
+	let mut h=BIG::frombytes(&h);
+	A=pair::g1mul(&mut A,&mut h);	// new
+	R.add(&mut A); //R.affine();
+
+	U=pair::g1mul(&mut U,&mut w);
+	let mut g=pair::ate(&sQ,&R);
+	g=pair::fexp(&g);
+
+	let mut c=g.trace();
+
+	hash(sha,&mut c,&mut U,sk);
+
+	return 0
+}
+
+
diff --git a/version3/rust/mpin192.rs b/version3/rust/mpin192.rs
new file mode 100644
index 0000000..d3fa079
--- /dev/null
+++ b/version3/rust/mpin192.rs
@@ -0,0 +1,780 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use std::time::{SystemTime};
+use std::time::UNIX_EPOCH;
+
+use xxx::ecp;
+use xxx::ecp::ECP;
+use xxx::ecp4::ECP4;
+use xxx::fp8::FP8;
+use xxx::fp24::FP24;
+use xxx::big::BIG;
+use xxx::pair192;
+use xxx::big;
+use xxx::rom;
+
+use rand::RAND;
+use hash256::HASH256;
+use hash384::HASH384;
+use hash512::HASH512;
+
+
+/* MPIN API Functions */
+
+/* Configure mode of operation */
+
+pub const EFS: usize=big::MODBYTES as usize;
+pub const EGS: usize=big::MODBYTES as usize;
+//pub const PAS: usize=16;
+pub const BAD_PARAMS: isize=-11;
+pub const INVALID_POINT: isize=-14;
+pub const WRONG_ORDER: isize=-18;
+pub const BAD_PIN: isize=-19;
+pub const SHA256: usize=32;
+pub const SHA384: usize=48;
+pub const SHA512: usize=64;
+
+/* Configure your PIN here */
+
+pub const MAXPIN: i32=10000;  /* PIN less than this */
+pub const PBLEN: i32=14;      /* Number of bits in PIN */
+pub const TS: usize=10;         /* 10 for 4 digit PIN, 14 for 6-digit PIN - 2^TS/TS approx = sqrt(MAXPIN) */
+pub const TRAP:usize=200;      /* 200 for 4 digit PIN, 2000 for 6-digit PIN  - approx 2*sqrt(MAXPIN) */
+
+//pub const HASH_TYPE: usize=SHA256;
+
+#[allow(non_snake_case)]
+fn hash(sha: usize,c: &mut FP8,U: &mut ECP,r: &mut [u8]) -> bool {
+	let mut w:[u8;EFS]=[0;EFS];
+	let mut t:[u8;10*EFS]=[0;10*EFS];
+
+	c.geta().geta().geta().tobytes(&mut w); for i in 0..EFS {t[i]=w[i]}
+	c.geta().geta().getb().tobytes(&mut w); for i in EFS..2*EFS {t[i]=w[i-EFS]}
+	c.geta().getb().geta().tobytes(&mut w); for i in 2*EFS..3*EFS {t[i]=w[i-2*EFS]}
+	c.geta().getb().getb().tobytes(&mut w); for i in 3*EFS..4*EFS {t[i]=w[i-3*EFS]}
+	c.getb().geta().geta().tobytes(&mut w); for i in 4*EFS..5*EFS {t[i]=w[i-4*EFS]}
+	c.getb().geta().getb().tobytes(&mut w); for i in 5*EFS..6*EFS {t[i]=w[i-5*EFS]}
+	c.getb().getb().geta().tobytes(&mut w); for i in 6*EFS..7*EFS {t[i]=w[i-6*EFS]}
+	c.getb().getb().getb().tobytes(&mut w); for i in 7*EFS..8*EFS {t[i]=w[i-7*EFS]}
+
+	U.getx().tobytes(&mut w); for i in 8*EFS..9*EFS {t[i]=w[i-8*EFS]}
+	U.gety().tobytes(&mut w); for i in 9*EFS..10*EFS {t[i]=w[i-9*EFS]}
+
+	if sha==SHA256 {
+		let mut h=HASH256::new();
+		h.process_array(&t);
+		let sh=h.hash();
+		for i in 0..ecp::AESKEY {r[i]=sh[i]}	
+		return true;	
+	}
+	if sha==SHA384 {
+		let mut h=HASH384::new();
+		h.process_array(&t);
+		let sh=h.hash();
+		for i in 0..ecp::AESKEY {r[i]=sh[i]}		
+		return true;
+	}
+	if sha==SHA512 {
+		let mut h=HASH512::new();
+		h.process_array(&t);
+		let sh=h.hash();
+		for i in 0..ecp::AESKEY {r[i]=sh[i]}
+		return true;		
+	}
+	return false;
+
+}
+
+/* Hash number (optional) and string to point on curve */
+
+fn hashit(sha: usize,n: usize,id: &[u8],w: &mut [u8]) -> bool {
+	let mut r:[u8;64]=[0;64];
+	let mut didit=false;
+	if sha==SHA256 {
+		let mut h=HASH256::new();
+		if n>0 {h.process_num(n as i32)}
+		h.process_array(id);
+        let hs=h.hash();	
+        for i in 0..sha {r[i]=hs[i];}	
+        didit=true;
+	}
+	if sha==SHA384 {
+		let mut h=HASH384::new();
+		if n>0 {h.process_num(n as i32)}
+		h.process_array(id);
+		let hs=h.hash();
+        for i in 0..sha {r[i]=hs[i];}			
+		didit=true;
+	}
+	if sha==SHA512 {
+		let mut h=HASH512::new();
+		if n>0 {h.process_num(n as i32)}
+		h.process_array(id);
+		let hs=h.hash();
+        for i in 0..sha {r[i]=hs[i];}	
+        didit=true;		
+	}
+	if !didit {return false}
+
+	let rm=big::MODBYTES as usize;
+
+	if sha>rm {
+		for i in 0..rm {w[i]=r[i]}
+	} else {
+		for i in 0..sha {w[i+rm-sha]=r[i]}
+		for i in 0..(rm-sha) {w[i]=0}
+
+
+		//for i in 0..sha {w[i]=r[i]}	
+		//for i in sha..rm {w[i]=0}
+	}
+
+	return true;
+}
+
+/* return time in slots since epoch */
+pub fn today() -> usize {
+  	return (SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()/(60*1440)) as usize;
+}
+
+/* these next two functions help to implement elligator squared - http://eprint.iacr.org/2014/043 */
+/* maps a random u to a point on the curve */
+#[allow(non_snake_case)]
+fn emap(u: &BIG,cb: isize) -> ECP {
+	let mut P:ECP;
+	let mut x=BIG::new_copy(u);
+	let mut p=BIG::new_ints(&rom::MODULUS);
+	x.rmod(&mut p);
+	loop {
+		P=ECP::new_bigint(&x,cb);
+		if !P.is_infinity() {break}
+		x.inc(1);  x.norm();
+	}
+	return P;
+}
+
+/* returns u derived from P. Random value in range 1 to return value should then be added to u */
+#[allow(non_snake_case)]
+fn unmap(u: &mut BIG,P: &mut ECP) -> isize {
+	let s=P.gets();
+	let mut R:ECP;
+	let mut r=0;
+	let x=P.getx();
+	u.copy(&x);
+	loop {
+		u.dec(1); u.norm();
+		r+=1;
+		R=ECP::new_bigint(u,s);
+		if !R.is_infinity() {break}
+	}
+	return r as isize;
+}
+
+pub fn hash_id(sha: usize,id: &[u8],w: &mut [u8]) -> bool {
+	return hashit(sha,0,id,w);
+}
+
+/* these next two functions implement elligator squared - http://eprint.iacr.org/2014/043 */
+/* Elliptic curve point E in format (0x04,x,y} is converted to form {0x0-,u,v} */
+/* Note that u and v are indistinguisible from random strings */
+#[allow(non_snake_case)]
+pub fn encoding(rng: &mut RAND,e: &mut [u8]) ->isize {
+	let mut t:[u8;EFS]=[0;EFS];
+
+	for i in 0..EFS {t[i]=e[i+1]}
+	let mut u=BIG::frombytes(&t);
+	for i in 0..EFS {t[i]=e[i+EFS+1]}
+	let mut v=BIG::frombytes(&t);
+		
+	let mut P=ECP::new_bigs(&u,&v);
+	if P.is_infinity() {return INVALID_POINT}
+
+	let p=BIG::new_ints(&rom::MODULUS);
+	u=BIG::randomnum(&p,rng);
+
+	let mut su=rng.getbyte() as isize; /*if (su<0) su=-su;*/ su%=2;
+		
+	let mut W=emap(&mut u,su);
+	P.sub(&mut W);
+	let sv=P.gets();
+	let rn=unmap(&mut v,&mut P);
+	let mut m=rng.getbyte() as isize; /*if (m<0) m=-m;*/ m%=rn;
+	v.inc(m+1);
+	e[0]=(su+2*sv) as u8;
+	u.tobytes(&mut t);
+	for i in 0..EFS {e[i+1]=t[i]}
+	v.tobytes(&mut t);
+	for i in 0..EFS {e[i+EFS+1]=t[i]}		
+		
+	return 0;
+}
+
+#[allow(non_snake_case)]
+pub fn decoding(d: &mut [u8]) -> isize {
+	let mut t:[u8;EFS]=[0;EFS];
+
+	if (d[0]&0x04)!=0 {return INVALID_POINT}
+
+	for i in 0..EFS {t[i]=d[i+1]}
+	let mut u=BIG::frombytes(&t);
+	for i in 0..EFS {t[i]=d[i+EFS+1]}
+	let mut v=BIG::frombytes(&t);
+
+	let su=(d[0]&1) as isize;
+	let sv=((d[0]>>1)&1) as isize;
+	let mut W=emap(&mut u,su);
+	let mut P=emap(&mut v,sv);
+	P.add(&mut W);
+	u=P.getx();
+	v=P.gety();
+	d[0]=0x04;
+	u.tobytes(&mut t);
+	for i in 0..EFS {d[i+1]=t[i]}
+	v.tobytes(&mut t);
+	for i in 0..EFS {d[i+EFS+1]=t[i]}		
+		
+	return 0;
+}
+
+/* R=R1+R2 in group G1 */
+#[allow(non_snake_case)]
+pub fn recombine_g1(r1: &[u8],r2: &[u8],r: &mut [u8]) -> isize {
+	let mut P=ECP::frombytes(&r1);
+	let mut Q=ECP::frombytes(&r2);
+
+	if P.is_infinity() || Q.is_infinity() {return INVALID_POINT}
+
+	P.add(&mut Q);
+
+	P.tobytes(r,false);
+	return 0;
+}
+
+/* W=W1+W2 in group G2 */
+#[allow(non_snake_case)]
+pub fn recombine_g2(w1: &[u8],w2: &[u8],w: &mut [u8]) -> isize {
+	let mut P=ECP4::frombytes(&w1);
+	let mut Q=ECP4::frombytes(&w2);
+
+	if P.is_infinity() || Q.is_infinity() {return INVALID_POINT}
+
+	P.add(&mut Q);
+	
+	P.tobytes(w);
+	return 0;
+}
+
+/* create random secret S */
+pub fn random_generate(rng: &mut RAND,s: &mut [u8]) -> isize {
+	let r=BIG::new_ints(&rom::CURVE_ORDER);
+	let mut sc=BIG::randomnum(&r,rng);
+	//if rom::AES_S>0 {
+	//	sc.mod2m(2*rom::AES_S);
+	//}		
+	sc.tobytes(s);
+	return 0;
+}
+
+/* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */
+#[allow(non_snake_case)]
+pub fn get_server_secret(s: &[u8],sst: &mut [u8]) -> isize {
+
+	let mut Q=ECP4::generator();
+
+	let mut sc=BIG::frombytes(s);
+	Q=pair192::g2mul(&mut Q,&mut sc);
+	Q.tobytes(sst);
+	return 0;
+}
+
+/*
+ W=x*H(G);
+ if RNG == NULL then X is passed in 
+ if RNG != NULL the X is passed out 
+ if type=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve
+*/
+#[allow(non_snake_case)]
+pub fn get_g1_multiple(rng: Option<&mut RAND>,typ: usize,x: &mut [u8],g: &[u8],w: &mut [u8]) -> isize {
+	let mut sx:BIG;
+	let r=BIG::new_ints(&rom::CURVE_ORDER);
+
+	if let Some(rd)=rng
+	{
+		sx=BIG::randomnum(&r,rd);
+		//if rom::AES_S>0 {
+		//	sx.mod2m(2*rom::AES_S);
+		//}
+		sx.tobytes(x);
+	} else {
+		sx=BIG::frombytes(x);
+	}
+	let mut P:ECP;
+
+	if typ==0 {
+		P=ECP::frombytes(g);
+		if P.is_infinity() {return INVALID_POINT}
+	} else {
+		P=ECP::mapit(g)
+	}
+
+
+
+	pair192::g1mul(&mut P,&mut sx).tobytes(w,false);
+	return 0;
+}
+
+
+/* Client secret CST=S*H(CID) where CID is client ID and S is master secret */
+/* CID is hashed externally */
+pub fn get_client_secret(s: &mut [u8],cid: &[u8],cst: &mut [u8]) -> isize {
+	return get_g1_multiple(None,1,s,cid,cst);
+}
+
+/* Extract PIN from TOKEN for identity CID */
+#[allow(non_snake_case)]
+pub fn extract_pin(sha: usize,cid: &[u8],pin: i32,token: &mut [u8]) -> isize {
+	return extract_factor(sha,cid,pin%MAXPIN,PBLEN,token);
+}
+
+/* Extract factor from TOKEN for identity CID */
+#[allow(non_snake_case)]
+pub fn extract_factor(sha: usize,cid: &[u8],factor: i32,facbits: i32,token: &mut [u8]) -> isize {
+	let mut P=ECP::frombytes(&token);
+	const RM:usize=big::MODBYTES as usize;
+	let mut h:[u8;RM]=[0;RM];
+	if P.is_infinity() {return INVALID_POINT}
+	hashit(sha,0,cid,&mut h);
+	let mut R=ECP::mapit(&h);
+
+	R=R.pinmul(factor,facbits);
+	P.sub(&mut R);
+
+	P.tobytes(token,false);
+
+	return 0;
+}
+
+/* Restore factor to TOKEN for identity CID */
+#[allow(non_snake_case)]
+pub fn restore_factor(sha: usize,cid: &[u8],factor: i32,facbits: i32,token: &mut [u8]) -> isize {
+	let mut P=ECP::frombytes(&token);
+	const RM:usize=big::MODBYTES as usize;
+	let mut h:[u8;RM]=[0;RM];
+	if P.is_infinity() {return INVALID_POINT}
+	hashit(sha,0,cid,&mut h);
+	let mut R=ECP::mapit(&h);
+
+	R=R.pinmul(factor,facbits);
+	P.add(&mut R);
+
+	P.tobytes(token,false);
+
+	return 0;
+}
+
+/* Extract PIN from TOKEN for identity CID 
+#[allow(non_snake_case)]
+pub fn extract_pin(sha: usize,cid: &[u8],pin: i32,token: &mut [u8]) -> isize {
+	let mut P=ECP::frombytes(&token);
+	const RM:usize=big::MODBYTES as usize;
+	let mut h:[u8;RM]=[0;RM];
+	if P.is_infinity() {return INVALID_POINT}
+	hashit(sha,0,cid,&mut h);
+	let mut R=ECP::mapit(&h);
+
+	R=R.pinmul(pin%MAXPIN,PBLEN);
+	P.sub(&mut R);
+
+	P.tobytes(token,false);
+
+	return 0;
+}
+*/
+
+
+/* Functions to support M-Pin Full */
+#[allow(non_snake_case)]
+pub fn precompute(token: &[u8],cid: &[u8],g1: &mut [u8],g2: &mut [u8]) -> isize {
+	let T=ECP::frombytes(&token);
+	if T.is_infinity() {return INVALID_POINT} 
+
+	let P=ECP::mapit(&cid);
+
+	let Q=ECP4::generator();
+
+	let mut g=pair192::ate(&Q,&T);
+	g=pair192::fexp(&g);
+	g.tobytes(g1);
+
+	g=pair192::ate(&Q,&P);
+	g=pair192::fexp(&g);
+	g.tobytes(g2);
+
+	return 0;
+}
+
+/* Time Permit CTT=S*(date|H(CID)) where S is master secret */
+#[allow(non_snake_case)]
+pub fn get_client_permit(sha: usize,date: usize,s: &[u8],cid: &[u8],ctt: &mut [u8]) ->isize {
+	const RM:usize=big::MODBYTES as usize;
+	let mut h:[u8;RM]=[0;RM];	
+	hashit(sha,date,cid,&mut h);
+	let mut P=ECP::mapit(&h);
+
+	let mut sc=BIG::frombytes(s);
+	pair192::g1mul(&mut P,&mut sc).tobytes(ctt,false);
+	return 0;
+}
+
+/* Implement step 1 on client side of MPin protocol */
+#[allow(non_snake_case)]
+pub fn client_1(sha: usize,date: usize,client_id: &[u8],rng: Option<&mut RAND>,x: &mut [u8],pin: usize,token: &[u8],sec: &mut [u8],xid: Option<&mut [u8]>,xcid: Option<&mut [u8]>,permit: Option<&[u8]>) ->isize {
+	let r=BIG::new_ints(&rom::CURVE_ORDER);
+		
+	let mut sx:BIG;
+
+	if let Some(rd)=rng
+	{
+		sx=BIG::randomnum(&r,rd);
+		//if rom::AES_S>0 {
+		//	sx.mod2m(2*rom::AES_S);
+		//}
+		sx.tobytes(x);
+	} else {
+		sx=BIG::frombytes(x);
+	}
+
+	const RM:usize=big::MODBYTES as usize;
+	let mut h:[u8;RM]=[0;RM];
+
+	hashit(sha,0,&client_id,&mut h);
+	let mut P=ECP::mapit(&h);
+	
+	let mut T=ECP::frombytes(&token);
+	if T.is_infinity() {return INVALID_POINT}
+
+	let mut W=P.pinmul((pin as i32)%MAXPIN,PBLEN);
+	T.add(&mut W);
+	if date!=0 {
+		if let Some(rpermit)=permit {W=ECP::frombytes(&rpermit);}
+		if W.is_infinity() {return INVALID_POINT}
+		T.add(&mut W);
+		let mut h2:[u8;RM]=[0;RM];		
+		hashit(sha,date,&h,&mut h2);
+		W=ECP::mapit(&h2);
+		if let Some(mut rxid)=xid {
+			P=pair192::g1mul(&mut P,&mut sx);
+			P.tobytes(&mut rxid,false);
+			W=pair192::g1mul(&mut W,&mut sx);
+			P.add(&mut W);
+		} else {
+			P.add(&mut W);
+			P=pair192::g1mul(&mut P,&mut sx);
+		}
+		if let Some(mut rxcid)=xcid {P.tobytes(&mut rxcid,false)}
+	} else {
+		if let Some(mut rxid)=xid {
+			P=pair192::g1mul(&mut P,&mut sx);
+			P.tobytes(&mut rxid,false);
+		}
+	}
+
+	T.tobytes(sec,false);
+	return 0;
+}
+
+/* Outputs H(CID) and H(T|H(CID)) for time permits. If no time permits set HID=HTID */
+#[allow(non_snake_case)]
+pub fn server_1(sha: usize,date: usize,cid: &[u8],hid: &mut [u8],htid: Option<&mut [u8]>) {
+	const RM:usize=big::MODBYTES as usize;
+	let mut h:[u8;RM]=[0;RM];
+
+	hashit(sha,0,cid,&mut h);	
+
+	let mut P=ECP::mapit(&h);
+	
+	P.tobytes(hid,false);
+	if date!=0 {
+		let mut h2:[u8;RM]=[0;RM];		
+		hashit(sha,date,&h,&mut h2);
+		let mut R=ECP::mapit(&h2);
+		P.add(&mut R);
+		if let Some(rhtid)=htid {P.tobytes(rhtid,false);}
+	} 
+}
+
+/* Implement step 2 on client side of MPin protocol */
+#[allow(non_snake_case)]
+pub fn client_2(x: &[u8],y: &[u8],sec: &mut [u8]) -> isize {
+	let mut r=BIG::new_ints(&rom::CURVE_ORDER);
+	let mut P=ECP::frombytes(sec);
+	if P.is_infinity() {return INVALID_POINT}
+
+	let mut px=BIG::frombytes(x);
+	let py=BIG::frombytes(y);
+	px.add(&py);
+	px.rmod(&mut r);
+	//px.rsub(r)
+
+	P=pair192::g1mul(&mut P,&mut px);
+	P.neg();
+	P.tobytes(sec,false);
+	
+	return 0;
+}
+
+/* return time since epoch */
+pub fn get_time() -> usize {
+  	return (SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) as usize;	
+}
+
+/* Generate Y = H(epoch, xCID/xID) */
+pub fn get_y(sha: usize,timevalue: usize,xcid: &[u8],y: &mut [u8]) {
+	const RM:usize=big::MODBYTES as usize;
+	let mut h:[u8;RM]=[0;RM];
+
+	hashit(sha,timevalue,xcid,&mut h);	
+
+	let mut sy= BIG::frombytes(&h);
+	let mut q=BIG::new_ints(&rom::CURVE_ORDER);
+	sy.rmod(&mut q);
+	//if rom::AES_S>0 {
+	//	sy.mod2m(2*rom::AES_S);
+	//}
+	sy.tobytes(y);
+}
+
+/* Implement step 2 of MPin protocol on server side */
+#[allow(non_snake_case)]
+pub fn server_2(date: usize,hid: &[u8],htid: Option<&[u8]>,y: &[u8],sst: &[u8],xid: Option<&[u8]>,xcid: Option<&[u8]>,msec: &[u8],e: Option<&mut [u8]>,f: Option<&mut [u8]>) -> isize {
+//	q:=NewBIGints(Modulus)
+	let Q=ECP4::generator();
+
+	let sQ=ECP4::frombytes(&sst);
+	if sQ.is_infinity() {return INVALID_POINT}	
+
+	let mut R:ECP;
+	if date!=0 {
+		if let Some(rxcid)=xcid {R=ECP::frombytes(&rxcid);}
+		else {return BAD_PARAMS}
+	} else {
+		if let Some(rxid)=xid {R=ECP::frombytes(&rxid)}
+		else {return BAD_PARAMS}
+	}
+	if R.is_infinity() {return INVALID_POINT}
+
+	let mut sy=BIG::frombytes(&y);
+	let mut P:ECP;
+	if date!=0 {
+		if let Some(rhtid)=htid {P=ECP::frombytes(&rhtid)}
+		else {return BAD_PARAMS}
+	} else {
+		P=ECP::frombytes(&hid);
+	}
+	
+	if P.is_infinity() {return INVALID_POINT}
+
+	P=pair192::g1mul(&mut P,&mut sy);
+	P.add(&mut R); //P.affine();
+	R=ECP::frombytes(&msec);
+	if R.is_infinity() {return INVALID_POINT}
+
+	let mut g:FP24;
+//		FP24 g1=new FP24(0);
+
+	g=pair192::ate2(&Q,&R,&sQ,&P);
+	g=pair192::fexp(&g);
+
+	if !g.isunity() {
+		
+		if let Some(rxid)=xid {
+			if let Some(re)=e {
+				if let Some(rf)=f {
+
+					g.tobytes(re);
+					if date!=0 {
+						P=ECP::frombytes(&hid);
+						if P.is_infinity() {return INVALID_POINT}		
+						R=ECP::frombytes(&rxid);
+						if R.is_infinity() {return INVALID_POINT}			
+						P=pair192::g1mul(&mut P,&mut sy);
+						P.add(&mut R);	//P.affine();								
+					}
+					g=pair192::ate(&Q,&P);
+					g=pair192::fexp(&g);
+					g.tobytes(rf);
+
+				}
+			}
+		}
+	
+		return BAD_PIN;
+	}
+
+	return 0;
+}
+
+/* Pollards kangaroos used to return PIN error */
+pub fn kangaroo(e: &[u8],f: &[u8]) -> isize {
+	let mut ge=FP24::frombytes(e);
+	let mut gf=FP24::frombytes(f);
+	let mut distance: [isize;TS]=[0;TS];
+	let mut t=FP24::new_copy(&gf);
+
+	let mut table: [FP24;TS]=[FP24::new();TS];
+	let mut s:isize=1;
+	for m in 0..TS {
+		distance[m]=s;
+		table[m]=FP24::new_copy(&t);
+		s*=2;
+		t.usqr();
+	}
+	t.one();
+	let mut dn:isize=0;
+	let mut i:usize;
+	for _ in 0..TRAP {
+		i=(t.geta().geta().geta().geta().lastbits(20)%(TS as isize)) as usize;
+		t.mul(&mut table[i]);
+		dn+=distance[i];
+	}
+	gf.copy(&t); gf.conj();
+	let mut steps:usize=0; let mut dm:isize=0;
+	let mut res:isize=0;
+	while dm-dn<MAXPIN as isize {
+		steps+=1;
+		if steps>4*TRAP {break}
+		i=(ge.geta().geta().geta().geta().lastbits(20)%(TS as isize)) as usize;
+		ge.mul(&mut table[i]);
+		dm+=distance[i];
+		if ge.equals(&mut t) {
+			res=dm-dn;
+			break;
+		}
+		if ge.equals(&mut gf) {
+			res=dn-dm;
+			break;
+		}
+
+	}
+	if steps>4*TRAP || dm-dn>=MAXPIN as isize {res=0 }    // Trap Failed  - probable invalid token
+	return res;
+}
+
+/* Hash the M-Pin transcript - new */
+
+pub fn hash_all(sha: usize,hid: &[u8],xid: &[u8],xcid: Option<&[u8]>,sec: &[u8],y: &[u8],r: &[u8],w: &[u8],h: &mut[u8]) -> bool {
+	let mut tlen:usize=0;
+	const RM:usize=big::MODBYTES as usize;	
+	let mut t: [u8;10*RM+4]=[0;10*RM+4];
+
+	for i in 0 .. hid.len() {t[i]=hid[i]}
+	tlen+=hid.len();
+
+	if let Some(rxcid)=xcid {
+		for i in 0..rxcid.len() {t[i+tlen]=rxcid[i]}
+		tlen+=rxcid.len();
+	} else {
+		for i in 0..xid.len() {t[i+tlen]=xid[i]}
+		tlen+=xid.len();
+	}	
+
+	for i in 0..sec.len() {t[i+tlen]=sec[i]}
+	tlen+=sec.len();		
+	for i in 0..y.len() {t[i+tlen]=y[i]}
+	tlen+=y.len();
+	for i in 0..r.len() {t[i+tlen]=r[i]}
+	tlen+=r.len();		
+	for i in 0..w.len() {t[i+tlen]=w[i]}
+	tlen+=w.len();	
+	if tlen!=10*RM+4 {return false}
+
+	return hashit(sha,0,&t,h);
+}
+
+/* calculate common key on client side */
+/* wCID = w.(A+AT) */
+#[allow(non_snake_case)]
+pub fn client_key(sha: usize,g1: &[u8],g2: &[u8],pin: usize,r: &[u8],x: &[u8],h: &[u8],wcid: &[u8],ck: &mut [u8]) -> isize {
+
+	let mut g1=FP24::frombytes(&g1);
+	let mut g2=FP24::frombytes(&g2);
+	let mut z=BIG::frombytes(&r);
+	let mut x=BIG::frombytes(&x);
+	let h=BIG::frombytes(&h);
+
+	let mut W=ECP::frombytes(&wcid);
+	if W.is_infinity() {return INVALID_POINT} 
+
+	W=pair192::g1mul(&mut W,&mut x);
+
+//	let mut f=FP2::new_bigs(&BIG::new_ints(&rom::FRA),&BIG::new_ints(&rom::FRB));
+	let mut r=BIG::new_ints(&rom::CURVE_ORDER);
+//	let q=BIG::new_ints(&rom::MODULUS);
+
+	z.add(&h);	//new
+	z.rmod(&mut r);
+
+	g2.pinpow(pin as i32,PBLEN);
+	g1.mul(&mut g2);
+
+	let mut c=g1.compow(&z,&mut r);
+
+
+	hash(sha,&mut c,&mut W,ck);
+
+	return 0
+}
+
+/* calculate common key on server side */
+/* Z=r.A - no time permits involved */
+#[allow(non_snake_case)]
+pub fn server_key(sha: usize,z: &[u8],sst: &[u8],w: &[u8],h: &[u8],hid: &[u8],xid: &[u8],xcid: Option<&[u8]>,sk: &mut [u8]) -> isize {
+	let sQ=ECP4::frombytes(&sst);
+	if sQ.is_infinity() {return INVALID_POINT} 
+	let mut R=ECP::frombytes(&z);
+	if R.is_infinity() {return INVALID_POINT} 
+	let mut A=ECP::frombytes(&hid);
+	if A.is_infinity() {return INVALID_POINT} 
+
+	let mut U=ECP::new();
+	if let Some(rxcid)=xcid {
+		U.copy(&ECP::frombytes(&rxcid));
+	} else {
+		U.copy(&ECP::frombytes(&xid));
+	}
+	
+	if U.is_infinity() {return INVALID_POINT} 
+
+	let mut w=BIG::frombytes(&w);
+	let mut h=BIG::frombytes(&h);
+	A=pair192::g1mul(&mut A,&mut h);	// new
+	R.add(&mut A); //R.affine();
+
+	U=pair192::g1mul(&mut U,&mut w);
+	let mut g=pair192::ate(&sQ,&R);
+	g=pair192::fexp(&g);
+
+	let mut c=g.trace();
+
+	hash(sha,&mut c,&mut U,sk);
+
+	return 0
+}
+
diff --git a/version3/rust/mpin256.rs b/version3/rust/mpin256.rs
new file mode 100644
index 0000000..8aa20d9
--- /dev/null
+++ b/version3/rust/mpin256.rs
@@ -0,0 +1,791 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use std::time::{SystemTime};
+use std::time::UNIX_EPOCH;
+
+use xxx::ecp;
+use xxx::ecp::ECP;
+use xxx::ecp8::ECP8;
+use xxx::fp16::FP16;
+use xxx::fp48::FP48;
+use xxx::big::BIG;
+use xxx::pair256;
+use xxx::big;
+use xxx::rom;
+
+use rand::RAND;
+use hash256::HASH256;
+use hash384::HASH384;
+use hash512::HASH512;
+
+
+/* MPIN API Functions */
+
+/* Configure mode of operation */
+
+pub const EFS: usize=big::MODBYTES as usize;
+pub const EGS: usize=big::MODBYTES as usize;
+//pub const PAS: usize=16;
+pub const BAD_PARAMS: isize=-11;
+pub const INVALID_POINT: isize=-14;
+pub const WRONG_ORDER: isize=-18;
+pub const BAD_PIN: isize=-19;
+pub const SHA256: usize=32;
+pub const SHA384: usize=48;
+pub const SHA512: usize=64;
+
+/* Configure your PIN here */
+
+pub const MAXPIN: i32=10000;  /* PIN less than this */
+pub const PBLEN: i32=14;      /* Number of bits in PIN */
+pub const TS: usize=10;         /* 10 for 4 digit PIN, 14 for 6-digit PIN - 2^TS/TS approx = sqrt(MAXPIN) */
+pub const TRAP:usize=200;      /* 200 for 4 digit PIN, 2000 for 6-digit PIN  - approx 2*sqrt(MAXPIN) */
+
+//pub const HASH_TYPE: usize=SHA256;
+
+#[allow(non_snake_case)]
+fn hash(sha: usize,c: &mut FP16,U: &mut ECP,r: &mut [u8]) -> bool {
+	let mut w:[u8;EFS]=[0;EFS];
+	let mut t:[u8;18*EFS]=[0;18*EFS];
+
+	c.geta().geta().geta().geta().tobytes(&mut w); for i in 0..EFS {t[i]=w[i]}
+	c.geta().geta().geta().getb().tobytes(&mut w); for i in EFS..2*EFS {t[i]=w[i-EFS]}
+	c.geta().geta().getb().geta().tobytes(&mut w); for i in 2*EFS..3*EFS {t[i]=w[i-2*EFS]}
+	c.geta().geta().getb().getb().tobytes(&mut w); for i in 3*EFS..4*EFS {t[i]=w[i-3*EFS]}
+	c.geta().getb().geta().geta().tobytes(&mut w); for i in 4*EFS..5*EFS {t[i]=w[i-4*EFS]}
+	c.geta().getb().geta().getb().tobytes(&mut w); for i in 5*EFS..6*EFS {t[i]=w[i-5*EFS]}
+	c.geta().getb().getb().geta().tobytes(&mut w); for i in 6*EFS..7*EFS {t[i]=w[i-6*EFS]}
+	c.geta().getb().getb().getb().tobytes(&mut w); for i in 7*EFS..8*EFS {t[i]=w[i-7*EFS]}
+
+
+	c.getb().geta().geta().geta().tobytes(&mut w); for i in 8*EFS..9*EFS {t[i]=w[i-8*EFS]}
+	c.getb().geta().geta().getb().tobytes(&mut w); for i in 9*EFS..10*EFS {t[i]=w[i-9*EFS]}
+	c.getb().geta().getb().geta().tobytes(&mut w); for i in 10*EFS..11*EFS {t[i]=w[i-10*EFS]}
+	c.getb().geta().getb().getb().tobytes(&mut w); for i in 11*EFS..12*EFS {t[i]=w[i-11*EFS]}
+	c.getb().getb().geta().geta().tobytes(&mut w); for i in 12*EFS..13*EFS {t[i]=w[i-12*EFS]}
+	c.getb().getb().geta().getb().tobytes(&mut w); for i in 13*EFS..14*EFS {t[i]=w[i-13*EFS]}
+	c.getb().getb().getb().geta().tobytes(&mut w); for i in 14*EFS..15*EFS {t[i]=w[i-14*EFS]}
+	c.getb().getb().getb().getb().tobytes(&mut w); for i in 15*EFS..16*EFS {t[i]=w[i-15*EFS]}
+
+
+	U.getx().tobytes(&mut w); for i in 16*EFS..17*EFS {t[i]=w[i-16*EFS]}
+	U.gety().tobytes(&mut w); for i in 17*EFS..18*EFS {t[i]=w[i-17*EFS]}
+
+	if sha==SHA256 {
+		let mut h=HASH256::new();
+		h.process_array(&t);
+		let sh=h.hash();
+		for i in 0..ecp::AESKEY {r[i]=sh[i]}	
+		return true;	
+	}
+	if sha==SHA384 {
+		let mut h=HASH384::new();
+		h.process_array(&t);
+		let sh=h.hash();
+		for i in 0..ecp::AESKEY {r[i]=sh[i]}		
+		return true;
+	}
+	if sha==SHA512 {
+		let mut h=HASH512::new();
+		h.process_array(&t);
+		let sh=h.hash();
+		for i in 0..ecp::AESKEY {r[i]=sh[i]}
+		return true;		
+	}
+	return false;
+
+}
+
+/* Hash number (optional) and string to point on curve */
+
+fn hashit(sha: usize,n: usize,id: &[u8],w: &mut [u8]) -> bool {
+	let mut r:[u8;64]=[0;64];
+	let mut didit=false;
+	if sha==SHA256 {
+		let mut h=HASH256::new();
+		if n>0 {h.process_num(n as i32)}
+		h.process_array(id);
+        let hs=h.hash();	
+        for i in 0..sha {r[i]=hs[i];}	
+        didit=true;
+	}
+	if sha==SHA384 {
+		let mut h=HASH384::new();
+		if n>0 {h.process_num(n as i32)}
+		h.process_array(id);
+		let hs=h.hash();
+        for i in 0..sha {r[i]=hs[i];}			
+		didit=true;
+	}
+	if sha==SHA512 {
+		let mut h=HASH512::new();
+		if n>0 {h.process_num(n as i32)}
+		h.process_array(id);
+		let hs=h.hash();
+        for i in 0..sha {r[i]=hs[i];}	
+        didit=true;		
+	}
+	if !didit {return false}
+
+	let rm=big::MODBYTES as usize;
+
+	if sha>rm {
+		for i in 0..rm {w[i]=r[i]}
+	} else {
+		for i in 0..sha {w[i+rm-sha]=r[i]}
+		for i in 0..(rm-sha) {w[i]=0}
+
+
+		//for i in 0..sha {w[i]=r[i]}	
+		//for i in sha..rm {w[i]=0}
+	}
+
+	return true;
+}
+
+/* return time in slots since epoch */
+pub fn today() -> usize {
+  	return (SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()/(60*1440)) as usize;
+}
+
+/* these next two functions help to implement elligator squared - http://eprint.iacr.org/2014/043 */
+/* maps a random u to a point on the curve */
+#[allow(non_snake_case)]
+fn emap(u: &BIG,cb: isize) -> ECP {
+	let mut P:ECP;
+	let mut x=BIG::new_copy(u);
+	let mut p=BIG::new_ints(&rom::MODULUS);
+	x.rmod(&mut p);
+	loop {
+		P=ECP::new_bigint(&x,cb);
+		if !P.is_infinity() {break}
+		x.inc(1);  x.norm();
+	}
+	return P;
+}
+
+/* returns u derived from P. Random value in range 1 to return value should then be added to u */
+#[allow(non_snake_case)]
+fn unmap(u: &mut BIG,P: &mut ECP) -> isize {
+	let s=P.gets();
+	let mut R:ECP;
+	let mut r=0;
+	let x=P.getx();
+	u.copy(&x);
+	loop {
+		u.dec(1); u.norm();
+		r+=1;
+		R=ECP::new_bigint(u,s);
+		if !R.is_infinity() {break}
+	}
+	return r as isize;
+}
+
+pub fn hash_id(sha: usize,id: &[u8],w: &mut [u8]) -> bool {
+	return hashit(sha,0,id,w);
+}
+
+/* these next two functions implement elligator squared - http://eprint.iacr.org/2014/043 */
+/* Elliptic curve point E in format (0x04,x,y} is converted to form {0x0-,u,v} */
+/* Note that u and v are indistinguisible from random strings */
+#[allow(non_snake_case)]
+pub fn encoding(rng: &mut RAND,e: &mut [u8]) ->isize {
+	let mut t:[u8;EFS]=[0;EFS];
+
+	for i in 0..EFS {t[i]=e[i+1]}
+	let mut u=BIG::frombytes(&t);
+	for i in 0..EFS {t[i]=e[i+EFS+1]}
+	let mut v=BIG::frombytes(&t);
+		
+	let mut P=ECP::new_bigs(&u,&v);
+	if P.is_infinity() {return INVALID_POINT}
+
+	let p=BIG::new_ints(&rom::MODULUS);
+	u=BIG::randomnum(&p,rng);
+
+	let mut su=rng.getbyte() as isize; /*if (su<0) su=-su;*/ su%=2;
+		
+	let mut W=emap(&mut u,su);
+	P.sub(&mut W);
+	let sv=P.gets();
+	let rn=unmap(&mut v,&mut P);
+	let mut m=rng.getbyte() as isize; /*if (m<0) m=-m;*/ m%=rn;
+	v.inc(m+1);
+	e[0]=(su+2*sv) as u8;
+	u.tobytes(&mut t);
+	for i in 0..EFS {e[i+1]=t[i]}
+	v.tobytes(&mut t);
+	for i in 0..EFS {e[i+EFS+1]=t[i]}		
+		
+	return 0;
+}
+
+#[allow(non_snake_case)]
+pub fn decoding(d: &mut [u8]) -> isize {
+	let mut t:[u8;EFS]=[0;EFS];
+
+	if (d[0]&0x04)!=0 {return INVALID_POINT}
+
+	for i in 0..EFS {t[i]=d[i+1]}
+	let mut u=BIG::frombytes(&t);
+	for i in 0..EFS {t[i]=d[i+EFS+1]}
+	let mut v=BIG::frombytes(&t);
+
+	let su=(d[0]&1) as isize;
+	let sv=((d[0]>>1)&1) as isize;
+	let mut W=emap(&mut u,su);
+	let mut P=emap(&mut v,sv);
+	P.add(&mut W);
+	u=P.getx();
+	v=P.gety();
+	d[0]=0x04;
+	u.tobytes(&mut t);
+	for i in 0..EFS {d[i+1]=t[i]}
+	v.tobytes(&mut t);
+	for i in 0..EFS {d[i+EFS+1]=t[i]}		
+		
+	return 0;
+}
+
+/* R=R1+R2 in group G1 */
+#[allow(non_snake_case)]
+pub fn recombine_g1(r1: &[u8],r2: &[u8],r: &mut [u8]) -> isize {
+	let mut P=ECP::frombytes(&r1);
+	let mut Q=ECP::frombytes(&r2);
+
+	if P.is_infinity() || Q.is_infinity() {return INVALID_POINT}
+
+	P.add(&mut Q);
+
+	P.tobytes(r,false);
+	return 0;
+}
+
+/* W=W1+W2 in group G2 */
+#[allow(non_snake_case)]
+pub fn recombine_g2(w1: &[u8],w2: &[u8],w: &mut [u8]) -> isize {
+	let mut P=ECP8::frombytes(&w1);
+	let mut Q=ECP8::frombytes(&w2);
+
+	if P.is_infinity() || Q.is_infinity() {return INVALID_POINT}
+
+	P.add(&mut Q);
+	
+	P.tobytes(w);
+	return 0;
+}
+
+/* create random secret S */
+pub fn random_generate(rng: &mut RAND,s: &mut [u8]) -> isize {
+	let r=BIG::new_ints(&rom::CURVE_ORDER);
+	let mut sc=BIG::randomnum(&r,rng);
+	//if rom::AES_S>0 {
+	//	sc.mod2m(2*rom::AES_S);
+	//}		
+	sc.tobytes(s);
+	return 0;
+}
+
+/* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */
+#[allow(non_snake_case)]
+pub fn get_server_secret(s: &[u8],sst: &mut [u8]) -> isize {
+
+	let mut Q=ECP8::generator();
+
+	let mut sc=BIG::frombytes(s);
+	Q=pair256::g2mul(&mut Q,&mut sc);
+	Q.tobytes(sst);
+	return 0;
+}
+
+/*
+ W=x*H(G);
+ if RNG == NULL then X is passed in 
+ if RNG != NULL the X is passed out 
+ if type=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve
+*/
+#[allow(non_snake_case)]
+pub fn get_g1_multiple(rng: Option<&mut RAND>,typ: usize,x: &mut [u8],g: &[u8],w: &mut [u8]) -> isize {
+	let mut sx:BIG;
+	let r=BIG::new_ints(&rom::CURVE_ORDER);
+
+	if let Some(rd)=rng
+	{
+		sx=BIG::randomnum(&r,rd);
+		//if rom::AES_S>0 {
+		//	sx.mod2m(2*rom::AES_S);
+		//}
+		sx.tobytes(x);
+	} else {
+		sx=BIG::frombytes(x);
+	}
+	let mut P:ECP;
+
+	if typ==0 {
+		P=ECP::frombytes(g);
+		if P.is_infinity() {return INVALID_POINT}
+	} else {
+		P=ECP::mapit(g)
+	}
+
+
+
+	pair256::g1mul(&mut P,&mut sx).tobytes(w,false);
+	return 0;
+}
+
+
+/* Client secret CST=S*H(CID) where CID is client ID and S is master secret */
+/* CID is hashed externally */
+pub fn get_client_secret(s: &mut [u8],cid: &[u8],cst: &mut [u8]) -> isize {
+	return get_g1_multiple(None,1,s,cid,cst);
+}
+
+/* Extract PIN from TOKEN for identity CID */
+#[allow(non_snake_case)]
+pub fn extract_pin(sha: usize,cid: &[u8],pin: i32,token: &mut [u8]) -> isize {
+	return extract_factor(sha,cid,pin%MAXPIN,PBLEN,token);
+}
+
+/* Extract factor from TOKEN for identity CID */
+#[allow(non_snake_case)]
+pub fn extract_factor(sha: usize,cid: &[u8],factor: i32,facbits: i32,token: &mut [u8]) -> isize {
+	let mut P=ECP::frombytes(&token);
+	const RM:usize=big::MODBYTES as usize;
+	let mut h:[u8;RM]=[0;RM];
+	if P.is_infinity() {return INVALID_POINT}
+	hashit(sha,0,cid,&mut h);
+	let mut R=ECP::mapit(&h);
+
+	R=R.pinmul(factor,facbits);
+	P.sub(&mut R);
+
+	P.tobytes(token,false);
+
+	return 0;
+}
+
+/* Restore factor to TOKEN for identity CID */
+#[allow(non_snake_case)]
+pub fn restore_factor(sha: usize,cid: &[u8],factor: i32,facbits: i32,token: &mut [u8]) -> isize {
+	let mut P=ECP::frombytes(&token);
+	const RM:usize=big::MODBYTES as usize;
+	let mut h:[u8;RM]=[0;RM];
+	if P.is_infinity() {return INVALID_POINT}
+	hashit(sha,0,cid,&mut h);
+	let mut R=ECP::mapit(&h);
+
+	R=R.pinmul(factor,facbits);
+	P.add(&mut R);
+
+	P.tobytes(token,false);
+
+	return 0;
+}
+
+/* Extract PIN from TOKEN for identity CID 
+#[allow(non_snake_case)]
+pub fn extract_pin(sha: usize,cid: &[u8],pin: i32,token: &mut [u8]) -> isize {
+	let mut P=ECP::frombytes(&token);
+	const RM:usize=big::MODBYTES as usize;
+	let mut h:[u8;RM]=[0;RM];
+	if P.is_infinity() {return INVALID_POINT}
+	hashit(sha,0,cid,&mut h);
+	let mut R=ECP::mapit(&h);
+
+	R=R.pinmul(pin%MAXPIN,PBLEN);
+	P.sub(&mut R);
+
+	P.tobytes(token,false);
+
+	return 0;
+}
+*/
+
+
+/* Functions to support M-Pin Full */
+#[allow(non_snake_case)]
+pub fn precompute(token: &[u8],cid: &[u8],g1: &mut [u8],g2: &mut [u8]) -> isize {
+	let T=ECP::frombytes(&token);
+	if T.is_infinity() {return INVALID_POINT} 
+
+	let P=ECP::mapit(&cid);
+
+	let Q=ECP8::generator();
+
+	let mut g=pair256::ate(&Q,&T);
+	g=pair256::fexp(&g);
+	g.tobytes(g1);
+
+	g=pair256::ate(&Q,&P);
+	g=pair256::fexp(&g);
+	g.tobytes(g2);
+
+	return 0;
+}
+
+/* Time Permit CTT=S*(date|H(CID)) where S is master secret */
+#[allow(non_snake_case)]
+pub fn get_client_permit(sha: usize,date: usize,s: &[u8],cid: &[u8],ctt: &mut [u8]) ->isize {
+	const RM:usize=big::MODBYTES as usize;
+	let mut h:[u8;RM]=[0;RM];	
+	hashit(sha,date,cid,&mut h);
+	let mut P=ECP::mapit(&h);
+
+	let mut sc=BIG::frombytes(s);
+	pair256::g1mul(&mut P,&mut sc).tobytes(ctt,false);
+	return 0;
+}
+
+/* Implement step 1 on client side of MPin protocol */
+#[allow(non_snake_case)]
+pub fn client_1(sha: usize,date: usize,client_id: &[u8],rng: Option<&mut RAND>,x: &mut [u8],pin: usize,token: &[u8],sec: &mut [u8],xid: Option<&mut [u8]>,xcid: Option<&mut [u8]>,permit: Option<&[u8]>) ->isize {
+	let r=BIG::new_ints(&rom::CURVE_ORDER);
+		
+	let mut sx:BIG;
+
+	if let Some(rd)=rng
+	{
+		sx=BIG::randomnum(&r,rd);
+		//if rom::AES_S>0 {
+		//	sx.mod2m(2*rom::AES_S);
+		//}
+		sx.tobytes(x);
+	} else {
+		sx=BIG::frombytes(x);
+	}
+
+	const RM:usize=big::MODBYTES as usize;
+	let mut h:[u8;RM]=[0;RM];
+
+	hashit(sha,0,&client_id,&mut h);
+	let mut P=ECP::mapit(&h);
+	
+	let mut T=ECP::frombytes(&token);
+	if T.is_infinity() {return INVALID_POINT}
+
+	let mut W=P.pinmul((pin as i32)%MAXPIN,PBLEN);
+	T.add(&mut W);
+	if date!=0 {
+		if let Some(rpermit)=permit {W=ECP::frombytes(&rpermit);}
+		if W.is_infinity() {return INVALID_POINT}
+		T.add(&mut W);
+		let mut h2:[u8;RM]=[0;RM];		
+		hashit(sha,date,&h,&mut h2);
+		W=ECP::mapit(&h2);
+		if let Some(mut rxid)=xid {
+			P=pair256::g1mul(&mut P,&mut sx);
+			P.tobytes(&mut rxid,false);
+			W=pair256::g1mul(&mut W,&mut sx);
+			P.add(&mut W);
+		} else {
+			P.add(&mut W);
+			P=pair256::g1mul(&mut P,&mut sx);
+		}
+		if let Some(mut rxcid)=xcid {P.tobytes(&mut rxcid,false)}
+	} else {
+		if let Some(mut rxid)=xid {
+			P=pair256::g1mul(&mut P,&mut sx);
+			P.tobytes(&mut rxid,false);
+		}
+	}
+
+	T.tobytes(sec,false);
+	return 0;
+}
+
+/* Outputs H(CID) and H(T|H(CID)) for time permits. If no time permits set HID=HTID */
+#[allow(non_snake_case)]
+pub fn server_1(sha: usize,date: usize,cid: &[u8],hid: &mut [u8],htid: Option<&mut [u8]>) {
+	const RM:usize=big::MODBYTES as usize;
+	let mut h:[u8;RM]=[0;RM];
+
+	hashit(sha,0,cid,&mut h);	
+
+	let mut P=ECP::mapit(&h);
+	
+	P.tobytes(hid,false);
+	if date!=0 {
+		let mut h2:[u8;RM]=[0;RM];		
+		hashit(sha,date,&h,&mut h2);
+		let mut R=ECP::mapit(&h2);
+		P.add(&mut R);
+		if let Some(rhtid)=htid {P.tobytes(rhtid,false);}
+	} 
+}
+
+/* Implement step 2 on client side of MPin protocol */
+#[allow(non_snake_case)]
+pub fn client_2(x: &[u8],y: &[u8],sec: &mut [u8]) -> isize {
+	let mut r=BIG::new_ints(&rom::CURVE_ORDER);
+	let mut P=ECP::frombytes(sec);
+	if P.is_infinity() {return INVALID_POINT}
+
+	let mut px=BIG::frombytes(x);
+	let py=BIG::frombytes(y);
+	px.add(&py);
+	px.rmod(&mut r);
+	//px.rsub(r)
+
+	P=pair256::g1mul(&mut P,&mut px);
+	P.neg();
+	P.tobytes(sec,false);
+	
+	return 0;
+}
+
+/* return time since epoch */
+pub fn get_time() -> usize {
+  	return (SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) as usize;	
+}
+
+/* Generate Y = H(epoch, xCID/xID) */
+pub fn get_y(sha: usize,timevalue: usize,xcid: &[u8],y: &mut [u8]) {
+	const RM:usize=big::MODBYTES as usize;
+	let mut h:[u8;RM]=[0;RM];
+
+	hashit(sha,timevalue,xcid,&mut h);	
+
+	let mut sy= BIG::frombytes(&h);
+	let mut q=BIG::new_ints(&rom::CURVE_ORDER);
+	sy.rmod(&mut q);
+	//if rom::AES_S>0 {
+	//	sy.mod2m(2*rom::AES_S);
+	//}
+	sy.tobytes(y);
+}
+
+/* Implement step 2 of MPin protocol on server side */
+#[allow(non_snake_case)]
+pub fn server_2(date: usize,hid: &[u8],htid: Option<&[u8]>,y: &[u8],sst: &[u8],xid: Option<&[u8]>,xcid: Option<&[u8]>,msec: &[u8],e: Option<&mut [u8]>,f: Option<&mut [u8]>) -> isize {
+//	q:=NewBIGints(Modulus)
+	let Q=ECP8::generator();
+
+	let sQ=ECP8::frombytes(&sst);
+	if sQ.is_infinity() {return INVALID_POINT}	
+
+	let mut R:ECP;
+	if date!=0 {
+		if let Some(rxcid)=xcid {R=ECP::frombytes(&rxcid);}
+		else {return BAD_PARAMS}
+	} else {
+		if let Some(rxid)=xid {R=ECP::frombytes(&rxid)}
+		else {return BAD_PARAMS}
+	}
+	if R.is_infinity() {return INVALID_POINT}
+
+	let mut sy=BIG::frombytes(&y);
+	let mut P:ECP;
+	if date!=0 {
+		if let Some(rhtid)=htid {P=ECP::frombytes(&rhtid)}
+		else {return BAD_PARAMS}
+	} else {
+		P=ECP::frombytes(&hid);
+	}
+	
+	if P.is_infinity() {return INVALID_POINT}
+
+	P=pair256::g1mul(&mut P,&mut sy);
+	P.add(&mut R); //P.affine();
+	R=ECP::frombytes(&msec);
+	if R.is_infinity() {return INVALID_POINT}
+
+	let mut g:FP48;
+//		FP48 g1=new FP48(0);
+
+	g=pair256::ate2(&Q,&R,&sQ,&P);
+	g=pair256::fexp(&g);
+
+	if !g.isunity() {
+		
+		if let Some(rxid)=xid {
+			if let Some(re)=e {
+				if let Some(rf)=f {
+
+					g.tobytes(re);
+					if date!=0 {
+						P=ECP::frombytes(&hid);
+						if P.is_infinity() {return INVALID_POINT}		
+						R=ECP::frombytes(&rxid);
+						if R.is_infinity() {return INVALID_POINT}			
+						P=pair256::g1mul(&mut P,&mut sy);
+						P.add(&mut R);	//P.affine();								
+					}
+					g=pair256::ate(&Q,&P);
+					g=pair256::fexp(&g);
+					g.tobytes(rf);
+
+				}
+			}
+		}
+	
+		return BAD_PIN;
+	}
+
+	return 0;
+}
+
+/* Pollards kangaroos used to return PIN error */
+pub fn kangaroo(e: &[u8],f: &[u8]) -> isize {
+	let mut ge=FP48::frombytes(e);
+	let mut gf=FP48::frombytes(f);
+	let mut distance: [isize;TS]=[0;TS];
+	let mut t=FP48::new_copy(&gf);
+
+	let mut table: [FP48;TS]=[FP48::new();TS];
+	let mut s:isize=1;
+	for m in 0..TS {
+		distance[m]=s;
+		table[m]=FP48::new_copy(&t);
+		s*=2;
+		t.usqr();
+	}
+	t.one();
+	let mut dn:isize=0;
+	let mut i:usize;
+	for _ in 0..TRAP {
+		i=(t.geta().geta().geta().geta().geta().lastbits(20)%(TS as isize)) as usize;
+		t.mul(&mut table[i]);
+		dn+=distance[i];
+	}
+	gf.copy(&t); gf.conj();
+	let mut steps:usize=0; let mut dm:isize=0;
+	let mut res:isize=0;
+	while dm-dn<MAXPIN as isize {
+		steps+=1;
+		if steps>4*TRAP {break}
+		i=(ge.geta().geta().geta().geta().geta().lastbits(20)%(TS as isize)) as usize;
+		ge.mul(&mut table[i]);
+		dm+=distance[i];
+		if ge.equals(&mut t) {
+			res=dm-dn;
+			break;
+		}
+		if ge.equals(&mut gf) {
+			res=dn-dm;
+			break;
+		}
+
+	}
+	if steps>4*TRAP || dm-dn>=MAXPIN as isize {res=0 }    // Trap Failed  - probable invalid token
+	return res;
+}
+
+/* Hash the M-Pin transcript - new */
+
+pub fn hash_all(sha: usize,hid: &[u8],xid: &[u8],xcid: Option<&[u8]>,sec: &[u8],y: &[u8],r: &[u8],w: &[u8],h: &mut[u8]) -> bool {
+	let mut tlen:usize=0;
+	const RM:usize=big::MODBYTES as usize;	
+	let mut t: [u8;10*RM+4]=[0;10*RM+4];
+
+	for i in 0 .. hid.len() {t[i]=hid[i]}
+	tlen+=hid.len();
+
+	if let Some(rxcid)=xcid {
+		for i in 0..rxcid.len() {t[i+tlen]=rxcid[i]}
+		tlen+=rxcid.len();
+	} else {
+		for i in 0..xid.len() {t[i+tlen]=xid[i]}
+		tlen+=xid.len();
+	}	
+
+	for i in 0..sec.len() {t[i+tlen]=sec[i]}
+	tlen+=sec.len();		
+	for i in 0..y.len() {t[i+tlen]=y[i]}
+	tlen+=y.len();
+	for i in 0..r.len() {t[i+tlen]=r[i]}
+	tlen+=r.len();		
+	for i in 0..w.len() {t[i+tlen]=w[i]}
+	tlen+=w.len();	
+	if tlen!=10*RM+4 {return false}
+
+	return hashit(sha,0,&t,h);
+}
+
+/* calculate common key on client side */
+/* wCID = w.(A+AT) */
+#[allow(non_snake_case)]
+pub fn client_key(sha: usize,g1: &[u8],g2: &[u8],pin: usize,r: &[u8],x: &[u8],h: &[u8],wcid: &[u8],ck: &mut [u8]) -> isize {
+
+	let mut g1=FP48::frombytes(&g1);
+	let mut g2=FP48::frombytes(&g2);
+	let mut z=BIG::frombytes(&r);
+	let mut x=BIG::frombytes(&x);
+	let h=BIG::frombytes(&h);
+
+	let mut W=ECP::frombytes(&wcid);
+	if W.is_infinity() {return INVALID_POINT} 
+
+	W=pair256::g1mul(&mut W,&mut x);
+
+//	let mut f=FP2::new_bigs(&BIG::new_ints(&rom::FRA),&BIG::new_ints(&rom::FRB));
+	let mut r=BIG::new_ints(&rom::CURVE_ORDER);
+//	let q=BIG::new_ints(&rom::MODULUS);
+
+	z.add(&h);	//new
+	z.rmod(&mut r);
+
+	g2.pinpow(pin as i32,PBLEN);
+	g1.mul(&mut g2);
+
+	let mut c=g1.compow(&z,&mut r);
+
+
+	hash(sha,&mut c,&mut W,ck);
+
+	return 0
+}
+
+/* calculate common key on server side */
+/* Z=r.A - no time permits involved */
+#[allow(non_snake_case)]
+pub fn server_key(sha: usize,z: &[u8],sst: &[u8],w: &[u8],h: &[u8],hid: &[u8],xid: &[u8],xcid: Option<&[u8]>,sk: &mut [u8]) -> isize {
+	let sQ=ECP8::frombytes(&sst);
+	if sQ.is_infinity() {return INVALID_POINT} 
+	let mut R=ECP::frombytes(&z);
+	if R.is_infinity() {return INVALID_POINT} 
+	let mut A=ECP::frombytes(&hid);
+	if A.is_infinity() {return INVALID_POINT} 
+
+	let mut U=ECP::new();
+	if let Some(rxcid)=xcid {
+		U.copy(&ECP::frombytes(&rxcid));
+	} else {
+		U.copy(&ECP::frombytes(&xid));
+	}
+	
+	if U.is_infinity() {return INVALID_POINT} 
+
+	let mut w=BIG::frombytes(&w);
+	let mut h=BIG::frombytes(&h);
+	A=pair256::g1mul(&mut A,&mut h);	// new
+	R.add(&mut A); //R.affine();
+
+	U=pair256::g1mul(&mut U,&mut w);
+	let mut g=pair256::ate(&sQ,&R);
+	g=pair256::fexp(&g);
+
+	let mut c=g.trace();
+
+	hash(sha,&mut c,&mut U,sk);
+
+	return 0
+}
+
diff --git a/version3/rust/nhs.rs b/version3/rust/nhs.rs
new file mode 100644
index 0000000..5f14cf4
--- /dev/null
+++ b/version3/rust/nhs.rs
@@ -0,0 +1,511 @@
+/*
+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.
+*/
+
+/* NewHope Simple API high-level functions  */
+
+use sha3;
+use sha3::SHA3;
+use rand::RAND;
+
+const PRIME: i32=0x3001;	// q in Hex
+const LGN: usize=10;		// Degree n=2^LGN
+const ND: u32=0xF7002FFF;	// 1/(R-q) mod R
+const ONE: i32=0x2AC8;		// R mod q
+const R2MODP: u64=0x1620;	// R^2 mod q
+
+
+const DEGREE: usize=(1<<LGN);
+const WL: usize=32;
+
+const INV: i32=  0xeab;
+const INVPR: i32= 0x2c2a;
+
+const ROOTS : [i32;1024] =[0x2ac8,0x2baf,0x299b,0x685,0x2f04,0x158d,0x2d49,0x24b5,0x1edc,0xab3,0x2a95,0x24d,0x3cb,0x6a8,0x12f9,0x15ba,0x1861,0x2a89,0x1c5c,0xbe6,0xc1e,0x2024,0x207,0x19ce,0x2710,0x1744,0x18bc,0x2cd7,0x396,0x18d5,0x1c45,0xc4,0x21a6,0xe03,0x2b3c,0x2d91,0xc5d,0x432,0x1fbc,0xcae,0x2512,0x2979,0x3b2,0x714,0xb2e,0x1a97,0x1a03,0x1bcd,0x2216,0x2701,0xa,0x263c,0x1179,0x200c,0x2d08,0x1c34,0x291,0x2c99,0x2a5a,0x723,0xb1d,0x1ccc,0x1fb6,0x2f58,0x2bfe,0x1cda,0x2a0,0x5f1,0x2de,0x1fc7,0x1ea8,0x1719,0x2fa7,0x27ec,0x20ff,0x12c0,0x1ac1,0x2232,0x2f9b,0xd3e,0x2aed,0x15f0,0x11e8,0xed0,0x26a,0x1de5,0xa3f,0xf43,0xebf,0x204e,0xac7,0x2d9c,0x5ea,0x25d1,0xb6,0x49c,0x995,0x2555,0x26e2,0x100,0x1878,0x5aa,0x2e10,0x271c,0xcb,0x1b4c,0x2fb8,0x25b7,0x1543,0x2c7b,0x241a,0x2223,0x20ca,0x24ed,0x137,0x1b65,0x1dc2,0x7c7,0x2ec3,0xd0c,0x1169,0x1c7a,0x1ea1,0xf89,0x2199,0x291d,0x1088,0x2046,0x256d,0x2bc7,0x2e9b,0x41f,0x1b55,0x2b38,0xd0,0x2e6a,0x1755,0x6bc,0x2724,0x3ba,0x222e,0x2c5c,0x2da5,0x213c,0x10fe,0x169a,0x1552,0x5d3,0x300,0x1b5d,0x1342,0x2004,0x256f,0x2039,0x667,0x23b5,0x1123,0xdb,0x2da0,0xe1e,0x2f54,0x2767,0x154a,0x40a,0x11d3,0x2821,0xc09,0x974,0x694,0xfbf,0x27ba,0x132,0x83f,0x2d06,0x10e,0x183f,0x29ae,0x28c3,0x2dc9,0x1144,0x2c70,0x2a4a,0xf3c,0x1e32,0x1171,0x1e43,0xdd4,0x2ddf,0x28d2,0xfac,0x3c4,0x2f19,0x10a6,0x2f7,0xe1d,0x828,0x138f,0x1332,0xfab,0xcf6,0x13f8,0x24a0,0x112d,0x2717,0x6e7,0x1044,0x36e,0xfe8,0x6a,0xba7,0x1d69,0x29ec,0x23b2,0xaee,0x16df,0x1068,0x1a7e,0x253f,0x24c,0xb33,0x2683,0x15ce,0x1ad3,0x1a36,0xc96,0xaea,0x260a,0xce,0x28b1,0xe4f,0x2b11,0x5f8,0x1fc4,0xe77,0x2366,0x11f9,0x153c,0x24eb,0x20cd,0x1398,0x22,0x2b97,0x249b,0x8eb,0x12b2,0x2fe3,0x29c1,0x1b00,0x2663,0xeaa,0x2e06,0xe0,0x1569,0x10f5,0x284e,0xa38,0x201d,0x1c53,0x1681,0x1f6f,0x2f95,0x2fe8,0xacb,0x1680,0x17fd,0x2c39,0x165a,0x10bb,0x29d8,0x2622,0x1196,0x884,0x2a79,0x140e,0x2d80,0x6fa,0x11b2,0x26c4,0x355,0x1054,0x29e9,0x23ed,0xbe3,0x24fa,0x1fb3,0x10ac,0x2919,0x2584,0x10a4,0xe85,0x650,0x1893,0x1dc1,0xd8e,0x12dc,0x2d42,0x284d,0xfff,0x250f,0xacd,0x13c3,0x6cc,0x1a79,0x1221,0x2614,0x270a,0x1ea,0x155,0x2818,0x222c,0x2e5b,0x25d8,0x1dbf,0x191c,0xb0f,0xdac,0x1082,0x12ef,0x11b6,0xfa8,0x2b72,0x159d,0x209e,0x31b,0x2c7c,0x14f7,0xe09,0x1bb2,0x1ec7,0x2404,0x20ae,0x6ad,0xed6,0x2b70,0x1c7b,0x18d1,0x2732,0x12da,0xd56,0x5c1,0x1648,0x18b7,0x1605,0x1bc4,0x280,0x2ece,0xc,0x1aae,0x1c4,0x1cdb,0x22d6,0x21d8,0x257c,0x51f,0x211b,0xff,0x2ee0,0x2585,0xe1,0x2c35,0x26db,0x2971,0x2208,0x17e1,0x21be,0x135e,0x28d6,0x2891,0x1689,0x2138,0xb86,0x2e3a,0x1204,0x2d10,0x2324,0xf3f,0x2508,0x33d,0xcb2,0x292a,0xe27,0x2e64,0x29f8,0x2d46,0x9b7,0x20eb,0x1b7c,0x9eb,0x2b2a,0x58c,0x27d0,0x121b,0x272e,0x29f6,0x2dbd,0x2697,0x2aac,0xd6f,0x1c67,0x2c5b,0x108d,0x363,0x249d,0x2d5e,0x2fd,0x2cb2,0x1f8f,0x20a4,0xa19,0x2ac9,0x19b1,0x1581,0x17a2,0x29eb,0x1b72,0x13b0,0xee4,0xa8f,0x2315,0x5e6,0x951,0x2e29,0xdad,0x1f2b,0x224e,0x37f,0x1a72,0xa91,0x1407,0x2df9,0x3ad,0x23f7,0x1a24,0x1d2a,0x234b,0x1df3,0x1143,0x7ff,0x1a6d,0x2774,0x2690,0x2ab5,0x586,0x2781,0x2009,0x2fdd,0x2881,0x399,0x2fb6,0x144,0x137f,0xfa0,0x2e4c,0x1c7f,0x2fac,0xb09,0x1264,0x127b,0x198c,0x2b40,0x230,0x1cf4,0x180b,0xb58,0x144a,0x2aec,0xfb,0x2602,0x14ee,0x783,0x1098,0x23d8,0x203,0xe9,0x108a,0x14b8,0xeec,0xc58,0x1248,0x243c,0x28aa,0x6bf,0x27c4,0x276e,0x19b8,0x1d11,0x2e16,0x472,0x1464,0x24b9,0x662,0x1097,0x2067,0x20d6,0x171c,0x4,0x682,0x17bb,0x1186,0x4f2,0x3ff,0x2a43,0x1dc7,0x1ae5,0x8cc,0x2e7c,0x2ef8,0x2ae0,0x2904,0xed4,0x6c5,0x14ae,0xb72,0x11c3,0x337,0x2da3,0x2916,0x6d8,0x1cf9,0x10ee,0x1800,0x1ae4,0xa0d,0x101b,0x1a8d,0x2e98,0x24cd,0x813,0x1aa4,0x9b9,0x680,0x2349,0x24d1,0x20f8,0xe31,0x249f,0x216b,0x12d9,0x1d21,0x19db,0x191a,0x1dd0,0x5df,0x55c,0x2b86,0x213,0xe9e,0x1ef1,0x268a,0x1d5e,0x1e20,0x28c1,0x1379,0x249,0x19de,0x18b,0x1e41,0x2a1e,0x2612,0x297,0x2e96,0x2102,0x46,0x1b9f,0x1a4d,0x2050,0x1b32,0x568,0x11f7,0x1829,0x870,0x1f4,0x1dca,0x990,0x1df6,0x2b62,0x13ec,0x9f2,0x1260,0x2997,0x1412,0x1e6d,0x1694,0x11ac,0x2d8b,0x276f,0x26f5,0x233e,0x2b44,0x2f5a,0x2d37,0x2cb1,0xc75,0x98d,0x1d56,0x7ae,0x10e6,0x113f,0x17b8,0xad3,0x737,0x221e,0x1b70,0x1f3e,0x2966,0x18b2,0x4fa,0x2044,0x1312,0x154e,0x2029,0x700,0x1b45,0x27a6,0x226a,0x21bf,0x58d,0x2f11,0x2e02,0x17fc,0x4d2,0x1757,0xcb1,0x2ef1,0x2582,0x1276,0x881,0x2fc0,0x104a,0x670,0x274f,0x2b53,0x19dd,0x752,0x1663,0xcbd,0x2b2b,0x2fc6,0x13b6,0x21e6,0x15f6,0x126b,0x2637,0x1cd9,0x2f50,0xe82,0x5b0,0x24e0,0x1350,0x2f24,0x21f7,0x1a16,0x2f3e,0x167e,0x1f7d,0x28a0,0x16f0,0xe33,0x53b,0x28c5,0x1500,0x2f88,0x26cc,0x2018,0x1604,0x218b,0x2cd1,0x9ee,0x17f3,0x5fd,0x1f5a,0x2d0,0x2b46,0x23cc,0x503,0x1c46,0x1cc3,0x28e2,0x243e,0x122b,0x2e0c,0xe37,0x2611,0x85e,0x9b8,0x1b24,0x762,0x19b6,0x3bc,0x2d50,0x2079,0x18da,0x170a,0x800,0xaa2,0x135a,0x1a15,0x13d1,0xca,0x2113,0x2db9,0xdb2,0x1a5c,0x29a9,0x1488,0x14c1,0x2c9,0x917,0x28e7,0x265c,0xdab,0x2ab9,0x2bc6,0x105b,0x1839,0x219c,0x50,0x11da,0x1802,0xf56,0x2e6,0x2190,0xddb,0x56e,0x9d9,0x1c81,0x1016,0x12d6,0x296f,0x14b4,0x1014,0x1e64,0x1d90,0x89f,0x2bc2,0x2777,0x2819,0x1c65,0x1a41,0x5a2,0x2cd2,0x427,0xd71,0x29c8,0x1e58,0x53f,0x7c5,0x1dcd,0x4a1,0x1268,0x2597,0x2926,0xee,0x111b,0x1038,0xe6c,0x22dc,0x2f2f,0x441,0x2cfd,0x1cb0,0x6a4,0x2224,0x620,0x5dc,0x16b1,0x2a1d,0x1787,0x20c7,0x641,0xd84,0x1c05,0x2d0d,0x2f52,0x1b8c,0xd7d,0x17e8,0x1589,0xc73,0x151b,0x4e2,0x1ae9,0x1b18,0xb9b,0x949,0x2c60,0x1e7a,0xd5,0x1bdc,0x1f57,0x1753,0x124a,0x559,0xb76,0x2334,0x12d1,0x1de1,0x14b2,0x2faa,0x1697,0x147a,0x5a1,0x2c30,0x1c02,0x1043,0x2ee1,0x2402,0x1cc8,0x2a16,0xff7,0x1364,0x1b9a,0x2a53,0x2f94,0x294c,0x1ee5,0x1a87,0x2141,0xd66,0x953,0x28a3,0x2f30,0x2477,0x18e3,0x1035,0x1fc1,0x1d68,0x2fb3,0x138c,0x2487,0x1bf8,0xd96,0x1018,0x748,0x244e,0x15bd,0x175e,0x2be,0x23d,0x1da,0x176d,0xc17,0x24be,0x2ebb,0x7d8,0x100a,0x759,0x1db4,0x2259,0x23f4,0x2d59,0x2847,0xbf5,0x1cfe,0xa20,0x258,0x1180,0x279c,0x54,0x2abf,0xc5c,0x9f9,0x3d5,0x2ce4,0x165f,0x23d9,0x27b9,0x6f9,0x281a,0x169e,0x627,0x156d,0x1ff8,0x211,0x2e34,0x1724,0x2c2e,0x2790,0x2dd5,0x2bf2,0xdbc,0x2884,0x20a9,0x2390,0x1e1a,0x1b6a,0x5f7,0xab7,0x1333,0x16ab,0x28dd,0x20,0x30f,0x24b6,0x5c2,0x1ce4,0x1400,0x2669,0x60,0x156c,0xe20,0x26d4,0x26ab,0x1ebb,0x223d,0x5b4,0x2025,0x1e1c,0xaae,0x2e08,0x6cd,0x1677,0x13d9,0x17b5,0x1046,0x1d8c,0x14eb,0x18d8,0x1ce5,0x2478,0x16ae,0xb79,0x23d4,0x684,0x156b,0x567,0x1a,0x29ce,0x83a,0x19e8,0x58e,0x294a,0x1136,0x2319,0x2fba,0x1a29,0x1d,0x1879,0x291b,0x19f6,0x2c2f,0x21c9,0x19bb,0xbbc,0x26f9,0xc22,0x708,0x11a1,0x18d3,0x7f8,0x28f8,0x2427,0x1deb,0xaed,0x26aa,0x2482,0x203b,0x2f05,0x2b82,0x192f,0x2df4,0x8dc,0x2877,0xd5e,0x240e,0x775,0x2dae,0x1d3e,0x20ba,0x215b,0x22d1,0xeba,0xf50,0xaa8,0x184a,0x1f67,0x2e04,0xc6e,0x6dd,0x1a09,0x27f,0x494,0x1426,0xae3,0xe15,0x65f,0x13c4,0x105,0x872,0x2667,0x1ff6,0xd9f,0x2ca1,0x2f39,0x2657,0x23fd,0x2405,0xb73,0x2294,0x1f1e,0x2eba,0x110a,0x2cae,0x141f,0x22cd,0x25d6,0x11c1,0x1c,0x2d8e,0x161a,0x1aa8,0x229e,0x1bf9,0x7cf,0x106d,0x2c40,0xd93,0x255e,0x28c2,0xc1a,0x2f17,0x7ca,0x2f63,0xbf];
+const IROOTS : [i32;1024] =[0x2ac8,0x452,0x297c,0x666,0xb4c,0x2b8,0x1a74,0xfd,0x1a47,0x1d08,0x2959,0x2c36,0x2db4,0x56c,0x254e,0x1125,0x2f3d,0x13bc,0x172c,0x2c6b,0x32a,0x1745,0x18bd,0x8f1,0x1633,0x2dfa,0xfdd,0x23e3,0x241b,0x13a5,0x578,0x17a0,0xa9,0x104b,0x1335,0x24e4,0x28de,0x5a7,0x368,0x2d70,0x13cd,0x2f9,0xff5,0x1e88,0x9c5,0x2ff7,0x900,0xdeb,0x1434,0x15fe,0x156a,0x24d3,0x28ed,0x2c4f,0x688,0xaef,0x2353,0x1045,0x2bcf,0x23a4,0x270,0x4c5,0x21fe,0xe5b,0xfbb,0x1f79,0x6e4,0xe68,0x2078,0x1160,0x1387,0x1e98,0x22f5,0x13e,0x283a,0x123f,0x149c,0x2eca,0xb14,0xf37,0xdde,0xbe7,0x386,0x1abe,0xa4a,0x49,0x14b5,0x2f36,0x8e5,0x1f1,0x2a57,0x1789,0x2f01,0x91f,0xaac,0x266c,0x2b65,0x2f4b,0xa30,0x2a17,0x265,0x253a,0xfb3,0x2142,0x20be,0x25c2,0x121c,0x2d97,0x2131,0x1e19,0x1a11,0x514,0x22c3,0x66,0xdcf,0x1540,0x1d41,0xf02,0x815,0x5a,0x18e8,0x1159,0x103a,0x2d23,0x2a10,0x2d61,0x1327,0x403,0x25c9,0x7b3,0x1f0c,0x1a98,0x2f21,0x1fb,0x2157,0x99e,0x1501,0x640,0x1e,0x1d4f,0x2716,0xb66,0x46a,0x2fdf,0x1c69,0xf34,0xb16,0x1ac5,0x1e08,0xc9b,0x218a,0x103d,0x2a09,0x4f0,0x21b2,0x750,0x2f33,0x9f7,0x2517,0x236b,0x15cb,0x152e,0x1a33,0x97e,0x24ce,0x2db5,0xac2,0x1583,0x1f99,0x1922,0x2513,0xc4f,0x615,0x1298,0x245a,0x2f97,0x2019,0x2c93,0x1fbd,0x291a,0x8ea,0x1ed4,0xb61,0x1c09,0x230b,0x2056,0x1ccf,0x1c72,0x27d9,0x21e4,0x2d0a,0x1f5b,0xe8,0x2c3d,0x2055,0x72f,0x222,0x222d,0x11be,0x1e90,0x11cf,0x20c5,0x5b7,0x391,0x1ebd,0x238,0x73e,0x653,0x17c2,0x2ef3,0x2fb,0x27c2,0x2ecf,0x847,0x2042,0x296d,0x268d,0x23f8,0x7e0,0x1e2e,0x2bf7,0x1ab7,0x89a,0xad,0x21e3,0x261,0x2f26,0x1ede,0xc4c,0x299a,0xfc8,0xa92,0xffd,0x1cbf,0x14a4,0x2d01,0x2a2e,0x1aaf,0x1967,0x1f03,0xec5,0x25c,0x3a5,0xdd3,0x2c47,0x8dd,0x2945,0x18ac,0x197,0x2f31,0x4c9,0x14ac,0x2be2,0x166,0x43a,0xa94,0x1b53,0x293c,0x212d,0x6fd,0x521,0x109,0x185,0x2735,0x151c,0x123a,0x5be,0x2c02,0x2b0f,0x1e7b,0x1846,0x297f,0x2ffd,0x18e5,0xf2b,0xf9a,0x1f6a,0x299f,0xb48,0x1b9d,0x2b8f,0x1eb,0x12f0,0x1649,0x893,0x83d,0x2942,0x757,0xbc5,0x1db9,0x23a9,0x2115,0x1b49,0x1f77,0x2f18,0x2dfe,0xc29,0x1f69,0x287e,0x1b13,0x9ff,0x2f06,0x515,0x1bb7,0x24a9,0x17f6,0x130d,0x2dd1,0x4c1,0x1675,0x1d86,0x1d9d,0x24f8,0x55,0x1382,0x1b5,0x2061,0x1c82,0x2ebd,0x4b,0x2c68,0x780,0x24,0xff8,0x880,0x2a7b,0x54c,0x971,0x88d,0x1594,0x2802,0x1ebe,0x120e,0xcb6,0x12d7,0x15dd,0xc0a,0x2c54,0x208,0x1bfa,0x2570,0x158f,0x2c82,0xdb3,0x10d6,0x2254,0x1d8,0x26b0,0x2a1b,0xcec,0x2572,0x211d,0x1c51,0x148f,0x616,0x185f,0x1a80,0x1650,0x538,0x25e8,0xf5d,0x1072,0x34f,0x2d04,0x2a3,0xb64,0x2c9e,0x1f74,0x3a6,0x139a,0x2292,0x555,0x96a,0x244,0x60b,0x8d3,0x1de6,0x831,0x2a75,0x4d7,0x2616,0x1485,0xf16,0x264a,0x2bb,0x609,0x19d,0x21da,0x6d7,0x234f,0x2cc4,0xaf9,0x20c2,0xcdd,0x2f1,0x1dfd,0x1c7,0x247b,0xec9,0x1978,0x770,0x72b,0x1ca3,0xe43,0x1820,0xdf9,0x690,0x926,0x3cc,0x2f20,0xa7c,0x121,0x2f02,0xee6,0x2ae2,0xa85,0xe29,0xd2b,0x1326,0x2e3d,0x1553,0x2ff5,0x133,0x2d81,0x143d,0x19fc,0x174a,0x19b9,0x2a40,0x22ab,0x1d27,0x8cf,0x1730,0x1386,0x491,0x212b,0x2954,0xf53,0xbfd,0x113a,0x144f,0x21f8,0x1b0a,0x385,0x2ce6,0xf63,0x1a64,0x48f,0x2059,0x1e4b,0x1d12,0x1f7f,0x2255,0x24f2,0x16e5,0x1242,0xa29,0x1a6,0xdd5,0x7e9,0x2eac,0x2e17,0x8f7,0x9ed,0x1de0,0x1588,0x2935,0x1c3e,0x2534,0xaf2,0x2002,0x7b4,0x2bf,0x1d25,0x2273,0x1240,0x176e,0x29b1,0x217c,0x1f5d,0xa7d,0x6e8,0x1f55,0x104e,0xb07,0x241e,0xc14,0x618,0x1fad,0x2cac,0x93d,0x1e4f,0x2907,0x281,0x1bf3,0x588,0x277d,0x1e6b,0x9df,0x629,0x1f46,0x19a7,0x3c8,0x1804,0x1981,0x2536,0x19,0x6c,0x1092,0x1980,0x13ae,0xfe4,0x2f42,0x9e,0x2837,0xea,0x23e7,0x73f,0xaa3,0x226e,0x3c1,0x1f94,0x2832,0x1408,0xd63,0x1559,0x19e7,0x273,0x2fe5,0x1e40,0xa2b,0xd34,0x1be2,0x353,0x1ef7,0x147,0x10e3,0xd6d,0x248e,0xbfc,0xc04,0x9aa,0xc8,0x360,0x2262,0x100b,0x99a,0x278f,0x2efc,0x1c3d,0x29a2,0x21ec,0x251e,0x1bdb,0x2b6d,0x2d82,0x15f8,0x2924,0x2393,0x1fd,0x109a,0x17b7,0x2559,0x20b1,0x2147,0xd30,0xea6,0xf47,0x12c3,0x253,0x288c,0xbf3,0x22a3,0x78a,0x2725,0x20d,0x16d2,0x47f,0xfc,0xfc6,0xb7f,0x957,0x2514,0x1216,0xbda,0x709,0x2809,0x172e,0x1e60,0x28f9,0x23df,0x908,0x2445,0x1646,0xe38,0x3d2,0x160b,0x6e6,0x1788,0x2fe4,0x15d8,0x47,0xce8,0x1ecb,0x6b7,0x2a73,0x1619,0x27c7,0x633,0x2fe7,0x2a9a,0x1a96,0x297d,0xc2d,0x2488,0x1953,0xb89,0x131c,0x1729,0x1b16,0x1275,0x1fbb,0x184c,0x1c28,0x198a,0x2934,0x1f9,0x2553,0x11e5,0xfdc,0x2a4d,0xdc4,0x1146,0x956,0x92d,0x21e1,0x1a95,0x2fa1,0x998,0x1c01,0x131d,0x2a3f,0xb4b,0x2cf2,0x2fe1,0x724,0x1956,0x1cce,0x254a,0x2a0a,0x1497,0x11e7,0xc71,0xf58,0x77d,0x2245,0x40f,0x22c,0x871,0x3d3,0x18dd,0x1cd,0x2df0,0x1009,0x1a94,0x29da,0x1963,0x7e7,0x2908,0x848,0xc28,0x19a2,0x31d,0x2c2c,0x2608,0x23a5,0x542,0x2fad,0x865,0x1e81,0x2da9,0x25e1,0x1303,0x240c,0x7ba,0x2a8,0xc0d,0xda8,0x124d,0x28a8,0x1ff7,0x2829,0x146,0xb43,0x23ea,0x1894,0x2e27,0x2dc4,0x2d43,0x18a3,0x1a44,0xbb3,0x28b9,0x1fe9,0x226b,0x1409,0xb7a,0x1c75,0x4e,0x1299,0x1040,0x1fcc,0x171e,0xb8a,0xd1,0x75e,0x26ae,0x229b,0xec0,0x157a,0x111c,0x6b5,0x6d,0x5ae,0x1467,0x1c9d,0x200a,0x5eb,0x1339,0xbff,0x120,0x1fbe,0x13ff,0x3d1,0x2a60,0x1b87,0x196a,0x57,0x1b4f,0x1220,0x1d30,0xccd,0x248b,0x2aa8,0x1db7,0x18ae,0x10aa,0x1425,0x2f2c,0x1187,0x3a1,0x26b8,0x2466,0x14e9,0x1518,0x2b1f,0x1ae6,0x238e,0x1a78,0x1819,0x2284,0x1475,0xaf,0x2f4,0x13fc,0x227d,0x29c0,0xf3a,0x187a,0x5e4,0x1950,0x2a25,0x29e1,0xddd,0x295d,0x1351,0x304,0x2bc0,0xd2,0xd25,0x2195,0x1fc9,0x1ee6,0x2f13,0x6db,0xa6a,0x1d99,0x2b60,0x1234,0x283c,0x2ac2,0x11a9,0x639,0x2290,0x2bda,0x32f,0x2a5f,0x15c0,0x139c,0x7e8,0x88a,0x43f,0x2762,0x1271,0x119d,0x1fed,0x1b4d,0x692,0x1d2b,0x1feb,0x1380,0x2628,0x2a93,0x2226,0xe71,0x2d1b,0x20ab,0x17ff,0x1e27,0x2fb1,0xe65,0x17c8,0x1fa6,0x43b,0x548,0x2256,0x9a5,0x71a,0x26ea,0x2d38,0x1b40,0x1b79,0x658,0x15a5,0x224f,0x248,0xeee,0x2f37,0x1c30,0x15ec,0x1ca7,0x255f,0x2801,0x18f7,0x1727,0xf88,0x2b1,0x2c45,0x164b,0x289f,0x14dd,0x2649,0x27a3,0x9f0,0x21ca,0x1f5,0x1dd6,0xbc3,0x71f,0x133e,0x13bb,0x2afe,0xc35,0x4bb,0x2d31,0x10a7,0x2a04,0x180e,0x2613,0x330,0xe76,0x19fd,0xfe9,0x935,0x79,0x1b01,0x73c,0x2ac6,0x21ce,0x1911,0x761,0x1084,0x1983,0xc3,0x15eb,0xe0a,0xdd,0x1cb1,0xb21,0x2a51,0x217f,0xb1,0x1328,0x9ca,0x1d96,0x1a0b,0xe1b,0x1c4b,0x3b,0x4d6,0x2344,0x199e,0x28af,0x1624,0x4ae,0x8b2,0x2991,0x1fb7,0x41,0x2780,0x1d8b,0xa7f,0x110,0x2350,0x18aa,0x2b2f,0x1805,0x1ff,0xf0,0x2a74,0xe42,0xd97,0x85b,0x14bc,0x2901,0xfd8,0x1ab3,0x1cef,0xfbd,0x2b07,0x174f,0x69b,0x10c3,0x1491,0xde3,0x28ca,0x252e,0x1849,0x1ec2,0x1f1b,0x2853,0x12ab,0x2674,0x238c,0x350,0x2ca,0xa7,0x4bd,0xcc3,0x90c,0x892,0x276,0x1e55,0x196d,0x1194,0x1bef,0x66a,0x1da1,0x260f,0x1c15,0x49f,0x120b,0x2671,0x1237,0x2e0d,0x2791,0x17d8,0x1e0a,0x2a99,0x14cf,0xfb1,0x15b4,0x1462,0x2fbb,0xeff,0x16b,0x2d6a,0x9ef,0x5e3,0x11c0,0x2e76,0x1623,0x2db8,0x1c88,0x740,0x11e1,0x12a3,0x977,0x1110,0x2163,0x2dee,0x47b,0x2aa5,0x2a22,0x1231,0x16e7,0x1626,0x12e0,0x1d28,0xe96,0xb62,0x21d0,0xf09,0xb30,0xcb8,0x2981,0x2648,0x155d,0x27ee,0xb34,0x169,0x1574,0x1fe6,0x25f4,0x151d,0x1801,0x1f13,0x1308,0x2929,0x6eb,0x25e,0x2cca,0x1e3e,0x248f];
+
+fn round(a: i32,b: i32) -> i32 {
+		return (a+b/2)/b;
+}
+
+/* Constant time absolute value */
+fn nabs(x: i32) -> i32 {
+		let mask=x>>31;
+		return (x+mask)^mask;		
+}
+
+/* Montgomery stuff */
+
+fn redc(t: u64) -> i32 {
+		let m=(t as u32).wrapping_mul(ND);
+		return (((m as u64)*(PRIME as u64)+t)>>WL) as i32;		
+}
+
+fn nres(x: i32) -> i32  {
+		return redc((x as u64)*R2MODP)
+}
+
+fn modmul(a: i32,b: i32) -> i32  {
+		return redc((a as u64)*(b as u64));
+}
+
+/* Cooley-Tukey NTT */
+fn ntt(x: &mut [i32])  {
+	let mut t=DEGREE/2;
+	let q=PRIME;
+
+/* Convert to Montgomery form */
+	for j in 0..DEGREE {x[j]=nres(x[j])}
+	let mut m=1;
+	while m<DEGREE {
+		let mut k=0;
+		for i in 0..m {
+			let s=ROOTS[m+i];
+			for j in k..k+t {
+				let u=x[j];
+				let v=modmul(x[j+t],s);
+				x[j]=u+v;
+				x[j+t]=u+2*q-v;
+			}
+			k+=2*t;
+		}
+		t/=2;
+		m*=2;
+	}
+}
+
+/* Gentleman-Sande INTT */
+
+fn intt(x: &mut [i32]) {
+	let mut t=1;
+	let q=PRIME;
+	let mut m=DEGREE/2;
+	while m>1 {
+		let mut k=0;
+		for i in 0..m {
+			let s=IROOTS[m+i];
+			for j in k..k+t {	
+				let u=x[j]; 
+				let v=x[j+t];
+				x[j]=u+v;
+				let w=u+(DEGREE as i32)*q-v;
+				x[j+t]=modmul(w,s);
+			}
+			k+=2*t;
+		}
+		t*=2;
+		m/=2;
+	}
+
+/* Last iteration merged with n^-1 */
+	t=DEGREE/2;
+	for j in 0..t {
+		let u=x[j];
+		let v=x[j+t];
+		let w=u+(DEGREE as i32)*q-v; 
+		x[j+t]=modmul(w,INVPR);
+		x[j]=modmul(u+v,INV);
+	}
+/* convert back from Montgomery to "normal" form */
+	for j in 0..DEGREE {
+		x[j]=redc(x[j] as u64);
+		x[j]-=q;
+		x[j]+=(x[j]>>(WL-1))&q;		
+	} 
+}
+
+/* See https://eprint.iacr.org/2016/1157.pdf */ 
+
+fn encode(key: &[u8],poly: &mut [i32]) {
+	let q2=PRIME/2;
+	let mut j=0;
+	let mut i=0;
+	while i<256  {
+		let mut kj=key[j];
+		j+=1;
+		for _ in 0..8 {
+			let b=(kj&1) as i32;
+			poly[i]=b*q2;
+			poly[i+256]=b*q2;
+			poly[i+512]=b*q2;
+			poly[i+768]=b*q2;
+			kj>>=1;
+			i+=1;
+		}
+	}			
+}
+
+fn decode(poly: &[i32],key: &mut [u8]) {
+	let q2=PRIME/2;
+	for i in 0..32 {
+		key[i]=0;
+	}
+
+	let mut i=0;
+	let mut j=0;
+	while i<256 {
+		for _ in 0..8 {
+			let t=nabs(poly[i]-q2)+nabs(poly[i+256]-q2)+nabs(poly[i+512]-q2)+nabs(poly[i+768]-q2);
+			let mut b=t-PRIME;
+			b=(b>>31)&1;
+			key[j]=(key[j]>>1)+((b<<7) as u8);
+			i+=1;
+		}
+		j+=1;
+	}
+}
+
+/* convert 32-byte seed to random polynomial */
+
+fn parse(seed: &[u8],poly: &mut[i32]) {
+	let mut hash:[u8;4*DEGREE]=[0;4*DEGREE];
+	let mut sh=SHA3::new(sha3::SHAKE128);
+	for i in 0..32 {
+		sh.process(seed[i])
+	}
+	sh.shake(&mut hash,4*DEGREE);
+
+	let mut j=0;
+	for i in 0..DEGREE {
+		let mut n=(hash[j]&0x7f) as i32; n<<=8;
+		n+=(hash[j+1]) as i32; n<<=8;
+		n+=(hash[j+2]) as i32; n<<=8;
+		n+=(hash[j+3]) as i32; j+=4;
+		poly[i]=nres(n);
+		//poly[i]=modmul(n,ONE); // reduce 31-bit random number mod q
+	}
+} 
+
+/* Compress 14 bits polynomial coefficients into byte array */
+/* 7 bytes is 3x14 */
+
+fn nhs_pack(poly: &[i32],array: &mut [u8]) {
+	let mut j=0;
+	let mut i=0;
+	while i<DEGREE  {
+		let a=poly[i]; let b=poly[i+1]; let c=poly[i+2]; let d=poly[i+3]; i+=4;
+		array[j]=(a&0xff) as u8;
+		array[j+1]=(((a>>8)|(b<<6))&0xff) as u8;
+		array[j+2]=((b>>2)&0xff) as u8;
+		array[j+3]=(((b>>10)|(c<<4))&0xff) as u8;
+		array[j+4]=((c>>4)&0xff) as u8;
+		array[j+5]=(((c>>12)|(d<<2))&0xff) as u8;
+		array[j+6]=(d>>6) as u8;
+		j+=7;
+	}
+}
+
+fn nhs_unpack(array: &[u8],poly: &mut [i32]) {
+	let mut j=0;
+	let mut i=0;
+	while i<DEGREE {
+		let a=((array[j])&0xff) as i32; let b=((array[j+1])&0xff) as i32; let c=((array[j+2])&0xff) as i32; let d=((array[j+3])&0xff) as i32; let e=((array[j+4])&0xff) as i32; let f=((array[j+5])&0xff) as i32; let g=((array[j+6])&0xff) as i32; j+=7;
+		poly[i]=a|((b&0x3f)<<8);
+		poly[i+1]=(b>>6)|(c<<2)|((d&0xf)<<10);
+		poly[i+2]=(d>>4)|(e<<4)|((f&3)<<12);
+		poly[i+3]=(f>>2)|(g<<6);
+		i+=4;
+	}
+}
+
+/* See https://eprint.iacr.org/2016/1157.pdf */ 
+
+fn compress(poly: &[i32],array: &mut [u8]) {
+	let mut col=0 as i32;
+	let mut j=0;
+	let mut i=0;
+	while i<DEGREE  {
+		for _ in 0..8  {
+			let b=round(poly[i]*8,PRIME)&7; 
+			col=(col<<3)+b;
+			i+=1;
+		}
+		array[j]=(col&0xff) as u8;
+		array[j+1]=((col>>8)&0xff) as u8;
+		array[j+2]=((col>>16)&0xff) as u8;
+		j+=3; col=0;
+	}
+}
+
+fn decompress(array: &[u8],poly: &mut [i32]) {
+	let mut j=0;
+	let mut i=0;
+	while i<DEGREE  {
+		let mut col=(array[j+2] as i32)&0xff;
+		col=(col<<8)+((array[j+1] as i32)&0xff);
+		col=(col<<8)+((array[j] as i32)&0xff);
+		j+=3;
+		for _ in 0..8 {
+			let b=(col&0xe00000)>>21; col<<=3;
+			poly[i]=round(b*PRIME,8);
+			i+=1;
+		}
+	}
+}
+
+/* generate centered binomial distribution */ 
+
+fn error(rng: &mut RAND,poly: &mut [i32]) {
+	for i in 0..DEGREE {
+		let mut n1=((rng.getbyte() as i32)&0xff)+(((rng.getbyte() as i32)&0xff)<<8);
+		let mut n2=((rng.getbyte() as i32)&0xff)+(((rng.getbyte() as i32)&0xff)<<8);
+		let mut r=0 as i32;
+		for _ in 0..16 {
+			r+=(n1&1)-(n2&1);
+			n1>>=1; n2>>=1;
+		}
+		poly[i]=r+PRIME;
+	}
+}
+
+
+fn redc_it(p: &mut [i32]) {
+	for i in 0..DEGREE {
+		p[i]=redc(p[i] as u64);
+	}
+}
+
+fn nres_it(p: &mut [i32]) {
+	for i in 0..DEGREE {
+		p[i]=nres(p[i]);
+	}
+}
+
+fn poly_mul(p1: &mut [i32],p3: &[i32]) {
+	for i in 0..DEGREE {
+		p1[i]=modmul(p1[i],p3[i]);
+	}
+}
+
+fn poly_add(p1: &mut [i32],p3: &[i32]) {
+	for i in 0..DEGREE {
+		p1[i]=p1[i]+p3[i];
+	}
+}
+
+fn poly_rsub(p1: &mut [i32],p2: &[i32]) {
+	for i in 0..DEGREE {
+		p1[i]=p2[i]+PRIME-p1[i];
+	}
+}
+
+/* reduces inputs < 2q */
+fn poly_soft_reduce(poly: &mut [i32]) {
+	for i in 0..DEGREE {
+		let e=poly[i]-PRIME;
+		poly[i]=e+((e>>(WL-1))&PRIME);
+	}
+}
+
+/* fully reduces modulo q */
+fn poly_hard_reduce(poly: &mut [i32]) {
+	for i in 0..DEGREE {
+		let mut e=modmul(poly[i],ONE);
+		e=e-PRIME;
+		poly[i]=e+((e>>(WL-1))&PRIME);
+	}
+}
+
+/* API files */
+
+pub fn server_1(mut rng: &mut RAND,sb: &mut [u8],ss: &mut [u8]) {
+	let mut seed:[u8;32]=[0;32];
+	let mut array:[u8;1792]=[0;1792];
+	let mut s:[i32;DEGREE]=[0;DEGREE];
+	let mut e:[i32;DEGREE]=[0;DEGREE];
+	let mut b:[i32;DEGREE]=[0;DEGREE];		
+
+	for i in 0..32 {
+		seed[i]=rng.getbyte();
+	}
+
+	parse(&seed,&mut b);
+
+	error(&mut rng,&mut e);
+	error(&mut rng,&mut s);
+
+	ntt(&mut s);
+	ntt(&mut e);
+	poly_mul(&mut b,&s);
+	poly_add(&mut b,&e);
+	poly_hard_reduce(&mut b);
+
+	redc_it(&mut b);
+	nhs_pack(&b,&mut array);
+
+	for i in 0..32 {
+		sb[i]=seed[i];
+	}
+
+	for i in 0..1792 {
+		sb[i+32]=array[i];
+	}
+
+	poly_hard_reduce(&mut s);
+	nhs_pack(&s,&mut array);
+
+	for i in 0..1792 {
+		ss[i]=array[i];
+	}
+}
+
+pub fn client(mut rng: &mut RAND,sb: &[u8],uc: &mut [u8],okey: &mut [u8]) {
+	let mut sh=SHA3::new(sha3::HASH256);	
+	
+	let mut seed:[u8;32]=[0;32];
+	let mut array:[u8;1792]=[0;1792];
+	let mut key:[u8;32]=[0;32];
+	let mut cc:[u8;384]=[0;384];
+
+	let mut sd:[i32;DEGREE]=[0;DEGREE];
+	let mut ed:[i32;DEGREE]=[0;DEGREE];
+	let mut u:[i32;DEGREE]=[0;DEGREE];		
+	let mut k:[i32;DEGREE]=[0;DEGREE];
+	let mut c:[i32;DEGREE]=[0;DEGREE];		
+
+	error(&mut rng,&mut sd);
+	error(&mut rng,&mut ed);
+
+	ntt(&mut sd);
+	ntt(&mut ed);
+
+	for i in 0..32 {
+		seed[i]=sb[i];
+	}
+
+	for i in 0..1792 {
+		array[i]=sb[i+32];
+	}
+
+	parse(&seed,&mut u);
+
+	poly_mul(&mut u,&sd);
+	poly_add(&mut u,&ed);
+	poly_hard_reduce(&mut u);
+
+	for i in 0..32 {
+		key[i]=rng.getbyte();
+	}
+
+	for i in 0..32 {
+		sh.process(key[i]);
+	}
+	sh.hash(&mut key);
+
+	encode(&key,&mut k);
+
+	nhs_unpack(&array,&mut c);
+	nres_it(&mut c);
+
+	poly_mul(&mut c,&sd);
+	intt(&mut c);
+	error(&mut rng,&mut ed);
+	poly_add(&mut c,&ed);
+	poly_add(&mut c,&k);
+
+	compress(&c,&mut cc);
+
+	sh=SHA3::new(sha3::HASH256);
+	for i in 0..32 {
+		sh.process(key[i]);
+	}
+	sh.hash(&mut key);
+
+	for i in 0..32 {
+		okey[i]=key[i];
+	}
+
+	redc_it(&mut u);
+	nhs_pack(&u,&mut array);
+
+	for i in 0..1792 {
+		uc[i]=array[i];
+	}
+
+	for i in 0..384 {
+		uc[i+1792]=cc[i];
+	}
+}
+
+pub fn server_2(ss: &[u8],uc: &[u8],okey: &mut [u8]) {
+	let mut sh=SHA3::new(sha3::HASH256);
+
+	let mut s:[i32;DEGREE]=[0;DEGREE];		
+	let mut k:[i32;DEGREE]=[0;DEGREE];
+	let mut c:[i32;DEGREE]=[0;DEGREE];		
+
+	let mut array:[u8;1792]=[0;1792];
+	let mut key:[u8;32]=[0;32];
+	let mut cc:[u8;384]=[0;384];
+
+	for i in 0..1792 {
+		array[i]=uc[i];
+	}
+
+	nhs_unpack(&array,&mut k);
+	nres_it(&mut k);
+
+	for i in 0..384 {
+		cc[i]=uc[i+1792];
+	}
+
+	decompress(&cc,&mut c);
+
+	for i in 0..1792 {
+		array[i]=ss[i];
+	}
+
+	nhs_unpack(&array,&mut s);
+
+	poly_mul(&mut k,&s);
+	intt(&mut k);
+	poly_rsub(&mut k,&c);
+	poly_soft_reduce(&mut k);
+
+	decode(&k,&mut key);
+
+	for i in 0..32 {
+		sh.process(key[i]);
+	}
+	sh.hash(&mut key);
+
+	for i in 0..32 {
+		okey[i]=key[i];
+	}
+}
+
+/*
+fn main() {
+	let x=3;
+	let y=redc(x as u64);
+	let z=redc((y as u64)*(R2MODP));
+	println!("{:02x}",z);
+
+	let mut a:[i32;1024]=[0;1024];
+	for i in 0..1024 {a[i]=i as i32}
+
+	ntt(&mut a);
+
+	for i in 0..1024 {a[i]=modmul(a[i],ONE)}
+
+	intt(&mut a);
+
+	println!("{:02x}",a[7]);
+
+}
+*/
diff --git a/version3/rust/pair.rs b/version3/rust/pair.rs
new file mode 100644
index 0000000..3bbd152
--- /dev/null
+++ b/version3/rust/pair.rs
@@ -0,0 +1,764 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+
+use xxx::fp::FP;
+use xxx::ecp::ECP;
+use xxx::fp2::FP2;
+use xxx::ecp2::ECP2;
+use xxx::fp4::FP4;
+use xxx::fp12::FP12;
+use xxx::big::BIG;
+use xxx::dbig::DBIG;
+use xxx::ecp;
+use xxx::rom;
+
+//use std::thread;
+
+
+#[allow(non_snake_case)]
+fn linedbl(A: &mut ECP2,qx: &FP,qy: &FP) -> FP12 {
+	let mut a=FP4::new();
+	let mut b=FP4::new();
+	let mut c=FP4::new();	
+
+	let mut xx=FP2::new_copy(&A.getpx());  //X
+	let mut yy=FP2::new_copy(&A.getpy());  //Y
+	let mut zz=FP2::new_copy(&A.getpz());  //Z
+	let mut yz=FP2::new_copy(&yy);        //Y 
+	yz.mul(&zz);                //YZ
+	xx.sqr();	               //X^2
+	yy.sqr();	               //Y^2
+	zz.sqr();			       //Z^2
+			
+	yz.imul(4);
+	yz.neg(); yz.norm();       //-2YZ
+	yz.pmul(qy);               //-2YZ.Ys
+
+	xx.imul(6);                //3X^2
+	xx.pmul(qx);               //3X^2.Xs
+
+	let sb=3*rom::CURVE_B_I;
+	zz.imul(sb); 	
+	if ecp::SEXTIC_TWIST==ecp::D_TYPE {				
+		zz.div_ip2();  
+	}
+	if ecp::SEXTIC_TWIST==ecp::M_TYPE {	
+		zz.mul_ip();
+		zz.dbl();
+		yz.mul_ip();
+		yz.norm();
+	}	
+
+	zz.norm(); // 3b.Z^2 
+
+	yy.dbl();
+	zz.sub(&yy); zz.norm();     // 3b.Z^2-Y^2
+
+	a.copy(&FP4::new_fp2s(&yz,&zz)); // -2YZ.Ys | 3b.Z^2-Y^2 | 3X^2.Xs 
+	if ecp::SEXTIC_TWIST==ecp::D_TYPE {		
+		b.copy(&FP4::new_fp2(&xx));       // L(0,1) | L(0,0) | L(1,0)
+	}
+	if ecp::SEXTIC_TWIST==ecp::M_TYPE {
+		c.copy(&FP4::new_fp2(&xx));
+		c.times_i();  
+	}		
+	A.dbl();
+	return FP12::new_fp4s(&a,&b,&c);	
+}
+
+#[allow(non_snake_case)]
+fn lineadd(A: &mut ECP2,B: &ECP2,qx: &FP,qy: &FP) -> FP12 {
+
+	let mut a=FP4::new();
+	let mut b=FP4::new();
+	let mut c=FP4::new();	
+
+	let mut x1=FP2::new_copy(&A.getpx());    // X1
+	let mut y1=FP2::new_copy(&A.getpy());    // Y1
+	let mut t1=FP2::new_copy(&A.getpz());    // Z1
+	let mut t2=FP2::new_copy(&A.getpz());    // Z1
+			
+	t1.mul(&B.getpy());    // T1=Z1.Y2 
+	t2.mul(&B.getpx());    // T2=Z1.X2
+
+	x1.sub(&t2); x1.norm();  // X1=X1-Z1.X2
+	y1.sub(&t1); y1.norm();  // Y1=Y1-Z1.Y2
+
+	t1.copy(&x1);            // T1=X1-Z1.X2
+	x1.pmul(qy);            // X1=(X1-Z1.X2).Ys
+	if ecp::SEXTIC_TWIST==ecp::M_TYPE {
+		x1.mul_ip();
+		x1.norm();
+	}
+
+	t1.mul(&B.getpy());       // T1=(X1-Z1.X2).Y2
+
+	t2.copy(&y1);            // T2=Y1-Z1.Y2
+	t2.mul(&B.getpx());       // T2=(Y1-Z1.Y2).X2
+	t2.sub(&t1); t2.norm();          // T2=(Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2
+	y1.pmul(qx); y1.neg(); y1.norm(); // Y1=-(Y1-Z1.Y2).Xs
+
+	a.copy(&FP4::new_fp2s(&x1,&t2)); // (X1-Z1.X2).Ys  |  (Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2  | - (Y1-Z1.Y2).Xs
+	if ecp::SEXTIC_TWIST==ecp::D_TYPE {	
+		b.copy(&FP4::new_fp2(&y1));
+	}
+	if ecp::SEXTIC_TWIST==ecp::M_TYPE {
+		c.copy(&FP4::new_fp2(&y1));
+		c.times_i();
+	}	
+
+	A.add(B);
+	return FP12::new_fp4s(&a,&b,&c);
+}
+
+#[allow(non_snake_case)]
+/* Optimal R-ate pairing */
+pub fn ate(P1: &ECP2,Q1: &ECP) -> FP12 {
+	let mut f = FP2::new_bigs(&BIG::new_ints(&rom::FRA),&BIG::new_ints(&rom::FRB));
+	let x = BIG::new_ints(&rom::CURVE_BNX);
+	let mut n = BIG::new_copy(&x);
+	let mut K = ECP2::new();
+
+	if ecp::CURVE_PAIRING_TYPE == ecp::BN {
+		if ecp::SEXTIC_TWIST==ecp::M_TYPE {
+			f.inverse();
+			f.norm();
+		}
+		n.pmul(6); 
+		if ecp::SIGN_OF_X == ecp::POSITIVEX {
+			n.inc(2);
+		} else {
+			n.dec(2);		
+		}
+
+	} else {n.copy(&x)}
+	
+	n.norm();
+	let mut n3 = BIG::new_copy(&n);
+	n3.pmul(3);
+	n3.norm();
+
+	let mut P=ECP2::new(); P.copy(P1); P.affine();
+	let mut Q=ECP::new(); Q.copy(Q1); Q.affine();
+
+
+	let qx=FP::new_copy(&Q.getpx());
+	let qy=FP::new_copy(&Q.getpy());
+
+	let mut A=ECP2::new();
+	let mut r=FP12::new_int(1);
+
+	A.copy(&P);
+	let mut NP=ECP2::new();
+	NP.copy(&P);
+	NP.neg();
+
+	let nb=n3.nbits();
+
+	for i in (1..nb-1).rev() {
+		r.sqr();	
+		//let mut lv=FP12::new();
+		//let handler = thread::spawn(move || {
+		//	lv=linedbl(&mut A,&qx,&qy);
+		//});
+		//handler.join().unwrap();
+	
+		let mut lv=linedbl(&mut A,&qx,&qy);
+		r.smul(&lv,ecp::SEXTIC_TWIST);
+		let bt=n3.bit(i)-n.bit(i);
+		if bt==1 {
+			lv=lineadd(&mut A,&P,&qx,&qy);
+			r.smul(&lv,ecp::SEXTIC_TWIST);
+		}		
+		if bt == -1 {
+
+			lv=lineadd(&mut A,&NP,&qx,&qy);
+			r.smul(&lv,ecp::SEXTIC_TWIST);	
+
+		}
+	}
+
+	if ecp::SIGN_OF_X == ecp::NEGATIVEX {
+		r.conj();			
+	}
+
+
+/* R-ate fixup required for BN curves */
+
+	if ecp::CURVE_PAIRING_TYPE == ecp::BN {
+		if ecp::SIGN_OF_X == ecp::NEGATIVEX {
+			//r.conj();
+			A.neg();			
+		}
+
+		K.copy(&P);
+		K.frob(&f);
+
+		let mut lv=lineadd(&mut A,&K,&qx,&qy);
+		r.smul(&lv,ecp::SEXTIC_TWIST);
+		K.frob(&f);
+		K.neg();
+		lv=lineadd(&mut A,&K,&qx,&qy);
+		r.smul(&lv,ecp::SEXTIC_TWIST);
+	}
+
+	return r;
+}
+
+#[allow(non_snake_case)]
+/* Optimal R-ate double pairing e(P,Q).e(R,S) */
+pub fn ate2(P1: &ECP2,Q1: &ECP,R1: &ECP2,S1: &ECP) -> FP12 {
+	let mut f = FP2::new_bigs(&BIG::new_ints(&rom::FRA),&BIG::new_ints(&rom::FRB));
+	let x = BIG::new_ints(&rom::CURVE_BNX);
+	let mut n = BIG::new_copy(&x);
+	let mut K = ECP2::new();
+
+	if ecp::CURVE_PAIRING_TYPE == ecp::BN {
+		if ecp::SEXTIC_TWIST==ecp::M_TYPE {
+			f.inverse();
+			f.norm();
+		}
+		n.pmul(6); 
+		if ecp::SIGN_OF_X == ecp::POSITIVEX {
+			n.inc(2);
+		} else {
+			n.dec(2);		
+		}
+	} else {n.copy(&x)}
+	
+	n.norm();
+	let mut n3 = BIG::new_copy(&n);
+	n3.pmul(3);
+	n3.norm();
+
+	let mut P=ECP2::new(); P.copy(P1); P.affine();
+	let mut Q=ECP::new(); Q.copy(Q1); Q.affine();
+	let mut R=ECP2::new(); R.copy(R1); R.affine();
+	let mut S=ECP::new(); S.copy(S1); S.affine();
+
+
+	let qx=FP::new_copy(&Q.getpx());
+	let qy=FP::new_copy(&Q.getpy());
+
+	let sx=FP::new_copy(&S.getpx());
+	let sy=FP::new_copy(&S.getpy());
+
+	let mut A=ECP2::new();
+	let mut B=ECP2::new();
+	let mut r=FP12::new_int(1);
+
+	A.copy(&P);
+	B.copy(&R);
+
+	let mut NP=ECP2::new();
+	NP.copy(&P);
+	NP.neg();
+	let mut NR=ECP2::new();
+	NR.copy(&R);
+	NR.neg();
+
+	let nb=n3.nbits();
+
+	for i in (1..nb-1).rev() {
+		r.sqr();		
+		let mut lv=linedbl(&mut A,&qx,&qy);
+		r.smul(&lv,ecp::SEXTIC_TWIST);
+		lv=linedbl(&mut B,&sx,&sy);
+		r.smul(&lv,ecp::SEXTIC_TWIST);
+		let bt=n3.bit(i)-n.bit(i);		
+		if bt == 1 {
+			lv=lineadd(&mut A,&P,&qx,&qy);
+			r.smul(&lv,ecp::SEXTIC_TWIST);
+			lv=lineadd(&mut B,&R,&sx,&sy);
+			r.smul(&lv,ecp::SEXTIC_TWIST);
+		}
+		if bt == -1 {
+
+			lv=lineadd(&mut A,&NP,&qx,&qy);
+			r.smul(&lv,ecp::SEXTIC_TWIST);
+			lv=lineadd(&mut B,&NR,&sx,&sy);
+			r.smul(&lv,ecp::SEXTIC_TWIST);
+
+		}
+	}
+
+	if ecp::SIGN_OF_X == ecp::NEGATIVEX {
+		r.conj();			
+	}
+
+/* R-ate fixup */
+	if ecp::CURVE_PAIRING_TYPE == ecp::BN {
+		if ecp::SIGN_OF_X == ecp::NEGATIVEX {		
+			//r.conj();
+			A.neg();
+			B.neg();
+		}
+		K.copy(&P);
+		K.frob(&f);
+		
+		let mut lv=lineadd(&mut A,&K,&qx,&qy);
+		r.smul(&lv,ecp::SEXTIC_TWIST);
+		K.frob(&f);
+		K.neg();
+		lv=lineadd(&mut A,&K,&qx,&qy);
+		r.smul(&lv,ecp::SEXTIC_TWIST);
+
+		K.copy(&R);
+		K.frob(&f);
+		
+		lv=lineadd(&mut B,&K,&sx,&sy);
+		r.smul(&lv,ecp::SEXTIC_TWIST);
+		K.frob(&f);
+		K.neg();
+		lv=lineadd(&mut B,&K,&sx,&sy);
+		r.smul(&lv,ecp::SEXTIC_TWIST);
+	}
+
+	return r;
+}
+
+/* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */
+pub fn fexp(m: &FP12) -> FP12 {
+	let f = FP2::new_bigs(&BIG::new_ints(&rom::FRA),&BIG::new_ints(&rom::FRB));
+	let mut x = BIG::new_ints(&rom::CURVE_BNX);
+	let mut r=FP12::new_copy(m);
+		
+/* Easy part of final exp */
+	let mut lv=FP12::new_copy(&r);
+	lv.inverse();
+	r.conj();
+
+	r.mul(&lv);
+	lv.copy(&r);
+	r.frob(&f);
+	r.frob(&f);
+	r.mul(&lv);
+/* Hard part of final exp */
+	if ecp::CURVE_PAIRING_TYPE == ecp::BN {
+		lv.copy(&r);
+		lv.frob(&f);
+		let mut x0=FP12::new_copy(&lv);
+		x0.frob(&f);
+		lv.mul(&r);
+		x0.mul(&lv);
+		x0.frob(&f);
+		let mut x1=FP12::new_copy(&r);
+		x1.conj();
+		let mut x4=r.pow(&mut x);
+		if ecp::SIGN_OF_X == ecp::POSITIVEX {
+			x4.conj();
+		}
+
+		let mut x3=FP12::new_copy(&x4);
+		x3.frob(&f);
+
+		let mut x2=x4.pow(&mut x);
+		if ecp::SIGN_OF_X == ecp::POSITIVEX {
+			x2.conj();
+		}
+		let mut x5=FP12::new_copy(&x2); x5.conj();
+		lv=x2.pow(&mut x);
+		if ecp::SIGN_OF_X == ecp::POSITIVEX {
+			lv.conj();
+		}
+		x2.frob(&f);
+		r.copy(&x2); r.conj();
+
+		x4.mul(&r);
+		x2.frob(&f);
+
+		r.copy(&lv);
+		r.frob(&f);
+		lv.mul(&r);
+
+		lv.usqr();
+		lv.mul(&x4);
+		lv.mul(&x5);
+		r.copy(&x3);
+		r.mul(&x5);
+		r.mul(&lv);
+		lv.mul(&x2);
+		r.usqr();
+		r.mul(&lv);
+		r.usqr();
+		lv.copy(&r);
+		lv.mul(&x1);
+		r.mul(&x0);
+		lv.usqr();
+		r.mul(&lv);
+		r.reduce();
+	} else {
+
+// Ghamman & Fouotsa Method
+
+		let mut y0=FP12::new_copy(&r); y0.usqr();
+		let mut y1=y0.pow(&mut x);
+		if ecp::SIGN_OF_X == ecp::NEGATIVEX {
+			y1.conj();
+		}		
+		x.fshr(1); let mut y2=y1.pow(&mut x); 
+		if ecp::SIGN_OF_X == ecp::NEGATIVEX {
+			y2.conj();
+		}	
+		x.fshl(1);
+		let mut y3=FP12::new_copy(&r); y3.conj();
+		y1.mul(&y3);
+
+		y1.conj();
+		y1.mul(&y2);
+
+		y2=y1.pow(&mut x);
+		if ecp::SIGN_OF_X == ecp::NEGATIVEX {
+			y2.conj();
+		}	
+		y3=y2.pow(&mut x);
+		if ecp::SIGN_OF_X == ecp::NEGATIVEX {
+			y3.conj();
+		}		
+		y1.conj();
+		y3.mul(&y1);
+
+		y1.conj();
+		y1.frob(&f); y1.frob(&f); y1.frob(&f);
+		y2.frob(&f); y2.frob(&f);
+		y1.mul(&y2);
+
+		y2=y3.pow(&mut x);
+		if ecp::SIGN_OF_X == ecp::NEGATIVEX {
+			y2.conj();
+		}			
+		y2.mul(&y0);
+		y2.mul(&r);
+
+		y1.mul(&y2);
+		y2.copy(&y3); y2.frob(&f);
+		y1.mul(&y2);
+		r.copy(&y1);
+		r.reduce();
+
+
+/*
+		let mut x0=FP12::new_copy(&r);
+		let mut x1=FP12::new_copy(&r);
+		lv.copy(&r); lv.frob(&mut f);
+		let mut x3=FP12::new_copy(&lv); x3.conj(); x1.mul(&mut x3);
+		lv.frob(&mut f); lv.frob(&mut f);
+		x1.mul(&mut lv);
+
+		r=r.pow(&mut x);  //r=r.pow(x);
+		x3.copy(&r); x3.conj(); x1.mul(&mut x3);
+		lv.copy(&r); lv.frob(&mut f);
+		x0.mul(&mut lv);
+		lv.frob(&mut f);
+		x1.mul(&mut lv);
+		lv.frob(&mut f);
+		x3.copy(&lv); x3.conj(); x0.mul(&mut x3);
+
+		r=r.pow(&mut x);
+		x0.mul(&mut r);
+		lv.copy(&r); lv.frob(&mut f); lv.frob(&mut f);
+		x3.copy(&lv); x3.conj(); x0.mul(&mut x3);
+		lv.frob(&mut f);
+		x1.mul(&mut lv);
+
+		r=r.pow(&mut x);
+		lv.copy(&r); lv.frob(&mut f);
+		x3.copy(&lv); x3.conj(); x0.mul(&mut x3);
+		lv.frob(&mut f);
+		x1.mul(&mut lv);
+
+		r=r.pow(&mut x);
+		x3.copy(&r); x3.conj(); x0.mul(&mut x3);
+		lv.copy(&r); lv.frob(&mut f);
+		x1.mul(&mut lv);
+
+		r=r.pow(&mut x);
+		x1.mul(&mut r);
+
+		x0.usqr();
+		x0.mul(&mut x1);
+		r.copy(&x0);
+		r.reduce();  */
+	}
+	return r;
+}
+
+#[allow(non_snake_case)]
+/* GLV method */
+fn glv(e: &BIG) -> [BIG;2] {
+	let mut u:[BIG;2]=[BIG::new(),BIG::new()];
+	if ecp::CURVE_PAIRING_TYPE == ecp::BN {
+		let mut t=BIG::new();
+		let q=BIG::new_ints(&rom::CURVE_ORDER);
+		let mut v:[BIG;2]=[BIG::new(),BIG::new()];
+
+		for i in 0..2 {
+			t.copy(&BIG::new_ints(&rom::CURVE_W[i]));  // why not just t=new BIG(ROM.CURVE_W[i]); 
+			let mut d:DBIG = BIG::mul(&t,e);
+			v[i].copy(&d.div(&q));
+		}
+		u[0].copy(&e);
+		for i in 0..2 {
+			for j in 0..2 {
+				t=BIG::new_ints(&rom::CURVE_SB[j][i]);
+				t=BIG::modmul(&mut v[j],&mut t,&q);
+				u[i].add(&q);
+				u[i].sub(&t);
+				u[i].rmod(&q);
+			}
+		}
+	} else {
+		let q=BIG::new_ints(&rom::CURVE_ORDER);
+		let x=BIG::new_ints(&rom::CURVE_BNX);
+		let x2=BIG::smul(&x,&x);
+		u[0].copy(&e);  
+		u[0].rmod(&x2);
+		u[1].copy(&e); 
+		u[1].div(&x2);
+		u[1].rsub(&q);
+	}
+	return u;
+}
+
+#[allow(non_snake_case)]
+/* Galbraith & Scott Method */
+pub fn gs(e: &BIG) -> [BIG;4] {
+	let mut u:[BIG;4]=[BIG::new(),BIG::new(),BIG::new(),BIG::new()];
+	if ecp::CURVE_PAIRING_TYPE == ecp::BN {
+		let mut t=BIG::new();
+		let q=BIG::new_ints(&rom::CURVE_ORDER);
+
+		let mut v:[BIG;4]=[BIG::new(),BIG::new(),BIG::new(),BIG::new()];
+		for i in 0..4 {
+			t.copy(&BIG::new_ints(&rom::CURVE_WB[i]));
+			let mut d:DBIG=BIG::mul(&t,e);
+			v[i].copy(&d.div(&q));
+		}
+		u[0].copy(&e);
+		for i in 0..4 {
+			for j in 0..4 {
+				t=BIG::new_ints(&rom::CURVE_BB[j][i]);
+				t=BIG::modmul(&mut v[j],&mut t,&q);
+				u[i].add(&q);
+				u[i].sub(&t);
+				u[i].rmod(&q);
+			}
+		}
+	} else {
+		let q=BIG::new_ints(&rom::CURVE_ORDER);	
+		let x=BIG::new_ints(&rom::CURVE_BNX);
+		let mut w=BIG::new_copy(&e);
+		for i in 0..3 {
+			u[i].copy(&w);
+			u[i].rmod(&x);
+			w.div(&x);
+		}
+		u[3].copy(&w);
+		if ecp::SIGN_OF_X == ecp::NEGATIVEX {
+			let mut t=BIG::new();	
+			t.copy(&BIG::modneg(&mut u[1],&q));
+			u[1].copy(&t);
+			t.copy(&BIG::modneg(&mut u[3],&q));	
+			u[3].copy(&t);	
+		}
+	}
+	return u;
+}	
+
+#[allow(non_snake_case)]
+/* Multiply P by e in group G1 */
+pub fn g1mul(P: &ECP,e: &mut BIG) -> ECP {
+	let mut R=ECP::new();
+	if rom::USE_GLV {
+	//	P.affine();
+		R.copy(P);
+		let mut Q=ECP::new();
+		Q.copy(P); Q.affine();
+		let q=BIG::new_ints(&rom::CURVE_ORDER);
+		let mut cru=FP::new_big(&BIG::new_ints(&rom::CURVE_CRU));
+		let mut u=glv(e);
+		Q.mulx(&mut cru);
+
+		let mut np=u[0].nbits();
+		let mut t:BIG=BIG::modneg(&mut u[0],&q);
+		let mut nn=t.nbits();
+		if nn<np {
+			u[0].copy(&t);
+			R.neg();
+		}
+
+		np=u[1].nbits();
+		t=BIG::modneg(&mut u[1],&q);
+		nn=t.nbits();
+		if nn<np {
+			u[1].copy(&t);
+			Q.neg();
+		}
+		u[0].norm();
+		u[1].norm();
+		R=R.mul2(&u[0],&mut Q,&u[1]);
+			
+	} else {
+		R=P.mul(e);
+	}
+	return R;
+}
+
+#[allow(non_snake_case)]
+/* Multiply P by e in group G2 */
+pub fn g2mul(P: &ECP2,e: &BIG) -> ECP2 {
+	let mut R=ECP2::new();
+	if rom::USE_GS_G2 {
+		let mut Q:[ECP2;4]=[ECP2::new(),ECP2::new(),ECP2::new(),ECP2::new()];
+		let mut f = FP2::new_bigs(&BIG::new_ints(&rom::FRA),&BIG::new_ints(&rom::FRB));
+		let q=BIG::new_ints(&rom::CURVE_ORDER);
+		let mut u=gs(e);
+		let mut T=ECP2::new();
+
+		if ecp::SEXTIC_TWIST==ecp::M_TYPE {
+			f.inverse();
+			f.norm();
+		}	
+
+		let mut t=BIG::new();
+	//	P.affine();
+		Q[0].copy(&P);
+		for i in 1..4 {
+			T.copy(&Q[i-1]);
+			Q[i].copy(&T);
+			Q[i].frob(&f);
+		}
+		for i in 0..4 {
+			let np=u[i].nbits();
+			t.copy(&BIG::modneg(&mut u[i],&q));
+			let nn=t.nbits();
+			if nn<np {
+				u[i].copy(&t);
+				Q[i].neg();
+			}
+			u[i].norm();
+		}
+
+		R.copy(&ECP2::mul4(&mut Q,&u));
+
+	} else {
+		R.copy(&P.mul(e));
+	}
+	return R;
+}
+
+/* f=f^e */
+/* Note that this method requires a lot of RAM! Better to use compressed XTR method, see FP4.java */
+pub fn gtpow(d: &FP12,e: &BIG) -> FP12 {
+	let mut r=FP12::new();
+	if rom::USE_GS_GT {
+		let mut g:[FP12;4]=[FP12::new(),FP12::new(),FP12::new(),FP12::new()];
+		let f = FP2::new_bigs(&BIG::new_ints(&rom::FRA),&BIG::new_ints(&rom::FRB));
+		let q=BIG::new_ints(&rom::CURVE_ORDER);
+		let mut t=BIG::new();
+		let mut u=gs(e);
+		let mut w=FP12::new();
+
+		g[0].copy(&d);
+		for i in 1..4 {
+			w.copy(&g[i-1]);
+			g[i].copy(&w);
+			g[i].frob(&f);
+		}
+		for i in 0..4 {
+			let np=u[i].nbits();
+			t.copy(&BIG::modneg(&mut u[i],&q));
+			let nn=t.nbits();
+			if nn<np {
+				u[i].copy(&t);
+				g[i].conj();
+			}
+			u[i].norm();			
+		}
+		r.copy(&FP12::pow4(&mut g,&u));
+	} else {
+		r.copy(&d.pow(e));
+	}
+	return r;
+}
+
+/*
+#[allow(non_snake_case)]
+fn main()
+{
+	let mut Q=ECP::new_bigs(&BIG::new_ints(&rom::CURVE_GX),&BIG::new_ints(&rom::CURVE_GY));
+	let mut P=ECP2::new_fp2s(&FP2::new_bigs(&BIG::new_ints(&rom::CURVE_PXA),&BIG::new_ints(&rom::CURVE_PXB)),&FP2::new_bigs(&BIG::new_ints(&rom::CURVE_PYA),&BIG::new_ints(&rom::CURVE_PYB)));
+
+	let mut r=BIG::new_ints(&rom::CURVE_ORDER);
+	
+	println!("P= {}",P.tostring());
+	println!("Q= {}",Q.tostring());
+
+	//m:=NewBIGint(17)
+
+	let mut e=ate(&mut P,&mut Q);
+	println!("\ne= {}",e.tostring());
+
+	e=fexp(&e);
+
+	for i in 1..10 {
+		e=ate(&mut P,&mut Q);
+		e=fexp(&e);
+	}
+
+
+	//	e=GTpow(e,m);
+
+	println!("\ne= {}",e.tostring());
+
+	
+	fmt.Printf("\n");
+	GLV:=glv(r)
+
+	fmt.Printf("GLV[0]= "+GLV[0].toString())
+	fmt.Printf("\n")
+
+	fmt.Printf("GLV[0]= "+GLV[1].toString())
+	fmt.Printf("\n")
+
+	G:=NewECP(); G.copy(Q)
+	R:=NewECP2(); R.copy(P)
+
+
+	e=ate(R,Q)
+	e=fexp(e)
+
+	e=GTpow(e,xa)
+	fmt.Printf("\ne= "+e.toString());
+	fmt.Printf("\n")
+
+	R=G2mul(R,xa)
+	e=ate(R,G)
+	e=fexp(e)
+
+	fmt.Printf("\ne= "+e.toString())
+	fmt.Printf("\n")
+
+	G=G1mul(G,xa)
+	e=ate(P,G)
+	e=fexp(e)
+	fmt.Printf("\ne= "+e.toString())
+	fmt.Printf("\n") 
+}*/
diff --git a/version3/rust/pair192.rs b/version3/rust/pair192.rs
new file mode 100644
index 0000000..d1f733b
--- /dev/null
+++ b/version3/rust/pair192.rs
@@ -0,0 +1,494 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+
+use xxx::fp::FP;
+use xxx::ecp::ECP;
+use xxx::fp2::FP2;
+use xxx::ecp4::ECP4;
+use xxx::fp4::FP4;
+use xxx::fp8::FP8;
+use xxx::fp24::FP24;
+use xxx::big::BIG;
+use xxx::ecp;
+use xxx::rom;
+
+#[allow(non_snake_case)]
+fn linedbl(A: &mut ECP4,qx: &FP,qy: &FP) -> FP24 {
+	let mut a=FP8::new();
+	let mut b=FP8::new();
+	let mut c=FP8::new();	
+
+	let mut xx=FP4::new_copy(&A.getpx());  //X
+	let mut yy=FP4::new_copy(&A.getpy());  //Y
+	let mut zz=FP4::new_copy(&A.getpz());  //Z
+	let mut yz=FP4::new_copy(&yy);        //Y 
+	yz.mul(&zz);                //YZ
+	xx.sqr();	               //X^2
+	yy.sqr();	               //Y^2
+	zz.sqr();			       //Z^2
+			
+	yz.imul(4);
+	yz.neg(); yz.norm();       //-2YZ
+	yz.qmul(qy);               //-2YZ.Ys
+
+	xx.imul(6);                //3X^2
+	xx.qmul(qx);               //3X^2.Xs
+
+	let sb=3*rom::CURVE_B_I;
+	zz.imul(sb); 	
+	if ecp::SEXTIC_TWIST==ecp::D_TYPE {				
+		zz.div_2i();  
+	}
+	if ecp::SEXTIC_TWIST==ecp::M_TYPE {	
+		zz.times_i();
+		zz.dbl();
+		yz.times_i();
+		//yz.norm();
+	}	
+
+	zz.norm(); // 3b.Z^2 
+
+	yy.dbl();
+	zz.sub(&yy); zz.norm();     // 3b.Z^2-Y^2
+
+	a.copy(&FP8::new_fp4s(&yz,&zz)); // -2YZ.Ys | 3b.Z^2-Y^2 | 3X^2.Xs 
+	if ecp::SEXTIC_TWIST==ecp::D_TYPE {		
+		b.copy(&FP8::new_fp4(&xx));       // L(0,1) | L(0,0) | L(1,0)
+	}
+	if ecp::SEXTIC_TWIST==ecp::M_TYPE {
+		c.copy(&FP8::new_fp4(&xx));
+		c.times_i();  
+	}		
+	A.dbl();
+	return FP24::new_fp8s(&a,&b,&c);	
+}
+
+#[allow(non_snake_case)]
+fn lineadd(A: &mut ECP4,B: &ECP4,qx: &FP,qy: &FP) -> FP24 {
+
+	let mut a=FP8::new();
+	let mut b=FP8::new();
+	let mut c=FP8::new();	
+
+	let mut x1=FP4::new_copy(&A.getpx());    // X1
+	let mut y1=FP4::new_copy(&A.getpy());    // Y1
+	let mut t1=FP4::new_copy(&A.getpz());    // Z1
+	let mut t2=FP4::new_copy(&A.getpz());    // Z1
+			
+	t1.mul(&B.getpy());    // T1=Z1.Y2 
+	t2.mul(&B.getpx());    // T2=Z1.X2
+
+	x1.sub(&t2); x1.norm();  // X1=X1-Z1.X2
+	y1.sub(&t1); y1.norm();  // Y1=Y1-Z1.Y2
+
+	t1.copy(&x1);            // T1=X1-Z1.X2
+	x1.qmul(qy);            // X1=(X1-Z1.X2).Ys
+	if ecp::SEXTIC_TWIST==ecp::M_TYPE {
+		x1.times_i();
+		//x1.norm();
+	}
+
+	t1.mul(&B.getpy());       // T1=(X1-Z1.X2).Y2
+
+	t2.copy(&y1);            // T2=Y1-Z1.Y2
+	t2.mul(&B.getpx());       // T2=(Y1-Z1.Y2).X2
+	t2.sub(&t1); t2.norm();          // T2=(Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2
+	y1.qmul(qx); y1.neg(); y1.norm(); // Y1=-(Y1-Z1.Y2).Xs
+
+	a.copy(&FP8::new_fp4s(&x1,&t2)); // (X1-Z1.X2).Ys  |  (Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2  | - (Y1-Z1.Y2).Xs
+	if ecp::SEXTIC_TWIST==ecp::D_TYPE {	
+		b.copy(&FP8::new_fp4(&y1));
+	}
+	if ecp::SEXTIC_TWIST==ecp::M_TYPE {
+		c.copy(&FP8::new_fp4(&y1));
+		c.times_i();
+	}	
+
+	A.add(B);
+	return FP24::new_fp8s(&a,&b,&c);
+}
+
+#[allow(non_snake_case)]
+/* Optimal R-ate pairing */
+pub fn ate(P1: &ECP4,Q1: &ECP) -> FP24 {
+	let x = BIG::new_ints(&rom::CURVE_BNX);
+	let n = BIG::new_copy(&x);
+
+	let mut n3 = BIG::new_copy(&n);
+	n3.pmul(3);
+	n3.norm();
+
+	let mut P=ECP4::new(); P.copy(P1); P.affine();
+	let mut Q=ECP::new(); Q.copy(Q1); Q.affine();
+
+
+	let qx=FP::new_copy(&Q.getpx());
+	let qy=FP::new_copy(&Q.getpy());
+
+	let mut A=ECP4::new();
+	let mut r=FP24::new_int(1);
+
+	A.copy(&P);
+	let mut NP=ECP4::new();
+	NP.copy(&P);
+	NP.neg();
+
+	let nb=n3.nbits();
+
+	for i in (1..nb-1).rev() {
+		r.sqr();		
+		let mut lv=linedbl(&mut A,&qx,&qy);
+		r.smul(&lv,ecp::SEXTIC_TWIST);
+		let bt=n3.bit(i)-n.bit(i);
+		if bt==1 {
+			lv=lineadd(&mut A,&P,&qx,&qy);
+			r.smul(&lv,ecp::SEXTIC_TWIST);
+		}		
+		if bt == -1 {
+
+			lv=lineadd(&mut A,&NP,&qx,&qy);
+			r.smul(&lv,ecp::SEXTIC_TWIST);	
+
+		}
+	}
+
+	if ecp::SIGN_OF_X == ecp::NEGATIVEX {
+		r.conj();			
+	}
+
+	return r;
+}
+
+#[allow(non_snake_case)]
+/* Optimal R-ate double pairing e(P,Q).e(R,S) */
+pub fn ate2(P1: &ECP4,Q1: &ECP,R1: &ECP4,S1: &ECP) -> FP24 {
+	let x = BIG::new_ints(&rom::CURVE_BNX);
+	let n = BIG::new_copy(&x);
+	
+	let mut n3 = BIG::new_copy(&n);
+	n3.pmul(3);
+	n3.norm();
+
+	let mut P=ECP4::new(); P.copy(P1); P.affine();
+	let mut Q=ECP::new(); Q.copy(Q1); Q.affine();
+	let mut R=ECP4::new(); R.copy(R1); R.affine();
+	let mut S=ECP::new(); S.copy(S1); S.affine();
+
+	let qx=FP::new_copy(&Q.getpx());
+	let qy=FP::new_copy(&Q.getpy());
+
+	let sx=FP::new_copy(&S.getpx());
+	let sy=FP::new_copy(&S.getpy());
+
+	let mut A=ECP4::new();
+	let mut B=ECP4::new();
+	let mut r=FP24::new_int(1);
+
+	A.copy(&P);
+	B.copy(&R);
+
+	let mut NP=ECP4::new();
+	NP.copy(&P);
+	NP.neg();
+	let mut NR=ECP4::new();
+	NR.copy(&R);
+	NR.neg();
+
+	let nb=n3.nbits();
+
+	for i in (1..nb-1).rev() {
+		r.sqr();		
+		let mut lv=linedbl(&mut A,&qx,&qy);
+		r.smul(&lv,ecp::SEXTIC_TWIST);
+		lv=linedbl(&mut B,&sx,&sy);
+		r.smul(&lv,ecp::SEXTIC_TWIST);
+		let bt=n3.bit(i)-n.bit(i);		
+		if bt == 1 {
+			lv=lineadd(&mut A,&P,&qx,&qy);
+			r.smul(&lv,ecp::SEXTIC_TWIST);
+			lv=lineadd(&mut B,&R,&sx,&sy);
+			r.smul(&lv,ecp::SEXTIC_TWIST);
+		}
+		if bt == -1 {
+
+			lv=lineadd(&mut A,&NP,&qx,&qy);
+			r.smul(&lv,ecp::SEXTIC_TWIST);
+			lv=lineadd(&mut B,&NR,&sx,&sy);
+			r.smul(&lv,ecp::SEXTIC_TWIST);
+
+		}
+	}
+
+	if ecp::SIGN_OF_X == ecp::NEGATIVEX {
+		r.conj();			
+	}
+
+	return r;
+}
+
+/* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */
+pub fn fexp(m: &FP24) -> FP24 {
+	let f = FP2::new_bigs(&BIG::new_ints(&rom::FRA),&BIG::new_ints(&rom::FRB));
+	let mut x = BIG::new_ints(&rom::CURVE_BNX);
+	let mut r=FP24::new_copy(m);
+		
+/* Easy part of final exp */
+	let mut lv=FP24::new_copy(&r);
+	lv.inverse();
+	r.conj();
+
+	r.mul(&lv);
+	lv.copy(&r);
+	r.frob(&f,4);
+	r.mul(&lv);
+
+/* Hard part of final exp */
+// Ghamman & Fouotsa Method
+
+
+	let mut t7=FP24::new_copy(&r); t7.usqr();
+	let mut t1=t7.pow(&mut x);
+
+	x.fshr(1);
+	let mut t2=t1.pow(&mut x);
+	x.fshl(1);
+
+	if ecp::SIGN_OF_X==ecp::NEGATIVEX {
+		t1.conj();
+	}
+	let mut t3=FP24::new_copy(&t1); t3.conj();
+	t2.mul(&t3);
+	t2.mul(&r);
+
+
+	t3.copy(&t2.pow(&mut x));
+	let mut t4=t3.pow(&mut x);
+	let mut t5=t4.pow(&mut x);
+
+	if ecp::SIGN_OF_X==ecp::NEGATIVEX {
+		t3.conj(); t5.conj();
+	}
+
+	t3.frob(&f,6); t4.frob(&f,5);
+	t3.mul(&t4);
+
+	let mut t6=t5.pow(&mut x);
+	if ecp::SIGN_OF_X==ecp::NEGATIVEX {
+		t6.conj();
+	}
+
+	t5.frob(&f,4);
+	t3.mul(&t5);
+
+	let mut t0=FP24::new_copy(&t2); t0.conj();
+	t6.mul(&t0);
+
+	t5.copy(&t6);
+	t5.frob(&f,3);
+
+	t3.mul(&t5);
+	t5.copy(&t6.pow(&mut x));
+	t6.copy(&t5.pow(&mut x));
+
+	if ecp::SIGN_OF_X==ecp::NEGATIVEX {
+		t5.conj();
+	}
+
+	t0.copy(&t5);
+	t0.frob(&f,2);
+	t3.mul(&t0);
+	t0.copy(&t6);
+	t0.frob(&f,1);
+
+	t3.mul(&t0);
+	t5.copy(&t6.pow(&mut x));
+
+	if ecp::SIGN_OF_X==ecp::NEGATIVEX {
+		t5.conj();
+	}
+	t2.frob(&f,7);
+
+	t5.mul(&t7);
+	t3.mul(&t2);
+	t3.mul(&t5);
+
+	r.mul(&t3);
+
+
+	r.reduce();
+	return r;
+}
+
+#[allow(non_snake_case)]
+/* GLV method */
+fn glv(e: &BIG) -> [BIG;2] {
+	let mut u:[BIG;2]=[BIG::new(),BIG::new()];
+	let q=BIG::new_ints(&rom::CURVE_ORDER);
+	let mut x=BIG::new_ints(&rom::CURVE_BNX);
+	let x2=BIG::smul(&x,&x);
+	x.copy(&BIG::smul(&x2,&x2));
+	u[0].copy(&e);  
+	u[0].rmod(&x);
+	u[1].copy(&e); 
+	u[1].div(&x);
+	u[1].rsub(&q);
+	
+	return u;
+}
+
+#[allow(non_snake_case)]
+/* Galbraith & Scott Method */
+pub fn gs(e: &BIG) -> [BIG;8] {
+	let mut u:[BIG;8]=[BIG::new(),BIG::new(),BIG::new(),BIG::new(),BIG::new(),BIG::new(),BIG::new(),BIG::new()];
+	let q=BIG::new_ints(&rom::CURVE_ORDER);	
+	let x=BIG::new_ints(&rom::CURVE_BNX);
+	let mut w=BIG::new_copy(&e);
+	for i in 0..7 {
+		u[i].copy(&w);
+		u[i].rmod(&x);
+		w.div(&x);
+	}
+	u[7].copy(&w);
+	if ecp::SIGN_OF_X == ecp::NEGATIVEX {
+		let mut t=BIG::new();	
+		t.copy(&BIG::modneg(&mut u[1],&q));
+		u[1].copy(&t);
+		t.copy(&BIG::modneg(&mut u[3],&q));	
+		u[3].copy(&t);	
+		t.copy(&BIG::modneg(&mut u[5],&q));
+		u[5].copy(&t);
+		t.copy(&BIG::modneg(&mut u[7],&q));	
+		u[7].copy(&t);			
+	}
+	return u;
+}	
+
+#[allow(non_snake_case)]
+/* Multiply P by e in group G1 */
+pub fn g1mul(P: &ECP,e: &mut BIG) -> ECP {
+	let mut R=ECP::new();
+	if rom::USE_GLV {
+	//	P.affine();
+		R.copy(P);
+		let mut Q=ECP::new();
+		Q.copy(P); Q.affine();
+		let q=BIG::new_ints(&rom::CURVE_ORDER);
+		let mut cru=FP::new_big(&BIG::new_ints(&rom::CURVE_CRU));
+		let mut u=glv(e);
+		Q.mulx(&mut cru);
+
+		let mut np=u[0].nbits();
+		let mut t:BIG=BIG::modneg(&mut u[0],&q);
+		let mut nn=t.nbits();
+		if nn<np {
+			u[0].copy(&t);
+			R.neg();
+		}
+
+		np=u[1].nbits();
+		t=BIG::modneg(&mut u[1],&q);
+		nn=t.nbits();
+		if nn<np {
+			u[1].copy(&t);
+			Q.neg();
+		}
+		u[0].norm();
+		u[1].norm();
+		R=R.mul2(&u[0],&mut Q,&u[1]);
+			
+	} else {
+		R=P.mul(e);
+	}
+	return R;
+}
+
+#[allow(non_snake_case)]
+/* Multiply P by e in group G2 */
+pub fn g2mul(P: &ECP4,e: &BIG) -> ECP4 {
+	let mut R=ECP4::new();
+	if rom::USE_GS_G2 {
+		let mut Q:[ECP4;8]=[ECP4::new(),ECP4::new(),ECP4::new(),ECP4::new(),ECP4::new(),ECP4::new(),ECP4::new(),ECP4::new()];
+		let q=BIG::new_ints(&rom::CURVE_ORDER);
+		let mut u=gs(e);
+		let mut T=ECP4::new();
+
+		let f=ECP4::frob_constants();
+
+		let mut t=BIG::new();
+		//P.affine();
+		Q[0].copy(&P);
+		for i in 1..8 {
+			T.copy(&Q[i-1]);
+			Q[i].copy(&T);
+			Q[i].frob(&f,1);
+		}
+		for i in 0..8 {
+			let np=u[i].nbits();
+			t.copy(&BIG::modneg(&mut u[i],&q));
+			let nn=t.nbits();
+			if nn<np {
+				u[i].copy(&t);
+				Q[i].neg();
+			}
+			u[i].norm();
+		}
+
+		R.copy(&ECP4::mul8(&mut Q,&u));
+
+	} else {
+		R.copy(&P.mul(e));
+	}
+	return R;
+}
+
+/* f=f^e */
+/* Note that this method requires a lot of RAM! Better to use compressed XTR method, see FP4.java */
+pub fn gtpow(d: &FP24,e: &BIG) -> FP24 {
+	let mut r=FP24::new();
+	if rom::USE_GS_GT {
+		let mut g:[FP24;8]=[FP24::new(),FP24::new(),FP24::new(),FP24::new(),FP24::new(),FP24::new(),FP24::new(),FP24::new()];
+		let f = FP2::new_bigs(&BIG::new_ints(&rom::FRA),&BIG::new_ints(&rom::FRB));
+		let q=BIG::new_ints(&rom::CURVE_ORDER);
+		let mut t=BIG::new();
+		let mut u=gs(e);
+		let mut w=FP24::new();
+
+		g[0].copy(&d);
+		for i in 1..8 {
+			w.copy(&g[i-1]);
+			g[i].copy(&w);
+			g[i].frob(&f,1);
+		}
+		for i in 0..8 {
+			let np=u[i].nbits();
+			t.copy(&BIG::modneg(&mut u[i],&q));
+			let nn=t.nbits();
+			if nn<np {
+				u[i].copy(&t);
+				g[i].conj();
+			}
+			u[i].norm();			
+		}
+		r.copy(&FP24::pow8(&mut g,&u));
+	} else {
+		r.copy(&d.pow(e));
+	}
+	return r;
+}
diff --git a/version3/rust/pair256.rs b/version3/rust/pair256.rs
new file mode 100644
index 0000000..702dcf0
--- /dev/null
+++ b/version3/rust/pair256.rs
@@ -0,0 +1,574 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+
+use xxx::fp::FP;
+use xxx::ecp::ECP;
+use xxx::fp2::FP2;
+use xxx::ecp8::ECP8;
+use xxx::fp8::FP8;
+use xxx::fp16::FP16;
+use xxx::fp48::FP48;
+use xxx::big::BIG;
+use xxx::ecp;
+use xxx::rom;
+
+#[allow(non_snake_case)]
+fn linedbl(A: &mut ECP8,qx: &FP,qy: &FP) -> FP48 {
+	let mut a=FP16::new();
+	let mut b=FP16::new();
+	let mut c=FP16::new();	
+
+	let mut xx=FP8::new_copy(&A.getpx());  //X
+	let mut yy=FP8::new_copy(&A.getpy());  //Y
+	let mut zz=FP8::new_copy(&A.getpz());  //Z
+	let mut yz=FP8::new_copy(&yy);        //Y 
+	yz.mul(&zz);                //YZ
+	xx.sqr();	               //X^2
+	yy.sqr();	               //Y^2
+	zz.sqr();			       //Z^2
+			
+	yz.imul(4);
+	yz.neg(); yz.norm();       //-2YZ
+	yz.tmul(qy);               //-2YZ.Ys
+
+	xx.imul(6);                //3X^2
+	xx.tmul(qx);               //3X^2.Xs
+
+	let sb=3*rom::CURVE_B_I;
+	zz.imul(sb); 	
+	if ecp::SEXTIC_TWIST==ecp::D_TYPE {				
+		zz.div_2i();  
+	}
+	if ecp::SEXTIC_TWIST==ecp::M_TYPE {	
+		zz.times_i();
+		zz.dbl();
+		yz.times_i();
+		//yz.norm();
+	}	
+
+	zz.norm(); // 3b.Z^2 
+
+	yy.dbl();
+	zz.sub(&yy); zz.norm();     // 3b.Z^2-Y^2
+
+	a.copy(&FP16::new_fp8s(&yz,&zz)); // -2YZ.Ys | 3b.Z^2-Y^2 | 3X^2.Xs 
+	if ecp::SEXTIC_TWIST==ecp::D_TYPE {		
+		b.copy(&FP16::new_fp8(&xx));       // L(0,1) | L(0,0) | L(1,0)
+	}
+	if ecp::SEXTIC_TWIST==ecp::M_TYPE {
+		c.copy(&FP16::new_fp8(&xx));
+		c.times_i();  
+	}		
+	A.dbl();
+	return FP48::new_fp16s(&a,&b,&c);	
+}
+
+#[allow(non_snake_case)]
+fn lineadd(A: &mut ECP8,B: &ECP8,qx: &FP,qy: &FP) -> FP48 {
+
+	let mut a=FP16::new();
+	let mut b=FP16::new();
+	let mut c=FP16::new();	
+
+	let mut x1=FP8::new_copy(&A.getpx());    // X1
+	let mut y1=FP8::new_copy(&A.getpy());    // Y1
+	let mut t1=FP8::new_copy(&A.getpz());    // Z1
+	let mut t2=FP8::new_copy(&A.getpz());    // Z1
+			
+	t1.mul(&B.getpy());    // T1=Z1.Y2 
+	t2.mul(&B.getpx());    // T2=Z1.X2
+
+	x1.sub(&t2); x1.norm();  // X1=X1-Z1.X2
+	y1.sub(&t1); y1.norm();  // Y1=Y1-Z1.Y2
+
+	t1.copy(&x1);            // T1=X1-Z1.X2
+	x1.tmul(qy);            // X1=(X1-Z1.X2).Ys
+	if ecp::SEXTIC_TWIST==ecp::M_TYPE {
+		x1.times_i();
+		//x1.norm();
+	}
+
+	t1.mul(&B.getpy());       // T1=(X1-Z1.X2).Y2
+
+	t2.copy(&y1);            // T2=Y1-Z1.Y2
+	t2.mul(&B.getpx());       // T2=(Y1-Z1.Y2).X2
+	t2.sub(&t1); t2.norm();          // T2=(Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2
+	y1.tmul(qx); y1.neg(); y1.norm(); // Y1=-(Y1-Z1.Y2).Xs
+
+	a.copy(&FP16::new_fp8s(&x1,&t2)); // (X1-Z1.X2).Ys  |  (Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2  | - (Y1-Z1.Y2).Xs
+	if ecp::SEXTIC_TWIST==ecp::D_TYPE {	
+		b.copy(&FP16::new_fp8(&y1));
+	}
+	if ecp::SEXTIC_TWIST==ecp::M_TYPE {
+		c.copy(&FP16::new_fp8(&y1));
+		c.times_i();
+	}	
+
+	A.add(B);
+	return FP48::new_fp16s(&a,&b,&c);
+}
+
+#[allow(non_snake_case)]
+/* Optimal R-ate pairing */
+pub fn ate(P1: &ECP8,Q1: &ECP) -> FP48 {
+	let x = BIG::new_ints(&rom::CURVE_BNX);
+	let n = BIG::new_copy(&x);
+
+	let mut n3 = BIG::new_copy(&n);
+	n3.pmul(3);
+	n3.norm();
+
+	let mut P=ECP8::new(); P.copy(P1); P.affine();
+	let mut Q=ECP::new(); Q.copy(Q1); Q.affine();
+
+	let qx=FP::new_copy(&Q.getpx());
+	let qy=FP::new_copy(&Q.getpy());
+
+	let mut A=ECP8::new();
+	let mut r=FP48::new_int(1);
+
+	A.copy(&P);
+	let mut NP=ECP8::new();
+	NP.copy(&P);
+	NP.neg();
+
+	let nb=n3.nbits();
+
+	for i in (1..nb-1).rev() {
+		r.sqr();		
+		let mut lv=linedbl(&mut A,&qx,&qy);
+		r.smul(&lv,ecp::SEXTIC_TWIST);
+		let bt=n3.bit(i)-n.bit(i);
+		if bt==1 {
+			lv=lineadd(&mut A,&P,&qx,&qy);
+			r.smul(&lv,ecp::SEXTIC_TWIST);
+		}		
+		if bt == -1 {
+
+			lv=lineadd(&mut A,&NP,&qx,&qy);
+			r.smul(&lv,ecp::SEXTIC_TWIST);	
+
+		}
+	}
+
+	if ecp::SIGN_OF_X == ecp::NEGATIVEX {
+		r.conj();			
+	}
+
+	return r;
+}
+
+#[allow(non_snake_case)]
+/* Optimal R-ate double pairing e(P,Q).e(R,S) */
+pub fn ate2(P1: &ECP8,Q1: &ECP,R1: &ECP8,S1: &ECP) -> FP48 {
+	let x = BIG::new_ints(&rom::CURVE_BNX);
+	let n = BIG::new_copy(&x);
+	
+	let mut n3 = BIG::new_copy(&n);
+	n3.pmul(3);
+	n3.norm();
+
+	let mut P=ECP8::new(); P.copy(P1); P.affine();
+	let mut Q=ECP::new(); Q.copy(Q1); Q.affine();
+	let mut R=ECP8::new(); R.copy(R1); R.affine();
+	let mut S=ECP::new(); S.copy(S1); S.affine();
+
+	let qx=FP::new_copy(&Q.getpx());
+	let qy=FP::new_copy(&Q.getpy());
+
+	let sx=FP::new_copy(&S.getpx());
+	let sy=FP::new_copy(&S.getpy());
+
+	let mut A=ECP8::new();
+	let mut B=ECP8::new();
+	let mut r=FP48::new_int(1);
+
+	A.copy(&P);
+	B.copy(&R);
+
+	let mut NP=ECP8::new();
+	NP.copy(&P);
+	NP.neg();
+	let mut NR=ECP8::new();
+	NR.copy(&R);
+	NR.neg();
+
+	let nb=n3.nbits();
+
+	for i in (1..nb-1).rev() {
+		r.sqr();		
+		let mut lv=linedbl(&mut A,&qx,&qy);
+		r.smul(&lv,ecp::SEXTIC_TWIST);
+		lv=linedbl(&mut B,&sx,&sy);
+		r.smul(&lv,ecp::SEXTIC_TWIST);
+		let bt=n3.bit(i)-n.bit(i);		
+		if bt == 1 {
+			lv=lineadd(&mut A,&P,&qx,&qy);
+			r.smul(&lv,ecp::SEXTIC_TWIST);
+			lv=lineadd(&mut B,&R,&sx,&sy);
+			r.smul(&lv,ecp::SEXTIC_TWIST);
+		}
+		if bt == -1 {
+
+			lv=lineadd(&mut A,&NP,&qx,&qy);
+			r.smul(&lv,ecp::SEXTIC_TWIST);
+			lv=lineadd(&mut B,&NR,&sx,&sy);
+			r.smul(&lv,ecp::SEXTIC_TWIST);
+
+		}
+	}
+
+	if ecp::SIGN_OF_X == ecp::NEGATIVEX {
+		r.conj();			
+	}
+
+	return r;
+}
+
+/* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */
+pub fn fexp(m: &FP48) -> FP48 {
+	let f = FP2::new_bigs(&BIG::new_ints(&rom::FRA),&BIG::new_ints(&rom::FRB));
+	let mut x = BIG::new_ints(&rom::CURVE_BNX);
+	let mut r=FP48::new_copy(m);
+		
+/* Easy part of final exp */
+	let mut lv=FP48::new_copy(&r);
+	lv.inverse();
+	r.conj();
+
+	r.mul(&lv);
+	lv.copy(&r);
+	r.frob(&f,8);
+	r.mul(&lv);
+
+/* Hard part of final exp */
+// Ghamman & Fouotsa Method
+
+
+	let mut t7=FP48::new_copy(&r); t7.usqr();
+	let mut t1=t7.pow(&mut x);
+
+	x.fshr(1);
+	let mut t2=t1.pow(&mut x);
+	x.fshl(1);
+
+	if ecp::SIGN_OF_X==ecp::NEGATIVEX {
+		t1.conj();
+	}
+
+	let mut t3=FP48::new_copy(&t1); t3.conj();
+	t2.mul(&t3);
+	t2.mul(&r);
+
+	r.mul(&t7);
+
+	t1.copy(&t2.pow(& mut x));
+
+	if ecp::SIGN_OF_X==ecp::NEGATIVEX {
+		t1.conj();
+	}
+	t3.copy(&t1);
+	t3.frob(&f,14);
+	r.mul(&t3);
+	lv.copy(&t1.pow(&mut x)); t1.copy(&lv);
+	if ecp::SIGN_OF_X==ecp::NEGATIVEX {
+		t1.conj();
+	}
+
+	t3.copy(&t1);
+	t3.frob(&f,13);
+	r.mul(&t3);
+	lv.copy(&t1.pow(&mut x)); t1.copy(&lv);
+	if ecp::SIGN_OF_X==ecp::NEGATIVEX {
+		t1.conj();
+	}
+
+	t3.copy(&t1);
+	t3.frob(&f,12);
+	r.mul(&t3);
+	lv.copy(&t1.pow(&mut x)); t1.copy(&lv);
+	if ecp::SIGN_OF_X==ecp::NEGATIVEX {
+		t1.conj();
+	}
+
+	t3.copy(&t1);
+	t3.frob(&f,11);
+	r.mul(&t3);
+	lv.copy(&t1.pow(&mut x)); t1.copy(&lv);
+	if ecp::SIGN_OF_X==ecp::NEGATIVEX {
+		t1.conj();
+	}
+
+	t3.copy(&t1);
+	t3.frob(&f,10);
+	r.mul(&t3);
+	lv.copy(&t1.pow(&mut x)); t1.copy(&lv);
+	if ecp::SIGN_OF_X==ecp::NEGATIVEX {
+		t1.conj();
+	}
+
+	t3.copy(&t1);
+	t3.frob(&f,9);
+	r.mul(&t3);
+	lv.copy(&t1.pow(&mut x)); t1.copy(&lv);
+	if ecp::SIGN_OF_X==ecp::NEGATIVEX {
+		t1.conj();
+	}
+
+	t3.copy(&t1);
+	t3.frob(&f,8);
+	r.mul(&t3);
+	lv.copy(&t1.pow(&mut x)); t1.copy(&lv);
+	if ecp::SIGN_OF_X==ecp::NEGATIVEX {
+		t1.conj();
+	}
+
+	t3.copy(&t2); t3.conj();
+	t1.mul(&t3);
+	t3.copy(&t1);
+	t3.frob(&f,7);
+	r.mul(&t3);
+	lv.copy(&t1.pow(&mut x)); t1.copy(&lv);
+	if ecp::SIGN_OF_X==ecp::NEGATIVEX {
+		t1.conj();
+	}
+
+	t3.copy(&t1);
+	t3.frob(&f,6);
+	r.mul(&t3);
+	lv.copy(&t1.pow(&mut x)); t1.copy(&lv);
+	if ecp::SIGN_OF_X==ecp::NEGATIVEX {
+		t1.conj();
+	}
+
+	t3.copy(&t1);
+	t3.frob(&f,5);
+	r.mul(&t3);
+	lv.copy(&t1.pow(&mut x)); t1.copy(&lv);
+	if ecp::SIGN_OF_X==ecp::NEGATIVEX {
+		t1.conj();
+	}
+
+	t3.copy(&t1);
+	t3.frob(&f,4);
+	r.mul(&t3);
+	lv.copy(&t1.pow(&mut x)); t1.copy(&lv);
+	if ecp::SIGN_OF_X==ecp::NEGATIVEX {
+		t1.conj();
+	}
+
+	t3.copy(&t1);
+	t3.frob(&f,3);
+	r.mul(&t3);
+	lv.copy(&t1.pow(&mut x)); t1.copy(&lv);
+	if ecp::SIGN_OF_X==ecp::NEGATIVEX {
+		t1.conj();
+	}
+
+	t3.copy(&t1);
+	t3.frob(&f,2);
+	r.mul(&t3);
+	lv.copy(&t1.pow(&mut x)); t1.copy(&lv);
+	if ecp::SIGN_OF_X==ecp::NEGATIVEX {
+		t1.conj();
+	}
+
+	t3.copy(&t1);
+	t3.frob(&f,1);
+	r.mul(&t3);
+	lv.copy(&t1.pow(&mut x)); t1.copy(&lv);
+	if ecp::SIGN_OF_X==ecp::NEGATIVEX {
+		t1.conj();
+	}
+	
+	r.mul(&t1);
+	t2.frob(&f,15);
+	r.mul(&t2);
+
+	r.reduce();
+	return r;
+}
+
+#[allow(non_snake_case)]
+/* GLV method */
+fn glv(e: &BIG) -> [BIG;2] {
+	let mut u:[BIG;2]=[BIG::new(),BIG::new()];
+	let q=BIG::new_ints(&rom::CURVE_ORDER);
+	let mut x=BIG::new_ints(&rom::CURVE_BNX);
+	let mut x2=BIG::smul(&x,&x);
+	x.copy(&BIG::smul(&x2,&x2));
+	x2.copy(&BIG::smul(&x,&x));	
+	u[0].copy(&e);  
+	u[0].rmod(&x2);
+	u[1].copy(&e); 
+	u[1].div(&x2);
+	u[1].rsub(&q);
+	
+	return u;
+}
+
+#[allow(non_snake_case)]
+/* Galbraith & Scott Method */
+pub fn gs(e: &BIG) -> [BIG;16] {
+	let mut u:[BIG;16]=[BIG::new(),BIG::new(),BIG::new(),BIG::new(),BIG::new(),BIG::new(),BIG::new(),BIG::new(),BIG::new(),BIG::new(),BIG::new(),BIG::new(),BIG::new(),BIG::new(),BIG::new(),BIG::new()];
+	let q=BIG::new_ints(&rom::CURVE_ORDER);	
+	let x=BIG::new_ints(&rom::CURVE_BNX);
+	let mut w=BIG::new_copy(&e);
+	for i in 0..15 {
+		u[i].copy(&w);
+		u[i].rmod(&x);
+		w.div(&x);
+	}
+	u[15].copy(&w);
+	if ecp::SIGN_OF_X == ecp::NEGATIVEX {
+		let mut t=BIG::new();	
+		t.copy(&BIG::modneg(&mut u[1],&q));
+		u[1].copy(&t);
+		t.copy(&BIG::modneg(&mut u[3],&q));	
+		u[3].copy(&t);	
+		t.copy(&BIG::modneg(&mut u[5],&q));
+		u[5].copy(&t);
+		t.copy(&BIG::modneg(&mut u[7],&q));	
+		u[7].copy(&t);			
+		t.copy(&BIG::modneg(&mut u[9],&q));
+		u[9].copy(&t);
+		t.copy(&BIG::modneg(&mut u[11],&q));	
+		u[11].copy(&t);	
+		t.copy(&BIG::modneg(&mut u[13],&q));
+		u[13].copy(&t);
+		t.copy(&BIG::modneg(&mut u[15],&q));	
+		u[15].copy(&t);				
+	}
+	return u;
+}	
+
+#[allow(non_snake_case)]
+/* Multiply P by e in group G1 */
+pub fn g1mul(P: &ECP,e: &mut BIG) -> ECP {
+	let mut R=ECP::new();
+	if rom::USE_GLV {
+	//	P.affine();
+		R.copy(P);
+		let mut Q=ECP::new();
+		Q.copy(P); Q.affine();
+		let q=BIG::new_ints(&rom::CURVE_ORDER);
+		let mut cru=FP::new_big(&BIG::new_ints(&rom::CURVE_CRU));
+		let mut u=glv(e);
+		Q.mulx(&mut cru);
+
+		let mut np=u[0].nbits();
+		let mut t:BIG=BIG::modneg(&mut u[0],&q);
+		let mut nn=t.nbits();
+		if nn<np {
+			u[0].copy(&t);
+			R.neg();
+		}
+
+		np=u[1].nbits();
+		t=BIG::modneg(&mut u[1],&q);
+		nn=t.nbits();
+		if nn<np {
+			u[1].copy(&t);
+			Q.neg();
+		}
+		u[0].norm();
+		u[1].norm();
+		R=R.mul2(&u[0],&mut Q,&u[1]);
+			
+	} else {
+		R=P.mul(e);
+	}
+	return R;
+}
+
+#[allow(non_snake_case)]
+/* Multiply P by e in group G2 */
+pub fn g2mul(P: &ECP8,e: &BIG) -> ECP8 {
+	let mut R=ECP8::new();
+	if rom::USE_GS_G2 {
+		let mut Q:[ECP8;16]=[ECP8::new(),ECP8::new(),ECP8::new(),ECP8::new(),ECP8::new(),ECP8::new(),ECP8::new(),ECP8::new(),ECP8::new(),ECP8::new(),ECP8::new(),ECP8::new(),ECP8::new(),ECP8::new(),ECP8::new(),ECP8::new()];
+		let q=BIG::new_ints(&rom::CURVE_ORDER);
+		let mut u=gs(e);
+		let mut T=ECP8::new();
+
+		let f=ECP8::frob_constants();
+
+		let mut t=BIG::new();
+		//P.affine();
+		Q[0].copy(&P);
+		for i in 1..16 {
+			T.copy(&Q[i-1]);
+			Q[i].copy(&T);
+			Q[i].frob(&f,1);
+		}
+		for i in 0..16 {
+			let np=u[i].nbits();
+			t.copy(&BIG::modneg(&mut u[i],&q));
+			let nn=t.nbits();
+			if nn<np {
+				u[i].copy(&t);
+				Q[i].neg();
+			}
+			u[i].norm();
+		}
+
+		R.copy(&ECP8::mul16(&mut Q,&u));
+
+	} else {
+		R.copy(&P.mul(e));
+	}
+	return R;
+}
+
+/* f=f^e */
+/* Note that this method requires a lot of RAM! Better to use compressed XTR method, see FP4.java */
+pub fn gtpow(d: &FP48,e: &BIG) -> FP48 {
+	let mut r=FP48::new();
+	if rom::USE_GS_GT {
+		let mut g:[FP48;16]=[FP48::new(),FP48::new(),FP48::new(),FP48::new(),FP48::new(),FP48::new(),FP48::new(),FP48::new(),FP48::new(),FP48::new(),FP48::new(),FP48::new(),FP48::new(),FP48::new(),FP48::new(),FP48::new()];
+		let f = FP2::new_bigs(&BIG::new_ints(&rom::FRA),&BIG::new_ints(&rom::FRB));
+		let q=BIG::new_ints(&rom::CURVE_ORDER);
+		let mut t=BIG::new();
+		let mut u=gs(e);
+		let mut w=FP48::new();
+
+		g[0].copy(&d);
+		for i in 1..16 {
+			w.copy(&g[i-1]);
+			g[i].copy(&w);
+			g[i].frob(&f,1);
+		}
+		for i in 0..16 {
+			let np=u[i].nbits();
+			t.copy(&BIG::modneg(&mut u[i],&q));
+			let nn=t.nbits();
+			if nn<np {
+				u[i].copy(&t);
+				g[i].conj();
+			}
+			u[i].norm();			
+		}
+		r.copy(&FP48::pow16(&mut g,&u));
+	} else {
+		r.copy(&d.pow(e));
+	}
+	return r;
+}
+
diff --git a/version3/rust/rand.rs b/version3/rust/rand.rs
new file mode 100644
index 0000000..fadd91d
--- /dev/null
+++ b/version3/rust/rand.rs
@@ -0,0 +1,147 @@
+/*
+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.
+*/
+
+//mod hash256;
+
+use hash256::HASH256;
+
+const RAND_NK: usize=21;
+const RAND_NJ: usize=6;
+const RAND_NV: usize=8;
+
+pub struct RAND {
+	ira: [u32;RAND_NK],  /* random number...   */
+	rndptr: usize,
+	borrow: u32,
+	pool_ptr: usize,
+	pool: [u8;32]
+}
+
+impl RAND {
+
+	pub fn new() -> RAND {
+		RAND {
+			ira: [0;RAND_NK],
+			rndptr:0,
+			borrow: 0,
+			pool_ptr:0,
+			pool:[0;32]
+		}
+	}
+
+	pub fn clean(&mut self) {
+		self.pool_ptr=0; self.rndptr=0;
+		for i in 0..32 {self.pool[i]=0}
+		for i in 0..RAND_NK {self.ira[i]=0}
+		self.borrow=0;		
+	}
+
+	fn sbrand(&mut self) -> u32 { /* Marsaglia & Zaman random number generator */
+		self.rndptr+=1;
+		if self.rndptr<RAND_NK {return self.ira[self.rndptr]}
+		self.rndptr=0;
+		let mut k=RAND_NK-RAND_NJ;
+		for i in 0..RAND_NK { /* calculate next NK values */
+			if k==RAND_NK {k=0}
+			let t=self.ira[k];
+			let pdiff=t.wrapping_sub(self.ira[i]).wrapping_sub(self.borrow);
+			if pdiff<t {self.borrow=0}
+			if pdiff>t {self.borrow=1}
+			self.ira[i]=pdiff; 
+			k+=1;
+		}
+		return self.ira[0];
+	}
+
+	fn sirand(&mut self,seed: u32) {
+		let mut m: u32=1;
+		let mut sd=seed;
+		self.borrow=0;
+		self.rndptr=0;
+		self.ira[0]^=sd;
+		for i in 1..RAND_NK { /* fill initialisation vector */
+			let inn=(RAND_NV*i)%RAND_NK;
+			self.ira[inn]^=m;      /* note XOR */
+			let t=m;
+			m=sd.wrapping_sub(m);
+			sd=t;
+		}
+		for _ in 0..10000 {self.sbrand();} /* "warm-up" & stir the generator */
+	}
+
+	fn fill_pool(&mut self) {
+		let mut sh=HASH256::new();
+		for _ in 0..128 {sh.process((self.sbrand()&0xff) as u8)}
+		let w=sh.hash();
+		for i in 0..32 {self.pool[i]=w[i]}
+		self.pool_ptr=0;
+	}
+
+	fn pack(b: [u8;4]) -> u32 { /* pack 4 bytes into a 32-bit Word */
+		return ((((b[3] as u32))&0xff)<<24)|(((b[2] as u32)&0xff)<<16)|(((b[1] as u32)&0xff)<<8)|((b[0] as u32)&0xff);
+	}
+
+/* Initialize RNG with some real entropy from some external source */
+	pub fn seed(&mut self,rawlen: usize,raw: &[u8]) { /* initialise from at least 128 byte string of raw random entropy */
+		let mut b: [u8;4]=[0;4];
+		let mut sh=HASH256::new();
+		self.pool_ptr=0;
+
+		for i in 0..RAND_NK {self.ira[i]=0}
+		if rawlen>0 {
+			for i in 0..rawlen {
+				sh.process(raw[i]);
+			}
+			let digest=sh.hash();
+
+/* initialise PRNG from distilled randomness */
+
+			for i in 0..8  {
+				b[0]=digest[4*i]; b[1]=digest[4*i+1]; b[2]=digest[4*i+2]; b[3]=digest[4*i+3];
+				self.sirand(RAND::pack(b));
+			}
+		}
+		self.fill_pool();
+	}	
+
+/* get random byte */
+	pub fn getbyte(&mut self) -> u8 { 
+		let r=self.pool[self.pool_ptr];
+		self.pool_ptr+=1;
+		if self.pool_ptr>=32 {self.fill_pool()}
+		return (r&0xff) as u8;
+	}
+}
+
+/* test main program */
+/*
+fn main() {
+	let mut raw : [u8;100]=[0;100];
+	let mut rng=RAND::new();
+
+	rng.clean();
+	for i in 0..100 {raw[i]=i as u8}
+
+	rng.seed(100,&raw);
+ 
+	for _ in 0..1000 {
+		print!("{:03} ",rng.getbyte());
+	}
+}
+*/
diff --git a/version3/rust/readme.txt b/version3/rust/readme.txt
new file mode 100644
index 0000000..ccff216
--- /dev/null
+++ b/version3/rust/readme.txt
@@ -0,0 +1,40 @@
+NOTE: This version of the library requires Version 1.17+ of Rust for 64-bit 
+support. Unfortunately support for the 128-bit integer type is still
+flagged as unstable, and so for now a nightly build of rust must be used.
+
+NEW: 128-bit integers are now stable with version 1.26. So please use latest 
+version.
+
+Namespaces are used to separate different curves.
+
+To build the library and see it in action, copy all of the files in this 
+directory to a fresh root directory. Then execute the python3 script 
+config32.py or config64.py (depending on whether you want a 32 or 64-bit 
+build), and select the curves that you wish to support. Libraries will be 
+built automatically including all of the modules that you will need.
+
+As a quick example execute from your root directory
+
+py config64.py
+
+or
+
+python3 config64.py
+
+Then select options 1, 3, 7, 18, 20, 25, 26 and 27 (these are fixed for 
+the example program provided). Select 0 to exit.
+
+Then copy the library from amcl/target/release/libamcl.rlib to the
+root directory, and execute
+
+rustc TestALL.rs --extern amcl=libamcl.rlib
+
+Run this test program by executing the program TestALL
+
+rustc BenchtestALL.rs --extern amcl=libamcl.rlib
+
+Run this test program by executing the program BenchtestALL
+
+
+
+
diff --git a/version3/rust/rom_anssi_32.rs b/version3/rust/rom_anssi_32.rs
new file mode 100644
index 0000000..dce8b58
--- /dev/null
+++ b/version3/rust/rom_anssi_32.rs
@@ -0,0 +1,39 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use anssi::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 28
+// anssi Modulus 
+pub const MODULUS:[Chunk;NLEN]=[0x86E9C03,0xFCF353D,0x8CA6DE8,0xADBCABC,0x35B3961,0xE8CE424,0xF10126D,0xB3AD58,0x1FD178C,0xF];
+pub const R2MODP:[Chunk;NLEN]=[0x288CC9C,0x18D2374,0x646BD2B,0x4929E67,0xD6F7F2D,0x220E6C1,0xABCE02E,0x751B1FD,0x7401B78,0xE];
+pub const MCONST:Chunk=0x64E1155;
+
+// anssi Curve
+
+pub const CURVE_COF_I:isize = 1;
+pub const CURVE_A:isize = -3;
+pub const CURVE_B_I:isize = 0;
+pub const CURVE_COF:[Chunk;NLEN]=[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_B:[Chunk;NLEN]=[0xB7BB73F,0x75ED967,0x1A18030,0xC9AE4B,0xFDFEC,0x754A44C,0xD4ABA,0x5428A93,0xE353FCA,0xE];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0x6D655E1,0xFDD459C,0x2BF941F,0x67E140D,0x35B53DC,0xE8CE424,0xF10126D,0xB3AD58,0x1FD178C,0xF];
+pub const CURVE_GX:[Chunk;NLEN]=[0x98F5CFF,0xC97A2DD,0x8B70164,0xD2DCAF9,0x3958C27,0x4749D42,0xB31183D,0x56C139E,0x6B3D4C3,0xB];
+pub const CURVE_GY:[Chunk;NLEN]=[0x4062CFB,0x115A155,0x4C9E183,0xC307E8E,0xF8C2701,0xF0F3ECE,0x11F9271,0xC8B2049,0x142E0F7,0x6];
+
diff --git a/version3/rust/rom_anssi_64.rs b/version3/rust/rom_anssi_64.rs
new file mode 100644
index 0000000..dde7f66
--- /dev/null
+++ b/version3/rust/rom_anssi_64.rs
@@ -0,0 +1,39 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use anssi::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 56
+// anssi Modulus 
+pub const MODULUS:[Chunk;NLEN]=[0xFCF353D86E9C03,0xADBCABC8CA6DE8,0xE8CE42435B3961,0xB3AD58F10126D,0xF1FD178C];
+pub const R2MODP:[Chunk;NLEN]=[0x18D2374288CC9C,0x4929E67646BD2B,0x220E6C1D6F7F2D,0x751B1FDABCE02E,0xE7401B78];
+pub const MCONST:Chunk=0x97483A164E1155;
+
+// anssi Curve 
+
+pub const CURVE_COF_I:isize = 1;
+pub const CURVE_A:isize = -3;
+pub const CURVE_B_I:isize = 0;
+pub const CURVE_COF:[Chunk;NLEN]=[0x1,0x0,0x0,0x0,0x0];
+pub const CURVE_B:[Chunk;NLEN]=[0x75ED967B7BB73F,0xC9AE4B1A18030,0x754A44C00FDFEC,0x5428A9300D4ABA,0xEE353FCA];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0xFDD459C6D655E1,0x67E140D2BF941F,0xE8CE42435B53DC,0xB3AD58F10126D,0xF1FD178C];
+pub const CURVE_GX:[Chunk;NLEN]=[0xC97A2DD98F5CFF,0xD2DCAF98B70164,0x4749D423958C27,0x56C139EB31183D,0xB6B3D4C3];
+pub const CURVE_GY:[Chunk;NLEN]=[0x115A1554062CFB,0xC307E8E4C9E183,0xF0F3ECEF8C2701,0xC8B204911F9271,0x6142E0F7];
+
diff --git a/version3/rust/rom_bls24_32.rs b/version3/rust/rom_bls24_32.rs
new file mode 100644
index 0000000..c9c7497
--- /dev/null
+++ b/version3/rust/rom_bls24_32.rs
@@ -0,0 +1,59 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use bls24::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 29
+// bls24 Modulus
+
+pub const MODULUS:[Chunk;NLEN]=[0xA06152B,0x2260B3A,0xB4C36BE,0x5FFC5D0,0xBDB6A64,0x5B78E2E,0x1C1A28CA,0x10E6441B,0x1F244061,0xB4704F0,0x141E5CCD,0x9837504,0x3F2E77E,0xD763740,0x1316EA0E,0xF0079,0x555C];
+pub const R2MODP:[Chunk;NLEN]=[0x8533EA9,0x6A02789,0x183B24DE,0x1E45ECF8,0xC8F8F37,0x10CAD209,0x4C0C4B8,0x9B1FABD,0xDEBE4C0,0xDC353F9,0x18A18E26,0x10F489BB,0x31206A5,0x19673BBF,0x6BE69F9,0xB091169,0x9CD];
+pub const MCONST:Chunk=0x95FE7D;
+pub const FRA:[Chunk;NLEN]=[0x1BF96F1D,0xAE53A55,0x31BFEEB,0x183FF17A,0x6237469,0x12A4F4F1,0x12101FE3,0x16E79D94,0xFF59267,0x5EB4EB4,0x78CC49F,0x274BA33,0x149184F3,0x16C6DCBA,0x1C90B694,0x10F729CE,0x4BBC];
+pub const FRB:[Chunk;NLEN]=[0xE0CA60E,0x1740D0E4,0x83037D2,0xDBFD456,0x5B7F5FA,0x1312993D,0xA0A08E6,0x19FEA687,0xF2EADF9,0x55BB63C,0xC91982E,0x70EBAD1,0xF61628B,0x16AF5A85,0x16863379,0xF17D6AA,0x99F];
+
+pub const CURVE_COF_I:isize = 0;
+pub const CURVE_A:isize = 0;
+pub const CURVE_B_I:isize = 19;
+pub const CURVE_B:[Chunk;NLEN]=[0x13,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0x10000001,0xD047FF,0x1FD54464,0x1E3CE067,0xE322DDA,0x1D356F3F,0x7433B44,0x49091F9,0x1729CC2,0x250286C,0x16E62ED,0xB403E1E,0x1001000,0x80,0x0,0x0,0x0];
+pub const CURVE_GX:[Chunk;NLEN]=[0xBE3CCD4,0x33B07AF,0x1B67D159,0x3DFC5B5,0xEBA1FCC,0x1A3C1F84,0x56BE204,0xEF8DF1B,0x11AE2D84,0x5FEE546,0x161B3BF9,0x183B20EE,0x1EA5D99B,0x14F0C5BF,0xBE521B7,0x17C682F9,0x1AB2];
+pub const CURVE_GY:[Chunk;NLEN]=[0x121E5245,0x65D2E56,0x11577DB1,0x16DACC11,0x14F39746,0x459F694,0x12483FCF,0xC828B04,0xFD63E5A,0x7B1D52,0xAFDE738,0xF349254,0x1A4529FF,0x10E53353,0xF91DEE1,0x16E18D8A,0x47FC];
+
+pub const CURVE_BNX:[Chunk;NLEN]=[0x11FF80,0x80010,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_COF:[Chunk;NLEN]=[0x19F415AB,0x1E0FFDFF,0x15AAADFF,0xAA,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_CRU:[Chunk;NLEN]=[0xDD794A9,0x1DE138A3,0x2BCCE90,0xC746127,0x15223DDC,0x1DD8890B,0xED08DB7,0xE24B9F,0xE379CE6,0x37011AC,0x11BAC820,0x1EEFAD01,0x200860F,0x147218A6,0xF16A209,0xF0079,0x555C];
+pub const CURVE_PXAA:[Chunk;NLEN]=[0x14E24678,0x1F149A9B,0x9609022,0x1C186868,0xCDEFC69,0x1C87BB2E,0x14A2235F,0x7586755,0x5896747,0x159BFE92,0x3B5572E,0x1710A521,0x71EB14A,0xC643C33,0x12581DE5,0x1BCA747D,0x959];
+pub const CURVE_PXAB:[Chunk;NLEN]=[0x1FB099B8,0x3FCF5D7,0x4A91C0E,0xC6EEB40,0x11FC2385,0x11B5AE8D,0x1A9CC3E7,0x194FE144,0x185DB2A5,0x930E1C7,0x14F85F9A,0x1F2ED4E,0x1D1BE5AD,0xF26169C,0xCF7F194,0x1DA1062E,0x3B0D];
+pub const CURVE_PXBA:[Chunk;NLEN]=[0x11AD15D3,0xD0E6F38,0x17DB85BB,0x30A62F1,0x1EA3E09A,0x17B25FA1,0x1B7959AC,0x1165B19A,0x6C74FDB,0x18F790E1,0x12278FDA,0x1E008F79,0x103F329,0x14619FF1,0x1EBCAA8,0xFF5A9CA,0x3EC2];
+pub const CURVE_PXBB:[Chunk;NLEN]=[0x1EE0F480,0x3D5943A,0xF5B12E3,0x128AADC8,0x180E1CB9,0x1EFD916F,0x48BC7F,0x1D5EE1FA,0x5698EF5,0x11D6AED9,0x1386BC6E,0x196E900B,0x1CE2E465,0xC2A8ED3,0x1E67DF99,0x71B7940,0xA5B];
+pub const CURVE_PYAA:[Chunk;NLEN]=[0x14781AA0,0xC324C98,0xEDC2AC,0x16C13B46,0x145FC44B,0x12529530,0x1310A8C4,0x1768C5C0,0xE19AE68,0x56E1C1D,0x13DAF93F,0x17E94366,0xF901AD0,0x76800CC,0x10250D8B,0x1E6BAE6D,0x5057];
+pub const CURVE_PYAB:[Chunk;NLEN]=[0xEAE08FA,0xDDF62BF,0xA97E5AB,0xF0EE97,0x99A42CA,0x1C326578,0xF33DC11,0x8B913F7,0xFEF8552,0x19F35B90,0x58DDBDE,0xFC32FF2,0x1587B5DF,0xB5EB07A,0x1A258DE0,0x1692CC3D,0x2CE2];
+pub const CURVE_PYBA:[Chunk;NLEN]=[0x5F0CC41,0xB9813B5,0x14C2A87D,0xFF1264A,0x19AF8A14,0x6CE6C3,0x2A7F8A2,0x121DCA7D,0x7D37153,0x19D21078,0x15466DC7,0x1362982B,0x1DD3CB5B,0x1CFC0D1C,0x18C69AF8,0x8CC7DC,0x1807];
+pub const CURVE_PYBB:[Chunk;NLEN]=[0x115C1CAE,0x78D9732,0x16C26237,0x5A81A6A,0x1C38A777,0x56121FE,0x4DAD9D7,0x1BEBA670,0xA1D72FC,0xD60B274,0x19734258,0x1D621775,0x4691771,0x14206B68,0x17B22DE4,0x29D5B37,0x499D];
+pub const CURVE_W:[[Chunk;NLEN];2]=[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]];
+pub const CURVE_SB:[[[Chunk;NLEN];2];2]=[[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]];
+pub const CURVE_WB:[[Chunk;NLEN];4]=[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]];
+pub const CURVE_BB:[[[Chunk;NLEN];4];4]=[[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]];
+
+pub const USE_GLV:bool = true;
+pub const USE_GS_G2:bool = true;
+pub const USE_GS_GT:bool = true;
+pub const GT_STRONG:bool = true;
diff --git a/version3/rust/rom_bls24_64.rs b/version3/rust/rom_bls24_64.rs
new file mode 100644
index 0000000..0bfe82a
--- /dev/null
+++ b/version3/rust/rom_bls24_64.rs
@@ -0,0 +1,59 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use bls24::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 56
+// bls24 Modulus
+
+pub const MODULUS:[Chunk;NLEN]=[0x44C1674A06152B,0xFFE2E82D30DAF8,0x6F1C5CBDB6A642,0x3220DF068A328B,0xE09E1F24406187,0xBA825079733568,0x6E803F2E77E4C1,0x3CCC5BA839AEC,0x555C0078];
+pub const R2MODP:[Chunk;NLEN]=[0x6A4A1FE013DF5B,0xE8E46D4D1BDE65,0x1F841391F45C67,0x9148A4516FB28,0x4398524EDF4C88,0x41C0E241B6DCE8,0xE42C208C19411,0xA7FE6FD73A7B1C,0xFCCCA76];
+pub const MCONST:Chunk=0xBD5D7D8095FE7D;
+pub const FRA:[Chunk;NLEN]=[0x5CA74ABBF96F1D,0x1FF8BD0C6FFBAD,0x49E9E26237469C,0x3CECA48407F8E5,0x69D68FF59267B7,0x5D199E33127CBD,0xB97549184F313A,0x4E77242DA52D8D,0x4BBC87B9];
+pub const FRB:[Chunk;NLEN]=[0xE81A1C8E0CA60E,0xDFEA2B20C0DF4A,0x25327A5B7F5FA6,0xF5343A828239A6,0x76C78F2EADF9CF,0x5D68B24660B8AB,0xB50AF61628B387,0xB555A18CDE6D5E,0x99F78BE];
+
+pub const CURVE_COF_I:isize = 0;
+pub const CURVE_A:isize = 0;
+pub const CURVE_B_I:isize = 19;
+pub const CURVE_B:[Chunk;NLEN]=[0x13,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0x1A08FFF0000001,0x1E7033FF551190,0x6ADE7EE322DDAF,0x848FC9D0CED13A,0x50D81729CC224,0x1F0F05B98BB44A,0x10010010005A0,0x0,0x0];
+pub const CURVE_GX:[Chunk;NLEN]=[0x6760F5EBE3CCD4,0xEFE2DAED9F4564,0x783F08EBA1FCC1,0xC6F8D95AF88134,0xDCA8D1AE2D8477,0x9077586CEFE4BF,0x8B7FEA5D99BC1D,0x17CAF9486DE9E1,0x1AB2BE34];
+pub const CURVE_GY:[Chunk;NLEN]=[0xCBA5CAD21E5245,0x6D6608C55DF6C4,0xB3ED294F39746B,0x145824920FF3C8,0x63AA4FD63E5A64,0x492A2BF79CE00F,0x66A7A4529FF79A,0x6C53E477B861CA,0x47FCB70C];
+
+pub const CURVE_BNX:[Chunk;NLEN]=[0x100020011FF80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_COF:[Chunk;NLEN]=[0xC1FFBFF9F415AB,0x5556AAB7FF,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_CRU:[Chunk;NLEN]=[0xBC27146DD794A9,0x3A30938AF33A43,0xB112175223DDC6,0x125CFBB4236DFB,0x2358E379CE607,0xD680C6EB20806E,0x314C200860FF77,0x3CBC5A88268E4,0x555C0078];
+pub const CURVE_PXAA:[Chunk;NLEN]=[0xE2935374E24678,0xC34342582408B,0xF765CCDEFC69E,0xC33AAD2888D7F9,0x7FD2458967473A,0x52908ED55CBAB3,0x786671EB14AB88,0xA3EC96077958C8,0x959DE53];
+pub const CURVE_PXAB:[Chunk;NLEN]=[0x7F9EBAFFB099B8,0x3775A012A47038,0x6B5D1B1FC23856,0x7F0A26A730F9E3,0x1C38F85DB2A5CA,0x76A753E17E6926,0x2D39D1BE5AD0F9,0x31733DFC651E4C,0x3B0DED08];
+pub const CURVE_PXBA:[Chunk;NLEN]=[0xA1CDE711AD15D3,0x853178DF6E16ED,0x64BF43EA3E09A1,0x2D8CD6DE566B2F,0xF21C26C74FDB8B,0x47BCC89E3F6B1E,0x3FE2103F329F00,0x4E507AF2AA28C3,0x3EC27FAD];
+pub const CURVE_PXBB:[Chunk;NLEN]=[0x7AB2875EE0F480,0x4556E43D6C4B8C,0xFB22DF80E1CB99,0xF70FD0122F1FFD,0xD5DB25698EF5EA,0x4805CE1AF1BA3A,0x1DA7CE2E465CB7,0xCA0799F7E65855,0xA5B38DB];
+pub const CURVE_PYAA:[Chunk;NLEN]=[0x86499314781AA0,0x609DA303B70AB1,0xA52A6145FC44BB,0x462E04C42A3124,0xC383AE19AE68BB,0xA1B34F6BE4FCAD,0x198F901AD0BF4,0x736C094362CED0,0x5057F35D];
+pub const CURVE_PYAB:[Chunk;NLEN]=[0xBBEC57EEAE08FA,0x78774BAA5F96AD,0x64CAF099A42CA0,0xC89FBBCCF70478,0x6B720FEF855245,0x97F916376F7B3E,0x60F5587B5DF7E1,0x61EE89637816BD,0x2CE2B496];
+pub const CURVE_PYBA:[Chunk;NLEN]=[0x730276A5F0CC41,0xF89325530AA1F5,0xD9CD879AF8A147,0xEE53E8A9FE2880,0x420F07D3715390,0x4C15D519B71F3A,0x1A39DD3CB5B9B1,0x3EE631A6BE39F8,0x18070466];
+pub const CURVE_PYBB:[Chunk;NLEN]=[0xF1B2E6515C1CAE,0xD40D355B0988DC,0xC243FDC38A7772,0x5D338136B675CA,0x164E8A1D72FCDF,0xBBAE5CD0961AC,0xD6D04691771EB1,0xD9BDEC8B792840,0x499D14EA];
+pub const CURVE_W:[[Chunk;NLEN];2]=[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]];
+pub const CURVE_SB:[[[Chunk;NLEN];2];2]=[[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]];
+pub const CURVE_WB:[[Chunk;NLEN];4]=[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]];
+pub const CURVE_BB:[[[Chunk;NLEN];4];4]=[[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]];
+
+pub const USE_GLV:bool = true;
+pub const USE_GS_G2:bool = true;
+pub const USE_GS_GT:bool = true;
+pub const GT_STRONG:bool = true;
diff --git a/version3/rust/rom_bls381_32.rs b/version3/rust/rom_bls381_32.rs
new file mode 100644
index 0000000..c39e477
--- /dev/null
+++ b/version3/rust/rom_bls381_32.rs
@@ -0,0 +1,57 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use bls381::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 29
+// bls381 Modulus
+
+pub const MODULUS:[Chunk;NLEN]=[0x1FFFAAAB,0xFF7FFFF,0x14FFFFEE,0x17FFFD62,0xF6241EA,0x9507B58,0xAFD9CC3,0x109E70A2,0x1764774B,0x121A5D66,0x12C6E9ED,0x12FFCD34,0x111EA3,0xD];
+pub const R2MODP:[Chunk;NLEN]=[0x15BEF7AE,0x1031CD0E,0x2DD93E8,0x9226323,0xE6E2CD2,0x11684DAA,0x1170E5DB,0x88E25B1,0x1B366399,0x1C536F47,0xD1F9CBC,0x278B67F,0x1EA66A2B,0xC];
+pub const MCONST:Chunk=0x1FFCFFFD;
+pub const FRA:[Chunk;NLEN]=[0x12235FB8,0x83BAF6C,0x19E04F63,0x1D4A7AC7,0xB9C4F67,0x1EBC25D,0x1D3DEC91,0x1FA797AB,0x1F0FD603,0x1016068,0x108C6FAD,0x5760CCF,0x104D3BF0,0xC];
+pub const FRB:[Chunk;NLEN]=[0xDDC4AF3,0x7BC5093,0x1B1FB08B,0x1AB5829A,0x3C5F282,0x764B8FB,0xDBFB032,0x10F6D8F6,0x1854A147,0x1118FCFD,0x23A7A40,0xD89C065,0xFC3E2B3,0x0];
+
+pub const CURVE_COF_I:isize = 0;
+pub const CURVE_A:isize = 0;
+pub const CURVE_B_I:isize = 4;
+pub const CURVE_B:[Chunk;NLEN]=[0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0x1,0x1FFFFFF8,0x1F96FFBF,0x1B4805FF,0x1D80553B,0xC0404D0,0x1520CCE7,0xA6533AF,0x73EDA7,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_GX:[Chunk;NLEN]=[0x1B22C6BB,0x19D78056,0x1E86BBFE,0xBD07FF2,0x1AC586C5,0x1D1F8B8D,0x4168538,0x9F2EE97,0xFC3688C,0x27D4D60,0x9A558E3,0x32FAF28,0x1F1D3A73,0xB];
+pub const CURVE_GY:[Chunk;NLEN]=[0x6C5E7E1,0x551194A,0x222B903,0x198E8945,0xB3EDD03,0xC659602,0xBD8036C,0x12BABA01,0x4FCF5E0,0xBA0EC57,0x8278C3B,0x75541E3,0xB3F481E,0x4];
+
+
+pub const CURVE_BNX:[Chunk;NLEN]=[0x10000,0x10080000,0x34,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_COF:[Chunk;NLEN]=[0xAAAB,0x55558,0x157855A3,0x191800AA,0x396,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_CRU:[Chunk;NLEN]=[0x1FFEFFFE,0x100FFFFF,0x280008B,0xFB026C4,0x9688DE1,0x149DF37C,0x1FAB76CE,0xED41EE,0x11BA69C6,0x1EFBB672,0x17C659CB,0x0,0x0,0x0];
+
+pub const CURVE_PXA:[Chunk;NLEN]=[0x121BDB8,0x402B646,0x16EFBF5,0x18064D50,0x1D1770BA,0x5B23D71,0xC0AD144,0x1A9F4807,0x11C6E47A,0x196E2882,0x9820149,0x11E1522,0x4AA2B2F,0x1];
+pub const CURVE_PXB:[Chunk;NLEN]=[0x1D042B7E,0xD63E82A,0x51755F9,0x19E22427,0x15049334,0x10DDEE3F,0x186AD769,0x1A132416,0x5596BD0,0x4413A7B,0x1F6B34E8,0x4E33EC0,0x1E02B605,0x9];
+pub const CURVE_PYA:[Chunk;NLEN]=[0x8B82801,0xC9AA430,0xB28A278,0x15939877,0xD12C923,0xD34A8B0,0xE9DB50A,0x155197BA,0x1AADFD9B,0x16D171A8,0x3327371,0x4FADC23,0xE5D5277,0x6];
+pub const CURVE_PYB:[Chunk;NLEN]=[0x105F79BE,0x15483AFF,0x1B07686A,0xE1A4EB9,0x99AB3F3,0x955AB97,0xEBC99D2,0xFD0B4EC,0x19CB3E28,0x15E145C,0xCAB34AC,0x1D4E6998,0x6C4A02,0x3];
+pub const CURVE_W:[[Chunk;NLEN];2]=[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]];
+pub const CURVE_SB:[[[Chunk;NLEN];2];2]=[[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]];
+pub const CURVE_WB:[[Chunk;NLEN];4]=[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]];
+pub const CURVE_BB:[[[Chunk;NLEN];4];4]=[[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]];
+
+pub const USE_GLV:bool = true;
+pub const USE_GS_G2:bool = true;
+pub const USE_GS_GT:bool = true;
+pub const GT_STRONG:bool = false;
diff --git a/version3/rust/rom_bls381_64.rs b/version3/rust/rom_bls381_64.rs
new file mode 100644
index 0000000..cdfaeee
--- /dev/null
+++ b/version3/rust/rom_bls381_64.rs
@@ -0,0 +1,56 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use bls381::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 58
+// bls381 Modulus
+
+pub const MODULUS:[Chunk;NLEN]=[0x1FEFFFFFFFFAAAB,0x2FFFFAC54FFFFEE,0x12A0F6B0F6241EA,0x213CE144AFD9CC3,0x2434BACD764774B,0x25FF9A692C6E9ED,0x1A0111EA3];
+pub const R2MODP:[Chunk;NLEN]=[0x20639A1D5BEF7AE,0x1244C6462DD93E8,0x22D09B54E6E2CD2,0x111C4B63170E5DB,0x38A6DE8FB366399,0x4F16CFED1F9CBC,0x19EA66A2B];
+pub const MCONST:Chunk=0x1F3FFFCFFFCFFFD;
+pub const FRA:[Chunk;NLEN]=[0x10775ED92235FB8,0x3A94F58F9E04F63,0x3D784BAB9C4F67,0x3F4F2F57D3DEC91,0x202C0D1F0FD603,0xAEC199F08C6FAD,0x1904D3BF0];
+pub const FRB:[Chunk;NLEN]=[0xF78A126DDC4AF3,0x356B0535B1FB08B,0xEC971F63C5F282,0x21EDB1ECDBFB032,0x2231F9FB854A147,0x1B1380CA23A7A40,0xFC3E2B3];
+
+pub const CURVE_COF_I:isize = 0;
+pub const CURVE_A:isize = 0;
+pub const CURVE_B_I:isize = 4;
+pub const CURVE_B:[Chunk;NLEN]=[0x4,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0x3FFFFFF00000001,0x36900BFFF96FFBF,0x180809A1D80553B,0x14CA675F520CCE7,0x73EDA7,0x0,0x0];
+pub const CURVE_GX:[Chunk;NLEN]=[0x33AF00ADB22C6BB,0x17A0FFE5E86BBFE,0x3A3F171BAC586C5,0x13E5DD2E4168538,0x4FA9AC0FC3688C,0x65F5E509A558E3,0x17F1D3A73];
+pub const CURVE_GY:[Chunk;NLEN]=[0xAA232946C5E7E1,0x331D128A222B903,0x18CB2C04B3EDD03,0x25757402BD8036C,0x1741D8AE4FCF5E0,0xEAA83C68278C3B,0x8B3F481E];
+
+pub const CURVE_BNX:[Chunk;NLEN]=[0x201000000010000,0x34,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_COF:[Chunk;NLEN]=[0xAAAB0000AAAB,0x3230015557855A3,0x396,0x0,0x0,0x0,0x0];
+pub const CURVE_CRU:[Chunk;NLEN]=[0x201FFFFFFFEFFFE,0x1F604D88280008B,0x293BE6F89688DE1,0x1DA83DDFAB76CE,0x3DF76CE51BA69C6,0x17C659CB,0x0];
+
+pub const CURVE_PXA:[Chunk;NLEN]=[0x8056C8C121BDB8,0x300C9AA016EFBF5,0xB647AE3D1770BA,0x353E900EC0AD144,0x32DC51051C6E47A,0x23C2A449820149,0x24AA2B2F];
+pub const CURVE_PXB:[Chunk;NLEN]=[0x1AC7D055D042B7E,0x33C4484E51755F9,0x21BBDC7F5049334,0x3426482D86AD769,0x88274F65596BD0,0x9C67D81F6B34E8,0x13E02B605];
+pub const CURVE_PYA:[Chunk;NLEN]=[0x193548608B82801,0x2B2730EEB28A278,0x1A695160D12C923,0x2AA32F74E9DB50A,0x2DA2E351AADFD9B,0x9F5B8463327371,0xCE5D5277];
+pub const CURVE_PYB:[Chunk;NLEN]=[0x2A9075FF05F79BE,0x1C349D73B07686A,0x12AB572E99AB3F3,0x1FA169D8EBC99D2,0x2BC28B99CB3E28,0x3A9CD330CAB34AC,0x606C4A02];
+pub const CURVE_W:[[Chunk;NLEN];2]=[[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]];
+pub const CURVE_SB:[[[Chunk;NLEN];2];2]=[[[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]]];
+pub const CURVE_WB:[[Chunk;NLEN];4]=[[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]];
+pub const CURVE_BB:[[[Chunk;NLEN];4];4]=[[[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]]];
+
+pub const USE_GLV:bool = true;
+pub const USE_GS_G2:bool = true;
+pub const USE_GS_GT:bool = true;
+pub const GT_STRONG:bool = false;
diff --git a/version3/rust/rom_bls383_32.rs b/version3/rust/rom_bls383_32.rs
new file mode 100644
index 0000000..8325397
--- /dev/null
+++ b/version3/rust/rom_bls383_32.rs
@@ -0,0 +1,55 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use bls383::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 29
+pub const MODULUS:[Chunk;NLEN]=[0x5AAB0AB,0x11B8EB24,0x19214AF6,0x187E5314,0x124F47A8,0x1C00B4B0,0x1446B0C6,0x59E6CB4,0x4A0AD46,0xFF5494,0x81B6B71,0x956DD6B,0x16556956,0x2A];
+pub const R2MODP:[Chunk;NLEN]=[0x116907F4,0x405B700,0x1752AC11,0x67A9E7C,0x1941C581,0x1AEA38C4,0xB1E4D22,0xCE841AE,0xA0FC49B,0xB4B1F48,0x13852312,0x1B3FDCED,0x1FECE397,0x26];
+pub const MCONST:Chunk=0x73435FD;
+pub const FRA:[Chunk;NLEN]=[0x1311DAC1,0x296B969,0x19DCF806,0x126901FC,0xD8C8A36,0x1A2572A8,0xA1A0959,0x1A47F743,0x110E4C6C,0x1608DA97,0xCE2E7F0,0x4FED178,0xACD5BF0,0x11];
+pub const FRB:[Chunk;NLEN]=[0x1298D5EA,0xF2231BA,0x1F4452F0,0x6155117,0x4C2BD72,0x1DB4208,0xA2CA76D,0xB567571,0x139260D9,0xAF679FC,0x1B388380,0x4580BF2,0xB880D66,0x19];
+
+// Base Bits= 29
+
+pub const CURVE_A:isize = 0;
+pub const CURVE_COF_I:isize = 0;
+pub const CURVE_COF:[Chunk;NLEN]=[0x15169EAB,0xA82AB0A,0xAAEFFED,0x15558001,0x555,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_B_I:isize = 15;
+pub const CURVE_B:[Chunk;NLEN]=[0xF,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0x1EBC0001,0x1904CF5F,0x834E5CE,0xBE12B42,0xB381DE0,0xE40B4C,0x270110,0x10018017,0x1002001,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_GX:[Chunk;NLEN]=[0x8734573,0x623B9C8,0x1D1DC11E,0xBB7E107,0x1E3445C5,0x1D6C2578,0x10B0BE1E,0xED6103E,0x10F31D9F,0x296ED82,0x18E0D7D0,0x12F3D9C9,0x1FCBA55B,0x20];
+pub const CURVE_GY:[Chunk;NLEN]=[0x3F224,0x968B2F4,0x1FE63F48,0xFA93D90,0x14D2DDE5,0x54A56F5,0x12441D4C,0x18CD76C8,0x199D0DAD,0xE18E236,0x92BA73,0x99F6600,0x8F16727,0x3];
+
+pub const CURVE_BNX:[Chunk;NLEN]=[0x1001200,0x400000,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_CRU:[Chunk;NLEN]=[0xEAAC2A9,0x61B3A81,0x17D974B7,0xBED0345,0xA341BC2,0x17A51A6F,0x5738948,0x69B7BAE,0x14605445,0x374A43,0x8116AD1,0x956DD69,0x16556956,0x2A];
+pub const CURVE_PXA:[Chunk;NLEN]=[0xD7F2D86,0x1E59DB1,0x17474F85,0x1FB56CF2,0x572EE81,0xE487AB1,0x96F51FC,0x190A5AAE,0x6432501,0x13E58F3A,0x101E6425,0xFD807D1,0x34D2240,0x3];
+pub const CURVE_PXB:[Chunk;NLEN]=[0x452DE15,0x1ECF20F6,0x1FF9837B,0x95651AA,0xD5D75B5,0x5D44749,0x12277F66,0x1DB3A0B9,0x1D24F498,0x19441B0E,0x1CDE9DC5,0x2C975,0xD78006,0x18];
+pub const CURVE_PYA:[Chunk;NLEN]=[0x1408CB41,0x34785DC,0x3586597,0x13DBC9E4,0x1A2E75B4,0x1D65489,0xCF9A25E,0x1ACE7933,0x1B6E990E,0x19FF31A3,0x12527615,0x1A44A68F,0x1792CF93,0x19];
+pub const CURVE_PYB:[Chunk;NLEN]=[0x1F479093,0x16C2321B,0x1889218E,0x87961BC,0x1BC98B01,0x197A24FB,0xA3DEBC2,0x88D67DF,0x1CE0D,0x1E8AD3D7,0x93B9EE9,0x59B18D6,0xE5247DD,0x10];
+pub const CURVE_W:[[Chunk;NLEN];2]=[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]];
+pub const CURVE_SB:[[[Chunk;NLEN];2];2]=[[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]];
+pub const CURVE_WB:[[Chunk;NLEN];4]=[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]];
+pub const CURVE_BB:[[[Chunk;NLEN];4];4]=[[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]];
+
+pub const USE_GLV:bool = true;
+pub const USE_GS_G2:bool = true;
+pub const USE_GS_GT:bool = true;
+pub const GT_STRONG:bool = true;
diff --git a/version3/rust/rom_bls383_64.rs b/version3/rust/rom_bls383_64.rs
new file mode 100644
index 0000000..7f07534
--- /dev/null
+++ b/version3/rust/rom_bls383_64.rs
@@ -0,0 +1,55 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use bls383::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 58
+pub const MODULUS:[Chunk;NLEN]=[0x2371D6485AAB0AB,0x30FCA6299214AF6,0x3801696124F47A8,0xB3CD969446B0C6,0x1FEA9284A0AD46,0x12ADBAD681B6B71,0x556556956];
+pub const R2MODP:[Chunk;NLEN]=[0x80B6E0116907F4,0xCF53CF9752AC11,0x35D47189941C581,0x19D0835CB1E4D22,0x16963E90A0FC49B,0x367FB9DB3852312,0x4DFECE397];
+pub const MCONST:Chunk=0x1BC0571073435FD;
+pub const FRA:[Chunk;NLEN]=[0x52D72D3311DAC1,0x24D203F99DCF806,0x344AE550D8C8A36,0x348FEE86A1A0959,0x2C11B52F10E4C6C,0x9FDA2F0CE2E7F0,0x22ACD5BF0];
+pub const FRB:[Chunk;NLEN]=[0x1E446375298D5EA,0xC2AA22FF4452F0,0x3B684104C2BD72,0x16ACEAE2A2CA76D,0x15ECF3F939260D9,0x8B017E5B388380,0x32B880D66];
+
+// Base Bits= 58
+
+pub const CURVE_A:isize = 0;
+pub const CURVE_COF_I:isize = 0;
+pub const CURVE_COF:[Chunk;NLEN]=[0x150556155169EAB,0x2AAB0002AAEFFED,0x555,0x0,0x0,0x0,0x0];
+pub const CURVE_B_I:isize = 15;
+pub const CURVE_B:[Chunk;NLEN]=[0xF,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0x32099EBFEBC0001,0x17C25684834E5CE,0x1C81698B381DE0,0x2003002E0270110,0x1002001,0x0,0x0];
+pub const CURVE_GX:[Chunk;NLEN]=[0xC4773908734573,0x176FC20FD1DC11E,0x3AD84AF1E3445C5,0x1DAC207D0B0BE1E,0x52DDB050F31D9F,0x25E7B3938E0D7D0,0x41FCBA55B];
+pub const CURVE_GY:[Chunk;NLEN]=[0x12D165E8003F224,0x1F527B21FE63F48,0xA94ADEB4D2DDE5,0x319AED912441D4C,0x1C31C46D99D0DAD,0x133ECC00092BA73,0x68F16727];
+
+pub const CURVE_BNX:[Chunk;NLEN]=[0x8000001001200,0x40,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_CRU:[Chunk;NLEN]=[0xC367502EAAC2A9,0x17DA068B7D974B7,0x2F4A34DEA341BC2,0xD36F75C5738948,0x6E94874605445,0x12ADBAD28116AD1,0x556556956];
+pub const CURVE_PXA:[Chunk;NLEN]=[0x3CB3B62D7F2D86,0x3F6AD9E57474F85,0x1C90F562572EE81,0x3214B55C96F51FC,0x27CB1E746432501,0x1FB00FA301E6425,0x634D2240];
+pub const CURVE_PXB:[Chunk;NLEN]=[0x3D9E41EC452DE15,0x12ACA355FF9837B,0xBA88E92D5D75B5,0x3B6741732277F66,0x3288361DD24F498,0x592EBCDE9DC5,0x300D78006];
+pub const CURVE_PYA:[Chunk;NLEN]=[0x68F0BB9408CB41,0x27B793C83586597,0x3ACA913A2E75B4,0x359CF266CF9A25E,0x33FE6347B6E990E,0x34894D1F2527615,0x33792CF93];
+pub const CURVE_PYB:[Chunk;NLEN]=[0x2D846437F479093,0x10F2C379889218E,0x32F449F7BC98B01,0x111ACFBEA3DEBC2,0x3D15A7AE001CE0D,0xB3631AC93B9EE9,0x20E5247DD];
+pub const CURVE_W:[[Chunk;NLEN];2]=[[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]];
+pub const CURVE_SB:[[[Chunk;NLEN];2];2]=[[[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]]];
+pub const CURVE_WB:[[Chunk;NLEN];4]=[[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]];
+pub const CURVE_BB:[[[Chunk;NLEN];4];4]=[[[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]]];
+
+pub const USE_GLV:bool = true;
+pub const USE_GS_G2:bool = true;
+pub const USE_GS_GT:bool = true;
+pub const GT_STRONG:bool = true;
diff --git a/version3/rust/rom_bls461_32.rs b/version3/rust/rom_bls461_32.rs
new file mode 100644
index 0000000..f62bf65
--- /dev/null
+++ b/version3/rust/rom_bls461_32.rs
@@ -0,0 +1,55 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use bls461::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 28
+// bls461 Modulus
+
+pub const MODULUS:[Chunk;NLEN]=[0xAAAAAAB,0xAC0000A,0x54AAAAA,0x5555,0x400020,0x91557F0,0xF26AA,0xFA5C1CC,0xB42A8DF,0x7B14848,0x8BACCA4,0x6F1E32D,0x4935FBD,0x55D6941,0xD5A555A,0x5545554,0x1555];
+pub const R2MODP:[Chunk;NLEN]=[0xC9B6A33,0x2ECD087,0x3CCB2B1,0xCD461FE,0x8CB5AB2,0xC5B9635,0x5312E92,0xB659F64,0x3B596FA,0x8679006,0xA92E2B3,0x3CE05E3,0x363550F,0x7C07A8E,0x382C083,0x6347FEA,0xBD];
+pub const MCONST:Chunk=0xFFFFFFD;
+pub const FRA:[Chunk;NLEN]=[0xB812A3A,0x7117BF9,0x99C400F,0xC6308A5,0x5BF8A1,0x510E075,0x45FA5A6,0xCE4858D,0x770B31A,0xBC2CB04,0xE2FC61E,0xD073588,0x4366190,0x4DFEFA8,0x69E55E2,0x504B7F,0x12E4];
+pub const FRB:[Chunk;NLEN]=[0xF298071,0x3AE8410,0xBAE6A9B,0x39D4CAF,0xFE4077E,0x404777A,0xBAF8104,0x2C13C3E,0x3D1F5C5,0xBEE7D44,0xA8B0685,0x9EAADA4,0x5CFE2C,0x7D7999,0x6BBFF78,0x50409D5,0x271];
+
+// bls461 Curve
+pub const CURVE_COF_I:isize = 0;
+pub const CURVE_A:isize = 0;
+pub const CURVE_B_I:isize = 9;
+pub const CURVE_B:[Chunk;NLEN]=[0x9,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0x1,0x0,0xFFFFC00,0x7FEFFFE,0x110000,0x7FFC800,0x801FC01,0x5FD000E,0x17FE0,0xFFFC018,0xFFFFFF7,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_GX:[Chunk;NLEN]=[0xADEE93D,0x4D026A8,0x74B7411,0xD9C00EE,0x31AC7F2,0xC3981B5,0x9218229,0xD3564DC,0xA096650,0x6F7C292,0x9743616,0xBE922B1,0x12CF668,0xC81327,0x463B73A,0xE74E99B,0xAD0];
+pub const CURVE_GY:[Chunk;NLEN]=[0xAD1D465,0xF763157,0xC4FF470,0x17884C8,0xB8D215D,0xA819E66,0xF4959D0,0xE5C3245,0xB84910A,0xB8BFA40,0xBE96EEC,0x8BF9F8C,0xF277ACC,0x5F1C3F2,0x5F68C9,0xCDB14B3,0x77B];
+pub const CURVE_BNX:[Chunk;NLEN]=[0x0,0xFBFFFE0,0x1FFFFF,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_COF:[Chunk;NLEN]=[0xAAAAAAB,0xA7FFFEA,0x1556AA,0xD55AAAB,0x554FFFF,0x1555,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_CRU:[Chunk;NLEN]=[0xFFFFFFE,0x40001F,0xFE00000,0xFFE7FFF,0xF0FFF6F,0x7200C47,0x7BCC604,0x15796DB,0xCF47771,0x9875433,0x613F0E8,0x5000502,0xEBFFF60,0x1FFFFF,0x0,0x0,0x0];
+pub const CURVE_PXA:[Chunk;NLEN]=[0x6D0A37C,0x5B50318,0x75DCC46,0xC2E492E,0xD6878A9,0xE01F919,0xF92F564,0x86DB74F,0x66803F0,0x46D581A,0x7ED78D,0x2F97C29,0xC270C89,0xF679453,0x6A50A9A,0x54138A0,0x10CC];
+pub const CURVE_PXB:[Chunk;NLEN]=[0x2C1C0AD,0xF85CA8C,0x25CADE9,0x6CD66C4,0xA289609,0xC612951,0xEE2401A,0x529ABEB,0xF65B17D,0xBA09D33,0xD4C5AF5,0x4D4371E,0x46A672E,0xA279D22,0xACEA37C,0x1FB4FE5,0x95C];
+pub const CURVE_PYA:[Chunk;NLEN]=[0x2FB006,0xCCD0C1B,0xA12A337,0x3D194A4,0xC92C895,0x4960CFC,0x39FC68B,0x3A9B00F,0xED1BA0F,0xA7DBBC5,0xA9CDFD8,0x27CC2F7,0x4E73ED2,0x6070F4F,0xEBA7E67,0xAC848E7,0x226];
+pub const CURVE_PYB:[Chunk;NLEN]=[0xDF1457C,0xA506ADF,0x4C20A8,0xD6A31DC,0x36E3FB4,0xEA9A8F1,0x92F5668,0x3C3BE44,0x67A1297,0x74BEABA,0x56A20BE,0x4C42E38,0x45157F0,0x2AB1D00,0xBB402EA,0x101B4FA,0xE38];
+pub const CURVE_W:[[Chunk;NLEN];2]=[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]];
+pub const CURVE_SB:[[[Chunk;NLEN];2];2]=[[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]];
+pub const CURVE_WB:[[Chunk;NLEN];4]=[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]];
+pub const CURVE_BB:[[[Chunk;NLEN];4];4]=[[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]];
+
+pub const USE_GLV:bool = true;
+pub const USE_GS_G2:bool = true;
+pub const USE_GS_GT:bool = true;
+pub const GT_STRONG:bool = false;
diff --git a/version3/rust/rom_bls461_64.rs b/version3/rust/rom_bls461_64.rs
new file mode 100644
index 0000000..7a0f52f
--- /dev/null
+++ b/version3/rust/rom_bls461_64.rs
@@ -0,0 +1,56 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use bls461::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 60
+// bls461 Modulus
+
+pub const MODULUS:[Chunk;NLEN]=[0xAAC0000AAAAAAAB,0x20000555554AAAA,0x6AA91557F004000,0xA8DFFA5C1CC00F2,0xACCA47B14848B42,0x935FBD6F1E32D8B,0xD5A555A55D69414,0x15555545554];
+pub const R2MODP:[Chunk;NLEN]=[0x96D08774614DDA8,0xCD45F539225D5BD,0xD712EB760C95AB1,0xB3B687155F30B55,0xC4E62A05C3F5B81,0xBA1151676CA3CD0,0x7EDD8A958F442BE,0x12B89DD3F91];
+pub const MCONST:Chunk=0xC0005FFFFFFFD;
+pub const FRA:[Chunk;NLEN]=[0xF7117BF9B812A3A,0xA1C6308A599C400,0x5A6510E07505BF8,0xB31ACE4858D45FA,0xFC61EBC2CB04770,0x366190D073588E2,0x69E55E24DFEFA84,0x12E40504B7F];
+pub const FRB:[Chunk;NLEN]=[0xB3AE8410F298071,0x7E39D4CAFBAE6A9,0x104404777AFE407,0xF5C52C13C3EBAF8,0xB0685BEE7D443D1,0x5CFE2C9EAADA4A8,0x6BBFF7807D79990,0x27150409D5];
+
+// bls461 Curve
+pub const CURVE_COF_I:isize = 0;
+pub const CURVE_A:isize = 0;
+pub const CURVE_B_I:isize = 9;
+pub const CURVE_B:[Chunk;NLEN]=[0x9,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0x1,0x7FEFFFEFFFFC0,0xC017FFC80001100,0x7FE05FD000E801F,0xFFFF7FFFC018001,0xFF,0x0,0x0];
+pub const CURVE_GX:[Chunk;NLEN]=[0x14D026A8ADEE93D,0xF2D9C00EE74B741,0x229C3981B531AC7,0x6650D3564DC9218,0x436166F7C292A09,0x2CF668BE922B197,0x463B73A0C813271,0xAD0E74E99B];
+pub const CURVE_GY:[Chunk;NLEN]=[0xF763157AD1D465,0x5D17884C8C4FF47,0x9D0A819E66B8D21,0x910AE5C3245F495,0x96EECB8BFA40B84,0x277ACC8BF9F8CBE,0x5F68C95F1C3F2F,0x77BCDB14B3];
+
+pub const CURVE_BNX:[Chunk;NLEN]=[0xFFBFFFE00000000,0x1FFFF,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_COF:[Chunk;NLEN]=[0xAA7FFFEAAAAAAAB,0xFFD55AAAB01556A,0x1555554FF,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_CRU:[Chunk;NLEN]=[0x40001FFFFFFFE,0x6FFFE7FFFFE0000,0x6047200C47F0FFF,0x777115796DB7BCC,0x3F0E89875433CF4,0xBFFF60500050261,0x1FFFFFE,0x0];
+pub const CURVE_PXA:[Chunk;NLEN]=[0x65B503186D0A37C,0xA9C2E492E75DCC4,0x564E01F919D6878,0x3F086DB74FF92F,0xED78D46D581A668,0x270C892F97C2907,0x6A50A9AF679453C,0x10CC54138A0];
+pub const CURVE_PXB:[Chunk;NLEN]=[0x9F85CA8C2C1C0AD,0x96CD66C425CADE,0x1AC612951A2896,0xB17D529ABEBEE24,0xC5AF5BA09D33F65,0x6A672E4D4371ED4,0xACEA37CA279D224,0x95C1FB4FE5];
+pub const CURVE_PYA:[Chunk;NLEN]=[0x7CCD0C1B02FB006,0x953D194A4A12A33,0x68B4960CFCC92C8,0xBA0F3A9B00F39FC,0xCDFD8A7DBBC5ED1,0xE73ED227CC2F7A9,0xEBA7E676070F4F4,0x226AC848E7];
+pub const CURVE_PYB:[Chunk;NLEN]=[0x8A506ADFDF1457C,0xB4D6A31DC04C20A,0x668EA9A8F136E3F,0x12973C3BE4492F5,0xA20BE74BEABA67A,0x5157F04C42E3856,0xBB402EA2AB1D004,0xE38101B4FA];
+pub const CURVE_W:[[Chunk;NLEN];2]=[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]];
+pub const CURVE_SB:[[[Chunk;NLEN];2];2]=[[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]];
+pub const CURVE_WB:[[Chunk;NLEN];4]=[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]];
+pub const CURVE_BB:[[[Chunk;NLEN];4];4]=[[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]];
+
+pub const USE_GLV:bool = true;
+pub const USE_GS_G2:bool = true;
+pub const USE_GS_GT:bool = true;
+pub const GT_STRONG:bool = false;
diff --git a/version3/rust/rom_bls48_32.rs b/version3/rust/rom_bls48_32.rs
new file mode 100644
index 0000000..9723a13
--- /dev/null
+++ b/version3/rust/rom_bls48_32.rs
@@ -0,0 +1,67 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use bls48::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 29
+// bls48 Modulus
+
+pub const MODULUS:[Chunk;NLEN]=[0x1CF6AC0B,0x17B7307F,0x19877E7B,0x12CE0134,0x14228402,0x1BD4C386,0x1DACBB04,0x40410D0,0x25A415,0x980B53E,0xDE6E250,0x15D9AAD6,0x5DA950,0x1029B7A,0x54AB351,0x14AD90CE,0x3729047,0x1FE7E2D9,0x145F610B,0x1F];
+pub const R2MODP:[Chunk;NLEN]=[0xD59D0FA,0x12F01FD0,0xDE8FD41,0x35AAEE1,0xB937F48,0x50700E8,0x1F50EFCE,0x1019B13C,0x3470A2F,0x11094115,0xF9FB72D,0x6AD10E2,0x1CFD9F8,0x44F4785,0x2B48793,0x1148ED3,0xF609E61,0x1EE34BC7,0x1735D29E,0x0];
+pub const MCONST:Chunk=0x9DA805D;
+pub const FRA:[Chunk;NLEN]=[0x1325BF89,0x1311E7EC,0xCD0A56F,0x1A0FD46E,0xE83BCCA,0xCA97DD0,0x18D1D297,0x5F1E137,0x7AB9F2C,0x13FC255F,0x1C9DECEB,0x9DEF4A2,0x3C0F60B,0x1D9909E4,0x1FF27FF7,0x1DBF8208,0x89BB36C,0x40044E0,0x62E01EE,0x5];
+pub const FRB:[Chunk;NLEN]=[0x1325BF89,0x1311E7EC,0xCD0A56F,0x1A0FD46E,0xE83BCCA,0xCA97DD0,0x18D1D297,0x5F1E137,0x7AB9F2C,0x13FC255F,0x1C9DECEB,0x9DEF4A2,0x3C0F60B,0x1D9909E4,0x1FF27FF7,0x1DBF8208,0x89BB36C,0x40044E0,0x62E01EE,0x5];
+
+pub const CURVE_COF_I:isize = 0;
+pub const CURVE_A:isize = 0;
+pub const CURVE_B_I:isize = 17;
+pub const CURVE_B:[Chunk;NLEN]=[0x11,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0x1,0x17FFF800,0xA769C21,0x8AA813C,0x2029C21,0xA68F58B,0xB6307F4,0x1184DA51,0x6DFED78,0x1A3C85E9,0x571037B,0x1637F1F9,0x1C465FB0,0x98354B9,0x118DF17A,0x1422355D,0x43BF73E,0x6,0x0,0x0];
+pub const CURVE_GX:[Chunk;NLEN]=[0x5D71D33,0x1943697B,0x18CB783F,0x1B00AA9F,0x1711EE0B,0x7F80B23,0x129FD8CC,0x1345E03F,0x9A80F66,0x7038173,0xC056511,0x142801F5,0x42B2C3A,0x1AF09869,0x7924166,0x8381264,0x957EDD7,0xBACAEDC,0xA27A4A1,0x13];
+pub const CURVE_GY:[Chunk;NLEN]=[0xA6ED83A,0x14D2D9FF,0xA29C33D,0x1B8972A9,0x6958677,0x19C8F547,0x1DED7E3E,0x14F9E3DC,0x18FB7229,0x27171C0,0x1551E32D,0xE6184CC,0x6260E3C,0x733D204,0x579C437,0x1534665C,0x2B3349D,0x3162FD7,0xB634253,0x1];
+
+pub const CURVE_BNX:[Chunk;NLEN]=[0x1DE40020,0x3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_COF:[Chunk;NLEN]=[0x1F12ABEB,0x516887B,0x5,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_CRU:[Chunk;NLEN]=[0xCBBA429,0x1B273F3,0xD3DD160,0x19C61452,0x308093A,0x146E1E34,0xAE0E768,0x1185948,0x1B73BC2D,0x93D855C,0x1B1A639C,0x118C919B,0xFF04AE3,0xF1CCD77,0x91318E5,0x10644780,0x3A79F7,0x1BE77919,0x145F60F3,0x1F];
+pub const CURVE_PXAAA:[Chunk;NLEN]=[0x923CE4A,0x14697474,0xAE04F4A,0x17AE205A,0x1313A20C,0x10B2EC50,0x18DF074F,0x15FE3FE8,0x7C90B98,0x959BF85,0xE57BD37,0x14376C96,0xBF57375,0xE20B625,0x12EE2172,0x1CBBCE85,0x1A5D9487,0xD0E024B,0x195E3602,0x1C];
+pub const CURVE_PXAAB:[Chunk;NLEN]=[0xC0A1BE1,0x138E6E2D,0x1DF5FDC,0x151FC760,0x33972C5,0x56AA3C2,0x2491D8C,0x115B9FD7,0x140A11FA,0x1873AE35,0x1F259C26,0x74B0647,0x12D18B04,0x4672431,0x1C27F419,0x1CAA4D35,0x18DB48B6,0x13A54BDA,0x5080497,0x5];
+pub const CURVE_PXABA:[Chunk;NLEN]=[0x170C5DC4,0x11D39263,0x16B3BCB6,0x152C95BB,0x19BEC736,0x8849A12,0x49AB2A8,0xC7162D3,0xC58CD55,0x15C2659,0x11EE8B90,0xB40CAFC,0xE233167,0x7BEC8BE,0x129335BD,0x151C7DBB,0x78B689B,0x1B6B8EED,0x14BFBE3D,0x16];
+pub const CURVE_PXABB:[Chunk;NLEN]=[0x1A64B740,0x6B14B34,0x12481578,0x23FA931,0x323ADD1,0x206B82A,0xD789E1B,0x1FCFA666,0x1F4EEA7,0xF1E39E2,0x1968610,0xAF3EBD3,0x590D3B,0xDA0C35A,0x17306AAF,0xCF9DD2B,0x3F63B1A,0x96FF2F9,0xE102A76,0x12];
+pub const CURVE_PXBAA:[Chunk;NLEN]=[0x12F1E01F,0xDD8630B,0x12C29802,0x186239A6,0x19218788,0x4C87D1,0x16AE2501,0x775C076,0x870C80B,0x1A394429,0x1637D478,0x4A420E8,0x1C3AD4D4,0x10E5E713,0x111E6AD5,0x514FCF0,0x7CC49D3,0xC678A2,0x1787BDFD,0x1B];
+pub const CURVE_PXBAB:[Chunk;NLEN]=[0x637383D,0x1851C11C,0x661F866,0x14404A7F,0x15D3D212,0x9AE28F6,0x8051F25,0x1E1CE2BF,0x137D882F,0xB231CEB,0xA8DB8FC,0x18957645,0x5E54DA8,0x1FF41C44,0x1A297414,0x17E1CBC5,0x1014F91F,0x4282AB7,0xB6CE9E3,0x10];
+pub const CURVE_PXBBA:[Chunk;NLEN]=[0x1711939C,0xB41ED9E,0x69066BA,0x137CA3AD,0xCF2F6C0,0x5E6DAB9,0x2CE1323,0x946E448,0xF353D1C,0x14D9919F,0x46B7046,0x1A12015,0x3D6070,0x18C3E8D2,0x1F23BA45,0x1F1A337C,0x435A9CC,0x6CA1DF1,0x8A9CE1,0x15];
+pub const CURVE_PXBBB:[Chunk;NLEN]=[0x56F4899,0x196A0854,0xA959750,0x38A3D72,0x190BC9BC,0x145752BC,0x1E9E26DA,0x1403F88,0x71895E3,0x14162F5D,0x19FEC5FF,0x14190B16,0x7597C,0x19A3CF18,0x26A4B00,0x113D1BB6,0x7857A32,0xE0B78AB,0x1DD51E0F,0x1B];
+pub const CURVE_PYAAA:[Chunk;NLEN]=[0x14137844,0x1704BE7D,0x1FD3CCDD,0x189D8C93,0x1C768851,0xF5C37D5,0xE29C659,0x20AB1C1,0xF8896E0,0x1E08663E,0x1D1D539C,0x117E1C47,0x156CDD39,0x161F1017,0x143E8C72,0x174B22FD,0x18706190,0x49AA47E,0x19BB42E1,0xE];
+pub const CURVE_PYAAB:[Chunk;NLEN]=[0xDC83190,0x12F19247,0x1AA26424,0x15D55E88,0xC418D32,0xB0E91DD,0x47CBFF7,0x2D992C1,0xDE03C1F,0x7694AE5,0x5C741A2,0x1D423AC6,0x5E02B9E,0x1E903F10,0x4EA6513,0x433A1F1,0x8EFA1C4,0xED54713,0x1E72CE4F,0x4];
+pub const CURVE_PYABA:[Chunk;NLEN]=[0x1985C0D,0xEE2FE82,0x64770FA,0x11A809B4,0x1483ACE9,0x18BCD2FA,0x171F32C,0x1612D58D,0x1E658341,0x1CBE2201,0x186E971,0x73F0E1,0xB0A5F40,0xAC90FB0,0x1635E008,0x237498B,0x1F3140D6,0xBF789A9,0x1166F259,0x1A];
+pub const CURVE_PYABB:[Chunk;NLEN]=[0x159D42F8,0x1B7F0540,0x45895D7,0x14875FA2,0x1E9E7F2B,0x10139D87,0x10F3FD7D,0x11D3717F,0x69E5006,0xF9BB3C4,0x13C9ED8D,0x16516DA,0x102F51DE,0x2725FEC,0x1F125B66,0xFFC324,0x1ED80731,0x1C16C4D,0x383AAA8,0x14];
+pub const CURVE_PYBAA:[Chunk;NLEN]=[0x1F38039F,0x6A8959C,0x13C68984,0x11DD12AF,0x58093CF,0x1C8550A0,0xFFA1622,0xFF85979,0x1F2ABB75,0x18862E62,0x1EB6A2C9,0x1EC80B64,0x8EC2F18,0xE7BF713,0xC36B65A,0x19C5DD89,0x18A1D1AB,0xF772C8D,0xC11927C,0x5];
+pub const CURVE_PYBAB:[Chunk;NLEN]=[0x95F7865,0x134F0379,0x1CE9A0E,0x17E0EADD,0x1DACADD7,0x1B18F9F8,0x181D3943,0x186679A,0x2505BB0,0x1FDF1DC8,0x11B36A49,0x11E254E9,0xA438576,0x102B09AE,0x139984F4,0x15BC0233,0x1B6F180E,0x960562B,0x48CA65B,0x6];
+pub const CURVE_PYBBA:[Chunk;NLEN]=[0x7CC1979,0xEC1D4FB,0x1D89E6F0,0x955F38E,0x1635FDA9,0x123D8E10,0x10076209,0x494404A,0xD733D7,0x17678BCF,0x153841F9,0x10696FFD,0x5BC9FE8,0x1A20D8B2,0xE22EC9D,0x18449116,0x108C86C5,0x1B4CD720,0x34967,0x19];
+pub const CURVE_PYBBB:[Chunk;NLEN]=[0xFC9F25B,0x7E44AB1,0xE9AB5D3,0x589F00D,0x1C9D264F,0xC7478B4,0x16B24A13,0x1D2C146B,0xEF84D9A,0xF47ECDE,0x1BFEE16A,0x1B69071E,0x11AB4C1C,0xBE9D9EF,0x390F005,0x78C8288,0x1B9BF549,0x9320730,0x3D84D97,0x14];
+pub const CURVE_W:[[Chunk;NLEN];2]=[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]];
+pub const CURVE_SB:[[[Chunk;NLEN];2];2]=[[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]];
+pub const CURVE_WB:[[Chunk;NLEN];4]=[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]];
+pub const CURVE_BB:[[[Chunk;NLEN];4];4]=[[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]];
+
+pub const USE_GLV:bool = true;
+pub const USE_GS_G2:bool = true;
+pub const USE_GS_GT:bool = true;
+pub const GT_STRONG:bool = true;
diff --git a/version3/rust/rom_bls48_64.rs b/version3/rust/rom_bls48_64.rs
new file mode 100644
index 0000000..b4155ed
--- /dev/null
+++ b/version3/rust/rom_bls48_64.rs
@@ -0,0 +1,67 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use bls48::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 58
+// bls48 Modulus
+
+pub const MODULUS:[Chunk;NLEN]=[0x2F6E60FFCF6AC0B,0x259C02699877E7B,0x37A9870D4228402,0x80821A1DACBB04,0x13016A7C025A415,0x2BB355ACDE6E250,0x20536F405DA950,0x295B219C54AB351,0x3FCFC5B23729047,0x3F45F610B];
+pub const R2MODP:[Chunk;NLEN]=[0x25E03FA0D59D0FA,0x6B55DC2DE8FD41,0xA0E01D0B937F48,0x20336279F50EFCE,0x2212822A3470A2F,0xD5A21C4F9FB72D,0x89E8F0A1CFD9F8,0x2291DA62B48793,0x3DC6978EF609E61,0x1735D29E];
+pub const MCONST:Chunk=0x21BFCBCA9DA805D;
+pub const FRA:[Chunk;NLEN]=[0x2623CFD9325BF89,0x341FA8DCCD0A56F,0x1952FBA0E83BCCA,0xBE3C26F8D1D297,0x27F84ABE7AB9F2C,0x13BDE945C9DECEB,0x3B3213C83C0F60B,0x3B7F0411FF27FF7,0x80089C089BB36C,0xA62E01EE];
+pub const FRB:[Chunk;NLEN]=[0x2623CFD9325BF89,0x341FA8DCCD0A56F,0x1952FBA0E83BCCA,0xBE3C26F8D1D297,0x27F84ABE7AB9F2C,0x13BDE945C9DECEB,0x3B3213C83C0F60B,0x3B7F0411FF27FF7,0x80089C089BB36C,0xA62E01EE];
+
+pub const CURVE_COF_I:isize = 0;
+pub const CURVE_A:isize = 0;
+pub const CURVE_B_I:isize = 17;
+pub const CURVE_B:[Chunk;NLEN]=[0x11,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0x2FFFF0000000001,0x11550278A769C21,0x14D1EB162029C21,0x2309B4A2B6307F4,0x34790BD26DFED78,0x2C6FE3F2571037B,0x1306A973C465FB0,0x28446ABB18DF17A,0xC43BF73E,0x0];
+pub const CURVE_GX:[Chunk;NLEN]=[0x3286D2F65D71D33,0x3601553F8CB783F,0xFF01647711EE0B,0x268BC07F29FD8CC,0xE0702E69A80F66,0x285003EAC056511,0x35E130D242B2C3A,0x107024C87924166,0x17595DB8957EDD7,0x26A27A4A1];
+pub const CURVE_GY:[Chunk;NLEN]=[0x29A5B3FEA6ED83A,0x3712E552A29C33D,0x3391EA8E6958677,0x29F3C7B9DED7E3E,0x4E2E3818FB7229,0x1CC30999551E32D,0xE67A4086260E3C,0x2A68CCB8579C437,0x62C5FAE2B3349D,0x2B634253];
+
+pub const CURVE_BNX:[Chunk;NLEN]=[0x7DE40020,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_COF:[Chunk;NLEN]=[0xA2D10F7F12ABEB,0x5,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_CRU:[Chunk;NLEN]=[0x364E7E6CBBA429,0x338C28A4D3DD160,0x28DC3C68308093A,0x230B290AE0E768,0x127B0AB9B73BC2D,0x23192337B1A639C,0x1E399AEEFF04AE3,0x20C88F0091318E5,0x37CEF23203A79F7,0x3F45F60F3];
+pub const CURVE_PXAAA:[Chunk;NLEN]=[0x28D2E8E8923CE4A,0x2F5C40B4AE04F4A,0x2165D8A1313A20C,0x2BFC7FD18DF074F,0x12B37F0A7C90B98,0x286ED92CE57BD37,0x1C416C4ABF57375,0x39779D0B2EE2172,0x1A1C0497A5D9487,0x3995E3602];
+pub const CURVE_PXAAB:[Chunk;NLEN]=[0x271CDC5AC0A1BE1,0x2A3F8EC01DF5FDC,0xAD5478433972C5,0x22B73FAE2491D8C,0x30E75C6B40A11FA,0xE960C8FF259C26,0x8CE48632D18B04,0x39549A6BC27F419,0x274A97B58DB48B6,0xA5080497];
+pub const CURVE_PXABA:[Chunk;NLEN]=[0x23A724C770C5DC4,0x2A592B776B3BCB6,0x110934259BEC736,0x18E2C5A649AB2A8,0x2B84CB2C58CD55,0x168195F91EE8B90,0xF7D917CE233167,0x2A38FB7729335BD,0x36D71DDA78B689B,0x2D4BFBE3D];
+pub const CURVE_PXABB:[Chunk;NLEN]=[0xD629669A64B740,0x47F52632481578,0x40D7054323ADD1,0x3F9F4CCCD789E1B,0x1E3C73C41F4EEA7,0x15E7D7A61968610,0x1B4186B40590D3B,0x19F3BA577306AAF,0x12DFE5F23F63B1A,0x24E102A76];
+pub const CURVE_PXBAA:[Chunk;NLEN]=[0x1BB0C6172F1E01F,0x30C4734D2C29802,0x990FA39218788,0xEEB80ED6AE2501,0x34728852870C80B,0x94841D1637D478,0x21CBCE27C3AD4D4,0xA29F9E111E6AD5,0x18CF1447CC49D3,0x37787BDFD];
+pub const CURVE_PXBAB:[Chunk;NLEN]=[0x30A38238637383D,0x288094FE661F866,0x135C51ED5D3D212,0x3C39C57E8051F25,0x164639D737D882F,0x312AEC8AA8DB8FC,0x3FE838885E54DA8,0x2FC3978BA297414,0x850556F014F91F,0x20B6CE9E3];
+pub const CURVE_PXBBA:[Chunk;NLEN]=[0x1683DB3D711939C,0x26F9475A69066BA,0xBCDB572CF2F6C0,0x128DC8902CE1323,0x29B3233EF353D1C,0x342402A46B7046,0x3187D1A403D6070,0x3E3466F9F23BA45,0xD943BE2435A9CC,0x2A08A9CE1];
+pub const CURVE_PXBBB:[Chunk;NLEN]=[0x32D410A856F4899,0x7147AE4A959750,0x28AEA57990BC9BC,0x2807F11E9E26DA,0x282C5EBA71895E3,0x2832162D9FEC5FF,0x33479E30007597C,0x227A376C26A4B00,0x1C16F1567857A32,0x37DD51E0F];
+pub const CURVE_PYAAA:[Chunk;NLEN]=[0x2E097CFB4137844,0x313B1927FD3CCDD,0x1EB86FABC768851,0x4156382E29C659,0x3C10CC7CF8896E0,0x22FC388FD1D539C,0x2C3E202F56CDD39,0x2E9645FB43E8C72,0x93548FD8706190,0x1D9BB42E1];
+pub const CURVE_PYAAB:[Chunk;NLEN]=[0x25E3248EDC83190,0x2BAABD11AA26424,0x161D23BAC418D32,0x5B3258247CBFF7,0xED295CADE03C1F,0x3A84758C5C741A2,0x3D207E205E02B9E,0x86743E24EA6513,0x1DAA8E268EFA1C4,0x9E72CE4F];
+pub const CURVE_PYABA:[Chunk;NLEN]=[0x1DC5FD041985C0D,0x2350136864770FA,0x3179A5F5483ACE9,0x2C25AB1A171F32C,0x397C4403E658341,0xE7E1C2186E971,0x15921F60B0A5F40,0x46E9317635E008,0x17EF1353F3140D6,0x35166F259];
+pub const CURVE_PYABB:[Chunk;NLEN]=[0x36FE0A8159D42F8,0x290EBF4445895D7,0x20273B0FE9E7F2B,0x23A6E2FF0F3FD7D,0x1F37678869E5006,0x2CA2DB53C9ED8D,0x4E4BFD902F51DE,0x1FF8649F125B66,0x382D89BED80731,0x28383AAA8];
+pub const CURVE_PYBAA:[Chunk;NLEN]=[0xD512B39F38039F,0x23BA255F3C68984,0x390AA14058093CF,0x1FF0B2F2FFA1622,0x310C5CC5F2ABB75,0x3D9016C9EB6A2C9,0x1CF7EE268EC2F18,0x338BBB12C36B65A,0x1EEE591B8A1D1AB,0xAC11927C];
+pub const CURVE_PYBAB:[Chunk;NLEN]=[0x269E06F295F7865,0x2FC1D5BA1CE9A0E,0x3631F3F1DACADD7,0x30CCF3581D3943,0x3FBE3B902505BB0,0x23C4A9D31B36A49,0x2056135CA438576,0x2B78046739984F4,0x12C0AC57B6F180E,0xC48CA65B];
+pub const CURVE_PYBBA:[Chunk;NLEN]=[0x1D83A9F67CC1979,0x12ABE71DD89E6F0,0x247B1C21635FDA9,0x92880950076209,0x2ECF179E0D733D7,0x20D2DFFB53841F9,0x3441B1645BC9FE8,0x3089222CE22EC9D,0x3699AE4108C86C5,0x320034967];
+pub const CURVE_PYBBB:[Chunk;NLEN]=[0xFC89562FC9F25B,0xB13E01AE9AB5D3,0x18E8F169C9D264F,0x3A5828D76B24A13,0x1E8FD9BCEF84D9A,0x36D20E3DBFEE16A,0x17D3B3DF1AB4C1C,0xF190510390F005,0x12640E61B9BF549,0x283D84D97];
+pub const CURVE_W:[[Chunk;NLEN];2]=[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]];
+pub const CURVE_SB:[[[Chunk;NLEN];2];2]=[[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]];
+pub const CURVE_WB:[[Chunk;NLEN];4]=[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]];
+pub const CURVE_BB:[[[Chunk;NLEN];4];4]=[[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]];
+
+pub const USE_GLV:bool = true;
+pub const USE_GS_G2:bool = true;
+pub const USE_GS_GT:bool = true;
+pub const GT_STRONG:bool = true;
diff --git a/version3/rust/rom_bn254CX_32.rs b/version3/rust/rom_bn254CX_32.rs
new file mode 100644
index 0000000..da1aac9
--- /dev/null
+++ b/version3/rust/rom_bn254CX_32.rs
@@ -0,0 +1,56 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use bn254CX::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 28
+// bn254CX Modulus 
+pub const MODULUS:[Chunk;NLEN]=[0xC1B55B3,0x6623EF5,0x93EE1BE,0xD6EE180,0x6D3243F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2];
+pub const R2MODP:[Chunk;NLEN]=[0x8A0800A,0x466A061,0x43056A3,0x2B3A225,0x9C6600,0x148515B,0x6BDF50,0xEC9EA56,0xC992E66,0x1];
+pub const MCONST:Chunk=0x9789E85;
+pub const FRA:[Chunk;NLEN]=[0x5C80EA3,0xD908335,0x3F8215B,0x7326F17,0x8986867,0x8AACA71,0x4AFE18B,0xA63A016,0x359082F,0x1];
+pub const FRB:[Chunk;NLEN]=[0x6534710,0x8D1BBC0,0x546C062,0x63C7269,0xE3ABBD8,0xD9CDBC4,0x900DC53,0x623628A,0xA6F7D0,0x1];
+
+// bn254CX Curve 
+pub const CURVE_COF_I:isize = 1;
+pub const CURVE_A:isize = 0;
+pub const CURVE_B_I:isize = 2;
+pub const CURVE_B:[Chunk;NLEN]=[0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0x6EB1F6D,0x11C0A63,0x906CEBE,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2];
+pub const CURVE_GX:[Chunk;NLEN]=[0xC1B55B2,0x6623EF5,0x93EE1BE,0xD6EE180,0x6D3243F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2];
+pub const CURVE_GY:[Chunk;NLEN]=[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_BNX:[Chunk;NLEN]=[0x3C012B1,0x0,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_COF:[Chunk;NLEN]=[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_CRU:[Chunk;NLEN]=[0x4235C97,0xE093179,0xF875631,0xDF6471E,0xF1440BD,0xCA83,0x480000,0x0,0x0,0x0];
+
+pub const CURVE_PXA:[Chunk;NLEN]=[0x4D2EC74,0x851CEEE,0xE2726C0,0x85BFA03,0xBBB907C,0xF5C34,0x6358B25,0x7053B25,0x9682D2C,0x1];
+pub const CURVE_PXB:[Chunk;NLEN]=[0xE29CFE1,0xA58E8B2,0x9C30F47,0x97B0C20,0x743F81B,0x37A8E99,0xAA011C9,0x3E19F64,0x466B9EC,0x1];
+pub const CURVE_PYA:[Chunk;NLEN]=[0xF0BE09F,0xFBFCEBC,0xEC1B30C,0xB33D847,0x2096361,0x157DAEE,0xDD81E22,0x72332B8,0xA79EDD9,0x0];
+pub const CURVE_PYB:[Chunk;NLEN]=[0x898EE9D,0x904B228,0x2EDEBED,0x4EA569D,0x461C286,0x512D8D3,0x35C6E4,0xECC4C09,0x6160C39,0x0];
+
+pub const CURVE_W:[[Chunk;NLEN];2]=[[0x62FEB83,0x5463491,0x381200,0xB4,0x6000,0x0,0x0,0x0,0x0,0x0],[0x7802561,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0]];
+pub const CURVE_SB:[[[Chunk;NLEN];2];2]=[[[0xDB010E4,0x5463491,0x381280,0xB4,0x6000,0x0,0x0,0x0,0x0,0x0],[0x7802561,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x7802561,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0xBB33EA,0xBD5D5D2,0x8CEBCBD,0xD6EE018,0x6D2643F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2]]];
+pub const CURVE_WB:[[Chunk;NLEN];4]=[[0x67A84B0,0x1C21185,0x12B040,0x3C,0x2000,0x0,0x0,0x0,0x0,0x0],[0xE220475,0xCDF995B,0xA7F9A36,0x94EDA8C,0xA0DC07E,0x8702,0x300000,0x0,0x0,0x0],[0xF10B93,0x66FCCAE,0x53FCD3B,0x4A76D46,0x506E03F,0x4381,0x180000,0x0,0x0,0x0],[0xDFAAA11,0x1C21185,0x12B0C0,0x3C,0x2000,0x0,0x0,0x0,0x0,0x0]];
+pub const CURVE_BB:[[[Chunk;NLEN];4];4]=[[[0x32B0CBD,0x11C0A63,0x906CE7E,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2],[0x32B0CBC,0x11C0A63,0x906CE7E,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2],[0x32B0CBC,0x11C0A63,0x906CE7E,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2],[0x7802562,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x7802561,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x32B0CBC,0x11C0A63,0x906CE7E,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2],[0x32B0CBD,0x11C0A63,0x906CE7E,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2],[0x32B0CBC,0x11C0A63,0x906CE7E,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2]],[[0x7802562,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x7802561,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x7802561,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x7802561,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x3C012B2,0x0,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0xF004AC2,0x0,0x100,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0xF6AFA0A,0x11C0A62,0x906CE3E,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2],[0x3C012B2,0x0,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]];
+
+pub const USE_GLV:bool = true;
+pub const USE_GS_G2:bool = true;
+pub const USE_GS_GT:bool = true;
+pub const GT_STRONG:bool = true;
diff --git a/version3/rust/rom_bn254CX_64.rs b/version3/rust/rom_bn254CX_64.rs
new file mode 100644
index 0000000..68f0fb3
--- /dev/null
+++ b/version3/rust/rom_bn254CX_64.rs
@@ -0,0 +1,58 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use bn254CX::big::NLEN;
+use arch::Chunk;
+
+
+// Base Bits= 56
+// bn254CX Modulus
+pub const MODULUS:[Chunk;NLEN]=[0x6623EF5C1B55B3,0xD6EE18093EE1BE,0x647A6366D3243F,0x8702A0DB0BDDF,0x24000000];
+pub const R2MODP:[Chunk;NLEN]=[0x466A0618A0800A,0x2B3A22543056A3,0x148515B09C6600,0xEC9EA5606BDF50,0x1C992E66];
+pub const MCONST:Chunk=0x4E205BF9789E85;
+pub const FRA:[Chunk;NLEN]=[0xD9083355C80EA3,0x7326F173F8215B,0x8AACA718986867,0xA63A0164AFE18B,0x1359082F];
+pub const FRB:[Chunk;NLEN]=[0x8D1BBC06534710,0x63C7269546C062,0xD9CDBC4E3ABBD8,0x623628A900DC53,0x10A6F7D0];
+
+// bn254CX Curve
+pub const CURVE_COF_I:isize = 1;
+pub const CURVE_A:isize = 0;
+pub const CURVE_B_I:isize = 2;
+pub const CURVE_B:[Chunk;NLEN]=[0x2,0x0,0x0,0x0,0x0];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0x11C0A636EB1F6D,0xD6EE0CC906CEBE,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000];
+pub const CURVE_GX:[Chunk;NLEN]=[0x6623EF5C1B55B2,0xD6EE18093EE1BE,0x647A6366D3243F,0x8702A0DB0BDDF,0x24000000];
+pub const CURVE_GY:[Chunk;NLEN]=[0x1,0x0,0x0,0x0,0x0];
+pub const CURVE_BNX:[Chunk;NLEN]=[0x3C012B1,0x40,0x0,0x0,0x0];
+pub const CURVE_COF:[Chunk;NLEN]=[0x1,0x0,0x0,0x0,0x0];
+pub const CURVE_CRU:[Chunk;NLEN]=[0xE0931794235C97,0xDF6471EF875631,0xCA83F1440BD,0x480000,0x0];
+
+pub const CURVE_PXA:[Chunk;NLEN]=[0x851CEEE4D2EC74,0x85BFA03E2726C0,0xF5C34BBB907C,0x7053B256358B25,0x19682D2C];
+pub const CURVE_PXB:[Chunk;NLEN]=[0xA58E8B2E29CFE1,0x97B0C209C30F47,0x37A8E99743F81B,0x3E19F64AA011C9,0x1466B9EC];
+pub const CURVE_PYA:[Chunk;NLEN]=[0xFBFCEBCF0BE09F,0xB33D847EC1B30C,0x157DAEE2096361,0x72332B8DD81E22,0xA79EDD9];
+pub const CURVE_PYB:[Chunk;NLEN]=[0x904B228898EE9D,0x4EA569D2EDEBED,0x512D8D3461C286,0xECC4C09035C6E4,0x6160C39];
+
+
+pub const CURVE_W:[[Chunk;NLEN];2]=[[0x546349162FEB83,0xB40381200,0x6000,0x0,0x0],[0x7802561,0x80,0x0,0x0,0x0]];
+pub const CURVE_SB:[[[Chunk;NLEN];2];2]=[[[0x5463491DB010E4,0xB40381280,0x6000,0x0,0x0],[0x7802561,0x80,0x0,0x0,0x0]],[[0x7802561,0x80,0x0,0x0,0x0],[0xBD5D5D20BB33EA,0xD6EE0188CEBCBD,0x647A6366D2643F,0x8702A0DB0BDDF,0x24000000]]];
+pub const CURVE_WB:[[Chunk;NLEN];4]=[[0x1C2118567A84B0,0x3C012B040,0x2000,0x0,0x0],[0xCDF995BE220475,0x94EDA8CA7F9A36,0x8702A0DC07E,0x300000,0x0],[0x66FCCAE0F10B93,0x4A76D4653FCD3B,0x4381506E03F,0x180000,0x0],[0x1C21185DFAAA11,0x3C012B0C0,0x2000,0x0,0x0]];
+pub const CURVE_BB:[[[Chunk;NLEN];4];4]=[[[0x11C0A6332B0CBD,0xD6EE0CC906CE7E,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000],[0x11C0A6332B0CBC,0xD6EE0CC906CE7E,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000],[0x11C0A6332B0CBC,0xD6EE0CC906CE7E,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000],[0x7802562,0x80,0x0,0x0,0x0]],[[0x7802561,0x80,0x0,0x0,0x0],[0x11C0A6332B0CBC,0xD6EE0CC906CE7E,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000],[0x11C0A6332B0CBD,0xD6EE0CC906CE7E,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000],[0x11C0A6332B0CBC,0xD6EE0CC906CE7E,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000]],[[0x7802562,0x80,0x0,0x0,0x0],[0x7802561,0x80,0x0,0x0,0x0],[0x7802561,0x80,0x0,0x0,0x0],[0x7802561,0x80,0x0,0x0,0x0]],[[0x3C012B2,0x40,0x0,0x0,0x0],[0xF004AC2,0x100,0x0,0x0,0x0],[0x11C0A62F6AFA0A,0xD6EE0CC906CE3E,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000],[0x3C012B2,0x40,0x0,0x0,0x0]]];
+
+pub const USE_GLV:bool = true;
+pub const USE_GS_G2:bool = true;
+pub const USE_GS_GT:bool = true;
+pub const GT_STRONG:bool = true;
diff --git a/version3/rust/rom_bn254_32.rs b/version3/rust/rom_bn254_32.rs
new file mode 100644
index 0000000..b4cdb12
--- /dev/null
+++ b/version3/rust/rom_bn254_32.rs
@@ -0,0 +1,53 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use bn254::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 28
+pub const MODULUS:[Chunk;NLEN]=[0x13,0x0,0x13A7,0x0,0x86121,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2];
+pub const R2MODP:[Chunk;NLEN]=[0xF5E7E39,0x2F2A96F,0xB96F13C,0x64E8642,0xC7146,0x9926F7B,0x4DACD24,0x8321E7B,0xD127A2E,0x1];
+pub const MCONST:Chunk=0x79435E5;
+pub const FRA:[Chunk;NLEN]=[0xF2A6DE9,0x7DE6C06,0xF77C2E1,0x74924D3,0x53F8509,0x50A8469,0xCB6499B,0x212E7C8,0xB377619,0x1];
+pub const FRB:[Chunk;NLEN]=[0xD5922A,0x82193F9,0x8850C5,0x8B6DB2C,0xAC8DC17,0x2F57B96,0x503EAB2,0x1ED1837,0x9EBEE69,0x0];
+
+// BN254 Curve
+pub const CURVE_COF_I:isize = 1;
+pub const CURVE_A:isize = 0;
+pub const CURVE_B_I:isize = 2;
+pub const CURVE_B:[Chunk;NLEN]=[0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0xD,0x0,0x10A1,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2];
+pub const CURVE_GX:[Chunk;NLEN]=[0x12,0x0,0x13A7,0x0,0x86121,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2];
+pub const CURVE_GY:[Chunk;NLEN]=[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_BNX:[Chunk;NLEN]=[0x1,0x8000000,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_COF:[Chunk;NLEN]=[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_CRU:[Chunk;NLEN]=[0x7,0x8000000,0x6CD,0x0,0x24909,0x4000000,0x49B362,0x0,0x0,0x0];
+pub const CURVE_PXA:[Chunk;NLEN]=[0x803FB2B,0xEE4224C,0x8BF0D91,0x8BBB489,0xDB6A464,0x7E8C61E,0xFEB8D8C,0x519EB62,0x61A10BB,0x0];
+pub const CURVE_PXB:[Chunk;NLEN]=[0x7D54CF3,0x8C34C1E,0x784B70D,0x746BAE3,0xA5B1F4D,0x8C5982A,0x3310AA7,0xBA73783,0x516AAF9,0x0];
+pub const CURVE_PYA:[Chunk;NLEN]=[0x1CD2B9A,0xF0E0789,0xE09BD19,0xAE6BDB,0x22329BD,0x96698C8,0x39A90E0,0x6BAF934,0x21897A0,0x0];
+pub const CURVE_PYB:[Chunk;NLEN]=[0xB3ACE9B,0x2D1AEC6,0x9C9578A,0x6FFD73,0xD37B090,0x56F5F38,0x68F6D44,0x7C8B152,0xEBB2B0E,0x0];
+pub const CURVE_W:[[Chunk;NLEN];2]=[[0x3,0x0,0x204,0x8000000,0x6181,0x0,0x0,0x0,0x0,0x0],[0x1,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0]];
+pub const CURVE_SB:[[[Chunk;NLEN];2];2]=[[[0x4,0x0,0x285,0x8000000,0x6181,0x0,0x0,0x0,0x0,0x0],[0x1,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x1,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0xA,0x0,0xE9D,0x0,0x79E1E,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2]]];
+pub const CURVE_WB:[[Chunk;NLEN];4]=[[0x0,0x8000000,0x40,0x8000000,0x2080,0x0,0x0,0x0,0x0,0x0],[0x5,0x8000000,0x54A,0x0,0x1C707,0x8000000,0x312241,0x0,0x0,0x0],[0x3,0x8000000,0x2C5,0x8000000,0xE383,0xC000000,0x189120,0x0,0x0,0x0],[0x1,0x8000000,0xC1,0x8000000,0x2080,0x0,0x0,0x0,0x0,0x0]];
+pub const CURVE_BB:[[[Chunk;NLEN];4];4]=[[[0xD,0x8000000,0x1060,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2],[0xC,0x8000000,0x1060,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2],[0xC,0x8000000,0x1060,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2],[0x2,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x1,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0xC,0x8000000,0x1060,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2],[0xD,0x8000000,0x1060,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2],[0xC,0x8000000,0x1060,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2]],[[0x2,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x2,0x8000000,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x2,0x0,0x102,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0xA,0x0,0x1020,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2],[0x2,0x8000000,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]];
+
+pub const USE_GLV:bool = true;
+pub const USE_GS_G2:bool = true;
+pub const USE_GS_GT:bool = true;
+pub const GT_STRONG:bool = false;
diff --git a/version3/rust/rom_bn254_64.rs b/version3/rust/rom_bn254_64.rs
new file mode 100644
index 0000000..84b2e8d
--- /dev/null
+++ b/version3/rust/rom_bn254_64.rs
@@ -0,0 +1,53 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use bn254::big::NLEN;
+use arch::Chunk;
+
+// BN254 Modulus
+// Base Bits= 56
+pub const MODULUS:[Chunk;NLEN]=[0x13,0x13A7,0x80000000086121,0x40000001BA344D,0x25236482];
+pub const R2MODP:[Chunk;NLEN]=[0x2F2A96FF5E7E39,0x64E8642B96F13C,0x9926F7B00C7146,0x8321E7B4DACD24,0x1D127A2E];
+pub const MCONST:Chunk=0x435E50D79435E5;
+pub const FRA:[Chunk;NLEN]=[0x7DE6C06F2A6DE9,0x74924D3F77C2E1,0x50A846953F8509,0x212E7C8CB6499B,0x1B377619];
+pub const FRB:[Chunk;NLEN]=[0x82193F90D5922A,0x8B6DB2C08850C5,0x2F57B96AC8DC17,0x1ED1837503EAB2,0x9EBEE69];
+
+pub const CURVE_COF_I:isize = 1;
+pub const CURVE_A:isize = 0;
+pub const CURVE_B_I:isize = 2;
+pub const CURVE_B:[Chunk;NLEN]=[0x2,0x0,0x0,0x0,0x0];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0xD,0x800000000010A1,0x8000000007FF9F,0x40000001BA344D,0x25236482];
+pub const CURVE_GX:[Chunk;NLEN]=[0x12,0x13A7,0x80000000086121,0x40000001BA344D,0x25236482];
+pub const CURVE_GY:[Chunk;NLEN]=[0x1,0x0,0x0,0x0,0x0];
+pub const CURVE_BNX:[Chunk;NLEN]=[0x80000000000001,0x40,0x0,0x0,0x0];
+pub const CURVE_COF:[Chunk;NLEN]=[0x1,0x0,0x0,0x0,0x0];
+pub const CURVE_CRU:[Chunk;NLEN]=[0x80000000000007,0x6CD,0x40000000024909,0x49B362,0x0];
+pub const CURVE_PXA:[Chunk;NLEN]=[0xEE4224C803FB2B,0x8BBB4898BF0D91,0x7E8C61EDB6A464,0x519EB62FEB8D8C,0x61A10BB];
+pub const CURVE_PXB:[Chunk;NLEN]=[0x8C34C1E7D54CF3,0x746BAE3784B70D,0x8C5982AA5B1F4D,0xBA737833310AA7,0x516AAF9];
+pub const CURVE_PYA:[Chunk;NLEN]=[0xF0E07891CD2B9A,0xAE6BDBE09BD19,0x96698C822329BD,0x6BAF93439A90E0,0x21897A0];
+pub const CURVE_PYB:[Chunk;NLEN]=[0x2D1AEC6B3ACE9B,0x6FFD739C9578A,0x56F5F38D37B090,0x7C8B15268F6D44,0xEBB2B0E];
+pub const CURVE_W:[[Chunk;NLEN];2]=[[0x3,0x80000000000204,0x6181,0x0,0x0],[0x1,0x81,0x0,0x0,0x0]];
+pub const CURVE_SB:[[[Chunk;NLEN];2];2]=[[[0x4,0x80000000000285,0x6181,0x0,0x0],[0x1,0x81,0x0,0x0,0x0]],[[0x1,0x81,0x0,0x0,0x0],[0xA,0xE9D,0x80000000079E1E,0x40000001BA344D,0x25236482]]];
+pub const CURVE_WB:[[Chunk;NLEN];4]=[[0x80000000000000,0x80000000000040,0x2080,0x0,0x0],[0x80000000000005,0x54A,0x8000000001C707,0x312241,0x0],[0x80000000000003,0x800000000002C5,0xC000000000E383,0x189120,0x0],[0x80000000000001,0x800000000000C1,0x2080,0x0,0x0]];
+pub const CURVE_BB:[[[Chunk;NLEN];4];4]=[[[0x8000000000000D,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482],[0x8000000000000C,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482],[0x8000000000000C,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482],[0x2,0x81,0x0,0x0,0x0]],[[0x1,0x81,0x0,0x0,0x0],[0x8000000000000C,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482],[0x8000000000000D,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482],[0x8000000000000C,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482]],[[0x2,0x81,0x0,0x0,0x0],[0x1,0x81,0x0,0x0,0x0],[0x1,0x81,0x0,0x0,0x0],[0x1,0x81,0x0,0x0,0x0]],[[0x80000000000002,0x40,0x0,0x0,0x0],[0x2,0x102,0x0,0x0,0x0],[0xA,0x80000000001020,0x8000000007FF9F,0x40000001BA344D,0x25236482],[0x80000000000002,0x40,0x0,0x0,0x0]]];
+
+pub const USE_GLV:bool = true;
+pub const USE_GS_G2:bool = true;
+pub const USE_GS_GT:bool = true;
+pub const GT_STRONG:bool = false;
diff --git a/version3/rust/rom_brainpool_32.rs b/version3/rust/rom_brainpool_32.rs
new file mode 100644
index 0000000..7c9836b
--- /dev/null
+++ b/version3/rust/rom_brainpool_32.rs
@@ -0,0 +1,40 @@
+/*
+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.
+*/
+
+/* Note that the original curve has been transformed to an isomorphic curve with A=-3 */
+
+use brainpool::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 28
+// brainpool Modulus
+pub const MODULUS:[Chunk;NLEN]=[0xF6E5377,0x13481D1,0x6202820,0xF623D52,0xD726E3B,0x909D838,0xC3E660A,0xA1EEA9B,0x9FB57DB,0xA];
+pub const R2MODP:[Chunk;NLEN]=[0xB9A3787,0x9E04F49,0x8F3CF49,0x2931721,0xF1DBC89,0x54E8C3C,0xF7559CA,0xBB411A3,0x773E15F,0x9];
+pub const MCONST:Chunk=0xEFD89B9;
+
+// brainpool Curve 
+pub const CURVE_COF_I:isize = 1;
+pub const CURVE_A:isize = -3;
+pub const CURVE_B_I:isize = 0;
+pub const CURVE_COF:[Chunk;NLEN]=[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_B:[Chunk;NLEN]=[0xEE92B04,0xE58101F,0xF49256A,0xEBC4AF2,0x6B7BF93,0x733D0B7,0x4FE66A7,0x30D84EA,0x62C61C4,0x6];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0x74856A7,0x1E0E829,0x1A6F790,0x7AA3B56,0xD718C39,0x909D838,0xC3E660A,0xA1EEA9B,0x9FB57DB,0xA];
+pub const CURVE_GX:[Chunk;NLEN]=[0xE1305F4,0xA191562,0xFBC2B79,0x42C47AA,0x149AFA1,0xB23A656,0x7732213,0xC1CFE7B,0x3E8EB3C,0xA];
+pub const CURVE_GY:[Chunk;NLEN]=[0xB25C9BE,0xABE8F35,0x27001D,0xB6DE39D,0x17E69BC,0xE146444,0xD7F7B22,0x3439C56,0xD996C82,0x2];
+
diff --git a/version3/rust/rom_brainpool_64.rs b/version3/rust/rom_brainpool_64.rs
new file mode 100644
index 0000000..65765d8
--- /dev/null
+++ b/version3/rust/rom_brainpool_64.rs
@@ -0,0 +1,40 @@
+/*
+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.
+*/
+
+/* Note that the original curve has been transformed to an isomorphic curve with A=-3 */
+
+use brainpool::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 56
+// brainpool Modulus 
+pub const MODULUS:[Chunk;NLEN]=[0x13481D1F6E5377,0xF623D526202820,0x909D838D726E3B,0xA1EEA9BC3E660A,0xA9FB57DB];
+pub const R2MODP:[Chunk;NLEN]=[0x9E04F49B9A3787,0x29317218F3CF49,0x54E8C3CF1DBC89,0xBB411A3F7559CA,0x9773E15F];
+pub const MCONST:Chunk=0xA75590CEFD89B9;
+
+// brainpool Curve
+pub const CURVE_COF_I:isize = 1;
+pub const CURVE_A:isize = -3;
+pub const CURVE_B_I:isize = 0;
+pub const CURVE_COF:[Chunk;NLEN]=[0x1,0x0,0x0,0x0,0x0];
+pub const CURVE_B:[Chunk;NLEN]=[0xE58101FEE92B04,0xEBC4AF2F49256A,0x733D0B76B7BF93,0x30D84EA4FE66A7,0x662C61C4];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0x1E0E82974856A7,0x7AA3B561A6F790,0x909D838D718C39,0xA1EEA9BC3E660A,0xA9FB57DB];
+pub const CURVE_GX:[Chunk;NLEN]=[0xA191562E1305F4,0x42C47AAFBC2B79,0xB23A656149AFA1,0xC1CFE7B7732213,0xA3E8EB3C];
+pub const CURVE_GY:[Chunk;NLEN]=[0xABE8F35B25C9BE,0xB6DE39D027001D,0xE14644417E69BC,0x3439C56D7F7B22,0x2D996C82];
+
diff --git a/version3/rust/rom_c25519_32.rs b/version3/rust/rom_c25519_32.rs
new file mode 100644
index 0000000..dbeb1c7
--- /dev/null
+++ b/version3/rust/rom_c25519_32.rs
@@ -0,0 +1,39 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use c25519::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 29
+// Curve25519 Modulus 
+pub const MODULUS:[Chunk;NLEN]=[0x1FFFFFED,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFFF];
+pub const R2MODP:[Chunk;NLEN]=[0x169000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const MCONST:Chunk=0x13;
+
+// c25519 Curve 
+pub const CURVE_COF_I:isize = 8;
+pub const CURVE_A:isize = 486662;
+pub const CURVE_B_I:isize = 0;
+pub const CURVE_COF:[Chunk;NLEN]=[0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_B:[Chunk;NLEN]=[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0x1CF5D3ED,0x9318D2,0x1DE73596,0x1DF3BD45,0x14D,0x0,0x0,0x0,0x100000];
+pub const CURVE_GX:[Chunk;NLEN]=[0x9,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_GY:[Chunk;NLEN]=[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+
+
diff --git a/version3/rust/rom_c25519_64.rs b/version3/rust/rom_c25519_64.rs
new file mode 100644
index 0000000..4b7edda
--- /dev/null
+++ b/version3/rust/rom_c25519_64.rs
@@ -0,0 +1,38 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use c25519::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 56
+// Curve25519 Modulus
+pub const MODULUS:[Chunk;NLEN]=[0xFFFFFFFFFFFFED,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0x7FFFFFFF];
+pub const R2MODP:[Chunk;NLEN]=[0xA4000000000000,0x5,0x0,0x0,0x0];
+pub const MCONST:Chunk=0x13;
+
+// c25519 Curve
+pub const CURVE_COF_I:isize = 8;
+pub const CURVE_A:isize = 486662;
+pub const CURVE_B_I:isize = 0;
+pub const CURVE_COF:[Chunk;NLEN]=[0x8,0x0,0x0,0x0,0x0];
+pub const CURVE_B:[Chunk;NLEN]=[0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0x12631A5CF5D3ED,0xF9DEA2F79CD658,0x14DE,0x0,0x10000000];
+pub const CURVE_GX:[Chunk;NLEN]=[0x9,0x0,0x0,0x0,0x0];
+pub const CURVE_GY:[Chunk;NLEN]=[0x0,0x0,0x0,0x0,0x0];
+
diff --git a/version3/rust/rom_c41417_32.rs b/version3/rust/rom_c41417_32.rs
new file mode 100644
index 0000000..ea69185
--- /dev/null
+++ b/version3/rust/rom_c41417_32.rs
@@ -0,0 +1,38 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use c41417::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 29
+// c41417 Modulus 
+pub const MODULUS:[Chunk;NLEN]=[0x1FFFFFEF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFF];
+pub const R2MODP:[Chunk;NLEN]=[0x0,0x242000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const MCONST:Chunk=0x11;
+
+// c41417 Curve 
+pub const CURVE_COF_I:isize = 8;
+pub const CURVE_A:isize = 1;
+pub const CURVE_B_I:isize = 3617;
+pub const CURVE_COF:[Chunk;NLEN]=[0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_B:[Chunk;NLEN]=[0xE21,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0x106AF79,0x18738D2F,0x18F3C606,0x1806715A,0x22B36F1,0xA67B830,0xCF32490,0x1FFFFFFD,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1F];
+pub const CURVE_GX:[Chunk;NLEN]=[0x13CBC595,0x7E9C097,0x14DF1931,0x14E7F550,0x1A111301,0x15A6B6B5,0xD526292,0x18FEAFFE,0x1F44C03E,0x1E6A31B4,0x70C9B97,0x43180C6,0x1443300,0x19A4828A,0x68];
+pub const CURVE_GY:[Chunk;NLEN]=[0x22,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+
diff --git a/version3/rust/rom_c41417_64.rs b/version3/rust/rom_c41417_64.rs
new file mode 100644
index 0000000..015c7b3
--- /dev/null
+++ b/version3/rust/rom_c41417_64.rs
@@ -0,0 +1,38 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use c41417::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 60
+// c41417 Modulus 
+pub const MODULUS:[Chunk;NLEN]=[0xFFFFFFFFFFFFFEF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0x3FFFFFFFFFFFFF];
+pub const R2MODP:[Chunk;NLEN]=[0x121000,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const MCONST:Chunk=0x11;
+
+// c41417 Curve 
+pub const CURVE_COF_I:isize = 8;
+pub const CURVE_A:isize = 1;
+pub const CURVE_B_I:isize = 3617;
+pub const CURVE_COF:[Chunk;NLEN]=[0x8,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_B:[Chunk;NLEN]=[0xE21,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0xB0E71A5E106AF79,0x1C0338AD63CF181,0x414CF706022B36F,0xFFFFFFFFEB3CC92,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0x7FFFFFFFFFFFF];
+pub const CURVE_GX:[Chunk;NLEN]=[0x4FD3812F3CBC595,0x1A73FAA8537C64C,0x4AB4D6D6BA11130,0x3EC7F57FF35498A,0xE5FCD46369F44C0,0x300218C0631C326,0x1A334905141443];
+pub const CURVE_GY:[Chunk;NLEN]=[0x22,0x0,0x0,0x0,0x0,0x0,0x0];
+
diff --git a/version3/rust/rom_ed25519_32.rs b/version3/rust/rom_ed25519_32.rs
new file mode 100644
index 0000000..3b1652b
--- /dev/null
+++ b/version3/rust/rom_ed25519_32.rs
@@ -0,0 +1,38 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use ed25519::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 29
+// Curve25519 Modulus 
+pub const MODULUS:[Chunk;NLEN]=[0x1FFFFFED,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFFF];
+pub const R2MODP:[Chunk;NLEN]=[0x169000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const MCONST:Chunk=0x13;
+
+// Ed25519 Curve
+pub const CURVE_COF_I:isize = 8;
+pub const CURVE_A:isize = -1;
+pub const CURVE_B_I:isize = 0;
+pub const CURVE_COF:[Chunk;NLEN]=[0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_B:[Chunk;NLEN]=[0x135978A3,0xF5A6E50,0x10762ADD,0x149A82,0x1E898007,0x3CBBBC,0x19CE331D,0x1DC56DFF,0x52036C];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0x1CF5D3ED,0x9318D2,0x1DE73596,0x1DF3BD45,0x14D,0x0,0x0,0x0,0x100000];
+pub const CURVE_GX:[Chunk;NLEN]=[0xF25D51A,0xAB16B04,0x969ECB2,0x198EC12A,0xDC5C692,0x1118FEEB,0xFFB0293,0x1A79ADCA,0x216936];
+pub const CURVE_GY:[Chunk;NLEN]=[0x6666658,0x13333333,0x19999999,0xCCCCCCC,0x6666666,0x13333333,0x19999999,0xCCCCCCC,0x666666];
+
diff --git a/version3/rust/rom_ed25519_64.rs b/version3/rust/rom_ed25519_64.rs
new file mode 100644
index 0000000..75a85f1
--- /dev/null
+++ b/version3/rust/rom_ed25519_64.rs
@@ -0,0 +1,38 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use ed25519::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 56
+// Curve25519 Modulus
+pub const MODULUS:[Chunk;NLEN]=[0xFFFFFFFFFFFFED,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0x7FFFFFFF];
+pub const R2MODP:[Chunk;NLEN]=[0xA4000000000000,0x5,0x0,0x0,0x0];
+pub const MCONST:Chunk=0x13;
+
+// Ed25519 Curve
+pub const CURVE_COF_I:isize = 8;
+pub const CURVE_A:isize = -1;
+pub const CURVE_B_I:isize = 0;
+pub const CURVE_COF:[Chunk;NLEN]=[0x8,0x0,0x0,0x0,0x0];
+pub const CURVE_B:[Chunk;NLEN]=[0xEB4DCA135978A3,0xA4D4141D8AB75,0x797779E8980070,0x2B6FFE738CC740,0x52036CEE];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0x12631A5CF5D3ED,0xF9DEA2F79CD658,0x14DE,0x0,0x10000000];
+pub const CURVE_GX:[Chunk;NLEN]=[0x562D608F25D51A,0xC7609525A7B2C9,0x31FDD6DC5C692C,0xCD6E53FEC0A4E2,0x216936D3];
+pub const CURVE_GY:[Chunk;NLEN]=[0x66666666666658,0x66666666666666,0x66666666666666,0x66666666666666,0x66666666];
+
diff --git a/version3/rust/rom_fp256bn_32.rs b/version3/rust/rom_fp256bn_32.rs
new file mode 100644
index 0000000..9b72e1f
--- /dev/null
+++ b/version3/rust/rom_fp256bn_32.rs
@@ -0,0 +1,54 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use fp256bn::big::NLEN;
+use arch::Chunk;
+
+
+// Base Bits= 28
+pub const MODULUS:[Chunk;NLEN]=[0xED33013,0x292DDBA,0x80A82D3,0x65FB129,0x49F0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF];
+pub const R2MODP:[Chunk;NLEN]=[0x3B9F8B,0xEDE3363,0xFEC54E8,0x92FFEE9,0x3C55F79,0x13C1C06,0xC0123FA,0xA12F2EA,0xE559B2A,0x8];
+pub const MCONST:Chunk=0x537E5E5;
+
+pub const CURVE_COF_I:isize = 1;
+pub const CURVE_A:isize = 0;
+pub const CURVE_B_I:isize = 3;
+pub const CURVE_B:[Chunk;NLEN]=[0x3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0x10B500D,0x2D536CD,0x9921AF6,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF];
+pub const CURVE_GX:[Chunk;NLEN]=[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_GY:[Chunk;NLEN]=[0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+
+pub const FRA:[Chunk;NLEN]=[0xF943106,0x760328A,0xAB28F74,0x71511E3,0x7CF39A1,0x8DDB086,0x52D1A6E,0xCA786F3,0xD617662,0x3];
+pub const FRB:[Chunk;NLEN]=[0xF3EFF0D,0xB32AB2F,0xD57F35E,0xF4A9F45,0xCCFD33A,0xD113693,0x819CB83,0x3584819,0x29E899D,0xC];
+pub const CURVE_BNX:[Chunk;NLEN]=[0xB0A801,0x82F5C03,0x68,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_COF:[Chunk;NLEN]=[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_CRU:[Chunk;NLEN]=[0x3A1B807,0x1C0A24A,0x32D1EDB,0xD79DF19,0x8659BCD,0x4092101,0x13988E1,0x0,0x0,0x0];
+pub const CURVE_PXA:[Chunk;NLEN]=[0x9C09EFB,0x2616B68,0xF843CD2,0x539A12B,0x13ACE1C,0x577C289,0x28560F,0xB4C96C2,0xE0C3350,0xF];
+pub const CURVE_PXB:[Chunk;NLEN]=[0x37E6A2B,0x69ED34A,0x3589D2,0x78E287D,0x3B924DD,0xC637D81,0x4DB5AE1,0x738AC05,0xEA66057,0x4];
+pub const CURVE_PYA:[Chunk;NLEN]=[0xEDC27FF,0x9B481B,0x15848E9,0x24758D6,0xE51EFCB,0x75124E3,0x376770D,0xC542A3B,0x2046E7,0x7];
+pub const CURVE_PYB:[Chunk;NLEN]=[0xAAD049B,0x1281114,0xA98B3E0,0xBE80821,0x29F8B4C,0x49297EB,0x42EEA6,0xD388C29,0x554E3BC,0x0];
+pub const CURVE_W:[[Chunk;NLEN];2]=[[0xB054003,0xF0036E1,0xE78663A,0xFFFFFFF,0xFFFF,0x0,0x0,0x0,0x0,0x0],[0x1615001,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0]];
+pub const CURVE_SB:[[[Chunk;NLEN];2];2]=[[[0xC669004,0xF5EEEE7,0xE78670B,0xFFFFFFF,0xFFFF,0x0,0x0,0x0,0x0,0x0],[0x1615001,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x1615001,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x606100A,0x3D4FFEB,0xB19B4BB,0x65FB129,0x49D0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF]]];
+pub const CURVE_WB:[[Chunk;NLEN];4]=[[0xD30A800,0x20678F0,0x4D2CC10,0x5555555,0x5555,0x0,0x0,0x0,0x0,0x0],[0xD7DC805,0xD6764C0,0xBC3AD1A,0x8FBEA10,0x4467DE,0x8061601,0xD105EB,0x0,0x0,0x0],[0xF173803,0xACB6061,0x5E1D6C1,0x47DF508,0x82233EF,0xC030B00,0x6882F5,0x0,0x0,0x0],[0xE91F801,0x26530F6,0x4D2CCE1,0x5555555,0x5555,0x0,0x0,0x0,0x0,0x0]];
+pub const CURVE_BB:[[[Chunk;NLEN];4];4]=[[[0x5AA80D,0xAA5DACA,0x9921A8D,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF],[0x5AA80C,0xAA5DACA,0x9921A8D,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF],[0x5AA80C,0xAA5DACA,0x9921A8D,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF],[0x1615002,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x1615001,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x5AA80C,0xAA5DACA,0x9921A8D,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF],[0x5AA80D,0xAA5DACA,0x9921A8D,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF],[0x5AA80C,0xAA5DACA,0x9921A8D,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF]],[[0x1615002,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1615001,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1615001,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1615001,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0xB0A802,0x82F5C03,0x68,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x2C2A002,0xBD700C,0x1A2,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0xFAA000A,0x2767EC6,0x9921A25,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF],[0xB0A802,0x82F5C03,0x68,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]];
+
+pub const USE_GLV:bool = true;
+pub const USE_GS_G2:bool = true;
+pub const USE_GS_GT:bool = true;
+pub const GT_STRONG:bool = false;
diff --git a/version3/rust/rom_fp256bn_64.rs b/version3/rust/rom_fp256bn_64.rs
new file mode 100644
index 0000000..15579f6
--- /dev/null
+++ b/version3/rust/rom_fp256bn_64.rs
@@ -0,0 +1,54 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use fp256bn::big::NLEN;
+use arch::Chunk;
+
+// fp256bn Modulus
+// Base Bits= 56
+pub const MODULUS:[Chunk;NLEN]=[0x292DDBAED33013,0x65FB12980A82D3,0x5EEE71A49F0CDC,0xFFFCF0CD46E5F2,0xFFFFFFFF];
+pub const R2MODP:[Chunk;NLEN]=[0xEDE336303B9F8B,0x92FFEE9FEC54E8,0x13C1C063C55F79,0xA12F2EAC0123FA,0x8E559B2A];
+pub const MCONST:Chunk=0x6C964E0537E5E5;
+
+pub const CURVE_COF_I:isize = 1;
+pub const CURVE_A:isize = 0;
+pub const CURVE_B_I:isize = 3;
+pub const CURVE_B:[Chunk;NLEN]=[0x3,0x0,0x0,0x0,0x0];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0x2D536CD10B500D,0x65FB1299921AF6,0x5EEE71A49E0CDC,0xFFFCF0CD46E5F2,0xFFFFFFFF];
+pub const CURVE_GX:[Chunk;NLEN]=[0x1,0x0,0x0,0x0,0x0];
+pub const CURVE_GY:[Chunk;NLEN]=[0x2,0x0,0x0,0x0,0x0];
+
+pub const FRA:[Chunk;NLEN]=[0x760328AF943106,0x71511E3AB28F74,0x8DDB0867CF39A1,0xCA786F352D1A6E,0x3D617662];
+pub const FRB:[Chunk;NLEN]=[0xB32AB2FF3EFF0D,0xF4A9F45D57F35E,0xD113693CCFD33A,0x3584819819CB83,0xC29E899D];
+pub const CURVE_BNX:[Chunk;NLEN]=[0x82F5C030B0A801,0x68,0x0,0x0,0x0];
+pub const CURVE_COF:[Chunk;NLEN]=[0x1,0x0,0x0,0x0,0x0];
+pub const CURVE_CRU:[Chunk;NLEN]=[0x1C0A24A3A1B807,0xD79DF1932D1EDB,0x40921018659BCD,0x13988E1,0x0];
+pub const CURVE_PXA:[Chunk;NLEN]=[0x2616B689C09EFB,0x539A12BF843CD2,0x577C28913ACE1C,0xB4C96C2028560F,0xFE0C3350];
+pub const CURVE_PXB:[Chunk;NLEN]=[0x69ED34A37E6A2B,0x78E287D03589D2,0xC637D813B924DD,0x738AC054DB5AE1,0x4EA66057];
+pub const CURVE_PYA:[Chunk;NLEN]=[0x9B481BEDC27FF,0x24758D615848E9,0x75124E3E51EFCB,0xC542A3B376770D,0x702046E7];
+pub const CURVE_PYB:[Chunk;NLEN]=[0x1281114AAD049B,0xBE80821A98B3E0,0x49297EB29F8B4C,0xD388C29042EEA6,0x554E3BC];
+pub const CURVE_W:[[Chunk;NLEN];2]=[[0xF0036E1B054003,0xFFFFFFFE78663A,0xFFFF,0x0,0x0],[0x5EB8061615001,0xD1,0x0,0x0,0x0]];
+pub const CURVE_SB:[[[Chunk;NLEN];2];2]=[[[0xF5EEEE7C669004,0xFFFFFFFE78670B,0xFFFF,0x0,0x0],[0x5EB8061615001,0xD1,0x0,0x0,0x0]],[[0x5EB8061615001,0xD1,0x0,0x0,0x0],[0x3D4FFEB606100A,0x65FB129B19B4BB,0x5EEE71A49D0CDC,0xFFFCF0CD46E5F2,0xFFFFFFFF]]];
+pub const CURVE_WB:[[Chunk;NLEN];4]=[[0x20678F0D30A800,0x55555554D2CC10,0x5555,0x0,0x0],[0xD6764C0D7DC805,0x8FBEA10BC3AD1A,0x806160104467DE,0xD105EB,0x0],[0xACB6061F173803,0x47DF5085E1D6C1,0xC030B0082233EF,0x6882F5,0x0],[0x26530F6E91F801,0x55555554D2CCE1,0x5555,0x0,0x0]];
+pub const CURVE_BB:[[[Chunk;NLEN];4];4]=[[[0xAA5DACA05AA80D,0x65FB1299921A8D,0x5EEE71A49E0CDC,0xFFFCF0CD46E5F2,0xFFFFFFFF],[0xAA5DACA05AA80C,0x65FB1299921A8D,0x5EEE71A49E0CDC,0xFFFCF0CD46E5F2,0xFFFFFFFF],[0xAA5DACA05AA80C,0x65FB1299921A8D,0x5EEE71A49E0CDC,0xFFFCF0CD46E5F2,0xFFFFFFFF],[0x5EB8061615002,0xD1,0x0,0x0,0x0]],[[0x5EB8061615001,0xD1,0x0,0x0,0x0],[0xAA5DACA05AA80C,0x65FB1299921A8D,0x5EEE71A49E0CDC,0xFFFCF0CD46E5F2,0xFFFFFFFF],[0xAA5DACA05AA80D,0x65FB1299921A8D,0x5EEE71A49E0CDC,0xFFFCF0CD46E5F2,0xFFFFFFFF],[0xAA5DACA05AA80C,0x65FB1299921A8D,0x5EEE71A49E0CDC,0xFFFCF0CD46E5F2,0xFFFFFFFF]],[[0x5EB8061615002,0xD1,0x0,0x0,0x0],[0x5EB8061615001,0xD1,0x0,0x0,0x0],[0x5EB8061615001,0xD1,0x0,0x0,0x0],[0x5EB8061615001,0xD1,0x0,0x0,0x0]],[[0x82F5C030B0A802,0x68,0x0,0x0,0x0],[0xBD700C2C2A002,0x1A2,0x0,0x0,0x0],[0x2767EC6FAA000A,0x65FB1299921A25,0x5EEE71A49E0CDC,0xFFFCF0CD46E5F2,0xFFFFFFFF],[0x82F5C030B0A802,0x68,0x0,0x0,0x0]]];
+
+pub const USE_GLV:bool = true;
+pub const USE_GS_G2:bool = true;
+pub const USE_GS_GT:bool = true;
+pub const GT_STRONG:bool = false;
diff --git a/version3/rust/rom_fp512bn_32.rs b/version3/rust/rom_fp512bn_32.rs
new file mode 100644
index 0000000..2f64139
--- /dev/null
+++ b/version3/rust/rom_fp512bn_32.rs
@@ -0,0 +1,53 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use fp512bn::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 29
+pub const MODULUS:[Chunk;NLEN]=[0x2ADEF33,0x7594049,0x131919ED,0x14AB9CBE,0x16FE1916,0x12EF5591,0x2E39231,0x3D597D3,0x55146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF];
+pub const R2MODP:[Chunk;NLEN]=[0xFD68B47,0xFCF5D2C,0x437675A,0x1BBC3FBF,0x1411E413,0x13453559,0x10B5639,0x1C34CE79,0x6D476BF,0xFD05F2B,0x15D17C28,0x6C9F76E,0x1C2375B3,0x78CCE9B,0x15F0AB33,0x1960F32E,0x1A8D44E,0x57A38];
+pub const MCONST:Chunk=0x1CCC5C05;
+
+pub const CURVE_COF_I:isize = 1;
+pub const CURVE_A:isize = 0;
+pub const CURVE_B_I:isize = 3;
+pub const CURVE_B:[Chunk;NLEN]=[0x3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0x119A09ED,0x153252FA,0x1E68AD01,0x627C09,0x79A34A1,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF];
+pub const CURVE_GX:[Chunk;NLEN]=[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_GY:[Chunk;NLEN]=[0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+
+pub const FRA:[Chunk;NLEN]=[0x14B73AB2,0x4B0BD8F,0xABB47D,0x2A29EC4,0x18681E17,0x104069DE,0x12EED67D,0x1553D0A5,0x398E9F8,0x7971034,0xAC9AF23,0x52DEF23,0x14EA18A5,0x1463E345,0x6DE465A,0x17F212B4,0x1AA9CF5B,0xF7B8];
+pub const FRB:[Chunk;NLEN]=[0xDF6B481,0x2A882B9,0x126D6570,0x1208FDFA,0x1E95FAFF,0x2AEEBB2,0xFF4BBB4,0xE81C72D,0x1B85CD6,0xF67746,0x56549CD,0xC68B6EC,0x776A178,0x8925C3B,0x1921B9A5,0x80DED4B,0x55630A4,0x70847];
+pub const CURVE_BNX:[Chunk;NLEN]=[0x1E1BD80F,0x59835DA,0xC3DFC04,0x5EB8061,0x688,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_COF:[Chunk;NLEN]=[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_CRU:[Chunk;NLEN]=[0x1C79298A,0x1838B104,0x2C5F052,0x1DCCF337,0x6092AEC,0x4B35F29,0x1EB361E,0x11384EA,0x3074B20,0x17BB08FD,0x3A8B3E3,0xD70D66F,0x3D2A614,0x1CF63EE4,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF];
+pub const CURVE_PXA:[Chunk;NLEN]=[0xDB646B5,0x183D4B70,0x1CBFFA3,0x11F0E632,0x1C78F221,0x1F10DE5D,0x171B715E,0xF0C6A29,0x10B02453,0xBE63C66,0xE6D5F69,0x166B1E1B,0x4BBBD29,0x179E750F,0x6E9D04,0xC912B10,0x1339E138,0x1D8B2];
+pub const CURVE_PXB:[Chunk;NLEN]=[0x1A8AE0E9,0xDAE5F7E,0x22446CF,0x1948239B,0x15ADCE40,0xB709C1E,0x18357943,0xE50AA4D,0x19781E22,0x12B35CA6,0x11DAA2C0,0x18D8DDE4,0x5EA656D,0x15F45A41,0xD311A02,0xCFCD913,0x13CBF850,0x240E0];
+pub const CURVE_PYA:[Chunk;NLEN]=[0xDDE67A1,0x12401895,0x17BEE178,0x142F5AC2,0xB7BC5CD,0x92A1404,0x1A3B748C,0x17BD82A7,0x14B6CD18,0xAC34CE,0x1740FB97,0x1ECC15F9,0x17085B1D,0x1D1BA793,0x1BD6AC32,0x18F70525,0xC84C827,0x3780F];
+pub const CURVE_PYB:[Chunk;NLEN]=[0x84F8E8B,0xC5B8C36,0xFDD85A1,0xB84449,0x19C08DFF,0x56BF713,0x1C5290C4,0x187C5CA0,0x1DA2897F,0x24B0CA0,0x326D8F4,0x2310CF6,0x1021438C,0xFBAEC8F,0xD9030C5,0x1CF06358,0x1CEC8B04,0x28D1D];
+pub const CURVE_W:[[Chunk;NLEN];2]=[[0x9834583,0x887C4BA,0x5A85CFC,0xBF7223A,0xF63FE96,0x1FFFFFFE,0x1FFFFFFF,0x1FFFFFFF,0xFFFFFF,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1C37B01F,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]];
+pub const CURVE_SB:[[[Chunk;NLEN];2];2]=[[[0xD4B9564,0x1D575904,0xD2C64F3,0x202177,0xF63F186,0x1FFFFFFE,0x1FFFFFFF,0x1FFFFFFF,0xFFFFFF,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x156259CE,0xA01E744,0x5ECB4F9,0x148B7B47,0x79A2790,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF]],[[0x1C37B01F,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x9834583,0x887C4BA,0x5A85CFC,0xBF7223A,0xF63FE96,0x1FFFFFFE,0x1FFFFFFF,0x1FFFFFFF,0xFFFFFF,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]];
+pub const CURVE_WB:[[Chunk;NLEN];4]=[[0x155A29F0,0x16D59B55,0xF4C305,0x18858C0B,0x5215FBF,0xAAAAAAA,0x15555555,0xAAAAAAA,0x555555,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x2355D4B,0x1758095D,0x1FE13C5F,0x41F83FA,0xBB5E5CF,0x97D4EF1,0xB503D62,0x172C0C9B,0x16315274,0x15E1A9A8,0x859835D,0x2C3DFC0,0x105EB806,0x68,0x0,0x0,0x0,0x0],[0x289AAD,0x1E781F9C,0x60F9C31,0x1505822E,0x15DAF62B,0x4BEA778,0x15A81EB1,0xB96064D,0xB18A93A,0x1AF0D4D4,0x42CC1AE,0x161EFE0,0x82F5C03,0x34,0x0,0x0,0x0,0x0],[0x192279D1,0xBA52F9F,0x878CAFD,0xCAE8B48,0x52152AF,0xAAAAAAA,0x15555555,0xAAAAAAA,0x555555,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]];
+pub const CURVE_BB:[[[Chunk;NLEN];4];4]=[[[0x1E1BD810,0x59835DA,0xC3DFC04,0x5EB8061,0x688,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1E1BD80F,0x59835DA,0xC3DFC04,0x5EB8061,0x688,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1E1BD80F,0x59835DA,0xC3DFC04,0x5EB8061,0x688,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x156259CF,0xA01E744,0x5ECB4F9,0x148B7B47,0x79A2790,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF]],[[0x1C37B01F,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x137E31DE,0xF9A1D1F,0x122AB0FD,0x1A76FBA8,0x79A2E18,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF],[0x137E31DD,0xF9A1D1F,0x122AB0FD,0x1A76FBA8,0x79A2E18,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF],[0x137E31DE,0xF9A1D1F,0x122AB0FD,0x1A76FBA8,0x79A2E18,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF]],[[0x1C37B01E,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1C37B01F,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1C37B01F,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1C37B01F,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x137E31DF,0xF9A1D1F,0x122AB0FD,0x1A76FBA8,0x79A2E18,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF],[0x192AA9AF,0x1ED17B8E,0xD70BCF0,0x8B47A84,0x79A1A80,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF],[0x1C37B01D,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x137E31DF,0xF9A1D1F,0x122AB0FD,0x1A76FBA8,0x79A2E18,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF]]];
+
+pub const USE_GLV:bool = true;
+pub const USE_GS_G2:bool = true;
+pub const USE_GS_GT:bool = true;
+pub const GT_STRONG:bool = false;
diff --git a/version3/rust/rom_fp512bn_64.rs b/version3/rust/rom_fp512bn_64.rs
new file mode 100644
index 0000000..bcc3768
--- /dev/null
+++ b/version3/rust/rom_fp512bn_64.rs
@@ -0,0 +1,53 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use fp512bn::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 60
+pub const MODULUS:[Chunk;NLEN]=[0x4EB280922ADEF33,0x6A55CE5F4C6467B,0xC65DEAB236FE191,0xCF1EACBE98B8E48,0x3C111B0EF455146,0xA1D8CB5307C0BBE,0xFFFF9EC7F01C60B,0xFFFFFFFFFFFFFFF,0xFFFFFFFF];
+pub const R2MODP:[Chunk;NLEN]=[0x1FA6DCEF99812E9,0xAB3452895A0B74E,0xC53EA988C079E1E,0x1E90E033BA630B9,0xF1EA41C0714D8B0,0xE72785387509E28,0xD86794F834DAB00,0x9757C2ACCD342A1,0x44ECB079];
+pub const MCONST:Chunk=0x692A189FCCC5C05;
+
+pub const CURVE_COF_I:isize = 1;
+pub const CURVE_A:isize = 0;
+pub const CURVE_B_I:isize = 3;
+pub const CURVE_B:[Chunk;NLEN]=[0x3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0x6A64A5F519A09ED,0x10313E04F9A2B40,0xC65DEAB2679A34A,0xCF1EACBE98B8E48,0x3C111B0EF445146,0xA1D8CB5307C0BBE,0xFFFF9EC7F01C60B,0xFFFFFFFFFFFFFFF,0xFFFFFFFF];
+pub const CURVE_GX:[Chunk;NLEN]=[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_GY:[Chunk;NLEN]=[0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+
+pub const FRA:[Chunk;NLEN]=[0x49617B1F4B73AB2,0x71514F6202AED1F,0xF6080D3BD8681E1,0xF8AA9E852CBBB59,0xC8CF2E2068398E9,0x8A5296F791AB26B,0x196A8C7C68B4EA1,0xCF5BBF9095A1B79,0x1EF71AA9];
+pub const FRB:[Chunk;NLEN]=[0x5510572DF6B481,0xF9047EFD49B595C,0xD055DD765E95FAF,0xD6740E396BFD2EE,0x7341ECEE8C1B85C,0x1786345B7615952,0xE695124B876776A,0x30A4406F6A5E486,0xE108E556];
+pub const CURVE_BNX:[Chunk;NLEN]=[0xB306BB5E1BD80F,0x82F5C030B0F7F01,0x68,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_COF:[Chunk;NLEN]=[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_CRU:[Chunk;NLEN]=[0xB0716209C79298A,0xCEE6799B8B17C14,0x78966BE526092AE,0x20089C27507ACD8,0xF8EF7611FA3074B,0x6146B86B378EA2C,0xFFFF9EC7DC83D2A,0xFFFFFFFFFFFFFFF,0xFFFFFFFF];
+pub const CURVE_PXA:[Chunk;NLEN]=[0xF07A96E0DB646B5,0x18F87319072FFE8,0x7BE21BCBBC78F22,0x537863514DC6DC5,0xDA57CC78CD0B024,0xD29B358F0DB9B57,0x7412F3CEA1E4BBB,0xE138648958801BA,0x3B165339];
+pub const CURVE_PXB:[Chunk;NLEN]=[0xDB5CBEFDA8AE0E9,0xCA411CD88911B3,0xD6E1383D5ADCE4,0x227285526E0D5E5,0xB02566B94D9781E,0x56DC6C6EF2476A8,0x680ABE8B4825EA6,0xF85067E6C89B4C4,0x481C13CB];
+pub const CURVE_PYA:[Chunk;NLEN]=[0x2480312ADDE67A1,0xDA17AD615EFB85E,0x312542808B7BC5C,0x18BDEC153E8EDD2,0xE5C158699D4B6CD,0xB1DF660AFCDD03E,0xB0CBA374F277085,0xC827C7B8292EF5A,0x6F01EC84];
+pub const CURVE_PYB:[Chunk;NLEN]=[0x58B7186C84F8E8B,0xF05C2224BF76168,0x10AD7EE279C08DF,0x7FC3E2E50714A43,0x3D04961941DA289,0x38C118867B0C9B6,0xC315F75D91F0214,0x8B04E7831AC3640,0x51A3BCEC];
+pub const CURVE_W:[[Chunk;NLEN];2]=[[0x110F89749834583,0x65FB911D16A173F,0xFFFFFFFFCF63FE9,0xFFFFFFFFFFFFFFF,0xFFFF,0x0,0x0,0x0,0x0],[0x1660D76BC37B01F,0x5EB806161EFE02,0xD1,0x0,0x0,0x0,0x0,0x0,0x0]];
+pub const CURVE_SB:[[[Chunk;NLEN];2];2]=[[[0xFAAEB208D4B9564,0x601010BBB4B193C,0xFFFFFFFFCF63F18,0xFFFFFFFFFFFFFFF,0xFFFF,0x0,0x0,0x0,0x0],[0x5403CE8956259CE,0xA45BDA397B2D3E,0xC65DEAB2679A279,0xCF1EACBE98B8E48,0x3C111B0EF445146,0xA1D8CB5307C0BBE,0xFFFF9EC7F01C60B,0xFFFFFFFFFFFFFFF,0xFFFFFFFF]],[[0x1660D76BC37B01F,0x5EB806161EFE02,0xD1,0x0,0x0,0x0,0x0,0x0,0x0],[0x110F89749834583,0x65FB911D16A173F,0xFFFFFFFFCF63FE9,0xFFFFFFFFFFFFFFF,0xFFFF,0x0,0x0,0x0,0x0]]];
+pub const CURVE_WB:[[Chunk;NLEN];4]=[[0x6DAB36AB55A29F0,0xFC42C60583D30C1,0x5555555545215FB,0x555555555555555,0x5555,0x0,0x0,0x0,0x0],[0xEEB012BA2355D4B,0xF20FC1FD7F84F17,0x892FA9DE2BB5E5C,0x74B96064DAD40F5,0xD76BC3535163152,0x806161EFE021660,0xD105EB,0x0,0x0],[0x7CF03F380289AAD,0xBA82C117183E70C,0xC497D4EF15DAF62,0x3A5CB0326D6A07A,0x6BB5E1A9A8B18A9,0xC030B0F7F010B30,0x6882F5,0x0,0x0],[0x574A5F3F92279D1,0xF65745A421E32BF,0x55555555452152A,0x555555555555555,0x5555,0x0,0x0,0x0,0x0]];
+pub const CURVE_BB:[[[Chunk;NLEN];4];4]=[[[0xB306BB5E1BD810,0x82F5C030B0F7F01,0x68,0x0,0x0,0x0,0x0,0x0,0x0],[0xB306BB5E1BD80F,0x82F5C030B0F7F01,0x68,0x0,0x0,0x0,0x0,0x0,0x0],[0xB306BB5E1BD80F,0x82F5C030B0F7F01,0x68,0x0,0x0,0x0,0x0,0x0,0x0],[0x5403CE8956259CF,0xA45BDA397B2D3E,0xC65DEAB2679A279,0xCF1EACBE98B8E48,0x3C111B0EF445146,0xA1D8CB5307C0BBE,0xFFFF9EC7F01C60B,0xFFFFFFFFFFFFFFF,0xFFFFFFFF]],[[0x1660D76BC37B01F,0x5EB806161EFE02,0xD1,0x0,0x0,0x0,0x0,0x0,0x0],[0x5F343A3F37E31DE,0x8D3B7DD448AAC3F,0xC65DEAB2679A2E1,0xCF1EACBE98B8E48,0x3C111B0EF445146,0xA1D8CB5307C0BBE,0xFFFF9EC7F01C60B,0xFFFFFFFFFFFFFFF,0xFFFFFFFF],[0x5F343A3F37E31DD,0x8D3B7DD448AAC3F,0xC65DEAB2679A2E1,0xCF1EACBE98B8E48,0x3C111B0EF445146,0xA1D8CB5307C0BBE,0xFFFF9EC7F01C60B,0xFFFFFFFFFFFFFFF,0xFFFFFFFF],[0x5F343A3F37E31DE,0x8D3B7DD448AAC3F,0xC65DEAB2679A2E1,0xCF1EACBE98B8E48,0x3C111B0EF445146,0xA1D8CB5307C0BBE,0xFFFF9EC7F01C60B,0xFFFFFFFFFFFFFFF,0xFFFFFFFF]],[[0x1660D76BC37B01E,0x5EB806161EFE02,0xD1,0x0,0x0,0x0,0x0,0x0,0x0],[0x1660D76BC37B01F,0x5EB806161EFE02,0xD1,0x0,0x0,0x0,0x0,0x0,0x0],[0x1660D76BC37B01F,0x5EB806161EFE02,0xD1,0x0,0x0,0x0,0x0,0x0,0x0],[0x1660D76BC37B01F,0x5EB806161EFE02,0xD1,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x5F343A3F37E31DF,0x8D3B7DD448AAC3F,0xC65DEAB2679A2E1,0xCF1EACBE98B8E48,0x3C111B0EF445146,0xA1D8CB5307C0BBE,0xFFFF9EC7F01C60B,0xFFFFFFFFFFFFFFF,0xFFFFFFFF],[0x3DA2F71D92AA9AF,0x45A3D4235C2F3C,0xC65DEAB2679A1A8,0xCF1EACBE98B8E48,0x3C111B0EF445146,0xA1D8CB5307C0BBE,0xFFFF9EC7F01C60B,0xFFFFFFFFFFFFFFF,0xFFFFFFFF],[0x1660D76BC37B01D,0x5EB806161EFE02,0xD1,0x0,0x0,0x0,0x0,0x0,0x0],[0x5F343A3F37E31DF,0x8D3B7DD448AAC3F,0xC65DEAB2679A2E1,0xCF1EACBE98B8E48,0x3C111B0EF445146,0xA1D8CB5307C0BBE,0xFFFF9EC7F01C60B,0xFFFFFFFFFFFFFFF,0xFFFFFFFF]]];
+
+pub const USE_GLV:bool = true;
+pub const USE_GS_G2:bool = true;
+pub const USE_GS_GT:bool = true;
+pub const GT_STRONG:bool = false;
diff --git a/version3/rust/rom_goldilocks_32.rs b/version3/rust/rom_goldilocks_32.rs
new file mode 100644
index 0000000..7451476
--- /dev/null
+++ b/version3/rust/rom_goldilocks_32.rs
@@ -0,0 +1,38 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use goldilocks::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 29
+// Goldilocks modulus
+pub const MODULUS:[Chunk;NLEN]=[0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FDFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFF];
+pub const R2MODP:[Chunk;NLEN]=[0x0,0x10,0x0,0x0,0x0,0x0,0x0,0x0,0x3000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const MCONST:Chunk=0x1;
+
+// Goldilocks curve
+pub const CURVE_COF_I:isize = 4;
+pub const CURVE_A:isize = 1;
+pub const CURVE_B_I:isize = -39081;
+pub const CURVE_COF:[Chunk;NLEN]=[0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_B:[Chunk;NLEN]=[0x1FFF6756,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FDFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFF];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0xB5844F3,0x1BC61495,0x1163D548,0x1984E51B,0x3690216,0xDA4D76B,0xFA7113B,0x1FEF9944,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FF];
+pub const CURVE_GX:[Chunk;NLEN]=[0x15555555,0xAAAAAAA,0x15555555,0xAAAAAAA,0x15555555,0xAAAAAAA,0x15555555,0x152AAAAA,0xAAAAAAA,0x15555555,0xAAAAAAA,0x15555555,0xAAAAAAA,0x15555555,0xAAAAAAA,0x1555];
+pub const CURVE_GY:[Chunk;NLEN]=[0xA9386ED,0x1757DE6F,0x13681AF6,0x19657DA3,0x3098BBB,0x12C19D15,0x12E03595,0xE515B18,0x17B7E36D,0x1AC426E,0xDBB5E8,0x10D8560,0x159D6205,0xB8246D9,0x17A58D2B,0x15C0];
+
diff --git a/version3/rust/rom_goldilocks_64.rs b/version3/rust/rom_goldilocks_64.rs
new file mode 100644
index 0000000..81cb7ab
--- /dev/null
+++ b/version3/rust/rom_goldilocks_64.rs
@@ -0,0 +1,38 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use goldilocks::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 58
+// Goldilocks modulus
+pub const MODULUS:[Chunk;NLEN]=[0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FBFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFF];
+pub const R2MODP:[Chunk;NLEN]=[0x200000000,0x0,0x0,0x0,0x3000000,0x0,0x0,0x0];
+pub const MCONST:Chunk=0x1;
+
+// Goldilocks curve
+pub const CURVE_COF_I:isize = 4;
+pub const CURVE_A:isize = 1;
+pub const CURVE_B_I:isize = -39081;
+pub const CURVE_COF:[Chunk;NLEN]=[0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_B:[Chunk;NLEN]=[0x3FFFFFFFFFF6756,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FBFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFF];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0x378C292AB5844F3,0x3309CA37163D548,0x1B49AED63690216,0x3FDF3288FA7113B,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0xFFFFFFFFFF];
+pub const CURVE_GX:[Chunk;NLEN]=[0x155555555555555,0x155555555555555,0x155555555555555,0x2A5555555555555,0x2AAAAAAAAAAAAAA,0x2AAAAAAAAAAAAAA,0x2AAAAAAAAAAAAAA,0x2AAAAAAAAAA];
+pub const CURVE_GY:[Chunk;NLEN]=[0x2EAFBCDEA9386ED,0x32CAFB473681AF6,0x25833A2A3098BBB,0x1CA2B6312E03595,0x35884DD7B7E36D,0x21B0AC00DBB5E8,0x17048DB359D6205,0x2B817A58D2B];
+
diff --git a/version3/rust/rom_hifive_32.rs b/version3/rust/rom_hifive_32.rs
new file mode 100644
index 0000000..7b725f0
--- /dev/null
+++ b/version3/rust/rom_hifive_32.rs
@@ -0,0 +1,38 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use hifive::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 29
+// hifive Modulus
+pub const MODULUS:[Chunk;NLEN]=[0x1FFFFFFD,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFF];
+pub const R2MODP:[Chunk;NLEN]=[0x9000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const MCONST:Chunk=0x3;
+
+// hifive Curve 
+pub const CURVE_COF_I:isize = 8;
+pub const CURVE_A:isize = 1;
+pub const CURVE_B_I:isize = 11111;
+pub const CURVE_COF:[Chunk;NLEN]=[0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_B:[Chunk;NLEN]=[0x2B67,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0x1E9FA805,0x197CACB9,0x1E4EEA9E,0x17AD70F,0x1FA9850C,0x38A0A,0x0,0x0,0x0,0x0,0x0,0x4000];
+pub const CURVE_GX:[Chunk;NLEN]=[0xC,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_GY:[Chunk;NLEN]=[0x5FE8632,0x15F63428,0xD976C4,0x1AACA194,0x35B6DB5,0x8E3F7A,0x52D1B0E,0xF0A7A36,0x1C161D00,0x8170C70,0x1185AD59,0x181B];
+
diff --git a/version3/rust/rom_hifive_64.rs b/version3/rust/rom_hifive_64.rs
new file mode 100644
index 0000000..0dd3b49
--- /dev/null
+++ b/version3/rust/rom_hifive_64.rs
@@ -0,0 +1,38 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use hifive::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 60
+// hifive Modulus 
+pub const MODULUS:[Chunk;NLEN]=[0xFFFFFFFFFFFFFFD,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFF];
+pub const R2MODP:[Chunk;NLEN]=[0x9000000000000,0x0,0x0,0x0,0x0,0x0];
+pub const MCONST:Chunk=0x3;
+
+// hifive Curve
+pub const CURVE_COF_I:isize = 8;
+pub const CURVE_A:isize = 1;
+pub const CURVE_B_I:isize = 11111;
+pub const CURVE_COF:[Chunk;NLEN]=[0x8,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_B:[Chunk;NLEN]=[0x2B67,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0xB2F95973E9FA805,0xC0BD6B87F93BAA7,0x71415FA9850,0x0,0x0,0x200000000];
+pub const CURVE_GX:[Chunk;NLEN]=[0xC,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_GY:[Chunk;NLEN]=[0x2BEC68505FE8632,0x5D5650CA0365DB1,0x3811C7EF435B6DB,0x7853D1B14B46C,0x56502E18E1C161D,0xC0DC616B];
+
diff --git a/version3/rust/rom_nist256_32.rs b/version3/rust/rom_nist256_32.rs
new file mode 100644
index 0000000..56ad3fe
--- /dev/null
+++ b/version3/rust/rom_nist256_32.rs
@@ -0,0 +1,41 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+use nist256::big::NLEN;
+use arch::Chunk;
+
+
+// Base Bits= 28
+// nist256 modulus
+pub const MODULUS:[Chunk;NLEN]=[0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFF,0x0,0x0,0x1000000,0x0,0xFFFFFFF,0xF];
+pub const R2MODP:[Chunk;NLEN]=[0x50000,0x300000,0x0,0x0,0xFFFFFFA,0xFFFFFBF,0xFFFFEFF,0xFFFAFFF,0x2FFFF,0x0];
+pub const MCONST:Chunk=0x1;
+
+// nist256 curve
+pub const CURVE_COF_I:isize = 1;
+pub const CURVE_A:isize = -3;
+pub const CURVE_B_I:isize = 0;
+pub const CURVE_COF:[Chunk;NLEN]=[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_B:[Chunk;NLEN]=[0x7D2604B,0xCE3C3E2,0x3B0F63B,0x6B0CC5,0x6BC651D,0x5576988,0x7B3EBBD,0xAA3A93E,0xAC635D8,0x5];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0xC632551,0xB9CAC2F,0x79E84F3,0xFAADA71,0xFFFBCE6,0xFFFFFFF,0xFFFFFF,0x0,0xFFFFFFF,0xF];
+pub const CURVE_GX:[Chunk;NLEN]=[0x898C296,0xA13945D,0xB33A0F4,0x7D812DE,0xF27703,0xE563A44,0x7F8BCE6,0xE12C424,0xB17D1F2,0x6];
+pub const CURVE_GY:[Chunk;NLEN]=[0x7BF51F5,0xB640683,0x15ECECB,0x33576B3,0xE162BCE,0x4A7C0F9,0xB8EE7EB,0xFE1A7F9,0xFE342E2,0x4];
+
diff --git a/version3/rust/rom_nist256_64.rs b/version3/rust/rom_nist256_64.rs
new file mode 100644
index 0000000..849f3af
--- /dev/null
+++ b/version3/rust/rom_nist256_64.rs
@@ -0,0 +1,40 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+use nist256::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 56
+// nist256 modulus
+pub const MODULUS:[Chunk;NLEN]=[0xFFFFFFFFFFFFFF,0xFFFFFFFFFF,0x0,0x1000000,0xFFFFFFFF];
+pub const R2MODP:[Chunk;NLEN]=[0x3000000050000,0x0,0xFFFFFBFFFFFFFA,0xFFFAFFFFFFFEFF,0x2FFFF];
+pub const MCONST:Chunk=0x1;
+
+// nist256 curve
+pub const CURVE_COF_I:isize = 1;
+pub const CURVE_A:isize = -3;
+pub const CURVE_B_I:isize = 0;
+pub const CURVE_COF:[Chunk;NLEN]=[0x1,0x0,0x0,0x0,0x0];
+pub const CURVE_B:[Chunk;NLEN]=[0xCE3C3E27D2604B,0x6B0CC53B0F63B,0x55769886BC651D,0xAA3A93E7B3EBBD,0x5AC635D8];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0xB9CAC2FC632551,0xFAADA7179E84F3,0xFFFFFFFFFFBCE6,0xFFFFFF,0xFFFFFFFF];
+pub const CURVE_GX:[Chunk;NLEN]=[0xA13945D898C296,0x7D812DEB33A0F4,0xE563A440F27703,0xE12C4247F8BCE6,0x6B17D1F2];
+pub const CURVE_GY:[Chunk;NLEN]=[0xB6406837BF51F5,0x33576B315ECECB,0x4A7C0F9E162BCE,0xFE1A7F9B8EE7EB,0x4FE342E2];
+
diff --git a/version3/rust/rom_nist384_32.rs b/version3/rust/rom_nist384_32.rs
new file mode 100644
index 0000000..dd79a08
--- /dev/null
+++ b/version3/rust/rom_nist384_32.rs
@@ -0,0 +1,38 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use nist384::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 29
+// nist384 Modulus 
+pub const MODULUS:[Chunk;NLEN]=[0x1FFFFFFF,0x7,0x0,0x1FFFFE00,0x1FFFEFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F];
+pub const R2MODP:[Chunk;NLEN]=[0x0,0x8000,0x1FF80000,0x1FFFFF,0x2000000,0x0,0x0,0x1FFFFFFC,0xF,0x100,0x400,0x0,0x0,0x0];
+pub const MCONST:Chunk=0x1;
+
+// nist384 Curve 
+pub const CURVE_COF_I:isize = 1;
+pub const CURVE_A:isize = -3;
+pub const CURVE_B_I:isize = 0;
+pub const CURVE_COF:[Chunk;NLEN]=[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_B:[Chunk;NLEN]=[0x13EC2AEF,0x142E476E,0xBB4674A,0xC731B14,0x1875AC65,0x447A809,0x4480C50,0xDDFD028,0x19181D9C,0x1F1FC168,0x623815A,0x47DCFC9,0x1312FA7E,0x59];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0xCC52973,0x760CB56,0xC29DEBB,0x141B6491,0x12DDF581,0x6C0FA1B,0x1FFF1D8D,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F];
+pub const CURVE_GX:[Chunk;NLEN]=[0x12760AB7,0x12A2F1C3,0x154A5B0E,0x5E4BB7E,0x2A38550,0xF0412A,0xE6167DD,0xC5174F3,0x146E1D3B,0x1799056B,0x3AC71C7,0x1D160A6F,0x87CA22B,0x55];
+pub const CURVE_GY:[Chunk;NLEN]=[0x10EA0E5F,0x1218EBE4,0x1FA0675E,0x1639C3A,0xB8C00A6,0x1889DAF8,0x11F3A768,0x17A51342,0x9F8F41D,0x1C9496E1,0x1767A62F,0xC4C58DE,0x17DE4A9,0x1B];
+
diff --git a/version3/rust/rom_nist384_64.rs b/version3/rust/rom_nist384_64.rs
new file mode 100644
index 0000000..b092fb5
--- /dev/null
+++ b/version3/rust/rom_nist384_64.rs
@@ -0,0 +1,38 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use nist384::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 56
+// nist384 Modulus
+pub const MODULUS:[Chunk;NLEN]=[0xFFFFFFFF,0xFFFF0000000000,0xFFFFFFFFFEFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFF];
+pub const R2MODP:[Chunk;NLEN]=[0xFE000000010000,0xFFFFFF,0x2,0xFFFFFFFE00,0x1000000020000,0x0,0x0];
+pub const MCONST:Chunk=0x100000001;
+
+// nist384 Curve 
+pub const CURVE_COF_I:isize = 1;
+pub const CURVE_A:isize = -3;
+pub const CURVE_B_I:isize = 0;
+pub const CURVE_COF:[Chunk;NLEN]=[0x1,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_B:[Chunk;NLEN]=[0x85C8EDD3EC2AEF,0x398D8A2ED19D2A,0x8F5013875AC656,0xFE814112031408,0xF82D19181D9C6E,0xE7E4988E056BE3,0xB3312FA7E23E];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0xEC196ACCC52973,0xDB248B0A77AEC,0x81F4372DDF581A,0xFFFFFFFFC7634D,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFF];
+pub const CURVE_GX:[Chunk;NLEN]=[0x545E3872760AB7,0xF25DBF55296C3A,0xE082542A385502,0x8BA79B9859F741,0x20AD746E1D3B62,0x5378EB1C71EF3,0xAA87CA22BE8B];
+pub const CURVE_GY:[Chunk;NLEN]=[0x431D7C90EA0E5F,0xB1CE1D7E819D7A,0x13B5F0B8C00A60,0x289A147CE9DA31,0x92DC29F8F41DBD,0x2C6F5D9E98BF92,0x3617DE4A9626];
+
diff --git a/version3/rust/rom_nist521_32.rs b/version3/rust/rom_nist521_32.rs
new file mode 100644
index 0000000..a736b86
--- /dev/null
+++ b/version3/rust/rom_nist521_32.rs
@@ -0,0 +1,39 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use nist521::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 28
+// nist521 Modulus 
+pub const MODULUS:[Chunk;NLEN]=[0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0x1FFFF];
+pub const R2MODP:[Chunk;NLEN]=[0x400000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const MCONST:Chunk=0x1;
+
+// nist521 Curve 
+pub const CURVE_COF_I:isize = 1;
+pub const CURVE_A:isize = -3;
+pub const CURVE_B_I:isize = 0;
+pub const CURVE_COF:[Chunk;NLEN]=[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_B:[Chunk;NLEN]=[0xB503F00,0x451FD46,0xC34F1EF,0xDF883D2,0xF073573,0xBD3BB1B,0xB1652C0,0xEC7E937,0x6193951,0xF109E15,0x489918E,0x15F3B8B,0x25B99B3,0xEEA2DA7,0xB68540,0x929A21A,0xE1C9A1F,0x3EB9618,0x5195];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0x1386409,0x6FB71E9,0xC47AEBB,0xC9B8899,0x5D03BB5,0x48F709A,0xB7FCC01,0xBF2F966,0x1868783,0xFFFFFA5,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0x1FFFF];
+pub const CURVE_GX:[Chunk;NLEN]=[0x2E5BD66,0x7E7E31C,0xA429BF9,0xB3C1856,0x8DE3348,0x27A2FFA,0x8FE1DC1,0xEFE7592,0x14B5E77,0x4D3DBAA,0x8AF606B,0xB521F82,0x139053F,0x429C648,0x62395B4,0x9E3ECB6,0x404E9CD,0x8E06B70,0xC685];
+pub const CURVE_GY:[Chunk;NLEN]=[0xFD16650,0xBE94769,0x2C24088,0x7086A27,0x761353C,0x13FAD0,0xC550B9,0x5EF4264,0x7EE7299,0x3E662C9,0xFBD1727,0x446817A,0x449579B,0xD998F54,0x42C7D1B,0x5C8A5FB,0xA3BC004,0x296A789,0x11839];
+
+
diff --git a/version3/rust/rom_nist521_64.rs b/version3/rust/rom_nist521_64.rs
new file mode 100644
index 0000000..a4460a4
--- /dev/null
+++ b/version3/rust/rom_nist521_64.rs
@@ -0,0 +1,38 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use nist521::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 60
+// nist521 Modulus 
+pub const MODULUS:[Chunk;NLEN]=[0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0x1FFFFFFFFFF];
+pub const R2MODP:[Chunk;NLEN]=[0x4000000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const MCONST:Chunk=0x1;
+
+// nist521 Curve 
+pub const CURVE_COF_I:isize = 1;
+pub const CURVE_A:isize = -3;
+pub const CURVE_B_I:isize = 0;
+pub const CURVE_COF:[Chunk;NLEN]=[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_B:[Chunk;NLEN]=[0xF451FD46B503F00,0x73DF883D2C34F1E,0x2C0BD3BB1BF0735,0x3951EC7E937B165,0x9918EF109E15619,0x5B99B315F3B8B48,0xB68540EEA2DA72,0x8E1C9A1F929A21A,0x51953EB961];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0xB6FB71E91386409,0xB5C9B8899C47AEB,0xC0148F709A5D03B,0x8783BF2F966B7FC,0xFFFFFFFFFFA5186,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0x1FFFFFFFFFF];
+pub const CURVE_GX:[Chunk;NLEN]=[0x97E7E31C2E5BD66,0x48B3C1856A429BF,0xDC127A2FFA8DE33,0x5E77EFE75928FE1,0xF606B4D3DBAA14B,0x39053FB521F828A,0x62395B4429C6481,0x404E9CD9E3ECB6,0xC6858E06B7];
+pub const CURVE_GY:[Chunk;NLEN]=[0x8BE94769FD16650,0x3C7086A272C2408,0xB9013FAD076135,0x72995EF42640C55,0xD17273E662C97EE,0x49579B446817AFB,0x42C7D1BD998F544,0x9A3BC0045C8A5FB,0x11839296A78];
+
diff --git a/version3/rust/rom_nums256e_32.rs b/version3/rust/rom_nums256e_32.rs
new file mode 100644
index 0000000..c2a17f0
--- /dev/null
+++ b/version3/rust/rom_nums256e_32.rs
@@ -0,0 +1,40 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use nums256e::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 29
+// nums256 Modulus 
+pub const MODULUS:[Chunk;NLEN]=[0x1FFFFF43,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFFFFFF];
+pub const R2MODP:[Chunk;NLEN]=[0x22E2400,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const MCONST:Chunk=0xBD;
+
+// nums256e Curve
+pub const CURVE_COF_I:isize = 4;
+pub const CURVE_A:isize = 1;
+pub const CURVE_B_I:isize = -15342;
+pub const CURVE_COF:[Chunk;NLEN]=[0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_B:[Chunk;NLEN]=[0x1FFFC355,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFFFFFF];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0xEDD4AF5,0x123D8C87,0x1650E6C6,0xAB54A5E,0x419,0x0,0x0,0x0,0x400000];
+pub const CURVE_GX:[Chunk;NLEN]=[0xEED13DA,0x6F60481,0x20D61A8,0x13141DC6,0x9BD60C3,0x1EAFB490,0xDF73478,0x1F6D5D44,0x8A7514];
+pub const CURVE_GY:[Chunk;NLEN]=[0x198A89E6,0x1D30B73B,0x15BB4CB,0x1EC3B021,0x18010715,0x12ECD325,0x171F3A59,0x13FB3B24,0x44D53E];
+
+
+
diff --git a/version3/rust/rom_nums256e_64.rs b/version3/rust/rom_nums256e_64.rs
new file mode 100644
index 0000000..0607c45
--- /dev/null
+++ b/version3/rust/rom_nums256e_64.rs
@@ -0,0 +1,42 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use nums256e::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 56
+// nums256 Modulus 
+pub const MODULUS:[Chunk;NLEN]=[0xFFFFFFFFFFFF43,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFF];
+pub const R2MODP:[Chunk;NLEN]=[0x89000000000000,0x8B,0x0,0x0,0x0];
+pub const MCONST:Chunk=0xBD;
+
+// nums256e Curve
+pub const CURVE_COF_I:isize = 4;
+pub const CURVE_A:isize = 1;
+pub const CURVE_B_I:isize = -15342;
+pub const CURVE_COF:[Chunk;NLEN]=[0x4,0x0,0x0,0x0,0x0];
+pub const CURVE_B:[Chunk;NLEN]=[0xFFFFFFFFFFC355,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFF];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0x47B190EEDD4AF5,0x5AA52F59439B1A,0x4195,0x0,0x40000000];
+pub const CURVE_GX:[Chunk;NLEN]=[0xDEC0902EED13DA,0x8A0EE3083586A0,0x5F69209BD60C39,0x6AEA237DCD1E3D,0x8A7514FB];
+pub const CURVE_GY:[Chunk;NLEN]=[0xA616E7798A89E6,0x61D810856ED32F,0xD9A64B8010715F,0xD9D925C7CE9665,0x44D53E9F];
+
+
+
+
+
diff --git a/version3/rust/rom_nums256w_32.rs b/version3/rust/rom_nums256w_32.rs
new file mode 100644
index 0000000..0bd73c3
--- /dev/null
+++ b/version3/rust/rom_nums256w_32.rs
@@ -0,0 +1,38 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use nums256w::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 28
+// nums256 modulus
+pub const MODULUS:[Chunk;NLEN]=[0xFFFFF43,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xF];
+pub const R2MODP:[Chunk;NLEN]=[0x0,0x8900000,0x8B,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const MCONST:Chunk=0xBD;
+
+// nums256w curve
+pub const CURVE_COF_I:isize = 1;
+pub const CURVE_A:isize = -3;
+pub const CURVE_B_I:isize = 152961;
+pub const CURVE_COF:[Chunk;NLEN]=[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_B:[Chunk;NLEN]=[0x25581,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0x751A825,0xAB20294,0x65C6020,0x8275EA2,0xFFFE43C,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xF];
+pub const CURVE_GX:[Chunk;NLEN]=[0x21AACB1,0x52EE1EB,0x4C73ABC,0x9B0903D,0xB098357,0xA04F42C,0x1297A95,0x5AAADB6,0xC9ED6B6,0xB];
+pub const CURVE_GY:[Chunk;NLEN]=[0x184DE9F,0xB5B9CB2,0x10FBB80,0xC3D1153,0x35C955,0xF77E04E,0x673448B,0x3399B6A,0x8FC0F1,0xD];
+
diff --git a/version3/rust/rom_nums256w_64.rs b/version3/rust/rom_nums256w_64.rs
new file mode 100644
index 0000000..5835480
--- /dev/null
+++ b/version3/rust/rom_nums256w_64.rs
@@ -0,0 +1,40 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use nums256w::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 56
+// nums256 Modulus 
+pub const MODULUS:[Chunk;NLEN]=[0xFFFFFFFFFFFF43,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFF];
+pub const R2MODP:[Chunk;NLEN]=[0x89000000000000,0x8B,0x0,0x0,0x0];
+pub const MCONST:Chunk=0xBD;
+
+// nums256w Curve
+pub const CURVE_COF_I:isize = 1;
+pub const CURVE_A:isize = -3;
+pub const CURVE_B_I:isize = 152961;
+pub const CURVE_COF:[Chunk;NLEN]=[0x1,0x0,0x0,0x0,0x0];
+pub const CURVE_B:[Chunk;NLEN]=[0x25581,0x0,0x0,0x0,0x0];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0xAB20294751A825,0x8275EA265C6020,0xFFFFFFFFFFE43C,0xFFFFFFFFFFFFFF,0xFFFFFFFF];
+pub const CURVE_GX:[Chunk;NLEN]=[0x52EE1EB21AACB1,0x9B0903D4C73ABC,0xA04F42CB098357,0x5AAADB61297A95,0xBC9ED6B6];
+pub const CURVE_GY:[Chunk;NLEN]=[0xB5B9CB2184DE9F,0xC3D115310FBB80,0xF77E04E035C955,0x3399B6A673448B,0xD08FC0F1];
+
+
+
diff --git a/version3/rust/rom_nums384e_32.rs b/version3/rust/rom_nums384e_32.rs
new file mode 100644
index 0000000..678c73d
--- /dev/null
+++ b/version3/rust/rom_nums384e_32.rs
@@ -0,0 +1,40 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use nums384e::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 29
+// nums384 Modulus
+pub const MODULUS:[Chunk;NLEN]=[0x1FFFFEC3,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F];
+pub const R2MODP:[Chunk;NLEN]=[0x0,0x4448000,0x6,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const MCONST:Chunk=0x13D;
+
+// nums384e Curve
+pub const CURVE_COF_I:isize = 4;
+pub const CURVE_A:isize = 1;
+pub const CURVE_B_I:isize = -11556;
+pub const CURVE_COF:[Chunk;NLEN]=[0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_B:[Chunk;NLEN]=[0x1FFFD19F,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0x6A3897D,0x5CEE627,0xD721E48,0x8AAB556,0x1E1CF61E,0xD0E5A35,0x1FFF891C,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1F];
+pub const CURVE_GX:[Chunk;NLEN]=[0xC206BDE,0x6AA0723,0x116504D4,0x52562CA,0x163406FF,0x1FD47998,0x10015D8F,0x8DCB7C9,0x15B30BF4,0x14D72AED,0x102DA884,0xB524CD9,0x1B111FB4,0x30];
+pub const CURVE_GY:[Chunk;NLEN]=[0x10729392,0xC681F0F,0x1B123727,0x561F28D,0x1964B007,0xC7BFB22,0x1D5A0C3E,0xE9E284B,0x1716AD82,0x11D886E,0x1CE2C69,0x134DDD61,0x983E67B,0x41];
+
+
+
diff --git a/version3/rust/rom_nums384e_64.rs b/version3/rust/rom_nums384e_64.rs
new file mode 100644
index 0000000..c020641
--- /dev/null
+++ b/version3/rust/rom_nums384e_64.rs
@@ -0,0 +1,39 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use nums384e::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 56
+// nums384 Modulus 
+pub const MODULUS:[Chunk;NLEN]=[0xFFFFFFFFFFFEC3,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFF];
+pub const R2MODP:[Chunk;NLEN]=[0x188890000,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const MCONST:Chunk=0x13D;
+
+// nums384e Curve
+pub const CURVE_COF_I:isize = 4;
+pub const CURVE_A:isize = 1;
+pub const CURVE_B_I:isize = -11556;
+pub const CURVE_COF:[Chunk;NLEN]=[0x4,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_B:[Chunk;NLEN]=[0xFFFFFFFFFFD19F,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFF];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0xB9DCC4E6A3897D,0x555AAB35C87920,0x1CB46BE1CF61E4,0xFFFFFFFFE2471A,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0x3FFFFFFFFFFF];
+pub const CURVE_GX:[Chunk;NLEN]=[0xD540E46C206BDE,0x92B16545941350,0xA8F33163406FF2,0xE5BE4C005763FF,0xE55DB5B30BF446,0x266CC0B6A2129A,0x61B111FB45A9];
+pub const CURVE_GY:[Chunk;NLEN]=[0x8D03E1F0729392,0xB0F946EC48DC9D,0xF7F645964B0072,0xF1425F56830F98,0xB10DD716AD8274,0xEEB08738B1A423,0x82983E67B9A6];
+
+
diff --git a/version3/rust/rom_nums384w_32.rs b/version3/rust/rom_nums384w_32.rs
new file mode 100644
index 0000000..0b47490
--- /dev/null
+++ b/version3/rust/rom_nums384w_32.rs
@@ -0,0 +1,39 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use nums384w::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 29
+// nums384 Modulus 
+pub const MODULUS:[Chunk;NLEN]=[0x1FFFFEC3,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F];
+pub const R2MODP:[Chunk;NLEN]=[0x0,0x4448000,0x6,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const MCONST:Chunk=0x13D;
+
+// nums384w Curve
+pub const CURVE_COF_I:isize = 1;
+pub const CURVE_A:isize = -3;
+pub const CURVE_B_I:isize = -34568;
+pub const CURVE_COF:[Chunk;NLEN]=[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_B:[Chunk;NLEN]=[0x1FFF77BB,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0x1B0E61B9,0x26C0FB3,0xDF89E98,0x153A7A98,0x16881BED,0x178F75AE,0x1FFF587A,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F];
+pub const CURVE_GX:[Chunk;NLEN]=[0x98152A,0x1CE5D021,0x18711EFA,0x1DDA201E,0xC742522,0x148D9536,0x7D3CEF4,0x19BF703F,0x60225C1,0x12082F8D,0x12203288,0x2DE3038,0x17956F0B,0x3A];
+pub const CURVE_GY:[Chunk;NLEN]=[0x6180716,0x3A5C763,0x1D2B4997,0xD69B77F,0x837EBCD,0x1BE890D,0xE72E482,0xEFF0FEE,0x1EB00469,0x2C267B,0x15F8CF4C,0x3371C71,0xDEE368E,0x56];
+
+
diff --git a/version3/rust/rom_nums384w_64.rs b/version3/rust/rom_nums384w_64.rs
new file mode 100644
index 0000000..74ae0d3
--- /dev/null
+++ b/version3/rust/rom_nums384w_64.rs
@@ -0,0 +1,38 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use nums384w::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 58
+// nums384 Modulus 
+pub const MODULUS:[Chunk;NLEN]=[0x3FFFFFFFFFFFEC3,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0xFFFFFFFFF];
+pub const R2MODP:[Chunk;NLEN]=[0x88900000000000,0x6,0x0,0x0,0x0,0x0,0x0];
+pub const MCONST:Chunk=0x13D;
+
+// nums384w Curve
+pub const CURVE_COF_I:isize = 1;
+pub const CURVE_A:isize = -3;
+pub const CURVE_B_I:isize = -34568;
+pub const CURVE_COF:[Chunk;NLEN]=[0x1,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_B:[Chunk;NLEN]=[0x3FFFFFFFFFF77BB,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0xFFFFFFFFF];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0x4D81F67B0E61B9,0x2A74F530DF89E98,0x2F1EEB5D6881BED,0x3FFFFFFFFFF587A,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0xFFFFFFFFF];
+pub const CURVE_GX:[Chunk;NLEN]=[0x39CBA042098152A,0x3BB4403D8711EFA,0x291B2A6CC742522,0x337EE07E7D3CEF4,0x24105F1A60225C1,0x5BC60712203288,0x757956F0B];
+pub const CURVE_GY:[Chunk;NLEN]=[0x74B8EC66180716,0x1AD36EFFD2B4997,0x37D121A837EBCD,0x1DFE1FDCE72E482,0x584CF7EB00469,0x66E38E35F8CF4C,0xACDEE368E];
+
diff --git a/version3/rust/rom_nums512e_32.rs b/version3/rust/rom_nums512e_32.rs
new file mode 100644
index 0000000..706ed22
--- /dev/null
+++ b/version3/rust/rom_nums512e_32.rs
@@ -0,0 +1,37 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use nums512e::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 29
+// nums512 Modulus 
+pub const MODULUS:[Chunk;NLEN]=[0x1FFFFDC7,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF];
+pub const R2MODP:[Chunk;NLEN]=[0xB100000,0x278,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const MCONST:Chunk=0x239;
+
+// nums512e Curve
+pub const CURVE_COF_I:isize = 4;
+pub const CURVE_A:isize = 1;
+pub const CURVE_B_I:isize = -78296;
+pub const CURVE_COF:[Chunk;NLEN]=[0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_B:[Chunk;NLEN]=[0x1FFECBEF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0x1BEED46D,0x1A3467A8,0x1BFB3FD9,0xC0AF0DB,0x86F52A4,0xC64B85B,0x6EA78FF,0xDA5F9F2,0x1FB4F063,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFF];
+pub const CURVE_GX:[Chunk;NLEN]=[0x19EC57FE,0xDCD594C,0x113C0571,0xA4A84F9,0x104AD0FE,0x4C92B44,0xC3DE2F7,0x9DDC8CE,0x74621C1,0x1139DC0A,0x9E85FAF,0x1B894704,0x1D1E79F4,0x9E29997,0x32DE223,0x16D38F43,0x116D128D,0x6FC71];
+pub const CURVE_GY:[Chunk;NLEN]=[0x1E2F5E1,0x136EF606,0x1C7407CC,0xDA71537,0xC1FD026,0x3431576,0x15898068,0x1E5D32C6,0x120CA53,0xC84F41A,0xA4ADAE5,0x104B3A45,0x76F726D,0x1512B772,0x3D5DEA0,0x194E3316,0x1FF39D49,0x3684D];
diff --git a/version3/rust/rom_nums512e_64.rs b/version3/rust/rom_nums512e_64.rs
new file mode 100644
index 0000000..cbac801
--- /dev/null
+++ b/version3/rust/rom_nums512e_64.rs
@@ -0,0 +1,38 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use nums512e::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 60
+// nums512 Modulus
+pub const MODULUS:[Chunk;NLEN]=[0xFFFFFFFFFFFFDC7,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFF];
+pub const R2MODP:[Chunk;NLEN]=[0x100000000000000,0x4F0B,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const MCONST:Chunk=0x239;
+
+// nums512e Curve
+pub const CURVE_COF_I:isize = 4;
+pub const CURVE_A:isize = 1;
+pub const CURVE_B_I:isize = -78296;
+pub const CURVE_COF:[Chunk;NLEN]=[0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_B:[Chunk;NLEN]=[0xFFFFFFFFFFECBEF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFF];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0x7468CF51BEED46D,0x4605786DEFECFF6,0xFD8C970B686F52A,0x636D2FCF91BA9E3,0xFFFFFFFFFFFB4F0,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0x3FFFFFFF];
+pub const CURVE_GX:[Chunk;NLEN]=[0x5B9AB2999EC57FE,0xE525427CC4F015C,0xDC992568904AD0F,0xC14EEE46730F78B,0xEBE273B81474621,0x9F4DC4A38227A17,0x888D3C5332FD1E7,0x128DB69C7A18CB7,0xDF8E316D];
+pub const CURVE_GY:[Chunk;NLEN]=[0x26DDEC0C1E2F5E1,0x66D38A9BF1D01F3,0xA06862AECC1FD02,0x53F2E9963562601,0xB95909E834120CA,0x26D8259D22A92B6,0x7A82A256EE476F7,0x9D49CA7198B0F57,0x6D09BFF3];
+
diff --git a/version3/rust/rom_nums512w_32.rs b/version3/rust/rom_nums512w_32.rs
new file mode 100644
index 0000000..4a81cd5
--- /dev/null
+++ b/version3/rust/rom_nums512w_32.rs
@@ -0,0 +1,39 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use nums512w::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 29
+// nums512 Modulus 
+pub const MODULUS:[Chunk;NLEN]=[0x1FFFFDC7,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF];
+pub const R2MODP:[Chunk;NLEN]=[0xB100000,0x278,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const MCONST:Chunk=0x239;
+
+// nums512w Curve
+pub const CURVE_COF_I:isize = 1;
+pub const CURVE_A:isize = -3;
+pub const CURVE_B_I:isize = 121243;
+pub const CURVE_COF:[Chunk;NLEN]=[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_B:[Chunk;NLEN]=[0x1D99B,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0x433555D,0x10A9F9C8,0x1F3490F3,0xD166CC0,0xBDC63B5,0xC76CBE8,0xC6D3F09,0x1F729CF0,0x1F5B3CA4,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF];
+pub const CURVE_GX:[Chunk;NLEN]=[0xCABAE57,0x4143CAC,0x1BD778B7,0x1AC026FA,0x15831D5,0x14312AB,0x167A4DE5,0xA20ED66,0x195021A1,0x129836CF,0x1141B830,0xA03ED0A,0xCAD83BB,0x1E9DA94C,0xDC00A80,0x1527B45,0x1447141D,0x1D601];
+pub const CURVE_GY:[Chunk;NLEN]=[0x183527A6,0x1D043B01,0x1F43FA48,0x16B83C99,0x5602CF2,0x1420592D,0x17A70486,0x1B5161DD,0x14A28415,0x3DE8A78,0x3D2C983,0x17797719,0x197DBDEA,0x15D88025,0x1BBB718F,0xAD679C1,0x14CA29AD,0x4A1D2];
+
+
diff --git a/version3/rust/rom_nums512w_64.rs b/version3/rust/rom_nums512w_64.rs
new file mode 100644
index 0000000..ec2dac2
--- /dev/null
+++ b/version3/rust/rom_nums512w_64.rs
@@ -0,0 +1,38 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use nums512w::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 60
+// nums512 Modulus 
+pub const MODULUS:[Chunk;NLEN]=[0xFFFFFFFFFFFFDC7,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFF];
+pub const R2MODP:[Chunk;NLEN]=[0x100000000000000,0x4F0B,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const MCONST:Chunk=0x239;
+
+// nums512w Curve
+pub const CURVE_COF_I:isize = 1;
+pub const CURVE_A:isize = -3;
+pub const CURVE_B_I:isize = 121243;
+pub const CURVE_COF:[Chunk;NLEN]=[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_B:[Chunk;NLEN]=[0x1D99B,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0xE153F390433555D,0x568B36607CD243C,0x258ED97D0BDC63B,0xA4FB94E7831B4FC,0xFFFFFFFFFFF5B3C,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFF];
+pub const CURVE_GX:[Chunk;NLEN]=[0xC8287958CABAE57,0x5D60137D6F5DE2D,0x94286255615831D,0xA151076B359E937,0xC25306D9F95021,0x3BB501F6854506E,0x2A03D3B5298CAD8,0x141D0A93DA2B700,0x3AC03447];
+pub const CURVE_GY:[Chunk;NLEN]=[0x3A08760383527A6,0x2B5C1E4CFD0FE92,0x1A840B25A5602CF,0x15DA8B0EEDE9C12,0x60C7BD14F14A284,0xDEABBCBB8C8F4B2,0xC63EBB1004B97DB,0x29AD56B3CE0EEED,0x943A54CA];
+
diff --git a/version3/rust/rom_secp256k1_32.rs b/version3/rust/rom_secp256k1_32.rs
new file mode 100644
index 0000000..6dd7a1d
--- /dev/null
+++ b/version3/rust/rom_secp256k1_32.rs
@@ -0,0 +1,40 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+use secp256k1::big::NLEN;
+use arch::Chunk;
+
+
+// Base Bits= 28
+// secp256k1 modulus
+pub const MODULUS:[Chunk;NLEN]=[0xFFFFC2F,0xFFFFFEF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xF];
+pub const R2MODP:[Chunk;NLEN]=[0x0,0xA100000,0x2000E90,0x7A,0x1,0x0,0x0,0x0,0x0,0x0];
+pub const MCONST:Chunk=0x2253531;
+
+// secp256k1 curve
+pub const CURVE_A:isize = 0;
+pub const CURVE_COF_I:isize = 1;
+pub const CURVE_COF:[Chunk;NLEN]=[0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_B_I:isize = 7;
+pub const CURVE_B:[Chunk;NLEN]=[0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0x364141,0xD25E8CD,0x8A03BBF,0xDCE6AF4,0xFFEBAAE,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xF];
+pub const CURVE_GX:[Chunk;NLEN]=[0x6F81798,0xF2815B1,0xE28D959,0xFCDB2DC,0xB07029B,0x95CE870,0xC55A062,0xF9DCBBA,0x9BE667E,0x7];
+pub const CURVE_GY:[Chunk;NLEN]=[0xB10D4B8,0x47D08FF,0x554199C,0xB448A68,0x8A8FD17,0xFC0E110,0x55DA4FB,0x26A3C46,0x83ADA77,0x4];
\ No newline at end of file
diff --git a/version3/rust/rom_secp256k1_64.rs b/version3/rust/rom_secp256k1_64.rs
new file mode 100644
index 0000000..6dca53d
--- /dev/null
+++ b/version3/rust/rom_secp256k1_64.rs
@@ -0,0 +1,39 @@
+/*
+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.
+*/
+
+/* Fixed Data in ROM - Field and Curve parameters */
+
+use secp256k1::big::NLEN;
+use arch::Chunk;
+
+// Base Bits= 56
+// secp256k1 modulus
+pub const MODULUS:[Chunk;NLEN]=[0xFFFFFEFFFFFC2F,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFF];
+pub const R2MODP:[Chunk;NLEN]=[0xA1000000000000,0x7A2000E90,0x1,0x0,0x0];
+pub const MCONST:Chunk=0x38091DD2253531;
+
+// secp256k1 curve
+pub const CURVE_A:isize = 0;
+pub const CURVE_COF_I:isize = 1;
+pub const CURVE_COF:[Chunk;NLEN]=[0x1,0x0,0x0,0x0,0x0];
+pub const CURVE_B_I:isize = 7;
+pub const CURVE_B:[Chunk;NLEN]=[0x7,0x0,0x0,0x0,0x0];
+pub const CURVE_ORDER:[Chunk;NLEN]=[0xD25E8CD0364141,0xDCE6AF48A03BBF,0xFFFFFFFFFEBAAE,0xFFFFFFFFFFFFFF,0xFFFFFFFF];
+pub const CURVE_GX:[Chunk;NLEN]=[0xF2815B16F81798,0xFCDB2DCE28D959,0x95CE870B07029B,0xF9DCBBAC55A062,0x79BE667E];
+pub const CURVE_GY:[Chunk;NLEN]=[0x47D08FFB10D4B8,0xB448A68554199C,0xFC0E1108A8FD17,0x26A3C4655DA4FB,0x483ADA77];
diff --git a/version3/rust/rsa.rs b/version3/rust/rsa.rs
new file mode 100644
index 0000000..fbe4457
--- /dev/null
+++ b/version3/rust/rsa.rs
@@ -0,0 +1,362 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+use xxx::big;
+use xxx::ff;
+use xxx::ff::FF;
+
+use rand::RAND;
+use hash256::HASH256;
+use hash384::HASH384;
+use hash512::HASH512;
+
+pub const RFS:usize =(big::MODBYTES as usize)*ff::FFLEN;
+pub const SHA256:usize=32;
+pub const SHA384:usize=48;
+pub const SHA512:usize=64;
+
+pub const HASH_TYPE:usize=SHA256;
+
+pub struct RsaPrivateKey {
+	p:FF,
+	q:FF,
+	dp:FF,
+	dq:FF,
+	c:FF
+}
+
+pub struct RsaPublicKey {
+	e: isize,
+	n: FF
+}
+
+pub fn new_private_key(n: usize) -> RsaPrivateKey {
+	RsaPrivateKey {p:FF::new_int(n),q:FF::new_int(n),dp:FF::new_int(n),dq:FF::new_int(n),c:FF::new_int(n)}
+}
+
+pub fn new_public_key(m: usize) -> RsaPublicKey {
+	RsaPublicKey {e:0,n:FF::new_int(m)}
+}
+
+fn hashit(sha: usize,a: Option<&[u8]>,n: isize,w: &mut [u8]) {
+	if sha==SHA256 {
+		let mut h=HASH256::new();
+		if let Some(x)=a {
+			h.process_array(x);
+		}
+		if n>=0 {h.process_num(n as i32)}
+        let hs=h.hash();	
+        for i in 0..sha {w[i]=hs[i]}
+	}
+	if sha==SHA384 {
+		let mut h=HASH384::new();
+		if let Some(x)=a {
+			h.process_array(x);
+		}
+		if n>=0 {h.process_num(n as i32)}
+        let hs=h.hash();	
+        for i in 0..sha {w[i]=hs[i]}
+	}
+	if sha==SHA512 {
+		let mut h=HASH512::new();
+		if let Some(x)=a {
+			h.process_array(x);
+		}
+		if n>=0 {h.process_num(n as i32)}
+        let hs=h.hash();	
+        for i in 0..sha {w[i]=hs[i]}
+	}
+}
+
+pub fn key_pair(rng: &mut RAND,e: isize,prv: &mut RsaPrivateKey,pbc: &mut RsaPublicKey) { /* IEEE1363 A16.11/A16.12 more or less */
+	let n=pbc.n.getlen()/2;
+	let mut t=FF::new_int(n);
+	let mut p1=FF::new_int(n);
+	let mut q1=FF::new_int(n);
+
+	loop {
+		prv.p.random(rng);
+		while prv.p.lastbits(2)!=3 {prv.p.inc(1)}		
+		while !FF::prime(&prv.p,rng) {			
+			prv.p.inc(4);		
+		}
+		
+		p1.copy(&prv.p);
+		p1.dec(1);
+
+		if p1.cfactor(e) {continue}
+		break;
+	}
+
+	loop {
+		prv.q.random(rng);
+		while prv.q.lastbits(2)!=3 {prv.q.inc(1)}
+		while !FF::prime(&prv.q,rng) {
+			prv.q.inc(4);
+		}
+			
+		q1.copy(&prv.q);
+		q1.dec(1);
+
+		if q1.cfactor(e) {continue}
+
+		break;
+	}
+	
+	pbc.n=FF::mul(&prv.p,&prv.q);
+	pbc.e=e;
+
+	t.copy(&p1);
+	t.shr();
+	prv.dp.set(e);
+	prv.dp.invmodp(&t);
+	if prv.dp.parity()==0 {prv.dp.add(&t)}
+	prv.dp.norm();
+
+	t.copy(&q1);
+	t.shr();
+	prv.dq.set(e);
+	prv.dq.invmodp(&t);
+	if prv.dq.parity()==0 {prv.dq.add(&t)}
+	prv.dq.norm();
+
+	prv.c.copy(&prv.p);
+	prv.c.invmodp(&prv.q);
+}
+
+/* Mask Generation Function */
+
+pub fn mgf1(sha: usize,z: &[u8],olen: usize,k: &mut [u8]) {
+	let hlen=sha;
+
+	let mut j=0;
+	for i in 0..k.len() {k[i]=0}
+
+	let mut cthreshold=olen/hlen; 
+	if olen%hlen!=0 {cthreshold+=1}
+	for counter in 0..cthreshold {
+		let mut b:[u8;64]=[0;64];		
+		hashit(sha,Some(z),counter as isize,&mut b);
+
+		if j+hlen>olen {
+			for i in 0..(olen%hlen) {k[j]=b[i]; j+=1}
+		} else {
+			for i in 0..hlen {k[j]=b[i]; j+=1}
+		}
+	}	
+}
+
+/* SHAXXX identifier strings */
+const SHA256ID:[u8;19]= [0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20];
+const SHA384ID:[u8;19]= [0x30,0x41,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00,0x04,0x30];
+const SHA512ID:[u8;19]= [0x30,0x51,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0x04,0x40];
+
+pub fn pkcs15(sha: usize,m: &[u8],w: &mut [u8]) -> bool {
+	let olen=ff::FF_BITS/8;
+	let hlen=sha;
+	let idlen=19;
+	let mut b:[u8;64]=[0;64];  /* Not good */	
+
+	if olen<idlen+hlen+10 {return false}
+	hashit(sha,Some(m),-1,&mut b);
+
+	for i in 0..w.len() {w[i]=0}
+	let mut i=0;
+	w[i]=0; i+=1;
+	w[i]=1; i+=1;
+	for _ in 0..olen-idlen-hlen-3 {w[i]=0xff; i+=1}
+	w[i]=0; i+=1;
+
+	if hlen==SHA256 {
+		for j in 0..idlen {w[i]=SHA256ID[j]; i+=1}
+	}
+	if hlen==SHA384 {
+		for j in 0..idlen {w[i]=SHA384ID[j]; i+=1}
+	}
+	if hlen==SHA512 {
+		for j in 0..idlen {w[i]=SHA512ID[j]; i+=1}
+	}
+	for j in 0..hlen {w[i]=b[j]; i+=1}
+
+	return true;
+}
+
+/* OAEP Message Encoding for Encryption */
+pub fn oaep_encode(sha: usize,m: &[u8],rng: &mut RAND,p: Option<&[u8]>,f: &mut [u8]) -> bool { 
+	let olen=RFS-1;
+	let mlen=m.len();
+
+	let hlen=sha;
+
+	let mut seed:[u8;64]=[0;64];
+
+	let seedlen=hlen;
+	if mlen>olen-hlen-seedlen-1 {return false} 
+
+	let mut dbmask:[u8;RFS]=[0;RFS];
+
+	hashit(sha,p,-1,f);
+	let slen=olen-mlen-hlen-seedlen-1;      
+
+	for i in 0..slen {f[hlen+i]=0}
+	f[hlen+slen]=1;
+	for i in 0..mlen {f[hlen+slen+1+i]=m[i]}
+
+	for i in 0..seedlen {seed[i]=rng.getbyte()}
+	
+	mgf1(sha,&seed,olen-seedlen,&mut dbmask);
+
+	for i in 0..olen-seedlen {dbmask[i]^=f[i]}
+
+	mgf1(sha,&dbmask[0..olen-seedlen],seedlen,f);
+
+	for i in 0..seedlen {f[i]^=seed[i]}
+
+	for i in 0..olen-seedlen {f[i+seedlen]=dbmask[i]}
+
+	/* pad to length RFS */
+	let d=1;
+	for i in (d..RFS).rev() {
+		f[i]=f[i-d];
+	}
+	for i in (0..d).rev() {
+		f[i]=0;
+	}
+	return true;
+}
+
+/* OAEP Message Decoding for Decryption */
+pub fn oaep_decode(sha: usize,p: Option<&[u8]>,f: &mut [u8]) -> usize {
+	let olen=RFS-1;
+
+	let hlen=sha;
+	let mut seed:[u8;64]=[0;64];
+	let seedlen=hlen;
+	let mut chash:[u8;64]=[0;64];
+	
+	if olen<seedlen+hlen+1 {return 0}
+	let mut dbmask:[u8;RFS]=[0;RFS];
+	//for i in 0..olen-seedlen {dbmask[i]=0}
+
+	if f.len()<RFS {
+		let d=RFS-f.len();
+		for i in (d..RFS).rev() {
+			f[i]=f[i-d];
+		}
+		for i in (0..d).rev() {
+			f[i]=0;
+		}
+	}
+
+	hashit(sha,p,-1,&mut chash);
+
+	let x=f[0];
+
+	for i in seedlen..olen {
+		dbmask[i-seedlen]=f[i+1];
+	}
+
+	mgf1(sha,&dbmask[0..olen-seedlen],seedlen,&mut seed);
+	for i in 0..seedlen {seed[i]^=f[i+1]}
+	mgf1(sha,&seed,olen-seedlen,f);
+	for i in 0..olen-seedlen {dbmask[i]^=f[i]}
+
+	let mut comp=true;
+	for i in 0..hlen {
+		if chash[i]!=dbmask[i] {comp=false}
+	}
+
+	for i in 0..olen-seedlen-hlen {
+		dbmask[i]=dbmask[i+hlen]
+	}
+
+	for i in 0..hlen {
+		seed[i]=0; chash[i]=0
+	}
+		
+	let mut k=0;
+	loop {
+		if k>=olen-seedlen-hlen {return 0}
+		if dbmask[k]!=0 {break}
+		k+=1;
+	}
+
+	let t=dbmask[k];
+	if !comp || x!=0 || t!=0x01 {
+		for i in 0..olen-seedlen {dbmask[i]=0}
+		return 0;
+	}
+
+	for i in 0..olen-seedlen-hlen-k-1 {
+		f[i]=dbmask[i+k+1];
+	}
+	
+	for i in 0..olen-seedlen  {dbmask[i]=0}
+
+	return olen-seedlen-hlen-k-1;
+}
+
+/* destroy the Private Key structure */
+pub fn private_key_kill(prv: &mut RsaPrivateKey) {
+	prv.p.zero();
+	prv.q.zero();
+	prv.dp.zero();
+	prv.dq.zero();
+	prv.c.zero();
+}
+
+/* RSA encryption with the public key */
+pub fn encrypt(pbc: &RsaPublicKey,f: &[u8],g: &mut [u8]) {
+	let m=pbc.n.getlen();
+	let mut r=FF::new_int(m);
+
+	FF::frombytes(&mut r,f);
+	r.power(pbc.e,&pbc.n);
+	r.tobytes(g);
+}
+
+/* RSA decryption with the private key */
+pub fn decrypt(prv: &RsaPrivateKey,g: &[u8],f: &mut [u8]) {
+	let n=prv.p.getlen();
+	let mut r=FF::new_int(2*n);
+
+	FF::frombytes(&mut r,g);
+	let mut jp=r.dmod(&prv.p);
+	let mut jq=r.dmod(&prv.q);
+
+	jp.skpow(&prv.dp,&prv.p);
+	jq.skpow(&prv.dq,&prv.q);
+
+	r.zero();
+	r.dscopy(&jp);
+	jp.rmod(&prv.q);
+	if FF::comp(&jp,&jq)>0 {jq.add(&prv.q)}
+	jq.sub(&jp);
+	jq.norm();
+
+	let mut t=FF::mul(&prv.c,&jq);
+	jq=t.dmod(&prv.q);
+
+	t=FF::mul(&jq,&prv.p);
+	r.add(&t);
+	r.norm();
+
+	r.tobytes(f);
+}
+
diff --git a/version3/rust/sha3.rs b/version3/rust/sha3.rs
new file mode 100644
index 0000000..2607bac
--- /dev/null
+++ b/version3/rust/sha3.rs
@@ -0,0 +1,242 @@
+/*
+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.
+*/
+
+
+pub const HASH224: usize=28;
+pub const HASH256: usize=32;
+pub const HASH384: usize=48;
+pub const HASH512: usize=64;
+pub const SHAKE128: usize=16;
+pub const SHAKE256: usize=32;
+
+const ROUNDS: usize=24;
+
+const RC : [u64;24] = [
+		0x0000000000000001,0x0000000000008082,0x800000000000808A,0x8000000080008000,
+		0x000000000000808B,0x0000000080000001,0x8000000080008081,0x8000000000008009,
+		0x000000000000008A,0x0000000000000088,0x0000000080008009,0x000000008000000A,
+		0x000000008000808B,0x800000000000008B,0x8000000000008089,0x8000000000008003,
+		0x8000000000008002,0x8000000000000080,0x000000000000800A,0x800000008000000A,
+		0x8000000080008081,0x8000000000008080,0x0000000080000001,0x8000000080008008];
+
+
+
+pub struct SHA3 {
+	length: u64,
+	rate: usize,
+	len: usize, 
+	s: [[u64;5];5]
+}
+
+impl SHA3 {
+	fn rotl(x: u64,n: u64) -> u64 {
+		return ((x)<<n) | ((x)>>(64-n));
+	}
+
+	fn transform(&mut self) { /* basic transformation step */
+		let mut c: [u64; 5] = [0; 5];
+		let mut d: [u64; 5] = [0; 5];
+		let mut b: [[u64;5];5]=[[0;5];5];
+
+		for k in 0..ROUNDS  {
+			c[0]=self.s[0][0]^self.s[0][1]^self.s[0][2]^self.s[0][3]^self.s[0][4];
+			c[1]=self.s[1][0]^self.s[1][1]^self.s[1][2]^self.s[1][3]^self.s[1][4];
+			c[2]=self.s[2][0]^self.s[2][1]^self.s[2][2]^self.s[2][3]^self.s[2][4];
+			c[3]=self.s[3][0]^self.s[3][1]^self.s[3][2]^self.s[3][3]^self.s[3][4];
+			c[4]=self.s[4][0]^self.s[4][1]^self.s[4][2]^self.s[4][3]^self.s[4][4];
+
+			d[0]=c[4]^SHA3::rotl(c[1],1);
+			d[1]=c[0]^SHA3::rotl(c[2],1);
+			d[2]=c[1]^SHA3::rotl(c[3],1);
+			d[3]=c[2]^SHA3::rotl(c[4],1);
+			d[4]=c[3]^SHA3::rotl(c[0],1);
+
+			for i in 0..5 {
+				for j in 0..5 {
+					self.s[i][j]^=d[i];
+				}
+			}
+
+			b[0][0]=self.s[0][0];
+			b[1][3]=SHA3::rotl(self.s[0][1],36);
+			b[2][1]=SHA3::rotl(self.s[0][2],3);
+			b[3][4]=SHA3::rotl(self.s[0][3],41);
+			b[4][2]=SHA3::rotl(self.s[0][4],18);
+
+			b[0][2]=SHA3::rotl(self.s[1][0],1);
+			b[1][0]=SHA3::rotl(self.s[1][1],44);
+			b[2][3]=SHA3::rotl(self.s[1][2],10);
+			b[3][1]=SHA3::rotl(self.s[1][3],45);
+			b[4][4]=SHA3::rotl(self.s[1][4],2);
+
+			b[0][4]=SHA3::rotl(self.s[2][0],62);
+			b[1][2]=SHA3::rotl(self.s[2][1],6);
+			b[2][0]=SHA3::rotl(self.s[2][2],43);
+			b[3][3]=SHA3::rotl(self.s[2][3],15);
+			b[4][1]=SHA3::rotl(self.s[2][4],61);
+
+			b[0][1]=SHA3::rotl(self.s[3][0],28);
+			b[1][4]=SHA3::rotl(self.s[3][1],55);
+			b[2][2]=SHA3::rotl(self.s[3][2],25);
+			b[3][0]=SHA3::rotl(self.s[3][3],21);
+			b[4][3]=SHA3::rotl(self.s[3][4],56);
+
+			b[0][3]=SHA3::rotl(self.s[4][0],27);
+			b[1][1]=SHA3::rotl(self.s[4][1],20);
+			b[2][4]=SHA3::rotl(self.s[4][2],39);
+			b[3][2]=SHA3::rotl(self.s[4][3],8);
+			b[4][0]=SHA3::rotl(self.s[4][4],14);
+
+			for i in 0..5 {
+				for j in 0..5 {
+					self.s[i][j]=b[i][j]^(!b[(i+1)%5][j]&b[(i+2)%5][j]);
+				}
+			}
+
+			self.s[0][0]^=RC[k];
+		}
+	} 	
+
+/* Initialise Hash function */
+	pub fn init(&mut self,olen: usize) { /* initialise */
+		for i in 0..5 {
+			for j in 0..5 {
+				self.s[i][j]=0;
+			}
+		}
+		self.length=0; 
+		self.len=olen;
+		self.rate=200-2*olen;
+	}	
+
+	pub fn new(olen: usize) -> SHA3 {
+		let mut nh=SHA3 {
+			length: 0,
+			rate: 0,
+			len: 0,
+			s: [[0;5];5]
+		};
+		nh.init(olen);
+		return nh;
+	}
+
+/* process a single byte */
+	pub fn process(&mut self,byt: u8) { /* process the next message byte */
+		let cnt=(self.length%(self.rate as u64)) as usize;
+		let b=cnt%8;
+		let ind=cnt/8;
+		let i=ind%5;
+		let j=ind/5;
+		self.s[i][j]^=((byt&0xff) as u64) << (8*b);
+		self.length+=1;
+		if cnt+1 == self.rate {
+			self.transform();
+		}
+	}
+
+	pub fn squeeze(&mut self,buff: &mut [u8],olen: usize) {
+		//let olen=buff.len();
+		let mut done=false;
+		let mut m=0;
+		loop {
+			for j in 0..5 {
+				for i in 0..5 {
+					let mut el=self.s[i][j];
+					for _ in 0..8 {
+						buff[m]=(el&0xff) as u8;
+						m+=1;
+						if m>=olen || (m%self.rate)==0 {
+							done=true;
+							break;
+						}
+						el>>=8;
+					}
+					if done {break}
+				}
+				if done {break}
+			}
+			if m>=olen {break}
+			done=false;
+			self.transform();			
+		} 
+
+	}
+
+/* Generate 32-byte Hash */
+	pub fn hash(&mut self,digest: &mut [u8]) { /* pad message and finish - supply digest */
+		let q=self.rate-(self.length%(self.rate as u64)) as usize;
+		if q==1 {
+			self.process(0x86);
+		} else {
+			self.process(0x06);
+			while (self.length%(self.rate as u64)) as usize != self.rate-1 {self.process(0x00)}
+			self.process(0x80);
+		}
+		let hlen=self.len as usize;
+		self.squeeze(digest,hlen);
+	}
+
+	pub fn shake(&mut self,digest: &mut[u8],olen: usize) {
+		let q=self.rate-(self.length%(self.rate as u64)) as usize;
+		if q==1 {
+			self.process(0x9f);
+		} else {
+			self.process(0x1f);
+			while (self.length%(self.rate as u64)) as usize != self.rate-1 {self.process(0x00)}
+			self.process(0x80);
+		}
+		self.squeeze(digest,olen);		
+	}
+
+}
+
+//916f6061fe879741ca6469b43971dfdb28b1a32dc36cb3254e812be27aad1d18
+//afebb2ef542e6579c50cad06d2e578f9f8dd6881d7dc824d26360feebf18a4fa73e3261122948efcfd492e74e82e2189ed0fb440d187f382270cb455f21dd185
+//98be04516c04cc73593fef3ed0352ea9f6443942d6950e29a372a681c3deaf4535423709b02843948684e029010badcc0acd8303fc85fdad3eabf4f78cae165635f57afd28810fc2
+/*
+fn main() {
+	let s = String::from("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu");	
+	let mut digest: [u8;100]=[0;100];	
+	let test = s.into_bytes();
+
+	let mut sh=SHA3::new(HASH256);
+	for i in 0..test.len(){
+		sh.process(test[i]);
+	}
+	sh.hash(&mut digest);    
+	for i in 0..32 {print!("{:02x}",digest[i])}
+	println!("");
+
+	sh=SHA3::new(HASH512);
+	for i in 0..test.len(){
+		sh.process(test[i]);
+	}
+	sh.hash(&mut digest);    
+	for i in 0..64 {print!("{:02x}",digest[i])}
+	println!("");
+
+	sh=SHA3::new(SHAKE256);
+	for i in 0..test.len(){
+		sh.process(test[i]);
+	}
+	sh.shake(&mut digest,72);    
+	for i in 0..72 {print!("{:02x}",digest[i])}
+	println!("");
+
+} */
diff --git a/version3/swift/BenchtestALL.swift b/version3/swift/BenchtestALL.swift
new file mode 100644
index 0000000..7c10d76
--- /dev/null
+++ b/version3/swift/BenchtestALL.swift
@@ -0,0 +1,888 @@
+/*
+	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 TimeRSA_2048(_ rng: inout RAND)
+{
+    let RFS=RSA.RFS
+    let MIN_TIME=10.0
+    let MIN_ITERS=10 
+    var fail=false;
+
+    var pub=rsa_public_key(Int(FF.FFLEN))
+    var priv=rsa_private_key(Int(FF.HFLEN))
+
+    var M=[UInt8](repeating: 0,count: RFS)
+    var C=[UInt8](repeating: 0,count: RFS)
+    var P=[UInt8](repeating: 0,count: RFS)
+ 
+    print("\nTiming/Testing 2048-bit RSA")
+    print("Generating public/private key pair")
+
+    var start=Date()
+    var iterations=0
+    var elapsed=0.0
+    while elapsed<MIN_TIME || iterations<MIN_ITERS {
+        RSA.KEY_PAIR(&rng,65537,&priv,&pub)
+        iterations+=1
+        elapsed = -start.timeIntervalSinceNow
+    }
+    elapsed=1000.0*elapsed/Double(iterations)
+    print(String(format: "RSA gen - %d iterations",iterations),terminator: "");
+    print(String(format: " %.2f ms per iteration",elapsed))
+    
+    for i in 0..<RFS {M[i]=UInt8(i%128)}
+    
+    start=Date()
+    iterations=0
+    elapsed=0.0
+    while elapsed<MIN_TIME || iterations<MIN_ITERS {
+        RSA.ENCRYPT(pub,M,&C)
+        iterations+=1
+        elapsed = -start.timeIntervalSinceNow
+    }
+    elapsed=1000.0*elapsed/Double(iterations)
+    print(String(format: "RSA enc - %d iterations",iterations),terminator: "");
+    print(String(format: " %.2f ms per iteration",elapsed))
+   
+    start=Date()
+    iterations=0
+    elapsed=0.0
+    while elapsed<MIN_TIME || iterations<MIN_ITERS {
+        RSA.DECRYPT(priv,C,&P)
+        iterations+=1
+        elapsed = -start.timeIntervalSinceNow
+    }
+    elapsed=1000.0*elapsed/Double(iterations)
+    print(String(format: "RSA dec - %d iterations",iterations),terminator: "");
+    print(String(format: " %.2f ms per iteration",elapsed))
+   
+    var cmp=true
+    for i in 0..<RFS {
+        if P[i] != M[i] {cmp=false}
+    }
+    
+    if !cmp {
+        print("FAILURE - RSA decryption")
+        fail=true;
+    }
+    
+    if !fail {
+       print("All tests pass")
+    }
+}
+
+
+public func TimeECDH_ed25519(_ rng: inout RAND)
+{
+    let MIN_TIME=10.0
+    let MIN_ITERS=10
+    
+    var fail=false;
+
+    print("\nTiming/Testing ED25519 ECC")
+    if ed25519.ECP.CURVETYPE==ed25519.ECP.WEIERSTRASS {
+        print("Weierstrass parameterisation")
+    }
+    if ed25519.ECP.CURVETYPE==ed25519.ECP.EDWARDS {
+        print("Edwards parameterisation")
+    }
+    if ed25519.ECP.CURVETYPE==ed25519.ECP.MONTGOMERY {
+        print("Montgomery representation")
+    }
+    if ed25519.FP.MODTYPE==ed25519.FP.PSEUDO_MERSENNE {
+        print("Pseudo-Mersenne Modulus")
+    }
+    if ed25519.FP.MODTYPE==ed25519.FP.MONTGOMERY_FRIENDLY {
+        print("Montgomery Friendly Modulus")
+    }
+    if ed25519.FP.MODTYPE==ed25519.FP.GENERALISED_MERSENNE {
+        print("Generalised-Mersenne Modulus")
+    }
+    if ed25519.FP.MODTYPE==ed25519.FP.NOT_SPECIAL {
+        print("Not special Modulus")
+    }
+    print("Modulus size \(ed25519.FP.MODBITS) bits")
+    print("\(ed25519.BIG.CHUNK) bit build")
+    
+
+    var s:ed25519.BIG
+    let G=ed25519.ECP.generator();
+    
+    let r=ed25519.BIG(ed25519.ROM.CURVE_Order)
+    s=ed25519.BIG.randomnum(r,&rng)
+    
+    var W=G.mul(r)
+    if !W.is_infinity() {
+        print("FAILURE - rG!=O")
+        fail=true;
+    }
+    
+    let start=Date()
+    var iterations=0
+    var elapsed=0.0
+    while elapsed<MIN_TIME || iterations<MIN_ITERS {
+        W=G.mul(s)
+        iterations+=1
+        elapsed = -start.timeIntervalSinceNow
+    }
+    elapsed=1000.0*elapsed/Double(iterations)
+    print(String(format: "EC  mul - %d iterations",iterations),terminator: "");
+    print(String(format: " %.2f ms per iteration",elapsed))
+
+    if !fail {
+       print("All tests pass")
+    }    
+}
+
+public func TimeECDH_nist256(_ rng: inout RAND)
+{
+    let MIN_TIME=10.0
+    let MIN_ITERS=10
+    
+    var fail=false;
+
+    print("\nTiming/Testing NIST256 ECC")
+    if nist256.ECP.CURVETYPE==nist256.ECP.WEIERSTRASS {
+        print("Weierstrass parameterisation")
+    }
+    if nist256.ECP.CURVETYPE==nist256.ECP.EDWARDS {
+        print("Edwards parameterisation")
+    }
+    if nist256.ECP.CURVETYPE==nist256.ECP.MONTGOMERY {
+        print("Montgomery representation")
+    }
+    if nist256.FP.MODTYPE==nist256.FP.PSEUDO_MERSENNE {
+        print("Pseudo-Mersenne Modulus")
+    }
+    if nist256.FP.MODTYPE==nist256.FP.MONTGOMERY_FRIENDLY {
+        print("Montgomery Friendly Modulus")
+    }
+    if nist256.FP.MODTYPE==nist256.FP.GENERALISED_MERSENNE {
+        print("Generalised-Mersenne Modulus")
+    }
+    if nist256.FP.MODTYPE==nist256.FP.NOT_SPECIAL {
+        print("Not special Modulus")
+    }
+    print("Modulus size \(nist256.FP.MODBITS) bits")
+    print("\(nist256.BIG.CHUNK) bit build")
+    
+
+    var s:nist256.BIG
+    let G=nist256.ECP.generator();
+    
+    let r=nist256.BIG(nist256.ROM.CURVE_Order)
+    s=nist256.BIG.randomnum(r,&rng)
+    
+    var W=G.mul(r)
+    if !W.is_infinity() {
+        print("FAILURE - rG!=O")
+        fail=true;
+    }
+    
+    let start=Date()
+    var iterations=0
+    var elapsed=0.0
+    while elapsed<MIN_TIME || iterations<MIN_ITERS {
+        W=G.mul(s)
+        iterations+=1
+        elapsed = -start.timeIntervalSinceNow
+    }
+    elapsed=1000.0*elapsed/Double(iterations)
+    print(String(format: "EC  mul - %d iterations",iterations),terminator: "");
+    print(String(format: " %.2f ms per iteration",elapsed))
+
+    if !fail {
+       print("All tests pass")
+    }    
+}
+
+
+public func TimeECDH_goldilocks(_ rng: inout RAND)
+{
+    let MIN_TIME=10.0
+    let MIN_ITERS=10
+    
+    var fail=false;
+
+    print("\nTiming/Testing GOLDILOCKS ECC")
+    if goldilocks.ECP.CURVETYPE==goldilocks.ECP.WEIERSTRASS {
+        print("Weierstrass parameterisation")
+    }
+    if goldilocks.ECP.CURVETYPE==goldilocks.ECP.EDWARDS {
+        print("Edwards parameterisation")
+    }
+    if goldilocks.ECP.CURVETYPE==goldilocks.ECP.MONTGOMERY {
+        print("Montgomery representation")
+    }
+    if goldilocks.FP.MODTYPE==goldilocks.FP.PSEUDO_MERSENNE {
+        print("Pseudo-Mersenne Modulus")
+    }
+    if goldilocks.FP.MODTYPE==goldilocks.FP.MONTGOMERY_FRIENDLY {
+        print("Montgomery Friendly Modulus")
+    }
+    if goldilocks.FP.MODTYPE==goldilocks.FP.GENERALISED_MERSENNE {
+        print("Generalised-Mersenne Modulus")
+    }
+    if goldilocks.FP.MODTYPE==goldilocks.FP.NOT_SPECIAL {
+        print("Not special Modulus")
+    }
+    print("Modulus size \(goldilocks.FP.MODBITS) bits")
+    print("\(goldilocks.BIG.CHUNK) bit build")
+    
+
+    var s:goldilocks.BIG
+    let G=goldilocks.ECP.generator();
+    
+    let r=goldilocks.BIG(goldilocks.ROM.CURVE_Order)
+    s=goldilocks.BIG.randomnum(r,&rng)
+    
+    var W=G.mul(r)
+    if !W.is_infinity() {
+        print("FAILURE - rG!=O")
+        fail=true;
+    }
+    
+    let start=Date()
+    var iterations=0
+    var elapsed=0.0
+    while elapsed<MIN_TIME || iterations<MIN_ITERS {
+        W=G.mul(s)
+        iterations+=1
+        elapsed = -start.timeIntervalSinceNow
+    }
+    elapsed=1000.0*elapsed/Double(iterations)
+    print(String(format: "EC  mul - %d iterations",iterations),terminator: "");
+    print(String(format: " %.2f ms per iteration",elapsed))
+
+    if !fail {
+       print("All tests pass")
+    }    
+}
+
+public func TimeMPIN_bn254(_ rng: inout RAND)
+{
+    let MIN_TIME=10.0
+    let MIN_ITERS=10   
+    var fail=false;
+
+    print("\nTiming/Testing BN254 Pairings")
+    if bn254.ECP.CURVE_PAIRING_TYPE==bn254.ECP.BN {
+        print("BN Pairing-Friendly Curve")
+    }
+    if bn254.ECP.CURVE_PAIRING_TYPE==bn254.ECP.BLS {
+        print("BLS Pairing-Friendly Curve")
+    }
+    print("Modulus size \(bn254.FP.MODBITS) bits")
+    print("\(bn254.BIG.CHUNK) bit build")
+    
+    let G=bn254.ECP.generator();
+    
+    let r=bn254.BIG(bn254.ROM.CURVE_Order)
+    let s=bn254.BIG.randomnum(r,&rng)
+    
+    var P=bn254.PAIR.G1mul(G,r);
+    
+    if !P.is_infinity() {
+        print("FAILURE - rP!=O")
+        fail=true
+    }
+    
+    var start=Date()
+    var iterations=0
+    var elapsed=0.0
+    while elapsed<MIN_TIME || iterations<MIN_ITERS {
+        P=bn254.PAIR.G1mul(G,s)
+        iterations+=1
+        elapsed = -start.timeIntervalSinceNow
+    }
+    elapsed=1000.0*elapsed/Double(iterations)
+    print(String(format: "G1  mul              - %d iterations",iterations),terminator: "");
+    print(String(format: " %.2f ms per iteration",elapsed))
+    
+    var Q=bn254.ECP2.generator();
+    
+    var W=bn254.PAIR.G2mul(Q,r)
+    
+    if !W.is_infinity() {
+        print("FAILURE - rQ!=O")
+        fail=true
+    }
+    
+    start=Date()
+    iterations=0
+    elapsed=0.0
+    while elapsed<MIN_TIME || iterations<MIN_ITERS {
+        W=bn254.PAIR.G2mul(Q,s)
+        iterations+=1
+        elapsed = -start.timeIntervalSinceNow
+    }
+    elapsed=1000.0*elapsed/Double(iterations)
+    print(String(format: "G2  mul              - %d iterations",iterations),terminator: "");
+    print(String(format: " %.2f ms per iteration",elapsed))
+    
+    var w=bn254.PAIR.ate(Q,P)
+    w=bn254.PAIR.fexp(w)
+    
+    var g=bn254.PAIR.GTpow(w,r)
+    
+    if !g.isunity() {
+        print("FAILURE - g^r!=1")
+        fail=true
+    }
+    
+    start=Date()
+    iterations=0
+    elapsed=0.0
+    while elapsed<MIN_TIME || iterations<MIN_ITERS {
+        g=bn254.PAIR.GTpow(w,s)
+        iterations+=1
+        elapsed = -start.timeIntervalSinceNow
+    }
+    elapsed=1000.0*elapsed/Double(iterations)
+    print(String(format: "GT  pow              - %d iterations",iterations),terminator: "");
+    print(String(format: " %.2f ms per iteration",elapsed))
+   
+    g.copy(w)
+    
+    start=Date()
+    iterations=0
+    elapsed=0.0
+    while elapsed<MIN_TIME || iterations<MIN_ITERS {
+        _=g.compow(s,r)
+        iterations+=1
+        elapsed = -start.timeIntervalSinceNow
+    }
+    elapsed=1000.0*elapsed/Double(iterations)
+    print(String(format: "GT  pow (compressed) - %d iterations",iterations),terminator: "");
+    print(String(format: " %.2f ms per iteration",elapsed))
+    
+    start=Date()
+    iterations=0
+    elapsed=0.0
+    while elapsed<MIN_TIME || iterations<MIN_ITERS {
+        w=bn254.PAIR.ate(Q,P)
+        iterations+=1
+        elapsed = -start.timeIntervalSinceNow
+    }
+    elapsed=1000.0*elapsed/Double(iterations)
+    print(String(format: "PAIRing ATE          - %d iterations",iterations),terminator: "");
+    print(String(format: " %.2f ms per iteration",elapsed))
+
+    start=Date()
+    iterations=0
+    elapsed=0.0
+    while elapsed<MIN_TIME || iterations<MIN_ITERS {
+        g=bn254.PAIR.fexp(w)
+        iterations+=1
+        elapsed = -start.timeIntervalSinceNow
+    }
+    elapsed=1000.0*elapsed/Double(iterations)
+    print(String(format: "PAIRing FEXP         - %d iterations",iterations),terminator: "");
+    print(String(format: " %.2f ms per iteration",elapsed))
+ 
+    P.copy(G)
+    Q.copy(W)
+    
+    P=bn254.PAIR.G1mul(P,s)
+    g=bn254.PAIR.ate(Q,P)
+    g=bn254.PAIR.fexp(g)
+    
+    P.copy(G)
+    Q=bn254.PAIR.G2mul(Q,s)
+    w=bn254.PAIR.ate(Q,P)
+    w=bn254.PAIR.fexp(w)
+    
+    if !g.equals(w) {
+        print("FAILURE - e(sQ,P)!=e(Q,sP)")
+        fail=true
+    }
+    
+    if !fail {
+        print("All tests pass")
+    }
+}
+
+public func TimeMPIN_bls383(_ rng: inout RAND)
+{
+    let MIN_TIME=10.0
+    let MIN_ITERS=10   
+    var fail=false;
+
+    print("\nTiming/Testing BLS383 Pairings")
+    if bls383.ECP.CURVE_PAIRING_TYPE==bls383.ECP.BN {
+        print("BN Pairing-Friendly Curve")
+    }
+    if bls383.ECP.CURVE_PAIRING_TYPE==bls383.ECP.BLS {
+        print("BLS Pairing-Friendly Curve")
+    }
+    print("Modulus size \(bls383.FP.MODBITS) bits")
+    print("\(bls383.BIG.CHUNK) bit build")
+    
+    let G=bls383.ECP.generator();
+    
+    let r=bls383.BIG(bls383.ROM.CURVE_Order)
+    let s=bls383.BIG.randomnum(r,&rng)
+    
+    var P=bls383.PAIR.G1mul(G,r);
+    
+    if !P.is_infinity() {
+        print("FAILURE - rP!=O")
+        fail=true
+    }
+    
+    var start=Date()
+    var iterations=0
+    var elapsed=0.0
+    while elapsed<MIN_TIME || iterations<MIN_ITERS {
+        P=bls383.PAIR.G1mul(G,s)
+        iterations+=1
+        elapsed = -start.timeIntervalSinceNow
+    }
+    elapsed=1000.0*elapsed/Double(iterations)
+    print(String(format: "G1  mul              - %d iterations",iterations),terminator: "");
+    print(String(format: " %.2f ms per iteration",elapsed))
+    
+    var Q=bls383.ECP2.generator();
+    
+    var W=bls383.PAIR.G2mul(Q,r)
+    
+    if !W.is_infinity() {
+        print("FAILURE - rQ!=O")
+        fail=true
+    }
+    
+    start=Date()
+    iterations=0
+    elapsed=0.0
+    while elapsed<MIN_TIME || iterations<MIN_ITERS {
+        W=bls383.PAIR.G2mul(Q,s)
+        iterations+=1
+        elapsed = -start.timeIntervalSinceNow
+    }
+    elapsed=1000.0*elapsed/Double(iterations)
+    print(String(format: "G2  mul              - %d iterations",iterations),terminator: "");
+    print(String(format: " %.2f ms per iteration",elapsed))
+    
+    var w=bls383.PAIR.ate(Q,P)
+    w=bls383.PAIR.fexp(w)
+    
+    var g=bls383.PAIR.GTpow(w,r)
+    
+    if !g.isunity() {
+        print("FAILURE - g^r!=1")
+        fail=true
+    }
+    
+    start=Date()
+    iterations=0
+    elapsed=0.0
+    while elapsed<MIN_TIME || iterations<MIN_ITERS {
+        g=bls383.PAIR.GTpow(w,s)
+        iterations+=1
+        elapsed = -start.timeIntervalSinceNow
+    }
+    elapsed=1000.0*elapsed/Double(iterations)
+    print(String(format: "GT  pow              - %d iterations",iterations),terminator: "");
+    print(String(format: " %.2f ms per iteration",elapsed))
+   
+    g.copy(w)
+    
+    start=Date()
+    iterations=0
+    elapsed=0.0
+    while elapsed<MIN_TIME || iterations<MIN_ITERS {
+        _=g.compow(s,r)
+        iterations+=1
+        elapsed = -start.timeIntervalSinceNow
+    }
+    elapsed=1000.0*elapsed/Double(iterations)
+    print(String(format: "GT  pow (compressed) - %d iterations",iterations),terminator: "");
+    print(String(format: " %.2f ms per iteration",elapsed))
+    
+    start=Date()
+    iterations=0
+    elapsed=0.0
+    while elapsed<MIN_TIME || iterations<MIN_ITERS {
+        w=bls383.PAIR.ate(Q,P)
+        iterations+=1
+        elapsed = -start.timeIntervalSinceNow
+    }
+    elapsed=1000.0*elapsed/Double(iterations)
+    print(String(format: "PAIRing ATE          - %d iterations",iterations),terminator: "");
+    print(String(format: " %.2f ms per iteration",elapsed))
+
+    start=Date()
+    iterations=0
+    elapsed=0.0
+    while elapsed<MIN_TIME || iterations<MIN_ITERS {
+        g=bls383.PAIR.fexp(w)
+        iterations+=1
+        elapsed = -start.timeIntervalSinceNow
+    }
+    elapsed=1000.0*elapsed/Double(iterations)
+    print(String(format: "PAIRing FEXP         - %d iterations",iterations),terminator: "");
+    print(String(format: " %.2f ms per iteration",elapsed))
+ 
+    P.copy(G)
+    Q.copy(W)
+    
+    P=bls383.PAIR.G1mul(P,s)
+    g=bls383.PAIR.ate(Q,P)
+    g=bls383.PAIR.fexp(g)
+    
+    P.copy(G)
+    Q=bls383.PAIR.G2mul(Q,s)
+    w=bls383.PAIR.ate(Q,P)
+    w=bls383.PAIR.fexp(w)
+    
+    if !g.equals(w) {
+        print("FAILURE - e(sQ,P)!=e(Q,sP)")
+        fail=true
+    }
+    
+    if !fail {
+        print("All tests pass")
+    }
+}
+
+
+public func TimeMPIN_bls24(_ rng: inout RAND)
+{
+    let MIN_TIME=10.0
+    let MIN_ITERS=10   
+    var fail=false;
+
+    print("\nTiming/Testing BLS24 Pairings")
+    if bls24.ECP.CURVE_PAIRING_TYPE==bls24.ECP.BN {
+        print("BN Pairing-Friendly Curve")
+    }
+    if bls24.ECP.CURVE_PAIRING_TYPE==bls24.ECP.BLS {
+        print("BLS24 Pairing-Friendly Curve")
+    }
+    print("Modulus size \(bls24.FP.MODBITS) bits")
+    print("\(bls24.BIG.CHUNK) bit build")
+    
+    let G=bls24.ECP.generator();
+    
+    let r=bls24.BIG(bls24.ROM.CURVE_Order)
+    let s=bls24.BIG.randomnum(r,&rng)
+    
+    var P=PAIR192.G1mul(G,r);
+    
+    if !P.is_infinity() {
+        print("FAILURE - rP!=O")
+        fail=true
+    }
+    
+    var start=Date()
+    var iterations=0
+    var elapsed=0.0
+    while elapsed<MIN_TIME || iterations<MIN_ITERS {
+        P=PAIR192.G1mul(G,s)
+        iterations+=1
+        elapsed = -start.timeIntervalSinceNow
+    }
+    elapsed=1000.0*elapsed/Double(iterations)
+    print(String(format: "G1  mul              - %d iterations",iterations),terminator: "");
+    print(String(format: " %.2f ms per iteration",elapsed))
+    
+    var Q=ECP4.generator();
+    
+    var W=PAIR192.G2mul(Q,r)
+    
+    if !W.is_infinity() {
+        print("FAILURE - rQ!=O")
+        fail=true
+    }
+    
+    start=Date()
+    iterations=0
+    elapsed=0.0
+    while elapsed<MIN_TIME || iterations<MIN_ITERS {
+        W=PAIR192.G2mul(Q,s)
+        iterations+=1
+        elapsed = -start.timeIntervalSinceNow
+    }
+    elapsed=1000.0*elapsed/Double(iterations)
+    print(String(format: "G2  mul              - %d iterations",iterations),terminator: "");
+    print(String(format: " %.2f ms per iteration",elapsed))
+    
+    var w=PAIR192.ate(Q,P)
+    w=PAIR192.fexp(w)
+    
+    var g=PAIR192.GTpow(w,r)
+    
+    if !g.isunity() {
+        print("FAILURE - g^r!=1")
+        fail=true
+    }
+    
+    start=Date()
+    iterations=0
+    elapsed=0.0
+    while elapsed<MIN_TIME || iterations<MIN_ITERS {
+        g=PAIR192.GTpow(w,s)
+        iterations+=1
+        elapsed = -start.timeIntervalSinceNow
+    }
+    elapsed=1000.0*elapsed/Double(iterations)
+    print(String(format: "GT  pow              - %d iterations",iterations),terminator: "");
+    print(String(format: " %.2f ms per iteration",elapsed))
+   
+    g.copy(w)
+    
+    start=Date()
+    iterations=0
+    elapsed=0.0
+    while elapsed<MIN_TIME || iterations<MIN_ITERS {
+        _=g.compow(s,r)
+        iterations+=1
+        elapsed = -start.timeIntervalSinceNow
+    }
+    elapsed=1000.0*elapsed/Double(iterations)
+    print(String(format: "GT  pow (compressed) - %d iterations",iterations),terminator: "");
+    print(String(format: " %.2f ms per iteration",elapsed))
+    
+    start=Date()
+    iterations=0
+    elapsed=0.0
+    while elapsed<MIN_TIME || iterations<MIN_ITERS {
+        w=PAIR192.ate(Q,P)
+        iterations+=1
+        elapsed = -start.timeIntervalSinceNow
+    }
+    elapsed=1000.0*elapsed/Double(iterations)
+    print(String(format: "PAIRing ATE          - %d iterations",iterations),terminator: "");
+    print(String(format: " %.2f ms per iteration",elapsed))
+
+    start=Date()
+    iterations=0
+    elapsed=0.0
+    while elapsed<MIN_TIME || iterations<MIN_ITERS {
+        g=PAIR192.fexp(w)
+        iterations+=1
+        elapsed = -start.timeIntervalSinceNow
+    }
+    elapsed=1000.0*elapsed/Double(iterations)
+    print(String(format: "PAIRing FEXP         - %d iterations",iterations),terminator: "");
+    print(String(format: " %.2f ms per iteration",elapsed))
+ 
+    P.copy(G)
+    Q.copy(W)
+    
+    P=PAIR192.G1mul(P,s)
+    g=PAIR192.ate(Q,P)
+    g=PAIR192.fexp(g)
+    
+    P.copy(G)
+    Q=PAIR192.G2mul(Q,s)
+    w=PAIR192.ate(Q,P)
+    w=PAIR192.fexp(w)
+    
+    if !g.equals(w) {
+        print("FAILURE - e(sQ,P)!=e(Q,sP)")
+        fail=true
+    }
+    
+    if !fail {
+        print("All tests pass")
+    }
+}
+
+
+public func TimeMPIN_bls48(_ rng: inout RAND)
+{
+    let MIN_TIME=10.0
+    let MIN_ITERS=10   
+    var fail=false;
+
+    print("\nTiming/Testing BLS48 Pairings")
+    if bls48.ECP.CURVE_PAIRING_TYPE==bls48.ECP.BN {
+        print("BN Pairing-Friendly Curve")
+    }
+    if bls48.ECP.CURVE_PAIRING_TYPE==bls48.ECP.BLS {
+        print("BLS48 Pairing-Friendly Curve")
+    }
+    print("Modulus size \(bls48.FP.MODBITS) bits")
+    print("\(bls48.BIG.CHUNK) bit build")
+    
+    let G=bls48.ECP.generator();
+    
+    let r=bls48.BIG(bls48.ROM.CURVE_Order)
+    let s=bls48.BIG.randomnum(r,&rng)
+    
+    var P=PAIR256.G1mul(G,r);
+    
+    if !P.is_infinity() {
+        print("FAILURE - rP!=O")
+        fail=true
+    }
+    
+    var start=Date()
+    var iterations=0
+    var elapsed=0.0
+    while elapsed<MIN_TIME || iterations<MIN_ITERS {
+        P=PAIR256.G1mul(G,s)
+        iterations+=1
+        elapsed = -start.timeIntervalSinceNow
+    }
+    elapsed=1000.0*elapsed/Double(iterations)
+    print(String(format: "G1  mul              - %d iterations",iterations),terminator: "");
+    print(String(format: " %.2f ms per iteration",elapsed))
+    
+    var Q=ECP8.generator();
+    
+    var W=PAIR256.G2mul(Q,r)
+    
+    if !W.is_infinity() {
+        print("FAILURE - rQ!=O")
+        fail=true
+    }
+    
+    start=Date()
+    iterations=0
+    elapsed=0.0
+    while elapsed<MIN_TIME || iterations<MIN_ITERS {
+        W=PAIR256.G2mul(Q,s)
+        iterations+=1
+        elapsed = -start.timeIntervalSinceNow
+    }
+    elapsed=1000.0*elapsed/Double(iterations)
+    print(String(format: "G2  mul              - %d iterations",iterations),terminator: "");
+    print(String(format: " %.2f ms per iteration",elapsed))
+    
+    var w=PAIR256.ate(Q,P)
+    w=PAIR256.fexp(w)
+    
+    var g=PAIR256.GTpow(w,r)
+    
+    if !g.isunity() {
+        print("FAILURE - g^r!=1")
+        fail=true
+    }
+    
+    start=Date()
+    iterations=0
+    elapsed=0.0
+    while elapsed<MIN_TIME || iterations<MIN_ITERS {
+        g=PAIR256.GTpow(w,s)
+        iterations+=1
+        elapsed = -start.timeIntervalSinceNow
+    }
+    elapsed=1000.0*elapsed/Double(iterations)
+    print(String(format: "GT  pow              - %d iterations",iterations),terminator: "");
+    print(String(format: " %.2f ms per iteration",elapsed))
+   
+    g.copy(w)
+    
+    start=Date()
+    iterations=0
+    elapsed=0.0
+    while elapsed<MIN_TIME || iterations<MIN_ITERS {
+        _=g.compow(s,r)
+        iterations+=1
+        elapsed = -start.timeIntervalSinceNow
+    }
+    elapsed=1000.0*elapsed/Double(iterations)
+    print(String(format: "GT  pow (compressed) - %d iterations",iterations),terminator: "");
+    print(String(format: " %.2f ms per iteration",elapsed))
+    
+    start=Date()
+    iterations=0
+    elapsed=0.0
+    while elapsed<MIN_TIME || iterations<MIN_ITERS {
+        w=PAIR256.ate(Q,P)
+        iterations+=1
+        elapsed = -start.timeIntervalSinceNow
+    }
+    elapsed=1000.0*elapsed/Double(iterations)
+    print(String(format: "PAIRing ATE          - %d iterations",iterations),terminator: "");
+    print(String(format: " %.2f ms per iteration",elapsed))
+
+    start=Date()
+    iterations=0
+    elapsed=0.0
+    while elapsed<MIN_TIME || iterations<MIN_ITERS {
+        g=PAIR256.fexp(w)
+        iterations+=1
+        elapsed = -start.timeIntervalSinceNow
+    }
+    elapsed=1000.0*elapsed/Double(iterations)
+    print(String(format: "PAIRing FEXP         - %d iterations",iterations),terminator: "");
+    print(String(format: " %.2f ms per iteration",elapsed))
+ 
+    P.copy(G)
+    Q.copy(W)
+    
+    P=PAIR256.G1mul(P,s)
+    g=PAIR256.ate(Q,P)
+    g=PAIR256.fexp(g)
+    
+    P.copy(G)
+    Q=PAIR256.G2mul(Q,s)
+    w=PAIR256.ate(Q,P)
+    w=PAIR256.fexp(w)
+    
+    if !g.equals(w) {
+        print("FAILURE - e(sQ,P)!=e(Q,sP)")
+        fail=true
+    }
+    
+    if !fail {
+        print("All tests pass")
+    }
+}
+
+
+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)
+
+
+TimeECDH_ed25519(&rng)  
+TimeECDH_nist256(&rng)
+TimeECDH_goldilocks(&rng)
+TimeRSA_2048(&rng)
+TimeMPIN_bn254(&rng)
+TimeMPIN_bls383(&rng)
+TimeMPIN_bls24(&rng)
+TimeMPIN_bls48(&rng)
+
+
diff --git a/version3/swift/TestALL.swift b/version3/swift/TestALL.swift
new file mode 100644
index 0000000..cef42d7
--- /dev/null
+++ b/version3/swift/TestALL.swift
@@ -0,0 +1,1425 @@
+/*
+	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)
diff --git a/version3/swift/TestNHS.swift b/version3/swift/TestNHS.swift
new file mode 100644
index 0000000..6acd328
--- /dev/null
+++ b/version3/swift/TestNHS.swift
@@ -0,0 +1,70 @@
+/*
+	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.
+*/
+
+//
+//  TestNHS.swift - Tests NewHope Simple API
+//  swift -I. -L. -lamcl TestNHS.swift
+// See https://eprint.iacr.org/2016/1157 (Alkim, Ducas, Popplemann and Schwabe)
+
+
+import Foundation
+import amcl // comment out for Xcode
+
+public func TestNHS()
+{
+	var S=[UInt8](repeating:0,count:1792)
+	var SB=[UInt8](repeating:0,count:1824)
+	var UC=[UInt8](repeating:0,count:2176)
+	var KEYA=[UInt8](repeating:0,count:32)
+	var KEYB=[UInt8](repeating:0,count:32)
+
+
+	var RAW=[UInt8](repeating: 0,count: 100)
+	var srng=RAND()
+				var crng=RAND()
+				crng.clean()
+    
+	srng.clean()
+	for i in 0..<100 {RAW[i]=UInt8((i+1)&0xff)}
+	srng.seed(100,RAW)
+				
+				for i in 0..<100 {RAW[i]=UInt8((i+2)&0xff)}
+				crng.seed(100,RAW)
+
+
+	NHS.SERVER_1(&srng,&SB,&S)
+				NHS.CLIENT(&crng,SB,&UC,&KEYB)
+
+ 			   	for i in 0..<32 {
+            				let h=String(KEYB[i],radix:16)
+            				print("\(h)", terminator: "")
+        			}
+        			print("")
+
+	NHS.SERVER_2(S,UC,&KEYA)
+
+	for i in 0..<32 {
+            	let h=String(KEYA[i],radix:16)
+            	print("\(h)", terminator: "")
+        }
+        print("")
+}
+
+TestNHS()
+
diff --git a/version3/swift/aes.swift b/version3/swift/aes.swift
new file mode 100644
index 0000000..e79d479
--- /dev/null
+++ b/version3/swift/aes.swift
@@ -0,0 +1,641 @@
+/*
+	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.
+*/
+
+//
+//  aes.swift
+//
+//  Created by Michael Scott on 22/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+//   AES Encryption
+//
+
+public struct AES {
+    var mode:Int=0;
+    private var fkey=[UInt32](repeating: 0,count: 44)
+    private var rkey=[UInt32](repeating: 0,count: 44)
+    var f=[UInt8](repeating: 0,count: 16)
+    
+    public init() {}
+
+    static public let ECB:Int=0
+    static public let CBC:Int=1
+    static public let CFB1:Int=2
+    static public let CFB2:Int=3
+    static public let CFB4:Int=5
+    static public let OFB1:Int=14
+    static public let OFB2:Int=15
+    static public let OFB4:Int=17
+    static public let OFB8:Int=21
+    static public let OFB16:Int=29
+    static public let CTR1:Int=30
+    static public let CTR2:Int=31
+    static public let CTR4:Int=33 
+    static public let CTR8:Int=37 
+    static public let CTR16:Int=45
+
+    static let KS:Int=16; /* Key Size in bytes */
+    static let BS:Int=16; /* Block Size */
+    
+    private static let InCo:[UInt8] = [ 0xB,0xD,0x9,0xE]  /* Inverse Coefficients */
+    
+    private static let ptab:[UInt8] =
+    [ 1, 3, 5, 15, 17, 51, 85, 255, 26, 46, 114, 150, 161, 248, 19, 53,
+     95, 225, 56, 72, 216, 115, 149, 164, 247, 2, 6, 10, 30, 34, 102, 170,
+     229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217, 112, 144, 171, 230, 49,
+     83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104, 184, 211, 110, 178, 205,
+     76, 212, 103, 169, 224, 59, 77, 215, 98, 166, 241, 8, 24, 40, 120, 136,
+     131, 158, 185, 208, 107, 189, 220, 127, 129, 152, 179, 206, 73, 219, 118, 154,
+     181, 196, 87, 249, 16, 48, 80, 240, 11, 29, 39, 105, 187, 214, 97, 163,
+     254, 25, 43, 125, 135, 146, 173, 236, 47, 113, 147, 174, 233, 32, 96, 160,
+     251, 22, 58, 78, 210, 109, 183, 194, 93, 231, 50, 86, 250, 21, 63, 65,
+     195, 94, 226, 61, 71, 201, 64, 192, 91, 237, 44, 116, 156, 191, 218, 117,
+     159, 186, 213, 100, 172, 239, 42, 126, 130, 157, 188, 223, 122, 142, 137, 128,
+     155, 182, 193, 88, 232, 35, 101, 175, 234, 37, 111, 177, 200, 67, 197, 84,
+     252, 31, 33, 99, 165, 244, 7, 9, 27, 45, 119, 153, 176, 203, 70, 202,
+     69, 207, 74, 222, 121, 139, 134, 145, 168, 227, 62, 66, 198, 81, 243, 14,
+     18, 54, 90, 238, 41, 123, 141, 140, 143, 138, 133, 148, 167, 242, 13, 23,
+     57, 75, 221, 124, 132, 151, 162, 253, 28, 36, 108, 180, 199, 82, 246, 1]
+    
+    private static let ltab:[UInt8] =
+    [ 0, 255, 25, 1, 50, 2, 26, 198, 75, 199, 27, 104, 51, 238, 223, 3,
+     100, 4, 224, 14, 52, 141, 129, 239, 76, 113, 8, 200, 248, 105, 28, 193,
+     125, 194, 29, 181, 249, 185, 39, 106, 77, 228, 166, 114, 154, 201, 9, 120,
+     101, 47, 138, 5, 33, 15, 225, 36, 18, 240, 130, 69, 53, 147, 218, 142,
+     150, 143, 219, 189, 54, 208, 206, 148, 19, 92, 210, 241, 64, 70, 131, 56,
+     102, 221, 253, 48, 191, 6, 139, 98, 179, 37, 226, 152, 34, 136, 145, 16,
+     126, 110, 72, 195, 163, 182, 30, 66, 58, 107, 40, 84, 250, 133, 61, 186,
+     43, 121, 10, 21, 155, 159, 94, 202, 78, 212, 172, 229, 243, 115, 167, 87,
+     175, 88, 168, 80, 244, 234, 214, 116, 79, 174, 233, 213, 231, 230, 173, 232,
+     44, 215, 117, 122, 235, 22, 11, 245, 89, 203, 95, 176, 156, 169, 81, 160,
+     127, 12, 246, 111, 23, 196, 73, 236, 216, 67, 31, 45, 164, 118, 123, 183,
+     204, 187, 62, 90, 251, 96, 177, 134, 59, 82, 161, 108, 170, 85, 41, 157,
+     151, 178, 135, 144, 97, 190, 220, 252, 188, 149, 207, 205, 55, 63, 91, 209,
+     83, 57, 132, 60, 65, 162, 109, 71, 20, 42, 158, 93, 86, 242, 211, 171,
+     68, 17, 146, 217, 35, 32, 46, 137, 180, 124, 184, 38, 119, 153, 227, 165,
+     103, 74, 237, 222, 197, 49, 254, 24, 13, 99, 140, 128, 192, 247, 112, 7]
+    
+    private static let fbsub:[UInt8] =
+    [ 99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118,
+     202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192,
+     183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21,
+     4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117,
+     9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132,
+     83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207,
+     208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168,
+     81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210,
+     205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115,
+     96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219,
+     224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121,
+     231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8,
+     186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138,
+     112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158,
+     225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223,
+     140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22]
+    
+    private static let rbsub:[UInt8] =
+    [ 82, 9, 106, 213, 48, 54, 165, 56, 191, 64, 163, 158, 129, 243, 215, 251,
+     124, 227, 57, 130, 155, 47, 255, 135, 52, 142, 67, 68, 196, 222, 233, 203,
+     84, 123, 148, 50, 166, 194, 35, 61, 238, 76, 149, 11, 66, 250, 195, 78,
+     8, 46, 161, 102, 40, 217, 36, 178, 118, 91, 162, 73, 109, 139, 209, 37,
+     114, 248, 246, 100, 134, 104, 152, 22, 212, 164, 92, 204, 93, 101, 182, 146,
+     108, 112, 72, 80, 253, 237, 185, 218, 94, 21, 70, 87, 167, 141, 157, 132,
+     144, 216, 171, 0, 140, 188, 211, 10, 247, 228, 88, 5, 184, 179, 69, 6,
+     208, 44, 30, 143, 202, 63, 15, 2, 193, 175, 189, 3, 1, 19, 138, 107,
+     58, 145, 17, 65, 79, 103, 220, 234, 151, 242, 207, 206, 240, 180, 230, 115,
+     150, 172, 116, 34, 231, 173, 53, 133, 226, 249, 55, 232, 28, 117, 223, 110,
+     71, 241, 26, 113, 29, 41, 197, 137, 111, 183, 98, 14, 170, 24, 190, 27,
+     252, 86, 62, 75, 198, 210, 121, 32, 154, 219, 192, 254, 120, 205, 90, 244,
+     31, 221, 168, 51, 136, 7, 199, 49, 177, 18, 16, 89, 39, 128, 236, 95,
+     96, 81, 127, 169, 25, 181, 74, 13, 45, 229, 122, 159, 147, 201, 156, 239,
+     160, 224, 59, 77, 174, 42, 245, 176, 200, 235, 187, 60, 131, 83, 153, 97,
+     23, 43, 4, 126, 186, 119, 214, 38, 225, 105, 20, 99, 85, 33, 12, 125]
+    
+    private static let rco:[UInt8] =
+    [1,2,4,8,16,32,64,128,27,54,108,216,171,77,154,47]
+
+    private static let ftable:[UInt32] =
+    [0xa56363c6,0x847c7cf8,0x997777ee,0x8d7b7bf6,0xdf2f2ff,0xbd6b6bd6,
+    0xb16f6fde,0x54c5c591,0x50303060,0x3010102,0xa96767ce,0x7d2b2b56,
+    0x19fefee7,0x62d7d7b5,0xe6abab4d,0x9a7676ec,0x45caca8f,0x9d82821f,
+    0x40c9c989,0x877d7dfa,0x15fafaef,0xeb5959b2,0xc947478e,0xbf0f0fb,
+    0xecadad41,0x67d4d4b3,0xfda2a25f,0xeaafaf45,0xbf9c9c23,0xf7a4a453,
+    0x967272e4,0x5bc0c09b,0xc2b7b775,0x1cfdfde1,0xae93933d,0x6a26264c,
+    0x5a36366c,0x413f3f7e,0x2f7f7f5,0x4fcccc83,0x5c343468,0xf4a5a551,
+    0x34e5e5d1,0x8f1f1f9,0x937171e2,0x73d8d8ab,0x53313162,0x3f15152a,
+    0xc040408,0x52c7c795,0x65232346,0x5ec3c39d,0x28181830,0xa1969637,
+    0xf05050a,0xb59a9a2f,0x907070e,0x36121224,0x9b80801b,0x3de2e2df,
+    0x26ebebcd,0x6927274e,0xcdb2b27f,0x9f7575ea,0x1b090912,0x9e83831d,
+    0x742c2c58,0x2e1a1a34,0x2d1b1b36,0xb26e6edc,0xee5a5ab4,0xfba0a05b,
+    0xf65252a4,0x4d3b3b76,0x61d6d6b7,0xceb3b37d,0x7b292952,0x3ee3e3dd,
+    0x712f2f5e,0x97848413,0xf55353a6,0x68d1d1b9,0x0,0x2cededc1,
+    0x60202040,0x1ffcfce3,0xc8b1b179,0xed5b5bb6,0xbe6a6ad4,0x46cbcb8d,
+    0xd9bebe67,0x4b393972,0xde4a4a94,0xd44c4c98,0xe85858b0,0x4acfcf85,
+    0x6bd0d0bb,0x2aefefc5,0xe5aaaa4f,0x16fbfbed,0xc5434386,0xd74d4d9a,
+    0x55333366,0x94858511,0xcf45458a,0x10f9f9e9,0x6020204,0x817f7ffe,
+    0xf05050a0,0x443c3c78,0xba9f9f25,0xe3a8a84b,0xf35151a2,0xfea3a35d,
+    0xc0404080,0x8a8f8f05,0xad92923f,0xbc9d9d21,0x48383870,0x4f5f5f1,
+    0xdfbcbc63,0xc1b6b677,0x75dadaaf,0x63212142,0x30101020,0x1affffe5,
+    0xef3f3fd,0x6dd2d2bf,0x4ccdcd81,0x140c0c18,0x35131326,0x2fececc3,
+    0xe15f5fbe,0xa2979735,0xcc444488,0x3917172e,0x57c4c493,0xf2a7a755,
+    0x827e7efc,0x473d3d7a,0xac6464c8,0xe75d5dba,0x2b191932,0x957373e6,
+    0xa06060c0,0x98818119,0xd14f4f9e,0x7fdcdca3,0x66222244,0x7e2a2a54,
+    0xab90903b,0x8388880b,0xca46468c,0x29eeeec7,0xd3b8b86b,0x3c141428,
+    0x79dedea7,0xe25e5ebc,0x1d0b0b16,0x76dbdbad,0x3be0e0db,0x56323264,
+    0x4e3a3a74,0x1e0a0a14,0xdb494992,0xa06060c,0x6c242448,0xe45c5cb8,
+    0x5dc2c29f,0x6ed3d3bd,0xefacac43,0xa66262c4,0xa8919139,0xa4959531,
+    0x37e4e4d3,0x8b7979f2,0x32e7e7d5,0x43c8c88b,0x5937376e,0xb76d6dda,
+    0x8c8d8d01,0x64d5d5b1,0xd24e4e9c,0xe0a9a949,0xb46c6cd8,0xfa5656ac,
+    0x7f4f4f3,0x25eaeacf,0xaf6565ca,0x8e7a7af4,0xe9aeae47,0x18080810,
+    0xd5baba6f,0x887878f0,0x6f25254a,0x722e2e5c,0x241c1c38,0xf1a6a657,
+    0xc7b4b473,0x51c6c697,0x23e8e8cb,0x7cdddda1,0x9c7474e8,0x211f1f3e,
+    0xdd4b4b96,0xdcbdbd61,0x868b8b0d,0x858a8a0f,0x907070e0,0x423e3e7c,
+    0xc4b5b571,0xaa6666cc,0xd8484890,0x5030306,0x1f6f6f7,0x120e0e1c,
+    0xa36161c2,0x5f35356a,0xf95757ae,0xd0b9b969,0x91868617,0x58c1c199,
+    0x271d1d3a,0xb99e9e27,0x38e1e1d9,0x13f8f8eb,0xb398982b,0x33111122,
+    0xbb6969d2,0x70d9d9a9,0x898e8e07,0xa7949433,0xb69b9b2d,0x221e1e3c,
+    0x92878715,0x20e9e9c9,0x49cece87,0xff5555aa,0x78282850,0x7adfdfa5,
+    0x8f8c8c03,0xf8a1a159,0x80898909,0x170d0d1a,0xdabfbf65,0x31e6e6d7,
+    0xc6424284,0xb86868d0,0xc3414182,0xb0999929,0x772d2d5a,0x110f0f1e,
+    0xcbb0b07b,0xfc5454a8,0xd6bbbb6d,0x3a16162c]
+
+    private static let rtable:[UInt32] =
+    [0x50a7f451,0x5365417e,0xc3a4171a,0x965e273a,0xcb6bab3b,0xf1459d1f,
+    0xab58faac,0x9303e34b,0x55fa3020,0xf66d76ad,0x9176cc88,0x254c02f5,
+    0xfcd7e54f,0xd7cb2ac5,0x80443526,0x8fa362b5,0x495ab1de,0x671bba25,
+    0x980eea45,0xe1c0fe5d,0x2752fc3,0x12f04c81,0xa397468d,0xc6f9d36b,
+    0xe75f8f03,0x959c9215,0xeb7a6dbf,0xda595295,0x2d83bed4,0xd3217458,
+    0x2969e049,0x44c8c98e,0x6a89c275,0x78798ef4,0x6b3e5899,0xdd71b927,
+    0xb64fe1be,0x17ad88f0,0x66ac20c9,0xb43ace7d,0x184adf63,0x82311ae5,
+    0x60335197,0x457f5362,0xe07764b1,0x84ae6bbb,0x1ca081fe,0x942b08f9,
+    0x58684870,0x19fd458f,0x876cde94,0xb7f87b52,0x23d373ab,0xe2024b72,
+    0x578f1fe3,0x2aab5566,0x728ebb2,0x3c2b52f,0x9a7bc586,0xa50837d3,
+    0xf2872830,0xb2a5bf23,0xba6a0302,0x5c8216ed,0x2b1ccf8a,0x92b479a7,
+    0xf0f207f3,0xa1e2694e,0xcdf4da65,0xd5be0506,0x1f6234d1,0x8afea6c4,
+    0x9d532e34,0xa055f3a2,0x32e18a05,0x75ebf6a4,0x39ec830b,0xaaef6040,
+    0x69f715e,0x51106ebd,0xf98a213e,0x3d06dd96,0xae053edd,0x46bde64d,
+    0xb58d5491,0x55dc471,0x6fd40604,0xff155060,0x24fb9819,0x97e9bdd6,
+    0xcc434089,0x779ed967,0xbd42e8b0,0x888b8907,0x385b19e7,0xdbeec879,
+    0x470a7ca1,0xe90f427c,0xc91e84f8,0x0,0x83868009,0x48ed2b32,
+    0xac70111e,0x4e725a6c,0xfbff0efd,0x5638850f,0x1ed5ae3d,0x27392d36,
+    0x64d90f0a,0x21a65c68,0xd1545b9b,0x3a2e3624,0xb1670a0c,0xfe75793,
+    0xd296eeb4,0x9e919b1b,0x4fc5c080,0xa220dc61,0x694b775a,0x161a121c,
+    0xaba93e2,0xe52aa0c0,0x43e0223c,0x1d171b12,0xb0d090e,0xadc78bf2,
+    0xb9a8b62d,0xc8a91e14,0x8519f157,0x4c0775af,0xbbdd99ee,0xfd607fa3,
+    0x9f2601f7,0xbcf5725c,0xc53b6644,0x347efb5b,0x7629438b,0xdcc623cb,
+    0x68fcedb6,0x63f1e4b8,0xcadc31d7,0x10856342,0x40229713,0x2011c684,
+    0x7d244a85,0xf83dbbd2,0x1132f9ae,0x6da129c7,0x4b2f9e1d,0xf330b2dc,
+    0xec52860d,0xd0e3c177,0x6c16b32b,0x99b970a9,0xfa489411,0x2264e947,
+    0xc48cfca8,0x1a3ff0a0,0xd82c7d56,0xef903322,0xc74e4987,0xc1d138d9,
+    0xfea2ca8c,0x360bd498,0xcf81f5a6,0x28de7aa5,0x268eb7da,0xa4bfad3f,
+    0xe49d3a2c,0xd927850,0x9bcc5f6a,0x62467e54,0xc2138df6,0xe8b8d890,
+    0x5ef7392e,0xf5afc382,0xbe805d9f,0x7c93d069,0xa92dd56f,0xb31225cf,
+    0x3b99acc8,0xa77d1810,0x6e639ce8,0x7bbb3bdb,0x97826cd,0xf418596e,
+    0x1b79aec,0xa89a4f83,0x656e95e6,0x7ee6ffaa,0x8cfbc21,0xe6e815ef,
+    0xd99be7ba,0xce366f4a,0xd4099fea,0xd67cb029,0xafb2a431,0x31233f2a,
+    0x3094a5c6,0xc066a235,0x37bc4e74,0xa6ca82fc,0xb0d090e0,0x15d8a733,
+    0x4a9804f1,0xf7daec41,0xe50cd7f,0x2ff69117,0x8dd64d76,0x4db0ef43,
+    0x544daacc,0xdf0496e4,0xe3b5d19e,0x1b886a4c,0xb81f2cc1,0x7f516546,
+    0x4ea5e9d,0x5d358c01,0x737487fa,0x2e410bfb,0x5a1d67b3,0x52d2db92,
+    0x335610e9,0x1347d66d,0x8c61d79a,0x7a0ca137,0x8e14f859,0x893c13eb,
+    0xee27a9ce,0x35c961b7,0xede51ce1,0x3cb1477a,0x59dfd29c,0x3f73f255,
+    0x79ce1418,0xbf37c773,0xeacdf753,0x5baafd5f,0x146f3ddf,0x86db4478,
+    0x81f3afca,0x3ec468b9,0x2c342438,0x5f40a3c2,0x72c31d16,0xc25e2bc,
+    0x8b493c28,0x41950dff,0x7101a839,0xdeb30c08,0x9ce4b4d8,0x90c15664,
+    0x6184cb7b,0x70b632d5,0x745c6c48,0x4257b8d0]
+    
+    /* Rotates 32-bit word left by 1, 2 or 3 byte  */
+    
+    private static func ROTL8(_ x: UInt32) -> UInt32
+    {
+        return (((x)<<8)|((x)>>24))
+    }
+    
+    private static func ROTL16(_ x: UInt32) -> UInt32
+    {
+        return (((x)<<16)|((x)>>16))
+    }
+    
+    private static func ROTL24(_ x: UInt32) -> UInt32
+    {
+        return (((x)<<24)|((x)>>8))
+    }
+    
+    private static func pack(_ b: [UInt8]) -> UInt32
+    { /* pack bytes into a 32-bit Word */
+        var r=((UInt32(b[3])&0xff)<<24)|((UInt32(b[2])&0xff)<<16)
+        r = r|((UInt32(b[1])&0xff)<<8)|(UInt32(b[0])&0xff)
+        return r
+    }
+  
+    private static func unpack(_ a: UInt32) -> [UInt8]
+    { /* unpack bytes from a word */
+        let b:[UInt8]=[UInt8(a&0xff),UInt8((a>>8)&0xff),UInt8((a>>16)&0xff),UInt8((a>>24)&0xff)];
+        return b;
+    }
+    
+    private static func bmul(_ x: UInt8,_ y:UInt8) -> UInt8
+    { /* x.y= AntiLog(Log(x) + Log(y)) */
+    
+        let ix=Int(x)&0xff
+        let iy=Int(y)&0xff
+        let lx=Int(ltab[ix])&0xff
+        let ly=Int(ltab[iy])&0xff
+    
+        if x != 0 && y != 0 {return ptab[(lx+ly)%255]}
+        else {return UInt8(0)}
+    }
+    
+    private static func SubByte(_ a: UInt32) -> UInt32
+    {
+        var b=unpack(a)
+        b[0]=fbsub[Int(b[0])]
+        b[1]=fbsub[Int(b[1])]
+        b[2]=fbsub[Int(b[2])]
+        b[3]=fbsub[Int(b[3])]
+        return pack(b);
+    }
+    
+    private static func product(_ x: UInt32,_ y: UInt32) -> UInt8
+    { /* dot product of two 4-byte arrays */
+        var xb=unpack(x);
+        var yb=unpack(y);
+    
+        return (bmul(xb[0],yb[0])^bmul(xb[1],yb[1])^bmul(xb[2],yb[2])^bmul(xb[3],yb[3]))
+    }
+
+    private static func InvMixCol(_ x: UInt32) -> UInt32
+    { /* matrix Multiplication */
+        var b=[UInt8](repeating: 0,count: 4)
+        var m=pack(InCo);
+        b[3]=product(m,x);
+        m=ROTL24(m);
+        b[2]=product(m,x);
+        m=ROTL24(m);
+        b[1]=product(m,x);
+        m=ROTL24(m);
+        b[0]=product(m,x);
+        let y=pack(b)
+        return y
+    }
+  
+    private static func increment(_ f:inout [UInt8])
+    {
+        for i in 0 ..< 16
+        {
+            f[i]+=1
+            if f[i] != 0 {break}
+        }
+    }   
+
+    /* reset cipher */
+    public mutating func reset(_ m: Int,_ iv:[UInt8]?)
+    { /* reset mode, or reset iv */
+        mode=m;
+        for i in 0 ..< 16 {f[i]=0}
+        if (mode != AES.ECB) && (iv != nil)
+            {for i in 0 ..< 16 {f[i]=iv![i]}} /*??*/
+    }
+    
+    public mutating func init_it(_ m:Int,_ key:[UInt8],_ iv:[UInt8]?)
+    {   /* Key=16 bytes */
+        /* Key Scheduler. Create expanded encryption key */
+        var CipherKey=[UInt32](repeating: 0,count: 4)
+        var b=[UInt8](repeating: 0,count: 4)
+        let nk=4;
+        reset(m,iv);
+        let N=44;
+        
+        var j=0
+        for  i in 0 ..< nk
+        {
+            for k in 0 ..< 4 {b[k]=key[j+k]}
+            CipherKey[i]=AES.pack(b);
+            j+=4;
+        }
+        for i in 0 ..< nk {fkey[i]=CipherKey[i]}
+        j=nk
+        var k=0
+        while j<N
+        {
+            fkey[j]=fkey[j-nk]^AES.SubByte(AES.ROTL24(fkey[j-1]))^UInt32(AES.rco[k])
+            var i=1
+            while i<nk && (i+j)<N
+            {
+                fkey[i+j]=fkey[i+j-nk]^fkey[i+j-1]
+                i+=1
+            }
+            j+=nk
+            k+=1
+        }
+        
+        /* now for the expanded decrypt key in reverse order */
+        
+        for j in 0 ..< 4 {rkey[j+N-4]=fkey[j]}
+        var i=4
+        while i<N-4
+        {
+            let k=N-4-i;
+            for j in 0 ..< 4 {rkey[k+j]=AES.InvMixCol(fkey[i+j])}
+            i+=4
+        }
+        for j in N-4 ..< N {rkey[j-N+4]=fkey[j]}
+    }
+    
+    func getreg() -> [UInt8]
+    {
+        var ir=[UInt8](repeating: 0,count: 16)
+        for i in 0 ..< 16 {ir[i]=f[i]}
+        return ir;
+    }
+    
+    /* Encrypt a single block */
+    func ecb_encrypt(_ buff:inout [UInt8])
+    {
+        var b=[UInt8](repeating: 0,count: 4)
+        var p=[UInt32](repeating: 0,count: 4)
+        var q=[UInt32](repeating: 0,count: 4)
+    
+        var j=0
+        for i in 0 ..< 4
+        {
+            for k in 0 ..< 4 {b[k]=buff[j+k]}
+            p[i]=AES.pack(b);
+            p[i]^=fkey[i];
+            j+=4
+        }
+    
+        var k=4;
+    
+    /* State alternates between p and q */
+        for _ in 1 ..< 10
+        {
+            q[0]=fkey[k]^AES.ftable[Int(p[0]&0xff)]^AES.ROTL8(AES.ftable[Int((p[1]>>8)&0xff)])^AES.ROTL16(AES.ftable[Int((p[2]>>16)&0xff)])^AES.ROTL24(AES.ftable[Int((p[3]>>24)&0xff)])
+            
+            q[1]=fkey[k+1]^AES.ftable[Int(p[1]&0xff)]^AES.ROTL8(AES.ftable[Int((p[2]>>8)&0xff)])^AES.ROTL16(AES.ftable[Int((p[3]>>16)&0xff)])^AES.ROTL24(AES.ftable[Int((p[0]>>24)&0xff)])
+            
+            q[2]=fkey[k+2]^AES.ftable[Int(p[2]&0xff)]^AES.ROTL8(AES.ftable[Int((p[3]>>8)&0xff)])^AES.ROTL16(AES.ftable[Int((p[0]>>16)&0xff)])^AES.ROTL24(AES.ftable[Int((p[1]>>24)&0xff)])
+            
+            q[3]=fkey[k+3]^AES.ftable[Int(p[3]&0xff)]^AES.ROTL8(AES.ftable[Int((p[0]>>8)&0xff)])^AES.ROTL16(AES.ftable[Int((p[1]>>16)&0xff)])^AES.ROTL24(AES.ftable[Int((p[2]>>24)&0xff)])
+            
+            k+=4;
+            for j in 0 ..< 4
+            {
+				let t=p[j]; p[j]=q[j]; q[j]=t;
+            }
+        }
+    
+    /* Last Round */
+    
+        q[0]=fkey[k]^UInt32(AES.fbsub[Int(p[0]&0xff)])^AES.ROTL8(UInt32(AES.fbsub[Int((p[1]>>8)&0xff)]))^AES.ROTL16(UInt32(AES.fbsub[Int((p[2]>>16)&0xff)]))^AES.ROTL24(UInt32(AES.fbsub[Int((p[3]>>24)&0xff)]))
+    
+        q[1]=fkey[k+1]^UInt32(AES.fbsub[Int(p[1]&0xff)])^AES.ROTL8(UInt32(AES.fbsub[Int((p[2]>>8)&0xff)]))^AES.ROTL16(UInt32(AES.fbsub[Int((p[3]>>16)&0xff)]))^AES.ROTL24(UInt32(AES.fbsub[Int((p[0]>>24)&0xff)]))
+    
+        q[2]=fkey[k+2]^UInt32(AES.fbsub[Int(p[2]&0xff)])^AES.ROTL8(UInt32(AES.fbsub[Int((p[3]>>8)&0xff)]))^AES.ROTL16(UInt32(AES.fbsub[Int((p[0]>>16)&0xff)]))^AES.ROTL24(UInt32(AES.fbsub[Int((p[1]>>24)&0xff)]))
+    
+        q[3]=fkey[k+3]^UInt32(AES.fbsub[Int((p[3])&0xff)])^AES.ROTL8(UInt32(AES.fbsub[Int((p[0]>>8)&0xff)]))^AES.ROTL16(UInt32(AES.fbsub[Int((p[1]>>16)&0xff)]))^AES.ROTL24(UInt32(AES.fbsub[Int((p[2]>>24)&0xff)]))
+    
+        j=0
+        for i in 0 ..< 4
+        {
+            b=AES.unpack(q[i])
+            for k in 0 ..< 4 {buff[j+k]=b[k]}
+            j+=4
+        }
+    }
+    
+    /* Decrypt a single block */
+    func ecb_decrypt(_ buff:inout [UInt8])
+    {
+        var b=[UInt8](repeating: 0,count: 4)
+        var p=[UInt32](repeating: 0,count: 4)
+        var q=[UInt32](repeating: 0,count: 4)
+    
+        var j=0
+        for i in 0 ..< 4
+        {
+            for k in 0 ..< 4 {b[k]=buff[j+k]}
+            p[i]=AES.pack(b);
+            p[i]^=rkey[i];
+            j+=4
+        }
+    
+        var k=4
+    
+    /* State alternates between p and q */
+        for _ in 1 ..< 10
+        {
+            
+            q[0]=rkey[k]^AES.rtable[Int(p[0]&0xff)]^AES.ROTL8(AES.rtable[Int((p[3]>>8)&0xff)])^AES.ROTL16(AES.rtable[Int((p[2]>>16)&0xff)])^AES.ROTL24(AES.rtable[Int((p[1]>>24)&0xff)])
+            
+            q[1]=rkey[k+1]^AES.rtable[Int(p[1]&0xff)]^AES.ROTL8(AES.rtable[Int((p[0]>>8)&0xff)])^AES.ROTL16(AES.rtable[Int((p[3]>>16)&0xff)])^AES.ROTL24(AES.rtable[Int((p[2]>>24)&0xff)])
+            
+        
+            q[2]=rkey[k+2]^AES.rtable[Int(p[2]&0xff)]^AES.ROTL8(AES.rtable[Int((p[1]>>8)&0xff)])^AES.ROTL16(AES.rtable[Int((p[0]>>16)&0xff)])^AES.ROTL24(AES.rtable[Int((p[3]>>24)&0xff)])
+       
+            q[3]=rkey[k+3]^AES.rtable[Int(p[3]&0xff)]^AES.ROTL8(AES.rtable[Int((p[2]>>8)&0xff)])^AES.ROTL16(AES.rtable[Int((p[1]>>16)&0xff)])^AES.ROTL24(AES.rtable[Int((p[0]>>24)&0xff)])
+            
+    
+            k+=4;
+            for j in 0 ..< 4
+            {
+				let t=p[j]; p[j]=q[j]; q[j]=t;
+            }
+        }
+    
+    /* Last Round */
+        
+        q[0]=rkey[k]^UInt32(AES.rbsub[Int(p[0]&0xff)])^AES.ROTL8(UInt32(AES.rbsub[Int((p[3]>>8)&0xff)]))^AES.ROTL16(UInt32(AES.rbsub[Int((p[2]>>16)&0xff)]))^AES.ROTL24(UInt32(AES.rbsub[Int((p[1]>>24)&0xff)]))
+        
+        q[1]=rkey[k+1]^UInt32(AES.rbsub[Int(p[1]&0xff)])^AES.ROTL8(UInt32(AES.rbsub[Int((p[0]>>8)&0xff)]))^AES.ROTL16(UInt32(AES.rbsub[Int((p[3]>>16)&0xff)]))^AES.ROTL24(UInt32(AES.rbsub[Int((p[2]>>24)&0xff)]))
+        
+        
+        q[2]=rkey[k+2]^UInt32(AES.rbsub[Int(p[2]&0xff)])^AES.ROTL8(UInt32(AES.rbsub[Int((p[1]>>8)&0xff)]))^AES.ROTL16(UInt32(AES.rbsub[Int((p[0]>>16)&0xff)]))^AES.ROTL24(UInt32(AES.rbsub[Int((p[3]>>24)&0xff)]))
+
+        q[3]=rkey[k+3]^UInt32(AES.rbsub[Int((p[3])&0xff)])^AES.ROTL8(UInt32(AES.rbsub[Int((p[2]>>8)&0xff)]))^AES.ROTL16(UInt32(AES.rbsub[Int((p[1]>>16)&0xff)]))^AES.ROTL24(UInt32(AES.rbsub[Int((p[0]>>24)&0xff)]))
+    
+        j=0
+        for i in 0 ..< 4
+        {
+            b=AES.unpack(q[i]);
+            for k in 0 ..< 4 {buff[j+k]=b[k]}
+            j+=4
+        }
+    }
+    
+    /* Encrypt using selected mode of operation */
+    @discardableResult public mutating func encrypt(_ buff:inout [UInt8]) -> UInt32
+    {
+        var st=[UInt8](repeating: 0,count: 16)
+    
+    // Supported Modes of Operation
+    
+        var fell_off:UInt32=0;
+        switch (mode)
+        {
+        case AES.ECB:
+            ecb_encrypt(&buff)
+            return 0
+        case AES.CBC:
+            for j in 0 ..< 16 {buff[j]^=f[j]}
+            ecb_encrypt(&buff);
+            for j in 0 ..< 16 {f[j]=buff[j]}
+            return 0;
+    
+        case AES.CFB1:
+            fallthrough
+        case AES.CFB2:
+            fallthrough
+        case AES.CFB4:
+            let bytes=mode-AES.CFB1+1
+            for j in 0 ..< bytes {fell_off=(fell_off<<8)|UInt32(f[j])}
+            for j in 0 ..< 16 {st[j]=f[j]}
+            for j in bytes ..< 16 {f[j-bytes]=f[j]}
+            ecb_encrypt(&st);
+            for j in 0 ..< bytes
+            {
+				buff[j]^=st[j];
+				f[16-bytes+j]=buff[j];
+            }
+            return fell_off;
+    
+        case AES.OFB1:
+            fallthrough
+        case AES.OFB2:
+            fallthrough
+        case AES.OFB4:
+            fallthrough
+        case AES.OFB8:
+            fallthrough
+        case AES.OFB16:
+    
+            let bytes=mode-AES.OFB1+1
+            ecb_encrypt(&f)
+            for j in 0 ..< bytes {buff[j]^=f[j]}
+            return 0;
+    
+        case AES.CTR1:
+            fallthrough
+        case AES.CTR2:
+            fallthrough
+        case AES.CTR4:
+            fallthrough
+        case AES.CTR8:
+            fallthrough
+        case AES.CTR16:
+            let bytes=mode-AES.CTR1+1
+            for j in 0 ..< 16 {st[j]=f[j]}
+            ecb_encrypt(&st)
+            for j in 0 ..< bytes {buff[j]^=st[j]}
+            AES.increment(&f)
+            return 0
+
+        default:
+            return 0;
+        }
+    }
+    
+    /* Decrypt using selected mode of operation */
+    @discardableResult public mutating func decrypt(_ buff:inout [UInt8]) -> UInt32
+    {
+
+        var st=[UInt8](repeating: 0,count: 16)
+        
+        // Supported Modes of Operation
+        
+        var fell_off:UInt32=0;
+        switch (mode)
+        {
+        case AES.ECB:
+            ecb_decrypt(&buff);
+            return 0;
+        case AES.CBC:
+            for j in 0 ..< 16
+            {
+				st[j]=f[j];
+				f[j]=buff[j];
+            }
+            ecb_decrypt(&buff);
+            for j in 0 ..< 16
+            {
+				buff[j]^=st[j];
+				st[j]=0;
+            }
+            return 0;
+        case AES.CFB1:
+            fallthrough
+        case AES.CFB2:
+            fallthrough
+        case AES.CFB4:
+            let bytes=mode-AES.CFB1+1;
+            for j in 0 ..< bytes {fell_off=(fell_off<<8)|UInt32(f[j])}
+            for j in 0 ..< 16 {st[j]=f[j]}
+            for j in bytes ..< 16 {f[j-bytes]=f[j]}
+            ecb_encrypt(&st);
+            for j in 0 ..< bytes
+            {
+				f[16-bytes+j]=buff[j]
+				buff[j]^=st[j]
+            }
+            return fell_off
+        case AES.OFB1:
+            fallthrough
+        case AES.OFB2:
+            fallthrough
+        case AES.OFB4:
+            fallthrough
+        case AES.OFB8:
+            fallthrough
+        case AES.OFB16:
+            let bytes=mode-AES.OFB1+1
+            ecb_encrypt(&f);
+            for j in 0 ..< bytes {buff[j]^=f[j]}
+            return 0;
+
+        case AES.CTR1:
+            fallthrough
+        case AES.CTR2:
+            fallthrough
+        case AES.CTR4:
+            fallthrough
+        case AES.CTR8:
+            fallthrough
+        case AES.CTR16:
+            let bytes=mode-AES.CTR1+1
+            for j in 0 ..< 16 {st[j]=f[j]}
+            ecb_encrypt(&st)
+            for j in 0 ..< bytes {buff[j]^=st[j]}
+            AES.increment(&f)
+            return 0
+
+        default:
+            return 0;
+        }
+    }
+        
+    /* Clean up and delete left-overs */
+    public mutating func end()
+    { // clean up
+        for i in 0 ..< 44
+            {fkey[i]=0; rkey[i]=0}
+        for i in 0 ..< 16
+            {f[i]=0}
+    }
+    
+}
diff --git a/version3/swift/big.swift b/version3/swift/big.swift
new file mode 100644
index 0000000..f87ca0c
--- /dev/null
+++ b/version3/swift/big.swift
@@ -0,0 +1,1150 @@
+/*
+	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.
+*/
+
+//
+//  big.swift
+//
+//  Created by Michael Scott on 12/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//  BIG number class
+//
+
+import amcl
+
+#if D32
+public typealias Chunk = Int32
+public typealias DChunk = Int64
+#endif
+
+#if D64
+public typealias Chunk = Int64
+#endif
+
+
+public struct BIG{
+#if D32
+    static public let CHUNK:Int=32
+    static let BASEBITS:UInt = @BASE32@    
+#endif
+#if D64
+    static public let CHUNK:Int=64
+    static let BASEBITS:UInt = @BASE64@    
+#endif
+
+    static let MODBYTES:UInt = @NB@
+
+
+    static let NLEN:Int=Int(1+((8*BIG.MODBYTES-1)/BIG.BASEBITS))
+    static let DNLEN:Int=2*BIG.NLEN
+    static let BMASK:Chunk=((1<<Chunk(BIG.BASEBITS))-1)
+    static let HBITS = (BIG.BASEBITS/2)
+    static let HMASK:Chunk = ((1<<Chunk(BIG.HBITS))-1) 
+    static let NEXCESS:Int = (1<<(BIG.CHUNK-Int(BIG.BASEBITS)-1))
+    static let BIGBITS:UInt = (BIG.MODBYTES*8)
+
+    var w=[Chunk](repeating: 0,count: NLEN)
+/* Constructors */
+    init() {
+        for i in 0 ..< BIG.NLEN {w[i]=0}
+    }
+    init(_ x: Int)
+    {
+        w[0]=Chunk(x);
+        for i in 1 ..< BIG.NLEN {w[i]=0}
+    }
+    init(_ x: BIG)
+    {
+        for i in 0 ..< BIG.NLEN {w[i]=x.w[i]}
+    }
+    init(_ x: DBIG)
+    {
+        for i in 0 ..< BIG.NLEN {w[i]=x.w[i]}
+    }
+    public init(_ x: [Chunk])
+    {
+        for i in 0 ..< BIG.NLEN {w[i]=x[i]}
+    }
+    func get(_ i: Int) -> Chunk
+    {
+        return w[i]
+    }
+    mutating func set(_ i: Int,_ x: Chunk)
+    {
+        w[i]=x
+    }
+    mutating func xortop(_ x: Chunk)
+    {
+        w[BIG.NLEN-1]^=x
+    }
+    mutating func ortop(_ x: Chunk)
+    {
+        w[BIG.NLEN-1]|=x
+    }
+
+#if D32
+
+    static func muladd(_ a: Chunk,_ b: Chunk,_ c: Chunk,_ r: Chunk) -> (Chunk,Chunk)
+    {
+        let prod:DChunk = DChunk(a)*DChunk(b)+DChunk(c)+DChunk(r)
+        let bot=Chunk(prod&DChunk(BIG.BMASK))
+        let top=Chunk(prod>>DChunk(BIG.BASEBITS))
+        return (top,bot)
+    }
+#endif
+#if D64
+
+    static func muladd(_ a: Chunk,_ b: Chunk,_ c: Chunk,_ r: Chunk) -> (Chunk,Chunk)
+    {
+	let (tp,bt)=a.multipliedFullWidth(by: b)
+	var bot = Chunk(bt)&BIG.BMASK
+	var top = (tp << Chunk(64-BIG.BASEBITS)) | Chunk(bt >> BIG.BASEBITS)
+/*
+        let x0=a&BIG.HMASK;
+        let x1=(a>>Chunk(BIG.HBITS))
+        let y0=b&BIG.HMASK;
+        let y1=(b>>Chunk(BIG.HBITS))
+        var bot=x0*y0
+        var top=x1*y1
+        let mid=x0*y1+x1*y0
+        let u0=mid&BIG.HMASK
+        let u1=(mid>>Chunk(BIG.HBITS))
+        bot=bot+(u0<<Chunk(BIG.HBITS))
+	top+=u1
+*/
+        bot+=c; bot+=r
+        let carry=bot>>Chunk(BIG.BASEBITS)
+        bot &= BIG.BMASK
+        top+=carry
+        return (top,bot)
+    }
+    
+#endif
+    /* test for zero */
+    func iszilch() -> Bool
+    {
+        for i in 0 ..< BIG.NLEN {if w[i] != 0 {return false}}
+        return true
+    }
+/* set to zero */
+    mutating func zero()
+    {
+        for i in 0 ..< BIG.NLEN {w[i] = 0}
+    }
+/* set to one */
+    mutating func one()
+    {
+        w[0]=1
+        for i in 1 ..< BIG.NLEN {w[i]=0}
+    }
+/* Test for equal to one */
+    func isunity() -> Bool
+    {
+        for i in 1 ..< BIG.NLEN {if w[i] != 0 {return false}}
+        if w[0] != 1 {return false}
+        return true
+    }
+/* Copy from another BIG */
+    mutating func copy(_ x: BIG)
+    {
+        for i in 0 ..< BIG.NLEN {w[i] = x.w[i]}
+    }
+    mutating func copy(_ x: DBIG)
+    {
+        for i in 0 ..< BIG.NLEN {w[i] = x.w[i]}
+    }
+/* Conditional swap of two bigs depending on d using XOR - no branches */
+    mutating func cswap(_ b: inout BIG,_ d: Int)
+    {
+        var c = Chunk(d)
+        c = ~(c-1)
+        for i in 0 ..< BIG.NLEN
+        {
+            let t=c&(w[i]^b.w[i])
+            w[i]^=t
+            b.w[i]^=t
+        }
+    }
+    mutating func cmove(_ g: BIG,_ d: Int)
+    {
+        let b=Chunk(-d)
+        for i in 0 ..< BIG.NLEN
+        {
+            w[i]^=(w[i]^g.w[i])&b;
+        }
+    }
+/* normalise BIG - force all digits < 2^BIG.BASEBITS */
+    @discardableResult mutating func norm() -> Chunk
+    {
+        var carry=Chunk(0);
+        for i in 0 ..< BIG.NLEN-1
+        {
+            let d=w[i]+carry
+            w[i]=d&BIG.BMASK
+            carry=d>>Chunk(BIG.BASEBITS)
+        }
+        w[BIG.NLEN-1]+=carry
+        return (w[BIG.NLEN-1]>>Chunk((8*BIG.MODBYTES)%BIG.BASEBITS))
+    }
+/* Shift right by less than a word */
+    @discardableResult mutating func fshr(_ k: UInt) -> Int
+    {
+        let kw=Chunk(k);
+        let r=w[0]&((Chunk(1)<<kw)-1)
+        for i in 0 ..< BIG.NLEN-1
+        {
+            w[i]=(w[i]>>kw)|((w[i+1]<<(Chunk(BIG.BASEBITS)-kw))&BIG.BMASK)
+        }
+        w[BIG.NLEN-1]>>=kw;
+        return Int(r)
+    }
+/* general shift right */
+    mutating func shr(_ k: UInt)
+    {
+        let n=k%BIG.BASEBITS
+        let m=Int(k/BIG.BASEBITS)
+        for i in 0 ..< BIG.NLEN-m-1
+        {
+            w[i]=(w[m+i]>>Chunk(n))|((w[m+i+1]<<Chunk(BIG.BASEBITS-n))&BIG.BMASK)
+        }
+        w[BIG.NLEN - m - 1]=w[BIG.NLEN-1]>>Chunk(n)
+        for i in BIG.NLEN - m ..< BIG.NLEN {w[i]=0}
+    }
+/* Shift right by less than a word */
+    @discardableResult mutating func fshl(_ k: Int) -> Int
+    {
+        let kw=Chunk(k)
+        w[BIG.NLEN-1]=((w[BIG.NLEN-1]<<kw))|(w[BIG.NLEN-2]>>(Chunk(BIG.BASEBITS)-kw))
+        for i in (1...BIG.NLEN-2).reversed()
+        {
+            w[i]=((w[i]<<kw)&BIG.BMASK)|(w[i-1]>>(Chunk(BIG.BASEBITS)-kw))
+        }
+        w[0]=(w[0]<<kw)&BIG.BMASK
+        return Int(w[BIG.NLEN-1]>>Chunk((8*BIG.MODBYTES)%BIG.BASEBITS))
+    }
+/* general shift left */
+    mutating func shl(_ k: UInt)
+    {
+        let n=k%BIG.BASEBITS
+        let m=Int(k/BIG.BASEBITS)
+        
+        w[BIG.NLEN-1]=(w[BIG.NLEN-1-m]<<Chunk(n))
+        if BIG.NLEN>=m+2 {w[BIG.NLEN-1]|=(w[BIG.NLEN-m-2]>>Chunk(BIG.BASEBITS-n))}
+        for i in (m+1...BIG.NLEN-2).reversed()
+        {
+            w[i]=((w[i-m]<<Chunk(n))&BIG.BMASK)|(w[i-m-1]>>Chunk(BIG.BASEBITS-n))
+        }
+        w[m]=(w[0]<<Chunk(n))&BIG.BMASK
+        for i in 0 ..< m {w[i]=0}
+    }
+/* return number of bits */
+    func nbits() -> Int
+    {
+        var k=(BIG.NLEN-1)
+        var t=BIG(self)
+        t.norm()
+        while k>=0 && t.w[k]==0 {k -= 1}
+        if k<0 {return 0}
+        var bts=Int(BIG.BASEBITS)*k
+        var c=t.w[k];
+        while c != 0 {c/=2; bts += 1}
+        return bts
+    }
+    func toRawString() -> String
+    {
+        var s:String="("
+        for i in 0 ..< BIG.NLEN-1
+        {
+            let n=String(w[i],radix:16,uppercase:false)
+            s+=n
+            s+=","
+            
+        }
+        let n=String(w[BIG.NLEN-1],radix:16,uppercase:false)
+        s+=n
+        s+=")"
+        return s
+    }
+/* Convert to Hex String */
+    func toString() -> String
+    {
+        _ = BIG()
+        var s:String=""
+        var len=nbits()
+        if len%4 == 0 {len/=4}
+        else {len/=4; len += 1}
+        if len<2*Int(BIG.MODBYTES) {len=2*Int(BIG.MODBYTES)}
+
+        for i in (0...len-1).reversed()
+        {
+            var b = BIG(self)
+            b.shr(UInt(i*4))
+            let n=String(b.w[0]&15,radix:16,uppercase:false)
+            s+=n
+        }
+        
+        return s
+    }
+/* return this+x */
+    func plus(_ x: BIG) -> BIG
+    {
+        var s=BIG()
+        for i in 0 ..< BIG.NLEN
+        {
+            s.w[i]=w[i]+x.w[i]
+        }
+        return s
+    }
+/* this+=x */
+    mutating func add(_ x: BIG)
+    {
+        for i in 0 ..< BIG.NLEN
+        {
+            w[i]+=x.w[i]
+        }
+    }
+
+/* this|=x */
+    mutating func or(_ x: BIG)
+    {
+        for i in 0 ..< BIG.NLEN
+        {
+            w[i]|=x.w[i]
+        }
+    }
+
+/* this+=x, where x is int */
+    mutating func inc(_ x: Int) {
+        norm();
+        w[0]+=Chunk(x);
+    }
+/* return this.x */
+   	func minus(_ x: BIG) -> BIG
+    {
+        var d=BIG();
+        for i in 0 ..< BIG.NLEN
+        {
+            d.w[i]=w[i]-x.w[i];
+        }
+        return d;
+    }
+/* this-=x */
+    mutating func sub(_ x: BIG)
+    {
+        for i in 0 ..< BIG.NLEN
+        {
+            w[i]-=x.w[i]
+        }
+    }
+/* reverse subtract this=x-this */
+    mutating func rsub(_ x: BIG)
+    {
+        for i in 0 ..< BIG.NLEN
+        {
+            w[i]=x.w[i]-w[i]
+        }
+    }
+/* this-=x where x is int */
+    mutating func dec(_ x: Int) {
+        norm();
+        w[0]-=Chunk(x);
+    }
+/* this*=x, where x is small int<NEXCESS */
+    mutating func imul(_ c: Int)
+    {
+        for i in 0 ..< BIG.NLEN {w[i]*=Chunk(c)}
+    }
+/* convert this BIG to byte array */
+    func tobytearray(_ b: inout [UInt8],_ n: Int)
+    {
+        //norm();
+        var c=BIG(self);
+        c.norm()
+        for i in (0...Int(BIG.MODBYTES)-1).reversed()
+        {
+            b[i+n]=UInt8(c.w[0]&0xff);
+            c.fshr(8);
+        }
+    }
+/* convert from byte array to BIG */
+    static func frombytearray(_ b: [UInt8],_ n: Int) -> BIG
+    {
+        var m=BIG();
+    
+        for i in 0 ..< Int(BIG.MODBYTES)
+        {
+            m.fshl(8)
+            m.w[0]+=Chunk(b[i+n])&0xff    //(int)b[i+n]&0xff;
+        }
+        return m;
+    }
+    func toBytes(_ b: inout [UInt8])
+    {
+        tobytearray(&b,0)
+    }
+    static func fromBytes(_ b: [UInt8]) -> BIG
+    {
+        return frombytearray(b,0)
+    }
+/* set this[i]+=x*y+c, and return high part
+    func muladd(_ x: Int32,_ y: Int32,_ c: Int32,_ i: Int) -> Int32
+    {
+        let prod:DChunk = DChunk(x)*DChunk(y)+DChunk(c)+DChunk(w[i])
+        w[i]=Int32(prod&DChunk(BIG.BMASK))
+        return Int32(prod>>DChunk(BIG.BASEBITS))
+    } */
+
+/* this*=x, where x is >NEXCESS */
+    @discardableResult mutating func pmul(_ c: Int) -> Chunk
+    {
+        var carry=Chunk(0);
+        //norm();
+        for i in 0 ..< BIG.NLEN
+        {
+            let ak=w[i]
+            let (top,bot)=BIG.muladd(ak,Chunk(c),carry,Chunk(0))
+            carry=top; w[i]=bot;
+        }
+        return carry;
+    }
+/* this*=c and catch overflow in DBIG */
+    mutating func pxmul(_ c: Int) -> DBIG
+    {
+        var m=DBIG()
+        var carry=Chunk(0)
+        for j in 0 ..< BIG.NLEN
+        {
+            let (top,bot)=BIG.muladd(w[j],Chunk(c),carry,m.w[j])
+            carry=top; m.w[j]=bot
+        }
+        m.w[BIG.NLEN]=carry
+        return m;
+    }
+/* divide by 3 */
+    mutating func div3() -> Chunk
+    {
+        var carry=Chunk(0)
+        norm();
+        let base=Chunk(1<<BIG.BASEBITS);
+        for i in (0...BIG.NLEN-1).reversed()
+        {
+            let ak=(carry*base+w[i]);
+            w[i]=ak/3;
+            carry=ak%3;
+        }
+        return carry;
+    }
+/* return a*b where result fits in a BIG */
+    static func smul(_ a: BIG,_ b: BIG) -> BIG
+    {
+        var c=BIG()
+        for i in 0 ..< BIG.NLEN
+        {
+            var carry=Chunk(0)
+            for j in 0 ..< BIG.NLEN
+            {
+                if (i+j<BIG.NLEN) {
+                    let (top,bot)=BIG.muladd(a.w[i],b.w[j],carry,c.w[i+j])
+                    carry=top; c.w[i+j]=bot
+                    //carry=c.muladd(a.w[i],b.w[j],carry,i+j)
+                }
+            }
+        }
+        return c;
+    }
+/* Compare a and b, return 0 if a==b, -1 if a<b, +1 if a>b. Inputs must be normalised */
+    static func comp(_ a: BIG,_ b: BIG) -> Int
+    {
+        for i in (0...BIG.NLEN-1).reversed()
+        {
+            if (a.w[i]==b.w[i]) {continue}
+            if (a.w[i]>b.w[i]) {return 1}
+            else  {return -1}
+        }
+        return 0;
+    }
+/* set x = x mod 2^m */
+    mutating func mod2m(_ m: UInt)
+    {
+        let wd=Int(m/BIG.BASEBITS)
+        let bt=m%BIG.BASEBITS
+        let msk=Chunk(1<<bt)-1;
+        w[wd]&=msk;
+        for i in wd+1 ..< BIG.NLEN {w[i]=0}
+    }
+/* Arazi and Qi inversion mod 256 */
+    static func invmod256(_ a: Int) -> Int
+    {
+        var t1:Int=0
+        var c=(a>>1)&1
+        t1+=c
+        t1&=1
+        t1=2-t1
+        t1<<=1
+        var U=t1+1
+    
+    // i=2
+        var b=a&3
+        t1=U*b; t1>>=2
+        c=(a>>2)&3
+        var t2=(U*c)&3
+        t1+=t2
+        t1*=U; t1&=3
+        t1=4-t1
+        t1<<=2
+        U+=t1
+    
+    // i=4
+        b=a&15
+        t1=U*b; t1>>=4
+        c=(a>>4)&15
+        t2=(U*c)&15
+        t1+=t2
+        t1*=U; t1&=15
+        t1=16-t1
+        t1<<=4
+        U+=t1
+    
+        return U
+    }
+/* return parity */
+    func parity() -> Int
+    {
+        return Int(w[0]%2)
+    }
+    
+/* return n-th bit */
+    func bit(_ n: UInt) -> Int
+    {
+        if ((w[Int(n/BIG.BASEBITS)]&(1<<Chunk(n%BIG.BASEBITS)))>0) {return 1;}
+        else {return 0;}
+    }
+    
+    /* return n last bits */
+    mutating func lastbits(_ n: UInt) -> Int
+    {
+        let msk=(Chunk(1)<<Chunk(n))-1;
+        norm();
+        return Int((w[0])&msk)
+    }
+/* a=1/a mod 2^256. This is very fast! */
+    mutating func invmod2m()
+    {
+        var U=BIG()
+        var b=BIG()
+        var c=BIG()
+    
+        U.inc(BIG.invmod256(lastbits(8)))
+    
+        var i=UInt(8)
+        while (i<BIG.BIGBITS)
+        {
+            U.norm();
+            b.copy(self)
+            b.mod2m(i)
+            var t1=BIG.smul(U,b)
+            t1.shr(i)
+            c.copy(self)
+            c.shr(i)
+            c.mod2m(i)
+    
+            var t2=BIG.smul(U,c)
+            t2.mod2m(i)
+            t1.add(t2); t1.norm()
+            b=BIG.smul(t1,U)
+            t1.copy(b)
+            t1.mod2m(i)
+    
+            t2.one(); t2.shl(i); t1.rsub(t2); t1.norm()
+            t1.shl(i)
+            U.add(t1)
+            i<<=1
+        }
+        U.mod2m(BIG.BIGBITS)
+        self.copy(U)
+        self.norm()
+    }
+    /* reduce this mod m */
+    mutating func mod(_ m1: BIG)
+    {
+        var k=0
+        var m=BIG(m1)
+        var r=BIG(0)
+        norm()
+        if (BIG.comp(self,m)<0) {return}
+        repeat
+        {
+            m.fshl(1)
+            k += 1
+        } while (BIG.comp(self,m)>=0)
+    
+        while (k>0)
+        {
+            m.fshr(1)
+
+		r.copy(self)
+		r.sub(m)
+		r.norm()
+		cmove(r,Int(1-((r.w[BIG.NLEN-1]>>Chunk(BIG.CHUNK-1))&1)))
+/*
+            if (BIG.comp(self,m)>=0)
+            {
+				sub(m)
+				norm()
+            } */
+            k -= 1
+        }
+    }
+    /* divide this by m */
+    mutating func div(_ m1: BIG)
+    {
+        var k=0
+        norm()
+        var e=BIG(1)
+        var b=BIG(self)
+        var r=BIG(0)
+        var m=BIG(m1)
+        zero()
+    
+        while (BIG.comp(b,m)>=0)
+        {
+            e.fshl(1)
+            m.fshl(1)
+            k += 1
+        }
+    
+        while (k>0)
+        {
+            m.fshr(1)
+            e.fshr(1)
+
+		r.copy(b)
+		r.sub(m)
+		r.norm()
+		let d=Int(1-((r.w[BIG.NLEN-1]>>Chunk(BIG.CHUNK-1))&1))
+		b.cmove(r,d)
+		r.copy(self)
+		r.add(e)
+		r.norm()
+		cmove(r,d)
+/*
+            if (BIG.comp(b,m)>=0)
+            {
+				add(e)
+				norm()
+				b.sub(m)
+				b.norm()
+            } */
+            k -= 1;
+        }
+    }
+    /* get 8*BIG.MODBYTES size random number */
+    static func random(_ rng: inout RAND) -> BIG
+    {
+        var m=BIG();
+        var j:Int=0
+        var r:UInt8=0
+        /* generate random BIG */
+        for _ in 0 ..< Int(8*BIG.MODBYTES)
+        {
+            if (j==0) {r=rng.getByte()}
+            else {r>>=1}
+    
+            let b=Chunk(r&1);
+            m.shl(1); m.w[0]+=b;// m.inc(b);
+            j += 1; j&=7;
+        }
+        return m;
+    }
+    
+    /* Create random BIG in portable way, one bit at a time, less than q */
+    static public func randomnum(_ q: BIG,_ rng: inout RAND) -> BIG
+    {
+        var d=DBIG(0);
+        var j:Int=0
+        var r:UInt8=0
+        
+        for _ in 0 ..< 2*q.nbits()
+        {
+            if (j==0) {r=rng.getByte()}
+            else {r>>=1}
+    
+            let b=Chunk(r&1);
+            d.shl(1); d.w[0]+=b; // m.inc(b);
+            j += 1; j&=7;
+        }
+        let m=d.mod(q);
+        return m;
+    }
+    
+    /* return NAF value as +/- 1, 3 or 5. x and x3 should be normed.
+    nbs is number of bits processed, and nzs is number of trailing 0s detected
+    static func nafbits(_ x: BIG,_ x3:BIG ,i:Int) -> [Chunk]
+    {
+        var j:Int
+        var n=[Chunk](repeating: 0,count: 3)
+        var nb=x3.bit(UInt(i))-x.bit(UInt(i))
+        n[1]=1;
+        n[0]=0;
+        if (nb==0) {n[0]=0; return n}
+        if (i==0) {n[0]=Chunk(nb); return n}
+        if (nb>0) {n[0]=1}
+        else      {n[0]=(-1)}
+    
+        j=i-1
+        while (true)
+        {
+            n[1] += 1
+            n[0]*=2
+            nb=x3.bit(UInt(j))-x.bit(UInt(j))
+            if (nb>0) {n[0]+=1}
+            if (nb<0) {n[0]-=1}
+            if (n[0]>5 || n[0] < -5) {break}
+            j-=1
+            if j==0 {break}
+        }
+    
+        if ((n[0]%2 != 0) && (j != 0))
+        { // backtrack 
+            if (nb>0) {n[0]=(n[0]-1)/2}
+            if (nb<0) {n[0]=(n[0]+1)/2}
+            n[1] -= 1;
+        }
+        while (n[0]%2==0)
+        { // remove trailing zeros 
+            n[0]/=2
+            n[2] += 1
+            n[1] -= 1
+        }
+        return n;
+    } */
+    
+    /* Jacobi Symbol (this/p). Returns 0, 1 or -1 */
+    mutating func jacobi(_ p: BIG) -> Int
+    {
+        var n8:Int
+        var k:Int
+        var m:Int=0;
+        var t=BIG()
+        var x=BIG()
+        var n=BIG()
+        let zilch=BIG()
+        let one=BIG(1)
+        if (p.parity()==0 || BIG.comp(self,zilch)==0 || BIG.comp(p,one)<=0) {return 0}
+        norm()
+        x.copy(self)
+        n.copy(p)
+        x.mod(p)
+    
+        while (BIG.comp(n,one)>0)
+        {
+            if (BIG.comp(x,zilch)==0) {return 0}
+            n8=n.lastbits(3)
+            k=0
+            while (x.parity()==0)
+            {
+				k += 1
+				x.shr(1)
+            }
+            if (k%2==1) {m+=((n8*n8-1)/8)}
+            let w=Int(x.lastbits(2)-1)
+            m+=(n8-1)*w/4
+            t.copy(n)
+            t.mod(x)
+            n.copy(x)
+            x.copy(t)
+            m%=2
+    
+        }
+        if (m==0) {return 1}
+        else {return -1}
+    }
+    /* this=1/this mod p. Binary method */
+    mutating func invmodp(_ p: BIG)
+    {
+        mod(p)
+        var u=BIG(self)
+        var v=BIG(p)
+        var x1=BIG(1)
+        var x2=BIG()
+        var t=BIG()
+        let one=BIG(1)
+    
+        while ((BIG.comp(u,one) != 0 ) && (BIG.comp(v,one) != 0 ))
+        {
+            while (u.parity()==0)
+            {
+				u.fshr(1);
+				if (x1.parity() != 0 )
+				{
+                    x1.add(p);
+                    x1.norm();
+				}
+				x1.fshr(1);
+            }
+            while (v.parity()==0)
+            {
+				v.fshr(1);
+				if (x2.parity() != 0 )
+				{
+                    x2.add(p);
+                    x2.norm();
+				}
+				x2.fshr(1);
+            }
+            if (BIG.comp(u,v)>=0)
+            {
+				u.sub(v);
+				u.norm();
+                if (BIG.comp(x1,x2)>=0) {x1.sub(x2)}
+				else
+				{
+                    t.copy(p);
+                    t.sub(x2);
+                    x1.add(t);
+				}
+				x1.norm();
+            }
+            else
+            {
+				v.sub(u);
+				v.norm();
+                if (BIG.comp(x2,x1)>=0) {x2.sub(x1)}
+				else
+				{
+                    t.copy(p);
+                    t.sub(x1);
+                    x2.add(t);
+				}
+				x2.norm();
+            }
+        }
+        if (BIG.comp(u,one)==0) {copy(x1)}
+        else {copy(x2)}
+    }
+    /* return a*b as DBIG */
+#if D32
+    static func mul(_ a: BIG,_ b:BIG) -> DBIG
+    {
+        var t:DChunk
+        var co:DChunk
+        var c=DBIG()
+        let RM:DChunk=DChunk(BIG.BMASK);
+        let RB:DChunk=DChunk(BIG.BASEBITS)
+   //     a.norm();
+   //     b.norm();
+        
+        var d=[DChunk](repeating: 0,count: BIG.NLEN)
+        var s:DChunk
+        for i in 0 ..< BIG.NLEN
+        {
+            d[i]=DChunk(a.w[i])*DChunk(b.w[i]);
+        }
+        s=d[0]
+        t=s; c.w[0]=Chunk(t&RM); co=t>>RB
+        for k in 1 ..< BIG.NLEN
+        {
+            s+=d[k]; t=co+s;
+            for i in 1+k/2...k
+                {t+=DChunk(a.w[i]-a.w[k-i])*DChunk(b.w[k-i]-b.w[i])}
+            c.w[k]=Chunk(t&RM); co=t>>RB
+        }
+        for k in BIG.NLEN ..< 2*BIG.NLEN-1
+        {
+            s-=d[k-BIG.NLEN]; t=co+s;
+  
+            //for var i=BIG.NLEN-1;i>=1+k/2;i--
+            var i=1+k/2
+            while i<BIG.NLEN
+            //for i in 1+k/2...BIG.NLEN-1
+            {
+                t+=DChunk(a.w[i]-a.w[k-i])*DChunk(b.w[k-i]-b.w[i])
+                i+=1
+            }
+        
+            c.w[k]=Chunk(t&RM); co=t>>RB
+        }
+        c.w[2*BIG.NLEN-1]=Chunk(co);
+        
+        return c
+    }
+    
+    /* return a^2 as DBIG */
+    static func sqr(_ a: BIG) -> DBIG
+    {
+        var t:DChunk
+        var co:DChunk
+        var c=DBIG()
+        let RM:DChunk=DChunk(BIG.BMASK);
+        let RB:DChunk=DChunk(BIG.BASEBITS)
+   //     a.norm();
+
+        t=DChunk(a.w[0])*DChunk(a.w[0])
+        c.w[0]=Chunk(t&RM); co=t>>RB
+        var j:Int
+        j=1
+        while j<BIG.NLEN-1
+        {
+            t=DChunk(a.w[j])*DChunk(a.w[0]); for  i in 1 ..< (j+1)/2 {t+=DChunk(a.w[j-i])*DChunk(a.w[i])}; t+=t;  t+=co 
+            c.w[j]=Chunk(t&RM); co=t>>RB
+            j+=1
+            t=DChunk(a.w[j])*DChunk(a.w[0]); for  i in 1 ..< (j+1)/2 {t+=DChunk(a.w[j-i])*DChunk(a.w[i])}; t+=t; t+=co; t+=DChunk(a.w[j/2])*DChunk(a.w[j/2]) 
+            c.w[j]=Chunk(t&RM); co=t>>RB
+            j+=1
+        }
+
+        j=BIG.NLEN-1+(BIG.NLEN%2)
+        while j<BIG.DNLEN-3
+        {
+            t=DChunk(a.w[BIG.NLEN-1])*DChunk(a.w[j-BIG.NLEN+1]); for i in j-BIG.NLEN+2 ..< (j+1)/2 {t+=DChunk(a.w[j-i])*DChunk(a.w[i])}; t+=t; t+=co 
+            c.w[j]=Chunk(t&RM); co=t>>RB
+            j+=1;
+            t=DChunk(a.w[BIG.NLEN-1])*DChunk(a.w[j-BIG.NLEN+1]); for i in j-BIG.NLEN+2 ..< (j+1)/2 {t+=DChunk(a.w[j-i])*DChunk(a.w[i])}; t+=t; t+=co; t+=DChunk(a.w[j/2])*DChunk(a.w[j/2]) 
+            c.w[j]=Chunk(t&RM); co=t>>RB
+            j+=1;
+        }
+
+        t=DChunk(a.w[BIG.NLEN-2])*DChunk(a.w[BIG.NLEN-1])
+        t+=t; t+=co;
+        c.w[BIG.DNLEN-3]=Chunk(t&RM); co=t>>RB
+    
+        t=DChunk(a.w[BIG.NLEN-1])*DChunk(a.w[BIG.NLEN-1])+co
+        c.w[BIG.DNLEN-2]=Chunk(t&RM); co=t>>RB
+        c.w[BIG.DNLEN-1]=Chunk(co)
+
+
+/*
+
+        t=DChunk(a.w[0])*DChunk(a.w[0])
+        c.w[0]=Chunk(t&RM); co=t>>RB
+        t=DChunk(a.w[1])*DChunk(a.w[0]); t+=t; t+=co
+        c.w[1]=Chunk(t&RM); co=t>>RB
+        
+        var j:Int
+        let last=BIG.NLEN-(BIG.NLEN%2)
+        j=2
+        //for j=2;j<last;j+=2
+        while (j<last)
+        {
+            t=DChunk(a.w[j])*DChunk(a.w[0]); for i in 1 ..< (j+1)/2 {t+=DChunk(a.w[j-i])*DChunk(a.w[i])} ; t+=t; t+=co; t+=DChunk(a.w[j/2])*DChunk(a.w[j/2])
+            c.w[j]=Chunk(t&RM); co=t>>RB
+            t=DChunk(a.w[j+1])*DChunk(a.w[0]); for i in 1 ..< (j+2)/2 {t+=DChunk(a.w[j+1-i])*DChunk(a.w[i])} ; t+=t; t+=co
+            c.w[j+1]=Chunk(t&RM); co=t>>RB
+            j+=2
+        }
+        j=last
+        if (BIG.NLEN%2)==1
+        {
+            t=DChunk(a.w[j])*DChunk(a.w[0]); for i in 1 ..< (j+1)/2 {t+=DChunk(a.w[j-i])*DChunk(a.w[i])} ; t+=t; t+=co; t+=DChunk(a.w[j/2])*DChunk(a.w[j/2])
+            c.w[j]=Chunk(t&RM); co=t>>RB; j += 1
+            t=DChunk(a.w[BIG.NLEN-1])*DChunk(a.w[j-BIG.NLEN+1]); for i in j-BIG.NLEN+2 ..< (j+1)/2 {t+=DChunk(a.w[j-i])*DChunk(a.w[i])}; t+=t; t+=co
+            c.w[j]=Chunk(t&RM); co=t>>RB; j += 1
+        }
+        while (j<BIG.DNLEN-2)
+        {
+            t=DChunk(a.w[BIG.NLEN-1])*DChunk(a.w[j-BIG.NLEN+1]); for i in j-BIG.NLEN+2 ..< (j+1)/2 {t+=DChunk(a.w[j-i])*DChunk(a.w[i])} ; t+=t; t+=co; t+=DChunk(a.w[j/2])*DChunk(a.w[j/2])
+            c.w[j]=Chunk(t&RM); co=t>>RB
+            t=DChunk(a.w[BIG.NLEN-1])*DChunk(a.w[j-BIG.NLEN+2]); for i in j-BIG.NLEN+3 ..< (j+2)/2 {t+=DChunk(a.w[j+1-i])*DChunk(a.w[i])} ; t+=t; t+=co
+            c.w[j+1]=Chunk(t&RM); co=t>>RB
+            j+=2
+        }
+        t=DChunk(a.w[BIG.NLEN-1])*DChunk(a.w[BIG.NLEN-1])+co
+        c.w[BIG.DNLEN-2]=Chunk(t&RM); co=t>>RB
+        c.w[BIG.DNLEN-1]=Chunk(co)
+*/    
+        return c;
+    }
+    static func monty(_ md:BIG,_ mc:Chunk,_ d: inout DBIG) -> BIG
+    {
+    //    let md=BIG(ROM.Modulus);
+        let RM:DChunk=DChunk(BIG.BMASK)
+        let RB:DChunk=DChunk(BIG.BASEBITS)
+        
+        
+        var t:DChunk
+        var s:DChunk
+        var c:DChunk
+        var dd=[DChunk](repeating: 0,count: BIG.NLEN)
+        var v=[Chunk](repeating: 0,count: BIG.NLEN)
+        var b=BIG(0)
+        
+        t=DChunk(d.w[0]); v[0]=(Chunk(t&RM)&*mc)&BIG.BMASK; t+=DChunk(v[0])*DChunk(md.w[0]); c=DChunk(d.w[1])+(t>>RB); s=0
+        for k in 1 ..< BIG.NLEN
+        {
+            t=c+s+DChunk(v[0])*DChunk(md.w[k])
+            //for i in 1+k/2...k-1
+            //for var i=k-1;i>k/2;i--
+            var i=1+k/2
+            while i<k
+            {
+                t+=DChunk(v[k-i]-v[i])*DChunk(md.w[i]-md.w[k-i])
+                i+=1
+            }
+            v[k]=(Chunk(t&RM)&*mc)&BIG.BMASK; t+=DChunk(v[k])*DChunk(md.w[0]); c=DChunk(d.w[k+1])+(t>>RB)
+            dd[k]=DChunk(v[k])*DChunk(md.w[k]); s+=dd[k]
+        }
+        for k in BIG.NLEN ..< 2*BIG.NLEN-1
+        {
+            t=c+s;
+            //for i in 1+k/2...BIG.NLEN-1
+            //for var i=BIG.NLEN-1;i>=1+k/2;i--
+            var i=1+k/2
+            while i<BIG.NLEN
+            {
+                t+=DChunk(v[k-i]-v[i])*DChunk(md.w[i]-md.w[k-i])
+                i+=1
+            }
+            b.w[k-BIG.NLEN]=Chunk(t&RM); c=DChunk(d.w[k+1])+(t>>RB); s-=dd[k-BIG.NLEN+1]
+        }
+        b.w[BIG.NLEN-1]=Chunk(c&RM)
+     //   b.norm()
+        return b;
+    }
+#endif
+#if D64
+    static func mul(_ a: BIG,_ b:BIG) -> DBIG
+    {
+        var c=DBIG()
+        var carry:Chunk
+        for i in 0 ..< BIG.NLEN {
+            carry=0
+            for j in 0..<BIG.NLEN {
+                let (top,bot)=BIG.muladd(a.w[i],b.w[j],carry,c.w[i+j])
+                carry=top; c.w[i+j]=bot
+            }
+            c.w[BIG.NLEN+i]=carry
+        }
+        return c
+    }
+    static func sqr(_ a: BIG) -> DBIG
+    {
+        var c=DBIG()
+        var carry:Chunk
+        for i in 0 ..< BIG.NLEN {
+            carry=0
+            for j in i+1 ..< BIG.NLEN {
+                let (top,bot)=BIG.muladd(2*a.w[i],a.w[j],carry,c.w[i+j])
+                carry=top; c.w[i+j]=bot
+            }
+            c.w[BIG.NLEN+i]=carry
+        }
+        for i in 0 ..< BIG.NLEN {
+            let (top,bot)=BIG.muladd(a.w[i],a.w[i],Chunk(0),c.w[2*i])
+            c.w[2*i]=bot
+            c.w[2*i+1]+=top
+        }
+        c.norm()
+        return c
+    }
+    static func monty(_ md:BIG,_ mc:Chunk,_ d: inout DBIG) -> BIG
+    {
+        var b=BIG()
+    //    let md=BIG(ROM.Modulus);
+        var carry:Chunk
+        var m:Chunk
+        for i in 0 ..< BIG.NLEN {
+            if mc == -1 {
+                m=(-d.w[i])&BIG.BMASK
+            } else {
+                if mc == 1 {
+                    m=d.w[i]
+                } else {
+                    m=(mc&*d.w[i])&BIG.BMASK;
+                }
+            }
+            carry=0
+            for j in 0 ..< BIG.NLEN {
+                let (top,bot)=BIG.muladd(m,md.w[j],carry,d.w[i+j])
+                carry=top; d.w[i+j]=bot
+            }
+            d.w[BIG.NLEN+i]+=carry
+        }
+        for i in 0 ..< BIG.NLEN {
+            b.w[i]=d.w[BIG.NLEN+i]
+        }
+        b.norm();
+        return b
+    }
+#endif
+
+/* Optimized combined shift, subtract and norm */
+    static func ssn(_ r: inout BIG,_ a :BIG,_ m: inout BIG) -> Int
+    {
+        let n=BIG.NLEN-1
+        m.w[0]=(m.w[0]>>1)|((m.w[1]<<Chunk(BIG.BASEBITS-1))&BIG.BMASK)
+        r.w[0]=a.w[0]-m.w[0]
+        var carry=r.w[0]>>Chunk(BIG.BASEBITS)
+        r.w[0] &= BIG.BMASK
+        for i in 1 ..< n {
+            m.w[i]=(m.w[i]>>1)|((m.w[i+1]<<Chunk(BIG.BASEBITS-1))&BIG.BMASK)
+            r.w[i]=a.w[i]-m.w[i]+carry
+            carry=r.w[i]>>Chunk(BIG.BASEBITS)
+            r.w[i] &= BIG.BMASK
+        }
+	   m.w[n]>>=1
+	   r.w[n]=a.w[n]-m.w[n]+carry
+	   return Int((r.w[n]>>Chunk(BIG.CHUNK-1))&Chunk(1))
+    }
+    
+    /* return a*b mod m */
+    static func modmul(_ a1: BIG,_ b1 :BIG,_ m: BIG) -> BIG
+    {
+        var a=BIG(a1); var b=BIG(b1);
+        a.mod(m)
+        b.mod(m)
+        var d=mul(a,b)
+        return d.mod(m)
+    }
+    
+    /* return a^2 mod m */
+    static func modsqr(_ a1: BIG,_ m: BIG) -> BIG
+    {
+        var a=BIG(a1)
+        a.mod(m)
+        var d=sqr(a)
+        return d.mod(m)
+    }
+    
+    /* return -a mod m */
+    static func modneg(_ a1: BIG,_ m: BIG) -> BIG
+    {
+        var a=BIG(a1)
+        a.mod(m)
+        return m.minus(a)
+    }
+    
+    /* return this^e mod m */
+    mutating func powmod(_ e1: BIG,_ m: BIG) -> BIG
+    {
+        norm();
+        var e=BIG(e1)
+        e.norm();
+        var a=BIG(1)
+        var z=BIG(e)
+        var s=BIG(self)
+        while (true)
+        {
+            let bt=z.parity();
+            z.fshr(1)
+            if bt==1 {a=BIG.modmul(a,s,m)}
+            if (z.iszilch()) {break}
+            s=BIG.modsqr(s,m)
+        }
+        return a
+    }
+}
diff --git a/version3/swift/config32.py b/version3/swift/config32.py
new file mode 100644
index 0000000..520f0f0
--- /dev/null
+++ b/version3/swift/config32.py
@@ -0,0 +1,354 @@
+import os
+import sys
+
+deltext=""
+slashtext=""
+copytext=""
+if sys.platform.startswith("linux") or sys.platform.startswith("darwin") :
+	copytext="cp "
+	deltext="rm "
+	slashtext="/"
+if sys.platform.startswith("win") :
+	copytext="copy "
+	deltext="del "
+	slashtext="\\"
+
+chosen=[]
+cptr=0
+
+def replace(namefile,oldtext,newtext):
+	f = open(namefile,'r')
+	filedata = f.read()
+	f.close()
+
+	newdata = filedata.replace(oldtext,newtext)
+
+	f = open(namefile,'w')
+	f.write(newdata)
+	f.close()
+
+
+def rsaset(tb,nb,base,ml) :
+	global deltext,slashtext,copytext
+	global cptr,chosen
+
+	chosen.append(tb)
+	cptr=cptr+1
+
+	fpath="amcl"+slashtext+tb+slashtext
+	os.system("mkdir amcl"+slashtext+tb)
+
+	os.system(copytext+"big.swift "+fpath+"big.swift")
+	os.system(copytext+"dbig.swift "+fpath+"dbig.swift")
+	os.system(copytext+"ff.swift "+fpath+"ff.swift")
+	os.system(copytext+"rsa.swift "+fpath+"rsa.swift")
+
+	replace(fpath+"big.swift","@NB@",nb)
+	replace(fpath+"big.swift","@BASE32@",base)
+	replace(fpath+"big.swift","@BASE64@",base)
+
+	replace(fpath+"ff.swift","@ML@",ml);
+
+	os.system("swiftc -DD32 "+fpath+"*.swift -L. -lamcl -I. -O -Ounchecked -whole-module-optimization -emit-library -emit-module -module-name "+tb)
+	os.system(deltext+fpath+"*.*")
+	os.system("rmdir amcl"+slashtext+tb)
+
+
+def curveset(tc,nb,base,nbt,m8,mt,ct,pf,stw,sx,cs) :
+	global deltext,slashtext,copytext
+	global cptr,chosen
+
+	chosen.append(tc)
+	cptr=cptr+1
+
+	fpath="amcl"+slashtext+tc+slashtext
+	os.system("mkdir amcl"+slashtext+tc)
+
+	os.system(copytext+"big.swift "+fpath+"big.swift")
+	os.system(copytext+"dbig.swift "+fpath+"dbig.swift")
+	os.system(copytext+"fp.swift "+fpath+"fp.swift")
+	os.system(copytext+"ecp.swift "+fpath+"ecp.swift")
+	os.system(copytext+"rom_"+tc+".swift "+fpath+"rom.swift")
+
+	replace(fpath+"big.swift","@NB@",nb)
+	replace(fpath+"big.swift","@BASE32@",base)
+	replace(fpath+"big.swift","@BASE64@",base)
+
+	replace(fpath+"fp.swift","@NBT@",nbt)
+	replace(fpath+"fp.swift","@M8@",m8)
+	replace(fpath+"fp.swift","@MT@",mt)
+
+	ib=int(base)
+	inb=int(nb)
+	inbt=int(nbt)
+	sh=ib*(1+((8*inb-1)//ib))-inbt
+	if sh > 14 :
+		sh=14
+	replace(fpath+"fp.swift","@SH@",str(sh))
+
+
+	replace(fpath+"ecp.swift","@CT@",ct)
+	replace(fpath+"ecp.swift","@PF@",pf)
+
+	replace(fpath+"ecp.swift","@ST@",stw)
+	replace(fpath+"ecp.swift","@SX@",sx)
+
+	if cs == "128" :
+		replace(fpath+"ecp.swift","@HT@","32")
+		replace(fpath+"ecp.swift","@AK@","16")
+	if cs == "192" :
+		replace(fpath+"ecp.swift","@HT@","48")
+		replace(fpath+"ecp.swift","@AK@","24")
+	if cs == "256" :
+		replace(fpath+"ecp.swift","@HT@","64")
+		replace(fpath+"ecp.swift","@AK@","32")
+
+	if pf != "NOT" :
+
+		os.system(copytext+"fp2.swift "+fpath+"fp2.swift")
+		os.system(copytext+"fp4.swift "+fpath+"fp4.swift")
+		if cs == "128" :
+			os.system(copytext+"ecp2.swift "+fpath+"ecp2.swift")
+			os.system(copytext+"fp12.swift "+fpath+"fp12.swift")
+			os.system(copytext+"pair.swift "+fpath+"pair.swift")
+			os.system(copytext+"mpin.swift "+fpath+"mpin.swift")
+		if cs == "192" :
+			os.system(copytext+"fp8.swift "+fpath+"fp8.swift")
+			os.system(copytext+"ecp4.swift "+fpath+"ecp4.swift")
+			os.system(copytext+"fp24.swift "+fpath+"fp24.swift")
+			os.system(copytext+"pair192.swift "+fpath+"pair192.swift")
+			os.system(copytext+"mpin192.swift "+fpath+"mpin192.swift")
+		if cs == "256" :
+			os.system(copytext+"fp8.swift "+fpath+"fp8.swift")
+			os.system(copytext+"fp16.swift "+fpath+"fp16.swift")
+			os.system(copytext+"ecp8.swift "+fpath+"ecp8.swift")
+			os.system(copytext+"fp48.swift "+fpath+"fp48.swift")
+			os.system(copytext+"pair256.swift "+fpath+"pair256.swift")
+			os.system(copytext+"mpin256.swift "+fpath+"mpin256.swift")
+	else :
+		os.system(copytext+"ecdh.swift "+fpath+"ecdh.swift")
+
+
+	os.system("swiftc -DD32 "+fpath+"*.swift -L. -lamcl -I. -O -Ounchecked -whole-module-optimization -emit-library -emit-module -module-name "+tc)
+	os.system(deltext+fpath+"*.*")
+	os.system("rmdir amcl"+slashtext+tc)
+
+
+os.system("mkdir amcl")
+os.system(copytext+ "hash*.swift amcl"+slashtext+".")
+os.system(copytext+ "sha3.swift amcl"+slashtext+".")
+os.system(copytext+ "rand.swift amcl"+slashtext+".")
+os.system(copytext+ "aes.swift amcl"+slashtext+".")
+os.system(copytext+ "gcm.swift amcl"+slashtext+".")
+os.system(copytext+ "nhs.swift amcl"+slashtext+".")
+
+os.system("swiftc amcl"+slashtext+"*.swift -O -Ounchecked -whole-module-optimization -emit-library -emit-module -module-name amcl")
+
+print("Elliptic Curves")
+print("1. ed25519")
+print("2. c25519")
+print("3. nist256")
+print("4. brainpool")
+print("5. anssi")
+print("6. hifive")
+print("7. goldilocks")
+print("8. nist384")
+print("9. c41417")
+print("10. nist521\n")
+print("11. nums256w")
+print("12. nums256e")
+print("13. nums384w")
+print("14. nums384e")
+print("15. nums512w")
+print("16. nums512e")
+print("17. secp256k1\n")
+
+print("Pairing-Friendly Elliptic Curves")
+print("18. bn254")
+print("19. bn254CX")
+print("20. bls383")
+print("21. bls381")
+print("22. fp256BN")
+print("23. fp512BN")
+print("24. bls461\n")
+
+print("25. bls24")
+print("26. bls48\n")
+
+print("RSA")
+print("27. rsa2048")
+print("28. rsa3072")
+print("29. rsa4096")
+
+selection=[]
+ptr=0
+max=30
+
+curve_selected=False
+pfcurve_selected=False
+rsa_selected=False
+
+while ptr<max:
+	x=int(input("Choose a Scheme to support - 0 to finish: "))
+	if x == 0:
+		break
+#	print("Choice= ",x)
+	already=False
+	for i in range(0,ptr):
+		if x==selection[i]:
+			already=True
+			break
+	if already:
+		continue
+	
+	selection.append(x)
+	ptr=ptr+1
+
+# curveset(curve,big_length_bytes,bits_in_base,modulus_bits,modulus_mod_8,modulus_type,curve_type,pairing_friendly,curve security)
+# where "curve" is the common name for the elliptic curve   
+# big_length_bytes is the modulus size rounded up to a number of bytes
+# bits_in_base gives the number base used for 32 bit architectures, as n where the base is 2^n
+# modulus_bits is the actual bit length of the modulus.
+# modulus_mod_8 is the remainder when the modulus is divided by 8
+# modulus_type is NOT_SPECIAL, or PSEUDO_MERSENNE, or MONTGOMERY_Friendly, or GENERALISED_MERSENNE (supported for GOLDILOCKS only)
+# curve_type is WEIERSTRASS, EDWARDS or MONTGOMERY
+# pairing_friendly is BN, BLS or NOT (if not pairing friendly
+# curve security is AES equiavlent, rounded up.
+
+
+	if x==1:
+		curveset("ed25519","32","29","255","5","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==2:
+		curveset("c25519","32","29","255","5","PSEUDO_MERSENNE","MONTGOMERY","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==3:
+		curveset("nist256","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==4:
+		curveset("brainpool","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==5:
+		curveset("anssi","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+		curve_selected=True
+
+	if x==6:
+		curveset("hifive","42","29","336","5","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","192")
+		curve_selected=True
+	if x==7:
+		curveset("goldilocks","56","29","448","7","GENERALISED_MERSENNE","EDWARDS","NOT","NOT","NOT","256")
+		curve_selected=True
+	if x==8:
+		curveset("nist384","48","29","384","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","192")
+		curve_selected=True
+	if x==9:
+		curveset("c41417","52","29","414","7","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","256")
+		curve_selected=True
+	if x==10:
+		curveset("nist521","66","28","521","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","256")
+		curve_selected=True
+
+
+	if x==11:
+		curveset("nums256w","32","28","256","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==12:
+		curveset("nums256e","32","29","256","3","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==13:
+		curveset("nums384w","48","29","384","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","192")
+		curve_selected=True
+	if x==14:
+		curveset("nums384e","48","29","384","3","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","192")
+		curve_selected=True
+	if x==15:
+		curveset("nums512w","64","29","512","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","256")
+		curve_selected=True
+	if x==16:
+		curveset("nums512e","64","29","512","7","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","256")
+		curve_selected=True
+
+	if x==17:
+		curveset("secp256k1","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+		curve_selected=True
+
+
+	if x==18:
+		curveset("bn254","32","28","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+	if x==19:
+		curveset("bn254CX","32","28","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+	if x==20:
+		curveset("bls383","48","29","383","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","128")
+		pfcurve_selected=True
+
+	if x==21:
+		curveset("bls381","48","29","381","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+
+	if x==22:
+		curveset("fp256bn","32","28","256","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+	if x==23:
+		curveset("fp512bn","64","29","512","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","POSITIVEX","128")
+		pfcurve_selected=True
+# https://eprint.iacr.org/2017/334.pdf
+	if x==24:
+		curveset("bls461","58","28","461","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+
+	if x==25:
+		curveset("bls24","60","29","479","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","192")
+		pfcurve_selected=True
+
+	if x==26:
+		curveset("bls48","70","29","556","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","256")
+		pfcurve_selected=True
+
+
+# rsaset(rsaname,big_length_bytes,bits_in_base,multiplier)
+# The RSA name reflects the modulus size, which is a 2^m multiplier
+# of the underlying big length
+
+# There are choices here, different ways of getting the same result, but some faster than others
+	if x==27:
+		#256 is slower but may allow reuse of 256-bit BIGs used for elliptic curve
+		#512 is faster.. but best is 1024
+		rsaset("rsa2048","128","28","2")
+		#rsaset("rsa2048","64","29","60",4")
+		#rsaset("rsa2048","32","29","56","8")
+		rsa_selected=True
+	if x==28:
+		rsaset("rsa3072","48","28","8")
+		rsa_selected=True
+	if x==29:
+		#rsaset("rsa4096","32","29","56",16")
+		rsaset("rsa4096","64","29","8")
+		rsa_selected=True
+
+os.system(deltext+" hash*.swift")
+os.system(deltext+" sha3.swift")
+os.system(deltext+" aes.swift")
+os.system(deltext+" rand.swift")
+os.system(deltext+" gcm.swift")
+os.system(deltext+" nhs.swift")
+
+os.system(deltext+" big.swift")
+os.system(deltext+" dbig.swift")
+os.system(deltext+" fp*.swift")
+
+os.system(deltext+" ecp*.swift")
+os.system(deltext+" ecdh.swift")
+os.system(deltext+" ff.swift")
+os.system(deltext+" rsa.swift")
+os.system(deltext+" pair*.swift")
+os.system(deltext+" mpin*.swift")
+os.system(deltext+" rom*.swift")
+
+os.system(deltext+"amcl"+slashtext+"*.*")
+os.system("rmdir amcl")
+
+# create library
+
+
diff --git a/version3/swift/config64.py b/version3/swift/config64.py
new file mode 100644
index 0000000..cef680b
--- /dev/null
+++ b/version3/swift/config64.py
@@ -0,0 +1,352 @@
+import os
+import sys
+
+deltext=""
+slashtext=""
+copytext=""
+if sys.platform.startswith("linux") or sys.platform.startswith("darwin") :
+	copytext="cp "
+	deltext="rm "
+	slashtext="/"
+if sys.platform.startswith("win") :
+	copytext="copy "
+	deltext="del "
+	slashtext="\\"
+
+chosen=[]
+cptr=0
+
+def replace(namefile,oldtext,newtext):
+	f = open(namefile,'r')
+	filedata = f.read()
+	f.close()
+
+	newdata = filedata.replace(oldtext,newtext)
+
+	f = open(namefile,'w')
+	f.write(newdata)
+	f.close()
+
+
+def rsaset(tb,nb,base,ml) :
+	global deltext,slashtext,copytext
+	global cptr,chosen
+
+	chosen.append(tb)
+	cptr=cptr+1
+
+	fpath="amcl"+slashtext+tb+slashtext
+	os.system("mkdir amcl"+slashtext+tb)
+
+	os.system(copytext+"big.swift "+fpath+"big.swift")
+	os.system(copytext+"dbig.swift "+fpath+"dbig.swift")
+	os.system(copytext+"ff.swift "+fpath+"ff.swift")
+	os.system(copytext+"rsa.swift "+fpath+"rsa.swift")
+
+	replace(fpath+"big.swift","@NB@",nb)
+	replace(fpath+"big.swift","@BASE32@",base)
+	replace(fpath+"big.swift","@BASE64@",base)
+
+
+	replace(fpath+"ff.swift","@ML@",ml);
+
+	os.system("swiftc -DD64 "+fpath+"*.swift -L. -lamcl -I. -O -Ounchecked -whole-module-optimization -emit-library -emit-module -module-name "+tb)
+	os.system(deltext+fpath+"*.*")
+	os.system("rmdir amcl"+slashtext+tb)
+
+
+def curveset(tc,nb,base,nbt,m8,mt,ct,pf,stw,sx,cs) :
+	global deltext,slashtext,copytext
+	global cptr,chosen
+
+	chosen.append(tc)
+	cptr=cptr+1
+
+	fpath="amcl"+slashtext+tc+slashtext
+	os.system("mkdir amcl"+slashtext+tc)
+
+	os.system(copytext+"big.swift "+fpath+"big.swift")
+	os.system(copytext+"dbig.swift "+fpath+"dbig.swift")
+	os.system(copytext+"fp.swift "+fpath+"fp.swift")
+	os.system(copytext+"ecp.swift "+fpath+"ecp.swift")
+	os.system(copytext+"rom_"+tc+".swift "+fpath+"rom.swift")
+
+	replace(fpath+"big.swift","@NB@",nb)
+	replace(fpath+"big.swift","@BASE32@",base)
+	replace(fpath+"big.swift","@BASE64@",base)
+
+	replace(fpath+"fp.swift","@NBT@",nbt)
+	replace(fpath+"fp.swift","@M8@",m8)
+	replace(fpath+"fp.swift","@MT@",mt)
+
+	ib=int(base)
+	inb=int(nb)
+	inbt=int(nbt)
+	sh=ib*(1+((8*inb-1)//ib))-inbt
+	if sh > 30 :
+		sh=30
+	replace(fpath+"fp.swift","@SH@",str(sh))
+
+	replace(fpath+"ecp.swift","@CT@",ct)
+	replace(fpath+"ecp.swift","@PF@",pf)
+
+	replace(fpath+"ecp.swift","@ST@",stw)
+	replace(fpath+"ecp.swift","@SX@",sx)
+
+	if cs == "128" :
+		replace(fpath+"ecp.swift","@HT@","32")
+		replace(fpath+"ecp.swift","@AK@","16")
+	if cs == "192" :
+		replace(fpath+"ecp.swift","@HT@","48")
+		replace(fpath+"ecp.swift","@AK@","24")
+	if cs == "256" :
+		replace(fpath+"ecp.swift","@HT@","64")
+		replace(fpath+"ecp.swift","@AK@","32")
+
+	if pf != "NOT" :
+		os.system(copytext+"fp2.swift "+fpath+"fp2.swift")
+		os.system(copytext+"fp4.swift "+fpath+"fp4.swift")
+		if cs == "128" :
+			os.system(copytext+"ecp2.swift "+fpath+"ecp2.swift")
+			os.system(copytext+"fp12.swift "+fpath+"fp12.swift")
+			os.system(copytext+"pair.swift "+fpath+"pair.swift")
+			os.system(copytext+"mpin.swift "+fpath+"mpin.swift")
+		if cs == "192" :
+			os.system(copytext+"fp8.swift "+fpath+"fp8.swift")
+			os.system(copytext+"ecp4.swift "+fpath+"ecp4.swift")
+			os.system(copytext+"fp24.swift "+fpath+"fp24.swift")
+			os.system(copytext+"pair192.swift "+fpath+"pair192.swift")
+			os.system(copytext+"mpin192.swift "+fpath+"mpin192.swift")
+		if cs == "256" :
+			os.system(copytext+"fp8.swift "+fpath+"fp8.swift")
+			os.system(copytext+"fp16.swift "+fpath+"fp16.swift")
+			os.system(copytext+"ecp8.swift "+fpath+"ecp8.swift")
+			os.system(copytext+"fp48.swift "+fpath+"fp48.swift")
+			os.system(copytext+"pair256.swift "+fpath+"pair256.swift")
+			os.system(copytext+"mpin256.swift "+fpath+"mpin256.swift")
+
+	else :
+		os.system(copytext+"ecdh.swift "+fpath+"ecdh.swift")
+
+
+	os.system("swiftc -DD64 "+fpath+"*.swift -L. -lamcl -I. -O -Ounchecked -whole-module-optimization -emit-library -emit-module -module-name "+tc)
+	os.system(deltext+fpath+"*.*")
+	os.system("rmdir amcl"+slashtext+tc)
+
+
+os.system("mkdir amcl")
+os.system(copytext+ "hash*.swift amcl"+slashtext+".")
+os.system(copytext+ "sha3.swift amcl"+slashtext+".")
+os.system(copytext+ "rand.swift amcl"+slashtext+".")
+os.system(copytext+ "aes.swift amcl"+slashtext+".")
+os.system(copytext+ "gcm.swift amcl"+slashtext+".")
+os.system(copytext+ "nhs.swift amcl"+slashtext+".")
+
+os.system("swiftc amcl"+slashtext+"*.swift -O -Ounchecked -whole-module-optimization -emit-library -emit-module -module-name amcl")
+
+print("Elliptic Curves")
+print("1. ed25519")
+print("2. c25519")
+print("3. nist256")
+print("4. brainpool")
+print("5. anssi")
+print("6. hifive")
+print("7. goldilocks")
+print("8. nist384")
+print("9. c41417")
+print("10. nist521\n")
+print("11. nums256w")
+print("12. nums256e")
+print("13. nums384w")
+print("14. nums384e")
+print("15. nums512w")
+print("16. nums512e")
+print("17. secp256k1\n")
+
+print("Pairing-Friendly Elliptic Curves")
+print("18. bn254")
+print("19. bn254CX")
+print("20. bls383")
+print("21. bls381")
+print("22. fp256BN")
+print("23. fp512BN")
+print("24. bls461\n")
+
+print("25. bls24")
+print("26. bls48\n")
+
+print("RSA")
+print("27. rsa2048")
+print("28. rsa3072")
+print("29. rsa4096")
+
+selection=[]
+ptr=0
+max=30
+
+curve_selected=False
+pfcurve_selected=False
+rsa_selected=False
+
+while ptr<max:
+	x=int(input("Choose a Scheme to support - 0 to finish: "))
+	if x == 0:
+		break
+#	print("Choice= ",x)
+	already=False
+	for i in range(0,ptr):
+		if x==selection[i]:
+			already=True
+			break
+	if already:
+		continue
+	
+	selection.append(x)
+	ptr=ptr+1
+
+# curveset(curve,big_length_bytes,bits_in_base,modulus_bits,modulus_mod_8,modulus_type,curve_type,pairing_friendly,curve security)
+# where "curve" is the common name for the elliptic curve   
+# big_length_bytes is the modulus size rounded up to a number of bytes
+# bits_in_base gives the number base used for 32 bit architectures, as n where the base is 2^n
+# modulus_bits is the actual bit length of the modulus.
+# modulus_mod_8 is the remainder when the modulus is divided by 8
+# modulus_type is NOT_SPECIAL, or PSEUDO_MERSENNE, or MONTGOMERY_Friendly, or GENERALISED_MERSENNE (supported for GOLDILOCKS only)
+# curve_type is WEIERSTRASS, EDWARDS or MONTGOMERY
+# pairing_friendly is BN, BLS or NOT (if not pairing friendly
+# curve security is AES equiavlent, rounded up.
+
+
+	if x==1:
+		curveset("ed25519","32","56","255","5","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==2:
+		curveset("c25519","32","56","255","5","PSEUDO_MERSENNE","MONTGOMERY","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==3:
+		curveset("nist256","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==4:
+		curveset("brainpool","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==5:
+		curveset("anssi","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+		curve_selected=True
+
+	if x==6:
+		curveset("hifive","42","60","336","5","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","192")
+		curve_selected=True
+	if x==7:
+		curveset("goldilocks","56","58","448","7","GENERALISED_MERSENNE","EDWARDS","NOT","NOT","NOT","256")
+		curve_selected=True
+	if x==8:
+		curveset("nist384","48","56","384","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","192")
+		curve_selected=True
+	if x==9:
+		curveset("c41417","52","60","414","7","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","256")
+		curve_selected=True
+	if x==10:
+		curveset("nist521","66","60","521","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","256")
+		curve_selected=True
+
+	if x==11:
+		curveset("nums256w","32","56","256","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==12:
+		curveset("nums256e","32","56","256","3","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","128")
+		curve_selected=True
+	if x==13:
+		curveset("nums384w","48","58","384","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","192")
+		curve_selected=True
+	if x==14:
+		curveset("nums384e","48","56","384","3","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","192")
+		curve_selected=True
+	if x==15:
+		curveset("nums512w","64","60","512","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","256")
+		curve_selected=True
+	if x==16:
+		curveset("nums512e","64","60","512","7","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","256")
+		curve_selected=True
+
+	if x==17:
+		curveset("secp256k1","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+		curve_selected=True
+
+	if x==18:
+		curveset("bn254","32","56","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+	if x==19:
+		curveset("bn254CX","32","56","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+	if x==20:
+		curveset("bls383","48","58","383","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","128")
+		pfcurve_selected=True
+
+	if x==21:
+		curveset("bls381","48","58","381","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+
+
+	if x==22:
+		curveset("fp256bn","32","56","256","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+	if x==23:
+		curveset("fp512bn","64","60","512","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","POSITIVEX","128")
+		pfcurve_selected=True
+# https://eprint.iacr.org/2017/334.pdf
+	if x==24:
+		curveset("bls461","58","60","461","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+
+	if x==25:
+		curveset("bls24","60","56","479","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","192")
+		pfcurve_selected=True
+
+	if x==26:
+		curveset("bls48","70","58","556","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","256")
+		pfcurve_selected=True
+
+# rsaset(rsaname,big_length_bytes,bits_in_base,multiplier)
+# The RSA name reflects the modulus size, which is a 2^m multiplier
+# of the underlying big length
+
+# There are choices here, different ways of getting the same result, but some faster than others
+	if x==27:
+		#256 is slower but may allow reuse of 256-bit BIGs used for elliptic curve
+		#512 is faster.. but best is 1024
+		rsaset("rsa2048","128","58","2")
+		#rsaset("rsa2048","64","60",4")
+		#rsaset("rsa2048","32","56",8")
+		rsa_selected=True
+	if x==28:
+		rsaset("rsa3072","48","56","8")
+		rsa_selected=True
+	if x==29:
+		#rsaset("rsa4096","32","56",16")
+		rsaset("rsa4096","64","60","8")
+		rsa_selected=True
+
+os.system(deltext+" hash*.swift")
+os.system(deltext+" sha3.swift")
+os.system(deltext+" aes.swift")
+os.system(deltext+" rand.swift")
+os.system(deltext+" gcm.swift")
+os.system(deltext+" nhs.swift")
+
+os.system(deltext+" big.swift")
+os.system(deltext+" dbig.swift")
+os.system(deltext+" fp*.swift")
+
+os.system(deltext+" ecp*.swift")
+os.system(deltext+" ecdh.swift")
+os.system(deltext+" ff.swift")
+os.system(deltext+" rsa.swift")
+os.system(deltext+" pair*.swift")
+os.system(deltext+" mpin*.swift")
+os.system(deltext+" rom*.swift")
+
+os.system(deltext+"amcl"+slashtext+"*.*")
+os.system("rmdir amcl")
+
+# create library
+
+
diff --git a/version3/swift/dbig.swift b/version3/swift/dbig.swift
new file mode 100644
index 0000000..378a0ba
--- /dev/null
+++ b/version3/swift/dbig.swift
@@ -0,0 +1,291 @@
+
+/*
+	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.
+*/
+
+//
+//  dbig.swift
+//
+//  Created by Michael Scott on 13/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+    struct DBIG{
+    var w=[Chunk](repeating: 0,count: BIG.DNLEN)
+    init() {
+        for i in 0 ..< BIG.DNLEN {w[i]=0}
+    }
+    init(_ x: Int)
+    {
+        w[0]=Chunk(x);
+        for i in 1 ..< BIG.DNLEN {w[i]=0}
+    }
+    init(_ x: BIG)
+    {
+        for i in 0 ..< BIG.NLEN {w[i]=x.w[i]}
+        w[BIG.NLEN-1]=x.w[BIG.NLEN-1]&BIG.BMASK
+        w[BIG.NLEN]=x.w[BIG.NLEN-1]>>Chunk(BIG.BASEBITS)
+        for i in BIG.NLEN+1 ..< BIG.DNLEN {w[i]=0}
+    }
+    init(_ x: DBIG)
+    {
+        for i in 0 ..< BIG.DNLEN {w[i]=x.w[i]}
+    }
+    init(_ x: [Chunk])
+    {
+        for i in 0 ..< BIG.DNLEN {w[i]=x[i]}
+    }
+
+    mutating func cmove(_ g: DBIG,_ d: Int)
+    {
+        let b = Chunk(-d)
+    
+        for i in 0 ..< BIG.DNLEN
+        {
+            w[i]^=(w[i]^g.w[i])&b;
+        }
+    }
+
+/* Copy from another DBIG */
+    mutating func copy(_ x: DBIG)
+    {
+        for i in 0 ..< BIG.DNLEN {w[i] = x.w[i]}
+    }
+
+    mutating func ucopy(_ x: BIG)
+    {
+        for i in 0 ..< BIG.NLEN {w[i] = 0}
+        for i in BIG.NLEN ..< BIG.DNLEN {w[i] = x.w[i-BIG.NLEN]}        
+    }
+
+    /* this+=x */
+    mutating func add(_ x: DBIG)
+    {
+        for i in 0 ..< BIG.DNLEN
+        {
+            w[i]+=x.w[i]
+        }
+    }
+
+    /* this-=x */
+    mutating func sub(_ x: DBIG)
+    {
+        for i in 0 ..< BIG.DNLEN
+        {
+            w[i]-=x.w[i]
+        }
+    }
+
+    /* this-=x */
+    mutating func rsub(_ x: DBIG)
+    {
+        for i in 0 ..< BIG.DNLEN
+        {
+            w[i]=x.w[i]-w[i]
+        }
+    }    
+/*    func muladd(_ x: Int32,_ y: Int32,_ c: Int32,_ i: Int) -> Int32
+    {
+        let prod:Int64 = Int64(x)*Int64(y)+Int64(c)+Int64(w[i])
+        w[i]=Int32(prod&Int64(BIG.BMASK))
+        return Int32(prod>>Int64(BIG.BASEBITS))
+    } */
+    /* general shift left */
+    mutating func shl(_ k: UInt)
+    {
+        let n=k%BIG.BASEBITS
+        let m=Int(k/BIG.BASEBITS)
+        w[BIG.DNLEN-1]=((w[BIG.DNLEN-1-m]<<Chunk(n)))|(w[BIG.DNLEN-m-2]>>Chunk(BIG.BASEBITS-n))
+        for i in (m+1...BIG.DNLEN-2).reversed()
+     //   for var i=BIG.DNLEN-2;i>m;i--
+        {
+            w[i]=((w[i-m]<<Chunk(n))&BIG.BMASK)|(w[i-m-1]>>Chunk(BIG.BASEBITS-n))
+        }
+        w[m]=(w[0]<<Chunk(n))&BIG.BMASK
+        for i in 0 ..< m {w[i]=0}
+    }
+    /* general shift right */
+    mutating func shr(_ k: UInt)
+    {
+        let n=k%BIG.BASEBITS
+        let m=Int(k/BIG.BASEBITS)
+        for i in 0 ..< BIG.DNLEN-m-1
+        {
+            w[i]=(w[m+i]>>Chunk(n))|((w[m+i+1]<<Chunk(BIG.BASEBITS-n))&BIG.BMASK)
+        }
+        w[BIG.DNLEN - m - 1]=w[BIG.DNLEN-1]>>Chunk(n)
+        for i in BIG.DNLEN - m ..< BIG.DNLEN {w[i]=0}
+    }
+    /* Compare a and b, return 0 if a==b, -1 if a<b, +1 if a>b. Inputs must be normalised */
+    static func comp(_ a: DBIG,_ b: DBIG) -> Int
+    {
+        for i in (0...BIG.DNLEN-1).reversed()
+       // for var i=BIG.DNLEN-1;i>=0;i--
+        {
+            if (a.w[i]==b.w[i]) {continue}
+            if (a.w[i]>b.w[i]) {return 1}
+            else  {return -1}
+        }
+        return 0;
+    }
+    /* normalise BIG - force all digits < 2^BASEBITS */
+    mutating func norm()
+    {
+        var carry:Chunk=0
+        for i in 0 ..< BIG.DNLEN-1
+        {
+            let d=w[i]+carry
+            w[i]=d&BIG.BMASK
+            carry=d>>Chunk(BIG.BASEBITS)
+        }
+        w[BIG.DNLEN-1]+=carry
+    }
+    /* reduces this DBIG mod a BIG, and returns the BIG */
+    mutating func mod(_ c: BIG) -> BIG
+    {
+        var k:Int=0
+        norm()
+        var m=DBIG(c)
+        var r=DBIG(0)
+    
+        if DBIG.comp(self,m)<0 {return BIG(self)}
+    
+        repeat
+        {
+            m.shl(1)
+            k += 1
+        }
+        while (DBIG.comp(self,m)>=0);
+    
+        while (k>0)
+        {
+            m.shr(1)
+
+		r.copy(self)
+		r.sub(m)
+		r.norm()
+		cmove(r,Int(1-((r.w[BIG.DNLEN-1]>>Chunk(BIG.CHUNK-1))&1)))
+/*
+
+            if (DBIG.comp(self,m)>=0)
+            {
+				sub(m)
+				norm()
+            } */
+            k -= 1;
+        }
+        return BIG(self)
+    }
+    /* return this/c */
+    mutating func div(_ c:BIG) -> BIG
+    {
+        var k:Int=0
+        var m=DBIG(c)
+        var a=BIG(0)
+        var e=BIG(1)
+        var r=BIG(0)
+        var dr=DBIG(0)
+
+        norm()
+    
+        while (DBIG.comp(self,m)>=0)
+        {
+            e.fshl(1)
+            m.shl(1)
+            k += 1
+        }
+    
+        while (k>0)
+        {
+            m.shr(1)
+            e.shr(1)
+
+		dr.copy(self)
+		dr.sub(m)
+		dr.norm()
+		let d=Int(1-((dr.w[BIG.DNLEN-1]>>Chunk(BIG.CHUNK-1))&1))
+		cmove(dr,d)
+		r.copy(a)
+		r.add(e)
+		r.norm()
+		a.cmove(r,d)
+/*
+            if (DBIG.comp(self,m)>0)
+            {
+				a.add(e)
+				a.norm()
+				sub(m)
+				norm()
+            } */
+            k -= 1
+        }
+        return a
+    }
+    
+    /* split DBIG at position n, return higher half, keep lower half */
+    mutating func split(_ n: UInt) -> BIG
+    {
+        var t=BIG(0)
+        let m=n%BIG.BASEBITS
+        var carry=w[BIG.DNLEN-1]<<Chunk(BIG.BASEBITS-m)
+    
+        for i in (BIG.NLEN-1...BIG.DNLEN-2).reversed()
+      //  for var i=BIG.DNLEN-2;i>=BIG.NLEN-1;i--
+        {
+            let nw=(w[i]>>Chunk(m))|carry;
+            carry=(w[i]<<Chunk(BIG.BASEBITS-m))&BIG.BMASK;
+            t.set(i-BIG.NLEN+1,nw);
+        }
+        w[BIG.NLEN-1]&=((1<<Chunk(m))-1);
+        return t;
+    }
+    /* return number of bits */
+    func nbits() -> Int
+    {
+        var k=(BIG.DNLEN-1)
+        var t=BIG(self)        
+        t.norm()
+        while k>=0 && t.w[k]==0 {k -= 1}
+        if k<0 {return 0}
+        var bts=Int(BIG.BASEBITS)*k
+        var c=t.w[k];
+        while c != 0 {c/=2; bts+=1}
+        return bts
+    }
+    /* Convert to Hex String */
+    func toString() -> String
+    {
+        _ = DBIG()
+        var s:String=""
+        var len=nbits()
+        if len%4 == 0 {len/=4}
+        else {len/=4; len += 1}
+        
+        for i in (0...len-1).reversed()
+    //    for var i=len-1;i>=0;i--
+        {
+            var b = DBIG(self)
+            b.shr(UInt(i*4))
+            let n=String(b.w[0]&15,radix:16,uppercase:false)
+            s+=n
+        }
+        
+        return s
+    }
+    
+}
diff --git a/version3/swift/ecdh.swift b/version3/swift/ecdh.swift
new file mode 100644
index 0000000..7084a22
--- /dev/null
+++ b/version3/swift/ecdh.swift
@@ -0,0 +1,595 @@
+/*
+	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.
+*/
+
+//
+//  ecdh.swift
+//
+//  Created by Michael Scott on 30/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+//import Foundation
+//import Darwin
+import amcl
+
+/* Elliptic Curve API high-level functions  */
+
+public struct ECDH
+{
+    static let INVALID_PUBLIC_KEY:Int = -2
+    static let ERROR:Int = -3
+    static let INVALID:Int = -4
+    static public let EFS=Int(BIG.MODBYTES);
+    static public let EGS=Int(BIG.MODBYTES);
+    //static public let EAS=16;
+    //static public let EBS=16;
+    static public let SHA256=32
+    static public let SHA384=48
+    static public let SHA512=64
+    
+    //static public let HASH_TYPE=SHA512
+
+    /* Convert Integer to n-byte array */
+    private static func inttoBytes(_ n: Int,_ len:Int) -> [UInt8]
+    {
+        var b=[UInt8](repeating: 0,count: len)
+        var nn=n
+    
+        var i=len;
+        while (nn>0 && i>0)
+        {
+            i -= 1;
+            b[i]=UInt8(nn&0xff);
+            nn /= 256;
+        }
+        return b;
+    }
+    
+    private static func hashit(_ sha: Int,_ A:[UInt8],_ n: Int32,_ B:[UInt8]?,_ pad:Int) -> [UInt8]
+    {
+        var R=[UInt8]()
+        if sha==SHA256
+        {
+            var H=HASH256()
+            H.process_array(A); if n>0 {H.process_num(n)}
+                if B != nil {H.process_array(B!)}
+            R=H.hash()
+        }
+        if sha==SHA384
+        {
+            var H=HASH384()
+            H.process_array(A); if n>0 {H.process_num(n)}
+            if B != nil {H.process_array(B!)}
+            R=H.hash()
+        }
+        if sha==SHA512
+        {
+            var H=HASH512()
+            H.process_array(A); if n>0 {H.process_num(n)}
+            if B != nil {H.process_array(B!)}
+            R=H.hash()
+        }
+        if R.isEmpty || pad==0 {return R}
+        var W=[UInt8](repeating: 0,count: pad)
+        if pad<=sha
+        {
+            for i in 0 ..< pad {W[i]=R[i]}
+        }
+        else
+        {
+	    for i in 0 ..< sha {W[i+pad-sha]=R[i]}
+
+            //for i in 0 ..< sha {W[i]=R[i]}
+        }
+        return W
+    }
+    
+    /* Key Derivation Functions */
+    /* Input octet Z */
+    /* Output key of length olen */
+    static public func KDF1(_ sha: Int,_ Z: [UInt8],_ olen:Int) -> [UInt8]
+    {
+    /* NOTE: the parameter olen is the length of the output K in bytes */
+        let hlen=sha
+        var K=[UInt8](repeating: 0,count: olen)
+        var k=0;
+    
+        var cthreshold=olen/hlen; if (olen%hlen) != 0 {cthreshold += 1}
+    
+        for counter in 0 ..< cthreshold
+        {
+            let B=hashit(sha,Z,Int32(counter),nil,0)
+            if k+hlen>olen {for i in 0 ..< olen%hlen {K[k]=B[i]; k+=1}}
+            else {for i in 0 ..< hlen {K[k]=B[i]; k+=1}}
+        }
+        return K;
+    }
+    
+    static public func KDF2(_ sha:Int,_ Z:[UInt8],_ P:[UInt8]?,_ olen:Int) -> [UInt8]
+    {
+    /* NOTE: the parameter olen is the length of the output k in bytes */
+        let hlen=sha
+        var K=[UInt8](repeating: 0,count: olen)
+        var k=0;
+    
+        var cthreshold=olen/hlen; if (olen%hlen) != 0 {cthreshold += 1}
+    
+        for counter in 1...cthreshold
+        {
+            let B=hashit(sha,Z,Int32(counter),P,0)
+            if k+hlen>olen {for i in 0 ..< olen%hlen {K[k]=B[i]; k+=1}}
+            else {for i in 0 ..< hlen {K[k]=B[i]; k+=1}}
+        }
+        return K;
+    }
+   
+    /* Password based Key Derivation Function */
+    /* Input password p, salt s, and repeat count */
+    /* Output key of length olen */
+    static public func PBKDF2(_ sha:Int,_ Pass:[UInt8],_ Salt:[UInt8],_ rep:Int,_ olen:Int) -> [UInt8]
+    {
+        var d=olen/sha;
+        if (olen%sha) != 0 {d+=1}
+        var F=[UInt8](repeating: 0,count: sha)
+        var U=[UInt8](repeating: 0,count: sha)
+        var S=[UInt8](repeating: 0,count: Salt.count+4)
+    
+        var K=[UInt8](repeating: 0,count: d*sha)
+        
+        var opt=0;
+    
+        for i in 1...d
+        {
+            for j in 0 ..< Salt.count {S[j]=Salt[j]}
+            var N=ECDH.inttoBytes(i,4);
+            for j in 0 ..< 4 {S[Salt.count+j]=N[j]}
+    
+            //printBinary(Pass);
+            
+            ECDH.HMAC(sha,S,Pass,&F);
+             
+            for j in 0 ..< sha {U[j]=F[j]}
+            for _ in 2...rep
+            {
+                ECDH.HMAC(sha,U,Pass,&U);
+                for k in 0 ..< sha {F[k]^=U[k]}
+            }
+            for j in 0 ..< sha {K[opt]=F[j]; opt+=1}
+        }
+        var key=[UInt8](repeating: 0,count: olen)
+        for i in 0 ..< olen {key[i]=K[i]}
+        return key;
+    }
+    
+    /* Calculate HMAC of m using key k. HMAC is tag of length olen */
+    @discardableResult static public func HMAC(_ sha:Int,_ M:[UInt8],_ K:[UInt8],_ tag:inout [UInt8]) -> Int
+    {
+    /* Input is from an octet m        *
+    * olen is requested output length in bytes. k is the key  *
+    * The output is the calculated tag */
+        var b=64
+        if sha>32 {b=128}
+        
+        var K0=[UInt8](repeating: 0,count: b)
+        let olen=tag.count;
+        var B=[UInt8]();
+        
+        if olen<4 /*|| olen>HASH.len*/ {return 0}
+    
+        if (K.count > b)
+        {
+            //H.process_array(K); var B=H.hash();
+            B=hashit(sha,K,0,nil,0)
+            for i in 0 ..< sha {K0[i]=B[i]}
+        }
+        else
+        {
+            for i in 0 ..< K.count {K0[i]=K[i]}
+        }
+        for i in 0 ..< b {K0[i]^=0x36}
+  
+ //       printBinary(K0)
+        
+        B=hashit(sha,K0,0,M,0)
+        
+ //       printBinary(B);
+    
+        for i in 0 ..< b {K0[i]^=0x6a}
+        B=hashit(sha,K0,0,B,olen)
+        
+        for i in 0 ..< olen {tag[i]=B[i]}
+    
+        return 1;
+    }
+    /* AES encryption/decryption. Encrypt byte array M using key K and returns ciphertext */
+    static public func AES_CBC_IV0_ENCRYPT(_ K:[UInt8],_ M:[UInt8]) -> [UInt8]
+    { /* AES CBC encryption, with Null IV and key K */
+    /* Input is from an octet string M, output is to an octet string C */
+    /* Input is padded as necessary to make up a full final block */
+        var a=AES();
+        var buff=[UInt8](repeating: 0,count: 16)
+        let clen=16+(M.count/16)*16;
+    
+        var C=[UInt8](repeating: 0,count: clen)
+    
+        a.init_it(AES.CBC,K,nil)
+    
+        var ipt=0; var opt=0;
+        var fin=false;
+        var i:Int=0
+        while true
+        {
+            i=0
+            while i<16
+            {
+                if (ipt<M.count) {buff[i]=M[ipt]; ipt+=1}
+				else {fin=true; break;}
+                i+=1
+            }
+            if fin {break}
+            a.encrypt(&buff);
+            for j in 0 ..< 16
+                {C[opt]=buff[j]; opt+=1}
+        }
+    
+    /* last block, filled up to i-th index */
+    
+        let padlen=16-i;
+        for j in i ..< 16 {buff[j]=UInt8(padlen&0xff)}
+    
+        a.encrypt(&buff);
+    
+        for j in 0 ..< 16
+            {C[opt]=buff[j]; opt+=1}
+        a.end();
+        return C;
+    }
+    
+    /* returns plaintext if all consistent, else returns null string */
+    static public func AES_CBC_IV0_DECRYPT(_ K:[UInt8],_ C:[UInt8]) -> [UInt8]
+    { /* padding is removed */
+        var a=AES();
+        
+        var buff=[UInt8](repeating: 0,count: 16)
+        var MM=[UInt8](repeating: 0,count: C.count)
+    
+        var ipt=0; var opt=0;
+    
+        a.init_it(AES.CBC,K,nil);
+    
+        if C.count==0 {return [UInt8]()}
+        var ch=C[ipt]; ipt+=1
+    
+        var fin=false;
+        var i:Int=0
+        while true
+        {
+            i=0
+            while i<16
+            {
+				buff[i]=ch;
+				if ipt>=C.count {fin=true; break;}
+                else {ch=C[ipt]; ipt+=1}
+                i+=1
+            }
+            a.decrypt(&buff);
+            if fin {break}
+            for j in 0 ..< 16
+                {MM[opt]=buff[j]; opt+=1}
+        }
+    
+        a.end();
+        var bad=false;
+        let padlen:Int=Int(buff[15]);
+        if i != 15 || padlen<1 || padlen>16 {bad=true}
+        if padlen>=2 && padlen<=16
+        {
+            for j in 16-padlen ..< 16 {if buff[j] != buff[15] {bad=true}}
+        }
+        if !bad
+        {
+            for j in 0 ..< 16-padlen
+                {MM[opt]=buff[j]; opt+=1}
+        }
+    
+        if bad {return [UInt8]()}
+    
+        var M=[UInt8](repeating: 0,count: opt)
+        for j in 0 ..< opt {M[j]=MM[j]}
+    
+        return M;
+    }
+    
+    /* Calculate a public/private EC GF(p) key pair W,S where W=S.G mod EC(p),
+    * where S is the secret key and W is the public key
+    * and G is fixed generator.
+    * If RNG is NULL then the private key is provided externally in S
+    * otherwise it is generated randomly internally */
+    @discardableResult  static public func KEY_PAIR_GENERATE(_ RNG: inout RAND?,_ S:inout [UInt8],_ W:inout [UInt8]) -> Int
+    {
+        let res=0;
+     //   var T=[UInt8](count:ECDH.EFS,repeatedValue:0)
+        var s:BIG
+        var G:ECP
+
+        G=ECP.generator();
+    
+        let r=BIG(ROM.CURVE_Order)
+    
+        if (RNG==nil)
+        {
+            s=BIG.fromBytes(S)
+            s.mod(r)
+        }
+        else
+        {
+            s=BIG.randomnum(r,&RNG!)
+    
+         //   s.toBytes(&T)
+         //   for i in 0 ..< EGS {S[i]=T[i]}
+        }
+    
+	//if (ROM.AES_S>0)
+	//{
+	//    s.mod2m(2*ROM.AES_S)
+	//}
+        s.toBytes(&S)
+
+        let WP=G.mul(s)
+        WP.toBytes(&W,false)  // To use point compression on public keys, change to true 
+    
+        return res;
+    }
+   
+    /* validate public key */
+    static public func PUBLIC_KEY_VALIDATE(_ W:[UInt8]) -> Int
+    {
+        var WP=ECP.fromBytes(W);
+        var res=0;
+    
+        let r=BIG(ROM.CURVE_Order)
+    
+        if WP.is_infinity() {res=INVALID_PUBLIC_KEY}
+    
+        if res==0
+        {
+
+
+            let q=BIG(ROM.Modulus)
+            let nb=UInt(q.nbits())
+            var k=BIG(1); k.shl((nb+4)/2)
+            k.add(q)
+            k.div(r)
+
+            while k.parity()==0 {
+                k.shr(1)
+                WP.dbl()
+            }
+
+            if !k.isunity() {WP=WP.mul(k)}
+            if WP.is_infinity() {res=INVALID_PUBLIC_KEY} 
+
+        }
+        return res;
+    }
+    /* IEEE-1363 Diffie-Hellman online calculation Z=S.WD */
+    @discardableResult static public func ECPSVDP_DH(_ S:[UInt8],_ WD:[UInt8],_ Z:inout [UInt8]) -> Int
+    {
+        var res=0
+        var T=[UInt8](repeating: 0,count: ECDH.EFS)
+    
+        var s=BIG.fromBytes(S)
+    
+        var W=ECP.fromBytes(WD)
+        if W.is_infinity() {res=ECDH.ERROR}
+    
+        if (res==0)
+        {
+            let r=BIG(ROM.CURVE_Order)
+            s.mod(r)
+    
+            W=W.mul(s);
+            if W.is_infinity() {res=ERROR}
+            else
+            {
+                W.getX().toBytes(&T);
+                for i in 0 ..< ECDH.EFS {Z[i]=T[i]}
+            }
+        }
+        return res;
+    }
+    /* IEEE ECDSA Signature, C and D are signature on F using private key S */
+    static public func ECPSP_DSA(_ sha:Int,_ RNG: inout RAND,_ S:[UInt8],_ F:[UInt8],_ C:inout [UInt8],_ D:inout [UInt8]) -> Int
+    {
+        var T=[UInt8](repeating: 0,count: ECDH.EFS)
+        let B=hashit(sha,F,0,nil,Int(BIG.MODBYTES))
+    
+        let G=ECP.generator();  
+        let r=BIG(ROM.CURVE_Order)
+    
+        let s=BIG.fromBytes(S)
+        let f=BIG.fromBytes(B)
+    
+        var c=BIG(0)
+        var d=BIG(0)
+        var V=ECP()
+    
+        repeat {
+            var u=BIG.randomnum(r,&RNG);
+            let w=BIG.randomnum(r,&RNG);  /* side channel masking */
+  	    //if ROM.AES_S>0
+	    //{
+		//u.mod2m(2*ROM.AES_S)
+	    //}  
+            V.copy(G)
+            V=V.mul(u)
+            let vx=V.getX()
+            c.copy(vx)
+            c.mod(r)
+            if c.iszilch() {continue}
+            u.copy(BIG.modmul(u,w,r))
+            u.invmodp(r)
+            d.copy(BIG.modmul(s,c,r))
+            d.add(f)
+            d.copy(BIG.modmul(d,w,r))
+            d.copy(BIG.modmul(u,d,r))
+        } while d.iszilch()
+    
+        c.toBytes(&T)
+        for i in 0 ..< ECDH.EFS {C[i]=T[i]}
+        d.toBytes(&T)
+        for i in 0 ..< ECDH.EFS {D[i]=T[i]}
+        return 0;
+    }
+    
+    /* IEEE1363 ECDSA Signature Verification. Signature C and D on F is verified using public key W */
+    static public func ECPVP_DSA(_ sha:Int,_ W:[UInt8],_ F:[UInt8],_ C:[UInt8],_ D:[UInt8]) -> Int
+    {
+        var res=0
+        let B=hashit(sha,F,0,nil,Int(BIG.MODBYTES))
+    
+        let G=ECP.generator();
+        let r=BIG(ROM.CURVE_Order)
+    
+        let c=BIG.fromBytes(C)
+        var d=BIG.fromBytes(D)
+        var f=BIG.fromBytes(B)
+    
+        if c.iszilch() || BIG.comp(c,r)>=0 || d.iszilch() || BIG.comp(d,r)>=0
+            {res=ECDH.INVALID}
+    
+        if res==0
+        {
+            d.invmodp(r);
+            f.copy(BIG.modmul(f,d,r))
+            let h2=BIG.modmul(c,d,r)
+    
+            let WP=ECP.fromBytes(W)
+            if WP.is_infinity() {res=ECDH.ERROR}
+            else
+            {
+				var P=ECP();
+				P.copy(WP);
+				P=P.mul2(h2,G,f);
+                if P.is_infinity() {res=INVALID}
+				else
+				{
+                    d=P.getX();
+                    d.mod(r);
+                    if (BIG.comp(d,c) != 0) {res=ECDH.INVALID}
+				}
+            }
+        }
+    
+        return res;
+    }
+    
+    /* IEEE1363 ECIES encryption. Encryption of plaintext M uses public key W and produces ciphertext V,C,T */
+    static public func ECIES_ENCRYPT(_ sha:Int,_ P1:[UInt8],_ P2:[UInt8],_ RNG: inout RAND?,_ W:[UInt8],_ M:[UInt8],_ V:inout [UInt8],_ T:inout [UInt8]) -> [UInt8]
+    {
+        var Z=[UInt8](repeating: 0,count: ECDH.EFS)
+        var VZ=[UInt8](repeating: 0,count: 3*ECDH.EFS+1)
+        var K1=[UInt8](repeating: 0,count: ECP.AESKEY)
+        var K2=[UInt8](repeating: 0,count: ECP.AESKEY)
+        var U=[UInt8](repeating: 0,count: ECDH.EGS)
+
+
+        if ECDH.KEY_PAIR_GENERATE(&RNG,&U,&V) != 0 {return [UInt8]()}
+        if ECDH.ECPSVDP_DH(U,W,&Z) != 0 {return [UInt8]()}
+    
+        for i in 0 ..< 2*ECDH.EFS+1 {VZ[i]=V[i]}
+        for i in 0 ..< ECDH.EFS {VZ[2*ECDH.EFS+1+i]=Z[i]}
+    
+    
+        var K=KDF2(sha,VZ,P1,2*ECP.AESKEY)
+    
+        for i in 0 ..< ECP.AESKEY {K1[i]=K[i]; K2[i]=K[ECP.AESKEY+i];}
+    
+        var C=AES_CBC_IV0_ENCRYPT(K1,M)
+    
+        var L2=inttoBytes(P2.count,8)
+    
+        var AC=[UInt8](repeating: 0,count: C.count+P2.count+8)
+        
+        for i in 0 ..< C.count {AC[i]=C[i]}
+        for i in 0 ..< P2.count {AC[C.count+i]=P2[i]}
+        for i in 0 ..< 8 {AC[C.count+P2.count+i]=L2[i]}
+    
+        ECDH.HMAC(sha,AC,K2,&T)
+    
+        return C
+    }
+
+/* constant time n-byte compare */
+    static func ncomp(_ T1:[UInt8],_ T2:[UInt8],_ n:Int) -> Bool {
+	var res=0
+	for i in 0 ..< n {
+		res|=Int(T1[i]^T2[i])
+	}
+	if res==0 {return true}
+	return false
+    }
+
+    /* IEEE1363 ECIES decryption. Decryption of ciphertext V,C,T using private key U outputs plaintext M */
+    static public func ECIES_DECRYPT(_ sha:Int,_ P1:[UInt8],_ P2:[UInt8],_ V:[UInt8],_ C:[UInt8],_ T:[UInt8],_ U:[UInt8]) -> [UInt8]
+    {
+        var Z=[UInt8](repeating: 0,count: ECDH.EFS)
+        var VZ=[UInt8](repeating: 0,count: 3*ECDH.EFS+1)
+        var K1=[UInt8](repeating: 0,count: ECP.AESKEY)
+        var K2=[UInt8](repeating: 0,count: ECP.AESKEY)
+
+        var TAG=[UInt8](repeating: 0,count: T.count)
+    
+        if ECPSVDP_DH(U,V,&Z) != 0 {return [UInt8]()}
+    
+        for i in 0 ..< 2*ECDH.EFS+1 {VZ[i]=V[i]}
+        for i in 0 ..< ECDH.EFS {VZ[2*EFS+1+i]=Z[i]}
+    
+        var K=KDF2(sha,VZ,P1,2*ECP.AESKEY)
+    
+        for i in 0 ..< ECP.AESKEY {K1[i]=K[i]; K2[i]=K[ECP.AESKEY+i]}
+    
+        let M=ECDH.AES_CBC_IV0_DECRYPT(K1,C)
+    
+        if M.count==0 {return M}
+    
+        var L2=inttoBytes(P2.count,8)
+    
+        var AC=[UInt8](repeating: 0,count: C.count+P2.count+8)
+    
+        for i in 0 ..< C.count {AC[i]=C[i]}
+        for i in 0 ..< P2.count {AC[C.count+i]=P2[i]}
+        for i in 0 ..< 8 {AC[C.count+P2.count+i]=L2[i]}
+    
+        ECDH.HMAC(sha,AC,K2,&TAG)
+    
+	if !ncomp(T,TAG,T.count) {return [UInt8]()}	
+
+ //       var same=true
+ //       for i in 0 ..< T.count
+ //       {
+ //           if T[i] != TAG[i] {same=false}
+ //       }
+ //       if !same {return [UInt8]()}
+    
+        return M;
+    
+    }
+    
+}
diff --git a/version3/swift/ecp.swift b/version3/swift/ecp.swift
new file mode 100644
index 0000000..682ec22
--- /dev/null
+++ b/version3/swift/ecp.swift
@@ -0,0 +1,1070 @@
+/*
+	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.
+*/
+//
+//  ecp.swift
+//
+//  Created by Michael Scott on 30/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+
+public struct ECP {
+
+    static public let WEIERSTRASS=0
+    static public let EDWARDS=1
+    static public let MONTGOMERY=2
+    static public let NOT=0
+    static public let BN=1
+    static public let BLS=2
+    static public let D_TYPE=0
+    static public let M_TYPE=1
+    static public let POSITIVEX=0
+    static public let NEGATIVEX=1
+
+    static public let CURVETYPE = @CT@
+    static public let CURVE_PAIRING_TYPE = @PF@
+    static public let SEXTIC_TWIST = @ST@
+    static public let SIGN_OF_X = @SX@
+
+    static public let HASH_TYPE = @HT@
+    static public let AESKEY = @AK@
+
+    private var x:FP
+    private var y:FP
+    private var z:FP
+    //private var INF:Bool
+    
+   /* Constructor - set to O */
+    init()
+    {
+        x=FP(0)
+        y=FP(1)
+        if ECP.CURVETYPE==ECP.EDWARDS {
+		z=FP(1)
+	} else {
+		z=FP(0)
+	}
+    //    INF=true
+    }
+    
+    /* test for O point-at-infinity */
+    public func is_infinity() -> Bool
+    {
+        //if INF {return true}        
+        if (ECP.CURVETYPE==ECP.EDWARDS)
+        {
+            return x.iszilch() && y.equals(z)
+        }
+        if (ECP.CURVETYPE==ECP.WEIERSTRASS)
+        {
+            return x.iszilch() && z.iszilch()
+        }        
+        if (ECP.CURVETYPE==ECP.MONTGOMERY)     
+        {
+            return z.iszilch()
+        }   
+        return true
+    }
+ 
+    /* Conditional swap of P and Q dependant on d */
+    private mutating func cswap(_ Q: inout ECP,_ d:Int)
+    {
+        x.cswap(&(Q.x),d);
+        if ECP.CURVETYPE != ECP.MONTGOMERY {y.cswap(&(Q.y),d)}
+        z.cswap(&(Q.z),d);
+/*
+        var bd:Bool
+        if d==0 {bd=false}
+        else {bd=true}
+        bd=bd && (INF != Q.INF)
+        INF = (INF != bd)
+        Q.INF = (Q.INF != bd) */
+    }
+    
+    /* Conditional move of Q to P dependant on d */
+    private mutating func cmove(_ Q: ECP,_ d:Int)
+    {
+        x.cmove(Q.x,d);
+        if ECP.CURVETYPE != ECP.MONTGOMERY {y.cmove(Q.y,d)}
+        z.cmove(Q.z,d);
+   /*     var bd:Bool
+        if d==0 {bd=false}
+        else {bd=true}
+        INF = (INF != Q.INF) && bd; */
+    }
+    
+    /* return 1 if b==c, no branching */
+    private static func teq(_ b: Int32,_ c:Int32) -> Int
+    {
+        var x=b^c
+        x-=1  // if x=0, x now -1
+        return Int((x>>31)&1)
+    }
+ 
+    /* self=P */
+    public mutating func copy(_ P: ECP)
+    {
+        x.copy(P.x)
+        if ECP.CURVETYPE != ECP.MONTGOMERY {y.copy(P.y)}
+        z.copy(P.z)
+    //    INF=P.INF
+    }
+    /* self=-self */
+    mutating func neg() {
+    //    if is_infinity() {return}
+        if (ECP.CURVETYPE == ECP.WEIERSTRASS)
+        {
+            y.neg(); y.norm();
+        }
+        if (ECP.CURVETYPE == ECP.EDWARDS)
+        {
+            x.neg(); x.norm();
+        }
+        return;
+    }
+    
+    /* Constant time select from pre-computed table */
+    private mutating func select(_ W:[ECP],_ b:Int32)
+    {
+        var MP=ECP()
+        let m=b>>31
+        var babs=(b^m)-m
+    
+        babs=(babs-1)/2
+    
+        cmove(W[0],ECP.teq(babs,0)); // conditional move
+        cmove(W[1],ECP.teq(babs,1))
+        cmove(W[2],ECP.teq(babs,2))
+        cmove(W[3],ECP.teq(babs,3))
+        cmove(W[4],ECP.teq(babs,4))
+        cmove(W[5],ECP.teq(babs,5))
+        cmove(W[6],ECP.teq(babs,6))
+        cmove(W[7],ECP.teq(babs,7))
+    
+        MP.copy(self)
+        MP.neg()
+        cmove(MP,Int(m&1))
+    }
+    
+    /* Test P == Q */
+    func equals(_ Q: ECP) -> Bool
+    {
+    //    if (is_infinity() && Q.is_infinity()) {return true}
+    //    if (is_infinity() || Q.is_infinity()) {return false}
+ 
+        var a=FP(0)
+        var b=FP(0)
+        a.copy(x); a.mul(Q.z)
+        b.copy(Q.x); b.mul(z)
+        if !a.equals(b) {return false}
+        if ECP.CURVETYPE != ECP.MONTGOMERY
+        {
+			a.copy(y); a.mul(Q.z); 
+			b.copy(Q.y); b.mul(z); 
+			if !a.equals(b) {return false}
+        }
+        return true
+    }
+  
+    mutating func mulx(_ w: FP)
+    {
+        x.mul(w)
+    }
+
+/* set self=O */
+    mutating func inf()
+    {
+    //    INF=true;
+        x.zero()
+        if ECP.CURVETYPE != ECP.MONTGOMERY {y.one()}
+        if ECP.CURVETYPE != ECP.EDWARDS {z.zero()}
+        else {z.one()}
+    }
+    
+    /* Calculate RHS of curve equation */
+    static func RHS(_ x: FP) -> FP
+    {
+        var r=FP(x)
+        r.sqr()
+    
+        if ECP.CURVETYPE == ECP.WEIERSTRASS
+        { // x^3+Ax+B
+            let b=FP(BIG(ROM.CURVE_B))
+            r.mul(x)
+            if (ROM.CURVE_A == -3)
+            {
+				var cx=FP(x)
+				cx.imul(3)
+				cx.neg(); cx.norm()
+				r.add(cx)
+            }
+            r.add(b);
+        }
+        if (ECP.CURVETYPE == ECP.EDWARDS)
+        { // (Ax^2-1)/(Bx^2-1)
+            var b=FP(BIG(ROM.CURVE_B))
+    
+            let one=FP(1);
+            b.mul(r);
+            b.sub(one); b.norm()
+            if ROM.CURVE_A == -1 {r.neg()}
+            r.sub(one); r.norm()
+            b.inverse()
+            r.mul(b);
+        }
+        if ECP.CURVETYPE == ECP.MONTGOMERY
+        { // x^3+Ax^2+x
+            var x3=FP(0)
+            x3.copy(r);
+            x3.mul(x);
+            r.imul(ROM.CURVE_A);
+            r.add(x3);
+            r.add(x);
+        }
+        r.reduce();
+        return r;
+    }
+    
+    /* set (x,y) from two BIGs */
+    public init(_ ix: BIG,_ iy: BIG)
+    {
+        x=FP(ix)
+        y=FP(iy)
+        z=FP(1)
+    //    INF=true
+        x.norm()
+        let rhs=ECP.RHS(x);
+    
+        if ECP.CURVETYPE == ECP.MONTGOMERY
+        {
+            if rhs.jacobi() != 1 {inf()}
+        }
+        else
+        {
+            var y2=FP(y)
+            y2.sqr()
+            if !y2.equals(rhs) {inf()}
+        }
+    }
+    
+    /* set (x,y) from BIG and a bit */
+    public init(_ ix: BIG,_ s:Int)
+    {
+        x=FP(ix)
+        x.norm()
+        var rhs=ECP.RHS(x)
+        y=FP(0)
+        z=FP(1)
+    //    INF=true
+        if rhs.jacobi()==1
+        {
+            var ny=rhs.sqrt()
+            if (ny.redc().parity() != s) {ny.neg()}
+            y.copy(ny)
+   //         INF=false;
+        }
+        else {inf()}
+    }
+    
+    /* set from x - calculate y from curve equation */
+    public init(_ ix:BIG)
+    {
+        x=FP(ix)
+        x.norm()
+        var rhs=ECP.RHS(x)
+        y=FP(0)
+        z=FP(1)
+        if rhs.jacobi()==1
+        {
+            if ECP.CURVETYPE != ECP.MONTGOMERY {y.copy(rhs.sqrt())}
+         //   INF=false;
+        }
+        else {inf()}
+    }
+    
+    /* set to affine - from (x,y,z) to (x,y) */
+    mutating func affine()
+    {
+        if is_infinity() {return}
+        let one=FP(1)
+        if (z.equals(one)) {
+            x.reduce(); y.reduce()
+            return
+        }
+        z.inverse()
+
+        x.mul(z); x.reduce()
+        if ECP.CURVETYPE != ECP.MONTGOMERY
+        {
+            y.mul(z); y.reduce()
+ 
+        }
+        z.copy(one)
+    }
+    /* extract x as a BIG */
+    func getX() -> BIG
+    {
+        var W=ECP(); W.copy(self)
+        W.affine()
+        return W.x.redc()
+    }
+    /* extract y as a BIG */
+    func getY() -> BIG
+    {
+        var W=ECP(); W.copy(self)
+        W.affine();
+        return W.y.redc();
+    }
+    
+    /* get sign of Y */
+    func getS() -> Int
+    {
+        //affine()
+        let y=getY()
+        return y.parity()
+    }
+    /* extract x as an FP */
+    func getx() -> FP
+    {
+        return x;
+    }
+    /* extract y as an FP */
+    func gety() -> FP
+    {
+        return y;
+    }
+    /* extract z as an FP */
+    func getz() -> FP
+    {
+        return z;
+    }
+    /* convert to byte array */
+    func toBytes(_ b:inout [UInt8],_ compress: Bool)
+    {
+        let RM=Int(BIG.MODBYTES)
+        var t=[UInt8](repeating: 0,count: RM)
+        var W=ECP(); W.copy(self)
+        W.affine()
+        W.x.redc().toBytes(&t)
+        for i in 0 ..< RM {b[i+1]=t[i]}
+
+        if ECP.CURVETYPE == ECP.MONTGOMERY {
+		b[0]=0x06
+		return
+	}
+    
+	if compress {
+		b[0]=0x02
+		if W.y.redc().parity()==1 {b[0]=0x03}
+		return
+	}
+
+	b[0]=0x04
+
+        W.y.redc().toBytes(&t);
+        for i in 0 ..< RM {b[i+RM+1]=t[i]}
+    }
+    /* convert from byte array to point */
+    static func fromBytes(_ b: [UInt8]) -> ECP
+    {
+        let RM=Int(BIG.MODBYTES)
+        var t=[UInt8](repeating: 0,count: RM)
+        let p=BIG(ROM.Modulus);
+    
+        for i in 0 ..< RM {t[i]=b[i+1]}
+        let px=BIG.fromBytes(t)
+        if BIG.comp(px,p)>=0 {return ECP()}
+    
+        if ECP.CURVETYPE == ECP.MONTGOMERY {
+		return ECP(px)
+	}
+
+        if b[0]==0x04 {
+            for i in 0 ..< RM {t[i]=b[i+RM+1]}
+            let py=BIG.fromBytes(t)
+            if BIG.comp(py,p)>=0 {return ECP()}
+            return ECP(px,py)
+        }
+        
+	if b[0]==0x02 || b[0]==0x03 {
+	    return ECP(px,Int(b[0]&1))
+	}
+
+	return ECP()
+    }
+    /* convert to hex string */
+    func toString() -> String
+    {
+        var W=ECP(); W.copy(self)
+        if W.is_infinity() {return "infinity"}
+        W.affine();
+        if ECP.CURVETYPE==ECP.MONTGOMERY {return "("+W.x.redc().toString()+")"}
+        else {return "("+W.x.redc().toString()+","+W.y.redc().toString()+")"}
+    }
+    
+    /* self*=2 */
+    mutating func dbl()
+    {
+//        if INF {return} 
+        if (ECP.CURVETYPE == ECP.WEIERSTRASS)
+        {
+
+            if ROM.CURVE_A == 0
+            {
+                var t0=FP(y)        
+                t0.sqr()
+                var t1=FP(y)
+                t1.mul(z);
+                var t2=FP(z)
+                t2.sqr()
+
+                z.copy(t0)
+                z.add(t0); z.norm() 
+                z.add(z); z.add(z); z.norm()
+                t2.imul(3*ROM.CURVE_B_I)
+
+                var x3=FP(t2)
+                x3.mul(z)
+
+                var y3=FP(t0)
+                y3.add(t2); y3.norm()
+                z.mul(t1)
+                t1.copy(t2); t1.add(t2); t2.add(t1)
+                t0.sub(t2); t0.norm(); y3.mul(t0); y3.add(x3)
+                t1.copy(x); t1.mul(y)
+                x.copy(t0); x.norm(); x.mul(t1); x.add(x)
+                x.norm()
+                y.copy(y3); y.norm()
+            }
+            else {
+                var t0=FP(x)
+                var t1=FP(y)
+                var t2=FP(z)
+                var t3=FP(x)
+                var z3=FP(z)
+                var y3=FP(0)
+                var x3=FP(0)
+                var b=FP(0)
+
+                if ROM.CURVE_B_I==0
+                {
+                    b.copy(FP(BIG(ROM.CURVE_B)))
+                }
+
+                t0.sqr()  //1    x^2
+                t1.sqr()  //2    y^2
+                t2.sqr()  //3
+
+                t3.mul(y) //4
+                t3.add(t3); t3.norm()//5
+                z3.mul(x)   //6
+                z3.add(z3);  z3.norm()//7
+                y3.copy(t2) 
+                
+                if ROM.CURVE_B_I==0 {
+                    y3.mul(b) //8
+                }
+                else { 
+                    y3.imul(ROM.CURVE_B_I)
+                }
+
+                y3.sub(z3) //y3.norm(); //9  ***
+                x3.copy(y3); x3.add(y3); x3.norm()//10
+
+                y3.add(x3) //y3.norm();//11
+                x3.copy(t1); x3.sub(y3); x3.norm()//12
+                y3.add(t1); y3.norm()//13
+                y3.mul(x3) //14
+                x3.mul(t3) //15
+                t3.copy(t2); t3.add(t2) //t3.norm(); //16
+                t2.add(t3) //t2.norm(); //17
+
+                if ROM.CURVE_B_I==0 {
+                    z3.mul(b) //18
+                }
+                else {
+                    z3.imul(ROM.CURVE_B_I)
+                }
+
+                z3.sub(t2) //z3.norm();//19
+                z3.sub(t0); z3.norm()//20  ***
+                t3.copy(z3); t3.add(z3) //t3.norm();//21
+
+                z3.add(t3); z3.norm() //22
+                t3.copy(t0); t3.add(t0) //t3.norm(); //23
+                t0.add(t3) //t0.norm();//24
+                t0.sub(t2); t0.norm()//25
+
+                t0.mul(z3)//26
+                y3.add(t0) //y3.norm();//27
+                t0.copy(y); t0.mul(z)//28
+                t0.add(t0); t0.norm() //29
+                z3.mul(t0)//30
+                x3.sub(z3) //x3.norm();//31
+                t0.add(t0); t0.norm()//32
+                t1.add(t1); t1.norm()//33
+                z3.copy(t0); z3.mul(t1)//34
+
+                x.copy(x3); x.norm()
+                y.copy(y3); y.norm()
+                z.copy(z3); z.norm()                
+            }
+        }
+        if ECP.CURVETYPE == ECP.EDWARDS
+        {
+            var C=FP(x)
+            var D=FP(y)
+            var H=FP(z)
+            var J=FP(0)
+    
+            x.mul(y); x.add(x); x.norm()
+            C.sqr()
+            D.sqr()
+            if ROM.CURVE_A == -1 {C.neg()}
+            y.copy(C); y.add(D); y.norm()
+            H.sqr(); H.add(H)
+            z.copy(y)
+            J.copy(y); J.sub(H); J.norm()
+            x.mul(J)
+            C.sub(D); C.norm()
+            y.mul(C)
+            z.mul(J)
+    
+        }
+        if ECP.CURVETYPE == ECP.MONTGOMERY
+        {
+            var A=FP(x)
+            var B=FP(x);
+            var AA=FP(0);
+            var BB=FP(0);
+            var C=FP(0);
+        
+            A.add(z); A.norm()
+            AA.copy(A); AA.sqr()
+            B.sub(z); B.norm()
+            BB.copy(B); BB.sqr()
+            C.copy(AA); C.sub(BB); C.norm()
+    
+            x.copy(AA); x.mul(BB)
+    
+            A.copy(C); A.imul((ROM.CURVE_A+2)/4)
+    
+            BB.add(A); BB.norm()
+            z.copy(BB); z.mul(C)
+        }
+        return
+    }
+    
+    /* self+=Q */
+    mutating func add(_ Q:ECP)
+    {
+    /*    if (INF)
+        {
+            copy(Q)
+            return
+        }
+        if Q.INF {return} */
+
+        if ECP.CURVETYPE == ECP.WEIERSTRASS
+        {
+
+                if ROM.CURVE_A == 0
+                {
+                    let b=3*ROM.CURVE_B_I
+                    var t0=FP(x)
+                    t0.mul(Q.x)
+                    var t1=FP(y)
+                    t1.mul(Q.y)
+                    var t2=FP(z)
+                    t2.mul(Q.z)
+                    var t3=FP(x)
+                    t3.add(y); t3.norm()
+                    var t4=FP(Q.x)
+                    t4.add(Q.y); t4.norm()
+                    t3.mul(t4)
+                    t4.copy(t0); t4.add(t1)
+
+                    t3.sub(t4); t3.norm()
+                    t4.copy(y)
+                    t4.add(z); t4.norm()
+                    var x3=FP(Q.y)
+                    x3.add(Q.z); x3.norm()
+
+                    t4.mul(x3)
+                    x3.copy(t1)
+                    x3.add(t2)
+    
+                    t4.sub(x3); t4.norm()
+                    x3.copy(x); x3.add(z); x3.norm()
+                    var y3=FP(Q.x)
+                    y3.add(Q.z); y3.norm()
+                    x3.mul(y3)
+                    y3.copy(t0)
+                    y3.add(t2)
+                    y3.rsub(x3); y3.norm()
+                    x3.copy(t0); x3.add(t0)
+                    t0.add(x3); t0.norm()
+                    t2.imul(b);
+
+                    var z3=FP(t1); z3.add(t2); z3.norm()
+                    t1.sub(t2); t1.norm()
+                    y3.imul(b)
+    
+                    x3.copy(y3); x3.mul(t4); t2.copy(t3); t2.mul(t1); x3.rsub(t2)
+                    y3.mul(t0); t1.mul(z3); y3.add(t1)
+                    t0.mul(t3); z3.mul(t4); z3.add(t0)
+
+                    x.copy(x3); x.norm() 
+                    y.copy(y3); y.norm()
+                    z.copy(z3); z.norm()
+                } 
+                else {
+
+                    var t0=FP(x)
+                    var t1=FP(y)
+                    var t2=FP(z)
+                    var t3=FP(x)
+                    var t4=FP(Q.x)
+                    var z3=FP(0)
+                    var y3=FP(Q.x)
+                    var x3=FP(Q.y)
+                    var b=FP(0)
+
+                    if ROM.CURVE_B_I==0
+                    {
+                        b.copy(FP(BIG(ROM.CURVE_B)))
+                    }
+
+                    t0.mul(Q.x) //1
+                    t1.mul(Q.y) //2
+                    t2.mul(Q.z) //3
+
+                    t3.add(y); t3.norm() //4
+                    t4.add(Q.y); t4.norm()//5
+                    t3.mul(t4)//6
+                    t4.copy(t0); t4.add(t1) //t4.norm(); //7
+                    t3.sub(t4); t3.norm() //8
+                    t4.copy(y); t4.add(z); t4.norm()//9
+                    x3.add(Q.z); x3.norm()//10
+                    t4.mul(x3) //11
+                    x3.copy(t1); x3.add(t2) //x3.norm();//12
+
+                    t4.sub(x3); t4.norm()//13
+                    x3.copy(x); x3.add(z); x3.norm() //14
+                    y3.add(Q.z); y3.norm()//15
+
+                    x3.mul(y3) //16
+                    y3.copy(t0); y3.add(t2) //y3.norm();//17
+
+                    y3.rsub(x3); y3.norm() //18
+                    z3.copy(t2)
+                
+
+                    if ROM.CURVE_B_I==0
+                    {
+                        z3.mul(b) //18
+                    }
+                    else {
+                        z3.imul(ROM.CURVE_B_I)
+                    }
+                
+                    x3.copy(y3); x3.sub(z3); x3.norm() //20
+                    z3.copy(x3); z3.add(x3) //z3.norm(); //21
+
+                    x3.add(z3) //x3.norm(); //22
+                    z3.copy(t1); z3.sub(x3); z3.norm() //23
+                    x3.add(t1); x3.norm() //24
+
+                    if ROM.CURVE_B_I==0
+                    {
+                        y3.mul(b) //18
+                    }
+                    else {
+                        y3.imul(ROM.CURVE_B_I)
+                    }
+
+                    t1.copy(t2); t1.add(t2) //t1.norm();//26
+                    t2.add(t1) //t2.norm();//27
+
+                    y3.sub(t2) //y3.norm(); //28
+
+                    y3.sub(t0); y3.norm() //29
+                    t1.copy(y3); t1.add(y3) //t1.norm();//30
+                    y3.add(t1); y3.norm() //31
+
+                    t1.copy(t0); t1.add(t0) //t1.norm(); //32
+                    t0.add(t1) //t0.norm();//33
+                    t0.sub(t2); t0.norm()//34
+                    t1.copy(t4); t1.mul(y3)//35
+                    t2.copy(t0); t2.mul(y3)//36
+                    y3.copy(x3); y3.mul(z3)//37
+                    y3.add(t2) //y3.norm();//38
+                    x3.mul(t3)//39
+                    x3.sub(t1)//40
+                    z3.mul(t4)//41
+                    t1.copy(t3); t1.mul(t0)//42
+                    z3.add(t1)
+                    x.copy(x3); x.norm() 
+                    y.copy(y3); y.norm()
+                    z.copy(z3); z.norm()
+                }
+        }
+        if ECP.CURVETYPE == ECP.EDWARDS
+        {
+            let b=FP(BIG(ROM.CURVE_B))
+            var A=FP(z)
+            var B=FP(0)
+            var C=FP(x)
+            var D=FP(y)
+            var E=FP(0)
+            var F=FP(0)
+            var G=FP(0)
+    
+            A.mul(Q.z)
+            B.copy(A); B.sqr()
+            C.mul(Q.x)
+            D.mul(Q.y)
+    
+            E.copy(C); E.mul(D); E.mul(b)
+            F.copy(B); F.sub(E)
+            G.copy(B); G.add(E)
+    
+            if ROM.CURVE_A==1
+            {
+				E.copy(D); E.sub(C)
+            }
+            C.add(D)
+    
+            B.copy(x); B.add(y)
+            D.copy(Q.x); D.add(Q.y)
+            B.norm(); D.norm()
+            B.mul(D)
+            B.sub(C); B.norm(); F.norm()
+            B.mul(F)
+            x.copy(A); x.mul(B)
+            G.norm()
+            if ROM.CURVE_A==1
+            {
+				E.norm(); C.copy(E); C.mul(G)
+            }
+            if ROM.CURVE_A == -1
+            {
+				C.norm(); C.mul(G)
+            }
+            y.copy(A); y.mul(C)
+            z.copy(F); z.mul(G)
+
+        }
+        return;
+    }
+    
+    /* Differential Add for Montgomery curves. self+=Q where W is self-Q and is affine. */
+    mutating func dadd(_ Q:ECP,_ W:ECP)
+    {
+        var A=FP(x)
+        var B=FP(x)
+        var C=FP(Q.x)
+        var D=FP(Q.x)
+        var DA=FP(0)
+        var CB=FP(0)
+    
+        A.add(z)
+        B.sub(z)
+    
+        C.add(Q.z)
+        D.sub(Q.z)
+        A.norm()
+    
+        D.norm()
+        DA.copy(D); DA.mul(A)
+
+        C.norm();
+        B.norm();        
+        CB.copy(C); CB.mul(B)
+        
+        A.copy(DA); A.add(CB); A.norm(); A.sqr()
+        B.copy(DA); B.sub(CB); B.norm(); B.sqr()
+    
+        x.copy(A)
+        z.copy(W.x); z.mul(B)
+
+    }
+    /* this-=Q */
+    mutating func sub(_ Q:ECP)
+    {
+        var NQ=ECP(); NQ.copy(Q)
+        NQ.neg()
+        add(NQ)
+    }
+
+    /* constant time multiply by small integer of length bts - use ladder */
+    func pinmul(_ e:Int32,_ bts:Int32) -> ECP
+    {
+        if ECP.CURVETYPE == ECP.MONTGOMERY
+            {return self.mul(BIG(Int(e)))}
+        else
+        {
+            var P=ECP()
+            var R0=ECP()
+            var R1=ECP(); R1.copy(self)
+    
+            for i in (0...bts-1).reversed()
+            {
+				let b=Int(e>>i)&1;
+				P.copy(R1);
+				P.add(R0);
+				R0.cswap(&R1,b);
+				R1.copy(P);
+				R0.dbl();
+				R0.cswap(&R1,b);
+            }
+            P.copy(R0);
+            P.affine();
+            return P;
+        }
+    }
+    
+    /* return e.self */
+    
+    public func mul(_ e:BIG) -> ECP
+    {
+        if (e.iszilch() || is_infinity()) {return ECP()}
+    
+        var P=ECP()
+        if ECP.CURVETYPE == ECP.MONTGOMERY
+        {
+            /* use Ladder */
+            var D=ECP()
+            var R0=ECP(); R0.copy(self)
+            var R1=ECP(); R1.copy(self)
+            R1.dbl();
+            D.copy(self); D.affine();
+            let nb=e.nbits();
+            
+            for i in (0...nb-2).reversed()
+            {
+				let b=e.bit(UInt(i))
+                //print("\(b)")
+				P.copy(R1)
+				P.dadd(R0,D)
+				R0.cswap(&R1,b)
+				R1.copy(P)
+				R0.dbl()
+				R0.cswap(&R1,b)
+            }
+            P.copy(R0)
+        }
+        else
+        {
+    // fixed size windows
+            var mt=BIG()
+            var t=BIG()
+            var Q=ECP()
+            var C=ECP()
+            var W=[ECP]()
+            let n=1+(BIG.NLEN*Int(BIG.BASEBITS)+3)/4
+            var w=[Int8](repeating: 0,count: n)
+    
+            //affine();
+    
+    // precompute table
+            Q.copy(self)
+            Q.dbl()
+            W.append(ECP())
+            
+            W[0].copy(self)
+    
+            for i in 1 ..< 8
+            {
+                W.append(ECP())
+				W[i].copy(W[i-1])
+				W[i].add(Q)
+            }
+    
+    // make exponent odd - add 2P if even, P if odd
+            t.copy(e);
+            let s=t.parity();
+            t.inc(1); t.norm(); let ns=t.parity();
+            mt.copy(t); mt.inc(1); mt.norm();
+            t.cmove(mt,s);
+            Q.cmove(self,ns);
+            C.copy(Q);
+    
+            let nb=1+(t.nbits()+3)/4;
+    
+    // convert exponent to signed 4-bit window
+            for i in 0 ..< nb
+            {
+				w[i]=Int8(t.lastbits(5)-16);
+				t.dec(Int(w[i]));
+                t.norm();
+				t.fshr(4);
+            }
+            w[nb]=Int8(t.lastbits(5))
+    
+            P.copy(W[Int((w[nb])-1)/2]);
+            for i in (0...nb-1).reversed()
+            {
+				Q.select(W,Int32(w[i]));
+				P.dbl();
+				P.dbl();
+				P.dbl();
+				P.dbl();
+				P.add(Q);
+            }
+            P.sub(C); /* apply correction */
+        }
+        P.affine();
+        return P;
+    }
+    
+    /* Return e.this+f.Q */
+    
+    public func mul2(_ e:BIG,_ Q:ECP,_ f:BIG) -> ECP
+    {
+        var te=BIG()
+        var tf=BIG()
+        var mt=BIG()
+        var S=ECP()
+        var T=ECP()
+        var C=ECP()
+        var W=[ECP]()
+        let n=1+(BIG.NLEN*Int(BIG.BASEBITS)+1)/2
+        var w=[Int8](repeating: 0,count: n);
+        
+        //affine();
+        //Q.affine();
+    
+        te.copy(e);
+        tf.copy(f);
+    
+    // precompute table
+        for _ in 0 ..< 8 {W.append(ECP())}
+        W[1].copy(self); W[1].sub(Q)
+        W[2].copy(self); W[2].add(Q)
+        S.copy(Q); S.dbl();
+        W[0].copy(W[1]); W[0].sub(S)
+        W[3].copy(W[2]); W[3].add(S)
+        T.copy(self); T.dbl()
+        W[5].copy(W[1]); W[5].add(T)
+        W[6].copy(W[2]); W[6].add(T)
+        W[4].copy(W[5]); W[4].sub(S)
+        W[7].copy(W[6]); W[7].add(S)
+    
+    
+    // if multiplier is odd, add 2, else add 1 to multiplier, and add 2P or P to correction
+    
+        var s=te.parity()
+        te.inc(1); te.norm(); var ns=te.parity(); mt.copy(te); mt.inc(1); mt.norm()
+        te.cmove(mt,s)
+        T.cmove(self,ns)
+        C.copy(T)
+    
+        s=tf.parity()
+        tf.inc(1); tf.norm(); ns=tf.parity(); mt.copy(tf); mt.inc(1); mt.norm()
+        tf.cmove(mt,s)
+        S.cmove(Q,ns)
+        C.add(S)
+    
+        mt.copy(te); mt.add(tf); mt.norm()
+        let nb=1+(mt.nbits()+1)/2
+    
+    // convert exponent to signed 2-bit window
+        for i in 0 ..< nb
+        {
+            let a=(te.lastbits(3)-4);
+            te.dec(a); te.norm();
+            te.fshr(2);
+            let b=(tf.lastbits(3)-4);
+            tf.dec(b); tf.norm();
+            tf.fshr(2);
+            w[i]=Int8(4*a+b);
+        }
+        w[nb]=Int8(4*te.lastbits(3)+tf.lastbits(3));
+        S.copy(W[Int(w[nb]-1)/2]);
+        for i in (0...nb-1).reversed()
+        {
+            T.select(W,Int32(w[i]));
+            S.dbl();
+            S.dbl();
+            S.add(T);
+        }
+        S.sub(C); /* apply correction */
+        S.affine();
+        return S;
+    }
+    
+   mutating func cfp()
+   {
+
+	let cf=ROM.CURVE_Cof_I;
+	if cf==1 {return}
+	if cf==4 {
+		dbl(); dbl()
+		//affine()
+		return
+	} 
+	if cf==8 {
+		dbl(); dbl(); dbl()
+		//affine()
+		return;
+	}
+	let c=BIG(ROM.CURVE_Cof);
+	copy(mul(c));
+
+   }
+
+    static func mapit(_ h:[UInt8]) -> ECP
+    {
+        let q=BIG(ROM.Modulus)
+        var x=BIG.fromBytes(h)
+        x.mod(q)
+        var P=ECP()
+        while (true) {
+		while (true) {
+			if ECP.CURVETYPE != ECP.MONTGOMERY {
+				P.copy(ECP(x,0))
+			} else {
+				P.copy(ECP(x))
+			}
+			x.inc(1); x.norm();
+			if !P.is_infinity() {break}
+		}
+		P.cfp()
+		if !P.is_infinity() {break}
+	}
+
+        return P
+    }    
+   
+    static public func generator() -> ECP
+    {
+        let gx=BIG(ROM.CURVE_Gx);
+        var G:ECP
+        if ECP.CURVETYPE != ECP.MONTGOMERY
+        {
+            let gy=BIG(ROM.CURVE_Gy)
+            G=ECP(gx,gy)
+        }
+        else
+            {G=ECP(gx)}   
+        return G     
+    }
+    
+}
diff --git a/version3/swift/ecp2.swift b/version3/swift/ecp2.swift
new file mode 100644
index 0000000..d3cab0c
--- /dev/null
+++ b/version3/swift/ecp2.swift
@@ -0,0 +1,735 @@
+/*
+	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.
+*/
+//
+//  ecp2.swift
+//
+//  Created by Michael Scott on 07/07/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+/* AMCL Weierstrass elliptic curve functions over FP2 */
+
+public struct ECP2 {
+    private var x:FP2
+    private var y:FP2
+    private var z:FP2
+ //   private var INF:Bool
+    
+    /* Constructor - set self=O */
+    init()
+    {
+    //    INF=true
+        x=FP2(0)
+        y=FP2(1)
+        z=FP2(0)
+    }
+    /* Test self=O? */
+    public func is_infinity() -> Bool
+    {
+    //    if INF {return true}
+        return x.iszilch() && z.iszilch()
+    }
+    /* copy self=P */
+    mutating public func copy(_ P:ECP2)
+    {
+        x.copy(P.x)
+        y.copy(P.y)
+        z.copy(P.z)
+    //    INF=P.INF
+    }
+    /* set self=O */
+    mutating func inf() {
+    //    INF=true
+        x.zero()
+        y.one()
+        z.zero()
+    }
+    /* Conditional move of Q to P dependant on d */
+    mutating func cmove(_ Q:ECP2,_ d:Int)
+    {
+        x.cmove(Q.x,d);
+        y.cmove(Q.y,d);
+        z.cmove(Q.z,d);
+    /*
+        var bd:Bool
+        if d==0 {bd=false}
+        else {bd=true}
+        INF = (INF != ((INF != Q.INF) && bd)) */
+    }
+    
+    /* return 1 if b==c, no branching */
+    private static func teq(_ b:Int32,_ c:Int32) -> Int
+    {
+        var x=b^c
+        x-=1  // if x=0, x now -1
+        return Int((x>>31)&1)
+    }
+    /* Constant time select from pre-computed table */
+    mutating func select(_ W:[ECP2],_ b:Int32)
+    {
+        var MP=ECP2()
+        let m=b>>31
+        var babs=(b^m)-m
+        
+        babs=(babs-1)/2
+    
+        cmove(W[0],ECP2.teq(babs,0)) // conditional move
+        cmove(W[1],ECP2.teq(babs,1))
+        cmove(W[2],ECP2.teq(babs,2))
+        cmove(W[3],ECP2.teq(babs,3))
+        cmove(W[4],ECP2.teq(babs,4))
+        cmove(W[5],ECP2.teq(babs,5))
+        cmove(W[6],ECP2.teq(babs,6))
+        cmove(W[7],ECP2.teq(babs,7))
+    
+        MP.copy(self)
+        MP.neg()
+        cmove(MP,Int(m&1))
+    }
+ 
+    /* Test if P == Q */
+    func equals(_ Q:ECP2) -> Bool
+    {
+    //    if is_infinity() && Q.is_infinity() {return true}
+    //    if is_infinity() || Q.is_infinity() {return false}
+    
+        var a=FP2(x)                            // *****
+        var b=FP2(Q.x)
+        a.mul(Q.z); b.mul(z) 
+        if !a.equals(b) {return false}
+        a.copy(y); a.mul(Q.z)
+        b.copy(Q.y); b.mul(z)
+        if !a.equals(b) {return false}
+    
+        return true;
+    }
+    /* set self=-self */
+    mutating func neg()
+    {
+    //    if is_infinity() {return}
+        y.norm(); y.neg(); y.norm()
+        return
+    }
+    /* set to Affine - (x,y,z) to (x,y) */
+    mutating func affine() {
+        if is_infinity() {return}
+        let one=FP2(1)
+        if z.equals(one) {
+            x.reduce(); y.reduce()
+            return
+        }
+        z.inverse()
+    
+        x.mul(z); x.reduce()
+        y.mul(z); y.reduce()
+        z.copy(one)
+    }
+    /* extract affine x as FP2 */
+    func getX() -> FP2
+    {
+        var W=ECP2(); W.copy(self)
+        W.affine()
+        return W.x
+    }
+    /* extract affine y as FP2 */
+    func getY() -> FP2
+    {
+        var W=ECP2(); W.copy(self)
+        W.affine()
+        return W.y
+    }
+    /* extract projective x */
+    func getx() -> FP2
+    {
+        return x
+    }
+    /* extract projective y */
+    func gety() -> FP2
+    {
+        return y
+    }
+    /* extract projective z */
+    func getz() -> FP2
+    {
+        return z
+    }
+    /* convert to byte array */
+    func toBytes(_ b:inout [UInt8])
+    {
+        let RM=Int(BIG.MODBYTES)
+        var t=[UInt8](repeating: 0,count: RM)
+        var W=ECP2(); W.copy(self)
+
+        W.affine();
+        W.x.getA().toBytes(&t)
+        for i in 0 ..< RM
+            {b[i]=t[i]}
+        W.x.getB().toBytes(&t);
+        for i in 0 ..< RM
+            {b[i+RM]=t[i]}
+    
+        W.y.getA().toBytes(&t);
+        for i in 0 ..< RM
+            {b[i+2*RM]=t[i]}
+        W.y.getB().toBytes(&t);
+        for i in 0 ..< RM
+            {b[i+3*RM]=t[i]}
+    }
+    /* convert from byte array to point */
+    static func fromBytes(_ b:[UInt8]) -> ECP2
+    {
+        let RM=Int(BIG.MODBYTES)
+        var t=[UInt8](repeating: 0,count: RM)
+
+    
+        for i in 0 ..< RM {t[i]=b[i]}
+        var ra=BIG.fromBytes(t);
+        for i in 0 ..< RM {t[i]=b[i+RM]}
+        var rb=BIG.fromBytes(t);
+        let rx=FP2(ra,rb)
+    
+        for i in 0 ..< RM {t[i]=b[i+2*RM]}
+        ra=BIG.fromBytes(t)
+        for i in 0 ..< RM {t[i]=b[i+3*RM]}
+        rb=BIG.fromBytes(t)
+        let ry=FP2(ra,rb)
+    
+        return ECP2(rx,ry)
+    }
+/* convert self to hex string */
+    func toString() -> String
+    {
+        var W=ECP2(); W.copy(self)
+        if W.is_infinity() {return "infinity"}
+        W.affine()
+        return "("+W.x.toString()+","+W.y.toString()+")"
+    }
+    
+/* Calculate RHS of twisted curve equation x^3+B/i */
+    static func RHS(_ x:FP2) -> FP2
+    {
+        //x.norm()
+        var r=FP2(x)
+        r.sqr()
+        var b=FP2(BIG(ROM.CURVE_B))
+        if ECP.SEXTIC_TWIST == ECP.D_TYPE {
+            b.div_ip()
+        }
+        if ECP.SEXTIC_TWIST == ECP.M_TYPE {
+            b.norm()
+            b.mul_ip()
+            b.norm()
+        }
+        r.mul(x)
+        r.add(b)
+    
+        r.reduce()
+        return r
+    }
+/* construct self from (x,y) - but set to O if not on curve */
+    public init(_ ix:FP2,_ iy:FP2)
+    {
+        x=FP2(ix)
+        y=FP2(iy)
+        z=FP2(1)
+        x.norm()
+        let rhs=ECP2.RHS(x)
+        var y2=FP2(y)
+        y2.sqr()
+        if !y2.equals(rhs) {inf()}
+    }
+    /* construct this from x - but set to O if not on curve */
+    init(_ ix:FP2)
+    {
+        x=FP2(ix)
+        y=FP2(1)
+        z=FP2(1)
+        x.norm()
+        var rhs=ECP2.RHS(x)
+        if rhs.sqrt()
+        {
+            y.copy(rhs);
+        //    INF=false;
+        }
+        else {inf()}
+    }
+    
+    /* this+=this */
+    @discardableResult mutating func dbl() -> Int
+    {
+    //    if (INF) {return -1}
+        if y.iszilch()
+        {
+            inf();
+            return -1;
+        }
+    
+        var iy=FP2(y)
+        if ECP.SEXTIC_TWIST == ECP.D_TYPE {       
+            iy.mul_ip(); iy.norm()
+        }
+
+        var t0=FP2(y) 
+        t0.sqr();
+        if ECP.SEXTIC_TWIST == ECP.D_TYPE {           
+            t0.mul_ip() 
+        }  
+        var t1=FP2(iy)  
+        t1.mul(z)
+        var t2=FP2(z)
+        t2.sqr()
+
+        z.copy(t0)
+        z.add(t0); z.norm() 
+        z.add(z)
+        z.add(z) 
+        z.norm()  
+
+        t2.imul(3*ROM.CURVE_B_I) 
+        if ECP.SEXTIC_TWIST == ECP.M_TYPE {
+            t2.mul_ip()
+            t2.norm()   
+        }
+        var x3=FP2(t2)
+        x3.mul(z) 
+
+        var y3=FP2(t0)   
+
+        y3.add(t2); y3.norm()
+        z.mul(t1)
+        t1.copy(t2); t1.add(t2); t2.add(t1); t2.norm()  
+        t0.sub(t2); t0.norm()                           //y^2-9bz^2
+        y3.mul(t0); y3.add(x3)                          //(y^2+3z*2)(y^2-9z^2)+3b.z^2.8y^2
+        t1.copy(x); t1.mul(iy)                     //
+        x.copy(t0); x.norm(); x.mul(t1); x.add(x)       //(y^2-9bz^2)xy2
+
+        x.norm() 
+        y.copy(y3); y.norm()
+        return 1
+    }
+/* this+=Q - return 0 for add, 1 for double, -1 for O */
+    @discardableResult mutating func add(_ Q:ECP2) -> Int
+    {
+    /*    if INF
+        {
+            copy(Q)
+            return -1
+        }
+        if Q.INF {return -1} */
+
+        let b=3*ROM.CURVE_B_I
+        var t0=FP2(x)
+        t0.mul(Q.x)         // x.Q.x
+        var t1=FP2(y)
+        t1.mul(Q.y)         // y.Q.y
+
+        var t2=FP2(z)
+        t2.mul(Q.z)
+        var t3=FP2(x)
+        t3.add(y); t3.norm()          //t3=X1+Y1
+        var t4=FP2(Q.x)            
+        t4.add(Q.y); t4.norm()         //t4=X2+Y2
+        t3.mul(t4)                     //t3=(X1+Y1)(X2+Y2)
+        t4.copy(t0); t4.add(t1)        //t4=X1.X2+Y1.Y2
+
+        t3.sub(t4); t3.norm(); 
+        if ECP.SEXTIC_TWIST == ECP.D_TYPE {
+            t3.mul_ip();  t3.norm()         //t3=(X1+Y1)(X2+Y2)-(X1.X2+Y1.Y2) = X1.Y2+X2.Y1
+        }
+        t4.copy(y)                    
+        t4.add(z); t4.norm()           //t4=Y1+Z1
+        var x3=FP2(Q.y)
+        x3.add(Q.z); x3.norm()         //x3=Y2+Z2
+
+        t4.mul(x3)                     //t4=(Y1+Z1)(Y2+Z2)
+        x3.copy(t1)                    //
+        x3.add(t2)                     //X3=Y1.Y2+Z1.Z2
+    
+        t4.sub(x3); t4.norm(); 
+        if ECP.SEXTIC_TWIST == ECP.D_TYPE {  
+            t4.mul_ip(); t4.norm()          //t4=(Y1+Z1)(Y2+Z2) - (Y1.Y2+Z1.Z2) = Y1.Z2+Y2.Z1
+        }
+        x3.copy(x); x3.add(z); x3.norm()   // x3=X1+Z1
+        var y3=FP2(Q.x)                
+        y3.add(Q.z); y3.norm()             // y3=X2+Z2
+        x3.mul(y3)                         // x3=(X1+Z1)(X2+Z2)
+        y3.copy(t0)
+        y3.add(t2)                         // y3=X1.X2+Z1+Z2
+        y3.rsub(x3); y3.norm()             // y3=(X1+Z1)(X2+Z2) - (X1.X2+Z1.Z2) = X1.Z2+X2.Z1
+        if ECP.SEXTIC_TWIST == ECP.D_TYPE {  
+            t0.mul_ip(); t0.norm() // x.Q.x
+            t1.mul_ip(); t1.norm() // y.Q.y
+        }
+        x3.copy(t0); x3.add(t0) 
+        t0.add(x3); t0.norm()
+        t2.imul(b)
+        if ECP.SEXTIC_TWIST == ECP.M_TYPE {
+            t2.mul_ip(); t2.norm()
+        }  
+        var z3=FP2(t1); z3.add(t2); z3.norm()
+        t1.sub(t2); t1.norm()
+        y3.imul(b)
+        if ECP.SEXTIC_TWIST == ECP.M_TYPE {          
+            y3.mul_ip()
+            y3.norm()
+        }
+        x3.copy(y3); x3.mul(t4); t2.copy(t3); t2.mul(t1); x3.rsub(t2)
+        y3.mul(t0); t1.mul(z3); y3.add(t1)
+        t0.mul(t3); z3.mul(t4); z3.add(t0)
+
+        x.copy(x3); x.norm()
+        y.copy(y3); y.norm()
+        z.copy(z3); z.norm()    
+
+        return 0
+    }
+
+    /* set self-=Q */
+    @discardableResult mutating func sub(_ Q:ECP2) -> Int
+    {
+        var NQ=ECP2(); NQ.copy(Q)
+        NQ.neg()
+        let D=add(NQ)
+        //Q.neg()
+        return D
+    }
+/* set self*=q, where q is Modulus, using Frobenius */
+    mutating func frob(_ X:FP2)
+    {
+    //    if INF {return}
+        var X2=FP2(X)
+        X2.sqr()
+        x.conj()
+        y.conj()
+        z.conj()
+        z.reduce()
+        x.mul(X2)
+        y.mul(X2)
+        y.mul(X)
+    }
+    
+    /* P*=e */
+    func mul(_ e:BIG) -> ECP2
+    {
+    /* fixed size windows */
+        var mt=BIG()
+        var t=BIG()
+        var P=ECP2()
+        var Q=ECP2()
+        var C=ECP2()
+        
+        var W=[ECP2]();
+        for _ in 0 ..< 8 {W.append(ECP2())}
+        
+        var w=[Int8](repeating: 0,count: 1+(BIG.NLEN*Int(BIG.BASEBITS)+3)/4)
+    
+        if is_infinity() {return ECP2()}
+    
+        //affine()
+    
+    /* precompute table */
+        Q.copy(self)
+        Q.dbl()
+        W[0].copy(self)
+    
+        for i in 1 ..< 8
+        {
+            W[i].copy(W[i-1])
+            W[i].add(Q)
+        }
+    
+    /* make exponent odd - add 2P if even, P if odd */
+        t.copy(e)
+        let s=t.parity()
+        t.inc(1); t.norm(); let ns=t.parity(); mt.copy(t); mt.inc(1); mt.norm()
+        t.cmove(mt,s)
+        Q.cmove(self,ns)
+        C.copy(Q)
+    
+        let nb=1+(t.nbits()+3)/4
+    /* convert exponent to signed 4-bit window */
+        for i in 0 ..< nb
+        {
+            w[i]=Int8(t.lastbits(5)-16)
+            t.dec(Int(w[i])); t.norm()
+            t.fshr(4)
+        }
+        w[nb]=Int8(t.lastbits(5))
+    
+        P.copy(W[Int(w[nb]-1)/2])
+        for i in (0...nb-1).reversed()
+        //for var i=nb-1;i>=0;i--
+        {
+            Q.select(W,Int32(w[i]))
+            P.dbl()
+            P.dbl()
+            P.dbl()
+            P.dbl()
+            P.add(Q)
+        }
+        P.sub(C);
+        P.affine()
+        return P;
+    }
+    
+    /* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3 */
+    // Bos & Costello https://eprint.iacr.org/2013/458.pdf
+    // Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
+    // Side channel attack secure 
+
+    static func mul4(_ Q:[ECP2],_ u:[BIG]) -> ECP2
+    {
+        var W=ECP2()
+        var P=ECP2()
+        
+        var T=[ECP2]();
+        for _ in 0 ..< 8 {T.append(ECP2())}
+    
+        var mt=BIG()
+        var t=[BIG]()
+    
+        var w=[Int8](repeating: 0,count: BIG.NLEN*Int(BIG.BASEBITS)+1)
+        var s=[Int8](repeating: 0,count: BIG.NLEN*Int(BIG.BASEBITS)+1)
+    
+        for i in 0 ..< 4
+        {
+            t.append(BIG(u[i]))
+            t[i].norm()
+            //Q[i].affine()
+        }
+
+    // precompute table 
+
+        T[0].copy(Q[0])  // Q[0]
+        T[1].copy(T[0]); T[1].add(Q[1])  // Q[0]+Q[1]
+        T[2].copy(T[0]); T[2].add(Q[2])  // Q[0]+Q[2]
+        T[3].copy(T[1]); T[3].add(Q[2])  // Q[0]+Q[1]+Q[2]
+        T[4].copy(T[0]); T[4].add(Q[3])  // Q[0]+Q[3]
+        T[5].copy(T[1]); T[5].add(Q[3])  // Q[0]+Q[1]+Q[3]
+        T[6].copy(T[2]); T[6].add(Q[3])  // Q[0]+Q[2]+Q[3]
+        T[7].copy(T[3]); T[7].add(Q[3])  // Q[0]+Q[1]+Q[2]+Q[3]
+
+// Make it odd
+        let pb=1-t[0].parity()
+        t[0].inc(pb)
+        t[0].norm()  
+
+// Number of bits
+        mt.zero();
+        for i in 0 ..< 4 {
+            mt.or(t[i]); 
+        }
+
+        let nb=1+mt.nbits()
+
+// Sign pivot 
+
+        s[nb-1]=1
+        for i in 0 ..< nb-1 {
+            t[0].fshr(1)
+            s[i]=2*Int8(t[0].parity())-1
+        }
+
+// Recoded exponent
+        for i in 0 ..< nb {
+            w[i]=0
+            var k=1
+            for j in 1 ..< 4 {
+                let bt=s[i]*Int8(t[j].parity())
+                t[j].fshr(1)
+                t[j].dec(Int(bt>>1))
+                t[j].norm()
+                w[i]+=bt*Int8(k)
+                k=2*k
+            }
+        }   
+
+// Main loop
+        P.select(T,Int32(2*w[nb-1]+1));
+        for i in (0 ..< nb-1).reversed() {
+            P.dbl()
+            W.select(T,Int32(2*w[i]+s[i]))
+            P.add(W)
+        }    
+
+        W.copy(P)  
+        W.sub(Q[0])
+        P.cmove(W,pb) 
+        P.affine()
+        return P
+    }
+
+    /* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3 */
+/*    
+    static func mul4(_ Q:[ECP2],_ u:[BIG]) -> ECP2
+    {
+        var a=[Int32](repeating: 0,count: 4)
+        let T=ECP2()
+        let C=ECP2()
+        let P=ECP2()
+        
+        var W=[ECP2]();
+        for _ in 0 ..< 8 {W.append(ECP2())}
+    
+        let mt=BIG()
+        var t=[BIG]()
+    
+        var w=[Int8](repeating: 0,count: BIG.NLEN*Int(BIG.BASEBITS)+1)
+    
+        for i in 0 ..< 4
+        {
+            t.append(BIG(u[i]))
+            //Q[i].affine()
+        }
+    
+    // precompute table 
+    
+        W[0].copy(Q[0]); W[0].sub(Q[1])
+        W[1].copy(W[0])
+        W[2].copy(W[0])
+        W[3].copy(W[0])
+        W[4].copy(Q[0]); W[4].add(Q[1])
+        W[5].copy(W[4])
+        W[6].copy(W[4])
+        W[7].copy(W[4])
+        T.copy(Q[2]); T.sub(Q[3])
+        W[1].sub(T)
+        W[2].add(T)
+        W[5].sub(T)
+        W[6].add(T)
+        T.copy(Q[2]); T.add(Q[3])
+        W[0].sub(T)
+        W[3].add(T)
+        W[4].sub(T)
+        W[7].add(T)
+    
+    // if multiplier is even add 1 to multiplier, and add P to correction 
+        mt.zero(); C.inf()
+        for i in 0 ..< 4
+        {
+            if (t[i].parity()==0)
+            {
+				t[i].inc(1); t[i].norm()
+                C.add(Q[i])
+            }
+            mt.add(t[i]); mt.norm()
+        }
+    
+        let nb=1+mt.nbits();
+    
+    // convert exponent to signed 1-bit window 
+        for j in 0 ..< nb
+        {
+            	for i in 0 ..< 4 {
+			a[i]=Int32(t[i].lastbits(2)-2)
+                
+			t[i].dec(Int(a[i]))
+                	t[i].norm()
+			t[i].fshr(1)
+            	}
+		let sum=8*a[0]+4*a[1]+2*a[2]+a[3]
+            	w[j]=Int8(sum)
+        }
+        w[nb]=Int8(8*t[0].lastbits(2)+4*t[1].lastbits(2))
+        w[nb]+=Int8(2*t[2].lastbits(2)+t[3].lastbits(2))
+    
+        P.copy(W[Int(w[nb]-1)/2])
+        for i in (0...nb-1).reversed()
+        //for var i=nb-1;i>=0;i--
+        {
+            T.select(W,Int32(w[i]))
+            P.dbl()
+            P.add(T)
+        }
+        P.sub(C) // apply correction 
+    
+        P.affine()
+        return P
+    }
+*/    
+     // needed for SOK
+    static func mapit(_ h:[UInt8]) -> ECP2
+    {
+        let q=BIG(ROM.Modulus)
+        var x=BIG.fromBytes(h)
+        let one=BIG(1)
+        var Q=ECP2()
+        x.mod(q);
+        while (true)
+        {
+            let X=FP2(one,x);
+            Q=ECP2(X);
+            if !Q.is_infinity() {break}
+            x.inc(1); x.norm();
+        }
+    // Fast Hashing to G2 - Fuentes-Castaneda, Knapp and Rodriguez-Henriquez
+        let Fra=BIG(ROM.Fra);
+        let Frb=BIG(ROM.Frb);
+        var X=FP2(Fra,Frb);
+        if ECP.SEXTIC_TWIST == ECP.M_TYPE { 
+            X.inverse()
+            X.norm()
+        }         
+        x=BIG(ROM.CURVE_Bnx);
+    
+        if ECP.CURVE_PAIRING_TYPE == ECP.BN {
+            var T=Q.mul(x); 
+            if ECP.SIGN_OF_X == ECP.NEGATIVEX {
+                T.neg()
+            }
+            var K=ECP2(); K.copy(T)
+            K.dbl(); K.add(T); //K.affine()
+    
+            K.frob(X)
+            Q.frob(X); Q.frob(X); Q.frob(X)
+            Q.add(T); Q.add(K)
+            T.frob(X); T.frob(X)
+            Q.add(T)
+        }
+        if ECP.CURVE_PAIRING_TYPE == ECP.BLS {
+            var xQ=Q.mul(x);
+            var x2Q=xQ.mul(x);
+
+            if ECP.SIGN_OF_X == ECP.NEGATIVEX {
+                xQ.neg()
+            }
+
+            x2Q.sub(xQ)
+            x2Q.sub(Q)
+
+            xQ.sub(Q)
+            xQ.frob(X)
+
+            Q.dbl()
+            Q.frob(X)
+            Q.frob(X)
+
+            Q.add(x2Q)
+            Q.add(xQ)
+        }        
+        Q.affine()
+        return Q
+    }   
+    
+    static public func generator() -> ECP2
+    {
+        return ECP2(FP2(BIG(ROM.CURVE_Pxa),BIG(ROM.CURVE_Pxb)),FP2(BIG(ROM.CURVE_Pya),BIG(ROM.CURVE_Pyb)))
+    }
+
+}
diff --git a/version3/swift/ecp4.swift b/version3/swift/ecp4.swift
new file mode 100644
index 0000000..c0521ef
--- /dev/null
+++ b/version3/swift/ecp4.swift
@@ -0,0 +1,739 @@
+/*
+	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.
+*/
+//
+//  ecp4.swift
+//
+//  Created by Michael Scott on 07/07/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+/* AMCL Weierstrass elliptic curve functions over FP4 */
+
+public struct ECP4 {
+    private var x:FP4
+    private var y:FP4
+    private var z:FP4
+ //   private var INF:Bool
+    
+    /* Constructor - set self=O */
+    init()
+    {
+    //    INF=true
+        x=FP4(0)
+        y=FP4(1)
+        z=FP4(0)
+    }
+    /* Test self=O? */
+    public func is_infinity() -> Bool
+    {
+    //    if INF {return true}
+        return x.iszilch() && z.iszilch()
+    }
+    /* copy self=P */
+    public mutating func copy(_ P:ECP4)
+    {
+        x.copy(P.x)
+        y.copy(P.y)
+        z.copy(P.z)
+    //    INF=P.INF
+    }
+    /* set self=O */
+    mutating func inf() {
+    //    INF=true
+        x.zero()
+        y.one()
+        z.zero()
+    }
+
+    /* Conditional move of Q to P dependant on d */
+    mutating func cmove(_ Q:ECP4,_ d:Int)
+    {
+        x.cmove(Q.x,d);
+        y.cmove(Q.y,d);
+        z.cmove(Q.z,d);
+    /*
+        var bd:Bool
+        if d==0 {bd=false}
+        else {bd=true}
+        INF = (INF != ((INF != Q.INF) && bd)) */
+    }
+    
+    /* return 1 if b==c, no branching */
+    private static func teq(_ b:Int32,_ c:Int32) -> Int
+    {
+        var x=b^c
+        x-=1  // if x=0, x now -1
+        return Int((x>>31)&1)
+    }
+    /* Constant time select from pre-computed table */
+    mutating func select(_ W:[ECP4],_ b:Int32)
+    {
+        var MP=ECP4()
+        let m=b>>31
+        var babs=(b^m)-m
+        
+        babs=(babs-1)/2
+    
+        cmove(W[0],ECP4.teq(babs,0)) // conditional move
+        cmove(W[1],ECP4.teq(babs,1))
+        cmove(W[2],ECP4.teq(babs,2))
+        cmove(W[3],ECP4.teq(babs,3))
+        cmove(W[4],ECP4.teq(babs,4))
+        cmove(W[5],ECP4.teq(babs,5))
+        cmove(W[6],ECP4.teq(babs,6))
+        cmove(W[7],ECP4.teq(babs,7))
+    
+        MP.copy(self)
+        MP.neg()
+        cmove(MP,Int(m&1))
+    }
+
+    /* Test if P == Q */
+    func equals(_ Q:ECP4) -> Bool
+    {
+    //    if is_infinity() && Q.is_infinity() {return true}
+    //    if is_infinity() || Q.is_infinity() {return false}
+    
+        var a=FP4(x)                            // *****
+        var b=FP4(Q.x)
+        a.mul(Q.z); b.mul(z) 
+        if !a.equals(b) {return false}
+        a.copy(y); a.mul(Q.z)
+        b.copy(Q.y); b.mul(z)
+        if !a.equals(b) {return false}
+    
+        return true;
+    }
+    /* set self=-self */
+    mutating func neg()
+    {
+    //    if is_infinity() {return}
+        y.norm(); y.neg(); y.norm()
+        return
+    }
+    /* set to Affine - (x,y,z) to (x,y) */
+    mutating func affine() {
+        if is_infinity() {return}
+        let one=FP4(1)
+        if z.equals(one) {
+            x.reduce(); y.reduce()
+            return
+        }
+        z.inverse()
+    
+        x.mul(z); x.reduce()
+        y.mul(z); y.reduce()
+        z.copy(one)
+    }
+
+    /* extract affine x as FP4 */
+    func getX() -> FP4
+    {
+        var W=ECP4(); W.copy(self)
+        W.affine()
+        return W.x
+    }
+    /* extract affine y as FP4 */
+    func getY() -> FP4
+    {
+        var W=ECP4(); W.copy(self)
+        W.affine()
+        return W.y
+    }
+    /* extract projective x */
+    func getx() -> FP4
+    {
+        return x
+    }
+    /* extract projective y */
+    func gety() -> FP4
+    {
+        return y
+    }
+    /* extract projective z */
+    func getz() -> FP4
+    {
+        return z
+    }
+
+    /* convert to byte array */
+    func toBytes(_ b:inout [UInt8])
+    {
+        let RM=Int(BIG.MODBYTES)
+        var t=[UInt8](repeating: 0,count: RM)
+        var W=ECP4(); W.copy(self)
+        W.affine();
+        
+        W.x.geta().getA().toBytes(&t)
+        for i in 0 ..< RM
+            {b[i]=t[i]}
+        W.x.geta().getB().toBytes(&t);
+        for i in 0 ..< RM
+            {b[i+RM]=t[i]}
+    
+        W.x.getb().getA().toBytes(&t)
+        for i in 0 ..< RM
+            {b[i+2*RM]=t[i]}
+        W.x.getb().getB().toBytes(&t);
+        for i in 0 ..< RM
+            {b[i+3*RM]=t[i]}
+
+
+        W.y.geta().getA().toBytes(&t);
+        for i in 0 ..< RM
+            {b[i+4*RM]=t[i]}
+        W.y.geta().getB().toBytes(&t);
+        for i in 0 ..< RM
+            {b[i+5*RM]=t[i]}
+
+        W.y.getb().getA().toBytes(&t);
+        for i in 0 ..< RM
+            {b[i+6*RM]=t[i]}
+        W.y.getb().getB().toBytes(&t);
+        for i in 0 ..< RM
+            {b[i+7*RM]=t[i]}
+      
+    }
+
+    /* convert from byte array to point */
+    static func fromBytes(_ b:[UInt8]) -> ECP4
+    {
+        let RM=Int(BIG.MODBYTES)
+        var t=[UInt8](repeating: 0,count: RM)
+
+        for i in 0 ..< RM {t[i]=b[i]}
+        var ra=BIG.fromBytes(t);
+        for i in 0 ..< RM {t[i]=b[i+RM]}
+        var rb=BIG.fromBytes(t);
+
+        var ra2=FP2(ra,rb)
+
+        for i in 0 ..< RM {t[i]=b[i+2*RM]}
+        ra.copy(BIG.fromBytes(t));
+        for i in 0 ..< RM {t[i]=b[i+3*RM]}
+        rb.copy(BIG.fromBytes(t));
+
+        var rb2=FP2(ra,rb)
+
+
+        let rx=FP4(ra2,rb2)
+    
+        for i in 0 ..< RM {t[i]=b[i+4*RM]}
+        ra.copy(BIG.fromBytes(t))
+        for i in 0 ..< RM {t[i]=b[i+5*RM]}
+        rb.copy(BIG.fromBytes(t))
+
+        ra2.copy(FP2(ra,rb))
+
+        for i in 0 ..< RM {t[i]=b[i+6*RM]}
+        ra.copy(BIG.fromBytes(t))
+        for i in 0 ..< RM {t[i]=b[i+7*RM]}
+        rb.copy(BIG.fromBytes(t))
+
+        rb2.copy(FP2(ra,rb))
+
+        let ry=FP4(ra2,rb2)
+    
+        return ECP4(rx,ry)
+    }
+
+/* convert self to hex string */
+    func toString() -> String
+    {
+        var W=ECP4(); W.copy(self)
+        if W.is_infinity() {return "infinity"}
+        W.affine()
+        return "("+W.x.toString()+","+W.y.toString()+")"
+    }
+    
+/* Calculate RHS of twisted curve equation x^3+B/i */
+    static func RHS(_ x:FP4) -> FP4
+    {
+        //x.norm()
+        var r=FP4(x)
+        r.sqr()
+        var b=FP4(FP2(BIG(ROM.CURVE_B)))
+        if ECP.SEXTIC_TWIST == ECP.D_TYPE {
+            b.div_i()
+        }
+        if ECP.SEXTIC_TWIST == ECP.M_TYPE {
+            b.times_i()
+        }
+        r.mul(x)
+        r.add(b)
+    
+        r.reduce()
+        return r
+    }
+/* construct self from (x,y) - but set to O if not on curve */
+    public init(_ ix:FP4,_ iy:FP4)
+    {
+        x=FP4(ix)
+        y=FP4(iy)
+        z=FP4(1)
+        x.norm()
+        let rhs=ECP4.RHS(x)
+        var y2=FP4(y)
+        y2.sqr()
+        if !y2.equals(rhs) {inf()}
+    }
+
+    /* construct this from x - but set to O if not on curve */
+    init(_ ix:FP4)
+    {
+        x=FP4(ix)
+        y=FP4(1)
+        z=FP4(1)
+        x.norm()
+        var rhs=ECP4.RHS(x)
+        if rhs.sqrt()
+        {
+            y.copy(rhs);
+        }
+        else {inf()}
+    }
+
+    /* this+=this */
+    @discardableResult mutating func dbl() -> Int
+    {
+    //    if (INF) {return -1}
+        if y.iszilch()
+        {
+            inf();
+            return -1;
+        }
+    
+        var iy=FP4(y)
+        if ECP.SEXTIC_TWIST == ECP.D_TYPE {       
+            iy.times_i(); 
+        }
+
+        var t0=FP4(y) 
+        t0.sqr();
+        if ECP.SEXTIC_TWIST == ECP.D_TYPE {           
+            t0.times_i() 
+        }  
+        var t1=FP4(iy)  
+        t1.mul(z)
+        var t2=FP4(z)
+        t2.sqr()
+
+        z.copy(t0)
+        z.add(t0); z.norm() 
+        z.add(z)
+        z.add(z) 
+        z.norm()  
+
+        t2.imul(3*ROM.CURVE_B_I) 
+        if ECP.SEXTIC_TWIST == ECP.M_TYPE {
+            t2.times_i()  
+        }
+        var x3=FP4(t2)
+        x3.mul(z) 
+
+        var y3=FP4(t0)   
+
+        y3.add(t2); y3.norm()
+        z.mul(t1)
+        t1.copy(t2); t1.add(t2); t2.add(t1); t2.norm()  
+        t0.sub(t2); t0.norm()                           //y^2-9bz^2
+        y3.mul(t0); y3.add(x3)                          //(y^2+3z*2)(y^2-9z^2)+3b.z^2.8y^2
+        t1.copy(x); t1.mul(iy)                     //
+        x.copy(t0); x.norm(); x.mul(t1); x.add(x)       //(y^2-9bz^2)xy2
+
+        x.norm() 
+        y.copy(y3); y.norm()
+        return 1
+    }
+
+/* this+=Q - return 0 for add, 1 for double, -1 for O */
+    @discardableResult mutating func add(_ Q:ECP4) -> Int
+    {
+
+        let b=3*ROM.CURVE_B_I
+        var t0=FP4(x)
+        t0.mul(Q.x)         // x.Q.x
+        var t1=FP4(y)
+        t1.mul(Q.y)         // y.Q.y
+
+        var t2=FP4(z)
+        t2.mul(Q.z)
+        var t3=FP4(x)
+        t3.add(y); t3.norm()          //t3=X1+Y1
+        var t4=FP4(Q.x)            
+        t4.add(Q.y); t4.norm()         //t4=X2+Y2
+        t3.mul(t4)                     //t3=(X1+Y1)(X2+Y2)
+        t4.copy(t0); t4.add(t1)        //t4=X1.X2+Y1.Y2
+
+        t3.sub(t4); t3.norm(); 
+        if ECP.SEXTIC_TWIST == ECP.D_TYPE {
+            t3.times_i()         //t3=(X1+Y1)(X2+Y2)-(X1.X2+Y1.Y2) = X1.Y2+X2.Y1
+        }
+        t4.copy(y)                    
+        t4.add(z); t4.norm()           //t4=Y1+Z1
+        var x3=FP4(Q.y)
+        x3.add(Q.z); x3.norm()         //x3=Y2+Z2
+
+        t4.mul(x3)                     //t4=(Y1+Z1)(Y2+Z2)
+        x3.copy(t1)                    //
+        x3.add(t2)                     //X3=Y1.Y2+Z1.Z2
+    
+        t4.sub(x3); t4.norm(); 
+        if ECP.SEXTIC_TWIST == ECP.D_TYPE {  
+            t4.times_i()          //t4=(Y1+Z1)(Y2+Z2) - (Y1.Y2+Z1.Z2) = Y1.Z2+Y2.Z1
+        }
+        x3.copy(x); x3.add(z); x3.norm()   // x3=X1+Z1
+        var y3=FP4(Q.x)                
+        y3.add(Q.z); y3.norm()             // y3=X2+Z2
+        x3.mul(y3)                         // x3=(X1+Z1)(X2+Z2)
+        y3.copy(t0)
+        y3.add(t2)                         // y3=X1.X2+Z1+Z2
+        y3.rsub(x3); y3.norm()             // y3=(X1+Z1)(X2+Z2) - (X1.X2+Z1.Z2) = X1.Z2+X2.Z1
+        if ECP.SEXTIC_TWIST == ECP.D_TYPE {  
+            t0.times_i() // x.Q.x
+            t1.times_i() // y.Q.y
+        }
+        x3.copy(t0); x3.add(t0) 
+        t0.add(x3); t0.norm()
+        t2.imul(b)
+        if ECP.SEXTIC_TWIST == ECP.M_TYPE {
+            t2.times_i()
+        }  
+        var z3=FP4(t1); z3.add(t2); z3.norm()
+        t1.sub(t2); t1.norm()
+        y3.imul(b)
+        if ECP.SEXTIC_TWIST == ECP.M_TYPE {          
+            y3.times_i()
+        }
+        x3.copy(y3); x3.mul(t4); t2.copy(t3); t2.mul(t1); x3.rsub(t2)
+        y3.mul(t0); t1.mul(z3); y3.add(t1)
+        t0.mul(t3); z3.mul(t4); z3.add(t0)
+
+        x.copy(x3); x.norm()
+        y.copy(y3); y.norm()
+        z.copy(z3); z.norm()    
+
+        return 0
+    }
+
+    /* set self-=Q */
+    @discardableResult mutating func sub(_ Q:ECP4) -> Int
+    {
+        var NQ=ECP4(); NQ.copy(Q)
+        NQ.neg()
+        let D=add(NQ)
+        //Q.neg()
+        return D
+    }
+
+
+    static func frob_constants() -> [FP2]
+    {
+        let Fra=BIG(ROM.Fra)
+        let Frb=BIG(ROM.Frb)
+        let X=FP2(Fra,Frb)
+
+        var f0=FP2(X); f0.sqr()
+        var f2=FP2(f0)
+        f2.mul_ip(); f2.norm()
+        var f1=FP2(f2); f1.sqr()
+        f2.mul(f1); f1.copy(X)
+        if ECP.SEXTIC_TWIST == ECP.M_TYPE {
+            f1.mul_ip()
+            f1.inverse()
+            f0.copy(f1); f0.sqr()
+
+        }        
+        f0.mul_ip(); f0.norm()
+        f1.mul(f0)
+
+        let F=[FP2(f0),FP2(f1),FP2(f2)];
+        return F;
+    }
+
+
+/* set self*=q, where q is Modulus, using Frobenius */
+    mutating func frob(_ F:[FP2],_ n:Int)
+    {
+        for _ in 0 ..< n {
+            x.frob(F[2])
+            x.pmul(F[0])
+        
+            y.frob(F[2])
+            y.pmul(F[1])
+            y.times_i()
+
+            z.frob(F[2])
+        }
+    }
+
+    /* P*=e */
+    func mul(_ e:BIG) -> ECP4
+    {
+    /* fixed size windows */
+        var mt=BIG()
+        var t=BIG()
+        var P=ECP4()
+        var Q=ECP4()
+        var C=ECP4()
+        
+        var W=[ECP4]();
+        for _ in 0 ..< 8 {W.append(ECP4())}
+        
+        var w=[Int8](repeating: 0,count: 1+(BIG.NLEN*Int(BIG.BASEBITS)+3)/4)
+    
+        if is_infinity() {return ECP4()}
+    
+        //affine()
+    
+    /* precompute table */
+        Q.copy(self)
+        Q.dbl()
+        W[0].copy(self)
+    
+        for i in 1 ..< 8
+        {
+            W[i].copy(W[i-1])
+            W[i].add(Q)
+        }
+    
+    /* make exponent odd - add 2P if even, P if odd */
+        t.copy(e)
+        let s=t.parity()
+        t.inc(1); t.norm(); let ns=t.parity(); mt.copy(t); mt.inc(1); mt.norm()
+        t.cmove(mt,s)
+        Q.cmove(self,ns)
+        C.copy(Q)
+    
+        let nb=1+(t.nbits()+3)/4
+    /* convert exponent to signed 4-bit window */
+        for i in 0 ..< nb
+        {
+            w[i]=Int8(t.lastbits(5)-16)
+            t.dec(Int(w[i])); t.norm()
+            t.fshr(4)
+        }
+        w[nb]=Int8(t.lastbits(5))
+    
+        P.copy(W[Int(w[nb]-1)/2])
+        for i in (0...nb-1).reversed()
+        {
+            Q.select(W,Int32(w[i]))
+            P.dbl()
+            P.dbl()
+            P.dbl()
+            P.dbl()
+            P.add(Q)
+        }
+        P.sub(C);
+        P.affine()
+        return P;
+    }
+    
+    /* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3.. */
+    // Bos & Costello https://eprint.iacr.org/2013/458.pdf
+    // Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
+    // Side channel attack secure 
+
+    static func mul8(_ Q:[ECP4],_ u:[BIG]) -> ECP4
+    {
+        var W=ECP4()
+        var P=ECP4()
+        
+        var T1=[ECP4]()
+        var T2=[ECP4]()
+               
+        for _ in 0 ..< 8 {
+            T1.append(ECP4())
+            T2.append(ECP4())
+        }
+    
+        var mt=BIG()
+        var t=[BIG]()
+    
+        var w1=[Int8](repeating: 0,count: BIG.NLEN*Int(BIG.BASEBITS)+1)
+        var s1=[Int8](repeating: 0,count: BIG.NLEN*Int(BIG.BASEBITS)+1)
+    
+        var w2=[Int8](repeating: 0,count: BIG.NLEN*Int(BIG.BASEBITS)+1)
+        var s2=[Int8](repeating: 0,count: BIG.NLEN*Int(BIG.BASEBITS)+1)
+
+        for i in 0 ..< 8
+        {
+            t.append(BIG(u[i]))
+            t[i].norm()
+            //Q[i].affine()
+        }
+
+    // precompute table 
+
+        T1[0].copy(Q[0])  // Q[0]
+        T1[1].copy(T1[0]); T1[1].add(Q[1])  // Q[0]+Q[1]
+        T1[2].copy(T1[0]); T1[2].add(Q[2])  // Q[0]+Q[2]
+        T1[3].copy(T1[1]); T1[3].add(Q[2])  // Q[0]+Q[1]+Q[2]
+        T1[4].copy(T1[0]); T1[4].add(Q[3])  // Q[0]+Q[3]
+        T1[5].copy(T1[1]); T1[5].add(Q[3])  // Q[0]+Q[1]+Q[3]
+        T1[6].copy(T1[2]); T1[6].add(Q[3])  // Q[0]+Q[2]+Q[3]
+        T1[7].copy(T1[3]); T1[7].add(Q[3])  // Q[0]+Q[1]+Q[2]+Q[3]
+
+// Use Frobenius
+
+        let F=ECP4.frob_constants()
+
+        for i in 0 ..< 8 {
+            T2[i].copy(T1[i]); T2[i].frob(F,4)
+        }
+
+// Make it odd
+        let pb1=1-t[0].parity()
+        t[0].inc(pb1)
+        t[0].norm()  
+
+        let pb2=1-t[4].parity()
+        t[4].inc(pb2)
+        t[4].norm()          
+
+// Number of bits
+        mt.zero();
+        for i in 0 ..< 8 {
+            mt.or(t[i]); 
+        }
+
+        let nb=1+mt.nbits()
+
+// Sign pivot 
+
+        s1[nb-1]=1
+        s2[nb-1]=1
+        for i in 0 ..< nb-1 {
+            t[0].fshr(1)
+            s1[i]=2*Int8(t[0].parity())-1
+            t[4].fshr(1)
+            s2[i]=2*Int8(t[4].parity())-1            
+        }
+
+// Recoded exponent
+        for i in 0 ..< nb {
+            w1[i]=0
+            var k=1
+            for j in 1 ..< 4 {
+                let bt=s1[i]*Int8(t[j].parity())
+                t[j].fshr(1)
+                t[j].dec(Int(bt>>1))
+                t[j].norm()
+                w1[i]+=bt*Int8(k)
+                k=2*k
+            }
+            w2[i]=0
+            k=1
+            for j in 5 ..< 8 {
+                let bt=s2[i]*Int8(t[j].parity())
+                t[j].fshr(1)
+                t[j].dec(Int(bt>>1))
+                t[j].norm()
+                w2[i]+=bt*Int8(k)
+                k=2*k
+            }            
+        }   
+
+// Main loop
+        P.select(T1,Int32(2*w1[nb-1]+1))
+        W.select(T2,Int32(2*w2[nb-1]+1))
+        P.add(W)
+        for i in (0 ..< nb-1).reversed() {
+            P.dbl()
+            W.select(T1,Int32(2*w1[i]+s1[i]))
+            P.add(W)
+            W.select(T2,Int32(2*w2[i]+s2[i]))
+            P.add(W)
+        }    
+
+        W.copy(P)  
+        W.sub(Q[0])
+        P.cmove(W,pb1) 
+
+        W.copy(P)  
+        W.sub(Q[4])
+        P.cmove(W,pb2) 
+
+        P.affine()
+        return P
+    }
+
+     // needed for SOK
+    static func mapit(_ h:[UInt8]) -> ECP4
+    {
+        let q=BIG(ROM.Modulus)
+        var x=BIG.fromBytes(h)
+        let one=BIG(1)
+        var Q=ECP4()
+        x.mod(q);
+        while (true)
+        {
+            let X=FP4(FP2(one,x))
+            Q=ECP4(X);
+            if !Q.is_infinity() {break}
+            x.inc(1); x.norm();
+        }
+    // Fast Hashing to G2 - Fuentes-Castaneda, Knapp and Rodriguez-Henriquez
+        let F=ECP4.frob_constants()        
+        x=BIG(ROM.CURVE_Bnx);
+    
+        var xQ=Q.mul(x);
+        var x2Q=xQ.mul(x)
+        var x3Q=x2Q.mul(x)
+        var x4Q=x3Q.mul(x)
+
+        if ECP.SIGN_OF_X == ECP.NEGATIVEX {
+            xQ.neg()
+            x3Q.neg()
+        }
+
+        x4Q.sub(x3Q)
+        x4Q.sub(Q)
+
+        x3Q.sub(x2Q)
+        x3Q.frob(F,1)
+
+        x2Q.sub(xQ)
+        x2Q.frob(F,2)
+
+        xQ.sub(Q)
+        xQ.frob(F,3)
+
+        Q.dbl()
+        Q.frob(F,4)
+
+        Q.add(x4Q)
+        Q.add(x3Q)
+        Q.add(x2Q)
+        Q.add(xQ)
+      
+        Q.affine()
+        return Q
+    }  
+
+
+    static public func generator() -> ECP4
+    {
+        return ECP4(FP4(FP2(BIG(ROM.CURVE_Pxaa),BIG(ROM.CURVE_Pxab)),FP2(BIG(ROM.CURVE_Pxba),BIG(ROM.CURVE_Pxbb))),FP4(FP2(BIG(ROM.CURVE_Pyaa),BIG(ROM.CURVE_Pyab)),FP2(BIG(ROM.CURVE_Pyba),BIG(ROM.CURVE_Pybb))))
+    }
+
+}
+
+
diff --git a/version3/swift/ecp8.swift b/version3/swift/ecp8.swift
new file mode 100644
index 0000000..6da696f
--- /dev/null
+++ b/version3/swift/ecp8.swift
@@ -0,0 +1,894 @@
+/*
+	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.
+*/
+//
+//  ecp8.swift
+//
+//  Created by Michael Scott on 07/07/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+/* AMCL Weierstrass elliptic curve functions over FP8 */
+
+public struct ECP8 {
+    private var x:FP8
+    private var y:FP8
+    private var z:FP8
+ //   private var INF:Bool
+    
+    /* Constructor - set self=O */
+    init()
+    {
+    //    INF=true
+        x=FP8(0)
+        y=FP8(1)
+        z=FP8(0)
+    }
+    /* Test self=O? */
+    public func is_infinity() -> Bool
+    {
+    //    if INF {return true}
+        return x.iszilch() && z.iszilch()
+    }
+    /* copy self=P */
+    public mutating func copy(_ P:ECP8)
+    {
+        x.copy(P.x)
+        y.copy(P.y)
+        z.copy(P.z)
+    //    INF=P.INF
+    }
+    /* set self=O */
+    mutating func inf() {
+    //    INF=true
+        x.zero()
+        y.one()
+        z.zero()
+    }
+
+   /* Conditional move of Q to P dependant on d */
+    mutating func cmove(_ Q:ECP8,_ d:Int)
+    {
+        x.cmove(Q.x,d);
+        y.cmove(Q.y,d);
+        z.cmove(Q.z,d);
+    }
+    
+    /* return 1 if b==c, no branching */
+    private static func teq(_ b:Int32,_ c:Int32) -> Int
+    {
+        var x=b^c
+        x-=1  // if x=0, x now -1
+        return Int((x>>31)&1)
+    }
+    /* Constant time select from pre-computed table */
+    mutating func select(_ W:[ECP8],_ b:Int32)
+    {
+        var MP=ECP8()
+        let m=b>>31
+        var babs=(b^m)-m
+        
+        babs=(babs-1)/2
+    
+        cmove(W[0],ECP8.teq(babs,0)) // conditional move
+        cmove(W[1],ECP8.teq(babs,1))
+        cmove(W[2],ECP8.teq(babs,2))
+        cmove(W[3],ECP8.teq(babs,3))
+        cmove(W[4],ECP8.teq(babs,4))
+        cmove(W[5],ECP8.teq(babs,5))
+        cmove(W[6],ECP8.teq(babs,6))
+        cmove(W[7],ECP8.teq(babs,7))
+    
+        MP.copy(self)
+        MP.neg()
+        cmove(MP,Int(m&1))
+    }
+
+    /* Test if P == Q */
+    func equals(_ Q:ECP8) -> Bool
+    {
+
+        var a=FP8(x)                            // *****
+        var b=FP8(Q.x)
+        a.mul(Q.z); b.mul(z) 
+        if !a.equals(b) {return false}
+        a.copy(y); a.mul(Q.z)
+        b.copy(Q.y); b.mul(z)
+        if !a.equals(b) {return false}
+    
+        return true;
+    }
+
+   /* set self=-self */
+    mutating func neg()
+    {
+        y.norm(); y.neg(); y.norm()
+        return
+    }
+    /* set to Affine - (x,y,z) to (x,y) */
+    mutating func affine() {
+        if is_infinity() {return}
+        let one=FP8(1)
+        if z.equals(one) {
+            x.reduce(); y.reduce()
+            return
+        }
+        z.inverse()
+    
+        x.mul(z); x.reduce()
+        y.mul(z); y.reduce()
+        z.copy(one)
+    }
+
+    /* extract affine x as FP8 */
+    func getX() -> FP8
+    {
+        var W=ECP8(); W.copy(self)
+        W.affine()
+        return W.x
+    }
+    /* extract affine y as FP8 */
+    func getY() -> FP8
+    {
+        var W=ECP8(); W.copy(self)
+        W.affine()
+        return W.y
+    }
+    /* extract projective x */
+    func getx() -> FP8
+    {
+        return x
+    }
+    /* extract projective y */
+    func gety() -> FP8
+    {
+        return y
+    }
+    /* extract projective z */
+    func getz() -> FP8
+    {
+        return z
+    }
+
+    /* convert to byte array */
+    func toBytes(_ b:inout [UInt8])
+    {
+        let RM=Int(BIG.MODBYTES)
+        var t=[UInt8](repeating: 0,count: RM)
+        var W=ECP8(); W.copy(self)
+        W.affine();
+        
+        W.x.geta().geta().getA().toBytes(&t)
+        for i in 0 ..< RM
+            {b[i]=t[i]}
+        W.x.geta().geta().getB().toBytes(&t);
+        for i in 0 ..< RM
+            {b[i+RM]=t[i]}
+    
+        W.x.geta().getb().getA().toBytes(&t)
+        for i in 0 ..< RM
+            {b[i+2*RM]=t[i]}
+        W.x.geta().getb().getB().toBytes(&t);
+        for i in 0 ..< RM
+            {b[i+3*RM]=t[i]}
+
+        W.x.getb().geta().getA().toBytes(&t)
+        for i in 0 ..< RM
+            {b[i+4*RM]=t[i]}
+        W.x.getb().geta().getB().toBytes(&t);
+        for i in 0 ..< RM
+            {b[i+5*RM]=t[i]}
+    
+        W.x.getb().getb().getA().toBytes(&t)
+        for i in 0 ..< RM
+            {b[i+6*RM]=t[i]}
+        W.x.getb().getb().getB().toBytes(&t);
+        for i in 0 ..< RM
+            {b[i+7*RM]=t[i]}
+
+
+        W.y.geta().geta().getA().toBytes(&t);
+        for i in 0 ..< RM
+            {b[i+8*RM]=t[i]}
+        W.y.geta().geta().getB().toBytes(&t);
+        for i in 0 ..< RM
+            {b[i+9*RM]=t[i]}
+
+        W.y.geta().getb().getA().toBytes(&t);
+        for i in 0 ..< RM
+            {b[i+10*RM]=t[i]}
+        W.y.geta().getb().getB().toBytes(&t);
+        for i in 0 ..< RM
+            {b[i+11*RM]=t[i]}
+
+        W.y.getb().geta().getA().toBytes(&t);
+        for i in 0 ..< RM
+            {b[i+12*RM]=t[i]}
+        W.y.getb().geta().getB().toBytes(&t);
+        for i in 0 ..< RM
+            {b[i+13*RM]=t[i]}
+
+        W.y.getb().getb().getA().toBytes(&t);
+        for i in 0 ..< RM
+            {b[i+14*RM]=t[i]}
+        W.y.getb().getb().getB().toBytes(&t);
+        for i in 0 ..< RM
+            {b[i+15*RM]=t[i]}            
+      
+    }
+
+    /* convert from byte array to point */
+    static func fromBytes(_ b:[UInt8]) -> ECP8
+    {
+        let RM=Int(BIG.MODBYTES)
+        var t=[UInt8](repeating: 0,count: RM)
+
+        for i in 0 ..< RM {t[i]=b[i]}
+        var ra=BIG.fromBytes(t);
+        for i in 0 ..< RM {t[i]=b[i+RM]}
+        var rb=BIG.fromBytes(t);
+
+        var ra2=FP2(ra,rb)
+
+        for i in 0 ..< RM {t[i]=b[i+2*RM]}
+        ra.copy(BIG.fromBytes(t));
+        for i in 0 ..< RM {t[i]=b[i+3*RM]}
+        rb.copy(BIG.fromBytes(t));
+
+        var rb2=FP2(ra,rb)
+
+        var ra4=FP4(ra2,rb2)
+
+        for i in 0 ..< RM {t[i]=b[i+4*RM]}
+        ra.copy(BIG.fromBytes(t))
+        for i in 0 ..< RM {t[i]=b[i+5*RM]}
+        rb.copy(BIG.fromBytes(t))
+
+        ra2.copy(FP2(ra,rb))
+
+        for i in 0 ..< RM {t[i]=b[i+6*RM]}
+        ra.copy(BIG.fromBytes(t));
+        for i in 0 ..< RM {t[i]=b[i+7*RM]}
+        rb.copy(BIG.fromBytes(t));
+
+        rb2.copy(FP2(ra,rb))
+
+        var rb4=FP4(ra2,rb2)
+
+        let rx=FP8(ra4,rb4)
+
+
+
+    
+        for i in 0 ..< RM {t[i]=b[i+8*RM]}
+        ra.copy(BIG.fromBytes(t))
+        for i in 0 ..< RM {t[i]=b[i+9*RM]}
+        rb.copy(BIG.fromBytes(t))
+
+        ra2.copy(FP2(ra,rb))
+
+        for i in 0 ..< RM {t[i]=b[i+10*RM]}
+        ra.copy(BIG.fromBytes(t))
+        for i in 0 ..< RM {t[i]=b[i+11*RM]}
+        rb.copy(BIG.fromBytes(t))
+
+        rb2.copy(FP2(ra,rb))
+
+        ra4.copy(FP4(ra2,rb2))
+
+        for i in 0 ..< RM {t[i]=b[i+12*RM]}
+        ra.copy(BIG.fromBytes(t))
+        for i in 0 ..< RM {t[i]=b[i+13*RM]}
+        rb.copy(BIG.fromBytes(t))
+
+        ra2.copy(FP2(ra,rb))
+
+        for i in 0 ..< RM {t[i]=b[i+14*RM]}
+        ra.copy(BIG.fromBytes(t))
+        for i in 0 ..< RM {t[i]=b[i+15*RM]}
+        rb.copy(BIG.fromBytes(t))
+
+        rb2.copy(FP2(ra,rb))
+
+        rb4.copy(FP4(ra2,rb2))
+
+
+        let ry=FP8(ra4,rb4)
+    
+        return ECP8(rx,ry)
+    }
+
+/* convert self to hex string */
+    func toString() -> String
+    {
+        var W=ECP8(); W.copy(self)
+        if W.is_infinity() {return "infinity"}
+        W.affine()
+        return "("+W.x.toString()+","+W.y.toString()+")"
+    }
+    
+/* Calculate RHS of twisted curve equation x^3+B/i */
+    static func RHS(_ x:FP8) -> FP8
+    {
+        //x.norm()
+        var r=FP8(x)
+        r.sqr()
+        var b=FP8(FP4(FP2(BIG(ROM.CURVE_B))))
+        if ECP.SEXTIC_TWIST == ECP.D_TYPE {
+            b.div_i()
+        }
+        if ECP.SEXTIC_TWIST == ECP.M_TYPE {
+            b.times_i()
+        }
+        r.mul(x)
+        r.add(b)
+    
+        r.reduce()
+        return r
+    }
+
+/* construct self from (x,y) - but set to O if not on curve */
+    public init(_ ix:FP8,_ iy:FP8)
+    {
+        x=FP8(ix)
+        y=FP8(iy)
+        z=FP8(1)
+        let rhs=ECP8.RHS(x)
+        var y2=FP8(y)
+        y2.sqr()
+        if !y2.equals(rhs) {inf()}
+    }
+
+    /* construct this from x - but set to O if not on curve */
+    init(_ ix:FP8)
+    {
+        x=FP8(ix)
+        y=FP8(1)
+        z=FP8(1)
+        var rhs=ECP8.RHS(x)
+        if rhs.sqrt()
+        {
+            y.copy(rhs);
+        }
+        else {inf()}
+    }
+
+    /* this+=this */
+    @discardableResult mutating func dbl() -> Int
+    {
+        if y.iszilch()
+        {
+            inf();
+            return -1;
+        }
+    
+        var iy=FP8(y)
+        if ECP.SEXTIC_TWIST == ECP.D_TYPE {       
+            iy.times_i(); 
+        }
+
+        var t0=FP8(y) 
+        t0.sqr();
+        if ECP.SEXTIC_TWIST == ECP.D_TYPE {           
+            t0.times_i() 
+        }  
+        var t1=FP8(iy)  
+        t1.mul(z)
+        var t2=FP8(z)
+        t2.sqr()
+
+        z.copy(t0)
+        z.add(t0); z.norm() 
+        z.add(z)
+        z.add(z) 
+        z.norm()  
+
+        t2.imul(3*ROM.CURVE_B_I) 
+        if ECP.SEXTIC_TWIST == ECP.M_TYPE {
+            t2.times_i()  
+        }
+        var x3=FP8(t2)
+        x3.mul(z) 
+
+        var y3=FP8(t0)   
+
+        y3.add(t2); y3.norm()
+        z.mul(t1)
+        t1.copy(t2); t1.add(t2); t2.add(t1); t2.norm()  
+        t0.sub(t2); t0.norm()                           //y^2-9bz^2
+        y3.mul(t0); y3.add(x3)                          //(y^2+3z*2)(y^2-9z^2)+3b.z^2.8y^2
+        t1.copy(x); t1.mul(iy)                     //
+        x.copy(t0); x.norm(); x.mul(t1); x.add(x)       //(y^2-9bz^2)xy2
+
+        x.norm() 
+        y.copy(y3); y.norm()
+        return 1
+    }
+/* this+=Q - return 0 for add, 1 for double, -1 for O */
+    @discardableResult mutating func add(_ Q:ECP8) -> Int
+    {
+
+        let b=3*ROM.CURVE_B_I
+        var t0=FP8(x)
+        t0.mul(Q.x)         // x.Q.x
+        var t1=FP8(y)
+        t1.mul(Q.y)         // y.Q.y
+
+        var t2=FP8(z)
+        t2.mul(Q.z)
+        var t3=FP8(x)
+        t3.add(y); t3.norm()          //t3=X1+Y1
+        var t4=FP8(Q.x)            
+        t4.add(Q.y); t4.norm()         //t4=X2+Y2
+        t3.mul(t4)                     //t3=(X1+Y1)(X2+Y2)
+        t4.copy(t0); t4.add(t1)        //t4=X1.X2+Y1.Y2
+
+        t3.sub(t4); t3.norm(); 
+        if ECP.SEXTIC_TWIST == ECP.D_TYPE {
+            t3.times_i()         //t3=(X1+Y1)(X2+Y2)-(X1.X2+Y1.Y2) = X1.Y2+X2.Y1
+        }
+        t4.copy(y)                    
+        t4.add(z); t4.norm()           //t4=Y1+Z1
+        var x3=FP8(Q.y)
+        x3.add(Q.z); x3.norm()         //x3=Y2+Z2
+
+        t4.mul(x3)                     //t4=(Y1+Z1)(Y2+Z2)
+        x3.copy(t1)                    //
+        x3.add(t2)                     //X3=Y1.Y2+Z1.Z2
+    
+        t4.sub(x3); t4.norm(); 
+        if ECP.SEXTIC_TWIST == ECP.D_TYPE {  
+            t4.times_i()          //t4=(Y1+Z1)(Y2+Z2) - (Y1.Y2+Z1.Z2) = Y1.Z2+Y2.Z1
+        }
+        x3.copy(x); x3.add(z); x3.norm()   // x3=X1+Z1
+        var y3=FP8(Q.x)                
+        y3.add(Q.z); y3.norm()             // y3=X2+Z2
+        x3.mul(y3)                         // x3=(X1+Z1)(X2+Z2)
+        y3.copy(t0)
+        y3.add(t2)                         // y3=X1.X2+Z1+Z2
+        y3.rsub(x3); y3.norm()             // y3=(X1+Z1)(X2+Z2) - (X1.X2+Z1.Z2) = X1.Z2+X2.Z1
+        if ECP.SEXTIC_TWIST == ECP.D_TYPE {  
+            t0.times_i() // x.Q.x
+            t1.times_i() // y.Q.y
+        }
+        x3.copy(t0); x3.add(t0) 
+        t0.add(x3); t0.norm()
+        t2.imul(b)
+        if ECP.SEXTIC_TWIST == ECP.M_TYPE {
+            t2.times_i()
+        }  
+        var z3=FP8(t1); z3.add(t2); z3.norm()
+        t1.sub(t2); t1.norm()
+        y3.imul(b)
+        if ECP.SEXTIC_TWIST == ECP.M_TYPE {          
+            y3.times_i()
+        }
+        x3.copy(y3); x3.mul(t4); t2.copy(t3); t2.mul(t1); x3.rsub(t2)
+        y3.mul(t0); t1.mul(z3); y3.add(t1)
+        t0.mul(t3); z3.mul(t4); z3.add(t0)
+
+        x.copy(x3); x.norm()
+        y.copy(y3); y.norm()
+        z.copy(z3); z.norm()    
+
+        return 0
+    }
+    /* set self-=Q */
+    @discardableResult mutating func sub(_ Q:ECP8) -> Int
+    {
+        var NQ=ECP8(); NQ.copy(Q)
+        NQ.neg()
+        let D=add(NQ)
+        //Q.neg()
+        return D
+    }
+
+    static func frob_constants() -> [FP2]
+    {
+        let Fra=BIG(ROM.Fra)
+        let Frb=BIG(ROM.Frb)
+        let X=FP2(Fra,Frb)
+
+        var f0=FP2(X); f0.sqr()
+        var f2=FP2(f0)
+        f2.mul_ip(); f2.norm()
+        var f1=FP2(f2); f1.sqr()
+        f2.mul(f1); 
+
+        f2.mul_ip(); f2.norm()
+
+        f1.copy(X)
+        if ECP.SEXTIC_TWIST == ECP.M_TYPE {
+            f1.mul_ip()
+            f1.inverse()
+            f0.copy(f1); f0.sqr()
+
+        }        
+        f0.mul_ip(); f0.norm()
+        f1.mul(f0)
+
+        let F=[FP2(f0),FP2(f1),FP2(f2)];
+        return F;
+    }
+
+/* set self*=q, where q is Modulus, using Frobenius */
+    mutating func frob(_ F:[FP2],_ n:Int)
+    {
+        for _ in 0 ..< n {
+            x.frob(F[2])
+            x.qmul(F[0])
+        
+            if ECP.SEXTIC_TWIST == ECP.M_TYPE {
+                x.div_i2()
+            }
+            if ECP.SEXTIC_TWIST == ECP.D_TYPE {
+                x.times_i2()
+            }
+            y.frob(F[2])
+            y.qmul(F[1])
+            if ECP.SEXTIC_TWIST == ECP.M_TYPE {
+                y.div_i()
+            }
+
+            if ECP.SEXTIC_TWIST == ECP.D_TYPE {
+                y.times_i2();  y.times_i2();  y.times_i()
+            }
+
+            z.frob(F[2])
+        }
+    }
+
+    /* P*=e */
+    func mul(_ e:BIG) -> ECP8
+    {
+    /* fixed size windows */
+        var mt=BIG()
+        var t=BIG()
+        var P=ECP8()
+        var Q=ECP8()
+        var C=ECP8()
+        
+        var W=[ECP8]();
+        for _ in 0 ..< 8 {W.append(ECP8())}
+        
+        var w=[Int8](repeating: 0,count: 1+(BIG.NLEN*Int(BIG.BASEBITS)+3)/4)
+    
+        if is_infinity() {return ECP8()}
+    
+        //affine()
+    
+    /* precompute table */
+        Q.copy(self)
+        Q.dbl()
+        W[0].copy(self)
+    
+        for i in 1 ..< 8
+        {
+            W[i].copy(W[i-1])
+            W[i].add(Q)
+        }
+    
+    /* make exponent odd - add 2P if even, P if odd */
+        t.copy(e)
+        let s=t.parity()
+        t.inc(1); t.norm(); let ns=t.parity(); mt.copy(t); mt.inc(1); mt.norm()
+        t.cmove(mt,s)
+        Q.cmove(self,ns)
+        C.copy(Q)
+    
+        let nb=1+(t.nbits()+3)/4
+    /* convert exponent to signed 4-bit window */
+        for i in 0 ..< nb
+        {
+            w[i]=Int8(t.lastbits(5)-16)
+            t.dec(Int(w[i])); t.norm()
+            t.fshr(4)
+        }
+        w[nb]=Int8(t.lastbits(5))
+    
+        P.copy(W[Int(w[nb]-1)/2])
+        for i in (0...nb-1).reversed()
+        {
+            Q.select(W,Int32(w[i]))
+            P.dbl()
+            P.dbl()
+            P.dbl()
+            P.dbl()
+            P.add(Q)
+        }
+        P.sub(C);
+        P.affine()
+        return P;
+    }
+    
+    /* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3.. */
+    // Bos & Costello https://eprint.iacr.org/2013/458.pdf
+    // Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
+    // Side channel attack secure 
+
+    static func mul16(_ Q:[ECP8],_ u:[BIG]) -> ECP8
+    {
+        var W=ECP8()
+        var P=ECP8()
+        
+        var T1=[ECP8]()
+        var T2=[ECP8]()
+        var T3=[ECP8]()
+        var T4=[ECP8]()               
+
+        for _ in 0 ..< 8 {
+            T1.append(ECP8())
+            T2.append(ECP8())
+            T3.append(ECP8())
+            T4.append(ECP8())            
+        }
+    
+        var mt=BIG()
+        var t=[BIG]()
+    
+        var w1=[Int8](repeating: 0,count: BIG.NLEN*Int(BIG.BASEBITS)+1)
+        var s1=[Int8](repeating: 0,count: BIG.NLEN*Int(BIG.BASEBITS)+1)
+    
+        var w2=[Int8](repeating: 0,count: BIG.NLEN*Int(BIG.BASEBITS)+1)
+        var s2=[Int8](repeating: 0,count: BIG.NLEN*Int(BIG.BASEBITS)+1)
+
+        var w3=[Int8](repeating: 0,count: BIG.NLEN*Int(BIG.BASEBITS)+1)
+        var s3=[Int8](repeating: 0,count: BIG.NLEN*Int(BIG.BASEBITS)+1)
+    
+        var w4=[Int8](repeating: 0,count: BIG.NLEN*Int(BIG.BASEBITS)+1)
+        var s4=[Int8](repeating: 0,count: BIG.NLEN*Int(BIG.BASEBITS)+1)
+
+
+        for i in 0 ..< 16
+        {
+            t.append(BIG(u[i]))
+            t[i].norm()
+            //Q[i].affine()
+        }
+
+    // precompute table 
+
+        T1[0].copy(Q[0])  // Q[0]
+        T1[1].copy(T1[0]); T1[1].add(Q[1])  // Q[0]+Q[1]
+        T1[2].copy(T1[0]); T1[2].add(Q[2])  // Q[0]+Q[2]
+        T1[3].copy(T1[1]); T1[3].add(Q[2])  // Q[0]+Q[1]+Q[2]
+        T1[4].copy(T1[0]); T1[4].add(Q[3])  // Q[0]+Q[3]
+        T1[5].copy(T1[1]); T1[5].add(Q[3])  // Q[0]+Q[1]+Q[3]
+        T1[6].copy(T1[2]); T1[6].add(Q[3])  // Q[0]+Q[2]+Q[3]
+        T1[7].copy(T1[3]); T1[7].add(Q[3])  // Q[0]+Q[1]+Q[2]+Q[3]
+
+// Use Frobenius
+
+        let F=ECP8.frob_constants()
+
+        for i in 0 ..< 8 {
+            T2[i].copy(T1[i]); T2[i].frob(F,4)
+            T3[i].copy(T2[i]); T3[i].frob(F,4)
+            T4[i].copy(T3[i]); T4[i].frob(F,4)            
+        }
+
+// Make it odd
+        let pb1=1-t[0].parity()
+        t[0].inc(pb1)
+        t[0].norm()  
+
+        let pb2=1-t[4].parity()
+        t[4].inc(pb2)
+        t[4].norm()          
+
+        let pb3=1-t[8].parity()
+        t[8].inc(pb3)
+        t[8].norm()  
+
+        let pb4=1-t[12].parity()
+        t[12].inc(pb4)
+        t[12].norm()   
+
+
+// Number of bits
+        mt.zero();
+        for i in 0 ..< 16 {
+            mt.or(t[i]); 
+        }
+
+        let nb=1+mt.nbits()
+
+// Sign pivot 
+
+        s1[nb-1]=1
+        s2[nb-1]=1
+        s3[nb-1]=1
+        s4[nb-1]=1        
+        for i in 0 ..< nb-1 {
+            t[0].fshr(1)
+            s1[i]=2*Int8(t[0].parity())-1
+            t[4].fshr(1)
+            s2[i]=2*Int8(t[4].parity())-1        
+            t[8].fshr(1)
+            s3[i]=2*Int8(t[8].parity())-1
+            t[12].fshr(1)
+            s4[i]=2*Int8(t[12].parity())-1                   
+        }
+
+// Recoded exponent
+        for i in 0 ..< nb {
+            w1[i]=0
+            var k=1
+            for j in 1 ..< 4 {
+                let bt=s1[i]*Int8(t[j].parity())
+                t[j].fshr(1)
+                t[j].dec(Int(bt>>1))
+                t[j].norm()
+                w1[i]+=bt*Int8(k)
+                k=2*k
+            }
+            w2[i]=0
+            k=1
+            for j in 5 ..< 8 {
+                let bt=s2[i]*Int8(t[j].parity())
+                t[j].fshr(1)
+                t[j].dec(Int(bt>>1))
+                t[j].norm()
+                w2[i]+=bt*Int8(k)
+                k=2*k
+            }            
+            w3[i]=0
+            k=1
+            for j in 9 ..< 12 {
+                let bt=s3[i]*Int8(t[j].parity())
+                t[j].fshr(1)
+                t[j].dec(Int(bt>>1))
+                t[j].norm()
+                w3[i]+=bt*Int8(k)
+                k=2*k
+            }            
+            w4[i]=0
+            k=1
+            for j in 13 ..< 16 {
+                let bt=s4[i]*Int8(t[j].parity())
+                t[j].fshr(1)
+                t[j].dec(Int(bt>>1))
+                t[j].norm()
+                w4[i]+=bt*Int8(k)
+                k=2*k
+            }                                    
+        }   
+
+// Main loop
+        P.select(T1,Int32(2*w1[nb-1]+1))
+        W.select(T2,Int32(2*w2[nb-1]+1))
+        P.add(W)
+        W.select(T3,Int32(2*w3[nb-1]+1))
+        P.add(W)
+        W.select(T4,Int32(2*w4[nb-1]+1))
+        P.add(W)                
+        for i in (0 ..< nb-1).reversed() {
+            P.dbl()
+            W.select(T1,Int32(2*w1[i]+s1[i]))
+            P.add(W)
+            W.select(T2,Int32(2*w2[i]+s2[i]))
+            P.add(W)
+            W.select(T3,Int32(2*w3[i]+s3[i]))
+            P.add(W)
+            W.select(T4,Int32(2*w4[i]+s4[i]))
+            P.add(W)            
+        }    
+
+        W.copy(P)  
+        W.sub(Q[0])
+        P.cmove(W,pb1) 
+
+        W.copy(P)  
+        W.sub(Q[4])
+        P.cmove(W,pb2) 
+
+        W.copy(P)  
+        W.sub(Q[8])
+        P.cmove(W,pb3) 
+
+        W.copy(P)  
+        W.sub(Q[12])
+        P.cmove(W,pb4) 
+
+        P.affine()
+        return P
+    }
+
+
+     // needed for SOK
+    static func mapit(_ h:[UInt8]) -> ECP8
+    {
+        let q=BIG(ROM.Modulus)
+        var x=BIG.fromBytes(h)
+        let one=BIG(1)
+        var Q=ECP8()
+        x.mod(q);
+        while (true)
+        {
+            let X=FP8(FP4(FP2(one,x)))
+            Q=ECP8(X);
+            if !Q.is_infinity() {break}
+            x.inc(1); x.norm();
+        }
+    // Fast Hashing to G2 - Fuentes-Castaneda, Knapp and Rodriguez-Henriquez
+        let F=ECP8.frob_constants()        
+        x=BIG(ROM.CURVE_Bnx);
+    
+        var xQ=Q.mul(x);
+        var x2Q=xQ.mul(x)
+        var x3Q=x2Q.mul(x)
+        var x4Q=x3Q.mul(x)
+        var x5Q=x4Q.mul(x);
+        var x6Q=x5Q.mul(x)
+        var x7Q=x6Q.mul(x)
+        var x8Q=x7Q.mul(x)        
+
+        if ECP.SIGN_OF_X == ECP.NEGATIVEX {
+            xQ.neg()
+            x3Q.neg()
+            x5Q.neg()
+            x7Q.neg()            
+        }
+
+        x8Q.sub(x7Q)
+        x8Q.sub(Q)
+
+        x7Q.sub(x6Q)
+        x7Q.frob(F,1)
+
+        x6Q.sub(x5Q)
+        x6Q.frob(F,2)
+
+        x5Q.sub(x4Q)
+        x5Q.frob(F,3)
+
+        x4Q.sub(x3Q)
+        x4Q.frob(F,4)
+
+        x3Q.sub(x2Q)
+        x3Q.frob(F,5)
+
+        x2Q.sub(xQ)
+        x2Q.frob(F,6)
+
+        xQ.sub(Q)
+        xQ.frob(F,7)
+
+        Q.dbl()
+        Q.frob(F,8)
+
+        Q.add(x8Q)
+        Q.add(x7Q)
+        Q.add(x6Q)
+        Q.add(x5Q)
+
+        Q.add(x4Q)
+        Q.add(x3Q)
+        Q.add(x2Q)
+        Q.add(xQ)
+      
+        Q.affine()
+        return Q
+    }  
+
+    static public func generator() -> ECP8
+    {
+        return ECP8(FP8(FP4(FP2(BIG(ROM.CURVE_Pxaaa),BIG(ROM.CURVE_Pxaab)),FP2(BIG(ROM.CURVE_Pxaba),BIG(ROM.CURVE_Pxabb))),FP4(FP2(BIG(ROM.CURVE_Pxbaa),BIG(ROM.CURVE_Pxbab)),FP2(BIG(ROM.CURVE_Pxbba),BIG(ROM.CURVE_Pxbbb)))),FP8(FP4(FP2(BIG(ROM.CURVE_Pyaaa),BIG(ROM.CURVE_Pyaab)),FP2(BIG(ROM.CURVE_Pyaba),BIG(ROM.CURVE_Pyabb))),FP4(FP2(BIG(ROM.CURVE_Pybaa),BIG(ROM.CURVE_Pybab)),FP2(BIG(ROM.CURVE_Pybba),BIG(ROM.CURVE_Pybbb)))))
+    }
+
+}
\ No newline at end of file
diff --git a/version3/swift/ff.swift b/version3/swift/ff.swift
new file mode 100644
index 0000000..3556b57
--- /dev/null
+++ b/version3/swift/ff.swift
@@ -0,0 +1,996 @@
+/*
+	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.
+*/
+
+//
+//  ff.swift
+//
+//  Created by Michael Scott on 24/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+/* Large Finite Field arithmetic */
+/* AMCL mod p functions */
+
+import amcl
+
+final public class FF {
+
+    static public let FFLEN:UInt=@ML@
+
+    static public let FF_BITS:UInt=(BIG.BIGBITS*FF.FFLEN) /* Finite Field Size in bits - must be BIGBITS.2^n */
+    static public let HFLEN=(FF.FFLEN/2);  /* Useful for half-size RSA private key operations */
+
+    static let P_MBITS:UInt=BIG.MODBYTES*8
+    static let P_OMASK:Chunk=Chunk(-1)<<Chunk(FF.P_MBITS%BIG.BASEBITS)
+    static let P_FEXCESS:Chunk=(1<<Chunk(BIG.BASEBITS*UInt(BIG.NLEN)-FF.P_MBITS-1))
+    static let P_TBITS=(FF.P_MBITS%BIG.BASEBITS)
+ 
+
+
+    var v = [BIG]()
+    var length:Int=1
+
+/* calculate Field Excess */
+    static func EXCESS(_ a: BIG) -> Chunk
+    {
+        return ((a.w[BIG.NLEN-1] & FF.P_OMASK)>>Chunk(FF.P_MBITS%BIG.BASEBITS))+1
+    }
+
+#if D32
+    static func pexceed(_ a: BIG,_ b : BIG) -> Bool
+    {
+        let ea=FF.EXCESS(a)
+        let eb=FF.EXCESS(b)
+        if (DChunk(ea)+1)*(DChunk(eb)+1) > DChunk(FF.P_FEXCESS) {return true}
+        return false;
+    }
+    static func sexceed(_ a: BIG) -> Bool
+    {
+        let ea=FF.EXCESS(a)
+        if (DChunk(ea)+1)*(DChunk(ea)+1) > DChunk(FF.P_FEXCESS) {return true}
+        return false;
+    }
+#endif
+#if D64
+    static func pexceed(_ a: BIG,_ b : BIG) -> Bool
+    {
+        let ea=FF.EXCESS(a)
+        let eb=FF.EXCESS(b)
+        if (ea+1) > FF.P_FEXCESS/(eb+1) {return true}
+        return false;
+    }
+    static func sexceed(_ a: BIG) -> Bool
+    {
+        let ea=FF.EXCESS(a)
+        if (ea+1) > FF.P_FEXCESS/(ea+1) {return true}
+        return false;
+    }
+#endif
+    
+
+    /* Constructors */
+    init(_ n: Int)
+    {
+        for _ in 0 ..< n
+        {
+            v.append(BIG(0));
+        }
+        length=n;
+    }
+    
+    init(_ x: [[Chunk]],n: Int)
+    {
+        for i in 0 ..< n
+        {
+            v.append(BIG(x[i]))
+        }
+        length=n;
+    }
+    
+    func getlen() -> Int
+    {
+        return length;
+    }
+    
+    /* set to zero */
+    func zero()
+    {
+        for i in 0 ..< length
+        {
+            v[i].zero();
+        }
+    }
+    
+    /* set to integer */
+    func set(_ m: Int)
+    {
+        zero();
+        v[0].set(0,Chunk(m));
+    }
+    
+    /* copy from FF b */
+    func copy(_ b: FF)
+    {
+        for i in 0 ..< length
+        {
+            v[i].copy(b.v[i]);
+        }
+    }
+    
+    /* x=y<<n */
+    func dsucopy(_ b: FF)
+    {
+        for i in 0 ..< b.length
+        {
+            v[b.length+i].copy(b.v[i]);
+            v[i].zero();
+        }
+    }
+    /* x=y */
+    func dscopy(_ b: FF)
+    {
+        for i in 0 ..< b.length
+        {
+            v[i].copy(b.v[i]);
+            v[b.length+i].zero();
+        }
+    }
+    /* x=y>>n */
+    func sducopy(_ b: FF)
+    {
+        for i in 0 ..< length
+        {
+            v[i].copy(b.v[length+i]);
+        }
+    }
+    func one()
+    {
+        v[0].one();
+        for i in 1 ..< length
+        {
+            v[i].zero();
+        }
+    }
+    /* test equals 0 */
+    func iszilch() -> Bool
+    {
+        for i in 0 ..< length
+        {
+            if (!v[i].iszilch()) {return false}
+        }
+        return true;
+    }
+    /* shift right by BIGBITS-bit words */
+    func shrw(_ n: Int)
+    {
+        for i in 0 ..< n
+        {
+            v[i].copy(v[i+n]);
+            v[i+n].zero();
+        }
+    }
+    
+    /* shift left by BIGBITS-bit words */
+    func shlw(_ n: Int)
+    {
+        for i in 0 ..< n
+        {
+        v[n+i].copy(v[i]);
+        v[i].zero();
+        }
+    }
+    
+    /* extract last bit */
+    func parity() -> Int
+    {
+        return v[0].parity()
+    }
+    
+    func lastbits(_ m: Int) ->Int
+    {
+        return v[0].lastbits(UInt(m));
+    }
+    
+    /* compare x and y - must be normalised, and of same length */
+    static func comp(_ a: FF,_ b:FF) -> Int
+    {
+        for i in (0...a.length-1).reversed()
+       // for var i=a.length-1;i>=0;i--
+        {
+            let j=BIG.comp(a.v[i],b.v[i])
+            if j != 0 {return j}
+        }
+        return 0;
+    }
+    /* recursive add */
+    func radd(_ vp: Int,_ x:FF,_ xp:Int,_ y:FF,_ yp:Int,_ n: Int)
+    {
+        for i in 0 ..< n
+        {
+            v[vp+i].copy(x.v[xp+i])
+            v[vp+i].add(y.v[yp+i])
+        }
+    }
+    /* recursive inc */
+    func rinc(_ vp: Int,_ y: FF,_ yp: Int,_ n:Int)
+    {
+        for i in 0 ..< n
+        {
+            v[vp+i].add(y.v[yp+i])
+        }
+    }
+    /* recursive add */
+    func rsub(_ vp: Int,_ x:FF,_ xp:Int,_ y:FF,_ yp:Int,_ n: Int)
+    {
+        for i in 0 ..< n
+        {
+            v[vp+i].copy(x.v[xp+i])
+            v[vp+i].sub(y.v[yp+i])
+        }
+    }
+    /* recursive inc */
+    func rdec(_ vp: Int,_ y: FF,_ yp: Int,_ n:Int)
+    {
+        for i in 0 ..< n
+        {
+            v[vp+i].sub(y.v[yp+i])
+        }
+    }
+    /* simple add */
+    func add(_ b: FF)
+    {
+        for i in 0 ..< length
+            {v[i].add(b.v[i])}
+    }
+    
+    /* simple sub */
+    func sub(_ b: FF)
+    {
+        for i in 0 ..< length
+            {v[i].sub(b.v[i])}
+    }
+    /* reverse sub */
+    func revsub(_ b: FF)
+    {
+        for i in 0 ..< length
+            {v[i].rsub(b.v[i])}
+    }
+    /* normalise - but hold any overflow in top part unless n<0 */
+    private func rnorm(_ vp: Int,_ n: Int)
+    {
+        var trunc=false;
+        var nn=n
+   
+        if (nn<0)
+        { /* -v n signals to do truncation */
+            nn = -nn
+            trunc=true;
+        }
+        for i in 0 ..< nn-1
+        {
+            let carry=v[vp+i].norm();
+            v[vp+i].xortop(carry<<Chunk(FF.P_TBITS))
+            v[vp+i+1].w[0]+=carry; //inc(carry)
+        }
+        let carry=v[vp+nn-1].norm();
+        if (trunc)
+            {v[vp+nn-1].xortop(carry<<Chunk(FF.P_TBITS))}
+    }
+    
+    func norm()
+    {
+        rnorm(0,length)
+    }
+    
+    /* increment/decrement by a small integer */
+    func inc(_ m: Int)
+    {
+        v[0].inc(m);
+        norm();
+    }
+    
+    func dec(_ m: Int)
+    {
+        v[0].dec(m);
+        norm();
+    }
+    
+    /* shift left by one bit */
+    func shl()
+    {
+        var delay_carry=0;
+        for i in 0 ..< length-1
+        {
+            let carry=v[i].fshl(1)
+            v[i].inc(delay_carry);
+            v[i].xortop(Chunk(carry)<<Chunk(FF.P_TBITS));
+            delay_carry=carry;
+        }
+        v[length-1].fshl(1)
+        v[length-1].inc(delay_carry)
+    }
+    
+    /* shift right by one bit */
+    func shr()
+    {
+        for i in (1..<length).reversed()
+        {
+            let carry=v[i].fshr(1);
+            v[i-1].ortop(Chunk(carry)<<Chunk(FF.P_TBITS));
+        }
+        v[0].fshr(1);
+    }
+    
+    /* Convert to Hex String */
+    func toString() -> String
+    {
+        norm();
+        var s="";
+        for i in (0...length-1).reversed()
+        {
+            s+=v[i].toString();
+        }
+        return s;
+    }
+    
+    /* Convert FFs to/from byte arrays */
+    func toBytes(_ b: inout [UInt8])
+    {
+        for i in 0 ..< length
+        {
+            v[i].tobytearray(&b,(length-i-1)*Int(BIG.MODBYTES))
+        }
+    }
+    static func fromBytes(_ x: FF,_ b:[UInt8])
+    {
+        for i in 0 ..< x.length
+        {
+            x.v[i]=BIG.frombytearray(b,(x.length-i-1)*Int(BIG.MODBYTES))
+        }
+    }
+    
+    /* in-place swapping using xor - side channel resistant - lengths must be the same */
+    private static func cswap(_ a: FF,_ b:FF,_ d:Int)
+    {
+        for i in 0 ..< a.length
+        {
+            a.v[i].cswap(&(b.v[i]),d)
+        }
+    }
+    /* z=x*y, t is workspace */
+    private func karmul(_ vp: Int,_ x: FF,_ xp: Int,_ y:FF,_ yp: Int,_ t:FF,_ tp:Int,_ n:Int)
+    {
+        if (n==1)
+        {
+            x.v[xp].norm(); y.v[yp].norm()
+            var d=BIG.mul(x.v[xp],y.v[yp])
+            v[vp+1]=d.split(8*BIG.MODBYTES)
+            v[vp].copy(d)
+            return
+        }
+        let nd2=n/2
+        radd(vp,x,xp,x,xp+nd2,nd2)
+        rnorm(vp,nd2)
+        radd(vp+nd2,y,yp,y,yp+nd2,nd2)
+        rnorm(vp+nd2,nd2)
+        
+        t.karmul(tp,self,vp,self,vp+nd2,t,tp+n,nd2)
+        karmul(vp,x,xp,y,yp,t,tp+n,nd2)
+        karmul(vp+n,x,xp+nd2,y,yp+nd2,t,tp+n,nd2)
+        t.rdec(tp,self,vp,n)
+        t.rdec(tp,self,vp+n,n)
+        rinc(vp+nd2,t,tp,n)
+        rnorm(vp,2*n)
+    }
+    
+    private func karsqr(_ vp: Int,_ x: FF,_ xp:Int,_ t:FF,_ tp:Int,_ n:Int)
+    {
+        if (n==1)
+        {
+            x.v[xp].norm()
+            var d=BIG.sqr(x.v[xp])
+            v[vp+1].copy(d.split(8*BIG.MODBYTES))
+            v[vp].copy(d);
+            return;
+        }
+    
+        let nd2=n/2
+        karsqr(vp,x,xp,t,tp+n,nd2)
+        karsqr(vp+n,x,xp+nd2,t,tp+n,nd2)
+        t.karmul(tp,x,xp,x,xp+nd2,t,tp+n,nd2)
+        rinc(vp+nd2,t,tp,n)
+        rinc(vp+nd2,t,tp,n)
+        rnorm(vp+nd2,n)
+    }
+    private func karmul_lower(_ vp:Int,_ x:FF,_ xp:Int,_ y:FF,_ yp:Int,_ t:FF,_ tp:Int,_ n: Int)
+    { /* Calculates Least Significant bottom half of x*y */
+        if (n==1)
+        { /* only calculate bottom half of product */
+            v[vp].copy(BIG.smul(x.v[xp],y.v[yp]))
+            return
+        }
+        let nd2=n/2
+    
+        karmul(vp,x,xp,y,yp,t,tp+n,nd2)
+        t.karmul_lower(tp,x,xp+nd2,y,yp,t,tp+n,nd2);
+        rinc(vp+nd2,t,tp,nd2);
+        t.karmul_lower(tp,x,xp,y,yp+nd2,t,tp+n,nd2);
+        rinc(vp+nd2,t,tp,nd2);
+        rnorm(vp+nd2,-nd2);  /* truncate it */
+    }
+    
+    private func karmul_upper(_ x: FF,_ y:FF,_ t:FF,_ n:Int)
+    { /* Calculates Most Significant upper half of x*y, given lower part */
+        let nd2=n/2;
+        radd(n,x,0,x,nd2,nd2);
+        radd(n+nd2,y,0,y,nd2,nd2);
+	rnorm(n,nd2);
+	rnorm(n+nd2,nd2);
+    
+        t.karmul(0,self,n+nd2,self,n,t,n,nd2);  /* t = (a0+a1)(b0+b1) */
+        karmul(n,x,nd2,y,nd2,t,n,nd2);          /* z[n]= a1*b1 */
+    /* z[0-nd2]=l(a0b0) z[nd2-n]= h(a0b0)+l(t)-l(a0b0)-l(a1b1) */
+        t.rdec(0,self,n,n);                     /* t=t-a1b1  */
+        rinc(nd2,self,0,nd2);                   /* z[nd2-n]+=l(a0b0) = h(a0b0)+l(t)-l(a1b1)  */
+        rdec(nd2,t,0,nd2);                      /* z[nd2-n]=h(a0b0)+l(t)-l(a1b1)-l(t-a1b1)=h(a0b0) */
+        rnorm(0,-n);                            /* a0b0 now in z - truncate it */
+        t.rdec(0,self,0,n);                     /* (a0+a1)(b0+b1) - a0b0 */
+        rinc(nd2,t,0,n);
+    
+        rnorm(nd2,n);
+    }
+    /* z=x*y. Assumes x and y are of same length. */
+    static func mul(_ x: FF,_ y:FF) -> FF
+    {
+        let n=x.length
+        let z=FF(2*n)
+        let t=FF(2*n)
+        z.karmul(0,x,0,y,0,t,0,n)
+        return z
+    }
+    
+    /* z=x^2 */
+    static func sqr(_ x: FF) -> FF
+    {
+        let n=x.length
+        let z=FF(2*n)
+        let t=FF(2*n)
+        z.karsqr(0,x,0,t,0,n)
+        return z
+    }
+    /* return low part of product self*y */
+    func lmul(_ y: FF)
+    {
+        let n=length;
+        let t=FF(2*n);
+        let x=FF(n); x.copy(self);
+        karmul_lower(0,x,0,y,0,t,0,n);
+    }
+    
+    /* Set b=b mod c */
+    func mod(_ c: FF)
+    {
+        var k=0
+    
+        norm()
+        if (FF.comp(self,c)<0)
+            {return}
+        repeat
+        {
+            c.shl()
+            k+=1
+        } while (FF.comp(self,c)>=0)
+    
+        while (k>0)
+        {
+            c.shr();
+            if (FF.comp(self,c)>=0)
+            {
+				sub(c)
+				norm()
+            }
+            k-=1
+        }
+    }
+    
+    /* return This mod modulus, N is modulus, ND is Montgomery Constant */
+    func reduce(_ N: FF,_ ND:FF) -> FF
+    { /* fast karatsuba Montgomery reduction */
+        let n=N.length
+        let t=FF(2*n)
+        let r=FF(n)
+        let m=FF(n)
+    
+        r.sducopy(self)
+        m.karmul_lower(0,self,0,ND,0,t,0,n)
+        karmul_upper(N,m,t,n)
+        m.sducopy(self)
+    
+        r.add(N);
+        r.sub(m);
+        r.norm();
+    
+        return r;
+    }
+    /* Set r=this mod b */
+    /* this is of length - 2*n */
+    /* r,b is of length - n */
+    func dmod(_ b: FF) -> FF
+    {
+        let n=b.length
+        let m=FF(2*n)
+        let x=FF(2*n)
+        let r=FF(n)
+    
+        x.copy(self)
+        x.norm()
+        m.dsucopy(b)
+        var k=Int(BIG.BIGBITS)*n
+    
+        while (FF.comp(x,m)>=0)
+        {
+		x.sub(m);
+		x.norm();
+        }
+
+        while (k>0)
+        {
+            m.shr()
+    
+            if (FF.comp(x,m)>=0)
+            {
+				x.sub(m);
+				x.norm();
+            }
+            k -= 1;
+        }
+    
+        r.copy(x);
+        r.mod(b);
+        return r;
+    }
+    /* Set return=1/this mod p. Binary method - a<p on entry */
+    
+    func invmodp(_ p: FF)
+    {
+        let n=p.length;
+    
+        let u=FF(n)
+        let v=FF(n)
+        let x1=FF(n)
+        let x2=FF(n)
+        let t=FF(n)
+        let one=FF(n)
+    
+        one.one()
+        u.copy(self)
+        v.copy(p)
+        x1.copy(one)
+        x2.zero()
+    
+    // reduce n in here as well!
+        while (FF.comp(u,one) != 0 && FF.comp(v,one) != 0)
+        {
+            while (u.parity()==0)
+            {
+                u.shr()
+                if (x1.parity() != 0)
+                {
+                    x1.add(p)
+                    x1.norm()
+                }
+                x1.shr()
+            }
+            while (v.parity()==0)
+            {
+                v.shr()
+                if (x2.parity() != 0)
+                {
+                    x2.add(p)
+                    x2.norm()
+                }
+                x2.shr();
+            }
+            if (FF.comp(u,v)>=0)
+            {
+                u.sub(v)
+                u.norm()
+                if (FF.comp(x1,x2)>=0) {x1.sub(x2)}
+                else
+                {
+                    t.copy(p)
+                    t.sub(x2)
+                    x1.add(t)
+                }
+                x1.norm()
+            }
+            else
+            {
+                v.sub(u)
+                v.norm()
+                if (FF.comp(x2,x1)>=0) {x2.sub(x1)}
+                else
+                {
+                    t.copy(p)
+                    t.sub(x1)
+                    x2.add(t)
+                }
+                x2.norm()
+            }
+        }
+        if FF.comp(u,one)==0
+            {copy(x1)}
+        else
+            {copy(x2)}
+    }
+    
+    /* nresidue mod m */
+    func nres(_ m: FF)
+    {
+        let n=m.length
+        if (n==1) {
+                var d=DBIG(v[0])
+                d.shl(UInt(BIG.NLEN)*BIG.BASEBITS)
+                v[0].copy(d.mod(m.v[0]))
+            } else {
+                let d=FF(2*n)
+                d.dsucopy(self)
+                copy(d.dmod(m))
+            }
+    }
+    
+    func redc(_ m: FF,_ ND:FF)
+    {
+        let n=m.length
+        if (n==1) {
+                var d=DBIG(v[0])
+                v[0].copy(BIG.monty(m.v[0],(Chunk(1)<<Chunk(BIG.BASEBITS))-ND.v[0].w[0],&d))
+            } else {
+                let d=FF(2*n)
+                mod(m)
+                d.dscopy(self)
+                copy(d.reduce(m,ND))
+                mod(m)
+            }
+    }
+    private func mod2m(_ m: Int)
+    {
+        for i in m ..< length
+            {v[i].zero()}
+    }
+    /* U=1/a mod 2^m - Arazi & Qi */
+    private func invmod2m() -> FF
+    {
+        let n=length;
+    
+        let b=FF(n);
+        let c=FF(n);
+        let U=FF(n);
+    
+        U.zero();
+        U.v[0].copy(v[0]);
+        U.v[0].invmod2m();
+    
+        var i=1
+        //for var i=1;i<n;i<<=1
+        while (i<n)
+        {
+            b.copy(self); b.mod2m(i);
+            let t=FF.mul(U,b); t.shrw(i); b.copy(t);
+            c.copy(self); c.shrw(i); c.mod2m(i);
+            c.lmul(U); c.mod2m(i);
+    
+            b.add(c); b.norm();
+            b.lmul(U); b.mod2m(i);
+    
+            c.one(); c.shlw(i); b.revsub(c); b.norm();
+            b.shlw(i);
+            U.add(b);
+            i<<=1
+        }
+        U.norm();
+        return U;
+    }
+    
+    func random(_ rng: inout RAND)
+    {
+        let n=length;
+        for i in 0 ..< n
+        {
+            v[i].copy(BIG.random(&rng));
+        }
+    /* make sure top bit is 1 */
+        while (v[n-1].nbits()<Int(BIG.MODBYTES)*8) {v[n-1].copy(BIG.random(&rng))}
+    }
+    /* generate random x */
+    func randomnum(_ p: FF,_ rng: inout RAND)
+    {
+        let n=length;
+        let d=FF(2*n);
+    
+        for i in 0 ..< 2*n
+        {
+            d.v[i].copy(BIG.random(&rng));
+        }
+        copy(d.dmod(p));
+    }
+    /* this*=y mod p */
+    func modmul(_ y: FF,_ p:FF,_ nd: FF)
+    {
+        if FF.pexceed(v[length-1],y.v[y.length-1]) {mod(p)}
+        let n=p.length
+        if (n==1) {
+                var d=BIG.mul(v[0],y.v[0])
+                v[0].copy(BIG.monty(p.v[0],(Chunk(1)<<Chunk(BIG.BASEBITS))-nd.v[0].w[0],&d))
+            } else {
+                let d=FF.mul(self,y);
+                copy(d.reduce(p,nd));
+            }
+    }
+    
+    /* this*=y mod p */
+    func modsqr(_ p: FF,_ nd:FF)
+    {
+        if FF.sexceed(v[length-1]) {mod(p)}
+        let n=p.length
+        if (n==1) {
+                var d=BIG.sqr(v[0])
+                v[0].copy(BIG.monty(p.v[0],(Chunk(1)<<Chunk(BIG.BASEBITS))-nd.v[0].w[0],&d))
+            } else {
+                let d=FF.sqr(self);
+                copy(d.reduce(p,nd));
+            }
+    }
+    
+    /* self=self^e mod p using side-channel resistant Montgomery Ladder, for large e */
+    func skpow(_ e: FF,_ p:FF)
+    {
+        let n=p.length
+        let R0=FF(n)
+        let R1=FF(n)
+        let ND=p.invmod2m()
+    
+        mod(p)
+        R0.one()
+        R1.copy(self)
+        R0.nres(p)
+        R1.nres(p)
+    
+        for i in (0...8*Int(BIG.MODBYTES)*n-1).reversed()
+        {
+            let b=Int(e.v[i/Int(BIG.BIGBITS)].bit(UInt(i%Int(BIG.BIGBITS))))
+            copy(R0)
+            modmul(R1,p,ND)
+    
+            FF.cswap(R0,R1,b)
+            R0.modsqr(p,ND)
+    
+            R1.copy(self)
+            FF.cswap(R0,R1,b)
+    
+        }
+    
+        copy(R0)
+        redc(p,ND)
+    }
+    
+    /* this =this^e mod p using side-channel resistant Montgomery Ladder, for short e */
+    func skpow(_ e: BIG,_ p:FF)
+    {
+        let n=p.length
+        let R0=FF(n)
+        let R1=FF(n)
+        let ND=p.invmod2m()
+    
+        mod(p)
+        R0.one()
+        R1.copy(self)
+        R0.nres(p)
+        R1.nres(p)
+    
+        for i in (0...8*Int(BIG.MODBYTES)-1).reversed()
+        {
+            let b=(e.bit(UInt(i)))
+            copy(R0)
+            modmul(R1,p,ND)
+    
+            FF.cswap(R0,R1,b)
+            R0.modsqr(p,ND)
+    
+            R1.copy(self)
+            FF.cswap(R0,R1,b)
+        }
+        copy(R0)
+        redc(p,ND)
+    }
+    
+    /* raise to an integer power - right-to-left method */
+    func power(_ e:Int,_ p:FF)
+    {
+        let n=p.length
+        var f=true
+        let w=FF(n)
+        let ND=p.invmod2m()
+        var ee=e;
+    
+        w.copy(self)
+        w.nres(p)
+    
+        if (ee==2)
+        {
+            copy(w)
+            modsqr(p,ND)
+        }
+        else
+        {
+            while true
+            {
+                if (ee%2==1)
+                {
+                    if (f) {copy(w)}
+                    else {modmul(w,p,ND)}
+                    f=false;
+                }
+                ee>>=1;
+                if (ee==0) {break}
+                w.modsqr(p,ND)
+            }
+        }
+        redc(p,ND)
+    }
+    
+    /* this=this^e mod p, faster but not side channel resistant */
+    func pow(_ e: FF,_ p:FF)
+    {
+        let n=p.length
+        let w=FF(n)
+        let ND=p.invmod2m()
+    
+        w.copy(self);
+        one();
+        nres(p);
+        w.nres(p);
+        for i in (0...8*Int(BIG.MODBYTES)*n-1).reversed()
+      //  for var i=8*Int(BIG.MODBYTES)*n-1;i>=0;i--
+        {
+            modsqr(p,ND)
+            let b=e.v[i/Int(BIG.BIGBITS)].bit(UInt(i%Int(BIG.BIGBITS)))
+            if (b==1) {modmul(w,p,ND)}
+        }
+        redc(p,ND);
+    }
+    /* double exponentiation r=x^e.y^f mod p */
+    func pow2(_ e: BIG,_ y:FF,_ f:BIG,_ p:FF)
+    {
+        let n=p.length
+        let xn=FF(n)
+        let yn=FF(n)
+        let xy=FF(n)
+        let ND=p.invmod2m()
+    
+        xn.copy(self)
+        yn.copy(y)
+        xn.nres(p)
+        yn.nres(p)
+        xy.copy(xn); xy.modmul(yn,p,ND)
+        one()
+        nres(p)
+    
+        for i in (0...8*Int(BIG.MODBYTES)-1).reversed()
+    //    for var i=8*Int(BIG.MODBYTES)-1;i>=0;i--
+        {
+            let eb=e.bit(UInt(i))
+            let fb=f.bit(UInt(i))
+            modsqr(p,ND)
+            if (eb==1)
+            {
+                if (fb==1) {modmul(xy,p,ND)}
+                else {modmul(xn,p,ND)}
+            }
+            else
+            {
+                if (fb==1) {modmul(yn,p,ND)}
+            }
+        }
+        redc(p,ND)
+    }
+    static func igcd(_ x:Int,_ y:Int) -> Int
+    { /* integer GCD, returns GCD of x and y */
+        var xx=x;
+        var yy=y;
+        if (yy==0) {return xx}
+        while true
+        {
+            let r=xx%yy; if r==0 {break}
+            xx=yy; yy=r;
+        }
+        return yy;
+    }
+   
+    /* quick and dirty check for common factor with n */
+    func cfactor(_ s: Int) -> Bool
+    {
+        let n=length;
+        let x=FF(n);
+        let y=FF(n);
+        y.set(s);
+        
+        x.copy(self);
+        x.norm();
+        
+        repeat
+        {
+            x.sub(y);
+            x.norm();
+            while ( (!x.iszilch()) && x.parity()==0) {x.shr()}
+        } while (FF.comp(x,y)>0);
+        let g=x.v[0].get(0);
+        let r=FF.igcd(s,Int(g));
+        
+        if (r>1) {return true}
+        return false;
+    }
+ 
+    /* Miller-Rabin test for primality. Slow. */
+    static func prime(_ p: FF,_ rng: inout RAND) -> Bool
+    {
+        var s=0
+        let n=p.length
+        var loop:Bool
+
+        let d=FF(n)
+        let x=FF(n)
+        let unity=FF(n)
+        let nm1=FF(n)
+    
+        let sf:Int=4849845; /* 3*5*.. *19 */
+        p.norm();
+        if (p.cfactor(sf)) {return false}
+        unity.one();
+        nm1.copy(p);
+        nm1.sub(unity);
+        nm1.norm();
+        d.copy(nm1);
+        
+        while (d.parity()==0)
+        {
+            d.shr();
+            s += 1;
+        }
+        
+        if (s==0) {return false}
+        for _ in 0 ..< 10
+        {
+            x.randomnum(p,&rng)
+            x.pow(d,p)
+            if (FF.comp(x,unity)==0 || FF.comp(x,nm1)==0) {continue}
+            loop=false
+            for _ in 1 ..< s
+            {
+				x.power(2,p);
+                if (FF.comp(x,unity)==0) {return false}
+				if (FF.comp(x,nm1)==0) {loop=true; break;}
+            }
+            if (loop) {continue}
+            return false;
+        }
+        return true;
+    }
+
+}
diff --git a/version3/swift/fp.swift b/version3/swift/fp.swift
new file mode 100644
index 0000000..9978679
--- /dev/null
+++ b/version3/swift/fp.swift
@@ -0,0 +1,616 @@
+/*
+	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.
+*/
+//
+//  fp.swift
+//
+//  Created by Michael Scott on 20/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//  Small Finite Field arithmetic
+//  AMCL mod p functions
+//
+
+public struct FP {
+
+
+    static public let NOT_SPECIAL=0
+    static public let PSEUDO_MERSENNE=1
+    static public let MONTGOMERY_FRIENDLY=2
+    static public let GENERALISED_MERSENNE=3
+
+    static public let MODBITS:UInt = @NBT@
+    static let MOD8:UInt = @M8@
+    static public let MODTYPE =  @MT@   
+
+    static let FEXCESS:Int32 = ((Int32(1)<<@SH@)-1)
+    static let OMASK:Chunk=Chunk(-1)<<Chunk(FP.MODBITS%BIG.BASEBITS)
+    static let TBITS:UInt=FP.MODBITS%BIG.BASEBITS; // Number of active bits in top word
+    static let TMASK:Chunk=(1<<Chunk(FP.TBITS))-1
+
+    var x:BIG
+    var xes:Int32
+    static let p=BIG(ROM.Modulus)
+    static let r2modp=BIG(ROM.R2modp)
+
+/* convert to Montgomery n-residue form */
+    mutating func nres()
+    {
+        if FP.MODTYPE != FP.PSEUDO_MERSENNE && FP.MODTYPE != FP.GENERALISED_MERSENNE
+        {
+            var d=BIG.mul(x,FP.r2modp);
+            x.copy(FP.mod(&d))
+            xes=2
+        } else {xes=1}
+    }
+/* convert back to regular form */
+    func redc() -> BIG
+    {
+        if FP.MODTYPE != FP.PSEUDO_MERSENNE && FP.MODTYPE != FP.GENERALISED_MERSENNE
+        {
+            var d=DBIG(x)
+            return FP.mod(&d)
+        }
+        else
+        {
+            let r=BIG(x)
+            return r;
+        }
+    }
+    
+    /* reduce a DBIG to a BIG using the appropriate form of the modulus */
+    static func mod(_ d: inout DBIG) -> BIG
+    {
+ 
+        if FP.MODTYPE==FP.PSEUDO_MERSENNE
+        {
+            var t=d.split(FP.MODBITS)
+            let b=BIG(d)
+            let v=t.pmul(Int(ROM.MConst))
+
+            t.add(b)
+            t.norm()
+
+
+            let tw=t.w[BIG.NLEN-1]
+            t.w[BIG.NLEN-1] &= TMASK
+            t.inc(Int(ROM.MConst*((tw>>Chunk(FP.TBITS))+(v<<Chunk(BIG.BASEBITS-FP.TBITS)))))
+    
+            t.norm()
+            return t
+
+        }
+        if FP.MODTYPE==FP.MONTGOMERY_FRIENDLY
+        {
+            for i in 0 ..< BIG.NLEN {
+                let (top,bot)=BIG.muladd(d.w[i],ROM.MConst-1,d.w[i],d.w[BIG.NLEN+i-1])
+                d.w[BIG.NLEN+i]+=top; d.w[BIG.NLEN+i-1]=bot
+ //                   d.w[BIG.NLEN+i]+=d.muladd(d.w[i],ROM.MConst-1,d.w[i],BIG.NLEN+i-1)
+            }
+    
+            var b=BIG(0);
+    
+            for i in 0 ..< BIG.NLEN
+            {
+                b.w[i]=d.w[BIG.NLEN+i]
+            }
+            b.norm()
+            return b;
+        }
+        if FP.MODTYPE==FP.GENERALISED_MERSENNE
+        { // GoldiLocks Only
+            let t=d.split(FP.MODBITS)
+            let RM2=FP.MODBITS/2
+            var b=BIG(d)
+            b.add(t)
+            var dd=DBIG(t)
+            dd.shl(RM2)
+            
+            var tt=dd.split(FP.MODBITS)
+            let lo=BIG(dd)
+            b.add(tt)
+            b.add(lo)
+            b.norm()
+            tt.shl(RM2)
+            b.add(tt)
+            
+            let carry=b.w[BIG.NLEN-1]>>Chunk(FP.TBITS)
+            b.w[BIG.NLEN-1]&=TMASK
+            b.w[0]+=carry
+            
+            b.w[Int(224/BIG.BASEBITS)]+=carry<<Chunk(224%BIG.BASEBITS)
+            b.norm()
+            return b;
+        }
+        if FP.MODTYPE==FP.NOT_SPECIAL
+        {
+            let md=BIG(ROM.Modulus);
+
+            return BIG.monty(md,ROM.MConst,&d)
+        }
+        return BIG(0)
+    }
+
+
+    init()
+    {
+        x=BIG(0)
+        xes=1
+    }
+    init(_ a: Int)
+    {
+        x=BIG(a)
+        xes=1
+        nres()
+    }
+    init(_ a: BIG)
+    {
+        x=BIG(a)
+        xes=1
+        nres()
+    }
+    init(_ a: FP)
+    {
+        x=BIG(a.x)
+        xes=a.xes
+    }
+    /* convert to string */
+    func toString() -> String
+    {
+        let s=redc().toString()
+        return s
+    }
+    
+    func toRawString() -> String
+    {
+        let s=x.toRawString()
+        return s
+    }
+
+
+
+/* reduce this mod Modulus */
+    mutating func reduce()
+    {
+
+        var m=BIG(FP.p)
+        var r=BIG(FP.p)
+        var sb:Int
+
+        x.norm()
+
+	   if xes>16 {
+		  let q=FP.quo(x,m)
+		  let carry=r.pmul(q)
+		  r.w[BIG.NLEN-1]+=carry<<Chunk(BIG.BASEBITS); // correction - put any carry out back in again
+		  x.sub(r)
+		  x.norm()		
+		  sb=2
+	   } else {
+		  sb=FP.logb2(UInt32(xes-Int32(1)))
+	   }
+        m.fshl(sb)
+
+        while sb>0 {
+            let sr=BIG.ssn(&r,x,&m)
+            x.cmove(r,1-sr)
+            sb -= 1
+        }
+	
+        xes=1
+    }
+    
+/* test this=0? */
+    func iszilch() -> Bool
+    {
+        var z=FP(self)
+        z.reduce()
+        return z.x.iszilch()
+    }
+    
+/* copy from FP b */
+    mutating func copy(_ b: FP)
+    {
+        x.copy(b.x)
+        xes=b.xes
+    }
+    
+/* set this=0 */
+    mutating func zero()
+    {
+        x.zero();
+        xes=1;
+    }
+    
+/* set this=1 */
+    mutating func one()
+    {
+        x.one(); nres()
+    }
+    
+/* normalise this */
+    mutating func norm()
+    {
+        x.norm();
+    }
+/* swap FPs depending on d */
+    mutating func cswap(_ b: inout FP,_ d: Int)
+    {
+        var c=Int32(d)
+        x.cswap(&(b.x),d)
+        c = ~(c-1)
+        let t=c&(xes^b.xes)
+        xes^=t
+        b.xes^=t        
+    }
+    
+/* copy FPs depending on d */
+    mutating func cmove(_ b: FP,_ d:Int)
+    {
+        let c=Int32(-d)
+        x.cmove(b.x,d)
+        xes^=(xes^b.xes)&c        
+    }
+/* this*=b mod Modulus */
+    mutating func mul(_ b: FP)
+    {
+
+        if Int64(xes)*Int64(b.xes) > Int64(FP.FEXCESS) {reduce()}
+        
+        var d=BIG.mul(x,b.x)
+        x.copy(FP.mod(&d))
+        xes=2
+    }
+    static func logb2(_ w: UInt32) -> Int
+    {
+        var v = w
+        v |= (v >> 1)
+        v |= (v >> 2)
+        v |= (v >> 4)
+        v |= (v >> 8)
+        v |= (v >> 16)
+        
+        v = v - ((v >> 1) & 0x55555555)
+        v = (v & 0x33333333) + ((v >> 2) & 0x33333333)
+        let r = Int((   ((v + (v >> 4)) & 0xF0F0F0F)   &* 0x1010101) >> 24)
+        return (r)
+    }
+
+// find appoximation to quotient of a/m
+// Out by at most 2.
+// Note that MAXXES is bounded to be 2-bits less than half a word
+    static func quo(_ n: BIG,_ m: BIG) -> Int
+    {
+        let hb=UInt(BIG.CHUNK)/2
+        if FP.TBITS < hb {
+		  let sh=Chunk(hb-FP.TBITS);
+		  let num=((n.w[BIG.NLEN-1]<<sh))|(n.w[BIG.NLEN-2]>>(Chunk(BIG.BASEBITS)-sh));
+		  let den=((m.w[BIG.NLEN-1]<<sh))|(m.w[BIG.NLEN-2]>>(Chunk(BIG.BASEBITS)-sh));
+		  return Int(num/(den+1));
+	   } else {
+		  let num=n.w[BIG.NLEN-1];
+		  let den=m.w[BIG.NLEN-1];
+		  return Int(num/(den+1));
+	   }
+    }
+
+    /* this = -this mod Modulus */
+    mutating func neg()
+    {
+        var m=BIG(FP.p)
+        let sb=FP.logb2(UInt32(xes-Int32(1)))
+        m.fshl(sb)
+        x.rsub(m)
+        xes=(1<<Int32(sb))+1
+        if xes>FP.FEXCESS {reduce()}
+    }
+    /* this*=c mod Modulus, where c is a small int */
+    mutating func imul(_ c: Int)
+    {
+        var cc=c
+    //    norm();
+        var s=false
+        if (cc<0)
+        {
+            cc = -cc
+            s=true
+        }
+
+        if FP.MODTYPE==FP.PSEUDO_MERSENNE || FP.MODTYPE==FP.GENERALISED_MERSENNE
+        {
+            var d=x.pxmul(cc)
+            x.copy(FP.mod(&d))
+            xes=2
+        }
+        else {
+            if xes*Int32(cc)<FP.FEXCESS
+            {
+                x.pmul(cc)
+                xes*=Int32(cc);
+            }
+            else {
+                let n=FP(cc)
+                self.mul(n)
+            }
+        }
+
+        if s {neg();  norm()}
+       
+    }
+    
+/* this*=this mod Modulus */
+    mutating func sqr()
+    {
+        if Int64(xes)*Int64(xes) > Int64(FP.FEXCESS) {reduce()}   
+        var d=BIG.sqr(x);
+        x.copy(FP.mod(&d));
+        xes=2
+    }
+    
+    /* this+=b */
+    mutating func add(_ b: FP)
+    {
+        x.add(b.x);
+        xes+=b.xes
+        if xes>FP.FEXCESS {reduce()}
+    }
+/* this-=b */
+    mutating func sub(_ b: FP)
+    {
+        var n=FP(b)
+        n.neg()
+        self.add(n)
+    }
+/* this=b-this */
+    mutating func rsub(_ b: FP)
+    {
+        self.neg();
+        self.add(b)
+    }
+/* this/=2 mod Modulus */
+    mutating func div2()
+    {
+    //    x.norm()
+        if (x.parity()==0)
+            {x.fshr(1)}
+        else
+        {
+            x.add(FP.p)
+            x.norm()
+            x.fshr(1)
+        }
+    }
+/* this=1/this mod Modulus */
+
+    mutating func fpow() -> FP 
+    {
+        var ac: [Int] = [1, 2, 3, 6, 12, 15, 30, 60, 120, 240, 255]
+        var xp=[FP]() 
+// phase 1
+        xp.append(FP(self))
+        xp.append(FP(self)); xp[1].sqr()
+        xp.append(FP(xp[1])); xp[2].mul(self)
+        xp.append(FP(xp[2])); xp[3].sqr()
+        xp.append(FP(xp[3])); xp[4].sqr()
+        xp.append(FP(xp[4])); xp[5].mul(xp[2])
+        xp.append(FP(xp[5])); xp[6].sqr()
+        xp.append(FP(xp[6])); xp[7].sqr()
+        xp.append(FP(xp[7])); xp[8].sqr()
+        xp.append(FP(xp[8])); xp[9].sqr()
+        xp.append(FP(xp[9])); xp[10].mul(xp[5])
+
+        var n: Int
+        var c: Int
+
+        if (FP.MOD8==5)
+        {
+            n=Int(FP.MODBITS)-3
+            c=(Int(ROM.MConst)+5)/8
+        } else {
+            n=Int(FP.MODBITS)-2
+            c=(Int(ROM.MConst)+3)/4            
+        }
+
+
+        var bw=0; var w=1; while w<c {w*=2; bw+=1}
+        var k=w-c
+
+        var i=10; var key=FP(0)
+
+        if k != 0 {
+            while ac[i]>k {i-=1}
+            key.copy(xp[i])
+            k-=ac[i]
+        }
+        while k != 0 {
+            i-=1
+            if ac[i]>k {continue}
+            key.mul(xp[i])
+            k-=ac[i] 
+        }
+
+// phase 2 
+        xp[1].copy(xp[2])
+        xp[2].copy(xp[5])
+        xp[3].copy(xp[10])
+
+        var j=3; var m=8
+        let nw=n-bw
+        var t=FP(0)
+
+        while 2*m<nw {
+            t.copy(xp[j]); j+=1
+            for _ in 0..<m {t.sqr()} 
+            xp[j].copy(xp[j-1])
+            xp[j].mul(t)
+            m*=2
+        }
+
+        var lo=nw-m
+        var r=FP(xp[j])
+
+        while lo != 0 {
+            m/=2; j-=1
+            if lo<m {continue}
+            lo-=m
+            t.copy(r)
+            for _ in 0..<m {t.sqr()}
+            r.copy(t)
+            r.mul(xp[j])
+        }
+
+        for _ in 0..<bw {r.sqr()}
+
+        if w-c != 0 {
+            r.mul(key)
+        }
+        return r        
+    }
+
+    mutating func inverse()
+    {
+        if FP.MODTYPE==FP.PSEUDO_MERSENNE {
+            var y=fpow()
+            if (FP.MOD8==5)
+            {
+                var t=FP(self)
+                t.sqr()
+                mul(t)
+                y.sqr()
+
+            } 
+            y.sqr()
+            y.sqr()
+            mul(y)
+        } else {
+            var m2=BIG(ROM.Modulus)
+            m2.dec(2); m2.norm()
+            copy(pow(m2))
+        }
+
+    }
+    
+/* return TRUE if this==a */
+    func equals(_ a: FP) -> Bool
+    {
+        var f=FP(self)
+        var s=FP(a)
+        f.reduce()
+        s.reduce()
+        if (BIG.comp(f.x,s.x)==0) {return true}
+        return false;
+    }
+
+
+/* return this^e mod Modulus */
+    mutating func pow(_ e: BIG) -> FP
+    {
+        var tb=[FP]() 
+        let n=1+(BIG.NLEN*Int(BIG.BASEBITS)+3)/4
+        var w=[Int8](repeating: 0,count: n)     
+        norm()
+        var t=BIG(e); t.norm()
+        let nb=1+(t.nbits()+3)/4    
+
+        for i in 0 ..< nb  {
+            let lsbs=t.lastbits(4)
+            t.dec(lsbs)
+            t.norm()
+            w[i]=Int8(lsbs)
+            t.fshr(4);
+        }
+        tb.append(FP(1))
+        tb.append(FP(self))
+        for i in 2 ..< 16 {
+            tb.append(FP(tb[i-1]))
+            tb[i].mul(self)
+        }
+        var r=FP(tb[Int(w[nb-1])])
+        for i in (0...nb-2).reversed() {
+            r.sqr()
+            r.sqr()
+            r.sqr()
+            r.sqr()
+            r.mul(tb[Int(w[i])])
+        }
+        r.reduce()
+        return r
+    }
+
+
+/* return this^e mod Modulus 
+    func pow(_ e: BIG) -> FP
+    {
+        let r=FP(1)
+        e.norm()
+        x.norm()
+	   let m=FP(self)
+        while (true)
+        {
+            let bt=e.parity()
+            e.fshr(1)
+            if bt==1 {r.mul(m)}
+            if e.iszilch() {break}
+            m.sqr();
+        }
+        r.x.mod(FP.p);
+        return r;
+    } */
+
+/* return sqrt(this) mod Modulus */
+    mutating func sqrt() -> FP
+    {
+        reduce();
+        if (FP.MOD8==5)
+        {
+            var v: FP
+            var i=FP(self); i.x.shl(1)
+            if FP.MODTYPE==FP.PSEUDO_MERSENNE {
+                v=i.fpow()
+            } else {       
+                var b=BIG(FP.p)
+                b.dec(5); b.norm(); b.shr(3)
+                v=i.pow(b)
+            }
+            i.mul(v); i.mul(v)
+            i.x.dec(1)
+            var r=FP(self)
+            r.mul(v); r.mul(i)
+            r.reduce()
+            return r
+        }
+        else
+        {
+           if FP.MODTYPE==FP.PSEUDO_MERSENNE {
+                var r=fpow()
+                r.mul(self)
+                return r
+            } else {                   
+                var b=BIG(FP.p)
+                b.inc(1); b.norm(); b.shr(2)
+                return pow(b)
+            }
+        }
+    }
+/* return jacobi symbol (this/Modulus) */
+    func jacobi() -> Int
+    {
+        var w=redc()
+        return w.jacobi(FP.p)
+    }
+    
+}
diff --git a/version3/swift/fp12.swift b/version3/swift/fp12.swift
new file mode 100644
index 0000000..2ed94cd
--- /dev/null
+++ b/version3/swift/fp12.swift
@@ -0,0 +1,815 @@
+/*
+	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.
+*/
+
+//
+//  fp12.swift
+//
+//  Created by Michael Scott on 07/07/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+/* AMCL Fp^12 functions */
+/* FP12 elements are of the form a+i.b+i^2.c */
+
+public struct FP12
+{
+    private var a:FP4
+    private var b:FP4
+    private var c:FP4
+    
+    /* reduce all components of this mod Modulus */
+    mutating func reduce()
+    {
+        a.reduce()
+        b.reduce()
+        c.reduce()
+    }
+    /* normalise all components of this */
+    mutating func norm()
+    {
+        a.norm();
+        b.norm();
+        c.norm();
+    }
+    /* Constructors */
+    init(_ d:FP4)
+    {
+        a=FP4(d)
+        b=FP4(0)
+        c=FP4(0)
+    }
+    
+    init(_ d:Int)
+    {
+        a=FP4(d)
+        b=FP4(0)
+        c=FP4(0)
+    }
+    
+    init(_ d:FP4,_ e:FP4,_ f:FP4)
+    {
+        a=FP4(d)
+        b=FP4(e)
+        c=FP4(f)
+    }
+    
+    init(_ x:FP12)
+    {
+        a=FP4(x.a)
+        b=FP4(x.b)
+        c=FP4(x.c)
+    }
+    /* test x==0 ? */
+    func iszilch() -> Bool
+    {
+        //reduce();
+        return a.iszilch() && b.iszilch() && c.iszilch()
+    }
+
+    mutating func cmove(_ g:FP12,_ d:Int)
+    {
+        a.cmove(g.a,d)
+        b.cmove(g.b,d)
+        c.cmove(g.c,d)
+    }
+
+    /* return 1 if b==c, no branching */
+    private static func teq(_ b:Int32,_ c:Int32) -> Int
+    {
+        var x=b^c
+        x-=1  // if x=0, x now -1
+        return Int((x>>31)&1)
+    }
+    /* Constant time select from pre-computed table */
+    mutating func select(_ g:[FP12],_ b:Int32)
+    {
+
+        let m=b>>31
+        var babs=(b^m)-m
+        
+        babs=(babs-1)/2
+    
+        cmove(g[0],FP12.teq(babs,0)) // conditional move
+        cmove(g[1],FP12.teq(babs,1))
+        cmove(g[2],FP12.teq(babs,2))
+        cmove(g[3],FP12.teq(babs,3))
+        cmove(g[4],FP12.teq(babs,4))
+        cmove(g[5],FP12.teq(babs,5))
+        cmove(g[6],FP12.teq(babs,6))
+        cmove(g[7],FP12.teq(babs,7))
+    
+        var invf=FP12(self)
+        invf.conj()
+        cmove(invf,Int(m&1))
+    }
+
+    /* test x==1 ? */
+    public func isunity() -> Bool
+    {
+        let one=FP4(1)
+        return a.equals(one) && b.iszilch() && c.iszilch()
+    }
+    /* return 1 if x==y, else 0 */
+    public func equals(_ x:FP12) -> Bool
+    {
+        return a.equals(x.a) && b.equals(x.b) && c.equals(x.c)
+    }
+    /* extract a from self */
+    func geta() -> FP4
+    {
+        return a
+    }
+    /* extract b */
+    func getb()  -> FP4
+    {
+        return b
+    }
+    /* extract c */
+    func getc() -> FP4
+    {
+        return c
+    }
+    /* copy self=x */
+    public mutating func copy(_ x:FP12)
+    {
+        a.copy(x.a)
+        b.copy(x.b)
+        c.copy(x.c)
+    }
+    /* set self=1 */
+    mutating func one()
+    {
+        a.one()
+        b.zero()
+        c.zero()
+    }
+    /* self=conj(self) */
+    mutating func conj()
+    {
+        a.conj()
+        b.nconj()
+        c.conj()
+    }
+    /* Granger-Scott Unitary Squaring */
+    mutating func usqr()
+    {
+        var A=FP4(a)
+        var B=FP4(c)
+        var C=FP4(b)
+        var D=FP4(0)
+    
+        a.sqr()
+        D.copy(a); D.add(a)
+        a.add(D)
+    
+        a.norm()
+        A.nconj()
+    
+        A.add(A)
+        a.add(A)
+        B.sqr()
+        B.times_i()
+    
+        D.copy(B); D.add(B)
+        B.add(D)
+        B.norm()
+    
+        C.sqr()
+        D.copy(C); D.add(C)
+        C.add(D)
+        C.norm()
+    
+        b.conj()
+        b.add(b)
+        c.nconj()
+    
+        c.add(c)
+        b.add(B)
+        c.add(C)
+        reduce()
+    
+    }
+    /* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
+    mutating func sqr()
+    {
+        var A=FP4(a)
+        var B=FP4(b)
+        var C=FP4(c)
+        var D=FP4(a)
+    
+        A.sqr()
+        B.mul(c)
+        B.add(B); B.norm()
+        C.sqr()
+        D.mul(b)
+        D.add(D)
+
+        c.add(a)
+        c.add(b); c.norm()
+        c.sqr()
+    
+        a.copy(A)
+    
+        A.add(B)
+        A.norm()
+        A.add(C)
+        A.add(D)
+        A.norm()
+    
+        A.neg()
+        B.times_i()
+        C.times_i()
+    
+        a.add(B)
+
+        b.copy(C); b.add(D)
+        c.add(A)
+    
+        norm()
+    }
+    
+    /* FP12 full multiplication this=this*y */
+    mutating func mul(_ y:FP12)
+    {
+        var z0=FP4(a)
+        var z1=FP4(0)
+        var z2=FP4(b)
+        var z3=FP4(0)
+        var t0=FP4(a)
+        var t1=FP4(y.a)
+    
+        z0.mul(y.a)
+        z2.mul(y.b)
+    
+        t0.add(b)
+        t1.add(y.b)
+
+        t0.norm(); t1.norm()
+    
+        z1.copy(t0); z1.mul(t1)
+        t0.copy(b); t0.add(c)
+    
+        t1.copy(y.b); t1.add(y.c)
+
+        t0.norm(); t1.norm()
+
+        z3.copy(t0); z3.mul(t1)
+    
+        t0.copy(z0); t0.neg()
+        t1.copy(z2); t1.neg()
+    
+        z1.add(t0)
+        b.copy(z1); b.add(t1)
+    
+        z3.add(t1)
+        z2.add(t0)
+    
+        t0.copy(a); t0.add(c)
+        t1.copy(y.a); t1.add(y.c)
+
+        t0.norm(); t1.norm()
+
+        t0.mul(t1)
+        z2.add(t0)
+    
+        t0.copy(c); t0.mul(y.c)
+        t1.copy(t0); t1.neg()
+    
+        c.copy(z2); c.add(t1)
+        z3.add(t1)
+        t0.times_i()
+        b.add(t0)
+    
+        z3.norm()
+        z3.times_i()
+        a.copy(z0); a.add(z3)
+    
+        norm()
+    }
+    
+    /* Special case of multiplication arises from special form of ATE pairing line function */
+    mutating func smul(_ y:FP12,_ twist:Int)
+    {
+        if twist == ECP.D_TYPE {
+            var z0=FP4(a)
+            var z2=FP4(b)
+            var z3=FP4(b)
+            var t0=FP4(0)
+            var t1=FP4(y.a)
+    
+            z0.mul(y.a)
+            z2.pmul(y.b.real())
+            b.add(a)
+            t1.adds(y.b.real())
+            //t1.real().add(y.b.real())
+    
+            b.norm(); t1.norm()
+
+            b.mul(t1)
+            z3.add(c); z3.norm()
+            z3.pmul(y.b.real())
+    
+            t0.copy(z0); t0.neg()
+            t1.copy(z2); t1.neg()
+    
+            b.add(t0)
+    
+            b.add(t1)
+            z3.add(t1)
+            z2.add(t0)
+    
+            t0.copy(a); t0.add(c)
+            t0.norm(); z3.norm()
+            t0.mul(y.a)
+            c.copy(z2); c.add(t0)
+    
+            z3.times_i()
+            a.copy(z0); a.add(z3)
+        }
+        if twist == ECP.M_TYPE {
+            var z0=FP4(a)
+            var z1=FP4(0)
+            var z2=FP4(0)
+            var z3=FP4(0)
+            var t0=FP4(a)
+            var t1=FP4(0)
+        
+            z0.mul(y.a)
+            t0.add(b)
+            t0.norm()
+
+            z1.copy(t0); z1.mul(y.a)
+            t0.copy(b); t0.add(c)
+            t0.norm();
+
+            z3.copy(t0); //z3.mul(y.c);
+            z3.pmul(y.c.getb())
+            z3.times_i()
+
+            t0.copy(z0); t0.neg()
+
+            z1.add(t0)
+            b.copy(z1);
+            z2.copy(t0)
+
+            t0.copy(a); t0.add(c)
+            t1.copy(y.a); t1.add(y.c)
+
+            t0.norm()
+            t1.norm()
+    
+            t0.mul(t1)
+            z2.add(t0)
+
+            t0.copy(c)
+            
+            t0.pmul(y.c.getb())
+            t0.times_i()
+
+            t1.copy(t0); t1.neg()
+
+            c.copy(z2); c.add(t1)
+            z3.add(t1)
+            t0.times_i()
+            b.add(t0)
+            z3.norm();
+            z3.times_i()
+            a.copy(z0); a.add(z3)      
+        }
+        norm()
+    }
+    /* self=1/self */
+    mutating func inverse()
+    {
+        var f0=FP4(a)
+        var f1=FP4(b)
+        var f2=FP4(a)
+        var f3=FP4(0)
+    
+        norm()
+        f0.sqr()
+        f1.mul(c)
+        f1.times_i()
+        f0.sub(f1); f0.norm()
+    
+        f1.copy(c); f1.sqr()
+        f1.times_i()
+        f2.mul(b)
+        f1.sub(f2); f1.norm()
+    
+        f2.copy(b); f2.sqr()
+        f3.copy(a); f3.mul(c)
+        f2.sub(f3); f2.norm()
+    
+        f3.copy(b); f3.mul(f2)
+        f3.times_i()
+        a.mul(f0)
+        f3.add(a)
+        c.mul(f1)
+        c.times_i()
+    
+        f3.add(c); f3.norm()
+        f3.inverse()
+        a.copy(f0); a.mul(f3)
+        b.copy(f1); b.mul(f3)
+        c.copy(f2); c.mul(f3)
+    }
+    
+    /* self=self^p using Frobenius */
+    mutating func frob(_ f:FP2)
+    {
+        var f2=FP2(f)
+        var f3=FP2(f)
+    
+        f2.sqr()
+        f3.mul(f2)
+    
+        a.frob(f3)
+        b.frob(f3)
+        c.frob(f3)
+    
+        b.pmul(f)
+        c.pmul(f2)
+    }
+    
+    /* trace function */
+    func trace() -> FP4
+    {
+        var t=FP4(0)
+        t.copy(a)
+        t.imul(3)
+        t.reduce()
+        return t
+    }
+    /* convert from byte array to FP12 */
+    static func fromBytes(_ w:[UInt8]) -> FP12
+    {
+        let RM=Int(BIG.MODBYTES)
+        var t=[UInt8](repeating: 0,count: RM)
+    
+        for i in 0 ..< RM {t[i]=w[i]}
+        var a=BIG.fromBytes(t)
+        for i in 0 ..< RM {t[i]=w[i+RM]}
+        var b=BIG.fromBytes(t)
+        var c=FP2(a,b)
+    
+        for i in 0 ..< RM {t[i]=w[i+2*RM]}
+        a=BIG.fromBytes(t)
+        for i in 0 ..< RM {t[i]=w[i+3*RM]}
+        b=BIG.fromBytes(t)
+        var d=FP2(a,b)
+    
+        let e=FP4(c,d)
+    
+        for i in 0 ..< RM {t[i]=w[i+4*RM]}
+        a=BIG.fromBytes(t)
+        for i in 0 ..< RM {t[i]=w[i+5*RM]}
+        b=BIG.fromBytes(t)
+        c=FP2(a,b)
+    
+        for i in 0 ..< RM {t[i]=w[i+6*RM]}
+        a=BIG.fromBytes(t)
+        for i in 0 ..< RM {t[i]=w[i+7*RM]}
+        b=BIG.fromBytes(t)
+        d=FP2(a,b)
+    
+        let f=FP4(c,d)
+    
+    
+        for i in 0 ..< RM {t[i]=w[i+8*RM]}
+        a=BIG.fromBytes(t)
+        for i in 0 ..< RM {t[i]=w[i+9*RM]}
+        b=BIG.fromBytes(t)
+        c=FP2(a,b)
+    
+        for i in 0 ..< RM {t[i]=w[i+10*RM]}
+        a=BIG.fromBytes(t)
+        for i in 0 ..< RM {t[i]=w[i+11*RM]}
+        b=BIG.fromBytes(t);
+        d=FP2(a,b)
+    
+        let g=FP4(c,d)
+    
+        return FP12(e,f,g)
+    }
+    
+    /* convert this to byte array */
+    func toBytes(_ w:inout [UInt8])
+    {
+        let RM=Int(BIG.MODBYTES)
+        var t=[UInt8](repeating: 0,count: RM)
+
+        a.geta().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i]=t[i]}
+        a.geta().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+RM]=t[i]}
+        a.getb().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+2*RM]=t[i]}
+        a.getb().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+3*RM]=t[i]}
+    
+        b.geta().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+4*RM]=t[i]}
+        b.geta().getB().toBytes(&t);
+        for i in 0 ..< RM {w[i+5*RM]=t[i]}
+        b.getb().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+6*RM]=t[i]}
+        b.getb().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+7*RM]=t[i]}
+    
+        c.geta().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+8*RM]=t[i]}
+        c.geta().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+9*RM]=t[i]}
+        c.getb().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+10*RM]=t[i]}
+        c.getb().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+11*RM]=t[i]}
+    }
+    /* convert to hex string */
+    public func toString() -> String
+    {
+        return ("["+a.toString()+","+b.toString()+","+c.toString()+"]")
+    }
+    
+    /* self=self^e */
+    /* Note this is simple square and multiply, so not side-channel safe */
+    func pow(_ e:BIG) -> FP12
+    {
+        var sf = FP12(self)
+        sf.norm()
+        //e.norm()
+        var e1=BIG(e)
+        e1.norm()
+        var e3=BIG(e1)
+        e3.pmul(3)
+        e3.norm();
+
+        var w=FP12(sf)
+        let nb=e3.nbits()
+ 
+        for i in (1...nb-2).reversed()
+        {
+            w.usqr()
+            let bt=e3.bit(UInt(i))-e1.bit(UInt(i))
+            if bt == 1 {
+                w.mul(sf)
+            }
+            if bt == -1 {
+                sf.conj(); w.mul(sf); sf.conj()
+            }            
+        }
+    
+        w.reduce()
+        return w
+    }
+    /* constant time powering by small integer of max length bts */
+    mutating func pinpow(_ e:Int32,_ bts:Int32)
+    {
+        var R=[FP12]()
+        R.append(FP12(1))
+        R.append(FP12(self))
+
+        //for var i=bts-1;i>=0;i--
+        for i in (0...bts-1).reversed()
+        {
+            let b=Int((e>>i)&1)
+            R[1-b].mul(R[b])
+            R[b].usqr()
+        }
+        copy(R[0])
+    }
+
+    public func compow(_ e :BIG,_ r :BIG) -> FP4
+    {
+        let f=FP2(BIG(ROM.Fra),BIG(ROM.Frb))
+        let q=BIG(ROM.Modulus)       
+
+        var g1=FP12(self)
+        var g2=FP12(self)
+
+        var m=BIG(q)
+        m.mod(r)
+    
+        var a=BIG(e)
+        a.mod(m)
+    
+        var b=BIG(e)
+        b.div(m);
+    
+        var c=g1.trace()
+
+	if b.iszilch() 
+	{
+		c=c.xtr_pow(e)
+		return c
+	}
+
+        g2.frob(f)
+        let cp=g2.trace()
+        g1.conj()
+        g2.mul(g1)
+        let cpm1=g2.trace()
+        g2.mul(g1)
+        let cpm2=g2.trace()
+    
+        c=c.xtr_pow2(cp,cpm1,cpm2,a,b)
+
+        return c
+    }
+    
+
+    /* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3 */
+    // Bos & Costello https://eprint.iacr.org/2013/458.pdf
+    // Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
+    // Side channel attack secure 
+
+    static func pow4(_ q:[FP12],_ u:[BIG]) -> FP12
+    {
+        var g=[FP12]();
+        
+        for _ in 0 ..< 8 {g.append(FP12(0))}
+        
+        var r=FP12(0)
+        var p=FP12(0)
+        
+        var t=[BIG]()
+        for i in 0 ..< 4 {
+            t.append(BIG(u[i]))
+            t[i].norm()
+        }
+
+        var mt=BIG(0);
+        var w=[Int8](repeating: 0,count: BIG.NLEN*Int(BIG.BASEBITS)+1)           
+        var s=[Int8](repeating: 0,count: BIG.NLEN*Int(BIG.BASEBITS)+1)   
+
+// precompute table 
+        g[0].copy(q[0])   // q[0]
+        g[1].copy(g[0]); g[1].mul(q[1])   // q[0].q[1]
+        g[2].copy(g[0]); g[2].mul(q[2])   // q[0].q[2]
+        g[3].copy(g[1]); g[3].mul(q[2])   // q[0].q[1].q[2]
+        g[4].copy(g[0]); g[4].mul(q[3])   // q[0].q[3]
+        g[5].copy(g[1]); g[5].mul(q[3])   // q[0].q[1].q[3]
+        g[6].copy(g[2]); g[6].mul(q[3])   // q[0].q[2].q[3]
+        g[7].copy(g[3]); g[7].mul(q[3])   // q[0].q[1].q[2].q[3]
+
+// Make it odd
+        let pb=1-t[0].parity()
+        t[0].inc(pb)
+        t[0].norm()  
+
+// Number of bits
+        mt.zero();
+        for i in 0 ..< 4 {
+            mt.or(t[i]); 
+        }
+
+        let nb=1+mt.nbits()
+
+// Sign pivot 
+
+        s[nb-1]=1
+        for i in 0 ..< nb-1 {
+            t[0].fshr(1)
+            s[i]=2*Int8(t[0].parity())-1
+        }
+
+// Recoded exponent
+        for i in 0 ..< nb {
+            w[i]=0
+            var k=1
+            for j in 1 ..< 4 {
+                let bt=s[i]*Int8(t[j].parity())
+                t[j].fshr(1)
+                t[j].dec(Int(bt>>1))
+                t[j].norm()
+                w[i]+=bt*Int8(k)
+                k=2*k
+            }
+        }   
+
+// Main loop
+        p.select(g,Int32(2*w[nb-1]+1))
+        for i in (0 ..< nb-1).reversed() {
+            p.usqr()
+            r.select(g,Int32(2*w[i]+s[i]))
+            p.mul(r)
+        }      
+
+// apply correction
+        r.copy(q[0]); r.conj()   
+        r.mul(p)
+        p.cmove(r,pb)
+        p.reduce()
+        return p
+    }
+
+    /* p=q0^u0.q1^u1.q2^u2.q3^u3 */
+    /* Timing attack secure, but not cache attack secure */
+/*    
+    static func pow4(_ q:[FP12],_ u:[BIG]) -> FP12
+    {
+        var a=[Int32](repeating: 0,count: 4)
+        var g=[FP12]();
+        
+        for _ in 0 ..< 8 {g.append(FP12(0))}
+        var s=[FP12]();
+        for _ in 0 ..< 2 {s.append(FP12(0))}
+        
+        let c=FP12(1)
+        let p=FP12(0)
+        
+        var t=[BIG]()
+        for i in 0 ..< 4
+            {t.append(BIG(u[i]))}
+        
+        let mt=BIG(0);
+        var w=[Int8](repeating: 0,count: BIG.NLEN*Int(BIG.BASEBITS)+1)
+    
+        g[0].copy(q[0]); s[0].copy(q[1]); s[0].conj(); g[0].mul(s[0])
+        g[1].copy(g[0])
+        g[2].copy(g[0])
+        g[3].copy(g[0])
+        g[4].copy(q[0]); g[4].mul(q[1])
+        g[5].copy(g[4])
+        g[6].copy(g[4])
+        g[7].copy(g[4])
+    
+        s[1].copy(q[2]); s[0].copy(q[3]); s[0].conj(); s[1].mul(s[0])
+        s[0].copy(s[1]); s[0].conj(); g[1].mul(s[0])
+        g[2].mul(s[1])
+        g[5].mul(s[0])
+        g[6].mul(s[1])
+        s[1].copy(q[2]); s[1].mul(q[3])
+        s[0].copy(s[1]); s[0].conj(); g[0].mul(s[0])
+        g[3].mul(s[1])
+        g[4].mul(s[0])
+        g[7].mul(s[1])
+
+    // if power is even add 1 to power, and add q to correction 
+    
+        for i in 0 ..< 4
+        {
+            if t[i].parity()==0
+            {
+				t[i].inc(1); t[i].norm()
+				c.mul(q[i])
+            }
+            mt.add(t[i]); mt.norm()
+        }
+        c.conj();
+        let nb=1+mt.nbits();
+    
+    // convert exponent to signed 1-bit window 
+        for j in 0 ..< nb
+        {
+            	for i in 0 ..< 4
+            	{
+			a[i]=Int32(t[i].lastbits(2)-2)
+			t[i].dec(Int(a[i]));
+                	t[i].norm()
+			t[i].fshr(1)
+            	}
+		let sum=8*a[0]+4*a[1]+2*a[2]+a[3]
+  		w[j]=Int8(sum)
+        }
+        w[nb]=Int8(8*t[0].lastbits(2)+4*t[1].lastbits(2))
+        w[nb]+=Int8(2*t[2].lastbits(2)+t[3].lastbits(2))
+        p.copy(g[Int(w[nb]-1)/2])
+    
+        //for var i=nb-1;i>=0;i--
+        for i in (0...nb-1).reversed()
+        {
+            let m=w[i]>>7
+            let j=(w[i]^m)-m  // j=abs(w[i]) 
+            let k=Int((j-1)/2)
+            s[0].copy(g[k]); s[1].copy(g[k]); s[1].conj()
+            p.usqr()
+            p.mul(s[Int(m&1)])
+        }
+        p.mul(c)  // apply correction 
+        p.reduce()
+        return p
+    }
+    
+*/    
+    
+    
+
+}
diff --git a/version3/swift/fp16.swift b/version3/swift/fp16.swift
new file mode 100644
index 0000000..d053395
--- /dev/null
+++ b/version3/swift/fp16.swift
@@ -0,0 +1,576 @@
+/*
+	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.
+*/
+
+//
+//  fp16.swift
+//
+//  Created by Michael Scott on 07/07/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+/* Finite Field arithmetic  Fp^16 functions */
+
+/* FP16 elements are of the form a+ib, where i is sqrt(sqrt(sqrt(-1+sqrt(-1)))  */
+
+public struct FP16 {
+    private var a:FP8
+    private var b:FP8
+
+    /* constructors */
+    init(_ c:Int)
+    {
+        a=FP8(c)
+        b=FP8(0)
+    }
+    
+    init(_ x:FP16)
+    {
+        a=FP8(x.a)
+        b=FP8(x.b)
+    }
+    
+    init(_ c:FP8,_ d:FP8)
+    {
+        a=FP8(c)
+        b=FP8(d)
+    }
+    
+    init(_ c:FP8)
+    {
+        a=FP8(c)
+        b=FP8(0)
+    }
+    /* reduce all components of this mod Modulus */
+    mutating func reduce()
+    {
+        a.reduce()
+        b.reduce()
+    }
+    /* normalise all components of this mod Modulus */
+    mutating func norm()
+    {
+        a.norm()
+        b.norm()
+    }
+    /* test this==0 ? */
+    func iszilch() -> Bool
+    {
+        //reduce()
+        return a.iszilch() && b.iszilch()
+    }
+
+    mutating func cmove(_ g:FP16,_ d:Int)
+    {
+        a.cmove(g.a,d)
+        b.cmove(g.b,d)
+    }
+
+
+    /* test this==1 ? */
+    func isunity() -> Bool
+    {
+        let one=FP8(1);
+        return a.equals(one) && b.iszilch()
+    }
+    
+    /* test is w real? That is in a+ib test b is zero */
+    func isreal() -> Bool
+    {
+        return b.iszilch();
+    }
+    /* extract real part a */
+    func real() -> FP8
+    {
+        return a;
+    }
+    
+    func geta() -> FP8
+    {
+        return a;
+    }
+    /* extract imaginary part b */
+    func getb() -> FP8
+    {
+        return b;
+    }
+
+    /* test self=x? */
+    func equals(_ x:FP16) -> Bool
+    {
+        return a.equals(x.a) && b.equals(x.b)
+    }
+    /* copy self=x */
+    mutating func copy(_ x:FP16)
+    {
+        a.copy(x.a)
+        b.copy(x.b)
+    }    
+
+        /* set this=0 */
+    mutating func zero()
+    {
+        a.zero()
+        b.zero()
+    }
+    /* set this=1 */
+    mutating func one()
+    {
+        a.one()
+        b.zero()
+    }
+    /* set self=-self */
+    mutating func neg()
+    {
+        norm()
+        var m=FP8(a)
+        var t=FP8(0)
+        m.add(b)
+        m.neg()
+    //    m.norm()
+        t.copy(m); t.add(b)
+        b.copy(m)
+        b.add(a)
+        a.copy(t)
+        norm()
+    }
+    /* self=conjugate(self) */
+    mutating func conj()
+    {
+        b.neg(); norm()
+    }
+    /* this=-conjugate(this) */
+    mutating func nconj()
+    {
+        a.neg(); norm()
+    }
+    /* self+=x */
+
+    mutating func adds(_ x: FP8)
+    {
+        a.add(x)
+    }
+
+    mutating func add(_ x:FP16)
+    {
+        a.add(x.a)
+        b.add(x.b)
+    }
+    /* self-=x */
+    mutating func sub(_ x:FP16)
+    {
+        var m=FP16(x)
+        m.neg()
+        add(m)
+    }
+
+    /* self-=x */
+    mutating func rsub(_ x: FP16) {
+        neg()
+        add(x)
+    }    
+
+    /* self*=s where s is FP8 */
+    mutating func pmul(_ s:FP8)
+    {
+        a.mul(s)
+        b.mul(s)
+    }
+
+    /* self*=s where s is FP2 */
+    mutating func qmul(_ s:FP2) {
+        a.qmul(s)
+        b.qmul(s)
+    }
+
+    /* self*=c where c is int */
+    mutating func imul(_ c:Int)
+    {
+        a.imul(c)
+        b.imul(c)
+    }
+
+    /* self*=self */
+    mutating func sqr()
+    {
+//        norm();
+    
+        var t1=FP8(a)
+        var t2=FP8(b)
+        var t3=FP8(a)
+    
+        t3.mul(b)
+        t1.add(b)
+        t2.times_i()
+    
+        t2.add(a)
+
+        t1.norm(); t2.norm()
+        a.copy(t1)
+    
+        a.mul(t2)
+    
+        t2.copy(t3)
+        t2.times_i()
+        t2.add(t3); t2.norm()
+
+        t2.neg()
+        a.add(t2)
+    
+        b.copy(t3)
+        b.add(t3)
+    
+        norm()
+    }
+
+    /* self*=y */
+    mutating func mul(_ y:FP16)
+    {
+    //    norm();
+    
+        var t1=FP8(a)
+        var t2=FP8(b)
+        var t3=FP8(0)
+        var t4=FP8(b)
+    
+        t1.mul(y.a)
+        t2.mul(y.b)
+        t3.copy(y.b)
+        t3.add(y.a)
+        t4.add(a)
+
+        t3.norm(); t4.norm()
+    
+        t4.mul(t3)
+
+        t3.copy(t1)
+        t3.neg()
+        t4.add(t3)
+        t4.norm()
+
+        t3.copy(t2)
+        t3.neg()
+        b.copy(t4)
+        b.add(t3)
+
+        t2.times_i()
+        a.copy(t2)
+        a.add(t1)
+
+        norm();
+    }
+    /* convert this to hex string */
+    func toString() -> String
+    {
+        return ("["+a.toString()+","+b.toString()+"]")
+    }
+
+   func toRawString() -> String
+    {
+        return ("["+a.toRawString()+","+b.toRawString()+"]")
+    }
+    /* self=1/self */
+    mutating func inverse()
+    {
+        norm();
+    
+        var t1=FP8(a)
+        var t2=FP8(b)
+    
+        t1.sqr()
+        t2.sqr()
+        t2.times_i(); t2.norm()
+        t1.sub(t2); t1.norm()
+        t1.inverse()
+        a.mul(t1)
+        t1.neg(); t1.norm()
+        b.mul(t1)
+    }
+
+    /* self*=i where i = sqrt(sqrt(-1+sqrt(-1))) */
+    mutating func times_i()
+    {
+        var s=FP8(b)
+        let t=FP8(a)
+        s.times_i()
+        a.copy(s)
+        b.copy(t)
+        norm()
+    }
+
+    mutating func times_i2() {
+        a.times_i()
+        b.times_i()
+    }  
+
+    mutating func times_i4() {
+        a.times_i2()
+        b.times_i2()
+    }      
+
+    /* self=self^p using Frobenius */
+    mutating func frob(_ f:FP2)
+    {
+        var ff=FP2(f); ff.sqr(); ff.norm()
+
+        a.frob(ff)
+        b.frob(ff)
+        b.qmul(f)
+        b.times_i()
+    }
+
+    /* self=self^e */
+    func pow(_ e:BIG) -> FP16
+    {
+        var w=FP16(self)
+        w.norm()
+        var z=BIG(e)
+        var r=FP16(1)
+        z.norm()
+        while (true)
+        {
+            let bt=z.parity()
+            z.fshr(1)
+            if bt==1 {r.mul(w)}
+            if z.iszilch() {break}
+            w.sqr()
+        }
+        r.reduce()
+        return r
+    }
+
+    /* XTR xtr_a function */
+    mutating func xtr_A(_ w:FP16,_ y:FP16,_ z:FP16)
+    {
+        var r=FP16(w)
+        var t=FP16(w)
+        r.sub(y); r.norm()
+        r.pmul(a)
+        t.add(y); t.norm()
+        t.pmul(b)
+        t.times_i()
+    
+        copy(r)
+        add(t)
+        add(z)
+    
+        norm()
+    }
+    /* XTR xtr_d function */
+    mutating func xtr_D()
+    {
+        var w=FP16(self)
+        sqr(); w.conj()
+        w.add(w); w.norm();
+        sub(w)
+        reduce()
+    }
+    /* r=x^n using XTR method on traces of FP48s */
+    func xtr_pow(_ n:BIG) -> FP16
+    {
+        var sf=FP16(self)
+        sf.norm()
+        var a=FP16(3)
+        var b=FP16(sf)
+        var c=FP16(b)
+        c.xtr_D()
+        var t=FP16(0)
+        var r=FP16(0)
+    
+        //n.norm();
+        let par=n.parity()
+        var v=BIG(n); v.norm(); v.fshr(1)
+        if par==0 {v.dec(1); v.norm()}
+    
+        let nb=v.nbits()
+        //for i in (0...nb-1).reverse()
+        var i=nb-1
+        //for var i=nb-1;i>=0;i--
+        while i>=0
+        {
+            if (v.bit(UInt(i)) != 1)
+            {
+                t.copy(b)
+                sf.conj()
+                c.conj()
+                b.xtr_A(a,sf,c)
+                sf.conj()
+                c.copy(t)
+                c.xtr_D()
+                a.xtr_D()
+            }
+            else
+            {
+                t.copy(a); t.conj()
+                a.copy(b)
+                a.xtr_D()
+                b.xtr_A(c,sf,t)
+                c.xtr_D()
+            }
+            i-=1
+        }
+        if par==0 {r.copy(c)}
+        else {r.copy(b)}
+        r.reduce()
+        return r
+    }
+    
+    /* r=ck^a.cl^n using XTR double exponentiation method on traces of FP48s. See Stam thesis. */
+    func xtr_pow2(_ ck:FP16,_ ckml:FP16,_ ckm2l:FP16,_ a:BIG,_ b:BIG) -> FP16
+    {
+ 
+        var e=BIG(a)
+        var d=BIG(b)
+        var w=BIG(0)
+        e.norm(); d.norm()    
+
+        var cu=FP16(ck)  // can probably be passed in w/o copying
+        var cv=FP16(self)
+        var cumv=FP16(ckml)
+        var cum2v=FP16(ckm2l)
+        var r=FP16(0)
+        var t=FP16(0)
+    
+        var f2:Int=0
+        while d.parity()==0 && e.parity()==0
+        {
+            d.fshr(1);
+            e.fshr(1);
+            f2 += 1;
+        }
+    
+        while (BIG.comp(d,e) != 0)
+        {
+            if BIG.comp(d,e)>0
+            {
+                w.copy(e); w.imul(4); w.norm()
+                if BIG.comp(d,w)<=0
+                {
+                    w.copy(d); d.copy(e)
+                    e.rsub(w); e.norm()
+    
+                    t.copy(cv)
+                    t.xtr_A(cu,cumv,cum2v)
+                    cum2v.copy(cumv)
+                    cum2v.conj()
+                    cumv.copy(cv)
+                    cv.copy(cu)
+                    cu.copy(t)
+    
+                }
+                else if d.parity()==0
+                {
+                    d.fshr(1)
+                    r.copy(cum2v); r.conj()
+                    t.copy(cumv)
+                    t.xtr_A(cu,cv,r)
+                    cum2v.copy(cumv)
+                    cum2v.xtr_D()
+                    cumv.copy(t)
+                    cu.xtr_D()
+                }
+                else if e.parity()==1
+                {
+                    d.sub(e); d.norm()
+                    d.fshr(1)
+                    t.copy(cv)
+                    t.xtr_A(cu,cumv,cum2v)
+                    cu.xtr_D()
+                    cum2v.copy(cv)
+                    cum2v.xtr_D()
+                    cum2v.conj()
+                    cv.copy(t)
+                }
+                else
+                {
+                    w.copy(d)
+                    d.copy(e); d.fshr(1)
+                    e.copy(w)
+                    t.copy(cumv)
+                    t.xtr_D()
+                    cumv.copy(cum2v); cumv.conj()
+                    cum2v.copy(t); cum2v.conj()
+                    t.copy(cv)
+                    t.xtr_D()
+                    cv.copy(cu)
+                    cu.copy(t)
+                }
+            }
+            if BIG.comp(d,e)<0
+            {
+                w.copy(d); w.imul(4); w.norm()
+                if BIG.comp(e,w)<=0
+                {
+                    e.sub(d); e.norm()
+                    t.copy(cv)
+                    t.xtr_A(cu,cumv,cum2v)
+                    cum2v.copy(cumv)
+                    cumv.copy(cu)
+                    cu.copy(t)
+                }
+                else if e.parity()==0
+                {
+                    w.copy(d)
+                    d.copy(e); d.fshr(1)
+                    e.copy(w)
+                    t.copy(cumv)
+                    t.xtr_D()
+                    cumv.copy(cum2v); cumv.conj()
+                    cum2v.copy(t); cum2v.conj()
+                    t.copy(cv)
+                    t.xtr_D()
+                    cv.copy(cu)
+                    cu.copy(t)
+                }
+                else if d.parity()==1
+                {
+                    w.copy(e)
+                    e.copy(d)
+                    w.sub(d); w.norm()
+                    d.copy(w); d.fshr(1)
+                    t.copy(cv)
+                    t.xtr_A(cu,cumv,cum2v)
+                    cumv.conj()
+                    cum2v.copy(cu)
+                    cum2v.xtr_D()
+                    cum2v.conj()
+                    cu.copy(cv)
+                    cu.xtr_D()
+                    cv.copy(t)
+                }
+                else
+                {
+                    d.fshr(1)
+                    r.copy(cum2v); r.conj()
+                    t.copy(cumv)
+                    t.xtr_A(cu,cv,r)
+                    cum2v.copy(cumv)
+                    cum2v.xtr_D()
+                    cumv.copy(t)
+                    cu.xtr_D()
+                }
+            }
+        }
+        r.copy(cv)
+        r.xtr_A(cu,cumv,cum2v)
+        for _ in 0 ..< f2
+            {r.xtr_D()}
+        r=r.xtr_pow(d)
+        return r
+    }
+}
diff --git a/version3/swift/fp2.swift b/version3/swift/fp2.swift
new file mode 100644
index 0000000..fc8fb49
--- /dev/null
+++ b/version3/swift/fp2.swift
@@ -0,0 +1,359 @@
+/*
+	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.
+*/
+
+//
+//  fp2.swift
+//
+//  Created by Michael Scott on 07/07/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+/* Finite Field arithmetic  Fp^2 functions */
+
+/* FP2 elements are of the form a+ib, where i is sqrt(-1) */
+
+
+public struct FP2
+{
+    private var a:FP
+    private var b:FP
+
+    /* Constructors */
+    init(_ c: Int)
+    {
+        a=FP(c)
+        b=FP(0)
+    }
+    
+    init(_ x:FP2)
+    {
+        a=FP(x.a)
+        b=FP(x.b)
+    }
+
+    init(_ c:FP,_ d:FP)
+    {
+        a=FP(c)
+        b=FP(d)
+    }
+    
+    public init(_ c:BIG,_ d:BIG)
+    {
+        a=FP(c)
+        b=FP(d)
+    }
+
+    init(_ c:FP)
+    {
+        a=FP(c)
+        b=FP(0)
+    }
+    
+    init(_ c:BIG)
+    {
+        a=FP(c)
+        b=FP(0)
+    }
+
+    /* test this=0 ? */
+    func iszilch() -> Bool
+    {
+        //reduce()
+        return (a.iszilch() && b.iszilch())
+    }
+    
+    mutating func cmove(_ g:FP2,_ d:Int)
+    {
+        a.cmove(g.a,d)
+        b.cmove(g.b,d)
+    }
+
+    /* test this=1 ? */
+    func isunity() -> Bool
+    {
+        let one=FP(1)
+        return (a.equals(one) && b.iszilch())
+    }
+    
+    /* test this=x */
+    func equals(_ x:FP2) -> Bool
+    {
+        return (a.equals(x.a) && b.equals(x.b));
+    }
+    
+    
+    /* reduce components mod Modulus */
+    mutating func reduce()
+    {
+        a.reduce()
+        b.reduce()
+    }
+    
+    /* normalise components of w */
+    mutating func norm()
+    {
+        a.norm()
+        b.norm()
+    }
+    
+    /* extract a */
+    func getA() -> BIG
+    {
+        return a.redc()
+    }
+    
+    /* extract b */
+    func getB() -> BIG
+    {
+        return b.redc()
+    }
+
+    /* copy self=x */
+    mutating func copy(_ x:FP2)
+    {
+        a.copy(x.a)
+        b.copy(x.b)
+    }
+    
+    /* set self=0 */
+    mutating func zero()
+    {
+        a.zero()
+        b.zero()
+    }
+    
+    /* set self=1 */
+    mutating func one()
+    {
+        a.one()
+        b.zero()
+    }
+    
+    /* negate self mod Modulus */
+    mutating func neg()
+    {
+    //    norm();
+        var m=FP(a)
+        var t=FP(0)
+    
+        m.add(b)
+        m.neg()
+    //    m.norm()
+        t.copy(m); t.add(b)
+        b.copy(m)
+        b.add(a)
+        a.copy(t)
+    }
+    
+    /* set to a-ib */
+    mutating func conj()
+    {
+        b.neg(); b.norm()
+    }
+
+    /* self+=a */
+    mutating func add(_ x:FP2)
+    {
+        a.add(x.a)
+        b.add(x.b)
+    }
+    
+    /* self-=a */
+    mutating func sub(_ x:FP2)
+    {
+        var m=FP2(x)
+        m.neg()
+        add(m)
+    }
+
+    /* self=a-self */
+    mutating func rsub(_ x:FP2)
+    {
+        self.neg()
+        self.add(x)
+    }
+
+    /* self*=s, where s is an FP */
+    mutating func pmul(_ s:FP)
+    {
+        a.mul(s)
+        b.mul(s)
+    }
+    
+    /* self*=i, where i is an int */
+    mutating func imul(_ c:Int)
+    {
+        a.imul(c);
+        b.imul(c);
+    }
+    
+    /* self*=self */
+    mutating func sqr()
+    {
+        var w1=FP(a)
+        var w3=FP(a)
+        var mb=FP(b)
+
+        w1.add(b)
+
+        w3.add(a)
+        w3.norm()
+        b.mul(w3)
+
+        mb.neg()
+        a.add(mb)
+
+        a.norm()
+        w1.norm()
+
+        a.mul(w1)
+
+    }
+    /* self*=y */
+    mutating func mul(_ y:FP2)
+    { 
+        if Int64(a.xes+b.xes)*Int64(y.a.xes+y.b.xes) > Int64(FP.FEXCESS)
+        {
+            if a.xes>1 {a.reduce()}
+            if b.xes>1 {b.reduce()}       
+        }
+
+        var pR=DBIG(0)
+        pR.ucopy(FP.p)
+
+        var C=BIG(a.x)
+        var D=BIG(y.a.x)
+
+        var A=BIG.mul(a.x,y.a.x)
+        var B=BIG.mul(b.x,y.b.x)
+
+        C.add(b.x); C.norm()
+        D.add(y.b.x); D.norm()
+
+        var E=BIG.mul(C,D)
+        var F=DBIG(A); F.add(B);
+        B.rsub(pR);
+
+        A.add(B); A.norm()
+        E.sub(F); E.norm()
+
+        a.x.copy(FP.mod(&A)); a.xes=3
+        b.x.copy(FP.mod(&E)); b.xes=2
+    
+    }
+ 
+    /* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */
+    /* returns true if this is QR */
+    mutating func sqrt() -> Bool
+    {
+        if iszilch() {return true}
+        var w1=FP(b)
+        var w2=FP(a)
+        w1.sqr(); w2.sqr(); w1.add(w2)
+        if w1.jacobi() != 1 { zero(); return false; }
+        w1=w1.sqrt()
+        w2.copy(a); w2.add(w1); w2.norm(); w2.div2()
+        if w2.jacobi() != 1
+        {
+            w2.copy(a); w2.sub(w1); w2.norm(); w2.div2()
+            if w2.jacobi() != 1 { zero(); return false }
+        }
+        w2=w2.sqrt()
+        a.copy(w2)
+        w2.add(w2)
+        w2.inverse()
+        b.mul(w2)
+        return true
+    }
+    /* output to hex string */
+    func toString() -> String
+    {
+        return ("["+a.toString()+","+b.toString()+"]")
+    }
+    
+    func toRawString() -> String
+    {
+        return ("["+a.toRawString()+","+b.toRawString()+"]")
+    }
+
+    /* self=1/self */
+    mutating func inverse()
+    {
+        norm();
+        var w1=FP(a)
+        var w2=FP(b)
+    
+        w1.sqr()
+        w2.sqr()
+        w1.add(w2)
+        w1.inverse()
+        a.mul(w1)
+        w1.neg(); w1.norm()
+        b.mul(w1)
+    }
+
+    /* self/=2 */
+    mutating func div2()
+    {
+        a.div2();
+        b.div2();
+    }
+    
+    /* self*=sqrt(-1) */
+    mutating func times_i()
+    {
+        let z=FP(a)
+        a.copy(b); a.neg()
+        b.copy(z)
+    }
+
+    /* w*=(1+sqrt(-1)) */
+    /* where X*2-(1+sqrt(-1)) is irreducible for FP4, assumes p=3 mod 8 */
+    mutating func mul_ip()
+    {
+    //    norm();
+        let t=FP2(self)
+        let z=FP(a)
+        a.copy(b)
+        a.neg()
+        b.copy(z)
+        add(t)
+    //    norm()
+    }
+    /* w/=(1+sqrt(-1)) */
+    mutating func div_ip()
+    {
+        var t=FP2(0)
+        norm()
+        t.a.copy(a); t.a.add(b)
+        t.b.copy(b); t.b.sub(a)
+        copy(t); norm()
+        div2()
+    }
+    
+    mutating func div_ip2()
+    {
+        var t=FP2(0)
+	norm()
+        t.a.copy(a); t.a.add(b)
+        t.b.copy(b); t.b.sub(a)
+        copy(t); norm()
+    }
+
+}
diff --git a/version3/swift/fp24.swift b/version3/swift/fp24.swift
new file mode 100644
index 0000000..40d3f55
--- /dev/null
+++ b/version3/swift/fp24.swift
@@ -0,0 +1,852 @@
+/*
+	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.
+*/
+
+//
+//  fp24.swift
+//
+//  Created by Michael Scott on 07/07/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+/* AMCL Fp^24 functions */
+/* FP24 elements are of the form a+i.b+i^2.c */
+
+public struct FP24
+{
+    private var a:FP8
+    private var b:FP8
+    private var c:FP8
+    
+    /* reduce all components of this mod Modulus */
+    mutating func reduce()
+    {
+        a.reduce()
+        b.reduce()
+        c.reduce()
+    }
+    /* normalise all components of this */
+    mutating func norm()
+    {
+        a.norm();
+        b.norm();
+        c.norm();
+    }
+    /* Constructors */
+    init(_ d:FP8)
+    {
+        a=FP8(d)
+        b=FP8(0)
+        c=FP8(0)
+    }
+    
+    init(_ d:Int)
+    {
+        a=FP8(d)
+        b=FP8(0)
+        c=FP8(0)
+    }
+
+    init(_ d:FP8,_ e:FP8,_ f:FP8)
+    {
+        a=FP8(d)
+        b=FP8(e)
+        c=FP8(f)
+    }
+    
+    init(_ x:FP24)
+    {
+        a=FP8(x.a)
+        b=FP8(x.b)
+        c=FP8(x.c)
+    }
+    /* test x==0 ? */
+    func iszilch() -> Bool
+    {
+        //reduce();
+        return a.iszilch() && b.iszilch() && c.iszilch()
+    }
+
+    mutating func cmove(_ g:FP24,_ d:Int)
+    {
+        a.cmove(g.a,d)
+        b.cmove(g.b,d)
+        c.cmove(g.c,d)
+    }
+
+    /* return 1 if b==c, no branching */
+    private static func teq(_ b:Int32,_ c:Int32) -> Int
+    {
+        var x=b^c
+        x-=1  // if x=0, x now -1
+        return Int((x>>31)&1)
+    }
+    /* Constant time select from pre-computed table */
+    mutating func select(_ g:[FP24],_ b:Int32)
+    {
+
+        let m=b>>31
+        var babs=(b^m)-m
+        
+        babs=(babs-1)/2
+    
+        cmove(g[0],FP24.teq(babs,0)) // conditional move
+        cmove(g[1],FP24.teq(babs,1))
+        cmove(g[2],FP24.teq(babs,2))
+        cmove(g[3],FP24.teq(babs,3))
+        cmove(g[4],FP24.teq(babs,4))
+        cmove(g[5],FP24.teq(babs,5))
+        cmove(g[6],FP24.teq(babs,6))
+        cmove(g[7],FP24.teq(babs,7))
+    
+        var invf=FP24(self)
+        invf.conj()
+        cmove(invf,Int(m&1))
+    }
+
+    /* test x==1 ? */
+    public func isunity() -> Bool
+    {
+        let one=FP8(1)
+        return a.equals(one) && b.iszilch() && c.iszilch()
+    }
+    /* return 1 if x==y, else 0 */
+    public func equals(_ x:FP24) -> Bool
+    {
+        return a.equals(x.a) && b.equals(x.b) && c.equals(x.c)
+    }
+    /* extract a from self */
+    func geta() -> FP8
+    {
+        return a
+    }
+    /* extract b */
+    func getb()  -> FP8
+    {
+        return b
+    }
+    /* extract c */
+    func getc() -> FP8
+    {
+        return c
+    }
+    /* copy self=x */
+    public mutating func copy(_ x:FP24)
+    {
+        a.copy(x.a)
+        b.copy(x.b)
+        c.copy(x.c)
+    }
+    /* set self=1 */
+    mutating func one()
+    {
+        a.one()
+        b.zero()
+        c.zero()
+    }
+    /* self=conj(self) */
+    mutating func conj()
+    {
+        a.conj()
+        b.nconj()
+        c.conj()
+    }
+
+    /* Granger-Scott Unitary Squaring */
+    mutating func usqr()
+    {
+        var A=FP8(a)
+        var B=FP8(c)
+        var C=FP8(b)
+        var D=FP8(0)
+    
+        a.sqr()
+        D.copy(a); D.add(a)
+        a.add(D)
+    
+        a.norm()
+        A.nconj()
+    
+        A.add(A)
+        a.add(A)
+        B.sqr()
+        B.times_i()
+    
+        D.copy(B); D.add(B)
+        B.add(D)
+        B.norm()
+    
+        C.sqr()
+        D.copy(C); D.add(C)
+        C.add(D)
+        C.norm()
+    
+        b.conj()
+        b.add(b)
+        c.nconj()
+    
+        c.add(c)
+        b.add(B)
+        c.add(C)
+        reduce()
+    
+    }
+
+    /* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
+    mutating func sqr()
+    {
+        var A=FP8(a)
+        var B=FP8(b)
+        var C=FP8(c)
+        var D=FP8(a)
+    
+        A.sqr()
+        B.mul(c)
+        B.add(B); B.norm()
+        C.sqr()
+        D.mul(b)
+        D.add(D)
+
+        c.add(a)
+        c.add(b); c.norm()
+        c.sqr()
+    
+        a.copy(A)
+    
+        A.add(B)
+        A.norm()
+        A.add(C)
+        A.add(D)
+        A.norm()
+    
+        A.neg()
+        B.times_i()
+        C.times_i()
+    
+        a.add(B)
+
+        b.copy(C); b.add(D)
+        c.add(A)
+    
+        norm()
+    }
+
+    /* FP24 full multiplication this=this*y */
+    mutating func mul(_ y:FP24)
+    {
+        var z0=FP8(a)
+        var z1=FP8(0)
+        var z2=FP8(b)
+        var z3=FP8(0)
+        var t0=FP8(a)
+        var t1=FP8(y.a)
+    
+        z0.mul(y.a)
+        z2.mul(y.b)
+    
+        t0.add(b)
+        t1.add(y.b)
+
+        t0.norm(); t1.norm()
+    
+        z1.copy(t0); z1.mul(t1)
+        t0.copy(b); t0.add(c)
+    
+        t1.copy(y.b); t1.add(y.c)
+
+        t0.norm(); t1.norm()
+
+        z3.copy(t0); z3.mul(t1)
+    
+        t0.copy(z0); t0.neg()
+        t1.copy(z2); t1.neg()
+    
+        z1.add(t0)
+        b.copy(z1); b.add(t1)
+    
+        z3.add(t1)
+        z2.add(t0)
+    
+        t0.copy(a); t0.add(c)
+        t1.copy(y.a); t1.add(y.c)
+
+        t0.norm(); t1.norm()
+
+        t0.mul(t1)
+        z2.add(t0)
+    
+        t0.copy(c); t0.mul(y.c)
+        t1.copy(t0); t1.neg()
+    
+        c.copy(z2); c.add(t1)
+        z3.add(t1)
+        t0.times_i()
+        b.add(t0)
+    
+        z3.norm()
+        z3.times_i()
+        a.copy(z0); a.add(z3)
+    
+        norm()
+    }
+
+    /* Special case of multiplication arises from special form of ATE pairing line function */
+    mutating func smul(_ y:FP24,_ twist:Int)
+    {
+        if twist == ECP.D_TYPE {
+            var z0=FP8(a)
+            var z2=FP8(b)
+            var z3=FP8(b)
+            var t0=FP8(0)
+            var t1=FP8(y.a)
+    
+            z0.mul(y.a)
+            z2.pmul(y.b.real())
+            b.add(a)
+            t1.adds(y.b.real())
+    
+            b.norm(); t1.norm()
+
+            b.mul(t1)
+            z3.add(c); z3.norm()
+            z3.pmul(y.b.real())
+    
+            t0.copy(z0); t0.neg()
+            t1.copy(z2); t1.neg()
+    
+            b.add(t0)
+    
+            b.add(t1)
+            z3.add(t1)
+            z2.add(t0)
+    
+            t0.copy(a); t0.add(c)
+            t0.norm(); z3.norm()
+            t0.mul(y.a)
+            c.copy(z2); c.add(t0)
+    
+            z3.times_i()
+            a.copy(z0); a.add(z3)
+        }
+        if twist == ECP.M_TYPE {
+            var z0=FP8(a)
+            var z1=FP8(0)
+            var z2=FP8(0)
+            var z3=FP8(0)
+            var t0=FP8(a)
+            var t1=FP8(0)
+        
+            z0.mul(y.a)
+            t0.add(b)
+            t0.norm()
+
+            z1.copy(t0); z1.mul(y.a)
+            t0.copy(b); t0.add(c)
+            t0.norm();
+
+            z3.copy(t0); //z3.mul(y.c);
+            z3.pmul(y.c.getb())
+            z3.times_i()
+
+            t0.copy(z0); t0.neg()
+
+            z1.add(t0)
+            b.copy(z1);
+            z2.copy(t0)
+
+            t0.copy(a); t0.add(c)
+            t1.copy(y.a); t1.add(y.c)
+
+            t0.norm()
+            t1.norm()
+    
+            t0.mul(t1)
+            z2.add(t0)
+
+            t0.copy(c)
+            
+            t0.pmul(y.c.getb())
+            t0.times_i()
+
+            t1.copy(t0); t1.neg()
+
+            c.copy(z2); c.add(t1)
+            z3.add(t1)
+            t0.times_i()
+            b.add(t0)
+            z3.norm();
+            z3.times_i()
+            a.copy(z0); a.add(z3)      
+        }
+        norm()
+    }
+
+    /* self=1/self */
+    mutating func inverse()
+    {
+        var f0=FP8(a)
+        var f1=FP8(b)
+        var f2=FP8(a)
+        var f3=FP8(0)
+    
+        norm()
+        f0.sqr()
+        f1.mul(c)
+        f1.times_i()
+        f0.sub(f1); f0.norm()
+    
+        f1.copy(c); f1.sqr()
+        f1.times_i()
+        f2.mul(b)
+        f1.sub(f2); f1.norm()
+    
+        f2.copy(b); f2.sqr()
+        f3.copy(a); f3.mul(c)
+        f2.sub(f3); f2.norm()
+    
+        f3.copy(b); f3.mul(f2)
+        f3.times_i()
+        a.mul(f0)
+        f3.add(a)
+        c.mul(f1)
+        c.times_i()
+    
+        f3.add(c); f3.norm()
+        f3.inverse()
+        a.copy(f0); a.mul(f3)
+        b.copy(f1); b.mul(f3)
+        c.copy(f2); c.mul(f3)
+    }
+
+    /* self=self^p using Frobenius */
+    mutating func frob(_ f:FP2,_ n:Int)
+    {
+
+        var f2=FP2(f)
+        var f3=FP2(f)
+    
+        f2.sqr()
+        f3.mul(f2)
+        f3.mul_ip(); f3.norm()    
+
+        for _ in 0 ..< n {
+            a.frob(f3)
+            b.frob(f3)
+            c.frob(f3)
+
+            b.qmul(f); b.times_i2()
+            c.qmul(f2); c.times_i2(); c.times_i2()
+        }        
+
+    }
+
+    /* trace function */
+    func trace() -> FP8
+    {
+        var t=FP8(0)
+        t.copy(a)
+        t.imul(3)
+        t.reduce()
+        return t
+    }
+
+    /* convert from byte array to FP24 */
+    static func fromBytes(_ w:[UInt8]) -> FP24
+    {
+        let RM=Int(BIG.MODBYTES)
+        var t=[UInt8](repeating: 0,count: RM)
+    
+        for i in 0 ..< RM {t[i]=w[i]}
+        var a=BIG.fromBytes(t)
+        for i in 0 ..< RM {t[i]=w[i+RM]}
+        var b=BIG.fromBytes(t)
+        var c=FP2(a,b)
+    
+        for i in 0 ..< RM {t[i]=w[i+2*RM]}
+        a.copy(BIG.fromBytes(t))
+        for i in 0 ..< RM {t[i]=w[i+3*RM]}
+        b.copy(BIG.fromBytes(t))
+        var d=FP2(a,b)
+    
+        var ea=FP4(c,d)
+
+        for i in 0 ..< RM {t[i]=w[i+4*RM]}
+        a.copy(BIG.fromBytes(t))
+        for i in 0 ..< RM {t[i]=w[i+5*RM]}
+        b.copy(BIG.fromBytes(t))
+        c.copy(FP2(a,b))
+    
+        for i in 0 ..< RM {t[i]=w[i+6*RM]}
+        a.copy(BIG.fromBytes(t))
+        for i in 0 ..< RM {t[i]=w[i+7*RM]}
+        b.copy(BIG.fromBytes(t))
+        d.copy(FP2(a,b))
+    
+        var eb=FP4(c,d)
+
+        let e=FP8(ea,eb)
+    
+        for i in 0 ..< RM {t[i]=w[i+8*RM]}
+        a.copy(BIG.fromBytes(t))
+        for i in 0 ..< RM {t[i]=w[i+9*RM]}
+        b.copy(BIG.fromBytes(t))
+        c.copy(FP2(a,b))
+    
+        for i in 0 ..< RM {t[i]=w[i+10*RM]}
+        a.copy(BIG.fromBytes(t))
+        for i in 0 ..< RM {t[i]=w[i+11*RM]}
+        b.copy(BIG.fromBytes(t))
+        d.copy(FP2(a,b))
+
+        ea.copy(FP4(c,d))
+
+
+        for i in 0 ..< RM {t[i]=w[i+12*RM]}
+        a.copy(BIG.fromBytes(t))
+        for i in 0 ..< RM {t[i]=w[i+13*RM]}
+        b.copy(BIG.fromBytes(t))
+        c.copy(FP2(a,b))
+    
+        for i in 0 ..< RM {t[i]=w[i+14*RM]}
+        a.copy(BIG.fromBytes(t))
+        for i in 0 ..< RM {t[i]=w[i+15*RM]}
+        b.copy(BIG.fromBytes(t))
+        d.copy(FP2(a,b))
+
+        eb.copy(FP4(c,d))
+
+    
+        let f=FP8(ea,eb)
+    
+    
+        for i in 0 ..< RM {t[i]=w[i+16*RM]}
+        a.copy(BIG.fromBytes(t))
+        for i in 0 ..< RM {t[i]=w[i+17*RM]}
+        b.copy(BIG.fromBytes(t))
+        c.copy(FP2(a,b))
+    
+        for i in 0 ..< RM {t[i]=w[i+18*RM]}
+        a.copy(BIG.fromBytes(t))
+        for i in 0 ..< RM {t[i]=w[i+19*RM]}
+        b.copy(BIG.fromBytes(t))
+        d.copy(FP2(a,b))
+
+        ea.copy(FP4(c,d))
+
+    
+        for i in 0 ..< RM {t[i]=w[i+20*RM]}
+        a.copy(BIG.fromBytes(t))
+        for i in 0 ..< RM {t[i]=w[i+21*RM]}
+        b.copy(BIG.fromBytes(t))
+        c.copy(FP2(a,b))
+    
+        for i in 0 ..< RM {t[i]=w[i+22*RM]}
+        a.copy(BIG.fromBytes(t))
+        for i in 0 ..< RM {t[i]=w[i+23*RM]}
+        b.copy(BIG.fromBytes(t))
+        d.copy(FP2(a,b))
+
+        eb.copy(FP4(c,d))
+
+        let g=FP8(ea,eb)
+    
+        return FP24(e,f,g)
+    }
+
+    /* convert this to byte array */
+    func toBytes(_ w:inout [UInt8])
+    {
+        let RM=Int(BIG.MODBYTES)
+        var t=[UInt8](repeating: 0,count: RM)
+
+        a.geta().geta().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i]=t[i]}
+        a.geta().geta().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+RM]=t[i]}
+        a.geta().getb().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+2*RM]=t[i]}
+        a.geta().getb().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+3*RM]=t[i]}
+    
+        a.getb().geta().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+4*RM]=t[i]}
+        a.getb().geta().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+5*RM]=t[i]}
+        a.getb().getb().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+6*RM]=t[i]}
+        a.getb().getb().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+7*RM]=t[i]}
+  
+
+
+        b.geta().geta().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+8*RM]=t[i]}
+        b.geta().geta().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+9*RM]=t[i]}
+        b.geta().getb().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+10*RM]=t[i]}
+        b.geta().getb().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+11*RM]=t[i]}
+    
+        b.getb().geta().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+12*RM]=t[i]}
+        b.getb().geta().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+13*RM]=t[i]}
+        b.getb().getb().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+14*RM]=t[i]}
+        b.getb().getb().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+15*RM]=t[i]}
+
+
+
+        c.geta().geta().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+16*RM]=t[i]}
+        c.geta().geta().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+17*RM]=t[i]}
+        c.geta().getb().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+18*RM]=t[i]}
+        c.geta().getb().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+19*RM]=t[i]}
+
+        c.getb().geta().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+20*RM]=t[i]}
+        c.getb().geta().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+21*RM]=t[i]}
+        c.getb().getb().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+22*RM]=t[i]}
+        c.getb().getb().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+23*RM]=t[i]}        
+    }
+
+    /* convert to hex string */
+    public func toString() -> String
+    {
+        return ("["+a.toString()+","+b.toString()+","+c.toString()+"]")
+    }
+    
+    /* self=self^e */
+    /* Note this is simple square and multiply, so not side-channel safe */
+    func pow(_ e:BIG) -> FP24
+    {
+        var sf = FP24(self)
+        sf.norm()
+ 
+        var e1=BIG(e)
+        e1.norm()
+        var e3=BIG(e1)
+        e3.pmul(3)
+        e3.norm();
+
+        var w=FP24(sf)
+        let nb=e3.nbits()
+ 
+        for i in (1...nb-2).reversed()
+        {
+            w.usqr()
+            let bt=e3.bit(UInt(i))-e1.bit(UInt(i))
+            if bt == 1 {
+                w.mul(sf)
+            }
+            if bt == -1 {
+                sf.conj(); w.mul(sf); sf.conj()
+            }            
+        }
+    
+        w.reduce()
+        return w
+    }
+
+    /* constant time powering by small integer of max length bts */
+    mutating func pinpow(_ e:Int32,_ bts:Int32)
+    {
+        var R=[FP24]()
+        R.append(FP24(1))
+        R.append(FP24(self))
+
+        //for var i=bts-1;i>=0;i--
+        for i in (0...bts-1).reversed()
+        {
+            let b=Int((e>>i)&1)
+            R[1-b].mul(R[b])
+            R[b].usqr()
+        }
+        copy(R[0])
+    }
+
+    public func compow(_ e :BIG,_ r :BIG) -> FP8
+    {
+        let f=FP2(BIG(ROM.Fra),BIG(ROM.Frb))
+        let q=BIG(ROM.Modulus)       
+
+        var g1=FP24(self)
+        var g2=FP24(self)
+
+        var m=BIG(q)
+        m.mod(r)
+    
+        var a=BIG(e)
+        a.mod(m)
+    
+        var b=BIG(e)
+        b.div(m);
+    
+        var c=g1.trace()
+
+        if b.iszilch() 
+        {
+            c=c.xtr_pow(e)
+            return c
+        }
+
+        g2.frob(f,1)
+        let cp=g2.trace()
+        g1.conj()
+        g2.mul(g1)
+        let cpm1=g2.trace()
+        g2.mul(g1)
+        let cpm2=g2.trace()
+    
+        c=c.xtr_pow2(cp,cpm1,cpm2,a,b)
+
+        return c
+    }
+
+    /* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3.. */
+    // Bos & Costello https://eprint.iacr.org/2013/458.pdf
+    // Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
+    // Side channel attack secure 
+
+    static func pow8(_ q:[FP24],_ u:[BIG]) -> FP24
+    {
+        var g1=[FP24]()
+        var g2=[FP24]()        
+        
+        for _ in 0 ..< 8 {
+            g1.append(FP24(0))
+            g2.append(FP24(0))            
+        }
+        
+        var r=FP24(0)
+        var p=FP24(0)
+        
+        var t=[BIG]()
+        for i in 0 ..< 8 {
+            t.append(BIG(u[i]))
+            t[i].norm()
+        }
+
+        var mt=BIG(0);
+        var w1=[Int8](repeating: 0,count: BIG.NLEN*Int(BIG.BASEBITS)+1)           
+        var s1=[Int8](repeating: 0,count: BIG.NLEN*Int(BIG.BASEBITS)+1)   
+        var w2=[Int8](repeating: 0,count: BIG.NLEN*Int(BIG.BASEBITS)+1)           
+        var s2=[Int8](repeating: 0,count: BIG.NLEN*Int(BIG.BASEBITS)+1)   
+
+
+// precompute table 
+        g1[0].copy(q[0])   // q[0]
+        g1[1].copy(g1[0]); g1[1].mul(q[1])   // q[0].q[1]
+        g1[2].copy(g1[0]); g1[2].mul(q[2])   // q[0].q[2]
+        g1[3].copy(g1[1]); g1[3].mul(q[2])   // q[0].q[1].q[2]
+        g1[4].copy(g1[0]); g1[4].mul(q[3])   // q[0].q[3]
+        g1[5].copy(g1[1]); g1[5].mul(q[3])   // q[0].q[1].q[3]
+        g1[6].copy(g1[2]); g1[6].mul(q[3])   // q[0].q[2].q[3]
+        g1[7].copy(g1[3]); g1[7].mul(q[3])   // q[0].q[1].q[2].q[3]
+
+// Use Frobenius
+    let f=FP2(BIG(ROM.Fra),BIG(ROM.Frb))
+    for i in 0 ..< 8  {
+        g2[i].copy(g1[i]); g2[i].frob(f,4)       
+    }
+
+// Make it odd
+        let pb1=1-t[0].parity()
+        t[0].inc(pb1)
+        t[0].norm()  
+
+        let pb2=1-t[4].parity()
+        t[4].inc(pb2)
+        t[4].norm()          
+
+// Number of bits
+        mt.zero();
+        for i in 0 ..< 8 {
+            mt.or(t[i]); 
+        }
+
+        let nb=1+mt.nbits()
+
+// Sign pivot 
+
+        s1[nb-1]=1
+        s2[nb-1]=1
+        for i in 0 ..< nb-1 {
+            t[0].fshr(1)
+            s1[i]=2*Int8(t[0].parity())-1
+            t[4].fshr(1)
+            s2[i]=2*Int8(t[4].parity())-1            
+        }
+
+// Recoded exponent
+        for i in 0 ..< nb {
+            w1[i]=0
+            var k=1
+            for j in 1 ..< 4 {
+                let bt=s1[i]*Int8(t[j].parity())
+                t[j].fshr(1)
+                t[j].dec(Int(bt>>1))
+                t[j].norm()
+                w1[i]+=bt*Int8(k)
+                k=2*k
+            }
+            w2[i]=0
+            k=1
+            for j in 5 ..< 8 {
+                let bt=s2[i]*Int8(t[j].parity())
+                t[j].fshr(1)
+                t[j].dec(Int(bt>>1))
+                t[j].norm()
+                w2[i]+=bt*Int8(k)
+                k=2*k
+            }            
+        }   
+
+// Main loop
+        p.select(g1,Int32(2*w1[nb-1]+1))
+        r.select(g2,Int32(2*w2[nb-1]+1))
+        p.mul(r)        
+        for i in (0 ..< nb-1).reversed() {
+            p.usqr()
+            r.select(g1,Int32(2*w1[i]+s1[i]))
+            p.mul(r)
+            r.select(g2,Int32(2*w2[i]+s2[i]))
+            p.mul(r)            
+        }      
+
+// apply correction
+        r.copy(q[0]); r.conj()   
+        r.mul(p)
+        p.cmove(r,pb1)
+
+        r.copy(q[4]); r.conj()   
+        r.mul(p)
+        p.cmove(r,pb2)
+
+        p.reduce()
+        return p
+    }
+}
diff --git a/version3/swift/fp4.swift b/version3/swift/fp4.swift
new file mode 100644
index 0000000..8043e2d
--- /dev/null
+++ b/version3/swift/fp4.swift
@@ -0,0 +1,632 @@
+/*
+	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.
+*/
+
+//
+//  fp4.swift
+//
+//  Created by Michael Scott on 07/07/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+/* Finite Field arithmetic  Fp^4 functions */
+
+/* FP4 elements are of the form a+ib, where i is sqrt(-1+sqrt(-1))  */
+
+public struct FP4 {
+    private var a:FP2
+    private var b:FP2
+
+    /* constructors */
+    init(_ c:Int)
+    {
+        a=FP2(c)
+        b=FP2(0)
+    }
+    
+    init(_ x:FP4)
+    {
+        a=FP2(x.a)
+        b=FP2(x.b)
+    }
+    
+    init(_ c:FP2,_ d:FP2)
+    {
+        a=FP2(c)
+        b=FP2(d)
+    }
+    
+    init(_ c:FP2)
+    {
+        a=FP2(c)
+        b=FP2(0)
+    }
+    /* reduce all components of this mod Modulus */
+    mutating func reduce()
+    {
+        a.reduce()
+        b.reduce()
+    }
+    /* normalise all components of this mod Modulus */
+    mutating func norm()
+    {
+        a.norm()
+        b.norm()
+    }
+    /* test this==0 ? */
+    func iszilch() -> Bool
+    {
+        //reduce()
+        return a.iszilch() && b.iszilch()
+    }
+
+    mutating func cmove(_ g:FP4,_ d:Int)
+    {
+        a.cmove(g.a,d)
+        b.cmove(g.b,d)
+    }
+
+    /* test this==1 ? */
+    func isunity() -> Bool
+    {
+    let one=FP2(1);
+    return a.equals(one) && b.iszilch()
+    }
+    
+    /* test is w real? That is in a+ib test b is zero */
+    func isreal() -> Bool
+    {
+        return b.iszilch();
+    }
+    /* extract real part a */
+    func real() -> FP2
+    {
+        return a;
+    }
+    
+    func geta() -> FP2
+    {
+        return a;
+    }
+    /* extract imaginary part b */
+    func getb() -> FP2
+    {
+    return b;
+    }
+    /* test self=x? */
+    func equals(_ x:FP4) -> Bool
+    {
+        return a.equals(x.a) && b.equals(x.b)
+    }
+    /* copy self=x */
+    mutating func copy(_ x:FP4)
+    {
+        a.copy(x.a)
+        b.copy(x.b)
+    }
+    /* set this=0 */
+    mutating func zero()
+    {
+        a.zero()
+        b.zero()
+    }
+    /* set this=1 */
+    mutating func one()
+    {
+        a.one()
+        b.zero()
+    }
+    /* set self=-self */
+    mutating func neg()
+    {
+        norm()
+        var m=FP2(a)
+        var t=FP2(0)
+        m.add(b)
+        m.neg()
+    //    m.norm()
+        t.copy(m); t.add(b)
+        b.copy(m)
+        b.add(a)
+        a.copy(t)
+        norm()
+    }
+    /* self=conjugate(self) */
+    mutating func conj()
+    {
+        b.neg(); norm()
+    }
+    /* this=-conjugate(this) */
+    mutating func nconj()
+    {
+        a.neg(); norm()
+    }
+
+    mutating func adds(_ x: FP2)
+    {
+        a.add(x)
+    }
+
+    /* self+=x */
+    mutating func add(_ x:FP4)
+    {
+        a.add(x.a)
+        b.add(x.b)
+    }
+    /* self-=x */
+    mutating func sub(_ x:FP4)
+    {
+        var m=FP4(x)
+        m.neg()
+        add(m)
+    }
+    
+    /* self-=x */
+    mutating func rsub(_ x: FP4) {
+        neg()
+        add(x)
+    }    
+
+    /* self*=s where s is FP2 */
+    mutating func pmul(_ s:FP2)
+    {
+        a.mul(s)
+        b.mul(s)
+    }
+
+    /* self*=s where s is FP */
+    mutating func qmul(_ s:FP) {
+        a.pmul(s)
+        b.pmul(s)
+    }
+
+    /* self*=c where c is int */
+    mutating func imul(_ c:Int)
+    {
+        a.imul(c)
+        b.imul(c)
+    }
+    /* self*=self */
+    mutating func sqr()
+    {
+//        norm();
+    
+        var t1=FP2(a)
+        var t2=FP2(b)
+        var t3=FP2(a)
+    
+        t3.mul(b)
+        t1.add(b)
+        t2.mul_ip()
+    
+        t2.add(a)
+
+        t1.norm(); t2.norm()
+        a.copy(t1)
+    
+        a.mul(t2)
+    
+        t2.copy(t3)
+        t2.mul_ip()
+        t2.add(t3); t2.norm()
+
+        t2.neg()
+        a.add(t2)
+    
+        b.copy(t3)
+        b.add(t3)
+    
+        norm()
+    }
+    /* self*=y */
+    mutating func mul(_ y:FP4)
+    {
+    //    norm();
+    
+        var t1=FP2(a)
+        var t2=FP2(b)
+        var t3=FP2(0)
+        var t4=FP2(b)
+    
+        t1.mul(y.a)
+        t2.mul(y.b)
+        t3.copy(y.b)
+        t3.add(y.a)
+        t4.add(a)
+
+        t3.norm(); t4.norm()
+    
+        t4.mul(t3)
+
+        t3.copy(t1)
+        t3.neg()
+        t4.add(t3)
+        t4.norm()
+
+        t3.copy(t2)
+        t3.neg()
+        b.copy(t4)
+        b.add(t3)
+
+        t2.mul_ip()
+        a.copy(t2)
+        a.add(t1)
+
+        norm();
+    }
+    /* convert this to hex string */
+    func toString() -> String
+    {
+        return ("["+a.toString()+","+b.toString()+"]")
+    }
+    
+    func toRawString() -> String
+    {
+        return ("["+a.toRawString()+","+b.toRawString()+"]")
+    }
+    /* self=1/self */
+    mutating func inverse()
+    {
+        norm();
+    
+        var t1=FP2(a)
+        var t2=FP2(b)
+    
+        t1.sqr()
+        t2.sqr()
+        t2.mul_ip(); t2.norm()
+        t1.sub(t2)
+        t1.inverse()
+        a.mul(t1)
+        t1.neg(); t1.norm()
+        b.mul(t1)
+    }
+    
+    /* self*=i where i = sqrt(-1+sqrt(-1)) */
+    mutating func times_i()
+    {
+    //    norm();
+        var s=FP2(b)
+        var t=FP2(b)
+        s.times_i()
+        t.add(s)
+    //    t.norm()
+        b.copy(a)
+        a.copy(t)
+        norm()
+    }
+    
+    /* self=self^p using Frobenius */
+    mutating func frob(_ f:FP2)
+    {
+        a.conj()
+        b.conj()
+        b.mul(f)
+    }
+    /* self=self^e */
+    func pow(_ e:BIG) -> FP4
+    {
+        var w=FP4(self)
+        w.norm()        
+        var z=BIG(e)
+        var r=FP4(1)
+        z.norm()
+        while (true)
+        {
+            let bt=z.parity()
+            z.fshr(1)
+            if bt==1 {r.mul(w)}
+            if z.iszilch() {break}
+            w.sqr()
+        }
+        r.reduce()
+        return r
+    }
+    /* XTR xtr_a function */
+    mutating func xtr_A(_ w:FP4,_ y:FP4,_ z:FP4)
+    {
+        var r=FP4(w)
+        var t=FP4(w)
+        r.sub(y); r.norm()
+        r.pmul(a)
+        t.add(y); t.norm()
+        t.pmul(b)
+        t.times_i()
+    
+        copy(r)
+        add(t)
+        add(z)
+    
+        norm()
+    }
+    /* XTR xtr_d function */
+    mutating func xtr_D()
+    {
+        var w=FP4(self)
+        sqr(); w.conj()
+        w.add(w); w.norm();
+        sub(w)
+        reduce()
+    }
+    /* r=x^n using XTR method on traces of FP12s */
+    func xtr_pow(_ n:BIG) -> FP4
+    {
+        var a=FP4(3)
+        var b=FP4(self)
+        var c=FP4(b)
+        c.xtr_D()
+        var t=FP4(0)
+        var r=FP4(0)
+        var sf=FP4(self)
+    
+        //n.norm();
+        let par=n.parity()
+        var v=BIG(n); v.norm(); v.fshr(1)
+        if par==0 {v.dec(1); v.norm()}
+    
+        let nb=v.nbits()
+        //for i in (0...nb-1).reverse()
+        var i=nb-1
+        //for var i=nb-1;i>=0;i--
+        while i>=0
+        {
+            if (v.bit(UInt(i)) != 1)
+            {
+				t.copy(b)
+				sf.conj()
+				c.conj()
+				b.xtr_A(a,sf,c)
+				sf.conj()
+				c.copy(t)
+				c.xtr_D()
+				a.xtr_D()
+            }
+            else
+            {
+				t.copy(a); t.conj()
+				a.copy(b)
+				a.xtr_D()
+				b.xtr_A(c,sf,t)
+				c.xtr_D()
+            }
+            i-=1
+        }
+        if par==0 {r.copy(c)}
+        else {r.copy(b)}
+        r.reduce()
+        return r
+    }
+    
+    /* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */
+    func xtr_pow2(_ ck:FP4,_ ckml:FP4,_ ckm2l:FP4,_ a:BIG,_ b:BIG) -> FP4
+    {
+
+        var e=BIG(a)
+        var d=BIG(b)
+        var w=BIG(0)
+        e.norm(); d.norm()
+    
+        var cu=FP4(ck)  // can probably be passed in w/o copying
+        var cv=FP4(self)
+        var cumv=FP4(ckml)
+        var cum2v=FP4(ckm2l)
+        var r=FP4(0)
+        var t=FP4(0)
+    
+        var f2:Int=0
+        while d.parity()==0 && e.parity()==0
+        {
+            d.fshr(1);
+            e.fshr(1);
+            f2 += 1;
+        }
+    
+        while (BIG.comp(d,e) != 0)
+        {
+            if BIG.comp(d,e)>0
+            {
+				w.copy(e); w.imul(4); w.norm()
+				if BIG.comp(d,w)<=0
+				{
+                    w.copy(d); d.copy(e)
+                    e.rsub(w); e.norm()
+    
+                    t.copy(cv)
+                    t.xtr_A(cu,cumv,cum2v)
+                    cum2v.copy(cumv)
+                    cum2v.conj()
+                    cumv.copy(cv)
+                    cv.copy(cu)
+                    cu.copy(t)
+    
+				}
+				else if d.parity()==0
+				{
+                    d.fshr(1)
+                    r.copy(cum2v); r.conj()
+                    t.copy(cumv)
+                    t.xtr_A(cu,cv,r)
+                    cum2v.copy(cumv)
+                    cum2v.xtr_D()
+                    cumv.copy(t)
+                    cu.xtr_D()
+				}
+				else if e.parity()==1
+				{
+                    d.sub(e); d.norm()
+                    d.fshr(1)
+                    t.copy(cv)
+                    t.xtr_A(cu,cumv,cum2v)
+                    cu.xtr_D()
+                    cum2v.copy(cv)
+                    cum2v.xtr_D()
+                    cum2v.conj()
+                    cv.copy(t)
+				}
+				else
+				{
+                    w.copy(d)
+                    d.copy(e); d.fshr(1)
+                    e.copy(w)
+                    t.copy(cumv)
+                    t.xtr_D()
+                    cumv.copy(cum2v); cumv.conj()
+                    cum2v.copy(t); cum2v.conj()
+                    t.copy(cv)
+                    t.xtr_D()
+                    cv.copy(cu)
+                    cu.copy(t)
+				}
+            }
+            if BIG.comp(d,e)<0
+            {
+				w.copy(d); w.imul(4); w.norm()
+				if BIG.comp(e,w)<=0
+				{
+                    e.sub(d); e.norm()
+                    t.copy(cv)
+                    t.xtr_A(cu,cumv,cum2v)
+                    cum2v.copy(cumv)
+                    cumv.copy(cu)
+                    cu.copy(t)
+				}
+				else if e.parity()==0
+				{
+                    w.copy(d)
+                    d.copy(e); d.fshr(1)
+                    e.copy(w)
+                    t.copy(cumv)
+                    t.xtr_D()
+                    cumv.copy(cum2v); cumv.conj()
+                    cum2v.copy(t); cum2v.conj()
+                    t.copy(cv)
+                    t.xtr_D()
+                    cv.copy(cu)
+                    cu.copy(t)
+				}
+				else if d.parity()==1
+				{
+                    w.copy(e)
+                    e.copy(d)
+                    w.sub(d); w.norm()
+                    d.copy(w); d.fshr(1)
+                    t.copy(cv)
+                    t.xtr_A(cu,cumv,cum2v)
+                    cumv.conj()
+                    cum2v.copy(cu)
+                    cum2v.xtr_D()
+                    cum2v.conj()
+                    cu.copy(cv)
+                    cu.xtr_D()
+                    cv.copy(t)
+				}
+				else
+				{
+                    d.fshr(1)
+                    r.copy(cum2v); r.conj()
+                    t.copy(cumv)
+                    t.xtr_A(cu,cv,r)
+                    cum2v.copy(cumv)
+                    cum2v.xtr_D()
+                    cumv.copy(t)
+                    cu.xtr_D()
+				}
+            }
+        }
+        r.copy(cv)
+        r.xtr_A(cu,cumv,cum2v)
+        for _ in 0 ..< f2
+            {r.xtr_D()}
+        r=r.xtr_pow(d)
+        return r
+    }
+    
+    /* self/=2 */
+    mutating func div2() {
+        a.div2()
+        b.div2()
+    }
+
+    mutating func div_i() {
+        var u=FP2(a)
+        let v=FP2(b)
+        u.div_ip()
+        a.copy(v)
+        b.copy(u)
+    }   
+
+    mutating func div_2i() {
+        var u=FP2(a)
+        var v=FP2(b)
+        u.div_ip2()
+        v.add(v); v.norm()
+        a.copy(v)
+        b.copy(u) 
+    }
+
+/* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */
+/* returns true if this is QR */
+    mutating func sqrt() -> Bool {
+        if iszilch() {return true}
+
+        var aa=FP2(a)
+        var s=FP2(b)
+        var t=FP2(a)
+
+        if s.iszilch() {
+            if t.sqrt() {
+                a.copy(t)
+                b.zero()
+            } else {
+                t.div_ip()
+                _=t.sqrt()
+                b.copy(t)
+                a.zero()
+            }
+            return true
+        }
+        s.sqr()
+        a.sqr()
+        s.mul_ip()
+        s.norm()
+        aa.sub(s)
+
+        s.copy(aa)
+        if !s.sqrt() {
+            return false
+        }
+
+        aa.copy(t); aa.add(s); aa.norm(); aa.div2()
+
+        if !aa.sqrt() {
+            aa.copy(t); aa.sub(s); aa.norm(); aa.div2()
+            if !a.sqrt() {
+                return false
+            }
+        }
+        t.copy(b)
+        s.copy(aa); s.add(aa)
+        s.inverse()
+
+        t.mul(s)
+        a.copy(aa)
+        b.copy(t)
+
+        return true
+    }
+}
diff --git a/version3/swift/fp48.swift b/version3/swift/fp48.swift
new file mode 100644
index 0000000..0917643
--- /dev/null
+++ b/version3/swift/fp48.swift
@@ -0,0 +1,1071 @@
+/*
+	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.
+*/
+
+//
+//  fp48.swift
+//
+//  Created by Michael Scott on 07/07/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+/* AMCL Fp^48 functions */
+/* FP48 elements are of the form a+i.b+i^2.c */
+
+public struct FP48
+{
+    private var a:FP16
+    private var b:FP16
+    private var c:FP16
+    
+    /* reduce all components of this mod Modulus */
+    mutating func reduce()
+    {
+        a.reduce()
+        b.reduce()
+        c.reduce()
+    }
+    /* normalise all components of this */
+    mutating func norm()
+    {
+        a.norm();
+        b.norm();
+        c.norm();
+    }
+    /* Constructors */
+    init(_ d:FP16)
+    {
+        a=FP16(d)
+        b=FP16(0)
+        c=FP16(0)
+    }
+    
+    init(_ d:Int)
+    {
+        a=FP16(d)
+        b=FP16(0)
+        c=FP16(0)
+    }
+
+    init(_ d:FP16,_ e:FP16,_ f:FP16)
+    {
+        a=FP16(d)
+        b=FP16(e)
+        c=FP16(f)
+    }
+
+    init(_ x:FP48)
+    {
+        a=FP16(x.a)
+        b=FP16(x.b)
+        c=FP16(x.c)
+    }
+    /* test x==0 ? */
+    func iszilch() -> Bool
+    {
+        //reduce();
+        return a.iszilch() && b.iszilch() && c.iszilch()
+    }
+
+    mutating func cmove(_ g:FP48,_ d:Int)
+    {
+        a.cmove(g.a,d)
+        b.cmove(g.b,d)
+        c.cmove(g.c,d)
+    }
+
+    /* return 1 if b==c, no branching */
+    private static func teq(_ b:Int32,_ c:Int32) -> Int
+    {
+        var x=b^c
+        x-=1  // if x=0, x now -1
+        return Int((x>>31)&1)
+    }
+    /* Constant time select from pre-computed table */
+    mutating func select(_ g:[FP48],_ b:Int32)
+    {
+
+        let m=b>>31
+        var babs=(b^m)-m
+        
+        babs=(babs-1)/2
+    
+        cmove(g[0],FP48.teq(babs,0)) // conditional move
+        cmove(g[1],FP48.teq(babs,1))
+        cmove(g[2],FP48.teq(babs,2))
+        cmove(g[3],FP48.teq(babs,3))
+        cmove(g[4],FP48.teq(babs,4))
+        cmove(g[5],FP48.teq(babs,5))
+        cmove(g[6],FP48.teq(babs,6))
+        cmove(g[7],FP48.teq(babs,7))
+    
+        var invf=FP48(self)
+        invf.conj()
+        cmove(invf,Int(m&1))
+    }
+
+    /* test x==1 ? */
+    public func isunity() -> Bool
+    {
+        let one=FP16(1)
+        return a.equals(one) && b.iszilch() && c.iszilch()
+    }
+    /* return 1 if x==y, else 0 */
+    public func equals(_ x:FP48) -> Bool
+    {
+        return a.equals(x.a) && b.equals(x.b) && c.equals(x.c)
+    }
+
+    /* extract a from self */
+    func geta() -> FP16
+    {
+        return a
+    }
+    /* extract b */
+    func getb()  -> FP16
+    {
+        return b
+    }
+    /* extract c */
+    func getc() -> FP16
+    {
+        return c
+    }
+    /* copy self=x */
+    public mutating func copy(_ x:FP48)
+    {
+        a.copy(x.a)
+        b.copy(x.b)
+        c.copy(x.c)
+    }
+    /* set self=1 */
+    mutating func one()
+    {
+        a.one()
+        b.zero()
+        c.zero()
+    }
+    /* self=conj(self) */
+    mutating func conj()
+    {
+        a.conj()
+        b.nconj()
+        c.conj()
+    }
+
+    /* Granger-Scott Unitary Squaring */
+    mutating func usqr()
+    {
+        var A=FP16(a)
+        var B=FP16(c)
+        var C=FP16(b)
+        var D=FP16(0)
+    
+        a.sqr()
+        D.copy(a); D.add(a)
+        a.add(D)
+    
+        a.norm()
+        A.nconj()
+    
+        A.add(A)
+        a.add(A)
+        B.sqr()
+        B.times_i()
+    
+        D.copy(B); D.add(B)
+        B.add(D)
+        B.norm()
+    
+        C.sqr()
+        D.copy(C); D.add(C)
+        C.add(D)
+        C.norm()
+    
+        b.conj()
+        b.add(b)
+        c.nconj()
+    
+        c.add(c)
+        b.add(B)
+        c.add(C)
+        reduce()
+    
+    }
+
+    /* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
+    mutating func sqr()
+    {
+        var A=FP16(a)
+        var B=FP16(b)
+        var C=FP16(c)
+        var D=FP16(a)
+    
+        A.sqr()
+        B.mul(c)
+        B.add(B); B.norm()
+        C.sqr()
+        D.mul(b)
+        D.add(D)
+
+        c.add(a)
+        c.add(b); c.norm()
+        c.sqr()
+    
+        a.copy(A)
+    
+        A.add(B)
+        A.norm()
+        A.add(C)
+        A.add(D)
+        A.norm()
+    
+        A.neg()
+        B.times_i()
+        C.times_i()
+    
+        a.add(B)
+
+        b.copy(C); b.add(D)
+        c.add(A)
+    
+        norm()
+    }
+
+    /* FP48 full multiplication this=this*y */
+    mutating func mul(_ y:FP48)
+    {
+        var z0=FP16(a)
+        var z1=FP16(0)
+        var z2=FP16(b)
+        var z3=FP16(0)
+        var t0=FP16(a)
+        var t1=FP16(y.a)
+    
+        z0.mul(y.a)
+        z2.mul(y.b)
+    
+        t0.add(b)
+        t1.add(y.b)
+
+        t0.norm(); t1.norm()
+    
+        z1.copy(t0); z1.mul(t1)
+        t0.copy(b); t0.add(c)
+    
+        t1.copy(y.b); t1.add(y.c)
+
+        t0.norm(); t1.norm()
+
+        z3.copy(t0); z3.mul(t1)
+    
+        t0.copy(z0); t0.neg()
+        t1.copy(z2); t1.neg()
+    
+        z1.add(t0)
+        b.copy(z1); b.add(t1)
+    
+        z3.add(t1)
+        z2.add(t0)
+    
+        t0.copy(a); t0.add(c)
+        t1.copy(y.a); t1.add(y.c)
+
+        t0.norm(); t1.norm()
+
+        t0.mul(t1)
+        z2.add(t0)
+    
+        t0.copy(c); t0.mul(y.c)
+        t1.copy(t0); t1.neg()
+    
+        c.copy(z2); c.add(t1)
+        z3.add(t1)
+        t0.times_i()
+        b.add(t0)
+    
+        z3.norm()
+        z3.times_i()
+        a.copy(z0); a.add(z3)
+    
+        norm()
+    }
+
+    /* Special case of multiplication arises from special form of ATE pairing line function */
+    mutating func smul(_ y:FP48,_ twist:Int)
+    {
+        if twist == ECP.D_TYPE {
+            var z0=FP16(a)
+            var z2=FP16(b)
+            var z3=FP16(b)
+            var t0=FP16(0)
+            var t1=FP16(y.a)
+    
+            z0.mul(y.a)
+            z2.pmul(y.b.real())
+            b.add(a)
+            t1.adds(y.b.real())
+    
+            b.norm(); t1.norm()
+
+            b.mul(t1)
+            z3.add(c); z3.norm()
+            z3.pmul(y.b.real())
+    
+            t0.copy(z0); t0.neg()
+            t1.copy(z2); t1.neg()
+    
+            b.add(t0)
+    
+            b.add(t1)
+            z3.add(t1)
+            z2.add(t0)
+    
+            t0.copy(a); t0.add(c)
+            t0.norm(); z3.norm()
+            t0.mul(y.a)
+            c.copy(z2); c.add(t0)
+    
+            z3.times_i()
+            a.copy(z0); a.add(z3)
+        }
+        if twist == ECP.M_TYPE {
+            var z0=FP16(a)
+            var z1=FP16(0)
+            var z2=FP16(0)
+            var z3=FP16(0)
+            var t0=FP16(a)
+            var t1=FP16(0)
+        
+            z0.mul(y.a)
+            t0.add(b)
+            t0.norm()
+
+            z1.copy(t0); z1.mul(y.a)
+            t0.copy(b); t0.add(c)
+            t0.norm();
+
+            z3.copy(t0); //z3.mul(y.c);
+            z3.pmul(y.c.getb())
+            z3.times_i()
+
+            t0.copy(z0); t0.neg()
+
+            z1.add(t0)
+            b.copy(z1);
+            z2.copy(t0)
+
+            t0.copy(a); t0.add(c)
+            t1.copy(y.a); t1.add(y.c)
+
+            t0.norm()
+            t1.norm()
+    
+            t0.mul(t1)
+            z2.add(t0)
+
+            t0.copy(c)
+            
+            t0.pmul(y.c.getb())
+            t0.times_i()
+
+            t1.copy(t0); t1.neg()
+
+            c.copy(z2); c.add(t1)
+            z3.add(t1)
+            t0.times_i()
+            b.add(t0)
+            z3.norm();
+            z3.times_i()
+            a.copy(z0); a.add(z3)      
+        }
+        norm()
+    }
+    /* self=1/self */
+    mutating func inverse()
+    {
+        var f0=FP16(a)
+        var f1=FP16(b)
+        var f2=FP16(a)
+        var f3=FP16(0)
+    
+        norm()
+        f0.sqr()
+        f1.mul(c)
+        f1.times_i()
+        f0.sub(f1); f0.norm()
+    
+        f1.copy(c); f1.sqr()
+        f1.times_i()
+        f2.mul(b)
+        f1.sub(f2); f1.norm()
+    
+        f2.copy(b); f2.sqr()
+        f3.copy(a); f3.mul(c)
+        f2.sub(f3); f2.norm()
+    
+        f3.copy(b); f3.mul(f2)
+        f3.times_i()
+        a.mul(f0)
+        f3.add(a)
+        c.mul(f1)
+        c.times_i()
+    
+        f3.add(c); f3.norm()
+        f3.inverse()
+        a.copy(f0); a.mul(f3)
+        b.copy(f1); b.mul(f3)
+        c.copy(f2); c.mul(f3)
+    }
+
+    /* self=self^p using Frobenius */
+    mutating func frob(_ f:FP2,_ n:Int)
+    {
+
+        var f2=FP2(f)
+        var f3=FP2(f)
+    
+        f2.sqr()
+        f3.mul(f2)
+
+        f3.mul_ip(); f3.norm()    
+        f3.mul_ip(); f3.norm()  
+
+        for _ in 0 ..< n {
+            a.frob(f3)
+            b.frob(f3)
+            c.frob(f3)
+
+            b.qmul(f); b.times_i4(); b.times_i2()
+            c.qmul(f2); c.times_i4(); c.times_i4(); c.times_i4()
+        }        
+
+    }
+
+    /* trace function */
+    func trace() -> FP16
+    {
+        var t=FP16(0)
+        t.copy(a)
+        t.imul(3)
+        t.reduce()
+        return t
+    }
+
+    /* convert from byte array to FP48 */
+    static func fromBytes(_ w:[UInt8]) -> FP48
+    {
+        let RM=Int(BIG.MODBYTES)
+        var t=[UInt8](repeating: 0,count: RM)
+    
+        for i in 0 ..< RM {t[i]=w[i]}
+        var a=BIG.fromBytes(t)
+        for i in 0 ..< RM {t[i]=w[i+RM]}
+        var b=BIG.fromBytes(t)
+        var c=FP2(a,b)
+    
+        for i in 0 ..< RM {t[i]=w[i+2*RM]}
+        a.copy(BIG.fromBytes(t))
+        for i in 0 ..< RM {t[i]=w[i+3*RM]}
+        b.copy(BIG.fromBytes(t))
+        var d=FP2(a,b)
+    
+        var ea=FP4(c,d)
+
+        for i in 0 ..< RM {t[i]=w[i+4*RM]}
+        a.copy(BIG.fromBytes(t))
+        for i in 0 ..< RM {t[i]=w[i+5*RM]}
+        b.copy(BIG.fromBytes(t))
+        c.copy(FP2(a,b))
+    
+        for i in 0 ..< RM {t[i]=w[i+6*RM]}
+        a.copy(BIG.fromBytes(t))
+        for i in 0 ..< RM {t[i]=w[i+7*RM]}
+        b.copy(BIG.fromBytes(t))
+        d.copy(FP2(a,b))
+    
+        var eb=FP4(c,d)
+
+        var ea4=FP8(ea,eb);
+
+        for i in 0 ..< RM {t[i]=w[i+8*RM]}
+        a.copy(BIG.fromBytes(t))
+        for i in 0 ..< RM {t[i]=w[i+9*RM]}
+        b.copy(BIG.fromBytes(t))
+        c.copy(FP2(a,b))
+    
+        for i in 0 ..< RM {t[i]=w[i+10*RM]}
+        a.copy(BIG.fromBytes(t))
+        for i in 0 ..< RM {t[i]=w[i+11*RM]}
+        b.copy(BIG.fromBytes(t))
+        d.copy(FP2(a,b))
+    
+        ea.copy(FP4(c,d))
+
+        for i in 0 ..< RM {t[i]=w[i+12*RM]}
+        a.copy(BIG.fromBytes(t))
+        for i in 0 ..< RM {t[i]=w[i+13*RM]}
+        b.copy(BIG.fromBytes(t))
+        c.copy(FP2(a,b))
+    
+        for i in 0 ..< RM {t[i]=w[i+14*RM]}
+        a.copy(BIG.fromBytes(t))
+        for i in 0 ..< RM {t[i]=w[i+15*RM]}
+        b.copy(BIG.fromBytes(t))
+        d.copy(FP2(a,b))
+    
+        eb.copy(FP4(c,d))
+
+        var eb4=FP8(ea,eb);
+
+        let e=FP16(ea4,eb4)
+
+
+    
+        for i in 0 ..< RM {t[i]=w[i+16*RM]}
+        a.copy(BIG.fromBytes(t))
+        for i in 0 ..< RM {t[i]=w[i+17*RM]}
+        b.copy(BIG.fromBytes(t))
+        c.copy(FP2(a,b))
+    
+        for i in 0 ..< RM {t[i]=w[i+18*RM]}
+        a.copy(BIG.fromBytes(t))
+        for i in 0 ..< RM {t[i]=w[i+19*RM]}
+        b.copy(BIG.fromBytes(t))
+        d.copy(FP2(a,b))
+
+        ea.copy(FP4(c,d))
+
+
+        for i in 0 ..< RM {t[i]=w[i+20*RM]}
+        a.copy(BIG.fromBytes(t))
+        for i in 0 ..< RM {t[i]=w[i+21*RM]}
+        b.copy(BIG.fromBytes(t))
+        c.copy(FP2(a,b))
+    
+        for i in 0 ..< RM {t[i]=w[i+22*RM]}
+        a.copy(BIG.fromBytes(t))
+        for i in 0 ..< RM {t[i]=w[i+23*RM]}
+        b.copy(BIG.fromBytes(t))
+        d.copy(FP2(a,b))
+
+        eb.copy(FP4(c,d))
+
+        ea4.copy(FP8(ea,eb))
+
+        for i in 0 ..< RM {t[i]=w[i+24*RM]}
+        a.copy(BIG.fromBytes(t))
+        for i in 0 ..< RM {t[i]=w[i+25*RM]}
+        b.copy(BIG.fromBytes(t))
+        c.copy(FP2(a,b))
+    
+        for i in 0 ..< RM {t[i]=w[i+26*RM]}
+        a.copy(BIG.fromBytes(t))
+        for i in 0 ..< RM {t[i]=w[i+27*RM]}
+        b.copy(BIG.fromBytes(t))
+        d.copy(FP2(a,b))
+
+        ea.copy(FP4(c,d))
+
+
+        for i in 0 ..< RM {t[i]=w[i+28*RM]}
+        a.copy(BIG.fromBytes(t))
+        for i in 0 ..< RM {t[i]=w[i+29*RM]}
+        b.copy(BIG.fromBytes(t))
+        c.copy(FP2(a,b))
+    
+        for i in 0 ..< RM {t[i]=w[i+30*RM]}
+        a.copy(BIG.fromBytes(t))
+        for i in 0 ..< RM {t[i]=w[i+31*RM]}
+        b.copy(BIG.fromBytes(t))
+        d.copy(FP2(a,b))
+
+        eb.copy(FP4(c,d))
+
+        eb4.copy(FP8(ea,eb))
+
+        let f=FP16(ea4,eb4)
+    
+    
+
+        for i in 0 ..< RM {t[i]=w[i+32*RM]}
+        a.copy(BIG.fromBytes(t))
+        for i in 0 ..< RM {t[i]=w[i+33*RM]}
+        b.copy(BIG.fromBytes(t))
+        c.copy(FP2(a,b))
+    
+        for i in 0 ..< RM {t[i]=w[i+34*RM]}
+        a.copy(BIG.fromBytes(t))
+        for i in 0 ..< RM {t[i]=w[i+35*RM]}
+        b.copy(BIG.fromBytes(t))
+        d.copy(FP2(a,b))
+
+        ea.copy(FP4(c,d))
+
+    
+        for i in 0 ..< RM {t[i]=w[i+36*RM]}
+        a.copy(BIG.fromBytes(t))
+        for i in 0 ..< RM {t[i]=w[i+37*RM]}
+        b.copy(BIG.fromBytes(t))
+        c.copy(FP2(a,b))
+    
+        for i in 0 ..< RM {t[i]=w[i+38*RM]}
+        a.copy(BIG.fromBytes(t))
+        for i in 0 ..< RM {t[i]=w[i+39*RM]}
+        b.copy(BIG.fromBytes(t))
+        d.copy(FP2(a,b))
+
+        eb.copy(FP4(c,d))
+
+        ea4.copy(FP8(ea,eb))
+
+        for i in 0 ..< RM {t[i]=w[i+40*RM]}
+        a.copy(BIG.fromBytes(t))
+        for i in 0 ..< RM {t[i]=w[i+41*RM]}
+        b.copy(BIG.fromBytes(t))
+        c.copy(FP2(a,b))
+    
+        for i in 0 ..< RM {t[i]=w[i+42*RM]}
+        a.copy(BIG.fromBytes(t))
+        for i in 0 ..< RM {t[i]=w[i+43*RM]}
+        b.copy(BIG.fromBytes(t))
+        d.copy(FP2(a,b))
+
+        ea.copy(FP4(c,d))
+
+    
+        for i in 0 ..< RM {t[i]=w[i+44*RM]}
+        a.copy(BIG.fromBytes(t))
+        for i in 0 ..< RM {t[i]=w[i+45*RM]}
+        b.copy(BIG.fromBytes(t))
+        c.copy(FP2(a,b))
+    
+        for i in 0 ..< RM {t[i]=w[i+46*RM]}
+        a.copy(BIG.fromBytes(t))
+        for i in 0 ..< RM {t[i]=w[i+47*RM]}
+        b.copy(BIG.fromBytes(t))
+        d.copy(FP2(a,b))
+
+        eb.copy(FP4(c,d))
+
+        eb4.copy(FP8(ea,eb))
+
+        let g=FP16(ea4,eb4)
+    
+        return FP48(e,f,g)
+    }
+
+    /* convert this to byte array */
+    func toBytes(_ w:inout [UInt8])
+    {
+        let RM=Int(BIG.MODBYTES)
+        var t=[UInt8](repeating: 0,count: RM)
+
+        a.geta().geta().geta().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i]=t[i]}
+        a.geta().geta().geta().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+RM]=t[i]}
+        a.geta().geta().getb().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+2*RM]=t[i]}
+        a.geta().geta().getb().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+3*RM]=t[i]}
+    
+        a.geta().getb().geta().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+4*RM]=t[i]}
+        a.geta().getb().geta().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+5*RM]=t[i]}
+        a.geta().getb().getb().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+6*RM]=t[i]}
+        a.geta().getb().getb().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+7*RM]=t[i]}
+  
+        a.getb().geta().geta().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+8*RM]=t[i]}
+        a.getb().geta().geta().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+9*RM]=t[i]}
+        a.getb().geta().getb().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+10*RM]=t[i]}
+        a.getb().geta().getb().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+11*RM]=t[i]}
+    
+        a.getb().getb().geta().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+12*RM]=t[i]}
+        a.getb().getb().geta().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+13*RM]=t[i]}
+        a.getb().getb().getb().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+14*RM]=t[i]}
+        a.getb().getb().getb().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+15*RM]=t[i]}
+
+
+
+        b.geta().geta().geta().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+16*RM]=t[i]}
+        b.geta().geta().geta().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+17*RM]=t[i]}
+        b.geta().geta().getb().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+18*RM]=t[i]}
+        b.geta().geta().getb().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+19*RM]=t[i]}
+        b.geta().getb().geta().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+20*RM]=t[i]}
+        b.geta().getb().geta().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+21*RM]=t[i]}
+        b.geta().getb().getb().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+22*RM]=t[i]}
+        b.geta().getb().getb().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+23*RM]=t[i]}
+
+
+        b.getb().geta().geta().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+24*RM]=t[i]}
+        b.getb().geta().geta().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+25*RM]=t[i]}
+        b.getb().geta().getb().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+26*RM]=t[i]}
+        b.getb().geta().getb().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+27*RM]=t[i]}
+        b.getb().getb().geta().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+28*RM]=t[i]}
+        b.getb().getb().geta().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+29*RM]=t[i]}
+        b.getb().getb().getb().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+30*RM]=t[i]}
+        b.getb().getb().getb().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+31*RM]=t[i]}
+
+
+
+        c.geta().geta().geta().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+32*RM]=t[i]}
+        c.geta().geta().geta().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+33*RM]=t[i]}
+        c.geta().geta().getb().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+34*RM]=t[i]}
+        c.geta().geta().getb().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+35*RM]=t[i]}
+        c.geta().getb().geta().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+36*RM]=t[i]}
+        c.geta().getb().geta().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+37*RM]=t[i]}
+        c.geta().getb().getb().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+38*RM]=t[i]}
+        c.geta().getb().getb().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+39*RM]=t[i]}        
+
+
+        c.getb().geta().geta().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+40*RM]=t[i]}
+        c.getb().geta().geta().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+41*RM]=t[i]}
+        c.getb().geta().getb().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+42*RM]=t[i]}
+        c.getb().geta().getb().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+43*RM]=t[i]}
+        c.getb().getb().geta().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+44*RM]=t[i]}
+        c.getb().getb().geta().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+45*RM]=t[i]}
+        c.getb().getb().getb().getA().toBytes(&t)
+        for i in 0 ..< RM {w[i+46*RM]=t[i]}
+        c.getb().getb().getb().getB().toBytes(&t)
+        for i in 0 ..< RM {w[i+47*RM]=t[i]}        
+
+    }
+
+    /* convert to hex string */
+    public func toString() -> String
+    {
+        return ("["+a.toString()+","+b.toString()+","+c.toString()+"]")
+    }
+    
+    /* self=self^e */
+    /* Note this is simple square and multiply, so not side-channel safe */
+    func pow(_ e:BIG) -> FP48
+    {
+        var sf=FP48(self)
+        sf.norm()
+        
+        var e1=BIG(e)
+        e1.norm()        
+        var e3=BIG(e1)
+        e3.pmul(3)
+        e3.norm();
+
+        var w=FP48(sf)
+        let nb=e3.nbits()
+ 
+        for i in (1...nb-2).reversed()
+        {
+            w.usqr()
+            let bt=e3.bit(UInt(i))-e1.bit(UInt(i))
+            if bt == 1 {
+                w.mul(sf)
+            }
+            if bt == -1 {
+                sf.conj(); w.mul(sf); sf.conj()
+            }            
+        }
+    
+        w.reduce()
+        return w
+    }
+
+    /* constant time powering by small integer of max length bts */
+    mutating func pinpow(_ e:Int32,_ bts:Int32)
+    {
+        var R=[FP48]()
+        R.append(FP48(1))
+        R.append(FP48(self))
+
+        //for var i=bts-1;i>=0;i--
+        for i in (0...bts-1).reversed()
+        {
+            let b=Int((e>>i)&1)
+            R[1-b].mul(R[b])
+            R[b].usqr()
+        }
+        copy(R[0])
+    }
+
+    public func compow(_ e :BIG,_ r :BIG) -> FP16
+    {
+        let f=FP2(BIG(ROM.Fra),BIG(ROM.Frb))
+        let q=BIG(ROM.Modulus)       
+
+        var g1=FP48(self)
+        var g2=FP48(self)
+
+        var m=BIG(q)
+        m.mod(r)
+    
+        var a=BIG(e)
+        a.mod(m)
+    
+        var b=BIG(e)
+        b.div(m);
+    
+        var c=g1.trace()
+
+        if b.iszilch() 
+        {
+            c=c.xtr_pow(e)
+            return c
+        }
+
+        g2.frob(f,1)
+        let cp=g2.trace()
+        g1.conj()
+        g2.mul(g1)
+        let cpm1=g2.trace()
+        g2.mul(g1)
+        let cpm2=g2.trace()
+    
+        c=c.xtr_pow2(cp,cpm1,cpm2,a,b)
+
+        return c
+    }
+
+
+    /* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3.. */
+    // Bos & Costello https://eprint.iacr.org/2013/458.pdf
+    // Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
+    // Side channel attack secure 
+
+    static func pow16(_ q:[FP48],_ u:[BIG]) -> FP48
+    {
+        var g1=[FP48]()
+        var g2=[FP48]()        
+        var g3=[FP48]()
+        var g4=[FP48]()        
+
+        
+        for _ in 0 ..< 8 {
+            g1.append(FP48(0))
+            g2.append(FP48(0))       
+            g3.append(FP48(0))
+            g4.append(FP48(0))                    
+        }
+        
+        var r=FP48(0)
+        var p=FP48(0)
+        
+        var t=[BIG]()
+        for i in 0 ..< 16 {
+            t.append(BIG(u[i]))
+            t[i].norm()
+        }
+
+        var mt=BIG(0);
+        var w1=[Int8](repeating: 0,count: BIG.NLEN*Int(BIG.BASEBITS)+1)           
+        var s1=[Int8](repeating: 0,count: BIG.NLEN*Int(BIG.BASEBITS)+1)   
+        var w2=[Int8](repeating: 0,count: BIG.NLEN*Int(BIG.BASEBITS)+1)           
+        var s2=[Int8](repeating: 0,count: BIG.NLEN*Int(BIG.BASEBITS)+1)   
+        var w3=[Int8](repeating: 0,count: BIG.NLEN*Int(BIG.BASEBITS)+1)           
+        var s3=[Int8](repeating: 0,count: BIG.NLEN*Int(BIG.BASEBITS)+1)   
+        var w4=[Int8](repeating: 0,count: BIG.NLEN*Int(BIG.BASEBITS)+1)           
+        var s4=[Int8](repeating: 0,count: BIG.NLEN*Int(BIG.BASEBITS)+1)   
+
+
+// precompute table 
+        g1[0].copy(q[0])   // q[0]
+        g1[1].copy(g1[0]); g1[1].mul(q[1])   // q[0].q[1]
+        g1[2].copy(g1[0]); g1[2].mul(q[2])   // q[0].q[2]
+        g1[3].copy(g1[1]); g1[3].mul(q[2])   // q[0].q[1].q[2]
+        g1[4].copy(g1[0]); g1[4].mul(q[3])   // q[0].q[3]
+        g1[5].copy(g1[1]); g1[5].mul(q[3])   // q[0].q[1].q[3]
+        g1[6].copy(g1[2]); g1[6].mul(q[3])   // q[0].q[2].q[3]
+        g1[7].copy(g1[3]); g1[7].mul(q[3])   // q[0].q[1].q[2].q[3]
+
+// Use Frobenius
+    let f=FP2(BIG(ROM.Fra),BIG(ROM.Frb))
+    for i in 0 ..< 8  {
+        g2[i].copy(g1[i]); g2[i].frob(f,4)       
+        g3[i].copy(g2[i]); g3[i].frob(f,4)     
+        g4[i].copy(g3[i]); g4[i].frob(f,4)                     
+    }
+
+// Make it odd
+        let pb1=1-t[0].parity()
+        t[0].inc(pb1)
+        t[0].norm()  
+
+        let pb2=1-t[4].parity()
+        t[4].inc(pb2)
+        t[4].norm()          
+
+        let pb3=1-t[8].parity()
+        t[8].inc(pb3)
+        t[8].norm()  
+
+        let pb4=1-t[12].parity()
+        t[12].inc(pb4)
+        t[12].norm()    
+
+// Number of bits
+        mt.zero();
+        for i in 0 ..< 16 {
+            mt.or(t[i]); 
+        }
+
+        let nb=1+mt.nbits()
+
+// Sign pivot 
+
+        s1[nb-1]=1
+        s2[nb-1]=1
+        s3[nb-1]=1
+        s4[nb-1]=1        
+        for i in 0 ..< nb-1 {
+            t[0].fshr(1)
+            s1[i]=2*Int8(t[0].parity())-1
+            t[4].fshr(1)
+            s2[i]=2*Int8(t[4].parity())-1        
+            t[8].fshr(1)
+            s3[i]=2*Int8(t[8].parity())-1
+            t[12].fshr(1)
+            s4[i]=2*Int8(t[12].parity())-1                   
+        }
+
+// Recoded exponent
+        for i in 0 ..< nb {
+            w1[i]=0
+            var k=1
+            for j in 1 ..< 4 {
+                let bt=s1[i]*Int8(t[j].parity())
+                t[j].fshr(1)
+                t[j].dec(Int(bt>>1))
+                t[j].norm()
+                w1[i]+=bt*Int8(k)
+                k=2*k
+            }
+            w2[i]=0
+            k=1
+            for j in 5 ..< 8 {
+                let bt=s2[i]*Int8(t[j].parity())
+                t[j].fshr(1)
+                t[j].dec(Int(bt>>1))
+                t[j].norm()
+                w2[i]+=bt*Int8(k)
+                k=2*k
+            }            
+            w3[i]=0
+            k=1
+            for j in 9 ..< 12 {
+                let bt=s3[i]*Int8(t[j].parity())
+                t[j].fshr(1)
+                t[j].dec(Int(bt>>1))
+                t[j].norm()
+                w3[i]+=bt*Int8(k)
+                k=2*k
+            }            
+            w4[i]=0
+            k=1
+            for j in 13 ..< 16 {
+                let bt=s4[i]*Int8(t[j].parity())
+                t[j].fshr(1)
+                t[j].dec(Int(bt>>1))
+                t[j].norm()
+                w4[i]+=bt*Int8(k)
+                k=2*k
+            }                                    
+        }   
+
+// Main loop
+        p.select(g1,Int32(2*w1[nb-1]+1))
+        r.select(g2,Int32(2*w2[nb-1]+1))
+        p.mul(r)        
+        r.select(g3,Int32(2*w3[nb-1]+1))
+        p.mul(r)    
+        r.select(g4,Int32(2*w4[nb-1]+1))
+        p.mul(r)                    
+        for i in (0 ..< nb-1).reversed() {
+            p.usqr()
+            r.select(g1,Int32(2*w1[i]+s1[i]))
+            p.mul(r)
+            r.select(g2,Int32(2*w2[i]+s2[i]))
+            p.mul(r)            
+            r.select(g3,Int32(2*w3[i]+s3[i]))
+            p.mul(r)
+            r.select(g4,Int32(2*w4[i]+s4[i]))
+            p.mul(r)                    
+        }      
+
+// apply correction
+        r.copy(q[0]); r.conj()   
+        r.mul(p)
+        p.cmove(r,pb1)
+
+        r.copy(q[4]); r.conj()   
+        r.mul(p)
+        p.cmove(r,pb2)
+
+        r.copy(q[8]); r.conj()   
+        r.mul(p)
+        p.cmove(r,pb3)
+
+        r.copy(q[12]); r.conj()   
+        r.mul(p)
+        p.cmove(r,pb4)
+
+        p.reduce()
+        return p
+    }
+
+}
+
diff --git a/version3/swift/fp8.swift b/version3/swift/fp8.swift
new file mode 100644
index 0000000..552cb4b
--- /dev/null
+++ b/version3/swift/fp8.swift
@@ -0,0 +1,658 @@
+/*
+	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.
+*/
+
+//
+//  fp8.swift
+//
+//  Created by Michael Scott on 07/07/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+/* Finite Field arithmetic  Fp^8 functions */
+
+/* FP8 elements are of the form a+ib, where i is sqrt(sqrt(-1+sqrt(-1)))  */
+
+public struct FP8 {
+    private var a:FP4
+    private var b:FP4
+
+    /* constructors */
+    init(_ c:Int)
+    {
+        a=FP4(c)
+        b=FP4(0)
+    }
+    
+    init(_ x:FP8)
+    {
+        a=FP4(x.a)
+        b=FP4(x.b)
+    }
+    
+    init(_ c:FP4,_ d:FP4)
+    {
+        a=FP4(c)
+        b=FP4(d)
+    }
+    
+    init(_ c:FP4)
+    {
+        a=FP4(c)
+        b=FP4(0)
+    }
+    /* reduce all components of this mod Modulus */
+    mutating func reduce()
+    {
+        a.reduce()
+        b.reduce()
+    }
+    /* normalise all components of this mod Modulus */
+    mutating func norm()
+    {
+        a.norm()
+        b.norm()
+    }
+
+    /* test this==0 ? */
+    func iszilch() -> Bool
+    {
+        //reduce()
+        return a.iszilch() && b.iszilch()
+    }
+
+    mutating func cmove(_ g:FP8,_ d:Int)
+    {
+        a.cmove(g.a,d)
+        b.cmove(g.b,d)
+    }
+
+
+    /* test this==1 ? */
+    func isunity() -> Bool
+    {
+    let one=FP4(1);
+    return a.equals(one) && b.iszilch()
+    }
+    
+    /* test is w real? That is in a+ib test b is zero */
+    func isreal() -> Bool
+    {
+        return b.iszilch();
+    }
+    /* extract real part a */
+    func real() -> FP4
+    {
+        return a;
+    }
+    
+    func geta() -> FP4
+    {
+        return a;
+    }
+    /* extract imaginary part b */
+    func getb() -> FP4
+    {
+    return b;
+    }
+
+    /* test self=x? */
+    func equals(_ x:FP8) -> Bool
+    {
+        return a.equals(x.a) && b.equals(x.b)
+    }
+    /* copy self=x */
+    mutating func copy(_ x:FP8)
+    {
+        a.copy(x.a)
+        b.copy(x.b)
+    }
+    /* set this=0 */
+    mutating func zero()
+    {
+        a.zero()
+        b.zero()
+    }
+    /* set this=1 */
+    mutating func one()
+    {
+        a.one()
+        b.zero()
+    }
+    /* set self=-self */
+    mutating func neg()
+    {
+        norm()
+        var m=FP4(a)
+        var t=FP4(0)
+        m.add(b)
+        m.neg()
+    //    m.norm()
+        t.copy(m); t.add(b)
+        b.copy(m)
+        b.add(a)
+        a.copy(t)
+        norm()
+    }
+    /* self=conjugate(self) */
+    mutating func conj()
+    {
+        b.neg(); norm()
+    }
+    /* this=-conjugate(this) */
+    mutating func nconj()
+    {
+        a.neg(); norm()
+    }
+
+    mutating func adds(_ x: FP4)
+    {
+        a.add(x)
+    }
+    /* self+=x */
+    mutating func add(_ x:FP8)
+    {
+        a.add(x.a)
+        b.add(x.b)
+    }
+    /* self-=x */
+    mutating func sub(_ x:FP8)
+    {
+        var m=FP8(x)
+        m.neg()
+        add(m)
+    }
+
+    /* self-=x */
+    mutating func rsub(_ x: FP8) {
+        neg()
+        add(x)
+    }    
+
+    /* self*=s where s is FP4 */
+    mutating func pmul(_ s:FP4)
+    {
+        a.mul(s)
+        b.mul(s)
+    }
+
+    /* self*=s where s is FP2 */
+    mutating func qmul(_ s:FP2) {
+        a.pmul(s)
+        b.pmul(s)
+    }
+
+    /* self*=s where s is FP */
+    mutating func tmul(_ s:FP) {
+        a.qmul(s)
+        b.qmul(s)
+    }
+
+    /* self*=c where c is int */
+    mutating func imul(_ c:Int)
+    {
+        a.imul(c)
+        b.imul(c)
+    }
+
+    /* self*=self */
+    mutating func sqr()
+    {
+//        norm();
+    
+        var t1=FP4(a)
+        var t2=FP4(b)
+        var t3=FP4(a)
+    
+        t3.mul(b)
+        t1.add(b)
+        t2.times_i()
+    
+        t2.add(a)
+
+        t1.norm(); t2.norm()
+        a.copy(t1)
+    
+        a.mul(t2)
+    
+        t2.copy(t3)
+        t2.times_i()
+        t2.add(t3); t2.norm()
+
+        t2.neg()
+        a.add(t2)
+    
+        b.copy(t3)
+        b.add(t3)
+    
+        norm()
+    }
+
+    /* self*=y */
+    mutating func mul(_ y:FP8)
+    {
+    //    norm();
+    
+        var t1=FP4(a)
+        var t2=FP4(b)
+        var t3=FP4(0)
+        var t4=FP4(b)
+    
+        t1.mul(y.a)
+        t2.mul(y.b)
+        t3.copy(y.b)
+        t3.add(y.a)
+        t4.add(a)
+
+        t3.norm(); t4.norm()
+    
+        t4.mul(t3)
+
+        t3.copy(t1)
+        t3.neg()
+        t4.add(t3)
+        t4.norm()
+
+        t3.copy(t2)
+        t3.neg()
+        b.copy(t4)
+        b.add(t3)
+
+        t2.times_i()
+        a.copy(t2)
+        a.add(t1)
+
+        norm();
+    }
+    /* convert this to hex string */
+    func toString() -> String
+    {
+        return ("["+a.toString()+","+b.toString()+"]")
+    }
+
+   func toRawString() -> String
+    {
+        return ("["+a.toRawString()+","+b.toRawString()+"]")
+    }
+    /* self=1/self */
+    mutating func inverse()
+    {
+        norm();
+    
+        var t1=FP4(a)
+        var t2=FP4(b)
+    
+        t1.sqr()
+        t2.sqr()
+        t2.times_i(); t2.norm()
+        t1.sub(t2); t1.norm()
+        t1.inverse()
+        a.mul(t1)
+        t1.neg(); t1.norm()
+        b.mul(t1)
+    }
+
+    /* self*=i where i = sqrt(-1+sqrt(-1)) */
+    mutating func times_i()
+    {
+        var s=FP4(b)
+        let t=FP4(a)
+        s.times_i()
+        a.copy(s)
+        b.copy(t)
+        norm()
+    }
+
+    mutating func times_i2() {
+        a.times_i()
+        b.times_i()
+    }    
+
+    /* self=self^p using Frobenius */
+    mutating func frob(_ f:FP2)
+    {
+        var ff=FP2(f); ff.sqr(); ff.mul_ip(); ff.norm()
+
+        a.frob(ff)
+        b.frob(ff)
+        b.pmul(f)
+        b.times_i()
+    }
+
+    /* self=self^e */
+    func pow(_ e:BIG) -> FP8
+    {
+        
+        var w=FP8(self)
+        w.norm()
+        var z=BIG(e)
+        var r=FP8(1)
+        z.norm()
+        while (true)
+        {
+            let bt=z.parity()
+            z.fshr(1)
+            if bt==1 {r.mul(w)}
+            if z.iszilch() {break}
+            w.sqr()
+        }
+        r.reduce()
+        return r
+    }
+
+    /* XTR xtr_a function */
+    mutating func xtr_A(_ w:FP8,_ y:FP8,_ z:FP8)
+    {
+        var r=FP8(w)
+        var t=FP8(w)
+        r.sub(y); r.norm()
+        r.pmul(a)
+        t.add(y); t.norm()
+        t.pmul(b)
+        t.times_i()
+    
+        copy(r)
+        add(t)
+        add(z)
+    
+        norm()
+    }
+    /* XTR xtr_d function */
+    mutating func xtr_D()
+    {
+        var w=FP8(self)
+        sqr(); w.conj()
+        w.add(w); w.norm();
+        sub(w)
+        reduce()
+    }
+    /* r=x^n using XTR method on traces of FP24s */
+    func xtr_pow(_ n:BIG) -> FP8
+    {
+        var a=FP8(3)
+        var b=FP8(self)
+        var c=FP8(b)
+        c.xtr_D()
+        var t=FP8(0)
+        var r=FP8(0)
+        var sf=FP8(self)
+    
+        //n.norm();
+        let par=n.parity()
+        var v=BIG(n); v.norm(); v.fshr(1)
+        if par==0 {v.dec(1); v.norm()}
+    
+        let nb=v.nbits()
+        //for i in (0...nb-1).reverse()
+        var i=nb-1
+        //for var i=nb-1;i>=0;i--
+        while i>=0
+        {
+            if (v.bit(UInt(i)) != 1)
+            {
+                t.copy(b)
+                sf.conj()
+                c.conj()
+                b.xtr_A(a,sf,c)
+                sf.conj()
+                c.copy(t)
+                c.xtr_D()
+                a.xtr_D()
+            }
+            else
+            {
+                t.copy(a); t.conj()
+                a.copy(b)
+                a.xtr_D()
+                b.xtr_A(c,sf,t)
+                c.xtr_D()
+            }
+            i-=1
+        }
+        if par==0 {r.copy(c)}
+        else {r.copy(b)}
+        r.reduce()
+        return r
+    }
+    
+    /* r=ck^a.cl^n using XTR double exponentiation method on traces of FP24s. See Stam thesis. */
+    func xtr_pow2(_ ck:FP8,_ ckml:FP8,_ ckm2l:FP8,_ a:BIG,_ b:BIG) -> FP8
+    {
+ 
+        var e=BIG(a)
+        var d=BIG(b)
+        e.norm(); d.norm()
+               
+        var w=BIG(0)
+    
+        var cu=FP8(ck)  // can probably be passed in w/o copying
+        var cv=FP8(self)
+        var cumv=FP8(ckml)
+        var cum2v=FP8(ckm2l)
+        var r=FP8(0)
+        var t=FP8(0)
+    
+        var f2:Int=0
+        while d.parity()==0 && e.parity()==0
+        {
+            d.fshr(1);
+            e.fshr(1);
+            f2 += 1;
+        }
+    
+        while (BIG.comp(d,e) != 0)
+        {
+            if BIG.comp(d,e)>0
+            {
+                w.copy(e); w.imul(4); w.norm()
+                if BIG.comp(d,w)<=0
+                {
+                    w.copy(d); d.copy(e)
+                    e.rsub(w); e.norm()
+    
+                    t.copy(cv)
+                    t.xtr_A(cu,cumv,cum2v)
+                    cum2v.copy(cumv)
+                    cum2v.conj()
+                    cumv.copy(cv)
+                    cv.copy(cu)
+                    cu.copy(t)
+    
+                }
+                else if d.parity()==0
+                {
+                    d.fshr(1)
+                    r.copy(cum2v); r.conj()
+                    t.copy(cumv)
+                    t.xtr_A(cu,cv,r)
+                    cum2v.copy(cumv)
+                    cum2v.xtr_D()
+                    cumv.copy(t)
+                    cu.xtr_D()
+                }
+                else if e.parity()==1
+                {
+                    d.sub(e); d.norm()
+                    d.fshr(1)
+                    t.copy(cv)
+                    t.xtr_A(cu,cumv,cum2v)
+                    cu.xtr_D()
+                    cum2v.copy(cv)
+                    cum2v.xtr_D()
+                    cum2v.conj()
+                    cv.copy(t)
+                }
+                else
+                {
+                    w.copy(d)
+                    d.copy(e); d.fshr(1)
+                    e.copy(w)
+                    t.copy(cumv)
+                    t.xtr_D()
+                    cumv.copy(cum2v); cumv.conj()
+                    cum2v.copy(t); cum2v.conj()
+                    t.copy(cv)
+                    t.xtr_D()
+                    cv.copy(cu)
+                    cu.copy(t)
+                }
+            }
+            if BIG.comp(d,e)<0
+            {
+                w.copy(d); w.imul(4); w.norm()
+                if BIG.comp(e,w)<=0
+                {
+                    e.sub(d); e.norm()
+                    t.copy(cv)
+                    t.xtr_A(cu,cumv,cum2v)
+                    cum2v.copy(cumv)
+                    cumv.copy(cu)
+                    cu.copy(t)
+                }
+                else if e.parity()==0
+                {
+                    w.copy(d)
+                    d.copy(e); d.fshr(1)
+                    e.copy(w)
+                    t.copy(cumv)
+                    t.xtr_D()
+                    cumv.copy(cum2v); cumv.conj()
+                    cum2v.copy(t); cum2v.conj()
+                    t.copy(cv)
+                    t.xtr_D()
+                    cv.copy(cu)
+                    cu.copy(t)
+                }
+                else if d.parity()==1
+                {
+                    w.copy(e)
+                    e.copy(d)
+                    w.sub(d); w.norm()
+                    d.copy(w); d.fshr(1)
+                    t.copy(cv)
+                    t.xtr_A(cu,cumv,cum2v)
+                    cumv.conj()
+                    cum2v.copy(cu)
+                    cum2v.xtr_D()
+                    cum2v.conj()
+                    cu.copy(cv)
+                    cu.xtr_D()
+                    cv.copy(t)
+                }
+                else
+                {
+                    d.fshr(1)
+                    r.copy(cum2v); r.conj()
+                    t.copy(cumv)
+                    t.xtr_A(cu,cv,r)
+                    cum2v.copy(cumv)
+                    cum2v.xtr_D()
+                    cumv.copy(t)
+                    cu.xtr_D()
+                }
+            }
+        }
+        r.copy(cv)
+        r.xtr_A(cu,cumv,cum2v)
+        for _ in 0 ..< f2
+            {r.xtr_D()}
+        r=r.xtr_pow(d)
+        return r
+    }
+    
+
+    /* self/=2 */
+    mutating func div2() {
+        a.div2()
+        b.div2()
+    }
+
+    mutating func div_i() {
+        var u=FP4(a)
+        let v=FP4(b)
+        u.div_i()
+        a.copy(v)
+        b.copy(u)
+    }   
+
+    mutating func div_i2() {
+        a.div_i()
+        b.div_i()
+    }
+
+    mutating func div_2i() {
+        var u=FP4(a)
+        var v=FP4(b)
+        u.div_2i()
+        v.add(v); v.norm()
+        a.copy(v)
+        b.copy(u) 
+    }
+
+/* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */
+/* returns true if this is QR */
+    mutating func sqrt() -> Bool {
+        if iszilch() {return true}
+
+        var aa=FP4(a)
+        var s=FP4(b)
+        var t=FP4(a)
+
+        if s.iszilch() {
+            if t.sqrt() {
+                a.copy(t)
+                b.zero()
+            } else {
+                t.div_i()
+                _=t.sqrt()
+                b.copy(t)
+                a.zero()
+            }
+            return true
+        }
+        s.sqr()
+        a.sqr()
+        s.times_i()
+        s.norm()
+        aa.sub(s)
+
+        s.copy(aa)
+        if !s.sqrt() {
+            return false
+        }
+
+        aa.copy(t); aa.add(s); aa.norm(); aa.div2()
+
+        if !aa.sqrt() {
+            aa.copy(t); aa.sub(s); aa.norm(); aa.div2()
+            if !a.sqrt() {
+                return false
+            }
+        }
+        t.copy(b)
+        s.copy(aa); s.add(aa)
+        s.inverse()
+
+        t.mul(s)
+        a.copy(aa)
+        b.copy(t)
+
+        return true
+    }
+
+}
\ No newline at end of file
diff --git a/version3/swift/gcm.swift b/version3/swift/gcm.swift
new file mode 100644
index 0000000..e29001d
--- /dev/null
+++ b/version3/swift/gcm.swift
@@ -0,0 +1,326 @@
+/*
+	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.
+*/
+
+//
+//  gcm.swift
+//
+//  Created by Michael Scott on 23/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+import Foundation
+
+/*
+* Implementation of the AES-GCM Encryption/Authentication
+*
+* Some restrictions..
+* 1. Only for use with AES
+* 2. Returned tag is always 128-bits. Truncate at your own risk.
+* 3. The order of function calls must follow some rules
+*
+* Typical sequence of calls..
+* 1. call GCM_init
+* 2. call GCM_add_header any number of times, as long as length of header is multiple of 16 bytes (block size)
+* 3. call GCM_add_header one last time with any length of header
+* 4. call GCM_add_cipher any number of times, as long as length of cipher/plaintext is multiple of 16 bytes
+* 5. call GCM_add_cipher one last time with any length of cipher/plaintext
+* 6. call GCM_finish to extract the tag.
+*
+* See http://www.mindspring.com/~dmcgrew/gcm-nist-6.pdf
+*/
+
+struct GCM {
+    static let NB:Int=4
+    static let GCM_ACCEPTING_HEADER:Int=0
+    static let GCM_ACCEPTING_CIPHER:Int=1
+    static let GCM_NOT_ACCEPTING_MORE:Int=2
+    static let GCM_FINISHED:Int=3
+    static let GCM_ENCRYPTING:Int=0
+    static let GCM_DECRYPTING:Int=1
+    
+    private var table=[[UInt32]](repeating: [UInt32](repeating: 0,count: 4),count: 128) /* 2k bytes */
+    private var stateX=[UInt8](repeating: 0,count: 16)
+    private var Y_0=[UInt8](repeating: 0,count: 16)
+    
+    private var counter:Int=0
+    private var lenA=[UInt32](repeating: 0,count: 2)
+    private var lenC=[UInt32](repeating: 0,count: 2)
+    private var status:Int=0
+    private var a=AES()
+    
+    private static func pack(_ b: [UInt8]) -> UInt32
+    { /* pack bytes into a 32-bit Word */
+        var r=((UInt32(b[0])&0xff)<<24)|((UInt32(b[1])&0xff)<<16)
+        r = r|((UInt32(b[2])&0xff)<<8)|(UInt32(b[3])&0xff)
+        return r
+    }
+    
+    private static func unpack(_ a: UInt32) -> [UInt8]
+    { /* unpack bytes from a word */
+        let b:[UInt8]=[UInt8((a>>24)&0xff),UInt8((a>>16)&0xff),UInt8((a>>8)&0xff),UInt8(a&0xff)];
+        return b
+    }
+    
+    private mutating func precompute(_ H: [UInt8])
+    {
+        var b=[UInt8](repeating: 0,count: 4)
+        var j=0
+        for i in 0 ..< GCM.NB
+        {
+            b[0]=H[j]; b[1]=H[j+1]; b[2]=H[j+2]; b[3]=H[j+3];
+            table[0][i]=GCM.pack(b);
+            j+=4
+        }
+        for i in 1 ..< 128
+        {
+            var c:UInt32=0
+            for j in 0 ..< GCM.NB {table[i][j]=c|(table[i-1][j])>>1; c=table[i-1][j]<<31;}
+            if c != 0  {table[i][0]^=0xE1000000} /* irreducible polynomial */
+        }
+    }
+ 
+    private mutating func gf2mul()
+    { /* gf2m mul - Z=H*X mod 2^128 */
+        var P=[UInt32](repeating: 0,count: 4)
+    
+        for i in 0 ..< 4 {P[i]=0}
+        var j=8; var m=0;
+        for i in 0 ..< 128
+        {
+            j-=1
+            var c=UInt32((stateX[m]>>UInt8(j))&1); c = ( ~c ) + 1
+            for k in 0 ..< GCM.NB {P[k]^=(table[i][k] & c)}
+            if (j==0)
+            {
+		j=8; m += 1;
+                if (m==16) {break}
+            }
+        }
+        j=0
+        for i in 0 ..< GCM.NB
+        {
+            var b=GCM.unpack(P[i])
+            stateX[j]=b[0]; stateX[j+1]=b[1]; stateX[j+2]=b[2]; stateX[j+3]=b[3];
+            j+=4
+        }
+    }
+    private mutating func wrap()
+    { /* Finish off GHASH */
+        var F=[UInt32](repeating: 0,count: 4)
+        var L=[UInt8](repeating: 0,count: 16)
+    
+    /* convert lengths from bytes to bits */
+        F[0]=(lenA[0]<<3)|(lenA[1]&0xE0000000)>>29
+        F[1]=lenA[1]<<3;
+        F[2]=(lenC[0]<<3)|(lenC[1]&0xE0000000)>>29
+        F[3]=lenC[1]<<3;
+        var j=0
+        for i in 0 ..< GCM.NB
+        {
+            var b=GCM.unpack(F[i]);
+            L[j]=b[0]; L[j+1]=b[1]; L[j+2]=b[2]; L[j+3]=b[3]
+            j+=4
+        }
+        for i in 0 ..< 16 {stateX[i]^=L[i]}
+        gf2mul()
+    }
+    
+    private mutating func ghash(_ plain: [UInt8],_ len: Int) -> Bool
+    {
+    //    var B=[UInt8](count:16,repeatedValue:0)
+    
+        if status==GCM.GCM_ACCEPTING_HEADER {status=GCM.GCM_ACCEPTING_CIPHER}
+        if (status != GCM.GCM_ACCEPTING_CIPHER) {return false}
+        
+        var j=0;
+        while (j<len)
+        {
+            for i in 0 ..< 16
+            {
+				stateX[i]^=plain[j];
+                j+=1;
+                lenC[1]+=1; if lenC[1]==0 {lenC[0]+=1}
+                if j>=len {break;}
+            }
+            gf2mul();
+        }
+        if len%16 != 0 {status=GCM.GCM_NOT_ACCEPTING_MORE}
+        return true;
+    }
+    
+    /* Initialize GCM mode */
+    mutating func init_it(_ key: [UInt8],_ niv: Int,_ iv: [UInt8])
+    { /* iv size niv is usually 12 bytes (96 bits). AES key size nk can be 16,24 or 32 bytes */
+        var H=[UInt8](repeating: 0,count: 16)
+        
+        for i in 0 ..< 16 {H[i]=0; stateX[i]=0}
+        
+        a.init_it(AES.ECB,key,iv)
+        a.ecb_encrypt(&H);    /* E(K,0) */
+        precompute(H)
+        
+        lenA[0]=0;lenC[0]=0;lenA[1]=0;lenC[1]=0;
+        if (niv==12)
+        {
+            for i in 0 ..< 12 {a.f[i]=iv[i]}
+            var b=GCM.unpack(UInt32(1))
+            a.f[12]=b[0]; a.f[13]=b[1]; a.f[14]=b[2]; a.f[15]=b[3];  /* initialise IV */
+            for i in 0 ..< 16 {Y_0[i]=a.f[i]}
+        }
+        else
+        {
+            status=GCM.GCM_ACCEPTING_CIPHER;
+            _ = ghash(iv,niv) /* GHASH(H,0,IV) */
+            wrap()
+            for i in 0 ..< 16 {a.f[i]=stateX[i];Y_0[i]=a.f[i];stateX[i]=0}
+            lenA[0]=0;lenC[0]=0;lenA[1]=0;lenC[1]=0;
+        }
+        status=GCM.GCM_ACCEPTING_HEADER;
+    }
+    
+    /* Add Header data - included but not encrypted */
+    mutating func add_header(_ header: [UInt8],_ len: Int) -> Bool
+    { /* Add some header. Won't be encrypted, but will be authenticated. len is length of header */
+        if status != GCM.GCM_ACCEPTING_HEADER {return false}
+    
+        var j=0
+        while (j<len)
+        {
+            for i in 0 ..< 16
+            {
+				stateX[i]^=header[j];
+                j+=1;
+                lenA[1]+=1; if lenA[1]==0 {lenA[0]+=1}
+                if j>=len {break}
+            }
+            gf2mul();
+        }
+        if len%16 != 0 {status=GCM.GCM_ACCEPTING_CIPHER}
+        return true;
+    }
+    /* Add Plaintext - included and encrypted */
+    mutating func add_plain(_ plain: [UInt8],_ len: Int) -> [UInt8]
+    {
+        var B=[UInt8](repeating: 0,count: 16)
+        var b=[UInt8](repeating: 0,count: 4)
+        
+        var cipher=[UInt8](repeating: 0,count: len)
+        var counter:UInt32=0
+        if status == GCM.GCM_ACCEPTING_HEADER {status=GCM.GCM_ACCEPTING_CIPHER}
+        if status != GCM.GCM_ACCEPTING_CIPHER {return [UInt8]()}
+        
+        var j=0
+        while (j<len)
+        {
+    
+            b[0]=a.f[12]; b[1]=a.f[13]; b[2]=a.f[14]; b[3]=a.f[15];
+            counter=GCM.pack(b);
+            counter+=1;
+            b=GCM.unpack(counter);
+            a.f[12]=b[0]; a.f[13]=b[1]; a.f[14]=b[2]; a.f[15]=b[3]; /* increment counter */
+            for i in 0 ..< 16 {B[i]=a.f[i]}
+            a.ecb_encrypt(&B);        /* encrypt it  */
+    
+            for i in 0 ..< 16
+            {
+		cipher[j]=(plain[j]^B[i]);
+		stateX[i]^=cipher[j];
+                j+=1;
+                lenC[1]+=1; if lenC[1]==0 {lenC[0]+=1}
+                if j>=len {break}
+            }
+            gf2mul();
+        }
+        if len%16 != 0 {status=GCM.GCM_NOT_ACCEPTING_MORE}
+        return cipher;
+    }
+    /* Add Ciphertext - decrypts to plaintext */
+    mutating func add_cipher(_ cipher: [UInt8],_ len: Int) -> [UInt8]
+    {
+        var B=[UInt8](repeating: 0,count: 16)
+        var b=[UInt8](repeating: 0,count: 4)
+        
+        var plain=[UInt8](repeating: 0,count: len)
+        var counter:UInt32=0
+        
+        if status==GCM.GCM_ACCEPTING_HEADER {status=GCM.GCM_ACCEPTING_CIPHER}
+        if status != GCM.GCM_ACCEPTING_CIPHER {return [UInt8]()}
+    
+        var j=0
+        while (j<len)
+        {
+    
+            b[0]=a.f[12]; b[1]=a.f[13]; b[2]=a.f[14]; b[3]=a.f[15];
+            counter=GCM.pack(b);
+            counter+=1;
+            b=GCM.unpack(counter);
+            a.f[12]=b[0]; a.f[13]=b[1]; a.f[14]=b[2]; a.f[15]=b[3]; /* increment counter */
+            for i in 0 ..< 16 {B[i]=a.f[i]}
+            a.ecb_encrypt(&B);        /* encrypt it  */
+            for i in 0 ..< 16
+            {
+                let oc=cipher[j]
+                plain[j]=(cipher[j]^B[i]);
+                stateX[i]^=oc;
+                j+=1;
+                lenC[1]+=1; if lenC[1]==0 {lenC[0]+=1}
+                if j>=len {break}
+            }
+            gf2mul()
+        }
+        if len%16 != 0 {status=GCM.GCM_NOT_ACCEPTING_MORE}
+        return plain;
+    }
+    
+    /* Finish and extract Tag */
+    mutating func finish(_ extract: Bool) -> [UInt8]
+    { /* Finish off GHASH and extract tag (MAC) */
+        var tag=[UInt8](repeating: 0,count: 16)
+    
+        wrap();
+        /* extract tag */
+        if (extract)
+        {
+            a.ecb_encrypt(&Y_0);        /* E(K,Y0) */
+            for i in 0 ..< 16 {Y_0[i]^=stateX[i]}
+            for i in 0 ..< 16 {tag[i]=Y_0[i];Y_0[i]=0;stateX[i]=0;}
+        }
+        status=GCM.GCM_FINISHED;
+        a.end();
+        return tag;
+    }
+    
+    static func hex2bytes(_ s: String) -> [UInt8]
+    {
+        var array=Array(arrayLiteral: s)
+        let len=array.count;
+        var data=[UInt8](repeating: 0,count: len/2)
+
+        var i=0
+        while (i<len)
+        {
+            data[i / 2] = UInt8(strtoul(String(array[i]),nil,16)<<4)+UInt8(strtoul(String(array[i+1]),nil,16))
+            i+=2
+        }
+        return data;
+    }
+    
+    
+}
+
diff --git a/version3/swift/hash256.swift b/version3/swift/hash256.swift
new file mode 100644
index 0000000..eb1ca92
--- /dev/null
+++ b/version3/swift/hash256.swift
@@ -0,0 +1,188 @@
+/*
+	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.
+*/
+
+//
+//  hash256.swift - Implementation of SHA-256
+//
+//  Created by Michael Scott on 17/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//  SHA256 Implementation
+//
+
+public struct HASH256{
+
+    private var length=[UInt32](repeating: 0,count: 2)
+    private var h=[UInt32](repeating: 0,count: 8)
+    private var w=[UInt32](repeating: 0,count: 64)
+    static let H0:UInt32=0x6A09E667
+    static let H1:UInt32=0xBB67AE85
+    static let H2:UInt32=0x3C6EF372
+    static let H3:UInt32=0xA54FF53A
+    static let H4:UInt32=0x510E527F
+    static let H5:UInt32=0x9B05688C
+    static let H6:UInt32=0x1F83D9AB
+    static let H7:UInt32=0x5BE0CD19
+    
+    static let len:Int=32
+    
+    static let K:[UInt32]=[
+    0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,
+    0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,
+    0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,
+    0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,
+    0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
+    0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070,
+    0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,
+    0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2]
+    
+    
+    private static func S(_ n: UInt32,_ x: UInt32) -> UInt32
+    {
+        return ((x>>n)|(x<<(32-n)))
+    }
+
+    private static func R(_ n: UInt32,_ x: UInt32) -> UInt32
+    {
+        return (x>>n)
+    }
+    
+    private static func Ch(_ x: UInt32,_ y: UInt32,_ z:UInt32) -> UInt32
+    {
+        return ((x&y)^(~(x)&z))
+    }
+    
+    private static func Maj(_ x: UInt32,_ y: UInt32,_ z:UInt32) -> UInt32
+    {
+        return ((x&y)^(x&z)^(y&z))
+    }
+    
+    private static func Sig0(_ x: UInt32) -> UInt32
+    {
+        return (S(2,x)^S(13,x)^S(22,x))
+    }
+    
+    private static func Sig1(_ x: UInt32) -> UInt32
+    {
+        return (S(6,x)^S(11,x)^S(25,x))
+    }
+    
+    private static func theta0(_ x: UInt32) -> UInt32
+    {
+        return (S(7,x)^S(18,x)^R(3,x))
+    }
+    
+    private static func theta1(_ x: UInt32) -> UInt32
+    {
+        return (S(17,x)^S(19,x)^R(10,x))
+    }
+ 
+    private mutating func transform()
+    { /* basic transformation step */
+        var a,b,c,d,e,f,g,hh,t1,t2 :UInt32
+        for j in 16 ..< 64
+        {
+            w[j]=HASH256.theta1(w[j-2])&+w[j-7]&+HASH256.theta0(w[j-15])&+w[j-16]
+        }
+        a=h[0]; b=h[1]; c=h[2]; d=h[3]
+        e=h[4]; f=h[5]; g=h[6]; hh=h[7]
+    
+        for j in 0 ..< 64
+        { /* 64 times - mush it up */
+            t1=hh&+HASH256.Sig1(e)&+HASH256.Ch(e,f,g)&+HASH256.K[j]&+w[j]
+            t2=HASH256.Sig0(a)&+HASH256.Maj(a,b,c)
+            hh=g; g=f; f=e;
+            e=d&+t1;
+            d=c;
+            c=b;
+            b=a;
+            a=t1&+t2;
+        }
+        h[0]=h[0]&+a; h[1]=h[1]&+b; h[2]=h[2]&+c; h[3]=h[3]&+d
+        h[4]=h[4]&+e; h[5]=h[5]&+f; h[6]=h[6]&+g; h[7]=h[7]&+hh;
+    }
+    
+    /* Re-Initialise Hash function */
+    mutating func init_it()
+    { /* initialise */
+        for i in 0 ..< 64 {w[i]=0}
+        length[0]=0; length[1]=0
+        h[0]=HASH256.H0;
+        h[1]=HASH256.H1;
+        h[2]=HASH256.H2;
+        h[3]=HASH256.H3;
+        h[4]=HASH256.H4;
+        h[5]=HASH256.H5;
+        h[6]=HASH256.H6;
+        h[7]=HASH256.H7;
+    }
+    
+    public init()
+    {
+        init_it()
+    }
+    
+    /* process a single byte */
+    public mutating func process(_ byt: UInt8)
+    { /* process the next message byte */
+        let cnt=Int((length[0]/32)%16)
+        w[cnt]<<=8;
+        w[cnt]|=(UInt32(byt)&0xFF);
+        length[0]+=8;
+        if (length[0]==0) { length[1] += 1; length[0]=0 }
+        if ((length[0]%512)==0) {transform()}
+    }
+    
+    /* process an array of bytes */
+    public mutating func process_array(_ b: [UInt8])
+    {
+        for i in 0 ..< b.count {process((b[i]))}
+    }
+    
+    /* process a 32-bit integer */
+    public mutating func process_num(_ n:Int32)
+    {
+        process(UInt8((n>>24)&0xff))
+        process(UInt8((n>>16)&0xff))
+        process(UInt8((n>>8)&0xff))
+        process(UInt8(n&0xff))
+    }
+
+    /* Generate 32-byte Hash */
+    public mutating func hash() -> [UInt8]
+    { /* pad message and finish - supply digest */
+        var digest=[UInt8](repeating: 0,count: 32)
+        
+        let len0=length[0]
+        let len1=length[1]
+        process(0x80);
+        while ((length[0]%512) != 448) {process(0)}
+        w[14]=len1
+        w[15]=len0;
+        transform()
+        for i in 0 ..< HASH256.len
+        { /* convert to bytes */
+            let r=(8*(3-UInt32(i)%4));
+            digest[i]=UInt8((h[i/4]>>r) & 0xff);
+        }
+        init_it();
+        return digest;
+    }
+    
+    
+}
diff --git a/version3/swift/hash384.swift b/version3/swift/hash384.swift
new file mode 100644
index 0000000..3fd78f5
--- /dev/null
+++ b/version3/swift/hash384.swift
@@ -0,0 +1,198 @@
+/*
+	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.
+*/
+
+//
+//  hash384.swift - Implementation of SHA-384
+//
+//  Created by Michael Scott on 29/03/2016.
+//  Copyright © 2016 Michael Scott. All rights reserved.
+//
+
+import Foundation
+
+public struct HASH384{
+
+    private var length=[UInt64](repeating: 0,count: 2)
+    private var h=[UInt64](repeating: 0,count: 8)
+    private var w=[UInt64](repeating: 0,count: 80)
+    static let H0:UInt64=0xcbbb9d5dc1059ed8
+    static let H1:UInt64=0x629a292a367cd507
+    static let H2:UInt64=0x9159015a3070dd17
+    static let H3:UInt64=0x152fecd8f70e5939
+    static let H4:UInt64=0x67332667ffc00b31
+    static let H5:UInt64=0x8eb44a8768581511
+    static let H6:UInt64=0xdb0c2e0d64f98fa7
+    static let H7:UInt64=0x47b5481dbefa4fa4
+    
+    static let len:Int=48
+    
+    static let K:[UInt64]=[
+        0x428a2f98d728ae22,0x7137449123ef65cd,0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc,
+        0x3956c25bf348b538,0x59f111f1b605d019,0x923f82a4af194f9b,0xab1c5ed5da6d8118,
+        0xd807aa98a3030242,0x12835b0145706fbe,0x243185be4ee4b28c,0x550c7dc3d5ffb4e2,
+        0x72be5d74f27b896f,0x80deb1fe3b1696b1,0x9bdc06a725c71235,0xc19bf174cf692694,
+        0xe49b69c19ef14ad2,0xefbe4786384f25e3,0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65,
+        0x2de92c6f592b0275,0x4a7484aa6ea6e483,0x5cb0a9dcbd41fbd4,0x76f988da831153b5,
+        0x983e5152ee66dfab,0xa831c66d2db43210,0xb00327c898fb213f,0xbf597fc7beef0ee4,
+        0xc6e00bf33da88fc2,0xd5a79147930aa725,0x06ca6351e003826f,0x142929670a0e6e70,
+        0x27b70a8546d22ffc,0x2e1b21385c26c926,0x4d2c6dfc5ac42aed,0x53380d139d95b3df,
+        0x650a73548baf63de,0x766a0abb3c77b2a8,0x81c2c92e47edaee6,0x92722c851482353b,
+        0xa2bfe8a14cf10364,0xa81a664bbc423001,0xc24b8b70d0f89791,0xc76c51a30654be30,
+        0xd192e819d6ef5218,0xd69906245565a910,0xf40e35855771202a,0x106aa07032bbd1b8,
+        0x19a4c116b8d2d0c8,0x1e376c085141ab53,0x2748774cdf8eeb99,0x34b0bcb5e19b48a8,
+        0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb,0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3,
+        0x748f82ee5defb2fc,0x78a5636f43172f60,0x84c87814a1f0ab72,0x8cc702081a6439ec,
+        0x90befffa23631e28,0xa4506cebde82bde9,0xbef9a3f7b2c67915,0xc67178f2e372532b,
+        0xca273eceea26619c,0xd186b8c721c0c207,0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178,
+        0x06f067aa72176fba,0x0a637dc5a2c898a6,0x113f9804bef90dae,0x1b710b35131c471b,
+        0x28db77f523047d84,0x32caab7b40c72493,0x3c9ebe0a15c9bebc,0x431d67c49c100d4c,
+        0x4cc5d4becb3e42b6,0x597f299cfc657e2a,0x5fcb6fab3ad6faec,0x6c44198c4a475817]
+
+    private static func S(_ n: UInt32,_ x: UInt64) -> UInt64
+    {
+        return ((x>>UInt64(n))|(x<<(64-UInt64(n))))
+    }
+    
+    private static func R(_ n: UInt32,_ x: UInt64) -> UInt64
+    {
+        return (x>>UInt64(n))
+    }
+    
+    private static func Ch(_ x: UInt64,_ y: UInt64,_ z:UInt64) -> UInt64
+    {
+        return ((x&y)^(~(x)&z))
+    }
+    
+    private static func Maj(_ x: UInt64,_ y: UInt64,_ z:UInt64) -> UInt64
+    {
+        return ((x&y)^(x&z)^(y&z))
+    }
+    
+    private static func Sig0(_ x: UInt64) -> UInt64
+    {
+        return (S(28,x)^S(34,x)^S(39,x))
+    }
+    
+    private static func Sig1(_ x: UInt64) -> UInt64
+    {
+        return (S(14,x)^S(18,x)^S(41,x))
+    }
+    
+    private static func theta0(_ x: UInt64) -> UInt64
+    {
+        return (S(1,x)^S(8,x)^R(7,x))
+    }
+    
+    private static func theta1(_ x: UInt64) -> UInt64
+    {
+        return (S(19,x)^S(61,x)^R(6,x))
+    }
+    
+    private mutating func transform()
+    { /* basic transformation step */
+        var a,b,c,d,e,f,g,hh,t1,t2 :UInt64
+        for j in 16 ..< 80
+        {
+            w[j]=HASH384.theta1(w[j-2])&+w[j-7]&+HASH384.theta0(w[j-15])&+w[j-16]
+        }
+        a=h[0]; b=h[1]; c=h[2]; d=h[3]
+        e=h[4]; f=h[5]; g=h[6]; hh=h[7]
+        
+        for j in 0 ..< 80
+        { /* 64 times - mush it up */
+            t1=hh&+HASH384.Sig1(e)&+HASH384.Ch(e,f,g)&+HASH384.K[j]&+w[j]
+            t2=HASH384.Sig0(a)&+HASH384.Maj(a,b,c)
+            hh=g; g=f; f=e;
+            e=d&+t1;
+            d=c;
+            c=b;
+            b=a;
+            a=t1&+t2;
+        }
+        h[0]=h[0]&+a; h[1]=h[1]&+b; h[2]=h[2]&+c; h[3]=h[3]&+d
+        h[4]=h[4]&+e; h[5]=h[5]&+f; h[6]=h[6]&+g; h[7]=h[7]&+hh;
+    }
+    
+    /* Re-Initialise Hash function */
+    mutating func init_it()
+    { /* initialise */
+        for i in 0 ..< 80 {w[i]=0}
+        length[0]=0; length[1]=0
+        h[0]=HASH384.H0;
+        h[1]=HASH384.H1;
+        h[2]=HASH384.H2;
+        h[3]=HASH384.H3;
+        h[4]=HASH384.H4;
+        h[5]=HASH384.H5;
+        h[6]=HASH384.H6;
+        h[7]=HASH384.H7;
+    }
+    
+    public init()
+    {
+        init_it()
+    }
+    
+    /* process a single byte */
+    public mutating func process(_ byt: UInt8)
+    { /* process the next message byte */
+        let cnt=Int((length[0]/64)%16)
+        w[cnt]<<=8;
+        w[cnt]|=(UInt64(byt)&0xFF);
+        length[0]+=8;
+        if (length[0]==0) { length[1] += 1; length[0]=0 }
+        if ((length[0]%1024)==0) {transform()}
+    }
+    
+    /* process an array of bytes */
+    public mutating func process_array(_ b: [UInt8])
+    {
+        for i in 0 ..< b.count {process((b[i]))}
+    }
+    
+    /* process a 32-bit integer */
+    public mutating func process_num(_ n:Int32)
+    {
+        process(UInt8((n>>24)&0xff))
+        process(UInt8((n>>16)&0xff))
+        process(UInt8((n>>8)&0xff))
+        process(UInt8(n&0xff))
+    }
+    
+    /* Generate 48-byte Hash */
+    public mutating func hash() -> [UInt8]
+    { /* pad message and finish - supply digest */
+        var digest=[UInt8](repeating: 0,count: 48)
+        
+        let len0=length[0]
+        let len1=length[1]
+        process(0x80);
+        while ((length[0]%1024) != 896) {process(0)}
+        w[14]=len1
+        w[15]=len0;
+        transform()
+        for i in 0 ..< HASH384.len
+        { /* convert to bytes */
+            digest[i]=UInt8((h[i/8]>>(8*(7-UInt64(i)%8))) & 0xff);
+        }
+        init_it();
+        return digest;
+    }
+    
+}
diff --git a/version3/swift/hash512.swift b/version3/swift/hash512.swift
new file mode 100644
index 0000000..2832628
--- /dev/null
+++ b/version3/swift/hash512.swift
@@ -0,0 +1,198 @@
+/*
+	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.
+*/
+
+//
+//  hash512.swift - Implementation of SHA-512
+//
+//  Created by Michael Scott on 29/03/2016.
+//  Copyright © 2016 Michael Scott. All rights reserved.
+//
+
+import Foundation
+
+public struct HASH512{
+
+    private var length=[UInt64](repeating: 0,count: 2)
+    private var h=[UInt64](repeating: 0,count: 8)
+    private var w=[UInt64](repeating: 0,count: 80)
+    static let H0:UInt64=0x6a09e667f3bcc908
+    static let H1:UInt64=0xbb67ae8584caa73b
+    static let H2:UInt64=0x3c6ef372fe94f82b
+    static let H3:UInt64=0xa54ff53a5f1d36f1
+    static let H4:UInt64=0x510e527fade682d1
+    static let H5:UInt64=0x9b05688c2b3e6c1f
+    static let H6:UInt64=0x1f83d9abfb41bd6b
+    static let H7:UInt64=0x5be0cd19137e2179
+    
+    static let len:Int=64
+    
+    static let K:[UInt64]=[
+        0x428a2f98d728ae22,0x7137449123ef65cd,0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc,
+        0x3956c25bf348b538,0x59f111f1b605d019,0x923f82a4af194f9b,0xab1c5ed5da6d8118,
+        0xd807aa98a3030242,0x12835b0145706fbe,0x243185be4ee4b28c,0x550c7dc3d5ffb4e2,
+        0x72be5d74f27b896f,0x80deb1fe3b1696b1,0x9bdc06a725c71235,0xc19bf174cf692694,
+        0xe49b69c19ef14ad2,0xefbe4786384f25e3,0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65,
+        0x2de92c6f592b0275,0x4a7484aa6ea6e483,0x5cb0a9dcbd41fbd4,0x76f988da831153b5,
+        0x983e5152ee66dfab,0xa831c66d2db43210,0xb00327c898fb213f,0xbf597fc7beef0ee4,
+        0xc6e00bf33da88fc2,0xd5a79147930aa725,0x06ca6351e003826f,0x142929670a0e6e70,
+        0x27b70a8546d22ffc,0x2e1b21385c26c926,0x4d2c6dfc5ac42aed,0x53380d139d95b3df,
+        0x650a73548baf63de,0x766a0abb3c77b2a8,0x81c2c92e47edaee6,0x92722c851482353b,
+        0xa2bfe8a14cf10364,0xa81a664bbc423001,0xc24b8b70d0f89791,0xc76c51a30654be30,
+        0xd192e819d6ef5218,0xd69906245565a910,0xf40e35855771202a,0x106aa07032bbd1b8,
+        0x19a4c116b8d2d0c8,0x1e376c085141ab53,0x2748774cdf8eeb99,0x34b0bcb5e19b48a8,
+        0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb,0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3,
+        0x748f82ee5defb2fc,0x78a5636f43172f60,0x84c87814a1f0ab72,0x8cc702081a6439ec,
+        0x90befffa23631e28,0xa4506cebde82bde9,0xbef9a3f7b2c67915,0xc67178f2e372532b,
+        0xca273eceea26619c,0xd186b8c721c0c207,0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178,
+        0x06f067aa72176fba,0x0a637dc5a2c898a6,0x113f9804bef90dae,0x1b710b35131c471b,
+        0x28db77f523047d84,0x32caab7b40c72493,0x3c9ebe0a15c9bebc,0x431d67c49c100d4c,
+        0x4cc5d4becb3e42b6,0x597f299cfc657e2a,0x5fcb6fab3ad6faec,0x6c44198c4a475817]
+    
+    private static func S(_ n: UInt32,_ x: UInt64) -> UInt64
+    {
+        return ((x>>UInt64(n))|(x<<(64-UInt64(n))))
+    }
+    
+    private static func R(_ n: UInt32,_ x: UInt64) -> UInt64
+    {
+        return (x>>UInt64(n))
+    }
+    
+    private static func Ch(_ x: UInt64,_ y: UInt64,_ z:UInt64) -> UInt64
+    {
+        return ((x&y)^(~(x)&z))
+    }
+    
+    private static func Maj(_ x: UInt64,_ y: UInt64,_ z:UInt64) -> UInt64
+    {
+        return ((x&y)^(x&z)^(y&z))
+    }
+    
+    private static func Sig0(_ x: UInt64) -> UInt64
+    {
+        return (S(28,x)^S(34,x)^S(39,x))
+    }
+    
+    private static func Sig1(_ x: UInt64) -> UInt64
+    {
+        return (S(14,x)^S(18,x)^S(41,x))
+    }
+    
+    private static func theta0(_ x: UInt64) -> UInt64
+    {
+        return (S(1,x)^S(8,x)^R(7,x))
+    }
+    
+    private static func theta1(_ x: UInt64) -> UInt64
+    {
+        return (S(19,x)^S(61,x)^R(6,x))
+    }
+    
+    private mutating func transform()
+    { /* basic transformation step */
+        var a,b,c,d,e,f,g,hh,t1,t2 :UInt64
+        for j in 16 ..< 80
+        {
+            w[j]=HASH512.theta1(w[j-2])&+w[j-7]&+HASH512.theta0(w[j-15])&+w[j-16]
+        }
+        a=h[0]; b=h[1]; c=h[2]; d=h[3]
+        e=h[4]; f=h[5]; g=h[6]; hh=h[7]
+        
+        for j in 0 ..< 80
+        { /* 64 times - mush it up */
+            t1=hh&+HASH512.Sig1(e)&+HASH512.Ch(e,f,g)&+HASH512.K[j]&+w[j]
+            t2=HASH512.Sig0(a)&+HASH512.Maj(a,b,c)
+            hh=g; g=f; f=e;
+            e=d&+t1;
+            d=c;
+            c=b;
+            b=a;
+            a=t1&+t2;
+        }
+        h[0]=h[0]&+a; h[1]=h[1]&+b; h[2]=h[2]&+c; h[3]=h[3]&+d
+        h[4]=h[4]&+e; h[5]=h[5]&+f; h[6]=h[6]&+g; h[7]=h[7]&+hh;
+    }
+    
+    /* Re-Initialise Hash function */
+    mutating func init_it()
+    { /* initialise */
+        for i in 0 ..< 80 {w[i]=0}
+        length[0]=0; length[1]=0
+        h[0]=HASH512.H0;
+        h[1]=HASH512.H1;
+        h[2]=HASH512.H2;
+        h[3]=HASH512.H3;
+        h[4]=HASH512.H4;
+        h[5]=HASH512.H5;
+        h[6]=HASH512.H6;
+        h[7]=HASH512.H7;
+    }
+    
+    public init()
+    {
+        init_it()
+    }
+    
+    /* process a single byte */
+    public mutating func process(_ byt: UInt8)
+    { /* process the next message byte */
+        let cnt=Int((length[0]/64)%16)
+        w[cnt]<<=8;
+        w[cnt]|=(UInt64(byt)&0xFF);
+        length[0]+=8;
+        if (length[0]==0) { length[1] += 1; length[0]=0 }
+        if ((length[0]%1024)==0) {transform()}
+    }
+    
+    /* process an array of bytes */
+    public mutating func process_array(_ b: [UInt8])
+    {
+        for i in 0 ..< b.count {process((b[i]))}
+    }
+    
+    /* process a 32-bit integer */
+    public mutating func process_num(_ n:Int32)
+    {
+        process(UInt8((n>>24)&0xff))
+        process(UInt8((n>>16)&0xff))
+        process(UInt8((n>>8)&0xff))
+        process(UInt8(n&0xff))
+    }
+    
+    /* Generate 64-byte Hash */
+    public mutating func hash() -> [UInt8]
+    { /* pad message and finish - supply digest */
+        var digest=[UInt8](repeating: 0,count: 64)
+        
+        let len0=length[0]
+        let len1=length[1]
+        process(0x80);
+        while ((length[0]%1024) != 896) {process(0)}
+        w[14]=len1
+        w[15]=len0;
+        transform()
+        for i in 0 ..< HASH512.len
+        { /* convert to bytes */
+            digest[i]=UInt8((h[i/8]>>(8*(7-UInt64(i)%8))) & 0xff);
+        }
+        init_it();
+        return digest;
+    }
+    
+}
diff --git a/version3/swift/mpin.swift b/version3/swift/mpin.swift
new file mode 100644
index 0000000..28a955b
--- /dev/null
+++ b/version3/swift/mpin.swift
@@ -0,0 +1,822 @@
+/*
+	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.
+*/
+
+//
+//  mpin.swift
+//
+//  Created by Michael Scott on 08/07/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+import Foundation
+import amcl
+
+public struct MPIN
+{
+    static public let EFS=Int(BIG.MODBYTES)
+    static public let EGS=Int(BIG.MODBYTES)
+    //static public let PAS:Int=16
+    static let INVALID_POINT:Int = -14
+    static let BAD_PARAMS:Int = -11
+    static let WRONG_ORDER:Int = -18
+    static public let BAD_PIN:Int = -19
+    static public let SHA256=32
+    static public let SHA384=48
+    static public let SHA512=64
+    
+    /* Configure your PIN here */
+    
+    static let MAXPIN:Int32 = 10000  // PIN less than this
+    static let PBLEN:Int32 = 14      // Number of bits in PIN
+    static let TS:Int = 10         // 10 for 4 digit PIN, 14 for 6-digit PIN - 2^TS/TS approx = sqrt(MAXPIN)
+    static let TRAP:Int = 200      // 200 for 4 digit PIN, 2000 for 6-digit PIN  - approx 2*sqrt(MAXPIN)
+
+    //static public let HASH_TYPE=SHA256
+    
+    private static func mpin_hash(_ sha:Int,_ c: FP4,_ U: ECP) -> [UInt8]
+    {
+        var w=[UInt8](repeating: 0,count: EFS)
+        var t=[UInt8](repeating: 0,count: 6*EFS)
+        var h=[UInt8]()
+        
+        c.geta().getA().toBytes(&w); for i in 0 ..< EFS {t[i]=w[i]}
+        c.geta().getB().toBytes(&w); for i in EFS ..< 2*EFS {t[i]=w[i-EFS]}
+        c.getb().getA().toBytes(&w); for i in 2*EFS ..< 3*EFS {t[i]=w[i-2*EFS]}
+        c.getb().getB().toBytes(&w); for i in 3*EFS ..< 4*EFS {t[i]=w[i-3*EFS]}
+        
+        U.getX().toBytes(&w); for i in 4*EFS ..< 5*EFS {t[i]=w[i-4*EFS]}
+        U.getY().toBytes(&w); for i in 5*EFS ..< 6*EFS {t[i]=w[i-5*EFS]}
+        
+        if sha==SHA256
+        {
+            var H=HASH256()
+            H.process_array(t)
+            h=H.hash()
+        }
+        if sha==SHA384
+        {
+            var H=HASH384()
+            H.process_array(t)
+            h=H.hash()
+        }
+        if sha==SHA512
+        {
+            var H=HASH512()
+            H.process_array(t)
+            h=H.hash()
+        }
+        if h.isEmpty {return h}
+        var R=[UInt8](repeating: 0,count: ECP.AESKEY)
+        for i in 0 ..< ECP.AESKEY {R[i]=h[i]}
+        return R
+    }
+    
+    // Hash number (optional) and string to point on curve
+    
+    private static func hashit(_ sha:Int,_ n:Int32,_ ID:[UInt8]) -> [UInt8]
+    {
+        var R=[UInt8]()
+        if sha==SHA256
+        {
+            var
+             H=HASH256()
+            if n != 0 {H.process_num(n)}
+            H.process_array(ID)
+            R=H.hash()
+        }
+        if sha==SHA384
+        {
+            var H=HASH384()
+            if n != 0 {H.process_num(n)}
+            H.process_array(ID)
+            R=H.hash()
+        }
+        if sha==SHA512
+        {
+            var H=HASH512()
+            if n != 0 {H.process_num(n)}
+            H.process_array(ID)
+            R=H.hash()
+        }
+        if R.isEmpty {return R}
+        let RM=Int(BIG.MODBYTES)
+        var W=[UInt8](repeating: 0,count: RM)
+        if sha >= RM
+        {
+            for i in 0 ..< RM {W[i]=R[i]}
+        }
+        else
+        {
+	    for i in 0 ..< sha {W[i+RM-sha]=R[i]}
+
+            //for i in 0 ..< sha {W[i]=R[i]}
+        }
+        return W
+    }
+    
+    
+    // return time in slots since epoch
+    static public func today() -> Int32
+    {
+        let date=Date()
+        return (Int32(date.timeIntervalSince1970/(60*1440)))
+    }
+
+    // these next two functions help to implement elligator squared - http://eprint.iacr.org/2014/043
+    // maps a random u to a point on the curve
+    static func map(_ u:BIG,_ cb:Int) -> ECP
+    {
+        var x=BIG(u)
+        let p=BIG(ROM.Modulus)
+        x.mod(p)
+        var P=ECP(x,cb)
+        while (true)
+        {
+            if !P.is_infinity() {break}
+            x.inc(1);  x.norm()
+            P=ECP(x,cb)
+        }
+        return P
+    }
+
+    // returns u derived from P. Random value in range 1 to return value should then be added to u
+    static func unmap(_ u:inout BIG,_ P:ECP) -> Int
+    {
+        let s=P.getS()
+        var r:Int32=0
+        let x=P.getX()
+        u.copy(x)
+        var R=ECP()
+        while (true)
+        {
+            u.dec(1); u.norm()
+            r += 1
+            R=ECP(u,s)
+            if !R.is_infinity() {break}
+        }
+        return Int(r)
+    }
+    
+    static public func HASH_ID(_ sha:Int,_ ID:[UInt8]) -> [UInt8]
+    {
+        return hashit(sha,0,ID)
+    }
+    
+    // these next two functions implement elligator squared - http://eprint.iacr.org/2014/043
+    // Elliptic curve point E in format (0x04,x,y} is converted to form {0x0-,u,v}
+    // Note that u and v are indistinguisible from random strings
+    static public func ENCODING(_ rng: inout RAND,_ E:inout [UInt8]) -> Int
+    {
+        var T=[UInt8](repeating: 0,count: EFS)
+    
+        for i in 0 ..< EFS {T[i]=E[i+1]}
+        var u=BIG.fromBytes(T);
+        for i in 0 ..< EFS {T[i]=E[i+EFS+1]}
+        var v=BIG.fromBytes(T)
+    
+        var P=ECP(u,v);
+        if P.is_infinity() {return INVALID_POINT}
+    
+        let p=BIG(ROM.Modulus)
+        u=BIG.randomnum(p,&rng)
+    
+        var su=rng.getByte();
+        su%=2
+    
+        let W=MPIN.map(u,Int(su))
+        P.sub(W);
+        let sv=P.getS();
+        let rn=MPIN.unmap(&v,P)
+        let m=rng.getByte();
+        let incr=1+Int(m)%rn
+        v.inc(incr)
+        E[0]=(su+UInt8(2*sv))
+        u.toBytes(&T)
+        for i in 0 ..< EFS {E[i+1]=T[i]}
+        v.toBytes(&T)
+        for i in 0 ..< EFS {E[i+EFS+1]=T[i]}
+    
+        return 0;
+    }
+
+    static public func DECODING(_ D:inout [UInt8]) -> Int
+    {
+        var T=[UInt8](repeating: 0,count: EFS)
+    
+        if (D[0]&0x04) != 0 {return INVALID_POINT}
+    
+        for i in 0 ..< EFS {T[i]=D[i+1]}
+        var u=BIG.fromBytes(T)
+        for i in 0 ..< EFS {T[i]=D[i+EFS+1]}
+        var v=BIG.fromBytes(T)
+    
+        let su=D[0]&1
+        let sv=(D[0]>>1)&1
+        let W=map(u,Int(su))
+        var P=map(v,Int(sv))
+        P.add(W)
+        u=P.getX()
+        v=P.getY()
+        D[0]=0x04
+        u.toBytes(&T);
+        for i in 0 ..< EFS {D[i+1]=T[i]}
+        v.toBytes(&T)
+        for i in 0 ..< EFS {D[i+EFS+1]=T[i]}
+    
+        return 0
+    }
+    // R=R1+R2 in group G1
+    static public func RECOMBINE_G1(_ R1:[UInt8],_ R2:[UInt8],_ R:inout [UInt8]) -> Int
+    {
+        var P=ECP.fromBytes(R1)
+        let Q=ECP.fromBytes(R2)
+    
+        if P.is_infinity() || Q.is_infinity() {return INVALID_POINT}
+    
+        P.add(Q)
+    
+        P.toBytes(&R,false)
+        return 0;
+    }
+    // W=W1+W2 in group G2
+    static public func RECOMBINE_G2(_ W1:[UInt8],_ W2:[UInt8],_  W:inout [UInt8]) -> Int
+    {
+        var P=ECP2.fromBytes(W1)
+        let Q=ECP2.fromBytes(W2)
+    
+        if P.is_infinity() || Q.is_infinity() {return INVALID_POINT}
+    
+        P.add(Q)
+        
+        P.toBytes(&W)
+        return 0
+    }
+    // create random secret S
+    static public func RANDOM_GENERATE(_ rng: inout RAND,_ S:inout [UInt8]) -> Int
+    {
+        let r=BIG(ROM.CURVE_Order)
+        let s=BIG.randomnum(r,&rng)
+	//if ROM.AES_S>0
+	//{
+	//	s.mod2m(2*ROM.AES_S)
+	//}    
+        s.toBytes(&S);
+        return 0;
+    }
+
+    // Extract PIN from TOKEN for identity CID
+    static public func EXTRACT_PIN(_ sha:Int,_ CID:[UInt8],_ pin:Int32,_ TOKEN:inout [UInt8]) -> Int
+    {
+        return MPIN.EXTRACT_FACTOR(sha,CID,pin%MAXPIN,PBLEN,&TOKEN)
+    }
+
+    // Extract factor from TOKEN for identity CID
+    static public func EXTRACT_FACTOR(_ sha:Int,_ CID:[UInt8],_ factor:Int32,_ facbits:Int32,_ TOKEN:inout [UInt8]) -> Int
+    {
+        var P=ECP.fromBytes(TOKEN)
+        if P.is_infinity() {return INVALID_POINT}
+        let h=MPIN.hashit(sha,0,CID)
+        var R=ECP.mapit(h)
+
+        R=R.pinmul(factor,facbits)
+        P.sub(R)
+    
+        P.toBytes(&TOKEN,false)
+    
+        return 0
+    }    
+
+    // ERestore factor to TOKEN for identity CID
+    static public func RESTORE_FACTOR(_ sha:Int,_ CID:[UInt8],_ factor:Int32,_ facbits:Int32,_ TOKEN:inout [UInt8]) -> Int
+    {
+        var P=ECP.fromBytes(TOKEN)
+        if P.is_infinity() {return INVALID_POINT}
+        let h=MPIN.hashit(sha,0,CID)
+        var R=ECP.mapit(h)
+
+        R=R.pinmul(factor,facbits)
+        P.add(R)
+    
+        P.toBytes(&TOKEN,false)
+    
+        return 0
+    }    
+
+    // Extract PIN from TOKEN for identity CID
+    /*
+    static public func EXTRACT_PIN(_ sha:Int,_ CID:[UInt8],_ pin:Int32,_ TOKEN:inout [UInt8]) -> Int
+    {
+        let P=ECP.fromBytes(TOKEN)
+        if P.is_infinity() {return INVALID_POINT}
+        let h=MPIN.hashit(sha,0,CID)
+        var R=ECP.mapit(h)
+
+        R=R.pinmul(pin%MAXPIN,MPIN.PBLEN)
+        P.sub(R)
+    
+        P.toBytes(&TOKEN,false)
+    
+        return 0
+    }*/
+
+
+    // Implement step 2 on client side of MPin protocol
+    static public func CLIENT_2(_ X:[UInt8],_ Y:[UInt8],_ SEC:inout [UInt8]) -> Int
+    {
+        let r=BIG(ROM.CURVE_Order)
+        var P=ECP.fromBytes(SEC)
+        if P.is_infinity() {return INVALID_POINT}
+    
+        var px=BIG.fromBytes(X)
+        let py=BIG.fromBytes(Y)
+        px.add(py)
+        px.mod(r)
+     //   px.rsub(r)
+
+        P=PAIR.G1mul(P,px)
+        P.neg()
+        P.toBytes(&SEC,false);
+      //  PAIR.G1mul(P,px).toBytes(&SEC,false)
+        return 0
+    }
+    
+    // Implement step 1 on client side of MPin protocol
+    static public func CLIENT_1(_ sha:Int,_ date:Int32,_ CLIENT_ID:[UInt8],_ rng: inout RAND?,_ X:inout [UInt8],_ pin:Int32,_ TOKEN:[UInt8],_ SEC:inout [UInt8],_ xID:inout [UInt8]?,_ xCID:inout [UInt8]?,_ PERMIT:[UInt8]?) -> Int
+    {
+
+        let r=BIG(ROM.CURVE_Order)
+   //     let q=BIG(ROM.Modulus)
+        var x:BIG
+        if rng != nil
+        {
+            x=BIG.randomnum(r,&rng!)
+            //if ROM.AES_S>0
+            //{
+             //   x.mod2m(2*ROM.AES_S)
+            //}
+            x.toBytes(&X);
+        }
+        else
+        {
+            x=BIG.fromBytes(X);
+        }
+    //    var t=[UInt8](count:EFS,repeatedValue:0)
+
+        var h=MPIN.hashit(sha,0,CLIENT_ID)
+        var P=ECP.mapit(h);
+    
+        var T=ECP.fromBytes(TOKEN);
+        if T.is_infinity() {return INVALID_POINT}
+    
+        var W=P.pinmul(pin%MPIN.MAXPIN,MPIN.PBLEN)
+        T.add(W)
+        if date != 0
+        {
+            W=ECP.fromBytes(PERMIT!)
+            if W.is_infinity() {return INVALID_POINT}
+            T.add(W);
+            h=MPIN.hashit(sha,date,h)
+            W=ECP.mapit(h);
+            if xID != nil
+            {
+				P=PAIR.G1mul(P,x)
+				P.toBytes(&xID!,false)
+				W=PAIR.G1mul(W,x)
+				P.add(W)
+            }
+            else
+            {
+				P.add(W);
+				P=PAIR.G1mul(P,x);
+            }
+            if xCID != nil {P.toBytes(&xCID!,false)}
+        }
+        else
+        {
+            if xID != nil
+            {
+				P=PAIR.G1mul(P,x)
+				P.toBytes(&xID!,false)
+            }
+        }
+    
+    
+        T.toBytes(&SEC,false);
+        return 0;
+    }
+    // Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret
+    static public func GET_SERVER_SECRET(_ S:[UInt8],_ SST:inout [UInt8]) -> Int
+    {
+        var Q=ECP2.generator();
+    
+        let s=BIG.fromBytes(S)
+        Q=PAIR.G2mul(Q,s)
+        Q.toBytes(&SST)
+        return 0
+    }
+ 
+    
+    //W=x*H(G);
+    //if RNG == NULL then X is passed in
+    //if RNG != NULL the X is passed out
+    //if type=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve
+    
+    static public func GET_G1_MULTIPLE(_ rng: inout RAND?,_ type:Int,_ X:inout [UInt8],_ G:[UInt8],_ W:inout [UInt8]) -> Int
+    {
+        var x:BIG
+        let r=BIG(ROM.CURVE_Order)
+        if rng != nil
+        {
+            x=BIG.randomnum(r,&rng!)
+            //if ROM.AES_S>0
+            //{
+            //    x.mod2m(2*ROM.AES_S)
+            //}
+            x.toBytes(&X)
+        }
+        else
+        {
+            x=BIG.fromBytes(X);
+        }
+        var P:ECP
+        if type==0
+        {
+            P=ECP.fromBytes(G)
+            if P.is_infinity() {return INVALID_POINT}
+        }
+        else
+            {P=ECP.mapit(G)}
+    
+        PAIR.G1mul(P,x).toBytes(&W,false)
+        return 0;
+    }
+    // Client secret CST=S*H(CID) where CID is client ID and S is master secret
+    // CID is hashed externally
+    static public func GET_CLIENT_SECRET(_ S:inout [UInt8],_ CID:[UInt8],_ CST:inout [UInt8]) -> Int
+    {
+        var RNG : RAND? = nil
+        return GET_G1_MULTIPLE(&RNG,1,&S,CID,&CST)
+    }
+    // Time Permit CTT=S*(date|H(CID)) where S is master secret
+    static public func GET_CLIENT_PERMIT(_ sha:Int,_ date:Int32,_ S:[UInt8],_ CID:[UInt8],_ CTT:inout [UInt8]) -> Int
+    {
+        let h=MPIN.hashit(sha,date,CID)
+        let P=ECP.mapit(h)
+    
+        let s=BIG.fromBytes(S)
+        PAIR.G1mul(P,s).toBytes(&CTT,false)
+        return 0;
+    }
+  
+    // Outputs H(CID) and H(T|H(CID)) for time permits. If no time permits set HID=HTID
+    static public func SERVER_1(_ sha:Int,_ date:Int32,_ CID:[UInt8],_ HID:inout [UInt8],_ HTID:inout [UInt8]?)
+    {
+        var h=MPIN.hashit(sha,0,CID)
+        var P=ECP.mapit(h)
+
+	P.toBytes(&HID,false)
+        if date != 0
+        {
+       //     if HID != nil {P.toBytes(&HID!,false)}
+            h=hashit(sha,date,h)
+            let R=ECP.mapit(h)
+            P.add(R)
+            P.toBytes(&HTID!,false)
+        }
+        //else {P.toBytes(&HID!,false)}
+    }
+    // Implement step 2 of MPin protocol on server side
+    static public func SERVER_2(_ date:Int32,_ HID:[UInt8]?,_ HTID:[UInt8]?,_ Y:[UInt8],_ SST:[UInt8],_ xID:[UInt8]?,_ xCID:[UInt8]?,_ mSEC:[UInt8],_ E:inout [UInt8]?,_ F:inout [UInt8]?) -> Int
+    { 
+      //  _=BIG(ROM.Modulus);
+        let Q=ECP2.generator();
+        let sQ=ECP2.fromBytes(SST)
+        if sQ.is_infinity() {return INVALID_POINT}
+        var R:ECP
+        if date != 0
+            {R=ECP.fromBytes(xCID!)}
+        else
+        {
+            if xID==nil {return MPIN.BAD_PARAMS}
+            R=ECP.fromBytes(xID!)
+        }
+        if R.is_infinity() {return INVALID_POINT}
+        let y=BIG.fromBytes(Y)
+        var P:ECP
+        if date != 0 {P=ECP.fromBytes(HTID!)}
+        else
+        {
+            if HID==nil {return MPIN.BAD_PARAMS}
+            P=ECP.fromBytes(HID!)
+        }
+    
+        if P.is_infinity() {return INVALID_POINT}
+    
+        P=PAIR.G1mul(P,y)
+        P.add(R); //P.affine()
+        R=ECP.fromBytes(mSEC)
+        if R.is_infinity() {return MPIN.INVALID_POINT}
+
+    
+        var g=PAIR.ate2(Q,R,sQ,P)
+        g=PAIR.fexp(g)
+    
+        if !g.isunity()
+        {
+            if HID != nil && xID != nil && E != nil && F != nil
+            {
+				g.toBytes(&E!)
+				if date != 0
+				{
+                    P=ECP.fromBytes(HID!)
+                    if P.is_infinity() {return MPIN.INVALID_POINT}
+                    R=ECP.fromBytes(xID!)
+                    if R.is_infinity() {return MPIN.INVALID_POINT}
+    
+                    P=PAIR.G1mul(P,y);
+                    P.add(R); //P.affine()
+				}
+				g=PAIR.ate(Q,P);
+				g=PAIR.fexp(g);
+				g.toBytes(&F!);
+            }
+            return MPIN.BAD_PIN;
+        }
+    
+        return 0
+    }
+    // Pollards kangaroos used to return PIN error
+    static public func KANGAROO(_ E:[UInt8]?,_ F:[UInt8]?) -> Int
+    {
+        var ge=FP12.fromBytes(E!)
+        var gf=FP12.fromBytes(F!)
+        var distance=[Int]();
+        var t=FP12(gf);
+        var table=[FP12]()
+        
+        var s:Int=1
+        for _ in 0 ..< Int(TS)
+        {
+            distance.append(s)
+            table.append(FP12(t))
+            s*=2
+            t.usqr()
+ 
+        }
+        t.one()
+        var dn:Int=0
+        for _ in 0 ..< TRAP
+        {
+            var lsbs=BIG(t.geta().geta().getA())
+            let i=Int(lsbs.lastbits(8))%TS
+            t.mul(table[i])
+            dn+=distance[i]
+        }
+        gf.copy(t); gf.conj()
+        var steps=0; var dm:Int=0
+        var res=0;
+        while (dm-dn<Int(MAXPIN))
+        {
+            steps += 1;
+            if steps>4*TRAP {break}
+            var lsbs=BIG(ge.geta().geta().getA())
+            let i=Int(lsbs.lastbits(8))%TS
+            ge.mul(table[i])
+            dm+=distance[i]
+            if (ge.equals(t))
+            {
+				res=dm-dn;
+				break;
+            }
+            if (ge.equals(gf))
+            {
+				res=dn-dm
+				break
+            }
+    
+        }
+        if steps>4*TRAP || dm-dn>=Int(MAXPIN) {res=0 }    // Trap Failed  - probable invalid token
+        return res
+    }
+    // Functions to support M-Pin Full
+    
+    static public func PRECOMPUTE(_ TOKEN:[UInt8],_ CID:[UInt8],_ G1:inout [UInt8],_ G2:inout [UInt8]) -> Int
+    {
+        let T=ECP.fromBytes(TOKEN);
+        if T.is_infinity() {return INVALID_POINT}
+    
+        let P=ECP.mapit(CID)
+    
+        let Q=ECP2.generator();
+    
+        var g=PAIR.ate(Q,T)
+        g=PAIR.fexp(g)
+        g.toBytes(&G1)
+    
+        g=PAIR.ate(Q,P)
+        g=PAIR.fexp(g)
+        g.toBytes(&G2)
+    
+        return 0
+    }
+    
+    static public func HASH_ALL(_ sha:Int,_ HID:[UInt8],_ xID:[UInt8]?,_ xCID:[UInt8]?,_ SEC:[UInt8],_ Y:[UInt8],_ R:[UInt8],_ W:[UInt8]  ) -> [UInt8]
+    {
+        var T=[UInt8](repeating: 0,count: 10*EFS+4)
+        var tlen=0
+
+        for i in 0 ..< HID.count  {T[i]=HID[i]}
+        tlen+=HID.count
+        if xCID != nil {
+            for i in 0 ..< xCID!.count  {T[i+tlen]=xCID![i]}
+            tlen+=xCID!.count
+        } else {
+            for i in 0 ..< xID!.count {T[i+tlen]=xID![i]}
+            tlen+=xID!.count
+        }
+        for i in 0 ..< SEC.count {T[i+tlen]=SEC[i]}
+        tlen+=SEC.count;
+        for i in 0 ..< Y.count {T[i+tlen]=Y[i]}
+        tlen+=Y.count;
+        for i in 0 ..< R.count {T[i+tlen]=R[i]}
+        tlen+=R.count;
+        for i in 0 ..< W.count {T[i+tlen]=W[i]}
+        tlen+=W.count;
+
+        return hashit(sha,0,T);
+    }
+
+    // calculate common key on client side
+    // wCID = w.(A+AT)
+    static public func CLIENT_KEY(_ sha:Int,_ G1:[UInt8],_ G2:[UInt8],_ pin:Int32,_ R:[UInt8],_ X:[UInt8],_ H:[UInt8],_ wCID:[UInt8],_ CK:inout [UInt8]) -> Int
+    {
+        var g1=FP12.fromBytes(G1)
+        var g2=FP12.fromBytes(G2)
+        var z=BIG.fromBytes(R)
+        let x=BIG.fromBytes(X)
+        let h=BIG.fromBytes(H)
+    
+        var W=ECP.fromBytes(wCID)
+        if W.is_infinity() {return INVALID_POINT}
+    
+        W=PAIR.G1mul(W,x)
+    
+     //   let f=FP2(BIG(ROM.Fra),BIG(ROM.Frb))
+        let r=BIG(ROM.CURVE_Order)
+     //   let q=BIG(ROM.Modulus)
+    
+        z.add(h)   // new
+        z.mod(r)
+
+        g2.pinpow(pin,PBLEN)
+        g1.mul(g2)
+
+        let c=g1.compow(z,r)
+/*
+        let m=BIG(q)
+        m.mod(r)
+    
+        let a=BIG(z)
+        a.mod(m)
+    
+        let b=BIG(z)
+        b.div(m);
+    
+
+    
+        var c=g1.trace()
+//        g2.copy(g1)
+        g2.frob(f)
+        let cp=g2.trace()
+        g1.conj()
+        g2.mul(g1)
+        let cpm1=g2.trace()
+        g2.mul(g1)
+        let cpm2=g2.trace()
+    
+        c=c.xtr_pow2(cp,cpm1,cpm2,a,b)
+ */     
+        let t=mpin_hash(sha,c,W)
+
+        for i in 0 ..< ECP.AESKEY {CK[i]=t[i]}
+    
+        return 0
+    }
+    // calculate common key on server side
+    // Z=r.A - no time permits involved
+    
+    static public func SERVER_KEY(_ sha:Int,_ Z:[UInt8],_ SST:[UInt8],_ W:[UInt8],_ H:[UInt8],_ HID:[UInt8],_ xID:[UInt8],_ xCID:[UInt8]?,_ SK:inout [UInt8]) -> Int
+    {
+   //     var t=[UInt8](count:EFS,repeatedValue:0)
+    
+        let sQ=ECP2.fromBytes(SST)
+        if sQ.is_infinity() {return INVALID_POINT}
+        var R=ECP.fromBytes(Z)
+        if R.is_infinity() {return INVALID_POINT}
+        var A=ECP.fromBytes(HID)
+        if A.is_infinity() {return INVALID_POINT}
+    
+        var U:ECP
+        if xCID != nil
+            {U=ECP.fromBytes(xCID!)}
+        else
+            {U=ECP.fromBytes(xID)}
+        
+        if U.is_infinity() {return INVALID_POINT}
+    
+        let w=BIG.fromBytes(W)
+        let h=BIG.fromBytes(H)
+        A=PAIR.G1mul(A,h)
+        R.add(A); //R.affine()
+
+        U=PAIR.G1mul(U,w)
+        var g=PAIR.ate(sQ,R)
+        g=PAIR.fexp(g)
+    
+        let c=g.trace()
+        
+        let t=mpin_hash(sha,c,U)
+ 
+        for i in 0 ..< ECP.AESKEY {SK[i]=t[i]}
+    
+        return 0
+    }
+    
+    // return time since epoch
+    static public func GET_TIME() -> Int32
+    {
+        let date=Date()
+        return (Int32(date.timeIntervalSince1970))
+    }
+
+    // Generate Y = H(epoch, xCID/xID)
+    static public func GET_Y(_ sha:Int,_ TimeValue:Int32,_ xCID:[UInt8],_ Y:inout [UInt8])
+    {
+        let h = MPIN.hashit(sha,TimeValue,xCID)
+        var y = BIG.fromBytes(h)
+        let q=BIG(ROM.CURVE_Order)
+        y.mod(q)
+	//if ROM.AES_S>0
+	//{
+	//	y.mod2m(2*ROM.AES_S)
+	//}
+        y.toBytes(&Y)
+    }
+    // One pass MPIN Client
+    static public func CLIENT(_ sha:Int,_ date:Int32,_ CLIENT_ID:[UInt8],_ RNG: inout RAND?,_ X:inout [UInt8],_ pin:Int32,_ TOKEN:[UInt8],_  SEC:inout [UInt8],_ xID:inout [UInt8]?,_ xCID:inout [UInt8]?,_ PERMIT:[UInt8]?,_ TimeValue:Int32,_ Y:inout [UInt8]) -> Int
+    {
+        var rtn=0
+        //var xID=xID 
+  
+        rtn = MPIN.CLIENT_1(sha,date,CLIENT_ID,&RNG,&X,pin,TOKEN,&SEC,&xID,&xCID,PERMIT!)
+
+        if rtn != 0 {return rtn}
+    
+        if date==0 {MPIN.GET_Y(sha,TimeValue,xID!,&Y)}
+        else {MPIN.GET_Y(sha,TimeValue,xCID!,&Y)}
+    
+        rtn = MPIN.CLIENT_2(X,Y,&SEC)
+        if (rtn != 0) {return rtn}
+    
+        return 0
+    }
+    // One pass MPIN Server
+    static public func SERVER(_ sha:Int,_ date:Int32,_ HID:inout [UInt8],_ HTID:inout [UInt8]?,_ Y:inout [UInt8],_ SST:[UInt8],_ xID:[UInt8]?,_ xCID:[UInt8],_ SEC:[UInt8],_ E:inout [UInt8]?,_ F:inout [UInt8]?,_ CID:[UInt8],_ TimeValue:Int32) -> Int
+    {
+        var rtn=0
+    
+        var pID:[UInt8]
+        if date == 0
+            {pID = xID!}
+        else
+            {pID = xCID}
+    
+        SERVER_1(sha,date,CID,&HID,&HTID);
+    
+        GET_Y(sha,TimeValue,pID,&Y);
+    
+        rtn = SERVER_2(date,HID,HTID!,Y,SST,xID,xCID,SEC,&E,&F);
+        if rtn != 0 {return rtn}
+    
+        return 0
+    }
+   
+}
+ 
+
diff --git a/version3/swift/mpin192.swift b/version3/swift/mpin192.swift
new file mode 100644
index 0000000..d4b1510
--- /dev/null
+++ b/version3/swift/mpin192.swift
@@ -0,0 +1,828 @@
+/*
+	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.
+*/
+
+//
+//  mpin192.swift
+//
+//  Created by Michael Scott on 08/07/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+import Foundation
+import amcl
+
+public struct MPIN192
+{
+    static public let EFS=Int(BIG.MODBYTES)
+    static public let EGS=Int(BIG.MODBYTES)
+    //static public let PAS:Int=16
+    static let INVALID_POINT:Int = -14
+    static let BAD_PARAMS:Int = -11
+    static let WRONG_ORDER:Int = -18
+    static public let BAD_PIN:Int = -19
+    static public let SHA256=32
+    static public let SHA384=48
+    static public let SHA512=64
+    
+    /* Configure your PIN here */
+    
+    static let MAXPIN:Int32 = 10000  // PIN less than this
+    static let PBLEN:Int32 = 14      // Number of bits in PIN
+    static let TS:Int = 10         // 10 for 4 digit PIN, 14 for 6-digit PIN - 2^TS/TS approx = sqrt(MAXPIN)
+    static let TRAP:Int = 200      // 200 for 4 digit PIN, 2000 for 6-digit PIN  - approx 2*sqrt(MAXPIN)
+
+   
+    private static func mpin_hash(_ sha:Int,_ c: FP8,_ U: ECP) -> [UInt8]
+    {
+        var w=[UInt8](repeating: 0,count: EFS)
+        var t=[UInt8](repeating: 0,count: 10*EFS)
+        var h=[UInt8]()
+        
+        c.geta().geta().getA().toBytes(&w); for i in 0 ..< EFS {t[i]=w[i]}
+        c.geta().geta().getB().toBytes(&w); for i in EFS ..< 2*EFS {t[i]=w[i-EFS]}
+        c.geta().getb().getA().toBytes(&w); for i in 2*EFS ..< 3*EFS {t[i]=w[i-2*EFS]}
+        c.geta().getb().getB().toBytes(&w); for i in 3*EFS ..< 4*EFS {t[i]=w[i-3*EFS]}
+
+        c.getb().geta().getA().toBytes(&w); for i in 4*EFS ..< 5*EFS {t[i]=w[i-4*EFS]}
+        c.getb().geta().getB().toBytes(&w); for i in 5*EFS ..< 6*EFS {t[i]=w[i-5*EFS]}
+        c.getb().getb().getA().toBytes(&w); for i in 6*EFS ..< 7*EFS {t[i]=w[i-6*EFS]}
+        c.getb().getb().getB().toBytes(&w); for i in 7*EFS ..< 8*EFS {t[i]=w[i-7*EFS]}
+
+
+        U.getX().toBytes(&w); for i in 8*EFS ..< 9*EFS {t[i]=w[i-8*EFS]}
+        U.getY().toBytes(&w); for i in 9*EFS ..< 10*EFS {t[i]=w[i-9*EFS]}
+        
+        if sha==SHA256
+        {
+            var H=HASH256()
+            H.process_array(t)
+            h=H.hash()
+        }
+        if sha==SHA384
+        {
+            var H=HASH384()
+            H.process_array(t)
+            h=H.hash()
+        }
+        if sha==SHA512
+        {
+            var H=HASH512()
+            H.process_array(t)
+            h=H.hash()
+        }
+        if h.isEmpty {return h}
+        var R=[UInt8](repeating: 0,count: ECP.AESKEY)
+        for i in 0 ..< ECP.AESKEY {R[i]=h[i]}
+        return R
+    }
+    
+    // Hash number (optional) and string to point on curve
+    
+    private static func hashit(_ sha:Int,_ n:Int32,_ ID:[UInt8]) -> [UInt8]
+    {
+        var R=[UInt8]()
+        if sha==SHA256
+        {
+            var H=HASH256()
+            if n != 0 {H.process_num(n)}
+            H.process_array(ID)
+            R=H.hash()
+        }
+        if sha==SHA384
+        {
+            var H=HASH384()
+            if n != 0 {H.process_num(n)}
+            H.process_array(ID)
+            R=H.hash()
+        }
+        if sha==SHA512
+        {
+            var H=HASH512()
+            if n != 0 {H.process_num(n)}
+            H.process_array(ID)
+            R=H.hash()
+        }
+        if R.isEmpty {return R}
+        let RM=Int(BIG.MODBYTES)
+        var W=[UInt8](repeating: 0,count: RM)
+        if sha >= RM
+        {
+            for i in 0 ..< RM {W[i]=R[i]}
+        }
+        else
+        {
+        for i in 0 ..< sha {W[i+RM-sha]=R[i]}
+
+            //for i in 0 ..< sha {W[i]=R[i]}
+        }
+        return W
+    }
+    
+    
+    // return time in slots since epoch
+    static public func today() -> Int32
+    {
+        let date=Date()
+        return (Int32(date.timeIntervalSince1970/(60*1440)))
+    }
+
+    // these next two functions help to implement elligator squared - http://eprint.iacr.org/2014/043
+    // maps a random u to a point on the curve
+    static func map(_ u:BIG,_ cb:Int) -> ECP
+    {
+        var x=BIG(u)
+        let p=BIG(ROM.Modulus)
+        x.mod(p)
+        var P=ECP(x,cb)
+        while (true)
+        {
+            if !P.is_infinity() {break}
+            x.inc(1);  x.norm()
+            P=ECP(x,cb)
+        }
+        return P
+    }
+
+    // returns u derived from P. Random value in range 1 to return value should then be added to u
+    static func unmap(_ u:inout BIG,_ P:ECP) -> Int
+    {
+        let s=P.getS()
+        var r:Int32=0
+        let x=P.getX()
+        u.copy(x)
+        var R=ECP()
+        while (true)
+        {
+            u.dec(1); u.norm()
+            r += 1
+            R=ECP(u,s)
+            if !R.is_infinity() {break}
+        }
+        return Int(r)
+    }
+    
+    static public func HASH_ID(_ sha:Int,_ ID:[UInt8]) -> [UInt8]
+    {
+        return hashit(sha,0,ID)
+    }
+    
+    // these next two functions implement elligator squared - http://eprint.iacr.org/2014/043
+    // Elliptic curve point E in format (0x04,x,y} is converted to form {0x0-,u,v}
+    // Note that u and v are indistinguisible from random strings
+    static public func ENCODING(_ rng: inout RAND,_ E:inout [UInt8]) -> Int
+    {
+        var T=[UInt8](repeating: 0,count: EFS)
+    
+        for i in 0 ..< EFS {T[i]=E[i+1]}
+        var u=BIG.fromBytes(T);
+        for i in 0 ..< EFS {T[i]=E[i+EFS+1]}
+        var v=BIG.fromBytes(T)
+    
+        var P=ECP(u,v);
+        if P.is_infinity() {return INVALID_POINT}
+    
+        let p=BIG(ROM.Modulus)
+        u=BIG.randomnum(p,&rng)
+    
+        var su=rng.getByte();
+        su%=2
+    
+        let W=MPIN192.map(u,Int(su))
+        P.sub(W);
+        let sv=P.getS();
+        let rn=MPIN192.unmap(&v,P)
+        let m=rng.getByte();
+        let incr=1+Int(m)%rn
+        v.inc(incr)
+        E[0]=(su+UInt8(2*sv))
+        u.toBytes(&T)
+        for i in 0 ..< EFS {E[i+1]=T[i]}
+        v.toBytes(&T)
+        for i in 0 ..< EFS {E[i+EFS+1]=T[i]}
+    
+        return 0;
+    }
+
+    static public func DECODING(_ D:inout [UInt8]) -> Int
+    {
+        var T=[UInt8](repeating: 0,count: EFS)
+    
+        if (D[0]&0x04) != 0 {return INVALID_POINT}
+    
+        for i in 0 ..< EFS {T[i]=D[i+1]}
+        var u=BIG.fromBytes(T)
+        for i in 0 ..< EFS {T[i]=D[i+EFS+1]}
+        var v=BIG.fromBytes(T)
+    
+        let su=D[0]&1
+        let sv=(D[0]>>1)&1
+        let W=map(u,Int(su))
+        var P=map(v,Int(sv))
+        P.add(W)
+        u=P.getX()
+        v=P.getY()
+        D[0]=0x04
+        u.toBytes(&T);
+        for i in 0 ..< EFS {D[i+1]=T[i]}
+        v.toBytes(&T)
+        for i in 0 ..< EFS {D[i+EFS+1]=T[i]}
+    
+        return 0
+    }
+    // R=R1+R2 in group G1
+    static public func RECOMBINE_G1(_ R1:[UInt8],_ R2:[UInt8],_ R:inout [UInt8]) -> Int
+    {
+        var P=ECP.fromBytes(R1)
+        let Q=ECP.fromBytes(R2)
+    
+        if P.is_infinity() || Q.is_infinity() {return INVALID_POINT}
+    
+        P.add(Q)
+    
+        P.toBytes(&R,false)
+        return 0;
+    }
+    // W=W1+W2 in group G2
+    static public func RECOMBINE_G2(_ W1:[UInt8],_ W2:[UInt8],_  W:inout [UInt8]) -> Int
+    {
+        var P=ECP4.fromBytes(W1)
+        let Q=ECP4.fromBytes(W2)
+    
+        if P.is_infinity() || Q.is_infinity() {return INVALID_POINT}
+    
+        P.add(Q)
+        
+        P.toBytes(&W)
+        return 0
+    }
+    // create random secret S
+    static public func RANDOM_GENERATE(_ rng: inout RAND,_ S:inout [UInt8]) -> Int
+    {
+        let r=BIG(ROM.CURVE_Order)
+        let s=BIG.randomnum(r,&rng)
+    //if ROM.AES_S>0
+    //{
+    //  s.mod2m(2*ROM.AES_S)
+    //}    
+        s.toBytes(&S);
+        return 0;
+    }
+
+    // Extract PIN from TOKEN for identity CID
+    static public func EXTRACT_PIN(_ sha:Int,_ CID:[UInt8],_ pin:Int32,_ TOKEN:inout [UInt8]) -> Int
+    {
+        return MPIN192.EXTRACT_FACTOR(sha,CID,pin%MAXPIN,PBLEN,&TOKEN)
+    }
+
+    // Extract factor from TOKEN for identity CID
+    static public func EXTRACT_FACTOR(_ sha:Int,_ CID:[UInt8],_ factor:Int32,_ facbits:Int32,_ TOKEN:inout [UInt8]) -> Int
+    {
+        var P=ECP.fromBytes(TOKEN)
+        if P.is_infinity() {return INVALID_POINT}
+        let h=MPIN192.hashit(sha,0,CID)
+        var R=ECP.mapit(h)
+
+        R=R.pinmul(factor,facbits)
+        P.sub(R)
+    
+        P.toBytes(&TOKEN,false)
+    
+        return 0
+    }    
+
+    // ERestore factor to TOKEN for identity CID
+    static public func RESTORE_FACTOR(_ sha:Int,_ CID:[UInt8],_ factor:Int32,_ facbits:Int32,_ TOKEN:inout [UInt8]) -> Int
+    {
+        var P=ECP.fromBytes(TOKEN)
+        if P.is_infinity() {return INVALID_POINT}
+        let h=MPIN192.hashit(sha,0,CID)
+        var R=ECP.mapit(h)
+
+        R=R.pinmul(factor,facbits)
+        P.add(R)
+    
+        P.toBytes(&TOKEN,false)
+    
+        return 0
+    }    
+
+    // Extract PIN from TOKEN for identity CID
+    /*
+    static public func EXTRACT_PIN(_ sha:Int,_ CID:[UInt8],_ pin:Int32,_ TOKEN:inout [UInt8]) -> Int
+    {
+        let P=ECP.fromBytes(TOKEN)
+        if P.is_infinity() {return INVALID_POINT}
+        let h=MPIN192.hashit(sha,0,CID)
+        var R=ECP.mapit(h)
+
+        R=R.pinmul(pin%MAXPIN,MPIN192.PBLEN)
+        P.sub(R)
+    
+        P.toBytes(&TOKEN,false)
+    
+        return 0
+    }*/
+
+
+    // Implement step 2 on client side of MPin protocol
+    static public func CLIENT_2(_ X:[UInt8],_ Y:[UInt8],_ SEC:inout [UInt8]) -> Int
+    {
+        let r=BIG(ROM.CURVE_Order)
+        var P=ECP.fromBytes(SEC)
+        if P.is_infinity() {return INVALID_POINT}
+    
+        var px=BIG.fromBytes(X)
+        let py=BIG.fromBytes(Y)
+        px.add(py)
+        px.mod(r)
+     //   px.rsub(r)
+
+        P=PAIR192.G1mul(P,px)
+        P.neg()
+        P.toBytes(&SEC,false);
+      //  PAIR192.G1mul(P,px).toBytes(&SEC,false)
+        return 0
+    }
+    
+    // Implement step 1 on client side of MPin protocol
+    static public func CLIENT_1(_ sha:Int,_ date:Int32,_ CLIENT_ID:[UInt8],_ rng: inout RAND?,_ X:inout [UInt8],_ pin:Int32,_ TOKEN:[UInt8],_ SEC:inout [UInt8],_ xID:inout [UInt8]?,_ xCID:inout [UInt8]?,_ PERMIT:[UInt8]?) -> Int
+    {
+
+        let r=BIG(ROM.CURVE_Order)
+   //     let q=BIG(ROM.Modulus)
+        var x:BIG
+        if rng != nil
+        {
+            x=BIG.randomnum(r,&rng!)
+            //if ROM.AES_S>0
+            //{
+             //   x.mod2m(2*ROM.AES_S)
+            //}
+            x.toBytes(&X);
+        }
+        else
+        {
+            x=BIG.fromBytes(X);
+        }
+    //    var t=[UInt8](count:EFS,repeatedValue:0)
+
+        var h=MPIN192.hashit(sha,0,CLIENT_ID)
+        var P=ECP.mapit(h);
+    
+        var T=ECP.fromBytes(TOKEN);
+        if T.is_infinity() {return INVALID_POINT}
+    
+        var W=P.pinmul(pin%MPIN192.MAXPIN,MPIN192.PBLEN)
+        T.add(W)
+        if date != 0
+        {
+            W=ECP.fromBytes(PERMIT!)
+            if W.is_infinity() {return INVALID_POINT}
+            T.add(W);
+            h=MPIN192.hashit(sha,date,h)
+            W=ECP.mapit(h);
+            if xID != nil
+            {
+                P=PAIR192.G1mul(P,x)
+                P.toBytes(&xID!,false)
+                W=PAIR192.G1mul(W,x)
+                P.add(W)
+            }
+            else
+            {
+                P.add(W);
+                P=PAIR192.G1mul(P,x);
+            }
+            if xCID != nil {P.toBytes(&xCID!,false)}
+        }
+        else
+        {
+            if xID != nil
+            {
+                P=PAIR192.G1mul(P,x)
+                P.toBytes(&xID!,false)
+            }
+        }
+    
+    
+        T.toBytes(&SEC,false);
+        return 0;
+    }
+    // Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret
+    static public func GET_SERVER_SECRET(_ S:[UInt8],_ SST:inout [UInt8]) -> Int
+    {
+        var Q=ECP4.generator();
+    
+        let s=BIG.fromBytes(S)
+        Q=PAIR192.G2mul(Q,s)
+        Q.toBytes(&SST)
+        return 0
+    }
+ 
+    
+    //W=x*H(G);
+    //if RNG == NULL then X is passed in
+    //if RNG != NULL the X is passed out
+    //if type=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve
+    
+    static public func GET_G1_MULTIPLE(_ rng: inout RAND?,_ type:Int,_ X:inout [UInt8],_ G:[UInt8],_ W:inout [UInt8]) -> Int
+    {
+        var x:BIG
+        let r=BIG(ROM.CURVE_Order)
+        if rng != nil
+        {
+            x=BIG.randomnum(r,&rng!)
+            //if ROM.AES_S>0
+            //{
+            //    x.mod2m(2*ROM.AES_S)
+            //}
+            x.toBytes(&X)
+        }
+        else
+        {
+            x=BIG.fromBytes(X);
+        }
+        var P:ECP
+        if type==0
+        {
+            P=ECP.fromBytes(G)
+            if P.is_infinity() {return INVALID_POINT}
+        }
+        else
+            {P=ECP.mapit(G)}
+    
+        PAIR192.G1mul(P,x).toBytes(&W,false)
+        return 0;
+    }
+    // Client secret CST=S*H(CID) where CID is client ID and S is master secret
+    // CID is hashed externally
+    static public func GET_CLIENT_SECRET(_ S:inout [UInt8],_ CID:[UInt8],_ CST:inout [UInt8]) -> Int
+    {
+        var RNG : RAND? = nil        
+        return GET_G1_MULTIPLE(&RNG,1,&S,CID,&CST)
+    }
+    // Time Permit CTT=S*(date|H(CID)) where S is master secret
+    static public func GET_CLIENT_PERMIT(_ sha:Int,_ date:Int32,_ S:[UInt8],_ CID:[UInt8],_ CTT:inout [UInt8]) -> Int
+    {
+        let h=MPIN192.hashit(sha,date,CID)
+        let P=ECP.mapit(h)
+    
+        let s=BIG.fromBytes(S)
+        PAIR192.G1mul(P,s).toBytes(&CTT,false)
+        return 0;
+    }
+  
+    // Outputs H(CID) and H(T|H(CID)) for time permits. If no time permits set HID=HTID
+    static public func SERVER_1(_ sha:Int,_ date:Int32,_ CID:[UInt8],_ HID:inout [UInt8],_ HTID:inout [UInt8]?)
+    {
+        var h=MPIN192.hashit(sha,0,CID)
+        var P=ECP.mapit(h)
+
+        P.toBytes(&HID,false)
+        if date != 0
+        {
+       //     if HID != nil {P.toBytes(&HID!,false)}
+            h=hashit(sha,date,h)
+            let R=ECP.mapit(h)
+            P.add(R)
+            P.toBytes(&HTID!,false)
+        }
+        //else {P.toBytes(&HID!,false)}
+    }
+    // Implement step 2 of MPin protocol on server side
+    static public func SERVER_2(_ date:Int32,_ HID:[UInt8]?,_ HTID:[UInt8]?,_ Y:[UInt8],_ SST:[UInt8],_ xID:[UInt8]?,_ xCID:[UInt8]?,_ mSEC:[UInt8],_ E:inout [UInt8]?,_ F:inout [UInt8]?) -> Int
+    { 
+      //  _=BIG(ROM.Modulus);
+        let Q=ECP4.generator();
+        let sQ=ECP4.fromBytes(SST)
+        if sQ.is_infinity() {return INVALID_POINT}
+        var R:ECP
+        if date != 0
+            {R=ECP.fromBytes(xCID!)}
+        else
+        {
+            if xID==nil {return MPIN192.BAD_PARAMS}
+            R=ECP.fromBytes(xID!)
+        }
+        if R.is_infinity() {return INVALID_POINT}
+        let y=BIG.fromBytes(Y)
+        var P:ECP
+        if date != 0 {P=ECP.fromBytes(HTID!)}
+        else
+        {
+            if HID==nil {return MPIN192.BAD_PARAMS}
+            P=ECP.fromBytes(HID!)
+        }
+    
+        if P.is_infinity() {return INVALID_POINT}
+    
+        P=PAIR192.G1mul(P,y)
+        P.add(R); //P.affine()
+        R=ECP.fromBytes(mSEC)
+        if R.is_infinity() {return MPIN192.INVALID_POINT}
+
+    
+        var g=PAIR192.ate2(Q,R,sQ,P)
+        g=PAIR192.fexp(g)
+    
+        if !g.isunity()
+        {
+            if HID != nil && xID != nil && E != nil && F != nil
+            {
+                g.toBytes(&E!)
+                if date != 0
+                {
+                    P=ECP.fromBytes(HID!)
+                    if P.is_infinity() {return MPIN192.INVALID_POINT}
+                    R=ECP.fromBytes(xID!)
+                    if R.is_infinity() {return MPIN192.INVALID_POINT}
+    
+                    P=PAIR192.G1mul(P,y);
+                    P.add(R); //P.affine()
+                }
+                g=PAIR192.ate(Q,P);
+                g=PAIR192.fexp(g);
+                g.toBytes(&F!);
+            }
+            return MPIN192.BAD_PIN;
+        }
+    
+        return 0
+    }
+    // Pollards kangaroos used to return PIN error
+    static public func KANGAROO(_ E:[UInt8]?,_ F:[UInt8]?) -> Int
+    {
+        var ge=FP24.fromBytes(E!)
+        var gf=FP24.fromBytes(F!)
+        var distance=[Int]();
+        var t=FP24(gf);
+        var table=[FP24]()
+        
+        var s:Int=1
+        for _ in 0 ..< Int(TS)
+        {
+            distance.append(s)
+            table.append(FP24(t))
+            s*=2
+            t.usqr()
+ 
+        }
+        t.one()
+        var dn:Int=0
+        for _ in 0 ..< TRAP
+        {
+            var lsbs=BIG(t.geta().geta().geta().getA())
+            let i=Int(lsbs.lastbits(8))%TS
+            t.mul(table[i])
+            dn+=distance[i]
+        }
+        gf.copy(t); gf.conj()
+        var steps=0; var dm:Int=0
+        var res=0;
+        while (dm-dn<Int(MAXPIN))
+        {
+            steps += 1;
+            if steps>4*TRAP {break}
+            var lsbs=BIG(ge.geta().geta().geta().getA())
+            let i=Int(lsbs.lastbits(8))%TS
+            ge.mul(table[i])
+            dm+=distance[i]
+            if (ge.equals(t))
+            {
+                res=dm-dn;
+                break;
+            }
+            if (ge.equals(gf))
+            {
+                res=dn-dm
+                break
+            }
+    
+        }
+        if steps>4*TRAP || dm-dn>=Int(MAXPIN) {res=0 }    // Trap Failed  - probable invalid token
+        return res
+    }
+    // Functions to support M-Pin Full
+    
+    static public func PRECOMPUTE(_ TOKEN:[UInt8],_ CID:[UInt8],_ G1:inout [UInt8],_ G2:inout [UInt8]) -> Int
+    {
+        let T=ECP.fromBytes(TOKEN);
+        if T.is_infinity() {return INVALID_POINT}
+    
+        let P=ECP.mapit(CID)
+    
+        let Q=ECP4.generator();
+    
+        var g=PAIR192.ate(Q,T)
+        g=PAIR192.fexp(g)
+        g.toBytes(&G1)
+    
+        g=PAIR192.ate(Q,P)
+        g=PAIR192.fexp(g)
+        g.toBytes(&G2)
+    
+        return 0
+    }
+    
+    static public func HASH_ALL(_ sha:Int,_ HID:[UInt8],_ xID:[UInt8]?,_ xCID:[UInt8]?,_ SEC:[UInt8],_ Y:[UInt8],_ R:[UInt8],_ W:[UInt8]  ) -> [UInt8]
+    {
+        var T=[UInt8](repeating: 0,count: 10*EFS+4)
+        var tlen=0
+
+        for i in 0 ..< HID.count  {T[i]=HID[i]}
+        tlen+=HID.count
+        if xCID != nil {
+            for i in 0 ..< xCID!.count  {T[i+tlen]=xCID![i]}
+            tlen+=xCID!.count
+        } else {
+            for i in 0 ..< xID!.count {T[i+tlen]=xID![i]}
+            tlen+=xID!.count
+        }
+        for i in 0 ..< SEC.count {T[i+tlen]=SEC[i]}
+        tlen+=SEC.count;
+        for i in 0 ..< Y.count {T[i+tlen]=Y[i]}
+        tlen+=Y.count;
+        for i in 0 ..< R.count {T[i+tlen]=R[i]}
+        tlen+=R.count;
+        for i in 0 ..< W.count {T[i+tlen]=W[i]}
+        tlen+=W.count;
+
+        return hashit(sha,0,T);
+    }
+
+    // calculate common key on client side
+    // wCID = w.(A+AT)
+    static public func CLIENT_KEY(_ sha:Int,_ G1:[UInt8],_ G2:[UInt8],_ pin:Int32,_ R:[UInt8],_ X:[UInt8],_ H:[UInt8],_ wCID:[UInt8],_ CK:inout [UInt8]) -> Int
+    {
+        var g1=FP24.fromBytes(G1)
+        var g2=FP24.fromBytes(G2)
+        var z=BIG.fromBytes(R)
+        let x=BIG.fromBytes(X)
+        let h=BIG.fromBytes(H)
+    
+        var W=ECP.fromBytes(wCID)
+        if W.is_infinity() {return INVALID_POINT}
+    
+        W=PAIR192.G1mul(W,x)
+    
+     //   let f=FP2(BIG(ROM.Fra),BIG(ROM.Frb))
+        let r=BIG(ROM.CURVE_Order)
+     //   let q=BIG(ROM.Modulus)
+    
+        z.add(h)   // new
+        z.mod(r)
+
+        g2.pinpow(pin,PBLEN)
+        g1.mul(g2)
+
+        let c=g1.compow(z,r)
+/*
+        let m=BIG(q)
+        m.mod(r)
+    
+        let a=BIG(z)
+        a.mod(m)
+    
+        let b=BIG(z)
+        b.div(m);
+    
+
+    
+        var c=g1.trace()
+//        g2.copy(g1)
+        g2.frob(f)
+        let cp=g2.trace()
+        g1.conj()
+        g2.mul(g1)
+        let cpm1=g2.trace()
+        g2.mul(g1)
+        let cpm2=g2.trace()
+    
+        c=c.xtr_pow2(cp,cpm1,cpm2,a,b)
+ */     
+        let t=mpin_hash(sha,c,W)
+
+        for i in 0 ..< ECP.AESKEY {CK[i]=t[i]}
+    
+        return 0
+    }
+    // calculate common key on server side
+    // Z=r.A - no time permits involved
+    
+    static public func SERVER_KEY(_ sha:Int,_ Z:[UInt8],_ SST:[UInt8],_ W:[UInt8],_ H:[UInt8],_ HID:[UInt8],_ xID:[UInt8],_ xCID:[UInt8]?,_ SK:inout [UInt8]) -> Int
+    {
+   //     var t=[UInt8](count:EFS,repeatedValue:0)
+    
+        let sQ=ECP4.fromBytes(SST)
+        if sQ.is_infinity() {return INVALID_POINT}
+        var R=ECP.fromBytes(Z)
+        if R.is_infinity() {return INVALID_POINT}
+        var A=ECP.fromBytes(HID)
+        if A.is_infinity() {return INVALID_POINT}
+    
+        var U:ECP
+        if xCID != nil
+            {U=ECP.fromBytes(xCID!)}
+        else
+            {U=ECP.fromBytes(xID)}
+        
+        if U.is_infinity() {return INVALID_POINT}
+    
+        let w=BIG.fromBytes(W)
+        let h=BIG.fromBytes(H)
+        A=PAIR192.G1mul(A,h)
+        R.add(A); //R.affine()
+
+        U=PAIR192.G1mul(U,w)
+        var g=PAIR192.ate(sQ,R)
+        g=PAIR192.fexp(g)
+    
+        let c=g.trace()
+        
+        let t=mpin_hash(sha,c,U)
+ 
+        for i in 0 ..< ECP.AESKEY {SK[i]=t[i]}
+    
+        return 0
+    }
+    
+    // return time since epoch
+    static public func GET_TIME() -> Int32
+    {
+        let date=Date()
+        return (Int32(date.timeIntervalSince1970))
+    }
+
+    // Generate Y = H(epoch, xCID/xID)
+    static public func GET_Y(_ sha:Int,_ TimeValue:Int32,_ xCID:[UInt8],_ Y:inout [UInt8])
+    {
+        let h = MPIN192.hashit(sha,TimeValue,xCID)
+        var y = BIG.fromBytes(h)
+        let q=BIG(ROM.CURVE_Order)
+        y.mod(q)
+    //if ROM.AES_S>0
+    //{
+    //  y.mod2m(2*ROM.AES_S)
+    //}
+        y.toBytes(&Y)
+    }
+    // One pass MPIN Client
+    static public func CLIENT(_ sha:Int,_ date:Int32,_ CLIENT_ID:[UInt8],_ RNG: inout RAND?,_ X:inout [UInt8],_ pin:Int32,_ TOKEN:[UInt8],_  SEC:inout [UInt8],_ xID:inout [UInt8]?,_ xCID:inout [UInt8]?,_ PERMIT:[UInt8]?,_ TimeValue:Int32,_ Y:inout [UInt8]) -> Int
+    {
+        var rtn=0
+        //var xID=xID 
+  
+        rtn = MPIN192.CLIENT_1(sha,date,CLIENT_ID,&RNG,&X,pin,TOKEN,&SEC,&xID,&xCID,PERMIT!)
+
+        if rtn != 0 {return rtn}
+    
+        if date==0 {MPIN192.GET_Y(sha,TimeValue,xID!,&Y)}
+        else {MPIN192.GET_Y(sha,TimeValue,xCID!,&Y)}
+    
+        rtn = MPIN192.CLIENT_2(X,Y,&SEC)
+        if (rtn != 0) {return rtn}
+    
+        return 0
+    }
+    // One pass MPIN Server
+    static public func SERVER(_ sha:Int,_ date:Int32,_ HID:inout [UInt8],_ HTID:inout [UInt8]?,_ Y:inout [UInt8],_ SST:[UInt8],_ xID:[UInt8]?,_ xCID:[UInt8],_ SEC:[UInt8],_ E:inout [UInt8]?,_ F:inout [UInt8]?,_ CID:[UInt8],_ TimeValue:Int32) -> Int
+    {
+        var rtn=0
+    
+        var pID:[UInt8]
+        if date == 0
+            {pID = xID!}
+        else
+            {pID = xCID}
+    
+        SERVER_1(sha,date,CID,&HID,&HTID);
+    
+        GET_Y(sha,TimeValue,pID,&Y);
+    
+        rtn = SERVER_2(date,HID,HTID!,Y,SST,xID,xCID,SEC,&E,&F);
+        if rtn != 0 {return rtn}
+    
+        return 0
+    }
+   
+}
+ 
+
+
+
diff --git a/version3/swift/mpin256.swift b/version3/swift/mpin256.swift
new file mode 100644
index 0000000..60bd8c5
--- /dev/null
+++ b/version3/swift/mpin256.swift
@@ -0,0 +1,816 @@
+/*
+	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.
+*/
+
+//
+//  mpin256.swift
+//
+//  Created by Michael Scott on 08/07/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+import Foundation
+import amcl
+
+public struct MPIN256
+{
+    static public let EFS=Int(BIG.MODBYTES)
+    static public let EGS=Int(BIG.MODBYTES)
+    //static public let PAS:Int=16
+    static let INVALID_POINT:Int = -14
+    static let BAD_PARAMS:Int = -11
+    static let WRONG_ORDER:Int = -18
+    static public let BAD_PIN:Int = -19
+    static public let SHA256=32
+    static public let SHA384=48
+    static public let SHA512=64
+    
+    /* Configure your PIN here */
+    
+    static let MAXPIN:Int32 = 10000  // PIN less than this
+    static let PBLEN:Int32 = 14      // Number of bits in PIN
+    static let TS:Int = 10         // 10 for 4 digit PIN, 14 for 6-digit PIN - 2^TS/TS approx = sqrt(MAXPIN)
+    static let TRAP:Int = 200      // 200 for 4 digit PIN, 2000 for 6-digit PIN  - approx 2*sqrt(MAXPIN)
+
+   
+    private static func mpin_hash(_ sha:Int,_ c: FP16,_ U: ECP) -> [UInt8]
+    {
+        var w=[UInt8](repeating: 0,count: EFS)
+        var t=[UInt8](repeating: 0,count: 18*EFS)
+        var h=[UInt8]()
+        
+        c.geta().geta().geta().getA().toBytes(&w); for i in 0 ..< EFS {t[i]=w[i]}
+        c.geta().geta().geta().getB().toBytes(&w); for i in EFS ..< 2*EFS {t[i]=w[i-EFS]}
+        c.geta().geta().getb().getA().toBytes(&w); for i in 2*EFS ..< 3*EFS {t[i]=w[i-2*EFS]}
+        c.geta().geta().getb().getB().toBytes(&w); for i in 3*EFS ..< 4*EFS {t[i]=w[i-3*EFS]}
+
+        c.geta().getb().geta().getA().toBytes(&w); for i in 4*EFS ..< 5*EFS {t[i]=w[i-4*EFS]}
+        c.geta().getb().geta().getB().toBytes(&w); for i in 5*EFS ..< 6*EFS {t[i]=w[i-5*EFS]}
+        c.geta().getb().getb().getA().toBytes(&w); for i in 6*EFS ..< 7*EFS {t[i]=w[i-6*EFS]}
+        c.geta().getb().getb().getB().toBytes(&w); for i in 7*EFS ..< 8*EFS {t[i]=w[i-7*EFS]}
+
+        c.getb().geta().geta().getA().toBytes(&w); for i in 8*EFS ..< 9*EFS {t[i]=w[i-8*EFS]}
+        c.getb().geta().geta().getB().toBytes(&w); for i in 9*EFS ..< 10*EFS {t[i]=w[i-9*EFS]}
+        c.getb().geta().getb().getA().toBytes(&w); for i in 10*EFS ..< 11*EFS {t[i]=w[i-10*EFS]}
+        c.getb().geta().getb().getB().toBytes(&w); for i in 11*EFS ..< 12*EFS {t[i]=w[i-11*EFS]}
+
+        c.getb().getb().geta().getA().toBytes(&w); for i in 12*EFS ..< 13*EFS {t[i]=w[i-12*EFS]}
+        c.getb().getb().geta().getB().toBytes(&w); for i in 13*EFS ..< 14*EFS {t[i]=w[i-13*EFS]}
+        c.getb().getb().getb().getA().toBytes(&w); for i in 14*EFS ..< 15*EFS {t[i]=w[i-14*EFS]}
+        c.getb().getb().getb().getB().toBytes(&w); for i in 15*EFS ..< 16*EFS {t[i]=w[i-15*EFS]}
+
+
+
+        U.getX().toBytes(&w); for i in 16*EFS ..< 17*EFS {t[i]=w[i-16*EFS]}
+        U.getY().toBytes(&w); for i in 17*EFS ..< 18*EFS {t[i]=w[i-17*EFS]}
+        
+        if sha==SHA256
+        {
+            var H=HASH256()
+            H.process_array(t)
+            h=H.hash()
+        }
+        if sha==SHA384
+        {
+            var H=HASH384()
+            H.process_array(t)
+            h=H.hash()
+        }
+        if sha==SHA512
+        {
+            var H=HASH512()
+            H.process_array(t)
+            h=H.hash()
+        }
+        if h.isEmpty {return h}
+        var R=[UInt8](repeating: 0,count: ECP.AESKEY)
+        for i in 0 ..< ECP.AESKEY {R[i]=h[i]}
+        return R
+    }
+    
+    // Hash number (optional) and string to point on curve
+    
+    private static func hashit(_ sha:Int,_ n:Int32,_ ID:[UInt8]) -> [UInt8]
+    {
+        var R=[UInt8]()
+        if sha==SHA256
+        {
+            var H=HASH256()
+            if n != 0 {H.process_num(n)}
+            H.process_array(ID)
+            R=H.hash()
+        }
+        if sha==SHA384
+        {
+            var H=HASH384()
+            if n != 0 {H.process_num(n)}
+            H.process_array(ID)
+            R=H.hash()
+        }
+        if sha==SHA512
+        {
+            var H=HASH512()
+            if n != 0 {H.process_num(n)}
+            H.process_array(ID)
+            R=H.hash()
+        }
+        if R.isEmpty {return R}
+        let RM=Int(BIG.MODBYTES)
+        var W=[UInt8](repeating: 0,count: RM)
+        if sha >= RM
+        {
+            for i in 0 ..< RM {W[i]=R[i]}
+        }
+        else
+        {
+        for i in 0 ..< sha {W[i+RM-sha]=R[i]}
+
+            //for i in 0 ..< sha {W[i]=R[i]}
+        }
+        return W
+    }
+    
+    
+    // return time in slots since epoch
+    static public func today() -> Int32
+    {
+        let date=Date()
+        return (Int32(date.timeIntervalSince1970/(60*1440)))
+    }
+
+    // these next two functions help to implement elligator squared - http://eprint.iacr.org/2014/043
+    // maps a random u to a point on the curve
+    static func map(_ u:BIG,_ cb:Int) -> ECP
+    {
+        var x=BIG(u)
+        let p=BIG(ROM.Modulus)
+        x.mod(p)
+        var P=ECP(x,cb)
+        while (true)
+        {
+            if !P.is_infinity() {break}
+            x.inc(1);  x.norm()
+            P=ECP(x,cb)
+        }
+        return P
+    }
+
+    // returns u derived from P. Random value in range 1 to return value should then be added to u
+    static func unmap(_ u:inout BIG,_ P:ECP) -> Int
+    {
+        let s=P.getS()
+        var r:Int32=0
+        let x=P.getX()
+        u.copy(x)
+        var R=ECP()
+        while (true)
+        {
+            u.dec(1); u.norm()
+            r += 1
+            R=ECP(u,s)
+            if !R.is_infinity() {break}
+        }
+        return Int(r)
+    }
+    
+    static public func HASH_ID(_ sha:Int,_ ID:[UInt8]) -> [UInt8]
+    {
+        return hashit(sha,0,ID)
+    }
+    
+    // these next two functions implement elligator squared - http://eprint.iacr.org/2014/043
+    // Elliptic curve point E in format (0x04,x,y} is converted to form {0x0-,u,v}
+    // Note that u and v are indistinguisible from random strings
+    static public func ENCODING(_ rng: inout RAND,_ E:inout [UInt8]) -> Int
+    {
+        var T=[UInt8](repeating: 0,count: EFS)
+    
+        for i in 0 ..< EFS {T[i]=E[i+1]}
+        var u=BIG.fromBytes(T);
+        for i in 0 ..< EFS {T[i]=E[i+EFS+1]}
+        var v=BIG.fromBytes(T)
+    
+        var P=ECP(u,v);
+        if P.is_infinity() {return INVALID_POINT}
+    
+        let p=BIG(ROM.Modulus)
+        u=BIG.randomnum(p,&rng)
+    
+        var su=rng.getByte();
+        su%=2
+    
+        let W=MPIN256.map(u,Int(su))
+        P.sub(W);
+        let sv=P.getS();
+        let rn=MPIN256.unmap(&v,P)
+        let m=rng.getByte();
+        let incr=1+Int(m)%rn
+        v.inc(incr)
+        E[0]=(su+UInt8(2*sv))
+        u.toBytes(&T)
+        for i in 0 ..< EFS {E[i+1]=T[i]}
+        v.toBytes(&T)
+        for i in 0 ..< EFS {E[i+EFS+1]=T[i]}
+    
+        return 0;
+    }
+
+    static public func DECODING(_ D:inout [UInt8]) -> Int
+    {
+        var T=[UInt8](repeating: 0,count: EFS)
+    
+        if (D[0]&0x04) != 0 {return INVALID_POINT}
+    
+        for i in 0 ..< EFS {T[i]=D[i+1]}
+        var u=BIG.fromBytes(T)
+        for i in 0 ..< EFS {T[i]=D[i+EFS+1]}
+        var v=BIG.fromBytes(T)
+    
+        let su=D[0]&1
+        let sv=(D[0]>>1)&1
+        let W=map(u,Int(su))
+        var P=map(v,Int(sv))
+        P.add(W)
+        u=P.getX()
+        v=P.getY()
+        D[0]=0x04
+        u.toBytes(&T);
+        for i in 0 ..< EFS {D[i+1]=T[i]}
+        v.toBytes(&T)
+        for i in 0 ..< EFS {D[i+EFS+1]=T[i]}
+    
+        return 0
+    }
+    // R=R1+R2 in group G1
+    static public func RECOMBINE_G1(_ R1:[UInt8],_ R2:[UInt8],_ R:inout [UInt8]) -> Int
+    {
+        var P=ECP.fromBytes(R1)
+        let Q=ECP.fromBytes(R2)
+    
+        if P.is_infinity() || Q.is_infinity() {return INVALID_POINT}
+    
+        P.add(Q)
+    
+        P.toBytes(&R,false)
+        return 0;
+    }
+    // W=W1+W2 in group G2
+    static public func RECOMBINE_G2(_ W1:[UInt8],_ W2:[UInt8],_  W:inout [UInt8]) -> Int
+    {
+        var P=ECP8.fromBytes(W1)
+        let Q=ECP8.fromBytes(W2)
+    
+        if P.is_infinity() || Q.is_infinity() {return INVALID_POINT}
+    
+        P.add(Q)
+        
+        P.toBytes(&W)
+        return 0
+    }
+    // create random secret S
+    static public func RANDOM_GENERATE(_ rng: inout RAND,_ S:inout [UInt8]) -> Int
+    {
+        let r=BIG(ROM.CURVE_Order)
+        let s=BIG.randomnum(r,&rng)
+    //if ROM.AES_S>0
+    //{
+    //  s.mod2m(2*ROM.AES_S)
+    //}    
+        s.toBytes(&S);
+        return 0;
+    }
+
+    // Extract PIN from TOKEN for identity CID
+    static public func EXTRACT_PIN(_ sha:Int,_ CID:[UInt8],_ pin:Int32,_ TOKEN:inout [UInt8]) -> Int
+    {
+        return MPIN256.EXTRACT_FACTOR(sha,CID,pin%MAXPIN,PBLEN,&TOKEN)
+    }
+
+    // Extract factor from TOKEN for identity CID
+    static public func EXTRACT_FACTOR(_ sha:Int,_ CID:[UInt8],_ factor:Int32,_ facbits:Int32,_ TOKEN:inout [UInt8]) -> Int
+    {
+        var P=ECP.fromBytes(TOKEN)
+        if P.is_infinity() {return INVALID_POINT}
+        let h=MPIN256.hashit(sha,0,CID)
+        var R=ECP.mapit(h)
+
+        R=R.pinmul(factor,facbits)
+        P.sub(R)
+    
+        P.toBytes(&TOKEN,false)
+    
+        return 0
+    }    
+
+    // ERestore factor to TOKEN for identity CID
+    static public func RESTORE_FACTOR(_ sha:Int,_ CID:[UInt8],_ factor:Int32,_ facbits:Int32,_ TOKEN:inout [UInt8]) -> Int
+    {
+        var P=ECP.fromBytes(TOKEN)
+        if P.is_infinity() {return INVALID_POINT}
+        let h=MPIN256.hashit(sha,0,CID)
+        var R=ECP.mapit(h)
+
+        R=R.pinmul(factor,facbits)
+        P.add(R)
+    
+        P.toBytes(&TOKEN,false)
+    
+        return 0
+    }    
+
+    // Extract PIN from TOKEN for identity CID
+    /*
+    static public func EXTRACT_PIN(_ sha:Int,_ CID:[UInt8],_ pin:Int32,_ TOKEN:inout [UInt8]) -> Int
+    {
+        let P=ECP.fromBytes(TOKEN)
+        if P.is_infinity() {return INVALID_POINT}
+        let h=MPIN256.hashit(sha,0,CID)
+        var R=ECP.mapit(h)
+
+        R=R.pinmul(pin%MAXPIN,MPIN256.PBLEN)
+        P.sub(R)
+    
+        P.toBytes(&TOKEN,false)
+    
+        return 0
+    }*/
+
+
+    // Implement step 2 on client side of MPin protocol
+    static public func CLIENT_2(_ X:[UInt8],_ Y:[UInt8],_ SEC:inout [UInt8]) -> Int
+    {
+        let r=BIG(ROM.CURVE_Order)
+        var P=ECP.fromBytes(SEC)
+        if P.is_infinity() {return INVALID_POINT}
+    
+        var px=BIG.fromBytes(X)
+        let py=BIG.fromBytes(Y)
+        px.add(py)
+        px.mod(r)
+     //   px.rsub(r)
+
+        P=PAIR256.G1mul(P,px)
+        P.neg()
+        P.toBytes(&SEC,false);
+      //  PAIR256.G1mul(P,px).toBytes(&SEC,false)
+        return 0
+    }
+    
+    // Implement step 1 on client side of MPin protocol
+    static public func CLIENT_1(_ sha:Int,_ date:Int32,_ CLIENT_ID:[UInt8],_ rng: inout RAND?,_ X:inout [UInt8],_ pin:Int32,_ TOKEN:[UInt8],_ SEC:inout [UInt8],_ xID:inout [UInt8]?,_ xCID:inout [UInt8]?,_ PERMIT:[UInt8]?) -> Int
+    {
+
+        let r=BIG(ROM.CURVE_Order)
+   //     let q=BIG(ROM.Modulus)
+        var x:BIG
+        if rng != nil
+        {
+            x=BIG.randomnum(r,&rng!)
+            //if ROM.AES_S>0
+            //{
+             //   x.mod2m(2*ROM.AES_S)
+            //}
+            x.toBytes(&X);
+        }
+        else
+        {
+            x=BIG.fromBytes(X);
+        }
+    //    var t=[UInt8](count:EFS,repeatedValue:0)
+
+        var h=MPIN256.hashit(sha,0,CLIENT_ID)
+        var P=ECP.mapit(h);
+    
+        var T=ECP.fromBytes(TOKEN);
+        if T.is_infinity() {return INVALID_POINT}
+    
+        var W=P.pinmul(pin%MPIN256.MAXPIN,MPIN256.PBLEN)
+        T.add(W)
+        if date != 0
+        {
+            W=ECP.fromBytes(PERMIT!)
+            if W.is_infinity() {return INVALID_POINT}
+            T.add(W);
+            h=MPIN256.hashit(sha,date,h)
+            W=ECP.mapit(h);
+            if xID != nil
+            {
+                P=PAIR256.G1mul(P,x)
+                P.toBytes(&xID!,false)
+                W=PAIR256.G1mul(W,x)
+                P.add(W)
+            }
+            else
+            {
+                P.add(W);
+                P=PAIR256.G1mul(P,x);
+            }
+            if xCID != nil {P.toBytes(&xCID!,false)}
+        }
+        else
+        {
+            if xID != nil
+            {
+                P=PAIR256.G1mul(P,x)
+                P.toBytes(&xID!,false)
+            }
+        }
+    
+    
+        T.toBytes(&SEC,false);
+        return 0;
+    }
+    // Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret
+    static public func GET_SERVER_SECRET(_ S:[UInt8],_ SST:inout [UInt8]) -> Int
+    {
+        var Q=ECP8.generator();
+    
+        let s=BIG.fromBytes(S)
+        Q=PAIR256.G2mul(Q,s)
+        Q.toBytes(&SST)
+        return 0
+    }
+ 
+    
+    //W=x*H(G);
+    //if RNG == NULL then X is passed in
+    //if RNG != NULL the X is passed out
+    //if type=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve
+    
+    static public func GET_G1_MULTIPLE(_ rng: inout RAND?,_ type:Int,_ X:inout [UInt8],_ G:[UInt8],_ W:inout [UInt8]) -> Int
+    {
+        var x:BIG
+        let r=BIG(ROM.CURVE_Order)
+        if rng != nil
+        {
+            x=BIG.randomnum(r,&rng!)
+            //if ROM.AES_S>0
+            //{
+            //    x.mod2m(2*ROM.AES_S)
+            //}
+            x.toBytes(&X)
+        }
+        else
+        {
+            x=BIG.fromBytes(X);
+        }
+        var P:ECP
+        if type==0
+        {
+            P=ECP.fromBytes(G)
+            if P.is_infinity() {return INVALID_POINT}
+        }
+        else
+            {P=ECP.mapit(G)}
+    
+        PAIR256.G1mul(P,x).toBytes(&W,false)
+        return 0;
+    }
+    // Client secret CST=S*H(CID) where CID is client ID and S is master secret
+    // CID is hashed externally
+    static public func GET_CLIENT_SECRET(_ S:inout [UInt8],_ CID:[UInt8],_ CST:inout [UInt8]) -> Int
+    {
+        var RNG : RAND? = nil        
+        return GET_G1_MULTIPLE(&RNG,1,&S,CID,&CST)
+    }
+    // Time Permit CTT=S*(date|H(CID)) where S is master secret
+    static public func GET_CLIENT_PERMIT(_ sha:Int,_ date:Int32,_ S:[UInt8],_ CID:[UInt8],_ CTT:inout [UInt8]) -> Int
+    {
+        let h=MPIN256.hashit(sha,date,CID)
+        let P=ECP.mapit(h)
+    
+        let s=BIG.fromBytes(S)
+        PAIR256.G1mul(P,s).toBytes(&CTT,false)
+        return 0;
+    }
+  
+    // Outputs H(CID) and H(T|H(CID)) for time permits. If no time permits set HID=HTID
+    static public func SERVER_1(_ sha:Int,_ date:Int32,_ CID:[UInt8],_ HID:inout [UInt8],_ HTID:inout [UInt8]?)
+    {
+        var h=MPIN256.hashit(sha,0,CID)
+        var P=ECP.mapit(h)
+
+        P.toBytes(&HID,false)
+        if date != 0
+        {
+       //     if HID != nil {P.toBytes(&HID!,false)}
+            h=hashit(sha,date,h)
+            let R=ECP.mapit(h)
+            P.add(R)
+            P.toBytes(&HTID!,false)
+        }
+        //else {P.toBytes(&HID!,false)}
+    }
+    // Implement step 2 of MPin protocol on server side
+    static public func SERVER_2(_ date:Int32,_ HID:[UInt8]?,_ HTID:[UInt8]?,_ Y:[UInt8],_ SST:[UInt8],_ xID:[UInt8]?,_ xCID:[UInt8]?,_ mSEC:[UInt8],_ E:inout [UInt8]?,_ F:inout [UInt8]?) -> Int
+    { 
+      //  _=BIG(ROM.Modulus);
+        let Q=ECP8.generator();
+        let sQ=ECP8.fromBytes(SST)
+        if sQ.is_infinity() {return INVALID_POINT}
+        var R:ECP
+        if date != 0
+            {R=ECP.fromBytes(xCID!)}
+        else
+        {
+            if xID==nil {return MPIN256.BAD_PARAMS}
+            R=ECP.fromBytes(xID!)
+        }
+        if R.is_infinity() {return INVALID_POINT}
+        let y=BIG.fromBytes(Y)
+        var P:ECP
+        if date != 0 {P=ECP.fromBytes(HTID!)}
+        else
+        {
+            if HID==nil {return MPIN256.BAD_PARAMS}
+            P=ECP.fromBytes(HID!)
+        }
+    
+        if P.is_infinity() {return INVALID_POINT}
+    
+        P=PAIR256.G1mul(P,y)
+        P.add(R); //P.affine()
+        R=ECP.fromBytes(mSEC)
+        if R.is_infinity() {return MPIN256.INVALID_POINT}
+
+    
+        var g=PAIR256.ate2(Q,R,sQ,P)
+        g=PAIR256.fexp(g)
+    
+        if !g.isunity()
+        {
+            if HID != nil && xID != nil && E != nil && F != nil
+            {
+                g.toBytes(&E!)
+                if date != 0
+                {
+                    P=ECP.fromBytes(HID!)
+                    if P.is_infinity() {return MPIN256.INVALID_POINT}
+                    R=ECP.fromBytes(xID!)
+                    if R.is_infinity() {return MPIN256.INVALID_POINT}
+    
+                    P=PAIR256.G1mul(P,y);
+                    P.add(R); //P.affine()
+                }
+                g=PAIR256.ate(Q,P);
+                g=PAIR256.fexp(g);
+                g.toBytes(&F!);
+            }
+            return MPIN256.BAD_PIN;
+        }
+    
+        return 0
+    }
+    // Pollards kangaroos used to return PIN error
+    static public func KANGAROO(_ E:[UInt8]?,_ F:[UInt8]?) -> Int
+    {
+        var ge=FP48.fromBytes(E!)
+        var gf=FP48.fromBytes(F!)
+        var distance=[Int]();
+        var t=FP48(gf);
+        var table=[FP48]()
+        
+        var s:Int=1
+        for _ in 0 ..< Int(TS)
+        {
+            distance.append(s)
+            table.append(FP48(t))
+            s*=2
+            t.usqr()
+ 
+        }
+        t.one()
+        var dn:Int=0
+        for _ in 0 ..< TRAP
+        {
+            var lsbs=BIG(t.geta().geta().geta().geta().getA())
+            let i=Int(lsbs.lastbits(8))%TS
+            t.mul(table[i])
+            dn+=distance[i]
+        }
+        gf.copy(t); gf.conj()
+        var steps=0; var dm:Int=0
+        var res=0;
+        while (dm-dn<Int(MAXPIN))
+        {
+            steps += 1;
+            if steps>4*TRAP {break}
+            var lsbs=BIG(ge.geta().geta().geta().geta().getA())
+            let i=Int(lsbs.lastbits(8))%TS
+            ge.mul(table[i])
+            dm+=distance[i]
+            if (ge.equals(t))
+            {
+                res=dm-dn;
+                break;
+            }
+            if (ge.equals(gf))
+            {
+                res=dn-dm
+                break
+            }
+    
+        }
+        if steps>4*TRAP || dm-dn>=Int(MAXPIN) {res=0 }    // Trap Failed  - probable invalid token
+        return res
+    }
+    // Functions to support M-Pin Full
+    
+    static public func PRECOMPUTE(_ TOKEN:[UInt8],_ CID:[UInt8],_ G1:inout [UInt8],_ G2:inout [UInt8]) -> Int
+    {
+        let T=ECP.fromBytes(TOKEN);
+        if T.is_infinity() {return INVALID_POINT}
+    
+        let P=ECP.mapit(CID)
+    
+        let Q=ECP8.generator();
+    
+        var g=PAIR256.ate(Q,T)
+        g=PAIR256.fexp(g)
+        g.toBytes(&G1)
+    
+        g=PAIR256.ate(Q,P)
+        g=PAIR256.fexp(g)
+        g.toBytes(&G2)
+    
+        return 0
+    }
+    
+    static public func HASH_ALL(_ sha:Int,_ HID:[UInt8],_ xID:[UInt8]?,_ xCID:[UInt8]?,_ SEC:[UInt8],_ Y:[UInt8],_ R:[UInt8],_ W:[UInt8]  ) -> [UInt8]
+    {
+        var T=[UInt8](repeating: 0,count: 10*EFS+4)
+        var tlen=0
+
+        for i in 0 ..< HID.count  {T[i]=HID[i]}
+        tlen+=HID.count
+        if xCID != nil {
+            for i in 0 ..< xCID!.count  {T[i+tlen]=xCID![i]}
+            tlen+=xCID!.count
+        } else {
+            for i in 0 ..< xID!.count {T[i+tlen]=xID![i]}
+            tlen+=xID!.count
+        }
+        for i in 0 ..< SEC.count {T[i+tlen]=SEC[i]}
+        tlen+=SEC.count;
+        for i in 0 ..< Y.count {T[i+tlen]=Y[i]}
+        tlen+=Y.count;
+        for i in 0 ..< R.count {T[i+tlen]=R[i]}
+        tlen+=R.count;
+        for i in 0 ..< W.count {T[i+tlen]=W[i]}
+        tlen+=W.count;
+
+        return hashit(sha,0,T);
+    }
+
+    // calculate common key on client side
+    // wCID = w.(A+AT)
+    static public func CLIENT_KEY(_ sha:Int,_ G1:[UInt8],_ G2:[UInt8],_ pin:Int32,_ R:[UInt8],_ X:[UInt8],_ H:[UInt8],_ wCID:[UInt8],_ CK:inout [UInt8]) -> Int
+    {
+        var g1=FP48.fromBytes(G1)
+        var g2=FP48.fromBytes(G2)
+        var z=BIG.fromBytes(R)
+        let x=BIG.fromBytes(X)
+        let h=BIG.fromBytes(H)
+    
+        var W=ECP.fromBytes(wCID)
+        if W.is_infinity() {return INVALID_POINT}
+    
+        W=PAIR256.G1mul(W,x)
+    
+     //   let f=FP2(BIG(ROM.Fra),BIG(ROM.Frb))
+        let r=BIG(ROM.CURVE_Order)
+     //   let q=BIG(ROM.Modulus)
+    
+        z.add(h)   // new
+        z.mod(r)
+
+        g2.pinpow(pin,PBLEN)
+        g1.mul(g2)
+
+        let c=g1.compow(z,r)
+
+        let t=mpin_hash(sha,c,W)
+
+        for i in 0 ..< ECP.AESKEY {CK[i]=t[i]}
+    
+        return 0
+    }
+    // calculate common key on server side
+    // Z=r.A - no time permits involved
+    
+    static public func SERVER_KEY(_ sha:Int,_ Z:[UInt8],_ SST:[UInt8],_ W:[UInt8],_ H:[UInt8],_ HID:[UInt8],_ xID:[UInt8],_ xCID:[UInt8]?,_ SK:inout [UInt8]) -> Int
+    {
+   //     var t=[UInt8](count:EFS,repeatedValue:0)
+    
+        let sQ=ECP8.fromBytes(SST)
+        if sQ.is_infinity() {return INVALID_POINT}
+        var R=ECP.fromBytes(Z)
+        if R.is_infinity() {return INVALID_POINT}
+        var A=ECP.fromBytes(HID)
+        if A.is_infinity() {return INVALID_POINT}
+    
+        var U:ECP
+        if xCID != nil
+            {U=ECP.fromBytes(xCID!)}
+        else
+            {U=ECP.fromBytes(xID)}
+        
+        if U.is_infinity() {return INVALID_POINT}
+    
+        let w=BIG.fromBytes(W)
+        let h=BIG.fromBytes(H)
+        A=PAIR256.G1mul(A,h)
+        R.add(A); //R.affine()
+
+        U=PAIR256.G1mul(U,w)
+        var g=PAIR256.ate(sQ,R)
+        g=PAIR256.fexp(g)
+    
+        let c=g.trace()
+        
+        let t=mpin_hash(sha,c,U)
+ 
+        for i in 0 ..< ECP.AESKEY {SK[i]=t[i]}
+    
+        return 0
+    }
+    
+    // return time since epoch
+    static public func GET_TIME() -> Int32
+    {
+        let date=Date()
+        return (Int32(date.timeIntervalSince1970))
+    }
+
+    // Generate Y = H(epoch, xCID/xID)
+    static public func GET_Y(_ sha:Int,_ TimeValue:Int32,_ xCID:[UInt8],_ Y:inout [UInt8])
+    {
+        let h = MPIN256.hashit(sha,TimeValue,xCID)
+        var y = BIG.fromBytes(h)
+        let q=BIG(ROM.CURVE_Order)
+        y.mod(q)
+    //if ROM.AES_S>0
+    //{
+    //  y.mod2m(2*ROM.AES_S)
+    //}
+        y.toBytes(&Y)
+    }
+    // One pass MPIN Client
+    static public func CLIENT(_ sha:Int,_ date:Int32,_ CLIENT_ID:[UInt8],_ RNG: inout RAND?,_ X:inout [UInt8],_ pin:Int32,_ TOKEN:[UInt8],_  SEC:inout [UInt8],_ xID:inout [UInt8]?,_ xCID:inout [UInt8]?,_ PERMIT:[UInt8]?,_ TimeValue:Int32,_ Y:inout [UInt8]) -> Int
+    {
+        var rtn=0
+        //var xID=xID 
+  
+        rtn = MPIN256.CLIENT_1(sha,date,CLIENT_ID,&RNG,&X,pin,TOKEN,&SEC,&xID,&xCID,PERMIT!)
+
+        if rtn != 0 {return rtn}
+    
+        if date==0 {MPIN256.GET_Y(sha,TimeValue,xID!,&Y)}
+        else {MPIN256.GET_Y(sha,TimeValue,xCID!,&Y)}
+    
+        rtn = MPIN256.CLIENT_2(X,Y,&SEC)
+        if (rtn != 0) {return rtn}
+    
+        return 0
+    }
+    // One pass MPIN Server
+    static public func SERVER(_ sha:Int,_ date:Int32,_ HID:inout [UInt8],_ HTID:inout [UInt8]?,_ Y:inout [UInt8],_ SST:[UInt8],_ xID:[UInt8]?,_ xCID:[UInt8],_ SEC:[UInt8],_ E:inout [UInt8]?,_ F:inout [UInt8]?,_ CID:[UInt8],_ TimeValue:Int32) -> Int
+    {
+        var rtn=0
+    
+        var pID:[UInt8]
+        if date == 0
+            {pID = xID!}
+        else
+            {pID = xCID}
+    
+        SERVER_1(sha,date,CID,&HID,&HTID);
+    
+        GET_Y(sha,TimeValue,pID,&Y);
+    
+        rtn = SERVER_2(date,HID,HTID!,Y,SST,xID,xCID,SEC,&E,&F);
+        if rtn != 0 {return rtn}
+    
+        return 0
+    }
+   
+}
+ 
+
+
+
diff --git a/version3/swift/nhs.swift b/version3/swift/nhs.swift
new file mode 100644
index 0000000..333df50
--- /dev/null
+++ b/version3/swift/nhs.swift
@@ -0,0 +1,550 @@
+/*
+	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.
+*/
+
+//
+//  nhs.swift
+//
+
+//import Foundation
+//import Darwin
+
+//import amcl
+
+/* NewHope Simple API high-level functions  */
+
+final public class NHS
+{
+   	static let PRIME:Int32 = 0x3001	// q in Hex
+	static let LGN:Int = 10	// Degree n=2^LGN
+
+	static let ND:UInt32 = 0xF7002FFF	// 1/(R-q) mod R
+	static let ONE: Int32 = 0x2AC8	// R mod q
+	static let R2MODP: UInt64 = 0x1620	// R^2 mod q
+
+
+	static let DEGREE: Int = (1<<LGN)
+	static let WL: Int32 = 32
+
+	static let inv: Int32 =  0xeab
+	static let invpr: Int32 = 0x2c2a
+
+static let roots:[Int32] = [0x2ac8,0x2baf,0x299b,0x685,0x2f04,0x158d,0x2d49,0x24b5,0x1edc,0xab3,0x2a95,0x24d,0x3cb,0x6a8,0x12f9,0x15ba,0x1861,0x2a89,0x1c5c,0xbe6,0xc1e,0x2024,0x207,0x19ce,0x2710,0x1744,0x18bc,0x2cd7,0x396,0x18d5,0x1c45,0xc4,0x21a6,0xe03,0x2b3c,0x2d91,0xc5d,0x432,0x1fbc,0xcae,0x2512,0x2979,0x3b2,0x714,0xb2e,0x1a97,0x1a03,0x1bcd,0x2216,0x2701,0xa,0x263c,0x1179,0x200c,0x2d08,0x1c34,0x291,0x2c99,0x2a5a,0x723,0xb1d,0x1ccc,0x1fb6,0x2f58,0x2bfe,0x1cda,0x2a0,0x5f1,0x2de,0x1fc7,0x1ea8,0x1719,0x2fa7,0x27ec,0x20ff,0x12c0,0x1ac1,0x2232,0x2f9b,0xd3e,0x2aed,0x15f0,0x11e8,0xed0,0x26a,0x1de5,0xa3f,0xf43,0xebf,0x204e,0xac7,0x2d9c,0x5ea,0x25d1,0xb6,0x49c,0x995,0x2555,0x26e2,0x100,0x1878,0x5aa,0x2e10,0x271c,0xcb,0x1b4c,0x2fb8,0x25b7,0x1543,0x2c7b,0x241a,0x2223,0x20ca,0x24ed,0x137,0x1b65,0x1dc2,0x7c7,0x2ec3,0xd0c,0x1169,0x1c7a,0x1ea1,0xf89,0x2199,0x291d,0x1088,0x2046,0x256d,0x2bc7,0x2e9b,0x41f,0x1b55,0x2b38,0xd0,0x2e6a,0x1755,0x6bc,0x2724,0x3ba,0x222e,0x2c5c,0x2da5,0x213c,0x10fe,0x169a,0x1552,0x5d3,0x300,0x1b5d,0x1342,0x2004,0x256f,0x2039,0x667,0x23b5,0x1123,0xdb,0x2da0,0xe1e,0x2f54,0x2767,0x154a,0x40a,0x11d3,0x2821,0xc09,0x974,0x694,0xfbf,0x27ba,0x132,0x83f,0x2d06,0x10e,0x183f,0x29ae,0x28c3,0x2dc9,0x1144,0x2c70,0x2a4a,0xf3c,0x1e32,0x1171,0x1e43,0xdd4,0x2ddf,0x28d2,0xfac,0x3c4,0x2f19,0x10a6,0x2f7,0xe1d,0x828,0x138f,0x1332,0xfab,0xcf6,0x13f8,0x24a0,0x112d,0x2717,0x6e7,0x1044,0x36e,0xfe8,0x6a,0xba7,0x1d69,0x29ec,0x23b2,0xaee,0x16df,0x1068,0x1a7e,0x253f,0x24c,0xb33,0x2683,0x15ce,0x1ad3,0x1a36,0xc96,0xaea,0x260a,0xce,0x28b1,0xe4f,0x2b11,0x5f8,0x1fc4,0xe77,0x2366,0x11f9,0x153c,0x24eb,0x20cd,0x1398,0x22,0x2b97,0x249b,0x8eb,0x12b2,0x2fe3,0x29c1,0x1b00,0x2663,0xeaa,0x2e06,0xe0,0x1569,0x10f5,0x284e,0xa38,0x201d,0x1c53,0x1681,0x1f6f,0x2f95,0x2fe8,0xacb,0x1680,0x17fd,0x2c39,0x165a,0x10bb,0x29d8,0x2622,0x1196,0x884,0x2a79,0x140e,0x2d80,0x6fa,0x11b2,0x26c4,0x355,0x1054,0x29e9,0x23ed,0xbe3,0x24fa,0x1fb3,0x10ac,0x2919,0x2584,0x10a4,0xe85,0x650,0x1893,0x1dc1,0xd8e,0x12dc,0x2d42,0x284d,0xfff,0x250f,0xacd,0x13c3,0x6cc,0x1a79,0x1221,0x2614,0x270a,0x1ea,0x155,0x2818,0x222c,0x2e5b,0x25d8,0x1dbf,0x191c,0xb0f,0xdac,0x1082,0x12ef,0x11b6,0xfa8,0x2b72,0x159d,0x209e,0x31b,0x2c7c,0x14f7,0xe09,0x1bb2,0x1ec7,0x2404,0x20ae,0x6ad,0xed6,0x2b70,0x1c7b,0x18d1,0x2732,0x12da,0xd56,0x5c1,0x1648,0x18b7,0x1605,0x1bc4,0x280,0x2ece,0xc,0x1aae,0x1c4,0x1cdb,0x22d6,0x21d8,0x257c,0x51f,0x211b,0xff,0x2ee0,0x2585,0xe1,0x2c35,0x26db,0x2971,0x2208,0x17e1,0x21be,0x135e,0x28d6,0x2891,0x1689,0x2138,0xb86,0x2e3a,0x1204,0x2d10,0x2324,0xf3f,0x2508,0x33d,0xcb2,0x292a,0xe27,0x2e64,0x29f8,0x2d46,0x9b7,0x20eb,0x1b7c,0x9eb,0x2b2a,0x58c,0x27d0,0x121b,0x272e,0x29f6,0x2dbd,0x2697,0x2aac,0xd6f,0x1c67,0x2c5b,0x108d,0x363,0x249d,0x2d5e,0x2fd,0x2cb2,0x1f8f,0x20a4,0xa19,0x2ac9,0x19b1,0x1581,0x17a2,0x29eb,0x1b72,0x13b0,0xee4,0xa8f,0x2315,0x5e6,0x951,0x2e29,0xdad,0x1f2b,0x224e,0x37f,0x1a72,0xa91,0x1407,0x2df9,0x3ad,0x23f7,0x1a24,0x1d2a,0x234b,0x1df3,0x1143,0x7ff,0x1a6d,0x2774,0x2690,0x2ab5,0x586,0x2781,0x2009,0x2fdd,0x2881,0x399,0x2fb6,0x144,0x137f,0xfa0,0x2e4c,0x1c7f,0x2fac,0xb09,0x1264,0x127b,0x198c,0x2b40,0x230,0x1cf4,0x180b,0xb58,0x144a,0x2aec,0xfb,0x2602,0x14ee,0x783,0x1098,0x23d8,0x203,0xe9,0x108a,0x14b8,0xeec,0xc58,0x1248,0x243c,0x28aa,0x6bf,0x27c4,0x276e,0x19b8,0x1d11,0x2e16,0x472,0x1464,0x24b9,0x662,0x1097,0x2067,0x20d6,0x171c,0x4,0x682,0x17bb,0x1186,0x4f2,0x3ff,0x2a43,0x1dc7,0x1ae5,0x8cc,0x2e7c,0x2ef8,0x2ae0,0x2904,0xed4,0x6c5,0x14ae,0xb72,0x11c3,0x337,0x2da3,0x2916,0x6d8,0x1cf9,0x10ee,0x1800,0x1ae4,0xa0d,0x101b,0x1a8d,0x2e98,0x24cd,0x813,0x1aa4,0x9b9,0x680,0x2349,0x24d1,0x20f8,0xe31,0x249f,0x216b,0x12d9,0x1d21,0x19db,0x191a,0x1dd0,0x5df,0x55c,0x2b86,0x213,0xe9e,0x1ef1,0x268a,0x1d5e,0x1e20,0x28c1,0x1379,0x249,0x19de,0x18b,0x1e41,0x2a1e,0x2612,0x297,0x2e96,0x2102,0x46,0x1b9f,0x1a4d,0x2050,0x1b32,0x568,0x11f7,0x1829,0x870,0x1f4,0x1dca,0x990,0x1df6,0x2b62,0x13ec,0x9f2,0x1260,0x2997,0x1412,0x1e6d,0x1694,0x11ac,0x2d8b,0x276f,0x26f5,0x233e,0x2b44,0x2f5a,0x2d37,0x2cb1,0xc75,0x98d,0x1d56,0x7ae,0x10e6,0x113f,0x17b8,0xad3,0x737,0x221e,0x1b70,0x1f3e,0x2966,0x18b2,0x4fa,0x2044,0x1312,0x154e,0x2029,0x700,0x1b45,0x27a6,0x226a,0x21bf,0x58d,0x2f11,0x2e02,0x17fc,0x4d2,0x1757,0xcb1,0x2ef1,0x2582,0x1276,0x881,0x2fc0,0x104a,0x670,0x274f,0x2b53,0x19dd,0x752,0x1663,0xcbd,0x2b2b,0x2fc6,0x13b6,0x21e6,0x15f6,0x126b,0x2637,0x1cd9,0x2f50,0xe82,0x5b0,0x24e0,0x1350,0x2f24,0x21f7,0x1a16,0x2f3e,0x167e,0x1f7d,0x28a0,0x16f0,0xe33,0x53b,0x28c5,0x1500,0x2f88,0x26cc,0x2018,0x1604,0x218b,0x2cd1,0x9ee,0x17f3,0x5fd,0x1f5a,0x2d0,0x2b46,0x23cc,0x503,0x1c46,0x1cc3,0x28e2,0x243e,0x122b,0x2e0c,0xe37,0x2611,0x85e,0x9b8,0x1b24,0x762,0x19b6,0x3bc,0x2d50,0x2079,0x18da,0x170a,0x800,0xaa2,0x135a,0x1a15,0x13d1,0xca,0x2113,0x2db9,0xdb2,0x1a5c,0x29a9,0x1488,0x14c1,0x2c9,0x917,0x28e7,0x265c,0xdab,0x2ab9,0x2bc6,0x105b,0x1839,0x219c,0x50,0x11da,0x1802,0xf56,0x2e6,0x2190,0xddb,0x56e,0x9d9,0x1c81,0x1016,0x12d6,0x296f,0x14b4,0x1014,0x1e64,0x1d90,0x89f,0x2bc2,0x2777,0x2819,0x1c65,0x1a41,0x5a2,0x2cd2,0x427,0xd71,0x29c8,0x1e58,0x53f,0x7c5,0x1dcd,0x4a1,0x1268,0x2597,0x2926,0xee,0x111b,0x1038,0xe6c,0x22dc,0x2f2f,0x441,0x2cfd,0x1cb0,0x6a4,0x2224,0x620,0x5dc,0x16b1,0x2a1d,0x1787,0x20c7,0x641,0xd84,0x1c05,0x2d0d,0x2f52,0x1b8c,0xd7d,0x17e8,0x1589,0xc73,0x151b,0x4e2,0x1ae9,0x1b18,0xb9b,0x949,0x2c60,0x1e7a,0xd5,0x1bdc,0x1f57,0x1753,0x124a,0x559,0xb76,0x2334,0x12d1,0x1de1,0x14b2,0x2faa,0x1697,0x147a,0x5a1,0x2c30,0x1c02,0x1043,0x2ee1,0x2402,0x1cc8,0x2a16,0xff7,0x1364,0x1b9a,0x2a53,0x2f94,0x294c,0x1ee5,0x1a87,0x2141,0xd66,0x953,0x28a3,0x2f30,0x2477,0x18e3,0x1035,0x1fc1,0x1d68,0x2fb3,0x138c,0x2487,0x1bf8,0xd96,0x1018,0x748,0x244e,0x15bd,0x175e,0x2be,0x23d,0x1da,0x176d,0xc17,0x24be,0x2ebb,0x7d8,0x100a,0x759,0x1db4,0x2259,0x23f4,0x2d59,0x2847,0xbf5,0x1cfe,0xa20,0x258,0x1180,0x279c,0x54,0x2abf,0xc5c,0x9f9,0x3d5,0x2ce4,0x165f,0x23d9,0x27b9,0x6f9,0x281a,0x169e,0x627,0x156d,0x1ff8,0x211,0x2e34,0x1724,0x2c2e,0x2790,0x2dd5,0x2bf2,0xdbc,0x2884,0x20a9,0x2390,0x1e1a,0x1b6a,0x5f7,0xab7,0x1333,0x16ab,0x28dd,0x20,0x30f,0x24b6,0x5c2,0x1ce4,0x1400,0x2669,0x60,0x156c,0xe20,0x26d4,0x26ab,0x1ebb,0x223d,0x5b4,0x2025,0x1e1c,0xaae,0x2e08,0x6cd,0x1677,0x13d9,0x17b5,0x1046,0x1d8c,0x14eb,0x18d8,0x1ce5,0x2478,0x16ae,0xb79,0x23d4,0x684,0x156b,0x567,0x1a,0x29ce,0x83a,0x19e8,0x58e,0x294a,0x1136,0x2319,0x2fba,0x1a29,0x1d,0x1879,0x291b,0x19f6,0x2c2f,0x21c9,0x19bb,0xbbc,0x26f9,0xc22,0x708,0x11a1,0x18d3,0x7f8,0x28f8,0x2427,0x1deb,0xaed,0x26aa,0x2482,0x203b,0x2f05,0x2b82,0x192f,0x2df4,0x8dc,0x2877,0xd5e,0x240e,0x775,0x2dae,0x1d3e,0x20ba,0x215b,0x22d1,0xeba,0xf50,0xaa8,0x184a,0x1f67,0x2e04,0xc6e,0x6dd,0x1a09,0x27f,0x494,0x1426,0xae3,0xe15,0x65f,0x13c4,0x105,0x872,0x2667,0x1ff6,0xd9f,0x2ca1,0x2f39,0x2657,0x23fd,0x2405,0xb73,0x2294,0x1f1e,0x2eba,0x110a,0x2cae,0x141f,0x22cd,0x25d6,0x11c1,0x1c,0x2d8e,0x161a,0x1aa8,0x229e,0x1bf9,0x7cf,0x106d,0x2c40,0xd93,0x255e,0x28c2,0xc1a,0x2f17,0x7ca,0x2f63,0xbf];
+static let iroots:[Int32] = [0x2ac8,0x452,0x297c,0x666,0xb4c,0x2b8,0x1a74,0xfd,0x1a47,0x1d08,0x2959,0x2c36,0x2db4,0x56c,0x254e,0x1125,0x2f3d,0x13bc,0x172c,0x2c6b,0x32a,0x1745,0x18bd,0x8f1,0x1633,0x2dfa,0xfdd,0x23e3,0x241b,0x13a5,0x578,0x17a0,0xa9,0x104b,0x1335,0x24e4,0x28de,0x5a7,0x368,0x2d70,0x13cd,0x2f9,0xff5,0x1e88,0x9c5,0x2ff7,0x900,0xdeb,0x1434,0x15fe,0x156a,0x24d3,0x28ed,0x2c4f,0x688,0xaef,0x2353,0x1045,0x2bcf,0x23a4,0x270,0x4c5,0x21fe,0xe5b,0xfbb,0x1f79,0x6e4,0xe68,0x2078,0x1160,0x1387,0x1e98,0x22f5,0x13e,0x283a,0x123f,0x149c,0x2eca,0xb14,0xf37,0xdde,0xbe7,0x386,0x1abe,0xa4a,0x49,0x14b5,0x2f36,0x8e5,0x1f1,0x2a57,0x1789,0x2f01,0x91f,0xaac,0x266c,0x2b65,0x2f4b,0xa30,0x2a17,0x265,0x253a,0xfb3,0x2142,0x20be,0x25c2,0x121c,0x2d97,0x2131,0x1e19,0x1a11,0x514,0x22c3,0x66,0xdcf,0x1540,0x1d41,0xf02,0x815,0x5a,0x18e8,0x1159,0x103a,0x2d23,0x2a10,0x2d61,0x1327,0x403,0x25c9,0x7b3,0x1f0c,0x1a98,0x2f21,0x1fb,0x2157,0x99e,0x1501,0x640,0x1e,0x1d4f,0x2716,0xb66,0x46a,0x2fdf,0x1c69,0xf34,0xb16,0x1ac5,0x1e08,0xc9b,0x218a,0x103d,0x2a09,0x4f0,0x21b2,0x750,0x2f33,0x9f7,0x2517,0x236b,0x15cb,0x152e,0x1a33,0x97e,0x24ce,0x2db5,0xac2,0x1583,0x1f99,0x1922,0x2513,0xc4f,0x615,0x1298,0x245a,0x2f97,0x2019,0x2c93,0x1fbd,0x291a,0x8ea,0x1ed4,0xb61,0x1c09,0x230b,0x2056,0x1ccf,0x1c72,0x27d9,0x21e4,0x2d0a,0x1f5b,0xe8,0x2c3d,0x2055,0x72f,0x222,0x222d,0x11be,0x1e90,0x11cf,0x20c5,0x5b7,0x391,0x1ebd,0x238,0x73e,0x653,0x17c2,0x2ef3,0x2fb,0x27c2,0x2ecf,0x847,0x2042,0x296d,0x268d,0x23f8,0x7e0,0x1e2e,0x2bf7,0x1ab7,0x89a,0xad,0x21e3,0x261,0x2f26,0x1ede,0xc4c,0x299a,0xfc8,0xa92,0xffd,0x1cbf,0x14a4,0x2d01,0x2a2e,0x1aaf,0x1967,0x1f03,0xec5,0x25c,0x3a5,0xdd3,0x2c47,0x8dd,0x2945,0x18ac,0x197,0x2f31,0x4c9,0x14ac,0x2be2,0x166,0x43a,0xa94,0x1b53,0x293c,0x212d,0x6fd,0x521,0x109,0x185,0x2735,0x151c,0x123a,0x5be,0x2c02,0x2b0f,0x1e7b,0x1846,0x297f,0x2ffd,0x18e5,0xf2b,0xf9a,0x1f6a,0x299f,0xb48,0x1b9d,0x2b8f,0x1eb,0x12f0,0x1649,0x893,0x83d,0x2942,0x757,0xbc5,0x1db9,0x23a9,0x2115,0x1b49,0x1f77,0x2f18,0x2dfe,0xc29,0x1f69,0x287e,0x1b13,0x9ff,0x2f06,0x515,0x1bb7,0x24a9,0x17f6,0x130d,0x2dd1,0x4c1,0x1675,0x1d86,0x1d9d,0x24f8,0x55,0x1382,0x1b5,0x2061,0x1c82,0x2ebd,0x4b,0x2c68,0x780,0x24,0xff8,0x880,0x2a7b,0x54c,0x971,0x88d,0x1594,0x2802,0x1ebe,0x120e,0xcb6,0x12d7,0x15dd,0xc0a,0x2c54,0x208,0x1bfa,0x2570,0x158f,0x2c82,0xdb3,0x10d6,0x2254,0x1d8,0x26b0,0x2a1b,0xcec,0x2572,0x211d,0x1c51,0x148f,0x616,0x185f,0x1a80,0x1650,0x538,0x25e8,0xf5d,0x1072,0x34f,0x2d04,0x2a3,0xb64,0x2c9e,0x1f74,0x3a6,0x139a,0x2292,0x555,0x96a,0x244,0x60b,0x8d3,0x1de6,0x831,0x2a75,0x4d7,0x2616,0x1485,0xf16,0x264a,0x2bb,0x609,0x19d,0x21da,0x6d7,0x234f,0x2cc4,0xaf9,0x20c2,0xcdd,0x2f1,0x1dfd,0x1c7,0x247b,0xec9,0x1978,0x770,0x72b,0x1ca3,0xe43,0x1820,0xdf9,0x690,0x926,0x3cc,0x2f20,0xa7c,0x121,0x2f02,0xee6,0x2ae2,0xa85,0xe29,0xd2b,0x1326,0x2e3d,0x1553,0x2ff5,0x133,0x2d81,0x143d,0x19fc,0x174a,0x19b9,0x2a40,0x22ab,0x1d27,0x8cf,0x1730,0x1386,0x491,0x212b,0x2954,0xf53,0xbfd,0x113a,0x144f,0x21f8,0x1b0a,0x385,0x2ce6,0xf63,0x1a64,0x48f,0x2059,0x1e4b,0x1d12,0x1f7f,0x2255,0x24f2,0x16e5,0x1242,0xa29,0x1a6,0xdd5,0x7e9,0x2eac,0x2e17,0x8f7,0x9ed,0x1de0,0x1588,0x2935,0x1c3e,0x2534,0xaf2,0x2002,0x7b4,0x2bf,0x1d25,0x2273,0x1240,0x176e,0x29b1,0x217c,0x1f5d,0xa7d,0x6e8,0x1f55,0x104e,0xb07,0x241e,0xc14,0x618,0x1fad,0x2cac,0x93d,0x1e4f,0x2907,0x281,0x1bf3,0x588,0x277d,0x1e6b,0x9df,0x629,0x1f46,0x19a7,0x3c8,0x1804,0x1981,0x2536,0x19,0x6c,0x1092,0x1980,0x13ae,0xfe4,0x2f42,0x9e,0x2837,0xea,0x23e7,0x73f,0xaa3,0x226e,0x3c1,0x1f94,0x2832,0x1408,0xd63,0x1559,0x19e7,0x273,0x2fe5,0x1e40,0xa2b,0xd34,0x1be2,0x353,0x1ef7,0x147,0x10e3,0xd6d,0x248e,0xbfc,0xc04,0x9aa,0xc8,0x360,0x2262,0x100b,0x99a,0x278f,0x2efc,0x1c3d,0x29a2,0x21ec,0x251e,0x1bdb,0x2b6d,0x2d82,0x15f8,0x2924,0x2393,0x1fd,0x109a,0x17b7,0x2559,0x20b1,0x2147,0xd30,0xea6,0xf47,0x12c3,0x253,0x288c,0xbf3,0x22a3,0x78a,0x2725,0x20d,0x16d2,0x47f,0xfc,0xfc6,0xb7f,0x957,0x2514,0x1216,0xbda,0x709,0x2809,0x172e,0x1e60,0x28f9,0x23df,0x908,0x2445,0x1646,0xe38,0x3d2,0x160b,0x6e6,0x1788,0x2fe4,0x15d8,0x47,0xce8,0x1ecb,0x6b7,0x2a73,0x1619,0x27c7,0x633,0x2fe7,0x2a9a,0x1a96,0x297d,0xc2d,0x2488,0x1953,0xb89,0x131c,0x1729,0x1b16,0x1275,0x1fbb,0x184c,0x1c28,0x198a,0x2934,0x1f9,0x2553,0x11e5,0xfdc,0x2a4d,0xdc4,0x1146,0x956,0x92d,0x21e1,0x1a95,0x2fa1,0x998,0x1c01,0x131d,0x2a3f,0xb4b,0x2cf2,0x2fe1,0x724,0x1956,0x1cce,0x254a,0x2a0a,0x1497,0x11e7,0xc71,0xf58,0x77d,0x2245,0x40f,0x22c,0x871,0x3d3,0x18dd,0x1cd,0x2df0,0x1009,0x1a94,0x29da,0x1963,0x7e7,0x2908,0x848,0xc28,0x19a2,0x31d,0x2c2c,0x2608,0x23a5,0x542,0x2fad,0x865,0x1e81,0x2da9,0x25e1,0x1303,0x240c,0x7ba,0x2a8,0xc0d,0xda8,0x124d,0x28a8,0x1ff7,0x2829,0x146,0xb43,0x23ea,0x1894,0x2e27,0x2dc4,0x2d43,0x18a3,0x1a44,0xbb3,0x28b9,0x1fe9,0x226b,0x1409,0xb7a,0x1c75,0x4e,0x1299,0x1040,0x1fcc,0x171e,0xb8a,0xd1,0x75e,0x26ae,0x229b,0xec0,0x157a,0x111c,0x6b5,0x6d,0x5ae,0x1467,0x1c9d,0x200a,0x5eb,0x1339,0xbff,0x120,0x1fbe,0x13ff,0x3d1,0x2a60,0x1b87,0x196a,0x57,0x1b4f,0x1220,0x1d30,0xccd,0x248b,0x2aa8,0x1db7,0x18ae,0x10aa,0x1425,0x2f2c,0x1187,0x3a1,0x26b8,0x2466,0x14e9,0x1518,0x2b1f,0x1ae6,0x238e,0x1a78,0x1819,0x2284,0x1475,0xaf,0x2f4,0x13fc,0x227d,0x29c0,0xf3a,0x187a,0x5e4,0x1950,0x2a25,0x29e1,0xddd,0x295d,0x1351,0x304,0x2bc0,0xd2,0xd25,0x2195,0x1fc9,0x1ee6,0x2f13,0x6db,0xa6a,0x1d99,0x2b60,0x1234,0x283c,0x2ac2,0x11a9,0x639,0x2290,0x2bda,0x32f,0x2a5f,0x15c0,0x139c,0x7e8,0x88a,0x43f,0x2762,0x1271,0x119d,0x1fed,0x1b4d,0x692,0x1d2b,0x1feb,0x1380,0x2628,0x2a93,0x2226,0xe71,0x2d1b,0x20ab,0x17ff,0x1e27,0x2fb1,0xe65,0x17c8,0x1fa6,0x43b,0x548,0x2256,0x9a5,0x71a,0x26ea,0x2d38,0x1b40,0x1b79,0x658,0x15a5,0x224f,0x248,0xeee,0x2f37,0x1c30,0x15ec,0x1ca7,0x255f,0x2801,0x18f7,0x1727,0xf88,0x2b1,0x2c45,0x164b,0x289f,0x14dd,0x2649,0x27a3,0x9f0,0x21ca,0x1f5,0x1dd6,0xbc3,0x71f,0x133e,0x13bb,0x2afe,0xc35,0x4bb,0x2d31,0x10a7,0x2a04,0x180e,0x2613,0x330,0xe76,0x19fd,0xfe9,0x935,0x79,0x1b01,0x73c,0x2ac6,0x21ce,0x1911,0x761,0x1084,0x1983,0xc3,0x15eb,0xe0a,0xdd,0x1cb1,0xb21,0x2a51,0x217f,0xb1,0x1328,0x9ca,0x1d96,0x1a0b,0xe1b,0x1c4b,0x3b,0x4d6,0x2344,0x199e,0x28af,0x1624,0x4ae,0x8b2,0x2991,0x1fb7,0x41,0x2780,0x1d8b,0xa7f,0x110,0x2350,0x18aa,0x2b2f,0x1805,0x1ff,0xf0,0x2a74,0xe42,0xd97,0x85b,0x14bc,0x2901,0xfd8,0x1ab3,0x1cef,0xfbd,0x2b07,0x174f,0x69b,0x10c3,0x1491,0xde3,0x28ca,0x252e,0x1849,0x1ec2,0x1f1b,0x2853,0x12ab,0x2674,0x238c,0x350,0x2ca,0xa7,0x4bd,0xcc3,0x90c,0x892,0x276,0x1e55,0x196d,0x1194,0x1bef,0x66a,0x1da1,0x260f,0x1c15,0x49f,0x120b,0x2671,0x1237,0x2e0d,0x2791,0x17d8,0x1e0a,0x2a99,0x14cf,0xfb1,0x15b4,0x1462,0x2fbb,0xeff,0x16b,0x2d6a,0x9ef,0x5e3,0x11c0,0x2e76,0x1623,0x2db8,0x1c88,0x740,0x11e1,0x12a3,0x977,0x1110,0x2163,0x2dee,0x47b,0x2aa5,0x2a22,0x1231,0x16e7,0x1626,0x12e0,0x1d28,0xe96,0xb62,0x21d0,0xf09,0xb30,0xcb8,0x2981,0x2648,0x155d,0x27ee,0xb34,0x169,0x1574,0x1fe6,0x25f4,0x151d,0x1801,0x1f13,0x1308,0x2929,0x6eb,0x25e,0x2cca,0x1e3e,0x248f];
+
+
+	private static func round(_ a: Int32,_ b: Int32) -> Int32
+	{
+		return (a+b/2)/b
+	}
+
+	private static func nabs(_ x: Int32) -> Int32
+	{
+		let mask=(x>>31)
+		return (x+mask)^mask		
+	}
+
+/* Montgomery stuff */
+
+	private static func redc(_ T: UInt64) -> Int32
+	{
+		let m:UInt32=(UInt32(T&0xffffffff) &* ND)
+		return Int32((UInt64(m)*UInt64(PRIME)+T)>>UInt64(WL))		
+	}
+
+	private static func nres(_ x: Int32) -> Int32 
+	{
+		return redc(UInt64(x)*R2MODP)
+	}
+
+	private static func modmul(_ a: Int32,_ b: Int32) -> Int32 
+	{
+		return redc(UInt64(a)*UInt64(b));
+	}
+
+/* Cooley-Tukey NTT */
+	private static func ntt(_ x:inout [Int32]) 
+	{
+		var t=DEGREE/2
+		let q=PRIME
+
+/* Convert to Montgomery form */
+		for j in 0..<DEGREE {x[j]=nres(x[j])}
+		var m=1
+		while m<DEGREE {
+			var k=0
+			for i in 0..<m {
+				let S=roots[m+i]
+				for j in k..<k+t {
+					let U=x[j]
+					let V=modmul(x[j+t],S)
+					x[j]=U+V
+					x[j+t]=U+2*q-V
+				}
+				k+=2*t
+			}
+			t/=2
+			m*=2
+		}
+	}
+
+/* Gentleman-Sande INTT */
+
+	private static func intt(_ x:inout [Int32]) 
+	{
+		var t=1
+		let q=PRIME
+		var m=DEGREE/2
+		while m>1 {
+			var k=0
+			for i in 0..<m {
+				let S=iroots[m+i]
+				for j in k..<k+t {	
+					let U=x[j] 
+					let V=x[j+t]
+					x[j]=U+V
+					let W=U+Int32(DEGREE)*q-V 
+					x[j+t]=modmul(W,S) 
+				}
+				k+=2*t
+			}
+			t*=2
+			m/=2
+		}
+
+/* Last iteration merged with n^-1 */
+		t=DEGREE/2
+		for j in 0..<t {
+			let U=x[j]
+			let V=x[j+t]
+			let W=U+Int32(DEGREE)*q-V 
+			x[j+t]=modmul(W,invpr)
+			x[j]=modmul(U+V,inv)
+		}
+/* convert back from Montgomery to "normal" form */
+		for j in 0..<DEGREE {
+			x[j]=redc(UInt64(x[j]))
+			x[j]-=q
+			x[j]+=(x[j]>>(WL-1))&q
+		} 
+	}
+
+/* See https://eprint.iacr.org/2016/1157.pdf */ 
+
+	private static func encode(_ key: [UInt8],_ poly:inout [Int32]) {
+
+		let q2=PRIME/2
+		var j=0
+		var i=0
+		while i<256  {
+			var kj=key[j]
+			j+=1
+			for _ in 0..<8 {
+				let b=Int32(kj&1)
+				poly[i]=b*q2
+				poly[i+256]=b*q2
+				poly[i+512]=b*q2
+				poly[i+768]=b*q2
+				kj>>=1
+				i+=1
+			}
+		}			
+	}
+
+	private static func decode(_ poly: [Int32],_ key:inout [UInt8]) {
+		let q2=PRIME/2
+		for i in 0..<32 {
+			key[i]=0;
+		}
+
+		var i=0
+		var j=0
+		while i<256 {
+			for _ in 0..<8 {
+				let t=nabs(poly[i]-q2)+nabs(poly[i+256]-q2)+nabs(poly[i+512]-q2)+nabs(poly[i+768]-q2)
+				var b=t-PRIME
+				b=(b>>31)&1
+				key[j]=(key[j]>>1)+UInt8(b<<7)
+				i+=1
+			}
+			j+=1
+		}
+	}
+/* convert 32-byte seed to random polynomial */
+
+	private static func parse(_ seed: [UInt8],_ poly:inout [Int32]) {
+		var hash=[UInt8](repeating:0,count:4*DEGREE)
+
+		var sh=SHA3(SHA3.SHAKE128)
+
+		for i in 0..<32 {
+			sh.process(seed[i])
+		}
+		sh.shake(&hash,4*DEGREE)
+
+		var j=0
+		for i in 0..<DEGREE {
+			var n=Int32(hash[j]&0x7f); n<<=8
+			n+=Int32(hash[j+1]); n<<=8
+			n+=Int32(hash[j+2]); n<<=8
+			n+=Int32(hash[j+3]); j+=4
+			poly[i]=nres(n)
+			//poly[i]=modmul(n,ONE); // reduce 31-bit random number mod q
+		}
+	} 
+/* Compress 14 bits polynomial coefficients into byte array */
+/* 7 bytes is 3x14 */
+
+	private static func nhs_pack(_ poly: [Int32],_ array:inout [UInt8]) {
+		var j=0
+		var i=0
+		while i<DEGREE  {
+			let a=poly[i]; let b=poly[i+1]; let c=poly[i+2]; let d=poly[i+3]; i+=4
+			array[j]=UInt8(a&0xff)
+			array[j+1]=UInt8(((a>>8)|(b<<6))&0xff)
+			array[j+2]=UInt8((b>>2)&0xff)
+			array[j+3]=UInt8(((b>>10)|(c<<4))&0xff)
+			array[j+4]=UInt8((c>>4)&0xff)
+			array[j+5]=UInt8(((c>>12)|(d<<2))&0xff)
+			array[j+6]=UInt8(d>>6)
+			j+=7
+		}
+	}
+
+	private static func nhs_unpack(_ array: [UInt8],_ poly:inout [Int32]) {
+		var j=0
+		var i=0
+		while i<DEGREE {
+			let a=Int32((array[j])&0xff); let b=Int32((array[j+1])&0xff); let c=Int32((array[j+2])&0xff); let d=Int32((array[j+3])&0xff); let e=Int32((array[j+4])&0xff); let f=Int32((array[j+5])&0xff); let g=Int32((array[j+6])&0xff); j+=7
+			poly[i]=a|((b&0x3f)<<8)
+			poly[i+1]=(b>>6)|(c<<2)|((d&0xf)<<10)
+			poly[i+2]=(d>>4)|(e<<4)|((f&3)<<12)
+			poly[i+3]=(f>>2)|(g<<6)
+			i+=4
+		}
+	}
+/* See https://eprint.iacr.org/2016/1157.pdf */ 
+
+	private static func compress(_ poly: [Int32],_ array:inout [UInt8]) {
+	
+		var col:Int32=0
+		var j=0
+		var i=0
+		while i<DEGREE  {
+			for _ in 0..<8  {
+				let b=round((poly[i]*8),PRIME)&7 
+				col=(col<<3)+b
+				i+=1
+			}
+			array[j]=UInt8(col&0xff)
+			array[j+1]=UInt8((col>>8)&0xff)
+			array[j+2]=UInt8((col>>16)&0xff)
+			j+=3; col=0
+		}
+	}
+
+	private static func decompress(_ array: [UInt8],_ poly:inout [Int32]) {
+		var col:Int32=0
+		var j=0
+		var i=0
+		while i<DEGREE  {
+			col=Int32(array[j+2])&0xff;
+			col=(col<<8)+(Int32(array[j+1])&0xff)
+			col=(col<<8)+(Int32(array[j])&0xff)
+			j+=3
+			for _ in 0..<8 {
+				let b=(col&0xe00000)>>21; col<<=3
+				poly[i]=round((b*PRIME),8)
+				i+=1
+			}
+		}
+	}
+/* generate centered binomial distribution */ 
+
+	private static func error(_ rng: inout RAND,_ poly:inout [Int32]) {
+		var r: Int32
+		for i in 0..<DEGREE {
+			var n1=(Int32(rng.getByte())&0xff)+((Int32(rng.getByte())&0xff)<<8)
+			var n2=(Int32(rng.getByte())&0xff)+((Int32(rng.getByte())&0xff)<<8)
+			r=0
+			for _ in 0..<16 {
+				r+=(n1&1)-(n2&1)
+				n1>>=1; n2>>=1
+			}
+			poly[i]=(r+PRIME);
+		}
+	}
+
+	private static func redc_it(_ p:inout [Int32]) {
+		for i in 0..<DEGREE {
+			p[i]=redc(UInt64(p[i]))
+		}
+		
+	}
+
+	private static func nres_it(_ p:inout [Int32]) {
+		for i in 0..<DEGREE {
+			p[i]=nres(p[i])
+		}
+		
+	}
+
+	private static func poly_mul(_ p1:inout [Int32],_ p2: [Int32],_ p3: [Int32]) {
+		for i in 0..<DEGREE {
+			p1[i]=modmul(p2[i],p3[i])
+		}
+	}
+
+	private static func poly_add(_ p1:inout [Int32],_ p2: [Int32],_ p3: [Int32]) {
+		for i in 0..<DEGREE {
+			p1[i]=(p2[i]+p3[i])
+		}
+	}
+
+	private static func poly_sub(_ p1:inout [Int32],_ p2: [Int32],_ p3: [Int32]) {
+		for i in 0..<DEGREE {
+			p1[i]=(p2[i]+PRIME-p3[i])
+		}
+	}
+/* reduces inputs < 2q */
+	private static func poly_soft_reduce(_ poly:inout [Int32]) {
+		for i in 0..<DEGREE {
+			let e=poly[i]-PRIME
+			poly[i]=e+((e>>(WL-1))&PRIME)
+		}
+	}
+
+/* fully reduces modulo q */
+	private static func poly_hard_reduce(_ poly:inout [Int32]) {
+		for i in 0..<DEGREE {
+			var e=modmul(poly[i],ONE)
+			e=e-PRIME
+			poly[i]=e+((e>>(WL-1))&PRIME)
+		}
+	}
+/* API files */
+
+	public static func SERVER_1(_ rng: inout RAND,_ SB:inout [UInt8],_ S:inout [UInt8]) {
+		var seed=[UInt8](repeating:0,count:32)
+		var array=[UInt8](repeating:0,count:1792)
+		var s=[Int32](repeating:0,count:DEGREE)
+		var e=[Int32](repeating:0,count:DEGREE)
+		var b=[Int32](repeating:0,count:DEGREE)
+
+		for i in 0..<32 {
+			seed[i]=rng.getByte()
+		}
+
+		parse(seed,&b)
+	
+		error(&rng,&e)
+		error(&rng,&s)
+
+		ntt(&s)
+		ntt(&e)
+		poly_mul(&b,b,s)
+		poly_add(&b,b,e)
+		poly_hard_reduce(&b)
+
+		redc_it(&b)
+		nhs_pack(b,&array)
+
+		for i in 0..<32 {
+			SB[i]=seed[i]
+		}
+
+		for i in 0..<1792 {
+			SB[i+32]=array[i]
+		}
+
+		poly_hard_reduce(&s)
+		nhs_pack(s,&array)
+
+		for i in 0..<1792 {
+			S[i]=array[i]
+		}
+	}
+
+	public static func CLIENT(_ rng: inout RAND,_ SB: [UInt8],_ UC:inout [UInt8],_ KEY:inout [UInt8]) {
+		var sh=SHA3(SHA3.HASH256)
+		var seed=[UInt8](repeating:0,count:32)
+		var array=[UInt8](repeating:0,count:1792)
+		var key=[UInt8](repeating:0,count:32)
+		var cc=[UInt8](repeating:0,count:384)
+
+		var sd=[Int32](repeating:0,count:DEGREE)
+		var ed=[Int32](repeating:0,count:DEGREE)
+		var u=[Int32](repeating:0,count:DEGREE)
+		var k=[Int32](repeating:0,count:DEGREE)
+		var c=[Int32](repeating:0,count:DEGREE)
+
+		error(&rng,&sd)
+		error(&rng,&ed)
+
+		ntt(&sd)
+		ntt(&ed)
+
+		for i in 0..<32 {
+			seed[i]=SB[i]
+		}
+
+		for i in 0..<1792 {
+			array[i]=SB[i+32]
+		}
+
+		parse(seed,&u)
+
+		poly_mul(&u,u,sd)
+		poly_add(&u,u,ed)
+		poly_hard_reduce(&u)
+
+		for i in 0..<32 {
+			key[i]=rng.getByte()
+		}
+
+		for i in 0..<32 {
+			sh.process(key[i])
+		}
+		sh.hash(&key)
+
+		encode(key,&k)
+
+		nhs_unpack(array,&c)
+		nres_it(&c)
+
+		poly_mul(&c,c,sd)
+		intt(&c)
+		error(&rng,&ed)
+		poly_add(&c,c,ed)
+		poly_add(&c,c,k)
+
+		compress(c,&cc)
+
+		sh=SHA3(SHA3.HASH256)
+		for i in 0..<32 {
+			sh.process(key[i])
+		}
+		sh.hash(&key);
+
+		for i in 0..<32 {
+			KEY[i]=key[i]
+		}
+
+		redc_it(&u)
+		nhs_pack(u,&array)
+
+		for i in 0..<1792 {
+			UC[i]=array[i]
+		}
+
+		for i in 0..<384 {
+			UC[i+1792]=cc[i]
+		}
+	}
+
+	public static func SERVER_2(_ S: [UInt8],_ UC: [UInt8],_ KEY:inout [UInt8]) {
+		var sh=SHA3(SHA3.HASH256)
+
+		var c=[Int32](repeating:0,count:DEGREE)
+		var k=[Int32](repeating:0,count:DEGREE)
+		var s=[Int32](repeating:0,count:DEGREE)
+
+		var array=[UInt8](repeating:0,count:1792)
+		var key=[UInt8](repeating:0,count:32)
+		var cc=[UInt8](repeating:0,count:384)
+
+		for i in 0..<1792 {
+			array[i]=UC[i]
+		}
+
+		nhs_unpack(array,&k)
+		nres_it(&k)
+
+		for i in 0..<384 {
+			cc[i]=UC[i+1792]
+		}
+
+		decompress(cc,&c)
+
+		for i in 0..<1792 {
+			array[i]=S[i]
+		}
+
+		nhs_unpack(array,&s)
+
+		poly_mul(&k,k,s)
+		intt(&k)
+		poly_sub(&k,c,k)
+		poly_soft_reduce(&k)
+
+		decode(k,&key)
+
+		for i in 0..<32 {
+			sh.process(key[i])
+		}
+		sh.hash(&key)
+
+		for i in 0..<32 {
+			KEY[i]=key[i]
+		}
+	}
+
+}
+/*
+public func TestNHS()
+{
+	var S=[UInt8](repeating:0,count:1792)
+	var SB=[UInt8](repeating:0,count:1824)
+	var UC=[UInt8](repeating:0,count:2176)
+	var KEYA=[UInt8](repeating:0,count:32)
+	var KEYB=[UInt8](repeating:0,count:32)
+
+
+	var RAW=[UInt8](repeating: 0,count: 100)
+	let srng=RAND()
+				let crng=RAND()
+				crng.clean()
+    
+	srng.clean()
+	for i in 0..<100 {RAW[i]=UInt8((i+1)&0xff)}
+	srng.seed(100,RAW)
+				
+				for i in 0..<100 {RAW[i]=UInt8((i+2)&0xff)}
+				crng.seed(100,RAW)
+
+
+	NHS.SERVER_1(srng,&SB,&S)
+				NHS.CLIENT(crng,SB,&UC,&KEYB)
+
+ 			   	for i in 0..<32 {
+            				let h=String(KEYB[i],radix:16)
+            				print("\(h)", terminator: "")
+        			}
+        			print("")
+
+	NHS.SERVER_2(S,UC,&KEYA)
+
+	for i in 0..<32 {
+            	let h=String(KEYA[i],radix:16)
+            	print("\(h)", terminator: "")
+        }
+        print("")
+}
+
+*/
+
diff --git a/version3/swift/pair.swift b/version3/swift/pair.swift
new file mode 100644
index 0000000..869511b
--- /dev/null
+++ b/version3/swift/pair.swift
@@ -0,0 +1,724 @@
+/*
+	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.
+*/
+
+//
+//  pair.swift
+//
+//  Created by Michael Scott on 07/07/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+/* AMCL BN Curve Pairing functions */
+
+public struct PAIR {
+    
+    // Line function
+    static func linedbl(_ A: inout ECP2,_ Qx:FP,_ Qy:FP) -> FP12
+    {
+        var a:FP4
+        var b:FP4
+        var c:FP4
+
+        var XX=FP2(A.getx())  //X
+        var YY=FP2(A.gety())  //Y
+        var ZZ=FP2(A.getz())  //Z
+        var YZ=FP2(YY)        //Y 
+        YZ.mul(ZZ)                //YZ
+        XX.sqr()                  //X^2
+        YY.sqr()                  //Y^2
+        ZZ.sqr()                  //Z^2
+            
+        YZ.imul(4)
+        YZ.neg(); YZ.norm()       //-2YZ
+        YZ.pmul(Qy)               //-2YZ.Ys
+
+        XX.imul(6)               //3X^2
+        XX.pmul(Qx)              //3X^2.Xs
+
+        let sb=3*ROM.CURVE_B_I
+        ZZ.imul(sb)  
+        if ECP.SEXTIC_TWIST == ECP.D_TYPE {             
+             ZZ.div_ip2();  
+        }
+        if ECP.SEXTIC_TWIST == ECP.M_TYPE {
+            ZZ.mul_ip()
+            ZZ.add(ZZ)
+            ZZ.norm()
+            YZ.mul_ip()
+            YZ.norm()
+        }              
+        ZZ.norm() // 3b.Z^2 
+
+        YY.add(YY)
+        ZZ.sub(YY); ZZ.norm()     // 3b.Z^2-Y^2
+
+        a=FP4(YZ,ZZ)          // -2YZ.Ys | 3b.Z^2-Y^2 | 3X^2.Xs 
+        if ECP.SEXTIC_TWIST == ECP.D_TYPE {             
+            b=FP4(XX)            // L(0,1) | L(0,0) | L(1,0)
+            c=FP4(0)
+        } else { 
+            b=FP4(0)
+            c=FP4(XX); c.times_i()
+        }        
+        A.dbl()
+
+        return FP12(a,b,c)
+    }
+
+
+    // Line function
+    static func lineadd(_ A: inout ECP2,_ B:ECP2,_ Qx:FP,_ Qy:FP) -> FP12
+    {
+        var a:FP4
+        var b:FP4
+        var c:FP4
+
+        var X1=FP2(A.getx())    // X1
+        var Y1=FP2(A.gety())    // Y1
+        var T1=FP2(A.getz())    // Z1
+        var T2=FP2(A.getz())    // Z1
+            
+        T1.mul(B.gety())    // T1=Z1.Y2 
+        T2.mul(B.getx())    // T2=Z1.X2
+
+        X1.sub(T2); X1.norm()  // X1=X1-Z1.X2
+        Y1.sub(T1); Y1.norm()  // Y1=Y1-Z1.Y2
+
+        T1.copy(X1)            // T1=X1-Z1.X2
+        X1.pmul(Qy)            // X1=(X1-Z1.X2).Ys
+        if ECP.SEXTIC_TWIST == ECP.M_TYPE {
+            X1.mul_ip()
+            X1.norm()
+        }              
+        T1.mul(B.gety())       // T1=(X1-Z1.X2).Y2
+
+        T2.copy(Y1)            // T2=Y1-Z1.Y2
+        T2.mul(B.getx())       // T2=(Y1-Z1.Y2).X2
+        T2.sub(T1); T2.norm()          // T2=(Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2
+        Y1.pmul(Qx);  Y1.neg(); Y1.norm() // Y1=-(Y1-Z1.Y2).Xs
+
+        a=FP4(X1,T2)       // (X1-Z1.X2).Ys  |  (Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2  | - (Y1-Z1.Y2).Xs
+        if ECP.SEXTIC_TWIST == ECP.D_TYPE {              
+            b=FP4(Y1)
+            c=FP4(0)
+        } else {
+            b=FP4(0)
+            c=FP4(Y1); c.times_i()
+         }  
+        A.add(B)
+        return FP12(a,b,c)
+    }
+
+
+    // Optimal R-ate pairing
+    static public func ate(_ P1:ECP2,_ Q1:ECP) -> FP12
+    {
+        var f=FP2(BIG(ROM.Fra),BIG(ROM.Frb))
+        let x=BIG(ROM.CURVE_Bnx)
+        var n=BIG(x)
+        var K=ECP2()
+        
+        var lv:FP12
+
+        if ECP.CURVE_PAIRING_TYPE == ECP.BN {
+            if ECP.SEXTIC_TWIST == ECP.M_TYPE {  
+                f.inverse()
+                f.norm()
+            }
+            n.pmul(6);
+            if ECP.SIGN_OF_X == ECP.NEGATIVEX { 
+                n.dec(2)
+            } else {
+                n.inc(2)
+            }
+        } else {n.copy(x)}
+	
+        n.norm()
+
+        var n3=BIG(n)
+        n3.pmul(3)
+        n3.norm()
+
+        var P=ECP2(); P.copy(P1); P.affine()
+        var Q=ECP(); Q.copy(Q1); Q.affine()
+
+
+        let Qx=FP(Q.getx())
+        let Qy=FP(Q.gety())
+    
+        var A=ECP2()
+        A.copy(P)
+
+        var NP=ECP2()
+        NP.copy(P)
+        NP.neg()
+
+        var r=FP12(1)
+        let nb=n3.nbits()
+    
+        for i in (1...nb-2).reversed()
+        //for var i=nb-2;i>=1;i--
+        {
+            r.sqr()            
+            lv=linedbl(&A,Qx,Qy)
+            r.smul(lv,ECP.SEXTIC_TWIST)
+            let bt=n3.bit(UInt(i))-n.bit(UInt(i))
+            if bt == 1 {
+		      lv=lineadd(&A,P,Qx,Qy)
+		      r.smul(lv,ECP.SEXTIC_TWIST)
+            }
+            if bt == -1 {
+                //P.neg()
+                lv=lineadd(&A,NP,Qx,Qy)
+                r.smul(lv,ECP.SEXTIC_TWIST)
+                //P.neg()
+            }
+        }
+    
+        if ECP.SIGN_OF_X == ECP.NEGATIVEX {
+            r.conj()
+         }     
+
+    // R-ate fixup required for BN curves
+
+	   if ECP.CURVE_PAIRING_TYPE == ECP.BN {
+            if ECP.SIGN_OF_X == ECP.NEGATIVEX {
+                //r.conj()
+                A.neg()
+            }           
+            K.copy(P)
+            K.frob(f)
+
+            lv=lineadd(&A,K,Qx,Qy)
+            r.smul(lv,ECP.SEXTIC_TWIST)
+            K.frob(f)
+            K.neg()
+            lv=lineadd(&A,K,Qx,Qy)
+            r.smul(lv,ECP.SEXTIC_TWIST)
+        }
+        return r
+    }
+    // Optimal R-ate double pairing e(P,Q).e(R,S)
+    static public func ate2(_ P1:ECP2,_ Q1:ECP,_ R1:ECP2,_ S1:ECP) -> FP12
+    {
+        var f=FP2(BIG(ROM.Fra),BIG(ROM.Frb))
+        let x=BIG(ROM.CURVE_Bnx)
+        var n=BIG(x)
+        var K=ECP2()
+        var lv:FP12
+
+        if ECP.CURVE_PAIRING_TYPE == ECP.BN {
+            if ECP.SEXTIC_TWIST == ECP.M_TYPE {  
+                f.inverse()
+                f.norm()
+            }
+            n.pmul(6); 
+            if ECP.SIGN_OF_X == ECP.NEGATIVEX { 
+                n.dec(2)
+            } else {
+                n.inc(2)
+            }        
+        } else {n.copy(x)}
+	
+        n.norm()
+        var n3=BIG(n)
+        n3.pmul(3)
+        n3.norm()
+    
+	   var P=ECP2(); P.copy(P1); P.affine()
+	   var Q=ECP(); Q.copy(Q1); Q.affine()
+	   var R=ECP2(); R.copy(R1); R.affine()
+	   var S=ECP(); S.copy(S1); S.affine()
+
+
+        let Qx=FP(Q.getx())
+        let Qy=FP(Q.gety())
+        let Sx=FP(S.getx())
+        let Sy=FP(S.gety())
+    
+        var A=ECP2()
+        var B=ECP2()
+        var r=FP12(1)
+    
+        A.copy(P)
+        B.copy(R)
+        var NP=ECP2()
+        NP.copy(P)
+        NP.neg()
+        var NR=ECP2()
+        NR.copy(R)
+        NR.neg()
+
+
+        let nb=n3.nbits()
+    
+        for i in (1...nb-2).reversed()
+        //for var i=nb-2;i>=1;i--
+        {
+            r.sqr()            
+            lv=linedbl(&A,Qx,Qy)
+            r.smul(lv,ECP.SEXTIC_TWIST)
+            lv=linedbl(&B,Sx,Sy)
+            r.smul(lv,ECP.SEXTIC_TWIST)
+            let bt=n3.bit(UInt(i))-n.bit(UInt(i))
+
+            if bt == 1 {
+                lv=lineadd(&A,P,Qx,Qy)
+                r.smul(lv,ECP.SEXTIC_TWIST)
+                lv=lineadd(&B,R,Sx,Sy)
+                r.smul(lv,ECP.SEXTIC_TWIST)
+            }
+
+            if bt == -1 {
+                //P.neg(); 
+                lv=lineadd(&A,NP,Qx,Qy)
+                r.smul(lv,ECP.SEXTIC_TWIST)
+		//P.neg(); 
+		//R.neg()
+                lv=lineadd(&B,NR,Sx,Sy)
+                r.smul(lv,ECP.SEXTIC_TWIST)
+                //R.neg()                
+            }            
+
+        }
+    
+        if ECP.SIGN_OF_X == ECP.NEGATIVEX {
+            r.conj()
+         }     
+
+    // R-ate fixup required for BN curves
+
+	   if ECP.CURVE_PAIRING_TYPE == ECP.BN {
+            if ECP.SIGN_OF_X == ECP.NEGATIVEX {
+                //r.conj()
+                A.neg()                
+                B.neg()
+            }
+            K.copy(P)
+            K.frob(f)
+
+            lv=lineadd(&A,K,Qx,Qy)
+            r.smul(lv,ECP.SEXTIC_TWIST)
+            K.frob(f)
+            K.neg()
+            lv=lineadd(&A,K,Qx,Qy)
+            r.smul(lv,ECP.SEXTIC_TWIST)
+    
+            K.copy(R)
+            K.frob(f)
+
+            lv=lineadd(&B,K,Sx,Sy)
+            r.smul(lv,ECP.SEXTIC_TWIST)
+            K.frob(f)
+            K.neg()
+            lv=lineadd(&B,K,Sx,Sy)
+            r.smul(lv,ECP.SEXTIC_TWIST)
+        }
+        return r
+    }
+    
+    // final exponentiation - keep separate for multi-pairings and to avoid thrashing stack
+    static public func fexp(_ m:FP12) -> FP12
+    {
+        let f=FP2(BIG(ROM.Fra),BIG(ROM.Frb));
+        let x=BIG(ROM.CURVE_Bnx)
+        var r=FP12(m)
+    
+    // Easy part of final exp
+        var lv=FP12(r)
+        lv.inverse()
+        r.conj()
+    
+        r.mul(lv)
+        lv.copy(r)
+        r.frob(f)
+        r.frob(f)
+        r.mul(lv)
+        
+    // Hard part of final exp
+	if ECP.CURVE_PAIRING_TYPE == ECP.BN {
+		lv.copy(r)
+		lv.frob(f)
+		var x0=FP12(lv)
+		x0.frob(f)
+		lv.mul(r)
+		x0.mul(lv)
+		x0.frob(f)
+		var x1=FP12(r)
+		x1.conj()
+		var x4=r.pow(x)
+        if ECP.SIGN_OF_X == ECP.POSITIVEX {
+            x4.conj()
+        }
+		var x3=FP12(x4)
+		x3.frob(f)
+    
+		var x2=x4.pow(x)
+        if ECP.SIGN_OF_X == ECP.POSITIVEX {
+            x2.conj()
+        }    
+		var x5=FP12(x2); x5.conj()
+		lv=x2.pow(x)
+        if ECP.SIGN_OF_X == ECP.POSITIVEX {
+            lv.conj()
+        }   
+		x2.frob(f)
+		r.copy(x2); r.conj()
+    
+		x4.mul(r)
+		x2.frob(f)
+    
+		r.copy(lv)
+		r.frob(f)
+		lv.mul(r)
+    
+		lv.usqr()
+		lv.mul(x4)
+		lv.mul(x5)
+		r.copy(x3)
+		r.mul(x5)
+		r.mul(lv)
+		lv.mul(x2)
+		r.usqr()
+		r.mul(lv)
+		r.usqr()
+		lv.copy(r)
+		lv.mul(x1)
+		r.mul(x0)
+		lv.usqr()
+		r.mul(lv)
+		r.reduce()
+	} else {
+		var x0=FP12(r)
+		var x1=FP12(r)
+		lv.copy(r); lv.frob(f)
+		var x3=FP12(lv); x3.conj(); x1.mul(x3)
+		lv.frob(f); lv.frob(f)
+		x1.mul(lv)
+
+		r.copy(r.pow(x))  //r=r.pow(x);
+        if ECP.SIGN_OF_X == ECP.NEGATIVEX {
+            r.conj()
+        }          
+		x3.copy(r); x3.conj(); x1.mul(x3)
+		lv.copy(r); lv.frob(f)
+		x0.mul(lv)
+		lv.frob(f)
+		x1.mul(lv)
+		lv.frob(f)
+		x3.copy(lv); x3.conj(); x0.mul(x3)
+
+		r.copy(r.pow(x))
+        if ECP.SIGN_OF_X == ECP.NEGATIVEX {
+            r.conj()
+        }  
+		x0.mul(r)
+		lv.copy(r); lv.frob(f); lv.frob(f)
+		x3.copy(lv); x3.conj(); x0.mul(x3)
+		lv.frob(f)
+		x1.mul(lv)
+
+		r.copy(r.pow(x))
+        if ECP.SIGN_OF_X == ECP.NEGATIVEX {
+            r.conj()
+        }          
+		lv.copy(r); lv.frob(f)
+		x3.copy(lv); x3.conj(); x0.mul(x3)
+		lv.frob(f)
+		x1.mul(lv)
+
+		r.copy(r.pow(x))
+        if ECP.SIGN_OF_X == ECP.NEGATIVEX {
+            r.conj()
+        }          
+		x3.copy(r); x3.conj(); x0.mul(x3)
+		lv.copy(r); lv.frob(f)
+		x1.mul(lv)
+
+		r.copy(r.pow(x))
+        if ECP.SIGN_OF_X == ECP.NEGATIVEX {
+            r.conj()
+        }          
+		x1.mul(r)
+
+		x0.usqr()
+		x0.mul(x1)
+		r.copy(x0)
+		r.reduce()
+	}
+        return r
+    }
+    
+    // GLV method
+    static func glv(_ e:BIG) -> [BIG]
+    {
+	var u=[BIG]();
+	if ECP.CURVE_PAIRING_TYPE == ECP.BN {
+		var t=BIG(0)
+		let q=BIG(ROM.CURVE_Order)
+		var v=[BIG]();
+		for _ in 0 ..< 2
+		{
+			u.append(BIG(0))
+			v.append(BIG(0))
+		}
+        
+		for i in 0 ..< 2
+		{
+			t.copy(BIG(ROM.CURVE_W[i]))
+			var d=BIG.mul(t,e)
+			v[i].copy(d.div(q))
+		}
+		u[0].copy(e);
+		for i in 0 ..< 2
+		{
+			for j in 0 ..< 2
+			{
+				t.copy(BIG(ROM.CURVE_SB[j][i]))
+				t.copy(BIG.modmul(v[j],t,q))
+				u[i].add(q)
+				u[i].sub(t)
+				u[i].mod(q)
+			}
+		}
+	} else { // -(x^2).P = (Beta.x,y)
+		let q=BIG(ROM.CURVE_Order)
+		let x=BIG(ROM.CURVE_Bnx)
+		let x2=BIG.smul(x,x)
+		u.append(BIG(e))
+		u[0].mod(x2)
+		u.append(BIG(e))
+		u[1].div(x2)
+		u[1].rsub(q)
+
+	}
+        return u
+    }
+    // Galbraith & Scott Method
+    static func gs(_ e:BIG) -> [BIG]
+    {
+        var u=[BIG]();
+        if ECP.CURVE_PAIRING_TYPE == ECP.BN {
+		  var t=BIG(0)
+		  let q=BIG(ROM.CURVE_Order)
+		  var v=[BIG]();
+		  for _ in 0 ..< 4
+		  {
+			 u.append(BIG(0))
+			 v.append(BIG(0))
+		  }
+        
+		  for i in 0 ..< 4
+		  {
+			 t.copy(BIG(ROM.CURVE_WB[i]))
+			 var d=BIG.mul(t,e)
+			 v[i].copy(d.div(q))
+		  }
+		  u[0].copy(e);
+		  for i in 0 ..< 4
+		  {
+			for j in 0 ..< 4
+			{
+				t.copy(BIG(ROM.CURVE_BB[j][i]))
+				t.copy(BIG.modmul(v[j],t,q))
+				u[i].add(q)
+				u[i].sub(t)
+				u[i].mod(q)
+			}
+
+		  }
+	} else {
+            let q=BIG(ROM.CURVE_Order)        
+            let x=BIG(ROM.CURVE_Bnx)
+            var w=BIG(e)
+            for i in 0 ..< 3
+            {
+			     u.append(BIG(w))
+			     u[i].mod(x)
+			     w.div(x)
+            }
+            u.append(BIG(w))
+            if ECP.SIGN_OF_X == ECP.NEGATIVEX {
+                u[1].copy(BIG.modneg(u[1],q))
+                u[3].copy(BIG.modneg(u[3],q))                
+            }        
+        }
+        return u
+    }	
+    
+    // Multiply P by e in group G1
+    static public func G1mul(_ P:ECP,_ e:BIG) -> ECP
+    {
+        var R:ECP
+        if (ROM.USE_GLV)
+        {
+            //P.affine()
+            R=ECP()
+            R.copy(P)
+            var Q=ECP()
+            Q.copy(P); Q.affine()
+            let q=BIG(ROM.CURVE_Order)
+            let cru=FP(BIG(ROM.CURVE_Cru))
+            var t=BIG(0)
+            var u=PAIR.glv(e)
+            Q.mulx(cru);
+    
+            var np=u[0].nbits()
+            t.copy(BIG.modneg(u[0],q))
+            var nn=t.nbits()
+            if (nn<np)
+            {
+				u[0].copy(t)
+				R.neg()
+            }
+    
+            np=u[1].nbits()
+            t.copy(BIG.modneg(u[1],q))
+            nn=t.nbits()
+            if (nn<np)
+            {
+				u[1].copy(t)
+				Q.neg()
+            }
+            u[0].norm()
+            u[1].norm()
+            R=R.mul2(u[0],Q,u[1])
+        }
+        else
+        {
+            R=P.mul(e)
+        }
+        return R
+    }
+    
+    // Multiply P by e in group G2
+    static public func G2mul(_ P:ECP2,_ e:BIG) -> ECP2
+    {
+        var R:ECP2
+        if (ROM.USE_GS_G2)
+        {
+            var Q=[ECP2]()
+            var f=FP2(BIG(ROM.Fra),BIG(ROM.Frb));
+            let q=BIG(ROM.CURVE_Order);
+            var u=PAIR.gs(e);
+    
+            if ECP.SEXTIC_TWIST == ECP.M_TYPE {  
+                f.inverse()
+                f.norm()
+            }
+
+            var t=BIG(0)
+            //P.affine()
+            Q.append(ECP2())
+            Q[0].copy(P);
+            for i in 1 ..< 4
+            {
+                Q.append(ECP2()); Q[i].copy(Q[i-1]);
+				Q[i].frob(f);
+            }
+            for i in 0 ..< 4
+            {
+				let np=u[i].nbits()
+				t.copy(BIG.modneg(u[i],q))
+				let nn=t.nbits()
+				if (nn<np)
+				{
+                    u[i].copy(t)
+                    Q[i].neg()
+				}
+                u[i].norm()
+            }
+    
+            R=ECP2.mul4(Q,u)
+        }
+        else
+        {
+            R=P.mul(e)
+        }
+        return R;
+    }
+    // f=f^e
+    // Note that this method requires a lot of RAM! Better to use compressed XTR method, see FP4.java
+    static public func GTpow(_ d:FP12,_ e:BIG) -> FP12
+    {
+        var r:FP12
+        if (ROM.USE_GS_GT)
+        {
+            var g=[FP12]()
+            let f=FP2(BIG(ROM.Fra),BIG(ROM.Frb))
+            let q=BIG(ROM.CURVE_Order)
+            var t=BIG(0)
+        
+            var u=gs(e)
+            g.append(FP12(0))
+            g[0].copy(d);
+            for i in 1 ..< 4
+            {
+                g.append(FP12(0)); g[i].copy(g[i-1])
+				g[i].frob(f)
+            }
+            for i in 0 ..< 4
+            {
+				let np=u[i].nbits()
+				t.copy(BIG.modneg(u[i],q))
+				let nn=t.nbits()
+				if (nn<np)
+				{
+                    u[i].copy(t)
+                    g[i].conj()
+				}
+                u[i].norm()                
+            }
+            r=FP12.pow4(g,u)
+        }
+        else
+        {
+            r=d.pow(e)
+        }
+        return r
+    }
+    // test group membership - no longer needed
+    // with GT-Strong curve, now only check that m!=1, conj(m)*m==1, and m.m^{p^4}=m^{p^2}
+/*
+    static func GTmember(m:FP12) -> Bool
+    {
+        if m.isunity() {return false}
+        let r=FP12(m)
+        r.conj()
+        r.mul(m)
+        if !r.isunity() {return false}
+    
+        let f=FP2(BIG(ROM.Fra),BIG(ROM.Frb))
+    
+        r.copy(m); r.frob(f); r.frob(f)
+        var w=FP12(r); w.frob(f); w.frob(f)
+        w.mul(m)
+        if !ROM.GT_STRONG
+        {
+            if !w.equals(r) {return false}
+            let x=BIG(ROM.CURVE_Bnx)
+            r.copy(m); w=r.pow(x); w=w.pow(x)
+            r.copy(w); r.sqr(); r.mul(w); r.sqr()
+            w.copy(m); w.frob(f)
+        }
+        return w.equals(r)
+    }
+*/   
+}
+
diff --git a/version3/swift/pair192.swift b/version3/swift/pair192.swift
new file mode 100644
index 0000000..553d930
--- /dev/null
+++ b/version3/swift/pair192.swift
@@ -0,0 +1,512 @@
+/*
+	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.
+*/
+
+//
+//  pair192.swift
+//
+//  Created by Michael Scott on 07/07/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+/* AMCL BLS Curve Pairing functions */
+
+public struct PAIR192 {
+    
+    // Line function
+    static func linedbl(_ A: inout ECP4,_ Qx:FP,_ Qy:FP) -> FP24
+    {
+        var a:FP8
+        var b:FP8
+        var c:FP8
+
+        var XX=FP4(A.getx())  //X
+        var YY=FP4(A.gety())  //Y
+        var ZZ=FP4(A.getz())  //Z
+        var YZ=FP4(YY)        //Y 
+        YZ.mul(ZZ)                //YZ
+        XX.sqr()                  //X^2
+        YY.sqr()                  //Y^2
+        ZZ.sqr()                  //Z^2
+            
+        YZ.imul(4)
+        YZ.neg(); YZ.norm()       //-2YZ
+        YZ.qmul(Qy)               //-2YZ.Ys
+
+        XX.imul(6)               //3X^2
+        XX.qmul(Qx)              //3X^2.Xs
+
+        let sb=3*ROM.CURVE_B_I
+        ZZ.imul(sb)  
+        if ECP.SEXTIC_TWIST == ECP.D_TYPE {             
+            ZZ.div_2i();  
+        }
+        if ECP.SEXTIC_TWIST == ECP.M_TYPE {
+            ZZ.times_i()
+            ZZ.add(ZZ)
+            YZ.times_i()
+        }              
+        ZZ.norm() // 3b.Z^2 
+
+        YY.add(YY)
+        ZZ.sub(YY); ZZ.norm()     // 3b.Z^2-Y^2
+
+        a=FP8(YZ,ZZ)          // -2YZ.Ys | 3b.Z^2-Y^2 | 3X^2.Xs 
+        if ECP.SEXTIC_TWIST == ECP.D_TYPE {             
+            b=FP8(XX)            // L(0,1) | L(0,0) | L(1,0)
+            c=FP8(0)
+        } else { 
+            b=FP8(0)
+            c=FP8(XX); c.times_i()
+        }        
+        A.dbl()
+
+        return FP24(a,b,c)
+    }
+
+    static func lineadd(_ A: inout ECP4,_ B:ECP4,_ Qx:FP,_ Qy:FP) -> FP24
+    {
+        var a:FP8
+        var b:FP8
+        var c:FP8
+
+        var X1=FP4(A.getx())    // X1
+        var Y1=FP4(A.gety())    // Y1
+        var T1=FP4(A.getz())    // Z1
+        var T2=FP4(A.getz())    // Z1
+            
+        T1.mul(B.gety())    // T1=Z1.Y2 
+        T2.mul(B.getx())    // T2=Z1.X2
+
+        X1.sub(T2); X1.norm()  // X1=X1-Z1.X2
+        Y1.sub(T1); Y1.norm()  // Y1=Y1-Z1.Y2
+
+        T1.copy(X1)            // T1=X1-Z1.X2
+        X1.qmul(Qy)            // X1=(X1-Z1.X2).Ys
+        if ECP.SEXTIC_TWIST == ECP.M_TYPE {
+            X1.times_i()
+        }              
+        T1.mul(B.gety())       // T1=(X1-Z1.X2).Y2
+
+        T2.copy(Y1)            // T2=Y1-Z1.Y2
+        T2.mul(B.getx())       // T2=(Y1-Z1.Y2).X2
+        T2.sub(T1); T2.norm()          // T2=(Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2
+        Y1.qmul(Qx);  Y1.neg(); Y1.norm() // Y1=-(Y1-Z1.Y2).Xs
+
+        a=FP8(X1,T2)       // (X1-Z1.X2).Ys  |  (Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2  | - (Y1-Z1.Y2).Xs
+        if ECP.SEXTIC_TWIST == ECP.D_TYPE {              
+            b=FP8(Y1)
+            c=FP8(0)
+        } else {
+            b=FP8(0)
+            c=FP8(Y1); c.times_i()
+        }  
+        A.add(B)
+
+        return FP24(a,b,c)
+    }
+
+
+    // Optimal R-ate pairing
+    static public func ate(_ P1:ECP4,_ Q1:ECP) -> FP24
+    {
+        let x=BIG(ROM.CURVE_Bnx)
+        let n=BIG(x)
+        
+        var lv:FP24
+
+        var n3=BIG(n)
+        n3.pmul(3)
+        n3.norm()
+
+        var P=ECP4(); P.copy(P1); P.affine()
+        var Q=ECP(); Q.copy(Q1); Q.affine()
+
+
+        let Qx=FP(Q.getx())
+        let Qy=FP(Q.gety())
+    
+        var A=ECP4()
+        var r=FP24(1)
+    
+        A.copy(P)
+        var NP=ECP4()
+        NP.copy(P)
+        NP.neg()
+
+        let nb=n3.nbits()
+    
+        for i in (1...nb-2).reversed()
+        //for var i=nb-2;i>=1;i--
+        {
+            r.sqr()            
+            lv=linedbl(&A,Qx,Qy)
+            r.smul(lv,ECP.SEXTIC_TWIST)
+            let bt=n3.bit(UInt(i))-n.bit(UInt(i))
+            if bt == 1 {
+              lv=lineadd(&A,P,Qx,Qy)
+              r.smul(lv,ECP.SEXTIC_TWIST)
+            }
+            if bt == -1 {
+                //P.neg()
+                lv=lineadd(&A,NP,Qx,Qy)
+                r.smul(lv,ECP.SEXTIC_TWIST)
+                //P.neg()
+            }
+        }
+    
+        if ECP.SIGN_OF_X == ECP.NEGATIVEX {
+            r.conj()
+         }     
+
+        return r
+    }    
+
+    // Optimal R-ate double pairing e(P,Q).e(R,S)
+    static public func ate2(_ P1:ECP4,_ Q1:ECP,_ R1:ECP4,_ S1:ECP) -> FP24
+    {
+        let x=BIG(ROM.CURVE_Bnx)
+        let n=BIG(x)
+        var lv:FP24
+
+        var n3=BIG(n)
+        n3.pmul(3)
+        n3.norm()
+    
+        var P=ECP4(); P.copy(P1); P.affine()
+        var Q=ECP(); Q.copy(Q1); Q.affine()
+        var R=ECP4(); R.copy(R1); R.affine()
+        var S=ECP(); S.copy(S1); S.affine()
+
+
+        let Qx=FP(Q.getx())
+        let Qy=FP(Q.gety())
+        let Sx=FP(S.getx())
+        let Sy=FP(S.gety())
+    
+        var A=ECP4()
+        var B=ECP4()
+        var r=FP24(1)
+    
+        A.copy(P)
+        B.copy(R)
+        var NP=ECP4()
+        NP.copy(P)
+        NP.neg()
+        var NR=ECP4()
+        NR.copy(R)
+        NR.neg()
+
+        let nb=n3.nbits()
+    
+        for i in (1...nb-2).reversed()
+        {
+            r.sqr()            
+            lv=linedbl(&A,Qx,Qy)
+            r.smul(lv,ECP.SEXTIC_TWIST)
+            lv=linedbl(&B,Sx,Sy)
+            r.smul(lv,ECP.SEXTIC_TWIST)
+            let bt=n3.bit(UInt(i))-n.bit(UInt(i))
+
+            if bt == 1 {
+                lv=lineadd(&A,P,Qx,Qy)
+                r.smul(lv,ECP.SEXTIC_TWIST)
+                lv=lineadd(&B,R,Sx,Sy)
+                r.smul(lv,ECP.SEXTIC_TWIST)
+            }
+
+            if bt == -1 {
+                //P.neg(); 
+                lv=lineadd(&A,NP,Qx,Qy)
+                r.smul(lv,ECP.SEXTIC_TWIST)
+                //P.neg(); 
+                //R.neg()
+                lv=lineadd(&B,NR,Sx,Sy)
+                r.smul(lv,ECP.SEXTIC_TWIST)
+                //R.neg()                
+            }            
+
+        }
+    
+        if ECP.SIGN_OF_X == ECP.NEGATIVEX {
+            r.conj()
+        }     
+
+        return r
+    }
+    
+    // final exponentiation - keep separate for multi-pairings and to avoid thrashing stack
+    static public func fexp(_ m:FP24) -> FP24
+    {
+        let f=FP2(BIG(ROM.Fra),BIG(ROM.Frb));
+        var x=BIG(ROM.CURVE_Bnx)
+        var r=FP24(m)
+    
+    // Easy part of final exp
+        var lv=FP24(r)
+        lv.inverse()
+        r.conj()
+    
+        r.mul(lv)
+        lv.copy(r)
+        r.frob(f,4)
+        r.mul(lv)
+        
+    // Hard part of final exp
+
+        var t7=FP24(r); t7.usqr()
+        var t1=t7.pow(x)
+
+        x.fshr(1)
+        var t2=t1.pow(x)
+        x.fshl(1)
+
+        if ECP.SIGN_OF_X==ECP.NEGATIVEX {
+            t1.conj()
+        }
+        var t3=FP24(t1); t3.conj()
+        t2.mul(t3)
+        t2.mul(r)
+
+        t3.copy(t2.pow(x))
+        var t4=t3.pow(x)
+        var t5=t4.pow(x)
+
+        if ECP.SIGN_OF_X==ECP.NEGATIVEX {
+            t3.conj(); t5.conj()
+        }
+
+        t3.frob(f,6); t4.frob(f,5)
+        t3.mul(t4);
+
+        var t6=t5.pow(x)
+        if ECP.SIGN_OF_X==ECP.NEGATIVEX {
+            t6.conj()
+        }
+
+        t5.frob(f,4)
+        t3.mul(t5)
+
+        var t0=FP24(t2); t0.conj()
+        t6.mul(t0)
+
+        t5.copy(t6)
+        t5.frob(f,3)
+
+        t3.mul(t5)
+        t5.copy(t6.pow(x))
+        t6.copy(t5.pow(x))
+
+        if ECP.SIGN_OF_X==ECP.NEGATIVEX {
+            t5.conj()
+        }
+
+        t0.copy(t5)
+        t0.frob(f,2)
+        t3.mul(t0)
+        t0.copy(t6)
+        t0.frob(f,1)
+
+        t3.mul(t0)
+        t5.copy(t6.pow(x))
+
+        if ECP.SIGN_OF_X==ECP.NEGATIVEX {
+            t5.conj()
+        }
+        t2.frob(f,7)
+
+        t5.mul(t7)
+        t3.mul(t2)
+        t3.mul(t5)
+
+        r.mul(t3)
+
+        r.reduce()
+        return r
+    }
+
+    // GLV method
+    static func glv(_ e:BIG) -> [BIG]
+    {
+        var u=[BIG]();
+        let q=BIG(ROM.CURVE_Order)
+        var x=BIG(ROM.CURVE_Bnx)
+        let x2=BIG.smul(x,x)
+        x.copy(BIG.smul(x2,x2))
+        u.append(BIG(e))
+        u[0].mod(x)
+        u.append(BIG(e))
+        u[1].div(x)
+        u[1].rsub(q)
+
+        return u
+    }
+
+    // Galbraith & Scott Method
+    static func gs(_ e:BIG) -> [BIG]
+    {
+        var u=[BIG]();
+        let q=BIG(ROM.CURVE_Order)        
+        let x=BIG(ROM.CURVE_Bnx)
+        var w=BIG(e)
+        for i in 0 ..< 7
+        {
+            u.append(BIG(w))
+            u[i].mod(x)
+            w.div(x)
+        }
+        u.append(BIG(w))
+        if ECP.SIGN_OF_X == ECP.NEGATIVEX {
+            u[1].copy(BIG.modneg(u[1],q))
+            u[3].copy(BIG.modneg(u[3],q))         
+            u[5].copy(BIG.modneg(u[5],q))
+            u[7].copy(BIG.modneg(u[7],q))                       
+        }        
+
+        return u
+    }   
+
+
+    // Multiply P by e in group G1
+    static public func G1mul(_ P:ECP,_ e:BIG) -> ECP
+    {
+        var R:ECP
+        if (ROM.USE_GLV)
+        {
+            //P.affine()
+            R=ECP()
+            R.copy(P)
+            var Q=ECP()
+            Q.copy(P); Q.affine()
+            let q=BIG(ROM.CURVE_Order)
+            let cru=FP(BIG(ROM.CURVE_Cru))
+            var t=BIG(0)
+            var u=PAIR192.glv(e)
+            Q.mulx(cru);            
+    
+            var np=u[0].nbits()
+            t.copy(BIG.modneg(u[0],q))
+            var nn=t.nbits()
+            if (nn<np)
+            {
+                u[0].copy(t)
+                R.neg()
+            }
+    
+            np=u[1].nbits()
+            t.copy(BIG.modneg(u[1],q))
+            nn=t.nbits()
+            if (nn<np)
+            {
+                u[1].copy(t)
+                Q.neg()
+            }
+            u[0].norm()
+            u[1].norm()
+            R=R.mul2(u[0],Q,u[1])
+        }
+        else
+        {
+            R=P.mul(e)
+        }
+        return R
+    }
+
+    // Multiply P by e in group G2
+    static public func G2mul(_ P:ECP4,_ e:BIG) -> ECP4
+    {
+        var R:ECP4
+        if (ROM.USE_GS_G2)
+        {
+            var Q=[ECP4]()
+            let F=ECP4.frob_constants()
+            let q=BIG(ROM.CURVE_Order);
+            var u=PAIR192.gs(e);
+    
+            var t=BIG(0)
+            //P.affine()
+            Q.append(ECP4())
+            Q[0].copy(P);
+            for i in 1 ..< 8
+            {
+                Q.append(ECP4()); Q[i].copy(Q[i-1]);
+                Q[i].frob(F,1);
+            }
+            for i in 0 ..< 8
+            {
+                let np=u[i].nbits()
+                t.copy(BIG.modneg(u[i],q))
+                let nn=t.nbits()
+                if (nn<np)
+                {
+                    u[i].copy(t)
+                    Q[i].neg()
+                }
+                u[i].norm()
+            }
+    
+            R=ECP4.mul8(Q,u)
+        }
+        else
+        {
+            R=P.mul(e)
+        }
+        return R;
+    }
+
+    // f=f^e
+    // Note that this method requires a lot of RAM! Better to use compressed XTR method, see FP8.swift
+    static public func GTpow(_ d:FP24,_ e:BIG) -> FP24
+    {
+        var r:FP24
+        if (ROM.USE_GS_GT)
+        {
+            var g=[FP24]()
+            let f=FP2(BIG(ROM.Fra),BIG(ROM.Frb))
+            let q=BIG(ROM.CURVE_Order)
+            var t=BIG(0)
+        
+            var u=gs(e)
+            g.append(FP24(0))
+            g[0].copy(d);
+            for i in 1 ..< 8
+            {
+                g.append(FP24(0)); g[i].copy(g[i-1])
+                g[i].frob(f,1)
+            }
+            for i in 0 ..< 8
+            {
+                let np=u[i].nbits()
+                t.copy(BIG.modneg(u[i],q))
+                let nn=t.nbits()
+                if (nn<np)
+                {
+                    u[i].copy(t)
+                    g[i].conj()
+                }
+                u[i].norm()                
+            }
+            r=FP24.pow8(g,u)
+        }
+        else
+        {
+            r=d.pow(e)
+        }
+        return r
+    }
+}
diff --git a/version3/swift/pair256.swift b/version3/swift/pair256.swift
new file mode 100644
index 0000000..0c19dba
--- /dev/null
+++ b/version3/swift/pair256.swift
@@ -0,0 +1,587 @@
+/*
+	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.
+*/
+
+//
+//  pair256.swift
+//
+//  Created by Michael Scott on 07/07/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+/* AMCL BLS Curve Pairing functions */
+
+public struct PAIR256 {
+    
+    // Line function
+    static func linedbl(_ A: inout ECP8,_ Qx:FP,_ Qy:FP) -> FP48
+    {
+        var a:FP16
+        var b:FP16
+        var c:FP16
+
+        var XX=FP8(A.getx())  //X
+        var YY=FP8(A.gety())  //Y
+        var ZZ=FP8(A.getz())  //Z
+        var YZ=FP8(YY)        //Y 
+        YZ.mul(ZZ)                //YZ
+        XX.sqr()                  //X^2
+        YY.sqr()                  //Y^2
+        ZZ.sqr()                  //Z^2
+            
+        YZ.imul(4)
+        YZ.neg(); YZ.norm()       //-2YZ
+        YZ.tmul(Qy)               //-2YZ.Ys
+
+        XX.imul(6)               //3X^2
+        XX.tmul(Qx)              //3X^2.Xs
+
+        let sb=3*ROM.CURVE_B_I
+        ZZ.imul(sb)  
+        if ECP.SEXTIC_TWIST == ECP.D_TYPE {             
+            ZZ.div_2i();  
+        }
+        if ECP.SEXTIC_TWIST == ECP.M_TYPE {
+            ZZ.times_i()
+            ZZ.add(ZZ)
+            YZ.times_i()
+        }              
+        ZZ.norm() // 3b.Z^2 
+
+        YY.add(YY)
+        ZZ.sub(YY); ZZ.norm()     // 3b.Z^2-Y^2
+
+        a=FP16(YZ,ZZ)          // -2YZ.Ys | 3b.Z^2-Y^2 | 3X^2.Xs 
+        if ECP.SEXTIC_TWIST == ECP.D_TYPE {             
+            b=FP16(XX)            // L(0,1) | L(0,0) | L(1,0)
+            c=FP16(0)
+        } else { 
+            b=FP16(0)
+            c=FP16(XX); c.times_i()
+        }        
+        A.dbl()
+
+        return FP48(a,b,c)
+    }
+
+    static func lineadd(_ A: inout ECP8,_ B:ECP8,_ Qx:FP,_ Qy:FP) -> FP48
+    {
+        var a:FP16
+        var b:FP16
+        var c:FP16
+
+        var X1=FP8(A.getx())    // X1
+        var Y1=FP8(A.gety())    // Y1
+        var T1=FP8(A.getz())    // Z1
+        var T2=FP8(A.getz())    // Z1
+            
+        T1.mul(B.gety())    // T1=Z1.Y2 
+        T2.mul(B.getx())    // T2=Z1.X2
+
+        X1.sub(T2); X1.norm()  // X1=X1-Z1.X2
+        Y1.sub(T1); Y1.norm()  // Y1=Y1-Z1.Y2
+
+        T1.copy(X1)            // T1=X1-Z1.X2
+        X1.tmul(Qy)            // X1=(X1-Z1.X2).Ys
+        if ECP.SEXTIC_TWIST == ECP.M_TYPE {
+            X1.times_i()
+        }              
+        T1.mul(B.gety())       // T1=(X1-Z1.X2).Y2
+
+        T2.copy(Y1)            // T2=Y1-Z1.Y2
+        T2.mul(B.getx())       // T2=(Y1-Z1.Y2).X2
+        T2.sub(T1); T2.norm()          // T2=(Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2
+        Y1.tmul(Qx);  Y1.neg(); Y1.norm() // Y1=-(Y1-Z1.Y2).Xs
+
+        a=FP16(X1,T2)       // (X1-Z1.X2).Ys  |  (Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2  | - (Y1-Z1.Y2).Xs
+        if ECP.SEXTIC_TWIST == ECP.D_TYPE {              
+            b=FP16(Y1)
+            c=FP16(0)
+        } else {
+            b=FP16(0)
+            c=FP16(Y1); c.times_i()
+        }  
+        A.add(B)
+
+        return FP48(a,b,c)
+    }
+
+
+    // Optimal R-ate pairing
+    static public func ate(_ P1:ECP8,_ Q1:ECP) -> FP48
+    {
+        let x=BIG(ROM.CURVE_Bnx)
+        let n=BIG(x)
+        
+        var lv:FP48
+
+        var n3=BIG(n)
+        n3.pmul(3)
+        n3.norm()
+
+        var P=ECP8(); P.copy(P1); P.affine()
+        var Q=ECP(); Q.copy(Q1); Q.affine()
+
+        let Qx=FP(Q.getx())
+        let Qy=FP(Q.gety())
+    
+        var A=ECP8()
+        var r=FP48(1)
+    
+        A.copy(P)
+        var NP=ECP8()
+        NP.copy(P)
+        NP.neg()
+
+        let nb=n3.nbits()
+    
+        for i in (1...nb-2).reversed()
+        //for var i=nb-2;i>=1;i--
+        {
+            r.sqr()            
+            lv=linedbl(&A,Qx,Qy)
+            r.smul(lv,ECP.SEXTIC_TWIST)
+            let bt=n3.bit(UInt(i))-n.bit(UInt(i))
+            if bt == 1 {
+              lv=lineadd(&A,P,Qx,Qy)
+              r.smul(lv,ECP.SEXTIC_TWIST)
+            }
+            if bt == -1 {
+                //P.neg()
+                lv=lineadd(&A,NP,Qx,Qy)
+                r.smul(lv,ECP.SEXTIC_TWIST)
+                //P.neg()
+            }
+        }
+    
+        if ECP.SIGN_OF_X == ECP.NEGATIVEX {
+            r.conj()
+         }     
+
+        return r
+    }    
+
+    // Optimal R-ate double pairing e(P,Q).e(R,S)
+    static public func ate2(_ P1:ECP8,_ Q1:ECP,_ R1:ECP8,_ S1:ECP) -> FP48
+    {
+        let x=BIG(ROM.CURVE_Bnx)
+        let n=BIG(x)
+        var lv:FP48
+
+        var n3=BIG(n)
+        n3.pmul(3)
+        n3.norm()
+    
+        var P=ECP8(); P.copy(P1); P.affine()
+        var Q=ECP(); Q.copy(Q1); Q.affine()
+        var R=ECP8(); R.copy(R1); R.affine()
+        var S=ECP(); S.copy(S1); S.affine()
+
+
+        let Qx=FP(Q.getx())
+        let Qy=FP(Q.gety())
+        let Sx=FP(S.getx())
+        let Sy=FP(S.gety())
+    
+        var A=ECP8()
+        var B=ECP8()
+        var r=FP48(1)
+    
+        A.copy(P)
+        B.copy(R)
+        var NP=ECP8()
+        NP.copy(P)
+        NP.neg()
+        var NR=ECP8()
+        NR.copy(R)
+        NR.neg()
+
+        let nb=n3.nbits()
+    
+        for i in (1...nb-2).reversed()
+        {
+            r.sqr()            
+            lv=linedbl(&A,Qx,Qy)
+            r.smul(lv,ECP.SEXTIC_TWIST)
+            lv=linedbl(&B,Sx,Sy)
+            r.smul(lv,ECP.SEXTIC_TWIST)
+            let bt=n3.bit(UInt(i))-n.bit(UInt(i))
+
+            if bt == 1 {
+                lv=lineadd(&A,P,Qx,Qy)
+                r.smul(lv,ECP.SEXTIC_TWIST)
+                lv=lineadd(&B,R,Sx,Sy)
+                r.smul(lv,ECP.SEXTIC_TWIST)
+            }
+
+            if bt == -1 {
+                //P.neg(); 
+                lv=lineadd(&A,NP,Qx,Qy)
+                r.smul(lv,ECP.SEXTIC_TWIST)
+                //P.neg(); 
+                //R.neg()
+                lv=lineadd(&B,NR,Sx,Sy)
+                r.smul(lv,ECP.SEXTIC_TWIST)
+                //R.neg()                
+            }            
+
+        }
+    
+        if ECP.SIGN_OF_X == ECP.NEGATIVEX {
+            r.conj()
+        }     
+
+        return r
+    }
+
+    // final exponentiation - keep separate for multi-pairings and to avoid thrashing stack
+    static public func fexp(_ m:FP48) -> FP48
+    {
+        let f=FP2(BIG(ROM.Fra),BIG(ROM.Frb));
+        var x=BIG(ROM.CURVE_Bnx)
+        var r=FP48(m)
+    
+    // Easy part of final exp
+        var lv=FP48(r)
+        lv.inverse()
+        r.conj()
+    
+        r.mul(lv)
+        lv.copy(r)
+        r.frob(f,8)
+        r.mul(lv)
+        
+    // Hard part of final exp
+
+        var t7=FP48(r); t7.usqr()
+        var t1=t7.pow(x)
+
+        x.fshr(1)
+        var t2=t1.pow(x)
+        x.fshl(1)
+
+        if ECP.SIGN_OF_X==ECP.NEGATIVEX {
+            t1.conj()
+        }
+
+        var t3=FP48(t1); t3.conj()
+        t2.mul(t3)
+        t2.mul(r)
+
+        r.mul(t7)
+
+        t1.copy(t2.pow(x))
+        if ECP.SIGN_OF_X==ECP.NEGATIVEX {
+            t1.conj()
+        }
+        t3.copy(t1)
+        t3.frob(f,14)
+        r.mul(t3)
+        t1.copy(t1.pow(x))
+        if ECP.SIGN_OF_X==ECP.NEGATIVEX {
+            t1.conj()
+        }
+
+        t3.copy(t1)
+        t3.frob(f,13)
+        r.mul(t3)
+        t1.copy(t1.pow(x))
+        if ECP.SIGN_OF_X==ECP.NEGATIVEX {
+            t1.conj()
+        }
+
+        t3.copy(t1)
+        t3.frob(f,12)
+        r.mul(t3)
+        t1.copy(t1.pow(x))
+        if ECP.SIGN_OF_X==ECP.NEGATIVEX {
+            t1.conj()
+        }
+
+        t3.copy(t1)
+        t3.frob(f,11)
+        r.mul(t3)
+        t1.copy(t1.pow(x))
+        if ECP.SIGN_OF_X==ECP.NEGATIVEX {
+            t1.conj()
+        }
+
+        t3.copy(t1)
+        t3.frob(f,10)
+        r.mul(t3)
+        t1.copy(t1.pow(x))
+        if ECP.SIGN_OF_X==ECP.NEGATIVEX {
+            t1.conj()
+        }
+
+        t3.copy(t1)
+        t3.frob(f,9)
+        r.mul(t3)
+        t1.copy(t1.pow(x))
+        if ECP.SIGN_OF_X==ECP.NEGATIVEX {
+            t1.conj()
+        }
+
+        t3.copy(t1)
+        t3.frob(f,8)
+        r.mul(t3)
+        t1.copy(t1.pow(x))
+        if ECP.SIGN_OF_X==ECP.NEGATIVEX {
+            t1.conj()
+        }
+
+        t3.copy(t2); t3.conj()
+        t1.mul(t3)
+        t3.copy(t1);
+        t3.frob(f,7)
+        r.mul(t3)
+        t1.copy(t1.pow(x))
+        if ECP.SIGN_OF_X==ECP.NEGATIVEX {
+            t1.conj()
+        }
+
+        t3.copy(t1)
+        t3.frob(f,6)
+        r.mul(t3)
+        t1.copy(t1.pow(x))
+        if ECP.SIGN_OF_X==ECP.NEGATIVEX {
+            t1.conj()
+        }
+
+        t3.copy(t1)
+        t3.frob(f,5)
+        r.mul(t3)
+        t1.copy(t1.pow(x))
+        if ECP.SIGN_OF_X==ECP.NEGATIVEX {
+            t1.conj()
+        }
+
+        t3.copy(t1)
+        t3.frob(f,4)
+        r.mul(t3)
+        t1.copy(t1.pow(x))
+        if ECP.SIGN_OF_X==ECP.NEGATIVEX {
+            t1.conj()
+        }
+
+        t3.copy(t1)
+        t3.frob(f,3)
+        r.mul(t3)
+        t1.copy(t1.pow(x))
+        if ECP.SIGN_OF_X==ECP.NEGATIVEX {
+            t1.conj()
+        }
+
+        t3.copy(t1)
+        t3.frob(f,2)
+        r.mul(t3)
+        t1.copy(t1.pow(x))
+        if ECP.SIGN_OF_X==ECP.NEGATIVEX {
+            t1.conj()
+        }
+
+        t3.copy(t1)
+        t3.frob(f,1)
+        r.mul(t3)
+        t1.copy(t1.pow(x))
+        if ECP.SIGN_OF_X==ECP.NEGATIVEX {
+            t1.conj()
+        }
+    
+        r.mul(t1)
+        t2.frob(f,15)
+        r.mul(t2)
+
+        r.reduce()
+        return r
+    }
+
+    // GLV method
+    static func glv(_ e:BIG) -> [BIG]
+    {
+        var u=[BIG]();
+        let q=BIG(ROM.CURVE_Order)
+        var x=BIG(ROM.CURVE_Bnx)
+        var x2=BIG.smul(x,x)
+        x.copy(BIG.smul(x2,x2))
+        x2.copy(BIG.smul(x,x))
+        u.append(BIG(e))
+        u[0].mod(x2)
+        u.append(BIG(e))
+        u[1].div(x2)
+        u[1].rsub(q)
+
+        return u
+    }
+
+    // Galbraith & Scott Method
+    static func gs(_ e:BIG) -> [BIG]
+    {
+        var u=[BIG]();
+        let q=BIG(ROM.CURVE_Order)        
+        let x=BIG(ROM.CURVE_Bnx)
+        var w=BIG(e)
+        for i in 0 ..< 15
+        {
+            u.append(BIG(w))
+            u[i].mod(x)
+            w.div(x)
+        }
+        u.append(BIG(w))
+        if ECP.SIGN_OF_X == ECP.NEGATIVEX {
+            u[1].copy(BIG.modneg(u[1],q))
+            u[3].copy(BIG.modneg(u[3],q))         
+            u[5].copy(BIG.modneg(u[5],q))
+            u[7].copy(BIG.modneg(u[7],q))             
+            u[9].copy(BIG.modneg(u[9],q))
+            u[11].copy(BIG.modneg(u[11],q))         
+            u[13].copy(BIG.modneg(u[13],q))
+            u[15].copy(BIG.modneg(u[15],q))                              
+        }        
+
+        return u
+    }   
+
+    // Multiply P by e in group G1
+    static public func G1mul(_ P:ECP,_ e:BIG) -> ECP
+    {
+        var R:ECP
+        if (ROM.USE_GLV)
+        {
+            //P.affine()
+            R=ECP()
+            R.copy(P)
+            var Q=ECP()
+            Q.copy(P); Q.affine()
+            let q=BIG(ROM.CURVE_Order)
+            let cru=FP(BIG(ROM.CURVE_Cru))
+            var t=BIG(0)
+            var u=PAIR256.glv(e)
+            Q.mulx(cru);            
+    
+            var np=u[0].nbits()
+            t.copy(BIG.modneg(u[0],q))
+            var nn=t.nbits()
+            if (nn<np)
+            {
+                u[0].copy(t)
+                R.neg()
+            }
+    
+            np=u[1].nbits()
+            t.copy(BIG.modneg(u[1],q))
+            nn=t.nbits()
+            if (nn<np)
+            {
+                u[1].copy(t)
+                Q.neg()
+            }
+            u[0].norm()
+            u[1].norm()
+            R=R.mul2(u[0],Q,u[1])
+        }
+        else
+        {
+            R=P.mul(e)
+        }
+        return R
+    }
+
+    // Multiply P by e in group G2
+    static public func G2mul(_ P:ECP8,_ e:BIG) -> ECP8
+    {
+        var R:ECP8
+        if (ROM.USE_GS_G2)
+        {
+            var Q=[ECP8]()
+            let F=ECP8.frob_constants()
+            let q=BIG(ROM.CURVE_Order);
+            var u=PAIR256.gs(e);
+    
+            var t=BIG(0)
+            //P.affine()
+            Q.append(ECP8())
+            Q[0].copy(P);
+            for i in 1 ..< 16
+            {
+                Q.append(ECP8()); Q[i].copy(Q[i-1]);
+                Q[i].frob(F,1);
+            }
+            for i in 0 ..< 16
+            {
+                let np=u[i].nbits()
+                t.copy(BIG.modneg(u[i],q))
+                let nn=t.nbits()
+                if (nn<np)
+                {
+                    u[i].copy(t)
+                    Q[i].neg()
+                }
+                u[i].norm()
+            }
+    
+            R=ECP8.mul16(Q,u)
+        }
+        else
+        {
+            R=P.mul(e)
+        }
+        return R;
+    }
+
+    // f=f^e
+    // Note that this method requires a lot of RAM! Better to use compressed XTR method, see FP16.swift
+    static public func GTpow(_ d:FP48,_ e:BIG) -> FP48
+    {
+        var r:FP48
+        if (ROM.USE_GS_GT)
+        {
+            var g=[FP48]()
+            let f=FP2(BIG(ROM.Fra),BIG(ROM.Frb))
+            let q=BIG(ROM.CURVE_Order)
+            var t=BIG(0)
+        
+            var u=gs(e)
+            g.append(FP48(0))
+            g[0].copy(d);
+            for i in 1 ..< 16
+            {
+                g.append(FP48(0)); g[i].copy(g[i-1])
+                g[i].frob(f,1)
+            }
+            for i in 0 ..< 16
+            {
+                let np=u[i].nbits()
+                t.copy(BIG.modneg(u[i],q))
+                let nn=t.nbits()
+                if (nn<np)
+                {
+                    u[i].copy(t)
+                    g[i].conj()
+                }
+                u[i].norm()                
+            }
+            r=FP48.pow16(g,u)
+        }
+        else
+        {
+            r=d.pow(e)
+        }
+        return r
+    }
+}
diff --git a/version3/swift/rand.swift b/version3/swift/rand.swift
new file mode 100644
index 0000000..567fbcf
--- /dev/null
+++ b/version3/swift/rand.swift
@@ -0,0 +1,136 @@
+/*
+	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.
+*/
+
+//
+//  rand.swift
+//
+//  Created by Michael Scott on 17/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+//  Cryptographic strong random number generator
+
+/* Marsaglia & Zaman Random number generator constants */
+public struct RAND {
+    private static let NK:Int=21
+    private static let NJ:Int=6
+    private static let NV:Int=8
+    private var ira=[UInt32](repeating: 0,count: NK)
+    private var rndptr:Int=0
+    private var borrow:UInt32=0
+    private var pool_ptr:Int=0
+    private var pool=[UInt8](repeating: 0,count: 32)
+    
+    public mutating func clean()
+    {
+        pool_ptr=0
+        rndptr=0
+        for i in 0 ..< 32 {pool[i]=0}
+        for i in 0 ..< RAND.NK {ira[i]=0}
+        borrow=0;
+    }
+    
+    public init() {clean()}
+    
+    private mutating func sbrand() -> UInt32
+    { /* Marsaglia & Zaman random number generator */
+        rndptr+=1;
+        if rndptr<RAND.NK {return ira[rndptr]}
+        rndptr=0;
+        var k=RAND.NK-RAND.NJ
+        for i in 0 ..< RAND.NK
+        {
+            if k==RAND.NK {k=0}
+            let t=ira[k];
+            let pdiff=t &- ira[i] &- borrow
+            if pdiff<t {borrow=0}
+            if pdiff>t {borrow=1}
+            ira[i]=pdiff
+            k += 1;
+        }
+        return ira[0]
+    }
+    
+    mutating func sirand(_ seed: UInt32)
+    {
+        var m:UInt32=1
+        var s:UInt32=seed
+        borrow=0;
+        rndptr=0
+        ira[0]^=s
+        for i in 1 ..< RAND.NK
+        { /* fill initialisation vector */
+            let ipn=(RAND.NV*i)%RAND.NK
+            ira[ipn]^=m
+            let t=m
+            m=s &- m
+            s=t
+        }
+        for _ in 0 ..< 10000 {_ = sbrand()}
+    }
+    
+    private mutating func fill_pool()
+    {
+        var sh=HASH256()
+        for _ in 0 ..< 128 {sh.process(UInt8(sbrand()&0xff))}
+        pool=sh.hash()
+        pool_ptr=0
+    }
+    
+    private mutating func pack(_ b: [UInt8]) -> UInt32
+    {
+	var r=UInt32(b[3])<<24
+	r |=  UInt32(b[2])<<16
+	r |=  UInt32(b[1])<<8
+	r |=  UInt32(b[0])
+	return r
+        //return (UInt32(b[3])<<24)|(UInt32(b[2])<<16)|(UInt32(b[1])<<8)|(UInt32(b[0]))
+    }
+  
+/* Initialize RNG with some real entropy from some external source */
+    public mutating func seed(_ rawlen: Int,_ raw: [UInt8])
+    { /* initialise from at least 128 byte string of raw random entropy */
+        var digest=[UInt8]()
+        var b=[UInt8](repeating: 0, count: 4)
+        var sh=HASH256()
+        pool_ptr=0
+        for i in 0 ..< RAND.NK {ira[i]=0}
+        if rawlen>0
+        {
+            for i in 0 ..< rawlen {sh.process(raw[i])}
+            digest=sh.hash()
+            
+            for i in 0 ..< 8
+            {
+                b[0]=digest[4*i]; b[1]=digest[4*i+1]; b[2]=digest[4*i+2]; b[3]=digest[4*i+3]
+                sirand(pack(b))
+            }
+            
+        }
+        fill_pool()
+    }
+    
+    public mutating func getByte() -> UInt8
+    {
+        let r=pool[pool_ptr]; pool_ptr+=1
+        if pool_ptr>=32 {fill_pool()}
+        return r
+    }
+    
+    
+}
diff --git a/version3/swift/readme.txt b/version3/swift/readme.txt
new file mode 100644
index 0000000..7b272bd
--- /dev/null
+++ b/version3/swift/readme.txt
@@ -0,0 +1,43 @@
+
+NEW: 7/10/2018 classes replaced with structs, which are *much* faster (~50%).
+Who knew? Unfortunately Swift performance (as of 4.2) continues to be 
+crucified by its lack of support for short fixed length arrays allocated 
+from the stack. Instead they are allocated as variable length from the heap, 
+so the code spends more time doing garbage collection than doing crypto.
+
+Each supported primitive is implemented inside of its own swift namespace. 
+
+So for example to support both ed25519 and the NIST P256 curves, one
+could import into a particular module both "ed25519" and "nist256"
+
+Separate ROM files provide the constants required for each curve. Some
+files (big.swift, fp.swift, ecp.swift) also specify certain constants 
+that must be set for the particular curve.
+
+--------------------------------------
+
+To build the library and see it in action, copy all of the files in this 
+directory to a fresh root directory. Then execute the python3 script 
+config32.py or config64.py (depending om whether you want a 32 or 
+64-bit build), and select the curves that you wish to support. Libraries 
+will be built automatically including all of the modules that you will need.
+
+As a quick example execute from your root directory
+
+py config64.py
+
+or
+
+python3 config64.py
+
+Then select options 1, 3, 7, 18, 20, 25, 26 and 27 (these are fixed for the 
+example program provided). Select 0 to exit.
+
+Then execute
+
+swift -I. -L. -led25519 -lnist256 -lgoldilocks -lbn254 -lbls383 -lbls24 -lbls48 -lrsa2048 TestALL.swift 
+
+and
+
+swift -I. -L. -led25519 -lnist256 -lgoldilocks -lbn254 -lbls383 -lbls24 -lbls48 -lrsa2048 BenchtestALL.swift 
+
diff --git a/version3/swift/rom_anssi.swift b/version3/swift/rom_anssi.swift
new file mode 100644
index 0000000..a77017c
--- /dev/null
+++ b/version3/swift/rom_anssi.swift
@@ -0,0 +1,73 @@
+/*
+	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.
+*/
+
+//
+//  rom.swift
+//
+//  Created by Michael Scott on 12/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+final public class ROM{
+ 
+#if D32
+
+
+// Base Bits= 28
+//  anssi Curve Modulus
+static let Modulus:[Chunk] = [0x86E9C03,0xFCF353D,0x8CA6DE8,0xADBCABC,0x35B3961,0xE8CE424,0xF10126D,0xB3AD58,0x1FD178C,0xF]
+static let R2modp:[Chunk] = [0x288CC9C,0x18D2374,0x646BD2B,0x4929E67,0xD6F7F2D,0x220E6C1,0xABCE02E,0x751B1FD,0x7401B78,0xE]
+static let MConst:Chunk = 0x64E1155
+
+//  anssi Curve
+static let CURVE_Cof_I:Int = 1
+static let CURVE_Cof:[Chunk] = [0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static let CURVE_A:Int = -3
+static let CURVE_B_I:Int = 0
+static let CURVE_B:[Chunk] = [0xB7BB73F,0x75ED967,0x1A18030,0xC9AE4B,0xFDFEC,0x754A44C,0xD4ABA,0x5428A93,0xE353FCA,0xE]
+static public let CURVE_Order:[Chunk] = [0x6D655E1,0xFDD459C,0x2BF941F,0x67E140D,0x35B53DC,0xE8CE424,0xF10126D,0xB3AD58,0x1FD178C,0xF]
+static public let CURVE_Gx:[Chunk] = [0x98F5CFF,0xC97A2DD,0x8B70164,0xD2DCAF9,0x3958C27,0x4749D42,0xB31183D,0x56C139E,0x6B3D4C3,0xB]
+static public let CURVE_Gy:[Chunk] = [0x4062CFB,0x115A155,0x4C9E183,0xC307E8E,0xF8C2701,0xF0F3ECE,0x11F9271,0xC8B2049,0x142E0F7,0x6]
+
+
+#endif
+
+#if D64
+
+// Base Bits= 56
+//  anssi Curve Modulus
+static let Modulus:[Chunk] = [0xFCF353D86E9C03,0xADBCABC8CA6DE8,0xE8CE42435B3961,0xB3AD58F10126D,0xF1FD178C]
+static let R2modp:[Chunk] = [0x18D2374288CC9C,0x4929E67646BD2B,0x220E6C1D6F7F2D,0x751B1FDABCE02E,0xE7401B78]
+static let MConst:Chunk = 0x97483A164E1155
+
+//  anssi Curve
+static let CURVE_Cof_I:Int = 1
+static let CURVE_Cof:[Chunk] = [0x1,0x0,0x0,0x0,0x0]
+static let CURVE_A:Int = -3
+static let CURVE_B_I:Int = 0
+static let CURVE_B:[Chunk] = [0x75ED967B7BB73F,0xC9AE4B1A18030,0x754A44C00FDFEC,0x5428A9300D4ABA,0xEE353FCA]
+static public let CURVE_Order:[Chunk] = [0xFDD459C6D655E1,0x67E140D2BF941F,0xE8CE42435B53DC,0xB3AD58F10126D,0xF1FD178C]
+static public let CURVE_Gx:[Chunk] = [0xC97A2DD98F5CFF,0xD2DCAF98B70164,0x4749D423958C27,0x56C139EB31183D,0xB6B3D4C3]
+static public let CURVE_Gy:[Chunk] = [0x115A1554062CFB,0xC307E8E4C9E183,0xF0F3ECEF8C2701,0xC8B204911F9271,0x6142E0F7]
+
+
+#endif
+
+}
+
diff --git a/version3/swift/rom_bls24.swift b/version3/swift/rom_bls24.swift
new file mode 100644
index 0000000..6cc2817
--- /dev/null
+++ b/version3/swift/rom_bls24.swift
@@ -0,0 +1,104 @@
+/*
+	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.
+*/
+
+//
+//  rom.swift
+//
+final public class ROM{
+ 
+#if D32
+// Base Bits= 29
+//  bls24 Curve Modulus
+    
+static let Modulus:[Chunk] = [0xA06152B,0x2260B3A,0xB4C36BE,0x5FFC5D0,0xBDB6A64,0x5B78E2E,0x1C1A28CA,0x10E6441B,0x1F244061,0xB4704F0,0x141E5CCD,0x9837504,0x3F2E77E,0xD763740,0x1316EA0E,0xF0079,0x555C]
+static let R2modp:[Chunk] = [0x8533EA9,0x6A02789,0x183B24DE,0x1E45ECF8,0xC8F8F37,0x10CAD209,0x4C0C4B8,0x9B1FABD,0xDEBE4C0,0xDC353F9,0x18A18E26,0x10F489BB,0x31206A5,0x19673BBF,0x6BE69F9,0xB091169,0x9CD]
+static let MConst:Chunk = 0x95FE7D
+static public let Fra:[Chunk] = [0x1BF96F1D,0xAE53A55,0x31BFEEB,0x183FF17A,0x6237469,0x12A4F4F1,0x12101FE3,0x16E79D94,0xFF59267,0x5EB4EB4,0x78CC49F,0x274BA33,0x149184F3,0x16C6DCBA,0x1C90B694,0x10F729CE,0x4BBC]
+static public let Frb:[Chunk] = [0xE0CA60E,0x1740D0E4,0x83037D2,0xDBFD456,0x5B7F5FA,0x1312993D,0xA0A08E6,0x19FEA687,0xF2EADF9,0x55BB63C,0xC91982E,0x70EBAD1,0xF61628B,0x16AF5A85,0x16863379,0xF17D6AA,0x99F]
+
+static let CURVE_Cof_I:Int = 0
+static let CURVE_A:Int = 0
+static let CURVE_B_I:Int = 19
+static public let CURVE_B:[Chunk] = [0x13,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Order:[Chunk] = [0x10000001,0xD047FF,0x1FD54464,0x1E3CE067,0xE322DDA,0x1D356F3F,0x7433B44,0x49091F9,0x1729CC2,0x250286C,0x16E62ED,0xB403E1E,0x1001000,0x80,0x0,0x0,0x0]
+static public let CURVE_Gx:[Chunk] = [0xBE3CCD4,0x33B07AF,0x1B67D159,0x3DFC5B5,0xEBA1FCC,0x1A3C1F84,0x56BE204,0xEF8DF1B,0x11AE2D84,0x5FEE546,0x161B3BF9,0x183B20EE,0x1EA5D99B,0x14F0C5BF,0xBE521B7,0x17C682F9,0x1AB2]
+static public let CURVE_Gy:[Chunk] = [0x121E5245,0x65D2E56,0x11577DB1,0x16DACC11,0x14F39746,0x459F694,0x12483FCF,0xC828B04,0xFD63E5A,0x7B1D52,0xAFDE738,0xF349254,0x1A4529FF,0x10E53353,0xF91DEE1,0x16E18D8A,0x47FC]
+
+static public let CURVE_Bnx:[Chunk] = [0x11FF80,0x80010,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Cof:[Chunk] = [0x19F415AB,0x1E0FFDFF,0x15AAADFF,0xAA,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Cru:[Chunk] = [0xDD794A9,0x1DE138A3,0x2BCCE90,0xC746127,0x15223DDC,0x1DD8890B,0xED08DB7,0xE24B9F,0xE379CE6,0x37011AC,0x11BAC820,0x1EEFAD01,0x200860F,0x147218A6,0xF16A209,0xF0079,0x555C]
+static public let CURVE_Pxaa:[Chunk] = [0x14E24678,0x1F149A9B,0x9609022,0x1C186868,0xCDEFC69,0x1C87BB2E,0x14A2235F,0x7586755,0x5896747,0x159BFE92,0x3B5572E,0x1710A521,0x71EB14A,0xC643C33,0x12581DE5,0x1BCA747D,0x959]
+static public let CURVE_Pxab:[Chunk] = [0x1FB099B8,0x3FCF5D7,0x4A91C0E,0xC6EEB40,0x11FC2385,0x11B5AE8D,0x1A9CC3E7,0x194FE144,0x185DB2A5,0x930E1C7,0x14F85F9A,0x1F2ED4E,0x1D1BE5AD,0xF26169C,0xCF7F194,0x1DA1062E,0x3B0D]
+static public let CURVE_Pxba:[Chunk] = [0x11AD15D3,0xD0E6F38,0x17DB85BB,0x30A62F1,0x1EA3E09A,0x17B25FA1,0x1B7959AC,0x1165B19A,0x6C74FDB,0x18F790E1,0x12278FDA,0x1E008F79,0x103F329,0x14619FF1,0x1EBCAA8,0xFF5A9CA,0x3EC2]
+static public let CURVE_Pxbb:[Chunk] = [0x1EE0F480,0x3D5943A,0xF5B12E3,0x128AADC8,0x180E1CB9,0x1EFD916F,0x48BC7F,0x1D5EE1FA,0x5698EF5,0x11D6AED9,0x1386BC6E,0x196E900B,0x1CE2E465,0xC2A8ED3,0x1E67DF99,0x71B7940,0xA5B]
+static public let CURVE_Pyaa:[Chunk] = [0x14781AA0,0xC324C98,0xEDC2AC,0x16C13B46,0x145FC44B,0x12529530,0x1310A8C4,0x1768C5C0,0xE19AE68,0x56E1C1D,0x13DAF93F,0x17E94366,0xF901AD0,0x76800CC,0x10250D8B,0x1E6BAE6D,0x5057]
+static public let CURVE_Pyab:[Chunk] = [0xEAE08FA,0xDDF62BF,0xA97E5AB,0xF0EE97,0x99A42CA,0x1C326578,0xF33DC11,0x8B913F7,0xFEF8552,0x19F35B90,0x58DDBDE,0xFC32FF2,0x1587B5DF,0xB5EB07A,0x1A258DE0,0x1692CC3D,0x2CE2]
+static public let CURVE_Pyba:[Chunk] = [0x5F0CC41,0xB9813B5,0x14C2A87D,0xFF1264A,0x19AF8A14,0x6CE6C3,0x2A7F8A2,0x121DCA7D,0x7D37153,0x19D21078,0x15466DC7,0x1362982B,0x1DD3CB5B,0x1CFC0D1C,0x18C69AF8,0x8CC7DC,0x1807]
+static public let CURVE_Pybb:[Chunk] = [0x115C1CAE,0x78D9732,0x16C26237,0x5A81A6A,0x1C38A777,0x56121FE,0x4DAD9D7,0x1BEBA670,0xA1D72FC,0xD60B274,0x19734258,0x1D621775,0x4691771,0x14206B68,0x17B22DE4,0x29D5B37,0x499D]
+static let CURVE_W:[[Chunk]] = [[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]
+static let CURVE_SB:[[[Chunk]]] = [[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]] 
+static let CURVE_WB:[[Chunk]] = [[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]
+static let CURVE_BB:[[[Chunk]]] = [[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]]
+
+
+
+#endif
+
+#if D64
+// Base Bits= 56
+
+static let Modulus:[Chunk] = [0x44C1674A06152B,0xFFE2E82D30DAF8,0x6F1C5CBDB6A642,0x3220DF068A328B,0xE09E1F24406187,0xBA825079733568,0x6E803F2E77E4C1,0x3CCC5BA839AEC,0x555C0078]
+static let R2modp:[Chunk] = [0x6A4A1FE013DF5B,0xE8E46D4D1BDE65,0x1F841391F45C67,0x9148A4516FB28,0x4398524EDF4C88,0x41C0E241B6DCE8,0xE42C208C19411,0xA7FE6FD73A7B1C,0xFCCCA76]
+static let MConst:Chunk = 0xBD5D7D8095FE7D
+static public let Fra:[Chunk] = [0x5CA74ABBF96F1D,0x1FF8BD0C6FFBAD,0x49E9E26237469C,0x3CECA48407F8E5,0x69D68FF59267B7,0x5D199E33127CBD,0xB97549184F313A,0x4E77242DA52D8D,0x4BBC87B9]
+static public let Frb:[Chunk] = [0xE81A1C8E0CA60E,0xDFEA2B20C0DF4A,0x25327A5B7F5FA6,0xF5343A828239A6,0x76C78F2EADF9CF,0x5D68B24660B8AB,0xB50AF61628B387,0xB555A18CDE6D5E,0x99F78BE]
+
+static let CURVE_Cof_I:Int = 0
+static let CURVE_A:Int = 0
+static let CURVE_B_I:Int = 19
+static public let CURVE_B:[Chunk] = [0x13,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Order:[Chunk] = [0x1A08FFF0000001,0x1E7033FF551190,0x6ADE7EE322DDAF,0x848FC9D0CED13A,0x50D81729CC224,0x1F0F05B98BB44A,0x10010010005A0,0x0,0x0]
+static public let CURVE_Gx:[Chunk] = [0x6760F5EBE3CCD4,0xEFE2DAED9F4564,0x783F08EBA1FCC1,0xC6F8D95AF88134,0xDCA8D1AE2D8477,0x9077586CEFE4BF,0x8B7FEA5D99BC1D,0x17CAF9486DE9E1,0x1AB2BE34]
+static public let CURVE_Gy:[Chunk] = [0xCBA5CAD21E5245,0x6D6608C55DF6C4,0xB3ED294F39746B,0x145824920FF3C8,0x63AA4FD63E5A64,0x492A2BF79CE00F,0x66A7A4529FF79A,0x6C53E477B861CA,0x47FCB70C]
+
+static public let CURVE_Bnx:[Chunk] = [0x100020011FF80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Cof:[Chunk] = [0xC1FFBFF9F415AB,0x5556AAB7FF,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Cru:[Chunk] = [0xBC27146DD794A9,0x3A30938AF33A43,0xB112175223DDC6,0x125CFBB4236DFB,0x2358E379CE607,0xD680C6EB20806E,0x314C200860FF77,0x3CBC5A88268E4,0x555C0078]
+static public let CURVE_Pxaa:[Chunk] = [0xE2935374E24678,0xC34342582408B,0xF765CCDEFC69E,0xC33AAD2888D7F9,0x7FD2458967473A,0x52908ED55CBAB3,0x786671EB14AB88,0xA3EC96077958C8,0x959DE53]
+static public let CURVE_Pxab:[Chunk] = [0x7F9EBAFFB099B8,0x3775A012A47038,0x6B5D1B1FC23856,0x7F0A26A730F9E3,0x1C38F85DB2A5CA,0x76A753E17E6926,0x2D39D1BE5AD0F9,0x31733DFC651E4C,0x3B0DED08]
+static public let CURVE_Pxba:[Chunk] = [0xA1CDE711AD15D3,0x853178DF6E16ED,0x64BF43EA3E09A1,0x2D8CD6DE566B2F,0xF21C26C74FDB8B,0x47BCC89E3F6B1E,0x3FE2103F329F00,0x4E507AF2AA28C3,0x3EC27FAD]
+static public let CURVE_Pxbb:[Chunk] = [0x7AB2875EE0F480,0x4556E43D6C4B8C,0xFB22DF80E1CB99,0xF70FD0122F1FFD,0xD5DB25698EF5EA,0x4805CE1AF1BA3A,0x1DA7CE2E465CB7,0xCA0799F7E65855,0xA5B38DB]
+static public let CURVE_Pyaa:[Chunk] = [0x86499314781AA0,0x609DA303B70AB1,0xA52A6145FC44BB,0x462E04C42A3124,0xC383AE19AE68BB,0xA1B34F6BE4FCAD,0x198F901AD0BF4,0x736C094362CED0,0x5057F35D]
+static public let CURVE_Pyab:[Chunk] = [0xBBEC57EEAE08FA,0x78774BAA5F96AD,0x64CAF099A42CA0,0xC89FBBCCF70478,0x6B720FEF855245,0x97F916376F7B3E,0x60F5587B5DF7E1,0x61EE89637816BD,0x2CE2B496]
+static public let CURVE_Pyba:[Chunk] = [0x730276A5F0CC41,0xF89325530AA1F5,0xD9CD879AF8A147,0xEE53E8A9FE2880,0x420F07D3715390,0x4C15D519B71F3A,0x1A39DD3CB5B9B1,0x3EE631A6BE39F8,0x18070466]
+static public let CURVE_Pybb:[Chunk] = [0xF1B2E6515C1CAE,0xD40D355B0988DC,0xC243FDC38A7772,0x5D338136B675CA,0x164E8A1D72FCDF,0xBBAE5CD0961AC,0xD6D04691771EB1,0xD9BDEC8B792840,0x499D14EA]
+static let CURVE_W:[[Chunk]] = [[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]
+static let CURVE_SB:[[[Chunk]]] = [[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]]
+static let CURVE_WB:[[Chunk]] = [[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]
+static let CURVE_BB:[[[Chunk]]] = [[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]]
+
+#endif
+
+    static let USE_GLV = true
+    static let USE_GS_G2 = true
+    static let USE_GS_GT = true
+    static let GT_STRONG = true
+
+}
+
diff --git a/version3/swift/rom_bls381.swift b/version3/swift/rom_bls381.swift
new file mode 100644
index 0000000..226dae7
--- /dev/null
+++ b/version3/swift/rom_bls381.swift
@@ -0,0 +1,105 @@
+/*
+	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.
+*/
+
+//
+//  rom.swift
+//
+//  Created by Michael Scott on 12/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+final public class ROM{
+ 
+#if D32
+
+// Base Bits= 29
+//  bls381 Curve Modulus
+
+
+static let Modulus:[Chunk] = [0x1FFFAAAB,0xFF7FFFF,0x14FFFFEE,0x17FFFD62,0xF6241EA,0x9507B58,0xAFD9CC3,0x109E70A2,0x1764774B,0x121A5D66,0x12C6E9ED,0x12FFCD34,0x111EA3,0xD]
+static let R2modp:[Chunk] = [0x15BEF7AE,0x1031CD0E,0x2DD93E8,0x9226323,0xE6E2CD2,0x11684DAA,0x1170E5DB,0x88E25B1,0x1B366399,0x1C536F47,0xD1F9CBC,0x278B67F,0x1EA66A2B,0xC]
+static let MConst:Chunk = 0x1FFCFFFD
+static public let Fra:[Chunk] = [0x12235FB8,0x83BAF6C,0x19E04F63,0x1D4A7AC7,0xB9C4F67,0x1EBC25D,0x1D3DEC91,0x1FA797AB,0x1F0FD603,0x1016068,0x108C6FAD,0x5760CCF,0x104D3BF0,0xC]
+static public let Frb:[Chunk] = [0xDDC4AF3,0x7BC5093,0x1B1FB08B,0x1AB5829A,0x3C5F282,0x764B8FB,0xDBFB032,0x10F6D8F6,0x1854A147,0x1118FCFD,0x23A7A40,0xD89C065,0xFC3E2B3,0x0]
+
+static let CURVE_Cof_I:Int = 0
+static let CURVE_A:Int = 0
+static let CURVE_B_I:Int = 4
+static public let CURVE_B:[Chunk] = [0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Order:[Chunk] = [0x1,0x1FFFFFF8,0x1F96FFBF,0x1B4805FF,0x1D80553B,0xC0404D0,0x1520CCE7,0xA6533AF,0x73EDA7,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Gx:[Chunk] = [0x1B22C6BB,0x19D78056,0x1E86BBFE,0xBD07FF2,0x1AC586C5,0x1D1F8B8D,0x4168538,0x9F2EE97,0xFC3688C,0x27D4D60,0x9A558E3,0x32FAF28,0x1F1D3A73,0xB]
+static public let CURVE_Gy:[Chunk] = [0x6C5E7E1,0x551194A,0x222B903,0x198E8945,0xB3EDD03,0xC659602,0xBD8036C,0x12BABA01,0x4FCF5E0,0xBA0EC57,0x8278C3B,0x75541E3,0xB3F481E,0x4]
+
+static public let CURVE_Bnx:[Chunk] = [0x10000,0x10080000,0x34,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Cof:[Chunk] = [0xAAAB,0x55558,0x157855A3,0x191800AA,0x396,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Cru:[Chunk] = [0x1FFEFFFE,0x100FFFFF,0x280008B,0xFB026C4,0x9688DE1,0x149DF37C,0x1FAB76CE,0xED41EE,0x11BA69C6,0x1EFBB672,0x17C659CB,0x0,0x0,0x0]
+
+static public let CURVE_Pxa:[Chunk] = [0x121BDB8,0x402B646,0x16EFBF5,0x18064D50,0x1D1770BA,0x5B23D71,0xC0AD144,0x1A9F4807,0x11C6E47A,0x196E2882,0x9820149,0x11E1522,0x4AA2B2F,0x1]
+static public let CURVE_Pxb:[Chunk] = [0x1D042B7E,0xD63E82A,0x51755F9,0x19E22427,0x15049334,0x10DDEE3F,0x186AD769,0x1A132416,0x5596BD0,0x4413A7B,0x1F6B34E8,0x4E33EC0,0x1E02B605,0x9]
+static public let CURVE_Pya:[Chunk] = [0x8B82801,0xC9AA430,0xB28A278,0x15939877,0xD12C923,0xD34A8B0,0xE9DB50A,0x155197BA,0x1AADFD9B,0x16D171A8,0x3327371,0x4FADC23,0xE5D5277,0x6]
+static public let CURVE_Pyb:[Chunk] = [0x105F79BE,0x15483AFF,0x1B07686A,0xE1A4EB9,0x99AB3F3,0x955AB97,0xEBC99D2,0xFD0B4EC,0x19CB3E28,0x15E145C,0xCAB34AC,0x1D4E6998,0x6C4A02,0x3]
+static let CURVE_W:[[Chunk]] = [[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]
+static let CURVE_SB:[[[Chunk]]] = [[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]]
+static let CURVE_WB:[[Chunk]] = [[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]
+static let CURVE_BB:[[[Chunk]]] = [[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]]
+
+#endif
+
+#if D64
+
+// Base Bits= 58
+//  bls381 Curve Modulus
+
+static let Modulus:[Chunk] = [0x1FEFFFFFFFFAAAB,0x2FFFFAC54FFFFEE,0x12A0F6B0F6241EA,0x213CE144AFD9CC3,0x2434BACD764774B,0x25FF9A692C6E9ED,0x1A0111EA3]
+static let R2modp:[Chunk] = [0x20639A1D5BEF7AE,0x1244C6462DD93E8,0x22D09B54E6E2CD2,0x111C4B63170E5DB,0x38A6DE8FB366399,0x4F16CFED1F9CBC,0x19EA66A2B]
+static let MConst:Chunk = 0x1F3FFFCFFFCFFFD
+static public let Fra:[Chunk] = [0x10775ED92235FB8,0x3A94F58F9E04F63,0x3D784BAB9C4F67,0x3F4F2F57D3DEC91,0x202C0D1F0FD603,0xAEC199F08C6FAD,0x1904D3BF0]
+static public let Frb:[Chunk] = [0xF78A126DDC4AF3,0x356B0535B1FB08B,0xEC971F63C5F282,0x21EDB1ECDBFB032,0x2231F9FB854A147,0x1B1380CA23A7A40,0xFC3E2B3]
+
+static let CURVE_Cof_I:Int = 0
+static let CURVE_A:Int = 0
+static let CURVE_B_I:Int = 4
+static public let CURVE_B:[Chunk] = [0x4,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Order:[Chunk] = [0x3FFFFFF00000001,0x36900BFFF96FFBF,0x180809A1D80553B,0x14CA675F520CCE7,0x73EDA7,0x0,0x0]
+static public let CURVE_Gx:[Chunk] = [0x33AF00ADB22C6BB,0x17A0FFE5E86BBFE,0x3A3F171BAC586C5,0x13E5DD2E4168538,0x4FA9AC0FC3688C,0x65F5E509A558E3,0x17F1D3A73]
+static public let CURVE_Gy:[Chunk] = [0xAA232946C5E7E1,0x331D128A222B903,0x18CB2C04B3EDD03,0x25757402BD8036C,0x1741D8AE4FCF5E0,0xEAA83C68278C3B,0x8B3F481E]
+
+
+static public let CURVE_Bnx:[Chunk] = [0x201000000010000,0x34,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Cof:[Chunk] = [0xAAAB0000AAAB,0x3230015557855A3,0x396,0x0,0x0,0x0,0x0]
+static public let CURVE_Cru:[Chunk] = [0x201FFFFFFFEFFFE,0x1F604D88280008B,0x293BE6F89688DE1,0x1DA83DDFAB76CE,0x3DF76CE51BA69C6,0x17C659CB,0x0]
+
+static public let CURVE_Pxa:[Chunk] = [0x8056C8C121BDB8,0x300C9AA016EFBF5,0xB647AE3D1770BA,0x353E900EC0AD144,0x32DC51051C6E47A,0x23C2A449820149,0x24AA2B2F]
+static public let CURVE_Pxb:[Chunk] = [0x1AC7D055D042B7E,0x33C4484E51755F9,0x21BBDC7F5049334,0x3426482D86AD769,0x88274F65596BD0,0x9C67D81F6B34E8,0x13E02B605]
+static public let CURVE_Pya:[Chunk] = [0x193548608B82801,0x2B2730EEB28A278,0x1A695160D12C923,0x2AA32F74E9DB50A,0x2DA2E351AADFD9B,0x9F5B8463327371,0xCE5D5277]
+static public let CURVE_Pyb:[Chunk] = [0x2A9075FF05F79BE,0x1C349D73B07686A,0x12AB572E99AB3F3,0x1FA169D8EBC99D2,0x2BC28B99CB3E28,0x3A9CD330CAB34AC,0x606C4A02]
+static let CURVE_W:[[Chunk]] = [[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]]
+static let CURVE_SB:[[[Chunk]]] = [[[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]]] 
+static let CURVE_WB:[[Chunk]] = [[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]]
+static let CURVE_BB:[[[Chunk]]] = [[[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]]]
+
+#endif
+
+    static let USE_GLV = true
+    static let USE_GS_G2 = true
+    static let USE_GS_GT = true
+    static let GT_STRONG = false
+
+}
+
diff --git a/version3/swift/rom_bls383.swift b/version3/swift/rom_bls383.swift
new file mode 100644
index 0000000..cd4a8a3
--- /dev/null
+++ b/version3/swift/rom_bls383.swift
@@ -0,0 +1,101 @@
+/*
+	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.
+*/
+
+//
+//  rom.swift
+//
+//  Created by Michael Scott on 12/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+final public class ROM{
+ 
+#if D32
+
+
+// Base Bits= 29
+static let Modulus:[Chunk] = [0x5AAB0AB,0x11B8EB24,0x19214AF6,0x187E5314,0x124F47A8,0x1C00B4B0,0x1446B0C6,0x59E6CB4,0x4A0AD46,0xFF5494,0x81B6B71,0x956DD6B,0x16556956,0x2A]
+static let R2modp:[Chunk] = [0x116907F4,0x405B700,0x1752AC11,0x67A9E7C,0x1941C581,0x1AEA38C4,0xB1E4D22,0xCE841AE,0xA0FC49B,0xB4B1F48,0x13852312,0x1B3FDCED,0x1FECE397,0x26]
+static let MConst:Chunk = 0x73435FD
+static public let Fra:[Chunk] = [0x1311DAC1,0x296B969,0x19DCF806,0x126901FC,0xD8C8A36,0x1A2572A8,0xA1A0959,0x1A47F743,0x110E4C6C,0x1608DA97,0xCE2E7F0,0x4FED178,0xACD5BF0,0x11]
+static public let Frb:[Chunk] = [0x1298D5EA,0xF2231BA,0x1F4452F0,0x6155117,0x4C2BD72,0x1DB4208,0xA2CA76D,0xB567571,0x139260D9,0xAF679FC,0x1B388380,0x4580BF2,0xB880D66,0x19]
+
+static let CURVE_A:Int = 0
+static let CURVE_Cof_I:Int = 0
+static public let CURVE_Cof:[Chunk] = [0x15169EAB,0xA82AB0A,0xAAEFFED,0x15558001,0x555,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static let CURVE_B_I:Int = 15
+static public let CURVE_B:[Chunk] = [0xF,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Order:[Chunk] = [0x1EBC0001,0x1904CF5F,0x834E5CE,0xBE12B42,0xB381DE0,0xE40B4C,0x270110,0x10018017,0x1002001,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Gx:[Chunk] = [0x8734573,0x623B9C8,0x1D1DC11E,0xBB7E107,0x1E3445C5,0x1D6C2578,0x10B0BE1E,0xED6103E,0x10F31D9F,0x296ED82,0x18E0D7D0,0x12F3D9C9,0x1FCBA55B,0x20]
+static public let CURVE_Gy:[Chunk] = [0x3F224,0x968B2F4,0x1FE63F48,0xFA93D90,0x14D2DDE5,0x54A56F5,0x12441D4C,0x18CD76C8,0x199D0DAD,0xE18E236,0x92BA73,0x99F6600,0x8F16727,0x3]
+
+static public let CURVE_Bnx:[Chunk] = [0x1001200,0x400000,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Cru:[Chunk] = [0xEAAC2A9,0x61B3A81,0x17D974B7,0xBED0345,0xA341BC2,0x17A51A6F,0x5738948,0x69B7BAE,0x14605445,0x374A43,0x8116AD1,0x956DD69,0x16556956,0x2A]
+static public let CURVE_Pxa:[Chunk] = [0xD7F2D86,0x1E59DB1,0x17474F85,0x1FB56CF2,0x572EE81,0xE487AB1,0x96F51FC,0x190A5AAE,0x6432501,0x13E58F3A,0x101E6425,0xFD807D1,0x34D2240,0x3]
+static public let CURVE_Pxb:[Chunk] = [0x452DE15,0x1ECF20F6,0x1FF9837B,0x95651AA,0xD5D75B5,0x5D44749,0x12277F66,0x1DB3A0B9,0x1D24F498,0x19441B0E,0x1CDE9DC5,0x2C975,0xD78006,0x18]
+static public let CURVE_Pya:[Chunk] = [0x1408CB41,0x34785DC,0x3586597,0x13DBC9E4,0x1A2E75B4,0x1D65489,0xCF9A25E,0x1ACE7933,0x1B6E990E,0x19FF31A3,0x12527615,0x1A44A68F,0x1792CF93,0x19]
+static public let CURVE_Pyb:[Chunk] = [0x1F479093,0x16C2321B,0x1889218E,0x87961BC,0x1BC98B01,0x197A24FB,0xA3DEBC2,0x88D67DF,0x1CE0D,0x1E8AD3D7,0x93B9EE9,0x59B18D6,0xE5247DD,0x10]
+static let CURVE_W:[[Chunk]] = [[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]
+static let CURVE_SB:[[[Chunk]]] = [[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]]
+static let CURVE_WB:[[Chunk]] = [[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]
+static let CURVE_BB:[[[Chunk]]] = [[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]]    
+
+#endif
+
+#if D64
+
+// Base Bits= 58
+static let Modulus:[Chunk] = [0x2371D6485AAB0AB,0x30FCA6299214AF6,0x3801696124F47A8,0xB3CD969446B0C6,0x1FEA9284A0AD46,0x12ADBAD681B6B71,0x556556956]
+static let R2modp:[Chunk] = [0x80B6E0116907F4,0xCF53CF9752AC11,0x35D47189941C581,0x19D0835CB1E4D22,0x16963E90A0FC49B,0x367FB9DB3852312,0x4DFECE397]
+static let MConst:Chunk = 0x1BC0571073435FD
+static public let Fra:[Chunk] = [0x52D72D3311DAC1,0x24D203F99DCF806,0x344AE550D8C8A36,0x348FEE86A1A0959,0x2C11B52F10E4C6C,0x9FDA2F0CE2E7F0,0x22ACD5BF0]
+static public let Frb:[Chunk] = [0x1E446375298D5EA,0xC2AA22FF4452F0,0x3B684104C2BD72,0x16ACEAE2A2CA76D,0x15ECF3F939260D9,0x8B017E5B388380,0x32B880D66]
+
+//*** rom curve parameters *****
+// Base Bits= 58
+
+static let CURVE_A:Int = 0
+static let CURVE_Cof_I:Int = 0
+static public let CURVE_Cof:[Chunk] = [0x150556155169EAB,0x2AAB0002AAEFFED,0x555,0x0,0x0,0x0,0x0]
+static let CURVE_B_I:Int = 15
+static public let CURVE_B:[Chunk] = [0xF,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Order:[Chunk] = [0x32099EBFEBC0001,0x17C25684834E5CE,0x1C81698B381DE0,0x2003002E0270110,0x1002001,0x0,0x0]
+static public let CURVE_Gx:[Chunk] = [0xC4773908734573,0x176FC20FD1DC11E,0x3AD84AF1E3445C5,0x1DAC207D0B0BE1E,0x52DDB050F31D9F,0x25E7B3938E0D7D0,0x41FCBA55B]
+static public let CURVE_Gy:[Chunk] = [0x12D165E8003F224,0x1F527B21FE63F48,0xA94ADEB4D2DDE5,0x319AED912441D4C,0x1C31C46D99D0DAD,0x133ECC00092BA73,0x68F16727]
+
+static public let CURVE_Bnx:[Chunk] = [0x8000001001200,0x40,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Cru:[Chunk] = [0xC367502EAAC2A9,0x17DA068B7D974B7,0x2F4A34DEA341BC2,0xD36F75C5738948,0x6E94874605445,0x12ADBAD28116AD1,0x556556956]
+static public let CURVE_Pxa:[Chunk] = [0x3CB3B62D7F2D86,0x3F6AD9E57474F85,0x1C90F562572EE81,0x3214B55C96F51FC,0x27CB1E746432501,0x1FB00FA301E6425,0x634D2240]
+static public let CURVE_Pxb:[Chunk] = [0x3D9E41EC452DE15,0x12ACA355FF9837B,0xBA88E92D5D75B5,0x3B6741732277F66,0x3288361DD24F498,0x592EBCDE9DC5,0x300D78006]
+static public let CURVE_Pya:[Chunk] = [0x68F0BB9408CB41,0x27B793C83586597,0x3ACA913A2E75B4,0x359CF266CF9A25E,0x33FE6347B6E990E,0x34894D1F2527615,0x33792CF93]
+static public let CURVE_Pyb:[Chunk] = [0x2D846437F479093,0x10F2C379889218E,0x32F449F7BC98B01,0x111ACFBEA3DEBC2,0x3D15A7AE001CE0D,0xB3631AC93B9EE9,0x20E5247DD]
+static let CURVE_W:[[Chunk]] = [[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]]
+static let CURVE_SB:[[[Chunk]]] = [[[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]]]
+static let CURVE_WB:[[Chunk]] = [[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]]
+static let CURVE_BB:[[[Chunk]]] = [[[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]]]
+
+#endif
+
+    static let USE_GLV = true
+    static let USE_GS_G2 = true
+    static let USE_GS_GT = true
+    static let GT_STRONG = true
+
+}
+
diff --git a/version3/swift/rom_bls461.swift b/version3/swift/rom_bls461.swift
new file mode 100644
index 0000000..033d0ab
--- /dev/null
+++ b/version3/swift/rom_bls461.swift
@@ -0,0 +1,107 @@
+/*
+	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.
+*/
+
+//
+//  rom.swift
+//
+//  Created by Michael Scott on 12/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+final public class ROM{
+ 
+#if D32
+
+
+// Base Bits= 28
+//  bls461 Curve Modulus
+
+
+static let Modulus:[Chunk] = [0xAAAAAAB,0xAC0000A,0x54AAAAA,0x5555,0x400020,0x91557F0,0xF26AA,0xFA5C1CC,0xB42A8DF,0x7B14848,0x8BACCA4,0x6F1E32D,0x4935FBD,0x55D6941,0xD5A555A,0x5545554,0x1555]
+static let R2modp:[Chunk] = [0xC9B6A33,0x2ECD087,0x3CCB2B1,0xCD461FE,0x8CB5AB2,0xC5B9635,0x5312E92,0xB659F64,0x3B596FA,0x8679006,0xA92E2B3,0x3CE05E3,0x363550F,0x7C07A8E,0x382C083,0x6347FEA,0xBD]
+static let MConst:Chunk = 0xFFFFFFD
+static public let Fra:[Chunk] = [0xB812A3A,0x7117BF9,0x99C400F,0xC6308A5,0x5BF8A1,0x510E075,0x45FA5A6,0xCE4858D,0x770B31A,0xBC2CB04,0xE2FC61E,0xD073588,0x4366190,0x4DFEFA8,0x69E55E2,0x504B7F,0x12E4]
+static public let Frb:[Chunk] = [0xF298071,0x3AE8410,0xBAE6A9B,0x39D4CAF,0xFE4077E,0x404777A,0xBAF8104,0x2C13C3E,0x3D1F5C5,0xBEE7D44,0xA8B0685,0x9EAADA4,0x5CFE2C,0x7D7999,0x6BBFF78,0x50409D5,0x271]
+
+// bls461 Curve
+
+static let CURVE_Cof_I:Int = 0
+static let CURVE_A:Int = 0
+static let CURVE_B_I:Int = 9
+static public let CURVE_B:[Chunk] = [0x9,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Order:[Chunk] = [0x1,0x0,0xFFFFC00,0x7FEFFFE,0x110000,0x7FFC800,0x801FC01,0x5FD000E,0x17FE0,0xFFFC018,0xFFFFFF7,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Gx:[Chunk] = [0xADEE93D,0x4D026A8,0x74B7411,0xD9C00EE,0x31AC7F2,0xC3981B5,0x9218229,0xD3564DC,0xA096650,0x6F7C292,0x9743616,0xBE922B1,0x12CF668,0xC81327,0x463B73A,0xE74E99B,0xAD0]
+static public let CURVE_Gy:[Chunk] = [0xAD1D465,0xF763157,0xC4FF470,0x17884C8,0xB8D215D,0xA819E66,0xF4959D0,0xE5C3245,0xB84910A,0xB8BFA40,0xBE96EEC,0x8BF9F8C,0xF277ACC,0x5F1C3F2,0x5F68C9,0xCDB14B3,0x77B]
+
+static public let CURVE_Bnx:[Chunk] = [0x0,0xFBFFFE0,0x1FFFFF,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Cof:[Chunk] = [0xAAAAAAB,0xA7FFFEA,0x1556AA,0xD55AAAB,0x554FFFF,0x1555,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Cru:[Chunk] = [0xFFFFFFE,0x40001F,0xFE00000,0xFFE7FFF,0xF0FFF6F,0x7200C47,0x7BCC604,0x15796DB,0xCF47771,0x9875433,0x613F0E8,0x5000502,0xEBFFF60,0x1FFFFF,0x0,0x0,0x0]
+static public let CURVE_Pxa:[Chunk] = [0x6D0A37C,0x5B50318,0x75DCC46,0xC2E492E,0xD6878A9,0xE01F919,0xF92F564,0x86DB74F,0x66803F0,0x46D581A,0x7ED78D,0x2F97C29,0xC270C89,0xF679453,0x6A50A9A,0x54138A0,0x10CC]
+static public let CURVE_Pxb:[Chunk] = [0x2C1C0AD,0xF85CA8C,0x25CADE9,0x6CD66C4,0xA289609,0xC612951,0xEE2401A,0x529ABEB,0xF65B17D,0xBA09D33,0xD4C5AF5,0x4D4371E,0x46A672E,0xA279D22,0xACEA37C,0x1FB4FE5,0x95C]
+static public let CURVE_Pya:[Chunk] = [0x2FB006,0xCCD0C1B,0xA12A337,0x3D194A4,0xC92C895,0x4960CFC,0x39FC68B,0x3A9B00F,0xED1BA0F,0xA7DBBC5,0xA9CDFD8,0x27CC2F7,0x4E73ED2,0x6070F4F,0xEBA7E67,0xAC848E7,0x226]
+static public let CURVE_Pyb:[Chunk] = [0xDF1457C,0xA506ADF,0x4C20A8,0xD6A31DC,0x36E3FB4,0xEA9A8F1,0x92F5668,0x3C3BE44,0x67A1297,0x74BEABA,0x56A20BE,0x4C42E38,0x45157F0,0x2AB1D00,0xBB402EA,0x101B4FA,0xE38]
+static let CURVE_W:[[Chunk]] = [[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]
+static let CURVE_SB:[[[Chunk]]] = [[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]] 
+static let CURVE_WB:[[Chunk]] = [[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]
+static let CURVE_BB:[[[Chunk]]] = [[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]]
+
+#endif
+
+#if D64
+
+// Base Bits= 60
+// bls461 Modulus
+
+static let Modulus:[Chunk] = [0xAAC0000AAAAAAAB,0x20000555554AAAA,0x6AA91557F004000,0xA8DFFA5C1CC00F2,0xACCA47B14848B42,0x935FBD6F1E32D8B,0xD5A555A55D69414,0x15555545554]
+static let R2modp:[Chunk] = [0x96D08774614DDA8,0xCD45F539225D5BD,0xD712EB760C95AB1,0xB3B687155F30B55,0xC4E62A05C3F5B81,0xBA1151676CA3CD0,0x7EDD8A958F442BE,0x12B89DD3F91]
+static let MConst:Chunk = 0xC0005FFFFFFFD
+static public let Fra:[Chunk] = [0xF7117BF9B812A3A,0xA1C6308A599C400,0x5A6510E07505BF8,0xB31ACE4858D45FA,0xFC61EBC2CB04770,0x366190D073588E2,0x69E55E24DFEFA84,0x12E40504B7F]
+static public let Frb:[Chunk] = [0xB3AE8410F298071,0x7E39D4CAFBAE6A9,0x104404777AFE407,0xF5C52C13C3EBAF8,0xB0685BEE7D443D1,0x5CFE2C9EAADA4A8,0x6BBFF7807D79990,0x27150409D5]
+
+//  bls461 Curve
+
+static let CURVE_Cof_I:Int = 0
+static let CURVE_A:Int = 0
+static let CURVE_B_I:Int = 9
+static public let CURVE_B:[Chunk] = [0x9,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Order:[Chunk] = [0x1,0x7FEFFFEFFFFC0,0xC017FFC80001100,0x7FE05FD000E801F,0xFFFF7FFFC018001,0xFF,0x0,0x0]
+static public let CURVE_Gx:[Chunk] = [0x14D026A8ADEE93D,0xF2D9C00EE74B741,0x229C3981B531AC7,0x6650D3564DC9218,0x436166F7C292A09,0x2CF668BE922B197,0x463B73A0C813271,0xAD0E74E99B]
+static public let CURVE_Gy:[Chunk] = [0xF763157AD1D465,0x5D17884C8C4FF47,0x9D0A819E66B8D21,0x910AE5C3245F495,0x96EECB8BFA40B84,0x277ACC8BF9F8CBE,0x5F68C95F1C3F2F,0x77BCDB14B3]
+
+static public let CURVE_Bnx:[Chunk] = [0xFFBFFFE00000000,0x1FFFF,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Cof:[Chunk] = [0xAA7FFFEAAAAAAAB,0xFFD55AAAB01556A,0x1555554FF,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Cru:[Chunk] = [0x40001FFFFFFFE,0x6FFFE7FFFFE0000,0x6047200C47F0FFF,0x777115796DB7BCC,0x3F0E89875433CF4,0xBFFF60500050261,0x1FFFFFE,0x0] 
+static public let CURVE_Pxa:[Chunk] = [0x65B503186D0A37C,0xA9C2E492E75DCC4,0x564E01F919D6878,0x3F086DB74FF92F,0xED78D46D581A668,0x270C892F97C2907,0x6A50A9AF679453C,0x10CC54138A0]
+static public let CURVE_Pxb:[Chunk] = [0x9F85CA8C2C1C0AD,0x96CD66C425CADE,0x1AC612951A2896,0xB17D529ABEBEE24,0xC5AF5BA09D33F65,0x6A672E4D4371ED4,0xACEA37CA279D224,0x95C1FB4FE5]
+static public let CURVE_Pya:[Chunk] = [0x7CCD0C1B02FB006,0x953D194A4A12A33,0x68B4960CFCC92C8,0xBA0F3A9B00F39FC,0xCDFD8A7DBBC5ED1,0xE73ED227CC2F7A9,0xEBA7E676070F4F4,0x226AC848E7]
+static public let CURVE_Pyb:[Chunk] = [0x8A506ADFDF1457C,0xB4D6A31DC04C20A,0x668EA9A8F136E3F,0x12973C3BE4492F5,0xA20BE74BEABA67A,0x5157F04C42E3856,0xBB402EA2AB1D004,0xE38101B4FA]
+static let CURVE_W:[[Chunk]] = [[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]
+static let CURVE_SB:[[[Chunk]]] = [[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]]
+static let CURVE_WB:[[Chunk]] = [[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]
+static let CURVE_BB:[[[Chunk]]] = [[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]]
+
+#endif
+
+    static let USE_GLV = true
+    static let USE_GS_G2 = true
+    static let USE_GS_GT = true
+    static let GT_STRONG = false
+
+}
+
diff --git a/version3/swift/rom_bls48.swift b/version3/swift/rom_bls48.swift
new file mode 100644
index 0000000..3bdaa43
--- /dev/null
+++ b/version3/swift/rom_bls48.swift
@@ -0,0 +1,120 @@
+/*
+	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.
+*/
+
+//
+//  rom.swift
+//
+final public class ROM{
+ 
+#if D32
+// Base Bits= 29
+//  bls48 Curve Modulus
+    
+static let Modulus:[Chunk] = [0x1CF6AC0B,0x17B7307F,0x19877E7B,0x12CE0134,0x14228402,0x1BD4C386,0x1DACBB04,0x40410D0,0x25A415,0x980B53E,0xDE6E250,0x15D9AAD6,0x5DA950,0x1029B7A,0x54AB351,0x14AD90CE,0x3729047,0x1FE7E2D9,0x145F610B,0x1F]
+static let R2modp:[Chunk] = [0xD59D0FA,0x12F01FD0,0xDE8FD41,0x35AAEE1,0xB937F48,0x50700E8,0x1F50EFCE,0x1019B13C,0x3470A2F,0x11094115,0xF9FB72D,0x6AD10E2,0x1CFD9F8,0x44F4785,0x2B48793,0x1148ED3,0xF609E61,0x1EE34BC7,0x1735D29E,0x0]
+static let MConst:Chunk = 0x9DA805D
+static public let Fra:[Chunk] = [0x1325BF89,0x1311E7EC,0xCD0A56F,0x1A0FD46E,0xE83BCCA,0xCA97DD0,0x18D1D297,0x5F1E137,0x7AB9F2C,0x13FC255F,0x1C9DECEB,0x9DEF4A2,0x3C0F60B,0x1D9909E4,0x1FF27FF7,0x1DBF8208,0x89BB36C,0x40044E0,0x62E01EE,0x5]
+static public let Frb:[Chunk] = [0x1325BF89,0x1311E7EC,0xCD0A56F,0x1A0FD46E,0xE83BCCA,0xCA97DD0,0x18D1D297,0x5F1E137,0x7AB9F2C,0x13FC255F,0x1C9DECEB,0x9DEF4A2,0x3C0F60B,0x1D9909E4,0x1FF27FF7,0x1DBF8208,0x89BB36C,0x40044E0,0x62E01EE,0x5]
+
+static let CURVE_Cof_I:Int = 0
+static let CURVE_A:Int = 0
+static let CURVE_B_I:Int = 17
+static public let CURVE_B:[Chunk] = [0x11,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Order:[Chunk] = [0x1,0x17FFF800,0xA769C21,0x8AA813C,0x2029C21,0xA68F58B,0xB6307F4,0x1184DA51,0x6DFED78,0x1A3C85E9,0x571037B,0x1637F1F9,0x1C465FB0,0x98354B9,0x118DF17A,0x1422355D,0x43BF73E,0x6,0x0,0x0]
+static public let CURVE_Gx:[Chunk] = [0x5D71D33,0x1943697B,0x18CB783F,0x1B00AA9F,0x1711EE0B,0x7F80B23,0x129FD8CC,0x1345E03F,0x9A80F66,0x7038173,0xC056511,0x142801F5,0x42B2C3A,0x1AF09869,0x7924166,0x8381264,0x957EDD7,0xBACAEDC,0xA27A4A1,0x13]
+static public let CURVE_Gy:[Chunk] = [0xA6ED83A,0x14D2D9FF,0xA29C33D,0x1B8972A9,0x6958677,0x19C8F547,0x1DED7E3E,0x14F9E3DC,0x18FB7229,0x27171C0,0x1551E32D,0xE6184CC,0x6260E3C,0x733D204,0x579C437,0x1534665C,0x2B3349D,0x3162FD7,0xB634253,0x1]
+
+static public let CURVE_Bnx:[Chunk] = [0x1DE40020,0x3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Cof:[Chunk] = [0x1F12ABEB,0x516887B,0x5,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Cru:[Chunk] = [0xCBBA429,0x1B273F3,0xD3DD160,0x19C61452,0x308093A,0x146E1E34,0xAE0E768,0x1185948,0x1B73BC2D,0x93D855C,0x1B1A639C,0x118C919B,0xFF04AE3,0xF1CCD77,0x91318E5,0x10644780,0x3A79F7,0x1BE77919,0x145F60F3,0x1F]
+static public let CURVE_Pxaaa:[Chunk] = [0x923CE4A,0x14697474,0xAE04F4A,0x17AE205A,0x1313A20C,0x10B2EC50,0x18DF074F,0x15FE3FE8,0x7C90B98,0x959BF85,0xE57BD37,0x14376C96,0xBF57375,0xE20B625,0x12EE2172,0x1CBBCE85,0x1A5D9487,0xD0E024B,0x195E3602,0x1C]
+static public let CURVE_Pxaab:[Chunk] = [0xC0A1BE1,0x138E6E2D,0x1DF5FDC,0x151FC760,0x33972C5,0x56AA3C2,0x2491D8C,0x115B9FD7,0x140A11FA,0x1873AE35,0x1F259C26,0x74B0647,0x12D18B04,0x4672431,0x1C27F419,0x1CAA4D35,0x18DB48B6,0x13A54BDA,0x5080497,0x5]
+static public let CURVE_Pxaba:[Chunk] = [0x170C5DC4,0x11D39263,0x16B3BCB6,0x152C95BB,0x19BEC736,0x8849A12,0x49AB2A8,0xC7162D3,0xC58CD55,0x15C2659,0x11EE8B90,0xB40CAFC,0xE233167,0x7BEC8BE,0x129335BD,0x151C7DBB,0x78B689B,0x1B6B8EED,0x14BFBE3D,0x16]
+static public let CURVE_Pxabb:[Chunk] = [0x1A64B740,0x6B14B34,0x12481578,0x23FA931,0x323ADD1,0x206B82A,0xD789E1B,0x1FCFA666,0x1F4EEA7,0xF1E39E2,0x1968610,0xAF3EBD3,0x590D3B,0xDA0C35A,0x17306AAF,0xCF9DD2B,0x3F63B1A,0x96FF2F9,0xE102A76,0x12] 
+static public let CURVE_Pxbaa:[Chunk] = [0x12F1E01F,0xDD8630B,0x12C29802,0x186239A6,0x19218788,0x4C87D1,0x16AE2501,0x775C076,0x870C80B,0x1A394429,0x1637D478,0x4A420E8,0x1C3AD4D4,0x10E5E713,0x111E6AD5,0x514FCF0,0x7CC49D3,0xC678A2,0x1787BDFD,0x1B]
+static public let CURVE_Pxbab:[Chunk] = [0x637383D,0x1851C11C,0x661F866,0x14404A7F,0x15D3D212,0x9AE28F6,0x8051F25,0x1E1CE2BF,0x137D882F,0xB231CEB,0xA8DB8FC,0x18957645,0x5E54DA8,0x1FF41C44,0x1A297414,0x17E1CBC5,0x1014F91F,0x4282AB7,0xB6CE9E3,0x10]
+static public let CURVE_Pxbba:[Chunk] = [0x1711939C,0xB41ED9E,0x69066BA,0x137CA3AD,0xCF2F6C0,0x5E6DAB9,0x2CE1323,0x946E448,0xF353D1C,0x14D9919F,0x46B7046,0x1A12015,0x3D6070,0x18C3E8D2,0x1F23BA45,0x1F1A337C,0x435A9CC,0x6CA1DF1,0x8A9CE1,0x15]
+static public let CURVE_Pxbbb:[Chunk] = [0x56F4899,0x196A0854,0xA959750,0x38A3D72,0x190BC9BC,0x145752BC,0x1E9E26DA,0x1403F88,0x71895E3,0x14162F5D,0x19FEC5FF,0x14190B16,0x7597C,0x19A3CF18,0x26A4B00,0x113D1BB6,0x7857A32,0xE0B78AB,0x1DD51E0F,0x1B]
+static public let CURVE_Pyaaa:[Chunk] = [0x14137844,0x1704BE7D,0x1FD3CCDD,0x189D8C93,0x1C768851,0xF5C37D5,0xE29C659,0x20AB1C1,0xF8896E0,0x1E08663E,0x1D1D539C,0x117E1C47,0x156CDD39,0x161F1017,0x143E8C72,0x174B22FD,0x18706190,0x49AA47E,0x19BB42E1,0xE]
+static public let CURVE_Pyaab:[Chunk] = [0xDC83190,0x12F19247,0x1AA26424,0x15D55E88,0xC418D32,0xB0E91DD,0x47CBFF7,0x2D992C1,0xDE03C1F,0x7694AE5,0x5C741A2,0x1D423AC6,0x5E02B9E,0x1E903F10,0x4EA6513,0x433A1F1,0x8EFA1C4,0xED54713,0x1E72CE4F,0x4]
+static public let CURVE_Pyaba:[Chunk] = [0x1985C0D,0xEE2FE82,0x64770FA,0x11A809B4,0x1483ACE9,0x18BCD2FA,0x171F32C,0x1612D58D,0x1E658341,0x1CBE2201,0x186E971,0x73F0E1,0xB0A5F40,0xAC90FB0,0x1635E008,0x237498B,0x1F3140D6,0xBF789A9,0x1166F259,0x1A]
+static public let CURVE_Pyabb:[Chunk] = [0x159D42F8,0x1B7F0540,0x45895D7,0x14875FA2,0x1E9E7F2B,0x10139D87,0x10F3FD7D,0x11D3717F,0x69E5006,0xF9BB3C4,0x13C9ED8D,0x16516DA,0x102F51DE,0x2725FEC,0x1F125B66,0xFFC324,0x1ED80731,0x1C16C4D,0x383AAA8,0x14]
+static public let CURVE_Pybaa:[Chunk] = [0x1F38039F,0x6A8959C,0x13C68984,0x11DD12AF,0x58093CF,0x1C8550A0,0xFFA1622,0xFF85979,0x1F2ABB75,0x18862E62,0x1EB6A2C9,0x1EC80B64,0x8EC2F18,0xE7BF713,0xC36B65A,0x19C5DD89,0x18A1D1AB,0xF772C8D,0xC11927C,0x5]
+static public let CURVE_Pybab:[Chunk] = [0x95F7865,0x134F0379,0x1CE9A0E,0x17E0EADD,0x1DACADD7,0x1B18F9F8,0x181D3943,0x186679A,0x2505BB0,0x1FDF1DC8,0x11B36A49,0x11E254E9,0xA438576,0x102B09AE,0x139984F4,0x15BC0233,0x1B6F180E,0x960562B,0x48CA65B,0x6]
+static public let CURVE_Pybba:[Chunk] = [0x7CC1979,0xEC1D4FB,0x1D89E6F0,0x955F38E,0x1635FDA9,0x123D8E10,0x10076209,0x494404A,0xD733D7,0x17678BCF,0x153841F9,0x10696FFD,0x5BC9FE8,0x1A20D8B2,0xE22EC9D,0x18449116,0x108C86C5,0x1B4CD720,0x34967,0x19]
+static public let CURVE_Pybbb:[Chunk] = [0xFC9F25B,0x7E44AB1,0xE9AB5D3,0x589F00D,0x1C9D264F,0xC7478B4,0x16B24A13,0x1D2C146B,0xEF84D9A,0xF47ECDE,0x1BFEE16A,0x1B69071E,0x11AB4C1C,0xBE9D9EF,0x390F005,0x78C8288,0x1B9BF549,0x9320730,0x3D84D97,0x14]
+static let CURVE_W:[[Chunk]] = [[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]
+static let CURVE_SB:[[[Chunk]]] = [[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]]
+static let CURVE_WB:[[Chunk]] = [[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]
+static let CURVE_BB:[[[Chunk]]] = [[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]]
+
+
+
+#endif
+
+#if D64
+// Base Bits= 58
+
+static let Modulus:[Chunk] = [0x2F6E60FFCF6AC0B,0x259C02699877E7B,0x37A9870D4228402,0x80821A1DACBB04,0x13016A7C025A415,0x2BB355ACDE6E250,0x20536F405DA950,0x295B219C54AB351,0x3FCFC5B23729047,0x3F45F610B]
+static let R2modp:[Chunk] = [0x25E03FA0D59D0FA,0x6B55DC2DE8FD41,0xA0E01D0B937F48,0x20336279F50EFCE,0x2212822A3470A2F,0xD5A21C4F9FB72D,0x89E8F0A1CFD9F8,0x2291DA62B48793,0x3DC6978EF609E61,0x1735D29E]
+static let MConst:Chunk = 0x21BFCBCA9DA805D
+static public let Fra:[Chunk] = [0x2623CFD9325BF89,0x341FA8DCCD0A56F,0x1952FBA0E83BCCA,0xBE3C26F8D1D297,0x27F84ABE7AB9F2C,0x13BDE945C9DECEB,0x3B3213C83C0F60B,0x3B7F0411FF27FF7,0x80089C089BB36C,0xA62E01EE]
+static public let Frb:[Chunk] = [0x2623CFD9325BF89,0x341FA8DCCD0A56F,0x1952FBA0E83BCCA,0xBE3C26F8D1D297,0x27F84ABE7AB9F2C,0x13BDE945C9DECEB,0x3B3213C83C0F60B,0x3B7F0411FF27FF7,0x80089C089BB36C,0xA62E01EE]
+
+static let CURVE_Cof_I:Int = 0
+static let CURVE_A:Int = 0
+static let CURVE_B_I:Int = 17
+static public let CURVE_B:[Chunk] = [0x11,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Order:[Chunk] = [0x2FFFF0000000001,0x11550278A769C21,0x14D1EB162029C21,0x2309B4A2B6307F4,0x34790BD26DFED78,0x2C6FE3F2571037B,0x1306A973C465FB0,0x28446ABB18DF17A,0xC43BF73E,0x0]
+static public let CURVE_Gx:[Chunk] = [0x3286D2F65D71D33,0x3601553F8CB783F,0xFF01647711EE0B,0x268BC07F29FD8CC,0xE0702E69A80F66,0x285003EAC056511,0x35E130D242B2C3A,0x107024C87924166,0x17595DB8957EDD7,0x26A27A4A1]
+static public let CURVE_Gy:[Chunk] = [0x29A5B3FEA6ED83A,0x3712E552A29C33D,0x3391EA8E6958677,0x29F3C7B9DED7E3E,0x4E2E3818FB7229,0x1CC30999551E32D,0xE67A4086260E3C,0x2A68CCB8579C437,0x62C5FAE2B3349D,0x2B634253]
+
+static public let CURVE_Bnx:[Chunk] = [0x7DE40020,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Cof:[Chunk] = [0xA2D10F7F12ABEB,0x5,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Cru:[Chunk] = [0x364E7E6CBBA429,0x338C28A4D3DD160,0x28DC3C68308093A,0x230B290AE0E768,0x127B0AB9B73BC2D,0x23192337B1A639C,0x1E399AEEFF04AE3,0x20C88F0091318E5,0x37CEF23203A79F7,0x3F45F60F3]
+static public let CURVE_Pxaaa:[Chunk] = [0x28D2E8E8923CE4A,0x2F5C40B4AE04F4A,0x2165D8A1313A20C,0x2BFC7FD18DF074F,0x12B37F0A7C90B98,0x286ED92CE57BD37,0x1C416C4ABF57375,0x39779D0B2EE2172,0x1A1C0497A5D9487,0x3995E3602]
+static public let CURVE_Pxaab:[Chunk] = [0x271CDC5AC0A1BE1,0x2A3F8EC01DF5FDC,0xAD5478433972C5,0x22B73FAE2491D8C,0x30E75C6B40A11FA,0xE960C8FF259C26,0x8CE48632D18B04,0x39549A6BC27F419,0x274A97B58DB48B6,0xA5080497]
+static public let CURVE_Pxaba:[Chunk] = [0x23A724C770C5DC4,0x2A592B776B3BCB6,0x110934259BEC736,0x18E2C5A649AB2A8,0x2B84CB2C58CD55,0x168195F91EE8B90,0xF7D917CE233167,0x2A38FB7729335BD,0x36D71DDA78B689B,0x2D4BFBE3D]
+static public let CURVE_Pxabb:[Chunk] = [0xD629669A64B740,0x47F52632481578,0x40D7054323ADD1,0x3F9F4CCCD789E1B,0x1E3C73C41F4EEA7,0x15E7D7A61968610,0x1B4186B40590D3B,0x19F3BA577306AAF,0x12DFE5F23F63B1A,0x24E102A76]
+static public let CURVE_Pxbaa:[Chunk] = [0x1BB0C6172F1E01F,0x30C4734D2C29802,0x990FA39218788,0xEEB80ED6AE2501,0x34728852870C80B,0x94841D1637D478,0x21CBCE27C3AD4D4,0xA29F9E111E6AD5,0x18CF1447CC49D3,0x37787BDFD]
+static public let CURVE_Pxbab:[Chunk] = [0x30A38238637383D,0x288094FE661F866,0x135C51ED5D3D212,0x3C39C57E8051F25,0x164639D737D882F,0x312AEC8AA8DB8FC,0x3FE838885E54DA8,0x2FC3978BA297414,0x850556F014F91F,0x20B6CE9E3]
+static public let CURVE_Pxbba:[Chunk] = [0x1683DB3D711939C,0x26F9475A69066BA,0xBCDB572CF2F6C0,0x128DC8902CE1323,0x29B3233EF353D1C,0x342402A46B7046,0x3187D1A403D6070,0x3E3466F9F23BA45,0xD943BE2435A9CC,0x2A08A9CE1]
+static public let CURVE_Pxbbb:[Chunk] = [0x32D410A856F4899,0x7147AE4A959750,0x28AEA57990BC9BC,0x2807F11E9E26DA,0x282C5EBA71895E3,0x2832162D9FEC5FF,0x33479E30007597C,0x227A376C26A4B00,0x1C16F1567857A32,0x37DD51E0F]
+static public let CURVE_Pyaaa:[Chunk] = [0x2E097CFB4137844,0x313B1927FD3CCDD,0x1EB86FABC768851,0x4156382E29C659,0x3C10CC7CF8896E0,0x22FC388FD1D539C,0x2C3E202F56CDD39,0x2E9645FB43E8C72,0x93548FD8706190,0x1D9BB42E1]
+static public let CURVE_Pyaab:[Chunk] = [0x25E3248EDC83190,0x2BAABD11AA26424,0x161D23BAC418D32,0x5B3258247CBFF7,0xED295CADE03C1F,0x3A84758C5C741A2,0x3D207E205E02B9E,0x86743E24EA6513,0x1DAA8E268EFA1C4,0x9E72CE4F]
+static public let CURVE_Pyaba:[Chunk] = [0x1DC5FD041985C0D,0x2350136864770FA,0x3179A5F5483ACE9,0x2C25AB1A171F32C,0x397C4403E658341,0xE7E1C2186E971,0x15921F60B0A5F40,0x46E9317635E008,0x17EF1353F3140D6,0x35166F259]
+static public let CURVE_Pyabb:[Chunk] = [0x36FE0A8159D42F8,0x290EBF4445895D7,0x20273B0FE9E7F2B,0x23A6E2FF0F3FD7D,0x1F37678869E5006,0x2CA2DB53C9ED8D,0x4E4BFD902F51DE,0x1FF8649F125B66,0x382D89BED80731,0x28383AAA8]
+static public let CURVE_Pybaa:[Chunk] = [0xD512B39F38039F,0x23BA255F3C68984,0x390AA14058093CF,0x1FF0B2F2FFA1622,0x310C5CC5F2ABB75,0x3D9016C9EB6A2C9,0x1CF7EE268EC2F18,0x338BBB12C36B65A,0x1EEE591B8A1D1AB,0xAC11927C]
+static public let CURVE_Pybab:[Chunk] = [0x269E06F295F7865,0x2FC1D5BA1CE9A0E,0x3631F3F1DACADD7,0x30CCF3581D3943,0x3FBE3B902505BB0,0x23C4A9D31B36A49,0x2056135CA438576,0x2B78046739984F4,0x12C0AC57B6F180E,0xC48CA65B]
+static public let CURVE_Pybba:[Chunk] = [0x1D83A9F67CC1979,0x12ABE71DD89E6F0,0x247B1C21635FDA9,0x92880950076209,0x2ECF179E0D733D7,0x20D2DFFB53841F9,0x3441B1645BC9FE8,0x3089222CE22EC9D,0x3699AE4108C86C5,0x320034967]
+static public let CURVE_Pybbb:[Chunk] = [0xFC89562FC9F25B,0xB13E01AE9AB5D3,0x18E8F169C9D264F,0x3A5828D76B24A13,0x1E8FD9BCEF84D9A,0x36D20E3DBFEE16A,0x17D3B3DF1AB4C1C,0xF190510390F005,0x12640E61B9BF549,0x283D84D97]
+static let CURVE_W:[[Chunk]] = [[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]
+static let CURVE_SB:[[[Chunk]]] = [[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]]
+static let CURVE_WB:[[Chunk]] = [[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]
+static let CURVE_BB:[[[Chunk]]] = [[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]]
+
+#endif
+
+    static let USE_GLV = true
+    static let USE_GS_G2 = true
+    static let USE_GS_GT = true
+    static let GT_STRONG = true
+
+}
+
diff --git a/version3/swift/rom_bn254.swift b/version3/swift/rom_bn254.swift
new file mode 100644
index 0000000..9214533
--- /dev/null
+++ b/version3/swift/rom_bn254.swift
@@ -0,0 +1,104 @@
+/*
+	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.
+*/
+
+//
+//  rom.swift
+//
+//  Created by Michael Scott on 12/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+import amcl
+
+final public class ROM{
+ 
+#if D32
+
+// Base Bits= 28
+// BN254 Curve Modulus
+static let Modulus:[Chunk] = [0x13,0x0,0x13A7,0x0,0x86121,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2]
+static let R2modp:[Chunk] = [0xF5E7E39,0x2F2A96F,0xB96F13C,0x64E8642,0xC7146,0x9926F7B,0x4DACD24,0x8321E7B,0xD127A2E,0x1]
+static let MConst:Chunk = 0x79435E5
+static let Fra:[Chunk] = [0xF2A6DE9,0x7DE6C06,0xF77C2E1,0x74924D3,0x53F8509,0x50A8469,0xCB6499B,0x212E7C8,0xB377619,0x1]
+static let Frb:[Chunk] = [0xD5922A,0x82193F9,0x8850C5,0x8B6DB2C,0xAC8DC17,0x2F57B96,0x503EAB2,0x1ED1837,0x9EBEE69,0x0]
+
+// BN254 Curve
+
+static let CURVE_Cof_I:Int = 1
+static let CURVE_A:Int = 0
+static let CURVE_B_I:Int = 2
+static let CURVE_B:[Chunk] = [0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Order:[Chunk] = [0xD,0x0,0x10A1,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2]
+static public let CURVE_Gx:[Chunk] = [0x12,0x0,0x13A7,0x0,0x86121,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2]
+static public let CURVE_Gy:[Chunk] = [0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static let CURVE_Bnx:[Chunk] = [0x1,0x8000000,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static let CURVE_Cof:[Chunk] = [0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static let CURVE_Cru:[Chunk] = [0x7,0x8000000,0x6CD,0x0,0x24909,0x4000000,0x49B362,0x0,0x0,0x0]
+static public let CURVE_Pxa:[Chunk] = [0x803FB2B,0xEE4224C,0x8BF0D91,0x8BBB489,0xDB6A464,0x7E8C61E,0xFEB8D8C,0x519EB62,0x61A10BB,0x0]
+static public let CURVE_Pxb:[Chunk] = [0x7D54CF3,0x8C34C1E,0x784B70D,0x746BAE3,0xA5B1F4D,0x8C5982A,0x3310AA7,0xBA73783,0x516AAF9,0x0]
+static public let CURVE_Pya:[Chunk] = [0x1CD2B9A,0xF0E0789,0xE09BD19,0xAE6BDB,0x22329BD,0x96698C8,0x39A90E0,0x6BAF934,0x21897A0,0x0]
+static public let CURVE_Pyb:[Chunk] = [0xB3ACE9B,0x2D1AEC6,0x9C9578A,0x6FFD73,0xD37B090,0x56F5F38,0x68F6D44,0x7C8B152,0xEBB2B0E,0x0]
+static let CURVE_W:[[Chunk]] = [[0x3,0x0,0x204,0x8000000,0x6181,0x0,0x0,0x0,0x0,0x0],[0x1,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]
+static let CURVE_SB:[[[Chunk]]] = [[[0x4,0x0,0x285,0x8000000,0x6181,0x0,0x0,0x0,0x0,0x0],[0x1,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x1,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0xA,0x0,0xE9D,0x0,0x79E1E,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2]]]
+static let CURVE_WB:[[Chunk]] = [[0x0,0x8000000,0x40,0x8000000,0x2080,0x0,0x0,0x0,0x0,0x0],[0x5,0x8000000,0x54A,0x0,0x1C707,0x8000000,0x312241,0x0,0x0,0x0],[0x3,0x8000000,0x2C5,0x8000000,0xE383,0xC000000,0x189120,0x0,0x0,0x0],[0x1,0x8000000,0xC1,0x8000000,0x2080,0x0,0x0,0x0,0x0,0x0]]
+static let CURVE_BB:[[[Chunk]]] = [[[0xD,0x8000000,0x1060,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2],[0xC,0x8000000,0x1060,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2],[0xC,0x8000000,0x1060,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2],[0x2,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x1,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0xC,0x8000000,0x1060,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2],[0xD,0x8000000,0x1060,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2],[0xC,0x8000000,0x1060,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2]],[[0x2,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1,0x0,0x81,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x2,0x8000000,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x2,0x0,0x102,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0xA,0x0,0x1020,0x8000000,0x7FF9F,0x8000000,0x1BA344D,0x4000000,0x5236482,0x2],[0x2,0x8000000,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]]
+
+
+#endif
+
+#if D64
+
+// Base Bits= 56
+// BN254 Curve Modulus
+static let Modulus:[Chunk] = [0x13,0x13A7,0x80000000086121,0x40000001BA344D,0x25236482]
+static let R2modp:[Chunk] = [0x2F2A96FF5E7E39,0x64E8642B96F13C,0x9926F7B00C7146,0x8321E7B4DACD24,0x1D127A2E]
+static let MConst:Chunk = 0x435E50D79435E5
+static public let Fra:[Chunk] = [0x7DE6C06F2A6DE9,0x74924D3F77C2E1,0x50A846953F8509,0x212E7C8CB6499B,0x1B377619]
+static public let Frb:[Chunk] = [0x82193F90D5922A,0x8B6DB2C08850C5,0x2F57B96AC8DC17,0x1ED1837503EAB2,0x9EBEE69]
+
+// BN254 Curve
+
+static let CURVE_Cof_I:Int = 1
+static let CURVE_A:Int = 0
+static let CURVE_B_I:Int = 2
+static let CURVE_B:[Chunk] = [0x2,0x0,0x0,0x0,0x0]
+static public let CURVE_Order:[Chunk] = [0xD,0x800000000010A1,0x8000000007FF9F,0x40000001BA344D,0x25236482]
+static public let CURVE_Gx:[Chunk] = [0x12,0x13A7,0x80000000086121,0x40000001BA344D,0x25236482]
+static public let CURVE_Gy:[Chunk] = [0x1,0x0,0x0,0x0,0x0]
+static let CURVE_Bnx:[Chunk] = [0x80000000000001,0x40,0x0,0x0,0x0]
+static let CURVE_Cof:[Chunk] = [0x1,0x0,0x0,0x0,0x0]
+static let CURVE_Cru:[Chunk] = [0x80000000000007,0x6CD,0x40000000024909,0x49B362,0x0]
+static public let CURVE_Pxa:[Chunk] = [0xEE4224C803FB2B,0x8BBB4898BF0D91,0x7E8C61EDB6A464,0x519EB62FEB8D8C,0x61A10BB]
+static public let CURVE_Pxb:[Chunk] = [0x8C34C1E7D54CF3,0x746BAE3784B70D,0x8C5982AA5B1F4D,0xBA737833310AA7,0x516AAF9]
+static public let CURVE_Pya:[Chunk] = [0xF0E07891CD2B9A,0xAE6BDBE09BD19,0x96698C822329BD,0x6BAF93439A90E0,0x21897A0]
+static public let CURVE_Pyb:[Chunk] = [0x2D1AEC6B3ACE9B,0x6FFD739C9578A,0x56F5F38D37B090,0x7C8B15268F6D44,0xEBB2B0E]
+static let CURVE_W:[[Chunk]] = [[0x3,0x80000000000204,0x6181,0x0,0x0],[0x1,0x81,0x0,0x0,0x0]]
+static let CURVE_SB:[[[Chunk]]] = [[[0x4,0x80000000000285,0x6181,0x0,0x0],[0x1,0x81,0x0,0x0,0x0]],[[0x1,0x81,0x0,0x0,0x0],[0xA,0xE9D,0x80000000079E1E,0x40000001BA344D,0x25236482]]]
+static let CURVE_WB:[[Chunk]] = [[0x80000000000000,0x80000000000040,0x2080,0x0,0x0],[0x80000000000005,0x54A,0x8000000001C707,0x312241,0x0],[0x80000000000003,0x800000000002C5,0xC000000000E383,0x189120,0x0],[0x80000000000001,0x800000000000C1,0x2080,0x0,0x0]]
+static let CURVE_BB:[[[Chunk]]] = [[[0x8000000000000D,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482],[0x8000000000000C,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482],[0x8000000000000C,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482],[0x2,0x81,0x0,0x0,0x0]],[[0x1,0x81,0x0,0x0,0x0],[0x8000000000000C,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482],[0x8000000000000D,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482],[0x8000000000000C,0x80000000001060,0x8000000007FF9F,0x40000001BA344D,0x25236482]],[[0x2,0x81,0x0,0x0,0x0],[0x1,0x81,0x0,0x0,0x0],[0x1,0x81,0x0,0x0,0x0],[0x1,0x81,0x0,0x0,0x0]],[[0x80000000000002,0x40,0x0,0x0,0x0],[0x2,0x102,0x0,0x0,0x0],[0xA,0x80000000001020,0x8000000007FF9F,0x40000001BA344D,0x25236482],[0x80000000000002,0x40,0x0,0x0,0x0]]]
+
+#endif
+
+static let USE_GLV = true
+static let USE_GS_G2 = true
+static let USE_GS_GT = true
+static let GT_STRONG = false
+
+}
+
diff --git a/version3/swift/rom_bn254CX.swift b/version3/swift/rom_bn254CX.swift
new file mode 100644
index 0000000..62e467f
--- /dev/null
+++ b/version3/swift/rom_bn254CX.swift
@@ -0,0 +1,106 @@
+/*
+	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.
+*/
+
+//
+//  rom.swift
+//
+//  Created by Michael Scott on 12/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+final public class ROM{
+ 
+#if D32
+
+// Base Bits= 28
+//  bn254CX Curve Modulus
+static let Modulus:[Chunk] = [0xC1B55B3,0x6623EF5,0x93EE1BE,0xD6EE180,0x6D3243F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2]
+static let R2modp:[Chunk] = [0x8A0800A,0x466A061,0x43056A3,0x2B3A225,0x9C6600,0x148515B,0x6BDF50,0xEC9EA56,0xC992E66,0x1]
+static let MConst:Chunk = 0x9789E85
+static let Fra:[Chunk] = [0x5C80EA3,0xD908335,0x3F8215B,0x7326F17,0x8986867,0x8AACA71,0x4AFE18B,0xA63A016,0x359082F,0x1]
+static let Frb:[Chunk] = [0x6534710,0x8D1BBC0,0x546C062,0x63C7269,0xE3ABBD8,0xD9CDBC4,0x900DC53,0x623628A,0xA6F7D0,0x1]
+
+//  bn254CX Curve
+
+static let CURVE_Cof_I:Int = 1
+static let CURVE_A:Int = 0
+static let CURVE_B_I:Int = 2
+static let CURVE_B:[Chunk] = [0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Order:[Chunk] = [0x6EB1F6D,0x11C0A63,0x906CEBE,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2]
+static public let CURVE_Gx:[Chunk] = [0xC1B55B2,0x6623EF5,0x93EE1BE,0xD6EE180,0x6D3243F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2]
+static public let CURVE_Gy:[Chunk] = [0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static let CURVE_Bnx:[Chunk] = [0x3C012B1,0x0,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static let CURVE_Cof:[Chunk] = [0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0] 
+static let CURVE_Cru:[Chunk] = [0x4235C97,0xE093179,0xF875631,0xDF6471E,0xF1440BD,0xCA83,0x480000,0x0,0x0,0x0]
+
+static public let CURVE_Pxa:[Chunk] = [0x4D2EC74,0x851CEEE,0xE2726C0,0x85BFA03,0xBBB907C,0xF5C34,0x6358B25,0x7053B25,0x9682D2C,0x1]
+static public let CURVE_Pxb:[Chunk] = [0xE29CFE1,0xA58E8B2,0x9C30F47,0x97B0C20,0x743F81B,0x37A8E99,0xAA011C9,0x3E19F64,0x466B9EC,0x1]
+static public let CURVE_Pya:[Chunk] = [0xF0BE09F,0xFBFCEBC,0xEC1B30C,0xB33D847,0x2096361,0x157DAEE,0xDD81E22,0x72332B8,0xA79EDD9,0x0]
+static public let CURVE_Pyb:[Chunk] = [0x898EE9D,0x904B228,0x2EDEBED,0x4EA569D,0x461C286,0x512D8D3,0x35C6E4,0xECC4C09,0x6160C39,0x0]
+
+static let CURVE_W:[[Chunk]] = [[0x62FEB83,0x5463491,0x381200,0xB4,0x6000,0x0,0x0,0x0,0x0,0x0],[0x7802561,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]
+static let CURVE_SB:[[[Chunk]]] = [[[0xDB010E4,0x5463491,0x381280,0xB4,0x6000,0x0,0x0,0x0,0x0,0x0],[0x7802561,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x7802561,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0xBB33EA,0xBD5D5D2,0x8CEBCBD,0xD6EE018,0x6D2643F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2]]]
+static let CURVE_WB:[[Chunk]] = [[0x67A84B0,0x1C21185,0x12B040,0x3C,0x2000,0x0,0x0,0x0,0x0,0x0],[0xE220475,0xCDF995B,0xA7F9A36,0x94EDA8C,0xA0DC07E,0x8702,0x300000,0x0,0x0,0x0],[0xF10B93,0x66FCCAE,0x53FCD3B,0x4A76D46,0x506E03F,0x4381,0x180000,0x0,0x0,0x0],[0xDFAAA11,0x1C21185,0x12B0C0,0x3C,0x2000,0x0,0x0,0x0,0x0,0x0]]
+static let CURVE_BB:[[[Chunk]]] = [[[0x32B0CBD,0x11C0A63,0x906CE7E,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2],[0x32B0CBC,0x11C0A63,0x906CE7E,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2],[0x32B0CBC,0x11C0A63,0x906CE7E,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2],[0x7802562,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x7802561,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x32B0CBC,0x11C0A63,0x906CE7E,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2],[0x32B0CBD,0x11C0A63,0x906CE7E,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2],[0x32B0CBC,0x11C0A63,0x906CE7E,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2]],[[0x7802562,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x7802561,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x7802561,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x7802561,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x3C012B2,0x0,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0xF004AC2,0x0,0x100,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0xF6AFA0A,0x11C0A62,0x906CE3E,0xD6EE0CC,0x6D2C43F,0x647A636,0xDB0BDDF,0x8702A0,0x4000000,0x2],[0x3C012B2,0x0,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]]
+
+    
+#endif
+
+#if D64
+
+// Base Bits= 56
+//  bn254CX Curve Modulus
+static let Modulus:[Chunk] = [0x6623EF5C1B55B3,0xD6EE18093EE1BE,0x647A6366D3243F,0x8702A0DB0BDDF,0x24000000]
+static let R2modp:[Chunk] = [0x466A0618A0800A,0x2B3A22543056A3,0x148515B09C6600,0xEC9EA5606BDF50,0x1C992E66]
+static let MConst:Chunk = 0x4E205BF9789E85
+static let Fra:[Chunk] = [0xD9083355C80EA3,0x7326F173F8215B,0x8AACA718986867,0xA63A0164AFE18B,0x1359082F]
+static let Frb:[Chunk] = [0x8D1BBC06534710,0x63C7269546C062,0xD9CDBC4E3ABBD8,0x623628A900DC53,0x10A6F7D0]
+
+//  bn254CX Curve
+
+static let CURVE_Cof_I:Int = 1
+static let CURVE_A:Int = 0
+static let CURVE_B_I:Int = 2
+static let CURVE_B:[Chunk] = [0x2,0x0,0x0,0x0,0x0]
+static public let CURVE_Order:[Chunk] = [0x11C0A636EB1F6D,0xD6EE0CC906CEBE,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000]
+static public let CURVE_Gx:[Chunk] = [0x6623EF5C1B55B2,0xD6EE18093EE1BE,0x647A6366D3243F,0x8702A0DB0BDDF,0x24000000]
+static public let CURVE_Gy:[Chunk] = [0x1,0x0,0x0,0x0,0x0]
+static let CURVE_Bnx:[Chunk] = [0x3C012B1,0x40,0x0,0x0,0x0]
+static let CURVE_Cof:[Chunk] = [0x1,0x0,0x0,0x0,0x0]
+static let CURVE_Cru:[Chunk] = [0xE0931794235C97,0xDF6471EF875631,0xCA83F1440BD,0x480000,0x0]
+
+static public let CURVE_Pxa:[Chunk] = [0x851CEEE4D2EC74,0x85BFA03E2726C0,0xF5C34BBB907C,0x7053B256358B25,0x19682D2C]
+static public let CURVE_Pxb:[Chunk] = [0xA58E8B2E29CFE1,0x97B0C209C30F47,0x37A8E99743F81B,0x3E19F64AA011C9,0x1466B9EC]
+static public let CURVE_Pya:[Chunk] = [0xFBFCEBCF0BE09F,0xB33D847EC1B30C,0x157DAEE2096361,0x72332B8DD81E22,0xA79EDD9]
+static public let CURVE_Pyb:[Chunk] = [0x904B228898EE9D,0x4EA569D2EDEBED,0x512D8D3461C286,0xECC4C09035C6E4,0x6160C39]
+
+static let CURVE_W:[[Chunk]] = [[0x546349162FEB83,0xB40381200,0x6000,0x0,0x0],[0x7802561,0x80,0x0,0x0,0x0]]
+static let CURVE_SB:[[[Chunk]]] = [[[0x5463491DB010E4,0xB40381280,0x6000,0x0,0x0],[0x7802561,0x80,0x0,0x0,0x0]],[[0x7802561,0x80,0x0,0x0,0x0],[0xBD5D5D20BB33EA,0xD6EE0188CEBCBD,0x647A6366D2643F,0x8702A0DB0BDDF,0x24000000]]]
+static let CURVE_WB:[[Chunk]] = [[0x1C2118567A84B0,0x3C012B040,0x2000,0x0,0x0],[0xCDF995BE220475,0x94EDA8CA7F9A36,0x8702A0DC07E,0x300000,0x0],[0x66FCCAE0F10B93,0x4A76D4653FCD3B,0x4381506E03F,0x180000,0x0],[0x1C21185DFAAA11,0x3C012B0C0,0x2000,0x0,0x0]]
+static let CURVE_BB:[[[Chunk]]] = [[[0x11C0A6332B0CBD,0xD6EE0CC906CE7E,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000],[0x11C0A6332B0CBC,0xD6EE0CC906CE7E,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000],[0x11C0A6332B0CBC,0xD6EE0CC906CE7E,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000],[0x7802562,0x80,0x0,0x0,0x0]],[[0x7802561,0x80,0x0,0x0,0x0],[0x11C0A6332B0CBC,0xD6EE0CC906CE7E,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000],[0x11C0A6332B0CBD,0xD6EE0CC906CE7E,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000],[0x11C0A6332B0CBC,0xD6EE0CC906CE7E,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000]],[[0x7802562,0x80,0x0,0x0,0x0],[0x7802561,0x80,0x0,0x0,0x0],[0x7802561,0x80,0x0,0x0,0x0],[0x7802561,0x80,0x0,0x0,0x0]],[[0x3C012B2,0x40,0x0,0x0,0x0],[0xF004AC2,0x100,0x0,0x0,0x0],[0x11C0A62F6AFA0A,0xD6EE0CC906CE3E,0x647A6366D2C43F,0x8702A0DB0BDDF,0x24000000],[0x3C012B2,0x40,0x0,0x0,0x0]]]
+
+
+#endif
+
+    static let USE_GLV = true
+    static let USE_GS_G2 = true
+    static let USE_GS_GT = true
+    static let GT_STRONG = true
+}
+
diff --git a/version3/swift/rom_brainpool.swift b/version3/swift/rom_brainpool.swift
new file mode 100644
index 0000000..6bca8b3
--- /dev/null
+++ b/version3/swift/rom_brainpool.swift
@@ -0,0 +1,74 @@
+/*
+	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.
+*/
+
+//
+//  rom.swift
+//
+//  Created by Michael Scott on 12/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+// Note that the original curve has been transformed to an isomorphic curve with A=-3 
+
+
+final public class ROM{
+ 
+#if D32
+
+// Base Bits= 28
+//  Brainpool Modulus
+static let Modulus:[Chunk] = [0xF6E5377,0x13481D1,0x6202820,0xF623D52,0xD726E3B,0x909D838,0xC3E660A,0xA1EEA9B,0x9FB57DB,0xA]
+static let R2modp:[Chunk] = [0xB9A3787,0x9E04F49,0x8F3CF49,0x2931721,0xF1DBC89,0x54E8C3C,0xF7559CA,0xBB411A3,0x773E15F,0x9]
+static let MConst:Chunk = 0xEFD89B9
+
+//  Brainpool Curve
+static let CURVE_Cof_I:Int=1
+static let CURVE_Cof:[Chunk] = [0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static let CURVE_A:Int = -3
+static let CURVE_B_I:Int = 0
+static let CURVE_B:[Chunk] = [0xEE92B04,0xE58101F,0xF49256A,0xEBC4AF2,0x6B7BF93,0x733D0B7,0x4FE66A7,0x30D84EA,0x62C61C4,0x6]
+static public let CURVE_Order:[Chunk] = [0x74856A7,0x1E0E829,0x1A6F790,0x7AA3B56,0xD718C39,0x909D838,0xC3E660A,0xA1EEA9B,0x9FB57DB,0xA]
+static public let CURVE_Gx:[Chunk] = [0xE1305F4,0xA191562,0xFBC2B79,0x42C47AA,0x149AFA1,0xB23A656,0x7732213,0xC1CFE7B,0x3E8EB3C,0xA]
+static public let CURVE_Gy:[Chunk] = [0xB25C9BE,0xABE8F35,0x27001D,0xB6DE39D,0x17E69BC,0xE146444,0xD7F7B22,0x3439C56,0xD996C82,0x2]
+
+#endif
+
+#if D64
+
+// Base Bits= 56
+//  Brainpool  Modulus
+static let Modulus:[Chunk] = [0x13481D1F6E5377,0xF623D526202820,0x909D838D726E3B,0xA1EEA9BC3E660A,0xA9FB57DB]
+static let R2modp:[Chunk] = [0x9E04F49B9A3787,0x29317218F3CF49,0x54E8C3CF1DBC89,0xBB411A3F7559CA,0x9773E15F]
+static let MConst:Chunk = 0xA75590CEFD89B9
+
+//  Brainpool Curve
+static let CURVE_Cof_I:Int=1
+static let CURVE_Cof:[Chunk] = [0x1,0x0,0x0,0x0,0x0]
+static let CURVE_A:Int = -3
+static let CURVE_B_I:Int = 0
+static let CURVE_B:[Chunk] = [0xE58101FEE92B04,0xEBC4AF2F49256A,0x733D0B76B7BF93,0x30D84EA4FE66A7,0x662C61C4]
+static public let CURVE_Order:[Chunk] = [0x1E0E82974856A7,0x7AA3B561A6F790,0x909D838D718C39,0xA1EEA9BC3E660A,0xA9FB57DB]
+static public let CURVE_Gx:[Chunk] = [0xA191562E1305F4,0x42C47AAFBC2B79,0xB23A656149AFA1,0xC1CFE7B7732213,0xA3E8EB3C]
+static public let CURVE_Gy:[Chunk] = [0xABE8F35B25C9BE,0xB6DE39D027001D,0xE14644417E69BC,0x3439C56D7F7B22,0x2D996C82]
+
+
+#endif
+
+}
+
diff --git a/version3/swift/rom_c25519.swift b/version3/swift/rom_c25519.swift
new file mode 100644
index 0000000..10c8fb6
--- /dev/null
+++ b/version3/swift/rom_c25519.swift
@@ -0,0 +1,72 @@
+/*
+	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.
+*/
+
+//
+//  rom.swift
+//
+//  Created by Michael Scott on 12/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+final public class ROM{
+ 
+#if D32
+
+// Base Bits= 29
+//  Curve 25519 Modulus
+static let Modulus:[Chunk] = [0x1FFFFFED,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFFF]
+static let R2modp:[Chunk] = [0x169000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static let MConst:Chunk = 0x13
+
+//  Curve 25519
+static let CURVE_Cof_I:Int = 8
+static let CURVE_Cof:[Chunk] = [0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static let CURVE_A:Int = 486662
+static let CURVE_B_I:Int = 0
+static let CURVE_B:[Chunk] = [0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Order:[Chunk] = [0x1CF5D3ED,0x9318D2,0x1DE73596,0x1DF3BD45,0x14D,0x0,0x0,0x0,0x100000]
+static public let CURVE_Gx:[Chunk] = [0x9,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Gy:[Chunk] = [0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+
+
+#endif
+
+#if D64
+
+
+// Base Bits= 56
+// Curve 25519 Modulus
+static let Modulus:[Chunk] = [0xFFFFFFFFFFFFED,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0x7FFFFFFF]
+static let R2modp:[Chunk] = [0xA4000000000000,0x5,0x0,0x0,0x0]
+static let MConst:Chunk = 0x13
+
+//  Curve 25519
+static let CURVE_Cof_I:Int = 8
+static let CURVE_Cof:[Chunk] = [0x8,0x0,0x0,0x0,0x0]
+static let CURVE_A:Int = 486662
+static let CURVE_B_I:Int = 0
+static let CURVE_B:[Chunk] = [0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Order:[Chunk] = [0x12631A5CF5D3ED,0xF9DEA2F79CD658,0x14DE,0x0,0x10000000]
+static public let CURVE_Gx:[Chunk] = [0x9,0x0,0x0,0x0,0x0]
+static public let CURVE_Gy:[Chunk] = [0x0,0x0,0x0,0x0,0x0]
+
+#endif
+
+}
+
diff --git a/version3/swift/rom_c41417.swift b/version3/swift/rom_c41417.swift
new file mode 100644
index 0000000..b9009a0
--- /dev/null
+++ b/version3/swift/rom_c41417.swift
@@ -0,0 +1,71 @@
+/*
+	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.
+*/
+
+//
+//  rom.swift
+//
+//  Created by Michael Scott on 12/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+final public class ROM{
+ 
+#if D32
+
+// Base Bits= 29
+//  c41417 Curve Modulus
+static let Modulus:[Chunk] = [0x1FFFFFEF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFF]
+static let R2modp:[Chunk] = [0x0,0x242000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static let MConst:Chunk = 0x11
+
+//  c41417 Curve
+static let CURVE_Cof_I:Int = 8
+static let CURVE_Cof:[Chunk] = [0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static let CURVE_A:Int = 1
+static let CURVE_B_I:Int = 3617
+static let CURVE_B:[Chunk] = [0xE21,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Order:[Chunk] = [0x106AF79,0x18738D2F,0x18F3C606,0x1806715A,0x22B36F1,0xA67B830,0xCF32490,0x1FFFFFFD,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1F]
+static public let CURVE_Gx:[Chunk] = [0x13CBC595,0x7E9C097,0x14DF1931,0x14E7F550,0x1A111301,0x15A6B6B5,0xD526292,0x18FEAFFE,0x1F44C03E,0x1E6A31B4,0x70C9B97,0x43180C6,0x1443300,0x19A4828A,0x68]
+static public let CURVE_Gy:[Chunk] = [0x22,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+
+
+#endif
+
+#if D64
+
+// Base Bits= 60
+//  c41417 Curve Modulus
+static let Modulus:[Chunk] = [0xFFFFFFFFFFFFFEF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0x3FFFFFFFFFFFFF]
+static let R2modp:[Chunk] = [0x121000,0x0,0x0,0x0,0x0,0x0,0x0]
+static let MConst:Chunk = 0x11
+
+//  c41417 Curve
+static let CURVE_Cof_I:Int = 8
+static let CURVE_B:[Chunk] = [0x8,0x0,0x0,0x0,0x0,0x0,0x0]
+static let CURVE_A:Int = 1
+static let CURVE_B_I:Int = 3617
+static let CURVE_B:[Chunk] = [0xE21,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Order:[Chunk] = [0xB0E71A5E106AF79,0x1C0338AD63CF181,0x414CF706022B36F,0xFFFFFFFFEB3CC92,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0x7FFFFFFFFFFFF]
+static public let CURVE_Gx:[Chunk] = [0x4FD3812F3CBC595,0x1A73FAA8537C64C,0x4AB4D6D6BA11130,0x3EC7F57FF35498A,0xE5FCD46369F44C0,0x300218C0631C326,0x1A334905141443]
+static public let CURVE_Gy:[Chunk] = [0x22,0x0,0x0,0x0,0x0,0x0,0x0]
+
+#endif
+
+}
+
diff --git a/version3/swift/rom_ed25519.swift b/version3/swift/rom_ed25519.swift
new file mode 100644
index 0000000..0511c13
--- /dev/null
+++ b/version3/swift/rom_ed25519.swift
@@ -0,0 +1,72 @@
+/*
+	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.
+*/
+
+//
+//  rom.swift
+//
+//  Created by Michael Scott on 12/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+final public class ROM{
+ 
+#if D32
+
+
+// Base Bits= 29
+// C25519 Curve Modulus
+	static let Modulus:[Chunk] = [0x1FFFFFED,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFFF]
+	static let R2modp:[Chunk] = [0x169000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+	static let MConst:Chunk = 0x13;
+
+// ED25519 Curve
+	static let CURVE_Cof_I:Int = 8
+	static let CURVE_Cof:[Chunk] = [0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+	static let CURVE_A:Int = -1
+	static let CURVE_B_I:Int = 0
+	static let CURVE_B:[Chunk] = [0x135978A3,0xF5A6E50,0x10762ADD,0x149A82,0x1E898007,0x3CBBBC,0x19CE331D,0x1DC56DFF,0x52036C]
+	static public let CURVE_Order:[Chunk] = [0x1CF5D3ED,0x9318D2,0x1DE73596,0x1DF3BD45,0x14D,0x0,0x0,0x0,0x100000]
+	static public let CURVE_Gx:[Chunk] = [0xF25D51A,0xAB16B04,0x969ECB2,0x198EC12A,0xDC5C692,0x1118FEEB,0xFFB0293,0x1A79ADCA,0x216936]
+	static public let CURVE_Gy:[Chunk] = [0x6666658,0x13333333,0x19999999,0xCCCCCCC,0x6666666,0x13333333,0x19999999,0xCCCCCCC,0x666666]
+
+ 
+#endif
+
+#if D64
+
+// Base Bits= 56
+// C25519 Curve Modulus
+	static let Modulus:[Chunk] = [0xFFFFFFFFFFFFED,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0x7FFFFFFF]
+	static let R2modp:[Chunk] = [0xA4000000000000,0x5,0x0,0x0,0x0]
+	static let MConst:Chunk = 0x13
+
+// ED25519 Curve
+	static let CURVE_Cof_I:Int = 8
+	static let CURVE_Cof:[Chunk] = [0x8,0x0,0x0,0x0,0x0]
+	static let CURVE_A:Int = -1
+	static let CURVE_B_I:Int = 0
+	static let CURVE_B:[Chunk] = [0xEB4DCA135978A3,0xA4D4141D8AB75,0x797779E8980070,0x2B6FFE738CC740,0x52036CEE]
+	static public let CURVE_Order:[Chunk] = [0x12631A5CF5D3ED,0xF9DEA2F79CD658,0x14DE,0x0,0x10000000]
+	static public let CURVE_Gx:[Chunk] = [0x562D608F25D51A,0xC7609525A7B2C9,0x31FDD6DC5C692C,0xCD6E53FEC0A4E2,0x216936D3]
+	static public let CURVE_Gy:[Chunk] = [0x66666666666658,0x66666666666666,0x66666666666666,0x66666666666666,0x66666666]
+
+#endif
+
+}
+
diff --git a/version3/swift/rom_fp256bn.swift b/version3/swift/rom_fp256bn.swift
new file mode 100644
index 0000000..a4afa08
--- /dev/null
+++ b/version3/swift/rom_fp256bn.swift
@@ -0,0 +1,102 @@
+/*
+	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.
+*/
+
+//
+//  rom.swift
+//
+//  Created by Michael Scott on 12/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+import amcl
+
+final public class ROM{
+ 
+#if D32
+
+// Base Bits= 28
+// fp256bn Curve Modulus
+static let Modulus:[Chunk] = [0xED33013,0x292DDBA,0x80A82D3,0x65FB129,0x49F0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF]
+static let R2modp:[Chunk] = [0x3B9F8B,0xEDE3363,0xFEC54E8,0x92FFEE9,0x3C55F79,0x13C1C06,0xC0123FA,0xA12F2EA,0xE559B2A,0x8]
+static let MConst:Chunk = 0x537E5E5
+
+static let CURVE_Cof_I:Int = 1
+static let CURVE_A:Int = 0
+static let CURVE_B_I:Int = 3
+static public let CURVE_B:[Chunk] = [0x3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Order:[Chunk] = [0x10B500D,0x2D536CD,0x9921AF6,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF]
+static public let CURVE_Gx:[Chunk] = [0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Gy:[Chunk] = [0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+
+static public let Fra:[Chunk] = [0xF943106,0x760328A,0xAB28F74,0x71511E3,0x7CF39A1,0x8DDB086,0x52D1A6E,0xCA786F3,0xD617662,0x3]
+static public let Frb:[Chunk] = [0xF3EFF0D,0xB32AB2F,0xD57F35E,0xF4A9F45,0xCCFD33A,0xD113693,0x819CB83,0x3584819,0x29E899D,0xC]
+static public let CURVE_Bnx:[Chunk] = [0xB0A801,0x82F5C03,0x68,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Cof:[Chunk] = [0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0] 
+static public let CURVE_Cru:[Chunk] = [0x3A1B807,0x1C0A24A,0x32D1EDB,0xD79DF19,0x8659BCD,0x4092101,0x13988E1,0x0,0x0,0x0]
+static public let CURVE_Pxa:[Chunk] = [0x9C09EFB,0x2616B68,0xF843CD2,0x539A12B,0x13ACE1C,0x577C289,0x28560F,0xB4C96C2,0xE0C3350,0xF]
+static public let CURVE_Pxb:[Chunk] = [0x37E6A2B,0x69ED34A,0x3589D2,0x78E287D,0x3B924DD,0xC637D81,0x4DB5AE1,0x738AC05,0xEA66057,0x4]
+static public let CURVE_Pya:[Chunk] = [0xEDC27FF,0x9B481B,0x15848E9,0x24758D6,0xE51EFCB,0x75124E3,0x376770D,0xC542A3B,0x2046E7,0x7]
+static public let CURVE_Pyb:[Chunk] = [0xAAD049B,0x1281114,0xA98B3E0,0xBE80821,0x29F8B4C,0x49297EB,0x42EEA6,0xD388C29,0x554E3BC,0x0]
+static let CURVE_W:[[Chunk]] = [[0xB054003,0xF0036E1,0xE78663A,0xFFFFFFF,0xFFFF,0x0,0x0,0x0,0x0,0x0],[0x1615001,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]
+static let CURVE_SB:[[[Chunk]]] = [[[0xC669004,0xF5EEEE7,0xE78670B,0xFFFFFFF,0xFFFF,0x0,0x0,0x0,0x0,0x0],[0x1615001,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x1615001,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x606100A,0x3D4FFEB,0xB19B4BB,0x65FB129,0x49D0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF]]]
+static let CURVE_WB:[[Chunk]] = [[0xD30A800,0x20678F0,0x4D2CC10,0x5555555,0x5555,0x0,0x0,0x0,0x0,0x0],[0xD7DC805,0xD6764C0,0xBC3AD1A,0x8FBEA10,0x4467DE,0x8061601,0xD105EB,0x0,0x0,0x0],[0xF173803,0xACB6061,0x5E1D6C1,0x47DF508,0x82233EF,0xC030B00,0x6882F5,0x0,0x0,0x0],[0xE91F801,0x26530F6,0x4D2CCE1,0x5555555,0x5555,0x0,0x0,0x0,0x0,0x0]]
+static let CURVE_BB:[[[Chunk]]] = [[[0x5AA80D,0xAA5DACA,0x9921A8D,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF],[0x5AA80C,0xAA5DACA,0x9921A8D,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF],[0x5AA80C,0xAA5DACA,0x9921A8D,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF],[0x1615002,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x1615001,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x5AA80C,0xAA5DACA,0x9921A8D,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF],[0x5AA80D,0xAA5DACA,0x9921A8D,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF],[0x5AA80C,0xAA5DACA,0x9921A8D,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF]],[[0x1615002,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1615001,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1615001,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1615001,0x5EB806,0xD1,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0xB0A802,0x82F5C03,0x68,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x2C2A002,0xBD700C,0x1A2,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0xFAA000A,0x2767EC6,0x9921A25,0x65FB129,0x49E0CDC,0x5EEE71A,0xD46E5F2,0xFFFCF0C,0xFFFFFFF,0xF],[0xB0A802,0x82F5C03,0x68,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]]
+
+
+
+#endif
+
+#if D64
+
+// Base Bits= 56
+static let Modulus:[Chunk] = [0x292DDBAED33013,0x65FB12980A82D3,0x5EEE71A49F0CDC,0xFFFCF0CD46E5F2,0xFFFFFFFF]
+static let R2modp:[Chunk] = [0xEDE336303B9F8B,0x92FFEE9FEC54E8,0x13C1C063C55F79,0xA12F2EAC0123FA,0x8E559B2A]
+static let MConst:Chunk = 0x6C964E0537E5E5
+
+static let CURVE_Cof_I:Int = 1
+static let CURVE_A:Int = 0
+static let CURVE_B_I:Int = 3
+static public let CURVE_B:[Chunk] = [0x3,0x0,0x0,0x0,0x0]
+static public let CURVE_Order:[Chunk] = [0x2D536CD10B500D,0x65FB1299921AF6,0x5EEE71A49E0CDC,0xFFFCF0CD46E5F2,0xFFFFFFFF]
+static public let CURVE_Gx:[Chunk] = [0x1,0x0,0x0,0x0,0x0]
+static public let CURVE_Gy:[Chunk] = [0x2,0x0,0x0,0x0,0x0]
+
+static public let Fra:[Chunk] = [0x760328AF943106,0x71511E3AB28F74,0x8DDB0867CF39A1,0xCA786F352D1A6E,0x3D617662]
+static public let Frb:[Chunk] = [0xB32AB2FF3EFF0D,0xF4A9F45D57F35E,0xD113693CCFD33A,0x3584819819CB83,0xC29E899D]
+static public let CURVE_Bnx:[Chunk] = [0x82F5C030B0A801,0x68,0x0,0x0,0x0]
+static public let CURVE_Cof:[Chunk] = [0x1,0x0,0x0,0x0,0x0]
+static public let CURVE_Cru:[Chunk] = [0x1C0A24A3A1B807,0xD79DF1932D1EDB,0x40921018659BCD,0x13988E1,0x0]
+static public let CURVE_Pxa:[Chunk] = [0x2616B689C09EFB,0x539A12BF843CD2,0x577C28913ACE1C,0xB4C96C2028560F,0xFE0C3350]
+static public let CURVE_Pxb:[Chunk] = [0x69ED34A37E6A2B,0x78E287D03589D2,0xC637D813B924DD,0x738AC054DB5AE1,0x4EA66057]
+static public let CURVE_Pya:[Chunk] = [0x9B481BEDC27FF,0x24758D615848E9,0x75124E3E51EFCB,0xC542A3B376770D,0x702046E7]
+static public let CURVE_Pyb:[Chunk] = [0x1281114AAD049B,0xBE80821A98B3E0,0x49297EB29F8B4C,0xD388C29042EEA6,0x554E3BC]
+static let CURVE_W:[[Chunk]] = [[0xF0036E1B054003,0xFFFFFFFE78663A,0xFFFF,0x0,0x0],[0x5EB8061615001,0xD1,0x0,0x0,0x0]]
+static let CURVE_SB:[[[Chunk]]] = [[[0xF5EEEE7C669004,0xFFFFFFFE78670B,0xFFFF,0x0,0x0],[0x5EB8061615001,0xD1,0x0,0x0,0x0]],[[0x5EB8061615001,0xD1,0x0,0x0,0x0],[0x3D4FFEB606100A,0x65FB129B19B4BB,0x5EEE71A49D0CDC,0xFFFCF0CD46E5F2,0xFFFFFFFF]]]
+static let CURVE_WB:[[Chunk]] = [[0x20678F0D30A800,0x55555554D2CC10,0x5555,0x0,0x0],[0xD6764C0D7DC805,0x8FBEA10BC3AD1A,0x806160104467DE,0xD105EB,0x0],[0xACB6061F173803,0x47DF5085E1D6C1,0xC030B0082233EF,0x6882F5,0x0],[0x26530F6E91F801,0x55555554D2CCE1,0x5555,0x0,0x0]]
+static let CURVE_BB:[[[Chunk]]] = [[[0xAA5DACA05AA80D,0x65FB1299921A8D,0x5EEE71A49E0CDC,0xFFFCF0CD46E5F2,0xFFFFFFFF],[0xAA5DACA05AA80C,0x65FB1299921A8D,0x5EEE71A49E0CDC,0xFFFCF0CD46E5F2,0xFFFFFFFF],[0xAA5DACA05AA80C,0x65FB1299921A8D,0x5EEE71A49E0CDC,0xFFFCF0CD46E5F2,0xFFFFFFFF],[0x5EB8061615002,0xD1,0x0,0x0,0x0]],[[0x5EB8061615001,0xD1,0x0,0x0,0x0],[0xAA5DACA05AA80C,0x65FB1299921A8D,0x5EEE71A49E0CDC,0xFFFCF0CD46E5F2,0xFFFFFFFF],[0xAA5DACA05AA80D,0x65FB1299921A8D,0x5EEE71A49E0CDC,0xFFFCF0CD46E5F2,0xFFFFFFFF],[0xAA5DACA05AA80C,0x65FB1299921A8D,0x5EEE71A49E0CDC,0xFFFCF0CD46E5F2,0xFFFFFFFF]],[[0x5EB8061615002,0xD1,0x0,0x0,0x0],[0x5EB8061615001,0xD1,0x0,0x0,0x0],[0x5EB8061615001,0xD1,0x0,0x0,0x0],[0x5EB8061615001,0xD1,0x0,0x0,0x0]],[[0x82F5C030B0A802,0x68,0x0,0x0,0x0],[0xBD700C2C2A002,0x1A2,0x0,0x0,0x0],[0x2767EC6FAA000A,0x65FB1299921A25,0x5EEE71A49E0CDC,0xFFFCF0CD46E5F2,0xFFFFFFFF],[0x82F5C030B0A802,0x68,0x0,0x0,0x0]]]
+
+#endif
+
+static let USE_GLV = true
+static let USE_GS_G2 = true
+static let USE_GS_GT = true
+static let GT_STRONG = false
+
+}
+
diff --git a/version3/swift/rom_fp512bn.swift b/version3/swift/rom_fp512bn.swift
new file mode 100644
index 0000000..597dbd8
--- /dev/null
+++ b/version3/swift/rom_fp512bn.swift
@@ -0,0 +1,105 @@
+/*
+	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.
+*/
+
+//
+//  rom.swift
+//
+//  Created by Michael Scott on 12/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+import amcl
+
+final public class ROM{
+ 
+#if D32
+
+// Base Bits= 29
+// fp512bn Curve Modulus
+
+static let Modulus:[Chunk] = [0x2ADEF33,0x7594049,0x131919ED,0x14AB9CBE,0x16FE1916,0x12EF5591,0x2E39231,0x3D597D3,0x55146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF]
+static let R2modp:[Chunk] = [0xFD68B47,0xFCF5D2C,0x437675A,0x1BBC3FBF,0x1411E413,0x13453559,0x10B5639,0x1C34CE79,0x6D476BF,0xFD05F2B,0x15D17C28,0x6C9F76E,0x1C2375B3,0x78CCE9B,0x15F0AB33,0x1960F32E,0x1A8D44E,0x57A38]
+static let MConst:Chunk = 0x1CCC5C05
+
+static let CURVE_Cof_I:Int = 1
+static let CURVE_A:Int = 0
+static let CURVE_B_I:Int = 3
+static public let CURVE_B:[Chunk] = [0x3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Order:[Chunk] = [0x119A09ED,0x153252FA,0x1E68AD01,0x627C09,0x79A34A1,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF]
+static public let CURVE_Gx:[Chunk] = [0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Gy:[Chunk] = [0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+
+static public let Fra:[Chunk] = [0x14B73AB2,0x4B0BD8F,0xABB47D,0x2A29EC4,0x18681E17,0x104069DE,0x12EED67D,0x1553D0A5,0x398E9F8,0x7971034,0xAC9AF23,0x52DEF23,0x14EA18A5,0x1463E345,0x6DE465A,0x17F212B4,0x1AA9CF5B,0xF7B8]
+static public let Frb:[Chunk] = [0xDF6B481,0x2A882B9,0x126D6570,0x1208FDFA,0x1E95FAFF,0x2AEEBB2,0xFF4BBB4,0xE81C72D,0x1B85CD6,0xF67746,0x56549CD,0xC68B6EC,0x776A178,0x8925C3B,0x1921B9A5,0x80DED4B,0x55630A4,0x70847]
+static public let CURVE_Bnx:[Chunk] = [0x1E1BD80F,0x59835DA,0xC3DFC04,0x5EB8061,0x688,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Cof:[Chunk] = [0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Cru:[Chunk] = [0x1C79298A,0x1838B104,0x2C5F052,0x1DCCF337,0x6092AEC,0x4B35F29,0x1EB361E,0x11384EA,0x3074B20,0x17BB08FD,0x3A8B3E3,0xD70D66F,0x3D2A614,0x1CF63EE4,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF]
+static public let CURVE_Pxa:[Chunk] = [0xDB646B5,0x183D4B70,0x1CBFFA3,0x11F0E632,0x1C78F221,0x1F10DE5D,0x171B715E,0xF0C6A29,0x10B02453,0xBE63C66,0xE6D5F69,0x166B1E1B,0x4BBBD29,0x179E750F,0x6E9D04,0xC912B10,0x1339E138,0x1D8B2]
+static public let CURVE_Pxb:[Chunk] = [0x1A8AE0E9,0xDAE5F7E,0x22446CF,0x1948239B,0x15ADCE40,0xB709C1E,0x18357943,0xE50AA4D,0x19781E22,0x12B35CA6,0x11DAA2C0,0x18D8DDE4,0x5EA656D,0x15F45A41,0xD311A02,0xCFCD913,0x13CBF850,0x240E0]
+static public let CURVE_Pya:[Chunk] = [0xDDE67A1,0x12401895,0x17BEE178,0x142F5AC2,0xB7BC5CD,0x92A1404,0x1A3B748C,0x17BD82A7,0x14B6CD18,0xAC34CE,0x1740FB97,0x1ECC15F9,0x17085B1D,0x1D1BA793,0x1BD6AC32,0x18F70525,0xC84C827,0x3780F]
+static public let CURVE_Pyb:[Chunk] = [0x84F8E8B,0xC5B8C36,0xFDD85A1,0xB84449,0x19C08DFF,0x56BF713,0x1C5290C4,0x187C5CA0,0x1DA2897F,0x24B0CA0,0x326D8F4,0x2310CF6,0x1021438C,0xFBAEC8F,0xD9030C5,0x1CF06358,0x1CEC8B04,0x28D1D]
+static let CURVE_W:[[Chunk]] = [[0x9834583,0x887C4BA,0x5A85CFC,0xBF7223A,0xF63FE96,0x1FFFFFFE,0x1FFFFFFF,0x1FFFFFFF,0xFFFFFF,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1C37B01F,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]
+static let CURVE_SB:[[[Chunk]]] = [[[0xD4B9564,0x1D575904,0xD2C64F3,0x202177,0xF63F186,0x1FFFFFFE,0x1FFFFFFF,0x1FFFFFFF,0xFFFFFF,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x156259CE,0xA01E744,0x5ECB4F9,0x148B7B47,0x79A2790,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF]],[[0x1C37B01F,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x9834583,0x887C4BA,0x5A85CFC,0xBF7223A,0xF63FE96,0x1FFFFFFE,0x1FFFFFFF,0x1FFFFFFF,0xFFFFFF,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]]
+static let CURVE_WB:[[Chunk]] = [[0x155A29F0,0x16D59B55,0xF4C305,0x18858C0B,0x5215FBF,0xAAAAAAA,0x15555555,0xAAAAAAA,0x555555,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x2355D4B,0x1758095D,0x1FE13C5F,0x41F83FA,0xBB5E5CF,0x97D4EF1,0xB503D62,0x172C0C9B,0x16315274,0x15E1A9A8,0x859835D,0x2C3DFC0,0x105EB806,0x68,0x0,0x0,0x0,0x0],[0x289AAD,0x1E781F9C,0x60F9C31,0x1505822E,0x15DAF62B,0x4BEA778,0x15A81EB1,0xB96064D,0xB18A93A,0x1AF0D4D4,0x42CC1AE,0x161EFE0,0x82F5C03,0x34,0x0,0x0,0x0,0x0],[0x192279D1,0xBA52F9F,0x878CAFD,0xCAE8B48,0x52152AF,0xAAAAAAA,0x15555555,0xAAAAAAA,0x555555,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]
+static let CURVE_BB:[[[Chunk]]] = [[[0x1E1BD810,0x59835DA,0xC3DFC04,0x5EB8061,0x688,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1E1BD80F,0x59835DA,0xC3DFC04,0x5EB8061,0x688,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1E1BD80F,0x59835DA,0xC3DFC04,0x5EB8061,0x688,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x156259CF,0xA01E744,0x5ECB4F9,0x148B7B47,0x79A2790,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF]],[[0x1C37B01F,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x137E31DE,0xF9A1D1F,0x122AB0FD,0x1A76FBA8,0x79A2E18,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF],[0x137E31DD,0xF9A1D1F,0x122AB0FD,0x1A76FBA8,0x79A2E18,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF],[0x137E31DE,0xF9A1D1F,0x122AB0FD,0x1A76FBA8,0x79A2E18,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF]],[[0x1C37B01E,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1C37B01F,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1C37B01F,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x1C37B01F,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x137E31DF,0xF9A1D1F,0x122AB0FD,0x1A76FBA8,0x79A2E18,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF],[0x192AA9AF,0x1ED17B8E,0xD70BCF0,0x8B47A84,0x79A1A80,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF],[0x1C37B01D,0xB306BB5,0x187BF808,0xBD700C2,0xD10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x137E31DF,0xF9A1D1F,0x122AB0FD,0x1A76FBA8,0x79A2E18,0x12EF5593,0x2E39231,0x3D597D3,0x45146CF,0x88D877A,0x102EF8F0,0x1196A60F,0x1C60BA1D,0x1CF63F80,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF]]]
+
+
+
+#endif
+
+#if D64
+
+
+// Base Bits= 60
+static let Modulus:[Chunk] = [0x4EB280922ADEF33,0x6A55CE5F4C6467B,0xC65DEAB236FE191,0xCF1EACBE98B8E48,0x3C111B0EF455146,0xA1D8CB5307C0BBE,0xFFFF9EC7F01C60B,0xFFFFFFFFFFFFFFF,0xFFFFFFFF]
+static let R2modp:[Chunk] = [0x1FA6DCEF99812E9,0xAB3452895A0B74E,0xC53EA988C079E1E,0x1E90E033BA630B9,0xF1EA41C0714D8B0,0xE72785387509E28,0xD86794F834DAB00,0x9757C2ACCD342A1,0x44ECB079]
+static let MConst:Chunk = 0x692A189FCCC5C05
+
+static let CURVE_Cof_I:Int = 1
+static let CURVE_A:Int = 0
+static let CURVE_B_I:Int = 3
+static public let CURVE_B:[Chunk] = [0x3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Order:[Chunk] = [0x6A64A5F519A09ED,0x10313E04F9A2B40,0xC65DEAB2679A34A,0xCF1EACBE98B8E48,0x3C111B0EF445146,0xA1D8CB5307C0BBE,0xFFFF9EC7F01C60B,0xFFFFFFFFFFFFFFF,0xFFFFFFFF]
+static public let CURVE_Gx:[Chunk] = [0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Gy:[Chunk] = [0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+
+static public let Fra:[Chunk] = [0x49617B1F4B73AB2,0x71514F6202AED1F,0xF6080D3BD8681E1,0xF8AA9E852CBBB59,0xC8CF2E2068398E9,0x8A5296F791AB26B,0x196A8C7C68B4EA1,0xCF5BBF9095A1B79,0x1EF71AA9]
+static public let Frb:[Chunk] = [0x5510572DF6B481,0xF9047EFD49B595C,0xD055DD765E95FAF,0xD6740E396BFD2EE,0x7341ECEE8C1B85C,0x1786345B7615952,0xE695124B876776A,0x30A4406F6A5E486,0xE108E556]
+static public let CURVE_Bnx:[Chunk] = [0xB306BB5E1BD80F,0x82F5C030B0F7F01,0x68,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Cof:[Chunk] = [0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Cru:[Chunk] = [0xB0716209C79298A,0xCEE6799B8B17C14,0x78966BE526092AE,0x20089C27507ACD8,0xF8EF7611FA3074B,0x6146B86B378EA2C,0xFFFF9EC7DC83D2A,0xFFFFFFFFFFFFFFF,0xFFFFFFFF]
+static public let CURVE_Pxa:[Chunk] = [0xF07A96E0DB646B5,0x18F87319072FFE8,0x7BE21BCBBC78F22,0x537863514DC6DC5,0xDA57CC78CD0B024,0xD29B358F0DB9B57,0x7412F3CEA1E4BBB,0xE138648958801BA,0x3B165339]
+static public let CURVE_Pxb:[Chunk] = [0xDB5CBEFDA8AE0E9,0xCA411CD88911B3,0xD6E1383D5ADCE4,0x227285526E0D5E5,0xB02566B94D9781E,0x56DC6C6EF2476A8,0x680ABE8B4825EA6,0xF85067E6C89B4C4,0x481C13CB]
+static public let CURVE_Pya:[Chunk] = [0x2480312ADDE67A1,0xDA17AD615EFB85E,0x312542808B7BC5C,0x18BDEC153E8EDD2,0xE5C158699D4B6CD,0xB1DF660AFCDD03E,0xB0CBA374F277085,0xC827C7B8292EF5A,0x6F01EC84]
+static public let CURVE_Pyb:[Chunk] = [0x58B7186C84F8E8B,0xF05C2224BF76168,0x10AD7EE279C08DF,0x7FC3E2E50714A43,0x3D04961941DA289,0x38C118867B0C9B6,0xC315F75D91F0214,0x8B04E7831AC3640,0x51A3BCEC]
+static let CURVE_W:[[Chunk]] = [[0x110F89749834583,0x65FB911D16A173F,0xFFFFFFFFCF63FE9,0xFFFFFFFFFFFFFFF,0xFFFF,0x0,0x0,0x0,0x0],[0x1660D76BC37B01F,0x5EB806161EFE02,0xD1,0x0,0x0,0x0,0x0,0x0,0x0]]
+static let CURVE_SB:[[[Chunk]]] = [[[0xFAAEB208D4B9564,0x601010BBB4B193C,0xFFFFFFFFCF63F18,0xFFFFFFFFFFFFFFF,0xFFFF,0x0,0x0,0x0,0x0],[0x5403CE8956259CE,0xA45BDA397B2D3E,0xC65DEAB2679A279,0xCF1EACBE98B8E48,0x3C111B0EF445146,0xA1D8CB5307C0BBE,0xFFFF9EC7F01C60B,0xFFFFFFFFFFFFFFF,0xFFFFFFFF]],[[0x1660D76BC37B01F,0x5EB806161EFE02,0xD1,0x0,0x0,0x0,0x0,0x0,0x0],[0x110F89749834583,0x65FB911D16A173F,0xFFFFFFFFCF63FE9,0xFFFFFFFFFFFFFFF,0xFFFF,0x0,0x0,0x0,0x0]]]
+static let CURVE_WB:[[Chunk]] = [[0x6DAB36AB55A29F0,0xFC42C60583D30C1,0x5555555545215FB,0x555555555555555,0x5555,0x0,0x0,0x0,0x0],[0xEEB012BA2355D4B,0xF20FC1FD7F84F17,0x892FA9DE2BB5E5C,0x74B96064DAD40F5,0xD76BC3535163152,0x806161EFE021660,0xD105EB,0x0,0x0],[0x7CF03F380289AAD,0xBA82C117183E70C,0xC497D4EF15DAF62,0x3A5CB0326D6A07A,0x6BB5E1A9A8B18A9,0xC030B0F7F010B30,0x6882F5,0x0,0x0],[0x574A5F3F92279D1,0xF65745A421E32BF,0x55555555452152A,0x555555555555555,0x5555,0x0,0x0,0x0,0x0]]
+static let CURVE_BB:[[[Chunk]]] = [[[0xB306BB5E1BD810,0x82F5C030B0F7F01,0x68,0x0,0x0,0x0,0x0,0x0,0x0],[0xB306BB5E1BD80F,0x82F5C030B0F7F01,0x68,0x0,0x0,0x0,0x0,0x0,0x0],[0xB306BB5E1BD80F,0x82F5C030B0F7F01,0x68,0x0,0x0,0x0,0x0,0x0,0x0],[0x5403CE8956259CF,0xA45BDA397B2D3E,0xC65DEAB2679A279,0xCF1EACBE98B8E48,0x3C111B0EF445146,0xA1D8CB5307C0BBE,0xFFFF9EC7F01C60B,0xFFFFFFFFFFFFFFF,0xFFFFFFFF]],[[0x1660D76BC37B01F,0x5EB806161EFE02,0xD1,0x0,0x0,0x0,0x0,0x0,0x0],[0x5F343A3F37E31DE,0x8D3B7DD448AAC3F,0xC65DEAB2679A2E1,0xCF1EACBE98B8E48,0x3C111B0EF445146,0xA1D8CB5307C0BBE,0xFFFF9EC7F01C60B,0xFFFFFFFFFFFFFFF,0xFFFFFFFF],[0x5F343A3F37E31DD,0x8D3B7DD448AAC3F,0xC65DEAB2679A2E1,0xCF1EACBE98B8E48,0x3C111B0EF445146,0xA1D8CB5307C0BBE,0xFFFF9EC7F01C60B,0xFFFFFFFFFFFFFFF,0xFFFFFFFF],[0x5F343A3F37E31DE,0x8D3B7DD448AAC3F,0xC65DEAB2679A2E1,0xCF1EACBE98B8E48,0x3C111B0EF445146,0xA1D8CB5307C0BBE,0xFFFF9EC7F01C60B,0xFFFFFFFFFFFFFFF,0xFFFFFFFF]],[[0x1660D76BC37B01E,0x5EB806161EFE02,0xD1,0x0,0x0,0x0,0x0,0x0,0x0],[0x1660D76BC37B01F,0x5EB806161EFE02,0xD1,0x0,0x0,0x0,0x0,0x0,0x0],[0x1660D76BC37B01F,0x5EB806161EFE02,0xD1,0x0,0x0,0x0,0x0,0x0,0x0],[0x1660D76BC37B01F,0x5EB806161EFE02,0xD1,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x5F343A3F37E31DF,0x8D3B7DD448AAC3F,0xC65DEAB2679A2E1,0xCF1EACBE98B8E48,0x3C111B0EF445146,0xA1D8CB5307C0BBE,0xFFFF9EC7F01C60B,0xFFFFFFFFFFFFFFF,0xFFFFFFFF],[0x3DA2F71D92AA9AF,0x45A3D4235C2F3C,0xC65DEAB2679A1A8,0xCF1EACBE98B8E48,0x3C111B0EF445146,0xA1D8CB5307C0BBE,0xFFFF9EC7F01C60B,0xFFFFFFFFFFFFFFF,0xFFFFFFFF],[0x1660D76BC37B01D,0x5EB806161EFE02,0xD1,0x0,0x0,0x0,0x0,0x0,0x0],[0x5F343A3F37E31DF,0x8D3B7DD448AAC3F,0xC65DEAB2679A2E1,0xCF1EACBE98B8E48,0x3C111B0EF445146,0xA1D8CB5307C0BBE,0xFFFF9EC7F01C60B,0xFFFFFFFFFFFFFFF,0xFFFFFFFF]]]
+
+
+#endif
+
+static let USE_GLV = true
+static let USE_GS_G2 = true
+static let USE_GS_GT = true
+static let GT_STRONG = false
+
+}
+
diff --git a/version3/swift/rom_goldilocks.swift b/version3/swift/rom_goldilocks.swift
new file mode 100644
index 0000000..0082fd1
--- /dev/null
+++ b/version3/swift/rom_goldilocks.swift
@@ -0,0 +1,70 @@
+/*
+	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.
+*/
+
+//
+//  rom.swift
+//
+//  Created by Michael Scott on 12/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+final public class ROM{
+ 
+#if D32
+
+// Base Bits= 29
+//  goldilocks Curve Modulus
+static let Modulus:[Chunk] = [0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FDFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFF]
+static let R2modp:[Chunk] = [0x0,0x10,0x0,0x0,0x0,0x0,0x0,0x0,0x3000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static let MConst:Chunk = 0x1
+
+//  goldilocks Curve
+static let CURVE_Cof_I:Int = 4
+static let CURVE_Cof:[Chunk] = [0x4,0x10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static let CURVE_A:Int = 1
+static let CURVE_B_I:Int = -39081
+static let CURVE_B:[Chunk] = [0x1FFF6756,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FDFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFF]
+static public let CURVE_Order:[Chunk] = [0xB5844F3,0x1BC61495,0x1163D548,0x1984E51B,0x3690216,0xDA4D76B,0xFA7113B,0x1FEF9944,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FF]
+static public let CURVE_Gx:[Chunk] = [0x15555555,0xAAAAAAA,0x15555555,0xAAAAAAA,0x15555555,0xAAAAAAA,0x15555555,0x152AAAAA,0xAAAAAAA,0x15555555,0xAAAAAAA,0x15555555,0xAAAAAAA,0x15555555,0xAAAAAAA,0x1555]
+static public let CURVE_Gy:[Chunk] = [0xA9386ED,0x1757DE6F,0x13681AF6,0x19657DA3,0x3098BBB,0x12C19D15,0x12E03595,0xE515B18,0x17B7E36D,0x1AC426E,0xDBB5E8,0x10D8560,0x159D6205,0xB8246D9,0x17A58D2B,0x15C0]
+
+#endif
+
+#if D64
+
+// Base Bits= 58
+//  goldilocks Curve Modulus
+static let Modulus:[Chunk] = [0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FBFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFF]
+static let R2modp:[Chunk] = [0x200000000,0x0,0x0,0x0,0x3000000,0x0,0x0,0x0]
+static let MConst:Chunk = 0x1
+
+//  goldilocks Curve
+static let CURVE_Cof_I:Int = 4
+static let CURVE_Cof:[Chunk] = [0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static let CURVE_A:Int = 1
+static let CURVE_B_I:Int = -39081
+static let CURVE_B:[Chunk] = [0x3FFFFFFFFFF6756,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FBFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFF]
+static public let CURVE_Order:[Chunk] = [0x378C292AB5844F3,0x3309CA37163D548,0x1B49AED63690216,0x3FDF3288FA7113B,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0xFFFFFFFFFF]
+static public let CURVE_Gx:[Chunk] = [0x155555555555555,0x155555555555555,0x155555555555555,0x2A5555555555555,0x2AAAAAAAAAAAAAA,0x2AAAAAAAAAAAAAA,0x2AAAAAAAAAAAAAA,0x2AAAAAAAAAA]
+static public let CURVE_Gy:[Chunk] = [0x2EAFBCDEA9386ED,0x32CAFB473681AF6,0x25833A2A3098BBB,0x1CA2B6312E03595,0x35884DD7B7E36D,0x21B0AC00DBB5E8,0x17048DB359D6205,0x2B817A58D2B]
+
+#endif
+
+}
+
diff --git a/version3/swift/rom_hifive.swift b/version3/swift/rom_hifive.swift
new file mode 100644
index 0000000..7beccfb
--- /dev/null
+++ b/version3/swift/rom_hifive.swift
@@ -0,0 +1,72 @@
+/*
+	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.
+*/
+
+//
+//  rom.swift
+//
+//  Created by Michael Scott on 12/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+final public class ROM{
+ 
+#if D32
+
+// Base Bits= 29
+//  hifive Curve Modulus
+static let Modulus:[Chunk] = [0x1FFFFFFD,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFF] 
+static let R2modp:[Chunk] = [0x9000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static let MConst:Chunk = 0x3
+
+//  hifive Curve
+static let CURVE_Cof_I:Int = 8
+static let CURVE_Cof:[Chunk] = [0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static let CURVE_A:Int = 1
+static let CURVE_B_I:Int = 11111
+static let CURVE_B:[Chunk] = [0x2B67,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Order:[Chunk] = [0x1E9FA805,0x197CACB9,0x1E4EEA9E,0x17AD70F,0x1FA9850C,0x38A0A,0x0,0x0,0x0,0x0,0x0,0x4000]
+static public let CURVE_Gx:[Chunk] = [0xC,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Gy:[Chunk] = [0x5FE8632,0x15F63428,0xD976C4,0x1AACA194,0x35B6DB5,0x8E3F7A,0x52D1B0E,0xF0A7A36,0x1C161D00,0x8170C70,0x1185AD59,0x181B]
+ 
+
+#endif
+
+#if D64
+
+// Base Bits= 60
+//  hifive Curve Modulus
+static let Modulus:[Chunk] = [0xFFFFFFFFFFFFFFD,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFF]
+static let R2modp:[Chunk] = [0x9000000000000,0x0,0x0,0x0,0x0,0x0]
+static let MConst:Chunk = 0x3
+
+//  hifive Curve
+static let CURVE_Cof_I:Int = 8
+static let CURVE_Cof:[Chunk] = [0x8,0x0,0x0,0x0,0x0,0x0]
+static let CURVE_A:Int = 1
+static let CURVE_B_I:Int = 11111
+static let CURVE_B:[Chunk] = [0x2B67,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Order:[Chunk] = [0xB2F95973E9FA805,0xC0BD6B87F93BAA7,0x71415FA9850,0x0,0x0,0x200000000]
+static public let CURVE_Gx:[Chunk] = [0xC,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Gy:[Chunk] = [0x2BEC68505FE8632,0x5D5650CA0365DB1,0x3811C7EF435B6DB,0x7853D1B14B46C,0x56502E18E1C161D,0xC0DC616B]
+ 
+
+#endif
+
+}
+
diff --git a/version3/swift/rom_nist256.swift b/version3/swift/rom_nist256.swift
new file mode 100644
index 0000000..d19b647
--- /dev/null
+++ b/version3/swift/rom_nist256.swift
@@ -0,0 +1,70 @@
+/*
+	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.
+*/
+
+//
+//  rom.swift
+//
+//  Created by Michael Scott on 12/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+final public class ROM{
+ 
+#if D32
+// Base Bits= 28
+//  nist256 Curve Modulus
+static let Modulus:[Chunk] = [0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFF,0x0,0x0,0x1000000,0x0,0xFFFFFFF,0xF]
+static let R2modp:[Chunk] = [0x50000,0x300000,0x0,0x0,0xFFFFFFA,0xFFFFFBF,0xFFFFEFF,0xFFFAFFF,0x2FFFF,0x0]
+static let MConst:Chunk = 0x1
+
+//  nist256 Curve
+static let CURVE_Cof_I:Int = 1
+static let CURVE_Cof:[Chunk] = [0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static let CURVE_A:Int = -3
+static let CURVE_B_I:Int = 0
+static let CURVE_B:[Chunk] = [0x7D2604B,0xCE3C3E2,0x3B0F63B,0x6B0CC5,0x6BC651D,0x5576988,0x7B3EBBD,0xAA3A93E,0xAC635D8,0x5]
+static public let CURVE_Order:[Chunk] = [0xC632551,0xB9CAC2F,0x79E84F3,0xFAADA71,0xFFFBCE6,0xFFFFFFF,0xFFFFFF,0x0,0xFFFFFFF,0xF]
+static public let CURVE_Gx:[Chunk] = [0x898C296,0xA13945D,0xB33A0F4,0x7D812DE,0xF27703,0xE563A44,0x7F8BCE6,0xE12C424,0xB17D1F2,0x6]
+static public let CURVE_Gy:[Chunk] = [0x7BF51F5,0xB640683,0x15ECECB,0x33576B3,0xE162BCE,0x4A7C0F9,0xB8EE7EB,0xFE1A7F9,0xFE342E2,0x4]
+
+#endif
+
+#if D64
+
+// Base Bits= 56
+//  nist256 Curve Modulus
+static let Modulus:[Chunk] = [0xFFFFFFFFFFFFFF,0xFFFFFFFFFF,0x0,0x1000000,0xFFFFFFFF]
+static let R2modp:[Chunk] = [0x3000000050000,0x0,0xFFFFFBFFFFFFFA,0xFFFAFFFFFFFEFF,0x2FFFF]
+static let MConst:Chunk = 0x1
+
+//  nist256 Curve
+static let CURVE_Cof_I:Int = 1
+static let CURVE_Cof:[Chunk] = [0x1,0x0,0x0,0x0,0x0]
+static let CURVE_A:Int = -3
+static let CURVE_B_I:Int = 0
+static let CURVE_B:[Chunk] = [0xCE3C3E27D2604B,0x6B0CC53B0F63B,0x55769886BC651D,0xAA3A93E7B3EBBD,0x5AC635D8]
+static public let CURVE_Order:[Chunk] = [0xB9CAC2FC632551,0xFAADA7179E84F3,0xFFFFFFFFFFBCE6,0xFFFFFF,0xFFFFFFFF]
+static public let CURVE_Gx:[Chunk] = [0xA13945D898C296,0x7D812DEB33A0F4,0xE563A440F27703,0xE12C4247F8BCE6,0x6B17D1F2]
+static public let CURVE_Gy:[Chunk] = [0xB6406837BF51F5,0x33576B315ECECB,0x4A7C0F9E162BCE,0xFE1A7F9B8EE7EB,0x4FE342E2]
+
+
+#endif
+
+}
+
diff --git a/version3/swift/rom_nist384.swift b/version3/swift/rom_nist384.swift
new file mode 100644
index 0000000..12511eb
--- /dev/null
+++ b/version3/swift/rom_nist384.swift
@@ -0,0 +1,70 @@
+/*
+	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.
+*/
+
+//
+//  rom.swift
+//
+//  Created by Michael Scott on 12/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+final public class ROM{
+ 
+#if D32
+
+// Base Bits= 29
+//  nist384 Curve Modulus
+static let Modulus:[Chunk] = [0x1FFFFFFF,0x7,0x0,0x1FFFFE00,0x1FFFEFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F]
+static let R2modp:[Chunk] = [0x0,0x8000,0x1FF80000,0x1FFFFF,0x2000000,0x0,0x0,0x1FFFFFFC,0xF,0x100,0x400,0x0,0x0,0x0]
+static let MConst:Chunk = 0x1
+
+//  nist384 Curve
+static let CURVE_Cof_I:Int = 1
+static let CURVE_Cof:[Chunk] = [0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static let CURVE_A:Int = -3
+static let CURVE_B_I:Int = 0
+static let CURVE_B:[Chunk] = [0x13EC2AEF,0x142E476E,0xBB4674A,0xC731B14,0x1875AC65,0x447A809,0x4480C50,0xDDFD028,0x19181D9C,0x1F1FC168,0x623815A,0x47DCFC9,0x1312FA7E,0x59]
+static public let CURVE_Order:[Chunk] = [0xCC52973,0x760CB56,0xC29DEBB,0x141B6491,0x12DDF581,0x6C0FA1B,0x1FFF1D8D,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F]
+static public let CURVE_Gx:[Chunk] = [0x12760AB7,0x12A2F1C3,0x154A5B0E,0x5E4BB7E,0x2A38550,0xF0412A,0xE6167DD,0xC5174F3,0x146E1D3B,0x1799056B,0x3AC71C7,0x1D160A6F,0x87CA22B,0x55]
+static public let CURVE_Gy:[Chunk] = [0x10EA0E5F,0x1218EBE4,0x1FA0675E,0x1639C3A,0xB8C00A6,0x1889DAF8,0x11F3A768,0x17A51342,0x9F8F41D,0x1C9496E1,0x1767A62F,0xC4C58DE,0x17DE4A9,0x1B]
+
+#endif
+
+#if D64
+
+// Base Bits= 56
+//  nist384 Curve Modulus
+static let Modulus:[Chunk] = [0xFFFFFFFF,0xFFFF0000000000,0xFFFFFFFFFEFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFF]
+static let R2modp:[Chunk] = [0xFE000000010000,0xFFFFFF,0x2,0xFFFFFFFE00,0x1000000020000,0x0,0x0]
+static let MConst:Chunk = 0x100000001
+
+//  nist384 Curve
+static let CURVE_Cof_I:Int = 1
+static let CURVE_Cof:[Chunk] = [0x1,0x0,0x0,0x0,0x0,0x0,0x0]
+static let CURVE_A:Int = -3
+static let CURVE_B_I:Int = 0
+static let CURVE_B:[Chunk] = [0x85C8EDD3EC2AEF,0x398D8A2ED19D2A,0x8F5013875AC656,0xFE814112031408,0xF82D19181D9C6E,0xE7E4988E056BE3,0xB3312FA7E23E]
+static public let CURVE_Order:[Chunk] = [0xEC196ACCC52973,0xDB248B0A77AEC,0x81F4372DDF581A,0xFFFFFFFFC7634D,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFF]
+static public let CURVE_Gx:[Chunk] = [0x545E3872760AB7,0xF25DBF55296C3A,0xE082542A385502,0x8BA79B9859F741,0x20AD746E1D3B62,0x5378EB1C71EF3,0xAA87CA22BE8B]
+static public let CURVE_Gy:[Chunk] = [0x431D7C90EA0E5F,0xB1CE1D7E819D7A,0x13B5F0B8C00A60,0x289A147CE9DA31,0x92DC29F8F41DBD,0x2C6F5D9E98BF92,0x3617DE4A9626]
+
+#endif
+
+}
+
diff --git a/version3/swift/rom_nist521.swift b/version3/swift/rom_nist521.swift
new file mode 100644
index 0000000..f1913ed
--- /dev/null
+++ b/version3/swift/rom_nist521.swift
@@ -0,0 +1,71 @@
+/*
+	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.
+*/
+
+//
+//  rom.swift
+//
+//  Created by Michael Scott on 12/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+final public class ROM{
+ 
+#if D32
+
+// Base Bits= 28
+//  nist521 Curve Modulus
+static let Modulus:[Chunk] = [0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0x1FFFF]
+static let R2modp:[Chunk] = [0x400000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static let MConst:Chunk = 0x1
+
+//  nist521 Curve
+static let CURVE_Cof_I:Int = 1
+static let CURVE_Cof:[Chunk] = [0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static let CURVE_A:Int = -3
+static let CURVE_B_I:Int = 0
+static let CURVE_B:[Chunk] = [0xB503F00,0x451FD46,0xC34F1EF,0xDF883D2,0xF073573,0xBD3BB1B,0xB1652C0,0xEC7E937,0x6193951,0xF109E15,0x489918E,0x15F3B8B,0x25B99B3,0xEEA2DA7,0xB68540,0x929A21A,0xE1C9A1F,0x3EB9618,0x5195]
+static public let CURVE_Order:[Chunk] = [0x1386409,0x6FB71E9,0xC47AEBB,0xC9B8899,0x5D03BB5,0x48F709A,0xB7FCC01,0xBF2F966,0x1868783,0xFFFFFA5,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0x1FFFF]
+static public let CURVE_Gx:[Chunk] = [0x2E5BD66,0x7E7E31C,0xA429BF9,0xB3C1856,0x8DE3348,0x27A2FFA,0x8FE1DC1,0xEFE7592,0x14B5E77,0x4D3DBAA,0x8AF606B,0xB521F82,0x139053F,0x429C648,0x62395B4,0x9E3ECB6,0x404E9CD,0x8E06B70,0xC685]
+static public let CURVE_Gy:[Chunk] = [0xFD16650,0xBE94769,0x2C24088,0x7086A27,0x761353C,0x13FAD0,0xC550B9,0x5EF4264,0x7EE7299,0x3E662C9,0xFBD1727,0x446817A,0x449579B,0xD998F54,0x42C7D1B,0x5C8A5FB,0xA3BC004,0x296A789,0x11839]
+
+
+#endif
+
+#if D64
+
+// Base Bits= 60
+//  nist521 Curve Modulus
+static let Modulus:[Chunk] = [0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0x1FFFFFFFFFF]
+static let R2modp:[Chunk] = [0x4000000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static let MConst:Chunk = 0x1
+
+//  nist521 Curve
+static let CURVE_Cof_I:Int = 1
+static let CURVE_Cof:[Chunk] = [0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static let CURVE_A:Int = -3
+static let CURVE_B_I:Int = 0
+static let CURVE_B:[Chunk] = [0xF451FD46B503F00,0x73DF883D2C34F1E,0x2C0BD3BB1BF0735,0x3951EC7E937B165,0x9918EF109E15619,0x5B99B315F3B8B48,0xB68540EEA2DA72,0x8E1C9A1F929A21A,0x51953EB961]
+static public let CURVE_Order:[Chunk] = [0xB6FB71E91386409,0xB5C9B8899C47AEB,0xC0148F709A5D03B,0x8783BF2F966B7FC,0xFFFFFFFFFFA5186,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0x1FFFFFFFFFF]
+static public let CURVE_Gx:[Chunk] = [0x97E7E31C2E5BD66,0x48B3C1856A429BF,0xDC127A2FFA8DE33,0x5E77EFE75928FE1,0xF606B4D3DBAA14B,0x39053FB521F828A,0x62395B4429C6481,0x404E9CD9E3ECB6,0xC6858E06B7]
+static public let CURVE_Gy:[Chunk] = [0x8BE94769FD16650,0x3C7086A272C2408,0xB9013FAD076135,0x72995EF42640C55,0xD17273E662C97EE,0x49579B446817AFB,0x42C7D1BD998F544,0x9A3BC0045C8A5FB,0x11839296A78]
+
+#endif
+
+}
+
diff --git a/version3/swift/rom_nums256e.swift b/version3/swift/rom_nums256e.swift
new file mode 100644
index 0000000..fc1d77a
--- /dev/null
+++ b/version3/swift/rom_nums256e.swift
@@ -0,0 +1,72 @@
+/*
+	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.
+*/
+
+//
+//  rom.swift
+//
+//  Created by Michael Scott on 12/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+final public class ROM{
+ 
+#if D32
+
+// Base Bits= 29
+//  nums256 Modulus
+static let Modulus:[Chunk] = [0x1FFFFF43,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFFFFFF]
+static let R2modp:[Chunk] = [0x22E2400,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static let MConst:Chunk = 0xBD
+
+//  nums256 Edwards Curve
+static let CURVE_Cof_I:Int = 4
+static let CURVE_Cof:[Chunk] = [0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static let CURVE_A:Int = 1
+static let CURVE_B_I:Int = -15342
+static let CURVE_B:[Chunk] = [0x1FFFC355,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0xFFFFFF]
+static public let CURVE_Order:[Chunk] = [0xEDD4AF5,0x123D8C87,0x1650E6C6,0xAB54A5E,0x419,0x0,0x0,0x0,0x400000]
+static public let CURVE_Gx:[Chunk] = [0xEED13DA,0x6F60481,0x20D61A8,0x13141DC6,0x9BD60C3,0x1EAFB490,0xDF73478,0x1F6D5D44,0x8A7514]
+static public let CURVE_Gy:[Chunk] = [0x198A89E6,0x1D30B73B,0x15BB4CB,0x1EC3B021,0x18010715,0x12ECD325,0x171F3A59,0x13FB3B24,0x44D53E]
+
+
+#endif
+
+#if D64
+
+// Base Bits= 56
+//  nums256 Modulus
+static let Modulus:[Chunk] = [0xFFFFFFFFFFFF43,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFF]
+static let R2modp:[Chunk] = [0x89000000000000,0x8B,0x0,0x0,0x0]
+static let MConst:Chunk = 0xBD
+
+//  nums256 Edwards Curve
+static let CURVE_Cof_I:Int = 4
+static let CURVE_Cof:[Chunk] = [0x4,0x0,0x0,0x0,0x0]
+static let CURVE_A:Int = 1
+static let CURVE_B_I:Int = -15342
+static let CURVE_B:[Chunk] = [0xFFFFFFFFFFC355,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFF]
+static public let CURVE_Order:[Chunk] = [0x47B190EEDD4AF5,0x5AA52F59439B1A,0x4195,0x0,0x40000000]
+static public let CURVE_Gx:[Chunk] = [0xDEC0902EED13DA,0x8A0EE3083586A0,0x5F69209BD60C39,0x6AEA237DCD1E3D,0x8A7514FB]
+static public let CURVE_Gy:[Chunk] = [0xA616E7798A89E6,0x61D810856ED32F,0xD9A64B8010715F,0xD9D925C7CE9665,0x44D53E9F]
+
+
+#endif
+
+}
+
diff --git a/version3/swift/rom_nums256w.swift b/version3/swift/rom_nums256w.swift
new file mode 100644
index 0000000..a869cc0
--- /dev/null
+++ b/version3/swift/rom_nums256w.swift
@@ -0,0 +1,72 @@
+/*
+	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.
+*/
+
+//
+//  rom.swift
+//
+//  Created by Michael Scott on 12/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+final public class ROM{
+ 
+#if D32
+
+// Base Bits= 28
+//  nums256 Modulus
+static let Modulus:[Chunk] = [0xFFFFF43,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xF]
+static let R2modp:[Chunk] = [0x0,0x8900000,0x8B,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static let MConst:Chunk = 0xBD
+
+//  nums256 Weierstrass Curve
+static let CURVE_Cof_I:Int = 1
+static let CURVE_Cof:[Chunk] = [0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static let CURVE_A:Int = -3
+static let CURVE_B_I:Int = 152961
+static let CURVE_B:[Chunk] = [0x25581,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Order:[Chunk] = [0x751A825,0xAB20294,0x65C6020,0x8275EA2,0xFFFE43C,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xF]
+static public let CURVE_Gx:[Chunk] = [0x21AACB1,0x52EE1EB,0x4C73ABC,0x9B0903D,0xB098357,0xA04F42C,0x1297A95,0x5AAADB6,0xC9ED6B6,0xB]
+static public let CURVE_Gy:[Chunk] = [0x184DE9F,0xB5B9CB2,0x10FBB80,0xC3D1153,0x35C955,0xF77E04E,0x673448B,0x3399B6A,0x8FC0F1,0xD]
+
+
+#endif
+
+#if D64
+
+// Base Bits= 56
+//  nums256 Modulus
+static let Modulus:[Chunk] = [0xFFFFFFFFFFFF43,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFF]
+static let R2modp:[Chunk] = [0x89000000000000,0x8B,0x0,0x0,0x0]
+static let MConst:Chunk = 0xBD
+
+//  nums256 Weierstrass Curve
+static let CURVE_Cof_I:Int = 1
+static let CURVE_Cof:[Chunk] = [0x1,0x0,0x0,0x0,0x0]
+static let CURVE_A:Int = -3
+static let CURVE_B_I:Int = 152961
+static let CURVE_B:[Chunk] = [0x25581,0x0,0x0,0x0,0x0]
+static public let CURVE_Order:[Chunk] = [0xAB20294751A825,0x8275EA265C6020,0xFFFFFFFFFFE43C,0xFFFFFFFFFFFFFF,0xFFFFFFFF]
+static public let CURVE_Gx:[Chunk] = [0x52EE1EB21AACB1,0x9B0903D4C73ABC,0xA04F42CB098357,0x5AAADB61297A95,0xBC9ED6B6]
+static public let CURVE_Gy:[Chunk] = [0xB5B9CB2184DE9F,0xC3D115310FBB80,0xF77E04E035C955,0x3399B6A673448B,0xD08FC0F1]
+
+
+#endif
+
+}
+
diff --git a/version3/swift/rom_nums384e.swift b/version3/swift/rom_nums384e.swift
new file mode 100644
index 0000000..dda0c48
--- /dev/null
+++ b/version3/swift/rom_nums384e.swift
@@ -0,0 +1,72 @@
+/*
+	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.
+*/
+
+//
+//  rom.swift
+//
+//  Created by Michael Scott on 12/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+final public class ROM{
+ 
+#if D32
+
+// Base Bits= 29
+//  nums384 Modulus
+static let Modulus:[Chunk] = [0x1FFFFEC3,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F]
+static let R2modp:[Chunk] = [0x0,0x4448000,0x6,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static let MConst:Chunk = 0x13D
+
+//  nums384 Edwards Curve
+static let CURVE_Cof_I:Int = 4
+static let CURVE_Cof:[Chunk] = [0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static let CURVE_A:Int = 1
+static let CURVE_B_I:Int = -11556
+static let CURVE_B:[Chunk] = [0x1FFFD19F,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F]
+static public let CURVE_Order:[Chunk] = [0x6A3897D,0x5CEE627,0xD721E48,0x8AAB556,0x1E1CF61E,0xD0E5A35,0x1FFF891C,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1F]
+static public let CURVE_Gx:[Chunk] = [0xC206BDE,0x6AA0723,0x116504D4,0x52562CA,0x163406FF,0x1FD47998,0x10015D8F,0x8DCB7C9,0x15B30BF4,0x14D72AED,0x102DA884,0xB524CD9,0x1B111FB4,0x30]
+static public let CURVE_Gy:[Chunk] = [0x10729392,0xC681F0F,0x1B123727,0x561F28D,0x1964B007,0xC7BFB22,0x1D5A0C3E,0xE9E284B,0x1716AD82,0x11D886E,0x1CE2C69,0x134DDD61,0x983E67B,0x41]
+
+
+#endif
+
+#if D64
+
+// Base Bits= 56
+//  nums384 Modulus
+static let Modulus:[Chunk] = [0xFFFFFFFFFFFEC3,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFF]
+static let R2modp:[Chunk] = [0x188890000,0x0,0x0,0x0,0x0,0x0,0x0]
+static let MConst:Chunk = 0x13D
+
+//  nums384 Edwards Curve
+static let CURVE_Cof_I:Int = 4
+static let CURVE_Cof:[Chunk] = [0x4,0x0,0x0,0x0,0x0,0x0,0x0]
+static let CURVE_A:Int = 1
+static let CURVE_B_I:Int = -11556
+static let CURVE_B:[Chunk] = [0xFFFFFFFFFFD19F,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFF]
+static public let CURVE_Order:[Chunk] = [0xB9DCC4E6A3897D,0x555AAB35C87920,0x1CB46BE1CF61E4,0xFFFFFFFFE2471A,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0x3FFFFFFFFFFF]
+static public let CURVE_Gx:[Chunk] = [0xD540E46C206BDE,0x92B16545941350,0xA8F33163406FF2,0xE5BE4C005763FF,0xE55DB5B30BF446,0x266CC0B6A2129A,0x61B111FB45A9]
+static public let CURVE_Gy:[Chunk] = [0x8D03E1F0729392,0xB0F946EC48DC9D,0xF7F645964B0072,0xF1425F56830F98,0xB10DD716AD8274,0xEEB08738B1A423,0x82983E67B9A6]
+
+
+#endif
+
+}
+
diff --git a/version3/swift/rom_nums384w.swift b/version3/swift/rom_nums384w.swift
new file mode 100644
index 0000000..0f73a8e
--- /dev/null
+++ b/version3/swift/rom_nums384w.swift
@@ -0,0 +1,73 @@
+/*
+	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.
+*/
+
+//
+//  rom.swift
+//
+//  Created by Michael Scott on 12/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+final public class ROM{
+ 
+#if D32
+
+// Base Bits= 29
+//  nums384 Modulus
+static let Modulus:[Chunk] = [0x1FFFFEC3,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F]
+static let R2modp:[Chunk] = [0x0,0x4448000,0x6,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static let MConst:Chunk = 0x13D
+
+//  nums384 Weierstrass Curve
+static let CURVE_Cof_I:Int = 1
+static let CURVE_Cof:[Chunk] = [0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static let CURVE_A:Int = -3
+static let CURVE_B_I:Int = -34568
+static let CURVE_B:[Chunk] = [0x1FFF77BB,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F]
+static public let CURVE_Order:[Chunk] = [0x1B0E61B9,0x26C0FB3,0xDF89E98,0x153A7A98,0x16881BED,0x178F75AE,0x1FFF587A,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7F]
+static public let CURVE_Gx:[Chunk] = [0x98152A,0x1CE5D021,0x18711EFA,0x1DDA201E,0xC742522,0x148D9536,0x7D3CEF4,0x19BF703F,0x60225C1,0x12082F8D,0x12203288,0x2DE3038,0x17956F0B,0x3A]
+static public let CURVE_Gy:[Chunk] = [0x6180716,0x3A5C763,0x1D2B4997,0xD69B77F,0x837EBCD,0x1BE890D,0xE72E482,0xEFF0FEE,0x1EB00469,0x2C267B,0x15F8CF4C,0x3371C71,0xDEE368E,0x56]
+
+
+#endif
+
+#if D64
+
+// Base Bits= 58
+//  nums384 Modulus
+static let Modulus:[Chunk] = [0x3FFFFFFFFFFFEC3,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0xFFFFFFFFF]
+static let R2modp:[Chunk] = [0x88900000000000,0x6,0x0,0x0,0x0,0x0,0x0]
+static let MConst:Chunk = 0x13D
+
+//  nums384 Weierstrass Curve
+static let CURVE_Cof_I:Int = 1
+static let CURVE_Cof:[Chunk] = [0x1,0x0,0x0,0x0,0x0,0x0,0x0]
+static let CURVE_A:Int = -3
+static let CURVE_B_I:Int = -34568
+static let CURVE_B:[Chunk] = [0x3FFFFFFFFFF77BB,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0xFFFFFFFFF]
+static public let CURVE_Order:[Chunk] = [0x4D81F67B0E61B9,0x2A74F530DF89E98,0x2F1EEB5D6881BED,0x3FFFFFFFFFF587A,0x3FFFFFFFFFFFFFF,0x3FFFFFFFFFFFFFF,0xFFFFFFFFF]
+static public let CURVE_Gx:[Chunk] = [0x39CBA042098152A,0x3BB4403D8711EFA,0x291B2A6CC742522,0x337EE07E7D3CEF4,0x24105F1A60225C1,0x5BC60712203288,0x757956F0B]
+static public let CURVE_Gy:[Chunk] = [0x74B8EC66180716,0x1AD36EFFD2B4997,0x37D121A837EBCD,0x1DFE1FDCE72E482,0x584CF7EB00469,0x66E38E35F8CF4C,0xACDEE368E]
+
+
+
+#endif
+
+}
+
diff --git a/version3/swift/rom_nums512e.swift b/version3/swift/rom_nums512e.swift
new file mode 100644
index 0000000..5971b84
--- /dev/null
+++ b/version3/swift/rom_nums512e.swift
@@ -0,0 +1,75 @@
+/*
+	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.
+*/
+
+//
+//  rom.swift
+//
+//  Created by Michael Scott on 12/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+final public class ROM{
+ 
+#if D32
+
+// Base Bits= 29
+//  nums512 Modulus
+static let Modulus:[Chunk] = [0x1FFFFDC7,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF]
+static let R2modp:[Chunk] = [0xB100000,0x278,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static let MConst:Chunk = 0x239
+
+//  nums512 Edwards Curve
+static let CURVE_Cof_I:Int = 4
+static let CURVE_Cof:[Chunk] = [0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static let CURVE_A:Int = 1
+static let CURVE_B_I:Int = -78296
+static public let CURVE_B:[Chunk] = [0x1FFECBEF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF]
+static public let CURVE_Order:[Chunk] = [0x1BEED46D,0x1A3467A8,0x1BFB3FD9,0xC0AF0DB,0x86F52A4,0xC64B85B,0x6EA78FF,0xDA5F9F2,0x1FB4F063,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFF]
+static public let CURVE_Gx:[Chunk] = [0x19EC57FE,0xDCD594C,0x113C0571,0xA4A84F9,0x104AD0FE,0x4C92B44,0xC3DE2F7,0x9DDC8CE,0x74621C1,0x1139DC0A,0x9E85FAF,0x1B894704,0x1D1E79F4,0x9E29997,0x32DE223,0x16D38F43,0x116D128D,0x6FC71]
+static public let CURVE_Gy:[Chunk] = [0x1E2F5E1,0x136EF606,0x1C7407CC,0xDA71537,0xC1FD026,0x3431576,0x15898068,0x1E5D32C6,0x120CA53,0xC84F41A,0xA4ADAE5,0x104B3A45,0x76F726D,0x1512B772,0x3D5DEA0,0x194E3316,0x1FF39D49,0x3684D]
+
+
+//  nums384 Edwards Curve
+
+#endif
+
+#if D64
+
+// Base Bits= 60
+//  nums512 Modulus
+static let Modulus:[Chunk] = [0xFFFFFFFFFFFFDC7,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFF]
+static let R2modp:[Chunk] = [0x100000000000000,0x4F0B,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static let MConst:Chunk = 0x239
+
+//  nums512 Edwards Curve
+static let CURVE_Cof_I:Int = 4
+static let CURVE_Cof:[Chunk] = [0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static let CURVE_A:Int = 1
+static let CURVE_B_I:Int = -78296
+static let CURVE_B:[Chunk] = [0xFFFFFFFFFFECBEF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFF]
+static public let CURVE_Order:[Chunk] = [0x7468CF51BEED46D,0x4605786DEFECFF6,0xFD8C970B686F52A,0x636D2FCF91BA9E3,0xFFFFFFFFFFFB4F0,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0x3FFFFFFF]
+static public let CURVE_Gx:[Chunk] = [0x5B9AB2999EC57FE,0xE525427CC4F015C,0xDC992568904AD0F,0xC14EEE46730F78B,0xEBE273B81474621,0x9F4DC4A38227A17,0x888D3C5332FD1E7,0x128DB69C7A18CB7,0xDF8E316D]
+static public let CURVE_Gy:[Chunk] = [0x26DDEC0C1E2F5E1,0x66D38A9BF1D01F3,0xA06862AECC1FD02,0x53F2E9963562601,0xB95909E834120CA,0x26D8259D22A92B6,0x7A82A256EE476F7,0x9D49CA7198B0F57,0x6D09BFF3]
+
+
+
+#endif
+
+}
+
diff --git a/version3/swift/rom_nums512w.swift b/version3/swift/rom_nums512w.swift
new file mode 100644
index 0000000..a9c331d
--- /dev/null
+++ b/version3/swift/rom_nums512w.swift
@@ -0,0 +1,72 @@
+/*
+	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.
+*/
+
+//
+//  rom.swift
+//
+//  Created by Michael Scott on 12/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+final public class ROM{
+ 
+#if D32
+
+// Base Bits= 29
+//  nums512 Modulus
+static let Modulus:[Chunk] = [0x1FFFFDC7,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF]
+static let R2modp:[Chunk] = [0xB100000,0x278,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static let MConst:Chunk = 0x239
+
+//  nums512 Weierstrass Curve
+static let CURVE_Cof_I:Int = 1
+static let CURVE_Cof:[Chunk] = [0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static let CURVE_A:Int = -3
+static let CURVE_B_I:Int = 121243
+static let CURVE_B:[Chunk] = [0x1D99B,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Order:[Chunk] = [0x433555D,0x10A9F9C8,0x1F3490F3,0xD166CC0,0xBDC63B5,0xC76CBE8,0xC6D3F09,0x1F729CF0,0x1F5B3CA4,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x1FFFFFFF,0x7FFFF]
+static public let CURVE_Gx:[Chunk] = [0xCABAE57,0x4143CAC,0x1BD778B7,0x1AC026FA,0x15831D5,0x14312AB,0x167A4DE5,0xA20ED66,0x195021A1,0x129836CF,0x1141B830,0xA03ED0A,0xCAD83BB,0x1E9DA94C,0xDC00A80,0x1527B45,0x1447141D,0x1D601]
+static public let CURVE_Gy:[Chunk] = [0x183527A6,0x1D043B01,0x1F43FA48,0x16B83C99,0x5602CF2,0x1420592D,0x17A70486,0x1B5161DD,0x14A28415,0x3DE8A78,0x3D2C983,0x17797719,0x197DBDEA,0x15D88025,0x1BBB718F,0xAD679C1,0x14CA29AD,0x4A1D2]
+
+
+#endif
+
+#if D64
+
+// Base Bits= 60
+//  nums512 Modulus
+static let Modulus:[Chunk] = [0xFFFFFFFFFFFFDC7,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFF]
+static let R2modp:[Chunk] = [0x100000000000000,0x4F0B,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static let MConst:Chunk = 0x239
+
+//  nums512 Weierstrass Curve
+static let CURVE_Cof_I:Int = 1
+static let CURVE_Cof:[Chunk] = [0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static let CURVE_A:Int = -3
+static let CURVE_B_I:Int = 121243
+static let CURVE_B:[Chunk] = [0x1D99B,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Order:[Chunk] = [0xE153F390433555D,0x568B36607CD243C,0x258ED97D0BDC63B,0xA4FB94E7831B4FC,0xFFFFFFFFFFF5B3C,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFF,0xFFFFFFFF]
+static public let CURVE_Gx:[Chunk] = [0xC8287958CABAE57,0x5D60137D6F5DE2D,0x94286255615831D,0xA151076B359E937,0xC25306D9F95021,0x3BB501F6854506E,0x2A03D3B5298CAD8,0x141D0A93DA2B700,0x3AC03447]
+static public let CURVE_Gy:[Chunk] = [0x3A08760383527A6,0x2B5C1E4CFD0FE92,0x1A840B25A5602CF,0x15DA8B0EEDE9C12,0x60C7BD14F14A284,0xDEABBCBB8C8F4B2,0xC63EBB1004B97DB,0x29AD56B3CE0EEED,0x943A54CA]
+
+
+#endif
+
+}
+
diff --git a/version3/swift/rom_secp256k1.swift b/version3/swift/rom_secp256k1.swift
new file mode 100644
index 0000000..7f46aba
--- /dev/null
+++ b/version3/swift/rom_secp256k1.swift
@@ -0,0 +1,70 @@
+/*
+	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.
+*/
+
+//
+//  rom.swift
+//
+//  Created by Michael Scott on 12/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+final public class ROM{
+ 
+#if D32
+// Base Bits= 28
+//  secp256k1 Curve Modulus
+static let Modulus:[Chunk] = [0xFFFFC2F,0xFFFFFEF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xF]
+static let R2modp:[Chunk] = [0x0,0xA100000,0x2000E90,0x7A,0x1,0x0,0x0,0x0,0x0,0x0]
+static let MConst:Chunk = 0x2253531
+
+//  secp256k1 Curve
+static let CURVE_A:Int = 0
+static let CURVE_Cof_I:Int = 1
+static public let CURVE_Cof:[Chunk] = [0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static let CURVE_B_I:Int = 7
+static public let CURVE_B:[Chunk] = [0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
+static public let CURVE_Order:[Chunk] = [0x364141,0xD25E8CD,0x8A03BBF,0xDCE6AF4,0xFFEBAAE,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xFFFFFFF,0xF]
+static public let CURVE_Gx:[Chunk] = [0x6F81798,0xF2815B1,0xE28D959,0xFCDB2DC,0xB07029B,0x95CE870,0xC55A062,0xF9DCBBA,0x9BE667E,0x7]
+static public let CURVE_Gy:[Chunk] = [0xB10D4B8,0x47D08FF,0x554199C,0xB448A68,0x8A8FD17,0xFC0E110,0x55DA4FB,0x26A3C46,0x83ADA77,0x4]
+
+#endif
+
+#if D64
+
+// Base Bits= 56
+//  secp256k1 Curve Modulus
+static let Modulus:[Chunk] = [0xFFFFFEFFFFFC2F,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFF]
+static let R2modp:[Chunk] = [0xA1000000000000,0x7A2000E90,0x1,0x0,0x0]
+static let MConst:Chunk = 0x38091DD2253531
+
+//  secp256k1 Curve
+static let CURVE_A:Int = 0
+static let CURVE_Cof_I:Int = 1
+static public let CURVE_Cof:[Chunk] = [0x1,0x0,0x0,0x0,0x0]
+static let CURVE_B_I:Int = 7
+static public let CURVE_B:[Chunk] = [0x7,0x0,0x0,0x0,0x0]
+static public let CURVE_Order:[Chunk] = [0xD25E8CD0364141,0xDCE6AF48A03BBF,0xFFFFFFFFFEBAAE,0xFFFFFFFFFFFFFF,0xFFFFFFFF]
+static public let CURVE_Gx:[Chunk] = [0xF2815B16F81798,0xFCDB2DCE28D959,0x95CE870B07029B,0xF9DCBBAC55A062,0x79BE667E]
+static public let CURVE_Gy:[Chunk] = [0x47D08FFB10D4B8,0xB448A68554199C,0xFC0E1108A8FD17,0x26A3C4655DA4FB,0x483ADA77]
+
+
+#endif
+
+}
+
diff --git a/version3/swift/rsa.swift b/version3/swift/rsa.swift
new file mode 100644
index 0000000..40ec027
--- /dev/null
+++ b/version3/swift/rsa.swift
@@ -0,0 +1,390 @@
+/*
+	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.
+*/
+
+//
+//  rsa.swift
+//
+//  Created by Michael Scott on 25/06/2015.
+//  Copyright (c) 2015 Michael Scott. All rights reserved.
+//
+
+import amcl
+
+/* RSA API high-level functions  */
+
+public struct rsa_private_key {
+    var p:FF
+    var q:FF
+    var dp:FF
+    var dq:FF
+    var c:FF
+    
+    public init(_ n: Int)
+    {
+    p=FF(n);
+    q=FF(n);
+    dp=FF(n);
+    dq=FF(n);
+    c=FF(n);
+    }
+}
+
+public struct rsa_public_key
+{
+    var e:Int
+    var n:FF
+    
+    public init(_ m:Int)
+    {
+        e=0;
+        n=FF(m);
+    }
+}
+
+public struct RSA {
+    
+    static public let RFS=Int(BIG.MODBYTES*FF.FFLEN)
+    static public let SHA256=32
+    static public let SHA384=48
+    static public let SHA512=64
+    
+    static public let HASH_TYPE=SHA384
+    
+    /* Hash number (optional) and string to array size of Bigs */
+ 
+    static private func hashit(_ sha:Int,_ A: [UInt8]?,_ n: Int32) -> [UInt8]
+    {
+        if sha==RSA.SHA256
+        {
+            var H=HASH256()
+            if A != nil {H.process_array(A!)}
+            if n >= 0 {H.process_num(n)}
+            let R=H.hash()
+            return R
+        }
+        if sha==RSA.SHA384
+        {
+            var H=HASH384()
+            if A != nil {H.process_array(A!)}
+            if n >= 0 {H.process_num(n)}
+            let R=H.hash()
+            return R
+        }
+        if sha==RSA.SHA512
+        {
+            var H=HASH512()
+            if A != nil {H.process_array(A!)}
+            if n >= 0 {H.process_num(n)}
+            let R=H.hash()
+            return R
+        }
+        return [UInt8]()
+    }
+
+    /* generate an RSA key pair */
+    
+    static public func KEY_PAIR(_ rng: inout RAND,_ e:Int,_ PRIV: inout rsa_private_key,_ PUB: inout rsa_public_key)
+    { /* IEEE1363 A16.11/A16.12 more or less */
+    
+        let n=PUB.n.getlen()/2;
+        let t = FF(n);
+        let p1=FF(n);
+        let q1=FF(n);
+    
+        while true
+        {
+    
+            PRIV.p.random(&rng);
+            while PRIV.p.lastbits(2) != 3 {PRIV.p.inc(1)}
+            while !FF.prime(PRIV.p,&rng) {PRIV.p.inc(4)}
+    
+            p1.copy(PRIV.p);
+            p1.dec(1);
+    
+            if p1.cfactor(e) {continue}
+            break;
+        }
+    
+        while true
+        {
+            PRIV.q.random(&rng);
+            while PRIV.q.lastbits(2) != 3 {PRIV.q.inc(1)}
+            while !FF.prime(PRIV.q,&rng) {PRIV.q.inc(4)}
+    
+            q1.copy(PRIV.q);
+            q1.dec(1);
+    
+            if q1.cfactor(e) {continue}
+    
+            break;
+        }
+    
+        PUB.n=FF.mul(PRIV.p,PRIV.q);
+        PUB.e=e;
+    
+        t.copy(p1);
+        t.shr();
+        PRIV.dp.set(e);
+        PRIV.dp.invmodp(t);
+        if (PRIV.dp.parity()==0) {PRIV.dp.add(t)}
+        PRIV.dp.norm();
+    
+        t.copy(q1);
+        t.shr();
+        PRIV.dq.set(e);
+        PRIV.dq.invmodp(t);
+        if (PRIV.dq.parity()==0) {PRIV.dq.add(t)}
+        PRIV.dq.norm();
+    
+        PRIV.c.copy(PRIV.p);
+        PRIV.c.invmodp(PRIV.q);
+    
+        return;
+    }
+    /* Mask Generation Function */
+    
+    static func MGF1(_ sha: Int,_ Z: [UInt8],_ olen:Int,_ K:inout [UInt8])
+    {
+        let hlen=sha
+    
+        var k=0;
+        for i in 0 ..< K.count {K[i]=0}
+    
+        var cthreshold=Int32(olen/hlen); if (olen%hlen != 0) {cthreshold += 1}
+        for counter:Int32 in 0 ..< cthreshold
+        {
+            var B=RSA.hashit(sha,Z,counter)
+            if (k+hlen>olen) {for i in 0 ..< olen%hlen {K[k]=B[i]; k+=1}}
+            else {for i in 0 ..< hlen {K[k]=B[i]; k+=1}}
+        }
+    }
+    
+    static let SHA256ID:[UInt8]=[0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20]
+    static let SHA384ID:[UInt8]=[0x30,0x41,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00,0x04,0x30]
+    static let SHA512ID:[UInt8]=[0x30,0x51,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0x04,0x40]
+    
+    /* PKCS 1.5 padding of a message to be signed */
+    static public func PKCS15(_ sha:Int,_ m:[UInt8],_ w:inout [UInt8])->Bool
+    {
+        let hlen=sha
+        let olen=Int(FF.FF_BITS/8)
+        let idlen=19;
+        
+        if olen<idlen+hlen+10 {return false}
+        let H=hashit(sha,m,-1)
+        for i in 0 ..< w.count {w[i]=0}
+        
+        w[0]=0
+        w[1]=1
+        var i=2
+        var j=0
+        
+        while j<olen-idlen-hlen-3
+        {
+            w[i]=0xff
+            i+=1; j+=1
+        }
+        w[i]=0; i+=1;
+        
+        if hlen==RSA.SHA256
+        {
+            for j in 0 ..< idlen {w[i]=SHA256ID[j]; i+=1}
+        }
+        if hlen==RSA.SHA384
+        {
+            for j in 0 ..< idlen {w[i]=SHA384ID[j]; i+=1}
+        }
+        if hlen==RSA.SHA512
+        {
+            for j in 0 ..< idlen {w[i]=SHA512ID[j]; i+=1}
+        }
+        
+        for j in 0 ..< hlen {w[i]=H[j];i+=1}
+        
+        return true
+    }
+    
+    
+    /* OAEP Message Encoding for Encryption */
+    static public func OAEP_ENCODE(_ sha:Int,_ m:[UInt8],_ rng: inout RAND,_ p:[UInt8]?) -> [UInt8]
+    {
+        let olen=RFS-1;
+        let mlen=m.count;
+        var f=[UInt8](repeating: 0,count: RSA.RFS)
+    
+        let hlen=sha;
+        var SEED=[UInt8](repeating: 0,count: hlen)
+        let seedlen=hlen;
+        if (mlen>olen-hlen-seedlen-1) {return [UInt8]()}
+    
+        var DBMASK=[UInt8](repeating: 0,count: olen-seedlen)
+        
+        var h=hashit(sha,p,-1)
+        for i in 0 ..< hlen {f[i]=h[i]}
+    
+        let slen=olen-mlen-hlen-seedlen-1;
+    
+        for i in 0 ..< slen {f[hlen+i]=0}
+        f[hlen+slen]=1;
+        for i in 0 ..< mlen {f[hlen+slen+1+i]=m[i]}
+    
+        for i in 0 ..< seedlen {SEED[i]=rng.getByte()}
+        RSA.MGF1(sha,SEED,olen-seedlen,&DBMASK)
+    
+        for i in 0 ..< olen-seedlen {DBMASK[i]^=f[i]}
+        RSA.MGF1(sha,DBMASK,seedlen,&f)
+    
+        for i in 0 ..< seedlen {f[i]^=SEED[i]}
+    
+        for i in 0 ..< olen-seedlen {f[i+seedlen]=DBMASK[i]}
+    
+    /* pad to length RFS */
+        let d:Int=1;
+        for i in (d...RFS-1).reversed()
+            {f[i]=f[i-d]}
+        for i in 0...d-1
+            {f[i]=0}
+    
+        return f;
+    }
+    
+    /* OAEP Message Decoding for Decryption */
+    static public func OAEP_DECODE(_ sha: Int,_ p: [UInt8]?,_ f:inout [UInt8]) -> [UInt8]
+    {
+        let olen=RFS-1
+        var k:Int
+        let hlen=sha
+        var SEED=[UInt8](repeating: 0,count: hlen)
+        let seedlen=hlen
+        var CHASH=[UInt8](repeating: 0,count: hlen)
+        
+        if olen<seedlen+hlen+1 {return [UInt8()]}
+        var DBMASK=[UInt8](repeating: 0,count: olen-seedlen)
+        for i in 0 ..< olen-seedlen {DBMASK[i]=0}
+    
+        if (f.count<RFS)
+        {
+            let d=RFS-f.count;
+            for i in (d...RFS-1).reversed()
+                {f[i]=f[i-d]}
+            for i in 0...d-1
+                {f[i]=0}
+    
+        }
+    
+        var h=hashit(sha,p,-1)
+        for i in 0 ..< hlen {CHASH[i]=h[i]}
+    
+        let x=f[0];
+    
+        for i in seedlen ..< olen
+            {DBMASK[i-seedlen]=f[i+1]}
+    
+        RSA.MGF1(sha,DBMASK,seedlen,&SEED);
+        for i in 0 ..< seedlen {SEED[i]^=f[i+1]}
+        RSA.MGF1(sha,SEED,olen-seedlen,&f);
+        for i in 0 ..< olen-seedlen {DBMASK[i]^=f[i]}
+    
+        var comp=true;
+        for i in 0 ..< hlen
+        {
+            if (CHASH[i] != DBMASK[i]) {comp=false}
+        }
+    
+        for i in 0 ..< olen-seedlen-hlen
+        {DBMASK[i]=DBMASK[i+hlen]}
+    
+        for i in 0 ..< hlen
+            {SEED[i]=0;CHASH[i]=0;}
+    
+        k=0
+        while (true)
+        {
+            if (k>=olen-seedlen-hlen) {return [UInt8]()}
+            if (DBMASK[k] != 0) {break}
+            k+=1
+        }
+    
+        let t=DBMASK[k];
+        if (!comp || x != 0 || t != 0x01)
+        {
+            for i in 0 ..< olen-seedlen {DBMASK[i]=0}
+            return [UInt8]()
+        }
+    
+        var r=[UInt8](repeating: 0,count: olen-seedlen-hlen-k-1)
+    
+        for i in 0 ..< olen-seedlen-hlen-k-1
+            {r[i]=DBMASK[i+k+1]}
+    
+        for i in 0 ..< olen-seedlen {DBMASK[i]=0}
+    
+        return r;
+    }
+    /* destroy the Private Key structure */
+    static public func PRIVATE_KEY_KILL(_ PRIV: rsa_private_key)
+    {
+        PRIV.p.zero();
+        PRIV.q.zero();
+        PRIV.dp.zero();
+        PRIV.dq.zero();
+        PRIV.c.zero();
+    }
+    /* RSA encryption with the public key */
+    static public func ENCRYPT(_ PUB: rsa_public_key,_ F:[UInt8],_ G:inout [UInt8])
+    {
+        let n=PUB.n.getlen()
+        let f=FF(n)
+    
+        FF.fromBytes(f,F)
+        f.power(PUB.e,PUB.n)
+        f.toBytes(&G)
+    }
+    /* RSA decryption with the private key */
+    static public func DECRYPT(_ PRIV: rsa_private_key,_ G:[UInt8],_ F:inout [UInt8])
+    {
+        let n=PRIV.p.getlen()
+        let g=FF(2*n)
+    
+        FF.fromBytes(g,G)
+        let jp=g.dmod(PRIV.p)
+        var jq=g.dmod(PRIV.q)
+    
+        jp.skpow(PRIV.dp,PRIV.p)
+        jq.skpow(PRIV.dq,PRIV.q)
+    
+        g.zero()
+        g.dscopy(jp)
+        jp.mod(PRIV.q)
+        if (FF.comp(jp,jq)>0) {jq.add(PRIV.q)}
+        jq.sub(jp)
+        jq.norm()
+    
+        var t=FF.mul(PRIV.c,jq)
+        jq=t.dmod(PRIV.q)
+    
+        t=FF.mul(jq,PRIV.p)
+        g.add(t);
+        g.norm();
+    
+        g.toBytes(&F);
+    }
+    
+}
+
diff --git a/version3/swift/sha3.swift b/version3/swift/sha3.swift
new file mode 100644
index 0000000..fa99d5a
--- /dev/null
+++ b/version3/swift/sha3.swift
@@ -0,0 +1,264 @@
+/*
+	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.
+*/
+
+//
+//  sha3.swift - Implementation of SHA3
+//
+//  Created by Michael Scott on 7/08/2017.
+//
+
+import Foundation
+
+public struct SHA3{
+
+    	private var length:UInt64
+	private var rate:Int
+	private var len:Int
+	private var s=[[UInt64]](repeating:[UInt64](repeating:0,count:5),count:5)
+
+    	static let RC:[UInt64]=[
+		0x0000000000000001,0x0000000000008082,0x800000000000808A,0x8000000080008000,
+		0x000000000000808B,0x0000000080000001,0x8000000080008081,0x8000000000008009,
+		0x000000000000008A,0x0000000000000088,0x0000000080008009,0x000000008000000A,
+		0x000000008000808B,0x800000000000008B,0x8000000000008089,0x8000000000008003,
+		0x8000000000008002,0x8000000000000080,0x000000000000800A,0x800000008000000A,
+		0x8000000080008081,0x8000000000008080,0x0000000080000001,0x8000000080008008]
+
+	static let HASH224:Int=28
+	static let HASH256:Int=32
+	static let HASH384:Int=48
+	static let HASH512:Int=64
+	static let SHAKE128:Int=16
+	static let SHAKE256:Int=32
+    	
+	static let ROUNDS:Int=24
+    
+    	private static func rotl(_ x: UInt64,_ n: UInt32) -> UInt64
+    	{
+        	return ((x<<UInt64(n))|(x>>(64-UInt64(n))))
+    	}
+   
+    	private mutating func transform()
+    	{ /* basic transformation step */
+        	var c=[UInt64](repeating:0,count:5)
+		var d=[UInt64](repeating:0,count:5)
+		var b=[[UInt64]](repeating:[UInt64](repeating:0,count:5),count:5)
+	
+		for k in 0 ..< SHA3.ROUNDS 
+		{
+			c[0]=s[0][0]^s[0][1]^s[0][2]^s[0][3]^s[0][4]
+			c[1]=s[1][0]^s[1][1]^s[1][2]^s[1][3]^s[1][4]
+			c[2]=s[2][0]^s[2][1]^s[2][2]^s[2][3]^s[2][4]
+			c[3]=s[3][0]^s[3][1]^s[3][2]^s[3][3]^s[3][4]
+			c[4]=s[4][0]^s[4][1]^s[4][2]^s[4][3]^s[4][4]
+
+			d[0]=c[4]^SHA3.rotl(c[1],1)
+			d[1]=c[0]^SHA3.rotl(c[2],1)
+			d[2]=c[1]^SHA3.rotl(c[3],1)
+			d[3]=c[2]^SHA3.rotl(c[4],1)
+			d[4]=c[3]^SHA3.rotl(c[0],1)
+
+			for i in 0 ..< 5 {
+				for j in 0 ..< 5 {
+					s[i][j]^=d[i]
+				}
+			}
+		
+			b[0][0]=s[0][0]
+			b[1][3]=SHA3.rotl(s[0][1],36)
+			b[2][1]=SHA3.rotl(s[0][2],3)
+			b[3][4]=SHA3.rotl(s[0][3],41)
+			b[4][2]=SHA3.rotl(s[0][4],18)
+
+			b[0][2]=SHA3.rotl(s[1][0],1)
+			b[1][0]=SHA3.rotl(s[1][1],44)
+			b[2][3]=SHA3.rotl(s[1][2],10)
+			b[3][1]=SHA3.rotl(s[1][3],45)
+			b[4][4]=SHA3.rotl(s[1][4],2)
+
+			b[0][4]=SHA3.rotl(s[2][0],62)
+			b[1][2]=SHA3.rotl(s[2][1],6)
+			b[2][0]=SHA3.rotl(s[2][2],43)
+			b[3][3]=SHA3.rotl(s[2][3],15)
+			b[4][1]=SHA3.rotl(s[2][4],61)
+
+			b[0][1]=SHA3.rotl(s[3][0],28)
+			b[1][4]=SHA3.rotl(s[3][1],55)
+			b[2][2]=SHA3.rotl(s[3][2],25)
+			b[3][0]=SHA3.rotl(s[3][3],21)
+			b[4][3]=SHA3.rotl(s[3][4],56)
+
+			b[0][3]=SHA3.rotl(s[4][0],27)
+			b[1][1]=SHA3.rotl(s[4][1],20)
+			b[2][4]=SHA3.rotl(s[4][2],39)
+			b[3][2]=SHA3.rotl(s[4][3],8)
+			b[4][0]=SHA3.rotl(s[4][4],14)
+
+			for i in 0 ..< 5 {
+				for j in 0 ..< 5 {
+					s[i][j]=b[i][j]^(~b[(i+1)%5][j]&b[(i+2)%5][j])
+				}
+			}
+			s[0][0]^=SHA3.RC[k]
+		}
+    	}
+    
+    /* Re-Initialise Hash function */
+    	mutating func init_it(_ olen: Int)
+    	{ /* initialise */
+		len=olen
+		rate=200-2*olen 
+    	}
+    
+    	public init(_ olen: Int)
+    	{
+      		for i in 0 ..< 5 {
+			for j in 0..<5 {
+				s[i][j]=0
+			}
+		}
+        	length=0
+		len=0
+		rate=0 
+        	init_it(olen)
+    	}
+    
+    /* process a single byte */
+    	public mutating func process(_ byt: UInt8)
+    	{ /* process the next message byte */
+		let cnt=Int(length%UInt64(rate))
+		let b=cnt%8
+		let ind=cnt/8
+		let i=ind%5
+		let j=ind/5
+		s[i][j]^=(UInt64(byt)&0xff)<<UInt64(8*b)
+		length+=1
+		if cnt+1 == rate {transform()}
+    	}
+
+	public mutating func squeeze(_ buff:inout [UInt8],_ olen: Int)
+	{
+		var done=false
+		var m: Int = 0
+	/* extract by columns */
+		while true {
+			for j in 0 ..< 5 {
+				for i in 0 ..< 5 
+				{
+					var el=s[i][j]
+					for _ in 0 ..< 8 
+					{
+						buff[m]=UInt8(el&0xff)
+						m+=1
+						if m>=olen || (m%rate)==0 {
+							done=true
+							break
+						}
+						el>>=8
+					}
+					if done {break}
+				}
+				if done {break}
+			}
+			if m>=olen {break}
+			done=false
+			transform()
+		}		
+	}
+    
+    /* Generate Hash */
+	public mutating func hash(_ digest:inout [UInt8])
+    	{ /* pad message and finish - supply digest */
+        	let q=rate-Int(length%UInt64(rate))
+		if q==1 {process(0x86)}
+		else {
+			process(0x06)
+			while Int(length%UInt64(rate)) != rate-1 {process(0x00)}
+			process(0x80)
+		}
+		squeeze(&digest,len)
+	}
+
+    public mutating func shake(_ digest:inout [UInt8],_ olen: Int)
+	{
+		let q=rate-Int(length%UInt64(rate))
+		if q==1 {process(0x9f)}
+		else {
+			process(0x1f)
+			while Int(length%UInt64(rate)) != rate-1 {process(0x00)}
+			process(0x80)
+		}
+ 		squeeze(&digest,olen)
+	}   
+}
+
+//916f6061fe879741ca6469b43971dfdb28b1a32dc36cb3254e812be27aad1d18
+//afebb2ef542e6579c50cad06d2e578f9f8dd6881d7dc824d26360feebf18a4fa73e3261122948efcfd492e74e82e2189ed0fb440d187f382270cb455f21dd185
+//98be04516c04cc73593fef3ed0352ea9f6443942d6950e29a372a681c3deaf4535423709b02843948684e029010badcc0acd8303fc85fdad3eabf4f78cae165635f57afd28810fc2
+
+/*
+public func TestSHA3()
+{
+    	let test=String("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu")
+    
+    	var digest=[UInt8](repeating: 0,count: 172)
+    
+    	let t=[UInt8]( (test!).utf8)
+
+	var sh=SHA3(SHA3.HASH256)
+	for i in 0..<t.count {
+		sh.process(t[i])
+	}
+	sh.hash(&digest)
+
+       	for i in 0 ..< 32
+        {
+            let h=String(digest[i],radix:16)
+            print("\(h)", terminator: "")
+        }
+        print("")
+	    
+	sh=SHA3(SHA3.HASH512)
+	for i in 0..<t.count {
+		sh.process(t[i])
+	}
+	sh.hash(&digest)
+
+       	for i in 0 ..< 64
+        {
+            let h=String(digest[i],radix:16)
+            print("\(h)", terminator: "")
+        }
+        print("")
+
+	sh=SHA3(SHA3.SHAKE256)
+	for i in 0..<t.count {
+		sh.process(t[i])
+	}
+	sh.shake(&digest,72)
+
+       	for i in 0 ..< 72
+        {
+            let h=String(digest[i],radix:16)
+            print("\(h)", terminator: "")
+        }
+        print("")
+}
+
+TestSHA3()  */
diff --git a/version3/wasm/config.py b/version3/wasm/config.py
new file mode 100644
index 0000000..e13c2fd
--- /dev/null
+++ b/version3/wasm/config.py
@@ -0,0 +1,669 @@
+import os
+import sys
+
+deltext=""
+if sys.platform.startswith("linux")  :
+	deltext="rm"
+	copytext="cp"
+if sys.platform.startswith("darwin")  :
+	deltext="rm"
+	copytext="cp"
+if sys.platform.startswith("win") :
+	deltext="del"
+	copytext="copy"
+
+def replace(namefile,oldtext,newtext):
+	f = open(namefile,'r')
+	filedata = f.read()
+	f.close()
+
+	newdata = filedata.replace(oldtext,newtext)
+
+	f = open(namefile,'w')
+	f.write(newdata)
+	f.close()
+
+
+def rsaset(tb,tff,nb,base,ml) :
+	bd=tb+"_"+base
+	fnameh="config_big_"+bd+".h"
+	os.system(copytext+" config_big.h "+fnameh)
+	replace(fnameh,"XXX",bd)
+	replace(fnameh,"@NB@",nb)
+	replace(fnameh,"@BASE@",base)
+
+	fnameh="config_ff_"+tff+".h"
+	os.system(copytext+" config_ff.h "+fnameh)
+	replace(fnameh,"XXX",bd)
+	replace(fnameh,"WWW",tff)
+	replace(fnameh,"@ML@",ml);
+
+	fnamec="big_"+bd+".c"
+	fnamebc="big_"+bd+".bc"
+	fnameh="big_"+bd+".h"
+
+	os.system(copytext+" big.c "+fnamec)
+	os.system(copytext+" big.h "+fnameh)
+
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"XXX",bd)
+	os.system("emcc -O2 "+fnamec+" -o "+fnamebc)
+
+	fnamec="ff_"+tff+".c"
+	fnamebc="ff_"+tff+".bc"
+	fnameh="ff_"+tff+".h"
+
+	os.system(copytext+" ff.c "+fnamec)
+	os.system(copytext+" ff.h "+fnameh)
+
+	replace(fnamec,"WWW",tff)
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"WWW",tff)
+	replace(fnameh,"XXX",bd)
+	os.system("emcc -O2 "+fnamec+" -o "+fnamebc)
+
+	fnamec="rsa_"+tff+".c"
+	fnamebc="rsa_"+tff+".bc"
+	fnameh="rsa_"+tff+".h"
+
+	os.system(copytext+" rsa.c "+fnamec)
+	os.system(copytext+" rsa.h "+fnameh)
+
+	replace(fnamec,"WWW",tff)
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"WWW",tff)
+	replace(fnameh,"XXX",bd)
+	os.system("emcc -O2 "+fnamec+" -o "+fnamebc)
+
+def curveset(tb,tf,tc,nb,base,nbt,m8,mt,ct,pf,stw,sx,cs) :
+	bd=tb+"_"+base
+
+	fnameh="config_big_"+bd+".h"
+	os.system(copytext+" config_big.h "+fnameh)
+
+	replace(fnameh,"XXX",bd)
+	replace(fnameh,"@NB@",nb)
+	replace(fnameh,"@BASE@",base)
+
+
+	fnameh="config_field_"+tf+".h"
+	os.system(copytext+" config_field.h "+fnameh)
+	replace(fnameh,"XXX",bd)
+	replace(fnameh,"YYY",tf)
+	replace(fnameh,"@NBT@",nbt)
+	replace(fnameh,"@M8@",m8)
+	replace(fnameh,"@MT@",mt)
+
+	ib=int(base)
+
+	ib=int(base)
+	inb=int(nb)
+	inbt=int(nbt)
+	sh=ib*(1+((8*inb-1)//ib))-inbt
+	if sh > 14 :
+		sh=14
+	replace(fnameh,"@SH@",str(sh))
+
+	fnameh="config_curve_"+tc+".h"	
+	os.system(copytext+" config_curve.h "+fnameh)
+	replace(fnameh,"XXX",bd)
+	replace(fnameh,"YYY",tf)
+	replace(fnameh,"ZZZ",tc)
+	replace(fnameh,"@CT@",ct)
+	replace(fnameh,"@PF@",pf)
+
+	replace(fnameh,"@ST@",stw)
+	replace(fnameh,"@SX@",sx)
+	replace(fnameh,"@CS@",cs)
+
+	fnamec="big_"+bd+".c"
+	fnamebc="big_"+bd+".bc"
+	fnameh="big_"+bd+".h"
+
+	os.system(copytext+" big.c "+fnamec)
+	os.system(copytext+" big.h "+fnameh)
+
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"XXX",bd)
+	os.system("emcc -O2 "+fnamec+" -o "+fnamebc)
+
+	fnamec="fp_"+tf+".c"
+	fnamebc="fp_"+tf+".bc"
+	fnameh="fp_"+tf+".h"
+
+	os.system(copytext+" fp.c "+fnamec)
+	os.system(copytext+" fp.h "+fnameh)
+
+	replace(fnamec,"YYY",tf)
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"YYY",tf)
+	replace(fnameh,"XXX",bd)
+	os.system("emcc -O2 "+fnamec+" -o "+fnamebc)
+
+	os.system("emcc -O2 rom_field_"+tf+".c -o rom_field_"+tf+".bc");
+
+	fnamec="ecp_"+tc+".c"
+	fnamebc="ecp_"+tc+".bc"
+	fnameh="ecp_"+tc+".h"
+
+	os.system(copytext+" ecp.c "+fnamec)
+	os.system(copytext+" ecp.h "+fnameh)
+
+	replace(fnamec,"ZZZ",tc)
+	replace(fnamec,"YYY",tf)
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"ZZZ",tc)
+	replace(fnameh,"YYY",tf)
+	replace(fnameh,"XXX",bd)
+	os.system("emcc -O2 "+fnamec+" -o "+fnamebc)
+
+	fnamec="ecdh_"+tc+".c"
+	fnamebc="ecdh_"+tc+".bc"
+	fnameh="ecdh_"+tc+".h"
+
+	os.system(copytext+" ecdh.c "+fnamec)
+	os.system(copytext+" ecdh.h "+fnameh)
+
+	replace(fnamec,"ZZZ",tc)
+	replace(fnamec,"YYY",tf)
+	replace(fnamec,"XXX",bd)
+	replace(fnameh,"ZZZ",tc)
+	replace(fnameh,"YYY",tf)
+	replace(fnameh,"XXX",bd)
+	os.system("emcc -O2 "+fnamec+" -o "+fnamebc)
+
+	os.system("emcc -O2 rom_curve_"+tc+".c -o rom_curve_"+tc+".bc");
+
+	if pf != "NOT" :
+		fnamec="fp2_"+tf+".c"
+		fnamebc="fp2_"+tf+".bc"
+		fnameh="fp2_"+tf+".h"
+
+		os.system(copytext+" fp2.c "+fnamec)
+		os.system(copytext+" fp2.h "+fnameh)
+		replace(fnamec,"YYY",tf)
+		replace(fnamec,"XXX",bd)
+		replace(fnameh,"YYY",tf)
+		replace(fnameh,"XXX",bd)
+		os.system("emcc -O2 "+fnamec+" -o "+fnamebc)
+
+		fnamec="fp4_"+tf+".c"
+		fnamebc="fp4_"+tf+".bc"
+		fnameh="fp4_"+tf+".h"
+
+		os.system(copytext+" fp4.c "+fnamec)
+		os.system(copytext+" fp4.h "+fnameh)
+		replace(fnamec,"YYY",tf)
+		replace(fnamec,"XXX",bd)
+		replace(fnamec,"ZZZ",tc)
+		replace(fnameh,"YYY",tf)
+		replace(fnameh,"XXX",bd)
+		replace(fnameh,"ZZZ",tc)
+		os.system("emcc -O2 "+fnamec+" -o "+fnamebc)
+
+
+		if cs == "128" :
+			fnamec="fp12_"+tf+".c"
+			fnamebc="fp12_"+tf+".bc"
+			fnameh="fp12_"+tf+".h"
+
+			os.system(copytext+" fp12.c "+fnamec)
+			os.system(copytext+" fp12.h "+fnameh)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("emcc -O2 "+fnamec+" -o "+fnamebc)
+
+			fnamec="ecp2_"+tc+".c"
+			fnamebc="ecp2_"+tc+".bc"
+			fnameh="ecp2_"+tc+".h"
+
+			os.system(copytext+" ecp2.c "+fnamec)
+			os.system(copytext+" ecp2.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("emcc -O2 "+fnamec+" -o "+fnamebc)
+
+			fnamec="pair_"+tc+".c"
+			fnamebc="pair_"+tc+".bc"
+			fnameh="pair_"+tc+".h"
+
+			os.system(copytext+" pair.c "+fnamec)
+			os.system(copytext+" pair.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("emcc -O2 "+fnamec+" -o "+fnamebc)
+
+			fnamec="mpin_"+tc+".c"
+			fnamebc="mpin_"+tc+".bc"
+			fnameh="mpin_"+tc+".h"
+
+			os.system(copytext+" mpin.c "+fnamec)
+			os.system(copytext+" mpin.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("emcc -O2 "+fnamec+" -o "+fnamebc)
+
+		if cs == "192" :
+			fnamec="fp8_"+tf+".c"
+			fnamebc="fp8_"+tf+".bc"
+			fnameh="fp8_"+tf+".h"
+
+			os.system(copytext+" fp8.c "+fnamec)
+			os.system(copytext+" fp8.h "+fnameh)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			os.system("emcc -O2 "+fnamec+" -o "+fnamebc)
+
+
+			fnamec="fp24_"+tf+".c"
+			fnamebc="fp24_"+tf+".bc"
+			fnameh="fp24_"+tf+".h"
+
+			os.system(copytext+" fp24.c "+fnamec)
+			os.system(copytext+" fp24.h "+fnameh)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("emcc -O2 "+fnamec+" -o "+fnamebc)
+
+			fnamec="ecp4_"+tc+".c"
+			fnamebc="ecp4_"+tc+".bc"
+			fnameh="ecp4_"+tc+".h"
+
+			os.system(copytext+" ecp4.c "+fnamec)
+			os.system(copytext+" ecp4.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("emcc -O2 "+fnamec+" -o "+fnamebc)
+
+			fnamec="pair192_"+tc+".c"
+			fnamebc="pair192_"+tc+".bc"
+			fnameh="pair192_"+tc+".h"
+
+			os.system(copytext+" pair192.c "+fnamec)
+			os.system(copytext+" pair192.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("emcc -O2 "+fnamec+" -o "+fnamebc)
+
+			fnamec="mpin192_"+tc+".c"
+			fnamebc="mpin192_"+tc+".bc"
+			fnameh="mpin192_"+tc+".h"
+
+			os.system(copytext+" mpin192.c "+fnamec)
+			os.system(copytext+" mpin192.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("emcc -O2 "+fnamec+" -o "+fnamebc)		
+
+		if cs == "256" :
+
+			fnamec="fp8_"+tf+".c"
+			fnamebc="fp8_"+tf+".bc"
+			fnameh="fp8_"+tf+".h"
+
+			os.system(copytext+" fp8.c "+fnamec)
+			os.system(copytext+" fp8.h "+fnameh)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			os.system("emcc -O2 "+fnamec+" -o "+fnamebc)
+
+
+			fnamec="ecp8_"+tc+".c"
+			fnamebc="ecp8_"+tc+".bc"
+			fnameh="ecp8_"+tc+".h"
+
+			os.system(copytext+" ecp8.c "+fnamec)
+			os.system(copytext+" ecp8.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("emcc -O2 "+fnamec+" -o "+fnamebc)
+
+
+			fnamec="fp16_"+tf+".c"
+			fnamebc="fp16_"+tf+".bc"
+			fnameh="fp16_"+tf+".h"
+
+			os.system(copytext+" fp16.c "+fnamec)
+			os.system(copytext+" fp16.h "+fnameh)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			os.system("emcc -O2 "+fnamec+" -o "+fnamebc)
+
+
+			fnamec="fp48_"+tf+".c"
+			fnamebc="fp48_"+tf+".bc"
+			fnameh="fp48_"+tf+".h"
+
+			os.system(copytext+" fp48.c "+fnamec)
+			os.system(copytext+" fp48.h "+fnameh)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("emcc -O2 "+fnamec+" -o "+fnamebc)
+
+
+			fnamec="pair256_"+tc+".c"
+			fnamebc="pair256_"+tc+".bc"
+			fnameh="pair256_"+tc+".h"
+
+			os.system(copytext+" pair256.c "+fnamec)
+			os.system(copytext+" pair256.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("emcc -O2 "+fnamec+" -o "+fnamebc)
+
+			fnamec="mpin256_"+tc+".c"
+			fnamebc="mpin256_"+tc+".bc"
+			fnameh="mpin256_"+tc+".h"
+
+			os.system(copytext+" mpin256.c "+fnamec)
+			os.system(copytext+" mpin256.h "+fnameh)
+			replace(fnamec,"ZZZ",tc)
+			replace(fnamec,"YYY",tf)
+			replace(fnamec,"XXX",bd)
+			replace(fnameh,"ZZZ",tc)
+			replace(fnameh,"YYY",tf)
+			replace(fnameh,"XXX",bd)
+			os.system("emcc -O2 "+fnamec+" -o "+fnamebc)				
+
+replace("arch.h","@WL@","32")
+print("Elliptic Curves")
+print("1. ED25519")
+print("2. C25519")
+print("3. NIST256")
+print("4. BRAINPOOL")
+print("5. ANSSI")
+print("6. HIFIVE")
+print("7. GOLDILOCKS")
+print("8. NIST384")
+print("9. C41417")
+print("10. NIST521\n")
+print("11. NUMS256W")
+print("12. NUMS256E")
+print("13. NUMS384W")
+print("14. NUMS384E")
+print("15. NUMS512W")
+print("16. NUMS512E")
+print("17. SECP256K1\n")
+
+print("Pairing-Friendly Elliptic Curves")
+print("18. BN254")
+print("19. BN254CX")
+print("20. BLS383")
+print("21. BLS381")
+print("22. FP256BN")
+print("23. FP512BN")
+print("24. BLS461\n")
+print("25. BLS24")
+print("26. BLS48\n")
+
+print("RSA")
+print("27. RSA2048")
+print("28. RSA3072")
+print("29. RSA4096")
+
+selection=[]
+ptr=0
+max=30
+
+curve_selected=False
+pfcurve_selected=False
+rsa_selected=False
+
+while ptr<max:
+	x=int(input("Choose a Scheme to support - 0 to finish: "))
+	if x == 0:
+		break
+#	print("Choice= ",x)
+	already=False
+	for i in range(0,ptr):
+		if x==selection[i]:
+			already=True
+			break
+	if already:
+		continue
+	
+	selection.append(x)
+	ptr=ptr+1
+
+# curveset(big,field,curve,big_length_bytes,bits_in_base,modulus_bits,modulus_mod_8,modulus_type,curve_type,pairing_friendly,sextic twist,sign of x,curve security)
+# for each curve give names for big, field and curve. In many cases the latter two will be the same. 
+# Typically "big" is the size in bits, always a multiple of 8, "field" describes the modulus, and "curve" is the common name for the elliptic curve   
+# big_length_bytes is "big" divided by 8
+# Next give the number base used for 32 bit architectures, as n where the base is 2^n (note that these must be fixed for the same "big" name, if is ever re-used for another curve)
+# modulus_bits is the bit length of the modulus, typically the same or slightly smaller than "big"
+# modulus_mod_8 is the remainder when the modulus is divided by 8
+# modulus_type is NOT_SPECIAL, or PSEUDO_MERSENNE, or MONTGOMERY_Friendly, or GENERALISED_MERSENNE (supported for GOLDILOCKS only)
+# curve_type is WEIERSTRASS, EDWARDS or MONTGOMERY
+# pairing_friendly is BN, BLS or NOT (if not pairing friendly)
+# if pairing friendly. M or D type twist, and sign of the family parameter x
+# curve security is AES equiavlent, rounded up.
+
+	if x==1:
+		curveset("256","25519","ED25519","32","29","255","5","PSEUDO_MERSENNE","EDWARDS","NOT","","","128")
+		curve_selected=True
+	if x==2:
+		curveset("256","25519","C25519","32","29","255","5","PSEUDO_MERSENNE","MONTGOMERY","NOT","","","128")
+		curve_selected=True
+	if x==3:
+		curveset("256","NIST256","NIST256","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","128")
+		curve_selected=True
+	if x==4:
+		curveset("256","BRAINPOOL","BRAINPOOL","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","128")
+		curve_selected=True
+	if x==5:
+		curveset("256","ANSSI","ANSSI","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","128")
+		curve_selected=True
+
+	if x==6:
+		curveset("336","HIFIVE","HIFIVE","42","29","336","5","PSEUDO_MERSENNE","EDWARDS","NOT","","","192")
+		curve_selected=True
+	if x==7:
+		curveset("448","GOLDILOCKS","GOLDILOCKS","56","29","448","7","GENERALISED_MERSENNE","EDWARDS","NOT","","","256")
+		curve_selected=True
+	if x==8:
+		curveset("384","NIST384","NIST384","48","29","384","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","192")
+		curve_selected=True
+	if x==9:
+		curveset("416","C41417","C41417","52","29","414","7","PSEUDO_MERSENNE","EDWARDS","NOT","","","256")
+		curve_selected=True
+	if x==10:
+		curveset("528","NIST521","NIST521","66","28","521","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","256")
+		curve_selected=True
+
+	if x==11:
+		curveset("256","256PMW","NUMS256W","32","28","256","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","128")
+		curve_selected=True
+	if x==12:
+		curveset("256","256PME","NUMS256E","32","29","256","3","PSEUDO_MERSENNE","EDWARDS","NOT","","","128")
+		curve_selected=True
+	if x==13:
+		curveset("384","384PM","NUMS384W","48","29","284","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","192")
+		curve_selected=True
+	if x==14:
+		curveset("384","384PM","NUMS384E","48","29","384","3","PSEUDO_MERSENNE","EDWARDS","NOT","","","192")
+		curve_selected=True
+	if x==15:
+		curveset("512","512PM","NUMS512W","64","29","512","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","256")
+		curve_selected=True
+	if x==16:
+		curveset("512","512PM","NUMS512E","64","29","512","7","PSEUDO_MERSENNE","EDWARDS","NOT","","","256")
+		curve_selected=True
+
+	if x==17:
+		curveset("256","SECP256K1","SECP256K1","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","128")
+		curve_selected=True
+
+
+	if x==18:
+		curveset("256","BN254","BN254","32","28","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+	if x==19:
+		curveset("256","BN254CX","BN254CX","32","28","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+	if x==20:
+		curveset("384","BLS383","BLS383","48","29","383","3","NOT_SPECIAL","WEIERSTRASS","BLS","D_TYPE","POSITIVEX","128")
+		pfcurve_selected=True
+
+	if x==21:
+		curveset("384","BLS381","BLS381","48","29","381","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+
+	if x==22:
+		curveset("256","FP256BN","FP256BN","32","28","256","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+	if x==23:
+		curveset("512","FP512BN","FP512BN","64","29","512","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","POSITIVEX","128")
+		pfcurve_selected=True
+# https://eprint.iacr.org/2017/334.pdf
+	if x==24:
+		curveset("464","BLS461","BLS461","58","28","461","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128")
+		pfcurve_selected=True
+
+	if x==25:
+		curveset("480","BLS24","BLS24","60","29","479","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","192")
+		pfcurve_selected=True
+
+
+	if x==26:
+		curveset("560","BLS48","BLS48","70","29","556","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","256")
+		pfcurve_selected=True
+
+
+# rsaset(big,ring,big_length_bytes,bits_in_base,multiplier)
+# for each choice give distinct names for "big" and "ring".
+# Typically "big" is the length in bits of the underlying big number type
+# "ring" is the RSA modulus size = "big" times 2^m
+# big_length_bytes is "big" divided by 8
+# Next give the number base used for 32 bit architecture, as n where the base is 2^n
+# multiplier is 2^m (see above)
+
+# There are choices here, different ways of getting the same result, but some faster than others
+	if x==27:
+		#256 is slower but may allow reuse of 256-bit BIGs used for elliptic curve
+		#512 is faster.. but best is 1024
+		rsaset("1024","2048","128","28","2")
+		#rsaset("512","2048","64","29","4")
+		#rsaset("256","2048","32","29","8")
+		rsa_selected=True
+	if x==28:
+		rsaset("384","3072","48","28","8")
+		rsa_selected=True
+	if x==29:
+		#rsaset("256","4096","32","29","16")
+		rsaset("512","4096","64","29","8")
+		rsa_selected=True
+
+
+os.system(deltext+" big.*")
+os.system(deltext+" fp.*")
+os.system(deltext+" ecp.*")
+os.system(deltext+" ecdh.*")
+os.system(deltext+" ff.*")
+os.system(deltext+" rsa.*")
+os.system(deltext+" config_big.h")
+os.system(deltext+" config_field.h")
+os.system(deltext+" config_curve.h")
+os.system(deltext+" config_ff.h")
+os.system(deltext+" fp2.*")
+os.system(deltext+" fp4.*")
+os.system(deltext+" fp8.*")
+os.system(deltext+" fp16.*")
+
+
+os.system(deltext+" fp12.*")
+os.system(deltext+" fp24.*")
+os.system(deltext+" fp48.*")
+
+os.system(deltext+" ecp2.*")
+os.system(deltext+" ecp4.*")
+os.system(deltext+" ecp8.*")
+
+os.system(deltext+" pair.*")
+os.system(deltext+" mpin.*")
+
+os.system(deltext+" pair192.*")
+os.system(deltext+" mpin192.*")
+
+os.system(deltext+" pair256.*")
+os.system(deltext+" mpin256.*")
+
+# create library
+os.system("emcc -O2  randapi.c -o randapi.bc")
+if curve_selected :
+	os.system("emcc -O2  ecdh_support.c -o ecdh_support.bc")
+if rsa_selected :
+	os.system("emcc -O2  rsa_support.c -o rsa_support.bc")
+if pfcurve_selected :
+	os.system("emcc -O2  pbc_support.c -o pbc_support.bc")
+
+os.system("emcc -O2 hash.c -o hash.bc")
+os.system("emcc -O2 rand.c -o rand.bc")
+os.system("emcc -O2 oct.c -o oct.bc")
+os.system("emcc -O2 aes.c -o aes.bc")
+os.system("emcc -O2 gcm.c -o gcm.bc")
+os.system("emcc -O2 newhope.c -o newhope.bc")
+
+if sys.platform.startswith("win") :
+	os.system("for %i in (*.bc) do @echo %~nxi >> f.list")
+	os.system("emar rc amcl.a @f.list")
+	os.system(deltext+" f.list")
+
+else :
+	os.system("emar rc amcl.a *.bc")
+	
+os.system(deltext+" *.bc")
+
+#print("Your section was ");	
+#for i in range(0,ptr):
+#	print (selection[i])
+
diff --git a/version3/wasm/readme.txt b/version3/wasm/readme.txt
new file mode 100644
index 0000000..f7682e5
--- /dev/null
+++ b/version3/wasm/readme.txt
@@ -0,0 +1,72 @@
+
+AMCL in Webassembly 
+
+See https://webassembly.org/getting-started/developers-guide/
+
+
+The AMCL library already has a Javascript version, but can also run up 
+to 10 times faster in a browser that supports Webassembly. And thats
+most of the popular browsers in use today.*
+
+The C, C++ or Rust version of the AMCL library can be compiled to a 
+bitcode that runs directly in the browser, by-passing Javascript 
+entirely. Which is good for our type of application, as the way
+in which Javascript handles integer arithmetic is very slow.
+
+To install the Emscripten C/C++ compiler follow the instructions
+above. Then copy the AMCL C code into a new directory, along with
+the config.py file from this directory. In the new directory execute
+
+python3 config.py
+
+Then select options 1, 3, 7, 18, 20, 25, 26 and 27, which are fixed for 
+the example programs.
+
+Build the test programs with
+
+emcc -O2 benchtest_all.c amcl.a -s WASM=1 -o benchtest_all.html
+
+and
+
+emcc -O2 testall.c amcl.a -s WASM=1 -o testall.html
+
+Then run a local HTML server (as described in the link above) and load the 
+HTML file.
+
+Wait for the benchtest_all program to complete (which will take a while).
+
+*Firefox, Safari, Edge, Chrome
+
+
+-------------------------------
+
+Webassembly can also be generated from the Rust code. First the Rust compiler 
+must be updated to target wasm, by
+
+rustup target add wasm32-unknown-emscripten
+
+The Emscripten toolchain is also required, as above
+
+Edit the Rust file config32.py, where it generates "cargo rustc" instruction 
+(around line 372), and include the flag --target wasm32-unknown-emscripten
+
+Build the Rust library as described in the Rust readme.txt file by executing
+
+python3 config32.py
+
+Copy the AMCL library to the current directory
+
+cp amcl/target/wasm32-unknown-emscripten/release/libamcl.rlib .
+
+Finally build one of the test programs by, for example
+
+rustc --target wasm32-unknown-emscripten BenchtestALL.rs --extern amcl=libamcl.rlib -o BenchtestALL.html
+
+Note that this will create a HTML file, which can be loaded into a browser as 
+described above.
+
+Right now (6/2018) this doesn't work with the 64-bit build, I suspect because 
+Webassembly is not happy with 128-bit integers. But in time it might (and 
+would then be even faster).
+
+
diff --git a/windows.md b/windows.md
deleted file mode 100644
index fe5e089..0000000
--- a/windows.md
+++ /dev/null
@@ -1,70 +0,0 @@
-<h2>Software dependencies</h2>
-
-<p>Minimalist GNU for Windows <a href="http://www.mingw.org/">MinGW</a> provides the 
-tool set used to build the library and should be installed. When the MinGW installer
-starts select the mingw32-base and mingw32-gcc-g++ components. From the menu select
-"Installation" -> "Apply Changes", then click "Apply". Finally add C:\MinGW\bin
-to the PATH variable.</p>
-
-<p>CMake is required to build the library and can be downloaded from www.cmake.org</p>
-
-<p>The C Foreign Function Interface for Python <a href="https://cffi.readthedocs.org/en/latest/">CFFI</a> module
-is also required, if you wish to use the Python module.</p>
-
-<ul type="disc">
-  <li>pip install cffi</li>
-</ul>
-
-In order to build the documentation <a href="http://www.stack.nl/~dimitri/doxygen/">doxygen</a> is required.
-
-<h2>Build Instructions</h2>
-
-<p>Start a command prompt as an administrator</p>
-
-<p>The default build is for 32 bit machines</p>
-
-<ol type="disc">
-  <li>mkdir Release</li>
-  <li>cd Release</li>
-  <li>cmake -G "MinGW Makefiles" ..</li>
-  <li>mingw32-make</li>
-  <li>mingw32-make test</li>
-  <li>mingw32-make doc</li>
-  <li>mingw32-make install</li>
-</ol>
-
-<p>
-
-Post install append the PATH system variable to point to the install ./lib.
-
-My Computer -> Properties -> Advanced > Environment Variables
-
-</p>
-
-
-<p>The build can be configured using by setting flags on the command line i.e.</p>
-
-<ol type="disc">
-  <li>cmake -G "MinGW Makefiles" -DWORD_LENGTH=64 ..</li>
-</ol>
-
-<h2>Uninstall software</h2>
-
-<ul type="disc">
-  <li>mingw32-make uninstall</li>
-</ul>
-
-<h2>Building an installer</h2>
-
-<p>After having built the libraries you can build a Windows installer using this command</p>
-
-<ul type="disc">
-  <li>sudo mingw32-make package</li>
-</ul>
-
-<p>In order for this to work <a href="http://nsis.sourceforge.net/Download">NSSI</a> has
-to have been installed</p>
-
-
-
-